From 512d659d67ab5f8d6ff533e37239f00871a55991 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 12 Dec 2023 16:20:06 +0100 Subject: [PATCH 001/303] Bump version to v13.3.0.1 --- CHANGELOG.md | 22 ++++++++--- FIRMWARE.md | 2 +- README.md | 2 +- RELEASENOTES.md | 66 ++----------------------------- tasmota/include/tasmota_version.h | 2 +- 5 files changed, 24 insertions(+), 70 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c80594ac9..640f721a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,23 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - Development -## [13.2.0.3] +## [13.3.0.1] +### Added + +### Breaking Changed + +### Changed + +### Fixed + +### Removed + +## [Released] + +## [13.3.0] 20231213 +- Release Quinlan + +## [13.2.0.3] 20231213 ### Added - DeepSleep support through TIMERS (#20117) - Command ``WebCanvas linear-gradient(#F02 7%,#F93,#FF4,#082,#00F,#708 93%)`` to set GUI canvas @@ -21,8 +37,6 @@ All notable changes to this project will be documented in this file. - ESP32 Neopixel flicker for Core3/IDF5 (#20196) - HASPmota `bar` fixed `val` attribute (#20208) -### Removed - ## [13.2.0.2] 20231130 ### Added - Scripter TCP client (#19914) @@ -88,8 +102,6 @@ All notable changes to this project will be documented in this file. - ESP32 I2C allow bus2 support when bus1 is not enabled - ESP32 IR receive with Arduino Core 3 (#19904) -## [Released] - ## [13.2.0] 20231019 - Release Quincy diff --git a/FIRMWARE.md b/FIRMWARE.md index 43f76f8d2..816882c26 100644 --- a/FIRMWARE.md +++ b/FIRMWARE.md @@ -18,7 +18,7 @@ See [CHANGELOG.md](https://github.com/arendst/Tasmota/blob/development/tasmota/C ## Development -[![Dev Version](https://img.shields.io/badge/development%20version-v13.2.x.x-blue.svg)](https://github.com/arendst/Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-v13.3.x.x-blue.svg)](https://github.com/arendst/Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://ota.tasmota.com/tasmota/) [![Tasmota CI](https://github.com/arendst/Tasmota/workflows/Tasmota%20CI/badge.svg)](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+CI%22) [![Tasmota ESP32 CI](https://github.com/arendst/Tasmota/workflows/Tasmota%20ESP32%20CI/badge.svg)](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+ESP32+CI%22) diff --git a/README.md b/README.md index 1ca83d791..7d7c15901 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Firmware binaries can be downloaded from http://ota.tasmota.com/tasmota/release/ ## Development -[![Dev Version](https://img.shields.io/badge/development%20version-v13.2.x.x-blue.svg)](https://github.com/arendst/Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-v13.3.x.x-blue.svg)](https://github.com/arendst/Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://ota.tasmota.com/tasmota/) [![Tasmota CI](https://github.com/arendst/Tasmota/actions/workflows/build_all_the_things.yml/badge.svg)](https://github.com/arendst/Tasmota/actions/workflows/build_all_the_things.yml) [![Build_development](https://github.com/arendst/Tasmota/actions/workflows/Tasmota_build_devel.yml/badge.svg)](https://github.com/arendst/Tasmota/actions/workflows/Tasmota_build_devel.yml) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 4d337ae3d..0c736dace 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -75,7 +75,7 @@ Latest released binaries can be downloaded from - http://ota.tasmota.com/tasmota/release Historical binaries can be downloaded from -- http://ota.tasmota.com/tasmota/release-13.2.0 +- http://ota.tasmota.com/tasmota/release-13.3.0 The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmota.com/tasmota/release/tasmota.bin.gz`` @@ -106,7 +106,7 @@ Latest released binaries can be downloaded from - https://ota.tasmota.com/tasmota32/release Historical binaries can be downloaded from -- https://ota.tasmota.com/tasmota32/release-13.2.0 +- https://ota.tasmota.com/tasmota32/release-13.3.0 The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasmota.com/tasmota32/release/tasmota32.bin`` @@ -116,71 +116,13 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm [Complete list](BUILDS.md) of available feature and sensors. -## Changelog v13.2.0.3 +## Changelog v13.3.0.1 ### Added -- Support for ESP32-C2 and ESP32-C6 using Arduino Core3 -- Command ``GpioRead`` to show input state [#19810](https://github.com/arendst/Tasmota/issues/19810) -- Command ``WebCanvas linear-gradient(#F02 7%,#F93,#FF4,#082,#00F,#708 93%)`` to set GUI canvas -- I2C bus2 support to iAQ core sensor [#19799](https://github.com/arendst/Tasmota/issues/19799) -- I2C bus2 support to HTU temperature and humidity sensor -- I2C bus2 support to BH1750 ambient light sensor -- I2C bus2 support to ADS1115 A/D Converter -- I2C bus2 support to SHTxX temperature and humidity sensor -- I2C bus2 support to HYTxxx temperature and humidity sensor -- I2C bus2 support to SI1145/6/7 Ultra violet index and light sensor -- I2C bus2 support to LM75AD temperature sensor -- Support for Winsen XH03x dust particle sensors using USE_PMS5003 and PMS_MODEL_ZH03X [#19850](https://github.com/arendst/Tasmota/issues/19850) -- ST7735S display.ini for 1.44 inch 128x128 red SPI display [#19862](https://github.com/arendst/Tasmota/issues/19862) -- Scripter TCP client [#19914](https://github.com/arendst/Tasmota/issues/19914) -- NeoPool hydrolysis setpoint and max -- NeoPool command ``NPFiltrationSpeed`` to set non-standard filtration type speed [#19857](https://github.com/arendst/Tasmota/issues/19857) -- NeoPool command ``SetOption157`` to enable output of sensitive data [#19857](https://github.com/arendst/Tasmota/issues/19857) -- NeoPool command ``NPBoost`` [#19973](https://github.com/arendst/Tasmota/issues/19973) -- NeoPool sensor delta trigger (command ``NPTelePeriod``) [#19973](https://github.com/arendst/Tasmota/issues/19973) -- NeoPool enhancements for HomeAssistant [#19857](https://github.com/arendst/Tasmota/issues/19857) -- NeoPool store settings on unified file system [#19973](https://github.com/arendst/Tasmota/issues/19973) -- DeepSleep support through TIMERS [#20117](https://github.com/arendst/Tasmota/issues/20117) -- ESP32 auto TasConsole USB or Serial connection for Core3 by @staars -- ESP32 Partition Wizard can be loaded dynamically [#19980](https://github.com/arendst/Tasmota/issues/19980) -- ESP32 support for Avago Tech Bluetooth Buttons [#20088](https://github.com/arendst/Tasmota/issues/20088) -- Berry ``debug.gcdebug()`` to enable GC debugging [#19936](https://github.com/arendst/Tasmota/issues/19936) -- Berry AES_CBC to crypto module [#19964](https://github.com/arendst/Tasmota/issues/19964) -- Berry `scale_int`, equivalent of `scale_uint` for signed integers [#20090](https://github.com/arendst/Tasmota/issues/20090) -- HASPmota add styling properties [#19912](https://github.com/arendst/Tasmota/issues/19912) -- Matter flow sensor support [#19852](https://github.com/arendst/Tasmota/issues/19852) ### Breaking Changed -- NeoPool SENSOR topic ``Power`` renamed to ``Powerunit`` [#19857](https://github.com/arendst/Tasmota/issues/19857) -- Remove Berry `every_200ms` event which didn't work anyways [#20205](https://github.com/arendst/Tasmota/issues/20205) ### Changed -- ESP32 Framework (Arduino Core3) from v3.0.0-alpha1 to v3.0.0-alpha3 -- ESP32 LVGL library from v8.3.10 to v8.3.11 (no functional change) -- Increase MAX_HUE_DEVICES to 32 [#19820](https://github.com/arendst/Tasmota/issues/19820) -- NeoPool ``NPHydrolysis`` percent and unit [#19924](https://github.com/arendst/Tasmota/issues/19924) -- Thermostat JSON index from 0 to 1 [#20011](https://github.com/arendst/Tasmota/issues/20011) -- MI32 updates [#19893](https://github.com/arendst/Tasmota/issues/19893) -- ESP32 keep FileSystem intact when over flashing with VSC [#19816](https://github.com/arendst/Tasmota/issues/19816) -- Berry leds animation refactoring stage 1 [#20197](https://github.com/arendst/Tasmota/issues/20197) -- Berry ULP API changes for Core3/IDF5 [#20198](https://github.com/arendst/Tasmota/issues/20198) -- Matter Light0 now accept a Relay number [#19809](https://github.com/arendst/Tasmota/issues/19809) -- Matter update hierarchy of plugins [#19915](https://github.com/arendst/Tasmota/issues/19915) ### Fixed -- Compile USE_PID [#19890](https://github.com/arendst/Tasmota/issues/19890) -- Scripter timer issue [#19914](https://github.com/arendst/Tasmota/issues/19914) -- NeoPool filtration mode display [#19801](https://github.com/arendst/Tasmota/issues/19801) -- ``changeUIntScale`` for linearity when expanding range [#20089](https://github.com/arendst/Tasmota/issues/20089) -- TUYA state machine (in TUYA v1) [#20110](https://github.com/arendst/Tasmota/issues/20110) -- ``WebQuery`` response buffer corruption and format character ``%`` [#20111](https://github.com/arendst/Tasmota/issues/20111) -- ESP32 I2C allow bus2 support when bus1 is not enabled -- ESP32 remove restart energy logging if no energy monitoring is selected -- ESP32 IR receive with Arduino Core3 [#19904](https://github.com/arendst/Tasmota/issues/19904) -- ESP32 Zero-Cross Dimmer for Core3 [#19929](https://github.com/arendst/Tasmota/issues/19929) -- ESP32-C3 ledlink functionality regression from v13.1.0.2 -- ESP32 Neopixel flicker for Core3/IDF5 [#20196](https://github.com/arendst/Tasmota/issues/20196) -- Berry parser error in specific cases [#20059](https://github.com/arendst/Tasmota/issues/20059) -- Berry ``gpio.dac_voltage()`` regression from v13.1.0.1 [#19997](https://github.com/arendst/Tasmota/issues/19997) -- HASPmota `bar` fixed `val` attribute [#20208](https://github.com/arendst/Tasmota/issues/20208) -### Removed +### Removed \ No newline at end of file diff --git a/tasmota/include/tasmota_version.h b/tasmota/include/tasmota_version.h index b302c0370..94bd18c62 100644 --- a/tasmota/include/tasmota_version.h +++ b/tasmota/include/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t TASMOTA_VERSION = 0x0D020003; // 13.2.0.3 +const uint32_t TASMOTA_VERSION = 0x0D030001; // 13.3.0.1 #endif // _TASMOTA_VERSION_H_ From 5102dbf1d2168eee61b4a176b8b1d87359718455 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Wed, 13 Dec 2023 20:07:12 +0100 Subject: [PATCH 002/303] Matter Contact sensor was not triggering any update (#20232) --- CHANGELOG.md | 1 + .../Matter_Plugin_2_Sensor_Contact.be | 20 ++--- ...olidified_Matter_Plugin_2_Sensor_Contact.h | 89 ++++++++++--------- 3 files changed, 56 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 640f721a0..13aa4bcfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ All notable changes to this project will be documented in this file. - TUYA state machine (in TUYA v1) (#20110) - ESP32 Neopixel flicker for Core3/IDF5 (#20196) - HASPmota `bar` fixed `val` attribute (#20208) +- Matter Contact sensor was not triggering any update ## [13.2.0.2] 20231130 ### Added diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Contact.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Contact.be index 5932b0060..f560d9540 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Contact.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Contact.be @@ -61,19 +61,17 @@ class Matter_Plugin_Sensor_Contact : Matter_Plugin_Device def update_shadow() super(self).update_shadow() if !self.VIRTUAL - import json - var ret = tasmota.cmd("Status 8", true) - if ret != nil - var j = json.load(ret) - if j != nil - var state = false - state = (j.find("Switch" + str(self.tasmota_switch_index)) == "ON") + var switch_str = "Switch" + str(self.tasmota_switch_index) - if self.shadow_contact != state - self.attribute_updated(0x0045, 0x0000) - self.shadow_contact = state - end + var j = tasmota.cmd("Status 8", true) + if j != nil j = j.find("StatusSNS") end + if j != nil && j.contains(switch_str) + var state = (j.find(switch_str) == "ON") + + if (self.shadow_contact != state) + self.attribute_updated(0x0045, 0x0000) end + self.shadow_contact = state end end end diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h index d097a5ba3..4d5b133d2 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h @@ -85,7 +85,7 @@ be_local_closure(Matter_Plugin_Sensor_Contact_parse_configuration, /* name */ ********************************************************************/ be_local_closure(Matter_Plugin_Sensor_Contact_update_shadow, /* name */ be_nested_proto( - 9, /* nstack */ + 8, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -96,14 +96,14 @@ be_local_closure(Matter_Plugin_Sensor_Contact_update_shadow, /* name */ ( &(const bvalue[14]) { /* constants */ /* K0 */ be_nested_str_weak(update_shadow), /* K1 */ be_nested_str_weak(VIRTUAL), - /* K2 */ be_nested_str_weak(json), - /* K3 */ be_nested_str_weak(tasmota), - /* K4 */ be_nested_str_weak(cmd), - /* K5 */ be_nested_str_weak(Status_X208), - /* K6 */ be_nested_str_weak(load), + /* K2 */ be_nested_str_weak(Switch), + /* K3 */ be_nested_str_weak(tasmota_switch_index), + /* K4 */ be_nested_str_weak(tasmota), + /* K5 */ be_nested_str_weak(cmd), + /* K6 */ be_nested_str_weak(Status_X208), /* K7 */ be_nested_str_weak(find), - /* K8 */ be_nested_str_weak(Switch), - /* K9 */ be_nested_str_weak(tasmota_switch_index), + /* K8 */ be_nested_str_weak(StatusSNS), + /* K9 */ be_nested_str_weak(contains), /* K10 */ be_nested_str_weak(ON), /* K11 */ be_nested_str_weak(shadow_contact), /* K12 */ be_nested_str_weak(attribute_updated), @@ -111,47 +111,50 @@ be_local_closure(Matter_Plugin_Sensor_Contact_update_shadow, /* name */ }), be_str_weak(update_shadow), &be_const_str_solidified, - ( &(const binstruction[40]) { /* code */ + ( &(const binstruction[43]) { /* code */ 0x60040003, // 0000 GETGBL R1 G3 0x5C080000, // 0001 MOVE R2 R0 0x7C040200, // 0002 CALL R1 1 0x8C040300, // 0003 GETMET R1 R1 K0 0x7C040200, // 0004 CALL R1 1 0x88040101, // 0005 GETMBR R1 R0 K1 - 0x7406001F, // 0006 JMPT R1 #0027 - 0xA4060400, // 0007 IMPORT R1 K2 - 0xB80A0600, // 0008 GETNGBL R2 K3 - 0x8C080504, // 0009 GETMET R2 R2 K4 - 0x58100005, // 000A LDCONST R4 K5 - 0x50140200, // 000B LDBOOL R5 1 0 - 0x7C080600, // 000C CALL R2 3 - 0x4C0C0000, // 000D LDNIL R3 - 0x200C0403, // 000E NE R3 R2 R3 - 0x780E0016, // 000F JMPF R3 #0027 - 0x8C0C0306, // 0010 GETMET R3 R1 K6 - 0x5C140400, // 0011 MOVE R5 R2 - 0x7C0C0400, // 0012 CALL R3 2 - 0x4C100000, // 0013 LDNIL R4 - 0x20100604, // 0014 NE R4 R3 R4 - 0x78120010, // 0015 JMPF R4 #0027 - 0x50100000, // 0016 LDBOOL R4 0 0 - 0x8C140707, // 0017 GETMET R5 R3 K7 - 0x601C0008, // 0018 GETGBL R7 G8 - 0x88200109, // 0019 GETMBR R8 R0 K9 - 0x7C1C0200, // 001A CALL R7 1 - 0x001E1007, // 001B ADD R7 K8 R7 - 0x7C140400, // 001C CALL R5 2 - 0x1C140B0A, // 001D EQ R5 R5 K10 - 0x5C100A00, // 001E MOVE R4 R5 - 0x8814010B, // 001F GETMBR R5 R0 K11 - 0x20140A04, // 0020 NE R5 R5 R4 - 0x78160004, // 0021 JMPF R5 #0027 - 0x8C14010C, // 0022 GETMET R5 R0 K12 - 0x541E0044, // 0023 LDINT R7 69 - 0x5820000D, // 0024 LDCONST R8 K13 - 0x7C140600, // 0025 CALL R5 3 - 0x90021604, // 0026 SETMBR R0 K11 R4 - 0x80000000, // 0027 RET 0 + 0x74060022, // 0006 JMPT R1 #002A + 0x60040008, // 0007 GETGBL R1 G8 + 0x88080103, // 0008 GETMBR R2 R0 K3 + 0x7C040200, // 0009 CALL R1 1 + 0x00060401, // 000A ADD R1 K2 R1 + 0xB80A0800, // 000B GETNGBL R2 K4 + 0x8C080505, // 000C GETMET R2 R2 K5 + 0x58100006, // 000D LDCONST R4 K6 + 0x50140200, // 000E LDBOOL R5 1 0 + 0x7C080600, // 000F CALL R2 3 + 0x4C0C0000, // 0010 LDNIL R3 + 0x200C0403, // 0011 NE R3 R2 R3 + 0x780E0003, // 0012 JMPF R3 #0017 + 0x8C0C0507, // 0013 GETMET R3 R2 K7 + 0x58140008, // 0014 LDCONST R5 K8 + 0x7C0C0400, // 0015 CALL R3 2 + 0x5C080600, // 0016 MOVE R2 R3 + 0x4C0C0000, // 0017 LDNIL R3 + 0x200C0403, // 0018 NE R3 R2 R3 + 0x780E000F, // 0019 JMPF R3 #002A + 0x8C0C0509, // 001A GETMET R3 R2 K9 + 0x5C140200, // 001B MOVE R5 R1 + 0x7C0C0400, // 001C CALL R3 2 + 0x780E000B, // 001D JMPF R3 #002A + 0x8C0C0507, // 001E GETMET R3 R2 K7 + 0x5C140200, // 001F MOVE R5 R1 + 0x7C0C0400, // 0020 CALL R3 2 + 0x1C0C070A, // 0021 EQ R3 R3 K10 + 0x8810010B, // 0022 GETMBR R4 R0 K11 + 0x20100803, // 0023 NE R4 R4 R3 + 0x78120003, // 0024 JMPF R4 #0029 + 0x8C10010C, // 0025 GETMET R4 R0 K12 + 0x541A0044, // 0026 LDINT R6 69 + 0x581C000D, // 0027 LDCONST R7 K13 + 0x7C100600, // 0028 CALL R4 3 + 0x90021603, // 0029 SETMBR R0 K11 R3 + 0x80000000, // 002A RET 0 }) ) ); From 827f614933358681f3d260e7842110e9366e0f3c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 14 Dec 2023 15:12:36 +0100 Subject: [PATCH 003/303] Update SECURITY.md --- SECURITY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SECURITY.md b/SECURITY.md index f0a8de1ed..1adcb6008 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,4 +2,4 @@ ## Reporting a Vulnerability -Please report security issues to https://sidweb.nl/cms3/en/contact +Please report security issues to https://ota.tasmota.com/tasmota/contact/contact.php From b421e2d88b7e34d1fc31c379f527e236e1cf4513 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 14 Dec 2023 15:17:44 +0100 Subject: [PATCH 004/303] Update changelogs --- CHANGELOG.md | 2 +- RELEASENOTES.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13aa4bcfc..1978a41f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. ### Changed ### Fixed +- Matter Contact sensor was not triggering any update (#20232) ### Removed @@ -36,7 +37,6 @@ All notable changes to this project will be documented in this file. - TUYA state machine (in TUYA v1) (#20110) - ESP32 Neopixel flicker for Core3/IDF5 (#20196) - HASPmota `bar` fixed `val` attribute (#20208) -- Matter Contact sensor was not triggering any update ## [13.2.0.2] 20231130 ### Added diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0c736dace..6eb72fe2e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -124,5 +124,6 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ### Changed ### Fixed +- Matter Contact sensor was not triggering any update [#20232](https://github.com/arendst/Tasmota/issues/20232) ### Removed \ No newline at end of file From 7b12450876c39722ce8dfa51d9760af491e4ef0b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 14 Dec 2023 15:29:19 +0100 Subject: [PATCH 005/303] Update SECURITY.md --- SECURITY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SECURITY.md b/SECURITY.md index 1adcb6008..ef3246b10 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,4 +2,4 @@ ## Reporting a Vulnerability -Please report security issues to https://ota.tasmota.com/tasmota/contact/contact.php +Please report security issues to [Tasmota](https://ota.tasmota.com/tasmota/contact/contact.php) From c1f8ee5dbb0371c769fced9b4f8e386b84c6521a Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 14 Dec 2023 20:13:17 +0100 Subject: [PATCH 006/303] Refactoring of Berry `animate` module for WS2812 Leds (#20236) --- CHANGELOG.md | 1 + lib/libesp32/berry/default/be_modtab.c | 9 +- .../berry_tasmota/src/be_animate_lib.c | 7 - .../berry_tasmota/src/be_animate_module.c | 197 ++ .../src/be_leds_animator_class.c | 9 - .../berry_tasmota/src/be_leds_pulse_class.c | 9 - .../berry_tasmota/src/be_tasmota_lib.c | 2 + .../{leds_0_animator.be => animate_0_core.be} | 17 +- ...ffects.be => animate_1_animate_effects.be} | 48 +- .../src/embedded/animate_9_module.be | 508 +++++ .../src/embedded/animate_module.be | 573 ------ ...animator.h => solidified_animate_0_core.h} | 159 +- ...=> solidified_animate_1_animate_effects.h} | 114 +- ...module.h => solidified_animate_9_module.h} | 1800 ++++++++--------- .../animate_demo_palette_background.be | 11 + .../berry/animate_demo/animate_demo_pulse.be | 23 + tasmota/berry/animate_demo/leds_animation.be | 173 ++ tasmota/berry/animate_demo/leds_blend_demo.be | 37 + tasmota/berry/emulator/Leds_frame.be | 42 + .../leds_animate_demo_palette_background.be | 51 - tasmota/berry/leds/rainbow.be | 185 -- .../xdrv_52_3_berry_tasmota.ino | 55 + 22 files changed, 2073 insertions(+), 1957 deletions(-) delete mode 100644 lib/libesp32/berry_tasmota/src/be_animate_lib.c create mode 100644 lib/libesp32/berry_tasmota/src/be_animate_module.c delete mode 100644 lib/libesp32/berry_tasmota/src/be_leds_animator_class.c delete mode 100644 lib/libesp32/berry_tasmota/src/be_leds_pulse_class.c rename lib/libesp32/berry_tasmota/src/embedded/{leds_0_animator.be => animate_0_core.be} (94%) rename lib/libesp32/berry_tasmota/src/embedded/{leds_1_animate_effects.be => animate_1_animate_effects.be} (82%) create mode 100644 lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be delete mode 100644 lib/libesp32/berry_tasmota/src/embedded/animate_module.be rename lib/libesp32/berry_tasmota/src/solidify/{solidified_leds_0_animator.h => solidified_animate_0_core.h} (85%) rename lib/libesp32/berry_tasmota/src/solidify/{solidified_leds_1_animate_effects.h => solidified_animate_1_animate_effects.h} (89%) rename lib/libesp32/berry_tasmota/src/solidify/{solidified_animate_module.h => solidified_animate_9_module.h} (60%) create mode 100644 tasmota/berry/animate_demo/animate_demo_palette_background.be create mode 100644 tasmota/berry/animate_demo/animate_demo_pulse.be create mode 100644 tasmota/berry/animate_demo/leds_animation.be create mode 100644 tasmota/berry/animate_demo/leds_blend_demo.be create mode 100644 tasmota/berry/emulator/Leds_frame.be delete mode 100644 tasmota/berry/leds/leds_animate_demo_palette_background.be delete mode 100644 tasmota/berry/leds/rainbow.be diff --git a/CHANGELOG.md b/CHANGELOG.md index 1978a41f4..2a77974ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added ### Breaking Changed +- Refactoring of Berry `animate` module for WS2812 Leds ### Changed diff --git a/lib/libesp32/berry/default/be_modtab.c b/lib/libesp32/berry/default/be_modtab.c index 0333db5ea..a4e7c7a33 100644 --- a/lib/libesp32/berry/default/be_modtab.c +++ b/lib/libesp32/berry/default/be_modtab.c @@ -146,7 +146,10 @@ BERRY_LOCAL const bntvmodule_t* const be_module_table[] = { #ifdef USE_UNISHOX_COMPRESSION &be_native_module(unishox), #endif // USE_UNISHOX_COMPRESSION + +#ifdef USE_WS2812 &be_native_module(animate), +#endif // USE_WS2812 #ifdef USE_LVGL &be_native_module(lv), @@ -206,10 +209,7 @@ be_extern_native_class(AXP192); be_extern_native_class(AXP202); be_extern_native_class(OneWire); be_extern_native_class(Leds_ntv); -be_extern_native_class(Leds_frame); be_extern_native_class(Leds); -be_extern_native_class(Leds_animator); -be_extern_native_class(Leds_pulse); be_extern_native_class(AudioGenerator); be_extern_native_class(AudioFileSource); be_extern_native_class(AudioOutputI2S); @@ -278,9 +278,6 @@ BERRY_LOCAL bclass_array be_class_table = { #ifdef USE_WS2812 &be_native_class(Leds_ntv), &be_native_class(Leds), - &be_native_class(Leds_frame), - &be_native_class(Leds_animator), - &be_native_class(Leds_pulse), #endif // USE_WS2812 #ifdef USE_ENERGY_SENSOR &be_native_class(energy_struct), diff --git a/lib/libesp32/berry_tasmota/src/be_animate_lib.c b/lib/libesp32/berry_tasmota/src/be_animate_lib.c deleted file mode 100644 index 77a88bbc8..000000000 --- a/lib/libesp32/berry_tasmota/src/be_animate_lib.c +++ /dev/null @@ -1,7 +0,0 @@ -/******************************************************************** - * Berry module `animate` - * - * To use: `import animate` - * - *******************************************************************/ -#include "solidify/solidified_animate_module.h" diff --git a/lib/libesp32/berry_tasmota/src/be_animate_module.c b/lib/libesp32/berry_tasmota/src/be_animate_module.c new file mode 100644 index 000000000..b21102e8f --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_animate_module.c @@ -0,0 +1,197 @@ +/* + be_animate_module.c - implements the animate module for Leds + + Copyright (C) 2023 Stephan Hadinger & Theo Arends + + 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 . +*/ + +/*******************************************************************\ + * `animate` global module +\*******************************************************************/ + +#include "be_constobj.h" +#include "be_mapping.h" + +#include "solidify/solidified_animate_0_core.h" +#include "solidify/solidified_animate_1_animate_effects.h" +#include "solidify/solidified_animate_9_module.h" + + +/*******************************************************************\ + * standard palettes +\*******************************************************************/ +static const uint8_t PALETTE_RAINBOW_WHITE[] = { + 0x50, 0xFF, 0x00, 0x00, // red + 0x30, 0xFF, 0x00, 0x00, // red + 0x50, 0xFF, 0xA5, 0x00, // orange + 0x30, 0xFF, 0xA5, 0x00, // orange + 0x50, 0xFF, 0xFF, 0x00, // yellow + 0x30, 0xFF, 0xFF, 0x00, // yellow + 0x50, 0x00, 0xFF, 0x00, // green + 0x30, 0x00, 0xFF, 0x00, // green + 0x50, 0x00, 0x00, 0xFF, // blue + 0x30, 0x00, 0x00, 0xFF, // blue + 0x50, 0xFF, 0x00, 0xFF, // indigo + 0x30, 0xFF, 0x00, 0xFF, // indigo + 0x50, 0xFF, 0xFF, 0xFF, // white + 0x30, 0xFF, 0xFF, 0xFF, // white + 0x00, 0xFF, 0x00, 0x00, // red +}; + +static const uint8_t PALETTE_STANDARD_TAG[] = { + 0x40, 0xFF, 0x00, 0x00, // red + 0x40, 0xFF, 0xA5, 0x00, // orange + 0x40, 0xFF, 0xFF, 0x00, // yellow + 0x40, 0x00, 0xFF, 0x00, // green + 0x40, 0x00, 0x00, 0xFF, // blue + 0x40, 0xFF, 0x00, 0xFF, // indigo + 0x40, 0xFF, 0xFF, 0xFF, // violet + 0x00, 0xFF, 0x00, 0x00, // red +}; + +// Gradient palette "ib_jul01_gp", originally from +// http://soliton.vm.bytemark.co.uk/pub/cpt-city/ing/xmas/tn/ib_jul01.png.index.html +static const uint8_t PALETTE_ib_jul01_gp[] = { + 0x00, 0xE6, 0x06, 0x11, // rgb(230, 6, 17) 0.000%, + 0x5E, 0x25, 0x60, 0x5A, // rgb( 37, 96, 90) 37.010%, + 0x85, 0x90, 0xBD, 0x6A, // rgb(144,189,106) 52.000%, + 0xFF, 0xBB, 0x03, 0x0D, // rgb(187, 3, 13) 100.000% +}; + +static const uint8_t PALETTE_STANDARD_VAL[] = { + 0x00, 0xFF, 0x00, 0x00, // red + 0x24, 0xFF, 0xA5, 0x00, // orange + 0x49, 0xFF, 0xFF, 0x00, // yellow + 0x6E, 0x00, 0xFF, 0x00, // green + 0x92, 0x00, 0x00, 0xFF, // blue + 0xB7, 0xFF, 0x00, 0xFF, // indigo + 0xDB, 0xFF, 0xFF, 0xFF, // violet + 0xFF, 0xFF, 0x00, 0x00, // red +}; + +static const uint8_t PALETTE_SATURATED_TAG[] = { + 0x40, 0xFF, 0x00, 0x00, // red + 0x40, 0xFF, 0xA5, 0x00, // orange + 0x40, 0xFF, 0xFF, 0x00, // yellow + 0x40, 0x00, 0xFF, 0x00, // green + 0x40, 0x00, 0x00, 0xFF, // blue + 0x40, 0xFF, 0x00, 0xFF, // indigo + 0x40, 0xFF, 0xFF, 0xFF, // violet + 0x00, 0xFF, 0x00, 0x00, // red +}; + +extern const bclass be_class_Leds_frame; + +#include "be_fixed_animate.h" + +/* @const_object_info_begin + +module animate (scope: global, strings: weak) { + SAWTOOTH, int(1) + TRIANGLE, int(2) + SQUARE, int(3) + COSINE, int(4) + SINE, int(5) + LASTFORM, int(5) + + PALETTE_STANDARD_TAG, comptr(PALETTE_STANDARD_TAG) + PALETTE_RAINBOW_WHITE, comptr(PALETTE_RAINBOW_WHITE) + PALETTE_STANDARD_VAL, comptr(PALETTE_STANDARD_VAL) + PALETTE_SATURATED_TAG, comptr(PALETTE_SATURATED_TAG) + + (), class(be_class_Animate_core) + core, class(be_class_Animate_core) // alias + animator, class(be_class_Animate_animator) + frame, class(be_class_Leds_frame) + pulse, class(be_class_Animate_pulse) + palette, class(be_class_Animate_palette) + oscillator, class(be_class_Animate_oscillator) +} + +@const_object_info_end */ + +/* Unit test for palettes + +import animate +var p, gradient +p = animate.palette.ptr_to_palette(animate.PALETTE_STANDARD_TAG) +assert(p == bytes('40FF000040FFA50040FFFF004000FF00400000FF40FF00FF40FFFFFF00FF0000')) +gradient = animate.palette.to_css_gradient(p) +assert(gradient == 'background:linear-gradient(to right,#FF0000 0.0%,#FFA500 14.3%,#FFFF00 28.6%,#00FF00 42.9%,#0000FF 57.1%,#FF00FF 71.4%,#FFFFFF 85.7%,#FF0000 100.0%);') + +p = animate.palette.ptr_to_palette(animate.PALETTE_STANDARD_VAL) +assert(p == bytes('00FF000024FFA50049FFFF006E00FF00920000FFB7FF00FFDBFFFFFFFFFF0000')) +gradient = animate.palette.to_css_gradient(animate.PALETTE_STANDARD_VAL) +assert(gradient == 'background:linear-gradient(to right,#FF0000 0.0%,#FFA500 14.1%,#FFFF00 28.6%,#00FF00 43.1%,#0000FF 57.3%,#FF00FF 71.8%,#FFFFFF 85.9%,#FF0000 100.0%);') + + +# unit tests +import animate +var o = animate.oscillator(-1000, 1000, 3000) +o.start(1000) +assert(o.value == -1000) +assert(o.animate(1500) == -667) +assert(o.animate(2500) == 0) +assert(o.animate(3999) == 1000) +assert(o.animate(4000) == -1000) +assert(o.animate(4100) == -933) + +o = animate.oscillator(-1000, 1000, 6000, animate.TRIANGLE) +o.start(1000) +assert(o.value == -1000) +assert(o.animate(1500) == -667) +assert(o.animate(2500) == 0) +assert(o.animate(3999) == 1000) +assert(o.animate(4000) == 1000) +assert(o.animate(4100) == 933) +assert(o.animate(6000) == -334) +assert(o.animate(7000) == -1000) +assert(o.animate(7100) == -933) + +o = animate.oscillator(-1000, 1000, 6000, animate.SQUARE) +o.start(1000) +assert(o.value == -1000) +assert(o.animate(1500) == -1000) +assert(o.animate(2500) == -1000) +assert(o.animate(3999) == -1000) +assert(o.animate(4000) == 1000) +assert(o.animate(4100) == 1000) +assert(o.animate(6000) == 1000) +assert(o.animate(7000) == -1000) +assert(o.animate(7100) == -1000) + +o = animate.oscillator(-1000, 1000, 6000, animate.SINE) +o.start(1000) +assert(o.animate(1000) == 0) +assert(o.animate(1500) == 500) +assert(o.animate(2000) == 867) +assert(o.animate(2500) == 1000) +assert(o.animate(4000) == 0) +assert(o.animate(5500) == -1000) +assert(o.animate(7000) == 0) + +o = animate.oscillator(-1000, 1000, 6000, animate.COSINE) +o.start(1000) +assert(o.animate(1000) == -1000) +assert(o.animate(1500) == -867) +assert(o.animate(2000) == -500) +assert(o.animate(2500) == 0) +assert(o.animate(4000) == 1000) +assert(o.animate(5500) == 0) +assert(o.animate(7000) == -1000) + + + +*/ \ No newline at end of file diff --git a/lib/libesp32/berry_tasmota/src/be_leds_animator_class.c b/lib/libesp32/berry_tasmota/src/be_leds_animator_class.c deleted file mode 100644 index 3bf10367a..000000000 --- a/lib/libesp32/berry_tasmota/src/be_leds_animator_class.c +++ /dev/null @@ -1,9 +0,0 @@ -/******************************************************************** - * Berry class `Leds_animator` - * - *******************************************************************/ -#ifdef USE_WS2812 - -#include "solidify/solidified_leds_0_animator.h" - -#endif // USE_WS2812 diff --git a/lib/libesp32/berry_tasmota/src/be_leds_pulse_class.c b/lib/libesp32/berry_tasmota/src/be_leds_pulse_class.c deleted file mode 100644 index 3a2753b56..000000000 --- a/lib/libesp32/berry_tasmota/src/be_leds_pulse_class.c +++ /dev/null @@ -1,9 +0,0 @@ -/******************************************************************** - * Berry class `Leds_pulse` - * - *******************************************************************/ -#ifdef USE_WS2812 - -#include "solidify/solidified_leds_1_animate_effects.h" - -#endif // USE_WS2812 diff --git a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c index 9bd9120b7..f023a832f 100644 --- a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c @@ -35,6 +35,7 @@ extern int l_delay(bvm *vm); extern int l_delay_microseconds(bvm *vm); extern int l_scaleuint(bvm *vm); extern int l_scaleint(bvm *vm); +extern int l_sineint(bvm *vm); extern int l_logInfo(bvm *vm); extern int l_loglevel(bvm *vm); extern int l_save(bvm *vm); @@ -120,6 +121,7 @@ class be_class_tasmota (scope: global, name: Tasmota) { delay_microseconds, func(l_delay_microseconds) scale_uint, static_func(l_scaleuint) scale_int, static_func(l_scaleint) + sine_int, static_func(l_sineint) log, func(l_logInfo) loglevel, func(l_loglevel) save, func(l_save) diff --git a/lib/libesp32/berry_tasmota/src/embedded/leds_0_animator.be b/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be similarity index 94% rename from lib/libesp32/berry_tasmota/src/embedded/leds_0_animator.be rename to lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be index e6de57d09..f7bdf2e52 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/leds_0_animator.be +++ b/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be @@ -1,13 +1,8 @@ -# class Leds_animator - -#@ solidify:Leds_animator,weak - -# for solidification -class Leds_frame end +# class Animate_core ########################################################################################## # -# class Leds_animator +# class Animate_core # # Simple framework to orchestrate all the animations for a led strip or led matrix # @@ -15,7 +10,8 @@ class Leds_frame end # This version uses `fast_loop` for up to 5ms animation time (200 Hz) # ########################################################################################## -class Leds_animator +#@ solidify:Animate_core,weak +class Animate_core var strip # neopixelbus object var pixel_count # number of pixels in the strip var bri # brightness of the animation, 0..100, default 50 @@ -35,6 +31,7 @@ class Leds_animator var back_color # background color RRGGBB def init(strip, bri) + import animate self.strip = strip if (bri == nil) bri = 50 end self.bri = bri # percentage of brightness 0..100 @@ -44,8 +41,8 @@ class Leds_animator self.painters = [] # self.clear() # clear all leds first - self.frame = Leds_frame(self.pixel_count) - self.layer = Leds_frame(self.pixel_count) + self.frame = animate.frame(self.pixel_count) + self.layer = animate.frame(self.pixel_count) # self.fast_loop_cb = def() self.fast_loop() end self.back_color = 0x000000 diff --git a/lib/libesp32/berry_tasmota/src/embedded/leds_1_animate_effects.be b/lib/libesp32/berry_tasmota/src/embedded/animate_1_animate_effects.be similarity index 82% rename from lib/libesp32/berry_tasmota/src/embedded/leds_1_animate_effects.be rename to lib/libesp32/berry_tasmota/src/embedded/animate_1_animate_effects.be index fd8d112ed..e2a5a9736 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/leds_1_animate_effects.be +++ b/lib/libesp32/berry_tasmota/src/embedded/animate_1_animate_effects.be @@ -1,14 +1,12 @@ -# class Leds_pulse - -#@ solidify:Leds_pulse,weak +# class Animate_pulse ########################################################################################## # -# class Leds_pulse +# class Animate_pulse # # Display a color pulse # -# index (1) +# pos (1) # | # v # _______ @@ -17,16 +15,17 @@ # | | | | # |2| 3 |2| # -# 1: `index`, start of the pulse (in pixel) +# 1: `pos`, start of the pulse (in pixel) # 2: `slew_size`, number of pixels to fade from back to fore color, can be `0` # 3: `pulse_size`, number of pixels of the pulse # ########################################################################################## -class Leds_pulse +#@ solidify:Animate_pulse,weak +class Animate_pulse var color var back_color - var index + var pos var slew_size var pulse_size @@ -54,8 +53,8 @@ class Leds_pulse self.back_color = c end - def set_index(index) - self.index = index + def set_pos(pos) + self.pos = pos end def set_slew_size(slew_size) @@ -72,18 +71,18 @@ class Leds_pulse if (back_color != 0xFF000000) frame.fill_pixels(back_color) # fill with transparent color end - var index = self.index + var pos = self.pos var slew_size = self.slew_size var pulse_size = self.pulse_size var color = self.color var pixel_size = frame.pixel_size - # var min_index = index - slew_size - # var max_index = index + pulse_size + slew_size - 1 + # var min_index = pos - slew_size + # var max_index = pos + pulse_size + slew_size - 1 var pulse_min, pulse_max - pulse_min = index - pulse_max = index + pulse_size + pulse_min = pos + pulse_max = pos + pulse_size if (pulse_min < 0) pulse_min = 0 end if (pulse_max >= pixel_size) pulse_max = pixel_size end @@ -94,28 +93,28 @@ class Leds_pulse end if (slew_size > 0) - # check first slew, from `min_index` to `index - 1` + # check first slew, from `min_index` to `pos - 1` # Slew 1 - pulse_min = index - slew_size - pulse_max = index + pulse_min = pos - slew_size + pulse_max = pos if (pulse_min < 0) pulse_min = 0 end if (pulse_max >= pixel_size) pulse_max = pixel_size end i = pulse_min while (i < pulse_max) # blend from 255 (back) to 0 (fore) - frame[i] = frame.blend(back_color, color, tasmota.scale_int(i, index - slew_size - 1, index, 255, 0)) + frame[i] = frame.blend(back_color, color, tasmota.scale_int(i, pos - slew_size - 1, pos, 255, 0)) # blend i += 1 end # Slew 2 - pulse_min = index + pulse_size - pulse_max = index + pulse_size + slew_size + pulse_min = pos + pulse_size + pulse_max = pos + pulse_size + slew_size if (pulse_min < 0) pulse_min = 0 end if (pulse_max >= pixel_size) pulse_max = pixel_size end i = pulse_min while (i < pulse_max) # blend - frame[i] = frame.blend(back_color, color, tasmota.scale_int(i, index + pulse_size - 1, index + pulse_size + slew_size, 0, 255)) + frame[i] = frame.blend(back_color, color, tasmota.scale_int(i, pos + pulse_size - 1, pos + pulse_size + slew_size, 0, 255)) i += 1 end end @@ -130,10 +129,11 @@ end # if false -var frame = Leds_frame(10) +import animate +var frame = animate.frame(10) assert(frame.tohex() == '00000000000000000000000000000000000000000000000000000000000000000000000000000000') -var pulse = Leds_pulse(0x00FF00, 3, 2) +var pulse = Animate_pulse(0x00FF00, 3, 2) pulse.set_index(5) pulse.paint(frame) assert(frame.tohex() == '0000000000000000000000000055000000AA000000FF000000FF000000FF000000AA000000550000') diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be b/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be new file mode 100644 index 000000000..45f22b81b --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be @@ -0,0 +1,508 @@ +# +# class Animate +# +# Animation framework +# + +animate = module("animate") + +# for solidification +class Leds_frame end + +animate.("()") = Animate_core # make it available as `animate()` +animate.frame = Leds_frame +animate.pulse = Animate_pulse + +################################################################################# +# class Animate_palette +# +# Animated color palette +################################################################################# + +################################################################################# +# Palette format compatible +# +# Takes a binary array with a set of 4 bytes elements: VRGB +# V: Value in a range 0..255. The first value must be 0, +# the last needs to be 255. +# Numbers must be in strictly increasin numbers. +# The algorithm maps a 0..255 rotating value to its color +# in the palette. +# R: Red component +# G: Green component +# B: Blue component +# Note: RGB is in big Endian to make it more readable, although +# it's little-endian when in memory. Be aware! +# RGB values are stored at max brightness and without gamma correction +################################################################################# + +# # Gradient palette "ib_jul01_gp", originally from +# # http://soliton.vm.bytemark.co.uk/pub/cpt-city/ing/xmas/tn/ib_jul01.png.index.html +# var PALETTE_ib_jul01_gp = bytes( +# "00" "E60611" +# "5E" "25605A" +# "85" "90BD6A" +# "FF" "BB030D" +# ) +# # animate.PALETTE_ib_jul01_gp = PALETTE_ib_jul01_gp +# # rgb(230, 6, 17) 0.000%, +# # rgb( 37, 96, 90) 37.010%, +# # rgb(144,189,106) 52.000%, +# # rgb(187, 3, 13) 100.000% + +# var PALETTE_STANDARD_VAL = bytes( +# "00" "FF0000" # red +# "24" "FFA500" # orange +# "49" "FFFF00" # yellow +# "6E" "008800" # green +# "92" "0000FF" # blue +# "B7" "4B0082" # indigo +# "DB" "EE82EE" # violet +# "FF" "FF0000" # red +# ) +# # animate.PALETTE_STANDARD = PALETTE_STANDARD + +# var PALETTE_SATURATED_TAG = bytes( +# "40" "FF0000" # red +# "40" "FFA500" # orange +# "40" "FFFF00" # yellow +# "40" "00FF00" # green +# "40" "0000FF" # blue +# "40" "FF00FF" # indigo +# "40" "EE44A5" # violet +# "00" "FF0000" # red +# ) + +# var PALETTE_STANDARD_TAG = bytes( +# "40" "FF0000" # red +# "40" "FFA500" # orange +# "40" "FFFF00" # yellow +# "40" "008800" # green +# "40" "0000FF" # blue +# "40" "4B0082" # indigo +# "40" "EE82EE" # violet +# "00" "FF0000" # red +# ) +# # animate.PALETTE_STANDARD = PALETTE_STANDARD + + +#@ solidify:Animate_animator,weak +class Animate_animator + # timing information + var running # true if running + var duration_ms # duration_ms of the entire cycle in ms, cannot be `0` + var origin # origin in ms of the current cycle, as per tasmota.millis() reference + # callback information + var obj # object to call + var mth # object method to call + + def init(duration_ms) + self.duration_ms = duration_ms + end + + def set_duration_ms(duration_ms) + self.duration_ms = duration_ms + end + + def set_cb(obj, mth) + self.obj = obj + self.mth = mth + end + + def start(millis) + if (self.duration_ms == nil) return end + if millis == nil millis = tasmota.millis() end + self.origin = millis + self.running = true + end + + def stop() + self.origin = nil + self.running = false + end + + def is_running() + return bool(self.running) + end + + # called at the end of each cycle + def beat() + end + +end + +#@ solidify:Animate_palette,weak +class Animate_palette : Animate_animator + ## inherited + ## timing information + # var running + # var duration_ms # duration_ms of the entire cycle in ms, cannot be `0` + # var origin # origin in ms of the current cycle, as per tasmota.millis() reference + ## callback information + # var obj # object to call + # var mth # object method to call + + # parsing of palette + var palette # raw bytes object + var slots_arr # constructed array of timestamp slots + var slots # number of slots + # range information (when used as range color) + var range_min # minimum value expected as input + var range_max # maximum value expected as input, needs (range_min < range_max, can be negative) + # brightness + var bri # brightness to be applied to palette 0..100 + # color object to do RGB color calculation + var color # instance of light_state, used for color calculation (reuse of object) + + def init(palette, duration_ms) + super(self).init(duration_ms) + self.running = false + if (type(palette) == 'ptr') palette = self.ptr_to_palette(palette) end # convert comptr to palette buffer + self.palette = palette + self.bri = 100 + self.slots = size(palette) / 4 + if duration_ms != nil + self.set_duration(duration_ms) + end + self.color = light_state(light_state.RGB) + end + + # setter to be used as cb + def set_bri(bri) + self.bri = int(bri) + end + + # convert a comptr to a bytes() for palette + # parse the raw bytes to find the actual length + # + # input: comptr + # return: bytes() object of palette + static def ptr_to_palette(p) + if type(p) == 'ptr' + var b_raw = bytes(p, 2000) # arbitrary large size + var idx = 1 + if b_raw[0] != 0 + # palette in tick counts + while true + if b_raw[idx * 4] == 0 + break + end + idx += 1 + end + else + # palette is in value range from 0..255 + while true + if b_raw[idx * 4] == 0xFF + break + end + idx += 1 + end + end + var sz = (idx + 1) * 4 + return bytes(p, sz) + end + end + + def parse_palette(min, max) + var arr = [] + var slots = self.slots + arr.resize(slots) + + # check if we have slots or values + # if first value index is non-zero, it's ticks count + if self.palette.get(0, 1) != 0 + # palette in tick counts + # compute the total number of ticks + var total_ticks = 0 + var idx = 0 + while idx < slots - 1 + total_ticks += self.palette.get(idx * 4, 1) + idx += 1 + end + var cur_ticks = 0 + idx = 0 + while idx < slots + arr[idx] = tasmota.scale_int(cur_ticks, 0, total_ticks, min, max) + cur_ticks += self.palette.get(idx * 4, 1) + idx += 1 + end + else + # palette is in value range from 0..255 + var idx = 0 + while idx < slots + var val = self.palette.get(idx * 4, 1) + arr[idx] = tasmota.scale_int(val, 0, 255, min, max) + idx += 1 + end + end + # print(f"ANM: {arr=}") + return arr + end + + def set_duration(duration_ms) + if (duration_ms == nil) return end + if duration_ms <= 0 raise "value_error", "duration_ms must be positive" end + self.duration_ms = duration_ms + + self.slots_arr = self.parse_palette(0, duration_ms - 1) + end + + def set_range(min, max) + if (min >= max) raise "value_error", "min must be lower than mex" end + self.range_min = min + self.range_max = max + + self.slots_arr = self.parse_palette(min, max) + end + + # compute the css linear-gradient description + # + # Example: background: linear-gradient(to right, #000000, #e66465 11.0%, #9198e5); + static def to_css_gradient(palette) + var p = _class(palette) + var arr = p.parse_palette(0, 1000) + var ret = "background:linear-gradient(to right" + var idx = 0 + while idx < size(arr) + var prm = arr[idx] # per mile + + var bgrt = p.palette.get(idx * 4, 4) + var r = (bgrt >> 8) & 0xFF + var g = (bgrt >> 16) & 0xFF + var b = (bgrt >> 24) & 0xFF + ret += f",#{r:02X}{g:02X}{b:02X} {prm/10.0:.1f}%" + idx += 1 + end + ret += ");" + return ret + end + + def set_value(value) + if (self.range_min == nil || self.range_max == nil) return nil end + var scale_int = tasmota.scale_int + + # find slot + var slots = self.slots + var idx = slots - 2 + while idx > 0 + if value >= self.slots_arr[idx] break end + idx -= 1 + end + var bgrt0 = self.palette.get(idx * 4, 4) + var bgrt1 = self.palette.get((idx + 1) * 4, 4) + var t0 = self.slots_arr[idx] + var t1 = self.slots_arr[idx + 1] + var r = scale_int(value, t0, t1, (bgrt0 >> 8) & 0xFF, (bgrt1 >> 8) & 0xFF) + var g = scale_int(value, t0, t1, (bgrt0 >> 16) & 0xFF, (bgrt1 >> 16) & 0xFF) + var b = scale_int(value, t0, t1, (bgrt0 >> 24) & 0xFF, (bgrt1 >> 24) & 0xFF) + var rgb = (r << 16) | (g << 8) | b + # + var obj = self.obj + var mth = self.mth + if (obj && mth) + mth(obj, rgb) + end + # if self.cb != nil + # self.cb(rgb) + # end + # + # print(f"ANM: {rgb=:%06X}") + return rgb + end + + def animate(millis) + if (self.duration_ms == nil) return end + if millis == nil millis = tasmota.millis() end + var past = millis - self.origin + if past < 0 + past = 0 + millis = self.origin + end + var duration_ms = self.duration_ms + var scale_uint = tasmota.scale_uint + if past >= duration_ms + self.origin += (past / duration_ms) * duration_ms + past = past % duration_ms + end + # find slot + var slots = self.slots + var idx = slots - 2 + while idx > 0 + if past >= self.slots_arr[idx] break end + idx -= 1 + end + var bgrt0 = self.palette.get(idx * 4, 4) + var bgrt1 = self.palette.get((idx + 1) * 4, 4) + var t0 = self.slots_arr[idx] + var t1 = self.slots_arr[idx + 1] + var r = scale_uint(past, t0, t1, (bgrt0 >> 8) & 0xFF, (bgrt1 >> 8) & 0xFF) + var g = scale_uint(past, t0, t1, (bgrt0 >> 16) & 0xFF, (bgrt1 >> 16) & 0xFF) + var b = scale_uint(past, t0, t1, (bgrt0 >> 24) & 0xFF, (bgrt1 >> 24) & 0xFF) + + var color = self.color + color.set_rgb((bgrt0 >> 8) & 0xFF, (bgrt0 >> 16) & 0xFF, (bgrt0 >> 24) & 0xFF) + var bri0 = color.bri + color.set_rgb((bgrt1 >> 8) & 0xFF, (bgrt1 >> 16) & 0xFF, (bgrt1 >> 24) & 0xFF) + var bri1 = color.bri + var bri2 = scale_uint(past, t0, t1, bri0, bri1) + color.set_rgb(r, g, b) + color.set_bri(bri2) + + r = color.r + g = color.g + b = color.b + + # apply self.bri if not `100` + var bri = self.bri + if bri != 100 + r = tasmota.scale_uint(r, 0, 100, 0, bri) + g = tasmota.scale_uint(g, 0, 100, 0, bri) + b = tasmota.scale_uint(b, 0, 100, 0, bri) + end + + # var rgb = (r << 16) | (g << 8) | b + var rgb = (r << 16) | (g << 8) | b + + var obj = self.obj + var mth = self.mth + if (obj && mth) + mth(obj, rgb) + end + + return rgb + end +end +animate.palette = Animate_palette + +#- + +pal = Animate_palette(PALETTE_STANDARD_TAG, 7000) +pal = Animate_palette(PALETTE_STANDARD_VAL, 7000) + + +import animate +var pal = animate.palette(PALETTE_STANDARD_TAG, 7000) +pal.start(0) +for t: range(0,8000,200) + pal.tick(t) +end + +-# + +animate.SAWTOOTH = 1 +animate.TRIANGLE = 2 +animate.SQUARE = 3 +animate.COSINE = 4 +animate.SINE = 5 +animate.LASTFOMR = 5 # identify last form + +#@ solidify:Animate_oscillator,weak +class Animate_oscillator : Animate_animator + ## inherited + ## timing information + # var running + # var duration_ms # duration_ms of the entire cycle in ms, cannot be `0` + # var origin # origin in ms of the current cycle, as per tasmota.millis() reference + var phase # 0..100% - phase shift, default 0 + var duty_cycle # 0..100% - duty cycle, default 50% + ## callback information + # var obj # object to call + # var mth # object method to call + var a # starting value + var b # end value + var form # waveform + # current value + var value + + def init(a, b, duration_ms, form) + self.phase = 0 + self.duty_cycle = 50 + self.a = a + self.b = b + self.duration_ms = duration_ms + self.value = a + if (form == nil) form = 1 end + self.form = form + end + + def set_phase(phase) + if (phase < 0) phase = 0 end + if (phase > 100) phase = 100 end + self.phase = phase + end + + def set_duty_cycle(duty_cycle) + if (duty_cycle < 0) duty_cycle = 0 end + if (duty_cycle > 100) duty_cycle = 100 end + self.duty_cycle = duty_cycle + end + + def set_a(a) + self.a = a + end + def set_b(b) + self.b = b + end + + def animate(millis) + if (self.duration_ms == nil) return end + if millis == nil millis = tasmota.millis() end + var past = millis - self.origin + if past < 0 + past = 0 + millis = self.originally + end + var duration_ms = self.duration_ms + var duration_ms_mid # mid point considering duty cycle + duration_ms_mid = tasmota.scale_uint(self.duty_cycle, 0, 100, 0, duration_ms) + if past >= duration_ms + self.origin += (past / duration_ms) * duration_ms + past = past % duration_ms + # handle end of cycle + self.beat() + end + + var a = self.a + var b = self.b + var value = self.value + var past_with_phase = past # adjust past with phase + if self.phase > 0 + past_with_phase += tasmota.scale_uint(self.phase, 0, 100, 0, duration_ms) + if (past_with_phase > duration_ms) past_with_phase -= duration_ms end # if overflow, take modulus + end + + if self.form == 1 #-SAWTOOTH-# + value = tasmota.scale_int(past_with_phase, 0, duration_ms - 1, a, b) + elif self.form == 2 #-TRIANGLE-# + if past_with_phase < duration_ms_mid + value = tasmota.scale_int(past_with_phase, 0, duration_ms_mid - 1, a, b) + else + value = tasmota.scale_int(past_with_phase, duration_ms_mid, duration_ms - 1, b, a) + end + elif self.form == 3 #-SQUARE-# + if past_with_phase < duration_ms_mid + value = a + else + value = b + end + elif (self.form == 4) #-COSINE-# || (self.form == 5) #-SINE-# + # map timing to 0..32767 + var angle = tasmota.scale_int(past_with_phase, 0, duration_ms - 1, 0, 32767) + if (self.form == 4) #-COSINE-# + angle -= 8192 + end + var x = tasmota.sine_int(angle) # -4096 .. 4096 + value = tasmota.scale_int(x, -4096, 4096, a, b) + end + self.value = value + + var obj = self.obj + var mth = self.mth + if (obj && mth) + mth(obj, value) + end + + return value + end +end +animate.oscillator = Animate_oscillator diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_module.be b/lib/libesp32/berry_tasmota/src/embedded/animate_module.be deleted file mode 100644 index f1857c90c..000000000 --- a/lib/libesp32/berry_tasmota/src/embedded/animate_module.be +++ /dev/null @@ -1,573 +0,0 @@ -# -# class Animate -# -# Animation framework -# - -#@ solidify:animate,weak -animate = module("animate") - -# state-machine: from val a to b -class Animate_ins_ramp - var a # starting value - var b # end value - var duration # duration in milliseconds - - def init(a,b,duration) - self.a = a - self.b = b - self.duration = duration - end -end -animate.ins_ramp = Animate_ins_ramp - - -################################################################################# -# class Animate_palette -# -# Animated color palette -################################################################################# - -################################################################################# -# Palette format compatible -# -# Takes a binary array with a set of 4 bytes elements: VRGB -# V: Value in a range 0..255. The first value must be 0, -# the last needs to be 255. -# Numbers must be in strictly increasin numbers. -# The algorithm maps a 0..255 rotating value to its color -# in the palette. -# R: Red component -# G: Green component -# B: Blue component -# Note: RGB is in big Endian to make it more readable, although -# it's little-endian when in memory. Be aware! -# RGB values are stored at max brightness and without gamma correction -################################################################################# - -# Gradient palette "ib_jul01_gp", originally from -# http://soliton.vm.bytemark.co.uk/pub/cpt-city/ing/xmas/tn/ib_jul01.png.index.html -var PALETTE_ib_jul01_gp = bytes( - "00" "E60611" - "5E" "25605A" - "85" "90BD6A" - "FF" "BB030D" -) -# animate.PALETTE_ib_jul01_gp = PALETTE_ib_jul01_gp -# rgb(230, 6, 17) 0.000%, -# rgb( 37, 96, 90) 37.010%, -# rgb(144,189,106) 52.000%, -# rgb(187, 3, 13) 100.000% - -var PALETTE_STANDARD_VAL = bytes( - "00" "FF0000" # red - "24" "FFA500" # orange - "49" "FFFF00" # yellow - "6E" "008800" # green - "92" "0000FF" # blue - "B7" "4B0082" # indigo - "DB" "EE82EE" # violet - "FF" "FF0000" # red -) -# animate.PALETTE_STANDARD = PALETTE_STANDARD - -var PALETTE_SATURATED_TAG = bytes( - "40" "FF0000" # red - "40" "FFA500" # orange - "40" "FFFF00" # yellow - "40" "00FF00" # green - "40" "0000FF" # blue - "40" "FF00FF" # indigo - "40" "EE44A5" # violet - "00" "FF0000" # red -) - -var PALETTE_STANDARD_TAG = bytes( - "40" "FF0000" # red - "40" "FFA500" # orange - "40" "FFFF00" # yellow - "40" "008800" # green - "40" "0000FF" # blue - "40" "4B0082" # indigo - "40" "EE82EE" # violet - "00" "FF0000" # red -) -# animate.PALETTE_STANDARD = PALETTE_STANDARD - - -class Animate_palette - # parsing of palette - var palette # raw bytes object - var slots_arr # constructed array of timestamp slots - var slots # number of slots - # timing information - var running - var duration_ms # duration_ms of the entire cycle in ms, cannot be `0` - var origin # origin in ms of the current cycle, as per tasmota.millis() reference - # range information (when used as range color) - var range_min # minimum value expected as input - var range_max # maximum value expected as input, needs (range_min < range_max, can be negative) - # callback information - var animate_obj # object to call - var animate_mth # object method to call - # brightness - var bri # brightness to be applied to palette 0..100 - # color object to do RGB color calculation - var color # instance of light_state, used for color calculation (reuse of object) - - def init(palette, duration_s) - self.running = false - self.palette = palette - self.bri = 100 - self.slots = size(palette) / 4 - if duration_s != nil - self.set_duration(int(duration_s * 1000)) - end - self.color = light_state(light_state.RGB) - end - - def set_cb(obj, mth) - self.animate_obj = obj - self.animate_mth = mth - end - - # setter to be used as cb - def set_bri(bri) - self.bri = int(bri) - end - - def start(millis) - if (self.duration_ms == nil) return end - if millis == nil millis = tasmota.millis() end - self.origin = millis - self.running = true - end - - def stop() - self.origin = nil - self.running = false - end - - def is_running() - return bool(self.running) - end - - def parse_palette(min, max) - var arr = [] - var slots = self.slots - arr.resize(slots) - - # check if we have slots or values - # if first value index is non-zero, it's ticks count - if self.palette.get(0, 1) != 0 - # palette in tick counts - # compute the total number of ticks - var total_ticks = 0 - var idx = 0 - while idx < slots - 1 - total_ticks += self.palette.get(idx * 4, 1) - idx += 1 - end - var cur_ticks = 0 - idx = 0 - while idx < slots - arr[idx] = tasmota.scale_int(cur_ticks, 0, total_ticks, min, max) - cur_ticks += self.palette.get(idx * 4, 1) - idx += 1 - end - else - # palette is in value range from 0..255 - var idx = 0 - while idx < slots - var val = self.palette.get(idx * 4, 1) - arr[idx] = tasmota.scale_int(val, 0, 255, min, max) - idx += 1 - end - end - # print(f"ANM: {arr=}") - return arr - end - - def set_duration(duration_ms) - if (duration_ms == nil) return end - if duration_ms <= 0 raise "value_error", "duration_ms must be positive" end - self.duration_ms = duration_ms - - self.slots_arr = self.parse_palette(0, duration_ms - 1) - end - - def set_range(min, max) - if (min >= max) raise "value_error", "min must be lower than mex" end - self.range_min = min - self.range_max = max - - self.slots_arr = self.parse_palette(min, max) - end - - # compute the css linear-gradient description - # - # Example: background: linear-gradient(to right, #000000, #e66465 11.0%, #9198e5); - def to_css_gradient() - var arr = self.parse_palette(0, 1000) - var ret = "background:linear-gradient(to right" - var idx = 0 - while idx < size(arr) - var prm = arr[idx] # per mile - - var bgrt = self.palette.get(idx * 4, 4) - var r = (bgrt >> 8) & 0xFF - var g = (bgrt >> 16) & 0xFF - var b = (bgrt >> 24) & 0xFF - ret += f",#{r:02X}{g:02X}{b:02X} {prm/10.0:.1f}%" - idx += 1 - end - ret += ");" - return ret - end - - def set_value(value) - if (self.range_min == nil || self.range_max == nil) return nil end - var scale_int = tasmota.scale_int - - # find slot - var slots = self.slots - var idx = slots - 2 - while idx > 0 - if value >= self.slots_arr[idx] break end - idx -= 1 - end - var bgrt0 = self.palette.get(idx * 4, 4) - var bgrt1 = self.palette.get((idx + 1) * 4, 4) - var t0 = self.slots_arr[idx] - var t1 = self.slots_arr[idx + 1] - var r = scale_int(value, t0, t1, (bgrt0 >> 8) & 0xFF, (bgrt1 >> 8) & 0xFF) - var g = scale_int(value, t0, t1, (bgrt0 >> 16) & 0xFF, (bgrt1 >> 16) & 0xFF) - var b = scale_int(value, t0, t1, (bgrt0 >> 24) & 0xFF, (bgrt1 >> 24) & 0xFF) - var rgb = (r << 16) | (g << 8) | b - # - var obj = self.animate_obj - var mth = self.animate_mth - if (obj && mth) - mth(obj, rgb) - end - # if self.cb != nil - # self.cb(rgb) - # end - # - # print(f"ANM: {rgb=:%06X}") - return rgb - end - - def animate(millis) - if (self.duration_ms == nil) return end - if millis == nil millis = tasmota.millis() end - var past = millis - self.origin - if past < 0 - past = 0 - millis = self.origin - end - var duration_ms = self.duration_ms - var scale_uint = tasmota.scale_uint - if past >= duration_ms - self.origin += (past / duration_ms) * duration_ms - past = past % duration_ms - end - # find slot - var slots = self.slots - var idx = slots - 2 - while idx > 0 - if past >= self.slots_arr[idx] break end - idx -= 1 - end - var bgrt0 = self.palette.get(idx * 4, 4) - var bgrt1 = self.palette.get((idx + 1) * 4, 4) - var t0 = self.slots_arr[idx] - var t1 = self.slots_arr[idx + 1] - var r = scale_uint(past, t0, t1, (bgrt0 >> 8) & 0xFF, (bgrt1 >> 8) & 0xFF) - var g = scale_uint(past, t0, t1, (bgrt0 >> 16) & 0xFF, (bgrt1 >> 16) & 0xFF) - var b = scale_uint(past, t0, t1, (bgrt0 >> 24) & 0xFF, (bgrt1 >> 24) & 0xFF) - - var color = self.color - color.set_rgb((bgrt0 >> 8) & 0xFF, (bgrt0 >> 16) & 0xFF, (bgrt0 >> 24) & 0xFF) - var bri0 = color.bri - color.set_rgb((bgrt1 >> 8) & 0xFF, (bgrt1 >> 16) & 0xFF, (bgrt1 >> 24) & 0xFF) - var bri1 = color.bri - var bri2 = scale_uint(past, t0, t1, bri0, bri1) - color.set_rgb(r, g, b) - color.set_bri(bri2) - - r = color.r - g = color.g - b = color.b - - # apply self.bri if not `100` - var bri = self.bri - if bri != 100 - r = tasmota.scale_uint(r, 0, 100, 0, bri) - g = tasmota.scale_uint(g, 0, 100, 0, bri) - b = tasmota.scale_uint(b, 0, 100, 0, bri) - end - - # var rgb = (r << 16) | (g << 8) | b - var rgb = (r << 16) | (g << 8) | b - - var obj = self.animate_obj - var mth = self.animate_mth - if (obj && mth) - mth(obj, rgb) - end - - return rgb - end -end -animate.palette = Animate_palette - -#- - -pal = Animate_palette(PALETTE_STANDARD_TAG, 7000) -pal = Animate_palette(PALETTE_STANDARD_VAL, 7000) - - -import animate -var pal = animate.palette(PALETTE_STANDARD_TAG, 7000) -pal.start(0) -for t: range(0,8000,200) - pal.tick(t) -end - --# - -################################################################################# -# class Animate_segment -# -# Animate a small segment ______/+++\______ -# length in 1/256 pixels -# slew in 1/256 pixels -# fore foregroung color -# back background color (or transparent) -# origin in 1/256 pixels -# -# strip -################################################################################# -# class Animate_segment -# var strip -# var length -# var slew -# var fore -# var back -# var origin - -# def init(strip) -# self.strip = strip -# self.length = 256 # 1 pixel -# self.slew = 0 # 0 pixel (immediate) -# self.fore = 0x00FF0000 # red opaque -# self.back = 0xFF000000 # transparent -# self.origin = 0 # start of strip -# end - -# def paint(bri) -# # move all important values in registers -# var strip = self.strip -# var pix_offset = strip.pixel_offset() -# var pix_count = strip.pixel_count() -# var pix_buffer = strip.pixels_buffer() -# var pix_size = strip.pixel_size() - -# var length = self.length -# var slew = self.slew -# var fore = self.fore -# var back = self.back -# var origin = self.origin - -# var pix = 0 # iterate on each pixel -# var limit_low = (origin - slew) / 256 -# var limit_high = (origin + length + slew) / 256 -# while pix < pix_count -# # are we off limits -# if (pix >= limit_low) && (pix <= limit_high) # outside of those boundaries, we just apply backgroung -# strip.set_pixel_color(pix, fore, bri) -# else -# strip.set_pixel_color(pix, back, bri) -# end -# pix += 1 -# end -# end -# end -# animate.segment = Animate_segment - -# state-machine: pause and goto -class Animate_ins_goto - var pc_rel # relative PC, -1 previous instruction, 1 next instruction, 0 means see pc_abs - var pc_abs # absolute PC, only if pc_rel == 0, address if next instruction - var duration # pause in milliseconds before goto, -1 means infinite (state-machine can be changed externally) - - def init(pc_rel, pc_abs, duration) - self.pc_rel = pc_rel - self.pc_abs = pc_abs - self.duration = duration - end -end -animate.ins_goto = Animate_ins_goto - -class Animate_engine - var code # array of state-machine instructions - var closure # closure to call with the new value - var animate_obj # object to call (alternative to closure) - var animate_mth # method to call on object - var pc # program-counter - var ins_time # absolute time when the current instruction started - var running # is the animation running? allows fast return - var value # current value - - def init() - self.code = [] - self.pc = 0 # start at instruction 0 - self.ins_time = 0 - self.running = false # not running by default - # - end - - def set_cb(obj, mth) - self.animate_obj = obj - self.animate_mth = mth - end - - # start but needs external calls to `animate()` - # cur_time:int (opt) current timestamp in ms, defaults to `tasmota.millis()` - # val:int (opt) starting value, default to `nil` - def start(cur_time, val) - if cur_time == nil cur_time = tasmota.millis() end - if (val != nil) self.value = val end - self.ins_time = cur_time - - self.running = true - end - - # # runs autonomously in the Tasmota event loop - # def autorun(cur_time, val) - # self.run(cur_time, val) - # end - - def stop() - self.running = false - end - - def is_running() - return self.running - end - - def animate(cur_time) # time in milliseconds, optional, defaults to `tasmota.millis()` - if !self.running return end - if cur_time == nil cur_time = tasmota.millis() end - # run through instructions - while true - var sub_index = cur_time - self.ins_time # time since the beginning of current instruction - # - # make sure PC is valid - if self.pc >= size(self.code) - self.running = false - break - end - # - if self.pc < 0 raise "internal_error", "Animate pc is out of range" end - var ins = self.code[self.pc] - - # Instruction Ramp - if isinstance(ins, animate.ins_ramp) - var closure = self.closure # assign to a local variable to not call a method - var obj = self.animate_obj - var mth = self.animate_mth - if sub_index < ins.duration - # we're still in the ramp - self.value = tasmota.scale_uint(sub_index, 0, ins.duration, ins.a, ins.b) - # call method - if (obj && mth) mth(obj, self.value) end - # call closure - if (closure) closure(self.value) end # call closure, need try? TODO - break - else - self.value = ins.b - # call method - if (obj && mth) mth(obj, self.value) end - # call closure - if (closure) closure(self.value) end # set to last value - self.pc += 1 # next instruction - self.ins_time = cur_time - (sub_index - ins.duration) - end - - # Instruction Goto - elif isinstance(ins, animate.ins_goto) - if sub_index < ins.duration - break - else - if ins.pc_rel != 0 - self.pc += ins.pc_rel - else - self.pc = ins.pc_abs - end - self.ins_time = cur_time - (sub_index - ins.duration) - end - - # Invalid - else - raise "internal_error", "unknown instruction" - end - end - return self.value - - end -end -animate.engine = Animate_engine - -class Animate_from_to : Animate_engine - - def init(obj, mth, from, to, duration) - super(self).init() - self.set_cb(obj, mth) - self.code.push(animate.ins_ramp(from, to, duration)) - end - -end -animate.from_to = Animate_from_to - -### -# -# a=Animate_from_to(nil, 0, 100, 5000) -# -### - -class Animate_rotate : Animate_engine - - def init(obj, mth, from, to, duration) - super(self).init() - self.set_cb(obj, mth) - self.code.push(animate.ins_ramp(from, to, duration)) - self.code.push(animate.ins_goto(0, 0, 0)) # goto abs pc = 0 without any pause - end - -end -animate.rotate = Animate_rotate - -#- -a=Animate_rotate(nil, 0, 100, 5000) -a.autorun() --# - -class Animate_back_forth : Animate_engine - - def init(obj, mth, from, to, duration) - super(self).init() - self.set_cb(obj, mth) - self.code.push(animate.ins_ramp(from, to, duration)) - self.code.push(animate.ins_ramp(to, from, duration)) - self.code.push(animate.ins_goto(0, 0, 0)) # goto abs pc = 0 without any pause - end - -end -animate.back_forth = Animate_back_forth - -#- -a=Animate_back_forth(nil, 0, 100, 5000) -a.autorun() --# diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_leds_0_animator.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h similarity index 85% rename from lib/libesp32/berry_tasmota/src/solidify/solidified_leds_0_animator.h rename to lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h index ea031d397..f507d4144 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_leds_0_animator.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h @@ -1,15 +1,15 @@ -/* Solidification of leds_0_animator.h */ +/* Solidification of animate_0_core.h */ /********************************************************************\ * Generated code, don't edit * \********************************************************************/ #include "be_constobj.h" -extern const bclass be_class_Leds_animator; +extern const bclass be_class_Animate_core; /******************************************************************** ** Solidified function: remove ********************************************************************/ -be_local_closure(Leds_animator_remove, /* name */ +be_local_closure(Animate_core_remove, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -44,7 +44,7 @@ be_local_closure(Leds_animator_remove, /* name */ /******************************************************************** ** Solidified function: add_background_animator ********************************************************************/ -be_local_closure(Leds_animator_add_background_animator, /* name */ +be_local_closure(Animate_core_add_background_animator, /* name */ be_nested_proto( 6, /* nstack */ 2, /* argc */ @@ -79,7 +79,7 @@ be_local_closure(Leds_animator_add_background_animator, /* name */ /******************************************************************** ** Solidified function: clear ********************************************************************/ -be_local_closure(Leds_animator_clear, /* name */ +be_local_closure(Animate_core_clear, /* name */ be_nested_proto( 3, /* nstack */ 1, /* argc */ @@ -112,7 +112,7 @@ be_local_closure(Leds_animator_clear, /* name */ /******************************************************************** ** Solidified function: add_animator ********************************************************************/ -be_local_closure(Leds_animator_add_animator, /* name */ +be_local_closure(Animate_core_add_animator, /* name */ be_nested_proto( 5, /* nstack */ 2, /* argc */ @@ -143,7 +143,7 @@ be_local_closure(Leds_animator_add_animator, /* name */ /******************************************************************** ** Solidified function: animate ********************************************************************/ -be_local_closure(Leds_animator_animate, /* name */ +be_local_closure(Animate_core_animate, /* name */ be_nested_proto( 1, /* nstack */ 1, /* argc */ @@ -167,7 +167,7 @@ be_local_closure(Leds_animator_animate, /* name */ /******************************************************************** ** Solidified function: get_bri ********************************************************************/ -be_local_closure(Leds_animator_get_bri, /* name */ +be_local_closure(Animate_core_get_bri, /* name */ be_nested_proto( 3, /* nstack */ 2, /* argc */ @@ -194,7 +194,7 @@ be_local_closure(Leds_animator_get_bri, /* name */ /******************************************************************** ** Solidified function: set_bri ********************************************************************/ -be_local_closure(Leds_animator_set_bri, /* name */ +be_local_closure(Animate_core_set_bri, /* name */ be_nested_proto( 2, /* nstack */ 2, /* argc */ @@ -221,7 +221,7 @@ be_local_closure(Leds_animator_set_bri, /* name */ /******************************************************************** ** Solidified function: set_back_color ********************************************************************/ -be_local_closure(Leds_animator_set_back_color, /* name */ +be_local_closure(Animate_core_set_back_color, /* name */ be_nested_proto( 2, /* nstack */ 2, /* argc */ @@ -248,7 +248,7 @@ be_local_closure(Leds_animator_set_back_color, /* name */ /******************************************************************** ** Solidified function: stop ********************************************************************/ -be_local_closure(Leds_animator_stop, /* name */ +be_local_closure(Animate_core_stop, /* name */ be_nested_proto( 6, /* nstack */ 1, /* argc */ @@ -299,7 +299,7 @@ be_local_closure(Leds_animator_stop, /* name */ /******************************************************************** ** Solidified function: set_cb ********************************************************************/ -be_local_closure(Leds_animator_set_cb, /* name */ +be_local_closure(Animate_core_set_cb, /* name */ be_nested_proto( 3, /* nstack */ 3, /* argc */ @@ -328,9 +328,9 @@ be_local_closure(Leds_animator_set_cb, /* name */ /******************************************************************** ** Solidified function: init ********************************************************************/ -be_local_closure(Leds_animator_init, /* name */ +be_local_closure(Animate_core_init, /* name */ be_nested_proto( - 5, /* nstack */ + 7, /* nstack */ 3, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -363,15 +363,15 @@ be_local_closure(Leds_animator_init, /* name */ }), 1, /* has constants */ ( &(const bvalue[13]) { /* constants */ - /* K0 */ be_nested_str_weak(strip), - /* K1 */ be_nested_str_weak(bri), - /* K2 */ be_nested_str_weak(running), - /* K3 */ be_nested_str_weak(pixel_count), - /* K4 */ be_nested_str_weak(animators), - /* K5 */ be_nested_str_weak(painters), - /* K6 */ be_nested_str_weak(clear), - /* K7 */ be_nested_str_weak(frame), - /* K8 */ be_nested_str_weak(Leds_frame), + /* K0 */ be_nested_str_weak(animate), + /* K1 */ be_nested_str_weak(strip), + /* K2 */ be_nested_str_weak(bri), + /* K3 */ be_nested_str_weak(running), + /* K4 */ be_nested_str_weak(pixel_count), + /* K5 */ be_nested_str_weak(animators), + /* K6 */ be_nested_str_weak(painters), + /* K7 */ be_nested_str_weak(clear), + /* K8 */ be_nested_str_weak(frame), /* K9 */ be_nested_str_weak(layer), /* K10 */ be_nested_str_weak(fast_loop_cb), /* K11 */ be_nested_str_weak(back_color), @@ -379,39 +379,40 @@ be_local_closure(Leds_animator_init, /* name */ }), be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[32]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x4C0C0000, // 0001 LDNIL R3 - 0x1C0C0403, // 0002 EQ R3 R2 R3 - 0x780E0000, // 0003 JMPF R3 #0005 - 0x540A0031, // 0004 LDINT R2 50 - 0x90020202, // 0005 SETMBR R0 K1 R2 - 0x500C0000, // 0006 LDBOOL R3 0 0 - 0x90020403, // 0007 SETMBR R0 K2 R3 - 0x8C0C0303, // 0008 GETMET R3 R1 K3 - 0x7C0C0200, // 0009 CALL R3 1 - 0x90020603, // 000A SETMBR R0 K3 R3 - 0x600C0012, // 000B GETGBL R3 G18 - 0x7C0C0000, // 000C CALL R3 0 - 0x90020803, // 000D SETMBR R0 K4 R3 - 0x600C0012, // 000E GETGBL R3 G18 - 0x7C0C0000, // 000F CALL R3 0 - 0x90020A03, // 0010 SETMBR R0 K5 R3 - 0x8C0C0106, // 0011 GETMET R3 R0 K6 - 0x7C0C0200, // 0012 CALL R3 1 - 0xB80E1000, // 0013 GETNGBL R3 K8 - 0x88100103, // 0014 GETMBR R4 R0 K3 - 0x7C0C0200, // 0015 CALL R3 1 - 0x90020E03, // 0016 SETMBR R0 K7 R3 - 0xB80E1000, // 0017 GETNGBL R3 K8 - 0x88100103, // 0018 GETMBR R4 R0 K3 - 0x7C0C0200, // 0019 CALL R3 1 - 0x90021203, // 001A SETMBR R0 K9 R3 - 0x840C0000, // 001B CLOSURE R3 P0 - 0x90021403, // 001C SETMBR R0 K10 R3 - 0x9002170C, // 001D SETMBR R0 K11 K12 - 0xA0000000, // 001E CLOSE R0 - 0x80000000, // 001F RET 0 + ( &(const binstruction[33]) { /* code */ + 0xA40E0000, // 0000 IMPORT R3 K0 + 0x90020201, // 0001 SETMBR R0 K1 R1 + 0x4C100000, // 0002 LDNIL R4 + 0x1C100404, // 0003 EQ R4 R2 R4 + 0x78120000, // 0004 JMPF R4 #0006 + 0x540A0031, // 0005 LDINT R2 50 + 0x90020402, // 0006 SETMBR R0 K2 R2 + 0x50100000, // 0007 LDBOOL R4 0 0 + 0x90020604, // 0008 SETMBR R0 K3 R4 + 0x8C100304, // 0009 GETMET R4 R1 K4 + 0x7C100200, // 000A CALL R4 1 + 0x90020804, // 000B SETMBR R0 K4 R4 + 0x60100012, // 000C GETGBL R4 G18 + 0x7C100000, // 000D CALL R4 0 + 0x90020A04, // 000E SETMBR R0 K5 R4 + 0x60100012, // 000F GETGBL R4 G18 + 0x7C100000, // 0010 CALL R4 0 + 0x90020C04, // 0011 SETMBR R0 K6 R4 + 0x8C100107, // 0012 GETMET R4 R0 K7 + 0x7C100200, // 0013 CALL R4 1 + 0x8C100708, // 0014 GETMET R4 R3 K8 + 0x88180104, // 0015 GETMBR R6 R0 K4 + 0x7C100400, // 0016 CALL R4 2 + 0x90021004, // 0017 SETMBR R0 K8 R4 + 0x8C100708, // 0018 GETMET R4 R3 K8 + 0x88180104, // 0019 GETMBR R6 R0 K4 + 0x7C100400, // 001A CALL R4 2 + 0x90021204, // 001B SETMBR R0 K9 R4 + 0x84100000, // 001C CLOSURE R4 P0 + 0x90021404, // 001D SETMBR R0 K10 R4 + 0x9002170C, // 001E SETMBR R0 K11 K12 + 0xA0000000, // 001F CLOSE R0 + 0x80000000, // 0020 RET 0 }) ) ); @@ -421,7 +422,7 @@ be_local_closure(Leds_animator_init, /* name */ /******************************************************************** ** Solidified function: add_painter ********************************************************************/ -be_local_closure(Leds_animator_add_painter, /* name */ +be_local_closure(Animate_core_add_painter, /* name */ be_nested_proto( 5, /* nstack */ 2, /* argc */ @@ -452,7 +453,7 @@ be_local_closure(Leds_animator_add_painter, /* name */ /******************************************************************** ** Solidified function: fast_loop ********************************************************************/ -be_local_closure(Leds_animator_fast_loop, /* name */ +be_local_closure(Animate_core_fast_loop, /* name */ be_nested_proto( 12, /* nstack */ 1, /* argc */ @@ -585,7 +586,7 @@ be_local_closure(Leds_animator_fast_loop, /* name */ /******************************************************************** ** Solidified function: start ********************************************************************/ -be_local_closure(Leds_animator_start, /* name */ +be_local_closure(Animate_core_start, /* name */ be_nested_proto( 6, /* nstack */ 1, /* argc */ @@ -636,49 +637,49 @@ be_local_closure(Leds_animator_start, /* name */ /******************************************************************** -** Solidified class: Leds_animator +** Solidified class: Animate_core ********************************************************************/ -be_local_class(Leds_animator, +be_local_class(Animate_core, 13, NULL, be_nested_map(28, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_weak(bri, 23), be_const_var(2) }, - { be_const_key_weak(remove, -1), be_const_closure(Leds_animator_remove_closure) }, - { be_const_key_weak(start, 21), be_const_closure(Leds_animator_start_closure) }, - { be_const_key_weak(fast_loop, -1), be_const_closure(Leds_animator_fast_loop_closure) }, - { be_const_key_weak(add_animator, -1), be_const_closure(Leds_animator_add_animator_closure) }, + { be_const_key_weak(remove, -1), be_const_closure(Animate_core_remove_closure) }, + { be_const_key_weak(start, 21), be_const_closure(Animate_core_start_closure) }, + { be_const_key_weak(fast_loop, -1), be_const_closure(Animate_core_fast_loop_closure) }, + { be_const_key_weak(add_animator, -1), be_const_closure(Animate_core_add_animator_closure) }, { be_const_key_weak(FAST_LOOP_MIN, 8), be_const_int(20) }, - { be_const_key_weak(animate, -1), be_const_closure(Leds_animator_animate_closure) }, + { be_const_key_weak(animate, -1), be_const_closure(Animate_core_animate_closure) }, { be_const_key_weak(pixel_count, -1), be_const_var(1) }, { be_const_key_weak(animators, -1), be_const_var(4) }, { be_const_key_weak(back_color, 11), be_const_var(12) }, { be_const_key_weak(fast_loop_cb, 12), be_const_var(6) }, { be_const_key_weak(frame, -1), be_const_var(10) }, { be_const_key_weak(animate_object, -1), be_const_var(8) }, - { be_const_key_weak(stop, -1), be_const_closure(Leds_animator_stop_closure) }, - { be_const_key_weak(init, -1), be_const_closure(Leds_animator_init_closure) }, - { be_const_key_weak(set_cb, 13), be_const_closure(Leds_animator_set_cb_closure) }, + { be_const_key_weak(stop, -1), be_const_closure(Animate_core_stop_closure) }, + { be_const_key_weak(init, -1), be_const_closure(Animate_core_init_closure) }, + { be_const_key_weak(set_cb, 13), be_const_closure(Animate_core_set_cb_closure) }, { be_const_key_weak(running, -1), be_const_var(3) }, { be_const_key_weak(strip, 15), be_const_var(0) }, { be_const_key_weak(fast_loop_next, -1), be_const_var(7) }, - { be_const_key_weak(set_back_color, 14), be_const_closure(Leds_animator_set_back_color_closure) }, - { be_const_key_weak(add_painter, -1), be_const_closure(Leds_animator_add_painter_closure) }, - { be_const_key_weak(set_bri, 24), be_const_closure(Leds_animator_set_bri_closure) }, + { be_const_key_weak(set_back_color, 14), be_const_closure(Animate_core_set_back_color_closure) }, + { be_const_key_weak(add_painter, -1), be_const_closure(Animate_core_add_painter_closure) }, + { be_const_key_weak(set_bri, 24), be_const_closure(Animate_core_set_bri_closure) }, { be_const_key_weak(layer, 9), be_const_var(11) }, { be_const_key_weak(animate_method, 6), be_const_var(9) }, - { be_const_key_weak(get_bri, -1), be_const_closure(Leds_animator_get_bri_closure) }, + { be_const_key_weak(get_bri, -1), be_const_closure(Animate_core_get_bri_closure) }, { be_const_key_weak(painters, -1), be_const_var(5) }, - { be_const_key_weak(clear, 3), be_const_closure(Leds_animator_clear_closure) }, - { be_const_key_weak(add_background_animator, 2), be_const_closure(Leds_animator_add_background_animator_closure) }, + { be_const_key_weak(clear, 3), be_const_closure(Animate_core_clear_closure) }, + { be_const_key_weak(add_background_animator, 2), be_const_closure(Animate_core_add_background_animator_closure) }, })), - be_str_weak(Leds_animator) + be_str_weak(Animate_core) ); /*******************************************************************/ -void be_load_Leds_animator_class(bvm *vm) { - be_pushntvclass(vm, &be_class_Leds_animator); - be_setglobal(vm, "Leds_animator"); +void be_load_Animate_core_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Animate_core); + be_setglobal(vm, "Animate_core"); be_pop(vm, 1); } /********************************************************************/ diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_leds_1_animate_effects.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_animate_effects.h similarity index 89% rename from lib/libesp32/berry_tasmota/src/solidify/solidified_leds_1_animate_effects.h rename to lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_animate_effects.h index 1c2891e5b..bb8b9dee3 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_leds_1_animate_effects.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_animate_effects.h @@ -1,15 +1,42 @@ -/* Solidification of leds_1_animate_effects.h */ +/* Solidification of animate_1_animate_effects.h */ /********************************************************************\ * Generated code, don't edit * \********************************************************************/ #include "be_constobj.h" -extern const bclass be_class_Leds_pulse; +extern const bclass be_class_Animate_pulse; + +/******************************************************************** +** Solidified function: set_pulse_size +********************************************************************/ +be_local_closure(Animate_pulse_set_pulse_size, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(pulse_size), + }), + be_str_weak(set_pulse_size), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + /******************************************************************** ** Solidified function: set_slew_size ********************************************************************/ -be_local_closure(Leds_pulse_set_slew_size, /* name */ +be_local_closure(Animate_pulse_set_slew_size, /* name */ be_nested_proto( 2, /* nstack */ 2, /* argc */ @@ -36,7 +63,7 @@ be_local_closure(Leds_pulse_set_slew_size, /* name */ /******************************************************************** ** Solidified function: set_back_color ********************************************************************/ -be_local_closure(Leds_pulse_set_back_color, /* name */ +be_local_closure(Animate_pulse_set_back_color, /* name */ be_nested_proto( 2, /* nstack */ 2, /* argc */ @@ -61,9 +88,9 @@ be_local_closure(Leds_pulse_set_back_color, /* name */ /******************************************************************** -** Solidified function: set_index +** Solidified function: set_pos ********************************************************************/ -be_local_closure(Leds_pulse_set_index, /* name */ +be_local_closure(Animate_pulse_set_pos, /* name */ be_nested_proto( 2, /* nstack */ 2, /* argc */ @@ -74,9 +101,9 @@ be_local_closure(Leds_pulse_set_index, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(index), + /* K0 */ be_nested_str_weak(pos), }), - be_str_weak(set_index), + be_str_weak(set_pos), &be_const_str_solidified, ( &(const binstruction[ 2]) { /* code */ 0x90020001, // 0000 SETMBR R0 K0 R1 @@ -88,9 +115,9 @@ be_local_closure(Leds_pulse_set_index, /* name */ /******************************************************************** -** Solidified function: set_pulse_size +** Solidified function: set_color ********************************************************************/ -be_local_closure(Leds_pulse_set_pulse_size, /* name */ +be_local_closure(Animate_pulse_set_color, /* name */ be_nested_proto( 2, /* nstack */ 2, /* argc */ @@ -101,9 +128,9 @@ be_local_closure(Leds_pulse_set_pulse_size, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(pulse_size), + /* K0 */ be_nested_str_weak(color), }), - be_str_weak(set_pulse_size), + be_str_weak(set_color), &be_const_str_solidified, ( &(const binstruction[ 2]) { /* code */ 0x90020001, // 0000 SETMBR R0 K0 R1 @@ -117,7 +144,7 @@ be_local_closure(Leds_pulse_set_pulse_size, /* name */ /******************************************************************** ** Solidified function: init ********************************************************************/ -be_local_closure(Leds_pulse_init, /* name */ +be_local_closure(Animate_pulse_init, /* name */ be_nested_proto( 5, /* nstack */ 4, /* argc */ @@ -169,37 +196,10 @@ be_local_closure(Leds_pulse_init, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: set_color -********************************************************************/ -be_local_closure(Leds_pulse_set_color, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(color), - }), - be_str_weak(set_color), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: paint ********************************************************************/ -be_local_closure(Leds_pulse_paint, /* name */ +be_local_closure(Animate_pulse_paint, /* name */ be_nested_proto( 22, /* nstack */ 2, /* argc */ @@ -213,7 +213,7 @@ be_local_closure(Leds_pulse_paint, /* name */ /* K0 */ be_nested_str_weak(back_color), /* K1 */ be_const_int(-16777216), /* K2 */ be_nested_str_weak(fill_pixels), - /* K3 */ be_nested_str_weak(index), + /* K3 */ be_nested_str_weak(pos), /* K4 */ be_nested_str_weak(slew_size), /* K5 */ be_nested_str_weak(pulse_size), /* K6 */ be_nested_str_weak(color), @@ -325,33 +325,33 @@ be_local_closure(Leds_pulse_paint, /* name */ /******************************************************************** -** Solidified class: Leds_pulse +** Solidified class: Animate_pulse ********************************************************************/ -be_local_class(Leds_pulse, +be_local_class(Animate_pulse, 5, NULL, be_nested_map(12, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(paint, 9), be_const_closure(Leds_pulse_paint_closure) }, - { be_const_key_weak(set_slew_size, -1), be_const_closure(Leds_pulse_set_slew_size_closure) }, + { be_const_key_weak(paint, -1), be_const_closure(Animate_pulse_paint_closure) }, + { be_const_key_weak(set_slew_size, -1), be_const_closure(Animate_pulse_set_slew_size_closure) }, { be_const_key_weak(pulse_size, -1), be_const_var(4) }, - { be_const_key_weak(set_back_color, 6), be_const_closure(Leds_pulse_set_back_color_closure) }, - { be_const_key_weak(set_index, 7), be_const_closure(Leds_pulse_set_index_closure) }, - { be_const_key_weak(back_color, -1), be_const_var(1) }, - { be_const_key_weak(set_color, 8), be_const_closure(Leds_pulse_set_color_closure) }, + { be_const_key_weak(set_back_color, 8), be_const_closure(Animate_pulse_set_back_color_closure) }, { be_const_key_weak(color, -1), be_const_var(0) }, - { be_const_key_weak(init, -1), be_const_closure(Leds_pulse_init_closure) }, - { be_const_key_weak(set_pulse_size, -1), be_const_closure(Leds_pulse_set_pulse_size_closure) }, + { be_const_key_weak(back_color, -1), be_const_var(1) }, + { be_const_key_weak(set_pos, -1), be_const_closure(Animate_pulse_set_pos_closure) }, + { be_const_key_weak(set_color, -1), be_const_closure(Animate_pulse_set_color_closure) }, + { be_const_key_weak(init, 7), be_const_closure(Animate_pulse_init_closure) }, + { be_const_key_weak(pos, -1), be_const_var(2) }, { be_const_key_weak(slew_size, 5), be_const_var(3) }, - { be_const_key_weak(index, 0), be_const_var(2) }, + { be_const_key_weak(set_pulse_size, 0), be_const_closure(Animate_pulse_set_pulse_size_closure) }, })), - be_str_weak(Leds_pulse) + be_str_weak(Animate_pulse) ); /*******************************************************************/ -void be_load_Leds_pulse_class(bvm *vm) { - be_pushntvclass(vm, &be_class_Leds_pulse); - be_setglobal(vm, "Leds_pulse"); +void be_load_Animate_pulse_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Animate_pulse); + be_setglobal(vm, "Animate_pulse"); be_pop(vm, 1); } /********************************************************************/ diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_module.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h similarity index 60% rename from lib/libesp32/berry_tasmota/src/solidify/solidified_animate_module.h rename to lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h index 5d0f45c10..a337b5f82 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_module.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h @@ -1,17 +1,17 @@ -/* Solidification of animate_module.h */ +/* Solidification of animate_9_module.h */ /********************************************************************\ * Generated code, don't edit * \********************************************************************/ #include "be_constobj.h" -extern const bclass be_class_Animate_palette; +extern const bclass be_class_Animate_animator; /******************************************************************** -** Solidified function: to_css_gradient +** Solidified function: is_running ********************************************************************/ -be_local_closure(Animate_palette_to_css_gradient, /* name */ +be_local_closure(Animate_animator_is_running, /* name */ be_nested_proto( - 15, /* nstack */ + 3, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -19,62 +19,16 @@ be_local_closure(Animate_palette_to_css_gradient, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(parse_palette), - /* K1 */ be_const_int(0), - /* K2 */ be_nested_str_weak(background_X3Alinear_X2Dgradient_X28to_X20right), - /* K3 */ be_nested_str_weak(palette), - /* K4 */ be_nested_str_weak(get), - /* K5 */ be_nested_str_weak(_X2C_X23_X2502X_X2502X_X2502X_X20_X25_X2E1f_X25_X25), - /* K6 */ be_const_real_hex(0x41200000), - /* K7 */ be_const_int(1), - /* K8 */ be_nested_str_weak(_X29_X3B), + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(running), }), - be_str_weak(to_css_gradient), + be_str_weak(is_running), &be_const_str_solidified, - ( &(const binstruction[42]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x580C0001, // 0001 LDCONST R3 K1 - 0x541203E7, // 0002 LDINT R4 1000 - 0x7C040600, // 0003 CALL R1 3 - 0x58080002, // 0004 LDCONST R2 K2 - 0x580C0001, // 0005 LDCONST R3 K1 - 0x6010000C, // 0006 GETGBL R4 G12 - 0x5C140200, // 0007 MOVE R5 R1 - 0x7C100200, // 0008 CALL R4 1 - 0x14100604, // 0009 LT R4 R3 R4 - 0x7812001C, // 000A JMPF R4 #0028 - 0x94100203, // 000B GETIDX R4 R1 R3 - 0x88140103, // 000C GETMBR R5 R0 K3 - 0x8C140B04, // 000D GETMET R5 R5 K4 - 0x541E0003, // 000E LDINT R7 4 - 0x081C0607, // 000F MUL R7 R3 R7 - 0x54220003, // 0010 LDINT R8 4 - 0x7C140600, // 0011 CALL R5 3 - 0x541A0007, // 0012 LDINT R6 8 - 0x3C180A06, // 0013 SHR R6 R5 R6 - 0x541E00FE, // 0014 LDINT R7 255 - 0x2C180C07, // 0015 AND R6 R6 R7 - 0x541E000F, // 0016 LDINT R7 16 - 0x3C1C0A07, // 0017 SHR R7 R5 R7 - 0x542200FE, // 0018 LDINT R8 255 - 0x2C1C0E08, // 0019 AND R7 R7 R8 - 0x54220017, // 001A LDINT R8 24 - 0x3C200A08, // 001B SHR R8 R5 R8 - 0x542600FE, // 001C LDINT R9 255 - 0x2C201009, // 001D AND R8 R8 R9 - 0x60240018, // 001E GETGBL R9 G24 - 0x58280005, // 001F LDCONST R10 K5 - 0x5C2C0C00, // 0020 MOVE R11 R6 - 0x5C300E00, // 0021 MOVE R12 R7 - 0x5C341000, // 0022 MOVE R13 R8 - 0x0C380906, // 0023 DIV R14 R4 K6 - 0x7C240A00, // 0024 CALL R9 5 - 0x00080409, // 0025 ADD R2 R2 R9 - 0x000C0707, // 0026 ADD R3 R3 K7 - 0x7001FFDD, // 0027 JMP #0006 - 0x00080508, // 0028 ADD R2 R2 K8 - 0x80040400, // 0029 RET 1 R2 + ( &(const binstruction[ 4]) { /* code */ + 0x60040017, // 0000 GETGBL R1 G23 + 0x88080100, // 0001 GETMBR R2 R0 K0 + 0x7C040200, // 0002 CALL R1 1 + 0x80040200, // 0003 RET 1 R1 }) ) ); @@ -82,102 +36,23 @@ be_local_closure(Animate_palette_to_css_gradient, /* name */ /******************************************************************** -** Solidified function: parse_palette +** Solidified function: beat ********************************************************************/ -be_local_closure(Animate_palette_parse_palette, /* name */ +be_local_closure(Animate_animator_beat, /* name */ be_nested_proto( - 15, /* nstack */ - 3, /* argc */ + 1, /* nstack */ + 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str_weak(slots), - /* K1 */ be_nested_str_weak(resize), - /* K2 */ be_nested_str_weak(palette), - /* K3 */ be_nested_str_weak(get), - /* K4 */ be_const_int(0), - /* K5 */ be_const_int(1), - /* K6 */ be_nested_str_weak(tasmota), - /* K7 */ be_nested_str_weak(scale_int), - }), - be_str_weak(parse_palette), + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(beat), &be_const_str_solidified, - ( &(const binstruction[71]) { /* code */ - 0x600C0012, // 0000 GETGBL R3 G18 - 0x7C0C0000, // 0001 CALL R3 0 - 0x88100100, // 0002 GETMBR R4 R0 K0 - 0x8C140701, // 0003 GETMET R5 R3 K1 - 0x5C1C0800, // 0004 MOVE R7 R4 - 0x7C140400, // 0005 CALL R5 2 - 0x88140102, // 0006 GETMBR R5 R0 K2 - 0x8C140B03, // 0007 GETMET R5 R5 K3 - 0x581C0004, // 0008 LDCONST R7 K4 - 0x58200005, // 0009 LDCONST R8 K5 - 0x7C140600, // 000A CALL R5 3 - 0x20140B04, // 000B NE R5 R5 K4 - 0x78160024, // 000C JMPF R5 #0032 - 0x58140004, // 000D LDCONST R5 K4 - 0x58180004, // 000E LDCONST R6 K4 - 0x041C0905, // 000F SUB R7 R4 K5 - 0x141C0C07, // 0010 LT R7 R6 R7 - 0x781E0008, // 0011 JMPF R7 #001B - 0x881C0102, // 0012 GETMBR R7 R0 K2 - 0x8C1C0F03, // 0013 GETMET R7 R7 K3 - 0x54260003, // 0014 LDINT R9 4 - 0x08240C09, // 0015 MUL R9 R6 R9 - 0x58280005, // 0016 LDCONST R10 K5 - 0x7C1C0600, // 0017 CALL R7 3 - 0x00140A07, // 0018 ADD R5 R5 R7 - 0x00180D05, // 0019 ADD R6 R6 K5 - 0x7001FFF3, // 001A JMP #000F - 0x581C0004, // 001B LDCONST R7 K4 - 0x58180004, // 001C LDCONST R6 K4 - 0x14200C04, // 001D LT R8 R6 R4 - 0x78220011, // 001E JMPF R8 #0031 - 0xB8220C00, // 001F GETNGBL R8 K6 - 0x8C201107, // 0020 GETMET R8 R8 K7 - 0x5C280E00, // 0021 MOVE R10 R7 - 0x582C0004, // 0022 LDCONST R11 K4 - 0x5C300A00, // 0023 MOVE R12 R5 - 0x5C340200, // 0024 MOVE R13 R1 - 0x5C380400, // 0025 MOVE R14 R2 - 0x7C200C00, // 0026 CALL R8 6 - 0x980C0C08, // 0027 SETIDX R3 R6 R8 - 0x88200102, // 0028 GETMBR R8 R0 K2 - 0x8C201103, // 0029 GETMET R8 R8 K3 - 0x542A0003, // 002A LDINT R10 4 - 0x08280C0A, // 002B MUL R10 R6 R10 - 0x582C0005, // 002C LDCONST R11 K5 - 0x7C200600, // 002D CALL R8 3 - 0x001C0E08, // 002E ADD R7 R7 R8 - 0x00180D05, // 002F ADD R6 R6 K5 - 0x7001FFEB, // 0030 JMP #001D - 0x70020013, // 0031 JMP #0046 - 0x58140004, // 0032 LDCONST R5 K4 - 0x14180A04, // 0033 LT R6 R5 R4 - 0x781A0010, // 0034 JMPF R6 #0046 - 0x88180102, // 0035 GETMBR R6 R0 K2 - 0x8C180D03, // 0036 GETMET R6 R6 K3 - 0x54220003, // 0037 LDINT R8 4 - 0x08200A08, // 0038 MUL R8 R5 R8 - 0x58240005, // 0039 LDCONST R9 K5 - 0x7C180600, // 003A CALL R6 3 - 0xB81E0C00, // 003B GETNGBL R7 K6 - 0x8C1C0F07, // 003C GETMET R7 R7 K7 - 0x5C240C00, // 003D MOVE R9 R6 - 0x58280004, // 003E LDCONST R10 K4 - 0x542E00FE, // 003F LDINT R11 255 - 0x5C300200, // 0040 MOVE R12 R1 - 0x5C340400, // 0041 MOVE R13 R2 - 0x7C1C0C00, // 0042 CALL R7 6 - 0x980C0A07, // 0043 SETIDX R3 R5 R7 - 0x00140B05, // 0044 ADD R5 R5 K5 - 0x7001FFEC, // 0045 JMP #0033 - 0x80040600, // 0046 RET 1 R3 + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 }) ) ); @@ -187,84 +62,24 @@ be_local_closure(Animate_palette_parse_palette, /* name */ /******************************************************************** ** Solidified function: init ********************************************************************/ -be_local_closure(Animate_palette_init, /* name */ +be_local_closure(Animate_animator_init, /* name */ be_nested_proto( - 7, /* nstack */ - 3, /* argc */ + 2, /* nstack */ + 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str_weak(running), - /* K1 */ be_nested_str_weak(palette), - /* K2 */ be_nested_str_weak(bri), - /* K3 */ be_nested_str_weak(slots), - /* K4 */ be_nested_str_weak(set_duration), - /* K5 */ be_nested_str_weak(color), - /* K6 */ be_nested_str_weak(light_state), - /* K7 */ be_nested_str_weak(RGB), + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(duration_ms), }), be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[26]) { /* code */ - 0x500C0000, // 0000 LDBOOL R3 0 0 - 0x90020003, // 0001 SETMBR R0 K0 R3 - 0x90020201, // 0002 SETMBR R0 K1 R1 - 0x540E0063, // 0003 LDINT R3 100 - 0x90020403, // 0004 SETMBR R0 K2 R3 - 0x600C000C, // 0005 GETGBL R3 G12 - 0x5C100200, // 0006 MOVE R4 R1 - 0x7C0C0200, // 0007 CALL R3 1 - 0x54120003, // 0008 LDINT R4 4 - 0x0C0C0604, // 0009 DIV R3 R3 R4 - 0x90020603, // 000A SETMBR R0 K3 R3 - 0x4C0C0000, // 000B LDNIL R3 - 0x200C0403, // 000C NE R3 R2 R3 - 0x780E0005, // 000D JMPF R3 #0014 - 0x8C0C0104, // 000E GETMET R3 R0 K4 - 0x60140009, // 000F GETGBL R5 G9 - 0x541A03E7, // 0010 LDINT R6 1000 - 0x08180406, // 0011 MUL R6 R2 R6 - 0x7C140200, // 0012 CALL R5 1 - 0x7C0C0400, // 0013 CALL R3 2 - 0xB80E0C00, // 0014 GETNGBL R3 K6 - 0xB8120C00, // 0015 GETNGBL R4 K6 - 0x88100907, // 0016 GETMBR R4 R4 K7 - 0x7C0C0200, // 0017 CALL R3 1 - 0x90020A03, // 0018 SETMBR R0 K5 R3 - 0x80000000, // 0019 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_cb -********************************************************************/ -be_local_closure(Animate_palette_set_cb, /* name */ - be_nested_proto( - 3, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(animate_obj), - /* K1 */ be_nested_str_weak(animate_mth), - }), - be_str_weak(set_cb), - &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ + ( &(const binstruction[ 2]) { /* code */ 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x80000000, // 0002 RET 0 + 0x80000000, // 0001 RET 0 }) ) ); @@ -274,7 +89,7 @@ be_local_closure(Animate_palette_set_cb, /* name */ /******************************************************************** ** Solidified function: stop ********************************************************************/ -be_local_closure(Animate_palette_stop, /* name */ +be_local_closure(Animate_animator_stop, /* name */ be_nested_proto( 2, /* nstack */ 1, /* argc */ @@ -302,6 +117,213 @@ be_local_closure(Animate_palette_stop, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: set_duration_ms +********************************************************************/ +be_local_closure(Animate_animator_set_duration_ms, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(duration_ms), + }), + be_str_weak(set_duration_ms), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_cb +********************************************************************/ +be_local_closure(Animate_animator_set_cb, /* name */ + be_nested_proto( + 3, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(obj), + /* K1 */ be_nested_str_weak(mth), + }), + be_str_weak(set_cb), + &be_const_str_solidified, + ( &(const binstruction[ 3]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start +********************************************************************/ +be_local_closure(Animate_animator_start, /* name */ + be_nested_proto( + 4, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(duration_ms), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(millis), + /* K3 */ be_nested_str_weak(origin), + /* K4 */ be_nested_str_weak(running), + }), + be_str_weak(start), + &be_const_str_solidified, + ( &(const binstruction[16]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x1C080403, // 0002 EQ R2 R2 R3 + 0x780A0000, // 0003 JMPF R2 #0005 + 0x80000400, // 0004 RET 0 + 0x4C080000, // 0005 LDNIL R2 + 0x1C080202, // 0006 EQ R2 R1 R2 + 0x780A0003, // 0007 JMPF R2 #000C + 0xB80A0200, // 0008 GETNGBL R2 K1 + 0x8C080502, // 0009 GETMET R2 R2 K2 + 0x7C080200, // 000A CALL R2 1 + 0x5C040400, // 000B MOVE R1 R2 + 0x90020601, // 000C SETMBR R0 K3 R1 + 0x50080200, // 000D LDBOOL R2 1 0 + 0x90020802, // 000E SETMBR R0 K4 R2 + 0x80000000, // 000F RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Animate_animator +********************************************************************/ +be_local_class(Animate_animator, + 5, + NULL, + be_nested_map(12, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(running, 4), be_const_var(0) }, + { be_const_key_weak(is_running, 2), be_const_closure(Animate_animator_is_running_closure) }, + { be_const_key_weak(beat, -1), be_const_closure(Animate_animator_beat_closure) }, + { be_const_key_weak(init, -1), be_const_closure(Animate_animator_init_closure) }, + { be_const_key_weak(mth, -1), be_const_var(4) }, + { be_const_key_weak(stop, -1), be_const_closure(Animate_animator_stop_closure) }, + { be_const_key_weak(duration_ms, -1), be_const_var(1) }, + { be_const_key_weak(origin, -1), be_const_var(2) }, + { be_const_key_weak(set_cb, -1), be_const_closure(Animate_animator_set_cb_closure) }, + { be_const_key_weak(set_duration_ms, 8), be_const_closure(Animate_animator_set_duration_ms_closure) }, + { be_const_key_weak(obj, -1), be_const_var(3) }, + { be_const_key_weak(start, -1), be_const_closure(Animate_animator_start_closure) }, + })), + be_str_weak(Animate_animator) +); +/*******************************************************************/ + +void be_load_Animate_animator_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Animate_animator); + be_setglobal(vm, "Animate_animator"); + be_pop(vm, 1); +} + +extern const bclass be_class_Animate_palette; + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_palette_init, /* name */ + be_nested_proto( + 6, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_str_weak(init), + /* K1 */ be_nested_str_weak(running), + /* K2 */ be_nested_str_weak(ptr), + /* K3 */ be_nested_str_weak(ptr_to_palette), + /* K4 */ be_nested_str_weak(palette), + /* K5 */ be_nested_str_weak(bri), + /* K6 */ be_nested_str_weak(slots), + /* K7 */ be_nested_str_weak(set_duration), + /* K8 */ be_nested_str_weak(color), + /* K9 */ be_nested_str_weak(light_state), + /* K10 */ be_nested_str_weak(RGB), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[38]) { /* code */ + 0x600C0003, // 0000 GETGBL R3 G3 + 0x5C100000, // 0001 MOVE R4 R0 + 0x7C0C0200, // 0002 CALL R3 1 + 0x8C0C0700, // 0003 GETMET R3 R3 K0 + 0x5C140400, // 0004 MOVE R5 R2 + 0x7C0C0400, // 0005 CALL R3 2 + 0x500C0000, // 0006 LDBOOL R3 0 0 + 0x90020203, // 0007 SETMBR R0 K1 R3 + 0x600C0004, // 0008 GETGBL R3 G4 + 0x5C100200, // 0009 MOVE R4 R1 + 0x7C0C0200, // 000A CALL R3 1 + 0x1C0C0702, // 000B EQ R3 R3 K2 + 0x780E0003, // 000C JMPF R3 #0011 + 0x8C0C0103, // 000D GETMET R3 R0 K3 + 0x5C140200, // 000E MOVE R5 R1 + 0x7C0C0400, // 000F CALL R3 2 + 0x5C040600, // 0010 MOVE R1 R3 + 0x90020801, // 0011 SETMBR R0 K4 R1 + 0x540E0063, // 0012 LDINT R3 100 + 0x90020A03, // 0013 SETMBR R0 K5 R3 + 0x600C000C, // 0014 GETGBL R3 G12 + 0x5C100200, // 0015 MOVE R4 R1 + 0x7C0C0200, // 0016 CALL R3 1 + 0x54120003, // 0017 LDINT R4 4 + 0x0C0C0604, // 0018 DIV R3 R3 R4 + 0x90020C03, // 0019 SETMBR R0 K6 R3 + 0x4C0C0000, // 001A LDNIL R3 + 0x200C0403, // 001B NE R3 R2 R3 + 0x780E0002, // 001C JMPF R3 #0020 + 0x8C0C0107, // 001D GETMET R3 R0 K7 + 0x5C140400, // 001E MOVE R5 R2 + 0x7C0C0400, // 001F CALL R3 2 + 0xB80E1200, // 0020 GETNGBL R3 K9 + 0xB8121200, // 0021 GETNGBL R4 K9 + 0x8810090A, // 0022 GETMBR R4 R4 K10 + 0x7C0C0200, // 0023 CALL R3 1 + 0x90021003, // 0024 SETMBR R0 K8 R3 + 0x80000000, // 0025 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: animate ********************************************************************/ @@ -335,8 +357,8 @@ be_local_closure(Animate_palette_animate, /* name */ /* K16 */ be_nested_str_weak(r), /* K17 */ be_nested_str_weak(g), /* K18 */ be_nested_str_weak(b), - /* K19 */ be_nested_str_weak(animate_obj), - /* K20 */ be_nested_str_weak(animate_mth), + /* K19 */ be_nested_str_weak(obj), + /* K20 */ be_nested_str_weak(mth), }), be_str_weak(animate), &be_const_str_solidified, @@ -540,6 +562,79 @@ be_local_closure(Animate_palette_animate, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: ptr_to_palette +********************************************************************/ +be_local_closure(Animate_palette_ptr_to_palette, /* name */ + be_nested_proto( + 8, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_const_class(be_class_Animate_palette), + /* K1 */ be_nested_str_weak(ptr), + /* K2 */ be_const_int(1), + /* K3 */ be_const_int(0), + }), + be_str_weak(ptr_to_palette), + &be_const_str_solidified, + ( &(const binstruction[45]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x60080004, // 0001 GETGBL R2 G4 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C080200, // 0003 CALL R2 1 + 0x1C080501, // 0004 EQ R2 R2 K1 + 0x780A0025, // 0005 JMPF R2 #002C + 0x60080015, // 0006 GETGBL R2 G21 + 0x5C0C0000, // 0007 MOVE R3 R0 + 0x541207CF, // 0008 LDINT R4 2000 + 0x7C080400, // 0009 CALL R2 2 + 0x580C0002, // 000A LDCONST R3 K2 + 0x94100503, // 000B GETIDX R4 R2 K3 + 0x20100903, // 000C NE R4 R4 K3 + 0x7812000A, // 000D JMPF R4 #0019 + 0x50100200, // 000E LDBOOL R4 1 0 + 0x78120007, // 000F JMPF R4 #0018 + 0x54120003, // 0010 LDINT R4 4 + 0x08100604, // 0011 MUL R4 R3 R4 + 0x94100404, // 0012 GETIDX R4 R2 R4 + 0x1C100903, // 0013 EQ R4 R4 K3 + 0x78120000, // 0014 JMPF R4 #0016 + 0x70020001, // 0015 JMP #0018 + 0x000C0702, // 0016 ADD R3 R3 K2 + 0x7001FFF5, // 0017 JMP #000E + 0x7002000A, // 0018 JMP #0024 + 0x50100200, // 0019 LDBOOL R4 1 0 + 0x78120008, // 001A JMPF R4 #0024 + 0x54120003, // 001B LDINT R4 4 + 0x08100604, // 001C MUL R4 R3 R4 + 0x94100404, // 001D GETIDX R4 R2 R4 + 0x541600FE, // 001E LDINT R5 255 + 0x1C100805, // 001F EQ R4 R4 R5 + 0x78120000, // 0020 JMPF R4 #0022 + 0x70020001, // 0021 JMP #0024 + 0x000C0702, // 0022 ADD R3 R3 K2 + 0x7001FFF4, // 0023 JMP #0019 + 0x00100702, // 0024 ADD R4 R3 K2 + 0x54160003, // 0025 LDINT R5 4 + 0x08100805, // 0026 MUL R4 R4 R5 + 0x60140015, // 0027 GETGBL R5 G21 + 0x5C180000, // 0028 MOVE R6 R0 + 0x5C1C0800, // 0029 MOVE R7 R4 + 0x7C140400, // 002A CALL R5 2 + 0x80040A00, // 002B RET 1 R5 + 0x80000000, // 002C RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: set_range ********************************************************************/ @@ -581,6 +676,109 @@ be_local_closure(Animate_palette_set_range, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: parse_palette +********************************************************************/ +be_local_closure(Animate_palette_parse_palette, /* name */ + be_nested_proto( + 15, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_str_weak(slots), + /* K1 */ be_nested_str_weak(resize), + /* K2 */ be_nested_str_weak(palette), + /* K3 */ be_nested_str_weak(get), + /* K4 */ be_const_int(0), + /* K5 */ be_const_int(1), + /* K6 */ be_nested_str_weak(tasmota), + /* K7 */ be_nested_str_weak(scale_int), + }), + be_str_weak(parse_palette), + &be_const_str_solidified, + ( &(const binstruction[71]) { /* code */ + 0x600C0012, // 0000 GETGBL R3 G18 + 0x7C0C0000, // 0001 CALL R3 0 + 0x88100100, // 0002 GETMBR R4 R0 K0 + 0x8C140701, // 0003 GETMET R5 R3 K1 + 0x5C1C0800, // 0004 MOVE R7 R4 + 0x7C140400, // 0005 CALL R5 2 + 0x88140102, // 0006 GETMBR R5 R0 K2 + 0x8C140B03, // 0007 GETMET R5 R5 K3 + 0x581C0004, // 0008 LDCONST R7 K4 + 0x58200005, // 0009 LDCONST R8 K5 + 0x7C140600, // 000A CALL R5 3 + 0x20140B04, // 000B NE R5 R5 K4 + 0x78160024, // 000C JMPF R5 #0032 + 0x58140004, // 000D LDCONST R5 K4 + 0x58180004, // 000E LDCONST R6 K4 + 0x041C0905, // 000F SUB R7 R4 K5 + 0x141C0C07, // 0010 LT R7 R6 R7 + 0x781E0008, // 0011 JMPF R7 #001B + 0x881C0102, // 0012 GETMBR R7 R0 K2 + 0x8C1C0F03, // 0013 GETMET R7 R7 K3 + 0x54260003, // 0014 LDINT R9 4 + 0x08240C09, // 0015 MUL R9 R6 R9 + 0x58280005, // 0016 LDCONST R10 K5 + 0x7C1C0600, // 0017 CALL R7 3 + 0x00140A07, // 0018 ADD R5 R5 R7 + 0x00180D05, // 0019 ADD R6 R6 K5 + 0x7001FFF3, // 001A JMP #000F + 0x581C0004, // 001B LDCONST R7 K4 + 0x58180004, // 001C LDCONST R6 K4 + 0x14200C04, // 001D LT R8 R6 R4 + 0x78220011, // 001E JMPF R8 #0031 + 0xB8220C00, // 001F GETNGBL R8 K6 + 0x8C201107, // 0020 GETMET R8 R8 K7 + 0x5C280E00, // 0021 MOVE R10 R7 + 0x582C0004, // 0022 LDCONST R11 K4 + 0x5C300A00, // 0023 MOVE R12 R5 + 0x5C340200, // 0024 MOVE R13 R1 + 0x5C380400, // 0025 MOVE R14 R2 + 0x7C200C00, // 0026 CALL R8 6 + 0x980C0C08, // 0027 SETIDX R3 R6 R8 + 0x88200102, // 0028 GETMBR R8 R0 K2 + 0x8C201103, // 0029 GETMET R8 R8 K3 + 0x542A0003, // 002A LDINT R10 4 + 0x08280C0A, // 002B MUL R10 R6 R10 + 0x582C0005, // 002C LDCONST R11 K5 + 0x7C200600, // 002D CALL R8 3 + 0x001C0E08, // 002E ADD R7 R7 R8 + 0x00180D05, // 002F ADD R6 R6 K5 + 0x7001FFEB, // 0030 JMP #001D + 0x70020013, // 0031 JMP #0046 + 0x58140004, // 0032 LDCONST R5 K4 + 0x14180A04, // 0033 LT R6 R5 R4 + 0x781A0010, // 0034 JMPF R6 #0046 + 0x88180102, // 0035 GETMBR R6 R0 K2 + 0x8C180D03, // 0036 GETMET R6 R6 K3 + 0x54220003, // 0037 LDINT R8 4 + 0x08200A08, // 0038 MUL R8 R5 R8 + 0x58240005, // 0039 LDCONST R9 K5 + 0x7C180600, // 003A CALL R6 3 + 0xB81E0C00, // 003B GETNGBL R7 K6 + 0x8C1C0F07, // 003C GETMET R7 R7 K7 + 0x5C240C00, // 003D MOVE R9 R6 + 0x58280004, // 003E LDCONST R10 K4 + 0x542E00FE, // 003F LDINT R11 255 + 0x5C300200, // 0040 MOVE R12 R1 + 0x5C340400, // 0041 MOVE R13 R2 + 0x7C1C0C00, // 0042 CALL R7 6 + 0x980C0A07, // 0043 SETIDX R3 R5 R7 + 0x00140B05, // 0044 ADD R5 R5 K5 + 0x7001FFEC, // 0045 JMP #0033 + 0x80040600, // 0046 RET 1 R3 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: set_bri ********************************************************************/ @@ -611,35 +809,6 @@ be_local_closure(Animate_palette_set_bri, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: is_running -********************************************************************/ -be_local_closure(Animate_palette_is_running, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(running), - }), - be_str_weak(is_running), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x60040017, // 0000 GETGBL R1 G23 - 0x88080100, // 0001 GETMBR R2 R0 K0 - 0x7C040200, // 0002 CALL R1 1 - 0x80040200, // 0003 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: set_duration ********************************************************************/ @@ -710,8 +879,8 @@ be_local_closure(Animate_palette_set_value, /* name */ /* K8 */ be_const_int(1), /* K9 */ be_nested_str_weak(palette), /* K10 */ be_nested_str_weak(get), - /* K11 */ be_nested_str_weak(animate_obj), - /* K12 */ be_nested_str_weak(animate_mth), + /* K11 */ be_nested_str_weak(obj), + /* K12 */ be_nested_str_weak(mth), }), be_str_weak(set_value), &be_const_str_solidified, @@ -819,11 +988,129 @@ be_local_closure(Animate_palette_set_value, /* name */ /******************************************************************** -** Solidified function: start +** Solidified function: to_css_gradient ********************************************************************/ -be_local_closure(Animate_palette_start, /* name */ +be_local_closure(Animate_palette_to_css_gradient, /* name */ be_nested_proto( - 4, /* nstack */ + 17, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[10]) { /* constants */ + /* K0 */ be_const_class(be_class_Animate_palette), + /* K1 */ be_nested_str_weak(parse_palette), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(background_X3Alinear_X2Dgradient_X28to_X20right), + /* K4 */ be_nested_str_weak(palette), + /* K5 */ be_nested_str_weak(get), + /* K6 */ be_nested_str_weak(_X2C_X23_X2502X_X2502X_X2502X_X20_X25_X2E1f_X25_X25), + /* K7 */ be_const_real_hex(0x41200000), + /* K8 */ be_const_int(1), + /* K9 */ be_nested_str_weak(_X29_X3B), + }), + be_str_weak(to_css_gradient), + &be_const_str_solidified, + ( &(const binstruction[46]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x5C080200, // 0001 MOVE R2 R1 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C080200, // 0003 CALL R2 1 + 0x8C0C0501, // 0004 GETMET R3 R2 K1 + 0x58140002, // 0005 LDCONST R5 K2 + 0x541A03E7, // 0006 LDINT R6 1000 + 0x7C0C0600, // 0007 CALL R3 3 + 0x58100003, // 0008 LDCONST R4 K3 + 0x58140002, // 0009 LDCONST R5 K2 + 0x6018000C, // 000A GETGBL R6 G12 + 0x5C1C0600, // 000B MOVE R7 R3 + 0x7C180200, // 000C CALL R6 1 + 0x14180A06, // 000D LT R6 R5 R6 + 0x781A001C, // 000E JMPF R6 #002C + 0x94180605, // 000F GETIDX R6 R3 R5 + 0x881C0504, // 0010 GETMBR R7 R2 K4 + 0x8C1C0F05, // 0011 GETMET R7 R7 K5 + 0x54260003, // 0012 LDINT R9 4 + 0x08240A09, // 0013 MUL R9 R5 R9 + 0x542A0003, // 0014 LDINT R10 4 + 0x7C1C0600, // 0015 CALL R7 3 + 0x54220007, // 0016 LDINT R8 8 + 0x3C200E08, // 0017 SHR R8 R7 R8 + 0x542600FE, // 0018 LDINT R9 255 + 0x2C201009, // 0019 AND R8 R8 R9 + 0x5426000F, // 001A LDINT R9 16 + 0x3C240E09, // 001B SHR R9 R7 R9 + 0x542A00FE, // 001C LDINT R10 255 + 0x2C24120A, // 001D AND R9 R9 R10 + 0x542A0017, // 001E LDINT R10 24 + 0x3C280E0A, // 001F SHR R10 R7 R10 + 0x542E00FE, // 0020 LDINT R11 255 + 0x2C28140B, // 0021 AND R10 R10 R11 + 0x602C0018, // 0022 GETGBL R11 G24 + 0x58300006, // 0023 LDCONST R12 K6 + 0x5C341000, // 0024 MOVE R13 R8 + 0x5C381200, // 0025 MOVE R14 R9 + 0x5C3C1400, // 0026 MOVE R15 R10 + 0x0C400D07, // 0027 DIV R16 R6 K7 + 0x7C2C0A00, // 0028 CALL R11 5 + 0x0010080B, // 0029 ADD R4 R4 R11 + 0x00140B08, // 002A ADD R5 R5 K8 + 0x7001FFDD, // 002B JMP #000A + 0x00100909, // 002C ADD R4 R4 K9 + 0x80040800, // 002D RET 1 R4 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Animate_palette +********************************************************************/ +extern const bclass be_class_Animate_animator; +be_local_class(Animate_palette, + 7, + &be_class_Animate_animator, + be_nested_map(16, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(palette, 5), be_const_var(0) }, + { be_const_key_weak(range_min, -1), be_const_var(3) }, + { be_const_key_weak(slots_arr, -1), be_const_var(1) }, + { be_const_key_weak(init, -1), be_const_closure(Animate_palette_init_closure) }, + { be_const_key_weak(bri, 14), be_const_var(5) }, + { be_const_key_weak(animate, -1), be_const_closure(Animate_palette_animate_closure) }, + { be_const_key_weak(slots, -1), be_const_var(2) }, + { be_const_key_weak(ptr_to_palette, -1), be_const_static_closure(Animate_palette_ptr_to_palette_closure) }, + { be_const_key_weak(color, -1), be_const_var(6) }, + { be_const_key_weak(set_range, 10), be_const_closure(Animate_palette_set_range_closure) }, + { be_const_key_weak(to_css_gradient, -1), be_const_static_closure(Animate_palette_to_css_gradient_closure) }, + { be_const_key_weak(set_bri, -1), be_const_closure(Animate_palette_set_bri_closure) }, + { be_const_key_weak(set_duration, -1), be_const_closure(Animate_palette_set_duration_closure) }, + { be_const_key_weak(set_value, -1), be_const_closure(Animate_palette_set_value_closure) }, + { be_const_key_weak(parse_palette, -1), be_const_closure(Animate_palette_parse_palette_closure) }, + { be_const_key_weak(range_max, -1), be_const_var(4) }, + })), + be_str_weak(Animate_palette) +); +/*******************************************************************/ + +void be_load_Animate_palette_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Animate_palette); + be_setglobal(vm, "Animate_palette"); + be_pop(vm, 1); +} + +extern const bclass be_class_Animate_oscillator; + +/******************************************************************** +** Solidified function: set_b +********************************************************************/ +be_local_closure(Animate_oscillator_set_b, /* name */ + be_nested_proto( + 2, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -831,16 +1118,132 @@ be_local_closure(Animate_palette_start, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(b), + }), + be_str_weak(set_b), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_a +********************************************************************/ +be_local_closure(Animate_oscillator_set_a, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(a), + }), + be_str_weak(set_a), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_oscillator_init, /* name */ + be_nested_proto( + 6, /* nstack */ + 5, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(phase), + /* K1 */ be_const_int(0), + /* K2 */ be_nested_str_weak(duty_cycle), + /* K3 */ be_nested_str_weak(a), + /* K4 */ be_nested_str_weak(b), + /* K5 */ be_nested_str_weak(duration_ms), + /* K6 */ be_nested_str_weak(value), + /* K7 */ be_const_int(1), + /* K8 */ be_nested_str_weak(form), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[13]) { /* code */ + 0x90020101, // 0000 SETMBR R0 K0 K1 + 0x54160031, // 0001 LDINT R5 50 + 0x90020405, // 0002 SETMBR R0 K2 R5 + 0x90020601, // 0003 SETMBR R0 K3 R1 + 0x90020802, // 0004 SETMBR R0 K4 R2 + 0x90020A03, // 0005 SETMBR R0 K5 R3 + 0x90020C01, // 0006 SETMBR R0 K6 R1 + 0x4C140000, // 0007 LDNIL R5 + 0x1C140805, // 0008 EQ R5 R4 R5 + 0x78160000, // 0009 JMPF R5 #000B + 0x58100007, // 000A LDCONST R4 K7 + 0x90021004, // 000B SETMBR R0 K8 R4 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: animate +********************************************************************/ +be_local_closure(Animate_oscillator_animate, /* name */ + be_nested_proto( + 18, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[21]) { /* constants */ /* K0 */ be_nested_str_weak(duration_ms), /* K1 */ be_nested_str_weak(tasmota), /* K2 */ be_nested_str_weak(millis), /* K3 */ be_nested_str_weak(origin), - /* K4 */ be_nested_str_weak(running), + /* K4 */ be_const_int(0), + /* K5 */ be_nested_str_weak(originally), + /* K6 */ be_nested_str_weak(scale_uint), + /* K7 */ be_nested_str_weak(duty_cycle), + /* K8 */ be_nested_str_weak(beat), + /* K9 */ be_nested_str_weak(a), + /* K10 */ be_nested_str_weak(b), + /* K11 */ be_nested_str_weak(value), + /* K12 */ be_nested_str_weak(phase), + /* K13 */ be_nested_str_weak(form), + /* K14 */ be_const_int(1), + /* K15 */ be_nested_str_weak(scale_int), + /* K16 */ be_const_int(2), + /* K17 */ be_const_int(3), + /* K18 */ be_nested_str_weak(sine_int), + /* K19 */ be_nested_str_weak(obj), + /* K20 */ be_nested_str_weak(mth), }), - be_str_weak(start), + be_str_weak(animate), &be_const_str_solidified, - ( &(const binstruction[16]) { /* code */ + ( &(const binstruction[150]) { /* code */ 0x88080100, // 0000 GETMBR R2 R0 K0 0x4C0C0000, // 0001 LDNIL R3 0x1C080403, // 0002 EQ R2 R2 R3 @@ -853,10 +1256,144 @@ be_local_closure(Animate_palette_start, /* name */ 0x8C080502, // 0009 GETMET R2 R2 K2 0x7C080200, // 000A CALL R2 1 0x5C040400, // 000B MOVE R1 R2 - 0x90020601, // 000C SETMBR R0 K3 R1 - 0x50080200, // 000D LDBOOL R2 1 0 - 0x90020802, // 000E SETMBR R0 K4 R2 - 0x80000000, // 000F RET 0 + 0x88080103, // 000C GETMBR R2 R0 K3 + 0x04080202, // 000D SUB R2 R1 R2 + 0x140C0504, // 000E LT R3 R2 K4 + 0x780E0001, // 000F JMPF R3 #0012 + 0x58080004, // 0010 LDCONST R2 K4 + 0x88040105, // 0011 GETMBR R1 R0 K5 + 0x880C0100, // 0012 GETMBR R3 R0 K0 + 0x4C100000, // 0013 LDNIL R4 + 0xB8160200, // 0014 GETNGBL R5 K1 + 0x8C140B06, // 0015 GETMET R5 R5 K6 + 0x881C0107, // 0016 GETMBR R7 R0 K7 + 0x58200004, // 0017 LDCONST R8 K4 + 0x54260063, // 0018 LDINT R9 100 + 0x58280004, // 0019 LDCONST R10 K4 + 0x5C2C0600, // 001A MOVE R11 R3 + 0x7C140C00, // 001B CALL R5 6 + 0x5C100A00, // 001C MOVE R4 R5 + 0x28140403, // 001D GE R5 R2 R3 + 0x78160007, // 001E JMPF R5 #0027 + 0x0C180403, // 001F DIV R6 R2 R3 + 0x08180C03, // 0020 MUL R6 R6 R3 + 0x88140103, // 0021 GETMBR R5 R0 K3 + 0x00140A06, // 0022 ADD R5 R5 R6 + 0x90020605, // 0023 SETMBR R0 K3 R5 + 0x10080403, // 0024 MOD R2 R2 R3 + 0x8C140108, // 0025 GETMET R5 R0 K8 + 0x7C140200, // 0026 CALL R5 1 + 0x88140109, // 0027 GETMBR R5 R0 K9 + 0x8818010A, // 0028 GETMBR R6 R0 K10 + 0x881C010B, // 0029 GETMBR R7 R0 K11 + 0x5C200400, // 002A MOVE R8 R2 + 0x8824010C, // 002B GETMBR R9 R0 K12 + 0x24241304, // 002C GT R9 R9 K4 + 0x7826000B, // 002D JMPF R9 #003A + 0xB8260200, // 002E GETNGBL R9 K1 + 0x8C241306, // 002F GETMET R9 R9 K6 + 0x882C010C, // 0030 GETMBR R11 R0 K12 + 0x58300004, // 0031 LDCONST R12 K4 + 0x54360063, // 0032 LDINT R13 100 + 0x58380004, // 0033 LDCONST R14 K4 + 0x5C3C0600, // 0034 MOVE R15 R3 + 0x7C240C00, // 0035 CALL R9 6 + 0x00201009, // 0036 ADD R8 R8 R9 + 0x24241003, // 0037 GT R9 R8 R3 + 0x78260000, // 0038 JMPF R9 #003A + 0x04201003, // 0039 SUB R8 R8 R3 + 0x8824010D, // 003A GETMBR R9 R0 K13 + 0x1C24130E, // 003B EQ R9 R9 K14 + 0x78260009, // 003C JMPF R9 #0047 + 0xB8260200, // 003D GETNGBL R9 K1 + 0x8C24130F, // 003E GETMET R9 R9 K15 + 0x5C2C1000, // 003F MOVE R11 R8 + 0x58300004, // 0040 LDCONST R12 K4 + 0x0434070E, // 0041 SUB R13 R3 K14 + 0x5C380A00, // 0042 MOVE R14 R5 + 0x5C3C0C00, // 0043 MOVE R15 R6 + 0x7C240C00, // 0044 CALL R9 6 + 0x5C1C1200, // 0045 MOVE R7 R9 + 0x70020044, // 0046 JMP #008C + 0x8824010D, // 0047 GETMBR R9 R0 K13 + 0x1C241310, // 0048 EQ R9 R9 K16 + 0x78260015, // 0049 JMPF R9 #0060 + 0x14241004, // 004A LT R9 R8 R4 + 0x78260009, // 004B JMPF R9 #0056 + 0xB8260200, // 004C GETNGBL R9 K1 + 0x8C24130F, // 004D GETMET R9 R9 K15 + 0x5C2C1000, // 004E MOVE R11 R8 + 0x58300004, // 004F LDCONST R12 K4 + 0x0434090E, // 0050 SUB R13 R4 K14 + 0x5C380A00, // 0051 MOVE R14 R5 + 0x5C3C0C00, // 0052 MOVE R15 R6 + 0x7C240C00, // 0053 CALL R9 6 + 0x5C1C1200, // 0054 MOVE R7 R9 + 0x70020008, // 0055 JMP #005F + 0xB8260200, // 0056 GETNGBL R9 K1 + 0x8C24130F, // 0057 GETMET R9 R9 K15 + 0x5C2C1000, // 0058 MOVE R11 R8 + 0x5C300800, // 0059 MOVE R12 R4 + 0x0434070E, // 005A SUB R13 R3 K14 + 0x5C380C00, // 005B MOVE R14 R6 + 0x5C3C0A00, // 005C MOVE R15 R5 + 0x7C240C00, // 005D CALL R9 6 + 0x5C1C1200, // 005E MOVE R7 R9 + 0x7002002B, // 005F JMP #008C + 0x8824010D, // 0060 GETMBR R9 R0 K13 + 0x1C241311, // 0061 EQ R9 R9 K17 + 0x78260005, // 0062 JMPF R9 #0069 + 0x14241004, // 0063 LT R9 R8 R4 + 0x78260001, // 0064 JMPF R9 #0067 + 0x5C1C0A00, // 0065 MOVE R7 R5 + 0x70020000, // 0066 JMP #0068 + 0x5C1C0C00, // 0067 MOVE R7 R6 + 0x70020022, // 0068 JMP #008C + 0x8824010D, // 0069 GETMBR R9 R0 K13 + 0x542A0003, // 006A LDINT R10 4 + 0x1C24120A, // 006B EQ R9 R9 R10 + 0x74260003, // 006C JMPT R9 #0071 + 0x8824010D, // 006D GETMBR R9 R0 K13 + 0x542A0004, // 006E LDINT R10 5 + 0x1C24120A, // 006F EQ R9 R9 R10 + 0x7826001A, // 0070 JMPF R9 #008C + 0xB8260200, // 0071 GETNGBL R9 K1 + 0x8C24130F, // 0072 GETMET R9 R9 K15 + 0x5C2C1000, // 0073 MOVE R11 R8 + 0x58300004, // 0074 LDCONST R12 K4 + 0x0434070E, // 0075 SUB R13 R3 K14 + 0x58380004, // 0076 LDCONST R14 K4 + 0x543E7FFE, // 0077 LDINT R15 32767 + 0x7C240C00, // 0078 CALL R9 6 + 0x8828010D, // 0079 GETMBR R10 R0 K13 + 0x542E0003, // 007A LDINT R11 4 + 0x1C28140B, // 007B EQ R10 R10 R11 + 0x782A0001, // 007C JMPF R10 #007F + 0x542A1FFF, // 007D LDINT R10 8192 + 0x0424120A, // 007E SUB R9 R9 R10 + 0xB82A0200, // 007F GETNGBL R10 K1 + 0x8C281512, // 0080 GETMET R10 R10 K18 + 0x5C301200, // 0081 MOVE R12 R9 + 0x7C280400, // 0082 CALL R10 2 + 0xB82E0200, // 0083 GETNGBL R11 K1 + 0x8C2C170F, // 0084 GETMET R11 R11 K15 + 0x5C341400, // 0085 MOVE R13 R10 + 0x5439EFFF, // 0086 LDINT R14 -4096 + 0x543E0FFF, // 0087 LDINT R15 4096 + 0x5C400A00, // 0088 MOVE R16 R5 + 0x5C440C00, // 0089 MOVE R17 R6 + 0x7C2C0C00, // 008A CALL R11 6 + 0x5C1C1600, // 008B MOVE R7 R11 + 0x90021607, // 008C SETMBR R0 K11 R7 + 0x88240113, // 008D GETMBR R9 R0 K19 + 0x88280114, // 008E GETMBR R10 R0 K20 + 0x78260004, // 008F JMPF R9 #0095 + 0x782A0003, // 0090 JMPF R10 #0095 + 0x5C2C1400, // 0091 MOVE R11 R10 + 0x5C301200, // 0092 MOVE R12 R9 + 0x5C340E00, // 0093 MOVE R13 R7 + 0x7C2C0400, // 0094 CALL R11 2 + 0x80040E00, // 0095 RET 1 R7 }) ) ); @@ -864,223 +1401,11 @@ be_local_closure(Animate_palette_start, /* name */ /******************************************************************** -** Solidified class: Animate_palette +** Solidified function: set_duty_cycle ********************************************************************/ -be_local_class(Animate_palette, - 12, - NULL, - be_nested_map(24, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(start, -1), be_const_closure(Animate_palette_start_closure) }, - { be_const_key_weak(to_css_gradient, -1), be_const_closure(Animate_palette_to_css_gradient_closure) }, - { be_const_key_weak(range_min, -1), be_const_var(6) }, - { be_const_key_weak(init, -1), be_const_closure(Animate_palette_init_closure) }, - { be_const_key_weak(set_value, -1), be_const_closure(Animate_palette_set_value_closure) }, - { be_const_key_weak(stop, -1), be_const_closure(Animate_palette_stop_closure) }, - { be_const_key_weak(slots, 15), be_const_var(2) }, - { be_const_key_weak(origin, -1), be_const_var(5) }, - { be_const_key_weak(animate, 19), be_const_closure(Animate_palette_animate_closure) }, - { be_const_key_weak(set_range, 2), be_const_closure(Animate_palette_set_range_closure) }, - { be_const_key_weak(slots_arr, -1), be_const_var(1) }, - { be_const_key_weak(set_bri, -1), be_const_closure(Animate_palette_set_bri_closure) }, - { be_const_key_weak(bri, 17), be_const_var(10) }, - { be_const_key_weak(is_running, -1), be_const_closure(Animate_palette_is_running_closure) }, - { be_const_key_weak(animate_mth, -1), be_const_var(9) }, - { be_const_key_weak(duration_ms, -1), be_const_var(4) }, - { be_const_key_weak(color, -1), be_const_var(11) }, - { be_const_key_weak(set_duration, 22), be_const_closure(Animate_palette_set_duration_closure) }, - { be_const_key_weak(animate_obj, -1), be_const_var(8) }, - { be_const_key_weak(palette, -1), be_const_var(0) }, - { be_const_key_weak(parse_palette, 14), be_const_closure(Animate_palette_parse_palette_closure) }, - { be_const_key_weak(set_cb, 4), be_const_closure(Animate_palette_set_cb_closure) }, - { be_const_key_weak(running, -1), be_const_var(3) }, - { be_const_key_weak(range_max, 0), be_const_var(7) }, - })), - be_str_weak(Animate_palette) -); - -extern const bclass be_class_Animate_rotate; - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Animate_rotate_init, /* name */ +be_local_closure(Animate_oscillator_set_duty_cycle, /* name */ be_nested_proto( - 13, /* nstack */ - 6, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str_weak(init), - /* K1 */ be_nested_str_weak(set_cb), - /* K2 */ be_nested_str_weak(code), - /* K3 */ be_nested_str_weak(push), - /* K4 */ be_nested_str_weak(animate), - /* K5 */ be_nested_str_weak(ins_ramp), - /* K6 */ be_nested_str_weak(ins_goto), - /* K7 */ be_const_int(0), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[28]) { /* code */ - 0x60180003, // 0000 GETGBL R6 G3 - 0x5C1C0000, // 0001 MOVE R7 R0 - 0x7C180200, // 0002 CALL R6 1 - 0x8C180D00, // 0003 GETMET R6 R6 K0 - 0x7C180200, // 0004 CALL R6 1 - 0x8C180101, // 0005 GETMET R6 R0 K1 - 0x5C200200, // 0006 MOVE R8 R1 - 0x5C240400, // 0007 MOVE R9 R2 - 0x7C180600, // 0008 CALL R6 3 - 0x88180102, // 0009 GETMBR R6 R0 K2 - 0x8C180D03, // 000A GETMET R6 R6 K3 - 0xB8220800, // 000B GETNGBL R8 K4 - 0x8C201105, // 000C GETMET R8 R8 K5 - 0x5C280600, // 000D MOVE R10 R3 - 0x5C2C0800, // 000E MOVE R11 R4 - 0x5C300A00, // 000F MOVE R12 R5 - 0x7C200800, // 0010 CALL R8 4 - 0x7C180400, // 0011 CALL R6 2 - 0x88180102, // 0012 GETMBR R6 R0 K2 - 0x8C180D03, // 0013 GETMET R6 R6 K3 - 0xB8220800, // 0014 GETNGBL R8 K4 - 0x8C201106, // 0015 GETMET R8 R8 K6 - 0x58280007, // 0016 LDCONST R10 K7 - 0x582C0007, // 0017 LDCONST R11 K7 - 0x58300007, // 0018 LDCONST R12 K7 - 0x7C200800, // 0019 CALL R8 4 - 0x7C180400, // 001A CALL R6 2 - 0x80000000, // 001B RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: Animate_rotate -********************************************************************/ -extern const bclass be_class_Animate_engine; -be_local_class(Animate_rotate, - 0, - &be_class_Animate_engine, - be_nested_map(1, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(init, -1), be_const_closure(Animate_rotate_init_closure) }, - })), - be_str_weak(Animate_rotate) -); - -extern const bclass be_class_Animate_ins_goto; - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Animate_ins_goto_init, /* name */ - be_nested_proto( - 4, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(pc_rel), - /* K1 */ be_nested_str_weak(pc_abs), - /* K2 */ be_nested_str_weak(duration), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x90020403, // 0002 SETMBR R0 K2 R3 - 0x80000000, // 0003 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: Animate_ins_goto -********************************************************************/ -be_local_class(Animate_ins_goto, - 3, - NULL, - be_nested_map(4, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(pc_rel, -1), be_const_var(0) }, - { be_const_key_weak(duration, -1), be_const_var(2) }, - { be_const_key_weak(init, -1), be_const_closure(Animate_ins_goto_init_closure) }, - { be_const_key_weak(pc_abs, 2), be_const_var(1) }, - })), - be_str_weak(Animate_ins_goto) -); - -extern const bclass be_class_Animate_ins_ramp; - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Animate_ins_ramp_init, /* name */ - be_nested_proto( - 4, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(a), - /* K1 */ be_nested_str_weak(b), - /* K2 */ be_nested_str_weak(duration), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x90020403, // 0002 SETMBR R0 K2 R3 - 0x80000000, // 0003 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: Animate_ins_ramp -********************************************************************/ -be_local_class(Animate_ins_ramp, - 3, - NULL, - be_nested_map(4, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(a, -1), be_const_var(0) }, - { be_const_key_weak(b, 2), be_const_var(1) }, - { be_const_key_weak(duration, -1), be_const_var(2) }, - { be_const_key_weak(init, -1), be_const_closure(Animate_ins_ramp_init_closure) }, - })), - be_str_weak(Animate_ins_ramp) -); - -extern const bclass be_class_Animate_engine; - -/******************************************************************** -** Solidified function: animate -********************************************************************/ -be_local_closure(Animate_engine_animate, /* name */ - be_nested_proto( - 14, /* nstack */ + 3, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -1088,148 +1413,22 @@ be_local_closure(Animate_engine_animate, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[24]) { /* constants */ - /* K0 */ be_nested_str_weak(running), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(millis), - /* K3 */ be_nested_str_weak(ins_time), - /* K4 */ be_nested_str_weak(pc), - /* K5 */ be_nested_str_weak(code), - /* K6 */ be_const_int(0), - /* K7 */ be_nested_str_weak(internal_error), - /* K8 */ be_nested_str_weak(Animate_X20pc_X20is_X20out_X20of_X20range), - /* K9 */ be_nested_str_weak(animate), - /* K10 */ be_nested_str_weak(ins_ramp), - /* K11 */ be_nested_str_weak(closure), - /* K12 */ be_nested_str_weak(animate_obj), - /* K13 */ be_nested_str_weak(animate_mth), - /* K14 */ be_nested_str_weak(duration), - /* K15 */ be_nested_str_weak(value), - /* K16 */ be_nested_str_weak(scale_uint), - /* K17 */ be_nested_str_weak(a), - /* K18 */ be_nested_str_weak(b), - /* K19 */ be_const_int(1), - /* K20 */ be_nested_str_weak(ins_goto), - /* K21 */ be_nested_str_weak(pc_rel), - /* K22 */ be_nested_str_weak(pc_abs), - /* K23 */ be_nested_str_weak(unknown_X20instruction), + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_weak(duty_cycle), }), - be_str_weak(animate), + be_str_weak(set_duty_cycle), &be_const_str_solidified, - ( &(const binstruction[113]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x740A0000, // 0001 JMPT R2 #0003 - 0x80000400, // 0002 RET 0 - 0x4C080000, // 0003 LDNIL R2 - 0x1C080202, // 0004 EQ R2 R1 R2 - 0x780A0003, // 0005 JMPF R2 #000A - 0xB80A0200, // 0006 GETNGBL R2 K1 - 0x8C080502, // 0007 GETMET R2 R2 K2 - 0x7C080200, // 0008 CALL R2 1 - 0x5C040400, // 0009 MOVE R1 R2 - 0x50080200, // 000A LDBOOL R2 1 0 - 0x780A0062, // 000B JMPF R2 #006F - 0x88080103, // 000C GETMBR R2 R0 K3 - 0x04080202, // 000D SUB R2 R1 R2 - 0x880C0104, // 000E GETMBR R3 R0 K4 - 0x6010000C, // 000F GETGBL R4 G12 - 0x88140105, // 0010 GETMBR R5 R0 K5 - 0x7C100200, // 0011 CALL R4 1 - 0x280C0604, // 0012 GE R3 R3 R4 - 0x780E0002, // 0013 JMPF R3 #0017 - 0x500C0000, // 0014 LDBOOL R3 0 0 - 0x90020003, // 0015 SETMBR R0 K0 R3 - 0x70020057, // 0016 JMP #006F - 0x880C0104, // 0017 GETMBR R3 R0 K4 - 0x140C0706, // 0018 LT R3 R3 K6 - 0x780E0000, // 0019 JMPF R3 #001B - 0xB0060F08, // 001A RAISE 1 K7 K8 - 0x880C0105, // 001B GETMBR R3 R0 K5 - 0x88100104, // 001C GETMBR R4 R0 K4 - 0x940C0604, // 001D GETIDX R3 R3 R4 - 0x6010000F, // 001E GETGBL R4 G15 - 0x5C140600, // 001F MOVE R5 R3 - 0xB81A1200, // 0020 GETNGBL R6 K9 - 0x88180D0A, // 0021 GETMBR R6 R6 K10 - 0x7C100400, // 0022 CALL R4 2 - 0x7812002E, // 0023 JMPF R4 #0053 - 0x8810010B, // 0024 GETMBR R4 R0 K11 - 0x8814010C, // 0025 GETMBR R5 R0 K12 - 0x8818010D, // 0026 GETMBR R6 R0 K13 - 0x881C070E, // 0027 GETMBR R7 R3 K14 - 0x141C0407, // 0028 LT R7 R2 R7 - 0x781E0014, // 0029 JMPF R7 #003F - 0xB81E0200, // 002A GETNGBL R7 K1 - 0x8C1C0F10, // 002B GETMET R7 R7 K16 - 0x5C240400, // 002C MOVE R9 R2 - 0x58280006, // 002D LDCONST R10 K6 - 0x882C070E, // 002E GETMBR R11 R3 K14 - 0x88300711, // 002F GETMBR R12 R3 K17 - 0x88340712, // 0030 GETMBR R13 R3 K18 - 0x7C1C0C00, // 0031 CALL R7 6 - 0x90021E07, // 0032 SETMBR R0 K15 R7 - 0x78160004, // 0033 JMPF R5 #0039 - 0x781A0003, // 0034 JMPF R6 #0039 - 0x5C1C0C00, // 0035 MOVE R7 R6 - 0x5C200A00, // 0036 MOVE R8 R5 - 0x8824010F, // 0037 GETMBR R9 R0 K15 - 0x7C1C0400, // 0038 CALL R7 2 - 0x78120002, // 0039 JMPF R4 #003D - 0x5C1C0800, // 003A MOVE R7 R4 - 0x8820010F, // 003B GETMBR R8 R0 K15 - 0x7C1C0200, // 003C CALL R7 1 - 0x70020030, // 003D JMP #006F - 0x70020012, // 003E JMP #0052 - 0x881C0712, // 003F GETMBR R7 R3 K18 - 0x90021E07, // 0040 SETMBR R0 K15 R7 - 0x78160004, // 0041 JMPF R5 #0047 - 0x781A0003, // 0042 JMPF R6 #0047 - 0x5C1C0C00, // 0043 MOVE R7 R6 - 0x5C200A00, // 0044 MOVE R8 R5 - 0x8824010F, // 0045 GETMBR R9 R0 K15 - 0x7C1C0400, // 0046 CALL R7 2 - 0x78120002, // 0047 JMPF R4 #004B - 0x5C1C0800, // 0048 MOVE R7 R4 - 0x8820010F, // 0049 GETMBR R8 R0 K15 - 0x7C1C0200, // 004A CALL R7 1 - 0x881C0104, // 004B GETMBR R7 R0 K4 - 0x001C0F13, // 004C ADD R7 R7 K19 - 0x90020807, // 004D SETMBR R0 K4 R7 - 0x881C070E, // 004E GETMBR R7 R3 K14 - 0x041C0407, // 004F SUB R7 R2 R7 - 0x041C0207, // 0050 SUB R7 R1 R7 - 0x90020607, // 0051 SETMBR R0 K3 R7 - 0x7002001A, // 0052 JMP #006E - 0x6010000F, // 0053 GETGBL R4 G15 - 0x5C140600, // 0054 MOVE R5 R3 - 0xB81A1200, // 0055 GETNGBL R6 K9 - 0x88180D14, // 0056 GETMBR R6 R6 K20 - 0x7C100400, // 0057 CALL R4 2 - 0x78120013, // 0058 JMPF R4 #006D - 0x8810070E, // 0059 GETMBR R4 R3 K14 - 0x14100404, // 005A LT R4 R2 R4 - 0x78120001, // 005B JMPF R4 #005E - 0x70020011, // 005C JMP #006F - 0x7002000D, // 005D JMP #006C - 0x88100715, // 005E GETMBR R4 R3 K21 - 0x20100906, // 005F NE R4 R4 K6 - 0x78120004, // 0060 JMPF R4 #0066 - 0x88100104, // 0061 GETMBR R4 R0 K4 - 0x88140715, // 0062 GETMBR R5 R3 K21 - 0x00100805, // 0063 ADD R4 R4 R5 - 0x90020804, // 0064 SETMBR R0 K4 R4 - 0x70020001, // 0065 JMP #0068 - 0x88100716, // 0066 GETMBR R4 R3 K22 - 0x90020804, // 0067 SETMBR R0 K4 R4 - 0x8810070E, // 0068 GETMBR R4 R3 K14 - 0x04100404, // 0069 SUB R4 R2 R4 - 0x04100204, // 006A SUB R4 R1 R4 - 0x90020604, // 006B SETMBR R0 K3 R4 - 0x70020000, // 006C JMP #006E - 0xB0060F17, // 006D RAISE 1 K7 K23 - 0x7001FF9A, // 006E JMP #000A - 0x8808010F, // 006F GETMBR R2 R0 K15 - 0x80040400, // 0070 RET 1 R2 + ( &(const binstruction[ 9]) { /* code */ + 0x14080300, // 0000 LT R2 R1 K0 + 0x780A0000, // 0001 JMPF R2 #0003 + 0x58040000, // 0002 LDCONST R1 K0 + 0x540A0063, // 0003 LDINT R2 100 + 0x24080202, // 0004 GT R2 R1 R2 + 0x780A0000, // 0005 JMPF R2 #0007 + 0x54060063, // 0006 LDINT R1 100 + 0x90020201, // 0007 SETMBR R0 K1 R1 + 0x80000000, // 0008 RET 0 }) ) ); @@ -1237,104 +1436,12 @@ be_local_closure(Animate_engine_animate, /* name */ /******************************************************************** -** Solidified function: init +** Solidified function: set_phase ********************************************************************/ -be_local_closure(Animate_engine_init, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(code), - /* K1 */ be_nested_str_weak(pc), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(ins_time), - /* K4 */ be_nested_str_weak(running), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x60040012, // 0000 GETGBL R1 G18 - 0x7C040000, // 0001 CALL R1 0 - 0x90020001, // 0002 SETMBR R0 K0 R1 - 0x90020302, // 0003 SETMBR R0 K1 K2 - 0x90020702, // 0004 SETMBR R0 K3 K2 - 0x50040000, // 0005 LDBOOL R1 0 0 - 0x90020801, // 0006 SETMBR R0 K4 R1 - 0x80000000, // 0007 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: stop -********************************************************************/ -be_local_closure(Animate_engine_stop, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(running), - }), - be_str_weak(stop), - &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0x50040000, // 0000 LDBOOL R1 0 0 - 0x90020001, // 0001 SETMBR R0 K0 R1 - 0x80000000, // 0002 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: is_running -********************************************************************/ -be_local_closure(Animate_engine_is_running, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(running), - }), - be_str_weak(is_running), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_cb -********************************************************************/ -be_local_closure(Animate_engine_set_cb, /* name */ +be_local_closure(Animate_oscillator_set_phase, /* name */ be_nested_proto( 3, /* nstack */ - 3, /* argc */ + 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -1342,15 +1449,21 @@ be_local_closure(Animate_engine_set_cb, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(animate_obj), - /* K1 */ be_nested_str_weak(animate_mth), + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_weak(phase), }), - be_str_weak(set_cb), + be_str_weak(set_phase), &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x80000000, // 0002 RET 0 + ( &(const binstruction[ 9]) { /* code */ + 0x14080300, // 0000 LT R2 R1 K0 + 0x780A0000, // 0001 JMPF R2 #0003 + 0x58040000, // 0002 LDCONST R1 K0 + 0x540A0063, // 0003 LDINT R2 100 + 0x24080202, // 0004 GT R2 R1 R2 + 0x780A0000, // 0005 JMPF R2 #0007 + 0x54060063, // 0006 LDINT R1 100 + 0x90020201, // 0007 SETMBR R0 K1 R1 + 0x80000000, // 0008 RET 0 }) ) ); @@ -1358,242 +1471,35 @@ be_local_closure(Animate_engine_set_cb, /* name */ /******************************************************************** -** Solidified function: start +** Solidified class: Animate_oscillator ********************************************************************/ -be_local_closure(Animate_engine_start, /* name */ - be_nested_proto( - 5, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(millis), - /* K2 */ be_nested_str_weak(value), - /* K3 */ be_nested_str_weak(ins_time), - /* K4 */ be_nested_str_weak(running), - }), - be_str_weak(start), - &be_const_str_solidified, - ( &(const binstruction[15]) { /* code */ - 0x4C0C0000, // 0000 LDNIL R3 - 0x1C0C0203, // 0001 EQ R3 R1 R3 - 0x780E0003, // 0002 JMPF R3 #0007 - 0xB80E0000, // 0003 GETNGBL R3 K0 - 0x8C0C0701, // 0004 GETMET R3 R3 K1 - 0x7C0C0200, // 0005 CALL R3 1 - 0x5C040600, // 0006 MOVE R1 R3 - 0x4C0C0000, // 0007 LDNIL R3 - 0x200C0403, // 0008 NE R3 R2 R3 - 0x780E0000, // 0009 JMPF R3 #000B - 0x90020402, // 000A SETMBR R0 K2 R2 - 0x90020601, // 000B SETMBR R0 K3 R1 - 0x500C0200, // 000C LDBOOL R3 1 0 - 0x90020803, // 000D SETMBR R0 K4 R3 - 0x80000000, // 000E RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: Animate_engine -********************************************************************/ -be_local_class(Animate_engine, - 8, - NULL, - be_nested_map(14, +extern const bclass be_class_Animate_animator; +be_local_class(Animate_oscillator, + 6, + &be_class_Animate_animator, + be_nested_map(12, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(animate, -1), be_const_closure(Animate_engine_animate_closure) }, - { be_const_key_weak(ins_time, -1), be_const_var(5) }, - { be_const_key_weak(running, 10), be_const_var(6) }, - { be_const_key_weak(stop, 7), be_const_closure(Animate_engine_stop_closure) }, - { be_const_key_weak(closure, -1), be_const_var(1) }, - { be_const_key_weak(init, 1), be_const_closure(Animate_engine_init_closure) }, - { be_const_key_weak(animate_mth, -1), be_const_var(3) }, - { be_const_key_weak(set_cb, -1), be_const_closure(Animate_engine_set_cb_closure) }, - { be_const_key_weak(code, -1), be_const_var(0) }, - { be_const_key_weak(is_running, -1), be_const_closure(Animate_engine_is_running_closure) }, - { be_const_key_weak(animate_obj, 11), be_const_var(2) }, - { be_const_key_weak(pc, -1), be_const_var(4) }, - { be_const_key_weak(value, 6), be_const_var(7) }, - { be_const_key_weak(start, -1), be_const_closure(Animate_engine_start_closure) }, + { be_const_key_weak(phase, -1), be_const_var(0) }, + { be_const_key_weak(b, -1), be_const_var(3) }, + { be_const_key_weak(set_b, -1), be_const_closure(Animate_oscillator_set_b_closure) }, + { be_const_key_weak(set_a, 10), be_const_closure(Animate_oscillator_set_a_closure) }, + { be_const_key_weak(a, -1), be_const_var(2) }, + { be_const_key_weak(set_phase, -1), be_const_closure(Animate_oscillator_set_phase_closure) }, + { be_const_key_weak(value, -1), be_const_var(5) }, + { be_const_key_weak(duty_cycle, -1), be_const_var(1) }, + { be_const_key_weak(animate, 7), be_const_closure(Animate_oscillator_animate_closure) }, + { be_const_key_weak(set_duty_cycle, -1), be_const_closure(Animate_oscillator_set_duty_cycle_closure) }, + { be_const_key_weak(init, -1), be_const_closure(Animate_oscillator_init_closure) }, + { be_const_key_weak(form, 5), be_const_var(4) }, })), - be_str_weak(Animate_engine) -); - -extern const bclass be_class_Animate_back_forth; - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Animate_back_forth_init, /* name */ - be_nested_proto( - 13, /* nstack */ - 6, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str_weak(init), - /* K1 */ be_nested_str_weak(set_cb), - /* K2 */ be_nested_str_weak(code), - /* K3 */ be_nested_str_weak(push), - /* K4 */ be_nested_str_weak(animate), - /* K5 */ be_nested_str_weak(ins_ramp), - /* K6 */ be_nested_str_weak(ins_goto), - /* K7 */ be_const_int(0), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[37]) { /* code */ - 0x60180003, // 0000 GETGBL R6 G3 - 0x5C1C0000, // 0001 MOVE R7 R0 - 0x7C180200, // 0002 CALL R6 1 - 0x8C180D00, // 0003 GETMET R6 R6 K0 - 0x7C180200, // 0004 CALL R6 1 - 0x8C180101, // 0005 GETMET R6 R0 K1 - 0x5C200200, // 0006 MOVE R8 R1 - 0x5C240400, // 0007 MOVE R9 R2 - 0x7C180600, // 0008 CALL R6 3 - 0x88180102, // 0009 GETMBR R6 R0 K2 - 0x8C180D03, // 000A GETMET R6 R6 K3 - 0xB8220800, // 000B GETNGBL R8 K4 - 0x8C201105, // 000C GETMET R8 R8 K5 - 0x5C280600, // 000D MOVE R10 R3 - 0x5C2C0800, // 000E MOVE R11 R4 - 0x5C300A00, // 000F MOVE R12 R5 - 0x7C200800, // 0010 CALL R8 4 - 0x7C180400, // 0011 CALL R6 2 - 0x88180102, // 0012 GETMBR R6 R0 K2 - 0x8C180D03, // 0013 GETMET R6 R6 K3 - 0xB8220800, // 0014 GETNGBL R8 K4 - 0x8C201105, // 0015 GETMET R8 R8 K5 - 0x5C280800, // 0016 MOVE R10 R4 - 0x5C2C0600, // 0017 MOVE R11 R3 - 0x5C300A00, // 0018 MOVE R12 R5 - 0x7C200800, // 0019 CALL R8 4 - 0x7C180400, // 001A CALL R6 2 - 0x88180102, // 001B GETMBR R6 R0 K2 - 0x8C180D03, // 001C GETMET R6 R6 K3 - 0xB8220800, // 001D GETNGBL R8 K4 - 0x8C201106, // 001E GETMET R8 R8 K6 - 0x58280007, // 001F LDCONST R10 K7 - 0x582C0007, // 0020 LDCONST R11 K7 - 0x58300007, // 0021 LDCONST R12 K7 - 0x7C200800, // 0022 CALL R8 4 - 0x7C180400, // 0023 CALL R6 2 - 0x80000000, // 0024 RET 0 - }) - ) + be_str_weak(Animate_oscillator) ); /*******************************************************************/ - -/******************************************************************** -** Solidified class: Animate_back_forth -********************************************************************/ -extern const bclass be_class_Animate_engine; -be_local_class(Animate_back_forth, - 0, - &be_class_Animate_engine, - be_nested_map(1, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(init, -1), be_const_closure(Animate_back_forth_init_closure) }, - })), - be_str_weak(Animate_back_forth) -); - -extern const bclass be_class_Animate_from_to; - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Animate_from_to_init, /* name */ - be_nested_proto( - 13, /* nstack */ - 6, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(init), - /* K1 */ be_nested_str_weak(set_cb), - /* K2 */ be_nested_str_weak(code), - /* K3 */ be_nested_str_weak(push), - /* K4 */ be_nested_str_weak(animate), - /* K5 */ be_nested_str_weak(ins_ramp), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[19]) { /* code */ - 0x60180003, // 0000 GETGBL R6 G3 - 0x5C1C0000, // 0001 MOVE R7 R0 - 0x7C180200, // 0002 CALL R6 1 - 0x8C180D00, // 0003 GETMET R6 R6 K0 - 0x7C180200, // 0004 CALL R6 1 - 0x8C180101, // 0005 GETMET R6 R0 K1 - 0x5C200200, // 0006 MOVE R8 R1 - 0x5C240400, // 0007 MOVE R9 R2 - 0x7C180600, // 0008 CALL R6 3 - 0x88180102, // 0009 GETMBR R6 R0 K2 - 0x8C180D03, // 000A GETMET R6 R6 K3 - 0xB8220800, // 000B GETNGBL R8 K4 - 0x8C201105, // 000C GETMET R8 R8 K5 - 0x5C280600, // 000D MOVE R10 R3 - 0x5C2C0800, // 000E MOVE R11 R4 - 0x5C300A00, // 000F MOVE R12 R5 - 0x7C200800, // 0010 CALL R8 4 - 0x7C180400, // 0011 CALL R6 2 - 0x80000000, // 0012 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: Animate_from_to -********************************************************************/ -extern const bclass be_class_Animate_engine; -be_local_class(Animate_from_to, - 0, - &be_class_Animate_engine, - be_nested_map(1, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(init, -1), be_const_closure(Animate_from_to_init_closure) }, - })), - be_str_weak(Animate_from_to) -); - -/******************************************************************** -** Solidified module: animate -********************************************************************/ -be_local_module(animate, - "animate", - be_nested_map(7, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(ins_ramp, -1), be_const_class(be_class_Animate_ins_ramp) }, - { be_const_key_weak(from_to, -1), be_const_class(be_class_Animate_from_to) }, - { be_const_key_weak(palette, 3), be_const_class(be_class_Animate_palette) }, - { be_const_key_weak(engine, 5), be_const_class(be_class_Animate_engine) }, - { be_const_key_weak(back_forth, -1), be_const_class(be_class_Animate_back_forth) }, - { be_const_key_weak(rotate, -1), be_const_class(be_class_Animate_rotate) }, - { be_const_key_weak(ins_goto, -1), be_const_class(be_class_Animate_ins_goto) }, - })) -); -BE_EXPORT_VARIABLE be_define_const_native_module(animate); -/********************************************************************/ +void be_load_Animate_oscillator_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Animate_oscillator); + be_setglobal(vm, "Animate_oscillator"); + be_pop(vm, 1); +} /********************************************************************/ /* End of solidification */ diff --git a/tasmota/berry/animate_demo/animate_demo_palette_background.be b/tasmota/berry/animate_demo/animate_demo_palette_background.be new file mode 100644 index 000000000..03648b419 --- /dev/null +++ b/tasmota/berry/animate_demo/animate_demo_palette_background.be @@ -0,0 +1,11 @@ +# +# Example for M5Stack Led Matrix +# 5 x 5 WS2812 +# +import animate + +var duration = 10000 +var strip = Leds(5 * 5, gpio.pin(gpio.WS2812, 0)) +var anim = animate(strip) +anim.add_background_animator(animate.palette(animate.PALETTE_RAINBOW_WHITE, duration)) +anim.start() diff --git a/tasmota/berry/animate_demo/animate_demo_pulse.be b/tasmota/berry/animate_demo/animate_demo_pulse.be new file mode 100644 index 000000000..0a2b6dd40 --- /dev/null +++ b/tasmota/berry/animate_demo/animate_demo_pulse.be @@ -0,0 +1,23 @@ +# +# Example for M5Stack Led Matrix +# 5 x 5 WS2812 +# +import animate + +var duration = 10000 +var strip = Leds(5 * 5, gpio.pin(gpio.WS2812, 0)) +var anim = animate(strip) +anim.set_back_color(0x2222AA) +var pulse = animate.pulse(0xFF4444, 2, 1) +var osc1 = animate.oscillator(-3, 26, 5000, animate.COSINE) +osc1.set_cb(pulse, pulse.set_pos) + +anim.add_animator(osc1) +anim.add_painter(pulse) + +# animate color of pulse +var palette = animate.palette(animate.PALETTE_RAINBOW_WHITE, 30000) +palette.set_cb(pulse, pulse.set_color) +anim.add_animator(palette) + +anim.start() diff --git a/tasmota/berry/animate_demo/leds_animation.be b/tasmota/berry/animate_demo/leds_animation.be new file mode 100644 index 000000000..96f4d47ea --- /dev/null +++ b/tasmota/berry/animate_demo/leds_animation.be @@ -0,0 +1,173 @@ +################################################################################# +# Web UI for Leds animation +# +################################################################################# + +var leds_animation = module('leds_animation') + +################################################################################# +# Leds_animation_UI +# +# WebUI for the Leds animation +################################################################################# +class Leds_animation_UI + + def init() + tasmota.add_driver(self) + end + + # create a method for adding a button to the main menu + # the button 'Leds animation' redirects to '/leds_anim?' + def web_add_button() + import webserver + webserver.content_send( + "

") + end + + #- ---------------------------------------------------------------------- -# + #- Show page to migrate to factory layout + single OTA + #- ---------------------------------------------------------------------- -# + def show_migrate_to_factory(p) + # display ota partitions + import webserver + import string + + if !self.factory_migrate_eligible(p) return end + + webserver.content_send("
 Migrate to safeboot partition layout 

") + + webserver.content_send("

The `safeboot` layout allows for increased size
of firmware or file-system.

") + webserver.content_send("

Please see Safeboot layout documentation

") + webserver.content_send("

 

") + + webserver.content_send(string.format("

Step 1: %s

", self.display_step_state(self.test_step_1(p), "boot on `app1`"))) + webserver.content_send(string.format("

Step 2: %s

", self.display_step_state(self.test_step_2(p), "flash `safeboot` to `app0`"))) + webserver.content_send(string.format("

Step 3: %s

", self.display_step_state(self.test_step_3(p), "change partition map"))) + webserver.content_send(string.format("

Step 4: %s

", self.display_step_state(self.test_step_4(p), "flash final firmware"))) + + webserver.content_send("
") + var ota_url = tasmota.cmd("OtaUrl").find("OtaUrl", "") + webserver.content_send(string.format("
OTA Url

", + ota_url)) + + import persist + var safeboot_url = persist.find("safeboot_url", self.default_safeboot_URL()) + webserver.content_send(string.format("
SAFEBOOT Url (don't change)
", + safeboot_url)) + + webserver.content_send("

") + + webserver.content_send("

") + end + + ####################################################################### + # Show background colors + ####################################################################### + def show_background_color() + import webserver + var back_color = 0xFF8800 + var back_anim_time = 5.0 + + + webserver.content_send("
 Background  " + "
") + + # webserver.content_send(f"") + # webserver.content_send("
") + webserver.content_send("") + webserver.content_send(f"") + webserver.content_send("

") + + webserver.content_send("") + webserver.content_send("") + webserver.content_send(f"" + "" + "" + "") + webserver.content_send("" + "" + "" + "") + webserver.content_send("" + "" + "" + "") + webserver.content_send("" + "" + "" + "") + webserver.content_send("
Static
Palette1
Palette1
Palette1
") + webserver.content_send("

" + "

") + end + + ####################################################################### + # Show main config + ####################################################################### + def show_main_config() + import webserver + var leds_anim_enabled = true + var leds_size = 25 + + webserver.content_send("
 Leds configuration  " + "

Check the Leds animation documentation.

" + "
") + + # checkbox for Matter enable + var leds_anim_enabled_checked = leds_anim_enabled ? 'checked' : '' + webserver.content_send(f"

") + webserver.content_send("

") + + webserver.content_send("") + webserver.content_send(f"") + + webserver.content_send("

" + "

") + end + + ####################################################################### + # Display the complete page + ####################################################################### + def page_view() + import webserver + if !webserver.check_privileged_access() return nil end + + webserver.content_start("Leds animation") #- title of the web page -# + webserver.content_send_style() #- send standard Tasmota styles -# + + self.show_main_config() + self.show_background_color() + webserver.content_button(webserver.BUTTON_MANAGEMENT) #- button back to management page -# + + webserver.content_stop() #- end of web page -# + end + + #- ---------------------------------------------------------------------- -# + # respond to web_add_handler() event to register web listeners + #- ---------------------------------------------------------------------- -# + #- this is called at Tasmota start-up, as soon as Wifi/Eth is up and web server running -# + def web_add_handler() + import webserver + #- we need to register a closure, not just a function, that captures the current instance -# + webserver.on("/leds_anim", / -> self.page_view(), webserver.HTTP_GET) + webserver.on("/leds_anim", / -> self.page_ctl(), webserver.HTTP_POST) + end +end +leds_animation.Leds_animation_UI = Leds_animation_UI + + +#- create and register driver in Tasmota -# +if tasmota + var ui = leds_animation.Leds_animation_UI() + ## can be removed if put in 'autoexec.bat' + ui.web_add_handler() +end + +return leds_animation + +#- Example + +import leds_animation + +-# diff --git a/tasmota/berry/animate_demo/leds_blend_demo.be b/tasmota/berry/animate_demo/leds_blend_demo.be new file mode 100644 index 000000000..88596e276 --- /dev/null +++ b/tasmota/berry/animate_demo/leds_blend_demo.be @@ -0,0 +1,37 @@ +# test blending + +import animate + +var LEDS_LENGTH = 25 +var strip +var front, back +var bri + +strip = Leds(LEDS_LENGTH, gpio.pin(gpio.WS2812,0)) +bri = 70 + +back = bytes().resize(LEDS_LENGTH * 4) +front = bytes().resize(LEDS_LENGTH * 4) +strip.clear_to(0x442211) +strip.show() + +var back = animate.frame(LEDS_LENGTH) +var front = animate.frame(LEDS_LENGTH) +back.fill_pixels(0xFF2200, 80) +for i:0..24 + front.set_pixel(i, 0, 255, 0, (i*255)/24) +end +back.blend_pixels(back, front) + +print("front=", front.tohex()) +print("back =", back.tohex()) +var pixels_buffer = strip.pixels_buffer() +print("pixs =", pixels_buffer.tohex()) +back.paste_pixels(pixels_buffer, bri, true) +strip.dirty() +strip.show() + +## Output: +# front= 00FF000000FF000A00FF001500FF001F00FF002A00FF003500FF003F00FF004A00FF005500FF005F00FF006A00FF007400FF007F00FF008A00FF009400FF009F00FF00AA00FF00B400FF00BF00FF00C900FF00D400FF00DF00FF00E900FF00F400FF00FF +# back = 0022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF000022FF00 +# pixs = 020701020701020701020701020701020701020701020701020701020701020701020701020701020701020701020701020701020701020701020701020701020701020701020701020701 diff --git a/tasmota/berry/emulator/Leds_frame.be b/tasmota/berry/emulator/Leds_frame.be new file mode 100644 index 000000000..eb3f520ee --- /dev/null +++ b/tasmota/berry/emulator/Leds_frame.be @@ -0,0 +1,42 @@ +# Leds_frame + +class Leds_frame + var pixel_size + + def init() + end + + def blend(color_a, color_b, alpha) + var r = (color_a >> 16) & 0xFF + var g = (color_a >> 8) & 0xFF + var b = (color_a ) & 0xFF + var r2 = (color_b >> 16) & 0xFF + var g2 = (color_b >> 8) & 0xFF + var b2 = (color_b ) & 0xFF + var r3 = tasmota.scale_uint(alpha, 0, 255, r2, r) + var g3 = tasmota.scale_uint(alpha, 0, 255, g2, g) + var b3 = tasmota.scale_uint(alpha, 0, 255, b2, b) + var rgb = (r3 << 16) | (g3 << 8) | b3 + return rgb + end + +end + +return Leds_frame + +# /* @const_object_info_begin +# class be_class_Leds_frame (scope: global, name: Leds_frame, super:be_class_bytes, strings: weak) { +# pixel_size, var + +# init, closure(Leds_frame_be_init_closure) + +# item, closure(Leds_frame_be_item_closure) +# setitem, closure(Leds_frame_be_setitem_closure) +# set_pixel, closure(Leds_frame_be_set_pixel_closure) + +# // the following are on buffers +# blend, static_func(be_leds_blend) +# fill_pixels, func(be_leds_fill_pixels) +# blend_pixels, func(be_leds_blend_pixels) +# paste_pixels, func(be_leds_paste_pixels) +# } \ No newline at end of file diff --git a/tasmota/berry/leds/leds_animate_demo_palette_background.be b/tasmota/berry/leds/leds_animate_demo_palette_background.be deleted file mode 100644 index 1e1681000..000000000 --- a/tasmota/berry/leds/leds_animate_demo_palette_background.be +++ /dev/null @@ -1,51 +0,0 @@ -# -# Example for M5Stack Led Matrix -# 5 x 5 WS2812 -# -import animate -class Background_demo : Leds_animator - static var PALETTE_STANDARD_TAG = bytes( - "40" "FF0000" # red - "40" "FFA500" # orange - "40" "FFFF00" # yellow - "40" "00EE00" # green - "40" "0000FF" # blue - "40" "4B00FF" # indigo - "40" "FF82FF" # violet - "00" "FF0000" # red - ) - - static var PALETTE_RAINBOW_WHITE = bytes( - "50" "FF0000" # red - "30" "FF0000" # red - "50" "FFA500" # orange - "30" "FFA500" # orange - "50" "FFFF00" # yellow - "30" "FFFF00" # yellow - "50" "00FF00" # green - "30" "00FF00" # green - "50" "0000FF" # blue - "30" "0000FF" # blue - "50" "FF00FF" # indigo - "30" "FF00FF" # indigo - "50" "FFFFFF" # white - "30" "FFFFFF" # white - "00" "FF0000" # red - ) - - # duration in seconds - def init(strip, duration) - import animate - super(self).init(strip) - # var pal = animate.palette(self.PALETTE_STANDARD_TAG, duration) - var pal = animate.palette(self.PALETTE_RAINBOW_WHITE, duration) - self.add_background_animator(pal) - end - - def animate() - end -end - -var strip = Leds(5 * 5, gpio.pin(gpio.WS2812, 0)) -var r = Background_demo(strip, 20) -r.start() diff --git a/tasmota/berry/leds/rainbow.be b/tasmota/berry/leds/rainbow.be deleted file mode 100644 index d29720c93..000000000 --- a/tasmota/berry/leds/rainbow.be +++ /dev/null @@ -1,185 +0,0 @@ -# simple Rainbow animator - -#- -# Ex: if WS2812 configured to WS2812 - channel 2 - -var strip = neopixelbus(25, gpio.pin(gpio.WS2812, 1)) -rainbow = Rainbow(strip) -rainbow.start() - --# - -import animate - -class Rainbow : Leds_animator - var cur_offset # current offset in the palette - static palette = [ 0xFF0000, #- red -# - 0xFFA500, #- orange -# - 0xFFFF00, #- yellow -# - 0x008800, #- green -# - 0x0000FF, #- blue -# - 0x4B0082, #- indigo -# - 0xEE82EE, #- violet -# - ] - - def init(strip, duration) - import animate - super(self).init(strip) - self.cur_offset = 0 - # add an animator to change `self.cur_offset` to each value of the palette - self.add_anim(animate.rotate(def(v) self.cur_offset = v end, 0, size(self.palette), int(duration * 1000))) - end - - def animate() - # move instance variables to registers to avoid GETMBR inside the loop - var cur_offset = self.cur_offset - var modulus = size(self.palette) - var palette = self.palette - var strip = self.strip - var bri = self.bri - var set_pixel_color = strip.set_pixel_color - - var i = 0 - while i < self.pixel_count # doing a loop rather than a `for` prevents from allocating a new object - var col = palette[(cur_offset + i) % modulus] - set_pixel_color(strip, i, col, bri) # simulate the method call without GETMET - i += 1 - end - strip.show() - end - -end - -#- - -var strip = Leds.matrix(5,5, gpio.pin(gpio.WS2812, 1)) -var r = Rainbow(strip, 1.0) -r.start() - --# - -class Rainbow_stripes : Leds_animator - var cur_offset # current offset in the palette - static palette = [ 0xFF0000, #- red -# - 0xFFA500, #- orange -# - 0xFFFF00, #- yellow -# - 0x008800, #- green -# - 0x0000FF, #- blue -# - 0x4B0082, #- indigo -# - 0xEE82EE, #- violet -# - ] - - def init(strip, duration) - import animate - super(self).init(strip) - self.cur_offset = 0 - # add an animator to change `self.cur_offset` to each value of the palette - self.add_anim(animate.rotate(def(v) self.cur_offset = v end, 0, size(self.palette), int(duration * 1000))) - end - - def animate() - # move instance variables to registers to avoid GETMBR inside the loop - var cur_offset = self.cur_offset - var modulus = size(self.palette) - var palette = self.palette - var strip = self.strip - var bri = self.bri - var set_matrix_pixel_color = strip.set_matrix_pixel_color - var h = self.strip.h - var w = self.strip.w - - var y = 0 - while y < h - var x = 0 - var col = palette[(cur_offset + y) % modulus] - while x < w - set_matrix_pixel_color(strip, x, y, col, bri) # simulate the method call without GETMET - x += 1 - end - y += 1 - end - strip.show() - end - -end - -#- - -var strip = Leds.matrix(5,5, gpio.pin(gpio.WS2812, 1)) -var r = Rainbow_stripes(strip, 0.5) -r.start() - --# - -class Round : Leds_animator - var cur_val - var min_val, max_val - var incr_val - var h - - def init(strip, glow_duration, color_duration) - import animate - super(self).init(strip) - self.cur_val = 5 << 8 - self.h = 0 # start with hue = 0 (red) - # add animator for color over 30 colors - self.add_anim(animate.rotate(def(h) self.h = h end, 0, 359, int(color_duration * 1000))) - self.add_anim(animate.back_forth(def(v) self.cur_val = v end, 2 << 8, 6 << 8, int(glow_duration * 1000))) - end - - def animate() - # move instance variables to registers to avoid GETMBR inside the loop - var strip = self.strip - var bri = self.bri - var set_matrix_pixel_color = strip.set_matrix_pixel_color - var h = self.strip.h - var w = self.strip.w - var ch = h / 2 - var cw = w / 2 - var col_ref = tasmota.hs2rgb(self.h) - - var y = 0 - while y < h - var x = 0 - while x < w - var col = col_ref - var dist = self.fast_sqrt_int( ((y - ch)*(y - ch) + (x - cw)*(x - cw)) << 16) - var rel_bri = tasmota.scale_uint(dist, 0, self.cur_val, bri, 0) - set_matrix_pixel_color(strip, x, y, col, rel_bri) # simulate the method call without GETMET - x += 1 - end - y += 1 - end - strip.show() - end - - # https://stackoverflow.com/questions/34187171/fast-integer-square-root-approximation - static def fast_sqrt_int(val) - var a, b - - if val < 2 return val end - - a = 1255 # starting point is relatively unimportant - - b = val / a; a = (a+b) /2; - b = val / a; a = (a+b) /2; - b = val / a; a = (a+b) /2; - b = val / a; a = (a+b) /2; - b = val / a; a = (a+b) /2; - b = val / a; a = (a+b) /2; - if (val < 20000) - b = val / a; a = (a+b) /2; - b = val / a; a = (a+b) /2; - end - - return a - end -end - -#- - -var strip = Leds.matrix(5,5, gpio.pin(gpio.WS2812, 1)) -var r = Round(strip, 2, 30) -r.start() - --# diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino index 320023b34..c4df2e318 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino @@ -427,6 +427,61 @@ extern "C" { be_raise(vm, kTypeError, nullptr); } + /* + Implements the 5-order polynomial approximation to sin(x). + @param i angle (with 2^15 units/circle) + @return 16 bit fixed point Sine value (4.12) (ie: +4096 = +1 & -4096 = -1) + + The result is accurate to within +- 1 count. ie: +/-2.44e-4. + */ + int16_t fpsin(int16_t i) + { + /* Convert (signed) input to a value between 0 and 8192. (8192 is pi/2, which is the region of the curve fit). */ + /* ------------------------------------------------------------------- */ + i <<= 1; + uint8_t c = i<0; //set carry for output pos/neg + + if(i == (i|0x4000)) // flip input value to corresponding value in range [0..8192) + i = (1<<15) - i; + i = (i & 0x7FFF) >> 1; + /* ------------------------------------------------------------------- */ + + /* The following section implements the formula: + = y * 2^-n * ( A1 - 2^(q-p)* y * 2^-n * y * 2^-n * [B1 - 2^-r * y * 2^-n * C1 * y]) * 2^(a-q) + Where the constants are defined as follows: + */ + // enum {A1=3370945099UL, B1=2746362156UL, C1=292421UL}; + // enum {n=13, p=32, q=31, r=3, a=12}; + + uint32_t y = (292421UL*((uint32_t)i))>>13; + y = 2746362156UL - (((uint32_t)i*y)>>3); + y = (uint32_t)i * (y>>13); + y = (uint32_t)i * (y>>13); + y = 3370945099UL - (y>>(32-31)); + y = (uint32_t)i * (y>>13); + y = (y+(1UL<<(31-12-1)))>>(31-12); // Rounding + + return c ? -y : y; + } + + // Berry: tasmota.sine_int(int) -> int + // + // Input: 8192 is pi/2 + // Output: -4096 is -1, 4096 is +1 + // + // https://www.nullhardware.com/blog/fixed-point-sine-and-cosine-for-embedded-systems/ + int32_t l_sineint(struct bvm *vm); + int32_t l_sineint(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 1 && be_isint(vm, 1)) { + int32_t val = be_toint(vm, 1); + + be_pushint(vm, fpsin(val)); + be_return(vm); + } + be_raise(vm, kTypeError, nullptr); + } + int32_t l_respCmnd(bvm *vm); int32_t l_respCmnd(bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments From d6bf19190f3ddad1a338e92f97f0ab2922a973bd Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 14 Dec 2023 23:09:40 +0100 Subject: [PATCH 007/303] Small fixes to animate module (#20238) --- .../berry_tasmota/src/be_animate_module.c | 3 +- .../src/embedded/animate_0_core.be | 12 +- .../src/solidify/solidified_animate_0_core.h | 148 +++++++++--------- .../animate_demo_palette_background.be | 2 +- .../berry/animate_demo/animate_demo_pulse.be | 2 +- 5 files changed, 83 insertions(+), 84 deletions(-) diff --git a/lib/libesp32/berry_tasmota/src/be_animate_module.c b/lib/libesp32/berry_tasmota/src/be_animate_module.c index b21102e8f..688585f06 100644 --- a/lib/libesp32/berry_tasmota/src/be_animate_module.c +++ b/lib/libesp32/berry_tasmota/src/be_animate_module.c @@ -111,8 +111,7 @@ module animate (scope: global, strings: weak) { PALETTE_STANDARD_VAL, comptr(PALETTE_STANDARD_VAL) PALETTE_SATURATED_TAG, comptr(PALETTE_SATURATED_TAG) - (), class(be_class_Animate_core) - core, class(be_class_Animate_core) // alias + core, class(be_class_Animate_core) animator, class(be_class_Animate_animator) frame, class(be_class_Leds_frame) pulse, class(be_class_Animate_pulse) diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be b/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be index f7bdf2e52..5e91278fe 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be +++ b/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be @@ -22,8 +22,8 @@ class Animate_core static var FAST_LOOP_MIN = 20 var fast_loop_next # next time-stamp for fast_loop # cb for animation - var animate_object # object called at each tick - var animate_method # method of object called at each tick + var obj # object called at each tick + var mth # method of object called at each tick # frame ojects var frame # Leds_frame frame object var layer # Leds_frame for layer on top of frame @@ -101,8 +101,8 @@ class Animate_core end def set_cb(obj, method) - self.animate_object = obj - self.animate_method = method + self.obj = obj + self.mth = method end def fast_loop() @@ -136,8 +136,8 @@ class Animate_core i += 1 end # tirgger animate and display - var obj = self.animate_object - var mth = self.animate_method + var obj = self.obj + var mth = self.mth if (obj && mth) mth(obj) end diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h index f507d4144..d124cc5b3 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h @@ -164,33 +164,6 @@ be_local_closure(Animate_core_animate, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: get_bri -********************************************************************/ -be_local_closure(Animate_core_get_bri, /* name */ - be_nested_proto( - 3, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(bri), - }), - be_str_weak(get_bri), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x80040400, // 0001 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: set_bri ********************************************************************/ @@ -218,33 +191,6 @@ be_local_closure(Animate_core_set_bri, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: set_back_color -********************************************************************/ -be_local_closure(Animate_core_set_back_color, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(back_color), - }), - be_str_weak(set_back_color), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: stop ********************************************************************/ @@ -296,6 +242,33 @@ be_local_closure(Animate_core_stop, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: set_back_color +********************************************************************/ +be_local_closure(Animate_core_set_back_color, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(back_color), + }), + be_str_weak(set_back_color), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: set_cb ********************************************************************/ @@ -310,8 +283,8 @@ be_local_closure(Animate_core_set_cb, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(animate_object), - /* K1 */ be_nested_str_weak(animate_method), + /* K0 */ be_nested_str_weak(obj), + /* K1 */ be_nested_str_weak(mth), }), be_str_weak(set_cb), &be_const_str_solidified, @@ -450,6 +423,33 @@ be_local_closure(Animate_core_add_painter, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: get_bri +********************************************************************/ +be_local_closure(Animate_core_get_bri, /* name */ + be_nested_proto( + 3, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(bri), + }), + be_str_weak(get_bri), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x80040400, // 0001 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: fast_loop ********************************************************************/ @@ -484,8 +484,8 @@ be_local_closure(Animate_core_fast_loop, /* name */ /* K17 */ be_const_int(-16777216), /* K18 */ be_nested_str_weak(paint), /* K19 */ be_nested_str_weak(blend_pixels), - /* K20 */ be_nested_str_weak(animate_object), - /* K21 */ be_nested_str_weak(animate_method), + /* K20 */ be_nested_str_weak(obj), + /* K21 */ be_nested_str_weak(mth), /* K22 */ be_nested_str_weak(paste_pixels), /* K23 */ be_nested_str_weak(pixels_buffer), /* K24 */ be_nested_str_weak(bri), @@ -644,31 +644,31 @@ be_local_class(Animate_core, NULL, be_nested_map(28, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(bri, 23), be_const_var(2) }, + { be_const_key_weak(bri, 8), be_const_var(2) }, { be_const_key_weak(remove, -1), be_const_closure(Animate_core_remove_closure) }, - { be_const_key_weak(start, 21), be_const_closure(Animate_core_start_closure) }, + { be_const_key_weak(start, 11), be_const_closure(Animate_core_start_closure) }, { be_const_key_weak(fast_loop, -1), be_const_closure(Animate_core_fast_loop_closure) }, { be_const_key_weak(add_animator, -1), be_const_closure(Animate_core_add_animator_closure) }, - { be_const_key_weak(FAST_LOOP_MIN, 8), be_const_int(20) }, - { be_const_key_weak(animate, -1), be_const_closure(Animate_core_animate_closure) }, + { be_const_key_weak(FAST_LOOP_MIN, 9), be_const_int(20) }, + { be_const_key_weak(obj, -1), be_const_var(8) }, { be_const_key_weak(pixel_count, -1), be_const_var(1) }, + { be_const_key_weak(animate, -1), be_const_closure(Animate_core_animate_closure) }, { be_const_key_weak(animators, -1), be_const_var(4) }, - { be_const_key_weak(back_color, 11), be_const_var(12) }, - { be_const_key_weak(fast_loop_cb, 12), be_const_var(6) }, + { be_const_key_weak(fast_loop_cb, -1), be_const_var(6) }, + { be_const_key_weak(get_bri, 24), be_const_closure(Animate_core_get_bri_closure) }, + { be_const_key_weak(back_color, 13), be_const_var(12) }, { be_const_key_weak(frame, -1), be_const_var(10) }, - { be_const_key_weak(animate_object, -1), be_const_var(8) }, - { be_const_key_weak(stop, -1), be_const_closure(Animate_core_stop_closure) }, + { be_const_key_weak(set_cb, 23), be_const_closure(Animate_core_set_cb_closure) }, { be_const_key_weak(init, -1), be_const_closure(Animate_core_init_closure) }, - { be_const_key_weak(set_cb, 13), be_const_closure(Animate_core_set_cb_closure) }, - { be_const_key_weak(running, -1), be_const_var(3) }, - { be_const_key_weak(strip, 15), be_const_var(0) }, + { be_const_key_weak(running, 21), be_const_var(3) }, + { be_const_key_weak(strip, 14), be_const_var(0) }, { be_const_key_weak(fast_loop_next, -1), be_const_var(7) }, - { be_const_key_weak(set_back_color, 14), be_const_closure(Animate_core_set_back_color_closure) }, + { be_const_key_weak(set_back_color, 15), be_const_closure(Animate_core_set_back_color_closure) }, { be_const_key_weak(add_painter, -1), be_const_closure(Animate_core_add_painter_closure) }, - { be_const_key_weak(set_bri, 24), be_const_closure(Animate_core_set_bri_closure) }, - { be_const_key_weak(layer, 9), be_const_var(11) }, - { be_const_key_weak(animate_method, 6), be_const_var(9) }, - { be_const_key_weak(get_bri, -1), be_const_closure(Animate_core_get_bri_closure) }, + { be_const_key_weak(mth, -1), be_const_var(9) }, + { be_const_key_weak(layer, 12), be_const_var(11) }, + { be_const_key_weak(stop, -1), be_const_closure(Animate_core_stop_closure) }, + { be_const_key_weak(set_bri, -1), be_const_closure(Animate_core_set_bri_closure) }, { be_const_key_weak(painters, -1), be_const_var(5) }, { be_const_key_weak(clear, 3), be_const_closure(Animate_core_clear_closure) }, { be_const_key_weak(add_background_animator, 2), be_const_closure(Animate_core_add_background_animator_closure) }, diff --git a/tasmota/berry/animate_demo/animate_demo_palette_background.be b/tasmota/berry/animate_demo/animate_demo_palette_background.be index 03648b419..6c314e42f 100644 --- a/tasmota/berry/animate_demo/animate_demo_palette_background.be +++ b/tasmota/berry/animate_demo/animate_demo_palette_background.be @@ -6,6 +6,6 @@ import animate var duration = 10000 var strip = Leds(5 * 5, gpio.pin(gpio.WS2812, 0)) -var anim = animate(strip) +var anim = animate.core(strip) anim.add_background_animator(animate.palette(animate.PALETTE_RAINBOW_WHITE, duration)) anim.start() diff --git a/tasmota/berry/animate_demo/animate_demo_pulse.be b/tasmota/berry/animate_demo/animate_demo_pulse.be index 0a2b6dd40..09b075683 100644 --- a/tasmota/berry/animate_demo/animate_demo_pulse.be +++ b/tasmota/berry/animate_demo/animate_demo_pulse.be @@ -6,7 +6,7 @@ import animate var duration = 10000 var strip = Leds(5 * 5, gpio.pin(gpio.WS2812, 0)) -var anim = animate(strip) +var anim = animate.core(strip) anim.set_back_color(0x2222AA) var pulse = animate.pulse(0xFF4444, 2, 1) var osc1 = animate.oscillator(-3, 26, 5000, animate.COSINE) From d10b30ef5565b162b0fe2dee020a9723e59eac0d Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Sat, 16 Dec 2023 14:40:18 +0100 Subject: [PATCH 008/303] Update NeoPool register desc (#20245) --- .../tasmota_xsns_sensor/xsns_83_neopool.ino | 326 ++++++++---------- 1 file changed, 152 insertions(+), 174 deletions(-) diff --git a/tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino b/tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino index ac4901c4f..18b30b914 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino @@ -1,7 +1,7 @@ /* xsns_83_neopool.ino - Sugar Valley NeoPool Control System Modbus support for Tasmota - Copyright (C) 2022 Norbert Richter + Copyright (C) 2023 Norbert Richter 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 @@ -31,10 +31,7 @@ * Bayrol * Hay * - * Sugar Valley RS485 connector inside (DISPLAY/WIFI/EXTERN) - * pins (from top to bottom): - * - * RS485 MODBUS + * Sugar Valley RS485 connector inside (DISPLAY/WIFI/EXTERN) pins (from top to bottom): * ___ * 1 |* |- +12V (internal power supply) * 2 |* |- (not connected) @@ -42,10 +39,13 @@ * 4 |* |- Modbus B- * 5 |*__|- Modbus GND * - * RS485 Parameter: 19200 Baud / 1 Stopbit / Parity None + * Parameter: 19200 Baud / 1 Stopbit / Parity None + * Protocol: Modbus RTU + * NeoPool controller is Modbus server (formerly known as slave) + * Tasmota is Modbus client (formerly known as master) * - * Channel connector DISPLAY is useless as long as the internal display is also connect, - * use WIFI or EXTERN instead. + * Connector DISPLAY is useless as long as the internal display is also connected to the + * second DISPLAY connector. Use WIFI or EXTERN. * * Hardware serial will be selected if GPIO1 = [NeoPool Rx] and GPIO3 = [NeoPool Tx] \*********************************************************************************************/ @@ -81,62 +81,62 @@ * (see https://downloads.vodnici.net/uploads/wpforo/attachments/69/171-Modbus-registers.pdf) \*********************************************************************************************/ enum NeoPoolRegister { - // addr Unit Description + // addr Unit Description - "!" indicates register is not officially documented // ------ ------ ------------------------------------------------------------ - // MODBUS page (0x00xx) - undocumented - for internal use - MBF_POWER_MODULE_VERSION = 0x0002, // 0x0002 undocumented - power module version (MSB=Major, LSB=Minor) - MBF_POWER_MODULE_NODEID = 0x0004, // 0x0004 undocumented - power module Node ID (6 register 0x0004 - 0x0009) - MBF_POWER_MODULE_REGISTER = 0x000C, // 0x000C undocumented - Writing an address in this register causes the power module register address to be read out into MBF_POWER_MODULE_DATA, see MBF_POWER_MODULE_REG_* - MBF_POWER_MODULE_DATA = 0x000D, // 0x000D undocumented - power module data as requested in MBF_POWER_MODULE_REGISTER - MBF_VOLT_24_36 = 0x0022, // 0x0022* undocumented - Current 24-36V line in mV - MBF_VOLT_12 = 0x0023, // 0x0023* undocumented - Current 12V line in mV - MBF_VOLT_5 = 0x006A, // 0x006A* undocumented - 5V line in mV / 0,62069 - MBF_AMP_4_20_MICRO = 0x0072, // 0x0072* undocumented - 2-40mA line in µA * 10 (1=0,01mA) + // MODBUS page (0x00xx) - Manages general configuration of the box. This page is reserved for internal purposes + MBF_POWER_MODULE_VERSION = 0x0002, // 0x0002 ! Power module version (MSB=Major, LSB=Minor) + MBF_POWER_MODULE_NODEID = 0x0004, // 0x0004 ! Power module Node ID (6 register 0x0004 - 0x0009) + MBF_POWER_MODULE_REGISTER = 0x000C, // 0x000C ! Writing an address in this register causes the power module register address to be read out into MBF_POWER_MODULE_DATA, see MBF_POWER_MODULE_REG_* + MBF_POWER_MODULE_DATA = 0x000D, // 0x000D ! power module data as requested in MBF_POWER_MODULE_REGISTER + MBF_VOLT_24_36 = 0x0022, // 0x0022* ! Current 24-36V line in mV + MBF_VOLT_12 = 0x0023, // 0x0023* ! Current 12V line in mV + MBF_VOLT_5 = 0x006A, // 0x006A* ! 5V line in mV / 0,62069 + MBF_AMP_4_20_MICRO = 0x0072, // 0x0072* ! 2-40mA line in µA * 10 (1=0,01mA) - // MEASURE page (0x01xx) - MBF_ION_CURRENT = 0x0100, // 0x0100* Current measured in the ionization system - MBF_HIDRO_CURRENT, // 0x0101* Intensity level currently measured in the hydrolysissystem - MBF_MEASURE_PH, // 0x0102* ph Level measured in hundredths (700 = 7.00) - MBF_MEASURE_RX, // 0x0103* mV Redox level in mV - MBF_MEASURE_CL, // 0x0104* ppm Level measured in hundredths of chlorine ppm (100 = 1.00 ppm) - MBF_MEASURE_CONDUCTIVITY, // 0x0105* % Level of conductivity measured in the water. - MBF_MEASURE_TEMPERATURE, // 0x0106* °C Water temperature sensor (100 = 10.0°C) - MBF_PH_STATUS, // 0x0107* mask Status of the module control pH + // MEASURE page (0x01xx) - Contains the different measurement information including hydrolysis current, pH level, redox level, etc. + MBF_ION_CURRENT = 0x0100, // 0x0100* Ionization level measured + MBF_HIDRO_CURRENT, // 0x0101* Hydrolysis intensity level + MBF_MEASURE_PH, // 0x0102* ph pH level measured in 1/100 (700 = 7.00) + MBF_MEASURE_RX, // 0x0103* mV Redox level measured in mV + MBF_MEASURE_CL, // 0x0104* ppm Chlorine level measured in 1/100 ppm (100 = 1.00 ppm) + MBF_MEASURE_CONDUCTIVITY, // 0x0105* % Conductivity level measured in % + MBF_MEASURE_TEMPERATURE, // 0x0106* °C Temperature sensor measured in 1/10° C (100 = 10.0°C) + MBF_PH_STATUS, // 0x0107* mask Status of the pH-module MBF_RX_STATUS, // 0x0108* mask Status of the Rx-module MBF_CL_STATUS, // 0x0109* mask Status of the Chlorine-module MBF_CD_STATUS, // 0x010A* mask Status of the Conductivity-module MBF_ION_STATUS = 0x010C, // 0x010C* mask Status of the Ionization-module MBF_HIDRO_STATUS, // 0x010D* mask Status of the Hydrolysis-module - MBF_RELAY_STATE, // 0x010E* mask Status of each configurable relays + MBF_RELAY_STATE, // 0x010E* mask Status of each configurable relay MBF_HIDRO_SWITCH_VALUE, // 0x010F* INTERNAL - contains the opening of the hydrolysis PWM. - MBF_NOTIFICATION, // 0x0110* mask Reports whether a page of properties has changed since the last time it was consulted. - MBF_HIDRO_VOLTAGE, // 0x0111 Reports on the stress applied to the hydrolysis cell. This register, together with that of MBF_HIDRO_CURRENT allows extrapolating the salinity of the water. + MBF_NOTIFICATION, // 0x0110* mask Bit field that informs whether a property page has changed since the last time it was queried. (see MBMSK_NOTIF_*). This register makes it possible to refresh the content of the registers maintained by a modbus master in an optimized way, without the need to reread all registers periodically, but only those on a page that has been changed. + MBF_HIDRO_VOLTAGE, // 0x0111 The voltage applied to the hydrolysis cell. This register, together with that of MBF_HIDRO_CURRENT allows extrapolation of water salinity. - // GLOBAL page (0x02xx) - MBF_CELL_RUNTIME_LOW = 0x0206, // 0x0206* undocumented - cell runtime (32 bit) - low word - MBF_CELL_RUNTIME_HIGH, // 0x0207* undocumented - cell runtime (32 bit) - high word - MBF_CELL_RUNTIME_PART_LOW, // 0x0208* undocumented - cell part runtime (32 bit) - low word - MBF_CELL_RUNTIME_PART_HIGH, // 0x0209* undocumented - cell part runtime (32 bit) - high word - MBF_CELL_BOOST = 0x020C, // 0x020C* mask undocumented - 0x0000 = Boost Off, 0x05A0 = Boost with redox ctrl, 0x85A0 = Boost without redox ctrl - MBF_CELL_RUNTIME_POLA_LOW = 0x0214, // 0x0214* undocumented - cell runtime polarity A (32 bit) - low word - MBF_CELL_RUNTIME_POLA_HIGH, // 0x0215* undocumented - cell runtime polarity A (32 bit) - high word - MBF_CELL_RUNTIME_POLB_LOW, // 0x0216* undocumented - cell runtime polarity B (32 bit) - low word - MBF_CELL_RUNTIME_POLB_HIGH, // 0x0217* undocumented - cell runtime polarity B (32 bit) - high word - MBF_CELL_RUNTIME_POL_CHANGES_LOW, // 0x0218* undocumented - cell runtime polarity changes (32 bit) - low word - MBF_CELL_RUNTIME_POL_CHANGES_HIGH, // 0x0219* undocumented - cell runtime polarity changes (32 bit) - high word - MBF_HIDRO_MODULE_VERSION = 0x0280, // 0x0280 undocumented - Hydrolysis module version - MBF_HIDRO_MODULE_CONNECTIVITY = 0x0281, // 0x0281 undocumented - Hydrolysis module connection quality (in myriad: 0..10000) - MBF_SET_COUNTDOWN_KEY_AUX_OFF = 0x0287, // 0x0287 mask undocumented - switch AUX1-4 OFF - only for AUX which is assigned as AUX and set to MBV_PAR_CTIMER_COUNTDOWN_KEY_* mode - see MBV_PAR_CTIMER_COUNTDOWN_KEY_AUX* - MBF_SET_COUNTDOWN_KEY_AUX_ON, // 0x0288 mask undocumented - switch AUX1-4 ON - only for AUX which is assigned as AUX and set to MBV_PAR_CTIMER_COUNTDOWN_KEY_* mode - see MBV_PAR_CTIMER_COUNTDOWN_KEY_AUX* - MBF_SET_MANUAL_CTRL, // 0x0289 undocumented - write a 1 before manual control MBF_RELAY_STATE, after done write 0 and do MBF_EXEC - MBF_ESCAPE = 0x0297, // 0x0297 undocumented - A write operation to this register is the same as using the ESC button on main screen - clears error - MBF_SAVE_TO_EEPROM = 0x02F0, // 0x02F0 A write operation to this register starts a EEPROM storage operation immediately. During the EEPROM storage procedure, the system may be unresponsive to MODBUS requests. The operation will last always less than 1 second. - MBF_EXEC = 0x02F5, // 0x02F5 undocumented - immediately take over settings - a write operation to this register take over the previous written data + // GLOBAL page (0x02xx) - Contains global information, such as the amount of time that each power unit has been working. + MBF_CELL_RUNTIME_LOW = 0x0206, // 0x0206* ! Cell runtime (32 bit value - low word) + MBF_CELL_RUNTIME_HIGH, // 0x0207* ! Cell runtime (32 bit value - high word) + MBF_CELL_RUNTIME_PART_LOW, // 0x0208* ! Cell part runtime (32 bit value - low word) + MBF_CELL_RUNTIME_PART_HIGH, // 0x0209* ! Cell part runtime (32 bit value - high word) + MBF_CELL_BOOST = 0x020C, // 0x020C* mask ! Boost control (see MBMSK_CELL_BOOST_*) + MBF_CELL_RUNTIME_POLA_LOW = 0x0214, // 0x0214* ! Cell runtime polarity 1 (32 bit value - low word) + MBF_CELL_RUNTIME_POLA_HIGH, // 0x0215* ! Cell runtime polarity 1 (32 bit value - high word) + MBF_CELL_RUNTIME_POLB_LOW, // 0x0216* ! Cell runtime polarity 2 (32 bit value - low word) + MBF_CELL_RUNTIME_POLB_HIGH, // 0x0217* ! Cell runtime polarity 2 (32 bit value - high word) + MBF_CELL_RUNTIME_POL_CHANGES_LOW, // 0x0218* ! Cell runtime polarity change count (32 bit value - low word) + MBF_CELL_RUNTIME_POL_CHANGES_HIGH, // 0x0219* ! Cell runtime polarity change count (32 bit value - high word) + MBF_HIDRO_MODULE_VERSION = 0x0280, // 0x0280 ! Hydrolysis module version + MBF_HIDRO_MODULE_CONNECTIVITY = 0x0281, // 0x0281 ! Hydrolysis module connection quality (in myriad: 0..10000) + MBF_SET_COUNTDOWN_KEY_AUX_OFF = 0x0287, // 0x0287 mask ! switch AUX1-4 OFF - only for AUX which is assigned as AUX and set to MBV_PAR_CTIMER_COUNTDOWN_KEY_* mode - see MBV_PAR_CTIMER_COUNTDOWN_KEY_AUX* + MBF_SET_COUNTDOWN_KEY_AUX_ON, // 0x0288 mask ! switch AUX1-4 ON - only for AUX which is assigned as AUX and set to MBV_PAR_CTIMER_COUNTDOWN_KEY_* mode - see MBV_PAR_CTIMER_COUNTDOWN_KEY_AUX* + MBF_SET_MANUAL_CTRL, // 0x0289 ! write a 1 before manual control MBF_RELAY_STATE, after done write 0 and do MBF_EXEC + MBF_ESCAPE = 0x0297, // 0x0297 ! A write operation to this register is the same as using the ESC button on main screen - clears error + MBF_SAVE_TO_EEPROM = 0x02F0, // 0x02F0 A write operation to this register immediately starts a EEPROM storage operation. During the EEPROM storage procedure, the system may be unresponsive to MODBUS requests. The operation will last always less than 1 second. + MBF_EXEC = 0x02F5, // 0x02F5 ! A write operation to this register immediately take over settings of the previous written data - // FACTORY page (0x03xx) - MBF_PAR_VERSION = 0x0300, // 0x0300* Software version of the PowerBox (unused) + // FACTORY page (0x03xx) - Contains factory data such as calibration parameters for the different power units. + MBF_PAR_VERSION = 0x0300, // 0x0300* Software version of the PowerBox MBF_PAR_MODEL, // 0x0301* mask System model options - MBF_PAR_SERNUM, // 0x0302* Serial number of the PowerBox (unused) + MBF_PAR_SERNUM, // 0x0302* Serial number of the PowerBox MBF_PAR_ION_NOM, // 0x0303* Ionization maximum production level (DO NOT WRITE!) MBF_PAR_HIDRO_NOM = 0x0306, // 0x0306* Hydrolysis maximum production level. (DO NOT WRITE!) If the hydrolysis is set to work in percent mode, this value will be 100. If the hydrolysis module is set to work in g/h production, this module will contain the maximum amount of production in g/h units. (DO NOT WRITE!) MBF_PAR_SAL_AMPS = 0x030A, // 0x030A Current command in regulation for which we are going to measure voltage @@ -147,17 +147,17 @@ enum NeoPoolRegister { MBF_PAR_HIDRO_MAX_PWM_STEP_UP, // 0x0324 This register sets the PWM ramp up of the hydrolysis in pulses per duty cycle. This register makes it possible to adjust the rate at which the power delivered to the cell increases, allowing a gradual rise in power so that the operation of the switching source of the equipment is not saturated. Default 150 MBF_PAR_HIDRO_MAX_PWM_STEP_DOWN, // 0x0325 This register sets the PWM down ramp of the hydrolysis in pulses per duty cycle. This register allows adjusting the rate at which the power delivered to the cell decreases, allowing a gradual drop in power so that the switched source of the equipment is not disconnected due to lack of consumption. This gradual fall must be in accordance with the type of cell used, since said cell stores charge once the current stimulus has ceased. Default 20 - // INSTALLER page (0x04xx) - MBF_PAR_ION_POL0 = 0x0400, // 0x0400 Time in min the team must spend working on positive polarization in copper-silver ionization. - MBF_PAR_ION_POL1, // 0x0401 Time in min the team must spend working on positive polarization in copper-silver ionization. - MBF_PAR_ION_POL2, // 0x0402 Time in min the team must spend working on positive polarization in copper-silver ionization. - MBF_PAR_HIDRO_ION_CAUDAL, // 0x0403 mask Bitmask register regulates the external control mode of ionization, hydrolysis and pumps. - MBF_PAR_HIDRO_MODE, // 0x0404 Regulates the external control mode of hydrolysis from the modules of measure. 0: no control, 1: standard control (on / off), 2: with timed pump - MBF_PAR_HIDRO_POL0, // 0x0405 Time must spend working on positive polarization in hydrolysis / electrolysis. Time is stored in minutes. - MBF_PAR_HIDRO_POL1, // 0x0406 Time must spend working on positive polarization in hydrolysis / electrolysis. Time is stored in minutes. - MBF_PAR_HIDRO_POL2, // 0x0407 Time must spend working on positive polarization in hydrolysis / electrolysis. Time is stored in minutes. - MBF_PAR_TIME_LOW, // 0x0408* System timestamp (32 bit unixtime) - low word - MBF_PAR_TIME_HIGH, // 0x0409* System timestamp (32 bit unixtime) - high word + // INSTALLER page (0x04xx) - Contains a set of configuration registers related to the equipment installation, such as the relays used for each function, the amount of time that each pump must operate, etc. + MBF_PAR_ION_POL0 = 0x0400, // 0x0400 Time in minutes that the equipment must remain working in positive polarization in the copper-silver ionization. + MBF_PAR_ION_POL1, // 0x0401 Time in minutes that the equipment must remain working in negative polarization in the copper-silver ionization. + MBF_PAR_ION_POL2, // 0x0402 Time in minutes that the equipment must remain working in dead time (without delivering power) in the copper-silver ionization. + MBF_PAR_HIDRO_ION_CAUDAL, // 0x0403 mask Bitmask register regulates the external control mode of ionization, hydrolysis and pumps (see MBMSK_HIDRO_ION_CAUDAL_*) + MBF_PAR_HIDRO_MODE, // 0x0404 Regulates the external control mode of hydrolysis from the modules of measure. 0 = no control, 1 = standard control (on / off), 2 = with timed pump + MBF_PAR_HIDRO_POL0, // 0x0405 Time in minutes that the equipment must remain in positive polarization during hydrolysis/electrolysis. + MBF_PAR_HIDRO_POL1, // 0x0406 Time in minutes that the equipment must remain in negative polarization during hydrolysis/electrolysis. + MBF_PAR_HIDRO_POL2, // 0x0407 Time in minutes that the equipment must remain working in dead time (without delivering power) in the hydrolysis/electrolysis. + MBF_PAR_TIME_LOW, // 0x0408* System timestamp as unix timestamp (32 bit value - low word). + MBF_PAR_TIME_HIGH, // 0x0409* System timestamp as unix timestsmp (32 bit value - high word). MBF_PAR_PH_ACID_RELAY_GPIO, // 0x040A* Relay number assigned to the acid pump function (only with pH module). MBF_PAR_PH_BASE_RELAY_GPIO, // 0x040B* Relay number assigned to the base pump function (only with pH module). MBF_PAR_RX_RELAY_GPIO, // 0x040C* Relay number assigned to the Redox level regulation function. If the value is 0, there is no relay assigned, and therefore there is no pump function (ON / OFF should not be displayed) @@ -168,27 +168,27 @@ enum NeoPoolRegister { MBF_PAR_FILT_MODE, // 0x0411* Filtration mode (see MBV_PAR_FILT_*) MBF_PAR_FILT_GPIO, // 0x0412* Relay selected to perform the filtering function (by default it is relay 2). When this value is at zero, there is no relay assigned and therefore it is understood that the equipment does not control the filtration. In this case, the filter option does not appear in the user menu. MBF_PAR_FILT_MANUAL_STATE, // 0x0413 Filtration status in manual mode (on = 1; off = 0) - MBF_PAR_HEATING_MODE, // 0x0414 Heating mode. 0: the equipment is not heated. 1: the equipment is heating. - MBF_PAR_HEATING_GPIO, // 0x0415 Relay selected to perform the heating function (by default it is relay 7). When this value is at zero, there is no relay assigned and therefore it is understood that the equipment does not control the heating. In this case, the filter modes associated with heating will not be displayed. - MBF_PAR_HEATING_TEMP, // 0x0416 Heating setpoint temperature - MBF_PAR_CLIMA_ONOFF, // 0x0417 Activation of the air conditioning mode (0 inactive; 1 active. - MBF_PAR_SMART_TEMP_HIGH, // 0x0418 Superior temperature of the Smart mode - MBF_PAR_SMART_TEMP_LOW, // 0x0419 Lower temperature of the Smart mode - MBF_PAR_SMART_ANTI_FREEZE, // 0x041A Antifreeze mode activated (1) or not (0). This adjustment is only available in the Smart filtration mode. - MBF_PAR_SMART_INTERVAL_REDUCTION, // 0x041B This register is read-only and reports to the outside what percentage (0 to 100%) is being applied to the nominal filtration time. 100% means that the total programmed time is being filtered. - MBF_PAR_INTELLIGENT_TEMP, // 0x041C Setpoint temperature for smart mode - MBF_PAR_INTELLIGENT_FILT_MIN_TIME, // 0x041D Minimum filtration time in minutes - MBF_PAR_INTELLIGENT_BONUS_TIME, // 0x041E Bonus time for the current set of intervals - MBF_PAR_INTELLIGENT_TT_NEXT_INTERVAL, // 0x041F Time to next filtration interval. When it reaches 0 an interval is started and the number of seconds is reloaded for the next interval (2x3600) - MBF_PAR_INTELLIGENT_INTERVALS, // 0x0420 Number of started intervals. When it reaches 12 it is reset to 0 and the bonus time is reloaded with the value of MBF_PAR_INTELLIGENT_FILT_MIN_TIME - MBF_PAR_FILTRATION_STATE, // 0x0421 Filtration function state: 0 is off and 1 is on. The filtration state is regulated according to the MBF_PAR_FILT_MANUAL_STATE register if the filtration mode held in register MBF_PAR_FILT_MODE is set to FILT_MODE_MANUAL (0). + MBF_PAR_HEATING_MODE, // 0x0414 Heating mode: 0 = the equipment is not heated. 1 = the equipment is heating. + MBF_PAR_HEATING_GPIO, // 0x0415 Relay number assigned to perform the heating function (by default it is relay 7). When this value is at zero, there is no relay assigned and therefore it is understood that the equipment does not control the heating. In this case, the filter modes associated with heating will not be displayed. + MBF_PAR_HEATING_TEMP, // 0x0416 Heating mode: Heating setpoint temperature + MBF_PAR_CLIMA_ONOFF, // 0x0417 Activation of the climate mode (0 = inactive, 1 = active). + MBF_PAR_SMART_TEMP_HIGH, // 0x0418 Smart mode: Upper temperature + MBF_PAR_SMART_TEMP_LOW, // 0x0419 Smart mode: Lower temperature + MBF_PAR_SMART_ANTI_FREEZE, // 0x041A Smart mode: Antifreeze mode activated (1) or not (0). + MBF_PAR_SMART_INTERVAL_REDUCTION, // 0x041B Smart mode: This register is read-only and reports to the outside what percentage (0 to 100%) is being applied to the nominal filtration time. 100% means that the total programmed time is being filtered. + MBF_PAR_INTELLIGENT_TEMP, // 0x041C Intelligent mode: Setpoint temperature + MBF_PAR_INTELLIGENT_FILT_MIN_TIME, // 0x041D Intelligent mode: Minimum filtration time in minutes + MBF_PAR_INTELLIGENT_BONUS_TIME, // 0x041E Intelligent mode: Bonus time for the current set of intervals + MBF_PAR_INTELLIGENT_TT_NEXT_INTERVAL, // 0x041F Intelligent mode: Time to next filtration interval. When it reaches 0 an interval is started and the number of seconds is reloaded for the next interval (2x3600) + MBF_PAR_INTELLIGENT_INTERVALS, // 0x0420 Intelligent mode: Number of started intervals. When it reaches 12 it is reset to 0 and the bonus time is reloaded with the value of MBF_PAR_INTELLIGENT_FILT_MIN_TIME + MBF_PAR_FILTRATION_STATE, // 0x0421 Filtration state: 0 is off and 1 is on. The filtration state is regulated according to the MBF_PAR_FILT_MANUAL_STATE register if the filtration mode held in register MBF_PAR_FILT_MODE is set to FILT_MODE_MANUAL (0). MBF_PAR_HEATING_DELAY_TIME, // 0x0422 Timer in seconds that counts up when the heating is to be enabled. Once this counter reaches 60 seconds, the heating is then enabled. This counter is for internal use only. - MBF_PAR_FILTERING_TIME_LOW, // 0x0423 32-bit value: - MBF_PAR_FILTERING_TIME_HIGH, // 0x0424 Internal timer for the intelligent filtering mode. It counts the filtering time done during a given day. This register is only for internal use and should not be modified by the user. - MBF_PAR_INTELLIGENT_INTERVAL_TIME_LOW, // 0x0425 32-bit value: - MBF_PAR_INTELLIGENT_INTERVAL_TIME_HIGH, // 0x0426 Internal timer that counts the filtration interval assigned to the the intelligent mode. This register is only for internal use and should not be modified by the user. + MBF_PAR_FILTERING_TIME_LOW, // 0x0423 Internal timer for the intelligent filtering mode (32-bit value - low word). It counts the filtering time done during a given day. This register is only for internal use and should not be modified by the user. + MBF_PAR_FILTERING_TIME_HIGH, // 0x0424 Internal timer for the intelligent filtering mode (32-bit value - high word) + MBF_PAR_INTELLIGENT_INTERVAL_TIME_LOW, // 0x0425 Internal timer that counts the filtration interval assigned to the the intelligent mode (32-bit value - low word). This register is only for internal use and should not be modified by the user. + MBF_PAR_INTELLIGENT_INTERVAL_TIME_HIGH, // 0x0426 Internal timer that counts the filtration interval assigned to the the intelligent mode (32-bit value - high word) MBF_PAR_UV_MODE, // 0x0427 UV mode active or not - see MBV_PAR_UV_MODE*. To enable UV support for a given device, add the mask MBMSK_MODEL_UV to the MBF_PAR_MODEL register. - MBF_PAR_UV_HIDE_WARN, // 0x0428 mask Suppression for warning messages in the UV mode. + MBF_PAR_UV_HIDE_WARN, // 0x0428 mask Suppression for warning messages in the UV mode (see MBMSK_UV_HIDE_WARN_*) MBF_PAR_UV_RELAY_GPIO, // 0x0429 Relay number assigned to the UV function. MBF_PAR_PH_PUMP_REP_TIME_ON, // 0x042A mask Time that the pH pump will be turn on in the repetitive mode (see MBMSK_PH_PUMP_*). Contains a special time format, see desc for MBMSK_PH_PUMP_TIME. MBF_PAR_PH_PUMP_REP_TIME_OFF, // 0x042B mask Time that the pH pump will be turn off in the repetitive mode. Contains a special time format, see desc for MBMSK_PH_PUMP_TIME, has no upper configuration bit 0x8000 @@ -197,33 +197,33 @@ enum NeoPoolRegister { MBF_PAR_PUMP_RELAY_TIME_OFF, // 0x042E Time level in minutes or seconds that the dosing pump must remain off when the temporized pump mode is selected. This time level register applies to all pumps except pH. Contains a special time format, see desc for MBMSK_PH_PUMP_TIME, has no upper configuration bit 0x8000 MBF_PAR_PUMP_RELAY_TIME_ON, // 0x042F Time level in minutes or seconds that the dosing pump must remain on when the temporized pump mode is selected. This time level register applies to all pumps except pH. Contains a special time format, see desc for MBMSK_PH_PUMP_TIME, has no upper configuration bit 0x8000 MBF_PAR_RELAY_PH, // 0x0430 Determine what pH regulation configuration the equipment has (see MBV_PAR_RELAY_PH_*) - MBF_PAR_RELAY_MAX_TIME, // 0x0431 Maximum amount of time, in seconds, that a dosing pump can operate before rising an alarm signal. The behavior of the system when the dosing time is exceeded is regulated by the type of action stored in the MBF_PAR_RELAY_MODE register. + MBF_PAR_RELAY_MAX_TIME, // 0x0431 Maximum amount of time in seconds, that a dosing pump can operate before rising an alarm signal. The behavior of the system when the dosing time is exceeded is regulated by the type of action stored in the MBF_PAR_RELAY_MODE register. MBF_PAR_RELAY_MODE, // 0x0432 Behavior of the system when the dosing time is exceeded (see MBMSK_PAR_RELAY_MODE_* and MBV_PAR_RELAY_MODE_*) MBF_PAR_RELAY_ACTIVATION_DELAY, // 0x0433 Delay time in seconds for the pH pump when the measured pH value is outside the allowable pH setpoints. The system internally adds an extra time of 10 seconds to the value stored here. The pump starts the dosing operation once the condition of pH out of valid interval is maintained during the time specified in this register. - MBF_PAR_TIMER_BLOCK_BASE, // 0x0434 This block of 180 registers holds the configuration of the system timers. The system has a set of 12 fully configurable timers, each one assigned to a specific function, described below: - MBF_PAR_TIMER_BLOCK_FILT_INT1 = 0x0434, // 0x0434 Filtration interval 1 (15 register - see MBV_TIMER_OFFMB_* for desc) - MBF_PAR_TIMER_BLOCK_FILT_INT2 = 0x0443, // 0x0443 Filtration interval 2 (15 register - see MBV_TIMER_OFFMB_* for desc) - MBF_PAR_TIMER_BLOCK_FILT_INT3 = 0x0452, // 0x0452 Filtration interval 3 (15 register - see MBV_TIMER_OFFMB_* for desc) - MBF_PAR_TIMER_BLOCK_AUX1_INT2 = 0x0461, // 0x0461 Auxiliary relay 1 - 2. interval (15 register - see MBV_TIMER_OFFMB_* for desc) - MBF_PAR_TIMER_BLOCK_LIGHT_INT = 0x0470, // 0x0470 Lighting interval (15 register - see MBV_TIMER_OFFMB_* for desc) - MBF_PAR_TIMER_BLOCK_AUX2_INT2 = 0x047F, // 0x047F Auxiliary relay 2 - 2. interval (15 register - see MBV_TIMER_OFFMB_* for desc) - MBF_PAR_TIMER_BLOCK_AUX3_INT2 = 0x048E, // 0x048E Auxiliary relay 3 - 2. interval (15 register - see MBV_TIMER_OFFMB_* for desc) - MBF_PAR_TIMER_BLOCK_AUX4_INT2 = 0x049D, // 0x049D Auxiliary relay 4 - 2. interval (15 register - see MBV_TIMER_OFFMB_* for desc) - MBF_PAR_TIMER_BLOCK_AUX1_INT1 = 0x04AC, // 0x04AC Auxiliary relay 1 - 1. interval (15 register - see MBV_TIMER_OFFMB_* for desc) - MBF_PAR_TIMER_BLOCK_AUX2_INT1 = 0x04BB, // 0x04BB Auxiliary relay 2 - 1. interval (15 register - see MBV_TIMER_OFFMB_* for desc) - MBF_PAR_TIMER_BLOCK_AUX3_INT1 = 0x04CA, // 0x04CA Auxiliary relay 3 - 1. interval (15 register - see MBV_TIMER_OFFMB_* for desc) - MBF_PAR_TIMER_BLOCK_AUX4_INT1 = 0x04D9, // 0x04D9 Auxiliary relay 4 - 1. interval (15 register - see MBV_TIMER_OFFMB_* for desc) + MBF_PAR_TIMER_BLOCK_BASE, // 0x0434 Block of 180 registers containing the configuration of the 12 timers with 15 registers each (see MBV_TIMER_OFFMB_*). The system has a set of 12 fully configurable timers, each one assigned to a specific function: + MBF_PAR_TIMER_BLOCK_FILT_INT1 = 0x0434, // 0x0434 Filtration timer 1 + MBF_PAR_TIMER_BLOCK_FILT_INT2 = 0x0443, // 0x0443 Filtration tiemr 2 + MBF_PAR_TIMER_BLOCK_FILT_INT3 = 0x0452, // 0x0452 Filtration timer 3 + MBF_PAR_TIMER_BLOCK_AUX1_INT2 = 0x0461, // 0x0461 Aux1 timer 2 + MBF_PAR_TIMER_BLOCK_LIGHT_INT = 0x0470, // 0x0470 Lighting timer + MBF_PAR_TIMER_BLOCK_AUX2_INT2 = 0x047F, // 0x047F Aux2 timer 2 + MBF_PAR_TIMER_BLOCK_AUX3_INT2 = 0x048E, // 0x048E Aux3 timer 2 + MBF_PAR_TIMER_BLOCK_AUX4_INT2 = 0x049D, // 0x049D Aux4 timer 2 + MBF_PAR_TIMER_BLOCK_AUX1_INT1 = 0x04AC, // 0x04AC Aux1 timer 1 + MBF_PAR_TIMER_BLOCK_AUX2_INT1 = 0x04BB, // 0x04BB Aux2 timer 1 + MBF_PAR_TIMER_BLOCK_AUX3_INT1 = 0x04CA, // 0x04CA Aux3 timer 1 + MBF_PAR_TIMER_BLOCK_AUX4_INT1 = 0x04D9, // 0x04D9 Aux4 timer 1 MBF_PAR_FILTVALVE_ENABLE = 0x04E8, // 0x04E8 Filter cleaning functionality mode (0 = off, 1 = Besgo) MBF_PAR_FILTVALVE_MODE, // 0x04E9 Filter cleaning valve timing mode, possible modes: MBV_PAR_CTIMER_ENABLED, MBV_PAR_CTIMER_ALWAYS_ON, MBV_PAR_CTIMER_ALWAYS_OFF MBF_PAR_FILTVALVE_GPIO, // 0x04EA Relay associated with the filter cleaning function. default AUX2 (value 5) - MBF_PAR_FILTVALVE_START_LOW, // 0x04EB start timestamp of filter cleaning (32-bit) - MBF_PAR_FILTVALVE_START_HIGH, // 0x04EC " + MBF_PAR_FILTVALVE_START_LOW, // 0x04EB Start timestamp of filter cleaning (32-bit value - low word) + MBF_PAR_FILTVALVE_START_HIGH, // 0x04EC Start timestamp of filter cleaning (32-bit value - high word) MBF_PAR_FILTVALVE_PERIOD_MINUTES, // 0x04ED Period in minutes between cleaning actions. For example, if a value of 60 is stored in this registry, a cleanup action will occur every hour. MBF_PAR_FILTVALVE_INTERVAL, // 0x04EE Cleaning action duration in seconds. MBF_PAR_FILTVALVE_REMAINING, // 0x04EF Time remaining for the current cleaning action in seconds. If this register is 0, it means that there is no cleaning function running. When a cleanup function is started, the contents of the MBF_PAR_FILTVALVE_INTERVAL register are copied to this register, then decremented once per second. The display uses this log to track the progress of the cleaning function. MBF_ACTION_COPY_TO_RTC, // 0x04F0 A write (any value) forces the writing of the RTC time registers MBF_PAR_TIME_LOW (0x0408) and MBF_PAR_TIME_HIGH (0x0409) into the RTC internal microcontroller clock management registers. - // USER page (0x05xx) To make the modification of this register persistent, execute the EEPROM storage procedure described in global register MBF_SAVE_TO_EEPROM. + // USER page (0x05xx) - Contains user configuration registers, such as the production level for the ionization and the hydrolysis, or the set points for the pH, redox, or chlorine regulation loops. MBF_PAR_ION = 0x0500, // 0x0500* Ionization target production level. The value adjusted in this register must not exceed the value set in the MBF_PAR_ION_NOM factory register. MBF_PAR_ION_PR, // 0x0501* Amount of time in minutes that the ionization must be activated each time that the filtration starts. MBF_PAR_HIDRO, // 0x0502* Hydrolisis target production level. When the hydrolysis production is to be set in percent values, this value will contain the percent of production. If the hydrolysis module is set to work in g/h production, this module will contain the desired amount of production in g/h units. The value adjusted in this register must not exceed the value set in the MBF_PAR_HIDRO_NOM factory register. @@ -231,47 +231,25 @@ enum NeoPoolRegister { MBF_PAR_PH2, // 0x0505* Lower limit of the pH regulation system. The value set in this register is multiplied by 100. This means that if we want to set a value of 7.0, the numerical content that we must write in this register is 700. This register must be always lower than MBF_PAR_PH1. MBF_PAR_RX1 = 0x0508, // 0x0508* Set point for the redox regulation system. This value must be in the range of 0 to 1000. MBF_PAR_CL1 = 0x050A, // 0x050A* Set point for the chlorine regulation system. The value stored in this register is multiplied by 100. This mean that if we want to set a value of 1.5 ppm, we will have to write a numerical value of 150. This value stored in this register must be in the range of 0 to 1000. - MBF_PAR_FILTRATION_CONF = 0x050F, // 0x050F* mask undocumented - filtration type and speed, see MBMSK_PAR_FILTRATION_CONF_* - MBF_PAR_FILTRATION_SPEED_FUNC = 0x0513, // 0x0513 undocumented - filtration speed function control + MBF_PAR_FILTRATION_CONF = 0x050F, // 0x050F* mask ! filtration type and speed, see MBMSK_PAR_FILTRATION_CONF_* + MBF_PAR_FILTRATION_SPEED_FUNC = 0x0513, // 0x0513 ! filtration speed function control MBF_PAR_FUNCTION_DEPENDENCY = 0x051B, // 0x051B mask Specification for the dependency of different functions, such as heating, from external events like FL1 (see MBMSK_FCTDEP_HEATING/MBMSK_DEPENDENCY_*) - // MISC page (0x06xx) + // MISC page (0x06xx) - Contains the configuration parameters for the screen controllers (language, colours, sound, etc). MBF_PAR_UICFG_MACHINE = 0x0600, // 0x0600* Machine type (see MBV_PAR_MACH_* and kNeoPoolMachineNames[]) MBF_PAR_UICFG_LANGUAGE, // 0x0601* Selected language (see MBV_PAR_LANG_*) MBF_PAR_UICFG_BACKLIGHT, // 0x0602* Display backlight (see MBV_PAR_BACKLIGHT_*) MBF_PAR_UICFG_SOUND, // 0x0603* mask Audible alerts (see MBMSK_PAR_SOUND_*) MBF_PAR_UICFG_PASSWORD, // 0x0604* System password encoded in BCD MBF_PAR_UICFG_VISUAL_OPTIONS, // 0x0605* mask Stores the different display options for the user interface menus (bitmask). Some bits allow you to hide options that are normally visible (bits 0 to 3) while other bits allow you to show options that are normally hidden (bits 9 to 15) - MBF_PAR_UICFG_VISUAL_OPTIONS_EXT, // 0x0606* mask This register stores additional display options for the user interface menus, see MBMSK_VOE_* + MBF_PAR_UICFG_VISUAL_OPTIONS_EXT, // 0x0606* mask This register stores additional display options for the user interface menus (see MBMSK_VOE_*) MBF_PAR_UICFG_MACH_VISUAL_STYLE, // 0x0607* mask This register is an expansion of register 0x0600 and 0x0605. The lower part of the register (8 bits LSB) is used to store the type of color selected when in register 0x600 has been specified that the machine is of type "generic". Colors and styles correspond to those listed in record 0x600 MBF_PAR_UICFG_MACHINE. The upper part (8-bit MSB) contains extra bits MBMSK_VS_FORCE_UNITS_GRH, MBMSK_VS_FORCE_UNITS_PERCENTAGE and MBMSK_ELECTROLISIS - MBF_PAR_UICFG_MACH_NAME_BOLD_0, // 0x0608 This set of 4 registers stores an ASCIIZ string of up to 8 characters that is used to specify the bold part of the title to be displayed at startup if the specified machine type is generic. Note: only lowercase letters (a-z) can be used. - MBF_PAR_UICFG_MACH_NAME_BOLD_1, // 0x0609 - MBF_PAR_UICFG_MACH_NAME_BOLD_2, // 0x060A - MBF_PAR_UICFG_MACH_NAME_BOLD_3, // 0x060B - MBF_PAR_UICFG_MACH_NAME_LIGHT_0, // 0x060C This set of 4 registers stores an ASCIIZ string of up to 8 characters that is used to specify the normal intensity part of the title that will be displayed at startup if the specified machine type is generic. Note: Only lowercase letters (a-z) can be used. - MBF_PAR_UICFG_MACH_NAME_LIGHT_1, // 0x060D - MBF_PAR_UICFG_MACH_NAME_LIGHT_2, // 0x060E - MBF_PAR_UICFG_MACH_NAME_LIGHT_3, // 0x060F - MBF_PAR_UICFG_MACH_NAME_AUX1_0, // 0x0610 Aux1 relay name: 5 registers ASCIIZ string of up to 10 characters - MBF_PAR_UICFG_MACH_NAME_AUX1_1, // 0x0611 - MBF_PAR_UICFG_MACH_NAME_AUX1_2, // 0x0612 - MBF_PAR_UICFG_MACH_NAME_AUX1_3, // 0x0613 - MBF_PAR_UICFG_MACH_NAME_AUX1_4, // 0x0614 - MBF_PAR_UICFG_MACH_NAME_AUX2_0, // 0x0615 Aux2 relay name: 5 registers ASCIIZ string of up to 10 characters - MBF_PAR_UICFG_MACH_NAME_AUX2_1, // 0x0616 - MBF_PAR_UICFG_MACH_NAME_AUX2_2, // 0x0617 - MBF_PAR_UICFG_MACH_NAME_AUX2_3, // 0x0618 - MBF_PAR_UICFG_MACH_NAME_AUX2_4, // 0x0619 - MBF_PAR_UICFG_MACH_NAME_AUX3_0, // 0x061A Aux3 relay name: 5 registers ASCIIZ string of up to 10 characters - MBF_PAR_UICFG_MACH_NAME_AUX3_1, // 0x061B - MBF_PAR_UICFG_MACH_NAME_AUX3_2, // 0x061C - MBF_PAR_UICFG_MACH_NAME_AUX3_3, // 0x061D - MBF_PAR_UICFG_MACH_NAME_AUX3_4, // 0x061E - MBF_PAR_UICFG_MACH_NAME_AUX4_0, // 0x061F Aux4 relay name: 5 registers ASCIIZ string of up to 10 characters - MBF_PAR_UICFG_MACH_NAME_AUX4_1, // 0x0620 - MBF_PAR_UICFG_MACH_NAME_AUX4_2, // 0x0621 - MBF_PAR_UICFG_MACH_NAME_AUX4_3, // 0x0622 - MBF_PAR_UICFG_MACH_NAME_AUX4_4, // 0x0623 + MBF_PAR_UICFG_MACH_NAME_BOLD = 0x0608, // 0x0608 Machine name bold part title displayed during startup (if machine type is generic). Note: Only lowercase letters (a-z) can be used. 4 register ASCIIZ string with up to 8 characters + MBF_PAR_UICFG_MACH_NAME_LIGHT = 0x060C, // 0x060C Machine name normal intensity part title displayed during startup (if machine type is generic). Note: Only lowercase letters (a-z) can be used. 4 register ASCIIZ string with up to 8 characters + MBF_PAR_UICFG_MACH_NAME_AUX1 = 0x0610, // 0x0610 Aux1 relay name: 5 register ASCIIZ string with up to 10 characters + MBF_PAR_UICFG_MACH_NAME_AUX2 = 0x0615, // 0x0615 Aux2 relay name: 5 register ASCIIZ string with up to 10 characters + MBF_PAR_UICFG_MACH_NAME_AUX3 = 0x061A, // 0x061A Aux3 relay name: 5 register ASCIIZ string with up to 10 characters + MBF_PAR_UICFG_MACH_NAME_AUX4 = 0x061F, // 0x061F Aux4 relay name: 5 register ASCIIZ string with up to 10 characters }; // Sugar Valley register constants and bit masks @@ -279,14 +257,14 @@ enum NeoPoolConstAndBitMask { // MBF_PH_STATUS MBMSK_PH_STATUS_ALARM = 0x000F, // PH alarm. The possible alarm values are depending on the regulation model: // Valid alarm values for pH regulation with acid and base: - MBV_PH_ACID_BASE_ALARM0 = 0, // no alarm - MBV_PH_ACID_BASE_ALARM1 = 1, // pH too high; the pH value is 0.8 points higher than the setpoint (PH1 on acid systems, PH2 on base systems, PH1 on acid+base systems) - MBV_PH_ACID_BASE_ALARM2 = 2, // pH too low: the pH value is 0.8 points lower than the set point value set in (PH1 on acid systems, PH2 on base systems, PH2 on acid+base systems) - MBV_PH_ACID_BASE_ALARM3 = 3, // pH pump has exceeded the working time set by the MBF_PAR_RELAY_PH_MAX_TIME parameter and has stopped. - MBV_PH_ACID_BASE_ALARM4 = 4, // pH higher than the set point (PH1 + 0.1 on acid systems, PH2 + 0.1 on base systems, PH1 on acid+base systems) - MBV_PH_ACID_BASE_ALARM5 = 5, // pH lower than the set point (PH1 - 0.3 on acid systems, PH2 - 0.3 on base systems, PH2 on acid+base systems) - MBV_PH_ACID_BASE_ALARM6 = 6, // undocumented - tank level alarm - + MBV_PH_ACID_BASE_ALARM0 = 0, // no alarm + MBV_PH_ACID_BASE_ALARM1 = 1, // pH too high; the pH value is 0.8 points higher than the setpoint (PH1 on acid systems, PH2 on base systems, PH1 on acid+base systems) + MBV_PH_ACID_BASE_ALARM2 = 2, // pH too low: the pH value is 0.8 points lower than the set point value set in (PH1 on acid systems, PH2 on base systems, PH2 on acid+base systems) + MBV_PH_ACID_BASE_ALARM3 = 3, // pH pump has exceeded the working time set by the MBF_PAR_RELAY_PH_MAX_TIME parameter and has stopped. + MBV_PH_ACID_BASE_ALARM4 = 4, // pH higher than the set point (PH1 + 0.1 on acid systems, PH2 + 0.1 on base systems, PH1 on acid+base systems) + MBV_PH_ACID_BASE_ALARM5 = 5, // pH lower than the set point (PH1 - 0.3 on acid systems, PH2 - 0.3 on base systems, PH2 on acid+base systems) + MBV_PH_ACID_BASE_ALARM6 = 6, // ! tank level alarm + // bit MBMSK_PH_STATUS_CTRL_BY_FL = 0x0400, // 10 Control status of the pH module by flow detection (if enabled by MBF_PAR_HIDRO_ION_CAUDAL) MBMSK_PH_STATUS_ACID_PUMP_ACTIVE = 0x0800, // 11 Acid pH pump relay on (pump on) MBMSK_PH_STATUS_BASE_PUMP_ACTIVE = 0x1000, // 12 Base pH Pump Relay On (Pump On) @@ -294,38 +272,38 @@ enum NeoPoolConstAndBitMask { MBMSK_PH_STATUS_MEASURE_ACTIVE = 0x4000, // 14 Active pH measurement module and making measurements. If this bit is at 1, the pH bar should be displayed. MBMSK_PH_STATUS_MODULE_PRESENT = 0x8000, // 15 Detected pH measurement module - // MBF_RX_STATUS + // MBF_RX_STATUS // bit MBMSK_RX_STATUS_RX_PUMP_ACTIVE = 0x1000, // 12 Redox pump relay on (pump activated) MBMSK_RX_STATUS_CTRL_ACTIVE = 0x2000, // 13 Active Redox control module and controlling pump MBMSK_RX_STATUS_MEASURE_ACTIVE = 0x4000, // 14 Active Redox measurement module and performing measurements. If this bit is at 1, the Redox bar should be displayed on the screen. MBMSK_RX_STATUS_MODULE_PRESENT = 0x8000, // 15 Redox measurement module detected in the system - // MBF_CL_STATUS + // MBF_CL_STATUS // bit MBMSK_CL_STATUS_CHLORINE_FLOW = 0x0008, // 3 Chlorine Probe Flow Sensor. This sensor is built into the probe itself and serves to detect whether there is water passing through the chlorine measurement probe. In case the sensor is at 0, the chlorine measurement will not be valid. MBMSK_CL_STATUS_CL_PUMP_ACTIVE = 0x1000, // 12 Chlorine pump relay on (pump on) MBMSK_CL_STATUS_CTRL_ACTIVE = 0x2000, // 13 Active chlorine control module and controlling pump MBMSK_CL_STATUS_MEASURE_ACTIVE = 0x4000, // 14 Active chlorine measurement module and taking measurements. If this bit is 1, the chlorine bar should be displayed on the screen. MBMSK_CL_STATUS_MODULE_PRESENT = 0x8000, // 15 Chlorine measurement module detected in the system - // MBF_CD_STATUS + // MBF_CD_STATUS // bit MBMSK_CD_STATUS_RX_PUMP_ACTIVE = 0x1000, // 12 Conductivity pump relay on (pump active) MBMSK_CD_STATUS_CTRL_ACTIVE = 0x2000, // 13 Active conductivity control module and controlling pump MBMSK_CD_STATUS_MEASURE_ACTIVE = 0x4000, // 14 Active conductivity measurement module and making measurements. If this bit is 1, the conditionality bar should be displayed on the screen. MBMSK_CD_STATUS_MODULE_PRESENT = 0x8000, // 15 Conductivity measurement module detected in the system - // MBF_ION_STATUS + // MBF_ION_STATUS // bit MBMSK_ION_STATUS_ON_TARGET = 0x0001, // 0 On Target - the system has reached the set point. MBMSK_ION_STATUS_LOW = 0x0002, // 1 Low - Ionization cannot reach the set point. - MBMSK_ION_STATUS_RESERVED = 0x0004, // 2 + MBMSK_ION_STATUS_RESERVED = 0x0004, // 2 reserved MBMSK_ION_STATUS_PROGTIME_EXCEEDED = 0x0008, // 3 Pr off - The programmed ionization time has been exceeded MBMSK_ION_STATUS_POLOFF = 0x1000, // 12 Ion Pol off - Ionization in dead time MBMSK_ION_STATUS_POL1 = 0x2000, // 13 Ion Pol 1 - Ionization working in polarization 1 MBMSK_ION_STATUS_POL2 = 0x4000, // 14 Ion Pol 2 - Ionization working in polarization 2 - // MBF_HIDRO_STATUS + // MBF_HIDRO_STATUS // bit MBMSK_HIDRO_STATUS_ON_TARGET = 0x0001, // 0 On Target - the system has reached the set point. MBMSK_HIDRO_STATUS_LOW = 0x0002, // 1 Low - Hydrolysis cannot reach the set point. - MBMSK_HIDRO_STATUS_RESERVED = 0x0004, // 2 + MBMSK_HIDRO_STATUS_RESERVED = 0x0004, // 2 reserved MBMSK_HIDRO_STATUS_FL1 = 0x0008, // 3 Flow - Hydrolysis cell flow indicator (FL1) MBMSK_HIDRO_STATUS_COVER = 0x0010, // 4 Cover - Cover input activated MBMSK_HIDRO_STATUS_MODULE_ACTIVE = 0x0020, // 5 Active - Active Module hydrolysis (hidroEnable) @@ -338,7 +316,7 @@ enum NeoPoolConstAndBitMask { MBMSK_HIDRO_STATUS_POL1 = 0x2000, // 13 Ion Pol 1 - Ionization working in polarization 1 MBMSK_HIDRO_STATUS_POL2 = 0x4000, // 14 Ion Pol 2 - Ionization working in polarization 2 - // MBF_RELAY_STATE + // MBF_RELAY_STATE // bit MBMSK_RELAY_STATE1 = 0x0001, // 0 Relay 1 state (1 on; 0 off) (normally assigned to ph) MBMSK_RELAY_STATE2 = 0x0002, // 1 Relay 2 state (1 on; 0 off) (normally assigned to filtering) MBMSK_RELAY_STATE3 = 0x0004, // 2 Relay 3 status (1 on; 0 off) (normally assigned to lighting) @@ -352,7 +330,7 @@ enum NeoPoolConstAndBitMask { MBMSK_RELAY_FILTSPEED = 0x0700, // Filtration current speed mask MBSHFT_RELAY_FILTSPEED = 8, // Filtration current speed bit shift - // MBF_NOTIFICATION + // MBF_NOTIFICATION // bit MBMSK_NOTIF_MODBUS_CHANGED = 0x0001, // 0 Modbus page changed MBMSK_NOTIF_GLOBAL_CHANGED = 0x0002, // 1 Global page changed MBMSK_NOTIF_FACTORY_CHANGED = 0x0004, // 2 Factory page changed @@ -361,11 +339,11 @@ enum NeoPoolConstAndBitMask { MBMSK_NOTIF_MISC_CHANGED = 0x0020, // 5 Misc page changed // MBF_CELL_BOOST - MBMSK_CELL_BOOST_NO_REDOX_CTL = 0x8000, // undocumented - Disable redox ctrl - MBMSK_CELL_BOOST_STATE = 0x0500, // undocumented - Boost - MBMSK_CELL_BOOST_START = 0x00A0, // undocumented - Start boost + MBMSK_CELL_BOOST_NO_REDOX_CTL = 0x8000, // ! Disable redox ctrl + MBMSK_CELL_BOOST_STATE = 0x0500, // ! Boost + MBMSK_CELL_BOOST_START = 0x00A0, // ! Start boost - // MBF_PAR_MODEL + // MBF_PAR_MODEL // bit MBMSK_MODEL_ION = 0x0001, // 0 The equipment includes ionization control MBMSK_MODEL_HIDRO = 0x0002, // 1 The equipment includes hydrolysis or electrolysis MBMSK_MODEL_UV = 0x0004, // 2 The equipment includes disinfection control by ultraviolet lamp @@ -378,7 +356,7 @@ enum NeoPoolConstAndBitMask { MBV_PAR_HIDRO_FLOW_SIGNAL_PADDLE_AND_STD= 3, // Detection based on the paddle switch, associated with the FL1 input, and the standard detector. The system will understand that there is flow when both elements detect flow. If either one opens, the hydrolysis will stop. MBV_PAR_HIDRO_FLOW_SIGNAL_PADDLE_OR_STD = 4, // Detection based on the paddle switch, associated with the FL1 input, or the standard detector. The system will understand that there is flow when either of the two elements detects flow. Hydrolysis will stop only if both detectors detect no flow. - // MBF_PAR_HIDRO_ION_CAUDAL + // MBF_PAR_HIDRO_ION_CAUDAL // bit MBMSK_HIDRO_ION_CAUDAL_FL1_CTRL = 0x0001, // 0 If the FL1 signal is detected to be inactive, the actuation of the different elements of the system is disabled. MBMSK_HIDRO_ION_CAUDAL_FL2_CTRL = 0x0002, // 1 If the FL2 signal is detected to be inactive, the actuation of the different elements of the system is disabled. MBMSK_HIDRO_ION_CAUDAL_FULL_CL_HIDRO_CTRL=0x0004, // 2 If there is a chlorine module installed and it is detected that its flow sensor is inactive, the action of the different elements of the system is disabled. @@ -399,9 +377,9 @@ enum NeoPoolConstAndBitMask { MBV_PAR_UV_MODE0 = 0, // UV is switched off and it will not turn on when filtration starts MBV_PAR_UV_MODE1 = 1, // UV is switched on and it will turn on when filtration starts. Time counter for the UV lamp will be incremented. - // MBF_PAR_UV_HIDE_WARN - MBMSK_UV_HIDE_WARN_CLEAN = 0x0001, // 0 - MBMSK_UV_HIDE_WARN_REPLACE = 0x0002, // 1 + // MBF_PAR_UV_HIDE_WARN // bit + MBMSK_UV_HIDE_WARN_CLEAN = 0x0001, // 0 Suppress UV lamp clean wanring + MBMSK_UV_HIDE_WARN_REPLACE = 0x0002, // 1 Suppress UV lamp replace warning // MBF_PAR_PH_PUMP_REP_TIME_ON MBMSK_PH_PUMP_TIME = 0x7FFF, // Time level for the pump: The time level has a special coding format. It can cover periods of 1 to 180 seconds with 1 second granularity and from 3 to 999 minutes with 1 minute granularity. f the value is set to 30 for example, a 30 second time will be considered. If we have the value 200, we will have an on time of (200-180+3) = 23 minutes. @@ -496,7 +474,7 @@ enum NeoPoolConstAndBitMask { MBV_TIMER_OFFMB_TIMER_INTERVAL = 7, // Time in seconds that the timer has to run when started (32-bit, LSB first) MBV_TIMER_OFFMB_TIMER_COUNTDOWN = 9, // Time remaining in seconds for the countdown mode (32-bit, LSB first) MBV_TIMER_OFFMB_TIMER_FUNCTION = 11, // Function assigned to this timer, see MBV_PAR_CTIMER_FCT_* - MBV_TIMER_OFFMB_TIMER_WORK_TIME = 13, // Number of seconds that the timer has been operating + MBV_TIMER_OFFMB_TIMER_WORK_TIME = 13, // Number of seconds that the timer has been operating (valid only if MBV_TIMER_OFFMB_TIMER_ENABLE is in MBV_PAR_CTIMER_COUNTDOWN_KEY_* mode) // MBV_TIMER_OFFMB_TIMER_ENABLE working modes: MBV_PAR_CTIMER_DISABLE = 0, // Timer disabled MBV_PAR_CTIMER_ENABLED = 1, // Timer enabled and independent @@ -517,21 +495,21 @@ enum NeoPoolConstAndBitMask { MBV_PAR_CTIMER_FCT_FILTRATION = 0x0001, // Filtration function of the system MBV_PAR_CTIMER_FCT_LIGHTING = 0x0002, // Lighting function of the system MBV_PAR_CTIMER_FCT_HEATING = 0x0004, // Heating function of the system - MBV_PAR_CTIMER_FCT_AUXREL1 = 0x0100, // Function assigned to relay 1 (Filtration) - MBV_PAR_CTIMER_FCT_AUXREL2 = 0x0200, // Function assigned to relay 2 (Light) - MBV_PAR_CTIMER_FCT_AUXREL3 = 0x0400, // Function assigned to relay 3 (Heating) - MBV_PAR_CTIMER_FCT_AUXREL4 = 0x0800, // Function assigned to relay 4 (AUX1) - MBV_PAR_CTIMER_FCT_AUXREL5 = 0x1000, // Function assigned to relay 5 (AUX2) - MBV_PAR_CTIMER_FCT_AUXREL6 = 0x2000, // Function assigned to relay 6 (AUX3) - MBV_PAR_CTIMER_FCT_AUXREL7 = 0x4000, // Function assigned to relay 7 (AUX4) + MBV_PAR_CTIMER_FCT_RELAY1 = 0x0100, // Function assigned to relay 1 (Filtration) + MBV_PAR_CTIMER_FCT_RELAY2 = 0x0200, // Function assigned to relay 2 (Light) + MBV_PAR_CTIMER_FCT_RELAY3 = 0x0400, // Function assigned to relay 3 (pH Pump) + MBV_PAR_CTIMER_FCT_RELAY4 = 0x0800, // Function assigned to relay 4 (AUX1) + MBV_PAR_CTIMER_FCT_RELAY5 = 0x1000, // Function assigned to relay 5 (AUX2) + MBV_PAR_CTIMER_FCT_RELAY6 = 0x2000, // Function assigned to relay 6 (AUX3) + MBV_PAR_CTIMER_FCT_RELAY7 = 0x4000, // Function assigned to relay 7 (AUX4) - // MBF_PAR_UICFG_SOUND + // MBF_PAR_UICFG_SOUND // bit MBMSK_PAR_SOUND_CLICK = 0x0001, // 0 Click sounds every time a key is pressed MBMSK_PAR_SOUND_POPUP = 0x0002, // 1 Sound plays each time a pop-up message appears MBMSK_PAR_SOUND_ALERTS = 0x0004, // 2 An alarm sounds when there is an alert on the equipment (AL3) MBMSK_PAR_SOUND_FILTRATION = 0x0008, // 3 Audible warning every time the filtration is started - // MBF_PAR_UICFG_VISUAL_OPTIONS + // MBF_PAR_UICFG_VISUAL_OPTIONS // bit MBMSK_HIDE_TEMPERATURE = 0x0001, // 0 Hide temperature measurement from main menu MBMSK_HIDE_FILTRATION = 0x0002, // 1 Hide filter status from main menu MBMSK_HIDE_LIGHTING = 0x0004, // 2 Hide lighting status from main menu @@ -549,7 +527,7 @@ enum NeoPoolConstAndBitMask { MBMSK_SHOW_INSTALLER_MENU = 0x4000, // 14 Shows access to the installer menu in the main menu without the need for a password. MBMSK_SHOW_FACTORY_MENU = 0x8000, // 15 Shows access to the factory menu in the main menu without the need for a password. - // MBF_PAR_UICFG_VISUAL_OPTIONS_EXT + // MBF_PAR_UICFG_VISUAL_OPTIONS_EXT // bit MBMSK_VOE_SHOW_PNEUMATIC_VALVE = 0x0001, // 0 Shows the pneumatic valve MBMSK_VOE_HIDE_AUX_REL_DEPENDENCY = 0x0002, // 1 Hides the auxiliary relay dependency MBMSK_VOE_SHOW_BESGO_NAME = 0x0004, // 2 Show “Besgo” instead of “Pneumatic” for the pneumatic valve titles. @@ -564,13 +542,13 @@ enum NeoPoolConstAndBitMask { MBMSK_VOE_HIDE_BASIC_EXT_CONTROL = 0x0800, // 11 Hide basic external controls MBMSK_VOE_HIDE_DIAGNOSTICS = 0x1000, // 12 Hide diagnostics - // MBF_PAR_UICFG_MACH_VISUAL_STYLE + // MBF_PAR_UICFG_MACH_VISUAL_STYLE // bit MBMSK_VS_FORCE_UNITS_GRH = 0x2000, // 13 Display the hydrolysis/electrolysis in units of grams per hour (gr/h). MBMSK_VS_FORCE_UNITS_PERCENTAGE = 0x4000, // 14 Display the hydrolysis/electrolysis in percentage units (%). MBMSK_ELECTROLISIS = 0x8000, // 15 Display the word electrolysis instead of hydrolysis in generic mode. // MBF_POWER_MODULE_REG_* - MBV_POWER_MODULE_REG_INFO = 0, // undocumented - set of 26-byte power module register stores an ASCIIZ string containing the subversion and timestamp of the module, e. g. ".57\nMay 26 2020\n01:08:10\n\0" + MBV_POWER_MODULE_REG_INFO = 0, // ! set of 26-byte power module register stores an ASCIIZ string containing the subversion and timestamp of the module, e. g. ".57\nMay 26 2020\n01:08:10\n\0" }; #include @@ -2165,9 +2143,9 @@ void NeoPoolShow(bool json) strncpy_P(sdesc, PSTR(D_NEOPOOL_RELAY_VALVE), sizeof(sdesc)); } else if (i > 2) { // Aux - char sname[(MBF_PAR_UICFG_MACH_NAME_AUX2_0 - MBF_PAR_UICFG_MACH_NAME_AUX1_0) * 2 + 1]; - uint16_t base = MBF_PAR_UICFG_MACH_NAME_AUX1_0 + ((i - 3) * (MBF_PAR_UICFG_MACH_NAME_AUX2_0 - MBF_PAR_UICFG_MACH_NAME_AUX1_0)); - for (uint16_t k = 0; k < (MBF_PAR_UICFG_MACH_NAME_AUX2_0 - MBF_PAR_UICFG_MACH_NAME_AUX1_0); k++) { + char sname[(MBF_PAR_UICFG_MACH_NAME_AUX2 - MBF_PAR_UICFG_MACH_NAME_AUX1) * 2 + 1]; + uint16_t base = MBF_PAR_UICFG_MACH_NAME_AUX1 + ((i - 3) * (MBF_PAR_UICFG_MACH_NAME_AUX2 - MBF_PAR_UICFG_MACH_NAME_AUX1)); + for (uint16_t k = 0; k < (MBF_PAR_UICFG_MACH_NAME_AUX2 - MBF_PAR_UICFG_MACH_NAME_AUX1); k++) { uint16_t data = NeoPoolGetData(base + k); sname[k*2] = (char)(data >> 8); sname[k*2 + 1] = (char)(data & 0xFF); @@ -3019,7 +2997,7 @@ void NeopoolCheckChanges(void) { uint16_t data = NeoPoolGetData(pgm_read_word(NeoPoolRegCheck + i) & 0x0FFF); if (NeoPoolRegCheckData[i] != data) { #ifdef DEBUG_TASMOTA_SENSOR - AddLog(LOG_LEVEL_DEBUG, PSTR("NEO: NeopoolCheckChanges() addr 0x%04X: data stored %d (0x%04X), data read %d (0x%04X)"), + AddLog(LOG_LEVEL_DEBUG, PSTR("NEO: NeopoolCheckChanges() addr 0x%04X: data stored %d (0x%04X), data read %d (0x%04X)"), pgm_read_word(NeoPoolRegCheck + i) & 0x0FFF, NeoPoolRegCheckData[i], NeoPoolRegCheckData[i], data, data); From 3f4b69f91ccce6f9c2669b82092e5f460baca0dc Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 16 Dec 2023 17:26:58 +0100 Subject: [PATCH 009/303] Improve animation (#20246) --- .../src/embedded/animate_0_core.be | 22 + .../src/embedded/animate_9_module.be | 5 + .../src/solidify/solidified_animate_0_core.h | 1018 +++++++++-------- .../solidify/solidified_animate_9_module.h | 213 ++-- .../xdrv_52_3_berry_leds.ino | 5 +- 5 files changed, 705 insertions(+), 558 deletions(-) diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be b/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be index 5e91278fe..5809ed3f3 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be +++ b/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be @@ -62,6 +62,28 @@ class Animate_core self.animators.push(anim) end + # remove a specific animator + # remove all animators if no parameter or nil + # silently ignores if the animator can't be found + def remove_animator(anim) + var animators = self.animators + if (anim != nil) + animators.remove(animators.find(anim)) + else + animators.clear() + end + end + + def remove_painter(p) + var painters = self.painters + if (p != nil) + painters.remove(painters.find(p)) + else + painters.clear() + end + end + + def add_painter(painter) self.painters.push(painter) end diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be b/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be index 45f22b81b..aa9ef07e6 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be +++ b/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be @@ -444,6 +444,11 @@ class Animate_oscillator : Animate_animator self.b = b end + def set_form(form) + if (form == nil) form = 1 end + self.form = form + end + def animate(millis) if (self.duration_ms == nil) return end if millis == nil millis = tasmota.millis() end diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h index d124cc5b3..2221e785c 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h @@ -6,450 +6,6 @@ extern const bclass be_class_Animate_core; -/******************************************************************** -** Solidified function: remove -********************************************************************/ -be_local_closure(Animate_core_remove, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(clear), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(remove_fast_loop), - /* K3 */ be_nested_str_weak(fast_loop_cb), - }), - be_str_weak(remove), - &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0xB8060200, // 0002 GETNGBL R1 K1 - 0x8C040302, // 0003 GETMET R1 R1 K2 - 0x880C0103, // 0004 GETMBR R3 R0 K3 - 0x7C040400, // 0005 CALL R1 2 - 0x80000000, // 0006 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: add_background_animator -********************************************************************/ -be_local_closure(Animate_core_add_background_animator, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(set_cb), - /* K1 */ be_nested_str_weak(set_back_color), - /* K2 */ be_nested_str_weak(add_animator), - }), - be_str_weak(add_background_animator), - &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x8C080300, // 0000 GETMET R2 R1 K0 - 0x5C100000, // 0001 MOVE R4 R0 - 0x88140101, // 0002 GETMBR R5 R0 K1 - 0x7C080600, // 0003 CALL R2 3 - 0x8C080102, // 0004 GETMET R2 R0 K2 - 0x5C100200, // 0005 MOVE R4 R1 - 0x7C080400, // 0006 CALL R2 2 - 0x80000000, // 0007 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: clear -********************************************************************/ -be_local_closure(Animate_core_clear, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(stop), - /* K1 */ be_nested_str_weak(strip), - /* K2 */ be_nested_str_weak(clear), - }), - be_str_weak(clear), - &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0x88040101, // 0002 GETMBR R1 R0 K1 - 0x8C040302, // 0003 GETMET R1 R1 K2 - 0x7C040200, // 0004 CALL R1 1 - 0x80000000, // 0005 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: add_animator -********************************************************************/ -be_local_closure(Animate_core_add_animator, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(animators), - /* K1 */ be_nested_str_weak(push), - }), - be_str_weak(add_animator), - &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x80000000, // 0004 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: animate -********************************************************************/ -be_local_closure(Animate_core_animate, /* name */ - be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(animate), - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_bri -********************************************************************/ -be_local_closure(Animate_core_set_bri, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(bri), - }), - be_str_weak(set_bri), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: stop -********************************************************************/ -be_local_closure(Animate_core_stop, /* name */ - be_nested_proto( - 6, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str_weak(running), - /* K1 */ be_nested_str_weak(animators), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(stop), - /* K4 */ be_const_int(1), - /* K5 */ be_nested_str_weak(tasmota), - /* K6 */ be_nested_str_weak(remove_fast_loop), - /* K7 */ be_nested_str_weak(fast_loop_cb), - }), - be_str_weak(stop), - &be_const_str_solidified, - ( &(const binstruction[19]) { /* code */ - 0x50040000, // 0000 LDBOOL R1 0 0 - 0x90020001, // 0001 SETMBR R0 K0 R1 - 0x88040101, // 0002 GETMBR R1 R0 K1 - 0x58080002, // 0003 LDCONST R2 K2 - 0x600C000C, // 0004 GETGBL R3 G12 - 0x5C100200, // 0005 MOVE R4 R1 - 0x7C0C0200, // 0006 CALL R3 1 - 0x140C0403, // 0007 LT R3 R2 R3 - 0x780E0004, // 0008 JMPF R3 #000E - 0x940C0202, // 0009 GETIDX R3 R1 R2 - 0x8C0C0703, // 000A GETMET R3 R3 K3 - 0x7C0C0200, // 000B CALL R3 1 - 0x00080504, // 000C ADD R2 R2 K4 - 0x7001FFF5, // 000D JMP #0004 - 0xB80E0A00, // 000E GETNGBL R3 K5 - 0x8C0C0706, // 000F GETMET R3 R3 K6 - 0x88140107, // 0010 GETMBR R5 R0 K7 - 0x7C0C0400, // 0011 CALL R3 2 - 0x80000000, // 0012 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_back_color -********************************************************************/ -be_local_closure(Animate_core_set_back_color, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(back_color), - }), - be_str_weak(set_back_color), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_cb -********************************************************************/ -be_local_closure(Animate_core_set_cb, /* name */ - be_nested_proto( - 3, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(obj), - /* K1 */ be_nested_str_weak(mth), - }), - be_str_weak(set_cb), - &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x80000000, // 0002 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Animate_core_init, /* name */ - be_nested_proto( - 7, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 1]) { - be_nested_proto( - 2, /* nstack */ - 0, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(fast_loop), - }), - be_str_weak(_anonymous_), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x68000000, // 0000 GETUPV R0 U0 - 0x8C000100, // 0001 GETMET R0 R0 K0 - 0x7C000200, // 0002 CALL R0 1 - 0x80000000, // 0003 RET 0 - }) - ), - }), - 1, /* has constants */ - ( &(const bvalue[13]) { /* constants */ - /* K0 */ be_nested_str_weak(animate), - /* K1 */ be_nested_str_weak(strip), - /* K2 */ be_nested_str_weak(bri), - /* K3 */ be_nested_str_weak(running), - /* K4 */ be_nested_str_weak(pixel_count), - /* K5 */ be_nested_str_weak(animators), - /* K6 */ be_nested_str_weak(painters), - /* K7 */ be_nested_str_weak(clear), - /* K8 */ be_nested_str_weak(frame), - /* K9 */ be_nested_str_weak(layer), - /* K10 */ be_nested_str_weak(fast_loop_cb), - /* K11 */ be_nested_str_weak(back_color), - /* K12 */ be_const_int(0), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[33]) { /* code */ - 0xA40E0000, // 0000 IMPORT R3 K0 - 0x90020201, // 0001 SETMBR R0 K1 R1 - 0x4C100000, // 0002 LDNIL R4 - 0x1C100404, // 0003 EQ R4 R2 R4 - 0x78120000, // 0004 JMPF R4 #0006 - 0x540A0031, // 0005 LDINT R2 50 - 0x90020402, // 0006 SETMBR R0 K2 R2 - 0x50100000, // 0007 LDBOOL R4 0 0 - 0x90020604, // 0008 SETMBR R0 K3 R4 - 0x8C100304, // 0009 GETMET R4 R1 K4 - 0x7C100200, // 000A CALL R4 1 - 0x90020804, // 000B SETMBR R0 K4 R4 - 0x60100012, // 000C GETGBL R4 G18 - 0x7C100000, // 000D CALL R4 0 - 0x90020A04, // 000E SETMBR R0 K5 R4 - 0x60100012, // 000F GETGBL R4 G18 - 0x7C100000, // 0010 CALL R4 0 - 0x90020C04, // 0011 SETMBR R0 K6 R4 - 0x8C100107, // 0012 GETMET R4 R0 K7 - 0x7C100200, // 0013 CALL R4 1 - 0x8C100708, // 0014 GETMET R4 R3 K8 - 0x88180104, // 0015 GETMBR R6 R0 K4 - 0x7C100400, // 0016 CALL R4 2 - 0x90021004, // 0017 SETMBR R0 K8 R4 - 0x8C100708, // 0018 GETMET R4 R3 K8 - 0x88180104, // 0019 GETMBR R6 R0 K4 - 0x7C100400, // 001A CALL R4 2 - 0x90021204, // 001B SETMBR R0 K9 R4 - 0x84100000, // 001C CLOSURE R4 P0 - 0x90021404, // 001D SETMBR R0 K10 R4 - 0x9002170C, // 001E SETMBR R0 K11 K12 - 0xA0000000, // 001F CLOSE R0 - 0x80000000, // 0020 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: add_painter -********************************************************************/ -be_local_closure(Animate_core_add_painter, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(painters), - /* K1 */ be_nested_str_weak(push), - }), - be_str_weak(add_painter), - &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x80000000, // 0004 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_bri -********************************************************************/ -be_local_closure(Animate_core_get_bri, /* name */ - be_nested_proto( - 3, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(bri), - }), - be_str_weak(get_bri), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x80040400, // 0001 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: fast_loop ********************************************************************/ @@ -583,6 +139,189 @@ be_local_closure(Animate_core_fast_loop, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: add_animator +********************************************************************/ +be_local_closure(Animate_core_add_animator, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(animators), + /* K1 */ be_nested_str_weak(push), + }), + be_str_weak(add_animator), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: remove_painter +********************************************************************/ +be_local_closure(Animate_core_remove_painter, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(painters), + /* K1 */ be_nested_str_weak(remove), + /* K2 */ be_nested_str_weak(find), + /* K3 */ be_nested_str_weak(clear), + }), + be_str_weak(remove_painter), + &be_const_str_solidified, + ( &(const binstruction[13]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x200C0203, // 0002 NE R3 R1 R3 + 0x780E0005, // 0003 JMPF R3 #000A + 0x8C0C0501, // 0004 GETMET R3 R2 K1 + 0x8C140502, // 0005 GETMET R5 R2 K2 + 0x5C1C0200, // 0006 MOVE R7 R1 + 0x7C140400, // 0007 CALL R5 2 + 0x7C0C0400, // 0008 CALL R3 2 + 0x70020001, // 0009 JMP #000C + 0x8C0C0503, // 000A GETMET R3 R2 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: remove_animator +********************************************************************/ +be_local_closure(Animate_core_remove_animator, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(animators), + /* K1 */ be_nested_str_weak(remove), + /* K2 */ be_nested_str_weak(find), + /* K3 */ be_nested_str_weak(clear), + }), + be_str_weak(remove_animator), + &be_const_str_solidified, + ( &(const binstruction[13]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x200C0203, // 0002 NE R3 R1 R3 + 0x780E0005, // 0003 JMPF R3 #000A + 0x8C0C0501, // 0004 GETMET R3 R2 K1 + 0x8C140502, // 0005 GETMET R5 R2 K2 + 0x5C1C0200, // 0006 MOVE R7 R1 + 0x7C140400, // 0007 CALL R5 2 + 0x7C0C0400, // 0008 CALL R3 2 + 0x70020001, // 0009 JMP #000C + 0x8C0C0503, // 000A GETMET R3 R2 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: remove +********************************************************************/ +be_local_closure(Animate_core_remove, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(clear), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(remove_fast_loop), + /* K3 */ be_nested_str_weak(fast_loop_cb), + }), + be_str_weak(remove), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0xB8060200, // 0002 GETNGBL R1 K1 + 0x8C040302, // 0003 GETMET R1 R1 K2 + 0x880C0103, // 0004 GETMBR R3 R0 K3 + 0x7C040400, // 0005 CALL R1 2 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_background_animator +********************************************************************/ +be_local_closure(Animate_core_add_background_animator, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(set_cb), + /* K1 */ be_nested_str_weak(set_back_color), + /* K2 */ be_nested_str_weak(add_animator), + }), + be_str_weak(add_background_animator), + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x8C080300, // 0000 GETMET R2 R1 K0 + 0x5C100000, // 0001 MOVE R4 R0 + 0x88140101, // 0002 GETMBR R5 R0 K1 + 0x7C080600, // 0003 CALL R2 3 + 0x8C080102, // 0004 GETMET R2 R0 K2 + 0x5C100200, // 0005 MOVE R4 R1 + 0x7C080400, // 0006 CALL R2 2 + 0x80000000, // 0007 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: start ********************************************************************/ @@ -636,42 +375,387 @@ be_local_closure(Animate_core_start, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: clear +********************************************************************/ +be_local_closure(Animate_core_clear, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(stop), + /* K1 */ be_nested_str_weak(strip), + /* K2 */ be_nested_str_weak(clear), + }), + be_str_weak(clear), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x88040101, // 0002 GETMBR R1 R0 K1 + 0x8C040302, // 0003 GETMET R1 R1 K2 + 0x7C040200, // 0004 CALL R1 1 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_core_init, /* name */ + be_nested_proto( + 7, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 1]) { + be_nested_proto( + 2, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(fast_loop), + }), + be_str_weak(_anonymous_), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x7C000200, // 0002 CALL R0 1 + 0x80000000, // 0003 RET 0 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[13]) { /* constants */ + /* K0 */ be_nested_str_weak(animate), + /* K1 */ be_nested_str_weak(strip), + /* K2 */ be_nested_str_weak(bri), + /* K3 */ be_nested_str_weak(running), + /* K4 */ be_nested_str_weak(pixel_count), + /* K5 */ be_nested_str_weak(animators), + /* K6 */ be_nested_str_weak(painters), + /* K7 */ be_nested_str_weak(clear), + /* K8 */ be_nested_str_weak(frame), + /* K9 */ be_nested_str_weak(layer), + /* K10 */ be_nested_str_weak(fast_loop_cb), + /* K11 */ be_nested_str_weak(back_color), + /* K12 */ be_const_int(0), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[33]) { /* code */ + 0xA40E0000, // 0000 IMPORT R3 K0 + 0x90020201, // 0001 SETMBR R0 K1 R1 + 0x4C100000, // 0002 LDNIL R4 + 0x1C100404, // 0003 EQ R4 R2 R4 + 0x78120000, // 0004 JMPF R4 #0006 + 0x540A0031, // 0005 LDINT R2 50 + 0x90020402, // 0006 SETMBR R0 K2 R2 + 0x50100000, // 0007 LDBOOL R4 0 0 + 0x90020604, // 0008 SETMBR R0 K3 R4 + 0x8C100304, // 0009 GETMET R4 R1 K4 + 0x7C100200, // 000A CALL R4 1 + 0x90020804, // 000B SETMBR R0 K4 R4 + 0x60100012, // 000C GETGBL R4 G18 + 0x7C100000, // 000D CALL R4 0 + 0x90020A04, // 000E SETMBR R0 K5 R4 + 0x60100012, // 000F GETGBL R4 G18 + 0x7C100000, // 0010 CALL R4 0 + 0x90020C04, // 0011 SETMBR R0 K6 R4 + 0x8C100107, // 0012 GETMET R4 R0 K7 + 0x7C100200, // 0013 CALL R4 1 + 0x8C100708, // 0014 GETMET R4 R3 K8 + 0x88180104, // 0015 GETMBR R6 R0 K4 + 0x7C100400, // 0016 CALL R4 2 + 0x90021004, // 0017 SETMBR R0 K8 R4 + 0x8C100708, // 0018 GETMET R4 R3 K8 + 0x88180104, // 0019 GETMBR R6 R0 K4 + 0x7C100400, // 001A CALL R4 2 + 0x90021204, // 001B SETMBR R0 K9 R4 + 0x84100000, // 001C CLOSURE R4 P0 + 0x90021404, // 001D SETMBR R0 K10 R4 + 0x9002170C, // 001E SETMBR R0 K11 K12 + 0xA0000000, // 001F CLOSE R0 + 0x80000000, // 0020 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: stop +********************************************************************/ +be_local_closure(Animate_core_stop, /* name */ + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_str_weak(running), + /* K1 */ be_nested_str_weak(animators), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(stop), + /* K4 */ be_const_int(1), + /* K5 */ be_nested_str_weak(tasmota), + /* K6 */ be_nested_str_weak(remove_fast_loop), + /* K7 */ be_nested_str_weak(fast_loop_cb), + }), + be_str_weak(stop), + &be_const_str_solidified, + ( &(const binstruction[19]) { /* code */ + 0x50040000, // 0000 LDBOOL R1 0 0 + 0x90020001, // 0001 SETMBR R0 K0 R1 + 0x88040101, // 0002 GETMBR R1 R0 K1 + 0x58080002, // 0003 LDCONST R2 K2 + 0x600C000C, // 0004 GETGBL R3 G12 + 0x5C100200, // 0005 MOVE R4 R1 + 0x7C0C0200, // 0006 CALL R3 1 + 0x140C0403, // 0007 LT R3 R2 R3 + 0x780E0004, // 0008 JMPF R3 #000E + 0x940C0202, // 0009 GETIDX R3 R1 R2 + 0x8C0C0703, // 000A GETMET R3 R3 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0x00080504, // 000C ADD R2 R2 K4 + 0x7001FFF5, // 000D JMP #0004 + 0xB80E0A00, // 000E GETNGBL R3 K5 + 0x8C0C0706, // 000F GETMET R3 R3 K6 + 0x88140107, // 0010 GETMBR R5 R0 K7 + 0x7C0C0400, // 0011 CALL R3 2 + 0x80000000, // 0012 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: animate +********************************************************************/ +be_local_closure(Animate_core_animate, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(animate), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_cb +********************************************************************/ +be_local_closure(Animate_core_set_cb, /* name */ + be_nested_proto( + 3, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(obj), + /* K1 */ be_nested_str_weak(mth), + }), + be_str_weak(set_cb), + &be_const_str_solidified, + ( &(const binstruction[ 3]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_painter +********************************************************************/ +be_local_closure(Animate_core_add_painter, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(painters), + /* K1 */ be_nested_str_weak(push), + }), + be_str_weak(add_painter), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_bri +********************************************************************/ +be_local_closure(Animate_core_get_bri, /* name */ + be_nested_proto( + 3, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(bri), + }), + be_str_weak(get_bri), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x80040400, // 0001 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_back_color +********************************************************************/ +be_local_closure(Animate_core_set_back_color, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(back_color), + }), + be_str_weak(set_back_color), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_bri +********************************************************************/ +be_local_closure(Animate_core_set_bri, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(bri), + }), + be_str_weak(set_bri), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified class: Animate_core ********************************************************************/ be_local_class(Animate_core, 13, NULL, - be_nested_map(28, + be_nested_map(30, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(bri, 8), be_const_var(2) }, - { be_const_key_weak(remove, -1), be_const_closure(Animate_core_remove_closure) }, - { be_const_key_weak(start, 11), be_const_closure(Animate_core_start_closure) }, - { be_const_key_weak(fast_loop, -1), be_const_closure(Animate_core_fast_loop_closure) }, - { be_const_key_weak(add_animator, -1), be_const_closure(Animate_core_add_animator_closure) }, - { be_const_key_weak(FAST_LOOP_MIN, 9), be_const_int(20) }, - { be_const_key_weak(obj, -1), be_const_var(8) }, + { be_const_key_weak(running, -1), be_const_var(3) }, { be_const_key_weak(pixel_count, -1), be_const_var(1) }, - { be_const_key_weak(animate, -1), be_const_closure(Animate_core_animate_closure) }, - { be_const_key_weak(animators, -1), be_const_var(4) }, - { be_const_key_weak(fast_loop_cb, -1), be_const_var(6) }, - { be_const_key_weak(get_bri, 24), be_const_closure(Animate_core_get_bri_closure) }, - { be_const_key_weak(back_color, 13), be_const_var(12) }, + { be_const_key_weak(fast_loop, -1), be_const_closure(Animate_core_fast_loop_closure) }, + { be_const_key_weak(animators, 8), be_const_var(4) }, + { be_const_key_weak(fast_loop_cb, 7), be_const_var(6) }, + { be_const_key_weak(set_back_color, 26), be_const_closure(Animate_core_set_back_color_closure) }, + { be_const_key_weak(add_animator, -1), be_const_closure(Animate_core_add_animator_closure) }, { be_const_key_weak(frame, -1), be_const_var(10) }, - { be_const_key_weak(set_cb, 23), be_const_closure(Animate_core_set_cb_closure) }, + { be_const_key_weak(strip, 27), be_const_var(0) }, + { be_const_key_weak(remove_animator, 5), be_const_closure(Animate_core_remove_animator_closure) }, { be_const_key_weak(init, -1), be_const_closure(Animate_core_init_closure) }, - { be_const_key_weak(running, 21), be_const_var(3) }, - { be_const_key_weak(strip, 14), be_const_var(0) }, - { be_const_key_weak(fast_loop_next, -1), be_const_var(7) }, - { be_const_key_weak(set_back_color, 15), be_const_closure(Animate_core_set_back_color_closure) }, - { be_const_key_weak(add_painter, -1), be_const_closure(Animate_core_add_painter_closure) }, + { be_const_key_weak(start, -1), be_const_closure(Animate_core_start_closure) }, { be_const_key_weak(mth, -1), be_const_var(9) }, - { be_const_key_weak(layer, 12), be_const_var(11) }, + { be_const_key_weak(add_painter, -1), be_const_closure(Animate_core_add_painter_closure) }, + { be_const_key_weak(clear, -1), be_const_closure(Animate_core_clear_closure) }, + { be_const_key_weak(remove_painter, 23), be_const_closure(Animate_core_remove_painter_closure) }, + { be_const_key_weak(layer, -1), be_const_var(11) }, { be_const_key_weak(stop, -1), be_const_closure(Animate_core_stop_closure) }, + { be_const_key_weak(fast_loop_next, 16), be_const_var(7) }, + { be_const_key_weak(FAST_LOOP_MIN, -1), be_const_int(20) }, + { be_const_key_weak(animate, -1), be_const_closure(Animate_core_animate_closure) }, + { be_const_key_weak(back_color, -1), be_const_var(12) }, + { be_const_key_weak(obj, 21), be_const_var(8) }, + { be_const_key_weak(set_cb, 10), be_const_closure(Animate_core_set_cb_closure) }, + { be_const_key_weak(bri, 13), be_const_var(2) }, + { be_const_key_weak(get_bri, -1), be_const_closure(Animate_core_get_bri_closure) }, + { be_const_key_weak(painters, 28), be_const_var(5) }, + { be_const_key_weak(add_background_animator, 1), be_const_closure(Animate_core_add_background_animator_closure) }, + { be_const_key_weak(remove, -1), be_const_closure(Animate_core_remove_closure) }, { be_const_key_weak(set_bri, -1), be_const_closure(Animate_core_set_bri_closure) }, - { be_const_key_weak(painters, -1), be_const_var(5) }, - { be_const_key_weak(clear, 3), be_const_closure(Animate_core_clear_closure) }, - { be_const_key_weak(add_background_animator, 2), be_const_closure(Animate_core_add_background_animator_closure) }, })), be_str_weak(Animate_core) ); diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h index a337b5f82..a1def1f3d 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h @@ -1106,11 +1106,11 @@ void be_load_Animate_palette_class(bvm *vm) { extern const bclass be_class_Animate_oscillator; /******************************************************************** -** Solidified function: set_b +** Solidified function: set_duty_cycle ********************************************************************/ -be_local_closure(Animate_oscillator_set_b, /* name */ +be_local_closure(Animate_oscillator_set_duty_cycle, /* name */ be_nested_proto( - 2, /* nstack */ + 3, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -1118,14 +1118,22 @@ be_local_closure(Animate_oscillator_set_b, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(b), + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_weak(duty_cycle), }), - be_str_weak(set_b), + be_str_weak(set_duty_cycle), &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 + ( &(const binstruction[ 9]) { /* code */ + 0x14080300, // 0000 LT R2 R1 K0 + 0x780A0000, // 0001 JMPF R2 #0003 + 0x58040000, // 0002 LDCONST R1 K0 + 0x540A0063, // 0003 LDINT R2 100 + 0x24080202, // 0004 GT R2 R1 R2 + 0x780A0000, // 0005 JMPF R2 #0007 + 0x54060063, // 0006 LDINT R1 100 + 0x90020201, // 0007 SETMBR R0 K1 R1 + 0x80000000, // 0008 RET 0 }) ) ); @@ -1159,6 +1167,100 @@ be_local_closure(Animate_oscillator_set_a, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: set_b +********************************************************************/ +be_local_closure(Animate_oscillator_set_b, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(b), + }), + be_str_weak(set_b), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_form +********************************************************************/ +be_local_closure(Animate_oscillator_set_form, /* name */ + be_nested_proto( + 3, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_const_int(1), + /* K1 */ be_nested_str_weak(form), + }), + be_str_weak(set_form), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x1C080202, // 0001 EQ R2 R1 R2 + 0x780A0000, // 0002 JMPF R2 #0004 + 0x58040000, // 0003 LDCONST R1 K0 + 0x90020201, // 0004 SETMBR R0 K1 R1 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_phase +********************************************************************/ +be_local_closure(Animate_oscillator_set_phase, /* name */ + be_nested_proto( + 3, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_weak(phase), + }), + be_str_weak(set_phase), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x14080300, // 0000 LT R2 R1 K0 + 0x780A0000, // 0001 JMPF R2 #0003 + 0x58040000, // 0002 LDCONST R1 K0 + 0x540A0063, // 0003 LDINT R2 100 + 0x24080202, // 0004 GT R2 R1 R2 + 0x780A0000, // 0005 JMPF R2 #0007 + 0x54060063, // 0006 LDINT R1 100 + 0x90020201, // 0007 SETMBR R0 K1 R1 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: init ********************************************************************/ @@ -1400,76 +1502,6 @@ be_local_closure(Animate_oscillator_animate, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: set_duty_cycle -********************************************************************/ -be_local_closure(Animate_oscillator_set_duty_cycle, /* name */ - be_nested_proto( - 3, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str_weak(duty_cycle), - }), - be_str_weak(set_duty_cycle), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0x14080300, // 0000 LT R2 R1 K0 - 0x780A0000, // 0001 JMPF R2 #0003 - 0x58040000, // 0002 LDCONST R1 K0 - 0x540A0063, // 0003 LDINT R2 100 - 0x24080202, // 0004 GT R2 R1 R2 - 0x780A0000, // 0005 JMPF R2 #0007 - 0x54060063, // 0006 LDINT R1 100 - 0x90020201, // 0007 SETMBR R0 K1 R1 - 0x80000000, // 0008 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_phase -********************************************************************/ -be_local_closure(Animate_oscillator_set_phase, /* name */ - be_nested_proto( - 3, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str_weak(phase), - }), - be_str_weak(set_phase), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0x14080300, // 0000 LT R2 R1 K0 - 0x780A0000, // 0001 JMPF R2 #0003 - 0x58040000, // 0002 LDCONST R1 K0 - 0x540A0063, // 0003 LDINT R2 100 - 0x24080202, // 0004 GT R2 R1 R2 - 0x780A0000, // 0005 JMPF R2 #0007 - 0x54060063, // 0006 LDINT R1 100 - 0x90020201, // 0007 SETMBR R0 K1 R1 - 0x80000000, // 0008 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified class: Animate_oscillator ********************************************************************/ @@ -1477,20 +1509,21 @@ extern const bclass be_class_Animate_animator; be_local_class(Animate_oscillator, 6, &be_class_Animate_animator, - be_nested_map(12, + be_nested_map(13, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(phase, -1), be_const_var(0) }, - { be_const_key_weak(b, -1), be_const_var(3) }, - { be_const_key_weak(set_b, -1), be_const_closure(Animate_oscillator_set_b_closure) }, - { be_const_key_weak(set_a, 10), be_const_closure(Animate_oscillator_set_a_closure) }, + { be_const_key_weak(animate, -1), be_const_closure(Animate_oscillator_animate_closure) }, { be_const_key_weak(a, -1), be_const_var(2) }, - { be_const_key_weak(set_phase, -1), be_const_closure(Animate_oscillator_set_phase_closure) }, + { be_const_key_weak(init, 11), be_const_closure(Animate_oscillator_init_closure) }, + { be_const_key_weak(duty_cycle, 10), be_const_var(1) }, + { be_const_key_weak(b, -1), be_const_var(3) }, { be_const_key_weak(value, -1), be_const_var(5) }, - { be_const_key_weak(duty_cycle, -1), be_const_var(1) }, - { be_const_key_weak(animate, 7), be_const_closure(Animate_oscillator_animate_closure) }, - { be_const_key_weak(set_duty_cycle, -1), be_const_closure(Animate_oscillator_set_duty_cycle_closure) }, - { be_const_key_weak(init, -1), be_const_closure(Animate_oscillator_init_closure) }, - { be_const_key_weak(form, 5), be_const_var(4) }, + { be_const_key_weak(set_duty_cycle, 2), be_const_closure(Animate_oscillator_set_duty_cycle_closure) }, + { be_const_key_weak(set_a, -1), be_const_closure(Animate_oscillator_set_a_closure) }, + { be_const_key_weak(set_b, -1), be_const_closure(Animate_oscillator_set_b_closure) }, + { be_const_key_weak(set_form, -1), be_const_closure(Animate_oscillator_set_form_closure) }, + { be_const_key_weak(phase, -1), be_const_var(0) }, + { be_const_key_weak(form, -1), be_const_var(4) }, + { be_const_key_weak(set_phase, 0), be_const_closure(Animate_oscillator_set_phase_closure) }, })), be_str_weak(Animate_oscillator) ); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino index 47d80c98f..9ac9c4c45 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino @@ -348,13 +348,16 @@ extern "C" { uint32_t r = (color_a >> 16) & 0xFF; uint32_t g = (color_a >> 8) & 0xFF; uint32_t b = (color_a ) & 0xFF; + uint32_t a = (color_a >> 24) & 0xFF; uint32_t r2 = (color_b >> 16) & 0xFF; uint32_t g2 = (color_b >> 8) & 0xFF; uint32_t b2 = (color_b ) & 0xFF; + uint32_t a2 = (color_b >> 24) & 0xFF; uint32_t r3 = changeUIntScale(alpha, 0, 255, r2, r); uint32_t g3 = changeUIntScale(alpha, 0, 255, g2, g); uint32_t b3 = changeUIntScale(alpha, 0, 255, b2, b); - uint32_t rgb = (r3 << 16) | (g3 << 8) | b3; + uint32_t a3 = changeUIntScale(alpha, 0, 255, a2, a); + uint32_t rgb = (a3 << 24) | (r3 << 16) | (g3 << 8) | b3; be_pushint(vm, rgb); be_return(vm); } From 7c290388d9ca70501536d0939178d574890567d8 Mon Sep 17 00:00:00 2001 From: Barbudor Date: Sat, 16 Dec 2023 18:23:51 +0100 Subject: [PATCH 010/303] Sonoff Basic R4 Magic switch (#20247) * magic switch take 1 * good to go * good to go * final, including in tasmota32c3 --- .../include/tasmota_configurations_ESP32.h | 3 + tasmota/include/tasmota_template.h | 7 + tasmota/language/af_AF.h | 3 +- tasmota/language/bg_BG.h | 1 + tasmota/language/ca_AD.h | 1 + tasmota/language/cs_CZ.h | 1 + tasmota/language/de_DE.h | 1 + tasmota/language/el_GR.h | 1 + tasmota/language/en_GB.h | 1 + tasmota/language/es_ES.h | 1 + tasmota/language/fr_FR.h | 1 + tasmota/language/fy_NL.h | 1 + tasmota/language/he_HE.h | 1 + tasmota/language/hu_HU.h | 1 + tasmota/language/it_IT.h | 3 +- tasmota/language/ko_KO.h | 1 + tasmota/language/nl_NL.h | 1 + tasmota/language/pl_PL.h | 1 + tasmota/language/pt_BR.h | 1 + tasmota/language/pt_PT.h | 1 + tasmota/language/ro_RO.h | 1 + tasmota/language/ru_RU.h | 1 + tasmota/language/sk_SK.h | 1 + tasmota/language/sv_SE.h | 1 + tasmota/language/tr_TR.h | 1 + tasmota/language/uk_UA.h | 1 + tasmota/language/vi_VN.h | 1 + tasmota/language/zh_CN.h | 1 + tasmota/language/zh_TW.h | 1 + tasmota/my_user_config.h | 3 + .../xdrv_91_magic_switch.ino | 187 ++++++++++++++++++ 31 files changed, 229 insertions(+), 2 deletions(-) create mode 100644 tasmota/tasmota_xdrv_driver/xdrv_91_magic_switch.ino diff --git a/tasmota/include/tasmota_configurations_ESP32.h b/tasmota/include/tasmota_configurations_ESP32.h index 4a9716d16..06891b607 100644 --- a/tasmota/include/tasmota_configurations_ESP32.h +++ b/tasmota/include/tasmota_configurations_ESP32.h @@ -606,6 +606,9 @@ #define USE_LIGHT_PALETTE // Add support for color palette (+0k9 code) #define USE_LIGHT_ARTNET // Add support for DMX/ArtNet via UDP on port 6454 (+3.5k code) +#ifdef CONFIG_IDF_TARGET_ESP32C3 +#define USE_MAGIC_SWITCH // Add Sonoff MagicSwitch support as implemented in Sonoff Basic R4 +#endif #define USE_DS18x20 // Add support for DS18x20 sensors with id sort, single scan and read retry (+1k3 code) diff --git a/tasmota/include/tasmota_template.h b/tasmota/include/tasmota_template.h index 260e59a46..63779e918 100644 --- a/tasmota/include/tasmota_template.h +++ b/tasmota/include/tasmota_template.h @@ -214,6 +214,7 @@ enum UserSelectablePins { GPIO_HDMI_CEC, // Support for HDMI CEC GPIO_HC8_RXD, // HC8 Serial interface GPIO_I2S_DAC, // Audio DAC support for ESP32 and ESP32S2 + GPIO_MAGIC_SWITCH, // MagicSwitch as in Sonoff BasicR4 GPIO_SENSOR_END }; // Error as warning to rethink GPIO usage with max 2045 @@ -475,6 +476,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_HDMI_CEC "|" D_SENSOR_HC8_RX "|" D_SENSOR_I2S_DAC "|" + D_GPIO_MAGIC_SWITCH "|" ; const char kSensorNamesFixed[] PROGMEM = @@ -493,6 +495,7 @@ const char kSensorNamesFixed[] PROGMEM = #define MAX_DSB 4 #define MAX_BP1658CJ_DAT 16 #define MAX_DINGTIAN_SHIFT 4 +#define MAX_MAGIC_SWITCH_MODES 2 #define MAX_BL0942_RX 4 // Baudrates 1 (4800), 2 (9600), 3 (19200), 4 (38400) const uint16_t kGpioNiceList[] PROGMEM = { @@ -1143,6 +1146,10 @@ const uint16_t kGpioNiceList[] PROGMEM = { AGPIO(GPIO_DINGTIAN_RCK), #endif +#ifdef USE_MAGIC_SWITCH + AGPIO(GPIO_MAGIC_SWITCH) + MAX_MAGIC_SWITCH_MODES, +#endif + /*-------------------------------------------------------------------------------------------*\ * ESP32 specifics \*-------------------------------------------------------------------------------------------*/ diff --git a/tasmota/language/af_AF.h b/tasmota/language/af_AF.h index 95a4ff647..d90ee06c7 100644 --- a/tasmota/language/af_AF.h +++ b/tasmota/language/af_AF.h @@ -288,7 +288,7 @@ #define D_RESET_CONFIGURATION "Stel die konfigurasie terug" #define D_BACKUP_CONFIGURATION "Rugsteun die konfigurasie" #define D_RESTORE_CONFIGURATION "Herstel die konfigurasie" -#define D_START_RESTORE "Start restore" +#define D_START_RESTORE "Start restore" #define D_MAIN_MENU "Hoofkieslys" #define D_MODULE_PARAMETERS "Moduleparameters" @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index b7f00e51a..bffd921e2 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "А" diff --git a/tasmota/language/ca_AD.h b/tasmota/language/ca_AD.h index 4683b5c55..834481513 100644 --- a/tasmota/language/ca_AD.h +++ b/tasmota/language/ca_AD.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index 1441d328d..9a8197a40 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index 8d5ef0279..c76ddbb29 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h index 4cf6fc13e..1edf65357 100644 --- a/tasmota/language/el_GR.h +++ b/tasmota/language/el_GR.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index aa91d4c55..139316d74 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h index 06add4a53..8c0ed3475 100644 --- a/tasmota/language/es_ES.h +++ b/tasmota/language/es_ES.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index 861fe57cb..0e89c0560 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units diff --git a/tasmota/language/fy_NL.h b/tasmota/language/fy_NL.h index cf4d8a187..436782c93 100644 --- a/tasmota/language/fy_NL.h +++ b/tasmota/language/fy_NL.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index e4199ab15..d489b2f64 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index 914ae053a..a9715ef10 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -960,6 +960,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index 46b6a50cd..1a412fcff 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -956,7 +956,8 @@ #define D_SENSOR_BIOPDU_PZEM0XX_TX "BioPDU PZEM0XX - TX" #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 - RX" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" -#define D_SENSOR_LOX_O2_RX "LoxO2 - RX" +#define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index 9ceffb0ab..8fe87643b 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index 9927eb5e0..1ad5fa61f 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h index 1f1f44bef..7693b986d 100644 --- a/tasmota/language/pl_PL.h +++ b/tasmota/language/pl_PL.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index 3dac6d2bc..0ee9a4433 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index 8ae556c7e..e94a640f2 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index 6f09c9a27..b90c3a960 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h index 9de1e95cb..82f01ca3f 100644 --- a/tasmota/language/ru_RU.h +++ b/tasmota/language/ru_RU.h @@ -958,6 +958,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "А" diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index e943a2438..5ea1875bd 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index 72e940b12..99d27f132 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index 259825231..3377a17f6 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index ad9834916..d8b33392d 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "А" diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h index 4f4297646..990f558a0 100644 --- a/tasmota/language/vi_VN.h +++ b/tasmota/language/vi_VN.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index 1c49fd023..dc0a6ec4c 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index f45bb2b90..992838e00 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -957,6 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "安培" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 2f5543e15..22a7fb877 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -538,6 +538,9 @@ #define SHELLY_CMDS // Add command to send co-processor commands (+0k3 code) #define SHELLY_FW_UPGRADE // Add firmware upgrade option for co-processor (+3k4 code) // #define SHELLY_VOLTAGE_MON // Add support for reading voltage and current measurment (-0k0 code) +//#define USE_MAGIC_SWITCH // Add Sonoff MagicSwitch support as implemented in Sonoff Basic R4 (+612B flash, +64B IRAM for intr) +// #define MAGICSWITCH_MIN_PULSE 4000 // Overridable minimum pulse, also overridable by command MagicSwitchPulse (not saved to flash) +// #define MAGICSWITCH_MASKING_WINDOW_LEN 5 // Overridable masking window (in number of 50ms loops) // -- Optional light modules ---------------------- #define USE_LIGHT // Add support for light control diff --git a/tasmota/tasmota_xdrv_driver/xdrv_91_magic_switch.ino b/tasmota/tasmota_xdrv_driver/xdrv_91_magic_switch.ino new file mode 100644 index 000000000..5356ada69 --- /dev/null +++ b/tasmota/tasmota_xdrv_driver/xdrv_91_magic_switch.ino @@ -0,0 +1,187 @@ +/* + xdrv_91_magic_switch.ino - Driver for MagicSwitch as implemented in Sonoff BasicR4 + + Copyright (C) 2021 Barbudor + + 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 . +*/ + +#ifdef USE_MAGIC_SWITCH + +#define XDRV_91 91 + +/******************************************************************************************************** + * Check defines + */ + +#ifndef MAGICSWITCH_MIN_PULSE +#define MAGICSWITCH_MIN_PULSE 4000 +#endif + +#ifndef MAGICSWITCH_MASKING_WINDOW_LEN +#define MAGICSWITCH_MASKING_WINDOW_LEN 5 +#endif + +/******************************************************************************************************** + * Global private data + */ + +// MagicSwitch Index => Mode +// +// +// +// Index Mode Pull-Up +// 1 0 Pull-Up +// 2 1 No Pull-up +// 3 2 Pull-Up +// 4 3 No Pull-up +// 5 4 Pull-Up +// 6 5 No Pull-up +// 7 6 Pull-Up +// 8 7 No Pull-up + +#define MAGICSWITCH_MODE_NO_PULLUP 0x01 + + +struct MAGICSWITCH_DATA { + uint32_t start_time; // timestamp at rising edge + uint32_t pulse_len; // measured pulse length + uint32_t min_pulse; // minimum pulse length + uint8_t switch_state; // switch state - count down for masking window + uint8_t pin; // the GPIO of the input + uint8_t mode; // mode + int8_t key_offset; // index of the MagicSwitch in the list of Switches +} *MagicSwitch = nullptr; + + +/******************************************************************************************************** + * Interrupt level operations + */ + +extern "C" void IRAM_ATTR MagicSwitch_intr(void *arg) { + struct MAGICSWITCH_DATA* ms = (struct MAGICSWITCH_DATA*)arg; + uint32_t now = micros(); + bool pin_state = digitalRead(ms->pin); + if (ms->pulse_len) { // previous pulse not aknowledged, ignoring the edge + return; + } else if (pin_state) { // rising edge (hopefully if we didn't missed), record start time + ms->start_time = now | 1; // "| 1" => avoid 1 in 4M chance to get 0 + } else if (ms->start_time) { // falling edge, compute pulse length + uint32_t pulse_len = now - ms->start_time; + ms->start_time = 0; // in case of missing an rising edge, avoid triggering false detection + if (pulse_len >= ms->min_pulse) + ms->pulse_len = pulse_len; + } +} + +/******************************************************************************************************** + * Driver operations + */ + +void MagicSwitchLoop() +{ + if (MagicSwitch->switch_state) { + MagicSwitch->switch_state--; + if (!MagicSwitch->switch_state) { + SwitchSetVirtualPinState(MagicSwitch->key_offset, 0); + MagicSwitch->pulse_len = 0; // acknowledge the pulse, close the masking window + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("MSW: end")); + } + } else if (MagicSwitch->pulse_len) { + SwitchSetVirtualPinState(MagicSwitch->key_offset, 1); + MagicSwitch->switch_state = MAGICSWITCH_MASKING_WINDOW_LEN; + AddLog(LOG_LEVEL_DEBUG, PSTR("MSW: length:%d, window:%d"), MagicSwitch->pulse_len, MagicSwitch->switch_state); + } +} + +/******************************************************************************************************** + * Driver initialisation + */ + +void MagicSwitchInit(void) { + if (PinUsed(GPIO_MAGIC_SWITCH, GPIO_ANY)) { + // allocate data structure + MagicSwitch = (struct MAGICSWITCH_DATA*)calloc(1, sizeof(struct MAGICSWITCH_DATA)); + if (MagicSwitch) { + // get pins + MagicSwitch->pin = Pin(GPIO_MAGIC_SWITCH, GPIO_ANY); // input + MagicSwitch->mode = GetPin(MagicSwitch->pin) - AGPIO(GPIO_MAGIC_SWITCH); // Index 1 => mode 0, etc... + MagicSwitch->key_offset = -1; // means not yet configured + MagicSwitch->min_pulse = MAGICSWITCH_MIN_PULSE; + + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("MSW: pin:%d, mode:%d"), MagicSwitch->pin, MagicSwitch->mode); + + pinMode(MagicSwitch->pin, (MagicSwitch->mode & MAGICSWITCH_MODE_NO_PULLUP) ? INPUT : INPUT_PULLUP); + attachInterruptArg(MagicSwitch->pin, MagicSwitch_intr, MagicSwitch, CHANGE); + } + } +} + +bool MagicSwitchAddSwitch(void) { + if (MagicSwitch->key_offset < 0) { + MagicSwitch->key_offset = XdrvMailbox.index; + Settings->switchmode[MagicSwitch->key_offset] = 4; + AddLog(LOG_LEVEL_INFO, PSTR("MSW: Switch %d, Switchmode 4"), MagicSwitch->key_offset + 1); + return true; + } + return false; +} + +/******************************************************************************************************** + * Commands + */ + +const char kMagicSwitchCommands[] PROGMEM = "MagicSwitch|" + "Pulse" + ; + +void (* const MagicSwitchCommand[])(void) PROGMEM = { + &CmndMagicSwitchPulse + }; + +void CmndMagicSwitchPulse(void) +{ + if ((XdrvMailbox.payload >= 1000) && (XdrvMailbox.payload < 500000)) { + MagicSwitch->min_pulse = XdrvMailbox.payload; + } + ResponseCmndNumber(MagicSwitch->min_pulse); +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv91(uint32_t function) { + bool result = false; + + if (FUNC_SETUP_RING2 == function) { + MagicSwitchInit(); + } else if (MagicSwitch) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + //case FUNC_EVERY_250_MSECOND: + MagicSwitchLoop(); + break; + case FUNC_ADD_SWITCH: + result = MagicSwitchAddSwitch(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kMagicSwitchCommands, MagicSwitchCommand); + break; + } + } + return result; +} + +#endif // USE_MAGIC_SWITCH From 70768ea8ad122b583c92c02db37dfdcd760e8d04 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 16 Dec 2023 18:29:09 +0100 Subject: [PATCH 011/303] Update changelogs --- CHANGELOG.md | 3 ++- RELEASENOTES.md | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a77974ef..adce0b539 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,10 @@ All notable changes to this project will be documented in this file. ## [13.3.0.1] ### Added +- Support for Sonoff Basic R4 Magic Switch (#20247) ### Breaking Changed -- Refactoring of Berry `animate` module for WS2812 Leds +- Refactoring of Berry `animate` module for WS2812 Leds (#20236) ### Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6eb72fe2e..7f886e45f 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -118,8 +118,10 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ## Changelog v13.3.0.1 ### Added +- Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247) ### Breaking Changed +- Refactoring of Berry `animate` module for WS2812 Leds [#20236](https://github.com/arendst/Tasmota/issues/20236) ### Changed From cc5eb732ea8e9581ddd311547832c98cd669f0bf Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 16 Dec 2023 22:38:04 +0100 Subject: [PATCH 012/303] Fix animation (#20250) --- lib/libesp32/berry_tasmota/src/be_animate_module.c | 14 ++++++-------- .../src/embedded/animate_1_animate_effects.be | 1 + .../solidified_animate_1_animate_effects.h | 8 +++++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/libesp32/berry_tasmota/src/be_animate_module.c b/lib/libesp32/berry_tasmota/src/be_animate_module.c index 688585f06..7d741e0a9 100644 --- a/lib/libesp32/berry_tasmota/src/be_animate_module.c +++ b/lib/libesp32/berry_tasmota/src/be_animate_module.c @@ -57,7 +57,7 @@ static const uint8_t PALETTE_STANDARD_TAG[] = { 0x40, 0x00, 0xFF, 0x00, // green 0x40, 0x00, 0x00, 0xFF, // blue 0x40, 0xFF, 0x00, 0xFF, // indigo - 0x40, 0xFF, 0xFF, 0xFF, // violet + 0x40, 0xEE, 0x44, 0xA5, // violet 0x00, 0xFF, 0x00, 0x00, // red }; @@ -72,12 +72,11 @@ static const uint8_t PALETTE_ib_jul01_gp[] = { static const uint8_t PALETTE_STANDARD_VAL[] = { 0x00, 0xFF, 0x00, 0x00, // red - 0x24, 0xFF, 0xA5, 0x00, // orange - 0x49, 0xFF, 0xFF, 0x00, // yellow - 0x6E, 0x00, 0xFF, 0x00, // green - 0x92, 0x00, 0x00, 0xFF, // blue - 0xB7, 0xFF, 0x00, 0xFF, // indigo - 0xDB, 0xFF, 0xFF, 0xFF, // violet + 0x2A, 0xFF, 0xA5, 0x00, // orange + 0x55, 0xFF, 0xFF, 0x00, // yellow + 0x7F, 0x00, 0xFF, 0x00, // green + 0xAA, 0x00, 0x00, 0xFF, // blue + 0xD4, 0xFF, 0x00, 0xFF, // indigo 0xFF, 0xFF, 0x00, 0x00, // red }; @@ -88,7 +87,6 @@ static const uint8_t PALETTE_SATURATED_TAG[] = { 0x40, 0x00, 0xFF, 0x00, // green 0x40, 0x00, 0x00, 0xFF, // blue 0x40, 0xFF, 0x00, 0xFF, // indigo - 0x40, 0xFF, 0xFF, 0xFF, // violet 0x00, 0xFF, 0x00, 0x00, // red }; diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_1_animate_effects.be b/lib/libesp32/berry_tasmota/src/embedded/animate_1_animate_effects.be index e2a5a9736..e96f37f93 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/animate_1_animate_effects.be +++ b/lib/libesp32/berry_tasmota/src/embedded/animate_1_animate_effects.be @@ -40,6 +40,7 @@ class Animate_pulse self.pulse_size = pulse_size if slew_size < 0 slew_size = 0 end self.slew_size = slew_size + self.pos = 0 end ## diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_animate_effects.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_animate_effects.h index bb8b9dee3..9831e5a6e 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_animate_effects.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_animate_effects.h @@ -154,7 +154,7 @@ be_local_closure(Animate_pulse_init, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ + ( &(const bvalue[ 9]) { /* constants */ /* K0 */ be_const_int(16777215), /* K1 */ be_const_int(1), /* K2 */ be_const_int(0), @@ -163,10 +163,11 @@ be_local_closure(Animate_pulse_init, /* name */ /* K5 */ be_const_int(-16777216), /* K6 */ be_nested_str_weak(pulse_size), /* K7 */ be_nested_str_weak(slew_size), + /* K8 */ be_nested_str_weak(pos), }), be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[23]) { /* code */ + ( &(const binstruction[24]) { /* code */ 0x4C100000, // 0000 LDNIL R4 0x1C100204, // 0001 EQ R4 R1 R4 0x78120000, // 0002 JMPF R4 #0004 @@ -189,7 +190,8 @@ be_local_closure(Animate_pulse_init, /* name */ 0x78120000, // 0013 JMPF R4 #0015 0x580C0002, // 0014 LDCONST R3 K2 0x90020E03, // 0015 SETMBR R0 K7 R3 - 0x80000000, // 0016 RET 0 + 0x90021102, // 0016 SETMBR R0 K8 K2 + 0x80000000, // 0017 RET 0 }) ) ); From dc98f6e1909a10ef995b976757dbc453358bb6cd Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 17 Dec 2023 20:47:18 +0100 Subject: [PATCH 013/303] Simplify animate (#20254) * Simplify animate * make add_ methods idempotent --- .../src/embedded/animate_0_core.be | 16 +- .../src/embedded/animate_1_animate_effects.be | 24 +- .../src/embedded/animate_9_module.be | 30 +- .../src/solidify/solidified_animate_0_core.h | 993 +++++++++--------- .../solidified_animate_1_animate_effects.h | 162 ++- .../solidify/solidified_animate_9_module.h | 670 ++++++------ .../animate_demo/animate_demo_breathe.be | 28 + .../berry/animate_demo/animate_demo_pulse.be | 4 - 8 files changed, 1102 insertions(+), 825 deletions(-) create mode 100644 tasmota/berry/animate_demo/animate_demo_breathe.be diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be b/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be index 5809ed3f3..747376d9d 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be +++ b/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be @@ -32,6 +32,7 @@ class Animate_core def init(strip, bri) import animate + self.strip = strip if (bri == nil) bri = 50 end self.bri = bri # percentage of brightness 0..100 @@ -46,6 +47,13 @@ class Animate_core # self.fast_loop_cb = def() self.fast_loop() end self.back_color = 0x000000 + # + self.set_current() + end + + # set this animate.core as the current animator for configuration + def set_current() + global._cur_anim = self # declare the current animate.core for painters and animators to register end # cb @@ -59,7 +67,9 @@ class Animate_core end def add_animator(anim) - self.animators.push(anim) + if self.animators.find(anim) == nil + self.animators.push(anim) + end end # remove a specific animator @@ -85,7 +95,9 @@ class Animate_core def add_painter(painter) - self.painters.push(painter) + if self.painters.find(painter) == nil + self.painters.push(painter) + end end def clear() diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_1_animate_effects.be b/lib/libesp32/berry_tasmota/src/embedded/animate_1_animate_effects.be index e96f37f93..a059ee85c 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/animate_1_animate_effects.be +++ b/lib/libesp32/berry_tasmota/src/embedded/animate_1_animate_effects.be @@ -1,5 +1,25 @@ # class Animate_pulse +#@ solidify:Animate_painter,weak +# painter superclass +class Animate_painter + + def init() + # register ourselves into the current animate.core + var core = global._cur_anim + if (core != nil) + core.add_painter(self) + end + end + + # return true if buffer was filled successfully + # + # Needs to be overwritten + def paint(frame) + end + +end + ########################################################################################## # # class Animate_pulse @@ -22,7 +42,7 @@ ########################################################################################## #@ solidify:Animate_pulse,weak -class Animate_pulse +class Animate_pulse : Animate_painter var color var back_color var pos @@ -30,6 +50,8 @@ class Animate_pulse var pulse_size def init(color, pulse_size, slew_size) + super(self).init() + if (color == nil) color = 0xFFFFFF end # white by default if (pulse_size == nil) pulse_size = 1 end if (slew_size == nil) slew_size = 0 end diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be b/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be index aa9ef07e6..46fdcb16f 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be +++ b/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be @@ -96,8 +96,12 @@ class Animate_animator var obj # object to call var mth # object method to call - def init(duration_ms) - self.duration_ms = duration_ms + def init() + # register ourselves into the current animate.core + var core = global._cur_anim + if (core != nil) + core.add_animator(self) + end end def set_duration_ms(duration_ms) @@ -155,16 +159,27 @@ class Animate_palette : Animate_animator var color # instance of light_state, used for color calculation (reuse of object) def init(palette, duration_ms) - super(self).init(duration_ms) + super(self).init() + + self.duration_ms = duration_ms self.running = false + self.bri = 100 + self.color = light_state(light_state.RGB) + # + self.set_palette(palette) + end + + # load or change palette + def set_palette(palette) if (type(palette) == 'ptr') palette = self.ptr_to_palette(palette) end # convert comptr to palette buffer self.palette = palette - self.bri = 100 self.slots = size(palette) / 4 - if duration_ms != nil - self.set_duration(duration_ms) + # recompute palette + if self.duration_ms != nil + self.set_duration(self.duration_ms) + elif (self.range_min != nil) && (self.range_max != nil) + self.set_range(self.range_min, self.range_max) end - self.color = light_state(light_state.RGB) end # setter to be used as cb @@ -415,6 +430,7 @@ class Animate_oscillator : Animate_animator var value def init(a, b, duration_ms, form) + super(self).init() self.phase = 0 self.duty_cycle = 50 self.a = a diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h index 2221e785c..cc86ccf2e 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h @@ -6,6 +6,482 @@ extern const bclass be_class_Animate_core; +/******************************************************************** +** Solidified function: start +********************************************************************/ +be_local_closure(Animate_core_start, /* name */ + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(running), + /* K1 */ be_nested_str_weak(animators), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(start), + /* K4 */ be_const_int(1), + /* K5 */ be_nested_str_weak(fast_loop_next), + /* K6 */ be_nested_str_weak(tasmota), + /* K7 */ be_nested_str_weak(add_fast_loop), + /* K8 */ be_nested_str_weak(fast_loop_cb), + }), + be_str_weak(start), + &be_const_str_solidified, + ( &(const binstruction[20]) { /* code */ + 0x50040200, // 0000 LDBOOL R1 1 0 + 0x90020001, // 0001 SETMBR R0 K0 R1 + 0x88040101, // 0002 GETMBR R1 R0 K1 + 0x58080002, // 0003 LDCONST R2 K2 + 0x600C000C, // 0004 GETGBL R3 G12 + 0x5C100200, // 0005 MOVE R4 R1 + 0x7C0C0200, // 0006 CALL R3 1 + 0x140C0403, // 0007 LT R3 R2 R3 + 0x780E0004, // 0008 JMPF R3 #000E + 0x940C0202, // 0009 GETIDX R3 R1 R2 + 0x8C0C0703, // 000A GETMET R3 R3 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0x00080504, // 000C ADD R2 R2 K4 + 0x7001FFF5, // 000D JMP #0004 + 0x90020B02, // 000E SETMBR R0 K5 K2 + 0xB80E0C00, // 000F GETNGBL R3 K6 + 0x8C0C0707, // 0010 GETMET R3 R3 K7 + 0x88140108, // 0011 GETMBR R5 R0 K8 + 0x7C0C0400, // 0012 CALL R3 2 + 0x80000000, // 0013 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: remove +********************************************************************/ +be_local_closure(Animate_core_remove, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(clear), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(remove_fast_loop), + /* K3 */ be_nested_str_weak(fast_loop_cb), + }), + be_str_weak(remove), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0xB8060200, // 0002 GETNGBL R1 K1 + 0x8C040302, // 0003 GETMET R1 R1 K2 + 0x880C0103, // 0004 GETMBR R3 R0 K3 + 0x7C040400, // 0005 CALL R1 2 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_background_animator +********************************************************************/ +be_local_closure(Animate_core_add_background_animator, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(set_cb), + /* K1 */ be_nested_str_weak(set_back_color), + /* K2 */ be_nested_str_weak(add_animator), + }), + be_str_weak(add_background_animator), + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x8C080300, // 0000 GETMET R2 R1 K0 + 0x5C100000, // 0001 MOVE R4 R0 + 0x88140101, // 0002 GETMBR R5 R0 K1 + 0x7C080600, // 0003 CALL R2 3 + 0x8C080102, // 0004 GETMET R2 R0 K2 + 0x5C100200, // 0005 MOVE R4 R1 + 0x7C080400, // 0006 CALL R2 2 + 0x80000000, // 0007 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: remove_painter +********************************************************************/ +be_local_closure(Animate_core_remove_painter, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(painters), + /* K1 */ be_nested_str_weak(remove), + /* K2 */ be_nested_str_weak(find), + /* K3 */ be_nested_str_weak(clear), + }), + be_str_weak(remove_painter), + &be_const_str_solidified, + ( &(const binstruction[13]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x200C0203, // 0002 NE R3 R1 R3 + 0x780E0005, // 0003 JMPF R3 #000A + 0x8C0C0501, // 0004 GETMET R3 R2 K1 + 0x8C140502, // 0005 GETMET R5 R2 K2 + 0x5C1C0200, // 0006 MOVE R7 R1 + 0x7C140400, // 0007 CALL R5 2 + 0x7C0C0400, // 0008 CALL R3 2 + 0x70020001, // 0009 JMP #000C + 0x8C0C0503, // 000A GETMET R3 R2 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_animator +********************************************************************/ +be_local_closure(Animate_core_add_animator, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(animators), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(push), + }), + be_str_weak(add_animator), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x4C0C0000, // 0004 LDNIL R3 + 0x1C080403, // 0005 EQ R2 R2 R3 + 0x780A0003, // 0006 JMPF R2 #000B + 0x88080100, // 0007 GETMBR R2 R0 K0 + 0x8C080502, // 0008 GETMET R2 R2 K2 + 0x5C100200, // 0009 MOVE R4 R1 + 0x7C080400, // 000A CALL R2 2 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: animate +********************************************************************/ +be_local_closure(Animate_core_animate, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(animate), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: clear +********************************************************************/ +be_local_closure(Animate_core_clear, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(stop), + /* K1 */ be_nested_str_weak(strip), + /* K2 */ be_nested_str_weak(clear), + }), + be_str_weak(clear), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x88040101, // 0002 GETMBR R1 R0 K1 + 0x8C040302, // 0003 GETMET R1 R1 K2 + 0x7C040200, // 0004 CALL R1 1 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: stop +********************************************************************/ +be_local_closure(Animate_core_stop, /* name */ + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_str_weak(running), + /* K1 */ be_nested_str_weak(animators), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(stop), + /* K4 */ be_const_int(1), + /* K5 */ be_nested_str_weak(tasmota), + /* K6 */ be_nested_str_weak(remove_fast_loop), + /* K7 */ be_nested_str_weak(fast_loop_cb), + }), + be_str_weak(stop), + &be_const_str_solidified, + ( &(const binstruction[19]) { /* code */ + 0x50040000, // 0000 LDBOOL R1 0 0 + 0x90020001, // 0001 SETMBR R0 K0 R1 + 0x88040101, // 0002 GETMBR R1 R0 K1 + 0x58080002, // 0003 LDCONST R2 K2 + 0x600C000C, // 0004 GETGBL R3 G12 + 0x5C100200, // 0005 MOVE R4 R1 + 0x7C0C0200, // 0006 CALL R3 1 + 0x140C0403, // 0007 LT R3 R2 R3 + 0x780E0004, // 0008 JMPF R3 #000E + 0x940C0202, // 0009 GETIDX R3 R1 R2 + 0x8C0C0703, // 000A GETMET R3 R3 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0x00080504, // 000C ADD R2 R2 K4 + 0x7001FFF5, // 000D JMP #0004 + 0xB80E0A00, // 000E GETNGBL R3 K5 + 0x8C0C0706, // 000F GETMET R3 R3 K6 + 0x88140107, // 0010 GETMBR R5 R0 K7 + 0x7C0C0400, // 0011 CALL R3 2 + 0x80000000, // 0012 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_painter +********************************************************************/ +be_local_closure(Animate_core_add_painter, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(painters), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(push), + }), + be_str_weak(add_painter), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x4C0C0000, // 0004 LDNIL R3 + 0x1C080403, // 0005 EQ R2 R2 R3 + 0x780A0003, // 0006 JMPF R2 #000B + 0x88080100, // 0007 GETMBR R2 R0 K0 + 0x8C080502, // 0008 GETMET R2 R2 K2 + 0x5C100200, // 0009 MOVE R4 R1 + 0x7C080400, // 000A CALL R2 2 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_bri +********************************************************************/ +be_local_closure(Animate_core_set_bri, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(bri), + }), + be_str_weak(set_bri), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_current +********************************************************************/ +be_local_closure(Animate_core_set_current, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(global), + /* K1 */ be_nested_str_weak(_cur_anim), + }), + be_str_weak(set_current), + &be_const_str_solidified, + ( &(const binstruction[ 3]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x90060200, // 0001 SETMBR R1 K1 R0 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: remove_animator +********************************************************************/ +be_local_closure(Animate_core_remove_animator, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(animators), + /* K1 */ be_nested_str_weak(remove), + /* K2 */ be_nested_str_weak(find), + /* K3 */ be_nested_str_weak(clear), + }), + be_str_weak(remove_animator), + &be_const_str_solidified, + ( &(const binstruction[13]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x200C0203, // 0002 NE R3 R1 R3 + 0x780E0005, // 0003 JMPF R3 #000A + 0x8C0C0501, // 0004 GETMET R3 R2 K1 + 0x8C140502, // 0005 GETMET R5 R2 K2 + 0x5C1C0200, // 0006 MOVE R7 R1 + 0x7C140400, // 0007 CALL R5 2 + 0x7C0C0400, // 0008 CALL R3 2 + 0x70020001, // 0009 JMP #000C + 0x8C0C0503, // 000A GETMET R3 R2 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_cb +********************************************************************/ +be_local_closure(Animate_core_set_cb, /* name */ + be_nested_proto( + 3, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(obj), + /* K1 */ be_nested_str_weak(mth), + }), + be_str_weak(set_cb), + &be_const_str_solidified, + ( &(const binstruction[ 3]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: fast_loop ********************************************************************/ @@ -140,11 +616,11 @@ be_local_closure(Animate_core_fast_loop, /* name */ /******************************************************************** -** Solidified function: add_animator +** Solidified function: set_back_color ********************************************************************/ -be_local_closure(Animate_core_add_animator, /* name */ +be_local_closure(Animate_core_set_back_color, /* name */ be_nested_proto( - 5, /* nstack */ + 2, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -152,256 +628,14 @@ be_local_closure(Animate_core_add_animator, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(animators), - /* K1 */ be_nested_str_weak(push), + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(back_color), }), - be_str_weak(add_animator), + be_str_weak(set_back_color), &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x80000000, // 0004 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: remove_painter -********************************************************************/ -be_local_closure(Animate_core_remove_painter, /* name */ - be_nested_proto( - 8, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(painters), - /* K1 */ be_nested_str_weak(remove), - /* K2 */ be_nested_str_weak(find), - /* K3 */ be_nested_str_weak(clear), - }), - be_str_weak(remove_painter), - &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x200C0203, // 0002 NE R3 R1 R3 - 0x780E0005, // 0003 JMPF R3 #000A - 0x8C0C0501, // 0004 GETMET R3 R2 K1 - 0x8C140502, // 0005 GETMET R5 R2 K2 - 0x5C1C0200, // 0006 MOVE R7 R1 - 0x7C140400, // 0007 CALL R5 2 - 0x7C0C0400, // 0008 CALL R3 2 - 0x70020001, // 0009 JMP #000C - 0x8C0C0503, // 000A GETMET R3 R2 K3 - 0x7C0C0200, // 000B CALL R3 1 - 0x80000000, // 000C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: remove_animator -********************************************************************/ -be_local_closure(Animate_core_remove_animator, /* name */ - be_nested_proto( - 8, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(animators), - /* K1 */ be_nested_str_weak(remove), - /* K2 */ be_nested_str_weak(find), - /* K3 */ be_nested_str_weak(clear), - }), - be_str_weak(remove_animator), - &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x200C0203, // 0002 NE R3 R1 R3 - 0x780E0005, // 0003 JMPF R3 #000A - 0x8C0C0501, // 0004 GETMET R3 R2 K1 - 0x8C140502, // 0005 GETMET R5 R2 K2 - 0x5C1C0200, // 0006 MOVE R7 R1 - 0x7C140400, // 0007 CALL R5 2 - 0x7C0C0400, // 0008 CALL R3 2 - 0x70020001, // 0009 JMP #000C - 0x8C0C0503, // 000A GETMET R3 R2 K3 - 0x7C0C0200, // 000B CALL R3 1 - 0x80000000, // 000C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: remove -********************************************************************/ -be_local_closure(Animate_core_remove, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(clear), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(remove_fast_loop), - /* K3 */ be_nested_str_weak(fast_loop_cb), - }), - be_str_weak(remove), - &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0xB8060200, // 0002 GETNGBL R1 K1 - 0x8C040302, // 0003 GETMET R1 R1 K2 - 0x880C0103, // 0004 GETMBR R3 R0 K3 - 0x7C040400, // 0005 CALL R1 2 - 0x80000000, // 0006 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: add_background_animator -********************************************************************/ -be_local_closure(Animate_core_add_background_animator, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(set_cb), - /* K1 */ be_nested_str_weak(set_back_color), - /* K2 */ be_nested_str_weak(add_animator), - }), - be_str_weak(add_background_animator), - &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x8C080300, // 0000 GETMET R2 R1 K0 - 0x5C100000, // 0001 MOVE R4 R0 - 0x88140101, // 0002 GETMBR R5 R0 K1 - 0x7C080600, // 0003 CALL R2 3 - 0x8C080102, // 0004 GETMET R2 R0 K2 - 0x5C100200, // 0005 MOVE R4 R1 - 0x7C080400, // 0006 CALL R2 2 - 0x80000000, // 0007 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: start -********************************************************************/ -be_local_closure(Animate_core_start, /* name */ - be_nested_proto( - 6, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(running), - /* K1 */ be_nested_str_weak(animators), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(start), - /* K4 */ be_const_int(1), - /* K5 */ be_nested_str_weak(fast_loop_next), - /* K6 */ be_nested_str_weak(tasmota), - /* K7 */ be_nested_str_weak(add_fast_loop), - /* K8 */ be_nested_str_weak(fast_loop_cb), - }), - be_str_weak(start), - &be_const_str_solidified, - ( &(const binstruction[20]) { /* code */ - 0x50040200, // 0000 LDBOOL R1 1 0 - 0x90020001, // 0001 SETMBR R0 K0 R1 - 0x88040101, // 0002 GETMBR R1 R0 K1 - 0x58080002, // 0003 LDCONST R2 K2 - 0x600C000C, // 0004 GETGBL R3 G12 - 0x5C100200, // 0005 MOVE R4 R1 - 0x7C0C0200, // 0006 CALL R3 1 - 0x140C0403, // 0007 LT R3 R2 R3 - 0x780E0004, // 0008 JMPF R3 #000E - 0x940C0202, // 0009 GETIDX R3 R1 R2 - 0x8C0C0703, // 000A GETMET R3 R3 K3 - 0x7C0C0200, // 000B CALL R3 1 - 0x00080504, // 000C ADD R2 R2 K4 - 0x7001FFF5, // 000D JMP #0004 - 0x90020B02, // 000E SETMBR R0 K5 K2 - 0xB80E0C00, // 000F GETNGBL R3 K6 - 0x8C0C0707, // 0010 GETMET R3 R3 K7 - 0x88140108, // 0011 GETMBR R5 R0 K8 - 0x7C0C0400, // 0012 CALL R3 2 - 0x80000000, // 0013 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: clear -********************************************************************/ -be_local_closure(Animate_core_clear, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(stop), - /* K1 */ be_nested_str_weak(strip), - /* K2 */ be_nested_str_weak(clear), - }), - be_str_weak(clear), - &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0x88040101, // 0002 GETMBR R1 R0 K1 - 0x8C040302, // 0003 GETMET R1 R1 K2 - 0x7C040200, // 0004 CALL R1 1 - 0x80000000, // 0005 RET 0 + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 }) ) ); @@ -445,7 +679,7 @@ be_local_closure(Animate_core_init, /* name */ ), }), 1, /* has constants */ - ( &(const bvalue[13]) { /* constants */ + ( &(const bvalue[14]) { /* constants */ /* K0 */ be_nested_str_weak(animate), /* K1 */ be_nested_str_weak(strip), /* K2 */ be_nested_str_weak(bri), @@ -459,10 +693,11 @@ be_local_closure(Animate_core_init, /* name */ /* K10 */ be_nested_str_weak(fast_loop_cb), /* K11 */ be_nested_str_weak(back_color), /* K12 */ be_const_int(0), + /* K13 */ be_nested_str_weak(set_current), }), be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[33]) { /* code */ + ( &(const binstruction[35]) { /* code */ 0xA40E0000, // 0000 IMPORT R3 K0 0x90020201, // 0001 SETMBR R0 K1 R1 0x4C100000, // 0002 LDNIL R4 @@ -494,143 +729,10 @@ be_local_closure(Animate_core_init, /* name */ 0x84100000, // 001C CLOSURE R4 P0 0x90021404, // 001D SETMBR R0 K10 R4 0x9002170C, // 001E SETMBR R0 K11 K12 - 0xA0000000, // 001F CLOSE R0 - 0x80000000, // 0020 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: stop -********************************************************************/ -be_local_closure(Animate_core_stop, /* name */ - be_nested_proto( - 6, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str_weak(running), - /* K1 */ be_nested_str_weak(animators), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(stop), - /* K4 */ be_const_int(1), - /* K5 */ be_nested_str_weak(tasmota), - /* K6 */ be_nested_str_weak(remove_fast_loop), - /* K7 */ be_nested_str_weak(fast_loop_cb), - }), - be_str_weak(stop), - &be_const_str_solidified, - ( &(const binstruction[19]) { /* code */ - 0x50040000, // 0000 LDBOOL R1 0 0 - 0x90020001, // 0001 SETMBR R0 K0 R1 - 0x88040101, // 0002 GETMBR R1 R0 K1 - 0x58080002, // 0003 LDCONST R2 K2 - 0x600C000C, // 0004 GETGBL R3 G12 - 0x5C100200, // 0005 MOVE R4 R1 - 0x7C0C0200, // 0006 CALL R3 1 - 0x140C0403, // 0007 LT R3 R2 R3 - 0x780E0004, // 0008 JMPF R3 #000E - 0x940C0202, // 0009 GETIDX R3 R1 R2 - 0x8C0C0703, // 000A GETMET R3 R3 K3 - 0x7C0C0200, // 000B CALL R3 1 - 0x00080504, // 000C ADD R2 R2 K4 - 0x7001FFF5, // 000D JMP #0004 - 0xB80E0A00, // 000E GETNGBL R3 K5 - 0x8C0C0706, // 000F GETMET R3 R3 K6 - 0x88140107, // 0010 GETMBR R5 R0 K7 - 0x7C0C0400, // 0011 CALL R3 2 - 0x80000000, // 0012 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: animate -********************************************************************/ -be_local_closure(Animate_core_animate, /* name */ - be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(animate), - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_cb -********************************************************************/ -be_local_closure(Animate_core_set_cb, /* name */ - be_nested_proto( - 3, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(obj), - /* K1 */ be_nested_str_weak(mth), - }), - be_str_weak(set_cb), - &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x80000000, // 0002 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: add_painter -********************************************************************/ -be_local_closure(Animate_core_add_painter, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(painters), - /* K1 */ be_nested_str_weak(push), - }), - be_str_weak(add_painter), - &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x80000000, // 0004 RET 0 + 0x8C10010D, // 001F GETMET R4 R0 K13 + 0x7C100200, // 0020 CALL R4 1 + 0xA0000000, // 0021 CLOSE R0 + 0x80000000, // 0022 RET 0 }) ) ); @@ -664,98 +766,45 @@ be_local_closure(Animate_core_get_bri, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: set_back_color -********************************************************************/ -be_local_closure(Animate_core_set_back_color, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(back_color), - }), - be_str_weak(set_back_color), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_bri -********************************************************************/ -be_local_closure(Animate_core_set_bri, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(bri), - }), - be_str_weak(set_bri), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified class: Animate_core ********************************************************************/ be_local_class(Animate_core, 13, NULL, - be_nested_map(30, + be_nested_map(31, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(running, -1), be_const_var(3) }, - { be_const_key_weak(pixel_count, -1), be_const_var(1) }, - { be_const_key_weak(fast_loop, -1), be_const_closure(Animate_core_fast_loop_closure) }, - { be_const_key_weak(animators, 8), be_const_var(4) }, - { be_const_key_weak(fast_loop_cb, 7), be_const_var(6) }, - { be_const_key_weak(set_back_color, 26), be_const_closure(Animate_core_set_back_color_closure) }, - { be_const_key_weak(add_animator, -1), be_const_closure(Animate_core_add_animator_closure) }, - { be_const_key_weak(frame, -1), be_const_var(10) }, - { be_const_key_weak(strip, 27), be_const_var(0) }, - { be_const_key_weak(remove_animator, 5), be_const_closure(Animate_core_remove_animator_closure) }, - { be_const_key_weak(init, -1), be_const_closure(Animate_core_init_closure) }, - { be_const_key_weak(start, -1), be_const_closure(Animate_core_start_closure) }, - { be_const_key_weak(mth, -1), be_const_var(9) }, - { be_const_key_weak(add_painter, -1), be_const_closure(Animate_core_add_painter_closure) }, - { be_const_key_weak(clear, -1), be_const_closure(Animate_core_clear_closure) }, - { be_const_key_weak(remove_painter, 23), be_const_closure(Animate_core_remove_painter_closure) }, - { be_const_key_weak(layer, -1), be_const_var(11) }, - { be_const_key_weak(stop, -1), be_const_closure(Animate_core_stop_closure) }, - { be_const_key_weak(fast_loop_next, 16), be_const_var(7) }, - { be_const_key_weak(FAST_LOOP_MIN, -1), be_const_int(20) }, - { be_const_key_weak(animate, -1), be_const_closure(Animate_core_animate_closure) }, - { be_const_key_weak(back_color, -1), be_const_var(12) }, - { be_const_key_weak(obj, 21), be_const_var(8) }, - { be_const_key_weak(set_cb, 10), be_const_closure(Animate_core_set_cb_closure) }, - { be_const_key_weak(bri, 13), be_const_var(2) }, { be_const_key_weak(get_bri, -1), be_const_closure(Animate_core_get_bri_closure) }, - { be_const_key_weak(painters, 28), be_const_var(5) }, - { be_const_key_weak(add_background_animator, 1), be_const_closure(Animate_core_add_background_animator_closure) }, { be_const_key_weak(remove, -1), be_const_closure(Animate_core_remove_closure) }, + { be_const_key_weak(painters, -1), be_const_var(5) }, + { be_const_key_weak(fast_loop_cb, -1), be_const_var(6) }, + { be_const_key_weak(start, 6), be_const_closure(Animate_core_start_closure) }, + { be_const_key_weak(add_background_animator, -1), be_const_closure(Animate_core_add_background_animator_closure) }, + { be_const_key_weak(set_back_color, 30), be_const_closure(Animate_core_set_back_color_closure) }, + { be_const_key_weak(add_animator, -1), be_const_closure(Animate_core_add_animator_closure) }, + { be_const_key_weak(strip, 3), be_const_var(0) }, + { be_const_key_weak(animate, 14), be_const_closure(Animate_core_animate_closure) }, + { be_const_key_weak(clear, 0), be_const_closure(Animate_core_clear_closure) }, + { be_const_key_weak(stop, -1), be_const_closure(Animate_core_stop_closure) }, + { be_const_key_weak(remove_painter, 28), be_const_closure(Animate_core_remove_painter_closure) }, + { be_const_key_weak(fast_loop_next, 21), be_const_var(7) }, + { be_const_key_weak(animators, -1), be_const_var(4) }, + { be_const_key_weak(add_painter, -1), be_const_closure(Animate_core_add_painter_closure) }, { be_const_key_weak(set_bri, -1), be_const_closure(Animate_core_set_bri_closure) }, + { be_const_key_weak(frame, -1), be_const_var(10) }, + { be_const_key_weak(mth, 26), be_const_var(9) }, + { be_const_key_weak(back_color, -1), be_const_var(12) }, + { be_const_key_weak(set_current, -1), be_const_closure(Animate_core_set_current_closure) }, + { be_const_key_weak(bri, -1), be_const_var(2) }, + { be_const_key_weak(fast_loop, -1), be_const_closure(Animate_core_fast_loop_closure) }, + { be_const_key_weak(layer, -1), be_const_var(11) }, + { be_const_key_weak(set_cb, 23), be_const_closure(Animate_core_set_cb_closure) }, + { be_const_key_weak(remove_animator, 22), be_const_closure(Animate_core_remove_animator_closure) }, + { be_const_key_weak(FAST_LOOP_MIN, -1), be_const_int(20) }, + { be_const_key_weak(pixel_count, -1), be_const_var(1) }, + { be_const_key_weak(obj, -1), be_const_var(8) }, + { be_const_key_weak(init, -1), be_const_closure(Animate_core_init_closure) }, + { be_const_key_weak(running, -1), be_const_var(3) }, })), be_str_weak(Animate_core) ); diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_animate_effects.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_animate_effects.h index 9831e5a6e..21bcdeb19 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_animate_effects.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_animate_effects.h @@ -4,6 +4,89 @@ \********************************************************************/ #include "be_constobj.h" +extern const bclass be_class_Animate_painter; + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_painter_init, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(global), + /* K1 */ be_nested_str_weak(_cur_anim), + /* K2 */ be_nested_str_weak(add_painter), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x88040301, // 0001 GETMBR R1 R1 K1 + 0x4C080000, // 0002 LDNIL R2 + 0x20080202, // 0003 NE R2 R1 R2 + 0x780A0002, // 0004 JMPF R2 #0008 + 0x8C080302, // 0005 GETMET R2 R1 K2 + 0x5C100000, // 0006 MOVE R4 R0 + 0x7C080400, // 0007 CALL R2 2 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: paint +********************************************************************/ +be_local_closure(Animate_painter_paint, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(paint), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Animate_painter +********************************************************************/ +be_local_class(Animate_painter, + 0, + NULL, + be_nested_map(2, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(paint, -1), be_const_closure(Animate_painter_paint_closure) }, + { be_const_key_weak(init, 0), be_const_closure(Animate_painter_init_closure) }, + })), + be_str_weak(Animate_painter) +); +/*******************************************************************/ + +void be_load_Animate_painter_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Animate_painter); + be_setglobal(vm, "Animate_painter"); + be_pop(vm, 1); +} + extern const bclass be_class_Animate_pulse; /******************************************************************** @@ -146,7 +229,7 @@ be_local_closure(Animate_pulse_set_color, /* name */ ********************************************************************/ be_local_closure(Animate_pulse_init, /* name */ be_nested_proto( - 5, /* nstack */ + 6, /* nstack */ 4, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -154,44 +237,50 @@ be_local_closure(Animate_pulse_init, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_const_int(16777215), - /* K1 */ be_const_int(1), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(color), - /* K4 */ be_nested_str_weak(back_color), - /* K5 */ be_const_int(-16777216), - /* K6 */ be_nested_str_weak(pulse_size), - /* K7 */ be_nested_str_weak(slew_size), - /* K8 */ be_nested_str_weak(pos), + ( &(const bvalue[10]) { /* constants */ + /* K0 */ be_nested_str_weak(init), + /* K1 */ be_const_int(16777215), + /* K2 */ be_const_int(1), + /* K3 */ be_const_int(0), + /* K4 */ be_nested_str_weak(color), + /* K5 */ be_nested_str_weak(back_color), + /* K6 */ be_const_int(-16777216), + /* K7 */ be_nested_str_weak(pulse_size), + /* K8 */ be_nested_str_weak(slew_size), + /* K9 */ be_nested_str_weak(pos), }), be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[24]) { /* code */ - 0x4C100000, // 0000 LDNIL R4 - 0x1C100204, // 0001 EQ R4 R1 R4 - 0x78120000, // 0002 JMPF R4 #0004 - 0x58040000, // 0003 LDCONST R1 K0 - 0x4C100000, // 0004 LDNIL R4 - 0x1C100404, // 0005 EQ R4 R2 R4 - 0x78120000, // 0006 JMPF R4 #0008 - 0x58080001, // 0007 LDCONST R2 K1 - 0x4C100000, // 0008 LDNIL R4 - 0x1C100604, // 0009 EQ R4 R3 R4 - 0x78120000, // 000A JMPF R4 #000C - 0x580C0002, // 000B LDCONST R3 K2 - 0x90020601, // 000C SETMBR R0 K3 R1 - 0x90020905, // 000D SETMBR R0 K4 K5 - 0x14100502, // 000E LT R4 R2 K2 + ( &(const binstruction[29]) { /* code */ + 0x60100003, // 0000 GETGBL R4 G3 + 0x5C140000, // 0001 MOVE R5 R0 + 0x7C100200, // 0002 CALL R4 1 + 0x8C100900, // 0003 GETMET R4 R4 K0 + 0x7C100200, // 0004 CALL R4 1 + 0x4C100000, // 0005 LDNIL R4 + 0x1C100204, // 0006 EQ R4 R1 R4 + 0x78120000, // 0007 JMPF R4 #0009 + 0x58040001, // 0008 LDCONST R1 K1 + 0x4C100000, // 0009 LDNIL R4 + 0x1C100404, // 000A EQ R4 R2 R4 + 0x78120000, // 000B JMPF R4 #000D + 0x58080002, // 000C LDCONST R2 K2 + 0x4C100000, // 000D LDNIL R4 + 0x1C100604, // 000E EQ R4 R3 R4 0x78120000, // 000F JMPF R4 #0011 - 0x58080002, // 0010 LDCONST R2 K2 - 0x90020C02, // 0011 SETMBR R0 K6 R2 - 0x14100702, // 0012 LT R4 R3 K2 - 0x78120000, // 0013 JMPF R4 #0015 - 0x580C0002, // 0014 LDCONST R3 K2 - 0x90020E03, // 0015 SETMBR R0 K7 R3 - 0x90021102, // 0016 SETMBR R0 K8 K2 - 0x80000000, // 0017 RET 0 + 0x580C0003, // 0010 LDCONST R3 K3 + 0x90020801, // 0011 SETMBR R0 K4 R1 + 0x90020B06, // 0012 SETMBR R0 K5 K6 + 0x14100503, // 0013 LT R4 R2 K3 + 0x78120000, // 0014 JMPF R4 #0016 + 0x58080003, // 0015 LDCONST R2 K3 + 0x90020E02, // 0016 SETMBR R0 K7 R2 + 0x14100703, // 0017 LT R4 R3 K3 + 0x78120000, // 0018 JMPF R4 #001A + 0x580C0003, // 0019 LDCONST R3 K3 + 0x90021003, // 001A SETMBR R0 K8 R3 + 0x90021303, // 001B SETMBR R0 K9 K3 + 0x80000000, // 001C RET 0 }) ) ); @@ -329,9 +418,10 @@ be_local_closure(Animate_pulse_paint, /* name */ /******************************************************************** ** Solidified class: Animate_pulse ********************************************************************/ +extern const bclass be_class_Animate_painter; be_local_class(Animate_pulse, 5, - NULL, + &be_class_Animate_painter, be_nested_map(12, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_weak(paint, -1), be_const_closure(Animate_pulse_paint_closure) }, diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h index a1def1f3d..7f12ffcca 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h @@ -64,22 +64,31 @@ be_local_closure(Animate_animator_beat, /* name */ ********************************************************************/ be_local_closure(Animate_animator_init, /* name */ be_nested_proto( - 2, /* nstack */ - 2, /* argc */ + 5, /* nstack */ + 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(duration_ms), + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(global), + /* K1 */ be_nested_str_weak(_cur_anim), + /* K2 */ be_nested_str_weak(add_animator), }), be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 + ( &(const binstruction[ 9]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x88040301, // 0001 GETMBR R1 R1 K1 + 0x4C080000, // 0002 LDNIL R2 + 0x20080202, // 0003 NE R2 R1 R2 + 0x780A0002, // 0004 JMPF R2 #0008 + 0x8C080302, // 0005 GETMET R2 R1 K2 + 0x5C100000, // 0006 MOVE R4 R0 + 0x7C080400, // 0007 CALL R2 2 + 0x80000000, // 0008 RET 0 }) ) ); @@ -252,72 +261,72 @@ void be_load_Animate_animator_class(bvm *vm) { extern const bclass be_class_Animate_palette; /******************************************************************** -** Solidified function: init +** Solidified function: ptr_to_palette ********************************************************************/ -be_local_closure(Animate_palette_init, /* name */ +be_local_closure(Animate_palette_ptr_to_palette, /* name */ be_nested_proto( - 6, /* nstack */ - 3, /* argc */ - 2, /* varg */ + 8, /* nstack */ + 1, /* argc */ + 4, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ - /* K0 */ be_nested_str_weak(init), - /* K1 */ be_nested_str_weak(running), - /* K2 */ be_nested_str_weak(ptr), - /* K3 */ be_nested_str_weak(ptr_to_palette), - /* K4 */ be_nested_str_weak(palette), - /* K5 */ be_nested_str_weak(bri), - /* K6 */ be_nested_str_weak(slots), - /* K7 */ be_nested_str_weak(set_duration), - /* K8 */ be_nested_str_weak(color), - /* K9 */ be_nested_str_weak(light_state), - /* K10 */ be_nested_str_weak(RGB), + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_const_class(be_class_Animate_palette), + /* K1 */ be_nested_str_weak(ptr), + /* K2 */ be_const_int(1), + /* K3 */ be_const_int(0), }), - be_str_weak(init), + be_str_weak(ptr_to_palette), &be_const_str_solidified, - ( &(const binstruction[38]) { /* code */ - 0x600C0003, // 0000 GETGBL R3 G3 - 0x5C100000, // 0001 MOVE R4 R0 - 0x7C0C0200, // 0002 CALL R3 1 - 0x8C0C0700, // 0003 GETMET R3 R3 K0 - 0x5C140400, // 0004 MOVE R5 R2 - 0x7C0C0400, // 0005 CALL R3 2 - 0x500C0000, // 0006 LDBOOL R3 0 0 - 0x90020203, // 0007 SETMBR R0 K1 R3 - 0x600C0004, // 0008 GETGBL R3 G4 - 0x5C100200, // 0009 MOVE R4 R1 - 0x7C0C0200, // 000A CALL R3 1 - 0x1C0C0702, // 000B EQ R3 R3 K2 - 0x780E0003, // 000C JMPF R3 #0011 - 0x8C0C0103, // 000D GETMET R3 R0 K3 - 0x5C140200, // 000E MOVE R5 R1 - 0x7C0C0400, // 000F CALL R3 2 - 0x5C040600, // 0010 MOVE R1 R3 - 0x90020801, // 0011 SETMBR R0 K4 R1 - 0x540E0063, // 0012 LDINT R3 100 - 0x90020A03, // 0013 SETMBR R0 K5 R3 - 0x600C000C, // 0014 GETGBL R3 G12 - 0x5C100200, // 0015 MOVE R4 R1 - 0x7C0C0200, // 0016 CALL R3 1 - 0x54120003, // 0017 LDINT R4 4 - 0x0C0C0604, // 0018 DIV R3 R3 R4 - 0x90020C03, // 0019 SETMBR R0 K6 R3 - 0x4C0C0000, // 001A LDNIL R3 - 0x200C0403, // 001B NE R3 R2 R3 - 0x780E0002, // 001C JMPF R3 #0020 - 0x8C0C0107, // 001D GETMET R3 R0 K7 - 0x5C140400, // 001E MOVE R5 R2 - 0x7C0C0400, // 001F CALL R3 2 - 0xB80E1200, // 0020 GETNGBL R3 K9 - 0xB8121200, // 0021 GETNGBL R4 K9 - 0x8810090A, // 0022 GETMBR R4 R4 K10 - 0x7C0C0200, // 0023 CALL R3 1 - 0x90021003, // 0024 SETMBR R0 K8 R3 - 0x80000000, // 0025 RET 0 + ( &(const binstruction[45]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x60080004, // 0001 GETGBL R2 G4 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C080200, // 0003 CALL R2 1 + 0x1C080501, // 0004 EQ R2 R2 K1 + 0x780A0025, // 0005 JMPF R2 #002C + 0x60080015, // 0006 GETGBL R2 G21 + 0x5C0C0000, // 0007 MOVE R3 R0 + 0x541207CF, // 0008 LDINT R4 2000 + 0x7C080400, // 0009 CALL R2 2 + 0x580C0002, // 000A LDCONST R3 K2 + 0x94100503, // 000B GETIDX R4 R2 K3 + 0x20100903, // 000C NE R4 R4 K3 + 0x7812000A, // 000D JMPF R4 #0019 + 0x50100200, // 000E LDBOOL R4 1 0 + 0x78120007, // 000F JMPF R4 #0018 + 0x54120003, // 0010 LDINT R4 4 + 0x08100604, // 0011 MUL R4 R3 R4 + 0x94100404, // 0012 GETIDX R4 R2 R4 + 0x1C100903, // 0013 EQ R4 R4 K3 + 0x78120000, // 0014 JMPF R4 #0016 + 0x70020001, // 0015 JMP #0018 + 0x000C0702, // 0016 ADD R3 R3 K2 + 0x7001FFF5, // 0017 JMP #000E + 0x7002000A, // 0018 JMP #0024 + 0x50100200, // 0019 LDBOOL R4 1 0 + 0x78120008, // 001A JMPF R4 #0024 + 0x54120003, // 001B LDINT R4 4 + 0x08100604, // 001C MUL R4 R3 R4 + 0x94100404, // 001D GETIDX R4 R2 R4 + 0x541600FE, // 001E LDINT R5 255 + 0x1C100805, // 001F EQ R4 R4 R5 + 0x78120000, // 0020 JMPF R4 #0022 + 0x70020001, // 0021 JMP #0024 + 0x000C0702, // 0022 ADD R3 R3 K2 + 0x7001FFF4, // 0023 JMP #0019 + 0x00100702, // 0024 ADD R4 R3 K2 + 0x54160003, // 0025 LDINT R5 4 + 0x08100805, // 0026 MUL R4 R4 R5 + 0x60140015, // 0027 GETGBL R5 G21 + 0x5C180000, // 0028 MOVE R6 R0 + 0x5C1C0800, // 0029 MOVE R7 R4 + 0x7C140400, // 002A CALL R5 2 + 0x80040A00, // 002B RET 1 R5 + 0x80000000, // 002C RET 0 }) ) ); @@ -563,72 +572,69 @@ be_local_closure(Animate_palette_animate, /* name */ /******************************************************************** -** Solidified function: ptr_to_palette +** Solidified function: set_palette ********************************************************************/ -be_local_closure(Animate_palette_ptr_to_palette, /* name */ +be_local_closure(Animate_palette_set_palette, /* name */ be_nested_proto( - 8, /* nstack */ - 1, /* argc */ - 4, /* varg */ + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_const_class(be_class_Animate_palette), - /* K1 */ be_nested_str_weak(ptr), - /* K2 */ be_const_int(1), - /* K3 */ be_const_int(0), + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(ptr), + /* K1 */ be_nested_str_weak(ptr_to_palette), + /* K2 */ be_nested_str_weak(palette), + /* K3 */ be_nested_str_weak(slots), + /* K4 */ be_nested_str_weak(duration_ms), + /* K5 */ be_nested_str_weak(set_duration), + /* K6 */ be_nested_str_weak(range_min), + /* K7 */ be_nested_str_weak(range_max), + /* K8 */ be_nested_str_weak(set_range), }), - be_str_weak(ptr_to_palette), + be_str_weak(set_palette), &be_const_str_solidified, - ( &(const binstruction[45]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x60080004, // 0001 GETGBL R2 G4 - 0x5C0C0000, // 0002 MOVE R3 R0 - 0x7C080200, // 0003 CALL R2 1 - 0x1C080501, // 0004 EQ R2 R2 K1 - 0x780A0025, // 0005 JMPF R2 #002C - 0x60080015, // 0006 GETGBL R2 G21 - 0x5C0C0000, // 0007 MOVE R3 R0 - 0x541207CF, // 0008 LDINT R4 2000 - 0x7C080400, // 0009 CALL R2 2 - 0x580C0002, // 000A LDCONST R3 K2 - 0x94100503, // 000B GETIDX R4 R2 K3 - 0x20100903, // 000C NE R4 R4 K3 - 0x7812000A, // 000D JMPF R4 #0019 - 0x50100200, // 000E LDBOOL R4 1 0 - 0x78120007, // 000F JMPF R4 #0018 - 0x54120003, // 0010 LDINT R4 4 - 0x08100604, // 0011 MUL R4 R3 R4 - 0x94100404, // 0012 GETIDX R4 R2 R4 - 0x1C100903, // 0013 EQ R4 R4 K3 - 0x78120000, // 0014 JMPF R4 #0016 - 0x70020001, // 0015 JMP #0018 - 0x000C0702, // 0016 ADD R3 R3 K2 - 0x7001FFF5, // 0017 JMP #000E - 0x7002000A, // 0018 JMP #0024 - 0x50100200, // 0019 LDBOOL R4 1 0 - 0x78120008, // 001A JMPF R4 #0024 - 0x54120003, // 001B LDINT R4 4 - 0x08100604, // 001C MUL R4 R3 R4 - 0x94100404, // 001D GETIDX R4 R2 R4 - 0x541600FE, // 001E LDINT R5 255 - 0x1C100805, // 001F EQ R4 R4 R5 - 0x78120000, // 0020 JMPF R4 #0022 - 0x70020001, // 0021 JMP #0024 - 0x000C0702, // 0022 ADD R3 R3 K2 - 0x7001FFF4, // 0023 JMP #0019 - 0x00100702, // 0024 ADD R4 R3 K2 - 0x54160003, // 0025 LDINT R5 4 - 0x08100805, // 0026 MUL R4 R4 R5 - 0x60140015, // 0027 GETGBL R5 G21 - 0x5C180000, // 0028 MOVE R6 R0 - 0x5C1C0800, // 0029 MOVE R7 R4 - 0x7C140400, // 002A CALL R5 2 - 0x80040A00, // 002B RET 1 R5 - 0x80000000, // 002C RET 0 + ( &(const binstruction[37]) { /* code */ + 0x60080004, // 0000 GETGBL R2 G4 + 0x5C0C0200, // 0001 MOVE R3 R1 + 0x7C080200, // 0002 CALL R2 1 + 0x1C080500, // 0003 EQ R2 R2 K0 + 0x780A0003, // 0004 JMPF R2 #0009 + 0x8C080101, // 0005 GETMET R2 R0 K1 + 0x5C100200, // 0006 MOVE R4 R1 + 0x7C080400, // 0007 CALL R2 2 + 0x5C040400, // 0008 MOVE R1 R2 + 0x90020401, // 0009 SETMBR R0 K2 R1 + 0x6008000C, // 000A GETGBL R2 G12 + 0x5C0C0200, // 000B MOVE R3 R1 + 0x7C080200, // 000C CALL R2 1 + 0x540E0003, // 000D LDINT R3 4 + 0x0C080403, // 000E DIV R2 R2 R3 + 0x90020602, // 000F SETMBR R0 K3 R2 + 0x88080104, // 0010 GETMBR R2 R0 K4 + 0x4C0C0000, // 0011 LDNIL R3 + 0x20080403, // 0012 NE R2 R2 R3 + 0x780A0003, // 0013 JMPF R2 #0018 + 0x8C080105, // 0014 GETMET R2 R0 K5 + 0x88100104, // 0015 GETMBR R4 R0 K4 + 0x7C080400, // 0016 CALL R2 2 + 0x7002000B, // 0017 JMP #0024 + 0x88080106, // 0018 GETMBR R2 R0 K6 + 0x4C0C0000, // 0019 LDNIL R3 + 0x20080403, // 001A NE R2 R2 R3 + 0x780A0007, // 001B JMPF R2 #0024 + 0x88080107, // 001C GETMBR R2 R0 K7 + 0x4C0C0000, // 001D LDNIL R3 + 0x20080403, // 001E NE R2 R2 R3 + 0x780A0003, // 001F JMPF R2 #0024 + 0x8C080108, // 0020 GETMET R2 R0 K8 + 0x88100106, // 0021 GETMBR R4 R0 K6 + 0x88140107, // 0022 GETMBR R5 R0 K7 + 0x7C080600, // 0023 CALL R2 3 + 0x80000000, // 0024 RET 0 }) ) ); @@ -636,40 +642,109 @@ be_local_closure(Animate_palette_ptr_to_palette, /* name */ /******************************************************************** -** Solidified function: set_range +** Solidified function: to_css_gradient ********************************************************************/ -be_local_closure(Animate_palette_set_range, /* name */ +be_local_closure(Animate_palette_to_css_gradient, /* name */ be_nested_proto( - 7, /* nstack */ - 3, /* argc */ + 17, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[10]) { /* constants */ + /* K0 */ be_const_class(be_class_Animate_palette), + /* K1 */ be_nested_str_weak(parse_palette), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(background_X3Alinear_X2Dgradient_X28to_X20right), + /* K4 */ be_nested_str_weak(palette), + /* K5 */ be_nested_str_weak(get), + /* K6 */ be_nested_str_weak(_X2C_X23_X2502X_X2502X_X2502X_X20_X25_X2E1f_X25_X25), + /* K7 */ be_const_real_hex(0x41200000), + /* K8 */ be_const_int(1), + /* K9 */ be_nested_str_weak(_X29_X3B), + }), + be_str_weak(to_css_gradient), + &be_const_str_solidified, + ( &(const binstruction[46]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x5C080200, // 0001 MOVE R2 R1 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C080200, // 0003 CALL R2 1 + 0x8C0C0501, // 0004 GETMET R3 R2 K1 + 0x58140002, // 0005 LDCONST R5 K2 + 0x541A03E7, // 0006 LDINT R6 1000 + 0x7C0C0600, // 0007 CALL R3 3 + 0x58100003, // 0008 LDCONST R4 K3 + 0x58140002, // 0009 LDCONST R5 K2 + 0x6018000C, // 000A GETGBL R6 G12 + 0x5C1C0600, // 000B MOVE R7 R3 + 0x7C180200, // 000C CALL R6 1 + 0x14180A06, // 000D LT R6 R5 R6 + 0x781A001C, // 000E JMPF R6 #002C + 0x94180605, // 000F GETIDX R6 R3 R5 + 0x881C0504, // 0010 GETMBR R7 R2 K4 + 0x8C1C0F05, // 0011 GETMET R7 R7 K5 + 0x54260003, // 0012 LDINT R9 4 + 0x08240A09, // 0013 MUL R9 R5 R9 + 0x542A0003, // 0014 LDINT R10 4 + 0x7C1C0600, // 0015 CALL R7 3 + 0x54220007, // 0016 LDINT R8 8 + 0x3C200E08, // 0017 SHR R8 R7 R8 + 0x542600FE, // 0018 LDINT R9 255 + 0x2C201009, // 0019 AND R8 R8 R9 + 0x5426000F, // 001A LDINT R9 16 + 0x3C240E09, // 001B SHR R9 R7 R9 + 0x542A00FE, // 001C LDINT R10 255 + 0x2C24120A, // 001D AND R9 R9 R10 + 0x542A0017, // 001E LDINT R10 24 + 0x3C280E0A, // 001F SHR R10 R7 R10 + 0x542E00FE, // 0020 LDINT R11 255 + 0x2C28140B, // 0021 AND R10 R10 R11 + 0x602C0018, // 0022 GETGBL R11 G24 + 0x58300006, // 0023 LDCONST R12 K6 + 0x5C341000, // 0024 MOVE R13 R8 + 0x5C381200, // 0025 MOVE R14 R9 + 0x5C3C1400, // 0026 MOVE R15 R10 + 0x0C400D07, // 0027 DIV R16 R6 K7 + 0x7C2C0A00, // 0028 CALL R11 5 + 0x0010080B, // 0029 ADD R4 R4 R11 + 0x00140B08, // 002A ADD R5 R5 K8 + 0x7001FFDD, // 002B JMP #000A + 0x00100909, // 002C ADD R4 R4 K9 + 0x80040800, // 002D RET 1 R4 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_bri +********************************************************************/ +be_local_closure(Animate_palette_set_bri, /* name */ + be_nested_proto( + 4, /* nstack */ + 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(value_error), - /* K1 */ be_nested_str_weak(min_X20must_X20be_X20lower_X20than_X20mex), - /* K2 */ be_nested_str_weak(range_min), - /* K3 */ be_nested_str_weak(range_max), - /* K4 */ be_nested_str_weak(slots_arr), - /* K5 */ be_nested_str_weak(parse_palette), + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(bri), }), - be_str_weak(set_range), + be_str_weak(set_bri), &be_const_str_solidified, - ( &(const binstruction[11]) { /* code */ - 0x280C0202, // 0000 GE R3 R1 R2 - 0x780E0000, // 0001 JMPF R3 #0003 - 0xB0060101, // 0002 RAISE 1 K0 K1 - 0x90020401, // 0003 SETMBR R0 K2 R1 - 0x90020602, // 0004 SETMBR R0 K3 R2 - 0x8C0C0105, // 0005 GETMET R3 R0 K5 - 0x5C140200, // 0006 MOVE R5 R1 - 0x5C180400, // 0007 MOVE R6 R2 - 0x7C0C0600, // 0008 CALL R3 3 - 0x90020803, // 0009 SETMBR R0 K4 R3 - 0x80000000, // 000A RET 0 + ( &(const binstruction[ 5]) { /* code */ + 0x60080009, // 0000 GETGBL R2 G9 + 0x5C0C0200, // 0001 MOVE R3 R1 + 0x7C080200, // 0002 CALL R2 1 + 0x90020002, // 0003 SETMBR R0 K0 R2 + 0x80000000, // 0004 RET 0 }) ) ); @@ -780,74 +855,40 @@ be_local_closure(Animate_palette_parse_palette, /* name */ /******************************************************************** -** Solidified function: set_bri +** Solidified function: set_range ********************************************************************/ -be_local_closure(Animate_palette_set_bri, /* name */ +be_local_closure(Animate_palette_set_range, /* name */ be_nested_proto( - 4, /* nstack */ - 2, /* argc */ + 7, /* nstack */ + 3, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(bri), - }), - be_str_weak(set_bri), - &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x60080009, // 0000 GETGBL R2 G9 - 0x5C0C0200, // 0001 MOVE R3 R1 - 0x7C080200, // 0002 CALL R2 1 - 0x90020002, // 0003 SETMBR R0 K0 R2 - 0x80000000, // 0004 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_duration -********************************************************************/ -be_local_closure(Animate_palette_set_duration, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str_weak(value_error), - /* K2 */ be_nested_str_weak(duration_ms_X20must_X20be_X20positive), - /* K3 */ be_nested_str_weak(duration_ms), + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(value_error), + /* K1 */ be_nested_str_weak(min_X20must_X20be_X20lower_X20than_X20mex), + /* K2 */ be_nested_str_weak(range_min), + /* K3 */ be_nested_str_weak(range_max), /* K4 */ be_nested_str_weak(slots_arr), /* K5 */ be_nested_str_weak(parse_palette), - /* K6 */ be_const_int(1), }), - be_str_weak(set_duration), + be_str_weak(set_range), &be_const_str_solidified, - ( &(const binstruction[14]) { /* code */ - 0x4C080000, // 0000 LDNIL R2 - 0x1C080202, // 0001 EQ R2 R1 R2 - 0x780A0000, // 0002 JMPF R2 #0004 - 0x80000400, // 0003 RET 0 - 0x18080300, // 0004 LE R2 R1 K0 - 0x780A0000, // 0005 JMPF R2 #0007 - 0xB0060302, // 0006 RAISE 1 K1 K2 - 0x90020601, // 0007 SETMBR R0 K3 R1 - 0x8C080105, // 0008 GETMET R2 R0 K5 - 0x58100000, // 0009 LDCONST R4 K0 - 0x04140306, // 000A SUB R5 R1 K6 - 0x7C080600, // 000B CALL R2 3 - 0x90020802, // 000C SETMBR R0 K4 R2 - 0x80000000, // 000D RET 0 + ( &(const binstruction[11]) { /* code */ + 0x280C0202, // 0000 GE R3 R1 R2 + 0x780E0000, // 0001 JMPF R3 #0003 + 0xB0060101, // 0002 RAISE 1 K0 K1 + 0x90020401, // 0003 SETMBR R0 K2 R1 + 0x90020602, // 0004 SETMBR R0 K3 R2 + 0x8C0C0105, // 0005 GETMET R3 R0 K5 + 0x5C140200, // 0006 MOVE R5 R1 + 0x5C180400, // 0007 MOVE R6 R2 + 0x7C0C0600, // 0008 CALL R3 3 + 0x90020803, // 0009 SETMBR R0 K4 R3 + 0x80000000, // 000A RET 0 }) ) ); @@ -988,79 +1029,95 @@ be_local_closure(Animate_palette_set_value, /* name */ /******************************************************************** -** Solidified function: to_css_gradient +** Solidified function: set_duration ********************************************************************/ -be_local_closure(Animate_palette_to_css_gradient, /* name */ +be_local_closure(Animate_palette_set_duration, /* name */ be_nested_proto( - 17, /* nstack */ - 1, /* argc */ - 4, /* varg */ + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[10]) { /* constants */ - /* K0 */ be_const_class(be_class_Animate_palette), - /* K1 */ be_nested_str_weak(parse_palette), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(background_X3Alinear_X2Dgradient_X28to_X20right), - /* K4 */ be_nested_str_weak(palette), - /* K5 */ be_nested_str_weak(get), - /* K6 */ be_nested_str_weak(_X2C_X23_X2502X_X2502X_X2502X_X20_X25_X2E1f_X25_X25), - /* K7 */ be_const_real_hex(0x41200000), - /* K8 */ be_const_int(1), - /* K9 */ be_nested_str_weak(_X29_X3B), + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_weak(value_error), + /* K2 */ be_nested_str_weak(duration_ms_X20must_X20be_X20positive), + /* K3 */ be_nested_str_weak(duration_ms), + /* K4 */ be_nested_str_weak(slots_arr), + /* K5 */ be_nested_str_weak(parse_palette), + /* K6 */ be_const_int(1), }), - be_str_weak(to_css_gradient), + be_str_weak(set_duration), &be_const_str_solidified, - ( &(const binstruction[46]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x5C080200, // 0001 MOVE R2 R1 - 0x5C0C0000, // 0002 MOVE R3 R0 - 0x7C080200, // 0003 CALL R2 1 - 0x8C0C0501, // 0004 GETMET R3 R2 K1 - 0x58140002, // 0005 LDCONST R5 K2 - 0x541A03E7, // 0006 LDINT R6 1000 - 0x7C0C0600, // 0007 CALL R3 3 - 0x58100003, // 0008 LDCONST R4 K3 - 0x58140002, // 0009 LDCONST R5 K2 - 0x6018000C, // 000A GETGBL R6 G12 - 0x5C1C0600, // 000B MOVE R7 R3 - 0x7C180200, // 000C CALL R6 1 - 0x14180A06, // 000D LT R6 R5 R6 - 0x781A001C, // 000E JMPF R6 #002C - 0x94180605, // 000F GETIDX R6 R3 R5 - 0x881C0504, // 0010 GETMBR R7 R2 K4 - 0x8C1C0F05, // 0011 GETMET R7 R7 K5 - 0x54260003, // 0012 LDINT R9 4 - 0x08240A09, // 0013 MUL R9 R5 R9 - 0x542A0003, // 0014 LDINT R10 4 - 0x7C1C0600, // 0015 CALL R7 3 - 0x54220007, // 0016 LDINT R8 8 - 0x3C200E08, // 0017 SHR R8 R7 R8 - 0x542600FE, // 0018 LDINT R9 255 - 0x2C201009, // 0019 AND R8 R8 R9 - 0x5426000F, // 001A LDINT R9 16 - 0x3C240E09, // 001B SHR R9 R7 R9 - 0x542A00FE, // 001C LDINT R10 255 - 0x2C24120A, // 001D AND R9 R9 R10 - 0x542A0017, // 001E LDINT R10 24 - 0x3C280E0A, // 001F SHR R10 R7 R10 - 0x542E00FE, // 0020 LDINT R11 255 - 0x2C28140B, // 0021 AND R10 R10 R11 - 0x602C0018, // 0022 GETGBL R11 G24 - 0x58300006, // 0023 LDCONST R12 K6 - 0x5C341000, // 0024 MOVE R13 R8 - 0x5C381200, // 0025 MOVE R14 R9 - 0x5C3C1400, // 0026 MOVE R15 R10 - 0x0C400D07, // 0027 DIV R16 R6 K7 - 0x7C2C0A00, // 0028 CALL R11 5 - 0x0010080B, // 0029 ADD R4 R4 R11 - 0x00140B08, // 002A ADD R5 R5 K8 - 0x7001FFDD, // 002B JMP #000A - 0x00100909, // 002C ADD R4 R4 K9 - 0x80040800, // 002D RET 1 R4 + ( &(const binstruction[14]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x1C080202, // 0001 EQ R2 R1 R2 + 0x780A0000, // 0002 JMPF R2 #0004 + 0x80000400, // 0003 RET 0 + 0x18080300, // 0004 LE R2 R1 K0 + 0x780A0000, // 0005 JMPF R2 #0007 + 0xB0060302, // 0006 RAISE 1 K1 K2 + 0x90020601, // 0007 SETMBR R0 K3 R1 + 0x8C080105, // 0008 GETMET R2 R0 K5 + 0x58100000, // 0009 LDCONST R4 K0 + 0x04140306, // 000A SUB R5 R1 K6 + 0x7C080600, // 000B CALL R2 3 + 0x90020802, // 000C SETMBR R0 K4 R2 + 0x80000000, // 000D RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_palette_init, /* name */ + be_nested_proto( + 6, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_str_weak(init), + /* K1 */ be_nested_str_weak(duration_ms), + /* K2 */ be_nested_str_weak(running), + /* K3 */ be_nested_str_weak(bri), + /* K4 */ be_nested_str_weak(color), + /* K5 */ be_nested_str_weak(light_state), + /* K6 */ be_nested_str_weak(RGB), + /* K7 */ be_nested_str_weak(set_palette), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[19]) { /* code */ + 0x600C0003, // 0000 GETGBL R3 G3 + 0x5C100000, // 0001 MOVE R4 R0 + 0x7C0C0200, // 0002 CALL R3 1 + 0x8C0C0700, // 0003 GETMET R3 R3 K0 + 0x7C0C0200, // 0004 CALL R3 1 + 0x90020202, // 0005 SETMBR R0 K1 R2 + 0x500C0000, // 0006 LDBOOL R3 0 0 + 0x90020403, // 0007 SETMBR R0 K2 R3 + 0x540E0063, // 0008 LDINT R3 100 + 0x90020603, // 0009 SETMBR R0 K3 R3 + 0xB80E0A00, // 000A GETNGBL R3 K5 + 0xB8120A00, // 000B GETNGBL R4 K5 + 0x88100906, // 000C GETMBR R4 R4 K6 + 0x7C0C0200, // 000D CALL R3 1 + 0x90020803, // 000E SETMBR R0 K4 R3 + 0x8C0C0107, // 000F GETMET R3 R0 K7 + 0x5C140200, // 0010 MOVE R5 R1 + 0x7C0C0400, // 0011 CALL R3 2 + 0x80000000, // 0012 RET 0 }) ) ); @@ -1074,24 +1131,25 @@ extern const bclass be_class_Animate_animator; be_local_class(Animate_palette, 7, &be_class_Animate_animator, - be_nested_map(16, + be_nested_map(17, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(palette, 5), be_const_var(0) }, - { be_const_key_weak(range_min, -1), be_const_var(3) }, - { be_const_key_weak(slots_arr, -1), be_const_var(1) }, - { be_const_key_weak(init, -1), be_const_closure(Animate_palette_init_closure) }, - { be_const_key_weak(bri, 14), be_const_var(5) }, - { be_const_key_weak(animate, -1), be_const_closure(Animate_palette_animate_closure) }, + { be_const_key_weak(color, 13), be_const_var(6) }, { be_const_key_weak(slots, -1), be_const_var(2) }, - { be_const_key_weak(ptr_to_palette, -1), be_const_static_closure(Animate_palette_ptr_to_palette_closure) }, - { be_const_key_weak(color, -1), be_const_var(6) }, - { be_const_key_weak(set_range, 10), be_const_closure(Animate_palette_set_range_closure) }, - { be_const_key_weak(to_css_gradient, -1), be_const_static_closure(Animate_palette_to_css_gradient_closure) }, + { be_const_key_weak(animate, 11), be_const_closure(Animate_palette_animate_closure) }, + { be_const_key_weak(range_max, 10), be_const_var(4) }, + { be_const_key_weak(set_palette, -1), be_const_closure(Animate_palette_set_palette_closure) }, { be_const_key_weak(set_bri, -1), be_const_closure(Animate_palette_set_bri_closure) }, - { be_const_key_weak(set_duration, -1), be_const_closure(Animate_palette_set_duration_closure) }, + { be_const_key_weak(bri, -1), be_const_var(5) }, + { be_const_key_weak(to_css_gradient, 12), be_const_static_closure(Animate_palette_to_css_gradient_closure) }, + { be_const_key_weak(slots_arr, 1), be_const_var(1) }, + { be_const_key_weak(range_min, 5), be_const_var(3) }, { be_const_key_weak(set_value, -1), be_const_closure(Animate_palette_set_value_closure) }, + { be_const_key_weak(set_range, -1), be_const_closure(Animate_palette_set_range_closure) }, { be_const_key_weak(parse_palette, -1), be_const_closure(Animate_palette_parse_palette_closure) }, - { be_const_key_weak(range_max, -1), be_const_var(4) }, + { be_const_key_weak(palette, -1), be_const_var(0) }, + { be_const_key_weak(set_duration, -1), be_const_closure(Animate_palette_set_duration_closure) }, + { be_const_key_weak(init, -1), be_const_closure(Animate_palette_init_closure) }, + { be_const_key_weak(ptr_to_palette, 0), be_const_static_closure(Animate_palette_ptr_to_palette_closure) }, })), be_str_weak(Animate_palette) ); @@ -1266,7 +1324,7 @@ be_local_closure(Animate_oscillator_set_phase, /* name */ ********************************************************************/ be_local_closure(Animate_oscillator_init, /* name */ be_nested_proto( - 6, /* nstack */ + 7, /* nstack */ 5, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -1274,33 +1332,39 @@ be_local_closure(Animate_oscillator_init, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(phase), - /* K1 */ be_const_int(0), - /* K2 */ be_nested_str_weak(duty_cycle), - /* K3 */ be_nested_str_weak(a), - /* K4 */ be_nested_str_weak(b), - /* K5 */ be_nested_str_weak(duration_ms), - /* K6 */ be_nested_str_weak(value), - /* K7 */ be_const_int(1), - /* K8 */ be_nested_str_weak(form), + ( &(const bvalue[10]) { /* constants */ + /* K0 */ be_nested_str_weak(init), + /* K1 */ be_nested_str_weak(phase), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(duty_cycle), + /* K4 */ be_nested_str_weak(a), + /* K5 */ be_nested_str_weak(b), + /* K6 */ be_nested_str_weak(duration_ms), + /* K7 */ be_nested_str_weak(value), + /* K8 */ be_const_int(1), + /* K9 */ be_nested_str_weak(form), }), be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x90020101, // 0000 SETMBR R0 K0 K1 - 0x54160031, // 0001 LDINT R5 50 - 0x90020405, // 0002 SETMBR R0 K2 R5 - 0x90020601, // 0003 SETMBR R0 K3 R1 - 0x90020802, // 0004 SETMBR R0 K4 R2 - 0x90020A03, // 0005 SETMBR R0 K5 R3 - 0x90020C01, // 0006 SETMBR R0 K6 R1 - 0x4C140000, // 0007 LDNIL R5 - 0x1C140805, // 0008 EQ R5 R4 R5 - 0x78160000, // 0009 JMPF R5 #000B - 0x58100007, // 000A LDCONST R4 K7 - 0x90021004, // 000B SETMBR R0 K8 R4 - 0x80000000, // 000C RET 0 + ( &(const binstruction[18]) { /* code */ + 0x60140003, // 0000 GETGBL R5 G3 + 0x5C180000, // 0001 MOVE R6 R0 + 0x7C140200, // 0002 CALL R5 1 + 0x8C140B00, // 0003 GETMET R5 R5 K0 + 0x7C140200, // 0004 CALL R5 1 + 0x90020302, // 0005 SETMBR R0 K1 K2 + 0x54160031, // 0006 LDINT R5 50 + 0x90020605, // 0007 SETMBR R0 K3 R5 + 0x90020801, // 0008 SETMBR R0 K4 R1 + 0x90020A02, // 0009 SETMBR R0 K5 R2 + 0x90020C03, // 000A SETMBR R0 K6 R3 + 0x90020E01, // 000B SETMBR R0 K7 R1 + 0x4C140000, // 000C LDNIL R5 + 0x1C140805, // 000D EQ R5 R4 R5 + 0x78160000, // 000E JMPF R5 #0010 + 0x58100008, // 000F LDCONST R4 K8 + 0x90021204, // 0010 SETMBR R0 K9 R4 + 0x80000000, // 0011 RET 0 }) ) ); diff --git a/tasmota/berry/animate_demo/animate_demo_breathe.be b/tasmota/berry/animate_demo/animate_demo_breathe.be new file mode 100644 index 000000000..d9394adb4 --- /dev/null +++ b/tasmota/berry/animate_demo/animate_demo_breathe.be @@ -0,0 +1,28 @@ +# +# Example for M5Stack Led Matrix +# 5 x 5 WS2812 +# +import animate + +var PALETTE_BLACK_RED = bytes( + "00" "000000" # black + "88" "880000" # red + "FF" "FF5500" # orange + ) + + var duration = 3000 + var leds = 25 + + var strip = Leds(leds, gpio.pin(gpio.WS2812, 0)) + var anim = animate.core(strip, 100) + anim.set_back_color(0x000000) + + var pulse = animate.pulse(0xFF0000, leds, 0) + var palette = animate.palette(PALETTE_BLACK_RED) + palette.set_range(0, 255) + palette.set_cb(pulse, pulse.set_color) + + var osc1 = animate.oscillator(50, 255, duration, animate.COSINE) + osc1.set_cb(palette, palette.set_value) + + anim.start() diff --git a/tasmota/berry/animate_demo/animate_demo_pulse.be b/tasmota/berry/animate_demo/animate_demo_pulse.be index 09b075683..82c2d5ee3 100644 --- a/tasmota/berry/animate_demo/animate_demo_pulse.be +++ b/tasmota/berry/animate_demo/animate_demo_pulse.be @@ -12,12 +12,8 @@ var pulse = animate.pulse(0xFF4444, 2, 1) var osc1 = animate.oscillator(-3, 26, 5000, animate.COSINE) osc1.set_cb(pulse, pulse.set_pos) -anim.add_animator(osc1) -anim.add_painter(pulse) - # animate color of pulse var palette = animate.palette(animate.PALETTE_RAINBOW_WHITE, 30000) palette.set_cb(pulse, pulse.set_color) -anim.add_animator(palette) anim.start() From d3a30681b225b137420432b407c9101f2153d2c5 Mon Sep 17 00:00:00 2001 From: bovirus <1262554+bovirus@users.noreply.github.com> Date: Sun, 17 Dec 2023 21:13:07 +0100 Subject: [PATCH 014/303] Update Italian language (#20255) --- tasmota/language/it_IT.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index 1a412fcff..29a012781 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v9.4.0.1 - Last update 18.11.2023 + * Updated until v9.4.0.1 - Last update 17.12.2023 \*********************************************************************/ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -956,8 +956,8 @@ #define D_SENSOR_BIOPDU_PZEM0XX_TX "BioPDU PZEM0XX - TX" #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 - RX" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" -#define D_SENSOR_LOX_O2_RX "LoxO2 RX" -#define D_GPIO_MAGIC_SWITCH "MagicSwitch" +#define D_SENSOR_LOX_O2_RX "LoxO2 - RX" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" From 5fd8faa63370ae3e7bc8b6c82afc6823cd3ee82a Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 17 Dec 2023 21:23:43 +0100 Subject: [PATCH 015/303] Add animate palettes (#20256) --- .../berry_tasmota/src/be_animate_module.c | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/lib/libesp32/berry_tasmota/src/be_animate_module.c b/lib/libesp32/berry_tasmota/src/be_animate_module.c index 7d741e0a9..d638cbb79 100644 --- a/lib/libesp32/berry_tasmota/src/be_animate_module.c +++ b/lib/libesp32/berry_tasmota/src/be_animate_module.c @@ -70,6 +70,59 @@ static const uint8_t PALETTE_ib_jul01_gp[] = { 0xFF, 0xBB, 0x03, 0x0D, // rgb(187, 3, 13) 100.000% }; +// Gradient palette "ib44" +// http://soliton.vm.bytemark.co.uk/pub/cpt-city/ing/general/tn/ib44.png.index.html +static const uint8_t PALETTE_ib_44[] = { + 0, 214, 24, 16, + 64, 227, 115, 78, + 255, 239, 206, 140, +}; + +// Gradient palette "Fire-1" +// http://soliton.vm.bytemark.co.uk/pub/cpt-city/ds/icons/Fire-1.c3g +static const uint8_t PALETTE_Fire_1[] = { + 0, 255, 0, 0, + 128, 255, 128, 0, + 255, 255, 255, 0, +}; + +// Gradient palette "bhw1_sunconure" +// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_sunconure.png.index.html +static const uint8_t PALETTE_bhw1_sunconure[] = { + 0, 97, 240, 78, + 161, 246, 137, 30, + 255, 246, 45, 30, +}; + +// Gradient palette "bhw3_41" +// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw3/tn/bhw3_41.png.index.html +static const uint8_t PALETTE_bhw3_41[] = { + 0, 0, 0, 128, + 71, 64, 64, 255, + 75, 160, 160, 255, + 76, 255, 255, 255, + 178, 255, 255, 255, + 179, 255, 128, 128, + 196, 255, 0, 0, + 255, 128, 0, 0, +}; + +// Gradient palette "bhw4_089" +// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw4/tn/bhw4_089.png.index.html +static const uint8_t PALETTE_bhw4_089[] = { + 0, 174, 52, 28, + 28, 224, 154, 133, + 53, 235, 208, 206, + 79, 249, 208, 118, + 109, 228, 95, 50, + 132, 227, 165, 116, + 163, 226, 131, 67, + 184, 252, 213, 118, + 201, 252, 169, 125, + 224, 255, 194, 101, + 255, 215, 80, 35, +}; + static const uint8_t PALETTE_STANDARD_VAL[] = { 0x00, 0xFF, 0x00, 0x00, // red 0x2A, 0xFF, 0xA5, 0x00, // orange @@ -108,6 +161,11 @@ module animate (scope: global, strings: weak) { PALETTE_RAINBOW_WHITE, comptr(PALETTE_RAINBOW_WHITE) PALETTE_STANDARD_VAL, comptr(PALETTE_STANDARD_VAL) PALETTE_SATURATED_TAG, comptr(PALETTE_SATURATED_TAG) + PALETTE_ib_jul01_gp, comptr(PALETTE_ib_jul01_gp) + PALETTE_ib_44, comptr(PALETTE_ib_44) + PALETTE_Fire_1, comptr(PALETTE_Fire_1) + PALETTE_bhw1_sunconure, comptr(PALETTE_bhw1_sunconure) + PALETTE_bhw4_089, comptr(PALETTE_bhw4_089) core, class(be_class_Animate_core) animator, class(be_class_Animate_animator) From 2204ecdc516b885e88f02caff5c83688e7d0b1af Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Mon, 18 Dec 2023 10:17:39 +0100 Subject: [PATCH 016/303] Unify de_DE (#20257) * Unify de_DE Make de_DE more unify * Update de_DE.h --- tasmota/language/de_DE.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index c76ddbb29..31aaa5721 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v13.2.0.2 - Last update 19.11.2023 + * Updated until v13.3.0.1 - Last update 17.12.2023 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -278,12 +278,12 @@ #define D_CONSOLE "Konsole" #define D_CONFIRM_RESTART "Wirklich neustarten?" -#define D_CONFIGURE_MODULE "Gerät konfigurieren" -#define D_CONFIGURE_WIFI "WLAN konfigurieren" -#define D_CONFIGURE_MQTT "MQTT konfigurieren" -#define D_CONFIGURE_DOMOTICZ "Domoticz konfigurieren" -#define D_CONFIGURE_LOGGING "Logging konfigurieren" -#define D_CONFIGURE_OTHER "Sonstige Konfiguration" +#define D_CONFIGURE_MODULE "Geräteeinstellungen" +#define D_CONFIGURE_WIFI "WLAN-Einstellungen" +#define D_CONFIGURE_MQTT "MQTT-Einstellungen" +#define D_CONFIGURE_DOMOTICZ "Domoticz-Einstellungen" +#define D_CONFIGURE_LOGGING "Logging-Einstellungen" +#define D_CONFIGURE_OTHER "Weitere Einstellungen" #define D_CONFIRM_RESET_CONFIGURATION "Zurücksetzen der Konfiguration bestätigen" #define D_RESET_CONFIGURATION "Konfiguration zurücksetzen" #define D_BACKUP_CONFIGURATION "Konfiguration sichern" @@ -322,7 +322,7 @@ #define D_SHOW_MORE_OPTIONS "Mehr Optionen" #define D_CHECK_CREDENTIALS "Bitte SSID/Passwort überprüfen" #define D_SUCCESSFUL_WIFI_CONNECTION "mit Wifi verbunden" -#define D_NOW_YOU_CAN_CLOSE_THIS_WINDOW "Fenster kann geschlossen werden" +#define D_NOW_YOU_CAN_CLOSE_THIS_WINDOW "Das Fenster kann geschlossen werden" #define D_REDIRECTING_TO_NEW_IP "Umleitung zur neuen Geräte IP-Adresse" #define D_MQTT_PARAMETERS "MQTT-Einstellungen" @@ -339,7 +339,7 @@ #define D_SYSLOG_PORT "Syslog Port" #define D_TELEMETRY_PERIOD "Telemetrieperiode" -#define D_OTHER_PARAMETERS "Sonstige Einstellungen" +#define D_OTHER_PARAMETERS "Weiterte Einstellungen" #define D_TEMPLATE "Vorlage" #define D_ACTIVATE "Aktivieren" #define D_DEVICE_NAME "Gerätename" @@ -348,7 +348,7 @@ #define D_MQTT_TLS_ENABLE "MQTT TLS" #define D_HTTP_API "HTTP API" #define D_HTTP_API_ENABLE "HTTP API aktivieren" -#define D_FRIENDLY_NAME "Name [Friendly Name]" +#define D_FRIENDLY_NAME "Friendly Name" #define D_BELKIN_WEMO "Belkin WeMo" #define D_HUE_BRIDGE "Hue Bridge" #define D_SINGLE_DEVICE "Einzelnes Gerät" @@ -443,7 +443,7 @@ #define D_3_RESPONSE_PACKETS_SENT "3 Antwortpakete gesendet" // xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz-Parameter" +#define D_DOMOTICZ_PARAMETERS "Domoticz-Einstellungen" #define D_DOMOTICZ_IDX "Idx" #define D_DOMOTICZ_KEY_IDX "Key idx" #define D_DOMOTICZ_SWITCH_IDX "Switch idx" @@ -461,7 +461,7 @@ #define D_DOMOTICZ_UPDATE_TIMER "Update Zeitplan" // xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Zeitplan konfigurieren" +#define D_CONFIGURE_TIMER "Zeitplaneinstellungen" #define D_TIMER_PARAMETERS "Zeitplaneinstellungen" #define D_TIMER_ENABLE "Zeitpläne aktivieren" #define D_TIMER_ARM "Aktiv" @@ -957,7 +957,7 @@ #define D_SENSOR_BIOPDU_PZEM016_RX "BioPDU PZEM016 Rx" #define D_SENSOR_BIOPDU_BIT "BioPDU Bit" #define D_SENSOR_LOX_O2_RX "LoxO2 RX" -#define D_GPIO_MAGIC_SWITCH "MagicSwitch" +#define D_GPIO_MAGIC_SWITCH "MagicSwitch" // Units #define D_UNIT_AMPERE "A" From 6b35fc8ddb050dd891352e646044ffcfba80045d Mon Sep 17 00:00:00 2001 From: Arne Meeuw Date: Mon, 18 Dec 2023 11:03:18 +0100 Subject: [PATCH 017/303] Add support for CST816S touch interface (#20213) * Add initial version (prints coordinates) * Add CST816S_found * Revert formatting * Add supported gestures (untested) * Correct use of enums * Remove library dependency * Unification of methods * Remove redundant variables and format --- tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino | 71 +++++++++++++++++-- .../xdsp_17_universal.ino | 16 ++++- 2 files changed, 82 insertions(+), 5 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino index 01bbe97ca..44eca227e 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino @@ -71,6 +71,7 @@ typedef struct TSGlobal_t { TSGlobal_t TSGlobal; +bool CST816S_found = false; bool FT5206_found = false; bool GT911_found = false; bool XPT2046_found = false; @@ -97,7 +98,7 @@ void Touch_SetStatus(uint8_t touches, uint16_t raw_x, uint16_t raw_y, uint8_t ge // return true if succesful, false if not configured bool Touch_GetStatus(uint8_t* touches, uint16_t* x, uint16_t* y, uint8_t* gesture, uint16_t* raw_x, uint16_t* raw_y) { - if (TSGlobal.external_ts || FT5206_found || XPT2046_found) { + if (TSGlobal.external_ts || CST816S_found || FT5206_found || XPT2046_found) { if (touches) { *touches = TSGlobal.touches; } if (x) { *x = TSGlobal.touch_xp; } if (y) { *y = TSGlobal.touch_yp; } @@ -110,7 +111,7 @@ bool Touch_GetStatus(uint8_t* touches, uint16_t* x, uint16_t* y, uint8_t* gestur } uint32_t Touch_Status(int32_t sel) { - if (TSGlobal.external_ts || FT5206_found || GT911_found || XPT2046_found || SRES_found) { + if (TSGlobal.external_ts || CST816S_found || FT5206_found || GT911_found || XPT2046_found || SRES_found) { switch (sel) { case 0: return TSGlobal.touched; @@ -185,6 +186,62 @@ int16_t SRES_y() { } #endif +#ifdef USE_CST816S +#undef CST816S_address +#define CST816S_address 0x15 + +bool CST816S_event_available = false; +uint8_t CST816S_bus = 0; + +uint8_t CST816S_map_gesture(uint8_t gesture) { + switch (gesture) { + case 0x01: return TS_Gest_Move_Up; // SWIPE_UP + case 0x02: return TS_Gest_Move_Down; // SWIPE_DOWN + case 0x03: return TS_Gest_Move_Left; // SWIPE_LEFT + case 0x04: return TS_Gest_Move_Right; // SWIPE_RIGHT + case 0x05: return TS_Gest_None; // SINGLE_CLICK + case 0x0B: return TS_Gest_None; // DOUBLE_CLICK + case 0x0C: return TS_Gest_None; // LONG_PRESS + default: return TS_Gest_None; // NONE + } +} + +bool CST816S_available() { + if (CST816S_event_available) { + byte data_raw[8]; + I2cReadBuffer(CST816S_address, 0x01, data_raw, 6, CST816S_bus); + TSGlobal.raw_touch_xp = ((data_raw[2] & 0xF) << 8) + data_raw[3]; + TSGlobal.raw_touch_yp = ((data_raw[4] & 0xF) << 8) + data_raw[5]; + TSGlobal.gesture = CST816S_map_gesture(data_raw[0]); + CST816S_event_available = false; + return true; + } + return false; +} + +bool CST816S_Touch_Init(uint8_t bus, int8_t irq_pin, int8_t rst_pin, int interrupt = RISING) { + CST816S_found = false; + CST816S_bus = bus; + pinMode(irq_pin, INPUT); + pinMode(rst_pin, OUTPUT); + digitalWrite(rst_pin, HIGH); + delay(50); + digitalWrite(rst_pin, LOW); + delay(5); + digitalWrite(rst_pin, HIGH); + delay(50); + uint8_t version; + I2cReadBuffer(CST816S_address, 0x15, &version, 1, CST816S_bus); + delay(5); + uint8_t versionInfo[3]; + I2cReadBuffer(CST816S_address, 0xA7, versionInfo, 3, CST816S_bus); + attachInterrupt(irq_pin, []{ CST816S_event_available = true; }, interrupt); + CST816S_found = true; + AddLog(LOG_LEVEL_INFO, PSTR("TI: CST816S, version: %d, versionInfo: %d.%d.%d"), version, versionInfo[0], versionInfo[1], versionInfo[2]); + return CST816S_found; +} +#endif // USE_CST816S + #ifdef USE_FT5206 #include // touch panel controller @@ -307,6 +364,12 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) { } #endif +#ifdef USE_CST816S + if (CST816S_found) { + TSGlobal.touched = CST816S_available(); + } +#endif // USE_CST816S + #ifdef USE_FT5206 if (FT5206_found) { TSGlobal.touched = FT5206_touched(); @@ -360,7 +423,7 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) { #endif // USE_TOUCH_BUTTONS rotconvert(&TSGlobal.touch_xp, &TSGlobal.touch_yp); - AddLog(LOG_LEVEL_DEBUG_MORE, "TS : TSGlobal.touched x=%i y=%i (raw x=%i y=%i)", TSGlobal.touch_xp, TSGlobal.touch_yp, TSGlobal.raw_touch_xp, TSGlobal.raw_touch_yp); + AddLog(LOG_LEVEL_DEBUG_MORE, "TS : TSGlobal.touched x=%i y=%i gest=0x%02x (raw x=%i y=%i)", TSGlobal.touch_xp, TSGlobal.touch_yp, TSGlobal.gesture, TSGlobal.raw_touch_xp, TSGlobal.raw_touch_yp); #ifdef USE_TOUCH_BUTTONS CheckTouchButtons(TSGlobal.touched, TSGlobal.touch_xp, TSGlobal.touch_yp); @@ -522,7 +585,7 @@ bool Xdrv55(uint32_t function) { case FUNC_INIT: break; case FUNC_EVERY_100_MSECOND: - if (FT5206_found || XPT2046_found || GT911_found || SRES_found) { + if (CST816S_found || FT5206_found || XPT2046_found || GT911_found || SRES_found) { Touch_Check(TS_RotConvert); } break; diff --git a/tasmota/tasmota_xdsp_display/xdsp_17_universal.ino b/tasmota/tasmota_xdsp_display/xdsp_17_universal.ino index c0a1a377f..b9213ed17 100644 --- a/tasmota/tasmota_xdsp_display/xdsp_17_universal.ino +++ b/tasmota/tasmota_xdsp_display/xdsp_17_universal.ino @@ -35,6 +35,8 @@ extern FS *ffsp; #undef GT911_address #define GT911_address 0x5D +#undef CST816S_address +#define CST816S_address 0x15 enum {GPIO_DP_RES=GPIO_SENSOR_END-1,GPIO_DP_CS,GPIO_DP_RS,GPIO_DP_WR,GPIO_DP_RD,GPIO_DPAR0,GPIO_DPAR1,GPIO_DPAR2,GPIO_DPAR3,GPIO_DPAR4,GPIO_DPAR5,GPIO_DPAR6,GPIO_DPAR7,GPIO_DPAR8,GPIO_DPAR9,GPIO_DPAR10,GPIO_DPAR11,GPIO_DPAR12,GPIO_DPAR13,GPIO_DPAR14,GPIO_DPAR15}; @@ -312,7 +314,7 @@ int8_t cs; udisp = new uDisplay(ddesc); // checck for touch option TI1 or TI2 -#if defined(USE_FT5206) || defined(USE_GT911) +#if defined (USE_CST816S) || defined(USE_FT5206) || defined(USE_GT911) cp = strstr(ddesc, ":TI"); if (cp) { uint8_t wire_n = 1; @@ -350,6 +352,8 @@ int8_t cs; if (I2cSetDevice(i2caddr, wire_n)) { if (i2caddr == GT911_address) { I2cSetActiveFound(i2caddr, "GT911", wire_n); + } else if (i2caddr == CST816S_address) { + I2cSetActiveFound(i2caddr, "CST816S", wire_n); } else { I2cSetActiveFound(i2caddr, "FT5206", wire_n); } @@ -361,6 +365,8 @@ int8_t cs; if (I2cSetDevice(i2caddr)) { if (i2caddr == GT911_address) { I2cSetActiveFound(i2caddr, "GT911"); + } else if (i2caddr == CST816S_address) { + I2cSetActiveFound(i2caddr, "CST816S"); } else { I2cSetActiveFound(i2caddr, "FT5206"); } @@ -373,6 +379,10 @@ int8_t cs; #ifdef USE_GT911 if (!wire_n) GT911_Touch_Init(&Wire, irq, rst, xs, ys); else GT911_Touch_Init(&Wire1, irq, rst, xs, ys); +#endif + } else if (i2caddr == CST816S_address) { +#ifdef USE_CST816S + CST816S_Touch_Init(wire_n, irq, rst); #endif } else { #ifdef USE_FT5206 @@ -386,6 +396,10 @@ int8_t cs; if (i2caddr == GT911_address) { #ifdef USE_GT911 if (!wire_n) GT911_Touch_Init(&Wire, irq, rst, xs, ys); +#endif + } else if (i2caddr == CST816S_address) { +#ifdef USE_CST816S + CST816S_Touch_Init(wire_n, irq, rst); #endif } else { #ifdef USE_FT5206 From c111bb963ff4d22e970a71539b174ca7eaafaf8a Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Mon, 18 Dec 2023 11:27:12 +0100 Subject: [PATCH 018/303] Add NeoPool hydrolysis FL1 and Redox flag (#20258) --- tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino b/tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino index 18b30b914..81abf890f 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino @@ -1882,6 +1882,10 @@ void NeoPoolShow(bool json) ResponseAppend_P(PSTR(",\"" D_NEOPOOL_JSON_SHOCK "\":%d"), (NeoPoolGetData(MBF_HIDRO_STATUS) & MBMSK_HIDRO_STATUS_SHOCK_ENABLED) ? ((NeoPoolGetData(MBF_CELL_BOOST) & MBMSK_CELL_BOOST_NO_REDOX_CTL) ? 1 : 2) : 0 ); // S4 ResponseAppend_P(PSTR(",\"" D_NEOPOOL_JSON_LOW "\":%d"), (NeoPoolGetData(MBF_HIDRO_STATUS) & MBMSK_HIDRO_STATUS_LOW) ? 1 : 0 ); + // S5 + ResponseAppend_P(PSTR(",\"" D_NEOPOOL_JSON_FLOW1 "\":%d"), (NeoPoolGetData(MBF_HIDRO_STATUS) & MBMSK_HIDRO_STATUS_FL1) ? 0 : 1); + // S6 + ResponseAppend_P(PSTR(",\"" D_NEOPOOL_JSON_REDOX "\":%d"), (NeoPoolGetData(MBF_HIDRO_STATUS) & MBMSK_HIDRO_STATUS_REDOX_ENABLED) ? 1 : 0); ResponseJsonEnd(); } From f65ae0694b99f454a0525bc387ef8cac0162b5d7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 18 Dec 2023 12:31:14 +0100 Subject: [PATCH 019/303] Fix XSS phase 1 --- .../xdrv_01_9_webserver.ino | 47 ++++++++++--------- .../tasmota_xdrv_driver/xdrv_02_9_mqtt.ino | 10 ++-- .../tasmota_xdrv_driver/xdrv_06_snfbridge.ino | 2 +- .../tasmota_xdrv_driver/xdrv_10_scripter.ino | 2 +- .../xdrv_16_tuyamcu_v1.ino | 2 +- .../xdrv_16_tuyamcu_v2.ino | 2 +- .../tasmota_xlgt_light/xlgt_07_lsc_mcsl.ino | 2 +- 7 files changed, 36 insertions(+), 31 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino index 79c953b72..df267b533 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino @@ -477,6 +477,10 @@ static void WebGetArg(const char* arg, char* out, size_t max) // out[max-1] = '\0'; // Ensure terminating NUL } +String SettingsTextEscaped(uint32_t index) { + return HtmlEscape(SettingsText(index)); +} + String AddWebCommand(const char* command, const char* arg, const char* dflt) { /* // OK but fixed max argument @@ -865,7 +869,7 @@ void WSContentStart_P(const char* title, bool auth) { WSContentBegin(200, CT_HTML); if (title != nullptr) { - WSContentSend_P(HTTP_HEADER1, PSTR(D_HTML_LANGUAGE), SettingsText(SET_DEVICENAME), title); + WSContentSend_P(HTTP_HEADER1, PSTR(D_HTML_LANGUAGE), SettingsTextEscaped(SET_DEVICENAME).c_str(), title); } } @@ -909,7 +913,7 @@ void WSContentSendStyle_P(const char* formatP, ...) { WebColor(COL_TEXT_WARNING), #endif WebColor(COL_TITLE), - (Web.initial_config) ? "" : (Settings->flag5.gui_module_name) ? "" : ModuleName().c_str(), SettingsText(SET_DEVICENAME)); + (Web.initial_config) ? "" : (Settings->flag5.gui_module_name) ? "" : ModuleName().c_str(), SettingsTextEscaped(SET_DEVICENAME).c_str()); // SetOption53 - Show hostname and IP address in GUI main menu #if (RESTART_AFTER_INITIAL_WIFI_CONFIG) @@ -1264,12 +1268,12 @@ void HandleRoot(void) #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1, - (strlen(SettingsText(SET_BUTTON1))) ? SettingsText(SET_BUTTON1) : PSTR(D_BUTTON_TOGGLE), + (strlen(SettingsText(SET_BUTTON1))) ? SettingsTextEscaped(SET_BUTTON1).c_str() : PSTR(D_BUTTON_TOGGLE), ""); for (uint32_t i = 0; i < MaxFanspeed(); i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i); WSContentSend_P(HTTP_DEVICE_CONTROL, 16, i +2, - (strlen(SettingsText(SET_BUTTON2 + i))) ? SettingsText(SET_BUTTON2 + i) : stemp, + (strlen(SettingsText(SET_BUTTON2 + i))) ? SettingsTextEscaped(SET_BUTTON2 + i).c_str() : stemp, ""); } } else { @@ -1281,13 +1285,13 @@ void HandleRoot(void) int32_t ShutterWebButton; if (ShutterWebButton = IsShutterWebButton(idx)) { WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / cols, idx, - (set_button) ? GetWebButton(idx -1) : ((ShutterGetOptions(abs(ShutterWebButton)-1) & 2) /* is locked */ ? "-" : ((ShutterGetOptions(abs(ShutterWebButton)-1) & 8) /* invert web buttons */ ? ((ShutterWebButton>0) ? "▼" : "▲") : ((ShutterWebButton>0) ? "▲" : "▼"))), + (set_button) ? HtmlEscape(GetWebButton(idx -1)).c_str() : ((ShutterGetOptions(abs(ShutterWebButton)-1) & 2) /* is locked */ ? "-" : ((ShutterGetOptions(abs(ShutterWebButton)-1) & 8) /* invert web buttons */ ? ((ShutterWebButton>0) ? "▼" : "▲") : ((ShutterWebButton>0) ? "▲" : "▼"))), ""); } else { #endif // USE_SHUTTER snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / cols, idx, - (set_button) ? GetWebButton(idx -1) : (cols < 5) ? PSTR(D_BUTTON_TOGGLE) : "", + (set_button) ? HtmlEscape(GetWebButton(idx -1)).c_str() : (cols < 5) ? PSTR(D_BUTTON_TOGGLE) : "", (set_button) ? "" : (TasmotaGlobal.devices_present > 1) ? stemp : ""); #ifdef USE_SHUTTER } @@ -2078,15 +2082,15 @@ void HandleWifiConfiguration(void) { } WSContentSend_P(PSTR("
"), (limitScannedNetworks) ? PSTR(D_SHOW_MORE_WIFI_NETWORKS) : PSTR(D_SCAN_FOR_WIFI_NETWORKS)); - WSContentSend_P(HTTP_FORM_WIFI_PART1, (WifiIsInManagerMode()) ? "" : PSTR(" (" STA_SSID1 ")"), SettingsText(SET_STASSID1)); + WSContentSend_P(HTTP_FORM_WIFI_PART1, (WifiIsInManagerMode()) ? "" : PSTR(" (" STA_SSID1 ")"), SettingsTextEscaped(SET_STASSID1).c_str()); if (WifiIsInManagerMode()) { // As WIFI_HOSTNAME may contain %s-%04d it cannot be part of HTTP_FORM_WIFI where it will exception WSContentSend_P(PSTR(">

")); } else { #ifdef USE_CORS - WSContentSend_P(HTTP_FORM_WIFI_PART2, SettingsText(SET_STASSID2), WIFI_HOSTNAME, WIFI_HOSTNAME, SettingsText(SET_HOSTNAME), SettingsText(SET_CORS)); + WSContentSend_P(HTTP_FORM_WIFI_PART2, SettingsTextEscaped(SET_STASSID2).c_str(), WIFI_HOSTNAME, WIFI_HOSTNAME, SettingsTextEscaped(SET_HOSTNAME).c_str(), SettingsTextEscaped(SET_CORS).c_str()); #else - WSContentSend_P(HTTP_FORM_WIFI_PART2, SettingsText(SET_STASSID2), WIFI_HOSTNAME, WIFI_HOSTNAME, SettingsText(SET_HOSTNAME)); + WSContentSend_P(HTTP_FORM_WIFI_PART2, SettingsTextEscaped(SET_STASSID2).c_str(), WIFI_HOSTNAME, WIFI_HOSTNAME, SettingsTextEscaped(SET_HOSTNAME).c_str()); #endif } @@ -2099,9 +2103,9 @@ void HandleWifiConfiguration(void) { WSContentSend_P(PSTR("

")); if (WIFI_TESTING == Wifi.wifiTest) { - WSContentSend_P(PSTR(D_TRYING_TO_CONNECT "
%s

"), SettingsText(SET_STASSID1)); + WSContentSend_P(PSTR(D_TRYING_TO_CONNECT "
%s"), SettingsTextEscaped(SET_STASSID1).c_str()); } else if (WIFI_TEST_FINISHED_BAD == Wifi.wifiTest) { - WSContentSend_P(PSTR(D_CONNECT_FAILED_TO " %s
" D_CHECK_CREDENTIALS ""), SettingsText(SET_STASSID1)); + WSContentSend_P(PSTR(D_CONNECT_FAILED_TO " %s
" D_CHECK_CREDENTIALS ""), SettingsTextEscaped(SET_STASSID1).c_str()); } // More Options Button WSContentSend_P(PSTR("

"), @@ -2163,7 +2167,7 @@ void HandleLoggingConfiguration(void) { } WSContentSend_P(PSTR("

")); } - WSContentSend_P(HTTP_FORM_LOG2, SettingsText(SET_SYSLOG_HOST), Settings->syslog_port, Settings->tele_period); + WSContentSend_P(HTTP_FORM_LOG2, SettingsTextEscaped(SET_SYSLOG_HOST).c_str(), Settings->syslog_port, Settings->tele_period); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentStop(); @@ -2198,10 +2202,10 @@ void HandleOtherConfiguration(void) { WSContentSendStyle(); TemplateJson(); - WSContentSend_P(HTTP_FORM_OTHER, ResponseData(), (USER_MODULE == Settings->module) ? PSTR(" checked disabled") : "", + WSContentSend_P(HTTP_FORM_OTHER, HtmlEscape(ResponseData()).c_str(), (USER_MODULE == Settings->module) ? PSTR(" checked disabled") : "", (Settings->flag5.disable_referer_chk) ? PSTR(" checked") : "", // SetOption128 - Enable HTTP API (Settings->flag.mqtt_enabled) ? PSTR(" checked") : "", // SetOption3 - Enable MQTT - SettingsText(SET_FRIENDLYNAME1), SettingsText(SET_DEVICENAME)); + SettingsTextEscaped(SET_FRIENDLYNAME1).c_str(), SettingsTextEscaped(SET_DEVICENAME).c_str()); char stemp[32]; uint32_t maxfn = (TasmotaGlobal.devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!TasmotaGlobal.devices_present) ? 1 : TasmotaGlobal.devices_present; @@ -2215,7 +2219,7 @@ void HandleOtherConfiguration(void) { (i) ? stemp : "", i, (i) ? stemp : "", - SettingsText(SET_FRIENDLYNAME1 + i)); + SettingsTextEscaped(SET_FRIENDLYNAME1 + i).c_str()); } #ifdef USE_EMULATION @@ -2377,7 +2381,7 @@ void HandleInformation(void) if (IsModuleIfan()) { maxfn = 1; } #endif // USE_SONOFF_IFAN for (uint32_t i = 0; i < maxfn; i++) { - WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, SettingsText(SET_FRIENDLYNAME1 +i)); + WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, SettingsTextEscaped(SET_FRIENDLYNAME1 +i).c_str()); } WSContentSend_P(PSTR("}1}2 ")); // Empty line bool show_hr = false; @@ -2391,7 +2395,7 @@ void HandleInformation(void) int32_t rssi = WiFi.RSSI(); WSContentSend_P(PSTR("}1" D_AP "%d " D_INFORMATION "}2" D_SSID " %s
" D_RSSI " %d%%, %d dBm
" D_MODE " 11%c
" D_CHANNEL " %d
" D_BSSID " %s"), Settings->sta_active +1, - HtmlEscape(SettingsText(SET_STASSID1 + Settings->sta_active)).c_str(), + SettingsTextEscaped(SET_STASSID1 + Settings->sta_active).c_str(), WifiGetRssiAsQuality(rssi), rssi, pgm_read_byte(&kWifiPhyMode[WiFi.getPhyMode() & 0x3]), WiFi.channel(), @@ -2460,14 +2464,14 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1" D_HTTP_API "}2%s"), Settings->flag5.disable_referer_chk ? PSTR(D_ENABLED) : PSTR(D_DISABLED)); // SetOption 128 WSContentSend_P(PSTR("}1}2 ")); // Empty line if (Settings->flag.mqtt_enabled) { // SetOption3 - Enable MQTT - WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), SettingsText(SET_MQTT_HOST)); + WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), SettingsTextEscaped(SET_MQTT_HOST).c_str()); WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings->mqtt_port); #ifdef USE_MQTT_TLS WSContentSend_P(PSTR("}1" D_MQTT_TLS_ENABLE "}2%s"), Settings->flag4.mqtt_tls ? PSTR(D_ENABLED) : PSTR(D_DISABLED)); #endif // USE_MQTT_TLS - WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), SettingsText(SET_MQTT_USER)); + WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), SettingsTextEscaped(SET_MQTT_USER).c_str()); WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), TasmotaGlobal.mqtt_client); - WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), SettingsText(SET_MQTT_TOPIC)); + WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), SettingsTextEscaped(SET_MQTT_TOPIC).c_str()); uint32_t real_index = SET_MQTT_GRP_TOPIC; for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; } @@ -2634,7 +2638,7 @@ void HandleUpgradeFirmware(void) { WSContentStart_P(PSTR(D_FIRMWARE_UPGRADE)); WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_UPG, SettingsText(SET_OTAURL)); + WSContentSend_P(HTTP_FORM_UPG, SettingsTextEscaped(SET_OTAURL).c_str()); #ifdef ESP32 if (EspSingleOtaPartition() && !EspRunningFactoryPartition()) { WSContentSend_P(HTTP_FORM_RST_UPG_FCT, PSTR(D_START_UPGRADE)); @@ -3780,6 +3784,7 @@ void CmndWebCanvas(void) { - WebCanvas linear-gradient(#F02 7%,#F93,#FF4,#082,#00F,#708 93%) // Gradient pride flag - WebCanvas linear-gradient(#F02 16%,#F93 16% 33%,#FF4 33% 50%,#082 50% 67%,#00F 67% 84%,#708 84%) // Pride flag - WebCanvas linear-gradient(90deg,#05A 33%,#FFF 33% 67%,#F43 67%) // Flag France + - WebCanvas linear-gradient(#000 33%,#D00 33% 67%,#FC0 67%) // Flag Germany - WebCanvas linear-gradient(#059 33%,#FFF 33% 67%,#F43 67%) // Flag The Netherlands - WebCanvas linear-gradient(#05B 50%,#FD0 50%) // Flag Ukraine - WebCanvas linear-gradient(#FFF 33%,#07D 33% 67%,#F34 67%) // Flag Russia diff --git a/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino b/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino index 91eb1ef6d..7312135e8 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino @@ -1974,16 +1974,16 @@ void HandleMqttConfiguration(void) WSContentStart_P(PSTR(D_CONFIGURE_MQTT)); WSContentSendStyle(); WSContentSend_P(HTTP_FORM_MQTT1, - SettingsText(SET_MQTT_HOST), + SettingsTextEscaped(SET_MQTT_HOST).c_str(), Settings->mqtt_port, #ifdef USE_MQTT_TLS Mqtt.mqtt_tls ? PSTR(" checked") : "", // SetOption103 - Enable MQTT TLS #endif // USE_MQTT_TLS - Format(str, PSTR(MQTT_CLIENT_ID), sizeof(str)), PSTR(MQTT_CLIENT_ID), SettingsText(SET_MQTT_CLIENT)); + Format(str, PSTR(MQTT_CLIENT_ID), sizeof(str)), PSTR(MQTT_CLIENT_ID), SettingsTextEscaped(SET_MQTT_CLIENT).c_str()); WSContentSend_P(HTTP_FORM_MQTT2, - (!strlen(SettingsText(SET_MQTT_USER))) ? "0" : SettingsText(SET_MQTT_USER), - Format(str, PSTR(MQTT_TOPIC), sizeof(str)), PSTR(MQTT_TOPIC), SettingsText(SET_MQTT_TOPIC), - PSTR(MQTT_FULLTOPIC), PSTR(MQTT_FULLTOPIC), SettingsText(SET_MQTT_FULLTOPIC)); + (!strlen(SettingsText(SET_MQTT_USER))) ? "0" : SettingsTextEscaped(SET_MQTT_USER).c_str(), + Format(str, PSTR(MQTT_TOPIC), sizeof(str)), PSTR(MQTT_TOPIC), SettingsTextEscaped(SET_MQTT_TOPIC).c_str(), + PSTR(MQTT_FULLTOPIC), PSTR(MQTT_FULLTOPIC), SettingsTextEscaped(SET_MQTT_FULLTOPIC).c_str()); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentStop(); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_06_snfbridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_06_snfbridge.ino index 9b34c497d..2b9988ec6 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_06_snfbridge.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_06_snfbridge.ino @@ -516,7 +516,7 @@ void SonoffBridgeAddButton(void) { for (uint32_t j = 0; j < 4; j++) { idx++; WSContentSend_P(PSTR(""), idx, // &k is related to WebGetArg("k", tmp, sizeof(tmp)); - (strlen(GetWebButton(idx -1))) ? GetWebButton(idx -1) : itoa(idx, number, 10)); + (strlen(GetWebButton(idx -1))) ? HtmlEscape(GetWebButton(idx -1)).c_str() : itoa(idx, number, 10)); } } WSContentSend_P(PSTR("")); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino index f18ba4bc7..98a9c352f 100755 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino @@ -10325,7 +10325,7 @@ void ScriptFullWebpage(uint8_t page) { } WSContentBegin(200, CT_HTML); - WSContentSend_P(HTTP_HEADER1, PSTR(D_HTML_LANGUAGE), SettingsText(SET_DEVICENAME), PSTR("Full Screen")); + WSContentSend_P(HTTP_HEADER1, PSTR(D_HTML_LANGUAGE), SettingsTextEscaped(SET_DEVICENAME).c_str(), PSTR("Full Screen")); WSContentSend_P(HTTP_SCRIPT_FULLPAGE1, page , fullpage_refresh); WSContentSend_P(HTTP_SCRIPT_FULLPAGE2, fullpage_refresh); //WSContentSend_P(PSTR("
")); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino index 5ea82165d..1c0e29315 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino @@ -1624,7 +1624,7 @@ void TuyaAddButton(void) { char stemp[33]; snprintf_P(stemp, sizeof(stemp), PSTR("" D_JSON_IRHVAC_MODE "")); WSContentSend_P(HTTP_DEVICE_CONTROL, 26, TasmotaGlobal.devices_present + 1, - (strlen(GetWebButton(TasmotaGlobal.devices_present))) ? GetWebButton(TasmotaGlobal.devices_present) : stemp, ""); + (strlen(GetWebButton(TasmotaGlobal.devices_present))) ? HtmlEscape(GetWebButton(TasmotaGlobal.devices_present)).c_str() : stemp, ""); WSContentSend_P(PSTR("")); } } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino index a85b7fe53..78d562546 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino @@ -2432,7 +2432,7 @@ void TuyaAddButton(void) { char stemp[33]; snprintf_P(stemp, sizeof(stemp), PSTR("" D_JSON_IRHVAC_MODE "")); WSContentSend_P(HTTP_DEVICE_CONTROL, 26, TasmotaGlobal.devices_present + 1, - (strlen(GetWebButton(TasmotaGlobal.devices_present))) ? GetWebButton(TasmotaGlobal.devices_present) : stemp, ""); + (strlen(GetWebButton(TasmotaGlobal.devices_present))) ? HtmlEscape(GetWebButton(TasmotaGlobal.devices_present)).c_str() : stemp, ""); WSContentSend_P(PSTR("")); } } diff --git a/tasmota/tasmota_xlgt_light/xlgt_07_lsc_mcsl.ino b/tasmota/tasmota_xlgt_light/xlgt_07_lsc_mcsl.ino index 684c63cbb..4270fc665 100644 --- a/tasmota/tasmota_xlgt_light/xlgt_07_lsc_mcsl.ino +++ b/tasmota/tasmota_xlgt_light/xlgt_07_lsc_mcsl.ino @@ -269,7 +269,7 @@ void LscMcAddFuctionButtons(void) { WSContentSend_P(PSTR(""), // &lsc is related to WebGetArg("lsc", tmp, sizeof(tmp)); 100 / cols, idx -1, - (strlen(GetWebButton(idx))) ? GetWebButton(idx) : itoa(idx, number, 10)); + (strlen(GetWebButton(idx))) ? HtmlEscape(GetWebButton(idx)).c_str() : itoa(idx, number, 10)); } } WSContentSend_P(PSTR("")); From d2690ef7c00639c3c6330349858e622b95dfa4bf Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 18 Dec 2023 14:02:00 +0100 Subject: [PATCH 020/303] enable CST816S touch driver in firmware lvgl (#20264) --- tasmota/include/tasmota_configurations_ESP32.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/include/tasmota_configurations_ESP32.h b/tasmota/include/tasmota_configurations_ESP32.h index 06891b607..7b86bdd3c 100644 --- a/tasmota/include/tasmota_configurations_ESP32.h +++ b/tasmota/include/tasmota_configurations_ESP32.h @@ -322,6 +322,7 @@ #define USE_XPT2046 #define USE_FT5206 #define USE_GT911 +#define USE_CST816S #define USE_MPU_ACCEL #define USE_RTC_CHIPS // Enable RTC chip support and NTP server - Select only one #define USE_BM8563 From b69a335634fe45926b390c164e13066ed62c84ab Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 18 Dec 2023 14:26:13 +0100 Subject: [PATCH 021/303] Update changelogs --- CHANGELOG.md | 3 +++ RELEASENOTES.md | 3 +++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index adce0b539..a5e0040d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ All notable changes to this project will be documented in this file. ## [13.3.0.1] ### Added - Support for Sonoff Basic R4 Magic Switch (#20247) +- Support for CST816S touch interface (#20213) +- NeoPool hydrolysis FL1 and Redox flag (#20258) ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds (#20236) @@ -14,6 +16,7 @@ All notable changes to this project will be documented in this file. ### Fixed - Matter Contact sensor was not triggering any update (#20232) +- CVE-2021-36603 Cross Site Scripting (XSS) vulnerability (#12221) ### Removed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 7f886e45f..dd63b29dc 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -118,7 +118,9 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ## Changelog v13.3.0.1 ### Added +- Support for CST816S touch interface [#20213](https://github.com/arendst/Tasmota/issues/20213) - Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247) +- NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds [#20236](https://github.com/arendst/Tasmota/issues/20236) @@ -126,6 +128,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ### Changed ### Fixed +- CVE-2021-36603 Cross Site Scripting (XSS) vulnerability [#12221](https://github.com/arendst/Tasmota/issues/12221) - Matter Contact sensor was not triggering any update [#20232](https://github.com/arendst/Tasmota/issues/20232) ### Removed \ No newline at end of file From 81f90a251ccac097a136513b2f042fa8ec6d82cd Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Tue, 19 Dec 2023 09:37:02 +0100 Subject: [PATCH 022/303] de_DE Fixes and typos (#20269) * de_DE Fixes and typos * Hyphen --- tasmota/language/de_DE.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index 31aaa5721..c3bfe2dd7 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v13.3.0.1 - Last update 17.12.2023 + * Updated until v13.3.0.1 - Last update 18.12.2023 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -176,7 +176,7 @@ #define D_STOP "Stop" #define D_SUBNET_MASK "Subnetzmaske" #define D_SUBSCRIBE_TO "abonniere" -#define D_UNSUBSCRIBE_FROM "löse abo․ von" +#define D_UNSUBSCRIBE_FROM "löse Abo․ von" #define D_SUCCESSFUL "erfolgreich" #define D_SUNRISE "Sonnenaufgang" #define D_SUNSET "Sonnenuntergang" @@ -243,7 +243,7 @@ #define D_CONNECT_FAILED_AP_TIMEOUT "Verbindung fehlgeschlagen, da der AP nicht antwortet (timeout)" #define D_ATTEMPTING_CONNECTION "Verbindungsversuch…" #define D_CHECKING_CONNECTION "Prüfe Verbindung…" -#define D_QUERY_DONE "Suchanfrage abgeschlossen․ MQTT-Services gefunden" +#define D_QUERY_DONE "Suche abgeschlossen․ MQTT-Services gefunden" #define D_MQTT_SERVICE_FOUND "MQTT-Service gefunden bei" #define D_FOUND_AT "gefunden bei" #define D_SYSLOG_HOST_NOT_FOUND "Syslog-Host nicht gefunden" @@ -339,7 +339,7 @@ #define D_SYSLOG_PORT "Syslog Port" #define D_TELEMETRY_PERIOD "Telemetrieperiode" -#define D_OTHER_PARAMETERS "Weiterte Einstellungen" +#define D_OTHER_PARAMETERS "Weitere Einstellungen" #define D_TEMPLATE "Vorlage" #define D_ACTIVATE "Aktivieren" #define D_DEVICE_NAME "Gerätename" @@ -399,7 +399,7 @@ #define D_UPLOAD_ERR_3 "Falsche Dateisignatur" #define D_UPLOAD_ERR_4 "Datei überschreitet vorhdn․ Flashspeicher" #define D_UPLOAD_ERR_5 "Upload Buffer Vergleich weicht ab" -#define D_UPLOAD_ERR_6 "Upload fehlgeschlagen․ Aktiviere logging 3" +#define D_UPLOAD_ERR_6 "Upload fehlgeschlagen․ Aktiviere Logging 3" #define D_UPLOAD_ERR_7 "Upload abgebrochen" #define D_UPLOAD_ERR_8 "Datei ungültig" #define D_UPLOAD_ERR_9 "Datei zu groß" @@ -408,7 +408,7 @@ #define D_UPLOAD_ERR_12 "RF Chip beschreiben fehlgeschlagen" #define D_UPLOAD_ERR_13 "RF Firmware ungültig" #define D_UPLOAD_ERR_14 "Nicht kompatibel" -#define D_UPLOAD_ERROR_CODE "Upload Fehler Nummer" +#define D_UPLOAD_ERROR_CODE "Upload Fehlernummer" #define D_ENTER_COMMAND "Befehl eingeben" #define D_ENABLE_WEBLOG_FOR_RESPONSE "Aktivere Web Log Level 2 falls Reaktion erwartet" @@ -445,9 +445,9 @@ // xdrv_07_domoticz.ino #define D_DOMOTICZ_PARAMETERS "Domoticz-Einstellungen" #define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" +#define D_DOMOTICZ_KEY_IDX "Key Idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch Idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor Idx" #define D_DOMOTICZ_TEMP "Temp" #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" @@ -458,7 +458,7 @@ #define D_DOMOTICZ_CURRENT "Current/PM10" #define D_DOMOTICZ_AIRQUALITY "AirQuality" #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Update Zeitplan" +#define D_DOMOTICZ_UPDATE_TIMER "Zeitplan-Update" // xdrv_09_timers.ino #define D_CONFIGURE_TIMER "Zeitplaneinstellungen" @@ -472,7 +472,7 @@ #define D_TIMER_ACTION "Aktion" // xdrv_10_knx.ino -#define D_CONFIGURE_KNX "KNX konfigurieren" +#define D_CONFIGURE_KNX "KNX-Einstellungen" #define D_KNX_PARAMETERS "KNX-Parameter" #define D_KNX_GENERAL_CONFIG "Allgemein" #define D_KNX_PHYSICAL_ADDRESS "Physikalische Adresse" @@ -526,7 +526,7 @@ // xdrv_89_dali.ino #define D_SENSOR_DALI_RX "Dali RX" #define D_SENSOR_DALI_TX "Dali TX" -#define D_CONFIGURE_DALI "Konfig․ DALI" +#define D_CONFIGURE_DALI "DALI-Einstellungen" // xdrv_03_energy.ino #define D_ENERGY_TODAY "Energie heute" @@ -539,9 +539,9 @@ #define D_DOMOTICZ_SHUTTER "Rollo" // xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Konfiguriere PCF8574" +#define D_CONFIGURE_PCF8574 "PCF8574-Einstellungen" #define D_PCF8574_PARAMETERS "PCF8574 Parameter" -#define D_INVERT_PORTS "Invertiere Ports" +#define D_INVERT_PORTS "Ports invertieren" #define D_DEVICE "Gerät" #define D_DEVICE_INPUT "Eingang" #define D_DEVICE_OUTPUT "Ausgang" From 23b4cd08d469797ab65515d64a1405db93021ec0 Mon Sep 17 00:00:00 2001 From: budulinek Date: Tue, 19 Dec 2023 12:29:39 +0100 Subject: [PATCH 023/303] Realtime syslog (#20260) * Realtime Syslog * Update tasmota.ino --------- Co-authored-by: Theo Arends <11044339+arendst@users.noreply.github.com> --- tasmota/tasmota.ino | 2 ++ tasmota/tasmota_support/support_tasmota.ino | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 953db16b4..926839510 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -886,6 +886,8 @@ void Scheduler(void) { ArduinoOtaLoop(); #endif // USE_ARDUINO_OTA #endif // ESP8266 + + SyslogAsync(false); } void loop(void) { diff --git a/tasmota/tasmota_support/support_tasmota.ino b/tasmota/tasmota_support/support_tasmota.ino index 6f8c2870a..5df42a0d2 100644 --- a/tasmota/tasmota_support/support_tasmota.ino +++ b/tasmota/tasmota_support/support_tasmota.ino @@ -1142,7 +1142,6 @@ void PerformEverySecond(void) } MqttPublishLoggingAsync(false); - SyslogAsync(false); ResetGlobalValues(); From b81eaf5bc8276ec1d306358848ae130c14ab2f4a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 19 Dec 2023 12:45:13 +0100 Subject: [PATCH 024/303] Support syslog updates every sleep Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` (#20260) --- CHANGELOG.md | 1 + RELEASENOTES.md | 1 + tasmota/tasmota.ino | 2 ++ tasmota/tasmota_support/support_tasmota.ino | 3 +++ 4 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5e0040d6..2609fcd7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ All notable changes to this project will be documented in this file. - Refactoring of Berry `animate` module for WS2812 Leds (#20236) ### Changed +- Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` (#20260) ### Fixed - Matter Contact sensor was not triggering any update (#20232) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index dd63b29dc..2d809a33a 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -126,6 +126,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Refactoring of Berry `animate` module for WS2812 Leds [#20236](https://github.com/arendst/Tasmota/issues/20236) ### Changed +- Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` [#20260](https://github.com/arendst/Tasmota/issues/20260) ### Fixed - CVE-2021-36603 Cross Site Scripting (XSS) vulnerability [#12221](https://github.com/arendst/Tasmota/issues/12221) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 926839510..1cf661f04 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -887,7 +887,9 @@ void Scheduler(void) { #endif // USE_ARDUINO_OTA #endif // ESP8266 +#ifndef SYSLOG_UPDATE_SECOND SyslogAsync(false); +#endif // SYSLOG_UPDATE_SECOND } void loop(void) { diff --git a/tasmota/tasmota_support/support_tasmota.ino b/tasmota/tasmota_support/support_tasmota.ino index 5df42a0d2..94c431e86 100644 --- a/tasmota/tasmota_support/support_tasmota.ino +++ b/tasmota/tasmota_support/support_tasmota.ino @@ -1142,6 +1142,9 @@ void PerformEverySecond(void) } MqttPublishLoggingAsync(false); +#ifdef SYSLOG_UPDATE_SECOND + SyslogAsync(false); +#endif // SYSLOG_UPDATE_SECOND ResetGlobalValues(); From d78a223646b2d474f0ee818823cf98294ec2e841 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 19 Dec 2023 15:14:57 +0100 Subject: [PATCH 025/303] enable lib `ESP32 Async UDP` for core 3.0.0 --- platformio_tasmota32.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index d27d9a7d6..da646960f 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -39,7 +39,6 @@ build_flags = ${esp_defaults.build_flags} lib_ignore = HTTPUpdateServer USB - ESP32 Async UDP esp-nimble-cpp NetBIOS Preferences From 87b5886ea7d21e1fb6d73baf8a81cdd54bd17f3f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 19 Dec 2023 15:18:03 +0100 Subject: [PATCH 026/303] correct enable `ESP32 Async UDP` for core 3.0.0 --- platformio_tasmota32.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index da646960f..a930178d0 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -39,6 +39,7 @@ build_flags = ${esp_defaults.build_flags} lib_ignore = HTTPUpdateServer USB + ESP32 Async UDP esp-nimble-cpp NetBIOS Preferences @@ -85,7 +86,6 @@ lib_extra_dirs = lib/lib_ssl, lib/lib_basic, lib/lib_i2c, lib/lib_d lib_ignore = HTTPUpdateServer USB - ESP32 Async UDP NetBIOS Preferences ArduinoOTA From 9e2ae391fc33bca88acdeb3a468912840936bb59 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 19 Dec 2023 15:38:12 +0100 Subject: [PATCH 027/303] Fix ESP32 piezo ceramic buzzer Fix ESP32 piezo ceramic buzzer doesn't buzz (#20118) --- CHANGELOG.md | 1 + RELEASENOTES.md | 1 + tasmota/tasmota_xdrv_driver/xdrv_24_buzzer.ino | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2609fcd7f..4f1887cb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file. ### Fixed - Matter Contact sensor was not triggering any update (#20232) - CVE-2021-36603 Cross Site Scripting (XSS) vulnerability (#12221) +- ESP32 piezo ceramic buzzer doesn't buzz (#20118) ### Removed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 2d809a33a..8953e8264 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -130,6 +130,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ### Fixed - CVE-2021-36603 Cross Site Scripting (XSS) vulnerability [#12221](https://github.com/arendst/Tasmota/issues/12221) +- ESP32 piezo ceramic buzzer doesn't buzz [#20118](https://github.com/arendst/Tasmota/issues/20118) - Matter Contact sensor was not triggering any update [#20232](https://github.com/arendst/Tasmota/issues/20232) ### Removed \ No newline at end of file diff --git a/tasmota/tasmota_xdrv_driver/xdrv_24_buzzer.ino b/tasmota/tasmota_xdrv_driver/xdrv_24_buzzer.ino index 81dcc1dc7..9a54076d5 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_24_buzzer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_24_buzzer.ino @@ -52,7 +52,14 @@ void BuzzerSet(uint32_t state) { if (last_state != state) { // Set 50% duty cycle for frequency output // Set 0% (or 100% for inverted PWM) duty cycle which turns off frequency output either way +#ifdef ESP8266 analogWrite(Pin(GPIO_BUZZER), (state) ? Settings->pwm_range / 2 : 0); // set duty cycle for frequency output +#else + int32_t pin = Pin(GPIO_BUZZER); + if (analogAttach(pin, Buzzer.inverted) >= 0) { + analogWritePhase(pin, (state) ? Settings->pwm_range / 2 : 0, 0); + } +#endif last_state = state; } } else { From 04a841421711165888ba5f4f06762c807f82478d Mon Sep 17 00:00:00 2001 From: Marcus Better Date: Wed, 20 Dec 2023 04:00:52 -0500 Subject: [PATCH 028/303] Fix Tuya v2 module compilation (#20272) --- tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino index 78d562546..c3fc0b395 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino @@ -2129,7 +2129,7 @@ void TuyaProcessCommand(unsigned char *buffer){ } */ for (uint8_t cmdsID = 0; cmdsID < sizeof(TuyaExcludeCMDsFromMQTT); cmdsID++) { - if (pgm_read_byte(TuyaExcludeCMDsFromMQTT +cmdsID) == Tuya.buffer[3]) { + if (pgm_read_byte(TuyaExcludeCMDsFromMQTT +cmdsID) == cmd) { isCmdToSuppress = true; break; } From a445c7f23a32a18fa126286bd179aa8f050e6853 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 20 Dec 2023 16:00:27 +0100 Subject: [PATCH 029/303] Fix syslog server warning Fix syslog server warning caused by lack of field and hostname starting with 'z' (#14689) --- CHANGELOG.md | 1 + RELEASENOTES.md | 1 + tasmota/tasmota_support/support.ino | 14 +++++++++++--- tasmota/tasmota_support/support_rtc.ino | 12 ++++++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f1887cb2..a17df4982 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file. - Matter Contact sensor was not triggering any update (#20232) - CVE-2021-36603 Cross Site Scripting (XSS) vulnerability (#12221) - ESP32 piezo ceramic buzzer doesn't buzz (#20118) +- Syslog server warning caused by lack of field and hostname starting with 'z' (#14689) ### Removed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 8953e8264..52c7e1e08 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -130,6 +130,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ### Fixed - CVE-2021-36603 Cross Site Scripting (XSS) vulnerability [#12221](https://github.com/arendst/Tasmota/issues/12221) +- Syslog server warning caused by lack of field and hostname starting with 'z' [#14689](https://github.com/arendst/Tasmota/issues/14689) - ESP32 piezo ceramic buzzer doesn't buzz [#20118](https://github.com/arendst/Tasmota/issues/20118) - Matter Contact sensor was not triggering any update [#20232](https://github.com/arendst/Tasmota/issues/20232) diff --git a/tasmota/tasmota_support/support.ino b/tasmota/tasmota_support/support.ino index 361e4c425..c2e8ba855 100755 --- a/tasmota/tasmota_support/support.ino +++ b/tasmota/tasmota_support/support.ino @@ -2297,8 +2297,9 @@ void SyslogAsync(bool refresh) { char* line; size_t len; while (GetLog(TasmotaGlobal.syslog_level, &index, &line, &len)) { - // 00:00:02.096 HTP: Web server active on wemos5 with IP address 192.168.2.172 - // HTP: Web server active on wemos5 with IP address 192.168.2.172 + // <--- mxtime ---> TAG MSG + // 00:00:02.096-029 HTP: Web server active on wemos5 with IP address 192.168.2.172 + // HTP: Web server active on wemos5 with IP address 192.168.2.172 uint32_t mxtime = strchr(line, ' ') - line +1; // Remove mxtime if (mxtime > 0) { uint32_t current_hash = GetHash(SettingsText(SET_SYSLOG_HOST), strlen(SettingsText(SET_SYSLOG_HOST))); @@ -2321,7 +2322,14 @@ void SyslogAsync(bool refresh) { } char header[64]; - snprintf_P(header, sizeof(header), PSTR("%s ESP-"), NetworkHostname()); + // RFC3164 - BSD syslog protocol - TIMESTAMP HOSTNAME TAG MSG + // = Facility 16 (= local use 0), Severity 6 (= informational) => 16 * 8 + 6 = <134> + // TIMESTAMP = Mmm dd hh:mm:ss + // <134>Jan 1 00:00:02 wemos5 ESP-HTP: server active on wemos5 with IP address 192.168.2.172 + snprintf_P(header, sizeof(header), PSTR("<134>%s %s ESP-"), GetSyslogDate(line).c_str(), NetworkHostname()); + // Legacy format +// snprintf_P(header, sizeof(header), PSTR("%s ESP-"), NetworkHostname()); + char* line_start = line +mxtime; #ifdef ESP8266 // Packets over 1460 bytes are not send diff --git a/tasmota/tasmota_support/support_rtc.ino b/tasmota/tasmota_support/support_rtc.ino index ff93c14d6..95c1af38a 100644 --- a/tasmota/tasmota_support/support_rtc.ino +++ b/tasmota/tasmota_support/support_rtc.ino @@ -109,6 +109,18 @@ String GetBuildDateAndTime(void) { return String(bdt); // 2017-03-07T11:08:02 } +String GetSyslogDate(char* mxtime) { + // Mmm dd hh:mm:ss + // Jan 3 09:23:45 + // Assuming the day hasn't changed yet ;-) + uint32_t month_idx = (RtcTime.month -1) * 3; + char month[4] = { 0 }; + strncpy_P(month, kMonthNamesEnglish + month_idx, 3); + char dt[16]; + snprintf_P(dt, sizeof(dt), PSTR("%s %2d %s"), month, RtcTime.day_of_month, mxtime); + return String(dt); +} + String GetMinuteTime(uint32_t minutes) { char tm[6]; snprintf_P(tm, sizeof(tm), PSTR("%02d:%02d"), minutes / 60, minutes % 60); From 2f824b1976cd4ca3ef47087a387026121f4cffd4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 21 Dec 2023 14:30:49 +0100 Subject: [PATCH 030/303] Document different syslog layouts --- tasmota/tasmota_support/support.ino | 55 +++++++++++++++++++++---- tasmota/tasmota_support/support_rtc.ino | 16 +++++-- 2 files changed, 61 insertions(+), 10 deletions(-) diff --git a/tasmota/tasmota_support/support.ino b/tasmota/tasmota_support/support.ino index c2e8ba855..aca1e11d0 100755 --- a/tasmota/tasmota_support/support.ino +++ b/tasmota/tasmota_support/support.ino @@ -2297,7 +2297,7 @@ void SyslogAsync(bool refresh) { char* line; size_t len; while (GetLog(TasmotaGlobal.syslog_level, &index, &line, &len)) { - // <--- mxtime ---> TAG MSG + // <--- mxtime ---> TAG: <---------------------- MSG ----------------------------> // 00:00:02.096-029 HTP: Web server active on wemos5 with IP address 192.168.2.172 // HTP: Web server active on wemos5 with IP address 192.168.2.172 uint32_t mxtime = strchr(line, ' ') - line +1; // Remove mxtime @@ -2322,14 +2322,55 @@ void SyslogAsync(bool refresh) { } char header[64]; - // RFC3164 - BSD syslog protocol - TIMESTAMP HOSTNAME TAG MSG - // = Facility 16 (= local use 0), Severity 6 (= informational) => 16 * 8 + 6 = <134> - // TIMESTAMP = Mmm dd hh:mm:ss - // <134>Jan 1 00:00:02 wemos5 ESP-HTP: server active on wemos5 with IP address 192.168.2.172 - snprintf_P(header, sizeof(header), PSTR("<134>%s %s ESP-"), GetSyslogDate(line).c_str(), NetworkHostname()); - // Legacy format + /* Legacy format (until v13.3.0.1) - HOSTNAME TAG: MSG + SYSLOG-MSG = wemos5 ESP-HTP: Web server active on wemos5 with IP address 192.168.2.172 + Result = 2023-12-20T13:41:11.825749+01:00 wemos5 ESP-HTP: Web server active on wemos5 with IP address 192.168.2.172 + and below message in syslog if hostname starts with a "z" + 2023-12-17T00:09:52.797782+01:00 domus8 rsyslogd: Uncompression of a message failed with return code -3 - enable debug logging if you need further information. Message ignored. [v8.2302.0] + Notice in both cases the date and time is taken from the syslog server + */ // snprintf_P(header, sizeof(header), PSTR("%s ESP-"), NetworkHostname()); + /* Legacy format - HOSTNAME TAG: MSG + = Facility 16 (= local use 0), Severity 6 (= informational) => 16 * 8 + 6 = <134> + SYSLOG-MSG = <134>wemos5 ESP-HTP: Web server active on wemos5 with IP address 192.168.2.172 + Result = 2023-12-21T11:31:50.378816+01:00 wemos5 ESP-HTP: Web server active on wemos5 with IP address 192.168.2.172 + Notice in both cases the date and time is taken from the syslog server. Uncompression message is gone. + */ + snprintf_P(header, sizeof(header), PSTR("<134>%s ESP-"), NetworkHostname()); +// Result = 2023-12-21T11:31:50.378816+01:00 wemos5 Tasmota HTP: Web server active on wemos5 with IP address 192.168.2.172 +// snprintf_P(header, sizeof(header), PSTR("<134>%s Tasmota "), NetworkHostname()); + + /* RFC3164 - BSD syslog protocol - TIMESTAMP HOSTNAME TAG: MSG + = Facility 16 (= local use 0), Severity 6 (= informational) => 16 * 8 + 6 = <134> + TIMESTAMP = Mmm dd hh:mm:ss + SYSLOG-MSG = <134>Jan 1 00:00:02 wemos5 ESP-HTP: Web server active on wemos5 with IP address 192.168.2.172 + Result = 2023-01-01T00:00:02+01:00 wemos5 ESP-HTP: Web server active on wemos5 with IP address 192.168.2.172 + Notice Year is taken from syslog server. Month, day and time is provided by Tasmota device. No milliseconds + */ +// snprintf_P(header, sizeof(header), PSTR("<134>%s %s ESP-"), GetSyslogDate(line).c_str(), NetworkHostname()); +// Result = 2023-01-01T00:00:02+01:00 wemos5 Tasmota HTP: Web server active on wemos5 with IP address 192.168.2.172 +// snprintf_P(header, sizeof(header), PSTR("<134>%s %s Tasmota "), GetSyslogDate(line).c_str(), NetworkHostname()); + + /* RFC5425 - Syslog protocol - VERSION TIMESTAMP HOSTNAME APP_NAME PROCID STRUCTURED-DATA MSGID MSG + = Facility 16 (= local use 0), Severity 6 (= informational) => 16 * 8 + 6 = <134> + TIMESTAMP = yyyy-mm-ddThh:mm:ss.nnnZ (= UTC) or yyyy-mm-ddThh:mm:ss.nnn-hh:mm (= local with timezone) + APP_NAME = Tasmota + PROCID = - + STRUCTURED-DATA = - + MSGID = - + SYSLOG-MSG = <134>1 2023-01-01T00:00:02.096000+01:00 wemos5 Tasmota - - HTP: Web server active on wemos5 with IP address 192.168.2.172 + Result = 1970-01-01T00:00:02.096000+00:00 wemos5 Tasmota ESP-HTP: Web server active on wemos5 with IP address 192.168.2.172 + Notice date and time is provided by Tasmota device. + */ +// char line_time[13]; +// subStr(line_time, line, " ", 1); // 00:00:02.096-026 +// subStr(line_time, line_time, "-", 1); // 00:00:02.096 +// String systime = GetDate() + line_time + "000" + GetTimeZone(); // 1970-01-01T00:00:02.096000+01:00 +// snprintf_P(header, sizeof(header), PSTR("<134>1 %s %s Tasmota - - ESP-"), systime.c_str(), NetworkHostname()); +// Result = 1970-01-01T00:00:02.096000+00:00 wemos5 Tasmota HTP: Web server active on wemos5 with IP address 192.168.2.172 +// snprintf_P(header, sizeof(header), PSTR("<134>1 %s %s Tasmota - - "), systime.c_str(), NetworkHostname()); + char* line_start = line +mxtime; #ifdef ESP8266 // Packets over 1460 bytes are not send diff --git a/tasmota/tasmota_support/support_rtc.ino b/tasmota/tasmota_support/support_rtc.ino index 95c1af38a..3c6e9c983 100644 --- a/tasmota/tasmota_support/support_rtc.ino +++ b/tasmota/tasmota_support/support_rtc.ino @@ -121,6 +121,13 @@ String GetSyslogDate(char* mxtime) { return String(dt); } +String GetDate(void) { + // yyyy-mm-ddT + char dt[12]; + snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT"), RtcTime.year, RtcTime.month, RtcTime.day_of_month); + return String(dt); +} + String GetMinuteTime(uint32_t minutes) { char tm[6]; snprintf_P(tm, sizeof(tm), PSTR("%02d:%02d"), minutes / 60, minutes % 60); @@ -207,14 +214,17 @@ String GetDateAndTime(uint8_t time_type) { if (DT_LOCAL_MILLIS == time_type) { char ms[10]; snprintf_P(ms, sizeof(ms), PSTR(".%03d"), RtcMillis()); - dt += ms; + dt += ms; // 2017-03-07T11:08:02.123 time_type = DT_LOCAL; } - if (Settings->flag3.time_append_timezone && (DT_LOCAL == time_type)) { // SetOption52 - Append timezone to JSON time + if (DT_UTC == time_type) { + dt += "Z"; // 2017-03-07T11:08:02.123Z + } + else if (Settings->flag3.time_append_timezone && (DT_LOCAL == time_type)) { // SetOption52 - Append timezone to JSON time dt += GetTimeZone(); // 2017-03-07T11:08:02-07:00 } - return dt; // 2017-03-07T11:08:02-07:00 + return dt; // 2017-03-07T11:08:02-07:00 or 2017-03-07T11:08:02.123-07:00 } uint32_t UpTime(void) { From e5abd47c867ad88737e156408f3940f83927b54e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 21 Dec 2023 14:49:37 +0100 Subject: [PATCH 031/303] More syslog explaining --- tasmota/tasmota_support/support.ino | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tasmota/tasmota_support/support.ino b/tasmota/tasmota_support/support.ino index aca1e11d0..adc2e2fb6 100755 --- a/tasmota/tasmota_support/support.ino +++ b/tasmota/tasmota_support/support.ino @@ -2338,36 +2338,44 @@ void SyslogAsync(bool refresh) { Notice in both cases the date and time is taken from the syslog server. Uncompression message is gone. */ snprintf_P(header, sizeof(header), PSTR("<134>%s ESP-"), NetworkHostname()); + +// SYSLOG-MSG = <134>wemos5 Tasmota HTP: Web server active on wemos5 with IP address 192.168.2.172 // Result = 2023-12-21T11:31:50.378816+01:00 wemos5 Tasmota HTP: Web server active on wemos5 with IP address 192.168.2.172 // snprintf_P(header, sizeof(header), PSTR("<134>%s Tasmota "), NetworkHostname()); /* RFC3164 - BSD syslog protocol - TIMESTAMP HOSTNAME TAG: MSG = Facility 16 (= local use 0), Severity 6 (= informational) => 16 * 8 + 6 = <134> TIMESTAMP = Mmm dd hh:mm:ss + TAG: = ESP-HTP: SYSLOG-MSG = <134>Jan 1 00:00:02 wemos5 ESP-HTP: Web server active on wemos5 with IP address 192.168.2.172 Result = 2023-01-01T00:00:02+01:00 wemos5 ESP-HTP: Web server active on wemos5 with IP address 192.168.2.172 Notice Year is taken from syslog server. Month, day and time is provided by Tasmota device. No milliseconds */ // snprintf_P(header, sizeof(header), PSTR("<134>%s %s ESP-"), GetSyslogDate(line).c_str(), NetworkHostname()); + +// SYSLOG-MSG = <134>Jan 1 00:00:02 wemos5 Tasmota HTP: Web server active on wemos5 with IP address 192.168.2.172 // Result = 2023-01-01T00:00:02+01:00 wemos5 Tasmota HTP: Web server active on wemos5 with IP address 192.168.2.172 // snprintf_P(header, sizeof(header), PSTR("<134>%s %s Tasmota "), GetSyslogDate(line).c_str(), NetworkHostname()); /* RFC5425 - Syslog protocol - VERSION TIMESTAMP HOSTNAME APP_NAME PROCID STRUCTURED-DATA MSGID MSG = Facility 16 (= local use 0), Severity 6 (= informational) => 16 * 8 + 6 = <134> - TIMESTAMP = yyyy-mm-ddThh:mm:ss.nnnZ (= UTC) or yyyy-mm-ddThh:mm:ss.nnn-hh:mm (= local with timezone) + VERSION = 1 + TIMESTAMP = yyyy-mm-ddThh:mm:ss.nnnnnn-hh:mm (= local with timezone) APP_NAME = Tasmota PROCID = - STRUCTURED-DATA = - - MSGID = - - SYSLOG-MSG = <134>1 2023-01-01T00:00:02.096000+01:00 wemos5 Tasmota - - HTP: Web server active on wemos5 with IP address 192.168.2.172 + MSGID = ESP-HTP: + SYSLOG-MSG = <134>1 1970-01-01T00:00:02.096000+01:00 wemos5 Tasmota - - ESP-HTP: Web server active on wemos5 with IP address 192.168.2.172 Result = 1970-01-01T00:00:02.096000+00:00 wemos5 Tasmota ESP-HTP: Web server active on wemos5 with IP address 192.168.2.172 Notice date and time is provided by Tasmota device. */ -// char line_time[13]; +// char line_time[mxtime]; // subStr(line_time, line, " ", 1); // 00:00:02.096-026 // subStr(line_time, line_time, "-", 1); // 00:00:02.096 // String systime = GetDate() + line_time + "000" + GetTimeZone(); // 1970-01-01T00:00:02.096000+01:00 // snprintf_P(header, sizeof(header), PSTR("<134>1 %s %s Tasmota - - ESP-"), systime.c_str(), NetworkHostname()); + +// SYSLOG-MSG = <134>1 1970-01-01T00:00:02.096000+01:00 wemos5 Tasmota - - HTP: Web server active on wemos5 with IP address 192.168.2.172 // Result = 1970-01-01T00:00:02.096000+00:00 wemos5 Tasmota HTP: Web server active on wemos5 with IP address 192.168.2.172 // snprintf_P(header, sizeof(header), PSTR("<134>1 %s %s Tasmota - - "), systime.c_str(), NetworkHostname()); From 0e87096bade23a8e82552d45e78bfad965c00365 Mon Sep 17 00:00:00 2001 From: Christian Baars Date: Thu, 21 Dec 2023 20:28:08 +0100 Subject: [PATCH 032/303] allow Berry fast_loop for BLE module (#20281) --- lib/libesp32/berry_tasmota/src/be_MI32_lib.c | 4 +++ .../xdrv_52_3_berry_MI32.ino | 5 ++++ .../tasmota_xsns_sensor/xsns_62_esp32_mi.ino | 30 ++++++++++++------- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/lib/libesp32/berry_tasmota/src/be_MI32_lib.c b/lib/libesp32/berry_tasmota/src/be_MI32_lib.c index 22c0a0bc6..e56ad7ae2 100644 --- a/lib/libesp32/berry_tasmota/src/be_MI32_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_MI32_lib.c @@ -46,6 +46,9 @@ module MI32 (scope: global) { extern int be_BLE_init(bvm *vm); +extern void be_BLE_loop(void); +BE_FUNC_CTYPE_DECLARE(be_BLE_loop, "", ""); + extern void be_BLE_reg_conn_cb(void* function, uint8_t *buffer); BE_FUNC_CTYPE_DECLARE(be_BLE_reg_conn_cb, "", "cc"); @@ -79,6 +82,7 @@ BE_FUNC_CTYPE_DECLARE(be_BLE_adv_block, "", "@(bytes)~[i]"); /* @const_object_info_begin module BLE (scope: global) { init, func(be_BLE_init) + loop, ctype_func(be_BLE_loop) conn_cb, ctype_func(be_BLE_reg_conn_cb) set_svc, ctype_func(be_BLE_set_service) run, ctype_func(be_BLE_run) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_MI32.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_MI32.ino index eb5e9ed33..27a8ed9ba 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_MI32.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_MI32.ino @@ -76,6 +76,7 @@ extern "C" { ** BLE - generic BLE functions ********************************************************************/ extern bool MI32checkBLEinitialization(); + extern void MI32BerryLoop(); extern void MI32setBerryAdvCB(void* function, uint8_t *buffer); extern void MI32setBerryConnCB(void* function, uint8_t *buffer); extern void MI32setBerryServerCB(void* function, uint8_t *buffer); @@ -95,6 +96,10 @@ extern "C" { be_return_nil(vm); } + void be_BLE_loop(void){ + MI32BerryLoop(); + } + void be_BLE_reg_conn_cb(void* function, uint8_t *buffer); void be_BLE_reg_conn_cb(void* function, uint8_t *buffer){ MI32setBerryConnCB(function,buffer); diff --git a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino index c10a559c7..415b2b556 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino @@ -707,6 +707,10 @@ extern "C" { return (MI32.mode.init && Settings->flag5.mi32_enable); } + void MI32BerryLoop(){ + MI32BLELoop(); + } + bool MI32runBerryServer(uint16_t operation, bool response){ MI32.conCtx->operation = operation; MI32.conCtx->response = response; @@ -1861,15 +1865,10 @@ void MI32ParseResponse(char *buf, uint16_t bufsize, uint8_t addr[6], int RSSI) { } /** - * @brief Launch functions from Core 1 to make race conditions less likely - * - */ - -void MI32Every50mSecond(){ - if(MI32.mode.shallTriggerTele){ - MI32.mode.shallTriggerTele = 0; - MI32triggerTele(); - } + * Called automatically every 50 milliseconds or can be triggered from Berry with BLE.loop() - useful from fast_loop +*/ +void MI32BLELoop() +{ if(MI32.mode.triggerBerryAdvCB == 1){ if(MI32.beAdvCB != nullptr){ // AddLogBuffer(LOG_LEVEL_DEBUG,MI32.beAdvBuf,40); @@ -1945,14 +1944,25 @@ void MI32Every50mSecond(){ } } } - if(MI32.infoMsg > 0){ char _message[32]; GetTextIndexed(_message, sizeof(_message), MI32.infoMsg-1, kMI32_BLEInfoMsg); AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s"),_message); MI32.infoMsg = 0; } +} +/** + * @brief Launch functions from Core 1 to make race conditions less likely + * + */ + +void MI32Every50mSecond(){ + if(MI32.mode.shallTriggerTele){ + MI32.mode.shallTriggerTele = 0; + MI32triggerTele(); + } + MI32BLELoop(); } /** From 5988e77f8c79f750d31507b42689798329da6097 Mon Sep 17 00:00:00 2001 From: Bernhard Urban-Forster Date: Fri, 22 Dec 2023 14:21:59 +0100 Subject: [PATCH 033/303] as608: send mqtt message on non-matching finger (#20287) --- tasmota/tasmota_xsns_sensor/xsns_79_as608.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasmota/tasmota_xsns_sensor/xsns_79_as608.ino b/tasmota/tasmota_xsns_sensor/xsns_79_as608.ino index a69f62b08..b2059a90d 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_79_as608.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_79_as608.ino @@ -172,6 +172,8 @@ void As608Loop(void) { p = As608Finger->fingerSearch(); // Match found if (p != FINGERPRINT_OK) { // AddLog(LOG_LEVEL_DEBUG, PSTR("AS6: No matching finger")); + Response_P(PSTR("{\"" D_JSON_FPRINT "\":\"NOMATCH\"}")); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_JSON_FPRINT)); return; } From 4ac93a4d1a6f4d76a1306548eb3754189c24cbe9 Mon Sep 17 00:00:00 2001 From: lis0r <2305601+lis0r@users.noreply.github.com> Date: Fri, 22 Dec 2023 14:31:14 +0000 Subject: [PATCH 034/303] Add support for SJWS01LM BLE flooding sensor (#20288) --- .../xsns_62_esp32_mi_ble.ino | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino index 85e332e3f..c286bad38 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino @@ -376,6 +376,7 @@ struct mi_sensor_t{ uint32_t light:1; // binary light sensor uint32_t scale:1; uint32_t impedance:1; + uint32_t flooding:1; }; uint32_t raw; } feature; @@ -395,6 +396,7 @@ struct mi_sensor_t{ uint32_t PairBtn:1; uint32_t light:1; // binary light sensor uint32_t scale:1; + uint32_t flooding:1; }; uint32_t raw; } eventType; @@ -403,6 +405,7 @@ struct mi_sensor_t{ uint8_t pairing; int8_t light; // binary light sensor - initialise to -1 int16_t Btn; // moved so we can initialise to -1 + int16_t flooding; uint32_t lastTime; uint32_t lux; @@ -486,8 +489,9 @@ void (*const MI32_Commands[])(void) PROGMEM = { #define MI_SCALE_V2 16 #define MI_CGDK2 17 #define AT_BTN 18 +#define MI_SJWS01LM 19 -#define MI_MI32_TYPES 18 //count this manually +#define MI_MI32_TYPES 19 //count this manually const uint16_t kMI32DeviceID[MI_MI32_TYPES]={ 0x0000, // Unkown @@ -507,7 +511,8 @@ const uint16_t kMI32DeviceID[MI_MI32_TYPES]={ 0x181d, // Mi Scale V1 0x181b, // Mi Scale V2 0x066f, // CGDK2 - 0x004e // Avago Tech Bluetooth Buttons (Company Id) + 0x004e, // Avago Tech Bluetooth Buttons (Company Id) + 0x0863 // SJWS01LM }; const char kMI32DeviceType0[] PROGMEM = "Unknown"; @@ -528,7 +533,8 @@ const char kMI32DeviceType14[] PROGMEM ="MISCALEV1"; const char kMI32DeviceType15[] PROGMEM ="MISCALEV2"; const char kMI32DeviceType16[] PROGMEM ="CGDK2"; const char kMI32DeviceType17[] PROGMEM ="ATBTN"; -const char * kMI32DeviceType[] PROGMEM = {kMI32DeviceType0,kMI32DeviceType1,kMI32DeviceType2,kMI32DeviceType3,kMI32DeviceType4,kMI32DeviceType5,kMI32DeviceType6,kMI32DeviceType7,kMI32DeviceType8,kMI32DeviceType9,kMI32DeviceType10,kMI32DeviceType11,kMI32DeviceType12,kMI32DeviceType13,kMI32DeviceType14,kMI32DeviceType15,kMI32DeviceType16,kMI32DeviceType17}; +const char kMI32DeviceType18[] PROGMEM = "SJWS01LM"; +const char * kMI32DeviceType[] PROGMEM = {kMI32DeviceType0,kMI32DeviceType1,kMI32DeviceType2,kMI32DeviceType3,kMI32DeviceType4,kMI32DeviceType5,kMI32DeviceType6,kMI32DeviceType7,kMI32DeviceType8,kMI32DeviceType9,kMI32DeviceType10,kMI32DeviceType11,kMI32DeviceType12,kMI32DeviceType13,kMI32DeviceType14,kMI32DeviceType15,kMI32DeviceType16,kMI32DeviceType17,kMI32DeviceType18}; typedef int BATREAD_FUNCTION(int slot); typedef int UNITWRITE_FUNCTION(int slot, int unit); @@ -1539,6 +1545,7 @@ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter, _newSensor.lux = 0x00ffffff; _newSensor.light = -1; _newSensor.Btn = -1; + _newSensor.flooding = -1; _newSensor.lastCnt = counter; switch (_type) { @@ -1586,6 +1593,11 @@ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter, _newSensor.feature.Btn=1; _newSensor.needkey = KEY_NOT_REQUIRED; break; + case MI_SJWS01LM: + _newSensor.feature.flooding = 1; + _newSensor.feature.Btn = 1; + _newSensor.feature.bat = 1; + break; default: _newSensor.hum=NAN; @@ -2104,6 +2116,14 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){ res = 0; } break; //Flooding 0x1014 1 1 + case 0x1014:{ //'Flooding sensor' - 0=dry, 1=wet SJWS01LM + MIBLEsensors[_slot].flooding = (uint8_t)parsed->payload.data[0]; // just an 8 bit value in a union. + MIBLEsensors[_slot].eventType.flooding = 1; + MI32.mode.shallTriggerTele = 1; + MIBLEsensors[_slot].shallSendMQTT = 1; + MIBLEsensors[_slot].feature.flooding = 1; + } + break; //smoke 0x1015 1 1 //Gas 0x1016 case 0x1017:{ // 'No one moves' @@ -2752,6 +2772,7 @@ const char HTTP_MISCALE_WEIGHT_REMOVED[] PROGMEM = "{s}%s" " Weight removed" "{m const char HTTP_MISCALE_WEIGHT_STABILIZED[] PROGMEM = "{s}%s" " Weight stabilized" "{m}%s{e}"; const char HTTP_MISCALE_IMPEDANCE[] PROGMEM = "{s}%s" " Impedance" "{m}%u{e}"; const char HTTP_MISCALE_IMPEDANCE_STABILIZED[] PROGMEM = "{s}%s" " Impedance stabilized" "{m}%s{e}"; +const char HTTP_SJWS01LM_FLOODING[] PROGMEM = "{s}%s Flooding{m}%u {e}"; //const char HTTP_NEEDKEY[] PROGMEM = "{s}%s Btn); } } + if (p->feature.flooding){ + if(p->eventType.flooding || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate +#ifdef USE_HOME_ASSISTANT + ||(hass_mode==2) +#endif //USE_HOME_ASSISTANT + ){ + ResponseAppend_P(PSTR(",\"Flooding\":%d"),p->flooding); + } + } if(p->eventType.PairBtn && p->pairing){ ResponseAppend_P(PSTR(",\"Pair\":%u"),p->pairing); } @@ -3648,6 +3678,10 @@ void MI32Show(bool json) if (p->feature.Btn){ WSContentSend_PD(HTTP_LASTBUTTON, typeName, p->Btn); } + if (p->feature.flooding) + { + WSContentSend_PD(HTTP_SJWS01LM_FLOODING, typeName, p->flooding); + } if (p->pairing){ WSContentSend_PD(HTTP_PAIRING, typeName); } From fbc827d11d0a6ed03e13dff0b389ac2a5a70676c Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Fri, 22 Dec 2023 18:10:34 +0100 Subject: [PATCH 035/303] Berry fix leds brightness (#20292) --- .../berry_tasmota/src/be_animate_module.c | 23 +- .../berry_tasmota/src/embedded/animate_0.be | 3 + .../{animate_0_core.be => animate_1_core.be} | 12 +- ...ffects.be => animate_2_animate_effects.be} | 7 +- .../src/embedded/animate_9_module.be | 23 +- .../berry_tasmota/src/embedded/leds.be | 26 + .../src/solidify/solidified_animate_0.h | 7 + ...e_0_core.h => solidified_animate_1_core.h} | 902 ++++++----- ...=> solidified_animate_2_animate_effects.h} | 2 +- .../solidify/solidified_animate_9_module.h | 162 +- .../src/solidify/solidified_leds.h | 1375 +++++++++-------- .../berry/animate_demo/animate_demo_pulse.be | 3 +- .../xdrv_52_3_berry_leds.ino | 24 +- 13 files changed, 1401 insertions(+), 1168 deletions(-) create mode 100644 lib/libesp32/berry_tasmota/src/embedded/animate_0.be rename lib/libesp32/berry_tasmota/src/embedded/{animate_0_core.be => animate_1_core.be} (92%) rename lib/libesp32/berry_tasmota/src/embedded/{animate_1_animate_effects.be => animate_2_animate_effects.be} (97%) create mode 100644 lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0.h rename lib/libesp32/berry_tasmota/src/solidify/{solidified_animate_0_core.h => solidified_animate_1_core.h} (83%) rename lib/libesp32/berry_tasmota/src/solidify/{solidified_animate_1_animate_effects.h => solidified_animate_2_animate_effects.h} (99%) diff --git a/lib/libesp32/berry_tasmota/src/be_animate_module.c b/lib/libesp32/berry_tasmota/src/be_animate_module.c index d638cbb79..3c920e6be 100644 --- a/lib/libesp32/berry_tasmota/src/be_animate_module.c +++ b/lib/libesp32/berry_tasmota/src/be_animate_module.c @@ -24,8 +24,8 @@ #include "be_constobj.h" #include "be_mapping.h" -#include "solidify/solidified_animate_0_core.h" -#include "solidify/solidified_animate_1_animate_effects.h" +#include "solidify/solidified_animate_1_core.h" +#include "solidify/solidified_animate_2_animate_effects.h" #include "solidify/solidified_animate_9_module.h" @@ -154,7 +154,6 @@ module animate (scope: global, strings: weak) { TRIANGLE, int(2) SQUARE, int(3) COSINE, int(4) - SINE, int(5) LASTFORM, int(5) PALETTE_STANDARD_TAG, comptr(PALETTE_STANDARD_TAG) @@ -182,14 +181,14 @@ module animate (scope: global, strings: weak) { import animate var p, gradient p = animate.palette.ptr_to_palette(animate.PALETTE_STANDARD_TAG) -assert(p == bytes('40FF000040FFA50040FFFF004000FF00400000FF40FF00FF40FFFFFF00FF0000')) +assert(p == bytes('40FF000040FFA50040FFFF004000FF00400000FF40FF00FF40EE44A500FF0000')) gradient = animate.palette.to_css_gradient(p) -assert(gradient == 'background:linear-gradient(to right,#FF0000 0.0%,#FFA500 14.3%,#FFFF00 28.6%,#00FF00 42.9%,#0000FF 57.1%,#FF00FF 71.4%,#FFFFFF 85.7%,#FF0000 100.0%);') +assert(gradient == 'background:linear-gradient(to right,#FF0000 0.0%,#FFA500 14.3%,#FFFF00 28.6%,#00FF00 42.9%,#0000FF 57.1%,#FF00FF 71.4%,#EE44A5 85.7%,#FF0000 100.0%);') p = animate.palette.ptr_to_palette(animate.PALETTE_STANDARD_VAL) -assert(p == bytes('00FF000024FFA50049FFFF006E00FF00920000FFB7FF00FFDBFFFFFFFFFF0000')) +assert(p == bytes('00FF00002AFFA50055FFFF007F00FF00AA0000FFD4FF00FFFFFF0000')) gradient = animate.palette.to_css_gradient(animate.PALETTE_STANDARD_VAL) -assert(gradient == 'background:linear-gradient(to right,#FF0000 0.0%,#FFA500 14.1%,#FFFF00 28.6%,#00FF00 43.1%,#0000FF 57.3%,#FF00FF 71.8%,#FFFFFF 85.9%,#FF0000 100.0%);') +assert(gradient == 'background:linear-gradient(to right,#FF0000 0.0%,#FFA500 16.5%,#FFFF00 33.3%,#00FF00 49.8%,#0000FF 66.7%,#FF00FF 83.1%,#FF0000 100.0%);') # unit tests @@ -227,16 +226,6 @@ assert(o.animate(6000) == 1000) assert(o.animate(7000) == -1000) assert(o.animate(7100) == -1000) -o = animate.oscillator(-1000, 1000, 6000, animate.SINE) -o.start(1000) -assert(o.animate(1000) == 0) -assert(o.animate(1500) == 500) -assert(o.animate(2000) == 867) -assert(o.animate(2500) == 1000) -assert(o.animate(4000) == 0) -assert(o.animate(5500) == -1000) -assert(o.animate(7000) == 0) - o = animate.oscillator(-1000, 1000, 6000, animate.COSINE) o.start(1000) assert(o.animate(1000) == -1000) diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_0.be b/lib/libesp32/berry_tasmota/src/embedded/animate_0.be new file mode 100644 index 000000000..5c854f6e1 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/embedded/animate_0.be @@ -0,0 +1,3 @@ +# prepare for module `animate` + +global.animate = module('animate') \ No newline at end of file diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be b/lib/libesp32/berry_tasmota/src/embedded/animate_1_core.be similarity index 92% rename from lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be rename to lib/libesp32/berry_tasmota/src/embedded/animate_1_core.be index 747376d9d..bacaf561d 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/animate_0_core.be +++ b/lib/libesp32/berry_tasmota/src/embedded/animate_1_core.be @@ -36,6 +36,7 @@ class Animate_core self.strip = strip if (bri == nil) bri = 50 end self.bri = bri # percentage of brightness 0..100 + self.set_strip_bri() self.running = false self.pixel_count = strip.pixel_count() self.animators = [] @@ -51,6 +52,10 @@ class Animate_core self.set_current() end + def set_strip_bri() + self.strip.set_bri(tasmota.scale_uint(self.bri, 0, 100, 0, 255)) + end + # set this animate.core as the current animator for configuration def set_current() global._cur_anim = self # declare the current animate.core for painters and animators to register @@ -129,6 +134,7 @@ class Animate_core def set_bri(bri) self.bri = bri + self.set_strip_bri() end def get_bri(bri) return self.bri @@ -165,7 +171,10 @@ class Animate_core while i < size(self.painters) layer.fill_pixels(0xFF000000) # fill with transparent color if (self.painters[i].paint(layer)) +# print(f"frame0 {self.frame.tohex()}") +# print(f"layer0 {self.layer.tohex()}") frame.blend_pixels(layer) +# print(f"frame1 {self.frame.tohex()}") end i += 1 end @@ -177,7 +186,7 @@ class Animate_core end self.animate() # now display the frame - self.frame.paste_pixels(self.strip.pixels_buffer(), self.bri, self.strip.gamma) + self.frame.paste_pixels(self.strip.pixels_buffer(), self.strip.get_bri(), self.strip.get_gamma()) self.strip.dirty() self.strip.show() end @@ -192,3 +201,4 @@ class Animate_core tasmota.remove_fast_loop(self.fast_loop_cb) end end +animate.core = global.Animate_core diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_1_animate_effects.be b/lib/libesp32/berry_tasmota/src/embedded/animate_2_animate_effects.be similarity index 97% rename from lib/libesp32/berry_tasmota/src/embedded/animate_1_animate_effects.be rename to lib/libesp32/berry_tasmota/src/embedded/animate_2_animate_effects.be index a059ee85c..d2653db67 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/animate_1_animate_effects.be +++ b/lib/libesp32/berry_tasmota/src/embedded/animate_2_animate_effects.be @@ -19,6 +19,7 @@ class Animate_painter end end +animate.painter = global.Animate_painter ########################################################################################## # @@ -144,8 +145,8 @@ class Animate_pulse : Animate_painter return true end - end +animate.pulse = global.Animate_pulse # # Unit tests @@ -156,8 +157,8 @@ import animate var frame = animate.frame(10) assert(frame.tohex() == '00000000000000000000000000000000000000000000000000000000000000000000000000000000') -var pulse = Animate_pulse(0x00FF00, 3, 2) -pulse.set_index(5) +var pulse = animate.pulse(0x00FF00, 3, 2) +pulse.set_pos(5) pulse.paint(frame) assert(frame.tohex() == '0000000000000000000000000055000000AA000000FF000000FF000000FF000000AA000000550000') diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be b/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be index 46fdcb16f..6991f0fde 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be +++ b/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be @@ -4,15 +4,6 @@ # Animation framework # -animate = module("animate") - -# for solidification -class Leds_frame end - -animate.("()") = Animate_core # make it available as `animate()` -animate.frame = Leds_frame -animate.pulse = Animate_pulse - ################################################################################# # class Animate_palette # @@ -85,7 +76,6 @@ animate.pulse = Animate_pulse # ) # # animate.PALETTE_STANDARD = PALETTE_STANDARD - #@ solidify:Animate_animator,weak class Animate_animator # timing information @@ -134,6 +124,7 @@ class Animate_animator end end +animate.animator = Animate_animator #@ solidify:Animate_palette,weak class Animate_palette : Animate_animator @@ -408,7 +399,6 @@ animate.SAWTOOTH = 1 animate.TRIANGLE = 2 animate.SQUARE = 3 animate.COSINE = 4 -animate.SINE = 5 animate.LASTFOMR = 5 # identify last form #@ solidify:Animate_oscillator,weak @@ -471,7 +461,7 @@ class Animate_oscillator : Animate_animator var past = millis - self.origin if past < 0 past = 0 - millis = self.originally + millis = self.origin end var duration_ms = self.duration_ms var duration_ms_mid # mid point considering duty cycle @@ -506,13 +496,10 @@ class Animate_oscillator : Animate_animator else value = b end - elif (self.form == 4) #-COSINE-# || (self.form == 5) #-SINE-# + elif (self.form == 4) #-COSINE-# # map timing to 0..32767 var angle = tasmota.scale_int(past_with_phase, 0, duration_ms - 1, 0, 32767) - if (self.form == 4) #-COSINE-# - angle -= 8192 - end - var x = tasmota.sine_int(angle) # -4096 .. 4096 + var x = tasmota.sine_int(angle - 8192) # -4096 .. 4096, dephase from cosine to sine value = tasmota.scale_int(x, -4096, 4096, a, b) end self.value = value @@ -526,4 +513,4 @@ class Animate_oscillator : Animate_animator return value end end -animate.oscillator = Animate_oscillator +global.animate.oscillator = Animate_oscillator diff --git a/lib/libesp32/berry_tasmota/src/embedded/leds.be b/lib/libesp32/berry_tasmota/src/embedded/leds.be index 3e20b1c4a..1d9e505ac 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/leds.be +++ b/lib/libesp32/berry_tasmota/src/embedded/leds.be @@ -27,6 +27,7 @@ class Leds_ntv end class Leds : Leds_ntv var gamma # if true, apply gamma (true is default) var leds # number of leds + var bri # implicit brightness for this led strip (0..255, default is 50% = 127) # leds:int = number of leds of the strip # gpio:int (optional) = GPIO for NeoPixel. If not specified, takes the WS2812 gpio # typ:int (optional) = Type of LED, defaults to WS2812 RGB @@ -34,6 +35,7 @@ class Leds : Leds_ntv def init(leds, gpio_phy, typ, rmt) # rmt is optional self.gamma = true # gamma is enabled by default, it should be disabled explicitly if needed self.leds = int(leds) + self.bri = 127 # 50% brightness by default # if no GPIO, abort if gpio_phy == nil @@ -93,6 +95,16 @@ class Leds : Leds_ntv self.show() end + # set bri (0..255) + def set_bri(bri) + if (bri < 0) bri = 0 end + if (bri > 255) bri = 255 end + self.bri = bri + end + def get_bri() + return self.bri + end + def ctor(leds, gpio_phy, typ, rmt) if typ == nil typ = self.WS2812_GRB @@ -136,14 +148,22 @@ class Leds : Leds_ntv return 0 end def clear_to(col, bri) + if (bri == nil) bri = self.bri end self.call_native(9, self.to_gamma(col, bri)) end def set_pixel_color(idx, col, bri) + if (bri == nil) bri = self.bri end self.call_native(10, idx, self.to_gamma(col, bri)) end def get_pixel_color(idx) return self.call_native(11, idx) end + def set_gamma(gamma) + self.gamma = bool(gamma) + end + def get_gamma() + return self.gamma + end # def rotate_left(rot, first, last) # self.call_native(20, rot, first, last) # end @@ -159,6 +179,7 @@ class Leds : Leds_ntv # apply gamma and bri def to_gamma(rgb, bri) + if (bri == nil) bri = self.bri end return self.apply_bri_gamma(rgb, bri, self.gamma) end @@ -216,6 +237,7 @@ class Leds : Leds_ntv return self.leds end def clear_to(col, bri) + if (bri == nil) bri = self.bri end self.strip.call_native(9, self.strip.to_gamma(col, bri), self.offset, self.leds) # var i = 0 # while i < self.leds @@ -224,6 +246,7 @@ class Leds : Leds_ntv # end end def set_pixel_color(idx, col, bri) + if (bri == nil) bri = self.bri end self.strip.set_pixel_color(idx + self.offset, col, bri) end def get_pixel_color(idx) @@ -301,9 +324,11 @@ class Leds : Leds_ntv return self.offset end def clear_to(col, bri) + if (bri == nil) bri = self.bri end self.strip.call_native(9, self.strip.to_gamma(col, bri), self.offset, self.w * self.h) end def set_pixel_color(idx, col, bri) + if (bri == nil) bri = self.bri end self.strip.set_pixel_color(idx + self.offset, col, bri) end def get_pixel_color(idx) @@ -328,6 +353,7 @@ class Leds : Leds_ntv end def set_matrix_pixel_color(x, y, col, bri) + if (bri == nil) bri = self.bri end if self.alternate && x % 2 # reversed line self.strip.set_pixel_color(x * self.w + self.h - y - 1 + self.offset, col, bri) diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0.h new file mode 100644 index 000000000..a0a262928 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0.h @@ -0,0 +1,7 @@ +/* Solidification of animate_0.h */ +/********************************************************************\ +* Generated code, don't edit * +\********************************************************************/ +#include "be_constobj.h" +/********************************************************************/ +/* End of solidification */ diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_core.h similarity index 83% rename from lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h rename to lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_core.h index cc86ccf2e..280b7de5c 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0_core.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_core.h @@ -1,4 +1,4 @@ -/* Solidification of animate_0_core.h */ +/* Solidification of animate_1_core.h */ /********************************************************************\ * Generated code, don't edit * \********************************************************************/ @@ -7,11 +7,11 @@ extern const bclass be_class_Animate_core; /******************************************************************** -** Solidified function: start +** Solidified function: clear ********************************************************************/ -be_local_closure(Animate_core_start, /* name */ +be_local_closure(Animate_core_clear, /* name */ be_nested_proto( - 6, /* nstack */ + 3, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -19,110 +19,62 @@ be_local_closure(Animate_core_start, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(running), - /* K1 */ be_nested_str_weak(animators), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(start), - /* K4 */ be_const_int(1), - /* K5 */ be_nested_str_weak(fast_loop_next), - /* K6 */ be_nested_str_weak(tasmota), - /* K7 */ be_nested_str_weak(add_fast_loop), - /* K8 */ be_nested_str_weak(fast_loop_cb), - }), - be_str_weak(start), - &be_const_str_solidified, - ( &(const binstruction[20]) { /* code */ - 0x50040200, // 0000 LDBOOL R1 1 0 - 0x90020001, // 0001 SETMBR R0 K0 R1 - 0x88040101, // 0002 GETMBR R1 R0 K1 - 0x58080002, // 0003 LDCONST R2 K2 - 0x600C000C, // 0004 GETGBL R3 G12 - 0x5C100200, // 0005 MOVE R4 R1 - 0x7C0C0200, // 0006 CALL R3 1 - 0x140C0403, // 0007 LT R3 R2 R3 - 0x780E0004, // 0008 JMPF R3 #000E - 0x940C0202, // 0009 GETIDX R3 R1 R2 - 0x8C0C0703, // 000A GETMET R3 R3 K3 - 0x7C0C0200, // 000B CALL R3 1 - 0x00080504, // 000C ADD R2 R2 K4 - 0x7001FFF5, // 000D JMP #0004 - 0x90020B02, // 000E SETMBR R0 K5 K2 - 0xB80E0C00, // 000F GETNGBL R3 K6 - 0x8C0C0707, // 0010 GETMET R3 R3 K7 - 0x88140108, // 0011 GETMBR R5 R0 K8 - 0x7C0C0400, // 0012 CALL R3 2 - 0x80000000, // 0013 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: remove -********************************************************************/ -be_local_closure(Animate_core_remove, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(clear), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(remove_fast_loop), - /* K3 */ be_nested_str_weak(fast_loop_cb), - }), - be_str_weak(remove), - &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0xB8060200, // 0002 GETNGBL R1 K1 - 0x8C040302, // 0003 GETMET R1 R1 K2 - 0x880C0103, // 0004 GETMBR R3 R0 K3 - 0x7C040400, // 0005 CALL R1 2 - 0x80000000, // 0006 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: add_background_animator -********************************************************************/ -be_local_closure(Animate_core_add_background_animator, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(set_cb), - /* K1 */ be_nested_str_weak(set_back_color), - /* K2 */ be_nested_str_weak(add_animator), + /* K0 */ be_nested_str_weak(stop), + /* K1 */ be_nested_str_weak(strip), + /* K2 */ be_nested_str_weak(clear), }), - be_str_weak(add_background_animator), + be_str_weak(clear), &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x8C080300, // 0000 GETMET R2 R1 K0 - 0x5C100000, // 0001 MOVE R4 R0 - 0x88140101, // 0002 GETMBR R5 R0 K1 - 0x7C080600, // 0003 CALL R2 3 - 0x8C080102, // 0004 GETMET R2 R0 K2 - 0x5C100200, // 0005 MOVE R4 R1 - 0x7C080400, // 0006 CALL R2 2 - 0x80000000, // 0007 RET 0 + ( &(const binstruction[ 6]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x88040101, // 0002 GETMBR R1 R0 K1 + 0x8C040302, // 0003 GETMET R1 R1 K2 + 0x7C040200, // 0004 CALL R1 1 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_strip_bri +********************************************************************/ +be_local_closure(Animate_core_set_strip_bri, /* name */ + be_nested_proto( + 10, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(strip), + /* K1 */ be_nested_str_weak(set_bri), + /* K2 */ be_nested_str_weak(tasmota), + /* K3 */ be_nested_str_weak(scale_uint), + /* K4 */ be_nested_str_weak(bri), + /* K5 */ be_const_int(0), + }), + be_str_weak(set_strip_bri), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0xB80E0400, // 0002 GETNGBL R3 K2 + 0x8C0C0703, // 0003 GETMET R3 R3 K3 + 0x88140104, // 0004 GETMBR R5 R0 K4 + 0x58180005, // 0005 LDCONST R6 K5 + 0x541E0063, // 0006 LDINT R7 100 + 0x58200005, // 0007 LDCONST R8 K5 + 0x542600FE, // 0008 LDINT R9 255 + 0x7C0C0C00, // 0009 CALL R3 6 + 0x7C040400, // 000A CALL R1 2 + 0x80000000, // 000B RET 0 }) ) ); @@ -170,102 +122,6 @@ be_local_closure(Animate_core_remove_painter, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: add_animator -********************************************************************/ -be_local_closure(Animate_core_add_animator, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(animators), - /* K1 */ be_nested_str_weak(find), - /* K2 */ be_nested_str_weak(push), - }), - be_str_weak(add_animator), - &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x4C0C0000, // 0004 LDNIL R3 - 0x1C080403, // 0005 EQ R2 R2 R3 - 0x780A0003, // 0006 JMPF R2 #000B - 0x88080100, // 0007 GETMBR R2 R0 K0 - 0x8C080502, // 0008 GETMET R2 R2 K2 - 0x5C100200, // 0009 MOVE R4 R1 - 0x7C080400, // 000A CALL R2 2 - 0x80000000, // 000B RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: animate -********************************************************************/ -be_local_closure(Animate_core_animate, /* name */ - be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(animate), - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: clear -********************************************************************/ -be_local_closure(Animate_core_clear, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(stop), - /* K1 */ be_nested_str_weak(strip), - /* K2 */ be_nested_str_weak(clear), - }), - be_str_weak(clear), - &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0x88040101, // 0002 GETMBR R1 R0 K1 - 0x8C040302, // 0003 GETMET R1 R1 K2 - 0x7C040200, // 0004 CALL R1 1 - 0x80000000, // 0005 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: stop ********************************************************************/ @@ -317,6 +173,63 @@ be_local_closure(Animate_core_stop, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: get_bri +********************************************************************/ +be_local_closure(Animate_core_get_bri, /* name */ + be_nested_proto( + 3, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(bri), + }), + be_str_weak(get_bri), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x80040400, // 0001 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_bri +********************************************************************/ +be_local_closure(Animate_core_set_bri, /* name */ + be_nested_proto( + 4, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(bri), + /* K1 */ be_nested_str_weak(set_strip_bri), + }), + be_str_weak(set_bri), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x8C080101, // 0001 GETMET R2 R0 K1 + 0x7C080200, // 0002 CALL R2 1 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: add_painter ********************************************************************/ @@ -356,138 +269,12 @@ be_local_closure(Animate_core_add_painter, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: set_bri -********************************************************************/ -be_local_closure(Animate_core_set_bri, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(bri), - }), - be_str_weak(set_bri), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_current -********************************************************************/ -be_local_closure(Animate_core_set_current, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(global), - /* K1 */ be_nested_str_weak(_cur_anim), - }), - be_str_weak(set_current), - &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x90060200, // 0001 SETMBR R1 K1 R0 - 0x80000000, // 0002 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: remove_animator -********************************************************************/ -be_local_closure(Animate_core_remove_animator, /* name */ - be_nested_proto( - 8, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(animators), - /* K1 */ be_nested_str_weak(remove), - /* K2 */ be_nested_str_weak(find), - /* K3 */ be_nested_str_weak(clear), - }), - be_str_weak(remove_animator), - &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x200C0203, // 0002 NE R3 R1 R3 - 0x780E0005, // 0003 JMPF R3 #000A - 0x8C0C0501, // 0004 GETMET R3 R2 K1 - 0x8C140502, // 0005 GETMET R5 R2 K2 - 0x5C1C0200, // 0006 MOVE R7 R1 - 0x7C140400, // 0007 CALL R5 2 - 0x7C0C0400, // 0008 CALL R3 2 - 0x70020001, // 0009 JMP #000C - 0x8C0C0503, // 000A GETMET R3 R2 K3 - 0x7C0C0200, // 000B CALL R3 1 - 0x80000000, // 000C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_cb -********************************************************************/ -be_local_closure(Animate_core_set_cb, /* name */ - be_nested_proto( - 3, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(obj), - /* K1 */ be_nested_str_weak(mth), - }), - be_str_weak(set_cb), - &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x80000000, // 0002 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: fast_loop ********************************************************************/ be_local_closure(Animate_core_fast_loop, /* name */ be_nested_proto( - 12, /* nstack */ + 13, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -520,25 +307,25 @@ be_local_closure(Animate_core_fast_loop, /* name */ /* K21 */ be_nested_str_weak(mth), /* K22 */ be_nested_str_weak(paste_pixels), /* K23 */ be_nested_str_weak(pixels_buffer), - /* K24 */ be_nested_str_weak(bri), - /* K25 */ be_nested_str_weak(gamma), + /* K24 */ be_nested_str_weak(get_bri), + /* K25 */ be_nested_str_weak(get_gamma), /* K26 */ be_nested_str_weak(dirty), /* K27 */ be_nested_str_weak(show), }), be_str_weak(fast_loop), &be_const_str_solidified, - ( &(const binstruction[81]) { /* code */ + ( &(const binstruction[84]) { /* code */ 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x7806004D, // 0001 JMPF R1 #0050 + 0x78060050, // 0001 JMPF R1 #0053 0xB8060200, // 0002 GETNGBL R1 K1 0x8C040302, // 0003 GETMET R1 R1 K2 0x880C0103, // 0004 GETMBR R3 R0 K3 0x7C040400, // 0005 CALL R1 2 - 0x78060048, // 0006 JMPF R1 #0050 + 0x7806004B, // 0006 JMPF R1 #0053 0x88040104, // 0007 GETMBR R1 R0 K4 0x8C040305, // 0008 GETMET R1 R1 K5 0x7C040200, // 0009 CALL R1 1 - 0x78060044, // 000A JMPF R1 #0050 + 0x78060047, // 000A JMPF R1 #0053 0x88040106, // 000B GETMBR R1 R0 K6 0x8C040307, // 000C GETMET R1 R1 K7 0x880C0108, // 000D GETMBR R3 R0 K8 @@ -598,17 +385,20 @@ be_local_closure(Animate_core_fast_loop, /* name */ 0x88240104, // 0043 GETMBR R9 R0 K4 0x8C241317, // 0044 GETMET R9 R9 K23 0x7C240200, // 0045 CALL R9 1 - 0x88280118, // 0046 GETMBR R10 R0 K24 - 0x882C0104, // 0047 GETMBR R11 R0 K4 - 0x882C1719, // 0048 GETMBR R11 R11 K25 - 0x7C1C0800, // 0049 CALL R7 4 - 0x881C0104, // 004A GETMBR R7 R0 K4 - 0x8C1C0F1A, // 004B GETMET R7 R7 K26 - 0x7C1C0200, // 004C CALL R7 1 + 0x88280104, // 0046 GETMBR R10 R0 K4 + 0x8C281518, // 0047 GETMET R10 R10 K24 + 0x7C280200, // 0048 CALL R10 1 + 0x882C0104, // 0049 GETMBR R11 R0 K4 + 0x8C2C1719, // 004A GETMET R11 R11 K25 + 0x7C2C0200, // 004B CALL R11 1 + 0x7C1C0800, // 004C CALL R7 4 0x881C0104, // 004D GETMBR R7 R0 K4 - 0x8C1C0F1B, // 004E GETMET R7 R7 K27 + 0x8C1C0F1A, // 004E GETMET R7 R7 K26 0x7C1C0200, // 004F CALL R7 1 - 0x80000000, // 0050 RET 0 + 0x881C0104, // 0050 GETMBR R7 R0 K4 + 0x8C1C0F1B, // 0051 GETMET R7 R7 K27 + 0x7C1C0200, // 0052 CALL R7 1 + 0x80000000, // 0053 RET 0 }) ) ); @@ -616,11 +406,11 @@ be_local_closure(Animate_core_fast_loop, /* name */ /******************************************************************** -** Solidified function: set_back_color +** Solidified function: remove_animator ********************************************************************/ -be_local_closure(Animate_core_set_back_color, /* name */ +be_local_closure(Animate_core_remove_animator, /* name */ be_nested_proto( - 2, /* nstack */ + 8, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -628,14 +418,81 @@ be_local_closure(Animate_core_set_back_color, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(back_color), + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(animators), + /* K1 */ be_nested_str_weak(remove), + /* K2 */ be_nested_str_weak(find), + /* K3 */ be_nested_str_weak(clear), }), - be_str_weak(set_back_color), + be_str_weak(remove_animator), &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 + ( &(const binstruction[13]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x200C0203, // 0002 NE R3 R1 R3 + 0x780E0005, // 0003 JMPF R3 #000A + 0x8C0C0501, // 0004 GETMET R3 R2 K1 + 0x8C140502, // 0005 GETMET R5 R2 K2 + 0x5C1C0200, // 0006 MOVE R7 R1 + 0x7C140400, // 0007 CALL R5 2 + 0x7C0C0400, // 0008 CALL R3 2 + 0x70020001, // 0009 JMP #000C + 0x8C0C0503, // 000A GETMET R3 R2 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: animate +********************************************************************/ +be_local_closure(Animate_core_animate, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(animate), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_current +********************************************************************/ +be_local_closure(Animate_core_set_current, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(global), + /* K1 */ be_nested_str_weak(_cur_anim), + }), + be_str_weak(set_current), + &be_const_str_solidified, + ( &(const binstruction[ 3]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x90060200, // 0001 SETMBR R1 K1 R0 + 0x80000000, // 0002 RET 0 }) ) ); @@ -679,25 +536,26 @@ be_local_closure(Animate_core_init, /* name */ ), }), 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ + ( &(const bvalue[15]) { /* constants */ /* K0 */ be_nested_str_weak(animate), /* K1 */ be_nested_str_weak(strip), /* K2 */ be_nested_str_weak(bri), - /* K3 */ be_nested_str_weak(running), - /* K4 */ be_nested_str_weak(pixel_count), - /* K5 */ be_nested_str_weak(animators), - /* K6 */ be_nested_str_weak(painters), - /* K7 */ be_nested_str_weak(clear), - /* K8 */ be_nested_str_weak(frame), - /* K9 */ be_nested_str_weak(layer), - /* K10 */ be_nested_str_weak(fast_loop_cb), - /* K11 */ be_nested_str_weak(back_color), - /* K12 */ be_const_int(0), - /* K13 */ be_nested_str_weak(set_current), + /* K3 */ be_nested_str_weak(set_strip_bri), + /* K4 */ be_nested_str_weak(running), + /* K5 */ be_nested_str_weak(pixel_count), + /* K6 */ be_nested_str_weak(animators), + /* K7 */ be_nested_str_weak(painters), + /* K8 */ be_nested_str_weak(clear), + /* K9 */ be_nested_str_weak(frame), + /* K10 */ be_nested_str_weak(layer), + /* K11 */ be_nested_str_weak(fast_loop_cb), + /* K12 */ be_nested_str_weak(back_color), + /* K13 */ be_const_int(0), + /* K14 */ be_nested_str_weak(set_current), }), be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[35]) { /* code */ + ( &(const binstruction[37]) { /* code */ 0xA40E0000, // 0000 IMPORT R3 K0 0x90020201, // 0001 SETMBR R0 K1 R1 0x4C100000, // 0002 LDNIL R4 @@ -705,34 +563,36 @@ be_local_closure(Animate_core_init, /* name */ 0x78120000, // 0004 JMPF R4 #0006 0x540A0031, // 0005 LDINT R2 50 0x90020402, // 0006 SETMBR R0 K2 R2 - 0x50100000, // 0007 LDBOOL R4 0 0 - 0x90020604, // 0008 SETMBR R0 K3 R4 - 0x8C100304, // 0009 GETMET R4 R1 K4 - 0x7C100200, // 000A CALL R4 1 - 0x90020804, // 000B SETMBR R0 K4 R4 - 0x60100012, // 000C GETGBL R4 G18 - 0x7C100000, // 000D CALL R4 0 - 0x90020A04, // 000E SETMBR R0 K5 R4 - 0x60100012, // 000F GETGBL R4 G18 - 0x7C100000, // 0010 CALL R4 0 - 0x90020C04, // 0011 SETMBR R0 K6 R4 - 0x8C100107, // 0012 GETMET R4 R0 K7 - 0x7C100200, // 0013 CALL R4 1 - 0x8C100708, // 0014 GETMET R4 R3 K8 - 0x88180104, // 0015 GETMBR R6 R0 K4 - 0x7C100400, // 0016 CALL R4 2 - 0x90021004, // 0017 SETMBR R0 K8 R4 - 0x8C100708, // 0018 GETMET R4 R3 K8 - 0x88180104, // 0019 GETMBR R6 R0 K4 - 0x7C100400, // 001A CALL R4 2 - 0x90021204, // 001B SETMBR R0 K9 R4 - 0x84100000, // 001C CLOSURE R4 P0 + 0x8C100103, // 0007 GETMET R4 R0 K3 + 0x7C100200, // 0008 CALL R4 1 + 0x50100000, // 0009 LDBOOL R4 0 0 + 0x90020804, // 000A SETMBR R0 K4 R4 + 0x8C100305, // 000B GETMET R4 R1 K5 + 0x7C100200, // 000C CALL R4 1 + 0x90020A04, // 000D SETMBR R0 K5 R4 + 0x60100012, // 000E GETGBL R4 G18 + 0x7C100000, // 000F CALL R4 0 + 0x90020C04, // 0010 SETMBR R0 K6 R4 + 0x60100012, // 0011 GETGBL R4 G18 + 0x7C100000, // 0012 CALL R4 0 + 0x90020E04, // 0013 SETMBR R0 K7 R4 + 0x8C100108, // 0014 GETMET R4 R0 K8 + 0x7C100200, // 0015 CALL R4 1 + 0x8C100709, // 0016 GETMET R4 R3 K9 + 0x88180105, // 0017 GETMBR R6 R0 K5 + 0x7C100400, // 0018 CALL R4 2 + 0x90021204, // 0019 SETMBR R0 K9 R4 + 0x8C100709, // 001A GETMET R4 R3 K9 + 0x88180105, // 001B GETMBR R6 R0 K5 + 0x7C100400, // 001C CALL R4 2 0x90021404, // 001D SETMBR R0 K10 R4 - 0x9002170C, // 001E SETMBR R0 K11 K12 - 0x8C10010D, // 001F GETMET R4 R0 K13 - 0x7C100200, // 0020 CALL R4 1 - 0xA0000000, // 0021 CLOSE R0 - 0x80000000, // 0022 RET 0 + 0x84100000, // 001E CLOSURE R4 P0 + 0x90021604, // 001F SETMBR R0 K11 R4 + 0x9002190D, // 0020 SETMBR R0 K12 K13 + 0x8C10010E, // 0021 GETMET R4 R0 K14 + 0x7C100200, // 0022 CALL R4 1 + 0xA0000000, // 0023 CLOSE R0 + 0x80000000, // 0024 RET 0 }) ) ); @@ -740,11 +600,40 @@ be_local_closure(Animate_core_init, /* name */ /******************************************************************** -** Solidified function: get_bri +** Solidified function: set_cb ********************************************************************/ -be_local_closure(Animate_core_get_bri, /* name */ +be_local_closure(Animate_core_set_cb, /* name */ be_nested_proto( 3, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(obj), + /* K1 */ be_nested_str_weak(mth), + }), + be_str_weak(set_cb), + &be_const_str_solidified, + ( &(const binstruction[ 3]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_back_color +********************************************************************/ +be_local_closure(Animate_core_set_back_color, /* name */ + be_nested_proto( + 2, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -753,13 +642,175 @@ be_local_closure(Animate_core_get_bri, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(bri), + /* K0 */ be_nested_str_weak(back_color), }), - be_str_weak(get_bri), + be_str_weak(set_back_color), &be_const_str_solidified, ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_background_animator +********************************************************************/ +be_local_closure(Animate_core_add_background_animator, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(set_cb), + /* K1 */ be_nested_str_weak(set_back_color), + /* K2 */ be_nested_str_weak(add_animator), + }), + be_str_weak(add_background_animator), + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x8C080300, // 0000 GETMET R2 R1 K0 + 0x5C100000, // 0001 MOVE R4 R0 + 0x88140101, // 0002 GETMBR R5 R0 K1 + 0x7C080600, // 0003 CALL R2 3 + 0x8C080102, // 0004 GETMET R2 R0 K2 + 0x5C100200, // 0005 MOVE R4 R1 + 0x7C080400, // 0006 CALL R2 2 + 0x80000000, // 0007 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_animator +********************************************************************/ +be_local_closure(Animate_core_add_animator, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(animators), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(push), + }), + be_str_weak(add_animator), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x80040400, // 0001 RET 1 R2 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x4C0C0000, // 0004 LDNIL R3 + 0x1C080403, // 0005 EQ R2 R2 R3 + 0x780A0003, // 0006 JMPF R2 #000B + 0x88080100, // 0007 GETMBR R2 R0 K0 + 0x8C080502, // 0008 GETMET R2 R2 K2 + 0x5C100200, // 0009 MOVE R4 R1 + 0x7C080400, // 000A CALL R2 2 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: remove +********************************************************************/ +be_local_closure(Animate_core_remove, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(clear), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(remove_fast_loop), + /* K3 */ be_nested_str_weak(fast_loop_cb), + }), + be_str_weak(remove), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0xB8060200, // 0002 GETNGBL R1 K1 + 0x8C040302, // 0003 GETMET R1 R1 K2 + 0x880C0103, // 0004 GETMBR R3 R0 K3 + 0x7C040400, // 0005 CALL R1 2 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start +********************************************************************/ +be_local_closure(Animate_core_start, /* name */ + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(running), + /* K1 */ be_nested_str_weak(animators), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(start), + /* K4 */ be_const_int(1), + /* K5 */ be_nested_str_weak(fast_loop_next), + /* K6 */ be_nested_str_weak(tasmota), + /* K7 */ be_nested_str_weak(add_fast_loop), + /* K8 */ be_nested_str_weak(fast_loop_cb), + }), + be_str_weak(start), + &be_const_str_solidified, + ( &(const binstruction[20]) { /* code */ + 0x50040200, // 0000 LDBOOL R1 1 0 + 0x90020001, // 0001 SETMBR R0 K0 R1 + 0x88040101, // 0002 GETMBR R1 R0 K1 + 0x58080002, // 0003 LDCONST R2 K2 + 0x600C000C, // 0004 GETGBL R3 G12 + 0x5C100200, // 0005 MOVE R4 R1 + 0x7C0C0200, // 0006 CALL R3 1 + 0x140C0403, // 0007 LT R3 R2 R3 + 0x780E0004, // 0008 JMPF R3 #000E + 0x940C0202, // 0009 GETIDX R3 R1 R2 + 0x8C0C0703, // 000A GETMET R3 R3 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0x00080504, // 000C ADD R2 R2 K4 + 0x7001FFF5, // 000D JMP #0004 + 0x90020B02, // 000E SETMBR R0 K5 K2 + 0xB80E0C00, // 000F GETNGBL R3 K6 + 0x8C0C0707, // 0010 GETMET R3 R3 K7 + 0x88140108, // 0011 GETMBR R5 R0 K8 + 0x7C0C0400, // 0012 CALL R3 2 + 0x80000000, // 0013 RET 0 }) ) ); @@ -772,39 +823,40 @@ be_local_closure(Animate_core_get_bri, /* name */ be_local_class(Animate_core, 13, NULL, - be_nested_map(31, + be_nested_map(32, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(get_bri, -1), be_const_closure(Animate_core_get_bri_closure) }, - { be_const_key_weak(remove, -1), be_const_closure(Animate_core_remove_closure) }, - { be_const_key_weak(painters, -1), be_const_var(5) }, - { be_const_key_weak(fast_loop_cb, -1), be_const_var(6) }, - { be_const_key_weak(start, 6), be_const_closure(Animate_core_start_closure) }, - { be_const_key_weak(add_background_animator, -1), be_const_closure(Animate_core_add_background_animator_closure) }, - { be_const_key_weak(set_back_color, 30), be_const_closure(Animate_core_set_back_color_closure) }, - { be_const_key_weak(add_animator, -1), be_const_closure(Animate_core_add_animator_closure) }, - { be_const_key_weak(strip, 3), be_const_var(0) }, - { be_const_key_weak(animate, 14), be_const_closure(Animate_core_animate_closure) }, - { be_const_key_weak(clear, 0), be_const_closure(Animate_core_clear_closure) }, - { be_const_key_weak(stop, -1), be_const_closure(Animate_core_stop_closure) }, - { be_const_key_weak(remove_painter, 28), be_const_closure(Animate_core_remove_painter_closure) }, - { be_const_key_weak(fast_loop_next, 21), be_const_var(7) }, + { be_const_key_weak(set_strip_bri, -1), be_const_closure(Animate_core_set_strip_bri_closure) }, { be_const_key_weak(animators, -1), be_const_var(4) }, - { be_const_key_weak(add_painter, -1), be_const_closure(Animate_core_add_painter_closure) }, - { be_const_key_weak(set_bri, -1), be_const_closure(Animate_core_set_bri_closure) }, - { be_const_key_weak(frame, -1), be_const_var(10) }, - { be_const_key_weak(mth, 26), be_const_var(9) }, - { be_const_key_weak(back_color, -1), be_const_var(12) }, - { be_const_key_weak(set_current, -1), be_const_closure(Animate_core_set_current_closure) }, - { be_const_key_weak(bri, -1), be_const_var(2) }, - { be_const_key_weak(fast_loop, -1), be_const_closure(Animate_core_fast_loop_closure) }, - { be_const_key_weak(layer, -1), be_const_var(11) }, - { be_const_key_weak(set_cb, 23), be_const_closure(Animate_core_set_cb_closure) }, - { be_const_key_weak(remove_animator, 22), be_const_closure(Animate_core_remove_animator_closure) }, + { be_const_key_weak(clear, 0), be_const_closure(Animate_core_clear_closure) }, + { be_const_key_weak(remove, -1), be_const_closure(Animate_core_remove_closure) }, + { be_const_key_weak(mth, -1), be_const_var(9) }, + { be_const_key_weak(stop, 1), be_const_closure(Animate_core_stop_closure) }, + { be_const_key_weak(fast_loop_cb, 30), be_const_var(6) }, + { be_const_key_weak(get_bri, -1), be_const_closure(Animate_core_get_bri_closure) }, + { be_const_key_weak(add_animator, -1), be_const_closure(Animate_core_add_animator_closure) }, + { be_const_key_weak(add_background_animator, -1), be_const_closure(Animate_core_add_background_animator_closure) }, + { be_const_key_weak(fast_loop_next, -1), be_const_var(7) }, + { be_const_key_weak(remove_animator, -1), be_const_closure(Animate_core_remove_animator_closure) }, + { be_const_key_weak(add_painter, 28), be_const_closure(Animate_core_add_painter_closure) }, { be_const_key_weak(FAST_LOOP_MIN, -1), be_const_int(20) }, - { be_const_key_weak(pixel_count, -1), be_const_var(1) }, - { be_const_key_weak(obj, -1), be_const_var(8) }, + { be_const_key_weak(fast_loop, -1), be_const_closure(Animate_core_fast_loop_closure) }, + { be_const_key_weak(set_back_color, 11), be_const_closure(Animate_core_set_back_color_closure) }, + { be_const_key_weak(animate, 8), be_const_closure(Animate_core_animate_closure) }, + { be_const_key_weak(strip, 24), be_const_var(0) }, + { be_const_key_weak(layer, -1), be_const_var(11) }, { be_const_key_weak(init, -1), be_const_closure(Animate_core_init_closure) }, + { be_const_key_weak(bri, -1), be_const_var(2) }, + { be_const_key_weak(set_cb, 13), be_const_closure(Animate_core_set_cb_closure) }, + { be_const_key_weak(back_color, 18), be_const_var(12) }, + { be_const_key_weak(pixel_count, 15), be_const_var(1) }, + { be_const_key_weak(set_current, -1), be_const_closure(Animate_core_set_current_closure) }, + { be_const_key_weak(painters, -1), be_const_var(5) }, + { be_const_key_weak(obj, 10), be_const_var(8) }, + { be_const_key_weak(set_bri, 9), be_const_closure(Animate_core_set_bri_closure) }, { be_const_key_weak(running, -1), be_const_var(3) }, + { be_const_key_weak(remove_painter, 3), be_const_closure(Animate_core_remove_painter_closure) }, + { be_const_key_weak(frame, -1), be_const_var(10) }, + { be_const_key_weak(start, -1), be_const_closure(Animate_core_start_closure) }, })), be_str_weak(Animate_core) ); diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_animate_effects.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_2_animate_effects.h similarity index 99% rename from lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_animate_effects.h rename to lib/libesp32/berry_tasmota/src/solidify/solidified_animate_2_animate_effects.h index 21bcdeb19..360e3d2d8 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_animate_effects.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_2_animate_effects.h @@ -1,4 +1,4 @@ -/* Solidification of animate_1_animate_effects.h */ +/* Solidification of animate_2_animate_effects.h */ /********************************************************************\ * Generated code, don't edit * \********************************************************************/ diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h index 7f12ffcca..e64059188 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h @@ -1384,32 +1384,31 @@ be_local_closure(Animate_oscillator_animate, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[21]) { /* constants */ + ( &(const bvalue[20]) { /* constants */ /* K0 */ be_nested_str_weak(duration_ms), /* K1 */ be_nested_str_weak(tasmota), /* K2 */ be_nested_str_weak(millis), /* K3 */ be_nested_str_weak(origin), /* K4 */ be_const_int(0), - /* K5 */ be_nested_str_weak(originally), - /* K6 */ be_nested_str_weak(scale_uint), - /* K7 */ be_nested_str_weak(duty_cycle), - /* K8 */ be_nested_str_weak(beat), - /* K9 */ be_nested_str_weak(a), - /* K10 */ be_nested_str_weak(b), - /* K11 */ be_nested_str_weak(value), - /* K12 */ be_nested_str_weak(phase), - /* K13 */ be_nested_str_weak(form), - /* K14 */ be_const_int(1), - /* K15 */ be_nested_str_weak(scale_int), - /* K16 */ be_const_int(2), - /* K17 */ be_const_int(3), - /* K18 */ be_nested_str_weak(sine_int), - /* K19 */ be_nested_str_weak(obj), - /* K20 */ be_nested_str_weak(mth), + /* K5 */ be_nested_str_weak(scale_uint), + /* K6 */ be_nested_str_weak(duty_cycle), + /* K7 */ be_nested_str_weak(beat), + /* K8 */ be_nested_str_weak(a), + /* K9 */ be_nested_str_weak(b), + /* K10 */ be_nested_str_weak(value), + /* K11 */ be_nested_str_weak(phase), + /* K12 */ be_nested_str_weak(form), + /* K13 */ be_const_int(1), + /* K14 */ be_nested_str_weak(scale_int), + /* K15 */ be_const_int(2), + /* K16 */ be_const_int(3), + /* K17 */ be_nested_str_weak(sine_int), + /* K18 */ be_nested_str_weak(obj), + /* K19 */ be_nested_str_weak(mth), }), be_str_weak(animate), &be_const_str_solidified, - ( &(const binstruction[150]) { /* code */ + ( &(const binstruction[141]) { /* code */ 0x88080100, // 0000 GETMBR R2 R0 K0 0x4C0C0000, // 0001 LDNIL R3 0x1C080403, // 0002 EQ R2 R2 R3 @@ -1427,12 +1426,12 @@ be_local_closure(Animate_oscillator_animate, /* name */ 0x140C0504, // 000E LT R3 R2 K4 0x780E0001, // 000F JMPF R3 #0012 0x58080004, // 0010 LDCONST R2 K4 - 0x88040105, // 0011 GETMBR R1 R0 K5 + 0x88040103, // 0011 GETMBR R1 R0 K3 0x880C0100, // 0012 GETMBR R3 R0 K0 0x4C100000, // 0013 LDNIL R4 0xB8160200, // 0014 GETNGBL R5 K1 - 0x8C140B06, // 0015 GETMET R5 R5 K6 - 0x881C0107, // 0016 GETMBR R7 R0 K7 + 0x8C140B05, // 0015 GETMET R5 R5 K5 + 0x881C0106, // 0016 GETMBR R7 R0 K6 0x58200004, // 0017 LDCONST R8 K4 0x54260063, // 0018 LDINT R9 100 0x58280004, // 0019 LDCONST R10 K4 @@ -1447,18 +1446,18 @@ be_local_closure(Animate_oscillator_animate, /* name */ 0x00140A06, // 0022 ADD R5 R5 R6 0x90020605, // 0023 SETMBR R0 K3 R5 0x10080403, // 0024 MOD R2 R2 R3 - 0x8C140108, // 0025 GETMET R5 R0 K8 + 0x8C140107, // 0025 GETMET R5 R0 K7 0x7C140200, // 0026 CALL R5 1 - 0x88140109, // 0027 GETMBR R5 R0 K9 - 0x8818010A, // 0028 GETMBR R6 R0 K10 - 0x881C010B, // 0029 GETMBR R7 R0 K11 + 0x88140108, // 0027 GETMBR R5 R0 K8 + 0x88180109, // 0028 GETMBR R6 R0 K9 + 0x881C010A, // 0029 GETMBR R7 R0 K10 0x5C200400, // 002A MOVE R8 R2 - 0x8824010C, // 002B GETMBR R9 R0 K12 + 0x8824010B, // 002B GETMBR R9 R0 K11 0x24241304, // 002C GT R9 R9 K4 0x7826000B, // 002D JMPF R9 #003A 0xB8260200, // 002E GETNGBL R9 K1 - 0x8C241306, // 002F GETMET R9 R9 K6 - 0x882C010C, // 0030 GETMBR R11 R0 K12 + 0x8C241305, // 002F GETMET R9 R9 K5 + 0x882C010B, // 0030 GETMBR R11 R0 K11 0x58300004, // 0031 LDCONST R12 K4 0x54360063, // 0032 LDINT R13 100 0x58380004, // 0033 LDCONST R14 K4 @@ -1468,98 +1467,89 @@ be_local_closure(Animate_oscillator_animate, /* name */ 0x24241003, // 0037 GT R9 R8 R3 0x78260000, // 0038 JMPF R9 #003A 0x04201003, // 0039 SUB R8 R8 R3 - 0x8824010D, // 003A GETMBR R9 R0 K13 - 0x1C24130E, // 003B EQ R9 R9 K14 + 0x8824010C, // 003A GETMBR R9 R0 K12 + 0x1C24130D, // 003B EQ R9 R9 K13 0x78260009, // 003C JMPF R9 #0047 0xB8260200, // 003D GETNGBL R9 K1 - 0x8C24130F, // 003E GETMET R9 R9 K15 + 0x8C24130E, // 003E GETMET R9 R9 K14 0x5C2C1000, // 003F MOVE R11 R8 0x58300004, // 0040 LDCONST R12 K4 - 0x0434070E, // 0041 SUB R13 R3 K14 + 0x0434070D, // 0041 SUB R13 R3 K13 0x5C380A00, // 0042 MOVE R14 R5 0x5C3C0C00, // 0043 MOVE R15 R6 0x7C240C00, // 0044 CALL R9 6 0x5C1C1200, // 0045 MOVE R7 R9 - 0x70020044, // 0046 JMP #008C - 0x8824010D, // 0047 GETMBR R9 R0 K13 - 0x1C241310, // 0048 EQ R9 R9 K16 + 0x7002003B, // 0046 JMP #0083 + 0x8824010C, // 0047 GETMBR R9 R0 K12 + 0x1C24130F, // 0048 EQ R9 R9 K15 0x78260015, // 0049 JMPF R9 #0060 0x14241004, // 004A LT R9 R8 R4 0x78260009, // 004B JMPF R9 #0056 0xB8260200, // 004C GETNGBL R9 K1 - 0x8C24130F, // 004D GETMET R9 R9 K15 + 0x8C24130E, // 004D GETMET R9 R9 K14 0x5C2C1000, // 004E MOVE R11 R8 0x58300004, // 004F LDCONST R12 K4 - 0x0434090E, // 0050 SUB R13 R4 K14 + 0x0434090D, // 0050 SUB R13 R4 K13 0x5C380A00, // 0051 MOVE R14 R5 0x5C3C0C00, // 0052 MOVE R15 R6 0x7C240C00, // 0053 CALL R9 6 0x5C1C1200, // 0054 MOVE R7 R9 0x70020008, // 0055 JMP #005F 0xB8260200, // 0056 GETNGBL R9 K1 - 0x8C24130F, // 0057 GETMET R9 R9 K15 + 0x8C24130E, // 0057 GETMET R9 R9 K14 0x5C2C1000, // 0058 MOVE R11 R8 0x5C300800, // 0059 MOVE R12 R4 - 0x0434070E, // 005A SUB R13 R3 K14 + 0x0434070D, // 005A SUB R13 R3 K13 0x5C380C00, // 005B MOVE R14 R6 0x5C3C0A00, // 005C MOVE R15 R5 0x7C240C00, // 005D CALL R9 6 0x5C1C1200, // 005E MOVE R7 R9 - 0x7002002B, // 005F JMP #008C - 0x8824010D, // 0060 GETMBR R9 R0 K13 - 0x1C241311, // 0061 EQ R9 R9 K17 + 0x70020022, // 005F JMP #0083 + 0x8824010C, // 0060 GETMBR R9 R0 K12 + 0x1C241310, // 0061 EQ R9 R9 K16 0x78260005, // 0062 JMPF R9 #0069 0x14241004, // 0063 LT R9 R8 R4 0x78260001, // 0064 JMPF R9 #0067 0x5C1C0A00, // 0065 MOVE R7 R5 0x70020000, // 0066 JMP #0068 0x5C1C0C00, // 0067 MOVE R7 R6 - 0x70020022, // 0068 JMP #008C - 0x8824010D, // 0069 GETMBR R9 R0 K13 + 0x70020019, // 0068 JMP #0083 + 0x8824010C, // 0069 GETMBR R9 R0 K12 0x542A0003, // 006A LDINT R10 4 0x1C24120A, // 006B EQ R9 R9 R10 - 0x74260003, // 006C JMPT R9 #0071 - 0x8824010D, // 006D GETMBR R9 R0 K13 - 0x542A0004, // 006E LDINT R10 5 - 0x1C24120A, // 006F EQ R9 R9 R10 - 0x7826001A, // 0070 JMPF R9 #008C - 0xB8260200, // 0071 GETNGBL R9 K1 - 0x8C24130F, // 0072 GETMET R9 R9 K15 - 0x5C2C1000, // 0073 MOVE R11 R8 - 0x58300004, // 0074 LDCONST R12 K4 - 0x0434070E, // 0075 SUB R13 R3 K14 - 0x58380004, // 0076 LDCONST R14 K4 - 0x543E7FFE, // 0077 LDINT R15 32767 - 0x7C240C00, // 0078 CALL R9 6 - 0x8828010D, // 0079 GETMBR R10 R0 K13 - 0x542E0003, // 007A LDINT R11 4 - 0x1C28140B, // 007B EQ R10 R10 R11 - 0x782A0001, // 007C JMPF R10 #007F - 0x542A1FFF, // 007D LDINT R10 8192 - 0x0424120A, // 007E SUB R9 R9 R10 - 0xB82A0200, // 007F GETNGBL R10 K1 - 0x8C281512, // 0080 GETMET R10 R10 K18 - 0x5C301200, // 0081 MOVE R12 R9 - 0x7C280400, // 0082 CALL R10 2 - 0xB82E0200, // 0083 GETNGBL R11 K1 - 0x8C2C170F, // 0084 GETMET R11 R11 K15 - 0x5C341400, // 0085 MOVE R13 R10 - 0x5439EFFF, // 0086 LDINT R14 -4096 - 0x543E0FFF, // 0087 LDINT R15 4096 - 0x5C400A00, // 0088 MOVE R16 R5 - 0x5C440C00, // 0089 MOVE R17 R6 - 0x7C2C0C00, // 008A CALL R11 6 - 0x5C1C1600, // 008B MOVE R7 R11 - 0x90021607, // 008C SETMBR R0 K11 R7 - 0x88240113, // 008D GETMBR R9 R0 K19 - 0x88280114, // 008E GETMBR R10 R0 K20 - 0x78260004, // 008F JMPF R9 #0095 - 0x782A0003, // 0090 JMPF R10 #0095 - 0x5C2C1400, // 0091 MOVE R11 R10 - 0x5C301200, // 0092 MOVE R12 R9 - 0x5C340E00, // 0093 MOVE R13 R7 - 0x7C2C0400, // 0094 CALL R11 2 - 0x80040E00, // 0095 RET 1 R7 + 0x78260015, // 006C JMPF R9 #0083 + 0xB8260200, // 006D GETNGBL R9 K1 + 0x8C24130E, // 006E GETMET R9 R9 K14 + 0x5C2C1000, // 006F MOVE R11 R8 + 0x58300004, // 0070 LDCONST R12 K4 + 0x0434070D, // 0071 SUB R13 R3 K13 + 0x58380004, // 0072 LDCONST R14 K4 + 0x543E7FFE, // 0073 LDINT R15 32767 + 0x7C240C00, // 0074 CALL R9 6 + 0xB82A0200, // 0075 GETNGBL R10 K1 + 0x8C281511, // 0076 GETMET R10 R10 K17 + 0x54321FFF, // 0077 LDINT R12 8192 + 0x0430120C, // 0078 SUB R12 R9 R12 + 0x7C280400, // 0079 CALL R10 2 + 0xB82E0200, // 007A GETNGBL R11 K1 + 0x8C2C170E, // 007B GETMET R11 R11 K14 + 0x5C341400, // 007C MOVE R13 R10 + 0x5439EFFF, // 007D LDINT R14 -4096 + 0x543E0FFF, // 007E LDINT R15 4096 + 0x5C400A00, // 007F MOVE R16 R5 + 0x5C440C00, // 0080 MOVE R17 R6 + 0x7C2C0C00, // 0081 CALL R11 6 + 0x5C1C1600, // 0082 MOVE R7 R11 + 0x90021407, // 0083 SETMBR R0 K10 R7 + 0x88240112, // 0084 GETMBR R9 R0 K18 + 0x88280113, // 0085 GETMBR R10 R0 K19 + 0x78260004, // 0086 JMPF R9 #008C + 0x782A0003, // 0087 JMPF R10 #008C + 0x5C2C1400, // 0088 MOVE R11 R10 + 0x5C301200, // 0089 MOVE R12 R9 + 0x5C340E00, // 008A MOVE R13 R7 + 0x7C2C0400, // 008B CALL R11 2 + 0x80040E00, // 008C RET 1 R7 }) ) ); diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_leds.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_leds.h index ef3af9aba..3e0ef7846 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_leds.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_leds.h @@ -6,36 +6,6 @@ extern const bclass be_class_Leds; -/******************************************************************** -** Solidified function: show -********************************************************************/ -be_local_closure(Leds_show, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str(call_native), - /* K1 */ be_const_int(2), - }), - &be_const_str_show, - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x580C0001, // 0001 LDCONST R3 K1 - 0x7C040400, // 0002 CALL R1 2 - 0x80000000, // 0003 RET 0 - }) - ) -); -/*******************************************************************/ - - extern const bclass be_class_Leds_segment; /******************************************************************** @@ -78,28 +48,33 @@ be_local_closure(Leds_segment_clear_to, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str(strip), - /* K1 */ be_nested_str(call_native), - /* K2 */ be_nested_str(to_gamma), - /* K3 */ be_nested_str(offset), - /* K4 */ be_nested_str(leds), + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str(bri), + /* K1 */ be_nested_str(strip), + /* K2 */ be_nested_str(call_native), + /* K3 */ be_nested_str(to_gamma), + /* K4 */ be_nested_str(offset), + /* K5 */ be_nested_str(leds), }), &be_const_str_clear_to, &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x880C0100, // 0000 GETMBR R3 R0 K0 - 0x8C0C0701, // 0001 GETMET R3 R3 K1 - 0x54160008, // 0002 LDINT R5 9 - 0x88180100, // 0003 GETMBR R6 R0 K0 - 0x8C180D02, // 0004 GETMET R6 R6 K2 - 0x5C200200, // 0005 MOVE R8 R1 - 0x5C240400, // 0006 MOVE R9 R2 - 0x7C180600, // 0007 CALL R6 3 - 0x881C0103, // 0008 GETMBR R7 R0 K3 - 0x88200104, // 0009 GETMBR R8 R0 K4 - 0x7C0C0A00, // 000A CALL R3 5 - 0x80000000, // 000B RET 0 + ( &(const binstruction[16]) { /* code */ + 0x4C0C0000, // 0000 LDNIL R3 + 0x1C0C0403, // 0001 EQ R3 R2 R3 + 0x780E0000, // 0002 JMPF R3 #0004 + 0x88080100, // 0003 GETMBR R2 R0 K0 + 0x880C0101, // 0004 GETMBR R3 R0 K1 + 0x8C0C0702, // 0005 GETMET R3 R3 K2 + 0x54160008, // 0006 LDINT R5 9 + 0x88180101, // 0007 GETMBR R6 R0 K1 + 0x8C180D03, // 0008 GETMET R6 R6 K3 + 0x5C200200, // 0009 MOVE R8 R1 + 0x5C240400, // 000A MOVE R9 R2 + 0x7C180600, // 000B CALL R6 3 + 0x881C0104, // 000C GETMBR R7 R0 K4 + 0x88200105, // 000D GETMBR R8 R0 K5 + 0x7C0C0A00, // 000E CALL R3 5 + 0x80000000, // 000F RET 0 }) ) ); @@ -231,22 +206,27 @@ be_local_closure(Leds_segment_set_pixel_color, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str(strip), - /* K1 */ be_nested_str(set_pixel_color), - /* K2 */ be_nested_str(offset), + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str(bri), + /* K1 */ be_nested_str(strip), + /* K2 */ be_nested_str(set_pixel_color), + /* K3 */ be_nested_str(offset), }), &be_const_str_set_pixel_color, &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x88100100, // 0000 GETMBR R4 R0 K0 - 0x8C100901, // 0001 GETMET R4 R4 K1 - 0x88180102, // 0002 GETMBR R6 R0 K2 - 0x00180206, // 0003 ADD R6 R1 R6 - 0x5C1C0400, // 0004 MOVE R7 R2 - 0x5C200600, // 0005 MOVE R8 R3 - 0x7C100800, // 0006 CALL R4 4 - 0x80000000, // 0007 RET 0 + ( &(const binstruction[12]) { /* code */ + 0x4C100000, // 0000 LDNIL R4 + 0x1C100604, // 0001 EQ R4 R3 R4 + 0x78120000, // 0002 JMPF R4 #0004 + 0x880C0100, // 0003 GETMBR R3 R0 K0 + 0x88100101, // 0004 GETMBR R4 R0 K1 + 0x8C100902, // 0005 GETMET R4 R4 K2 + 0x88180103, // 0006 GETMBR R6 R0 K3 + 0x00180206, // 0007 ADD R6 R1 R6 + 0x5C1C0400, // 0008 MOVE R7 R2 + 0x5C200600, // 0009 MOVE R8 R3 + 0x7C100800, // 000A CALL R4 4 + 0x80000000, // 000B RET 0 }) ) ); @@ -567,112 +547,34 @@ be_local_closure(Leds_create_segment, /* name */ /******************************************************************** -** Solidified function: assign_rmt +** Solidified function: set_bri ********************************************************************/ -be_local_closure(Leds_assign_rmt, /* name */ +be_local_closure(Leds_set_bri, /* name */ be_nested_proto( - 9, /* nstack */ - 1, /* argc */ - 4, /* varg */ + 3, /* nstack */ + 2, /* argc */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[17]) { /* constants */ - /* K0 */ be_const_class(be_class_Leds), - /* K1 */ be_const_int(0), - /* K2 */ be_nested_str(value_error), - /* K3 */ be_nested_str(invalid_X20GPIO_X20number), - /* K4 */ be_nested_str(global), - /* K5 */ be_nested_str(contains), - /* K6 */ be_nested_str(_rmt), - /* K7 */ be_nested_str(gpio), - /* K8 */ be_nested_str(MAX_RMT), - /* K9 */ be_const_int(1), - /* K10 */ be_nested_str(push), - /* K11 */ be_nested_str(stop_iteration), - /* K12 */ be_nested_str(pin_used), - /* K13 */ be_nested_str(WS2812), - /* K14 */ be_nested_str(pin), - /* K15 */ be_nested_str(internal_error), - /* K16 */ be_nested_str(no_X20more_X20RMT_X20channel_X20available), + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str(bri), }), - &be_const_str_assign_rmt, + &be_const_str_set_bri, &be_const_str_solidified, - ( &(const binstruction[72]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x60080009, // 0001 GETGBL R2 G9 - 0x5C0C0000, // 0002 MOVE R3 R0 - 0x7C080200, // 0003 CALL R2 1 - 0x5C000400, // 0004 MOVE R0 R2 - 0x14080101, // 0005 LT R2 R0 K1 - 0x780A0000, // 0006 JMPF R2 #0008 - 0xB0060503, // 0007 RAISE 1 K2 K3 - 0xA40A0800, // 0008 IMPORT R2 K4 - 0x4C0C0000, // 0009 LDNIL R3 - 0x8C100505, // 000A GETMET R4 R2 K5 - 0x58180006, // 000B LDCONST R6 K6 - 0x7C100400, // 000C CALL R4 2 - 0x74120021, // 000D JMPT R4 #0030 - 0x60100012, // 000E GETGBL R4 G18 - 0x7C100000, // 000F CALL R4 0 - 0x5C0C0800, // 0010 MOVE R3 R4 - 0x900A0C03, // 0011 SETMBR R2 K6 R3 - 0x60100010, // 0012 GETGBL R4 G16 - 0xB8160E00, // 0013 GETNGBL R5 K7 - 0x88140B08, // 0014 GETMBR R5 R5 K8 - 0x04140B09, // 0015 SUB R5 R5 K9 - 0x40160205, // 0016 CONNECT R5 K1 R5 - 0x7C100200, // 0017 CALL R4 1 - 0xA8020005, // 0018 EXBLK 0 #001F - 0x5C140800, // 0019 MOVE R5 R4 - 0x7C140000, // 001A CALL R5 0 - 0x8C18070A, // 001B GETMET R6 R3 K10 - 0x5421FFFE, // 001C LDINT R8 -1 - 0x7C180400, // 001D CALL R6 2 - 0x7001FFF9, // 001E JMP #0019 - 0x5810000B, // 001F LDCONST R4 K11 - 0xAC100200, // 0020 CATCH R4 1 0 - 0xB0080000, // 0021 RAISE 2 R0 R0 - 0xB8120E00, // 0022 GETNGBL R4 K7 - 0x8C10090C, // 0023 GETMET R4 R4 K12 - 0xB81A0E00, // 0024 GETNGBL R6 K7 - 0x88180D0D, // 0025 GETMBR R6 R6 K13 - 0x581C0001, // 0026 LDCONST R7 K1 - 0x7C100600, // 0027 CALL R4 3 - 0x78120006, // 0028 JMPF R4 #0030 - 0xB8120E00, // 0029 GETNGBL R4 K7 - 0x8C10090E, // 002A GETMET R4 R4 K14 - 0xB81A0E00, // 002B GETNGBL R6 K7 - 0x88180D0D, // 002C GETMBR R6 R6 K13 - 0x581C0001, // 002D LDCONST R7 K1 - 0x7C100600, // 002E CALL R4 3 - 0x980E0204, // 002F SETIDX R3 K1 R4 - 0x880C0506, // 0030 GETMBR R3 R2 K6 - 0x58100001, // 0031 LDCONST R4 K1 - 0x5415FFFE, // 0032 LDINT R5 -1 - 0xB81A0E00, // 0033 GETNGBL R6 K7 - 0x88180D08, // 0034 GETMBR R6 R6 K8 - 0x14180806, // 0035 LT R6 R4 R6 - 0x781A000A, // 0036 JMPF R6 #0042 - 0x94180604, // 0037 GETIDX R6 R3 R4 - 0x1C1C0C00, // 0038 EQ R7 R6 R0 - 0x781E0000, // 0039 JMPF R7 #003B - 0x80040800, // 003A RET 1 R4 - 0x141C0D01, // 003B LT R7 R6 K1 - 0x781E0002, // 003C JMPF R7 #0040 - 0x141C0B01, // 003D LT R7 R5 K1 - 0x781E0000, // 003E JMPF R7 #0040 - 0x5C140800, // 003F MOVE R5 R4 - 0x00100909, // 0040 ADD R4 R4 K9 - 0x7001FFF0, // 0041 JMP #0033 - 0x28180B01, // 0042 GE R6 R5 K1 - 0x781A0001, // 0043 JMPF R6 #0046 - 0x980C0A00, // 0044 SETIDX R3 R5 R0 - 0x80040A00, // 0045 RET 1 R5 - 0xB0061F10, // 0046 RAISE 1 K15 K16 - 0x80000000, // 0047 RET 0 + ( &(const binstruction[ 9]) { /* code */ + 0x14080300, // 0000 LT R2 R1 K0 + 0x780A0000, // 0001 JMPF R2 #0003 + 0x58040000, // 0002 LDCONST R1 K0 + 0x540A00FE, // 0003 LDINT R2 255 + 0x24080202, // 0004 GT R2 R1 R2 + 0x780A0000, // 0005 JMPF R2 #0007 + 0x540600FE, // 0006 LDINT R1 255 + 0x90020201, // 0007 SETMBR R0 K1 R1 + 0x80000000, // 0008 RET 0 }) ) ); @@ -680,9 +582,9 @@ be_local_closure(Leds_assign_rmt, /* name */ /******************************************************************** -** Solidified function: can_show +** Solidified function: begin ********************************************************************/ -be_local_closure(Leds_can_show, /* name */ +be_local_closure(Leds_begin, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -694,14 +596,203 @@ be_local_closure(Leds_can_show, /* name */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ /* K0 */ be_nested_str(call_native), - /* K1 */ be_const_int(3), + /* K1 */ be_const_int(1), }), - &be_const_str_can_show, + &be_const_str_begin, &be_const_str_solidified, ( &(const binstruction[ 4]) { /* code */ 0x8C040100, // 0000 GETMET R1 R0 K0 0x580C0001, // 0001 LDCONST R3 K1 0x7C040400, // 0002 CALL R1 2 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: clear +********************************************************************/ +be_local_closure(Leds_clear, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str(clear_to), + /* K1 */ be_const_int(0), + /* K2 */ be_nested_str(show), + }), + &be_const_str_clear, + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x580C0001, // 0001 LDCONST R3 K1 + 0x7C040400, // 0002 CALL R1 2 + 0x8C040102, // 0003 GETMET R1 R0 K2 + 0x7C040200, // 0004 CALL R1 1 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Leds_init, /* name */ + be_nested_proto( + 11, /* nstack */ + 5, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[10]) { /* constants */ + /* K0 */ be_nested_str(gamma), + /* K1 */ be_nested_str(leds), + /* K2 */ be_nested_str(bri), + /* K3 */ be_nested_str(valuer_error), + /* K4 */ be_nested_str(no_X20GPIO_X20specified_X20for_X20neopixelbus), + /* K5 */ be_nested_str(ctor), + /* K6 */ be_nested_str(_p), + /* K7 */ be_nested_str(internal_error), + /* K8 */ be_nested_str(couldn_X27t_X20not_X20initialize_X20noepixelbus), + /* K9 */ be_nested_str(begin), + }), + &be_const_str_init, + &be_const_str_solidified, + ( &(const binstruction[26]) { /* code */ + 0x50140200, // 0000 LDBOOL R5 1 0 + 0x90020005, // 0001 SETMBR R0 K0 R5 + 0x60140009, // 0002 GETGBL R5 G9 + 0x5C180200, // 0003 MOVE R6 R1 + 0x7C140200, // 0004 CALL R5 1 + 0x90020205, // 0005 SETMBR R0 K1 R5 + 0x5416007E, // 0006 LDINT R5 127 + 0x90020405, // 0007 SETMBR R0 K2 R5 + 0x4C140000, // 0008 LDNIL R5 + 0x1C140405, // 0009 EQ R5 R2 R5 + 0x78160000, // 000A JMPF R5 #000C + 0xB0060704, // 000B RAISE 1 K3 K4 + 0x8C140105, // 000C GETMET R5 R0 K5 + 0x881C0101, // 000D GETMBR R7 R0 K1 + 0x5C200400, // 000E MOVE R8 R2 + 0x5C240600, // 000F MOVE R9 R3 + 0x5C280800, // 0010 MOVE R10 R4 + 0x7C140A00, // 0011 CALL R5 5 + 0x88140106, // 0012 GETMBR R5 R0 K6 + 0x4C180000, // 0013 LDNIL R6 + 0x1C140A06, // 0014 EQ R5 R5 R6 + 0x78160000, // 0015 JMPF R5 #0017 + 0xB0060F08, // 0016 RAISE 1 K7 K8 + 0x8C140109, // 0017 GETMET R5 R0 K9 + 0x7C140200, // 0018 CALL R5 1 + 0x80000000, // 0019 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: to_gamma +********************************************************************/ +be_local_closure(Leds_to_gamma, /* name */ + be_nested_proto( + 8, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str(bri), + /* K1 */ be_nested_str(apply_bri_gamma), + /* K2 */ be_nested_str(gamma), + }), + &be_const_str_to_gamma, + &be_const_str_solidified, + ( &(const binstruction[10]) { /* code */ + 0x4C0C0000, // 0000 LDNIL R3 + 0x1C0C0403, // 0001 EQ R3 R2 R3 + 0x780E0000, // 0002 JMPF R3 #0004 + 0x88080100, // 0003 GETMBR R2 R0 K0 + 0x8C0C0101, // 0004 GETMET R3 R0 K1 + 0x5C140200, // 0005 MOVE R5 R1 + 0x5C180400, // 0006 MOVE R6 R2 + 0x881C0102, // 0007 GETMBR R7 R0 K2 + 0x7C0C0800, // 0008 CALL R3 4 + 0x80040600, // 0009 RET 1 R3 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: show +********************************************************************/ +be_local_closure(Leds_show, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str(call_native), + /* K1 */ be_const_int(2), + }), + &be_const_str_show, + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x580C0001, // 0001 LDCONST R3 K1 + 0x7C040400, // 0002 CALL R1 2 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: pixel_count +********************************************************************/ +be_local_closure(Leds_pixel_count, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(call_native), + }), + &be_const_str_pixel_count, + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x540E0007, // 0001 LDINT R3 8 + 0x7C040400, // 0002 CALL R1 2 0x80040200, // 0003 RET 1 R1 }) ) @@ -709,6 +800,122 @@ be_local_closure(Leds_can_show, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: get_bri +********************************************************************/ +be_local_closure(Leds_get_bri, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(bri), + }), + &be_const_str_get_bri, + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_gamma +********************************************************************/ +be_local_closure(Leds_set_gamma, /* name */ + be_nested_proto( + 4, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(gamma), + }), + &be_const_str_set_gamma, + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x60080017, // 0000 GETGBL R2 G23 + 0x5C0C0200, // 0001 MOVE R3 R1 + 0x7C080200, // 0002 CALL R2 1 + 0x90020002, // 0003 SETMBR R0 K0 R2 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_pixel_color +********************************************************************/ +be_local_closure(Leds_get_pixel_color, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(call_native), + }), + &be_const_str_get_pixel_color, + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x8C080100, // 0000 GETMET R2 R0 K0 + 0x5412000A, // 0001 LDINT R4 11 + 0x5C140200, // 0002 MOVE R5 R1 + 0x7C080600, // 0003 CALL R2 3 + 0x80040400, // 0004 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: dirty +********************************************************************/ +be_local_closure(Leds_dirty, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(call_native), + }), + &be_const_str_dirty, + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x540E0004, // 0001 LDINT R3 5 + 0x7C040400, // 0002 CALL R1 2 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: matrix ********************************************************************/ @@ -750,11 +957,11 @@ be_local_closure(Leds_matrix, /* name */ /******************************************************************** -** Solidified function: pixel_count +** Solidified function: pixel_offset ********************************************************************/ -be_local_closure(Leds_pixel_count, /* name */ +be_local_closure(Leds_pixel_offset, /* name */ be_nested_proto( - 4, /* nstack */ + 1, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -763,15 +970,12 @@ be_local_closure(Leds_pixel_count, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str(call_native), + /* K0 */ be_const_int(0), }), - &be_const_str_pixel_count, + &be_const_str_pixel_offset, &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x540E0007, // 0001 LDINT R3 8 - 0x7C040400, // 0002 CALL R1 2 - 0x80040200, // 0003 RET 1 R1 + ( &(const binstruction[ 1]) { /* code */ + 0x80060000, // 0000 RET 1 K0 }) ) ); @@ -779,77 +983,38 @@ be_local_closure(Leds_pixel_count, /* name */ /******************************************************************** -** Solidified function: is_dirty +** Solidified function: clear_to ********************************************************************/ -be_local_closure(Leds_is_dirty, /* name */ +be_local_closure(Leds_clear_to, /* name */ be_nested_proto( - 4, /* nstack */ - 1, /* argc */ + 10, /* nstack */ + 3, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str(call_native), + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str(bri), + /* K1 */ be_nested_str(call_native), + /* K2 */ be_nested_str(to_gamma), }), - &be_const_str_is_dirty, + &be_const_str_clear_to, &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x540E0003, // 0001 LDINT R3 4 - 0x7C040400, // 0002 CALL R1 2 - 0x80040200, // 0003 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: pixels_buffer -********************************************************************/ -be_local_closure(Leds_pixels_buffer, /* name */ - be_nested_proto( - 8, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str(call_native), - /* K1 */ be_nested_str(pixel_size), - /* K2 */ be_nested_str(pixel_count), - /* K3 */ be_nested_str(_change_buffer), - }), - &be_const_str_pixels_buffer, - &be_const_str_solidified, - ( &(const binstruction[21]) { /* code */ - 0x8C080100, // 0000 GETMET R2 R0 K0 - 0x54120005, // 0001 LDINT R4 6 - 0x7C080400, // 0002 CALL R2 2 - 0x4C0C0000, // 0003 LDNIL R3 - 0x1C0C0203, // 0004 EQ R3 R1 R3 - 0x780E0009, // 0005 JMPF R3 #0010 - 0x600C0015, // 0006 GETGBL R3 G21 - 0x5C100400, // 0007 MOVE R4 R2 - 0x8C140101, // 0008 GETMET R5 R0 K1 - 0x7C140200, // 0009 CALL R5 1 - 0x8C180102, // 000A GETMET R6 R0 K2 - 0x7C180200, // 000B CALL R6 1 - 0x08140A06, // 000C MUL R5 R5 R6 - 0x7C0C0400, // 000D CALL R3 2 - 0x80040600, // 000E RET 1 R3 - 0x70020003, // 000F JMP #0014 - 0x8C0C0303, // 0010 GETMET R3 R1 K3 - 0x5C140400, // 0011 MOVE R5 R2 - 0x7C0C0400, // 0012 CALL R3 2 - 0x80040200, // 0013 RET 1 R1 - 0x80000000, // 0014 RET 0 + ( &(const binstruction[12]) { /* code */ + 0x4C0C0000, // 0000 LDNIL R3 + 0x1C0C0403, // 0001 EQ R3 R2 R3 + 0x780E0000, // 0002 JMPF R3 #0004 + 0x88080100, // 0003 GETMBR R2 R0 K0 + 0x8C0C0101, // 0004 GETMET R3 R0 K1 + 0x54160008, // 0005 LDINT R5 9 + 0x8C180102, // 0006 GETMET R6 R0 K2 + 0x5C200200, // 0007 MOVE R8 R1 + 0x5C240400, // 0008 MOVE R9 R2 + 0x7C180600, // 0009 CALL R6 3 + 0x7C0C0600, // 000A CALL R3 3 + 0x80000000, // 000B RET 0 }) ) ); @@ -869,22 +1034,56 @@ be_local_closure(Leds_set_pixel_color, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str(call_native), - /* K1 */ be_nested_str(to_gamma), + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str(bri), + /* K1 */ be_nested_str(call_native), + /* K2 */ be_nested_str(to_gamma), }), &be_const_str_set_pixel_color, &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0x8C100100, // 0000 GETMET R4 R0 K0 - 0x541A0009, // 0001 LDINT R6 10 - 0x5C1C0200, // 0002 MOVE R7 R1 - 0x8C200101, // 0003 GETMET R8 R0 K1 - 0x5C280400, // 0004 MOVE R10 R2 - 0x5C2C0600, // 0005 MOVE R11 R3 - 0x7C200600, // 0006 CALL R8 3 - 0x7C100800, // 0007 CALL R4 4 - 0x80000000, // 0008 RET 0 + ( &(const binstruction[13]) { /* code */ + 0x4C100000, // 0000 LDNIL R4 + 0x1C100604, // 0001 EQ R4 R3 R4 + 0x78120000, // 0002 JMPF R4 #0004 + 0x880C0100, // 0003 GETMBR R3 R0 K0 + 0x8C100101, // 0004 GETMET R4 R0 K1 + 0x541A0009, // 0005 LDINT R6 10 + 0x5C1C0200, // 0006 MOVE R7 R1 + 0x8C200102, // 0007 GETMET R8 R0 K2 + 0x5C280400, // 0008 MOVE R10 R2 + 0x5C2C0600, // 0009 MOVE R11 R3 + 0x7C200600, // 000A CALL R8 3 + 0x7C100800, // 000B CALL R4 4 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: pixel_size +********************************************************************/ +be_local_closure(Leds_pixel_size, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(call_native), + }), + &be_const_str_pixel_size, + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x540E0006, // 0001 LDINT R3 7 + 0x7C040400, // 0002 CALL R1 2 + 0x80040200, // 0003 RET 1 R1 }) ) ); @@ -906,31 +1105,36 @@ be_local_closure(Leds_matrix_clear_to, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str(strip), - /* K1 */ be_nested_str(call_native), - /* K2 */ be_nested_str(to_gamma), - /* K3 */ be_nested_str(offset), - /* K4 */ be_nested_str(w), - /* K5 */ be_nested_str(h), + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str(bri), + /* K1 */ be_nested_str(strip), + /* K2 */ be_nested_str(call_native), + /* K3 */ be_nested_str(to_gamma), + /* K4 */ be_nested_str(offset), + /* K5 */ be_nested_str(w), + /* K6 */ be_nested_str(h), }), &be_const_str_clear_to, &be_const_str_solidified, - ( &(const binstruction[14]) { /* code */ - 0x880C0100, // 0000 GETMBR R3 R0 K0 - 0x8C0C0701, // 0001 GETMET R3 R3 K1 - 0x54160008, // 0002 LDINT R5 9 - 0x88180100, // 0003 GETMBR R6 R0 K0 - 0x8C180D02, // 0004 GETMET R6 R6 K2 - 0x5C200200, // 0005 MOVE R8 R1 - 0x5C240400, // 0006 MOVE R9 R2 - 0x7C180600, // 0007 CALL R6 3 - 0x881C0103, // 0008 GETMBR R7 R0 K3 - 0x88200104, // 0009 GETMBR R8 R0 K4 - 0x88240105, // 000A GETMBR R9 R0 K5 - 0x08201009, // 000B MUL R8 R8 R9 - 0x7C0C0A00, // 000C CALL R3 5 - 0x80000000, // 000D RET 0 + ( &(const binstruction[18]) { /* code */ + 0x4C0C0000, // 0000 LDNIL R3 + 0x1C0C0403, // 0001 EQ R3 R2 R3 + 0x780E0000, // 0002 JMPF R3 #0004 + 0x88080100, // 0003 GETMBR R2 R0 K0 + 0x880C0101, // 0004 GETMBR R3 R0 K1 + 0x8C0C0702, // 0005 GETMET R3 R3 K2 + 0x54160008, // 0006 LDINT R5 9 + 0x88180101, // 0007 GETMBR R6 R0 K1 + 0x8C180D03, // 0008 GETMET R6 R6 K3 + 0x5C200200, // 0009 MOVE R8 R1 + 0x5C240400, // 000A MOVE R9 R2 + 0x7C180600, // 000B CALL R6 3 + 0x881C0104, // 000C GETMBR R7 R0 K4 + 0x88200105, // 000D GETMBR R8 R0 K5 + 0x88240106, // 000E GETMBR R9 R0 K6 + 0x08201009, // 000F MUL R8 R8 R9 + 0x7C0C0A00, // 0010 CALL R3 5 + 0x80000000, // 0011 RET 0 }) ) ); @@ -1081,22 +1285,27 @@ be_local_closure(Leds_matrix_set_pixel_color, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str(strip), - /* K1 */ be_nested_str(set_pixel_color), - /* K2 */ be_nested_str(offset), + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str(bri), + /* K1 */ be_nested_str(strip), + /* K2 */ be_nested_str(set_pixel_color), + /* K3 */ be_nested_str(offset), }), &be_const_str_set_pixel_color, &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x88100100, // 0000 GETMBR R4 R0 K0 - 0x8C100901, // 0001 GETMET R4 R4 K1 - 0x88180102, // 0002 GETMBR R6 R0 K2 - 0x00180206, // 0003 ADD R6 R1 R6 - 0x5C1C0400, // 0004 MOVE R7 R2 - 0x5C200600, // 0005 MOVE R8 R3 - 0x7C100800, // 0006 CALL R4 4 - 0x80000000, // 0007 RET 0 + ( &(const binstruction[12]) { /* code */ + 0x4C100000, // 0000 LDNIL R4 + 0x1C100604, // 0001 EQ R4 R3 R4 + 0x78120000, // 0002 JMPF R4 #0004 + 0x880C0100, // 0003 GETMBR R3 R0 K0 + 0x88100101, // 0004 GETMBR R4 R0 K1 + 0x8C100902, // 0005 GETMET R4 R4 K2 + 0x88180103, // 0006 GETMBR R6 R0 K3 + 0x00180206, // 0007 ADD R6 R1 R6 + 0x5C1C0400, // 0008 MOVE R7 R2 + 0x5C200600, // 0009 MOVE R8 R3 + 0x7C100800, // 000A CALL R4 4 + 0x80000000, // 000B RET 0 }) ) ); @@ -1176,48 +1385,53 @@ be_local_closure(Leds_matrix_set_matrix_pixel_color, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str(alternate), - /* K1 */ be_const_int(2), - /* K2 */ be_nested_str(strip), - /* K3 */ be_nested_str(set_pixel_color), - /* K4 */ be_nested_str(w), - /* K5 */ be_nested_str(h), - /* K6 */ be_const_int(1), - /* K7 */ be_nested_str(offset), + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str(bri), + /* K1 */ be_nested_str(alternate), + /* K2 */ be_const_int(2), + /* K3 */ be_nested_str(strip), + /* K4 */ be_nested_str(set_pixel_color), + /* K5 */ be_nested_str(w), + /* K6 */ be_nested_str(h), + /* K7 */ be_const_int(1), + /* K8 */ be_nested_str(offset), }), &be_const_str_set_matrix_pixel_color, &be_const_str_solidified, - ( &(const binstruction[29]) { /* code */ - 0x88140100, // 0000 GETMBR R5 R0 K0 - 0x7816000F, // 0001 JMPF R5 #0012 - 0x10140301, // 0002 MOD R5 R1 K1 - 0x7816000D, // 0003 JMPF R5 #0012 - 0x88140102, // 0004 GETMBR R5 R0 K2 - 0x8C140B03, // 0005 GETMET R5 R5 K3 - 0x881C0104, // 0006 GETMBR R7 R0 K4 - 0x081C0207, // 0007 MUL R7 R1 R7 - 0x88200105, // 0008 GETMBR R8 R0 K5 - 0x001C0E08, // 0009 ADD R7 R7 R8 - 0x041C0E02, // 000A SUB R7 R7 R2 - 0x041C0F06, // 000B SUB R7 R7 K6 - 0x88200107, // 000C GETMBR R8 R0 K7 + ( &(const binstruction[33]) { /* code */ + 0x4C140000, // 0000 LDNIL R5 + 0x1C140805, // 0001 EQ R5 R4 R5 + 0x78160000, // 0002 JMPF R5 #0004 + 0x88100100, // 0003 GETMBR R4 R0 K0 + 0x88140101, // 0004 GETMBR R5 R0 K1 + 0x7816000F, // 0005 JMPF R5 #0016 + 0x10140302, // 0006 MOD R5 R1 K2 + 0x7816000D, // 0007 JMPF R5 #0016 + 0x88140103, // 0008 GETMBR R5 R0 K3 + 0x8C140B04, // 0009 GETMET R5 R5 K4 + 0x881C0105, // 000A GETMBR R7 R0 K5 + 0x081C0207, // 000B MUL R7 R1 R7 + 0x88200106, // 000C GETMBR R8 R0 K6 0x001C0E08, // 000D ADD R7 R7 R8 - 0x5C200600, // 000E MOVE R8 R3 - 0x5C240800, // 000F MOVE R9 R4 - 0x7C140800, // 0010 CALL R5 4 - 0x70020009, // 0011 JMP #001C - 0x88140102, // 0012 GETMBR R5 R0 K2 - 0x8C140B03, // 0013 GETMET R5 R5 K3 - 0x881C0104, // 0014 GETMBR R7 R0 K4 - 0x081C0207, // 0015 MUL R7 R1 R7 - 0x001C0E02, // 0016 ADD R7 R7 R2 - 0x88200107, // 0017 GETMBR R8 R0 K7 - 0x001C0E08, // 0018 ADD R7 R7 R8 - 0x5C200600, // 0019 MOVE R8 R3 - 0x5C240800, // 001A MOVE R9 R4 - 0x7C140800, // 001B CALL R5 4 - 0x80000000, // 001C RET 0 + 0x041C0E02, // 000E SUB R7 R7 R2 + 0x041C0F07, // 000F SUB R7 R7 K7 + 0x88200108, // 0010 GETMBR R8 R0 K8 + 0x001C0E08, // 0011 ADD R7 R7 R8 + 0x5C200600, // 0012 MOVE R8 R3 + 0x5C240800, // 0013 MOVE R9 R4 + 0x7C140800, // 0014 CALL R5 4 + 0x70020009, // 0015 JMP #0020 + 0x88140103, // 0016 GETMBR R5 R0 K3 + 0x8C140B04, // 0017 GETMET R5 R5 K4 + 0x881C0105, // 0018 GETMBR R7 R0 K5 + 0x081C0207, // 0019 MUL R7 R1 R7 + 0x001C0E02, // 001A ADD R7 R7 R2 + 0x88200108, // 001B GETMBR R8 R0 K8 + 0x001C0E08, // 001C ADD R7 R7 R8 + 0x5C200600, // 001D MOVE R8 R3 + 0x5C240800, // 001E MOVE R9 R4 + 0x7C140800, // 001F CALL R5 4 + 0x80000000, // 0020 RET 0 }) ) ); @@ -1635,12 +1849,68 @@ be_local_closure(Leds_create_matrix, /* name */ /******************************************************************** -** Solidified function: to_gamma +** Solidified function: get_gamma ********************************************************************/ -be_local_closure(Leds_to_gamma, /* name */ +be_local_closure(Leds_get_gamma, /* name */ be_nested_proto( - 8, /* nstack */ - 3, /* argc */ + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(gamma), + }), + &be_const_str_get_gamma, + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: is_dirty +********************************************************************/ +be_local_closure(Leds_is_dirty, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(call_native), + }), + &be_const_str_is_dirty, + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x540E0003, // 0001 LDINT R3 4 + 0x7C040400, // 0002 CALL R1 2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: can_show +********************************************************************/ +be_local_closure(Leds_can_show, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -1648,18 +1918,129 @@ be_local_closure(Leds_to_gamma, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str(apply_bri_gamma), - /* K1 */ be_nested_str(gamma), + /* K0 */ be_nested_str(call_native), + /* K1 */ be_const_int(3), }), - &be_const_str_to_gamma, + &be_const_str_can_show, &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ - 0x8C0C0100, // 0000 GETMET R3 R0 K0 - 0x5C140200, // 0001 MOVE R5 R1 - 0x5C180400, // 0002 MOVE R6 R2 - 0x881C0101, // 0003 GETMBR R7 R0 K1 - 0x7C0C0800, // 0004 CALL R3 4 - 0x80040600, // 0005 RET 1 R3 + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x580C0001, // 0001 LDCONST R3 K1 + 0x7C040400, // 0002 CALL R1 2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: assign_rmt +********************************************************************/ +be_local_closure(Leds_assign_rmt, /* name */ + be_nested_proto( + 9, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[17]) { /* constants */ + /* K0 */ be_const_class(be_class_Leds), + /* K1 */ be_const_int(0), + /* K2 */ be_nested_str(value_error), + /* K3 */ be_nested_str(invalid_X20GPIO_X20number), + /* K4 */ be_nested_str(global), + /* K5 */ be_nested_str(contains), + /* K6 */ be_nested_str(_rmt), + /* K7 */ be_nested_str(gpio), + /* K8 */ be_nested_str(MAX_RMT), + /* K9 */ be_const_int(1), + /* K10 */ be_nested_str(push), + /* K11 */ be_nested_str(stop_iteration), + /* K12 */ be_nested_str(pin_used), + /* K13 */ be_nested_str(WS2812), + /* K14 */ be_nested_str(pin), + /* K15 */ be_nested_str(internal_error), + /* K16 */ be_nested_str(no_X20more_X20RMT_X20channel_X20available), + }), + &be_const_str_assign_rmt, + &be_const_str_solidified, + ( &(const binstruction[72]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x60080009, // 0001 GETGBL R2 G9 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C080200, // 0003 CALL R2 1 + 0x5C000400, // 0004 MOVE R0 R2 + 0x14080101, // 0005 LT R2 R0 K1 + 0x780A0000, // 0006 JMPF R2 #0008 + 0xB0060503, // 0007 RAISE 1 K2 K3 + 0xA40A0800, // 0008 IMPORT R2 K4 + 0x4C0C0000, // 0009 LDNIL R3 + 0x8C100505, // 000A GETMET R4 R2 K5 + 0x58180006, // 000B LDCONST R6 K6 + 0x7C100400, // 000C CALL R4 2 + 0x74120021, // 000D JMPT R4 #0030 + 0x60100012, // 000E GETGBL R4 G18 + 0x7C100000, // 000F CALL R4 0 + 0x5C0C0800, // 0010 MOVE R3 R4 + 0x900A0C03, // 0011 SETMBR R2 K6 R3 + 0x60100010, // 0012 GETGBL R4 G16 + 0xB8160E00, // 0013 GETNGBL R5 K7 + 0x88140B08, // 0014 GETMBR R5 R5 K8 + 0x04140B09, // 0015 SUB R5 R5 K9 + 0x40160205, // 0016 CONNECT R5 K1 R5 + 0x7C100200, // 0017 CALL R4 1 + 0xA8020005, // 0018 EXBLK 0 #001F + 0x5C140800, // 0019 MOVE R5 R4 + 0x7C140000, // 001A CALL R5 0 + 0x8C18070A, // 001B GETMET R6 R3 K10 + 0x5421FFFE, // 001C LDINT R8 -1 + 0x7C180400, // 001D CALL R6 2 + 0x7001FFF9, // 001E JMP #0019 + 0x5810000B, // 001F LDCONST R4 K11 + 0xAC100200, // 0020 CATCH R4 1 0 + 0xB0080000, // 0021 RAISE 2 R0 R0 + 0xB8120E00, // 0022 GETNGBL R4 K7 + 0x8C10090C, // 0023 GETMET R4 R4 K12 + 0xB81A0E00, // 0024 GETNGBL R6 K7 + 0x88180D0D, // 0025 GETMBR R6 R6 K13 + 0x581C0001, // 0026 LDCONST R7 K1 + 0x7C100600, // 0027 CALL R4 3 + 0x78120006, // 0028 JMPF R4 #0030 + 0xB8120E00, // 0029 GETNGBL R4 K7 + 0x8C10090E, // 002A GETMET R4 R4 K14 + 0xB81A0E00, // 002B GETNGBL R6 K7 + 0x88180D0D, // 002C GETMBR R6 R6 K13 + 0x581C0001, // 002D LDCONST R7 K1 + 0x7C100600, // 002E CALL R4 3 + 0x980E0204, // 002F SETIDX R3 K1 R4 + 0x880C0506, // 0030 GETMBR R3 R2 K6 + 0x58100001, // 0031 LDCONST R4 K1 + 0x5415FFFE, // 0032 LDINT R5 -1 + 0xB81A0E00, // 0033 GETNGBL R6 K7 + 0x88180D08, // 0034 GETMBR R6 R6 K8 + 0x14180806, // 0035 LT R6 R4 R6 + 0x781A000A, // 0036 JMPF R6 #0042 + 0x94180604, // 0037 GETIDX R6 R3 R4 + 0x1C1C0C00, // 0038 EQ R7 R6 R0 + 0x781E0000, // 0039 JMPF R7 #003B + 0x80040800, // 003A RET 1 R4 + 0x141C0D01, // 003B LT R7 R6 K1 + 0x781E0002, // 003C JMPF R7 #0040 + 0x141C0B01, // 003D LT R7 R5 K1 + 0x781E0000, // 003E JMPF R7 #0040 + 0x5C140800, // 003F MOVE R5 R4 + 0x00100909, // 0040 ADD R4 R4 K9 + 0x7001FFF0, // 0041 JMP #0033 + 0x28180B01, // 0042 GE R6 R5 K1 + 0x781A0001, // 0043 JMPF R6 #0046 + 0x980C0A00, // 0044 SETIDX R3 R5 R0 + 0x80040A00, // 0045 RET 1 R5 + 0xB0061F10, // 0046 RAISE 1 K15 K16 + 0x80000000, // 0047 RET 0 }) ) ); @@ -1714,74 +2095,11 @@ be_local_closure(Leds_ctor, /* name */ /******************************************************************** -** Solidified function: dirty +** Solidified function: pixels_buffer ********************************************************************/ -be_local_closure(Leds_dirty, /* name */ +be_local_closure(Leds_pixels_buffer, /* name */ be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str(call_native), - }), - &be_const_str_dirty, - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x540E0004, // 0001 LDINT R3 5 - 0x7C040400, // 0002 CALL R1 2 - 0x80000000, // 0003 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: clear_to -********************************************************************/ -be_local_closure(Leds_clear_to, /* name */ - be_nested_proto( - 10, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str(call_native), - /* K1 */ be_nested_str(to_gamma), - }), - &be_const_str_clear_to, - &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x8C0C0100, // 0000 GETMET R3 R0 K0 - 0x54160008, // 0001 LDINT R5 9 - 0x8C180101, // 0002 GETMET R6 R0 K1 - 0x5C200200, // 0003 MOVE R8 R1 - 0x5C240400, // 0004 MOVE R9 R2 - 0x7C180600, // 0005 CALL R6 3 - 0x7C0C0600, // 0006 CALL R3 3 - 0x80000000, // 0007 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_pixel_color -********************************************************************/ -be_local_closure(Leds_get_pixel_color, /* name */ - be_nested_proto( - 6, /* nstack */ + 8, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -1789,192 +2107,36 @@ be_local_closure(Leds_get_pixel_color, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ + ( &(const bvalue[ 4]) { /* constants */ /* K0 */ be_nested_str(call_native), + /* K1 */ be_nested_str(pixel_size), + /* K2 */ be_nested_str(pixel_count), + /* K3 */ be_nested_str(_change_buffer), }), - &be_const_str_get_pixel_color, + &be_const_str_pixels_buffer, &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ + ( &(const binstruction[21]) { /* code */ 0x8C080100, // 0000 GETMET R2 R0 K0 - 0x5412000A, // 0001 LDINT R4 11 - 0x5C140200, // 0002 MOVE R5 R1 - 0x7C080600, // 0003 CALL R2 3 - 0x80040400, // 0004 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Leds_init, /* name */ - be_nested_proto( - 11, /* nstack */ - 5, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str(gamma), - /* K1 */ be_nested_str(leds), - /* K2 */ be_nested_str(valuer_error), - /* K3 */ be_nested_str(no_X20GPIO_X20specified_X20for_X20neopixelbus), - /* K4 */ be_nested_str(ctor), - /* K5 */ be_nested_str(_p), - /* K6 */ be_nested_str(internal_error), - /* K7 */ be_nested_str(couldn_X27t_X20not_X20initialize_X20noepixelbus), - /* K8 */ be_nested_str(begin), - }), - &be_const_str_init, - &be_const_str_solidified, - ( &(const binstruction[24]) { /* code */ - 0x50140200, // 0000 LDBOOL R5 1 0 - 0x90020005, // 0001 SETMBR R0 K0 R5 - 0x60140009, // 0002 GETGBL R5 G9 - 0x5C180200, // 0003 MOVE R6 R1 - 0x7C140200, // 0004 CALL R5 1 - 0x90020205, // 0005 SETMBR R0 K1 R5 - 0x4C140000, // 0006 LDNIL R5 - 0x1C140405, // 0007 EQ R5 R2 R5 - 0x78160000, // 0008 JMPF R5 #000A - 0xB0060503, // 0009 RAISE 1 K2 K3 - 0x8C140104, // 000A GETMET R5 R0 K4 - 0x881C0101, // 000B GETMBR R7 R0 K1 - 0x5C200400, // 000C MOVE R8 R2 - 0x5C240600, // 000D MOVE R9 R3 - 0x5C280800, // 000E MOVE R10 R4 - 0x7C140A00, // 000F CALL R5 5 - 0x88140105, // 0010 GETMBR R5 R0 K5 - 0x4C180000, // 0011 LDNIL R6 - 0x1C140A06, // 0012 EQ R5 R5 R6 - 0x78160000, // 0013 JMPF R5 #0015 - 0xB0060D07, // 0014 RAISE 1 K6 K7 - 0x8C140108, // 0015 GETMET R5 R0 K8 - 0x7C140200, // 0016 CALL R5 1 - 0x80000000, // 0017 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: begin -********************************************************************/ -be_local_closure(Leds_begin, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str(call_native), - /* K1 */ be_const_int(1), - }), - &be_const_str_begin, - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x580C0001, // 0001 LDCONST R3 K1 - 0x7C040400, // 0002 CALL R1 2 - 0x80000000, // 0003 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: pixel_offset -********************************************************************/ -be_local_closure(Leds_pixel_offset, /* name */ - be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_const_int(0), - }), - &be_const_str_pixel_offset, - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80060000, // 0000 RET 1 K0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: clear -********************************************************************/ -be_local_closure(Leds_clear, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str(clear_to), - /* K1 */ be_const_int(0), - /* K2 */ be_nested_str(show), - }), - &be_const_str_clear, - &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x580C0001, // 0001 LDCONST R3 K1 - 0x7C040400, // 0002 CALL R1 2 - 0x8C040102, // 0003 GETMET R1 R0 K2 - 0x7C040200, // 0004 CALL R1 1 - 0x80000000, // 0005 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: pixel_size -********************************************************************/ -be_local_closure(Leds_pixel_size, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str(call_native), - }), - &be_const_str_pixel_size, - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x540E0006, // 0001 LDINT R3 7 - 0x7C040400, // 0002 CALL R1 2 - 0x80040200, // 0003 RET 1 R1 + 0x54120005, // 0001 LDINT R4 6 + 0x7C080400, // 0002 CALL R2 2 + 0x4C0C0000, // 0003 LDNIL R3 + 0x1C0C0203, // 0004 EQ R3 R1 R3 + 0x780E0009, // 0005 JMPF R3 #0010 + 0x600C0015, // 0006 GETGBL R3 G21 + 0x5C100400, // 0007 MOVE R4 R2 + 0x8C140101, // 0008 GETMET R5 R0 K1 + 0x7C140200, // 0009 CALL R5 1 + 0x8C180102, // 000A GETMET R6 R0 K2 + 0x7C180200, // 000B CALL R6 1 + 0x08140A06, // 000C MUL R5 R5 R6 + 0x7C0C0400, // 000D CALL R3 2 + 0x80040600, // 000E RET 1 R3 + 0x70020003, // 000F JMP #0014 + 0x8C0C0303, // 0010 GETMET R3 R1 K3 + 0x5C140400, // 0011 MOVE R5 R2 + 0x7C0C0400, // 0012 CALL R3 2 + 0x80040200, // 0013 RET 1 R1 + 0x80000000, // 0014 RET 0 }) ) ); @@ -1986,32 +2148,37 @@ be_local_closure(Leds_pixel_size, /* name */ ********************************************************************/ extern const bclass be_class_Leds_ntv; be_local_class(Leds, - 2, + 3, &be_class_Leds_ntv, - be_nested_map(22, + be_nested_map(27, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key(show, -1), be_const_closure(Leds_show_closure) }, - { be_const_key(create_segment, -1), be_const_closure(Leds_create_segment_closure) }, - { be_const_key(assign_rmt, -1), be_const_static_closure(Leds_assign_rmt_closure) }, - { be_const_key(pixel_size, -1), be_const_closure(Leds_pixel_size_closure) }, - { be_const_key(matrix, 18), be_const_static_closure(Leds_matrix_closure) }, - { be_const_key(pixel_count, -1), be_const_closure(Leds_pixel_count_closure) }, - { be_const_key(ctor, -1), be_const_closure(Leds_ctor_closure) }, - { be_const_key(pixels_buffer, -1), be_const_closure(Leds_pixels_buffer_closure) }, - { be_const_key(set_pixel_color, -1), be_const_closure(Leds_set_pixel_color_closure) }, - { be_const_key(create_matrix, 15), be_const_closure(Leds_create_matrix_closure) }, - { be_const_key(is_dirty, 14), be_const_closure(Leds_is_dirty_closure) }, - { be_const_key(can_show, 6), be_const_closure(Leds_can_show_closure) }, - { be_const_key(to_gamma, -1), be_const_closure(Leds_to_gamma_closure) }, - { be_const_key(dirty, 19), be_const_closure(Leds_dirty_closure) }, - { be_const_key(begin, 12), be_const_closure(Leds_begin_closure) }, - { be_const_key(init, -1), be_const_closure(Leds_init_closure) }, - { be_const_key(gamma, 17), be_const_var(0) }, - { be_const_key(get_pixel_color, -1), be_const_closure(Leds_get_pixel_color_closure) }, - { be_const_key(clear_to, -1), be_const_closure(Leds_clear_to_closure) }, { be_const_key(leds, -1), be_const_var(1) }, + { be_const_key(create_segment, 25), be_const_closure(Leds_create_segment_closure) }, { be_const_key(clear, -1), be_const_closure(Leds_clear_closure) }, - { be_const_key(pixel_offset, 3), be_const_closure(Leds_pixel_offset_closure) }, + { be_const_key(begin, -1), be_const_closure(Leds_begin_closure) }, + { be_const_key(ctor, 7), be_const_closure(Leds_ctor_closure) }, + { be_const_key(assign_rmt, 12), be_const_static_closure(Leds_assign_rmt_closure) }, + { be_const_key(to_gamma, 8), be_const_closure(Leds_to_gamma_closure) }, + { be_const_key(dirty, -1), be_const_closure(Leds_dirty_closure) }, + { be_const_key(matrix, -1), be_const_static_closure(Leds_matrix_closure) }, + { be_const_key(pixel_offset, 2), be_const_closure(Leds_pixel_offset_closure) }, + { be_const_key(set_gamma, 4), be_const_closure(Leds_set_gamma_closure) }, + { be_const_key(get_pixel_color, -1), be_const_closure(Leds_get_pixel_color_closure) }, + { be_const_key(pixel_size, -1), be_const_closure(Leds_pixel_size_closure) }, + { be_const_key(create_matrix, -1), be_const_closure(Leds_create_matrix_closure) }, + { be_const_key(set_bri, 9), be_const_closure(Leds_set_bri_closure) }, + { be_const_key(clear_to, -1), be_const_closure(Leds_clear_to_closure) }, + { be_const_key(set_pixel_color, -1), be_const_closure(Leds_set_pixel_color_closure) }, + { be_const_key(gamma, -1), be_const_var(0) }, + { be_const_key(pixel_count, 17), be_const_closure(Leds_pixel_count_closure) }, + { be_const_key(get_bri, 13), be_const_closure(Leds_get_bri_closure) }, + { be_const_key(get_gamma, -1), be_const_closure(Leds_get_gamma_closure) }, + { be_const_key(bri, -1), be_const_var(2) }, + { be_const_key(is_dirty, -1), be_const_closure(Leds_is_dirty_closure) }, + { be_const_key(can_show, -1), be_const_closure(Leds_can_show_closure) }, + { be_const_key(init, 5), be_const_closure(Leds_init_closure) }, + { be_const_key(show, -1), be_const_closure(Leds_show_closure) }, + { be_const_key(pixels_buffer, -1), be_const_closure(Leds_pixels_buffer_closure) }, })), (bstring*) &be_const_str_Leds ); diff --git a/tasmota/berry/animate_demo/animate_demo_pulse.be b/tasmota/berry/animate_demo/animate_demo_pulse.be index 82c2d5ee3..0b60b0993 100644 --- a/tasmota/berry/animate_demo/animate_demo_pulse.be +++ b/tasmota/berry/animate_demo/animate_demo_pulse.be @@ -8,12 +8,13 @@ var duration = 10000 var strip = Leds(5 * 5, gpio.pin(gpio.WS2812, 0)) var anim = animate.core(strip) anim.set_back_color(0x2222AA) +anim.set_bri(60) # set brightness to 40% var pulse = animate.pulse(0xFF4444, 2, 1) var osc1 = animate.oscillator(-3, 26, 5000, animate.COSINE) osc1.set_cb(pulse, pulse.set_pos) # animate color of pulse -var palette = animate.palette(animate.PALETTE_RAINBOW_WHITE, 30000) +var palette = animate.palette(animate.PALETTE_STANDARD_VAL, 30000) palette.set_cb(pulse, pulse.set_color) anim.start() diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino index 9ac9c4c45..e75f5cbed 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino @@ -291,16 +291,16 @@ extern "C" { be_raise(vm, kTypeError, nullptr); } - static uint32_t ApplyBriGamma(uint32_t color_a /* 0xRRGGBB */, uint32_t bri /* 0..100 */, bool gamma) { + static uint32_t ApplyBriGamma(uint32_t color_a /* 0xRRGGBB */, uint32_t bri /* 0..255 */, bool gamma) { if (bri == 0) { return 0x000000; } // if bri is zero, short-cut uint32_t r = (color_a >> 16) & 0xFF; uint32_t g = (color_a >> 8) & 0xFF; uint32_t b = (color_a ) & 0xFF; - if (bri < 100) { // apply bri - r = changeUIntScale(bri, 0, 100, 0, r); - g = changeUIntScale(bri, 0, 100, 0, g); - b = changeUIntScale(bri, 0, 100, 0, b); + if (bri < 255) { // apply bri + r = changeUIntScale(bri, 0, 255, 0, r); + g = changeUIntScale(bri, 0, 255, 0, g); + b = changeUIntScale(bri, 0, 255, 0, b); } if (gamma) { // apply gamma @@ -312,23 +312,23 @@ extern "C" { return rgb; } - // Leds.apply_bri_gamma(color_rgb:int (0xRRGGBB) [bri:int (0..100), gamma:bool]) -> color:int (0xRRGGBB) + // Leds.apply_bri_gamma(color_rgb:int (0xRRGGBB) [bri:int (0..255), gamma:bool]) -> color:int (0xRRGGBB) // int32_t be_leds_apply_bri_gamma(bvm *vm); int32_t be_leds_apply_bri_gamma(bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments if (top >= 1 && be_isint(vm, 1)) { uint32_t color_a = be_toint(vm, 1); - uint32_t bri = 100; + uint32_t bri255 = 255; if (top >= 2 && be_isint(vm, 2)) { - bri = be_toint(vm, 2); + bri255 = be_toint(vm, 2); } bool gamma = false; if (top >= 3) { gamma = be_tobool(vm, 3); } - uint32_t rgb = ApplyBriGamma(color_a, bri, gamma); + uint32_t rgb = ApplyBriGamma(color_a, bri255, gamma); be_pushint(vm, rgb); be_return(vm); @@ -453,9 +453,9 @@ extern "C" { size_t dest_len = 0; uint8_t * dest_buf = (uint8_t*) be_tobytes(vm, 2, &dest_len); - uint32_t bri = 100; + uint32_t bri255 = 255; if (top >= 3 && be_isint(vm, 3)) { - bri = be_toint(vm, 3); + bri255 = be_toint(vm, 3); } bool gamma = false; if (top >= 4 && be_isbool(vm, 4)) { @@ -466,7 +466,7 @@ extern "C" { if (pixels_count > dest_len / 3) { pixels_count = dest_len / 3; } if (pixels_count > 0) { for (size_t i = 0; i < pixels_count; i++) { - uint32_t src_argb = ApplyBriGamma(src_buf[i], bri, gamma); + uint32_t src_argb = ApplyBriGamma(src_buf[i], bri255, gamma); uint32_t src_r = (src_argb >> 16) & 0xFF; uint32_t src_g = (src_argb >> 8) & 0xFF; uint32_t src_b = (src_argb ) & 0xFF; From 18e5f53e971dcab1a15ab74b6c9762c7b791a9ea Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 22 Dec 2023 19:40:47 +0100 Subject: [PATCH 036/303] Add new board setting "download speed" to esp32x boards json (#20291) * add download_speed setting * add "download speed" * add / change up- download speed --- boards/esp32-fix.json | 3 +++ boards/esp32.json | 3 +++ boards/esp32_solo1.json | 3 +++ boards/esp32c2.json | 3 +++ boards/esp32c2_2M.json | 3 +++ boards/esp32c3.json | 3 +++ boards/esp32c3cdc.json | 5 ++++- boards/esp32c6.json | 3 +++ boards/esp32c6cdc.json | 5 ++++- boards/esp32s2.json | 3 +++ boards/esp32s2cdc.json | 5 ++++- boards/esp32s3-opi_opi.json | 3 +++ boards/esp32s3-qio_opi.json | 3 +++ boards/esp32s3-qio_qspi.json | 3 +++ boards/esp32s3cdc-opi_opi.json | 5 ++++- boards/esp32s3cdc-qio_opi.json | 5 ++++- boards/esp32s3cdc-qio_qspi.json | 5 ++++- pio-tools/custom_target.py | 11 +++++++---- 18 files changed, 64 insertions(+), 10 deletions(-) diff --git a/boards/esp32-fix.json b/boards/esp32-fix.json index 8287019b8..73cf149fa 100644 --- a/boards/esp32-fix.json +++ b/boards/esp32-fix.json @@ -41,6 +41,9 @@ "require_upload_port": true, "speed": 460800 }, + "download": { + "speed": 230400 + }, "url": "https://en.wikipedia.org/wiki/ESP32", "vendor": "Espressif" } diff --git a/boards/esp32.json b/boards/esp32.json index 4dd2a3602..10c117cd7 100644 --- a/boards/esp32.json +++ b/boards/esp32.json @@ -41,6 +41,9 @@ "require_upload_port": true, "speed": 460800 }, + "download": { + "speed": 230400 + }, "url": "https://en.wikipedia.org/wiki/ESP32", "vendor": "Espressif" } diff --git a/boards/esp32_solo1.json b/boards/esp32_solo1.json index f3d9913b0..b80a58156 100644 --- a/boards/esp32_solo1.json +++ b/boards/esp32_solo1.json @@ -41,6 +41,9 @@ "require_upload_port": true, "speed": 460800 }, + "download": { + "speed": 230400 + }, "url": "https://en.wikipedia.org/wiki/ESP32", "vendor": "Espressif" } diff --git a/boards/esp32c2.json b/boards/esp32c2.json index cabab4cb4..ea5cbae2c 100644 --- a/boards/esp32c2.json +++ b/boards/esp32c2.json @@ -39,6 +39,9 @@ "require_upload_port": true, "speed": 460800 }, + "download": { + "speed": 230400 + }, "url": "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitc-1/index.html", "vendor": "Espressif" } diff --git a/boards/esp32c2_2M.json b/boards/esp32c2_2M.json index 969ff519c..fbffa167c 100644 --- a/boards/esp32c2_2M.json +++ b/boards/esp32c2_2M.json @@ -39,6 +39,9 @@ "require_upload_port": true, "speed": 460800 }, + "download": { + "speed": 230400 + }, "url": "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitc-1/index.html", "vendor": "Espressif" } diff --git a/boards/esp32c3.json b/boards/esp32c3.json index 2bb2f7660..6a49ba922 100644 --- a/boards/esp32c3.json +++ b/boards/esp32c3.json @@ -39,6 +39,9 @@ "require_upload_port": true, "speed": 460800 }, + "download": { + "speed": 230400 + }, "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitm-1.html", "vendor": "Espressif" } diff --git a/boards/esp32c3cdc.json b/boards/esp32c3cdc.json index 8e46134b3..7ee0326f0 100644 --- a/boards/esp32c3cdc.json +++ b/boards/esp32c3cdc.json @@ -41,7 +41,10 @@ "maximum_ram_size": 327680, "maximum_size": 4194304, "require_upload_port": true, - "speed": 460800 + "speed": 2000000 + }, + "download": { + "speed": 2000000 }, "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitm-1.html", "vendor": "Espressif" diff --git a/boards/esp32c6.json b/boards/esp32c6.json index 76e7620db..68feaec6e 100644 --- a/boards/esp32c6.json +++ b/boards/esp32c6.json @@ -39,6 +39,9 @@ "require_upload_port": true, "speed": 460800 }, + "download": { + "speed": 230400 + }, "url": "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitc-1/index.html", "vendor": "Espressif" } diff --git a/boards/esp32c6cdc.json b/boards/esp32c6cdc.json index eb8a6ffbb..9cde9e62b 100644 --- a/boards/esp32c6cdc.json +++ b/boards/esp32c6cdc.json @@ -41,7 +41,10 @@ "maximum_ram_size": 327680, "maximum_size": 4194304, "require_upload_port": true, - "speed": 460800 + "speed": 2000000 + }, + "download": { + "speed": 2000000 }, "url": "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitc-1/index.html", "vendor": "Espressif" diff --git a/boards/esp32s2.json b/boards/esp32s2.json index aa9efca8b..18bd9200a 100644 --- a/boards/esp32s2.json +++ b/boards/esp32s2.json @@ -38,6 +38,9 @@ "require_upload_port": true, "speed": 460800 }, + "download": { + "speed": 230400 + }, "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html", "vendor": "Espressif" } diff --git a/boards/esp32s2cdc.json b/boards/esp32s2cdc.json index f9a302699..c379be423 100644 --- a/boards/esp32s2cdc.json +++ b/boards/esp32s2cdc.json @@ -37,7 +37,10 @@ "maximum_size": 4194304, "require_upload_port": true, "before_reset": "usb_reset", - "speed": 460800 + "speed": 2000000 + }, + "download": { + "speed": 2000000 }, "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html", "vendor": "Espressif" diff --git a/boards/esp32s3-opi_opi.json b/boards/esp32s3-opi_opi.json index aa7e5db2a..92803a838 100644 --- a/boards/esp32s3-opi_opi.json +++ b/boards/esp32s3-opi_opi.json @@ -41,6 +41,9 @@ "require_upload_port": true, "speed": 460800 }, + "download": { + "speed": 230400 + }, "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/", "vendor": "Espressif" } \ No newline at end of file diff --git a/boards/esp32s3-qio_opi.json b/boards/esp32s3-qio_opi.json index 4f2a06c47..614831574 100644 --- a/boards/esp32s3-qio_opi.json +++ b/boards/esp32s3-qio_opi.json @@ -41,6 +41,9 @@ "require_upload_port": true, "speed": 460800 }, + "download": { + "speed": 230400 + }, "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/", "vendor": "Espressif" } diff --git a/boards/esp32s3-qio_qspi.json b/boards/esp32s3-qio_qspi.json index 42b20a4bc..9b11a31b0 100644 --- a/boards/esp32s3-qio_qspi.json +++ b/boards/esp32s3-qio_qspi.json @@ -41,6 +41,9 @@ "require_upload_port": true, "speed": 460800 }, + "download": { + "speed": 230400 + }, "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/", "vendor": "Espressif" } diff --git a/boards/esp32s3cdc-opi_opi.json b/boards/esp32s3cdc-opi_opi.json index a5992333c..684cba031 100644 --- a/boards/esp32s3cdc-opi_opi.json +++ b/boards/esp32s3cdc-opi_opi.json @@ -49,7 +49,10 @@ "maximum_ram_size": 327680, "maximum_size": 4194304, "require_upload_port": true, - "speed": 460800 + "speed": 2000000 + }, + "download": { + "speed": 2000000 }, "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/", "vendor": "Espressif" diff --git a/boards/esp32s3cdc-qio_opi.json b/boards/esp32s3cdc-qio_opi.json index 46ed77fca..46b363266 100644 --- a/boards/esp32s3cdc-qio_opi.json +++ b/boards/esp32s3cdc-qio_opi.json @@ -49,7 +49,10 @@ "maximum_ram_size": 327680, "maximum_size": 4194304, "require_upload_port": true, - "speed": 460800 + "speed": 2000000 + }, + "download": { + "speed": 2000000 }, "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/", "vendor": "Espressif" diff --git a/boards/esp32s3cdc-qio_qspi.json b/boards/esp32s3cdc-qio_qspi.json index 7e80448e3..fa90e8509 100644 --- a/boards/esp32s3cdc-qio_qspi.json +++ b/boards/esp32s3cdc-qio_qspi.json @@ -49,7 +49,10 @@ "maximum_ram_size": 327680, "maximum_size": 4194304, "require_upload_port": true, - "speed": 460800 + "speed": 2000000 + }, + "download": { + "speed": 2000000 }, "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/", "vendor": "Espressif" diff --git a/pio-tools/custom_target.py b/pio-tools/custom_target.py index a11d6a3ae..9623105aa 100644 --- a/pio-tools/custom_target.py +++ b/pio-tools/custom_target.py @@ -186,6 +186,7 @@ def parse_partition_table(content): def get_partition_table(): esptoolpy = join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py") upload_port = join(env.get("UPLOAD_PORT", "none")) + download_speed = join(str(board.get("download.speed", "115200"))) if "none" in upload_port: env.AutodetectUploadPort() upload_port = join(env.get("UPLOAD_PORT", "none")) @@ -193,7 +194,7 @@ def get_partition_table(): esptoolpy_flags = [ "--chip", mcu, "--port", upload_port, - "--baud", env.subst("$UPLOAD_SPEED"), + "--baud", download_speed, "--before", "default_reset", "--after", "hard_reset", "read_flash", @@ -246,6 +247,7 @@ def download_fs(fs_info: FSInfo): print(fs_info) esptoolpy = join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py") upload_port = join(env.get("UPLOAD_PORT", "none")) + download_speed = join(str(board.get("download.speed", "115200"))) if "none" in upload_port: env.AutodetectUploadPort() upload_port = join(env.get("UPLOAD_PORT", "none")) @@ -253,7 +255,7 @@ def download_fs(fs_info: FSInfo): esptoolpy_flags = [ "--chip", mcu, "--port", upload_port, - "--baud", env.subst("$UPLOAD_SPEED"), + "--baud", download_speed, "--before", "default_reset", "--after", "hard_reset", "read_flash", @@ -278,7 +280,7 @@ def unpack_fs(fs_info: FSInfo, downloaded_file: str): unpack_dir = env.GetProjectOption("custom_unpack_dir", "unpacked_fs") #unpack_dir = "unpacked_fs" if not os.path.exists(downloaded_file): - print(f"ERROR: {downloaded_file} with filesystem not found, maybe download failed due to upload_speed setting being too high.") + print(f"ERROR: {downloaded_file} with filesystem not found, maybe download failed due to download_speed setting being too high.") assert(0) try: if os.path.exists(unpack_dir): @@ -305,7 +307,7 @@ def display_fs(extracted_dir): print("Extracted " + str(file_count) + " file(s) from filesystem.") def command_download_fs(*args, **kwargs): - print("Entrypoint") + #print("Entrypoint") #print(env.Dump()) get_partition_table() info = get_fs_type_start_and_length() @@ -356,3 +358,4 @@ env.AddCustomTarget( title="Flash factory", description="Flash factory firmware" ) + From fb90a34b0a82a7399eaca7f5d07b4b42732de764 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 23 Dec 2023 10:54:22 +0100 Subject: [PATCH 037/303] Matter support for password for remote Tasmota devices (#20296) --- .../src/embedded/Matter_HTTP_async.be | 28 +- .../solidify/solidified_Matter_HTTP_async.h | 1424 +++++++++-------- 2 files changed, 764 insertions(+), 688 deletions(-) diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_HTTP_async.be b/lib/libesp32/berry_matter/src/embedded/Matter_HTTP_async.be index 3d9abbf95..3b2947664 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_HTTP_async.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_HTTP_async.be @@ -31,6 +31,7 @@ class Matter_HTTP_async : Matter_TCP_async # var tcp # instance of tcpclientasync # var time_start # timestamp when starting connection # var tcp_connected # is tcp connected, true/false/nil (nil is in-progress) + var auth # web authentication string (Basic Auth) or `nil`, in format `user:password` as bade64 var cmd # GET url command var response # aggrated response var response_offset # offset to parse in response @@ -42,8 +43,16 @@ class Matter_HTTP_async : Matter_TCP_async var phase # parsing phase: 0/ status line, 1/ headers, 2/ payload chunked var is_chunked # true if the content is chunked var chunk_size # nil or int, size of the current chunk - static var HTTP_GET = "GET %s HTTP/1.1\r\nHost %s:%s\r\nConnection: close\r\n\r\n" # see https://stackoverflow.com/questions/6686261/what-at-the-bare-minimum-is-required-for-an-http-request + static var HTTP_GET = "GET %s HTTP/1.1\r\n" # see https://stackoverflow.com/questions/6686261/what-at-the-bare-minimum-is-required-for-an-http-request + "Host %s:%s\r\n" + "Connection: close\r\n" + "\r\n" + static var HTTP_GET_AUTH = "GET %s HTTP/1.1\r\n" # same with auth + "Host %s:%s\r\n" + "Authorization: Basic %s\r\n" + "Connection: close\r\n" + "\r\n" static var HTTP_STATUS_REGEX = "HTTP/1\\.[0-1] (\\d+) .*?\r\n" # extract stattus code from first line static var HTTP_HEADER_REGEX = "([A-Za-z0-9-]+): (.*?)\r\n" # extract a header with its 2 parts static var HTTP_BODY_REGEX = "\r\n" # end of headers @@ -53,6 +62,15 @@ class Matter_HTTP_async : Matter_TCP_async ############################################################# # init def init(addr, port, timeout, fastloop) + # extract auth from add first + import string + addr = str(addr) # force string + var x = string.find(addr, "@") + if x >= 0 + self.auth = bytes().fromstring(addr[0 .. x-1]).tob64() + addr = addr[x+1 .. ] + end + # `addr` is cleaned from authentication information super(self).init(addr, port, timeout, fastloop) self.compile_re() end @@ -253,7 +271,13 @@ class Matter_HTTP_async : Matter_TCP_async addr = "[" + addr + "]" # IPv6 must be enclosed in brakets end - var req = format(self.HTTP_GET, self.cmd, addr, self.port) + var req + if (self.auth == nil) + req = format(self.HTTP_GET, self.cmd, addr, self.port) + else + # use AUTH information + req = format(self.HTTP_GET_AUTH, self.cmd, addr, self.port, self.auth) + end var ret = self.write(req) if ret != size(req) # print("Could not send","size=",size(req),"ret=",ret) diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_HTTP_async.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_HTTP_async.h index 49b05e0a9..d55db99f7 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_HTTP_async.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_HTTP_async.h @@ -6,375 +6,6 @@ extern const bclass be_class_Matter_HTTP_async; -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Matter_HTTP_async_init, /* name */ - be_nested_proto( - 11, /* nstack */ - 5, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(init), - /* K1 */ be_nested_str_weak(compile_re), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x60140003, // 0000 GETGBL R5 G3 - 0x5C180000, // 0001 MOVE R6 R0 - 0x7C140200, // 0002 CALL R5 1 - 0x8C140B00, // 0003 GETMET R5 R5 K0 - 0x5C1C0200, // 0004 MOVE R7 R1 - 0x5C200400, // 0005 MOVE R8 R2 - 0x5C240600, // 0006 MOVE R9 R3 - 0x5C280800, // 0007 MOVE R10 R4 - 0x7C140A00, // 0008 CALL R5 5 - 0x8C140101, // 0009 GETMET R5 R0 K1 - 0x7C140200, // 000A CALL R5 1 - 0x80000000, // 000B RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: event_http_failed -********************************************************************/ -be_local_closure(Matter_HTTP_async_event_http_failed, /* name */ - be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(event_http_failed), - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: compile_re -********************************************************************/ -be_local_closure(Matter_HTTP_async_compile_re, /* name */ - be_nested_proto( - 6, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[12]) { /* constants */ - /* K0 */ be_nested_str_weak(re), - /* K1 */ be_nested_str_weak(global), - /* K2 */ be_nested_str_weak(contains), - /* K3 */ be_nested_str_weak(_re_http_status), - /* K4 */ be_nested_str_weak(compile), - /* K5 */ be_nested_str_weak(HTTP_STATUS_REGEX), - /* K6 */ be_nested_str_weak(_re_http_header), - /* K7 */ be_nested_str_weak(HTTP_HEADER_REGEX), - /* K8 */ be_nested_str_weak(_re_http_body), - /* K9 */ be_nested_str_weak(HTTP_BODY_REGEX), - /* K10 */ be_nested_str_weak(_re_http_chunk), - /* K11 */ be_nested_str_weak(HTTP_CHUNK_REGEX), - }), - be_str_weak(compile_re), - &be_const_str_solidified, - ( &(const binstruction[27]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0xB80A0200, // 0001 GETNGBL R2 K1 - 0x8C080502, // 0002 GETMET R2 R2 K2 - 0x58100003, // 0003 LDCONST R4 K3 - 0x7C080400, // 0004 CALL R2 2 - 0x740A0013, // 0005 JMPT R2 #001A - 0xB80A0200, // 0006 GETNGBL R2 K1 - 0x8C0C0304, // 0007 GETMET R3 R1 K4 - 0x88140105, // 0008 GETMBR R5 R0 K5 - 0x7C0C0400, // 0009 CALL R3 2 - 0x900A0603, // 000A SETMBR R2 K3 R3 - 0xB80A0200, // 000B GETNGBL R2 K1 - 0x8C0C0304, // 000C GETMET R3 R1 K4 - 0x88140107, // 000D GETMBR R5 R0 K7 - 0x7C0C0400, // 000E CALL R3 2 - 0x900A0C03, // 000F SETMBR R2 K6 R3 - 0xB80A0200, // 0010 GETNGBL R2 K1 - 0x8C0C0304, // 0011 GETMET R3 R1 K4 - 0x88140109, // 0012 GETMBR R5 R0 K9 - 0x7C0C0400, // 0013 CALL R3 2 - 0x900A1003, // 0014 SETMBR R2 K8 R3 - 0xB80A0200, // 0015 GETNGBL R2 K1 - 0x8C0C0304, // 0016 GETMET R3 R1 K4 - 0x8814010B, // 0017 GETMBR R5 R0 K11 - 0x7C0C0400, // 0018 CALL R3 2 - 0x900A1403, // 0019 SETMBR R2 K10 R3 - 0x80000000, // 001A RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: parse_http_response -********************************************************************/ -be_local_closure(Matter_HTTP_async_parse_http_response, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_nested_str_weak(phase), - /* K1 */ be_const_int(0), - /* K2 */ be_nested_str_weak(parse_http_status_line), - /* K3 */ be_const_int(1), - /* K4 */ be_nested_str_weak(parse_http_headers), - /* K5 */ be_const_int(2), - /* K6 */ be_nested_str_weak(parse_http_payload), - }), - be_str_weak(parse_http_response), - &be_const_str_solidified, - ( &(const binstruction[18]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x1C040301, // 0001 EQ R1 R1 K1 - 0x78060002, // 0002 JMPF R1 #0006 - 0x8C040102, // 0003 GETMET R1 R0 K2 - 0x7C040200, // 0004 CALL R1 1 - 0x7002000A, // 0005 JMP #0011 - 0x88040100, // 0006 GETMBR R1 R0 K0 - 0x1C040303, // 0007 EQ R1 R1 K3 - 0x78060002, // 0008 JMPF R1 #000C - 0x8C040104, // 0009 GETMET R1 R0 K4 - 0x7C040200, // 000A CALL R1 1 - 0x70020004, // 000B JMP #0011 - 0x88040100, // 000C GETMBR R1 R0 K0 - 0x1C040305, // 000D EQ R1 R1 K5 - 0x78060001, // 000E JMPF R1 #0011 - 0x8C040106, // 000F GETMET R1 R0 K6 - 0x7C040200, // 0010 CALL R1 1 - 0x80000000, // 0011 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: event_available -********************************************************************/ -be_local_closure(Matter_HTTP_async_event_available, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(receive), - }), - be_str_weak(event_available), - &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0x80000000, // 0002 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: receive -********************************************************************/ -be_local_closure(Matter_HTTP_async_receive, /* name */ - be_nested_proto( - 6, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[15]) { /* constants */ - /* K0 */ be_nested_str_weak(tcp_connected), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(millis), - /* K3 */ be_nested_str_weak(time_start), - /* K4 */ be_nested_str_weak(timeout), - /* K5 */ be_nested_str_weak(status), - /* K6 */ be_nested_str_weak(close), - /* K7 */ be_nested_str_weak(http_status), - /* K8 */ be_nested_str_weak(event_http_timeout), - /* K9 */ be_nested_str_weak(tcp), - /* K10 */ be_nested_str_weak(available), - /* K11 */ be_const_int(0), - /* K12 */ be_nested_str_weak(read), - /* K13 */ be_nested_str_weak(response), - /* K14 */ be_nested_str_weak(parse_http_response), - }), - be_str_weak(receive), - &be_const_str_solidified, - ( &(const binstruction[48]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x50080200, // 0001 LDBOOL R2 1 0 - 0x20040202, // 0002 NE R1 R1 R2 - 0x78060000, // 0003 JMPF R1 #0005 - 0x80000200, // 0004 RET 0 - 0xB8060200, // 0005 GETNGBL R1 K1 - 0x8C040302, // 0006 GETMET R1 R1 K2 - 0x7C040200, // 0007 CALL R1 1 - 0x88080103, // 0008 GETMBR R2 R0 K3 - 0x04040202, // 0009 SUB R1 R1 R2 - 0x88080104, // 000A GETMBR R2 R0 K4 - 0x24040202, // 000B GT R1 R1 R2 - 0x78060008, // 000C JMPF R1 #0016 - 0x5405FFFC, // 000D LDINT R1 -3 - 0x90020A01, // 000E SETMBR R0 K5 R1 - 0x8C040106, // 000F GETMET R1 R0 K6 - 0x7C040200, // 0010 CALL R1 1 - 0x5405FFFD, // 0011 LDINT R1 -2 - 0x90020E01, // 0012 SETMBR R0 K7 R1 - 0x8C040108, // 0013 GETMET R1 R0 K8 - 0x7C040200, // 0014 CALL R1 1 - 0x70020018, // 0015 JMP #002F - 0x88040109, // 0016 GETMBR R1 R0 K9 - 0x8C04030A, // 0017 GETMET R1 R1 K10 - 0x7C040200, // 0018 CALL R1 1 - 0x5808000B, // 0019 LDCONST R2 K11 - 0x240C030B, // 001A GT R3 R1 K11 - 0x780E000E, // 001B JMPF R3 #002B - 0x880C0109, // 001C GETMBR R3 R0 K9 - 0x8C0C070C, // 001D GETMET R3 R3 K12 - 0x7C0C0200, // 001E CALL R3 1 - 0x8810010D, // 001F GETMBR R4 R0 K13 - 0x00100803, // 0020 ADD R4 R4 R3 - 0x90021A04, // 0021 SETMBR R0 K13 R4 - 0x6010000C, // 0022 GETGBL R4 G12 - 0x5C140600, // 0023 MOVE R5 R3 - 0x7C100200, // 0024 CALL R4 1 - 0x00080404, // 0025 ADD R2 R2 R4 - 0x88100109, // 0026 GETMBR R4 R0 K9 - 0x8C10090A, // 0027 GETMET R4 R4 K10 - 0x7C100200, // 0028 CALL R4 1 - 0x5C040800, // 0029 MOVE R1 R4 - 0x7001FFEE, // 002A JMP #001A - 0x240C050B, // 002B GT R3 R2 K11 - 0x780E0001, // 002C JMPF R3 #002F - 0x8C0C010E, // 002D GETMET R3 R0 K14 - 0x7C0C0200, // 002E CALL R3 1 - 0x80000000, // 002F RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: reset -********************************************************************/ -be_local_closure(Matter_HTTP_async_reset, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ - /* K0 */ be_nested_str_weak(reset), - /* K1 */ be_nested_str_weak(cmd), - /* K2 */ be_nested_str_weak(response), - /* K3 */ be_nested_str_weak(response_offset), - /* K4 */ be_const_int(0), - /* K5 */ be_nested_str_weak(payload), - /* K6 */ be_nested_str_weak(), - /* K7 */ be_nested_str_weak(phase), - /* K8 */ be_nested_str_weak(http_status), - /* K9 */ be_nested_str_weak(is_chunked), - /* K10 */ be_nested_str_weak(chunk_size), - }), - be_str_weak(reset), - &be_const_str_solidified, - ( &(const binstruction[18]) { /* code */ - 0x60040003, // 0000 GETGBL R1 G3 - 0x5C080000, // 0001 MOVE R2 R0 - 0x7C040200, // 0002 CALL R1 1 - 0x8C040300, // 0003 GETMET R1 R1 K0 - 0x7C040200, // 0004 CALL R1 1 - 0x4C040000, // 0005 LDNIL R1 - 0x90020201, // 0006 SETMBR R0 K1 R1 - 0x4C040000, // 0007 LDNIL R1 - 0x90020401, // 0008 SETMBR R0 K2 R1 - 0x90020704, // 0009 SETMBR R0 K3 K4 - 0x90020B06, // 000A SETMBR R0 K5 K6 - 0x90020F04, // 000B SETMBR R0 K7 K4 - 0x90021104, // 000C SETMBR R0 K8 K4 - 0x50040000, // 000D LDBOOL R1 0 0 - 0x90021201, // 000E SETMBR R0 K9 R1 - 0x4C040000, // 000F LDNIL R1 - 0x90021401, // 0010 SETMBR R0 K10 R1 - 0x80000000, // 0011 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: event_http_status_code -********************************************************************/ -be_local_closure(Matter_HTTP_async_event_http_status_code, /* name */ - be_nested_proto( - 3, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(status_code), - }), - be_str_weak(event_http_status_code), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: parse_http_payload ********************************************************************/ @@ -497,149 +128,6 @@ be_local_closure(Matter_HTTP_async_parse_http_payload, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: send_http -********************************************************************/ -be_local_closure(Matter_HTTP_async_send_http, /* name */ - be_nested_proto( - 8, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[17]) { /* constants */ - /* K0 */ be_nested_str_weak(string), - /* K1 */ be_nested_str_weak(response), - /* K2 */ be_nested_str_weak(), - /* K3 */ be_nested_str_weak(addr), - /* K4 */ be_nested_str_weak(find), - /* K5 */ be_nested_str_weak(_X3A), - /* K6 */ be_const_int(0), - /* K7 */ be_nested_str_weak(_X5B), - /* K8 */ be_nested_str_weak(_X5D), - /* K9 */ be_nested_str_weak(HTTP_GET), - /* K10 */ be_nested_str_weak(cmd), - /* K11 */ be_nested_str_weak(port), - /* K12 */ be_nested_str_weak(write), - /* K13 */ be_nested_str_weak(close), - /* K14 */ be_nested_str_weak(status), - /* K15 */ be_nested_str_weak(http_status), - /* K16 */ be_nested_str_weak(event_http_failed), - }), - be_str_weak(send_http), - &be_const_str_solidified, - ( &(const binstruction[35]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0x90020302, // 0001 SETMBR R0 K1 K2 - 0x88080103, // 0002 GETMBR R2 R0 K3 - 0x8C0C0304, // 0003 GETMET R3 R1 K4 - 0x5C140400, // 0004 MOVE R5 R2 - 0x58180005, // 0005 LDCONST R6 K5 - 0x7C0C0600, // 0006 CALL R3 3 - 0x280C0706, // 0007 GE R3 R3 K6 - 0x780E0002, // 0008 JMPF R3 #000C - 0x000E0E02, // 0009 ADD R3 K7 R2 - 0x000C0708, // 000A ADD R3 R3 K8 - 0x5C080600, // 000B MOVE R2 R3 - 0x600C0018, // 000C GETGBL R3 G24 - 0x88100109, // 000D GETMBR R4 R0 K9 - 0x8814010A, // 000E GETMBR R5 R0 K10 - 0x5C180400, // 000F MOVE R6 R2 - 0x881C010B, // 0010 GETMBR R7 R0 K11 - 0x7C0C0800, // 0011 CALL R3 4 - 0x8C10010C, // 0012 GETMET R4 R0 K12 - 0x5C180600, // 0013 MOVE R6 R3 - 0x7C100400, // 0014 CALL R4 2 - 0x6014000C, // 0015 GETGBL R5 G12 - 0x5C180600, // 0016 MOVE R6 R3 - 0x7C140200, // 0017 CALL R5 1 - 0x20140805, // 0018 NE R5 R4 R5 - 0x78160007, // 0019 JMPF R5 #0022 - 0x8C14010D, // 001A GETMET R5 R0 K13 - 0x7C140200, // 001B CALL R5 1 - 0x5415FFFB, // 001C LDINT R5 -4 - 0x90021C05, // 001D SETMBR R0 K14 R5 - 0x5415FFFE, // 001E LDINT R5 -1 - 0x90021E05, // 001F SETMBR R0 K15 R5 - 0x8C140110, // 0020 GETMET R5 R0 K16 - 0x7C140200, // 0021 CALL R5 1 - 0x80000000, // 0022 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: begin_sync -********************************************************************/ -be_local_closure(Matter_HTTP_async_begin_sync, /* name */ - be_nested_proto( - 10, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[10]) { /* constants */ - /* K0 */ be_nested_str_weak(timeout), - /* K1 */ be_nested_str_weak(set_timeout), - /* K2 */ be_nested_str_weak(SPINLOCK), - /* K3 */ be_nested_str_weak(begin), - /* K4 */ be_nested_str_weak(http_status), - /* K5 */ be_const_int(0), - /* K6 */ be_nested_str_weak(loop), - /* K7 */ be_nested_str_weak(tasmota), - /* K8 */ be_nested_str_weak(delay), - /* K9 */ be_nested_str_weak(payload), - }), - be_str_weak(begin_sync), - &be_const_str_solidified, - ( &(const binstruction[33]) { /* code */ - 0x880C0100, // 0000 GETMBR R3 R0 K0 - 0x4C100000, // 0001 LDNIL R4 - 0x20100404, // 0002 NE R4 R2 R4 - 0x78120002, // 0003 JMPF R4 #0007 - 0x8C100101, // 0004 GETMET R4 R0 K1 - 0x5C180400, // 0005 MOVE R6 R2 - 0x7C100400, // 0006 CALL R4 2 - 0x4C100000, // 0007 LDNIL R4 - 0x88140102, // 0008 GETMBR R5 R0 K2 - 0x8C180103, // 0009 GETMET R6 R0 K3 - 0x5C200200, // 000A MOVE R8 R1 - 0x7C180400, // 000B CALL R6 2 - 0x781A0009, // 000C JMPF R6 #0017 - 0x881C0104, // 000D GETMBR R7 R0 K4 - 0x1C1C0F05, // 000E EQ R7 R7 K5 - 0x781E0006, // 000F JMPF R7 #0017 - 0x8C1C0106, // 0010 GETMET R7 R0 K6 - 0x7C1C0200, // 0011 CALL R7 1 - 0xB81E0E00, // 0012 GETNGBL R7 K7 - 0x8C1C0F08, // 0013 GETMET R7 R7 K8 - 0x5C240A00, // 0014 MOVE R9 R5 - 0x7C1C0400, // 0015 CALL R7 2 - 0x7001FFF5, // 0016 JMP #000D - 0x8C1C0101, // 0017 GETMET R7 R0 K1 - 0x5C240600, // 0018 MOVE R9 R3 - 0x7C1C0400, // 0019 CALL R7 2 - 0x881C0104, // 001A GETMBR R7 R0 K4 - 0x241C0F05, // 001B GT R7 R7 K5 - 0x781E0001, // 001C JMPF R7 #001F - 0x881C0109, // 001D GETMBR R7 R0 K9 - 0x70020000, // 001E JMP #0020 - 0x4C1C0000, // 001F LDNIL R7 - 0x80040E00, // 0020 RET 1 R7 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: event_http_finished ********************************************************************/ @@ -665,30 +153,47 @@ be_local_closure(Matter_HTTP_async_event_http_finished, /* name */ /******************************************************************** -** Solidified function: event_timeout +** Solidified function: event_http_header ********************************************************************/ -be_local_closure(Matter_HTTP_async_event_timeout, /* name */ +be_local_closure(Matter_HTTP_async_event_http_header, /* name */ be_nested_proto( - 3, /* nstack */ - 1, /* argc */ + 7, /* nstack */ + 3, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(http_status), - /* K1 */ be_nested_str_weak(event_http_timeout), + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(string), + /* K1 */ be_nested_str_weak(tolower), + /* K2 */ be_nested_str_weak(transfer_X2Dencoding), + /* K3 */ be_nested_str_weak(chunked), + /* K4 */ be_nested_str_weak(is_chunked), }), - be_str_weak(event_timeout), + be_str_weak(event_http_header), &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x5405FFFD, // 0000 LDINT R1 -2 - 0x90020001, // 0001 SETMBR R0 K0 R1 - 0x8C040101, // 0002 GETMET R1 R0 K1 - 0x7C040200, // 0003 CALL R1 1 - 0x80000000, // 0004 RET 0 + ( &(const binstruction[19]) { /* code */ + 0xA40E0000, // 0000 IMPORT R3 K0 + 0x8C100701, // 0001 GETMET R4 R3 K1 + 0x5C180200, // 0002 MOVE R6 R1 + 0x7C100400, // 0003 CALL R4 2 + 0x5C040800, // 0004 MOVE R1 R4 + 0x8C100701, // 0005 GETMET R4 R3 K1 + 0x5C180400, // 0006 MOVE R6 R2 + 0x7C100400, // 0007 CALL R4 2 + 0x5C080800, // 0008 MOVE R2 R4 + 0x1C100302, // 0009 EQ R4 R1 K2 + 0x78120006, // 000A JMPF R4 #0012 + 0x8C100701, // 000B GETMET R4 R3 K1 + 0x5C180400, // 000C MOVE R6 R2 + 0x7C100400, // 000D CALL R4 2 + 0x1C100903, // 000E EQ R4 R4 K3 + 0x78120001, // 000F JMPF R4 #0012 + 0x50100200, // 0010 LDBOOL R4 1 0 + 0x90020804, // 0011 SETMBR R0 K4 R4 + 0x80000000, // 0012 RET 0 }) ) ); @@ -696,9 +201,104 @@ be_local_closure(Matter_HTTP_async_event_timeout, /* name */ /******************************************************************** -** Solidified function: event_established +** Solidified function: init ********************************************************************/ -be_local_closure(Matter_HTTP_async_event_established, /* name */ +be_local_closure(Matter_HTTP_async_init, /* name */ + be_nested_proto( + 13, /* nstack */ + 5, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_str_weak(string), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(_X40), + /* K3 */ be_const_int(0), + /* K4 */ be_nested_str_weak(auth), + /* K5 */ be_nested_str_weak(fromstring), + /* K6 */ be_const_int(1), + /* K7 */ be_nested_str_weak(tob64), + /* K8 */ be_const_int(2147483647), + /* K9 */ be_nested_str_weak(init), + /* K10 */ be_nested_str_weak(compile_re), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[36]) { /* code */ + 0xA4160000, // 0000 IMPORT R5 K0 + 0x60180008, // 0001 GETGBL R6 G8 + 0x5C1C0200, // 0002 MOVE R7 R1 + 0x7C180200, // 0003 CALL R6 1 + 0x5C040C00, // 0004 MOVE R1 R6 + 0x8C180B01, // 0005 GETMET R6 R5 K1 + 0x5C200200, // 0006 MOVE R8 R1 + 0x58240002, // 0007 LDCONST R9 K2 + 0x7C180600, // 0008 CALL R6 3 + 0x281C0D03, // 0009 GE R7 R6 K3 + 0x781E000C, // 000A JMPF R7 #0018 + 0x601C0015, // 000B GETGBL R7 G21 + 0x7C1C0000, // 000C CALL R7 0 + 0x8C1C0F05, // 000D GETMET R7 R7 K5 + 0x04240D06, // 000E SUB R9 R6 K6 + 0x40260609, // 000F CONNECT R9 K3 R9 + 0x94240209, // 0010 GETIDX R9 R1 R9 + 0x7C1C0400, // 0011 CALL R7 2 + 0x8C1C0F07, // 0012 GETMET R7 R7 K7 + 0x7C1C0200, // 0013 CALL R7 1 + 0x90020807, // 0014 SETMBR R0 K4 R7 + 0x001C0D06, // 0015 ADD R7 R6 K6 + 0x401C0F08, // 0016 CONNECT R7 R7 K8 + 0x94040207, // 0017 GETIDX R1 R1 R7 + 0x601C0003, // 0018 GETGBL R7 G3 + 0x5C200000, // 0019 MOVE R8 R0 + 0x7C1C0200, // 001A CALL R7 1 + 0x8C1C0F09, // 001B GETMET R7 R7 K9 + 0x5C240200, // 001C MOVE R9 R1 + 0x5C280400, // 001D MOVE R10 R2 + 0x5C2C0600, // 001E MOVE R11 R3 + 0x5C300800, // 001F MOVE R12 R4 + 0x7C1C0A00, // 0020 CALL R7 5 + 0x8C1C010A, // 0021 GETMET R7 R0 K10 + 0x7C1C0200, // 0022 CALL R7 1 + 0x80000000, // 0023 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: event_http_failed +********************************************************************/ +be_local_closure(Matter_HTTP_async_event_http_failed, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(event_http_failed), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: parse_http_response +********************************************************************/ +be_local_closure(Matter_HTTP_async_parse_http_response, /* name */ be_nested_proto( 3, /* nstack */ 1, /* argc */ @@ -708,15 +308,36 @@ be_local_closure(Matter_HTTP_async_event_established, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(send_http), + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str_weak(phase), + /* K1 */ be_const_int(0), + /* K2 */ be_nested_str_weak(parse_http_status_line), + /* K3 */ be_const_int(1), + /* K4 */ be_nested_str_weak(parse_http_headers), + /* K5 */ be_const_int(2), + /* K6 */ be_nested_str_weak(parse_http_payload), }), - be_str_weak(event_established), + be_str_weak(parse_http_response), &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0x80000000, // 0002 RET 0 + ( &(const binstruction[18]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x1C040301, // 0001 EQ R1 R1 K1 + 0x78060002, // 0002 JMPF R1 #0006 + 0x8C040102, // 0003 GETMET R1 R0 K2 + 0x7C040200, // 0004 CALL R1 1 + 0x7002000A, // 0005 JMP #0011 + 0x88040100, // 0006 GETMBR R1 R0 K0 + 0x1C040303, // 0007 EQ R1 R1 K3 + 0x78060002, // 0008 JMPF R1 #000C + 0x8C040104, // 0009 GETMET R1 R0 K4 + 0x7C040200, // 000A CALL R1 1 + 0x70020004, // 000B JMP #0011 + 0x88040100, // 000C GETMBR R1 R0 K0 + 0x1C040305, // 000D EQ R1 R1 K5 + 0x78060001, // 000E JMPF R1 #0011 + 0x8C040106, // 000F GETMET R1 R0 K6 + 0x7C040200, // 0010 CALL R1 1 + 0x80000000, // 0011 RET 0 }) ) ); @@ -755,9 +376,9 @@ be_local_closure(Matter_HTTP_async_event_refused, /* name */ /******************************************************************** -** Solidified function: event_closed +** Solidified function: reset ********************************************************************/ -be_local_closure(Matter_HTTP_async_event_closed, /* name */ +be_local_closure(Matter_HTTP_async_reset, /* name */ be_nested_proto( 3, /* nstack */ 1, /* argc */ @@ -767,22 +388,40 @@ be_local_closure(Matter_HTTP_async_event_closed, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(http_status), - /* K1 */ be_const_int(0), - /* K2 */ be_const_int(1), - /* K3 */ be_nested_str_weak(event_http_finished), + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_str_weak(reset), + /* K1 */ be_nested_str_weak(cmd), + /* K2 */ be_nested_str_weak(response), + /* K3 */ be_nested_str_weak(response_offset), + /* K4 */ be_const_int(0), + /* K5 */ be_nested_str_weak(payload), + /* K6 */ be_nested_str_weak(), + /* K7 */ be_nested_str_weak(phase), + /* K8 */ be_nested_str_weak(http_status), + /* K9 */ be_nested_str_weak(is_chunked), + /* K10 */ be_nested_str_weak(chunk_size), }), - be_str_weak(event_closed), + be_str_weak(reset), &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x1C040301, // 0001 EQ R1 R1 K1 - 0x78060002, // 0002 JMPF R1 #0006 - 0x90020102, // 0003 SETMBR R0 K0 K2 - 0x8C040103, // 0004 GETMET R1 R0 K3 - 0x7C040200, // 0005 CALL R1 1 - 0x80000000, // 0006 RET 0 + ( &(const binstruction[18]) { /* code */ + 0x60040003, // 0000 GETGBL R1 G3 + 0x5C080000, // 0001 MOVE R2 R0 + 0x7C040200, // 0002 CALL R1 1 + 0x8C040300, // 0003 GETMET R1 R1 K0 + 0x7C040200, // 0004 CALL R1 1 + 0x4C040000, // 0005 LDNIL R1 + 0x90020201, // 0006 SETMBR R0 K1 R1 + 0x4C040000, // 0007 LDNIL R1 + 0x90020401, // 0008 SETMBR R0 K2 R1 + 0x90020704, // 0009 SETMBR R0 K3 K4 + 0x90020B06, // 000A SETMBR R0 K5 K6 + 0x90020F04, // 000B SETMBR R0 K7 K4 + 0x90021104, // 000C SETMBR R0 K8 K4 + 0x50040000, // 000D LDBOOL R1 0 0 + 0x90021201, // 000E SETMBR R0 K9 R1 + 0x4C040000, // 000F LDNIL R1 + 0x90021401, // 0010 SETMBR R0 K10 R1 + 0x80000000, // 0011 RET 0 }) ) ); @@ -790,11 +429,44 @@ be_local_closure(Matter_HTTP_async_event_closed, /* name */ /******************************************************************** -** Solidified function: parse_http_status_line +** Solidified function: begin ********************************************************************/ -be_local_closure(Matter_HTTP_async_parse_http_status_line, /* name */ +be_local_closure(Matter_HTTP_async_begin, /* name */ be_nested_proto( - 5, /* nstack */ + 4, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(begin), + /* K1 */ be_nested_str_weak(cmd), + }), + be_str_weak(begin), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x60080003, // 0000 GETGBL R2 G3 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x8C080500, // 0003 GETMET R2 R2 K0 + 0x7C080200, // 0004 CALL R2 1 + 0x90020201, // 0005 SETMBR R0 K1 R1 + 0x80040400, // 0006 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: event_established +********************************************************************/ +be_local_closure(Matter_HTTP_async_event_established, /* name */ + be_nested_proto( + 3, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -802,51 +474,15 @@ be_local_closure(Matter_HTTP_async_parse_http_status_line, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[12]) { /* constants */ - /* K0 */ be_nested_str_weak(global), - /* K1 */ be_nested_str_weak(_re_http_status), - /* K2 */ be_nested_str_weak(match2), - /* K3 */ be_nested_str_weak(response), - /* K4 */ be_nested_str_weak(response_offset), - /* K5 */ be_const_int(0), - /* K6 */ be_nested_str_weak(status_code), - /* K7 */ be_const_int(1), - /* K8 */ be_nested_str_weak(phase), - /* K9 */ be_nested_str_weak(parse_http_headers), - /* K10 */ be_nested_str_weak(close), - /* K11 */ be_nested_str_weak(status), + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(send_http), }), - be_str_weak(parse_http_status_line), + be_str_weak(event_established), &be_const_str_solidified, - ( &(const binstruction[28]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x88040301, // 0001 GETMBR R1 R1 K1 - 0x8C040302, // 0002 GETMET R1 R1 K2 - 0x880C0103, // 0003 GETMBR R3 R0 K3 - 0x88100104, // 0004 GETMBR R4 R0 K4 - 0x7C040600, // 0005 CALL R1 3 - 0x78060009, // 0006 JMPF R1 #0011 - 0x94080305, // 0007 GETIDX R2 R1 K5 - 0x90020802, // 0008 SETMBR R0 K4 R2 - 0x60080009, // 0009 GETGBL R2 G9 - 0x940C0307, // 000A GETIDX R3 R1 K7 - 0x7C080200, // 000B CALL R2 1 - 0x90020C02, // 000C SETMBR R0 K6 R2 - 0x90021107, // 000D SETMBR R0 K8 K7 - 0x8C080109, // 000E GETMET R2 R0 K9 - 0x7C080200, // 000F CALL R2 1 - 0x70020009, // 0010 JMP #001B - 0x6008000C, // 0011 GETGBL R2 G12 - 0x880C0103, // 0012 GETMBR R3 R0 K3 - 0x7C080200, // 0013 CALL R2 1 - 0x540E0063, // 0014 LDINT R3 100 - 0x24080403, // 0015 GT R2 R2 R3 - 0x780A0003, // 0016 JMPF R2 #001B - 0x8C08010A, // 0017 GETMET R2 R0 K10 - 0x7C080200, // 0018 CALL R2 1 - 0x5409FFFB, // 0019 LDINT R2 -4 - 0x90021602, // 001A SETMBR R0 K11 R2 - 0x80000000, // 001B RET 0 + ( &(const binstruction[ 3]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x80000000, // 0002 RET 0 }) ) ); @@ -942,23 +578,316 @@ be_local_closure(Matter_HTTP_async_parse_http_headers, /* name */ /******************************************************************** -** Solidified function: event_http_timeout +** Solidified function: event_available ********************************************************************/ -be_local_closure(Matter_HTTP_async_event_http_timeout, /* name */ +be_local_closure(Matter_HTTP_async_event_available, /* name */ be_nested_proto( - 1, /* nstack */ + 3, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(event_http_timeout), + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(receive), + }), + be_str_weak(event_available), &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 + ( &(const binstruction[ 3]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: event_timeout +********************************************************************/ +be_local_closure(Matter_HTTP_async_event_timeout, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(http_status), + /* K1 */ be_nested_str_weak(event_http_timeout), + }), + be_str_weak(event_timeout), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x5405FFFD, // 0000 LDINT R1 -2 + 0x90020001, // 0001 SETMBR R0 K0 R1 + 0x8C040101, // 0002 GETMET R1 R0 K1 + 0x7C040200, // 0003 CALL R1 1 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: compile_re +********************************************************************/ +be_local_closure(Matter_HTTP_async_compile_re, /* name */ + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[12]) { /* constants */ + /* K0 */ be_nested_str_weak(re), + /* K1 */ be_nested_str_weak(global), + /* K2 */ be_nested_str_weak(contains), + /* K3 */ be_nested_str_weak(_re_http_status), + /* K4 */ be_nested_str_weak(compile), + /* K5 */ be_nested_str_weak(HTTP_STATUS_REGEX), + /* K6 */ be_nested_str_weak(_re_http_header), + /* K7 */ be_nested_str_weak(HTTP_HEADER_REGEX), + /* K8 */ be_nested_str_weak(_re_http_body), + /* K9 */ be_nested_str_weak(HTTP_BODY_REGEX), + /* K10 */ be_nested_str_weak(_re_http_chunk), + /* K11 */ be_nested_str_weak(HTTP_CHUNK_REGEX), + }), + be_str_weak(compile_re), + &be_const_str_solidified, + ( &(const binstruction[27]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xB80A0200, // 0001 GETNGBL R2 K1 + 0x8C080502, // 0002 GETMET R2 R2 K2 + 0x58100003, // 0003 LDCONST R4 K3 + 0x7C080400, // 0004 CALL R2 2 + 0x740A0013, // 0005 JMPT R2 #001A + 0xB80A0200, // 0006 GETNGBL R2 K1 + 0x8C0C0304, // 0007 GETMET R3 R1 K4 + 0x88140105, // 0008 GETMBR R5 R0 K5 + 0x7C0C0400, // 0009 CALL R3 2 + 0x900A0603, // 000A SETMBR R2 K3 R3 + 0xB80A0200, // 000B GETNGBL R2 K1 + 0x8C0C0304, // 000C GETMET R3 R1 K4 + 0x88140107, // 000D GETMBR R5 R0 K7 + 0x7C0C0400, // 000E CALL R3 2 + 0x900A0C03, // 000F SETMBR R2 K6 R3 + 0xB80A0200, // 0010 GETNGBL R2 K1 + 0x8C0C0304, // 0011 GETMET R3 R1 K4 + 0x88140109, // 0012 GETMBR R5 R0 K9 + 0x7C0C0400, // 0013 CALL R3 2 + 0x900A1003, // 0014 SETMBR R2 K8 R3 + 0xB80A0200, // 0015 GETNGBL R2 K1 + 0x8C0C0304, // 0016 GETMET R3 R1 K4 + 0x8814010B, // 0017 GETMBR R5 R0 K11 + 0x7C0C0400, // 0018 CALL R3 2 + 0x900A1403, // 0019 SETMBR R2 K10 R3 + 0x80000000, // 001A RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: event_closed +********************************************************************/ +be_local_closure(Matter_HTTP_async_event_closed, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(http_status), + /* K1 */ be_const_int(0), + /* K2 */ be_const_int(1), + /* K3 */ be_nested_str_weak(event_http_finished), + }), + be_str_weak(event_closed), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x1C040301, // 0001 EQ R1 R1 K1 + 0x78060002, // 0002 JMPF R1 #0006 + 0x90020102, // 0003 SETMBR R0 K0 K2 + 0x8C040103, // 0004 GETMET R1 R0 K3 + 0x7C040200, // 0005 CALL R1 1 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: begin_sync +********************************************************************/ +be_local_closure(Matter_HTTP_async_begin_sync, /* name */ + be_nested_proto( + 10, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[10]) { /* constants */ + /* K0 */ be_nested_str_weak(timeout), + /* K1 */ be_nested_str_weak(set_timeout), + /* K2 */ be_nested_str_weak(SPINLOCK), + /* K3 */ be_nested_str_weak(begin), + /* K4 */ be_nested_str_weak(http_status), + /* K5 */ be_const_int(0), + /* K6 */ be_nested_str_weak(loop), + /* K7 */ be_nested_str_weak(tasmota), + /* K8 */ be_nested_str_weak(delay), + /* K9 */ be_nested_str_weak(payload), + }), + be_str_weak(begin_sync), + &be_const_str_solidified, + ( &(const binstruction[33]) { /* code */ + 0x880C0100, // 0000 GETMBR R3 R0 K0 + 0x4C100000, // 0001 LDNIL R4 + 0x20100404, // 0002 NE R4 R2 R4 + 0x78120002, // 0003 JMPF R4 #0007 + 0x8C100101, // 0004 GETMET R4 R0 K1 + 0x5C180400, // 0005 MOVE R6 R2 + 0x7C100400, // 0006 CALL R4 2 + 0x4C100000, // 0007 LDNIL R4 + 0x88140102, // 0008 GETMBR R5 R0 K2 + 0x8C180103, // 0009 GETMET R6 R0 K3 + 0x5C200200, // 000A MOVE R8 R1 + 0x7C180400, // 000B CALL R6 2 + 0x781A0009, // 000C JMPF R6 #0017 + 0x881C0104, // 000D GETMBR R7 R0 K4 + 0x1C1C0F05, // 000E EQ R7 R7 K5 + 0x781E0006, // 000F JMPF R7 #0017 + 0x8C1C0106, // 0010 GETMET R7 R0 K6 + 0x7C1C0200, // 0011 CALL R7 1 + 0xB81E0E00, // 0012 GETNGBL R7 K7 + 0x8C1C0F08, // 0013 GETMET R7 R7 K8 + 0x5C240A00, // 0014 MOVE R9 R5 + 0x7C1C0400, // 0015 CALL R7 2 + 0x7001FFF5, // 0016 JMP #000D + 0x8C1C0101, // 0017 GETMET R7 R0 K1 + 0x5C240600, // 0018 MOVE R9 R3 + 0x7C1C0400, // 0019 CALL R7 2 + 0x881C0104, // 001A GETMBR R7 R0 K4 + 0x241C0F05, // 001B GT R7 R7 K5 + 0x781E0001, // 001C JMPF R7 #001F + 0x881C0109, // 001D GETMBR R7 R0 K9 + 0x70020000, // 001E JMP #0020 + 0x4C1C0000, // 001F LDNIL R7 + 0x80040E00, // 0020 RET 1 R7 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: send_http +********************************************************************/ +be_local_closure(Matter_HTTP_async_send_http, /* name */ + be_nested_proto( + 10, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[19]) { /* constants */ + /* K0 */ be_nested_str_weak(string), + /* K1 */ be_nested_str_weak(response), + /* K2 */ be_nested_str_weak(), + /* K3 */ be_nested_str_weak(addr), + /* K4 */ be_nested_str_weak(find), + /* K5 */ be_nested_str_weak(_X3A), + /* K6 */ be_const_int(0), + /* K7 */ be_nested_str_weak(_X5B), + /* K8 */ be_nested_str_weak(_X5D), + /* K9 */ be_nested_str_weak(auth), + /* K10 */ be_nested_str_weak(HTTP_GET), + /* K11 */ be_nested_str_weak(cmd), + /* K12 */ be_nested_str_weak(port), + /* K13 */ be_nested_str_weak(HTTP_GET_AUTH), + /* K14 */ be_nested_str_weak(write), + /* K15 */ be_nested_str_weak(close), + /* K16 */ be_nested_str_weak(status), + /* K17 */ be_nested_str_weak(http_status), + /* K18 */ be_nested_str_weak(event_http_failed), + }), + be_str_weak(send_http), + &be_const_str_solidified, + ( &(const binstruction[50]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x90020302, // 0001 SETMBR R0 K1 K2 + 0x88080103, // 0002 GETMBR R2 R0 K3 + 0x8C0C0304, // 0003 GETMET R3 R1 K4 + 0x5C140400, // 0004 MOVE R5 R2 + 0x58180005, // 0005 LDCONST R6 K5 + 0x7C0C0600, // 0006 CALL R3 3 + 0x280C0706, // 0007 GE R3 R3 K6 + 0x780E0002, // 0008 JMPF R3 #000C + 0x000E0E02, // 0009 ADD R3 K7 R2 + 0x000C0708, // 000A ADD R3 R3 K8 + 0x5C080600, // 000B MOVE R2 R3 + 0x4C0C0000, // 000C LDNIL R3 + 0x88100109, // 000D GETMBR R4 R0 K9 + 0x4C140000, // 000E LDNIL R5 + 0x1C100805, // 000F EQ R4 R4 R5 + 0x78120007, // 0010 JMPF R4 #0019 + 0x60100018, // 0011 GETGBL R4 G24 + 0x8814010A, // 0012 GETMBR R5 R0 K10 + 0x8818010B, // 0013 GETMBR R6 R0 K11 + 0x5C1C0400, // 0014 MOVE R7 R2 + 0x8820010C, // 0015 GETMBR R8 R0 K12 + 0x7C100800, // 0016 CALL R4 4 + 0x5C0C0800, // 0017 MOVE R3 R4 + 0x70020007, // 0018 JMP #0021 + 0x60100018, // 0019 GETGBL R4 G24 + 0x8814010D, // 001A GETMBR R5 R0 K13 + 0x8818010B, // 001B GETMBR R6 R0 K11 + 0x5C1C0400, // 001C MOVE R7 R2 + 0x8820010C, // 001D GETMBR R8 R0 K12 + 0x88240109, // 001E GETMBR R9 R0 K9 + 0x7C100A00, // 001F CALL R4 5 + 0x5C0C0800, // 0020 MOVE R3 R4 + 0x8C10010E, // 0021 GETMET R4 R0 K14 + 0x5C180600, // 0022 MOVE R6 R3 + 0x7C100400, // 0023 CALL R4 2 + 0x6014000C, // 0024 GETGBL R5 G12 + 0x5C180600, // 0025 MOVE R6 R3 + 0x7C140200, // 0026 CALL R5 1 + 0x20140805, // 0027 NE R5 R4 R5 + 0x78160007, // 0028 JMPF R5 #0031 + 0x8C14010F, // 0029 GETMET R5 R0 K15 + 0x7C140200, // 002A CALL R5 1 + 0x5415FFFB, // 002B LDINT R5 -4 + 0x90022005, // 002C SETMBR R0 K16 R5 + 0x5415FFFE, // 002D LDINT R5 -1 + 0x90022205, // 002E SETMBR R0 K17 R5 + 0x8C140112, // 002F GETMET R5 R0 K18 + 0x7C140200, // 0030 CALL R5 1 + 0x80000000, // 0031 RET 0 }) ) ); @@ -1004,11 +933,11 @@ be_local_closure(Matter_HTTP_async_event_http_headers_end, /* name */ /******************************************************************** -** Solidified function: event_http_header +** Solidified function: event_http_status_code ********************************************************************/ -be_local_closure(Matter_HTTP_async_event_http_header, /* name */ +be_local_closure(Matter_HTTP_async_event_http_status_code, /* name */ be_nested_proto( - 7, /* nstack */ + 3, /* nstack */ 3, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -1016,35 +945,14 @@ be_local_closure(Matter_HTTP_async_event_http_header, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(string), - /* K1 */ be_nested_str_weak(tolower), - /* K2 */ be_nested_str_weak(transfer_X2Dencoding), - /* K3 */ be_nested_str_weak(chunked), - /* K4 */ be_nested_str_weak(is_chunked), + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(status_code), }), - be_str_weak(event_http_header), + be_str_weak(event_http_status_code), &be_const_str_solidified, - ( &(const binstruction[19]) { /* code */ - 0xA40E0000, // 0000 IMPORT R3 K0 - 0x8C100701, // 0001 GETMET R4 R3 K1 - 0x5C180200, // 0002 MOVE R6 R1 - 0x7C100400, // 0003 CALL R4 2 - 0x5C040800, // 0004 MOVE R1 R4 - 0x8C100701, // 0005 GETMET R4 R3 K1 - 0x5C180400, // 0006 MOVE R6 R2 - 0x7C100400, // 0007 CALL R4 2 - 0x5C080800, // 0008 MOVE R2 R4 - 0x1C100302, // 0009 EQ R4 R1 K2 - 0x78120006, // 000A JMPF R4 #0012 - 0x8C100701, // 000B GETMET R4 R3 K1 - 0x5C180400, // 000C MOVE R6 R2 - 0x7C100400, // 000D CALL R4 2 - 0x1C100903, // 000E EQ R4 R4 K3 - 0x78120001, // 000F JMPF R4 #0012 - 0x50100200, // 0010 LDBOOL R4 1 0 - 0x90020804, // 0011 SETMBR R0 K4 R4 - 0x80000000, // 0012 RET 0 + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 }) ) ); @@ -1052,32 +960,174 @@ be_local_closure(Matter_HTTP_async_event_http_header, /* name */ /******************************************************************** -** Solidified function: begin +** Solidified function: parse_http_status_line ********************************************************************/ -be_local_closure(Matter_HTTP_async_begin, /* name */ +be_local_closure(Matter_HTTP_async_parse_http_status_line, /* name */ be_nested_proto( - 4, /* nstack */ - 2, /* argc */ + 5, /* nstack */ + 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(begin), - /* K1 */ be_nested_str_weak(cmd), + ( &(const bvalue[12]) { /* constants */ + /* K0 */ be_nested_str_weak(global), + /* K1 */ be_nested_str_weak(_re_http_status), + /* K2 */ be_nested_str_weak(match2), + /* K3 */ be_nested_str_weak(response), + /* K4 */ be_nested_str_weak(response_offset), + /* K5 */ be_const_int(0), + /* K6 */ be_nested_str_weak(status_code), + /* K7 */ be_const_int(1), + /* K8 */ be_nested_str_weak(phase), + /* K9 */ be_nested_str_weak(parse_http_headers), + /* K10 */ be_nested_str_weak(close), + /* K11 */ be_nested_str_weak(status), }), - be_str_weak(begin), + be_str_weak(parse_http_status_line), &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0x60080003, // 0000 GETGBL R2 G3 - 0x5C0C0000, // 0001 MOVE R3 R0 - 0x7C080200, // 0002 CALL R2 1 - 0x8C080500, // 0003 GETMET R2 R2 K0 - 0x7C080200, // 0004 CALL R2 1 - 0x90020201, // 0005 SETMBR R0 K1 R1 - 0x80040400, // 0006 RET 1 R2 + ( &(const binstruction[28]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x88040301, // 0001 GETMBR R1 R1 K1 + 0x8C040302, // 0002 GETMET R1 R1 K2 + 0x880C0103, // 0003 GETMBR R3 R0 K3 + 0x88100104, // 0004 GETMBR R4 R0 K4 + 0x7C040600, // 0005 CALL R1 3 + 0x78060009, // 0006 JMPF R1 #0011 + 0x94080305, // 0007 GETIDX R2 R1 K5 + 0x90020802, // 0008 SETMBR R0 K4 R2 + 0x60080009, // 0009 GETGBL R2 G9 + 0x940C0307, // 000A GETIDX R3 R1 K7 + 0x7C080200, // 000B CALL R2 1 + 0x90020C02, // 000C SETMBR R0 K6 R2 + 0x90021107, // 000D SETMBR R0 K8 K7 + 0x8C080109, // 000E GETMET R2 R0 K9 + 0x7C080200, // 000F CALL R2 1 + 0x70020009, // 0010 JMP #001B + 0x6008000C, // 0011 GETGBL R2 G12 + 0x880C0103, // 0012 GETMBR R3 R0 K3 + 0x7C080200, // 0013 CALL R2 1 + 0x540E0063, // 0014 LDINT R3 100 + 0x24080403, // 0015 GT R2 R2 R3 + 0x780A0003, // 0016 JMPF R2 #001B + 0x8C08010A, // 0017 GETMET R2 R0 K10 + 0x7C080200, // 0018 CALL R2 1 + 0x5409FFFB, // 0019 LDINT R2 -4 + 0x90021602, // 001A SETMBR R0 K11 R2 + 0x80000000, // 001B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: event_http_timeout +********************************************************************/ +be_local_closure(Matter_HTTP_async_event_http_timeout, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(event_http_timeout), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: receive +********************************************************************/ +be_local_closure(Matter_HTTP_async_receive, /* name */ + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[15]) { /* constants */ + /* K0 */ be_nested_str_weak(tcp_connected), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(millis), + /* K3 */ be_nested_str_weak(time_start), + /* K4 */ be_nested_str_weak(timeout), + /* K5 */ be_nested_str_weak(status), + /* K6 */ be_nested_str_weak(close), + /* K7 */ be_nested_str_weak(http_status), + /* K8 */ be_nested_str_weak(event_http_timeout), + /* K9 */ be_nested_str_weak(tcp), + /* K10 */ be_nested_str_weak(available), + /* K11 */ be_const_int(0), + /* K12 */ be_nested_str_weak(read), + /* K13 */ be_nested_str_weak(response), + /* K14 */ be_nested_str_weak(parse_http_response), + }), + be_str_weak(receive), + &be_const_str_solidified, + ( &(const binstruction[48]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x50080200, // 0001 LDBOOL R2 1 0 + 0x20040202, // 0002 NE R1 R1 R2 + 0x78060000, // 0003 JMPF R1 #0005 + 0x80000200, // 0004 RET 0 + 0xB8060200, // 0005 GETNGBL R1 K1 + 0x8C040302, // 0006 GETMET R1 R1 K2 + 0x7C040200, // 0007 CALL R1 1 + 0x88080103, // 0008 GETMBR R2 R0 K3 + 0x04040202, // 0009 SUB R1 R1 R2 + 0x88080104, // 000A GETMBR R2 R0 K4 + 0x24040202, // 000B GT R1 R1 R2 + 0x78060008, // 000C JMPF R1 #0016 + 0x5405FFFC, // 000D LDINT R1 -3 + 0x90020A01, // 000E SETMBR R0 K5 R1 + 0x8C040106, // 000F GETMET R1 R0 K6 + 0x7C040200, // 0010 CALL R1 1 + 0x5405FFFD, // 0011 LDINT R1 -2 + 0x90020E01, // 0012 SETMBR R0 K7 R1 + 0x8C040108, // 0013 GETMET R1 R0 K8 + 0x7C040200, // 0014 CALL R1 1 + 0x70020018, // 0015 JMP #002F + 0x88040109, // 0016 GETMBR R1 R0 K9 + 0x8C04030A, // 0017 GETMET R1 R1 K10 + 0x7C040200, // 0018 CALL R1 1 + 0x5808000B, // 0019 LDCONST R2 K11 + 0x240C030B, // 001A GT R3 R1 K11 + 0x780E000E, // 001B JMPF R3 #002B + 0x880C0109, // 001C GETMBR R3 R0 K9 + 0x8C0C070C, // 001D GETMET R3 R3 K12 + 0x7C0C0200, // 001E CALL R3 1 + 0x8810010D, // 001F GETMBR R4 R0 K13 + 0x00100803, // 0020 ADD R4 R4 R3 + 0x90021A04, // 0021 SETMBR R0 K13 R4 + 0x6010000C, // 0022 GETGBL R4 G12 + 0x5C140600, // 0023 MOVE R5 R3 + 0x7C100200, // 0024 CALL R4 1 + 0x00080404, // 0025 ADD R2 R2 R4 + 0x88100109, // 0026 GETMBR R4 R0 K9 + 0x8C10090A, // 0027 GETMET R4 R4 K10 + 0x7C100200, // 0028 CALL R4 1 + 0x5C040800, // 0029 MOVE R1 R4 + 0x7001FFEE, // 002A JMP #001A + 0x240C050B, // 002B GT R3 R2 K11 + 0x780E0001, // 002C JMPF R3 #002F + 0x8C0C010E, // 002D GETMET R3 R0 K14 + 0x7C0C0200, // 002E CALL R3 1 + 0x80000000, // 002F RET 0 }) ) ); @@ -1089,47 +1139,49 @@ be_local_closure(Matter_HTTP_async_begin, /* name */ ********************************************************************/ extern const bclass be_class_Matter_TCP_async; be_local_class(Matter_HTTP_async, - 9, + 10, &be_class_Matter_TCP_async, - be_nested_map(37, + be_nested_map(39, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(init, 2), be_const_closure(Matter_HTTP_async_init_closure) }, - { be_const_key_weak(response, 28), be_const_var(1) }, - { be_const_key_weak(http_status, -1), be_const_var(5) }, - { be_const_key_weak(HTTP_STATUS_REGEX, 14), be_nested_str_weak(HTTP_X2F1_X5C_X2E_X5B0_X2D1_X5D_X20_X28_X5Cd_X2B_X29_X20_X2E_X2A_X3F_X0D_X0A) }, - { be_const_key_weak(HTTP_GET, 8), be_nested_str_weak(GET_X20_X25s_X20HTTP_X2F1_X2E1_X0D_X0AHost_X20_X25s_X3A_X25s_X0D_X0AConnection_X3A_X20close_X0D_X0A_X0D_X0A) }, - { be_const_key_weak(response_offset, -1), be_const_var(2) }, - { be_const_key_weak(compile_re, -1), be_const_closure(Matter_HTTP_async_compile_re_closure) }, - { be_const_key_weak(event_http_header, -1), be_const_closure(Matter_HTTP_async_event_http_header_closure) }, - { be_const_key_weak(event_http_status_code, -1), be_const_closure(Matter_HTTP_async_event_http_status_code_closure) }, - { be_const_key_weak(payload, -1), be_const_var(4) }, - { be_const_key_weak(event_available, -1), be_const_closure(Matter_HTTP_async_event_available_closure) }, - { be_const_key_weak(chunk_size, 16), be_const_var(8) }, - { be_const_key_weak(event_http_timeout, -1), be_const_closure(Matter_HTTP_async_event_http_timeout_closure) }, + { be_const_key_weak(response, -1), be_const_var(2) }, { be_const_key_weak(parse_http_payload, -1), be_const_closure(Matter_HTTP_async_parse_http_payload_closure) }, - { be_const_key_weak(parse_http_status_line, 29), be_const_closure(Matter_HTTP_async_parse_http_status_line_closure) }, - { be_const_key_weak(begin_sync, -1), be_const_closure(Matter_HTTP_async_begin_sync_closure) }, - { be_const_key_weak(cmd, -1), be_const_var(0) }, - { be_const_key_weak(event_http_failed, 13), be_const_closure(Matter_HTTP_async_event_http_failed_closure) }, - { be_const_key_weak(SPINLOCK, -1), be_const_int(5) }, - { be_const_key_weak(reset, 31), be_const_closure(Matter_HTTP_async_reset_closure) }, - { be_const_key_weak(send_http, -1), be_const_closure(Matter_HTTP_async_send_http_closure) }, - { be_const_key_weak(parse_http_response, 15), be_const_closure(Matter_HTTP_async_parse_http_response_closure) }, - { be_const_key_weak(event_http_finished, -1), be_const_closure(Matter_HTTP_async_event_http_finished_closure) }, + { be_const_key_weak(receive, 10), be_const_closure(Matter_HTTP_async_receive_closure) }, + { be_const_key_weak(event_http_finished, 22), be_const_closure(Matter_HTTP_async_event_http_finished_closure) }, { be_const_key_weak(HTTP_BODY_REGEX, -1), be_nested_str_weak(_X0D_X0A) }, + { be_const_key_weak(HTTP_GET_AUTH, -1), be_nested_str_weak(GET_X20_X25s_X20HTTP_X2F1_X2E1_X0D_X0AHost_X20_X25s_X3A_X25s_X0D_X0AAuthorization_X3A_X20Basic_X20_X25s_X0D_X0AConnection_X3A_X20close_X0D_X0A_X0D_X0A) }, + { be_const_key_weak(init, -1), be_const_closure(Matter_HTTP_async_init_closure) }, + { be_const_key_weak(response_offset, 23), be_const_var(3) }, + { be_const_key_weak(parse_http_response, -1), be_const_closure(Matter_HTTP_async_parse_http_response_closure) }, { be_const_key_weak(event_refused, -1), be_const_closure(Matter_HTTP_async_event_refused_closure) }, - { be_const_key_weak(HTTP_HEADER_REGEX, -1), be_nested_str_weak(_X28_X5BA_X2DZa_X2Dz0_X2D9_X2D_X5D_X2B_X29_X3A_X20_X28_X2E_X2A_X3F_X29_X0D_X0A) }, - { be_const_key_weak(is_chunked, 25), be_const_var(7) }, - { be_const_key_weak(event_established, 24), be_const_closure(Matter_HTTP_async_event_established_closure) }, - { be_const_key_weak(HTTP_CHUNK_REGEX, -1), be_nested_str_weak(_X0D_X0A_X28_X5BA_X2DFa_X2Df0_X2D9_X5D_X2B_X29_X5B_X20_X09_X5D_X2A_X2E_X2A_X3F_X0D_X0A) }, - { be_const_key_weak(receive, -1), be_const_closure(Matter_HTTP_async_receive_closure) }, - { be_const_key_weak(event_closed, -1), be_const_closure(Matter_HTTP_async_event_closed_closure) }, - { be_const_key_weak(phase, -1), be_const_var(6) }, - { be_const_key_weak(parse_http_headers, -1), be_const_closure(Matter_HTTP_async_parse_http_headers_closure) }, - { be_const_key_weak(event_timeout, 12), be_const_closure(Matter_HTTP_async_event_timeout_closure) }, + { be_const_key_weak(event_http_timeout, -1), be_const_closure(Matter_HTTP_async_event_http_timeout_closure) }, + { be_const_key_weak(HTTP_STATUS_REGEX, -1), be_nested_str_weak(HTTP_X2F1_X5C_X2E_X5B0_X2D1_X5D_X20_X28_X5Cd_X2B_X29_X20_X2E_X2A_X3F_X0D_X0A) }, + { be_const_key_weak(cmd, -1), be_const_var(1) }, + { be_const_key_weak(event_http_status_code, -1), be_const_closure(Matter_HTTP_async_event_http_status_code_closure) }, + { be_const_key_weak(payload, -1), be_const_var(5) }, + { be_const_key_weak(is_chunked, -1), be_const_var(8) }, + { be_const_key_weak(HTTP_GET, -1), be_nested_str_weak(GET_X20_X25s_X20HTTP_X2F1_X2E1_X0D_X0AHost_X20_X25s_X3A_X25s_X0D_X0AConnection_X3A_X20close_X0D_X0A_X0D_X0A) }, + { be_const_key_weak(chunk_size, 16), be_const_var(9) }, + { be_const_key_weak(auth, 35), be_const_var(0) }, + { be_const_key_weak(parse_http_headers, 26), be_const_closure(Matter_HTTP_async_parse_http_headers_closure) }, + { be_const_key_weak(event_available, -1), be_const_closure(Matter_HTTP_async_event_available_closure) }, + { be_const_key_weak(status_code, 11), be_const_var(4) }, + { be_const_key_weak(phase, 36), be_const_var(7) }, { be_const_key_weak(event_http_headers_end, -1), be_const_closure(Matter_HTTP_async_event_http_headers_end_closure) }, - { be_const_key_weak(status_code, 7), be_const_var(3) }, - { be_const_key_weak(begin, -1), be_const_closure(Matter_HTTP_async_begin_closure) }, + { be_const_key_weak(reset, 31), be_const_closure(Matter_HTTP_async_reset_closure) }, + { be_const_key_weak(begin_sync, -1), be_const_closure(Matter_HTTP_async_begin_sync_closure) }, + { be_const_key_weak(send_http, -1), be_const_closure(Matter_HTTP_async_send_http_closure) }, + { be_const_key_weak(event_timeout, 28), be_const_closure(Matter_HTTP_async_event_timeout_closure) }, + { be_const_key_weak(HTTP_CHUNK_REGEX, -1), be_nested_str_weak(_X0D_X0A_X28_X5BA_X2DFa_X2Df0_X2D9_X5D_X2B_X29_X5B_X20_X09_X5D_X2A_X2E_X2A_X3F_X0D_X0A) }, + { be_const_key_weak(compile_re, 7), be_const_closure(Matter_HTTP_async_compile_re_closure) }, + { be_const_key_weak(HTTP_HEADER_REGEX, -1), be_nested_str_weak(_X28_X5BA_X2DZa_X2Dz0_X2D9_X2D_X5D_X2B_X29_X3A_X20_X28_X2E_X2A_X3F_X29_X0D_X0A) }, + { be_const_key_weak(event_closed, 30), be_const_closure(Matter_HTTP_async_event_closed_closure) }, + { be_const_key_weak(event_http_header, 14), be_const_closure(Matter_HTTP_async_event_http_header_closure) }, + { be_const_key_weak(event_http_failed, 13), be_const_closure(Matter_HTTP_async_event_http_failed_closure) }, + { be_const_key_weak(parse_http_status_line, -1), be_const_closure(Matter_HTTP_async_parse_http_status_line_closure) }, + { be_const_key_weak(event_established, -1), be_const_closure(Matter_HTTP_async_event_established_closure) }, + { be_const_key_weak(begin, 4), be_const_closure(Matter_HTTP_async_begin_closure) }, + { be_const_key_weak(http_status, -1), be_const_var(6) }, + { be_const_key_weak(SPINLOCK, 2), be_const_int(5) }, })), be_str_weak(Matter_HTTP_async) ); From 15e181ac53f285da66b26389d593871c9966784d Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 23 Dec 2023 11:57:01 +0100 Subject: [PATCH 038/303] Update CHANGELOG for Matter remote password --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a17df4982..c1b85a015 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. - Support for Sonoff Basic R4 Magic Switch (#20247) - Support for CST816S touch interface (#20213) - NeoPool hydrolysis FL1 and Redox flag (#20258) +- Matter support for password for remote Tasmota devices (#20296) ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds (#20236) From b4f1aafc4cc10b8f037cdfefe47c2cea4711f70d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 23 Dec 2023 12:18:25 +0100 Subject: [PATCH 039/303] Platform 2023.12.00 (#20298) --- platformio_tasmota32.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index a930178d0..13b6f35e6 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -93,7 +93,7 @@ lib_ignore = [core32] -platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.11.01/platform-espressif32.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.12.00/platform-espressif32.zip platform_packages = build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} From a6a8214ea7ca3fef365070f2c806f3aaa3e78f18 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 Dec 2023 16:13:13 +0100 Subject: [PATCH 040/303] Fix support for Domoticz floor/room topics Fix support for Domoticz floor/room topics. Regression from v12.0.1 (#20299) --- CHANGELOG.md | 1 + RELEASENOTES.md | 2 ++ .../tasmota_xdrv_driver/xdrv_07_domoticz.ino | 20 ++++++++++--------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1b85a015..2a7795908 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to this project will be documented in this file. - CVE-2021-36603 Cross Site Scripting (XSS) vulnerability (#12221) - ESP32 piezo ceramic buzzer doesn't buzz (#20118) - Syslog server warning caused by lack of field and hostname starting with 'z' (#14689) +- Support for Domoticz floor/room topics. Regression from v12.0.1 (#20299) ### Removed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 52c7e1e08..dba6bb153 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -121,6 +121,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Support for CST816S touch interface [#20213](https://github.com/arendst/Tasmota/issues/20213) - Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247) - NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) +- Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds [#20236](https://github.com/arendst/Tasmota/issues/20236) @@ -131,6 +132,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ### Fixed - CVE-2021-36603 Cross Site Scripting (XSS) vulnerability [#12221](https://github.com/arendst/Tasmota/issues/12221) - Syslog server warning caused by lack of field and hostname starting with 'z' [#14689](https://github.com/arendst/Tasmota/issues/14689) +- Support for Domoticz floor/room topics. Regression from v12.0.1 [#20299](https://github.com/arendst/Tasmota/issues/20299) - ESP32 piezo ceramic buzzer doesn't buzz [#20118](https://github.com/arendst/Tasmota/issues/20118) - Matter Contact sensor was not triggering any update [#20232](https://github.com/arendst/Tasmota/issues/20232) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino b/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino index d3e18c4d0..2994eeafc 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino @@ -218,14 +218,18 @@ bool DomoticzMqttData(void) { return true; // No valid data } - int32_t relay_index = -1; +// char dom_data[XdrvMailbox.data_len +1]; +// strcpy(dom_data, XdrvMailbox.data); +// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "Topic '%s', Data '%s'"), XdrvMailbox.topic, RemoveControlCharacter(dom_data)); // Quick check if this is mine using topic domoticz/out/{$idx} if (strlen(XdrvMailbox.topic) > strlen(DOMOTICZ_OUT_TOPIC)) { char* topic_index = &XdrvMailbox.topic[strlen(DOMOTICZ_OUT_TOPIC) +1]; - relay_index = DomoticzIdx2Relay(atoi(topic_index)); - if (relay_index < 0) { - return true; // Idx not mine + int32_t top_index = atoi(topic_index); // 0 if no number (in case of domoticz/out/floor/room) + if (top_index > 0) { + if (DomoticzIdx2Relay(top_index) < 0) { + return true; // Idx not mine + } } } @@ -235,18 +239,16 @@ bool DomoticzMqttData(void) { if (!domoticz) { return true; // To much or invalid data } + int32_t relay_index = DomoticzIdx2Relay(domoticz.getUInt(PSTR("idx"), 0)); if (relay_index < 0) { - relay_index = DomoticzIdx2Relay(domoticz.getUInt(PSTR("idx"), 0)); - if (relay_index < 0) { - return true; // Idx not mine - } + return true; // Idx not mine } int32_t nvalue = domoticz.getInt(PSTR("nvalue"), -1); if ((nvalue < 0) || (nvalue > 16)) { return true; // Nvalue out of boundaries } - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), Settings->domoticz_relay_idx[relay_index], nvalue); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "Topic %s, idx %d, nvalue %d"), XdrvMailbox.topic, Settings->domoticz_relay_idx[relay_index], nvalue); bool iscolordimmer = (strcmp_P(domoticz.getStr(PSTR("dtype")), PSTR("Color Switch")) == 0); bool isShutter = (strcmp_P(domoticz.getStr(PSTR("dtype")), PSTR("Light/Switch")) == 0) && (strncmp_P(domoticz.getStr(PSTR("switchType")),PSTR("Blinds"), 6) == 0); From 6c0028de4e297ee416efeb12051daae0d0000d5d Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 24 Dec 2023 09:31:53 +0100 Subject: [PATCH 041/303] Matter improve read sensors (#20302) * Matter improve read_sensors scheduling * Imprtove logging * add scheduler call * remove unwanted print * fix --- .../src/embedded/Matter_Plugin_2_Sensor.be | 11 + .../src/embedded/Matter_zz_Device.be | 35 +- .../solidified_Matter_Plugin_2_Sensor.h | 434 +- .../solidify/solidified_Matter_zz_Device.h | 9689 +++++++++-------- 4 files changed, 5164 insertions(+), 5005 deletions(-) diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor.be index cdeb53217..1678f2a4f 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor.be @@ -32,6 +32,17 @@ class Matter_Plugin_Sensor : Matter_Plugin_Device var tasmota_sensor_matcher # Actual matcher object var shadow_value # Last known value + ############################################################# + # Constructor + # + # device: contains the root device object so the plugin can "call home" + # endpoint: (int) the endpoint number (16 bits) + # arguments: (map) the map for all complementary arguments that are plugin specific + def init(device, endpoint, config) + super(self).init(device, endpoint, config) + device.add_read_sensors_schedule(self.UPDATE_TIME) + end + ############################################################# # parse_configuration # diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be b/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be index b0b01434d..64aa38ba6 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be @@ -72,6 +72,11 @@ class Matter_Device var root_salt var root_w0 var root_L + # cron equivalent to call `read_sensors()` regularly and dispatch to all entpoints + var probe_sensor_time # number of milliseconds to wait between each `read_sensors()` or `nil` if none active + var probe_sensor_timestamp # timestamp for `read_sensors()` probe (in millis()) + # if timestamp is `0`, this should be scheduled in priority + ############################################################# def init() @@ -132,10 +137,6 @@ class Matter_Device # autoconfigure other plugins if needed self.autoconf_device() - # for now read sensors every 30 seconds - # TODO still needed? - tasmota.add_cron("*/30 * * * * *", def () self._trigger_read_sensors() end, "matter_sensors_30s") - self._start_udp(self.UDP_PORT) self.start_mdns_announce_hostnames() @@ -317,6 +318,8 @@ class Matter_Device # dispatch every 250ms to all plugins def every_250ms() self.message_handler.every_250ms() + # call read_sensors if needed + self.read_sensors_scheduler() # call all plugins, use a manual loop to avoid creating a new object var idx = 0 while idx < size(self.plugins) @@ -325,12 +328,36 @@ class Matter_Device end end + ############################################################# + # add a scheduler for `read_sensors` and update schedule time + # if it's more often than previously + def add_read_sensors_schedule(update_time) + if (self.probe_sensor_time == nil) || (self.probe_sensor_time > update_time) + self.probe_sensor_time = update_time + self.probe_sensor_timestamp = matter.jitter(update_time) + end + end + + ############################################################# + # check if we need to call `read_sensors()` + def read_sensors_scheduler() + if (self.probe_sensor_time == nil) return end # nothing to schedule + if (self.probe_sensor_timestamp == 0) || (tasmota.time_reached(self.probe_sensor_timestamp)) + self._trigger_read_sensors() + # set new next timestamp + self.probe_sensor_timestamp = tasmota.millis(self.probe_sensor_time) + end + end + ############################################################# # trigger a read_sensors and dispatch to plugins # Internally used by cron def _trigger_read_sensors() import json var rs_json = tasmota.read_sensors() + if tasmota.loglevel(3) + tasmota.log("MTR: read_sensors: "+str(rs_json), 3) + end if rs_json == nil return end var rs = json.load(rs_json) if rs != nil diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor.h index 2a86d3ae8..e2d100e7b 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor.h @@ -6,6 +6,230 @@ extern const bclass be_class_Matter_Plugin_Sensor; +/******************************************************************** +** Solidified function: append_state_json +********************************************************************/ +be_local_closure(Matter_Plugin_Sensor_append_state_json, /* name */ + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(shadow_value), + /* K1 */ be_nested_str_weak(null), + /* K2 */ be_nested_str_weak(_X2C_X22_X25s_X22_X3A_X25s), + /* K3 */ be_nested_str_weak(JSON_NAME), + }), + be_str_weak(append_state_json), + &be_const_str_solidified, + ( &(const binstruction[13]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x20040202, // 0002 NE R1 R1 R2 + 0x78060001, // 0003 JMPF R1 #0006 + 0x88040100, // 0004 GETMBR R1 R0 K0 + 0x70020000, // 0005 JMP #0007 + 0x58040001, // 0006 LDCONST R1 K1 + 0x60080018, // 0007 GETGBL R2 G24 + 0x580C0002, // 0008 LDCONST R3 K2 + 0x88100103, // 0009 GETMBR R4 R0 K3 + 0x5C140200, // 000A MOVE R5 R1 + 0x7C080600, // 000B CALL R2 3 + 0x80040400, // 000C RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Matter_Plugin_Sensor_init, /* name */ + be_nested_proto( + 9, /* nstack */ + 4, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(init), + /* K1 */ be_nested_str_weak(add_read_sensors_schedule), + /* K2 */ be_nested_str_weak(UPDATE_TIME), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0x60100003, // 0000 GETGBL R4 G3 + 0x5C140000, // 0001 MOVE R5 R0 + 0x7C100200, // 0002 CALL R4 1 + 0x8C100900, // 0003 GETMET R4 R4 K0 + 0x5C180200, // 0004 MOVE R6 R1 + 0x5C1C0400, // 0005 MOVE R7 R2 + 0x5C200600, // 0006 MOVE R8 R3 + 0x7C100800, // 0007 CALL R4 4 + 0x8C100301, // 0008 GETMET R4 R1 K1 + 0x88180102, // 0009 GETMBR R6 R0 K2 + 0x7C100400, // 000A CALL R4 2 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: value_changed +********************************************************************/ +be_local_closure(Matter_Plugin_Sensor_value_changed, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(value_changed), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: parse_configuration +********************************************************************/ +be_local_closure(Matter_Plugin_Sensor_parse_configuration, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota_sensor_filter), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(ARG), + /* K3 */ be_nested_str_weak(tasmota_sensor_matcher), + /* K4 */ be_nested_str_weak(tasmota), + /* K5 */ be_nested_str_weak(Rule_Matcher), + /* K6 */ be_nested_str_weak(parse), + }), + be_str_weak(parse_configuration), + &be_const_str_solidified, + ( &(const binstruction[13]) { /* code */ + 0x8C080301, // 0000 GETMET R2 R1 K1 + 0x88100102, // 0001 GETMBR R4 R0 K2 + 0x7C080400, // 0002 CALL R2 2 + 0x90020002, // 0003 SETMBR R0 K0 R2 + 0x88080100, // 0004 GETMBR R2 R0 K0 + 0x780A0005, // 0005 JMPF R2 #000C + 0xB80A0800, // 0006 GETNGBL R2 K4 + 0x88080505, // 0007 GETMBR R2 R2 K5 + 0x8C080506, // 0008 GETMET R2 R2 K6 + 0x88100100, // 0009 GETMBR R4 R0 K0 + 0x7C080400, // 000A CALL R2 2 + 0x90020602, // 000B SETMBR R0 K3 R2 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: parse_sensors +********************************************************************/ +be_local_closure(Matter_Plugin_Sensor_parse_sensors, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(VIRTUAL), + /* K1 */ be_nested_str_weak(tasmota_sensor_matcher), + /* K2 */ be_nested_str_weak(pre_value), + /* K3 */ be_nested_str_weak(match), + /* K4 */ be_nested_str_weak(shadow_value), + /* K5 */ be_nested_str_weak(value_changed), + }), + be_str_weak(parse_sensors), + &be_const_str_solidified, + ( &(const binstruction[22]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x740A0012, // 0001 JMPT R2 #0015 + 0x88080101, // 0002 GETMBR R2 R0 K1 + 0x780A0010, // 0003 JMPF R2 #0015 + 0x8C080102, // 0004 GETMET R2 R0 K2 + 0x6010000A, // 0005 GETGBL R4 G10 + 0x88140101, // 0006 GETMBR R5 R0 K1 + 0x8C140B03, // 0007 GETMET R5 R5 K3 + 0x5C1C0200, // 0008 MOVE R7 R1 + 0x7C140400, // 0009 CALL R5 2 + 0x7C100200, // 000A CALL R4 1 + 0x7C080400, // 000B CALL R2 2 + 0x4C0C0000, // 000C LDNIL R3 + 0x200C0403, // 000D NE R3 R2 R3 + 0x780E0005, // 000E JMPF R3 #0015 + 0x880C0104, // 000F GETMBR R3 R0 K4 + 0x200C0403, // 0010 NE R3 R2 R3 + 0x780E0002, // 0011 JMPF R3 #0015 + 0x8C0C0105, // 0012 GETMET R3 R0 K5 + 0x7C0C0200, // 0013 CALL R3 1 + 0x90020802, // 0014 SETMBR R0 K4 R2 + 0x80000000, // 0015 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: pre_value +********************************************************************/ +be_local_closure(Matter_Plugin_Sensor_pre_value, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(pre_value), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80040200, // 0000 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: update_virtual ********************************************************************/ @@ -64,191 +288,6 @@ be_local_closure(Matter_Plugin_Sensor_update_virtual, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: parse_sensors -********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_parse_sensors, /* name */ - be_nested_proto( - 8, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(VIRTUAL), - /* K1 */ be_nested_str_weak(tasmota_sensor_matcher), - /* K2 */ be_nested_str_weak(pre_value), - /* K3 */ be_nested_str_weak(match), - /* K4 */ be_nested_str_weak(shadow_value), - /* K5 */ be_nested_str_weak(value_changed), - }), - be_str_weak(parse_sensors), - &be_const_str_solidified, - ( &(const binstruction[22]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x740A0012, // 0001 JMPT R2 #0015 - 0x88080101, // 0002 GETMBR R2 R0 K1 - 0x780A0010, // 0003 JMPF R2 #0015 - 0x8C080102, // 0004 GETMET R2 R0 K2 - 0x6010000A, // 0005 GETGBL R4 G10 - 0x88140101, // 0006 GETMBR R5 R0 K1 - 0x8C140B03, // 0007 GETMET R5 R5 K3 - 0x5C1C0200, // 0008 MOVE R7 R1 - 0x7C140400, // 0009 CALL R5 2 - 0x7C100200, // 000A CALL R4 1 - 0x7C080400, // 000B CALL R2 2 - 0x4C0C0000, // 000C LDNIL R3 - 0x200C0403, // 000D NE R3 R2 R3 - 0x780E0005, // 000E JMPF R3 #0015 - 0x880C0104, // 000F GETMBR R3 R0 K4 - 0x200C0403, // 0010 NE R3 R2 R3 - 0x780E0002, // 0011 JMPF R3 #0015 - 0x8C0C0105, // 0012 GETMET R3 R0 K5 - 0x7C0C0200, // 0013 CALL R3 1 - 0x90020802, // 0014 SETMBR R0 K4 R2 - 0x80000000, // 0015 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: parse_configuration -********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_parse_configuration, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota_sensor_filter), - /* K1 */ be_nested_str_weak(find), - /* K2 */ be_nested_str_weak(ARG), - /* K3 */ be_nested_str_weak(tasmota_sensor_matcher), - /* K4 */ be_nested_str_weak(tasmota), - /* K5 */ be_nested_str_weak(Rule_Matcher), - /* K6 */ be_nested_str_weak(parse), - }), - be_str_weak(parse_configuration), - &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x8C080301, // 0000 GETMET R2 R1 K1 - 0x88100102, // 0001 GETMBR R4 R0 K2 - 0x7C080400, // 0002 CALL R2 2 - 0x90020002, // 0003 SETMBR R0 K0 R2 - 0x88080100, // 0004 GETMBR R2 R0 K0 - 0x780A0005, // 0005 JMPF R2 #000C - 0xB80A0800, // 0006 GETNGBL R2 K4 - 0x88080505, // 0007 GETMBR R2 R2 K5 - 0x8C080506, // 0008 GETMET R2 R2 K6 - 0x88100100, // 0009 GETMBR R4 R0 K0 - 0x7C080400, // 000A CALL R2 2 - 0x90020602, // 000B SETMBR R0 K3 R2 - 0x80000000, // 000C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: pre_value -********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_pre_value, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(pre_value), - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80040200, // 0000 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: append_state_json -********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_append_state_json, /* name */ - be_nested_proto( - 6, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(shadow_value), - /* K1 */ be_nested_str_weak(null), - /* K2 */ be_nested_str_weak(_X2C_X22_X25s_X22_X3A_X25s), - /* K3 */ be_nested_str_weak(JSON_NAME), - }), - be_str_weak(append_state_json), - &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x4C080000, // 0001 LDNIL R2 - 0x20040202, // 0002 NE R1 R1 R2 - 0x78060001, // 0003 JMPF R1 #0006 - 0x88040100, // 0004 GETMBR R1 R0 K0 - 0x70020000, // 0005 JMP #0007 - 0x58040001, // 0006 LDCONST R1 K1 - 0x60080018, // 0007 GETGBL R2 G24 - 0x580C0002, // 0008 LDCONST R3 K2 - 0x88100103, // 0009 GETMBR R4 R0 K3 - 0x5C140200, // 000A MOVE R5 R1 - 0x7C080600, // 000B CALL R2 3 - 0x80040400, // 000C RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: value_changed -********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_value_changed, /* name */ - be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(value_changed), - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified class: Matter_Plugin_Sensor ********************************************************************/ @@ -256,21 +295,22 @@ extern const bclass be_class_Matter_Plugin_Device; be_local_class(Matter_Plugin_Sensor, 3, &be_class_Matter_Plugin_Device, - be_nested_map(13, + be_nested_map(14, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(ARG, 1), be_nested_str_weak(filter) }, - { be_const_key_weak(value_changed, -1), be_const_closure(Matter_Plugin_Sensor_value_changed_closure) }, + { be_const_key_weak(UPDATE_TIME, 3), be_const_int(5000) }, + { be_const_key_weak(ARG, -1), be_nested_str_weak(filter) }, + { be_const_key_weak(append_state_json, 0), be_const_closure(Matter_Plugin_Sensor_append_state_json_closure) }, { be_const_key_weak(update_virtual, -1), be_const_closure(Matter_Plugin_Sensor_update_virtual_closure) }, - { be_const_key_weak(ARG_HINT, 8), be_nested_str_weak(Filter_X20pattern) }, - { be_const_key_weak(tasmota_sensor_matcher, -1), be_const_var(1) }, - { be_const_key_weak(parse_sensors, -1), be_const_closure(Matter_Plugin_Sensor_parse_sensors_closure) }, - { be_const_key_weak(JSON_NAME, -1), be_nested_str_weak() }, - { be_const_key_weak(parse_configuration, -1), be_const_closure(Matter_Plugin_Sensor_parse_configuration_closure) }, - { be_const_key_weak(pre_value, 12), be_const_closure(Matter_Plugin_Sensor_pre_value_closure) }, - { be_const_key_weak(append_state_json, -1), be_const_closure(Matter_Plugin_Sensor_append_state_json_closure) }, - { be_const_key_weak(shadow_value, 9), be_const_var(2) }, - { be_const_key_weak(UPDATE_TIME, -1), be_const_int(5000) }, { be_const_key_weak(tasmota_sensor_filter, -1), be_const_var(0) }, + { be_const_key_weak(init, 13), be_const_closure(Matter_Plugin_Sensor_init_closure) }, + { be_const_key_weak(tasmota_sensor_matcher, -1), be_const_var(1) }, + { be_const_key_weak(ARG_HINT, 12), be_nested_str_weak(Filter_X20pattern) }, + { be_const_key_weak(parse_sensors, 10), be_const_closure(Matter_Plugin_Sensor_parse_sensors_closure) }, + { be_const_key_weak(JSON_NAME, -1), be_nested_str_weak() }, + { be_const_key_weak(pre_value, -1), be_const_closure(Matter_Plugin_Sensor_pre_value_closure) }, + { be_const_key_weak(shadow_value, 7), be_const_var(2) }, + { be_const_key_weak(parse_configuration, -1), be_const_closure(Matter_Plugin_Sensor_parse_configuration_closure) }, + { be_const_key_weak(value_changed, -1), be_const_closure(Matter_Plugin_Sensor_value_changed_closure) }, })), be_str_weak(Matter_Plugin_Sensor) ); diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h index a008118ea..aeb9d3b26 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h @@ -6,6 +6,121 @@ extern const bclass be_class_Matter_Device; +/******************************************************************** +** Solidified function: bridge_add_endpoint +********************************************************************/ +be_local_closure(Matter_Device_bridge_add_endpoint, /* name */ + be_nested_proto( + 17, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[21]) { /* constants */ + /* K0 */ be_nested_str_weak(plugins_classes), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(tasmota), + /* K3 */ be_nested_str_weak(log), + /* K4 */ be_nested_str_weak(MTR_X3A_X20unknown_X20class_X20name_X20_X27), + /* K5 */ be_nested_str_weak(_X27_X20skipping), + /* K6 */ be_const_int(3), + /* K7 */ be_nested_str_weak(next_ep), + /* K8 */ be_nested_str_weak(plugins), + /* K9 */ be_nested_str_weak(push), + /* K10 */ be_nested_str_weak(type), + /* K11 */ be_nested_str_weak(keys), + /* K12 */ be_nested_str_weak(stop_iteration), + /* K13 */ be_nested_str_weak(MTR_X3A_X20adding_X20endpoint_X20_X3D_X20_X25i_X20type_X3A_X25s_X25s), + /* K14 */ be_nested_str_weak(conf_to_log), + /* K15 */ be_const_int(2), + /* K16 */ be_nested_str_weak(plugins_config), + /* K17 */ be_nested_str_weak(plugins_persist), + /* K18 */ be_const_int(1), + /* K19 */ be_nested_str_weak(save_param), + /* K20 */ be_nested_str_weak(signal_endpoints_changed), + }), + be_str_weak(bridge_add_endpoint), + &be_const_str_solidified, + ( &(const binstruction[70]) { /* code */ + 0x880C0100, // 0000 GETMBR R3 R0 K0 + 0x8C0C0701, // 0001 GETMET R3 R3 K1 + 0x5C140200, // 0002 MOVE R5 R1 + 0x7C0C0400, // 0003 CALL R3 2 + 0x4C100000, // 0004 LDNIL R4 + 0x1C100604, // 0005 EQ R4 R3 R4 + 0x78120009, // 0006 JMPF R4 #0011 + 0xB8120400, // 0007 GETNGBL R4 K2 + 0x8C100903, // 0008 GETMET R4 R4 K3 + 0x60180008, // 0009 GETGBL R6 G8 + 0x5C1C0200, // 000A MOVE R7 R1 + 0x7C180200, // 000B CALL R6 1 + 0x001A0806, // 000C ADD R6 K4 R6 + 0x00180D05, // 000D ADD R6 R6 K5 + 0x581C0006, // 000E LDCONST R7 K6 + 0x7C100600, // 000F CALL R4 3 + 0x80000800, // 0010 RET 0 + 0x88100107, // 0011 GETMBR R4 R0 K7 + 0x60140008, // 0012 GETGBL R5 G8 + 0x5C180800, // 0013 MOVE R6 R4 + 0x7C140200, // 0014 CALL R5 1 + 0x5C180600, // 0015 MOVE R6 R3 + 0x5C1C0000, // 0016 MOVE R7 R0 + 0x5C200800, // 0017 MOVE R8 R4 + 0x5C240400, // 0018 MOVE R9 R2 + 0x7C180600, // 0019 CALL R6 3 + 0x881C0108, // 001A GETMBR R7 R0 K8 + 0x8C1C0F09, // 001B GETMET R7 R7 K9 + 0x5C240C00, // 001C MOVE R9 R6 + 0x7C1C0400, // 001D CALL R7 2 + 0x601C0013, // 001E GETGBL R7 G19 + 0x7C1C0000, // 001F CALL R7 0 + 0x981E1401, // 0020 SETIDX R7 K10 R1 + 0x60200010, // 0021 GETGBL R8 G16 + 0x8C24050B, // 0022 GETMET R9 R2 K11 + 0x7C240200, // 0023 CALL R9 1 + 0x7C200200, // 0024 CALL R8 1 + 0xA8020004, // 0025 EXBLK 0 #002B + 0x5C241000, // 0026 MOVE R9 R8 + 0x7C240000, // 0027 CALL R9 0 + 0x94280409, // 0028 GETIDX R10 R2 R9 + 0x981C120A, // 0029 SETIDX R7 R9 R10 + 0x7001FFFA, // 002A JMP #0026 + 0x5820000C, // 002B LDCONST R8 K12 + 0xAC200200, // 002C CATCH R8 1 0 + 0xB0080000, // 002D RAISE 2 R0 R0 + 0xB8220400, // 002E GETNGBL R8 K2 + 0x8C201103, // 002F GETMET R8 R8 K3 + 0x60280018, // 0030 GETGBL R10 G24 + 0x582C000D, // 0031 LDCONST R11 K13 + 0x5C300800, // 0032 MOVE R12 R4 + 0x5C340200, // 0033 MOVE R13 R1 + 0x8C38010E, // 0034 GETMET R14 R0 K14 + 0x5C400400, // 0035 MOVE R16 R2 + 0x7C380400, // 0036 CALL R14 2 + 0x7C280800, // 0037 CALL R10 4 + 0x582C000F, // 0038 LDCONST R11 K15 + 0x7C200600, // 0039 CALL R8 3 + 0x88200110, // 003A GETMBR R8 R0 K16 + 0x98200A07, // 003B SETIDX R8 R5 R7 + 0x50200200, // 003C LDBOOL R8 1 0 + 0x90022208, // 003D SETMBR R0 K17 R8 + 0x88200107, // 003E GETMBR R8 R0 K7 + 0x00201112, // 003F ADD R8 R8 K18 + 0x90020E08, // 0040 SETMBR R0 K7 R8 + 0x8C200113, // 0041 GETMET R8 R0 K19 + 0x7C200200, // 0042 CALL R8 1 + 0x8C200114, // 0043 GETMET R8 R0 K20 + 0x7C200200, // 0044 CALL R8 1 + 0x80040800, // 0045 RET 1 R4 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: save_before_restart ********************************************************************/ @@ -38,30 +153,59 @@ be_local_closure(Matter_Device_save_before_restart, /* name */ /******************************************************************** -** Solidified function: msg_send +** Solidified function: compute_manual_pairing_code ********************************************************************/ -be_local_closure(Matter_Device_msg_send, /* name */ +be_local_closure(Matter_Device_compute_manual_pairing_code, /* name */ be_nested_proto( - 5, /* nstack */ - 2, /* argc */ + 9, /* nstack */ + 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(udp_server), - /* K1 */ be_nested_str_weak(send_UDP), + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(root_discriminator), + /* K1 */ be_nested_str_weak(root_passcode), + /* K2 */ be_nested_str_weak(_X251i_X2505i_X2504i), + /* K3 */ be_nested_str_weak(matter), + /* K4 */ be_nested_str_weak(Verhoeff), + /* K5 */ be_nested_str_weak(checksum), }), - be_str_weak(msg_send), + be_str_weak(compute_manual_pairing_code), &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x80040400, // 0004 RET 1 R2 + ( &(const binstruction[30]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x540A0FFE, // 0001 LDINT R2 4095 + 0x2C040202, // 0002 AND R1 R1 R2 + 0x540A0009, // 0003 LDINT R2 10 + 0x3C040202, // 0004 SHR R1 R1 R2 + 0x88080100, // 0005 GETMBR R2 R0 K0 + 0x540E02FF, // 0006 LDINT R3 768 + 0x2C080403, // 0007 AND R2 R2 R3 + 0x540E0005, // 0008 LDINT R3 6 + 0x38080403, // 0009 SHL R2 R2 R3 + 0x880C0101, // 000A GETMBR R3 R0 K1 + 0x54123FFE, // 000B LDINT R4 16383 + 0x2C0C0604, // 000C AND R3 R3 R4 + 0x30080403, // 000D OR R2 R2 R3 + 0x880C0101, // 000E GETMBR R3 R0 K1 + 0x5412000D, // 000F LDINT R4 14 + 0x3C0C0604, // 0010 SHR R3 R3 R4 + 0x60100018, // 0011 GETGBL R4 G24 + 0x58140002, // 0012 LDCONST R5 K2 + 0x5C180200, // 0013 MOVE R6 R1 + 0x5C1C0400, // 0014 MOVE R7 R2 + 0x5C200600, // 0015 MOVE R8 R3 + 0x7C100800, // 0016 CALL R4 4 + 0xB8160600, // 0017 GETNGBL R5 K3 + 0x88140B04, // 0018 GETMBR R5 R5 K4 + 0x8C140B05, // 0019 GETMET R5 R5 K5 + 0x5C1C0800, // 001A MOVE R7 R4 + 0x7C140400, // 001B CALL R5 2 + 0x00100805, // 001C ADD R4 R4 R5 + 0x80040800, // 001D RET 1 R4 }) ) ); @@ -195,596 +339,53 @@ be_local_closure(Matter_Device_mdns_remove_PASE, /* name */ /******************************************************************** -** Solidified function: compute_qrcode_content +** Solidified function: conf_to_log ********************************************************************/ -be_local_closure(Matter_Device_compute_qrcode_content, /* name */ - be_nested_proto( - 8, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[12]) { /* constants */ - /* K0 */ be_nested_str_weak(resize), - /* K1 */ be_nested_str_weak(setbits), - /* K2 */ be_const_int(3), - /* K3 */ be_nested_str_weak(vendorid), - /* K4 */ be_nested_str_weak(productid), - /* K5 */ be_nested_str_weak(root_discriminator), - /* K6 */ be_nested_str_weak(root_passcode), - /* K7 */ be_const_int(134217727), - /* K8 */ be_nested_str_weak(MT_X3A), - /* K9 */ be_nested_str_weak(matter), - /* K10 */ be_nested_str_weak(Base38), - /* K11 */ be_nested_str_weak(encode), - }), - be_str_weak(compute_qrcode_content), - &be_const_str_solidified, - ( &(const binstruction[40]) { /* code */ - 0x60040015, // 0000 GETGBL R1 G21 - 0x7C040000, // 0001 CALL R1 0 - 0x8C040300, // 0002 GETMET R1 R1 K0 - 0x540E000A, // 0003 LDINT R3 11 - 0x7C040400, // 0004 CALL R1 2 - 0x8C080301, // 0005 GETMET R2 R1 K1 - 0x58100002, // 0006 LDCONST R4 K2 - 0x5416000F, // 0007 LDINT R5 16 - 0x88180103, // 0008 GETMBR R6 R0 K3 - 0x7C080800, // 0009 CALL R2 4 - 0x8C080301, // 000A GETMET R2 R1 K1 - 0x54120012, // 000B LDINT R4 19 - 0x5416000F, // 000C LDINT R5 16 - 0x88180104, // 000D GETMBR R6 R0 K4 - 0x7C080800, // 000E CALL R2 4 - 0x8C080301, // 000F GETMET R2 R1 K1 - 0x54120024, // 0010 LDINT R4 37 - 0x54160007, // 0011 LDINT R5 8 - 0x541A0003, // 0012 LDINT R6 4 - 0x7C080800, // 0013 CALL R2 4 - 0x8C080301, // 0014 GETMET R2 R1 K1 - 0x5412002C, // 0015 LDINT R4 45 - 0x5416000B, // 0016 LDINT R5 12 - 0x88180105, // 0017 GETMBR R6 R0 K5 - 0x541E0FFE, // 0018 LDINT R7 4095 - 0x2C180C07, // 0019 AND R6 R6 R7 - 0x7C080800, // 001A CALL R2 4 - 0x8C080301, // 001B GETMET R2 R1 K1 - 0x54120038, // 001C LDINT R4 57 - 0x5416001A, // 001D LDINT R5 27 - 0x88180106, // 001E GETMBR R6 R0 K6 - 0x2C180D07, // 001F AND R6 R6 K7 - 0x7C080800, // 0020 CALL R2 4 - 0xB80A1200, // 0021 GETNGBL R2 K9 - 0x8808050A, // 0022 GETMBR R2 R2 K10 - 0x8C08050B, // 0023 GETMET R2 R2 K11 - 0x5C100200, // 0024 MOVE R4 R1 - 0x7C080400, // 0025 CALL R2 2 - 0x000A1002, // 0026 ADD R2 K8 R2 - 0x80040400, // 0027 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: _init_basic_commissioning -********************************************************************/ -be_local_closure(Matter_Device__init_basic_commissioning, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(sessions), - /* K1 */ be_nested_str_weak(count_active_fabrics), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(start_root_basic_commissioning), - }), - be_str_weak(_init_basic_commissioning), - &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x7C040200, // 0002 CALL R1 1 - 0x1C040302, // 0003 EQ R1 R1 K2 - 0x78060001, // 0004 JMPF R1 #0007 - 0x8C040103, // 0005 GETMET R1 R0 K3 - 0x7C040200, // 0006 CALL R1 1 - 0x80000000, // 0007 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: every_250ms -********************************************************************/ -be_local_closure(Matter_Device_every_250ms, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(message_handler), - /* K1 */ be_nested_str_weak(every_250ms), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(plugins), - /* K4 */ be_const_int(1), - }), - be_str_weak(every_250ms), - &be_const_str_solidified, - ( &(const binstruction[16]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x7C040200, // 0002 CALL R1 1 - 0x58040002, // 0003 LDCONST R1 K2 - 0x6008000C, // 0004 GETGBL R2 G12 - 0x880C0103, // 0005 GETMBR R3 R0 K3 - 0x7C080200, // 0006 CALL R2 1 - 0x14080202, // 0007 LT R2 R1 R2 - 0x780A0005, // 0008 JMPF R2 #000F - 0x88080103, // 0009 GETMBR R2 R0 K3 - 0x94080401, // 000A GETIDX R2 R2 R1 - 0x8C080501, // 000B GETMET R2 R2 K1 - 0x7C080200, // 000C CALL R2 1 - 0x00040304, // 000D ADD R1 R1 K4 - 0x7001FFF4, // 000E JMP #0004 - 0x80000000, // 000F RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: invoke_request -********************************************************************/ -be_local_closure(Matter_Device_invoke_request, /* name */ - be_nested_proto( - 12, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str_weak(endpoint), - /* K2 */ be_nested_str_weak(plugins), - /* K3 */ be_nested_str_weak(invoke_request), - /* K4 */ be_const_int(1), - /* K5 */ be_nested_str_weak(status), - /* K6 */ be_nested_str_weak(matter), - /* K7 */ be_nested_str_weak(UNSUPPORTED_ENDPOINT), - }), - be_str_weak(invoke_request), - &be_const_str_solidified, - ( &(const binstruction[24]) { /* code */ - 0x58100000, // 0000 LDCONST R4 K0 - 0x88140701, // 0001 GETMBR R5 R3 K1 - 0x6018000C, // 0002 GETGBL R6 G12 - 0x881C0102, // 0003 GETMBR R7 R0 K2 - 0x7C180200, // 0004 CALL R6 1 - 0x14180806, // 0005 LT R6 R4 R6 - 0x781A000C, // 0006 JMPF R6 #0014 - 0x88180102, // 0007 GETMBR R6 R0 K2 - 0x94180C04, // 0008 GETIDX R6 R6 R4 - 0x881C0D01, // 0009 GETMBR R7 R6 K1 - 0x1C1C0E05, // 000A EQ R7 R7 R5 - 0x781E0005, // 000B JMPF R7 #0012 - 0x8C1C0D03, // 000C GETMET R7 R6 K3 - 0x5C240200, // 000D MOVE R9 R1 - 0x5C280400, // 000E MOVE R10 R2 - 0x5C2C0600, // 000F MOVE R11 R3 - 0x7C1C0800, // 0010 CALL R7 4 - 0x80040E00, // 0011 RET 1 R7 - 0x00100904, // 0012 ADD R4 R4 K4 - 0x7001FFED, // 0013 JMP #0002 - 0xB81A0C00, // 0014 GETNGBL R6 K6 - 0x88180D07, // 0015 GETMBR R6 R6 K7 - 0x900E0A06, // 0016 SETMBR R3 K5 R6 - 0x80000000, // 0017 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: start_operational_discovery_deferred -********************************************************************/ -be_local_closure(Matter_Device_start_operational_discovery_deferred, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 1]) { - be_nested_proto( - 3, /* nstack */ - 0, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 2]) { /* upvals */ - be_local_const_upval(1, 0), - be_local_const_upval(1, 1), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(start_operational_discovery), - }), - be_str_weak(_X3Clambda_X3E), - &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x68000000, // 0000 GETUPV R0 U0 - 0x8C000100, // 0001 GETMET R0 R0 K0 - 0x68080001, // 0002 GETUPV R2 U1 - 0x7C000400, // 0003 CALL R0 2 - 0x80040000, // 0004 RET 1 R0 - }) - ), - }), - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(set_timer), - /* K2 */ be_const_int(0), - }), - be_str_weak(start_operational_discovery_deferred), - &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0xB80A0000, // 0000 GETNGBL R2 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x58100002, // 0002 LDCONST R4 K2 - 0x84140000, // 0003 CLOSURE R5 P0 - 0x7C080600, // 0004 CALL R2 3 - 0xA0000000, // 0005 CLOSE R0 - 0x80000000, // 0006 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_active_endpoints -********************************************************************/ -be_local_closure(Matter_Device_get_active_endpoints, /* name */ +be_local_closure(Matter_Device_conf_to_log, /* name */ be_nested_proto( 9, /* nstack */ - 2, /* argc */ - 2, /* varg */ + 1, /* argc */ + 4, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(plugins), - /* K1 */ be_nested_str_weak(get_endpoint), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(find), - /* K4 */ be_nested_str_weak(push), + /* K0 */ be_const_class(be_class_Matter_Device), + /* K1 */ be_nested_str_weak(), + /* K2 */ be_nested_str_weak(k2l), + /* K3 */ be_nested_str_weak(type), + /* K4 */ be_nested_str_weak(_X20_X25s_X3A_X25s), /* K5 */ be_nested_str_weak(stop_iteration), }), - be_str_weak(get_active_endpoints), + be_str_weak(conf_to_log), &be_const_str_solidified, - ( &(const binstruction[28]) { /* code */ - 0x60080012, // 0000 GETGBL R2 G18 - 0x7C080000, // 0001 CALL R2 0 + ( &(const binstruction[24]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x58080001, // 0001 LDCONST R2 K1 0x600C0010, // 0002 GETGBL R3 G16 - 0x88100100, // 0003 GETMBR R4 R0 K0 - 0x7C0C0200, // 0004 CALL R3 1 - 0xA8020011, // 0005 EXBLK 0 #0018 - 0x5C100600, // 0006 MOVE R4 R3 - 0x7C100000, // 0007 CALL R4 0 - 0x8C140901, // 0008 GETMET R5 R4 K1 - 0x7C140200, // 0009 CALL R5 1 - 0x78060002, // 000A JMPF R1 #000E - 0x1C180B02, // 000B EQ R6 R5 K2 - 0x781A0000, // 000C JMPF R6 #000E - 0x7001FFF7, // 000D JMP #0006 - 0x8C180503, // 000E GETMET R6 R2 K3 - 0x5C200A00, // 000F MOVE R8 R5 - 0x7C180400, // 0010 CALL R6 2 - 0x4C1C0000, // 0011 LDNIL R7 - 0x1C180C07, // 0012 EQ R6 R6 R7 - 0x781A0002, // 0013 JMPF R6 #0017 - 0x8C180504, // 0014 GETMET R6 R2 K4 - 0x5C200A00, // 0015 MOVE R8 R5 - 0x7C180400, // 0016 CALL R6 2 - 0x7001FFED, // 0017 JMP #0006 - 0x580C0005, // 0018 LDCONST R3 K5 - 0xAC0C0200, // 0019 CATCH R3 1 0 - 0xB0080000, // 001A RAISE 2 R0 R0 - 0x80040400, // 001B RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: start_commissioning_complete_deferred -********************************************************************/ -be_local_closure(Matter_Device_start_commissioning_complete_deferred, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 1]) { - be_nested_proto( - 3, /* nstack */ - 0, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 2]) { /* upvals */ - be_local_const_upval(1, 0), - be_local_const_upval(1, 1), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(start_commissioning_complete), - }), - be_str_weak(_X3Clambda_X3E), - &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x68000000, // 0000 GETUPV R0 U0 - 0x8C000100, // 0001 GETMET R0 R0 K0 - 0x68080001, // 0002 GETUPV R2 U1 - 0x7C000400, // 0003 CALL R0 2 - 0x80040000, // 0004 RET 1 R0 - }) - ), - }), - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(set_timer), - /* K2 */ be_const_int(0), - }), - be_str_weak(start_commissioning_complete_deferred), - &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0xB80A0000, // 0000 GETNGBL R2 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x58100002, // 0002 LDCONST R4 K2 - 0x84140000, // 0003 CLOSURE R5 P0 - 0x7C080600, // 0004 CALL R2 3 - 0xA0000000, // 0005 CLOSE R0 - 0x80000000, // 0006 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: _instantiate_plugins_from_config -********************************************************************/ -be_local_closure(Matter_Device__instantiate_plugins_from_config, /* name */ - be_nested_proto( - 18, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[30]) { /* constants */ - /* K0 */ be_nested_str_weak(k2l_num), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(log), - /* K3 */ be_nested_str_weak(MTR_X3A_X20Configuring_X20endpoints), - /* K4 */ be_const_int(2), - /* K5 */ be_nested_str_weak(plugins), - /* K6 */ be_nested_str_weak(push), - /* K7 */ be_nested_str_weak(matter), - /* K8 */ be_nested_str_weak(Plugin_Root), - /* K9 */ be_const_int(0), - /* K10 */ be_nested_str_weak(MTR_X3A_X20_X20_X20endpoint_X20_X3D_X20_X255i_X20type_X3A_X25s_X25s), - /* K11 */ be_nested_str_weak(root), - /* K12 */ be_nested_str_weak(), - /* K13 */ be_nested_str_weak(Plugin_Aggregator), - /* K14 */ be_nested_str_weak(find), - /* K15 */ be_nested_str_weak(type), - /* K16 */ be_nested_str_weak(MTR_X3A_X20no_X20class_X20name_X2C_X20skipping), - /* K17 */ be_const_int(3), - /* K18 */ be_nested_str_weak(MTR_X3A_X20only_X20one_X20root_X20node_X20allowed), - /* K19 */ be_nested_str_weak(plugins_classes), - /* K20 */ be_nested_str_weak(MTR_X3A_X20unknown_X20class_X20name_X20_X27), - /* K21 */ be_nested_str_weak(_X27_X20skipping), - /* K22 */ be_nested_str_weak(conf_to_log), - /* K23 */ be_nested_str_weak(MTR_X3A_X20Exception), - /* K24 */ be_nested_str_weak(_X7C), - /* K25 */ be_nested_str_weak(stop_iteration), - /* K26 */ be_nested_str_weak(aggregator), - /* K27 */ be_nested_str_weak(publish_result), - /* K28 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Initialized_X22_X3A1_X7D_X7D), - /* K29 */ be_nested_str_weak(Matter), - }), - be_str_weak(_instantiate_plugins_from_config), - &be_const_str_solidified, - ( &(const binstruction[152]) { /* code */ - 0x8C080100, // 0000 GETMET R2 R0 K0 - 0x5C100200, // 0001 MOVE R4 R1 - 0x7C080400, // 0002 CALL R2 2 - 0xB80E0200, // 0003 GETNGBL R3 K1 - 0x8C0C0702, // 0004 GETMET R3 R3 K2 - 0x58140003, // 0005 LDCONST R5 K3 - 0x58180004, // 0006 LDCONST R6 K4 - 0x7C0C0600, // 0007 CALL R3 3 - 0x880C0105, // 0008 GETMBR R3 R0 K5 - 0x8C0C0706, // 0009 GETMET R3 R3 K6 - 0xB8160E00, // 000A GETNGBL R5 K7 - 0x8C140B08, // 000B GETMET R5 R5 K8 - 0x5C1C0000, // 000C MOVE R7 R0 - 0x58200009, // 000D LDCONST R8 K9 - 0x60240013, // 000E GETGBL R9 G19 - 0x7C240000, // 000F CALL R9 0 - 0x7C140800, // 0010 CALL R5 4 - 0x7C0C0400, // 0011 CALL R3 2 - 0xB80E0200, // 0012 GETNGBL R3 K1 - 0x8C0C0702, // 0013 GETMET R3 R3 K2 - 0x60140018, // 0014 GETGBL R5 G24 - 0x5818000A, // 0015 LDCONST R6 K10 - 0x581C0009, // 0016 LDCONST R7 K9 - 0x5820000B, // 0017 LDCONST R8 K11 - 0x5824000C, // 0018 LDCONST R9 K12 - 0x7C140800, // 0019 CALL R5 4 - 0x58180004, // 001A LDCONST R6 K4 - 0x7C0C0600, // 001B CALL R3 3 - 0x880C0105, // 001C GETMBR R3 R0 K5 - 0x8C0C0706, // 001D GETMET R3 R3 K6 - 0xB8160E00, // 001E GETNGBL R5 K7 - 0x8C140B0D, // 001F GETMET R5 R5 K13 - 0x5C1C0000, // 0020 MOVE R7 R0 - 0x5422FEFF, // 0021 LDINT R8 65280 - 0x60240013, // 0022 GETGBL R9 G19 - 0x7C240000, // 0023 CALL R9 0 - 0x7C140800, // 0024 CALL R5 4 - 0x7C0C0400, // 0025 CALL R3 2 - 0x600C0010, // 0026 GETGBL R3 G16 - 0x5C100400, // 0027 MOVE R4 R2 - 0x7C0C0200, // 0028 CALL R3 1 - 0xA802005A, // 0029 EXBLK 0 #0085 - 0x5C100600, // 002A MOVE R4 R3 - 0x7C100000, // 002B CALL R4 0 - 0x1C140909, // 002C EQ R5 R4 K9 - 0x78160000, // 002D JMPF R5 #002F - 0x7001FFFA, // 002E JMP #002A - 0xA8020042, // 002F EXBLK 0 #0073 - 0x60140008, // 0030 GETGBL R5 G8 - 0x5C180800, // 0031 MOVE R6 R4 - 0x7C140200, // 0032 CALL R5 1 - 0x94140205, // 0033 GETIDX R5 R1 R5 - 0x8C180B0E, // 0034 GETMET R6 R5 K14 - 0x5820000F, // 0035 LDCONST R8 K15 - 0x7C180400, // 0036 CALL R6 2 - 0x4C1C0000, // 0037 LDNIL R7 - 0x1C1C0C07, // 0038 EQ R7 R6 R7 - 0x781E0006, // 0039 JMPF R7 #0041 - 0xB81E0200, // 003A GETNGBL R7 K1 - 0x8C1C0F02, // 003B GETMET R7 R7 K2 - 0x58240010, // 003C LDCONST R9 K16 - 0x58280011, // 003D LDCONST R10 K17 - 0x7C1C0600, // 003E CALL R7 3 - 0xA8040001, // 003F EXBLK 1 1 - 0x7001FFE8, // 0040 JMP #002A - 0x1C1C0D0B, // 0041 EQ R7 R6 K11 - 0x781E0006, // 0042 JMPF R7 #004A - 0xB81E0200, // 0043 GETNGBL R7 K1 - 0x8C1C0F02, // 0044 GETMET R7 R7 K2 - 0x58240012, // 0045 LDCONST R9 K18 - 0x58280011, // 0046 LDCONST R10 K17 - 0x7C1C0600, // 0047 CALL R7 3 - 0xA8040001, // 0048 EXBLK 1 1 - 0x7001FFDF, // 0049 JMP #002A - 0x881C0113, // 004A GETMBR R7 R0 K19 - 0x8C1C0F0E, // 004B GETMET R7 R7 K14 - 0x5C240C00, // 004C MOVE R9 R6 - 0x7C1C0400, // 004D CALL R7 2 - 0x4C200000, // 004E LDNIL R8 - 0x1C200E08, // 004F EQ R8 R7 R8 - 0x7822000A, // 0050 JMPF R8 #005C - 0xB8220200, // 0051 GETNGBL R8 K1 - 0x8C201102, // 0052 GETMET R8 R8 K2 - 0x60280008, // 0053 GETGBL R10 G8 - 0x5C2C0C00, // 0054 MOVE R11 R6 - 0x7C280200, // 0055 CALL R10 1 - 0x002A280A, // 0056 ADD R10 K20 R10 - 0x00281515, // 0057 ADD R10 R10 K21 - 0x582C0004, // 0058 LDCONST R11 K4 - 0x7C200600, // 0059 CALL R8 3 - 0xA8040001, // 005A EXBLK 1 1 - 0x7001FFCD, // 005B JMP #002A - 0x5C200E00, // 005C MOVE R8 R7 - 0x5C240000, // 005D MOVE R9 R0 - 0x5C280800, // 005E MOVE R10 R4 - 0x5C2C0A00, // 005F MOVE R11 R5 - 0x7C200600, // 0060 CALL R8 3 - 0x88240105, // 0061 GETMBR R9 R0 K5 - 0x8C241306, // 0062 GETMET R9 R9 K6 - 0x5C2C1000, // 0063 MOVE R11 R8 - 0x7C240400, // 0064 CALL R9 2 - 0xB8260200, // 0065 GETNGBL R9 K1 - 0x8C241302, // 0066 GETMET R9 R9 K2 - 0x602C0018, // 0067 GETGBL R11 G24 - 0x5830000A, // 0068 LDCONST R12 K10 - 0x5C340800, // 0069 MOVE R13 R4 - 0x5C380C00, // 006A MOVE R14 R6 - 0x8C3C0116, // 006B GETMET R15 R0 K22 - 0x5C440A00, // 006C MOVE R17 R5 - 0x7C3C0400, // 006D CALL R15 2 - 0x7C2C0800, // 006E CALL R11 4 - 0x58300004, // 006F LDCONST R12 K4 - 0x7C240600, // 0070 CALL R9 3 - 0xA8040001, // 0071 EXBLK 1 1 - 0x70020010, // 0072 JMP #0084 - 0xAC140002, // 0073 CATCH R5 0 2 - 0x7002000D, // 0074 JMP #0083 - 0xB81E0200, // 0075 GETNGBL R7 K1 - 0x8C1C0F02, // 0076 GETMET R7 R7 K2 - 0x60240008, // 0077 GETGBL R9 G8 - 0x5C280A00, // 0078 MOVE R10 R5 - 0x7C240200, // 0079 CALL R9 1 - 0x00262E09, // 007A ADD R9 K23 R9 - 0x00241318, // 007B ADD R9 R9 K24 - 0x60280008, // 007C GETGBL R10 G8 - 0x5C2C0C00, // 007D MOVE R11 R6 - 0x7C280200, // 007E CALL R10 1 - 0x0024120A, // 007F ADD R9 R9 R10 - 0x58280004, // 0080 LDCONST R10 K4 - 0x7C1C0600, // 0081 CALL R7 3 - 0x70020000, // 0082 JMP #0084 - 0xB0080000, // 0083 RAISE 2 R0 R0 - 0x7001FFA4, // 0084 JMP #002A - 0x580C0019, // 0085 LDCONST R3 K25 - 0xAC0C0200, // 0086 CATCH R3 1 0 - 0xB0080000, // 0087 RAISE 2 R0 R0 - 0xB80E0200, // 0088 GETNGBL R3 K1 - 0x8C0C0702, // 0089 GETMET R3 R3 K2 - 0x60140018, // 008A GETGBL R5 G24 - 0x5818000A, // 008B LDCONST R6 K10 - 0x541EFEFF, // 008C LDINT R7 65280 - 0x5820001A, // 008D LDCONST R8 K26 - 0x5824000C, // 008E LDCONST R9 K12 - 0x7C140800, // 008F CALL R5 4 - 0x58180004, // 0090 LDCONST R6 K4 - 0x7C0C0600, // 0091 CALL R3 3 - 0xB80E0200, // 0092 GETNGBL R3 K1 - 0x8C0C071B, // 0093 GETMET R3 R3 K27 - 0x5814001C, // 0094 LDCONST R5 K28 - 0x5818001D, // 0095 LDCONST R6 K29 - 0x7C0C0600, // 0096 CALL R3 3 - 0x80000000, // 0097 RET 0 + 0x8C100302, // 0003 GETMET R4 R1 K2 + 0x5C180000, // 0004 MOVE R6 R0 + 0x7C100400, // 0005 CALL R4 2 + 0x7C0C0200, // 0006 CALL R3 1 + 0xA802000B, // 0007 EXBLK 0 #0014 + 0x5C100600, // 0008 MOVE R4 R3 + 0x7C100000, // 0009 CALL R4 0 + 0x1C140903, // 000A EQ R5 R4 K3 + 0x78160000, // 000B JMPF R5 #000D + 0x7001FFFA, // 000C JMP #0008 + 0x60140018, // 000D GETGBL R5 G24 + 0x58180004, // 000E LDCONST R6 K4 + 0x5C1C0800, // 000F MOVE R7 R4 + 0x94200004, // 0010 GETIDX R8 R0 R4 + 0x7C140600, // 0011 CALL R5 3 + 0x00080405, // 0012 ADD R2 R2 R5 + 0x7001FFF3, // 0013 JMP #0008 + 0x580C0005, // 0014 LDCONST R3 K5 + 0xAC0C0200, // 0015 CATCH R3 1 0 + 0xB0080000, // 0016 RAISE 2 R0 R0 + 0x80040400, // 0017 RET 1 R2 }) ) ); @@ -1033,536 +634,12 @@ be_local_closure(Matter_Device__mdns_announce_hostname, /* name */ /******************************************************************** -** Solidified function: bridge_remove_endpoint +** Solidified function: invoke_request ********************************************************************/ -be_local_closure(Matter_Device_bridge_remove_endpoint, /* name */ +be_local_closure(Matter_Device_invoke_request, /* name */ be_nested_proto( - 11, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[18]) { /* constants */ - /* K0 */ be_nested_str_weak(json), - /* K1 */ be_nested_str_weak(plugins_config), - /* K2 */ be_nested_str_weak(contains), - /* K3 */ be_nested_str_weak(tasmota), - /* K4 */ be_nested_str_weak(log), - /* K5 */ be_nested_str_weak(MTR_X3A_X20Cannot_X20remove_X20an_X20enpoint_X20not_X20configured_X3A_X20), - /* K6 */ be_const_int(3), - /* K7 */ be_nested_str_weak(MTR_X3A_X20deleting_X20endpoint_X20_X3D_X20_X25i), - /* K8 */ be_const_int(2), - /* K9 */ be_nested_str_weak(remove), - /* K10 */ be_nested_str_weak(plugins_persist), - /* K11 */ be_const_int(0), - /* K12 */ be_nested_str_weak(plugins), - /* K13 */ be_nested_str_weak(get_endpoint), - /* K14 */ be_const_int(1), - /* K15 */ be_nested_str_weak(clean_remotes), - /* K16 */ be_nested_str_weak(save_param), - /* K17 */ be_nested_str_weak(signal_endpoints_changed), - }), - be_str_weak(bridge_remove_endpoint), - &be_const_str_solidified, - ( &(const binstruction[58]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0x600C0008, // 0001 GETGBL R3 G8 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C0C0200, // 0003 CALL R3 1 - 0x4C100000, // 0004 LDNIL R4 - 0x4C140000, // 0005 LDNIL R5 - 0x88180101, // 0006 GETMBR R6 R0 K1 - 0x8C180D02, // 0007 GETMET R6 R6 K2 - 0x5C200600, // 0008 MOVE R8 R3 - 0x7C180400, // 0009 CALL R6 2 - 0x741A0005, // 000A JMPT R6 #0011 - 0xB81A0600, // 000B GETNGBL R6 K3 - 0x8C180D04, // 000C GETMET R6 R6 K4 - 0x00220A03, // 000D ADD R8 K5 R3 - 0x58240006, // 000E LDCONST R9 K6 - 0x7C180600, // 000F CALL R6 3 - 0x80000C00, // 0010 RET 0 - 0xB81A0600, // 0011 GETNGBL R6 K3 - 0x8C180D04, // 0012 GETMET R6 R6 K4 - 0x60200018, // 0013 GETGBL R8 G24 - 0x58240007, // 0014 LDCONST R9 K7 - 0x5C280200, // 0015 MOVE R10 R1 - 0x7C200400, // 0016 CALL R8 2 - 0x58240008, // 0017 LDCONST R9 K8 - 0x7C180600, // 0018 CALL R6 3 - 0x88180101, // 0019 GETMBR R6 R0 K1 - 0x8C180D09, // 001A GETMET R6 R6 K9 - 0x5C200600, // 001B MOVE R8 R3 - 0x7C180400, // 001C CALL R6 2 - 0x50180200, // 001D LDBOOL R6 1 0 - 0x90021406, // 001E SETMBR R0 K10 R6 - 0x5818000B, // 001F LDCONST R6 K11 - 0x601C000C, // 0020 GETGBL R7 G12 - 0x8820010C, // 0021 GETMBR R8 R0 K12 - 0x7C1C0200, // 0022 CALL R7 1 - 0x141C0C07, // 0023 LT R7 R6 R7 - 0x781E000D, // 0024 JMPF R7 #0033 - 0x881C010C, // 0025 GETMBR R7 R0 K12 - 0x941C0E06, // 0026 GETIDX R7 R7 R6 - 0x8C1C0F0D, // 0027 GETMET R7 R7 K13 - 0x7C1C0200, // 0028 CALL R7 1 - 0x1C1C0207, // 0029 EQ R7 R1 R7 - 0x781E0005, // 002A JMPF R7 #0031 - 0x881C010C, // 002B GETMBR R7 R0 K12 - 0x8C1C0F09, // 002C GETMET R7 R7 K9 - 0x5C240C00, // 002D MOVE R9 R6 - 0x7C1C0400, // 002E CALL R7 2 - 0x70020002, // 002F JMP #0033 - 0x70020000, // 0030 JMP #0032 - 0x00180D0E, // 0031 ADD R6 R6 K14 - 0x7001FFEC, // 0032 JMP #0020 - 0x8C1C010F, // 0033 GETMET R7 R0 K15 - 0x7C1C0200, // 0034 CALL R7 1 - 0x8C1C0110, // 0035 GETMET R7 R0 K16 - 0x7C1C0200, // 0036 CALL R7 1 - 0x8C1C0111, // 0037 GETMET R7 R0 K17 - 0x7C1C0200, // 0038 CALL R7 1 - 0x80000000, // 0039 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: find_plugin_by_endpoint -********************************************************************/ -be_local_closure(Matter_Device_find_plugin_by_endpoint, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str_weak(plugins), - /* K2 */ be_nested_str_weak(get_endpoint), - /* K3 */ be_const_int(1), - }), - be_str_weak(find_plugin_by_endpoint), - &be_const_str_solidified, - ( &(const binstruction[17]) { /* code */ - 0x58080000, // 0000 LDCONST R2 K0 - 0x600C000C, // 0001 GETGBL R3 G12 - 0x88100101, // 0002 GETMBR R4 R0 K1 - 0x7C0C0200, // 0003 CALL R3 1 - 0x140C0403, // 0004 LT R3 R2 R3 - 0x780E0008, // 0005 JMPF R3 #000F - 0x880C0101, // 0006 GETMBR R3 R0 K1 - 0x940C0602, // 0007 GETIDX R3 R3 R2 - 0x8C100702, // 0008 GETMET R4 R3 K2 - 0x7C100200, // 0009 CALL R4 1 - 0x1C100801, // 000A EQ R4 R4 R1 - 0x78120000, // 000B JMPF R4 #000D - 0x80040600, // 000C RET 1 R3 - 0x00080503, // 000D ADD R2 R2 K3 - 0x7001FFF1, // 000E JMP #0001 - 0x4C0C0000, // 000F LDNIL R3 - 0x80040600, // 0010 RET 1 R3 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: start_mdns_announce_hostnames -********************************************************************/ -be_local_closure(Matter_Device_start_mdns_announce_hostnames, /* name */ - be_nested_proto( - 6, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 2]) { - be_nested_proto( - 4, /* nstack */ - 0, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(_mdns_announce_hostname), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(remove_rule), - /* K3 */ be_nested_str_weak(Wifi_X23Connected), - /* K4 */ be_nested_str_weak(matter_mdns_host), - }), - be_str_weak(_anonymous_), - &be_const_str_solidified, - ( &(const binstruction[10]) { /* code */ - 0x68000000, // 0000 GETUPV R0 U0 - 0x8C000100, // 0001 GETMET R0 R0 K0 - 0x50080000, // 0002 LDBOOL R2 0 0 - 0x7C000400, // 0003 CALL R0 2 - 0xB8020200, // 0004 GETNGBL R0 K1 - 0x8C000102, // 0005 GETMET R0 R0 K2 - 0x58080003, // 0006 LDCONST R2 K3 - 0x580C0004, // 0007 LDCONST R3 K4 - 0x7C000600, // 0008 CALL R0 3 - 0x80000000, // 0009 RET 0 - }) - ), - be_nested_proto( - 4, /* nstack */ - 0, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(_mdns_announce_hostname), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(remove_rule), - /* K3 */ be_nested_str_weak(Eth_X23Connected), - /* K4 */ be_nested_str_weak(matter_mdns_host), - }), - be_str_weak(_anonymous_), - &be_const_str_solidified, - ( &(const binstruction[10]) { /* code */ - 0x68000000, // 0000 GETUPV R0 U0 - 0x8C000100, // 0001 GETMET R0 R0 K0 - 0x50080200, // 0002 LDBOOL R2 1 0 - 0x7C000400, // 0003 CALL R0 2 - 0xB8020200, // 0004 GETNGBL R0 K1 - 0x8C000102, // 0005 GETMET R0 R0 K2 - 0x58080003, // 0006 LDCONST R2 K3 - 0x580C0004, // 0007 LDCONST R3 K4 - 0x7C000600, // 0008 CALL R0 3 - 0x80000000, // 0009 RET 0 - }) - ), - }), - 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(wifi), - /* K2 */ be_nested_str_weak(up), - /* K3 */ be_nested_str_weak(_mdns_announce_hostname), - /* K4 */ be_nested_str_weak(add_rule), - /* K5 */ be_nested_str_weak(Wifi_X23Connected), - /* K6 */ be_nested_str_weak(matter_mdns_host), - /* K7 */ be_nested_str_weak(eth), - /* K8 */ be_nested_str_weak(Eth_X23Connected), - }), - be_str_weak(start_mdns_announce_hostnames), - &be_const_str_solidified, - ( &(const binstruction[32]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x7C040200, // 0002 CALL R1 1 - 0x94040302, // 0003 GETIDX R1 R1 K2 - 0x78060003, // 0004 JMPF R1 #0009 - 0x8C040103, // 0005 GETMET R1 R0 K3 - 0x500C0000, // 0006 LDBOOL R3 0 0 - 0x7C040400, // 0007 CALL R1 2 - 0x70020005, // 0008 JMP #000F - 0xB8060000, // 0009 GETNGBL R1 K0 - 0x8C040304, // 000A GETMET R1 R1 K4 - 0x580C0005, // 000B LDCONST R3 K5 - 0x84100000, // 000C CLOSURE R4 P0 - 0x58140006, // 000D LDCONST R5 K6 - 0x7C040800, // 000E CALL R1 4 - 0xB8060000, // 000F GETNGBL R1 K0 - 0x8C040307, // 0010 GETMET R1 R1 K7 - 0x7C040200, // 0011 CALL R1 1 - 0x94040302, // 0012 GETIDX R1 R1 K2 - 0x78060003, // 0013 JMPF R1 #0018 - 0x8C040103, // 0014 GETMET R1 R0 K3 - 0x500C0200, // 0015 LDBOOL R3 1 0 - 0x7C040400, // 0016 CALL R1 2 - 0x70020005, // 0017 JMP #001E - 0xB8060000, // 0018 GETNGBL R1 K0 - 0x8C040304, // 0019 GETMET R1 R1 K4 - 0x580C0008, // 001A LDCONST R3 K8 - 0x84100001, // 001B CLOSURE R4 P1 - 0x58140006, // 001C LDCONST R5 K6 - 0x7C040800, // 001D CALL R1 4 - 0xA0000000, // 001E CLOSE R0 - 0x80000000, // 001F RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: _start_udp -********************************************************************/ -be_local_closure(Matter_Device__start_udp, /* name */ - be_nested_proto( - 7, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 1]) { - be_nested_proto( - 8, /* nstack */ - 3, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(msg_received), - }), - be_str_weak(_X3Clambda_X3E), - &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0x680C0000, // 0000 GETUPV R3 U0 - 0x8C0C0700, // 0001 GETMET R3 R3 K0 - 0x5C140000, // 0002 MOVE R5 R0 - 0x5C180200, // 0003 MOVE R6 R1 - 0x5C1C0400, // 0004 MOVE R7 R2 - 0x7C0C0800, // 0005 CALL R3 4 - 0x80040600, // 0006 RET 1 R3 - }) - ), - }), - 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(udp_server), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(log), - /* K3 */ be_nested_str_weak(MTR_X3A_X20Starting_X20UDP_X20server_X20on_X20port_X3A_X20), - /* K4 */ be_const_int(2), - /* K5 */ be_nested_str_weak(matter), - /* K6 */ be_nested_str_weak(UDPServer), - /* K7 */ be_nested_str_weak(), - /* K8 */ be_nested_str_weak(start), - }), - be_str_weak(_start_udp), - &be_const_str_solidified, - ( &(const binstruction[28]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x780A0000, // 0001 JMPF R2 #0003 - 0x80000400, // 0002 RET 0 - 0x4C080000, // 0003 LDNIL R2 - 0x1C080202, // 0004 EQ R2 R1 R2 - 0x780A0000, // 0005 JMPF R2 #0007 - 0x540615A3, // 0006 LDINT R1 5540 - 0xB80A0200, // 0007 GETNGBL R2 K1 - 0x8C080502, // 0008 GETMET R2 R2 K2 - 0x60100008, // 0009 GETGBL R4 G8 - 0x5C140200, // 000A MOVE R5 R1 - 0x7C100200, // 000B CALL R4 1 - 0x00120604, // 000C ADD R4 K3 R4 - 0x58140004, // 000D LDCONST R5 K4 - 0x7C080600, // 000E CALL R2 3 - 0xB80A0A00, // 000F GETNGBL R2 K5 - 0x8C080506, // 0010 GETMET R2 R2 K6 - 0x5C100000, // 0011 MOVE R4 R0 - 0x58140007, // 0012 LDCONST R5 K7 - 0x5C180200, // 0013 MOVE R6 R1 - 0x7C080800, // 0014 CALL R2 4 - 0x90020002, // 0015 SETMBR R0 K0 R2 - 0x88080100, // 0016 GETMBR R2 R0 K0 - 0x8C080508, // 0017 GETMET R2 R2 K8 - 0x84100000, // 0018 CLOSURE R4 P0 - 0x7C080400, // 0019 CALL R2 2 - 0xA0000000, // 001A CLOSE R0 - 0x80000000, // 001B RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: signal_endpoints_changed -********************************************************************/ -be_local_closure(Matter_Device_signal_endpoints_changed, /* name */ - be_nested_proto( - 7, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(attribute_updated), - /* K1 */ be_const_int(0), - /* K2 */ be_const_int(3), - }), - be_str_weak(signal_endpoints_changed), - &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x580C0001, // 0001 LDCONST R3 K1 - 0x5412001C, // 0002 LDINT R4 29 - 0x58140002, // 0003 LDCONST R5 K2 - 0x50180000, // 0004 LDBOOL R6 0 0 - 0x7C040A00, // 0005 CALL R1 5 - 0x8C040100, // 0006 GETMET R1 R0 K0 - 0x540EFEFF, // 0007 LDINT R3 65280 - 0x5412001C, // 0008 LDINT R4 29 - 0x58140002, // 0009 LDCONST R5 K2 - 0x50180000, // 000A LDBOOL R6 0 0 - 0x7C040A00, // 000B CALL R1 5 - 0x80000000, // 000C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: sort_distinct -********************************************************************/ -be_local_closure(Matter_Device_sort_distinct, /* name */ - be_nested_proto( - 7, /* nstack */ - 1, /* argc */ - 4, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_const_class(be_class_Matter_Device), - /* K1 */ be_const_int(1), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(stop_iteration), - /* K4 */ be_nested_str_weak(remove), - }), - be_str_weak(sort_distinct), - &be_const_str_solidified, - ( &(const binstruction[53]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x60080010, // 0001 GETGBL R2 G16 - 0x600C000C, // 0002 GETGBL R3 G12 - 0x5C100000, // 0003 MOVE R4 R0 - 0x7C0C0200, // 0004 CALL R3 1 - 0x040C0701, // 0005 SUB R3 R3 K1 - 0x400E0203, // 0006 CONNECT R3 K1 R3 - 0x7C080200, // 0007 CALL R2 1 - 0xA8020010, // 0008 EXBLK 0 #001A - 0x5C0C0400, // 0009 MOVE R3 R2 - 0x7C0C0000, // 000A CALL R3 0 - 0x94100003, // 000B GETIDX R4 R0 R3 - 0x5C140600, // 000C MOVE R5 R3 - 0x24180B02, // 000D GT R6 R5 K2 - 0x781A0008, // 000E JMPF R6 #0018 - 0x04180B01, // 000F SUB R6 R5 K1 - 0x94180006, // 0010 GETIDX R6 R0 R6 - 0x24180C04, // 0011 GT R6 R6 R4 - 0x781A0004, // 0012 JMPF R6 #0018 - 0x04180B01, // 0013 SUB R6 R5 K1 - 0x94180006, // 0014 GETIDX R6 R0 R6 - 0x98000A06, // 0015 SETIDX R0 R5 R6 - 0x04140B01, // 0016 SUB R5 R5 K1 - 0x7001FFF4, // 0017 JMP #000D - 0x98000A04, // 0018 SETIDX R0 R5 R4 - 0x7001FFEE, // 0019 JMP #0009 - 0x58080003, // 001A LDCONST R2 K3 - 0xAC080200, // 001B CATCH R2 1 0 - 0xB0080000, // 001C RAISE 2 R0 R0 - 0x58080001, // 001D LDCONST R2 K1 - 0x600C000C, // 001E GETGBL R3 G12 - 0x5C100000, // 001F MOVE R4 R0 - 0x7C0C0200, // 0020 CALL R3 1 - 0x180C0701, // 0021 LE R3 R3 K1 - 0x780E0000, // 0022 JMPF R3 #0024 - 0x80040000, // 0023 RET 1 R0 - 0x940C0102, // 0024 GETIDX R3 R0 K2 - 0x6010000C, // 0025 GETGBL R4 G12 - 0x5C140000, // 0026 MOVE R5 R0 - 0x7C100200, // 0027 CALL R4 1 - 0x14100404, // 0028 LT R4 R2 R4 - 0x78120009, // 0029 JMPF R4 #0034 - 0x94100002, // 002A GETIDX R4 R0 R2 - 0x1C100803, // 002B EQ R4 R4 R3 - 0x78120003, // 002C JMPF R4 #0031 - 0x8C100104, // 002D GETMET R4 R0 K4 - 0x5C180400, // 002E MOVE R6 R2 - 0x7C100400, // 002F CALL R4 2 - 0x70020001, // 0030 JMP #0033 - 0x940C0002, // 0031 GETIDX R3 R0 R2 - 0x00080501, // 0032 ADD R2 R2 K1 - 0x7001FFF0, // 0033 JMP #0025 - 0x80040000, // 0034 RET 1 R0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: is_root_commissioning_open -********************************************************************/ -be_local_closure(Matter_Device_is_root_commissioning_open, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(commissioning_open), - /* K1 */ be_nested_str_weak(commissioning_admin_fabric), - }), - be_str_weak(is_root_commissioning_open), - &be_const_str_solidified, - ( &(const binstruction[11]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x4C080000, // 0001 LDNIL R2 - 0x20040202, // 0002 NE R1 R1 R2 - 0x78060003, // 0003 JMPF R1 #0008 - 0x88040101, // 0004 GETMBR R1 R0 K1 - 0x4C080000, // 0005 LDNIL R2 - 0x1C040202, // 0006 EQ R1 R1 R2 - 0x74060000, // 0007 JMPT R1 #0009 - 0x50040001, // 0008 LDBOOL R1 0 1 - 0x50040200, // 0009 LDBOOL R1 1 0 - 0x80040200, // 000A RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: register_http_remote -********************************************************************/ -be_local_closure(Matter_Device_register_http_remote, /* name */ - be_nested_proto( - 9, /* nstack */ - 3, /* argc */ + 12, /* nstack */ + 4, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -1570,60 +647,42 @@ be_local_closure(Matter_Device_register_http_remote, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str_weak(http_remotes), - /* K1 */ be_nested_str_weak(contains), - /* K2 */ be_nested_str_weak(get_timeout), - /* K3 */ be_nested_str_weak(set_timeout), - /* K4 */ be_nested_str_weak(matter), - /* K5 */ be_nested_str_weak(HTTP_remote), - /* K6 */ be_nested_str_weak(plugins_config_remotes), - /* K7 */ be_nested_str_weak(set_info), + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_weak(endpoint), + /* K2 */ be_nested_str_weak(plugins), + /* K3 */ be_nested_str_weak(invoke_request), + /* K4 */ be_const_int(1), + /* K5 */ be_nested_str_weak(status), + /* K6 */ be_nested_str_weak(matter), + /* K7 */ be_nested_str_weak(UNSUPPORTED_ENDPOINT), }), - be_str_weak(register_http_remote), + be_str_weak(invoke_request), &be_const_str_solidified, - ( &(const binstruction[42]) { /* code */ - 0x880C0100, // 0000 GETMBR R3 R0 K0 - 0x4C100000, // 0001 LDNIL R4 - 0x1C0C0604, // 0002 EQ R3 R3 R4 - 0x780E0002, // 0003 JMPF R3 #0007 - 0x600C0013, // 0004 GETGBL R3 G19 - 0x7C0C0000, // 0005 CALL R3 0 - 0x90020003, // 0006 SETMBR R0 K0 R3 - 0x4C0C0000, // 0007 LDNIL R3 - 0x88100100, // 0008 GETMBR R4 R0 K0 - 0x8C100901, // 0009 GETMET R4 R4 K1 - 0x5C180200, // 000A MOVE R6 R1 - 0x7C100400, // 000B CALL R4 2 - 0x78120009, // 000C JMPF R4 #0017 - 0x88100100, // 000D GETMBR R4 R0 K0 - 0x940C0801, // 000E GETIDX R3 R4 R1 - 0x8C140702, // 000F GETMET R5 R3 K2 - 0x7C140200, // 0010 CALL R5 1 - 0x14140405, // 0011 LT R5 R2 R5 - 0x78160002, // 0012 JMPF R5 #0016 - 0x8C140703, // 0013 GETMET R5 R3 K3 - 0x5C1C0400, // 0014 MOVE R7 R2 - 0x7C140400, // 0015 CALL R5 2 - 0x70020011, // 0016 JMP #0029 - 0xB8120800, // 0017 GETNGBL R4 K4 - 0x8C100905, // 0018 GETMET R4 R4 K5 - 0x5C180000, // 0019 MOVE R6 R0 - 0x5C1C0200, // 001A MOVE R7 R1 - 0x5C200400, // 001B MOVE R8 R2 - 0x7C100800, // 001C CALL R4 4 - 0x5C0C0800, // 001D MOVE R3 R4 - 0x88100106, // 001E GETMBR R4 R0 K6 - 0x8C100901, // 001F GETMET R4 R4 K1 - 0x5C180200, // 0020 MOVE R6 R1 - 0x7C100400, // 0021 CALL R4 2 - 0x78120003, // 0022 JMPF R4 #0027 - 0x8C100707, // 0023 GETMET R4 R3 K7 - 0x88180106, // 0024 GETMBR R6 R0 K6 - 0x94180C01, // 0025 GETIDX R6 R6 R1 - 0x7C100400, // 0026 CALL R4 2 - 0x88100100, // 0027 GETMBR R4 R0 K0 - 0x98100203, // 0028 SETIDX R4 R1 R3 - 0x80040600, // 0029 RET 1 R3 + ( &(const binstruction[24]) { /* code */ + 0x58100000, // 0000 LDCONST R4 K0 + 0x88140701, // 0001 GETMBR R5 R3 K1 + 0x6018000C, // 0002 GETGBL R6 G12 + 0x881C0102, // 0003 GETMBR R7 R0 K2 + 0x7C180200, // 0004 CALL R6 1 + 0x14180806, // 0005 LT R6 R4 R6 + 0x781A000C, // 0006 JMPF R6 #0014 + 0x88180102, // 0007 GETMBR R6 R0 K2 + 0x94180C04, // 0008 GETIDX R6 R6 R4 + 0x881C0D01, // 0009 GETMBR R7 R6 K1 + 0x1C1C0E05, // 000A EQ R7 R7 R5 + 0x781E0005, // 000B JMPF R7 #0012 + 0x8C1C0D03, // 000C GETMET R7 R6 K3 + 0x5C240200, // 000D MOVE R9 R1 + 0x5C280400, // 000E MOVE R10 R2 + 0x5C2C0600, // 000F MOVE R11 R3 + 0x7C1C0800, // 0010 CALL R7 4 + 0x80040E00, // 0011 RET 1 R7 + 0x00100904, // 0012 ADD R4 R4 K4 + 0x7001FFED, // 0013 JMP #0002 + 0xB81A0C00, // 0014 GETNGBL R6 K6 + 0x88180D07, // 0015 GETMBR R6 R6 K7 + 0x900E0A06, // 0016 SETMBR R3 K5 R6 + 0x80000000, // 0017 RET 0 }) ) ); @@ -1631,362 +690,9 @@ be_local_closure(Matter_Device_register_http_remote, /* name */ /******************************************************************** -** Solidified function: bridge_add_endpoint +** Solidified function: MtrInfo ********************************************************************/ -be_local_closure(Matter_Device_bridge_add_endpoint, /* name */ - be_nested_proto( - 17, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[21]) { /* constants */ - /* K0 */ be_nested_str_weak(plugins_classes), - /* K1 */ be_nested_str_weak(find), - /* K2 */ be_nested_str_weak(tasmota), - /* K3 */ be_nested_str_weak(log), - /* K4 */ be_nested_str_weak(MTR_X3A_X20unknown_X20class_X20name_X20_X27), - /* K5 */ be_nested_str_weak(_X27_X20skipping), - /* K6 */ be_const_int(3), - /* K7 */ be_nested_str_weak(next_ep), - /* K8 */ be_nested_str_weak(plugins), - /* K9 */ be_nested_str_weak(push), - /* K10 */ be_nested_str_weak(type), - /* K11 */ be_nested_str_weak(keys), - /* K12 */ be_nested_str_weak(stop_iteration), - /* K13 */ be_nested_str_weak(MTR_X3A_X20adding_X20endpoint_X20_X3D_X20_X25i_X20type_X3A_X25s_X25s), - /* K14 */ be_nested_str_weak(conf_to_log), - /* K15 */ be_const_int(2), - /* K16 */ be_nested_str_weak(plugins_config), - /* K17 */ be_nested_str_weak(plugins_persist), - /* K18 */ be_const_int(1), - /* K19 */ be_nested_str_weak(save_param), - /* K20 */ be_nested_str_weak(signal_endpoints_changed), - }), - be_str_weak(bridge_add_endpoint), - &be_const_str_solidified, - ( &(const binstruction[70]) { /* code */ - 0x880C0100, // 0000 GETMBR R3 R0 K0 - 0x8C0C0701, // 0001 GETMET R3 R3 K1 - 0x5C140200, // 0002 MOVE R5 R1 - 0x7C0C0400, // 0003 CALL R3 2 - 0x4C100000, // 0004 LDNIL R4 - 0x1C100604, // 0005 EQ R4 R3 R4 - 0x78120009, // 0006 JMPF R4 #0011 - 0xB8120400, // 0007 GETNGBL R4 K2 - 0x8C100903, // 0008 GETMET R4 R4 K3 - 0x60180008, // 0009 GETGBL R6 G8 - 0x5C1C0200, // 000A MOVE R7 R1 - 0x7C180200, // 000B CALL R6 1 - 0x001A0806, // 000C ADD R6 K4 R6 - 0x00180D05, // 000D ADD R6 R6 K5 - 0x581C0006, // 000E LDCONST R7 K6 - 0x7C100600, // 000F CALL R4 3 - 0x80000800, // 0010 RET 0 - 0x88100107, // 0011 GETMBR R4 R0 K7 - 0x60140008, // 0012 GETGBL R5 G8 - 0x5C180800, // 0013 MOVE R6 R4 - 0x7C140200, // 0014 CALL R5 1 - 0x5C180600, // 0015 MOVE R6 R3 - 0x5C1C0000, // 0016 MOVE R7 R0 - 0x5C200800, // 0017 MOVE R8 R4 - 0x5C240400, // 0018 MOVE R9 R2 - 0x7C180600, // 0019 CALL R6 3 - 0x881C0108, // 001A GETMBR R7 R0 K8 - 0x8C1C0F09, // 001B GETMET R7 R7 K9 - 0x5C240C00, // 001C MOVE R9 R6 - 0x7C1C0400, // 001D CALL R7 2 - 0x601C0013, // 001E GETGBL R7 G19 - 0x7C1C0000, // 001F CALL R7 0 - 0x981E1401, // 0020 SETIDX R7 K10 R1 - 0x60200010, // 0021 GETGBL R8 G16 - 0x8C24050B, // 0022 GETMET R9 R2 K11 - 0x7C240200, // 0023 CALL R9 1 - 0x7C200200, // 0024 CALL R8 1 - 0xA8020004, // 0025 EXBLK 0 #002B - 0x5C241000, // 0026 MOVE R9 R8 - 0x7C240000, // 0027 CALL R9 0 - 0x94280409, // 0028 GETIDX R10 R2 R9 - 0x981C120A, // 0029 SETIDX R7 R9 R10 - 0x7001FFFA, // 002A JMP #0026 - 0x5820000C, // 002B LDCONST R8 K12 - 0xAC200200, // 002C CATCH R8 1 0 - 0xB0080000, // 002D RAISE 2 R0 R0 - 0xB8220400, // 002E GETNGBL R8 K2 - 0x8C201103, // 002F GETMET R8 R8 K3 - 0x60280018, // 0030 GETGBL R10 G24 - 0x582C000D, // 0031 LDCONST R11 K13 - 0x5C300800, // 0032 MOVE R12 R4 - 0x5C340200, // 0033 MOVE R13 R1 - 0x8C38010E, // 0034 GETMET R14 R0 K14 - 0x5C400400, // 0035 MOVE R16 R2 - 0x7C380400, // 0036 CALL R14 2 - 0x7C280800, // 0037 CALL R10 4 - 0x582C000F, // 0038 LDCONST R11 K15 - 0x7C200600, // 0039 CALL R8 3 - 0x88200110, // 003A GETMBR R8 R0 K16 - 0x98200A07, // 003B SETIDX R8 R5 R7 - 0x50200200, // 003C LDBOOL R8 1 0 - 0x90022208, // 003D SETMBR R0 K17 R8 - 0x88200107, // 003E GETMBR R8 R0 K7 - 0x00201112, // 003F ADD R8 R8 K18 - 0x90020E08, // 0040 SETMBR R0 K7 R8 - 0x8C200113, // 0041 GETMET R8 R0 K19 - 0x7C200200, // 0042 CALL R8 1 - 0x8C200114, // 0043 GETMET R8 R0 K20 - 0x7C200200, // 0044 CALL R8 1 - 0x80040800, // 0045 RET 1 R4 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: mdns_remove_op_discovery_all_fabrics -********************************************************************/ -be_local_closure(Matter_Device_mdns_remove_op_discovery_all_fabrics, /* name */ - be_nested_proto( - 6, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(sessions), - /* K1 */ be_nested_str_weak(active_fabrics), - /* K2 */ be_nested_str_weak(get_device_id), - /* K3 */ be_nested_str_weak(get_fabric_id), - /* K4 */ be_nested_str_weak(mdns_remove_op_discovery), - /* K5 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(mdns_remove_op_discovery_all_fabrics), - &be_const_str_solidified, - ( &(const binstruction[22]) { /* code */ - 0x60040010, // 0000 GETGBL R1 G16 - 0x88080100, // 0001 GETMBR R2 R0 K0 - 0x8C080501, // 0002 GETMET R2 R2 K1 - 0x7C080200, // 0003 CALL R2 1 - 0x7C040200, // 0004 CALL R1 1 - 0xA802000B, // 0005 EXBLK 0 #0012 - 0x5C080200, // 0006 MOVE R2 R1 - 0x7C080000, // 0007 CALL R2 0 - 0x8C0C0502, // 0008 GETMET R3 R2 K2 - 0x7C0C0200, // 0009 CALL R3 1 - 0x780E0005, // 000A JMPF R3 #0011 - 0x8C0C0503, // 000B GETMET R3 R2 K3 - 0x7C0C0200, // 000C CALL R3 1 - 0x780E0002, // 000D JMPF R3 #0011 - 0x8C0C0104, // 000E GETMET R3 R0 K4 - 0x5C140400, // 000F MOVE R5 R2 - 0x7C0C0400, // 0010 CALL R3 2 - 0x7001FFF3, // 0011 JMP #0006 - 0x58040005, // 0012 LDCONST R1 K5 - 0xAC040200, // 0013 CATCH R1 1 0 - 0xB0080000, // 0014 RAISE 2 R0 R0 - 0x80000000, // 0015 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: load_param -********************************************************************/ -be_local_closure(Matter_Device_load_param, /* name */ - be_nested_proto( - 11, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[35]) { /* constants */ - /* K0 */ be_nested_str_weak(crypto), - /* K1 */ be_nested_str_weak(FILENAME), - /* K2 */ be_nested_str_weak(read), - /* K3 */ be_nested_str_weak(close), - /* K4 */ be_nested_str_weak(json), - /* K5 */ be_nested_str_weak(load), - /* K6 */ be_nested_str_weak(root_discriminator), - /* K7 */ be_nested_str_weak(find), - /* K8 */ be_nested_str_weak(distinguish), - /* K9 */ be_nested_str_weak(root_passcode), - /* K10 */ be_nested_str_weak(passcode), - /* K11 */ be_nested_str_weak(ipv4only), - /* K12 */ be_nested_str_weak(disable_bridge_mode), - /* K13 */ be_nested_str_weak(next_ep), - /* K14 */ be_nested_str_weak(nextep), - /* K15 */ be_nested_str_weak(plugins_config), - /* K16 */ be_nested_str_weak(config), - /* K17 */ be_nested_str_weak(tasmota), - /* K18 */ be_nested_str_weak(log), - /* K19 */ be_nested_str_weak(MTR_X3A_X20load_config_X20_X3D_X20), - /* K20 */ be_const_int(3), - /* K21 */ be_nested_str_weak(adjust_next_ep), - /* K22 */ be_nested_str_weak(plugins_persist), - /* K23 */ be_nested_str_weak(plugins_config_remotes), - /* K24 */ be_nested_str_weak(remotes), - /* K25 */ be_nested_str_weak(MTR_X3A_X20load_remotes_X20_X3D_X20), - /* K26 */ be_nested_str_weak(io_error), - /* K27 */ be_nested_str_weak(MTR_X3A_X20Session_Store_X3A_X3Aload_X20Exception_X3A), - /* K28 */ be_nested_str_weak(_X7C), - /* K29 */ be_const_int(2), - /* K30 */ be_nested_str_weak(random), - /* K31 */ be_nested_str_weak(get), - /* K32 */ be_const_int(0), - /* K33 */ be_nested_str_weak(generate_random_passcode), - /* K34 */ be_nested_str_weak(save_param), - }), - be_str_weak(load_param), - &be_const_str_solidified, - ( &(const binstruction[127]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0xA802004D, // 0001 EXBLK 0 #0050 - 0x60080011, // 0002 GETGBL R2 G17 - 0x880C0101, // 0003 GETMBR R3 R0 K1 - 0x7C080200, // 0004 CALL R2 1 - 0x8C0C0502, // 0005 GETMET R3 R2 K2 - 0x7C0C0200, // 0006 CALL R3 1 - 0x8C100503, // 0007 GETMET R4 R2 K3 - 0x7C100200, // 0008 CALL R4 1 - 0xA4120800, // 0009 IMPORT R4 K4 - 0x8C140905, // 000A GETMET R5 R4 K5 - 0x5C1C0600, // 000B MOVE R7 R3 - 0x7C140400, // 000C CALL R5 2 - 0x8C180B07, // 000D GETMET R6 R5 K7 - 0x58200008, // 000E LDCONST R8 K8 - 0x88240106, // 000F GETMBR R9 R0 K6 - 0x7C180600, // 0010 CALL R6 3 - 0x90020C06, // 0011 SETMBR R0 K6 R6 - 0x8C180B07, // 0012 GETMET R6 R5 K7 - 0x5820000A, // 0013 LDCONST R8 K10 - 0x88240109, // 0014 GETMBR R9 R0 K9 - 0x7C180600, // 0015 CALL R6 3 - 0x90021206, // 0016 SETMBR R0 K9 R6 - 0x60180017, // 0017 GETGBL R6 G23 - 0x8C1C0B07, // 0018 GETMET R7 R5 K7 - 0x5824000B, // 0019 LDCONST R9 K11 - 0x50280000, // 001A LDBOOL R10 0 0 - 0x7C1C0600, // 001B CALL R7 3 - 0x7C180200, // 001C CALL R6 1 - 0x90021606, // 001D SETMBR R0 K11 R6 - 0x60180017, // 001E GETGBL R6 G23 - 0x8C1C0B07, // 001F GETMET R7 R5 K7 - 0x5824000C, // 0020 LDCONST R9 K12 - 0x50280000, // 0021 LDBOOL R10 0 0 - 0x7C1C0600, // 0022 CALL R7 3 - 0x7C180200, // 0023 CALL R6 1 - 0x90021806, // 0024 SETMBR R0 K12 R6 - 0x8C180B07, // 0025 GETMET R6 R5 K7 - 0x5820000E, // 0026 LDCONST R8 K14 - 0x8824010D, // 0027 GETMBR R9 R0 K13 - 0x7C180600, // 0028 CALL R6 3 - 0x90021A06, // 0029 SETMBR R0 K13 R6 - 0x8C180B07, // 002A GETMET R6 R5 K7 - 0x58200010, // 002B LDCONST R8 K16 - 0x7C180400, // 002C CALL R6 2 - 0x90021E06, // 002D SETMBR R0 K15 R6 - 0x8818010F, // 002E GETMBR R6 R0 K15 - 0x4C1C0000, // 002F LDNIL R7 - 0x20180C07, // 0030 NE R6 R6 R7 - 0x781A000B, // 0031 JMPF R6 #003E - 0xB81A2200, // 0032 GETNGBL R6 K17 - 0x8C180D12, // 0033 GETMET R6 R6 K18 - 0x60200008, // 0034 GETGBL R8 G8 - 0x8824010F, // 0035 GETMBR R9 R0 K15 - 0x7C200200, // 0036 CALL R8 1 - 0x00222608, // 0037 ADD R8 K19 R8 - 0x58240014, // 0038 LDCONST R9 K20 - 0x7C180600, // 0039 CALL R6 3 - 0x8C180115, // 003A GETMET R6 R0 K21 - 0x7C180200, // 003B CALL R6 1 - 0x50180200, // 003C LDBOOL R6 1 0 - 0x90022C06, // 003D SETMBR R0 K22 R6 - 0x8C180B07, // 003E GETMET R6 R5 K7 - 0x58200018, // 003F LDCONST R8 K24 - 0x60240013, // 0040 GETGBL R9 G19 - 0x7C240000, // 0041 CALL R9 0 - 0x7C180600, // 0042 CALL R6 3 - 0x90022E06, // 0043 SETMBR R0 K23 R6 - 0x88180117, // 0044 GETMBR R6 R0 K23 - 0x781A0007, // 0045 JMPF R6 #004E - 0xB81A2200, // 0046 GETNGBL R6 K17 - 0x8C180D12, // 0047 GETMET R6 R6 K18 - 0x60200008, // 0048 GETGBL R8 G8 - 0x88240117, // 0049 GETMBR R9 R0 K23 - 0x7C200200, // 004A CALL R8 1 - 0x00223208, // 004B ADD R8 K25 R8 - 0x58240014, // 004C LDCONST R9 K20 - 0x7C180600, // 004D CALL R6 3 - 0xA8040001, // 004E EXBLK 1 1 - 0x70020012, // 004F JMP #0063 - 0xAC080002, // 0050 CATCH R2 0 2 - 0x7002000F, // 0051 JMP #0062 - 0x2010051A, // 0052 NE R4 R2 K26 - 0x7812000C, // 0053 JMPF R4 #0061 - 0xB8122200, // 0054 GETNGBL R4 K17 - 0x8C100912, // 0055 GETMET R4 R4 K18 - 0x60180008, // 0056 GETGBL R6 G8 - 0x5C1C0400, // 0057 MOVE R7 R2 - 0x7C180200, // 0058 CALL R6 1 - 0x001A3606, // 0059 ADD R6 K27 R6 - 0x00180D1C, // 005A ADD R6 R6 K28 - 0x601C0008, // 005B GETGBL R7 G8 - 0x5C200600, // 005C MOVE R8 R3 - 0x7C1C0200, // 005D CALL R7 1 - 0x00180C07, // 005E ADD R6 R6 R7 - 0x581C001D, // 005F LDCONST R7 K29 - 0x7C100600, // 0060 CALL R4 3 - 0x70020000, // 0061 JMP #0063 - 0xB0080000, // 0062 RAISE 2 R0 R0 - 0x50080000, // 0063 LDBOOL R2 0 0 - 0x880C0106, // 0064 GETMBR R3 R0 K6 - 0x4C100000, // 0065 LDNIL R4 - 0x1C0C0604, // 0066 EQ R3 R3 R4 - 0x780E000A, // 0067 JMPF R3 #0073 - 0x8C0C031E, // 0068 GETMET R3 R1 K30 - 0x5814001D, // 0069 LDCONST R5 K29 - 0x7C0C0400, // 006A CALL R3 2 - 0x8C0C071F, // 006B GETMET R3 R3 K31 - 0x58140020, // 006C LDCONST R5 K32 - 0x5818001D, // 006D LDCONST R6 K29 - 0x7C0C0600, // 006E CALL R3 3 - 0x54120FFE, // 006F LDINT R4 4095 - 0x2C0C0604, // 0070 AND R3 R3 R4 - 0x90020C03, // 0071 SETMBR R0 K6 R3 - 0x50080200, // 0072 LDBOOL R2 1 0 - 0x880C0109, // 0073 GETMBR R3 R0 K9 - 0x4C100000, // 0074 LDNIL R4 - 0x1C0C0604, // 0075 EQ R3 R3 R4 - 0x780E0003, // 0076 JMPF R3 #007B - 0x8C0C0121, // 0077 GETMET R3 R0 K33 - 0x7C0C0200, // 0078 CALL R3 1 - 0x90021203, // 0079 SETMBR R0 K9 R3 - 0x50080200, // 007A LDBOOL R2 1 0 - 0x780A0001, // 007B JMPF R2 #007E - 0x8C0C0122, // 007C GETMET R3 R0 K34 - 0x7C0C0200, // 007D CALL R3 1 - 0x80000000, // 007E RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: attribute_updated -********************************************************************/ -be_local_closure(Matter_Device_attribute_updated, /* name */ +be_local_closure(Matter_Device_MtrInfo, /* name */ be_nested_proto( 10, /* nstack */ 5, /* argc */ @@ -1997,190 +703,58 @@ be_local_closure(Matter_Device_attribute_updated, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(matter), - /* K1 */ be_nested_str_weak(Path), - /* K2 */ be_nested_str_weak(endpoint), - /* K3 */ be_nested_str_weak(cluster), - /* K4 */ be_nested_str_weak(attribute), - /* K5 */ be_nested_str_weak(message_handler), - /* K6 */ be_nested_str_weak(im), - /* K7 */ be_nested_str_weak(subs_shop), - /* K8 */ be_nested_str_weak(attribute_updated_ctx), + /* K0 */ be_nested_str_weak(), + /* K1 */ be_nested_str_weak(plugins), + /* K2 */ be_nested_str_weak(MtrInfo_one), + /* K3 */ be_nested_str_weak(endpoint), + /* K4 */ be_nested_str_weak(stop_iteration), + /* K5 */ be_nested_str_weak(int), + /* K6 */ be_nested_str_weak(find_plugin_by_friendly_name), + /* K7 */ be_nested_str_weak(tasmota), + /* K8 */ be_nested_str_weak(resp_cmnd_done), }), - be_str_weak(attribute_updated), - &be_const_str_solidified, - ( &(const binstruction[18]) { /* code */ - 0x4C140000, // 0000 LDNIL R5 - 0x1C140805, // 0001 EQ R5 R4 R5 - 0x78160000, // 0002 JMPF R5 #0004 - 0x50100000, // 0003 LDBOOL R4 0 0 - 0xB8160000, // 0004 GETNGBL R5 K0 - 0x8C140B01, // 0005 GETMET R5 R5 K1 - 0x7C140200, // 0006 CALL R5 1 - 0x90160401, // 0007 SETMBR R5 K2 R1 - 0x90160602, // 0008 SETMBR R5 K3 R2 - 0x90160803, // 0009 SETMBR R5 K4 R3 - 0x88180105, // 000A GETMBR R6 R0 K5 - 0x88180D06, // 000B GETMBR R6 R6 K6 - 0x88180D07, // 000C GETMBR R6 R6 K7 - 0x8C180D08, // 000D GETMET R6 R6 K8 - 0x5C200A00, // 000E MOVE R8 R5 - 0x5C240800, // 000F MOVE R9 R4 - 0x7C180600, // 0010 CALL R6 3 - 0x80000000, // 0011 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: k2l -********************************************************************/ -be_local_closure(Matter_Device_k2l, /* name */ - be_nested_proto( - 8, /* nstack */ - 1, /* argc */ - 4, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_const_class(be_class_Matter_Device), - /* K1 */ be_nested_str_weak(keys), - /* K2 */ be_nested_str_weak(push), - /* K3 */ be_nested_str_weak(stop_iteration), - /* K4 */ be_const_int(1), - /* K5 */ be_const_int(0), - }), - be_str_weak(k2l), - &be_const_str_solidified, - ( &(const binstruction[50]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x60080012, // 0001 GETGBL R2 G18 - 0x7C080000, // 0002 CALL R2 0 - 0x4C0C0000, // 0003 LDNIL R3 - 0x1C0C0003, // 0004 EQ R3 R0 R3 - 0x780E0000, // 0005 JMPF R3 #0007 - 0x80040400, // 0006 RET 1 R2 - 0x600C0010, // 0007 GETGBL R3 G16 - 0x8C100101, // 0008 GETMET R4 R0 K1 - 0x7C100200, // 0009 CALL R4 1 - 0x7C0C0200, // 000A CALL R3 1 - 0xA8020005, // 000B EXBLK 0 #0012 - 0x5C100600, // 000C MOVE R4 R3 - 0x7C100000, // 000D CALL R4 0 - 0x8C140502, // 000E GETMET R5 R2 K2 - 0x5C1C0800, // 000F MOVE R7 R4 - 0x7C140400, // 0010 CALL R5 2 - 0x7001FFF9, // 0011 JMP #000C - 0x580C0003, // 0012 LDCONST R3 K3 - 0xAC0C0200, // 0013 CATCH R3 1 0 - 0xB0080000, // 0014 RAISE 2 R0 R0 - 0x600C0010, // 0015 GETGBL R3 G16 - 0x6010000C, // 0016 GETGBL R4 G12 - 0x5C140400, // 0017 MOVE R5 R2 - 0x7C100200, // 0018 CALL R4 1 - 0x04100904, // 0019 SUB R4 R4 K4 - 0x40120804, // 001A CONNECT R4 K4 R4 - 0x7C0C0200, // 001B CALL R3 1 - 0xA8020010, // 001C EXBLK 0 #002E - 0x5C100600, // 001D MOVE R4 R3 - 0x7C100000, // 001E CALL R4 0 - 0x94140404, // 001F GETIDX R5 R2 R4 - 0x5C180800, // 0020 MOVE R6 R4 - 0x241C0D05, // 0021 GT R7 R6 K5 - 0x781E0008, // 0022 JMPF R7 #002C - 0x041C0D04, // 0023 SUB R7 R6 K4 - 0x941C0407, // 0024 GETIDX R7 R2 R7 - 0x241C0E05, // 0025 GT R7 R7 R5 - 0x781E0004, // 0026 JMPF R7 #002C - 0x041C0D04, // 0027 SUB R7 R6 K4 - 0x941C0407, // 0028 GETIDX R7 R2 R7 - 0x98080C07, // 0029 SETIDX R2 R6 R7 - 0x04180D04, // 002A SUB R6 R6 K4 - 0x7001FFF4, // 002B JMP #0021 - 0x98080C05, // 002C SETIDX R2 R6 R5 - 0x7001FFEE, // 002D JMP #001D - 0x580C0003, // 002E LDCONST R3 K3 - 0xAC0C0200, // 002F CATCH R3 1 0 - 0xB0080000, // 0030 RAISE 2 R0 R0 - 0x80040400, // 0031 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: _compute_pbkdf -********************************************************************/ -be_local_closure(Matter_Device__compute_pbkdf, /* name */ - be_nested_proto( - 13, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[10]) { /* constants */ - /* K0 */ be_nested_str_weak(crypto), - /* K1 */ be_nested_str_weak(add), - /* K2 */ be_nested_str_weak(PBKDF2_HMAC_SHA256), - /* K3 */ be_nested_str_weak(derive), - /* K4 */ be_const_int(0), - /* K5 */ be_nested_str_weak(root_w0), - /* K6 */ be_nested_str_weak(EC_P256), - /* K7 */ be_nested_str_weak(mod), - /* K8 */ be_nested_str_weak(root_L), - /* K9 */ be_nested_str_weak(public_key), - }), - be_str_weak(_compute_pbkdf), + be_str_weak(MtrInfo), &be_const_str_solidified, ( &(const binstruction[40]) { /* code */ - 0xA4120000, // 0000 IMPORT R4 K0 - 0x60140015, // 0001 GETGBL R5 G21 - 0x7C140000, // 0002 CALL R5 0 - 0x8C140B01, // 0003 GETMET R5 R5 K1 - 0x5C1C0200, // 0004 MOVE R7 R1 - 0x54220003, // 0005 LDINT R8 4 - 0x7C140600, // 0006 CALL R5 3 - 0x8C180902, // 0007 GETMET R6 R4 K2 - 0x7C180200, // 0008 CALL R6 1 - 0x8C180D03, // 0009 GETMET R6 R6 K3 - 0x5C200A00, // 000A MOVE R8 R5 - 0x5C240600, // 000B MOVE R9 R3 - 0x5C280400, // 000C MOVE R10 R2 - 0x542E004F, // 000D LDINT R11 80 - 0x7C180A00, // 000E CALL R6 5 - 0x541E0026, // 000F LDINT R7 39 - 0x401E0807, // 0010 CONNECT R7 K4 R7 - 0x941C0C07, // 0011 GETIDX R7 R6 R7 - 0x54220027, // 0012 LDINT R8 40 - 0x5426004E, // 0013 LDINT R9 79 - 0x40201009, // 0014 CONNECT R8 R8 R9 - 0x94200C08, // 0015 GETIDX R8 R6 R8 - 0x8C240906, // 0016 GETMET R9 R4 K6 - 0x7C240200, // 0017 CALL R9 1 - 0x8C241307, // 0018 GETMET R9 R9 K7 - 0x5C2C0E00, // 0019 MOVE R11 R7 - 0x7C240400, // 001A CALL R9 2 - 0x90020A09, // 001B SETMBR R0 K5 R9 - 0x8C240906, // 001C GETMET R9 R4 K6 - 0x7C240200, // 001D CALL R9 1 - 0x8C241307, // 001E GETMET R9 R9 K7 - 0x5C2C1000, // 001F MOVE R11 R8 - 0x7C240400, // 0020 CALL R9 2 - 0x8C280906, // 0021 GETMET R10 R4 K6 - 0x7C280200, // 0022 CALL R10 1 - 0x8C281509, // 0023 GETMET R10 R10 K9 - 0x5C301200, // 0024 MOVE R12 R9 - 0x7C280400, // 0025 CALL R10 2 - 0x9002100A, // 0026 SETMBR R0 K8 R10 + 0x1C140700, // 0000 EQ R5 R3 K0 + 0x7815FFFF, // 0001 JMPF R5 #0002 + 0x1C140700, // 0002 EQ R5 R3 K0 + 0x7816000D, // 0003 JMPF R5 #0012 + 0x60140010, // 0004 GETGBL R5 G16 + 0x88180101, // 0005 GETMBR R6 R0 K1 + 0x7C140200, // 0006 CALL R5 1 + 0xA8020005, // 0007 EXBLK 0 #000E + 0x5C180A00, // 0008 MOVE R6 R5 + 0x7C180000, // 0009 CALL R6 0 + 0x8C1C0102, // 000A GETMET R7 R0 K2 + 0x88240D03, // 000B GETMBR R9 R6 K3 + 0x7C1C0400, // 000C CALL R7 2 + 0x7001FFF9, // 000D JMP #0008 + 0x58140004, // 000E LDCONST R5 K4 + 0xAC140200, // 000F CATCH R5 1 0 + 0xB0080000, // 0010 RAISE 2 R0 R0 + 0x70020011, // 0011 JMP #0024 + 0x60140004, // 0012 GETGBL R5 G4 + 0x5C180800, // 0013 MOVE R6 R4 + 0x7C140200, // 0014 CALL R5 1 + 0x1C140B05, // 0015 EQ R5 R5 K5 + 0x78160003, // 0016 JMPF R5 #001B + 0x8C140102, // 0017 GETMET R5 R0 K2 + 0x5C1C0800, // 0018 MOVE R7 R4 + 0x7C140400, // 0019 CALL R5 2 + 0x70020008, // 001A JMP #0024 + 0x8C140106, // 001B GETMET R5 R0 K6 + 0x5C1C0600, // 001C MOVE R7 R3 + 0x7C140400, // 001D CALL R5 2 + 0x4C180000, // 001E LDNIL R6 + 0x20180A06, // 001F NE R6 R5 R6 + 0x781A0002, // 0020 JMPF R6 #0024 + 0x8C180102, // 0021 GETMET R6 R0 K2 + 0x88200B03, // 0022 GETMBR R8 R5 K3 + 0x7C180400, // 0023 CALL R6 2 + 0xB8160E00, // 0024 GETNGBL R5 K7 + 0x8C140B08, // 0025 GETMET R5 R5 K8 + 0x7C140200, // 0026 CALL R5 1 0x80000000, // 0027 RET 0 }) ) @@ -2188,1766 +762,6 @@ be_local_closure(Matter_Device__compute_pbkdf, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: register_commands -********************************************************************/ -be_local_closure(Matter_Device_register_commands, /* name */ - be_nested_proto( - 5, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 3]) { - be_nested_proto( - 10, /* nstack */ - 4, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(MtrJoin), - }), - be_str_weak(_X3Clambda_X3E), - &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x68100000, // 0000 GETUPV R4 U0 - 0x8C100900, // 0001 GETMET R4 R4 K0 - 0x5C180000, // 0002 MOVE R6 R0 - 0x5C1C0200, // 0003 MOVE R7 R1 - 0x5C200400, // 0004 MOVE R8 R2 - 0x5C240600, // 0005 MOVE R9 R3 - 0x7C100A00, // 0006 CALL R4 5 - 0x80040800, // 0007 RET 1 R4 - }) - ), - be_nested_proto( - 10, /* nstack */ - 4, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(MtrUpdate), - }), - be_str_weak(_X3Clambda_X3E), - &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x68100000, // 0000 GETUPV R4 U0 - 0x8C100900, // 0001 GETMET R4 R4 K0 - 0x5C180000, // 0002 MOVE R6 R0 - 0x5C1C0200, // 0003 MOVE R7 R1 - 0x5C200400, // 0004 MOVE R8 R2 - 0x5C240600, // 0005 MOVE R9 R3 - 0x7C100A00, // 0006 CALL R4 5 - 0x80040800, // 0007 RET 1 R4 - }) - ), - be_nested_proto( - 10, /* nstack */ - 4, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(MtrInfo), - }), - be_str_weak(_X3Clambda_X3E), - &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x68100000, // 0000 GETUPV R4 U0 - 0x8C100900, // 0001 GETMET R4 R4 K0 - 0x5C180000, // 0002 MOVE R6 R0 - 0x5C1C0200, // 0003 MOVE R7 R1 - 0x5C200400, // 0004 MOVE R8 R2 - 0x5C240600, // 0005 MOVE R9 R3 - 0x7C100A00, // 0006 CALL R4 5 - 0x80040800, // 0007 RET 1 R4 - }) - ), - }), - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(add_cmd), - /* K2 */ be_nested_str_weak(MtrJoin), - /* K3 */ be_nested_str_weak(MtrUpdate), - /* K4 */ be_nested_str_weak(MtrInfo), - }), - be_str_weak(register_commands), - &be_const_str_solidified, - ( &(const binstruction[17]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x580C0002, // 0002 LDCONST R3 K2 - 0x84100000, // 0003 CLOSURE R4 P0 - 0x7C040600, // 0004 CALL R1 3 - 0xB8060000, // 0005 GETNGBL R1 K0 - 0x8C040301, // 0006 GETMET R1 R1 K1 - 0x580C0003, // 0007 LDCONST R3 K3 - 0x84100001, // 0008 CLOSURE R4 P1 - 0x7C040600, // 0009 CALL R1 3 - 0xB8060000, // 000A GETNGBL R1 K0 - 0x8C040301, // 000B GETMET R1 R1 K1 - 0x580C0004, // 000C LDCONST R3 K4 - 0x84100002, // 000D CLOSURE R4 P2 - 0x7C040600, // 000E CALL R1 3 - 0xA0000000, // 000F CLOSE R0 - 0x80000000, // 0010 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Matter_Device_init, /* name */ - be_nested_proto( - 7, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 2]) { - be_nested_proto( - 4, /* nstack */ - 0, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(start), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(remove_rule), - /* K3 */ be_nested_str_weak(Wifi_X23Connected), - /* K4 */ be_nested_str_weak(matter_start), - }), - be_str_weak(_anonymous_), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0x68000000, // 0000 GETUPV R0 U0 - 0x8C000100, // 0001 GETMET R0 R0 K0 - 0x7C000200, // 0002 CALL R0 1 - 0xB8020200, // 0003 GETNGBL R0 K1 - 0x8C000102, // 0004 GETMET R0 R0 K2 - 0x58080003, // 0005 LDCONST R2 K3 - 0x580C0004, // 0006 LDCONST R3 K4 - 0x7C000600, // 0007 CALL R0 3 - 0x80000000, // 0008 RET 0 - }) - ), - be_nested_proto( - 4, /* nstack */ - 0, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(start), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(remove_rule), - /* K3 */ be_nested_str_weak(Eth_X23Connected), - /* K4 */ be_nested_str_weak(matter_start), - }), - be_str_weak(_anonymous_), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0x68000000, // 0000 GETUPV R0 U0 - 0x8C000100, // 0001 GETMET R0 R0 K0 - 0x7C000200, // 0002 CALL R0 1 - 0xB8020200, // 0003 GETNGBL R0 K1 - 0x8C000102, // 0004 GETMET R0 R0 K2 - 0x58080003, // 0005 LDCONST R2 K3 - 0x580C0004, // 0006 LDCONST R3 K4 - 0x7C000600, // 0007 CALL R0 3 - 0x80000000, // 0008 RET 0 - }) - ), - }), - 1, /* has constants */ - ( &(const bvalue[44]) { /* constants */ - /* K0 */ be_nested_str_weak(crypto), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(get_option), - /* K3 */ be_nested_str_weak(matter), - /* K4 */ be_nested_str_weak(MATTER_OPTION), - /* K5 */ be_nested_str_weak(UI), - /* K6 */ be_nested_str_weak(profiler), - /* K7 */ be_nested_str_weak(Profiler), - /* K8 */ be_nested_str_weak(started), - /* K9 */ be_nested_str_weak(tick), - /* K10 */ be_const_int(0), - /* K11 */ be_nested_str_weak(plugins), - /* K12 */ be_nested_str_weak(plugins_persist), - /* K13 */ be_nested_str_weak(plugins_config_remotes), - /* K14 */ be_nested_str_weak(vendorid), - /* K15 */ be_nested_str_weak(VENDOR_ID), - /* K16 */ be_nested_str_weak(productid), - /* K17 */ be_nested_str_weak(PRODUCT_ID), - /* K18 */ be_nested_str_weak(root_iterations), - /* K19 */ be_nested_str_weak(PBKDF_ITERATIONS), - /* K20 */ be_nested_str_weak(next_ep), - /* K21 */ be_const_int(1), - /* K22 */ be_nested_str_weak(root_salt), - /* K23 */ be_nested_str_weak(random), - /* K24 */ be_nested_str_weak(ipv4only), - /* K25 */ be_nested_str_weak(disable_bridge_mode), - /* K26 */ be_nested_str_weak(load_param), - /* K27 */ be_nested_str_weak(sessions), - /* K28 */ be_nested_str_weak(Session_Store), - /* K29 */ be_nested_str_weak(load_fabrics), - /* K30 */ be_nested_str_weak(message_handler), - /* K31 */ be_nested_str_weak(MessageHandler), - /* K32 */ be_nested_str_weak(ui), - /* K33 */ be_nested_str_weak(wifi), - /* K34 */ be_nested_str_weak(up), - /* K35 */ be_nested_str_weak(eth), - /* K36 */ be_nested_str_weak(start), - /* K37 */ be_nested_str_weak(add_rule), - /* K38 */ be_nested_str_weak(Wifi_X23Connected), - /* K39 */ be_nested_str_weak(matter_start), - /* K40 */ be_nested_str_weak(Eth_X23Connected), - /* K41 */ be_nested_str_weak(_init_basic_commissioning), - /* K42 */ be_nested_str_weak(add_driver), - /* K43 */ be_nested_str_weak(register_commands), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[107]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0xB80A0200, // 0001 GETNGBL R2 K1 - 0x8C080502, // 0002 GETMET R2 R2 K2 - 0xB8120600, // 0003 GETNGBL R4 K3 - 0x88100904, // 0004 GETMBR R4 R4 K4 - 0x7C080400, // 0005 CALL R2 2 - 0x740A0004, // 0006 JMPT R2 #000C - 0xB80A0600, // 0007 GETNGBL R2 K3 - 0x8C080505, // 0008 GETMET R2 R2 K5 - 0x5C100000, // 0009 MOVE R4 R0 - 0x7C080400, // 000A CALL R2 2 - 0x80000400, // 000B RET 0 - 0xB80A0600, // 000C GETNGBL R2 K3 - 0xB80E0600, // 000D GETNGBL R3 K3 - 0x8C0C0707, // 000E GETMET R3 R3 K7 - 0x7C0C0200, // 000F CALL R3 1 - 0x900A0C03, // 0010 SETMBR R2 K6 R3 - 0x50080000, // 0011 LDBOOL R2 0 0 - 0x90021002, // 0012 SETMBR R0 K8 R2 - 0x9002130A, // 0013 SETMBR R0 K9 K10 - 0x60080012, // 0014 GETGBL R2 G18 - 0x7C080000, // 0015 CALL R2 0 - 0x90021602, // 0016 SETMBR R0 K11 R2 - 0x50080000, // 0017 LDBOOL R2 0 0 - 0x90021802, // 0018 SETMBR R0 K12 R2 - 0x60080013, // 0019 GETGBL R2 G19 - 0x7C080000, // 001A CALL R2 0 - 0x90021A02, // 001B SETMBR R0 K13 R2 - 0x8808010F, // 001C GETMBR R2 R0 K15 - 0x90021C02, // 001D SETMBR R0 K14 R2 - 0x88080111, // 001E GETMBR R2 R0 K17 - 0x90022002, // 001F SETMBR R0 K16 R2 - 0x88080113, // 0020 GETMBR R2 R0 K19 - 0x90022402, // 0021 SETMBR R0 K18 R2 - 0x90022915, // 0022 SETMBR R0 K20 K21 - 0x8C080317, // 0023 GETMET R2 R1 K23 - 0x5412000F, // 0024 LDINT R4 16 - 0x7C080400, // 0025 CALL R2 2 - 0x90022C02, // 0026 SETMBR R0 K22 R2 - 0x50080000, // 0027 LDBOOL R2 0 0 - 0x90023002, // 0028 SETMBR R0 K24 R2 - 0x50080000, // 0029 LDBOOL R2 0 0 - 0x90023202, // 002A SETMBR R0 K25 R2 - 0x8C08011A, // 002B GETMET R2 R0 K26 - 0x7C080200, // 002C CALL R2 1 - 0xB80A0600, // 002D GETNGBL R2 K3 - 0x8C08051C, // 002E GETMET R2 R2 K28 - 0x5C100000, // 002F MOVE R4 R0 - 0x7C080400, // 0030 CALL R2 2 - 0x90023602, // 0031 SETMBR R0 K27 R2 - 0x8808011B, // 0032 GETMBR R2 R0 K27 - 0x8C08051D, // 0033 GETMET R2 R2 K29 - 0x7C080200, // 0034 CALL R2 1 - 0xB80A0600, // 0035 GETNGBL R2 K3 - 0x8C08051F, // 0036 GETMET R2 R2 K31 - 0x5C100000, // 0037 MOVE R4 R0 - 0x7C080400, // 0038 CALL R2 2 - 0x90023C02, // 0039 SETMBR R0 K30 R2 - 0xB80A0600, // 003A GETNGBL R2 K3 - 0x8C080505, // 003B GETMET R2 R2 K5 - 0x5C100000, // 003C MOVE R4 R0 - 0x7C080400, // 003D CALL R2 2 - 0x90024002, // 003E SETMBR R0 K32 R2 - 0xB80A0200, // 003F GETNGBL R2 K1 - 0x8C080521, // 0040 GETMET R2 R2 K33 - 0x7C080200, // 0041 CALL R2 1 - 0x94080522, // 0042 GETIDX R2 R2 K34 - 0x740A0004, // 0043 JMPT R2 #0049 - 0xB80A0200, // 0044 GETNGBL R2 K1 - 0x8C080523, // 0045 GETMET R2 R2 K35 - 0x7C080200, // 0046 CALL R2 1 - 0x94080522, // 0047 GETIDX R2 R2 K34 - 0x780A0001, // 0048 JMPF R2 #004B - 0x8C080124, // 0049 GETMET R2 R0 K36 - 0x7C080200, // 004A CALL R2 1 - 0xB80A0200, // 004B GETNGBL R2 K1 - 0x8C080521, // 004C GETMET R2 R2 K33 - 0x7C080200, // 004D CALL R2 1 - 0x94080522, // 004E GETIDX R2 R2 K34 - 0x740A0005, // 004F JMPT R2 #0056 - 0xB80A0200, // 0050 GETNGBL R2 K1 - 0x8C080525, // 0051 GETMET R2 R2 K37 - 0x58100026, // 0052 LDCONST R4 K38 - 0x84140000, // 0053 CLOSURE R5 P0 - 0x58180027, // 0054 LDCONST R6 K39 - 0x7C080800, // 0055 CALL R2 4 - 0xB80A0200, // 0056 GETNGBL R2 K1 - 0x8C080523, // 0057 GETMET R2 R2 K35 - 0x7C080200, // 0058 CALL R2 1 - 0x94080522, // 0059 GETIDX R2 R2 K34 - 0x740A0005, // 005A JMPT R2 #0061 - 0xB80A0200, // 005B GETNGBL R2 K1 - 0x8C080525, // 005C GETMET R2 R2 K37 - 0x58100028, // 005D LDCONST R4 K40 - 0x84140001, // 005E CLOSURE R5 P1 - 0x58180027, // 005F LDCONST R6 K39 - 0x7C080800, // 0060 CALL R2 4 - 0x8C080129, // 0061 GETMET R2 R0 K41 - 0x7C080200, // 0062 CALL R2 1 - 0xB80A0200, // 0063 GETNGBL R2 K1 - 0x8C08052A, // 0064 GETMET R2 R2 K42 - 0x5C100000, // 0065 MOVE R4 R0 - 0x7C080400, // 0066 CALL R2 2 - 0x8C08012B, // 0067 GETMET R2 R0 K43 - 0x7C080200, // 0068 CALL R2 1 - 0xA0000000, // 0069 CLOSE R0 - 0x80000000, // 006A RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: adjust_next_ep -********************************************************************/ -be_local_closure(Matter_Device_adjust_next_ep, /* name */ - be_nested_proto( - 5, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(plugins_config), - /* K1 */ be_nested_str_weak(keys), - /* K2 */ be_nested_str_weak(next_ep), - /* K3 */ be_const_int(1), - /* K4 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(adjust_next_ep), - &be_const_str_solidified, - ( &(const binstruction[21]) { /* code */ - 0x60040010, // 0000 GETGBL R1 G16 - 0x88080100, // 0001 GETMBR R2 R0 K0 - 0x8C080501, // 0002 GETMET R2 R2 K1 - 0x7C080200, // 0003 CALL R2 1 - 0x7C040200, // 0004 CALL R1 1 - 0xA802000A, // 0005 EXBLK 0 #0011 - 0x5C080200, // 0006 MOVE R2 R1 - 0x7C080000, // 0007 CALL R2 0 - 0x600C0009, // 0008 GETGBL R3 G9 - 0x5C100400, // 0009 MOVE R4 R2 - 0x7C0C0200, // 000A CALL R3 1 - 0x88100102, // 000B GETMBR R4 R0 K2 - 0x28100604, // 000C GE R4 R3 R4 - 0x78120001, // 000D JMPF R4 #0010 - 0x00100703, // 000E ADD R4 R3 K3 - 0x90020404, // 000F SETMBR R0 K2 R4 - 0x7001FFF4, // 0010 JMP #0006 - 0x58040004, // 0011 LDCONST R1 K4 - 0xAC040200, // 0012 CATCH R1 1 0 - 0xB0080000, // 0013 RAISE 2 R0 R0 - 0x80000000, // 0014 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: conf_to_log -********************************************************************/ -be_local_closure(Matter_Device_conf_to_log, /* name */ - be_nested_proto( - 9, /* nstack */ - 1, /* argc */ - 4, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_const_class(be_class_Matter_Device), - /* K1 */ be_nested_str_weak(), - /* K2 */ be_nested_str_weak(k2l), - /* K3 */ be_nested_str_weak(type), - /* K4 */ be_nested_str_weak(_X20_X25s_X3A_X25s), - /* K5 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(conf_to_log), - &be_const_str_solidified, - ( &(const binstruction[24]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x58080001, // 0001 LDCONST R2 K1 - 0x600C0010, // 0002 GETGBL R3 G16 - 0x8C100302, // 0003 GETMET R4 R1 K2 - 0x5C180000, // 0004 MOVE R6 R0 - 0x7C100400, // 0005 CALL R4 2 - 0x7C0C0200, // 0006 CALL R3 1 - 0xA802000B, // 0007 EXBLK 0 #0014 - 0x5C100600, // 0008 MOVE R4 R3 - 0x7C100000, // 0009 CALL R4 0 - 0x1C140903, // 000A EQ R5 R4 K3 - 0x78160000, // 000B JMPF R5 #000D - 0x7001FFFA, // 000C JMP #0008 - 0x60140018, // 000D GETGBL R5 G24 - 0x58180004, // 000E LDCONST R6 K4 - 0x5C1C0800, // 000F MOVE R7 R4 - 0x94200004, // 0010 GETIDX R8 R0 R4 - 0x7C140600, // 0011 CALL R5 3 - 0x00080405, // 0012 ADD R2 R2 R5 - 0x7001FFF3, // 0013 JMP #0008 - 0x580C0005, // 0014 LDCONST R3 K5 - 0xAC0C0200, // 0015 CATCH R3 1 0 - 0xB0080000, // 0016 RAISE 2 R0 R0 - 0x80040400, // 0017 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: every_50ms -********************************************************************/ -be_local_closure(Matter_Device_every_50ms, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(tick), - /* K1 */ be_const_int(1), - }), - be_str_weak(every_50ms), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x00040301, // 0001 ADD R1 R1 K1 - 0x90020001, // 0002 SETMBR R0 K0 R1 - 0x80000000, // 0003 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: k2l_num -********************************************************************/ -be_local_closure(Matter_Device_k2l_num, /* name */ - be_nested_proto( - 9, /* nstack */ - 1, /* argc */ - 4, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_const_class(be_class_Matter_Device), - /* K1 */ be_nested_str_weak(keys), - /* K2 */ be_nested_str_weak(push), - /* K3 */ be_nested_str_weak(stop_iteration), - /* K4 */ be_const_int(1), - /* K5 */ be_const_int(0), - }), - be_str_weak(k2l_num), - &be_const_str_solidified, - ( &(const binstruction[52]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x60080012, // 0001 GETGBL R2 G18 - 0x7C080000, // 0002 CALL R2 0 - 0x4C0C0000, // 0003 LDNIL R3 - 0x1C0C0003, // 0004 EQ R3 R0 R3 - 0x780E0000, // 0005 JMPF R3 #0007 - 0x80040400, // 0006 RET 1 R2 - 0x600C0010, // 0007 GETGBL R3 G16 - 0x8C100101, // 0008 GETMET R4 R0 K1 - 0x7C100200, // 0009 CALL R4 1 - 0x7C0C0200, // 000A CALL R3 1 - 0xA8020007, // 000B EXBLK 0 #0014 - 0x5C100600, // 000C MOVE R4 R3 - 0x7C100000, // 000D CALL R4 0 - 0x8C140502, // 000E GETMET R5 R2 K2 - 0x601C0009, // 000F GETGBL R7 G9 - 0x5C200800, // 0010 MOVE R8 R4 - 0x7C1C0200, // 0011 CALL R7 1 - 0x7C140400, // 0012 CALL R5 2 - 0x7001FFF7, // 0013 JMP #000C - 0x580C0003, // 0014 LDCONST R3 K3 - 0xAC0C0200, // 0015 CATCH R3 1 0 - 0xB0080000, // 0016 RAISE 2 R0 R0 - 0x600C0010, // 0017 GETGBL R3 G16 - 0x6010000C, // 0018 GETGBL R4 G12 - 0x5C140400, // 0019 MOVE R5 R2 - 0x7C100200, // 001A CALL R4 1 - 0x04100904, // 001B SUB R4 R4 K4 - 0x40120804, // 001C CONNECT R4 K4 R4 - 0x7C0C0200, // 001D CALL R3 1 - 0xA8020010, // 001E EXBLK 0 #0030 - 0x5C100600, // 001F MOVE R4 R3 - 0x7C100000, // 0020 CALL R4 0 - 0x94140404, // 0021 GETIDX R5 R2 R4 - 0x5C180800, // 0022 MOVE R6 R4 - 0x241C0D05, // 0023 GT R7 R6 K5 - 0x781E0008, // 0024 JMPF R7 #002E - 0x041C0D04, // 0025 SUB R7 R6 K4 - 0x941C0407, // 0026 GETIDX R7 R2 R7 - 0x241C0E05, // 0027 GT R7 R7 R5 - 0x781E0004, // 0028 JMPF R7 #002E - 0x041C0D04, // 0029 SUB R7 R6 K4 - 0x941C0407, // 002A GETIDX R7 R2 R7 - 0x98080C07, // 002B SETIDX R2 R6 R7 - 0x04180D04, // 002C SUB R6 R6 K4 - 0x7001FFF4, // 002D JMP #0023 - 0x98080C05, // 002E SETIDX R2 R6 R5 - 0x7001FFEE, // 002F JMP #001F - 0x580C0003, // 0030 LDCONST R3 K3 - 0xAC0C0200, // 0031 CATCH R3 1 0 - 0xB0080000, // 0032 RAISE 2 R0 R0 - 0x80040400, // 0033 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_plugin_class_arg -********************************************************************/ -be_local_closure(Matter_Device_get_plugin_class_arg, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(plugins_classes), - /* K1 */ be_nested_str_weak(find), - /* K2 */ be_nested_str_weak(ARG), - /* K3 */ be_nested_str_weak(), - }), - be_str_weak(get_plugin_class_arg), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x780A0001, // 0004 JMPF R2 #0007 - 0x880C0502, // 0005 GETMBR R3 R2 K2 - 0x70020000, // 0006 JMP #0008 - 0x580C0003, // 0007 LDCONST R3 K3 - 0x80040600, // 0008 RET 1 R3 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: autoconf_device_map -********************************************************************/ -be_local_closure(Matter_Device_autoconf_device_map, /* name */ - be_nested_proto( - 20, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[36]) { /* constants */ - /* K0 */ be_nested_str_weak(json), - /* K1 */ be_const_int(1), - /* K2 */ be_nested_str_weak(light), - /* K3 */ be_nested_str_weak(get), - /* K4 */ be_nested_str_weak(find), - /* K5 */ be_nested_str_weak(channels), - /* K6 */ be_nested_str_weak(), - /* K7 */ be_const_int(0), - /* K8 */ be_nested_str_weak(type), - /* K9 */ be_nested_str_weak(light1), - /* K10 */ be_const_int(2), - /* K11 */ be_nested_str_weak(light2), - /* K12 */ be_nested_str_weak(light3), - /* K13 */ be_nested_str_weak(tasmota), - /* K14 */ be_nested_str_weak(cmd), - /* K15 */ be_nested_str_weak(Status_X2013), - /* K16 */ be_nested_str_weak(log), - /* K17 */ be_nested_str_weak(MTR_X3A_X20Status_X2013_X20_X3D_X20), - /* K18 */ be_const_int(3), - /* K19 */ be_nested_str_weak(contains), - /* K20 */ be_nested_str_weak(StatusSHT), - /* K21 */ be_nested_str_weak(SHT), - /* K22 */ be_nested_str_weak(MTR_X3A_X20_X27_X25s_X27_X20_X3D_X20_X25s), - /* K23 */ be_nested_str_weak(Relay1), - /* K24 */ be_nested_str_weak(Relay2), - /* K25 */ be_nested_str_weak(push), - /* K26 */ be_nested_str_weak(MTR_X3A_X20relay1_X3D_X25s_X20relay2_X3D_X25s), - /* K27 */ be_nested_str_weak(TiltConfig), - /* K28 */ be_nested_str_weak(shutter_X2Btilt), - /* K29 */ be_nested_str_weak(shutter), - /* K30 */ be_nested_str_weak(get_power), - /* K31 */ be_nested_str_weak(relay), - /* K32 */ be_nested_str_weak(load), - /* K33 */ be_nested_str_weak(read_sensors), - /* K34 */ be_nested_str_weak(autoconf_sensors_list), - /* K35 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(autoconf_device_map), - &be_const_str_solidified, - ( &(const binstruction[198]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0x60080013, // 0001 GETGBL R2 G19 - 0x7C080000, // 0002 CALL R2 0 - 0x580C0001, // 0003 LDCONST R3 K1 - 0x50100000, // 0004 LDBOOL R4 0 0 - 0xA4160400, // 0005 IMPORT R5 K2 - 0x8C180B03, // 0006 GETMET R6 R5 K3 - 0x7C180200, // 0007 CALL R6 1 - 0x4C1C0000, // 0008 LDNIL R7 - 0x201C0C07, // 0009 NE R7 R6 R7 - 0x781E0024, // 000A JMPF R7 #0030 - 0x601C000C, // 000B GETGBL R7 G12 - 0x8C200D04, // 000C GETMET R8 R6 K4 - 0x58280005, // 000D LDCONST R10 K5 - 0x582C0006, // 000E LDCONST R11 K6 - 0x7C200600, // 000F CALL R8 3 - 0x7C1C0200, // 0010 CALL R7 1 - 0x24200F07, // 0011 GT R8 R7 K7 - 0x7822001C, // 0012 JMPF R8 #0030 - 0x1C200F01, // 0013 EQ R8 R7 K1 - 0x78220007, // 0014 JMPF R8 #001D - 0x60200008, // 0015 GETGBL R8 G8 - 0x5C240600, // 0016 MOVE R9 R3 - 0x7C200200, // 0017 CALL R8 1 - 0x60240013, // 0018 GETGBL R9 G19 - 0x7C240000, // 0019 CALL R9 0 - 0x98261109, // 001A SETIDX R9 K8 K9 - 0x98081009, // 001B SETIDX R2 R8 R9 - 0x70020010, // 001C JMP #002E - 0x1C200F0A, // 001D EQ R8 R7 K10 - 0x78220007, // 001E JMPF R8 #0027 - 0x60200008, // 001F GETGBL R8 G8 - 0x5C240600, // 0020 MOVE R9 R3 - 0x7C200200, // 0021 CALL R8 1 - 0x60240013, // 0022 GETGBL R9 G19 - 0x7C240000, // 0023 CALL R9 0 - 0x9826110B, // 0024 SETIDX R9 K8 K11 - 0x98081009, // 0025 SETIDX R2 R8 R9 - 0x70020006, // 0026 JMP #002E - 0x60200008, // 0027 GETGBL R8 G8 - 0x5C240600, // 0028 MOVE R9 R3 - 0x7C200200, // 0029 CALL R8 1 - 0x60240013, // 002A GETGBL R9 G19 - 0x7C240000, // 002B CALL R9 0 - 0x9826110C, // 002C SETIDX R9 K8 K12 - 0x98081009, // 002D SETIDX R2 R8 R9 - 0x50100200, // 002E LDBOOL R4 1 0 - 0x000C0701, // 002F ADD R3 R3 K1 - 0xB81E1A00, // 0030 GETNGBL R7 K13 - 0x8C1C0F0E, // 0031 GETMET R7 R7 K14 - 0x5824000F, // 0032 LDCONST R9 K15 - 0x50280200, // 0033 LDBOOL R10 1 0 - 0x7C1C0600, // 0034 CALL R7 3 - 0x60200012, // 0035 GETGBL R8 G18 - 0x7C200000, // 0036 CALL R8 0 - 0xB8261A00, // 0037 GETNGBL R9 K13 - 0x8C241310, // 0038 GETMET R9 R9 K16 - 0x602C0008, // 0039 GETGBL R11 G8 - 0x5C300E00, // 003A MOVE R12 R7 - 0x7C2C0200, // 003B CALL R11 1 - 0x002E220B, // 003C ADD R11 K17 R11 - 0x58300012, // 003D LDCONST R12 K18 - 0x7C240600, // 003E CALL R9 3 - 0x4C240000, // 003F LDNIL R9 - 0x20240E09, // 0040 NE R9 R7 R9 - 0x7826004F, // 0041 JMPF R9 #0092 - 0x8C240F13, // 0042 GETMET R9 R7 K19 - 0x582C0014, // 0043 LDCONST R11 K20 - 0x7C240400, // 0044 CALL R9 2 - 0x7826004B, // 0045 JMPF R9 #0092 - 0x941C0F14, // 0046 GETIDX R7 R7 K20 - 0x58240007, // 0047 LDCONST R9 K7 - 0x50280200, // 0048 LDBOOL R10 1 0 - 0x782A0047, // 0049 JMPF R10 #0092 - 0x60280008, // 004A GETGBL R10 G8 - 0x5C2C1200, // 004B MOVE R11 R9 - 0x7C280200, // 004C CALL R10 1 - 0x002A2A0A, // 004D ADD R10 K21 R10 - 0x8C2C0F13, // 004E GETMET R11 R7 K19 - 0x5C341400, // 004F MOVE R13 R10 - 0x7C2C0400, // 0050 CALL R11 2 - 0x742E0000, // 0051 JMPT R11 #0053 - 0x7002003E, // 0052 JMP #0092 - 0x942C0E0A, // 0053 GETIDX R11 R7 R10 - 0xB8321A00, // 0054 GETNGBL R12 K13 - 0x8C301910, // 0055 GETMET R12 R12 K16 - 0x60380018, // 0056 GETGBL R14 G24 - 0x583C0016, // 0057 LDCONST R15 K22 - 0x5C401400, // 0058 MOVE R16 R10 - 0x60440008, // 0059 GETGBL R17 G8 - 0x5C481600, // 005A MOVE R18 R11 - 0x7C440200, // 005B CALL R17 1 - 0x7C380600, // 005C CALL R14 3 - 0x583C0012, // 005D LDCONST R15 K18 - 0x7C300600, // 005E CALL R12 3 - 0x8C301704, // 005F GETMET R12 R11 K4 - 0x58380017, // 0060 LDCONST R14 K23 - 0x543DFFFE, // 0061 LDINT R15 -1 - 0x7C300600, // 0062 CALL R12 3 - 0x8C341704, // 0063 GETMET R13 R11 K4 - 0x583C0018, // 0064 LDCONST R15 K24 - 0x5441FFFE, // 0065 LDINT R16 -1 - 0x7C340600, // 0066 CALL R13 3 - 0x24381907, // 0067 GT R14 R12 K7 - 0x783A0002, // 0068 JMPF R14 #006C - 0x8C381119, // 0069 GETMET R14 R8 K25 - 0x04401901, // 006A SUB R16 R12 K1 - 0x7C380400, // 006B CALL R14 2 - 0x24381B07, // 006C GT R14 R13 K7 - 0x783A0002, // 006D JMPF R14 #0071 - 0x8C381119, // 006E GETMET R14 R8 K25 - 0x04401B01, // 006F SUB R16 R13 K1 - 0x7C380400, // 0070 CALL R14 2 - 0xB83A1A00, // 0071 GETNGBL R14 K13 - 0x8C381D10, // 0072 GETMET R14 R14 K16 - 0x60400018, // 0073 GETGBL R16 G24 - 0x5844001A, // 0074 LDCONST R17 K26 - 0x5C481800, // 0075 MOVE R18 R12 - 0x5C4C1A00, // 0076 MOVE R19 R13 - 0x7C400600, // 0077 CALL R16 3 - 0x58440012, // 0078 LDCONST R17 K18 - 0x7C380600, // 0079 CALL R14 3 - 0x8C381704, // 007A GETMET R14 R11 K4 - 0x5840001B, // 007B LDCONST R16 K27 - 0x7C380400, // 007C CALL R14 2 - 0x783A0002, // 007D JMPF R14 #0081 - 0x943C1D0A, // 007E GETIDX R15 R14 K10 - 0x243C1F07, // 007F GT R15 R15 K7 - 0x743E0000, // 0080 JMPT R15 #0082 - 0x503C0001, // 0081 LDBOOL R15 0 1 - 0x503C0200, // 0082 LDBOOL R15 1 0 - 0x60400008, // 0083 GETGBL R16 G8 - 0x5C440600, // 0084 MOVE R17 R3 - 0x7C400200, // 0085 CALL R16 1 - 0x60440013, // 0086 GETGBL R17 G19 - 0x7C440000, // 0087 CALL R17 0 - 0x783E0001, // 0088 JMPF R15 #008B - 0x5848001C, // 0089 LDCONST R18 K28 - 0x70020000, // 008A JMP #008C - 0x5848001D, // 008B LDCONST R18 K29 - 0x98461012, // 008C SETIDX R17 K8 R18 - 0x98463A09, // 008D SETIDX R17 K29 R9 - 0x98082011, // 008E SETIDX R2 R16 R17 - 0x000C0701, // 008F ADD R3 R3 K1 - 0x00241301, // 0090 ADD R9 R9 K1 - 0x7001FFB5, // 0091 JMP #0048 - 0x6024000C, // 0092 GETGBL R9 G12 - 0xB82A1A00, // 0093 GETNGBL R10 K13 - 0x8C28151E, // 0094 GETMET R10 R10 K30 - 0x7C280200, // 0095 CALL R10 1 - 0x7C240200, // 0096 CALL R9 1 - 0x58280007, // 0097 LDCONST R10 K7 - 0x78120000, // 0098 JMPF R4 #009A - 0x04241301, // 0099 SUB R9 R9 K1 - 0x142C1409, // 009A LT R11 R10 R9 - 0x782E0011, // 009B JMPF R11 #00AE - 0x8C2C1104, // 009C GETMET R11 R8 K4 - 0x5C341400, // 009D MOVE R13 R10 - 0x7C2C0400, // 009E CALL R11 2 - 0x4C300000, // 009F LDNIL R12 - 0x1C2C160C, // 00A0 EQ R11 R11 R12 - 0x782E0009, // 00A1 JMPF R11 #00AC - 0x602C0008, // 00A2 GETGBL R11 G8 - 0x5C300600, // 00A3 MOVE R12 R3 - 0x7C2C0200, // 00A4 CALL R11 1 - 0x60300013, // 00A5 GETGBL R12 G19 - 0x7C300000, // 00A6 CALL R12 0 - 0x9832111F, // 00A7 SETIDX R12 K8 K31 - 0x00341501, // 00A8 ADD R13 R10 K1 - 0x98323E0D, // 00A9 SETIDX R12 K31 R13 - 0x9808160C, // 00AA SETIDX R2 R11 R12 - 0x000C0701, // 00AB ADD R3 R3 K1 - 0x00281501, // 00AC ADD R10 R10 K1 - 0x7001FFEB, // 00AD JMP #009A - 0x8C2C0320, // 00AE GETMET R11 R1 K32 - 0xB8361A00, // 00AF GETNGBL R13 K13 - 0x8C341B21, // 00B0 GETMET R13 R13 K33 - 0x7C340200, // 00B1 CALL R13 1 - 0x7C2C0400, // 00B2 CALL R11 2 - 0x8C300122, // 00B3 GETMET R12 R0 K34 - 0x5C381600, // 00B4 MOVE R14 R11 - 0x7C300400, // 00B5 CALL R12 2 - 0x60340010, // 00B6 GETGBL R13 G16 - 0x5C381800, // 00B7 MOVE R14 R12 - 0x7C340200, // 00B8 CALL R13 1 - 0xA8020007, // 00B9 EXBLK 0 #00C2 - 0x5C381A00, // 00BA MOVE R14 R13 - 0x7C380000, // 00BB CALL R14 0 - 0x603C0008, // 00BC GETGBL R15 G8 - 0x5C400600, // 00BD MOVE R16 R3 - 0x7C3C0200, // 00BE CALL R15 1 - 0x98081E0E, // 00BF SETIDX R2 R15 R14 - 0x000C0701, // 00C0 ADD R3 R3 K1 - 0x7001FFF7, // 00C1 JMP #00BA - 0x58340023, // 00C2 LDCONST R13 K35 - 0xAC340200, // 00C3 CATCH R13 1 0 - 0xB0080000, // 00C4 RAISE 2 R0 R0 - 0x80040400, // 00C5 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: remove_fabric -********************************************************************/ -be_local_closure(Matter_Device_remove_fabric, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[16]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(log), - /* K2 */ be_nested_str_weak(MTR_X3A_X20removing_X20fabric_X20), - /* K3 */ be_nested_str_weak(get_fabric_id), - /* K4 */ be_nested_str_weak(copy), - /* K5 */ be_nested_str_weak(reverse), - /* K6 */ be_nested_str_weak(tohex), - /* K7 */ be_const_int(2), - /* K8 */ be_nested_str_weak(message_handler), - /* K9 */ be_nested_str_weak(im), - /* K10 */ be_nested_str_weak(subs_shop), - /* K11 */ be_nested_str_weak(remove_by_fabric), - /* K12 */ be_nested_str_weak(mdns_remove_op_discovery), - /* K13 */ be_nested_str_weak(sessions), - /* K14 */ be_nested_str_weak(remove_fabric), - /* K15 */ be_nested_str_weak(save_fabrics), - }), - be_str_weak(remove_fabric), - &be_const_str_solidified, - ( &(const binstruction[33]) { /* code */ - 0x4C080000, // 0000 LDNIL R2 - 0x20080202, // 0001 NE R2 R1 R2 - 0x780A0019, // 0002 JMPF R2 #001D - 0xB80A0000, // 0003 GETNGBL R2 K0 - 0x8C080501, // 0004 GETMET R2 R2 K1 - 0x8C100303, // 0005 GETMET R4 R1 K3 - 0x7C100200, // 0006 CALL R4 1 - 0x8C100904, // 0007 GETMET R4 R4 K4 - 0x7C100200, // 0008 CALL R4 1 - 0x8C100905, // 0009 GETMET R4 R4 K5 - 0x7C100200, // 000A CALL R4 1 - 0x8C100906, // 000B GETMET R4 R4 K6 - 0x7C100200, // 000C CALL R4 1 - 0x00120404, // 000D ADD R4 K2 R4 - 0x58140007, // 000E LDCONST R5 K7 - 0x7C080600, // 000F CALL R2 3 - 0x88080108, // 0010 GETMBR R2 R0 K8 - 0x88080509, // 0011 GETMBR R2 R2 K9 - 0x8808050A, // 0012 GETMBR R2 R2 K10 - 0x8C08050B, // 0013 GETMET R2 R2 K11 - 0x5C100200, // 0014 MOVE R4 R1 - 0x7C080400, // 0015 CALL R2 2 - 0x8C08010C, // 0016 GETMET R2 R0 K12 - 0x5C100200, // 0017 MOVE R4 R1 - 0x7C080400, // 0018 CALL R2 2 - 0x8808010D, // 0019 GETMBR R2 R0 K13 - 0x8C08050E, // 001A GETMET R2 R2 K14 - 0x5C100200, // 001B MOVE R4 R1 - 0x7C080400, // 001C CALL R2 2 - 0x8808010D, // 001D GETMBR R2 R0 K13 - 0x8C08050F, // 001E GETMET R2 R2 K15 - 0x7C080200, // 001F CALL R2 1 - 0x80000000, // 0020 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: stop -********************************************************************/ -be_local_closure(Matter_Device_stop, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(remove_driver), - /* K2 */ be_nested_str_weak(udp_server), - /* K3 */ be_nested_str_weak(stop), - }), - be_str_weak(stop), - &be_const_str_solidified, - ( &(const binstruction[10]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x5C0C0000, // 0002 MOVE R3 R0 - 0x7C040400, // 0003 CALL R1 2 - 0x88040102, // 0004 GETMBR R1 R0 K2 - 0x78060002, // 0005 JMPF R1 #0009 - 0x88040102, // 0006 GETMBR R1 R0 K2 - 0x8C040303, // 0007 GETMET R1 R1 K3 - 0x7C040200, // 0008 CALL R1 1 - 0x80000000, // 0009 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: mdns_announce_op_discovery -********************************************************************/ -be_local_closure(Matter_Device_mdns_announce_op_discovery, /* name */ - be_nested_proto( - 14, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[27]) { /* constants */ - /* K0 */ be_nested_str_weak(mdns), - /* K1 */ be_nested_str_weak(get_device_id), - /* K2 */ be_nested_str_weak(copy), - /* K3 */ be_nested_str_weak(reverse), - /* K4 */ be_nested_str_weak(get_fabric_compressed), - /* K5 */ be_nested_str_weak(tohex), - /* K6 */ be_nested_str_weak(_X2D), - /* K7 */ be_nested_str_weak(tasmota), - /* K8 */ be_nested_str_weak(log), - /* K9 */ be_nested_str_weak(MTR_X3A_X20Operational_X20Discovery_X20node_X20_X3D_X20), - /* K10 */ be_const_int(3), - /* K11 */ be_nested_str_weak(eth), - /* K12 */ be_nested_str_weak(find), - /* K13 */ be_nested_str_weak(up), - /* K14 */ be_nested_str_weak(MTR_X3A_X20adding_X20mDNS_X20on_X20_X25s_X20_X27_X25s_X27_X20ptr_X20to_X20_X60_X25s_X2Elocal_X60), - /* K15 */ be_nested_str_weak(hostname_eth), - /* K16 */ be_nested_str_weak(add_service), - /* K17 */ be_nested_str_weak(_matter), - /* K18 */ be_nested_str_weak(_tcp), - /* K19 */ be_nested_str_weak(_I), - /* K20 */ be_nested_str_weak(MTR_X3A_X20adding_X20subtype_X3A_X20), - /* K21 */ be_nested_str_weak(add_subtype), - /* K22 */ be_nested_str_weak(wifi), - /* K23 */ be_nested_str_weak(hostname_wifi), - /* K24 */ be_nested_str_weak(MTR_X3A_X20Exception), - /* K25 */ be_nested_str_weak(_X7C), - /* K26 */ be_const_int(2), - }), - be_str_weak(mdns_announce_op_discovery), - &be_const_str_solidified, - ( &(const binstruction[121]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0xA8020064, // 0001 EXBLK 0 #0067 - 0x8C0C0301, // 0002 GETMET R3 R1 K1 - 0x7C0C0200, // 0003 CALL R3 1 - 0x8C0C0702, // 0004 GETMET R3 R3 K2 - 0x7C0C0200, // 0005 CALL R3 1 - 0x8C0C0703, // 0006 GETMET R3 R3 K3 - 0x7C0C0200, // 0007 CALL R3 1 - 0x8C100304, // 0008 GETMET R4 R1 K4 - 0x7C100200, // 0009 CALL R4 1 - 0x8C140905, // 000A GETMET R5 R4 K5 - 0x7C140200, // 000B CALL R5 1 - 0x00140B06, // 000C ADD R5 R5 K6 - 0x8C180705, // 000D GETMET R6 R3 K5 - 0x7C180200, // 000E CALL R6 1 - 0x00140A06, // 000F ADD R5 R5 R6 - 0xB81A0E00, // 0010 GETNGBL R6 K7 - 0x8C180D08, // 0011 GETMET R6 R6 K8 - 0x00221205, // 0012 ADD R8 K9 R5 - 0x5824000A, // 0013 LDCONST R9 K10 - 0x7C180600, // 0014 CALL R6 3 - 0xB81A0E00, // 0015 GETNGBL R6 K7 - 0x8C180D0B, // 0016 GETMET R6 R6 K11 - 0x7C180200, // 0017 CALL R6 1 - 0x8C180D0C, // 0018 GETMET R6 R6 K12 - 0x5820000D, // 0019 LDCONST R8 K13 - 0x7C180400, // 001A CALL R6 2 - 0x781A0020, // 001B JMPF R6 #003D - 0xB81A0E00, // 001C GETNGBL R6 K7 - 0x8C180D08, // 001D GETMET R6 R6 K8 - 0x60200018, // 001E GETGBL R8 G24 - 0x5824000E, // 001F LDCONST R9 K14 - 0x5828000B, // 0020 LDCONST R10 K11 - 0x5C2C0A00, // 0021 MOVE R11 R5 - 0x8830010F, // 0022 GETMBR R12 R0 K15 - 0x7C200800, // 0023 CALL R8 4 - 0x5824000A, // 0024 LDCONST R9 K10 - 0x7C180600, // 0025 CALL R6 3 - 0x8C180510, // 0026 GETMET R6 R2 K16 - 0x58200011, // 0027 LDCONST R8 K17 - 0x58240012, // 0028 LDCONST R9 K18 - 0x542A15A3, // 0029 LDINT R10 5540 - 0x4C2C0000, // 002A LDNIL R11 - 0x5C300A00, // 002B MOVE R12 R5 - 0x8834010F, // 002C GETMBR R13 R0 K15 - 0x7C180E00, // 002D CALL R6 7 - 0x8C180905, // 002E GETMET R6 R4 K5 - 0x7C180200, // 002F CALL R6 1 - 0x001A2606, // 0030 ADD R6 K19 R6 - 0xB81E0E00, // 0031 GETNGBL R7 K7 - 0x8C1C0F08, // 0032 GETMET R7 R7 K8 - 0x00262806, // 0033 ADD R9 K20 R6 - 0x5828000A, // 0034 LDCONST R10 K10 - 0x7C1C0600, // 0035 CALL R7 3 - 0x8C1C0515, // 0036 GETMET R7 R2 K21 - 0x58240011, // 0037 LDCONST R9 K17 - 0x58280012, // 0038 LDCONST R10 K18 - 0x5C2C0A00, // 0039 MOVE R11 R5 - 0x8830010F, // 003A GETMBR R12 R0 K15 - 0x5C340C00, // 003B MOVE R13 R6 - 0x7C1C0C00, // 003C CALL R7 6 - 0xB81A0E00, // 003D GETNGBL R6 K7 - 0x8C180D16, // 003E GETMET R6 R6 K22 - 0x7C180200, // 003F CALL R6 1 - 0x8C180D0C, // 0040 GETMET R6 R6 K12 - 0x5820000D, // 0041 LDCONST R8 K13 - 0x7C180400, // 0042 CALL R6 2 - 0x781A0020, // 0043 JMPF R6 #0065 - 0xB81A0E00, // 0044 GETNGBL R6 K7 - 0x8C180D08, // 0045 GETMET R6 R6 K8 - 0x60200018, // 0046 GETGBL R8 G24 - 0x5824000E, // 0047 LDCONST R9 K14 - 0x58280016, // 0048 LDCONST R10 K22 - 0x5C2C0A00, // 0049 MOVE R11 R5 - 0x88300117, // 004A GETMBR R12 R0 K23 - 0x7C200800, // 004B CALL R8 4 - 0x5824000A, // 004C LDCONST R9 K10 - 0x7C180600, // 004D CALL R6 3 - 0x8C180510, // 004E GETMET R6 R2 K16 - 0x58200011, // 004F LDCONST R8 K17 - 0x58240012, // 0050 LDCONST R9 K18 - 0x542A15A3, // 0051 LDINT R10 5540 - 0x4C2C0000, // 0052 LDNIL R11 - 0x5C300A00, // 0053 MOVE R12 R5 - 0x88340117, // 0054 GETMBR R13 R0 K23 - 0x7C180E00, // 0055 CALL R6 7 - 0x8C180905, // 0056 GETMET R6 R4 K5 - 0x7C180200, // 0057 CALL R6 1 - 0x001A2606, // 0058 ADD R6 K19 R6 - 0xB81E0E00, // 0059 GETNGBL R7 K7 - 0x8C1C0F08, // 005A GETMET R7 R7 K8 - 0x00262806, // 005B ADD R9 K20 R6 - 0x5828000A, // 005C LDCONST R10 K10 - 0x7C1C0600, // 005D CALL R7 3 - 0x8C1C0515, // 005E GETMET R7 R2 K21 - 0x58240011, // 005F LDCONST R9 K17 - 0x58280012, // 0060 LDCONST R10 K18 - 0x5C2C0A00, // 0061 MOVE R11 R5 - 0x88300117, // 0062 GETMBR R12 R0 K23 - 0x5C340C00, // 0063 MOVE R13 R6 - 0x7C1C0C00, // 0064 CALL R7 6 - 0xA8040001, // 0065 EXBLK 1 1 - 0x70020010, // 0066 JMP #0078 - 0xAC0C0002, // 0067 CATCH R3 0 2 - 0x7002000D, // 0068 JMP #0077 - 0xB8160E00, // 0069 GETNGBL R5 K7 - 0x8C140B08, // 006A GETMET R5 R5 K8 - 0x601C0008, // 006B GETGBL R7 G8 - 0x5C200600, // 006C MOVE R8 R3 - 0x7C1C0200, // 006D CALL R7 1 - 0x001E3007, // 006E ADD R7 K24 R7 - 0x001C0F19, // 006F ADD R7 R7 K25 - 0x60200008, // 0070 GETGBL R8 G8 - 0x5C240800, // 0071 MOVE R9 R4 - 0x7C200200, // 0072 CALL R8 1 - 0x001C0E08, // 0073 ADD R7 R7 R8 - 0x5820001A, // 0074 LDCONST R8 K26 - 0x7C140600, // 0075 CALL R5 3 - 0x70020000, // 0076 JMP #0078 - 0xB0080000, // 0077 RAISE 2 R0 R0 - 0x80000000, // 0078 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: stop_basic_commissioning -********************************************************************/ -be_local_closure(Matter_Device_stop_basic_commissioning, /* name */ - be_nested_proto( - 5, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[13]) { /* constants */ - /* K0 */ be_nested_str_weak(is_root_commissioning_open), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(publish_result), - /* K3 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Commissioning_X22_X3A0_X7D_X7D), - /* K4 */ be_nested_str_weak(Matter), - /* K5 */ be_nested_str_weak(commissioning_open), - /* K6 */ be_nested_str_weak(mdns_remove_PASE), - /* K7 */ be_nested_str_weak(commissioning_iterations), - /* K8 */ be_nested_str_weak(commissioning_discriminator), - /* K9 */ be_nested_str_weak(commissioning_salt), - /* K10 */ be_nested_str_weak(commissioning_w0), - /* K11 */ be_nested_str_weak(commissioning_L), - /* K12 */ be_nested_str_weak(commissioning_admin_fabric), - }), - be_str_weak(stop_basic_commissioning), - &be_const_str_solidified, - ( &(const binstruction[25]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0x78060004, // 0002 JMPF R1 #0008 - 0xB8060200, // 0003 GETNGBL R1 K1 - 0x8C040302, // 0004 GETMET R1 R1 K2 - 0x580C0003, // 0005 LDCONST R3 K3 - 0x58100004, // 0006 LDCONST R4 K4 - 0x7C040600, // 0007 CALL R1 3 - 0x4C040000, // 0008 LDNIL R1 - 0x90020A01, // 0009 SETMBR R0 K5 R1 - 0x8C040106, // 000A GETMET R1 R0 K6 - 0x7C040200, // 000B CALL R1 1 - 0x4C040000, // 000C LDNIL R1 - 0x90020E01, // 000D SETMBR R0 K7 R1 - 0x4C040000, // 000E LDNIL R1 - 0x90021001, // 000F SETMBR R0 K8 R1 - 0x4C040000, // 0010 LDNIL R1 - 0x90021201, // 0011 SETMBR R0 K9 R1 - 0x4C040000, // 0012 LDNIL R1 - 0x90021401, // 0013 SETMBR R0 K10 R1 - 0x4C040000, // 0014 LDNIL R1 - 0x90021601, // 0015 SETMBR R0 K11 R1 - 0x4C040000, // 0016 LDNIL R1 - 0x90021801, // 0017 SETMBR R0 K12 R1 - 0x80000000, // 0018 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: autoconf_sensors_list -********************************************************************/ -be_local_closure(Matter_Device_autoconf_sensors_list, /* name */ - be_nested_proto( - 10, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[18]) { /* constants */ - /* K0 */ be_nested_str_weak(k2l), - /* K1 */ be_nested_str_weak(contains), - /* K2 */ be_nested_str_weak(Temperature), - /* K3 */ be_nested_str_weak(_X23Temperature), - /* K4 */ be_nested_str_weak(push), - /* K5 */ be_nested_str_weak(type), - /* K6 */ be_nested_str_weak(temperature), - /* K7 */ be_nested_str_weak(filter), - /* K8 */ be_nested_str_weak(stop_iteration), - /* K9 */ be_nested_str_weak(Pressure), - /* K10 */ be_nested_str_weak(_X23Pressure), - /* K11 */ be_nested_str_weak(pressure), - /* K12 */ be_nested_str_weak(Illuminance), - /* K13 */ be_nested_str_weak(_X23Illuminance), - /* K14 */ be_nested_str_weak(illuminance), - /* K15 */ be_nested_str_weak(Humidity), - /* K16 */ be_nested_str_weak(_X23Humidity), - /* K17 */ be_nested_str_weak(humidity), - }), - be_str_weak(autoconf_sensors_list), - &be_const_str_solidified, - ( &(const binstruction[119]) { /* code */ - 0x60080012, // 0000 GETGBL R2 G18 - 0x7C080000, // 0001 CALL R2 0 - 0x600C0010, // 0002 GETGBL R3 G16 - 0x8C100100, // 0003 GETMET R4 R0 K0 - 0x5C180200, // 0004 MOVE R6 R1 - 0x7C100400, // 0005 CALL R4 2 - 0x7C0C0200, // 0006 CALL R3 1 - 0xA8020013, // 0007 EXBLK 0 #001C - 0x5C100600, // 0008 MOVE R4 R3 - 0x7C100000, // 0009 CALL R4 0 - 0x94140204, // 000A GETIDX R5 R1 R4 - 0x6018000F, // 000B GETGBL R6 G15 - 0x5C1C0A00, // 000C MOVE R7 R5 - 0x60200013, // 000D GETGBL R8 G19 - 0x7C180400, // 000E CALL R6 2 - 0x781A000A, // 000F JMPF R6 #001B - 0x8C180B01, // 0010 GETMET R6 R5 K1 - 0x58200002, // 0011 LDCONST R8 K2 - 0x7C180400, // 0012 CALL R6 2 - 0x781A0006, // 0013 JMPF R6 #001B - 0x00180903, // 0014 ADD R6 R4 K3 - 0x8C1C0504, // 0015 GETMET R7 R2 K4 - 0x60240013, // 0016 GETGBL R9 G19 - 0x7C240000, // 0017 CALL R9 0 - 0x98260B06, // 0018 SETIDX R9 K5 K6 - 0x98260E06, // 0019 SETIDX R9 K7 R6 - 0x7C1C0400, // 001A CALL R7 2 - 0x7001FFEB, // 001B JMP #0008 - 0x580C0008, // 001C LDCONST R3 K8 - 0xAC0C0200, // 001D CATCH R3 1 0 - 0xB0080000, // 001E RAISE 2 R0 R0 - 0x600C0010, // 001F GETGBL R3 G16 - 0x8C100100, // 0020 GETMET R4 R0 K0 - 0x5C180200, // 0021 MOVE R6 R1 - 0x7C100400, // 0022 CALL R4 2 - 0x7C0C0200, // 0023 CALL R3 1 - 0xA8020013, // 0024 EXBLK 0 #0039 - 0x5C100600, // 0025 MOVE R4 R3 - 0x7C100000, // 0026 CALL R4 0 - 0x94140204, // 0027 GETIDX R5 R1 R4 - 0x6018000F, // 0028 GETGBL R6 G15 - 0x5C1C0A00, // 0029 MOVE R7 R5 - 0x60200013, // 002A GETGBL R8 G19 - 0x7C180400, // 002B CALL R6 2 - 0x781A000A, // 002C JMPF R6 #0038 - 0x8C180B01, // 002D GETMET R6 R5 K1 - 0x58200009, // 002E LDCONST R8 K9 - 0x7C180400, // 002F CALL R6 2 - 0x781A0006, // 0030 JMPF R6 #0038 - 0x0018090A, // 0031 ADD R6 R4 K10 - 0x8C1C0504, // 0032 GETMET R7 R2 K4 - 0x60240013, // 0033 GETGBL R9 G19 - 0x7C240000, // 0034 CALL R9 0 - 0x98260B0B, // 0035 SETIDX R9 K5 K11 - 0x98260E06, // 0036 SETIDX R9 K7 R6 - 0x7C1C0400, // 0037 CALL R7 2 - 0x7001FFEB, // 0038 JMP #0025 - 0x580C0008, // 0039 LDCONST R3 K8 - 0xAC0C0200, // 003A CATCH R3 1 0 - 0xB0080000, // 003B RAISE 2 R0 R0 - 0x600C0010, // 003C GETGBL R3 G16 - 0x8C100100, // 003D GETMET R4 R0 K0 - 0x5C180200, // 003E MOVE R6 R1 - 0x7C100400, // 003F CALL R4 2 - 0x7C0C0200, // 0040 CALL R3 1 - 0xA8020013, // 0041 EXBLK 0 #0056 - 0x5C100600, // 0042 MOVE R4 R3 - 0x7C100000, // 0043 CALL R4 0 - 0x94140204, // 0044 GETIDX R5 R1 R4 - 0x6018000F, // 0045 GETGBL R6 G15 - 0x5C1C0A00, // 0046 MOVE R7 R5 - 0x60200013, // 0047 GETGBL R8 G19 - 0x7C180400, // 0048 CALL R6 2 - 0x781A000A, // 0049 JMPF R6 #0055 - 0x8C180B01, // 004A GETMET R6 R5 K1 - 0x5820000C, // 004B LDCONST R8 K12 - 0x7C180400, // 004C CALL R6 2 - 0x781A0006, // 004D JMPF R6 #0055 - 0x0018090D, // 004E ADD R6 R4 K13 - 0x8C1C0504, // 004F GETMET R7 R2 K4 - 0x60240013, // 0050 GETGBL R9 G19 - 0x7C240000, // 0051 CALL R9 0 - 0x98260B0E, // 0052 SETIDX R9 K5 K14 - 0x98260E06, // 0053 SETIDX R9 K7 R6 - 0x7C1C0400, // 0054 CALL R7 2 - 0x7001FFEB, // 0055 JMP #0042 - 0x580C0008, // 0056 LDCONST R3 K8 - 0xAC0C0200, // 0057 CATCH R3 1 0 - 0xB0080000, // 0058 RAISE 2 R0 R0 - 0x600C0010, // 0059 GETGBL R3 G16 - 0x8C100100, // 005A GETMET R4 R0 K0 - 0x5C180200, // 005B MOVE R6 R1 - 0x7C100400, // 005C CALL R4 2 - 0x7C0C0200, // 005D CALL R3 1 - 0xA8020013, // 005E EXBLK 0 #0073 - 0x5C100600, // 005F MOVE R4 R3 - 0x7C100000, // 0060 CALL R4 0 - 0x94140204, // 0061 GETIDX R5 R1 R4 - 0x6018000F, // 0062 GETGBL R6 G15 - 0x5C1C0A00, // 0063 MOVE R7 R5 - 0x60200013, // 0064 GETGBL R8 G19 - 0x7C180400, // 0065 CALL R6 2 - 0x781A000A, // 0066 JMPF R6 #0072 - 0x8C180B01, // 0067 GETMET R6 R5 K1 - 0x5820000F, // 0068 LDCONST R8 K15 - 0x7C180400, // 0069 CALL R6 2 - 0x781A0006, // 006A JMPF R6 #0072 - 0x00180910, // 006B ADD R6 R4 K16 - 0x8C1C0504, // 006C GETMET R7 R2 K4 - 0x60240013, // 006D GETGBL R9 G19 - 0x7C240000, // 006E CALL R9 0 - 0x98260B11, // 006F SETIDX R9 K5 K17 - 0x98260E06, // 0070 SETIDX R9 K7 R6 - 0x7C1C0400, // 0071 CALL R7 2 - 0x7001FFEB, // 0072 JMP #005F - 0x580C0008, // 0073 LDCONST R3 K8 - 0xAC0C0200, // 0074 CATCH R3 1 0 - 0xB0080000, // 0075 RAISE 2 R0 R0 - 0x80040400, // 0076 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: clean_remotes -********************************************************************/ -be_local_closure(Matter_Device_clean_remotes, /* name */ - be_nested_proto( - 10, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[18]) { /* constants */ - /* K0 */ be_nested_str_weak(introspect), - /* K1 */ be_nested_str_weak(http_remotes), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(stop_iteration), - /* K4 */ be_nested_str_weak(plugins), - /* K5 */ be_nested_str_weak(get), - /* K6 */ be_nested_str_weak(http_remote), - /* K7 */ be_nested_str_weak(find), - /* K8 */ be_const_int(1), - /* K9 */ be_nested_str_weak(keys), - /* K10 */ be_nested_str_weak(push), - /* K11 */ be_nested_str_weak(tasmota), - /* K12 */ be_nested_str_weak(log), - /* K13 */ be_nested_str_weak(MTR_X3A_X20remove_X20unused_X20remote_X3A_X20), - /* K14 */ be_nested_str_weak(addr), - /* K15 */ be_const_int(3), - /* K16 */ be_nested_str_weak(close), - /* K17 */ be_nested_str_weak(remove), - }), - be_str_weak(clean_remotes), - &be_const_str_solidified, - ( &(const binstruction[81]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0x88080101, // 0001 GETMBR R2 R0 K1 - 0x780A004C, // 0002 JMPF R2 #0050 - 0x60080013, // 0003 GETGBL R2 G19 - 0x7C080000, // 0004 CALL R2 0 - 0x600C0010, // 0005 GETGBL R3 G16 - 0x88100101, // 0006 GETMBR R4 R0 K1 - 0x7C0C0200, // 0007 CALL R3 1 - 0xA8020003, // 0008 EXBLK 0 #000D - 0x5C100600, // 0009 MOVE R4 R3 - 0x7C100000, // 000A CALL R4 0 - 0x98080902, // 000B SETIDX R2 R4 K2 - 0x7001FFFB, // 000C JMP #0009 - 0x580C0003, // 000D LDCONST R3 K3 - 0xAC0C0200, // 000E CATCH R3 1 0 - 0xB0080000, // 000F RAISE 2 R0 R0 - 0x600C0010, // 0010 GETGBL R3 G16 - 0x88100104, // 0011 GETMBR R4 R0 K4 - 0x7C0C0200, // 0012 CALL R3 1 - 0xA802000F, // 0013 EXBLK 0 #0024 - 0x5C100600, // 0014 MOVE R4 R3 - 0x7C100000, // 0015 CALL R4 0 - 0x8C140305, // 0016 GETMET R5 R1 K5 - 0x5C1C0800, // 0017 MOVE R7 R4 - 0x58200006, // 0018 LDCONST R8 K6 - 0x7C140600, // 0019 CALL R5 3 - 0x4C180000, // 001A LDNIL R6 - 0x20180A06, // 001B NE R6 R5 R6 - 0x781A0005, // 001C JMPF R6 #0023 - 0x8C180507, // 001D GETMET R6 R2 K7 - 0x5C200A00, // 001E MOVE R8 R5 - 0x58240002, // 001F LDCONST R9 K2 - 0x7C180600, // 0020 CALL R6 3 - 0x00180D08, // 0021 ADD R6 R6 K8 - 0x98080A06, // 0022 SETIDX R2 R5 R6 - 0x7001FFEF, // 0023 JMP #0014 - 0x580C0003, // 0024 LDCONST R3 K3 - 0xAC0C0200, // 0025 CATCH R3 1 0 - 0xB0080000, // 0026 RAISE 2 R0 R0 - 0x600C0012, // 0027 GETGBL R3 G18 - 0x7C0C0000, // 0028 CALL R3 0 - 0x60100010, // 0029 GETGBL R4 G16 - 0x8C140509, // 002A GETMET R5 R2 K9 - 0x7C140200, // 002B CALL R5 1 - 0x7C100200, // 002C CALL R4 1 - 0xA8020008, // 002D EXBLK 0 #0037 - 0x5C140800, // 002E MOVE R5 R4 - 0x7C140000, // 002F CALL R5 0 - 0x94180405, // 0030 GETIDX R6 R2 R5 - 0x1C180D02, // 0031 EQ R6 R6 K2 - 0x781A0002, // 0032 JMPF R6 #0036 - 0x8C18070A, // 0033 GETMET R6 R3 K10 - 0x5C200A00, // 0034 MOVE R8 R5 - 0x7C180400, // 0035 CALL R6 2 - 0x7001FFF6, // 0036 JMP #002E - 0x58100003, // 0037 LDCONST R4 K3 - 0xAC100200, // 0038 CATCH R4 1 0 - 0xB0080000, // 0039 RAISE 2 R0 R0 - 0x60100010, // 003A GETGBL R4 G16 - 0x5C140600, // 003B MOVE R5 R3 - 0x7C100200, // 003C CALL R4 1 - 0xA802000E, // 003D EXBLK 0 #004D - 0x5C140800, // 003E MOVE R5 R4 - 0x7C140000, // 003F CALL R5 0 - 0xB81A1600, // 0040 GETNGBL R6 K11 - 0x8C180D0C, // 0041 GETMET R6 R6 K12 - 0x88200B0E, // 0042 GETMBR R8 R5 K14 - 0x00221A08, // 0043 ADD R8 K13 R8 - 0x5824000F, // 0044 LDCONST R9 K15 - 0x7C180600, // 0045 CALL R6 3 - 0x8C180B10, // 0046 GETMET R6 R5 K16 - 0x7C180200, // 0047 CALL R6 1 - 0x88180101, // 0048 GETMBR R6 R0 K1 - 0x8C180D11, // 0049 GETMET R6 R6 K17 - 0x88200B0E, // 004A GETMBR R8 R5 K14 - 0x7C180400, // 004B CALL R6 2 - 0x7001FFF0, // 004C JMP #003E - 0x58100003, // 004D LDCONST R4 K3 - 0xAC100200, // 004E CATCH R4 1 0 - 0xB0080000, // 004F RAISE 2 R0 R0 - 0x80000000, // 0050 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: update_remotes_info -********************************************************************/ -be_local_closure(Matter_Device_update_remotes_info, /* name */ - be_nested_proto( - 7, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(http_remotes), - /* K1 */ be_nested_str_weak(keys), - /* K2 */ be_nested_str_weak(get_info), - /* K3 */ be_const_int(0), - /* K4 */ be_nested_str_weak(stop_iteration), - /* K5 */ be_nested_str_weak(plugins_config_remotes), - }), - be_str_weak(update_remotes_info), - &be_const_str_solidified, - ( &(const binstruction[33]) { /* code */ - 0x60040013, // 0000 GETGBL R1 G19 - 0x7C040000, // 0001 CALL R1 0 - 0x88080100, // 0002 GETMBR R2 R0 K0 - 0x4C0C0000, // 0003 LDNIL R3 - 0x20080403, // 0004 NE R2 R2 R3 - 0x780A0018, // 0005 JMPF R2 #001F - 0x60080010, // 0006 GETGBL R2 G16 - 0x880C0100, // 0007 GETMBR R3 R0 K0 - 0x8C0C0701, // 0008 GETMET R3 R3 K1 - 0x7C0C0200, // 0009 CALL R3 1 - 0x7C080200, // 000A CALL R2 1 - 0xA802000F, // 000B EXBLK 0 #001C - 0x5C0C0400, // 000C MOVE R3 R2 - 0x7C0C0000, // 000D CALL R3 0 - 0x88100100, // 000E GETMBR R4 R0 K0 - 0x94100803, // 000F GETIDX R4 R4 R3 - 0x8C100902, // 0010 GETMET R4 R4 K2 - 0x7C100200, // 0011 CALL R4 1 - 0x4C140000, // 0012 LDNIL R5 - 0x20140805, // 0013 NE R5 R4 R5 - 0x78160005, // 0014 JMPF R5 #001B - 0x6014000C, // 0015 GETGBL R5 G12 - 0x5C180800, // 0016 MOVE R6 R4 - 0x7C140200, // 0017 CALL R5 1 - 0x24140B03, // 0018 GT R5 R5 K3 - 0x78160000, // 0019 JMPF R5 #001B - 0x98040604, // 001A SETIDX R1 R3 R4 - 0x7001FFEF, // 001B JMP #000C - 0x58080004, // 001C LDCONST R2 K4 - 0xAC080200, // 001D CATCH R2 1 0 - 0xB0080000, // 001E RAISE 2 R0 R0 - 0x90020A01, // 001F SETMBR R0 K5 R1 - 0x80040200, // 0020 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_plugin_class_displayname -********************************************************************/ -be_local_closure(Matter_Device_get_plugin_class_displayname, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(plugins_classes), - /* K1 */ be_nested_str_weak(find), - /* K2 */ be_nested_str_weak(DISPLAY_NAME), - /* K3 */ be_nested_str_weak(), - }), - be_str_weak(get_plugin_class_displayname), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x780A0001, // 0004 JMPF R2 #0007 - 0x880C0502, // 0005 GETMBR R3 R2 K2 - 0x70020000, // 0006 JMP #0008 - 0x580C0003, // 0007 LDCONST R3 K3 - 0x80040600, // 0008 RET 1 R3 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: process_attribute_read_solo -********************************************************************/ -be_local_closure(Matter_Device_process_attribute_read_solo, /* name */ - be_nested_proto( - 10, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ - /* K0 */ be_nested_str_weak(endpoint), - /* K1 */ be_nested_str_weak(cluster), - /* K2 */ be_nested_str_weak(attribute), - /* K3 */ be_nested_str_weak(find_plugin_by_endpoint), - /* K4 */ be_nested_str_weak(status), - /* K5 */ be_nested_str_weak(matter), - /* K6 */ be_nested_str_weak(UNSUPPORTED_ENDPOINT), - /* K7 */ be_nested_str_weak(contains_cluster), - /* K8 */ be_nested_str_weak(UNSUPPORTED_CLUSTER), - /* K9 */ be_nested_str_weak(contains_attribute), - /* K10 */ be_nested_str_weak(UNSUPPORTED_ATTRIBUTE), - }), - be_str_weak(process_attribute_read_solo), - &be_const_str_solidified, - ( &(const binstruction[45]) { /* code */ - 0x88080300, // 0000 GETMBR R2 R1 K0 - 0x880C0301, // 0001 GETMBR R3 R1 K1 - 0x88100302, // 0002 GETMBR R4 R1 K2 - 0x4C140000, // 0003 LDNIL R5 - 0x1C140405, // 0004 EQ R5 R2 R5 - 0x74160005, // 0005 JMPT R5 #000C - 0x4C140000, // 0006 LDNIL R5 - 0x1C140605, // 0007 EQ R5 R3 R5 - 0x74160002, // 0008 JMPT R5 #000C - 0x4C140000, // 0009 LDNIL R5 - 0x1C140805, // 000A EQ R5 R4 R5 - 0x78160001, // 000B JMPF R5 #000E - 0x4C140000, // 000C LDNIL R5 - 0x80040A00, // 000D RET 1 R5 - 0x8C140103, // 000E GETMET R5 R0 K3 - 0x5C1C0400, // 000F MOVE R7 R2 - 0x7C140400, // 0010 CALL R5 2 - 0x4C180000, // 0011 LDNIL R6 - 0x1C180A06, // 0012 EQ R6 R5 R6 - 0x781A0004, // 0013 JMPF R6 #0019 - 0xB81A0A00, // 0014 GETNGBL R6 K5 - 0x88180D06, // 0015 GETMBR R6 R6 K6 - 0x90060806, // 0016 SETMBR R1 K4 R6 - 0x4C180000, // 0017 LDNIL R6 - 0x80040C00, // 0018 RET 1 R6 - 0x8C180B07, // 0019 GETMET R6 R5 K7 - 0x5C200600, // 001A MOVE R8 R3 - 0x7C180400, // 001B CALL R6 2 - 0x741A0004, // 001C JMPT R6 #0022 - 0xB81A0A00, // 001D GETNGBL R6 K5 - 0x88180D08, // 001E GETMBR R6 R6 K8 - 0x90060806, // 001F SETMBR R1 K4 R6 - 0x4C180000, // 0020 LDNIL R6 - 0x80040C00, // 0021 RET 1 R6 - 0x8C180B09, // 0022 GETMET R6 R5 K9 - 0x5C200600, // 0023 MOVE R8 R3 - 0x5C240800, // 0024 MOVE R9 R4 - 0x7C180600, // 0025 CALL R6 3 - 0x741A0004, // 0026 JMPT R6 #002C - 0xB81A0A00, // 0027 GETNGBL R6 K5 - 0x88180D0A, // 0028 GETMBR R6 R6 K10 - 0x90060806, // 0029 SETMBR R1 K4 R6 - 0x4C180000, // 002A LDNIL R6 - 0x80040C00, // 002B RET 1 R6 - 0x80040A00, // 002C RET 1 R5 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: _trigger_read_sensors -********************************************************************/ -be_local_closure(Matter_Device__trigger_read_sensors, /* name */ - be_nested_proto( - 8, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ - /* K0 */ be_nested_str_weak(json), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(read_sensors), - /* K3 */ be_nested_str_weak(load), - /* K4 */ be_const_int(0), - /* K5 */ be_nested_str_weak(plugins), - /* K6 */ be_nested_str_weak(parse_sensors), - /* K7 */ be_const_int(1), - /* K8 */ be_nested_str_weak(log), - /* K9 */ be_nested_str_weak(MTR_X3A_X20unable_X20to_X20parse_X20read_sensors_X3A_X20), - /* K10 */ be_const_int(3), - }), - be_str_weak(_trigger_read_sensors), - &be_const_str_solidified, - ( &(const binstruction[37]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0xB80A0200, // 0001 GETNGBL R2 K1 - 0x8C080502, // 0002 GETMET R2 R2 K2 - 0x7C080200, // 0003 CALL R2 1 - 0x4C0C0000, // 0004 LDNIL R3 - 0x1C0C0403, // 0005 EQ R3 R2 R3 - 0x780E0000, // 0006 JMPF R3 #0008 - 0x80000600, // 0007 RET 0 - 0x8C0C0303, // 0008 GETMET R3 R1 K3 - 0x5C140400, // 0009 MOVE R5 R2 - 0x7C0C0400, // 000A CALL R3 2 - 0x4C100000, // 000B LDNIL R4 - 0x20100604, // 000C NE R4 R3 R4 - 0x7812000D, // 000D JMPF R4 #001C - 0x58100004, // 000E LDCONST R4 K4 - 0x6014000C, // 000F GETGBL R5 G12 - 0x88180105, // 0010 GETMBR R6 R0 K5 - 0x7C140200, // 0011 CALL R5 1 - 0x14140805, // 0012 LT R5 R4 R5 - 0x78160006, // 0013 JMPF R5 #001B - 0x88140105, // 0014 GETMBR R5 R0 K5 - 0x94140A04, // 0015 GETIDX R5 R5 R4 - 0x8C140B06, // 0016 GETMET R5 R5 K6 - 0x5C1C0600, // 0017 MOVE R7 R3 - 0x7C140400, // 0018 CALL R5 2 - 0x00100907, // 0019 ADD R4 R4 K7 - 0x7001FFF3, // 001A JMP #000F - 0x70020007, // 001B JMP #0024 - 0xB8120200, // 001C GETNGBL R4 K1 - 0x8C100908, // 001D GETMET R4 R4 K8 - 0x60180008, // 001E GETGBL R6 G8 - 0x5C1C0400, // 001F MOVE R7 R2 - 0x7C180200, // 0020 CALL R6 1 - 0x001A1206, // 0021 ADD R6 K9 R6 - 0x581C000A, // 0022 LDCONST R7 K10 - 0x7C100600, // 0023 CALL R4 3 - 0x80000000, // 0024 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: received_ack ********************************************************************/ @@ -3980,12 +794,12 @@ be_local_closure(Matter_Device_received_ack, /* name */ /******************************************************************** -** Solidified function: every_second +** Solidified function: MtrInfo_one ********************************************************************/ -be_local_closure(Matter_Device_every_second, /* name */ +be_local_closure(Matter_Device_MtrInfo_one, /* name */ be_nested_proto( - 4, /* nstack */ - 1, /* argc */ + 9, /* nstack */ + 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -3993,34 +807,36 @@ be_local_closure(Matter_Device_every_second, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(sessions), - /* K1 */ be_nested_str_weak(every_second), - /* K2 */ be_nested_str_weak(message_handler), - /* K3 */ be_nested_str_weak(commissioning_open), - /* K4 */ be_nested_str_weak(tasmota), - /* K5 */ be_nested_str_weak(time_reached), + /* K0 */ be_nested_str_weak(find_plugin_by_endpoint), + /* K1 */ be_nested_str_weak(state_json), + /* K2 */ be_nested_str_weak(_X7B_X22MtrInfo_X22_X3A_X25s_X7D), + /* K3 */ be_nested_str_weak(tasmota), + /* K4 */ be_nested_str_weak(publish_result), + /* K5 */ be_nested_str_weak(), }), - be_str_weak(every_second), + be_str_weak(MtrInfo_one), &be_const_str_solidified, - ( &(const binstruction[18]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x7C040200, // 0002 CALL R1 1 - 0x88040102, // 0003 GETMBR R1 R0 K2 - 0x8C040301, // 0004 GETMET R1 R1 K1 - 0x7C040200, // 0005 CALL R1 1 - 0x88040103, // 0006 GETMBR R1 R0 K3 - 0x4C080000, // 0007 LDNIL R2 - 0x20040202, // 0008 NE R1 R1 R2 - 0x78060006, // 0009 JMPF R1 #0011 - 0xB8060800, // 000A GETNGBL R1 K4 - 0x8C040305, // 000B GETMET R1 R1 K5 - 0x880C0103, // 000C GETMBR R3 R0 K3 - 0x7C040400, // 000D CALL R1 2 - 0x78060001, // 000E JMPF R1 #0011 - 0x4C040000, // 000F LDNIL R1 - 0x90020601, // 0010 SETMBR R0 K3 R1 - 0x80000000, // 0011 RET 0 + ( &(const binstruction[20]) { /* code */ + 0x8C080100, // 0000 GETMET R2 R0 K0 + 0x5C100200, // 0001 MOVE R4 R1 + 0x7C080400, // 0002 CALL R2 2 + 0x4C0C0000, // 0003 LDNIL R3 + 0x1C0C0403, // 0004 EQ R3 R2 R3 + 0x780E0000, // 0005 JMPF R3 #0007 + 0x80000600, // 0006 RET 0 + 0x8C0C0501, // 0007 GETMET R3 R2 K1 + 0x7C0C0200, // 0008 CALL R3 1 + 0x780E0008, // 0009 JMPF R3 #0013 + 0x60100018, // 000A GETGBL R4 G24 + 0x58140002, // 000B LDCONST R5 K2 + 0x5C180600, // 000C MOVE R6 R3 + 0x7C100400, // 000D CALL R4 2 + 0xB8160600, // 000E GETNGBL R5 K3 + 0x8C140B04, // 000F GETMET R5 R5 K4 + 0x5C1C0800, // 0010 MOVE R7 R4 + 0x58200005, // 0011 LDCONST R8 K5 + 0x7C140600, // 0012 CALL R5 3 + 0x80000000, // 0013 RET 0 }) ) ); @@ -4171,11 +987,11 @@ be_local_closure(Matter_Device_start_basic_commissioning, /* name */ /******************************************************************** -** Solidified function: compute_manual_pairing_code +** Solidified function: compute_qrcode_content ********************************************************************/ -be_local_closure(Matter_Device_compute_manual_pairing_code, /* name */ +be_local_closure(Matter_Device_compute_qrcode_content, /* name */ be_nested_proto( - 9, /* nstack */ + 8, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -4183,121 +999,63 @@ be_local_closure(Matter_Device_compute_manual_pairing_code, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(root_discriminator), - /* K1 */ be_nested_str_weak(root_passcode), - /* K2 */ be_nested_str_weak(_X251i_X2505i_X2504i), - /* K3 */ be_nested_str_weak(matter), - /* K4 */ be_nested_str_weak(Verhoeff), - /* K5 */ be_nested_str_weak(checksum), + ( &(const bvalue[12]) { /* constants */ + /* K0 */ be_nested_str_weak(resize), + /* K1 */ be_nested_str_weak(setbits), + /* K2 */ be_const_int(3), + /* K3 */ be_nested_str_weak(vendorid), + /* K4 */ be_nested_str_weak(productid), + /* K5 */ be_nested_str_weak(root_discriminator), + /* K6 */ be_nested_str_weak(root_passcode), + /* K7 */ be_const_int(134217727), + /* K8 */ be_nested_str_weak(MT_X3A), + /* K9 */ be_nested_str_weak(matter), + /* K10 */ be_nested_str_weak(Base38), + /* K11 */ be_nested_str_weak(encode), }), - be_str_weak(compute_manual_pairing_code), + be_str_weak(compute_qrcode_content), &be_const_str_solidified, - ( &(const binstruction[30]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x540A0FFE, // 0001 LDINT R2 4095 - 0x2C040202, // 0002 AND R1 R1 R2 - 0x540A0009, // 0003 LDINT R2 10 - 0x3C040202, // 0004 SHR R1 R1 R2 - 0x88080100, // 0005 GETMBR R2 R0 K0 - 0x540E02FF, // 0006 LDINT R3 768 - 0x2C080403, // 0007 AND R2 R2 R3 - 0x540E0005, // 0008 LDINT R3 6 - 0x38080403, // 0009 SHL R2 R2 R3 - 0x880C0101, // 000A GETMBR R3 R0 K1 - 0x54123FFE, // 000B LDINT R4 16383 - 0x2C0C0604, // 000C AND R3 R3 R4 - 0x30080403, // 000D OR R2 R2 R3 - 0x880C0101, // 000E GETMBR R3 R0 K1 - 0x5412000D, // 000F LDINT R4 14 - 0x3C0C0604, // 0010 SHR R3 R3 R4 - 0x60100018, // 0011 GETGBL R4 G24 - 0x58140002, // 0012 LDCONST R5 K2 - 0x5C180200, // 0013 MOVE R6 R1 - 0x5C1C0400, // 0014 MOVE R7 R2 - 0x5C200600, // 0015 MOVE R8 R3 - 0x7C100800, // 0016 CALL R4 4 - 0xB8160600, // 0017 GETNGBL R5 K3 - 0x88140B04, // 0018 GETMBR R5 R5 K4 - 0x8C140B05, // 0019 GETMET R5 R5 K5 - 0x5C1C0800, // 001A MOVE R7 R4 - 0x7C140400, // 001B CALL R5 2 - 0x00100805, // 001C ADD R4 R4 R5 - 0x80040800, // 001D RET 1 R4 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_plugin_remote_info -********************************************************************/ -be_local_closure(Matter_Device_get_plugin_remote_info, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(plugins_config_remotes), - /* K1 */ be_nested_str_weak(find), - }), - be_str_weak(get_plugin_remote_info), - &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x60140013, // 0003 GETGBL R5 G19 - 0x7C140000, // 0004 CALL R5 0 - 0x7C080600, // 0005 CALL R2 3 - 0x80040400, // 0006 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: event_fabrics_saved -********************************************************************/ -be_local_closure(Matter_Device_event_fabrics_saved, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(sessions), - /* K1 */ be_nested_str_weak(count_active_fabrics), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(plugins_persist), - /* K4 */ be_nested_str_weak(save_param), - }), - be_str_weak(event_fabrics_saved), - &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x7C040200, // 0002 CALL R1 1 - 0x24040302, // 0003 GT R1 R1 K2 - 0x78060005, // 0004 JMPF R1 #000B - 0x88040103, // 0005 GETMBR R1 R0 K3 - 0x74060003, // 0006 JMPT R1 #000B - 0x50040200, // 0007 LDBOOL R1 1 0 - 0x90020601, // 0008 SETMBR R0 K3 R1 - 0x8C040104, // 0009 GETMET R1 R0 K4 - 0x7C040200, // 000A CALL R1 1 - 0x80000000, // 000B RET 0 + ( &(const binstruction[40]) { /* code */ + 0x60040015, // 0000 GETGBL R1 G21 + 0x7C040000, // 0001 CALL R1 0 + 0x8C040300, // 0002 GETMET R1 R1 K0 + 0x540E000A, // 0003 LDINT R3 11 + 0x7C040400, // 0004 CALL R1 2 + 0x8C080301, // 0005 GETMET R2 R1 K1 + 0x58100002, // 0006 LDCONST R4 K2 + 0x5416000F, // 0007 LDINT R5 16 + 0x88180103, // 0008 GETMBR R6 R0 K3 + 0x7C080800, // 0009 CALL R2 4 + 0x8C080301, // 000A GETMET R2 R1 K1 + 0x54120012, // 000B LDINT R4 19 + 0x5416000F, // 000C LDINT R5 16 + 0x88180104, // 000D GETMBR R6 R0 K4 + 0x7C080800, // 000E CALL R2 4 + 0x8C080301, // 000F GETMET R2 R1 K1 + 0x54120024, // 0010 LDINT R4 37 + 0x54160007, // 0011 LDINT R5 8 + 0x541A0003, // 0012 LDINT R6 4 + 0x7C080800, // 0013 CALL R2 4 + 0x8C080301, // 0014 GETMET R2 R1 K1 + 0x5412002C, // 0015 LDINT R4 45 + 0x5416000B, // 0016 LDINT R5 12 + 0x88180105, // 0017 GETMBR R6 R0 K5 + 0x541E0FFE, // 0018 LDINT R7 4095 + 0x2C180C07, // 0019 AND R6 R6 R7 + 0x7C080800, // 001A CALL R2 4 + 0x8C080301, // 001B GETMET R2 R1 K1 + 0x54120038, // 001C LDINT R4 57 + 0x5416001A, // 001D LDINT R5 27 + 0x88180106, // 001E GETMBR R6 R0 K6 + 0x2C180D07, // 001F AND R6 R6 K7 + 0x7C080800, // 0020 CALL R2 4 + 0xB80A1200, // 0021 GETNGBL R2 K9 + 0x8808050A, // 0022 GETMBR R2 R2 K10 + 0x8C08050B, // 0023 GETMET R2 R2 K11 + 0x5C100200, // 0024 MOVE R4 R1 + 0x7C080400, // 0025 CALL R2 2 + 0x000A1002, // 0026 ADD R2 K8 R2 + 0x80040400, // 0027 RET 1 R2 }) ) ); @@ -4385,909 +1143,81 @@ be_local_closure(Matter_Device_autoconf_device, /* name */ /******************************************************************** -** Solidified function: start_root_basic_commissioning +** Solidified function: sort_distinct ********************************************************************/ -be_local_closure(Matter_Device_start_root_basic_commissioning, /* name */ +be_local_closure(Matter_Device_sort_distinct, /* name */ be_nested_proto( - 13, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[18]) { /* constants */ - /* K0 */ be_nested_str_weak(PASE_TIMEOUT), - /* K1 */ be_nested_str_weak(compute_manual_pairing_code), - /* K2 */ be_nested_str_weak(tasmota), - /* K3 */ be_nested_str_weak(log), - /* K4 */ be_nested_str_weak(MTR_X3A_X20Manual_X20pairing_X20code_X3A_X20_X25s), - /* K5 */ be_const_int(2), - /* K6 */ be_nested_str_weak(compute_qrcode_content), - /* K7 */ be_nested_str_weak(publish_result), - /* K8 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Commissioning_X22_X3A1_X2C_X22PairingCode_X22_X3A_X22_X25s_X22_X2C_X22QRCode_X22_X3A_X22_X25s_X22_X7D_X7D), - /* K9 */ be_nested_str_weak(Matter), - /* K10 */ be_nested_str_weak(_compute_pbkdf), - /* K11 */ be_nested_str_weak(root_passcode), - /* K12 */ be_nested_str_weak(root_iterations), - /* K13 */ be_nested_str_weak(root_salt), - /* K14 */ be_nested_str_weak(start_basic_commissioning), - /* K15 */ be_nested_str_weak(root_discriminator), - /* K16 */ be_nested_str_weak(root_w0), - /* K17 */ be_nested_str_weak(root_L), - }), - be_str_weak(start_root_basic_commissioning), - &be_const_str_solidified, - ( &(const binstruction[40]) { /* code */ - 0x4C080000, // 0000 LDNIL R2 - 0x1C080202, // 0001 EQ R2 R1 R2 - 0x780A0000, // 0002 JMPF R2 #0004 - 0x88040100, // 0003 GETMBR R1 R0 K0 - 0x8C080101, // 0004 GETMET R2 R0 K1 - 0x7C080200, // 0005 CALL R2 1 - 0xB80E0400, // 0006 GETNGBL R3 K2 - 0x8C0C0703, // 0007 GETMET R3 R3 K3 - 0x60140018, // 0008 GETGBL R5 G24 - 0x58180004, // 0009 LDCONST R6 K4 - 0x5C1C0400, // 000A MOVE R7 R2 - 0x7C140400, // 000B CALL R5 2 - 0x58180005, // 000C LDCONST R6 K5 - 0x7C0C0600, // 000D CALL R3 3 - 0x8C0C0106, // 000E GETMET R3 R0 K6 - 0x7C0C0200, // 000F CALL R3 1 - 0xB8120400, // 0010 GETNGBL R4 K2 - 0x8C100907, // 0011 GETMET R4 R4 K7 - 0x60180018, // 0012 GETGBL R6 G24 - 0x581C0008, // 0013 LDCONST R7 K8 - 0x5C200400, // 0014 MOVE R8 R2 - 0x5C240600, // 0015 MOVE R9 R3 - 0x7C180600, // 0016 CALL R6 3 - 0x581C0009, // 0017 LDCONST R7 K9 - 0x7C100600, // 0018 CALL R4 3 - 0x8C10010A, // 0019 GETMET R4 R0 K10 - 0x8818010B, // 001A GETMBR R6 R0 K11 - 0x881C010C, // 001B GETMBR R7 R0 K12 - 0x8820010D, // 001C GETMBR R8 R0 K13 - 0x7C100800, // 001D CALL R4 4 - 0x8C10010E, // 001E GETMET R4 R0 K14 - 0x5C180200, // 001F MOVE R6 R1 - 0x881C010C, // 0020 GETMBR R7 R0 K12 - 0x8820010F, // 0021 GETMBR R8 R0 K15 - 0x8824010D, // 0022 GETMBR R9 R0 K13 - 0x88280110, // 0023 GETMBR R10 R0 K16 - 0x882C0111, // 0024 GETMBR R11 R0 K17 - 0x4C300000, // 0025 LDNIL R12 - 0x7C101000, // 0026 CALL R4 8 - 0x80000000, // 0027 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: mdns_announce_op_discovery_all_fabrics -********************************************************************/ -be_local_closure(Matter_Device_mdns_announce_op_discovery_all_fabrics, /* name */ - be_nested_proto( - 6, /* nstack */ + 7, /* nstack */ 1, /* argc */ - 2, /* varg */ + 4, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(sessions), - /* K1 */ be_nested_str_weak(active_fabrics), - /* K2 */ be_nested_str_weak(get_device_id), - /* K3 */ be_nested_str_weak(get_fabric_id), - /* K4 */ be_nested_str_weak(mdns_announce_op_discovery), - /* K5 */ be_nested_str_weak(stop_iteration), + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_const_class(be_class_Matter_Device), + /* K1 */ be_const_int(1), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(stop_iteration), + /* K4 */ be_nested_str_weak(remove), }), - be_str_weak(mdns_announce_op_discovery_all_fabrics), + be_str_weak(sort_distinct), &be_const_str_solidified, - ( &(const binstruction[22]) { /* code */ - 0x60040010, // 0000 GETGBL R1 G16 - 0x88080100, // 0001 GETMBR R2 R0 K0 - 0x8C080501, // 0002 GETMET R2 R2 K1 - 0x7C080200, // 0003 CALL R2 1 - 0x7C040200, // 0004 CALL R1 1 - 0xA802000B, // 0005 EXBLK 0 #0012 - 0x5C080200, // 0006 MOVE R2 R1 - 0x7C080000, // 0007 CALL R2 0 - 0x8C0C0502, // 0008 GETMET R3 R2 K2 - 0x7C0C0200, // 0009 CALL R3 1 - 0x780E0005, // 000A JMPF R3 #0011 - 0x8C0C0503, // 000B GETMET R3 R2 K3 - 0x7C0C0200, // 000C CALL R3 1 - 0x780E0002, // 000D JMPF R3 #0011 - 0x8C0C0104, // 000E GETMET R3 R0 K4 - 0x5C140400, // 000F MOVE R5 R2 - 0x7C0C0400, // 0010 CALL R3 2 - 0x7001FFF3, // 0011 JMP #0006 - 0x58040005, // 0012 LDCONST R1 K5 - 0xAC040200, // 0013 CATCH R1 1 0 - 0xB0080000, // 0014 RAISE 2 R0 R0 - 0x80000000, // 0015 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: mdns_remove_op_discovery -********************************************************************/ -be_local_closure(Matter_Device_mdns_remove_op_discovery, /* name */ - be_nested_proto( - 12, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[23]) { /* constants */ - /* K0 */ be_nested_str_weak(mdns), - /* K1 */ be_nested_str_weak(get_device_id), - /* K2 */ be_nested_str_weak(copy), - /* K3 */ be_nested_str_weak(reverse), - /* K4 */ be_nested_str_weak(get_fabric_compressed), - /* K5 */ be_nested_str_weak(tohex), - /* K6 */ be_nested_str_weak(_X2D), - /* K7 */ be_nested_str_weak(tasmota), - /* K8 */ be_nested_str_weak(eth), - /* K9 */ be_nested_str_weak(find), - /* K10 */ be_nested_str_weak(up), - /* K11 */ be_nested_str_weak(log), - /* K12 */ be_nested_str_weak(MTR_X3A_X20remove_X20mDNS_X20on_X20_X25s_X20_X27_X25s_X27), - /* K13 */ be_const_int(3), - /* K14 */ be_nested_str_weak(remove_service), - /* K15 */ be_nested_str_weak(_matter), - /* K16 */ be_nested_str_weak(_tcp), - /* K17 */ be_nested_str_weak(hostname_eth), - /* K18 */ be_nested_str_weak(wifi), - /* K19 */ be_nested_str_weak(hostname_wifi), - /* K20 */ be_nested_str_weak(MTR_X3A_X20Exception), - /* K21 */ be_nested_str_weak(_X7C), - /* K22 */ be_const_int(2), - }), - be_str_weak(mdns_remove_op_discovery), - &be_const_str_solidified, - ( &(const binstruction[80]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0xA802003B, // 0001 EXBLK 0 #003E - 0x8C0C0301, // 0002 GETMET R3 R1 K1 - 0x7C0C0200, // 0003 CALL R3 1 - 0x8C0C0702, // 0004 GETMET R3 R3 K2 - 0x7C0C0200, // 0005 CALL R3 1 - 0x8C0C0703, // 0006 GETMET R3 R3 K3 - 0x7C0C0200, // 0007 CALL R3 1 - 0x8C100304, // 0008 GETMET R4 R1 K4 - 0x7C100200, // 0009 CALL R4 1 - 0x8C140905, // 000A GETMET R5 R4 K5 - 0x7C140200, // 000B CALL R5 1 - 0x00140B06, // 000C ADD R5 R5 K6 - 0x8C180705, // 000D GETMET R6 R3 K5 - 0x7C180200, // 000E CALL R6 1 - 0x00140A06, // 000F ADD R5 R5 R6 - 0xB81A0E00, // 0010 GETNGBL R6 K7 - 0x8C180D08, // 0011 GETMET R6 R6 K8 - 0x7C180200, // 0012 CALL R6 1 - 0x8C180D09, // 0013 GETMET R6 R6 K9 - 0x5820000A, // 0014 LDCONST R8 K10 - 0x7C180400, // 0015 CALL R6 2 - 0x781A000E, // 0016 JMPF R6 #0026 - 0xB81A0E00, // 0017 GETNGBL R6 K7 - 0x8C180D0B, // 0018 GETMET R6 R6 K11 - 0x60200018, // 0019 GETGBL R8 G24 - 0x5824000C, // 001A LDCONST R9 K12 - 0x58280008, // 001B LDCONST R10 K8 - 0x5C2C0A00, // 001C MOVE R11 R5 - 0x7C200600, // 001D CALL R8 3 - 0x5824000D, // 001E LDCONST R9 K13 - 0x7C180600, // 001F CALL R6 3 - 0x8C18050E, // 0020 GETMET R6 R2 K14 - 0x5820000F, // 0021 LDCONST R8 K15 - 0x58240010, // 0022 LDCONST R9 K16 - 0x5C280A00, // 0023 MOVE R10 R5 - 0x882C0111, // 0024 GETMBR R11 R0 K17 - 0x7C180A00, // 0025 CALL R6 5 - 0xB81A0E00, // 0026 GETNGBL R6 K7 - 0x8C180D12, // 0027 GETMET R6 R6 K18 - 0x7C180200, // 0028 CALL R6 1 - 0x8C180D09, // 0029 GETMET R6 R6 K9 - 0x5820000A, // 002A LDCONST R8 K10 - 0x7C180400, // 002B CALL R6 2 - 0x781A000E, // 002C JMPF R6 #003C - 0xB81A0E00, // 002D GETNGBL R6 K7 - 0x8C180D0B, // 002E GETMET R6 R6 K11 - 0x60200018, // 002F GETGBL R8 G24 - 0x5824000C, // 0030 LDCONST R9 K12 - 0x58280012, // 0031 LDCONST R10 K18 - 0x5C2C0A00, // 0032 MOVE R11 R5 - 0x7C200600, // 0033 CALL R8 3 - 0x5824000D, // 0034 LDCONST R9 K13 - 0x7C180600, // 0035 CALL R6 3 - 0x8C18050E, // 0036 GETMET R6 R2 K14 - 0x5820000F, // 0037 LDCONST R8 K15 - 0x58240010, // 0038 LDCONST R9 K16 - 0x5C280A00, // 0039 MOVE R10 R5 - 0x882C0113, // 003A GETMBR R11 R0 K19 - 0x7C180A00, // 003B CALL R6 5 - 0xA8040001, // 003C EXBLK 1 1 - 0x70020010, // 003D JMP #004F - 0xAC0C0002, // 003E CATCH R3 0 2 - 0x7002000D, // 003F JMP #004E - 0xB8160E00, // 0040 GETNGBL R5 K7 - 0x8C140B0B, // 0041 GETMET R5 R5 K11 - 0x601C0008, // 0042 GETGBL R7 G8 - 0x5C200600, // 0043 MOVE R8 R3 - 0x7C1C0200, // 0044 CALL R7 1 - 0x001E2807, // 0045 ADD R7 K20 R7 - 0x001C0F15, // 0046 ADD R7 R7 K21 - 0x60200008, // 0047 GETGBL R8 G8 - 0x5C240800, // 0048 MOVE R9 R4 - 0x7C200200, // 0049 CALL R8 1 - 0x001C0E08, // 004A ADD R7 R7 R8 - 0x58200016, // 004B LDCONST R8 K22 - 0x7C140600, // 004C CALL R5 3 - 0x70020000, // 004D JMP #004F - 0xB0080000, // 004E RAISE 2 R0 R0 - 0x80000000, // 004F RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: mdns_announce_PASE -********************************************************************/ -be_local_closure(Matter_Device_mdns_announce_PASE, /* name */ - be_nested_proto( - 12, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[41]) { /* constants */ - /* K0 */ be_nested_str_weak(mdns), - /* K1 */ be_nested_str_weak(crypto), - /* K2 */ be_nested_str_weak(VP), - /* K3 */ be_nested_str_weak(vendorid), - /* K4 */ be_nested_str_weak(_X2B), - /* K5 */ be_nested_str_weak(productid), - /* K6 */ be_nested_str_weak(D), - /* K7 */ be_nested_str_weak(commissioning_discriminator), - /* K8 */ be_nested_str_weak(CM), - /* K9 */ be_const_int(1), - /* K10 */ be_nested_str_weak(T), - /* K11 */ be_const_int(0), - /* K12 */ be_nested_str_weak(SII), - /* K13 */ be_nested_str_weak(SAI), - /* K14 */ be_nested_str_weak(commissioning_instance_wifi), - /* K15 */ be_nested_str_weak(random), - /* K16 */ be_nested_str_weak(tohex), - /* K17 */ be_nested_str_weak(commissioning_instance_eth), - /* K18 */ be_nested_str_weak(hostname_eth), - /* K19 */ be_nested_str_weak(add_service), - /* K20 */ be_nested_str_weak(_matterc), - /* K21 */ be_nested_str_weak(_udp), - /* K22 */ be_nested_str_weak(mdns_pase_eth), - /* K23 */ be_nested_str_weak(tasmota), - /* K24 */ be_nested_str_weak(log), - /* K25 */ be_nested_str_weak(MTR_X3A_X20announce_X20mDNS_X20on_X20_X25s_X20_X27_X25s_X27_X20ptr_X20to_X20_X60_X25s_X2Elocal_X60), - /* K26 */ be_nested_str_weak(eth), - /* K27 */ be_const_int(2), - /* K28 */ be_nested_str_weak(_L), - /* K29 */ be_nested_str_weak(MTR_X3A_X20adding_X20subtype_X3A_X20), - /* K30 */ be_const_int(3), - /* K31 */ be_nested_str_weak(add_subtype), - /* K32 */ be_nested_str_weak(_S), - /* K33 */ be_nested_str_weak(_V), - /* K34 */ be_nested_str_weak(_CM1), - /* K35 */ be_nested_str_weak(hostname_wifi), - /* K36 */ be_nested_str_weak(mdns_pase_wifi), - /* K37 */ be_nested_str_weak(MTR_X3A_X20starting_X20mDNS_X20on_X20_X25s_X20_X27_X25s_X27_X20ptr_X20to_X20_X60_X25s_X2Elocal_X60), - /* K38 */ be_nested_str_weak(wifi), - /* K39 */ be_nested_str_weak(MTR_X3A_X20Exception), - /* K40 */ be_nested_str_weak(_X7C), - }), - be_str_weak(mdns_announce_PASE), - &be_const_str_solidified, - ( &(const binstruction[236]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0xA40A0200, // 0001 IMPORT R2 K1 - 0x600C0013, // 0002 GETGBL R3 G19 - 0x7C0C0000, // 0003 CALL R3 0 - 0x60100008, // 0004 GETGBL R4 G8 - 0x88140103, // 0005 GETMBR R5 R0 K3 - 0x7C100200, // 0006 CALL R4 1 - 0x00100904, // 0007 ADD R4 R4 K4 - 0x60140008, // 0008 GETGBL R5 G8 - 0x88180105, // 0009 GETMBR R6 R0 K5 - 0x7C140200, // 000A CALL R5 1 - 0x00100805, // 000B ADD R4 R4 R5 - 0x980E0404, // 000C SETIDX R3 K2 R4 - 0x88100107, // 000D GETMBR R4 R0 K7 - 0x980E0C04, // 000E SETIDX R3 K6 R4 - 0x980E1109, // 000F SETIDX R3 K8 K9 - 0x980E150B, // 0010 SETIDX R3 K10 K11 - 0x54121387, // 0011 LDINT R4 5000 - 0x980E1804, // 0012 SETIDX R3 K12 R4 - 0x5412012B, // 0013 LDINT R4 300 - 0x980E1A04, // 0014 SETIDX R3 K13 R4 - 0x8C10050F, // 0015 GETMET R4 R2 K15 - 0x541A0007, // 0016 LDINT R6 8 - 0x7C100400, // 0017 CALL R4 2 - 0x8C100910, // 0018 GETMET R4 R4 K16 - 0x7C100200, // 0019 CALL R4 1 - 0x90021C04, // 001A SETMBR R0 K14 R4 - 0x8C10050F, // 001B GETMET R4 R2 K15 - 0x541A0007, // 001C LDINT R6 8 - 0x7C100400, // 001D CALL R4 2 - 0x8C100910, // 001E GETMET R4 R4 K16 - 0x7C100200, // 001F CALL R4 1 - 0x90022204, // 0020 SETMBR R0 K17 R4 - 0xA80200B7, // 0021 EXBLK 0 #00DA - 0x88100112, // 0022 GETMBR R4 R0 K18 - 0x78120058, // 0023 JMPF R4 #007D - 0x8C100313, // 0024 GETMET R4 R1 K19 - 0x58180014, // 0025 LDCONST R6 K20 - 0x581C0015, // 0026 LDCONST R7 K21 - 0x542215A3, // 0027 LDINT R8 5540 - 0x5C240600, // 0028 MOVE R9 R3 - 0x88280111, // 0029 GETMBR R10 R0 K17 - 0x882C0112, // 002A GETMBR R11 R0 K18 - 0x7C100E00, // 002B CALL R4 7 - 0x50100200, // 002C LDBOOL R4 1 0 - 0x90022C04, // 002D SETMBR R0 K22 R4 - 0xB8122E00, // 002E GETNGBL R4 K23 - 0x8C100918, // 002F GETMET R4 R4 K24 - 0x60180018, // 0030 GETGBL R6 G24 - 0x581C0019, // 0031 LDCONST R7 K25 - 0x5820001A, // 0032 LDCONST R8 K26 - 0x88240111, // 0033 GETMBR R9 R0 K17 - 0x88280112, // 0034 GETMBR R10 R0 K18 - 0x7C180800, // 0035 CALL R6 4 - 0x581C001B, // 0036 LDCONST R7 K27 - 0x7C100600, // 0037 CALL R4 3 - 0x60100008, // 0038 GETGBL R4 G8 - 0x88140107, // 0039 GETMBR R5 R0 K7 - 0x541A0FFE, // 003A LDINT R6 4095 - 0x2C140A06, // 003B AND R5 R5 R6 - 0x7C100200, // 003C CALL R4 1 - 0x00123804, // 003D ADD R4 K28 R4 - 0xB8162E00, // 003E GETNGBL R5 K23 - 0x8C140B18, // 003F GETMET R5 R5 K24 - 0x001E3A04, // 0040 ADD R7 K29 R4 - 0x5820001E, // 0041 LDCONST R8 K30 - 0x7C140600, // 0042 CALL R5 3 - 0x8C14031F, // 0043 GETMET R5 R1 K31 - 0x581C0014, // 0044 LDCONST R7 K20 - 0x58200015, // 0045 LDCONST R8 K21 - 0x88240111, // 0046 GETMBR R9 R0 K17 - 0x88280112, // 0047 GETMBR R10 R0 K18 - 0x5C2C0800, // 0048 MOVE R11 R4 - 0x7C140C00, // 0049 CALL R5 6 - 0x60140008, // 004A GETGBL R5 G8 - 0x88180107, // 004B GETMBR R6 R0 K7 - 0x541E0EFF, // 004C LDINT R7 3840 - 0x2C180C07, // 004D AND R6 R6 R7 - 0x541E0007, // 004E LDINT R7 8 - 0x3C180C07, // 004F SHR R6 R6 R7 - 0x7C140200, // 0050 CALL R5 1 - 0x00164005, // 0051 ADD R5 K32 R5 - 0x5C100A00, // 0052 MOVE R4 R5 - 0xB8162E00, // 0053 GETNGBL R5 K23 - 0x8C140B18, // 0054 GETMET R5 R5 K24 - 0x001E3A04, // 0055 ADD R7 K29 R4 - 0x5820001E, // 0056 LDCONST R8 K30 - 0x7C140600, // 0057 CALL R5 3 - 0x8C14031F, // 0058 GETMET R5 R1 K31 - 0x581C0014, // 0059 LDCONST R7 K20 - 0x58200015, // 005A LDCONST R8 K21 - 0x88240111, // 005B GETMBR R9 R0 K17 - 0x88280112, // 005C GETMBR R10 R0 K18 - 0x5C2C0800, // 005D MOVE R11 R4 - 0x7C140C00, // 005E CALL R5 6 - 0x60140008, // 005F GETGBL R5 G8 - 0x88180103, // 0060 GETMBR R6 R0 K3 - 0x7C140200, // 0061 CALL R5 1 - 0x00164205, // 0062 ADD R5 K33 R5 - 0x5C100A00, // 0063 MOVE R4 R5 - 0xB8162E00, // 0064 GETNGBL R5 K23 - 0x8C140B18, // 0065 GETMET R5 R5 K24 - 0x001E3A04, // 0066 ADD R7 K29 R4 - 0x5820001E, // 0067 LDCONST R8 K30 - 0x7C140600, // 0068 CALL R5 3 - 0x8C14031F, // 0069 GETMET R5 R1 K31 - 0x581C0014, // 006A LDCONST R7 K20 - 0x58200015, // 006B LDCONST R8 K21 - 0x88240111, // 006C GETMBR R9 R0 K17 - 0x88280112, // 006D GETMBR R10 R0 K18 - 0x5C2C0800, // 006E MOVE R11 R4 - 0x7C140C00, // 006F CALL R5 6 - 0x58100022, // 0070 LDCONST R4 K34 - 0xB8162E00, // 0071 GETNGBL R5 K23 - 0x8C140B18, // 0072 GETMET R5 R5 K24 - 0x001E3A04, // 0073 ADD R7 K29 R4 - 0x5820001E, // 0074 LDCONST R8 K30 - 0x7C140600, // 0075 CALL R5 3 - 0x8C14031F, // 0076 GETMET R5 R1 K31 - 0x581C0014, // 0077 LDCONST R7 K20 - 0x58200015, // 0078 LDCONST R8 K21 - 0x88240111, // 0079 GETMBR R9 R0 K17 - 0x88280112, // 007A GETMBR R10 R0 K18 - 0x5C2C0800, // 007B MOVE R11 R4 - 0x7C140C00, // 007C CALL R5 6 - 0x88100123, // 007D GETMBR R4 R0 K35 - 0x78120058, // 007E JMPF R4 #00D8 - 0x8C100313, // 007F GETMET R4 R1 K19 - 0x58180014, // 0080 LDCONST R6 K20 - 0x581C0015, // 0081 LDCONST R7 K21 - 0x542215A3, // 0082 LDINT R8 5540 - 0x5C240600, // 0083 MOVE R9 R3 - 0x8828010E, // 0084 GETMBR R10 R0 K14 - 0x882C0123, // 0085 GETMBR R11 R0 K35 - 0x7C100E00, // 0086 CALL R4 7 - 0x50100200, // 0087 LDBOOL R4 1 0 - 0x90024804, // 0088 SETMBR R0 K36 R4 - 0xB8122E00, // 0089 GETNGBL R4 K23 - 0x8C100918, // 008A GETMET R4 R4 K24 - 0x60180018, // 008B GETGBL R6 G24 - 0x581C0025, // 008C LDCONST R7 K37 - 0x58200026, // 008D LDCONST R8 K38 - 0x8824010E, // 008E GETMBR R9 R0 K14 - 0x88280123, // 008F GETMBR R10 R0 K35 - 0x7C180800, // 0090 CALL R6 4 - 0x581C001E, // 0091 LDCONST R7 K30 - 0x7C100600, // 0092 CALL R4 3 - 0x60100008, // 0093 GETGBL R4 G8 - 0x88140107, // 0094 GETMBR R5 R0 K7 - 0x541A0FFE, // 0095 LDINT R6 4095 - 0x2C140A06, // 0096 AND R5 R5 R6 - 0x7C100200, // 0097 CALL R4 1 - 0x00123804, // 0098 ADD R4 K28 R4 - 0xB8162E00, // 0099 GETNGBL R5 K23 - 0x8C140B18, // 009A GETMET R5 R5 K24 - 0x001E3A04, // 009B ADD R7 K29 R4 - 0x5820001E, // 009C LDCONST R8 K30 - 0x7C140600, // 009D CALL R5 3 - 0x8C14031F, // 009E GETMET R5 R1 K31 - 0x581C0014, // 009F LDCONST R7 K20 - 0x58200015, // 00A0 LDCONST R8 K21 - 0x8824010E, // 00A1 GETMBR R9 R0 K14 - 0x88280123, // 00A2 GETMBR R10 R0 K35 - 0x5C2C0800, // 00A3 MOVE R11 R4 - 0x7C140C00, // 00A4 CALL R5 6 - 0x60140008, // 00A5 GETGBL R5 G8 - 0x88180107, // 00A6 GETMBR R6 R0 K7 - 0x541E0EFF, // 00A7 LDINT R7 3840 - 0x2C180C07, // 00A8 AND R6 R6 R7 - 0x541E0007, // 00A9 LDINT R7 8 - 0x3C180C07, // 00AA SHR R6 R6 R7 - 0x7C140200, // 00AB CALL R5 1 - 0x00164005, // 00AC ADD R5 K32 R5 - 0x5C100A00, // 00AD MOVE R4 R5 - 0xB8162E00, // 00AE GETNGBL R5 K23 - 0x8C140B18, // 00AF GETMET R5 R5 K24 - 0x001E3A04, // 00B0 ADD R7 K29 R4 - 0x5820001E, // 00B1 LDCONST R8 K30 - 0x7C140600, // 00B2 CALL R5 3 - 0x8C14031F, // 00B3 GETMET R5 R1 K31 - 0x581C0014, // 00B4 LDCONST R7 K20 - 0x58200015, // 00B5 LDCONST R8 K21 - 0x8824010E, // 00B6 GETMBR R9 R0 K14 - 0x88280123, // 00B7 GETMBR R10 R0 K35 - 0x5C2C0800, // 00B8 MOVE R11 R4 - 0x7C140C00, // 00B9 CALL R5 6 - 0x60140008, // 00BA GETGBL R5 G8 - 0x88180103, // 00BB GETMBR R6 R0 K3 - 0x7C140200, // 00BC CALL R5 1 - 0x00164205, // 00BD ADD R5 K33 R5 - 0x5C100A00, // 00BE MOVE R4 R5 - 0xB8162E00, // 00BF GETNGBL R5 K23 - 0x8C140B18, // 00C0 GETMET R5 R5 K24 - 0x001E3A04, // 00C1 ADD R7 K29 R4 - 0x5820001E, // 00C2 LDCONST R8 K30 - 0x7C140600, // 00C3 CALL R5 3 - 0x8C14031F, // 00C4 GETMET R5 R1 K31 - 0x581C0014, // 00C5 LDCONST R7 K20 - 0x58200015, // 00C6 LDCONST R8 K21 - 0x8824010E, // 00C7 GETMBR R9 R0 K14 - 0x88280123, // 00C8 GETMBR R10 R0 K35 - 0x5C2C0800, // 00C9 MOVE R11 R4 - 0x7C140C00, // 00CA CALL R5 6 - 0x58100022, // 00CB LDCONST R4 K34 - 0xB8162E00, // 00CC GETNGBL R5 K23 - 0x8C140B18, // 00CD GETMET R5 R5 K24 - 0x001E3A04, // 00CE ADD R7 K29 R4 - 0x5820001E, // 00CF LDCONST R8 K30 - 0x7C140600, // 00D0 CALL R5 3 - 0x8C14031F, // 00D1 GETMET R5 R1 K31 - 0x581C0014, // 00D2 LDCONST R7 K20 - 0x58200015, // 00D3 LDCONST R8 K21 - 0x8824010E, // 00D4 GETMBR R9 R0 K14 - 0x88280123, // 00D5 GETMBR R10 R0 K35 - 0x5C2C0800, // 00D6 MOVE R11 R4 - 0x7C140C00, // 00D7 CALL R5 6 - 0xA8040001, // 00D8 EXBLK 1 1 - 0x70020010, // 00D9 JMP #00EB - 0xAC100002, // 00DA CATCH R4 0 2 - 0x7002000D, // 00DB JMP #00EA - 0xB81A2E00, // 00DC GETNGBL R6 K23 - 0x8C180D18, // 00DD GETMET R6 R6 K24 - 0x60200008, // 00DE GETGBL R8 G8 - 0x5C240800, // 00DF MOVE R9 R4 - 0x7C200200, // 00E0 CALL R8 1 - 0x00224E08, // 00E1 ADD R8 K39 R8 - 0x00201128, // 00E2 ADD R8 R8 K40 - 0x60240008, // 00E3 GETGBL R9 G8 - 0x5C280A00, // 00E4 MOVE R10 R5 - 0x7C240200, // 00E5 CALL R9 1 - 0x00201009, // 00E6 ADD R8 R8 R9 - 0x5824001B, // 00E7 LDCONST R9 K27 - 0x7C180600, // 00E8 CALL R6 3 - 0x70020000, // 00E9 JMP #00EB - 0xB0080000, // 00EA RAISE 2 R0 R0 - 0x80000000, // 00EB RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: start_commissioning_complete -********************************************************************/ -be_local_closure(Matter_Device_start_commissioning_complete, /* name */ - be_nested_proto( - 11, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ - /* K0 */ be_nested_str_weak(get_fabric), - /* K1 */ be_nested_str_weak(get_fabric_id), - /* K2 */ be_nested_str_weak(copy), - /* K3 */ be_nested_str_weak(reverse), - /* K4 */ be_nested_str_weak(tohex), - /* K5 */ be_nested_str_weak(get_admin_vendor_name), - /* K6 */ be_nested_str_weak(tasmota), - /* K7 */ be_nested_str_weak(log), - /* K8 */ be_nested_str_weak(MTR_X3A_X20_X2D_X2D_X2D_X20Commissioning_X20complete_X20for_X20Fabric_X20_X27_X25s_X27_X20_X28Vendor_X20_X25s_X29_X20_X2D_X2D_X2D), - /* K9 */ be_const_int(2), - /* K10 */ be_nested_str_weak(stop_basic_commissioning), - }), - be_str_weak(start_commissioning_complete), - &be_const_str_solidified, - ( &(const binstruction[24]) { /* code */ - 0x8C080300, // 0000 GETMET R2 R1 K0 - 0x7C080200, // 0001 CALL R2 1 - 0x8C0C0501, // 0002 GETMET R3 R2 K1 - 0x7C0C0200, // 0003 CALL R3 1 - 0x8C0C0702, // 0004 GETMET R3 R3 K2 - 0x7C0C0200, // 0005 CALL R3 1 - 0x8C0C0703, // 0006 GETMET R3 R3 K3 - 0x7C0C0200, // 0007 CALL R3 1 - 0x8C0C0704, // 0008 GETMET R3 R3 K4 - 0x7C0C0200, // 0009 CALL R3 1 - 0x8C100505, // 000A GETMET R4 R2 K5 - 0x7C100200, // 000B CALL R4 1 - 0xB8160C00, // 000C GETNGBL R5 K6 - 0x8C140B07, // 000D GETMET R5 R5 K7 - 0x601C0018, // 000E GETGBL R7 G24 - 0x58200008, // 000F LDCONST R8 K8 - 0x5C240600, // 0010 MOVE R9 R3 - 0x5C280800, // 0011 MOVE R10 R4 - 0x7C1C0600, // 0012 CALL R7 3 - 0x58200009, // 0013 LDCONST R8 K9 - 0x7C140600, // 0014 CALL R5 3 - 0x8C14010A, // 0015 GETMET R5 R0 K10 - 0x7C140200, // 0016 CALL R5 1 - 0x80000000, // 0017 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: MtrInfo -********************************************************************/ -be_local_closure(Matter_Device_MtrInfo, /* name */ - be_nested_proto( - 10, /* nstack */ - 5, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(), - /* K1 */ be_nested_str_weak(plugins), - /* K2 */ be_nested_str_weak(MtrInfo_one), - /* K3 */ be_nested_str_weak(endpoint), - /* K4 */ be_nested_str_weak(stop_iteration), - /* K5 */ be_nested_str_weak(int), - /* K6 */ be_nested_str_weak(find_plugin_by_friendly_name), - /* K7 */ be_nested_str_weak(tasmota), - /* K8 */ be_nested_str_weak(resp_cmnd_done), - }), - be_str_weak(MtrInfo), - &be_const_str_solidified, - ( &(const binstruction[40]) { /* code */ - 0x1C140700, // 0000 EQ R5 R3 K0 - 0x7815FFFF, // 0001 JMPF R5 #0002 - 0x1C140700, // 0002 EQ R5 R3 K0 - 0x7816000D, // 0003 JMPF R5 #0012 - 0x60140010, // 0004 GETGBL R5 G16 - 0x88180101, // 0005 GETMBR R6 R0 K1 - 0x7C140200, // 0006 CALL R5 1 - 0xA8020005, // 0007 EXBLK 0 #000E - 0x5C180A00, // 0008 MOVE R6 R5 - 0x7C180000, // 0009 CALL R6 0 - 0x8C1C0102, // 000A GETMET R7 R0 K2 - 0x88240D03, // 000B GETMBR R9 R6 K3 - 0x7C1C0400, // 000C CALL R7 2 - 0x7001FFF9, // 000D JMP #0008 - 0x58140004, // 000E LDCONST R5 K4 - 0xAC140200, // 000F CATCH R5 1 0 - 0xB0080000, // 0010 RAISE 2 R0 R0 - 0x70020011, // 0011 JMP #0024 - 0x60140004, // 0012 GETGBL R5 G4 - 0x5C180800, // 0013 MOVE R6 R4 - 0x7C140200, // 0014 CALL R5 1 - 0x1C140B05, // 0015 EQ R5 R5 K5 - 0x78160003, // 0016 JMPF R5 #001B - 0x8C140102, // 0017 GETMET R5 R0 K2 - 0x5C1C0800, // 0018 MOVE R7 R4 - 0x7C140400, // 0019 CALL R5 2 - 0x70020008, // 001A JMP #0024 - 0x8C140106, // 001B GETMET R5 R0 K6 - 0x5C1C0600, // 001C MOVE R7 R3 - 0x7C140400, // 001D CALL R5 2 - 0x4C180000, // 001E LDNIL R6 - 0x20180A06, // 001F NE R6 R5 R6 - 0x781A0002, // 0020 JMPF R6 #0024 - 0x8C180102, // 0021 GETMET R6 R0 K2 - 0x88200B03, // 0022 GETMBR R8 R5 K3 - 0x7C180400, // 0023 CALL R6 2 - 0xB8160E00, // 0024 GETNGBL R5 K7 - 0x8C140B08, // 0025 GETMET R5 R5 K8 - 0x7C140200, // 0026 CALL R5 1 - 0x80000000, // 0027 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: MtrUpdate -********************************************************************/ -be_local_closure(Matter_Device_MtrUpdate, /* name */ - be_nested_proto( - 18, /* nstack */ - 5, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[25]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(resp_cmnd_str), - /* K2 */ be_nested_str_weak(Invalid_X20JSON), - /* K3 */ be_nested_str_weak(find_key_i), - /* K4 */ be_nested_str_weak(Ep), - /* K5 */ be_nested_str_weak(Name), - /* K6 */ be_const_int(0), - /* K7 */ be_nested_str_weak(Invalid_X20_X27Ep_X27_X20attribute), - /* K8 */ be_nested_str_weak(find_plugin_by_endpoint), - /* K9 */ be_nested_str_weak(remove), - /* K10 */ be_nested_str_weak(find_plugin_by_friendly_name), - /* K11 */ be_nested_str_weak(Invalid_X20Device), - /* K12 */ be_nested_str_weak(VIRTUAL), - /* K13 */ be_nested_str_weak(Device_X20is_X20not_X20virtual), - /* K14 */ be_nested_str_weak(consolidate_update_commands), - /* K15 */ be_nested_str_weak(keys), - /* K16 */ be_nested_str_weak(find_list_i), - /* K17 */ be_nested_str_weak(Invalid_X20attribute_X20_X27_X25s_X27), - /* K18 */ be_nested_str_weak(stop_iteration), - /* K19 */ be_nested_str_weak(update_virtual), - /* K20 */ be_nested_str_weak(state_json), - /* K21 */ be_nested_str_weak(_X7B_X22_X25s_X22_X3A_X25s_X7D), - /* K22 */ be_nested_str_weak(resp_cmnd), - /* K23 */ be_nested_str_weak(resp_cmnd_done), - /* K24 */ be_nested_str_weak(Missing_X20_X27Device_X27_X20attribute), - }), - be_str_weak(MtrUpdate), - &be_const_str_solidified, - ( &(const binstruction[126]) { /* code */ - 0x4C140000, // 0000 LDNIL R5 - 0x1C140805, // 0001 EQ R5 R4 R5 - 0x78160004, // 0002 JMPF R5 #0008 - 0xB8160000, // 0003 GETNGBL R5 K0 - 0x8C140B01, // 0004 GETMET R5 R5 K1 - 0x581C0002, // 0005 LDCONST R7 K2 - 0x7C140400, // 0006 CALL R5 2 - 0x80040A00, // 0007 RET 1 R5 - 0xB8160000, // 0008 GETNGBL R5 K0 - 0x8C140B03, // 0009 GETMET R5 R5 K3 - 0x5C1C0800, // 000A MOVE R7 R4 - 0x58200004, // 000B LDCONST R8 K4 - 0x7C140600, // 000C CALL R5 3 - 0xB81A0000, // 000D GETNGBL R6 K0 - 0x8C180D03, // 000E GETMET R6 R6 K3 - 0x5C200800, // 000F MOVE R8 R4 - 0x58240005, // 0010 LDCONST R9 K5 - 0x7C180600, // 0011 CALL R6 3 - 0x74160000, // 0012 JMPT R5 #0014 - 0x781A0064, // 0013 JMPF R6 #0079 - 0x4C1C0000, // 0014 LDNIL R7 - 0x78160010, // 0015 JMPF R5 #0027 - 0x60200009, // 0016 GETGBL R8 G9 - 0x94240805, // 0017 GETIDX R9 R4 R5 - 0x7C200200, // 0018 CALL R8 1 - 0x18241106, // 0019 LE R9 R8 K6 - 0x78260004, // 001A JMPF R9 #0020 - 0xB8260000, // 001B GETNGBL R9 K0 - 0x8C241301, // 001C GETMET R9 R9 K1 - 0x582C0007, // 001D LDCONST R11 K7 - 0x7C240400, // 001E CALL R9 2 - 0x80041200, // 001F RET 1 R9 - 0x8C240108, // 0020 GETMET R9 R0 K8 - 0x5C2C1000, // 0021 MOVE R11 R8 - 0x7C240400, // 0022 CALL R9 2 - 0x5C1C1200, // 0023 MOVE R7 R9 - 0x8C240909, // 0024 GETMET R9 R4 K9 - 0x5C2C0A00, // 0025 MOVE R11 R5 - 0x7C240400, // 0026 CALL R9 2 - 0x781A0009, // 0027 JMPF R6 #0032 - 0x4C200000, // 0028 LDNIL R8 - 0x1C200E08, // 0029 EQ R8 R7 R8 - 0x78220003, // 002A JMPF R8 #002F - 0x8C20010A, // 002B GETMET R8 R0 K10 - 0x94280806, // 002C GETIDX R10 R4 R6 - 0x7C200400, // 002D CALL R8 2 - 0x5C1C1000, // 002E MOVE R7 R8 - 0x8C200909, // 002F GETMET R8 R4 K9 - 0x5C280C00, // 0030 MOVE R10 R6 - 0x7C200400, // 0031 CALL R8 2 - 0x4C200000, // 0032 LDNIL R8 - 0x1C200E08, // 0033 EQ R8 R7 R8 - 0x78220004, // 0034 JMPF R8 #003A - 0xB8220000, // 0035 GETNGBL R8 K0 - 0x8C201101, // 0036 GETMET R8 R8 K1 - 0x5828000B, // 0037 LDCONST R10 K11 - 0x7C200400, // 0038 CALL R8 2 - 0x80041000, // 0039 RET 1 R8 - 0x88200F0C, // 003A GETMBR R8 R7 K12 - 0x74220004, // 003B JMPT R8 #0041 - 0xB8220000, // 003C GETNGBL R8 K0 - 0x8C201101, // 003D GETMET R8 R8 K1 - 0x5828000D, // 003E LDCONST R10 K13 - 0x7C200400, // 003F CALL R8 2 - 0x80041000, // 0040 RET 1 R8 - 0x8C200F0E, // 0041 GETMET R8 R7 K14 - 0x7C200200, // 0042 CALL R8 1 - 0x60240013, // 0043 GETGBL R9 G19 - 0x7C240000, // 0044 CALL R9 0 - 0x60280010, // 0045 GETGBL R10 G16 - 0x8C2C090F, // 0046 GETMET R11 R4 K15 - 0x7C2C0200, // 0047 CALL R11 1 - 0x7C280200, // 0048 CALL R10 1 - 0xA8020016, // 0049 EXBLK 0 #0061 - 0x5C2C1400, // 004A MOVE R11 R10 - 0x7C2C0000, // 004B CALL R11 0 - 0xB8320000, // 004C GETNGBL R12 K0 - 0x8C301910, // 004D GETMET R12 R12 K16 - 0x5C381000, // 004E MOVE R14 R8 - 0x5C3C1600, // 004F MOVE R15 R11 - 0x7C300600, // 0050 CALL R12 3 - 0x4C340000, // 0051 LDNIL R13 - 0x1C34180D, // 0052 EQ R13 R12 R13 - 0x78360008, // 0053 JMPF R13 #005D - 0xB8360000, // 0054 GETNGBL R13 K0 - 0x8C341B01, // 0055 GETMET R13 R13 K1 - 0x603C0018, // 0056 GETGBL R15 G24 - 0x58400011, // 0057 LDCONST R16 K17 - 0x5C441600, // 0058 MOVE R17 R11 - 0x7C3C0400, // 0059 CALL R15 2 - 0x7C340400, // 005A CALL R13 2 - 0xA8040001, // 005B EXBLK 1 1 - 0x80001A00, // 005C RET 0 - 0x9434100C, // 005D GETIDX R13 R8 R12 - 0x9438080B, // 005E GETIDX R14 R4 R11 - 0x98241A0E, // 005F SETIDX R9 R13 R14 - 0x7001FFE8, // 0060 JMP #004A - 0x58280012, // 0061 LDCONST R10 K18 - 0xAC280200, // 0062 CATCH R10 1 0 - 0xB0080000, // 0063 RAISE 2 R0 R0 - 0x8C280F13, // 0064 GETMET R10 R7 K19 - 0x5C301200, // 0065 MOVE R12 R9 - 0x7C280400, // 0066 CALL R10 2 - 0x8C280F14, // 0067 GETMET R10 R7 K20 - 0x7C280200, // 0068 CALL R10 1 - 0x782A000A, // 0069 JMPF R10 #0075 - 0x602C0018, // 006A GETGBL R11 G24 - 0x58300015, // 006B LDCONST R12 K21 - 0x5C340200, // 006C MOVE R13 R1 - 0x5C381400, // 006D MOVE R14 R10 - 0x7C2C0600, // 006E CALL R11 3 - 0xB8320000, // 006F GETNGBL R12 K0 - 0x8C301916, // 0070 GETMET R12 R12 K22 - 0x5C381600, // 0071 MOVE R14 R11 - 0x7C300400, // 0072 CALL R12 2 - 0x80041800, // 0073 RET 1 R12 - 0x70020003, // 0074 JMP #0079 - 0xB82E0000, // 0075 GETNGBL R11 K0 - 0x8C2C1717, // 0076 GETMET R11 R11 K23 - 0x7C2C0200, // 0077 CALL R11 1 - 0x80041600, // 0078 RET 1 R11 - 0xB81E0000, // 0079 GETNGBL R7 K0 - 0x8C1C0F01, // 007A GETMET R7 R7 K1 - 0x58240018, // 007B LDCONST R9 K24 - 0x7C1C0400, // 007C CALL R7 2 - 0x80000000, // 007D RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: MtrJoin -********************************************************************/ -be_local_closure(Matter_Device_MtrJoin, /* name */ - be_nested_proto( - 8, /* nstack */ - 5, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(start_root_basic_commissioning), - /* K1 */ be_nested_str_weak(stop_basic_commissioning), - /* K2 */ be_nested_str_weak(tasmota), - /* K3 */ be_nested_str_weak(resp_cmnd_done), - }), - be_str_weak(MtrJoin), - &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x60140009, // 0000 GETGBL R5 G9 - 0x5C180600, // 0001 MOVE R6 R3 - 0x7C140200, // 0002 CALL R5 1 - 0x78160002, // 0003 JMPF R5 #0007 - 0x8C180100, // 0004 GETMET R6 R0 K0 - 0x7C180200, // 0005 CALL R6 1 - 0x70020001, // 0006 JMP #0009 - 0x8C180101, // 0007 GETMET R6 R0 K1 - 0x7C180200, // 0008 CALL R6 1 - 0xB81A0400, // 0009 GETNGBL R6 K2 - 0x8C180D03, // 000A GETMET R6 R6 K3 - 0x7C180200, // 000B CALL R6 1 - 0x80000000, // 000C RET 0 + ( &(const binstruction[53]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x60080010, // 0001 GETGBL R2 G16 + 0x600C000C, // 0002 GETGBL R3 G12 + 0x5C100000, // 0003 MOVE R4 R0 + 0x7C0C0200, // 0004 CALL R3 1 + 0x040C0701, // 0005 SUB R3 R3 K1 + 0x400E0203, // 0006 CONNECT R3 K1 R3 + 0x7C080200, // 0007 CALL R2 1 + 0xA8020010, // 0008 EXBLK 0 #001A + 0x5C0C0400, // 0009 MOVE R3 R2 + 0x7C0C0000, // 000A CALL R3 0 + 0x94100003, // 000B GETIDX R4 R0 R3 + 0x5C140600, // 000C MOVE R5 R3 + 0x24180B02, // 000D GT R6 R5 K2 + 0x781A0008, // 000E JMPF R6 #0018 + 0x04180B01, // 000F SUB R6 R5 K1 + 0x94180006, // 0010 GETIDX R6 R0 R6 + 0x24180C04, // 0011 GT R6 R6 R4 + 0x781A0004, // 0012 JMPF R6 #0018 + 0x04180B01, // 0013 SUB R6 R5 K1 + 0x94180006, // 0014 GETIDX R6 R0 R6 + 0x98000A06, // 0015 SETIDX R0 R5 R6 + 0x04140B01, // 0016 SUB R5 R5 K1 + 0x7001FFF4, // 0017 JMP #000D + 0x98000A04, // 0018 SETIDX R0 R5 R4 + 0x7001FFEE, // 0019 JMP #0009 + 0x58080003, // 001A LDCONST R2 K3 + 0xAC080200, // 001B CATCH R2 1 0 + 0xB0080000, // 001C RAISE 2 R0 R0 + 0x58080001, // 001D LDCONST R2 K1 + 0x600C000C, // 001E GETGBL R3 G12 + 0x5C100000, // 001F MOVE R4 R0 + 0x7C0C0200, // 0020 CALL R3 1 + 0x180C0701, // 0021 LE R3 R3 K1 + 0x780E0000, // 0022 JMPF R3 #0024 + 0x80040000, // 0023 RET 1 R0 + 0x940C0102, // 0024 GETIDX R3 R0 K2 + 0x6010000C, // 0025 GETGBL R4 G12 + 0x5C140000, // 0026 MOVE R5 R0 + 0x7C100200, // 0027 CALL R4 1 + 0x14100404, // 0028 LT R4 R2 R4 + 0x78120009, // 0029 JMPF R4 #0034 + 0x94100002, // 002A GETIDX R4 R0 R2 + 0x1C100803, // 002B EQ R4 R4 R3 + 0x78120003, // 002C JMPF R4 #0031 + 0x8C100104, // 002D GETMET R4 R0 K4 + 0x5C180400, // 002E MOVE R6 R2 + 0x7C100400, // 002F CALL R4 2 + 0x70020001, // 0030 JMP #0033 + 0x940C0002, // 0031 GETIDX R3 R0 R2 + 0x00080501, // 0032 ADD R2 R2 K1 + 0x7001FFF0, // 0033 JMP #0025 + 0x80040000, // 0034 RET 1 R0 }) ) ); @@ -5605,11 +1535,11 @@ be_local_closure(Matter_Device_process_attribute_expansion, /* name */ /******************************************************************** -** Solidified function: find_plugin_by_friendly_name +** Solidified function: add_read_sensors_schedule ********************************************************************/ -be_local_closure(Matter_Device_find_plugin_by_friendly_name, /* name */ +be_local_closure(Matter_Device_add_read_sensors_schedule, /* name */ be_nested_proto( - 7, /* nstack */ + 5, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -5618,49 +1548,365 @@ be_local_closure(Matter_Device_find_plugin_by_friendly_name, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str_weak(plugins), - /* K2 */ be_nested_str_weak(get_name), - /* K3 */ be_const_int(1), + /* K0 */ be_nested_str_weak(probe_sensor_time), + /* K1 */ be_nested_str_weak(probe_sensor_timestamp), + /* K2 */ be_nested_str_weak(matter), + /* K3 */ be_nested_str_weak(jitter), }), - be_str_weak(find_plugin_by_friendly_name), + be_str_weak(add_read_sensors_schedule), &be_const_str_solidified, - ( &(const binstruction[35]) { /* code */ - 0x4C080000, // 0000 LDNIL R2 - 0x1C080202, // 0001 EQ R2 R1 R2 - 0x740A0004, // 0002 JMPT R2 #0008 - 0x6008000C, // 0003 GETGBL R2 G12 - 0x5C0C0200, // 0004 MOVE R3 R1 - 0x7C080200, // 0005 CALL R2 1 - 0x1C080500, // 0006 EQ R2 R2 K0 - 0x780A0001, // 0007 JMPF R2 #000A - 0x4C080000, // 0008 LDNIL R2 - 0x80040400, // 0009 RET 1 R2 - 0x58080000, // 000A LDCONST R2 K0 - 0x600C000C, // 000B GETGBL R3 G12 - 0x88100101, // 000C GETMBR R4 R0 K1 - 0x7C0C0200, // 000D CALL R3 1 - 0x140C0403, // 000E LT R3 R2 R3 - 0x780E0010, // 000F JMPF R3 #0021 - 0x880C0101, // 0010 GETMBR R3 R0 K1 - 0x940C0602, // 0011 GETIDX R3 R3 R2 - 0x8C100702, // 0012 GETMET R4 R3 K2 - 0x7C100200, // 0013 CALL R4 1 - 0x4C140000, // 0014 LDNIL R5 - 0x20140805, // 0015 NE R5 R4 R5 - 0x78160007, // 0016 JMPF R5 #001F - 0x6014000C, // 0017 GETGBL R5 G12 - 0x5C180800, // 0018 MOVE R6 R4 - 0x7C140200, // 0019 CALL R5 1 - 0x24140B00, // 001A GT R5 R5 K0 - 0x78160002, // 001B JMPF R5 #001F - 0x1C140801, // 001C EQ R5 R4 R1 - 0x78160000, // 001D JMPF R5 #001F - 0x80040600, // 001E RET 1 R3 - 0x00080503, // 001F ADD R2 R2 K3 - 0x7001FFE9, // 0020 JMP #000B - 0x4C0C0000, // 0021 LDNIL R3 - 0x80040600, // 0022 RET 1 R3 + ( &(const binstruction[14]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x1C080403, // 0002 EQ R2 R2 R3 + 0x740A0002, // 0003 JMPT R2 #0007 + 0x88080100, // 0004 GETMBR R2 R0 K0 + 0x24080401, // 0005 GT R2 R2 R1 + 0x780A0005, // 0006 JMPF R2 #000D + 0x90020001, // 0007 SETMBR R0 K0 R1 + 0xB80A0400, // 0008 GETNGBL R2 K2 + 0x8C080503, // 0009 GETMET R2 R2 K3 + 0x5C100200, // 000A MOVE R4 R1 + 0x7C080400, // 000B CALL R2 2 + 0x90020202, // 000C SETMBR R0 K1 R2 + 0x80000000, // 000D RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: attribute_updated +********************************************************************/ +be_local_closure(Matter_Device_attribute_updated, /* name */ + be_nested_proto( + 10, /* nstack */ + 5, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(matter), + /* K1 */ be_nested_str_weak(Path), + /* K2 */ be_nested_str_weak(endpoint), + /* K3 */ be_nested_str_weak(cluster), + /* K4 */ be_nested_str_weak(attribute), + /* K5 */ be_nested_str_weak(message_handler), + /* K6 */ be_nested_str_weak(im), + /* K7 */ be_nested_str_weak(subs_shop), + /* K8 */ be_nested_str_weak(attribute_updated_ctx), + }), + be_str_weak(attribute_updated), + &be_const_str_solidified, + ( &(const binstruction[18]) { /* code */ + 0x4C140000, // 0000 LDNIL R5 + 0x1C140805, // 0001 EQ R5 R4 R5 + 0x78160000, // 0002 JMPF R5 #0004 + 0x50100000, // 0003 LDBOOL R4 0 0 + 0xB8160000, // 0004 GETNGBL R5 K0 + 0x8C140B01, // 0005 GETMET R5 R5 K1 + 0x7C140200, // 0006 CALL R5 1 + 0x90160401, // 0007 SETMBR R5 K2 R1 + 0x90160602, // 0008 SETMBR R5 K3 R2 + 0x90160803, // 0009 SETMBR R5 K4 R3 + 0x88180105, // 000A GETMBR R6 R0 K5 + 0x88180D06, // 000B GETMBR R6 R6 K6 + 0x88180D07, // 000C GETMBR R6 R6 K7 + 0x8C180D08, // 000D GETMET R6 R6 K8 + 0x5C200A00, // 000E MOVE R8 R5 + 0x5C240800, // 000F MOVE R9 R4 + 0x7C180600, // 0010 CALL R6 3 + 0x80000000, // 0011 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: _trigger_read_sensors +********************************************************************/ +be_local_closure(Matter_Device__trigger_read_sensors, /* name */ + be_nested_proto( + 8, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[13]) { /* constants */ + /* K0 */ be_nested_str_weak(json), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(read_sensors), + /* K3 */ be_nested_str_weak(loglevel), + /* K4 */ be_const_int(3), + /* K5 */ be_nested_str_weak(log), + /* K6 */ be_nested_str_weak(MTR_X3A_X20read_sensors_X3A_X20), + /* K7 */ be_nested_str_weak(load), + /* K8 */ be_const_int(0), + /* K9 */ be_nested_str_weak(plugins), + /* K10 */ be_nested_str_weak(parse_sensors), + /* K11 */ be_const_int(1), + /* K12 */ be_nested_str_weak(MTR_X3A_X20unable_X20to_X20parse_X20read_sensors_X3A_X20), + }), + be_str_weak(_trigger_read_sensors), + &be_const_str_solidified, + ( &(const binstruction[50]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xB80A0200, // 0001 GETNGBL R2 K1 + 0x8C080502, // 0002 GETMET R2 R2 K2 + 0x7C080200, // 0003 CALL R2 1 + 0xB80E0200, // 0004 GETNGBL R3 K1 + 0x8C0C0703, // 0005 GETMET R3 R3 K3 + 0x58140004, // 0006 LDCONST R5 K4 + 0x7C0C0400, // 0007 CALL R3 2 + 0x780E0007, // 0008 JMPF R3 #0011 + 0xB80E0200, // 0009 GETNGBL R3 K1 + 0x8C0C0705, // 000A GETMET R3 R3 K5 + 0x60140008, // 000B GETGBL R5 G8 + 0x5C180400, // 000C MOVE R6 R2 + 0x7C140200, // 000D CALL R5 1 + 0x00160C05, // 000E ADD R5 K6 R5 + 0x58180004, // 000F LDCONST R6 K4 + 0x7C0C0600, // 0010 CALL R3 3 + 0x4C0C0000, // 0011 LDNIL R3 + 0x1C0C0403, // 0012 EQ R3 R2 R3 + 0x780E0000, // 0013 JMPF R3 #0015 + 0x80000600, // 0014 RET 0 + 0x8C0C0307, // 0015 GETMET R3 R1 K7 + 0x5C140400, // 0016 MOVE R5 R2 + 0x7C0C0400, // 0017 CALL R3 2 + 0x4C100000, // 0018 LDNIL R4 + 0x20100604, // 0019 NE R4 R3 R4 + 0x7812000D, // 001A JMPF R4 #0029 + 0x58100008, // 001B LDCONST R4 K8 + 0x6014000C, // 001C GETGBL R5 G12 + 0x88180109, // 001D GETMBR R6 R0 K9 + 0x7C140200, // 001E CALL R5 1 + 0x14140805, // 001F LT R5 R4 R5 + 0x78160006, // 0020 JMPF R5 #0028 + 0x88140109, // 0021 GETMBR R5 R0 K9 + 0x94140A04, // 0022 GETIDX R5 R5 R4 + 0x8C140B0A, // 0023 GETMET R5 R5 K10 + 0x5C1C0600, // 0024 MOVE R7 R3 + 0x7C140400, // 0025 CALL R5 2 + 0x0010090B, // 0026 ADD R4 R4 K11 + 0x7001FFF3, // 0027 JMP #001C + 0x70020007, // 0028 JMP #0031 + 0xB8120200, // 0029 GETNGBL R4 K1 + 0x8C100905, // 002A GETMET R4 R4 K5 + 0x60180008, // 002B GETGBL R6 G8 + 0x5C1C0400, // 002C MOVE R7 R2 + 0x7C180200, // 002D CALL R6 1 + 0x001A1806, // 002E ADD R6 K12 R6 + 0x581C0004, // 002F LDCONST R7 K4 + 0x7C100600, // 0030 CALL R4 3 + 0x80000000, // 0031 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start_commissioning_complete +********************************************************************/ +be_local_closure(Matter_Device_start_commissioning_complete, /* name */ + be_nested_proto( + 11, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_str_weak(get_fabric), + /* K1 */ be_nested_str_weak(get_fabric_id), + /* K2 */ be_nested_str_weak(copy), + /* K3 */ be_nested_str_weak(reverse), + /* K4 */ be_nested_str_weak(tohex), + /* K5 */ be_nested_str_weak(get_admin_vendor_name), + /* K6 */ be_nested_str_weak(tasmota), + /* K7 */ be_nested_str_weak(log), + /* K8 */ be_nested_str_weak(MTR_X3A_X20_X2D_X2D_X2D_X20Commissioning_X20complete_X20for_X20Fabric_X20_X27_X25s_X27_X20_X28Vendor_X20_X25s_X29_X20_X2D_X2D_X2D), + /* K9 */ be_const_int(2), + /* K10 */ be_nested_str_weak(stop_basic_commissioning), + }), + be_str_weak(start_commissioning_complete), + &be_const_str_solidified, + ( &(const binstruction[24]) { /* code */ + 0x8C080300, // 0000 GETMET R2 R1 K0 + 0x7C080200, // 0001 CALL R2 1 + 0x8C0C0501, // 0002 GETMET R3 R2 K1 + 0x7C0C0200, // 0003 CALL R3 1 + 0x8C0C0702, // 0004 GETMET R3 R3 K2 + 0x7C0C0200, // 0005 CALL R3 1 + 0x8C0C0703, // 0006 GETMET R3 R3 K3 + 0x7C0C0200, // 0007 CALL R3 1 + 0x8C0C0704, // 0008 GETMET R3 R3 K4 + 0x7C0C0200, // 0009 CALL R3 1 + 0x8C100505, // 000A GETMET R4 R2 K5 + 0x7C100200, // 000B CALL R4 1 + 0xB8160C00, // 000C GETNGBL R5 K6 + 0x8C140B07, // 000D GETMET R5 R5 K7 + 0x601C0018, // 000E GETGBL R7 G24 + 0x58200008, // 000F LDCONST R8 K8 + 0x5C240600, // 0010 MOVE R9 R3 + 0x5C280800, // 0011 MOVE R10 R4 + 0x7C1C0600, // 0012 CALL R7 3 + 0x58200009, // 0013 LDCONST R8 K9 + 0x7C140600, // 0014 CALL R5 3 + 0x8C14010A, // 0015 GETMET R5 R0 K10 + 0x7C140200, // 0016 CALL R5 1 + 0x80000000, // 0017 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: process_attribute_read_solo +********************************************************************/ +be_local_closure(Matter_Device_process_attribute_read_solo, /* name */ + be_nested_proto( + 10, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_str_weak(endpoint), + /* K1 */ be_nested_str_weak(cluster), + /* K2 */ be_nested_str_weak(attribute), + /* K3 */ be_nested_str_weak(find_plugin_by_endpoint), + /* K4 */ be_nested_str_weak(status), + /* K5 */ be_nested_str_weak(matter), + /* K6 */ be_nested_str_weak(UNSUPPORTED_ENDPOINT), + /* K7 */ be_nested_str_weak(contains_cluster), + /* K8 */ be_nested_str_weak(UNSUPPORTED_CLUSTER), + /* K9 */ be_nested_str_weak(contains_attribute), + /* K10 */ be_nested_str_weak(UNSUPPORTED_ATTRIBUTE), + }), + be_str_weak(process_attribute_read_solo), + &be_const_str_solidified, + ( &(const binstruction[45]) { /* code */ + 0x88080300, // 0000 GETMBR R2 R1 K0 + 0x880C0301, // 0001 GETMBR R3 R1 K1 + 0x88100302, // 0002 GETMBR R4 R1 K2 + 0x4C140000, // 0003 LDNIL R5 + 0x1C140405, // 0004 EQ R5 R2 R5 + 0x74160005, // 0005 JMPT R5 #000C + 0x4C140000, // 0006 LDNIL R5 + 0x1C140605, // 0007 EQ R5 R3 R5 + 0x74160002, // 0008 JMPT R5 #000C + 0x4C140000, // 0009 LDNIL R5 + 0x1C140805, // 000A EQ R5 R4 R5 + 0x78160001, // 000B JMPF R5 #000E + 0x4C140000, // 000C LDNIL R5 + 0x80040A00, // 000D RET 1 R5 + 0x8C140103, // 000E GETMET R5 R0 K3 + 0x5C1C0400, // 000F MOVE R7 R2 + 0x7C140400, // 0010 CALL R5 2 + 0x4C180000, // 0011 LDNIL R6 + 0x1C180A06, // 0012 EQ R6 R5 R6 + 0x781A0004, // 0013 JMPF R6 #0019 + 0xB81A0A00, // 0014 GETNGBL R6 K5 + 0x88180D06, // 0015 GETMBR R6 R6 K6 + 0x90060806, // 0016 SETMBR R1 K4 R6 + 0x4C180000, // 0017 LDNIL R6 + 0x80040C00, // 0018 RET 1 R6 + 0x8C180B07, // 0019 GETMET R6 R5 K7 + 0x5C200600, // 001A MOVE R8 R3 + 0x7C180400, // 001B CALL R6 2 + 0x741A0004, // 001C JMPT R6 #0022 + 0xB81A0A00, // 001D GETNGBL R6 K5 + 0x88180D08, // 001E GETMBR R6 R6 K8 + 0x90060806, // 001F SETMBR R1 K4 R6 + 0x4C180000, // 0020 LDNIL R6 + 0x80040C00, // 0021 RET 1 R6 + 0x8C180B09, // 0022 GETMET R6 R5 K9 + 0x5C200600, // 0023 MOVE R8 R3 + 0x5C240800, // 0024 MOVE R9 R4 + 0x7C180600, // 0025 CALL R6 3 + 0x741A0004, // 0026 JMPT R6 #002C + 0xB81A0A00, // 0027 GETNGBL R6 K5 + 0x88180D0A, // 0028 GETMBR R6 R6 K10 + 0x90060806, // 0029 SETMBR R1 K4 R6 + 0x4C180000, // 002A LDNIL R6 + 0x80040C00, // 002B RET 1 R6 + 0x80040A00, // 002C RET 1 R5 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start_commissioning_complete_deferred +********************************************************************/ +be_local_closure(Matter_Device_start_commissioning_complete_deferred, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 1]) { + be_nested_proto( + 3, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 2]) { /* upvals */ + be_local_const_upval(1, 0), + be_local_const_upval(1, 1), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(start_commissioning_complete), + }), + be_str_weak(_X3Clambda_X3E), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x68080001, // 0002 GETUPV R2 U1 + 0x7C000400, // 0003 CALL R0 2 + 0x80040000, // 0004 RET 1 R0 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(set_timer), + /* K2 */ be_const_int(0), + }), + be_str_weak(start_commissioning_complete_deferred), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0xB80A0000, // 0000 GETNGBL R2 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x58100002, // 0002 LDCONST R4 K2 + 0x84140000, // 0003 CLOSURE R5 P0 + 0x7C080600, // 0004 CALL R2 3 + 0xA0000000, // 0005 CLOSE R0 + 0x80000000, // 0006 RET 0 }) ) ); @@ -5803,6 +2049,3492 @@ be_local_closure(Matter_Device_save_param, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: mdns_announce_op_discovery_all_fabrics +********************************************************************/ +be_local_closure(Matter_Device_mdns_announce_op_discovery_all_fabrics, /* name */ + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(sessions), + /* K1 */ be_nested_str_weak(active_fabrics), + /* K2 */ be_nested_str_weak(get_device_id), + /* K3 */ be_nested_str_weak(get_fabric_id), + /* K4 */ be_nested_str_weak(mdns_announce_op_discovery), + /* K5 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(mdns_announce_op_discovery_all_fabrics), + &be_const_str_solidified, + ( &(const binstruction[22]) { /* code */ + 0x60040010, // 0000 GETGBL R1 G16 + 0x88080100, // 0001 GETMBR R2 R0 K0 + 0x8C080501, // 0002 GETMET R2 R2 K1 + 0x7C080200, // 0003 CALL R2 1 + 0x7C040200, // 0004 CALL R1 1 + 0xA802000B, // 0005 EXBLK 0 #0012 + 0x5C080200, // 0006 MOVE R2 R1 + 0x7C080000, // 0007 CALL R2 0 + 0x8C0C0502, // 0008 GETMET R3 R2 K2 + 0x7C0C0200, // 0009 CALL R3 1 + 0x780E0005, // 000A JMPF R3 #0011 + 0x8C0C0503, // 000B GETMET R3 R2 K3 + 0x7C0C0200, // 000C CALL R3 1 + 0x780E0002, // 000D JMPF R3 #0011 + 0x8C0C0104, // 000E GETMET R3 R0 K4 + 0x5C140400, // 000F MOVE R5 R2 + 0x7C0C0400, // 0010 CALL R3 2 + 0x7001FFF3, // 0011 JMP #0006 + 0x58040005, // 0012 LDCONST R1 K5 + 0xAC040200, // 0013 CATCH R1 1 0 + 0xB0080000, // 0014 RAISE 2 R0 R0 + 0x80000000, // 0015 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: adjust_next_ep +********************************************************************/ +be_local_closure(Matter_Device_adjust_next_ep, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(plugins_config), + /* K1 */ be_nested_str_weak(keys), + /* K2 */ be_nested_str_weak(next_ep), + /* K3 */ be_const_int(1), + /* K4 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(adjust_next_ep), + &be_const_str_solidified, + ( &(const binstruction[21]) { /* code */ + 0x60040010, // 0000 GETGBL R1 G16 + 0x88080100, // 0001 GETMBR R2 R0 K0 + 0x8C080501, // 0002 GETMET R2 R2 K1 + 0x7C080200, // 0003 CALL R2 1 + 0x7C040200, // 0004 CALL R1 1 + 0xA802000A, // 0005 EXBLK 0 #0011 + 0x5C080200, // 0006 MOVE R2 R1 + 0x7C080000, // 0007 CALL R2 0 + 0x600C0009, // 0008 GETGBL R3 G9 + 0x5C100400, // 0009 MOVE R4 R2 + 0x7C0C0200, // 000A CALL R3 1 + 0x88100102, // 000B GETMBR R4 R0 K2 + 0x28100604, // 000C GE R4 R3 R4 + 0x78120001, // 000D JMPF R4 #0010 + 0x00100703, // 000E ADD R4 R3 K3 + 0x90020404, // 000F SETMBR R0 K2 R4 + 0x7001FFF4, // 0010 JMP #0006 + 0x58040004, // 0011 LDCONST R1 K4 + 0xAC040200, // 0012 CATCH R1 1 0 + 0xB0080000, // 0013 RAISE 2 R0 R0 + 0x80000000, // 0014 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Matter_Device_init, /* name */ + be_nested_proto( + 7, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 2]) { + be_nested_proto( + 4, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(start), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(remove_rule), + /* K3 */ be_nested_str_weak(Wifi_X23Connected), + /* K4 */ be_nested_str_weak(matter_start), + }), + be_str_weak(_anonymous_), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x7C000200, // 0002 CALL R0 1 + 0xB8020200, // 0003 GETNGBL R0 K1 + 0x8C000102, // 0004 GETMET R0 R0 K2 + 0x58080003, // 0005 LDCONST R2 K3 + 0x580C0004, // 0006 LDCONST R3 K4 + 0x7C000600, // 0007 CALL R0 3 + 0x80000000, // 0008 RET 0 + }) + ), + be_nested_proto( + 4, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(start), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(remove_rule), + /* K3 */ be_nested_str_weak(Eth_X23Connected), + /* K4 */ be_nested_str_weak(matter_start), + }), + be_str_weak(_anonymous_), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x7C000200, // 0002 CALL R0 1 + 0xB8020200, // 0003 GETNGBL R0 K1 + 0x8C000102, // 0004 GETMET R0 R0 K2 + 0x58080003, // 0005 LDCONST R2 K3 + 0x580C0004, // 0006 LDCONST R3 K4 + 0x7C000600, // 0007 CALL R0 3 + 0x80000000, // 0008 RET 0 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[44]) { /* constants */ + /* K0 */ be_nested_str_weak(crypto), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(get_option), + /* K3 */ be_nested_str_weak(matter), + /* K4 */ be_nested_str_weak(MATTER_OPTION), + /* K5 */ be_nested_str_weak(UI), + /* K6 */ be_nested_str_weak(profiler), + /* K7 */ be_nested_str_weak(Profiler), + /* K8 */ be_nested_str_weak(started), + /* K9 */ be_nested_str_weak(tick), + /* K10 */ be_const_int(0), + /* K11 */ be_nested_str_weak(plugins), + /* K12 */ be_nested_str_weak(plugins_persist), + /* K13 */ be_nested_str_weak(plugins_config_remotes), + /* K14 */ be_nested_str_weak(vendorid), + /* K15 */ be_nested_str_weak(VENDOR_ID), + /* K16 */ be_nested_str_weak(productid), + /* K17 */ be_nested_str_weak(PRODUCT_ID), + /* K18 */ be_nested_str_weak(root_iterations), + /* K19 */ be_nested_str_weak(PBKDF_ITERATIONS), + /* K20 */ be_nested_str_weak(next_ep), + /* K21 */ be_const_int(1), + /* K22 */ be_nested_str_weak(root_salt), + /* K23 */ be_nested_str_weak(random), + /* K24 */ be_nested_str_weak(ipv4only), + /* K25 */ be_nested_str_weak(disable_bridge_mode), + /* K26 */ be_nested_str_weak(load_param), + /* K27 */ be_nested_str_weak(sessions), + /* K28 */ be_nested_str_weak(Session_Store), + /* K29 */ be_nested_str_weak(load_fabrics), + /* K30 */ be_nested_str_weak(message_handler), + /* K31 */ be_nested_str_weak(MessageHandler), + /* K32 */ be_nested_str_weak(ui), + /* K33 */ be_nested_str_weak(wifi), + /* K34 */ be_nested_str_weak(up), + /* K35 */ be_nested_str_weak(eth), + /* K36 */ be_nested_str_weak(start), + /* K37 */ be_nested_str_weak(add_rule), + /* K38 */ be_nested_str_weak(Wifi_X23Connected), + /* K39 */ be_nested_str_weak(matter_start), + /* K40 */ be_nested_str_weak(Eth_X23Connected), + /* K41 */ be_nested_str_weak(_init_basic_commissioning), + /* K42 */ be_nested_str_weak(add_driver), + /* K43 */ be_nested_str_weak(register_commands), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[107]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xB80A0200, // 0001 GETNGBL R2 K1 + 0x8C080502, // 0002 GETMET R2 R2 K2 + 0xB8120600, // 0003 GETNGBL R4 K3 + 0x88100904, // 0004 GETMBR R4 R4 K4 + 0x7C080400, // 0005 CALL R2 2 + 0x740A0004, // 0006 JMPT R2 #000C + 0xB80A0600, // 0007 GETNGBL R2 K3 + 0x8C080505, // 0008 GETMET R2 R2 K5 + 0x5C100000, // 0009 MOVE R4 R0 + 0x7C080400, // 000A CALL R2 2 + 0x80000400, // 000B RET 0 + 0xB80A0600, // 000C GETNGBL R2 K3 + 0xB80E0600, // 000D GETNGBL R3 K3 + 0x8C0C0707, // 000E GETMET R3 R3 K7 + 0x7C0C0200, // 000F CALL R3 1 + 0x900A0C03, // 0010 SETMBR R2 K6 R3 + 0x50080000, // 0011 LDBOOL R2 0 0 + 0x90021002, // 0012 SETMBR R0 K8 R2 + 0x9002130A, // 0013 SETMBR R0 K9 K10 + 0x60080012, // 0014 GETGBL R2 G18 + 0x7C080000, // 0015 CALL R2 0 + 0x90021602, // 0016 SETMBR R0 K11 R2 + 0x50080000, // 0017 LDBOOL R2 0 0 + 0x90021802, // 0018 SETMBR R0 K12 R2 + 0x60080013, // 0019 GETGBL R2 G19 + 0x7C080000, // 001A CALL R2 0 + 0x90021A02, // 001B SETMBR R0 K13 R2 + 0x8808010F, // 001C GETMBR R2 R0 K15 + 0x90021C02, // 001D SETMBR R0 K14 R2 + 0x88080111, // 001E GETMBR R2 R0 K17 + 0x90022002, // 001F SETMBR R0 K16 R2 + 0x88080113, // 0020 GETMBR R2 R0 K19 + 0x90022402, // 0021 SETMBR R0 K18 R2 + 0x90022915, // 0022 SETMBR R0 K20 K21 + 0x8C080317, // 0023 GETMET R2 R1 K23 + 0x5412000F, // 0024 LDINT R4 16 + 0x7C080400, // 0025 CALL R2 2 + 0x90022C02, // 0026 SETMBR R0 K22 R2 + 0x50080000, // 0027 LDBOOL R2 0 0 + 0x90023002, // 0028 SETMBR R0 K24 R2 + 0x50080000, // 0029 LDBOOL R2 0 0 + 0x90023202, // 002A SETMBR R0 K25 R2 + 0x8C08011A, // 002B GETMET R2 R0 K26 + 0x7C080200, // 002C CALL R2 1 + 0xB80A0600, // 002D GETNGBL R2 K3 + 0x8C08051C, // 002E GETMET R2 R2 K28 + 0x5C100000, // 002F MOVE R4 R0 + 0x7C080400, // 0030 CALL R2 2 + 0x90023602, // 0031 SETMBR R0 K27 R2 + 0x8808011B, // 0032 GETMBR R2 R0 K27 + 0x8C08051D, // 0033 GETMET R2 R2 K29 + 0x7C080200, // 0034 CALL R2 1 + 0xB80A0600, // 0035 GETNGBL R2 K3 + 0x8C08051F, // 0036 GETMET R2 R2 K31 + 0x5C100000, // 0037 MOVE R4 R0 + 0x7C080400, // 0038 CALL R2 2 + 0x90023C02, // 0039 SETMBR R0 K30 R2 + 0xB80A0600, // 003A GETNGBL R2 K3 + 0x8C080505, // 003B GETMET R2 R2 K5 + 0x5C100000, // 003C MOVE R4 R0 + 0x7C080400, // 003D CALL R2 2 + 0x90024002, // 003E SETMBR R0 K32 R2 + 0xB80A0200, // 003F GETNGBL R2 K1 + 0x8C080521, // 0040 GETMET R2 R2 K33 + 0x7C080200, // 0041 CALL R2 1 + 0x94080522, // 0042 GETIDX R2 R2 K34 + 0x740A0004, // 0043 JMPT R2 #0049 + 0xB80A0200, // 0044 GETNGBL R2 K1 + 0x8C080523, // 0045 GETMET R2 R2 K35 + 0x7C080200, // 0046 CALL R2 1 + 0x94080522, // 0047 GETIDX R2 R2 K34 + 0x780A0001, // 0048 JMPF R2 #004B + 0x8C080124, // 0049 GETMET R2 R0 K36 + 0x7C080200, // 004A CALL R2 1 + 0xB80A0200, // 004B GETNGBL R2 K1 + 0x8C080521, // 004C GETMET R2 R2 K33 + 0x7C080200, // 004D CALL R2 1 + 0x94080522, // 004E GETIDX R2 R2 K34 + 0x740A0005, // 004F JMPT R2 #0056 + 0xB80A0200, // 0050 GETNGBL R2 K1 + 0x8C080525, // 0051 GETMET R2 R2 K37 + 0x58100026, // 0052 LDCONST R4 K38 + 0x84140000, // 0053 CLOSURE R5 P0 + 0x58180027, // 0054 LDCONST R6 K39 + 0x7C080800, // 0055 CALL R2 4 + 0xB80A0200, // 0056 GETNGBL R2 K1 + 0x8C080523, // 0057 GETMET R2 R2 K35 + 0x7C080200, // 0058 CALL R2 1 + 0x94080522, // 0059 GETIDX R2 R2 K34 + 0x740A0005, // 005A JMPT R2 #0061 + 0xB80A0200, // 005B GETNGBL R2 K1 + 0x8C080525, // 005C GETMET R2 R2 K37 + 0x58100028, // 005D LDCONST R4 K40 + 0x84140001, // 005E CLOSURE R5 P1 + 0x58180027, // 005F LDCONST R6 K39 + 0x7C080800, // 0060 CALL R2 4 + 0x8C080129, // 0061 GETMET R2 R0 K41 + 0x7C080200, // 0062 CALL R2 1 + 0xB80A0200, // 0063 GETNGBL R2 K1 + 0x8C08052A, // 0064 GETMET R2 R2 K42 + 0x5C100000, // 0065 MOVE R4 R0 + 0x7C080400, // 0066 CALL R2 2 + 0x8C08012B, // 0067 GETMET R2 R0 K43 + 0x7C080200, // 0068 CALL R2 1 + 0xA0000000, // 0069 CLOSE R0 + 0x80000000, // 006A RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: _instantiate_plugins_from_config +********************************************************************/ +be_local_closure(Matter_Device__instantiate_plugins_from_config, /* name */ + be_nested_proto( + 18, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[30]) { /* constants */ + /* K0 */ be_nested_str_weak(k2l_num), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(log), + /* K3 */ be_nested_str_weak(MTR_X3A_X20Configuring_X20endpoints), + /* K4 */ be_const_int(2), + /* K5 */ be_nested_str_weak(plugins), + /* K6 */ be_nested_str_weak(push), + /* K7 */ be_nested_str_weak(matter), + /* K8 */ be_nested_str_weak(Plugin_Root), + /* K9 */ be_const_int(0), + /* K10 */ be_nested_str_weak(MTR_X3A_X20_X20_X20endpoint_X20_X3D_X20_X255i_X20type_X3A_X25s_X25s), + /* K11 */ be_nested_str_weak(root), + /* K12 */ be_nested_str_weak(), + /* K13 */ be_nested_str_weak(Plugin_Aggregator), + /* K14 */ be_nested_str_weak(find), + /* K15 */ be_nested_str_weak(type), + /* K16 */ be_nested_str_weak(MTR_X3A_X20no_X20class_X20name_X2C_X20skipping), + /* K17 */ be_const_int(3), + /* K18 */ be_nested_str_weak(MTR_X3A_X20only_X20one_X20root_X20node_X20allowed), + /* K19 */ be_nested_str_weak(plugins_classes), + /* K20 */ be_nested_str_weak(MTR_X3A_X20unknown_X20class_X20name_X20_X27), + /* K21 */ be_nested_str_weak(_X27_X20skipping), + /* K22 */ be_nested_str_weak(conf_to_log), + /* K23 */ be_nested_str_weak(MTR_X3A_X20Exception), + /* K24 */ be_nested_str_weak(_X7C), + /* K25 */ be_nested_str_weak(stop_iteration), + /* K26 */ be_nested_str_weak(aggregator), + /* K27 */ be_nested_str_weak(publish_result), + /* K28 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Initialized_X22_X3A1_X7D_X7D), + /* K29 */ be_nested_str_weak(Matter), + }), + be_str_weak(_instantiate_plugins_from_config), + &be_const_str_solidified, + ( &(const binstruction[152]) { /* code */ + 0x8C080100, // 0000 GETMET R2 R0 K0 + 0x5C100200, // 0001 MOVE R4 R1 + 0x7C080400, // 0002 CALL R2 2 + 0xB80E0200, // 0003 GETNGBL R3 K1 + 0x8C0C0702, // 0004 GETMET R3 R3 K2 + 0x58140003, // 0005 LDCONST R5 K3 + 0x58180004, // 0006 LDCONST R6 K4 + 0x7C0C0600, // 0007 CALL R3 3 + 0x880C0105, // 0008 GETMBR R3 R0 K5 + 0x8C0C0706, // 0009 GETMET R3 R3 K6 + 0xB8160E00, // 000A GETNGBL R5 K7 + 0x8C140B08, // 000B GETMET R5 R5 K8 + 0x5C1C0000, // 000C MOVE R7 R0 + 0x58200009, // 000D LDCONST R8 K9 + 0x60240013, // 000E GETGBL R9 G19 + 0x7C240000, // 000F CALL R9 0 + 0x7C140800, // 0010 CALL R5 4 + 0x7C0C0400, // 0011 CALL R3 2 + 0xB80E0200, // 0012 GETNGBL R3 K1 + 0x8C0C0702, // 0013 GETMET R3 R3 K2 + 0x60140018, // 0014 GETGBL R5 G24 + 0x5818000A, // 0015 LDCONST R6 K10 + 0x581C0009, // 0016 LDCONST R7 K9 + 0x5820000B, // 0017 LDCONST R8 K11 + 0x5824000C, // 0018 LDCONST R9 K12 + 0x7C140800, // 0019 CALL R5 4 + 0x58180004, // 001A LDCONST R6 K4 + 0x7C0C0600, // 001B CALL R3 3 + 0x880C0105, // 001C GETMBR R3 R0 K5 + 0x8C0C0706, // 001D GETMET R3 R3 K6 + 0xB8160E00, // 001E GETNGBL R5 K7 + 0x8C140B0D, // 001F GETMET R5 R5 K13 + 0x5C1C0000, // 0020 MOVE R7 R0 + 0x5422FEFF, // 0021 LDINT R8 65280 + 0x60240013, // 0022 GETGBL R9 G19 + 0x7C240000, // 0023 CALL R9 0 + 0x7C140800, // 0024 CALL R5 4 + 0x7C0C0400, // 0025 CALL R3 2 + 0x600C0010, // 0026 GETGBL R3 G16 + 0x5C100400, // 0027 MOVE R4 R2 + 0x7C0C0200, // 0028 CALL R3 1 + 0xA802005A, // 0029 EXBLK 0 #0085 + 0x5C100600, // 002A MOVE R4 R3 + 0x7C100000, // 002B CALL R4 0 + 0x1C140909, // 002C EQ R5 R4 K9 + 0x78160000, // 002D JMPF R5 #002F + 0x7001FFFA, // 002E JMP #002A + 0xA8020042, // 002F EXBLK 0 #0073 + 0x60140008, // 0030 GETGBL R5 G8 + 0x5C180800, // 0031 MOVE R6 R4 + 0x7C140200, // 0032 CALL R5 1 + 0x94140205, // 0033 GETIDX R5 R1 R5 + 0x8C180B0E, // 0034 GETMET R6 R5 K14 + 0x5820000F, // 0035 LDCONST R8 K15 + 0x7C180400, // 0036 CALL R6 2 + 0x4C1C0000, // 0037 LDNIL R7 + 0x1C1C0C07, // 0038 EQ R7 R6 R7 + 0x781E0006, // 0039 JMPF R7 #0041 + 0xB81E0200, // 003A GETNGBL R7 K1 + 0x8C1C0F02, // 003B GETMET R7 R7 K2 + 0x58240010, // 003C LDCONST R9 K16 + 0x58280011, // 003D LDCONST R10 K17 + 0x7C1C0600, // 003E CALL R7 3 + 0xA8040001, // 003F EXBLK 1 1 + 0x7001FFE8, // 0040 JMP #002A + 0x1C1C0D0B, // 0041 EQ R7 R6 K11 + 0x781E0006, // 0042 JMPF R7 #004A + 0xB81E0200, // 0043 GETNGBL R7 K1 + 0x8C1C0F02, // 0044 GETMET R7 R7 K2 + 0x58240012, // 0045 LDCONST R9 K18 + 0x58280011, // 0046 LDCONST R10 K17 + 0x7C1C0600, // 0047 CALL R7 3 + 0xA8040001, // 0048 EXBLK 1 1 + 0x7001FFDF, // 0049 JMP #002A + 0x881C0113, // 004A GETMBR R7 R0 K19 + 0x8C1C0F0E, // 004B GETMET R7 R7 K14 + 0x5C240C00, // 004C MOVE R9 R6 + 0x7C1C0400, // 004D CALL R7 2 + 0x4C200000, // 004E LDNIL R8 + 0x1C200E08, // 004F EQ R8 R7 R8 + 0x7822000A, // 0050 JMPF R8 #005C + 0xB8220200, // 0051 GETNGBL R8 K1 + 0x8C201102, // 0052 GETMET R8 R8 K2 + 0x60280008, // 0053 GETGBL R10 G8 + 0x5C2C0C00, // 0054 MOVE R11 R6 + 0x7C280200, // 0055 CALL R10 1 + 0x002A280A, // 0056 ADD R10 K20 R10 + 0x00281515, // 0057 ADD R10 R10 K21 + 0x582C0004, // 0058 LDCONST R11 K4 + 0x7C200600, // 0059 CALL R8 3 + 0xA8040001, // 005A EXBLK 1 1 + 0x7001FFCD, // 005B JMP #002A + 0x5C200E00, // 005C MOVE R8 R7 + 0x5C240000, // 005D MOVE R9 R0 + 0x5C280800, // 005E MOVE R10 R4 + 0x5C2C0A00, // 005F MOVE R11 R5 + 0x7C200600, // 0060 CALL R8 3 + 0x88240105, // 0061 GETMBR R9 R0 K5 + 0x8C241306, // 0062 GETMET R9 R9 K6 + 0x5C2C1000, // 0063 MOVE R11 R8 + 0x7C240400, // 0064 CALL R9 2 + 0xB8260200, // 0065 GETNGBL R9 K1 + 0x8C241302, // 0066 GETMET R9 R9 K2 + 0x602C0018, // 0067 GETGBL R11 G24 + 0x5830000A, // 0068 LDCONST R12 K10 + 0x5C340800, // 0069 MOVE R13 R4 + 0x5C380C00, // 006A MOVE R14 R6 + 0x8C3C0116, // 006B GETMET R15 R0 K22 + 0x5C440A00, // 006C MOVE R17 R5 + 0x7C3C0400, // 006D CALL R15 2 + 0x7C2C0800, // 006E CALL R11 4 + 0x58300004, // 006F LDCONST R12 K4 + 0x7C240600, // 0070 CALL R9 3 + 0xA8040001, // 0071 EXBLK 1 1 + 0x70020010, // 0072 JMP #0084 + 0xAC140002, // 0073 CATCH R5 0 2 + 0x7002000D, // 0074 JMP #0083 + 0xB81E0200, // 0075 GETNGBL R7 K1 + 0x8C1C0F02, // 0076 GETMET R7 R7 K2 + 0x60240008, // 0077 GETGBL R9 G8 + 0x5C280A00, // 0078 MOVE R10 R5 + 0x7C240200, // 0079 CALL R9 1 + 0x00262E09, // 007A ADD R9 K23 R9 + 0x00241318, // 007B ADD R9 R9 K24 + 0x60280008, // 007C GETGBL R10 G8 + 0x5C2C0C00, // 007D MOVE R11 R6 + 0x7C280200, // 007E CALL R10 1 + 0x0024120A, // 007F ADD R9 R9 R10 + 0x58280004, // 0080 LDCONST R10 K4 + 0x7C1C0600, // 0081 CALL R7 3 + 0x70020000, // 0082 JMP #0084 + 0xB0080000, // 0083 RAISE 2 R0 R0 + 0x7001FFA4, // 0084 JMP #002A + 0x580C0019, // 0085 LDCONST R3 K25 + 0xAC0C0200, // 0086 CATCH R3 1 0 + 0xB0080000, // 0087 RAISE 2 R0 R0 + 0xB80E0200, // 0088 GETNGBL R3 K1 + 0x8C0C0702, // 0089 GETMET R3 R3 K2 + 0x60140018, // 008A GETGBL R5 G24 + 0x5818000A, // 008B LDCONST R6 K10 + 0x541EFEFF, // 008C LDINT R7 65280 + 0x5820001A, // 008D LDCONST R8 K26 + 0x5824000C, // 008E LDCONST R9 K12 + 0x7C140800, // 008F CALL R5 4 + 0x58180004, // 0090 LDCONST R6 K4 + 0x7C0C0600, // 0091 CALL R3 3 + 0xB80E0200, // 0092 GETNGBL R3 K1 + 0x8C0C071B, // 0093 GETMET R3 R3 K27 + 0x5814001C, // 0094 LDCONST R5 K28 + 0x5818001D, // 0095 LDCONST R6 K29 + 0x7C0C0600, // 0096 CALL R3 3 + 0x80000000, // 0097 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: k2l_num +********************************************************************/ +be_local_closure(Matter_Device_k2l_num, /* name */ + be_nested_proto( + 9, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_const_class(be_class_Matter_Device), + /* K1 */ be_nested_str_weak(keys), + /* K2 */ be_nested_str_weak(push), + /* K3 */ be_nested_str_weak(stop_iteration), + /* K4 */ be_const_int(1), + /* K5 */ be_const_int(0), + }), + be_str_weak(k2l_num), + &be_const_str_solidified, + ( &(const binstruction[52]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x60080012, // 0001 GETGBL R2 G18 + 0x7C080000, // 0002 CALL R2 0 + 0x4C0C0000, // 0003 LDNIL R3 + 0x1C0C0003, // 0004 EQ R3 R0 R3 + 0x780E0000, // 0005 JMPF R3 #0007 + 0x80040400, // 0006 RET 1 R2 + 0x600C0010, // 0007 GETGBL R3 G16 + 0x8C100101, // 0008 GETMET R4 R0 K1 + 0x7C100200, // 0009 CALL R4 1 + 0x7C0C0200, // 000A CALL R3 1 + 0xA8020007, // 000B EXBLK 0 #0014 + 0x5C100600, // 000C MOVE R4 R3 + 0x7C100000, // 000D CALL R4 0 + 0x8C140502, // 000E GETMET R5 R2 K2 + 0x601C0009, // 000F GETGBL R7 G9 + 0x5C200800, // 0010 MOVE R8 R4 + 0x7C1C0200, // 0011 CALL R7 1 + 0x7C140400, // 0012 CALL R5 2 + 0x7001FFF7, // 0013 JMP #000C + 0x580C0003, // 0014 LDCONST R3 K3 + 0xAC0C0200, // 0015 CATCH R3 1 0 + 0xB0080000, // 0016 RAISE 2 R0 R0 + 0x600C0010, // 0017 GETGBL R3 G16 + 0x6010000C, // 0018 GETGBL R4 G12 + 0x5C140400, // 0019 MOVE R5 R2 + 0x7C100200, // 001A CALL R4 1 + 0x04100904, // 001B SUB R4 R4 K4 + 0x40120804, // 001C CONNECT R4 K4 R4 + 0x7C0C0200, // 001D CALL R3 1 + 0xA8020010, // 001E EXBLK 0 #0030 + 0x5C100600, // 001F MOVE R4 R3 + 0x7C100000, // 0020 CALL R4 0 + 0x94140404, // 0021 GETIDX R5 R2 R4 + 0x5C180800, // 0022 MOVE R6 R4 + 0x241C0D05, // 0023 GT R7 R6 K5 + 0x781E0008, // 0024 JMPF R7 #002E + 0x041C0D04, // 0025 SUB R7 R6 K4 + 0x941C0407, // 0026 GETIDX R7 R2 R7 + 0x241C0E05, // 0027 GT R7 R7 R5 + 0x781E0004, // 0028 JMPF R7 #002E + 0x041C0D04, // 0029 SUB R7 R6 K4 + 0x941C0407, // 002A GETIDX R7 R2 R7 + 0x98080C07, // 002B SETIDX R2 R6 R7 + 0x04180D04, // 002C SUB R6 R6 K4 + 0x7001FFF4, // 002D JMP #0023 + 0x98080C05, // 002E SETIDX R2 R6 R5 + 0x7001FFEE, // 002F JMP #001F + 0x580C0003, // 0030 LDCONST R3 K3 + 0xAC0C0200, // 0031 CATCH R3 1 0 + 0xB0080000, // 0032 RAISE 2 R0 R0 + 0x80040400, // 0033 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: find_plugin_by_friendly_name +********************************************************************/ +be_local_closure(Matter_Device_find_plugin_by_friendly_name, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_weak(plugins), + /* K2 */ be_nested_str_weak(get_name), + /* K3 */ be_const_int(1), + }), + be_str_weak(find_plugin_by_friendly_name), + &be_const_str_solidified, + ( &(const binstruction[35]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x1C080202, // 0001 EQ R2 R1 R2 + 0x740A0004, // 0002 JMPT R2 #0008 + 0x6008000C, // 0003 GETGBL R2 G12 + 0x5C0C0200, // 0004 MOVE R3 R1 + 0x7C080200, // 0005 CALL R2 1 + 0x1C080500, // 0006 EQ R2 R2 K0 + 0x780A0001, // 0007 JMPF R2 #000A + 0x4C080000, // 0008 LDNIL R2 + 0x80040400, // 0009 RET 1 R2 + 0x58080000, // 000A LDCONST R2 K0 + 0x600C000C, // 000B GETGBL R3 G12 + 0x88100101, // 000C GETMBR R4 R0 K1 + 0x7C0C0200, // 000D CALL R3 1 + 0x140C0403, // 000E LT R3 R2 R3 + 0x780E0010, // 000F JMPF R3 #0021 + 0x880C0101, // 0010 GETMBR R3 R0 K1 + 0x940C0602, // 0011 GETIDX R3 R3 R2 + 0x8C100702, // 0012 GETMET R4 R3 K2 + 0x7C100200, // 0013 CALL R4 1 + 0x4C140000, // 0014 LDNIL R5 + 0x20140805, // 0015 NE R5 R4 R5 + 0x78160007, // 0016 JMPF R5 #001F + 0x6014000C, // 0017 GETGBL R5 G12 + 0x5C180800, // 0018 MOVE R6 R4 + 0x7C140200, // 0019 CALL R5 1 + 0x24140B00, // 001A GT R5 R5 K0 + 0x78160002, // 001B JMPF R5 #001F + 0x1C140801, // 001C EQ R5 R4 R1 + 0x78160000, // 001D JMPF R5 #001F + 0x80040600, // 001E RET 1 R3 + 0x00080503, // 001F ADD R2 R2 K3 + 0x7001FFE9, // 0020 JMP #000B + 0x4C0C0000, // 0021 LDNIL R3 + 0x80040600, // 0022 RET 1 R3 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: msg_send +********************************************************************/ +be_local_closure(Matter_Device_msg_send, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(udp_server), + /* K1 */ be_nested_str_weak(send_UDP), + }), + be_str_weak(msg_send), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x80040400, // 0004 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_active_endpoints +********************************************************************/ +be_local_closure(Matter_Device_get_active_endpoints, /* name */ + be_nested_proto( + 9, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(plugins), + /* K1 */ be_nested_str_weak(get_endpoint), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(find), + /* K4 */ be_nested_str_weak(push), + /* K5 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(get_active_endpoints), + &be_const_str_solidified, + ( &(const binstruction[28]) { /* code */ + 0x60080012, // 0000 GETGBL R2 G18 + 0x7C080000, // 0001 CALL R2 0 + 0x600C0010, // 0002 GETGBL R3 G16 + 0x88100100, // 0003 GETMBR R4 R0 K0 + 0x7C0C0200, // 0004 CALL R3 1 + 0xA8020011, // 0005 EXBLK 0 #0018 + 0x5C100600, // 0006 MOVE R4 R3 + 0x7C100000, // 0007 CALL R4 0 + 0x8C140901, // 0008 GETMET R5 R4 K1 + 0x7C140200, // 0009 CALL R5 1 + 0x78060002, // 000A JMPF R1 #000E + 0x1C180B02, // 000B EQ R6 R5 K2 + 0x781A0000, // 000C JMPF R6 #000E + 0x7001FFF7, // 000D JMP #0006 + 0x8C180503, // 000E GETMET R6 R2 K3 + 0x5C200A00, // 000F MOVE R8 R5 + 0x7C180400, // 0010 CALL R6 2 + 0x4C1C0000, // 0011 LDNIL R7 + 0x1C180C07, // 0012 EQ R6 R6 R7 + 0x781A0002, // 0013 JMPF R6 #0017 + 0x8C180504, // 0014 GETMET R6 R2 K4 + 0x5C200A00, // 0015 MOVE R8 R5 + 0x7C180400, // 0016 CALL R6 2 + 0x7001FFED, // 0017 JMP #0006 + 0x580C0005, // 0018 LDCONST R3 K5 + 0xAC0C0200, // 0019 CATCH R3 1 0 + 0xB0080000, // 001A RAISE 2 R0 R0 + 0x80040400, // 001B RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start_root_basic_commissioning +********************************************************************/ +be_local_closure(Matter_Device_start_root_basic_commissioning, /* name */ + be_nested_proto( + 13, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[18]) { /* constants */ + /* K0 */ be_nested_str_weak(PASE_TIMEOUT), + /* K1 */ be_nested_str_weak(compute_manual_pairing_code), + /* K2 */ be_nested_str_weak(tasmota), + /* K3 */ be_nested_str_weak(log), + /* K4 */ be_nested_str_weak(MTR_X3A_X20Manual_X20pairing_X20code_X3A_X20_X25s), + /* K5 */ be_const_int(2), + /* K6 */ be_nested_str_weak(compute_qrcode_content), + /* K7 */ be_nested_str_weak(publish_result), + /* K8 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Commissioning_X22_X3A1_X2C_X22PairingCode_X22_X3A_X22_X25s_X22_X2C_X22QRCode_X22_X3A_X22_X25s_X22_X7D_X7D), + /* K9 */ be_nested_str_weak(Matter), + /* K10 */ be_nested_str_weak(_compute_pbkdf), + /* K11 */ be_nested_str_weak(root_passcode), + /* K12 */ be_nested_str_weak(root_iterations), + /* K13 */ be_nested_str_weak(root_salt), + /* K14 */ be_nested_str_weak(start_basic_commissioning), + /* K15 */ be_nested_str_weak(root_discriminator), + /* K16 */ be_nested_str_weak(root_w0), + /* K17 */ be_nested_str_weak(root_L), + }), + be_str_weak(start_root_basic_commissioning), + &be_const_str_solidified, + ( &(const binstruction[40]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x1C080202, // 0001 EQ R2 R1 R2 + 0x780A0000, // 0002 JMPF R2 #0004 + 0x88040100, // 0003 GETMBR R1 R0 K0 + 0x8C080101, // 0004 GETMET R2 R0 K1 + 0x7C080200, // 0005 CALL R2 1 + 0xB80E0400, // 0006 GETNGBL R3 K2 + 0x8C0C0703, // 0007 GETMET R3 R3 K3 + 0x60140018, // 0008 GETGBL R5 G24 + 0x58180004, // 0009 LDCONST R6 K4 + 0x5C1C0400, // 000A MOVE R7 R2 + 0x7C140400, // 000B CALL R5 2 + 0x58180005, // 000C LDCONST R6 K5 + 0x7C0C0600, // 000D CALL R3 3 + 0x8C0C0106, // 000E GETMET R3 R0 K6 + 0x7C0C0200, // 000F CALL R3 1 + 0xB8120400, // 0010 GETNGBL R4 K2 + 0x8C100907, // 0011 GETMET R4 R4 K7 + 0x60180018, // 0012 GETGBL R6 G24 + 0x581C0008, // 0013 LDCONST R7 K8 + 0x5C200400, // 0014 MOVE R8 R2 + 0x5C240600, // 0015 MOVE R9 R3 + 0x7C180600, // 0016 CALL R6 3 + 0x581C0009, // 0017 LDCONST R7 K9 + 0x7C100600, // 0018 CALL R4 3 + 0x8C10010A, // 0019 GETMET R4 R0 K10 + 0x8818010B, // 001A GETMBR R6 R0 K11 + 0x881C010C, // 001B GETMBR R7 R0 K12 + 0x8820010D, // 001C GETMBR R8 R0 K13 + 0x7C100800, // 001D CALL R4 4 + 0x8C10010E, // 001E GETMET R4 R0 K14 + 0x5C180200, // 001F MOVE R6 R1 + 0x881C010C, // 0020 GETMBR R7 R0 K12 + 0x8820010F, // 0021 GETMBR R8 R0 K15 + 0x8824010D, // 0022 GETMBR R9 R0 K13 + 0x88280110, // 0023 GETMBR R10 R0 K16 + 0x882C0111, // 0024 GETMBR R11 R0 K17 + 0x4C300000, // 0025 LDNIL R12 + 0x7C101000, // 0026 CALL R4 8 + 0x80000000, // 0027 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: bridge_remove_endpoint +********************************************************************/ +be_local_closure(Matter_Device_bridge_remove_endpoint, /* name */ + be_nested_proto( + 11, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[18]) { /* constants */ + /* K0 */ be_nested_str_weak(json), + /* K1 */ be_nested_str_weak(plugins_config), + /* K2 */ be_nested_str_weak(contains), + /* K3 */ be_nested_str_weak(tasmota), + /* K4 */ be_nested_str_weak(log), + /* K5 */ be_nested_str_weak(MTR_X3A_X20Cannot_X20remove_X20an_X20enpoint_X20not_X20configured_X3A_X20), + /* K6 */ be_const_int(3), + /* K7 */ be_nested_str_weak(MTR_X3A_X20deleting_X20endpoint_X20_X3D_X20_X25i), + /* K8 */ be_const_int(2), + /* K9 */ be_nested_str_weak(remove), + /* K10 */ be_nested_str_weak(plugins_persist), + /* K11 */ be_const_int(0), + /* K12 */ be_nested_str_weak(plugins), + /* K13 */ be_nested_str_weak(get_endpoint), + /* K14 */ be_const_int(1), + /* K15 */ be_nested_str_weak(clean_remotes), + /* K16 */ be_nested_str_weak(save_param), + /* K17 */ be_nested_str_weak(signal_endpoints_changed), + }), + be_str_weak(bridge_remove_endpoint), + &be_const_str_solidified, + ( &(const binstruction[58]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0x600C0008, // 0001 GETGBL R3 G8 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C0C0200, // 0003 CALL R3 1 + 0x4C100000, // 0004 LDNIL R4 + 0x4C140000, // 0005 LDNIL R5 + 0x88180101, // 0006 GETMBR R6 R0 K1 + 0x8C180D02, // 0007 GETMET R6 R6 K2 + 0x5C200600, // 0008 MOVE R8 R3 + 0x7C180400, // 0009 CALL R6 2 + 0x741A0005, // 000A JMPT R6 #0011 + 0xB81A0600, // 000B GETNGBL R6 K3 + 0x8C180D04, // 000C GETMET R6 R6 K4 + 0x00220A03, // 000D ADD R8 K5 R3 + 0x58240006, // 000E LDCONST R9 K6 + 0x7C180600, // 000F CALL R6 3 + 0x80000C00, // 0010 RET 0 + 0xB81A0600, // 0011 GETNGBL R6 K3 + 0x8C180D04, // 0012 GETMET R6 R6 K4 + 0x60200018, // 0013 GETGBL R8 G24 + 0x58240007, // 0014 LDCONST R9 K7 + 0x5C280200, // 0015 MOVE R10 R1 + 0x7C200400, // 0016 CALL R8 2 + 0x58240008, // 0017 LDCONST R9 K8 + 0x7C180600, // 0018 CALL R6 3 + 0x88180101, // 0019 GETMBR R6 R0 K1 + 0x8C180D09, // 001A GETMET R6 R6 K9 + 0x5C200600, // 001B MOVE R8 R3 + 0x7C180400, // 001C CALL R6 2 + 0x50180200, // 001D LDBOOL R6 1 0 + 0x90021406, // 001E SETMBR R0 K10 R6 + 0x5818000B, // 001F LDCONST R6 K11 + 0x601C000C, // 0020 GETGBL R7 G12 + 0x8820010C, // 0021 GETMBR R8 R0 K12 + 0x7C1C0200, // 0022 CALL R7 1 + 0x141C0C07, // 0023 LT R7 R6 R7 + 0x781E000D, // 0024 JMPF R7 #0033 + 0x881C010C, // 0025 GETMBR R7 R0 K12 + 0x941C0E06, // 0026 GETIDX R7 R7 R6 + 0x8C1C0F0D, // 0027 GETMET R7 R7 K13 + 0x7C1C0200, // 0028 CALL R7 1 + 0x1C1C0207, // 0029 EQ R7 R1 R7 + 0x781E0005, // 002A JMPF R7 #0031 + 0x881C010C, // 002B GETMBR R7 R0 K12 + 0x8C1C0F09, // 002C GETMET R7 R7 K9 + 0x5C240C00, // 002D MOVE R9 R6 + 0x7C1C0400, // 002E CALL R7 2 + 0x70020002, // 002F JMP #0033 + 0x70020000, // 0030 JMP #0032 + 0x00180D0E, // 0031 ADD R6 R6 K14 + 0x7001FFEC, // 0032 JMP #0020 + 0x8C1C010F, // 0033 GETMET R7 R0 K15 + 0x7C1C0200, // 0034 CALL R7 1 + 0x8C1C0110, // 0035 GETMET R7 R0 K16 + 0x7C1C0200, // 0036 CALL R7 1 + 0x8C1C0111, // 0037 GETMET R7 R0 K17 + 0x7C1C0200, // 0038 CALL R7 1 + 0x80000000, // 0039 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_plugin_class_displayname +********************************************************************/ +be_local_closure(Matter_Device_get_plugin_class_displayname, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(plugins_classes), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(DISPLAY_NAME), + /* K3 */ be_nested_str_weak(), + }), + be_str_weak(get_plugin_class_displayname), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x780A0001, // 0004 JMPF R2 #0007 + 0x880C0502, // 0005 GETMBR R3 R2 K2 + 0x70020000, // 0006 JMP #0008 + 0x580C0003, // 0007 LDCONST R3 K3 + 0x80040600, // 0008 RET 1 R3 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: update_remotes_info +********************************************************************/ +be_local_closure(Matter_Device_update_remotes_info, /* name */ + be_nested_proto( + 7, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(http_remotes), + /* K1 */ be_nested_str_weak(keys), + /* K2 */ be_nested_str_weak(get_info), + /* K3 */ be_const_int(0), + /* K4 */ be_nested_str_weak(stop_iteration), + /* K5 */ be_nested_str_weak(plugins_config_remotes), + }), + be_str_weak(update_remotes_info), + &be_const_str_solidified, + ( &(const binstruction[33]) { /* code */ + 0x60040013, // 0000 GETGBL R1 G19 + 0x7C040000, // 0001 CALL R1 0 + 0x88080100, // 0002 GETMBR R2 R0 K0 + 0x4C0C0000, // 0003 LDNIL R3 + 0x20080403, // 0004 NE R2 R2 R3 + 0x780A0018, // 0005 JMPF R2 #001F + 0x60080010, // 0006 GETGBL R2 G16 + 0x880C0100, // 0007 GETMBR R3 R0 K0 + 0x8C0C0701, // 0008 GETMET R3 R3 K1 + 0x7C0C0200, // 0009 CALL R3 1 + 0x7C080200, // 000A CALL R2 1 + 0xA802000F, // 000B EXBLK 0 #001C + 0x5C0C0400, // 000C MOVE R3 R2 + 0x7C0C0000, // 000D CALL R3 0 + 0x88100100, // 000E GETMBR R4 R0 K0 + 0x94100803, // 000F GETIDX R4 R4 R3 + 0x8C100902, // 0010 GETMET R4 R4 K2 + 0x7C100200, // 0011 CALL R4 1 + 0x4C140000, // 0012 LDNIL R5 + 0x20140805, // 0013 NE R5 R4 R5 + 0x78160005, // 0014 JMPF R5 #001B + 0x6014000C, // 0015 GETGBL R5 G12 + 0x5C180800, // 0016 MOVE R6 R4 + 0x7C140200, // 0017 CALL R5 1 + 0x24140B03, // 0018 GT R5 R5 K3 + 0x78160000, // 0019 JMPF R5 #001B + 0x98040604, // 001A SETIDX R1 R3 R4 + 0x7001FFEF, // 001B JMP #000C + 0x58080004, // 001C LDCONST R2 K4 + 0xAC080200, // 001D CATCH R2 1 0 + 0xB0080000, // 001E RAISE 2 R0 R0 + 0x90020A01, // 001F SETMBR R0 K5 R1 + 0x80040200, // 0020 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start +********************************************************************/ +be_local_closure(Matter_Device_start, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(started), + /* K1 */ be_nested_str_weak(autoconf_device), + /* K2 */ be_nested_str_weak(_start_udp), + /* K3 */ be_nested_str_weak(UDP_PORT), + /* K4 */ be_nested_str_weak(start_mdns_announce_hostnames), + }), + be_str_weak(start), + &be_const_str_solidified, + ( &(const binstruction[13]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x78060000, // 0001 JMPF R1 #0003 + 0x80000200, // 0002 RET 0 + 0x8C040101, // 0003 GETMET R1 R0 K1 + 0x7C040200, // 0004 CALL R1 1 + 0x8C040102, // 0005 GETMET R1 R0 K2 + 0x880C0103, // 0006 GETMBR R3 R0 K3 + 0x7C040400, // 0007 CALL R1 2 + 0x8C040104, // 0008 GETMET R1 R0 K4 + 0x7C040200, // 0009 CALL R1 1 + 0x50040200, // 000A LDBOOL R1 1 0 + 0x90020001, // 000B SETMBR R0 K0 R1 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: k2l +********************************************************************/ +be_local_closure(Matter_Device_k2l, /* name */ + be_nested_proto( + 8, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_const_class(be_class_Matter_Device), + /* K1 */ be_nested_str_weak(keys), + /* K2 */ be_nested_str_weak(push), + /* K3 */ be_nested_str_weak(stop_iteration), + /* K4 */ be_const_int(1), + /* K5 */ be_const_int(0), + }), + be_str_weak(k2l), + &be_const_str_solidified, + ( &(const binstruction[50]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x60080012, // 0001 GETGBL R2 G18 + 0x7C080000, // 0002 CALL R2 0 + 0x4C0C0000, // 0003 LDNIL R3 + 0x1C0C0003, // 0004 EQ R3 R0 R3 + 0x780E0000, // 0005 JMPF R3 #0007 + 0x80040400, // 0006 RET 1 R2 + 0x600C0010, // 0007 GETGBL R3 G16 + 0x8C100101, // 0008 GETMET R4 R0 K1 + 0x7C100200, // 0009 CALL R4 1 + 0x7C0C0200, // 000A CALL R3 1 + 0xA8020005, // 000B EXBLK 0 #0012 + 0x5C100600, // 000C MOVE R4 R3 + 0x7C100000, // 000D CALL R4 0 + 0x8C140502, // 000E GETMET R5 R2 K2 + 0x5C1C0800, // 000F MOVE R7 R4 + 0x7C140400, // 0010 CALL R5 2 + 0x7001FFF9, // 0011 JMP #000C + 0x580C0003, // 0012 LDCONST R3 K3 + 0xAC0C0200, // 0013 CATCH R3 1 0 + 0xB0080000, // 0014 RAISE 2 R0 R0 + 0x600C0010, // 0015 GETGBL R3 G16 + 0x6010000C, // 0016 GETGBL R4 G12 + 0x5C140400, // 0017 MOVE R5 R2 + 0x7C100200, // 0018 CALL R4 1 + 0x04100904, // 0019 SUB R4 R4 K4 + 0x40120804, // 001A CONNECT R4 K4 R4 + 0x7C0C0200, // 001B CALL R3 1 + 0xA8020010, // 001C EXBLK 0 #002E + 0x5C100600, // 001D MOVE R4 R3 + 0x7C100000, // 001E CALL R4 0 + 0x94140404, // 001F GETIDX R5 R2 R4 + 0x5C180800, // 0020 MOVE R6 R4 + 0x241C0D05, // 0021 GT R7 R6 K5 + 0x781E0008, // 0022 JMPF R7 #002C + 0x041C0D04, // 0023 SUB R7 R6 K4 + 0x941C0407, // 0024 GETIDX R7 R2 R7 + 0x241C0E05, // 0025 GT R7 R7 R5 + 0x781E0004, // 0026 JMPF R7 #002C + 0x041C0D04, // 0027 SUB R7 R6 K4 + 0x941C0407, // 0028 GETIDX R7 R2 R7 + 0x98080C07, // 0029 SETIDX R2 R6 R7 + 0x04180D04, // 002A SUB R6 R6 K4 + 0x7001FFF4, // 002B JMP #0021 + 0x98080C05, // 002C SETIDX R2 R6 R5 + 0x7001FFEE, // 002D JMP #001D + 0x580C0003, // 002E LDCONST R3 K3 + 0xAC0C0200, // 002F CATCH R3 1 0 + 0xB0080000, // 0030 RAISE 2 R0 R0 + 0x80040400, // 0031 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start_operational_discovery_deferred +********************************************************************/ +be_local_closure(Matter_Device_start_operational_discovery_deferred, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 1]) { + be_nested_proto( + 3, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 2]) { /* upvals */ + be_local_const_upval(1, 0), + be_local_const_upval(1, 1), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(start_operational_discovery), + }), + be_str_weak(_X3Clambda_X3E), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x68080001, // 0002 GETUPV R2 U1 + 0x7C000400, // 0003 CALL R0 2 + 0x80040000, // 0004 RET 1 R0 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(set_timer), + /* K2 */ be_const_int(0), + }), + be_str_weak(start_operational_discovery_deferred), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0xB80A0000, // 0000 GETNGBL R2 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x58100002, // 0002 LDCONST R4 K2 + 0x84140000, // 0003 CLOSURE R5 P0 + 0x7C080600, // 0004 CALL R2 3 + 0xA0000000, // 0005 CLOSE R0 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: autoconf_device_map +********************************************************************/ +be_local_closure(Matter_Device_autoconf_device_map, /* name */ + be_nested_proto( + 20, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[36]) { /* constants */ + /* K0 */ be_nested_str_weak(json), + /* K1 */ be_const_int(1), + /* K2 */ be_nested_str_weak(light), + /* K3 */ be_nested_str_weak(get), + /* K4 */ be_nested_str_weak(find), + /* K5 */ be_nested_str_weak(channels), + /* K6 */ be_nested_str_weak(), + /* K7 */ be_const_int(0), + /* K8 */ be_nested_str_weak(type), + /* K9 */ be_nested_str_weak(light1), + /* K10 */ be_const_int(2), + /* K11 */ be_nested_str_weak(light2), + /* K12 */ be_nested_str_weak(light3), + /* K13 */ be_nested_str_weak(tasmota), + /* K14 */ be_nested_str_weak(cmd), + /* K15 */ be_nested_str_weak(Status_X2013), + /* K16 */ be_nested_str_weak(log), + /* K17 */ be_nested_str_weak(MTR_X3A_X20Status_X2013_X20_X3D_X20), + /* K18 */ be_const_int(3), + /* K19 */ be_nested_str_weak(contains), + /* K20 */ be_nested_str_weak(StatusSHT), + /* K21 */ be_nested_str_weak(SHT), + /* K22 */ be_nested_str_weak(MTR_X3A_X20_X27_X25s_X27_X20_X3D_X20_X25s), + /* K23 */ be_nested_str_weak(Relay1), + /* K24 */ be_nested_str_weak(Relay2), + /* K25 */ be_nested_str_weak(push), + /* K26 */ be_nested_str_weak(MTR_X3A_X20relay1_X3D_X25s_X20relay2_X3D_X25s), + /* K27 */ be_nested_str_weak(TiltConfig), + /* K28 */ be_nested_str_weak(shutter_X2Btilt), + /* K29 */ be_nested_str_weak(shutter), + /* K30 */ be_nested_str_weak(get_power), + /* K31 */ be_nested_str_weak(relay), + /* K32 */ be_nested_str_weak(load), + /* K33 */ be_nested_str_weak(read_sensors), + /* K34 */ be_nested_str_weak(autoconf_sensors_list), + /* K35 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(autoconf_device_map), + &be_const_str_solidified, + ( &(const binstruction[198]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x60080013, // 0001 GETGBL R2 G19 + 0x7C080000, // 0002 CALL R2 0 + 0x580C0001, // 0003 LDCONST R3 K1 + 0x50100000, // 0004 LDBOOL R4 0 0 + 0xA4160400, // 0005 IMPORT R5 K2 + 0x8C180B03, // 0006 GETMET R6 R5 K3 + 0x7C180200, // 0007 CALL R6 1 + 0x4C1C0000, // 0008 LDNIL R7 + 0x201C0C07, // 0009 NE R7 R6 R7 + 0x781E0024, // 000A JMPF R7 #0030 + 0x601C000C, // 000B GETGBL R7 G12 + 0x8C200D04, // 000C GETMET R8 R6 K4 + 0x58280005, // 000D LDCONST R10 K5 + 0x582C0006, // 000E LDCONST R11 K6 + 0x7C200600, // 000F CALL R8 3 + 0x7C1C0200, // 0010 CALL R7 1 + 0x24200F07, // 0011 GT R8 R7 K7 + 0x7822001C, // 0012 JMPF R8 #0030 + 0x1C200F01, // 0013 EQ R8 R7 K1 + 0x78220007, // 0014 JMPF R8 #001D + 0x60200008, // 0015 GETGBL R8 G8 + 0x5C240600, // 0016 MOVE R9 R3 + 0x7C200200, // 0017 CALL R8 1 + 0x60240013, // 0018 GETGBL R9 G19 + 0x7C240000, // 0019 CALL R9 0 + 0x98261109, // 001A SETIDX R9 K8 K9 + 0x98081009, // 001B SETIDX R2 R8 R9 + 0x70020010, // 001C JMP #002E + 0x1C200F0A, // 001D EQ R8 R7 K10 + 0x78220007, // 001E JMPF R8 #0027 + 0x60200008, // 001F GETGBL R8 G8 + 0x5C240600, // 0020 MOVE R9 R3 + 0x7C200200, // 0021 CALL R8 1 + 0x60240013, // 0022 GETGBL R9 G19 + 0x7C240000, // 0023 CALL R9 0 + 0x9826110B, // 0024 SETIDX R9 K8 K11 + 0x98081009, // 0025 SETIDX R2 R8 R9 + 0x70020006, // 0026 JMP #002E + 0x60200008, // 0027 GETGBL R8 G8 + 0x5C240600, // 0028 MOVE R9 R3 + 0x7C200200, // 0029 CALL R8 1 + 0x60240013, // 002A GETGBL R9 G19 + 0x7C240000, // 002B CALL R9 0 + 0x9826110C, // 002C SETIDX R9 K8 K12 + 0x98081009, // 002D SETIDX R2 R8 R9 + 0x50100200, // 002E LDBOOL R4 1 0 + 0x000C0701, // 002F ADD R3 R3 K1 + 0xB81E1A00, // 0030 GETNGBL R7 K13 + 0x8C1C0F0E, // 0031 GETMET R7 R7 K14 + 0x5824000F, // 0032 LDCONST R9 K15 + 0x50280200, // 0033 LDBOOL R10 1 0 + 0x7C1C0600, // 0034 CALL R7 3 + 0x60200012, // 0035 GETGBL R8 G18 + 0x7C200000, // 0036 CALL R8 0 + 0xB8261A00, // 0037 GETNGBL R9 K13 + 0x8C241310, // 0038 GETMET R9 R9 K16 + 0x602C0008, // 0039 GETGBL R11 G8 + 0x5C300E00, // 003A MOVE R12 R7 + 0x7C2C0200, // 003B CALL R11 1 + 0x002E220B, // 003C ADD R11 K17 R11 + 0x58300012, // 003D LDCONST R12 K18 + 0x7C240600, // 003E CALL R9 3 + 0x4C240000, // 003F LDNIL R9 + 0x20240E09, // 0040 NE R9 R7 R9 + 0x7826004F, // 0041 JMPF R9 #0092 + 0x8C240F13, // 0042 GETMET R9 R7 K19 + 0x582C0014, // 0043 LDCONST R11 K20 + 0x7C240400, // 0044 CALL R9 2 + 0x7826004B, // 0045 JMPF R9 #0092 + 0x941C0F14, // 0046 GETIDX R7 R7 K20 + 0x58240007, // 0047 LDCONST R9 K7 + 0x50280200, // 0048 LDBOOL R10 1 0 + 0x782A0047, // 0049 JMPF R10 #0092 + 0x60280008, // 004A GETGBL R10 G8 + 0x5C2C1200, // 004B MOVE R11 R9 + 0x7C280200, // 004C CALL R10 1 + 0x002A2A0A, // 004D ADD R10 K21 R10 + 0x8C2C0F13, // 004E GETMET R11 R7 K19 + 0x5C341400, // 004F MOVE R13 R10 + 0x7C2C0400, // 0050 CALL R11 2 + 0x742E0000, // 0051 JMPT R11 #0053 + 0x7002003E, // 0052 JMP #0092 + 0x942C0E0A, // 0053 GETIDX R11 R7 R10 + 0xB8321A00, // 0054 GETNGBL R12 K13 + 0x8C301910, // 0055 GETMET R12 R12 K16 + 0x60380018, // 0056 GETGBL R14 G24 + 0x583C0016, // 0057 LDCONST R15 K22 + 0x5C401400, // 0058 MOVE R16 R10 + 0x60440008, // 0059 GETGBL R17 G8 + 0x5C481600, // 005A MOVE R18 R11 + 0x7C440200, // 005B CALL R17 1 + 0x7C380600, // 005C CALL R14 3 + 0x583C0012, // 005D LDCONST R15 K18 + 0x7C300600, // 005E CALL R12 3 + 0x8C301704, // 005F GETMET R12 R11 K4 + 0x58380017, // 0060 LDCONST R14 K23 + 0x543DFFFE, // 0061 LDINT R15 -1 + 0x7C300600, // 0062 CALL R12 3 + 0x8C341704, // 0063 GETMET R13 R11 K4 + 0x583C0018, // 0064 LDCONST R15 K24 + 0x5441FFFE, // 0065 LDINT R16 -1 + 0x7C340600, // 0066 CALL R13 3 + 0x24381907, // 0067 GT R14 R12 K7 + 0x783A0002, // 0068 JMPF R14 #006C + 0x8C381119, // 0069 GETMET R14 R8 K25 + 0x04401901, // 006A SUB R16 R12 K1 + 0x7C380400, // 006B CALL R14 2 + 0x24381B07, // 006C GT R14 R13 K7 + 0x783A0002, // 006D JMPF R14 #0071 + 0x8C381119, // 006E GETMET R14 R8 K25 + 0x04401B01, // 006F SUB R16 R13 K1 + 0x7C380400, // 0070 CALL R14 2 + 0xB83A1A00, // 0071 GETNGBL R14 K13 + 0x8C381D10, // 0072 GETMET R14 R14 K16 + 0x60400018, // 0073 GETGBL R16 G24 + 0x5844001A, // 0074 LDCONST R17 K26 + 0x5C481800, // 0075 MOVE R18 R12 + 0x5C4C1A00, // 0076 MOVE R19 R13 + 0x7C400600, // 0077 CALL R16 3 + 0x58440012, // 0078 LDCONST R17 K18 + 0x7C380600, // 0079 CALL R14 3 + 0x8C381704, // 007A GETMET R14 R11 K4 + 0x5840001B, // 007B LDCONST R16 K27 + 0x7C380400, // 007C CALL R14 2 + 0x783A0002, // 007D JMPF R14 #0081 + 0x943C1D0A, // 007E GETIDX R15 R14 K10 + 0x243C1F07, // 007F GT R15 R15 K7 + 0x743E0000, // 0080 JMPT R15 #0082 + 0x503C0001, // 0081 LDBOOL R15 0 1 + 0x503C0200, // 0082 LDBOOL R15 1 0 + 0x60400008, // 0083 GETGBL R16 G8 + 0x5C440600, // 0084 MOVE R17 R3 + 0x7C400200, // 0085 CALL R16 1 + 0x60440013, // 0086 GETGBL R17 G19 + 0x7C440000, // 0087 CALL R17 0 + 0x783E0001, // 0088 JMPF R15 #008B + 0x5848001C, // 0089 LDCONST R18 K28 + 0x70020000, // 008A JMP #008C + 0x5848001D, // 008B LDCONST R18 K29 + 0x98461012, // 008C SETIDX R17 K8 R18 + 0x98463A09, // 008D SETIDX R17 K29 R9 + 0x98082011, // 008E SETIDX R2 R16 R17 + 0x000C0701, // 008F ADD R3 R3 K1 + 0x00241301, // 0090 ADD R9 R9 K1 + 0x7001FFB5, // 0091 JMP #0048 + 0x6024000C, // 0092 GETGBL R9 G12 + 0xB82A1A00, // 0093 GETNGBL R10 K13 + 0x8C28151E, // 0094 GETMET R10 R10 K30 + 0x7C280200, // 0095 CALL R10 1 + 0x7C240200, // 0096 CALL R9 1 + 0x58280007, // 0097 LDCONST R10 K7 + 0x78120000, // 0098 JMPF R4 #009A + 0x04241301, // 0099 SUB R9 R9 K1 + 0x142C1409, // 009A LT R11 R10 R9 + 0x782E0011, // 009B JMPF R11 #00AE + 0x8C2C1104, // 009C GETMET R11 R8 K4 + 0x5C341400, // 009D MOVE R13 R10 + 0x7C2C0400, // 009E CALL R11 2 + 0x4C300000, // 009F LDNIL R12 + 0x1C2C160C, // 00A0 EQ R11 R11 R12 + 0x782E0009, // 00A1 JMPF R11 #00AC + 0x602C0008, // 00A2 GETGBL R11 G8 + 0x5C300600, // 00A3 MOVE R12 R3 + 0x7C2C0200, // 00A4 CALL R11 1 + 0x60300013, // 00A5 GETGBL R12 G19 + 0x7C300000, // 00A6 CALL R12 0 + 0x9832111F, // 00A7 SETIDX R12 K8 K31 + 0x00341501, // 00A8 ADD R13 R10 K1 + 0x98323E0D, // 00A9 SETIDX R12 K31 R13 + 0x9808160C, // 00AA SETIDX R2 R11 R12 + 0x000C0701, // 00AB ADD R3 R3 K1 + 0x00281501, // 00AC ADD R10 R10 K1 + 0x7001FFEB, // 00AD JMP #009A + 0x8C2C0320, // 00AE GETMET R11 R1 K32 + 0xB8361A00, // 00AF GETNGBL R13 K13 + 0x8C341B21, // 00B0 GETMET R13 R13 K33 + 0x7C340200, // 00B1 CALL R13 1 + 0x7C2C0400, // 00B2 CALL R11 2 + 0x8C300122, // 00B3 GETMET R12 R0 K34 + 0x5C381600, // 00B4 MOVE R14 R11 + 0x7C300400, // 00B5 CALL R12 2 + 0x60340010, // 00B6 GETGBL R13 G16 + 0x5C381800, // 00B7 MOVE R14 R12 + 0x7C340200, // 00B8 CALL R13 1 + 0xA8020007, // 00B9 EXBLK 0 #00C2 + 0x5C381A00, // 00BA MOVE R14 R13 + 0x7C380000, // 00BB CALL R14 0 + 0x603C0008, // 00BC GETGBL R15 G8 + 0x5C400600, // 00BD MOVE R16 R3 + 0x7C3C0200, // 00BE CALL R15 1 + 0x98081E0E, // 00BF SETIDX R2 R15 R14 + 0x000C0701, // 00C0 ADD R3 R3 K1 + 0x7001FFF7, // 00C1 JMP #00BA + 0x58340023, // 00C2 LDCONST R13 K35 + 0xAC340200, // 00C3 CATCH R13 1 0 + 0xB0080000, // 00C4 RAISE 2 R0 R0 + 0x80040400, // 00C5 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: mdns_announce_PASE +********************************************************************/ +be_local_closure(Matter_Device_mdns_announce_PASE, /* name */ + be_nested_proto( + 12, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[41]) { /* constants */ + /* K0 */ be_nested_str_weak(mdns), + /* K1 */ be_nested_str_weak(crypto), + /* K2 */ be_nested_str_weak(VP), + /* K3 */ be_nested_str_weak(vendorid), + /* K4 */ be_nested_str_weak(_X2B), + /* K5 */ be_nested_str_weak(productid), + /* K6 */ be_nested_str_weak(D), + /* K7 */ be_nested_str_weak(commissioning_discriminator), + /* K8 */ be_nested_str_weak(CM), + /* K9 */ be_const_int(1), + /* K10 */ be_nested_str_weak(T), + /* K11 */ be_const_int(0), + /* K12 */ be_nested_str_weak(SII), + /* K13 */ be_nested_str_weak(SAI), + /* K14 */ be_nested_str_weak(commissioning_instance_wifi), + /* K15 */ be_nested_str_weak(random), + /* K16 */ be_nested_str_weak(tohex), + /* K17 */ be_nested_str_weak(commissioning_instance_eth), + /* K18 */ be_nested_str_weak(hostname_eth), + /* K19 */ be_nested_str_weak(add_service), + /* K20 */ be_nested_str_weak(_matterc), + /* K21 */ be_nested_str_weak(_udp), + /* K22 */ be_nested_str_weak(mdns_pase_eth), + /* K23 */ be_nested_str_weak(tasmota), + /* K24 */ be_nested_str_weak(log), + /* K25 */ be_nested_str_weak(MTR_X3A_X20announce_X20mDNS_X20on_X20_X25s_X20_X27_X25s_X27_X20ptr_X20to_X20_X60_X25s_X2Elocal_X60), + /* K26 */ be_nested_str_weak(eth), + /* K27 */ be_const_int(2), + /* K28 */ be_nested_str_weak(_L), + /* K29 */ be_nested_str_weak(MTR_X3A_X20adding_X20subtype_X3A_X20), + /* K30 */ be_const_int(3), + /* K31 */ be_nested_str_weak(add_subtype), + /* K32 */ be_nested_str_weak(_S), + /* K33 */ be_nested_str_weak(_V), + /* K34 */ be_nested_str_weak(_CM1), + /* K35 */ be_nested_str_weak(hostname_wifi), + /* K36 */ be_nested_str_weak(mdns_pase_wifi), + /* K37 */ be_nested_str_weak(MTR_X3A_X20starting_X20mDNS_X20on_X20_X25s_X20_X27_X25s_X27_X20ptr_X20to_X20_X60_X25s_X2Elocal_X60), + /* K38 */ be_nested_str_weak(wifi), + /* K39 */ be_nested_str_weak(MTR_X3A_X20Exception), + /* K40 */ be_nested_str_weak(_X7C), + }), + be_str_weak(mdns_announce_PASE), + &be_const_str_solidified, + ( &(const binstruction[236]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xA40A0200, // 0001 IMPORT R2 K1 + 0x600C0013, // 0002 GETGBL R3 G19 + 0x7C0C0000, // 0003 CALL R3 0 + 0x60100008, // 0004 GETGBL R4 G8 + 0x88140103, // 0005 GETMBR R5 R0 K3 + 0x7C100200, // 0006 CALL R4 1 + 0x00100904, // 0007 ADD R4 R4 K4 + 0x60140008, // 0008 GETGBL R5 G8 + 0x88180105, // 0009 GETMBR R6 R0 K5 + 0x7C140200, // 000A CALL R5 1 + 0x00100805, // 000B ADD R4 R4 R5 + 0x980E0404, // 000C SETIDX R3 K2 R4 + 0x88100107, // 000D GETMBR R4 R0 K7 + 0x980E0C04, // 000E SETIDX R3 K6 R4 + 0x980E1109, // 000F SETIDX R3 K8 K9 + 0x980E150B, // 0010 SETIDX R3 K10 K11 + 0x54121387, // 0011 LDINT R4 5000 + 0x980E1804, // 0012 SETIDX R3 K12 R4 + 0x5412012B, // 0013 LDINT R4 300 + 0x980E1A04, // 0014 SETIDX R3 K13 R4 + 0x8C10050F, // 0015 GETMET R4 R2 K15 + 0x541A0007, // 0016 LDINT R6 8 + 0x7C100400, // 0017 CALL R4 2 + 0x8C100910, // 0018 GETMET R4 R4 K16 + 0x7C100200, // 0019 CALL R4 1 + 0x90021C04, // 001A SETMBR R0 K14 R4 + 0x8C10050F, // 001B GETMET R4 R2 K15 + 0x541A0007, // 001C LDINT R6 8 + 0x7C100400, // 001D CALL R4 2 + 0x8C100910, // 001E GETMET R4 R4 K16 + 0x7C100200, // 001F CALL R4 1 + 0x90022204, // 0020 SETMBR R0 K17 R4 + 0xA80200B7, // 0021 EXBLK 0 #00DA + 0x88100112, // 0022 GETMBR R4 R0 K18 + 0x78120058, // 0023 JMPF R4 #007D + 0x8C100313, // 0024 GETMET R4 R1 K19 + 0x58180014, // 0025 LDCONST R6 K20 + 0x581C0015, // 0026 LDCONST R7 K21 + 0x542215A3, // 0027 LDINT R8 5540 + 0x5C240600, // 0028 MOVE R9 R3 + 0x88280111, // 0029 GETMBR R10 R0 K17 + 0x882C0112, // 002A GETMBR R11 R0 K18 + 0x7C100E00, // 002B CALL R4 7 + 0x50100200, // 002C LDBOOL R4 1 0 + 0x90022C04, // 002D SETMBR R0 K22 R4 + 0xB8122E00, // 002E GETNGBL R4 K23 + 0x8C100918, // 002F GETMET R4 R4 K24 + 0x60180018, // 0030 GETGBL R6 G24 + 0x581C0019, // 0031 LDCONST R7 K25 + 0x5820001A, // 0032 LDCONST R8 K26 + 0x88240111, // 0033 GETMBR R9 R0 K17 + 0x88280112, // 0034 GETMBR R10 R0 K18 + 0x7C180800, // 0035 CALL R6 4 + 0x581C001B, // 0036 LDCONST R7 K27 + 0x7C100600, // 0037 CALL R4 3 + 0x60100008, // 0038 GETGBL R4 G8 + 0x88140107, // 0039 GETMBR R5 R0 K7 + 0x541A0FFE, // 003A LDINT R6 4095 + 0x2C140A06, // 003B AND R5 R5 R6 + 0x7C100200, // 003C CALL R4 1 + 0x00123804, // 003D ADD R4 K28 R4 + 0xB8162E00, // 003E GETNGBL R5 K23 + 0x8C140B18, // 003F GETMET R5 R5 K24 + 0x001E3A04, // 0040 ADD R7 K29 R4 + 0x5820001E, // 0041 LDCONST R8 K30 + 0x7C140600, // 0042 CALL R5 3 + 0x8C14031F, // 0043 GETMET R5 R1 K31 + 0x581C0014, // 0044 LDCONST R7 K20 + 0x58200015, // 0045 LDCONST R8 K21 + 0x88240111, // 0046 GETMBR R9 R0 K17 + 0x88280112, // 0047 GETMBR R10 R0 K18 + 0x5C2C0800, // 0048 MOVE R11 R4 + 0x7C140C00, // 0049 CALL R5 6 + 0x60140008, // 004A GETGBL R5 G8 + 0x88180107, // 004B GETMBR R6 R0 K7 + 0x541E0EFF, // 004C LDINT R7 3840 + 0x2C180C07, // 004D AND R6 R6 R7 + 0x541E0007, // 004E LDINT R7 8 + 0x3C180C07, // 004F SHR R6 R6 R7 + 0x7C140200, // 0050 CALL R5 1 + 0x00164005, // 0051 ADD R5 K32 R5 + 0x5C100A00, // 0052 MOVE R4 R5 + 0xB8162E00, // 0053 GETNGBL R5 K23 + 0x8C140B18, // 0054 GETMET R5 R5 K24 + 0x001E3A04, // 0055 ADD R7 K29 R4 + 0x5820001E, // 0056 LDCONST R8 K30 + 0x7C140600, // 0057 CALL R5 3 + 0x8C14031F, // 0058 GETMET R5 R1 K31 + 0x581C0014, // 0059 LDCONST R7 K20 + 0x58200015, // 005A LDCONST R8 K21 + 0x88240111, // 005B GETMBR R9 R0 K17 + 0x88280112, // 005C GETMBR R10 R0 K18 + 0x5C2C0800, // 005D MOVE R11 R4 + 0x7C140C00, // 005E CALL R5 6 + 0x60140008, // 005F GETGBL R5 G8 + 0x88180103, // 0060 GETMBR R6 R0 K3 + 0x7C140200, // 0061 CALL R5 1 + 0x00164205, // 0062 ADD R5 K33 R5 + 0x5C100A00, // 0063 MOVE R4 R5 + 0xB8162E00, // 0064 GETNGBL R5 K23 + 0x8C140B18, // 0065 GETMET R5 R5 K24 + 0x001E3A04, // 0066 ADD R7 K29 R4 + 0x5820001E, // 0067 LDCONST R8 K30 + 0x7C140600, // 0068 CALL R5 3 + 0x8C14031F, // 0069 GETMET R5 R1 K31 + 0x581C0014, // 006A LDCONST R7 K20 + 0x58200015, // 006B LDCONST R8 K21 + 0x88240111, // 006C GETMBR R9 R0 K17 + 0x88280112, // 006D GETMBR R10 R0 K18 + 0x5C2C0800, // 006E MOVE R11 R4 + 0x7C140C00, // 006F CALL R5 6 + 0x58100022, // 0070 LDCONST R4 K34 + 0xB8162E00, // 0071 GETNGBL R5 K23 + 0x8C140B18, // 0072 GETMET R5 R5 K24 + 0x001E3A04, // 0073 ADD R7 K29 R4 + 0x5820001E, // 0074 LDCONST R8 K30 + 0x7C140600, // 0075 CALL R5 3 + 0x8C14031F, // 0076 GETMET R5 R1 K31 + 0x581C0014, // 0077 LDCONST R7 K20 + 0x58200015, // 0078 LDCONST R8 K21 + 0x88240111, // 0079 GETMBR R9 R0 K17 + 0x88280112, // 007A GETMBR R10 R0 K18 + 0x5C2C0800, // 007B MOVE R11 R4 + 0x7C140C00, // 007C CALL R5 6 + 0x88100123, // 007D GETMBR R4 R0 K35 + 0x78120058, // 007E JMPF R4 #00D8 + 0x8C100313, // 007F GETMET R4 R1 K19 + 0x58180014, // 0080 LDCONST R6 K20 + 0x581C0015, // 0081 LDCONST R7 K21 + 0x542215A3, // 0082 LDINT R8 5540 + 0x5C240600, // 0083 MOVE R9 R3 + 0x8828010E, // 0084 GETMBR R10 R0 K14 + 0x882C0123, // 0085 GETMBR R11 R0 K35 + 0x7C100E00, // 0086 CALL R4 7 + 0x50100200, // 0087 LDBOOL R4 1 0 + 0x90024804, // 0088 SETMBR R0 K36 R4 + 0xB8122E00, // 0089 GETNGBL R4 K23 + 0x8C100918, // 008A GETMET R4 R4 K24 + 0x60180018, // 008B GETGBL R6 G24 + 0x581C0025, // 008C LDCONST R7 K37 + 0x58200026, // 008D LDCONST R8 K38 + 0x8824010E, // 008E GETMBR R9 R0 K14 + 0x88280123, // 008F GETMBR R10 R0 K35 + 0x7C180800, // 0090 CALL R6 4 + 0x581C001E, // 0091 LDCONST R7 K30 + 0x7C100600, // 0092 CALL R4 3 + 0x60100008, // 0093 GETGBL R4 G8 + 0x88140107, // 0094 GETMBR R5 R0 K7 + 0x541A0FFE, // 0095 LDINT R6 4095 + 0x2C140A06, // 0096 AND R5 R5 R6 + 0x7C100200, // 0097 CALL R4 1 + 0x00123804, // 0098 ADD R4 K28 R4 + 0xB8162E00, // 0099 GETNGBL R5 K23 + 0x8C140B18, // 009A GETMET R5 R5 K24 + 0x001E3A04, // 009B ADD R7 K29 R4 + 0x5820001E, // 009C LDCONST R8 K30 + 0x7C140600, // 009D CALL R5 3 + 0x8C14031F, // 009E GETMET R5 R1 K31 + 0x581C0014, // 009F LDCONST R7 K20 + 0x58200015, // 00A0 LDCONST R8 K21 + 0x8824010E, // 00A1 GETMBR R9 R0 K14 + 0x88280123, // 00A2 GETMBR R10 R0 K35 + 0x5C2C0800, // 00A3 MOVE R11 R4 + 0x7C140C00, // 00A4 CALL R5 6 + 0x60140008, // 00A5 GETGBL R5 G8 + 0x88180107, // 00A6 GETMBR R6 R0 K7 + 0x541E0EFF, // 00A7 LDINT R7 3840 + 0x2C180C07, // 00A8 AND R6 R6 R7 + 0x541E0007, // 00A9 LDINT R7 8 + 0x3C180C07, // 00AA SHR R6 R6 R7 + 0x7C140200, // 00AB CALL R5 1 + 0x00164005, // 00AC ADD R5 K32 R5 + 0x5C100A00, // 00AD MOVE R4 R5 + 0xB8162E00, // 00AE GETNGBL R5 K23 + 0x8C140B18, // 00AF GETMET R5 R5 K24 + 0x001E3A04, // 00B0 ADD R7 K29 R4 + 0x5820001E, // 00B1 LDCONST R8 K30 + 0x7C140600, // 00B2 CALL R5 3 + 0x8C14031F, // 00B3 GETMET R5 R1 K31 + 0x581C0014, // 00B4 LDCONST R7 K20 + 0x58200015, // 00B5 LDCONST R8 K21 + 0x8824010E, // 00B6 GETMBR R9 R0 K14 + 0x88280123, // 00B7 GETMBR R10 R0 K35 + 0x5C2C0800, // 00B8 MOVE R11 R4 + 0x7C140C00, // 00B9 CALL R5 6 + 0x60140008, // 00BA GETGBL R5 G8 + 0x88180103, // 00BB GETMBR R6 R0 K3 + 0x7C140200, // 00BC CALL R5 1 + 0x00164205, // 00BD ADD R5 K33 R5 + 0x5C100A00, // 00BE MOVE R4 R5 + 0xB8162E00, // 00BF GETNGBL R5 K23 + 0x8C140B18, // 00C0 GETMET R5 R5 K24 + 0x001E3A04, // 00C1 ADD R7 K29 R4 + 0x5820001E, // 00C2 LDCONST R8 K30 + 0x7C140600, // 00C3 CALL R5 3 + 0x8C14031F, // 00C4 GETMET R5 R1 K31 + 0x581C0014, // 00C5 LDCONST R7 K20 + 0x58200015, // 00C6 LDCONST R8 K21 + 0x8824010E, // 00C7 GETMBR R9 R0 K14 + 0x88280123, // 00C8 GETMBR R10 R0 K35 + 0x5C2C0800, // 00C9 MOVE R11 R4 + 0x7C140C00, // 00CA CALL R5 6 + 0x58100022, // 00CB LDCONST R4 K34 + 0xB8162E00, // 00CC GETNGBL R5 K23 + 0x8C140B18, // 00CD GETMET R5 R5 K24 + 0x001E3A04, // 00CE ADD R7 K29 R4 + 0x5820001E, // 00CF LDCONST R8 K30 + 0x7C140600, // 00D0 CALL R5 3 + 0x8C14031F, // 00D1 GETMET R5 R1 K31 + 0x581C0014, // 00D2 LDCONST R7 K20 + 0x58200015, // 00D3 LDCONST R8 K21 + 0x8824010E, // 00D4 GETMBR R9 R0 K14 + 0x88280123, // 00D5 GETMBR R10 R0 K35 + 0x5C2C0800, // 00D6 MOVE R11 R4 + 0x7C140C00, // 00D7 CALL R5 6 + 0xA8040001, // 00D8 EXBLK 1 1 + 0x70020010, // 00D9 JMP #00EB + 0xAC100002, // 00DA CATCH R4 0 2 + 0x7002000D, // 00DB JMP #00EA + 0xB81A2E00, // 00DC GETNGBL R6 K23 + 0x8C180D18, // 00DD GETMET R6 R6 K24 + 0x60200008, // 00DE GETGBL R8 G8 + 0x5C240800, // 00DF MOVE R9 R4 + 0x7C200200, // 00E0 CALL R8 1 + 0x00224E08, // 00E1 ADD R8 K39 R8 + 0x00201128, // 00E2 ADD R8 R8 K40 + 0x60240008, // 00E3 GETGBL R9 G8 + 0x5C280A00, // 00E4 MOVE R10 R5 + 0x7C240200, // 00E5 CALL R9 1 + 0x00201009, // 00E6 ADD R8 R8 R9 + 0x5824001B, // 00E7 LDCONST R9 K27 + 0x7C180600, // 00E8 CALL R6 3 + 0x70020000, // 00E9 JMP #00EB + 0xB0080000, // 00EA RAISE 2 R0 R0 + 0x80000000, // 00EB RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: clean_remotes +********************************************************************/ +be_local_closure(Matter_Device_clean_remotes, /* name */ + be_nested_proto( + 10, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[18]) { /* constants */ + /* K0 */ be_nested_str_weak(introspect), + /* K1 */ be_nested_str_weak(http_remotes), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(stop_iteration), + /* K4 */ be_nested_str_weak(plugins), + /* K5 */ be_nested_str_weak(get), + /* K6 */ be_nested_str_weak(http_remote), + /* K7 */ be_nested_str_weak(find), + /* K8 */ be_const_int(1), + /* K9 */ be_nested_str_weak(keys), + /* K10 */ be_nested_str_weak(push), + /* K11 */ be_nested_str_weak(tasmota), + /* K12 */ be_nested_str_weak(log), + /* K13 */ be_nested_str_weak(MTR_X3A_X20remove_X20unused_X20remote_X3A_X20), + /* K14 */ be_nested_str_weak(addr), + /* K15 */ be_const_int(3), + /* K16 */ be_nested_str_weak(close), + /* K17 */ be_nested_str_weak(remove), + }), + be_str_weak(clean_remotes), + &be_const_str_solidified, + ( &(const binstruction[81]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x88080101, // 0001 GETMBR R2 R0 K1 + 0x780A004C, // 0002 JMPF R2 #0050 + 0x60080013, // 0003 GETGBL R2 G19 + 0x7C080000, // 0004 CALL R2 0 + 0x600C0010, // 0005 GETGBL R3 G16 + 0x88100101, // 0006 GETMBR R4 R0 K1 + 0x7C0C0200, // 0007 CALL R3 1 + 0xA8020003, // 0008 EXBLK 0 #000D + 0x5C100600, // 0009 MOVE R4 R3 + 0x7C100000, // 000A CALL R4 0 + 0x98080902, // 000B SETIDX R2 R4 K2 + 0x7001FFFB, // 000C JMP #0009 + 0x580C0003, // 000D LDCONST R3 K3 + 0xAC0C0200, // 000E CATCH R3 1 0 + 0xB0080000, // 000F RAISE 2 R0 R0 + 0x600C0010, // 0010 GETGBL R3 G16 + 0x88100104, // 0011 GETMBR R4 R0 K4 + 0x7C0C0200, // 0012 CALL R3 1 + 0xA802000F, // 0013 EXBLK 0 #0024 + 0x5C100600, // 0014 MOVE R4 R3 + 0x7C100000, // 0015 CALL R4 0 + 0x8C140305, // 0016 GETMET R5 R1 K5 + 0x5C1C0800, // 0017 MOVE R7 R4 + 0x58200006, // 0018 LDCONST R8 K6 + 0x7C140600, // 0019 CALL R5 3 + 0x4C180000, // 001A LDNIL R6 + 0x20180A06, // 001B NE R6 R5 R6 + 0x781A0005, // 001C JMPF R6 #0023 + 0x8C180507, // 001D GETMET R6 R2 K7 + 0x5C200A00, // 001E MOVE R8 R5 + 0x58240002, // 001F LDCONST R9 K2 + 0x7C180600, // 0020 CALL R6 3 + 0x00180D08, // 0021 ADD R6 R6 K8 + 0x98080A06, // 0022 SETIDX R2 R5 R6 + 0x7001FFEF, // 0023 JMP #0014 + 0x580C0003, // 0024 LDCONST R3 K3 + 0xAC0C0200, // 0025 CATCH R3 1 0 + 0xB0080000, // 0026 RAISE 2 R0 R0 + 0x600C0012, // 0027 GETGBL R3 G18 + 0x7C0C0000, // 0028 CALL R3 0 + 0x60100010, // 0029 GETGBL R4 G16 + 0x8C140509, // 002A GETMET R5 R2 K9 + 0x7C140200, // 002B CALL R5 1 + 0x7C100200, // 002C CALL R4 1 + 0xA8020008, // 002D EXBLK 0 #0037 + 0x5C140800, // 002E MOVE R5 R4 + 0x7C140000, // 002F CALL R5 0 + 0x94180405, // 0030 GETIDX R6 R2 R5 + 0x1C180D02, // 0031 EQ R6 R6 K2 + 0x781A0002, // 0032 JMPF R6 #0036 + 0x8C18070A, // 0033 GETMET R6 R3 K10 + 0x5C200A00, // 0034 MOVE R8 R5 + 0x7C180400, // 0035 CALL R6 2 + 0x7001FFF6, // 0036 JMP #002E + 0x58100003, // 0037 LDCONST R4 K3 + 0xAC100200, // 0038 CATCH R4 1 0 + 0xB0080000, // 0039 RAISE 2 R0 R0 + 0x60100010, // 003A GETGBL R4 G16 + 0x5C140600, // 003B MOVE R5 R3 + 0x7C100200, // 003C CALL R4 1 + 0xA802000E, // 003D EXBLK 0 #004D + 0x5C140800, // 003E MOVE R5 R4 + 0x7C140000, // 003F CALL R5 0 + 0xB81A1600, // 0040 GETNGBL R6 K11 + 0x8C180D0C, // 0041 GETMET R6 R6 K12 + 0x88200B0E, // 0042 GETMBR R8 R5 K14 + 0x00221A08, // 0043 ADD R8 K13 R8 + 0x5824000F, // 0044 LDCONST R9 K15 + 0x7C180600, // 0045 CALL R6 3 + 0x8C180B10, // 0046 GETMET R6 R5 K16 + 0x7C180200, // 0047 CALL R6 1 + 0x88180101, // 0048 GETMBR R6 R0 K1 + 0x8C180D11, // 0049 GETMET R6 R6 K17 + 0x88200B0E, // 004A GETMBR R8 R5 K14 + 0x7C180400, // 004B CALL R6 2 + 0x7001FFF0, // 004C JMP #003E + 0x58100003, // 004D LDCONST R4 K3 + 0xAC100200, // 004E CATCH R4 1 0 + 0xB0080000, // 004F RAISE 2 R0 R0 + 0x80000000, // 0050 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: every_250ms +********************************************************************/ +be_local_closure(Matter_Device_every_250ms, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(message_handler), + /* K1 */ be_nested_str_weak(every_250ms), + /* K2 */ be_nested_str_weak(read_sensors_scheduler), + /* K3 */ be_const_int(0), + /* K4 */ be_nested_str_weak(plugins), + /* K5 */ be_const_int(1), + }), + be_str_weak(every_250ms), + &be_const_str_solidified, + ( &(const binstruction[18]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x8C040102, // 0003 GETMET R1 R0 K2 + 0x7C040200, // 0004 CALL R1 1 + 0x58040003, // 0005 LDCONST R1 K3 + 0x6008000C, // 0006 GETGBL R2 G12 + 0x880C0104, // 0007 GETMBR R3 R0 K4 + 0x7C080200, // 0008 CALL R2 1 + 0x14080202, // 0009 LT R2 R1 R2 + 0x780A0005, // 000A JMPF R2 #0011 + 0x88080104, // 000B GETMBR R2 R0 K4 + 0x94080401, // 000C GETIDX R2 R2 R1 + 0x8C080501, // 000D GETMET R2 R2 K1 + 0x7C080200, // 000E CALL R2 1 + 0x00040305, // 000F ADD R1 R1 K5 + 0x7001FFF4, // 0010 JMP #0006 + 0x80000000, // 0011 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: read_sensors_scheduler +********************************************************************/ +be_local_closure(Matter_Device_read_sensors_scheduler, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str_weak(probe_sensor_time), + /* K1 */ be_nested_str_weak(probe_sensor_timestamp), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(tasmota), + /* K4 */ be_nested_str_weak(time_reached), + /* K5 */ be_nested_str_weak(_trigger_read_sensors), + /* K6 */ be_nested_str_weak(millis), + }), + be_str_weak(read_sensors_scheduler), + &be_const_str_solidified, + ( &(const binstruction[21]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x1C040202, // 0002 EQ R1 R1 R2 + 0x78060000, // 0003 JMPF R1 #0005 + 0x80000200, // 0004 RET 0 + 0x88040101, // 0005 GETMBR R1 R0 K1 + 0x1C040302, // 0006 EQ R1 R1 K2 + 0x74060004, // 0007 JMPT R1 #000D + 0xB8060600, // 0008 GETNGBL R1 K3 + 0x8C040304, // 0009 GETMET R1 R1 K4 + 0x880C0101, // 000A GETMBR R3 R0 K1 + 0x7C040400, // 000B CALL R1 2 + 0x78060006, // 000C JMPF R1 #0014 + 0x8C040105, // 000D GETMET R1 R0 K5 + 0x7C040200, // 000E CALL R1 1 + 0xB8060600, // 000F GETNGBL R1 K3 + 0x8C040306, // 0010 GETMET R1 R1 K6 + 0x880C0100, // 0011 GETMBR R3 R0 K0 + 0x7C040400, // 0012 CALL R1 2 + 0x90020201, // 0013 SETMBR R0 K1 R1 + 0x80000000, // 0014 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: mdns_announce_op_discovery +********************************************************************/ +be_local_closure(Matter_Device_mdns_announce_op_discovery, /* name */ + be_nested_proto( + 14, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[27]) { /* constants */ + /* K0 */ be_nested_str_weak(mdns), + /* K1 */ be_nested_str_weak(get_device_id), + /* K2 */ be_nested_str_weak(copy), + /* K3 */ be_nested_str_weak(reverse), + /* K4 */ be_nested_str_weak(get_fabric_compressed), + /* K5 */ be_nested_str_weak(tohex), + /* K6 */ be_nested_str_weak(_X2D), + /* K7 */ be_nested_str_weak(tasmota), + /* K8 */ be_nested_str_weak(log), + /* K9 */ be_nested_str_weak(MTR_X3A_X20Operational_X20Discovery_X20node_X20_X3D_X20), + /* K10 */ be_const_int(3), + /* K11 */ be_nested_str_weak(eth), + /* K12 */ be_nested_str_weak(find), + /* K13 */ be_nested_str_weak(up), + /* K14 */ be_nested_str_weak(MTR_X3A_X20adding_X20mDNS_X20on_X20_X25s_X20_X27_X25s_X27_X20ptr_X20to_X20_X60_X25s_X2Elocal_X60), + /* K15 */ be_nested_str_weak(hostname_eth), + /* K16 */ be_nested_str_weak(add_service), + /* K17 */ be_nested_str_weak(_matter), + /* K18 */ be_nested_str_weak(_tcp), + /* K19 */ be_nested_str_weak(_I), + /* K20 */ be_nested_str_weak(MTR_X3A_X20adding_X20subtype_X3A_X20), + /* K21 */ be_nested_str_weak(add_subtype), + /* K22 */ be_nested_str_weak(wifi), + /* K23 */ be_nested_str_weak(hostname_wifi), + /* K24 */ be_nested_str_weak(MTR_X3A_X20Exception), + /* K25 */ be_nested_str_weak(_X7C), + /* K26 */ be_const_int(2), + }), + be_str_weak(mdns_announce_op_discovery), + &be_const_str_solidified, + ( &(const binstruction[121]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0xA8020064, // 0001 EXBLK 0 #0067 + 0x8C0C0301, // 0002 GETMET R3 R1 K1 + 0x7C0C0200, // 0003 CALL R3 1 + 0x8C0C0702, // 0004 GETMET R3 R3 K2 + 0x7C0C0200, // 0005 CALL R3 1 + 0x8C0C0703, // 0006 GETMET R3 R3 K3 + 0x7C0C0200, // 0007 CALL R3 1 + 0x8C100304, // 0008 GETMET R4 R1 K4 + 0x7C100200, // 0009 CALL R4 1 + 0x8C140905, // 000A GETMET R5 R4 K5 + 0x7C140200, // 000B CALL R5 1 + 0x00140B06, // 000C ADD R5 R5 K6 + 0x8C180705, // 000D GETMET R6 R3 K5 + 0x7C180200, // 000E CALL R6 1 + 0x00140A06, // 000F ADD R5 R5 R6 + 0xB81A0E00, // 0010 GETNGBL R6 K7 + 0x8C180D08, // 0011 GETMET R6 R6 K8 + 0x00221205, // 0012 ADD R8 K9 R5 + 0x5824000A, // 0013 LDCONST R9 K10 + 0x7C180600, // 0014 CALL R6 3 + 0xB81A0E00, // 0015 GETNGBL R6 K7 + 0x8C180D0B, // 0016 GETMET R6 R6 K11 + 0x7C180200, // 0017 CALL R6 1 + 0x8C180D0C, // 0018 GETMET R6 R6 K12 + 0x5820000D, // 0019 LDCONST R8 K13 + 0x7C180400, // 001A CALL R6 2 + 0x781A0020, // 001B JMPF R6 #003D + 0xB81A0E00, // 001C GETNGBL R6 K7 + 0x8C180D08, // 001D GETMET R6 R6 K8 + 0x60200018, // 001E GETGBL R8 G24 + 0x5824000E, // 001F LDCONST R9 K14 + 0x5828000B, // 0020 LDCONST R10 K11 + 0x5C2C0A00, // 0021 MOVE R11 R5 + 0x8830010F, // 0022 GETMBR R12 R0 K15 + 0x7C200800, // 0023 CALL R8 4 + 0x5824000A, // 0024 LDCONST R9 K10 + 0x7C180600, // 0025 CALL R6 3 + 0x8C180510, // 0026 GETMET R6 R2 K16 + 0x58200011, // 0027 LDCONST R8 K17 + 0x58240012, // 0028 LDCONST R9 K18 + 0x542A15A3, // 0029 LDINT R10 5540 + 0x4C2C0000, // 002A LDNIL R11 + 0x5C300A00, // 002B MOVE R12 R5 + 0x8834010F, // 002C GETMBR R13 R0 K15 + 0x7C180E00, // 002D CALL R6 7 + 0x8C180905, // 002E GETMET R6 R4 K5 + 0x7C180200, // 002F CALL R6 1 + 0x001A2606, // 0030 ADD R6 K19 R6 + 0xB81E0E00, // 0031 GETNGBL R7 K7 + 0x8C1C0F08, // 0032 GETMET R7 R7 K8 + 0x00262806, // 0033 ADD R9 K20 R6 + 0x5828000A, // 0034 LDCONST R10 K10 + 0x7C1C0600, // 0035 CALL R7 3 + 0x8C1C0515, // 0036 GETMET R7 R2 K21 + 0x58240011, // 0037 LDCONST R9 K17 + 0x58280012, // 0038 LDCONST R10 K18 + 0x5C2C0A00, // 0039 MOVE R11 R5 + 0x8830010F, // 003A GETMBR R12 R0 K15 + 0x5C340C00, // 003B MOVE R13 R6 + 0x7C1C0C00, // 003C CALL R7 6 + 0xB81A0E00, // 003D GETNGBL R6 K7 + 0x8C180D16, // 003E GETMET R6 R6 K22 + 0x7C180200, // 003F CALL R6 1 + 0x8C180D0C, // 0040 GETMET R6 R6 K12 + 0x5820000D, // 0041 LDCONST R8 K13 + 0x7C180400, // 0042 CALL R6 2 + 0x781A0020, // 0043 JMPF R6 #0065 + 0xB81A0E00, // 0044 GETNGBL R6 K7 + 0x8C180D08, // 0045 GETMET R6 R6 K8 + 0x60200018, // 0046 GETGBL R8 G24 + 0x5824000E, // 0047 LDCONST R9 K14 + 0x58280016, // 0048 LDCONST R10 K22 + 0x5C2C0A00, // 0049 MOVE R11 R5 + 0x88300117, // 004A GETMBR R12 R0 K23 + 0x7C200800, // 004B CALL R8 4 + 0x5824000A, // 004C LDCONST R9 K10 + 0x7C180600, // 004D CALL R6 3 + 0x8C180510, // 004E GETMET R6 R2 K16 + 0x58200011, // 004F LDCONST R8 K17 + 0x58240012, // 0050 LDCONST R9 K18 + 0x542A15A3, // 0051 LDINT R10 5540 + 0x4C2C0000, // 0052 LDNIL R11 + 0x5C300A00, // 0053 MOVE R12 R5 + 0x88340117, // 0054 GETMBR R13 R0 K23 + 0x7C180E00, // 0055 CALL R6 7 + 0x8C180905, // 0056 GETMET R6 R4 K5 + 0x7C180200, // 0057 CALL R6 1 + 0x001A2606, // 0058 ADD R6 K19 R6 + 0xB81E0E00, // 0059 GETNGBL R7 K7 + 0x8C1C0F08, // 005A GETMET R7 R7 K8 + 0x00262806, // 005B ADD R9 K20 R6 + 0x5828000A, // 005C LDCONST R10 K10 + 0x7C1C0600, // 005D CALL R7 3 + 0x8C1C0515, // 005E GETMET R7 R2 K21 + 0x58240011, // 005F LDCONST R9 K17 + 0x58280012, // 0060 LDCONST R10 K18 + 0x5C2C0A00, // 0061 MOVE R11 R5 + 0x88300117, // 0062 GETMBR R12 R0 K23 + 0x5C340C00, // 0063 MOVE R13 R6 + 0x7C1C0C00, // 0064 CALL R7 6 + 0xA8040001, // 0065 EXBLK 1 1 + 0x70020010, // 0066 JMP #0078 + 0xAC0C0002, // 0067 CATCH R3 0 2 + 0x7002000D, // 0068 JMP #0077 + 0xB8160E00, // 0069 GETNGBL R5 K7 + 0x8C140B08, // 006A GETMET R5 R5 K8 + 0x601C0008, // 006B GETGBL R7 G8 + 0x5C200600, // 006C MOVE R8 R3 + 0x7C1C0200, // 006D CALL R7 1 + 0x001E3007, // 006E ADD R7 K24 R7 + 0x001C0F19, // 006F ADD R7 R7 K25 + 0x60200008, // 0070 GETGBL R8 G8 + 0x5C240800, // 0071 MOVE R9 R4 + 0x7C200200, // 0072 CALL R8 1 + 0x001C0E08, // 0073 ADD R7 R7 R8 + 0x5820001A, // 0074 LDCONST R8 K26 + 0x7C140600, // 0075 CALL R5 3 + 0x70020000, // 0076 JMP #0078 + 0xB0080000, // 0077 RAISE 2 R0 R0 + 0x80000000, // 0078 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: MtrJoin +********************************************************************/ +be_local_closure(Matter_Device_MtrJoin, /* name */ + be_nested_proto( + 8, /* nstack */ + 5, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(start_root_basic_commissioning), + /* K1 */ be_nested_str_weak(stop_basic_commissioning), + /* K2 */ be_nested_str_weak(tasmota), + /* K3 */ be_nested_str_weak(resp_cmnd_done), + }), + be_str_weak(MtrJoin), + &be_const_str_solidified, + ( &(const binstruction[13]) { /* code */ + 0x60140009, // 0000 GETGBL R5 G9 + 0x5C180600, // 0001 MOVE R6 R3 + 0x7C140200, // 0002 CALL R5 1 + 0x78160002, // 0003 JMPF R5 #0007 + 0x8C180100, // 0004 GETMET R6 R0 K0 + 0x7C180200, // 0005 CALL R6 1 + 0x70020001, // 0006 JMP #0009 + 0x8C180101, // 0007 GETMET R6 R0 K1 + 0x7C180200, // 0008 CALL R6 1 + 0xB81A0400, // 0009 GETNGBL R6 K2 + 0x8C180D03, // 000A GETMET R6 R6 K3 + 0x7C180200, // 000B CALL R6 1 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: remove_fabric +********************************************************************/ +be_local_closure(Matter_Device_remove_fabric, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[16]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(log), + /* K2 */ be_nested_str_weak(MTR_X3A_X20removing_X20fabric_X20), + /* K3 */ be_nested_str_weak(get_fabric_id), + /* K4 */ be_nested_str_weak(copy), + /* K5 */ be_nested_str_weak(reverse), + /* K6 */ be_nested_str_weak(tohex), + /* K7 */ be_const_int(2), + /* K8 */ be_nested_str_weak(message_handler), + /* K9 */ be_nested_str_weak(im), + /* K10 */ be_nested_str_weak(subs_shop), + /* K11 */ be_nested_str_weak(remove_by_fabric), + /* K12 */ be_nested_str_weak(mdns_remove_op_discovery), + /* K13 */ be_nested_str_weak(sessions), + /* K14 */ be_nested_str_weak(remove_fabric), + /* K15 */ be_nested_str_weak(save_fabrics), + }), + be_str_weak(remove_fabric), + &be_const_str_solidified, + ( &(const binstruction[33]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x20080202, // 0001 NE R2 R1 R2 + 0x780A0019, // 0002 JMPF R2 #001D + 0xB80A0000, // 0003 GETNGBL R2 K0 + 0x8C080501, // 0004 GETMET R2 R2 K1 + 0x8C100303, // 0005 GETMET R4 R1 K3 + 0x7C100200, // 0006 CALL R4 1 + 0x8C100904, // 0007 GETMET R4 R4 K4 + 0x7C100200, // 0008 CALL R4 1 + 0x8C100905, // 0009 GETMET R4 R4 K5 + 0x7C100200, // 000A CALL R4 1 + 0x8C100906, // 000B GETMET R4 R4 K6 + 0x7C100200, // 000C CALL R4 1 + 0x00120404, // 000D ADD R4 K2 R4 + 0x58140007, // 000E LDCONST R5 K7 + 0x7C080600, // 000F CALL R2 3 + 0x88080108, // 0010 GETMBR R2 R0 K8 + 0x88080509, // 0011 GETMBR R2 R2 K9 + 0x8808050A, // 0012 GETMBR R2 R2 K10 + 0x8C08050B, // 0013 GETMET R2 R2 K11 + 0x5C100200, // 0014 MOVE R4 R1 + 0x7C080400, // 0015 CALL R2 2 + 0x8C08010C, // 0016 GETMET R2 R0 K12 + 0x5C100200, // 0017 MOVE R4 R1 + 0x7C080400, // 0018 CALL R2 2 + 0x8808010D, // 0019 GETMBR R2 R0 K13 + 0x8C08050E, // 001A GETMET R2 R2 K14 + 0x5C100200, // 001B MOVE R4 R1 + 0x7C080400, // 001C CALL R2 2 + 0x8808010D, // 001D GETMBR R2 R0 K13 + 0x8C08050F, // 001E GETMET R2 R2 K15 + 0x7C080200, // 001F CALL R2 1 + 0x80000000, // 0020 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: _compute_pbkdf +********************************************************************/ +be_local_closure(Matter_Device__compute_pbkdf, /* name */ + be_nested_proto( + 13, /* nstack */ + 4, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[10]) { /* constants */ + /* K0 */ be_nested_str_weak(crypto), + /* K1 */ be_nested_str_weak(add), + /* K2 */ be_nested_str_weak(PBKDF2_HMAC_SHA256), + /* K3 */ be_nested_str_weak(derive), + /* K4 */ be_const_int(0), + /* K5 */ be_nested_str_weak(root_w0), + /* K6 */ be_nested_str_weak(EC_P256), + /* K7 */ be_nested_str_weak(mod), + /* K8 */ be_nested_str_weak(root_L), + /* K9 */ be_nested_str_weak(public_key), + }), + be_str_weak(_compute_pbkdf), + &be_const_str_solidified, + ( &(const binstruction[40]) { /* code */ + 0xA4120000, // 0000 IMPORT R4 K0 + 0x60140015, // 0001 GETGBL R5 G21 + 0x7C140000, // 0002 CALL R5 0 + 0x8C140B01, // 0003 GETMET R5 R5 K1 + 0x5C1C0200, // 0004 MOVE R7 R1 + 0x54220003, // 0005 LDINT R8 4 + 0x7C140600, // 0006 CALL R5 3 + 0x8C180902, // 0007 GETMET R6 R4 K2 + 0x7C180200, // 0008 CALL R6 1 + 0x8C180D03, // 0009 GETMET R6 R6 K3 + 0x5C200A00, // 000A MOVE R8 R5 + 0x5C240600, // 000B MOVE R9 R3 + 0x5C280400, // 000C MOVE R10 R2 + 0x542E004F, // 000D LDINT R11 80 + 0x7C180A00, // 000E CALL R6 5 + 0x541E0026, // 000F LDINT R7 39 + 0x401E0807, // 0010 CONNECT R7 K4 R7 + 0x941C0C07, // 0011 GETIDX R7 R6 R7 + 0x54220027, // 0012 LDINT R8 40 + 0x5426004E, // 0013 LDINT R9 79 + 0x40201009, // 0014 CONNECT R8 R8 R9 + 0x94200C08, // 0015 GETIDX R8 R6 R8 + 0x8C240906, // 0016 GETMET R9 R4 K6 + 0x7C240200, // 0017 CALL R9 1 + 0x8C241307, // 0018 GETMET R9 R9 K7 + 0x5C2C0E00, // 0019 MOVE R11 R7 + 0x7C240400, // 001A CALL R9 2 + 0x90020A09, // 001B SETMBR R0 K5 R9 + 0x8C240906, // 001C GETMET R9 R4 K6 + 0x7C240200, // 001D CALL R9 1 + 0x8C241307, // 001E GETMET R9 R9 K7 + 0x5C2C1000, // 001F MOVE R11 R8 + 0x7C240400, // 0020 CALL R9 2 + 0x8C280906, // 0021 GETMET R10 R4 K6 + 0x7C280200, // 0022 CALL R10 1 + 0x8C281509, // 0023 GETMET R10 R10 K9 + 0x5C301200, // 0024 MOVE R12 R9 + 0x7C280400, // 0025 CALL R10 2 + 0x9002100A, // 0026 SETMBR R0 K8 R10 + 0x80000000, // 0027 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: _init_basic_commissioning +********************************************************************/ +be_local_closure(Matter_Device__init_basic_commissioning, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(sessions), + /* K1 */ be_nested_str_weak(count_active_fabrics), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(start_root_basic_commissioning), + }), + be_str_weak(_init_basic_commissioning), + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x1C040302, // 0003 EQ R1 R1 K2 + 0x78060001, // 0004 JMPF R1 #0007 + 0x8C040103, // 0005 GETMET R1 R0 K3 + 0x7C040200, // 0006 CALL R1 1 + 0x80000000, // 0007 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: msg_received +********************************************************************/ +be_local_closure(Matter_Device_msg_received, /* name */ + be_nested_proto( + 9, /* nstack */ + 4, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(message_handler), + /* K1 */ be_nested_str_weak(msg_received), + }), + be_str_weak(msg_received), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x88100100, // 0000 GETMBR R4 R0 K0 + 0x8C100901, // 0001 GETMET R4 R4 K1 + 0x5C180200, // 0002 MOVE R6 R1 + 0x5C1C0400, // 0003 MOVE R7 R2 + 0x5C200600, // 0004 MOVE R8 R3 + 0x7C100800, // 0005 CALL R4 4 + 0x80040800, // 0006 RET 1 R4 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: register_commands +********************************************************************/ +be_local_closure(Matter_Device_register_commands, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 3]) { + be_nested_proto( + 10, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(MtrJoin), + }), + be_str_weak(_X3Clambda_X3E), + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x68100000, // 0000 GETUPV R4 U0 + 0x8C100900, // 0001 GETMET R4 R4 K0 + 0x5C180000, // 0002 MOVE R6 R0 + 0x5C1C0200, // 0003 MOVE R7 R1 + 0x5C200400, // 0004 MOVE R8 R2 + 0x5C240600, // 0005 MOVE R9 R3 + 0x7C100A00, // 0006 CALL R4 5 + 0x80040800, // 0007 RET 1 R4 + }) + ), + be_nested_proto( + 10, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(MtrUpdate), + }), + be_str_weak(_X3Clambda_X3E), + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x68100000, // 0000 GETUPV R4 U0 + 0x8C100900, // 0001 GETMET R4 R4 K0 + 0x5C180000, // 0002 MOVE R6 R0 + 0x5C1C0200, // 0003 MOVE R7 R1 + 0x5C200400, // 0004 MOVE R8 R2 + 0x5C240600, // 0005 MOVE R9 R3 + 0x7C100A00, // 0006 CALL R4 5 + 0x80040800, // 0007 RET 1 R4 + }) + ), + be_nested_proto( + 10, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(MtrInfo), + }), + be_str_weak(_X3Clambda_X3E), + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x68100000, // 0000 GETUPV R4 U0 + 0x8C100900, // 0001 GETMET R4 R4 K0 + 0x5C180000, // 0002 MOVE R6 R0 + 0x5C1C0200, // 0003 MOVE R7 R1 + 0x5C200400, // 0004 MOVE R8 R2 + 0x5C240600, // 0005 MOVE R9 R3 + 0x7C100A00, // 0006 CALL R4 5 + 0x80040800, // 0007 RET 1 R4 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(add_cmd), + /* K2 */ be_nested_str_weak(MtrJoin), + /* K3 */ be_nested_str_weak(MtrUpdate), + /* K4 */ be_nested_str_weak(MtrInfo), + }), + be_str_weak(register_commands), + &be_const_str_solidified, + ( &(const binstruction[17]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x580C0002, // 0002 LDCONST R3 K2 + 0x84100000, // 0003 CLOSURE R4 P0 + 0x7C040600, // 0004 CALL R1 3 + 0xB8060000, // 0005 GETNGBL R1 K0 + 0x8C040301, // 0006 GETMET R1 R1 K1 + 0x580C0003, // 0007 LDCONST R3 K3 + 0x84100001, // 0008 CLOSURE R4 P1 + 0x7C040600, // 0009 CALL R1 3 + 0xB8060000, // 000A GETNGBL R1 K0 + 0x8C040301, // 000B GETMET R1 R1 K1 + 0x580C0004, // 000C LDCONST R3 K4 + 0x84100002, // 000D CLOSURE R4 P2 + 0x7C040600, // 000E CALL R1 3 + 0xA0000000, // 000F CLOSE R0 + 0x80000000, // 0010 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: is_commissioning_open +********************************************************************/ +be_local_closure(Matter_Device_is_commissioning_open, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(commissioning_open), + }), + be_str_weak(is_commissioning_open), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x20040202, // 0002 NE R1 R1 R2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: event_fabrics_saved +********************************************************************/ +be_local_closure(Matter_Device_event_fabrics_saved, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(sessions), + /* K1 */ be_nested_str_weak(count_active_fabrics), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(plugins_persist), + /* K4 */ be_nested_str_weak(save_param), + }), + be_str_weak(event_fabrics_saved), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x24040302, // 0003 GT R1 R1 K2 + 0x78060005, // 0004 JMPF R1 #000B + 0x88040103, // 0005 GETMBR R1 R0 K3 + 0x74060003, // 0006 JMPT R1 #000B + 0x50040200, // 0007 LDBOOL R1 1 0 + 0x90020601, // 0008 SETMBR R0 K3 R1 + 0x8C040104, // 0009 GETMET R1 R0 K4 + 0x7C040200, // 000A CALL R1 1 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: MtrUpdate +********************************************************************/ +be_local_closure(Matter_Device_MtrUpdate, /* name */ + be_nested_proto( + 18, /* nstack */ + 5, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[25]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(resp_cmnd_str), + /* K2 */ be_nested_str_weak(Invalid_X20JSON), + /* K3 */ be_nested_str_weak(find_key_i), + /* K4 */ be_nested_str_weak(Ep), + /* K5 */ be_nested_str_weak(Name), + /* K6 */ be_const_int(0), + /* K7 */ be_nested_str_weak(Invalid_X20_X27Ep_X27_X20attribute), + /* K8 */ be_nested_str_weak(find_plugin_by_endpoint), + /* K9 */ be_nested_str_weak(remove), + /* K10 */ be_nested_str_weak(find_plugin_by_friendly_name), + /* K11 */ be_nested_str_weak(Invalid_X20Device), + /* K12 */ be_nested_str_weak(VIRTUAL), + /* K13 */ be_nested_str_weak(Device_X20is_X20not_X20virtual), + /* K14 */ be_nested_str_weak(consolidate_update_commands), + /* K15 */ be_nested_str_weak(keys), + /* K16 */ be_nested_str_weak(find_list_i), + /* K17 */ be_nested_str_weak(Invalid_X20attribute_X20_X27_X25s_X27), + /* K18 */ be_nested_str_weak(stop_iteration), + /* K19 */ be_nested_str_weak(update_virtual), + /* K20 */ be_nested_str_weak(state_json), + /* K21 */ be_nested_str_weak(_X7B_X22_X25s_X22_X3A_X25s_X7D), + /* K22 */ be_nested_str_weak(resp_cmnd), + /* K23 */ be_nested_str_weak(resp_cmnd_done), + /* K24 */ be_nested_str_weak(Missing_X20_X27Device_X27_X20attribute), + }), + be_str_weak(MtrUpdate), + &be_const_str_solidified, + ( &(const binstruction[126]) { /* code */ + 0x4C140000, // 0000 LDNIL R5 + 0x1C140805, // 0001 EQ R5 R4 R5 + 0x78160004, // 0002 JMPF R5 #0008 + 0xB8160000, // 0003 GETNGBL R5 K0 + 0x8C140B01, // 0004 GETMET R5 R5 K1 + 0x581C0002, // 0005 LDCONST R7 K2 + 0x7C140400, // 0006 CALL R5 2 + 0x80040A00, // 0007 RET 1 R5 + 0xB8160000, // 0008 GETNGBL R5 K0 + 0x8C140B03, // 0009 GETMET R5 R5 K3 + 0x5C1C0800, // 000A MOVE R7 R4 + 0x58200004, // 000B LDCONST R8 K4 + 0x7C140600, // 000C CALL R5 3 + 0xB81A0000, // 000D GETNGBL R6 K0 + 0x8C180D03, // 000E GETMET R6 R6 K3 + 0x5C200800, // 000F MOVE R8 R4 + 0x58240005, // 0010 LDCONST R9 K5 + 0x7C180600, // 0011 CALL R6 3 + 0x74160000, // 0012 JMPT R5 #0014 + 0x781A0064, // 0013 JMPF R6 #0079 + 0x4C1C0000, // 0014 LDNIL R7 + 0x78160010, // 0015 JMPF R5 #0027 + 0x60200009, // 0016 GETGBL R8 G9 + 0x94240805, // 0017 GETIDX R9 R4 R5 + 0x7C200200, // 0018 CALL R8 1 + 0x18241106, // 0019 LE R9 R8 K6 + 0x78260004, // 001A JMPF R9 #0020 + 0xB8260000, // 001B GETNGBL R9 K0 + 0x8C241301, // 001C GETMET R9 R9 K1 + 0x582C0007, // 001D LDCONST R11 K7 + 0x7C240400, // 001E CALL R9 2 + 0x80041200, // 001F RET 1 R9 + 0x8C240108, // 0020 GETMET R9 R0 K8 + 0x5C2C1000, // 0021 MOVE R11 R8 + 0x7C240400, // 0022 CALL R9 2 + 0x5C1C1200, // 0023 MOVE R7 R9 + 0x8C240909, // 0024 GETMET R9 R4 K9 + 0x5C2C0A00, // 0025 MOVE R11 R5 + 0x7C240400, // 0026 CALL R9 2 + 0x781A0009, // 0027 JMPF R6 #0032 + 0x4C200000, // 0028 LDNIL R8 + 0x1C200E08, // 0029 EQ R8 R7 R8 + 0x78220003, // 002A JMPF R8 #002F + 0x8C20010A, // 002B GETMET R8 R0 K10 + 0x94280806, // 002C GETIDX R10 R4 R6 + 0x7C200400, // 002D CALL R8 2 + 0x5C1C1000, // 002E MOVE R7 R8 + 0x8C200909, // 002F GETMET R8 R4 K9 + 0x5C280C00, // 0030 MOVE R10 R6 + 0x7C200400, // 0031 CALL R8 2 + 0x4C200000, // 0032 LDNIL R8 + 0x1C200E08, // 0033 EQ R8 R7 R8 + 0x78220004, // 0034 JMPF R8 #003A + 0xB8220000, // 0035 GETNGBL R8 K0 + 0x8C201101, // 0036 GETMET R8 R8 K1 + 0x5828000B, // 0037 LDCONST R10 K11 + 0x7C200400, // 0038 CALL R8 2 + 0x80041000, // 0039 RET 1 R8 + 0x88200F0C, // 003A GETMBR R8 R7 K12 + 0x74220004, // 003B JMPT R8 #0041 + 0xB8220000, // 003C GETNGBL R8 K0 + 0x8C201101, // 003D GETMET R8 R8 K1 + 0x5828000D, // 003E LDCONST R10 K13 + 0x7C200400, // 003F CALL R8 2 + 0x80041000, // 0040 RET 1 R8 + 0x8C200F0E, // 0041 GETMET R8 R7 K14 + 0x7C200200, // 0042 CALL R8 1 + 0x60240013, // 0043 GETGBL R9 G19 + 0x7C240000, // 0044 CALL R9 0 + 0x60280010, // 0045 GETGBL R10 G16 + 0x8C2C090F, // 0046 GETMET R11 R4 K15 + 0x7C2C0200, // 0047 CALL R11 1 + 0x7C280200, // 0048 CALL R10 1 + 0xA8020016, // 0049 EXBLK 0 #0061 + 0x5C2C1400, // 004A MOVE R11 R10 + 0x7C2C0000, // 004B CALL R11 0 + 0xB8320000, // 004C GETNGBL R12 K0 + 0x8C301910, // 004D GETMET R12 R12 K16 + 0x5C381000, // 004E MOVE R14 R8 + 0x5C3C1600, // 004F MOVE R15 R11 + 0x7C300600, // 0050 CALL R12 3 + 0x4C340000, // 0051 LDNIL R13 + 0x1C34180D, // 0052 EQ R13 R12 R13 + 0x78360008, // 0053 JMPF R13 #005D + 0xB8360000, // 0054 GETNGBL R13 K0 + 0x8C341B01, // 0055 GETMET R13 R13 K1 + 0x603C0018, // 0056 GETGBL R15 G24 + 0x58400011, // 0057 LDCONST R16 K17 + 0x5C441600, // 0058 MOVE R17 R11 + 0x7C3C0400, // 0059 CALL R15 2 + 0x7C340400, // 005A CALL R13 2 + 0xA8040001, // 005B EXBLK 1 1 + 0x80001A00, // 005C RET 0 + 0x9434100C, // 005D GETIDX R13 R8 R12 + 0x9438080B, // 005E GETIDX R14 R4 R11 + 0x98241A0E, // 005F SETIDX R9 R13 R14 + 0x7001FFE8, // 0060 JMP #004A + 0x58280012, // 0061 LDCONST R10 K18 + 0xAC280200, // 0062 CATCH R10 1 0 + 0xB0080000, // 0063 RAISE 2 R0 R0 + 0x8C280F13, // 0064 GETMET R10 R7 K19 + 0x5C301200, // 0065 MOVE R12 R9 + 0x7C280400, // 0066 CALL R10 2 + 0x8C280F14, // 0067 GETMET R10 R7 K20 + 0x7C280200, // 0068 CALL R10 1 + 0x782A000A, // 0069 JMPF R10 #0075 + 0x602C0018, // 006A GETGBL R11 G24 + 0x58300015, // 006B LDCONST R12 K21 + 0x5C340200, // 006C MOVE R13 R1 + 0x5C381400, // 006D MOVE R14 R10 + 0x7C2C0600, // 006E CALL R11 3 + 0xB8320000, // 006F GETNGBL R12 K0 + 0x8C301916, // 0070 GETMET R12 R12 K22 + 0x5C381600, // 0071 MOVE R14 R11 + 0x7C300400, // 0072 CALL R12 2 + 0x80041800, // 0073 RET 1 R12 + 0x70020003, // 0074 JMP #0079 + 0xB82E0000, // 0075 GETNGBL R11 K0 + 0x8C2C1717, // 0076 GETMET R11 R11 K23 + 0x7C2C0200, // 0077 CALL R11 1 + 0x80041600, // 0078 RET 1 R11 + 0xB81E0000, // 0079 GETNGBL R7 K0 + 0x8C1C0F01, // 007A GETMET R7 R7 K1 + 0x58240018, // 007B LDCONST R9 K24 + 0x7C1C0400, // 007C CALL R7 2 + 0x80000000, // 007D RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: find_plugin_by_endpoint +********************************************************************/ +be_local_closure(Matter_Device_find_plugin_by_endpoint, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_weak(plugins), + /* K2 */ be_nested_str_weak(get_endpoint), + /* K3 */ be_const_int(1), + }), + be_str_weak(find_plugin_by_endpoint), + &be_const_str_solidified, + ( &(const binstruction[17]) { /* code */ + 0x58080000, // 0000 LDCONST R2 K0 + 0x600C000C, // 0001 GETGBL R3 G12 + 0x88100101, // 0002 GETMBR R4 R0 K1 + 0x7C0C0200, // 0003 CALL R3 1 + 0x140C0403, // 0004 LT R3 R2 R3 + 0x780E0008, // 0005 JMPF R3 #000F + 0x880C0101, // 0006 GETMBR R3 R0 K1 + 0x940C0602, // 0007 GETIDX R3 R3 R2 + 0x8C100702, // 0008 GETMET R4 R3 K2 + 0x7C100200, // 0009 CALL R4 1 + 0x1C100801, // 000A EQ R4 R4 R1 + 0x78120000, // 000B JMPF R4 #000D + 0x80040600, // 000C RET 1 R3 + 0x00080503, // 000D ADD R2 R2 K3 + 0x7001FFF1, // 000E JMP #0001 + 0x4C0C0000, // 000F LDNIL R3 + 0x80040600, // 0010 RET 1 R3 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start_mdns_announce_hostnames +********************************************************************/ +be_local_closure(Matter_Device_start_mdns_announce_hostnames, /* name */ + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 2]) { + be_nested_proto( + 4, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(_mdns_announce_hostname), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(remove_rule), + /* K3 */ be_nested_str_weak(Wifi_X23Connected), + /* K4 */ be_nested_str_weak(matter_mdns_host), + }), + be_str_weak(_anonymous_), + &be_const_str_solidified, + ( &(const binstruction[10]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x50080000, // 0002 LDBOOL R2 0 0 + 0x7C000400, // 0003 CALL R0 2 + 0xB8020200, // 0004 GETNGBL R0 K1 + 0x8C000102, // 0005 GETMET R0 R0 K2 + 0x58080003, // 0006 LDCONST R2 K3 + 0x580C0004, // 0007 LDCONST R3 K4 + 0x7C000600, // 0008 CALL R0 3 + 0x80000000, // 0009 RET 0 + }) + ), + be_nested_proto( + 4, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(_mdns_announce_hostname), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(remove_rule), + /* K3 */ be_nested_str_weak(Eth_X23Connected), + /* K4 */ be_nested_str_weak(matter_mdns_host), + }), + be_str_weak(_anonymous_), + &be_const_str_solidified, + ( &(const binstruction[10]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x50080200, // 0002 LDBOOL R2 1 0 + 0x7C000400, // 0003 CALL R0 2 + 0xB8020200, // 0004 GETNGBL R0 K1 + 0x8C000102, // 0005 GETMET R0 R0 K2 + 0x58080003, // 0006 LDCONST R2 K3 + 0x580C0004, // 0007 LDCONST R3 K4 + 0x7C000600, // 0008 CALL R0 3 + 0x80000000, // 0009 RET 0 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(wifi), + /* K2 */ be_nested_str_weak(up), + /* K3 */ be_nested_str_weak(_mdns_announce_hostname), + /* K4 */ be_nested_str_weak(add_rule), + /* K5 */ be_nested_str_weak(Wifi_X23Connected), + /* K6 */ be_nested_str_weak(matter_mdns_host), + /* K7 */ be_nested_str_weak(eth), + /* K8 */ be_nested_str_weak(Eth_X23Connected), + }), + be_str_weak(start_mdns_announce_hostnames), + &be_const_str_solidified, + ( &(const binstruction[32]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x94040302, // 0003 GETIDX R1 R1 K2 + 0x78060003, // 0004 JMPF R1 #0009 + 0x8C040103, // 0005 GETMET R1 R0 K3 + 0x500C0000, // 0006 LDBOOL R3 0 0 + 0x7C040400, // 0007 CALL R1 2 + 0x70020005, // 0008 JMP #000F + 0xB8060000, // 0009 GETNGBL R1 K0 + 0x8C040304, // 000A GETMET R1 R1 K4 + 0x580C0005, // 000B LDCONST R3 K5 + 0x84100000, // 000C CLOSURE R4 P0 + 0x58140006, // 000D LDCONST R5 K6 + 0x7C040800, // 000E CALL R1 4 + 0xB8060000, // 000F GETNGBL R1 K0 + 0x8C040307, // 0010 GETMET R1 R1 K7 + 0x7C040200, // 0011 CALL R1 1 + 0x94040302, // 0012 GETIDX R1 R1 K2 + 0x78060003, // 0013 JMPF R1 #0018 + 0x8C040103, // 0014 GETMET R1 R0 K3 + 0x500C0200, // 0015 LDBOOL R3 1 0 + 0x7C040400, // 0016 CALL R1 2 + 0x70020005, // 0017 JMP #001E + 0xB8060000, // 0018 GETNGBL R1 K0 + 0x8C040304, // 0019 GETMET R1 R1 K4 + 0x580C0008, // 001A LDCONST R3 K8 + 0x84100001, // 001B CLOSURE R4 P1 + 0x58140006, // 001C LDCONST R5 K6 + 0x7C040800, // 001D CALL R1 4 + 0xA0000000, // 001E CLOSE R0 + 0x80000000, // 001F RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: every_50ms +********************************************************************/ +be_local_closure(Matter_Device_every_50ms, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(tick), + /* K1 */ be_const_int(1), + }), + be_str_weak(every_50ms), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x00040301, // 0001 ADD R1 R1 K1 + 0x90020001, // 0002 SETMBR R0 K0 R1 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: stop +********************************************************************/ +be_local_closure(Matter_Device_stop, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(remove_driver), + /* K2 */ be_nested_str_weak(udp_server), + /* K3 */ be_nested_str_weak(stop), + }), + be_str_weak(stop), + &be_const_str_solidified, + ( &(const binstruction[10]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C040400, // 0003 CALL R1 2 + 0x88040102, // 0004 GETMBR R1 R0 K2 + 0x78060002, // 0005 JMPF R1 #0009 + 0x88040102, // 0006 GETMBR R1 R0 K2 + 0x8C040303, // 0007 GETMET R1 R1 K3 + 0x7C040200, // 0008 CALL R1 1 + 0x80000000, // 0009 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: mdns_remove_op_discovery +********************************************************************/ +be_local_closure(Matter_Device_mdns_remove_op_discovery, /* name */ + be_nested_proto( + 12, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[23]) { /* constants */ + /* K0 */ be_nested_str_weak(mdns), + /* K1 */ be_nested_str_weak(get_device_id), + /* K2 */ be_nested_str_weak(copy), + /* K3 */ be_nested_str_weak(reverse), + /* K4 */ be_nested_str_weak(get_fabric_compressed), + /* K5 */ be_nested_str_weak(tohex), + /* K6 */ be_nested_str_weak(_X2D), + /* K7 */ be_nested_str_weak(tasmota), + /* K8 */ be_nested_str_weak(eth), + /* K9 */ be_nested_str_weak(find), + /* K10 */ be_nested_str_weak(up), + /* K11 */ be_nested_str_weak(log), + /* K12 */ be_nested_str_weak(MTR_X3A_X20remove_X20mDNS_X20on_X20_X25s_X20_X27_X25s_X27), + /* K13 */ be_const_int(3), + /* K14 */ be_nested_str_weak(remove_service), + /* K15 */ be_nested_str_weak(_matter), + /* K16 */ be_nested_str_weak(_tcp), + /* K17 */ be_nested_str_weak(hostname_eth), + /* K18 */ be_nested_str_weak(wifi), + /* K19 */ be_nested_str_weak(hostname_wifi), + /* K20 */ be_nested_str_weak(MTR_X3A_X20Exception), + /* K21 */ be_nested_str_weak(_X7C), + /* K22 */ be_const_int(2), + }), + be_str_weak(mdns_remove_op_discovery), + &be_const_str_solidified, + ( &(const binstruction[80]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0xA802003B, // 0001 EXBLK 0 #003E + 0x8C0C0301, // 0002 GETMET R3 R1 K1 + 0x7C0C0200, // 0003 CALL R3 1 + 0x8C0C0702, // 0004 GETMET R3 R3 K2 + 0x7C0C0200, // 0005 CALL R3 1 + 0x8C0C0703, // 0006 GETMET R3 R3 K3 + 0x7C0C0200, // 0007 CALL R3 1 + 0x8C100304, // 0008 GETMET R4 R1 K4 + 0x7C100200, // 0009 CALL R4 1 + 0x8C140905, // 000A GETMET R5 R4 K5 + 0x7C140200, // 000B CALL R5 1 + 0x00140B06, // 000C ADD R5 R5 K6 + 0x8C180705, // 000D GETMET R6 R3 K5 + 0x7C180200, // 000E CALL R6 1 + 0x00140A06, // 000F ADD R5 R5 R6 + 0xB81A0E00, // 0010 GETNGBL R6 K7 + 0x8C180D08, // 0011 GETMET R6 R6 K8 + 0x7C180200, // 0012 CALL R6 1 + 0x8C180D09, // 0013 GETMET R6 R6 K9 + 0x5820000A, // 0014 LDCONST R8 K10 + 0x7C180400, // 0015 CALL R6 2 + 0x781A000E, // 0016 JMPF R6 #0026 + 0xB81A0E00, // 0017 GETNGBL R6 K7 + 0x8C180D0B, // 0018 GETMET R6 R6 K11 + 0x60200018, // 0019 GETGBL R8 G24 + 0x5824000C, // 001A LDCONST R9 K12 + 0x58280008, // 001B LDCONST R10 K8 + 0x5C2C0A00, // 001C MOVE R11 R5 + 0x7C200600, // 001D CALL R8 3 + 0x5824000D, // 001E LDCONST R9 K13 + 0x7C180600, // 001F CALL R6 3 + 0x8C18050E, // 0020 GETMET R6 R2 K14 + 0x5820000F, // 0021 LDCONST R8 K15 + 0x58240010, // 0022 LDCONST R9 K16 + 0x5C280A00, // 0023 MOVE R10 R5 + 0x882C0111, // 0024 GETMBR R11 R0 K17 + 0x7C180A00, // 0025 CALL R6 5 + 0xB81A0E00, // 0026 GETNGBL R6 K7 + 0x8C180D12, // 0027 GETMET R6 R6 K18 + 0x7C180200, // 0028 CALL R6 1 + 0x8C180D09, // 0029 GETMET R6 R6 K9 + 0x5820000A, // 002A LDCONST R8 K10 + 0x7C180400, // 002B CALL R6 2 + 0x781A000E, // 002C JMPF R6 #003C + 0xB81A0E00, // 002D GETNGBL R6 K7 + 0x8C180D0B, // 002E GETMET R6 R6 K11 + 0x60200018, // 002F GETGBL R8 G24 + 0x5824000C, // 0030 LDCONST R9 K12 + 0x58280012, // 0031 LDCONST R10 K18 + 0x5C2C0A00, // 0032 MOVE R11 R5 + 0x7C200600, // 0033 CALL R8 3 + 0x5824000D, // 0034 LDCONST R9 K13 + 0x7C180600, // 0035 CALL R6 3 + 0x8C18050E, // 0036 GETMET R6 R2 K14 + 0x5820000F, // 0037 LDCONST R8 K15 + 0x58240010, // 0038 LDCONST R9 K16 + 0x5C280A00, // 0039 MOVE R10 R5 + 0x882C0113, // 003A GETMBR R11 R0 K19 + 0x7C180A00, // 003B CALL R6 5 + 0xA8040001, // 003C EXBLK 1 1 + 0x70020010, // 003D JMP #004F + 0xAC0C0002, // 003E CATCH R3 0 2 + 0x7002000D, // 003F JMP #004E + 0xB8160E00, // 0040 GETNGBL R5 K7 + 0x8C140B0B, // 0041 GETMET R5 R5 K11 + 0x601C0008, // 0042 GETGBL R7 G8 + 0x5C200600, // 0043 MOVE R8 R3 + 0x7C1C0200, // 0044 CALL R7 1 + 0x001E2807, // 0045 ADD R7 K20 R7 + 0x001C0F15, // 0046 ADD R7 R7 K21 + 0x60200008, // 0047 GETGBL R8 G8 + 0x5C240800, // 0048 MOVE R9 R4 + 0x7C200200, // 0049 CALL R8 1 + 0x001C0E08, // 004A ADD R7 R7 R8 + 0x58200016, // 004B LDCONST R8 K22 + 0x7C140600, // 004C CALL R5 3 + 0x70020000, // 004D JMP #004F + 0xB0080000, // 004E RAISE 2 R0 R0 + 0x80000000, // 004F RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: _start_udp +********************************************************************/ +be_local_closure(Matter_Device__start_udp, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 1]) { + be_nested_proto( + 8, /* nstack */ + 3, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(msg_received), + }), + be_str_weak(_X3Clambda_X3E), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x680C0000, // 0000 GETUPV R3 U0 + 0x8C0C0700, // 0001 GETMET R3 R3 K0 + 0x5C140000, // 0002 MOVE R5 R0 + 0x5C180200, // 0003 MOVE R6 R1 + 0x5C1C0400, // 0004 MOVE R7 R2 + 0x7C0C0800, // 0005 CALL R3 4 + 0x80040600, // 0006 RET 1 R3 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(udp_server), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(log), + /* K3 */ be_nested_str_weak(MTR_X3A_X20Starting_X20UDP_X20server_X20on_X20port_X3A_X20), + /* K4 */ be_const_int(2), + /* K5 */ be_nested_str_weak(matter), + /* K6 */ be_nested_str_weak(UDPServer), + /* K7 */ be_nested_str_weak(), + /* K8 */ be_nested_str_weak(start), + }), + be_str_weak(_start_udp), + &be_const_str_solidified, + ( &(const binstruction[28]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x780A0000, // 0001 JMPF R2 #0003 + 0x80000400, // 0002 RET 0 + 0x4C080000, // 0003 LDNIL R2 + 0x1C080202, // 0004 EQ R2 R1 R2 + 0x780A0000, // 0005 JMPF R2 #0007 + 0x540615A3, // 0006 LDINT R1 5540 + 0xB80A0200, // 0007 GETNGBL R2 K1 + 0x8C080502, // 0008 GETMET R2 R2 K2 + 0x60100008, // 0009 GETGBL R4 G8 + 0x5C140200, // 000A MOVE R5 R1 + 0x7C100200, // 000B CALL R4 1 + 0x00120604, // 000C ADD R4 K3 R4 + 0x58140004, // 000D LDCONST R5 K4 + 0x7C080600, // 000E CALL R2 3 + 0xB80A0A00, // 000F GETNGBL R2 K5 + 0x8C080506, // 0010 GETMET R2 R2 K6 + 0x5C100000, // 0011 MOVE R4 R0 + 0x58140007, // 0012 LDCONST R5 K7 + 0x5C180200, // 0013 MOVE R6 R1 + 0x7C080800, // 0014 CALL R2 4 + 0x90020002, // 0015 SETMBR R0 K0 R2 + 0x88080100, // 0016 GETMBR R2 R0 K0 + 0x8C080508, // 0017 GETMET R2 R2 K8 + 0x84100000, // 0018 CLOSURE R4 P0 + 0x7C080400, // 0019 CALL R2 2 + 0xA0000000, // 001A CLOSE R0 + 0x80000000, // 001B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_plugin_remote_info +********************************************************************/ +be_local_closure(Matter_Device_get_plugin_remote_info, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(plugins_config_remotes), + /* K1 */ be_nested_str_weak(find), + }), + be_str_weak(get_plugin_remote_info), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x60140013, // 0003 GETGBL R5 G19 + 0x7C140000, // 0004 CALL R5 0 + 0x7C080600, // 0005 CALL R2 3 + 0x80040400, // 0006 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: register_http_remote +********************************************************************/ +be_local_closure(Matter_Device_register_http_remote, /* name */ + be_nested_proto( + 9, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_str_weak(http_remotes), + /* K1 */ be_nested_str_weak(contains), + /* K2 */ be_nested_str_weak(get_timeout), + /* K3 */ be_nested_str_weak(set_timeout), + /* K4 */ be_nested_str_weak(matter), + /* K5 */ be_nested_str_weak(HTTP_remote), + /* K6 */ be_nested_str_weak(plugins_config_remotes), + /* K7 */ be_nested_str_weak(set_info), + }), + be_str_weak(register_http_remote), + &be_const_str_solidified, + ( &(const binstruction[42]) { /* code */ + 0x880C0100, // 0000 GETMBR R3 R0 K0 + 0x4C100000, // 0001 LDNIL R4 + 0x1C0C0604, // 0002 EQ R3 R3 R4 + 0x780E0002, // 0003 JMPF R3 #0007 + 0x600C0013, // 0004 GETGBL R3 G19 + 0x7C0C0000, // 0005 CALL R3 0 + 0x90020003, // 0006 SETMBR R0 K0 R3 + 0x4C0C0000, // 0007 LDNIL R3 + 0x88100100, // 0008 GETMBR R4 R0 K0 + 0x8C100901, // 0009 GETMET R4 R4 K1 + 0x5C180200, // 000A MOVE R6 R1 + 0x7C100400, // 000B CALL R4 2 + 0x78120009, // 000C JMPF R4 #0017 + 0x88100100, // 000D GETMBR R4 R0 K0 + 0x940C0801, // 000E GETIDX R3 R4 R1 + 0x8C140702, // 000F GETMET R5 R3 K2 + 0x7C140200, // 0010 CALL R5 1 + 0x14140405, // 0011 LT R5 R2 R5 + 0x78160002, // 0012 JMPF R5 #0016 + 0x8C140703, // 0013 GETMET R5 R3 K3 + 0x5C1C0400, // 0014 MOVE R7 R2 + 0x7C140400, // 0015 CALL R5 2 + 0x70020011, // 0016 JMP #0029 + 0xB8120800, // 0017 GETNGBL R4 K4 + 0x8C100905, // 0018 GETMET R4 R4 K5 + 0x5C180000, // 0019 MOVE R6 R0 + 0x5C1C0200, // 001A MOVE R7 R1 + 0x5C200400, // 001B MOVE R8 R2 + 0x7C100800, // 001C CALL R4 4 + 0x5C0C0800, // 001D MOVE R3 R4 + 0x88100106, // 001E GETMBR R4 R0 K6 + 0x8C100901, // 001F GETMET R4 R4 K1 + 0x5C180200, // 0020 MOVE R6 R1 + 0x7C100400, // 0021 CALL R4 2 + 0x78120003, // 0022 JMPF R4 #0027 + 0x8C100707, // 0023 GETMET R4 R3 K7 + 0x88180106, // 0024 GETMBR R6 R0 K6 + 0x94180C01, // 0025 GETIDX R6 R6 R1 + 0x7C100400, // 0026 CALL R4 2 + 0x88100100, // 0027 GETMBR R4 R0 K0 + 0x98100203, // 0028 SETIDX R4 R1 R3 + 0x80040600, // 0029 RET 1 R3 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: mdns_remove_op_discovery_all_fabrics +********************************************************************/ +be_local_closure(Matter_Device_mdns_remove_op_discovery_all_fabrics, /* name */ + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(sessions), + /* K1 */ be_nested_str_weak(active_fabrics), + /* K2 */ be_nested_str_weak(get_device_id), + /* K3 */ be_nested_str_weak(get_fabric_id), + /* K4 */ be_nested_str_weak(mdns_remove_op_discovery), + /* K5 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(mdns_remove_op_discovery_all_fabrics), + &be_const_str_solidified, + ( &(const binstruction[22]) { /* code */ + 0x60040010, // 0000 GETGBL R1 G16 + 0x88080100, // 0001 GETMBR R2 R0 K0 + 0x8C080501, // 0002 GETMET R2 R2 K1 + 0x7C080200, // 0003 CALL R2 1 + 0x7C040200, // 0004 CALL R1 1 + 0xA802000B, // 0005 EXBLK 0 #0012 + 0x5C080200, // 0006 MOVE R2 R1 + 0x7C080000, // 0007 CALL R2 0 + 0x8C0C0502, // 0008 GETMET R3 R2 K2 + 0x7C0C0200, // 0009 CALL R3 1 + 0x780E0005, // 000A JMPF R3 #0011 + 0x8C0C0503, // 000B GETMET R3 R2 K3 + 0x7C0C0200, // 000C CALL R3 1 + 0x780E0002, // 000D JMPF R3 #0011 + 0x8C0C0104, // 000E GETMET R3 R0 K4 + 0x5C140400, // 000F MOVE R5 R2 + 0x7C0C0400, // 0010 CALL R3 2 + 0x7001FFF3, // 0011 JMP #0006 + 0x58040005, // 0012 LDCONST R1 K5 + 0xAC040200, // 0013 CATCH R1 1 0 + 0xB0080000, // 0014 RAISE 2 R0 R0 + 0x80000000, // 0015 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_plugin_class_arg +********************************************************************/ +be_local_closure(Matter_Device_get_plugin_class_arg, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(plugins_classes), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(ARG), + /* K3 */ be_nested_str_weak(), + }), + be_str_weak(get_plugin_class_arg), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x780A0001, // 0004 JMPF R2 #0007 + 0x880C0502, // 0005 GETMBR R3 R2 K2 + 0x70020000, // 0006 JMP #0008 + 0x580C0003, // 0007 LDCONST R3 K3 + 0x80040600, // 0008 RET 1 R3 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: generate_random_passcode ********************************************************************/ @@ -5871,42 +5603,9 @@ be_local_closure(Matter_Device_generate_random_passcode, /* name */ /******************************************************************** -** Solidified function: msg_received +** Solidified function: is_root_commissioning_open ********************************************************************/ -be_local_closure(Matter_Device_msg_received, /* name */ - be_nested_proto( - 9, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(message_handler), - /* K1 */ be_nested_str_weak(msg_received), - }), - be_str_weak(msg_received), - &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0x88100100, // 0000 GETMBR R4 R0 K0 - 0x8C100901, // 0001 GETMET R4 R4 K1 - 0x5C180200, // 0002 MOVE R6 R1 - 0x5C1C0400, // 0003 MOVE R7 R2 - 0x5C200600, // 0004 MOVE R8 R3 - 0x7C100800, // 0005 CALL R4 4 - 0x80040800, // 0006 RET 1 R4 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: is_commissioning_open -********************************************************************/ -be_local_closure(Matter_Device_is_commissioning_open, /* name */ +be_local_closure(Matter_Device_is_root_commissioning_open, /* name */ be_nested_proto( 3, /* nstack */ 1, /* argc */ @@ -5916,16 +5615,24 @@ be_local_closure(Matter_Device_is_commissioning_open, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ + ( &(const bvalue[ 2]) { /* constants */ /* K0 */ be_nested_str_weak(commissioning_open), + /* K1 */ be_nested_str_weak(commissioning_admin_fabric), }), - be_str_weak(is_commissioning_open), + be_str_weak(is_root_commissioning_open), &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ + ( &(const binstruction[11]) { /* code */ 0x88040100, // 0000 GETMBR R1 R0 K0 0x4C080000, // 0001 LDNIL R2 0x20040202, // 0002 NE R1 R1 R2 - 0x80040200, // 0003 RET 1 R1 + 0x78060003, // 0003 JMPF R1 #0008 + 0x88040101, // 0004 GETMBR R1 R0 K1 + 0x4C080000, // 0005 LDNIL R2 + 0x1C040202, // 0006 EQ R1 R1 R2 + 0x74060000, // 0007 JMPT R1 #0009 + 0x50040001, // 0008 LDBOOL R1 0 1 + 0x50040200, // 0009 LDBOOL R1 1 0 + 0x80040200, // 000A RET 1 R1 }) ) ); @@ -5933,11 +5640,73 @@ be_local_closure(Matter_Device_is_commissioning_open, /* name */ /******************************************************************** -** Solidified function: MtrInfo_one +** Solidified function: stop_basic_commissioning ********************************************************************/ -be_local_closure(Matter_Device_MtrInfo_one, /* name */ +be_local_closure(Matter_Device_stop_basic_commissioning, /* name */ be_nested_proto( - 9, /* nstack */ + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[13]) { /* constants */ + /* K0 */ be_nested_str_weak(is_root_commissioning_open), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(publish_result), + /* K3 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Commissioning_X22_X3A0_X7D_X7D), + /* K4 */ be_nested_str_weak(Matter), + /* K5 */ be_nested_str_weak(commissioning_open), + /* K6 */ be_nested_str_weak(mdns_remove_PASE), + /* K7 */ be_nested_str_weak(commissioning_iterations), + /* K8 */ be_nested_str_weak(commissioning_discriminator), + /* K9 */ be_nested_str_weak(commissioning_salt), + /* K10 */ be_nested_str_weak(commissioning_w0), + /* K11 */ be_nested_str_weak(commissioning_L), + /* K12 */ be_nested_str_weak(commissioning_admin_fabric), + }), + be_str_weak(stop_basic_commissioning), + &be_const_str_solidified, + ( &(const binstruction[25]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x78060004, // 0002 JMPF R1 #0008 + 0xB8060200, // 0003 GETNGBL R1 K1 + 0x8C040302, // 0004 GETMET R1 R1 K2 + 0x580C0003, // 0005 LDCONST R3 K3 + 0x58100004, // 0006 LDCONST R4 K4 + 0x7C040600, // 0007 CALL R1 3 + 0x4C040000, // 0008 LDNIL R1 + 0x90020A01, // 0009 SETMBR R0 K5 R1 + 0x8C040106, // 000A GETMET R1 R0 K6 + 0x7C040200, // 000B CALL R1 1 + 0x4C040000, // 000C LDNIL R1 + 0x90020E01, // 000D SETMBR R0 K7 R1 + 0x4C040000, // 000E LDNIL R1 + 0x90021001, // 000F SETMBR R0 K8 R1 + 0x4C040000, // 0010 LDNIL R1 + 0x90021201, // 0011 SETMBR R0 K9 R1 + 0x4C040000, // 0012 LDNIL R1 + 0x90021401, // 0013 SETMBR R0 K10 R1 + 0x4C040000, // 0014 LDNIL R1 + 0x90021601, // 0015 SETMBR R0 K11 R1 + 0x4C040000, // 0016 LDNIL R1 + 0x90021801, // 0017 SETMBR R0 K12 R1 + 0x80000000, // 0018 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: autoconf_sensors_list +********************************************************************/ +be_local_closure(Matter_Device_autoconf_sensors_list, /* name */ + be_nested_proto( + 10, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -5945,37 +5714,148 @@ be_local_closure(Matter_Device_MtrInfo_one, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(find_plugin_by_endpoint), - /* K1 */ be_nested_str_weak(state_json), - /* K2 */ be_nested_str_weak(_X7B_X22MtrInfo_X22_X3A_X25s_X7D), - /* K3 */ be_nested_str_weak(tasmota), - /* K4 */ be_nested_str_weak(publish_result), - /* K5 */ be_nested_str_weak(), + ( &(const bvalue[18]) { /* constants */ + /* K0 */ be_nested_str_weak(k2l), + /* K1 */ be_nested_str_weak(contains), + /* K2 */ be_nested_str_weak(Temperature), + /* K3 */ be_nested_str_weak(_X23Temperature), + /* K4 */ be_nested_str_weak(push), + /* K5 */ be_nested_str_weak(type), + /* K6 */ be_nested_str_weak(temperature), + /* K7 */ be_nested_str_weak(filter), + /* K8 */ be_nested_str_weak(stop_iteration), + /* K9 */ be_nested_str_weak(Pressure), + /* K10 */ be_nested_str_weak(_X23Pressure), + /* K11 */ be_nested_str_weak(pressure), + /* K12 */ be_nested_str_weak(Illuminance), + /* K13 */ be_nested_str_weak(_X23Illuminance), + /* K14 */ be_nested_str_weak(illuminance), + /* K15 */ be_nested_str_weak(Humidity), + /* K16 */ be_nested_str_weak(_X23Humidity), + /* K17 */ be_nested_str_weak(humidity), }), - be_str_weak(MtrInfo_one), + be_str_weak(autoconf_sensors_list), &be_const_str_solidified, - ( &(const binstruction[20]) { /* code */ - 0x8C080100, // 0000 GETMET R2 R0 K0 - 0x5C100200, // 0001 MOVE R4 R1 - 0x7C080400, // 0002 CALL R2 2 - 0x4C0C0000, // 0003 LDNIL R3 - 0x1C0C0403, // 0004 EQ R3 R2 R3 - 0x780E0000, // 0005 JMPF R3 #0007 - 0x80000600, // 0006 RET 0 - 0x8C0C0501, // 0007 GETMET R3 R2 K1 - 0x7C0C0200, // 0008 CALL R3 1 - 0x780E0008, // 0009 JMPF R3 #0013 - 0x60100018, // 000A GETGBL R4 G24 - 0x58140002, // 000B LDCONST R5 K2 - 0x5C180600, // 000C MOVE R6 R3 - 0x7C100400, // 000D CALL R4 2 - 0xB8160600, // 000E GETNGBL R5 K3 - 0x8C140B04, // 000F GETMET R5 R5 K4 - 0x5C1C0800, // 0010 MOVE R7 R4 - 0x58200005, // 0011 LDCONST R8 K5 - 0x7C140600, // 0012 CALL R5 3 - 0x80000000, // 0013 RET 0 + ( &(const binstruction[119]) { /* code */ + 0x60080012, // 0000 GETGBL R2 G18 + 0x7C080000, // 0001 CALL R2 0 + 0x600C0010, // 0002 GETGBL R3 G16 + 0x8C100100, // 0003 GETMET R4 R0 K0 + 0x5C180200, // 0004 MOVE R6 R1 + 0x7C100400, // 0005 CALL R4 2 + 0x7C0C0200, // 0006 CALL R3 1 + 0xA8020013, // 0007 EXBLK 0 #001C + 0x5C100600, // 0008 MOVE R4 R3 + 0x7C100000, // 0009 CALL R4 0 + 0x94140204, // 000A GETIDX R5 R1 R4 + 0x6018000F, // 000B GETGBL R6 G15 + 0x5C1C0A00, // 000C MOVE R7 R5 + 0x60200013, // 000D GETGBL R8 G19 + 0x7C180400, // 000E CALL R6 2 + 0x781A000A, // 000F JMPF R6 #001B + 0x8C180B01, // 0010 GETMET R6 R5 K1 + 0x58200002, // 0011 LDCONST R8 K2 + 0x7C180400, // 0012 CALL R6 2 + 0x781A0006, // 0013 JMPF R6 #001B + 0x00180903, // 0014 ADD R6 R4 K3 + 0x8C1C0504, // 0015 GETMET R7 R2 K4 + 0x60240013, // 0016 GETGBL R9 G19 + 0x7C240000, // 0017 CALL R9 0 + 0x98260B06, // 0018 SETIDX R9 K5 K6 + 0x98260E06, // 0019 SETIDX R9 K7 R6 + 0x7C1C0400, // 001A CALL R7 2 + 0x7001FFEB, // 001B JMP #0008 + 0x580C0008, // 001C LDCONST R3 K8 + 0xAC0C0200, // 001D CATCH R3 1 0 + 0xB0080000, // 001E RAISE 2 R0 R0 + 0x600C0010, // 001F GETGBL R3 G16 + 0x8C100100, // 0020 GETMET R4 R0 K0 + 0x5C180200, // 0021 MOVE R6 R1 + 0x7C100400, // 0022 CALL R4 2 + 0x7C0C0200, // 0023 CALL R3 1 + 0xA8020013, // 0024 EXBLK 0 #0039 + 0x5C100600, // 0025 MOVE R4 R3 + 0x7C100000, // 0026 CALL R4 0 + 0x94140204, // 0027 GETIDX R5 R1 R4 + 0x6018000F, // 0028 GETGBL R6 G15 + 0x5C1C0A00, // 0029 MOVE R7 R5 + 0x60200013, // 002A GETGBL R8 G19 + 0x7C180400, // 002B CALL R6 2 + 0x781A000A, // 002C JMPF R6 #0038 + 0x8C180B01, // 002D GETMET R6 R5 K1 + 0x58200009, // 002E LDCONST R8 K9 + 0x7C180400, // 002F CALL R6 2 + 0x781A0006, // 0030 JMPF R6 #0038 + 0x0018090A, // 0031 ADD R6 R4 K10 + 0x8C1C0504, // 0032 GETMET R7 R2 K4 + 0x60240013, // 0033 GETGBL R9 G19 + 0x7C240000, // 0034 CALL R9 0 + 0x98260B0B, // 0035 SETIDX R9 K5 K11 + 0x98260E06, // 0036 SETIDX R9 K7 R6 + 0x7C1C0400, // 0037 CALL R7 2 + 0x7001FFEB, // 0038 JMP #0025 + 0x580C0008, // 0039 LDCONST R3 K8 + 0xAC0C0200, // 003A CATCH R3 1 0 + 0xB0080000, // 003B RAISE 2 R0 R0 + 0x600C0010, // 003C GETGBL R3 G16 + 0x8C100100, // 003D GETMET R4 R0 K0 + 0x5C180200, // 003E MOVE R6 R1 + 0x7C100400, // 003F CALL R4 2 + 0x7C0C0200, // 0040 CALL R3 1 + 0xA8020013, // 0041 EXBLK 0 #0056 + 0x5C100600, // 0042 MOVE R4 R3 + 0x7C100000, // 0043 CALL R4 0 + 0x94140204, // 0044 GETIDX R5 R1 R4 + 0x6018000F, // 0045 GETGBL R6 G15 + 0x5C1C0A00, // 0046 MOVE R7 R5 + 0x60200013, // 0047 GETGBL R8 G19 + 0x7C180400, // 0048 CALL R6 2 + 0x781A000A, // 0049 JMPF R6 #0055 + 0x8C180B01, // 004A GETMET R6 R5 K1 + 0x5820000C, // 004B LDCONST R8 K12 + 0x7C180400, // 004C CALL R6 2 + 0x781A0006, // 004D JMPF R6 #0055 + 0x0018090D, // 004E ADD R6 R4 K13 + 0x8C1C0504, // 004F GETMET R7 R2 K4 + 0x60240013, // 0050 GETGBL R9 G19 + 0x7C240000, // 0051 CALL R9 0 + 0x98260B0E, // 0052 SETIDX R9 K5 K14 + 0x98260E06, // 0053 SETIDX R9 K7 R6 + 0x7C1C0400, // 0054 CALL R7 2 + 0x7001FFEB, // 0055 JMP #0042 + 0x580C0008, // 0056 LDCONST R3 K8 + 0xAC0C0200, // 0057 CATCH R3 1 0 + 0xB0080000, // 0058 RAISE 2 R0 R0 + 0x600C0010, // 0059 GETGBL R3 G16 + 0x8C100100, // 005A GETMET R4 R0 K0 + 0x5C180200, // 005B MOVE R6 R1 + 0x7C100400, // 005C CALL R4 2 + 0x7C0C0200, // 005D CALL R3 1 + 0xA8020013, // 005E EXBLK 0 #0073 + 0x5C100600, // 005F MOVE R4 R3 + 0x7C100000, // 0060 CALL R4 0 + 0x94140204, // 0061 GETIDX R5 R1 R4 + 0x6018000F, // 0062 GETGBL R6 G15 + 0x5C1C0A00, // 0063 MOVE R7 R5 + 0x60200013, // 0064 GETGBL R8 G19 + 0x7C180400, // 0065 CALL R6 2 + 0x781A000A, // 0066 JMPF R6 #0072 + 0x8C180B01, // 0067 GETMET R6 R5 K1 + 0x5820000F, // 0068 LDCONST R8 K15 + 0x7C180400, // 0069 CALL R6 2 + 0x781A0006, // 006A JMPF R6 #0072 + 0x00180910, // 006B ADD R6 R4 K16 + 0x8C1C0504, // 006C GETMET R7 R2 K4 + 0x60240013, // 006D GETGBL R9 G19 + 0x7C240000, // 006E CALL R9 0 + 0x98260B11, // 006F SETIDX R9 K5 K17 + 0x98260E06, // 0070 SETIDX R9 K7 R6 + 0x7C1C0400, // 0071 CALL R7 2 + 0x7001FFEB, // 0072 JMP #005F + 0x580C0008, // 0073 LDCONST R3 K8 + 0xAC0C0200, // 0074 CATCH R3 1 0 + 0xB0080000, // 0075 RAISE 2 R0 R0 + 0x80040400, // 0076 RET 1 R2 }) ) ); @@ -5983,76 +5863,273 @@ be_local_closure(Matter_Device_MtrInfo_one, /* name */ /******************************************************************** -** Solidified function: start +** Solidified function: signal_endpoints_changed ********************************************************************/ -be_local_closure(Matter_Device_start, /* name */ +be_local_closure(Matter_Device_signal_endpoints_changed, /* name */ be_nested_proto( - 6, /* nstack */ + 7, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 1]) { - be_nested_proto( - 2, /* nstack */ - 0, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(_trigger_read_sensors), - }), - be_str_weak(_anonymous_), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x68000000, // 0000 GETUPV R0 U0 - 0x8C000100, // 0001 GETMET R0 R0 K0 - 0x7C000200, // 0002 CALL R0 1 - 0x80000000, // 0003 RET 0 - }) - ), - }), + 0, /* has sup protos */ + NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(started), - /* K1 */ be_nested_str_weak(autoconf_device), - /* K2 */ be_nested_str_weak(tasmota), - /* K3 */ be_nested_str_weak(add_cron), - /* K4 */ be_nested_str_weak(_X2A_X2F30_X20_X2A_X20_X2A_X20_X2A_X20_X2A_X20_X2A), - /* K5 */ be_nested_str_weak(matter_sensors_30s), - /* K6 */ be_nested_str_weak(_start_udp), - /* K7 */ be_nested_str_weak(UDP_PORT), - /* K8 */ be_nested_str_weak(start_mdns_announce_hostnames), + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(attribute_updated), + /* K1 */ be_const_int(0), + /* K2 */ be_const_int(3), }), - be_str_weak(start), + be_str_weak(signal_endpoints_changed), &be_const_str_solidified, - ( &(const binstruction[20]) { /* code */ + ( &(const binstruction[13]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x580C0001, // 0001 LDCONST R3 K1 + 0x5412001C, // 0002 LDINT R4 29 + 0x58140002, // 0003 LDCONST R5 K2 + 0x50180000, // 0004 LDBOOL R6 0 0 + 0x7C040A00, // 0005 CALL R1 5 + 0x8C040100, // 0006 GETMET R1 R0 K0 + 0x540EFEFF, // 0007 LDINT R3 65280 + 0x5412001C, // 0008 LDINT R4 29 + 0x58140002, // 0009 LDCONST R5 K2 + 0x50180000, // 000A LDBOOL R6 0 0 + 0x7C040A00, // 000B CALL R1 5 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: every_second +********************************************************************/ +be_local_closure(Matter_Device_every_second, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(sessions), + /* K1 */ be_nested_str_weak(every_second), + /* K2 */ be_nested_str_weak(message_handler), + /* K3 */ be_nested_str_weak(commissioning_open), + /* K4 */ be_nested_str_weak(tasmota), + /* K5 */ be_nested_str_weak(time_reached), + }), + be_str_weak(every_second), + &be_const_str_solidified, + ( &(const binstruction[18]) { /* code */ 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x78060000, // 0001 JMPF R1 #0003 - 0x80000200, // 0002 RET 0 - 0x8C040101, // 0003 GETMET R1 R0 K1 - 0x7C040200, // 0004 CALL R1 1 - 0xB8060400, // 0005 GETNGBL R1 K2 - 0x8C040303, // 0006 GETMET R1 R1 K3 - 0x580C0004, // 0007 LDCONST R3 K4 - 0x84100000, // 0008 CLOSURE R4 P0 - 0x58140005, // 0009 LDCONST R5 K5 - 0x7C040800, // 000A CALL R1 4 - 0x8C040106, // 000B GETMET R1 R0 K6 - 0x880C0107, // 000C GETMBR R3 R0 K7 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x88040102, // 0003 GETMBR R1 R0 K2 + 0x8C040301, // 0004 GETMET R1 R1 K1 + 0x7C040200, // 0005 CALL R1 1 + 0x88040103, // 0006 GETMBR R1 R0 K3 + 0x4C080000, // 0007 LDNIL R2 + 0x20040202, // 0008 NE R1 R1 R2 + 0x78060006, // 0009 JMPF R1 #0011 + 0xB8060800, // 000A GETNGBL R1 K4 + 0x8C040305, // 000B GETMET R1 R1 K5 + 0x880C0103, // 000C GETMBR R3 R0 K3 0x7C040400, // 000D CALL R1 2 - 0x8C040108, // 000E GETMET R1 R0 K8 - 0x7C040200, // 000F CALL R1 1 - 0x50040200, // 0010 LDBOOL R1 1 0 - 0x90020001, // 0011 SETMBR R0 K0 R1 - 0xA0000000, // 0012 CLOSE R0 - 0x80000000, // 0013 RET 0 + 0x78060001, // 000E JMPF R1 #0011 + 0x4C040000, // 000F LDNIL R1 + 0x90020601, // 0010 SETMBR R0 K3 R1 + 0x80000000, // 0011 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: load_param +********************************************************************/ +be_local_closure(Matter_Device_load_param, /* name */ + be_nested_proto( + 11, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[35]) { /* constants */ + /* K0 */ be_nested_str_weak(crypto), + /* K1 */ be_nested_str_weak(FILENAME), + /* K2 */ be_nested_str_weak(read), + /* K3 */ be_nested_str_weak(close), + /* K4 */ be_nested_str_weak(json), + /* K5 */ be_nested_str_weak(load), + /* K6 */ be_nested_str_weak(root_discriminator), + /* K7 */ be_nested_str_weak(find), + /* K8 */ be_nested_str_weak(distinguish), + /* K9 */ be_nested_str_weak(root_passcode), + /* K10 */ be_nested_str_weak(passcode), + /* K11 */ be_nested_str_weak(ipv4only), + /* K12 */ be_nested_str_weak(disable_bridge_mode), + /* K13 */ be_nested_str_weak(next_ep), + /* K14 */ be_nested_str_weak(nextep), + /* K15 */ be_nested_str_weak(plugins_config), + /* K16 */ be_nested_str_weak(config), + /* K17 */ be_nested_str_weak(tasmota), + /* K18 */ be_nested_str_weak(log), + /* K19 */ be_nested_str_weak(MTR_X3A_X20load_config_X20_X3D_X20), + /* K20 */ be_const_int(3), + /* K21 */ be_nested_str_weak(adjust_next_ep), + /* K22 */ be_nested_str_weak(plugins_persist), + /* K23 */ be_nested_str_weak(plugins_config_remotes), + /* K24 */ be_nested_str_weak(remotes), + /* K25 */ be_nested_str_weak(MTR_X3A_X20load_remotes_X20_X3D_X20), + /* K26 */ be_nested_str_weak(io_error), + /* K27 */ be_nested_str_weak(MTR_X3A_X20Session_Store_X3A_X3Aload_X20Exception_X3A), + /* K28 */ be_nested_str_weak(_X7C), + /* K29 */ be_const_int(2), + /* K30 */ be_nested_str_weak(random), + /* K31 */ be_nested_str_weak(get), + /* K32 */ be_const_int(0), + /* K33 */ be_nested_str_weak(generate_random_passcode), + /* K34 */ be_nested_str_weak(save_param), + }), + be_str_weak(load_param), + &be_const_str_solidified, + ( &(const binstruction[127]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xA802004D, // 0001 EXBLK 0 #0050 + 0x60080011, // 0002 GETGBL R2 G17 + 0x880C0101, // 0003 GETMBR R3 R0 K1 + 0x7C080200, // 0004 CALL R2 1 + 0x8C0C0502, // 0005 GETMET R3 R2 K2 + 0x7C0C0200, // 0006 CALL R3 1 + 0x8C100503, // 0007 GETMET R4 R2 K3 + 0x7C100200, // 0008 CALL R4 1 + 0xA4120800, // 0009 IMPORT R4 K4 + 0x8C140905, // 000A GETMET R5 R4 K5 + 0x5C1C0600, // 000B MOVE R7 R3 + 0x7C140400, // 000C CALL R5 2 + 0x8C180B07, // 000D GETMET R6 R5 K7 + 0x58200008, // 000E LDCONST R8 K8 + 0x88240106, // 000F GETMBR R9 R0 K6 + 0x7C180600, // 0010 CALL R6 3 + 0x90020C06, // 0011 SETMBR R0 K6 R6 + 0x8C180B07, // 0012 GETMET R6 R5 K7 + 0x5820000A, // 0013 LDCONST R8 K10 + 0x88240109, // 0014 GETMBR R9 R0 K9 + 0x7C180600, // 0015 CALL R6 3 + 0x90021206, // 0016 SETMBR R0 K9 R6 + 0x60180017, // 0017 GETGBL R6 G23 + 0x8C1C0B07, // 0018 GETMET R7 R5 K7 + 0x5824000B, // 0019 LDCONST R9 K11 + 0x50280000, // 001A LDBOOL R10 0 0 + 0x7C1C0600, // 001B CALL R7 3 + 0x7C180200, // 001C CALL R6 1 + 0x90021606, // 001D SETMBR R0 K11 R6 + 0x60180017, // 001E GETGBL R6 G23 + 0x8C1C0B07, // 001F GETMET R7 R5 K7 + 0x5824000C, // 0020 LDCONST R9 K12 + 0x50280000, // 0021 LDBOOL R10 0 0 + 0x7C1C0600, // 0022 CALL R7 3 + 0x7C180200, // 0023 CALL R6 1 + 0x90021806, // 0024 SETMBR R0 K12 R6 + 0x8C180B07, // 0025 GETMET R6 R5 K7 + 0x5820000E, // 0026 LDCONST R8 K14 + 0x8824010D, // 0027 GETMBR R9 R0 K13 + 0x7C180600, // 0028 CALL R6 3 + 0x90021A06, // 0029 SETMBR R0 K13 R6 + 0x8C180B07, // 002A GETMET R6 R5 K7 + 0x58200010, // 002B LDCONST R8 K16 + 0x7C180400, // 002C CALL R6 2 + 0x90021E06, // 002D SETMBR R0 K15 R6 + 0x8818010F, // 002E GETMBR R6 R0 K15 + 0x4C1C0000, // 002F LDNIL R7 + 0x20180C07, // 0030 NE R6 R6 R7 + 0x781A000B, // 0031 JMPF R6 #003E + 0xB81A2200, // 0032 GETNGBL R6 K17 + 0x8C180D12, // 0033 GETMET R6 R6 K18 + 0x60200008, // 0034 GETGBL R8 G8 + 0x8824010F, // 0035 GETMBR R9 R0 K15 + 0x7C200200, // 0036 CALL R8 1 + 0x00222608, // 0037 ADD R8 K19 R8 + 0x58240014, // 0038 LDCONST R9 K20 + 0x7C180600, // 0039 CALL R6 3 + 0x8C180115, // 003A GETMET R6 R0 K21 + 0x7C180200, // 003B CALL R6 1 + 0x50180200, // 003C LDBOOL R6 1 0 + 0x90022C06, // 003D SETMBR R0 K22 R6 + 0x8C180B07, // 003E GETMET R6 R5 K7 + 0x58200018, // 003F LDCONST R8 K24 + 0x60240013, // 0040 GETGBL R9 G19 + 0x7C240000, // 0041 CALL R9 0 + 0x7C180600, // 0042 CALL R6 3 + 0x90022E06, // 0043 SETMBR R0 K23 R6 + 0x88180117, // 0044 GETMBR R6 R0 K23 + 0x781A0007, // 0045 JMPF R6 #004E + 0xB81A2200, // 0046 GETNGBL R6 K17 + 0x8C180D12, // 0047 GETMET R6 R6 K18 + 0x60200008, // 0048 GETGBL R8 G8 + 0x88240117, // 0049 GETMBR R9 R0 K23 + 0x7C200200, // 004A CALL R8 1 + 0x00223208, // 004B ADD R8 K25 R8 + 0x58240014, // 004C LDCONST R9 K20 + 0x7C180600, // 004D CALL R6 3 + 0xA8040001, // 004E EXBLK 1 1 + 0x70020012, // 004F JMP #0063 + 0xAC080002, // 0050 CATCH R2 0 2 + 0x7002000F, // 0051 JMP #0062 + 0x2010051A, // 0052 NE R4 R2 K26 + 0x7812000C, // 0053 JMPF R4 #0061 + 0xB8122200, // 0054 GETNGBL R4 K17 + 0x8C100912, // 0055 GETMET R4 R4 K18 + 0x60180008, // 0056 GETGBL R6 G8 + 0x5C1C0400, // 0057 MOVE R7 R2 + 0x7C180200, // 0058 CALL R6 1 + 0x001A3606, // 0059 ADD R6 K27 R6 + 0x00180D1C, // 005A ADD R6 R6 K28 + 0x601C0008, // 005B GETGBL R7 G8 + 0x5C200600, // 005C MOVE R8 R3 + 0x7C1C0200, // 005D CALL R7 1 + 0x00180C07, // 005E ADD R6 R6 R7 + 0x581C001D, // 005F LDCONST R7 K29 + 0x7C100600, // 0060 CALL R4 3 + 0x70020000, // 0061 JMP #0063 + 0xB0080000, // 0062 RAISE 2 R0 R0 + 0x50080000, // 0063 LDBOOL R2 0 0 + 0x880C0106, // 0064 GETMBR R3 R0 K6 + 0x4C100000, // 0065 LDNIL R4 + 0x1C0C0604, // 0066 EQ R3 R3 R4 + 0x780E000A, // 0067 JMPF R3 #0073 + 0x8C0C031E, // 0068 GETMET R3 R1 K30 + 0x5814001D, // 0069 LDCONST R5 K29 + 0x7C0C0400, // 006A CALL R3 2 + 0x8C0C071F, // 006B GETMET R3 R3 K31 + 0x58140020, // 006C LDCONST R5 K32 + 0x5818001D, // 006D LDCONST R6 K29 + 0x7C0C0600, // 006E CALL R3 3 + 0x54120FFE, // 006F LDINT R4 4095 + 0x2C0C0604, // 0070 AND R3 R3 R4 + 0x90020C03, // 0071 SETMBR R0 K6 R3 + 0x50080200, // 0072 LDBOOL R2 1 0 + 0x880C0109, // 0073 GETMBR R3 R0 K9 + 0x4C100000, // 0074 LDNIL R4 + 0x1C0C0604, // 0075 EQ R3 R3 R4 + 0x780E0003, // 0076 JMPF R3 #007B + 0x8C0C0121, // 0077 GETMET R3 R0 K33 + 0x7C0C0200, // 0078 CALL R3 1 + 0x90021203, // 0079 SETMBR R0 K9 R3 + 0x50080200, // 007A LDBOOL R2 1 0 + 0x780A0001, // 007B JMPF R2 #007E + 0x8C0C0122, // 007C GETMET R3 R0 K34 + 0x7C0C0200, // 007D CALL R3 1 + 0x80000000, // 007E RET 0 }) ) ); @@ -6063,109 +6140,26 @@ be_local_closure(Matter_Device_start, /* name */ ** Solidified class: Matter_Device ********************************************************************/ be_local_class(Matter_Device, - 36, + 38, NULL, - be_nested_map(112, + be_nested_map(116, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(signal_endpoints_changed, -1), be_const_closure(Matter_Device_signal_endpoints_changed_closure) }, - { be_const_key_weak(msg_send, 105), be_const_closure(Matter_Device_msg_send_closure) }, - { be_const_key_weak(sort_distinct, -1), be_const_static_closure(Matter_Device_sort_distinct_closure) }, - { be_const_key_weak(MtrInfo_one, -1), be_const_closure(Matter_Device_MtrInfo_one_closure) }, - { be_const_key_weak(plugins_persist, -1), be_const_var(2) }, - { be_const_key_weak(_init_basic_commissioning, -1), be_const_closure(Matter_Device__init_basic_commissioning_closure) }, - { be_const_key_weak(root_discriminator, -1), be_const_var(27) }, - { be_const_key_weak(hostname_wifi, 85), be_const_var(20) }, - { be_const_key_weak(plugins, 15), be_const_var(1) }, - { be_const_key_weak(start_operational_discovery_deferred, -1), be_const_closure(Matter_Device_start_operational_discovery_deferred_closure) }, - { be_const_key_weak(plugins_config, -1), be_const_var(3) }, - { be_const_key_weak(get_active_endpoints, -1), be_const_closure(Matter_Device_get_active_endpoints_closure) }, - { be_const_key_weak(is_commissioning_open, 56), be_const_closure(Matter_Device_is_commissioning_open_closure) }, - { be_const_key_weak(http_remotes, 34), be_const_var(26) }, - { be_const_key_weak(vendorid, -1), be_const_var(22) }, - { be_const_key_weak(ui, 77), be_const_var(9) }, - { be_const_key_weak(ipv4only, -1), be_const_var(29) }, - { be_const_key_weak(start_operational_discovery, 49), be_const_closure(Matter_Device_start_operational_discovery_closure) }, - { be_const_key_weak(_mdns_announce_hostname, -1), be_const_closure(Matter_Device__mdns_announce_hostname_closure) }, - { be_const_key_weak(bridge_remove_endpoint, 37), be_const_closure(Matter_Device_bridge_remove_endpoint_closure) }, - { be_const_key_weak(find_plugin_by_endpoint, -1), be_const_closure(Matter_Device_find_plugin_by_endpoint_closure) }, - { be_const_key_weak(start_mdns_announce_hostnames, -1), be_const_closure(Matter_Device_start_mdns_announce_hostnames_closure) }, - { be_const_key_weak(_start_udp, 2), be_const_closure(Matter_Device__start_udp_closure) }, - { be_const_key_weak(compute_qrcode_content, 0), be_const_closure(Matter_Device_compute_qrcode_content_closure) }, - { be_const_key_weak(msg_received, -1), be_const_closure(Matter_Device_msg_received_closure) }, - { be_const_key_weak(_instantiate_plugins_from_config, 75), be_const_closure(Matter_Device__instantiate_plugins_from_config_closure) }, - { be_const_key_weak(root_salt, 103), be_const_var(33) }, - { be_const_key_weak(udp_server, -1), be_const_var(5) }, - { be_const_key_weak(sessions, -1), be_const_var(8) }, - { be_const_key_weak(PASSCODE_INVALID, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(12, - ( (struct bvalue*) &(const bvalue[]) { - be_const_int(0), - be_const_int(11111111), - be_const_int(22222222), - be_const_int(33333333), - be_const_int(44444444), - be_const_int(55555555), - be_const_int(66666666), - be_const_int(77777777), - be_const_int(88888888), - be_const_int(99999999), - be_const_int(12345678), - be_const_int(87654321), - })) ) } )) }, - { be_const_key_weak(started, 93), be_const_var(0) }, - { be_const_key_weak(profiler, -1), be_const_var(6) }, - { be_const_key_weak(bridge_add_endpoint, 46), be_const_closure(Matter_Device_bridge_add_endpoint_closure) }, - { be_const_key_weak(productid, -1), be_const_var(23) }, - { be_const_key_weak(generate_random_passcode, -1), be_const_closure(Matter_Device_generate_random_passcode_closure) }, + { be_const_key_weak(bridge_add_endpoint, -1), be_const_closure(Matter_Device_bridge_add_endpoint_closure) }, { be_const_key_weak(load_param, -1), be_const_closure(Matter_Device_load_param_closure) }, - { be_const_key_weak(save_param, 62), be_const_closure(Matter_Device_save_param_closure) }, - { be_const_key_weak(init, -1), be_const_closure(Matter_Device_init_closure) }, - { be_const_key_weak(root_L, -1), be_const_var(35) }, - { be_const_key_weak(root_iterations, -1), be_const_var(32) }, - { be_const_key_weak(process_attribute_expansion, 86), be_const_closure(Matter_Device_process_attribute_expansion_closure) }, - { be_const_key_weak(_compute_pbkdf, -1), be_const_closure(Matter_Device__compute_pbkdf_closure) }, - { be_const_key_weak(commissioning_instance_wifi, -1), be_const_var(18) }, - { be_const_key_weak(register_commands, 45), be_const_closure(Matter_Device_register_commands_closure) }, - { be_const_key_weak(stop_basic_commissioning, -1), be_const_closure(Matter_Device_stop_basic_commissioning_closure) }, - { be_const_key_weak(MtrUpdate, -1), be_const_closure(Matter_Device_MtrUpdate_closure) }, - { be_const_key_weak(commissioning_admin_fabric, -1), be_const_var(17) }, - { be_const_key_weak(commissioning_L, -1), be_const_var(16) }, + { be_const_key_weak(compute_manual_pairing_code, 36), be_const_closure(Matter_Device_compute_manual_pairing_code_closure) }, + { be_const_key_weak(ipv4only, -1), be_const_var(29) }, { be_const_key_weak(conf_to_log, -1), be_const_static_closure(Matter_Device_conf_to_log_closure) }, - { be_const_key_weak(update_remotes_info, -1), be_const_closure(Matter_Device_update_remotes_info_closure) }, - { be_const_key_weak(get_plugin_class_displayname, -1), be_const_closure(Matter_Device_get_plugin_class_displayname_closure) }, - { be_const_key_weak(mdns_pase_eth, 65), be_const_var(24) }, - { be_const_key_weak(tick, -1), be_const_var(10) }, - { be_const_key_weak(mdns_pase_wifi, -1), be_const_var(25) }, - { be_const_key_weak(autoconf_device_map, -1), be_const_closure(Matter_Device_autoconf_device_map_closure) }, - { be_const_key_weak(remove_fabric, 67), be_const_closure(Matter_Device_remove_fabric_closure) }, - { be_const_key_weak(commissioning_instance_eth, -1), be_const_var(19) }, - { be_const_key_weak(start_commissioning_complete, 80), be_const_closure(Matter_Device_start_commissioning_complete_closure) }, - { be_const_key_weak(adjust_next_ep, 39), be_const_closure(Matter_Device_adjust_next_ep_closure) }, - { be_const_key_weak(commissioning_discriminator, 8), be_const_var(13) }, - { be_const_key_weak(PRODUCT_ID, 44), be_const_int(32768) }, - { be_const_key_weak(autoconf_sensors_list, -1), be_const_closure(Matter_Device_autoconf_sensors_list_closure) }, - { be_const_key_weak(UDP_PORT, 76), be_const_int(5540) }, - { be_const_key_weak(PBKDF_ITERATIONS, -1), be_const_int(1000) }, - { be_const_key_weak(every_250ms, 92), be_const_closure(Matter_Device_every_250ms_closure) }, - { be_const_key_weak(mdns_announce_PASE, 99), be_const_closure(Matter_Device_mdns_announce_PASE_closure) }, - { be_const_key_weak(mdns_remove_PASE, 50), be_const_closure(Matter_Device_mdns_remove_PASE_closure) }, - { be_const_key_weak(mdns_remove_op_discovery, -1), be_const_closure(Matter_Device_mdns_remove_op_discovery_closure) }, - { be_const_key_weak(mdns_announce_op_discovery_all_fabrics, -1), be_const_closure(Matter_Device_mdns_announce_op_discovery_all_fabrics_closure) }, - { be_const_key_weak(received_ack, -1), be_const_closure(Matter_Device_received_ack_closure) }, - { be_const_key_weak(start_basic_commissioning, -1), be_const_closure(Matter_Device_start_basic_commissioning_closure) }, - { be_const_key_weak(_trigger_read_sensors, -1), be_const_closure(Matter_Device__trigger_read_sensors_closure) }, - { be_const_key_weak(every_50ms, 69), be_const_closure(Matter_Device_every_50ms_closure) }, - { be_const_key_weak(every_second, -1), be_const_closure(Matter_Device_every_second_closure) }, - { be_const_key_weak(plugins_config_remotes, 70), be_const_var(4) }, - { be_const_key_weak(VENDOR_ID, -1), be_const_int(65521) }, - { be_const_key_weak(compute_manual_pairing_code, -1), be_const_closure(Matter_Device_compute_manual_pairing_code_closure) }, - { be_const_key_weak(get_plugin_remote_info, -1), be_const_closure(Matter_Device_get_plugin_remote_info_closure) }, - { be_const_key_weak(event_fabrics_saved, -1), be_const_closure(Matter_Device_event_fabrics_saved_closure) }, - { be_const_key_weak(autoconf_device, -1), be_const_closure(Matter_Device_autoconf_device_closure) }, - { be_const_key_weak(message_handler, -1), be_const_var(7) }, - { be_const_key_weak(start_root_basic_commissioning, -1), be_const_closure(Matter_Device_start_root_basic_commissioning_closure) }, + { be_const_key_weak(start_operational_discovery, -1), be_const_closure(Matter_Device_start_operational_discovery_closure) }, { be_const_key_weak(commissioning_w0, -1), be_const_var(15) }, - { be_const_key_weak(start_commissioning_complete_deferred, 68), be_const_closure(Matter_Device_start_commissioning_complete_deferred_closure) }, + { be_const_key_weak(every_second, -1), be_const_closure(Matter_Device_every_second_closure) }, + { be_const_key_weak(tick, 96), be_const_var(10) }, + { be_const_key_weak(profiler, 3), be_const_var(6) }, + { be_const_key_weak(MtrInfo, -1), be_const_closure(Matter_Device_MtrInfo_closure) }, + { be_const_key_weak(mdns_pase_eth, -1), be_const_var(24) }, + { be_const_key_weak(signal_endpoints_changed, 72), be_const_closure(Matter_Device_signal_endpoints_changed_closure) }, + { be_const_key_weak(MtrInfo_one, 58), be_const_closure(Matter_Device_MtrInfo_one_closure) }, + { be_const_key_weak(vendorid, 97), be_const_var(22) }, + { be_const_key_weak(commissioning_L, -1), be_const_var(16) }, { be_const_key_weak(plugins_classes, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { be_const_map( * be_nested_map(41, ( (struct bmapnode*) &(const bmapnode[]) { @@ -6211,33 +6205,120 @@ be_local_class(Matter_Device, { be_const_key_weak(humidity, -1), be_const_class(be_class_Matter_Plugin_Sensor_Humidity) }, { be_const_key_weak(http_flow, -1), be_const_class(be_class_Matter_Plugin_Bridge_Sensor_Flow) }, })) ) } )) }, - { be_const_key_weak(process_attribute_read_solo, -1), be_const_closure(Matter_Device_process_attribute_read_solo_closure) }, - { be_const_key_weak(attribute_updated, -1), be_const_closure(Matter_Device_attribute_updated_closure) }, - { be_const_key_weak(k2l_num, 57), be_const_static_closure(Matter_Device_k2l_num_closure) }, - { be_const_key_weak(FILENAME, 24), be_nested_str_weak(_matter_device_X2Ejson) }, - { be_const_key_weak(commissioning_open, -1), be_const_var(11) }, - { be_const_key_weak(MtrInfo, -1), be_const_closure(Matter_Device_MtrInfo_closure) }, - { be_const_key_weak(invoke_request, 47), be_const_closure(Matter_Device_invoke_request_closure) }, - { be_const_key_weak(next_ep, 84), be_const_var(31) }, - { be_const_key_weak(clean_remotes, -1), be_const_closure(Matter_Device_clean_remotes_closure) }, - { be_const_key_weak(MtrJoin, -1), be_const_closure(Matter_Device_MtrJoin_closure) }, - { be_const_key_weak(is_root_commissioning_open, 40), be_const_closure(Matter_Device_is_root_commissioning_open_closure) }, - { be_const_key_weak(find_plugin_by_friendly_name, -1), be_const_closure(Matter_Device_find_plugin_by_friendly_name_closure) }, - { be_const_key_weak(disable_bridge_mode, -1), be_const_var(30) }, - { be_const_key_weak(PASE_TIMEOUT, 36), be_const_int(600) }, - { be_const_key_weak(get_plugin_class_arg, -1), be_const_closure(Matter_Device_get_plugin_class_arg_closure) }, - { be_const_key_weak(register_http_remote, 31), be_const_closure(Matter_Device_register_http_remote_closure) }, - { be_const_key_weak(stop, 29), be_const_closure(Matter_Device_stop_closure) }, - { be_const_key_weak(mdns_announce_op_discovery, 27), be_const_closure(Matter_Device_mdns_announce_op_discovery_closure) }, - { be_const_key_weak(mdns_remove_op_discovery_all_fabrics, -1), be_const_closure(Matter_Device_mdns_remove_op_discovery_all_fabrics_closure) }, - { be_const_key_weak(hostname_eth, 16), be_const_var(21) }, - { be_const_key_weak(commissioning_salt, 107), be_const_var(14) }, - { be_const_key_weak(save_before_restart, 12), be_const_closure(Matter_Device_save_before_restart_closure) }, - { be_const_key_weak(root_w0, -1), be_const_var(34) }, - { be_const_key_weak(k2l, 7), be_const_static_closure(Matter_Device_k2l_closure) }, - { be_const_key_weak(commissioning_iterations, 3), be_const_var(12) }, - { be_const_key_weak(root_passcode, -1), be_const_var(28) }, + { be_const_key_weak(root_L, 28), be_const_var(35) }, + { be_const_key_weak(hostname_eth, -1), be_const_var(21) }, + { be_const_key_weak(autoconf_device, 11), be_const_closure(Matter_Device_autoconf_device_closure) }, + { be_const_key_weak(init, -1), be_const_closure(Matter_Device_init_closure) }, + { be_const_key_weak(root_salt, -1), be_const_var(33) }, + { be_const_key_weak(started, -1), be_const_var(0) }, + { be_const_key_weak(add_read_sensors_schedule, -1), be_const_closure(Matter_Device_add_read_sensors_schedule_closure) }, + { be_const_key_weak(hostname_wifi, 65), be_const_var(20) }, + { be_const_key_weak(disable_bridge_mode, 71), be_const_var(30) }, + { be_const_key_weak(generate_random_passcode, 66), be_const_closure(Matter_Device_generate_random_passcode_closure) }, + { be_const_key_weak(get_active_endpoints, -1), be_const_closure(Matter_Device_get_active_endpoints_closure) }, + { be_const_key_weak(_mdns_announce_hostname, -1), be_const_closure(Matter_Device__mdns_announce_hostname_closure) }, + { be_const_key_weak(productid, 84), be_const_var(23) }, + { be_const_key_weak(plugins_config_remotes, -1), be_const_var(4) }, + { be_const_key_weak(start_commissioning_complete, -1), be_const_closure(Matter_Device_start_commissioning_complete_closure) }, + { be_const_key_weak(bridge_remove_endpoint, -1), be_const_closure(Matter_Device_bridge_remove_endpoint_closure) }, + { be_const_key_weak(commissioning_admin_fabric, -1), be_const_var(17) }, + { be_const_key_weak(sort_distinct, 110), be_const_static_closure(Matter_Device_sort_distinct_closure) }, + { be_const_key_weak(mdns_announce_op_discovery_all_fabrics, -1), be_const_closure(Matter_Device_mdns_announce_op_discovery_all_fabrics_closure) }, + { be_const_key_weak(get_plugin_class_displayname, -1), be_const_closure(Matter_Device_get_plugin_class_displayname_closure) }, { be_const_key_weak(start, -1), be_const_closure(Matter_Device_start_closure) }, + { be_const_key_weak(adjust_next_ep, -1), be_const_closure(Matter_Device_adjust_next_ep_closure) }, + { be_const_key_weak(attribute_updated, 20), be_const_closure(Matter_Device_attribute_updated_closure) }, + { be_const_key_weak(PRODUCT_ID, -1), be_const_int(32768) }, + { be_const_key_weak(_instantiate_plugins_from_config, -1), be_const_closure(Matter_Device__instantiate_plugins_from_config_closure) }, + { be_const_key_weak(PASE_TIMEOUT, 17), be_const_int(600) }, + { be_const_key_weak(commissioning_discriminator, 56), be_const_var(13) }, + { be_const_key_weak(find_plugin_by_friendly_name, -1), be_const_closure(Matter_Device_find_plugin_by_friendly_name_closure) }, + { be_const_key_weak(msg_send, -1), be_const_closure(Matter_Device_msg_send_closure) }, + { be_const_key_weak(save_before_restart, 42), be_const_closure(Matter_Device_save_before_restart_closure) }, + { be_const_key_weak(UDP_PORT, -1), be_const_int(5540) }, + { be_const_key_weak(mdns_pase_wifi, -1), be_const_var(25) }, + { be_const_key_weak(start_root_basic_commissioning, -1), be_const_closure(Matter_Device_start_root_basic_commissioning_closure) }, + { be_const_key_weak(mdns_remove_op_discovery, 32), be_const_closure(Matter_Device_mdns_remove_op_discovery_closure) }, + { be_const_key_weak(invoke_request, 50), be_const_closure(Matter_Device_invoke_request_closure) }, + { be_const_key_weak(probe_sensor_time, 33), be_const_var(36) }, + { be_const_key_weak(commissioning_open, -1), be_const_var(11) }, + { be_const_key_weak(start_basic_commissioning, 101), be_const_closure(Matter_Device_start_basic_commissioning_closure) }, + { be_const_key_weak(commissioning_instance_wifi, -1), be_const_var(18) }, + { be_const_key_weak(read_sensors_scheduler, 27), be_const_closure(Matter_Device_read_sensors_scheduler_closure) }, + { be_const_key_weak(http_remotes, -1), be_const_var(26) }, + { be_const_key_weak(commissioning_iterations, -1), be_const_var(12) }, + { be_const_key_weak(PBKDF_ITERATIONS, -1), be_const_int(1000) }, + { be_const_key_weak(k2l, -1), be_const_static_closure(Matter_Device_k2l_closure) }, + { be_const_key_weak(start_operational_discovery_deferred, 48), be_const_closure(Matter_Device_start_operational_discovery_deferred_closure) }, + { be_const_key_weak(autoconf_device_map, -1), be_const_closure(Matter_Device_autoconf_device_map_closure) }, + { be_const_key_weak(mdns_announce_PASE, -1), be_const_closure(Matter_Device_mdns_announce_PASE_closure) }, + { be_const_key_weak(message_handler, -1), be_const_var(7) }, + { be_const_key_weak(every_50ms, -1), be_const_closure(Matter_Device_every_50ms_closure) }, + { be_const_key_weak(start_mdns_announce_hostnames, -1), be_const_closure(Matter_Device_start_mdns_announce_hostnames_closure) }, + { be_const_key_weak(_trigger_read_sensors, 95), be_const_closure(Matter_Device__trigger_read_sensors_closure) }, + { be_const_key_weak(every_250ms, -1), be_const_closure(Matter_Device_every_250ms_closure) }, + { be_const_key_weak(PASSCODE_INVALID, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + be_const_list( * be_nested_list(12, + ( (struct bvalue*) &(const bvalue[]) { + be_const_int(0), + be_const_int(11111111), + be_const_int(22222222), + be_const_int(33333333), + be_const_int(44444444), + be_const_int(55555555), + be_const_int(66666666), + be_const_int(77777777), + be_const_int(88888888), + be_const_int(99999999), + be_const_int(12345678), + be_const_int(87654321), + })) ) } )) }, + { be_const_key_weak(udp_server, 81), be_const_var(5) }, + { be_const_key_weak(_init_basic_commissioning, -1), be_const_closure(Matter_Device__init_basic_commissioning_closure) }, + { be_const_key_weak(MtrUpdate, -1), be_const_closure(Matter_Device_MtrUpdate_closure) }, + { be_const_key_weak(probe_sensor_timestamp, 37), be_const_var(37) }, + { be_const_key_weak(mdns_announce_op_discovery, 90), be_const_closure(Matter_Device_mdns_announce_op_discovery_closure) }, + { be_const_key_weak(remove_fabric, -1), be_const_closure(Matter_Device_remove_fabric_closure) }, + { be_const_key_weak(sessions, -1), be_const_var(8) }, + { be_const_key_weak(_compute_pbkdf, -1), be_const_closure(Matter_Device__compute_pbkdf_closure) }, + { be_const_key_weak(msg_received, 18), be_const_closure(Matter_Device_msg_received_closure) }, + { be_const_key_weak(k2l_num, 73), be_const_static_closure(Matter_Device_k2l_num_closure) }, + { be_const_key_weak(process_attribute_read_solo, 78), be_const_closure(Matter_Device_process_attribute_read_solo_closure) }, + { be_const_key_weak(is_commissioning_open, -1), be_const_closure(Matter_Device_is_commissioning_open_closure) }, + { be_const_key_weak(plugins_config, 47), be_const_var(3) }, + { be_const_key_weak(register_commands, -1), be_const_closure(Matter_Device_register_commands_closure) }, + { be_const_key_weak(root_w0, -1), be_const_var(34) }, + { be_const_key_weak(commissioning_salt, -1), be_const_var(14) }, + { be_const_key_weak(event_fabrics_saved, -1), be_const_closure(Matter_Device_event_fabrics_saved_closure) }, + { be_const_key_weak(compute_qrcode_content, 12), be_const_closure(Matter_Device_compute_qrcode_content_closure) }, + { be_const_key_weak(find_plugin_by_endpoint, -1), be_const_closure(Matter_Device_find_plugin_by_endpoint_closure) }, + { be_const_key_weak(update_remotes_info, 26), be_const_closure(Matter_Device_update_remotes_info_closure) }, + { be_const_key_weak(MtrJoin, -1), be_const_closure(Matter_Device_MtrJoin_closure) }, + { be_const_key_weak(start_commissioning_complete_deferred, 64), be_const_closure(Matter_Device_start_commissioning_complete_deferred_closure) }, + { be_const_key_weak(next_ep, -1), be_const_var(31) }, + { be_const_key_weak(stop, -1), be_const_closure(Matter_Device_stop_closure) }, + { be_const_key_weak(mdns_remove_PASE, 55), be_const_closure(Matter_Device_mdns_remove_PASE_closure) }, + { be_const_key_weak(plugins, -1), be_const_var(1) }, + { be_const_key_weak(plugins_persist, -1), be_const_var(2) }, + { be_const_key_weak(commissioning_instance_eth, 105), be_const_var(19) }, + { be_const_key_weak(_start_udp, -1), be_const_closure(Matter_Device__start_udp_closure) }, + { be_const_key_weak(get_plugin_remote_info, -1), be_const_closure(Matter_Device_get_plugin_remote_info_closure) }, + { be_const_key_weak(register_http_remote, -1), be_const_closure(Matter_Device_register_http_remote_closure) }, + { be_const_key_weak(root_passcode, -1), be_const_var(28) }, + { be_const_key_weak(mdns_remove_op_discovery_all_fabrics, -1), be_const_closure(Matter_Device_mdns_remove_op_discovery_all_fabrics_closure) }, + { be_const_key_weak(get_plugin_class_arg, -1), be_const_closure(Matter_Device_get_plugin_class_arg_closure) }, + { be_const_key_weak(FILENAME, -1), be_nested_str_weak(_matter_device_X2Ejson) }, + { be_const_key_weak(root_discriminator, -1), be_const_var(27) }, + { be_const_key_weak(clean_remotes, 21), be_const_closure(Matter_Device_clean_remotes_closure) }, + { be_const_key_weak(is_root_commissioning_open, -1), be_const_closure(Matter_Device_is_root_commissioning_open_closure) }, + { be_const_key_weak(stop_basic_commissioning, -1), be_const_closure(Matter_Device_stop_basic_commissioning_closure) }, + { be_const_key_weak(autoconf_sensors_list, -1), be_const_closure(Matter_Device_autoconf_sensors_list_closure) }, + { be_const_key_weak(save_param, -1), be_const_closure(Matter_Device_save_param_closure) }, + { be_const_key_weak(ui, -1), be_const_var(9) }, + { be_const_key_weak(received_ack, 9), be_const_closure(Matter_Device_received_ack_closure) }, + { be_const_key_weak(VENDOR_ID, 7), be_const_int(65521) }, + { be_const_key_weak(root_iterations, -1), be_const_var(32) }, + { be_const_key_weak(process_attribute_expansion, 1), be_const_closure(Matter_Device_process_attribute_expansion_closure) }, })), be_str_weak(Matter_Device) ); From c13886e00d68e4b1ccc1f6505a9ef371ea32d7ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?DUPONCHEEL=20S=C3=A9bastien?= Date: Mon, 25 Dec 2023 08:54:53 +0100 Subject: [PATCH 042/303] HDMI CEC: Fix HDMIType command (#20308) According to documentation HDMIType is from 0 to 5 but the actual check is lower than 1 and above or equal 6, so the function is never applied. Also note that setting the HDMIType to 0 use the default type value 4, that make impossible the emulation of a TV device. --- tasmota/tasmota_xdrv_driver/xdrv_70_1_hdmi_cec.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_70_1_hdmi_cec.ino b/tasmota/tasmota_xdrv_driver/xdrv_70_1_hdmi_cec.ino index e77e1a5b0..4a1daf136 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_70_1_hdmi_cec.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_70_1_hdmi_cec.ino @@ -189,7 +189,7 @@ void CmndHDMISend(void) { // void CmndHDMIType(void) { if (XdrvMailbox.data_len > 0) { - if ((XdrvMailbox.payload < 1) && (XdrvMailbox.payload >= CEC_Device::CDT_LAST)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < CEC_Device::CDT_LAST)) { uint8_t type = XdrvMailbox.payload; if (type != Settings->hdmi_cec_device_type) { Settings->hdmi_cec_device_type = XdrvMailbox.payload; From bebffa040f8ed1eaa6d727f171855f981f0de922 Mon Sep 17 00:00:00 2001 From: UBWH <72185209+UBWH@users.noreply.github.com> Date: Mon, 25 Dec 2023 16:13:32 +0800 Subject: [PATCH 043/303] Update xdrv_58_range_extender.ino (#20295) RESULT to RgxSSId command is not valid JSON BEFORE: RSL: RESULT = {"Rgx":{"Valid":"true","SSId":"solar_5BDBFC","Password":"MyPassword","IPAddress":"192.168.99.1","Subnetmask":"255.255.255.0"} AFTER RSL: RESULT = {"Rgx":{"Valid":"true","SSId":"solar_5BDBFC","Password":"MyPassword","IPAddress":"192.168.99.1","Subnetmask":"255.255.255.0"}} Not extra terminating '}' --- tasmota/tasmota_xdrv_driver/xdrv_58_range_extender.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_58_range_extender.ino b/tasmota/tasmota_xdrv_driver/xdrv_58_range_extender.ino index 3868dde46..d72880649 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_58_range_extender.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_58_range_extender.ino @@ -377,7 +377,7 @@ void CmndRgxPort(void) void ResponseRgxConfig(void) { RgxCheckConfig(); - Response_P(PSTR("{\"Rgx\":{\"Valid\":\"%s\",\"" D_CMND_SSID "\":\"%s\",\"" D_CMND_PASSWORD "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%_I\",\"" D_JSON_SUBNETMASK "\":\"%_I\"}"), + Response_P(PSTR("{\"Rgx\":{\"Valid\":\"%s\",\"" D_CMND_SSID "\":\"%s\",\"" D_CMND_PASSWORD "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%_I\",\"" D_JSON_SUBNETMASK "\":\"%_I\"}}"), (RgxSettings.status == RGX_CONFIG_INCOMPLETE) ? "false" : "true", EscapeJSONString(SettingsText(SET_RGX_SSID)).c_str(), EscapeJSONString(SettingsText(SET_RGX_PASSWORD)).c_str(), @@ -529,4 +529,4 @@ bool Xdrv58(uint32_t function) return result; } -#endif // USE_WIFI_RANGE_EXTENDER \ No newline at end of file +#endif // USE_WIFI_RANGE_EXTENDER From 2808653ad97b4b59b713d174416c549c9caaca41 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Mon, 25 Dec 2023 11:01:19 +0100 Subject: [PATCH 044/303] Moved Berry animate to its own `berry_animate` lib (#20309) * Moved Berry animate to its own `berry_animate` lib * Fix solidification * fix compilation * Fix compilation --- .github/workflows/Tasmota_build_devel.yml | 10 +- CHANGELOG.md | 1 + lib/libesp32/berry/gen.sh | 2 +- lib/libesp32/berry_animate/library.json | 17 + lib/libesp32/berry_animate/path.be | 2 + lib/libesp32/berry_animate/solidify_all.be | 99 + .../src/be_animate_module.c | 5 +- .../berry_animate/src/be_berry_leds_frame.cpp | 179 ++ .../src/be_leds_frame_lib.c | 2 + .../berry_animate/src/berry_animate.h | 8 + .../src/embedded/animate_0.be | 0 .../src/embedded/animate_1_core.be | 0 .../src/embedded/animate_2_animate_effects.be | 0 .../src/embedded/animate_9_module.be | 0 .../src/embedded/leds_frame_be_methods.be | 0 lib/libesp32/berry_animate/src/solidify/.keep | 0 .../src/solidify/solidified_animate_0.h | 7 + .../src/solidify/solidified_animate_1_core.h | 871 +++++++++ .../solidified_animate_2_animate_effects.h | 450 +++++ .../solidify/solidified_animate_9_module.h | 1592 +++++++++++++++++ .../solidified_leds_frame_be_methods.h | 186 ++ pio-tools/gen-berry-structures.py | 2 +- .../xdrv_52_3_berry_leds.ino | 188 +- .../tasmota_xdrv_driver/xdrv_52_9_berry.ino | 3 + 24 files changed, 3452 insertions(+), 172 deletions(-) create mode 100644 lib/libesp32/berry_animate/library.json create mode 100644 lib/libesp32/berry_animate/path.be create mode 100755 lib/libesp32/berry_animate/solidify_all.be rename lib/libesp32/{berry_tasmota => berry_animate}/src/be_animate_module.c (99%) create mode 100644 lib/libesp32/berry_animate/src/be_berry_leds_frame.cpp rename lib/libesp32/{berry_tasmota => berry_animate}/src/be_leds_frame_lib.c (96%) create mode 100644 lib/libesp32/berry_animate/src/berry_animate.h rename lib/libesp32/{berry_tasmota => berry_animate}/src/embedded/animate_0.be (100%) rename lib/libesp32/{berry_tasmota => berry_animate}/src/embedded/animate_1_core.be (100%) rename lib/libesp32/{berry_tasmota => berry_animate}/src/embedded/animate_2_animate_effects.be (100%) rename lib/libesp32/{berry_tasmota => berry_animate}/src/embedded/animate_9_module.be (100%) rename lib/libesp32/{berry_tasmota => berry_animate}/src/embedded/leds_frame_be_methods.be (100%) create mode 100644 lib/libesp32/berry_animate/src/solidify/.keep create mode 100644 lib/libesp32/berry_animate/src/solidify/solidified_animate_0.h create mode 100644 lib/libesp32/berry_animate/src/solidify/solidified_animate_1_core.h create mode 100644 lib/libesp32/berry_animate/src/solidify/solidified_animate_2_animate_effects.h create mode 100644 lib/libesp32/berry_animate/src/solidify/solidified_animate_9_module.h create mode 100644 lib/libesp32/berry_animate/src/solidify/solidified_leds_frame_be_methods.h diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml index 50eedbea2..48fc99fa4 100644 --- a/.github/workflows/Tasmota_build_devel.yml +++ b/.github/workflows/Tasmota_build_devel.yml @@ -38,14 +38,18 @@ jobs: run: | cd lib/libesp32/berry_matter ../berry/berry -s -g solidify_all.be + - name: Berry Animate Code + run: | + cd lib/libesp32/berry_animate + ../berry/berry -s -g solidify_all.be - name: LVGL Berry Code run: | cd lib/libesp32_lvgl/lv_binding_berry ../../libesp32/berry/berry -s -g solidify_all.be - uses: jason2866/upload-artifact@v2.0.2 with: - name: '["berry_tasmota", "berry_matter", "berry_lvgl", "berry_header"]' - path: '["./lib/libesp32/berry_tasmota/src/solidify", "./lib/libesp32/berry_matter/src/solidify", "./lib/libesp32_lvgl/lv_binding_berry/src/solidify", "./lib/libesp32/berry/generate"]' + name: '["berry_tasmota", "berry_matter", "berry_animate", "berry_lvgl", "berry_header"]' + path: '["./lib/libesp32/berry_tasmota/src/solidify", "./lib/libesp32/berry_matter/src/solidify", "./lib/libesp32/berry_animate/src/solidify", "./lib/libesp32_lvgl/lv_binding_berry/src/solidify", "./lib/libesp32/berry/generate"]' push_solidified: needs: be_solidify @@ -63,11 +67,13 @@ jobs: name: | berry_tasmota berry_matter + berrt_animate berry_lvgl berry_header path: | ./lib/libesp32/berry_tasmota/src/solidify ./lib/libesp32/berry_matter/src/solidify + ./lib/libesp32/berry_animate/src/solidify ./lib/libesp32_lvgl/lv_binding_berry/src/solidify ./lib/libesp32/berry/generate - uses: stefanzweifel/git-auto-commit-action@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a7795908..828a099c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file. ### Changed - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` (#20260) +- Moved Berry animate to its own `berry_animate` lib ### Fixed - Matter Contact sensor was not triggering any update (#20232) diff --git a/lib/libesp32/berry/gen.sh b/lib/libesp32/berry/gen.sh index 2df6ad838..a0edbd2df 100755 --- a/lib/libesp32/berry/gen.sh +++ b/lib/libesp32/berry/gen.sh @@ -5,4 +5,4 @@ # Included in the Platformio build process with `pio-tools/gen-berry-structures.py # rm -Rf ./generate/be_*.h -python3 tools/coc/coc -o generate src default ../berry_tasmota/src ../berry_mapping/src ../berry_int64/src ../../libesp32_lvgl/lv_binding_berry/src ../berry_matter/src/solidify ../berry_matter/src ../../libesp32_lvgl/lv_binding_berry/src/solidify ../../libesp32_lvgl/lv_binding_berry/generate -c default/berry_conf.h +python3 tools/coc/coc -o generate src default ../berry_tasmota/src ../berry_mapping/src ../berry_int64/src ../../libesp32_lvgl/lv_binding_berry/src ../berry_matter/src/solidify ../berry_matter/src ../berry_animate/src/solidify ../berry_animate/src ../../libesp32_lvgl/lv_binding_berry/src/solidify ../../libesp32_lvgl/lv_binding_berry/generate -c default/berry_conf.h diff --git a/lib/libesp32/berry_animate/library.json b/lib/libesp32/berry_animate/library.json new file mode 100644 index 000000000..3033e8a52 --- /dev/null +++ b/lib/libesp32/berry_animate/library.json @@ -0,0 +1,17 @@ +{ + "name": "Berry animation library for WS2812 leds", + "version": "0.1", + "description": "Berry animation library for WS2812 leds", + "license": "MIT", + "homepage": "https://github.com/arendst/Tasmota", + "frameworks": "arduino", + "platforms": "espressif32", + "authors": + { + "name": "Stephan Hadinger", + "maintainer": true + }, + "build": { + "flags": [ "-I$PROJECT_DIR/include", "-includetasmota_options.h" ] + } +} \ No newline at end of file diff --git a/lib/libesp32/berry_animate/path.be b/lib/libesp32/berry_animate/path.be new file mode 100644 index 000000000..afba51adc --- /dev/null +++ b/lib/libesp32/berry_animate/path.be @@ -0,0 +1,2 @@ +# empty module +# allows stand-alone `import path` diff --git a/lib/libesp32/berry_animate/solidify_all.be b/lib/libesp32/berry_animate/solidify_all.be new file mode 100755 index 000000000..cf19458aa --- /dev/null +++ b/lib/libesp32/berry_animate/solidify_all.be @@ -0,0 +1,99 @@ +#!/usr/bin/env -S ../berry/berry -s -g +# +# Berry solidify files + +import os +import global +import solidify +import string as string2 +import re + +import sys +sys.path().push('src/embedded') # allow to import from src/embedded + +# globals that need to exist to make compilation succeed +var globs = "path,ctypes_bytes_dyn,tasmota,ccronexpr,gpio,light,webclient,load,MD5,lv,light_state,udp,tcpclientasync," + "lv_clock,lv_clock_icon,lv_signal_arcs,lv_signal_bars,lv_wifi_arcs_icon,lv_wifi_arcs," + "lv_wifi_bars_icon,lv_wifi_bars," + "_lvgl," + "int64" + +for g:string2.split(globs, ",") + global.(g) = nil +end + +var prefix_dir = "src/embedded/" +var prefix_out = "src/solidify/" + +def sort(l) + # insertion sort + for i:1..size(l)-1 + var k = l[i] + var j = i + while (j > 0) && (l[j-1] > k) + l[j] = l[j-1] + j -= 1 + end + l[j] = k + end + return l +end + +def clean_directory(dir) + var file_list = os.listdir(dir) + for f : file_list + if f[0] == '.' continue end # ignore files starting with `.` + os.remove(dir + f) + end +end + +var pattern = "#@\\s*solidify:([A-Za-z0-9_.,]+)" + +def parse_file(fname, prefix_out) + print("Parsing: ", fname) + var f = open(prefix_dir + fname) + var src = f.read() + f.close() + # try to compile + var compiled = compile(src) + compiled() # run the compile code to instanciate the classes and modules + # output solidified + var fname_h = string2.split(fname, '.be')[0] + '.h' # take whatever is before the first '.be' + var fout = open(prefix_out + "solidified_" + fname_h, "w") + fout.write(f"/* Solidification of {fname_h} */\n") + fout.write("/********************************************************************\\\n") + fout.write("* Generated code, don't edit *\n") + fout.write("\\********************************************************************/\n") + fout.write('#include "be_constobj.h"\n') + + var directives = re.searchall(pattern, src) + # print(directives) + + for directive : directives + var object_list = string2.split(directive[1], ',') + var object_name = object_list[0] + var weak = (object_list.find('weak') != nil) # do we solidify with weak strings? + var o = global + var cl_name = nil + var obj_name = nil + for subname : string2.split(object_name, '.') + o = o.(subname) + cl_name = obj_name + obj_name = subname + end + solidify.dump(o, weak, fout, cl_name) + end + + fout.write("/********************************************************************/\n") + fout.write("/* End of solidification */\n") + fout.close() +end + +clean_directory(prefix_out) + +var src_file_list = os.listdir(prefix_dir) +src_file_list = sort(src_file_list) +for src_file : src_file_list + if src_file[0] == '.' continue end + parse_file(src_file, prefix_out) +end diff --git a/lib/libesp32/berry_tasmota/src/be_animate_module.c b/lib/libesp32/berry_animate/src/be_animate_module.c similarity index 99% rename from lib/libesp32/berry_tasmota/src/be_animate_module.c rename to lib/libesp32/berry_animate/src/be_animate_module.c index 3c920e6be..83ba2bb62 100644 --- a/lib/libesp32/berry_tasmota/src/be_animate_module.c +++ b/lib/libesp32/berry_animate/src/be_animate_module.c @@ -21,6 +21,7 @@ * `animate` global module \*******************************************************************/ +#ifdef USE_BERRY #include "be_constobj.h" #include "be_mapping.h" @@ -238,4 +239,6 @@ assert(o.animate(7000) == -1000) -*/ \ No newline at end of file +*/ + +#endif // USE_BERRY diff --git a/lib/libesp32/berry_animate/src/be_berry_leds_frame.cpp b/lib/libesp32/berry_animate/src/be_berry_leds_frame.cpp new file mode 100644 index 000000000..70917593f --- /dev/null +++ b/lib/libesp32/berry_animate/src/be_berry_leds_frame.cpp @@ -0,0 +1,179 @@ +/* + xdrv_52_3_berry_leds.ino - Berry scripting language, native fucnctions + + Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry + + 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 . +*/ + + +#ifdef USE_BERRY + +#include + +#ifdef USE_WS2812 + +extern uint16_t changeUIntScale(uint16_t inum, uint16_t ifrom_min, uint16_t ifrom_max,uint16_t ito_min, uint16_t ito_max); +extern uint32_t ApplyBriGamma(uint32_t color_a /* 0xRRGGBB */, uint32_t bri /* 0..255 */, bool gamma); + +extern "C" { + // Leds_frame.blend(color1:int, color2:int, alpha:int) -> int + // + int32_t be_leds_blend(bvm *vm); + int32_t be_leds_blend(bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top >= 3 && be_isint(vm, 1) && be_isint(vm, 2) && be_isint(vm, 3)) { + uint32_t color_a = be_toint(vm, 1); + uint32_t color_b = be_toint(vm, 2); + uint32_t alpha = be_toint(vm, 3); + uint32_t r = (color_a >> 16) & 0xFF; + uint32_t g = (color_a >> 8) & 0xFF; + uint32_t b = (color_a ) & 0xFF; + uint32_t a = (color_a >> 24) & 0xFF; + uint32_t r2 = (color_b >> 16) & 0xFF; + uint32_t g2 = (color_b >> 8) & 0xFF; + uint32_t b2 = (color_b ) & 0xFF; + uint32_t a2 = (color_b >> 24) & 0xFF; + uint32_t r3 = changeUIntScale(alpha, 0, 255, r2, r); + uint32_t g3 = changeUIntScale(alpha, 0, 255, g2, g); + uint32_t b3 = changeUIntScale(alpha, 0, 255, b2, b); + uint32_t a3 = changeUIntScale(alpha, 0, 255, a2, a); + uint32_t rgb = (a3 << 24) | (r3 << 16) | (g3 << 8) | b3; + be_pushint(vm, rgb); + be_return(vm); + } + be_raise(vm, "type_error", nullptr); + } + + // Leds_frame.blend_pixels(dest:bytes(), foreground:bytes) -> nil + // Destination can be the same as foreground or background + // + // All calculation are done in `0xAARRGGBB` format, AA=0 if opaque (i.e. ignored) + // Background has always alpha = 0 (any other value is ignored) - for simplification + // Size is truncated to smallest of all 3 buffers + int32_t be_leds_blend_pixels(bvm *vm); + int32_t be_leds_blend_pixels(bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top >= 2 && be_isbytes(vm, 2)) { + size_t dest_len = 0; + uint32_t * dest_buf = (uint32_t*) be_tobytes(vm, 1, &dest_len); + // back = dest for now, could be changed in the future + size_t back_len = 0; + const uint32_t * back_buf = (const uint32_t*) be_tobytes(vm, 1, &back_len); + size_t fore_len = 0; + const uint32_t * fore_buf = (const uint32_t*) be_tobytes(vm, 2, &fore_len); + + if (fore_len < dest_len) { dest_len = fore_len; } + if (back_len < dest_len) { dest_len = back_len; } + size_t pixels_count = dest_len / 4; + if (pixels_count > 0) { + uint32_t * dest = (uint32_t *)dest_buf; + uint32_t * back = (uint32_t *)back_buf; + uint32_t * fore = (uint32_t *)fore_buf; + for (size_t i = 0; i < pixels_count; i++) { + uint32_t back_argb = back[i]; + uint32_t fore_argb = fore[i]; + uint32_t fore_alpha = (fore_argb >> 24) & 0xFF; + uint32_t dest_rgb_new = back_argb; + if (fore_alpha == 0) { // opaque layer, copy value from fore + dest_rgb_new = fore_argb; + } else if (fore_alpha == 255) { // fore is transparent, use back + // nothing to do, dest_rgb_new = back_argb above + } else { + uint32_t back_r = (back_argb >> 16) & 0xFF; + uint32_t fore_r = (fore_argb >> 16) & 0xFF; + uint32_t back_g = (back_argb >> 8) & 0xFF; + uint32_t fore_g = (fore_argb >> 8) & 0xFF; + uint32_t back_b = (back_argb ) & 0xFF; + uint32_t fore_b = (fore_argb ) & 0xFF; + uint32_t dest_r_new = changeUIntScale(fore_alpha, 0, 255, fore_r, back_r); + uint32_t dest_g_new = changeUIntScale(fore_alpha, 0, 255, fore_g, back_g); + uint32_t dest_b_new = changeUIntScale(fore_alpha, 0, 255, fore_b, back_b); + dest_rgb_new = (dest_r_new << 16) | (dest_g_new << 8) | dest_b_new; + } + dest[i] = dest_rgb_new; + } + } + be_return_nil(vm); + } + be_raise(vm, "type_error", nullptr); + } + + // Leds_frame.fill_pixels(dest:bytes(), color:int) -> nil + // + // Fill buffer with same color + int32_t be_leds_fill_pixels(bvm *vm); + int32_t be_leds_fill_pixels(bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top >= 2 && be_isint(vm, 2)) { + size_t dest_len = 0; + uint32_t * dest_buf = (uint32_t*) be_tobytes(vm, 1, &dest_len); + uint32_t color = be_toint(vm, 2); + + size_t pixels_count = dest_len / 4; + if (pixels_count > 0) { + uint32_t * dest = (uint32_t *)dest_buf; + for (size_t i = 0; i < pixels_count; i++) { + dest[i] = color; + } + } + be_return_nil(vm); + } + be_raise(vm, "type_error", nullptr); + } + + // Leds_frame.paste_pixels(neopixel:bytes(), led_buffer:bytes(), bri:int 0..100, gamma:bool) + // + // Copy from ARGB buffer to GRB + int32_t be_leds_paste_pixels(bvm *vm); + int32_t be_leds_paste_pixels(bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top >= 2 && be_isbytes(vm, 2)) { + size_t src_len = 0; + uint32_t * src_buf = (uint32_t*) be_tobytes(vm, 1, &src_len); + size_t dest_len = 0; + uint8_t * dest_buf = (uint8_t*) be_tobytes(vm, 2, &dest_len); + + uint32_t bri255 = 255; + if (top >= 3 && be_isint(vm, 3)) { + bri255 = be_toint(vm, 3); + } + bool gamma = false; + if (top >= 4 && be_isbool(vm, 4)) { + gamma = be_tobool(vm, 4); + } + + size_t pixels_count = src_len / 4; + if (pixels_count > dest_len / 3) { pixels_count = dest_len / 3; } + if (pixels_count > 0) { + for (size_t i = 0; i < pixels_count; i++) { + uint32_t src_argb = ApplyBriGamma(src_buf[i], bri255, gamma); + uint32_t src_r = (src_argb >> 16) & 0xFF; + uint32_t src_g = (src_argb >> 8) & 0xFF; + uint32_t src_b = (src_argb ) & 0xFF; + dest_buf[i * 3 + 0] = src_g; + dest_buf[i * 3 + 1] = src_r; + dest_buf[i * 3 + 2] = src_b; + } + } + be_return_nil(vm); + } + be_raise(vm, "type_error", nullptr); + } + + +} + +#endif // USE_WS2812 +#endif // USE_BERRY diff --git a/lib/libesp32/berry_tasmota/src/be_leds_frame_lib.c b/lib/libesp32/berry_animate/src/be_leds_frame_lib.c similarity index 96% rename from lib/libesp32/berry_tasmota/src/be_leds_frame_lib.c rename to lib/libesp32/berry_animate/src/be_leds_frame_lib.c index a1b1c353b..36d82d28e 100644 --- a/lib/libesp32/berry_tasmota/src/be_leds_frame_lib.c +++ b/lib/libesp32/berry_animate/src/be_leds_frame_lib.c @@ -3,6 +3,7 @@ * *******************************************************************/ +#ifdef USE_BERRY #include "be_constobj.h" #ifdef USE_WS2812 @@ -37,3 +38,4 @@ class be_class_Leds_frame (scope: global, name: Leds_frame, super:be_class_bytes #include "be_fixed_be_class_Leds_frame.h" #endif // USE_WS2812 +#endif // USE_BERRY diff --git a/lib/libesp32/berry_animate/src/berry_animate.h b/lib/libesp32/berry_animate/src/berry_animate.h new file mode 100644 index 000000000..87e27bd27 --- /dev/null +++ b/lib/libesp32/berry_animate/src/berry_animate.h @@ -0,0 +1,8 @@ +// force include of module by including this file + +#ifndef __BERRY_ANIMATE__ +#define __BERRY_ANIMATE__ + + + +#endif // __BERRY_ANIMATE__ diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_0.be b/lib/libesp32/berry_animate/src/embedded/animate_0.be similarity index 100% rename from lib/libesp32/berry_tasmota/src/embedded/animate_0.be rename to lib/libesp32/berry_animate/src/embedded/animate_0.be diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_1_core.be b/lib/libesp32/berry_animate/src/embedded/animate_1_core.be similarity index 100% rename from lib/libesp32/berry_tasmota/src/embedded/animate_1_core.be rename to lib/libesp32/berry_animate/src/embedded/animate_1_core.be diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_2_animate_effects.be b/lib/libesp32/berry_animate/src/embedded/animate_2_animate_effects.be similarity index 100% rename from lib/libesp32/berry_tasmota/src/embedded/animate_2_animate_effects.be rename to lib/libesp32/berry_animate/src/embedded/animate_2_animate_effects.be diff --git a/lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be b/lib/libesp32/berry_animate/src/embedded/animate_9_module.be similarity index 100% rename from lib/libesp32/berry_tasmota/src/embedded/animate_9_module.be rename to lib/libesp32/berry_animate/src/embedded/animate_9_module.be diff --git a/lib/libesp32/berry_tasmota/src/embedded/leds_frame_be_methods.be b/lib/libesp32/berry_animate/src/embedded/leds_frame_be_methods.be similarity index 100% rename from lib/libesp32/berry_tasmota/src/embedded/leds_frame_be_methods.be rename to lib/libesp32/berry_animate/src/embedded/leds_frame_be_methods.be diff --git a/lib/libesp32/berry_animate/src/solidify/.keep b/lib/libesp32/berry_animate/src/solidify/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/lib/libesp32/berry_animate/src/solidify/solidified_animate_0.h b/lib/libesp32/berry_animate/src/solidify/solidified_animate_0.h new file mode 100644 index 000000000..a0a262928 --- /dev/null +++ b/lib/libesp32/berry_animate/src/solidify/solidified_animate_0.h @@ -0,0 +1,7 @@ +/* Solidification of animate_0.h */ +/********************************************************************\ +* Generated code, don't edit * +\********************************************************************/ +#include "be_constobj.h" +/********************************************************************/ +/* End of solidification */ diff --git a/lib/libesp32/berry_animate/src/solidify/solidified_animate_1_core.h b/lib/libesp32/berry_animate/src/solidify/solidified_animate_1_core.h new file mode 100644 index 000000000..280b7de5c --- /dev/null +++ b/lib/libesp32/berry_animate/src/solidify/solidified_animate_1_core.h @@ -0,0 +1,871 @@ +/* Solidification of animate_1_core.h */ +/********************************************************************\ +* Generated code, don't edit * +\********************************************************************/ +#include "be_constobj.h" + +extern const bclass be_class_Animate_core; + +/******************************************************************** +** Solidified function: clear +********************************************************************/ +be_local_closure(Animate_core_clear, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(stop), + /* K1 */ be_nested_str_weak(strip), + /* K2 */ be_nested_str_weak(clear), + }), + be_str_weak(clear), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x88040101, // 0002 GETMBR R1 R0 K1 + 0x8C040302, // 0003 GETMET R1 R1 K2 + 0x7C040200, // 0004 CALL R1 1 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_strip_bri +********************************************************************/ +be_local_closure(Animate_core_set_strip_bri, /* name */ + be_nested_proto( + 10, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(strip), + /* K1 */ be_nested_str_weak(set_bri), + /* K2 */ be_nested_str_weak(tasmota), + /* K3 */ be_nested_str_weak(scale_uint), + /* K4 */ be_nested_str_weak(bri), + /* K5 */ be_const_int(0), + }), + be_str_weak(set_strip_bri), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0xB80E0400, // 0002 GETNGBL R3 K2 + 0x8C0C0703, // 0003 GETMET R3 R3 K3 + 0x88140104, // 0004 GETMBR R5 R0 K4 + 0x58180005, // 0005 LDCONST R6 K5 + 0x541E0063, // 0006 LDINT R7 100 + 0x58200005, // 0007 LDCONST R8 K5 + 0x542600FE, // 0008 LDINT R9 255 + 0x7C0C0C00, // 0009 CALL R3 6 + 0x7C040400, // 000A CALL R1 2 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: remove_painter +********************************************************************/ +be_local_closure(Animate_core_remove_painter, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(painters), + /* K1 */ be_nested_str_weak(remove), + /* K2 */ be_nested_str_weak(find), + /* K3 */ be_nested_str_weak(clear), + }), + be_str_weak(remove_painter), + &be_const_str_solidified, + ( &(const binstruction[13]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x200C0203, // 0002 NE R3 R1 R3 + 0x780E0005, // 0003 JMPF R3 #000A + 0x8C0C0501, // 0004 GETMET R3 R2 K1 + 0x8C140502, // 0005 GETMET R5 R2 K2 + 0x5C1C0200, // 0006 MOVE R7 R1 + 0x7C140400, // 0007 CALL R5 2 + 0x7C0C0400, // 0008 CALL R3 2 + 0x70020001, // 0009 JMP #000C + 0x8C0C0503, // 000A GETMET R3 R2 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: stop +********************************************************************/ +be_local_closure(Animate_core_stop, /* name */ + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_str_weak(running), + /* K1 */ be_nested_str_weak(animators), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(stop), + /* K4 */ be_const_int(1), + /* K5 */ be_nested_str_weak(tasmota), + /* K6 */ be_nested_str_weak(remove_fast_loop), + /* K7 */ be_nested_str_weak(fast_loop_cb), + }), + be_str_weak(stop), + &be_const_str_solidified, + ( &(const binstruction[19]) { /* code */ + 0x50040000, // 0000 LDBOOL R1 0 0 + 0x90020001, // 0001 SETMBR R0 K0 R1 + 0x88040101, // 0002 GETMBR R1 R0 K1 + 0x58080002, // 0003 LDCONST R2 K2 + 0x600C000C, // 0004 GETGBL R3 G12 + 0x5C100200, // 0005 MOVE R4 R1 + 0x7C0C0200, // 0006 CALL R3 1 + 0x140C0403, // 0007 LT R3 R2 R3 + 0x780E0004, // 0008 JMPF R3 #000E + 0x940C0202, // 0009 GETIDX R3 R1 R2 + 0x8C0C0703, // 000A GETMET R3 R3 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0x00080504, // 000C ADD R2 R2 K4 + 0x7001FFF5, // 000D JMP #0004 + 0xB80E0A00, // 000E GETNGBL R3 K5 + 0x8C0C0706, // 000F GETMET R3 R3 K6 + 0x88140107, // 0010 GETMBR R5 R0 K7 + 0x7C0C0400, // 0011 CALL R3 2 + 0x80000000, // 0012 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_bri +********************************************************************/ +be_local_closure(Animate_core_get_bri, /* name */ + be_nested_proto( + 3, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(bri), + }), + be_str_weak(get_bri), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x80040400, // 0001 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_bri +********************************************************************/ +be_local_closure(Animate_core_set_bri, /* name */ + be_nested_proto( + 4, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(bri), + /* K1 */ be_nested_str_weak(set_strip_bri), + }), + be_str_weak(set_bri), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x8C080101, // 0001 GETMET R2 R0 K1 + 0x7C080200, // 0002 CALL R2 1 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_painter +********************************************************************/ +be_local_closure(Animate_core_add_painter, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(painters), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(push), + }), + be_str_weak(add_painter), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x4C0C0000, // 0004 LDNIL R3 + 0x1C080403, // 0005 EQ R2 R2 R3 + 0x780A0003, // 0006 JMPF R2 #000B + 0x88080100, // 0007 GETMBR R2 R0 K0 + 0x8C080502, // 0008 GETMET R2 R2 K2 + 0x5C100200, // 0009 MOVE R4 R1 + 0x7C080400, // 000A CALL R2 2 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: fast_loop +********************************************************************/ +be_local_closure(Animate_core_fast_loop, /* name */ + be_nested_proto( + 13, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[28]) { /* constants */ + /* K0 */ be_nested_str_weak(running), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(time_reached), + /* K3 */ be_nested_str_weak(fast_loop_next), + /* K4 */ be_nested_str_weak(strip), + /* K5 */ be_nested_str_weak(can_show), + /* K6 */ be_nested_str_weak(frame), + /* K7 */ be_nested_str_weak(fill_pixels), + /* K8 */ be_nested_str_weak(back_color), + /* K9 */ be_const_int(0), + /* K10 */ be_nested_str_weak(millis), + /* K11 */ be_nested_str_weak(FAST_LOOP_MIN), + /* K12 */ be_nested_str_weak(animators), + /* K13 */ be_nested_str_weak(animate), + /* K14 */ be_const_int(1), + /* K15 */ be_nested_str_weak(layer), + /* K16 */ be_nested_str_weak(painters), + /* K17 */ be_const_int(-16777216), + /* K18 */ be_nested_str_weak(paint), + /* K19 */ be_nested_str_weak(blend_pixels), + /* K20 */ be_nested_str_weak(obj), + /* K21 */ be_nested_str_weak(mth), + /* K22 */ be_nested_str_weak(paste_pixels), + /* K23 */ be_nested_str_weak(pixels_buffer), + /* K24 */ be_nested_str_weak(get_bri), + /* K25 */ be_nested_str_weak(get_gamma), + /* K26 */ be_nested_str_weak(dirty), + /* K27 */ be_nested_str_weak(show), + }), + be_str_weak(fast_loop), + &be_const_str_solidified, + ( &(const binstruction[84]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x78060050, // 0001 JMPF R1 #0053 + 0xB8060200, // 0002 GETNGBL R1 K1 + 0x8C040302, // 0003 GETMET R1 R1 K2 + 0x880C0103, // 0004 GETMBR R3 R0 K3 + 0x7C040400, // 0005 CALL R1 2 + 0x7806004B, // 0006 JMPF R1 #0053 + 0x88040104, // 0007 GETMBR R1 R0 K4 + 0x8C040305, // 0008 GETMET R1 R1 K5 + 0x7C040200, // 0009 CALL R1 1 + 0x78060047, // 000A JMPF R1 #0053 + 0x88040106, // 000B GETMBR R1 R0 K6 + 0x8C040307, // 000C GETMET R1 R1 K7 + 0x880C0108, // 000D GETMBR R3 R0 K8 + 0x7C040400, // 000E CALL R1 2 + 0x58040009, // 000F LDCONST R1 K9 + 0xB80A0200, // 0010 GETNGBL R2 K1 + 0x8C08050A, // 0011 GETMET R2 R2 K10 + 0x7C080200, // 0012 CALL R2 1 + 0x880C010B, // 0013 GETMBR R3 R0 K11 + 0x000C0403, // 0014 ADD R3 R2 R3 + 0x90020603, // 0015 SETMBR R0 K3 R3 + 0x600C000C, // 0016 GETGBL R3 G12 + 0x8810010C, // 0017 GETMBR R4 R0 K12 + 0x7C0C0200, // 0018 CALL R3 1 + 0x140C0203, // 0019 LT R3 R1 R3 + 0x780E0006, // 001A JMPF R3 #0022 + 0x880C010C, // 001B GETMBR R3 R0 K12 + 0x940C0601, // 001C GETIDX R3 R3 R1 + 0x8C0C070D, // 001D GETMET R3 R3 K13 + 0x5C140400, // 001E MOVE R5 R2 + 0x7C0C0400, // 001F CALL R3 2 + 0x0004030E, // 0020 ADD R1 R1 K14 + 0x7001FFF3, // 0021 JMP #0016 + 0x58040009, // 0022 LDCONST R1 K9 + 0x880C0106, // 0023 GETMBR R3 R0 K6 + 0x8810010F, // 0024 GETMBR R4 R0 K15 + 0x6014000C, // 0025 GETGBL R5 G12 + 0x88180110, // 0026 GETMBR R6 R0 K16 + 0x7C140200, // 0027 CALL R5 1 + 0x14140205, // 0028 LT R5 R1 R5 + 0x7816000D, // 0029 JMPF R5 #0038 + 0x8C140907, // 002A GETMET R5 R4 K7 + 0x581C0011, // 002B LDCONST R7 K17 + 0x7C140400, // 002C CALL R5 2 + 0x88140110, // 002D GETMBR R5 R0 K16 + 0x94140A01, // 002E GETIDX R5 R5 R1 + 0x8C140B12, // 002F GETMET R5 R5 K18 + 0x5C1C0800, // 0030 MOVE R7 R4 + 0x7C140400, // 0031 CALL R5 2 + 0x78160002, // 0032 JMPF R5 #0036 + 0x8C140713, // 0033 GETMET R5 R3 K19 + 0x5C1C0800, // 0034 MOVE R7 R4 + 0x7C140400, // 0035 CALL R5 2 + 0x0004030E, // 0036 ADD R1 R1 K14 + 0x7001FFEC, // 0037 JMP #0025 + 0x88140114, // 0038 GETMBR R5 R0 K20 + 0x88180115, // 0039 GETMBR R6 R0 K21 + 0x78160003, // 003A JMPF R5 #003F + 0x781A0002, // 003B JMPF R6 #003F + 0x5C1C0C00, // 003C MOVE R7 R6 + 0x5C200A00, // 003D MOVE R8 R5 + 0x7C1C0200, // 003E CALL R7 1 + 0x8C1C010D, // 003F GETMET R7 R0 K13 + 0x7C1C0200, // 0040 CALL R7 1 + 0x881C0106, // 0041 GETMBR R7 R0 K6 + 0x8C1C0F16, // 0042 GETMET R7 R7 K22 + 0x88240104, // 0043 GETMBR R9 R0 K4 + 0x8C241317, // 0044 GETMET R9 R9 K23 + 0x7C240200, // 0045 CALL R9 1 + 0x88280104, // 0046 GETMBR R10 R0 K4 + 0x8C281518, // 0047 GETMET R10 R10 K24 + 0x7C280200, // 0048 CALL R10 1 + 0x882C0104, // 0049 GETMBR R11 R0 K4 + 0x8C2C1719, // 004A GETMET R11 R11 K25 + 0x7C2C0200, // 004B CALL R11 1 + 0x7C1C0800, // 004C CALL R7 4 + 0x881C0104, // 004D GETMBR R7 R0 K4 + 0x8C1C0F1A, // 004E GETMET R7 R7 K26 + 0x7C1C0200, // 004F CALL R7 1 + 0x881C0104, // 0050 GETMBR R7 R0 K4 + 0x8C1C0F1B, // 0051 GETMET R7 R7 K27 + 0x7C1C0200, // 0052 CALL R7 1 + 0x80000000, // 0053 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: remove_animator +********************************************************************/ +be_local_closure(Animate_core_remove_animator, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(animators), + /* K1 */ be_nested_str_weak(remove), + /* K2 */ be_nested_str_weak(find), + /* K3 */ be_nested_str_weak(clear), + }), + be_str_weak(remove_animator), + &be_const_str_solidified, + ( &(const binstruction[13]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x200C0203, // 0002 NE R3 R1 R3 + 0x780E0005, // 0003 JMPF R3 #000A + 0x8C0C0501, // 0004 GETMET R3 R2 K1 + 0x8C140502, // 0005 GETMET R5 R2 K2 + 0x5C1C0200, // 0006 MOVE R7 R1 + 0x7C140400, // 0007 CALL R5 2 + 0x7C0C0400, // 0008 CALL R3 2 + 0x70020001, // 0009 JMP #000C + 0x8C0C0503, // 000A GETMET R3 R2 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: animate +********************************************************************/ +be_local_closure(Animate_core_animate, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(animate), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_current +********************************************************************/ +be_local_closure(Animate_core_set_current, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(global), + /* K1 */ be_nested_str_weak(_cur_anim), + }), + be_str_weak(set_current), + &be_const_str_solidified, + ( &(const binstruction[ 3]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x90060200, // 0001 SETMBR R1 K1 R0 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_core_init, /* name */ + be_nested_proto( + 7, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 1]) { + be_nested_proto( + 2, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(fast_loop), + }), + be_str_weak(_anonymous_), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x7C000200, // 0002 CALL R0 1 + 0x80000000, // 0003 RET 0 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[15]) { /* constants */ + /* K0 */ be_nested_str_weak(animate), + /* K1 */ be_nested_str_weak(strip), + /* K2 */ be_nested_str_weak(bri), + /* K3 */ be_nested_str_weak(set_strip_bri), + /* K4 */ be_nested_str_weak(running), + /* K5 */ be_nested_str_weak(pixel_count), + /* K6 */ be_nested_str_weak(animators), + /* K7 */ be_nested_str_weak(painters), + /* K8 */ be_nested_str_weak(clear), + /* K9 */ be_nested_str_weak(frame), + /* K10 */ be_nested_str_weak(layer), + /* K11 */ be_nested_str_weak(fast_loop_cb), + /* K12 */ be_nested_str_weak(back_color), + /* K13 */ be_const_int(0), + /* K14 */ be_nested_str_weak(set_current), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[37]) { /* code */ + 0xA40E0000, // 0000 IMPORT R3 K0 + 0x90020201, // 0001 SETMBR R0 K1 R1 + 0x4C100000, // 0002 LDNIL R4 + 0x1C100404, // 0003 EQ R4 R2 R4 + 0x78120000, // 0004 JMPF R4 #0006 + 0x540A0031, // 0005 LDINT R2 50 + 0x90020402, // 0006 SETMBR R0 K2 R2 + 0x8C100103, // 0007 GETMET R4 R0 K3 + 0x7C100200, // 0008 CALL R4 1 + 0x50100000, // 0009 LDBOOL R4 0 0 + 0x90020804, // 000A SETMBR R0 K4 R4 + 0x8C100305, // 000B GETMET R4 R1 K5 + 0x7C100200, // 000C CALL R4 1 + 0x90020A04, // 000D SETMBR R0 K5 R4 + 0x60100012, // 000E GETGBL R4 G18 + 0x7C100000, // 000F CALL R4 0 + 0x90020C04, // 0010 SETMBR R0 K6 R4 + 0x60100012, // 0011 GETGBL R4 G18 + 0x7C100000, // 0012 CALL R4 0 + 0x90020E04, // 0013 SETMBR R0 K7 R4 + 0x8C100108, // 0014 GETMET R4 R0 K8 + 0x7C100200, // 0015 CALL R4 1 + 0x8C100709, // 0016 GETMET R4 R3 K9 + 0x88180105, // 0017 GETMBR R6 R0 K5 + 0x7C100400, // 0018 CALL R4 2 + 0x90021204, // 0019 SETMBR R0 K9 R4 + 0x8C100709, // 001A GETMET R4 R3 K9 + 0x88180105, // 001B GETMBR R6 R0 K5 + 0x7C100400, // 001C CALL R4 2 + 0x90021404, // 001D SETMBR R0 K10 R4 + 0x84100000, // 001E CLOSURE R4 P0 + 0x90021604, // 001F SETMBR R0 K11 R4 + 0x9002190D, // 0020 SETMBR R0 K12 K13 + 0x8C10010E, // 0021 GETMET R4 R0 K14 + 0x7C100200, // 0022 CALL R4 1 + 0xA0000000, // 0023 CLOSE R0 + 0x80000000, // 0024 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_cb +********************************************************************/ +be_local_closure(Animate_core_set_cb, /* name */ + be_nested_proto( + 3, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(obj), + /* K1 */ be_nested_str_weak(mth), + }), + be_str_weak(set_cb), + &be_const_str_solidified, + ( &(const binstruction[ 3]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_back_color +********************************************************************/ +be_local_closure(Animate_core_set_back_color, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(back_color), + }), + be_str_weak(set_back_color), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_background_animator +********************************************************************/ +be_local_closure(Animate_core_add_background_animator, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(set_cb), + /* K1 */ be_nested_str_weak(set_back_color), + /* K2 */ be_nested_str_weak(add_animator), + }), + be_str_weak(add_background_animator), + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x8C080300, // 0000 GETMET R2 R1 K0 + 0x5C100000, // 0001 MOVE R4 R0 + 0x88140101, // 0002 GETMBR R5 R0 K1 + 0x7C080600, // 0003 CALL R2 3 + 0x8C080102, // 0004 GETMET R2 R0 K2 + 0x5C100200, // 0005 MOVE R4 R1 + 0x7C080400, // 0006 CALL R2 2 + 0x80000000, // 0007 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_animator +********************************************************************/ +be_local_closure(Animate_core_add_animator, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(animators), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(push), + }), + be_str_weak(add_animator), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x4C0C0000, // 0004 LDNIL R3 + 0x1C080403, // 0005 EQ R2 R2 R3 + 0x780A0003, // 0006 JMPF R2 #000B + 0x88080100, // 0007 GETMBR R2 R0 K0 + 0x8C080502, // 0008 GETMET R2 R2 K2 + 0x5C100200, // 0009 MOVE R4 R1 + 0x7C080400, // 000A CALL R2 2 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: remove +********************************************************************/ +be_local_closure(Animate_core_remove, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(clear), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(remove_fast_loop), + /* K3 */ be_nested_str_weak(fast_loop_cb), + }), + be_str_weak(remove), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0xB8060200, // 0002 GETNGBL R1 K1 + 0x8C040302, // 0003 GETMET R1 R1 K2 + 0x880C0103, // 0004 GETMBR R3 R0 K3 + 0x7C040400, // 0005 CALL R1 2 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start +********************************************************************/ +be_local_closure(Animate_core_start, /* name */ + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(running), + /* K1 */ be_nested_str_weak(animators), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(start), + /* K4 */ be_const_int(1), + /* K5 */ be_nested_str_weak(fast_loop_next), + /* K6 */ be_nested_str_weak(tasmota), + /* K7 */ be_nested_str_weak(add_fast_loop), + /* K8 */ be_nested_str_weak(fast_loop_cb), + }), + be_str_weak(start), + &be_const_str_solidified, + ( &(const binstruction[20]) { /* code */ + 0x50040200, // 0000 LDBOOL R1 1 0 + 0x90020001, // 0001 SETMBR R0 K0 R1 + 0x88040101, // 0002 GETMBR R1 R0 K1 + 0x58080002, // 0003 LDCONST R2 K2 + 0x600C000C, // 0004 GETGBL R3 G12 + 0x5C100200, // 0005 MOVE R4 R1 + 0x7C0C0200, // 0006 CALL R3 1 + 0x140C0403, // 0007 LT R3 R2 R3 + 0x780E0004, // 0008 JMPF R3 #000E + 0x940C0202, // 0009 GETIDX R3 R1 R2 + 0x8C0C0703, // 000A GETMET R3 R3 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0x00080504, // 000C ADD R2 R2 K4 + 0x7001FFF5, // 000D JMP #0004 + 0x90020B02, // 000E SETMBR R0 K5 K2 + 0xB80E0C00, // 000F GETNGBL R3 K6 + 0x8C0C0707, // 0010 GETMET R3 R3 K7 + 0x88140108, // 0011 GETMBR R5 R0 K8 + 0x7C0C0400, // 0012 CALL R3 2 + 0x80000000, // 0013 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Animate_core +********************************************************************/ +be_local_class(Animate_core, + 13, + NULL, + be_nested_map(32, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(set_strip_bri, -1), be_const_closure(Animate_core_set_strip_bri_closure) }, + { be_const_key_weak(animators, -1), be_const_var(4) }, + { be_const_key_weak(clear, 0), be_const_closure(Animate_core_clear_closure) }, + { be_const_key_weak(remove, -1), be_const_closure(Animate_core_remove_closure) }, + { be_const_key_weak(mth, -1), be_const_var(9) }, + { be_const_key_weak(stop, 1), be_const_closure(Animate_core_stop_closure) }, + { be_const_key_weak(fast_loop_cb, 30), be_const_var(6) }, + { be_const_key_weak(get_bri, -1), be_const_closure(Animate_core_get_bri_closure) }, + { be_const_key_weak(add_animator, -1), be_const_closure(Animate_core_add_animator_closure) }, + { be_const_key_weak(add_background_animator, -1), be_const_closure(Animate_core_add_background_animator_closure) }, + { be_const_key_weak(fast_loop_next, -1), be_const_var(7) }, + { be_const_key_weak(remove_animator, -1), be_const_closure(Animate_core_remove_animator_closure) }, + { be_const_key_weak(add_painter, 28), be_const_closure(Animate_core_add_painter_closure) }, + { be_const_key_weak(FAST_LOOP_MIN, -1), be_const_int(20) }, + { be_const_key_weak(fast_loop, -1), be_const_closure(Animate_core_fast_loop_closure) }, + { be_const_key_weak(set_back_color, 11), be_const_closure(Animate_core_set_back_color_closure) }, + { be_const_key_weak(animate, 8), be_const_closure(Animate_core_animate_closure) }, + { be_const_key_weak(strip, 24), be_const_var(0) }, + { be_const_key_weak(layer, -1), be_const_var(11) }, + { be_const_key_weak(init, -1), be_const_closure(Animate_core_init_closure) }, + { be_const_key_weak(bri, -1), be_const_var(2) }, + { be_const_key_weak(set_cb, 13), be_const_closure(Animate_core_set_cb_closure) }, + { be_const_key_weak(back_color, 18), be_const_var(12) }, + { be_const_key_weak(pixel_count, 15), be_const_var(1) }, + { be_const_key_weak(set_current, -1), be_const_closure(Animate_core_set_current_closure) }, + { be_const_key_weak(painters, -1), be_const_var(5) }, + { be_const_key_weak(obj, 10), be_const_var(8) }, + { be_const_key_weak(set_bri, 9), be_const_closure(Animate_core_set_bri_closure) }, + { be_const_key_weak(running, -1), be_const_var(3) }, + { be_const_key_weak(remove_painter, 3), be_const_closure(Animate_core_remove_painter_closure) }, + { be_const_key_weak(frame, -1), be_const_var(10) }, + { be_const_key_weak(start, -1), be_const_closure(Animate_core_start_closure) }, + })), + be_str_weak(Animate_core) +); +/*******************************************************************/ + +void be_load_Animate_core_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Animate_core); + be_setglobal(vm, "Animate_core"); + be_pop(vm, 1); +} +/********************************************************************/ +/* End of solidification */ diff --git a/lib/libesp32/berry_animate/src/solidify/solidified_animate_2_animate_effects.h b/lib/libesp32/berry_animate/src/solidify/solidified_animate_2_animate_effects.h new file mode 100644 index 000000000..360e3d2d8 --- /dev/null +++ b/lib/libesp32/berry_animate/src/solidify/solidified_animate_2_animate_effects.h @@ -0,0 +1,450 @@ +/* Solidification of animate_2_animate_effects.h */ +/********************************************************************\ +* Generated code, don't edit * +\********************************************************************/ +#include "be_constobj.h" + +extern const bclass be_class_Animate_painter; + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_painter_init, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(global), + /* K1 */ be_nested_str_weak(_cur_anim), + /* K2 */ be_nested_str_weak(add_painter), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x88040301, // 0001 GETMBR R1 R1 K1 + 0x4C080000, // 0002 LDNIL R2 + 0x20080202, // 0003 NE R2 R1 R2 + 0x780A0002, // 0004 JMPF R2 #0008 + 0x8C080302, // 0005 GETMET R2 R1 K2 + 0x5C100000, // 0006 MOVE R4 R0 + 0x7C080400, // 0007 CALL R2 2 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: paint +********************************************************************/ +be_local_closure(Animate_painter_paint, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(paint), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Animate_painter +********************************************************************/ +be_local_class(Animate_painter, + 0, + NULL, + be_nested_map(2, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(paint, -1), be_const_closure(Animate_painter_paint_closure) }, + { be_const_key_weak(init, 0), be_const_closure(Animate_painter_init_closure) }, + })), + be_str_weak(Animate_painter) +); +/*******************************************************************/ + +void be_load_Animate_painter_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Animate_painter); + be_setglobal(vm, "Animate_painter"); + be_pop(vm, 1); +} + +extern const bclass be_class_Animate_pulse; + +/******************************************************************** +** Solidified function: set_pulse_size +********************************************************************/ +be_local_closure(Animate_pulse_set_pulse_size, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(pulse_size), + }), + be_str_weak(set_pulse_size), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_slew_size +********************************************************************/ +be_local_closure(Animate_pulse_set_slew_size, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(slew_size), + }), + be_str_weak(set_slew_size), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_back_color +********************************************************************/ +be_local_closure(Animate_pulse_set_back_color, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(back_color), + }), + be_str_weak(set_back_color), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_pos +********************************************************************/ +be_local_closure(Animate_pulse_set_pos, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(pos), + }), + be_str_weak(set_pos), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_color +********************************************************************/ +be_local_closure(Animate_pulse_set_color, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(color), + }), + be_str_weak(set_color), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_pulse_init, /* name */ + be_nested_proto( + 6, /* nstack */ + 4, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[10]) { /* constants */ + /* K0 */ be_nested_str_weak(init), + /* K1 */ be_const_int(16777215), + /* K2 */ be_const_int(1), + /* K3 */ be_const_int(0), + /* K4 */ be_nested_str_weak(color), + /* K5 */ be_nested_str_weak(back_color), + /* K6 */ be_const_int(-16777216), + /* K7 */ be_nested_str_weak(pulse_size), + /* K8 */ be_nested_str_weak(slew_size), + /* K9 */ be_nested_str_weak(pos), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[29]) { /* code */ + 0x60100003, // 0000 GETGBL R4 G3 + 0x5C140000, // 0001 MOVE R5 R0 + 0x7C100200, // 0002 CALL R4 1 + 0x8C100900, // 0003 GETMET R4 R4 K0 + 0x7C100200, // 0004 CALL R4 1 + 0x4C100000, // 0005 LDNIL R4 + 0x1C100204, // 0006 EQ R4 R1 R4 + 0x78120000, // 0007 JMPF R4 #0009 + 0x58040001, // 0008 LDCONST R1 K1 + 0x4C100000, // 0009 LDNIL R4 + 0x1C100404, // 000A EQ R4 R2 R4 + 0x78120000, // 000B JMPF R4 #000D + 0x58080002, // 000C LDCONST R2 K2 + 0x4C100000, // 000D LDNIL R4 + 0x1C100604, // 000E EQ R4 R3 R4 + 0x78120000, // 000F JMPF R4 #0011 + 0x580C0003, // 0010 LDCONST R3 K3 + 0x90020801, // 0011 SETMBR R0 K4 R1 + 0x90020B06, // 0012 SETMBR R0 K5 K6 + 0x14100503, // 0013 LT R4 R2 K3 + 0x78120000, // 0014 JMPF R4 #0016 + 0x58080003, // 0015 LDCONST R2 K3 + 0x90020E02, // 0016 SETMBR R0 K7 R2 + 0x14100703, // 0017 LT R4 R3 K3 + 0x78120000, // 0018 JMPF R4 #001A + 0x580C0003, // 0019 LDCONST R3 K3 + 0x90021003, // 001A SETMBR R0 K8 R3 + 0x90021303, // 001B SETMBR R0 K9 K3 + 0x80000000, // 001C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: paint +********************************************************************/ +be_local_closure(Animate_pulse_paint, /* name */ + be_nested_proto( + 22, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[13]) { /* constants */ + /* K0 */ be_nested_str_weak(back_color), + /* K1 */ be_const_int(-16777216), + /* K2 */ be_nested_str_weak(fill_pixels), + /* K3 */ be_nested_str_weak(pos), + /* K4 */ be_nested_str_weak(slew_size), + /* K5 */ be_nested_str_weak(pulse_size), + /* K6 */ be_nested_str_weak(color), + /* K7 */ be_nested_str_weak(pixel_size), + /* K8 */ be_const_int(0), + /* K9 */ be_const_int(1), + /* K10 */ be_nested_str_weak(blend), + /* K11 */ be_nested_str_weak(tasmota), + /* K12 */ be_nested_str_weak(scale_int), + }), + be_str_weak(paint), + &be_const_str_solidified, + ( &(const binstruction[91]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x200C0501, // 0001 NE R3 R2 K1 + 0x780E0002, // 0002 JMPF R3 #0006 + 0x8C0C0302, // 0003 GETMET R3 R1 K2 + 0x5C140400, // 0004 MOVE R5 R2 + 0x7C0C0400, // 0005 CALL R3 2 + 0x880C0103, // 0006 GETMBR R3 R0 K3 + 0x88100104, // 0007 GETMBR R4 R0 K4 + 0x88140105, // 0008 GETMBR R5 R0 K5 + 0x88180106, // 0009 GETMBR R6 R0 K6 + 0x881C0307, // 000A GETMBR R7 R1 K7 + 0x4C200000, // 000B LDNIL R8 + 0x4C240000, // 000C LDNIL R9 + 0x5C200600, // 000D MOVE R8 R3 + 0x00280605, // 000E ADD R10 R3 R5 + 0x5C241400, // 000F MOVE R9 R10 + 0x14281108, // 0010 LT R10 R8 K8 + 0x782A0000, // 0011 JMPF R10 #0013 + 0x58200008, // 0012 LDCONST R8 K8 + 0x28281207, // 0013 GE R10 R9 R7 + 0x782A0000, // 0014 JMPF R10 #0016 + 0x5C240E00, // 0015 MOVE R9 R7 + 0x5C281000, // 0016 MOVE R10 R8 + 0x142C1409, // 0017 LT R11 R10 R9 + 0x782E0002, // 0018 JMPF R11 #001C + 0x98041406, // 0019 SETIDX R1 R10 R6 + 0x00281509, // 001A ADD R10 R10 K9 + 0x7001FFFA, // 001B JMP #0017 + 0x242C0908, // 001C GT R11 R4 K8 + 0x782E003A, // 001D JMPF R11 #0059 + 0x042C0604, // 001E SUB R11 R3 R4 + 0x5C201600, // 001F MOVE R8 R11 + 0x5C240600, // 0020 MOVE R9 R3 + 0x142C1108, // 0021 LT R11 R8 K8 + 0x782E0000, // 0022 JMPF R11 #0024 + 0x58200008, // 0023 LDCONST R8 K8 + 0x282C1207, // 0024 GE R11 R9 R7 + 0x782E0000, // 0025 JMPF R11 #0027 + 0x5C240E00, // 0026 MOVE R9 R7 + 0x5C281000, // 0027 MOVE R10 R8 + 0x142C1409, // 0028 LT R11 R10 R9 + 0x782E000F, // 0029 JMPF R11 #003A + 0x8C2C030A, // 002A GETMET R11 R1 K10 + 0x5C340400, // 002B MOVE R13 R2 + 0x5C380C00, // 002C MOVE R14 R6 + 0xB83E1600, // 002D GETNGBL R15 K11 + 0x8C3C1F0C, // 002E GETMET R15 R15 K12 + 0x5C441400, // 002F MOVE R17 R10 + 0x04480604, // 0030 SUB R18 R3 R4 + 0x04482509, // 0031 SUB R18 R18 K9 + 0x5C4C0600, // 0032 MOVE R19 R3 + 0x545200FE, // 0033 LDINT R20 255 + 0x58540008, // 0034 LDCONST R21 K8 + 0x7C3C0C00, // 0035 CALL R15 6 + 0x7C2C0800, // 0036 CALL R11 4 + 0x9804140B, // 0037 SETIDX R1 R10 R11 + 0x00281509, // 0038 ADD R10 R10 K9 + 0x7001FFED, // 0039 JMP #0028 + 0x002C0605, // 003A ADD R11 R3 R5 + 0x5C201600, // 003B MOVE R8 R11 + 0x002C0605, // 003C ADD R11 R3 R5 + 0x002C1604, // 003D ADD R11 R11 R4 + 0x5C241600, // 003E MOVE R9 R11 + 0x142C1108, // 003F LT R11 R8 K8 + 0x782E0000, // 0040 JMPF R11 #0042 + 0x58200008, // 0041 LDCONST R8 K8 + 0x282C1207, // 0042 GE R11 R9 R7 + 0x782E0000, // 0043 JMPF R11 #0045 + 0x5C240E00, // 0044 MOVE R9 R7 + 0x5C281000, // 0045 MOVE R10 R8 + 0x142C1409, // 0046 LT R11 R10 R9 + 0x782E0010, // 0047 JMPF R11 #0059 + 0x8C2C030A, // 0048 GETMET R11 R1 K10 + 0x5C340400, // 0049 MOVE R13 R2 + 0x5C380C00, // 004A MOVE R14 R6 + 0xB83E1600, // 004B GETNGBL R15 K11 + 0x8C3C1F0C, // 004C GETMET R15 R15 K12 + 0x5C441400, // 004D MOVE R17 R10 + 0x00480605, // 004E ADD R18 R3 R5 + 0x04482509, // 004F SUB R18 R18 K9 + 0x004C0605, // 0050 ADD R19 R3 R5 + 0x004C2604, // 0051 ADD R19 R19 R4 + 0x58500008, // 0052 LDCONST R20 K8 + 0x545600FE, // 0053 LDINT R21 255 + 0x7C3C0C00, // 0054 CALL R15 6 + 0x7C2C0800, // 0055 CALL R11 4 + 0x9804140B, // 0056 SETIDX R1 R10 R11 + 0x00281509, // 0057 ADD R10 R10 K9 + 0x7001FFEC, // 0058 JMP #0046 + 0x502C0200, // 0059 LDBOOL R11 1 0 + 0x80041600, // 005A RET 1 R11 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Animate_pulse +********************************************************************/ +extern const bclass be_class_Animate_painter; +be_local_class(Animate_pulse, + 5, + &be_class_Animate_painter, + be_nested_map(12, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(paint, -1), be_const_closure(Animate_pulse_paint_closure) }, + { be_const_key_weak(set_slew_size, -1), be_const_closure(Animate_pulse_set_slew_size_closure) }, + { be_const_key_weak(pulse_size, -1), be_const_var(4) }, + { be_const_key_weak(set_back_color, 8), be_const_closure(Animate_pulse_set_back_color_closure) }, + { be_const_key_weak(color, -1), be_const_var(0) }, + { be_const_key_weak(back_color, -1), be_const_var(1) }, + { be_const_key_weak(set_pos, -1), be_const_closure(Animate_pulse_set_pos_closure) }, + { be_const_key_weak(set_color, -1), be_const_closure(Animate_pulse_set_color_closure) }, + { be_const_key_weak(init, 7), be_const_closure(Animate_pulse_init_closure) }, + { be_const_key_weak(pos, -1), be_const_var(2) }, + { be_const_key_weak(slew_size, 5), be_const_var(3) }, + { be_const_key_weak(set_pulse_size, 0), be_const_closure(Animate_pulse_set_pulse_size_closure) }, + })), + be_str_weak(Animate_pulse) +); +/*******************************************************************/ + +void be_load_Animate_pulse_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Animate_pulse); + be_setglobal(vm, "Animate_pulse"); + be_pop(vm, 1); +} +/********************************************************************/ +/* End of solidification */ diff --git a/lib/libesp32/berry_animate/src/solidify/solidified_animate_9_module.h b/lib/libesp32/berry_animate/src/solidify/solidified_animate_9_module.h new file mode 100644 index 000000000..e64059188 --- /dev/null +++ b/lib/libesp32/berry_animate/src/solidify/solidified_animate_9_module.h @@ -0,0 +1,1592 @@ +/* Solidification of animate_9_module.h */ +/********************************************************************\ +* Generated code, don't edit * +\********************************************************************/ +#include "be_constobj.h" + +extern const bclass be_class_Animate_animator; + +/******************************************************************** +** Solidified function: is_running +********************************************************************/ +be_local_closure(Animate_animator_is_running, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(running), + }), + be_str_weak(is_running), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x60040017, // 0000 GETGBL R1 G23 + 0x88080100, // 0001 GETMBR R2 R0 K0 + 0x7C040200, // 0002 CALL R1 1 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: beat +********************************************************************/ +be_local_closure(Animate_animator_beat, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(beat), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_animator_init, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(global), + /* K1 */ be_nested_str_weak(_cur_anim), + /* K2 */ be_nested_str_weak(add_animator), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x88040301, // 0001 GETMBR R1 R1 K1 + 0x4C080000, // 0002 LDNIL R2 + 0x20080202, // 0003 NE R2 R1 R2 + 0x780A0002, // 0004 JMPF R2 #0008 + 0x8C080302, // 0005 GETMET R2 R1 K2 + 0x5C100000, // 0006 MOVE R4 R0 + 0x7C080400, // 0007 CALL R2 2 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: stop +********************************************************************/ +be_local_closure(Animate_animator_stop, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(origin), + /* K1 */ be_nested_str_weak(running), + }), + be_str_weak(stop), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x4C040000, // 0000 LDNIL R1 + 0x90020001, // 0001 SETMBR R0 K0 R1 + 0x50040000, // 0002 LDBOOL R1 0 0 + 0x90020201, // 0003 SETMBR R0 K1 R1 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_duration_ms +********************************************************************/ +be_local_closure(Animate_animator_set_duration_ms, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(duration_ms), + }), + be_str_weak(set_duration_ms), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_cb +********************************************************************/ +be_local_closure(Animate_animator_set_cb, /* name */ + be_nested_proto( + 3, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(obj), + /* K1 */ be_nested_str_weak(mth), + }), + be_str_weak(set_cb), + &be_const_str_solidified, + ( &(const binstruction[ 3]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start +********************************************************************/ +be_local_closure(Animate_animator_start, /* name */ + be_nested_proto( + 4, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(duration_ms), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(millis), + /* K3 */ be_nested_str_weak(origin), + /* K4 */ be_nested_str_weak(running), + }), + be_str_weak(start), + &be_const_str_solidified, + ( &(const binstruction[16]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x1C080403, // 0002 EQ R2 R2 R3 + 0x780A0000, // 0003 JMPF R2 #0005 + 0x80000400, // 0004 RET 0 + 0x4C080000, // 0005 LDNIL R2 + 0x1C080202, // 0006 EQ R2 R1 R2 + 0x780A0003, // 0007 JMPF R2 #000C + 0xB80A0200, // 0008 GETNGBL R2 K1 + 0x8C080502, // 0009 GETMET R2 R2 K2 + 0x7C080200, // 000A CALL R2 1 + 0x5C040400, // 000B MOVE R1 R2 + 0x90020601, // 000C SETMBR R0 K3 R1 + 0x50080200, // 000D LDBOOL R2 1 0 + 0x90020802, // 000E SETMBR R0 K4 R2 + 0x80000000, // 000F RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Animate_animator +********************************************************************/ +be_local_class(Animate_animator, + 5, + NULL, + be_nested_map(12, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(running, 4), be_const_var(0) }, + { be_const_key_weak(is_running, 2), be_const_closure(Animate_animator_is_running_closure) }, + { be_const_key_weak(beat, -1), be_const_closure(Animate_animator_beat_closure) }, + { be_const_key_weak(init, -1), be_const_closure(Animate_animator_init_closure) }, + { be_const_key_weak(mth, -1), be_const_var(4) }, + { be_const_key_weak(stop, -1), be_const_closure(Animate_animator_stop_closure) }, + { be_const_key_weak(duration_ms, -1), be_const_var(1) }, + { be_const_key_weak(origin, -1), be_const_var(2) }, + { be_const_key_weak(set_cb, -1), be_const_closure(Animate_animator_set_cb_closure) }, + { be_const_key_weak(set_duration_ms, 8), be_const_closure(Animate_animator_set_duration_ms_closure) }, + { be_const_key_weak(obj, -1), be_const_var(3) }, + { be_const_key_weak(start, -1), be_const_closure(Animate_animator_start_closure) }, + })), + be_str_weak(Animate_animator) +); +/*******************************************************************/ + +void be_load_Animate_animator_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Animate_animator); + be_setglobal(vm, "Animate_animator"); + be_pop(vm, 1); +} + +extern const bclass be_class_Animate_palette; + +/******************************************************************** +** Solidified function: ptr_to_palette +********************************************************************/ +be_local_closure(Animate_palette_ptr_to_palette, /* name */ + be_nested_proto( + 8, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_const_class(be_class_Animate_palette), + /* K1 */ be_nested_str_weak(ptr), + /* K2 */ be_const_int(1), + /* K3 */ be_const_int(0), + }), + be_str_weak(ptr_to_palette), + &be_const_str_solidified, + ( &(const binstruction[45]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x60080004, // 0001 GETGBL R2 G4 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C080200, // 0003 CALL R2 1 + 0x1C080501, // 0004 EQ R2 R2 K1 + 0x780A0025, // 0005 JMPF R2 #002C + 0x60080015, // 0006 GETGBL R2 G21 + 0x5C0C0000, // 0007 MOVE R3 R0 + 0x541207CF, // 0008 LDINT R4 2000 + 0x7C080400, // 0009 CALL R2 2 + 0x580C0002, // 000A LDCONST R3 K2 + 0x94100503, // 000B GETIDX R4 R2 K3 + 0x20100903, // 000C NE R4 R4 K3 + 0x7812000A, // 000D JMPF R4 #0019 + 0x50100200, // 000E LDBOOL R4 1 0 + 0x78120007, // 000F JMPF R4 #0018 + 0x54120003, // 0010 LDINT R4 4 + 0x08100604, // 0011 MUL R4 R3 R4 + 0x94100404, // 0012 GETIDX R4 R2 R4 + 0x1C100903, // 0013 EQ R4 R4 K3 + 0x78120000, // 0014 JMPF R4 #0016 + 0x70020001, // 0015 JMP #0018 + 0x000C0702, // 0016 ADD R3 R3 K2 + 0x7001FFF5, // 0017 JMP #000E + 0x7002000A, // 0018 JMP #0024 + 0x50100200, // 0019 LDBOOL R4 1 0 + 0x78120008, // 001A JMPF R4 #0024 + 0x54120003, // 001B LDINT R4 4 + 0x08100604, // 001C MUL R4 R3 R4 + 0x94100404, // 001D GETIDX R4 R2 R4 + 0x541600FE, // 001E LDINT R5 255 + 0x1C100805, // 001F EQ R4 R4 R5 + 0x78120000, // 0020 JMPF R4 #0022 + 0x70020001, // 0021 JMP #0024 + 0x000C0702, // 0022 ADD R3 R3 K2 + 0x7001FFF4, // 0023 JMP #0019 + 0x00100702, // 0024 ADD R4 R3 K2 + 0x54160003, // 0025 LDINT R5 4 + 0x08100805, // 0026 MUL R4 R4 R5 + 0x60140015, // 0027 GETGBL R5 G21 + 0x5C180000, // 0028 MOVE R6 R0 + 0x5C1C0800, // 0029 MOVE R7 R4 + 0x7C140400, // 002A CALL R5 2 + 0x80040A00, // 002B RET 1 R5 + 0x80000000, // 002C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: animate +********************************************************************/ +be_local_closure(Animate_palette_animate, /* name */ + be_nested_proto( + 26, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[21]) { /* constants */ + /* K0 */ be_nested_str_weak(duration_ms), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(millis), + /* K3 */ be_nested_str_weak(origin), + /* K4 */ be_const_int(0), + /* K5 */ be_nested_str_weak(scale_uint), + /* K6 */ be_nested_str_weak(slots), + /* K7 */ be_const_int(2), + /* K8 */ be_nested_str_weak(slots_arr), + /* K9 */ be_const_int(1), + /* K10 */ be_nested_str_weak(palette), + /* K11 */ be_nested_str_weak(get), + /* K12 */ be_nested_str_weak(color), + /* K13 */ be_nested_str_weak(set_rgb), + /* K14 */ be_nested_str_weak(bri), + /* K15 */ be_nested_str_weak(set_bri), + /* K16 */ be_nested_str_weak(r), + /* K17 */ be_nested_str_weak(g), + /* K18 */ be_nested_str_weak(b), + /* K19 */ be_nested_str_weak(obj), + /* K20 */ be_nested_str_weak(mth), + }), + be_str_weak(animate), + &be_const_str_solidified, + ( &(const binstruction[193]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x1C080403, // 0002 EQ R2 R2 R3 + 0x780A0000, // 0003 JMPF R2 #0005 + 0x80000400, // 0004 RET 0 + 0x4C080000, // 0005 LDNIL R2 + 0x1C080202, // 0006 EQ R2 R1 R2 + 0x780A0003, // 0007 JMPF R2 #000C + 0xB80A0200, // 0008 GETNGBL R2 K1 + 0x8C080502, // 0009 GETMET R2 R2 K2 + 0x7C080200, // 000A CALL R2 1 + 0x5C040400, // 000B MOVE R1 R2 + 0x88080103, // 000C GETMBR R2 R0 K3 + 0x04080202, // 000D SUB R2 R1 R2 + 0x140C0504, // 000E LT R3 R2 K4 + 0x780E0001, // 000F JMPF R3 #0012 + 0x58080004, // 0010 LDCONST R2 K4 + 0x88040103, // 0011 GETMBR R1 R0 K3 + 0x880C0100, // 0012 GETMBR R3 R0 K0 + 0xB8120200, // 0013 GETNGBL R4 K1 + 0x88100905, // 0014 GETMBR R4 R4 K5 + 0x28140403, // 0015 GE R5 R2 R3 + 0x78160005, // 0016 JMPF R5 #001D + 0x0C180403, // 0017 DIV R6 R2 R3 + 0x08180C03, // 0018 MUL R6 R6 R3 + 0x88140103, // 0019 GETMBR R5 R0 K3 + 0x00140A06, // 001A ADD R5 R5 R6 + 0x90020605, // 001B SETMBR R0 K3 R5 + 0x10080403, // 001C MOD R2 R2 R3 + 0x88140106, // 001D GETMBR R5 R0 K6 + 0x04180B07, // 001E SUB R6 R5 K7 + 0x241C0D04, // 001F GT R7 R6 K4 + 0x781E0006, // 0020 JMPF R7 #0028 + 0x881C0108, // 0021 GETMBR R7 R0 K8 + 0x941C0E06, // 0022 GETIDX R7 R7 R6 + 0x281C0407, // 0023 GE R7 R2 R7 + 0x781E0000, // 0024 JMPF R7 #0026 + 0x70020001, // 0025 JMP #0028 + 0x04180D09, // 0026 SUB R6 R6 K9 + 0x7001FFF6, // 0027 JMP #001F + 0x881C010A, // 0028 GETMBR R7 R0 K10 + 0x8C1C0F0B, // 0029 GETMET R7 R7 K11 + 0x54260003, // 002A LDINT R9 4 + 0x08240C09, // 002B MUL R9 R6 R9 + 0x542A0003, // 002C LDINT R10 4 + 0x7C1C0600, // 002D CALL R7 3 + 0x8820010A, // 002E GETMBR R8 R0 K10 + 0x8C20110B, // 002F GETMET R8 R8 K11 + 0x00280D09, // 0030 ADD R10 R6 K9 + 0x542E0003, // 0031 LDINT R11 4 + 0x0828140B, // 0032 MUL R10 R10 R11 + 0x542E0003, // 0033 LDINT R11 4 + 0x7C200600, // 0034 CALL R8 3 + 0x88240108, // 0035 GETMBR R9 R0 K8 + 0x94241206, // 0036 GETIDX R9 R9 R6 + 0x00280D09, // 0037 ADD R10 R6 K9 + 0x882C0108, // 0038 GETMBR R11 R0 K8 + 0x9428160A, // 0039 GETIDX R10 R11 R10 + 0x5C300800, // 003A MOVE R12 R4 + 0x5C340400, // 003B MOVE R13 R2 + 0x5C381200, // 003C MOVE R14 R9 + 0x5C3C1400, // 003D MOVE R15 R10 + 0x54420007, // 003E LDINT R16 8 + 0x3C400E10, // 003F SHR R16 R7 R16 + 0x544600FE, // 0040 LDINT R17 255 + 0x2C402011, // 0041 AND R16 R16 R17 + 0x54460007, // 0042 LDINT R17 8 + 0x3C441011, // 0043 SHR R17 R8 R17 + 0x544A00FE, // 0044 LDINT R18 255 + 0x2C442212, // 0045 AND R17 R17 R18 + 0x7C300A00, // 0046 CALL R12 5 + 0x5C2C1800, // 0047 MOVE R11 R12 + 0x5C300800, // 0048 MOVE R12 R4 + 0x5C340400, // 0049 MOVE R13 R2 + 0x5C381200, // 004A MOVE R14 R9 + 0x5C3C1400, // 004B MOVE R15 R10 + 0x5442000F, // 004C LDINT R16 16 + 0x3C400E10, // 004D SHR R16 R7 R16 + 0x544600FE, // 004E LDINT R17 255 + 0x2C402011, // 004F AND R16 R16 R17 + 0x5446000F, // 0050 LDINT R17 16 + 0x3C441011, // 0051 SHR R17 R8 R17 + 0x544A00FE, // 0052 LDINT R18 255 + 0x2C442212, // 0053 AND R17 R17 R18 + 0x7C300A00, // 0054 CALL R12 5 + 0x5C340800, // 0055 MOVE R13 R4 + 0x5C380400, // 0056 MOVE R14 R2 + 0x5C3C1200, // 0057 MOVE R15 R9 + 0x5C401400, // 0058 MOVE R16 R10 + 0x54460017, // 0059 LDINT R17 24 + 0x3C440E11, // 005A SHR R17 R7 R17 + 0x544A00FE, // 005B LDINT R18 255 + 0x2C442212, // 005C AND R17 R17 R18 + 0x544A0017, // 005D LDINT R18 24 + 0x3C481012, // 005E SHR R18 R8 R18 + 0x544E00FE, // 005F LDINT R19 255 + 0x2C482413, // 0060 AND R18 R18 R19 + 0x7C340A00, // 0061 CALL R13 5 + 0x8838010C, // 0062 GETMBR R14 R0 K12 + 0x8C3C1D0D, // 0063 GETMET R15 R14 K13 + 0x54460007, // 0064 LDINT R17 8 + 0x3C440E11, // 0065 SHR R17 R7 R17 + 0x544A00FE, // 0066 LDINT R18 255 + 0x2C442212, // 0067 AND R17 R17 R18 + 0x544A000F, // 0068 LDINT R18 16 + 0x3C480E12, // 0069 SHR R18 R7 R18 + 0x544E00FE, // 006A LDINT R19 255 + 0x2C482413, // 006B AND R18 R18 R19 + 0x544E0017, // 006C LDINT R19 24 + 0x3C4C0E13, // 006D SHR R19 R7 R19 + 0x545200FE, // 006E LDINT R20 255 + 0x2C4C2614, // 006F AND R19 R19 R20 + 0x7C3C0800, // 0070 CALL R15 4 + 0x883C1D0E, // 0071 GETMBR R15 R14 K14 + 0x8C401D0D, // 0072 GETMET R16 R14 K13 + 0x544A0007, // 0073 LDINT R18 8 + 0x3C481012, // 0074 SHR R18 R8 R18 + 0x544E00FE, // 0075 LDINT R19 255 + 0x2C482413, // 0076 AND R18 R18 R19 + 0x544E000F, // 0077 LDINT R19 16 + 0x3C4C1013, // 0078 SHR R19 R8 R19 + 0x545200FE, // 0079 LDINT R20 255 + 0x2C4C2614, // 007A AND R19 R19 R20 + 0x54520017, // 007B LDINT R20 24 + 0x3C501014, // 007C SHR R20 R8 R20 + 0x545600FE, // 007D LDINT R21 255 + 0x2C502815, // 007E AND R20 R20 R21 + 0x7C400800, // 007F CALL R16 4 + 0x88401D0E, // 0080 GETMBR R16 R14 K14 + 0x5C440800, // 0081 MOVE R17 R4 + 0x5C480400, // 0082 MOVE R18 R2 + 0x5C4C1200, // 0083 MOVE R19 R9 + 0x5C501400, // 0084 MOVE R20 R10 + 0x5C541E00, // 0085 MOVE R21 R15 + 0x5C582000, // 0086 MOVE R22 R16 + 0x7C440A00, // 0087 CALL R17 5 + 0x8C481D0D, // 0088 GETMET R18 R14 K13 + 0x5C501600, // 0089 MOVE R20 R11 + 0x5C541800, // 008A MOVE R21 R12 + 0x5C581A00, // 008B MOVE R22 R13 + 0x7C480800, // 008C CALL R18 4 + 0x8C481D0F, // 008D GETMET R18 R14 K15 + 0x5C502200, // 008E MOVE R20 R17 + 0x7C480400, // 008F CALL R18 2 + 0x882C1D10, // 0090 GETMBR R11 R14 K16 + 0x88301D11, // 0091 GETMBR R12 R14 K17 + 0x88341D12, // 0092 GETMBR R13 R14 K18 + 0x8848010E, // 0093 GETMBR R18 R0 K14 + 0x544E0063, // 0094 LDINT R19 100 + 0x204C2413, // 0095 NE R19 R18 R19 + 0x784E001A, // 0096 JMPF R19 #00B2 + 0xB84E0200, // 0097 GETNGBL R19 K1 + 0x8C4C2705, // 0098 GETMET R19 R19 K5 + 0x5C541600, // 0099 MOVE R21 R11 + 0x58580004, // 009A LDCONST R22 K4 + 0x545E0063, // 009B LDINT R23 100 + 0x58600004, // 009C LDCONST R24 K4 + 0x5C642400, // 009D MOVE R25 R18 + 0x7C4C0C00, // 009E CALL R19 6 + 0x5C2C2600, // 009F MOVE R11 R19 + 0xB84E0200, // 00A0 GETNGBL R19 K1 + 0x8C4C2705, // 00A1 GETMET R19 R19 K5 + 0x5C541800, // 00A2 MOVE R21 R12 + 0x58580004, // 00A3 LDCONST R22 K4 + 0x545E0063, // 00A4 LDINT R23 100 + 0x58600004, // 00A5 LDCONST R24 K4 + 0x5C642400, // 00A6 MOVE R25 R18 + 0x7C4C0C00, // 00A7 CALL R19 6 + 0x5C302600, // 00A8 MOVE R12 R19 + 0xB84E0200, // 00A9 GETNGBL R19 K1 + 0x8C4C2705, // 00AA GETMET R19 R19 K5 + 0x5C541A00, // 00AB MOVE R21 R13 + 0x58580004, // 00AC LDCONST R22 K4 + 0x545E0063, // 00AD LDINT R23 100 + 0x58600004, // 00AE LDCONST R24 K4 + 0x5C642400, // 00AF MOVE R25 R18 + 0x7C4C0C00, // 00B0 CALL R19 6 + 0x5C342600, // 00B1 MOVE R13 R19 + 0x544E000F, // 00B2 LDINT R19 16 + 0x384C1613, // 00B3 SHL R19 R11 R19 + 0x54520007, // 00B4 LDINT R20 8 + 0x38501814, // 00B5 SHL R20 R12 R20 + 0x304C2614, // 00B6 OR R19 R19 R20 + 0x304C260D, // 00B7 OR R19 R19 R13 + 0x88500113, // 00B8 GETMBR R20 R0 K19 + 0x88540114, // 00B9 GETMBR R21 R0 K20 + 0x78520004, // 00BA JMPF R20 #00C0 + 0x78560003, // 00BB JMPF R21 #00C0 + 0x5C582A00, // 00BC MOVE R22 R21 + 0x5C5C2800, // 00BD MOVE R23 R20 + 0x5C602600, // 00BE MOVE R24 R19 + 0x7C580400, // 00BF CALL R22 2 + 0x80042600, // 00C0 RET 1 R19 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_palette +********************************************************************/ +be_local_closure(Animate_palette_set_palette, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(ptr), + /* K1 */ be_nested_str_weak(ptr_to_palette), + /* K2 */ be_nested_str_weak(palette), + /* K3 */ be_nested_str_weak(slots), + /* K4 */ be_nested_str_weak(duration_ms), + /* K5 */ be_nested_str_weak(set_duration), + /* K6 */ be_nested_str_weak(range_min), + /* K7 */ be_nested_str_weak(range_max), + /* K8 */ be_nested_str_weak(set_range), + }), + be_str_weak(set_palette), + &be_const_str_solidified, + ( &(const binstruction[37]) { /* code */ + 0x60080004, // 0000 GETGBL R2 G4 + 0x5C0C0200, // 0001 MOVE R3 R1 + 0x7C080200, // 0002 CALL R2 1 + 0x1C080500, // 0003 EQ R2 R2 K0 + 0x780A0003, // 0004 JMPF R2 #0009 + 0x8C080101, // 0005 GETMET R2 R0 K1 + 0x5C100200, // 0006 MOVE R4 R1 + 0x7C080400, // 0007 CALL R2 2 + 0x5C040400, // 0008 MOVE R1 R2 + 0x90020401, // 0009 SETMBR R0 K2 R1 + 0x6008000C, // 000A GETGBL R2 G12 + 0x5C0C0200, // 000B MOVE R3 R1 + 0x7C080200, // 000C CALL R2 1 + 0x540E0003, // 000D LDINT R3 4 + 0x0C080403, // 000E DIV R2 R2 R3 + 0x90020602, // 000F SETMBR R0 K3 R2 + 0x88080104, // 0010 GETMBR R2 R0 K4 + 0x4C0C0000, // 0011 LDNIL R3 + 0x20080403, // 0012 NE R2 R2 R3 + 0x780A0003, // 0013 JMPF R2 #0018 + 0x8C080105, // 0014 GETMET R2 R0 K5 + 0x88100104, // 0015 GETMBR R4 R0 K4 + 0x7C080400, // 0016 CALL R2 2 + 0x7002000B, // 0017 JMP #0024 + 0x88080106, // 0018 GETMBR R2 R0 K6 + 0x4C0C0000, // 0019 LDNIL R3 + 0x20080403, // 001A NE R2 R2 R3 + 0x780A0007, // 001B JMPF R2 #0024 + 0x88080107, // 001C GETMBR R2 R0 K7 + 0x4C0C0000, // 001D LDNIL R3 + 0x20080403, // 001E NE R2 R2 R3 + 0x780A0003, // 001F JMPF R2 #0024 + 0x8C080108, // 0020 GETMET R2 R0 K8 + 0x88100106, // 0021 GETMBR R4 R0 K6 + 0x88140107, // 0022 GETMBR R5 R0 K7 + 0x7C080600, // 0023 CALL R2 3 + 0x80000000, // 0024 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: to_css_gradient +********************************************************************/ +be_local_closure(Animate_palette_to_css_gradient, /* name */ + be_nested_proto( + 17, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[10]) { /* constants */ + /* K0 */ be_const_class(be_class_Animate_palette), + /* K1 */ be_nested_str_weak(parse_palette), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(background_X3Alinear_X2Dgradient_X28to_X20right), + /* K4 */ be_nested_str_weak(palette), + /* K5 */ be_nested_str_weak(get), + /* K6 */ be_nested_str_weak(_X2C_X23_X2502X_X2502X_X2502X_X20_X25_X2E1f_X25_X25), + /* K7 */ be_const_real_hex(0x41200000), + /* K8 */ be_const_int(1), + /* K9 */ be_nested_str_weak(_X29_X3B), + }), + be_str_weak(to_css_gradient), + &be_const_str_solidified, + ( &(const binstruction[46]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x5C080200, // 0001 MOVE R2 R1 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C080200, // 0003 CALL R2 1 + 0x8C0C0501, // 0004 GETMET R3 R2 K1 + 0x58140002, // 0005 LDCONST R5 K2 + 0x541A03E7, // 0006 LDINT R6 1000 + 0x7C0C0600, // 0007 CALL R3 3 + 0x58100003, // 0008 LDCONST R4 K3 + 0x58140002, // 0009 LDCONST R5 K2 + 0x6018000C, // 000A GETGBL R6 G12 + 0x5C1C0600, // 000B MOVE R7 R3 + 0x7C180200, // 000C CALL R6 1 + 0x14180A06, // 000D LT R6 R5 R6 + 0x781A001C, // 000E JMPF R6 #002C + 0x94180605, // 000F GETIDX R6 R3 R5 + 0x881C0504, // 0010 GETMBR R7 R2 K4 + 0x8C1C0F05, // 0011 GETMET R7 R7 K5 + 0x54260003, // 0012 LDINT R9 4 + 0x08240A09, // 0013 MUL R9 R5 R9 + 0x542A0003, // 0014 LDINT R10 4 + 0x7C1C0600, // 0015 CALL R7 3 + 0x54220007, // 0016 LDINT R8 8 + 0x3C200E08, // 0017 SHR R8 R7 R8 + 0x542600FE, // 0018 LDINT R9 255 + 0x2C201009, // 0019 AND R8 R8 R9 + 0x5426000F, // 001A LDINT R9 16 + 0x3C240E09, // 001B SHR R9 R7 R9 + 0x542A00FE, // 001C LDINT R10 255 + 0x2C24120A, // 001D AND R9 R9 R10 + 0x542A0017, // 001E LDINT R10 24 + 0x3C280E0A, // 001F SHR R10 R7 R10 + 0x542E00FE, // 0020 LDINT R11 255 + 0x2C28140B, // 0021 AND R10 R10 R11 + 0x602C0018, // 0022 GETGBL R11 G24 + 0x58300006, // 0023 LDCONST R12 K6 + 0x5C341000, // 0024 MOVE R13 R8 + 0x5C381200, // 0025 MOVE R14 R9 + 0x5C3C1400, // 0026 MOVE R15 R10 + 0x0C400D07, // 0027 DIV R16 R6 K7 + 0x7C2C0A00, // 0028 CALL R11 5 + 0x0010080B, // 0029 ADD R4 R4 R11 + 0x00140B08, // 002A ADD R5 R5 K8 + 0x7001FFDD, // 002B JMP #000A + 0x00100909, // 002C ADD R4 R4 K9 + 0x80040800, // 002D RET 1 R4 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_bri +********************************************************************/ +be_local_closure(Animate_palette_set_bri, /* name */ + be_nested_proto( + 4, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(bri), + }), + be_str_weak(set_bri), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x60080009, // 0000 GETGBL R2 G9 + 0x5C0C0200, // 0001 MOVE R3 R1 + 0x7C080200, // 0002 CALL R2 1 + 0x90020002, // 0003 SETMBR R0 K0 R2 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: parse_palette +********************************************************************/ +be_local_closure(Animate_palette_parse_palette, /* name */ + be_nested_proto( + 15, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_str_weak(slots), + /* K1 */ be_nested_str_weak(resize), + /* K2 */ be_nested_str_weak(palette), + /* K3 */ be_nested_str_weak(get), + /* K4 */ be_const_int(0), + /* K5 */ be_const_int(1), + /* K6 */ be_nested_str_weak(tasmota), + /* K7 */ be_nested_str_weak(scale_int), + }), + be_str_weak(parse_palette), + &be_const_str_solidified, + ( &(const binstruction[71]) { /* code */ + 0x600C0012, // 0000 GETGBL R3 G18 + 0x7C0C0000, // 0001 CALL R3 0 + 0x88100100, // 0002 GETMBR R4 R0 K0 + 0x8C140701, // 0003 GETMET R5 R3 K1 + 0x5C1C0800, // 0004 MOVE R7 R4 + 0x7C140400, // 0005 CALL R5 2 + 0x88140102, // 0006 GETMBR R5 R0 K2 + 0x8C140B03, // 0007 GETMET R5 R5 K3 + 0x581C0004, // 0008 LDCONST R7 K4 + 0x58200005, // 0009 LDCONST R8 K5 + 0x7C140600, // 000A CALL R5 3 + 0x20140B04, // 000B NE R5 R5 K4 + 0x78160024, // 000C JMPF R5 #0032 + 0x58140004, // 000D LDCONST R5 K4 + 0x58180004, // 000E LDCONST R6 K4 + 0x041C0905, // 000F SUB R7 R4 K5 + 0x141C0C07, // 0010 LT R7 R6 R7 + 0x781E0008, // 0011 JMPF R7 #001B + 0x881C0102, // 0012 GETMBR R7 R0 K2 + 0x8C1C0F03, // 0013 GETMET R7 R7 K3 + 0x54260003, // 0014 LDINT R9 4 + 0x08240C09, // 0015 MUL R9 R6 R9 + 0x58280005, // 0016 LDCONST R10 K5 + 0x7C1C0600, // 0017 CALL R7 3 + 0x00140A07, // 0018 ADD R5 R5 R7 + 0x00180D05, // 0019 ADD R6 R6 K5 + 0x7001FFF3, // 001A JMP #000F + 0x581C0004, // 001B LDCONST R7 K4 + 0x58180004, // 001C LDCONST R6 K4 + 0x14200C04, // 001D LT R8 R6 R4 + 0x78220011, // 001E JMPF R8 #0031 + 0xB8220C00, // 001F GETNGBL R8 K6 + 0x8C201107, // 0020 GETMET R8 R8 K7 + 0x5C280E00, // 0021 MOVE R10 R7 + 0x582C0004, // 0022 LDCONST R11 K4 + 0x5C300A00, // 0023 MOVE R12 R5 + 0x5C340200, // 0024 MOVE R13 R1 + 0x5C380400, // 0025 MOVE R14 R2 + 0x7C200C00, // 0026 CALL R8 6 + 0x980C0C08, // 0027 SETIDX R3 R6 R8 + 0x88200102, // 0028 GETMBR R8 R0 K2 + 0x8C201103, // 0029 GETMET R8 R8 K3 + 0x542A0003, // 002A LDINT R10 4 + 0x08280C0A, // 002B MUL R10 R6 R10 + 0x582C0005, // 002C LDCONST R11 K5 + 0x7C200600, // 002D CALL R8 3 + 0x001C0E08, // 002E ADD R7 R7 R8 + 0x00180D05, // 002F ADD R6 R6 K5 + 0x7001FFEB, // 0030 JMP #001D + 0x70020013, // 0031 JMP #0046 + 0x58140004, // 0032 LDCONST R5 K4 + 0x14180A04, // 0033 LT R6 R5 R4 + 0x781A0010, // 0034 JMPF R6 #0046 + 0x88180102, // 0035 GETMBR R6 R0 K2 + 0x8C180D03, // 0036 GETMET R6 R6 K3 + 0x54220003, // 0037 LDINT R8 4 + 0x08200A08, // 0038 MUL R8 R5 R8 + 0x58240005, // 0039 LDCONST R9 K5 + 0x7C180600, // 003A CALL R6 3 + 0xB81E0C00, // 003B GETNGBL R7 K6 + 0x8C1C0F07, // 003C GETMET R7 R7 K7 + 0x5C240C00, // 003D MOVE R9 R6 + 0x58280004, // 003E LDCONST R10 K4 + 0x542E00FE, // 003F LDINT R11 255 + 0x5C300200, // 0040 MOVE R12 R1 + 0x5C340400, // 0041 MOVE R13 R2 + 0x7C1C0C00, // 0042 CALL R7 6 + 0x980C0A07, // 0043 SETIDX R3 R5 R7 + 0x00140B05, // 0044 ADD R5 R5 K5 + 0x7001FFEC, // 0045 JMP #0033 + 0x80040600, // 0046 RET 1 R3 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_range +********************************************************************/ +be_local_closure(Animate_palette_set_range, /* name */ + be_nested_proto( + 7, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(value_error), + /* K1 */ be_nested_str_weak(min_X20must_X20be_X20lower_X20than_X20mex), + /* K2 */ be_nested_str_weak(range_min), + /* K3 */ be_nested_str_weak(range_max), + /* K4 */ be_nested_str_weak(slots_arr), + /* K5 */ be_nested_str_weak(parse_palette), + }), + be_str_weak(set_range), + &be_const_str_solidified, + ( &(const binstruction[11]) { /* code */ + 0x280C0202, // 0000 GE R3 R1 R2 + 0x780E0000, // 0001 JMPF R3 #0003 + 0xB0060101, // 0002 RAISE 1 K0 K1 + 0x90020401, // 0003 SETMBR R0 K2 R1 + 0x90020602, // 0004 SETMBR R0 K3 R2 + 0x8C0C0105, // 0005 GETMET R3 R0 K5 + 0x5C140200, // 0006 MOVE R5 R1 + 0x5C180400, // 0007 MOVE R6 R2 + 0x7C0C0600, // 0008 CALL R3 3 + 0x90020803, // 0009 SETMBR R0 K4 R3 + 0x80000000, // 000A RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_value +********************************************************************/ +be_local_closure(Animate_palette_set_value, /* name */ + be_nested_proto( + 18, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[13]) { /* constants */ + /* K0 */ be_nested_str_weak(range_min), + /* K1 */ be_nested_str_weak(range_max), + /* K2 */ be_nested_str_weak(tasmota), + /* K3 */ be_nested_str_weak(scale_int), + /* K4 */ be_nested_str_weak(slots), + /* K5 */ be_const_int(2), + /* K6 */ be_const_int(0), + /* K7 */ be_nested_str_weak(slots_arr), + /* K8 */ be_const_int(1), + /* K9 */ be_nested_str_weak(palette), + /* K10 */ be_nested_str_weak(get), + /* K11 */ be_nested_str_weak(obj), + /* K12 */ be_nested_str_weak(mth), + }), + be_str_weak(set_value), + &be_const_str_solidified, + ( &(const binstruction[96]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x1C080403, // 0002 EQ R2 R2 R3 + 0x740A0003, // 0003 JMPT R2 #0008 + 0x88080101, // 0004 GETMBR R2 R0 K1 + 0x4C0C0000, // 0005 LDNIL R3 + 0x1C080403, // 0006 EQ R2 R2 R3 + 0x780A0001, // 0007 JMPF R2 #000A + 0x4C080000, // 0008 LDNIL R2 + 0x80040400, // 0009 RET 1 R2 + 0xB80A0400, // 000A GETNGBL R2 K2 + 0x88080503, // 000B GETMBR R2 R2 K3 + 0x880C0104, // 000C GETMBR R3 R0 K4 + 0x04100705, // 000D SUB R4 R3 K5 + 0x24140906, // 000E GT R5 R4 K6 + 0x78160006, // 000F JMPF R5 #0017 + 0x88140107, // 0010 GETMBR R5 R0 K7 + 0x94140A04, // 0011 GETIDX R5 R5 R4 + 0x28140205, // 0012 GE R5 R1 R5 + 0x78160000, // 0013 JMPF R5 #0015 + 0x70020001, // 0014 JMP #0017 + 0x04100908, // 0015 SUB R4 R4 K8 + 0x7001FFF6, // 0016 JMP #000E + 0x88140109, // 0017 GETMBR R5 R0 K9 + 0x8C140B0A, // 0018 GETMET R5 R5 K10 + 0x541E0003, // 0019 LDINT R7 4 + 0x081C0807, // 001A MUL R7 R4 R7 + 0x54220003, // 001B LDINT R8 4 + 0x7C140600, // 001C CALL R5 3 + 0x88180109, // 001D GETMBR R6 R0 K9 + 0x8C180D0A, // 001E GETMET R6 R6 K10 + 0x00200908, // 001F ADD R8 R4 K8 + 0x54260003, // 0020 LDINT R9 4 + 0x08201009, // 0021 MUL R8 R8 R9 + 0x54260003, // 0022 LDINT R9 4 + 0x7C180600, // 0023 CALL R6 3 + 0x881C0107, // 0024 GETMBR R7 R0 K7 + 0x941C0E04, // 0025 GETIDX R7 R7 R4 + 0x00200908, // 0026 ADD R8 R4 K8 + 0x88240107, // 0027 GETMBR R9 R0 K7 + 0x94201208, // 0028 GETIDX R8 R9 R8 + 0x5C280400, // 0029 MOVE R10 R2 + 0x5C2C0200, // 002A MOVE R11 R1 + 0x5C300E00, // 002B MOVE R12 R7 + 0x5C341000, // 002C MOVE R13 R8 + 0x543A0007, // 002D LDINT R14 8 + 0x3C380A0E, // 002E SHR R14 R5 R14 + 0x543E00FE, // 002F LDINT R15 255 + 0x2C381C0F, // 0030 AND R14 R14 R15 + 0x543E0007, // 0031 LDINT R15 8 + 0x3C3C0C0F, // 0032 SHR R15 R6 R15 + 0x544200FE, // 0033 LDINT R16 255 + 0x2C3C1E10, // 0034 AND R15 R15 R16 + 0x7C280A00, // 0035 CALL R10 5 + 0x5C241400, // 0036 MOVE R9 R10 + 0x5C280400, // 0037 MOVE R10 R2 + 0x5C2C0200, // 0038 MOVE R11 R1 + 0x5C300E00, // 0039 MOVE R12 R7 + 0x5C341000, // 003A MOVE R13 R8 + 0x543A000F, // 003B LDINT R14 16 + 0x3C380A0E, // 003C SHR R14 R5 R14 + 0x543E00FE, // 003D LDINT R15 255 + 0x2C381C0F, // 003E AND R14 R14 R15 + 0x543E000F, // 003F LDINT R15 16 + 0x3C3C0C0F, // 0040 SHR R15 R6 R15 + 0x544200FE, // 0041 LDINT R16 255 + 0x2C3C1E10, // 0042 AND R15 R15 R16 + 0x7C280A00, // 0043 CALL R10 5 + 0x5C2C0400, // 0044 MOVE R11 R2 + 0x5C300200, // 0045 MOVE R12 R1 + 0x5C340E00, // 0046 MOVE R13 R7 + 0x5C381000, // 0047 MOVE R14 R8 + 0x543E0017, // 0048 LDINT R15 24 + 0x3C3C0A0F, // 0049 SHR R15 R5 R15 + 0x544200FE, // 004A LDINT R16 255 + 0x2C3C1E10, // 004B AND R15 R15 R16 + 0x54420017, // 004C LDINT R16 24 + 0x3C400C10, // 004D SHR R16 R6 R16 + 0x544600FE, // 004E LDINT R17 255 + 0x2C402011, // 004F AND R16 R16 R17 + 0x7C2C0A00, // 0050 CALL R11 5 + 0x5432000F, // 0051 LDINT R12 16 + 0x3830120C, // 0052 SHL R12 R9 R12 + 0x54360007, // 0053 LDINT R13 8 + 0x3834140D, // 0054 SHL R13 R10 R13 + 0x3030180D, // 0055 OR R12 R12 R13 + 0x3030180B, // 0056 OR R12 R12 R11 + 0x8834010B, // 0057 GETMBR R13 R0 K11 + 0x8838010C, // 0058 GETMBR R14 R0 K12 + 0x78360004, // 0059 JMPF R13 #005F + 0x783A0003, // 005A JMPF R14 #005F + 0x5C3C1C00, // 005B MOVE R15 R14 + 0x5C401A00, // 005C MOVE R16 R13 + 0x5C441800, // 005D MOVE R17 R12 + 0x7C3C0400, // 005E CALL R15 2 + 0x80041800, // 005F RET 1 R12 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_duration +********************************************************************/ +be_local_closure(Animate_palette_set_duration, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_weak(value_error), + /* K2 */ be_nested_str_weak(duration_ms_X20must_X20be_X20positive), + /* K3 */ be_nested_str_weak(duration_ms), + /* K4 */ be_nested_str_weak(slots_arr), + /* K5 */ be_nested_str_weak(parse_palette), + /* K6 */ be_const_int(1), + }), + be_str_weak(set_duration), + &be_const_str_solidified, + ( &(const binstruction[14]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x1C080202, // 0001 EQ R2 R1 R2 + 0x780A0000, // 0002 JMPF R2 #0004 + 0x80000400, // 0003 RET 0 + 0x18080300, // 0004 LE R2 R1 K0 + 0x780A0000, // 0005 JMPF R2 #0007 + 0xB0060302, // 0006 RAISE 1 K1 K2 + 0x90020601, // 0007 SETMBR R0 K3 R1 + 0x8C080105, // 0008 GETMET R2 R0 K5 + 0x58100000, // 0009 LDCONST R4 K0 + 0x04140306, // 000A SUB R5 R1 K6 + 0x7C080600, // 000B CALL R2 3 + 0x90020802, // 000C SETMBR R0 K4 R2 + 0x80000000, // 000D RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_palette_init, /* name */ + be_nested_proto( + 6, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_str_weak(init), + /* K1 */ be_nested_str_weak(duration_ms), + /* K2 */ be_nested_str_weak(running), + /* K3 */ be_nested_str_weak(bri), + /* K4 */ be_nested_str_weak(color), + /* K5 */ be_nested_str_weak(light_state), + /* K6 */ be_nested_str_weak(RGB), + /* K7 */ be_nested_str_weak(set_palette), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[19]) { /* code */ + 0x600C0003, // 0000 GETGBL R3 G3 + 0x5C100000, // 0001 MOVE R4 R0 + 0x7C0C0200, // 0002 CALL R3 1 + 0x8C0C0700, // 0003 GETMET R3 R3 K0 + 0x7C0C0200, // 0004 CALL R3 1 + 0x90020202, // 0005 SETMBR R0 K1 R2 + 0x500C0000, // 0006 LDBOOL R3 0 0 + 0x90020403, // 0007 SETMBR R0 K2 R3 + 0x540E0063, // 0008 LDINT R3 100 + 0x90020603, // 0009 SETMBR R0 K3 R3 + 0xB80E0A00, // 000A GETNGBL R3 K5 + 0xB8120A00, // 000B GETNGBL R4 K5 + 0x88100906, // 000C GETMBR R4 R4 K6 + 0x7C0C0200, // 000D CALL R3 1 + 0x90020803, // 000E SETMBR R0 K4 R3 + 0x8C0C0107, // 000F GETMET R3 R0 K7 + 0x5C140200, // 0010 MOVE R5 R1 + 0x7C0C0400, // 0011 CALL R3 2 + 0x80000000, // 0012 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Animate_palette +********************************************************************/ +extern const bclass be_class_Animate_animator; +be_local_class(Animate_palette, + 7, + &be_class_Animate_animator, + be_nested_map(17, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(color, 13), be_const_var(6) }, + { be_const_key_weak(slots, -1), be_const_var(2) }, + { be_const_key_weak(animate, 11), be_const_closure(Animate_palette_animate_closure) }, + { be_const_key_weak(range_max, 10), be_const_var(4) }, + { be_const_key_weak(set_palette, -1), be_const_closure(Animate_palette_set_palette_closure) }, + { be_const_key_weak(set_bri, -1), be_const_closure(Animate_palette_set_bri_closure) }, + { be_const_key_weak(bri, -1), be_const_var(5) }, + { be_const_key_weak(to_css_gradient, 12), be_const_static_closure(Animate_palette_to_css_gradient_closure) }, + { be_const_key_weak(slots_arr, 1), be_const_var(1) }, + { be_const_key_weak(range_min, 5), be_const_var(3) }, + { be_const_key_weak(set_value, -1), be_const_closure(Animate_palette_set_value_closure) }, + { be_const_key_weak(set_range, -1), be_const_closure(Animate_palette_set_range_closure) }, + { be_const_key_weak(parse_palette, -1), be_const_closure(Animate_palette_parse_palette_closure) }, + { be_const_key_weak(palette, -1), be_const_var(0) }, + { be_const_key_weak(set_duration, -1), be_const_closure(Animate_palette_set_duration_closure) }, + { be_const_key_weak(init, -1), be_const_closure(Animate_palette_init_closure) }, + { be_const_key_weak(ptr_to_palette, 0), be_const_static_closure(Animate_palette_ptr_to_palette_closure) }, + })), + be_str_weak(Animate_palette) +); +/*******************************************************************/ + +void be_load_Animate_palette_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Animate_palette); + be_setglobal(vm, "Animate_palette"); + be_pop(vm, 1); +} + +extern const bclass be_class_Animate_oscillator; + +/******************************************************************** +** Solidified function: set_duty_cycle +********************************************************************/ +be_local_closure(Animate_oscillator_set_duty_cycle, /* name */ + be_nested_proto( + 3, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_weak(duty_cycle), + }), + be_str_weak(set_duty_cycle), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x14080300, // 0000 LT R2 R1 K0 + 0x780A0000, // 0001 JMPF R2 #0003 + 0x58040000, // 0002 LDCONST R1 K0 + 0x540A0063, // 0003 LDINT R2 100 + 0x24080202, // 0004 GT R2 R1 R2 + 0x780A0000, // 0005 JMPF R2 #0007 + 0x54060063, // 0006 LDINT R1 100 + 0x90020201, // 0007 SETMBR R0 K1 R1 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_a +********************************************************************/ +be_local_closure(Animate_oscillator_set_a, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(a), + }), + be_str_weak(set_a), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_b +********************************************************************/ +be_local_closure(Animate_oscillator_set_b, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(b), + }), + be_str_weak(set_b), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_form +********************************************************************/ +be_local_closure(Animate_oscillator_set_form, /* name */ + be_nested_proto( + 3, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_const_int(1), + /* K1 */ be_nested_str_weak(form), + }), + be_str_weak(set_form), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x1C080202, // 0001 EQ R2 R1 R2 + 0x780A0000, // 0002 JMPF R2 #0004 + 0x58040000, // 0003 LDCONST R1 K0 + 0x90020201, // 0004 SETMBR R0 K1 R1 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_phase +********************************************************************/ +be_local_closure(Animate_oscillator_set_phase, /* name */ + be_nested_proto( + 3, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_weak(phase), + }), + be_str_weak(set_phase), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x14080300, // 0000 LT R2 R1 K0 + 0x780A0000, // 0001 JMPF R2 #0003 + 0x58040000, // 0002 LDCONST R1 K0 + 0x540A0063, // 0003 LDINT R2 100 + 0x24080202, // 0004 GT R2 R1 R2 + 0x780A0000, // 0005 JMPF R2 #0007 + 0x54060063, // 0006 LDINT R1 100 + 0x90020201, // 0007 SETMBR R0 K1 R1 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Animate_oscillator_init, /* name */ + be_nested_proto( + 7, /* nstack */ + 5, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[10]) { /* constants */ + /* K0 */ be_nested_str_weak(init), + /* K1 */ be_nested_str_weak(phase), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(duty_cycle), + /* K4 */ be_nested_str_weak(a), + /* K5 */ be_nested_str_weak(b), + /* K6 */ be_nested_str_weak(duration_ms), + /* K7 */ be_nested_str_weak(value), + /* K8 */ be_const_int(1), + /* K9 */ be_nested_str_weak(form), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[18]) { /* code */ + 0x60140003, // 0000 GETGBL R5 G3 + 0x5C180000, // 0001 MOVE R6 R0 + 0x7C140200, // 0002 CALL R5 1 + 0x8C140B00, // 0003 GETMET R5 R5 K0 + 0x7C140200, // 0004 CALL R5 1 + 0x90020302, // 0005 SETMBR R0 K1 K2 + 0x54160031, // 0006 LDINT R5 50 + 0x90020605, // 0007 SETMBR R0 K3 R5 + 0x90020801, // 0008 SETMBR R0 K4 R1 + 0x90020A02, // 0009 SETMBR R0 K5 R2 + 0x90020C03, // 000A SETMBR R0 K6 R3 + 0x90020E01, // 000B SETMBR R0 K7 R1 + 0x4C140000, // 000C LDNIL R5 + 0x1C140805, // 000D EQ R5 R4 R5 + 0x78160000, // 000E JMPF R5 #0010 + 0x58100008, // 000F LDCONST R4 K8 + 0x90021204, // 0010 SETMBR R0 K9 R4 + 0x80000000, // 0011 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: animate +********************************************************************/ +be_local_closure(Animate_oscillator_animate, /* name */ + be_nested_proto( + 18, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[20]) { /* constants */ + /* K0 */ be_nested_str_weak(duration_ms), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(millis), + /* K3 */ be_nested_str_weak(origin), + /* K4 */ be_const_int(0), + /* K5 */ be_nested_str_weak(scale_uint), + /* K6 */ be_nested_str_weak(duty_cycle), + /* K7 */ be_nested_str_weak(beat), + /* K8 */ be_nested_str_weak(a), + /* K9 */ be_nested_str_weak(b), + /* K10 */ be_nested_str_weak(value), + /* K11 */ be_nested_str_weak(phase), + /* K12 */ be_nested_str_weak(form), + /* K13 */ be_const_int(1), + /* K14 */ be_nested_str_weak(scale_int), + /* K15 */ be_const_int(2), + /* K16 */ be_const_int(3), + /* K17 */ be_nested_str_weak(sine_int), + /* K18 */ be_nested_str_weak(obj), + /* K19 */ be_nested_str_weak(mth), + }), + be_str_weak(animate), + &be_const_str_solidified, + ( &(const binstruction[141]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x1C080403, // 0002 EQ R2 R2 R3 + 0x780A0000, // 0003 JMPF R2 #0005 + 0x80000400, // 0004 RET 0 + 0x4C080000, // 0005 LDNIL R2 + 0x1C080202, // 0006 EQ R2 R1 R2 + 0x780A0003, // 0007 JMPF R2 #000C + 0xB80A0200, // 0008 GETNGBL R2 K1 + 0x8C080502, // 0009 GETMET R2 R2 K2 + 0x7C080200, // 000A CALL R2 1 + 0x5C040400, // 000B MOVE R1 R2 + 0x88080103, // 000C GETMBR R2 R0 K3 + 0x04080202, // 000D SUB R2 R1 R2 + 0x140C0504, // 000E LT R3 R2 K4 + 0x780E0001, // 000F JMPF R3 #0012 + 0x58080004, // 0010 LDCONST R2 K4 + 0x88040103, // 0011 GETMBR R1 R0 K3 + 0x880C0100, // 0012 GETMBR R3 R0 K0 + 0x4C100000, // 0013 LDNIL R4 + 0xB8160200, // 0014 GETNGBL R5 K1 + 0x8C140B05, // 0015 GETMET R5 R5 K5 + 0x881C0106, // 0016 GETMBR R7 R0 K6 + 0x58200004, // 0017 LDCONST R8 K4 + 0x54260063, // 0018 LDINT R9 100 + 0x58280004, // 0019 LDCONST R10 K4 + 0x5C2C0600, // 001A MOVE R11 R3 + 0x7C140C00, // 001B CALL R5 6 + 0x5C100A00, // 001C MOVE R4 R5 + 0x28140403, // 001D GE R5 R2 R3 + 0x78160007, // 001E JMPF R5 #0027 + 0x0C180403, // 001F DIV R6 R2 R3 + 0x08180C03, // 0020 MUL R6 R6 R3 + 0x88140103, // 0021 GETMBR R5 R0 K3 + 0x00140A06, // 0022 ADD R5 R5 R6 + 0x90020605, // 0023 SETMBR R0 K3 R5 + 0x10080403, // 0024 MOD R2 R2 R3 + 0x8C140107, // 0025 GETMET R5 R0 K7 + 0x7C140200, // 0026 CALL R5 1 + 0x88140108, // 0027 GETMBR R5 R0 K8 + 0x88180109, // 0028 GETMBR R6 R0 K9 + 0x881C010A, // 0029 GETMBR R7 R0 K10 + 0x5C200400, // 002A MOVE R8 R2 + 0x8824010B, // 002B GETMBR R9 R0 K11 + 0x24241304, // 002C GT R9 R9 K4 + 0x7826000B, // 002D JMPF R9 #003A + 0xB8260200, // 002E GETNGBL R9 K1 + 0x8C241305, // 002F GETMET R9 R9 K5 + 0x882C010B, // 0030 GETMBR R11 R0 K11 + 0x58300004, // 0031 LDCONST R12 K4 + 0x54360063, // 0032 LDINT R13 100 + 0x58380004, // 0033 LDCONST R14 K4 + 0x5C3C0600, // 0034 MOVE R15 R3 + 0x7C240C00, // 0035 CALL R9 6 + 0x00201009, // 0036 ADD R8 R8 R9 + 0x24241003, // 0037 GT R9 R8 R3 + 0x78260000, // 0038 JMPF R9 #003A + 0x04201003, // 0039 SUB R8 R8 R3 + 0x8824010C, // 003A GETMBR R9 R0 K12 + 0x1C24130D, // 003B EQ R9 R9 K13 + 0x78260009, // 003C JMPF R9 #0047 + 0xB8260200, // 003D GETNGBL R9 K1 + 0x8C24130E, // 003E GETMET R9 R9 K14 + 0x5C2C1000, // 003F MOVE R11 R8 + 0x58300004, // 0040 LDCONST R12 K4 + 0x0434070D, // 0041 SUB R13 R3 K13 + 0x5C380A00, // 0042 MOVE R14 R5 + 0x5C3C0C00, // 0043 MOVE R15 R6 + 0x7C240C00, // 0044 CALL R9 6 + 0x5C1C1200, // 0045 MOVE R7 R9 + 0x7002003B, // 0046 JMP #0083 + 0x8824010C, // 0047 GETMBR R9 R0 K12 + 0x1C24130F, // 0048 EQ R9 R9 K15 + 0x78260015, // 0049 JMPF R9 #0060 + 0x14241004, // 004A LT R9 R8 R4 + 0x78260009, // 004B JMPF R9 #0056 + 0xB8260200, // 004C GETNGBL R9 K1 + 0x8C24130E, // 004D GETMET R9 R9 K14 + 0x5C2C1000, // 004E MOVE R11 R8 + 0x58300004, // 004F LDCONST R12 K4 + 0x0434090D, // 0050 SUB R13 R4 K13 + 0x5C380A00, // 0051 MOVE R14 R5 + 0x5C3C0C00, // 0052 MOVE R15 R6 + 0x7C240C00, // 0053 CALL R9 6 + 0x5C1C1200, // 0054 MOVE R7 R9 + 0x70020008, // 0055 JMP #005F + 0xB8260200, // 0056 GETNGBL R9 K1 + 0x8C24130E, // 0057 GETMET R9 R9 K14 + 0x5C2C1000, // 0058 MOVE R11 R8 + 0x5C300800, // 0059 MOVE R12 R4 + 0x0434070D, // 005A SUB R13 R3 K13 + 0x5C380C00, // 005B MOVE R14 R6 + 0x5C3C0A00, // 005C MOVE R15 R5 + 0x7C240C00, // 005D CALL R9 6 + 0x5C1C1200, // 005E MOVE R7 R9 + 0x70020022, // 005F JMP #0083 + 0x8824010C, // 0060 GETMBR R9 R0 K12 + 0x1C241310, // 0061 EQ R9 R9 K16 + 0x78260005, // 0062 JMPF R9 #0069 + 0x14241004, // 0063 LT R9 R8 R4 + 0x78260001, // 0064 JMPF R9 #0067 + 0x5C1C0A00, // 0065 MOVE R7 R5 + 0x70020000, // 0066 JMP #0068 + 0x5C1C0C00, // 0067 MOVE R7 R6 + 0x70020019, // 0068 JMP #0083 + 0x8824010C, // 0069 GETMBR R9 R0 K12 + 0x542A0003, // 006A LDINT R10 4 + 0x1C24120A, // 006B EQ R9 R9 R10 + 0x78260015, // 006C JMPF R9 #0083 + 0xB8260200, // 006D GETNGBL R9 K1 + 0x8C24130E, // 006E GETMET R9 R9 K14 + 0x5C2C1000, // 006F MOVE R11 R8 + 0x58300004, // 0070 LDCONST R12 K4 + 0x0434070D, // 0071 SUB R13 R3 K13 + 0x58380004, // 0072 LDCONST R14 K4 + 0x543E7FFE, // 0073 LDINT R15 32767 + 0x7C240C00, // 0074 CALL R9 6 + 0xB82A0200, // 0075 GETNGBL R10 K1 + 0x8C281511, // 0076 GETMET R10 R10 K17 + 0x54321FFF, // 0077 LDINT R12 8192 + 0x0430120C, // 0078 SUB R12 R9 R12 + 0x7C280400, // 0079 CALL R10 2 + 0xB82E0200, // 007A GETNGBL R11 K1 + 0x8C2C170E, // 007B GETMET R11 R11 K14 + 0x5C341400, // 007C MOVE R13 R10 + 0x5439EFFF, // 007D LDINT R14 -4096 + 0x543E0FFF, // 007E LDINT R15 4096 + 0x5C400A00, // 007F MOVE R16 R5 + 0x5C440C00, // 0080 MOVE R17 R6 + 0x7C2C0C00, // 0081 CALL R11 6 + 0x5C1C1600, // 0082 MOVE R7 R11 + 0x90021407, // 0083 SETMBR R0 K10 R7 + 0x88240112, // 0084 GETMBR R9 R0 K18 + 0x88280113, // 0085 GETMBR R10 R0 K19 + 0x78260004, // 0086 JMPF R9 #008C + 0x782A0003, // 0087 JMPF R10 #008C + 0x5C2C1400, // 0088 MOVE R11 R10 + 0x5C301200, // 0089 MOVE R12 R9 + 0x5C340E00, // 008A MOVE R13 R7 + 0x7C2C0400, // 008B CALL R11 2 + 0x80040E00, // 008C RET 1 R7 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Animate_oscillator +********************************************************************/ +extern const bclass be_class_Animate_animator; +be_local_class(Animate_oscillator, + 6, + &be_class_Animate_animator, + be_nested_map(13, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(animate, -1), be_const_closure(Animate_oscillator_animate_closure) }, + { be_const_key_weak(a, -1), be_const_var(2) }, + { be_const_key_weak(init, 11), be_const_closure(Animate_oscillator_init_closure) }, + { be_const_key_weak(duty_cycle, 10), be_const_var(1) }, + { be_const_key_weak(b, -1), be_const_var(3) }, + { be_const_key_weak(value, -1), be_const_var(5) }, + { be_const_key_weak(set_duty_cycle, 2), be_const_closure(Animate_oscillator_set_duty_cycle_closure) }, + { be_const_key_weak(set_a, -1), be_const_closure(Animate_oscillator_set_a_closure) }, + { be_const_key_weak(set_b, -1), be_const_closure(Animate_oscillator_set_b_closure) }, + { be_const_key_weak(set_form, -1), be_const_closure(Animate_oscillator_set_form_closure) }, + { be_const_key_weak(phase, -1), be_const_var(0) }, + { be_const_key_weak(form, -1), be_const_var(4) }, + { be_const_key_weak(set_phase, 0), be_const_closure(Animate_oscillator_set_phase_closure) }, + })), + be_str_weak(Animate_oscillator) +); +/*******************************************************************/ + +void be_load_Animate_oscillator_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Animate_oscillator); + be_setglobal(vm, "Animate_oscillator"); + be_pop(vm, 1); +} +/********************************************************************/ +/* End of solidification */ diff --git a/lib/libesp32/berry_animate/src/solidify/solidified_leds_frame_be_methods.h b/lib/libesp32/berry_animate/src/solidify/solidified_leds_frame_be_methods.h new file mode 100644 index 000000000..7a565f9f2 --- /dev/null +++ b/lib/libesp32/berry_animate/src/solidify/solidified_leds_frame_be_methods.h @@ -0,0 +1,186 @@ +/* Solidification of leds_frame_be_methods.h */ +/********************************************************************\ +* Generated code, don't edit * +\********************************************************************/ +#include "be_constobj.h" + +extern const bclass be_class_Leds_frame_be; + +/******************************************************************** +** Solidified function: setitem +********************************************************************/ +be_local_closure(Leds_frame_be_setitem, /* name */ + be_nested_proto( + 8, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(set), + }), + &be_const_str_setitem, + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x8C0C0100, // 0000 GETMET R3 R0 K0 + 0x54160003, // 0001 LDINT R5 4 + 0x08140205, // 0002 MUL R5 R1 R5 + 0x5C180400, // 0003 MOVE R6 R2 + 0x541E0003, // 0004 LDINT R7 4 + 0x7C0C0800, // 0005 CALL R3 4 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_pixel +********************************************************************/ +be_local_closure(Leds_frame_be_set_pixel, /* name */ + be_nested_proto( + 11, /* nstack */ + 6, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str(setitem), + }), + &be_const_str_set_pixel, + &be_const_str_solidified, + ( &(const binstruction[26]) { /* code */ + 0x4C180000, // 0000 LDNIL R6 + 0x1C180A06, // 0001 EQ R6 R5 R6 + 0x781A0000, // 0002 JMPF R6 #0004 + 0x58140000, // 0003 LDCONST R5 K0 + 0x541A00FE, // 0004 LDINT R6 255 + 0x2C180A06, // 0005 AND R6 R5 R6 + 0x541E0017, // 0006 LDINT R7 24 + 0x38180C07, // 0007 SHL R6 R6 R7 + 0x541E00FE, // 0008 LDINT R7 255 + 0x2C1C0407, // 0009 AND R7 R2 R7 + 0x5422000F, // 000A LDINT R8 16 + 0x381C0E08, // 000B SHL R7 R7 R8 + 0x30180C07, // 000C OR R6 R6 R7 + 0x541E00FE, // 000D LDINT R7 255 + 0x2C1C0607, // 000E AND R7 R3 R7 + 0x54220007, // 000F LDINT R8 8 + 0x381C0E08, // 0010 SHL R7 R7 R8 + 0x30180C07, // 0011 OR R6 R6 R7 + 0x541E00FE, // 0012 LDINT R7 255 + 0x2C1C0807, // 0013 AND R7 R4 R7 + 0x30180C07, // 0014 OR R6 R6 R7 + 0x8C1C0101, // 0015 GETMET R7 R0 K1 + 0x5C240200, // 0016 MOVE R9 R1 + 0x5C280C00, // 0017 MOVE R10 R6 + 0x7C1C0600, // 0018 CALL R7 3 + 0x80000000, // 0019 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: item +********************************************************************/ +be_local_closure(Leds_frame_be_item, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str(get), + }), + &be_const_str_item, + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x8C080100, // 0000 GETMET R2 R0 K0 + 0x54120003, // 0001 LDINT R4 4 + 0x08100204, // 0002 MUL R4 R1 R4 + 0x54160003, // 0003 LDINT R5 4 + 0x7C080600, // 0004 CALL R2 3 + 0x80040400, // 0005 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Leds_frame_be_init, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str(pixel_size), + /* K2 */ be_nested_str(init), + }), + &be_const_str_init, + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0x14080300, // 0000 LT R2 R1 K0 + 0x780A0000, // 0001 JMPF R2 #0003 + 0x44040200, // 0002 NEG R1 R1 + 0x90020201, // 0003 SETMBR R0 K1 R1 + 0x60080003, // 0004 GETGBL R2 G3 + 0x5C0C0000, // 0005 MOVE R3 R0 + 0x7C080200, // 0006 CALL R2 1 + 0x8C080502, // 0007 GETMET R2 R2 K2 + 0x5411FFFB, // 0008 LDINT R4 -4 + 0x08100204, // 0009 MUL R4 R1 R4 + 0x7C080400, // 000A CALL R2 2 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: Leds_frame_be +********************************************************************/ +be_local_class(Leds_frame_be, + 0, + NULL, + be_nested_map(4, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key(setitem, 1), be_const_closure(Leds_frame_be_setitem_closure) }, + { be_const_key(set_pixel, -1), be_const_closure(Leds_frame_be_set_pixel_closure) }, + { be_const_key(item, -1), be_const_closure(Leds_frame_be_item_closure) }, + { be_const_key(init, -1), be_const_closure(Leds_frame_be_init_closure) }, + })), + (bstring*) &be_const_str_Leds_frame_be +); +/*******************************************************************/ + +void be_load_Leds_frame_be_class(bvm *vm) { + be_pushntvclass(vm, &be_class_Leds_frame_be); + be_setglobal(vm, "Leds_frame_be"); + be_pop(vm, 1); +} +/********************************************************************/ +/* End of solidification */ diff --git a/pio-tools/gen-berry-structures.py b/pio-tools/gen-berry-structures.py index 923ff723b..f1cf36052 100644 --- a/pio-tools/gen-berry-structures.py +++ b/pio-tools/gen-berry-structures.py @@ -16,6 +16,6 @@ for filePath in fileList: # print("Deleting file : ", filePath) except: print("Error while deleting file : ", filePath) -cmd = (env["PYTHONEXE"],join("tools","coc","coc"),"-o","generate","src","default",join("..","berry_tasmota","src"),join("..","berry_matter","src","solidify"),join("..","berry_matter","src"),join("..","berry_tasmota","src","solidify"),join("..","berry_mapping","src"),join("..","berry_int64","src"),join("..","..","libesp32_lvgl","lv_binding_berry","src"),join("..","..","libesp32_lvgl","lv_binding_berry","src","solidify"),join("..","..","libesp32_lvgl","lv_binding_berry","generate"),"-c",join("default","berry_conf.h")) +cmd = (env["PYTHONEXE"],join("tools","coc","coc"),"-o","generate","src","default",join("..","berry_tasmota","src"),join("..","berry_matter","src","solidify"),join("..","berry_matter","src"),join("..","berry_animate","src","solidify"),join("..","berry_animate","src"),join("..","berry_tasmota","src","solidify"),join("..","berry_mapping","src"),join("..","berry_int64","src"),join("..","..","libesp32_lvgl","lv_binding_berry","src"),join("..","..","libesp32_lvgl","lv_binding_berry","src","solidify"),join("..","..","libesp32_lvgl","lv_binding_berry","generate"),"-c",join("default","berry_conf.h")) returncode = subprocess.call(cmd, shell=False) os.chdir(CURRENT_DIR) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino index e75f5cbed..08f287567 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_leds.ino @@ -251,6 +251,27 @@ extern "C" { } } +uint32_t ApplyBriGamma(uint32_t color_a /* 0xRRGGBB */, uint32_t bri /* 0..255 */, bool gamma) { + if (bri == 0) { return 0x000000; } // if bri is zero, short-cut + uint32_t r = (color_a >> 16) & 0xFF; + uint32_t g = (color_a >> 8) & 0xFF; + uint32_t b = (color_a ) & 0xFF; + + if (bri < 255) { // apply bri + r = changeUIntScale(bri, 0, 255, 0, r); + g = changeUIntScale(bri, 0, 255, 0, g); + b = changeUIntScale(bri, 0, 255, 0, b); + } + + if (gamma) { // apply gamma + r = ledGamma(r); + g = ledGamma(g); + b = ledGamma(b); + } + uint32_t rgb = (r << 16) | (g << 8) | b; + return rgb; +} + extern "C" { // Leds.blend_color(color_a:int, color_b:int [, alpha:int]) -> color:int // @@ -291,27 +312,6 @@ extern "C" { be_raise(vm, kTypeError, nullptr); } - static uint32_t ApplyBriGamma(uint32_t color_a /* 0xRRGGBB */, uint32_t bri /* 0..255 */, bool gamma) { - if (bri == 0) { return 0x000000; } // if bri is zero, short-cut - uint32_t r = (color_a >> 16) & 0xFF; - uint32_t g = (color_a >> 8) & 0xFF; - uint32_t b = (color_a ) & 0xFF; - - if (bri < 255) { // apply bri - r = changeUIntScale(bri, 0, 255, 0, r); - g = changeUIntScale(bri, 0, 255, 0, g); - b = changeUIntScale(bri, 0, 255, 0, b); - } - - if (gamma) { // apply gamma - r = ledGamma(r); - g = ledGamma(g); - b = ledGamma(b); - } - uint32_t rgb = (r << 16) | (g << 8) | b; - return rgb; - } - // Leds.apply_bri_gamma(color_rgb:int (0xRRGGBB) [bri:int (0..255), gamma:bool]) -> color:int (0xRRGGBB) // int32_t be_leds_apply_bri_gamma(bvm *vm); @@ -335,152 +335,6 @@ extern "C" { } be_raise(vm, kTypeError, nullptr); } - - // Leds_frame.blend(color1:int, color2:int, alpha:int) -> int - // - int32_t be_leds_blend(bvm *vm); - int32_t be_leds_blend(bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top >= 3 && be_isint(vm, 1) && be_isint(vm, 2) && be_isint(vm, 3)) { - uint32_t color_a = be_toint(vm, 1); - uint32_t color_b = be_toint(vm, 2); - uint32_t alpha = be_toint(vm, 3); - uint32_t r = (color_a >> 16) & 0xFF; - uint32_t g = (color_a >> 8) & 0xFF; - uint32_t b = (color_a ) & 0xFF; - uint32_t a = (color_a >> 24) & 0xFF; - uint32_t r2 = (color_b >> 16) & 0xFF; - uint32_t g2 = (color_b >> 8) & 0xFF; - uint32_t b2 = (color_b ) & 0xFF; - uint32_t a2 = (color_b >> 24) & 0xFF; - uint32_t r3 = changeUIntScale(alpha, 0, 255, r2, r); - uint32_t g3 = changeUIntScale(alpha, 0, 255, g2, g); - uint32_t b3 = changeUIntScale(alpha, 0, 255, b2, b); - uint32_t a3 = changeUIntScale(alpha, 0, 255, a2, a); - uint32_t rgb = (a3 << 24) | (r3 << 16) | (g3 << 8) | b3; - be_pushint(vm, rgb); - be_return(vm); - } - be_raise(vm, kTypeError, nullptr); - } - - // Leds_frame.blend_pixels(dest:bytes(), foreground:bytes) -> nil - // Destination can be the same as foreground or background - // - // All calculation are done in `0xAARRGGBB` format, AA=0 if opaque (i.e. ignored) - // Background has always alpha = 0 (any other value is ignored) - for simplification - // Size is truncated to smallest of all 3 buffers - int32_t be_leds_blend_pixels(bvm *vm); - int32_t be_leds_blend_pixels(bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top >= 2 && be_isbytes(vm, 2)) { - size_t dest_len = 0; - uint32_t * dest_buf = (uint32_t*) be_tobytes(vm, 1, &dest_len); - // back = dest for now, could be changed in the future - size_t back_len = 0; - const uint32_t * back_buf = (const uint32_t*) be_tobytes(vm, 1, &back_len); - size_t fore_len = 0; - const uint32_t * fore_buf = (const uint32_t*) be_tobytes(vm, 2, &fore_len); - - if (fore_len < dest_len) { dest_len = fore_len; } - if (back_len < dest_len) { dest_len = back_len; } - size_t pixels_count = dest_len / 4; - if (pixels_count > 0) { - uint32_t * dest = (uint32_t *)dest_buf; - uint32_t * back = (uint32_t *)back_buf; - uint32_t * fore = (uint32_t *)fore_buf; - for (size_t i = 0; i < pixels_count; i++) { - uint32_t back_argb = back[i]; - uint32_t fore_argb = fore[i]; - uint32_t fore_alpha = (fore_argb >> 24) & 0xFF; - uint32_t dest_rgb_new = back_argb; - if (fore_alpha == 0) { // opaque layer, copy value from fore - dest_rgb_new = fore_argb; - } else if (fore_alpha == 255) { // fore is transparent, use back - // nothing to do, dest_rgb_new = back_argb above - } else { - uint32_t back_r = (back_argb >> 16) & 0xFF; - uint32_t fore_r = (fore_argb >> 16) & 0xFF; - uint32_t back_g = (back_argb >> 8) & 0xFF; - uint32_t fore_g = (fore_argb >> 8) & 0xFF; - uint32_t back_b = (back_argb ) & 0xFF; - uint32_t fore_b = (fore_argb ) & 0xFF; - uint32_t dest_r_new = changeUIntScale(fore_alpha, 0, 255, fore_r, back_r); - uint32_t dest_g_new = changeUIntScale(fore_alpha, 0, 255, fore_g, back_g); - uint32_t dest_b_new = changeUIntScale(fore_alpha, 0, 255, fore_b, back_b); - dest_rgb_new = (dest_r_new << 16) | (dest_g_new << 8) | dest_b_new; - } - dest[i] = dest_rgb_new; - } - } - be_return_nil(vm); - } - be_raise(vm, kTypeError, nullptr); - } - - // Leds_frame.fill_pixels(dest:bytes(), color:int) -> nil - // - // Fill buffer with same color - int32_t be_leds_fill_pixels(bvm *vm); - int32_t be_leds_fill_pixels(bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top >= 2 && be_isint(vm, 2)) { - size_t dest_len = 0; - uint32_t * dest_buf = (uint32_t*) be_tobytes(vm, 1, &dest_len); - uint32_t color = be_toint(vm, 2); - - size_t pixels_count = dest_len / 4; - if (pixels_count > 0) { - uint32_t * dest = (uint32_t *)dest_buf; - for (size_t i = 0; i < pixels_count; i++) { - dest[i] = color; - } - } - be_return_nil(vm); - } - be_raise(vm, kTypeError, nullptr); - } - - // Leds_frame.paste_pixels(neopixel:bytes(), led_buffer:bytes(), bri:int 0..100, gamma:bool) - // - // Copy from ARGB buffer to GRB - int32_t be_leds_paste_pixels(bvm *vm); - int32_t be_leds_paste_pixels(bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top >= 2 && be_isbytes(vm, 2)) { - size_t src_len = 0; - uint32_t * src_buf = (uint32_t*) be_tobytes(vm, 1, &src_len); - size_t dest_len = 0; - uint8_t * dest_buf = (uint8_t*) be_tobytes(vm, 2, &dest_len); - - uint32_t bri255 = 255; - if (top >= 3 && be_isint(vm, 3)) { - bri255 = be_toint(vm, 3); - } - bool gamma = false; - if (top >= 4 && be_isbool(vm, 4)) { - gamma = be_tobool(vm, 4); - } - - size_t pixels_count = src_len / 4; - if (pixels_count > dest_len / 3) { pixels_count = dest_len / 3; } - if (pixels_count > 0) { - for (size_t i = 0; i < pixels_count; i++) { - uint32_t src_argb = ApplyBriGamma(src_buf[i], bri255, gamma); - uint32_t src_r = (src_argb >> 16) & 0xFF; - uint32_t src_g = (src_argb >> 8) & 0xFF; - uint32_t src_b = (src_argb ) & 0xFF; - dest_buf[i * 3 + 0] = src_g; - dest_buf[i * 3 + 1] = src_r; - dest_buf[i * 3 + 2] = src_b; - } - } - be_return_nil(vm); - } - be_raise(vm, kTypeError, nullptr); - } - - } #endif // USE_WS2812 diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino index a075a2e8d..38bbf9aa6 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino @@ -31,6 +31,9 @@ extern "C" { #ifdef USE_MATTER_DEVICE #include "berry_matter.h" #endif +#ifdef USE_WS2812 + #include "berry_animate.h" +#endif #include "be_vm.h" #include "ZipReadFS.h" #include "ccronexpr.h" From bb1e3cac97e6caf7d8cea92ca69f1eb706168ab8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 25 Dec 2023 11:41:51 +0100 Subject: [PATCH 045/303] Fix typo in Berry solidify GH actions --- .github/workflows/Tasmota_build_devel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml index 48fc99fa4..9d660b3a1 100644 --- a/.github/workflows/Tasmota_build_devel.yml +++ b/.github/workflows/Tasmota_build_devel.yml @@ -67,7 +67,7 @@ jobs: name: | berry_tasmota berry_matter - berrt_animate + berry_animate berry_lvgl berry_header path: | From d39896f6a2ff217dee649b9154bb52ebddc2c61d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?DUPONCHEEL=20S=C3=A9bastien?= Date: Mon, 25 Dec 2023 12:42:20 +0100 Subject: [PATCH 046/303] HDMI CEC: Allow TV device type emulation. (#20310) The previous check set device type default when HDMIType was set to CEC_Device::CDT_TV. --- tasmota/tasmota_xdrv_driver/xdrv_70_1_hdmi_cec.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_70_1_hdmi_cec.ino b/tasmota/tasmota_xdrv_driver/xdrv_70_1_hdmi_cec.ino index 4a1daf136..deb7c9776 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_70_1_hdmi_cec.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_70_1_hdmi_cec.ino @@ -65,7 +65,7 @@ void HdmiCecInit(void) { // CEC device type CEC_Device::CEC_DEVICE_TYPE device_type = (CEC_Device::CEC_DEVICE_TYPE) Settings->hdmi_cec_device_type; - if (device_type == CEC_Device::CDT_TV || device_type >= CEC_Device::CDT_LAST) { + if (device_type < 0 || device_type >= CEC_Device::CDT_LAST) { // if type in Settings is invalid, default to PLAYBACK_DEVICE device_type = CEC_Device::CDT_PLAYBACK_DEVICE; Settings->hdmi_cec_device_type = (uint8_t) device_type; From 77a58a3642f151fa4d49882ea5db7ff63df87260 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 25 Dec 2023 14:18:59 +0100 Subject: [PATCH 047/303] Fix domoticz topic edge case --- CHANGELOG.md | 2 +- .../tasmota_xdrv_driver/xdrv_07_domoticz.ino | 36 ++++++++++++++----- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 828a099c7..da65a65c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ All notable changes to this project will be documented in this file. ### Changed - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` (#20260) -- Moved Berry animate to its own `berry_animate` lib +- Moved Berry animate to its own `berry_animate` lib (#20309) ### Fixed - Matter Contact sensor was not triggering any update (#20232) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino b/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino index 2994eeafc..99e45cfce 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino @@ -18,10 +18,29 @@ */ #ifdef USE_DOMOTICZ +/*********************************************************************************************\ + * Domoticz support + * + * Adds commands: + * DzIdx - Set power number to Domoticz Idx allowing Domoticz to control Tasmota power + * DzKeyIdx - Set button number to Domoticz Idx allowing Tasmota button as input to Domoticz + * DzSwitchId - Set switch number to Domoticz Idx allowing Tasmota switch as input to Domoticz + * DzSensorIdx - Set sensor type to Domoticz Idx + * DzUpdateTimer 0 - Send power state at teleperiod to Domoticz (default) + * DzUpdateTimer - Send power state at interval to Domoticz + * DzSend1 , - {\"idx\":,\"nvalue\":0,\"svalue\":\"\",\"Battery\":xx,\"RSSI\":yy} + * Example: rule1 on power1#state do dzsend1 9001,%value% endon + * DzSend1 418,%var1%;%var2% or DzSend1 418,%var1%:%var2% - Notice colon as substitute to semi-colon + * DzSend2 , - USE_SHUTTER only - {\"idx\":,\"nvalue\":,\"svalue\":\"\",\"Battery\":xx,\"RSSI\":yy} + * DzSend3 , - {\"idx\":,\"nvalue\":,\"Battery\":xx,\"RSSI\":yy} + * DzSend4 , - {\"command\":\"switchlight\",\"idx\":,\"switchcmd\":\"\"} + * DzSend5 , - {\"command\":\"switchscene\",\"idx\":,\"switchcmd\":\"\"} +\*********************************************************************************************/ #define XDRV_07 7 -//#define D_PRFX_DOMOTICZ "Domoticz" +//#define USE_DOMOTICZ_DEBUG // Enable additional debug logging + #define D_PRFX_DOMOTICZ "Dz" #define D_CMND_IDX "Idx" #define D_CMND_KEYIDX "KeyIdx" @@ -218,16 +237,17 @@ bool DomoticzMqttData(void) { return true; // No valid data } -// char dom_data[XdrvMailbox.data_len +1]; -// strcpy(dom_data, XdrvMailbox.data); -// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "Topic '%s', Data '%s'"), XdrvMailbox.topic, RemoveControlCharacter(dom_data)); +#ifdef USE_DOMOTICZ_DEBUG + char dom_data[XdrvMailbox.data_len +1]; + strcpy(dom_data, XdrvMailbox.data); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "%s = %s"), XdrvMailbox.topic, RemoveControlCharacter(dom_data)); +#endif // USE_DOMOTICZ_DEBUG // Quick check if this is mine using topic domoticz/out/{$idx} if (strlen(XdrvMailbox.topic) > strlen(DOMOTICZ_OUT_TOPIC)) { char* topic_index = &XdrvMailbox.topic[strlen(DOMOTICZ_OUT_TOPIC) +1]; - int32_t top_index = atoi(topic_index); // 0 if no number (in case of domoticz/out/floor/room) - if (top_index > 0) { - if (DomoticzIdx2Relay(top_index) < 0) { + if (strchr(topic_index, '/') == nullptr) { // Skip if topic ...floor/room + if (DomoticzIdx2Relay(atoi(topic_index)) < 0) { return true; // Idx not mine } } @@ -248,7 +268,7 @@ bool DomoticzMqttData(void) { return true; // Nvalue out of boundaries } - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "Topic %s, idx %d, nvalue %d"), XdrvMailbox.topic, Settings->domoticz_relay_idx[relay_index], nvalue); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "%s, idx %d, nvalue %d"), XdrvMailbox.topic, Settings->domoticz_relay_idx[relay_index], nvalue); bool iscolordimmer = (strcmp_P(domoticz.getStr(PSTR("dtype")), PSTR("Color Switch")) == 0); bool isShutter = (strcmp_P(domoticz.getStr(PSTR("dtype")), PSTR("Light/Switch")) == 0) && (strncmp_P(domoticz.getStr(PSTR("switchType")),PSTR("Blinds"), 6) == 0); From 341545362076c531fc7ee8d435a7a11aff8eb759 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Tue, 26 Dec 2023 12:29:50 +0100 Subject: [PATCH 048/303] Berry Improve error message when constructor returns NULL (#20314) --- lib/libesp32/berry_mapping/src/be_class_wrapper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libesp32/berry_mapping/src/be_class_wrapper.c b/lib/libesp32/berry_mapping/src/be_class_wrapper.c index 94cbb9f51..a1abc23ee 100644 --- a/lib/libesp32/berry_mapping/src/be_class_wrapper.c +++ b/lib/libesp32/berry_mapping/src/be_class_wrapper.c @@ -399,7 +399,7 @@ int be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_type, i // `+` forbids any NULL value (raises an exception) while `=` allows a NULL value static void be_set_ctor_ptr(bvm *vm, void * ptr, const char *name) { if (name == NULL) return; // do nothing if no name of attribute - if (name[0] == '+' && ptr == NULL) { be_raise(vm, "value_error", "argument cannot be NULL"); } + if (name[0] == '+' && ptr == NULL) { be_raise(vm, "value_error", "native constructor cannot return NULL"); } if (name[0] == '+' || name[0] == '=') { name++; } // skip prefix '^' if any if (strlen(name) == 0) return; // do nothing if name is empty From b7b83eaaaad487aa66a8b1eeadb645da49aac7fd Mon Sep 17 00:00:00 2001 From: smhc Date: Tue, 26 Dec 2023 21:41:55 +1000 Subject: [PATCH 049/303] Only reduce sleep for lights if necessary (#20146) Co-authored-by: Shane Hird --- tasmota/tasmota_xdrv_driver/xdrv_04_light.ino | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino b/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino index 127e036c3..e52f31783 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino @@ -1777,9 +1777,10 @@ void LightAnimate(void) // make sure we update CT range in case SetOption82 was changed Light.strip_timer_counter++; - // set sleep parameter: either settings, - // or set a maximum of PWM_MAX_SLEEP if light is on or Fade is running - if (Light.power || Light.fade_running) { + // Set a maximum sleep of PWM_MAX_SLEEP if Fade is running, or if light is on and + // a frequently updating light scheme is in use. This is to allow smooth transitions + // between light levels and colors. + if ((Settings->light_scheme > LS_POWER && Light.power) || Light.fade_running) { if (TasmotaGlobal.sleep > PWM_MAX_SLEEP) { sleep_previous = TasmotaGlobal.sleep; // save previous value of sleep TasmotaGlobal.sleep = PWM_MAX_SLEEP; // set a maximum value (in milliseconds) to sleep to ensure that animations are smooth From c744612a29084b13f7fb350665980c1e727e842a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 26 Dec 2023 14:22:47 +0100 Subject: [PATCH 050/303] Fix scripter buffer overflow (#20303) --- tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino index 98a9c352f..6e8f41d3c 100755 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino @@ -9349,8 +9349,10 @@ bool Script_SubCmd(void) { cp += tlen; if (XdrvMailbox.data_len > 0) { *cp++ = '('; - strncpy(cp, XdrvMailbox.data,XdrvMailbox.data_len); - cp += XdrvMailbox.data_len; + uint32_t max_space = sizeof(cmdbuff) - tlen - 4; // 4 = #()0 + uint32_t max_len = min(XdrvMailbox.data_len, max_space); + strncpy(cp, XdrvMailbox.data, max_len); + cp += max_len; *cp++ = ')'; *cp = 0; } From 84fb3879c7d17431cb732f371a32054bb291e0b9 Mon Sep 17 00:00:00 2001 From: hk2k2 <70974088+hk2k2@users.noreply.github.com> Date: Wed, 27 Dec 2023 09:27:16 +0100 Subject: [PATCH 051/303] Update xdsp_15_tm1637.ino (#20317) Displaydimmer command has not worked correctly on 2 daisy-Chained MAX7219 7-Segment Displays. Only the first Module (8 Segments) changed their brightness. --- tasmota/tasmota_xdsp_display/xdsp_15_tm1637.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/tasmota_xdsp_display/xdsp_15_tm1637.ino b/tasmota/tasmota_xdsp_display/xdsp_15_tm1637.ino index b4599132c..4d43d23ff 100644 --- a/tasmota/tasmota_xdsp_display/xdsp_15_tm1637.ino +++ b/tasmota/tasmota_xdsp_display/xdsp_15_tm1637.ino @@ -1131,7 +1131,7 @@ void TM1637Dim(void) { for (uint8_t dev_addr = 0; dev_addr < Settings->display_width / 8; dev_addr++) { - max7219display->setIntensity(MAX7219_ADDR, brightness); // 0 - 7 + max7219display->setIntensity(MAX7219_ADDR + dev_addr, brightness); // 0 - 7 } } } From 13a9c3b5b23f5075de419138b0c2b114854e349f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 27 Dec 2023 17:29:03 +0100 Subject: [PATCH 052/303] Add delays to wifi init code Add delays to wifi init code to fix some edge power cases. --- tasmota/tasmota_support/support_wifi.ino | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tasmota/tasmota_support/support_wifi.ino b/tasmota/tasmota_support/support_wifi.ino index 348266166..c76a278a1 100644 --- a/tasmota/tasmota_support/support_wifi.ino +++ b/tasmota/tasmota_support/support_wifi.ino @@ -102,6 +102,7 @@ void WifiConfig(uint8_t type) UdpDisconnect(); #endif // USE_EMULATION WiFi.disconnect(); // Solve possible Wifi hangs + delay(100); Wifi.config_type = type; #ifndef USE_WEBSERVER @@ -146,7 +147,6 @@ void WifiSetMode(WiFiMode_t wifi_mode) { // See: https://github.com/esp8266/Arduino/issues/6172#issuecomment-500457407 WiFi.forceSleepWake(); // Make sure WiFi is really active. - delay(100); } uint32_t retry = 2; @@ -158,10 +158,8 @@ void WifiSetMode(WiFiMode_t wifi_mode) { if (wifi_mode == WIFI_OFF) { delay(1000); WiFi.forceSleepBegin(); - delay(1); - } else { - delay(30); // Must allow for some time to init. } + delay(100); // Must allow for some time to init. } void WiFiSetSleepMode(void) @@ -201,6 +199,7 @@ void WiFiSetSleepMode(void) WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Sleep (Esp8288/Arduino core and sdk default) } } + delay(100); } void WifiBegin(uint8_t flag, uint8_t channel) { @@ -215,15 +214,13 @@ void WifiBegin(uint8_t flag, uint8_t channel) { #ifdef USE_WIFI_RANGE_EXTENDER if (WiFi.getMode() != WIFI_AP_STA || !RgxApUp()) { // Preserve range extender connections (#17103) - WiFi.disconnect(true); // Delete SDK wifi config - delay(200); - WifiSetMode(WIFI_STA); // Disable AP mode - } -#else - WiFi.disconnect(true); // Delete SDK wifi config +#endif // USE_WIFI_RANGE_EXTENDER + WiFi.disconnect(true); // Delete SDK wifi config delay(200); - WifiSetMode(WIFI_STA); // Disable AP mode -#endif + WifiSetMode(WIFI_STA); // Disable AP mode +#ifdef USE_WIFI_RANGE_EXTENDER + } +#endif // USE_WIFI_RANGE_EXTENDER WiFiSetSleepMode(); WifiSetOutputPower(); @@ -261,6 +258,7 @@ void WifiBegin(uint8_t flag, uint8_t channel) { } else { WiFi.begin(SettingsText(SET_STASSID1 + Settings->sta_active), SettingsText(SET_STAPWD1 + Settings->sta_active)); } + delay(500); AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s%s " D_IN_MODE " 11%c " D_AS " %s..."), Settings->sta_active +1, SettingsText(SET_STASSID1 + Settings->sta_active), stemp, pgm_read_byte(&kWifiPhyMode[WiFi.getPhyMode() & 0x3]), TasmotaGlobal.hostname); @@ -804,6 +802,9 @@ bool HasIP(void) { } void WifiCheckIp(void) { + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_WIFI D_CHECKING_CONNECTION)); + Wifi.counter = WIFI_CHECK_SEC; + #ifdef USE_IPV6 if (WL_CONNECTED == WiFi.status()) { #ifdef ESP32 @@ -939,8 +940,6 @@ void WifiCheck(uint8_t param) } } else { if (Wifi.counter <= 0) { - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_WIFI D_CHECKING_CONNECTION)); - Wifi.counter = WIFI_CHECK_SEC; WifiCheckIp(); } if ((WL_CONNECTED == WiFi.status()) && WifiHasIP() && !Wifi.config_type) { @@ -978,6 +977,7 @@ float WifiGetOutputPower(void) { void WifiSetOutputPower(void) { if (Settings->wifi_output_power) { WiFi.setOutputPower((float)(Settings->wifi_output_power) / 10); + delay(100); } else { AddLog(LOG_LEVEL_DEBUG, PSTR("WIF: Dynamic Tx power enabled")); // WifiPower 0 } From 21c7edcb50daa890a8f642c2a9c8171d7cb794d3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 27 Dec 2023 22:03:56 +0100 Subject: [PATCH 053/303] Add display of active drivers using command ``status 4`` --- CHANGELOG.md | 1 + RELEASENOTES.md | 1 + tasmota/include/tasmota.h | 2 +- tasmota/tasmota.ino | 2 + .../xdrv_01_9_webserver.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_02_9_mqtt.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_03_energy.ino | 3 ++ .../xdrv_03_esp32_energy.ino | 3 ++ tasmota/tasmota_xdrv_driver/xdrv_04_light.ino | 23 +++++---- .../tasmota_xdrv_driver/xdrv_05_irremote.ino | 3 ++ .../xdrv_05_irremote_full.ino | 5 ++ .../tasmota_xdrv_driver/xdrv_06_snfbridge.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_07_domoticz.ino | 3 ++ .../xdrv_08_serial_bridge.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_09_timers.ino | 3 ++ tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_10_scripter.ino | 4 ++ tasmota/tasmota_xdrv_driver/xdrv_11_knx.ino | 3 ++ .../xdrv_122_file_settings_demo.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_127_debug.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_12_discovery.ino | 3 ++ .../xdrv_12_home_assistant.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_13_display.ino | 3 ++ tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino | 4 ++ .../tasmota_xdrv_driver/xdrv_15_pca9685.ino | 3 ++ .../xdrv_15_pca9685_v2.ino | 3 ++ .../xdrv_16_tuyamcu_v1.ino | 3 ++ .../xdrv_16_tuyamcu_v2.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_17_rcswitch.ino | 3 ++ .../xdrv_18_armtronix_dimmers.ino | 3 ++ .../xdrv_19_ps16dz_dimmer.ino | 3 ++ tasmota/tasmota_xdrv_driver/xdrv_20_hue.ino | 3 ++ tasmota/tasmota_xdrv_driver/xdrv_21_wemo.ino | 3 ++ .../xdrv_21_wemo_multi.ino | 3 ++ .../xdrv_22_sonoff_ifan.ino | 3 ++ .../xdrv_23_zigbee_A_impl.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_24_buzzer.ino | 3 ++ .../xdrv_25_A4988_Stepper.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_26_ariluxrf.ino | 3 ++ .../xdrv_27_esp32_shutter.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_27_shutter.ino | 3 ++ .../xdrv_28_pcf8574_v2.ino | 6 +++ .../tasmota_xdrv_driver/xdrv_29_deepsleep.ino | 3 ++ .../xdrv_30_exs_dimmer.ino | 3 ++ .../xdrv_31_tasmota_client.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_32_hotplug.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_33_nrf24l01.ino | 4 ++ .../xdrv_34_wemos_motor_v1.ino | 3 ++ .../xdrv_35_pwm_dimmer.ino | 4 ++ .../tasmota_xdrv_driver/xdrv_36_keeloq.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_37_sonoff_d1.ino | 3 ++ tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino | 11 ++-- .../xdrv_39_thermostat.ino | 4 ++ .../tasmota_xdrv_driver/xdrv_40_telegram.ino | 3 ++ .../xdrv_41_tcp_bridge.ino | 3 ++ .../xdrv_42_0_i2s_audio.ino | 4 ++ .../tasmota_xdrv_driver/xdrv_43_mlx90640.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_44_miel_hvac.ino | 4 ++ .../xdrv_45_shelly_dimmer.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_46_ccloader.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_47_ftc532.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_48_timeprop.ino | 3 ++ tasmota/tasmota_xdrv_driver/xdrv_49_pid.ino | 3 ++ .../xdrv_50_filesystem.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_51_bs814a2.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_52_9_berry.ino | 3 ++ .../xdrv_53_projector_ctrl.ino | 4 ++ tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino | 4 ++ tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_56_rtc_chips.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_57_9_tasmesh.ino | 3 ++ .../xdrv_58_range_extender.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_59_influxdb.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_60_shift595.ino | 21 ++++---- .../tasmota_xdrv_driver/xdrv_61_ds3502.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_62_improv.ino | 3 ++ .../xdrv_63_modbus_bridge.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_64_pca9632.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_65_tuyamcubr.ino | 4 ++ .../tasmota_xdrv_driver/xdrv_66_tm1638.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_67_mcp23xxx.ino | 3 ++ .../xdrv_68_zerocrossDimmer.ino | 3 ++ .../tasmota_xdrv_driver/xdrv_69_pca9557.ino | 3 ++ .../xdrv_70_1_hdmi_cec.ino | 26 +++++----- .../tasmota_xdrv_driver/xdrv_79_esp32_ble.ino | 3 ++ .../xdrv_81_esp32_webcam.ino | 3 ++ .../xdrv_81_esp32_webcam_task.ino | 3 ++ .../xdrv_82_esp32_ethernet.ino | 3 ++ .../xdrv_83_esp32_watch.ino | 3 ++ .../xdrv_85_esp32_ble_eq3_trv.ino | 3 ++ .../xdrv_86_esp32_sonoff_spm.ino | 3 ++ .../xdrv_87_esp32_sonoff_tm1621.ino | 3 ++ .../xdrv_88_esp32_shelly_pro.ino | 39 +++++++------- .../xdrv_88_esp32_shelly_pro_v1.ino | 33 ++++++------ .../xdrv_88_esp32_shelly_pro_v2.ino | 51 ++++++++++--------- .../xdrv_89_esp32_dali.ino | 3 ++ .../xdrv_90_esp32_dingtian_relay.ino | 3 ++ .../xdrv_91_magic_switch.ino | 3 ++ .../tasmota_xx2c_global/xdrv_interface.ino | 11 +++- .../tasmota_xx2c_global/xsns_interface.ino | 4 ++ 100 files changed, 406 insertions(+), 95 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da65a65c0..722216896 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file. - Support for CST816S touch interface (#20213) - NeoPool hydrolysis FL1 and Redox flag (#20258) - Matter support for password for remote Tasmota devices (#20296) +- Display of active drivers using command ``status 4`` ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds (#20236) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index dba6bb153..1dfa0a653 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -120,6 +120,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ### Added - Support for CST816S touch interface [#20213](https://github.com/arendst/Tasmota/issues/20213) - Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247) +- Display of active drivers using command ``status 4`` - NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) diff --git a/tasmota/include/tasmota.h b/tasmota/include/tasmota.h index d6ff4b2b7..1feca3fef 100644 --- a/tasmota/include/tasmota.h +++ b/tasmota/include/tasmota.h @@ -423,7 +423,7 @@ enum LightSubtypes { LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LS enum LightTypes { LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, LT_NU8, LT_SERIAL1, LT_SERIAL2, LT_RGB, LT_RGBW, LT_RGBWC, LT_NU14, LT_NU15 }; // Do not insert new fields -enum XsnsFunctions { FUNC_SETTINGS_OVERRIDE, FUNC_SETUP_RING1, FUNC_SETUP_RING2, FUNC_PRE_INIT, FUNC_INIT, +enum XsnsFunctions { FUNC_SETTINGS_OVERRIDE, FUNC_SETUP_RING1, FUNC_SETUP_RING2, FUNC_PRE_INIT, FUNC_INIT, FUNC_ACTIVE, FUNC_LOOP, FUNC_SLEEP_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_RESET_SETTINGS, FUNC_RESTORE_SETTINGS, FUNC_SAVE_SETTINGS, FUNC_SAVE_AT_MIDNIGHT, FUNC_SAVE_BEFORE_RESTART, FUNC_INTERRUPT_STOP, FUNC_INTERRUPT_START, FUNC_AFTER_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_SENSOR, FUNC_WEB_COL_SENSOR, diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 1cf661f04..7febc7a3b 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -775,6 +775,8 @@ void setup(void) { if (bitRead(Settings->rule_enabled, 0)) Run_Scripter(">BS",3,0); #endif + XdrvCall(FUNC_ACTIVE); // FUNC_ACTIVE + TasmotaGlobal.rules_flag.system_init = 1; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino index df267b533..20ce791f0 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino @@ -3894,6 +3894,9 @@ bool Xdrv01(uint32_t function) case FUNC_COMMAND: result = DecodeCommand(kWebCommands, WebCommand); break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino b/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino index 7312135e8..047a9eb5f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino @@ -2033,6 +2033,9 @@ bool Xdrv02(uint32_t function) case FUNC_PRE_INIT: MqttInit(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino index fa58c4725..66bf50acd 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino @@ -1497,6 +1497,9 @@ bool Xdrv03(uint32_t function) case FUNC_NETWORK_DOWN: XnrgCall(FUNC_NETWORK_DOWN); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino index a4bb1c615..228e8b9de 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino @@ -1799,6 +1799,9 @@ bool Xdrv03(uint32_t function) case FUNC_NETWORK_DOWN: XnrgCall(FUNC_NETWORK_DOWN); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino b/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino index e52f31783..14799f208 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino @@ -3460,17 +3460,20 @@ bool Xdrv04(uint32_t function) LightInit(); break; #ifdef USE_LIGHT_ARTNET - case FUNC_JSON_APPEND: - ArtNetJSONAppend(); - break; - case FUNC_NETWORK_UP: - ArtNetFuncNetworkUp(); - break; - case FUNC_NETWORK_DOWN: - ArtNetFuncNetworkDown(); - break; + case FUNC_JSON_APPEND: + ArtNetJSONAppend(); + break; + case FUNC_NETWORK_UP: + ArtNetFuncNetworkUp(); + break; + case FUNC_NETWORK_DOWN: + ArtNetFuncNetworkDown(); + break; #endif // USE_LIGHT_ARTNET - } + case FUNC_ACTIVE: + result = true; + break; + } } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_05_irremote.ino b/tasmota/tasmota_xdrv_driver/xdrv_05_irremote.ino index 0996484b5..271a34b9d 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_05_irremote.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_05_irremote.ino @@ -444,6 +444,9 @@ bool Xdrv05(uint32_t function) result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); } break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_05_irremote_full.ino b/tasmota/tasmota_xdrv_driver/xdrv_05_irremote_full.ino index 98f45373e..5115903ab 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_05_irremote_full.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_05_irremote_full.ino @@ -916,6 +916,11 @@ bool Xdrv05(uint32_t function) result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); } break; + case FUNC_ACTIVE: + if (ir_recv_active || ir_recv_active) { + result = true; + } + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_06_snfbridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_06_snfbridge.ino index 2b9988ec6..8bcb3e41e 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_06_snfbridge.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_06_snfbridge.ino @@ -566,6 +566,9 @@ bool Xdrv06(uint32_t function) case FUNC_PRE_INIT: SetSerial(19200, TS_SERIAL_8N1); break; + case FUNC_ACTIVE: + result = true; + break; } } #endif // ESP8266 diff --git a/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino b/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino index 99e45cfce..4d4c54102 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino @@ -699,6 +699,9 @@ bool Xdrv07(uint32_t function) { case FUNC_COMMAND: result = DecodeCommand(kDomoticzCommands, DomoticzCommand); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_08_serial_bridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_08_serial_bridge.ino index bcb38fc90..c3d432808 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_08_serial_bridge.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_08_serial_bridge.ino @@ -336,6 +336,9 @@ bool Xdrv08(uint32_t function) { case FUNC_COMMAND: result = DecodeCommand(kSerialBridgeCommands, SerialBridgeCommand); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_09_timers.ino b/tasmota/tasmota_xdrv_driver/xdrv_09_timers.ino index 14026806f..fa96bf3c3 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_09_timers.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_09_timers.ino @@ -979,6 +979,9 @@ bool Xdrv09(uint32_t function) case FUNC_COMMAND: result = DecodeCommand(kTimerCommands, TimerCommand); break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino index 945c9b8c2..13389b082 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino @@ -2504,6 +2504,9 @@ bool Xdrv10(uint32_t function) case FUNC_PRE_INIT: RulesInit(); break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino index 6e8f41d3c..63730602f 100755 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino @@ -13039,6 +13039,10 @@ bool Xdrv10(uint32_t function) case FUNC_NETWORK_UP: break; + + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_11_knx.ino b/tasmota/tasmota_xdrv_driver/xdrv_11_knx.ino index 719eea482..67fa26f49 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_11_knx.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_11_knx.ino @@ -1342,6 +1342,9 @@ bool Xdrv11(uint32_t function) break; // case FUNC_SET_POWER: // break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_122_file_settings_demo.ino b/tasmota/tasmota_xdrv_driver/xdrv_122_file_settings_demo.ino index 0e1dd13f3..7680df760 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_122_file_settings_demo.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_122_file_settings_demo.ino @@ -188,6 +188,9 @@ bool Xdrv122(uint32_t function) { case FUNC_SAVE_BEFORE_RESTART: // !!! DO NOT USE AS IT'S FUNCTION IS BETTER HANDLED BY FUNC_SAVE_SETTINGS !!! break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_127_debug.ino b/tasmota/tasmota_xdrv_driver/xdrv_127_debug.ino index fd4e99cf7..35d3a9ace 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_127_debug.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_127_debug.ino @@ -812,6 +812,9 @@ bool Xdrv127(uint32_t function) case FUNC_COMMAND: result = DecodeCommand(kDebugCommands, DebugCommand); break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_12_discovery.ino b/tasmota/tasmota_xdrv_driver/xdrv_12_discovery.ino index f71a19b8d..07e963088 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_12_discovery.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_12_discovery.ino @@ -328,6 +328,9 @@ bool Xdrv12(uint32_t function) { case FUNC_MQTT_INIT: TasDiscoverInit(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_12_home_assistant.ino b/tasmota/tasmota_xdrv_driver/xdrv_12_home_assistant.ino index 3b6378694..a58983ec2 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_12_home_assistant.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_12_home_assistant.ino @@ -1321,6 +1321,9 @@ bool Xdrv12(uint32_t function) case FUNC_MQTT_DATA: result = HAssMqttLWT(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino b/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino index 47bfd7c62..18a387e41 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino @@ -2939,6 +2939,9 @@ bool Xdrv13(uint32_t function) case FUNC_COMMAND: result = DecodeCommand(kDisplayCommands, DisplayCommand); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino b/tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino index 625f0359c..82582b5c5 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino @@ -414,6 +414,10 @@ bool Xdrv14(uint32_t function) case FUNC_EVERY_SECOND: MP3_EVERY_SECOND(); break; + + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_15_pca9685.ino b/tasmota/tasmota_xdrv_driver/xdrv_15_pca9685.ino index 8f82432c2..c9c980f9f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_15_pca9685.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_15_pca9685.ino @@ -228,6 +228,9 @@ bool Xdrv15(uint32_t function) result = PCA9685_Command(); } break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_15_pca9685_v2.ino b/tasmota/tasmota_xdrv_driver/xdrv_15_pca9685_v2.ino index 75ff7dd08..5ba364e30 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_15_pca9685_v2.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_15_pca9685_v2.ino @@ -613,6 +613,9 @@ bool Xdrv15(uint32_t function) result = PCA9685_Command(); } break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino index 1c0e29315..cb7184922 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino @@ -1725,6 +1725,9 @@ bool Xdrv16(uint32_t function) { TuyaSensorsShow(0); break; #endif // USE_WEBSERVER + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino index c3fc0b395..c9c0908e0 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino @@ -2575,6 +2575,9 @@ bool Xdrv16(uint32_t function) { TuyaSensorsShow(0); break; #endif // USE_WEBSERVER + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_17_rcswitch.ino b/tasmota/tasmota_xdrv_driver/xdrv_17_rcswitch.ino index 05c28fa07..51b868634 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_17_rcswitch.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_17_rcswitch.ino @@ -246,6 +246,9 @@ bool Xdrv17(uint32_t function) case FUNC_INIT: RfInit(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_18_armtronix_dimmers.ino b/tasmota/tasmota_xdrv_driver/xdrv_18_armtronix_dimmers.ino index e070e5d82..c512fdc3c 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_18_armtronix_dimmers.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_18_armtronix_dimmers.ino @@ -190,6 +190,9 @@ bool Xdrv18(uint32_t function) case FUNC_SET_CHANNELS: result = ArmtronixSetChannels(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_19_ps16dz_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_19_ps16dz_dimmer.ino index 69d0a69c0..a7c513bd7 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_19_ps16dz_dimmer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_19_ps16dz_dimmer.ino @@ -225,6 +225,9 @@ bool Xdrv19(uint32_t function) case FUNC_MODULE_INIT: result = PS16DZModuleSelected(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_20_hue.ino b/tasmota/tasmota_xdrv_driver/xdrv_20_hue.ino index 74611fa78..3fae7ed2f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_20_hue.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_20_hue.ino @@ -1168,6 +1168,9 @@ bool Xdrv20(uint32_t function) case FUNC_NETWORK_DOWN: UdpDisconnect(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_21_wemo.ino b/tasmota/tasmota_xdrv_driver/xdrv_21_wemo.ino index f3fa8ab92..a2fd187c7 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_21_wemo.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_21_wemo.ino @@ -366,6 +366,9 @@ bool Xdrv21(uint32_t function) case FUNC_NETWORK_DOWN: UdpDisconnect(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_21_wemo_multi.ino b/tasmota/tasmota_xdrv_driver/xdrv_21_wemo_multi.ino index c6b5f9410..641f9109d 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_21_wemo_multi.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_21_wemo_multi.ino @@ -465,6 +465,9 @@ bool Xdrv21(uint32_t function) case FUNC_NETWORK_DOWN: UdpDisconnect(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_22_sonoff_ifan.ino b/tasmota/tasmota_xdrv_driver/xdrv_22_sonoff_ifan.ino index 6cf5da0c5..13d8cfe24 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_22_sonoff_ifan.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_22_sonoff_ifan.ino @@ -261,6 +261,9 @@ bool Xdrv22(uint32_t function) { case FUNC_MODULE_INIT: result = SonoffIfanInit(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino index 175f7bd6b..341a82c2f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino @@ -2484,6 +2484,9 @@ bool Xdrv23(uint32_t function) { restoreDumpAllDevices(); } break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_24_buzzer.ino b/tasmota/tasmota_xdrv_driver/xdrv_24_buzzer.ino index 9a54076d5..8f4c52b3f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_24_buzzer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_24_buzzer.ino @@ -253,6 +253,9 @@ bool Xdrv24(uint32_t function) { case FUNC_PIN_STATE: result = BuzzerPinState(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_25_A4988_Stepper.ino b/tasmota/tasmota_xdrv_driver/xdrv_25_A4988_Stepper.ino index d72c51545..0d97adae1 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_25_A4988_Stepper.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_25_A4988_Stepper.ino @@ -137,6 +137,9 @@ bool Xdrv25(uint32_t function) case FUNC_COMMAND: result = DecodeCommand(kA4988Commands, A4988Command); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_26_ariluxrf.ino b/tasmota/tasmota_xdrv_driver/xdrv_26_ariluxrf.ino index ede03b44c..cf45edef1 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_26_ariluxrf.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_26_ariluxrf.ino @@ -187,6 +187,9 @@ bool Xdrv26(uint32_t function) case FUNC_INTERRUPT_START: AriluxRfInit(); break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino b/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino index e42402bc2..c40832657 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino @@ -2371,6 +2371,9 @@ bool Xdrv27(uint32_t function) ShutterShow(); break; #endif // USE_WEBSERVER + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino b/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino index a3c926220..b6a11b3bb 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino @@ -1972,6 +1972,9 @@ bool Xdrv27(uint32_t function) ShutterShow(); break; #endif // USE_WEBSERVER + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574_v2.ino b/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574_v2.ino index 6fb855bb4..7c56f460c 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574_v2.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574_v2.ino @@ -720,6 +720,9 @@ bool Xdrv28(uint32_t function) { break; #endif // USE_PCF8574_DISPLAYINPUT #endif // USE_WEBSERVER + case FUNC_ACTIVE: + result = true; + break; } #ifdef USE_PCF8574_MODE2 } else if (2 == Pcf8574.mode) { @@ -747,6 +750,9 @@ bool Xdrv28(uint32_t function) { case FUNC_ADD_SWITCH: result = Pcf8574AddSwitch(); break; + case FUNC_ACTIVE: + result = true; + break; } #endif // USE_PCF8574_MODE2 } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_29_deepsleep.ino b/tasmota/tasmota_xdrv_driver/xdrv_29_deepsleep.ino index bae29c8f1..b64880465 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_29_deepsleep.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_29_deepsleep.ino @@ -332,6 +332,9 @@ bool Xdrv29(uint32_t function) case FUNC_PRE_INIT: DeepSleepReInit(); break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_30_exs_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_30_exs_dimmer.ino index 7579072b3..fed86a93d 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_30_exs_dimmer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_30_exs_dimmer.ino @@ -611,6 +611,9 @@ bool Xdrv30(uint32_t function) result = DecodeCommand(kExsCommands, ExsCommand); break; #endif + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_31_tasmota_client.ino b/tasmota/tasmota_xdrv_driver/xdrv_31_tasmota_client.ino index e4d41988e..345fc9dba 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_31_tasmota_client.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_31_tasmota_client.ino @@ -559,6 +559,9 @@ bool Xdrv31(uint32_t function) { case FUNC_COMMAND: result = DecodeCommand(kTasmotaClientCommands, TasmotaClientCommand); break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_32_hotplug.ino b/tasmota/tasmota_xdrv_driver/xdrv_32_hotplug.ino index d5dba3b3c..6a247e5e5 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_32_hotplug.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_32_hotplug.ino @@ -94,6 +94,9 @@ bool Xdrv32(uint32_t function) case FUNC_PRE_INIT: HotPlugInit(); break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_33_nrf24l01.ino b/tasmota/tasmota_xdrv_driver/xdrv_33_nrf24l01.ino index 83381d203..2289aec23 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_33_nrf24l01.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_33_nrf24l01.ino @@ -85,6 +85,10 @@ bool Xdrv33(uint32_t function) { if (FUNC_INIT == function) { NRF24Detect(); + } else if (NRF24.chipType) { + if (FUNC_ACTIVE == function) { + result = true; + } } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_34_wemos_motor_v1.ino b/tasmota/tasmota_xdrv_driver/xdrv_34_wemos_motor_v1.ino index 4b25b714d..3708f2d82 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_34_wemos_motor_v1.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_34_wemos_motor_v1.ino @@ -284,6 +284,9 @@ bool Xdrv34(uint32_t function) result = WMotorV1Command(); } break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_35_pwm_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_35_pwm_dimmer.ino index 76e9e7bca..d5d2b00d3 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_35_pwm_dimmer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_35_pwm_dimmer.ino @@ -948,6 +948,10 @@ bool Xdrv35(uint32_t function) case FUNC_PRE_INIT: PWMModulePreInit(); break; + + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_36_keeloq.ino b/tasmota/tasmota_xdrv_driver/xdrv_36_keeloq.ino index 13b700920..2487f8495 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_36_keeloq.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_36_keeloq.ino @@ -276,6 +276,9 @@ bool Xdrv36(uint32_t function) KeeloqInit(); DEBUG_DRIVER_LOG(PSTR("KLQ: init done")); break; + case FUNC_ACTIVE: + result = true; + break; } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_37_sonoff_d1.ino b/tasmota/tasmota_xdrv_driver/xdrv_37_sonoff_d1.ino index a727b6080..0e656fc79 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_37_sonoff_d1.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_37_sonoff_d1.ino @@ -191,6 +191,9 @@ bool Xdrv37(uint32_t function) case FUNC_MODULE_INIT: result = SonoffD1ModuleSelected(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino b/tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino index ba7914c5f..77e8c5b6a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino @@ -442,11 +442,14 @@ bool Xdrv38(uint32_t function) switch (function) { case FUNC_EVERY_250_MSECOND: - PingResponsePoll(); // TODO - break; + PingResponsePoll(); // TODO + break; case FUNC_COMMAND: - result = DecodeCommand(kPingCommands, PingCommand); - break; + result = DecodeCommand(kPingCommands, PingCommand); + break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_39_thermostat.ino b/tasmota/tasmota_xdrv_driver/xdrv_39_thermostat.ino index e4ea49af2..3e32ca7dc 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_39_thermostat.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_39_thermostat.ino @@ -2204,6 +2204,10 @@ bool Xdrv39(uint32_t function) case FUNC_COMMAND: result = DecodeCommand(kThermostatCommands, ThermostatCommand); break; + + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_40_telegram.ino b/tasmota/tasmota_xdrv_driver/xdrv_40_telegram.ino index a511cdf2d..fddd5eed3 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_40_telegram.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_40_telegram.ino @@ -487,6 +487,9 @@ bool Xdrv40(uint32_t function) case FUNC_COMMAND: result = DecodeCommand(kTelegramCommands, TelegramCommand); break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_41_tcp_bridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_41_tcp_bridge.ino index 811bbb7ce..55ada143a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_41_tcp_bridge.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_41_tcp_bridge.ino @@ -290,6 +290,9 @@ bool Xdrv41(uint32_t function) case FUNC_COMMAND: result = DecodeCommand(kTCPCommands, TCPCommand); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio.ino index 616465717..c49798fa1 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio.ino @@ -760,6 +760,10 @@ bool Xdrv42(uint32_t function) { I2S_WR_Show(true); break; #endif // USE_I2S_WEBRADIO + + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_43_mlx90640.ino b/tasmota/tasmota_xdrv_driver/xdrv_43_mlx90640.ino index d13dd4416..2d74780b8 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_43_mlx90640.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_43_mlx90640.ino @@ -617,6 +617,9 @@ bool Xdrv43(uint32_t function) case FUNC_COMMAND: result = MLX90640Cmd(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino b/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino index 6c2fd55d4..5b9f19054 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino @@ -1336,6 +1336,10 @@ bool Xdrv44(uint32_t function) { case FUNC_COMMAND: result = DecodeCommand(miel_hvac_cmnd_names, miel_hvac_cmnds); break; + + case FUNC_ACTIVE: + result = true; + break; } return (result); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_45_shelly_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_45_shelly_dimmer.ino index 42ba5df0b..2bd091488 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_45_shelly_dimmer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_45_shelly_dimmer.ino @@ -872,6 +872,9 @@ bool Xdrv45(uint32_t function) { result = DecodeCommand(kShdCommands, ShdCommand); break; #endif // SHELLY_CMDS + case FUNC_ACTIVE: + result = true; + break; } } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_46_ccloader.ino b/tasmota/tasmota_xdrv_driver/xdrv_46_ccloader.ino index ab37d271a..a85275fa7 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_46_ccloader.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_46_ccloader.ino @@ -689,6 +689,9 @@ bool Xdrv46(uint32_t function) { CCLoadershow(0); break; #endif // USE_WEBSERVER + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_47_ftc532.ino b/tasmota/tasmota_xdrv_driver/xdrv_47_ftc532.ino index 220ab6078..c7afd9682 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_47_ftc532.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_47_ftc532.ino @@ -232,6 +232,9 @@ bool Xdrv47(uint32_t function) { ftc532_show(); break; } + case FUNC_ACTIVE: + result = true; + break; } // Return bool result return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_48_timeprop.ino b/tasmota/tasmota_xdrv_driver/xdrv_48_timeprop.ino index d1fc6754a..035bf8869 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_48_timeprop.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_48_timeprop.ino @@ -345,6 +345,9 @@ bool Xdrv48(uint32_t function) { case FUNC_JSON_APPEND: ShowValues(); break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_49_pid.ino b/tasmota/tasmota_xdrv_driver/xdrv_49_pid.ino index 22d86dbf9..40077b306 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_49_pid.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_49_pid.ino @@ -543,6 +543,9 @@ bool Xdrv49(uint32_t function) { PIDShowValuesWeb(); break; #endif // USE_WEBSERVER + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino b/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino index 58240cf2a..1a515bd47 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino @@ -1398,6 +1398,9 @@ bool Xdrv50(uint32_t function) { #endif break; #endif // USE_WEBSERVER + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_51_bs814a2.ino b/tasmota/tasmota_xdrv_driver/xdrv_51_bs814a2.ino index 5199b3919..8cd89310d 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_51_bs814a2.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_51_bs814a2.ino @@ -182,6 +182,9 @@ bool Xdrv51(uint32_t function) { case FUNC_JSON_APPEND: bs814_show(); break; + case FUNC_ACTIVE: + result = true; + break; } } // Return bool result diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino index 38bbf9aa6..70db00be5 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino @@ -969,6 +969,9 @@ bool Xdrv52(uint32_t function) callBerryEventDispatcher(PSTR("button_pressed"), nullptr, 0, nullptr); break; + case FUNC_ACTIVE: + result = true; + break; } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino b/tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino index 999f6a738..801a1ab00 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino @@ -473,6 +473,10 @@ bool Xdrv53(uint32_t function) { result = projector_ctrl_set_power(sc); break; + case FUNC_ACTIVE: + result = true; + break; + } return (result); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino b/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino index 58293139b..9540bf562 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino @@ -471,6 +471,10 @@ bool Xdrv54(uint32_t function) case FUNC_BUTTON_PRESSED: break; + case FUNC_ACTIVE: + result = true; + break; + } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino index 44eca227e..d7738e80a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino @@ -589,6 +589,9 @@ bool Xdrv55(uint32_t function) { Touch_Check(TS_RotConvert); } break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_56_rtc_chips.ino b/tasmota/tasmota_xdrv_driver/xdrv_56_rtc_chips.ino index 1b4e4f598..eacd3a9d2 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_56_rtc_chips.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_56_rtc_chips.ino @@ -518,6 +518,9 @@ bool Xdrv56(uint32_t function) { case FUNC_JSON_APPEND: if (RtcChip.ShowSensor) RtcChip.ShowSensor(1); break; + case FUNC_ACTIVE: + result = true; + break; } } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_57_9_tasmesh.ino b/tasmota/tasmota_xdrv_driver/xdrv_57_9_tasmesh.ino index 6691017af..b6fc08630 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_57_9_tasmesh.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_57_9_tasmesh.ino @@ -855,6 +855,9 @@ bool Xdrv57(uint32_t function) { MESHdeInit(); break; #endif // USE_DEEPSLEEP + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_58_range_extender.ino b/tasmota/tasmota_xdrv_driver/xdrv_58_range_extender.ino index d72880649..73fb3daab 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_58_range_extender.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_58_range_extender.ino @@ -524,6 +524,9 @@ bool Xdrv58(uint32_t function) } } break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_59_influxdb.ino b/tasmota/tasmota_xdrv_driver/xdrv_59_influxdb.ino index d53330e25..c8c6122d9 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_59_influxdb.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_59_influxdb.ino @@ -626,6 +626,9 @@ bool Xdrv59(uint32_t function) { case FUNC_EVERY_SECOND: InfluxDbLoop(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_60_shift595.ino b/tasmota/tasmota_xdrv_driver/xdrv_60_shift595.ino index f477fc8ff..809ec86ac 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_60_shift595.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_60_shift595.ino @@ -104,16 +104,19 @@ bool Xdrv60(uint32_t function) { if (FUNC_PRE_INIT == function) { Shift595Init(); - } else if (Shift595) { - switch (function) { - case FUNC_SET_POWER: - Shift595SwitchRelay(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kShift595Commands, Shift595Command); - break; - } + } else if (Shift595) { + switch (function) { + case FUNC_SET_POWER: + Shift595SwitchRelay(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kShift595Commands, Shift595Command); + break; + case FUNC_ACTIVE: + result = true; + break; } + } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_61_ds3502.ino b/tasmota/tasmota_xdrv_driver/xdrv_61_ds3502.ino index 0b158bdef..537885495 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_61_ds3502.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_61_ds3502.ino @@ -86,6 +86,9 @@ bool Xdrv61(uint32_t function) { case FUNC_COMMAND: result = DecodeCommand(kDS3502Commands, DS3502Command); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_62_improv.ino b/tasmota/tasmota_xdrv_driver/xdrv_62_improv.ino index 4b3a15154..f68954b1a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_62_improv.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_62_improv.ino @@ -353,6 +353,9 @@ bool Xdrv62(uint32_t function) { case FUNC_PRE_INIT: ImprovInit(); break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino index c93be3cb5..c8f3fa109 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino @@ -1169,6 +1169,9 @@ bool Xdrv63(uint32_t function) case FUNC_COMMAND: result = DecodeCommand(kModbusBridgeCommands, ModbusBridgeCommand); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_64_pca9632.ino b/tasmota/tasmota_xdrv_driver/xdrv_64_pca9632.ino index 7c36c6ab3..591495010 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_64_pca9632.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_64_pca9632.ino @@ -266,6 +266,9 @@ bool Xdrv64(uint32_t function) { result = PCA9632_Command(); } break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_65_tuyamcubr.ino b/tasmota/tasmota_xdrv_driver/xdrv_65_tuyamcubr.ino index d5d4b0ac8..caa1cefd3 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_65_tuyamcubr.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_65_tuyamcubr.ino @@ -1110,6 +1110,10 @@ Xdrv65(uint32_t function) case FUNC_COMMAND: result = DecodeCommand(tuyamcubr_cmnd_names, tuyamcubr_cmnds); break; + + case FUNC_ACTIVE: + result = true; + break; } return (result); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_66_tm1638.ino b/tasmota/tasmota_xdrv_driver/xdrv_66_tm1638.ino index e7d5f5a63..f93073411 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_66_tm1638.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_66_tm1638.ino @@ -232,6 +232,9 @@ bool Xdrv66(uint32_t function) { #endif result = TmAddKey(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_67_mcp23xxx.ino b/tasmota/tasmota_xdrv_driver/xdrv_67_mcp23xxx.ino index 1186bf5db..82aea1edb 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_67_mcp23xxx.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_67_mcp23xxx.ino @@ -834,6 +834,9 @@ bool Xdrv67(uint32_t function) { case FUNC_ADD_SWITCH: result = MCP23xAddSwitch(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_68_zerocrossDimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_68_zerocrossDimmer.ino index 49f6f9cfb..da7fc794e 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_68_zerocrossDimmer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_68_zerocrossDimmer.ino @@ -316,6 +316,9 @@ bool Xdrv68(uint32_t function) break; #endif // ZCDIMMERSET_SHOW #endif // USE_WEBSERVER + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_69_pca9557.ino b/tasmota/tasmota_xdrv_driver/xdrv_69_pca9557.ino index 190fb0e34..9ee9c1c87 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_69_pca9557.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_69_pca9557.ino @@ -527,6 +527,9 @@ bool Xdrv69(uint32_t function) { case FUNC_ADD_SWITCH: result = PCA9557AddSwitch(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_70_1_hdmi_cec.ino b/tasmota/tasmota_xdrv_driver/xdrv_70_1_hdmi_cec.ino index deb7c9776..981829691 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_70_1_hdmi_cec.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_70_1_hdmi_cec.ino @@ -302,21 +302,21 @@ bool Xdrv70(uint32_t function) { bool result = false; - switch (function) { - case FUNC_INIT: - HdmiCecInit(); - break; - case FUNC_LOOP: - case FUNC_SLEEP_LOOP: - if (HDMI_CEC_device) { + if (FUNC_INIT == function) { + HdmiCecInit(); + } else if (HDMI_CEC_device) { + switch (function) { + case FUNC_LOOP: + case FUNC_SLEEP_LOOP: HDMI_CEC_device->run(); - } - break; - case FUNC_COMMAND: - if (HDMI_CEC_device) { + break; + case FUNC_COMMAND: result = DecodeCommand(kHDMICommands, HDMICommand); - } - break; + break; + case FUNC_ACTIVE: + result = true; + break; + } } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_79_esp32_ble.ino b/tasmota/tasmota_xdrv_driver/xdrv_79_esp32_ble.ino index 6a2e01cc7..c907868e1 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_79_esp32_ble.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_79_esp32_ble.ino @@ -3634,6 +3634,9 @@ bool Xdrv79(uint32_t function) WebServer_on(PSTR("/" WEB_HANDLE_BLE), BLE_ESP32::HandleBleConfiguration); break; #endif // USE_WEBSERVER + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam.ino b/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam.ino index 541e2c55b..904e73c84 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam.ino @@ -1533,6 +1533,9 @@ bool Xdrv81(uint32_t function) { case FUNC_INIT: if(Wc.up == 0) WcSetup(Settings->webcam_config.resolution); break; + case FUNC_ACTIVE: + result = true; + break; } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam_task.ino b/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam_task.ino index 2b0e637d8..77636cf8b 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam_task.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam_task.ino @@ -3037,6 +3037,9 @@ bool Xdrv99(uint32_t function) { AddLog(LOG_LEVEL_DEBUG, PSTR("CAM: FUNC_SAVE_BEFORE_RESTART after delay")); #endif } break; + case FUNC_ACTIVE: + result = true; + break; } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino b/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino index f484566fa..8ae9c8d6a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino @@ -384,6 +384,9 @@ bool Xdrv82(uint32_t function) { case FUNC_INIT: EthernetInit(); break; + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_83_esp32_watch.ino b/tasmota/tasmota_xdrv_driver/xdrv_83_esp32_watch.ino index 939fab4d9..236db41f3 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_83_esp32_watch.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_83_esp32_watch.ino @@ -458,6 +458,9 @@ bool Xdrv83(uint32_t function) { case FUNC_LOOP: TTGO_loop(1); break; + case FUNC_ACTIVE: + result = true; + break; } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_85_esp32_ble_eq3_trv.ino b/tasmota/tasmota_xdrv_driver/xdrv_85_esp32_ble_eq3_trv.ino index 3e170c2c3..87883192c 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_85_esp32_ble_eq3_trv.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_85_esp32_ble_eq3_trv.ino @@ -1785,6 +1785,9 @@ bool Xdrv85(uint32_t function) case FUNC_WEB_SENSOR: break; #endif // USE_WEBSERVER + case FUNC_ACTIVE: + result = true; + break; } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino b/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino index 03cc63bf6..882407f21 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino @@ -2682,6 +2682,9 @@ bool Xdrv86(uint32_t function) { case FUNC_BUTTON_PRESSED: result = SSPMButton(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_87_esp32_sonoff_tm1621.ino b/tasmota/tasmota_xdrv_driver/xdrv_87_esp32_sonoff_tm1621.ino index 642f32ce3..b9006c740 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_87_esp32_sonoff_tm1621.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_87_esp32_sonoff_tm1621.ino @@ -600,6 +600,9 @@ bool Xdrv87(uint32_t function) { case FUNC_COMMAND: result = DecodeCommand(kTm1621Commands, kTm1621Command); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro.ino b/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro.ino index db7671733..20d0d01c7 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro.ino @@ -240,27 +240,30 @@ bool Xdrv88(uint32_t function) { if (FUNC_PRE_INIT == function) { ShellyProPreInit(); - } else if (SPro.detected) { - switch (function) { + } else if (SPro.detected) { + switch (function) { /* - case FUNC_BUTTON_PRESSED: - result = ShellyProButton(); - break; + case FUNC_BUTTON_PRESSED: + result = ShellyProButton(); + break; */ - case FUNC_EVERY_SECOND: - ShellyProLedLinkWifiOff(); - break; - case FUNC_SET_POWER: - ShellyProPower(); - break; - case FUNC_INIT: - ShellyProInit(); - break; - case FUNC_LED_LINK: - ShellyProLedLink(); - break; - } + case FUNC_EVERY_SECOND: + ShellyProLedLinkWifiOff(); + break; + case FUNC_SET_POWER: + ShellyProPower(); + break; + case FUNC_INIT: + ShellyProInit(); + break; + case FUNC_LED_LINK: + ShellyProLedLink(); + break; + case FUNC_ACTIVE: + result = true; + break; } + } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v1.ino b/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v1.ino index 6af3d65b7..2c01a5a4a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v1.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v1.ino @@ -153,22 +153,25 @@ bool Xdrv88(uint32_t function) { if (FUNC_PRE_INIT == function) { ShellyProPreInit(); - } else if (SPro.detected) { - switch (function) { - case FUNC_EVERY_SECOND: - ShellyProLedLinkWifiOff(); - break; - case FUNC_SET_POWER: - ShellyProPower(); - break; - case FUNC_LED_LINK: - ShellyProLedLink(); - break; - case FUNC_INIT: - ShellyProInit(); - break; - } + } else if (SPro.detected) { + switch (function) { + case FUNC_EVERY_SECOND: + ShellyProLedLinkWifiOff(); + break; + case FUNC_SET_POWER: + ShellyProPower(); + break; + case FUNC_LED_LINK: + ShellyProLedLink(); + break; + case FUNC_INIT: + ShellyProInit(); + break; + case FUNC_ACTIVE: + result = true; + break; } + } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v2.ino b/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v2.ino index f7bea6ca5..06456b990 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v2.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v2.ino @@ -486,33 +486,36 @@ bool Xdrv88(uint32_t function) { if (FUNC_SETUP_RING2 == function) { ShellyProPreInit(); - } else if (SPro.detected) { - switch (function) { + } else if (SPro.detected) { + switch (function) { /* - case FUNC_BUTTON_PRESSED: - result = ShellyProButton(); - break; + case FUNC_BUTTON_PRESSED: + result = ShellyProButton(); + break; */ - case FUNC_EVERY_SECOND: - ShellyProLedLinkWifiOff(); - break; - case FUNC_SET_POWER: - ShellyProPower(); - break; - case FUNC_INIT: - ShellyProInit(); - break; - case FUNC_ADD_BUTTON: - result = ShellyProAddButton(); - break; - case FUNC_ADD_SWITCH: - result = ShellyProAddSwitch(); - break; - case FUNC_LED_LINK: - ShellyProLedLink(); - break; - } + case FUNC_EVERY_SECOND: + ShellyProLedLinkWifiOff(); + break; + case FUNC_SET_POWER: + ShellyProPower(); + break; + case FUNC_INIT: + ShellyProInit(); + break; + case FUNC_ADD_BUTTON: + result = ShellyProAddButton(); + break; + case FUNC_ADD_SWITCH: + result = ShellyProAddSwitch(); + break; + case FUNC_LED_LINK: + ShellyProLedLink(); + break; + case FUNC_ACTIVE: + result = true; + break; } + } return result; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_89_esp32_dali.ino b/tasmota/tasmota_xdrv_driver/xdrv_89_esp32_dali.ino index d1fbeee5c..5168d077f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_89_esp32_dali.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_89_esp32_dali.ino @@ -574,6 +574,9 @@ bool Xdrv89(uint32_t function) case FUNC_COMMAND: result = DaliCmd(); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_90_esp32_dingtian_relay.ino b/tasmota/tasmota_xdrv_driver/xdrv_90_esp32_dingtian_relay.ino index c6dbd9193..d6d7da25a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_90_esp32_dingtian_relay.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_90_esp32_dingtian_relay.ino @@ -271,6 +271,9 @@ bool Xdrv90(uint32_t function) { result = DingtianAddKey(); break; #endif + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_91_magic_switch.ino b/tasmota/tasmota_xdrv_driver/xdrv_91_magic_switch.ino index 5356ada69..c0c128bcd 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_91_magic_switch.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_91_magic_switch.ino @@ -179,6 +179,9 @@ bool Xdrv91(uint32_t function) { case FUNC_COMMAND: result = DecodeCommand(kMagicSwitchCommands, MagicSwitchCommand); break; + case FUNC_ACTIVE: + result = true; + break; } } return result; diff --git a/tasmota/tasmota_xx2c_global/xdrv_interface.ino b/tasmota/tasmota_xx2c_global/xdrv_interface.ino index fda25f067..03ff1b2d9 100644 --- a/tasmota/tasmota_xx2c_global/xdrv_interface.ino +++ b/tasmota/tasmota_xx2c_global/xdrv_interface.ino @@ -1063,6 +1063,8 @@ const uint8_t kXdrvList[] = { /*********************************************************************************************/ +uint32_t Xdrv_active[4] = { 0 }; + void XsnsDriverState(void) { ResponseAppend_P(PSTR(",\"Drivers\":\"")); // Use string for future enable/disable signal for (uint32_t i = 0; i < sizeof(kXdrvList); i++) { @@ -1071,7 +1073,7 @@ void XsnsDriverState(void) { #else uint32_t driverid = kXdrvList[i]; #endif - ResponseAppend_P(PSTR("%s%d"), (i) ? "," : "", driverid); + ResponseAppend_P(PSTR("%s%s%d"), (i) ? "," : "", (!bitRead(Xdrv_active[i / 32], i % 32)) ? "!" : "", driverid); } ResponseAppend_P(PSTR("\"")); } @@ -1133,11 +1135,15 @@ bool XdrvCall(uint32_t function) { // DEBUG_TRACE_LOG(PSTR("DRV: %d"), function); +#ifdef USE_PROFILE_FUNCTION uint32_t profile_driver_start = millis(); +#endif // USE_PROFILE_FUNCTION for (uint32_t x = 0; x < xdrv_present; x++) { +#ifdef USE_PROFILE_FUNCTION uint32_t profile_function_start = millis(); +#endif // USE_PROFILE_FUNCTION result = xdrv_func_ptr[x](function); @@ -1150,6 +1156,9 @@ bool XdrvCall(uint32_t function) { PROFILE_FUNCTION("drv", index, function, profile_function_start); #endif // USE_PROFILE_FUNCTION + if (FUNC_ACTIVE == function) { + bitWrite(Xdrv_active[x / 32], x % 32, result); + } if (result && (function > FUNC_return_result)) { break; } diff --git a/tasmota/tasmota_xx2c_global/xsns_interface.ino b/tasmota/tasmota_xx2c_global/xsns_interface.ino index f78d5e9e2..2f020b92d 100644 --- a/tasmota/tasmota_xx2c_global/xsns_interface.ino +++ b/tasmota/tasmota_xx2c_global/xsns_interface.ino @@ -1116,13 +1116,17 @@ bool XsnsCall(uint32_t function) { // DEBUG_TRACE_LOG(PSTR("SNS: %d"), function); +#ifdef USE_PROFILE_FUNCTION uint32_t profile_driver_start = millis(); +#endif // USE_PROFILE_FUNCTION for (uint32_t x = 0; x < xsns_present; x++) { if (XsnsEnabled(0, x)) { // Skip disabled sensor if ((FUNC_WEB_SENSOR == function) && !XsnsEnabled(1, x)) { continue; } // Skip web info for disabled sensors +#ifdef USE_PROFILE_FUNCTION uint32_t profile_function_start = millis(); +#endif // USE_PROFILE_FUNCTION result = xsns_func_ptr[x](function); From 21de682f5898942c6f1122b3d23a4426fb0bab30 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 28 Dec 2023 13:48:27 +0100 Subject: [PATCH 054/303] Fix compile (#20329) --- tasmota/tasmota_xdrv_driver/xdrv_47_ftc532.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_47_ftc532.ino b/tasmota/tasmota_xdrv_driver/xdrv_47_ftc532.ino index c7afd9682..b31e2fe94 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_47_ftc532.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_47_ftc532.ino @@ -231,10 +231,10 @@ bool Xdrv47(uint32_t function) { case FUNC_JSON_APPEND: ftc532_show(); break; - } case FUNC_ACTIVE: result = true; break; + } } // Return bool result return result; From 67b36030dc028592bb49d52cbddaf2f90ac5beab Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 28 Dec 2023 17:00:35 +0100 Subject: [PATCH 055/303] Berry sync upstream #369 (#20330) --- lib/libesp32/berry/CMakeLists.txt | 38 ++++++++++++++ lib/libesp32/berry/default/berry.c | 81 ++++++++++++++++++++++-------- lib/libesp32/berry/src/be_mem.c | 69 +++++++++++++------------ 3 files changed, 135 insertions(+), 53 deletions(-) create mode 100644 lib/libesp32/berry/CMakeLists.txt diff --git a/lib/libesp32/berry/CMakeLists.txt b/lib/libesp32/berry/CMakeLists.txt new file mode 100644 index 000000000..aba79bf1b --- /dev/null +++ b/lib/libesp32/berry/CMakeLists.txt @@ -0,0 +1,38 @@ +cmake_minimum_required(VERSION 3.10) + +project(Berry C) +set(CMAKE_C_STANDARD 99) + +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +set(BERRY_COC ${CMAKE_CURRENT_SOURCE_DIR}/tools/coc/coc) +set(BERRY_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) +set(BERRY_CONFIG_DIR default CACHE FILEPATH "The directory of berry_conf.h.") +set(BERRY_CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/${BERRY_CONFIG_DIR}/berry_conf.h) +set(BERRY_GENERATE ${CMAKE_CURRENT_SOURCE_DIR}/generate) + +if (${CMAKE_HOST_WIN32}) + set(BERRY_COC python ${BERRY_COC}) +endif () + +file(MAKE_DIRECTORY generate) + +# berry library +file(GLOB SOURCES src/*.c) +add_library(libberry ${SOURCES}) +target_include_directories(libberry PUBLIC src ${BERRY_CONFIG_DIR}) + +add_custom_target(berry-coc + COMMAND ${BERRY_COC} -o ${BERRY_GENERATE} ${BERRY_SOURCE_DIR} -c ${BERRY_CONFIG} + DEPENDS ${SOURCES} COMMAND_EXPAND_LISTS + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Generate coc objects" +) +add_dependencies(libberry berry-coc) + +# berry default exe +file(GLOB SOURCES_EXE default/*.c) +add_executable(berry ${SOURCES_EXE}) +target_link_libraries(berry PUBLIC libberry) diff --git a/lib/libesp32/berry/default/berry.c b/lib/libesp32/berry/default/berry.c index 8a63d8ea8..4ddf7b6f0 100644 --- a/lib/libesp32/berry/default/berry.c +++ b/lib/libesp32/berry/default/berry.c @@ -59,6 +59,13 @@ FULL_VERSION " (build in " __DATE__ ", " __TIME__ ")\n" \ "[" COMPILER "] on " OS_NAME " (default)\n" \ +#if defined(_WIN32) +#define PATH_SEPARATOR ";" +#else +#define PATH_SEPARATOR ":" +#endif + + /* command help information */ #define help_information \ "Usage: berry [options] [script [args]]\n" \ @@ -66,6 +73,7 @@ " -i enter interactive mode after executing 'file'\n" \ " -l all variables in 'file' are parsed as local\n" \ " -e load 'script' source string and execute\n" \ + " -m custom module search path(s) separated by '" PATH_SEPARATOR "'\n"\ " -c compile script 'file' to bytecode file\n" \ " -o save bytecode to 'file'\n" \ " -g force named globals in VM\n" \ @@ -87,6 +95,7 @@ #define arg_g (1 << 7) #define arg_s (1 << 8) #define arg_err (1 << 9) +#define arg_m (1 << 10) struct arg_opts { int idx; @@ -95,6 +104,7 @@ struct arg_opts { const char *errarg; const char *src; const char *dst; + const char *modulepath; }; /* check if the character is a letter */ @@ -257,6 +267,10 @@ static int parse_arg(struct arg_opts *opt, int argc, char *argv[]) case 'e': args |= arg_e; break; case 'g': args |= arg_g; break; case 's': args |= arg_s; break; + case 'm': + args |= arg_m; + opt->modulepath = opt->optarg; + break; case '?': return args | arg_err; case 'c': args |= arg_c; @@ -286,12 +300,47 @@ static void push_args(bvm *vm, int argc, char *argv[]) be_pop(vm, 1); } +#if defined(_WIN32) +#define BERRY_ROOT "\\Windows\\system32" +static const char *module_paths[] = { + BERRY_ROOT "\\berry\\packages", +}; +#else +#define BERRY_ROOT "/usr/local" +static const char *module_paths[] = { + BERRY_ROOT "/lib/berry/packages", +}; +#endif + +static void berry_paths(bvm * vm) +{ + size_t i; + for (i = 0; i < array_count(module_paths); ++i) { + be_module_path_set(vm, module_paths[i]); + } +} + +static void berry_custom_paths(bvm *vm, const char *modulepath) +{ + const char delim[] = PATH_SEPARATOR; + char *copy = malloc(strlen(modulepath) + 1); + strcpy(copy, modulepath); + char *ptr = strtok(copy, delim); + + while (ptr != NULL) { + be_module_path_set(vm, ptr); + ptr = strtok(NULL, delim); + } + free(copy); +} + /* * command format: berry [options] [script [args]] * command options: * -i: enter interactive mode after executing 'script' * -b: load code from bytecode file * -e: load 'script' source and execute + * -m: specify custom module search path(s) * command format: berry options * command options: * -v: show version information @@ -305,7 +354,7 @@ static int analysis_args(bvm *vm, int argc, char *argv[]) { int args = 0; struct arg_opts opt = { 0 }; - opt.pattern = "vhilegsc?o?"; + opt.pattern = "m?vhilegsc?o?"; args = parse_arg(&opt, argc, argv); argc -= opt.idx; argv += opt.idx; @@ -315,6 +364,16 @@ static int analysis_args(bvm *vm, int argc, char *argv[]) be_pop(vm, 1); return -1; } + + if (args & arg_m) { + berry_custom_paths(vm, opt.modulepath); + args &= ~arg_m; + } + else { + // use default module paths + berry_paths(vm); + } + if (args & arg_g) { comp_set_named_gbl(vm); /* forced named global in VM code */ args &= ~arg_g; /* clear the flag for this option not to interfere with other options */ @@ -339,31 +398,11 @@ static int analysis_args(bvm *vm, int argc, char *argv[]) return load_script(vm, argc, argv, args); } -#if defined(_WIN32) -#define BERRY_ROOT "\\Windows\\system32" -static const char *module_paths[] = { - BERRY_ROOT "\\berry\\packages", -}; -#else -#define BERRY_ROOT "/usr/local" -static const char *module_paths[] = { - BERRY_ROOT "/lib/berry/packages", -}; -#endif - -static void berry_paths(bvm * vm) -{ - size_t i; - for (i = 0; i < array_count(module_paths); ++i) { - be_module_path_set(vm, module_paths[i]); - } -} int main(int argc, char *argv[]) { int res; bvm *vm = be_vm_new(); /* create a virtual machine instance */ - berry_paths(vm); res = analysis_args(vm, argc, argv); be_vm_delete(vm); /* free all objects and vm */ return res; diff --git a/lib/libesp32/berry/src/be_mem.c b/lib/libesp32/berry/src/be_mem.c index 24b75ec18..9d20ca055 100644 --- a/lib/libesp32/berry/src/be_mem.c +++ b/lib/libesp32/berry/src/be_mem.c @@ -26,12 +26,43 @@ #define realloc BE_EXPLICIT_REALLOC #endif -static void* malloc_from_pool(bvm *vm, size_t size); -static void free_from_pool(bvm *vm, void* ptr, size_t old_size); - #define POOL16_SIZE 16 #define POOL32_SIZE 32 +#ifdef _MSC_VER +#include +#pragma intrinsic(_BitScanForward) +#endif + +#if defined(__GNUC__) +#define popcount(v) __builtin_popcount(v) +#define ffs(v) __builtin_ffs(v) +#elif defined(_MSC_VER) +#define popcount(v) __popcnt(v) + +static int ffs(unsigned x) +{ + unsigned long i; + return _BitScanForward(&i, x) ? i : 0; +} +#else +/* https://github.com/hcs0/Hackers-Delight/blob/master/pop.c.txt - count number of 1-bits */ +static int popcount(uint32_t n) +{ + n = (n & 0x55555555u) + ((n >> 1) & 0x55555555u); + n = (n & 0x33333333u) + ((n >> 2) & 0x33333333u); + n = (n & 0x0f0f0f0fu) + ((n >> 4) & 0x0f0f0f0fu); + n = (n & 0x00ff00ffu) + ((n >> 8) & 0x00ff00ffu); + n = (n & 0x0000ffffu) + ((n >>16) & 0x0000ffffu); + return n; +} + +#error "unsupport compiler for ffs()" +#endif + +static void* malloc_from_pool(bvm *vm, size_t size); +static void free_from_pool(bvm *vm, void* ptr, size_t old_size); + BERRY_API void* be_os_malloc(size_t size) { return malloc(size); @@ -66,7 +97,7 @@ BERRY_API void* be_realloc(bvm *vm, void *ptr, size_t old_size, size_t new_size) if (!ptr || (old_size == 0)) { block = malloc_from_pool(vm, new_size); } - + /* Case 2: deallocate */ else if (new_size == 0) { #if BE_USE_PERF_COUNTERS @@ -176,11 +207,7 @@ static void* malloc_from_pool(bvm *vm, size_t size) { /* look for an empty slot */ if (pool16->bitmap != 0x0000) { /* there is a free slot */ -#ifdef __GNUC__ - int bit = __builtin_ffs(pool16->bitmap) - 1; -#else int bit = ffs(pool16->bitmap) - 1; -#endif if (bit >= 0) { /* we found a free slot */ // bitClear(pool16->bitmap, bit); @@ -208,11 +235,7 @@ static void* malloc_from_pool(bvm *vm, size_t size) { /* look for an empty slot */ if (pool32->bitmap != 0x0000) { /* there is a free slot */ -#ifdef __GNUC__ - int bit = __builtin_ffs(pool32->bitmap) - 1; -#else int bit = ffs(pool32->bitmap) - 1; -#endif if (bit >= 0) { /* we found a free slot */ // bitClear(pool32->bitmap, bit); @@ -327,24 +350,6 @@ BERRY_API void be_gc_free_memory_pools(bvm *vm) { vm->gc.pool32 = NULL; } -/* https://github.com/hcs0/Hackers-Delight/blob/master/pop.c.txt - count number of 1-bits */ -static int pop0(uint32_t n) __attribute__((unused)); -static int pop0(uint32_t n) { - n = (n & 0x55555555u) + ((n >> 1) & 0x55555555u); - n = (n & 0x33333333u) + ((n >> 2) & 0x33333333u); - n = (n & 0x0f0f0f0fu) + ((n >> 4) & 0x0f0f0f0fu); - n = (n & 0x00ff00ffu) + ((n >> 8) & 0x00ff00ffu); - n = (n & 0x0000ffffu) + ((n >>16) & 0x0000ffffu); - return n; -} - -#ifdef __GNUC__ - #define count_bits_1(v) __builtin_popcount(v) -#else - #define count_bits_1(v) pop0(v) -#endif - - BERRY_API void be_gc_memory_pools_info(bvm *vm, size_t* slots_used, size_t* slots_allocated) { size_t used = 0; size_t allocated = 0; @@ -352,14 +357,14 @@ BERRY_API void be_gc_memory_pools_info(bvm *vm, size_t* slots_used, size_t* slot gc16_t* pool16 = vm->gc.pool16; while (pool16) { allocated += POOL16_SLOTS; - used += POOL16_SLOTS - count_bits_1(pool16->bitmap); + used += POOL16_SLOTS - popcount(pool16->bitmap); pool16 = pool16->next; } gc32_t* pool32 = vm->gc.pool32; while (pool32) { allocated += POOL32_SLOTS; - used += POOL32_SLOTS - count_bits_1(pool32->bitmap); + used += POOL32_SLOTS - popcount(pool32->bitmap); pool32 = pool32->next; } if (slots_used) { *slots_used = used; } From d5a4f8441bfc0b98d6b482b684cc542d5ed4969b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 28 Dec 2023 17:25:01 +0100 Subject: [PATCH 056/303] Fix Berry claiming UART0 if needed (#20324) --- CHANGELOG.md | 2 ++ RELEASENOTES.md | 2 ++ tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino | 6 ++++++ tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino | 3 +++ tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino | 3 +++ tasmota/tasmota_xdrv_driver/xdrv_18_armtronix_dimmers.ino | 3 +++ tasmota/tasmota_xdrv_driver/xdrv_19_ps16dz_dimmer.ino | 3 +++ tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_9_serial.ino | 3 +++ tasmota/tasmota_xdrv_driver/xdrv_30_exs_dimmer.ino | 3 +++ tasmota/tasmota_xdrv_driver/xdrv_41_tcp_bridge.ino | 2 +- tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino | 3 +++ tasmota/tasmota_xdrv_driver/xdrv_45_shelly_dimmer.ino | 4 ++++ tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_serial.ino | 5 +++++ tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino | 3 +++ tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino | 3 +++ tasmota/tasmota_xdrv_driver/xdrv_65_tuyamcubr.ino | 4 ++++ tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino | 5 +++++ tasmota/tasmota_xnrg_energy/xnrg_02_cse7766.ino | 3 +++ tasmota/tasmota_xnrg_energy/xnrg_03_pzem004t.ino | 3 +++ tasmota/tasmota_xnrg_energy/xnrg_04_mcp39f501.ino | 3 +++ tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino | 3 +++ tasmota/tasmota_xnrg_energy/xnrg_14_bl09xx.ino | 3 +++ tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino | 3 +++ tasmota/tasmota_xnrg_energy/xnrg_22_bl6523.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_102_ld2410.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_105_lox_o2.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_107_gm861.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_113_hc8.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_15_mhz19.ino | 4 +++- tasmota/tasmota_xsns_sensor/xsns_18_pms5003.ino | 4 +++- tasmota/tasmota_xsns_sensor/xsns_20_novasds.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_22_sr04.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_23_me007.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_38_az7798.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_40_pn532.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_51_rdm6300.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_52_ibeacon.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_56_hpma.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_60_GPS.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_62_MI_HM10.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_64_hrxl.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_76_dyp.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_79_as608.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_86_tfminiplus.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_90_hrg15.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_91_vindriktning.ino | 3 +++ tasmota/tasmota_xsns_sensor/xsns_95_cm110x.ino | 3 +++ 47 files changed, 146 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 722216896..e726623d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file. - NeoPool hydrolysis FL1 and Redox flag (#20258) - Matter support for password for remote Tasmota devices (#20296) - Display of active drivers using command ``status 4`` +- ESP32 used UART information ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds (#20236) @@ -24,6 +25,7 @@ All notable changes to this project will be documented in this file. - ESP32 piezo ceramic buzzer doesn't buzz (#20118) - Syslog server warning caused by lack of field and hostname starting with 'z' (#14689) - Support for Domoticz floor/room topics. Regression from v12.0.1 (#20299) +- Berry claiming UART0 if needed (#20324) ### Removed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 1dfa0a653..9fe82cdde 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -122,6 +122,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247) - Display of active drivers using command ``status 4`` - NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) +- ESP32 used UART information - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) ### Breaking Changed @@ -135,6 +136,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Syslog server warning caused by lack of field and hostname starting with 'z' [#14689](https://github.com/arendst/Tasmota/issues/14689) - Support for Domoticz floor/room topics. Regression from v12.0.1 [#20299](https://github.com/arendst/Tasmota/issues/20299) - ESP32 piezo ceramic buzzer doesn't buzz [#20118](https://github.com/arendst/Tasmota/issues/20118) +- Berry claiming UART0 if needed [#20324](https://github.com/arendst/Tasmota/issues/20324) - Matter Contact sensor was not triggering any update [#20232](https://github.com/arendst/Tasmota/issues/20232) ### Removed \ No newline at end of file diff --git a/tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino b/tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino index 82582b5c5..e4855ee2e 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino @@ -183,6 +183,12 @@ void MP3PlayerInit(void) // start serial communication fixed to 9600 baud if (MP3Player->begin(9600)) { +#ifdef ESP32 + if (MP3Player->hardwareSerial()) { + ClaimSerial(); // Disable console using uart0 + } + AddLog(LOG_LEVEL_DEBUG, PSTR("MP3: Serial UART%d"), MP3Player->getUart()); +#endif // ESP32 MP3Player->flush(); delay(1000); MP3_CMD(MP3_CMD_RESET, MP3_CMD_RESET_VALUE); // reset the player to defaults diff --git a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino index cb7184922..9e8e4d462 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino @@ -1248,6 +1248,9 @@ void TuyaInit(void) { TuyaSerial = new TasmotaSerial(Pin(GPIO_TUYA_RX), Pin(GPIO_TUYA_TX), 2); if (TuyaSerial->begin(baudrate)) { if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: Serial UART%d"), TuyaSerial->getUart()); +#endif // ESP32 // Get MCU Configuration Tuya.SuspendTopic = true; Tuya.ignore_topic_timeout = millis() + 1000; // suppress /STAT topic for 1000ms to avoid data overflow diff --git a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino index c9c0908e0..549e48be3 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino @@ -2032,6 +2032,9 @@ void TuyaInit(void) { TuyaSerial = new TasmotaSerial(Pin(GPIO_TUYA_RX), Pin(GPIO_TUYA_TX), 2); if (TuyaSerial->begin(baudrate)) { if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: Serial UART%d"), TuyaSerial->getUart()); +#endif // ESP32 // Get MCU Configuration pTuya->SuspendTopic = true; pTuya->ignore_topic_timeout = millis() + 1000; // suppress /STAT topic for 1000ms to avoid data overflow diff --git a/tasmota/tasmota_xdrv_driver/xdrv_18_armtronix_dimmers.ino b/tasmota/tasmota_xdrv_driver/xdrv_18_armtronix_dimmers.ino index c512fdc3c..e67a0e542 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_18_armtronix_dimmers.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_18_armtronix_dimmers.ino @@ -101,6 +101,9 @@ void ArmtronixInit(void) if (ArmtronixSerial->begin(115200)) { if (ArmtronixSerial->hardwareSerial()) { ClaimSerial(); } ArmtronixSerial->println("Status"); +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("ARM: Serial UART%d"), ArmtronixSerial->getUart()); +#endif // ESP32 } } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_19_ps16dz_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_19_ps16dz_dimmer.ino index a7c513bd7..09d4715e9 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_19_ps16dz_dimmer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_19_ps16dz_dimmer.ino @@ -190,6 +190,9 @@ void PS16DZInit(void) PS16DZSerial = new TasmotaSerial(Pin(GPIO_RXD), Pin(GPIO_TXD), 2); if (PS16DZSerial->begin(19200)) { if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("PS1: Serial UART%d"), PS16DZSerial->getUart()); +#endif // ESP32 } } } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_9_serial.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_9_serial.ino index 05a049c8c..0f5249258 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_9_serial.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_9_serial.ino @@ -303,6 +303,9 @@ void ZigbeeInitSerial(void) if (ZigbeeSerial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "Serial UART%d"), ZigbeeSerial->getUart()); +#endif // ESP32 zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); zigbee.active = true; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_30_exs_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_30_exs_dimmer.ino index fed86a93d..6b80805c6 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_30_exs_dimmer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_30_exs_dimmer.ino @@ -415,6 +415,9 @@ void ExsInit(void) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("EXS: Serial UART%d"), ExsSerial->getUart()); +#endif // ESP32 ExsSerial->flush(); EsxMcuStart(); ExsSendCmd(EXS_CH_LOCK, 0); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_41_tcp_bridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_41_tcp_bridge.ino index 55ada143a..fdd4a2ad3 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_41_tcp_bridge.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_41_tcp_bridge.ino @@ -156,7 +156,7 @@ void TCPInit(void) { ClaimSerial(); } #ifdef ESP32 - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_TCP "using hardserial %d"), TCPSerial->getUart()); + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_TCP "Serial UART%d"), TCPSerial->getUart()); #endif } else { AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_TCP "failed init serial")); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino b/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino index 5b9f19054..36baa3749 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino @@ -1084,6 +1084,9 @@ miel_hvac_pre_init(void) ClaimSerial(); SetSerial(baudrate, TS_SERIAL_8E1); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME ": Serial UART%d"), sc->sc_serial->getUart()); +#endif sc->sc_device = TasmotaGlobal.devices_present; UpdateDevicesPresent(1); /* claim a POWER device slot */ diff --git a/tasmota/tasmota_xdrv_driver/xdrv_45_shelly_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_45_shelly_dimmer.ino index 2bd091488..560f2cfbe 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_45_shelly_dimmer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_45_shelly_dimmer.ino @@ -664,6 +664,10 @@ void ShdInit(void) if (ShdSerial->hardwareSerial()) ClaimSerial(); +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Serial UART%d"), ShdSerial->getUart()); +#endif + ShdSerial->flush(); ShdResetToAppMode(); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_serial.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_serial.ino index 5f20c8a8a..2ffe1dab6 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_serial.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_serial.ino @@ -56,6 +56,11 @@ extern "C" { if (!ok) { delete ser; be_raise(vm, "internal_error", "Unable to start serial"); + } else { + if (ser->hardwareSerial()) { + ClaimSerial(); // Disable console using uart0 + } + AddLog(LOG_LEVEL_DEBUG, PSTR("BRY: Serial UART%d"), ser->getUart()); } be_pushcomptr(vm, (void*) ser); be_setmember(vm, 1, ".p"); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino b/tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino index 801a1ab00..0a4224d30 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino @@ -122,6 +122,9 @@ projector_ctrl_pre_init(void) ClaimSerial(); SetSerial(baudrate, TS_SERIAL_8N1); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR(PROJECTOR_CTRL_LOGNAME ": Serial UART%d"), sc->sc_serial->getUart()); +#endif UpdateDevicesPresent(1); /* claim a POWER device slot */ sc->sc_device = TasmotaGlobal.devices_present; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino index c8f3fa109..ed82cd0ff 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino @@ -207,6 +207,9 @@ bool ModbusBridgeBegin(void) { if (2 == result) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("MBS: Serial UART%d"), modbusBridgeModbus->getUart()); +#endif AddLog(LOG_LEVEL_DEBUG, PSTR("MBS: MBR %s ser init at %d baud"), (2 == result ? "HW" : "SW"), Settings->modbus_sbaudrate * 300); if (nullptr == modbusBridge.buffer) { diff --git a/tasmota/tasmota_xdrv_driver/xdrv_65_tuyamcubr.ino b/tasmota/tasmota_xdrv_driver/xdrv_65_tuyamcubr.ino index caa1cefd3..150930dab 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_65_tuyamcubr.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_65_tuyamcubr.ino @@ -996,6 +996,10 @@ tuyamcubr_pre_init(void) if (sc->sc_serial->hardwareSerial()) ClaimSerial(); +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR(TUYAMCUBR_LOGNAME ": Serial UART%d"), sc->sc_serial->getUart()); +#endif + /* commit */ tuyamcubr_sc = sc; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino b/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino index 882407f21..e9319da56 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino @@ -1917,6 +1917,11 @@ void SSPMInit(void) { return; } + if (SspmSerial->hardwareSerial()) { + ClaimSerial(); + } + AddLog(LOG_LEVEL_DEBUG, PSTR("SPM: Serial UART%d"), SspmSerial->getUart()); + Xdrv86SettingsLoad(0); pinMode(SSPM_GPIO_ARM_RESET, OUTPUT); diff --git a/tasmota/tasmota_xnrg_energy/xnrg_02_cse7766.ino b/tasmota/tasmota_xnrg_energy/xnrg_02_cse7766.ino index 9ca4c5ce8..6e33897dd 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_02_cse7766.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_02_cse7766.ino @@ -232,6 +232,9 @@ void CseSnsInit(void) { SetSerial(4800, TS_SERIAL_8E1); ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("CSE: Serial UART%d"), CseSerial->getUart()); +#endif if (0 == Settings->param[P_CSE7766_INVALID_POWER]) { Settings->param[P_CSE7766_INVALID_POWER] = CSE_MAX_INVALID_POWER; // SetOption39 1..255 } diff --git a/tasmota/tasmota_xnrg_energy/xnrg_03_pzem004t.ino b/tasmota/tasmota_xnrg_energy/xnrg_03_pzem004t.ino index a965dbb6d..a275483c5 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_03_pzem004t.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_03_pzem004t.ino @@ -246,6 +246,9 @@ void PzemSnsInit(void) if (PzemSerial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("PZM: Serial UART%d"), PzemSerial->getUart()); +#endif Energy->phase_count = ENERGY_MAX_PHASES; // Start off with three phases Pzem.phase = 0; Pzem.read_state = 1; diff --git a/tasmota/tasmota_xnrg_energy/xnrg_04_mcp39f501.ino b/tasmota/tasmota_xnrg_energy/xnrg_04_mcp39f501.ino index 9cd8c4a52..1c4695b4d 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_04_mcp39f501.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_04_mcp39f501.ino @@ -572,6 +572,9 @@ void McpSnsInit(void) } else { mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE)); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("MCP: Serial UART%d"), McpSerial->getUart()); +#endif DigitalWrite(GPIO_MCP39F5_RST, 0, 1); // MCP enable Energy->use_overtemp = true; // Use global temperature for overtemp detection } else { diff --git a/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino b/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino index a087295b9..5945cf1f6 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino @@ -470,6 +470,9 @@ void solaxX1_SnsInit(void) solaxX1Serial = new TasmotaSerial(Pin(GPIO_SOLAXX1_RX), Pin(GPIO_SOLAXX1_TX), 1); if (solaxX1Serial->begin(SOLAXX1_SPEED)) { if (solaxX1Serial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("SX1: Serial UART%d"), solaxX1Serial->getUart()); +#endif } else { TasmotaGlobal.energy_driver = ENERGY_NONE; } diff --git a/tasmota/tasmota_xnrg_energy/xnrg_14_bl09xx.ino b/tasmota/tasmota_xnrg_energy/xnrg_14_bl09xx.ino index 343210e71..af1f0f6fc 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_14_bl09xx.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_14_bl09xx.ino @@ -307,6 +307,9 @@ void Bl09XXInit(void) { if (Bl09XXSerial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("BL9: Serial UART%d"), Bl09XXSerial->getUart()); +#endif if (HLW_UREF_PULSE == EnergyGetCalibration(ENERGY_VOLTAGE_CALIBRATION)) { for (uint32_t i = 0; i < 2; i++) { EnergySetCalibration(ENERGY_POWER_CALIBRATION, bl09xx_pref[Bl09XX.model], i); diff --git a/tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino b/tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino index b176065df..09a454201 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino @@ -583,6 +583,9 @@ void Cse7761SnsInit(void) { SetSerial(38400, TS_SERIAL_8E1); ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("C61: Serial UART%d"), Cse7761Serial->getUart()); +#endif #ifdef CSE7761_FREQUENCY #ifdef CSE7761_ZEROCROSS diff --git a/tasmota/tasmota_xnrg_energy/xnrg_22_bl6523.ino b/tasmota/tasmota_xnrg_energy/xnrg_22_bl6523.ino index 6df796461..b0b5d442a 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_22_bl6523.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_22_bl6523.ino @@ -238,6 +238,9 @@ void Bl6523Init(void) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("BL6: Serial UART%d and UART%d"), Bl6523RxSerial->getUart(), Bl6523TxSerial->getUart()); +#endif Bl6523.type = 1; Energy->phase_count = 1; AddLog(LOG_LEVEL_DEBUG, PSTR("BL6:Init Success" )); diff --git a/tasmota/tasmota_xsns_sensor/xsns_102_ld2410.ino b/tasmota/tasmota_xsns_sensor/xsns_102_ld2410.ino index b21a9b03a..3914179cd 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_102_ld2410.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_102_ld2410.ino @@ -407,6 +407,9 @@ void Ld2410Detect(void) { LD2410Serial = new TasmotaSerial(Pin(GPIO_LD2410_RX), Pin(GPIO_LD2410_TX), 2); if (LD2410Serial->begin(256000)) { if (LD2410Serial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("LD2: Serial UART%d"), LD2410Serial->getUart()); +#endif LD2410.retry = 4; LD2410.step = 12; diff --git a/tasmota/tasmota_xsns_sensor/xsns_105_lox_o2.ino b/tasmota/tasmota_xsns_sensor/xsns_105_lox_o2.ino index a644e964f..f006498b5 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_105_lox_o2.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_105_lox_o2.ino @@ -65,6 +65,9 @@ void LOXInit() if (LOXSerial->hardwareSerial()) ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("LOX: Serial UART%d"), LOXSerial->getUart()); +#endif } } diff --git a/tasmota/tasmota_xsns_sensor/xsns_107_gm861.ino b/tasmota/tasmota_xsns_sensor/xsns_107_gm861.ino index c54019c09..6d79911ac 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_107_gm861.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_107_gm861.ino @@ -265,6 +265,9 @@ void Gm861Init(void) { if (Gm861Serial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("GM8: Serial UART%d"), Gm861Serial->getUart()); +#endif Gm861->barcode[0] = '0'; // No barcode yet Gm861->state = GM861_STATE_INIT_OFFSET; } diff --git a/tasmota/tasmota_xsns_sensor/xsns_113_hc8.ino b/tasmota/tasmota_xsns_sensor/xsns_113_hc8.ino index 79845e837..bc1abae22 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_113_hc8.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_113_hc8.ino @@ -86,6 +86,9 @@ void Hc8Init(void) Hc8Serial = new TasmotaSerial(Pin(GPIO_HC8_RXD), -1, 1); if (Hc8Serial->begin(9600)) { if (Hc8Serial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("HC8: Serial UART%d"), Hc8Serial->getUart()); +#endif Hc8Initialized = true; } } diff --git a/tasmota/tasmota_xsns_sensor/xsns_15_mhz19.ino b/tasmota/tasmota_xsns_sensor/xsns_15_mhz19.ino index 3d89ff470..e1c21fffc 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_15_mhz19.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_15_mhz19.ino @@ -329,9 +329,11 @@ void MhzInit(void) MhzSerial = new TasmotaSerial(Pin(GPIO_MHZ_RXD), Pin(GPIO_MHZ_TXD), 1); if (MhzSerial->begin(9600)) { if (MhzSerial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("MHZ: Serial UART%d"), MhzSerial->getUart()); +#endif mhz_type = 1; } - } } diff --git a/tasmota/tasmota_xsns_sensor/xsns_18_pms5003.ino b/tasmota/tasmota_xsns_sensor/xsns_18_pms5003.ino index 426b6e286..a5f9e0ced 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_18_pms5003.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_18_pms5003.ino @@ -332,6 +332,9 @@ void PmsInit(void) { PmsSerial = new TasmotaSerial(Pin(GPIO_PMS5003_RX), (PinUsed(GPIO_PMS5003_TX)) ? Pin(GPIO_PMS5003_TX) : -1, 1); if (PmsSerial->begin(9600)) { if (PmsSerial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("PMS: Serial UART%d"), PmsSerial->getUart()); +#endif if (!PinUsed(GPIO_PMS5003_TX)) { // setting interval not supported if TX pin not connected Settings->pms_wake_interval = 0; @@ -345,7 +348,6 @@ void PmsInit(void) { Pms.time = Settings->pms_wake_interval - WARMUP_PERIOD; // Let it wake up in the next second } } - Pms.type = 1; } } diff --git a/tasmota/tasmota_xsns_sensor/xsns_20_novasds.ino b/tasmota/tasmota_xsns_sensor/xsns_20_novasds.ino index 20f6d8e30..417aa699d 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_20_novasds.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_20_novasds.ino @@ -208,6 +208,9 @@ void NovaSdsInit(void) if (NovaSdsSerial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("SDS: Serial UART%d"), NovaSdsSerial->getUart()); +#endif novasds_type = 1; NovaSdsSetWorkPeriod(); } diff --git a/tasmota/tasmota_xsns_sensor/xsns_22_sr04.ino b/tasmota/tasmota_xsns_sensor/xsns_22_sr04.ino index 4a4e28e17..21bd425da 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_22_sr04.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_22_sr04.ino @@ -146,6 +146,9 @@ void Sr04TModeDetect(void) { if (sonar_serial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("SR4: Serial UART%d"), sonar_serial->getUart()); +#endif } } diff --git a/tasmota/tasmota_xsns_sensor/xsns_23_me007.ino b/tasmota/tasmota_xsns_sensor/xsns_23_me007.ino index ebef6edd3..1332d7ae9 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_23_me007.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_23_me007.ino @@ -211,6 +211,9 @@ void me007_init( void ) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR(ME007_DEBUG_MSG_TAG "Serial UART%d"), gp_serial_if->getUart()); +#endif pinMode( me007_data_s.pin_trig_u8, OUTPUT ); /**< @details Configure trigger pin as output */ digitalWrite( me007_data_s.pin_trig_u8, HIGH ); /**< @details Set trigger pin to high-level as it ME007 requires a falling edge to initiate measurement */ diff --git a/tasmota/tasmota_xsns_sensor/xsns_38_az7798.ino b/tasmota/tasmota_xsns_sensor/xsns_38_az7798.ino index 1869ed76f..b456f8dd2 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_38_az7798.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_38_az7798.ino @@ -271,6 +271,9 @@ void AzInit(void) AzSerial = new TasmotaSerial(Pin(GPIO_AZ_RXD), Pin(GPIO_AZ_TXD), 1); if (AzSerial->begin(9600)) { if (AzSerial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("AZ7: Serial UART%d"), AzSerial->getUart()); +#endif az_type = 1; } } diff --git a/tasmota/tasmota_xsns_sensor/xsns_40_pn532.ino b/tasmota/tasmota_xsns_sensor/xsns_40_pn532.ino index dee669dd5..716178358 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_40_pn532.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_40_pn532.ino @@ -97,6 +97,9 @@ void PN532_Init(void) { PN532_Serial = new TasmotaSerial(Pin(GPIO_PN532_RXD), Pin(GPIO_PN532_TXD), 1); if (PN532_Serial->begin(115200)) { if (PN532_Serial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("NFC: Serial UART%d"), PN532_Serial->getUart()); +#endif PN532_wakeup(); uint32_t ver = PN532_getFirmwareVersion(); if (ver) { diff --git a/tasmota/tasmota_xsns_sensor/xsns_51_rdm6300.ino b/tasmota/tasmota_xsns_sensor/xsns_51_rdm6300.ino index 5a929524d..c4ca3a7ca 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_51_rdm6300.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_51_rdm6300.ino @@ -70,6 +70,9 @@ void RDM6300Init() { if (RDM6300Serial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("RDM: Serial UART%d"), RDM6300Serial->getUart()); +#endif } } } diff --git a/tasmota/tasmota_xsns_sensor/xsns_52_ibeacon.ino b/tasmota/tasmota_xsns_sensor/xsns_52_ibeacon.ino index 411e82e21..96420a010 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_52_ibeacon.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_52_ibeacon.ino @@ -326,6 +326,9 @@ void IBEACON_Init() { if (IBEACON_Serial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("BLE: Serial UART%d"), IBEACON_Serial->getUart()); +#endif hm17_sendcmd(HM17_TEST); hm17_lastms=millis(); // in case of using Settings this has to be moved diff --git a/tasmota/tasmota_xsns_sensor/xsns_56_hpma.ino b/tasmota/tasmota_xsns_sensor/xsns_56_hpma.ino index a318150d7..358b8febd 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_56_hpma.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_56_hpma.ino @@ -71,6 +71,9 @@ void HpmaInit(void) if (HpmaSerial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("HPM: Serial UART%d"), HpmaSerial->getUart()); +#endif hpma_type = 1; hpma115S0->Init(); hpma115S0->StartParticleMeasurement(); diff --git a/tasmota/tasmota_xsns_sensor/xsns_60_GPS.ino b/tasmota/tasmota_xsns_sensor/xsns_60_GPS.ino index fc53bd920..d37e4cf0c 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_60_GPS.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_60_GPS.ino @@ -383,6 +383,9 @@ void UBXDetect(void) ClaimSerial(); DEBUG_SENSOR_LOG(PSTR("UBX: claim HW")); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("UBX: Serial UART%d"), UBXSerial->getUart()); +#endif } } else { diff --git a/tasmota/tasmota_xsns_sensor/xsns_62_MI_HM10.ino b/tasmota/tasmota_xsns_sensor/xsns_62_MI_HM10.ino index b9334cf96..80609ff73 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_62_MI_HM10.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_62_MI_HM10.ino @@ -698,6 +698,9 @@ void HM10SerialInit(void) { ClaimSerial(); DEBUG_SENSOR_LOG(PSTR("%s: claim HW"),D_CMND_HM10); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("HM1: Serial UART%d"), HM10Serial->getUart()); +#endif HM10_Reset(); HM10.mode.pending_task = 1; HM10.mode.init = 1; diff --git a/tasmota/tasmota_xsns_sensor/xsns_64_hrxl.ino b/tasmota/tasmota_xsns_sensor/xsns_64_hrxl.ino index 727778fe1..22c40487a 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_64_hrxl.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_64_hrxl.ino @@ -43,6 +43,9 @@ void HRXLInit(void) { if (HRXLSerial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("HRX: Serial UART%d"), HRXLSerial->getUart()); +#endif HRXLSerial->setTimeout(HRXL_READ_TIMEOUT); } } diff --git a/tasmota/tasmota_xsns_sensor/xsns_76_dyp.ino b/tasmota/tasmota_xsns_sensor/xsns_76_dyp.ino index 9aa3ecaa2..203de7b56 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_76_dyp.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_76_dyp.ino @@ -52,6 +52,9 @@ void DYPInit(void) { if (DYPSerial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("DYP: Serial UART%d"), DYPSerial->getUart()); +#endif } } } diff --git a/tasmota/tasmota_xsns_sensor/xsns_79_as608.ino b/tasmota/tasmota_xsns_sensor/xsns_79_as608.ino index b2059a90d..7850ecb0c 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_79_as608.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_79_as608.ino @@ -116,6 +116,9 @@ void As608Init(void) { As608Finger->begin(57600); if (As608Serial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("AS6: Serial UART%d"), As608Serial->getUart()); +#endif if (As608Finger->verifyPassword()) { As608Finger->getTemplateCount(); diff --git a/tasmota/tasmota_xsns_sensor/xsns_86_tfminiplus.ino b/tasmota/tasmota_xsns_sensor/xsns_86_tfminiplus.ino index 02cce9e27..ebfcdd551 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_86_tfminiplus.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_86_tfminiplus.ino @@ -97,6 +97,9 @@ void TfmpInit(void) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("TFM: Serial UART%d"), TfmpSerial->getUart()); +#endif tfminiplus_sensor.ready = true; TfmpSerial->flush(); } diff --git a/tasmota/tasmota_xsns_sensor/xsns_90_hrg15.ino b/tasmota/tasmota_xsns_sensor/xsns_90_hrg15.ino index c83d92238..0f2f45244 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_90_hrg15.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_90_hrg15.ino @@ -159,6 +159,9 @@ void Rg15Init(void) { if (HydreonSerial) { if (HydreonSerial->begin(RG15_BAUDRATE)) { if (HydreonSerial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("HRG: Serial UART%d"), HydreonSerial->getUart()); +#endif Rg15.init_step = 5; // Perform RG-15 init } } diff --git a/tasmota/tasmota_xsns_sensor/xsns_91_vindriktning.ino b/tasmota/tasmota_xsns_sensor/xsns_91_vindriktning.ino index 2f866bf9c..f98605294 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_91_vindriktning.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_91_vindriktning.ino @@ -114,6 +114,9 @@ void VindriktningInit(void) { VindriktningSerial = new TasmotaSerial(Pin(GPIO_VINDRIKTNING_RX), -1, 1); if (VindriktningSerial->begin(9600)) { if (VindriktningSerial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("VDN: Serial UART%d"), VindriktningSerial->getUart()); +#endif Vindriktning.type = 1; } } diff --git a/tasmota/tasmota_xsns_sensor/xsns_95_cm110x.ino b/tasmota/tasmota_xsns_sensor/xsns_95_cm110x.ino index c71a91093..aa0b22697 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_95_cm110x.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_95_cm110x.ino @@ -394,6 +394,9 @@ void CM11Init(void) CM11Serial = new TasmotaSerial(Pin(GPIO_CM11_RXD), Pin(GPIO_CM11_TXD), 1); if (CM11Serial->begin(9600)) { if (CM11Serial->hardwareSerial()) { ClaimSerial(); } +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("CM1: Serial UART%d"), CM11Serial->getUart()); +#endif cm11_type = 1; CM11SendCmd(CM11_CMND_SW_VERSION); } From 6d94d9e766ced73135154a681114ad8d49cff308 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 28 Dec 2023 17:53:21 +0100 Subject: [PATCH 057/303] Cleanup --- tasmota/tasmota_xdrv_driver/xdrv_08_serial_bridge.ino | 4 ++-- tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_08_serial_bridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_08_serial_bridge.ino index c3d432808..fdce70e4a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_08_serial_bridge.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_08_serial_bridge.ino @@ -198,11 +198,11 @@ void SerialBridgeInit(void) { } else { serial_bridge_buffer = (char*)(malloc(SERIAL_BRIDGE_BUFSIZE)); } - SerialBridgeSerial->flush(); - SerialBridgePrintf("\r\n"); #ifdef ESP32 AddLog(LOG_LEVEL_DEBUG, PSTR("SBR: Serial UART%d"), SerialBridgeSerial->getUart()); #endif + SerialBridgeSerial->flush(); + SerialBridgePrintf("\r\n"); } } } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino b/tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino index e4855ee2e..58daa63ed 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_14_mp3.ino @@ -183,10 +183,8 @@ void MP3PlayerInit(void) // start serial communication fixed to 9600 baud if (MP3Player->begin(9600)) { + if (MP3Player->hardwareSerial()) { ClaimSerial(); } #ifdef ESP32 - if (MP3Player->hardwareSerial()) { - ClaimSerial(); // Disable console using uart0 - } AddLog(LOG_LEVEL_DEBUG, PSTR("MP3: Serial UART%d"), MP3Player->getUart()); #endif // ESP32 MP3Player->flush(); From 1f662a6dad8fd14a5dbf17b308f1306c85aecc0a Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 28 Dec 2023 22:19:58 +0100 Subject: [PATCH 058/303] HASPmota added `haspmota.page_show()` to change page (#20333) --- CHANGELOG.md | 1 + .../berry_tasmota/src/be_lv_haspmota.c | 1261 +++++++++-------- .../haspmota_src/haspmota_core/haspmota.be | 13 +- 3 files changed, 656 insertions(+), 619 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e726623d6..759b427a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. - Matter support for password for remote Tasmota devices (#20296) - Display of active drivers using command ``status 4`` - ESP32 used UART information +- HASPmota added `haspmota.page_show()` to change page ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds (#20236) diff --git a/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c b/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c index bf20a03e5..70f239d36 100644 --- a/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c +++ b/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c @@ -6335,12 +6335,115 @@ void be_load_lvh_qrcode_class(bvm *vm) { extern const bclass be_class_HASPmota; +/******************************************************************** +** Solidified function: page_show +********************************************************************/ +be_local_closure(HASPmota_page_show, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_str_weak(lvh_pages), + /* K1 */ be_nested_str_weak(lvh_page_cur_idx), + /* K2 */ be_nested_str_weak(pages_list_sorted), + /* K3 */ be_const_int(1), + /* K4 */ be_nested_str_weak(prev), + /* K5 */ be_nested_str_weak(next), + /* K6 */ be_nested_str_weak(back), + /* K7 */ be_nested_str_weak(re_page_target), + /* K8 */ be_nested_str_weak(match), + /* K9 */ be_const_int(0), + /* K10 */ be_nested_str_weak(show), + }), + be_str_weak(page_show), + &be_const_str_solidified, + ( &(const binstruction[68]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x880C0100, // 0001 GETMBR R3 R0 K0 + 0x88100101, // 0002 GETMBR R4 R0 K1 + 0x940C0604, // 0003 GETIDX R3 R3 R4 + 0x8C100102, // 0004 GETMET R4 R0 K2 + 0x88180101, // 0005 GETMBR R6 R0 K1 + 0x7C100400, // 0006 CALL R4 2 + 0x6014000C, // 0007 GETGBL R5 G12 + 0x5C180800, // 0008 MOVE R6 R4 + 0x7C140200, // 0009 CALL R5 1 + 0x18140B03, // 000A LE R5 R5 K3 + 0x78160000, // 000B JMPF R5 #000D + 0x80000A00, // 000C RET 0 + 0x1C140304, // 000D EQ R5 R1 K4 + 0x78160009, // 000E JMPF R5 #0019 + 0x60140009, // 000F GETGBL R5 G9 + 0x88180704, // 0010 GETMBR R6 R3 K4 + 0x7C140200, // 0011 CALL R5 1 + 0x5C080A00, // 0012 MOVE R2 R5 + 0x4C140000, // 0013 LDNIL R5 + 0x1C140405, // 0014 EQ R5 R2 R5 + 0x78160001, // 0015 JMPF R5 #0018 + 0x5415FFFE, // 0016 LDINT R5 -1 + 0x94080805, // 0017 GETIDX R2 R4 R5 + 0x70020020, // 0018 JMP #003A + 0x1C140305, // 0019 EQ R5 R1 K5 + 0x78160008, // 001A JMPF R5 #0024 + 0x60140009, // 001B GETGBL R5 G9 + 0x88180705, // 001C GETMBR R6 R3 K5 + 0x7C140200, // 001D CALL R5 1 + 0x5C080A00, // 001E MOVE R2 R5 + 0x4C140000, // 001F LDNIL R5 + 0x1C140405, // 0020 EQ R5 R2 R5 + 0x78160000, // 0021 JMPF R5 #0023 + 0x94080903, // 0022 GETIDX R2 R4 K3 + 0x70020015, // 0023 JMP #003A + 0x1C140306, // 0024 EQ R5 R1 K6 + 0x78160008, // 0025 JMPF R5 #002F + 0x60140009, // 0026 GETGBL R5 G9 + 0x88180706, // 0027 GETMBR R6 R3 K6 + 0x7C140200, // 0028 CALL R5 1 + 0x5C080A00, // 0029 MOVE R2 R5 + 0x4C140000, // 002A LDNIL R5 + 0x1C140405, // 002B EQ R5 R2 R5 + 0x78160000, // 002C JMPF R5 #002E + 0x58080003, // 002D LDCONST R2 K3 + 0x7002000A, // 002E JMP #003A + 0x88140107, // 002F GETMBR R5 R0 K7 + 0x8C140B08, // 0030 GETMET R5 R5 K8 + 0x5C1C0200, // 0031 MOVE R7 R1 + 0x7C140400, // 0032 CALL R5 2 + 0x78160005, // 0033 JMPF R5 #003A + 0x60140009, // 0034 GETGBL R5 G9 + 0x5419FFFE, // 0035 LDINT R6 -1 + 0x401A0606, // 0036 CONNECT R6 K3 R6 + 0x94180206, // 0037 GETIDX R6 R1 R6 + 0x7C140200, // 0038 CALL R5 1 + 0x5C080A00, // 0039 MOVE R2 R5 + 0x4C140000, // 003A LDNIL R5 + 0x20140405, // 003B NE R5 R2 R5 + 0x78160005, // 003C JMPF R5 #0043 + 0x24140509, // 003D GT R5 R2 K9 + 0x78160003, // 003E JMPF R5 #0043 + 0x88140100, // 003F GETMBR R5 R0 K0 + 0x94140A02, // 0040 GETIDX R5 R5 R2 + 0x8C140B0A, // 0041 GETMET R5 R5 K10 + 0x7C140200, // 0042 CALL R5 1 + 0x80000000, // 0043 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: do_action ********************************************************************/ be_local_closure(HASPmota_do_action, /* name */ be_nested_proto( - 10, /* nstack */ + 6, /* nstack */ 3, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -6348,99 +6451,224 @@ be_local_closure(HASPmota_do_action, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ + ( &(const bvalue[ 4]) { /* constants */ /* K0 */ be_nested_str_weak(lv), /* K1 */ be_nested_str_weak(EVENT_CLICKED), - /* K2 */ be_nested_str_weak(_action), - /* K3 */ be_nested_str_weak(lvh_pages), - /* K4 */ be_nested_str_weak(lvh_page_cur_idx), - /* K5 */ be_nested_str_weak(pages_list_sorted), - /* K6 */ be_const_int(1), - /* K7 */ be_nested_str_weak(prev), - /* K8 */ be_nested_str_weak(next), - /* K9 */ be_nested_str_weak(back), - /* K10 */ be_nested_str_weak(re_page_target), - /* K11 */ be_nested_str_weak(match), - /* K12 */ be_const_int(0), - /* K13 */ be_nested_str_weak(show), + /* K2 */ be_nested_str_weak(page_show), + /* K3 */ be_nested_str_weak(_action), }), be_str_weak(do_action), &be_const_str_solidified, - ( &(const binstruction[74]) { /* code */ + ( &(const binstruction[ 9]) { /* code */ 0xB80E0000, // 0000 GETNGBL R3 K0 0x880C0701, // 0001 GETMBR R3 R3 K1 0x200C0403, // 0002 NE R3 R2 R3 0x780E0000, // 0003 JMPF R3 #0005 0x80000600, // 0004 RET 0 - 0x880C0302, // 0005 GETMBR R3 R1 K2 - 0x88100103, // 0006 GETMBR R4 R0 K3 - 0x88140104, // 0007 GETMBR R5 R0 K4 - 0x94100805, // 0008 GETIDX R4 R4 R5 - 0x4C140000, // 0009 LDNIL R5 - 0x8C180105, // 000A GETMET R6 R0 K5 - 0x88200104, // 000B GETMBR R8 R0 K4 - 0x7C180400, // 000C CALL R6 2 - 0x601C000C, // 000D GETGBL R7 G12 - 0x5C200C00, // 000E MOVE R8 R6 - 0x7C1C0200, // 000F CALL R7 1 - 0x181C0F06, // 0010 LE R7 R7 K6 - 0x781E0000, // 0011 JMPF R7 #0013 - 0x80000E00, // 0012 RET 0 - 0x1C1C0707, // 0013 EQ R7 R3 K7 - 0x781E0009, // 0014 JMPF R7 #001F - 0x601C0009, // 0015 GETGBL R7 G9 - 0x88200907, // 0016 GETMBR R8 R4 K7 - 0x7C1C0200, // 0017 CALL R7 1 - 0x5C140E00, // 0018 MOVE R5 R7 - 0x4C1C0000, // 0019 LDNIL R7 - 0x1C1C0A07, // 001A EQ R7 R5 R7 - 0x781E0001, // 001B JMPF R7 #001E - 0x541DFFFE, // 001C LDINT R7 -1 - 0x94140C07, // 001D GETIDX R5 R6 R7 - 0x70020020, // 001E JMP #0040 - 0x1C1C0708, // 001F EQ R7 R3 K8 - 0x781E0008, // 0020 JMPF R7 #002A - 0x601C0009, // 0021 GETGBL R7 G9 - 0x88200908, // 0022 GETMBR R8 R4 K8 - 0x7C1C0200, // 0023 CALL R7 1 - 0x5C140E00, // 0024 MOVE R5 R7 - 0x4C1C0000, // 0025 LDNIL R7 - 0x1C1C0A07, // 0026 EQ R7 R5 R7 - 0x781E0000, // 0027 JMPF R7 #0029 - 0x94140D06, // 0028 GETIDX R5 R6 K6 - 0x70020015, // 0029 JMP #0040 - 0x1C1C0709, // 002A EQ R7 R3 K9 - 0x781E0008, // 002B JMPF R7 #0035 - 0x601C0009, // 002C GETGBL R7 G9 - 0x88200909, // 002D GETMBR R8 R4 K9 - 0x7C1C0200, // 002E CALL R7 1 - 0x5C140E00, // 002F MOVE R5 R7 - 0x4C1C0000, // 0030 LDNIL R7 - 0x1C1C0A07, // 0031 EQ R7 R5 R7 - 0x781E0000, // 0032 JMPF R7 #0034 - 0x58140006, // 0033 LDCONST R5 K6 - 0x7002000A, // 0034 JMP #0040 - 0x881C010A, // 0035 GETMBR R7 R0 K10 - 0x8C1C0F0B, // 0036 GETMET R7 R7 K11 - 0x5C240600, // 0037 MOVE R9 R3 - 0x7C1C0400, // 0038 CALL R7 2 - 0x781E0005, // 0039 JMPF R7 #0040 - 0x601C0009, // 003A GETGBL R7 G9 - 0x5421FFFE, // 003B LDINT R8 -1 - 0x40220C08, // 003C CONNECT R8 K6 R8 - 0x94200608, // 003D GETIDX R8 R3 R8 - 0x7C1C0200, // 003E CALL R7 1 - 0x5C140E00, // 003F MOVE R5 R7 - 0x4C1C0000, // 0040 LDNIL R7 - 0x201C0A07, // 0041 NE R7 R5 R7 - 0x781E0005, // 0042 JMPF R7 #0049 - 0x241C0B0C, // 0043 GT R7 R5 K12 - 0x781E0003, // 0044 JMPF R7 #0049 - 0x881C0103, // 0045 GETMBR R7 R0 K3 - 0x941C0E05, // 0046 GETIDX R7 R7 R5 - 0x8C1C0F0D, // 0047 GETMET R7 R7 K13 - 0x7C1C0200, // 0048 CALL R7 1 - 0x80000000, // 0049 RET 0 + 0x8C0C0102, // 0005 GETMET R3 R0 K2 + 0x88140303, // 0006 GETMBR R5 R1 K3 + 0x7C0C0400, // 0007 CALL R3 2 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: register_event +********************************************************************/ +be_local_closure(HASPmota_register_event, /* name */ + be_nested_proto( + 13, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 1]) { + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(event_dispatch), + }), + be_str_weak(_X3Clambda_X3E), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x68040000, // 0000 GETUPV R1 U0 + 0x8C040300, // 0001 GETMET R1 R1 K0 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C040400, // 0003 CALL R1 2 + 0x80040200, // 0004 RET 1 R1 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str_weak(cb), + /* K1 */ be_nested_str_weak(introspect), + /* K2 */ be_nested_str_weak(event_cb), + /* K3 */ be_nested_str_weak(gen_cb), + /* K4 */ be_nested_str_weak(_lv_obj), + /* K5 */ be_nested_str_weak(add_event_cb), + /* K6 */ be_nested_str_weak(toptr), + }), + be_str_weak(register_event), + &be_const_str_solidified, + ( &(const binstruction[20]) { /* code */ + 0xA40E0000, // 0000 IMPORT R3 K0 + 0xA4120200, // 0001 IMPORT R4 K1 + 0x88140102, // 0002 GETMBR R5 R0 K2 + 0x4C180000, // 0003 LDNIL R6 + 0x1C140A06, // 0004 EQ R5 R5 R6 + 0x78160003, // 0005 JMPF R5 #000A + 0x8C140703, // 0006 GETMET R5 R3 K3 + 0x841C0000, // 0007 CLOSURE R7 P0 + 0x7C140400, // 0008 CALL R5 2 + 0x90020405, // 0009 SETMBR R0 K2 R5 + 0x88140304, // 000A GETMBR R5 R1 K4 + 0x8C180B05, // 000B GETMET R6 R5 K5 + 0x88200102, // 000C GETMBR R8 R0 K2 + 0x5C240400, // 000D MOVE R9 R2 + 0x8C280906, // 000E GETMET R10 R4 K6 + 0x5C300200, // 000F MOVE R12 R1 + 0x7C280400, // 0010 CALL R10 2 + 0x7C180800, // 0011 CALL R6 4 + 0xA0000000, // 0012 CLOSE R0 + 0x80000000, // 0013 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: parse +********************************************************************/ +be_local_closure(HASPmota_parse, /* name */ + be_nested_proto( + 9, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(json), + /* K1 */ be_nested_str_weak(load), + /* K2 */ be_nested_str_weak(instance), + /* K3 */ be_nested_str_weak(parse_page), + /* K4 */ be_nested_str_weak(parse_obj), + /* K5 */ be_nested_str_weak(lvh_pages), + /* K6 */ be_nested_str_weak(lvh_page_cur_idx), + /* K7 */ be_nested_str_weak(value_error), + /* K8 */ be_nested_str_weak(unable_X20to_X20parse_X20JSON_X20line), + }), + be_str_weak(parse), + &be_const_str_solidified, + ( &(const binstruction[21]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0x8C0C0501, // 0001 GETMET R3 R2 K1 + 0x5C140200, // 0002 MOVE R5 R1 + 0x7C0C0400, // 0003 CALL R3 2 + 0x60100004, // 0004 GETGBL R4 G4 + 0x5C140600, // 0005 MOVE R5 R3 + 0x7C100200, // 0006 CALL R4 1 + 0x1C100902, // 0007 EQ R4 R4 K2 + 0x78120009, // 0008 JMPF R4 #0013 + 0x8C100103, // 0009 GETMET R4 R0 K3 + 0x5C180600, // 000A MOVE R6 R3 + 0x7C100400, // 000B CALL R4 2 + 0x8C100104, // 000C GETMET R4 R0 K4 + 0x5C180600, // 000D MOVE R6 R3 + 0x881C0105, // 000E GETMBR R7 R0 K5 + 0x88200106, // 000F GETMBR R8 R0 K6 + 0x941C0E08, // 0010 GETIDX R7 R7 R8 + 0x7C100600, // 0011 CALL R4 3 + 0x70020000, // 0012 JMP #0014 + 0xB0060F08, // 0013 RAISE 1 K7 K8 + 0x80000000, // 0014 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: event_dispatch +********************************************************************/ +be_local_closure(HASPmota_event_dispatch, /* name */ + be_nested_proto( + 9, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_str_weak(introspect), + /* K1 */ be_nested_str_weak(toptr), + /* K2 */ be_nested_str_weak(event), + /* K3 */ be_nested_str_weak(_change_buffer), + /* K4 */ be_nested_str_weak(lv), + /* K5 */ be_nested_str_weak(lv_event), + /* K6 */ be_nested_str_weak(user_data), + /* K7 */ be_const_int(0), + /* K8 */ be_nested_str_weak(fromptr), + /* K9 */ be_nested_str_weak(instance), + /* K10 */ be_nested_str_weak(event_cb), + }), + be_str_weak(event_dispatch), + &be_const_str_solidified, + ( &(const binstruction[35]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0x8C0C0501, // 0001 GETMET R3 R2 K1 + 0x5C140200, // 0002 MOVE R5 R1 + 0x7C0C0400, // 0003 CALL R3 2 + 0x88100102, // 0004 GETMBR R4 R0 K2 + 0x78120004, // 0005 JMPF R4 #000B + 0x88100102, // 0006 GETMBR R4 R0 K2 + 0x8C100903, // 0007 GETMET R4 R4 K3 + 0x5C180600, // 0008 MOVE R6 R3 + 0x7C100400, // 0009 CALL R4 2 + 0x70020004, // 000A JMP #0010 + 0xB8120800, // 000B GETNGBL R4 K4 + 0x8C100905, // 000C GETMET R4 R4 K5 + 0x5C180600, // 000D MOVE R6 R3 + 0x7C100400, // 000E CALL R4 2 + 0x90020404, // 000F SETMBR R0 K2 R4 + 0x88100102, // 0010 GETMBR R4 R0 K2 + 0x88100906, // 0011 GETMBR R4 R4 K6 + 0x60140009, // 0012 GETGBL R5 G9 + 0x5C180800, // 0013 MOVE R6 R4 + 0x7C140200, // 0014 CALL R5 1 + 0x20140B07, // 0015 NE R5 R5 K7 + 0x7816000A, // 0016 JMPF R5 #0022 + 0x8C140508, // 0017 GETMET R5 R2 K8 + 0x5C1C0800, // 0018 MOVE R7 R4 + 0x7C140400, // 0019 CALL R5 2 + 0x60180004, // 001A GETGBL R6 G4 + 0x5C1C0A00, // 001B MOVE R7 R5 + 0x7C180200, // 001C CALL R6 1 + 0x1C180D09, // 001D EQ R6 R6 K9 + 0x781A0002, // 001E JMPF R6 #0022 + 0x8C180B0A, // 001F GETMET R6 R5 K10 + 0x88200102, // 0020 GETMBR R8 R0 K2 + 0x7C180400, // 0021 CALL R6 2 + 0x80000000, // 0022 RET 0 }) ) ); @@ -6527,6 +6755,251 @@ be_local_closure(HASPmota_pages_list_sorted, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: sort +********************************************************************/ +be_local_closure(HASPmota_sort, /* name */ + be_nested_proto( + 7, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_const_class(be_class_HASPmota), + /* K1 */ be_const_int(1), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(sort), + &be_const_str_solidified, + ( &(const binstruction[30]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x60080010, // 0001 GETGBL R2 G16 + 0x600C000C, // 0002 GETGBL R3 G12 + 0x5C100000, // 0003 MOVE R4 R0 + 0x7C0C0200, // 0004 CALL R3 1 + 0x040C0701, // 0005 SUB R3 R3 K1 + 0x400E0203, // 0006 CONNECT R3 K1 R3 + 0x7C080200, // 0007 CALL R2 1 + 0xA8020010, // 0008 EXBLK 0 #001A + 0x5C0C0400, // 0009 MOVE R3 R2 + 0x7C0C0000, // 000A CALL R3 0 + 0x94100003, // 000B GETIDX R4 R0 R3 + 0x5C140600, // 000C MOVE R5 R3 + 0x24180B02, // 000D GT R6 R5 K2 + 0x781A0008, // 000E JMPF R6 #0018 + 0x04180B01, // 000F SUB R6 R5 K1 + 0x94180006, // 0010 GETIDX R6 R0 R6 + 0x24180C04, // 0011 GT R6 R6 R4 + 0x781A0004, // 0012 JMPF R6 #0018 + 0x04180B01, // 0013 SUB R6 R5 K1 + 0x94180006, // 0014 GETIDX R6 R0 R6 + 0x98000A06, // 0015 SETIDX R0 R5 R6 + 0x04140B01, // 0016 SUB R5 R5 K1 + 0x7001FFF4, // 0017 JMP #000D + 0x98000A04, // 0018 SETIDX R0 R5 R4 + 0x7001FFEE, // 0019 JMP #0009 + 0x58080003, // 001A LDCONST R2 K3 + 0xAC080200, // 001B CATCH R2 1 0 + 0xB0080000, // 001C RAISE 2 R0 R0 + 0x80040000, // 001D RET 1 R0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: parse_page +********************************************************************/ +be_local_closure(HASPmota_parse_page, /* name */ + be_nested_proto( + 9, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[14]) { /* constants */ + /* K0 */ be_nested_str_weak(has), + /* K1 */ be_nested_str_weak(page), + /* K2 */ be_nested_str_weak(int), + /* K3 */ be_nested_str_weak(lvh_page_cur_idx), + /* K4 */ be_nested_str_weak(lvh_pages), + /* K5 */ be_nested_str_weak(contains), + /* K6 */ be_nested_str_weak(lvh_page), + /* K7 */ be_nested_str_weak(find), + /* K8 */ be_nested_str_weak(id), + /* K9 */ be_const_int(0), + /* K10 */ be_nested_str_weak(get_page_cur), + /* K11 */ be_nested_str_weak(prev), + /* K12 */ be_nested_str_weak(next), + /* K13 */ be_nested_str_weak(back), + }), + be_str_weak(parse_page), + &be_const_str_solidified, + ( &(const binstruction[54]) { /* code */ + 0x8C080300, // 0000 GETMET R2 R1 K0 + 0x58100001, // 0001 LDCONST R4 K1 + 0x7C080400, // 0002 CALL R2 2 + 0x780A0030, // 0003 JMPF R2 #0035 + 0x60080004, // 0004 GETGBL R2 G4 + 0x940C0301, // 0005 GETIDX R3 R1 K1 + 0x7C080200, // 0006 CALL R2 1 + 0x1C080502, // 0007 EQ R2 R2 K2 + 0x780A002B, // 0008 JMPF R2 #0035 + 0x60080009, // 0009 GETGBL R2 G9 + 0x940C0301, // 000A GETIDX R3 R1 K1 + 0x7C080200, // 000B CALL R2 1 + 0x90020602, // 000C SETMBR R0 K3 R2 + 0x880C0104, // 000D GETMBR R3 R0 K4 + 0x8C0C0705, // 000E GETMET R3 R3 K5 + 0x5C140400, // 000F MOVE R5 R2 + 0x7C0C0400, // 0010 CALL R3 2 + 0x740E0006, // 0011 JMPT R3 #0019 + 0x880C0106, // 0012 GETMBR R3 R0 K6 + 0x88100104, // 0013 GETMBR R4 R0 K4 + 0x5C140600, // 0014 MOVE R5 R3 + 0x5C180400, // 0015 MOVE R6 R2 + 0x5C1C0000, // 0016 MOVE R7 R0 + 0x7C140400, // 0017 CALL R5 2 + 0x98100405, // 0018 SETIDX R4 R2 R5 + 0x8C0C0307, // 0019 GETMET R3 R1 K7 + 0x58140008, // 001A LDCONST R5 K8 + 0x7C0C0400, // 001B CALL R3 2 + 0x1C0C0709, // 001C EQ R3 R3 K9 + 0x780E0016, // 001D JMPF R3 #0035 + 0x8C0C010A, // 001E GETMET R3 R0 K10 + 0x7C0C0200, // 001F CALL R3 1 + 0x60100009, // 0020 GETGBL R4 G9 + 0x8C140307, // 0021 GETMET R5 R1 K7 + 0x581C000B, // 0022 LDCONST R7 K11 + 0x4C200000, // 0023 LDNIL R8 + 0x7C140600, // 0024 CALL R5 3 + 0x7C100200, // 0025 CALL R4 1 + 0x900E1604, // 0026 SETMBR R3 K11 R4 + 0x60100009, // 0027 GETGBL R4 G9 + 0x8C140307, // 0028 GETMET R5 R1 K7 + 0x581C000C, // 0029 LDCONST R7 K12 + 0x4C200000, // 002A LDNIL R8 + 0x7C140600, // 002B CALL R5 3 + 0x7C100200, // 002C CALL R4 1 + 0x900E1804, // 002D SETMBR R3 K12 R4 + 0x60100009, // 002E GETGBL R4 G9 + 0x8C140307, // 002F GETMET R5 R1 K7 + 0x581C000D, // 0030 LDCONST R7 K13 + 0x4C200000, // 0031 LDNIL R8 + 0x7C140600, // 0032 CALL R5 3 + 0x7C100200, // 0033 CALL R4 1 + 0x900E1A04, // 0034 SETMBR R3 K13 R4 + 0x80000000, // 0035 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: _load +********************************************************************/ +be_local_closure(HASPmota__load, /* name */ + be_nested_proto( + 14, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[17]) { /* constants */ + /* K0 */ be_nested_str_weak(string), + /* K1 */ be_nested_str_weak(json), + /* K2 */ be_nested_str_weak(lvh_page_cur_idx), + /* K3 */ be_const_int(1), + /* K4 */ be_nested_str_weak(lvh_page), + /* K5 */ be_nested_str_weak(lvh_pages), + /* K6 */ be_nested_str_weak(r), + /* K7 */ be_nested_str_weak(read), + /* K8 */ be_nested_str_weak(close), + /* K9 */ be_nested_str_weak(split), + /* K10 */ be_nested_str_weak(_X0A), + /* K11 */ be_const_int(0), + /* K12 */ be_nested_str_weak(load), + /* K13 */ be_nested_str_weak(instance), + /* K14 */ be_nested_str_weak(parse_page), + /* K15 */ be_nested_str_weak(parse_obj), + /* K16 */ be_nested_str_weak(remove), + }), + be_str_weak(_load), + &be_const_str_solidified, + ( &(const binstruction[54]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0xA40E0200, // 0001 IMPORT R3 K1 + 0x90020503, // 0002 SETMBR R0 K2 K3 + 0x88100104, // 0003 GETMBR R4 R0 K4 + 0x88140105, // 0004 GETMBR R5 R0 K5 + 0x5C180800, // 0005 MOVE R6 R4 + 0x581C0003, // 0006 LDCONST R7 K3 + 0x5C200000, // 0007 MOVE R8 R0 + 0x7C180400, // 0008 CALL R6 2 + 0x98160606, // 0009 SETIDX R5 K3 R6 + 0x60140011, // 000A GETGBL R5 G17 + 0x5C180200, // 000B MOVE R6 R1 + 0x581C0006, // 000C LDCONST R7 K6 + 0x7C140400, // 000D CALL R5 2 + 0x8C180B07, // 000E GETMET R6 R5 K7 + 0x7C180200, // 000F CALL R6 1 + 0x8C1C0B08, // 0010 GETMET R7 R5 K8 + 0x7C1C0200, // 0011 CALL R7 1 + 0x8C1C0509, // 0012 GETMET R7 R2 K9 + 0x5C240C00, // 0013 MOVE R9 R6 + 0x5828000A, // 0014 LDCONST R10 K10 + 0x7C1C0600, // 0015 CALL R7 3 + 0x4C140000, // 0016 LDNIL R5 + 0x4C180000, // 0017 LDNIL R6 + 0x6020000C, // 0018 GETGBL R8 G12 + 0x5C240E00, // 0019 MOVE R9 R7 + 0x7C200200, // 001A CALL R8 1 + 0x2420110B, // 001B GT R8 R8 K11 + 0x78220015, // 001C JMPF R8 #0033 + 0x8C20070C, // 001D GETMET R8 R3 K12 + 0x94280F0B, // 001E GETIDX R10 R7 K11 + 0x7C200400, // 001F CALL R8 2 + 0x60240004, // 0020 GETGBL R9 G4 + 0x5C281000, // 0021 MOVE R10 R8 + 0x7C240200, // 0022 CALL R9 1 + 0x1C24130D, // 0023 EQ R9 R9 K13 + 0x78260008, // 0024 JMPF R9 #002E + 0x8C24010E, // 0025 GETMET R9 R0 K14 + 0x5C2C1000, // 0026 MOVE R11 R8 + 0x7C240400, // 0027 CALL R9 2 + 0x8C24010F, // 0028 GETMET R9 R0 K15 + 0x5C2C1000, // 0029 MOVE R11 R8 + 0x88300105, // 002A GETMBR R12 R0 K5 + 0x88340102, // 002B GETMBR R13 R0 K2 + 0x9430180D, // 002C GETIDX R12 R12 R13 + 0x7C240600, // 002D CALL R9 3 + 0x4C200000, // 002E LDNIL R8 + 0x8C240F10, // 002F GETMET R9 R7 K16 + 0x582C000B, // 0030 LDCONST R11 K11 + 0x7C240400, // 0031 CALL R9 2 + 0x7001FFE4, // 0032 JMP #0018 + 0x4C1C0000, // 0033 LDNIL R7 + 0x90020503, // 0034 SETMBR R0 K2 K3 + 0x80000000, // 0035 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: get_page_cur ********************************************************************/ @@ -6557,6 +7030,53 @@ be_local_closure(HASPmota_get_page_cur, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: deinit +********************************************************************/ +be_local_closure(HASPmota_deinit, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(_val_rule), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(remove_rule), + /* K3 */ be_nested_str_weak(_text_rule), + }), + be_str_weak(deinit), + &be_const_str_solidified, + ( &(const binstruction[19]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x20040202, // 0002 NE R1 R1 R2 + 0x78060004, // 0003 JMPF R1 #0009 + 0xB8060200, // 0004 GETNGBL R1 K1 + 0x8C040302, // 0005 GETMET R1 R1 K2 + 0x880C0100, // 0006 GETMBR R3 R0 K0 + 0x5C100000, // 0007 MOVE R4 R0 + 0x7C040600, // 0008 CALL R1 3 + 0x88040103, // 0009 GETMBR R1 R0 K3 + 0x4C080000, // 000A LDNIL R2 + 0x20040202, // 000B NE R1 R1 R2 + 0x78060004, // 000C JMPF R1 #0012 + 0xB8060200, // 000D GETNGBL R1 K1 + 0x8C040302, // 000E GETMET R1 R1 K2 + 0x880C0103, // 000F GETMBR R3 R0 K3 + 0x5C100000, // 0010 MOVE R4 R0 + 0x7C040600, // 0011 CALL R1 3 + 0x80000000, // 0012 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: start ********************************************************************/ @@ -6753,221 +7273,6 @@ be_local_closure(HASPmota_init, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: register_event -********************************************************************/ -be_local_closure(HASPmota_register_event, /* name */ - be_nested_proto( - 13, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 1]) { - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(event_dispatch), - }), - be_str_weak(_X3Clambda_X3E), - &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x68040000, // 0000 GETUPV R1 U0 - 0x8C040300, // 0001 GETMET R1 R1 K0 - 0x5C0C0000, // 0002 MOVE R3 R0 - 0x7C040400, // 0003 CALL R1 2 - 0x80040200, // 0004 RET 1 R1 - }) - ), - }), - 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_nested_str_weak(cb), - /* K1 */ be_nested_str_weak(introspect), - /* K2 */ be_nested_str_weak(event_cb), - /* K3 */ be_nested_str_weak(gen_cb), - /* K4 */ be_nested_str_weak(_lv_obj), - /* K5 */ be_nested_str_weak(add_event_cb), - /* K6 */ be_nested_str_weak(toptr), - }), - be_str_weak(register_event), - &be_const_str_solidified, - ( &(const binstruction[20]) { /* code */ - 0xA40E0000, // 0000 IMPORT R3 K0 - 0xA4120200, // 0001 IMPORT R4 K1 - 0x88140102, // 0002 GETMBR R5 R0 K2 - 0x4C180000, // 0003 LDNIL R6 - 0x1C140A06, // 0004 EQ R5 R5 R6 - 0x78160003, // 0005 JMPF R5 #000A - 0x8C140703, // 0006 GETMET R5 R3 K3 - 0x841C0000, // 0007 CLOSURE R7 P0 - 0x7C140400, // 0008 CALL R5 2 - 0x90020405, // 0009 SETMBR R0 K2 R5 - 0x88140304, // 000A GETMBR R5 R1 K4 - 0x8C180B05, // 000B GETMET R6 R5 K5 - 0x88200102, // 000C GETMBR R8 R0 K2 - 0x5C240400, // 000D MOVE R9 R2 - 0x8C280906, // 000E GETMET R10 R4 K6 - 0x5C300200, // 000F MOVE R12 R1 - 0x7C280400, // 0010 CALL R10 2 - 0x7C180800, // 0011 CALL R6 4 - 0xA0000000, // 0012 CLOSE R0 - 0x80000000, // 0013 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: parse_page -********************************************************************/ -be_local_closure(HASPmota_parse_page, /* name */ - be_nested_proto( - 9, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ - /* K0 */ be_nested_str_weak(has), - /* K1 */ be_nested_str_weak(page), - /* K2 */ be_nested_str_weak(int), - /* K3 */ be_nested_str_weak(lvh_page_cur_idx), - /* K4 */ be_nested_str_weak(lvh_pages), - /* K5 */ be_nested_str_weak(contains), - /* K6 */ be_nested_str_weak(lvh_page), - /* K7 */ be_nested_str_weak(find), - /* K8 */ be_nested_str_weak(id), - /* K9 */ be_const_int(0), - /* K10 */ be_nested_str_weak(get_page_cur), - /* K11 */ be_nested_str_weak(prev), - /* K12 */ be_nested_str_weak(next), - /* K13 */ be_nested_str_weak(back), - }), - be_str_weak(parse_page), - &be_const_str_solidified, - ( &(const binstruction[54]) { /* code */ - 0x8C080300, // 0000 GETMET R2 R1 K0 - 0x58100001, // 0001 LDCONST R4 K1 - 0x7C080400, // 0002 CALL R2 2 - 0x780A0030, // 0003 JMPF R2 #0035 - 0x60080004, // 0004 GETGBL R2 G4 - 0x940C0301, // 0005 GETIDX R3 R1 K1 - 0x7C080200, // 0006 CALL R2 1 - 0x1C080502, // 0007 EQ R2 R2 K2 - 0x780A002B, // 0008 JMPF R2 #0035 - 0x60080009, // 0009 GETGBL R2 G9 - 0x940C0301, // 000A GETIDX R3 R1 K1 - 0x7C080200, // 000B CALL R2 1 - 0x90020602, // 000C SETMBR R0 K3 R2 - 0x880C0104, // 000D GETMBR R3 R0 K4 - 0x8C0C0705, // 000E GETMET R3 R3 K5 - 0x5C140400, // 000F MOVE R5 R2 - 0x7C0C0400, // 0010 CALL R3 2 - 0x740E0006, // 0011 JMPT R3 #0019 - 0x880C0106, // 0012 GETMBR R3 R0 K6 - 0x88100104, // 0013 GETMBR R4 R0 K4 - 0x5C140600, // 0014 MOVE R5 R3 - 0x5C180400, // 0015 MOVE R6 R2 - 0x5C1C0000, // 0016 MOVE R7 R0 - 0x7C140400, // 0017 CALL R5 2 - 0x98100405, // 0018 SETIDX R4 R2 R5 - 0x8C0C0307, // 0019 GETMET R3 R1 K7 - 0x58140008, // 001A LDCONST R5 K8 - 0x7C0C0400, // 001B CALL R3 2 - 0x1C0C0709, // 001C EQ R3 R3 K9 - 0x780E0016, // 001D JMPF R3 #0035 - 0x8C0C010A, // 001E GETMET R3 R0 K10 - 0x7C0C0200, // 001F CALL R3 1 - 0x60100009, // 0020 GETGBL R4 G9 - 0x8C140307, // 0021 GETMET R5 R1 K7 - 0x581C000B, // 0022 LDCONST R7 K11 - 0x4C200000, // 0023 LDNIL R8 - 0x7C140600, // 0024 CALL R5 3 - 0x7C100200, // 0025 CALL R4 1 - 0x900E1604, // 0026 SETMBR R3 K11 R4 - 0x60100009, // 0027 GETGBL R4 G9 - 0x8C140307, // 0028 GETMET R5 R1 K7 - 0x581C000C, // 0029 LDCONST R7 K12 - 0x4C200000, // 002A LDNIL R8 - 0x7C140600, // 002B CALL R5 3 - 0x7C100200, // 002C CALL R4 1 - 0x900E1804, // 002D SETMBR R3 K12 R4 - 0x60100009, // 002E GETGBL R4 G9 - 0x8C140307, // 002F GETMET R5 R1 K7 - 0x581C000D, // 0030 LDCONST R7 K13 - 0x4C200000, // 0031 LDNIL R8 - 0x7C140600, // 0032 CALL R5 3 - 0x7C100200, // 0033 CALL R4 1 - 0x900E1A04, // 0034 SETMBR R3 K13 R4 - 0x80000000, // 0035 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: deinit -********************************************************************/ -be_local_closure(HASPmota_deinit, /* name */ - be_nested_proto( - 5, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(_val_rule), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(remove_rule), - /* K3 */ be_nested_str_weak(_text_rule), - }), - be_str_weak(deinit), - &be_const_str_solidified, - ( &(const binstruction[19]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x4C080000, // 0001 LDNIL R2 - 0x20040202, // 0002 NE R1 R1 R2 - 0x78060004, // 0003 JMPF R1 #0009 - 0xB8060200, // 0004 GETNGBL R1 K1 - 0x8C040302, // 0005 GETMET R1 R1 K2 - 0x880C0100, // 0006 GETMBR R3 R0 K0 - 0x5C100000, // 0007 MOVE R4 R0 - 0x7C040600, // 0008 CALL R1 3 - 0x88040103, // 0009 GETMBR R1 R0 K3 - 0x4C080000, // 000A LDNIL R2 - 0x20040202, // 000B NE R1 R1 R2 - 0x78060004, // 000C JMPF R1 #0012 - 0xB8060200, // 000D GETNGBL R1 K1 - 0x8C040302, // 000E GETMET R1 R1 K2 - 0x880C0103, // 000F GETMBR R3 R0 K3 - 0x5C100000, // 0010 MOVE R4 R0 - 0x7C040600, // 0011 CALL R1 3 - 0x80000000, // 0012 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: page_dir_to ********************************************************************/ @@ -7029,213 +7334,6 @@ be_local_closure(HASPmota_page_dir_to, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: _load -********************************************************************/ -be_local_closure(HASPmota__load, /* name */ - be_nested_proto( - 14, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[17]) { /* constants */ - /* K0 */ be_nested_str_weak(string), - /* K1 */ be_nested_str_weak(json), - /* K2 */ be_nested_str_weak(lvh_page_cur_idx), - /* K3 */ be_const_int(1), - /* K4 */ be_nested_str_weak(lvh_page), - /* K5 */ be_nested_str_weak(lvh_pages), - /* K6 */ be_nested_str_weak(r), - /* K7 */ be_nested_str_weak(read), - /* K8 */ be_nested_str_weak(close), - /* K9 */ be_nested_str_weak(split), - /* K10 */ be_nested_str_weak(_X0A), - /* K11 */ be_const_int(0), - /* K12 */ be_nested_str_weak(load), - /* K13 */ be_nested_str_weak(instance), - /* K14 */ be_nested_str_weak(parse_page), - /* K15 */ be_nested_str_weak(parse_obj), - /* K16 */ be_nested_str_weak(remove), - }), - be_str_weak(_load), - &be_const_str_solidified, - ( &(const binstruction[54]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0xA40E0200, // 0001 IMPORT R3 K1 - 0x90020503, // 0002 SETMBR R0 K2 K3 - 0x88100104, // 0003 GETMBR R4 R0 K4 - 0x88140105, // 0004 GETMBR R5 R0 K5 - 0x5C180800, // 0005 MOVE R6 R4 - 0x581C0003, // 0006 LDCONST R7 K3 - 0x5C200000, // 0007 MOVE R8 R0 - 0x7C180400, // 0008 CALL R6 2 - 0x98160606, // 0009 SETIDX R5 K3 R6 - 0x60140011, // 000A GETGBL R5 G17 - 0x5C180200, // 000B MOVE R6 R1 - 0x581C0006, // 000C LDCONST R7 K6 - 0x7C140400, // 000D CALL R5 2 - 0x8C180B07, // 000E GETMET R6 R5 K7 - 0x7C180200, // 000F CALL R6 1 - 0x8C1C0B08, // 0010 GETMET R7 R5 K8 - 0x7C1C0200, // 0011 CALL R7 1 - 0x8C1C0509, // 0012 GETMET R7 R2 K9 - 0x5C240C00, // 0013 MOVE R9 R6 - 0x5828000A, // 0014 LDCONST R10 K10 - 0x7C1C0600, // 0015 CALL R7 3 - 0x4C140000, // 0016 LDNIL R5 - 0x4C180000, // 0017 LDNIL R6 - 0x6020000C, // 0018 GETGBL R8 G12 - 0x5C240E00, // 0019 MOVE R9 R7 - 0x7C200200, // 001A CALL R8 1 - 0x2420110B, // 001B GT R8 R8 K11 - 0x78220015, // 001C JMPF R8 #0033 - 0x8C20070C, // 001D GETMET R8 R3 K12 - 0x94280F0B, // 001E GETIDX R10 R7 K11 - 0x7C200400, // 001F CALL R8 2 - 0x60240004, // 0020 GETGBL R9 G4 - 0x5C281000, // 0021 MOVE R10 R8 - 0x7C240200, // 0022 CALL R9 1 - 0x1C24130D, // 0023 EQ R9 R9 K13 - 0x78260008, // 0024 JMPF R9 #002E - 0x8C24010E, // 0025 GETMET R9 R0 K14 - 0x5C2C1000, // 0026 MOVE R11 R8 - 0x7C240400, // 0027 CALL R9 2 - 0x8C24010F, // 0028 GETMET R9 R0 K15 - 0x5C2C1000, // 0029 MOVE R11 R8 - 0x88300105, // 002A GETMBR R12 R0 K5 - 0x88340102, // 002B GETMBR R13 R0 K2 - 0x9430180D, // 002C GETIDX R12 R12 R13 - 0x7C240600, // 002D CALL R9 3 - 0x4C200000, // 002E LDNIL R8 - 0x8C240F10, // 002F GETMET R9 R7 K16 - 0x582C000B, // 0030 LDCONST R11 K11 - 0x7C240400, // 0031 CALL R9 2 - 0x7001FFE4, // 0032 JMP #0018 - 0x4C1C0000, // 0033 LDNIL R7 - 0x90020503, // 0034 SETMBR R0 K2 K3 - 0x80000000, // 0035 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: parse -********************************************************************/ -be_local_closure(HASPmota_parse, /* name */ - be_nested_proto( - 9, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(json), - /* K1 */ be_nested_str_weak(load), - /* K2 */ be_nested_str_weak(instance), - /* K3 */ be_nested_str_weak(parse_page), - /* K4 */ be_nested_str_weak(parse_obj), - /* K5 */ be_nested_str_weak(lvh_pages), - /* K6 */ be_nested_str_weak(lvh_page_cur_idx), - /* K7 */ be_nested_str_weak(value_error), - /* K8 */ be_nested_str_weak(unable_X20to_X20parse_X20JSON_X20line), - }), - be_str_weak(parse), - &be_const_str_solidified, - ( &(const binstruction[21]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0x8C0C0501, // 0001 GETMET R3 R2 K1 - 0x5C140200, // 0002 MOVE R5 R1 - 0x7C0C0400, // 0003 CALL R3 2 - 0x60100004, // 0004 GETGBL R4 G4 - 0x5C140600, // 0005 MOVE R5 R3 - 0x7C100200, // 0006 CALL R4 1 - 0x1C100902, // 0007 EQ R4 R4 K2 - 0x78120009, // 0008 JMPF R4 #0013 - 0x8C100103, // 0009 GETMET R4 R0 K3 - 0x5C180600, // 000A MOVE R6 R3 - 0x7C100400, // 000B CALL R4 2 - 0x8C100104, // 000C GETMET R4 R0 K4 - 0x5C180600, // 000D MOVE R6 R3 - 0x881C0105, // 000E GETMBR R7 R0 K5 - 0x88200106, // 000F GETMBR R8 R0 K6 - 0x941C0E08, // 0010 GETIDX R7 R7 R8 - 0x7C100600, // 0011 CALL R4 3 - 0x70020000, // 0012 JMP #0014 - 0xB0060F08, // 0013 RAISE 1 K7 K8 - 0x80000000, // 0014 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: sort -********************************************************************/ -be_local_closure(HASPmota_sort, /* name */ - be_nested_proto( - 7, /* nstack */ - 1, /* argc */ - 4, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_const_class(be_class_HASPmota), - /* K1 */ be_const_int(1), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(sort), - &be_const_str_solidified, - ( &(const binstruction[30]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x60080010, // 0001 GETGBL R2 G16 - 0x600C000C, // 0002 GETGBL R3 G12 - 0x5C100000, // 0003 MOVE R4 R0 - 0x7C0C0200, // 0004 CALL R3 1 - 0x040C0701, // 0005 SUB R3 R3 K1 - 0x400E0203, // 0006 CONNECT R3 K1 R3 - 0x7C080200, // 0007 CALL R2 1 - 0xA8020010, // 0008 EXBLK 0 #001A - 0x5C0C0400, // 0009 MOVE R3 R2 - 0x7C0C0000, // 000A CALL R3 0 - 0x94100003, // 000B GETIDX R4 R0 R3 - 0x5C140600, // 000C MOVE R5 R3 - 0x24180B02, // 000D GT R6 R5 K2 - 0x781A0008, // 000E JMPF R6 #0018 - 0x04180B01, // 000F SUB R6 R5 K1 - 0x94180006, // 0010 GETIDX R6 R0 R6 - 0x24180C04, // 0011 GT R6 R6 R4 - 0x781A0004, // 0012 JMPF R6 #0018 - 0x04180B01, // 0013 SUB R6 R5 K1 - 0x94180006, // 0014 GETIDX R6 R0 R6 - 0x98000A06, // 0015 SETIDX R0 R5 R6 - 0x04140B01, // 0016 SUB R5 R5 K1 - 0x7001FFF4, // 0017 JMP #000D - 0x98000A04, // 0018 SETIDX R0 R5 R4 - 0x7001FFEE, // 0019 JMP #0009 - 0x58080003, // 001A LDCONST R2 K3 - 0xAC080200, // 001B CATCH R2 1 0 - 0xB0080000, // 001C RAISE 2 R0 R0 - 0x80040000, // 001D RET 1 R0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: parse_obj ********************************************************************/ @@ -7507,127 +7605,58 @@ be_local_closure(HASPmota_parse_obj, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: event_dispatch -********************************************************************/ -be_local_closure(HASPmota_event_dispatch, /* name */ - be_nested_proto( - 9, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ - /* K0 */ be_nested_str_weak(introspect), - /* K1 */ be_nested_str_weak(toptr), - /* K2 */ be_nested_str_weak(event), - /* K3 */ be_nested_str_weak(_change_buffer), - /* K4 */ be_nested_str_weak(lv), - /* K5 */ be_nested_str_weak(lv_event), - /* K6 */ be_nested_str_weak(user_data), - /* K7 */ be_const_int(0), - /* K8 */ be_nested_str_weak(fromptr), - /* K9 */ be_nested_str_weak(instance), - /* K10 */ be_nested_str_weak(event_cb), - }), - be_str_weak(event_dispatch), - &be_const_str_solidified, - ( &(const binstruction[35]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0x8C0C0501, // 0001 GETMET R3 R2 K1 - 0x5C140200, // 0002 MOVE R5 R1 - 0x7C0C0400, // 0003 CALL R3 2 - 0x88100102, // 0004 GETMBR R4 R0 K2 - 0x78120004, // 0005 JMPF R4 #000B - 0x88100102, // 0006 GETMBR R4 R0 K2 - 0x8C100903, // 0007 GETMET R4 R4 K3 - 0x5C180600, // 0008 MOVE R6 R3 - 0x7C100400, // 0009 CALL R4 2 - 0x70020004, // 000A JMP #0010 - 0xB8120800, // 000B GETNGBL R4 K4 - 0x8C100905, // 000C GETMET R4 R4 K5 - 0x5C180600, // 000D MOVE R6 R3 - 0x7C100400, // 000E CALL R4 2 - 0x90020404, // 000F SETMBR R0 K2 R4 - 0x88100102, // 0010 GETMBR R4 R0 K2 - 0x88100906, // 0011 GETMBR R4 R4 K6 - 0x60140009, // 0012 GETGBL R5 G9 - 0x5C180800, // 0013 MOVE R6 R4 - 0x7C140200, // 0014 CALL R5 1 - 0x20140B07, // 0015 NE R5 R5 K7 - 0x7816000A, // 0016 JMPF R5 #0022 - 0x8C140508, // 0017 GETMET R5 R2 K8 - 0x5C1C0800, // 0018 MOVE R7 R4 - 0x7C140400, // 0019 CALL R5 2 - 0x60180004, // 001A GETGBL R6 G4 - 0x5C1C0A00, // 001B MOVE R7 R5 - 0x7C180200, // 001C CALL R6 1 - 0x1C180D09, // 001D EQ R6 R6 K9 - 0x781A0002, // 001E JMPF R6 #0022 - 0x8C180B0A, // 001F GETMET R6 R5 K10 - 0x88200102, // 0020 GETMBR R8 R0 K2 - 0x7C180400, // 0021 CALL R6 2 - 0x80000000, // 0022 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified class: HASPmota ********************************************************************/ be_local_class(HASPmota, 10, NULL, - be_nested_map(43, + be_nested_map(44, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(lvh_textarea, 41), be_const_class(be_class_lvh_textarea) }, - { be_const_key_weak(scr, -1), be_const_var(3) }, - { be_const_key_weak(event_dispatch, 16), be_const_closure(HASPmota_event_dispatch_closure) }, - { be_const_key_weak(lvh_bar, -1), be_const_class(be_class_lvh_bar) }, - { be_const_key_weak(lvh_img, -1), be_const_class(be_class_lvh_img) }, { be_const_key_weak(event, -1), be_const_var(8) }, - { be_const_key_weak(do_action, 33), be_const_closure(HASPmota_do_action_closure) }, - { be_const_key_weak(pages_list_sorted, -1), be_const_closure(HASPmota_pages_list_sorted_closure) }, - { be_const_key_weak(lvh_btnmatrix, 42), be_const_class(be_class_lvh_btnmatrix) }, - { be_const_key_weak(start, -1), be_const_closure(HASPmota_start_closure) }, - { be_const_key_weak(init, 5), be_const_closure(HASPmota_init_closure) }, + { be_const_key_weak(parse_obj, 4), be_const_closure(HASPmota_parse_obj_closure) }, { be_const_key_weak(lvh_scr, -1), be_const_class(be_class_lvh_scr) }, - { be_const_key_weak(parse_page, -1), be_const_closure(HASPmota_parse_page_closure) }, - { be_const_key_weak(register_event, 24), be_const_closure(HASPmota_register_event_closure) }, - { be_const_key_weak(lvh_roller, 34), be_const_class(be_class_lvh_roller) }, - { be_const_key_weak(lvh_page, 11), be_const_class(be_class_lvh_page) }, - { be_const_key_weak(lvh_page_cur_idx, -1), be_const_var(6) }, - { be_const_key_weak(lvh_arc, 12), be_const_class(be_class_lvh_arc) }, - { be_const_key_weak(hres, 38), be_const_var(1) }, - { be_const_key_weak(dark, -1), be_const_var(0) }, - { be_const_key_weak(lvh_label, 37), be_const_class(be_class_lvh_label) }, - { be_const_key_weak(deinit, 14), be_const_closure(HASPmota_deinit_closure) }, - { be_const_key_weak(page_dir_to, -1), be_const_closure(HASPmota_page_dir_to_closure) }, - { be_const_key_weak(parse_obj, -1), be_const_closure(HASPmota_parse_obj_closure) }, - { be_const_key_weak(lvh_spinner, -1), be_const_class(be_class_lvh_spinner) }, - { be_const_key_weak(_load, -1), be_const_closure(HASPmota__load_closure) }, - { be_const_key_weak(lvh_qrcode, -1), be_const_class(be_class_lvh_qrcode) }, - { be_const_key_weak(parse, -1), be_const_closure(HASPmota_parse_closure) }, - { be_const_key_weak(lvh_pages, 2), be_const_var(5) }, - { be_const_key_weak(lvh_line, -1), be_const_class(be_class_lvh_line) }, + { be_const_key_weak(do_action, 16), be_const_closure(HASPmota_do_action_closure) }, { be_const_key_weak(lvh_switch, -1), be_const_class(be_class_lvh_switch) }, - { be_const_key_weak(re_page_target, -1), be_const_var(7) }, - { be_const_key_weak(r16, -1), be_const_var(4) }, - { be_const_key_weak(def_templ_name, -1), be_nested_str_weak(pages_X2Ejsonl) }, - { be_const_key_weak(lvh_obj, 19), be_const_class(be_class_lvh_obj) }, - { be_const_key_weak(sort, 23), be_const_static_closure(HASPmota_sort_closure) }, - { be_const_key_weak(lvh_dropdown, -1), be_const_class(be_class_lvh_dropdown) }, - { be_const_key_weak(lvh_checkbox, -1), be_const_class(be_class_lvh_checkbox) }, - { be_const_key_weak(lvh_slider, -1), be_const_class(be_class_lvh_slider) }, - { be_const_key_weak(vres, -1), be_const_var(2) }, - { be_const_key_weak(lvh_btn, -1), be_const_class(be_class_lvh_btn) }, + { be_const_key_weak(lvh_page, 9), be_const_class(be_class_lvh_page) }, + { be_const_key_weak(lvh_obj, -1), be_const_class(be_class_lvh_obj) }, + { be_const_key_weak(register_event, -1), be_const_closure(HASPmota_register_event_closure) }, + { be_const_key_weak(parse, 35), be_const_closure(HASPmota_parse_closure) }, { be_const_key_weak(event_cb, -1), be_const_var(9) }, - { be_const_key_weak(get_page_cur, -1), be_const_closure(HASPmota_get_page_cur_closure) }, + { be_const_key_weak(event_dispatch, -1), be_const_closure(HASPmota_event_dispatch_closure) }, + { be_const_key_weak(lvh_dropdown, 6), be_const_class(be_class_lvh_dropdown) }, + { be_const_key_weak(pages_list_sorted, -1), be_const_closure(HASPmota_pages_list_sorted_closure) }, + { be_const_key_weak(dark, -1), be_const_var(0) }, + { be_const_key_weak(lvh_roller, 21), be_const_class(be_class_lvh_roller) }, + { be_const_key_weak(lvh_btnmatrix, 23), be_const_class(be_class_lvh_btnmatrix) }, + { be_const_key_weak(hres, -1), be_const_var(1) }, + { be_const_key_weak(sort, -1), be_const_static_closure(HASPmota_sort_closure) }, + { be_const_key_weak(parse_page, 25), be_const_closure(HASPmota_parse_page_closure) }, + { be_const_key_weak(lvh_spinner, -1), be_const_class(be_class_lvh_spinner) }, + { be_const_key_weak(lvh_btn, 39), be_const_class(be_class_lvh_btn) }, + { be_const_key_weak(r16, -1), be_const_var(4) }, + { be_const_key_weak(page_show, 20), be_const_closure(HASPmota_page_show_closure) }, + { be_const_key_weak(scr, 41), be_const_var(3) }, + { be_const_key_weak(deinit, -1), be_const_closure(HASPmota_deinit_closure) }, + { be_const_key_weak(lvh_arc, -1), be_const_class(be_class_lvh_arc) }, + { be_const_key_weak(lvh_pages, -1), be_const_var(5) }, + { be_const_key_weak(start, 28), be_const_closure(HASPmota_start_closure) }, + { be_const_key_weak(lvh_bar, -1), be_const_class(be_class_lvh_bar) }, + { be_const_key_weak(vres, -1), be_const_var(2) }, + { be_const_key_weak(lvh_textarea, -1), be_const_class(be_class_lvh_textarea) }, + { be_const_key_weak(init, -1), be_const_closure(HASPmota_init_closure) }, + { be_const_key_weak(lvh_line, 30), be_const_class(be_class_lvh_line) }, + { be_const_key_weak(def_templ_name, -1), be_nested_str_weak(pages_X2Ejsonl) }, + { be_const_key_weak(re_page_target, -1), be_const_var(7) }, + { be_const_key_weak(lvh_qrcode, -1), be_const_class(be_class_lvh_qrcode) }, + { be_const_key_weak(lvh_page_cur_idx, -1), be_const_var(6) }, + { be_const_key_weak(lvh_img, -1), be_const_class(be_class_lvh_img) }, + { be_const_key_weak(page_dir_to, -1), be_const_closure(HASPmota_page_dir_to_closure) }, + { be_const_key_weak(_load, -1), be_const_closure(HASPmota__load_closure) }, + { be_const_key_weak(lvh_label, -1), be_const_class(be_class_lvh_label) }, + { be_const_key_weak(lvh_checkbox, -1), be_const_class(be_class_lvh_checkbox) }, + { be_const_key_weak(get_page_cur, 1), be_const_closure(HASPmota_get_page_cur_closure) }, + { be_const_key_weak(lvh_slider, 0), be_const_class(be_class_lvh_slider) }, })), be_str_weak(HASPmota) ); diff --git a/tasmota/berry/haspmota_src/haspmota_core/haspmota.be b/tasmota/berry/haspmota_src/haspmota_core/haspmota.be index a960af47b..2352c3128 100644 --- a/tasmota/berry/haspmota_src/haspmota_core/haspmota.be +++ b/tasmota/berry/haspmota_src/haspmota_core/haspmota.be @@ -1740,12 +1740,19 @@ class HASPmota #==================================================================== def do_action(lvh_object, event_code) if event_code != lv.EVENT_CLICKED return end - var action = lvh_object._action - var cur_page = self.lvh_pages[self.lvh_page_cur_idx] - # print("do_action","lvh_object",lvh_object,"action",action,"cur_page",cur_page,self.lvh_page_cur_idx) + self.page_show(lvh_object._action) + end + #==================================================================== + # Execute a page changing action from string `action` + # + # Arg1 `action` can be `prev`, `next`, `back` or `p` + # Returns: nil + #==================================================================== + def page_show(action) # action can be `prev`, `next`, `back`, or `p` like `p1` var to_page = nil + var cur_page = self.lvh_pages[self.lvh_page_cur_idx] var sorted_pages_list = self.pages_list_sorted(self.lvh_page_cur_idx) if size(sorted_pages_list) <= 1 return end # if only 1 page, do nothing # handle prev/next/back values From 6a8435b7313fee41bfdb497984186b63bdcb426b Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Fri, 29 Dec 2023 10:17:10 +0100 Subject: [PATCH 059/303] Berry added `introspect.set()` for class attributes (#20339) --- CHANGELOG.md | 1 + lib/libesp32/berry/src/be_api.c | 4 ++++ lib/libesp32/berry/src/be_introspectlib.c | 2 +- lib/libesp32/berry/tests/introspect.be | 22 ++++++++++++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 759b427a3..d24aea8b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file. - Display of active drivers using command ``status 4`` - ESP32 used UART information - HASPmota added `haspmota.page_show()` to change page +- Berry added `introspect.set()` for class attributes ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds (#20236) diff --git a/lib/libesp32/berry/src/be_api.c b/lib/libesp32/berry/src/be_api.c index ba5b915d2..5cc755929 100644 --- a/lib/libesp32/berry/src/be_api.c +++ b/lib/libesp32/berry/src/be_api.c @@ -643,6 +643,10 @@ BERRY_API bbool be_setmember(bvm *vm, int index, const char *k) bstring *key = be_newstr(vm, k); bmodule *mod = var_toobj(o); return be_module_setmember(vm, mod, key, v); + } else if (var_isclass(o)) { + bstring *key = be_newstr(vm, k); + bclass *cl = var_toobj(o); + return be_class_setmember(vm, cl, key, v); } return bfalse; } diff --git a/lib/libesp32/berry/src/be_introspectlib.c b/lib/libesp32/berry/src/be_introspectlib.c index 4f98f2d94..73e2da466 100644 --- a/lib/libesp32/berry/src/be_introspectlib.c +++ b/lib/libesp32/berry/src/be_introspectlib.c @@ -96,7 +96,7 @@ static int m_findmember(bvm *vm) static int m_setmember(bvm *vm) { int top = be_top(vm); - if (top >= 3 && (be_isinstance(vm, 1) || be_ismodule(vm, 1)) && be_isstring(vm, 2)) { + if (top >= 3 && (be_isinstance(vm, 1) || be_ismodule(vm, 1) || be_isclass(vm, 1)) && be_isstring(vm, 2)) { be_setmember(vm, 1, be_tostring(vm, 2)); be_return(vm); } diff --git a/lib/libesp32/berry/tests/introspect.be b/lib/libesp32/berry/tests/introspect.be index c93033982..1d9c7af29 100644 --- a/lib/libesp32/berry/tests/introspect.be +++ b/lib/libesp32/berry/tests/introspect.be @@ -42,3 +42,25 @@ assert(introspect.name(A) == 'A') assert(introspect.name(A.a) == 'a') assert(introspect.name(A.b) == 'b') assert(introspect.name(A.c) == nil) + +# test introspect get and set +# class and instance +class A + static var a + var b +end + +a = A() +introspect.set(A, "a", 10) +assert(A.a == 10) +assert(introspect.get(A, "a") == 10) + +introspect.set(a, "b", 20) +assert(a.b == 20) +assert(introspect.get(a, "b") == 20) + +# module +m = module('m') +introspect.set(m, 'c', 30) +assert(m.c == 30) +assert(introspect.get(m, 'c') == 30) From 4393327bb9929baae856df3a432073f27ae9ec59 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 29 Dec 2023 22:54:32 +0100 Subject: [PATCH 060/303] Add support negative power on BL0942 using index 5..8 (#20322) --- CHANGELOG.md | 5 +++-- RELEASENOTES.md | 3 +++ tasmota/include/tasmota_template.h | 2 +- .../tasmota_xnrg_energy/xnrg_14_bl09xx.ino | 19 +++++++++++++------ 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d24aea8b2..b34fad6bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,9 @@ All notable changes to this project will be documented in this file. - Matter support for password for remote Tasmota devices (#20296) - Display of active drivers using command ``status 4`` - ESP32 used UART information -- HASPmota added `haspmota.page_show()` to change page -- Berry added `introspect.set()` for class attributes +- HASPmota added `haspmota.page_show()` to change page (#20333) +- Berry added `introspect.set()` for class attributes (#20339) +- Support negative power on BL0942 using index 5..8 (#20322) ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds (#20236) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 9fe82cdde..a526e6cbe 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -122,7 +122,10 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247) - Display of active drivers using command ``status 4`` - NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) +- Support negative power on BL0942 using index 5..8 [#20322](https://github.com/arendst/Tasmota/issues/20322) - ESP32 used UART information +- Berry added `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) +- HASPmota added `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) ### Breaking Changed diff --git a/tasmota/include/tasmota_template.h b/tasmota/include/tasmota_template.h index 63779e918..1d09cb47b 100644 --- a/tasmota/include/tasmota_template.h +++ b/tasmota/include/tasmota_template.h @@ -496,7 +496,7 @@ const char kSensorNamesFixed[] PROGMEM = #define MAX_BP1658CJ_DAT 16 #define MAX_DINGTIAN_SHIFT 4 #define MAX_MAGIC_SWITCH_MODES 2 -#define MAX_BL0942_RX 4 // Baudrates 1 (4800), 2 (9600), 3 (19200), 4 (38400) +#define MAX_BL0942_RX 8 // Baudrates 1/5 (4800), 2/6 (9600), 3/7 (19200), 4/8 (38400), Support Positive values only 1..4, Support also negative values 5..8 const uint16_t kGpioNiceList[] PROGMEM = { GPIO_NONE, // Not used diff --git a/tasmota/tasmota_xnrg_energy/xnrg_14_bl09xx.ino b/tasmota/tasmota_xnrg_energy/xnrg_14_bl09xx.ino index af1f0f6fc..da66a5cf4 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_14_bl09xx.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_14_bl09xx.ino @@ -102,6 +102,7 @@ struct BL09XX { uint8_t address = 0; uint8_t model = 0; uint8_t rx_pin; + bool support_negative = 0; bool received = false; } Bl09XX; @@ -187,11 +188,15 @@ bool Bl09XXDecode42(void) { Bl09XX.voltage = Bl09XX.rx_buffer[6] << 16 | Bl09XX.rx_buffer[5] << 8 | Bl09XX.rx_buffer[4]; // V_RMS unsigned Bl09XX.current[0] = Bl09XX.rx_buffer[3] << 16 | Bl09XX.rx_buffer[2] << 8 | Bl09XX.rx_buffer[1]; // IA_RMS unsigned -// Bl09XX.power[0] = Bl09XX.rx_buffer[12] << 16 | Bl09XX.rx_buffer[11] << 8 | Bl09XX.rx_buffer[10]; // WATT_A signed -// if (bitRead(Bl09XX.power[0], 23)) { Bl09XX.power[0] |= 0xFF000000; } // Extend sign bit - // Above reverted in favour of https://github.com/arendst/Tasmota/issues/15374#issuecomment-1105293179 - int32_t tmp = Bl09XX.rx_buffer[12] << 24 | Bl09XX.rx_buffer[11] << 16 | Bl09XX.rx_buffer[10] << 8; // WATT_A signed - Bl09XX.power[0] = abs(tmp >> 8); + + if (Bl09XX.support_negative) { + Bl09XX.power[0] = Bl09XX.rx_buffer[12] << 16 | Bl09XX.rx_buffer[11] << 8 | Bl09XX.rx_buffer[10]; // WATT_A signed + if (bitRead(Bl09XX.power[0], 23)) { Bl09XX.power[0] |= 0xFF000000; } // Extend sign bit + // Above reverted in favour of https://github.com/arendst/Tasmota/issues/15374#issuecomment-1105293179 + } else { + int32_t tmp = Bl09XX.rx_buffer[12] << 24 | Bl09XX.rx_buffer[11] << 16 | Bl09XX.rx_buffer[10] << 8; // WATT_A signed + Bl09XX.power[0] = abs(tmp >> 8); + } #ifdef DEBUG_BL09XX AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("BL9: U %d, I %d, P %d"), @@ -361,7 +366,9 @@ void Bl09XXPreInit(void) { else if (PinUsed(GPIO_BL0942_RX, GPIO_ANY)) { Bl09XX.model = BL0942_MODEL; Bl09XX.rx_pin = Pin(GPIO_BL0942_RX, GPIO_ANY); - uint32_t baudrate = GetPin(Bl09XX.rx_pin) - AGPIO(GPIO_BL0942_RX); // 0 .. 3 + uint32_t option = GetPin(Bl09XX.rx_pin) - AGPIO(GPIO_BL0942_RX); // 0 .. 7 + Bl09XX.support_negative = (option > 3); // 4 .. 7 + uint32_t baudrate = option & 0x3; // 0 .. 3 and 4 .. 7 Bl09XX.baudrate <<= baudrate; // Support 1 (4800), 2 (9600), 3 (19200), 4 (38400) } if (Bl09XX.model != BL09XX_MODEL) { From a0f6b7f1a31f39703262d00a99c488c298b78351 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Fri, 29 Dec 2023 23:10:26 +0100 Subject: [PATCH 061/303] Relax checks of Partition Wizard for newest Shelly (#20349) --- CHANGELOG.md | 1 + tasmota/berry/modules/Partition_Wizard.tapp | Bin 35678 -> 35680 bytes .../Partition_Wizard/partition_wizard.be | 4 ++-- .../Partition_Wizard/partition_wizard.bec | Bin 16720 -> 16661 bytes 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b34fad6bb..ce8b3922a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to this project will be documented in this file. ### Changed - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` (#20260) - Moved Berry animate to its own `berry_animate` lib (#20309) +- Relax checks of Partition Wizard for newest Shelly ### Fixed - Matter Contact sensor was not triggering any update (#20232) diff --git a/tasmota/berry/modules/Partition_Wizard.tapp b/tasmota/berry/modules/Partition_Wizard.tapp index 1f4e94e0a28bc106209cb68eda6653e3ebb4c616..8198ccd14cac3222ccbec601defb071169aa4c85 100644 GIT binary patch delta 114 zcmcaNjp@NOrU^zYwr+Z<6U`codlt?Ozg?{$v%Hgm0fdDaWEct(i%K#}GV}A|%QLGI zi&FHGQbR*H8JNYT`coyO`ZvBj<~dp4o@?`VFBb=16ayx6bnAkYO}6M(U|Z0|00aOq C=_eon delta 93 zcmaDbjp^PrrU^zY)l1$bO*Cr|UcJ*PJjeS(;nGe91`rlzkeMvkEyl&kz+7Y`omyff hz47HS&&?aXd>nXD)K2E=)&(h (self.app_size_min * 1024) raise "internal_error", "safeboot is too large "+str(safeboot_size / 1024)+"kB" end tasmota.log(string.format("UPL: flashing `safeboot` from %s %ikB", safeboot_url, (safeboot_size / 1024) + 1), 2) var app0 = p.get_ota_slot(0) - if app0.start != 0x10000 raise "internal_error", "`app0` offset is not 0x10000" end + # if app0.start != 0x10000 raise "internal_error", "`app0` offset is not 0x10000" end cl.write_flash(app0.start) cl.close() return true diff --git a/tasmota/berry/modules/Partition_Wizard/partition_wizard.bec b/tasmota/berry/modules/Partition_Wizard/partition_wizard.bec index e6e82953351dc4f9cefc1fa6255d1485af6aa58d..3f884314cae6823852fe0e93558d63d085cbed6f 100644 GIT binary patch delta 412 zcmZ{fy-EW?5P)ZI_bz+6&CkU(Ug9OJ;f$a*3W8N)Wo2P;U>Tz*3Ko(a81xEBwO|S{ zm!}X!+$XTM@c{%|U&6#qQadnwGsAwv&SxKu`snr6LMQ6Zx<36msSo>wmFl6*0-DPSY3BvdYV|Si2)#oL zpNdB%U;a*3LYnoHQf@Yl)2{FUYRXvp%AyDLz50v-7s@>gdvZLfgem4F3mIRsjF8%c z39e0jrry?C=^fL64CugAKhA`h&;)=TV8Vn6*&Z^P9OFVrET+X78CYt6`^Pz@29*9$ zU9AFU`mgR(O`1>$QHo0=<>^bj*h+I4<8nCVWKPzAdEcCqnKVz;sIh^NJ$!HOZgFk$ n*nwh%Z7zw!1%+Y{VJ=OF4;c8z2nz{@A6q$}0O4wVua5ozLFQG? delta 471 zcmZ{fK}sV*6oy}=x;xdKYEx-3R5ER*7~0sVizo`N%mrpKiv~f2Bn#sR!x&71L3<%C zq!w8SM(_@b2z3xWfCq5r2~7K(tmi@Tzgm2J|GT{;FPG%$%pr&7+!>HoCDM7ml6XO+ z0Ggw4-g#OqMdNRkH4RpjHE@SQl;QgYfpziS6j??#Z5XD#lT?Jz?F|O4t~&1bhX<)T z8mhm?scMbZTR5Twrzc10L8t$xH~ekx+(%wR6^~iD9BEX7+h|;inc}8X-K{D8kuN2# z2q(32jN&-+7GepoVxFt7b7X8DmhMR$Kz-y;si*m3QsivyNV`HoPMgRp4kFw) z=gS>$%PD{lIFupaC)8pS0P)kZgt8$R5nJdfttK`T2>(kC%#=6YN{3zn>i Date: Sat, 30 Dec 2023 18:14:56 +1000 Subject: [PATCH 062/303] don't send commands to the AC while reading data from the AC. (#20352) on some units it can take around 250ms to reply to a request, by which time we're shoving another command to the unit. if this happens, the unit gives up and starts replying to the new command, which can again take 250ms. in this situation effectively nothing gets through. avoid this by checking if we're in the parser state machine. this also gives us timeout handling. tested on 4 different AC units. one which was unusable before is now functioning as expected, and the other 3 appear just as functional as they were before. --- tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino b/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino index 36baa3749..a51166ae6 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino @@ -329,6 +329,7 @@ enum miel_hvac_parser_state { struct miel_hvac_parser { enum miel_hvac_parser_state p_state; + uint8_t p_tmo; uint8_t p_type; uint8_t p_sum; uint8_t p_len; @@ -386,6 +387,7 @@ miel_hvac_parse(struct miel_hvac_softc *sc, uint8_t byte) /* reset state */ p->p_sum = 0; + p->p_tmo = 0; nstate = MIEL_HVAC_P_TYPE; break; @@ -1234,8 +1236,20 @@ miel_hvac_tick(struct miel_hvac_softc *sc) MIEL_HVAC_REQUEST_STAGE, }; + struct miel_hvac_parser *p = &sc->sc_parser; unsigned int i; + if (p->p_state != MIEL_HVAC_P_START) { + if (p->p_tmo) { + AddLog(LOG_LEVEL_DEBUG, PSTR(MIEL_HVAC_LOGNAME + ": read timeout")); + sc->sc_parser.p_state = MIEL_HVAC_P_START; + } else { + p->p_tmo = 1; + return; + } + } + if (miel_hvac_update_pending(sc)) { struct miel_hvac_msg_update *update = &sc->sc_update; From 2de3d427deb60e4d931f3bc3f95ec97682518bc2 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 30 Dec 2023 10:29:30 +0100 Subject: [PATCH 063/303] LVGL fix type for lv_imgbtn (#20354) --- CHANGELOG.md | 1 + lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h | 4 ++-- lib/libesp32_lvgl/lv_binding_berry/tools/convert.py | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce8b3922a..614794a2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ All notable changes to this project will be documented in this file. - Syslog server warning caused by lack of field and hostname starting with 'z' (#14689) - Support for Domoticz floor/room topics. Regression from v12.0.1 (#20299) - Berry claiming UART0 if needed (#20324) +- LVGL fix type for lv_imgbtn ### Removed diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h index 18ca143e1..aacce81e8 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h @@ -651,8 +651,8 @@ const be_ntv_func_def_t lv_colorwheel_func[] = { /* `lv_imgbtn` methods */ #ifdef BE_LV_WIDGET_IMGBTN const be_ntv_func_def_t lv_imgbtn_func[] = { - { "set_src", { (const void*) &lv_imgbtn_set_src, "", "(lv.lv_obj)(lv.lv_imgbtn_state)..." } }, - { "set_state", { (const void*) &lv_imgbtn_set_state, "", "(lv.lv_obj)(lv.lv_imgbtn_state)" } }, + { "set_src", { (const void*) &lv_imgbtn_set_src, "", "(lv.lv_obj)i..." } }, + { "set_state", { (const void*) &lv_imgbtn_set_state, "", "(lv.lv_obj)i" } }, }; #endif // BE_LV_WIDGET_IMGBTN diff --git a/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py b/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py index 8089c817e..3b69f8a44 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py +++ b/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py @@ -124,6 +124,8 @@ return_types = { "lv_anim_path_cb_t": "c", "lv_anim_ready_cb_t": "c", "lv_anim_start_cb_t": "c", + # lv_imgbtn + "lv_imgbtn_state_t": "i", # arrays "constchar * []": "str_arr", From a38f86905278ce08dac01f385033ad84d9eb38c1 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 30 Dec 2023 11:23:26 +0100 Subject: [PATCH 064/303] Fix other LVGL conversion to int (#20355) --- .../generate/be_lv_c_mapping.h | 20 +++++++++---------- .../lv_binding_berry/tools/convert.py | 6 ++++++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h index aacce81e8..44bdaf460 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h @@ -561,7 +561,7 @@ const be_ntv_func_def_t lv_group_func[] = { { "set_edge_cb", { (const void*) &lv_group_set_edge_cb, "", "(lv.lv_group)^lv_group_edge_cb^" } }, { "set_editing", { (const void*) &lv_group_set_editing, "", "(lv.lv_group)b" } }, { "set_focus_cb", { (const void*) &lv_group_set_focus_cb, "", "(lv.lv_group)^lv_group_focus_cb^" } }, - { "set_refocus_policy", { (const void*) &lv_group_set_refocus_policy, "", "(lv.lv_group)(lv.lv_group_refocus_policy)" } }, + { "set_refocus_policy", { (const void*) &lv_group_set_refocus_policy, "", "(lv.lv_group)i" } }, { "set_wrap", { (const void*) &lv_group_set_wrap, "", "(lv.lv_group)b" } }, { "swap_obj", { (const void*) &lv_group_swap_obj, "", "(lv.lv_obj)(lv.lv_obj)" } }, }; @@ -818,15 +818,15 @@ const be_ntv_func_def_t lv_btn_func[] = { /* `lv_btnmatrix` methods */ #ifdef BE_LV_WIDGET_BTNMATRIX const be_ntv_func_def_t lv_btnmatrix_func[] = { - { "clear_btn_ctrl", { (const void*) &lv_btnmatrix_clear_btn_ctrl, "", "(lv.lv_obj)i(lv.lv_btnmatrix_ctrl)" } }, - { "clear_btn_ctrl_all", { (const void*) &lv_btnmatrix_clear_btn_ctrl_all, "", "(lv.lv_obj)(lv.lv_btnmatrix_ctrl)" } }, + { "clear_btn_ctrl", { (const void*) &lv_btnmatrix_clear_btn_ctrl, "", "(lv.lv_obj)ii" } }, + { "clear_btn_ctrl_all", { (const void*) &lv_btnmatrix_clear_btn_ctrl_all, "", "(lv.lv_obj)i" } }, { "get_btn_text", { (const void*) &lv_btnmatrix_get_btn_text, "s", "(lv.lv_obj)i" } }, { "get_map", { (const void*) &lv_btnmatrix_get_map, "c", "(lv.lv_obj)" } }, { "get_one_checked", { (const void*) &lv_btnmatrix_get_one_checked, "b", "(lv.lv_obj)" } }, { "get_selected_btn", { (const void*) &lv_btnmatrix_get_selected_btn, "i", "(lv.lv_obj)" } }, - { "has_btn_ctrl", { (const void*) &lv_btnmatrix_has_btn_ctrl, "b", "(lv.lv_obj)i(lv.lv_btnmatrix_ctrl)" } }, - { "set_btn_ctrl", { (const void*) &lv_btnmatrix_set_btn_ctrl, "", "(lv.lv_obj)i(lv.lv_btnmatrix_ctrl)" } }, - { "set_btn_ctrl_all", { (const void*) &lv_btnmatrix_set_btn_ctrl_all, "", "(lv.lv_obj)(lv.lv_btnmatrix_ctrl)" } }, + { "has_btn_ctrl", { (const void*) &lv_btnmatrix_has_btn_ctrl, "b", "(lv.lv_obj)ii" } }, + { "set_btn_ctrl", { (const void*) &lv_btnmatrix_set_btn_ctrl, "", "(lv.lv_obj)ii" } }, + { "set_btn_ctrl_all", { (const void*) &lv_btnmatrix_set_btn_ctrl_all, "", "(lv.lv_obj)i" } }, { "set_btn_width", { (const void*) &lv_btnmatrix_set_btn_width, "", "(lv.lv_obj)ii" } }, { "set_ctrl_map", { (const void*) &lv_btnmatrix_set_ctrl_map, "", "(lv.lv_obj)(lv.lv_btnmatrix_ctrl)" } }, { "set_map", { (const void*) &lv_btnmatrix_set_map, "", "(lv.lv_obj)(lv.str_arr)" } }, @@ -935,7 +935,7 @@ const be_ntv_func_def_t lv_roller_func[] = { { "get_options", { (const void*) &lv_roller_get_options, "s", "(lv.lv_obj)" } }, { "get_selected", { (const void*) &lv_roller_get_selected, "i", "(lv.lv_obj)" } }, { "get_selected_str", { (const void*) &lv_roller_get_selected_str, "", "(lv.lv_obj)ci" } }, - { "set_options", { (const void*) &lv_roller_set_options, "", "(lv.lv_obj)s(lv.lv_roller_mode)" } }, + { "set_options", { (const void*) &lv_roller_set_options, "", "(lv.lv_obj)si" } }, { "set_selected", { (const void*) &lv_roller_set_selected, "", "(lv.lv_obj)ii" } }, { "set_visible_row_count", { (const void*) &lv_roller_set_visible_row_count, "", "(lv.lv_obj)i" } }, }; @@ -966,15 +966,15 @@ const be_ntv_func_def_t lv_switch_func[] = { /* `lv_table` methods */ #ifdef BE_LV_WIDGET_TABLE const be_ntv_func_def_t lv_table_func[] = { - { "add_cell_ctrl", { (const void*) &lv_table_add_cell_ctrl, "", "(lv.lv_obj)ii(lv.lv_table_cell_ctrl)" } }, - { "clear_cell_ctrl", { (const void*) &lv_table_clear_cell_ctrl, "", "(lv.lv_obj)ii(lv.lv_table_cell_ctrl)" } }, + { "add_cell_ctrl", { (const void*) &lv_table_add_cell_ctrl, "", "(lv.lv_obj)iii" } }, + { "clear_cell_ctrl", { (const void*) &lv_table_clear_cell_ctrl, "", "(lv.lv_obj)iii" } }, { "get_cell_user_data", { (const void*) &lv_table_get_cell_user_data, ".", "(lv.lv_obj)ii" } }, { "get_cell_value", { (const void*) &lv_table_get_cell_value, "s", "(lv.lv_obj)ii" } }, { "get_col_cnt", { (const void*) &lv_table_get_col_cnt, "i", "(lv.lv_obj)" } }, { "get_col_width", { (const void*) &lv_table_get_col_width, "i", "(lv.lv_obj)i" } }, { "get_row_cnt", { (const void*) &lv_table_get_row_cnt, "i", "(lv.lv_obj)" } }, { "get_selected_cell", { (const void*) &lv_table_get_selected_cell, "", "(lv.lv_obj)(lv.uint16)(lv.uint16)" } }, - { "has_cell_ctrl", { (const void*) &lv_table_has_cell_ctrl, "b", "(lv.lv_obj)ii(lv.lv_table_cell_ctrl)" } }, + { "has_cell_ctrl", { (const void*) &lv_table_has_cell_ctrl, "b", "(lv.lv_obj)iii" } }, { "set_cell_user_data", { (const void*) &lv_table_set_cell_user_data, "", "(lv.lv_obj)ii." } }, { "set_cell_value", { (const void*) &lv_table_set_cell_value, "", "(lv.lv_obj)iis" } }, { "set_cell_value_fmt", { (const void*) &lv_table_set_cell_value_fmt, "", "(lv.lv_obj)iis[......]" } }, diff --git a/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py b/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py index 3b69f8a44..0e7dc1c3b 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py +++ b/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py @@ -126,6 +126,12 @@ return_types = { "lv_anim_start_cb_t": "c", # lv_imgbtn "lv_imgbtn_state_t": "i", + # lv_btnmatrix + "lv_btnmatrix_ctrl_t": "i", + + "lv_group_refocus_policy_t": "i", + "lv_roller_mode_t": "i", + "lv_table_cell_ctrl_t": "i", # arrays "constchar * []": "str_arr", From 9194ac6c9424b667f71094c2e4452acb82a3ab01 Mon Sep 17 00:00:00 2001 From: gemu Date: Sat, 30 Dec 2023 13:20:33 +0100 Subject: [PATCH 065/303] max variables > 256 (#20358) --- .../tasmota_xdrv_driver/xdrv_10_scripter.ino | 138 ++++++++++++++---- 1 file changed, 106 insertions(+), 32 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino index 63730602f..0049e0a30 100755 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino @@ -70,9 +70,13 @@ const uint8_t SCRIPT_VERS[2] = {5, 2}; #endif // USE_SML_M #ifndef MAXFILT -#define MAXFILT 5 +#define MAXFILT 10 #endif + +#ifndef SCRIPT_SVARSIZE #define SCRIPT_SVARSIZE 20 +#endif + #ifndef SCRIPT_MAXSSIZE #define SCRIPT_MAXSSIZE 48 #endif @@ -156,6 +160,7 @@ char *Get_esc_char(char *cp, char *esc_chr); #define MAX_EXT_ARRAYS 5 #endif + #ifndef STASK_PRIO #define STASK_PRIO 1 #endif @@ -335,10 +340,18 @@ typedef union { }; } SCRIPT_TYPE; + +#if 1 +struct T_INDEX { + uint16_t index; + SCRIPT_TYPE bits; +}; +#else struct T_INDEX { uint8_t index; SCRIPT_TYPE bits; }; +#endif struct M_FILT { #ifdef LARGE_ARRAYS @@ -479,7 +492,7 @@ struct SCRIPT_MEM { uint16_t script_size; uint8_t *script_pram; uint16_t script_pram_size; - uint8_t numvars; + uint16_t numvars; uint8_t arres; void *script_mem; uint16_t script_mem_size; @@ -627,7 +640,7 @@ void ScriptEverySecond(void) { struct T_INDEX *vtp = glob_script_mem.type; TS_FLOAT delta = (millis() - glob_script_mem.script_lastmillis) / 1000.0; glob_script_mem.script_lastmillis = millis(); - for (uint8_t count=0; count 1) cpos -= 2; // now seek back to last line - uint8_t lbuff[256]; + uint8_t lbuff[FEXT_MAX_LINE_LENGTH]; uint8_t iob; uint16_t index = sizeof(lbuff) -1; fp->seek(cpos - sizeof(lbuff), SeekSet); @@ -1928,6 +1945,9 @@ int32_t extract_from_file(File *fp, char *ts_from, char *ts_to, int8_t coffs, T uint8_t buff[2], iob; fp->read(buff, 1); iob = buff[0]; + TS_FLOAT fval; + uint16_t curpos; + if (iob == '\t' || iob == ',' || iob == '\n' || iob == '\r') { rstr[sindex] = 0; sindex = 0; @@ -1964,10 +1984,11 @@ int32_t extract_from_file(File *fp, char *ts_from, char *ts_to, int8_t coffs, T } else { // data columns if (range) { - uint8_t curpos = colpos - coffs; + curpos = colpos - coffs; if (colpos >= coffs && curpos < numa) { if (a_len[curpos]) { - TS_FLOAT fval = CharToFloat(rstr); + fval = CharToFloat(rstr); +nextcol: uint8_t flg = 1; if ((mflg[curpos] & 1) == 1) { // absolute values, build diffs @@ -2008,12 +2029,20 @@ int32_t extract_from_file(File *fp, char *ts_from, char *ts_to, int8_t coffs, T } colpos++; if (iob == '\n' || iob == '\r') { - lastpos = fp->position(); - colpos = 0; - lines ++; - if (lines == 1) { - if (ipos) { - fp->seek(ipos, SeekSet); + // end of line + if (colpos <= numa) { + // empty column + curpos = colpos - coffs; + fval = 0; + goto nextcol; + } else { + lastpos = fp->position(); + colpos = 0; + lines ++; + if (lines == 1) { + if (ipos) { + fp->seek(ipos, SeekSet); + } } } } @@ -2315,7 +2344,7 @@ uint32_t match_vars(char *dvnam, TS_FLOAT **fp, char **sp, uint32_t *ind) { uint8_t slen = strlen(cp); if (slen == olen && *cp == dvnam[0]) { if (!strncmp(cp, dvnam, olen)) { - uint8_t index = vtp[count].index; + uint16_t index = vtp[count].index; if (vtp[count].bits.is_string == 0) { if (vtp[count].bits.is_filter) { // error @@ -2852,7 +2881,17 @@ chknext: SCRIPT_SKIP_SPACES uint16_t alens; TS_FLOAT *fps; + char *slp = lp; lp = get_array_by_name(lp, &fps, &alens, 0); + if (lp == 0 || fps == 0) { + lp = slp; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + for (uint32_t cnt = 0; cnt < alend; cnt++ ) { + fpd[cnt] = fvar; + } + fvar = alend; + goto nfuncexit; + } SCRIPT_SKIP_SPACES if (alens < alend) { alend = alens; @@ -2983,7 +3022,7 @@ chknext: uint8_t vtype; lp = isvar(lp + 4, &vtype, &ind, 0, 0, gv); if (!ind.bits.constant) { - uint8_t index = glob_script_mem.type[ind.index].index; + uint16_t index = glob_script_mem.type[ind.index].index; fvar = glob_script_mem.fvars[index] != glob_script_mem.s_fvars[index]; glob_script_mem.s_fvars[index] = glob_script_mem.fvars[index]; } else { @@ -3145,7 +3184,7 @@ extern void W8960_SetGain(uint8_t sel, uint16_t value); uint8_t vtype; lp = isvar(lp + 5, &vtype, &ind, 0, 0, gv); if (!ind.bits.constant) { - uint8_t index = glob_script_mem.type[ind.index].index; + uint16_t index = glob_script_mem.type[ind.index].index; fvar = glob_script_mem.fvars[index] - glob_script_mem.s_fvars[index]; glob_script_mem.s_fvars[index] = glob_script_mem.fvars[index]; } else { @@ -3341,7 +3380,7 @@ extern void W8960_SetGain(uint8_t sel, uint16_t value); if (!strncmp_XP(lp, XPSTR("fr("), 3)) { struct T_INDEX ind; uint8_t vtype; - uint8_t sindex = 0; + uint16_t sindex = 0; lp = isvar(lp + 3, &vtype, &ind, 0, 0, gv); if (vtype != VAR_NV) { // found variable as result @@ -4934,7 +4973,7 @@ extern char *SML_GetSVal(uint32_t index); fvar = -1; } else { // string result - uint8_t sindex = glob_script_mem.type[ind.index].index; + uint16_t sindex = glob_script_mem.type[ind.index].index; char *cp = glob_script_mem.glob_snp + (sindex * glob_script_mem.max_ssize); fvar = SML_Set_WStr(fvar1, cp); } @@ -4957,6 +4996,14 @@ extern char *SML_GetSVal(uint32_t index); SML_Decode(fvar - 1); goto nfuncexit; } + if (!strncmp_XP(lp, XPSTR("smls("), 5)) { + TS_FLOAT meter; + lp = GetNumericArgument(lp + 5, OPER_EQU, &meter, gv); + if (meter < 1) meter = 1; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, gv); + SML_Shift_Num(meter - 1, fvar); + goto nfuncexit; + } if (!strncmp_XP(lp, XPSTR("smlv["), 5)) { lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv); fvar = sml_getv(fvar); @@ -6424,7 +6471,7 @@ extern "C" { int32_t UpdVar(char *vname, float *fvar, uint32_t mode) { uint8_t type; - uint8_t index; + uint16_t index; if (*vname == '@') { vname++; type = *vname; @@ -8304,9 +8351,9 @@ void Scripter_save_pvars(void) { TS_FLOAT *fp = (TS_FLOAT*)glob_script_mem.script_pram; mlen+=sizeof(TS_FLOAT); struct T_INDEX *vtp = glob_script_mem.type; - for (uint8_t count = 0; count 0) { @@ -10537,7 +10584,7 @@ uint16_t cipos = 0; lp = isvar(lp, &vtype, &ind, &sysvar, 0, 0); if (vtype != VAR_NV) { SCRIPT_SKIP_SPACES - uint8_t index = glob_script_mem.type[ind.index].index; + uint16_t index = glob_script_mem.type[ind.index].index; if ((vtype & STYPE) == 0) { // numeric result //Serial.printf("numeric %d - %d \n",ind.index,index); @@ -10631,6 +10678,8 @@ uint32_t cnt; #define WSO_FORCEPLAIN 4 #define WSO_FORCEMAIN 8 #define WSO_FORCEGUI 16 +#define WSO_FORCETAB 32 +#define WSO_FORCESUBFILE 64 #define WSO_STOP_DIV 0x80 void WCS_DIV(uint8_t flag) { @@ -10731,7 +10780,7 @@ void ScriptWebShow(char mc, uint8_t page) { //goto nextwebline; } else if (!strncmp(lp, "%/", 2)) { // send file - if (mc) { + if (mc || (specopt & WSO_FORCESUBFILE)) { web_send_file(mc, lp + 1); } } else { @@ -10775,6 +10824,9 @@ int32_t web_send_file(char mc, char *fname) { // skip comment lines continue; } + if (*lp == ';') { + // continue; + } web_send_line(mc, lbuff); } file.close(); @@ -10814,6 +10866,15 @@ const char *gc_str; bool dogui = ((!mc && (*lin != '$')) || (mc == 'w' && (*lin != '$'))) && (!(specopt & WSO_FORCEMAIN)); + if (!strncmp(lin, "%=#", 3)) { + // subroutine + uint8_t sflg = specopt; + specopt = WSO_FORCEPLAIN; + lin = scripter_sub(lin + 1, 0); + specopt = sflg; + return lin; + } + if ((dogui && !(specopt & WSO_FORCEGUI)) || (!dogui && (specopt & WSO_FORCEGUI))) { //if ( ((!mc && (*lin != '$')) || (mc == 'w' && (*lin != '$'))) && (!(specopt & WSO_FORCEMAIN)) || (specopt & WSO_FORCEGUI)) { // normal web section @@ -11208,13 +11269,17 @@ const char *gc_str; lp++; } else { - if (mc == 'w' || (specopt & WSO_FORCEPLAIN)) { - WSContentSend_P(PSTR("%s"), lin); + if (specopt & WSO_FORCETAB) { + WSContentSend_P(PSTR("{s}%s{e}"), lin); } else { - if (optflg) { - WSContentSend_P(PSTR("
%s
"), lin); + if (mc == 'w' || (specopt & WSO_FORCEPLAIN)) { + WSContentSend_P(PSTR("%s"), lin); } else { - WSContentSend_P(PSTR("{s}%s{e}"), lin); + if (optflg) { + WSContentSend_P(PSTR("
%s
"), lin); + } else { + WSContentSend_P(PSTR("{s}%s{e}"), lin); + } } } } @@ -12140,15 +12205,24 @@ int32_t call2pwl(const char *url) { #endif // TESLA_POWERWALL +//#ifdef ESP8266 #include "WiFiClientSecureLightBearSSL.h" +//#else +//#include +//#endif //ESP8266 // get https info page json string uint32_t call2https(const char *host, const char *path) { //if (TasmotaGlobal.global_state.wifi_down) return 1; uint32_t status = 0; +//#ifdef ESP32 +// WiFiClientSecure *httpsClient; +// httpsClient = new WiFiClientSecure; +//#else BearSSL::WiFiClientSecure_light *httpsClient; httpsClient = new BearSSL::WiFiClientSecure_light(1024, 1024); +//#endif httpsClient->setTimeout(2000); httpsClient->setInsecure(); @@ -13039,7 +13113,7 @@ bool Xdrv10(uint32_t function) case FUNC_NETWORK_UP: break; - + case FUNC_ACTIVE: result = true; break; From 92c3261fb002eb7b1dec328bc9ab00718809fe8d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 30 Dec 2023 14:59:16 +0100 Subject: [PATCH 066/303] Update changelogs --- CHANGELOG.md | 4 ++-- RELEASENOTES.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 614794a2c..a8b5bd711 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ All notable changes to this project will be documented in this file. ### Changed - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` (#20260) - Moved Berry animate to its own `berry_animate` lib (#20309) -- Relax checks of Partition Wizard for newest Shelly +- Relax checks of Partition Wizard for newest Shelly (#20349) ### Fixed - Matter Contact sensor was not triggering any update (#20232) @@ -30,7 +30,7 @@ All notable changes to this project will be documented in this file. - Syslog server warning caused by lack of field and hostname starting with 'z' (#14689) - Support for Domoticz floor/room topics. Regression from v12.0.1 (#20299) - Berry claiming UART0 if needed (#20324) -- LVGL fix type for lv_imgbtn +- LVGL fix type for lv_imgbtn (#20354) ### Removed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index a526e6cbe..822337b19 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -139,6 +139,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Syslog server warning caused by lack of field and hostname starting with 'z' [#14689](https://github.com/arendst/Tasmota/issues/14689) - Support for Domoticz floor/room topics. Regression from v12.0.1 [#20299](https://github.com/arendst/Tasmota/issues/20299) - ESP32 piezo ceramic buzzer doesn't buzz [#20118](https://github.com/arendst/Tasmota/issues/20118) +- LVGL fix type for lv_imgbtn [#20354](https://github.com/arendst/Tasmota/issues/20354) - Berry claiming UART0 if needed [#20324](https://github.com/arendst/Tasmota/issues/20324) - Matter Contact sensor was not triggering any update [#20232](https://github.com/arendst/Tasmota/issues/20232) From 516621af5250d3ec39dfb349db1f07ba1730e7c0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 1 Jan 2024 18:22:01 +0100 Subject: [PATCH 067/303] don't change zip files --- .gitattributes | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitattributes b/.gitattributes index 745bc27a1..ad391420f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -15,3 +15,9 @@ *.PDF diff=astextplain *.rtf diff=astextplain *.RTF diff=astextplain + +# No changes for zip files +*.zip binary +*.autoconf binary +*.bin binary +*.tapp binary From 54e88c29262b78c2d917c52a423360b034a6aae3 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Tue, 2 Jan 2024 12:16:50 +0100 Subject: [PATCH 068/303] HASPmota type `chart` (#20372) --- CHANGELOG.md | 1 + .../berry_tasmota/src/be_lv_haspmota.c | 1771 +++++++++++------ .../haspmota_src/haspmota_core/haspmota.be | 100 +- 3 files changed, 1259 insertions(+), 613 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8b5bd711..32eb2fd88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. - HASPmota added `haspmota.page_show()` to change page (#20333) - Berry added `introspect.set()` for class attributes (#20339) - Support negative power on BL0942 using index 5..8 (#20322) +- HASPmota type `chart` ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds (#20236) diff --git a/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c b/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c index 70f239d36..c00dba442 100644 --- a/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c +++ b/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c @@ -40,6 +40,7 @@ extern const bclass be_class_lv_textarea; extern const bclass be_class_lv_theme; extern const bclass be_class_lv_timer; extern const bclass be_class_lv_qrcode; +extern const bclass be_class_lv_chart; extern const bclass be_class_lvh_page; @@ -1902,7 +1903,7 @@ be_local_closure(lvh_obj_setmember, /* name */ }), be_str_weak(setmember), &be_const_str_solidified, - ( &(const binstruction[134]) { /* code */ + ( &(const binstruction[159]) { /* code */ 0xA40E0000, // 0000 IMPORT R3 K0 0xA4120200, // 0001 IMPORT R4 K1 0x40160503, // 0002 CONNECT R5 K2 K3 @@ -2031,12 +2032,37 @@ be_local_closure(lvh_obj_setmember, /* name */ 0x60240001, // 007D GETGBL R9 G1 0x002A2808, // 007E ADD R10 K20 R8 0x7C240200, // 007F CALL R9 1 - 0x70020003, // 0080 JMP #0085 - 0x60200001, // 0081 GETGBL R8 G1 - 0x58240015, // 0082 LDCONST R9 K21 - 0x5C280200, // 0083 MOVE R10 R1 - 0x7C200400, // 0084 CALL R8 2 - 0x80000000, // 0085 RET 0 + 0x7002001C, // 0080 JMP #009E + 0x8C20090B, // 0081 GETMET R8 R4 K11 + 0x8828010F, // 0082 GETMBR R10 R0 K15 + 0x002E0801, // 0083 ADD R11 K4 R1 + 0x7C200600, // 0084 CALL R8 3 + 0x5C1C1000, // 0085 MOVE R7 R8 + 0x60200004, // 0086 GETGBL R8 G4 + 0x5C240E00, // 0087 MOVE R9 R7 + 0x7C200200, // 0088 CALL R8 1 + 0x1C20110C, // 0089 EQ R8 R8 K12 + 0x7822000E, // 008A JMPF R8 #009A + 0xA8020005, // 008B EXBLK 0 #0092 + 0x5C200E00, // 008C MOVE R8 R7 + 0x8824010F, // 008D GETMBR R9 R0 K15 + 0x5C280400, // 008E MOVE R10 R2 + 0x7C200400, // 008F CALL R8 2 + 0xA8040001, // 0090 EXBLK 1 1 + 0x70020006, // 0091 JMP #0099 + 0xAC200002, // 0092 CATCH R8 0 2 + 0x70020003, // 0093 JMP #0098 + 0x00281313, // 0094 ADD R10 R9 K19 + 0x00281401, // 0095 ADD R10 R10 R1 + 0xB004100A, // 0096 RAISE 1 R8 R10 + 0x70020000, // 0097 JMP #0099 + 0xB0080000, // 0098 RAISE 2 R0 R0 + 0x70020003, // 0099 JMP #009E + 0x60200001, // 009A GETGBL R8 G1 + 0x58240015, // 009B LDCONST R9 K21 + 0x5C280200, // 009C MOVE R10 R1 + 0x7C200400, // 009D CALL R8 2 + 0x80000000, // 009E RET 0 }) ) ); @@ -2277,7 +2303,7 @@ be_local_closure(lvh_obj_member, /* name */ }), be_str_weak(member), &be_const_str_solidified, - ( &(const binstruction[110]) { /* code */ + ( &(const binstruction[124]) { /* code */ 0xA40A0000, // 0000 IMPORT R2 K0 0xA40E0200, // 0001 IMPORT R3 K1 0x40120503, // 0002 CONNECT R4 K2 K3 @@ -2382,12 +2408,26 @@ be_local_closure(lvh_obj_member, /* name */ 0x8824010F, // 0065 GETMBR R9 R0 K15 0x7C200200, // 0066 CALL R8 1 0x80041000, // 0067 RET 1 R8 - 0x601C0008, // 0068 GETGBL R7 G8 - 0x5C200200, // 0069 MOVE R8 R1 - 0x7C1C0200, // 006A CALL R7 1 - 0x001E2207, // 006B ADD R7 K17 R7 - 0xB0062407, // 006C RAISE 1 K18 R7 - 0x80000000, // 006D RET 0 + 0x8C1C070B, // 0068 GETMET R7 R3 K11 + 0x8824010F, // 0069 GETMBR R9 R0 K15 + 0x002A0A01, // 006A ADD R10 K5 R1 + 0x7C1C0600, // 006B CALL R7 3 + 0x5C180E00, // 006C MOVE R6 R7 + 0x601C0004, // 006D GETGBL R7 G4 + 0x5C200C00, // 006E MOVE R8 R6 + 0x7C1C0200, // 006F CALL R7 1 + 0x1C1C0F0C, // 0070 EQ R7 R7 K12 + 0x781E0003, // 0071 JMPF R7 #0076 + 0x5C1C0C00, // 0072 MOVE R7 R6 + 0x8820010F, // 0073 GETMBR R8 R0 K15 + 0x7C1C0200, // 0074 CALL R7 1 + 0x80040E00, // 0075 RET 1 R7 + 0x601C0008, // 0076 GETGBL R7 G8 + 0x5C200200, // 0077 MOVE R8 R1 + 0x7C1C0200, // 0078 CALL R7 1 + 0x001E2207, // 0079 ADD R7 K17 R7 + 0xB0062407, // 007A RAISE 1 K18 R7 + 0x80000000, // 007B RET 0 }) ) ); @@ -4140,34 +4180,37 @@ be_local_class(lvh_obj, { be_const_key_weak(get_action, -1), be_const_closure(lvh_obj_get_action_closure) }, { be_const_key_weak(get_obj, 84), be_const_closure(lvh_obj_get_obj_closure) }, { be_const_key_weak(_attr_map, 50), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { - be_const_map( * be_nested_map(26, + be_const_map( * be_nested_map(29, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(rotation, -1), be_nested_str_weak(rotation) }, - { be_const_key_weak(bg_opa, -1), be_nested_str_weak(style_bg_opa) }, - { be_const_key_weak(end_angle, 3), be_nested_str_weak(bg_end_angle) }, - { be_const_key_weak(w, 18), be_nested_str_weak(width) }, - { be_const_key_weak(src, 6), be_nested_str_weak(src) }, - { be_const_key_weak(x, -1), be_nested_str_weak(x) }, - { be_const_key_weak(border_color, -1), be_nested_str_weak(style_border_color) }, - { be_const_key_weak(bg_grad_color, 0), be_nested_str_weak(style_bg_grad_color) }, - { be_const_key_weak(pad_all, -1), be_nested_str_weak(style_pad_all) }, - { be_const_key_weak(bg_color, 20), be_nested_str_weak(style_bg_color) }, - { be_const_key_weak(y, 8), be_nested_str_weak(y) }, - { be_const_key_weak(line_color, -1), be_nested_str_weak(style_line_color) }, - { be_const_key_weak(image_recolor_opa, 10), be_nested_str_weak(style_img_recolor_opa) }, - { be_const_key_weak(start_angle, 5), be_nested_str_weak(bg_start_angle) }, - { be_const_key_weak(end_angle1, 11), be_nested_str_weak(end_angle) }, + { be_const_key_weak(bg_grad_color, -1), be_nested_str_weak(style_bg_grad_color) }, + { be_const_key_weak(pad_bottom, -1), be_nested_str_weak(style_pad_bottom) }, + { be_const_key_weak(pad_top, -1), be_nested_str_weak(style_pad_top) }, + { be_const_key_weak(y, 10), be_nested_str_weak(y) }, { be_const_key_weak(border_side, -1), be_nested_str_weak(style_border_side) }, - { be_const_key_weak(pad_bottom, 9), be_nested_str_weak(style_pad_bottom) }, - { be_const_key_weak(radius, 4), be_nested_str_weak(style_radius) }, - { be_const_key_weak(pad_left, -1), be_nested_str_weak(style_pad_left) }, - { be_const_key_weak(image_recolor, -1), be_nested_str_weak(style_img_recolor) }, - { be_const_key_weak(border_width, -1), be_nested_str_weak(style_border_width) }, - { be_const_key_weak(pad_right, -1), be_nested_str_weak(style_pad_right) }, + { be_const_key_weak(w, -1), be_nested_str_weak(width) }, { be_const_key_weak(start_angle1, -1), be_nested_str_weak(start_angle) }, + { be_const_key_weak(width, 5), be_nested_str_weak(style_width) }, + { be_const_key_weak(start_angle, 23), be_nested_str_weak(bg_start_angle) }, { be_const_key_weak(h, -1), be_nested_str_weak(height) }, - { be_const_key_weak(pad_top, 16), be_nested_str_weak(style_pad_top) }, - { be_const_key_weak(bg_grad_dir, 14), be_nested_str_weak(style_bg_grad_dir) }, + { be_const_key_weak(rotation, -1), be_nested_str_weak(rotation) }, + { be_const_key_weak(src, 27), be_nested_str_weak(src) }, + { be_const_key_weak(line_color, -1), be_nested_str_weak(style_line_color) }, + { be_const_key_weak(image_recolor_opa, -1), be_nested_str_weak(style_img_recolor_opa) }, + { be_const_key_weak(end_angle, -1), be_nested_str_weak(bg_end_angle) }, + { be_const_key_weak(pad_right, 19), be_nested_str_weak(style_pad_right) }, + { be_const_key_weak(bg_grad_dir, -1), be_nested_str_weak(style_bg_grad_dir) }, + { be_const_key_weak(pad_all, -1), be_nested_str_weak(style_pad_all) }, + { be_const_key_weak(bg_color, 13), be_nested_str_weak(style_bg_color) }, + { be_const_key_weak(image_recolor, -1), be_nested_str_weak(style_img_recolor) }, + { be_const_key_weak(x, 12), be_nested_str_weak(x) }, + { be_const_key_weak(line_rounded, -1), be_nested_str_weak(style_line_rounded) }, + { be_const_key_weak(bg_opa, -1), be_nested_str_weak(style_bg_opa) }, + { be_const_key_weak(end_angle1, -1), be_nested_str_weak(end_angle) }, + { be_const_key_weak(border_color, 21), be_nested_str_weak(style_border_color) }, + { be_const_key_weak(height, -1), be_nested_str_weak(style_height) }, + { be_const_key_weak(pad_left, 17), be_nested_str_weak(style_pad_left) }, + { be_const_key_weak(radius, -1), be_nested_str_weak(style_radius) }, + { be_const_key_weak(border_width, 15), be_nested_str_weak(style_border_width) }, })) ) } )) }, { be_const_key_weak(register_event_cb, 17), be_const_closure(lvh_obj_register_event_cb_closure) }, { be_const_key_weak(set_pad_top2, 61), be_const_closure(lvh_obj_set_pad_top2_closure) }, @@ -6333,14 +6376,14 @@ void be_load_lvh_qrcode_class(bvm *vm) { be_pop(vm, 1); } -extern const bclass be_class_HASPmota; +extern const bclass be_class_lvh_chart; /******************************************************************** -** Solidified function: page_show +** Solidified function: add_point ********************************************************************/ -be_local_closure(HASPmota_page_show, /* name */ +be_local_closure(lvh_chart_add_point, /* name */ be_nested_proto( - 8, /* nstack */ + 6, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -6348,90 +6391,20 @@ be_local_closure(HASPmota_page_show, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ - /* K0 */ be_nested_str_weak(lvh_pages), - /* K1 */ be_nested_str_weak(lvh_page_cur_idx), - /* K2 */ be_nested_str_weak(pages_list_sorted), - /* K3 */ be_const_int(1), - /* K4 */ be_nested_str_weak(prev), - /* K5 */ be_nested_str_weak(next), - /* K6 */ be_nested_str_weak(back), - /* K7 */ be_nested_str_weak(re_page_target), - /* K8 */ be_nested_str_weak(match), - /* K9 */ be_const_int(0), - /* K10 */ be_nested_str_weak(show), + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(set_next_value), + /* K2 */ be_nested_str_weak(ser1), }), - be_str_weak(page_show), + be_str_weak(add_point), &be_const_str_solidified, - ( &(const binstruction[68]) { /* code */ - 0x4C080000, // 0000 LDNIL R2 - 0x880C0100, // 0001 GETMBR R3 R0 K0 - 0x88100101, // 0002 GETMBR R4 R0 K1 - 0x940C0604, // 0003 GETIDX R3 R3 R4 - 0x8C100102, // 0004 GETMET R4 R0 K2 - 0x88180101, // 0005 GETMBR R6 R0 K1 - 0x7C100400, // 0006 CALL R4 2 - 0x6014000C, // 0007 GETGBL R5 G12 - 0x5C180800, // 0008 MOVE R6 R4 - 0x7C140200, // 0009 CALL R5 1 - 0x18140B03, // 000A LE R5 R5 K3 - 0x78160000, // 000B JMPF R5 #000D - 0x80000A00, // 000C RET 0 - 0x1C140304, // 000D EQ R5 R1 K4 - 0x78160009, // 000E JMPF R5 #0019 - 0x60140009, // 000F GETGBL R5 G9 - 0x88180704, // 0010 GETMBR R6 R3 K4 - 0x7C140200, // 0011 CALL R5 1 - 0x5C080A00, // 0012 MOVE R2 R5 - 0x4C140000, // 0013 LDNIL R5 - 0x1C140405, // 0014 EQ R5 R2 R5 - 0x78160001, // 0015 JMPF R5 #0018 - 0x5415FFFE, // 0016 LDINT R5 -1 - 0x94080805, // 0017 GETIDX R2 R4 R5 - 0x70020020, // 0018 JMP #003A - 0x1C140305, // 0019 EQ R5 R1 K5 - 0x78160008, // 001A JMPF R5 #0024 - 0x60140009, // 001B GETGBL R5 G9 - 0x88180705, // 001C GETMBR R6 R3 K5 - 0x7C140200, // 001D CALL R5 1 - 0x5C080A00, // 001E MOVE R2 R5 - 0x4C140000, // 001F LDNIL R5 - 0x1C140405, // 0020 EQ R5 R2 R5 - 0x78160000, // 0021 JMPF R5 #0023 - 0x94080903, // 0022 GETIDX R2 R4 K3 - 0x70020015, // 0023 JMP #003A - 0x1C140306, // 0024 EQ R5 R1 K6 - 0x78160008, // 0025 JMPF R5 #002F - 0x60140009, // 0026 GETGBL R5 G9 - 0x88180706, // 0027 GETMBR R6 R3 K6 - 0x7C140200, // 0028 CALL R5 1 - 0x5C080A00, // 0029 MOVE R2 R5 - 0x4C140000, // 002A LDNIL R5 - 0x1C140405, // 002B EQ R5 R2 R5 - 0x78160000, // 002C JMPF R5 #002E - 0x58080003, // 002D LDCONST R2 K3 - 0x7002000A, // 002E JMP #003A - 0x88140107, // 002F GETMBR R5 R0 K7 - 0x8C140B08, // 0030 GETMET R5 R5 K8 - 0x5C1C0200, // 0031 MOVE R7 R1 - 0x7C140400, // 0032 CALL R5 2 - 0x78160005, // 0033 JMPF R5 #003A - 0x60140009, // 0034 GETGBL R5 G9 - 0x5419FFFE, // 0035 LDINT R6 -1 - 0x401A0606, // 0036 CONNECT R6 K3 R6 - 0x94180206, // 0037 GETIDX R6 R1 R6 - 0x7C140200, // 0038 CALL R5 1 - 0x5C080A00, // 0039 MOVE R2 R5 - 0x4C140000, // 003A LDNIL R5 - 0x20140405, // 003B NE R5 R2 R5 - 0x78160005, // 003C JMPF R5 #0043 - 0x24140509, // 003D GT R5 R2 K9 - 0x78160003, // 003E JMPF R5 #0043 - 0x88140100, // 003F GETMBR R5 R0 K0 - 0x94140A02, // 0040 GETIDX R5 R5 R2 - 0x8C140B0A, // 0041 GETMET R5 R5 K10 - 0x7C140200, // 0042 CALL R5 1 - 0x80000000, // 0043 RET 0 + ( &(const binstruction[ 6]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x88100102, // 0002 GETMBR R4 R0 K2 + 0x5C140200, // 0003 MOVE R5 R1 + 0x7C080600, // 0004 CALL R2 3 + 0x80000000, // 0005 RET 0 }) ) ); @@ -6439,12 +6412,347 @@ be_local_closure(HASPmota_page_show, /* name */ /******************************************************************** -** Solidified function: do_action +** Solidified function: post_init ********************************************************************/ -be_local_closure(HASPmota_do_action, /* name */ +be_local_closure(lvh_chart_post_init, /* name */ be_nested_proto( 6, /* nstack */ - 3, /* argc */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[17]) { /* constants */ + /* K0 */ be_nested_str_weak(y_min), + /* K1 */ be_const_int(0), + /* K2 */ be_nested_str_weak(y_max), + /* K3 */ be_nested_str_weak(h_div), + /* K4 */ be_const_int(3), + /* K5 */ be_nested_str_weak(v_div), + /* K6 */ be_nested_str_weak(_lv_obj), + /* K7 */ be_nested_str_weak(set_update_mode), + /* K8 */ be_nested_str_weak(lv), + /* K9 */ be_nested_str_weak(CHART_UPDATE_MODE_SHIFT), + /* K10 */ be_nested_str_weak(ser1), + /* K11 */ be_nested_str_weak(add_series), + /* K12 */ be_nested_str_weak(color), + /* K13 */ be_const_int(15615044), + /* K14 */ be_nested_str_weak(CHART_AXIS_PRIMARY_Y), + /* K15 */ be_nested_str_weak(ser2), + /* K16 */ be_const_int(4517444), + }), + be_str_weak(post_init), + &be_const_str_solidified, + ( &(const binstruction[32]) { /* code */ + 0x90020101, // 0000 SETMBR R0 K0 K1 + 0x54060063, // 0001 LDINT R1 100 + 0x90020401, // 0002 SETMBR R0 K2 R1 + 0x90020704, // 0003 SETMBR R0 K3 K4 + 0x54060004, // 0004 LDINT R1 5 + 0x90020A01, // 0005 SETMBR R0 K5 R1 + 0x88040106, // 0006 GETMBR R1 R0 K6 + 0x8C040307, // 0007 GETMET R1 R1 K7 + 0xB80E1000, // 0008 GETNGBL R3 K8 + 0x880C0709, // 0009 GETMBR R3 R3 K9 + 0x7C040400, // 000A CALL R1 2 + 0x88040106, // 000B GETMBR R1 R0 K6 + 0x8C04030B, // 000C GETMET R1 R1 K11 + 0xB80E1000, // 000D GETNGBL R3 K8 + 0x8C0C070C, // 000E GETMET R3 R3 K12 + 0x5814000D, // 000F LDCONST R5 K13 + 0x7C0C0400, // 0010 CALL R3 2 + 0xB8121000, // 0011 GETNGBL R4 K8 + 0x8810090E, // 0012 GETMBR R4 R4 K14 + 0x7C040600, // 0013 CALL R1 3 + 0x90021401, // 0014 SETMBR R0 K10 R1 + 0x88040106, // 0015 GETMBR R1 R0 K6 + 0x8C04030B, // 0016 GETMET R1 R1 K11 + 0xB80E1000, // 0017 GETNGBL R3 K8 + 0x8C0C070C, // 0018 GETMET R3 R3 K12 + 0x58140010, // 0019 LDCONST R5 K16 + 0x7C0C0400, // 001A CALL R3 2 + 0xB8121000, // 001B GETNGBL R4 K8 + 0x8810090E, // 001C GETMBR R4 R4 K14 + 0x7C040600, // 001D CALL R1 3 + 0x90021E01, // 001E SETMBR R0 K15 R1 + 0x80000000, // 001F RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_y_min +********************************************************************/ +be_local_closure(lvh_chart_set_y_min, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(y_min), + /* K1 */ be_nested_str_weak(_lv_obj), + /* K2 */ be_nested_str_weak(set_range), + /* K3 */ be_nested_str_weak(lv), + /* K4 */ be_nested_str_weak(CHART_AXIS_PRIMARY_Y), + /* K5 */ be_nested_str_weak(y_max), + }), + be_str_weak(set_y_min), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x88080101, // 0001 GETMBR R2 R0 K1 + 0x8C080502, // 0002 GETMET R2 R2 K2 + 0xB8120600, // 0003 GETNGBL R4 K3 + 0x88100904, // 0004 GETMBR R4 R4 K4 + 0x88140100, // 0005 GETMBR R5 R0 K0 + 0x88180105, // 0006 GETMBR R6 R0 K5 + 0x7C080800, // 0007 CALL R2 4 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_series1_color +********************************************************************/ +be_local_closure(lvh_chart_set_series1_color, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(set_series_color), + /* K2 */ be_nested_str_weak(ser1), + }), + be_str_weak(set_series1_color), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x88100102, // 0002 GETMBR R4 R0 K2 + 0x5C140200, // 0003 MOVE R5 R1 + 0x7C080600, // 0004 CALL R2 3 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_series2_color +********************************************************************/ +be_local_closure(lvh_chart_set_series2_color, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(set_series_color), + /* K2 */ be_nested_str_weak(ser2), + }), + be_str_weak(set_series2_color), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x88100102, // 0002 GETMBR R4 R0 K2 + 0x5C140200, // 0003 MOVE R5 R1 + 0x7C080600, // 0004 CALL R2 3 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_y_max +********************************************************************/ +be_local_closure(lvh_chart_set_y_max, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(y_max), + /* K1 */ be_nested_str_weak(_lv_obj), + /* K2 */ be_nested_str_weak(set_range), + /* K3 */ be_nested_str_weak(lv), + /* K4 */ be_nested_str_weak(CHART_AXIS_PRIMARY_Y), + /* K5 */ be_nested_str_weak(y_min), + }), + be_str_weak(set_y_max), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x88080101, // 0001 GETMBR R2 R0 K1 + 0x8C080502, // 0002 GETMET R2 R2 K2 + 0xB8120600, // 0003 GETNGBL R4 K3 + 0x88100904, // 0004 GETMBR R4 R4 K4 + 0x88140105, // 0005 GETMBR R5 R0 K5 + 0x88180100, // 0006 GETMBR R6 R0 K0 + 0x7C080800, // 0007 CALL R2 4 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_point2 +********************************************************************/ +be_local_closure(lvh_chart_add_point2, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(set_next_value), + /* K2 */ be_nested_str_weak(ser2), + }), + be_str_weak(add_point2), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x88100102, // 0002 GETMBR R4 R0 K2 + 0x5C140200, // 0003 MOVE R5 R1 + 0x7C080600, // 0004 CALL R2 3 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_y_max +********************************************************************/ +be_local_closure(lvh_chart_get_y_max, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(y_max), + }), + be_str_weak(get_y_max), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_val +********************************************************************/ +be_local_closure(lvh_chart_set_val, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(add_point), + }), + be_str_weak(set_val), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x8C080100, // 0000 GETMET R2 R0 K0 + 0x5C100200, // 0001 MOVE R4 R1 + 0x7C080400, // 0002 CALL R2 2 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_val2 +********************************************************************/ +be_local_closure(lvh_chart_set_val2, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(add_point2), + }), + be_str_weak(set_val2), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x8C080100, // 0000 GETMET R2 R0 K0 + 0x5C100200, // 0001 MOVE R4 R1 + 0x7C080400, // 0002 CALL R2 2 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_v_div_line_count +********************************************************************/ +be_local_closure(lvh_chart_set_v_div_line_count, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -6452,29 +6760,131 @@ be_local_closure(HASPmota_do_action, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(lv), - /* K1 */ be_nested_str_weak(EVENT_CLICKED), - /* K2 */ be_nested_str_weak(page_show), - /* K3 */ be_nested_str_weak(_action), + /* K0 */ be_nested_str_weak(v_div), + /* K1 */ be_nested_str_weak(_lv_obj), + /* K2 */ be_nested_str_weak(set_div_line_count), + /* K3 */ be_nested_str_weak(h_div), }), - be_str_weak(do_action), + be_str_weak(set_v_div_line_count), &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0xB80E0000, // 0000 GETNGBL R3 K0 - 0x880C0701, // 0001 GETMBR R3 R3 K1 - 0x200C0403, // 0002 NE R3 R2 R3 - 0x780E0000, // 0003 JMPF R3 #0005 - 0x80000600, // 0004 RET 0 - 0x8C0C0102, // 0005 GETMET R3 R0 K2 - 0x88140303, // 0006 GETMBR R5 R1 K3 - 0x7C0C0400, // 0007 CALL R3 2 - 0x80000000, // 0008 RET 0 + ( &(const binstruction[ 7]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x88080101, // 0001 GETMBR R2 R0 K1 + 0x8C080502, // 0002 GETMET R2 R2 K2 + 0x88100103, // 0003 GETMBR R4 R0 K3 + 0x88140100, // 0004 GETMBR R5 R0 K0 + 0x7C080600, // 0005 CALL R2 3 + 0x80000000, // 0006 RET 0 }) ) ); /*******************************************************************/ +/******************************************************************** +** Solidified function: get_y_min +********************************************************************/ +be_local_closure(lvh_chart_get_y_min, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(y_min), + }), + be_str_weak(get_y_min), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_h_div_line_count +********************************************************************/ +be_local_closure(lvh_chart_set_h_div_line_count, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(h_div), + /* K1 */ be_nested_str_weak(_lv_obj), + /* K2 */ be_nested_str_weak(set_div_line_count), + /* K3 */ be_nested_str_weak(v_div), + }), + be_str_weak(set_h_div_line_count), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x88080101, // 0001 GETMBR R2 R0 K1 + 0x8C080502, // 0002 GETMET R2 R2 K2 + 0x88100100, // 0003 GETMBR R4 R0 K0 + 0x88140103, // 0004 GETMBR R5 R0 K3 + 0x7C080600, // 0005 CALL R2 3 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: lvh_chart +********************************************************************/ +extern const bclass be_class_lvh_obj; +be_local_class(lvh_chart, + 6, + &be_class_lvh_obj, + be_nested_map(20, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(y_max, -1), be_const_var(3) }, + { be_const_key_weak(get_y_min, 18), be_const_closure(lvh_chart_get_y_min_closure) }, + { be_const_key_weak(set_v_div_line_count, 0), be_const_closure(lvh_chart_set_v_div_line_count_closure) }, + { be_const_key_weak(h_div, 6), be_const_var(4) }, + { be_const_key_weak(set_y_min, -1), be_const_closure(lvh_chart_set_y_min_closure) }, + { be_const_key_weak(ser2, 12), be_const_var(1) }, + { be_const_key_weak(set_val2, -1), be_const_closure(lvh_chart_set_val2_closure) }, + { be_const_key_weak(_lv_class, -1), be_const_class(be_class_lv_chart) }, + { be_const_key_weak(ser1, 1), be_const_var(0) }, + { be_const_key_weak(set_series2_color, -1), be_const_closure(lvh_chart_set_series2_color_closure) }, + { be_const_key_weak(post_init, 16), be_const_closure(lvh_chart_post_init_closure) }, + { be_const_key_weak(set_val, -1), be_const_closure(lvh_chart_set_val_closure) }, + { be_const_key_weak(add_point2, -1), be_const_closure(lvh_chart_add_point2_closure) }, + { be_const_key_weak(v_div, -1), be_const_var(5) }, + { be_const_key_weak(get_y_max, -1), be_const_closure(lvh_chart_get_y_max_closure) }, + { be_const_key_weak(y_min, 11), be_const_var(2) }, + { be_const_key_weak(set_y_max, -1), be_const_closure(lvh_chart_set_y_max_closure) }, + { be_const_key_weak(add_point, 2), be_const_closure(lvh_chart_add_point_closure) }, + { be_const_key_weak(set_series1_color, -1), be_const_closure(lvh_chart_set_series1_color_closure) }, + { be_const_key_weak(set_h_div_line_count, -1), be_const_closure(lvh_chart_set_h_div_line_count_closure) }, + })), + be_str_weak(lvh_chart) +); +/*******************************************************************/ + +void be_load_lvh_chart_class(bvm *vm) { + be_pushntvclass(vm, &be_class_lvh_chart); + be_setglobal(vm, "lvh_chart"); + be_pop(vm, 1); +} + +extern const bclass be_class_HASPmota; + /******************************************************************** ** Solidified function: register_event ********************************************************************/ @@ -6551,130 +6961,6 @@ be_local_closure(HASPmota_register_event, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: parse -********************************************************************/ -be_local_closure(HASPmota_parse, /* name */ - be_nested_proto( - 9, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(json), - /* K1 */ be_nested_str_weak(load), - /* K2 */ be_nested_str_weak(instance), - /* K3 */ be_nested_str_weak(parse_page), - /* K4 */ be_nested_str_weak(parse_obj), - /* K5 */ be_nested_str_weak(lvh_pages), - /* K6 */ be_nested_str_weak(lvh_page_cur_idx), - /* K7 */ be_nested_str_weak(value_error), - /* K8 */ be_nested_str_weak(unable_X20to_X20parse_X20JSON_X20line), - }), - be_str_weak(parse), - &be_const_str_solidified, - ( &(const binstruction[21]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0x8C0C0501, // 0001 GETMET R3 R2 K1 - 0x5C140200, // 0002 MOVE R5 R1 - 0x7C0C0400, // 0003 CALL R3 2 - 0x60100004, // 0004 GETGBL R4 G4 - 0x5C140600, // 0005 MOVE R5 R3 - 0x7C100200, // 0006 CALL R4 1 - 0x1C100902, // 0007 EQ R4 R4 K2 - 0x78120009, // 0008 JMPF R4 #0013 - 0x8C100103, // 0009 GETMET R4 R0 K3 - 0x5C180600, // 000A MOVE R6 R3 - 0x7C100400, // 000B CALL R4 2 - 0x8C100104, // 000C GETMET R4 R0 K4 - 0x5C180600, // 000D MOVE R6 R3 - 0x881C0105, // 000E GETMBR R7 R0 K5 - 0x88200106, // 000F GETMBR R8 R0 K6 - 0x941C0E08, // 0010 GETIDX R7 R7 R8 - 0x7C100600, // 0011 CALL R4 3 - 0x70020000, // 0012 JMP #0014 - 0xB0060F08, // 0013 RAISE 1 K7 K8 - 0x80000000, // 0014 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: event_dispatch -********************************************************************/ -be_local_closure(HASPmota_event_dispatch, /* name */ - be_nested_proto( - 9, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ - /* K0 */ be_nested_str_weak(introspect), - /* K1 */ be_nested_str_weak(toptr), - /* K2 */ be_nested_str_weak(event), - /* K3 */ be_nested_str_weak(_change_buffer), - /* K4 */ be_nested_str_weak(lv), - /* K5 */ be_nested_str_weak(lv_event), - /* K6 */ be_nested_str_weak(user_data), - /* K7 */ be_const_int(0), - /* K8 */ be_nested_str_weak(fromptr), - /* K9 */ be_nested_str_weak(instance), - /* K10 */ be_nested_str_weak(event_cb), - }), - be_str_weak(event_dispatch), - &be_const_str_solidified, - ( &(const binstruction[35]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0x8C0C0501, // 0001 GETMET R3 R2 K1 - 0x5C140200, // 0002 MOVE R5 R1 - 0x7C0C0400, // 0003 CALL R3 2 - 0x88100102, // 0004 GETMBR R4 R0 K2 - 0x78120004, // 0005 JMPF R4 #000B - 0x88100102, // 0006 GETMBR R4 R0 K2 - 0x8C100903, // 0007 GETMET R4 R4 K3 - 0x5C180600, // 0008 MOVE R6 R3 - 0x7C100400, // 0009 CALL R4 2 - 0x70020004, // 000A JMP #0010 - 0xB8120800, // 000B GETNGBL R4 K4 - 0x8C100905, // 000C GETMET R4 R4 K5 - 0x5C180600, // 000D MOVE R6 R3 - 0x7C100400, // 000E CALL R4 2 - 0x90020404, // 000F SETMBR R0 K2 R4 - 0x88100102, // 0010 GETMBR R4 R0 K2 - 0x88100906, // 0011 GETMBR R4 R4 K6 - 0x60140009, // 0012 GETGBL R5 G9 - 0x5C180800, // 0013 MOVE R6 R4 - 0x7C140200, // 0014 CALL R5 1 - 0x20140B07, // 0015 NE R5 R5 K7 - 0x7816000A, // 0016 JMPF R5 #0022 - 0x8C140508, // 0017 GETMET R5 R2 K8 - 0x5C1C0800, // 0018 MOVE R7 R4 - 0x7C140400, // 0019 CALL R5 2 - 0x60180004, // 001A GETGBL R6 G4 - 0x5C1C0A00, // 001B MOVE R7 R5 - 0x7C180200, // 001C CALL R6 1 - 0x1C180D09, // 001D EQ R6 R6 K9 - 0x781A0002, // 001E JMPF R6 #0022 - 0x8C180B0A, // 001F GETMET R6 R5 K10 - 0x88200102, // 0020 GETMBR R8 R0 K2 - 0x7C180400, // 0021 CALL R6 2 - 0x80000000, // 0022 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: pages_list_sorted ********************************************************************/ @@ -6756,67 +7042,9 @@ be_local_closure(HASPmota_pages_list_sorted, /* name */ /******************************************************************** -** Solidified function: sort +** Solidified function: parse ********************************************************************/ -be_local_closure(HASPmota_sort, /* name */ - be_nested_proto( - 7, /* nstack */ - 1, /* argc */ - 4, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_const_class(be_class_HASPmota), - /* K1 */ be_const_int(1), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(sort), - &be_const_str_solidified, - ( &(const binstruction[30]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x60080010, // 0001 GETGBL R2 G16 - 0x600C000C, // 0002 GETGBL R3 G12 - 0x5C100000, // 0003 MOVE R4 R0 - 0x7C0C0200, // 0004 CALL R3 1 - 0x040C0701, // 0005 SUB R3 R3 K1 - 0x400E0203, // 0006 CONNECT R3 K1 R3 - 0x7C080200, // 0007 CALL R2 1 - 0xA8020010, // 0008 EXBLK 0 #001A - 0x5C0C0400, // 0009 MOVE R3 R2 - 0x7C0C0000, // 000A CALL R3 0 - 0x94100003, // 000B GETIDX R4 R0 R3 - 0x5C140600, // 000C MOVE R5 R3 - 0x24180B02, // 000D GT R6 R5 K2 - 0x781A0008, // 000E JMPF R6 #0018 - 0x04180B01, // 000F SUB R6 R5 K1 - 0x94180006, // 0010 GETIDX R6 R0 R6 - 0x24180C04, // 0011 GT R6 R6 R4 - 0x781A0004, // 0012 JMPF R6 #0018 - 0x04180B01, // 0013 SUB R6 R5 K1 - 0x94180006, // 0014 GETIDX R6 R0 R6 - 0x98000A06, // 0015 SETIDX R0 R5 R6 - 0x04140B01, // 0016 SUB R5 R5 K1 - 0x7001FFF4, // 0017 JMP #000D - 0x98000A04, // 0018 SETIDX R0 R5 R4 - 0x7001FFEE, // 0019 JMP #0009 - 0x58080003, // 001A LDCONST R2 K3 - 0xAC080200, // 001B CATCH R2 1 0 - 0xB0080000, // 001C RAISE 2 R0 R0 - 0x80040000, // 001D RET 1 R0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: parse_page -********************************************************************/ -be_local_closure(HASPmota_parse_page, /* name */ +be_local_closure(HASPmota_parse, /* name */ be_nested_proto( 9, /* nstack */ 2, /* argc */ @@ -6826,251 +7054,41 @@ be_local_closure(HASPmota_parse_page, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ - /* K0 */ be_nested_str_weak(has), - /* K1 */ be_nested_str_weak(page), - /* K2 */ be_nested_str_weak(int), - /* K3 */ be_nested_str_weak(lvh_page_cur_idx), - /* K4 */ be_nested_str_weak(lvh_pages), - /* K5 */ be_nested_str_weak(contains), - /* K6 */ be_nested_str_weak(lvh_page), - /* K7 */ be_nested_str_weak(find), - /* K8 */ be_nested_str_weak(id), - /* K9 */ be_const_int(0), - /* K10 */ be_nested_str_weak(get_page_cur), - /* K11 */ be_nested_str_weak(prev), - /* K12 */ be_nested_str_weak(next), - /* K13 */ be_nested_str_weak(back), - }), - be_str_weak(parse_page), - &be_const_str_solidified, - ( &(const binstruction[54]) { /* code */ - 0x8C080300, // 0000 GETMET R2 R1 K0 - 0x58100001, // 0001 LDCONST R4 K1 - 0x7C080400, // 0002 CALL R2 2 - 0x780A0030, // 0003 JMPF R2 #0035 - 0x60080004, // 0004 GETGBL R2 G4 - 0x940C0301, // 0005 GETIDX R3 R1 K1 - 0x7C080200, // 0006 CALL R2 1 - 0x1C080502, // 0007 EQ R2 R2 K2 - 0x780A002B, // 0008 JMPF R2 #0035 - 0x60080009, // 0009 GETGBL R2 G9 - 0x940C0301, // 000A GETIDX R3 R1 K1 - 0x7C080200, // 000B CALL R2 1 - 0x90020602, // 000C SETMBR R0 K3 R2 - 0x880C0104, // 000D GETMBR R3 R0 K4 - 0x8C0C0705, // 000E GETMET R3 R3 K5 - 0x5C140400, // 000F MOVE R5 R2 - 0x7C0C0400, // 0010 CALL R3 2 - 0x740E0006, // 0011 JMPT R3 #0019 - 0x880C0106, // 0012 GETMBR R3 R0 K6 - 0x88100104, // 0013 GETMBR R4 R0 K4 - 0x5C140600, // 0014 MOVE R5 R3 - 0x5C180400, // 0015 MOVE R6 R2 - 0x5C1C0000, // 0016 MOVE R7 R0 - 0x7C140400, // 0017 CALL R5 2 - 0x98100405, // 0018 SETIDX R4 R2 R5 - 0x8C0C0307, // 0019 GETMET R3 R1 K7 - 0x58140008, // 001A LDCONST R5 K8 - 0x7C0C0400, // 001B CALL R3 2 - 0x1C0C0709, // 001C EQ R3 R3 K9 - 0x780E0016, // 001D JMPF R3 #0035 - 0x8C0C010A, // 001E GETMET R3 R0 K10 - 0x7C0C0200, // 001F CALL R3 1 - 0x60100009, // 0020 GETGBL R4 G9 - 0x8C140307, // 0021 GETMET R5 R1 K7 - 0x581C000B, // 0022 LDCONST R7 K11 - 0x4C200000, // 0023 LDNIL R8 - 0x7C140600, // 0024 CALL R5 3 - 0x7C100200, // 0025 CALL R4 1 - 0x900E1604, // 0026 SETMBR R3 K11 R4 - 0x60100009, // 0027 GETGBL R4 G9 - 0x8C140307, // 0028 GETMET R5 R1 K7 - 0x581C000C, // 0029 LDCONST R7 K12 - 0x4C200000, // 002A LDNIL R8 - 0x7C140600, // 002B CALL R5 3 - 0x7C100200, // 002C CALL R4 1 - 0x900E1804, // 002D SETMBR R3 K12 R4 - 0x60100009, // 002E GETGBL R4 G9 - 0x8C140307, // 002F GETMET R5 R1 K7 - 0x581C000D, // 0030 LDCONST R7 K13 - 0x4C200000, // 0031 LDNIL R8 - 0x7C140600, // 0032 CALL R5 3 - 0x7C100200, // 0033 CALL R4 1 - 0x900E1A04, // 0034 SETMBR R3 K13 R4 - 0x80000000, // 0035 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: _load -********************************************************************/ -be_local_closure(HASPmota__load, /* name */ - be_nested_proto( - 14, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[17]) { /* constants */ - /* K0 */ be_nested_str_weak(string), - /* K1 */ be_nested_str_weak(json), - /* K2 */ be_nested_str_weak(lvh_page_cur_idx), - /* K3 */ be_const_int(1), - /* K4 */ be_nested_str_weak(lvh_page), + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(json), + /* K1 */ be_nested_str_weak(load), + /* K2 */ be_nested_str_weak(instance), + /* K3 */ be_nested_str_weak(parse_page), + /* K4 */ be_nested_str_weak(parse_obj), /* K5 */ be_nested_str_weak(lvh_pages), - /* K6 */ be_nested_str_weak(r), - /* K7 */ be_nested_str_weak(read), - /* K8 */ be_nested_str_weak(close), - /* K9 */ be_nested_str_weak(split), - /* K10 */ be_nested_str_weak(_X0A), - /* K11 */ be_const_int(0), - /* K12 */ be_nested_str_weak(load), - /* K13 */ be_nested_str_weak(instance), - /* K14 */ be_nested_str_weak(parse_page), - /* K15 */ be_nested_str_weak(parse_obj), - /* K16 */ be_nested_str_weak(remove), + /* K6 */ be_nested_str_weak(lvh_page_cur_idx), + /* K7 */ be_nested_str_weak(value_error), + /* K8 */ be_nested_str_weak(unable_X20to_X20parse_X20JSON_X20line), }), - be_str_weak(_load), + be_str_weak(parse), &be_const_str_solidified, - ( &(const binstruction[54]) { /* code */ + ( &(const binstruction[21]) { /* code */ 0xA40A0000, // 0000 IMPORT R2 K0 - 0xA40E0200, // 0001 IMPORT R3 K1 - 0x90020503, // 0002 SETMBR R0 K2 K3 - 0x88100104, // 0003 GETMBR R4 R0 K4 - 0x88140105, // 0004 GETMBR R5 R0 K5 - 0x5C180800, // 0005 MOVE R6 R4 - 0x581C0003, // 0006 LDCONST R7 K3 - 0x5C200000, // 0007 MOVE R8 R0 - 0x7C180400, // 0008 CALL R6 2 - 0x98160606, // 0009 SETIDX R5 K3 R6 - 0x60140011, // 000A GETGBL R5 G17 - 0x5C180200, // 000B MOVE R6 R1 - 0x581C0006, // 000C LDCONST R7 K6 - 0x7C140400, // 000D CALL R5 2 - 0x8C180B07, // 000E GETMET R6 R5 K7 - 0x7C180200, // 000F CALL R6 1 - 0x8C1C0B08, // 0010 GETMET R7 R5 K8 - 0x7C1C0200, // 0011 CALL R7 1 - 0x8C1C0509, // 0012 GETMET R7 R2 K9 - 0x5C240C00, // 0013 MOVE R9 R6 - 0x5828000A, // 0014 LDCONST R10 K10 - 0x7C1C0600, // 0015 CALL R7 3 - 0x4C140000, // 0016 LDNIL R5 - 0x4C180000, // 0017 LDNIL R6 - 0x6020000C, // 0018 GETGBL R8 G12 - 0x5C240E00, // 0019 MOVE R9 R7 - 0x7C200200, // 001A CALL R8 1 - 0x2420110B, // 001B GT R8 R8 K11 - 0x78220015, // 001C JMPF R8 #0033 - 0x8C20070C, // 001D GETMET R8 R3 K12 - 0x94280F0B, // 001E GETIDX R10 R7 K11 - 0x7C200400, // 001F CALL R8 2 - 0x60240004, // 0020 GETGBL R9 G4 - 0x5C281000, // 0021 MOVE R10 R8 - 0x7C240200, // 0022 CALL R9 1 - 0x1C24130D, // 0023 EQ R9 R9 K13 - 0x78260008, // 0024 JMPF R9 #002E - 0x8C24010E, // 0025 GETMET R9 R0 K14 - 0x5C2C1000, // 0026 MOVE R11 R8 - 0x7C240400, // 0027 CALL R9 2 - 0x8C24010F, // 0028 GETMET R9 R0 K15 - 0x5C2C1000, // 0029 MOVE R11 R8 - 0x88300105, // 002A GETMBR R12 R0 K5 - 0x88340102, // 002B GETMBR R13 R0 K2 - 0x9430180D, // 002C GETIDX R12 R12 R13 - 0x7C240600, // 002D CALL R9 3 - 0x4C200000, // 002E LDNIL R8 - 0x8C240F10, // 002F GETMET R9 R7 K16 - 0x582C000B, // 0030 LDCONST R11 K11 - 0x7C240400, // 0031 CALL R9 2 - 0x7001FFE4, // 0032 JMP #0018 - 0x4C1C0000, // 0033 LDNIL R7 - 0x90020503, // 0034 SETMBR R0 K2 K3 - 0x80000000, // 0035 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_page_cur -********************************************************************/ -be_local_closure(HASPmota_get_page_cur, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(lvh_pages), - /* K1 */ be_nested_str_weak(lvh_page_cur_idx), - }), - be_str_weak(get_page_cur), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x88080101, // 0001 GETMBR R2 R0 K1 - 0x94040202, // 0002 GETIDX R1 R1 R2 - 0x80040200, // 0003 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: deinit -********************************************************************/ -be_local_closure(HASPmota_deinit, /* name */ - be_nested_proto( - 5, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(_val_rule), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(remove_rule), - /* K3 */ be_nested_str_weak(_text_rule), - }), - be_str_weak(deinit), - &be_const_str_solidified, - ( &(const binstruction[19]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x4C080000, // 0001 LDNIL R2 - 0x20040202, // 0002 NE R1 R1 R2 - 0x78060004, // 0003 JMPF R1 #0009 - 0xB8060200, // 0004 GETNGBL R1 K1 - 0x8C040302, // 0005 GETMET R1 R1 K2 - 0x880C0100, // 0006 GETMBR R3 R0 K0 - 0x5C100000, // 0007 MOVE R4 R0 - 0x7C040600, // 0008 CALL R1 3 - 0x88040103, // 0009 GETMBR R1 R0 K3 - 0x4C080000, // 000A LDNIL R2 - 0x20040202, // 000B NE R1 R1 R2 - 0x78060004, // 000C JMPF R1 #0012 - 0xB8060200, // 000D GETNGBL R1 K1 - 0x8C040302, // 000E GETMET R1 R1 K2 - 0x880C0103, // 000F GETMBR R3 R0 K3 - 0x5C100000, // 0010 MOVE R4 R0 - 0x7C040600, // 0011 CALL R1 3 - 0x80000000, // 0012 RET 0 + 0x8C0C0501, // 0001 GETMET R3 R2 K1 + 0x5C140200, // 0002 MOVE R5 R1 + 0x7C0C0400, // 0003 CALL R3 2 + 0x60100004, // 0004 GETGBL R4 G4 + 0x5C140600, // 0005 MOVE R5 R3 + 0x7C100200, // 0006 CALL R4 1 + 0x1C100902, // 0007 EQ R4 R4 K2 + 0x78120009, // 0008 JMPF R4 #0013 + 0x8C100103, // 0009 GETMET R4 R0 K3 + 0x5C180600, // 000A MOVE R6 R3 + 0x7C100400, // 000B CALL R4 2 + 0x8C100104, // 000C GETMET R4 R0 K4 + 0x5C180600, // 000D MOVE R6 R3 + 0x881C0105, // 000E GETMBR R7 R0 K5 + 0x88200106, // 000F GETMBR R8 R0 K6 + 0x941C0E08, // 0010 GETIDX R7 R7 R8 + 0x7C100600, // 0011 CALL R4 3 + 0x70020000, // 0012 JMP #0014 + 0xB0060F08, // 0013 RAISE 1 K7 K8 + 0x80000000, // 0014 RET 0 }) ) ); @@ -7239,6 +7257,109 @@ be_local_closure(HASPmota_start, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: page_show +********************************************************************/ +be_local_closure(HASPmota_page_show, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_str_weak(lvh_pages), + /* K1 */ be_nested_str_weak(lvh_page_cur_idx), + /* K2 */ be_nested_str_weak(pages_list_sorted), + /* K3 */ be_const_int(1), + /* K4 */ be_nested_str_weak(prev), + /* K5 */ be_nested_str_weak(next), + /* K6 */ be_nested_str_weak(back), + /* K7 */ be_nested_str_weak(re_page_target), + /* K8 */ be_nested_str_weak(match), + /* K9 */ be_const_int(0), + /* K10 */ be_nested_str_weak(show), + }), + be_str_weak(page_show), + &be_const_str_solidified, + ( &(const binstruction[68]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x880C0100, // 0001 GETMBR R3 R0 K0 + 0x88100101, // 0002 GETMBR R4 R0 K1 + 0x940C0604, // 0003 GETIDX R3 R3 R4 + 0x8C100102, // 0004 GETMET R4 R0 K2 + 0x88180101, // 0005 GETMBR R6 R0 K1 + 0x7C100400, // 0006 CALL R4 2 + 0x6014000C, // 0007 GETGBL R5 G12 + 0x5C180800, // 0008 MOVE R6 R4 + 0x7C140200, // 0009 CALL R5 1 + 0x18140B03, // 000A LE R5 R5 K3 + 0x78160000, // 000B JMPF R5 #000D + 0x80000A00, // 000C RET 0 + 0x1C140304, // 000D EQ R5 R1 K4 + 0x78160009, // 000E JMPF R5 #0019 + 0x60140009, // 000F GETGBL R5 G9 + 0x88180704, // 0010 GETMBR R6 R3 K4 + 0x7C140200, // 0011 CALL R5 1 + 0x5C080A00, // 0012 MOVE R2 R5 + 0x4C140000, // 0013 LDNIL R5 + 0x1C140405, // 0014 EQ R5 R2 R5 + 0x78160001, // 0015 JMPF R5 #0018 + 0x5415FFFE, // 0016 LDINT R5 -1 + 0x94080805, // 0017 GETIDX R2 R4 R5 + 0x70020020, // 0018 JMP #003A + 0x1C140305, // 0019 EQ R5 R1 K5 + 0x78160008, // 001A JMPF R5 #0024 + 0x60140009, // 001B GETGBL R5 G9 + 0x88180705, // 001C GETMBR R6 R3 K5 + 0x7C140200, // 001D CALL R5 1 + 0x5C080A00, // 001E MOVE R2 R5 + 0x4C140000, // 001F LDNIL R5 + 0x1C140405, // 0020 EQ R5 R2 R5 + 0x78160000, // 0021 JMPF R5 #0023 + 0x94080903, // 0022 GETIDX R2 R4 K3 + 0x70020015, // 0023 JMP #003A + 0x1C140306, // 0024 EQ R5 R1 K6 + 0x78160008, // 0025 JMPF R5 #002F + 0x60140009, // 0026 GETGBL R5 G9 + 0x88180706, // 0027 GETMBR R6 R3 K6 + 0x7C140200, // 0028 CALL R5 1 + 0x5C080A00, // 0029 MOVE R2 R5 + 0x4C140000, // 002A LDNIL R5 + 0x1C140405, // 002B EQ R5 R2 R5 + 0x78160000, // 002C JMPF R5 #002E + 0x58080003, // 002D LDCONST R2 K3 + 0x7002000A, // 002E JMP #003A + 0x88140107, // 002F GETMBR R5 R0 K7 + 0x8C140B08, // 0030 GETMET R5 R5 K8 + 0x5C1C0200, // 0031 MOVE R7 R1 + 0x7C140400, // 0032 CALL R5 2 + 0x78160005, // 0033 JMPF R5 #003A + 0x60140009, // 0034 GETGBL R5 G9 + 0x5419FFFE, // 0035 LDINT R6 -1 + 0x401A0606, // 0036 CONNECT R6 K3 R6 + 0x94180206, // 0037 GETIDX R6 R1 R6 + 0x7C140200, // 0038 CALL R5 1 + 0x5C080A00, // 0039 MOVE R2 R5 + 0x4C140000, // 003A LDNIL R5 + 0x20140405, // 003B NE R5 R2 R5 + 0x78160005, // 003C JMPF R5 #0043 + 0x24140509, // 003D GT R5 R2 K9 + 0x78160003, // 003E JMPF R5 #0043 + 0x88140100, // 003F GETMBR R5 R0 K0 + 0x94140A02, // 0040 GETIDX R5 R5 R2 + 0x8C140B0A, // 0041 GETMET R5 R5 K10 + 0x7C140200, // 0042 CALL R5 1 + 0x80000000, // 0043 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: init ********************************************************************/ @@ -7273,6 +7394,435 @@ be_local_closure(HASPmota_init, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: get_page_cur +********************************************************************/ +be_local_closure(HASPmota_get_page_cur, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(lvh_pages), + /* K1 */ be_nested_str_weak(lvh_page_cur_idx), + }), + be_str_weak(get_page_cur), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x88080101, // 0001 GETMBR R2 R0 K1 + 0x94040202, // 0002 GETIDX R1 R1 R2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: deinit +********************************************************************/ +be_local_closure(HASPmota_deinit, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(_val_rule), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(remove_rule), + /* K3 */ be_nested_str_weak(_text_rule), + }), + be_str_weak(deinit), + &be_const_str_solidified, + ( &(const binstruction[19]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x20040202, // 0002 NE R1 R1 R2 + 0x78060004, // 0003 JMPF R1 #0009 + 0xB8060200, // 0004 GETNGBL R1 K1 + 0x8C040302, // 0005 GETMET R1 R1 K2 + 0x880C0100, // 0006 GETMBR R3 R0 K0 + 0x5C100000, // 0007 MOVE R4 R0 + 0x7C040600, // 0008 CALL R1 3 + 0x88040103, // 0009 GETMBR R1 R0 K3 + 0x4C080000, // 000A LDNIL R2 + 0x20040202, // 000B NE R1 R1 R2 + 0x78060004, // 000C JMPF R1 #0012 + 0xB8060200, // 000D GETNGBL R1 K1 + 0x8C040302, // 000E GETMET R1 R1 K2 + 0x880C0103, // 000F GETMBR R3 R0 K3 + 0x5C100000, // 0010 MOVE R4 R0 + 0x7C040600, // 0011 CALL R1 3 + 0x80000000, // 0012 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: event_dispatch +********************************************************************/ +be_local_closure(HASPmota_event_dispatch, /* name */ + be_nested_proto( + 9, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_str_weak(introspect), + /* K1 */ be_nested_str_weak(toptr), + /* K2 */ be_nested_str_weak(event), + /* K3 */ be_nested_str_weak(_change_buffer), + /* K4 */ be_nested_str_weak(lv), + /* K5 */ be_nested_str_weak(lv_event), + /* K6 */ be_nested_str_weak(user_data), + /* K7 */ be_const_int(0), + /* K8 */ be_nested_str_weak(fromptr), + /* K9 */ be_nested_str_weak(instance), + /* K10 */ be_nested_str_weak(event_cb), + }), + be_str_weak(event_dispatch), + &be_const_str_solidified, + ( &(const binstruction[35]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0x8C0C0501, // 0001 GETMET R3 R2 K1 + 0x5C140200, // 0002 MOVE R5 R1 + 0x7C0C0400, // 0003 CALL R3 2 + 0x88100102, // 0004 GETMBR R4 R0 K2 + 0x78120004, // 0005 JMPF R4 #000B + 0x88100102, // 0006 GETMBR R4 R0 K2 + 0x8C100903, // 0007 GETMET R4 R4 K3 + 0x5C180600, // 0008 MOVE R6 R3 + 0x7C100400, // 0009 CALL R4 2 + 0x70020004, // 000A JMP #0010 + 0xB8120800, // 000B GETNGBL R4 K4 + 0x8C100905, // 000C GETMET R4 R4 K5 + 0x5C180600, // 000D MOVE R6 R3 + 0x7C100400, // 000E CALL R4 2 + 0x90020404, // 000F SETMBR R0 K2 R4 + 0x88100102, // 0010 GETMBR R4 R0 K2 + 0x88100906, // 0011 GETMBR R4 R4 K6 + 0x60140009, // 0012 GETGBL R5 G9 + 0x5C180800, // 0013 MOVE R6 R4 + 0x7C140200, // 0014 CALL R5 1 + 0x20140B07, // 0015 NE R5 R5 K7 + 0x7816000A, // 0016 JMPF R5 #0022 + 0x8C140508, // 0017 GETMET R5 R2 K8 + 0x5C1C0800, // 0018 MOVE R7 R4 + 0x7C140400, // 0019 CALL R5 2 + 0x60180004, // 001A GETGBL R6 G4 + 0x5C1C0A00, // 001B MOVE R7 R5 + 0x7C180200, // 001C CALL R6 1 + 0x1C180D09, // 001D EQ R6 R6 K9 + 0x781A0002, // 001E JMPF R6 #0022 + 0x8C180B0A, // 001F GETMET R6 R5 K10 + 0x88200102, // 0020 GETMBR R8 R0 K2 + 0x7C180400, // 0021 CALL R6 2 + 0x80000000, // 0022 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: do_action +********************************************************************/ +be_local_closure(HASPmota_do_action, /* name */ + be_nested_proto( + 6, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(lv), + /* K1 */ be_nested_str_weak(EVENT_CLICKED), + /* K2 */ be_nested_str_weak(page_show), + /* K3 */ be_nested_str_weak(_action), + }), + be_str_weak(do_action), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0xB80E0000, // 0000 GETNGBL R3 K0 + 0x880C0701, // 0001 GETMBR R3 R3 K1 + 0x200C0403, // 0002 NE R3 R2 R3 + 0x780E0000, // 0003 JMPF R3 #0005 + 0x80000600, // 0004 RET 0 + 0x8C0C0102, // 0005 GETMET R3 R0 K2 + 0x88140303, // 0006 GETMBR R5 R1 K3 + 0x7C0C0400, // 0007 CALL R3 2 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: sort +********************************************************************/ +be_local_closure(HASPmota_sort, /* name */ + be_nested_proto( + 7, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_const_class(be_class_HASPmota), + /* K1 */ be_const_int(1), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(sort), + &be_const_str_solidified, + ( &(const binstruction[30]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x60080010, // 0001 GETGBL R2 G16 + 0x600C000C, // 0002 GETGBL R3 G12 + 0x5C100000, // 0003 MOVE R4 R0 + 0x7C0C0200, // 0004 CALL R3 1 + 0x040C0701, // 0005 SUB R3 R3 K1 + 0x400E0203, // 0006 CONNECT R3 K1 R3 + 0x7C080200, // 0007 CALL R2 1 + 0xA8020010, // 0008 EXBLK 0 #001A + 0x5C0C0400, // 0009 MOVE R3 R2 + 0x7C0C0000, // 000A CALL R3 0 + 0x94100003, // 000B GETIDX R4 R0 R3 + 0x5C140600, // 000C MOVE R5 R3 + 0x24180B02, // 000D GT R6 R5 K2 + 0x781A0008, // 000E JMPF R6 #0018 + 0x04180B01, // 000F SUB R6 R5 K1 + 0x94180006, // 0010 GETIDX R6 R0 R6 + 0x24180C04, // 0011 GT R6 R6 R4 + 0x781A0004, // 0012 JMPF R6 #0018 + 0x04180B01, // 0013 SUB R6 R5 K1 + 0x94180006, // 0014 GETIDX R6 R0 R6 + 0x98000A06, // 0015 SETIDX R0 R5 R6 + 0x04140B01, // 0016 SUB R5 R5 K1 + 0x7001FFF4, // 0017 JMP #000D + 0x98000A04, // 0018 SETIDX R0 R5 R4 + 0x7001FFEE, // 0019 JMP #0009 + 0x58080003, // 001A LDCONST R2 K3 + 0xAC080200, // 001B CATCH R2 1 0 + 0xB0080000, // 001C RAISE 2 R0 R0 + 0x80040000, // 001D RET 1 R0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: _load +********************************************************************/ +be_local_closure(HASPmota__load, /* name */ + be_nested_proto( + 14, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[17]) { /* constants */ + /* K0 */ be_nested_str_weak(string), + /* K1 */ be_nested_str_weak(json), + /* K2 */ be_nested_str_weak(lvh_page_cur_idx), + /* K3 */ be_const_int(1), + /* K4 */ be_nested_str_weak(lvh_page), + /* K5 */ be_nested_str_weak(lvh_pages), + /* K6 */ be_nested_str_weak(r), + /* K7 */ be_nested_str_weak(read), + /* K8 */ be_nested_str_weak(close), + /* K9 */ be_nested_str_weak(split), + /* K10 */ be_nested_str_weak(_X0A), + /* K11 */ be_const_int(0), + /* K12 */ be_nested_str_weak(load), + /* K13 */ be_nested_str_weak(instance), + /* K14 */ be_nested_str_weak(parse_page), + /* K15 */ be_nested_str_weak(parse_obj), + /* K16 */ be_nested_str_weak(remove), + }), + be_str_weak(_load), + &be_const_str_solidified, + ( &(const binstruction[54]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0xA40E0200, // 0001 IMPORT R3 K1 + 0x90020503, // 0002 SETMBR R0 K2 K3 + 0x88100104, // 0003 GETMBR R4 R0 K4 + 0x88140105, // 0004 GETMBR R5 R0 K5 + 0x5C180800, // 0005 MOVE R6 R4 + 0x581C0003, // 0006 LDCONST R7 K3 + 0x5C200000, // 0007 MOVE R8 R0 + 0x7C180400, // 0008 CALL R6 2 + 0x98160606, // 0009 SETIDX R5 K3 R6 + 0x60140011, // 000A GETGBL R5 G17 + 0x5C180200, // 000B MOVE R6 R1 + 0x581C0006, // 000C LDCONST R7 K6 + 0x7C140400, // 000D CALL R5 2 + 0x8C180B07, // 000E GETMET R6 R5 K7 + 0x7C180200, // 000F CALL R6 1 + 0x8C1C0B08, // 0010 GETMET R7 R5 K8 + 0x7C1C0200, // 0011 CALL R7 1 + 0x8C1C0509, // 0012 GETMET R7 R2 K9 + 0x5C240C00, // 0013 MOVE R9 R6 + 0x5828000A, // 0014 LDCONST R10 K10 + 0x7C1C0600, // 0015 CALL R7 3 + 0x4C140000, // 0016 LDNIL R5 + 0x4C180000, // 0017 LDNIL R6 + 0x6020000C, // 0018 GETGBL R8 G12 + 0x5C240E00, // 0019 MOVE R9 R7 + 0x7C200200, // 001A CALL R8 1 + 0x2420110B, // 001B GT R8 R8 K11 + 0x78220015, // 001C JMPF R8 #0033 + 0x8C20070C, // 001D GETMET R8 R3 K12 + 0x94280F0B, // 001E GETIDX R10 R7 K11 + 0x7C200400, // 001F CALL R8 2 + 0x60240004, // 0020 GETGBL R9 G4 + 0x5C281000, // 0021 MOVE R10 R8 + 0x7C240200, // 0022 CALL R9 1 + 0x1C24130D, // 0023 EQ R9 R9 K13 + 0x78260008, // 0024 JMPF R9 #002E + 0x8C24010E, // 0025 GETMET R9 R0 K14 + 0x5C2C1000, // 0026 MOVE R11 R8 + 0x7C240400, // 0027 CALL R9 2 + 0x8C24010F, // 0028 GETMET R9 R0 K15 + 0x5C2C1000, // 0029 MOVE R11 R8 + 0x88300105, // 002A GETMBR R12 R0 K5 + 0x88340102, // 002B GETMBR R13 R0 K2 + 0x9430180D, // 002C GETIDX R12 R12 R13 + 0x7C240600, // 002D CALL R9 3 + 0x4C200000, // 002E LDNIL R8 + 0x8C240F10, // 002F GETMET R9 R7 K16 + 0x582C000B, // 0030 LDCONST R11 K11 + 0x7C240400, // 0031 CALL R9 2 + 0x7001FFE4, // 0032 JMP #0018 + 0x4C1C0000, // 0033 LDNIL R7 + 0x90020503, // 0034 SETMBR R0 K2 K3 + 0x80000000, // 0035 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: parse_page +********************************************************************/ +be_local_closure(HASPmota_parse_page, /* name */ + be_nested_proto( + 9, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[14]) { /* constants */ + /* K0 */ be_nested_str_weak(has), + /* K1 */ be_nested_str_weak(page), + /* K2 */ be_nested_str_weak(int), + /* K3 */ be_nested_str_weak(lvh_page_cur_idx), + /* K4 */ be_nested_str_weak(lvh_pages), + /* K5 */ be_nested_str_weak(contains), + /* K6 */ be_nested_str_weak(lvh_page), + /* K7 */ be_nested_str_weak(find), + /* K8 */ be_nested_str_weak(id), + /* K9 */ be_const_int(0), + /* K10 */ be_nested_str_weak(get_page_cur), + /* K11 */ be_nested_str_weak(prev), + /* K12 */ be_nested_str_weak(next), + /* K13 */ be_nested_str_weak(back), + }), + be_str_weak(parse_page), + &be_const_str_solidified, + ( &(const binstruction[54]) { /* code */ + 0x8C080300, // 0000 GETMET R2 R1 K0 + 0x58100001, // 0001 LDCONST R4 K1 + 0x7C080400, // 0002 CALL R2 2 + 0x780A0030, // 0003 JMPF R2 #0035 + 0x60080004, // 0004 GETGBL R2 G4 + 0x940C0301, // 0005 GETIDX R3 R1 K1 + 0x7C080200, // 0006 CALL R2 1 + 0x1C080502, // 0007 EQ R2 R2 K2 + 0x780A002B, // 0008 JMPF R2 #0035 + 0x60080009, // 0009 GETGBL R2 G9 + 0x940C0301, // 000A GETIDX R3 R1 K1 + 0x7C080200, // 000B CALL R2 1 + 0x90020602, // 000C SETMBR R0 K3 R2 + 0x880C0104, // 000D GETMBR R3 R0 K4 + 0x8C0C0705, // 000E GETMET R3 R3 K5 + 0x5C140400, // 000F MOVE R5 R2 + 0x7C0C0400, // 0010 CALL R3 2 + 0x740E0006, // 0011 JMPT R3 #0019 + 0x880C0106, // 0012 GETMBR R3 R0 K6 + 0x88100104, // 0013 GETMBR R4 R0 K4 + 0x5C140600, // 0014 MOVE R5 R3 + 0x5C180400, // 0015 MOVE R6 R2 + 0x5C1C0000, // 0016 MOVE R7 R0 + 0x7C140400, // 0017 CALL R5 2 + 0x98100405, // 0018 SETIDX R4 R2 R5 + 0x8C0C0307, // 0019 GETMET R3 R1 K7 + 0x58140008, // 001A LDCONST R5 K8 + 0x7C0C0400, // 001B CALL R3 2 + 0x1C0C0709, // 001C EQ R3 R3 K9 + 0x780E0016, // 001D JMPF R3 #0035 + 0x8C0C010A, // 001E GETMET R3 R0 K10 + 0x7C0C0200, // 001F CALL R3 1 + 0x60100009, // 0020 GETGBL R4 G9 + 0x8C140307, // 0021 GETMET R5 R1 K7 + 0x581C000B, // 0022 LDCONST R7 K11 + 0x4C200000, // 0023 LDNIL R8 + 0x7C140600, // 0024 CALL R5 3 + 0x7C100200, // 0025 CALL R4 1 + 0x900E1604, // 0026 SETMBR R3 K11 R4 + 0x60100009, // 0027 GETGBL R4 G9 + 0x8C140307, // 0028 GETMET R5 R1 K7 + 0x581C000C, // 0029 LDCONST R7 K12 + 0x4C200000, // 002A LDNIL R8 + 0x7C140600, // 002B CALL R5 3 + 0x7C100200, // 002C CALL R4 1 + 0x900E1804, // 002D SETMBR R3 K12 R4 + 0x60100009, // 002E GETGBL R4 G9 + 0x8C140307, // 002F GETMET R5 R1 K7 + 0x581C000D, // 0030 LDCONST R7 K13 + 0x4C200000, // 0031 LDNIL R8 + 0x7C140600, // 0032 CALL R5 3 + 0x7C100200, // 0033 CALL R4 1 + 0x900E1A04, // 0034 SETMBR R3 K13 R4 + 0x80000000, // 0035 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: page_dir_to ********************************************************************/ @@ -7369,7 +7919,7 @@ be_local_closure(HASPmota_parse_obj, /* name */ /* K18 */ be_nested_str_weak(class), /* K19 */ be_nested_str_weak(lvh_obj), /* K20 */ be_nested_str_weak(module), - /* K21 */ be_nested_str_weak(HSP_X3A_X20cannot_X20find_X20object_X20of_X20type_X20), + /* K21 */ be_nested_str_weak(HSP_X3A_X20Cannot_X20find_X20object_X20of_X20type_X20), /* K22 */ be_nested_str_weak(set_obj), /* K23 */ be_nested_str_weak(p_X25ib_X25i), /* K24 */ be_nested_str_weak(function), @@ -7611,52 +8161,53 @@ be_local_closure(HASPmota_parse_obj, /* name */ be_local_class(HASPmota, 10, NULL, - be_nested_map(44, + be_nested_map(45, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(event, -1), be_const_var(8) }, - { be_const_key_weak(parse_obj, 4), be_const_closure(HASPmota_parse_obj_closure) }, - { be_const_key_weak(lvh_scr, -1), be_const_class(be_class_lvh_scr) }, - { be_const_key_weak(do_action, 16), be_const_closure(HASPmota_do_action_closure) }, - { be_const_key_weak(lvh_switch, -1), be_const_class(be_class_lvh_switch) }, - { be_const_key_weak(lvh_page, 9), be_const_class(be_class_lvh_page) }, - { be_const_key_weak(lvh_obj, -1), be_const_class(be_class_lvh_obj) }, - { be_const_key_weak(register_event, -1), be_const_closure(HASPmota_register_event_closure) }, - { be_const_key_weak(parse, 35), be_const_closure(HASPmota_parse_closure) }, - { be_const_key_weak(event_cb, -1), be_const_var(9) }, - { be_const_key_weak(event_dispatch, -1), be_const_closure(HASPmota_event_dispatch_closure) }, - { be_const_key_weak(lvh_dropdown, 6), be_const_class(be_class_lvh_dropdown) }, - { be_const_key_weak(pages_list_sorted, -1), be_const_closure(HASPmota_pages_list_sorted_closure) }, - { be_const_key_weak(dark, -1), be_const_var(0) }, - { be_const_key_weak(lvh_roller, 21), be_const_class(be_class_lvh_roller) }, - { be_const_key_weak(lvh_btnmatrix, 23), be_const_class(be_class_lvh_btnmatrix) }, - { be_const_key_weak(hres, -1), be_const_var(1) }, - { be_const_key_weak(sort, -1), be_const_static_closure(HASPmota_sort_closure) }, - { be_const_key_weak(parse_page, 25), be_const_closure(HASPmota_parse_page_closure) }, - { be_const_key_weak(lvh_spinner, -1), be_const_class(be_class_lvh_spinner) }, - { be_const_key_weak(lvh_btn, 39), be_const_class(be_class_lvh_btn) }, - { be_const_key_weak(r16, -1), be_const_var(4) }, - { be_const_key_weak(page_show, 20), be_const_closure(HASPmota_page_show_closure) }, - { be_const_key_weak(scr, 41), be_const_var(3) }, - { be_const_key_weak(deinit, -1), be_const_closure(HASPmota_deinit_closure) }, - { be_const_key_weak(lvh_arc, -1), be_const_class(be_class_lvh_arc) }, - { be_const_key_weak(lvh_pages, -1), be_const_var(5) }, - { be_const_key_weak(start, 28), be_const_closure(HASPmota_start_closure) }, - { be_const_key_weak(lvh_bar, -1), be_const_class(be_class_lvh_bar) }, - { be_const_key_weak(vres, -1), be_const_var(2) }, - { be_const_key_weak(lvh_textarea, -1), be_const_class(be_class_lvh_textarea) }, - { be_const_key_weak(init, -1), be_const_closure(HASPmota_init_closure) }, - { be_const_key_weak(lvh_line, 30), be_const_class(be_class_lvh_line) }, - { be_const_key_weak(def_templ_name, -1), be_nested_str_weak(pages_X2Ejsonl) }, { be_const_key_weak(re_page_target, -1), be_const_var(7) }, - { be_const_key_weak(lvh_qrcode, -1), be_const_class(be_class_lvh_qrcode) }, - { be_const_key_weak(lvh_page_cur_idx, -1), be_const_var(6) }, - { be_const_key_weak(lvh_img, -1), be_const_class(be_class_lvh_img) }, - { be_const_key_weak(page_dir_to, -1), be_const_closure(HASPmota_page_dir_to_closure) }, - { be_const_key_weak(_load, -1), be_const_closure(HASPmota__load_closure) }, + { be_const_key_weak(lvh_pages, -1), be_const_var(5) }, + { be_const_key_weak(lvh_scr, -1), be_const_class(be_class_lvh_scr) }, + { be_const_key_weak(register_event, 44), be_const_closure(HASPmota_register_event_closure) }, + { be_const_key_weak(lvh_line, -1), be_const_class(be_class_lvh_line) }, + { be_const_key_weak(dark, 33), be_const_var(0) }, + { be_const_key_weak(pages_list_sorted, 37), be_const_closure(HASPmota_pages_list_sorted_closure) }, + { be_const_key_weak(parse, -1), be_const_closure(HASPmota_parse_closure) }, + { be_const_key_weak(lvh_page_cur_idx, 19), be_const_var(6) }, + { be_const_key_weak(parse_obj, 23), be_const_closure(HASPmota_parse_obj_closure) }, { be_const_key_weak(lvh_label, -1), be_const_class(be_class_lvh_label) }, + { be_const_key_weak(start, 10), be_const_closure(HASPmota_start_closure) }, + { be_const_key_weak(lvh_chart, -1), be_const_class(be_class_lvh_chart) }, + { be_const_key_weak(page_show, -1), be_const_closure(HASPmota_page_show_closure) }, { be_const_key_weak(lvh_checkbox, -1), be_const_class(be_class_lvh_checkbox) }, - { be_const_key_weak(get_page_cur, 1), be_const_closure(HASPmota_get_page_cur_closure) }, - { be_const_key_weak(lvh_slider, 0), be_const_class(be_class_lvh_slider) }, + { be_const_key_weak(init, -1), be_const_closure(HASPmota_init_closure) }, + { be_const_key_weak(lvh_obj, -1), be_const_class(be_class_lvh_obj) }, + { be_const_key_weak(get_page_cur, -1), be_const_closure(HASPmota_get_page_cur_closure) }, + { be_const_key_weak(hres, 12), be_const_var(1) }, + { be_const_key_weak(parse_page, 17), be_const_closure(HASPmota_parse_page_closure) }, + { be_const_key_weak(_load, 21), be_const_closure(HASPmota__load_closure) }, + { be_const_key_weak(lvh_slider, -1), be_const_class(be_class_lvh_slider) }, + { be_const_key_weak(deinit, -1), be_const_closure(HASPmota_deinit_closure) }, + { be_const_key_weak(lvh_roller, -1), be_const_class(be_class_lvh_roller) }, + { be_const_key_weak(lvh_spinner, 28), be_const_class(be_class_lvh_spinner) }, + { be_const_key_weak(event_dispatch, -1), be_const_closure(HASPmota_event_dispatch_closure) }, + { be_const_key_weak(vres, -1), be_const_var(2) }, + { be_const_key_weak(event_cb, 32), be_const_var(9) }, + { be_const_key_weak(event, 38), be_const_var(8) }, + { be_const_key_weak(lvh_btn, -1), be_const_class(be_class_lvh_btn) }, + { be_const_key_weak(r16, -1), be_const_var(4) }, + { be_const_key_weak(lvh_arc, -1), be_const_class(be_class_lvh_arc) }, + { be_const_key_weak(lvh_dropdown, 18), be_const_class(be_class_lvh_dropdown) }, + { be_const_key_weak(do_action, 16), be_const_closure(HASPmota_do_action_closure) }, + { be_const_key_weak(def_templ_name, 26), be_nested_str_weak(pages_X2Ejsonl) }, + { be_const_key_weak(lvh_btnmatrix, 9), be_const_class(be_class_lvh_btnmatrix) }, + { be_const_key_weak(sort, 20), be_const_static_closure(HASPmota_sort_closure) }, + { be_const_key_weak(lvh_qrcode, -1), be_const_class(be_class_lvh_qrcode) }, + { be_const_key_weak(lvh_bar, -1), be_const_class(be_class_lvh_bar) }, + { be_const_key_weak(lvh_page, -1), be_const_class(be_class_lvh_page) }, + { be_const_key_weak(lvh_textarea, -1), be_const_class(be_class_lvh_textarea) }, + { be_const_key_weak(scr, -1), be_const_var(3) }, + { be_const_key_weak(page_dir_to, -1), be_const_closure(HASPmota_page_dir_to_closure) }, + { be_const_key_weak(lvh_switch, -1), be_const_class(be_class_lvh_switch) }, + { be_const_key_weak(lvh_img, -1), be_const_class(be_class_lvh_img) }, })), be_str_weak(HASPmota) ); diff --git a/tasmota/berry/haspmota_src/haspmota_core/haspmota.be b/tasmota/berry/haspmota_src/haspmota_core/haspmota.be index 2352c3128..40c5bb438 100644 --- a/tasmota/berry/haspmota_src/haspmota_core/haspmota.be +++ b/tasmota/berry/haspmota_src/haspmota_core/haspmota.be @@ -20,7 +20,7 @@ var classes = [ "btn", "switch", "checkbox", "label", "spinner", "line", "img", "roller", "btnmatrix", "bar", "slider", "arc", "textarea", "dropdown", - "qrcode" + "qrcode", "chart" ] var f = open("haspmota.c", "w") for c:classes @@ -73,6 +73,9 @@ class lvh_obj "y": "y", "w": "width", "h": "height", + # special case for height/width that can be in styles + "height": "style_height", + "width": "style_width", # arc # "asjustable": nil, # "mode": nil, @@ -96,6 +99,7 @@ class lvh_obj "bg_grad_color": "style_bg_grad_color", "bg_grad_dir": "style_bg_grad_dir", "line_color": "style_line_color", + "line_rounded": "style_line_rounded", "pad_left": "style_pad_left", "pad_right": "style_pad_right", "pad_top": "style_pad_top", @@ -836,6 +840,12 @@ class lvh_obj end end + # finally try any `get_XXX` within the LVGL object + f = introspect.get(self._lv_obj, "get_" + k) + if type(f) == 'function' # found and function, call it + return f(self._lv_obj) + end + # fallback to exception if attribute unknown or not a function raise "value_error", "unknown attribute " + str(k) end @@ -905,7 +915,16 @@ class lvh_obj print("HSP: Could not find function set_"+kv) end else - print("HSP: unknown attribute:", k) + f = introspect.get(self._lv_obj, "set_" + k) + if type(f) == 'function' + try + f(self._lv_obj, v) + except .. as e, m + raise e, m + " for " + k + end + else + print("HSP: unknown attribute:", k) + end end end @@ -1328,6 +1347,79 @@ class lvh_bar : lvh_obj end end +################################################################################# +# Special case for lv.chart +# Adapted to getting values one after the other +################################################################################# +class lvh_chart : lvh_obj + static _lv_class = lv.chart + # ser1/ser2 contains the first/second series of data + var ser1, ser2 + # y_min/y_max contain the main range for y. Since LVGL does not have getters, we need to memorize on our side the lates tvalues + var y_min, y_max + # h_div/v_div contain the horizontal and vertical divisions, we need to memorize values because both are set from same API + var h_div, v_div + + def post_init() + # default values from LVGL are 0..100 + self.y_min = 0 + self.y_max = 100 + # default values + #define LV_CHART_HDIV_DEF 3 + #define LV_CHART_VDIV_DEF 5 + self.h_div = 3 + self.v_div = 5 + + self._lv_obj.set_update_mode(lv.CHART_UPDATE_MODE_SHIFT) + + self.ser1 = self._lv_obj.add_series(lv.color(0xEE4444), lv.CHART_AXIS_PRIMARY_Y) + self.ser2 = self._lv_obj.add_series(lv.color(0x44EE44), lv.CHART_AXIS_PRIMARY_Y) + end + + def add_point(v) + self._lv_obj.set_next_value(self.ser1, v) + end + def add_point2(v) + self._lv_obj.set_next_value(self.ser2, v) + end + + def set_val(v) + self.add_point(v) + end + def set_val2(v) + self.add_point2(v) + end + def get_y_min() + return self.y_min + end + def get_y_max() + return self.y_max + end + def set_y_min(y_min) + self.y_min = y_min + self._lv_obj.set_range(lv.CHART_AXIS_PRIMARY_Y, self.y_min, self.y_max) + end + def set_y_max(y_max) + self.y_max = y_max + self._lv_obj.set_range(lv.CHART_AXIS_PRIMARY_Y, self.y_min, self.y_max) + end + + def set_series1_color(color) + self._lv_obj.set_series_color(self.ser1, color) + end + def set_series2_color(color) + self._lv_obj.set_series_color(self.ser2, color) + end + def set_h_div_line_count(h_div) + self.h_div = h_div + self._lv_obj.set_div_line_count(self.h_div, self.v_div) + end + def set_v_div_line_count(v_div) + self.v_div = v_div + self._lv_obj.set_div_line_count(self.h_div, self.v_div) + end +end + ################################################################################# # # All other subclasses than just map the LVGL object @@ -1523,6 +1615,8 @@ class HASPmota # static lvh_gauge = lvh_gauge static lvh_textarea = lvh_textarea # additional? static lvh_qrcode = lvh_qrcode + # special cases + static lvh_chart = lvh_chart static def_templ_name = "pages.jsonl" # default template name @@ -1912,7 +2006,7 @@ class HASPmota end if obj_class == nil - print("HSP: cannot find object of type " + str(obj_type)) + print("HSP: Cannot find object of type " + str(obj_type)) return end From 03aea58a4cd8aabef08830b0e21879e9596f26cd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Jan 2024 14:29:23 +0100 Subject: [PATCH 069/303] Bump version v13.2.0.2 --- CHANGELOG.md | 22 ++++++++++++++++------ RELEASENOTES.md | 7 ++++--- tasmota/include/tasmota_version.h | 2 +- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32eb2fd88..11631b509 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,20 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - Development -## [13.3.0.1] +## [13.3.0.2] +### Added +- HASPmota type `chart` (#20372) + +### Breaking Changed + +### Changed + +### Fixed + +### Removed + + +## [13.3.0.1] 20240101 ### Added - Support for Sonoff Basic R4 Magic Switch (#20247) - Support for CST816S touch interface (#20213) @@ -11,10 +24,9 @@ All notable changes to this project will be documented in this file. - Matter support for password for remote Tasmota devices (#20296) - Display of active drivers using command ``status 4`` - ESP32 used UART information -- HASPmota added `haspmota.page_show()` to change page (#20333) -- Berry added `introspect.set()` for class attributes (#20339) +- HASPmota `haspmota.page_show()` to change page (#20333) +- Berry `introspect.set()` for class attributes (#20339) - Support negative power on BL0942 using index 5..8 (#20322) -- HASPmota type `chart` ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds (#20236) @@ -33,8 +45,6 @@ All notable changes to this project will be documented in this file. - Berry claiming UART0 if needed (#20324) - LVGL fix type for lv_imgbtn (#20354) -### Removed - ## [Released] ## [13.3.0] 20231213 diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 822337b19..6198b8991 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -116,7 +116,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm [Complete list](BUILDS.md) of available feature and sensors. -## Changelog v13.3.0.1 +## Changelog v13.3.0.2 ### Added - Support for CST816S touch interface [#20213](https://github.com/arendst/Tasmota/issues/20213) - Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247) @@ -124,8 +124,9 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) - Support negative power on BL0942 using index 5..8 [#20322](https://github.com/arendst/Tasmota/issues/20322) - ESP32 used UART information -- Berry added `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) -- HASPmota added `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) +- Berry `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) +- HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) +- HASPmota type `chart` [#20372](https://github.com/arendst/Tasmota/issues/20372) - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) ### Breaking Changed diff --git a/tasmota/include/tasmota_version.h b/tasmota/include/tasmota_version.h index 94bd18c62..ac87a0ef4 100644 --- a/tasmota/include/tasmota_version.h +++ b/tasmota/include/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t TASMOTA_VERSION = 0x0D030001; // 13.3.0.1 +const uint32_t TASMOTA_VERSION = 0x0D030002; // 13.3.0.2 #endif // _TASMOTA_VERSION_H_ From 6768ebc2ac8d76b788495259ceee78eccdd25255 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Wed, 3 Jan 2024 16:12:47 +0100 Subject: [PATCH 070/303] Berry fix static allocation when superclass is a member (#20385) --- lib/libesp32/berry/src/be_parser.c | 14 +++++--------- lib/libesp32/berry/tests/class_static.be | 9 +++++++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/libesp32/berry/src/be_parser.c b/lib/libesp32/berry/src/be_parser.c index 3afedf41c..be001bf97 100644 --- a/lib/libesp32/berry/src/be_parser.c +++ b/lib/libesp32/berry/src/be_parser.c @@ -1571,15 +1571,11 @@ static void class_stmt(bparser *parser) begin_block(parser->finfo, &binfo, 0); bstring *class_str = parser_newstr(parser, "_class"); /* we always define `_class` local variable */ - if (e.type == ETLOCAL) { - bexpdesc e1; /* if inline class, we add a second local variable for _class */ - init_exp(&e1, ETLOCAL, 0); - e1.v.idx = new_localvar(parser, class_str); - be_code_setvar(parser->finfo, &e1, &e, 1); - } else { /* if global class, we just reuse the newly created class in the register */ - init_exp(&e, ETLOCAL, 0); - e.v.idx = new_localvar(parser, class_str); - } + bexpdesc e1; /* if inline class, we add a second local variable for _class */ + init_exp(&e1, ETLOCAL, 0); + e1.v.idx = new_localvar(parser, class_str); + be_code_setvar(parser->finfo, &e1, &e, 1); + begin_varinfo(parser, class_str); class_block(parser, c, &e); diff --git a/lib/libesp32/berry/tests/class_static.be b/lib/libesp32/berry/tests/class_static.be index dbe8c222e..b56c5d282 100644 --- a/lib/libesp32/berry/tests/class_static.be +++ b/lib/libesp32/berry/tests/class_static.be @@ -155,3 +155,12 @@ assert(A.a == 1) assert(A.b == A) assert(A.c == [1, A]) assert(A.f(1) == A) + +# bug when superclass is a member +# the following would break with: +# +# attribute_error: class 'B' cannot assign to static attribute 'aa' +# stack traceback: +# stdin:1: in function `main` +class B end m = module('m') m.B = B +class A : m.B static aa = 1 end From 9d27f395d8012c4fd1e3d74384d50d215679fecb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 4 Jan 2024 18:28:37 +0100 Subject: [PATCH 071/303] Add ESP32 experimental support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled --- CHANGELOG.md | 1 + RELEASENOTES.md | 1 + tasmota/tasmota.ino | 15 +++++++++++++++ 3 files changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11631b509..d6382c1f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. ## [13.3.0.2] ### Added - HASPmota type `chart` (#20372) +- ESP32 experimental support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled ### Breaking Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6198b8991..f566b94db 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -124,6 +124,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) - Support negative power on BL0942 using index 5..8 [#20322](https://github.com/arendst/Tasmota/issues/20322) - ESP32 used UART information +- ESP32 experimental support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled - Berry `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) - HASPmota type `chart` [#20372](https://github.com/arendst/Tasmota/issues/20372) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 7febc7a3b..aa8802215 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -17,6 +17,12 @@ along with this program. If not, see . */ +//#define USE_ESP32_GPIO_VIEWER +#ifdef USE_ESP32_GPIO_VIEWER +#include // Must me the first include in your project +GPIOViewer gpio_viewer; +#endif // USE_ESP32_GPIO_VIEWER + // Location specific includes #ifndef ESP32_STAGE // ESP32 Stage has no core_version.h file. Disable include via PlatformIO Option #include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_7_1) @@ -892,6 +898,15 @@ void Scheduler(void) { #ifndef SYSLOG_UPDATE_SECOND SyslogAsync(false); #endif // SYSLOG_UPDATE_SECOND + +#ifdef USE_ESP32_GPIO_VIEWER + static bool gpio_viewer_wifi_connected = false; + if (!gpio_viewer_wifi_connected && !TasmotaGlobal.global_state.network_down) { + gpio_viewer_wifi_connected = true; + gpio_viewer.setSamplingInterval(200); // You can set the sampling interval in ms, if not set default is 100ms + gpio_viewer.begin(); + } +#endif // USE_ESP32_GPIO_VIEWER } void loop(void) { From 7042b8344cdcffa2e91dc0f9fdb701b0b629ad8d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 4 Jan 2024 18:31:04 +0100 Subject: [PATCH 072/303] Add libs --- lib/libesp32/AsyncTCP/LICENSE | 165 ++ lib/libesp32/AsyncTCP/README.md | 8 + lib/libesp32/AsyncTCP/library.properties | 9 + lib/libesp32/AsyncTCP/src/AsyncTCP.cpp | 1357 +++++++++++++++ lib/libesp32/AsyncTCP/src/AsyncTCP.h | 217 +++ lib/libesp32/ESPAsyncWebServer/.gitignore | 2 + lib/libesp32/ESPAsyncWebServer/.travis.yml | 46 + lib/libesp32/ESPAsyncWebServer/CMakeLists.txt | 17 + lib/libesp32/ESPAsyncWebServer/README.md | 1521 +++++++++++++++++ lib/libesp32/ESPAsyncWebServer/_config.yml | 1 + lib/libesp32/ESPAsyncWebServer/component.mk | 3 + .../examples/CaptivePortal/CaptivePortal.ino | 47 + .../ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino | 221 +++ .../examples/regex_patterns/.test.build_flags | 1 + .../regex_patterns/regex_patterns.ino | 77 + .../examples/simple_server/simple_server.ino | 74 + lib/libesp32/ESPAsyncWebServer/keywords.txt | 3 + lib/libesp32/ESPAsyncWebServer/library.json | 37 + .../ESPAsyncWebServer/library.properties | 9 + .../src/AsyncEventSource.cpp | 368 ++++ .../ESPAsyncWebServer/src/AsyncEventSource.h | 133 ++ .../ESPAsyncWebServer/src/AsyncJson.h | 254 +++ .../ESPAsyncWebServer/src/AsyncWebSocket.cpp | 1294 ++++++++++++++ .../ESPAsyncWebServer/src/AsyncWebSocket.h | 350 ++++ .../src/AsyncWebSynchronization.h | 87 + .../ESPAsyncWebServer/src/ESPAsyncWebServer.h | 471 +++++ .../ESPAsyncWebServer/src/SPIFFSEditor.cpp | 544 ++++++ .../ESPAsyncWebServer/src/SPIFFSEditor.h | 24 + .../ESPAsyncWebServer/src/StringArray.h | 193 +++ .../src/WebAuthentication.cpp | 235 +++ .../ESPAsyncWebServer/src/WebAuthentication.h | 34 + .../ESPAsyncWebServer/src/WebHandlerImpl.h | 151 ++ .../ESPAsyncWebServer/src/WebHandlers.cpp | 220 +++ .../ESPAsyncWebServer/src/WebRequest.cpp | 1008 +++++++++++ .../ESPAsyncWebServer/src/WebResponseImpl.h | 136 ++ .../ESPAsyncWebServer/src/WebResponses.cpp | 699 ++++++++ .../ESPAsyncWebServer/src/WebServer.cpp | 193 +++ lib/libesp32/ESPAsyncWebServer/src/edit.htm | 627 +++++++ lib/libesp32/gpio_viewer/.gitignore | 4 + lib/libesp32/gpio_viewer/LICENSE | 21 + lib/libesp32/gpio_viewer/README.md | 94 + .../examples/gpioviewer/gpioviewer.ino | 30 + lib/libesp32/gpio_viewer/gpio_viewer.ino | 149 ++ lib/libesp32/gpio_viewer/keywords.txt | 16 + lib/libesp32/gpio_viewer/library.properties | 11 + lib/libesp32/gpio_viewer/src/gpio_viewer.h | 360 ++++ 46 files changed, 11521 insertions(+) create mode 100644 lib/libesp32/AsyncTCP/LICENSE create mode 100644 lib/libesp32/AsyncTCP/README.md create mode 100644 lib/libesp32/AsyncTCP/library.properties create mode 100644 lib/libesp32/AsyncTCP/src/AsyncTCP.cpp create mode 100644 lib/libesp32/AsyncTCP/src/AsyncTCP.h create mode 100644 lib/libesp32/ESPAsyncWebServer/.gitignore create mode 100644 lib/libesp32/ESPAsyncWebServer/.travis.yml create mode 100644 lib/libesp32/ESPAsyncWebServer/CMakeLists.txt create mode 100644 lib/libesp32/ESPAsyncWebServer/README.md create mode 100644 lib/libesp32/ESPAsyncWebServer/_config.yml create mode 100644 lib/libesp32/ESPAsyncWebServer/component.mk create mode 100644 lib/libesp32/ESPAsyncWebServer/examples/CaptivePortal/CaptivePortal.ino create mode 100644 lib/libesp32/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino create mode 100644 lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/.test.build_flags create mode 100644 lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/regex_patterns.ino create mode 100644 lib/libesp32/ESPAsyncWebServer/examples/simple_server/simple_server.ino create mode 100644 lib/libesp32/ESPAsyncWebServer/keywords.txt create mode 100644 lib/libesp32/ESPAsyncWebServer/library.json create mode 100644 lib/libesp32/ESPAsyncWebServer/library.properties create mode 100644 lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.cpp create mode 100644 lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.h create mode 100644 lib/libesp32/ESPAsyncWebServer/src/AsyncJson.h create mode 100644 lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.cpp create mode 100644 lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.h create mode 100644 lib/libesp32/ESPAsyncWebServer/src/AsyncWebSynchronization.h create mode 100644 lib/libesp32/ESPAsyncWebServer/src/ESPAsyncWebServer.h create mode 100644 lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.cpp create mode 100644 lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.h create mode 100644 lib/libesp32/ESPAsyncWebServer/src/StringArray.h create mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.cpp create mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.h create mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebHandlerImpl.h create mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebHandlers.cpp create mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebRequest.cpp create mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebResponseImpl.h create mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebResponses.cpp create mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebServer.cpp create mode 100644 lib/libesp32/ESPAsyncWebServer/src/edit.htm create mode 100644 lib/libesp32/gpio_viewer/.gitignore create mode 100644 lib/libesp32/gpio_viewer/LICENSE create mode 100644 lib/libesp32/gpio_viewer/README.md create mode 100644 lib/libesp32/gpio_viewer/examples/gpioviewer/gpioviewer.ino create mode 100644 lib/libesp32/gpio_viewer/gpio_viewer.ino create mode 100644 lib/libesp32/gpio_viewer/keywords.txt create mode 100644 lib/libesp32/gpio_viewer/library.properties create mode 100644 lib/libesp32/gpio_viewer/src/gpio_viewer.h diff --git a/lib/libesp32/AsyncTCP/LICENSE b/lib/libesp32/AsyncTCP/LICENSE new file mode 100644 index 000000000..65c5ca88a --- /dev/null +++ b/lib/libesp32/AsyncTCP/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/lib/libesp32/AsyncTCP/README.md b/lib/libesp32/AsyncTCP/README.md new file mode 100644 index 000000000..cde5f1482 --- /dev/null +++ b/lib/libesp32/AsyncTCP/README.md @@ -0,0 +1,8 @@ +### Async TCP Library for ESP32 Arduino + +This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP32 MCUs. + +This library is the base for [ESPAsyncWebServer](https://github.com/dvarrel/ESPAsyncWebServer) + +## AsyncClient and AsyncServer +The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use. diff --git a/lib/libesp32/AsyncTCP/library.properties b/lib/libesp32/AsyncTCP/library.properties new file mode 100644 index 000000000..2c6ff0a23 --- /dev/null +++ b/lib/libesp32/AsyncTCP/library.properties @@ -0,0 +1,9 @@ +name=AsyncTCP +version=1.1.4 +author=dvarrel +maintainer=dvarrel +sentence=Async TCP Library for ESP32. Forked from https://github.com/me-no-dev/AsyncTCP +paragraph=to build a WebServer, with files saved in flash +category=Communication +url=https://github.com/dvarrel/AsyncTCP +architectures=esp32 diff --git a/lib/libesp32/AsyncTCP/src/AsyncTCP.cpp b/lib/libesp32/AsyncTCP/src/AsyncTCP.cpp new file mode 100644 index 000000000..89ff6ee32 --- /dev/null +++ b/lib/libesp32/AsyncTCP/src/AsyncTCP.cpp @@ -0,0 +1,1357 @@ +/* + Asynchronous TCP library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "Arduino.h" + +#include "AsyncTCP.h" +extern "C"{ +#include "lwip/opt.h" +#include "lwip/tcp.h" +#include "lwip/inet.h" +#include "lwip/dns.h" +#include "lwip/err.h" +} +#include "esp_task_wdt.h" + +/* + * TCP/IP Event Task + * */ + +typedef enum { + LWIP_TCP_SENT, LWIP_TCP_RECV, LWIP_TCP_FIN, LWIP_TCP_ERROR, LWIP_TCP_POLL, LWIP_TCP_CLEAR, LWIP_TCP_ACCEPT, LWIP_TCP_CONNECTED, LWIP_TCP_DNS +} lwip_event_t; + +typedef struct { + lwip_event_t event; + void *arg; + union { + struct { + void * pcb; + int8_t err; + } connected; + struct { + int8_t err; + } error; + struct { + tcp_pcb * pcb; + uint16_t len; + } sent; + struct { + tcp_pcb * pcb; + pbuf * pb; + int8_t err; + } recv; + struct { + tcp_pcb * pcb; + int8_t err; + } fin; + struct { + tcp_pcb * pcb; + } poll; + struct { + AsyncClient * client; + } accept; + struct { + const char * name; + ip_addr_t addr; + } dns; + }; +} lwip_event_packet_t; + +static xQueueHandle _async_queue; +static TaskHandle_t _async_service_task_handle = NULL; + + +SemaphoreHandle_t _slots_lock; +const int _number_of_closed_slots = CONFIG_LWIP_MAX_ACTIVE_TCP; +static uint32_t _closed_slots[_number_of_closed_slots]; +static uint32_t _closed_index = []() { + _slots_lock = xSemaphoreCreateBinary(); + xSemaphoreGive(_slots_lock); + for (int i = 0; i < _number_of_closed_slots; ++ i) { + _closed_slots[i] = 1; + } + return 1; +}(); + + +static inline bool _init_async_event_queue(){ + if(!_async_queue){ + _async_queue = xQueueCreate(32, sizeof(lwip_event_packet_t *)); + if(!_async_queue){ + return false; + } + } + return true; +} + +static inline bool _send_async_event(lwip_event_packet_t ** e){ + return _async_queue && xQueueSend(_async_queue, e, portMAX_DELAY) == pdPASS; +} + +static inline bool _prepend_async_event(lwip_event_packet_t ** e){ + return _async_queue && xQueueSendToFront(_async_queue, e, portMAX_DELAY) == pdPASS; +} + +static inline bool _get_async_event(lwip_event_packet_t ** e){ + return _async_queue && xQueueReceive(_async_queue, e, portMAX_DELAY) == pdPASS; +} + +static bool _remove_events_with_arg(void * arg){ + lwip_event_packet_t * first_packet = NULL; + lwip_event_packet_t * packet = NULL; + + if(!_async_queue){ + return false; + } + //figure out which is the first packet so we can keep the order + while(!first_packet){ + if(xQueueReceive(_async_queue, &first_packet, 0) != pdPASS){ + return false; + } + //discard packet if matching + if((int)first_packet->arg == (int)arg){ + free(first_packet); + first_packet = NULL; + //return first packet to the back of the queue + } else if(xQueueSend(_async_queue, &first_packet, portMAX_DELAY) != pdPASS){ + return false; + } + } + + while(xQueuePeek(_async_queue, &packet, 0) == pdPASS && packet != first_packet){ + if(xQueueReceive(_async_queue, &packet, 0) != pdPASS){ + return false; + } + if((int)packet->arg == (int)arg){ + free(packet); + packet = NULL; + } else if(xQueueSend(_async_queue, &packet, portMAX_DELAY) != pdPASS){ + return false; + } + } + return true; +} + +static void _handle_async_event(lwip_event_packet_t * e){ + if(e->arg == NULL){ + // do nothing when arg is NULL + //ets_printf("event arg == NULL: 0x%08x\n", e->recv.pcb); + } else if(e->event == LWIP_TCP_CLEAR){ + _remove_events_with_arg(e->arg); + } else if(e->event == LWIP_TCP_RECV){ + //ets_printf("-R: 0x%08x\n", e->recv.pcb); + AsyncClient::_s_recv(e->arg, e->recv.pcb, e->recv.pb, e->recv.err); + } else if(e->event == LWIP_TCP_FIN){ + //ets_printf("-F: 0x%08x\n", e->fin.pcb); + AsyncClient::_s_fin(e->arg, e->fin.pcb, e->fin.err); + } else if(e->event == LWIP_TCP_SENT){ + //ets_printf("-S: 0x%08x\n", e->sent.pcb); + AsyncClient::_s_sent(e->arg, e->sent.pcb, e->sent.len); + } else if(e->event == LWIP_TCP_POLL){ + //ets_printf("-P: 0x%08x\n", e->poll.pcb); + AsyncClient::_s_poll(e->arg, e->poll.pcb); + } else if(e->event == LWIP_TCP_ERROR){ + //ets_printf("-E: 0x%08x %d\n", e->arg, e->error.err); + AsyncClient::_s_error(e->arg, e->error.err); + } else if(e->event == LWIP_TCP_CONNECTED){ + //ets_printf("C: 0x%08x 0x%08x %d\n", e->arg, e->connected.pcb, e->connected.err); + AsyncClient::_s_connected(e->arg, e->connected.pcb, e->connected.err); + } else if(e->event == LWIP_TCP_ACCEPT){ + //ets_printf("A: 0x%08x 0x%08x\n", e->arg, e->accept.client); + AsyncServer::_s_accepted(e->arg, e->accept.client); + } else if(e->event == LWIP_TCP_DNS){ + //ets_printf("D: 0x%08x %s = %s\n", e->arg, e->dns.name, ipaddr_ntoa(&e->dns.addr)); + AsyncClient::_s_dns_found(e->dns.name, &e->dns.addr, e->arg); + } + free((void*)(e)); +} + +static void _async_service_task(void *pvParameters){ + lwip_event_packet_t * packet = NULL; + for (;;) { + if(_get_async_event(&packet)){ +#if CONFIG_ASYNC_TCP_USE_WDT + if(esp_task_wdt_add(NULL) != ESP_OK){ + log_e("Failed to add async task to WDT"); + } +#endif + _handle_async_event(packet); +#if CONFIG_ASYNC_TCP_USE_WDT + if(esp_task_wdt_delete(NULL) != ESP_OK){ + log_e("Failed to remove loop task from WDT"); + } +#endif + } + } + vTaskDelete(NULL); + _async_service_task_handle = NULL; +} +/* +static void _stop_async_task(){ + if(_async_service_task_handle){ + vTaskDelete(_async_service_task_handle); + _async_service_task_handle = NULL; + } +} +*/ +static bool _start_async_task(){ + if(!_init_async_event_queue()){ + return false; + } + if(!_async_service_task_handle){ + xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); + if(!_async_service_task_handle){ + return false; + } + } + return true; +} + +/* + * LwIP Callbacks + * */ + +static int8_t _tcp_clear_events(void * arg) { + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_CLEAR; + e->arg = arg; + if (!_prepend_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; +} + +static int8_t _tcp_connected(void * arg, tcp_pcb * pcb, int8_t err) { + //ets_printf("+C: 0x%08x\n", pcb); + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_CONNECTED; + e->arg = arg; + e->connected.pcb = pcb; + e->connected.err = err; + if (!_prepend_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; +} + +static int8_t _tcp_poll(void * arg, struct tcp_pcb * pcb) { + //ets_printf("+P: 0x%08x\n", pcb); + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_POLL; + e->arg = arg; + e->poll.pcb = pcb; + if (!_send_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; +} + +static int8_t _tcp_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, int8_t err) { + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + e->arg = arg; + if(pb){ + //ets_printf("+R: 0x%08x\n", pcb); + e->event = LWIP_TCP_RECV; + e->recv.pcb = pcb; + e->recv.pb = pb; + e->recv.err = err; + } else { + //ets_printf("+F: 0x%08x\n", pcb); + e->event = LWIP_TCP_FIN; + e->fin.pcb = pcb; + e->fin.err = err; + //close the PCB in LwIP thread + AsyncClient::_s_lwip_fin(e->arg, e->fin.pcb, e->fin.err); + } + if (!_send_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; +} + +static int8_t _tcp_sent(void * arg, struct tcp_pcb * pcb, uint16_t len) { + //ets_printf("+S: 0x%08x\n", pcb); + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_SENT; + e->arg = arg; + e->sent.pcb = pcb; + e->sent.len = len; + if (!_send_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; +} + +static void _tcp_error(void * arg, int8_t err) { + //ets_printf("+E: 0x%08x\n", arg); + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_ERROR; + e->arg = arg; + e->error.err = err; + if (!_send_async_event(&e)) { + free((void*)(e)); + } +} + +static void _tcp_dns_found(const char * name, struct ip_addr * ipaddr, void * arg) { + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + //ets_printf("+DNS: name=%s ipaddr=0x%08x arg=%x\n", name, ipaddr, arg); + e->event = LWIP_TCP_DNS; + e->arg = arg; + e->dns.name = name; + if (ipaddr) { + memcpy(&e->dns.addr, ipaddr, sizeof(struct ip_addr)); + } else { + memset(&e->dns.addr, 0, sizeof(e->dns.addr)); + } + if (!_send_async_event(&e)) { + free((void*)(e)); + } +} + +//Used to switch out from LwIP thread +static int8_t _tcp_accept(void * arg, AsyncClient * client) { + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_ACCEPT; + e->arg = arg; + e->accept.client = client; + if (!_prepend_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; +} + +/* + * TCP/IP API Calls + * */ + +#include "lwip/priv/tcpip_priv.h" + +typedef struct { + struct tcpip_api_call_data call; + tcp_pcb * pcb; + int8_t closed_slot; + int8_t err; + union { + struct { + const char* data; + size_t size; + uint8_t apiflags; + } write; + size_t received; + struct { + ip_addr_t * addr; + uint16_t port; + tcp_connected_fn cb; + } connect; + struct { + ip_addr_t * addr; + uint16_t port; + } bind; + uint8_t backlog; + }; +} tcp_api_call_t; + +static err_t _tcp_output_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = ERR_CONN; + if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { + msg->err = tcp_output(msg->pcb); + } + return msg->err; +} + +static esp_err_t _tcp_output(tcp_pcb * pcb, int8_t closed_slot) { + if(!pcb){ + return ERR_CONN; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_write_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = ERR_CONN; + if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { + msg->err = tcp_write(msg->pcb, msg->write.data, msg->write.size, msg->write.apiflags); + } + return msg->err; +} + +static esp_err_t _tcp_write(tcp_pcb * pcb, int8_t closed_slot, const char* data, size_t size, uint8_t apiflags) { + if(!pcb){ + return ERR_CONN; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + msg.write.data = data; + msg.write.size = size; + msg.write.apiflags = apiflags; + tcpip_api_call(_tcp_write_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_recved_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = ERR_CONN; + if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { + msg->err = 0; + tcp_recved(msg->pcb, msg->received); + } + return msg->err; +} + +static esp_err_t _tcp_recved(tcp_pcb * pcb, int8_t closed_slot, size_t len) { + if(!pcb){ + return ERR_CONN; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + msg.received = len; + tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = ERR_CONN; + if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { + msg->err = tcp_close(msg->pcb); + } + return msg->err; +} + +static esp_err_t _tcp_close(tcp_pcb * pcb, int8_t closed_slot) { + if(!pcb){ + return ERR_CONN; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_abort_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = ERR_CONN; + if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { + tcp_abort(msg->pcb); + } + return msg->err; +} + +static esp_err_t _tcp_abort(tcp_pcb * pcb, int8_t closed_slot) { + if(!pcb){ + return ERR_CONN; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_connect_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = tcp_connect(msg->pcb, msg->connect.addr, msg->connect.port, msg->connect.cb); + return msg->err; +} + +static esp_err_t _tcp_connect(tcp_pcb * pcb, int8_t closed_slot, ip_addr_t * addr, uint16_t port, tcp_connected_fn cb) { + if(!pcb){ + return ESP_FAIL; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + msg.connect.addr = addr; + msg.connect.port = port; + msg.connect.cb = cb; + tcpip_api_call(_tcp_connect_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_bind_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = tcp_bind(msg->pcb, msg->bind.addr, msg->bind.port); + return msg->err; +} + +static esp_err_t _tcp_bind(tcp_pcb * pcb, ip_addr_t * addr, uint16_t port) { + if(!pcb){ + return ESP_FAIL; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = -1; + msg.bind.addr = addr; + msg.bind.port = port; + tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_listen_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = 0; + msg->pcb = tcp_listen_with_backlog(msg->pcb, msg->backlog); + return msg->err; +} + +static tcp_pcb * _tcp_listen_with_backlog(tcp_pcb * pcb, uint8_t backlog) { + if(!pcb){ + return NULL; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = -1; + msg.backlog = backlog?backlog:0xFF; + tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call_data*)&msg); + return msg.pcb; +} + + + +/* + Async TCP Client + */ + +AsyncClient::AsyncClient(tcp_pcb* pcb) +: _connect_cb(0) +, _connect_cb_arg(0) +, _discard_cb(0) +, _discard_cb_arg(0) +, _sent_cb(0) +, _sent_cb_arg(0) +, _error_cb(0) +, _error_cb_arg(0) +, _recv_cb(0) +, _recv_cb_arg(0) +, _pb_cb(0) +, _pb_cb_arg(0) +, _timeout_cb(0) +, _timeout_cb_arg(0) +, _pcb_busy(false) +, _pcb_sent_at(0) +, _ack_pcb(true) +, _rx_last_packet(0) +, _rx_since_timeout(0) +, _ack_timeout(ASYNC_MAX_ACK_TIME) +, _connect_port(0) +, prev(NULL) +, next(NULL) +{ + _pcb = pcb; + _closed_slot = -1; + if(_pcb){ + _allocate_closed_slot(); + _rx_last_packet = millis(); + tcp_arg(_pcb, this); + tcp_recv(_pcb, &_tcp_recv); + tcp_sent(_pcb, &_tcp_sent); + tcp_err(_pcb, &_tcp_error); + tcp_poll(_pcb, &_tcp_poll, 1); + } +} + +AsyncClient::~AsyncClient(){ + if(_pcb) { + _close(); + } + _free_closed_slot(); +} + +/* + * Operators + * */ + +AsyncClient& AsyncClient::operator=(const AsyncClient& other){ + if (_pcb) { + _close(); + } + + _pcb = other._pcb; + _closed_slot = other._closed_slot; + if (_pcb) { + _rx_last_packet = millis(); + tcp_arg(_pcb, this); + tcp_recv(_pcb, &_tcp_recv); + tcp_sent(_pcb, &_tcp_sent); + tcp_err(_pcb, &_tcp_error); + tcp_poll(_pcb, &_tcp_poll, 1); + } + return *this; +} + +bool AsyncClient::operator==(const AsyncClient &other) { + return _pcb == other._pcb; +} + +AsyncClient & AsyncClient::operator+=(const AsyncClient &other) { + if(next == NULL){ + next = (AsyncClient*)(&other); + next->prev = this; + } else { + AsyncClient *c = next; + while(c->next != NULL) { + c = c->next; + } + c->next =(AsyncClient*)(&other); + c->next->prev = c; + } + return *this; +} + +/* + * Callback Setters + * */ + +void AsyncClient::onConnect(AcConnectHandler cb, void* arg){ + _connect_cb = cb; + _connect_cb_arg = arg; +} + +void AsyncClient::onDisconnect(AcConnectHandler cb, void* arg){ + _discard_cb = cb; + _discard_cb_arg = arg; +} + +void AsyncClient::onAck(AcAckHandler cb, void* arg){ + _sent_cb = cb; + _sent_cb_arg = arg; +} + +void AsyncClient::onError(AcErrorHandler cb, void* arg){ + _error_cb = cb; + _error_cb_arg = arg; +} + +void AsyncClient::onData(AcDataHandler cb, void* arg){ + _recv_cb = cb; + _recv_cb_arg = arg; +} + +void AsyncClient::onPacket(AcPacketHandler cb, void* arg){ + _pb_cb = cb; + _pb_cb_arg = arg; +} + +void AsyncClient::onTimeout(AcTimeoutHandler cb, void* arg){ + _timeout_cb = cb; + _timeout_cb_arg = arg; +} + +void AsyncClient::onPoll(AcConnectHandler cb, void* arg){ + _poll_cb = cb; + _poll_cb_arg = arg; +} + +/* + * Main Public Methods + * */ + +bool AsyncClient::connect(IPAddress ip, uint16_t port){ + if (_pcb){ + log_w("already connected, state %d", _pcb->state); + return false; + } + if(!_start_async_task()){ + log_e("failed to start task"); + return false; + } + + ip_addr_t addr; + addr.type = IPADDR_TYPE_V4; + addr.u_addr.ip4.addr = ip; + + tcp_pcb* pcb = tcp_new_ip_type(IPADDR_TYPE_V4); + if (!pcb){ + log_e("pcb == NULL"); + return false; + } + + tcp_arg(pcb, this); + tcp_err(pcb, &_tcp_error); + tcp_recv(pcb, &_tcp_recv); + tcp_sent(pcb, &_tcp_sent); + tcp_poll(pcb, &_tcp_poll, 1); + //_tcp_connect(pcb, &addr, port,(tcp_connected_fn)&_s_connected); + _tcp_connect(pcb, _closed_slot, &addr, port,(tcp_connected_fn)&_tcp_connected); + return true; +} + +bool AsyncClient::connect(const char* host, uint16_t port){ + ip_addr_t addr; + + if(!_start_async_task()){ + log_e("failed to start task"); + return false; + } + + err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_tcp_dns_found, this); + if(err == ERR_OK) { + return connect(IPAddress(addr.u_addr.ip4.addr), port); + } else if(err == ERR_INPROGRESS) { + _connect_port = port; + return true; + } + log_e("error: %d", err); + return false; +} + +void AsyncClient::close(bool now){ + if(_pcb){ + _tcp_recved(_pcb, _closed_slot, _rx_ack_len); + } + _close(); +} + +int8_t AsyncClient::abort(){ + if(_pcb) { + _tcp_abort(_pcb, _closed_slot ); + _pcb = NULL; + } + return ERR_ABRT; +} + +size_t AsyncClient::space(){ + if((_pcb != NULL) && (_pcb->state == 4)){ + return tcp_sndbuf(_pcb); + } + return 0; +} + +size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) { + if(!_pcb || size == 0 || data == NULL) { + return 0; + } + size_t room = space(); + if(!room) { + return 0; + } + size_t will_send = (room < size) ? room : size; + int8_t err = ERR_OK; + err = _tcp_write(_pcb, _closed_slot, data, will_send, apiflags); + if(err != ERR_OK) { + return 0; + } + return will_send; +} + +bool AsyncClient::send(){ + int8_t err = ERR_OK; + err = _tcp_output(_pcb, _closed_slot); + if(err == ERR_OK){ + _pcb_busy = true; + _pcb_sent_at = millis(); + return true; + } + return false; +} + +size_t AsyncClient::ack(size_t len){ + if(len > _rx_ack_len) + len = _rx_ack_len; + if(len){ + _tcp_recved(_pcb, _closed_slot, len); + } + _rx_ack_len -= len; + return len; +} + +void AsyncClient::ackPacket(struct pbuf * pb){ + if(!pb){ + return; + } + _tcp_recved(_pcb, _closed_slot, pb->len); + pbuf_free(pb); +} + +/* + * Main Private Methods + * */ + +int8_t AsyncClient::_close(){ + //ets_printf("X: 0x%08x\n", (uint32_t)this); + int8_t err = ERR_OK; + if(_pcb) { + //log_i(""); + tcp_arg(_pcb, NULL); + tcp_sent(_pcb, NULL); + tcp_recv(_pcb, NULL); + tcp_err(_pcb, NULL); + tcp_poll(_pcb, NULL, 0); + _tcp_clear_events(this); + err = _tcp_close(_pcb, _closed_slot); + if(err != ERR_OK) { + err = abort(); + } + _pcb = NULL; + if(_discard_cb) { + _discard_cb(_discard_cb_arg, this); + } + } + return err; +} + +void AsyncClient::_allocate_closed_slot(){ + xSemaphoreTake(_slots_lock, portMAX_DELAY); + uint32_t closed_slot_min_index = 0; + for (int i = 0; i < _number_of_closed_slots; ++ i) { + if ((_closed_slot == -1 || _closed_slots[i] <= closed_slot_min_index) && _closed_slots[i] != 0) { + closed_slot_min_index = _closed_slots[i]; + _closed_slot = i; + } + } + if (_closed_slot != -1) { + _closed_slots[_closed_slot] = 0; + } + xSemaphoreGive(_slots_lock); +} + +void AsyncClient::_free_closed_slot(){ + if (_closed_slot != -1) { + _closed_slots[_closed_slot] = _closed_index; + _closed_slot = -1; + ++ _closed_index; + } +} + +/* + * Private Callbacks + * */ + +int8_t AsyncClient::_connected(void* pcb, int8_t err){ + _pcb = reinterpret_cast(pcb); + if(_pcb){ + _rx_last_packet = millis(); + _pcb_busy = false; +// tcp_recv(_pcb, &_tcp_recv); +// tcp_sent(_pcb, &_tcp_sent); +// tcp_poll(_pcb, &_tcp_poll, 1); + } + if(_connect_cb) { + _connect_cb(_connect_cb_arg, this); + } + return ERR_OK; +} + +void AsyncClient::_error(int8_t err) { + if(_pcb){ + tcp_arg(_pcb, NULL); + if(_pcb->state == LISTEN) { + tcp_sent(_pcb, NULL); + tcp_recv(_pcb, NULL); + tcp_err(_pcb, NULL); + tcp_poll(_pcb, NULL, 0); + } + _pcb = NULL; + } + if(_error_cb) { + _error_cb(_error_cb_arg, this, err); + } + if(_discard_cb) { + _discard_cb(_discard_cb_arg, this); + } +} + +//In LwIP Thread +int8_t AsyncClient::_lwip_fin(tcp_pcb* pcb, int8_t err) { + if(!_pcb || pcb != _pcb){ + log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); + return ERR_OK; + } + tcp_arg(_pcb, NULL); + if(_pcb->state == LISTEN) { + tcp_sent(_pcb, NULL); + tcp_recv(_pcb, NULL); + tcp_err(_pcb, NULL); + tcp_poll(_pcb, NULL, 0); + } + if(tcp_close(_pcb) != ERR_OK) { + tcp_abort(_pcb); + } + _free_closed_slot(); + _pcb = NULL; + return ERR_OK; +} + +//In Async Thread +int8_t AsyncClient::_fin(tcp_pcb* pcb, int8_t err) { + _tcp_clear_events(this); + if(_discard_cb) { + _discard_cb(_discard_cb_arg, this); + } + return ERR_OK; +} + +int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { + _rx_last_packet = millis(); + //log_i("%u", len); + _pcb_busy = false; + if(_sent_cb) { + _sent_cb(_sent_cb_arg, this, len, (millis() - _pcb_sent_at)); + } + return ERR_OK; +} + +int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { + while(pb != NULL) { + _rx_last_packet = millis(); + //we should not ack before we assimilate the data + _ack_pcb = true; + pbuf *b = pb; + pb = b->next; + b->next = NULL; + if(_pb_cb){ + _pb_cb(_pb_cb_arg, this, b); + } else { + if(_recv_cb) { + _recv_cb(_recv_cb_arg, this, b->payload, b->len); + } + if(!_ack_pcb) { + _rx_ack_len += b->len; + } else if(_pcb) { + _tcp_recved(_pcb, _closed_slot, b->len); + } + pbuf_free(b); + } + } + return ERR_OK; +} + +int8_t AsyncClient::_poll(tcp_pcb* pcb){ + if(!_pcb){ + log_w("pcb is NULL"); + return ERR_OK; + } + if(pcb != _pcb){ + log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); + return ERR_OK; + } + + uint32_t now = millis(); + + // ACK Timeout + if(_pcb_busy && _ack_timeout && (now - _pcb_sent_at) >= _ack_timeout){ + _pcb_busy = false; + log_w("ack timeout %d", pcb->state); + if(_timeout_cb) + _timeout_cb(_timeout_cb_arg, this, (now - _pcb_sent_at)); + return ERR_OK; + } + // RX Timeout + if(_rx_since_timeout && (now - _rx_last_packet) >= (_rx_since_timeout * 1000)){ + log_w("rx timeout %d", pcb->state); + _close(); + return ERR_OK; + } + // Everything is fine + if(_poll_cb) { + _poll_cb(_poll_cb_arg, this); + } + return ERR_OK; +} + +void AsyncClient::_dns_found(struct ip_addr *ipaddr){ + if(ipaddr && ipaddr->u_addr.ip4.addr){ + connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port); + } else { + if(_error_cb) { + _error_cb(_error_cb_arg, this, -55); + } + if(_discard_cb) { + _discard_cb(_discard_cb_arg, this); + } + } +} + +/* + * Public Helper Methods + * */ + +void AsyncClient::stop() { + close(false); +} + +bool AsyncClient::free(){ + if(!_pcb) { + return true; + } + if(_pcb->state == 0 || _pcb->state > 4) { + return true; + } + return false; +} + +size_t AsyncClient::write(const char* data) { + if(data == NULL) { + return 0; + } + return write(data, strlen(data)); +} + +size_t AsyncClient::write(const char* data, size_t size, uint8_t apiflags) { + size_t will_send = add(data, size, apiflags); + if(!will_send || !send()) { + return 0; + } + return will_send; +} + +void AsyncClient::setRxTimeout(uint32_t timeout){ + _rx_since_timeout = timeout; +} + +uint32_t AsyncClient::getRxTimeout(){ + return _rx_since_timeout; +} + +uint32_t AsyncClient::getAckTimeout(){ + return _ack_timeout; +} + +void AsyncClient::setAckTimeout(uint32_t timeout){ + _ack_timeout = timeout; +} + +void AsyncClient::setNoDelay(bool nodelay){ + if(!_pcb) { + return; + } + if(nodelay) { + tcp_nagle_disable(_pcb); + } else { + tcp_nagle_enable(_pcb); + } +} + +bool AsyncClient::getNoDelay(){ + if(!_pcb) { + return false; + } + return tcp_nagle_disabled(_pcb); +} + +uint16_t AsyncClient::getMss(){ + if(!_pcb) { + return 0; + } + return tcp_mss(_pcb); +} + +uint32_t AsyncClient::getRemoteAddress() { + if(!_pcb) { + return 0; + } + return _pcb->remote_ip.u_addr.ip4.addr; +} + +uint16_t AsyncClient::getRemotePort() { + if(!_pcb) { + return 0; + } + return _pcb->remote_port; +} + +uint32_t AsyncClient::getLocalAddress() { + if(!_pcb) { + return 0; + } + return _pcb->local_ip.u_addr.ip4.addr; +} + +uint16_t AsyncClient::getLocalPort() { + if(!_pcb) { + return 0; + } + return _pcb->local_port; +} + +IPAddress AsyncClient::remoteIP() { + return IPAddress(getRemoteAddress()); +} + +uint16_t AsyncClient::remotePort() { + return getRemotePort(); +} + +IPAddress AsyncClient::localIP() { + return IPAddress(getLocalAddress()); +} + +uint16_t AsyncClient::localPort() { + return getLocalPort(); +} + +uint8_t AsyncClient::state() { + if(!_pcb) { + return 0; + } + return _pcb->state; +} + +bool AsyncClient::connected(){ + if (!_pcb) { + return false; + } + return _pcb->state == 4; +} + +bool AsyncClient::connecting(){ + if (!_pcb) { + return false; + } + return _pcb->state > 0 && _pcb->state < 4; +} + +bool AsyncClient::disconnecting(){ + if (!_pcb) { + return false; + } + return _pcb->state > 4 && _pcb->state < 10; +} + +bool AsyncClient::disconnected(){ + if (!_pcb) { + return true; + } + return _pcb->state == 0 || _pcb->state == 10; +} + +bool AsyncClient::freeable(){ + if (!_pcb) { + return true; + } + return _pcb->state == 0 || _pcb->state > 4; +} + +bool AsyncClient::canSend(){ + return space() > 0; +} + +const char * AsyncClient::errorToString(int8_t error){ + switch(error){ + case ERR_OK: return "OK"; + case ERR_MEM: return "Out of memory error"; + case ERR_BUF: return "Buffer error"; + case ERR_TIMEOUT: return "Timeout"; + case ERR_RTE: return "Routing problem"; + case ERR_INPROGRESS: return "Operation in progress"; + case ERR_VAL: return "Illegal value"; + case ERR_WOULDBLOCK: return "Operation would block"; + case ERR_USE: return "Address in use"; + case ERR_ALREADY: return "Already connected"; + case ERR_CONN: return "Not connected"; + case ERR_IF: return "Low-level netif error"; + case ERR_ABRT: return "Connection aborted"; + case ERR_RST: return "Connection reset"; + case ERR_CLSD: return "Connection closed"; + case ERR_ARG: return "Illegal argument"; + case -55: return "DNS failed"; + default: return "UNKNOWN"; + } +} + +const char * AsyncClient::stateToString(){ + switch(state()){ + case 0: return "Closed"; + case 1: return "Listen"; + case 2: return "SYN Sent"; + case 3: return "SYN Received"; + case 4: return "Established"; + case 5: return "FIN Wait 1"; + case 6: return "FIN Wait 2"; + case 7: return "Close Wait"; + case 8: return "Closing"; + case 9: return "Last ACK"; + case 10: return "Time Wait"; + default: return "UNKNOWN"; + } +} + +/* + * Static Callbacks (LwIP C2C++ interconnect) + * */ + +void AsyncClient::_s_dns_found(const char * name, struct ip_addr * ipaddr, void * arg){ + reinterpret_cast(arg)->_dns_found(ipaddr); +} + +int8_t AsyncClient::_s_poll(void * arg, struct tcp_pcb * pcb) { + return reinterpret_cast(arg)->_poll(pcb); +} + +int8_t AsyncClient::_s_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, int8_t err) { + return reinterpret_cast(arg)->_recv(pcb, pb, err); +} + +int8_t AsyncClient::_s_fin(void * arg, struct tcp_pcb * pcb, int8_t err) { + return reinterpret_cast(arg)->_fin(pcb, err); +} + +int8_t AsyncClient::_s_lwip_fin(void * arg, struct tcp_pcb * pcb, int8_t err) { + return reinterpret_cast(arg)->_lwip_fin(pcb, err); +} + +int8_t AsyncClient::_s_sent(void * arg, struct tcp_pcb * pcb, uint16_t len) { + return reinterpret_cast(arg)->_sent(pcb, len); +} + +void AsyncClient::_s_error(void * arg, int8_t err) { + reinterpret_cast(arg)->_error(err); +} + +int8_t AsyncClient::_s_connected(void * arg, void * pcb, int8_t err){ + return reinterpret_cast(arg)->_connected(pcb, err); +} + +/* + Async TCP Server + */ + +AsyncServer::AsyncServer(IPAddress addr, uint16_t port) +: _port(port) +, _addr(addr) +, _noDelay(false) +, _pcb(0) +, _connect_cb(0) +, _connect_cb_arg(0) +{} + +AsyncServer::AsyncServer(uint16_t port) +: _port(port) +, _addr((uint32_t) IPADDR_ANY) +, _noDelay(false) +, _pcb(0) +, _connect_cb(0) +, _connect_cb_arg(0) +{} + +AsyncServer::~AsyncServer(){ + end(); +} + +void AsyncServer::onClient(AcConnectHandler cb, void* arg){ + _connect_cb = cb; + _connect_cb_arg = arg; +} + +void AsyncServer::begin(){ + if(_pcb) { + return; + } + + if(!_start_async_task()){ + log_e("failed to start task"); + return; + } + int8_t err; + _pcb = tcp_new_ip_type(IPADDR_TYPE_V4); + if (!_pcb){ + log_e("_pcb == NULL"); + return; + } + + ip_addr_t local_addr; + local_addr.type = IPADDR_TYPE_V4; + local_addr.u_addr.ip4.addr = (uint32_t) _addr; + err = _tcp_bind(_pcb, &local_addr, _port); + + if (err != ERR_OK) { + _tcp_close(_pcb, -1); + log_e("bind error: %d", err); + return; + } + + static uint8_t backlog = 5; + _pcb = _tcp_listen_with_backlog(_pcb, backlog); + if (!_pcb) { + log_e("listen_pcb == NULL"); + return; + } + tcp_arg(_pcb, (void*) this); + tcp_accept(_pcb, &_s_accept); +} + +void AsyncServer::end(){ + if(_pcb){ + tcp_arg(_pcb, NULL); + tcp_accept(_pcb, NULL); + if(tcp_close(_pcb) != ERR_OK){ + _tcp_abort(_pcb, -1); + } + _pcb = NULL; + } +} + +//runs on LwIP thread +int8_t AsyncServer::_accept(tcp_pcb* pcb, int8_t err){ + //ets_printf("+A: 0x%08x\n", pcb); + if(_connect_cb){ + AsyncClient *c = new AsyncClient(pcb); + if(c){ + c->setNoDelay(_noDelay); + return _tcp_accept(this, c); + } + } + if(tcp_close(pcb) != ERR_OK){ + tcp_abort(pcb); + } + log_e("FAIL"); + return ERR_OK; +} + +int8_t AsyncServer::_accepted(AsyncClient* client){ + if(_connect_cb){ + _connect_cb(_connect_cb_arg, client); + } + return ERR_OK; +} + +void AsyncServer::setNoDelay(bool nodelay){ + _noDelay = nodelay; +} + +bool AsyncServer::getNoDelay(){ + return _noDelay; +} + +uint8_t AsyncServer::status(){ + if (!_pcb) { + return 0; + } + return _pcb->state; +} + +int8_t AsyncServer::_s_accept(void * arg, tcp_pcb * pcb, int8_t err){ + return reinterpret_cast(arg)->_accept(pcb, err); +} + +int8_t AsyncServer::_s_accepted(void *arg, AsyncClient* client){ + return reinterpret_cast(arg)->_accepted(client); +} diff --git a/lib/libesp32/AsyncTCP/src/AsyncTCP.h b/lib/libesp32/AsyncTCP/src/AsyncTCP.h new file mode 100644 index 000000000..ac87dedac --- /dev/null +++ b/lib/libesp32/AsyncTCP/src/AsyncTCP.h @@ -0,0 +1,217 @@ +/* + Asynchronous TCP library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef ASYNCTCP_H_ +#define ASYNCTCP_H_ + +#include "IPAddress.h" +#include "sdkconfig.h" +#include +extern "C" { + #include "freertos/semphr.h" + #include "lwip/pbuf.h" +} + +//If core is not defined, then we are running in Arduino or PIO +#ifndef CONFIG_ASYNC_TCP_RUNNING_CORE +#define CONFIG_ASYNC_TCP_RUNNING_CORE -1 //any available core +#define CONFIG_ASYNC_TCP_USE_WDT 1 //if enabled, adds between 33us and 200us per event +#endif + +class AsyncClient; + +#define ASYNC_MAX_ACK_TIME 5000 +#define ASYNC_WRITE_FLAG_COPY 0x01 //will allocate new buffer to hold the data while sending (else will hold reference to the data given) +#define ASYNC_WRITE_FLAG_MORE 0x02 //will not send PSH flag, meaning that there should be more data to be sent before the application should react. + +typedef std::function AcConnectHandler; +typedef std::function AcAckHandler; +typedef std::function AcErrorHandler; +typedef std::function AcDataHandler; +typedef std::function AcPacketHandler; +typedef std::function AcTimeoutHandler; + +struct tcp_pcb; +struct ip_addr; + +class AsyncClient { + public: + AsyncClient(tcp_pcb* pcb = 0); + ~AsyncClient(); + + AsyncClient & operator=(const AsyncClient &other); + AsyncClient & operator+=(const AsyncClient &other); + + bool operator==(const AsyncClient &other); + + bool operator!=(const AsyncClient &other) { + return !(*this == other); + } + bool connect(IPAddress ip, uint16_t port); + bool connect(const char* host, uint16_t port); + void close(bool now = false); + void stop(); + int8_t abort(); + bool free(); + + bool canSend();//ack is not pending + size_t space();//space available in the TCP window + size_t add(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY);//add for sending + bool send();//send all data added with the method above + + //write equals add()+send() + size_t write(const char* data); + size_t write(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY); //only when canSend() == true + + uint8_t state(); + bool connecting(); + bool connected(); + bool disconnecting(); + bool disconnected(); + bool freeable();//disconnected or disconnecting + + uint16_t getMss(); + + uint32_t getRxTimeout(); + void setRxTimeout(uint32_t timeout);//no RX data timeout for the connection in seconds + + uint32_t getAckTimeout(); + void setAckTimeout(uint32_t timeout);//no ACK timeout for the last sent packet in milliseconds + + void setNoDelay(bool nodelay); + bool getNoDelay(); + + uint32_t getRemoteAddress(); + uint16_t getRemotePort(); + uint32_t getLocalAddress(); + uint16_t getLocalPort(); + + //compatibility + IPAddress remoteIP(); + uint16_t remotePort(); + IPAddress localIP(); + uint16_t localPort(); + + void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect + void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected + void onAck(AcAckHandler cb, void* arg = 0); //ack received + void onError(AcErrorHandler cb, void* arg = 0); //unsuccessful connect or error + void onData(AcDataHandler cb, void* arg = 0); //data received (called if onPacket is not used) + void onPacket(AcPacketHandler cb, void* arg = 0); //data received + void onTimeout(AcTimeoutHandler cb, void* arg = 0); //ack timeout + void onPoll(AcConnectHandler cb, void* arg = 0); //every 125ms when connected + + void ackPacket(struct pbuf * pb);//ack pbuf from onPacket + size_t ack(size_t len); //ack data that you have not acked using the method below + void ackLater(){ _ack_pcb = false; } //will not ack the current packet. Call from onData + + const char * errorToString(int8_t error); + const char * stateToString(); + + //Do not use any of the functions below! + static int8_t _s_poll(void *arg, struct tcp_pcb *tpcb); + static int8_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, int8_t err); + static int8_t _s_fin(void *arg, struct tcp_pcb *tpcb, int8_t err); + static int8_t _s_lwip_fin(void *arg, struct tcp_pcb *tpcb, int8_t err); + static void _s_error(void *arg, int8_t err); + static int8_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len); + static int8_t _s_connected(void* arg, void* tpcb, int8_t err); + static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg); + + int8_t _recv(tcp_pcb* pcb, pbuf* pb, int8_t err); + tcp_pcb * pcb(){ return _pcb; } + + protected: + tcp_pcb* _pcb; + int8_t _closed_slot; + + AcConnectHandler _connect_cb; + void* _connect_cb_arg; + AcConnectHandler _discard_cb; + void* _discard_cb_arg; + AcAckHandler _sent_cb; + void* _sent_cb_arg; + AcErrorHandler _error_cb; + void* _error_cb_arg; + AcDataHandler _recv_cb; + void* _recv_cb_arg; + AcPacketHandler _pb_cb; + void* _pb_cb_arg; + AcTimeoutHandler _timeout_cb; + void* _timeout_cb_arg; + AcConnectHandler _poll_cb; + void* _poll_cb_arg; + + bool _pcb_busy; + uint32_t _pcb_sent_at; + bool _ack_pcb; + uint32_t _rx_ack_len; + uint32_t _rx_last_packet; + uint32_t _rx_since_timeout; + uint32_t _ack_timeout; + uint16_t _connect_port; + + int8_t _close(); + void _free_closed_slot(); + void _allocate_closed_slot(); + int8_t _connected(void* pcb, int8_t err); + void _error(int8_t err); + int8_t _poll(tcp_pcb* pcb); + int8_t _sent(tcp_pcb* pcb, uint16_t len); + int8_t _fin(tcp_pcb* pcb, int8_t err); + int8_t _lwip_fin(tcp_pcb* pcb, int8_t err); + void _dns_found(struct ip_addr *ipaddr); + + public: + AsyncClient* prev; + AsyncClient* next; +}; + +class AsyncServer { + public: + AsyncServer(IPAddress addr, uint16_t port); + AsyncServer(uint16_t port); + ~AsyncServer(); + void onClient(AcConnectHandler cb, void* arg); + void begin(); + void end(); + void setNoDelay(bool nodelay); + bool getNoDelay(); + uint8_t status(); + + //Do not use any of the functions below! + static int8_t _s_accept(void *arg, tcp_pcb* newpcb, int8_t err); + static int8_t _s_accepted(void *arg, AsyncClient* client); + + protected: + uint16_t _port; + IPAddress _addr; + bool _noDelay; + tcp_pcb* _pcb; + AcConnectHandler _connect_cb; + void* _connect_cb_arg; + + int8_t _accept(tcp_pcb* newpcb, int8_t err); + int8_t _accepted(AsyncClient* client); +}; + + +#endif /* ASYNCTCP_H_ */ diff --git a/lib/libesp32/ESPAsyncWebServer/.gitignore b/lib/libesp32/ESPAsyncWebServer/.gitignore new file mode 100644 index 000000000..a0f0e5386 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/.gitignore @@ -0,0 +1,2 @@ +.vscode +.DS_Store diff --git a/lib/libesp32/ESPAsyncWebServer/.travis.yml b/lib/libesp32/ESPAsyncWebServer/.travis.yml new file mode 100644 index 000000000..e1b703527 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/.travis.yml @@ -0,0 +1,46 @@ +sudo: false + +language: python + +os: + - linux + +git: + depth: false + +stages: + - build + +jobs: + include: + + - name: "Build Arduino ESP32" + if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) + stage: build + script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh esp32 + + - name: "Build Arduino ESP8266" + if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) + stage: build + script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh esp8266 + + - name: "Build Platformio ESP32" + if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) + stage: build + script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh esp32 1 1 + + - name: "Build Platformio ESP8266" + if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) + stage: build + script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh esp8266 1 1 + +notifications: + email: + on_success: change + on_failure: change + webhooks: + urls: + - https://webhooks.gitter.im/e/60e65d0c78ea0a920347 + on_success: change # options: [always|never|change] default: always + on_failure: always # options: [always|never|change] default: always + on_start: never # options: [always|never|change] default: always diff --git a/lib/libesp32/ESPAsyncWebServer/CMakeLists.txt b/lib/libesp32/ESPAsyncWebServer/CMakeLists.txt new file mode 100644 index 000000000..64292eca4 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/CMakeLists.txt @@ -0,0 +1,17 @@ +set(COMPONENT_SRCDIRS + "src" +) + +set(COMPONENT_ADD_INCLUDEDIRS + "src" +) + +set(COMPONENT_REQUIRES + "arduino-esp32" + "AsyncTCP" +) + +register_component() + +target_compile_definitions(${COMPONENT_TARGET} PUBLIC -DESP32) +target_compile_options(${COMPONENT_TARGET} PRIVATE -fno-rtti) diff --git a/lib/libesp32/ESPAsyncWebServer/README.md b/lib/libesp32/ESPAsyncWebServer/README.md new file mode 100644 index 000000000..d6dd3206a --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/README.md @@ -0,0 +1,1521 @@ +# ESPAsyncWebServer +[![Build Status](https://travis-ci.org/me-no-dev/ESPAsyncWebServer.svg?branch=master)](https://travis-ci.org/me-no-dev/ESPAsyncWebServer) ![](https://github.com/me-no-dev/ESPAsyncWebServer/workflows/ESP%20Async%20Web%20Server%20CI/badge.svg) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/395dd42cfc674e6ca2e326af3af80ffc)](https://www.codacy.com/manual/me-no-dev/ESPAsyncWebServer?utm_source=github.com&utm_medium=referral&utm_content=me-no-dev/ESPAsyncWebServer&utm_campaign=Badge_Grade) + +For help and support [![Join the chat at https://gitter.im/me-no-dev/ESPAsyncWebServer](https://badges.gitter.im/me-no-dev/ESPAsyncWebServer.svg)](https://gitter.im/me-no-dev/ESPAsyncWebServer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +Async HTTP and WebSocket Server for ESP8266 Arduino + +For ESP8266 it requires [ESPAsyncTCP](https://github.com/me-no-dev/ESPAsyncTCP) +To use this library you might need to have the latest git versions of [ESP8266](https://github.com/esp8266/Arduino) Arduino Core + +For ESP32 it requires [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) to work +To use this library you might need to have the latest git versions of [ESP32](https://github.com/espressif/arduino-esp32) Arduino Core + +## Table of contents +- [ESPAsyncWebServer](#espasyncwebserver) + - [Table of contents](#table-of-contents) + - [Installation](#installation) + - [Using PlatformIO](#using-platformio) + - [Why should you care](#why-should-you-care) + - [Important things to remember](#important-things-to-remember) + - [Principles of operation](#principles-of-operation) + - [The Async Web server](#the-async-web-server) + - [Request Life Cycle](#request-life-cycle) + - [Rewrites and how do they work](#rewrites-and-how-do-they-work) + - [Handlers and how do they work](#handlers-and-how-do-they-work) + - [Responses and how do they work](#responses-and-how-do-they-work) + - [Template processing](#template-processing) + - [Libraries and projects that use AsyncWebServer](#libraries-and-projects-that-use-asyncwebserver) + - [Request Variables](#request-variables) + - [Common Variables](#common-variables) + - [Headers](#headers) + - [GET, POST and FILE parameters](#get-post-and-file-parameters) + - [FILE Upload handling](#file-upload-handling) + - [Body data handling](#body-data-handling) + - [JSON body handling with ArduinoJson](#json-body-handling-with-arduinojson) + - [Responses](#responses) + - [Redirect to another URL](#redirect-to-another-url) + - [Basic response with HTTP Code](#basic-response-with-http-code) + - [Basic response with HTTP Code and extra headers](#basic-response-with-http-code-and-extra-headers) + - [Basic response with string content](#basic-response-with-string-content) + - [Basic response with string content and extra headers](#basic-response-with-string-content-and-extra-headers) + - [Send large webpage from PROGMEM](#send-large-webpage-from-progmem) + - [Send large webpage from PROGMEM and extra headers](#send-large-webpage-from-progmem-and-extra-headers) + - [Send large webpage from PROGMEM containing templates](#send-large-webpage-from-progmem-containing-templates) + - [Send large webpage from PROGMEM containing templates and extra headers](#send-large-webpage-from-progmem-containing-templates-and-extra-headers) + - [Send binary content from PROGMEM](#send-binary-content-from-progmem) + - [Respond with content coming from a Stream](#respond-with-content-coming-from-a-stream) + - [Respond with content coming from a Stream and extra headers](#respond-with-content-coming-from-a-stream-and-extra-headers) + - [Respond with content coming from a Stream containing templates](#respond-with-content-coming-from-a-stream-containing-templates) + - [Respond with content coming from a Stream containing templates and extra headers](#respond-with-content-coming-from-a-stream-containing-templates-and-extra-headers) + - [Respond with content coming from a File](#respond-with-content-coming-from-a-file) + - [Respond with content coming from a File and extra headers](#respond-with-content-coming-from-a-file-and-extra-headers) + - [Respond with content coming from a File containing templates](#respond-with-content-coming-from-a-file-containing-templates) + - [Respond with content using a callback](#respond-with-content-using-a-callback) + - [Respond with content using a callback and extra headers](#respond-with-content-using-a-callback-and-extra-headers) + - [Respond with content using a callback containing templates](#respond-with-content-using-a-callback-containing-templates) + - [Respond with content using a callback containing templates and extra headers](#respond-with-content-using-a-callback-containing-templates-and-extra-headers) + - [Chunked Response](#chunked-response) + - [Chunked Response containing templates](#chunked-response-containing-templates) + - [Print to response](#print-to-response) + - [ArduinoJson Basic Response](#arduinojson-basic-response) + - [ArduinoJson Advanced Response](#arduinojson-advanced-response) + - [Serving static files](#serving-static-files) + - [Serving specific file by name](#serving-specific-file-by-name) + - [Serving files in directory](#serving-files-in-directory) + - [Serving static files with authentication](#serving-static-files-with-authentication) + - [Specifying Cache-Control header](#specifying-cache-control-header) + - [Specifying Date-Modified header](#specifying-date-modified-header) + - [Specifying Template Processor callback](#specifying-template-processor-callback) + - [Param Rewrite With Matching](#param-rewrite-with-matching) + - [Using filters](#using-filters) + - [Serve different site files in AP mode](#serve-different-site-files-in-ap-mode) + - [Rewrite to different index on AP](#rewrite-to-different-index-on-ap) + - [Serving different hosts](#serving-different-hosts) + - [Determine interface inside callbacks](#determine-interface-inside-callbacks) + - [Bad Responses](#bad-responses) + - [Respond with content using a callback without content length to HTTP/1.0 clients](#respond-with-content-using-a-callback-without-content-length-to-http10-clients) + - [Async WebSocket Plugin](#async-websocket-plugin) + - [Async WebSocket Event](#async-websocket-event) + - [Methods for sending data to a socket client](#methods-for-sending-data-to-a-socket-client) + - [Direct access to web socket message buffer](#direct-access-to-web-socket-message-buffer) + - [Limiting the number of web socket clients](#limiting-the-number-of-web-socket-clients) + - [Async Event Source Plugin](#async-event-source-plugin) + - [Setup Event Source on the server](#setup-event-source-on-the-server) + - [Setup Event Source in the browser](#setup-event-source-in-the-browser) + - [Scanning for available WiFi Networks](#scanning-for-available-wifi-networks) + - [Remove handlers and rewrites](#remove-handlers-and-rewrites) + - [Setting up the server](#setting-up-the-server) + - [Setup global and class functions as request handlers](#setup-global-and-class-functions-as-request-handlers) + - [Methods for controlling websocket connections](#methods-for-controlling-websocket-connections) + - [Adding Default Headers](#adding-default-headers) + - [Path variable](#path-variable) + +## Installation + +### Using PlatformIO + +[PlatformIO](http://platformio.org) is an open source ecosystem for IoT development with cross platform build system, library manager and full support for Espressif ESP8266/ESP32 development. It works on the popular host OS: Mac OS X, Windows, Linux 32/64, Linux ARM (like Raspberry Pi, BeagleBone, CubieBoard). + +1. Install [PlatformIO IDE](http://platformio.org/platformio-ide) +2. Create new project using "PlatformIO Home > New Project" +3. Update dev/platform to staging version: + - [Instruction for Espressif 8266](http://docs.platformio.org/en/latest/platforms/espressif8266.html#using-arduino-framework-with-staging-version) + - [Instruction for Espressif 32](http://docs.platformio.org/en/latest/platforms/espressif32.html#using-arduino-framework-with-staging-version) + 4. Add "ESP Async WebServer" to project using [Project Configuration File `platformio.ini`](http://docs.platformio.org/page/projectconf.html) and [lib_deps](http://docs.platformio.org/page/projectconf/section_env_library.html#lib-deps) option: + +```ini +[env:myboard] +platform = espressif... +board = ... +framework = arduino + +# using the latest stable version +lib_deps = ESP Async WebServer + +# or using GIT Url (the latest development version) +lib_deps = https://github.com/me-no-dev/ESPAsyncWebServer.git +``` + 5. Happy coding with PlatformIO! + +## Why should you care +- Using asynchronous network means that you can handle more than one connection at the same time +- You are called once the request is ready and parsed +- When you send the response, you are immediately ready to handle other connections + while the server is taking care of sending the response in the background +- Speed is OMG +- Easy to use API, HTTP Basic and Digest MD5 Authentication (default), ChunkedResponse +- Easily extendible to handle any type of content +- Supports Continue 100 +- Async WebSocket plugin offering different locations without extra servers or ports +- Async EventSource (Server-Sent Events) plugin to send events to the browser +- URL Rewrite plugin for conditional and permanent url rewrites +- ServeStatic plugin that supports cache, Last-Modified, default index and more +- Simple template processing engine to handle templates + +## Important things to remember +- This is fully asynchronous server and as such does not run on the loop thread. +- You can not use yield or delay or any function that uses them inside the callbacks +- The server is smart enough to know when to close the connection and free resources +- You can not send more than one response to a single request + +## Principles of operation + +### The Async Web server +- Listens for connections +- Wraps the new clients into ```Request``` +- Keeps track of clients and cleans memory +- Manages ```Rewrites``` and apply them on the request url +- Manages ```Handlers``` and attaches them to Requests + +### Request Life Cycle +- TCP connection is received by the server +- The connection is wrapped inside ```Request``` object +- When the request head is received (type, url, get params, http version and host), + the server goes through all ```Rewrites``` (in the order they were added) to rewrite the url and inject query parameters, + next, it goes through all attached ```Handlers```(in the order they were added) trying to find one + that ```canHandle``` the given request. If none are found, the default(catch-all) handler is attached. +- The rest of the request is received, calling the ```handleUpload``` or ```handleBody``` methods of the ```Handler``` if they are needed (POST+File/Body) +- When the whole request is parsed, the result is given to the ```handleRequest``` method of the ```Handler``` and is ready to be responded to +- In the ```handleRequest``` method, to the ```Request``` is attached a ```Response``` object (see below) that will serve the response data back to the client +- When the ```Response``` is sent, the client is closed and freed from the memory + +### Rewrites and how do they work +- The ```Rewrites``` are used to rewrite the request url and/or inject get parameters for a specific request url path. +- All ```Rewrites``` are evaluated on the request in the order they have been added to the server. +- The ```Rewrite``` will change the request url only if the request url (excluding get parameters) is fully match + the rewrite url, and when the optional ```Filter``` callback return true. +- Setting a ```Filter``` to the ```Rewrite``` enables to control when to apply the rewrite, decision can be based on + request url, http version, request host/port/target host, get parameters or the request client's localIP or remoteIP. +- Two filter callbacks are provided: ```ON_AP_FILTER``` to execute the rewrite when request is made to the AP interface, + ```ON_STA_FILTER``` to execute the rewrite when request is made to the STA interface. +- The ```Rewrite``` can specify a target url with optional get parameters, e.g. ```/to-url?with=params``` + +### Handlers and how do they work +- The ```Handlers``` are used for executing specific actions to particular requests +- One ```Handler``` instance can be attached to any request and lives together with the server +- Setting a ```Filter``` to the ```Handler``` enables to control when to apply the handler, decision can be based on + request url, http version, request host/port/target host, get parameters or the request client's localIP or remoteIP. +- Two filter callbacks are provided: ```ON_AP_FILTER``` to execute the rewrite when request is made to the AP interface, + ```ON_STA_FILTER``` to execute the rewrite when request is made to the STA interface. +- The ```canHandle``` method is used for handler specific control on whether the requests can be handled + and for declaring any interesting headers that the ```Request``` should parse. Decision can be based on request + method, request url, http version, request host/port/target host and get parameters +- Once a ```Handler``` is attached to given ```Request``` (```canHandle``` returned true) + that ```Handler``` takes care to receive any file/data upload and attach a ```Response``` + once the ```Request``` has been fully parsed +- ```Handlers``` are evaluated in the order they are attached to the server. The ```canHandle``` is called only + if the ```Filter``` that was set to the ```Handler``` return true. +- The first ```Handler``` that can handle the request is selected, not further ```Filter``` and ```canHandle``` are called. + +### Responses and how do they work +- The ```Response``` objects are used to send the response data back to the client +- The ```Response``` object lives with the ```Request``` and is freed on end or disconnect +- Different techniques are used depending on the response type to send the data in packets + returning back almost immediately and sending the next packet when this one is received. + Any time in between is spent to run the user loop and handle other network packets +- Responding asynchronously is probably the most difficult thing for most to understand +- Many different options exist for the user to make responding a background task + +### Template processing +- ESPAsyncWebserver contains simple template processing engine. +- Template processing can be added to most response types. +- Currently it supports only replacing template placeholders with actual values. No conditional processing, cycles, etc. +- Placeholders are delimited with ```%``` symbols. Like this: ```%TEMPLATE_PLACEHOLDER%```. +- It works by extracting placeholder name from response text and passing it to user provided function which should return actual value to be used instead of placeholder. +- Since it's user provided function, it is possible for library users to implement conditional processing and cycles themselves. +- Since it's impossible to know the actual response size after template processing step in advance (and, therefore, to include it in response headers), the response becomes [chunked](#chunked-response). + +## Libraries and projects that use AsyncWebServer +- [WebSocketToSerial](https://github.com/hallard/WebSocketToSerial) - Debug serial devices through the web browser +- [Sattrack](https://github.com/Hopperpop/Sattrack) - Track the ISS with ESP8266 +- [ESP Radio](https://github.com/Edzelf/Esp-radio) - Icecast radio based on ESP8266 and VS1053 +- [VZero](https://github.com/andig/vzero) - the Wireless zero-config controller for volkszaehler.org +- [ESPurna](https://bitbucket.org/xoseperez/espurna) - ESPurna ("spark" in Catalan) is a custom C firmware for ESP8266 based smart switches. It was originally developed with the ITead Sonoff in mind. +- [fauxmoESP](https://bitbucket.org/xoseperez/fauxmoesp) - Belkin WeMo emulator library for ESP8266. +- [ESP-RFID](https://github.com/omersiar/esp-rfid) - MFRC522 RFID Access Control Management project for ESP8266. + +## Request Variables + +### Common Variables +```cpp +request->version(); // uint8_t: 0 = HTTP/1.0, 1 = HTTP/1.1 +request->method(); // enum: HTTP_GET, HTTP_POST, HTTP_DELETE, HTTP_PUT, HTTP_PATCH, HTTP_HEAD, HTTP_OPTIONS +request->url(); // String: URL of the request (not including host, port or GET parameters) +request->host(); // String: The requested host (can be used for virtual hosting) +request->contentType(); // String: ContentType of the request (not avaiable in Handler::canHandle) +request->contentLength(); // size_t: ContentLength of the request (not avaiable in Handler::canHandle) +request->multipart(); // bool: True if the request has content type "multipart" +``` + +### Headers +```cpp +//List all collected headers +int headers = request->headers(); +int i; +for(i=0;igetHeader(i); + Serial.printf("HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str()); +} + +//get specific header by name +if(request->hasHeader("MyHeader")){ + AsyncWebHeader* h = request->getHeader("MyHeader"); + Serial.printf("MyHeader: %s\n", h->value().c_str()); +} + +//List all collected headers (Compatibility) +int headers = request->headers(); +int i; +for(i=0;iheaderName(i).c_str(), request->header(i).c_str()); +} + +//get specific header by name (Compatibility) +if(request->hasHeader("MyHeader")){ + Serial.printf("MyHeader: %s\n", request->header("MyHeader").c_str()); +} +``` + +### GET, POST and FILE parameters +```cpp +//List all parameters +int params = request->params(); +for(int i=0;igetParam(i); + if(p->isFile()){ //p->isPost() is also true + Serial.printf("FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size()); + } else if(p->isPost()){ + Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); + } else { + Serial.printf("GET[%s]: %s\n", p->name().c_str(), p->value().c_str()); + } +} + +//Check if GET parameter exists +if(request->hasParam("download")) + AsyncWebParameter* p = request->getParam("download"); + +//Check if POST (but not File) parameter exists +if(request->hasParam("download", true)) + AsyncWebParameter* p = request->getParam("download", true); + +//Check if FILE was uploaded +if(request->hasParam("download", true, true)) + AsyncWebParameter* p = request->getParam("download", true, true); + +//List all parameters (Compatibility) +int args = request->args(); +for(int i=0;iargName(i).c_str(), request->arg(i).c_str()); +} + +//Check if parameter exists (Compatibility) +if(request->hasArg("download")) + String arg = request->arg("download"); +``` + +### FILE Upload handling +```cpp +void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ + if(!index){ + Serial.printf("UploadStart: %s\n", filename.c_str()); + } + for(size_t i=0; i(); + // ... +}); +server.addHandler(handler); +``` + +## Responses +### Redirect to another URL +```cpp +//to local url +request->redirect("/login"); + +//to external url +request->redirect("http://esp8266.com"); +``` + +### Basic response with HTTP Code +```cpp +request->send(404); //Sends 404 File Not Found +``` + +### Basic response with HTTP Code and extra headers +```cpp +AsyncWebServerResponse *response = request->beginResponse(404); //Sends 404 File Not Found +response->addHeader("Server","ESP Async Web Server"); +request->send(response); +``` + +### Basic response with string content +```cpp +request->send(200, "text/plain", "Hello World!"); +``` + +### Basic response with string content and extra headers +```cpp +AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", "Hello World!"); +response->addHeader("Server","ESP Async Web Server"); +request->send(response); +``` + +### Send large webpage from PROGMEM +```cpp +const char index_html[] PROGMEM = "..."; // large char array, tested with 14k +request->send_P(200, "text/html", index_html); +``` + +### Send large webpage from PROGMEM and extra headers +```cpp +const char index_html[] PROGMEM = "..."; // large char array, tested with 14k +AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", index_html); +response->addHeader("Server","ESP Async Web Server"); +request->send(response); +``` + +### Send large webpage from PROGMEM containing templates +```cpp +String processor(const String& var) +{ + if(var == "HELLO_FROM_TEMPLATE") + return F("Hello world!"); + return String(); +} + +// ... + +const char index_html[] PROGMEM = "..."; // large char array, tested with 14k +request->send_P(200, "text/html", index_html, processor); +``` + +### Send large webpage from PROGMEM containing templates and extra headers +```cpp +String processor(const String& var) +{ + if(var == "HELLO_FROM_TEMPLATE") + return F("Hello world!"); + return String(); +} + +// ... + +const char index_html[] PROGMEM = "..."; // large char array, tested with 14k +AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", index_html, processor); +response->addHeader("Server","ESP Async Web Server"); +request->send(response); +``` + +### Send binary content from PROGMEM +```cpp + +//File: favicon.ico.gz, Size: 726 +#define favicon_ico_gz_len 726 +const uint8_t favicon_ico_gz[] PROGMEM = { + 0x1F, 0x8B, 0x08, 0x08, 0x0B, 0x87, 0x90, 0x57, 0x00, 0x03, 0x66, 0x61, 0x76, 0x69, 0x63, 0x6F, + 0x6E, 0x2E, 0x69, 0x63, 0x6F, 0x00, 0xCD, 0x53, 0x5F, 0x48, 0x9A, 0x51, 0x14, 0xBF, 0x62, 0x6D, + 0x86, 0x96, 0xA9, 0x64, 0xD3, 0xFE, 0xA8, 0x99, 0x65, 0x1A, 0xB4, 0x8A, 0xA8, 0x51, 0x54, 0x23, + 0xA8, 0x11, 0x49, 0x51, 0x8A, 0x34, 0x62, 0x93, 0x85, 0x31, 0x58, 0x44, 0x12, 0x45, 0x2D, 0x58, + 0xF5, 0x52, 0x41, 0x10, 0x23, 0x82, 0xA0, 0x20, 0x98, 0x2F, 0xC1, 0x26, 0xED, 0xA1, 0x20, 0x89, + 0x04, 0xD7, 0x83, 0x58, 0x20, 0x28, 0x04, 0xAB, 0xD1, 0x9B, 0x8C, 0xE5, 0xC3, 0x60, 0x32, 0x64, + 0x0E, 0x56, 0xBF, 0x9D, 0xEF, 0xF6, 0x30, 0x82, 0xED, 0xAD, 0x87, 0xDD, 0x8F, 0xF3, 0xDD, 0x8F, + 0x73, 0xCF, 0xEF, 0x9C, 0xDF, 0x39, 0xBF, 0xFB, 0x31, 0x26, 0xA2, 0x27, 0x37, 0x97, 0xD1, 0x5B, + 0xCF, 0x9E, 0x67, 0x30, 0xA6, 0x66, 0x8C, 0x99, 0xC9, 0xC8, 0x45, 0x9E, 0x6B, 0x3F, 0x5F, 0x74, + 0xA6, 0x94, 0x5E, 0xDB, 0xFF, 0xB2, 0xE6, 0xE7, 0xE7, 0xF9, 0xDE, 0xD6, 0xD6, 0x96, 0xDB, 0xD8, + 0xD8, 0x78, 0xBF, 0xA1, 0xA1, 0xC1, 0xDA, 0xDC, 0xDC, 0x2C, 0xEB, 0xED, 0xED, 0x15, 0x9B, 0xCD, + 0xE6, 0x4A, 0x83, 0xC1, 0xE0, 0x2E, 0x29, 0x29, 0x99, 0xD6, 0x6A, 0xB5, 0x4F, 0x75, 0x3A, 0x9D, + 0x61, 0x75, 0x75, 0x95, 0xB5, 0xB7, 0xB7, 0xDF, 0xC8, 0xD1, 0xD4, 0xD4, 0xF4, 0xB0, 0xBA, 0xBA, + 0xFA, 0x83, 0xD5, 0x6A, 0xFD, 0x5A, 0x5E, 0x5E, 0x9E, 0x28, 0x2D, 0x2D, 0x0D, 0x10, 0xC6, 0x4B, + 0x98, 0x78, 0x5E, 0x5E, 0xDE, 0x95, 0x42, 0xA1, 0x40, 0x4E, 0x4E, 0xCE, 0x65, 0x76, 0x76, 0xF6, + 0x47, 0xB5, 0x5A, 0x6D, 0x4F, 0x26, 0x93, 0xA2, 0xD6, 0xD6, 0x56, 0x8E, 0x6D, 0x69, 0x69, 0xD1, + 0x11, 0x36, 0x62, 0xB1, 0x58, 0x60, 0x32, 0x99, 0xA0, 0xD7, 0xEB, 0x51, 0x58, 0x58, 0x88, 0xFC, + 0xFC, 0x7C, 0x10, 0x16, 0x02, 0x56, 0x2E, 0x97, 0x43, 0x2A, 0x95, 0x42, 0x2C, 0x16, 0x23, 0x33, + 0x33, 0x33, 0xAE, 0x52, 0xA9, 0x1E, 0x64, 0x65, 0x65, 0x71, 0x7C, 0x7D, 0x7D, 0xBD, 0x93, 0xEA, + 0xFE, 0x30, 0x1A, 0x8D, 0xE8, 0xEC, 0xEC, 0xC4, 0xE2, 0xE2, 0x22, 0x6A, 0x6A, 0x6A, 0x40, 0x39, + 0x41, 0xB5, 0x38, 0x4E, 0xC8, 0x33, 0x3C, 0x3C, 0x0C, 0x87, 0xC3, 0xC1, 0x6B, 0x54, 0x54, 0x54, + 0xBC, 0xE9, 0xEB, 0xEB, 0x93, 0x5F, 0x5C, 0x5C, 0x30, 0x8A, 0x9D, 0x2E, 0x2B, 0x2B, 0xBB, 0xA2, + 0x3E, 0x41, 0xBD, 0x21, 0x1E, 0x8F, 0x63, 0x6A, 0x6A, 0x0A, 0x81, 0x40, 0x00, 0x94, 0x1B, 0x3D, + 0x3D, 0x3D, 0x42, 0x3C, 0x96, 0x96, 0x96, 0x70, 0x7E, 0x7E, 0x8E, 0xE3, 0xE3, 0x63, 0xF8, 0xFD, + 0xFE, 0xB4, 0xD7, 0xEB, 0xF5, 0x8F, 0x8F, 0x8F, 0x5B, 0x68, 0x5E, 0x6F, 0x05, 0xCE, 0xB4, 0xE3, + 0xE8, 0xE8, 0x08, 0x27, 0x27, 0x27, 0xD8, 0xDF, 0xDF, 0xC7, 0xD9, 0xD9, 0x19, 0x6C, 0x36, 0x1B, + 0x36, 0x36, 0x36, 0x38, 0x9F, 0x85, 0x85, 0x05, 0xAC, 0xAF, 0xAF, 0x23, 0x1A, 0x8D, 0x22, 0x91, + 0x48, 0x20, 0x16, 0x8B, 0xFD, 0xDA, 0xDA, 0xDA, 0x7A, 0x41, 0x33, 0x7E, 0x57, 0x50, 0x50, 0x80, + 0x89, 0x89, 0x09, 0x84, 0xC3, 0x61, 0x6C, 0x6F, 0x6F, 0x23, 0x12, 0x89, 0xE0, 0xE0, 0xE0, 0x00, + 0x43, 0x43, 0x43, 0x58, 0x5E, 0x5E, 0xE6, 0x9C, 0x7D, 0x3E, 0x1F, 0x46, 0x47, 0x47, 0x79, 0xBE, + 0xBD, 0xBD, 0x3D, 0xE1, 0x3C, 0x1D, 0x0C, 0x06, 0x9F, 0x10, 0xB7, 0xC7, 0x84, 0x4F, 0xF6, 0xF7, + 0xF7, 0x63, 0x60, 0x60, 0x00, 0x83, 0x83, 0x83, 0x18, 0x19, 0x19, 0xC1, 0xDC, 0xDC, 0x1C, 0x8F, + 0x17, 0x7C, 0xA4, 0x27, 0xE7, 0x34, 0x39, 0x39, 0x89, 0x9D, 0x9D, 0x1D, 0x6E, 0x54, 0xE3, 0x13, + 0xE5, 0x34, 0x11, 0x37, 0x49, 0x51, 0x51, 0xD1, 0x4B, 0xA5, 0x52, 0xF9, 0x45, 0x26, 0x93, 0x5D, + 0x0A, 0xF3, 0x92, 0x48, 0x24, 0xA0, 0x6F, 0x14, 0x17, 0x17, 0xA3, 0xB6, 0xB6, 0x16, 0x5D, 0x5D, + 0x5D, 0x7C, 0x1E, 0xBB, 0xBB, 0xBB, 0x9C, 0xD7, 0xE1, 0xE1, 0x21, 0x42, 0xA1, 0xD0, 0x6B, 0xD2, + 0x45, 0x4C, 0x33, 0x12, 0x34, 0xCC, 0xA0, 0x19, 0x54, 0x92, 0x56, 0x0E, 0xD2, 0xD9, 0x43, 0xF8, + 0xCF, 0x82, 0x56, 0xC2, 0xDC, 0xEB, 0xEA, 0xEA, 0x38, 0x7E, 0x6C, 0x6C, 0x4C, 0xE0, 0xFE, 0x9D, + 0xB8, 0xBF, 0xA7, 0xFA, 0xAF, 0x56, 0x56, 0x56, 0xEE, 0x6D, 0x6E, 0x6E, 0xDE, 0xB8, 0x47, 0x55, + 0x55, 0x55, 0x6C, 0x66, 0x66, 0x46, 0x44, 0xDA, 0x3B, 0x34, 0x1A, 0x4D, 0x94, 0xB0, 0x3F, 0x09, + 0x7B, 0x45, 0xBD, 0xA5, 0x5D, 0x2E, 0x57, 0x8C, 0x7A, 0x73, 0xD9, 0xED, 0xF6, 0x3B, 0x84, 0xFF, + 0xE7, 0x7D, 0xA6, 0x3A, 0x2C, 0x95, 0x4A, 0xB1, 0x8E, 0x8E, 0x0E, 0x6D, 0x77, 0x77, 0xB7, 0xCD, + 0xE9, 0x74, 0x3E, 0x73, 0xBB, 0xDD, 0x8F, 0x3C, 0x1E, 0x8F, 0xE6, 0xF4, 0xF4, 0x94, 0xAD, 0xAD, + 0xAD, 0xDD, 0xDE, 0xCF, 0x73, 0x0B, 0x0B, 0xB8, 0xB6, 0xE0, 0x5D, 0xC6, 0x66, 0xC5, 0xE4, 0x10, + 0x4C, 0xF4, 0xF7, 0xD8, 0x59, 0xF2, 0x7F, 0xA3, 0xB8, 0xB4, 0xFC, 0x0F, 0xEE, 0x37, 0x70, 0xEC, + 0x16, 0x4A, 0x7E, 0x04, 0x00, 0x00 +}; + +AsyncWebServerResponse *response = request->beginResponse_P(200, "image/x-icon", favicon_ico_gz, favicon_ico_gz_len); +response->addHeader("Content-Encoding", "gzip"); +request->send(response); +``` + +### Respond with content coming from a Stream +```cpp +//read 12 bytes from Serial and send them as Content Type text/plain +request->send(Serial, "text/plain", 12); +``` + +### Respond with content coming from a Stream and extra headers +```cpp +//read 12 bytes from Serial and send them as Content Type text/plain +AsyncWebServerResponse *response = request->beginResponse(Serial, "text/plain", 12); +response->addHeader("Server","ESP Async Web Server"); +request->send(response); +``` + +### Respond with content coming from a Stream containing templates +```cpp +String processor(const String& var) +{ + if(var == "HELLO_FROM_TEMPLATE") + return F("Hello world!"); + return String(); +} + +// ... + +//read 12 bytes from Serial and send them as Content Type text/plain +request->send(Serial, "text/plain", 12, processor); +``` + +### Respond with content coming from a Stream containing templates and extra headers +```cpp +String processor(const String& var) +{ + if(var == "HELLO_FROM_TEMPLATE") + return F("Hello world!"); + return String(); +} + +// ... + +//read 12 bytes from Serial and send them as Content Type text/plain +AsyncWebServerResponse *response = request->beginResponse(Serial, "text/plain", 12, processor); +response->addHeader("Server","ESP Async Web Server"); +request->send(response); +``` + +### Respond with content coming from a File +```cpp +//Send index.htm with default content type +request->send(SPIFFS, "/index.htm"); + +//Send index.htm as text +request->send(SPIFFS, "/index.htm", "text/plain"); + +//Download index.htm +request->send(SPIFFS, "/index.htm", String(), true); +``` + +### Respond with content coming from a File and extra headers +```cpp +//Send index.htm with default content type +AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/index.htm"); + +//Send index.htm as text +AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/index.htm", "text/plain"); + +//Download index.htm +AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/index.htm", String(), true); + +response->addHeader("Server","ESP Async Web Server"); +request->send(response); +``` + +### Respond with content coming from a File containing templates +Internally uses [Chunked Response](#chunked-response). + +Index.htm contents: +``` +%HELLO_FROM_TEMPLATE% +``` + +Somewhere in source files: +```cpp +String processor(const String& var) +{ + if(var == "HELLO_FROM_TEMPLATE") + return F("Hello world!"); + return String(); +} + +// ... + +//Send index.htm with template processor function +request->send(SPIFFS, "/index.htm", String(), false, processor); +``` + +### Respond with content using a callback +```cpp +//send 128 bytes as plain text +request->send("text/plain", 128, [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { + //Write up to "maxLen" bytes into "buffer" and return the amount written. + //index equals the amount of bytes that have been already sent + //You will not be asked for more bytes once the content length has been reached. + //Keep in mind that you can not delay or yield waiting for more data! + //Send what you currently have and you will be asked for more again + return mySource.read(buffer, maxLen); +}); +``` + +### Respond with content using a callback and extra headers +```cpp +//send 128 bytes as plain text +AsyncWebServerResponse *response = request->beginResponse("text/plain", 128, [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { + //Write up to "maxLen" bytes into "buffer" and return the amount written. + //index equals the amount of bytes that have been already sent + //You will not be asked for more bytes once the content length has been reached. + //Keep in mind that you can not delay or yield waiting for more data! + //Send what you currently have and you will be asked for more again + return mySource.read(buffer, maxLen); +}); +response->addHeader("Server","ESP Async Web Server"); +request->send(response); +``` + +### Respond with content using a callback containing templates +```cpp +String processor(const String& var) +{ + if(var == "HELLO_FROM_TEMPLATE") + return F("Hello world!"); + return String(); +} + +// ... + +//send 128 bytes as plain text +request->send("text/plain", 128, [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { + //Write up to "maxLen" bytes into "buffer" and return the amount written. + //index equals the amount of bytes that have been already sent + //You will not be asked for more bytes once the content length has been reached. + //Keep in mind that you can not delay or yield waiting for more data! + //Send what you currently have and you will be asked for more again + return mySource.read(buffer, maxLen); +}, processor); +``` + +### Respond with content using a callback containing templates and extra headers +```cpp +String processor(const String& var) +{ + if(var == "HELLO_FROM_TEMPLATE") + return F("Hello world!"); + return String(); +} + +// ... + +//send 128 bytes as plain text +AsyncWebServerResponse *response = request->beginResponse("text/plain", 128, [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { + //Write up to "maxLen" bytes into "buffer" and return the amount written. + //index equals the amount of bytes that have been already sent + //You will not be asked for more bytes once the content length has been reached. + //Keep in mind that you can not delay or yield waiting for more data! + //Send what you currently have and you will be asked for more again + return mySource.read(buffer, maxLen); +}, processor); +response->addHeader("Server","ESP Async Web Server"); +request->send(response); +``` + +### Chunked Response +Used when content length is unknown. Works best if the client supports HTTP/1.1 +```cpp +AsyncWebServerResponse *response = request->beginChunkedResponse("text/plain", [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { + //Write up to "maxLen" bytes into "buffer" and return the amount written. + //index equals the amount of bytes that have been already sent + //You will be asked for more data until 0 is returned + //Keep in mind that you can not delay or yield waiting for more data! + return mySource.read(buffer, maxLen); +}); +response->addHeader("Server","ESP Async Web Server"); +request->send(response); +``` + +### Chunked Response containing templates +Used when content length is unknown. Works best if the client supports HTTP/1.1 +```cpp +String processor(const String& var) +{ + if(var == "HELLO_FROM_TEMPLATE") + return F("Hello world!"); + return String(); +} + +// ... + +AsyncWebServerResponse *response = request->beginChunkedResponse("text/plain", [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { + //Write up to "maxLen" bytes into "buffer" and return the amount written. + //index equals the amount of bytes that have been already sent + //You will be asked for more data until 0 is returned + //Keep in mind that you can not delay or yield waiting for more data! + return mySource.read(buffer, maxLen); +}, processor); +response->addHeader("Server","ESP Async Web Server"); +request->send(response); +``` + +### Print to response +```cpp +AsyncResponseStream *response = request->beginResponseStream("text/html"); +response->addHeader("Server","ESP Async Web Server"); +response->printf("Webpage at %s", request->url().c_str()); + +response->print("

Hello "); +response->print(request->client()->remoteIP()); +response->print("

"); + +response->print("

General

"); +response->print("
    "); +response->printf("
  • Version: HTTP/1.%u
  • ", request->version()); +response->printf("
  • Method: %s
  • ", request->methodToString()); +response->printf("
  • URL: %s
  • ", request->url().c_str()); +response->printf("
  • Host: %s
  • ", request->host().c_str()); +response->printf("
  • ContentType: %s
  • ", request->contentType().c_str()); +response->printf("
  • ContentLength: %u
  • ", request->contentLength()); +response->printf("
  • Multipart: %s
  • ", request->multipart()?"true":"false"); +response->print("
"); + +response->print("

Headers

"); +response->print("
    "); +int headers = request->headers(); +for(int i=0;igetHeader(i); + response->printf("
  • %s: %s
  • ", h->name().c_str(), h->value().c_str()); +} +response->print("
"); + +response->print("

Parameters

"); +response->print("
    "); +int params = request->params(); +for(int i=0;igetParam(i); + if(p->isFile()){ + response->printf("
  • FILE[%s]: %s, size: %u
  • ", p->name().c_str(), p->value().c_str(), p->size()); + } else if(p->isPost()){ + response->printf("
  • POST[%s]: %s
  • ", p->name().c_str(), p->value().c_str()); + } else { + response->printf("
  • GET[%s]: %s
  • ", p->name().c_str(), p->value().c_str()); + } +} +response->print("
"); + +response->print(""); +//send the response last +request->send(response); +``` + +### ArduinoJson Basic Response +This way of sending Json is great for when the result is below 4KB +```cpp +#include "AsyncJson.h" +#include "ArduinoJson.h" + + +AsyncResponseStream *response = request->beginResponseStream("application/json"); +DynamicJsonBuffer jsonBuffer; +JsonObject &root = jsonBuffer.createObject(); +root["heap"] = ESP.getFreeHeap(); +root["ssid"] = WiFi.SSID(); +root.printTo(*response); +request->send(response); +``` + +### ArduinoJson Advanced Response +This response can handle really large Json objects (tested to 40KB) +There isn't any noticeable speed decrease for small results with the method above +Since ArduinoJson does not allow reading parts of the string, the whole Json has to +be passed every time a chunks needs to be sent, which shows speed decrease proportional +to the resulting json packets +```cpp +#include "AsyncJson.h" +#include "ArduinoJson.h" + + +AsyncJsonResponse * response = new AsyncJsonResponse(); +response->addHeader("Server","ESP Async Web Server"); +JsonObject& root = response->getRoot(); +root["heap"] = ESP.getFreeHeap(); +root["ssid"] = WiFi.SSID(); +response->setLength(); +request->send(response); +``` + +## Serving static files +In addition to serving files from SPIFFS as described above, the server provide a dedicated handler that optimize the +performance of serving files from SPIFFS - ```AsyncStaticWebHandler```. Use ```server.serveStatic()``` function to +initialize and add a new instance of ```AsyncStaticWebHandler``` to the server. +The Handler will not handle the request if the file does not exists, e.g. the server will continue to look for another +handler that can handle the request. +Notice that you can chain setter functions to setup the handler, or keep a pointer to change it at a later time. + +### Serving specific file by name +```cpp +// Serve the file "/www/page.htm" when request url is "/page.htm" +server.serveStatic("/page.htm", SPIFFS, "/www/page.htm"); +``` + +### Serving files in directory +To serve files in a directory, the path to the files should specify a directory in SPIFFS and ends with "/". +```cpp +// Serve files in directory "/www/" when request url starts with "/" +// Request to the root or none existing files will try to server the defualt +// file name "index.htm" if exists +server.serveStatic("/", SPIFFS, "/www/"); + +// Server with different default file +server.serveStatic("/", SPIFFS, "/www/").setDefaultFile("default.html"); +``` + +### Serving static files with authentication + +```cpp +server + .serveStatic("/", SPIFFS, "/www/") + .setDefaultFile("default.html") + .setAuthentication("user", "pass"); +``` + +### Specifying Cache-Control header +It is possible to specify Cache-Control header value to reduce the number of calls to the server once the client loaded +the files. For more information on Cache-Control values see [Cache-Control](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9) +```cpp +// Cache responses for 10 minutes (600 seconds) +server.serveStatic("/", SPIFFS, "/www/").setCacheControl("max-age=600"); + +//*** Change Cache-Control after server setup *** + +// During setup - keep a pointer to the handler +AsyncStaticWebHandler* handler = &server.serveStatic("/", SPIFFS, "/www/").setCacheControl("max-age=600"); + +// At a later event - change Cache-Control +handler->setCacheControl("max-age=30"); +``` + +### Specifying Date-Modified header +It is possible to specify Date-Modified header to enable the server to return Not-Modified (304) response for requests +with "If-Modified-Since" header with the same value, instead of responding with the actual file content. +```cpp +// Update the date modified string every time files are updated +server.serveStatic("/", SPIFFS, "/www/").setLastModified("Mon, 20 Jun 2016 14:00:00 GMT"); + +//*** Chage last modified value at a later stage *** + +// During setup - read last modified value from config or EEPROM +String date_modified = loadDateModified(); +AsyncStaticWebHandler* handler = &server.serveStatic("/", SPIFFS, "/www/"); +handler->setLastModified(date_modified); + +// At a later event when files are updated +String date_modified = getNewDateModfied(); +saveDateModified(date_modified); // Save for next reset +handler->setLastModified(date_modified); +``` + +### Specifying Template Processor callback +It is possible to specify template processor for static files. For information on template processor see +[Respond with content coming from a File containing templates](#respond-with-content-coming-from-a-file-containing-templates). +```cpp +String processor(const String& var) +{ + if(var == "HELLO_FROM_TEMPLATE") + return F("Hello world!"); + return String(); +} + +// ... + +server.serveStatic("/", SPIFFS, "/www/").setTemplateProcessor(processor); +``` + +## Param Rewrite With Matching +It is possible to rewrite the request url with parameter matchg. Here is an example with one parameter: +Rewrite for example "/radio/{frequence}" -> "/radio?f={frequence}" + +```cpp +class OneParamRewrite : public AsyncWebRewrite +{ + protected: + String _urlPrefix; + int _paramIndex; + String _paramsBackup; + + public: + OneParamRewrite(const char* from, const char* to) + : AsyncWebRewrite(from, to) { + + _paramIndex = _from.indexOf('{'); + + if( _paramIndex >=0 && _from.endsWith("}")) { + _urlPrefix = _from.substring(0, _paramIndex); + int index = _params.indexOf('{'); + if(index >= 0) { + _params = _params.substring(0, index); + } + } else { + _urlPrefix = _from; + } + _paramsBackup = _params; + } + + bool match(AsyncWebServerRequest *request) override { + if(request->url().startsWith(_urlPrefix)) { + if(_paramIndex >= 0) { + _params = _paramsBackup + request->url().substring(_paramIndex); + } else { + _params = _paramsBackup; + } + return true; + + } else { + return false; + } + } +}; +``` + +Usage: + +```cpp + server.addRewrite( new OneParamRewrite("/radio/{frequence}", "/radio?f={frequence}") ); +``` + +## Using filters +Filters can be set to `Rewrite` or `Handler` in order to control when to apply the rewrite and consider the handler. +A filter is a callback function that evaluates the request and return a boolean `true` to include the item +or `false` to exclude it. +Two filter callback are provided for convince: +* `ON_STA_FILTER` - return true when requests are made to the STA (station mode) interface. +* `ON_AP_FILTER` - return true when requests are made to the AP (access point) interface. + +### Serve different site files in AP mode +```cpp +server.serveStatic("/", SPIFFS, "/www/").setFilter(ON_STA_FILTER); +server.serveStatic("/", SPIFFS, "/ap/").setFilter(ON_AP_FILTER); +``` + +### Rewrite to different index on AP +```cpp +// Serve the file "/www/index-ap.htm" in AP, and the file "/www/index.htm" on STA +server.rewrite("/", "index.htm"); +server.rewrite("/index.htm", "index-ap.htm").setFilter(ON_AP_FILTER); +server.serveStatic("/", SPIFFS, "/www/"); +``` + +### Serving different hosts +```cpp +// Filter callback using request host +bool filterOnHost1(AsyncWebServerRequest *request) { return request->host() == "host1"; } + +// Server setup: server files in "/host1/" to requests for "host1", and files in "/www/" otherwise. +server.serveStatic("/", SPIFFS, "/host1/").setFilter(filterOnHost1); +server.serveStatic("/", SPIFFS, "/www/"); +``` + +### Determine interface inside callbacks +```cpp + String RedirectUrl = "http://"; + if (ON_STA_FILTER(request)) { + RedirectUrl += WiFi.localIP().toString(); + } else { + RedirectUrl += WiFi.softAPIP().toString(); + } + RedirectUrl += "/index.htm"; + request->redirect(RedirectUrl); +``` + +## Bad Responses +Some responses are implemented, but you should not use them, because they do not conform to HTTP. +The following example will lead to unclean close of the connection and more time wasted +than providing the length of the content + +### Respond with content using a callback without content length to HTTP/1.0 clients +```cpp +//This is used as fallback for chunked responses to HTTP/1.0 Clients +request->send("text/plain", 0, [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { + //Write up to "maxLen" bytes into "buffer" and return the amount written. + //You will be asked for more data until 0 is returned + //Keep in mind that you can not delay or yield waiting for more data! + return mySource.read(buffer, maxLen); +}); +``` + +## Async WebSocket Plugin +The server includes a web socket plugin which lets you define different WebSocket locations to connect to +without starting another listening service or using different port + +### Async WebSocket Event +```cpp + +void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){ + if(type == WS_EVT_CONNECT){ + //client connected + os_printf("ws[%s][%u] connect\n", server->url(), client->id()); + client->printf("Hello Client %u :)", client->id()); + client->ping(); + } else if(type == WS_EVT_DISCONNECT){ + //client disconnected + os_printf("ws[%s][%u] disconnect: %u\n", server->url(), client->id()); + } else if(type == WS_EVT_ERROR){ + //error was received from the other end + os_printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t*)arg), (char*)data); + } else if(type == WS_EVT_PONG){ + //pong message was received (in response to a ping request maybe) + os_printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len)?(char*)data:""); + } else if(type == WS_EVT_DATA){ + //data packet + AwsFrameInfo * info = (AwsFrameInfo*)arg; + if(info->final && info->index == 0 && info->len == len){ + //the whole message is in a single frame and we got all of it's data + os_printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT)?"text":"binary", info->len); + if(info->opcode == WS_TEXT){ + data[len] = 0; + os_printf("%s\n", (char*)data); + } else { + for(size_t i=0; i < info->len; i++){ + os_printf("%02x ", data[i]); + } + os_printf("\n"); + } + if(info->opcode == WS_TEXT) + client->text("I got your text message"); + else + client->binary("I got your binary message"); + } else { + //message is comprised of multiple frames or the frame is split into multiple packets + if(info->index == 0){ + if(info->num == 0) + os_printf("ws[%s][%u] %s-message start\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); + os_printf("ws[%s][%u] frame[%u] start[%llu]\n", server->url(), client->id(), info->num, info->len); + } + + os_printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len); + if(info->message_opcode == WS_TEXT){ + data[len] = 0; + os_printf("%s\n", (char*)data); + } else { + for(size_t i=0; i < len; i++){ + os_printf("%02x ", data[i]); + } + os_printf("\n"); + } + + if((info->index + len) == info->len){ + os_printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len); + if(info->final){ + os_printf("ws[%s][%u] %s-message end\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); + if(info->message_opcode == WS_TEXT) + client->text("I got your text message"); + else + client->binary("I got your binary message"); + } + } + } + } +} +``` + +### Methods for sending data to a socket client +```cpp + + + +//Server methods +AsyncWebSocket ws("/ws"); +//printf to a client +ws.printf((uint32_t)client_id, arguments...); +//printf to all clients +ws.printfAll(arguments...); +//printf_P to a client +ws.printf_P((uint32_t)client_id, PSTR(format), arguments...); +//printfAll_P to all clients +ws.printfAll_P(PSTR(format), arguments...); +//send text to a client +ws.text((uint32_t)client_id, (char*)text); +ws.text((uint32_t)client_id, (uint8_t*)text, (size_t)len); +//send text from PROGMEM to a client +ws.text((uint32_t)client_id, PSTR("text")); +const char flash_text[] PROGMEM = "Text to send" +ws.text((uint32_t)client_id, FPSTR(flash_text)); +//send text to all clients +ws.textAll((char*)text); +ws.textAll((uint8_t*)text, (size_t)len); +//send binary to a client +ws.binary((uint32_t)client_id, (char*)binary); +ws.binary((uint32_t)client_id, (uint8_t*)binary, (size_t)len); +//send binary from PROGMEM to a client +const uint8_t flash_binary[] PROGMEM = { 0x01, 0x02, 0x03, 0x04 }; +ws.binary((uint32_t)client_id, flash_binary, 4); +//send binary to all clients +ws.binaryAll((char*)binary); +ws.binaryAll((uint8_t*)binary, (size_t)len); +//HTTP Authenticate before switch to Websocket protocol +ws.setAuthentication("user", "pass"); + +//client methods +AsyncWebSocketClient * client; +//printf +client->printf(arguments...); +//printf_P +client->printf_P(PSTR(format), arguments...); +//send text +client->text((char*)text); +client->text((uint8_t*)text, (size_t)len); +//send text from PROGMEM +client->text(PSTR("text")); +const char flash_text[] PROGMEM = "Text to send"; +client->text(FPSTR(flash_text)); +//send binary +client->binary((char*)binary); +client->binary((uint8_t*)binary, (size_t)len); +//send binary from PROGMEM +const uint8_t flash_binary[] PROGMEM = { 0x01, 0x02, 0x03, 0x04 }; +client->binary(flash_binary, 4); +``` + +### Direct access to web socket message buffer +When sending a web socket message using the above methods a buffer is created. Under certain circumstances you might want to manipulate or populate this buffer directly from your application, for example to prevent unnecessary duplications of the data. This example below shows how to create a buffer and print data to it from an ArduinoJson object then send it. + +```cpp +void sendDataWs(AsyncWebSocketClient * client) +{ + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.createObject(); + root["a"] = "abc"; + root["b"] = "abcd"; + root["c"] = "abcde"; + root["d"] = "abcdef"; + root["e"] = "abcdefg"; + size_t len = root.measureLength(); + AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); // creates a buffer (len + 1) for you. + if (buffer) { + root.printTo((char *)buffer->get(), len + 1); + if (client) { + client->text(buffer); + } else { + ws.textAll(buffer); + } + } +} +``` + +### Limiting the number of web socket clients +Browsers sometimes do not correctly close the websocket connection, even when the close() function is called in javascript. This will eventually exhaust the web server's resources and will cause the server to crash. Periodically calling the cleanClients() function from the main loop() function limits the number of clients by closing the oldest client when the maximum number of clients has been exceeded. This can called be every cycle, however, if you wish to use less power, then calling as infrequently as once per second is sufficient. + +```cpp +void loop(){ + ws.cleanupClients(); +} +``` + + +## Async Event Source Plugin +The server includes EventSource (Server-Sent Events) plugin which can be used to send short text events to the browser. +Difference between EventSource and WebSockets is that EventSource is single direction, text-only protocol. + +### Setup Event Source on the server +```cpp +AsyncWebServer server(80); +AsyncEventSource events("/events"); + +void setup(){ + // setup ...... + events.onConnect([](AsyncEventSourceClient *client){ + if(client->lastId()){ + Serial.printf("Client reconnected! Last message ID that it gat is: %u\n", client->lastId()); + } + //send event with message "hello!", id current millis + // and set reconnect delay to 1 second + client->send("hello!",NULL,millis(),1000); + }); + //HTTP Basic authentication + events.setAuthentication("user", "pass"); + server.addHandler(&events); + // setup ...... +} + +void loop(){ + if(eventTriggered){ // your logic here + //send event "myevent" + events.send("my event content","myevent",millis()); + } +} +``` + +### Setup Event Source in the browser +```javascript +if (!!window.EventSource) { + var source = new EventSource('/events'); + + source.addEventListener('open', function(e) { + console.log("Events Connected"); + }, false); + + source.addEventListener('error', function(e) { + if (e.target.readyState != EventSource.OPEN) { + console.log("Events Disconnected"); + } + }, false); + + source.addEventListener('message', function(e) { + console.log("message", e.data); + }, false); + + source.addEventListener('myevent', function(e) { + console.log("myevent", e.data); + }, false); +} +``` + +## Scanning for available WiFi Networks +```cpp +//First request will return 0 results unless you start scan from somewhere else (loop/setup) +//Do not request more often than 3-5 seconds +server.on("/scan", HTTP_GET, [](AsyncWebServerRequest *request){ + String json = "["; + int n = WiFi.scanComplete(); + if(n == -2){ + WiFi.scanNetworks(true); + } else if(n){ + for (int i = 0; i < n; ++i){ + if(i) json += ","; + json += "{"; + json += "\"rssi\":"+String(WiFi.RSSI(i)); + json += ",\"ssid\":\""+WiFi.SSID(i)+"\""; + json += ",\"bssid\":\""+WiFi.BSSIDstr(i)+"\""; + json += ",\"channel\":"+String(WiFi.channel(i)); + json += ",\"secure\":"+String(WiFi.encryptionType(i)); + json += ",\"hidden\":"+String(WiFi.isHidden(i)?"true":"false"); + json += "}"; + } + WiFi.scanDelete(); + if(WiFi.scanComplete() == -2){ + WiFi.scanNetworks(true); + } + } + json += "]"; + request->send(200, "application/json", json); + json = String(); +}); +``` + +## Remove handlers and rewrites + +Server goes through handlers in same order as they were added. You can't simple add handler with same path to override them. +To remove handler: +```arduino +// save callback for particular URL path +auto handler = server.on("/some/path", [](AsyncWebServerRequest *request){ + //do something useful +}); +// when you don't need handler anymore remove it +server.removeHandler(&handler); + +// same with rewrites +server.removeRewrite(&someRewrite); + +server.onNotFound([](AsyncWebServerRequest *request){ + request->send(404); +}); + +// remove server.onNotFound handler +server.onNotFound(NULL); + +// remove all rewrites, handlers and onNotFound/onFileUpload/onRequestBody callbacks +server.reset(); +``` + +## Setting up the server +```cpp +#include "ESPAsyncTCP.h" +#include "ESPAsyncWebServer.h" + +AsyncWebServer server(80); +AsyncWebSocket ws("/ws"); // access at ws://[esp ip]/ws +AsyncEventSource events("/events"); // event source (Server-Sent events) + +const char* ssid = "your-ssid"; +const char* password = "your-pass"; +const char* http_username = "admin"; +const char* http_password = "admin"; + +//flag to use from web update to reboot the ESP +bool shouldReboot = false; + +void onRequest(AsyncWebServerRequest *request){ + //Handle Unknown Request + request->send(404); +} + +void onBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){ + //Handle body +} + +void onUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ + //Handle upload +} + +void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){ + //Handle WebSocket event +} + +void setup(){ + Serial.begin(115200); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + if (WiFi.waitForConnectResult() != WL_CONNECTED) { + Serial.printf("WiFi Failed!\n"); + return; + } + + // attach AsyncWebSocket + ws.onEvent(onEvent); + server.addHandler(&ws); + + // attach AsyncEventSource + server.addHandler(&events); + + // respond to GET requests on URL /heap + server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){ + request->send(200, "text/plain", String(ESP.getFreeHeap())); + }); + + // upload a file to /upload + server.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request){ + request->send(200); + }, onUpload); + + // send a file when /index is requested + server.on("/index", HTTP_ANY, [](AsyncWebServerRequest *request){ + request->send(SPIFFS, "/index.htm"); + }); + + // HTTP basic authentication + server.on("/login", HTTP_GET, [](AsyncWebServerRequest *request){ + if(!request->authenticate(http_username, http_password)) + return request->requestAuthentication(); + request->send(200, "text/plain", "Login Success!"); + }); + + // Simple Firmware Update Form + server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){ + request->send(200, "text/html", "
"); + }); + server.on("/update", HTTP_POST, [](AsyncWebServerRequest *request){ + shouldReboot = !Update.hasError(); + AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", shouldReboot?"OK":"FAIL"); + response->addHeader("Connection", "close"); + request->send(response); + },[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ + if(!index){ + Serial.printf("Update Start: %s\n", filename.c_str()); + Update.runAsync(true); + if(!Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000)){ + Update.printError(Serial); + } + } + if(!Update.hasError()){ + if(Update.write(data, len) != len){ + Update.printError(Serial); + } + } + if(final){ + if(Update.end(true)){ + Serial.printf("Update Success: %uB\n", index+len); + } else { + Update.printError(Serial); + } + } + }); + + // attach filesystem root at URL /fs + server.serveStatic("/fs", SPIFFS, "/"); + + // Catch-All Handlers + // Any request that can not find a Handler that canHandle it + // ends in the callbacks below. + server.onNotFound(onRequest); + server.onFileUpload(onUpload); + server.onRequestBody(onBody); + + server.begin(); +} + +void loop(){ + if(shouldReboot){ + Serial.println("Rebooting..."); + delay(100); + ESP.restart(); + } + static char temp[128]; + sprintf(temp, "Seconds since boot: %u", millis()/1000); + events.send(temp, "time"); //send event "time" +} +``` + +### Setup global and class functions as request handlers + +```cpp +#include +#include +#include +#include + +void handleRequest(AsyncWebServerRequest *request){} + +class WebClass { +public : + AsyncWebServer classWebServer = AsyncWebServer(81); + + WebClass(){}; + + void classRequest (AsyncWebServerRequest *request){} + + void begin(){ + // attach global request handler + classWebServer.on("/example", HTTP_ANY, handleRequest); + + // attach class request handler + classWebServer.on("/example", HTTP_ANY, std::bind(&WebClass::classRequest, this, std::placeholders::_1)); + } +}; + +AsyncWebServer globalWebServer(80); +WebClass webClassInstance; + +void setup() { + // attach global request handler + globalWebServer.on("/example", HTTP_ANY, handleRequest); + + // attach class request handler + globalWebServer.on("/example", HTTP_ANY, std::bind(&WebClass::classRequest, webClassInstance, std::placeholders::_1)); +} + +void loop() { + +} +``` + +### Methods for controlling websocket connections + +```cpp + // Disable client connections if it was activated + if ( ws.enabled() ) + ws.enable(false); + + // enable client connections if it was disabled + if ( !ws.enabled() ) + ws.enable(true); +``` + +Example of OTA code + +```cpp + // OTA callbacks + ArduinoOTA.onStart([]() { + // Clean SPIFFS + SPIFFS.end(); + + // Disable client connections + ws.enable(false); + + // Advertise connected clients what's going on + ws.textAll("OTA Update Started"); + + // Close them + ws.closeAll(); + + }); + +``` + +### Adding Default Headers + +In some cases, such as when working with CORS, or with some sort of custom authentication system, +you might need to define a header that should get added to all responses (including static, websocket and EventSource). +The DefaultHeaders singleton allows you to do this. + +Example: + +```cpp +DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*"); +webServer.begin(); +``` + +*NOTE*: You will still need to respond to the OPTIONS method for CORS pre-flight in most cases. (unless you are only using GET) + +This is one option: + +```cpp +webServer.onNotFound([](AsyncWebServerRequest *request) { + if (request->method() == HTTP_OPTIONS) { + request->send(200); + } else { + request->send(404); + } +}); +``` + +### Path variable + +With path variable you can create a custom regex rule for a specific parameter in a route. +For example we want a `sensorId` parameter in a route rule to match only a integer. + +```cpp + server.on("^\\/sensor\\/([0-9]+)$", HTTP_GET, [] (AsyncWebServerRequest *request) { + String sensorId = request->pathArg(0); + }); +``` +*NOTE*: All regex patterns starts with `^` and ends with `$` + +To enable the `Path variable` support, you have to define the buildflag `-DASYNCWEBSERVER_REGEX`. + + +For Arduino IDE create/update `platform.local.txt`: + +`Windows`: C:\Users\(username)\AppData\Local\Arduino15\packages\\`{espxxxx}`\hardware\\`espxxxx`\\`{version}`\platform.local.txt + +`Linux`: ~/.arduino15/packages/`{espxxxx}`/hardware/`{espxxxx}`/`{version}`/platform.local.txt + +Add/Update the following line: +``` + compiler.cpp.extra_flags=-DDASYNCWEBSERVER_REGEX +``` + +For platformio modify `platformio.ini`: +```ini +[env:myboard] +build_flags = + -DASYNCWEBSERVER_REGEX +``` +*NOTE*: By enabling `ASYNCWEBSERVER_REGEX`, `` will be included. This will add an 100k to your binary. diff --git a/lib/libesp32/ESPAsyncWebServer/_config.yml b/lib/libesp32/ESPAsyncWebServer/_config.yml new file mode 100644 index 000000000..c4192631f --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file diff --git a/lib/libesp32/ESPAsyncWebServer/component.mk b/lib/libesp32/ESPAsyncWebServer/component.mk new file mode 100644 index 000000000..bb5bb1614 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/component.mk @@ -0,0 +1,3 @@ +COMPONENT_ADD_INCLUDEDIRS := src +COMPONENT_SRCDIRS := src +CXXFLAGS += -fno-rtti diff --git a/lib/libesp32/ESPAsyncWebServer/examples/CaptivePortal/CaptivePortal.ino b/lib/libesp32/ESPAsyncWebServer/examples/CaptivePortal/CaptivePortal.ino new file mode 100644 index 000000000..f97f142a6 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/examples/CaptivePortal/CaptivePortal.ino @@ -0,0 +1,47 @@ +#include +#ifdef ESP32 +#include +#include +#elif defined(ESP8266) +#include +#include +#endif +#include "ESPAsyncWebServer.h" + +DNSServer dnsServer; +AsyncWebServer server(80); + +class CaptiveRequestHandler : public AsyncWebHandler { +public: + CaptiveRequestHandler() {} + virtual ~CaptiveRequestHandler() {} + + bool canHandle(AsyncWebServerRequest *request){ + //request->addInterestingHeader("ANY"); + return true; + } + + void handleRequest(AsyncWebServerRequest *request) { + AsyncResponseStream *response = request->beginResponseStream("text/html"); + response->print("Captive Portal"); + response->print("

This is out captive portal front page.

"); + response->printf("

You were trying to reach: http://%s%s

", request->host().c_str(), request->url().c_str()); + response->printf("

Try opening this link instead

", WiFi.softAPIP().toString().c_str()); + response->print(""); + request->send(response); + } +}; + + +void setup(){ + //your other setup stuff... + WiFi.softAP("esp-captive"); + dnsServer.start(53, "*", WiFi.softAPIP()); + server.addHandler(new CaptiveRequestHandler()).setFilter(ON_AP_FILTER);//only when requested from AP + //more handlers... + server.begin(); +} + +void loop(){ + dnsServer.processNextRequest(); +} diff --git a/lib/libesp32/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino b/lib/libesp32/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino new file mode 100644 index 000000000..bf42d0038 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino @@ -0,0 +1,221 @@ +#include +#ifdef ESP32 +#include +#include +#include +#include +#include +#elif defined(ESP8266) +#include +#include +#include +#endif +#include +#include + +// SKETCH BEGIN +AsyncWebServer server(80); +AsyncWebSocket ws("/ws"); +AsyncEventSource events("/events"); + +void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){ + if(type == WS_EVT_CONNECT){ + Serial.printf("ws[%s][%u] connect\n", server->url(), client->id()); + client->printf("Hello Client %u :)", client->id()); + client->ping(); + } else if(type == WS_EVT_DISCONNECT){ + Serial.printf("ws[%s][%u] disconnect\n", server->url(), client->id()); + } else if(type == WS_EVT_ERROR){ + Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t*)arg), (char*)data); + } else if(type == WS_EVT_PONG){ + Serial.printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len)?(char*)data:""); + } else if(type == WS_EVT_DATA){ + AwsFrameInfo * info = (AwsFrameInfo*)arg; + String msg = ""; + if(info->final && info->index == 0 && info->len == len){ + //the whole message is in a single frame and we got all of it's data + Serial.printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT)?"text":"binary", info->len); + + if(info->opcode == WS_TEXT){ + for(size_t i=0; i < info->len; i++) { + msg += (char) data[i]; + } + } else { + char buff[3]; + for(size_t i=0; i < info->len; i++) { + sprintf(buff, "%02x ", (uint8_t) data[i]); + msg += buff ; + } + } + Serial.printf("%s\n",msg.c_str()); + + if(info->opcode == WS_TEXT) + client->text("I got your text message"); + else + client->binary("I got your binary message"); + } else { + //message is comprised of multiple frames or the frame is split into multiple packets + if(info->index == 0){ + if(info->num == 0) + Serial.printf("ws[%s][%u] %s-message start\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); + Serial.printf("ws[%s][%u] frame[%u] start[%llu]\n", server->url(), client->id(), info->num, info->len); + } + + Serial.printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len); + + if(info->opcode == WS_TEXT){ + for(size_t i=0; i < len; i++) { + msg += (char) data[i]; + } + } else { + char buff[3]; + for(size_t i=0; i < len; i++) { + sprintf(buff, "%02x ", (uint8_t) data[i]); + msg += buff ; + } + } + Serial.printf("%s\n",msg.c_str()); + + if((info->index + len) == info->len){ + Serial.printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len); + if(info->final){ + Serial.printf("ws[%s][%u] %s-message end\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); + if(info->message_opcode == WS_TEXT) + client->text("I got your text message"); + else + client->binary("I got your binary message"); + } + } + } + } +} + + +const char* ssid = "*******"; +const char* password = "*******"; +const char * hostName = "esp-async"; +const char* http_username = "admin"; +const char* http_password = "admin"; + +void setup(){ + Serial.begin(115200); + Serial.setDebugOutput(true); + WiFi.mode(WIFI_AP_STA); + WiFi.softAP(hostName); + WiFi.begin(ssid, password); + if (WiFi.waitForConnectResult() != WL_CONNECTED) { + Serial.printf("STA: Failed!\n"); + WiFi.disconnect(false); + delay(1000); + WiFi.begin(ssid, password); + } + + //Send OTA events to the browser + ArduinoOTA.onStart([]() { events.send("Update Start", "ota"); }); + ArduinoOTA.onEnd([]() { events.send("Update End", "ota"); }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + char p[32]; + sprintf(p, "Progress: %u%%\n", (progress/(total/100))); + events.send(p, "ota"); + }); + ArduinoOTA.onError([](ota_error_t error) { + if(error == OTA_AUTH_ERROR) events.send("Auth Failed", "ota"); + else if(error == OTA_BEGIN_ERROR) events.send("Begin Failed", "ota"); + else if(error == OTA_CONNECT_ERROR) events.send("Connect Failed", "ota"); + else if(error == OTA_RECEIVE_ERROR) events.send("Recieve Failed", "ota"); + else if(error == OTA_END_ERROR) events.send("End Failed", "ota"); + }); + ArduinoOTA.setHostname(hostName); + ArduinoOTA.begin(); + + MDNS.addService("http","tcp",80); + + SPIFFS.begin(); + + ws.onEvent(onWsEvent); + server.addHandler(&ws); + + events.onConnect([](AsyncEventSourceClient *client){ + client->send("hello!",NULL,millis(),1000); + }); + server.addHandler(&events); + +#ifdef ESP32 + server.addHandler(new SPIFFSEditor(SPIFFS, http_username,http_password)); +#elif defined(ESP8266) + server.addHandler(new SPIFFSEditor(http_username,http_password)); +#endif + + server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){ + request->send(200, "text/plain", String(ESP.getFreeHeap())); + }); + + server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm"); + + server.onNotFound([](AsyncWebServerRequest *request){ + Serial.printf("NOT_FOUND: "); + if(request->method() == HTTP_GET) + Serial.printf("GET"); + else if(request->method() == HTTP_POST) + Serial.printf("POST"); + else if(request->method() == HTTP_DELETE) + Serial.printf("DELETE"); + else if(request->method() == HTTP_PUT) + Serial.printf("PUT"); + else if(request->method() == HTTP_PATCH) + Serial.printf("PATCH"); + else if(request->method() == HTTP_HEAD) + Serial.printf("HEAD"); + else if(request->method() == HTTP_OPTIONS) + Serial.printf("OPTIONS"); + else + Serial.printf("UNKNOWN"); + Serial.printf(" http://%s%s\n", request->host().c_str(), request->url().c_str()); + + if(request->contentLength()){ + Serial.printf("_CONTENT_TYPE: %s\n", request->contentType().c_str()); + Serial.printf("_CONTENT_LENGTH: %u\n", request->contentLength()); + } + + int headers = request->headers(); + int i; + for(i=0;igetHeader(i); + Serial.printf("_HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str()); + } + + int params = request->params(); + for(i=0;igetParam(i); + if(p->isFile()){ + Serial.printf("_FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size()); + } else if(p->isPost()){ + Serial.printf("_POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); + } else { + Serial.printf("_GET[%s]: %s\n", p->name().c_str(), p->value().c_str()); + } + } + + request->send(404); + }); + server.onFileUpload([](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){ + if(!index) + Serial.printf("UploadStart: %s\n", filename.c_str()); + Serial.printf("%s", (const char*)data); + if(final) + Serial.printf("UploadEnd: %s (%u)\n", filename.c_str(), index+len); + }); + server.onRequestBody([](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){ + if(!index) + Serial.printf("BodyStart: %u\n", total); + Serial.printf("%s", (const char*)data); + if(index + len == total) + Serial.printf("BodyEnd: %u\n", total); + }); + server.begin(); +} + +void loop(){ + ArduinoOTA.handle(); + ws.cleanupClients(); +} diff --git a/lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/.test.build_flags b/lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/.test.build_flags new file mode 100644 index 000000000..9ea3bb74a --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/.test.build_flags @@ -0,0 +1 @@ +-DASYNCWEBSERVER_REGEX=1 diff --git a/lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/regex_patterns.ino b/lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/regex_patterns.ino new file mode 100644 index 000000000..fb013063e --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/regex_patterns.ino @@ -0,0 +1,77 @@ +// +// A simple server implementation with regex routes: +// * serve static messages +// * read GET and POST parameters +// * handle missing pages / 404s +// + +// Add buildflag ASYNCWEBSERVER_REGEX to enable the regex support + +// For platformio: platformio.ini: +// build_flags = +// -DASYNCWEBSERVER_REGEX + +// For arduino IDE: create/update platform.local.txt +// Windows: C:\Users\(username)\AppData\Local\Arduino15\packages\espxxxx\hardware\espxxxx\{version}\platform.local.txt +// Linux: ~/.arduino15/packages/espxxxx/hardware/espxxxx/{version}/platform.local.txt +// +// compiler.cpp.extra_flags=-DASYNCWEBSERVER_REGEX=1 + +#include +#ifdef ESP32 +#include +#include +#elif defined(ESP8266) +#include +#include +#endif +#include + +AsyncWebServer server(80); + +const char* ssid = "YOUR_SSID"; +const char* password = "YOUR_PASSWORD"; + +const char* PARAM_MESSAGE = "message"; + +void notFound(AsyncWebServerRequest *request) { + request->send(404, "text/plain", "Not found"); +} + +void setup() { + + Serial.begin(115200); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + if (WiFi.waitForConnectResult() != WL_CONNECTED) { + Serial.printf("WiFi Failed!\n"); + return; + } + + Serial.print("IP Address: "); + Serial.println(WiFi.localIP()); + + server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ + request->send(200, "text/plain", "Hello, world"); + }); + + // Send a GET request to /sensor/ + server.on("^\\/sensor\\/([0-9]+)$", HTTP_GET, [] (AsyncWebServerRequest *request) { + String sensorNumber = request->pathArg(0); + request->send(200, "text/plain", "Hello, sensor: " + sensorNumber); + }); + + // Send a GET request to /sensor//action/ + server.on("^\\/sensor\\/([0-9]+)\\/action\\/([a-zA-Z0-9]+)$", HTTP_GET, [] (AsyncWebServerRequest *request) { + String sensorNumber = request->pathArg(0); + String action = request->pathArg(1); + request->send(200, "text/plain", "Hello, sensor: " + sensorNumber + ", with action: " + action); + }); + + server.onNotFound(notFound); + + server.begin(); +} + +void loop() { +} diff --git a/lib/libesp32/ESPAsyncWebServer/examples/simple_server/simple_server.ino b/lib/libesp32/ESPAsyncWebServer/examples/simple_server/simple_server.ino new file mode 100644 index 000000000..bdbcf60dc --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/examples/simple_server/simple_server.ino @@ -0,0 +1,74 @@ +// +// A simple server implementation showing how to: +// * serve static messages +// * read GET and POST parameters +// * handle missing pages / 404s +// + +#include +#ifdef ESP32 +#include +#include +#elif defined(ESP8266) +#include +#include +#endif +#include + +AsyncWebServer server(80); + +const char* ssid = "YOUR_SSID"; +const char* password = "YOUR_PASSWORD"; + +const char* PARAM_MESSAGE = "message"; + +void notFound(AsyncWebServerRequest *request) { + request->send(404, "text/plain", "Not found"); +} + +void setup() { + + Serial.begin(115200); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + if (WiFi.waitForConnectResult() != WL_CONNECTED) { + Serial.printf("WiFi Failed!\n"); + return; + } + + Serial.print("IP Address: "); + Serial.println(WiFi.localIP()); + + server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ + request->send(200, "text/plain", "Hello, world"); + }); + + // Send a GET request to /get?message= + server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) { + String message; + if (request->hasParam(PARAM_MESSAGE)) { + message = request->getParam(PARAM_MESSAGE)->value(); + } else { + message = "No message sent"; + } + request->send(200, "text/plain", "Hello, GET: " + message); + }); + + // Send a POST request to /post with a form field message set to + server.on("/post", HTTP_POST, [](AsyncWebServerRequest *request){ + String message; + if (request->hasParam(PARAM_MESSAGE, true)) { + message = request->getParam(PARAM_MESSAGE, true)->value(); + } else { + message = "No message sent"; + } + request->send(200, "text/plain", "Hello, POST: " + message); + }); + + server.onNotFound(notFound); + + server.begin(); +} + +void loop() { +} \ No newline at end of file diff --git a/lib/libesp32/ESPAsyncWebServer/keywords.txt b/lib/libesp32/ESPAsyncWebServer/keywords.txt new file mode 100644 index 000000000..c391e6c43 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/keywords.txt @@ -0,0 +1,3 @@ +JsonArray KEYWORD1 +add KEYWORD2 +createArray KEYWORD3 diff --git a/lib/libesp32/ESPAsyncWebServer/library.json b/lib/libesp32/ESPAsyncWebServer/library.json new file mode 100644 index 000000000..750ca28d2 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/library.json @@ -0,0 +1,37 @@ +{ + "name":"ESP Async WebServer", + "description":"Asynchronous HTTP and WebSocket Server Library for ESP8266 and ESP32", + "keywords":"http,async,websocket,webserver", + "authors": + { + "name": "Hristo Gochkov", + "maintainer": true + }, + "repository": + { + "type": "git", + "url": "https://github.com/me-no-dev/ESPAsyncWebServer.git" + }, + "version": "1.2.3", + "license": "LGPL-3.0", + "frameworks": "arduino", + "platforms": ["espressif8266", "espressif32"], + "dependencies": [ + { + "owner": "me-no-dev", + "name": "ESPAsyncTCP", + "version": "^1.2.2", + "platforms": "espressif8266" + }, + { + "owner": "me-no-dev", + "name": "AsyncTCP", + "version": "^1.1.1", + "platforms": "espressif32" + }, + { + "name": "Hash", + "platforms": "espressif8266" + } + ] +} diff --git a/lib/libesp32/ESPAsyncWebServer/library.properties b/lib/libesp32/ESPAsyncWebServer/library.properties new file mode 100644 index 000000000..401b04173 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/library.properties @@ -0,0 +1,9 @@ +name=ESP Async WebServer +version=1.2.3 +author=Me-No-Dev +maintainer=Me-No-Dev +sentence=Async Web Server for ESP8266 and ESP31B +paragraph=Async Web Server for ESP8266 and ESP31B +category=Other +url=https://github.com/me-no-dev/ESPAsyncWebServer +architectures=* diff --git a/lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.cpp b/lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.cpp new file mode 100644 index 000000000..663177b59 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.cpp @@ -0,0 +1,368 @@ +/* + Asynchronous WebServer library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "Arduino.h" +#include "AsyncEventSource.h" + +static String generateEventMessage(const char *message, const char *event, uint32_t id, uint32_t reconnect){ + String ev = ""; + + if(reconnect){ + ev += "retry: "; + ev += String(reconnect); + ev += "\r\n"; + } + + if(id){ + ev += "id: "; + ev += String(id); + ev += "\r\n"; + } + + if(event != NULL){ + ev += "event: "; + ev += String(event); + ev += "\r\n"; + } + + if(message != NULL){ + size_t messageLen = strlen(message); + char * lineStart = (char *)message; + char * lineEnd; + do { + char * nextN = strchr(lineStart, '\n'); + char * nextR = strchr(lineStart, '\r'); + if(nextN == NULL && nextR == NULL){ + size_t llen = ((char *)message + messageLen) - lineStart; + char * ldata = (char *)malloc(llen+1); + if(ldata != NULL){ + memcpy(ldata, lineStart, llen); + ldata[llen] = 0; + ev += "data: "; + ev += ldata; + ev += "\r\n\r\n"; + free(ldata); + } + lineStart = (char *)message + messageLen; + } else { + char * nextLine = NULL; + if(nextN != NULL && nextR != NULL){ + if(nextR < nextN){ + lineEnd = nextR; + if(nextN == (nextR + 1)) + nextLine = nextN + 1; + else + nextLine = nextR + 1; + } else { + lineEnd = nextN; + if(nextR == (nextN + 1)) + nextLine = nextR + 1; + else + nextLine = nextN + 1; + } + } else if(nextN != NULL){ + lineEnd = nextN; + nextLine = nextN + 1; + } else { + lineEnd = nextR; + nextLine = nextR + 1; + } + + size_t llen = lineEnd - lineStart; + char * ldata = (char *)malloc(llen+1); + if(ldata != NULL){ + memcpy(ldata, lineStart, llen); + ldata[llen] = 0; + ev += "data: "; + ev += ldata; + ev += "\r\n"; + free(ldata); + } + lineStart = nextLine; + if(lineStart == ((char *)message + messageLen)) + ev += "\r\n"; + } + } while(lineStart < ((char *)message + messageLen)); + } + + return ev; +} + +// Message + +AsyncEventSourceMessage::AsyncEventSourceMessage(const char * data, size_t len) +: _data(nullptr), _len(len), _sent(0), _acked(0) +{ + _data = (uint8_t*)malloc(_len+1); + if(_data == nullptr){ + _len = 0; + } else { + memcpy(_data, data, len); + _data[_len] = 0; + } +} + +AsyncEventSourceMessage::~AsyncEventSourceMessage() { + if(_data != NULL) + free(_data); +} + +size_t AsyncEventSourceMessage::ack(size_t len, uint32_t time) { + (void)time; + // If the whole message is now acked... + if(_acked + len > _len){ + // Return the number of extra bytes acked (they will be carried on to the next message) + const size_t extra = _acked + len - _len; + _acked = _len; + return extra; + } + // Return that no extra bytes left. + _acked += len; + return 0; +} + +size_t AsyncEventSourceMessage::send(AsyncClient *client) { + const size_t len = _len - _sent; + if(client->space() < len){ + return 0; + } + size_t sent = client->add((const char *)_data, len); + if(client->canSend()) + client->send(); + _sent += sent; + return sent; +} + +// Client + +AsyncEventSourceClient::AsyncEventSourceClient(AsyncWebServerRequest *request, AsyncEventSource *server) +: _messageQueue(AsyncLinkedList([](AsyncEventSourceMessage *m){ delete m; })) +{ + _client = request->client(); + _server = server; + _lastId = 0; + if(request->hasHeader("Last-Event-ID")) + _lastId = atoi(request->getHeader("Last-Event-ID")->value().c_str()); + + _client->setRxTimeout(0); + _client->onError(NULL, NULL); + _client->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ (void)c; ((AsyncEventSourceClient*)(r))->_onAck(len, time); }, this); + _client->onPoll([](void *r, AsyncClient* c){ (void)c; ((AsyncEventSourceClient*)(r))->_onPoll(); }, this); + _client->onData(NULL, NULL); + _client->onTimeout([this](void *r, AsyncClient* c __attribute__((unused)), uint32_t time){ ((AsyncEventSourceClient*)(r))->_onTimeout(time); }, this); + _client->onDisconnect([this](void *r, AsyncClient* c){ ((AsyncEventSourceClient*)(r))->_onDisconnect(); delete c; }, this); + + _server->_addClient(this); + delete request; +} + +AsyncEventSourceClient::~AsyncEventSourceClient(){ + _messageQueue.free(); + close(); +} + +void AsyncEventSourceClient::_queueMessage(AsyncEventSourceMessage *dataMessage){ + if(dataMessage == NULL) + return; + if(!connected()){ + delete dataMessage; + return; + } + if(_messageQueue.length() >= SSE_MAX_QUEUED_MESSAGES){ + ets_printf("ERROR: Too many messages queued\n"); + delete dataMessage; + } else { + _messageQueue.add(dataMessage); + } + if(_client->canSend()) + _runQueue(); +} + +void AsyncEventSourceClient::_onAck(size_t len, uint32_t time){ + while(len && !_messageQueue.isEmpty()){ + len = _messageQueue.front()->ack(len, time); + if(_messageQueue.front()->finished()) + _messageQueue.remove(_messageQueue.front()); + } + + _runQueue(); +} + +void AsyncEventSourceClient::_onPoll(){ + if(!_messageQueue.isEmpty()){ + _runQueue(); + } +} + + +void AsyncEventSourceClient::_onTimeout(uint32_t time __attribute__((unused))){ + _client->close(true); +} + +void AsyncEventSourceClient::_onDisconnect(){ + _client = NULL; + _server->_handleDisconnect(this); +} + +void AsyncEventSourceClient::close(){ + if(_client != NULL) + _client->close(); +} + +void AsyncEventSourceClient::write(const char * message, size_t len){ + _queueMessage(new AsyncEventSourceMessage(message, len)); +} + +void AsyncEventSourceClient::send(const char *message, const char *event, uint32_t id, uint32_t reconnect){ + String ev = generateEventMessage(message, event, id, reconnect); + _queueMessage(new AsyncEventSourceMessage(ev.c_str(), ev.length())); +} + +void AsyncEventSourceClient::_runQueue(){ + while(!_messageQueue.isEmpty() && _messageQueue.front()->finished()){ + _messageQueue.remove(_messageQueue.front()); + } + + for(auto i = _messageQueue.begin(); i != _messageQueue.end(); ++i) + { + if(!(*i)->sent()) + (*i)->send(_client); + } +} + + +// Handler + +AsyncEventSource::AsyncEventSource(const String& url) + : _url(url) + , _clients(AsyncLinkedList([](AsyncEventSourceClient *c){ delete c; })) + , _connectcb(NULL) +{} + +AsyncEventSource::~AsyncEventSource(){ + close(); +} + +void AsyncEventSource::onConnect(ArEventHandlerFunction cb){ + _connectcb = cb; +} + +void AsyncEventSource::_addClient(AsyncEventSourceClient * client){ + /*char * temp = (char *)malloc(2054); + if(temp != NULL){ + memset(temp+1,' ',2048); + temp[0] = ':'; + temp[2049] = '\r'; + temp[2050] = '\n'; + temp[2051] = '\r'; + temp[2052] = '\n'; + temp[2053] = 0; + client->write((const char *)temp, 2053); + free(temp); + }*/ + + _clients.add(client); + if(_connectcb) + _connectcb(client); +} + +void AsyncEventSource::_handleDisconnect(AsyncEventSourceClient * client){ + _clients.remove(client); +} + +void AsyncEventSource::close(){ + for(const auto &c: _clients){ + if(c->connected()) + c->close(); + } +} + +// pmb fix +size_t AsyncEventSource::avgPacketsWaiting() const { + if(_clients.isEmpty()) + return 0; + + size_t aql=0; + uint32_t nConnectedClients=0; + + for(const auto &c: _clients){ + if(c->connected()) { + aql+=c->packetsWaiting(); + ++nConnectedClients; + } + } +// return aql / nConnectedClients; + return ((aql) + (nConnectedClients/2))/(nConnectedClients); // round up +} + +void AsyncEventSource::send(const char *message, const char *event, uint32_t id, uint32_t reconnect){ + + + String ev = generateEventMessage(message, event, id, reconnect); + for(const auto &c: _clients){ + if(c->connected()) { + c->write(ev.c_str(), ev.length()); + } + } +} + +size_t AsyncEventSource::count() const { + return _clients.count_if([](AsyncEventSourceClient *c){ + return c->connected(); + }); +} + +bool AsyncEventSource::canHandle(AsyncWebServerRequest *request){ + if(request->method() != HTTP_GET || !request->url().equals(_url)) { + return false; + } + request->addInterestingHeader("Last-Event-ID"); + return true; +} + +void AsyncEventSource::handleRequest(AsyncWebServerRequest *request){ + if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str())) + return request->requestAuthentication(); + request->send(new AsyncEventSourceResponse(this)); +} + +// Response + +AsyncEventSourceResponse::AsyncEventSourceResponse(AsyncEventSource *server){ + _server = server; + _code = 200; + _contentType = "text/event-stream"; + _sendContentLength = false; + addHeader("Cache-Control", "no-cache"); + addHeader("Connection","keep-alive"); +} + +void AsyncEventSourceResponse::_respond(AsyncWebServerRequest *request){ + String out = _assembleHead(request->version()); + request->client()->write(out.c_str(), _headLength); + _state = RESPONSE_WAIT_ACK; +} + +size_t AsyncEventSourceResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time __attribute__((unused))){ + if(len){ + new AsyncEventSourceClient(request, _server); + } + return 0; +} + diff --git a/lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.h b/lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.h new file mode 100644 index 000000000..6ff43a6e7 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.h @@ -0,0 +1,133 @@ +/* + Asynchronous WebServer library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef ASYNCEVENTSOURCE_H_ +#define ASYNCEVENTSOURCE_H_ + +#include +#ifdef ESP32 +#include +#define SSE_MAX_QUEUED_MESSAGES 32 +#else +#include +#define SSE_MAX_QUEUED_MESSAGES 8 +#endif +#include + +#include "AsyncWebSynchronization.h" + +#ifdef ESP8266 +#include +#ifdef CRYPTO_HASH_h // include Hash.h from espressif framework if the first include was from the crypto library +#include <../src/Hash.h> +#endif +#endif + +#ifdef ESP32 +#define DEFAULT_MAX_SSE_CLIENTS 8 +#else +#define DEFAULT_MAX_SSE_CLIENTS 4 +#endif + +class AsyncEventSource; +class AsyncEventSourceResponse; +class AsyncEventSourceClient; +typedef std::function ArEventHandlerFunction; + +class AsyncEventSourceMessage { + private: + uint8_t * _data; + size_t _len; + size_t _sent; + //size_t _ack; + size_t _acked; + public: + AsyncEventSourceMessage(const char * data, size_t len); + ~AsyncEventSourceMessage(); + size_t ack(size_t len, uint32_t time __attribute__((unused))); + size_t send(AsyncClient *client); + bool finished(){ return _acked == _len; } + bool sent() { return _sent == _len; } +}; + +class AsyncEventSourceClient { + private: + AsyncClient *_client; + AsyncEventSource *_server; + uint32_t _lastId; + AsyncLinkedList _messageQueue; + void _queueMessage(AsyncEventSourceMessage *dataMessage); + void _runQueue(); + + public: + + AsyncEventSourceClient(AsyncWebServerRequest *request, AsyncEventSource *server); + ~AsyncEventSourceClient(); + + AsyncClient* client(){ return _client; } + void close(); + void write(const char * message, size_t len); + void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); + bool connected() const { return (_client != NULL) && _client->connected(); } + uint32_t lastId() const { return _lastId; } + size_t packetsWaiting() const { return _messageQueue.length(); } + + //system callbacks (do not call) + void _onAck(size_t len, uint32_t time); + void _onPoll(); + void _onTimeout(uint32_t time); + void _onDisconnect(); +}; + +class AsyncEventSource: public AsyncWebHandler { + private: + String _url; + AsyncLinkedList _clients; + ArEventHandlerFunction _connectcb; + public: + AsyncEventSource(const String& url); + ~AsyncEventSource(); + + const char * url() const { return _url.c_str(); } + void close(); + void onConnect(ArEventHandlerFunction cb); + void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); + size_t count() const; //number clinets connected + size_t avgPacketsWaiting() const; + + //system callbacks (do not call) + void _addClient(AsyncEventSourceClient * client); + void _handleDisconnect(AsyncEventSourceClient * client); + virtual bool canHandle(AsyncWebServerRequest *request) override final; + virtual void handleRequest(AsyncWebServerRequest *request) override final; +}; + +class AsyncEventSourceResponse: public AsyncWebServerResponse { + private: + String _content; + AsyncEventSource *_server; + public: + AsyncEventSourceResponse(AsyncEventSource *server); + void _respond(AsyncWebServerRequest *request); + size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); + bool _sourceValid() const { return true; } +}; + + +#endif /* ASYNCEVENTSOURCE_H_ */ diff --git a/lib/libesp32/ESPAsyncWebServer/src/AsyncJson.h b/lib/libesp32/ESPAsyncWebServer/src/AsyncJson.h new file mode 100644 index 000000000..2fa6a2d26 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/AsyncJson.h @@ -0,0 +1,254 @@ +// AsyncJson.h +/* + Async Response to use with ArduinoJson and AsyncWebServer + Written by Andrew Melvin (SticilFace) with help from me-no-dev and BBlanchon. + + Example of callback in use + + server.on("/json", HTTP_ANY, [](AsyncWebServerRequest * request) { + + AsyncJsonResponse * response = new AsyncJsonResponse(); + JsonObject& root = response->getRoot(); + root["key1"] = "key number one"; + JsonObject& nested = root.createNestedObject("nested"); + nested["key1"] = "key number one"; + + response->setLength(); + request->send(response); + }); + + -------------------- + + Async Request to use with ArduinoJson and AsyncWebServer + Written by Arsène von Wyss (avonwyss) + + Example + + AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/rest/endpoint"); + handler->onRequest([](AsyncWebServerRequest *request, JsonVariant &json) { + JsonObject& jsonObj = json.as(); + // ... + }); + server.addHandler(handler); + +*/ +#ifndef ASYNC_JSON_H_ +#define ASYNC_JSON_H_ +#include +#include +#include + +#if ARDUINOJSON_VERSION_MAJOR == 5 + #define ARDUINOJSON_5_COMPATIBILITY +#else + #ifndef DYNAMIC_JSON_DOCUMENT_SIZE + #define DYNAMIC_JSON_DOCUMENT_SIZE 1024 + #endif +#endif + +constexpr const char* JSON_MIMETYPE = "application/json"; + +/* + * Json Response + * */ + +class ChunkPrint : public Print { + private: + uint8_t* _destination; + size_t _to_skip; + size_t _to_write; + size_t _pos; + public: + ChunkPrint(uint8_t* destination, size_t from, size_t len) + : _destination(destination), _to_skip(from), _to_write(len), _pos{0} {} + virtual ~ChunkPrint(){} + size_t write(uint8_t c){ + if (_to_skip > 0) { + _to_skip--; + return 1; + } else if (_to_write > 0) { + _to_write--; + _destination[_pos++] = c; + return 1; + } + return 0; + } + size_t write(const uint8_t *buffer, size_t size) + { + return this->Print::write(buffer, size); + } +}; + +class AsyncJsonResponse: public AsyncAbstractResponse { + protected: + +#ifdef ARDUINOJSON_5_COMPATIBILITY + DynamicJsonBuffer _jsonBuffer; +#else + DynamicJsonDocument _jsonBuffer; +#endif + + JsonVariant _root; + bool _isValid; + + public: + +#ifdef ARDUINOJSON_5_COMPATIBILITY + AsyncJsonResponse(bool isArray=false): _isValid{false} { + _code = 200; + _contentType = JSON_MIMETYPE; + if(isArray) + _root = _jsonBuffer.createArray(); + else + _root = _jsonBuffer.createObject(); + } +#else + AsyncJsonResponse(bool isArray=false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) : _jsonBuffer(maxJsonBufferSize), _isValid{false} { + _code = 200; + _contentType = JSON_MIMETYPE; + if(isArray) + _root = _jsonBuffer.createNestedArray(); + else + _root = _jsonBuffer.createNestedObject(); + } +#endif + + ~AsyncJsonResponse() {} + JsonVariant & getRoot() { return _root; } + bool _sourceValid() const { return _isValid; } + size_t setLength() { + +#ifdef ARDUINOJSON_5_COMPATIBILITY + _contentLength = _root.measureLength(); +#else + _contentLength = measureJson(_root); +#endif + + if (_contentLength) { _isValid = true; } + return _contentLength; + } + + size_t getSize() { return _jsonBuffer.size(); } + + size_t _fillBuffer(uint8_t *data, size_t len){ + ChunkPrint dest(data, _sentLength, len); + +#ifdef ARDUINOJSON_5_COMPATIBILITY + _root.printTo( dest ) ; +#else + serializeJson(_root, dest); +#endif + return len; + } +}; + +class PrettyAsyncJsonResponse: public AsyncJsonResponse { +public: +#ifdef ARDUINOJSON_5_COMPATIBILITY + PrettyAsyncJsonResponse (bool isArray=false) : AsyncJsonResponse{isArray} {} +#else + PrettyAsyncJsonResponse (bool isArray=false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) : AsyncJsonResponse{isArray, maxJsonBufferSize} {} +#endif + size_t setLength () { +#ifdef ARDUINOJSON_5_COMPATIBILITY + _contentLength = _root.measurePrettyLength (); +#else + _contentLength = measureJsonPretty(_root); +#endif + if (_contentLength) {_isValid = true;} + return _contentLength; + } + size_t _fillBuffer (uint8_t *data, size_t len) { + ChunkPrint dest (data, _sentLength, len); +#ifdef ARDUINOJSON_5_COMPATIBILITY + _root.prettyPrintTo (dest); +#else + serializeJsonPretty(_root, dest); +#endif + return len; + } +}; + +typedef std::function ArJsonRequestHandlerFunction; + +class AsyncCallbackJsonWebHandler: public AsyncWebHandler { +private: +protected: + const String _uri; + WebRequestMethodComposite _method; + ArJsonRequestHandlerFunction _onRequest; + size_t _contentLength; +#ifndef ARDUINOJSON_5_COMPATIBILITY + const size_t maxJsonBufferSize; +#endif + size_t _maxContentLength; +public: +#ifdef ARDUINOJSON_5_COMPATIBILITY + AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest) + : _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), _maxContentLength(16384) {} +#else + AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize=DYNAMIC_JSON_DOCUMENT_SIZE) + : _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), maxJsonBufferSize(maxJsonBufferSize), _maxContentLength(16384) {} +#endif + + void setMethod(WebRequestMethodComposite method){ _method = method; } + void setMaxContentLength(int maxContentLength){ _maxContentLength = maxContentLength; } + void onRequest(ArJsonRequestHandlerFunction fn){ _onRequest = fn; } + + virtual bool canHandle(AsyncWebServerRequest *request) override final{ + if(!_onRequest) + return false; + + if(!(_method & request->method())) + return false; + + if(_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri+"/"))) + return false; + + if ( !request->contentType().equalsIgnoreCase(JSON_MIMETYPE) ) + return false; + + request->addInterestingHeader("ANY"); + return true; + } + + virtual void handleRequest(AsyncWebServerRequest *request) override final { + if(_onRequest) { + if (request->_tempObject != NULL) { + +#ifdef ARDUINOJSON_5_COMPATIBILITY + DynamicJsonBuffer jsonBuffer; + JsonVariant json = jsonBuffer.parse((uint8_t*)(request->_tempObject)); + if (json.success()) { +#else + DynamicJsonDocument jsonBuffer(this->maxJsonBufferSize); + DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject)); + if(!error) { + JsonVariant json = jsonBuffer.as(); +#endif + + _onRequest(request, json); + return; + } + } + request->send(_contentLength > _maxContentLength ? 413 : 400); + } else { + request->send(500); + } + } + virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final { + } + virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final { + if (_onRequest) { + _contentLength = total; + if (total > 0 && request->_tempObject == NULL && total < _maxContentLength) { + request->_tempObject = malloc(total); + } + if (request->_tempObject != NULL) { + memcpy((uint8_t*)(request->_tempObject) + index, data, len); + } + } + } + virtual bool isRequestHandlerTrivial() override final {return _onRequest ? false : true;} +}; +#endif diff --git a/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.cpp b/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.cpp new file mode 100644 index 000000000..df0d668a9 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.cpp @@ -0,0 +1,1294 @@ +/* + Asynchronous WebServer library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "Arduino.h" +#include "AsyncWebSocket.h" + +#include + +#ifndef ESP8266 +#include "mbedtls/sha1.h" +#else +#include +#endif + +#define MAX_PRINTF_LEN 64 + +size_t webSocketSendFrameWindow(AsyncClient *client){ + if(!client->canSend()) + return 0; + size_t space = client->space(); + if(space < 9) + return 0; + return space - 8; +} + +size_t webSocketSendFrame(AsyncClient *client, bool final, uint8_t opcode, bool mask, uint8_t *data, size_t len){ + if(!client->canSend()) + return 0; + size_t space = client->space(); + if(space < 2) + return 0; + uint8_t mbuf[4] = {0,0,0,0}; + uint8_t headLen = 2; + if(len && mask){ + headLen += 4; + mbuf[0] = rand() % 0xFF; + mbuf[1] = rand() % 0xFF; + mbuf[2] = rand() % 0xFF; + mbuf[3] = rand() % 0xFF; + } + if(len > 125) + headLen += 2; + if(space < headLen) + return 0; + space -= headLen; + + if(len > space) len = space; + + uint8_t *buf = (uint8_t*)malloc(headLen); + if(buf == NULL){ + //os_printf("could not malloc %u bytes for frame header\n", headLen); + return 0; + } + + buf[0] = opcode & 0x0F; + if(final) + buf[0] |= 0x80; + if(len < 126) + buf[1] = len & 0x7F; + else { + buf[1] = 126; + buf[2] = (uint8_t)((len >> 8) & 0xFF); + buf[3] = (uint8_t)(len & 0xFF); + } + if(len && mask){ + buf[1] |= 0x80; + memcpy(buf + (headLen - 4), mbuf, 4); + } + if(client->add((const char *)buf, headLen) != headLen){ + //os_printf("error adding %lu header bytes\n", headLen); + free(buf); + return 0; + } + free(buf); + + if(len){ + if(len && mask){ + size_t i; + for(i=0;iadd((const char *)data, len) != len){ + //os_printf("error adding %lu data bytes\n", len); + return 0; + } + } + if(!client->send()){ + //os_printf("error sending frame: %lu\n", headLen+len); + return 0; + } + return len; +} + + +/* + * AsyncWebSocketMessageBuffer + */ + + + +AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer() + :_data(nullptr) + ,_len(0) + ,_lock(false) + ,_count(0) +{ + +} + +AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(uint8_t * data, size_t size) + :_data(nullptr) + ,_len(size) + ,_lock(false) + ,_count(0) +{ + + if (!data) { + return; + } + + _data = new uint8_t[_len + 1]; + + if (_data) { + memcpy(_data, data, _len); + _data[_len] = 0; + } +} + + +AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(size_t size) + :_data(nullptr) + ,_len(size) + ,_lock(false) + ,_count(0) +{ + _data = new uint8_t[_len + 1]; + + if (_data) { + _data[_len] = 0; + } + +} + +AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(const AsyncWebSocketMessageBuffer & copy) + :_data(nullptr) + ,_len(0) + ,_lock(false) + ,_count(0) +{ + _len = copy._len; + _lock = copy._lock; + _count = 0; + + if (_len) { + _data = new uint8_t[_len + 1]; + _data[_len] = 0; + } + + if (_data) { + memcpy(_data, copy._data, _len); + _data[_len] = 0; + } + +} + +AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(AsyncWebSocketMessageBuffer && copy) + :_data(nullptr) + ,_len(0) + ,_lock(false) + ,_count(0) +{ + _len = copy._len; + _lock = copy._lock; + _count = 0; + + if (copy._data) { + _data = copy._data; + copy._data = nullptr; + } + +} + +AsyncWebSocketMessageBuffer::~AsyncWebSocketMessageBuffer() +{ + if (_data) { + delete[] _data; + } +} + +bool AsyncWebSocketMessageBuffer::reserve(size_t size) +{ + _len = size; + + if (_data) { + delete[] _data; + _data = nullptr; + } + + _data = new uint8_t[_len + 1]; + + if (_data) { + _data[_len] = 0; + return true; + } else { + return false; + } + +} + + + +/* + * Control Frame + */ + +class AsyncWebSocketControl { + private: + uint8_t _opcode; + uint8_t *_data; + size_t _len; + bool _mask; + bool _finished; + public: + AsyncWebSocketControl(uint8_t opcode, uint8_t *data=NULL, size_t len=0, bool mask=false) + :_opcode(opcode) + ,_len(len) + ,_mask(len && mask) + ,_finished(false) + { + if(data == NULL) + _len = 0; + if(_len){ + if(_len > 125) + _len = 125; + _data = (uint8_t*)malloc(_len); + if(_data == NULL) + _len = 0; + else memcpy(_data, data, len); + } else _data = NULL; + } + virtual ~AsyncWebSocketControl(){ + if(_data != NULL) + free(_data); + } + virtual bool finished() const { return _finished; } + uint8_t opcode(){ return _opcode; } + uint8_t len(){ return _len + 2; } + size_t send(AsyncClient *client){ + _finished = true; + return webSocketSendFrame(client, true, _opcode & 0x0F, _mask, _data, _len); + } +}; + +/* + * Basic Buffered Message + */ + + +AsyncWebSocketBasicMessage::AsyncWebSocketBasicMessage(const char * data, size_t len, uint8_t opcode, bool mask) + :_len(len) + ,_sent(0) + ,_ack(0) + ,_acked(0) +{ + _opcode = opcode & 0x07; + _mask = mask; + _data = (uint8_t*)malloc(_len+1); + if(_data == NULL){ + _len = 0; + _status = WS_MSG_ERROR; + } else { + _status = WS_MSG_SENDING; + memcpy(_data, data, _len); + _data[_len] = 0; + } +} +AsyncWebSocketBasicMessage::AsyncWebSocketBasicMessage(uint8_t opcode, bool mask) + :_len(0) + ,_sent(0) + ,_ack(0) + ,_acked(0) + ,_data(NULL) +{ + _opcode = opcode & 0x07; + _mask = mask; + +} + + +AsyncWebSocketBasicMessage::~AsyncWebSocketBasicMessage() { + if(_data != NULL) + free(_data); +} + + void AsyncWebSocketBasicMessage::ack(size_t len, uint32_t time) { + (void)time; + _acked += len; + if(_sent == _len && _acked == _ack){ + _status = WS_MSG_SENT; + } +} + size_t AsyncWebSocketBasicMessage::send(AsyncClient *client) { + if(_status != WS_MSG_SENDING) + return 0; + if(_acked < _ack){ + return 0; + } + if(_sent == _len){ + if(_acked == _ack) + _status = WS_MSG_SENT; + return 0; + } + if(_sent > _len){ + _status = WS_MSG_ERROR; + return 0; + } + + size_t toSend = _len - _sent; + size_t window = webSocketSendFrameWindow(client); + + if(window < toSend) { + toSend = window; + } + + _sent += toSend; + _ack += toSend + ((toSend < 126)?2:4) + (_mask * 4); + + bool final = (_sent == _len); + uint8_t* dPtr = (uint8_t*)(_data + (_sent - toSend)); + uint8_t opCode = (toSend && _sent == toSend)?_opcode:(uint8_t)WS_CONTINUATION; + + size_t sent = webSocketSendFrame(client, final, opCode, _mask, dPtr, toSend); + _status = WS_MSG_SENDING; + if(toSend && sent != toSend){ + _sent -= (toSend - sent); + _ack -= (toSend - sent); + } + return sent; +} + +// bool AsyncWebSocketBasicMessage::reserve(size_t size) { +// if (size) { +// _data = (uint8_t*)malloc(size +1); +// if (_data) { +// memset(_data, 0, size); +// _len = size; +// _status = WS_MSG_SENDING; +// return true; +// } +// } +// return false; +// } + + +/* + * AsyncWebSocketMultiMessage Message + */ + + +AsyncWebSocketMultiMessage::AsyncWebSocketMultiMessage(AsyncWebSocketMessageBuffer * buffer, uint8_t opcode, bool mask) + :_len(0) + ,_sent(0) + ,_ack(0) + ,_acked(0) + ,_WSbuffer(nullptr) +{ + + _opcode = opcode & 0x07; + _mask = mask; + + if (buffer) { + _WSbuffer = buffer; + (*_WSbuffer)++; + _data = buffer->get(); + _len = buffer->length(); + _status = WS_MSG_SENDING; + //ets_printf("M: %u\n", _len); + } else { + _status = WS_MSG_ERROR; + } + +} + + +AsyncWebSocketMultiMessage::~AsyncWebSocketMultiMessage() { + if (_WSbuffer) { + (*_WSbuffer)--; // decreases the counter. + } +} + + void AsyncWebSocketMultiMessage::ack(size_t len, uint32_t time) { + (void)time; + _acked += len; + if(_sent >= _len && _acked >= _ack){ + _status = WS_MSG_SENT; + } + //ets_printf("A: %u\n", len); +} + size_t AsyncWebSocketMultiMessage::send(AsyncClient *client) { + if(_status != WS_MSG_SENDING) + return 0; + if(_acked < _ack){ + return 0; + } + if(_sent == _len){ + _status = WS_MSG_SENT; + return 0; + } + if(_sent > _len){ + _status = WS_MSG_ERROR; + //ets_printf("E: %u > %u\n", _sent, _len); + return 0; + } + + size_t toSend = _len - _sent; + size_t window = webSocketSendFrameWindow(client); + + if(window < toSend) { + toSend = window; + } + + _sent += toSend; + _ack += toSend + ((toSend < 126)?2:4) + (_mask * 4); + + //ets_printf("W: %u %u\n", _sent - toSend, toSend); + + bool final = (_sent == _len); + uint8_t* dPtr = (uint8_t*)(_data + (_sent - toSend)); + uint8_t opCode = (toSend && _sent == toSend)?_opcode:(uint8_t)WS_CONTINUATION; + + size_t sent = webSocketSendFrame(client, final, opCode, _mask, dPtr, toSend); + _status = WS_MSG_SENDING; + if(toSend && sent != toSend){ + //ets_printf("E: %u != %u\n", toSend, sent); + _sent -= (toSend - sent); + _ack -= (toSend - sent); + } + //ets_printf("S: %u %u\n", _sent, sent); + return sent; +} + + +/* + * Async WebSocket Client + */ + const char * AWSC_PING_PAYLOAD = "ESPAsyncWebServer-PING"; + const size_t AWSC_PING_PAYLOAD_LEN = 22; + +AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server) + : _controlQueue(AsyncLinkedList([](AsyncWebSocketControl *c){ delete c; })) + , _messageQueue(AsyncLinkedList([](AsyncWebSocketMessage *m){ delete m; })) + , _tempObject(NULL) +{ + _client = request->client(); + _server = server; + _clientId = _server->_getNextId(); + _status = WS_CONNECTED; + _pstate = 0; + _lastMessageTime = millis(); + _keepAlivePeriod = 0; + _client->setRxTimeout(0); + _client->onError([](void *r, AsyncClient* c, int8_t error){ (void)c; ((AsyncWebSocketClient*)(r))->_onError(error); }, this); + _client->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ (void)c; ((AsyncWebSocketClient*)(r))->_onAck(len, time); }, this); + _client->onDisconnect([](void *r, AsyncClient* c){ ((AsyncWebSocketClient*)(r))->_onDisconnect(); delete c; }, this); + _client->onTimeout([](void *r, AsyncClient* c, uint32_t time){ (void)c; ((AsyncWebSocketClient*)(r))->_onTimeout(time); }, this); + _client->onData([](void *r, AsyncClient* c, void *buf, size_t len){ (void)c; ((AsyncWebSocketClient*)(r))->_onData(buf, len); }, this); + _client->onPoll([](void *r, AsyncClient* c){ (void)c; ((AsyncWebSocketClient*)(r))->_onPoll(); }, this); + _server->_addClient(this); + _server->_handleEvent(this, WS_EVT_CONNECT, request, NULL, 0); + delete request; +} + +AsyncWebSocketClient::~AsyncWebSocketClient(){ + _messageQueue.free(); + _controlQueue.free(); + _server->_handleEvent(this, WS_EVT_DISCONNECT, NULL, NULL, 0); +} + +void AsyncWebSocketClient::_onAck(size_t len, uint32_t time){ + _lastMessageTime = millis(); + if(!_controlQueue.isEmpty()){ + auto head = _controlQueue.front(); + if(head->finished()){ + len -= head->len(); + if(_status == WS_DISCONNECTING && head->opcode() == WS_DISCONNECT){ + _controlQueue.remove(head); + _status = WS_DISCONNECTED; + _client->close(true); + return; + } + _controlQueue.remove(head); + } + } + if(len && !_messageQueue.isEmpty()){ + _messageQueue.front()->ack(len, time); + } + _server->_cleanBuffers(); + _runQueue(); +} + +void AsyncWebSocketClient::_onPoll(){ + if(_client->canSend() && (!_controlQueue.isEmpty() || !_messageQueue.isEmpty())){ + _runQueue(); + } else if(_keepAlivePeriod > 0 && _controlQueue.isEmpty() && _messageQueue.isEmpty() && (millis() - _lastMessageTime) >= _keepAlivePeriod){ + ping((uint8_t *)AWSC_PING_PAYLOAD, AWSC_PING_PAYLOAD_LEN); + } +} + +void AsyncWebSocketClient::_runQueue(){ + while(!_messageQueue.isEmpty() && _messageQueue.front()->finished()){ + _messageQueue.remove(_messageQueue.front()); + } + + if(!_controlQueue.isEmpty() && (_messageQueue.isEmpty() || _messageQueue.front()->betweenFrames()) && webSocketSendFrameWindow(_client) > (size_t)(_controlQueue.front()->len() - 1)){ + _controlQueue.front()->send(_client); + } else if(!_messageQueue.isEmpty() && _messageQueue.front()->betweenFrames() && webSocketSendFrameWindow(_client)){ + _messageQueue.front()->send(_client); + } +} + +bool AsyncWebSocketClient::queueIsFull(){ + if((_messageQueue.length() >= WS_MAX_QUEUED_MESSAGES) || (_status != WS_CONNECTED) ) return true; + return false; +} + +void AsyncWebSocketClient::_queueMessage(AsyncWebSocketMessage *dataMessage){ + if(dataMessage == NULL) + return; + if(_status != WS_CONNECTED){ + delete dataMessage; + return; + } + if(_messageQueue.length() >= WS_MAX_QUEUED_MESSAGES){ + ets_printf("ERROR: Too many messages queued\n"); + delete dataMessage; + } else { + _messageQueue.add(dataMessage); + } + if(_client->canSend()) + _runQueue(); +} + +void AsyncWebSocketClient::_queueControl(AsyncWebSocketControl *controlMessage){ + if(controlMessage == NULL) + return; + _controlQueue.add(controlMessage); + if(_client->canSend()) + _runQueue(); +} + +void AsyncWebSocketClient::close(uint16_t code, const char * message){ + if(_status != WS_CONNECTED) + return; + if(code){ + uint8_t packetLen = 2; + if(message != NULL){ + size_t mlen = strlen(message); + if(mlen > 123) mlen = 123; + packetLen += mlen; + } + char * buf = (char*)malloc(packetLen); + if(buf != NULL){ + buf[0] = (uint8_t)(code >> 8); + buf[1] = (uint8_t)(code & 0xFF); + if(message != NULL){ + memcpy(buf+2, message, packetLen -2); + } + _queueControl(new AsyncWebSocketControl(WS_DISCONNECT,(uint8_t*)buf,packetLen)); + free(buf); + return; + } + } + _queueControl(new AsyncWebSocketControl(WS_DISCONNECT)); +} + +void AsyncWebSocketClient::ping(uint8_t *data, size_t len){ + if(_status == WS_CONNECTED) + _queueControl(new AsyncWebSocketControl(WS_PING, data, len)); +} + +void AsyncWebSocketClient::_onError(int8_t){} + +void AsyncWebSocketClient::_onTimeout(uint32_t time){ + (void)time; + _client->close(true); +} + +void AsyncWebSocketClient::_onDisconnect(){ + _client = NULL; + _server->_handleDisconnect(this); +} + +void AsyncWebSocketClient::_onData(void *pbuf, size_t plen){ + _lastMessageTime = millis(); + uint8_t *data = (uint8_t*)pbuf; + while(plen > 0){ + if(!_pstate){ + const uint8_t *fdata = data; + _pinfo.index = 0; + _pinfo.final = (fdata[0] & 0x80) != 0; + _pinfo.opcode = fdata[0] & 0x0F; + _pinfo.masked = (fdata[1] & 0x80) != 0; + _pinfo.len = fdata[1] & 0x7F; + data += 2; + plen -= 2; + if(_pinfo.len == 126){ + _pinfo.len = fdata[3] | (uint16_t)(fdata[2]) << 8; + data += 2; + plen -= 2; + } else if(_pinfo.len == 127){ + _pinfo.len = fdata[9] | (uint16_t)(fdata[8]) << 8 | (uint32_t)(fdata[7]) << 16 | (uint32_t)(fdata[6]) << 24 | (uint64_t)(fdata[5]) << 32 | (uint64_t)(fdata[4]) << 40 | (uint64_t)(fdata[3]) << 48 | (uint64_t)(fdata[2]) << 56; + data += 8; + plen -= 8; + } + + if(_pinfo.masked){ + memcpy(_pinfo.mask, data, 4); + data += 4; + plen -= 4; + } + } + + const size_t datalen = std::min((size_t)(_pinfo.len - _pinfo.index), plen); + const auto datalast = data[datalen]; + + if(_pinfo.masked){ + for(size_t i=0;i_handleEvent(this, WS_EVT_DATA, (void *)&_pinfo, (uint8_t*)data, datalen); + + _pinfo.index += datalen; + } else if((datalen + _pinfo.index) == _pinfo.len){ + _pstate = 0; + if(_pinfo.opcode == WS_DISCONNECT){ + if(datalen){ + uint16_t reasonCode = (uint16_t)(data[0] << 8) + data[1]; + char * reasonString = (char*)(data+2); + if(reasonCode > 1001){ + _server->_handleEvent(this, WS_EVT_ERROR, (void *)&reasonCode, (uint8_t*)reasonString, strlen(reasonString)); + } + } + if(_status == WS_DISCONNECTING){ + _status = WS_DISCONNECTED; + _client->close(true); + } else { + _status = WS_DISCONNECTING; + _client->ackLater(); + _queueControl(new AsyncWebSocketControl(WS_DISCONNECT, data, datalen)); + } + } else if(_pinfo.opcode == WS_PING){ + _queueControl(new AsyncWebSocketControl(WS_PONG, data, datalen)); + } else if(_pinfo.opcode == WS_PONG){ + if(datalen != AWSC_PING_PAYLOAD_LEN || memcmp(AWSC_PING_PAYLOAD, data, AWSC_PING_PAYLOAD_LEN) != 0) + _server->_handleEvent(this, WS_EVT_PONG, NULL, data, datalen); + } else if(_pinfo.opcode < 8){//continuation or text/binary frame + _server->_handleEvent(this, WS_EVT_DATA, (void *)&_pinfo, data, datalen); + } + } else { + //os_printf("frame error: len: %u, index: %llu, total: %llu\n", datalen, _pinfo.index, _pinfo.len); + //what should we do? + break; + } + + // restore byte as _handleEvent may have added a null terminator i.e., data[len] = 0; + if (datalen > 0) + data[datalen] = datalast; + + data += datalen; + plen -= datalen; + } +} + +size_t AsyncWebSocketClient::printf(const char *format, ...) { + va_list arg; + va_start(arg, format); + char* temp = new char[MAX_PRINTF_LEN]; + if(!temp){ + va_end(arg); + return 0; + } + char* buffer = temp; + size_t len = vsnprintf(temp, MAX_PRINTF_LEN, format, arg); + va_end(arg); + + if (len > (MAX_PRINTF_LEN - 1)) { + buffer = new char[len + 1]; + if (!buffer) { + delete[] temp; + return 0; + } + va_start(arg, format); + vsnprintf(buffer, len + 1, format, arg); + va_end(arg); + } + text(buffer, len); + if (buffer != temp) { + delete[] buffer; + } + delete[] temp; + return len; +} + +#ifndef ESP32 +size_t AsyncWebSocketClient::printf_P(PGM_P formatP, ...) { + va_list arg; + va_start(arg, formatP); + char* temp = new char[MAX_PRINTF_LEN]; + if(!temp){ + va_end(arg); + return 0; + } + char* buffer = temp; + size_t len = vsnprintf_P(temp, MAX_PRINTF_LEN, formatP, arg); + va_end(arg); + + if (len > (MAX_PRINTF_LEN - 1)) { + buffer = new char[len + 1]; + if (!buffer) { + delete[] temp; + return 0; + } + va_start(arg, formatP); + vsnprintf_P(buffer, len + 1, formatP, arg); + va_end(arg); + } + text(buffer, len); + if (buffer != temp) { + delete[] buffer; + } + delete[] temp; + return len; +} +#endif + +void AsyncWebSocketClient::text(const char * message, size_t len){ + _queueMessage(new AsyncWebSocketBasicMessage(message, len)); +} +void AsyncWebSocketClient::text(const char * message){ + text(message, strlen(message)); +} +void AsyncWebSocketClient::text(uint8_t * message, size_t len){ + text((const char *)message, len); +} +void AsyncWebSocketClient::text(char * message){ + text(message, strlen(message)); +} +void AsyncWebSocketClient::text(const String &message){ + text(message.c_str(), message.length()); +} +void AsyncWebSocketClient::text(const __FlashStringHelper *data){ + PGM_P p = reinterpret_cast(data); + size_t n = 0; + while (1) { + if (pgm_read_byte(p+n) == 0) break; + n += 1; + } + char * message = (char*) malloc(n+1); + if(message){ + for(size_t b=0; b(data); + char * message = (char*) malloc(len); + if(message){ + for(size_t b=0; bremoteIP(); +} + +uint16_t AsyncWebSocketClient::remotePort() { + if(!_client) { + return 0; + } + return _client->remotePort(); +} + + + +/* + * Async Web Socket - Each separate socket location + */ + +AsyncWebSocket::AsyncWebSocket(const String& url) + :_url(url) + ,_clients(AsyncLinkedList([](AsyncWebSocketClient *c){ delete c; })) + ,_cNextId(1) + ,_enabled(true) + ,_buffers(AsyncLinkedList([](AsyncWebSocketMessageBuffer *b){ delete b; })) +{ + _eventHandler = NULL; +} + +AsyncWebSocket::~AsyncWebSocket(){} + +void AsyncWebSocket::_handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){ + if(_eventHandler != NULL){ + _eventHandler(this, client, type, arg, data, len); + } +} + +void AsyncWebSocket::_addClient(AsyncWebSocketClient * client){ + _clients.add(client); +} + +void AsyncWebSocket::_handleDisconnect(AsyncWebSocketClient * client){ + + _clients.remove_first([=](AsyncWebSocketClient * c){ + return c->id() == client->id(); + }); +} + +bool AsyncWebSocket::availableForWriteAll(){ + for(const auto& c: _clients){ + if(c->queueIsFull()) return false; + } + return true; +} + +bool AsyncWebSocket::availableForWrite(uint32_t id){ + for(const auto& c: _clients){ + if(c->queueIsFull() && (c->id() == id )) return false; + } + return true; +} + +size_t AsyncWebSocket::count() const { + return _clients.count_if([](AsyncWebSocketClient * c){ + return c->status() == WS_CONNECTED; + }); +} + +AsyncWebSocketClient * AsyncWebSocket::client(uint32_t id){ + for(const auto &c: _clients){ + if(c->id() == id && c->status() == WS_CONNECTED){ + return c; + } + } + return nullptr; +} + + +void AsyncWebSocket::close(uint32_t id, uint16_t code, const char * message){ + AsyncWebSocketClient * c = client(id); + if(c) + c->close(code, message); +} + +void AsyncWebSocket::closeAll(uint16_t code, const char * message){ + for(const auto& c: _clients){ + if(c->status() == WS_CONNECTED) + c->close(code, message); + } +} + +void AsyncWebSocket::cleanupClients(uint16_t maxClients) +{ + if (count() > maxClients){ + _clients.front()->close(); + } +} + +void AsyncWebSocket::ping(uint32_t id, uint8_t *data, size_t len){ + AsyncWebSocketClient * c = client(id); + if(c) + c->ping(data, len); +} + +void AsyncWebSocket::pingAll(uint8_t *data, size_t len){ + for(const auto& c: _clients){ + if(c->status() == WS_CONNECTED) + c->ping(data, len); + } +} + +void AsyncWebSocket::text(uint32_t id, const char * message, size_t len){ + AsyncWebSocketClient * c = client(id); + if(c) + c->text(message, len); +} + +void AsyncWebSocket::textAll(AsyncWebSocketMessageBuffer * buffer){ + if (!buffer) return; + buffer->lock(); + for(const auto& c: _clients){ + if(c->status() == WS_CONNECTED){ + c->text(buffer); + } + } + buffer->unlock(); + _cleanBuffers(); +} + + +void AsyncWebSocket::textAll(const char * message, size_t len){ + AsyncWebSocketMessageBuffer * WSBuffer = makeBuffer((uint8_t *)message, len); + textAll(WSBuffer); +} + +void AsyncWebSocket::binary(uint32_t id, const char * message, size_t len){ + AsyncWebSocketClient * c = client(id); + if(c) + c->binary(message, len); +} + +void AsyncWebSocket::binaryAll(const char * message, size_t len){ + AsyncWebSocketMessageBuffer * buffer = makeBuffer((uint8_t *)message, len); + binaryAll(buffer); +} + +void AsyncWebSocket::binaryAll(AsyncWebSocketMessageBuffer * buffer) +{ + if (!buffer) return; + buffer->lock(); + for(const auto& c: _clients){ + if(c->status() == WS_CONNECTED) + c->binary(buffer); + } + buffer->unlock(); + _cleanBuffers(); +} + +void AsyncWebSocket::message(uint32_t id, AsyncWebSocketMessage *message){ + AsyncWebSocketClient * c = client(id); + if(c) + c->message(message); +} + +void AsyncWebSocket::messageAll(AsyncWebSocketMultiMessage *message){ + for(const auto& c: _clients){ + if(c->status() == WS_CONNECTED) + c->message(message); + } + _cleanBuffers(); +} + +size_t AsyncWebSocket::printf(uint32_t id, const char *format, ...){ + AsyncWebSocketClient * c = client(id); + if(c){ + va_list arg; + va_start(arg, format); + size_t len = c->printf(format, arg); + va_end(arg); + return len; + } + return 0; +} + +size_t AsyncWebSocket::printfAll(const char *format, ...) { + va_list arg; + char* temp = new char[MAX_PRINTF_LEN]; + if(!temp){ + return 0; + } + va_start(arg, format); + size_t len = vsnprintf(temp, MAX_PRINTF_LEN, format, arg); + va_end(arg); + delete[] temp; + + AsyncWebSocketMessageBuffer * buffer = makeBuffer(len); + if (!buffer) { + return 0; + } + + va_start(arg, format); + vsnprintf( (char *)buffer->get(), len + 1, format, arg); + va_end(arg); + + textAll(buffer); + return len; +} + +#ifndef ESP32 +size_t AsyncWebSocket::printf_P(uint32_t id, PGM_P formatP, ...){ + AsyncWebSocketClient * c = client(id); + if(c != NULL){ + va_list arg; + va_start(arg, formatP); + size_t len = c->printf_P(formatP, arg); + va_end(arg); + return len; + } + return 0; +} +#endif + +size_t AsyncWebSocket::printfAll_P(PGM_P formatP, ...) { + va_list arg; + char* temp = new char[MAX_PRINTF_LEN]; + if(!temp){ + return 0; + } + va_start(arg, formatP); + size_t len = vsnprintf_P(temp, MAX_PRINTF_LEN, formatP, arg); + va_end(arg); + delete[] temp; + + AsyncWebSocketMessageBuffer * buffer = makeBuffer(len + 1); + if (!buffer) { + return 0; + } + + va_start(arg, formatP); + vsnprintf_P((char *)buffer->get(), len + 1, formatP, arg); + va_end(arg); + + textAll(buffer); + return len; +} + +void AsyncWebSocket::text(uint32_t id, const char * message){ + text(id, message, strlen(message)); +} +void AsyncWebSocket::text(uint32_t id, uint8_t * message, size_t len){ + text(id, (const char *)message, len); +} +void AsyncWebSocket::text(uint32_t id, char * message){ + text(id, message, strlen(message)); +} +void AsyncWebSocket::text(uint32_t id, const String &message){ + text(id, message.c_str(), message.length()); +} +void AsyncWebSocket::text(uint32_t id, const __FlashStringHelper *message){ + AsyncWebSocketClient * c = client(id); + if(c != NULL) + c->text(message); +} +void AsyncWebSocket::textAll(const char * message){ + textAll(message, strlen(message)); +} +void AsyncWebSocket::textAll(uint8_t * message, size_t len){ + textAll((const char *)message, len); +} +void AsyncWebSocket::textAll(char * message){ + textAll(message, strlen(message)); +} +void AsyncWebSocket::textAll(const String &message){ + textAll(message.c_str(), message.length()); +} +void AsyncWebSocket::textAll(const __FlashStringHelper *message){ + for(const auto& c: _clients){ + if(c->status() == WS_CONNECTED) + c->text(message); + } +} +void AsyncWebSocket::binary(uint32_t id, const char * message){ + binary(id, message, strlen(message)); +} +void AsyncWebSocket::binary(uint32_t id, uint8_t * message, size_t len){ + binary(id, (const char *)message, len); +} +void AsyncWebSocket::binary(uint32_t id, char * message){ + binary(id, message, strlen(message)); +} +void AsyncWebSocket::binary(uint32_t id, const String &message){ + binary(id, message.c_str(), message.length()); +} +void AsyncWebSocket::binary(uint32_t id, const __FlashStringHelper *message, size_t len){ + AsyncWebSocketClient * c = client(id); + if(c != NULL) + c-> binary(message, len); +} +void AsyncWebSocket::binaryAll(const char * message){ + binaryAll(message, strlen(message)); +} +void AsyncWebSocket::binaryAll(uint8_t * message, size_t len){ + binaryAll((const char *)message, len); +} +void AsyncWebSocket::binaryAll(char * message){ + binaryAll(message, strlen(message)); +} +void AsyncWebSocket::binaryAll(const String &message){ + binaryAll(message.c_str(), message.length()); +} +void AsyncWebSocket::binaryAll(const __FlashStringHelper *message, size_t len){ + for(const auto& c: _clients){ + if(c->status() == WS_CONNECTED) + c-> binary(message, len); + } + } + +const char * WS_STR_CONNECTION = "Connection"; +const char * WS_STR_UPGRADE = "Upgrade"; +const char * WS_STR_ORIGIN = "Origin"; +const char * WS_STR_VERSION = "Sec-WebSocket-Version"; +const char * WS_STR_KEY = "Sec-WebSocket-Key"; +const char * WS_STR_PROTOCOL = "Sec-WebSocket-Protocol"; +const char * WS_STR_ACCEPT = "Sec-WebSocket-Accept"; +const char * WS_STR_UUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + +bool AsyncWebSocket::canHandle(AsyncWebServerRequest *request){ + if(!_enabled) + return false; + + if(request->method() != HTTP_GET || !request->url().equals(_url) || !request->isExpectedRequestedConnType(RCT_WS)) + return false; + + request->addInterestingHeader(WS_STR_CONNECTION); + request->addInterestingHeader(WS_STR_UPGRADE); + request->addInterestingHeader(WS_STR_ORIGIN); + request->addInterestingHeader(WS_STR_VERSION); + request->addInterestingHeader(WS_STR_KEY); + request->addInterestingHeader(WS_STR_PROTOCOL); + return true; +} + +void AsyncWebSocket::handleRequest(AsyncWebServerRequest *request){ + if(!request->hasHeader(WS_STR_VERSION) || !request->hasHeader(WS_STR_KEY)){ + request->send(400); + return; + } + if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str())){ + return request->requestAuthentication(); + } + AsyncWebHeader* version = request->getHeader(WS_STR_VERSION); + if(version->value().toInt() != 13){ + AsyncWebServerResponse *response = request->beginResponse(400); + response->addHeader(WS_STR_VERSION,"13"); + request->send(response); + return; + } + AsyncWebHeader* key = request->getHeader(WS_STR_KEY); + AsyncWebServerResponse *response = new AsyncWebSocketResponse(key->value(), this); + if(request->hasHeader(WS_STR_PROTOCOL)){ + AsyncWebHeader* protocol = request->getHeader(WS_STR_PROTOCOL); + //ToDo: check protocol + response->addHeader(WS_STR_PROTOCOL, protocol->value()); + } + request->send(response); +} + +AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(size_t size) +{ + AsyncWebSocketMessageBuffer * buffer = new AsyncWebSocketMessageBuffer(size); + if (buffer) { + AsyncWebLockGuard l(_lock); + _buffers.add(buffer); + } + return buffer; +} + +AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(uint8_t * data, size_t size) +{ + AsyncWebSocketMessageBuffer * buffer = new AsyncWebSocketMessageBuffer(data, size); + + if (buffer) { + AsyncWebLockGuard l(_lock); + _buffers.add(buffer); + } + + return buffer; +} + +void AsyncWebSocket::_cleanBuffers() +{ + AsyncWebLockGuard l(_lock); + + for(AsyncWebSocketMessageBuffer * c: _buffers){ + if(c && c->canDelete()){ + _buffers.remove(c); + } + } +} + +AsyncWebSocket::AsyncWebSocketClientAsyncLinkedList AsyncWebSocket::getClients() const { + return _clients; +} + +/* + * Response to Web Socket request - sends the authorization and detaches the TCP Client from the web server + * Authentication code from https://github.com/Links2004/arduinoWebSockets/blob/master/src/WebSockets.cpp#L480 + */ + +AsyncWebSocketResponse::AsyncWebSocketResponse(const String& key, AsyncWebSocket *server){ + _server = server; + _code = 101; + _sendContentLength = false; + + uint8_t * hash = (uint8_t*)malloc(20); + if(hash == NULL){ + _state = RESPONSE_FAILED; + return; + } + char * buffer = (char *) malloc(33); + if(buffer == NULL){ + free(hash); + _state = RESPONSE_FAILED; + return; + } +#ifdef ESP8266 + sha1(key + WS_STR_UUID, hash); +#else + (String&)key += WS_STR_UUID; + mbedtls_sha1_context ctx; + mbedtls_sha1_init(&ctx); + mbedtls_sha1_starts_ret(&ctx); + mbedtls_sha1_update_ret(&ctx, (const unsigned char*)key.c_str(), key.length()); + mbedtls_sha1_finish_ret(&ctx, hash); + mbedtls_sha1_free(&ctx); +#endif + base64_encodestate _state; + base64_init_encodestate(&_state); + int len = base64_encode_block((const char *) hash, 20, buffer, &_state); + len = base64_encode_blockend((buffer + len), &_state); + addHeader(WS_STR_CONNECTION, WS_STR_UPGRADE); + addHeader(WS_STR_UPGRADE, "websocket"); + addHeader(WS_STR_ACCEPT,buffer); + free(buffer); + free(hash); +} + +void AsyncWebSocketResponse::_respond(AsyncWebServerRequest *request){ + if(_state == RESPONSE_FAILED){ + request->client()->close(true); + return; + } + String out = _assembleHead(request->version()); + request->client()->write(out.c_str(), _headLength); + _state = RESPONSE_WAIT_ACK; +} + +size_t AsyncWebSocketResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){ + (void)time; + if(len){ + new AsyncWebSocketClient(request, _server); + } + return 0; +} diff --git a/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.h b/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.h new file mode 100644 index 000000000..7fb1e92de --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.h @@ -0,0 +1,350 @@ +/* + Asynchronous WebServer library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef ASYNCWEBSOCKET_H_ +#define ASYNCWEBSOCKET_H_ + +#include +#ifdef ESP32 +#include +#define WS_MAX_QUEUED_MESSAGES 32 +#else +#include +#define WS_MAX_QUEUED_MESSAGES 8 +#endif +#include + +#include "AsyncWebSynchronization.h" + +#ifdef ESP8266 +#include +#ifdef CRYPTO_HASH_h // include Hash.h from espressif framework if the first include was from the crypto library +#include <../src/Hash.h> +#endif +#endif + +#ifdef ESP32 +#define DEFAULT_MAX_WS_CLIENTS 8 +#else +#define DEFAULT_MAX_WS_CLIENTS 4 +#endif + +class AsyncWebSocket; +class AsyncWebSocketResponse; +class AsyncWebSocketClient; +class AsyncWebSocketControl; + +typedef struct { + /** Message type as defined by enum AwsFrameType. + * Note: Applications will only see WS_TEXT and WS_BINARY. + * All other types are handled by the library. */ + uint8_t message_opcode; + /** Frame number of a fragmented message. */ + uint32_t num; + /** Is this the last frame in a fragmented message ?*/ + uint8_t final; + /** Is this frame masked? */ + uint8_t masked; + /** Message type as defined by enum AwsFrameType. + * This value is the same as message_opcode for non-fragmented + * messages, but may also be WS_CONTINUATION in a fragmented message. */ + uint8_t opcode; + /** Length of the current frame. + * This equals the total length of the message if num == 0 && final == true */ + uint64_t len; + /** Mask key */ + uint8_t mask[4]; + /** Offset of the data inside the current frame. */ + uint64_t index; +} AwsFrameInfo; + +typedef enum { WS_DISCONNECTED, WS_CONNECTED, WS_DISCONNECTING } AwsClientStatus; +typedef enum { WS_CONTINUATION, WS_TEXT, WS_BINARY, WS_DISCONNECT = 0x08, WS_PING, WS_PONG } AwsFrameType; +typedef enum { WS_MSG_SENDING, WS_MSG_SENT, WS_MSG_ERROR } AwsMessageStatus; +typedef enum { WS_EVT_CONNECT, WS_EVT_DISCONNECT, WS_EVT_PONG, WS_EVT_ERROR, WS_EVT_DATA } AwsEventType; + +class AsyncWebSocketMessageBuffer { + private: + uint8_t * _data; + size_t _len; + bool _lock; + uint32_t _count; + + public: + AsyncWebSocketMessageBuffer(); + AsyncWebSocketMessageBuffer(size_t size); + AsyncWebSocketMessageBuffer(uint8_t * data, size_t size); + AsyncWebSocketMessageBuffer(const AsyncWebSocketMessageBuffer &); + AsyncWebSocketMessageBuffer(AsyncWebSocketMessageBuffer &&); + ~AsyncWebSocketMessageBuffer(); + void operator ++(int i) { (void)i; _count++; } + void operator --(int i) { (void)i; if (_count > 0) { _count--; } ; } + bool reserve(size_t size); + void lock() { _lock = true; } + void unlock() { _lock = false; } + uint8_t * get() { return _data; } + size_t length() { return _len; } + uint32_t count() { return _count; } + bool canDelete() { return (!_count && !_lock); } + + friend AsyncWebSocket; + +}; + +class AsyncWebSocketMessage { + protected: + uint8_t _opcode; + bool _mask; + AwsMessageStatus _status; + public: + AsyncWebSocketMessage():_opcode(WS_TEXT),_mask(false),_status(WS_MSG_ERROR){} + virtual ~AsyncWebSocketMessage(){} + virtual void ack(size_t len __attribute__((unused)), uint32_t time __attribute__((unused))){} + virtual size_t send(AsyncClient *client __attribute__((unused))){ return 0; } + virtual bool finished(){ return _status != WS_MSG_SENDING; } + virtual bool betweenFrames() const { return false; } +}; + +class AsyncWebSocketBasicMessage: public AsyncWebSocketMessage { + private: + size_t _len; + size_t _sent; + size_t _ack; + size_t _acked; + uint8_t * _data; +public: + AsyncWebSocketBasicMessage(const char * data, size_t len, uint8_t opcode=WS_TEXT, bool mask=false); + AsyncWebSocketBasicMessage(uint8_t opcode=WS_TEXT, bool mask=false); + virtual ~AsyncWebSocketBasicMessage() override; + virtual bool betweenFrames() const override { return _acked == _ack; } + virtual void ack(size_t len, uint32_t time) override ; + virtual size_t send(AsyncClient *client) override ; +}; + +class AsyncWebSocketMultiMessage: public AsyncWebSocketMessage { + private: + uint8_t * _data; + size_t _len; + size_t _sent; + size_t _ack; + size_t _acked; + AsyncWebSocketMessageBuffer * _WSbuffer; +public: + AsyncWebSocketMultiMessage(AsyncWebSocketMessageBuffer * buffer, uint8_t opcode=WS_TEXT, bool mask=false); + virtual ~AsyncWebSocketMultiMessage() override; + virtual bool betweenFrames() const override { return _acked == _ack; } + virtual void ack(size_t len, uint32_t time) override ; + virtual size_t send(AsyncClient *client) override ; +}; + +class AsyncWebSocketClient { + private: + AsyncClient *_client; + AsyncWebSocket *_server; + uint32_t _clientId; + AwsClientStatus _status; + + AsyncLinkedList _controlQueue; + AsyncLinkedList _messageQueue; + + uint8_t _pstate; + AwsFrameInfo _pinfo; + + uint32_t _lastMessageTime; + uint32_t _keepAlivePeriod; + + void _queueMessage(AsyncWebSocketMessage *dataMessage); + void _queueControl(AsyncWebSocketControl *controlMessage); + void _runQueue(); + + public: + void *_tempObject; + + AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server); + ~AsyncWebSocketClient(); + + //client id increments for the given server + uint32_t id(){ return _clientId; } + AwsClientStatus status(){ return _status; } + AsyncClient* client(){ return _client; } + AsyncWebSocket *server(){ return _server; } + AwsFrameInfo const &pinfo() const { return _pinfo; } + + IPAddress remoteIP(); + uint16_t remotePort(); + + //control frames + void close(uint16_t code=0, const char * message=NULL); + void ping(uint8_t *data=NULL, size_t len=0); + + //set auto-ping period in seconds. disabled if zero (default) + void keepAlivePeriod(uint16_t seconds){ + _keepAlivePeriod = seconds * 1000; + } + uint16_t keepAlivePeriod(){ + return (uint16_t)(_keepAlivePeriod / 1000); + } + + //data packets + void message(AsyncWebSocketMessage *message){ _queueMessage(message); } + bool queueIsFull(); + + size_t printf(const char *format, ...) __attribute__ ((format (printf, 2, 3))); +#ifndef ESP32 + size_t printf_P(PGM_P formatP, ...) __attribute__ ((format (printf, 2, 3))); +#endif + void text(const char * message, size_t len); + void text(const char * message); + void text(uint8_t * message, size_t len); + void text(char * message); + void text(const String &message); + void text(const __FlashStringHelper *data); + void text(AsyncWebSocketMessageBuffer *buffer); + + void binary(const char * message, size_t len); + void binary(const char * message); + void binary(uint8_t * message, size_t len); + void binary(char * message); + void binary(const String &message); + void binary(const __FlashStringHelper *data, size_t len); + void binary(AsyncWebSocketMessageBuffer *buffer); + + bool canSend() { return _messageQueue.length() < WS_MAX_QUEUED_MESSAGES; } + + //system callbacks (do not call) + void _onAck(size_t len, uint32_t time); + void _onError(int8_t); + void _onPoll(); + void _onTimeout(uint32_t time); + void _onDisconnect(); + void _onData(void *pbuf, size_t plen); +}; + +typedef std::function AwsEventHandler; + +//WebServer Handler implementation that plays the role of a socket server +class AsyncWebSocket: public AsyncWebHandler { + public: + typedef AsyncLinkedList AsyncWebSocketClientAsyncLinkedList; + private: + String _url; + AsyncWebSocketClientAsyncLinkedList _clients; + uint32_t _cNextId; + AwsEventHandler _eventHandler; + bool _enabled; + AsyncWebLock _lock; + + public: + AsyncWebSocket(const String& url); + ~AsyncWebSocket(); + const char * url() const { return _url.c_str(); } + void enable(bool e){ _enabled = e; } + bool enabled() const { return _enabled; } + bool availableForWriteAll(); + bool availableForWrite(uint32_t id); + + size_t count() const; + AsyncWebSocketClient * client(uint32_t id); + bool hasClient(uint32_t id){ return client(id) != NULL; } + + void close(uint32_t id, uint16_t code=0, const char * message=NULL); + void closeAll(uint16_t code=0, const char * message=NULL); + void cleanupClients(uint16_t maxClients = DEFAULT_MAX_WS_CLIENTS); + + void ping(uint32_t id, uint8_t *data=NULL, size_t len=0); + void pingAll(uint8_t *data=NULL, size_t len=0); // done + + void text(uint32_t id, const char * message, size_t len); + void text(uint32_t id, const char * message); + void text(uint32_t id, uint8_t * message, size_t len); + void text(uint32_t id, char * message); + void text(uint32_t id, const String &message); + void text(uint32_t id, const __FlashStringHelper *message); + + void textAll(const char * message, size_t len); + void textAll(const char * message); + void textAll(uint8_t * message, size_t len); + void textAll(char * message); + void textAll(const String &message); + void textAll(const __FlashStringHelper *message); // need to convert + void textAll(AsyncWebSocketMessageBuffer * buffer); + + void binary(uint32_t id, const char * message, size_t len); + void binary(uint32_t id, const char * message); + void binary(uint32_t id, uint8_t * message, size_t len); + void binary(uint32_t id, char * message); + void binary(uint32_t id, const String &message); + void binary(uint32_t id, const __FlashStringHelper *message, size_t len); + + void binaryAll(const char * message, size_t len); + void binaryAll(const char * message); + void binaryAll(uint8_t * message, size_t len); + void binaryAll(char * message); + void binaryAll(const String &message); + void binaryAll(const __FlashStringHelper *message, size_t len); + void binaryAll(AsyncWebSocketMessageBuffer * buffer); + + void message(uint32_t id, AsyncWebSocketMessage *message); + void messageAll(AsyncWebSocketMultiMessage *message); + + size_t printf(uint32_t id, const char *format, ...) __attribute__ ((format (printf, 3, 4))); + size_t printfAll(const char *format, ...) __attribute__ ((format (printf, 2, 3))); +#ifndef ESP32 + size_t printf_P(uint32_t id, PGM_P formatP, ...) __attribute__ ((format (printf, 3, 4))); +#endif + size_t printfAll_P(PGM_P formatP, ...) __attribute__ ((format (printf, 2, 3))); + + //event listener + void onEvent(AwsEventHandler handler){ + _eventHandler = handler; + } + + //system callbacks (do not call) + uint32_t _getNextId(){ return _cNextId++; } + void _addClient(AsyncWebSocketClient * client); + void _handleDisconnect(AsyncWebSocketClient * client); + void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len); + virtual bool canHandle(AsyncWebServerRequest *request) override final; + virtual void handleRequest(AsyncWebServerRequest *request) override final; + + + // messagebuffer functions/objects. + AsyncWebSocketMessageBuffer * makeBuffer(size_t size = 0); + AsyncWebSocketMessageBuffer * makeBuffer(uint8_t * data, size_t size); + AsyncLinkedList _buffers; + void _cleanBuffers(); + + AsyncWebSocketClientAsyncLinkedList getClients() const; +}; + +//WebServer response to authenticate the socket and detach the tcp client from the web server request +class AsyncWebSocketResponse: public AsyncWebServerResponse { + private: + String _content; + AsyncWebSocket *_server; + public: + AsyncWebSocketResponse(const String& key, AsyncWebSocket *server); + void _respond(AsyncWebServerRequest *request); + size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); + bool _sourceValid() const { return true; } +}; + + +#endif /* ASYNCWEBSOCKET_H_ */ diff --git a/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSynchronization.h b/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSynchronization.h new file mode 100644 index 000000000..f36c52dcf --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSynchronization.h @@ -0,0 +1,87 @@ +#ifndef ASYNCWEBSYNCHRONIZATION_H_ +#define ASYNCWEBSYNCHRONIZATION_H_ + +// Synchronisation is only available on ESP32, as the ESP8266 isn't using FreeRTOS by default + +#include + +#ifdef ESP32 + +// This is the ESP32 version of the Sync Lock, using the FreeRTOS Semaphore +class AsyncWebLock +{ +private: + SemaphoreHandle_t _lock; + mutable void *_lockedBy; + +public: + AsyncWebLock() { + _lock = xSemaphoreCreateBinary(); + _lockedBy = NULL; + xSemaphoreGive(_lock); + } + + ~AsyncWebLock() { + vSemaphoreDelete(_lock); + } + + bool lock() const { + extern void *pxCurrentTCB; + if (_lockedBy != pxCurrentTCB) { + xSemaphoreTake(_lock, portMAX_DELAY); + _lockedBy = pxCurrentTCB; + return true; + } + return false; + } + + void unlock() const { + _lockedBy = NULL; + xSemaphoreGive(_lock); + } +}; + +#else + +// This is the 8266 version of the Sync Lock which is currently unimplemented +class AsyncWebLock +{ + +public: + AsyncWebLock() { + } + + ~AsyncWebLock() { + } + + bool lock() const { + return false; + } + + void unlock() const { + } +}; +#endif + +class AsyncWebLockGuard +{ +private: + const AsyncWebLock *_lock; + +public: + AsyncWebLockGuard(const AsyncWebLock &l) { + if (l.lock()) { + _lock = &l; + } else { + _lock = NULL; + } + } + + ~AsyncWebLockGuard() { + if (_lock) { + _lock->unlock(); + } + } +}; + +#endif // ASYNCWEBSYNCHRONIZATION_H_ \ No newline at end of file diff --git a/lib/libesp32/ESPAsyncWebServer/src/ESPAsyncWebServer.h b/lib/libesp32/ESPAsyncWebServer/src/ESPAsyncWebServer.h new file mode 100644 index 000000000..5f718c35c --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/ESPAsyncWebServer.h @@ -0,0 +1,471 @@ +/* + Asynchronous WebServer library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef _ESPAsyncWebServer_H_ +#define _ESPAsyncWebServer_H_ + +#include "Arduino.h" + +#include +#include "FS.h" + +#include "StringArray.h" + +#ifdef ESP32 +#include +#include +#elif defined(ESP8266) +#include +#include +#else +#error Platform not supported +#endif + +#ifdef ASYNCWEBSERVER_REGEX +#define ASYNCWEBSERVER_REGEX_ATTRIBUTE +#else +#define ASYNCWEBSERVER_REGEX_ATTRIBUTE __attribute__((warning("ASYNCWEBSERVER_REGEX not defined"))) +#endif + +#define DEBUGF(...) //Serial.printf(__VA_ARGS__) + +class AsyncWebServer; +class AsyncWebServerRequest; +class AsyncWebServerResponse; +class AsyncWebHeader; +class AsyncWebParameter; +class AsyncWebRewrite; +class AsyncWebHandler; +class AsyncStaticWebHandler; +class AsyncCallbackWebHandler; +class AsyncResponseStream; + +#ifndef WEBSERVER_H +typedef enum { + HTTP_GET = 0b00000001, + HTTP_POST = 0b00000010, + HTTP_DELETE = 0b00000100, + HTTP_PUT = 0b00001000, + HTTP_PATCH = 0b00010000, + HTTP_HEAD = 0b00100000, + HTTP_OPTIONS = 0b01000000, + HTTP_ANY = 0b01111111, +} WebRequestMethod; +#endif + +//if this value is returned when asked for data, packet will not be sent and you will be asked for data again +#define RESPONSE_TRY_AGAIN 0xFFFFFFFF + +typedef uint8_t WebRequestMethodComposite; +typedef std::function ArDisconnectHandler; + +/* + * PARAMETER :: Chainable object to hold GET/POST and FILE parameters + * */ + +class AsyncWebParameter { + private: + String _name; + String _value; + size_t _size; + bool _isForm; + bool _isFile; + + public: + + AsyncWebParameter(const String& name, const String& value, bool form=false, bool file=false, size_t size=0): _name(name), _value(value), _size(size), _isForm(form), _isFile(file){} + const String& name() const { return _name; } + const String& value() const { return _value; } + size_t size() const { return _size; } + bool isPost() const { return _isForm; } + bool isFile() const { return _isFile; } +}; + +/* + * HEADER :: Chainable object to hold the headers + * */ + +class AsyncWebHeader { + private: + String _name; + String _value; + + public: + AsyncWebHeader(const String& name, const String& value): _name(name), _value(value){} + AsyncWebHeader(const String& data): _name(), _value(){ + if(!data) return; + int index = data.indexOf(':'); + if (index < 0) return; + _name = data.substring(0, index); + _value = data.substring(index + 2); + } + ~AsyncWebHeader(){} + const String& name() const { return _name; } + const String& value() const { return _value; } + String toString() const { return String(_name+": "+_value+"\r\n"); } +}; + +/* + * REQUEST :: Each incoming Client is wrapped inside a Request and both live together until disconnect + * */ + +typedef enum { RCT_NOT_USED = -1, RCT_DEFAULT = 0, RCT_HTTP, RCT_WS, RCT_EVENT, RCT_MAX } RequestedConnectionType; + +typedef std::function AwsResponseFiller; +typedef std::function AwsTemplateProcessor; + +class AsyncWebServerRequest { + using File = fs::File; + using FS = fs::FS; + friend class AsyncWebServer; + friend class AsyncCallbackWebHandler; + private: + AsyncClient* _client; + AsyncWebServer* _server; + AsyncWebHandler* _handler; + AsyncWebServerResponse* _response; + StringArray _interestingHeaders; + ArDisconnectHandler _onDisconnectfn; + + String _temp; + uint8_t _parseState; + + uint8_t _version; + WebRequestMethodComposite _method; + String _url; + String _host; + String _contentType; + String _boundary; + String _authorization; + RequestedConnectionType _reqconntype; + void _removeNotInterestingHeaders(); + bool _isDigest; + bool _isMultipart; + bool _isPlainPost; + bool _expectingContinue; + size_t _contentLength; + size_t _parsedLength; + + AsyncLinkedList _headers; + AsyncLinkedList _params; + AsyncLinkedList _pathParams; + + uint8_t _multiParseState; + uint8_t _boundaryPosition; + size_t _itemStartIndex; + size_t _itemSize; + String _itemName; + String _itemFilename; + String _itemType; + String _itemValue; + uint8_t *_itemBuffer; + size_t _itemBufferIndex; + bool _itemIsFile; + + void _onPoll(); + void _onAck(size_t len, uint32_t time); + void _onError(int8_t error); + void _onTimeout(uint32_t time); + void _onDisconnect(); + void _onData(void *buf, size_t len); + + void _addParam(AsyncWebParameter*); + void _addPathParam(const char *param); + + bool _parseReqHead(); + bool _parseReqHeader(); + void _parseLine(); + void _parsePlainPostChar(uint8_t data); + void _parseMultipartPostByte(uint8_t data, bool last); + void _addGetParams(const String& params); + + void _handleUploadStart(); + void _handleUploadByte(uint8_t data, bool last); + void _handleUploadEnd(); + + public: + File _tempFile; + void *_tempObject; + + AsyncWebServerRequest(AsyncWebServer*, AsyncClient*); + ~AsyncWebServerRequest(); + + AsyncClient* client(){ return _client; } + uint8_t version() const { return _version; } + WebRequestMethodComposite method() const { return _method; } + const String& url() const { return _url; } + const String& host() const { return _host; } + const String& contentType() const { return _contentType; } + size_t contentLength() const { return _contentLength; } + bool multipart() const { return _isMultipart; } + const char * methodToString() const; + const char * requestedConnTypeToString() const; + RequestedConnectionType requestedConnType() const { return _reqconntype; } + bool isExpectedRequestedConnType(RequestedConnectionType erct1, RequestedConnectionType erct2 = RCT_NOT_USED, RequestedConnectionType erct3 = RCT_NOT_USED); + void onDisconnect (ArDisconnectHandler fn); + + //hash is the string representation of: + // base64(user:pass) for basic or + // user:realm:md5(user:realm:pass) for digest + bool authenticate(const char * hash); + bool authenticate(const char * username, const char * password, const char * realm = NULL, bool passwordIsHash = false); + void requestAuthentication(const char * realm = NULL, bool isDigest = true); + + void setHandler(AsyncWebHandler *handler){ _handler = handler; } + void addInterestingHeader(const String& name); + + void redirect(const String& url); + + void send(AsyncWebServerResponse *response); + void send(int code, const String& contentType=String(), const String& content=String()); + void send(FS &fs, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr); + void send(File content, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr); + void send(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback=nullptr); + void send(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr); + void sendChunked(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr); + void send_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback=nullptr); + void send_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback=nullptr); + + AsyncWebServerResponse *beginResponse(int code, const String& contentType=String(), const String& content=String()); + AsyncWebServerResponse *beginResponse(FS &fs, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr); + AsyncWebServerResponse *beginResponse(File content, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr); + AsyncWebServerResponse *beginResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback=nullptr); + AsyncWebServerResponse *beginResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr); + AsyncWebServerResponse *beginChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr); + AsyncResponseStream *beginResponseStream(const String& contentType, size_t bufferSize=1460); + AsyncWebServerResponse *beginResponse_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback=nullptr); + AsyncWebServerResponse *beginResponse_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback=nullptr); + + size_t headers() const; // get header count + bool hasHeader(const String& name) const; // check if header exists + bool hasHeader(const __FlashStringHelper * data) const; // check if header exists + + AsyncWebHeader* getHeader(const String& name) const; + AsyncWebHeader* getHeader(const __FlashStringHelper * data) const; + AsyncWebHeader* getHeader(size_t num) const; + + size_t params() const; // get arguments count + bool hasParam(const String& name, bool post=false, bool file=false) const; + bool hasParam(const __FlashStringHelper * data, bool post=false, bool file=false) const; + + AsyncWebParameter* getParam(const String& name, bool post=false, bool file=false) const; + AsyncWebParameter* getParam(const __FlashStringHelper * data, bool post, bool file) const; + AsyncWebParameter* getParam(size_t num) const; + + size_t args() const { return params(); } // get arguments count + const String& arg(const String& name) const; // get request argument value by name + const String& arg(const __FlashStringHelper * data) const; // get request argument value by F(name) + const String& arg(size_t i) const; // get request argument value by number + const String& argName(size_t i) const; // get request argument name by number + bool hasArg(const char* name) const; // check if argument exists + bool hasArg(const __FlashStringHelper * data) const; // check if F(argument) exists + + const String& ASYNCWEBSERVER_REGEX_ATTRIBUTE pathArg(size_t i) const; + + const String& header(const char* name) const;// get request header value by name + const String& header(const __FlashStringHelper * data) const;// get request header value by F(name) + const String& header(size_t i) const; // get request header value by number + const String& headerName(size_t i) const; // get request header name by number + String urlDecode(const String& text) const; +}; + +/* + * FILTER :: Callback to filter AsyncWebRewrite and AsyncWebHandler (done by the Server) + * */ + +typedef std::function ArRequestFilterFunction; + +bool ON_STA_FILTER(AsyncWebServerRequest *request); + +bool ON_AP_FILTER(AsyncWebServerRequest *request); + +/* + * REWRITE :: One instance can be handle any Request (done by the Server) + * */ + +class AsyncWebRewrite { + protected: + String _from; + String _toUrl; + String _params; + ArRequestFilterFunction _filter; + public: + AsyncWebRewrite(const char* from, const char* to): _from(from), _toUrl(to), _params(String()), _filter(NULL){ + int index = _toUrl.indexOf('?'); + if (index > 0) { + _params = _toUrl.substring(index +1); + _toUrl = _toUrl.substring(0, index); + } + } + virtual ~AsyncWebRewrite(){} + AsyncWebRewrite& setFilter(ArRequestFilterFunction fn) { _filter = fn; return *this; } + bool filter(AsyncWebServerRequest *request) const { return _filter == NULL || _filter(request); } + const String& from(void) const { return _from; } + const String& toUrl(void) const { return _toUrl; } + const String& params(void) const { return _params; } + virtual bool match(AsyncWebServerRequest *request) { return from() == request->url() && filter(request); } +}; + +/* + * HANDLER :: One instance can be attached to any Request (done by the Server) + * */ + +class AsyncWebHandler { + protected: + ArRequestFilterFunction _filter; + String _username; + String _password; + public: + AsyncWebHandler():_username(""), _password(""){} + AsyncWebHandler& setFilter(ArRequestFilterFunction fn) { _filter = fn; return *this; } + AsyncWebHandler& setAuthentication(const char *username, const char *password){ _username = String(username);_password = String(password); return *this; }; + bool filter(AsyncWebServerRequest *request){ return _filter == NULL || _filter(request); } + virtual ~AsyncWebHandler(){} + virtual bool canHandle(AsyncWebServerRequest *request __attribute__((unused))){ + return false; + } + virtual void handleRequest(AsyncWebServerRequest *request __attribute__((unused))){} + virtual void handleUpload(AsyncWebServerRequest *request __attribute__((unused)), const String& filename __attribute__((unused)), size_t index __attribute__((unused)), uint8_t *data __attribute__((unused)), size_t len __attribute__((unused)), bool final __attribute__((unused))){} + virtual void handleBody(AsyncWebServerRequest *request __attribute__((unused)), uint8_t *data __attribute__((unused)), size_t len __attribute__((unused)), size_t index __attribute__((unused)), size_t total __attribute__((unused))){} + virtual bool isRequestHandlerTrivial(){return true;} +}; + +/* + * RESPONSE :: One instance is created for each Request (attached by the Handler) + * */ + +typedef enum { + RESPONSE_SETUP, RESPONSE_HEADERS, RESPONSE_CONTENT, RESPONSE_WAIT_ACK, RESPONSE_END, RESPONSE_FAILED +} WebResponseState; + +class AsyncWebServerResponse { + protected: + int _code; + AsyncLinkedList _headers; + String _contentType; + size_t _contentLength; + bool _sendContentLength; + bool _chunked; + size_t _headLength; + size_t _sentLength; + size_t _ackedLength; + size_t _writtenLength; + WebResponseState _state; + const char* _responseCodeToString(int code); + + public: + AsyncWebServerResponse(); + virtual ~AsyncWebServerResponse(); + virtual void setCode(int code); + virtual void setContentLength(size_t len); + virtual void setContentType(const String& type); + virtual void addHeader(const String& name, const String& value); + virtual String _assembleHead(uint8_t version); + virtual bool _started() const; + virtual bool _finished() const; + virtual bool _failed() const; + virtual bool _sourceValid() const; + virtual void _respond(AsyncWebServerRequest *request); + virtual size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); +}; + +/* + * SERVER :: One instance + * */ + +typedef std::function ArRequestHandlerFunction; +typedef std::function ArUploadHandlerFunction; +typedef std::function ArBodyHandlerFunction; + +class AsyncWebServer { + protected: + AsyncServer _server; + AsyncLinkedList _rewrites; + AsyncLinkedList _handlers; + AsyncCallbackWebHandler* _catchAllHandler; + + public: + AsyncWebServer(uint16_t port); + ~AsyncWebServer(); + + void begin(); + void end(); + +#if ASYNC_TCP_SSL_ENABLED + void onSslFileRequest(AcSSlFileHandler cb, void* arg); + void beginSecure(const char *cert, const char *private_key_file, const char *password); +#endif + + AsyncWebRewrite& addRewrite(AsyncWebRewrite* rewrite); + bool removeRewrite(AsyncWebRewrite* rewrite); + AsyncWebRewrite& rewrite(const char* from, const char* to); + + AsyncWebHandler& addHandler(AsyncWebHandler* handler); + bool removeHandler(AsyncWebHandler* handler); + + AsyncCallbackWebHandler& on(const char* uri, ArRequestHandlerFunction onRequest); + AsyncCallbackWebHandler& on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest); + AsyncCallbackWebHandler& on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload); + AsyncCallbackWebHandler& on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload, ArBodyHandlerFunction onBody); + + AsyncStaticWebHandler& serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_control = NULL); + + void onNotFound(ArRequestHandlerFunction fn); //called when handler is not assigned + void onFileUpload(ArUploadHandlerFunction fn); //handle file uploads + void onRequestBody(ArBodyHandlerFunction fn); //handle posts with plain body content (JSON often transmitted this way as a request) + + void reset(); //remove all writers and handlers, with onNotFound/onFileUpload/onRequestBody + + void _handleDisconnect(AsyncWebServerRequest *request); + void _attachHandler(AsyncWebServerRequest *request); + void _rewriteRequest(AsyncWebServerRequest *request); +}; + +class DefaultHeaders { + using headers_t = AsyncLinkedList; + headers_t _headers; + + DefaultHeaders() + :_headers(headers_t([](AsyncWebHeader *h){ delete h; })) + {} +public: + using ConstIterator = headers_t::ConstIterator; + + void addHeader(const String& name, const String& value){ + _headers.add(new AsyncWebHeader(name, value)); + } + + ConstIterator begin() const { return _headers.begin(); } + ConstIterator end() const { return _headers.end(); } + + DefaultHeaders(DefaultHeaders const &) = delete; + DefaultHeaders &operator=(DefaultHeaders const &) = delete; + static DefaultHeaders &Instance() { + static DefaultHeaders instance; + return instance; + } +}; + +#include "WebResponseImpl.h" +#include "WebHandlerImpl.h" +#include "AsyncWebSocket.h" +#include "AsyncEventSource.h" + +#endif /* _AsyncWebServer_H_ */ diff --git a/lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.cpp b/lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.cpp new file mode 100644 index 000000000..a84fa87dd --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.cpp @@ -0,0 +1,544 @@ +#include "SPIFFSEditor.h" +#include + +//File: edit.htm.gz, Size: 4151 +#define edit_htm_gz_len 4151 +const uint8_t edit_htm_gz[] PROGMEM = { + 0x1F, 0x8B, 0x08, 0x08, 0xB8, 0x94, 0xB1, 0x59, 0x00, 0x03, 0x65, 0x64, 0x69, 0x74, 0x2E, 0x68, + 0x74, 0x6D, 0x00, 0xB5, 0x3A, 0x0B, 0x7B, 0xDA, 0xB8, 0xB2, 0x7F, 0xC5, 0x71, 0xCF, 0x66, 0xED, + 0x83, 0x31, 0x90, 0xA4, 0xD9, 0xD6, 0xC4, 0xC9, 0x42, 0x92, 0x36, 0x6D, 0xF3, 0x6A, 0x80, 0xB6, + 0x69, 0x4F, 0xEE, 0x7E, 0xC2, 0x16, 0xA0, 0xC6, 0x96, 0x5D, 0x5B, 0x0E, 0x49, 0x59, 0xFE, 0xFB, + 0x9D, 0x91, 0x6C, 0xB0, 0x09, 0x69, 0x77, 0xCF, 0xBD, 0xBB, 0xDD, 0x2D, 0x92, 0x46, 0x33, 0x9A, + 0x19, 0xCD, 0x53, 0xDE, 0xBD, 0x8D, 0xA3, 0x8B, 0xC3, 0xFE, 0xF5, 0xE5, 0xB1, 0x36, 0x11, 0x61, + 0xB0, 0xBF, 0x87, 0x7F, 0x6B, 0x01, 0xE1, 0x63, 0x97, 0xF2, 0xFD, 0x3D, 0xC1, 0x44, 0x40, 0xF7, + 0x8F, 0x7B, 0x97, 0xDA, 0xB1, 0xCF, 0x44, 0x94, 0xEC, 0x35, 0xD4, 0xCA, 0x5E, 0x2A, 0x1E, 0x02, + 0xAA, 0x85, 0xD4, 0x67, 0xC4, 0x4D, 0xBD, 0x84, 0xC2, 0x66, 0xDB, 0x0B, 0x67, 0xDF, 0xEB, 0x8C, + 0xFB, 0xF4, 0xDE, 0xD9, 0x6E, 0x36, 0xDB, 0x71, 0x94, 0x32, 0xC1, 0x22, 0xEE, 0x90, 0x61, 0x1A, + 0x05, 0x99, 0xA0, 0xED, 0x80, 0x8E, 0x84, 0xF3, 0x3C, 0xBE, 0x6F, 0x0F, 0xA3, 0xC4, 0xA7, 0x89, + 0xD3, 0x8A, 0xEF, 0x35, 0x00, 0x31, 0x5F, 0x7B, 0xB6, 0xB3, 0xB3, 0xD3, 0x1E, 0x12, 0xEF, 0x76, + 0x9C, 0x44, 0x19, 0xF7, 0xEB, 0x5E, 0x14, 0x44, 0x89, 0xF3, 0x6C, 0xF4, 0x1C, 0xFF, 0xB4, 0x7D, + 0x96, 0xC6, 0x01, 0x79, 0x70, 0x78, 0xC4, 0x29, 0xE0, 0xDE, 0xD7, 0xD3, 0x09, 0xF1, 0xA3, 0xA9, + 0xD3, 0xD4, 0x9A, 0x5A, 0xAB, 0x09, 0x44, 0x92, 0xF1, 0x90, 0x18, 0x4D, 0x0B, 0xFF, 0xD8, 0x3B, + 0x66, 0x7B, 0x14, 0x71, 0x51, 0x4F, 0xD9, 0x77, 0xEA, 0xB4, 0xB6, 0xE0, 0x34, 0x39, 0x1D, 0x91, + 0x90, 0x05, 0x0F, 0x4E, 0x4A, 0x78, 0x5A, 0x4F, 0x69, 0xC2, 0x46, 0x6A, 0x79, 0x4A, 0xD9, 0x78, + 0x22, 0x9C, 0xDF, 0x9A, 0xCD, 0x39, 0xF0, 0xAF, 0x65, 0xC1, 0x2C, 0x60, 0x29, 0x20, 0xA3, 0x78, + 0xEA, 0x3C, 0x11, 0xC5, 0x4E, 0x53, 0xB1, 0xDE, 0x6C, 0x87, 0x24, 0x19, 0x33, 0x0E, 0x83, 0x98, + 0xF8, 0x3E, 0xE3, 0x63, 0x47, 0xA1, 0x05, 0x6C, 0xB6, 0x90, 0x36, 0xA1, 0x01, 0x11, 0xEC, 0x8E, + 0xB6, 0x43, 0xC6, 0xEB, 0x53, 0xE6, 0x8B, 0x89, 0xB3, 0x0B, 0x3C, 0xB6, 0xBD, 0x2C, 0x49, 0x41, + 0xA6, 0x38, 0x62, 0x5C, 0xD0, 0x44, 0xA2, 0xA5, 0x31, 0xE1, 0xB3, 0x5C, 0x54, 0x54, 0x40, 0x21, + 0x27, 0xE3, 0x01, 0xE3, 0xB4, 0x3E, 0x0C, 0x22, 0xEF, 0x76, 0x71, 0xD2, 0x6E, 0x7C, 0x9F, 0x9F, + 0xE5, 0x4C, 0xA2, 0x3B, 0x9A, 0xCC, 0x96, 0xEA, 0x92, 0xD8, 0x15, 0x60, 0x85, 0x34, 0xA5, 0x74, + 0x6E, 0x8B, 0xBB, 0x0C, 0xA0, 0x96, 0xFC, 0x05, 0x29, 0x17, 0xFC, 0x2F, 0x45, 0x5A, 0x11, 0x5C, + 0xA1, 0x30, 0x1E, 0x67, 0x62, 0xF6, 0xF8, 0x2A, 0xA3, 0x98, 0x78, 0x4C, 0x3C, 0xA0, 0xFC, 0xB0, + 0x6D, 0x86, 0xBA, 0x04, 0xAC, 0x24, 0x24, 0x81, 0x86, 0x3A, 0xD7, 0x3E, 0xD0, 0xC4, 0x27, 0x9C, + 0x58, 0x9D, 0x84, 0x91, 0xC0, 0xEA, 0x2D, 0xB5, 0x5E, 0x0F, 0xA3, 0xEF, 0xF5, 0x0C, 0xC6, 0x30, + 0x0F, 0xA8, 0x27, 0x94, 0x92, 0xE1, 0x1E, 0x86, 0xB7, 0x4C, 0x3C, 0x06, 0x3C, 0x5A, 0x28, 0xA9, + 0x4B, 0x2A, 0x69, 0xA2, 0x2E, 0xB0, 0x25, 0xD5, 0x83, 0x1C, 0x4B, 0xC9, 0x95, 0x50, 0xF5, 0x61, + 0x24, 0x44, 0x14, 0x4A, 0x93, 0x5B, 0x08, 0xAC, 0x49, 0xAB, 0x79, 0xF1, 0xE8, 0x46, 0xD6, 0x6B, + 0xBF, 0x44, 0xBE, 0x0D, 0x7A, 0x15, 0xCC, 0x23, 0x41, 0x9D, 0x04, 0x6C, 0xCC, 0x9D, 0x90, 0xF9, + 0x7E, 0x40, 0x4B, 0x56, 0xEB, 0x64, 0x49, 0x60, 0xF8, 0x44, 0x10, 0x87, 0x85, 0x64, 0x4C, 0x1B, + 0x31, 0x1F, 0x03, 0x34, 0xA5, 0xBB, 0x3B, 0x16, 0xFB, 0xD0, 0xBD, 0xB8, 0x9A, 0x36, 0xDF, 0xBD, + 0x1E, 0x47, 0x1D, 0xF8, 0xE7, 0xBC, 0x37, 0x98, 0x1C, 0x0F, 0xC6, 0x30, 0xEA, 0xE2, 0xB4, 0xF3, + 0xFE, 0xB0, 0xF3, 0x1E, 0x7E, 0x0E, 0x5B, 0xB5, 0xAF, 0xA3, 0x6F, 0xB8, 0xD0, 0x7D, 0xED, 0x77, + 0xFB, 0x83, 0xE3, 0x4E, 0xE7, 0x5D, 0xE3, 0xCD, 0xF9, 0xF4, 0xE3, 0xBB, 0x5D, 0x04, 0x77, 0x83, + 0xE6, 0xD5, 0x87, 0x49, 0x73, 0xB0, 0xF5, 0x32, 0xF4, 0x4F, 0xFC, 0x89, 0x17, 0x0E, 0x3A, 0xEF, + 0x3F, 0x5E, 0xDD, 0x5D, 0x87, 0x83, 0x71, 0xEF, 0x63, 0x6B, 0xF2, 0x79, 0xEB, 0x43, 0xEF, 0xF3, + 0xC7, 0x57, 0xB7, 0xF4, 0xD3, 0xC9, 0xDB, 0xCF, 0xFD, 0x29, 0x20, 0x1C, 0x45, 0xBD, 0xC1, 0x55, + 0xF7, 0x43, 0x77, 0xFC, 0xB9, 0xEB, 0x1D, 0xDF, 0x0F, 0x83, 0xF3, 0xEE, 0xEB, 0xCE, 0xB0, 0xB3, + 0xE5, 0x51, 0x3A, 0xEE, 0x5F, 0x75, 0xB3, 0x37, 0xEF, 0x2E, 0xC6, 0x8C, 0x4D, 0x7A, 0x9F, 0xCF, + 0xFB, 0xDE, 0xE1, 0xF3, 0xD3, 0xC1, 0x49, 0x87, 0x4D, 0xCE, 0xDF, 0x5E, 0x35, 0x6F, 0x5F, 0xBF, + 0x3B, 0x3C, 0xF2, 0xAE, 0xDF, 0x5E, 0xEF, 0x1E, 0x6D, 0x37, 0x7E, 0xFB, 0xED, 0xCC, 0xBF, 0x60, + 0xBC, 0x7F, 0xF7, 0xBD, 0x33, 0x3E, 0x9C, 0xBE, 0x78, 0x48, 0xFB, 0x93, 0x37, 0x77, 0xBC, 0xF1, + 0x21, 0xFA, 0xFA, 0xE6, 0xE1, 0x0C, 0xFE, 0xBB, 0xBC, 0xAC, 0x0D, 0x7B, 0xAD, 0x74, 0xF0, 0xFE, + 0xCD, 0x87, 0xAD, 0xF4, 0xE5, 0xF3, 0xB8, 0x7B, 0x74, 0x74, 0x17, 0x0E, 0x2F, 0x1B, 0xA1, 0x7F, + 0x3B, 0x12, 0x2F, 0xB6, 0x45, 0x7C, 0x3D, 0xCE, 0x3E, 0x7F, 0x7B, 0xFE, 0x76, 0xD2, 0xB8, 0xA0, + 0xE4, 0x7A, 0x52, 0x7B, 0xF8, 0xFE, 0xF0, 0x62, 0xD2, 0x3F, 0xB9, 0x3B, 0x0F, 0xC8, 0xFD, 0xF9, + 0xB9, 0xF7, 0x3D, 0xAC, 0x05, 0xE4, 0xE5, 0x45, 0x3F, 0x20, 0x49, 0x6B, 0xE0, 0x77, 0x1A, 0xB5, + 0xC3, 0xAD, 0xCE, 0x8E, 0x48, 0xAE, 0x0E, 0xF9, 0xD1, 0xF6, 0xD7, 0xDE, 0x8B, 0x6E, 0xB7, 0x15, + 0x0D, 0xBF, 0x6D, 0xBD, 0xBE, 0xDD, 0x7D, 0x3D, 0xD8, 0x7D, 0x3F, 0x7C, 0xDF, 0xE9, 0xED, 0x74, + 0x07, 0xE4, 0xBA, 0xF7, 0xBE, 0x33, 0xDA, 0x19, 0x4E, 0x26, 0xEF, 0xDE, 0xF5, 0x5F, 0xF9, 0x9D, + 0xEF, 0x49, 0xE7, 0x62, 0xDA, 0xB9, 0x3F, 0x1E, 0x74, 0x4E, 0x6A, 0xEF, 0x8E, 0xCF, 0x9A, 0xAD, + 0xDE, 0xF5, 0xF6, 0xF8, 0x6C, 0x77, 0xDA, 0x4D, 0x8F, 0x3B, 0xEF, 0xBB, 0xCD, 0xF1, 0xDB, 0x5A, + 0x48, 0x3E, 0x47, 0x87, 0xDB, 0xE3, 0x37, 0xBB, 0xEC, 0xF2, 0x9A, 0x74, 0xDE, 0x74, 0xDF, 0xA6, + 0xEC, 0x2A, 0x3C, 0x19, 0x34, 0x3B, 0x9D, 0xD3, 0x0B, 0xFA, 0xEA, 0x70, 0x9B, 0xBC, 0xDB, 0xF2, + 0x3E, 0x82, 0xFE, 0x07, 0x9F, 0xE8, 0x6F, 0xB5, 0xCE, 0xF4, 0xA2, 0x19, 0x78, 0x2F, 0x69, 0xFF, + 0xE4, 0xBA, 0x2F, 0x6F, 0xE7, 0x38, 0x78, 0xD5, 0xBF, 0xED, 0x65, 0xEF, 0xC3, 0xC3, 0x43, 0x53, + 0xE3, 0x51, 0x3D, 0xA1, 0x31, 0x25, 0xA2, 0x1C, 0xAE, 0x16, 0xFE, 0x01, 0xB6, 0xB5, 0xB4, 0xC2, + 0xDC, 0x4F, 0x05, 0xBD, 0x17, 0x75, 0x9F, 0x7A, 0x51, 0x42, 0xE4, 0x1E, 0x40, 0xA0, 0x09, 0x9A, + 0xD8, 0xFC, 0x77, 0x19, 0x3F, 0x35, 0x15, 0x3F, 0x35, 0xC2, 0x7D, 0xCD, 0x28, 0x1C, 0x01, 0x83, + 0x87, 0x4F, 0xEF, 0x98, 0x47, 0xEB, 0x31, 0xBB, 0xA7, 0x41, 0x5D, 0x22, 0x3B, 0x4D, 0x73, 0x26, + 0xFD, 0xAD, 0xD8, 0x46, 0x38, 0x98, 0x9A, 0xA4, 0x5A, 0x2C, 0xF8, 0x5F, 0x89, 0x47, 0x21, 0xB0, + 0x81, 0xCB, 0x84, 0xF8, 0xAB, 0x7C, 0x27, 0x4A, 0xEA, 0xC3, 0x6C, 0x3C, 0x62, 0xF7, 0xE0, 0xD0, + 0x23, 0xC6, 0x99, 0xA0, 0x5A, 0x2B, 0x9D, 0xFF, 0x5E, 0x90, 0xB9, 0xA5, 0x0F, 0xA3, 0x84, 0x84, + 0x34, 0xD5, 0xFE, 0x22, 0x99, 0xD9, 0x28, 0x89, 0xC2, 0x65, 0x10, 0x99, 0x8B, 0xA8, 0x34, 0x99, + 0xCF, 0x9F, 0x65, 0x71, 0x10, 0x11, 0x10, 0x73, 0x4D, 0xE4, 0x50, 0xF1, 0x34, 0x91, 0x6E, 0xB5, + 0x88, 0xAB, 0xB9, 0x9B, 0x6D, 0xA1, 0x5B, 0x96, 0xDD, 0x7A, 0x6B, 0x67, 0xE9, 0xBA, 0x75, 0xB9, + 0x17, 0xE3, 0xFD, 0x9A, 0x4C, 0x81, 0xF1, 0xA0, 0x14, 0xEE, 0x9E, 0x09, 0x50, 0xE9, 0x13, 0x87, + 0xCB, 0x43, 0xF2, 0xC8, 0xB0, 0x60, 0x40, 0x05, 0xEA, 0x96, 0x8C, 0xD4, 0x85, 0x24, 0xB0, 0x6F, + 0xFE, 0x8C, 0xCA, 0xBC, 0x67, 0x3D, 0x8B, 0x13, 0xB8, 0x0D, 0x3A, 0xFD, 0x11, 0xCD, 0x42, 0xA6, + 0x2A, 0x6D, 0x45, 0x53, 0x65, 0xBC, 0x5C, 0x84, 0x65, 0xDA, 0x93, 0xBC, 0x16, 0xA4, 0x1F, 0x4B, + 0x05, 0xE0, 0x05, 0x37, 0xCF, 0x91, 0x9B, 0x1F, 0x6A, 0x75, 0x7B, 0xF7, 0x97, 0x9C, 0x87, 0x9D, + 0xE6, 0x2F, 0x73, 0x3B, 0xDF, 0x5B, 0xA4, 0xE4, 0x56, 0x13, 0xFE, 0x29, 0x32, 0xEF, 0x8B, 0x25, + 0x0B, 0xC3, 0xE7, 0xF8, 0xA7, 0x60, 0x10, 0xE9, 0x94, 0x80, 0xDB, 0x3B, 0x2F, 0x5F, 0xF8, 0xC3, + 0x02, 0x98, 0x0B, 0xF6, 0x24, 0x3C, 0x21, 0x3E, 0xCB, 0x52, 0xE7, 0x79, 0xF3, 0x97, 0x5C, 0x9F, + 0x5B, 0x3B, 0x28, 0xFB, 0xE2, 0x2E, 0x71, 0xB2, 0xB4, 0xD8, 0x34, 0x66, 0x5C, 0xDB, 0x4A, 0x35, + 0xBC, 0x6F, 0x92, 0x2C, 0x0C, 0xB3, 0x92, 0xED, 0xE7, 0xBF, 0x2F, 0x4D, 0x13, 0xF7, 0xCF, 0x9A, + 0xBF, 0xCC, 0x44, 0x02, 0xD9, 0x64, 0x04, 0xB9, 0xC6, 0x49, 0x22, 0x41, 0x04, 0x35, 0x9A, 0xE6, + 0x1C, 0x84, 0x5B, 0x03, 0xD8, 0xDE, 0x6D, 0xFA, 0x74, 0x6C, 0xCE, 0xE7, 0x7B, 0x0D, 0x99, 0xD7, + 0xA0, 0x6C, 0xF1, 0x12, 0x16, 0x8B, 0xFD, 0x51, 0xC6, 0x3D, 0xE4, 0x41, 0x1B, 0x53, 0x83, 0x9A, + 0xB3, 0x84, 0x8A, 0x2C, 0xE1, 0x9A, 0x1F, 0x79, 0x19, 0x1A, 0xBB, 0x3D, 0xA6, 0xE2, 0x58, 0xD9, + 0x7D, 0xF7, 0xE1, 0x8D, 0x0F, 0x3B, 0xE6, 0x0B, 0x04, 0x6F, 0x2D, 0x02, 0x38, 0x30, 0x9C, 0x97, + 0xE3, 0x54, 0xF6, 0x43, 0x82, 0x01, 0x22, 0xEF, 0xE8, 0x83, 0x41, 0x2D, 0xB1, 0x40, 0xA4, 0x36, + 0xAE, 0x1B, 0xC5, 0x2E, 0x80, 0x71, 0x73, 0x76, 0x07, 0x4A, 0x20, 0x2E, 0xFD, 0x22, 0x6E, 0x2C, + 0xE6, 0x72, 0xF8, 0x69, 0xE7, 0xBB, 0xC9, 0x1E, 0x3B, 0xA8, 0xB7, 0x1C, 0xB2, 0xCF, 0x0E, 0x5A, + 0xE0, 0x5E, 0x65, 0x6E, 0xE4, 0xB9, 0xAF, 0x58, 0x40, 0x07, 0xB9, 0xC3, 0xE1, 0x31, 0x48, 0x6C, + 0xB1, 0x85, 0x28, 0xE2, 0x5B, 0xCD, 0xE6, 0x86, 0x4B, 0x0F, 0x48, 0x00, 0x39, 0xCC, 0xD0, 0x8F, + 0xAF, 0xAE, 0x2E, 0xAE, 0xBE, 0xE8, 0x35, 0x5A, 0xD3, 0x6F, 0x1C, 0x4D, 0xAF, 0x71, 0xD3, 0x11, + 0x76, 0x42, 0x47, 0x09, 0x4D, 0x27, 0x97, 0x44, 0x4C, 0x8C, 0xD4, 0xBE, 0x23, 0x41, 0x56, 0x16, + 0x84, 0xA1, 0xDC, 0xC8, 0xA2, 0x70, 0x39, 0x9D, 0x6A, 0xAF, 0x40, 0xCD, 0x47, 0x90, 0xEA, 0xDA, + 0xC2, 0x26, 0x71, 0x4C, 0xB9, 0x6F, 0xE8, 0x31, 0x20, 0xEA, 0x16, 0x35, 0xAD, 0x84, 0x7E, 0xCB, + 0x68, 0x2A, 0x52, 0x1B, 0x2C, 0xD7, 0xD0, 0x2F, 0x07, 0x7D, 0xDD, 0xD2, 0x1B, 0xE8, 0x47, 0x3A, + 0xF0, 0x46, 0xCC, 0x39, 0x52, 0x89, 0x5C, 0xD0, 0xA4, 0x3E, 0xCC, 0xC0, 0xA0, 0xB8, 0x6E, 0xB6, + 0x23, 0x9B, 0x71, 0x4E, 0x93, 0x93, 0xFE, 0xD9, 0xA9, 0xAB, 0x5F, 0x29, 0x46, 0xB4, 0x53, 0x28, + 0x48, 0x74, 0x4B, 0x5E, 0x51, 0x7E, 0xC8, 0xE1, 0x84, 0x05, 0xBE, 0x11, 0x99, 0x6D, 0x24, 0xE1, + 0x49, 0x12, 0xB2, 0x40, 0x01, 0x0A, 0x9E, 0x2D, 0x1E, 0x62, 0xEA, 0xEA, 0x23, 0x50, 0x86, 0x6E, + 0x79, 0x76, 0x98, 0x05, 0x82, 0xC5, 0x01, 0x75, 0x37, 0x5A, 0x30, 0xE3, 0x60, 0x41, 0xAE, 0x8E, + 0xB9, 0x19, 0x61, 0xCC, 0x77, 0x75, 0x15, 0xA1, 0xF2, 0xB8, 0xB6, 0xEE, 0x14, 0x4F, 0x9D, 0x92, + 0x56, 0x4E, 0x49, 0xCB, 0xB8, 0x4A, 0xE0, 0x34, 0x3F, 0x18, 0xC3, 0x3C, 0xCE, 0xD4, 0x51, 0x05, + 0xCC, 0xA7, 0x23, 0x02, 0x9C, 0x7C, 0x40, 0x6D, 0xBA, 0x7A, 0x63, 0xDD, 0x41, 0xA9, 0x3A, 0xC8, + 0xAF, 0x6A, 0xC4, 0x2F, 0x6B, 0x44, 0xDD, 0xEE, 0x3A, 0x64, 0x5F, 0x21, 0x07, 0x55, 0xE4, 0xA0, + 0x8C, 0x7C, 0x28, 0x8D, 0x64, 0x1D, 0x72, 0xA0, 0x90, 0x93, 0x8A, 0x88, 0x89, 0x14, 0x51, 0x85, + 0xBD, 0x3A, 0x6A, 0x13, 0x05, 0xD2, 0xAD, 0xA4, 0x22, 0x66, 0x62, 0x83, 0x97, 0x92, 0x61, 0x40, + 0x7D, 0x77, 0xA3, 0x09, 0x33, 0x2C, 0xB6, 0xDD, 0xAD, 0xE6, 0x9A, 0x33, 0x12, 0x75, 0x46, 0x56, + 0x65, 0x30, 0x2B, 0x33, 0xA8, 0xF5, 0xC8, 0x1D, 0xD5, 0xD6, 0x31, 0x98, 0x99, 0x56, 0x60, 0x47, + 0xDC, 0x0B, 0x98, 0x77, 0xEB, 0x2E, 0xBD, 0xC5, 0x9C, 0xB1, 0x85, 0x85, 0x5A, 0x5C, 0x06, 0xBA, + 0x01, 0x94, 0x5E, 0x8B, 0xA5, 0x7C, 0x80, 0xFA, 0x9E, 0x5B, 0xD9, 0x5A, 0x02, 0xDC, 0xA6, 0xF7, + 0xD4, 0x3B, 0x8C, 0xC2, 0x90, 0xA0, 0xED, 0xA6, 0xC0, 0x41, 0x3E, 0xD1, 0xCD, 0xB9, 0x15, 0xAD, + 0xC5, 0x79, 0xC2, 0x45, 0x2C, 0x7F, 0x3D, 0x8B, 0x23, 0x03, 0x5C, 0xCE, 0xF5, 0x6C, 0xD4, 0x61, + 0x6A, 0x83, 0x1E, 0xC7, 0x62, 0xF2, 0x13, 0x17, 0x2A, 0x0C, 0x54, 0xA2, 0x7C, 0x69, 0xDE, 0x58, + 0x0B, 0x91, 0x56, 0x7C, 0xEA, 0xA2, 0xB7, 0xE2, 0x54, 0xA8, 0xBC, 0x8A, 0x5D, 0x9A, 0x4B, 0x1D, + 0x94, 0x61, 0xB9, 0xBD, 0x2F, 0xA0, 0xFA, 0x7C, 0x0E, 0xE7, 0x01, 0xFF, 0x13, 0x68, 0xF9, 0xE8, + 0x5F, 0x17, 0x60, 0xC9, 0xA3, 0x34, 0x78, 0x8B, 0xBB, 0x0D, 0xE3, 0xC0, 0xF9, 0x8F, 0x6D, 0x7C, + 0xF9, 0x1F, 0xFB, 0xA6, 0x66, 0x9A, 0x07, 0xFF, 0x6A, 0x48, 0x0D, 0x1B, 0xC2, 0xFC, 0xD2, 0xBA, + 0xB1, 0x08, 0x80, 0xED, 0x7F, 0x9B, 0xFF, 0xB1, 0x25, 0xB8, 0x02, 0x6B, 0xDF, 0x45, 0x90, 0x49, + 0xF0, 0x24, 0x34, 0xB0, 0x68, 0xA4, 0x91, 0xCD, 0x4D, 0x43, 0xB8, 0xA4, 0x72, 0x8D, 0x35, 0x51, + 0xD3, 0x6D, 0x88, 0x53, 0x50, 0x5B, 0xAC, 0x04, 0xBF, 0x3E, 0x24, 0x7A, 0x15, 0x5B, 0x17, 0x00, + 0xC9, 0x3D, 0xCA, 0x0C, 0x3D, 0x22, 0x97, 0x52, 0xCB, 0x0C, 0x02, 0x42, 0xA7, 0x89, 0xE7, 0x2A, + 0xAD, 0x1D, 0x14, 0x30, 0x17, 0xA2, 0xE0, 0xBC, 0x1C, 0x2D, 0x15, 0xEA, 0xAA, 0xFD, 0x17, 0x0A, + 0xA3, 0xD6, 0x12, 0x8A, 0x04, 0x31, 0xAD, 0xD8, 0x79, 0xC6, 0x72, 0x75, 0x4C, 0x59, 0xBA, 0x35, + 0x59, 0x5D, 0x96, 0xAD, 0x04, 0xAE, 0x2F, 0x8D, 0xFE, 0xD7, 0x3D, 0x16, 0x8E, 0xB5, 0x12, 0x3F, + 0xF8, 0x97, 0xFB, 0x2B, 0x46, 0xE4, 0xCD, 0x3F, 0xBC, 0x21, 0x70, 0x05, 0xA6, 0x41, 0x6D, 0x1E, + 0x4D, 0x0D, 0xB3, 0xF6, 0xAB, 0xAE, 0x49, 0x8A, 0xAE, 0x1E, 0x92, 0xFB, 0xBC, 0xA7, 0xC4, 0x8C, + 0xD7, 0xD6, 0x70, 0x5E, 0xB4, 0x28, 0xF9, 0x82, 0xEC, 0xE6, 0x48, 0x26, 0xA2, 0xB6, 0x56, 0x64, + 0x52, 0xD5, 0xCA, 0xE8, 0x5A, 0x63, 0xFF, 0xD7, 0x4A, 0x40, 0xB7, 0x98, 0xBA, 0x4E, 0x15, 0x8C, + 0xB3, 0x00, 0x1C, 0x93, 0x3E, 0x1D, 0x69, 0x03, 0x26, 0x03, 0x75, 0x35, 0x46, 0x5A, 0x81, 0xC1, + 0xCC, 0x03, 0xC3, 0x2B, 0xFB, 0xF3, 0x1E, 0x16, 0xBF, 0xFB, 0x97, 0xAA, 0xAA, 0x81, 0xD4, 0x8B, + 0x33, 0x5D, 0x59, 0x59, 0xD5, 0x4B, 0xE0, 0xD2, 0x08, 0xA0, 0x5B, 0x8B, 0x3C, 0x3A, 0x8C, 0xFC, + 0x87, 0x52, 0xF6, 0x4D, 0xBB, 0x0F, 0x87, 0x01, 0x49, 0xD3, 0x73, 0xB8, 0x01, 0x43, 0xF7, 0x42, + 0x50, 0xB8, 0xB2, 0xC2, 0xFD, 0xE6, 0xE6, 0x66, 0x15, 0x29, 0xA1, 0x21, 0x14, 0xDB, 0x8A, 0x2B, + 0xF0, 0x49, 0xD3, 0xF1, 0x81, 0x30, 0x18, 0xD2, 0x1A, 0xC6, 0xF0, 0x25, 0xE3, 0x47, 0x5C, 0x71, + 0xF4, 0xF4, 0x22, 0xA6, 0xFC, 0x33, 0xDC, 0x95, 0x32, 0xCB, 0x1A, 0xAD, 0xA6, 0x68, 0xFA, 0x8F, + 0xD8, 0x3E, 0xCA, 0x0D, 0x76, 0xC1, 0x7A, 0xBA, 0x56, 0xA1, 0xFC, 0x9F, 0x61, 0xB9, 0x94, 0x28, + 0xD6, 0x70, 0x9C, 0x40, 0x80, 0x5A, 0xC3, 0x31, 0xC4, 0x1A, 0x41, 0x17, 0xFC, 0x26, 0x6B, 0xF9, + 0xCD, 0xFE, 0x19, 0x7E, 0x97, 0x76, 0x1E, 0x15, 0x25, 0x91, 0xAA, 0xAF, 0x50, 0x02, 0x9F, 0xDD, + 0xE9, 0xA6, 0x15, 0xB9, 0x55, 0x0A, 0x50, 0x1B, 0x46, 0x41, 0xD0, 0x8F, 0xE2, 0x83, 0x27, 0xD6, + 0x9D, 0xC5, 0x7A, 0x31, 0xC8, 0xD9, 0x5C, 0x6E, 0xB1, 0xBC, 0xB5, 0x44, 0x4F, 0xA1, 0xEC, 0x5F, + 0x4B, 0x15, 0x01, 0x3F, 0x23, 0x8B, 0x7B, 0xAC, 0xD4, 0xA5, 0x36, 0x28, 0x0F, 0x56, 0x3F, 0xD5, + 0x3C, 0xCB, 0x5F, 0xCC, 0xAE, 0x6B, 0x51, 0x9B, 0xC0, 0x38, 0x57, 0x92, 0x8B, 0x4A, 0xB2, 0xC8, + 0x13, 0x01, 0xA8, 0x58, 0xC7, 0x2E, 0xC4, 0x4D, 0x6B, 0x7A, 0x7C, 0xBF, 0x5C, 0x83, 0xC2, 0xDF, + 0xF5, 0xD5, 0x12, 0x33, 0x08, 0xC4, 0xD3, 0x95, 0x4B, 0x29, 0x5F, 0x37, 0x29, 0x8A, 0x0E, 0x62, + 0x47, 0xA3, 0x51, 0x4A, 0xC5, 0x47, 0x0C, 0x49, 0x56, 0xB2, 0x98, 0x9F, 0xC8, 0x90, 0x04, 0x8C, + 0x45, 0x3C, 0x8C, 0xB2, 0x94, 0x46, 0x99, 0xA8, 0xA4, 0x16, 0x63, 0x21, 0xCC, 0x5E, 0xFA, 0xE7, + 0x9F, 0x8B, 0xC9, 0x7E, 0x5A, 0x0B, 0x96, 0xD3, 0xEB, 0x3D, 0xBF, 0x34, 0xD9, 0xF7, 0x6B, 0x89, + 0xB9, 0x7A, 0xE9, 0xFF, 0x67, 0x4B, 0x21, 0x65, 0x4B, 0xF1, 0xB0, 0x54, 0x2E, 0x62, 0x62, 0x29, + 0xE6, 0xC9, 0x82, 0x91, 0x97, 0x7C, 0x16, 0x0D, 0x1A, 0x2B, 0x25, 0x55, 0x9E, 0x97, 0x7D, 0x95, + 0x43, 0x40, 0x59, 0x71, 0xE5, 0x35, 0x11, 0x06, 0x34, 0xE0, 0x63, 0x64, 0xF2, 0x41, 0xEB, 0xA7, + 0xD1, 0x94, 0x26, 0x87, 0x24, 0xA5, 0x06, 0x24, 0xCD, 0x65, 0xDC, 0x41, 0xA8, 0xE9, 0x04, 0xEB, + 0x76, 0x6D, 0x6E, 0x12, 0x05, 0xCE, 0x33, 0x77, 0xC4, 0xB1, 0x26, 0x03, 0xF9, 0xB2, 0xCA, 0x09, + 0xD4, 0xC6, 0xBE, 0x12, 0xA4, 0x3E, 0x52, 0x25, 0xA8, 0x61, 0x5A, 0xD0, 0x76, 0xC0, 0x35, 0x5F, + 0x26, 0x51, 0x4C, 0xC6, 0xB2, 0x07, 0x83, 0x35, 0x74, 0x0F, 0xA4, 0x66, 0x6D, 0x34, 0x91, 0x60, + 0xA9, 0x73, 0x29, 0xFC, 0x66, 0xD9, 0xC2, 0x70, 0x4B, 0x57, 0xC9, 0xB0, 0xBD, 0xF4, 0xA5, 0x35, + 0x59, 0x83, 0xE0, 0x0B, 0x6C, 0x62, 0xE0, 0x1E, 0x68, 0x64, 0xF2, 0x7B, 0x00, 0x77, 0x6B, 0xB6, + 0xA3, 0x3D, 0xD6, 0x8E, 0x6A, 0x35, 0x53, 0x55, 0xE9, 0xAE, 0x0B, 0x6D, 0x4E, 0x74, 0x23, 0x0B, + 0x4B, 0x10, 0xAA, 0x9A, 0x59, 0x0C, 0x38, 0x1B, 0x81, 0xAA, 0xBA, 0xC0, 0x11, 0xD6, 0x98, 0x66, + 0xA9, 0x23, 0xF1, 0x97, 0x1D, 0xC9, 0x13, 0xB5, 0x07, 0x95, 0xF5, 0x05, 0xD4, 0x31, 0xAB, 0x25, + 0x86, 0x30, 0xD3, 0x29, 0x13, 0xDE, 0x04, 0x03, 0x90, 0x07, 0x5A, 0xD5, 0x05, 0x14, 0xB5, 0x8E, + 0x1C, 0x4D, 0x44, 0xB8, 0x1C, 0x05, 0xF9, 0xF0, 0x6B, 0x9A, 0x0F, 0xBC, 0xB4, 0x18, 0xDD, 0x97, + 0x80, 0x50, 0xD2, 0xE6, 0xE0, 0x88, 0x8F, 0xF2, 0x21, 0xF4, 0xB2, 0x05, 0x9D, 0x02, 0x58, 0xFC, + 0xC6, 0x71, 0x3E, 0x8A, 0x27, 0xC5, 0x68, 0x42, 0xEF, 0x17, 0x78, 0x51, 0x01, 0xF5, 0xA9, 0xEE, + 0x28, 0x1B, 0xDB, 0x68, 0xCE, 0xF3, 0x41, 0x6B, 0x29, 0x7F, 0xF0, 0xFF, 0x28, 0x7F, 0xCC, 0xC7, + 0x85, 0x34, 0x71, 0x31, 0x1A, 0xB3, 0x42, 0x96, 0x61, 0x18, 0xFF, 0x90, 0x93, 0xA4, 0xD4, 0x13, + 0x97, 0x7A, 0x5A, 0xF1, 0xB3, 0xB6, 0x53, 0x98, 0x8E, 0x31, 0xAA, 0xF8, 0xE3, 0xC8, 0xF6, 0xF0, + 0xF7, 0x3C, 0xF2, 0x65, 0x6D, 0x69, 0x5A, 0xA1, 0x31, 0x82, 0x3A, 0x57, 0x37, 0xCB, 0x7E, 0x9A, + 0xFD, 0xB7, 0xAD, 0xE8, 0xD1, 0xF1, 0xE9, 0x71, 0xFF, 0xB8, 0x5C, 0x38, 0x23, 0xE7, 0x25, 0x93, + 0x8A, 0x2B, 0x5D, 0xFA, 0xB2, 0x22, 0x80, 0x02, 0x1B, 0x45, 0x01, 0x7B, 0xDD, 0xDC, 0x54, 0x7E, + 0xF1, 0xB6, 0x77, 0x71, 0x6E, 0xC7, 0x24, 0x01, 0x8F, 0x24, 0x15, 0xE6, 0xC2, 0x82, 0x44, 0xF9, + 0xE0, 0xD7, 0xC7, 0xA5, 0x72, 0x5D, 0x7E, 0x61, 0x70, 0xC4, 0xDC, 0x52, 0xA7, 0xA9, 0x7E, 0x78, + 0xE2, 0x62, 0x5D, 0x99, 0xBF, 0x04, 0x41, 0x72, 0x1A, 0x2D, 0x13, 0x55, 0x11, 0x67, 0x46, 0xE5, + 0x30, 0x2F, 0xEE, 0xB2, 0x75, 0x0D, 0xD3, 0xC8, 0xB4, 0xC4, 0x84, 0xA5, 0xE5, 0x46, 0xA5, 0x12, + 0x14, 0xFE, 0xA2, 0xB6, 0xE7, 0x8B, 0x91, 0x24, 0xB7, 0x5A, 0x73, 0xAB, 0x6F, 0x41, 0x2A, 0x3E, + 0x58, 0x04, 0x23, 0x66, 0x39, 0xDB, 0x16, 0x77, 0xA3, 0x43, 0xEE, 0x61, 0x5C, 0x7F, 0xBA, 0x35, + 0x78, 0xD2, 0x3C, 0x79, 0x61, 0x9E, 0xFC, 0xB1, 0x7B, 0x2E, 0x1C, 0x45, 0xF9, 0xDA, 0xE2, 0x98, + 0xF6, 0x10, 0x58, 0xBB, 0x6D, 0x2F, 0x7D, 0x18, 0x20, 0xD2, 0x83, 0xCB, 0x00, 0xF4, 0x63, 0x58, + 0xFF, 0x4A, 0xEE, 0x88, 0x7A, 0x09, 0xAA, 0xA2, 0xAD, 0x73, 0x54, 0xD8, 0xEE, 0xFD, 0x81, 0xA3, + 0xF2, 0xCE, 0x65, 0x18, 0x48, 0x97, 0xC3, 0x92, 0x37, 0x8B, 0x75, 0xC1, 0x61, 0x19, 0x31, 0x64, + 0x6C, 0x00, 0xE3, 0xCD, 0x5D, 0x49, 0x13, 0xD5, 0x1C, 0xB4, 0xF0, 0x1B, 0x08, 0x8A, 0x4F, 0x39, + 0xCE, 0x9A, 0x38, 0xAD, 0x62, 0x72, 0xC5, 0x23, 0xC8, 0x4A, 0x67, 0x89, 0xC0, 0x6E, 0x10, 0x0D, + 0x0D, 0x7C, 0x64, 0x9A, 0xA1, 0xB6, 0x1D, 0x3E, 0x37, 0xD7, 0xBC, 0xD9, 0x54, 0xFA, 0x4B, 0x62, + 0x79, 0xD5, 0xB0, 0x8B, 0x1C, 0x56, 0xCC, 0x75, 0x7D, 0x1F, 0xF4, 0xA3, 0x4E, 0x29, 0xAF, 0x48, + 0xA4, 0x53, 0xD1, 0x83, 0xC4, 0x86, 0xA2, 0x41, 0xBE, 0x91, 0x40, 0x44, 0x72, 0x4A, 0x33, 0x5D, + 0xC7, 0xCA, 0xD2, 0x0B, 0x28, 0x49, 0x7A, 0xB2, 0x73, 0x95, 0x49, 0x6B, 0x25, 0x06, 0xFE, 0xC8, + 0xD7, 0xF0, 0xC7, 0xA1, 0xD0, 0xA3, 0x83, 0x9B, 0x49, 0x2B, 0x83, 0xA4, 0x23, 0x64, 0x83, 0xA9, + 0x37, 0xE4, 0xBB, 0xA8, 0x2D, 0x2F, 0xCB, 0xB4, 0x16, 0x50, 0x70, 0x71, 0x83, 0xBB, 0x11, 0x30, + 0x52, 0x5A, 0xC4, 0x9E, 0x94, 0xA8, 0xC7, 0x8F, 0x10, 0x1F, 0x53, 0x4A, 0x20, 0x06, 0x20, 0xA6, + 0x40, 0xD0, 0xA7, 0x42, 0x8A, 0x54, 0xE6, 0x92, 0x53, 0x2A, 0x20, 0xCA, 0x48, 0xCD, 0xE2, 0xC1, + 0x85, 0x78, 0xD4, 0x46, 0xD6, 0x80, 0xFD, 0xDC, 0xBD, 0x73, 0x33, 0xDE, 0x90, 0x68, 0x09, 0x56, + 0x36, 0x3D, 0x9A, 0xA6, 0x52, 0x5C, 0x54, 0xC7, 0x19, 0xF8, 0xA8, 0xA1, 0x03, 0x5A, 0x23, 0x84, + 0x11, 0x1E, 0x84, 0x8A, 0x01, 0x40, 0x7F, 0x42, 0xC3, 0x1C, 0x22, 0x70, 0x08, 0x20, 0x82, 0xA0, + 0x7F, 0x49, 0x0D, 0xF7, 0x64, 0x05, 0xC9, 0xF8, 0xD8, 0x6D, 0x35, 0xF0, 0x9D, 0x66, 0x95, 0xEC, + 0x20, 0xA5, 0xBD, 0x68, 0x24, 0xFA, 0x64, 0x98, 0x1A, 0x50, 0x00, 0xAC, 0xD9, 0x01, 0xA0, 0x1E, + 0x24, 0x5E, 0x63, 0x2B, 0x3F, 0xEF, 0x04, 0x2A, 0xBB, 0x00, 0xAB, 0xBB, 0x8E, 0x87, 0x5F, 0x39, + 0x4F, 0x19, 0xA7, 0x39, 0x26, 0x00, 0x7B, 0x93, 0x68, 0x7A, 0x99, 0x30, 0x2E, 0xCE, 0x64, 0x1B, + 0x6A, 0x6C, 0xB4, 0xE4, 0xF5, 0xA9, 0x87, 0x15, 0x79, 0x3F, 0xC5, 0x8B, 0xCB, 0x0C, 0xF3, 0xBA, + 0x53, 0x79, 0x77, 0xB1, 0x86, 0x70, 0x21, 0x50, 0x66, 0x38, 0xB3, 0x29, 0x74, 0xB0, 0xFA, 0xA1, + 0x48, 0x82, 0x7A, 0x4F, 0xB7, 0x42, 0xE2, 0xC1, 0x44, 0xED, 0x81, 0xF9, 0xDC, 0xC2, 0xD8, 0xE1, + 0x94, 0x83, 0x5A, 0x0A, 0xB5, 0x02, 0x45, 0xC6, 0x95, 0xCD, 0x98, 0x35, 0x1D, 0x6A, 0x58, 0x88, + 0x61, 0xE0, 0xAF, 0xFE, 0x05, 0x0F, 0x1E, 0x1C, 0xC8, 0x55, 0x3F, 0xE1, 0x23, 0xE3, 0x7E, 0xF4, + 0x23, 0x3E, 0x3E, 0xAF, 0xF0, 0xF1, 0x79, 0x1D, 0x1F, 0xB4, 0xAA, 0x3C, 0x98, 0x0C, 0x80, 0xEC, + 0x19, 0xE1, 0x64, 0x4C, 0x13, 0x58, 0xC0, 0x43, 0x50, 0x25, 0x7F, 0x8B, 0xB3, 0x84, 0xFE, 0x98, + 0xB3, 0xDE, 0x84, 0x8D, 0xC4, 0x23, 0xFE, 0x8A, 0xD5, 0xFF, 0x82, 0x4B, 0x3C, 0x70, 0x3D, 0x97, + 0x79, 0x6D, 0x5A, 0x49, 0x28, 0x3F, 0x7E, 0x2B, 0x91, 0x7E, 0xE4, 0x42, 0x78, 0xA9, 0x38, 0xC8, + 0xDF, 0xB7, 0xF4, 0x00, 0xBC, 0x11, 0xF8, 0x29, 0x35, 0x75, 0xBC, 0x0B, 0xA5, 0xFC, 0x29, 0x30, + 0x64, 0xA8, 0xC0, 0x47, 0xDD, 0xD9, 0xDC, 0x12, 0xAE, 0x01, 0x8A, 0xF1, 0xA3, 0x29, 0xB0, 0xEA, + 0xC9, 0x02, 0xD7, 0x9E, 0x40, 0x26, 0x04, 0x91, 0xE0, 0x48, 0xC8, 0xA7, 0x8D, 0x2F, 0x07, 0x9B, + 0x37, 0x35, 0xC8, 0x43, 0x2E, 0xFC, 0x98, 0x2E, 0x0C, 0x36, 0x6F, 0xFE, 0x6D, 0x36, 0xC6, 0xCC, + 0x5A, 0x76, 0xA4, 0x96, 0x4C, 0xF6, 0xF4, 0x0B, 0xBF, 0x71, 0x09, 0x48, 0x5D, 0x49, 0x78, 0x45, + 0x34, 0x03, 0x6B, 0x43, 0x61, 0xE1, 0x07, 0xFF, 0x47, 0x09, 0xF8, 0x91, 0x9E, 0x07, 0xCE, 0xBD, + 0xE6, 0x3D, 0x5E, 0x2F, 0x3E, 0x85, 0xE9, 0x56, 0xE9, 0xC1, 0x4A, 0xC7, 0xEF, 0x53, 0x3A, 0x76, + 0x59, 0xA2, 0x14, 0x4A, 0x14, 0x59, 0x88, 0x1A, 0x6A, 0x50, 0x0E, 0x51, 0x98, 0x89, 0x17, 0xCD, + 0x81, 0x02, 0x9B, 0x73, 0x34, 0x5B, 0x3A, 0x02, 0x0F, 0xF4, 0xF5, 0x45, 0xEE, 0xFC, 0x74, 0x76, + 0x7A, 0x22, 0x44, 0x7C, 0xA5, 0x62, 0x22, 0xD0, 0xAA, 0x2E, 0x2C, 0x2F, 0xCF, 0x9C, 0x89, 0xE4, + 0xA1, 0x28, 0x75, 0x30, 0x31, 0x28, 0x87, 0xFE, 0x74, 0x31, 0xFC, 0x0A, 0x71, 0xD6, 0xD0, 0xCF, + 0x52, 0x48, 0x58, 0x5B, 0x36, 0xA2, 0xF7, 0xFB, 0x97, 0xF6, 0xAE, 0xDD, 0x84, 0xBA, 0x00, 0xB4, + 0x0A, 0x69, 0x19, 0xEE, 0x7D, 0xFE, 0xB7, 0x90, 0xB7, 0xFF, 0x1E, 0x32, 0x83, 0xA8, 0x95, 0x42, + 0x58, 0x2A, 0xF0, 0xAB, 0xB8, 0x93, 0x24, 0x9A, 0x4A, 0xB4, 0xE3, 0x24, 0xC1, 0x4B, 0xE9, 0x43, + 0x85, 0xA2, 0x0D, 0x61, 0x31, 0xA5, 0x89, 0xE6, 0x47, 0x34, 0xD5, 0x78, 0x24, 0xB4, 0x34, 0x8B, + 0x63, 0x68, 0x5C, 0x56, 0xF4, 0x61, 0xEB, 0xC5, 0xEB, 0xCB, 0xFB, 0x8C, 0x66, 0xD4, 0xCF, 0x97, + 0x69, 0x52, 0xD1, 0x0B, 0x56, 0x50, 0xDF, 0x10, 0xEE, 0x7E, 0xB9, 0xC9, 0xEB, 0xA9, 0x8C, 0x73, + 0x8C, 0xA2, 0x1B, 0x2D, 0x35, 0x07, 0xE9, 0x26, 0x40, 0xD5, 0xE5, 0x59, 0x10, 0xCC, 0xDB, 0x2B, + 0xB4, 0xA0, 0xF1, 0x8A, 0x44, 0x24, 0x9F, 0xCB, 0x67, 0x7F, 0xE4, 0xC9, 0xA9, 0xE2, 0x82, 0x50, + 0xF2, 0x54, 0xA9, 0x36, 0xAD, 0x0D, 0x63, 0x83, 0x6A, 0x8C, 0xA7, 0x82, 0x70, 0x0F, 0xAF, 0x51, + 0xE9, 0xC2, 0x2C, 0x6A, 0x29, 0xDC, 0xDE, 0x46, 0x5F, 0xCB, 0x6D, 0xE9, 0x89, 0x7C, 0x2A, 0x25, + 0xE3, 0xAE, 0xAE, 0x63, 0x55, 0x45, 0xB1, 0x3E, 0x25, 0x61, 0x5A, 0x26, 0x5B, 0x54, 0x06, 0x26, + 0x77, 0x0B, 0x70, 0x9B, 0x06, 0x29, 0x1C, 0xBD, 0x7E, 0x7F, 0xCE, 0x46, 0xD1, 0xCE, 0x11, 0x80, + 0x69, 0xC5, 0x3E, 0x93, 0xD7, 0xE0, 0x24, 0xCC, 0x73, 0x07, 0x32, 0xE9, 0x4A, 0x03, 0x0E, 0xA9, + 0x98, 0x44, 0xFE, 0x81, 0x7E, 0xA0, 0x3B, 0x3A, 0xFC, 0xBB, 0x09, 0x35, 0x47, 0xCD, 0xA5, 0xD0, + 0xA4, 0xFA, 0x74, 0x70, 0xF5, 0x06, 0xC2, 0x53, 0x0C, 0xA5, 0x01, 0x17, 0x50, 0x34, 0xD7, 0x74, + 0x7C, 0x7A, 0x7D, 0x0C, 0x29, 0xC8, 0x7F, 0x21, 0x37, 0x66, 0xBB, 0xAA, 0x6C, 0xB8, 0xF3, 0xEA, + 0x75, 0x56, 0x2E, 0x03, 0x7A, 0x61, 0x8C, 0x58, 0x0F, 0x29, 0x7E, 0xFB, 0x7B, 0xF4, 0x9E, 0x8D, + 0x15, 0xD2, 0x6A, 0x5D, 0x6F, 0xCE, 0x76, 0x90, 0x67, 0x89, 0xD5, 0x43, 0x2C, 0x70, 0x97, 0x1F, + 0x29, 0x59, 0x95, 0x35, 0xDC, 0xF6, 0x48, 0x10, 0xE0, 0xC7, 0x5A, 0x03, 0x1B, 0x6A, 0x22, 0xB2, + 0xD4, 0x42, 0x22, 0x29, 0x08, 0x90, 0xD2, 0x3E, 0x84, 0x39, 0xD3, 0x92, 0x65, 0x86, 0xB2, 0xA1, + 0xBC, 0xFF, 0xC5, 0x9A, 0xA3, 0x64, 0x46, 0xE8, 0xCE, 0xF9, 0x6C, 0x73, 0x53, 0xD8, 0x85, 0x99, + 0x18, 0x05, 0x52, 0x8A, 0x01, 0x1C, 0x9A, 0x7D, 0x68, 0x2D, 0x8C, 0xB2, 0x90, 0x58, 0xAB, 0x3D, + 0xD2, 0xB6, 0x51, 0x55, 0x03, 0x54, 0x7C, 0x46, 0x01, 0x03, 0xCE, 0xB2, 0x24, 0x80, 0xA8, 0x8B, + 0x39, 0xBA, 0xB2, 0x2D, 0xC5, 0xBA, 0xD0, 0x84, 0x0E, 0xEC, 0x67, 0xC8, 0x12, 0x95, 0x97, 0xAD, + 0xA2, 0x27, 0x12, 0xC5, 0x77, 0x95, 0x9E, 0xC8, 0x6F, 0xE5, 0x84, 0xAA, 0xC8, 0x77, 0x88, 0x2F, + 0x13, 0x5C, 0xD4, 0xD1, 0x13, 0xA0, 0x24, 0x83, 0x52, 0x34, 0x60, 0x2A, 0x2C, 0x37, 0xEE, 0xEB, + 0xD3, 0xE9, 0xB4, 0x8E, 0xDF, 0x6A, 0xEB, 0x70, 0x82, 0xB2, 0x02, 0x5F, 0x5F, 0xC7, 0x21, 0x47, + 0x15, 0x58, 0xF8, 0x6E, 0xE1, 0xAC, 0xBA, 0xE8, 0x42, 0x7F, 0x2B, 0xDE, 0xD4, 0xAA, 0xD2, 0x59, + 0xE1, 0x73, 0x79, 0xDB, 0x7B, 0x3B, 0x2B, 0x20, 0x32, 0xC4, 0xAF, 0xB2, 0x90, 0x69, 0x20, 0x0D, + 0x3B, 0xE5, 0x46, 0x56, 0x25, 0x85, 0x65, 0x5C, 0xB0, 0xE3, 0x2C, 0x9D, 0x18, 0x33, 0x60, 0xDD, + 0x11, 0x96, 0xD2, 0x95, 0x43, 0x2D, 0x65, 0xB7, 0x0E, 0xB7, 0x0A, 0xFB, 0x70, 0x30, 0x83, 0x94, + 0x79, 0xFB, 0xF3, 0x4F, 0x39, 0x5B, 0xDE, 0xF6, 0x92, 0x62, 0x71, 0xE1, 0xF3, 0xFC, 0xA9, 0x35, + 0xAF, 0x69, 0xA5, 0xD1, 0xAF, 0xC4, 0x97, 0xBD, 0x46, 0xFE, 0x19, 0x3B, 0xFF, 0x9C, 0xAD, 0x81, + 0xB1, 0x43, 0x23, 0x2A, 0xDC, 0x4C, 0x8C, 0xEA, 0x2F, 0x34, 0xE6, 0x63, 0x79, 0x29, 0xBF, 0x2D, + 0xA0, 0x54, 0xA9, 0xD3, 0x68, 0x78, 0x3E, 0xFF, 0x9A, 0x42, 0x19, 0x1D, 0x65, 0xFE, 0x28, 0x20, + 0x09, 0xC5, 0x82, 0xA3, 0x41, 0xBE, 0x92, 0xFB, 0x46, 0xC0, 0x86, 0x69, 0x03, 0x93, 0x6D, 0xCB, + 0xDE, 0xB2, 0x77, 0x71, 0x64, 0x7F, 0x4D, 0xF7, 0x57, 0x4F, 0xD8, 0x5F, 0x34, 0x69, 0x58, 0x0B, + 0xE7, 0xB5, 0xAB, 0x8A, 0x4D, 0x6A, 0x83, 0xFB, 0xC4, 0xA7, 0x70, 0x3D, 0x6F, 0xB3, 0xCC, 0xB6, + 0x1A, 0xE4, 0x5F, 0x60, 0xD4, 0x31, 0xBA, 0x95, 0x2F, 0x92, 0xF4, 0x81, 0x7B, 0x18, 0x5B, 0x17, + 0x54, 0x26, 0x70, 0x49, 0xD5, 0x87, 0x34, 0xB9, 0xD3, 0x9C, 0x2F, 0x39, 0xC3, 0xB7, 0x3C, 0xA8, + 0x03, 0xE4, 0x37, 0x9C, 0x72, 0x39, 0xB0, 0xBF, 0x07, 0x5D, 0x33, 0x2A, 0x41, 0x79, 0xB1, 0x26, + 0x9B, 0xE6, 0x7C, 0x02, 0x82, 0x01, 0x70, 0xB1, 0xA3, 0x48, 0xCD, 0x2B, 0xCB, 0x98, 0x9B, 0x57, + 0x96, 0x54, 0xE2, 0x5F, 0x59, 0xCC, 0xDB, 0x9F, 0xFC, 0xDB, 0x4C, 0xF9, 0x7F, 0x5B, 0x28, 0x36, + 0x32, 0xF9, 0xE1, 0x09, 0xF7, 0x56, 0x3F, 0x45, 0xAD, 0x47, 0x51, 0xBB, 0xF7, 0xFF, 0x17, 0x53, + 0xE8, 0x9D, 0x36, 0x92, 0x29, 0x00, 0x00 +}; + +#define SPIFFS_MAXLENGTH_FILEPATH 32 +const char *excludeListFile = "/.exclude.files"; + +typedef struct ExcludeListS { + char *item; + ExcludeListS *next; +} ExcludeList; + +static ExcludeList *excludes = NULL; + +static bool matchWild(const char *pattern, const char *testee) { + const char *nxPat = NULL, *nxTst = NULL; + + while (*testee) { + if (( *pattern == '?' ) || (*pattern == *testee)){ + pattern++;testee++; + continue; + } + if (*pattern=='*'){ + nxPat=pattern++; nxTst=testee; + continue; + } + if (nxPat){ + pattern = nxPat+1; testee=++nxTst; + continue; + } + return false; + } + while (*pattern=='*'){pattern++;} + return (*pattern == 0); +} + +static bool addExclude(const char *item){ + size_t len = strlen(item); + if(!len){ + return false; + } + ExcludeList *e = (ExcludeList *)malloc(sizeof(ExcludeList)); + if(!e){ + return false; + } + e->item = (char *)malloc(len+1); + if(!e->item){ + free(e); + return false; + } + memcpy(e->item, item, len+1); + e->next = excludes; + excludes = e; + return true; +} + +static void loadExcludeList(fs::FS &_fs, const char *filename){ + static char linebuf[SPIFFS_MAXLENGTH_FILEPATH]; + fs::File excludeFile=_fs.open(filename, "r"); + if(!excludeFile){ + //addExclude("/*.js.gz"); + return; + } +#ifdef ESP32 + if(excludeFile.isDirectory()){ + excludeFile.close(); + return; + } +#endif + if (excludeFile.size() > 0){ + uint8_t idx; + bool isOverflowed = false; + while (excludeFile.available()){ + linebuf[0] = '\0'; + idx = 0; + int lastChar; + do { + lastChar = excludeFile.read(); + if(lastChar != '\r'){ + linebuf[idx++] = (char) lastChar; + } + } while ((lastChar >= 0) && (lastChar != '\n') && (idx < SPIFFS_MAXLENGTH_FILEPATH)); + + if(isOverflowed){ + isOverflowed = (lastChar != '\n'); + continue; + } + isOverflowed = (idx >= SPIFFS_MAXLENGTH_FILEPATH); + linebuf[idx-1] = '\0'; + if(!addExclude(linebuf)){ + excludeFile.close(); + return; + } + } + } + excludeFile.close(); +} + +static bool isExcluded(fs::FS &_fs, const char *filename) { + if(excludes == NULL){ + loadExcludeList(_fs, excludeListFile); + } + ExcludeList *e = excludes; + while(e){ + if (matchWild(e->item, filename)){ + return true; + } + e = e->next; + } + return false; +} + +// WEB HANDLER IMPLEMENTATION + +#ifdef ESP32 +SPIFFSEditor::SPIFFSEditor(const fs::FS& fs, const String& username, const String& password) +#else +SPIFFSEditor::SPIFFSEditor(const String& username, const String& password, const fs::FS& fs) +#endif +:_fs(fs) +,_username(username) +,_password(password) +,_authenticated(false) +,_startTime(0) +{} + +bool SPIFFSEditor::canHandle(AsyncWebServerRequest *request){ + if(request->url().equalsIgnoreCase("/edit")){ + if(request->method() == HTTP_GET){ + if(request->hasParam("list")) + return true; + if(request->hasParam("edit")){ + request->_tempFile = _fs.open(request->arg("edit"), "r"); + if(!request->_tempFile){ + return false; + } +#ifdef ESP32 + if(request->_tempFile.isDirectory()){ + request->_tempFile.close(); + return false; + } +#endif + } + if(request->hasParam("download")){ + request->_tempFile = _fs.open(request->arg("download"), "r"); + if(!request->_tempFile){ + return false; + } +#ifdef ESP32 + if(request->_tempFile.isDirectory()){ + request->_tempFile.close(); + return false; + } +#endif + } + request->addInterestingHeader("If-Modified-Since"); + return true; + } + else if(request->method() == HTTP_POST) + return true; + else if(request->method() == HTTP_DELETE) + return true; + else if(request->method() == HTTP_PUT) + return true; + + } + return false; +} + + +void SPIFFSEditor::handleRequest(AsyncWebServerRequest *request){ + if(_username.length() && _password.length() && !request->authenticate(_username.c_str(), _password.c_str())) + return request->requestAuthentication(); + + if(request->method() == HTTP_GET){ + if(request->hasParam("list")){ + String path = request->getParam("list")->value(); +#ifdef ESP32 + File dir = _fs.open(path); +#else + Dir dir = _fs.openDir(path); +#endif + path = String(); + String output = "["; +#ifdef ESP32 + File entry = dir.openNextFile(); + while(entry){ +#else + while(dir.next()){ + fs::File entry = dir.openFile("r"); +#endif + if (isExcluded(_fs, entry.name())) { +#ifdef ESP32 + entry = dir.openNextFile(); +#endif + continue; + } + if (output != "[") output += ','; + output += "{\"type\":\""; + output += "file"; + output += "\",\"name\":\""; + output += String(entry.name()); + output += "\",\"size\":"; + output += String(entry.size()); + output += "}"; +#ifdef ESP32 + entry = dir.openNextFile(); +#else + entry.close(); +#endif + } +#ifdef ESP32 + dir.close(); +#endif + output += "]"; + request->send(200, "application/json", output); + output = String(); + } + else if(request->hasParam("edit") || request->hasParam("download")){ + request->send(request->_tempFile, request->_tempFile.name(), String(), request->hasParam("download")); + } + else { + const char * buildTime = __DATE__ " " __TIME__ " GMT"; + if (request->header("If-Modified-Since").equals(buildTime)) { + request->send(304); + } else { + AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", edit_htm_gz, edit_htm_gz_len); + response->addHeader("Content-Encoding", "gzip"); + response->addHeader("Last-Modified", buildTime); + request->send(response); + } + } + } else if(request->method() == HTTP_DELETE){ + if(request->hasParam("path", true)){ + _fs.remove(request->getParam("path", true)->value()); + request->send(200, "", "DELETE: "+request->getParam("path", true)->value()); + } else + request->send(404); + } else if(request->method() == HTTP_POST){ + if(request->hasParam("data", true, true) && _fs.exists(request->getParam("data", true, true)->value())) + request->send(200, "", "UPLOADED: "+request->getParam("data", true, true)->value()); + else + request->send(500); + } else if(request->method() == HTTP_PUT){ + if(request->hasParam("path", true)){ + String filename = request->getParam("path", true)->value(); + if(_fs.exists(filename)){ + request->send(200); + } else { + fs::File f = _fs.open(filename, "w"); + if(f){ + f.write((uint8_t)0x00); + f.close(); + request->send(200, "", "CREATE: "+filename); + } else { + request->send(500); + } + } + } else + request->send(400); + } +} + +void SPIFFSEditor::handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){ + if(!index){ + if(!_username.length() || request->authenticate(_username.c_str(),_password.c_str())){ + _authenticated = true; + request->_tempFile = _fs.open(filename, "w"); + _startTime = millis(); + } + } + if(_authenticated && request->_tempFile){ + if(len){ + request->_tempFile.write(data,len); + } + if(final){ + request->_tempFile.close(); + } + } +} diff --git a/lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.h b/lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.h new file mode 100644 index 000000000..3586429e1 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.h @@ -0,0 +1,24 @@ +#ifndef SPIFFSEditor_H_ +#define SPIFFSEditor_H_ +#include + +class SPIFFSEditor: public AsyncWebHandler { + private: + fs::FS _fs; + String _username; + String _password; + bool _authenticated; + uint32_t _startTime; + public: +#ifdef ESP32 + SPIFFSEditor(const fs::FS& fs, const String& username=String(), const String& password=String()); +#else + SPIFFSEditor(const String& username=String(), const String& password=String(), const fs::FS& fs=SPIFFS); +#endif + virtual bool canHandle(AsyncWebServerRequest *request) override final; + virtual void handleRequest(AsyncWebServerRequest *request) override final; + virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final; + virtual bool isRequestHandlerTrivial() override final {return false;} +}; + +#endif diff --git a/lib/libesp32/ESPAsyncWebServer/src/StringArray.h b/lib/libesp32/ESPAsyncWebServer/src/StringArray.h new file mode 100644 index 000000000..801643967 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/StringArray.h @@ -0,0 +1,193 @@ +/* + Asynchronous WebServer library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef STRINGARRAY_H_ +#define STRINGARRAY_H_ + +#include "stddef.h" +#include "WString.h" + +template +class AsyncLinkedListNode { + T _value; + public: + AsyncLinkedListNode* next; + AsyncLinkedListNode(const T val): _value(val), next(nullptr) {} + ~AsyncLinkedListNode(){} + const T& value() const { return _value; }; + T& value(){ return _value; } +}; + +template class Item = AsyncLinkedListNode> +class AsyncLinkedList { + public: + typedef Item ItemType; + typedef std::function OnRemove; + typedef std::function Predicate; + private: + ItemType* _root; + OnRemove _onRemove; + + class Iterator { + ItemType* _node; + public: + Iterator(ItemType* current = nullptr) : _node(current) {} + Iterator(const Iterator& i) : _node(i._node) {} + Iterator& operator ++() { _node = _node->next; return *this; } + bool operator != (const Iterator& i) const { return _node != i._node; } + const T& operator * () const { return _node->value(); } + const T* operator -> () const { return &_node->value(); } + }; + + public: + typedef const Iterator ConstIterator; + ConstIterator begin() const { return ConstIterator(_root); } + ConstIterator end() const { return ConstIterator(nullptr); } + + AsyncLinkedList(OnRemove onRemove) : _root(nullptr), _onRemove(onRemove) {} + ~AsyncLinkedList(){} + void add(const T& t){ + auto it = new ItemType(t); + if(!_root){ + _root = it; + } else { + auto i = _root; + while(i->next) i = i->next; + i->next = it; + } + } + T& front() const { + return _root->value(); + } + + bool isEmpty() const { + return _root == nullptr; + } + size_t length() const { + size_t i = 0; + auto it = _root; + while(it){ + i++; + it = it->next; + } + return i; + } + size_t count_if(Predicate predicate) const { + size_t i = 0; + auto it = _root; + while(it){ + if (!predicate){ + i++; + } + else if (predicate(it->value())) { + i++; + } + it = it->next; + } + return i; + } + const T* nth(size_t N) const { + size_t i = 0; + auto it = _root; + while(it){ + if(i++ == N) + return &(it->value()); + it = it->next; + } + return nullptr; + } + bool remove(const T& t){ + auto it = _root; + auto pit = _root; + while(it){ + if(it->value() == t){ + if(it == _root){ + _root = _root->next; + } else { + pit->next = it->next; + } + + if (_onRemove) { + _onRemove(it->value()); + } + + delete it; + return true; + } + pit = it; + it = it->next; + } + return false; + } + bool remove_first(Predicate predicate){ + auto it = _root; + auto pit = _root; + while(it){ + if(predicate(it->value())){ + if(it == _root){ + _root = _root->next; + } else { + pit->next = it->next; + } + if (_onRemove) { + _onRemove(it->value()); + } + delete it; + return true; + } + pit = it; + it = it->next; + } + return false; + } + + void free(){ + while(_root != nullptr){ + auto it = _root; + _root = _root->next; + if (_onRemove) { + _onRemove(it->value()); + } + delete it; + } + _root = nullptr; + } +}; + + +class StringArray : public AsyncLinkedList { +public: + + StringArray() : AsyncLinkedList(nullptr) {} + + bool containsIgnoreCase(const String& str){ + for (const auto& s : *this) { + if (str.equalsIgnoreCase(s)) { + return true; + } + } + return false; + } +}; + + + + +#endif /* STRINGARRAY_H_ */ diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.cpp b/lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.cpp new file mode 100644 index 000000000..45246a196 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.cpp @@ -0,0 +1,235 @@ +/* + Asynchronous WebServer library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "WebAuthentication.h" +#include +#ifdef ESP32 +#include "mbedtls/md5.h" +#else +#include "md5.h" +#endif + + +// Basic Auth hash = base64("username:password") + +bool checkBasicAuthentication(const char * hash, const char * username, const char * password){ + if(username == NULL || password == NULL || hash == NULL) + return false; + + size_t toencodeLen = strlen(username)+strlen(password)+1; + size_t encodedLen = base64_encode_expected_len(toencodeLen); + if(strlen(hash) != encodedLen) + return false; + + char *toencode = new char[toencodeLen+1]; + if(toencode == NULL){ + return false; + } + char *encoded = new char[base64_encode_expected_len(toencodeLen)+1]; + if(encoded == NULL){ + delete[] toencode; + return false; + } + sprintf(toencode, "%s:%s", username, password); + if(base64_encode_chars(toencode, toencodeLen, encoded) > 0 && memcmp(hash, encoded, encodedLen) == 0){ + delete[] toencode; + delete[] encoded; + return true; + } + delete[] toencode; + delete[] encoded; + return false; +} + +static bool getMD5(uint8_t * data, uint16_t len, char * output){//33 bytes or more +#ifdef ESP32 + mbedtls_md5_context _ctx; +#else + md5_context_t _ctx; +#endif + uint8_t i; + uint8_t * _buf = (uint8_t*)malloc(16); + if(_buf == NULL) + return false; + memset(_buf, 0x00, 16); +#ifdef ESP32 + mbedtls_md5_init(&_ctx); + mbedtls_md5_starts_ret(&_ctx); + mbedtls_md5_update_ret(&_ctx, data, len); + mbedtls_md5_finish_ret(&_ctx, _buf); +#else + MD5Init(&_ctx); + MD5Update(&_ctx, data, len); + MD5Final(_buf, &_ctx); +#endif + for(i = 0; i < 16; i++) { + sprintf(output + (i * 2), "%02x", _buf[i]); + } + free(_buf); + return true; +} + +static String genRandomMD5(){ +#ifdef ESP8266 + uint32_t r = RANDOM_REG32; +#else + uint32_t r = rand(); +#endif + char * out = (char*)malloc(33); + if(out == NULL || !getMD5((uint8_t*)(&r), 4, out)) + return ""; + String res = String(out); + free(out); + return res; +} + +static String stringMD5(const String& in){ + char * out = (char*)malloc(33); + if(out == NULL || !getMD5((uint8_t*)(in.c_str()), in.length(), out)) + return ""; + String res = String(out); + free(out); + return res; +} + +String generateDigestHash(const char * username, const char * password, const char * realm){ + if(username == NULL || password == NULL || realm == NULL){ + return ""; + } + char * out = (char*)malloc(33); + String res = String(username); + res.concat(":"); + res.concat(realm); + res.concat(":"); + String in = res; + in.concat(password); + if(out == NULL || !getMD5((uint8_t*)(in.c_str()), in.length(), out)) + return ""; + res.concat(out); + free(out); + return res; +} + +String requestDigestAuthentication(const char * realm){ + String header = "realm=\""; + if(realm == NULL) + header.concat("asyncesp"); + else + header.concat(realm); + header.concat( "\", qop=\"auth\", nonce=\""); + header.concat(genRandomMD5()); + header.concat("\", opaque=\""); + header.concat(genRandomMD5()); + header.concat("\""); + return header; +} + +bool checkDigestAuthentication(const char * header, const char * method, const char * username, const char * password, const char * realm, bool passwordIsHash, const char * nonce, const char * opaque, const char * uri){ + if(username == NULL || password == NULL || header == NULL || method == NULL){ + //os_printf("AUTH FAIL: missing requred fields\n"); + return false; + } + + String myHeader = String(header); + int nextBreak = myHeader.indexOf(","); + if(nextBreak < 0){ + //os_printf("AUTH FAIL: no variables\n"); + return false; + } + + String myUsername = String(); + String myRealm = String(); + String myNonce = String(); + String myUri = String(); + String myResponse = String(); + String myQop = String(); + String myNc = String(); + String myCnonce = String(); + + myHeader += ", "; + do { + String avLine = myHeader.substring(0, nextBreak); + avLine.trim(); + myHeader = myHeader.substring(nextBreak+1); + nextBreak = myHeader.indexOf(","); + + int eqSign = avLine.indexOf("="); + if(eqSign < 0){ + //os_printf("AUTH FAIL: no = sign\n"); + return false; + } + String varName = avLine.substring(0, eqSign); + avLine = avLine.substring(eqSign + 1); + if(avLine.startsWith("\"")){ + avLine = avLine.substring(1, avLine.length() - 1); + } + + if(varName.equals("username")){ + if(!avLine.equals(username)){ + //os_printf("AUTH FAIL: username\n"); + return false; + } + myUsername = avLine; + } else if(varName.equals("realm")){ + if(realm != NULL && !avLine.equals(realm)){ + //os_printf("AUTH FAIL: realm\n"); + return false; + } + myRealm = avLine; + } else if(varName.equals("nonce")){ + if(nonce != NULL && !avLine.equals(nonce)){ + //os_printf("AUTH FAIL: nonce\n"); + return false; + } + myNonce = avLine; + } else if(varName.equals("opaque")){ + if(opaque != NULL && !avLine.equals(opaque)){ + //os_printf("AUTH FAIL: opaque\n"); + return false; + } + } else if(varName.equals("uri")){ + if(uri != NULL && !avLine.equals(uri)){ + //os_printf("AUTH FAIL: uri\n"); + return false; + } + myUri = avLine; + } else if(varName.equals("response")){ + myResponse = avLine; + } else if(varName.equals("qop")){ + myQop = avLine; + } else if(varName.equals("nc")){ + myNc = avLine; + } else if(varName.equals("cnonce")){ + myCnonce = avLine; + } + } while(nextBreak > 0); + + String ha1 = (passwordIsHash) ? String(password) : stringMD5(myUsername + ":" + myRealm + ":" + String(password)); + String ha2 = String(method) + ":" + myUri; + String response = ha1 + ":" + myNonce + ":" + myNc + ":" + myCnonce + ":" + myQop + ":" + stringMD5(ha2); + + if(myResponse.equals(stringMD5(response))){ + //os_printf("AUTH SUCCESS\n"); + return true; + } + + //os_printf("AUTH FAIL: password\n"); + return false; +} diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.h b/lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.h new file mode 100644 index 000000000..ff68265d9 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.h @@ -0,0 +1,34 @@ +/* + Asynchronous WebServer library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef WEB_AUTHENTICATION_H_ +#define WEB_AUTHENTICATION_H_ + +#include "Arduino.h" + +bool checkBasicAuthentication(const char * header, const char * username, const char * password); +String requestDigestAuthentication(const char * realm); +bool checkDigestAuthentication(const char * header, const char * method, const char * username, const char * password, const char * realm, bool passwordIsHash, const char * nonce, const char * opaque, const char * uri); + +//for storing hashed versions on the device that can be authenticated against +String generateDigestHash(const char * username, const char * password, const char * realm); + +#endif diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebHandlerImpl.h b/lib/libesp32/ESPAsyncWebServer/src/WebHandlerImpl.h new file mode 100644 index 000000000..9b7ba1b04 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/WebHandlerImpl.h @@ -0,0 +1,151 @@ +/* + Asynchronous WebServer library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef ASYNCWEBSERVERHANDLERIMPL_H_ +#define ASYNCWEBSERVERHANDLERIMPL_H_ + +#include +#ifdef ASYNCWEBSERVER_REGEX +#include +#endif + +#include "stddef.h" +#include + +class AsyncStaticWebHandler: public AsyncWebHandler { + using File = fs::File; + using FS = fs::FS; + private: + bool _getFile(AsyncWebServerRequest *request); + bool _fileExists(AsyncWebServerRequest *request, const String& path); + uint8_t _countBits(const uint8_t value) const; + protected: + FS _fs; + String _uri; + String _path; + String _default_file; + String _cache_control; + String _last_modified; + AwsTemplateProcessor _callback; + bool _isDir; + bool _gzipFirst; + uint8_t _gzipStats; + public: + AsyncStaticWebHandler(const char* uri, FS& fs, const char* path, const char* cache_control); + virtual bool canHandle(AsyncWebServerRequest *request) override final; + virtual void handleRequest(AsyncWebServerRequest *request) override final; + AsyncStaticWebHandler& setIsDir(bool isDir); + AsyncStaticWebHandler& setDefaultFile(const char* filename); + AsyncStaticWebHandler& setCacheControl(const char* cache_control); + AsyncStaticWebHandler& setLastModified(const char* last_modified); + AsyncStaticWebHandler& setLastModified(struct tm* last_modified); + #ifdef ESP8266 + AsyncStaticWebHandler& setLastModified(time_t last_modified); + AsyncStaticWebHandler& setLastModified(); //sets to current time. Make sure sntp is runing and time is updated + #endif + AsyncStaticWebHandler& setTemplateProcessor(AwsTemplateProcessor newCallback) {_callback = newCallback; return *this;} +}; + +class AsyncCallbackWebHandler: public AsyncWebHandler { + private: + protected: + String _uri; + WebRequestMethodComposite _method; + ArRequestHandlerFunction _onRequest; + ArUploadHandlerFunction _onUpload; + ArBodyHandlerFunction _onBody; + bool _isRegex; + public: + AsyncCallbackWebHandler() : _uri(), _method(HTTP_ANY), _onRequest(NULL), _onUpload(NULL), _onBody(NULL), _isRegex(false) {} + void setUri(const String& uri){ + _uri = uri; + _isRegex = uri.startsWith("^") && uri.endsWith("$"); + } + void setMethod(WebRequestMethodComposite method){ _method = method; } + void onRequest(ArRequestHandlerFunction fn){ _onRequest = fn; } + void onUpload(ArUploadHandlerFunction fn){ _onUpload = fn; } + void onBody(ArBodyHandlerFunction fn){ _onBody = fn; } + + virtual bool canHandle(AsyncWebServerRequest *request) override final{ + + if(!_onRequest) + return false; + + if(!(_method & request->method())) + return false; + +#ifdef ASYNCWEBSERVER_REGEX + if (_isRegex) { + std::regex pattern(_uri.c_str()); + std::smatch matches; + std::string s(request->url().c_str()); + if(std::regex_search(s, matches, pattern)) { + for (size_t i = 1; i < matches.size(); ++i) { // start from 1 + request->_addPathParam(matches[i].str().c_str()); + } + } else { + return false; + } + } else +#endif + if (_uri.length() && _uri.startsWith("/*.")) { + String uriTemplate = String (_uri); + uriTemplate = uriTemplate.substring(uriTemplate.lastIndexOf(".")); + if (!request->url().endsWith(uriTemplate)) + return false; + } + else + if (_uri.length() && _uri.endsWith("*")) { + String uriTemplate = String(_uri); + uriTemplate = uriTemplate.substring(0, uriTemplate.length() - 1); + if (!request->url().startsWith(uriTemplate)) + return false; + } + else if(_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri+"/"))) + return false; + + request->addInterestingHeader("ANY"); + return true; + } + + virtual void handleRequest(AsyncWebServerRequest *request) override final { + if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str())) + return request->requestAuthentication(); + if(_onRequest) + _onRequest(request); + else + request->send(500); + } + virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final { + if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str())) + return request->requestAuthentication(); + if(_onUpload) + _onUpload(request, filename, index, data, len, final); + } + virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final { + if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str())) + return request->requestAuthentication(); + if(_onBody) + _onBody(request, data, len, index, total); + } + virtual bool isRequestHandlerTrivial() override final {return _onRequest ? false : true;} +}; + +#endif /* ASYNCWEBSERVERHANDLERIMPL_H_ */ diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebHandlers.cpp b/lib/libesp32/ESPAsyncWebServer/src/WebHandlers.cpp new file mode 100644 index 000000000..1f435e68a --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/WebHandlers.cpp @@ -0,0 +1,220 @@ +/* + Asynchronous WebServer library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "ESPAsyncWebServer.h" +#include "WebHandlerImpl.h" + +AsyncStaticWebHandler::AsyncStaticWebHandler(const char* uri, FS& fs, const char* path, const char* cache_control) + : _fs(fs), _uri(uri), _path(path), _default_file("index.htm"), _cache_control(cache_control), _last_modified(""), _callback(nullptr) +{ + // Ensure leading '/' + if (_uri.length() == 0 || _uri[0] != '/') _uri = "/" + _uri; + if (_path.length() == 0 || _path[0] != '/') _path = "/" + _path; + + // If path ends with '/' we assume a hint that this is a directory to improve performance. + // However - if it does not end with '/' we, can't assume a file, path can still be a directory. + _isDir = _path[_path.length()-1] == '/'; + + // Remove the trailing '/' so we can handle default file + // Notice that root will be "" not "/" + if (_uri[_uri.length()-1] == '/') _uri = _uri.substring(0, _uri.length()-1); + if (_path[_path.length()-1] == '/') _path = _path.substring(0, _path.length()-1); + + // Reset stats + _gzipFirst = false; + _gzipStats = 0xF8; +} + +AsyncStaticWebHandler& AsyncStaticWebHandler::setIsDir(bool isDir){ + _isDir = isDir; + return *this; +} + +AsyncStaticWebHandler& AsyncStaticWebHandler::setDefaultFile(const char* filename){ + _default_file = String(filename); + return *this; +} + +AsyncStaticWebHandler& AsyncStaticWebHandler::setCacheControl(const char* cache_control){ + _cache_control = String(cache_control); + return *this; +} + +AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(const char* last_modified){ + _last_modified = String(last_modified); + return *this; +} + +AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(struct tm* last_modified){ + char result[30]; + strftime (result,30,"%a, %d %b %Y %H:%M:%S %Z", last_modified); + return setLastModified((const char *)result); +} + +#ifdef ESP8266 +AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(time_t last_modified){ + return setLastModified((struct tm *)gmtime(&last_modified)); +} + +AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(){ + time_t last_modified; + if(time(&last_modified) == 0) //time is not yet set + return *this; + return setLastModified(last_modified); +} +#endif +bool AsyncStaticWebHandler::canHandle(AsyncWebServerRequest *request){ + if(request->method() != HTTP_GET + || !request->url().startsWith(_uri) + || !request->isExpectedRequestedConnType(RCT_DEFAULT, RCT_HTTP) + ){ + return false; + } + if (_getFile(request)) { + // We interested in "If-Modified-Since" header to check if file was modified + if (_last_modified.length()) + request->addInterestingHeader("If-Modified-Since"); + + if(_cache_control.length()) + request->addInterestingHeader("If-None-Match"); + + DEBUGF("[AsyncStaticWebHandler::canHandle] TRUE\n"); + return true; + } + + return false; +} + +bool AsyncStaticWebHandler::_getFile(AsyncWebServerRequest *request) +{ + // Remove the found uri + String path = request->url().substring(_uri.length()); + + // We can skip the file check and look for default if request is to the root of a directory or that request path ends with '/' + bool canSkipFileCheck = (_isDir && path.length() == 0) || (path.length() && path[path.length()-1] == '/'); + + path = _path + path; + + // Do we have a file or .gz file + if (!canSkipFileCheck && _fileExists(request, path)) + return true; + + // Can't handle if not default file + if (_default_file.length() == 0) + return false; + + // Try to add default file, ensure there is a trailing '/' ot the path. + if (path.length() == 0 || path[path.length()-1] != '/') + path += "/"; + path += _default_file; + + return _fileExists(request, path); +} + +#ifdef ESP32 +#define FILE_IS_REAL(f) (f == true && !f.isDirectory()) +#else +#define FILE_IS_REAL(f) (f == true) +#endif + +bool AsyncStaticWebHandler::_fileExists(AsyncWebServerRequest *request, const String& path) +{ + bool fileFound = false; + bool gzipFound = false; + + String gzip = path + ".gz"; + + if (_gzipFirst) { + request->_tempFile = _fs.open(gzip, "r"); + gzipFound = FILE_IS_REAL(request->_tempFile); + if (!gzipFound){ + request->_tempFile = _fs.open(path, "r"); + fileFound = FILE_IS_REAL(request->_tempFile); + } + } else { + request->_tempFile = _fs.open(path, "r"); + fileFound = FILE_IS_REAL(request->_tempFile); + if (!fileFound){ + request->_tempFile = _fs.open(gzip, "r"); + gzipFound = FILE_IS_REAL(request->_tempFile); + } + } + + bool found = fileFound || gzipFound; + + if (found) { + // Extract the file name from the path and keep it in _tempObject + size_t pathLen = path.length(); + char * _tempPath = (char*)malloc(pathLen+1); + snprintf(_tempPath, pathLen+1, "%s", path.c_str()); + request->_tempObject = (void*)_tempPath; + + // Calculate gzip statistic + _gzipStats = (_gzipStats << 1) + (gzipFound ? 1 : 0); + if (_gzipStats == 0x00) _gzipFirst = false; // All files are not gzip + else if (_gzipStats == 0xFF) _gzipFirst = true; // All files are gzip + else _gzipFirst = _countBits(_gzipStats) > 4; // IF we have more gzip files - try gzip first + } + + return found; +} + +uint8_t AsyncStaticWebHandler::_countBits(const uint8_t value) const +{ + uint8_t w = value; + uint8_t n; + for (n=0; w!=0; n++) w&=w-1; + return n; +} + +void AsyncStaticWebHandler::handleRequest(AsyncWebServerRequest *request) +{ + // Get the filename from request->_tempObject and free it + String filename = String((char*)request->_tempObject); + free(request->_tempObject); + request->_tempObject = NULL; + if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str())) + return request->requestAuthentication(); + + if (request->_tempFile == true) { + String etag = String(request->_tempFile.size()); + if (_last_modified.length() && _last_modified == request->header("If-Modified-Since")) { + request->_tempFile.close(); + request->send(304); // Not modified + } else if (_cache_control.length() && request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag)) { + request->_tempFile.close(); + AsyncWebServerResponse * response = new AsyncBasicResponse(304); // Not modified + response->addHeader("Cache-Control", _cache_control); + response->addHeader("ETag", etag); + request->send(response); + } else { + AsyncWebServerResponse * response = new AsyncFileResponse(request->_tempFile, filename, String(), false, _callback); + if (_last_modified.length()) + response->addHeader("Last-Modified", _last_modified); + if (_cache_control.length()){ + response->addHeader("Cache-Control", _cache_control); + response->addHeader("ETag", etag); + } + request->send(response); + } + } else { + request->send(404); + } +} diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebRequest.cpp b/lib/libesp32/ESPAsyncWebServer/src/WebRequest.cpp new file mode 100644 index 000000000..20b0b1fe4 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/WebRequest.cpp @@ -0,0 +1,1008 @@ +/* + Asynchronous WebServer library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "ESPAsyncWebServer.h" +#include "WebResponseImpl.h" +#include "WebAuthentication.h" + +#ifndef ESP8266 +#define os_strlen strlen +#endif + +static const String SharedEmptyString = String(); + +#define __is_param_char(c) ((c) && ((c) != '{') && ((c) != '[') && ((c) != '&') && ((c) != '=')) + +enum { PARSE_REQ_START, PARSE_REQ_HEADERS, PARSE_REQ_BODY, PARSE_REQ_END, PARSE_REQ_FAIL }; + +AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c) + : _client(c) + , _server(s) + , _handler(NULL) + , _response(NULL) + , _temp() + , _parseState(0) + , _version(0) + , _method(HTTP_ANY) + , _url() + , _host() + , _contentType() + , _boundary() + , _authorization() + , _reqconntype(RCT_HTTP) + , _isDigest(false) + , _isMultipart(false) + , _isPlainPost(false) + , _expectingContinue(false) + , _contentLength(0) + , _parsedLength(0) + , _headers(AsyncLinkedList([](AsyncWebHeader *h){ delete h; })) + , _params(AsyncLinkedList([](AsyncWebParameter *p){ delete p; })) + , _pathParams(AsyncLinkedList([](String *p){ delete p; })) + , _multiParseState(0) + , _boundaryPosition(0) + , _itemStartIndex(0) + , _itemSize(0) + , _itemName() + , _itemFilename() + , _itemType() + , _itemValue() + , _itemBuffer(0) + , _itemBufferIndex(0) + , _itemIsFile(false) + , _tempObject(NULL) +{ + c->onError([](void *r, AsyncClient* c, int8_t error){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onError(error); }, this); + c->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onAck(len, time); }, this); + c->onDisconnect([](void *r, AsyncClient* c){ AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onDisconnect(); delete c; }, this); + c->onTimeout([](void *r, AsyncClient* c, uint32_t time){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onTimeout(time); }, this); + c->onData([](void *r, AsyncClient* c, void *buf, size_t len){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onData(buf, len); }, this); + c->onPoll([](void *r, AsyncClient* c){ (void)c; AsyncWebServerRequest *req = ( AsyncWebServerRequest*)r; req->_onPoll(); }, this); +} + +AsyncWebServerRequest::~AsyncWebServerRequest(){ + _headers.free(); + + _params.free(); + _pathParams.free(); + + _interestingHeaders.free(); + + if(_response != NULL){ + delete _response; + } + + if(_tempObject != NULL){ + free(_tempObject); + } + + if(_tempFile){ + _tempFile.close(); + } +} + +void AsyncWebServerRequest::_onData(void *buf, size_t len){ + size_t i = 0; + while (true) { + + if(_parseState < PARSE_REQ_BODY){ + // Find new line in buf + char *str = (char*)buf; + for (i = 0; i < len; i++) { + if (str[i] == '\n') { + break; + } + } + if (i == len) { // No new line, just add the buffer in _temp + char ch = str[len-1]; + str[len-1] = 0; + _temp.reserve(_temp.length()+len); + _temp.concat(str); + _temp.concat(ch); + } else { // Found new line - extract it and parse + str[i] = 0; // Terminate the string at the end of the line. + _temp.concat(str); + _temp.trim(); + _parseLine(); + if (++i < len) { + // Still have more buffer to process + buf = str+i; + len-= i; + continue; + } + } + } else if(_parseState == PARSE_REQ_BODY){ + // A handler should be already attached at this point in _parseLine function. + // If handler does nothing (_onRequest is NULL), we don't need to really parse the body. + const bool needParse = _handler && !_handler->isRequestHandlerTrivial(); + if(_isMultipart){ + if(needParse){ + size_t i; + for(i=0; i end) equal = end; + String name = params.substring(start, equal); + String value = equal + 1 < end ? params.substring(equal + 1, end) : String(); + _addParam(new AsyncWebParameter(urlDecode(name), urlDecode(value))); + start = end + 1; + } +} + +bool AsyncWebServerRequest::_parseReqHead(){ + // Split the head into method, url and version + int index = _temp.indexOf(' '); + String m = _temp.substring(0, index); + index = _temp.indexOf(' ', index+1); + String u = _temp.substring(m.length()+1, index); + _temp = _temp.substring(index+1); + + if(m == "GET"){ + _method = HTTP_GET; + } else if(m == "POST"){ + _method = HTTP_POST; + } else if(m == "DELETE"){ + _method = HTTP_DELETE; + } else if(m == "PUT"){ + _method = HTTP_PUT; + } else if(m == "PATCH"){ + _method = HTTP_PATCH; + } else if(m == "HEAD"){ + _method = HTTP_HEAD; + } else if(m == "OPTIONS"){ + _method = HTTP_OPTIONS; + } + + String g = String(); + index = u.indexOf('?'); + if(index > 0){ + g = u.substring(index +1); + u = u.substring(0, index); + } + _url = urlDecode(u); + _addGetParams(g); + + if(!_temp.startsWith("HTTP/1.0")) + _version = 1; + + _temp = String(); + return true; +} + +bool strContains(String src, String find, bool mindcase = true) { + int pos=0, i=0; + const int slen = src.length(); + const int flen = find.length(); + + if (slen < flen) return false; + while (pos <= (slen - flen)) { + for (i=0; i < flen; i++) { + if (mindcase) { + if (src[pos+i] != find[i]) i = flen + 1; // no match + } else if (tolower(src[pos+i]) != tolower(find[i])) i = flen + 1; // no match + } + if (i == flen) return true; + pos++; + } + return false; +} + +bool AsyncWebServerRequest::_parseReqHeader(){ + int index = _temp.indexOf(':'); + if(index){ + String name = _temp.substring(0, index); + String value = _temp.substring(index + 2); + if(name.equalsIgnoreCase("Host")){ + _host = value; + } else if(name.equalsIgnoreCase("Content-Type")){ + _contentType = value.substring(0, value.indexOf(';')); + if (value.startsWith("multipart/")){ + _boundary = value.substring(value.indexOf('=')+1); + _boundary.replace("\"",""); + _isMultipart = true; + } + } else if(name.equalsIgnoreCase("Content-Length")){ + _contentLength = atoi(value.c_str()); + } else if(name.equalsIgnoreCase("Expect") && value == "100-continue"){ + _expectingContinue = true; + } else if(name.equalsIgnoreCase("Authorization")){ + if(value.length() > 5 && value.substring(0,5).equalsIgnoreCase("Basic")){ + _authorization = value.substring(6); + } else if(value.length() > 6 && value.substring(0,6).equalsIgnoreCase("Digest")){ + _isDigest = true; + _authorization = value.substring(7); + } + } else { + if(name.equalsIgnoreCase("Upgrade") && value.equalsIgnoreCase("websocket")){ + // WebSocket request can be uniquely identified by header: [Upgrade: websocket] + _reqconntype = RCT_WS; + } else { + if(name.equalsIgnoreCase("Accept") && strContains(value, "text/event-stream", false)){ + // WebEvent request can be uniquely identified by header: [Accept: text/event-stream] + _reqconntype = RCT_EVENT; + } + } + } + _headers.add(new AsyncWebHeader(name, value)); + } + _temp = String(); + return true; +} + +void AsyncWebServerRequest::_parsePlainPostChar(uint8_t data){ + if(data && (char)data != '&') + _temp += (char)data; + if(!data || (char)data == '&' || _parsedLength == _contentLength){ + String name = "body"; + String value = _temp; + if(!_temp.startsWith("{") && !_temp.startsWith("[") && _temp.indexOf('=') > 0){ + name = _temp.substring(0, _temp.indexOf('=')); + value = _temp.substring(_temp.indexOf('=') + 1); + } + _addParam(new AsyncWebParameter(urlDecode(name), urlDecode(value), true)); + _temp = String(); + } +} + +void AsyncWebServerRequest::_handleUploadByte(uint8_t data, bool last){ + _itemBuffer[_itemBufferIndex++] = data; + + if(last || _itemBufferIndex == 1460){ + //check if authenticated before calling the upload + if(_handler) + _handler->handleUpload(this, _itemFilename, _itemSize - _itemBufferIndex, _itemBuffer, _itemBufferIndex, false); + _itemBufferIndex = 0; + } +} + +enum { + EXPECT_BOUNDARY, + PARSE_HEADERS, + WAIT_FOR_RETURN1, + EXPECT_FEED1, + EXPECT_DASH1, + EXPECT_DASH2, + BOUNDARY_OR_DATA, + DASH3_OR_RETURN2, + EXPECT_FEED2, + PARSING_FINISHED, + PARSE_ERROR +}; + +void AsyncWebServerRequest::_parseMultipartPostByte(uint8_t data, bool last){ +#define itemWriteByte(b) do { _itemSize++; if(_itemIsFile) _handleUploadByte(b, last); else _itemValue+=(char)(b); } while(0) + + if(!_parsedLength){ + _multiParseState = EXPECT_BOUNDARY; + _temp = String(); + _itemName = String(); + _itemFilename = String(); + _itemType = String(); + } + + if(_multiParseState == WAIT_FOR_RETURN1){ + if(data != '\r'){ + itemWriteByte(data); + } else { + _multiParseState = EXPECT_FEED1; + } + } else if(_multiParseState == EXPECT_BOUNDARY){ + if(_parsedLength < 2 && data != '-'){ + _multiParseState = PARSE_ERROR; + return; + } else if(_parsedLength - 2 < _boundary.length() && _boundary.c_str()[_parsedLength - 2] != data){ + _multiParseState = PARSE_ERROR; + return; + } else if(_parsedLength - 2 == _boundary.length() && data != '\r'){ + _multiParseState = PARSE_ERROR; + return; + } else if(_parsedLength - 3 == _boundary.length()){ + if(data != '\n'){ + _multiParseState = PARSE_ERROR; + return; + } + _multiParseState = PARSE_HEADERS; + _itemIsFile = false; + } + } else if(_multiParseState == PARSE_HEADERS){ + if((char)data != '\r' && (char)data != '\n') + _temp += (char)data; + if((char)data == '\n'){ + if(_temp.length()){ + if(_temp.length() > 12 && _temp.substring(0, 12).equalsIgnoreCase("Content-Type")){ + _itemType = _temp.substring(14); + _itemIsFile = true; + } else if(_temp.length() > 19 && _temp.substring(0, 19).equalsIgnoreCase("Content-Disposition")){ + _temp = _temp.substring(_temp.indexOf(';') + 2); + while(_temp.indexOf(';') > 0){ + String name = _temp.substring(0, _temp.indexOf('=')); + String nameVal = _temp.substring(_temp.indexOf('=') + 2, _temp.indexOf(';') - 1); + if(name == "name"){ + _itemName = nameVal; + } else if(name == "filename"){ + _itemFilename = nameVal; + _itemIsFile = true; + } + _temp = _temp.substring(_temp.indexOf(';') + 2); + } + String name = _temp.substring(0, _temp.indexOf('=')); + String nameVal = _temp.substring(_temp.indexOf('=') + 2, _temp.length() - 1); + if(name == "name"){ + _itemName = nameVal; + } else if(name == "filename"){ + _itemFilename = nameVal; + _itemIsFile = true; + } + } + _temp = String(); + } else { + _multiParseState = WAIT_FOR_RETURN1; + //value starts from here + _itemSize = 0; + _itemStartIndex = _parsedLength; + _itemValue = String(); + if(_itemIsFile){ + if(_itemBuffer) + free(_itemBuffer); + _itemBuffer = (uint8_t*)malloc(1460); + if(_itemBuffer == NULL){ + _multiParseState = PARSE_ERROR; + return; + } + _itemBufferIndex = 0; + } + } + } + } else if(_multiParseState == EXPECT_FEED1){ + if(data != '\n'){ + _multiParseState = WAIT_FOR_RETURN1; + itemWriteByte('\r'); _parseMultipartPostByte(data, last); + } else { + _multiParseState = EXPECT_DASH1; + } + } else if(_multiParseState == EXPECT_DASH1){ + if(data != '-'){ + _multiParseState = WAIT_FOR_RETURN1; + itemWriteByte('\r'); itemWriteByte('\n'); _parseMultipartPostByte(data, last); + } else { + _multiParseState = EXPECT_DASH2; + } + } else if(_multiParseState == EXPECT_DASH2){ + if(data != '-'){ + _multiParseState = WAIT_FOR_RETURN1; + itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); _parseMultipartPostByte(data, last); + } else { + _multiParseState = BOUNDARY_OR_DATA; + _boundaryPosition = 0; + } + } else if(_multiParseState == BOUNDARY_OR_DATA){ + if(_boundaryPosition < _boundary.length() && _boundary.c_str()[_boundaryPosition] != data){ + _multiParseState = WAIT_FOR_RETURN1; + itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); itemWriteByte('-'); + uint8_t i; + for(i=0; i<_boundaryPosition; i++) + itemWriteByte(_boundary.c_str()[i]); + _parseMultipartPostByte(data, last); + } else if(_boundaryPosition == _boundary.length() - 1){ + _multiParseState = DASH3_OR_RETURN2; + if(!_itemIsFile){ + _addParam(new AsyncWebParameter(_itemName, _itemValue, true)); + } else { + if(_itemSize){ + //check if authenticated before calling the upload + if(_handler) _handler->handleUpload(this, _itemFilename, _itemSize - _itemBufferIndex, _itemBuffer, _itemBufferIndex, true); + _itemBufferIndex = 0; + _addParam(new AsyncWebParameter(_itemName, _itemFilename, true, true, _itemSize)); + } + free(_itemBuffer); + _itemBuffer = NULL; + } + + } else { + _boundaryPosition++; + } + } else if(_multiParseState == DASH3_OR_RETURN2){ + if(data == '-' && (_contentLength - _parsedLength - 4) != 0){ + //os_printf("ERROR: The parser got to the end of the POST but is expecting %u bytes more!\nDrop an issue so we can have more info on the matter!\n", _contentLength - _parsedLength - 4); + _contentLength = _parsedLength + 4;//lets close the request gracefully + } + if(data == '\r'){ + _multiParseState = EXPECT_FEED2; + } else if(data == '-' && _contentLength == (_parsedLength + 4)){ + _multiParseState = PARSING_FINISHED; + } else { + _multiParseState = WAIT_FOR_RETURN1; + itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); itemWriteByte('-'); + uint8_t i; for(i=0; i<_boundary.length(); i++) itemWriteByte(_boundary.c_str()[i]); + _parseMultipartPostByte(data, last); + } + } else if(_multiParseState == EXPECT_FEED2){ + if(data == '\n'){ + _multiParseState = PARSE_HEADERS; + _itemIsFile = false; + } else { + _multiParseState = WAIT_FOR_RETURN1; + itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); itemWriteByte('-'); + uint8_t i; for(i=0; i<_boundary.length(); i++) itemWriteByte(_boundary.c_str()[i]); + itemWriteByte('\r'); _parseMultipartPostByte(data, last); + } + } +} + +void AsyncWebServerRequest::_parseLine(){ + if(_parseState == PARSE_REQ_START){ + if(!_temp.length()){ + _parseState = PARSE_REQ_FAIL; + _client->close(); + } else { + _parseReqHead(); + _parseState = PARSE_REQ_HEADERS; + } + return; + } + + if(_parseState == PARSE_REQ_HEADERS){ + if(!_temp.length()){ + //end of headers + _server->_rewriteRequest(this); + _server->_attachHandler(this); + _removeNotInterestingHeaders(); + if(_expectingContinue){ + const char * response = "HTTP/1.1 100 Continue\r\n\r\n"; + _client->write(response, os_strlen(response)); + } + //check handler for authentication + if(_contentLength){ + _parseState = PARSE_REQ_BODY; + } else { + _parseState = PARSE_REQ_END; + if(_handler) _handler->handleRequest(this); + else send(501); + } + } else _parseReqHeader(); + } +} + +size_t AsyncWebServerRequest::headers() const{ + return _headers.length(); +} + +bool AsyncWebServerRequest::hasHeader(const String& name) const { + for(const auto& h: _headers){ + if(h->name().equalsIgnoreCase(name)){ + return true; + } + } + return false; +} + +bool AsyncWebServerRequest::hasHeader(const __FlashStringHelper * data) const { + PGM_P p = reinterpret_cast(data); + size_t n = 0; + while (1) { + if (pgm_read_byte(p+n) == 0) break; + n += 1; + } + char * name = (char*) malloc(n+1); + name[n] = 0; + if (name) { + for(size_t b=0; bname().equalsIgnoreCase(name)){ + return h; + } + } + return nullptr; +} + +AsyncWebHeader* AsyncWebServerRequest::getHeader(const __FlashStringHelper * data) const { + PGM_P p = reinterpret_cast(data); + size_t n = strlen_P(p); + char * name = (char*) malloc(n+1); + if (name) { + strcpy_P(name, p); + AsyncWebHeader* result = getHeader( String(name)); + free(name); + return result; + } else { + return nullptr; + } +} + +AsyncWebHeader* AsyncWebServerRequest::getHeader(size_t num) const { + auto header = _headers.nth(num); + return header ? *header : nullptr; +} + +size_t AsyncWebServerRequest::params() const { + return _params.length(); +} + +bool AsyncWebServerRequest::hasParam(const String& name, bool post, bool file) const { + for(const auto& p: _params){ + if(p->name() == name && p->isPost() == post && p->isFile() == file){ + return true; + } + } + return false; +} + +bool AsyncWebServerRequest::hasParam(const __FlashStringHelper * data, bool post, bool file) const { + PGM_P p = reinterpret_cast(data); + size_t n = strlen_P(p); + + char * name = (char*) malloc(n+1); + name[n] = 0; + if (name) { + strcpy_P(name,p); + bool result = hasParam( name, post, file); + free(name); + return result; + } else { + return false; + } +} + +AsyncWebParameter* AsyncWebServerRequest::getParam(const String& name, bool post, bool file) const { + for(const auto& p: _params){ + if(p->name() == name && p->isPost() == post && p->isFile() == file){ + return p; + } + } + return nullptr; +} + +AsyncWebParameter* AsyncWebServerRequest::getParam(const __FlashStringHelper * data, bool post, bool file) const { + PGM_P p = reinterpret_cast(data); + size_t n = strlen_P(p); + char * name = (char*) malloc(n+1); + if (name) { + strcpy_P(name, p); + AsyncWebParameter* result = getParam(name, post, file); + free(name); + return result; + } else { + return nullptr; + } +} + +AsyncWebParameter* AsyncWebServerRequest::getParam(size_t num) const { + auto param = _params.nth(num); + return param ? *param : nullptr; +} + +void AsyncWebServerRequest::addInterestingHeader(const String& name){ + if(!_interestingHeaders.containsIgnoreCase(name)) + _interestingHeaders.add(name); +} + +void AsyncWebServerRequest::send(AsyncWebServerResponse *response){ + _response = response; + if(_response == NULL){ + _client->close(true); + _onDisconnect(); + return; + } + if(!_response->_sourceValid()){ + delete response; + _response = NULL; + send(500); + } + else { + _client->setRxTimeout(0); + _response->_respond(this); + } +} + +AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(int code, const String& contentType, const String& content){ + return new AsyncBasicResponse(code, contentType, content); +} + +AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(FS &fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){ + if(fs.exists(path) || (!download && fs.exists(path+".gz"))) + return new AsyncFileResponse(fs, path, contentType, download, callback); + return NULL; +} + +AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){ + if(content == true) + return new AsyncFileResponse(content, path, contentType, download, callback); + return NULL; +} + +AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback){ + return new AsyncStreamResponse(stream, contentType, len, callback); +} + +AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){ + return new AsyncCallbackResponse(contentType, len, callback, templateCallback); +} + +AsyncWebServerResponse * AsyncWebServerRequest::beginChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){ + if(_version) + return new AsyncChunkedResponse(contentType, callback, templateCallback); + return new AsyncCallbackResponse(contentType, 0, callback, templateCallback); +} + +AsyncResponseStream * AsyncWebServerRequest::beginResponseStream(const String& contentType, size_t bufferSize){ + return new AsyncResponseStream(contentType, bufferSize); +} + +AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback){ + return new AsyncProgmemResponse(code, contentType, content, len, callback); +} + +AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback){ + return beginResponse_P(code, contentType, (const uint8_t *)content, strlen_P(content), callback); +} + +void AsyncWebServerRequest::send(int code, const String& contentType, const String& content){ + send(beginResponse(code, contentType, content)); +} + +void AsyncWebServerRequest::send(FS &fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){ + if(fs.exists(path) || (!download && fs.exists(path+".gz"))){ + send(beginResponse(fs, path, contentType, download, callback)); + } else send(404); +} + +void AsyncWebServerRequest::send(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){ + if(content == true){ + send(beginResponse(content, path, contentType, download, callback)); + } else send(404); +} + +void AsyncWebServerRequest::send(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback){ + send(beginResponse(stream, contentType, len, callback)); +} + +void AsyncWebServerRequest::send(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){ + send(beginResponse(contentType, len, callback, templateCallback)); +} + +void AsyncWebServerRequest::sendChunked(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){ + send(beginChunkedResponse(contentType, callback, templateCallback)); +} + +void AsyncWebServerRequest::send_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback){ + send(beginResponse_P(code, contentType, content, len, callback)); +} + +void AsyncWebServerRequest::send_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback){ + send(beginResponse_P(code, contentType, content, callback)); +} + +void AsyncWebServerRequest::redirect(const String& url){ + AsyncWebServerResponse * response = beginResponse(302); + response->addHeader("Location",url); + send(response); +} + +bool AsyncWebServerRequest::authenticate(const char * username, const char * password, const char * realm, bool passwordIsHash){ + if(_authorization.length()){ + if(_isDigest) + return checkDigestAuthentication(_authorization.c_str(), methodToString(), username, password, realm, passwordIsHash, NULL, NULL, NULL); + else if(!passwordIsHash) + return checkBasicAuthentication(_authorization.c_str(), username, password); + else + return _authorization.equals(password); + } + return false; +} + +bool AsyncWebServerRequest::authenticate(const char * hash){ + if(!_authorization.length() || hash == NULL) + return false; + + if(_isDigest){ + String hStr = String(hash); + int separator = hStr.indexOf(":"); + if(separator <= 0) + return false; + String username = hStr.substring(0, separator); + hStr = hStr.substring(separator + 1); + separator = hStr.indexOf(":"); + if(separator <= 0) + return false; + String realm = hStr.substring(0, separator); + hStr = hStr.substring(separator + 1); + return checkDigestAuthentication(_authorization.c_str(), methodToString(), username.c_str(), hStr.c_str(), realm.c_str(), true, NULL, NULL, NULL); + } + + return (_authorization.equals(hash)); +} + +void AsyncWebServerRequest::requestAuthentication(const char * realm, bool isDigest){ + AsyncWebServerResponse * r = beginResponse(401); + if(!isDigest && realm == NULL){ + r->addHeader("WWW-Authenticate", "Basic realm=\"Login Required\""); + } else if(!isDigest){ + String header = "Basic realm=\""; + header.concat(realm); + header.concat("\""); + r->addHeader("WWW-Authenticate", header); + } else { + String header = "Digest "; + header.concat(requestDigestAuthentication(realm)); + r->addHeader("WWW-Authenticate", header); + } + send(r); +} + +bool AsyncWebServerRequest::hasArg(const char* name) const { + for(const auto& arg: _params){ + if(arg->name() == name){ + return true; + } + } + return false; +} + +bool AsyncWebServerRequest::hasArg(const __FlashStringHelper * data) const { + PGM_P p = reinterpret_cast(data); + size_t n = strlen_P(p); + char * name = (char*) malloc(n+1); + if (name) { + strcpy_P(name, p); + bool result = hasArg( name ); + free(name); + return result; + } else { + return false; + } +} + + +const String& AsyncWebServerRequest::arg(const String& name) const { + for(const auto& arg: _params){ + if(arg->name() == name){ + return arg->value(); + } + } + return SharedEmptyString; +} + +const String& AsyncWebServerRequest::arg(const __FlashStringHelper * data) const { + PGM_P p = reinterpret_cast(data); + size_t n = strlen_P(p); + char * name = (char*) malloc(n+1); + if (name) { + strcpy_P(name, p); + const String & result = arg( String(name) ); + free(name); + return result; + } else { + return SharedEmptyString; + } + +} + +const String& AsyncWebServerRequest::arg(size_t i) const { + return getParam(i)->value(); +} + +const String& AsyncWebServerRequest::argName(size_t i) const { + return getParam(i)->name(); +} + +const String& AsyncWebServerRequest::pathArg(size_t i) const { + auto param = _pathParams.nth(i); + return param ? **param : SharedEmptyString; +} + +const String& AsyncWebServerRequest::header(const char* name) const { + AsyncWebHeader* h = getHeader(String(name)); + return h ? h->value() : SharedEmptyString; +} + +const String& AsyncWebServerRequest::header(const __FlashStringHelper * data) const { + PGM_P p = reinterpret_cast(data); + size_t n = strlen_P(p); + char * name = (char*) malloc(n+1); + if (name) { + strcpy_P(name, p); + const String & result = header( (const char *)name ); + free(name); + return result; + } else { + return SharedEmptyString; + } +}; + + +const String& AsyncWebServerRequest::header(size_t i) const { + AsyncWebHeader* h = getHeader(i); + return h ? h->value() : SharedEmptyString; +} + +const String& AsyncWebServerRequest::headerName(size_t i) const { + AsyncWebHeader* h = getHeader(i); + return h ? h->name() : SharedEmptyString; +} + +String AsyncWebServerRequest::urlDecode(const String& text) const { + char temp[] = "0x00"; + unsigned int len = text.length(); + unsigned int i = 0; + String decoded = String(); + decoded.reserve(len); // Allocate the string internal buffer - never longer from source text + while (i < len){ + char decodedChar; + char encodedChar = text.charAt(i++); + if ((encodedChar == '%') && (i + 1 < len)){ + temp[2] = text.charAt(i++); + temp[3] = text.charAt(i++); + decodedChar = strtol(temp, NULL, 16); + } else if (encodedChar == '+') { + decodedChar = ' '; + } else { + decodedChar = encodedChar; // normal ascii char + } + decoded.concat(decodedChar); + } + return decoded; +} + + +const char * AsyncWebServerRequest::methodToString() const { + if(_method == HTTP_ANY) return "ANY"; + else if(_method & HTTP_GET) return "GET"; + else if(_method & HTTP_POST) return "POST"; + else if(_method & HTTP_DELETE) return "DELETE"; + else if(_method & HTTP_PUT) return "PUT"; + else if(_method & HTTP_PATCH) return "PATCH"; + else if(_method & HTTP_HEAD) return "HEAD"; + else if(_method & HTTP_OPTIONS) return "OPTIONS"; + return "UNKNOWN"; +} + +const char *AsyncWebServerRequest::requestedConnTypeToString() const { + switch (_reqconntype) { + case RCT_NOT_USED: return "RCT_NOT_USED"; + case RCT_DEFAULT: return "RCT_DEFAULT"; + case RCT_HTTP: return "RCT_HTTP"; + case RCT_WS: return "RCT_WS"; + case RCT_EVENT: return "RCT_EVENT"; + default: return "ERROR"; + } +} + +bool AsyncWebServerRequest::isExpectedRequestedConnType(RequestedConnectionType erct1, RequestedConnectionType erct2, RequestedConnectionType erct3) { + bool res = false; + if ((erct1 != RCT_NOT_USED) && (erct1 == _reqconntype)) res = true; + if ((erct2 != RCT_NOT_USED) && (erct2 == _reqconntype)) res = true; + if ((erct3 != RCT_NOT_USED) && (erct3 == _reqconntype)) res = true; + return res; +} diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebResponseImpl.h b/lib/libesp32/ESPAsyncWebServer/src/WebResponseImpl.h new file mode 100644 index 000000000..9a64e3a52 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/WebResponseImpl.h @@ -0,0 +1,136 @@ +/* + Asynchronous WebServer library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef ASYNCWEBSERVERRESPONSEIMPL_H_ +#define ASYNCWEBSERVERRESPONSEIMPL_H_ + +#ifdef Arduino_h +// arduino is not compatible with std::vector +#undef min +#undef max +#endif +#include +// It is possible to restore these defines, but one can use _min and _max instead. Or std::min, std::max. + +class AsyncBasicResponse: public AsyncWebServerResponse { + private: + String _content; + public: + AsyncBasicResponse(int code, const String& contentType=String(), const String& content=String()); + void _respond(AsyncWebServerRequest *request); + size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); + bool _sourceValid() const { return true; } +}; + +class AsyncAbstractResponse: public AsyncWebServerResponse { + private: + String _head; + // Data is inserted into cache at begin(). + // This is inefficient with vector, but if we use some other container, + // we won't be able to access it as contiguous array of bytes when reading from it, + // so by gaining performance in one place, we'll lose it in another. + std::vector _cache; + size_t _readDataFromCacheOrContent(uint8_t* data, const size_t len); + size_t _fillBufferAndProcessTemplates(uint8_t* buf, size_t maxLen); + protected: + AwsTemplateProcessor _callback; + public: + AsyncAbstractResponse(AwsTemplateProcessor callback=nullptr); + void _respond(AsyncWebServerRequest *request); + size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); + bool _sourceValid() const { return false; } + virtual size_t _fillBuffer(uint8_t *buf __attribute__((unused)), size_t maxLen __attribute__((unused))) { return 0; } +}; + +#ifndef TEMPLATE_PLACEHOLDER +#define TEMPLATE_PLACEHOLDER '%' +#endif + +#define TEMPLATE_PARAM_NAME_LENGTH 32 +class AsyncFileResponse: public AsyncAbstractResponse { + using File = fs::File; + using FS = fs::FS; + private: + File _content; + String _path; + void _setContentType(const String& path); + public: + AsyncFileResponse(FS &fs, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr); + AsyncFileResponse(File content, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr); + ~AsyncFileResponse(); + bool _sourceValid() const { return !!(_content); } + virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; +}; + +class AsyncStreamResponse: public AsyncAbstractResponse { + private: + Stream *_content; + public: + AsyncStreamResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback=nullptr); + bool _sourceValid() const { return !!(_content); } + virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; +}; + +class AsyncCallbackResponse: public AsyncAbstractResponse { + private: + AwsResponseFiller _content; + size_t _filledLength; + public: + AsyncCallbackResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr); + bool _sourceValid() const { return !!(_content); } + virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; +}; + +class AsyncChunkedResponse: public AsyncAbstractResponse { + private: + AwsResponseFiller _content; + size_t _filledLength; + public: + AsyncChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr); + bool _sourceValid() const { return !!(_content); } + virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; +}; + +class AsyncProgmemResponse: public AsyncAbstractResponse { + private: + const uint8_t * _content; + size_t _readLength; + public: + AsyncProgmemResponse(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback=nullptr); + bool _sourceValid() const { return true; } + virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; +}; + +class cbuf; + +class AsyncResponseStream: public AsyncAbstractResponse, public Print { + private: + cbuf *_content; + public: + AsyncResponseStream(const String& contentType, size_t bufferSize); + ~AsyncResponseStream(); + bool _sourceValid() const { return (_state < RESPONSE_END); } + virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; + size_t write(const uint8_t *data, size_t len); + size_t write(uint8_t data); + using Print::write; +}; + +#endif /* ASYNCWEBSERVERRESPONSEIMPL_H_ */ diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebResponses.cpp b/lib/libesp32/ESPAsyncWebServer/src/WebResponses.cpp new file mode 100644 index 000000000..cc66b00ea --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/WebResponses.cpp @@ -0,0 +1,699 @@ +/* + Asynchronous WebServer library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "ESPAsyncWebServer.h" +#include "WebResponseImpl.h" +#include "cbuf.h" + +// Since ESP8266 does not link memchr by default, here's its implementation. +void* memchr(void* ptr, int ch, size_t count) +{ + unsigned char* p = static_cast(ptr); + while(count--) + if(*p++ == static_cast(ch)) + return --p; + return nullptr; +} + + +/* + * Abstract Response + * */ +const char* AsyncWebServerResponse::_responseCodeToString(int code) { + switch (code) { + case 100: return "Continue"; + case 101: return "Switching Protocols"; + case 200: return "OK"; + case 201: return "Created"; + case 202: return "Accepted"; + case 203: return "Non-Authoritative Information"; + case 204: return "No Content"; + case 205: return "Reset Content"; + case 206: return "Partial Content"; + case 300: return "Multiple Choices"; + case 301: return "Moved Permanently"; + case 302: return "Found"; + case 303: return "See Other"; + case 304: return "Not Modified"; + case 305: return "Use Proxy"; + case 307: return "Temporary Redirect"; + case 400: return "Bad Request"; + case 401: return "Unauthorized"; + case 402: return "Payment Required"; + case 403: return "Forbidden"; + case 404: return "Not Found"; + case 405: return "Method Not Allowed"; + case 406: return "Not Acceptable"; + case 407: return "Proxy Authentication Required"; + case 408: return "Request Time-out"; + case 409: return "Conflict"; + case 410: return "Gone"; + case 411: return "Length Required"; + case 412: return "Precondition Failed"; + case 413: return "Request Entity Too Large"; + case 414: return "Request-URI Too Large"; + case 415: return "Unsupported Media Type"; + case 416: return "Requested range not satisfiable"; + case 417: return "Expectation Failed"; + case 500: return "Internal Server Error"; + case 501: return "Not Implemented"; + case 502: return "Bad Gateway"; + case 503: return "Service Unavailable"; + case 504: return "Gateway Time-out"; + case 505: return "HTTP Version not supported"; + default: return ""; + } +} + +AsyncWebServerResponse::AsyncWebServerResponse() + : _code(0) + , _headers(AsyncLinkedList([](AsyncWebHeader *h){ delete h; })) + , _contentType() + , _contentLength(0) + , _sendContentLength(true) + , _chunked(false) + , _headLength(0) + , _sentLength(0) + , _ackedLength(0) + , _writtenLength(0) + , _state(RESPONSE_SETUP) +{ + for(auto header: DefaultHeaders::Instance()) { + _headers.add(new AsyncWebHeader(header->name(), header->value())); + } +} + +AsyncWebServerResponse::~AsyncWebServerResponse(){ + _headers.free(); +} + +void AsyncWebServerResponse::setCode(int code){ + if(_state == RESPONSE_SETUP) + _code = code; +} + +void AsyncWebServerResponse::setContentLength(size_t len){ + if(_state == RESPONSE_SETUP) + _contentLength = len; +} + +void AsyncWebServerResponse::setContentType(const String& type){ + if(_state == RESPONSE_SETUP) + _contentType = type; +} + +void AsyncWebServerResponse::addHeader(const String& name, const String& value){ + _headers.add(new AsyncWebHeader(name, value)); +} + +String AsyncWebServerResponse::_assembleHead(uint8_t version){ + if(version){ + addHeader("Accept-Ranges","none"); + if(_chunked) + addHeader("Transfer-Encoding","chunked"); + } + String out = String(); + int bufSize = 300; + char buf[bufSize]; + + snprintf(buf, bufSize, "HTTP/1.%d %d %s\r\n", version, _code, _responseCodeToString(_code)); + out.concat(buf); + + if(_sendContentLength) { + snprintf(buf, bufSize, "Content-Length: %d\r\n", _contentLength); + out.concat(buf); + } + if(_contentType.length()) { + snprintf(buf, bufSize, "Content-Type: %s\r\n", _contentType.c_str()); + out.concat(buf); + } + + for(const auto& header: _headers){ + snprintf(buf, bufSize, "%s: %s\r\n", header->name().c_str(), header->value().c_str()); + out.concat(buf); + } + _headers.free(); + + out.concat("\r\n"); + _headLength = out.length(); + return out; +} + +bool AsyncWebServerResponse::_started() const { return _state > RESPONSE_SETUP; } +bool AsyncWebServerResponse::_finished() const { return _state > RESPONSE_WAIT_ACK; } +bool AsyncWebServerResponse::_failed() const { return _state == RESPONSE_FAILED; } +bool AsyncWebServerResponse::_sourceValid() const { return false; } +void AsyncWebServerResponse::_respond(AsyncWebServerRequest *request){ _state = RESPONSE_END; request->client()->close(); } +size_t AsyncWebServerResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){ (void)request; (void)len; (void)time; return 0; } + +/* + * String/Code Response + * */ +AsyncBasicResponse::AsyncBasicResponse(int code, const String& contentType, const String& content){ + _code = code; + _content = content; + _contentType = contentType; + if(_content.length()){ + _contentLength = _content.length(); + if(!_contentType.length()) + _contentType = "text/plain"; + } + addHeader("Connection","close"); +} + +void AsyncBasicResponse::_respond(AsyncWebServerRequest *request){ + _state = RESPONSE_HEADERS; + String out = _assembleHead(request->version()); + size_t outLen = out.length(); + size_t space = request->client()->space(); + if(!_contentLength && space >= outLen){ + _writtenLength += request->client()->write(out.c_str(), outLen); + _state = RESPONSE_WAIT_ACK; + } else if(_contentLength && space >= outLen + _contentLength){ + out += _content; + outLen += _contentLength; + _writtenLength += request->client()->write(out.c_str(), outLen); + _state = RESPONSE_WAIT_ACK; + } else if(space && space < outLen){ + String partial = out.substring(0, space); + _content = out.substring(space) + _content; + _contentLength += outLen - space; + _writtenLength += request->client()->write(partial.c_str(), partial.length()); + _state = RESPONSE_CONTENT; + } else if(space > outLen && space < (outLen + _contentLength)){ + size_t shift = space - outLen; + outLen += shift; + _sentLength += shift; + out += _content.substring(0, shift); + _content = _content.substring(shift); + _writtenLength += request->client()->write(out.c_str(), outLen); + _state = RESPONSE_CONTENT; + } else { + _content = out + _content; + _contentLength += outLen; + _state = RESPONSE_CONTENT; + } +} + +size_t AsyncBasicResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){ + (void)time; + _ackedLength += len; + if(_state == RESPONSE_CONTENT){ + size_t available = _contentLength - _sentLength; + size_t space = request->client()->space(); + //we can fit in this packet + if(space > available){ + _writtenLength += request->client()->write(_content.c_str(), available); + _content = String(); + _state = RESPONSE_WAIT_ACK; + return available; + } + //send some data, the rest on ack + String out = _content.substring(0, space); + _content = _content.substring(space); + _sentLength += space; + _writtenLength += request->client()->write(out.c_str(), space); + return space; + } else if(_state == RESPONSE_WAIT_ACK){ + if(_ackedLength >= _writtenLength){ + _state = RESPONSE_END; + } + } + return 0; +} + + +/* + * Abstract Response + * */ + +AsyncAbstractResponse::AsyncAbstractResponse(AwsTemplateProcessor callback): _callback(callback) +{ + // In case of template processing, we're unable to determine real response size + if(callback) { + _contentLength = 0; + _sendContentLength = false; + _chunked = true; + } +} + +void AsyncAbstractResponse::_respond(AsyncWebServerRequest *request){ + addHeader("Connection","close"); + _head = _assembleHead(request->version()); + _state = RESPONSE_HEADERS; + _ack(request, 0, 0); +} + +size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){ + (void)time; + if(!_sourceValid()){ + _state = RESPONSE_FAILED; + request->client()->close(); + return 0; + } + _ackedLength += len; + size_t space = request->client()->space(); + + size_t headLen = _head.length(); + if(_state == RESPONSE_HEADERS){ + if(space >= headLen){ + _state = RESPONSE_CONTENT; + space -= headLen; + } else { + String out = _head.substring(0, space); + _head = _head.substring(space); + _writtenLength += request->client()->write(out.c_str(), out.length()); + return out.length(); + } + } + + if(_state == RESPONSE_CONTENT){ + size_t outLen; + if(_chunked){ + if(space <= 8){ + return 0; + } + outLen = space; + } else if(!_sendContentLength){ + outLen = space; + } else { + outLen = ((_contentLength - _sentLength) > space)?space:(_contentLength - _sentLength); + } + + uint8_t *buf = (uint8_t *)malloc(outLen+headLen); + if (!buf) { + // os_printf("_ack malloc %d failed\n", outLen+headLen); + return 0; + } + + if(headLen){ + memcpy(buf, _head.c_str(), _head.length()); + } + + size_t readLen = 0; + + if(_chunked){ + // HTTP 1.1 allows leading zeros in chunk length. Or spaces may be added. + // See RFC2616 sections 2, 3.6.1. + readLen = _fillBufferAndProcessTemplates(buf+headLen+6, outLen - 8); + if(readLen == RESPONSE_TRY_AGAIN){ + free(buf); + return 0; + } + outLen = sprintf((char*)buf+headLen, "%x", readLen) + headLen; + while(outLen < headLen + 4) buf[outLen++] = ' '; + buf[outLen++] = '\r'; + buf[outLen++] = '\n'; + outLen += readLen; + buf[outLen++] = '\r'; + buf[outLen++] = '\n'; + } else { + readLen = _fillBufferAndProcessTemplates(buf+headLen, outLen); + if(readLen == RESPONSE_TRY_AGAIN){ + free(buf); + return 0; + } + outLen = readLen + headLen; + } + + if(headLen){ + _head = String(); + } + + if(outLen){ + _writtenLength += request->client()->write((const char*)buf, outLen); + } + + if(_chunked){ + _sentLength += readLen; + } else { + _sentLength += outLen - headLen; + } + + free(buf); + + if((_chunked && readLen == 0) || (!_sendContentLength && outLen == 0) || (!_chunked && _sentLength == _contentLength)){ + _state = RESPONSE_WAIT_ACK; + } + return outLen; + + } else if(_state == RESPONSE_WAIT_ACK){ + if(!_sendContentLength || _ackedLength >= _writtenLength){ + _state = RESPONSE_END; + if(!_chunked && !_sendContentLength) + request->client()->close(true); + } + } + return 0; +} + +size_t AsyncAbstractResponse::_readDataFromCacheOrContent(uint8_t* data, const size_t len) +{ + // If we have something in cache, copy it to buffer + const size_t readFromCache = std::min(len, _cache.size()); + if(readFromCache) { + memcpy(data, _cache.data(), readFromCache); + _cache.erase(_cache.begin(), _cache.begin() + readFromCache); + } + // If we need to read more... + const size_t needFromFile = len - readFromCache; + const size_t readFromContent = _fillBuffer(data + readFromCache, needFromFile); + return readFromCache + readFromContent; +} + +size_t AsyncAbstractResponse::_fillBufferAndProcessTemplates(uint8_t* data, size_t len) +{ + if(!_callback) + return _fillBuffer(data, len); + + const size_t originalLen = len; + len = _readDataFromCacheOrContent(data, len); + // Now we've read 'len' bytes, either from cache or from file + // Search for template placeholders + uint8_t* pTemplateStart = data; + while((pTemplateStart < &data[len]) && (pTemplateStart = (uint8_t*)memchr(pTemplateStart, TEMPLATE_PLACEHOLDER, &data[len - 1] - pTemplateStart + 1))) { // data[0] ... data[len - 1] + uint8_t* pTemplateEnd = (pTemplateStart < &data[len - 1]) ? (uint8_t*)memchr(pTemplateStart + 1, TEMPLATE_PLACEHOLDER, &data[len - 1] - pTemplateStart) : nullptr; + // temporary buffer to hold parameter name + uint8_t buf[TEMPLATE_PARAM_NAME_LENGTH + 1]; + String paramName; + // If closing placeholder is found: + if(pTemplateEnd) { + // prepare argument to callback + const size_t paramNameLength = std::min(sizeof(buf) - 1, (unsigned int)(pTemplateEnd - pTemplateStart - 1)); + if(paramNameLength) { + memcpy(buf, pTemplateStart + 1, paramNameLength); + buf[paramNameLength] = 0; + paramName = String(reinterpret_cast(buf)); + } else { // double percent sign encountered, this is single percent sign escaped. + // remove the 2nd percent sign + memmove(pTemplateEnd, pTemplateEnd + 1, &data[len] - pTemplateEnd - 1); + len += _readDataFromCacheOrContent(&data[len - 1], 1) - 1; + ++pTemplateStart; + } + } else if(&data[len - 1] - pTemplateStart + 1 < TEMPLATE_PARAM_NAME_LENGTH + 2) { // closing placeholder not found, check if it's in the remaining file data + memcpy(buf, pTemplateStart + 1, &data[len - 1] - pTemplateStart); + const size_t readFromCacheOrContent = _readDataFromCacheOrContent(buf + (&data[len - 1] - pTemplateStart), TEMPLATE_PARAM_NAME_LENGTH + 2 - (&data[len - 1] - pTemplateStart + 1)); + if(readFromCacheOrContent) { + pTemplateEnd = (uint8_t*)memchr(buf + (&data[len - 1] - pTemplateStart), TEMPLATE_PLACEHOLDER, readFromCacheOrContent); + if(pTemplateEnd) { + // prepare argument to callback + *pTemplateEnd = 0; + paramName = String(reinterpret_cast(buf)); + // Copy remaining read-ahead data into cache + _cache.insert(_cache.begin(), pTemplateEnd + 1, buf + (&data[len - 1] - pTemplateStart) + readFromCacheOrContent); + pTemplateEnd = &data[len - 1]; + } + else // closing placeholder not found in file data, store found percent symbol as is and advance to the next position + { + // but first, store read file data in cache + _cache.insert(_cache.begin(), buf + (&data[len - 1] - pTemplateStart), buf + (&data[len - 1] - pTemplateStart) + readFromCacheOrContent); + ++pTemplateStart; + } + } + else // closing placeholder not found in content data, store found percent symbol as is and advance to the next position + ++pTemplateStart; + } + else // closing placeholder not found in content data, store found percent symbol as is and advance to the next position + ++pTemplateStart; + if(paramName.length()) { + // call callback and replace with result. + // Everything in range [pTemplateStart, pTemplateEnd] can be safely replaced with parameter value. + // Data after pTemplateEnd may need to be moved. + // The first byte of data after placeholder is located at pTemplateEnd + 1. + // It should be located at pTemplateStart + numBytesCopied (to begin right after inserted parameter value). + const String paramValue(_callback(paramName)); + const char* pvstr = paramValue.c_str(); + const unsigned int pvlen = paramValue.length(); + const size_t numBytesCopied = std::min(pvlen, static_cast(&data[originalLen - 1] - pTemplateStart + 1)); + // make room for param value + // 1. move extra data to cache if parameter value is longer than placeholder AND if there is no room to store + if((pTemplateEnd + 1 < pTemplateStart + numBytesCopied) && (originalLen - (pTemplateStart + numBytesCopied - pTemplateEnd - 1) < len)) { + _cache.insert(_cache.begin(), &data[originalLen - (pTemplateStart + numBytesCopied - pTemplateEnd - 1)], &data[len]); + //2. parameter value is longer than placeholder text, push the data after placeholder which not saved into cache further to the end + memmove(pTemplateStart + numBytesCopied, pTemplateEnd + 1, &data[originalLen] - pTemplateStart - numBytesCopied); + len = originalLen; // fix issue with truncated data, not sure if it has any side effects + } else if(pTemplateEnd + 1 != pTemplateStart + numBytesCopied) + //2. Either parameter value is shorter than placeholder text OR there is enough free space in buffer to fit. + // Move the entire data after the placeholder + memmove(pTemplateStart + numBytesCopied, pTemplateEnd + 1, &data[len] - pTemplateEnd - 1); + // 3. replace placeholder with actual value + memcpy(pTemplateStart, pvstr, numBytesCopied); + // If result is longer than buffer, copy the remainder into cache (this could happen only if placeholder text itself did not fit entirely in buffer) + if(numBytesCopied < pvlen) { + _cache.insert(_cache.begin(), pvstr + numBytesCopied, pvstr + pvlen); + } else if(pTemplateStart + numBytesCopied < pTemplateEnd + 1) { // result is copied fully; if result is shorter than placeholder text... + // there is some free room, fill it from cache + const size_t roomFreed = pTemplateEnd + 1 - pTemplateStart - numBytesCopied; + const size_t totalFreeRoom = originalLen - len + roomFreed; + len += _readDataFromCacheOrContent(&data[len - roomFreed], totalFreeRoom) - roomFreed; + } else { // result is copied fully; it is longer than placeholder text + const size_t roomTaken = pTemplateStart + numBytesCopied - pTemplateEnd - 1; + len = std::min(len + roomTaken, originalLen); + } + } + } // while(pTemplateStart) + return len; +} + + +/* + * File Response + * */ + +AsyncFileResponse::~AsyncFileResponse(){ + if(_content) + _content.close(); +} + +void AsyncFileResponse::_setContentType(const String& path){ + if (path.endsWith(".html")) _contentType = "text/html"; + else if (path.endsWith(".htm")) _contentType = "text/html"; + else if (path.endsWith(".css")) _contentType = "text/css"; + else if (path.endsWith(".json")) _contentType = "application/json"; + else if (path.endsWith(".js")) _contentType = "application/javascript"; + else if (path.endsWith(".png")) _contentType = "image/png"; + else if (path.endsWith(".gif")) _contentType = "image/gif"; + else if (path.endsWith(".jpg")) _contentType = "image/jpeg"; + else if (path.endsWith(".ico")) _contentType = "image/x-icon"; + else if (path.endsWith(".svg")) _contentType = "image/svg+xml"; + else if (path.endsWith(".eot")) _contentType = "font/eot"; + else if (path.endsWith(".woff")) _contentType = "font/woff"; + else if (path.endsWith(".woff2")) _contentType = "font/woff2"; + else if (path.endsWith(".ttf")) _contentType = "font/ttf"; + else if (path.endsWith(".xml")) _contentType = "text/xml"; + else if (path.endsWith(".pdf")) _contentType = "application/pdf"; + else if (path.endsWith(".zip")) _contentType = "application/zip"; + else if(path.endsWith(".gz")) _contentType = "application/x-gzip"; + else _contentType = "text/plain"; +} + +AsyncFileResponse::AsyncFileResponse(FS &fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback): AsyncAbstractResponse(callback){ + _code = 200; + _path = path; + + if(!download && !fs.exists(_path) && fs.exists(_path+".gz")){ + _path = _path+".gz"; + addHeader("Content-Encoding", "gzip"); + _callback = nullptr; // Unable to process zipped templates + _sendContentLength = true; + _chunked = false; + } + + _content = fs.open(_path, "r"); + _contentLength = _content.size(); + + if(contentType == "") + _setContentType(path); + else + _contentType = contentType; + + int filenameStart = path.lastIndexOf('/') + 1; + char buf[26+path.length()-filenameStart]; + char* filename = (char*)path.c_str() + filenameStart; + + if(download) { + // set filename and force download + snprintf(buf, sizeof (buf), "attachment; filename=\"%s\"", filename); + } else { + // set filename and force rendering + snprintf(buf, sizeof (buf), "inline; filename=\"%s\"", filename); + } + addHeader("Content-Disposition", buf); +} + +AsyncFileResponse::AsyncFileResponse(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback): AsyncAbstractResponse(callback){ + _code = 200; + _path = path; + + if(!download && String(content.name()).endsWith(".gz") && !path.endsWith(".gz")){ + addHeader("Content-Encoding", "gzip"); + _callback = nullptr; // Unable to process gzipped templates + _sendContentLength = true; + _chunked = false; + } + + _content = content; + _contentLength = _content.size(); + + if(contentType == "") + _setContentType(path); + else + _contentType = contentType; + + int filenameStart = path.lastIndexOf('/') + 1; + char buf[26+path.length()-filenameStart]; + char* filename = (char*)path.c_str() + filenameStart; + + if(download) { + snprintf(buf, sizeof (buf), "attachment; filename=\"%s\"", filename); + } else { + snprintf(buf, sizeof (buf), "inline; filename=\"%s\"", filename); + } + addHeader("Content-Disposition", buf); +} + +size_t AsyncFileResponse::_fillBuffer(uint8_t *data, size_t len){ + return _content.read(data, len); +} + +/* + * Stream Response + * */ + +AsyncStreamResponse::AsyncStreamResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback): AsyncAbstractResponse(callback) { + _code = 200; + _content = &stream; + _contentLength = len; + _contentType = contentType; +} + +size_t AsyncStreamResponse::_fillBuffer(uint8_t *data, size_t len){ + size_t available = _content->available(); + size_t outLen = (available > len)?len:available; + size_t i; + for(i=0;iread(); + return outLen; +} + +/* + * Callback Response + * */ + +AsyncCallbackResponse::AsyncCallbackResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback): AsyncAbstractResponse(templateCallback) { + _code = 200; + _content = callback; + _contentLength = len; + if(!len) + _sendContentLength = false; + _contentType = contentType; + _filledLength = 0; +} + +size_t AsyncCallbackResponse::_fillBuffer(uint8_t *data, size_t len){ + size_t ret = _content(data, len, _filledLength); + if(ret != RESPONSE_TRY_AGAIN){ + _filledLength += ret; + } + return ret; +} + +/* + * Chunked Response + * */ + +AsyncChunkedResponse::AsyncChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor processorCallback): AsyncAbstractResponse(processorCallback) { + _code = 200; + _content = callback; + _contentLength = 0; + _contentType = contentType; + _sendContentLength = false; + _chunked = true; + _filledLength = 0; +} + +size_t AsyncChunkedResponse::_fillBuffer(uint8_t *data, size_t len){ + size_t ret = _content(data, len, _filledLength); + if(ret != RESPONSE_TRY_AGAIN){ + _filledLength += ret; + } + return ret; +} + +/* + * Progmem Response + * */ + +AsyncProgmemResponse::AsyncProgmemResponse(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback): AsyncAbstractResponse(callback) { + _code = code; + _content = content; + _contentType = contentType; + _contentLength = len; + _readLength = 0; +} + +size_t AsyncProgmemResponse::_fillBuffer(uint8_t *data, size_t len){ + size_t left = _contentLength - _readLength; + if (left > len) { + memcpy_P(data, _content + _readLength, len); + _readLength += len; + return len; + } + memcpy_P(data, _content + _readLength, left); + _readLength += left; + return left; +} + + +/* + * Response Stream (You can print/write/printf to it, up to the contentLen bytes) + * */ + +AsyncResponseStream::AsyncResponseStream(const String& contentType, size_t bufferSize){ + _code = 200; + _contentLength = 0; + _contentType = contentType; + _content = new cbuf(bufferSize); +} + +AsyncResponseStream::~AsyncResponseStream(){ + delete _content; +} + +size_t AsyncResponseStream::_fillBuffer(uint8_t *buf, size_t maxLen){ + return _content->read((char*)buf, maxLen); +} + +size_t AsyncResponseStream::write(const uint8_t *data, size_t len){ + if(_started()) + return 0; + + if(len > _content->room()){ + size_t needed = len - _content->room(); + _content->resizeAdd(needed); + } + size_t written = _content->write((const char*)data, len); + _contentLength += written; + return written; +} + +size_t AsyncResponseStream::write(uint8_t data){ + return write(&data, 1); +} diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebServer.cpp b/lib/libesp32/ESPAsyncWebServer/src/WebServer.cpp new file mode 100644 index 000000000..3e2b2e40b --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/WebServer.cpp @@ -0,0 +1,193 @@ +/* + Asynchronous WebServer library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "ESPAsyncWebServer.h" +#include "WebHandlerImpl.h" + +bool ON_STA_FILTER(AsyncWebServerRequest *request) { + return WiFi.localIP() == request->client()->localIP(); +} + +bool ON_AP_FILTER(AsyncWebServerRequest *request) { + return WiFi.localIP() != request->client()->localIP(); +} + + +AsyncWebServer::AsyncWebServer(uint16_t port) + : _server(port) + , _rewrites(AsyncLinkedList([](AsyncWebRewrite* r){ delete r; })) + , _handlers(AsyncLinkedList([](AsyncWebHandler* h){ delete h; })) +{ + _catchAllHandler = new AsyncCallbackWebHandler(); + if(_catchAllHandler == NULL) + return; + _server.onClient([](void *s, AsyncClient* c){ + if(c == NULL) + return; + c->setRxTimeout(3); + AsyncWebServerRequest *r = new AsyncWebServerRequest((AsyncWebServer*)s, c); + if(r == NULL){ + c->close(true); + c->free(); + delete c; + } + }, this); +} + +AsyncWebServer::~AsyncWebServer(){ + reset(); + end(); + if(_catchAllHandler) delete _catchAllHandler; +} + +AsyncWebRewrite& AsyncWebServer::addRewrite(AsyncWebRewrite* rewrite){ + _rewrites.add(rewrite); + return *rewrite; +} + +bool AsyncWebServer::removeRewrite(AsyncWebRewrite *rewrite){ + return _rewrites.remove(rewrite); +} + +AsyncWebRewrite& AsyncWebServer::rewrite(const char* from, const char* to){ + return addRewrite(new AsyncWebRewrite(from, to)); +} + +AsyncWebHandler& AsyncWebServer::addHandler(AsyncWebHandler* handler){ + _handlers.add(handler); + return *handler; +} + +bool AsyncWebServer::removeHandler(AsyncWebHandler *handler){ + return _handlers.remove(handler); +} + +void AsyncWebServer::begin(){ + _server.setNoDelay(true); + _server.begin(); +} + +void AsyncWebServer::end(){ + _server.end(); +} + +#if ASYNC_TCP_SSL_ENABLED +void AsyncWebServer::onSslFileRequest(AcSSlFileHandler cb, void* arg){ + _server.onSslFileRequest(cb, arg); +} + +void AsyncWebServer::beginSecure(const char *cert, const char *key, const char *password){ + _server.beginSecure(cert, key, password); +} +#endif + +void AsyncWebServer::_handleDisconnect(AsyncWebServerRequest *request){ + delete request; +} + +void AsyncWebServer::_rewriteRequest(AsyncWebServerRequest *request){ + for(const auto& r: _rewrites){ + if (r->match(request)){ + request->_url = r->toUrl(); + request->_addGetParams(r->params()); + } + } +} + +void AsyncWebServer::_attachHandler(AsyncWebServerRequest *request){ + for(const auto& h: _handlers){ + if (h->filter(request) && h->canHandle(request)){ + request->setHandler(h); + return; + } + } + + request->addInterestingHeader("ANY"); + request->setHandler(_catchAllHandler); +} + + +AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload, ArBodyHandlerFunction onBody){ + AsyncCallbackWebHandler* handler = new AsyncCallbackWebHandler(); + handler->setUri(uri); + handler->setMethod(method); + handler->onRequest(onRequest); + handler->onUpload(onUpload); + handler->onBody(onBody); + addHandler(handler); + return *handler; +} + +AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload){ + AsyncCallbackWebHandler* handler = new AsyncCallbackWebHandler(); + handler->setUri(uri); + handler->setMethod(method); + handler->onRequest(onRequest); + handler->onUpload(onUpload); + addHandler(handler); + return *handler; +} + +AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest){ + AsyncCallbackWebHandler* handler = new AsyncCallbackWebHandler(); + handler->setUri(uri); + handler->setMethod(method); + handler->onRequest(onRequest); + addHandler(handler); + return *handler; +} + +AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, ArRequestHandlerFunction onRequest){ + AsyncCallbackWebHandler* handler = new AsyncCallbackWebHandler(); + handler->setUri(uri); + handler->onRequest(onRequest); + addHandler(handler); + return *handler; +} + +AsyncStaticWebHandler& AsyncWebServer::serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_control){ + AsyncStaticWebHandler* handler = new AsyncStaticWebHandler(uri, fs, path, cache_control); + addHandler(handler); + return *handler; +} + +void AsyncWebServer::onNotFound(ArRequestHandlerFunction fn){ + _catchAllHandler->onRequest(fn); +} + +void AsyncWebServer::onFileUpload(ArUploadHandlerFunction fn){ + _catchAllHandler->onUpload(fn); +} + +void AsyncWebServer::onRequestBody(ArBodyHandlerFunction fn){ + _catchAllHandler->onBody(fn); +} + +void AsyncWebServer::reset(){ + _rewrites.free(); + _handlers.free(); + + if (_catchAllHandler != NULL){ + _catchAllHandler->onRequest(NULL); + _catchAllHandler->onUpload(NULL); + _catchAllHandler->onBody(NULL); + } +} + diff --git a/lib/libesp32/ESPAsyncWebServer/src/edit.htm b/lib/libesp32/ESPAsyncWebServer/src/edit.htm new file mode 100644 index 000000000..43d498455 --- /dev/null +++ b/lib/libesp32/ESPAsyncWebServer/src/edit.htm @@ -0,0 +1,627 @@ + + + + +ESP Editor + + + + + + +
+
+
+
+ + + + diff --git a/lib/libesp32/gpio_viewer/.gitignore b/lib/libesp32/gpio_viewer/.gitignore new file mode 100644 index 000000000..7f059b39f --- /dev/null +++ b/lib/libesp32/gpio_viewer/.gitignore @@ -0,0 +1,4 @@ +build +sounds +secrets.h +.vscode \ No newline at end of file diff --git a/lib/libesp32/gpio_viewer/LICENSE b/lib/libesp32/gpio_viewer/LICENSE new file mode 100644 index 000000000..c868c9b62 --- /dev/null +++ b/lib/libesp32/gpio_viewer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 thelastoutpostworkshop + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/libesp32/gpio_viewer/README.md b/lib/libesp32/gpio_viewer/README.md new file mode 100644 index 000000000..b7291510a --- /dev/null +++ b/lib/libesp32/gpio_viewer/README.md @@ -0,0 +1,94 @@ +# GPIOViewer Arduino Library to see live GPIO Pins on ESP32 boards + +**Transforms the way you troubleshoot your microcontroller projects**. + +### Youtube Tutorial +[](https://youtu.be/UxkOosaNohU) + +### Installation Arduino IDE (Version 2) +>ℹ️ Make sure you have the latest ESP32 boards by Espressif Systems in your Board Manager
+ +- Install the **GPIOViewer Library with the Arduino IDE Library Manager** or Download the [latest release](https://github.com/thelastoutpostworkshop/gpio_viewer/releases/latest) and install the library in the Arduino IDE : `Sketch > Include Library > Add ZIP Library...` +- Download [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) and install the library in the Arduino IDE `Sketch > Include Library > Add ZIP Library...` +- Install the the [AsyncTCP](https://github.com/dvarrel/AsyncTCP) using the Arduino IDE Library Manager. + +### Installation VSCode + PlatformIO + +Add the following to your platformio.ini file: + +``` +lib_deps = + https://github.com/dvarrel/AsyncTCP.git + https://github.com/me-no-dev/ESPAsyncWebServer.git + https://github.com/thelastoutpostworkshop/gpio_viewer.git +``` + +### Usage +>ℹ️ You can also use get examples provided with the library in the Arduino IDE through the menu `File > Examples > GPIOViewer`
+>ℹ️ You only need to include the library, declare the GPIOViewer and call begin() at the end of your setup, and that's it!
+>ℹ️ The URL to the web GPIO viewer application is printed on the serial monitor
+```c +#include // Must me the first include in your project +GPIOViewer gpio_viewer; + +void setup() +{ + Serial.begin(115200); + + // Comment the next line, If your code aleady include connection to Wifi + gpio_viewer.connectToWifi("Your SSID network", "Your WiFi Password"); + // gpio_viewer.setPort(5555); // You can set the http port, if not set default port is 8080 + + // Your own setup code start here + + // Must be at the end of your setup + // gpio_viewer.setSamplingInterval(25); // You can set the sampling interval in ms, if not set default is 100ms + gpio_viewer.begin(); +} +``` +>ℹ️ The default HTTP port is **8080** and default sampling interval is **100ms**. + +### GPIO Supported + +- Digital +- Analog +- PWM + +### Library Size + +- The GPIOViewer Library adds 50 KB to your projects. +- No worries! All the assets (ex. board images) of the web application are loaded from github pages and don't add to the size of your projects. + +### Performance +- Ensure you have a strong Wifi signal with a good transfer rate. 25ms sampling interval works great on Wifi 6 with 125 Mbps. +- If you get "ERROR: Too many messages queued" on the Serial Monitor, this means the data is not read fast enough by the web application. The data will still be displayed, but with some latency. Reduce the sampling interval or try to improve your Wifi performance. + +### ESP32 Boards Supported +>ℹ️ You can use the "Generic View" in the GPIO Web Application to see GPIO pin activites live even if your board image is not listed
+>ℹ️ You can also request an ESP32 board image addition by [creating a new issue](https://github.com/thelastoutpostworkshop/gpio_viewer/issues). + + +| Description | Image | Pinout | +|--------------------|-------------------------------------|-------------------------------------| +| ESP32 VROOM 32D (38 pins) | ! | | +| ESP32 VROOM 32D (30 pins) | ! || +| ESP32 D1 R32 | ! | | +| ESP32 C3 Wroom-02 | ! || +| ESP32 Wroom-32UE | ! || +| ESP32 EVB | ! || +| ESP32 S3 Wroom-1 | ! || +| Esp32 S2 Mini V1.0.0 | ! || +| ESP32 POE | ! || +| ESP32 C3 Mini | ! || +| ESP32 Pico Kit v4.1 | ! || +| Lilygo T7 Mini32 v1.5 | ! || +| Freenove ESP32-S3 | ! || +| Nano ESP32 | ! || +| StickLite-V3-ESP32S3 | ! || +| XIAO-ESP32-C3 | ! || +| T-Display S3 AMOLED | ! || +| TinyPICO Nano | ! || +| TinyPico V3 | ! || +| Wemos Lolin32 Lite V1 | ! || +| Wemos D1 Mini ESP32 | ! || +| XIAO-ESP32-C3 | ! || diff --git a/lib/libesp32/gpio_viewer/examples/gpioviewer/gpioviewer.ino b/lib/libesp32/gpio_viewer/examples/gpioviewer/gpioviewer.ino new file mode 100644 index 000000000..66def80f3 --- /dev/null +++ b/lib/libesp32/gpio_viewer/examples/gpioviewer/gpioviewer.ino @@ -0,0 +1,30 @@ +/*** +This example is intended to demonstrate the use of the GPIO Viewer Library. + +Tutorial : https://youtu.be/UxkOosaNohU +Documentation : https://github.com/thelastoutpostworkshop/gpio_viewer +***/ + +#include // Must me the first include in your project +GPIOViewer gpio_viewer; + +void setup() +{ + Serial.begin(115200); + + // Comment the next line, If your code aleady include connection to Wifi + gpio_viewer.connectToWifi("Your SSID network", "Your WiFi Password"); + // gpio_viewer.setPort(5555); // You can set the http port, if not set default port is 8080 + + // Your own setup code start here + + // Must be at the end of your setup + // gpio_viewer.setSamplingInterval(25); // You can set the sampling interval in ms, if not set default is 100ms + gpio_viewer.begin(); +} + +// You don't need to change your loop function +void loop() { + +} +// The rest of your code here \ No newline at end of file diff --git a/lib/libesp32/gpio_viewer/gpio_viewer.ino b/lib/libesp32/gpio_viewer/gpio_viewer.ino new file mode 100644 index 000000000..24386c2d3 --- /dev/null +++ b/lib/libesp32/gpio_viewer/gpio_viewer.ino @@ -0,0 +1,149 @@ +#include "src/gpio_viewer.h" +#include +#include // Install this library with the Arduino IDE Library Manager +#include "secrets.h" + +GPIOViewer gpio_viewer; + +#define ROTARY_PIN_A 23 +#define ROTARY_PIN_B 22 +#define ROTARY_PUSH_BUTTON 22 // Not used +SimpleRotary rotary(ROTARY_PIN_A, ROTARY_PIN_B, ROTARY_PUSH_BUTTON); + +int test_digital_pins[] = {33, 25, 26}; +const int testDigitalPinsCount = sizeof(test_digital_pins) / sizeof(test_digital_pins[0]); +int currentLed = 0; // Start with the first LED + +const int analogPinsCount = 3; +int test_analog_pins[analogPinsCount] = {32, 19, 18}; +int analogValue = 0; + +const int freq = 200; +const int resolution = 16; + +struct PWM_PINS +{ + int pin; + int channel; + uint16_t level; +}; + +PWM_PINS test_pwm_pins[] = {{15, 0}, {2, 1}, {0, 2}, {4, 3}}; +const int testPWMPinsCount = sizeof(test_pwm_pins) / sizeof(test_pwm_pins[0]); + +void setup() +{ + Serial.begin(115200); + + gpio_viewer.connectToWifi(ssid, password); // If your code aleady include connection to Wifi, you can comment this line + // gpio_viewer.setPort(5555); // You can set the http port, if not set default port is 8080 + + // Example - Your own setup code start here + test1_setup(); + + // Must be at the end of your setup + gpio_viewer.setSamplingInterval(75); // You can set the sampling interval in ms, if not set, default is 100ms + gpio_viewer.begin(); +} + +void loop() +{ + test1_loop(); +} + +void test1_setup() +{ + uint16_t amount = 0; + for (int i = 0; i < testPWMPinsCount; i++) + { + amount += (65535 / testPWMPinsCount); + ledcSetup(test_pwm_pins[i].channel, freq, resolution); + ledcAttachPin(test_pwm_pins[i].pin, test_pwm_pins[i].channel); + test_pwm_pins[i].level = amount; + } + for (int i = 0; i < testDigitalPinsCount; i++) + { + pinMode(test_digital_pins[i], OUTPUT); + digitalWrite(test_digital_pins[i], LOW); + } + for (int i = 0; i < analogPinsCount; i++) + { + pinMode(test_analog_pins[i], OUTPUT); + } + xTaskCreate(readRotaryEncoderTask, // Task function + "ReadRotaryEncoder", // Name of the task (for debugging) + 2048, // Stack size (bytes) + NULL, // Parameter to pass to the function + 1, // Task priority + NULL); +} +void test1_loop() +{ + for (int i = 0; i < analogPinsCount; i++) + { + analogValue += (i * 3); + analogWrite(test_analog_pins[i], analogValue++); + } + for (int i = 0; i < testPWMPinsCount; i++) + { + ledcWrite(test_pwm_pins[i].channel, test_pwm_pins[i].level); + delay(150); + } + delay(300); + for (int i = 0; i < testPWMPinsCount; i++) + { + ledcWrite(test_pwm_pins[i].channel, test_pwm_pins[i].level / 2); + delay(150); + } + for (int i = 0; i < testDigitalPinsCount; i++) + { + if (digitalRead(test_digital_pins[i]) == LOW) + { + + digitalWrite(test_digital_pins[i], HIGH); + } + else + { + + digitalWrite(test_digital_pins[i], LOW); + } + } + delay(300); +} + +void updateLeds() +{ + for (int i = 0; i < testDigitalPinsCount; i++) + { + digitalWrite(test_digital_pins[i], i == currentLed ? HIGH : LOW); + } +} + +void readRotaryEncoderTask(void *pvParameters) +{ + for (;;) + { // Infinite loop + readRotaryEncoder(); + vTaskDelay(pdMS_TO_TICKS(10)); // Delay for debouncing, adjust as needed + } +} + +void readRotaryEncoder(void) +{ + byte i; + i = rotary.rotate(); + + if (i == 1) + { + currentLed = (currentLed - 1 + testDigitalPinsCount) % testDigitalPinsCount; + updateLeds(); + Serial.println("CounterClockwise"); + } + + if (i == 2) + { + currentLed = (currentLed + 1) % testDigitalPinsCount; + updateLeds(); + Serial.println("Clockwise"); + } +} diff --git a/lib/libesp32/gpio_viewer/keywords.txt b/lib/libesp32/gpio_viewer/keywords.txt new file mode 100644 index 000000000..17719d72c --- /dev/null +++ b/lib/libesp32/gpio_viewer/keywords.txt @@ -0,0 +1,16 @@ +[Keywords] +####################################### +# Datatypes (KEYWORD1) +####################################### +byte +boolean +uint16_t +int16_t +int +enum + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +begin + diff --git a/lib/libesp32/gpio_viewer/library.properties b/lib/libesp32/gpio_viewer/library.properties new file mode 100644 index 000000000..c65ff1276 --- /dev/null +++ b/lib/libesp32/gpio_viewer/library.properties @@ -0,0 +1,11 @@ +name=GPIOViewer +version=1.0.4 +author=The Last Outpost Workshop +maintainer=The Last Outpost Workshop +sentence=Web Application to view GPIO pins live! +paragraph=Works ESP32 +category=Other +keywords=keywords.txt +url=https://github.com/thelastoutpostworkshop/gpio_viewer +architectures=esp32 +depends=AsyncTCP \ No newline at end of file diff --git a/lib/libesp32/gpio_viewer/src/gpio_viewer.h b/lib/libesp32/gpio_viewer/src/gpio_viewer.h new file mode 100644 index 000000000..6a4f1a58d --- /dev/null +++ b/lib/libesp32/gpio_viewer/src/gpio_viewer.h @@ -0,0 +1,360 @@ +#ifndef _GPIOVIEWER_ +#define _GPIOVIEWER_ +#ifndef WEBSERVER_H +// Compatiblity with the Wifi Manager if your using it in your project +#include +#endif +#ifndef WiFi_h +#include +#endif +#ifndef _ESPAsyncWebServer_H_ +#include +#endif +#ifndef ASYNCTCP_H_ +#include +#endif +#ifndef INC_FREERTOS_H +#include +#endif +#ifndef INC_TASK_H +#include +#endif +#endif + +// Start Tasmota specific ************************************* +extern int32_t analogGetChannel2(uint32_t pin); +extern uint8_t ledcReadResolution(uint8_t chan); +// Tasmota Logging +extern void AddLog(uint32_t loglevel, PGM_P formatP, ...); +// 0 1 2 3 4 +//enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE}; +// End Tasmota specific *************************************** + +const char *release = "1.0.5"; + +const String baseURL = "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/"; + +#define maxGPIOPins 49 + +// Global variables to capture PMW pins +const int maxChannels = 64; +int ledcChannelPin[maxChannels][2]; +int ledcChannelPinCount = 0; +int ledcChannelResolution[maxChannels][2]; +int ledcChannelResolutionCount = 0; + +enum pinTypes +{ + digitalPin = 0, + PWMPin = 1, + analogPin = 2 +}; + +class GPIOViewer +{ +public: + GPIOViewer() + { + } + + ~GPIOViewer() + { + delete events; + server->end(); + } + + void setPort(uint16_t port) + { + this->port = port; + } + + void setSamplingInterval(unsigned long samplingInterval) + { + this->samplingInterval = samplingInterval; + } + + void begin() + { +// Serial.printf("ESP32 Core Version %d.%d.%d\n", ESP_ARDUINO_VERSION_MAJOR, ESP_ARDUINO_VERSION_MINOR, ESP_ARDUINO_VERSION_PATCH); +// if (ESP_ARDUINO_VERSION_MAJOR < 2) +// { +// Serial.printf("Your ESP32 Core Version is not supported, update your ESP32 boards to the latest version\n"); +// return; +// } + printPWNTraps(); + checkWifiStatus(); + + server = new AsyncWebServer(port); + + // Set CORS headers for global responses + DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*"); + DefaultHeaders::Instance().addHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); + DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "Content-Type"); + + // Initialize and set up the AsyncEventSource + events = new AsyncEventSource("/events"); + events->onConnect([this](AsyncEventSourceClient *client) + { this->resetStatePins(); }); + + server->addHandler(events); + + // Serve the main page + server->on("/", [this](AsyncWebServerRequest *request) + { request->send_P(200, "text/html", generateIndexHTML().c_str()); }); + + server->on("/release", HTTP_GET, [this](AsyncWebServerRequest *request) + { sendMinReleaseVersion(request); }); + + server->begin(); + + // Create a task for monitoring GPIOs + xTaskCreate(&GPIOViewer::monitorTaskStatic, "GPIO Monitor Task", 2048, this, 1, NULL); + } + + static void monitorTaskStatic(void *pvParameter) + { + static_cast(pvParameter)->monitorTask(); + } + +private: + uint32_t lastPinStates[maxGPIOPins]; + uint16_t port = 8080; + unsigned long samplingInterval = 100; + AsyncWebServer *server; + AsyncEventSource *events; + size_t freeHeap = 0; + String freeRAM = formatBytes(ESP.getFreeSketchSpace()); + + void sendMinReleaseVersion(AsyncWebServerRequest *request) + { + String jsonResponse = "{\"release\": \"" + String(release) + "\"}"; + + request->send(200, "application/json", jsonResponse); + } + void checkWifiStatus(void) + { + if (WiFi.status() == WL_CONNECTED) + { + AddLog(2, "IOV: GPIOViewer Web Application URL is http://%s:%d", WiFi.localIP().toString().c_str(), port); + } + else + { + AddLog(2, "IOV: No network connection"); + } + } + + void printPWNTraps() + { + // Start Tasmota specific ************************************* + for (uint32_t pin = 0; pin < SOC_GPIO_PIN_COUNT; pin++) { + int32_t channel = analogGetChannel2(pin); + if (channel > -1) { + ledcChannelPin[ledcChannelPinCount][0] = pin; + ledcChannelPin[ledcChannelPinCount++][1] = channel; + uint8_t resolution = ledcReadResolution(channel); + ledcChannelResolution[ledcChannelResolutionCount][0] = channel; + ledcChannelResolution[ledcChannelResolutionCount++][1] = resolution; + } + } + // End Tasmota specific *************************************** + + AddLog(3, "IOV: %d pins are PWM", ledcChannelPinCount); + for (int i = 0; i < ledcChannelPinCount; i++) + { + AddLog(3, "IOV: pin %d is using channel %d", ledcChannelPin[i][0], ledcChannelPin[i][1]); + } + AddLog(3, "IOV: %d channels are used", ledcChannelResolutionCount); + for (int i = 0; i < ledcChannelResolutionCount; i++) + { + AddLog(3, "IOV: channel %d resolution is %d bits", ledcChannelResolution[i][0], ledcChannelResolution[i][1]); + } + } + + String generateIndexHTML() + { + String html = "ESP32 GPIO State"; + + html += ""; + html += ""; + html += ""; + html += ""; + + html += ""); + html += ""); + html += ""; + + html += "
\n"; + + html += "
"; + html += "
"; + + // Image + html += "
\n"; + html += "
"; + html += "Board Image\n"; + + html += "
"; + + html += "
"; + + // Append the script variables + String portScript = ""; + html += portScript; + + String eventSource = ""; + html += eventSource; + + String ip = ""; + html += ip; + + String sampling = ""; + html += sampling; + + html += ""; + + html += ""; + return html; + } + + void resetStatePins(void) + { + uint32_t originalValue; + pinTypes pintype; + AddLog(2, "IOV: GPIOViewer Connected, sampling interval is %lums", samplingInterval); + + for (int i = 0; i < maxGPIOPins; i++) + { + lastPinStates[i] = readGPIO(i, &originalValue, &pintype); + } + } + + // Monitor GPIO Values + void monitorTask() + { + uint32_t originalValue; + pinTypes pintype; + while (1) + { + String jsonMessage = "{"; + bool hasChanges = false; + + for (int i = 0; i < maxGPIOPins; i++) + { + int currentState = readGPIO(i, &originalValue, &pintype); + + if (originalValue != lastPinStates[i]) + { + if (hasChanges) + { + jsonMessage += ", "; + } + jsonMessage += "\"" + String(i) + "\": {\"s\": " + currentState + ", \"v\": " + originalValue + ", \"t\": " + pintype + "}"; + lastPinStates[i] = currentState; + hasChanges = true; + } + } + + jsonMessage += "}"; + + if (hasChanges) + { + sendGPIOStates(jsonMessage); + } + + size_t heap = esp_get_free_heap_size(); + if (heap != freeHeap) + { + freeHeap = heap; + events->send(formatBytes(freeHeap).c_str(), "free_heap", millis()); + } + + vTaskDelay(pdMS_TO_TICKS(samplingInterval)); + } + } + + int getLedcChannelForPin(int pin) + { + for (int i = 0; i < ledcChannelPinCount; i++) + { + if (ledcChannelPin[i][0] == pin) + { + return ledcChannelPin[i][1]; + } + } + return -1; // Pin not found, return -1 to indicate no channel is associated + } + int getChannelResolution(int channel) + { + for (int i = 0; i < ledcChannelResolutionCount; i++) + { + if (ledcChannelResolution[i][0] == channel) + { + return ledcChannelResolution[i][1]; + } + } + return -1; // Pin not found, return -1 to indicate no channel is associated + } + + int readGPIO(int gpioNum, uint32_t *originalValue, pinTypes *pintype) + { + int channel = getLedcChannelForPin(gpioNum); + int value; + if (channel != -1) + { + // This is a PWM Pin + value = mapLedcReadTo8Bit(channel, originalValue); + *pintype = PWMPin; + return value; + } + uint8_t analogChannel = analogGetChannel(gpioNum); + if (analogChannel != 0 && analogChannel != 255) + { + // This is an analog pin + // Serial.printf("A Pin %d value=%d,channel=%d\n", gpioNum, value,analogChannel); + + value = mapLedcReadTo8Bit(analogChannel, originalValue); + *pintype = analogPin; + return value; + } + else + { + // This is a digital pin + *pintype = digitalPin; + value = digitalRead(gpioNum); + *originalValue = value; + if (value == 1) + { + return 256; + } + return 0; + } + } + + int mapLedcReadTo8Bit(int channel, uint32_t *originalValue) + { + uint32_t maxDutyCycle = (1 << getChannelResolution(channel)) - 1; + *originalValue = ledcRead(channel); + return map(*originalValue, 0, maxDutyCycle, 0, 255); + } + + void sendGPIOStates(const String &states) + { + events->send(states.c_str(), "gpio-state", millis()); + } + + String formatBytes(size_t bytes) + { + if (bytes < 1024) + { + return String(bytes) + " B"; + } + else if (bytes < (1024 * 1024)) + { + return String(bytes / 1024.0, 2) + " KB"; + } + else + { + return String(bytes / 1024.0 / 1024.0, 2) + " MB"; + } + } +}; \ No newline at end of file From b56e8bb014cf680ad12bd0d543200b5510ce67eb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 4 Jan 2024 22:50:33 +0100 Subject: [PATCH 073/303] Revert "Add libs" This reverts commit 7042b8344cdcffa2e91dc0f9fdb701b0b629ad8d. --- lib/libesp32/AsyncTCP/LICENSE | 165 -- lib/libesp32/AsyncTCP/README.md | 8 - lib/libesp32/AsyncTCP/library.properties | 9 - lib/libesp32/AsyncTCP/src/AsyncTCP.cpp | 1357 --------------- lib/libesp32/AsyncTCP/src/AsyncTCP.h | 217 --- lib/libesp32/ESPAsyncWebServer/.gitignore | 2 - lib/libesp32/ESPAsyncWebServer/.travis.yml | 46 - lib/libesp32/ESPAsyncWebServer/CMakeLists.txt | 17 - lib/libesp32/ESPAsyncWebServer/README.md | 1521 ----------------- lib/libesp32/ESPAsyncWebServer/_config.yml | 1 - lib/libesp32/ESPAsyncWebServer/component.mk | 3 - .../examples/CaptivePortal/CaptivePortal.ino | 47 - .../ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino | 221 --- .../examples/regex_patterns/.test.build_flags | 1 - .../regex_patterns/regex_patterns.ino | 77 - .../examples/simple_server/simple_server.ino | 74 - lib/libesp32/ESPAsyncWebServer/keywords.txt | 3 - lib/libesp32/ESPAsyncWebServer/library.json | 37 - .../ESPAsyncWebServer/library.properties | 9 - .../src/AsyncEventSource.cpp | 368 ---- .../ESPAsyncWebServer/src/AsyncEventSource.h | 133 -- .../ESPAsyncWebServer/src/AsyncJson.h | 254 --- .../ESPAsyncWebServer/src/AsyncWebSocket.cpp | 1294 -------------- .../ESPAsyncWebServer/src/AsyncWebSocket.h | 350 ---- .../src/AsyncWebSynchronization.h | 87 - .../ESPAsyncWebServer/src/ESPAsyncWebServer.h | 471 ----- .../ESPAsyncWebServer/src/SPIFFSEditor.cpp | 544 ------ .../ESPAsyncWebServer/src/SPIFFSEditor.h | 24 - .../ESPAsyncWebServer/src/StringArray.h | 193 --- .../src/WebAuthentication.cpp | 235 --- .../ESPAsyncWebServer/src/WebAuthentication.h | 34 - .../ESPAsyncWebServer/src/WebHandlerImpl.h | 151 -- .../ESPAsyncWebServer/src/WebHandlers.cpp | 220 --- .../ESPAsyncWebServer/src/WebRequest.cpp | 1008 ----------- .../ESPAsyncWebServer/src/WebResponseImpl.h | 136 -- .../ESPAsyncWebServer/src/WebResponses.cpp | 699 -------- .../ESPAsyncWebServer/src/WebServer.cpp | 193 --- lib/libesp32/ESPAsyncWebServer/src/edit.htm | 627 ------- lib/libesp32/gpio_viewer/.gitignore | 4 - lib/libesp32/gpio_viewer/LICENSE | 21 - lib/libesp32/gpio_viewer/README.md | 94 - .../examples/gpioviewer/gpioviewer.ino | 30 - lib/libesp32/gpio_viewer/gpio_viewer.ino | 149 -- lib/libesp32/gpio_viewer/keywords.txt | 16 - lib/libesp32/gpio_viewer/library.properties | 11 - lib/libesp32/gpio_viewer/src/gpio_viewer.h | 360 ---- 46 files changed, 11521 deletions(-) delete mode 100644 lib/libesp32/AsyncTCP/LICENSE delete mode 100644 lib/libesp32/AsyncTCP/README.md delete mode 100644 lib/libesp32/AsyncTCP/library.properties delete mode 100644 lib/libesp32/AsyncTCP/src/AsyncTCP.cpp delete mode 100644 lib/libesp32/AsyncTCP/src/AsyncTCP.h delete mode 100644 lib/libesp32/ESPAsyncWebServer/.gitignore delete mode 100644 lib/libesp32/ESPAsyncWebServer/.travis.yml delete mode 100644 lib/libesp32/ESPAsyncWebServer/CMakeLists.txt delete mode 100644 lib/libesp32/ESPAsyncWebServer/README.md delete mode 100644 lib/libesp32/ESPAsyncWebServer/_config.yml delete mode 100644 lib/libesp32/ESPAsyncWebServer/component.mk delete mode 100644 lib/libesp32/ESPAsyncWebServer/examples/CaptivePortal/CaptivePortal.ino delete mode 100644 lib/libesp32/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino delete mode 100644 lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/.test.build_flags delete mode 100644 lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/regex_patterns.ino delete mode 100644 lib/libesp32/ESPAsyncWebServer/examples/simple_server/simple_server.ino delete mode 100644 lib/libesp32/ESPAsyncWebServer/keywords.txt delete mode 100644 lib/libesp32/ESPAsyncWebServer/library.json delete mode 100644 lib/libesp32/ESPAsyncWebServer/library.properties delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.cpp delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.h delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/AsyncJson.h delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.cpp delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.h delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/AsyncWebSynchronization.h delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/ESPAsyncWebServer.h delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.cpp delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.h delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/StringArray.h delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.cpp delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.h delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebHandlerImpl.h delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebHandlers.cpp delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebRequest.cpp delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebResponseImpl.h delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebResponses.cpp delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/WebServer.cpp delete mode 100644 lib/libesp32/ESPAsyncWebServer/src/edit.htm delete mode 100644 lib/libesp32/gpio_viewer/.gitignore delete mode 100644 lib/libesp32/gpio_viewer/LICENSE delete mode 100644 lib/libesp32/gpio_viewer/README.md delete mode 100644 lib/libesp32/gpio_viewer/examples/gpioviewer/gpioviewer.ino delete mode 100644 lib/libesp32/gpio_viewer/gpio_viewer.ino delete mode 100644 lib/libesp32/gpio_viewer/keywords.txt delete mode 100644 lib/libesp32/gpio_viewer/library.properties delete mode 100644 lib/libesp32/gpio_viewer/src/gpio_viewer.h diff --git a/lib/libesp32/AsyncTCP/LICENSE b/lib/libesp32/AsyncTCP/LICENSE deleted file mode 100644 index 65c5ca88a..000000000 --- a/lib/libesp32/AsyncTCP/LICENSE +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/lib/libesp32/AsyncTCP/README.md b/lib/libesp32/AsyncTCP/README.md deleted file mode 100644 index cde5f1482..000000000 --- a/lib/libesp32/AsyncTCP/README.md +++ /dev/null @@ -1,8 +0,0 @@ -### Async TCP Library for ESP32 Arduino - -This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP32 MCUs. - -This library is the base for [ESPAsyncWebServer](https://github.com/dvarrel/ESPAsyncWebServer) - -## AsyncClient and AsyncServer -The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use. diff --git a/lib/libesp32/AsyncTCP/library.properties b/lib/libesp32/AsyncTCP/library.properties deleted file mode 100644 index 2c6ff0a23..000000000 --- a/lib/libesp32/AsyncTCP/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=AsyncTCP -version=1.1.4 -author=dvarrel -maintainer=dvarrel -sentence=Async TCP Library for ESP32. Forked from https://github.com/me-no-dev/AsyncTCP -paragraph=to build a WebServer, with files saved in flash -category=Communication -url=https://github.com/dvarrel/AsyncTCP -architectures=esp32 diff --git a/lib/libesp32/AsyncTCP/src/AsyncTCP.cpp b/lib/libesp32/AsyncTCP/src/AsyncTCP.cpp deleted file mode 100644 index 89ff6ee32..000000000 --- a/lib/libesp32/AsyncTCP/src/AsyncTCP.cpp +++ /dev/null @@ -1,1357 +0,0 @@ -/* - Asynchronous TCP library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "Arduino.h" - -#include "AsyncTCP.h" -extern "C"{ -#include "lwip/opt.h" -#include "lwip/tcp.h" -#include "lwip/inet.h" -#include "lwip/dns.h" -#include "lwip/err.h" -} -#include "esp_task_wdt.h" - -/* - * TCP/IP Event Task - * */ - -typedef enum { - LWIP_TCP_SENT, LWIP_TCP_RECV, LWIP_TCP_FIN, LWIP_TCP_ERROR, LWIP_TCP_POLL, LWIP_TCP_CLEAR, LWIP_TCP_ACCEPT, LWIP_TCP_CONNECTED, LWIP_TCP_DNS -} lwip_event_t; - -typedef struct { - lwip_event_t event; - void *arg; - union { - struct { - void * pcb; - int8_t err; - } connected; - struct { - int8_t err; - } error; - struct { - tcp_pcb * pcb; - uint16_t len; - } sent; - struct { - tcp_pcb * pcb; - pbuf * pb; - int8_t err; - } recv; - struct { - tcp_pcb * pcb; - int8_t err; - } fin; - struct { - tcp_pcb * pcb; - } poll; - struct { - AsyncClient * client; - } accept; - struct { - const char * name; - ip_addr_t addr; - } dns; - }; -} lwip_event_packet_t; - -static xQueueHandle _async_queue; -static TaskHandle_t _async_service_task_handle = NULL; - - -SemaphoreHandle_t _slots_lock; -const int _number_of_closed_slots = CONFIG_LWIP_MAX_ACTIVE_TCP; -static uint32_t _closed_slots[_number_of_closed_slots]; -static uint32_t _closed_index = []() { - _slots_lock = xSemaphoreCreateBinary(); - xSemaphoreGive(_slots_lock); - for (int i = 0; i < _number_of_closed_slots; ++ i) { - _closed_slots[i] = 1; - } - return 1; -}(); - - -static inline bool _init_async_event_queue(){ - if(!_async_queue){ - _async_queue = xQueueCreate(32, sizeof(lwip_event_packet_t *)); - if(!_async_queue){ - return false; - } - } - return true; -} - -static inline bool _send_async_event(lwip_event_packet_t ** e){ - return _async_queue && xQueueSend(_async_queue, e, portMAX_DELAY) == pdPASS; -} - -static inline bool _prepend_async_event(lwip_event_packet_t ** e){ - return _async_queue && xQueueSendToFront(_async_queue, e, portMAX_DELAY) == pdPASS; -} - -static inline bool _get_async_event(lwip_event_packet_t ** e){ - return _async_queue && xQueueReceive(_async_queue, e, portMAX_DELAY) == pdPASS; -} - -static bool _remove_events_with_arg(void * arg){ - lwip_event_packet_t * first_packet = NULL; - lwip_event_packet_t * packet = NULL; - - if(!_async_queue){ - return false; - } - //figure out which is the first packet so we can keep the order - while(!first_packet){ - if(xQueueReceive(_async_queue, &first_packet, 0) != pdPASS){ - return false; - } - //discard packet if matching - if((int)first_packet->arg == (int)arg){ - free(first_packet); - first_packet = NULL; - //return first packet to the back of the queue - } else if(xQueueSend(_async_queue, &first_packet, portMAX_DELAY) != pdPASS){ - return false; - } - } - - while(xQueuePeek(_async_queue, &packet, 0) == pdPASS && packet != first_packet){ - if(xQueueReceive(_async_queue, &packet, 0) != pdPASS){ - return false; - } - if((int)packet->arg == (int)arg){ - free(packet); - packet = NULL; - } else if(xQueueSend(_async_queue, &packet, portMAX_DELAY) != pdPASS){ - return false; - } - } - return true; -} - -static void _handle_async_event(lwip_event_packet_t * e){ - if(e->arg == NULL){ - // do nothing when arg is NULL - //ets_printf("event arg == NULL: 0x%08x\n", e->recv.pcb); - } else if(e->event == LWIP_TCP_CLEAR){ - _remove_events_with_arg(e->arg); - } else if(e->event == LWIP_TCP_RECV){ - //ets_printf("-R: 0x%08x\n", e->recv.pcb); - AsyncClient::_s_recv(e->arg, e->recv.pcb, e->recv.pb, e->recv.err); - } else if(e->event == LWIP_TCP_FIN){ - //ets_printf("-F: 0x%08x\n", e->fin.pcb); - AsyncClient::_s_fin(e->arg, e->fin.pcb, e->fin.err); - } else if(e->event == LWIP_TCP_SENT){ - //ets_printf("-S: 0x%08x\n", e->sent.pcb); - AsyncClient::_s_sent(e->arg, e->sent.pcb, e->sent.len); - } else if(e->event == LWIP_TCP_POLL){ - //ets_printf("-P: 0x%08x\n", e->poll.pcb); - AsyncClient::_s_poll(e->arg, e->poll.pcb); - } else if(e->event == LWIP_TCP_ERROR){ - //ets_printf("-E: 0x%08x %d\n", e->arg, e->error.err); - AsyncClient::_s_error(e->arg, e->error.err); - } else if(e->event == LWIP_TCP_CONNECTED){ - //ets_printf("C: 0x%08x 0x%08x %d\n", e->arg, e->connected.pcb, e->connected.err); - AsyncClient::_s_connected(e->arg, e->connected.pcb, e->connected.err); - } else if(e->event == LWIP_TCP_ACCEPT){ - //ets_printf("A: 0x%08x 0x%08x\n", e->arg, e->accept.client); - AsyncServer::_s_accepted(e->arg, e->accept.client); - } else if(e->event == LWIP_TCP_DNS){ - //ets_printf("D: 0x%08x %s = %s\n", e->arg, e->dns.name, ipaddr_ntoa(&e->dns.addr)); - AsyncClient::_s_dns_found(e->dns.name, &e->dns.addr, e->arg); - } - free((void*)(e)); -} - -static void _async_service_task(void *pvParameters){ - lwip_event_packet_t * packet = NULL; - for (;;) { - if(_get_async_event(&packet)){ -#if CONFIG_ASYNC_TCP_USE_WDT - if(esp_task_wdt_add(NULL) != ESP_OK){ - log_e("Failed to add async task to WDT"); - } -#endif - _handle_async_event(packet); -#if CONFIG_ASYNC_TCP_USE_WDT - if(esp_task_wdt_delete(NULL) != ESP_OK){ - log_e("Failed to remove loop task from WDT"); - } -#endif - } - } - vTaskDelete(NULL); - _async_service_task_handle = NULL; -} -/* -static void _stop_async_task(){ - if(_async_service_task_handle){ - vTaskDelete(_async_service_task_handle); - _async_service_task_handle = NULL; - } -} -*/ -static bool _start_async_task(){ - if(!_init_async_event_queue()){ - return false; - } - if(!_async_service_task_handle){ - xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); - if(!_async_service_task_handle){ - return false; - } - } - return true; -} - -/* - * LwIP Callbacks - * */ - -static int8_t _tcp_clear_events(void * arg) { - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_CLEAR; - e->arg = arg; - if (!_prepend_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; -} - -static int8_t _tcp_connected(void * arg, tcp_pcb * pcb, int8_t err) { - //ets_printf("+C: 0x%08x\n", pcb); - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_CONNECTED; - e->arg = arg; - e->connected.pcb = pcb; - e->connected.err = err; - if (!_prepend_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; -} - -static int8_t _tcp_poll(void * arg, struct tcp_pcb * pcb) { - //ets_printf("+P: 0x%08x\n", pcb); - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_POLL; - e->arg = arg; - e->poll.pcb = pcb; - if (!_send_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; -} - -static int8_t _tcp_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, int8_t err) { - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - e->arg = arg; - if(pb){ - //ets_printf("+R: 0x%08x\n", pcb); - e->event = LWIP_TCP_RECV; - e->recv.pcb = pcb; - e->recv.pb = pb; - e->recv.err = err; - } else { - //ets_printf("+F: 0x%08x\n", pcb); - e->event = LWIP_TCP_FIN; - e->fin.pcb = pcb; - e->fin.err = err; - //close the PCB in LwIP thread - AsyncClient::_s_lwip_fin(e->arg, e->fin.pcb, e->fin.err); - } - if (!_send_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; -} - -static int8_t _tcp_sent(void * arg, struct tcp_pcb * pcb, uint16_t len) { - //ets_printf("+S: 0x%08x\n", pcb); - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_SENT; - e->arg = arg; - e->sent.pcb = pcb; - e->sent.len = len; - if (!_send_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; -} - -static void _tcp_error(void * arg, int8_t err) { - //ets_printf("+E: 0x%08x\n", arg); - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_ERROR; - e->arg = arg; - e->error.err = err; - if (!_send_async_event(&e)) { - free((void*)(e)); - } -} - -static void _tcp_dns_found(const char * name, struct ip_addr * ipaddr, void * arg) { - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - //ets_printf("+DNS: name=%s ipaddr=0x%08x arg=%x\n", name, ipaddr, arg); - e->event = LWIP_TCP_DNS; - e->arg = arg; - e->dns.name = name; - if (ipaddr) { - memcpy(&e->dns.addr, ipaddr, sizeof(struct ip_addr)); - } else { - memset(&e->dns.addr, 0, sizeof(e->dns.addr)); - } - if (!_send_async_event(&e)) { - free((void*)(e)); - } -} - -//Used to switch out from LwIP thread -static int8_t _tcp_accept(void * arg, AsyncClient * client) { - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_ACCEPT; - e->arg = arg; - e->accept.client = client; - if (!_prepend_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; -} - -/* - * TCP/IP API Calls - * */ - -#include "lwip/priv/tcpip_priv.h" - -typedef struct { - struct tcpip_api_call_data call; - tcp_pcb * pcb; - int8_t closed_slot; - int8_t err; - union { - struct { - const char* data; - size_t size; - uint8_t apiflags; - } write; - size_t received; - struct { - ip_addr_t * addr; - uint16_t port; - tcp_connected_fn cb; - } connect; - struct { - ip_addr_t * addr; - uint16_t port; - } bind; - uint8_t backlog; - }; -} tcp_api_call_t; - -static err_t _tcp_output_api(struct tcpip_api_call_data *api_call_msg){ - tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; - msg->err = ERR_CONN; - if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { - msg->err = tcp_output(msg->pcb); - } - return msg->err; -} - -static esp_err_t _tcp_output(tcp_pcb * pcb, int8_t closed_slot) { - if(!pcb){ - return ERR_CONN; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_write_api(struct tcpip_api_call_data *api_call_msg){ - tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; - msg->err = ERR_CONN; - if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { - msg->err = tcp_write(msg->pcb, msg->write.data, msg->write.size, msg->write.apiflags); - } - return msg->err; -} - -static esp_err_t _tcp_write(tcp_pcb * pcb, int8_t closed_slot, const char* data, size_t size, uint8_t apiflags) { - if(!pcb){ - return ERR_CONN; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - msg.write.data = data; - msg.write.size = size; - msg.write.apiflags = apiflags; - tcpip_api_call(_tcp_write_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_recved_api(struct tcpip_api_call_data *api_call_msg){ - tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; - msg->err = ERR_CONN; - if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { - msg->err = 0; - tcp_recved(msg->pcb, msg->received); - } - return msg->err; -} - -static esp_err_t _tcp_recved(tcp_pcb * pcb, int8_t closed_slot, size_t len) { - if(!pcb){ - return ERR_CONN; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - msg.received = len; - tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg){ - tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; - msg->err = ERR_CONN; - if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { - msg->err = tcp_close(msg->pcb); - } - return msg->err; -} - -static esp_err_t _tcp_close(tcp_pcb * pcb, int8_t closed_slot) { - if(!pcb){ - return ERR_CONN; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_abort_api(struct tcpip_api_call_data *api_call_msg){ - tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; - msg->err = ERR_CONN; - if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { - tcp_abort(msg->pcb); - } - return msg->err; -} - -static esp_err_t _tcp_abort(tcp_pcb * pcb, int8_t closed_slot) { - if(!pcb){ - return ERR_CONN; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_connect_api(struct tcpip_api_call_data *api_call_msg){ - tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; - msg->err = tcp_connect(msg->pcb, msg->connect.addr, msg->connect.port, msg->connect.cb); - return msg->err; -} - -static esp_err_t _tcp_connect(tcp_pcb * pcb, int8_t closed_slot, ip_addr_t * addr, uint16_t port, tcp_connected_fn cb) { - if(!pcb){ - return ESP_FAIL; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - msg.connect.addr = addr; - msg.connect.port = port; - msg.connect.cb = cb; - tcpip_api_call(_tcp_connect_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_bind_api(struct tcpip_api_call_data *api_call_msg){ - tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; - msg->err = tcp_bind(msg->pcb, msg->bind.addr, msg->bind.port); - return msg->err; -} - -static esp_err_t _tcp_bind(tcp_pcb * pcb, ip_addr_t * addr, uint16_t port) { - if(!pcb){ - return ESP_FAIL; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = -1; - msg.bind.addr = addr; - msg.bind.port = port; - tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_listen_api(struct tcpip_api_call_data *api_call_msg){ - tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; - msg->err = 0; - msg->pcb = tcp_listen_with_backlog(msg->pcb, msg->backlog); - return msg->err; -} - -static tcp_pcb * _tcp_listen_with_backlog(tcp_pcb * pcb, uint8_t backlog) { - if(!pcb){ - return NULL; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = -1; - msg.backlog = backlog?backlog:0xFF; - tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call_data*)&msg); - return msg.pcb; -} - - - -/* - Async TCP Client - */ - -AsyncClient::AsyncClient(tcp_pcb* pcb) -: _connect_cb(0) -, _connect_cb_arg(0) -, _discard_cb(0) -, _discard_cb_arg(0) -, _sent_cb(0) -, _sent_cb_arg(0) -, _error_cb(0) -, _error_cb_arg(0) -, _recv_cb(0) -, _recv_cb_arg(0) -, _pb_cb(0) -, _pb_cb_arg(0) -, _timeout_cb(0) -, _timeout_cb_arg(0) -, _pcb_busy(false) -, _pcb_sent_at(0) -, _ack_pcb(true) -, _rx_last_packet(0) -, _rx_since_timeout(0) -, _ack_timeout(ASYNC_MAX_ACK_TIME) -, _connect_port(0) -, prev(NULL) -, next(NULL) -{ - _pcb = pcb; - _closed_slot = -1; - if(_pcb){ - _allocate_closed_slot(); - _rx_last_packet = millis(); - tcp_arg(_pcb, this); - tcp_recv(_pcb, &_tcp_recv); - tcp_sent(_pcb, &_tcp_sent); - tcp_err(_pcb, &_tcp_error); - tcp_poll(_pcb, &_tcp_poll, 1); - } -} - -AsyncClient::~AsyncClient(){ - if(_pcb) { - _close(); - } - _free_closed_slot(); -} - -/* - * Operators - * */ - -AsyncClient& AsyncClient::operator=(const AsyncClient& other){ - if (_pcb) { - _close(); - } - - _pcb = other._pcb; - _closed_slot = other._closed_slot; - if (_pcb) { - _rx_last_packet = millis(); - tcp_arg(_pcb, this); - tcp_recv(_pcb, &_tcp_recv); - tcp_sent(_pcb, &_tcp_sent); - tcp_err(_pcb, &_tcp_error); - tcp_poll(_pcb, &_tcp_poll, 1); - } - return *this; -} - -bool AsyncClient::operator==(const AsyncClient &other) { - return _pcb == other._pcb; -} - -AsyncClient & AsyncClient::operator+=(const AsyncClient &other) { - if(next == NULL){ - next = (AsyncClient*)(&other); - next->prev = this; - } else { - AsyncClient *c = next; - while(c->next != NULL) { - c = c->next; - } - c->next =(AsyncClient*)(&other); - c->next->prev = c; - } - return *this; -} - -/* - * Callback Setters - * */ - -void AsyncClient::onConnect(AcConnectHandler cb, void* arg){ - _connect_cb = cb; - _connect_cb_arg = arg; -} - -void AsyncClient::onDisconnect(AcConnectHandler cb, void* arg){ - _discard_cb = cb; - _discard_cb_arg = arg; -} - -void AsyncClient::onAck(AcAckHandler cb, void* arg){ - _sent_cb = cb; - _sent_cb_arg = arg; -} - -void AsyncClient::onError(AcErrorHandler cb, void* arg){ - _error_cb = cb; - _error_cb_arg = arg; -} - -void AsyncClient::onData(AcDataHandler cb, void* arg){ - _recv_cb = cb; - _recv_cb_arg = arg; -} - -void AsyncClient::onPacket(AcPacketHandler cb, void* arg){ - _pb_cb = cb; - _pb_cb_arg = arg; -} - -void AsyncClient::onTimeout(AcTimeoutHandler cb, void* arg){ - _timeout_cb = cb; - _timeout_cb_arg = arg; -} - -void AsyncClient::onPoll(AcConnectHandler cb, void* arg){ - _poll_cb = cb; - _poll_cb_arg = arg; -} - -/* - * Main Public Methods - * */ - -bool AsyncClient::connect(IPAddress ip, uint16_t port){ - if (_pcb){ - log_w("already connected, state %d", _pcb->state); - return false; - } - if(!_start_async_task()){ - log_e("failed to start task"); - return false; - } - - ip_addr_t addr; - addr.type = IPADDR_TYPE_V4; - addr.u_addr.ip4.addr = ip; - - tcp_pcb* pcb = tcp_new_ip_type(IPADDR_TYPE_V4); - if (!pcb){ - log_e("pcb == NULL"); - return false; - } - - tcp_arg(pcb, this); - tcp_err(pcb, &_tcp_error); - tcp_recv(pcb, &_tcp_recv); - tcp_sent(pcb, &_tcp_sent); - tcp_poll(pcb, &_tcp_poll, 1); - //_tcp_connect(pcb, &addr, port,(tcp_connected_fn)&_s_connected); - _tcp_connect(pcb, _closed_slot, &addr, port,(tcp_connected_fn)&_tcp_connected); - return true; -} - -bool AsyncClient::connect(const char* host, uint16_t port){ - ip_addr_t addr; - - if(!_start_async_task()){ - log_e("failed to start task"); - return false; - } - - err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_tcp_dns_found, this); - if(err == ERR_OK) { - return connect(IPAddress(addr.u_addr.ip4.addr), port); - } else if(err == ERR_INPROGRESS) { - _connect_port = port; - return true; - } - log_e("error: %d", err); - return false; -} - -void AsyncClient::close(bool now){ - if(_pcb){ - _tcp_recved(_pcb, _closed_slot, _rx_ack_len); - } - _close(); -} - -int8_t AsyncClient::abort(){ - if(_pcb) { - _tcp_abort(_pcb, _closed_slot ); - _pcb = NULL; - } - return ERR_ABRT; -} - -size_t AsyncClient::space(){ - if((_pcb != NULL) && (_pcb->state == 4)){ - return tcp_sndbuf(_pcb); - } - return 0; -} - -size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) { - if(!_pcb || size == 0 || data == NULL) { - return 0; - } - size_t room = space(); - if(!room) { - return 0; - } - size_t will_send = (room < size) ? room : size; - int8_t err = ERR_OK; - err = _tcp_write(_pcb, _closed_slot, data, will_send, apiflags); - if(err != ERR_OK) { - return 0; - } - return will_send; -} - -bool AsyncClient::send(){ - int8_t err = ERR_OK; - err = _tcp_output(_pcb, _closed_slot); - if(err == ERR_OK){ - _pcb_busy = true; - _pcb_sent_at = millis(); - return true; - } - return false; -} - -size_t AsyncClient::ack(size_t len){ - if(len > _rx_ack_len) - len = _rx_ack_len; - if(len){ - _tcp_recved(_pcb, _closed_slot, len); - } - _rx_ack_len -= len; - return len; -} - -void AsyncClient::ackPacket(struct pbuf * pb){ - if(!pb){ - return; - } - _tcp_recved(_pcb, _closed_slot, pb->len); - pbuf_free(pb); -} - -/* - * Main Private Methods - * */ - -int8_t AsyncClient::_close(){ - //ets_printf("X: 0x%08x\n", (uint32_t)this); - int8_t err = ERR_OK; - if(_pcb) { - //log_i(""); - tcp_arg(_pcb, NULL); - tcp_sent(_pcb, NULL); - tcp_recv(_pcb, NULL); - tcp_err(_pcb, NULL); - tcp_poll(_pcb, NULL, 0); - _tcp_clear_events(this); - err = _tcp_close(_pcb, _closed_slot); - if(err != ERR_OK) { - err = abort(); - } - _pcb = NULL; - if(_discard_cb) { - _discard_cb(_discard_cb_arg, this); - } - } - return err; -} - -void AsyncClient::_allocate_closed_slot(){ - xSemaphoreTake(_slots_lock, portMAX_DELAY); - uint32_t closed_slot_min_index = 0; - for (int i = 0; i < _number_of_closed_slots; ++ i) { - if ((_closed_slot == -1 || _closed_slots[i] <= closed_slot_min_index) && _closed_slots[i] != 0) { - closed_slot_min_index = _closed_slots[i]; - _closed_slot = i; - } - } - if (_closed_slot != -1) { - _closed_slots[_closed_slot] = 0; - } - xSemaphoreGive(_slots_lock); -} - -void AsyncClient::_free_closed_slot(){ - if (_closed_slot != -1) { - _closed_slots[_closed_slot] = _closed_index; - _closed_slot = -1; - ++ _closed_index; - } -} - -/* - * Private Callbacks - * */ - -int8_t AsyncClient::_connected(void* pcb, int8_t err){ - _pcb = reinterpret_cast(pcb); - if(_pcb){ - _rx_last_packet = millis(); - _pcb_busy = false; -// tcp_recv(_pcb, &_tcp_recv); -// tcp_sent(_pcb, &_tcp_sent); -// tcp_poll(_pcb, &_tcp_poll, 1); - } - if(_connect_cb) { - _connect_cb(_connect_cb_arg, this); - } - return ERR_OK; -} - -void AsyncClient::_error(int8_t err) { - if(_pcb){ - tcp_arg(_pcb, NULL); - if(_pcb->state == LISTEN) { - tcp_sent(_pcb, NULL); - tcp_recv(_pcb, NULL); - tcp_err(_pcb, NULL); - tcp_poll(_pcb, NULL, 0); - } - _pcb = NULL; - } - if(_error_cb) { - _error_cb(_error_cb_arg, this, err); - } - if(_discard_cb) { - _discard_cb(_discard_cb_arg, this); - } -} - -//In LwIP Thread -int8_t AsyncClient::_lwip_fin(tcp_pcb* pcb, int8_t err) { - if(!_pcb || pcb != _pcb){ - log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); - return ERR_OK; - } - tcp_arg(_pcb, NULL); - if(_pcb->state == LISTEN) { - tcp_sent(_pcb, NULL); - tcp_recv(_pcb, NULL); - tcp_err(_pcb, NULL); - tcp_poll(_pcb, NULL, 0); - } - if(tcp_close(_pcb) != ERR_OK) { - tcp_abort(_pcb); - } - _free_closed_slot(); - _pcb = NULL; - return ERR_OK; -} - -//In Async Thread -int8_t AsyncClient::_fin(tcp_pcb* pcb, int8_t err) { - _tcp_clear_events(this); - if(_discard_cb) { - _discard_cb(_discard_cb_arg, this); - } - return ERR_OK; -} - -int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { - _rx_last_packet = millis(); - //log_i("%u", len); - _pcb_busy = false; - if(_sent_cb) { - _sent_cb(_sent_cb_arg, this, len, (millis() - _pcb_sent_at)); - } - return ERR_OK; -} - -int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { - while(pb != NULL) { - _rx_last_packet = millis(); - //we should not ack before we assimilate the data - _ack_pcb = true; - pbuf *b = pb; - pb = b->next; - b->next = NULL; - if(_pb_cb){ - _pb_cb(_pb_cb_arg, this, b); - } else { - if(_recv_cb) { - _recv_cb(_recv_cb_arg, this, b->payload, b->len); - } - if(!_ack_pcb) { - _rx_ack_len += b->len; - } else if(_pcb) { - _tcp_recved(_pcb, _closed_slot, b->len); - } - pbuf_free(b); - } - } - return ERR_OK; -} - -int8_t AsyncClient::_poll(tcp_pcb* pcb){ - if(!_pcb){ - log_w("pcb is NULL"); - return ERR_OK; - } - if(pcb != _pcb){ - log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); - return ERR_OK; - } - - uint32_t now = millis(); - - // ACK Timeout - if(_pcb_busy && _ack_timeout && (now - _pcb_sent_at) >= _ack_timeout){ - _pcb_busy = false; - log_w("ack timeout %d", pcb->state); - if(_timeout_cb) - _timeout_cb(_timeout_cb_arg, this, (now - _pcb_sent_at)); - return ERR_OK; - } - // RX Timeout - if(_rx_since_timeout && (now - _rx_last_packet) >= (_rx_since_timeout * 1000)){ - log_w("rx timeout %d", pcb->state); - _close(); - return ERR_OK; - } - // Everything is fine - if(_poll_cb) { - _poll_cb(_poll_cb_arg, this); - } - return ERR_OK; -} - -void AsyncClient::_dns_found(struct ip_addr *ipaddr){ - if(ipaddr && ipaddr->u_addr.ip4.addr){ - connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port); - } else { - if(_error_cb) { - _error_cb(_error_cb_arg, this, -55); - } - if(_discard_cb) { - _discard_cb(_discard_cb_arg, this); - } - } -} - -/* - * Public Helper Methods - * */ - -void AsyncClient::stop() { - close(false); -} - -bool AsyncClient::free(){ - if(!_pcb) { - return true; - } - if(_pcb->state == 0 || _pcb->state > 4) { - return true; - } - return false; -} - -size_t AsyncClient::write(const char* data) { - if(data == NULL) { - return 0; - } - return write(data, strlen(data)); -} - -size_t AsyncClient::write(const char* data, size_t size, uint8_t apiflags) { - size_t will_send = add(data, size, apiflags); - if(!will_send || !send()) { - return 0; - } - return will_send; -} - -void AsyncClient::setRxTimeout(uint32_t timeout){ - _rx_since_timeout = timeout; -} - -uint32_t AsyncClient::getRxTimeout(){ - return _rx_since_timeout; -} - -uint32_t AsyncClient::getAckTimeout(){ - return _ack_timeout; -} - -void AsyncClient::setAckTimeout(uint32_t timeout){ - _ack_timeout = timeout; -} - -void AsyncClient::setNoDelay(bool nodelay){ - if(!_pcb) { - return; - } - if(nodelay) { - tcp_nagle_disable(_pcb); - } else { - tcp_nagle_enable(_pcb); - } -} - -bool AsyncClient::getNoDelay(){ - if(!_pcb) { - return false; - } - return tcp_nagle_disabled(_pcb); -} - -uint16_t AsyncClient::getMss(){ - if(!_pcb) { - return 0; - } - return tcp_mss(_pcb); -} - -uint32_t AsyncClient::getRemoteAddress() { - if(!_pcb) { - return 0; - } - return _pcb->remote_ip.u_addr.ip4.addr; -} - -uint16_t AsyncClient::getRemotePort() { - if(!_pcb) { - return 0; - } - return _pcb->remote_port; -} - -uint32_t AsyncClient::getLocalAddress() { - if(!_pcb) { - return 0; - } - return _pcb->local_ip.u_addr.ip4.addr; -} - -uint16_t AsyncClient::getLocalPort() { - if(!_pcb) { - return 0; - } - return _pcb->local_port; -} - -IPAddress AsyncClient::remoteIP() { - return IPAddress(getRemoteAddress()); -} - -uint16_t AsyncClient::remotePort() { - return getRemotePort(); -} - -IPAddress AsyncClient::localIP() { - return IPAddress(getLocalAddress()); -} - -uint16_t AsyncClient::localPort() { - return getLocalPort(); -} - -uint8_t AsyncClient::state() { - if(!_pcb) { - return 0; - } - return _pcb->state; -} - -bool AsyncClient::connected(){ - if (!_pcb) { - return false; - } - return _pcb->state == 4; -} - -bool AsyncClient::connecting(){ - if (!_pcb) { - return false; - } - return _pcb->state > 0 && _pcb->state < 4; -} - -bool AsyncClient::disconnecting(){ - if (!_pcb) { - return false; - } - return _pcb->state > 4 && _pcb->state < 10; -} - -bool AsyncClient::disconnected(){ - if (!_pcb) { - return true; - } - return _pcb->state == 0 || _pcb->state == 10; -} - -bool AsyncClient::freeable(){ - if (!_pcb) { - return true; - } - return _pcb->state == 0 || _pcb->state > 4; -} - -bool AsyncClient::canSend(){ - return space() > 0; -} - -const char * AsyncClient::errorToString(int8_t error){ - switch(error){ - case ERR_OK: return "OK"; - case ERR_MEM: return "Out of memory error"; - case ERR_BUF: return "Buffer error"; - case ERR_TIMEOUT: return "Timeout"; - case ERR_RTE: return "Routing problem"; - case ERR_INPROGRESS: return "Operation in progress"; - case ERR_VAL: return "Illegal value"; - case ERR_WOULDBLOCK: return "Operation would block"; - case ERR_USE: return "Address in use"; - case ERR_ALREADY: return "Already connected"; - case ERR_CONN: return "Not connected"; - case ERR_IF: return "Low-level netif error"; - case ERR_ABRT: return "Connection aborted"; - case ERR_RST: return "Connection reset"; - case ERR_CLSD: return "Connection closed"; - case ERR_ARG: return "Illegal argument"; - case -55: return "DNS failed"; - default: return "UNKNOWN"; - } -} - -const char * AsyncClient::stateToString(){ - switch(state()){ - case 0: return "Closed"; - case 1: return "Listen"; - case 2: return "SYN Sent"; - case 3: return "SYN Received"; - case 4: return "Established"; - case 5: return "FIN Wait 1"; - case 6: return "FIN Wait 2"; - case 7: return "Close Wait"; - case 8: return "Closing"; - case 9: return "Last ACK"; - case 10: return "Time Wait"; - default: return "UNKNOWN"; - } -} - -/* - * Static Callbacks (LwIP C2C++ interconnect) - * */ - -void AsyncClient::_s_dns_found(const char * name, struct ip_addr * ipaddr, void * arg){ - reinterpret_cast(arg)->_dns_found(ipaddr); -} - -int8_t AsyncClient::_s_poll(void * arg, struct tcp_pcb * pcb) { - return reinterpret_cast(arg)->_poll(pcb); -} - -int8_t AsyncClient::_s_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, int8_t err) { - return reinterpret_cast(arg)->_recv(pcb, pb, err); -} - -int8_t AsyncClient::_s_fin(void * arg, struct tcp_pcb * pcb, int8_t err) { - return reinterpret_cast(arg)->_fin(pcb, err); -} - -int8_t AsyncClient::_s_lwip_fin(void * arg, struct tcp_pcb * pcb, int8_t err) { - return reinterpret_cast(arg)->_lwip_fin(pcb, err); -} - -int8_t AsyncClient::_s_sent(void * arg, struct tcp_pcb * pcb, uint16_t len) { - return reinterpret_cast(arg)->_sent(pcb, len); -} - -void AsyncClient::_s_error(void * arg, int8_t err) { - reinterpret_cast(arg)->_error(err); -} - -int8_t AsyncClient::_s_connected(void * arg, void * pcb, int8_t err){ - return reinterpret_cast(arg)->_connected(pcb, err); -} - -/* - Async TCP Server - */ - -AsyncServer::AsyncServer(IPAddress addr, uint16_t port) -: _port(port) -, _addr(addr) -, _noDelay(false) -, _pcb(0) -, _connect_cb(0) -, _connect_cb_arg(0) -{} - -AsyncServer::AsyncServer(uint16_t port) -: _port(port) -, _addr((uint32_t) IPADDR_ANY) -, _noDelay(false) -, _pcb(0) -, _connect_cb(0) -, _connect_cb_arg(0) -{} - -AsyncServer::~AsyncServer(){ - end(); -} - -void AsyncServer::onClient(AcConnectHandler cb, void* arg){ - _connect_cb = cb; - _connect_cb_arg = arg; -} - -void AsyncServer::begin(){ - if(_pcb) { - return; - } - - if(!_start_async_task()){ - log_e("failed to start task"); - return; - } - int8_t err; - _pcb = tcp_new_ip_type(IPADDR_TYPE_V4); - if (!_pcb){ - log_e("_pcb == NULL"); - return; - } - - ip_addr_t local_addr; - local_addr.type = IPADDR_TYPE_V4; - local_addr.u_addr.ip4.addr = (uint32_t) _addr; - err = _tcp_bind(_pcb, &local_addr, _port); - - if (err != ERR_OK) { - _tcp_close(_pcb, -1); - log_e("bind error: %d", err); - return; - } - - static uint8_t backlog = 5; - _pcb = _tcp_listen_with_backlog(_pcb, backlog); - if (!_pcb) { - log_e("listen_pcb == NULL"); - return; - } - tcp_arg(_pcb, (void*) this); - tcp_accept(_pcb, &_s_accept); -} - -void AsyncServer::end(){ - if(_pcb){ - tcp_arg(_pcb, NULL); - tcp_accept(_pcb, NULL); - if(tcp_close(_pcb) != ERR_OK){ - _tcp_abort(_pcb, -1); - } - _pcb = NULL; - } -} - -//runs on LwIP thread -int8_t AsyncServer::_accept(tcp_pcb* pcb, int8_t err){ - //ets_printf("+A: 0x%08x\n", pcb); - if(_connect_cb){ - AsyncClient *c = new AsyncClient(pcb); - if(c){ - c->setNoDelay(_noDelay); - return _tcp_accept(this, c); - } - } - if(tcp_close(pcb) != ERR_OK){ - tcp_abort(pcb); - } - log_e("FAIL"); - return ERR_OK; -} - -int8_t AsyncServer::_accepted(AsyncClient* client){ - if(_connect_cb){ - _connect_cb(_connect_cb_arg, client); - } - return ERR_OK; -} - -void AsyncServer::setNoDelay(bool nodelay){ - _noDelay = nodelay; -} - -bool AsyncServer::getNoDelay(){ - return _noDelay; -} - -uint8_t AsyncServer::status(){ - if (!_pcb) { - return 0; - } - return _pcb->state; -} - -int8_t AsyncServer::_s_accept(void * arg, tcp_pcb * pcb, int8_t err){ - return reinterpret_cast(arg)->_accept(pcb, err); -} - -int8_t AsyncServer::_s_accepted(void *arg, AsyncClient* client){ - return reinterpret_cast(arg)->_accepted(client); -} diff --git a/lib/libesp32/AsyncTCP/src/AsyncTCP.h b/lib/libesp32/AsyncTCP/src/AsyncTCP.h deleted file mode 100644 index ac87dedac..000000000 --- a/lib/libesp32/AsyncTCP/src/AsyncTCP.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - Asynchronous TCP library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef ASYNCTCP_H_ -#define ASYNCTCP_H_ - -#include "IPAddress.h" -#include "sdkconfig.h" -#include -extern "C" { - #include "freertos/semphr.h" - #include "lwip/pbuf.h" -} - -//If core is not defined, then we are running in Arduino or PIO -#ifndef CONFIG_ASYNC_TCP_RUNNING_CORE -#define CONFIG_ASYNC_TCP_RUNNING_CORE -1 //any available core -#define CONFIG_ASYNC_TCP_USE_WDT 1 //if enabled, adds between 33us and 200us per event -#endif - -class AsyncClient; - -#define ASYNC_MAX_ACK_TIME 5000 -#define ASYNC_WRITE_FLAG_COPY 0x01 //will allocate new buffer to hold the data while sending (else will hold reference to the data given) -#define ASYNC_WRITE_FLAG_MORE 0x02 //will not send PSH flag, meaning that there should be more data to be sent before the application should react. - -typedef std::function AcConnectHandler; -typedef std::function AcAckHandler; -typedef std::function AcErrorHandler; -typedef std::function AcDataHandler; -typedef std::function AcPacketHandler; -typedef std::function AcTimeoutHandler; - -struct tcp_pcb; -struct ip_addr; - -class AsyncClient { - public: - AsyncClient(tcp_pcb* pcb = 0); - ~AsyncClient(); - - AsyncClient & operator=(const AsyncClient &other); - AsyncClient & operator+=(const AsyncClient &other); - - bool operator==(const AsyncClient &other); - - bool operator!=(const AsyncClient &other) { - return !(*this == other); - } - bool connect(IPAddress ip, uint16_t port); - bool connect(const char* host, uint16_t port); - void close(bool now = false); - void stop(); - int8_t abort(); - bool free(); - - bool canSend();//ack is not pending - size_t space();//space available in the TCP window - size_t add(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY);//add for sending - bool send();//send all data added with the method above - - //write equals add()+send() - size_t write(const char* data); - size_t write(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY); //only when canSend() == true - - uint8_t state(); - bool connecting(); - bool connected(); - bool disconnecting(); - bool disconnected(); - bool freeable();//disconnected or disconnecting - - uint16_t getMss(); - - uint32_t getRxTimeout(); - void setRxTimeout(uint32_t timeout);//no RX data timeout for the connection in seconds - - uint32_t getAckTimeout(); - void setAckTimeout(uint32_t timeout);//no ACK timeout for the last sent packet in milliseconds - - void setNoDelay(bool nodelay); - bool getNoDelay(); - - uint32_t getRemoteAddress(); - uint16_t getRemotePort(); - uint32_t getLocalAddress(); - uint16_t getLocalPort(); - - //compatibility - IPAddress remoteIP(); - uint16_t remotePort(); - IPAddress localIP(); - uint16_t localPort(); - - void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect - void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected - void onAck(AcAckHandler cb, void* arg = 0); //ack received - void onError(AcErrorHandler cb, void* arg = 0); //unsuccessful connect or error - void onData(AcDataHandler cb, void* arg = 0); //data received (called if onPacket is not used) - void onPacket(AcPacketHandler cb, void* arg = 0); //data received - void onTimeout(AcTimeoutHandler cb, void* arg = 0); //ack timeout - void onPoll(AcConnectHandler cb, void* arg = 0); //every 125ms when connected - - void ackPacket(struct pbuf * pb);//ack pbuf from onPacket - size_t ack(size_t len); //ack data that you have not acked using the method below - void ackLater(){ _ack_pcb = false; } //will not ack the current packet. Call from onData - - const char * errorToString(int8_t error); - const char * stateToString(); - - //Do not use any of the functions below! - static int8_t _s_poll(void *arg, struct tcp_pcb *tpcb); - static int8_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, int8_t err); - static int8_t _s_fin(void *arg, struct tcp_pcb *tpcb, int8_t err); - static int8_t _s_lwip_fin(void *arg, struct tcp_pcb *tpcb, int8_t err); - static void _s_error(void *arg, int8_t err); - static int8_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len); - static int8_t _s_connected(void* arg, void* tpcb, int8_t err); - static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg); - - int8_t _recv(tcp_pcb* pcb, pbuf* pb, int8_t err); - tcp_pcb * pcb(){ return _pcb; } - - protected: - tcp_pcb* _pcb; - int8_t _closed_slot; - - AcConnectHandler _connect_cb; - void* _connect_cb_arg; - AcConnectHandler _discard_cb; - void* _discard_cb_arg; - AcAckHandler _sent_cb; - void* _sent_cb_arg; - AcErrorHandler _error_cb; - void* _error_cb_arg; - AcDataHandler _recv_cb; - void* _recv_cb_arg; - AcPacketHandler _pb_cb; - void* _pb_cb_arg; - AcTimeoutHandler _timeout_cb; - void* _timeout_cb_arg; - AcConnectHandler _poll_cb; - void* _poll_cb_arg; - - bool _pcb_busy; - uint32_t _pcb_sent_at; - bool _ack_pcb; - uint32_t _rx_ack_len; - uint32_t _rx_last_packet; - uint32_t _rx_since_timeout; - uint32_t _ack_timeout; - uint16_t _connect_port; - - int8_t _close(); - void _free_closed_slot(); - void _allocate_closed_slot(); - int8_t _connected(void* pcb, int8_t err); - void _error(int8_t err); - int8_t _poll(tcp_pcb* pcb); - int8_t _sent(tcp_pcb* pcb, uint16_t len); - int8_t _fin(tcp_pcb* pcb, int8_t err); - int8_t _lwip_fin(tcp_pcb* pcb, int8_t err); - void _dns_found(struct ip_addr *ipaddr); - - public: - AsyncClient* prev; - AsyncClient* next; -}; - -class AsyncServer { - public: - AsyncServer(IPAddress addr, uint16_t port); - AsyncServer(uint16_t port); - ~AsyncServer(); - void onClient(AcConnectHandler cb, void* arg); - void begin(); - void end(); - void setNoDelay(bool nodelay); - bool getNoDelay(); - uint8_t status(); - - //Do not use any of the functions below! - static int8_t _s_accept(void *arg, tcp_pcb* newpcb, int8_t err); - static int8_t _s_accepted(void *arg, AsyncClient* client); - - protected: - uint16_t _port; - IPAddress _addr; - bool _noDelay; - tcp_pcb* _pcb; - AcConnectHandler _connect_cb; - void* _connect_cb_arg; - - int8_t _accept(tcp_pcb* newpcb, int8_t err); - int8_t _accepted(AsyncClient* client); -}; - - -#endif /* ASYNCTCP_H_ */ diff --git a/lib/libesp32/ESPAsyncWebServer/.gitignore b/lib/libesp32/ESPAsyncWebServer/.gitignore deleted file mode 100644 index a0f0e5386..000000000 --- a/lib/libesp32/ESPAsyncWebServer/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.vscode -.DS_Store diff --git a/lib/libesp32/ESPAsyncWebServer/.travis.yml b/lib/libesp32/ESPAsyncWebServer/.travis.yml deleted file mode 100644 index e1b703527..000000000 --- a/lib/libesp32/ESPAsyncWebServer/.travis.yml +++ /dev/null @@ -1,46 +0,0 @@ -sudo: false - -language: python - -os: - - linux - -git: - depth: false - -stages: - - build - -jobs: - include: - - - name: "Build Arduino ESP32" - if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) - stage: build - script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh esp32 - - - name: "Build Arduino ESP8266" - if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) - stage: build - script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh esp8266 - - - name: "Build Platformio ESP32" - if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) - stage: build - script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh esp32 1 1 - - - name: "Build Platformio ESP8266" - if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) - stage: build - script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh esp8266 1 1 - -notifications: - email: - on_success: change - on_failure: change - webhooks: - urls: - - https://webhooks.gitter.im/e/60e65d0c78ea0a920347 - on_success: change # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: never # options: [always|never|change] default: always diff --git a/lib/libesp32/ESPAsyncWebServer/CMakeLists.txt b/lib/libesp32/ESPAsyncWebServer/CMakeLists.txt deleted file mode 100644 index 64292eca4..000000000 --- a/lib/libesp32/ESPAsyncWebServer/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -set(COMPONENT_SRCDIRS - "src" -) - -set(COMPONENT_ADD_INCLUDEDIRS - "src" -) - -set(COMPONENT_REQUIRES - "arduino-esp32" - "AsyncTCP" -) - -register_component() - -target_compile_definitions(${COMPONENT_TARGET} PUBLIC -DESP32) -target_compile_options(${COMPONENT_TARGET} PRIVATE -fno-rtti) diff --git a/lib/libesp32/ESPAsyncWebServer/README.md b/lib/libesp32/ESPAsyncWebServer/README.md deleted file mode 100644 index d6dd3206a..000000000 --- a/lib/libesp32/ESPAsyncWebServer/README.md +++ /dev/null @@ -1,1521 +0,0 @@ -# ESPAsyncWebServer -[![Build Status](https://travis-ci.org/me-no-dev/ESPAsyncWebServer.svg?branch=master)](https://travis-ci.org/me-no-dev/ESPAsyncWebServer) ![](https://github.com/me-no-dev/ESPAsyncWebServer/workflows/ESP%20Async%20Web%20Server%20CI/badge.svg) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/395dd42cfc674e6ca2e326af3af80ffc)](https://www.codacy.com/manual/me-no-dev/ESPAsyncWebServer?utm_source=github.com&utm_medium=referral&utm_content=me-no-dev/ESPAsyncWebServer&utm_campaign=Badge_Grade) - -For help and support [![Join the chat at https://gitter.im/me-no-dev/ESPAsyncWebServer](https://badges.gitter.im/me-no-dev/ESPAsyncWebServer.svg)](https://gitter.im/me-no-dev/ESPAsyncWebServer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - -Async HTTP and WebSocket Server for ESP8266 Arduino - -For ESP8266 it requires [ESPAsyncTCP](https://github.com/me-no-dev/ESPAsyncTCP) -To use this library you might need to have the latest git versions of [ESP8266](https://github.com/esp8266/Arduino) Arduino Core - -For ESP32 it requires [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) to work -To use this library you might need to have the latest git versions of [ESP32](https://github.com/espressif/arduino-esp32) Arduino Core - -## Table of contents -- [ESPAsyncWebServer](#espasyncwebserver) - - [Table of contents](#table-of-contents) - - [Installation](#installation) - - [Using PlatformIO](#using-platformio) - - [Why should you care](#why-should-you-care) - - [Important things to remember](#important-things-to-remember) - - [Principles of operation](#principles-of-operation) - - [The Async Web server](#the-async-web-server) - - [Request Life Cycle](#request-life-cycle) - - [Rewrites and how do they work](#rewrites-and-how-do-they-work) - - [Handlers and how do they work](#handlers-and-how-do-they-work) - - [Responses and how do they work](#responses-and-how-do-they-work) - - [Template processing](#template-processing) - - [Libraries and projects that use AsyncWebServer](#libraries-and-projects-that-use-asyncwebserver) - - [Request Variables](#request-variables) - - [Common Variables](#common-variables) - - [Headers](#headers) - - [GET, POST and FILE parameters](#get-post-and-file-parameters) - - [FILE Upload handling](#file-upload-handling) - - [Body data handling](#body-data-handling) - - [JSON body handling with ArduinoJson](#json-body-handling-with-arduinojson) - - [Responses](#responses) - - [Redirect to another URL](#redirect-to-another-url) - - [Basic response with HTTP Code](#basic-response-with-http-code) - - [Basic response with HTTP Code and extra headers](#basic-response-with-http-code-and-extra-headers) - - [Basic response with string content](#basic-response-with-string-content) - - [Basic response with string content and extra headers](#basic-response-with-string-content-and-extra-headers) - - [Send large webpage from PROGMEM](#send-large-webpage-from-progmem) - - [Send large webpage from PROGMEM and extra headers](#send-large-webpage-from-progmem-and-extra-headers) - - [Send large webpage from PROGMEM containing templates](#send-large-webpage-from-progmem-containing-templates) - - [Send large webpage from PROGMEM containing templates and extra headers](#send-large-webpage-from-progmem-containing-templates-and-extra-headers) - - [Send binary content from PROGMEM](#send-binary-content-from-progmem) - - [Respond with content coming from a Stream](#respond-with-content-coming-from-a-stream) - - [Respond with content coming from a Stream and extra headers](#respond-with-content-coming-from-a-stream-and-extra-headers) - - [Respond with content coming from a Stream containing templates](#respond-with-content-coming-from-a-stream-containing-templates) - - [Respond with content coming from a Stream containing templates and extra headers](#respond-with-content-coming-from-a-stream-containing-templates-and-extra-headers) - - [Respond with content coming from a File](#respond-with-content-coming-from-a-file) - - [Respond with content coming from a File and extra headers](#respond-with-content-coming-from-a-file-and-extra-headers) - - [Respond with content coming from a File containing templates](#respond-with-content-coming-from-a-file-containing-templates) - - [Respond with content using a callback](#respond-with-content-using-a-callback) - - [Respond with content using a callback and extra headers](#respond-with-content-using-a-callback-and-extra-headers) - - [Respond with content using a callback containing templates](#respond-with-content-using-a-callback-containing-templates) - - [Respond with content using a callback containing templates and extra headers](#respond-with-content-using-a-callback-containing-templates-and-extra-headers) - - [Chunked Response](#chunked-response) - - [Chunked Response containing templates](#chunked-response-containing-templates) - - [Print to response](#print-to-response) - - [ArduinoJson Basic Response](#arduinojson-basic-response) - - [ArduinoJson Advanced Response](#arduinojson-advanced-response) - - [Serving static files](#serving-static-files) - - [Serving specific file by name](#serving-specific-file-by-name) - - [Serving files in directory](#serving-files-in-directory) - - [Serving static files with authentication](#serving-static-files-with-authentication) - - [Specifying Cache-Control header](#specifying-cache-control-header) - - [Specifying Date-Modified header](#specifying-date-modified-header) - - [Specifying Template Processor callback](#specifying-template-processor-callback) - - [Param Rewrite With Matching](#param-rewrite-with-matching) - - [Using filters](#using-filters) - - [Serve different site files in AP mode](#serve-different-site-files-in-ap-mode) - - [Rewrite to different index on AP](#rewrite-to-different-index-on-ap) - - [Serving different hosts](#serving-different-hosts) - - [Determine interface inside callbacks](#determine-interface-inside-callbacks) - - [Bad Responses](#bad-responses) - - [Respond with content using a callback without content length to HTTP/1.0 clients](#respond-with-content-using-a-callback-without-content-length-to-http10-clients) - - [Async WebSocket Plugin](#async-websocket-plugin) - - [Async WebSocket Event](#async-websocket-event) - - [Methods for sending data to a socket client](#methods-for-sending-data-to-a-socket-client) - - [Direct access to web socket message buffer](#direct-access-to-web-socket-message-buffer) - - [Limiting the number of web socket clients](#limiting-the-number-of-web-socket-clients) - - [Async Event Source Plugin](#async-event-source-plugin) - - [Setup Event Source on the server](#setup-event-source-on-the-server) - - [Setup Event Source in the browser](#setup-event-source-in-the-browser) - - [Scanning for available WiFi Networks](#scanning-for-available-wifi-networks) - - [Remove handlers and rewrites](#remove-handlers-and-rewrites) - - [Setting up the server](#setting-up-the-server) - - [Setup global and class functions as request handlers](#setup-global-and-class-functions-as-request-handlers) - - [Methods for controlling websocket connections](#methods-for-controlling-websocket-connections) - - [Adding Default Headers](#adding-default-headers) - - [Path variable](#path-variable) - -## Installation - -### Using PlatformIO - -[PlatformIO](http://platformio.org) is an open source ecosystem for IoT development with cross platform build system, library manager and full support for Espressif ESP8266/ESP32 development. It works on the popular host OS: Mac OS X, Windows, Linux 32/64, Linux ARM (like Raspberry Pi, BeagleBone, CubieBoard). - -1. Install [PlatformIO IDE](http://platformio.org/platformio-ide) -2. Create new project using "PlatformIO Home > New Project" -3. Update dev/platform to staging version: - - [Instruction for Espressif 8266](http://docs.platformio.org/en/latest/platforms/espressif8266.html#using-arduino-framework-with-staging-version) - - [Instruction for Espressif 32](http://docs.platformio.org/en/latest/platforms/espressif32.html#using-arduino-framework-with-staging-version) - 4. Add "ESP Async WebServer" to project using [Project Configuration File `platformio.ini`](http://docs.platformio.org/page/projectconf.html) and [lib_deps](http://docs.platformio.org/page/projectconf/section_env_library.html#lib-deps) option: - -```ini -[env:myboard] -platform = espressif... -board = ... -framework = arduino - -# using the latest stable version -lib_deps = ESP Async WebServer - -# or using GIT Url (the latest development version) -lib_deps = https://github.com/me-no-dev/ESPAsyncWebServer.git -``` - 5. Happy coding with PlatformIO! - -## Why should you care -- Using asynchronous network means that you can handle more than one connection at the same time -- You are called once the request is ready and parsed -- When you send the response, you are immediately ready to handle other connections - while the server is taking care of sending the response in the background -- Speed is OMG -- Easy to use API, HTTP Basic and Digest MD5 Authentication (default), ChunkedResponse -- Easily extendible to handle any type of content -- Supports Continue 100 -- Async WebSocket plugin offering different locations without extra servers or ports -- Async EventSource (Server-Sent Events) plugin to send events to the browser -- URL Rewrite plugin for conditional and permanent url rewrites -- ServeStatic plugin that supports cache, Last-Modified, default index and more -- Simple template processing engine to handle templates - -## Important things to remember -- This is fully asynchronous server and as such does not run on the loop thread. -- You can not use yield or delay or any function that uses them inside the callbacks -- The server is smart enough to know when to close the connection and free resources -- You can not send more than one response to a single request - -## Principles of operation - -### The Async Web server -- Listens for connections -- Wraps the new clients into ```Request``` -- Keeps track of clients and cleans memory -- Manages ```Rewrites``` and apply them on the request url -- Manages ```Handlers``` and attaches them to Requests - -### Request Life Cycle -- TCP connection is received by the server -- The connection is wrapped inside ```Request``` object -- When the request head is received (type, url, get params, http version and host), - the server goes through all ```Rewrites``` (in the order they were added) to rewrite the url and inject query parameters, - next, it goes through all attached ```Handlers```(in the order they were added) trying to find one - that ```canHandle``` the given request. If none are found, the default(catch-all) handler is attached. -- The rest of the request is received, calling the ```handleUpload``` or ```handleBody``` methods of the ```Handler``` if they are needed (POST+File/Body) -- When the whole request is parsed, the result is given to the ```handleRequest``` method of the ```Handler``` and is ready to be responded to -- In the ```handleRequest``` method, to the ```Request``` is attached a ```Response``` object (see below) that will serve the response data back to the client -- When the ```Response``` is sent, the client is closed and freed from the memory - -### Rewrites and how do they work -- The ```Rewrites``` are used to rewrite the request url and/or inject get parameters for a specific request url path. -- All ```Rewrites``` are evaluated on the request in the order they have been added to the server. -- The ```Rewrite``` will change the request url only if the request url (excluding get parameters) is fully match - the rewrite url, and when the optional ```Filter``` callback return true. -- Setting a ```Filter``` to the ```Rewrite``` enables to control when to apply the rewrite, decision can be based on - request url, http version, request host/port/target host, get parameters or the request client's localIP or remoteIP. -- Two filter callbacks are provided: ```ON_AP_FILTER``` to execute the rewrite when request is made to the AP interface, - ```ON_STA_FILTER``` to execute the rewrite when request is made to the STA interface. -- The ```Rewrite``` can specify a target url with optional get parameters, e.g. ```/to-url?with=params``` - -### Handlers and how do they work -- The ```Handlers``` are used for executing specific actions to particular requests -- One ```Handler``` instance can be attached to any request and lives together with the server -- Setting a ```Filter``` to the ```Handler``` enables to control when to apply the handler, decision can be based on - request url, http version, request host/port/target host, get parameters or the request client's localIP or remoteIP. -- Two filter callbacks are provided: ```ON_AP_FILTER``` to execute the rewrite when request is made to the AP interface, - ```ON_STA_FILTER``` to execute the rewrite when request is made to the STA interface. -- The ```canHandle``` method is used for handler specific control on whether the requests can be handled - and for declaring any interesting headers that the ```Request``` should parse. Decision can be based on request - method, request url, http version, request host/port/target host and get parameters -- Once a ```Handler``` is attached to given ```Request``` (```canHandle``` returned true) - that ```Handler``` takes care to receive any file/data upload and attach a ```Response``` - once the ```Request``` has been fully parsed -- ```Handlers``` are evaluated in the order they are attached to the server. The ```canHandle``` is called only - if the ```Filter``` that was set to the ```Handler``` return true. -- The first ```Handler``` that can handle the request is selected, not further ```Filter``` and ```canHandle``` are called. - -### Responses and how do they work -- The ```Response``` objects are used to send the response data back to the client -- The ```Response``` object lives with the ```Request``` and is freed on end or disconnect -- Different techniques are used depending on the response type to send the data in packets - returning back almost immediately and sending the next packet when this one is received. - Any time in between is spent to run the user loop and handle other network packets -- Responding asynchronously is probably the most difficult thing for most to understand -- Many different options exist for the user to make responding a background task - -### Template processing -- ESPAsyncWebserver contains simple template processing engine. -- Template processing can be added to most response types. -- Currently it supports only replacing template placeholders with actual values. No conditional processing, cycles, etc. -- Placeholders are delimited with ```%``` symbols. Like this: ```%TEMPLATE_PLACEHOLDER%```. -- It works by extracting placeholder name from response text and passing it to user provided function which should return actual value to be used instead of placeholder. -- Since it's user provided function, it is possible for library users to implement conditional processing and cycles themselves. -- Since it's impossible to know the actual response size after template processing step in advance (and, therefore, to include it in response headers), the response becomes [chunked](#chunked-response). - -## Libraries and projects that use AsyncWebServer -- [WebSocketToSerial](https://github.com/hallard/WebSocketToSerial) - Debug serial devices through the web browser -- [Sattrack](https://github.com/Hopperpop/Sattrack) - Track the ISS with ESP8266 -- [ESP Radio](https://github.com/Edzelf/Esp-radio) - Icecast radio based on ESP8266 and VS1053 -- [VZero](https://github.com/andig/vzero) - the Wireless zero-config controller for volkszaehler.org -- [ESPurna](https://bitbucket.org/xoseperez/espurna) - ESPurna ("spark" in Catalan) is a custom C firmware for ESP8266 based smart switches. It was originally developed with the ITead Sonoff in mind. -- [fauxmoESP](https://bitbucket.org/xoseperez/fauxmoesp) - Belkin WeMo emulator library for ESP8266. -- [ESP-RFID](https://github.com/omersiar/esp-rfid) - MFRC522 RFID Access Control Management project for ESP8266. - -## Request Variables - -### Common Variables -```cpp -request->version(); // uint8_t: 0 = HTTP/1.0, 1 = HTTP/1.1 -request->method(); // enum: HTTP_GET, HTTP_POST, HTTP_DELETE, HTTP_PUT, HTTP_PATCH, HTTP_HEAD, HTTP_OPTIONS -request->url(); // String: URL of the request (not including host, port or GET parameters) -request->host(); // String: The requested host (can be used for virtual hosting) -request->contentType(); // String: ContentType of the request (not avaiable in Handler::canHandle) -request->contentLength(); // size_t: ContentLength of the request (not avaiable in Handler::canHandle) -request->multipart(); // bool: True if the request has content type "multipart" -``` - -### Headers -```cpp -//List all collected headers -int headers = request->headers(); -int i; -for(i=0;igetHeader(i); - Serial.printf("HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str()); -} - -//get specific header by name -if(request->hasHeader("MyHeader")){ - AsyncWebHeader* h = request->getHeader("MyHeader"); - Serial.printf("MyHeader: %s\n", h->value().c_str()); -} - -//List all collected headers (Compatibility) -int headers = request->headers(); -int i; -for(i=0;iheaderName(i).c_str(), request->header(i).c_str()); -} - -//get specific header by name (Compatibility) -if(request->hasHeader("MyHeader")){ - Serial.printf("MyHeader: %s\n", request->header("MyHeader").c_str()); -} -``` - -### GET, POST and FILE parameters -```cpp -//List all parameters -int params = request->params(); -for(int i=0;igetParam(i); - if(p->isFile()){ //p->isPost() is also true - Serial.printf("FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size()); - } else if(p->isPost()){ - Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); - } else { - Serial.printf("GET[%s]: %s\n", p->name().c_str(), p->value().c_str()); - } -} - -//Check if GET parameter exists -if(request->hasParam("download")) - AsyncWebParameter* p = request->getParam("download"); - -//Check if POST (but not File) parameter exists -if(request->hasParam("download", true)) - AsyncWebParameter* p = request->getParam("download", true); - -//Check if FILE was uploaded -if(request->hasParam("download", true, true)) - AsyncWebParameter* p = request->getParam("download", true, true); - -//List all parameters (Compatibility) -int args = request->args(); -for(int i=0;iargName(i).c_str(), request->arg(i).c_str()); -} - -//Check if parameter exists (Compatibility) -if(request->hasArg("download")) - String arg = request->arg("download"); -``` - -### FILE Upload handling -```cpp -void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ - if(!index){ - Serial.printf("UploadStart: %s\n", filename.c_str()); - } - for(size_t i=0; i(); - // ... -}); -server.addHandler(handler); -``` - -## Responses -### Redirect to another URL -```cpp -//to local url -request->redirect("/login"); - -//to external url -request->redirect("http://esp8266.com"); -``` - -### Basic response with HTTP Code -```cpp -request->send(404); //Sends 404 File Not Found -``` - -### Basic response with HTTP Code and extra headers -```cpp -AsyncWebServerResponse *response = request->beginResponse(404); //Sends 404 File Not Found -response->addHeader("Server","ESP Async Web Server"); -request->send(response); -``` - -### Basic response with string content -```cpp -request->send(200, "text/plain", "Hello World!"); -``` - -### Basic response with string content and extra headers -```cpp -AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", "Hello World!"); -response->addHeader("Server","ESP Async Web Server"); -request->send(response); -``` - -### Send large webpage from PROGMEM -```cpp -const char index_html[] PROGMEM = "..."; // large char array, tested with 14k -request->send_P(200, "text/html", index_html); -``` - -### Send large webpage from PROGMEM and extra headers -```cpp -const char index_html[] PROGMEM = "..."; // large char array, tested with 14k -AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", index_html); -response->addHeader("Server","ESP Async Web Server"); -request->send(response); -``` - -### Send large webpage from PROGMEM containing templates -```cpp -String processor(const String& var) -{ - if(var == "HELLO_FROM_TEMPLATE") - return F("Hello world!"); - return String(); -} - -// ... - -const char index_html[] PROGMEM = "..."; // large char array, tested with 14k -request->send_P(200, "text/html", index_html, processor); -``` - -### Send large webpage from PROGMEM containing templates and extra headers -```cpp -String processor(const String& var) -{ - if(var == "HELLO_FROM_TEMPLATE") - return F("Hello world!"); - return String(); -} - -// ... - -const char index_html[] PROGMEM = "..."; // large char array, tested with 14k -AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", index_html, processor); -response->addHeader("Server","ESP Async Web Server"); -request->send(response); -``` - -### Send binary content from PROGMEM -```cpp - -//File: favicon.ico.gz, Size: 726 -#define favicon_ico_gz_len 726 -const uint8_t favicon_ico_gz[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x0B, 0x87, 0x90, 0x57, 0x00, 0x03, 0x66, 0x61, 0x76, 0x69, 0x63, 0x6F, - 0x6E, 0x2E, 0x69, 0x63, 0x6F, 0x00, 0xCD, 0x53, 0x5F, 0x48, 0x9A, 0x51, 0x14, 0xBF, 0x62, 0x6D, - 0x86, 0x96, 0xA9, 0x64, 0xD3, 0xFE, 0xA8, 0x99, 0x65, 0x1A, 0xB4, 0x8A, 0xA8, 0x51, 0x54, 0x23, - 0xA8, 0x11, 0x49, 0x51, 0x8A, 0x34, 0x62, 0x93, 0x85, 0x31, 0x58, 0x44, 0x12, 0x45, 0x2D, 0x58, - 0xF5, 0x52, 0x41, 0x10, 0x23, 0x82, 0xA0, 0x20, 0x98, 0x2F, 0xC1, 0x26, 0xED, 0xA1, 0x20, 0x89, - 0x04, 0xD7, 0x83, 0x58, 0x20, 0x28, 0x04, 0xAB, 0xD1, 0x9B, 0x8C, 0xE5, 0xC3, 0x60, 0x32, 0x64, - 0x0E, 0x56, 0xBF, 0x9D, 0xEF, 0xF6, 0x30, 0x82, 0xED, 0xAD, 0x87, 0xDD, 0x8F, 0xF3, 0xDD, 0x8F, - 0x73, 0xCF, 0xEF, 0x9C, 0xDF, 0x39, 0xBF, 0xFB, 0x31, 0x26, 0xA2, 0x27, 0x37, 0x97, 0xD1, 0x5B, - 0xCF, 0x9E, 0x67, 0x30, 0xA6, 0x66, 0x8C, 0x99, 0xC9, 0xC8, 0x45, 0x9E, 0x6B, 0x3F, 0x5F, 0x74, - 0xA6, 0x94, 0x5E, 0xDB, 0xFF, 0xB2, 0xE6, 0xE7, 0xE7, 0xF9, 0xDE, 0xD6, 0xD6, 0x96, 0xDB, 0xD8, - 0xD8, 0x78, 0xBF, 0xA1, 0xA1, 0xC1, 0xDA, 0xDC, 0xDC, 0x2C, 0xEB, 0xED, 0xED, 0x15, 0x9B, 0xCD, - 0xE6, 0x4A, 0x83, 0xC1, 0xE0, 0x2E, 0x29, 0x29, 0x99, 0xD6, 0x6A, 0xB5, 0x4F, 0x75, 0x3A, 0x9D, - 0x61, 0x75, 0x75, 0x95, 0xB5, 0xB7, 0xB7, 0xDF, 0xC8, 0xD1, 0xD4, 0xD4, 0xF4, 0xB0, 0xBA, 0xBA, - 0xFA, 0x83, 0xD5, 0x6A, 0xFD, 0x5A, 0x5E, 0x5E, 0x9E, 0x28, 0x2D, 0x2D, 0x0D, 0x10, 0xC6, 0x4B, - 0x98, 0x78, 0x5E, 0x5E, 0xDE, 0x95, 0x42, 0xA1, 0x40, 0x4E, 0x4E, 0xCE, 0x65, 0x76, 0x76, 0xF6, - 0x47, 0xB5, 0x5A, 0x6D, 0x4F, 0x26, 0x93, 0xA2, 0xD6, 0xD6, 0x56, 0x8E, 0x6D, 0x69, 0x69, 0xD1, - 0x11, 0x36, 0x62, 0xB1, 0x58, 0x60, 0x32, 0x99, 0xA0, 0xD7, 0xEB, 0x51, 0x58, 0x58, 0x88, 0xFC, - 0xFC, 0x7C, 0x10, 0x16, 0x02, 0x56, 0x2E, 0x97, 0x43, 0x2A, 0x95, 0x42, 0x2C, 0x16, 0x23, 0x33, - 0x33, 0x33, 0xAE, 0x52, 0xA9, 0x1E, 0x64, 0x65, 0x65, 0x71, 0x7C, 0x7D, 0x7D, 0xBD, 0x93, 0xEA, - 0xFE, 0x30, 0x1A, 0x8D, 0xE8, 0xEC, 0xEC, 0xC4, 0xE2, 0xE2, 0x22, 0x6A, 0x6A, 0x6A, 0x40, 0x39, - 0x41, 0xB5, 0x38, 0x4E, 0xC8, 0x33, 0x3C, 0x3C, 0x0C, 0x87, 0xC3, 0xC1, 0x6B, 0x54, 0x54, 0x54, - 0xBC, 0xE9, 0xEB, 0xEB, 0x93, 0x5F, 0x5C, 0x5C, 0x30, 0x8A, 0x9D, 0x2E, 0x2B, 0x2B, 0xBB, 0xA2, - 0x3E, 0x41, 0xBD, 0x21, 0x1E, 0x8F, 0x63, 0x6A, 0x6A, 0x0A, 0x81, 0x40, 0x00, 0x94, 0x1B, 0x3D, - 0x3D, 0x3D, 0x42, 0x3C, 0x96, 0x96, 0x96, 0x70, 0x7E, 0x7E, 0x8E, 0xE3, 0xE3, 0x63, 0xF8, 0xFD, - 0xFE, 0xB4, 0xD7, 0xEB, 0xF5, 0x8F, 0x8F, 0x8F, 0x5B, 0x68, 0x5E, 0x6F, 0x05, 0xCE, 0xB4, 0xE3, - 0xE8, 0xE8, 0x08, 0x27, 0x27, 0x27, 0xD8, 0xDF, 0xDF, 0xC7, 0xD9, 0xD9, 0x19, 0x6C, 0x36, 0x1B, - 0x36, 0x36, 0x36, 0x38, 0x9F, 0x85, 0x85, 0x05, 0xAC, 0xAF, 0xAF, 0x23, 0x1A, 0x8D, 0x22, 0x91, - 0x48, 0x20, 0x16, 0x8B, 0xFD, 0xDA, 0xDA, 0xDA, 0x7A, 0x41, 0x33, 0x7E, 0x57, 0x50, 0x50, 0x80, - 0x89, 0x89, 0x09, 0x84, 0xC3, 0x61, 0x6C, 0x6F, 0x6F, 0x23, 0x12, 0x89, 0xE0, 0xE0, 0xE0, 0x00, - 0x43, 0x43, 0x43, 0x58, 0x5E, 0x5E, 0xE6, 0x9C, 0x7D, 0x3E, 0x1F, 0x46, 0x47, 0x47, 0x79, 0xBE, - 0xBD, 0xBD, 0x3D, 0xE1, 0x3C, 0x1D, 0x0C, 0x06, 0x9F, 0x10, 0xB7, 0xC7, 0x84, 0x4F, 0xF6, 0xF7, - 0xF7, 0x63, 0x60, 0x60, 0x00, 0x83, 0x83, 0x83, 0x18, 0x19, 0x19, 0xC1, 0xDC, 0xDC, 0x1C, 0x8F, - 0x17, 0x7C, 0xA4, 0x27, 0xE7, 0x34, 0x39, 0x39, 0x89, 0x9D, 0x9D, 0x1D, 0x6E, 0x54, 0xE3, 0x13, - 0xE5, 0x34, 0x11, 0x37, 0x49, 0x51, 0x51, 0xD1, 0x4B, 0xA5, 0x52, 0xF9, 0x45, 0x26, 0x93, 0x5D, - 0x0A, 0xF3, 0x92, 0x48, 0x24, 0xA0, 0x6F, 0x14, 0x17, 0x17, 0xA3, 0xB6, 0xB6, 0x16, 0x5D, 0x5D, - 0x5D, 0x7C, 0x1E, 0xBB, 0xBB, 0xBB, 0x9C, 0xD7, 0xE1, 0xE1, 0x21, 0x42, 0xA1, 0xD0, 0x6B, 0xD2, - 0x45, 0x4C, 0x33, 0x12, 0x34, 0xCC, 0xA0, 0x19, 0x54, 0x92, 0x56, 0x0E, 0xD2, 0xD9, 0x43, 0xF8, - 0xCF, 0x82, 0x56, 0xC2, 0xDC, 0xEB, 0xEA, 0xEA, 0x38, 0x7E, 0x6C, 0x6C, 0x4C, 0xE0, 0xFE, 0x9D, - 0xB8, 0xBF, 0xA7, 0xFA, 0xAF, 0x56, 0x56, 0x56, 0xEE, 0x6D, 0x6E, 0x6E, 0xDE, 0xB8, 0x47, 0x55, - 0x55, 0x55, 0x6C, 0x66, 0x66, 0x46, 0x44, 0xDA, 0x3B, 0x34, 0x1A, 0x4D, 0x94, 0xB0, 0x3F, 0x09, - 0x7B, 0x45, 0xBD, 0xA5, 0x5D, 0x2E, 0x57, 0x8C, 0x7A, 0x73, 0xD9, 0xED, 0xF6, 0x3B, 0x84, 0xFF, - 0xE7, 0x7D, 0xA6, 0x3A, 0x2C, 0x95, 0x4A, 0xB1, 0x8E, 0x8E, 0x0E, 0x6D, 0x77, 0x77, 0xB7, 0xCD, - 0xE9, 0x74, 0x3E, 0x73, 0xBB, 0xDD, 0x8F, 0x3C, 0x1E, 0x8F, 0xE6, 0xF4, 0xF4, 0x94, 0xAD, 0xAD, - 0xAD, 0xDD, 0xDE, 0xCF, 0x73, 0x0B, 0x0B, 0xB8, 0xB6, 0xE0, 0x5D, 0xC6, 0x66, 0xC5, 0xE4, 0x10, - 0x4C, 0xF4, 0xF7, 0xD8, 0x59, 0xF2, 0x7F, 0xA3, 0xB8, 0xB4, 0xFC, 0x0F, 0xEE, 0x37, 0x70, 0xEC, - 0x16, 0x4A, 0x7E, 0x04, 0x00, 0x00 -}; - -AsyncWebServerResponse *response = request->beginResponse_P(200, "image/x-icon", favicon_ico_gz, favicon_ico_gz_len); -response->addHeader("Content-Encoding", "gzip"); -request->send(response); -``` - -### Respond with content coming from a Stream -```cpp -//read 12 bytes from Serial and send them as Content Type text/plain -request->send(Serial, "text/plain", 12); -``` - -### Respond with content coming from a Stream and extra headers -```cpp -//read 12 bytes from Serial and send them as Content Type text/plain -AsyncWebServerResponse *response = request->beginResponse(Serial, "text/plain", 12); -response->addHeader("Server","ESP Async Web Server"); -request->send(response); -``` - -### Respond with content coming from a Stream containing templates -```cpp -String processor(const String& var) -{ - if(var == "HELLO_FROM_TEMPLATE") - return F("Hello world!"); - return String(); -} - -// ... - -//read 12 bytes from Serial and send them as Content Type text/plain -request->send(Serial, "text/plain", 12, processor); -``` - -### Respond with content coming from a Stream containing templates and extra headers -```cpp -String processor(const String& var) -{ - if(var == "HELLO_FROM_TEMPLATE") - return F("Hello world!"); - return String(); -} - -// ... - -//read 12 bytes from Serial and send them as Content Type text/plain -AsyncWebServerResponse *response = request->beginResponse(Serial, "text/plain", 12, processor); -response->addHeader("Server","ESP Async Web Server"); -request->send(response); -``` - -### Respond with content coming from a File -```cpp -//Send index.htm with default content type -request->send(SPIFFS, "/index.htm"); - -//Send index.htm as text -request->send(SPIFFS, "/index.htm", "text/plain"); - -//Download index.htm -request->send(SPIFFS, "/index.htm", String(), true); -``` - -### Respond with content coming from a File and extra headers -```cpp -//Send index.htm with default content type -AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/index.htm"); - -//Send index.htm as text -AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/index.htm", "text/plain"); - -//Download index.htm -AsyncWebServerResponse *response = request->beginResponse(SPIFFS, "/index.htm", String(), true); - -response->addHeader("Server","ESP Async Web Server"); -request->send(response); -``` - -### Respond with content coming from a File containing templates -Internally uses [Chunked Response](#chunked-response). - -Index.htm contents: -``` -%HELLO_FROM_TEMPLATE% -``` - -Somewhere in source files: -```cpp -String processor(const String& var) -{ - if(var == "HELLO_FROM_TEMPLATE") - return F("Hello world!"); - return String(); -} - -// ... - -//Send index.htm with template processor function -request->send(SPIFFS, "/index.htm", String(), false, processor); -``` - -### Respond with content using a callback -```cpp -//send 128 bytes as plain text -request->send("text/plain", 128, [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { - //Write up to "maxLen" bytes into "buffer" and return the amount written. - //index equals the amount of bytes that have been already sent - //You will not be asked for more bytes once the content length has been reached. - //Keep in mind that you can not delay or yield waiting for more data! - //Send what you currently have and you will be asked for more again - return mySource.read(buffer, maxLen); -}); -``` - -### Respond with content using a callback and extra headers -```cpp -//send 128 bytes as plain text -AsyncWebServerResponse *response = request->beginResponse("text/plain", 128, [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { - //Write up to "maxLen" bytes into "buffer" and return the amount written. - //index equals the amount of bytes that have been already sent - //You will not be asked for more bytes once the content length has been reached. - //Keep in mind that you can not delay or yield waiting for more data! - //Send what you currently have and you will be asked for more again - return mySource.read(buffer, maxLen); -}); -response->addHeader("Server","ESP Async Web Server"); -request->send(response); -``` - -### Respond with content using a callback containing templates -```cpp -String processor(const String& var) -{ - if(var == "HELLO_FROM_TEMPLATE") - return F("Hello world!"); - return String(); -} - -// ... - -//send 128 bytes as plain text -request->send("text/plain", 128, [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { - //Write up to "maxLen" bytes into "buffer" and return the amount written. - //index equals the amount of bytes that have been already sent - //You will not be asked for more bytes once the content length has been reached. - //Keep in mind that you can not delay or yield waiting for more data! - //Send what you currently have and you will be asked for more again - return mySource.read(buffer, maxLen); -}, processor); -``` - -### Respond with content using a callback containing templates and extra headers -```cpp -String processor(const String& var) -{ - if(var == "HELLO_FROM_TEMPLATE") - return F("Hello world!"); - return String(); -} - -// ... - -//send 128 bytes as plain text -AsyncWebServerResponse *response = request->beginResponse("text/plain", 128, [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { - //Write up to "maxLen" bytes into "buffer" and return the amount written. - //index equals the amount of bytes that have been already sent - //You will not be asked for more bytes once the content length has been reached. - //Keep in mind that you can not delay or yield waiting for more data! - //Send what you currently have and you will be asked for more again - return mySource.read(buffer, maxLen); -}, processor); -response->addHeader("Server","ESP Async Web Server"); -request->send(response); -``` - -### Chunked Response -Used when content length is unknown. Works best if the client supports HTTP/1.1 -```cpp -AsyncWebServerResponse *response = request->beginChunkedResponse("text/plain", [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { - //Write up to "maxLen" bytes into "buffer" and return the amount written. - //index equals the amount of bytes that have been already sent - //You will be asked for more data until 0 is returned - //Keep in mind that you can not delay or yield waiting for more data! - return mySource.read(buffer, maxLen); -}); -response->addHeader("Server","ESP Async Web Server"); -request->send(response); -``` - -### Chunked Response containing templates -Used when content length is unknown. Works best if the client supports HTTP/1.1 -```cpp -String processor(const String& var) -{ - if(var == "HELLO_FROM_TEMPLATE") - return F("Hello world!"); - return String(); -} - -// ... - -AsyncWebServerResponse *response = request->beginChunkedResponse("text/plain", [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { - //Write up to "maxLen" bytes into "buffer" and return the amount written. - //index equals the amount of bytes that have been already sent - //You will be asked for more data until 0 is returned - //Keep in mind that you can not delay or yield waiting for more data! - return mySource.read(buffer, maxLen); -}, processor); -response->addHeader("Server","ESP Async Web Server"); -request->send(response); -``` - -### Print to response -```cpp -AsyncResponseStream *response = request->beginResponseStream("text/html"); -response->addHeader("Server","ESP Async Web Server"); -response->printf("Webpage at %s", request->url().c_str()); - -response->print("

Hello "); -response->print(request->client()->remoteIP()); -response->print("

"); - -response->print("

General

"); -response->print("
    "); -response->printf("
  • Version: HTTP/1.%u
  • ", request->version()); -response->printf("
  • Method: %s
  • ", request->methodToString()); -response->printf("
  • URL: %s
  • ", request->url().c_str()); -response->printf("
  • Host: %s
  • ", request->host().c_str()); -response->printf("
  • ContentType: %s
  • ", request->contentType().c_str()); -response->printf("
  • ContentLength: %u
  • ", request->contentLength()); -response->printf("
  • Multipart: %s
  • ", request->multipart()?"true":"false"); -response->print("
"); - -response->print("

Headers

"); -response->print("
    "); -int headers = request->headers(); -for(int i=0;igetHeader(i); - response->printf("
  • %s: %s
  • ", h->name().c_str(), h->value().c_str()); -} -response->print("
"); - -response->print("

Parameters

"); -response->print("
    "); -int params = request->params(); -for(int i=0;igetParam(i); - if(p->isFile()){ - response->printf("
  • FILE[%s]: %s, size: %u
  • ", p->name().c_str(), p->value().c_str(), p->size()); - } else if(p->isPost()){ - response->printf("
  • POST[%s]: %s
  • ", p->name().c_str(), p->value().c_str()); - } else { - response->printf("
  • GET[%s]: %s
  • ", p->name().c_str(), p->value().c_str()); - } -} -response->print("
"); - -response->print(""); -//send the response last -request->send(response); -``` - -### ArduinoJson Basic Response -This way of sending Json is great for when the result is below 4KB -```cpp -#include "AsyncJson.h" -#include "ArduinoJson.h" - - -AsyncResponseStream *response = request->beginResponseStream("application/json"); -DynamicJsonBuffer jsonBuffer; -JsonObject &root = jsonBuffer.createObject(); -root["heap"] = ESP.getFreeHeap(); -root["ssid"] = WiFi.SSID(); -root.printTo(*response); -request->send(response); -``` - -### ArduinoJson Advanced Response -This response can handle really large Json objects (tested to 40KB) -There isn't any noticeable speed decrease for small results with the method above -Since ArduinoJson does not allow reading parts of the string, the whole Json has to -be passed every time a chunks needs to be sent, which shows speed decrease proportional -to the resulting json packets -```cpp -#include "AsyncJson.h" -#include "ArduinoJson.h" - - -AsyncJsonResponse * response = new AsyncJsonResponse(); -response->addHeader("Server","ESP Async Web Server"); -JsonObject& root = response->getRoot(); -root["heap"] = ESP.getFreeHeap(); -root["ssid"] = WiFi.SSID(); -response->setLength(); -request->send(response); -``` - -## Serving static files -In addition to serving files from SPIFFS as described above, the server provide a dedicated handler that optimize the -performance of serving files from SPIFFS - ```AsyncStaticWebHandler```. Use ```server.serveStatic()``` function to -initialize and add a new instance of ```AsyncStaticWebHandler``` to the server. -The Handler will not handle the request if the file does not exists, e.g. the server will continue to look for another -handler that can handle the request. -Notice that you can chain setter functions to setup the handler, or keep a pointer to change it at a later time. - -### Serving specific file by name -```cpp -// Serve the file "/www/page.htm" when request url is "/page.htm" -server.serveStatic("/page.htm", SPIFFS, "/www/page.htm"); -``` - -### Serving files in directory -To serve files in a directory, the path to the files should specify a directory in SPIFFS and ends with "/". -```cpp -// Serve files in directory "/www/" when request url starts with "/" -// Request to the root or none existing files will try to server the defualt -// file name "index.htm" if exists -server.serveStatic("/", SPIFFS, "/www/"); - -// Server with different default file -server.serveStatic("/", SPIFFS, "/www/").setDefaultFile("default.html"); -``` - -### Serving static files with authentication - -```cpp -server - .serveStatic("/", SPIFFS, "/www/") - .setDefaultFile("default.html") - .setAuthentication("user", "pass"); -``` - -### Specifying Cache-Control header -It is possible to specify Cache-Control header value to reduce the number of calls to the server once the client loaded -the files. For more information on Cache-Control values see [Cache-Control](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9) -```cpp -// Cache responses for 10 minutes (600 seconds) -server.serveStatic("/", SPIFFS, "/www/").setCacheControl("max-age=600"); - -//*** Change Cache-Control after server setup *** - -// During setup - keep a pointer to the handler -AsyncStaticWebHandler* handler = &server.serveStatic("/", SPIFFS, "/www/").setCacheControl("max-age=600"); - -// At a later event - change Cache-Control -handler->setCacheControl("max-age=30"); -``` - -### Specifying Date-Modified header -It is possible to specify Date-Modified header to enable the server to return Not-Modified (304) response for requests -with "If-Modified-Since" header with the same value, instead of responding with the actual file content. -```cpp -// Update the date modified string every time files are updated -server.serveStatic("/", SPIFFS, "/www/").setLastModified("Mon, 20 Jun 2016 14:00:00 GMT"); - -//*** Chage last modified value at a later stage *** - -// During setup - read last modified value from config or EEPROM -String date_modified = loadDateModified(); -AsyncStaticWebHandler* handler = &server.serveStatic("/", SPIFFS, "/www/"); -handler->setLastModified(date_modified); - -// At a later event when files are updated -String date_modified = getNewDateModfied(); -saveDateModified(date_modified); // Save for next reset -handler->setLastModified(date_modified); -``` - -### Specifying Template Processor callback -It is possible to specify template processor for static files. For information on template processor see -[Respond with content coming from a File containing templates](#respond-with-content-coming-from-a-file-containing-templates). -```cpp -String processor(const String& var) -{ - if(var == "HELLO_FROM_TEMPLATE") - return F("Hello world!"); - return String(); -} - -// ... - -server.serveStatic("/", SPIFFS, "/www/").setTemplateProcessor(processor); -``` - -## Param Rewrite With Matching -It is possible to rewrite the request url with parameter matchg. Here is an example with one parameter: -Rewrite for example "/radio/{frequence}" -> "/radio?f={frequence}" - -```cpp -class OneParamRewrite : public AsyncWebRewrite -{ - protected: - String _urlPrefix; - int _paramIndex; - String _paramsBackup; - - public: - OneParamRewrite(const char* from, const char* to) - : AsyncWebRewrite(from, to) { - - _paramIndex = _from.indexOf('{'); - - if( _paramIndex >=0 && _from.endsWith("}")) { - _urlPrefix = _from.substring(0, _paramIndex); - int index = _params.indexOf('{'); - if(index >= 0) { - _params = _params.substring(0, index); - } - } else { - _urlPrefix = _from; - } - _paramsBackup = _params; - } - - bool match(AsyncWebServerRequest *request) override { - if(request->url().startsWith(_urlPrefix)) { - if(_paramIndex >= 0) { - _params = _paramsBackup + request->url().substring(_paramIndex); - } else { - _params = _paramsBackup; - } - return true; - - } else { - return false; - } - } -}; -``` - -Usage: - -```cpp - server.addRewrite( new OneParamRewrite("/radio/{frequence}", "/radio?f={frequence}") ); -``` - -## Using filters -Filters can be set to `Rewrite` or `Handler` in order to control when to apply the rewrite and consider the handler. -A filter is a callback function that evaluates the request and return a boolean `true` to include the item -or `false` to exclude it. -Two filter callback are provided for convince: -* `ON_STA_FILTER` - return true when requests are made to the STA (station mode) interface. -* `ON_AP_FILTER` - return true when requests are made to the AP (access point) interface. - -### Serve different site files in AP mode -```cpp -server.serveStatic("/", SPIFFS, "/www/").setFilter(ON_STA_FILTER); -server.serveStatic("/", SPIFFS, "/ap/").setFilter(ON_AP_FILTER); -``` - -### Rewrite to different index on AP -```cpp -// Serve the file "/www/index-ap.htm" in AP, and the file "/www/index.htm" on STA -server.rewrite("/", "index.htm"); -server.rewrite("/index.htm", "index-ap.htm").setFilter(ON_AP_FILTER); -server.serveStatic("/", SPIFFS, "/www/"); -``` - -### Serving different hosts -```cpp -// Filter callback using request host -bool filterOnHost1(AsyncWebServerRequest *request) { return request->host() == "host1"; } - -// Server setup: server files in "/host1/" to requests for "host1", and files in "/www/" otherwise. -server.serveStatic("/", SPIFFS, "/host1/").setFilter(filterOnHost1); -server.serveStatic("/", SPIFFS, "/www/"); -``` - -### Determine interface inside callbacks -```cpp - String RedirectUrl = "http://"; - if (ON_STA_FILTER(request)) { - RedirectUrl += WiFi.localIP().toString(); - } else { - RedirectUrl += WiFi.softAPIP().toString(); - } - RedirectUrl += "/index.htm"; - request->redirect(RedirectUrl); -``` - -## Bad Responses -Some responses are implemented, but you should not use them, because they do not conform to HTTP. -The following example will lead to unclean close of the connection and more time wasted -than providing the length of the content - -### Respond with content using a callback without content length to HTTP/1.0 clients -```cpp -//This is used as fallback for chunked responses to HTTP/1.0 Clients -request->send("text/plain", 0, [](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { - //Write up to "maxLen" bytes into "buffer" and return the amount written. - //You will be asked for more data until 0 is returned - //Keep in mind that you can not delay or yield waiting for more data! - return mySource.read(buffer, maxLen); -}); -``` - -## Async WebSocket Plugin -The server includes a web socket plugin which lets you define different WebSocket locations to connect to -without starting another listening service or using different port - -### Async WebSocket Event -```cpp - -void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){ - if(type == WS_EVT_CONNECT){ - //client connected - os_printf("ws[%s][%u] connect\n", server->url(), client->id()); - client->printf("Hello Client %u :)", client->id()); - client->ping(); - } else if(type == WS_EVT_DISCONNECT){ - //client disconnected - os_printf("ws[%s][%u] disconnect: %u\n", server->url(), client->id()); - } else if(type == WS_EVT_ERROR){ - //error was received from the other end - os_printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t*)arg), (char*)data); - } else if(type == WS_EVT_PONG){ - //pong message was received (in response to a ping request maybe) - os_printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len)?(char*)data:""); - } else if(type == WS_EVT_DATA){ - //data packet - AwsFrameInfo * info = (AwsFrameInfo*)arg; - if(info->final && info->index == 0 && info->len == len){ - //the whole message is in a single frame and we got all of it's data - os_printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT)?"text":"binary", info->len); - if(info->opcode == WS_TEXT){ - data[len] = 0; - os_printf("%s\n", (char*)data); - } else { - for(size_t i=0; i < info->len; i++){ - os_printf("%02x ", data[i]); - } - os_printf("\n"); - } - if(info->opcode == WS_TEXT) - client->text("I got your text message"); - else - client->binary("I got your binary message"); - } else { - //message is comprised of multiple frames or the frame is split into multiple packets - if(info->index == 0){ - if(info->num == 0) - os_printf("ws[%s][%u] %s-message start\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); - os_printf("ws[%s][%u] frame[%u] start[%llu]\n", server->url(), client->id(), info->num, info->len); - } - - os_printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len); - if(info->message_opcode == WS_TEXT){ - data[len] = 0; - os_printf("%s\n", (char*)data); - } else { - for(size_t i=0; i < len; i++){ - os_printf("%02x ", data[i]); - } - os_printf("\n"); - } - - if((info->index + len) == info->len){ - os_printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len); - if(info->final){ - os_printf("ws[%s][%u] %s-message end\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); - if(info->message_opcode == WS_TEXT) - client->text("I got your text message"); - else - client->binary("I got your binary message"); - } - } - } - } -} -``` - -### Methods for sending data to a socket client -```cpp - - - -//Server methods -AsyncWebSocket ws("/ws"); -//printf to a client -ws.printf((uint32_t)client_id, arguments...); -//printf to all clients -ws.printfAll(arguments...); -//printf_P to a client -ws.printf_P((uint32_t)client_id, PSTR(format), arguments...); -//printfAll_P to all clients -ws.printfAll_P(PSTR(format), arguments...); -//send text to a client -ws.text((uint32_t)client_id, (char*)text); -ws.text((uint32_t)client_id, (uint8_t*)text, (size_t)len); -//send text from PROGMEM to a client -ws.text((uint32_t)client_id, PSTR("text")); -const char flash_text[] PROGMEM = "Text to send" -ws.text((uint32_t)client_id, FPSTR(flash_text)); -//send text to all clients -ws.textAll((char*)text); -ws.textAll((uint8_t*)text, (size_t)len); -//send binary to a client -ws.binary((uint32_t)client_id, (char*)binary); -ws.binary((uint32_t)client_id, (uint8_t*)binary, (size_t)len); -//send binary from PROGMEM to a client -const uint8_t flash_binary[] PROGMEM = { 0x01, 0x02, 0x03, 0x04 }; -ws.binary((uint32_t)client_id, flash_binary, 4); -//send binary to all clients -ws.binaryAll((char*)binary); -ws.binaryAll((uint8_t*)binary, (size_t)len); -//HTTP Authenticate before switch to Websocket protocol -ws.setAuthentication("user", "pass"); - -//client methods -AsyncWebSocketClient * client; -//printf -client->printf(arguments...); -//printf_P -client->printf_P(PSTR(format), arguments...); -//send text -client->text((char*)text); -client->text((uint8_t*)text, (size_t)len); -//send text from PROGMEM -client->text(PSTR("text")); -const char flash_text[] PROGMEM = "Text to send"; -client->text(FPSTR(flash_text)); -//send binary -client->binary((char*)binary); -client->binary((uint8_t*)binary, (size_t)len); -//send binary from PROGMEM -const uint8_t flash_binary[] PROGMEM = { 0x01, 0x02, 0x03, 0x04 }; -client->binary(flash_binary, 4); -``` - -### Direct access to web socket message buffer -When sending a web socket message using the above methods a buffer is created. Under certain circumstances you might want to manipulate or populate this buffer directly from your application, for example to prevent unnecessary duplications of the data. This example below shows how to create a buffer and print data to it from an ArduinoJson object then send it. - -```cpp -void sendDataWs(AsyncWebSocketClient * client) -{ - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.createObject(); - root["a"] = "abc"; - root["b"] = "abcd"; - root["c"] = "abcde"; - root["d"] = "abcdef"; - root["e"] = "abcdefg"; - size_t len = root.measureLength(); - AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); // creates a buffer (len + 1) for you. - if (buffer) { - root.printTo((char *)buffer->get(), len + 1); - if (client) { - client->text(buffer); - } else { - ws.textAll(buffer); - } - } -} -``` - -### Limiting the number of web socket clients -Browsers sometimes do not correctly close the websocket connection, even when the close() function is called in javascript. This will eventually exhaust the web server's resources and will cause the server to crash. Periodically calling the cleanClients() function from the main loop() function limits the number of clients by closing the oldest client when the maximum number of clients has been exceeded. This can called be every cycle, however, if you wish to use less power, then calling as infrequently as once per second is sufficient. - -```cpp -void loop(){ - ws.cleanupClients(); -} -``` - - -## Async Event Source Plugin -The server includes EventSource (Server-Sent Events) plugin which can be used to send short text events to the browser. -Difference between EventSource and WebSockets is that EventSource is single direction, text-only protocol. - -### Setup Event Source on the server -```cpp -AsyncWebServer server(80); -AsyncEventSource events("/events"); - -void setup(){ - // setup ...... - events.onConnect([](AsyncEventSourceClient *client){ - if(client->lastId()){ - Serial.printf("Client reconnected! Last message ID that it gat is: %u\n", client->lastId()); - } - //send event with message "hello!", id current millis - // and set reconnect delay to 1 second - client->send("hello!",NULL,millis(),1000); - }); - //HTTP Basic authentication - events.setAuthentication("user", "pass"); - server.addHandler(&events); - // setup ...... -} - -void loop(){ - if(eventTriggered){ // your logic here - //send event "myevent" - events.send("my event content","myevent",millis()); - } -} -``` - -### Setup Event Source in the browser -```javascript -if (!!window.EventSource) { - var source = new EventSource('/events'); - - source.addEventListener('open', function(e) { - console.log("Events Connected"); - }, false); - - source.addEventListener('error', function(e) { - if (e.target.readyState != EventSource.OPEN) { - console.log("Events Disconnected"); - } - }, false); - - source.addEventListener('message', function(e) { - console.log("message", e.data); - }, false); - - source.addEventListener('myevent', function(e) { - console.log("myevent", e.data); - }, false); -} -``` - -## Scanning for available WiFi Networks -```cpp -//First request will return 0 results unless you start scan from somewhere else (loop/setup) -//Do not request more often than 3-5 seconds -server.on("/scan", HTTP_GET, [](AsyncWebServerRequest *request){ - String json = "["; - int n = WiFi.scanComplete(); - if(n == -2){ - WiFi.scanNetworks(true); - } else if(n){ - for (int i = 0; i < n; ++i){ - if(i) json += ","; - json += "{"; - json += "\"rssi\":"+String(WiFi.RSSI(i)); - json += ",\"ssid\":\""+WiFi.SSID(i)+"\""; - json += ",\"bssid\":\""+WiFi.BSSIDstr(i)+"\""; - json += ",\"channel\":"+String(WiFi.channel(i)); - json += ",\"secure\":"+String(WiFi.encryptionType(i)); - json += ",\"hidden\":"+String(WiFi.isHidden(i)?"true":"false"); - json += "}"; - } - WiFi.scanDelete(); - if(WiFi.scanComplete() == -2){ - WiFi.scanNetworks(true); - } - } - json += "]"; - request->send(200, "application/json", json); - json = String(); -}); -``` - -## Remove handlers and rewrites - -Server goes through handlers in same order as they were added. You can't simple add handler with same path to override them. -To remove handler: -```arduino -// save callback for particular URL path -auto handler = server.on("/some/path", [](AsyncWebServerRequest *request){ - //do something useful -}); -// when you don't need handler anymore remove it -server.removeHandler(&handler); - -// same with rewrites -server.removeRewrite(&someRewrite); - -server.onNotFound([](AsyncWebServerRequest *request){ - request->send(404); -}); - -// remove server.onNotFound handler -server.onNotFound(NULL); - -// remove all rewrites, handlers and onNotFound/onFileUpload/onRequestBody callbacks -server.reset(); -``` - -## Setting up the server -```cpp -#include "ESPAsyncTCP.h" -#include "ESPAsyncWebServer.h" - -AsyncWebServer server(80); -AsyncWebSocket ws("/ws"); // access at ws://[esp ip]/ws -AsyncEventSource events("/events"); // event source (Server-Sent events) - -const char* ssid = "your-ssid"; -const char* password = "your-pass"; -const char* http_username = "admin"; -const char* http_password = "admin"; - -//flag to use from web update to reboot the ESP -bool shouldReboot = false; - -void onRequest(AsyncWebServerRequest *request){ - //Handle Unknown Request - request->send(404); -} - -void onBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){ - //Handle body -} - -void onUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ - //Handle upload -} - -void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){ - //Handle WebSocket event -} - -void setup(){ - Serial.begin(115200); - WiFi.mode(WIFI_STA); - WiFi.begin(ssid, password); - if (WiFi.waitForConnectResult() != WL_CONNECTED) { - Serial.printf("WiFi Failed!\n"); - return; - } - - // attach AsyncWebSocket - ws.onEvent(onEvent); - server.addHandler(&ws); - - // attach AsyncEventSource - server.addHandler(&events); - - // respond to GET requests on URL /heap - server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){ - request->send(200, "text/plain", String(ESP.getFreeHeap())); - }); - - // upload a file to /upload - server.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request){ - request->send(200); - }, onUpload); - - // send a file when /index is requested - server.on("/index", HTTP_ANY, [](AsyncWebServerRequest *request){ - request->send(SPIFFS, "/index.htm"); - }); - - // HTTP basic authentication - server.on("/login", HTTP_GET, [](AsyncWebServerRequest *request){ - if(!request->authenticate(http_username, http_password)) - return request->requestAuthentication(); - request->send(200, "text/plain", "Login Success!"); - }); - - // Simple Firmware Update Form - server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){ - request->send(200, "text/html", "
"); - }); - server.on("/update", HTTP_POST, [](AsyncWebServerRequest *request){ - shouldReboot = !Update.hasError(); - AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", shouldReboot?"OK":"FAIL"); - response->addHeader("Connection", "close"); - request->send(response); - },[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ - if(!index){ - Serial.printf("Update Start: %s\n", filename.c_str()); - Update.runAsync(true); - if(!Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000)){ - Update.printError(Serial); - } - } - if(!Update.hasError()){ - if(Update.write(data, len) != len){ - Update.printError(Serial); - } - } - if(final){ - if(Update.end(true)){ - Serial.printf("Update Success: %uB\n", index+len); - } else { - Update.printError(Serial); - } - } - }); - - // attach filesystem root at URL /fs - server.serveStatic("/fs", SPIFFS, "/"); - - // Catch-All Handlers - // Any request that can not find a Handler that canHandle it - // ends in the callbacks below. - server.onNotFound(onRequest); - server.onFileUpload(onUpload); - server.onRequestBody(onBody); - - server.begin(); -} - -void loop(){ - if(shouldReboot){ - Serial.println("Rebooting..."); - delay(100); - ESP.restart(); - } - static char temp[128]; - sprintf(temp, "Seconds since boot: %u", millis()/1000); - events.send(temp, "time"); //send event "time" -} -``` - -### Setup global and class functions as request handlers - -```cpp -#include -#include -#include -#include - -void handleRequest(AsyncWebServerRequest *request){} - -class WebClass { -public : - AsyncWebServer classWebServer = AsyncWebServer(81); - - WebClass(){}; - - void classRequest (AsyncWebServerRequest *request){} - - void begin(){ - // attach global request handler - classWebServer.on("/example", HTTP_ANY, handleRequest); - - // attach class request handler - classWebServer.on("/example", HTTP_ANY, std::bind(&WebClass::classRequest, this, std::placeholders::_1)); - } -}; - -AsyncWebServer globalWebServer(80); -WebClass webClassInstance; - -void setup() { - // attach global request handler - globalWebServer.on("/example", HTTP_ANY, handleRequest); - - // attach class request handler - globalWebServer.on("/example", HTTP_ANY, std::bind(&WebClass::classRequest, webClassInstance, std::placeholders::_1)); -} - -void loop() { - -} -``` - -### Methods for controlling websocket connections - -```cpp - // Disable client connections if it was activated - if ( ws.enabled() ) - ws.enable(false); - - // enable client connections if it was disabled - if ( !ws.enabled() ) - ws.enable(true); -``` - -Example of OTA code - -```cpp - // OTA callbacks - ArduinoOTA.onStart([]() { - // Clean SPIFFS - SPIFFS.end(); - - // Disable client connections - ws.enable(false); - - // Advertise connected clients what's going on - ws.textAll("OTA Update Started"); - - // Close them - ws.closeAll(); - - }); - -``` - -### Adding Default Headers - -In some cases, such as when working with CORS, or with some sort of custom authentication system, -you might need to define a header that should get added to all responses (including static, websocket and EventSource). -The DefaultHeaders singleton allows you to do this. - -Example: - -```cpp -DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*"); -webServer.begin(); -``` - -*NOTE*: You will still need to respond to the OPTIONS method for CORS pre-flight in most cases. (unless you are only using GET) - -This is one option: - -```cpp -webServer.onNotFound([](AsyncWebServerRequest *request) { - if (request->method() == HTTP_OPTIONS) { - request->send(200); - } else { - request->send(404); - } -}); -``` - -### Path variable - -With path variable you can create a custom regex rule for a specific parameter in a route. -For example we want a `sensorId` parameter in a route rule to match only a integer. - -```cpp - server.on("^\\/sensor\\/([0-9]+)$", HTTP_GET, [] (AsyncWebServerRequest *request) { - String sensorId = request->pathArg(0); - }); -``` -*NOTE*: All regex patterns starts with `^` and ends with `$` - -To enable the `Path variable` support, you have to define the buildflag `-DASYNCWEBSERVER_REGEX`. - - -For Arduino IDE create/update `platform.local.txt`: - -`Windows`: C:\Users\(username)\AppData\Local\Arduino15\packages\\`{espxxxx}`\hardware\\`espxxxx`\\`{version}`\platform.local.txt - -`Linux`: ~/.arduino15/packages/`{espxxxx}`/hardware/`{espxxxx}`/`{version}`/platform.local.txt - -Add/Update the following line: -``` - compiler.cpp.extra_flags=-DDASYNCWEBSERVER_REGEX -``` - -For platformio modify `platformio.ini`: -```ini -[env:myboard] -build_flags = - -DASYNCWEBSERVER_REGEX -``` -*NOTE*: By enabling `ASYNCWEBSERVER_REGEX`, `` will be included. This will add an 100k to your binary. diff --git a/lib/libesp32/ESPAsyncWebServer/_config.yml b/lib/libesp32/ESPAsyncWebServer/_config.yml deleted file mode 100644 index c4192631f..000000000 --- a/lib/libesp32/ESPAsyncWebServer/_config.yml +++ /dev/null @@ -1 +0,0 @@ -theme: jekyll-theme-cayman \ No newline at end of file diff --git a/lib/libesp32/ESPAsyncWebServer/component.mk b/lib/libesp32/ESPAsyncWebServer/component.mk deleted file mode 100644 index bb5bb1614..000000000 --- a/lib/libesp32/ESPAsyncWebServer/component.mk +++ /dev/null @@ -1,3 +0,0 @@ -COMPONENT_ADD_INCLUDEDIRS := src -COMPONENT_SRCDIRS := src -CXXFLAGS += -fno-rtti diff --git a/lib/libesp32/ESPAsyncWebServer/examples/CaptivePortal/CaptivePortal.ino b/lib/libesp32/ESPAsyncWebServer/examples/CaptivePortal/CaptivePortal.ino deleted file mode 100644 index f97f142a6..000000000 --- a/lib/libesp32/ESPAsyncWebServer/examples/CaptivePortal/CaptivePortal.ino +++ /dev/null @@ -1,47 +0,0 @@ -#include -#ifdef ESP32 -#include -#include -#elif defined(ESP8266) -#include -#include -#endif -#include "ESPAsyncWebServer.h" - -DNSServer dnsServer; -AsyncWebServer server(80); - -class CaptiveRequestHandler : public AsyncWebHandler { -public: - CaptiveRequestHandler() {} - virtual ~CaptiveRequestHandler() {} - - bool canHandle(AsyncWebServerRequest *request){ - //request->addInterestingHeader("ANY"); - return true; - } - - void handleRequest(AsyncWebServerRequest *request) { - AsyncResponseStream *response = request->beginResponseStream("text/html"); - response->print("Captive Portal"); - response->print("

This is out captive portal front page.

"); - response->printf("

You were trying to reach: http://%s%s

", request->host().c_str(), request->url().c_str()); - response->printf("

Try opening this link instead

", WiFi.softAPIP().toString().c_str()); - response->print(""); - request->send(response); - } -}; - - -void setup(){ - //your other setup stuff... - WiFi.softAP("esp-captive"); - dnsServer.start(53, "*", WiFi.softAPIP()); - server.addHandler(new CaptiveRequestHandler()).setFilter(ON_AP_FILTER);//only when requested from AP - //more handlers... - server.begin(); -} - -void loop(){ - dnsServer.processNextRequest(); -} diff --git a/lib/libesp32/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino b/lib/libesp32/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino deleted file mode 100644 index bf42d0038..000000000 --- a/lib/libesp32/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino +++ /dev/null @@ -1,221 +0,0 @@ -#include -#ifdef ESP32 -#include -#include -#include -#include -#include -#elif defined(ESP8266) -#include -#include -#include -#endif -#include -#include - -// SKETCH BEGIN -AsyncWebServer server(80); -AsyncWebSocket ws("/ws"); -AsyncEventSource events("/events"); - -void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){ - if(type == WS_EVT_CONNECT){ - Serial.printf("ws[%s][%u] connect\n", server->url(), client->id()); - client->printf("Hello Client %u :)", client->id()); - client->ping(); - } else if(type == WS_EVT_DISCONNECT){ - Serial.printf("ws[%s][%u] disconnect\n", server->url(), client->id()); - } else if(type == WS_EVT_ERROR){ - Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t*)arg), (char*)data); - } else if(type == WS_EVT_PONG){ - Serial.printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len)?(char*)data:""); - } else if(type == WS_EVT_DATA){ - AwsFrameInfo * info = (AwsFrameInfo*)arg; - String msg = ""; - if(info->final && info->index == 0 && info->len == len){ - //the whole message is in a single frame and we got all of it's data - Serial.printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT)?"text":"binary", info->len); - - if(info->opcode == WS_TEXT){ - for(size_t i=0; i < info->len; i++) { - msg += (char) data[i]; - } - } else { - char buff[3]; - for(size_t i=0; i < info->len; i++) { - sprintf(buff, "%02x ", (uint8_t) data[i]); - msg += buff ; - } - } - Serial.printf("%s\n",msg.c_str()); - - if(info->opcode == WS_TEXT) - client->text("I got your text message"); - else - client->binary("I got your binary message"); - } else { - //message is comprised of multiple frames or the frame is split into multiple packets - if(info->index == 0){ - if(info->num == 0) - Serial.printf("ws[%s][%u] %s-message start\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); - Serial.printf("ws[%s][%u] frame[%u] start[%llu]\n", server->url(), client->id(), info->num, info->len); - } - - Serial.printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len); - - if(info->opcode == WS_TEXT){ - for(size_t i=0; i < len; i++) { - msg += (char) data[i]; - } - } else { - char buff[3]; - for(size_t i=0; i < len; i++) { - sprintf(buff, "%02x ", (uint8_t) data[i]); - msg += buff ; - } - } - Serial.printf("%s\n",msg.c_str()); - - if((info->index + len) == info->len){ - Serial.printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len); - if(info->final){ - Serial.printf("ws[%s][%u] %s-message end\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); - if(info->message_opcode == WS_TEXT) - client->text("I got your text message"); - else - client->binary("I got your binary message"); - } - } - } - } -} - - -const char* ssid = "*******"; -const char* password = "*******"; -const char * hostName = "esp-async"; -const char* http_username = "admin"; -const char* http_password = "admin"; - -void setup(){ - Serial.begin(115200); - Serial.setDebugOutput(true); - WiFi.mode(WIFI_AP_STA); - WiFi.softAP(hostName); - WiFi.begin(ssid, password); - if (WiFi.waitForConnectResult() != WL_CONNECTED) { - Serial.printf("STA: Failed!\n"); - WiFi.disconnect(false); - delay(1000); - WiFi.begin(ssid, password); - } - - //Send OTA events to the browser - ArduinoOTA.onStart([]() { events.send("Update Start", "ota"); }); - ArduinoOTA.onEnd([]() { events.send("Update End", "ota"); }); - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - char p[32]; - sprintf(p, "Progress: %u%%\n", (progress/(total/100))); - events.send(p, "ota"); - }); - ArduinoOTA.onError([](ota_error_t error) { - if(error == OTA_AUTH_ERROR) events.send("Auth Failed", "ota"); - else if(error == OTA_BEGIN_ERROR) events.send("Begin Failed", "ota"); - else if(error == OTA_CONNECT_ERROR) events.send("Connect Failed", "ota"); - else if(error == OTA_RECEIVE_ERROR) events.send("Recieve Failed", "ota"); - else if(error == OTA_END_ERROR) events.send("End Failed", "ota"); - }); - ArduinoOTA.setHostname(hostName); - ArduinoOTA.begin(); - - MDNS.addService("http","tcp",80); - - SPIFFS.begin(); - - ws.onEvent(onWsEvent); - server.addHandler(&ws); - - events.onConnect([](AsyncEventSourceClient *client){ - client->send("hello!",NULL,millis(),1000); - }); - server.addHandler(&events); - -#ifdef ESP32 - server.addHandler(new SPIFFSEditor(SPIFFS, http_username,http_password)); -#elif defined(ESP8266) - server.addHandler(new SPIFFSEditor(http_username,http_password)); -#endif - - server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){ - request->send(200, "text/plain", String(ESP.getFreeHeap())); - }); - - server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm"); - - server.onNotFound([](AsyncWebServerRequest *request){ - Serial.printf("NOT_FOUND: "); - if(request->method() == HTTP_GET) - Serial.printf("GET"); - else if(request->method() == HTTP_POST) - Serial.printf("POST"); - else if(request->method() == HTTP_DELETE) - Serial.printf("DELETE"); - else if(request->method() == HTTP_PUT) - Serial.printf("PUT"); - else if(request->method() == HTTP_PATCH) - Serial.printf("PATCH"); - else if(request->method() == HTTP_HEAD) - Serial.printf("HEAD"); - else if(request->method() == HTTP_OPTIONS) - Serial.printf("OPTIONS"); - else - Serial.printf("UNKNOWN"); - Serial.printf(" http://%s%s\n", request->host().c_str(), request->url().c_str()); - - if(request->contentLength()){ - Serial.printf("_CONTENT_TYPE: %s\n", request->contentType().c_str()); - Serial.printf("_CONTENT_LENGTH: %u\n", request->contentLength()); - } - - int headers = request->headers(); - int i; - for(i=0;igetHeader(i); - Serial.printf("_HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str()); - } - - int params = request->params(); - for(i=0;igetParam(i); - if(p->isFile()){ - Serial.printf("_FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size()); - } else if(p->isPost()){ - Serial.printf("_POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); - } else { - Serial.printf("_GET[%s]: %s\n", p->name().c_str(), p->value().c_str()); - } - } - - request->send(404); - }); - server.onFileUpload([](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){ - if(!index) - Serial.printf("UploadStart: %s\n", filename.c_str()); - Serial.printf("%s", (const char*)data); - if(final) - Serial.printf("UploadEnd: %s (%u)\n", filename.c_str(), index+len); - }); - server.onRequestBody([](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){ - if(!index) - Serial.printf("BodyStart: %u\n", total); - Serial.printf("%s", (const char*)data); - if(index + len == total) - Serial.printf("BodyEnd: %u\n", total); - }); - server.begin(); -} - -void loop(){ - ArduinoOTA.handle(); - ws.cleanupClients(); -} diff --git a/lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/.test.build_flags b/lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/.test.build_flags deleted file mode 100644 index 9ea3bb74a..000000000 --- a/lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/.test.build_flags +++ /dev/null @@ -1 +0,0 @@ --DASYNCWEBSERVER_REGEX=1 diff --git a/lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/regex_patterns.ino b/lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/regex_patterns.ino deleted file mode 100644 index fb013063e..000000000 --- a/lib/libesp32/ESPAsyncWebServer/examples/regex_patterns/regex_patterns.ino +++ /dev/null @@ -1,77 +0,0 @@ -// -// A simple server implementation with regex routes: -// * serve static messages -// * read GET and POST parameters -// * handle missing pages / 404s -// - -// Add buildflag ASYNCWEBSERVER_REGEX to enable the regex support - -// For platformio: platformio.ini: -// build_flags = -// -DASYNCWEBSERVER_REGEX - -// For arduino IDE: create/update platform.local.txt -// Windows: C:\Users\(username)\AppData\Local\Arduino15\packages\espxxxx\hardware\espxxxx\{version}\platform.local.txt -// Linux: ~/.arduino15/packages/espxxxx/hardware/espxxxx/{version}/platform.local.txt -// -// compiler.cpp.extra_flags=-DASYNCWEBSERVER_REGEX=1 - -#include -#ifdef ESP32 -#include -#include -#elif defined(ESP8266) -#include -#include -#endif -#include - -AsyncWebServer server(80); - -const char* ssid = "YOUR_SSID"; -const char* password = "YOUR_PASSWORD"; - -const char* PARAM_MESSAGE = "message"; - -void notFound(AsyncWebServerRequest *request) { - request->send(404, "text/plain", "Not found"); -} - -void setup() { - - Serial.begin(115200); - WiFi.mode(WIFI_STA); - WiFi.begin(ssid, password); - if (WiFi.waitForConnectResult() != WL_CONNECTED) { - Serial.printf("WiFi Failed!\n"); - return; - } - - Serial.print("IP Address: "); - Serial.println(WiFi.localIP()); - - server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ - request->send(200, "text/plain", "Hello, world"); - }); - - // Send a GET request to /sensor/ - server.on("^\\/sensor\\/([0-9]+)$", HTTP_GET, [] (AsyncWebServerRequest *request) { - String sensorNumber = request->pathArg(0); - request->send(200, "text/plain", "Hello, sensor: " + sensorNumber); - }); - - // Send a GET request to /sensor//action/ - server.on("^\\/sensor\\/([0-9]+)\\/action\\/([a-zA-Z0-9]+)$", HTTP_GET, [] (AsyncWebServerRequest *request) { - String sensorNumber = request->pathArg(0); - String action = request->pathArg(1); - request->send(200, "text/plain", "Hello, sensor: " + sensorNumber + ", with action: " + action); - }); - - server.onNotFound(notFound); - - server.begin(); -} - -void loop() { -} diff --git a/lib/libesp32/ESPAsyncWebServer/examples/simple_server/simple_server.ino b/lib/libesp32/ESPAsyncWebServer/examples/simple_server/simple_server.ino deleted file mode 100644 index bdbcf60dc..000000000 --- a/lib/libesp32/ESPAsyncWebServer/examples/simple_server/simple_server.ino +++ /dev/null @@ -1,74 +0,0 @@ -// -// A simple server implementation showing how to: -// * serve static messages -// * read GET and POST parameters -// * handle missing pages / 404s -// - -#include -#ifdef ESP32 -#include -#include -#elif defined(ESP8266) -#include -#include -#endif -#include - -AsyncWebServer server(80); - -const char* ssid = "YOUR_SSID"; -const char* password = "YOUR_PASSWORD"; - -const char* PARAM_MESSAGE = "message"; - -void notFound(AsyncWebServerRequest *request) { - request->send(404, "text/plain", "Not found"); -} - -void setup() { - - Serial.begin(115200); - WiFi.mode(WIFI_STA); - WiFi.begin(ssid, password); - if (WiFi.waitForConnectResult() != WL_CONNECTED) { - Serial.printf("WiFi Failed!\n"); - return; - } - - Serial.print("IP Address: "); - Serial.println(WiFi.localIP()); - - server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ - request->send(200, "text/plain", "Hello, world"); - }); - - // Send a GET request to /get?message= - server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) { - String message; - if (request->hasParam(PARAM_MESSAGE)) { - message = request->getParam(PARAM_MESSAGE)->value(); - } else { - message = "No message sent"; - } - request->send(200, "text/plain", "Hello, GET: " + message); - }); - - // Send a POST request to /post with a form field message set to - server.on("/post", HTTP_POST, [](AsyncWebServerRequest *request){ - String message; - if (request->hasParam(PARAM_MESSAGE, true)) { - message = request->getParam(PARAM_MESSAGE, true)->value(); - } else { - message = "No message sent"; - } - request->send(200, "text/plain", "Hello, POST: " + message); - }); - - server.onNotFound(notFound); - - server.begin(); -} - -void loop() { -} \ No newline at end of file diff --git a/lib/libesp32/ESPAsyncWebServer/keywords.txt b/lib/libesp32/ESPAsyncWebServer/keywords.txt deleted file mode 100644 index c391e6c43..000000000 --- a/lib/libesp32/ESPAsyncWebServer/keywords.txt +++ /dev/null @@ -1,3 +0,0 @@ -JsonArray KEYWORD1 -add KEYWORD2 -createArray KEYWORD3 diff --git a/lib/libesp32/ESPAsyncWebServer/library.json b/lib/libesp32/ESPAsyncWebServer/library.json deleted file mode 100644 index 750ca28d2..000000000 --- a/lib/libesp32/ESPAsyncWebServer/library.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name":"ESP Async WebServer", - "description":"Asynchronous HTTP and WebSocket Server Library for ESP8266 and ESP32", - "keywords":"http,async,websocket,webserver", - "authors": - { - "name": "Hristo Gochkov", - "maintainer": true - }, - "repository": - { - "type": "git", - "url": "https://github.com/me-no-dev/ESPAsyncWebServer.git" - }, - "version": "1.2.3", - "license": "LGPL-3.0", - "frameworks": "arduino", - "platforms": ["espressif8266", "espressif32"], - "dependencies": [ - { - "owner": "me-no-dev", - "name": "ESPAsyncTCP", - "version": "^1.2.2", - "platforms": "espressif8266" - }, - { - "owner": "me-no-dev", - "name": "AsyncTCP", - "version": "^1.1.1", - "platforms": "espressif32" - }, - { - "name": "Hash", - "platforms": "espressif8266" - } - ] -} diff --git a/lib/libesp32/ESPAsyncWebServer/library.properties b/lib/libesp32/ESPAsyncWebServer/library.properties deleted file mode 100644 index 401b04173..000000000 --- a/lib/libesp32/ESPAsyncWebServer/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=ESP Async WebServer -version=1.2.3 -author=Me-No-Dev -maintainer=Me-No-Dev -sentence=Async Web Server for ESP8266 and ESP31B -paragraph=Async Web Server for ESP8266 and ESP31B -category=Other -url=https://github.com/me-no-dev/ESPAsyncWebServer -architectures=* diff --git a/lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.cpp b/lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.cpp deleted file mode 100644 index 663177b59..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/* - Asynchronous WebServer library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#include "Arduino.h" -#include "AsyncEventSource.h" - -static String generateEventMessage(const char *message, const char *event, uint32_t id, uint32_t reconnect){ - String ev = ""; - - if(reconnect){ - ev += "retry: "; - ev += String(reconnect); - ev += "\r\n"; - } - - if(id){ - ev += "id: "; - ev += String(id); - ev += "\r\n"; - } - - if(event != NULL){ - ev += "event: "; - ev += String(event); - ev += "\r\n"; - } - - if(message != NULL){ - size_t messageLen = strlen(message); - char * lineStart = (char *)message; - char * lineEnd; - do { - char * nextN = strchr(lineStart, '\n'); - char * nextR = strchr(lineStart, '\r'); - if(nextN == NULL && nextR == NULL){ - size_t llen = ((char *)message + messageLen) - lineStart; - char * ldata = (char *)malloc(llen+1); - if(ldata != NULL){ - memcpy(ldata, lineStart, llen); - ldata[llen] = 0; - ev += "data: "; - ev += ldata; - ev += "\r\n\r\n"; - free(ldata); - } - lineStart = (char *)message + messageLen; - } else { - char * nextLine = NULL; - if(nextN != NULL && nextR != NULL){ - if(nextR < nextN){ - lineEnd = nextR; - if(nextN == (nextR + 1)) - nextLine = nextN + 1; - else - nextLine = nextR + 1; - } else { - lineEnd = nextN; - if(nextR == (nextN + 1)) - nextLine = nextR + 1; - else - nextLine = nextN + 1; - } - } else if(nextN != NULL){ - lineEnd = nextN; - nextLine = nextN + 1; - } else { - lineEnd = nextR; - nextLine = nextR + 1; - } - - size_t llen = lineEnd - lineStart; - char * ldata = (char *)malloc(llen+1); - if(ldata != NULL){ - memcpy(ldata, lineStart, llen); - ldata[llen] = 0; - ev += "data: "; - ev += ldata; - ev += "\r\n"; - free(ldata); - } - lineStart = nextLine; - if(lineStart == ((char *)message + messageLen)) - ev += "\r\n"; - } - } while(lineStart < ((char *)message + messageLen)); - } - - return ev; -} - -// Message - -AsyncEventSourceMessage::AsyncEventSourceMessage(const char * data, size_t len) -: _data(nullptr), _len(len), _sent(0), _acked(0) -{ - _data = (uint8_t*)malloc(_len+1); - if(_data == nullptr){ - _len = 0; - } else { - memcpy(_data, data, len); - _data[_len] = 0; - } -} - -AsyncEventSourceMessage::~AsyncEventSourceMessage() { - if(_data != NULL) - free(_data); -} - -size_t AsyncEventSourceMessage::ack(size_t len, uint32_t time) { - (void)time; - // If the whole message is now acked... - if(_acked + len > _len){ - // Return the number of extra bytes acked (they will be carried on to the next message) - const size_t extra = _acked + len - _len; - _acked = _len; - return extra; - } - // Return that no extra bytes left. - _acked += len; - return 0; -} - -size_t AsyncEventSourceMessage::send(AsyncClient *client) { - const size_t len = _len - _sent; - if(client->space() < len){ - return 0; - } - size_t sent = client->add((const char *)_data, len); - if(client->canSend()) - client->send(); - _sent += sent; - return sent; -} - -// Client - -AsyncEventSourceClient::AsyncEventSourceClient(AsyncWebServerRequest *request, AsyncEventSource *server) -: _messageQueue(AsyncLinkedList([](AsyncEventSourceMessage *m){ delete m; })) -{ - _client = request->client(); - _server = server; - _lastId = 0; - if(request->hasHeader("Last-Event-ID")) - _lastId = atoi(request->getHeader("Last-Event-ID")->value().c_str()); - - _client->setRxTimeout(0); - _client->onError(NULL, NULL); - _client->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ (void)c; ((AsyncEventSourceClient*)(r))->_onAck(len, time); }, this); - _client->onPoll([](void *r, AsyncClient* c){ (void)c; ((AsyncEventSourceClient*)(r))->_onPoll(); }, this); - _client->onData(NULL, NULL); - _client->onTimeout([this](void *r, AsyncClient* c __attribute__((unused)), uint32_t time){ ((AsyncEventSourceClient*)(r))->_onTimeout(time); }, this); - _client->onDisconnect([this](void *r, AsyncClient* c){ ((AsyncEventSourceClient*)(r))->_onDisconnect(); delete c; }, this); - - _server->_addClient(this); - delete request; -} - -AsyncEventSourceClient::~AsyncEventSourceClient(){ - _messageQueue.free(); - close(); -} - -void AsyncEventSourceClient::_queueMessage(AsyncEventSourceMessage *dataMessage){ - if(dataMessage == NULL) - return; - if(!connected()){ - delete dataMessage; - return; - } - if(_messageQueue.length() >= SSE_MAX_QUEUED_MESSAGES){ - ets_printf("ERROR: Too many messages queued\n"); - delete dataMessage; - } else { - _messageQueue.add(dataMessage); - } - if(_client->canSend()) - _runQueue(); -} - -void AsyncEventSourceClient::_onAck(size_t len, uint32_t time){ - while(len && !_messageQueue.isEmpty()){ - len = _messageQueue.front()->ack(len, time); - if(_messageQueue.front()->finished()) - _messageQueue.remove(_messageQueue.front()); - } - - _runQueue(); -} - -void AsyncEventSourceClient::_onPoll(){ - if(!_messageQueue.isEmpty()){ - _runQueue(); - } -} - - -void AsyncEventSourceClient::_onTimeout(uint32_t time __attribute__((unused))){ - _client->close(true); -} - -void AsyncEventSourceClient::_onDisconnect(){ - _client = NULL; - _server->_handleDisconnect(this); -} - -void AsyncEventSourceClient::close(){ - if(_client != NULL) - _client->close(); -} - -void AsyncEventSourceClient::write(const char * message, size_t len){ - _queueMessage(new AsyncEventSourceMessage(message, len)); -} - -void AsyncEventSourceClient::send(const char *message, const char *event, uint32_t id, uint32_t reconnect){ - String ev = generateEventMessage(message, event, id, reconnect); - _queueMessage(new AsyncEventSourceMessage(ev.c_str(), ev.length())); -} - -void AsyncEventSourceClient::_runQueue(){ - while(!_messageQueue.isEmpty() && _messageQueue.front()->finished()){ - _messageQueue.remove(_messageQueue.front()); - } - - for(auto i = _messageQueue.begin(); i != _messageQueue.end(); ++i) - { - if(!(*i)->sent()) - (*i)->send(_client); - } -} - - -// Handler - -AsyncEventSource::AsyncEventSource(const String& url) - : _url(url) - , _clients(AsyncLinkedList([](AsyncEventSourceClient *c){ delete c; })) - , _connectcb(NULL) -{} - -AsyncEventSource::~AsyncEventSource(){ - close(); -} - -void AsyncEventSource::onConnect(ArEventHandlerFunction cb){ - _connectcb = cb; -} - -void AsyncEventSource::_addClient(AsyncEventSourceClient * client){ - /*char * temp = (char *)malloc(2054); - if(temp != NULL){ - memset(temp+1,' ',2048); - temp[0] = ':'; - temp[2049] = '\r'; - temp[2050] = '\n'; - temp[2051] = '\r'; - temp[2052] = '\n'; - temp[2053] = 0; - client->write((const char *)temp, 2053); - free(temp); - }*/ - - _clients.add(client); - if(_connectcb) - _connectcb(client); -} - -void AsyncEventSource::_handleDisconnect(AsyncEventSourceClient * client){ - _clients.remove(client); -} - -void AsyncEventSource::close(){ - for(const auto &c: _clients){ - if(c->connected()) - c->close(); - } -} - -// pmb fix -size_t AsyncEventSource::avgPacketsWaiting() const { - if(_clients.isEmpty()) - return 0; - - size_t aql=0; - uint32_t nConnectedClients=0; - - for(const auto &c: _clients){ - if(c->connected()) { - aql+=c->packetsWaiting(); - ++nConnectedClients; - } - } -// return aql / nConnectedClients; - return ((aql) + (nConnectedClients/2))/(nConnectedClients); // round up -} - -void AsyncEventSource::send(const char *message, const char *event, uint32_t id, uint32_t reconnect){ - - - String ev = generateEventMessage(message, event, id, reconnect); - for(const auto &c: _clients){ - if(c->connected()) { - c->write(ev.c_str(), ev.length()); - } - } -} - -size_t AsyncEventSource::count() const { - return _clients.count_if([](AsyncEventSourceClient *c){ - return c->connected(); - }); -} - -bool AsyncEventSource::canHandle(AsyncWebServerRequest *request){ - if(request->method() != HTTP_GET || !request->url().equals(_url)) { - return false; - } - request->addInterestingHeader("Last-Event-ID"); - return true; -} - -void AsyncEventSource::handleRequest(AsyncWebServerRequest *request){ - if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str())) - return request->requestAuthentication(); - request->send(new AsyncEventSourceResponse(this)); -} - -// Response - -AsyncEventSourceResponse::AsyncEventSourceResponse(AsyncEventSource *server){ - _server = server; - _code = 200; - _contentType = "text/event-stream"; - _sendContentLength = false; - addHeader("Cache-Control", "no-cache"); - addHeader("Connection","keep-alive"); -} - -void AsyncEventSourceResponse::_respond(AsyncWebServerRequest *request){ - String out = _assembleHead(request->version()); - request->client()->write(out.c_str(), _headLength); - _state = RESPONSE_WAIT_ACK; -} - -size_t AsyncEventSourceResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time __attribute__((unused))){ - if(len){ - new AsyncEventSourceClient(request, _server); - } - return 0; -} - diff --git a/lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.h b/lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.h deleted file mode 100644 index 6ff43a6e7..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/AsyncEventSource.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - Asynchronous WebServer library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#ifndef ASYNCEVENTSOURCE_H_ -#define ASYNCEVENTSOURCE_H_ - -#include -#ifdef ESP32 -#include -#define SSE_MAX_QUEUED_MESSAGES 32 -#else -#include -#define SSE_MAX_QUEUED_MESSAGES 8 -#endif -#include - -#include "AsyncWebSynchronization.h" - -#ifdef ESP8266 -#include -#ifdef CRYPTO_HASH_h // include Hash.h from espressif framework if the first include was from the crypto library -#include <../src/Hash.h> -#endif -#endif - -#ifdef ESP32 -#define DEFAULT_MAX_SSE_CLIENTS 8 -#else -#define DEFAULT_MAX_SSE_CLIENTS 4 -#endif - -class AsyncEventSource; -class AsyncEventSourceResponse; -class AsyncEventSourceClient; -typedef std::function ArEventHandlerFunction; - -class AsyncEventSourceMessage { - private: - uint8_t * _data; - size_t _len; - size_t _sent; - //size_t _ack; - size_t _acked; - public: - AsyncEventSourceMessage(const char * data, size_t len); - ~AsyncEventSourceMessage(); - size_t ack(size_t len, uint32_t time __attribute__((unused))); - size_t send(AsyncClient *client); - bool finished(){ return _acked == _len; } - bool sent() { return _sent == _len; } -}; - -class AsyncEventSourceClient { - private: - AsyncClient *_client; - AsyncEventSource *_server; - uint32_t _lastId; - AsyncLinkedList _messageQueue; - void _queueMessage(AsyncEventSourceMessage *dataMessage); - void _runQueue(); - - public: - - AsyncEventSourceClient(AsyncWebServerRequest *request, AsyncEventSource *server); - ~AsyncEventSourceClient(); - - AsyncClient* client(){ return _client; } - void close(); - void write(const char * message, size_t len); - void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); - bool connected() const { return (_client != NULL) && _client->connected(); } - uint32_t lastId() const { return _lastId; } - size_t packetsWaiting() const { return _messageQueue.length(); } - - //system callbacks (do not call) - void _onAck(size_t len, uint32_t time); - void _onPoll(); - void _onTimeout(uint32_t time); - void _onDisconnect(); -}; - -class AsyncEventSource: public AsyncWebHandler { - private: - String _url; - AsyncLinkedList _clients; - ArEventHandlerFunction _connectcb; - public: - AsyncEventSource(const String& url); - ~AsyncEventSource(); - - const char * url() const { return _url.c_str(); } - void close(); - void onConnect(ArEventHandlerFunction cb); - void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); - size_t count() const; //number clinets connected - size_t avgPacketsWaiting() const; - - //system callbacks (do not call) - void _addClient(AsyncEventSourceClient * client); - void _handleDisconnect(AsyncEventSourceClient * client); - virtual bool canHandle(AsyncWebServerRequest *request) override final; - virtual void handleRequest(AsyncWebServerRequest *request) override final; -}; - -class AsyncEventSourceResponse: public AsyncWebServerResponse { - private: - String _content; - AsyncEventSource *_server; - public: - AsyncEventSourceResponse(AsyncEventSource *server); - void _respond(AsyncWebServerRequest *request); - size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); - bool _sourceValid() const { return true; } -}; - - -#endif /* ASYNCEVENTSOURCE_H_ */ diff --git a/lib/libesp32/ESPAsyncWebServer/src/AsyncJson.h b/lib/libesp32/ESPAsyncWebServer/src/AsyncJson.h deleted file mode 100644 index 2fa6a2d26..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/AsyncJson.h +++ /dev/null @@ -1,254 +0,0 @@ -// AsyncJson.h -/* - Async Response to use with ArduinoJson and AsyncWebServer - Written by Andrew Melvin (SticilFace) with help from me-no-dev and BBlanchon. - - Example of callback in use - - server.on("/json", HTTP_ANY, [](AsyncWebServerRequest * request) { - - AsyncJsonResponse * response = new AsyncJsonResponse(); - JsonObject& root = response->getRoot(); - root["key1"] = "key number one"; - JsonObject& nested = root.createNestedObject("nested"); - nested["key1"] = "key number one"; - - response->setLength(); - request->send(response); - }); - - -------------------- - - Async Request to use with ArduinoJson and AsyncWebServer - Written by Arsène von Wyss (avonwyss) - - Example - - AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/rest/endpoint"); - handler->onRequest([](AsyncWebServerRequest *request, JsonVariant &json) { - JsonObject& jsonObj = json.as(); - // ... - }); - server.addHandler(handler); - -*/ -#ifndef ASYNC_JSON_H_ -#define ASYNC_JSON_H_ -#include -#include -#include - -#if ARDUINOJSON_VERSION_MAJOR == 5 - #define ARDUINOJSON_5_COMPATIBILITY -#else - #ifndef DYNAMIC_JSON_DOCUMENT_SIZE - #define DYNAMIC_JSON_DOCUMENT_SIZE 1024 - #endif -#endif - -constexpr const char* JSON_MIMETYPE = "application/json"; - -/* - * Json Response - * */ - -class ChunkPrint : public Print { - private: - uint8_t* _destination; - size_t _to_skip; - size_t _to_write; - size_t _pos; - public: - ChunkPrint(uint8_t* destination, size_t from, size_t len) - : _destination(destination), _to_skip(from), _to_write(len), _pos{0} {} - virtual ~ChunkPrint(){} - size_t write(uint8_t c){ - if (_to_skip > 0) { - _to_skip--; - return 1; - } else if (_to_write > 0) { - _to_write--; - _destination[_pos++] = c; - return 1; - } - return 0; - } - size_t write(const uint8_t *buffer, size_t size) - { - return this->Print::write(buffer, size); - } -}; - -class AsyncJsonResponse: public AsyncAbstractResponse { - protected: - -#ifdef ARDUINOJSON_5_COMPATIBILITY - DynamicJsonBuffer _jsonBuffer; -#else - DynamicJsonDocument _jsonBuffer; -#endif - - JsonVariant _root; - bool _isValid; - - public: - -#ifdef ARDUINOJSON_5_COMPATIBILITY - AsyncJsonResponse(bool isArray=false): _isValid{false} { - _code = 200; - _contentType = JSON_MIMETYPE; - if(isArray) - _root = _jsonBuffer.createArray(); - else - _root = _jsonBuffer.createObject(); - } -#else - AsyncJsonResponse(bool isArray=false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) : _jsonBuffer(maxJsonBufferSize), _isValid{false} { - _code = 200; - _contentType = JSON_MIMETYPE; - if(isArray) - _root = _jsonBuffer.createNestedArray(); - else - _root = _jsonBuffer.createNestedObject(); - } -#endif - - ~AsyncJsonResponse() {} - JsonVariant & getRoot() { return _root; } - bool _sourceValid() const { return _isValid; } - size_t setLength() { - -#ifdef ARDUINOJSON_5_COMPATIBILITY - _contentLength = _root.measureLength(); -#else - _contentLength = measureJson(_root); -#endif - - if (_contentLength) { _isValid = true; } - return _contentLength; - } - - size_t getSize() { return _jsonBuffer.size(); } - - size_t _fillBuffer(uint8_t *data, size_t len){ - ChunkPrint dest(data, _sentLength, len); - -#ifdef ARDUINOJSON_5_COMPATIBILITY - _root.printTo( dest ) ; -#else - serializeJson(_root, dest); -#endif - return len; - } -}; - -class PrettyAsyncJsonResponse: public AsyncJsonResponse { -public: -#ifdef ARDUINOJSON_5_COMPATIBILITY - PrettyAsyncJsonResponse (bool isArray=false) : AsyncJsonResponse{isArray} {} -#else - PrettyAsyncJsonResponse (bool isArray=false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) : AsyncJsonResponse{isArray, maxJsonBufferSize} {} -#endif - size_t setLength () { -#ifdef ARDUINOJSON_5_COMPATIBILITY - _contentLength = _root.measurePrettyLength (); -#else - _contentLength = measureJsonPretty(_root); -#endif - if (_contentLength) {_isValid = true;} - return _contentLength; - } - size_t _fillBuffer (uint8_t *data, size_t len) { - ChunkPrint dest (data, _sentLength, len); -#ifdef ARDUINOJSON_5_COMPATIBILITY - _root.prettyPrintTo (dest); -#else - serializeJsonPretty(_root, dest); -#endif - return len; - } -}; - -typedef std::function ArJsonRequestHandlerFunction; - -class AsyncCallbackJsonWebHandler: public AsyncWebHandler { -private: -protected: - const String _uri; - WebRequestMethodComposite _method; - ArJsonRequestHandlerFunction _onRequest; - size_t _contentLength; -#ifndef ARDUINOJSON_5_COMPATIBILITY - const size_t maxJsonBufferSize; -#endif - size_t _maxContentLength; -public: -#ifdef ARDUINOJSON_5_COMPATIBILITY - AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest) - : _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), _maxContentLength(16384) {} -#else - AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize=DYNAMIC_JSON_DOCUMENT_SIZE) - : _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), maxJsonBufferSize(maxJsonBufferSize), _maxContentLength(16384) {} -#endif - - void setMethod(WebRequestMethodComposite method){ _method = method; } - void setMaxContentLength(int maxContentLength){ _maxContentLength = maxContentLength; } - void onRequest(ArJsonRequestHandlerFunction fn){ _onRequest = fn; } - - virtual bool canHandle(AsyncWebServerRequest *request) override final{ - if(!_onRequest) - return false; - - if(!(_method & request->method())) - return false; - - if(_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri+"/"))) - return false; - - if ( !request->contentType().equalsIgnoreCase(JSON_MIMETYPE) ) - return false; - - request->addInterestingHeader("ANY"); - return true; - } - - virtual void handleRequest(AsyncWebServerRequest *request) override final { - if(_onRequest) { - if (request->_tempObject != NULL) { - -#ifdef ARDUINOJSON_5_COMPATIBILITY - DynamicJsonBuffer jsonBuffer; - JsonVariant json = jsonBuffer.parse((uint8_t*)(request->_tempObject)); - if (json.success()) { -#else - DynamicJsonDocument jsonBuffer(this->maxJsonBufferSize); - DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject)); - if(!error) { - JsonVariant json = jsonBuffer.as(); -#endif - - _onRequest(request, json); - return; - } - } - request->send(_contentLength > _maxContentLength ? 413 : 400); - } else { - request->send(500); - } - } - virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final { - } - virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final { - if (_onRequest) { - _contentLength = total; - if (total > 0 && request->_tempObject == NULL && total < _maxContentLength) { - request->_tempObject = malloc(total); - } - if (request->_tempObject != NULL) { - memcpy((uint8_t*)(request->_tempObject) + index, data, len); - } - } - } - virtual bool isRequestHandlerTrivial() override final {return _onRequest ? false : true;} -}; -#endif diff --git a/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.cpp b/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.cpp deleted file mode 100644 index df0d668a9..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.cpp +++ /dev/null @@ -1,1294 +0,0 @@ -/* - Asynchronous WebServer library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#include "Arduino.h" -#include "AsyncWebSocket.h" - -#include - -#ifndef ESP8266 -#include "mbedtls/sha1.h" -#else -#include -#endif - -#define MAX_PRINTF_LEN 64 - -size_t webSocketSendFrameWindow(AsyncClient *client){ - if(!client->canSend()) - return 0; - size_t space = client->space(); - if(space < 9) - return 0; - return space - 8; -} - -size_t webSocketSendFrame(AsyncClient *client, bool final, uint8_t opcode, bool mask, uint8_t *data, size_t len){ - if(!client->canSend()) - return 0; - size_t space = client->space(); - if(space < 2) - return 0; - uint8_t mbuf[4] = {0,0,0,0}; - uint8_t headLen = 2; - if(len && mask){ - headLen += 4; - mbuf[0] = rand() % 0xFF; - mbuf[1] = rand() % 0xFF; - mbuf[2] = rand() % 0xFF; - mbuf[3] = rand() % 0xFF; - } - if(len > 125) - headLen += 2; - if(space < headLen) - return 0; - space -= headLen; - - if(len > space) len = space; - - uint8_t *buf = (uint8_t*)malloc(headLen); - if(buf == NULL){ - //os_printf("could not malloc %u bytes for frame header\n", headLen); - return 0; - } - - buf[0] = opcode & 0x0F; - if(final) - buf[0] |= 0x80; - if(len < 126) - buf[1] = len & 0x7F; - else { - buf[1] = 126; - buf[2] = (uint8_t)((len >> 8) & 0xFF); - buf[3] = (uint8_t)(len & 0xFF); - } - if(len && mask){ - buf[1] |= 0x80; - memcpy(buf + (headLen - 4), mbuf, 4); - } - if(client->add((const char *)buf, headLen) != headLen){ - //os_printf("error adding %lu header bytes\n", headLen); - free(buf); - return 0; - } - free(buf); - - if(len){ - if(len && mask){ - size_t i; - for(i=0;iadd((const char *)data, len) != len){ - //os_printf("error adding %lu data bytes\n", len); - return 0; - } - } - if(!client->send()){ - //os_printf("error sending frame: %lu\n", headLen+len); - return 0; - } - return len; -} - - -/* - * AsyncWebSocketMessageBuffer - */ - - - -AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer() - :_data(nullptr) - ,_len(0) - ,_lock(false) - ,_count(0) -{ - -} - -AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(uint8_t * data, size_t size) - :_data(nullptr) - ,_len(size) - ,_lock(false) - ,_count(0) -{ - - if (!data) { - return; - } - - _data = new uint8_t[_len + 1]; - - if (_data) { - memcpy(_data, data, _len); - _data[_len] = 0; - } -} - - -AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(size_t size) - :_data(nullptr) - ,_len(size) - ,_lock(false) - ,_count(0) -{ - _data = new uint8_t[_len + 1]; - - if (_data) { - _data[_len] = 0; - } - -} - -AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(const AsyncWebSocketMessageBuffer & copy) - :_data(nullptr) - ,_len(0) - ,_lock(false) - ,_count(0) -{ - _len = copy._len; - _lock = copy._lock; - _count = 0; - - if (_len) { - _data = new uint8_t[_len + 1]; - _data[_len] = 0; - } - - if (_data) { - memcpy(_data, copy._data, _len); - _data[_len] = 0; - } - -} - -AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(AsyncWebSocketMessageBuffer && copy) - :_data(nullptr) - ,_len(0) - ,_lock(false) - ,_count(0) -{ - _len = copy._len; - _lock = copy._lock; - _count = 0; - - if (copy._data) { - _data = copy._data; - copy._data = nullptr; - } - -} - -AsyncWebSocketMessageBuffer::~AsyncWebSocketMessageBuffer() -{ - if (_data) { - delete[] _data; - } -} - -bool AsyncWebSocketMessageBuffer::reserve(size_t size) -{ - _len = size; - - if (_data) { - delete[] _data; - _data = nullptr; - } - - _data = new uint8_t[_len + 1]; - - if (_data) { - _data[_len] = 0; - return true; - } else { - return false; - } - -} - - - -/* - * Control Frame - */ - -class AsyncWebSocketControl { - private: - uint8_t _opcode; - uint8_t *_data; - size_t _len; - bool _mask; - bool _finished; - public: - AsyncWebSocketControl(uint8_t opcode, uint8_t *data=NULL, size_t len=0, bool mask=false) - :_opcode(opcode) - ,_len(len) - ,_mask(len && mask) - ,_finished(false) - { - if(data == NULL) - _len = 0; - if(_len){ - if(_len > 125) - _len = 125; - _data = (uint8_t*)malloc(_len); - if(_data == NULL) - _len = 0; - else memcpy(_data, data, len); - } else _data = NULL; - } - virtual ~AsyncWebSocketControl(){ - if(_data != NULL) - free(_data); - } - virtual bool finished() const { return _finished; } - uint8_t opcode(){ return _opcode; } - uint8_t len(){ return _len + 2; } - size_t send(AsyncClient *client){ - _finished = true; - return webSocketSendFrame(client, true, _opcode & 0x0F, _mask, _data, _len); - } -}; - -/* - * Basic Buffered Message - */ - - -AsyncWebSocketBasicMessage::AsyncWebSocketBasicMessage(const char * data, size_t len, uint8_t opcode, bool mask) - :_len(len) - ,_sent(0) - ,_ack(0) - ,_acked(0) -{ - _opcode = opcode & 0x07; - _mask = mask; - _data = (uint8_t*)malloc(_len+1); - if(_data == NULL){ - _len = 0; - _status = WS_MSG_ERROR; - } else { - _status = WS_MSG_SENDING; - memcpy(_data, data, _len); - _data[_len] = 0; - } -} -AsyncWebSocketBasicMessage::AsyncWebSocketBasicMessage(uint8_t opcode, bool mask) - :_len(0) - ,_sent(0) - ,_ack(0) - ,_acked(0) - ,_data(NULL) -{ - _opcode = opcode & 0x07; - _mask = mask; - -} - - -AsyncWebSocketBasicMessage::~AsyncWebSocketBasicMessage() { - if(_data != NULL) - free(_data); -} - - void AsyncWebSocketBasicMessage::ack(size_t len, uint32_t time) { - (void)time; - _acked += len; - if(_sent == _len && _acked == _ack){ - _status = WS_MSG_SENT; - } -} - size_t AsyncWebSocketBasicMessage::send(AsyncClient *client) { - if(_status != WS_MSG_SENDING) - return 0; - if(_acked < _ack){ - return 0; - } - if(_sent == _len){ - if(_acked == _ack) - _status = WS_MSG_SENT; - return 0; - } - if(_sent > _len){ - _status = WS_MSG_ERROR; - return 0; - } - - size_t toSend = _len - _sent; - size_t window = webSocketSendFrameWindow(client); - - if(window < toSend) { - toSend = window; - } - - _sent += toSend; - _ack += toSend + ((toSend < 126)?2:4) + (_mask * 4); - - bool final = (_sent == _len); - uint8_t* dPtr = (uint8_t*)(_data + (_sent - toSend)); - uint8_t opCode = (toSend && _sent == toSend)?_opcode:(uint8_t)WS_CONTINUATION; - - size_t sent = webSocketSendFrame(client, final, opCode, _mask, dPtr, toSend); - _status = WS_MSG_SENDING; - if(toSend && sent != toSend){ - _sent -= (toSend - sent); - _ack -= (toSend - sent); - } - return sent; -} - -// bool AsyncWebSocketBasicMessage::reserve(size_t size) { -// if (size) { -// _data = (uint8_t*)malloc(size +1); -// if (_data) { -// memset(_data, 0, size); -// _len = size; -// _status = WS_MSG_SENDING; -// return true; -// } -// } -// return false; -// } - - -/* - * AsyncWebSocketMultiMessage Message - */ - - -AsyncWebSocketMultiMessage::AsyncWebSocketMultiMessage(AsyncWebSocketMessageBuffer * buffer, uint8_t opcode, bool mask) - :_len(0) - ,_sent(0) - ,_ack(0) - ,_acked(0) - ,_WSbuffer(nullptr) -{ - - _opcode = opcode & 0x07; - _mask = mask; - - if (buffer) { - _WSbuffer = buffer; - (*_WSbuffer)++; - _data = buffer->get(); - _len = buffer->length(); - _status = WS_MSG_SENDING; - //ets_printf("M: %u\n", _len); - } else { - _status = WS_MSG_ERROR; - } - -} - - -AsyncWebSocketMultiMessage::~AsyncWebSocketMultiMessage() { - if (_WSbuffer) { - (*_WSbuffer)--; // decreases the counter. - } -} - - void AsyncWebSocketMultiMessage::ack(size_t len, uint32_t time) { - (void)time; - _acked += len; - if(_sent >= _len && _acked >= _ack){ - _status = WS_MSG_SENT; - } - //ets_printf("A: %u\n", len); -} - size_t AsyncWebSocketMultiMessage::send(AsyncClient *client) { - if(_status != WS_MSG_SENDING) - return 0; - if(_acked < _ack){ - return 0; - } - if(_sent == _len){ - _status = WS_MSG_SENT; - return 0; - } - if(_sent > _len){ - _status = WS_MSG_ERROR; - //ets_printf("E: %u > %u\n", _sent, _len); - return 0; - } - - size_t toSend = _len - _sent; - size_t window = webSocketSendFrameWindow(client); - - if(window < toSend) { - toSend = window; - } - - _sent += toSend; - _ack += toSend + ((toSend < 126)?2:4) + (_mask * 4); - - //ets_printf("W: %u %u\n", _sent - toSend, toSend); - - bool final = (_sent == _len); - uint8_t* dPtr = (uint8_t*)(_data + (_sent - toSend)); - uint8_t opCode = (toSend && _sent == toSend)?_opcode:(uint8_t)WS_CONTINUATION; - - size_t sent = webSocketSendFrame(client, final, opCode, _mask, dPtr, toSend); - _status = WS_MSG_SENDING; - if(toSend && sent != toSend){ - //ets_printf("E: %u != %u\n", toSend, sent); - _sent -= (toSend - sent); - _ack -= (toSend - sent); - } - //ets_printf("S: %u %u\n", _sent, sent); - return sent; -} - - -/* - * Async WebSocket Client - */ - const char * AWSC_PING_PAYLOAD = "ESPAsyncWebServer-PING"; - const size_t AWSC_PING_PAYLOAD_LEN = 22; - -AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server) - : _controlQueue(AsyncLinkedList([](AsyncWebSocketControl *c){ delete c; })) - , _messageQueue(AsyncLinkedList([](AsyncWebSocketMessage *m){ delete m; })) - , _tempObject(NULL) -{ - _client = request->client(); - _server = server; - _clientId = _server->_getNextId(); - _status = WS_CONNECTED; - _pstate = 0; - _lastMessageTime = millis(); - _keepAlivePeriod = 0; - _client->setRxTimeout(0); - _client->onError([](void *r, AsyncClient* c, int8_t error){ (void)c; ((AsyncWebSocketClient*)(r))->_onError(error); }, this); - _client->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ (void)c; ((AsyncWebSocketClient*)(r))->_onAck(len, time); }, this); - _client->onDisconnect([](void *r, AsyncClient* c){ ((AsyncWebSocketClient*)(r))->_onDisconnect(); delete c; }, this); - _client->onTimeout([](void *r, AsyncClient* c, uint32_t time){ (void)c; ((AsyncWebSocketClient*)(r))->_onTimeout(time); }, this); - _client->onData([](void *r, AsyncClient* c, void *buf, size_t len){ (void)c; ((AsyncWebSocketClient*)(r))->_onData(buf, len); }, this); - _client->onPoll([](void *r, AsyncClient* c){ (void)c; ((AsyncWebSocketClient*)(r))->_onPoll(); }, this); - _server->_addClient(this); - _server->_handleEvent(this, WS_EVT_CONNECT, request, NULL, 0); - delete request; -} - -AsyncWebSocketClient::~AsyncWebSocketClient(){ - _messageQueue.free(); - _controlQueue.free(); - _server->_handleEvent(this, WS_EVT_DISCONNECT, NULL, NULL, 0); -} - -void AsyncWebSocketClient::_onAck(size_t len, uint32_t time){ - _lastMessageTime = millis(); - if(!_controlQueue.isEmpty()){ - auto head = _controlQueue.front(); - if(head->finished()){ - len -= head->len(); - if(_status == WS_DISCONNECTING && head->opcode() == WS_DISCONNECT){ - _controlQueue.remove(head); - _status = WS_DISCONNECTED; - _client->close(true); - return; - } - _controlQueue.remove(head); - } - } - if(len && !_messageQueue.isEmpty()){ - _messageQueue.front()->ack(len, time); - } - _server->_cleanBuffers(); - _runQueue(); -} - -void AsyncWebSocketClient::_onPoll(){ - if(_client->canSend() && (!_controlQueue.isEmpty() || !_messageQueue.isEmpty())){ - _runQueue(); - } else if(_keepAlivePeriod > 0 && _controlQueue.isEmpty() && _messageQueue.isEmpty() && (millis() - _lastMessageTime) >= _keepAlivePeriod){ - ping((uint8_t *)AWSC_PING_PAYLOAD, AWSC_PING_PAYLOAD_LEN); - } -} - -void AsyncWebSocketClient::_runQueue(){ - while(!_messageQueue.isEmpty() && _messageQueue.front()->finished()){ - _messageQueue.remove(_messageQueue.front()); - } - - if(!_controlQueue.isEmpty() && (_messageQueue.isEmpty() || _messageQueue.front()->betweenFrames()) && webSocketSendFrameWindow(_client) > (size_t)(_controlQueue.front()->len() - 1)){ - _controlQueue.front()->send(_client); - } else if(!_messageQueue.isEmpty() && _messageQueue.front()->betweenFrames() && webSocketSendFrameWindow(_client)){ - _messageQueue.front()->send(_client); - } -} - -bool AsyncWebSocketClient::queueIsFull(){ - if((_messageQueue.length() >= WS_MAX_QUEUED_MESSAGES) || (_status != WS_CONNECTED) ) return true; - return false; -} - -void AsyncWebSocketClient::_queueMessage(AsyncWebSocketMessage *dataMessage){ - if(dataMessage == NULL) - return; - if(_status != WS_CONNECTED){ - delete dataMessage; - return; - } - if(_messageQueue.length() >= WS_MAX_QUEUED_MESSAGES){ - ets_printf("ERROR: Too many messages queued\n"); - delete dataMessage; - } else { - _messageQueue.add(dataMessage); - } - if(_client->canSend()) - _runQueue(); -} - -void AsyncWebSocketClient::_queueControl(AsyncWebSocketControl *controlMessage){ - if(controlMessage == NULL) - return; - _controlQueue.add(controlMessage); - if(_client->canSend()) - _runQueue(); -} - -void AsyncWebSocketClient::close(uint16_t code, const char * message){ - if(_status != WS_CONNECTED) - return; - if(code){ - uint8_t packetLen = 2; - if(message != NULL){ - size_t mlen = strlen(message); - if(mlen > 123) mlen = 123; - packetLen += mlen; - } - char * buf = (char*)malloc(packetLen); - if(buf != NULL){ - buf[0] = (uint8_t)(code >> 8); - buf[1] = (uint8_t)(code & 0xFF); - if(message != NULL){ - memcpy(buf+2, message, packetLen -2); - } - _queueControl(new AsyncWebSocketControl(WS_DISCONNECT,(uint8_t*)buf,packetLen)); - free(buf); - return; - } - } - _queueControl(new AsyncWebSocketControl(WS_DISCONNECT)); -} - -void AsyncWebSocketClient::ping(uint8_t *data, size_t len){ - if(_status == WS_CONNECTED) - _queueControl(new AsyncWebSocketControl(WS_PING, data, len)); -} - -void AsyncWebSocketClient::_onError(int8_t){} - -void AsyncWebSocketClient::_onTimeout(uint32_t time){ - (void)time; - _client->close(true); -} - -void AsyncWebSocketClient::_onDisconnect(){ - _client = NULL; - _server->_handleDisconnect(this); -} - -void AsyncWebSocketClient::_onData(void *pbuf, size_t plen){ - _lastMessageTime = millis(); - uint8_t *data = (uint8_t*)pbuf; - while(plen > 0){ - if(!_pstate){ - const uint8_t *fdata = data; - _pinfo.index = 0; - _pinfo.final = (fdata[0] & 0x80) != 0; - _pinfo.opcode = fdata[0] & 0x0F; - _pinfo.masked = (fdata[1] & 0x80) != 0; - _pinfo.len = fdata[1] & 0x7F; - data += 2; - plen -= 2; - if(_pinfo.len == 126){ - _pinfo.len = fdata[3] | (uint16_t)(fdata[2]) << 8; - data += 2; - plen -= 2; - } else if(_pinfo.len == 127){ - _pinfo.len = fdata[9] | (uint16_t)(fdata[8]) << 8 | (uint32_t)(fdata[7]) << 16 | (uint32_t)(fdata[6]) << 24 | (uint64_t)(fdata[5]) << 32 | (uint64_t)(fdata[4]) << 40 | (uint64_t)(fdata[3]) << 48 | (uint64_t)(fdata[2]) << 56; - data += 8; - plen -= 8; - } - - if(_pinfo.masked){ - memcpy(_pinfo.mask, data, 4); - data += 4; - plen -= 4; - } - } - - const size_t datalen = std::min((size_t)(_pinfo.len - _pinfo.index), plen); - const auto datalast = data[datalen]; - - if(_pinfo.masked){ - for(size_t i=0;i_handleEvent(this, WS_EVT_DATA, (void *)&_pinfo, (uint8_t*)data, datalen); - - _pinfo.index += datalen; - } else if((datalen + _pinfo.index) == _pinfo.len){ - _pstate = 0; - if(_pinfo.opcode == WS_DISCONNECT){ - if(datalen){ - uint16_t reasonCode = (uint16_t)(data[0] << 8) + data[1]; - char * reasonString = (char*)(data+2); - if(reasonCode > 1001){ - _server->_handleEvent(this, WS_EVT_ERROR, (void *)&reasonCode, (uint8_t*)reasonString, strlen(reasonString)); - } - } - if(_status == WS_DISCONNECTING){ - _status = WS_DISCONNECTED; - _client->close(true); - } else { - _status = WS_DISCONNECTING; - _client->ackLater(); - _queueControl(new AsyncWebSocketControl(WS_DISCONNECT, data, datalen)); - } - } else if(_pinfo.opcode == WS_PING){ - _queueControl(new AsyncWebSocketControl(WS_PONG, data, datalen)); - } else if(_pinfo.opcode == WS_PONG){ - if(datalen != AWSC_PING_PAYLOAD_LEN || memcmp(AWSC_PING_PAYLOAD, data, AWSC_PING_PAYLOAD_LEN) != 0) - _server->_handleEvent(this, WS_EVT_PONG, NULL, data, datalen); - } else if(_pinfo.opcode < 8){//continuation or text/binary frame - _server->_handleEvent(this, WS_EVT_DATA, (void *)&_pinfo, data, datalen); - } - } else { - //os_printf("frame error: len: %u, index: %llu, total: %llu\n", datalen, _pinfo.index, _pinfo.len); - //what should we do? - break; - } - - // restore byte as _handleEvent may have added a null terminator i.e., data[len] = 0; - if (datalen > 0) - data[datalen] = datalast; - - data += datalen; - plen -= datalen; - } -} - -size_t AsyncWebSocketClient::printf(const char *format, ...) { - va_list arg; - va_start(arg, format); - char* temp = new char[MAX_PRINTF_LEN]; - if(!temp){ - va_end(arg); - return 0; - } - char* buffer = temp; - size_t len = vsnprintf(temp, MAX_PRINTF_LEN, format, arg); - va_end(arg); - - if (len > (MAX_PRINTF_LEN - 1)) { - buffer = new char[len + 1]; - if (!buffer) { - delete[] temp; - return 0; - } - va_start(arg, format); - vsnprintf(buffer, len + 1, format, arg); - va_end(arg); - } - text(buffer, len); - if (buffer != temp) { - delete[] buffer; - } - delete[] temp; - return len; -} - -#ifndef ESP32 -size_t AsyncWebSocketClient::printf_P(PGM_P formatP, ...) { - va_list arg; - va_start(arg, formatP); - char* temp = new char[MAX_PRINTF_LEN]; - if(!temp){ - va_end(arg); - return 0; - } - char* buffer = temp; - size_t len = vsnprintf_P(temp, MAX_PRINTF_LEN, formatP, arg); - va_end(arg); - - if (len > (MAX_PRINTF_LEN - 1)) { - buffer = new char[len + 1]; - if (!buffer) { - delete[] temp; - return 0; - } - va_start(arg, formatP); - vsnprintf_P(buffer, len + 1, formatP, arg); - va_end(arg); - } - text(buffer, len); - if (buffer != temp) { - delete[] buffer; - } - delete[] temp; - return len; -} -#endif - -void AsyncWebSocketClient::text(const char * message, size_t len){ - _queueMessage(new AsyncWebSocketBasicMessage(message, len)); -} -void AsyncWebSocketClient::text(const char * message){ - text(message, strlen(message)); -} -void AsyncWebSocketClient::text(uint8_t * message, size_t len){ - text((const char *)message, len); -} -void AsyncWebSocketClient::text(char * message){ - text(message, strlen(message)); -} -void AsyncWebSocketClient::text(const String &message){ - text(message.c_str(), message.length()); -} -void AsyncWebSocketClient::text(const __FlashStringHelper *data){ - PGM_P p = reinterpret_cast(data); - size_t n = 0; - while (1) { - if (pgm_read_byte(p+n) == 0) break; - n += 1; - } - char * message = (char*) malloc(n+1); - if(message){ - for(size_t b=0; b(data); - char * message = (char*) malloc(len); - if(message){ - for(size_t b=0; bremoteIP(); -} - -uint16_t AsyncWebSocketClient::remotePort() { - if(!_client) { - return 0; - } - return _client->remotePort(); -} - - - -/* - * Async Web Socket - Each separate socket location - */ - -AsyncWebSocket::AsyncWebSocket(const String& url) - :_url(url) - ,_clients(AsyncLinkedList([](AsyncWebSocketClient *c){ delete c; })) - ,_cNextId(1) - ,_enabled(true) - ,_buffers(AsyncLinkedList([](AsyncWebSocketMessageBuffer *b){ delete b; })) -{ - _eventHandler = NULL; -} - -AsyncWebSocket::~AsyncWebSocket(){} - -void AsyncWebSocket::_handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){ - if(_eventHandler != NULL){ - _eventHandler(this, client, type, arg, data, len); - } -} - -void AsyncWebSocket::_addClient(AsyncWebSocketClient * client){ - _clients.add(client); -} - -void AsyncWebSocket::_handleDisconnect(AsyncWebSocketClient * client){ - - _clients.remove_first([=](AsyncWebSocketClient * c){ - return c->id() == client->id(); - }); -} - -bool AsyncWebSocket::availableForWriteAll(){ - for(const auto& c: _clients){ - if(c->queueIsFull()) return false; - } - return true; -} - -bool AsyncWebSocket::availableForWrite(uint32_t id){ - for(const auto& c: _clients){ - if(c->queueIsFull() && (c->id() == id )) return false; - } - return true; -} - -size_t AsyncWebSocket::count() const { - return _clients.count_if([](AsyncWebSocketClient * c){ - return c->status() == WS_CONNECTED; - }); -} - -AsyncWebSocketClient * AsyncWebSocket::client(uint32_t id){ - for(const auto &c: _clients){ - if(c->id() == id && c->status() == WS_CONNECTED){ - return c; - } - } - return nullptr; -} - - -void AsyncWebSocket::close(uint32_t id, uint16_t code, const char * message){ - AsyncWebSocketClient * c = client(id); - if(c) - c->close(code, message); -} - -void AsyncWebSocket::closeAll(uint16_t code, const char * message){ - for(const auto& c: _clients){ - if(c->status() == WS_CONNECTED) - c->close(code, message); - } -} - -void AsyncWebSocket::cleanupClients(uint16_t maxClients) -{ - if (count() > maxClients){ - _clients.front()->close(); - } -} - -void AsyncWebSocket::ping(uint32_t id, uint8_t *data, size_t len){ - AsyncWebSocketClient * c = client(id); - if(c) - c->ping(data, len); -} - -void AsyncWebSocket::pingAll(uint8_t *data, size_t len){ - for(const auto& c: _clients){ - if(c->status() == WS_CONNECTED) - c->ping(data, len); - } -} - -void AsyncWebSocket::text(uint32_t id, const char * message, size_t len){ - AsyncWebSocketClient * c = client(id); - if(c) - c->text(message, len); -} - -void AsyncWebSocket::textAll(AsyncWebSocketMessageBuffer * buffer){ - if (!buffer) return; - buffer->lock(); - for(const auto& c: _clients){ - if(c->status() == WS_CONNECTED){ - c->text(buffer); - } - } - buffer->unlock(); - _cleanBuffers(); -} - - -void AsyncWebSocket::textAll(const char * message, size_t len){ - AsyncWebSocketMessageBuffer * WSBuffer = makeBuffer((uint8_t *)message, len); - textAll(WSBuffer); -} - -void AsyncWebSocket::binary(uint32_t id, const char * message, size_t len){ - AsyncWebSocketClient * c = client(id); - if(c) - c->binary(message, len); -} - -void AsyncWebSocket::binaryAll(const char * message, size_t len){ - AsyncWebSocketMessageBuffer * buffer = makeBuffer((uint8_t *)message, len); - binaryAll(buffer); -} - -void AsyncWebSocket::binaryAll(AsyncWebSocketMessageBuffer * buffer) -{ - if (!buffer) return; - buffer->lock(); - for(const auto& c: _clients){ - if(c->status() == WS_CONNECTED) - c->binary(buffer); - } - buffer->unlock(); - _cleanBuffers(); -} - -void AsyncWebSocket::message(uint32_t id, AsyncWebSocketMessage *message){ - AsyncWebSocketClient * c = client(id); - if(c) - c->message(message); -} - -void AsyncWebSocket::messageAll(AsyncWebSocketMultiMessage *message){ - for(const auto& c: _clients){ - if(c->status() == WS_CONNECTED) - c->message(message); - } - _cleanBuffers(); -} - -size_t AsyncWebSocket::printf(uint32_t id, const char *format, ...){ - AsyncWebSocketClient * c = client(id); - if(c){ - va_list arg; - va_start(arg, format); - size_t len = c->printf(format, arg); - va_end(arg); - return len; - } - return 0; -} - -size_t AsyncWebSocket::printfAll(const char *format, ...) { - va_list arg; - char* temp = new char[MAX_PRINTF_LEN]; - if(!temp){ - return 0; - } - va_start(arg, format); - size_t len = vsnprintf(temp, MAX_PRINTF_LEN, format, arg); - va_end(arg); - delete[] temp; - - AsyncWebSocketMessageBuffer * buffer = makeBuffer(len); - if (!buffer) { - return 0; - } - - va_start(arg, format); - vsnprintf( (char *)buffer->get(), len + 1, format, arg); - va_end(arg); - - textAll(buffer); - return len; -} - -#ifndef ESP32 -size_t AsyncWebSocket::printf_P(uint32_t id, PGM_P formatP, ...){ - AsyncWebSocketClient * c = client(id); - if(c != NULL){ - va_list arg; - va_start(arg, formatP); - size_t len = c->printf_P(formatP, arg); - va_end(arg); - return len; - } - return 0; -} -#endif - -size_t AsyncWebSocket::printfAll_P(PGM_P formatP, ...) { - va_list arg; - char* temp = new char[MAX_PRINTF_LEN]; - if(!temp){ - return 0; - } - va_start(arg, formatP); - size_t len = vsnprintf_P(temp, MAX_PRINTF_LEN, formatP, arg); - va_end(arg); - delete[] temp; - - AsyncWebSocketMessageBuffer * buffer = makeBuffer(len + 1); - if (!buffer) { - return 0; - } - - va_start(arg, formatP); - vsnprintf_P((char *)buffer->get(), len + 1, formatP, arg); - va_end(arg); - - textAll(buffer); - return len; -} - -void AsyncWebSocket::text(uint32_t id, const char * message){ - text(id, message, strlen(message)); -} -void AsyncWebSocket::text(uint32_t id, uint8_t * message, size_t len){ - text(id, (const char *)message, len); -} -void AsyncWebSocket::text(uint32_t id, char * message){ - text(id, message, strlen(message)); -} -void AsyncWebSocket::text(uint32_t id, const String &message){ - text(id, message.c_str(), message.length()); -} -void AsyncWebSocket::text(uint32_t id, const __FlashStringHelper *message){ - AsyncWebSocketClient * c = client(id); - if(c != NULL) - c->text(message); -} -void AsyncWebSocket::textAll(const char * message){ - textAll(message, strlen(message)); -} -void AsyncWebSocket::textAll(uint8_t * message, size_t len){ - textAll((const char *)message, len); -} -void AsyncWebSocket::textAll(char * message){ - textAll(message, strlen(message)); -} -void AsyncWebSocket::textAll(const String &message){ - textAll(message.c_str(), message.length()); -} -void AsyncWebSocket::textAll(const __FlashStringHelper *message){ - for(const auto& c: _clients){ - if(c->status() == WS_CONNECTED) - c->text(message); - } -} -void AsyncWebSocket::binary(uint32_t id, const char * message){ - binary(id, message, strlen(message)); -} -void AsyncWebSocket::binary(uint32_t id, uint8_t * message, size_t len){ - binary(id, (const char *)message, len); -} -void AsyncWebSocket::binary(uint32_t id, char * message){ - binary(id, message, strlen(message)); -} -void AsyncWebSocket::binary(uint32_t id, const String &message){ - binary(id, message.c_str(), message.length()); -} -void AsyncWebSocket::binary(uint32_t id, const __FlashStringHelper *message, size_t len){ - AsyncWebSocketClient * c = client(id); - if(c != NULL) - c-> binary(message, len); -} -void AsyncWebSocket::binaryAll(const char * message){ - binaryAll(message, strlen(message)); -} -void AsyncWebSocket::binaryAll(uint8_t * message, size_t len){ - binaryAll((const char *)message, len); -} -void AsyncWebSocket::binaryAll(char * message){ - binaryAll(message, strlen(message)); -} -void AsyncWebSocket::binaryAll(const String &message){ - binaryAll(message.c_str(), message.length()); -} -void AsyncWebSocket::binaryAll(const __FlashStringHelper *message, size_t len){ - for(const auto& c: _clients){ - if(c->status() == WS_CONNECTED) - c-> binary(message, len); - } - } - -const char * WS_STR_CONNECTION = "Connection"; -const char * WS_STR_UPGRADE = "Upgrade"; -const char * WS_STR_ORIGIN = "Origin"; -const char * WS_STR_VERSION = "Sec-WebSocket-Version"; -const char * WS_STR_KEY = "Sec-WebSocket-Key"; -const char * WS_STR_PROTOCOL = "Sec-WebSocket-Protocol"; -const char * WS_STR_ACCEPT = "Sec-WebSocket-Accept"; -const char * WS_STR_UUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - -bool AsyncWebSocket::canHandle(AsyncWebServerRequest *request){ - if(!_enabled) - return false; - - if(request->method() != HTTP_GET || !request->url().equals(_url) || !request->isExpectedRequestedConnType(RCT_WS)) - return false; - - request->addInterestingHeader(WS_STR_CONNECTION); - request->addInterestingHeader(WS_STR_UPGRADE); - request->addInterestingHeader(WS_STR_ORIGIN); - request->addInterestingHeader(WS_STR_VERSION); - request->addInterestingHeader(WS_STR_KEY); - request->addInterestingHeader(WS_STR_PROTOCOL); - return true; -} - -void AsyncWebSocket::handleRequest(AsyncWebServerRequest *request){ - if(!request->hasHeader(WS_STR_VERSION) || !request->hasHeader(WS_STR_KEY)){ - request->send(400); - return; - } - if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str())){ - return request->requestAuthentication(); - } - AsyncWebHeader* version = request->getHeader(WS_STR_VERSION); - if(version->value().toInt() != 13){ - AsyncWebServerResponse *response = request->beginResponse(400); - response->addHeader(WS_STR_VERSION,"13"); - request->send(response); - return; - } - AsyncWebHeader* key = request->getHeader(WS_STR_KEY); - AsyncWebServerResponse *response = new AsyncWebSocketResponse(key->value(), this); - if(request->hasHeader(WS_STR_PROTOCOL)){ - AsyncWebHeader* protocol = request->getHeader(WS_STR_PROTOCOL); - //ToDo: check protocol - response->addHeader(WS_STR_PROTOCOL, protocol->value()); - } - request->send(response); -} - -AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(size_t size) -{ - AsyncWebSocketMessageBuffer * buffer = new AsyncWebSocketMessageBuffer(size); - if (buffer) { - AsyncWebLockGuard l(_lock); - _buffers.add(buffer); - } - return buffer; -} - -AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(uint8_t * data, size_t size) -{ - AsyncWebSocketMessageBuffer * buffer = new AsyncWebSocketMessageBuffer(data, size); - - if (buffer) { - AsyncWebLockGuard l(_lock); - _buffers.add(buffer); - } - - return buffer; -} - -void AsyncWebSocket::_cleanBuffers() -{ - AsyncWebLockGuard l(_lock); - - for(AsyncWebSocketMessageBuffer * c: _buffers){ - if(c && c->canDelete()){ - _buffers.remove(c); - } - } -} - -AsyncWebSocket::AsyncWebSocketClientAsyncLinkedList AsyncWebSocket::getClients() const { - return _clients; -} - -/* - * Response to Web Socket request - sends the authorization and detaches the TCP Client from the web server - * Authentication code from https://github.com/Links2004/arduinoWebSockets/blob/master/src/WebSockets.cpp#L480 - */ - -AsyncWebSocketResponse::AsyncWebSocketResponse(const String& key, AsyncWebSocket *server){ - _server = server; - _code = 101; - _sendContentLength = false; - - uint8_t * hash = (uint8_t*)malloc(20); - if(hash == NULL){ - _state = RESPONSE_FAILED; - return; - } - char * buffer = (char *) malloc(33); - if(buffer == NULL){ - free(hash); - _state = RESPONSE_FAILED; - return; - } -#ifdef ESP8266 - sha1(key + WS_STR_UUID, hash); -#else - (String&)key += WS_STR_UUID; - mbedtls_sha1_context ctx; - mbedtls_sha1_init(&ctx); - mbedtls_sha1_starts_ret(&ctx); - mbedtls_sha1_update_ret(&ctx, (const unsigned char*)key.c_str(), key.length()); - mbedtls_sha1_finish_ret(&ctx, hash); - mbedtls_sha1_free(&ctx); -#endif - base64_encodestate _state; - base64_init_encodestate(&_state); - int len = base64_encode_block((const char *) hash, 20, buffer, &_state); - len = base64_encode_blockend((buffer + len), &_state); - addHeader(WS_STR_CONNECTION, WS_STR_UPGRADE); - addHeader(WS_STR_UPGRADE, "websocket"); - addHeader(WS_STR_ACCEPT,buffer); - free(buffer); - free(hash); -} - -void AsyncWebSocketResponse::_respond(AsyncWebServerRequest *request){ - if(_state == RESPONSE_FAILED){ - request->client()->close(true); - return; - } - String out = _assembleHead(request->version()); - request->client()->write(out.c_str(), _headLength); - _state = RESPONSE_WAIT_ACK; -} - -size_t AsyncWebSocketResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){ - (void)time; - if(len){ - new AsyncWebSocketClient(request, _server); - } - return 0; -} diff --git a/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.h b/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.h deleted file mode 100644 index 7fb1e92de..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSocket.h +++ /dev/null @@ -1,350 +0,0 @@ -/* - Asynchronous WebServer library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#ifndef ASYNCWEBSOCKET_H_ -#define ASYNCWEBSOCKET_H_ - -#include -#ifdef ESP32 -#include -#define WS_MAX_QUEUED_MESSAGES 32 -#else -#include -#define WS_MAX_QUEUED_MESSAGES 8 -#endif -#include - -#include "AsyncWebSynchronization.h" - -#ifdef ESP8266 -#include -#ifdef CRYPTO_HASH_h // include Hash.h from espressif framework if the first include was from the crypto library -#include <../src/Hash.h> -#endif -#endif - -#ifdef ESP32 -#define DEFAULT_MAX_WS_CLIENTS 8 -#else -#define DEFAULT_MAX_WS_CLIENTS 4 -#endif - -class AsyncWebSocket; -class AsyncWebSocketResponse; -class AsyncWebSocketClient; -class AsyncWebSocketControl; - -typedef struct { - /** Message type as defined by enum AwsFrameType. - * Note: Applications will only see WS_TEXT and WS_BINARY. - * All other types are handled by the library. */ - uint8_t message_opcode; - /** Frame number of a fragmented message. */ - uint32_t num; - /** Is this the last frame in a fragmented message ?*/ - uint8_t final; - /** Is this frame masked? */ - uint8_t masked; - /** Message type as defined by enum AwsFrameType. - * This value is the same as message_opcode for non-fragmented - * messages, but may also be WS_CONTINUATION in a fragmented message. */ - uint8_t opcode; - /** Length of the current frame. - * This equals the total length of the message if num == 0 && final == true */ - uint64_t len; - /** Mask key */ - uint8_t mask[4]; - /** Offset of the data inside the current frame. */ - uint64_t index; -} AwsFrameInfo; - -typedef enum { WS_DISCONNECTED, WS_CONNECTED, WS_DISCONNECTING } AwsClientStatus; -typedef enum { WS_CONTINUATION, WS_TEXT, WS_BINARY, WS_DISCONNECT = 0x08, WS_PING, WS_PONG } AwsFrameType; -typedef enum { WS_MSG_SENDING, WS_MSG_SENT, WS_MSG_ERROR } AwsMessageStatus; -typedef enum { WS_EVT_CONNECT, WS_EVT_DISCONNECT, WS_EVT_PONG, WS_EVT_ERROR, WS_EVT_DATA } AwsEventType; - -class AsyncWebSocketMessageBuffer { - private: - uint8_t * _data; - size_t _len; - bool _lock; - uint32_t _count; - - public: - AsyncWebSocketMessageBuffer(); - AsyncWebSocketMessageBuffer(size_t size); - AsyncWebSocketMessageBuffer(uint8_t * data, size_t size); - AsyncWebSocketMessageBuffer(const AsyncWebSocketMessageBuffer &); - AsyncWebSocketMessageBuffer(AsyncWebSocketMessageBuffer &&); - ~AsyncWebSocketMessageBuffer(); - void operator ++(int i) { (void)i; _count++; } - void operator --(int i) { (void)i; if (_count > 0) { _count--; } ; } - bool reserve(size_t size); - void lock() { _lock = true; } - void unlock() { _lock = false; } - uint8_t * get() { return _data; } - size_t length() { return _len; } - uint32_t count() { return _count; } - bool canDelete() { return (!_count && !_lock); } - - friend AsyncWebSocket; - -}; - -class AsyncWebSocketMessage { - protected: - uint8_t _opcode; - bool _mask; - AwsMessageStatus _status; - public: - AsyncWebSocketMessage():_opcode(WS_TEXT),_mask(false),_status(WS_MSG_ERROR){} - virtual ~AsyncWebSocketMessage(){} - virtual void ack(size_t len __attribute__((unused)), uint32_t time __attribute__((unused))){} - virtual size_t send(AsyncClient *client __attribute__((unused))){ return 0; } - virtual bool finished(){ return _status != WS_MSG_SENDING; } - virtual bool betweenFrames() const { return false; } -}; - -class AsyncWebSocketBasicMessage: public AsyncWebSocketMessage { - private: - size_t _len; - size_t _sent; - size_t _ack; - size_t _acked; - uint8_t * _data; -public: - AsyncWebSocketBasicMessage(const char * data, size_t len, uint8_t opcode=WS_TEXT, bool mask=false); - AsyncWebSocketBasicMessage(uint8_t opcode=WS_TEXT, bool mask=false); - virtual ~AsyncWebSocketBasicMessage() override; - virtual bool betweenFrames() const override { return _acked == _ack; } - virtual void ack(size_t len, uint32_t time) override ; - virtual size_t send(AsyncClient *client) override ; -}; - -class AsyncWebSocketMultiMessage: public AsyncWebSocketMessage { - private: - uint8_t * _data; - size_t _len; - size_t _sent; - size_t _ack; - size_t _acked; - AsyncWebSocketMessageBuffer * _WSbuffer; -public: - AsyncWebSocketMultiMessage(AsyncWebSocketMessageBuffer * buffer, uint8_t opcode=WS_TEXT, bool mask=false); - virtual ~AsyncWebSocketMultiMessage() override; - virtual bool betweenFrames() const override { return _acked == _ack; } - virtual void ack(size_t len, uint32_t time) override ; - virtual size_t send(AsyncClient *client) override ; -}; - -class AsyncWebSocketClient { - private: - AsyncClient *_client; - AsyncWebSocket *_server; - uint32_t _clientId; - AwsClientStatus _status; - - AsyncLinkedList _controlQueue; - AsyncLinkedList _messageQueue; - - uint8_t _pstate; - AwsFrameInfo _pinfo; - - uint32_t _lastMessageTime; - uint32_t _keepAlivePeriod; - - void _queueMessage(AsyncWebSocketMessage *dataMessage); - void _queueControl(AsyncWebSocketControl *controlMessage); - void _runQueue(); - - public: - void *_tempObject; - - AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server); - ~AsyncWebSocketClient(); - - //client id increments for the given server - uint32_t id(){ return _clientId; } - AwsClientStatus status(){ return _status; } - AsyncClient* client(){ return _client; } - AsyncWebSocket *server(){ return _server; } - AwsFrameInfo const &pinfo() const { return _pinfo; } - - IPAddress remoteIP(); - uint16_t remotePort(); - - //control frames - void close(uint16_t code=0, const char * message=NULL); - void ping(uint8_t *data=NULL, size_t len=0); - - //set auto-ping period in seconds. disabled if zero (default) - void keepAlivePeriod(uint16_t seconds){ - _keepAlivePeriod = seconds * 1000; - } - uint16_t keepAlivePeriod(){ - return (uint16_t)(_keepAlivePeriod / 1000); - } - - //data packets - void message(AsyncWebSocketMessage *message){ _queueMessage(message); } - bool queueIsFull(); - - size_t printf(const char *format, ...) __attribute__ ((format (printf, 2, 3))); -#ifndef ESP32 - size_t printf_P(PGM_P formatP, ...) __attribute__ ((format (printf, 2, 3))); -#endif - void text(const char * message, size_t len); - void text(const char * message); - void text(uint8_t * message, size_t len); - void text(char * message); - void text(const String &message); - void text(const __FlashStringHelper *data); - void text(AsyncWebSocketMessageBuffer *buffer); - - void binary(const char * message, size_t len); - void binary(const char * message); - void binary(uint8_t * message, size_t len); - void binary(char * message); - void binary(const String &message); - void binary(const __FlashStringHelper *data, size_t len); - void binary(AsyncWebSocketMessageBuffer *buffer); - - bool canSend() { return _messageQueue.length() < WS_MAX_QUEUED_MESSAGES; } - - //system callbacks (do not call) - void _onAck(size_t len, uint32_t time); - void _onError(int8_t); - void _onPoll(); - void _onTimeout(uint32_t time); - void _onDisconnect(); - void _onData(void *pbuf, size_t plen); -}; - -typedef std::function AwsEventHandler; - -//WebServer Handler implementation that plays the role of a socket server -class AsyncWebSocket: public AsyncWebHandler { - public: - typedef AsyncLinkedList AsyncWebSocketClientAsyncLinkedList; - private: - String _url; - AsyncWebSocketClientAsyncLinkedList _clients; - uint32_t _cNextId; - AwsEventHandler _eventHandler; - bool _enabled; - AsyncWebLock _lock; - - public: - AsyncWebSocket(const String& url); - ~AsyncWebSocket(); - const char * url() const { return _url.c_str(); } - void enable(bool e){ _enabled = e; } - bool enabled() const { return _enabled; } - bool availableForWriteAll(); - bool availableForWrite(uint32_t id); - - size_t count() const; - AsyncWebSocketClient * client(uint32_t id); - bool hasClient(uint32_t id){ return client(id) != NULL; } - - void close(uint32_t id, uint16_t code=0, const char * message=NULL); - void closeAll(uint16_t code=0, const char * message=NULL); - void cleanupClients(uint16_t maxClients = DEFAULT_MAX_WS_CLIENTS); - - void ping(uint32_t id, uint8_t *data=NULL, size_t len=0); - void pingAll(uint8_t *data=NULL, size_t len=0); // done - - void text(uint32_t id, const char * message, size_t len); - void text(uint32_t id, const char * message); - void text(uint32_t id, uint8_t * message, size_t len); - void text(uint32_t id, char * message); - void text(uint32_t id, const String &message); - void text(uint32_t id, const __FlashStringHelper *message); - - void textAll(const char * message, size_t len); - void textAll(const char * message); - void textAll(uint8_t * message, size_t len); - void textAll(char * message); - void textAll(const String &message); - void textAll(const __FlashStringHelper *message); // need to convert - void textAll(AsyncWebSocketMessageBuffer * buffer); - - void binary(uint32_t id, const char * message, size_t len); - void binary(uint32_t id, const char * message); - void binary(uint32_t id, uint8_t * message, size_t len); - void binary(uint32_t id, char * message); - void binary(uint32_t id, const String &message); - void binary(uint32_t id, const __FlashStringHelper *message, size_t len); - - void binaryAll(const char * message, size_t len); - void binaryAll(const char * message); - void binaryAll(uint8_t * message, size_t len); - void binaryAll(char * message); - void binaryAll(const String &message); - void binaryAll(const __FlashStringHelper *message, size_t len); - void binaryAll(AsyncWebSocketMessageBuffer * buffer); - - void message(uint32_t id, AsyncWebSocketMessage *message); - void messageAll(AsyncWebSocketMultiMessage *message); - - size_t printf(uint32_t id, const char *format, ...) __attribute__ ((format (printf, 3, 4))); - size_t printfAll(const char *format, ...) __attribute__ ((format (printf, 2, 3))); -#ifndef ESP32 - size_t printf_P(uint32_t id, PGM_P formatP, ...) __attribute__ ((format (printf, 3, 4))); -#endif - size_t printfAll_P(PGM_P formatP, ...) __attribute__ ((format (printf, 2, 3))); - - //event listener - void onEvent(AwsEventHandler handler){ - _eventHandler = handler; - } - - //system callbacks (do not call) - uint32_t _getNextId(){ return _cNextId++; } - void _addClient(AsyncWebSocketClient * client); - void _handleDisconnect(AsyncWebSocketClient * client); - void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len); - virtual bool canHandle(AsyncWebServerRequest *request) override final; - virtual void handleRequest(AsyncWebServerRequest *request) override final; - - - // messagebuffer functions/objects. - AsyncWebSocketMessageBuffer * makeBuffer(size_t size = 0); - AsyncWebSocketMessageBuffer * makeBuffer(uint8_t * data, size_t size); - AsyncLinkedList _buffers; - void _cleanBuffers(); - - AsyncWebSocketClientAsyncLinkedList getClients() const; -}; - -//WebServer response to authenticate the socket and detach the tcp client from the web server request -class AsyncWebSocketResponse: public AsyncWebServerResponse { - private: - String _content; - AsyncWebSocket *_server; - public: - AsyncWebSocketResponse(const String& key, AsyncWebSocket *server); - void _respond(AsyncWebServerRequest *request); - size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); - bool _sourceValid() const { return true; } -}; - - -#endif /* ASYNCWEBSOCKET_H_ */ diff --git a/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSynchronization.h b/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSynchronization.h deleted file mode 100644 index f36c52dcf..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/AsyncWebSynchronization.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef ASYNCWEBSYNCHRONIZATION_H_ -#define ASYNCWEBSYNCHRONIZATION_H_ - -// Synchronisation is only available on ESP32, as the ESP8266 isn't using FreeRTOS by default - -#include - -#ifdef ESP32 - -// This is the ESP32 version of the Sync Lock, using the FreeRTOS Semaphore -class AsyncWebLock -{ -private: - SemaphoreHandle_t _lock; - mutable void *_lockedBy; - -public: - AsyncWebLock() { - _lock = xSemaphoreCreateBinary(); - _lockedBy = NULL; - xSemaphoreGive(_lock); - } - - ~AsyncWebLock() { - vSemaphoreDelete(_lock); - } - - bool lock() const { - extern void *pxCurrentTCB; - if (_lockedBy != pxCurrentTCB) { - xSemaphoreTake(_lock, portMAX_DELAY); - _lockedBy = pxCurrentTCB; - return true; - } - return false; - } - - void unlock() const { - _lockedBy = NULL; - xSemaphoreGive(_lock); - } -}; - -#else - -// This is the 8266 version of the Sync Lock which is currently unimplemented -class AsyncWebLock -{ - -public: - AsyncWebLock() { - } - - ~AsyncWebLock() { - } - - bool lock() const { - return false; - } - - void unlock() const { - } -}; -#endif - -class AsyncWebLockGuard -{ -private: - const AsyncWebLock *_lock; - -public: - AsyncWebLockGuard(const AsyncWebLock &l) { - if (l.lock()) { - _lock = &l; - } else { - _lock = NULL; - } - } - - ~AsyncWebLockGuard() { - if (_lock) { - _lock->unlock(); - } - } -}; - -#endif // ASYNCWEBSYNCHRONIZATION_H_ \ No newline at end of file diff --git a/lib/libesp32/ESPAsyncWebServer/src/ESPAsyncWebServer.h b/lib/libesp32/ESPAsyncWebServer/src/ESPAsyncWebServer.h deleted file mode 100644 index 5f718c35c..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/ESPAsyncWebServer.h +++ /dev/null @@ -1,471 +0,0 @@ -/* - Asynchronous WebServer library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#ifndef _ESPAsyncWebServer_H_ -#define _ESPAsyncWebServer_H_ - -#include "Arduino.h" - -#include -#include "FS.h" - -#include "StringArray.h" - -#ifdef ESP32 -#include -#include -#elif defined(ESP8266) -#include -#include -#else -#error Platform not supported -#endif - -#ifdef ASYNCWEBSERVER_REGEX -#define ASYNCWEBSERVER_REGEX_ATTRIBUTE -#else -#define ASYNCWEBSERVER_REGEX_ATTRIBUTE __attribute__((warning("ASYNCWEBSERVER_REGEX not defined"))) -#endif - -#define DEBUGF(...) //Serial.printf(__VA_ARGS__) - -class AsyncWebServer; -class AsyncWebServerRequest; -class AsyncWebServerResponse; -class AsyncWebHeader; -class AsyncWebParameter; -class AsyncWebRewrite; -class AsyncWebHandler; -class AsyncStaticWebHandler; -class AsyncCallbackWebHandler; -class AsyncResponseStream; - -#ifndef WEBSERVER_H -typedef enum { - HTTP_GET = 0b00000001, - HTTP_POST = 0b00000010, - HTTP_DELETE = 0b00000100, - HTTP_PUT = 0b00001000, - HTTP_PATCH = 0b00010000, - HTTP_HEAD = 0b00100000, - HTTP_OPTIONS = 0b01000000, - HTTP_ANY = 0b01111111, -} WebRequestMethod; -#endif - -//if this value is returned when asked for data, packet will not be sent and you will be asked for data again -#define RESPONSE_TRY_AGAIN 0xFFFFFFFF - -typedef uint8_t WebRequestMethodComposite; -typedef std::function ArDisconnectHandler; - -/* - * PARAMETER :: Chainable object to hold GET/POST and FILE parameters - * */ - -class AsyncWebParameter { - private: - String _name; - String _value; - size_t _size; - bool _isForm; - bool _isFile; - - public: - - AsyncWebParameter(const String& name, const String& value, bool form=false, bool file=false, size_t size=0): _name(name), _value(value), _size(size), _isForm(form), _isFile(file){} - const String& name() const { return _name; } - const String& value() const { return _value; } - size_t size() const { return _size; } - bool isPost() const { return _isForm; } - bool isFile() const { return _isFile; } -}; - -/* - * HEADER :: Chainable object to hold the headers - * */ - -class AsyncWebHeader { - private: - String _name; - String _value; - - public: - AsyncWebHeader(const String& name, const String& value): _name(name), _value(value){} - AsyncWebHeader(const String& data): _name(), _value(){ - if(!data) return; - int index = data.indexOf(':'); - if (index < 0) return; - _name = data.substring(0, index); - _value = data.substring(index + 2); - } - ~AsyncWebHeader(){} - const String& name() const { return _name; } - const String& value() const { return _value; } - String toString() const { return String(_name+": "+_value+"\r\n"); } -}; - -/* - * REQUEST :: Each incoming Client is wrapped inside a Request and both live together until disconnect - * */ - -typedef enum { RCT_NOT_USED = -1, RCT_DEFAULT = 0, RCT_HTTP, RCT_WS, RCT_EVENT, RCT_MAX } RequestedConnectionType; - -typedef std::function AwsResponseFiller; -typedef std::function AwsTemplateProcessor; - -class AsyncWebServerRequest { - using File = fs::File; - using FS = fs::FS; - friend class AsyncWebServer; - friend class AsyncCallbackWebHandler; - private: - AsyncClient* _client; - AsyncWebServer* _server; - AsyncWebHandler* _handler; - AsyncWebServerResponse* _response; - StringArray _interestingHeaders; - ArDisconnectHandler _onDisconnectfn; - - String _temp; - uint8_t _parseState; - - uint8_t _version; - WebRequestMethodComposite _method; - String _url; - String _host; - String _contentType; - String _boundary; - String _authorization; - RequestedConnectionType _reqconntype; - void _removeNotInterestingHeaders(); - bool _isDigest; - bool _isMultipart; - bool _isPlainPost; - bool _expectingContinue; - size_t _contentLength; - size_t _parsedLength; - - AsyncLinkedList _headers; - AsyncLinkedList _params; - AsyncLinkedList _pathParams; - - uint8_t _multiParseState; - uint8_t _boundaryPosition; - size_t _itemStartIndex; - size_t _itemSize; - String _itemName; - String _itemFilename; - String _itemType; - String _itemValue; - uint8_t *_itemBuffer; - size_t _itemBufferIndex; - bool _itemIsFile; - - void _onPoll(); - void _onAck(size_t len, uint32_t time); - void _onError(int8_t error); - void _onTimeout(uint32_t time); - void _onDisconnect(); - void _onData(void *buf, size_t len); - - void _addParam(AsyncWebParameter*); - void _addPathParam(const char *param); - - bool _parseReqHead(); - bool _parseReqHeader(); - void _parseLine(); - void _parsePlainPostChar(uint8_t data); - void _parseMultipartPostByte(uint8_t data, bool last); - void _addGetParams(const String& params); - - void _handleUploadStart(); - void _handleUploadByte(uint8_t data, bool last); - void _handleUploadEnd(); - - public: - File _tempFile; - void *_tempObject; - - AsyncWebServerRequest(AsyncWebServer*, AsyncClient*); - ~AsyncWebServerRequest(); - - AsyncClient* client(){ return _client; } - uint8_t version() const { return _version; } - WebRequestMethodComposite method() const { return _method; } - const String& url() const { return _url; } - const String& host() const { return _host; } - const String& contentType() const { return _contentType; } - size_t contentLength() const { return _contentLength; } - bool multipart() const { return _isMultipart; } - const char * methodToString() const; - const char * requestedConnTypeToString() const; - RequestedConnectionType requestedConnType() const { return _reqconntype; } - bool isExpectedRequestedConnType(RequestedConnectionType erct1, RequestedConnectionType erct2 = RCT_NOT_USED, RequestedConnectionType erct3 = RCT_NOT_USED); - void onDisconnect (ArDisconnectHandler fn); - - //hash is the string representation of: - // base64(user:pass) for basic or - // user:realm:md5(user:realm:pass) for digest - bool authenticate(const char * hash); - bool authenticate(const char * username, const char * password, const char * realm = NULL, bool passwordIsHash = false); - void requestAuthentication(const char * realm = NULL, bool isDigest = true); - - void setHandler(AsyncWebHandler *handler){ _handler = handler; } - void addInterestingHeader(const String& name); - - void redirect(const String& url); - - void send(AsyncWebServerResponse *response); - void send(int code, const String& contentType=String(), const String& content=String()); - void send(FS &fs, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr); - void send(File content, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr); - void send(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback=nullptr); - void send(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr); - void sendChunked(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr); - void send_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback=nullptr); - void send_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback=nullptr); - - AsyncWebServerResponse *beginResponse(int code, const String& contentType=String(), const String& content=String()); - AsyncWebServerResponse *beginResponse(FS &fs, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr); - AsyncWebServerResponse *beginResponse(File content, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr); - AsyncWebServerResponse *beginResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback=nullptr); - AsyncWebServerResponse *beginResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr); - AsyncWebServerResponse *beginChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr); - AsyncResponseStream *beginResponseStream(const String& contentType, size_t bufferSize=1460); - AsyncWebServerResponse *beginResponse_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback=nullptr); - AsyncWebServerResponse *beginResponse_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback=nullptr); - - size_t headers() const; // get header count - bool hasHeader(const String& name) const; // check if header exists - bool hasHeader(const __FlashStringHelper * data) const; // check if header exists - - AsyncWebHeader* getHeader(const String& name) const; - AsyncWebHeader* getHeader(const __FlashStringHelper * data) const; - AsyncWebHeader* getHeader(size_t num) const; - - size_t params() const; // get arguments count - bool hasParam(const String& name, bool post=false, bool file=false) const; - bool hasParam(const __FlashStringHelper * data, bool post=false, bool file=false) const; - - AsyncWebParameter* getParam(const String& name, bool post=false, bool file=false) const; - AsyncWebParameter* getParam(const __FlashStringHelper * data, bool post, bool file) const; - AsyncWebParameter* getParam(size_t num) const; - - size_t args() const { return params(); } // get arguments count - const String& arg(const String& name) const; // get request argument value by name - const String& arg(const __FlashStringHelper * data) const; // get request argument value by F(name) - const String& arg(size_t i) const; // get request argument value by number - const String& argName(size_t i) const; // get request argument name by number - bool hasArg(const char* name) const; // check if argument exists - bool hasArg(const __FlashStringHelper * data) const; // check if F(argument) exists - - const String& ASYNCWEBSERVER_REGEX_ATTRIBUTE pathArg(size_t i) const; - - const String& header(const char* name) const;// get request header value by name - const String& header(const __FlashStringHelper * data) const;// get request header value by F(name) - const String& header(size_t i) const; // get request header value by number - const String& headerName(size_t i) const; // get request header name by number - String urlDecode(const String& text) const; -}; - -/* - * FILTER :: Callback to filter AsyncWebRewrite and AsyncWebHandler (done by the Server) - * */ - -typedef std::function ArRequestFilterFunction; - -bool ON_STA_FILTER(AsyncWebServerRequest *request); - -bool ON_AP_FILTER(AsyncWebServerRequest *request); - -/* - * REWRITE :: One instance can be handle any Request (done by the Server) - * */ - -class AsyncWebRewrite { - protected: - String _from; - String _toUrl; - String _params; - ArRequestFilterFunction _filter; - public: - AsyncWebRewrite(const char* from, const char* to): _from(from), _toUrl(to), _params(String()), _filter(NULL){ - int index = _toUrl.indexOf('?'); - if (index > 0) { - _params = _toUrl.substring(index +1); - _toUrl = _toUrl.substring(0, index); - } - } - virtual ~AsyncWebRewrite(){} - AsyncWebRewrite& setFilter(ArRequestFilterFunction fn) { _filter = fn; return *this; } - bool filter(AsyncWebServerRequest *request) const { return _filter == NULL || _filter(request); } - const String& from(void) const { return _from; } - const String& toUrl(void) const { return _toUrl; } - const String& params(void) const { return _params; } - virtual bool match(AsyncWebServerRequest *request) { return from() == request->url() && filter(request); } -}; - -/* - * HANDLER :: One instance can be attached to any Request (done by the Server) - * */ - -class AsyncWebHandler { - protected: - ArRequestFilterFunction _filter; - String _username; - String _password; - public: - AsyncWebHandler():_username(""), _password(""){} - AsyncWebHandler& setFilter(ArRequestFilterFunction fn) { _filter = fn; return *this; } - AsyncWebHandler& setAuthentication(const char *username, const char *password){ _username = String(username);_password = String(password); return *this; }; - bool filter(AsyncWebServerRequest *request){ return _filter == NULL || _filter(request); } - virtual ~AsyncWebHandler(){} - virtual bool canHandle(AsyncWebServerRequest *request __attribute__((unused))){ - return false; - } - virtual void handleRequest(AsyncWebServerRequest *request __attribute__((unused))){} - virtual void handleUpload(AsyncWebServerRequest *request __attribute__((unused)), const String& filename __attribute__((unused)), size_t index __attribute__((unused)), uint8_t *data __attribute__((unused)), size_t len __attribute__((unused)), bool final __attribute__((unused))){} - virtual void handleBody(AsyncWebServerRequest *request __attribute__((unused)), uint8_t *data __attribute__((unused)), size_t len __attribute__((unused)), size_t index __attribute__((unused)), size_t total __attribute__((unused))){} - virtual bool isRequestHandlerTrivial(){return true;} -}; - -/* - * RESPONSE :: One instance is created for each Request (attached by the Handler) - * */ - -typedef enum { - RESPONSE_SETUP, RESPONSE_HEADERS, RESPONSE_CONTENT, RESPONSE_WAIT_ACK, RESPONSE_END, RESPONSE_FAILED -} WebResponseState; - -class AsyncWebServerResponse { - protected: - int _code; - AsyncLinkedList _headers; - String _contentType; - size_t _contentLength; - bool _sendContentLength; - bool _chunked; - size_t _headLength; - size_t _sentLength; - size_t _ackedLength; - size_t _writtenLength; - WebResponseState _state; - const char* _responseCodeToString(int code); - - public: - AsyncWebServerResponse(); - virtual ~AsyncWebServerResponse(); - virtual void setCode(int code); - virtual void setContentLength(size_t len); - virtual void setContentType(const String& type); - virtual void addHeader(const String& name, const String& value); - virtual String _assembleHead(uint8_t version); - virtual bool _started() const; - virtual bool _finished() const; - virtual bool _failed() const; - virtual bool _sourceValid() const; - virtual void _respond(AsyncWebServerRequest *request); - virtual size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); -}; - -/* - * SERVER :: One instance - * */ - -typedef std::function ArRequestHandlerFunction; -typedef std::function ArUploadHandlerFunction; -typedef std::function ArBodyHandlerFunction; - -class AsyncWebServer { - protected: - AsyncServer _server; - AsyncLinkedList _rewrites; - AsyncLinkedList _handlers; - AsyncCallbackWebHandler* _catchAllHandler; - - public: - AsyncWebServer(uint16_t port); - ~AsyncWebServer(); - - void begin(); - void end(); - -#if ASYNC_TCP_SSL_ENABLED - void onSslFileRequest(AcSSlFileHandler cb, void* arg); - void beginSecure(const char *cert, const char *private_key_file, const char *password); -#endif - - AsyncWebRewrite& addRewrite(AsyncWebRewrite* rewrite); - bool removeRewrite(AsyncWebRewrite* rewrite); - AsyncWebRewrite& rewrite(const char* from, const char* to); - - AsyncWebHandler& addHandler(AsyncWebHandler* handler); - bool removeHandler(AsyncWebHandler* handler); - - AsyncCallbackWebHandler& on(const char* uri, ArRequestHandlerFunction onRequest); - AsyncCallbackWebHandler& on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest); - AsyncCallbackWebHandler& on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload); - AsyncCallbackWebHandler& on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload, ArBodyHandlerFunction onBody); - - AsyncStaticWebHandler& serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_control = NULL); - - void onNotFound(ArRequestHandlerFunction fn); //called when handler is not assigned - void onFileUpload(ArUploadHandlerFunction fn); //handle file uploads - void onRequestBody(ArBodyHandlerFunction fn); //handle posts with plain body content (JSON often transmitted this way as a request) - - void reset(); //remove all writers and handlers, with onNotFound/onFileUpload/onRequestBody - - void _handleDisconnect(AsyncWebServerRequest *request); - void _attachHandler(AsyncWebServerRequest *request); - void _rewriteRequest(AsyncWebServerRequest *request); -}; - -class DefaultHeaders { - using headers_t = AsyncLinkedList; - headers_t _headers; - - DefaultHeaders() - :_headers(headers_t([](AsyncWebHeader *h){ delete h; })) - {} -public: - using ConstIterator = headers_t::ConstIterator; - - void addHeader(const String& name, const String& value){ - _headers.add(new AsyncWebHeader(name, value)); - } - - ConstIterator begin() const { return _headers.begin(); } - ConstIterator end() const { return _headers.end(); } - - DefaultHeaders(DefaultHeaders const &) = delete; - DefaultHeaders &operator=(DefaultHeaders const &) = delete; - static DefaultHeaders &Instance() { - static DefaultHeaders instance; - return instance; - } -}; - -#include "WebResponseImpl.h" -#include "WebHandlerImpl.h" -#include "AsyncWebSocket.h" -#include "AsyncEventSource.h" - -#endif /* _AsyncWebServer_H_ */ diff --git a/lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.cpp b/lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.cpp deleted file mode 100644 index a84fa87dd..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.cpp +++ /dev/null @@ -1,544 +0,0 @@ -#include "SPIFFSEditor.h" -#include - -//File: edit.htm.gz, Size: 4151 -#define edit_htm_gz_len 4151 -const uint8_t edit_htm_gz[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xB8, 0x94, 0xB1, 0x59, 0x00, 0x03, 0x65, 0x64, 0x69, 0x74, 0x2E, 0x68, - 0x74, 0x6D, 0x00, 0xB5, 0x3A, 0x0B, 0x7B, 0xDA, 0xB8, 0xB2, 0x7F, 0xC5, 0x71, 0xCF, 0x66, 0xED, - 0x83, 0x31, 0x90, 0xA4, 0xD9, 0xD6, 0xC4, 0xC9, 0x42, 0x92, 0x36, 0x6D, 0xF3, 0x6A, 0x80, 0xB6, - 0x69, 0x4F, 0xEE, 0x7E, 0xC2, 0x16, 0xA0, 0xC6, 0x96, 0x5D, 0x5B, 0x0E, 0x49, 0x59, 0xFE, 0xFB, - 0x9D, 0x91, 0x6C, 0xB0, 0x09, 0x69, 0x77, 0xCF, 0xBD, 0xBB, 0xDD, 0x2D, 0x92, 0x46, 0x33, 0x9A, - 0x19, 0xCD, 0x53, 0xDE, 0xBD, 0x8D, 0xA3, 0x8B, 0xC3, 0xFE, 0xF5, 0xE5, 0xB1, 0x36, 0x11, 0x61, - 0xB0, 0xBF, 0x87, 0x7F, 0x6B, 0x01, 0xE1, 0x63, 0x97, 0xF2, 0xFD, 0x3D, 0xC1, 0x44, 0x40, 0xF7, - 0x8F, 0x7B, 0x97, 0xDA, 0xB1, 0xCF, 0x44, 0x94, 0xEC, 0x35, 0xD4, 0xCA, 0x5E, 0x2A, 0x1E, 0x02, - 0xAA, 0x85, 0xD4, 0x67, 0xC4, 0x4D, 0xBD, 0x84, 0xC2, 0x66, 0xDB, 0x0B, 0x67, 0xDF, 0xEB, 0x8C, - 0xFB, 0xF4, 0xDE, 0xD9, 0x6E, 0x36, 0xDB, 0x71, 0x94, 0x32, 0xC1, 0x22, 0xEE, 0x90, 0x61, 0x1A, - 0x05, 0x99, 0xA0, 0xED, 0x80, 0x8E, 0x84, 0xF3, 0x3C, 0xBE, 0x6F, 0x0F, 0xA3, 0xC4, 0xA7, 0x89, - 0xD3, 0x8A, 0xEF, 0x35, 0x00, 0x31, 0x5F, 0x7B, 0xB6, 0xB3, 0xB3, 0xD3, 0x1E, 0x12, 0xEF, 0x76, - 0x9C, 0x44, 0x19, 0xF7, 0xEB, 0x5E, 0x14, 0x44, 0x89, 0xF3, 0x6C, 0xF4, 0x1C, 0xFF, 0xB4, 0x7D, - 0x96, 0xC6, 0x01, 0x79, 0x70, 0x78, 0xC4, 0x29, 0xE0, 0xDE, 0xD7, 0xD3, 0x09, 0xF1, 0xA3, 0xA9, - 0xD3, 0xD4, 0x9A, 0x5A, 0xAB, 0x09, 0x44, 0x92, 0xF1, 0x90, 0x18, 0x4D, 0x0B, 0xFF, 0xD8, 0x3B, - 0x66, 0x7B, 0x14, 0x71, 0x51, 0x4F, 0xD9, 0x77, 0xEA, 0xB4, 0xB6, 0xE0, 0x34, 0x39, 0x1D, 0x91, - 0x90, 0x05, 0x0F, 0x4E, 0x4A, 0x78, 0x5A, 0x4F, 0x69, 0xC2, 0x46, 0x6A, 0x79, 0x4A, 0xD9, 0x78, - 0x22, 0x9C, 0xDF, 0x9A, 0xCD, 0x39, 0xF0, 0xAF, 0x65, 0xC1, 0x2C, 0x60, 0x29, 0x20, 0xA3, 0x78, - 0xEA, 0x3C, 0x11, 0xC5, 0x4E, 0x53, 0xB1, 0xDE, 0x6C, 0x87, 0x24, 0x19, 0x33, 0x0E, 0x83, 0x98, - 0xF8, 0x3E, 0xE3, 0x63, 0x47, 0xA1, 0x05, 0x6C, 0xB6, 0x90, 0x36, 0xA1, 0x01, 0x11, 0xEC, 0x8E, - 0xB6, 0x43, 0xC6, 0xEB, 0x53, 0xE6, 0x8B, 0x89, 0xB3, 0x0B, 0x3C, 0xB6, 0xBD, 0x2C, 0x49, 0x41, - 0xA6, 0x38, 0x62, 0x5C, 0xD0, 0x44, 0xA2, 0xA5, 0x31, 0xE1, 0xB3, 0x5C, 0x54, 0x54, 0x40, 0x21, - 0x27, 0xE3, 0x01, 0xE3, 0xB4, 0x3E, 0x0C, 0x22, 0xEF, 0x76, 0x71, 0xD2, 0x6E, 0x7C, 0x9F, 0x9F, - 0xE5, 0x4C, 0xA2, 0x3B, 0x9A, 0xCC, 0x96, 0xEA, 0x92, 0xD8, 0x15, 0x60, 0x85, 0x34, 0xA5, 0x74, - 0x6E, 0x8B, 0xBB, 0x0C, 0xA0, 0x96, 0xFC, 0x05, 0x29, 0x17, 0xFC, 0x2F, 0x45, 0x5A, 0x11, 0x5C, - 0xA1, 0x30, 0x1E, 0x67, 0x62, 0xF6, 0xF8, 0x2A, 0xA3, 0x98, 0x78, 0x4C, 0x3C, 0xA0, 0xFC, 0xB0, - 0x6D, 0x86, 0xBA, 0x04, 0xAC, 0x24, 0x24, 0x81, 0x86, 0x3A, 0xD7, 0x3E, 0xD0, 0xC4, 0x27, 0x9C, - 0x58, 0x9D, 0x84, 0x91, 0xC0, 0xEA, 0x2D, 0xB5, 0x5E, 0x0F, 0xA3, 0xEF, 0xF5, 0x0C, 0xC6, 0x30, - 0x0F, 0xA8, 0x27, 0x94, 0x92, 0xE1, 0x1E, 0x86, 0xB7, 0x4C, 0x3C, 0x06, 0x3C, 0x5A, 0x28, 0xA9, - 0x4B, 0x2A, 0x69, 0xA2, 0x2E, 0xB0, 0x25, 0xD5, 0x83, 0x1C, 0x4B, 0xC9, 0x95, 0x50, 0xF5, 0x61, - 0x24, 0x44, 0x14, 0x4A, 0x93, 0x5B, 0x08, 0xAC, 0x49, 0xAB, 0x79, 0xF1, 0xE8, 0x46, 0xD6, 0x6B, - 0xBF, 0x44, 0xBE, 0x0D, 0x7A, 0x15, 0xCC, 0x23, 0x41, 0x9D, 0x04, 0x6C, 0xCC, 0x9D, 0x90, 0xF9, - 0x7E, 0x40, 0x4B, 0x56, 0xEB, 0x64, 0x49, 0x60, 0xF8, 0x44, 0x10, 0x87, 0x85, 0x64, 0x4C, 0x1B, - 0x31, 0x1F, 0x03, 0x34, 0xA5, 0xBB, 0x3B, 0x16, 0xFB, 0xD0, 0xBD, 0xB8, 0x9A, 0x36, 0xDF, 0xBD, - 0x1E, 0x47, 0x1D, 0xF8, 0xE7, 0xBC, 0x37, 0x98, 0x1C, 0x0F, 0xC6, 0x30, 0xEA, 0xE2, 0xB4, 0xF3, - 0xFE, 0xB0, 0xF3, 0x1E, 0x7E, 0x0E, 0x5B, 0xB5, 0xAF, 0xA3, 0x6F, 0xB8, 0xD0, 0x7D, 0xED, 0x77, - 0xFB, 0x83, 0xE3, 0x4E, 0xE7, 0x5D, 0xE3, 0xCD, 0xF9, 0xF4, 0xE3, 0xBB, 0x5D, 0x04, 0x77, 0x83, - 0xE6, 0xD5, 0x87, 0x49, 0x73, 0xB0, 0xF5, 0x32, 0xF4, 0x4F, 0xFC, 0x89, 0x17, 0x0E, 0x3A, 0xEF, - 0x3F, 0x5E, 0xDD, 0x5D, 0x87, 0x83, 0x71, 0xEF, 0x63, 0x6B, 0xF2, 0x79, 0xEB, 0x43, 0xEF, 0xF3, - 0xC7, 0x57, 0xB7, 0xF4, 0xD3, 0xC9, 0xDB, 0xCF, 0xFD, 0x29, 0x20, 0x1C, 0x45, 0xBD, 0xC1, 0x55, - 0xF7, 0x43, 0x77, 0xFC, 0xB9, 0xEB, 0x1D, 0xDF, 0x0F, 0x83, 0xF3, 0xEE, 0xEB, 0xCE, 0xB0, 0xB3, - 0xE5, 0x51, 0x3A, 0xEE, 0x5F, 0x75, 0xB3, 0x37, 0xEF, 0x2E, 0xC6, 0x8C, 0x4D, 0x7A, 0x9F, 0xCF, - 0xFB, 0xDE, 0xE1, 0xF3, 0xD3, 0xC1, 0x49, 0x87, 0x4D, 0xCE, 0xDF, 0x5E, 0x35, 0x6F, 0x5F, 0xBF, - 0x3B, 0x3C, 0xF2, 0xAE, 0xDF, 0x5E, 0xEF, 0x1E, 0x6D, 0x37, 0x7E, 0xFB, 0xED, 0xCC, 0xBF, 0x60, - 0xBC, 0x7F, 0xF7, 0xBD, 0x33, 0x3E, 0x9C, 0xBE, 0x78, 0x48, 0xFB, 0x93, 0x37, 0x77, 0xBC, 0xF1, - 0x21, 0xFA, 0xFA, 0xE6, 0xE1, 0x0C, 0xFE, 0xBB, 0xBC, 0xAC, 0x0D, 0x7B, 0xAD, 0x74, 0xF0, 0xFE, - 0xCD, 0x87, 0xAD, 0xF4, 0xE5, 0xF3, 0xB8, 0x7B, 0x74, 0x74, 0x17, 0x0E, 0x2F, 0x1B, 0xA1, 0x7F, - 0x3B, 0x12, 0x2F, 0xB6, 0x45, 0x7C, 0x3D, 0xCE, 0x3E, 0x7F, 0x7B, 0xFE, 0x76, 0xD2, 0xB8, 0xA0, - 0xE4, 0x7A, 0x52, 0x7B, 0xF8, 0xFE, 0xF0, 0x62, 0xD2, 0x3F, 0xB9, 0x3B, 0x0F, 0xC8, 0xFD, 0xF9, - 0xB9, 0xF7, 0x3D, 0xAC, 0x05, 0xE4, 0xE5, 0x45, 0x3F, 0x20, 0x49, 0x6B, 0xE0, 0x77, 0x1A, 0xB5, - 0xC3, 0xAD, 0xCE, 0x8E, 0x48, 0xAE, 0x0E, 0xF9, 0xD1, 0xF6, 0xD7, 0xDE, 0x8B, 0x6E, 0xB7, 0x15, - 0x0D, 0xBF, 0x6D, 0xBD, 0xBE, 0xDD, 0x7D, 0x3D, 0xD8, 0x7D, 0x3F, 0x7C, 0xDF, 0xE9, 0xED, 0x74, - 0x07, 0xE4, 0xBA, 0xF7, 0xBE, 0x33, 0xDA, 0x19, 0x4E, 0x26, 0xEF, 0xDE, 0xF5, 0x5F, 0xF9, 0x9D, - 0xEF, 0x49, 0xE7, 0x62, 0xDA, 0xB9, 0x3F, 0x1E, 0x74, 0x4E, 0x6A, 0xEF, 0x8E, 0xCF, 0x9A, 0xAD, - 0xDE, 0xF5, 0xF6, 0xF8, 0x6C, 0x77, 0xDA, 0x4D, 0x8F, 0x3B, 0xEF, 0xBB, 0xCD, 0xF1, 0xDB, 0x5A, - 0x48, 0x3E, 0x47, 0x87, 0xDB, 0xE3, 0x37, 0xBB, 0xEC, 0xF2, 0x9A, 0x74, 0xDE, 0x74, 0xDF, 0xA6, - 0xEC, 0x2A, 0x3C, 0x19, 0x34, 0x3B, 0x9D, 0xD3, 0x0B, 0xFA, 0xEA, 0x70, 0x9B, 0xBC, 0xDB, 0xF2, - 0x3E, 0x82, 0xFE, 0x07, 0x9F, 0xE8, 0x6F, 0xB5, 0xCE, 0xF4, 0xA2, 0x19, 0x78, 0x2F, 0x69, 0xFF, - 0xE4, 0xBA, 0x2F, 0x6F, 0xE7, 0x38, 0x78, 0xD5, 0xBF, 0xED, 0x65, 0xEF, 0xC3, 0xC3, 0x43, 0x53, - 0xE3, 0x51, 0x3D, 0xA1, 0x31, 0x25, 0xA2, 0x1C, 0xAE, 0x16, 0xFE, 0x01, 0xB6, 0xB5, 0xB4, 0xC2, - 0xDC, 0x4F, 0x05, 0xBD, 0x17, 0x75, 0x9F, 0x7A, 0x51, 0x42, 0xE4, 0x1E, 0x40, 0xA0, 0x09, 0x9A, - 0xD8, 0xFC, 0x77, 0x19, 0x3F, 0x35, 0x15, 0x3F, 0x35, 0xC2, 0x7D, 0xCD, 0x28, 0x1C, 0x01, 0x83, - 0x87, 0x4F, 0xEF, 0x98, 0x47, 0xEB, 0x31, 0xBB, 0xA7, 0x41, 0x5D, 0x22, 0x3B, 0x4D, 0x73, 0x26, - 0xFD, 0xAD, 0xD8, 0x46, 0x38, 0x98, 0x9A, 0xA4, 0x5A, 0x2C, 0xF8, 0x5F, 0x89, 0x47, 0x21, 0xB0, - 0x81, 0xCB, 0x84, 0xF8, 0xAB, 0x7C, 0x27, 0x4A, 0xEA, 0xC3, 0x6C, 0x3C, 0x62, 0xF7, 0xE0, 0xD0, - 0x23, 0xC6, 0x99, 0xA0, 0x5A, 0x2B, 0x9D, 0xFF, 0x5E, 0x90, 0xB9, 0xA5, 0x0F, 0xA3, 0x84, 0x84, - 0x34, 0xD5, 0xFE, 0x22, 0x99, 0xD9, 0x28, 0x89, 0xC2, 0x65, 0x10, 0x99, 0x8B, 0xA8, 0x34, 0x99, - 0xCF, 0x9F, 0x65, 0x71, 0x10, 0x11, 0x10, 0x73, 0x4D, 0xE4, 0x50, 0xF1, 0x34, 0x91, 0x6E, 0xB5, - 0x88, 0xAB, 0xB9, 0x9B, 0x6D, 0xA1, 0x5B, 0x96, 0xDD, 0x7A, 0x6B, 0x67, 0xE9, 0xBA, 0x75, 0xB9, - 0x17, 0xE3, 0xFD, 0x9A, 0x4C, 0x81, 0xF1, 0xA0, 0x14, 0xEE, 0x9E, 0x09, 0x50, 0xE9, 0x13, 0x87, - 0xCB, 0x43, 0xF2, 0xC8, 0xB0, 0x60, 0x40, 0x05, 0xEA, 0x96, 0x8C, 0xD4, 0x85, 0x24, 0xB0, 0x6F, - 0xFE, 0x8C, 0xCA, 0xBC, 0x67, 0x3D, 0x8B, 0x13, 0xB8, 0x0D, 0x3A, 0xFD, 0x11, 0xCD, 0x42, 0xA6, - 0x2A, 0x6D, 0x45, 0x53, 0x65, 0xBC, 0x5C, 0x84, 0x65, 0xDA, 0x93, 0xBC, 0x16, 0xA4, 0x1F, 0x4B, - 0x05, 0xE0, 0x05, 0x37, 0xCF, 0x91, 0x9B, 0x1F, 0x6A, 0x75, 0x7B, 0xF7, 0x97, 0x9C, 0x87, 0x9D, - 0xE6, 0x2F, 0x73, 0x3B, 0xDF, 0x5B, 0xA4, 0xE4, 0x56, 0x13, 0xFE, 0x29, 0x32, 0xEF, 0x8B, 0x25, - 0x0B, 0xC3, 0xE7, 0xF8, 0xA7, 0x60, 0x10, 0xE9, 0x94, 0x80, 0xDB, 0x3B, 0x2F, 0x5F, 0xF8, 0xC3, - 0x02, 0x98, 0x0B, 0xF6, 0x24, 0x3C, 0x21, 0x3E, 0xCB, 0x52, 0xE7, 0x79, 0xF3, 0x97, 0x5C, 0x9F, - 0x5B, 0x3B, 0x28, 0xFB, 0xE2, 0x2E, 0x71, 0xB2, 0xB4, 0xD8, 0x34, 0x66, 0x5C, 0xDB, 0x4A, 0x35, - 0xBC, 0x6F, 0x92, 0x2C, 0x0C, 0xB3, 0x92, 0xED, 0xE7, 0xBF, 0x2F, 0x4D, 0x13, 0xF7, 0xCF, 0x9A, - 0xBF, 0xCC, 0x44, 0x02, 0xD9, 0x64, 0x04, 0xB9, 0xC6, 0x49, 0x22, 0x41, 0x04, 0x35, 0x9A, 0xE6, - 0x1C, 0x84, 0x5B, 0x03, 0xD8, 0xDE, 0x6D, 0xFA, 0x74, 0x6C, 0xCE, 0xE7, 0x7B, 0x0D, 0x99, 0xD7, - 0xA0, 0x6C, 0xF1, 0x12, 0x16, 0x8B, 0xFD, 0x51, 0xC6, 0x3D, 0xE4, 0x41, 0x1B, 0x53, 0x83, 0x9A, - 0xB3, 0x84, 0x8A, 0x2C, 0xE1, 0x9A, 0x1F, 0x79, 0x19, 0x1A, 0xBB, 0x3D, 0xA6, 0xE2, 0x58, 0xD9, - 0x7D, 0xF7, 0xE1, 0x8D, 0x0F, 0x3B, 0xE6, 0x0B, 0x04, 0x6F, 0x2D, 0x02, 0x38, 0x30, 0x9C, 0x97, - 0xE3, 0x54, 0xF6, 0x43, 0x82, 0x01, 0x22, 0xEF, 0xE8, 0x83, 0x41, 0x2D, 0xB1, 0x40, 0xA4, 0x36, - 0xAE, 0x1B, 0xC5, 0x2E, 0x80, 0x71, 0x73, 0x76, 0x07, 0x4A, 0x20, 0x2E, 0xFD, 0x22, 0x6E, 0x2C, - 0xE6, 0x72, 0xF8, 0x69, 0xE7, 0xBB, 0xC9, 0x1E, 0x3B, 0xA8, 0xB7, 0x1C, 0xB2, 0xCF, 0x0E, 0x5A, - 0xE0, 0x5E, 0x65, 0x6E, 0xE4, 0xB9, 0xAF, 0x58, 0x40, 0x07, 0xB9, 0xC3, 0xE1, 0x31, 0x48, 0x6C, - 0xB1, 0x85, 0x28, 0xE2, 0x5B, 0xCD, 0xE6, 0x86, 0x4B, 0x0F, 0x48, 0x00, 0x39, 0xCC, 0xD0, 0x8F, - 0xAF, 0xAE, 0x2E, 0xAE, 0xBE, 0xE8, 0x35, 0x5A, 0xD3, 0x6F, 0x1C, 0x4D, 0xAF, 0x71, 0xD3, 0x11, - 0x76, 0x42, 0x47, 0x09, 0x4D, 0x27, 0x97, 0x44, 0x4C, 0x8C, 0xD4, 0xBE, 0x23, 0x41, 0x56, 0x16, - 0x84, 0xA1, 0xDC, 0xC8, 0xA2, 0x70, 0x39, 0x9D, 0x6A, 0xAF, 0x40, 0xCD, 0x47, 0x90, 0xEA, 0xDA, - 0xC2, 0x26, 0x71, 0x4C, 0xB9, 0x6F, 0xE8, 0x31, 0x20, 0xEA, 0x16, 0x35, 0xAD, 0x84, 0x7E, 0xCB, - 0x68, 0x2A, 0x52, 0x1B, 0x2C, 0xD7, 0xD0, 0x2F, 0x07, 0x7D, 0xDD, 0xD2, 0x1B, 0xE8, 0x47, 0x3A, - 0xF0, 0x46, 0xCC, 0x39, 0x52, 0x89, 0x5C, 0xD0, 0xA4, 0x3E, 0xCC, 0xC0, 0xA0, 0xB8, 0x6E, 0xB6, - 0x23, 0x9B, 0x71, 0x4E, 0x93, 0x93, 0xFE, 0xD9, 0xA9, 0xAB, 0x5F, 0x29, 0x46, 0xB4, 0x53, 0x28, - 0x48, 0x74, 0x4B, 0x5E, 0x51, 0x7E, 0xC8, 0xE1, 0x84, 0x05, 0xBE, 0x11, 0x99, 0x6D, 0x24, 0xE1, - 0x49, 0x12, 0xB2, 0x40, 0x01, 0x0A, 0x9E, 0x2D, 0x1E, 0x62, 0xEA, 0xEA, 0x23, 0x50, 0x86, 0x6E, - 0x79, 0x76, 0x98, 0x05, 0x82, 0xC5, 0x01, 0x75, 0x37, 0x5A, 0x30, 0xE3, 0x60, 0x41, 0xAE, 0x8E, - 0xB9, 0x19, 0x61, 0xCC, 0x77, 0x75, 0x15, 0xA1, 0xF2, 0xB8, 0xB6, 0xEE, 0x14, 0x4F, 0x9D, 0x92, - 0x56, 0x4E, 0x49, 0xCB, 0xB8, 0x4A, 0xE0, 0x34, 0x3F, 0x18, 0xC3, 0x3C, 0xCE, 0xD4, 0x51, 0x05, - 0xCC, 0xA7, 0x23, 0x02, 0x9C, 0x7C, 0x40, 0x6D, 0xBA, 0x7A, 0x63, 0xDD, 0x41, 0xA9, 0x3A, 0xC8, - 0xAF, 0x6A, 0xC4, 0x2F, 0x6B, 0x44, 0xDD, 0xEE, 0x3A, 0x64, 0x5F, 0x21, 0x07, 0x55, 0xE4, 0xA0, - 0x8C, 0x7C, 0x28, 0x8D, 0x64, 0x1D, 0x72, 0xA0, 0x90, 0x93, 0x8A, 0x88, 0x89, 0x14, 0x51, 0x85, - 0xBD, 0x3A, 0x6A, 0x13, 0x05, 0xD2, 0xAD, 0xA4, 0x22, 0x66, 0x62, 0x83, 0x97, 0x92, 0x61, 0x40, - 0x7D, 0x77, 0xA3, 0x09, 0x33, 0x2C, 0xB6, 0xDD, 0xAD, 0xE6, 0x9A, 0x33, 0x12, 0x75, 0x46, 0x56, - 0x65, 0x30, 0x2B, 0x33, 0xA8, 0xF5, 0xC8, 0x1D, 0xD5, 0xD6, 0x31, 0x98, 0x99, 0x56, 0x60, 0x47, - 0xDC, 0x0B, 0x98, 0x77, 0xEB, 0x2E, 0xBD, 0xC5, 0x9C, 0xB1, 0x85, 0x85, 0x5A, 0x5C, 0x06, 0xBA, - 0x01, 0x94, 0x5E, 0x8B, 0xA5, 0x7C, 0x80, 0xFA, 0x9E, 0x5B, 0xD9, 0x5A, 0x02, 0xDC, 0xA6, 0xF7, - 0xD4, 0x3B, 0x8C, 0xC2, 0x90, 0xA0, 0xED, 0xA6, 0xC0, 0x41, 0x3E, 0xD1, 0xCD, 0xB9, 0x15, 0xAD, - 0xC5, 0x79, 0xC2, 0x45, 0x2C, 0x7F, 0x3D, 0x8B, 0x23, 0x03, 0x5C, 0xCE, 0xF5, 0x6C, 0xD4, 0x61, - 0x6A, 0x83, 0x1E, 0xC7, 0x62, 0xF2, 0x13, 0x17, 0x2A, 0x0C, 0x54, 0xA2, 0x7C, 0x69, 0xDE, 0x58, - 0x0B, 0x91, 0x56, 0x7C, 0xEA, 0xA2, 0xB7, 0xE2, 0x54, 0xA8, 0xBC, 0x8A, 0x5D, 0x9A, 0x4B, 0x1D, - 0x94, 0x61, 0xB9, 0xBD, 0x2F, 0xA0, 0xFA, 0x7C, 0x0E, 0xE7, 0x01, 0xFF, 0x13, 0x68, 0xF9, 0xE8, - 0x5F, 0x17, 0x60, 0xC9, 0xA3, 0x34, 0x78, 0x8B, 0xBB, 0x0D, 0xE3, 0xC0, 0xF9, 0x8F, 0x6D, 0x7C, - 0xF9, 0x1F, 0xFB, 0xA6, 0x66, 0x9A, 0x07, 0xFF, 0x6A, 0x48, 0x0D, 0x1B, 0xC2, 0xFC, 0xD2, 0xBA, - 0xB1, 0x08, 0x80, 0xED, 0x7F, 0x9B, 0xFF, 0xB1, 0x25, 0xB8, 0x02, 0x6B, 0xDF, 0x45, 0x90, 0x49, - 0xF0, 0x24, 0x34, 0xB0, 0x68, 0xA4, 0x91, 0xCD, 0x4D, 0x43, 0xB8, 0xA4, 0x72, 0x8D, 0x35, 0x51, - 0xD3, 0x6D, 0x88, 0x53, 0x50, 0x5B, 0xAC, 0x04, 0xBF, 0x3E, 0x24, 0x7A, 0x15, 0x5B, 0x17, 0x00, - 0xC9, 0x3D, 0xCA, 0x0C, 0x3D, 0x22, 0x97, 0x52, 0xCB, 0x0C, 0x02, 0x42, 0xA7, 0x89, 0xE7, 0x2A, - 0xAD, 0x1D, 0x14, 0x30, 0x17, 0xA2, 0xE0, 0xBC, 0x1C, 0x2D, 0x15, 0xEA, 0xAA, 0xFD, 0x17, 0x0A, - 0xA3, 0xD6, 0x12, 0x8A, 0x04, 0x31, 0xAD, 0xD8, 0x79, 0xC6, 0x72, 0x75, 0x4C, 0x59, 0xBA, 0x35, - 0x59, 0x5D, 0x96, 0xAD, 0x04, 0xAE, 0x2F, 0x8D, 0xFE, 0xD7, 0x3D, 0x16, 0x8E, 0xB5, 0x12, 0x3F, - 0xF8, 0x97, 0xFB, 0x2B, 0x46, 0xE4, 0xCD, 0x3F, 0xBC, 0x21, 0x70, 0x05, 0xA6, 0x41, 0x6D, 0x1E, - 0x4D, 0x0D, 0xB3, 0xF6, 0xAB, 0xAE, 0x49, 0x8A, 0xAE, 0x1E, 0x92, 0xFB, 0xBC, 0xA7, 0xC4, 0x8C, - 0xD7, 0xD6, 0x70, 0x5E, 0xB4, 0x28, 0xF9, 0x82, 0xEC, 0xE6, 0x48, 0x26, 0xA2, 0xB6, 0x56, 0x64, - 0x52, 0xD5, 0xCA, 0xE8, 0x5A, 0x63, 0xFF, 0xD7, 0x4A, 0x40, 0xB7, 0x98, 0xBA, 0x4E, 0x15, 0x8C, - 0xB3, 0x00, 0x1C, 0x93, 0x3E, 0x1D, 0x69, 0x03, 0x26, 0x03, 0x75, 0x35, 0x46, 0x5A, 0x81, 0xC1, - 0xCC, 0x03, 0xC3, 0x2B, 0xFB, 0xF3, 0x1E, 0x16, 0xBF, 0xFB, 0x97, 0xAA, 0xAA, 0x81, 0xD4, 0x8B, - 0x33, 0x5D, 0x59, 0x59, 0xD5, 0x4B, 0xE0, 0xD2, 0x08, 0xA0, 0x5B, 0x8B, 0x3C, 0x3A, 0x8C, 0xFC, - 0x87, 0x52, 0xF6, 0x4D, 0xBB, 0x0F, 0x87, 0x01, 0x49, 0xD3, 0x73, 0xB8, 0x01, 0x43, 0xF7, 0x42, - 0x50, 0xB8, 0xB2, 0xC2, 0xFD, 0xE6, 0xE6, 0x66, 0x15, 0x29, 0xA1, 0x21, 0x14, 0xDB, 0x8A, 0x2B, - 0xF0, 0x49, 0xD3, 0xF1, 0x81, 0x30, 0x18, 0xD2, 0x1A, 0xC6, 0xF0, 0x25, 0xE3, 0x47, 0x5C, 0x71, - 0xF4, 0xF4, 0x22, 0xA6, 0xFC, 0x33, 0xDC, 0x95, 0x32, 0xCB, 0x1A, 0xAD, 0xA6, 0x68, 0xFA, 0x8F, - 0xD8, 0x3E, 0xCA, 0x0D, 0x76, 0xC1, 0x7A, 0xBA, 0x56, 0xA1, 0xFC, 0x9F, 0x61, 0xB9, 0x94, 0x28, - 0xD6, 0x70, 0x9C, 0x40, 0x80, 0x5A, 0xC3, 0x31, 0xC4, 0x1A, 0x41, 0x17, 0xFC, 0x26, 0x6B, 0xF9, - 0xCD, 0xFE, 0x19, 0x7E, 0x97, 0x76, 0x1E, 0x15, 0x25, 0x91, 0xAA, 0xAF, 0x50, 0x02, 0x9F, 0xDD, - 0xE9, 0xA6, 0x15, 0xB9, 0x55, 0x0A, 0x50, 0x1B, 0x46, 0x41, 0xD0, 0x8F, 0xE2, 0x83, 0x27, 0xD6, - 0x9D, 0xC5, 0x7A, 0x31, 0xC8, 0xD9, 0x5C, 0x6E, 0xB1, 0xBC, 0xB5, 0x44, 0x4F, 0xA1, 0xEC, 0x5F, - 0x4B, 0x15, 0x01, 0x3F, 0x23, 0x8B, 0x7B, 0xAC, 0xD4, 0xA5, 0x36, 0x28, 0x0F, 0x56, 0x3F, 0xD5, - 0x3C, 0xCB, 0x5F, 0xCC, 0xAE, 0x6B, 0x51, 0x9B, 0xC0, 0x38, 0x57, 0x92, 0x8B, 0x4A, 0xB2, 0xC8, - 0x13, 0x01, 0xA8, 0x58, 0xC7, 0x2E, 0xC4, 0x4D, 0x6B, 0x7A, 0x7C, 0xBF, 0x5C, 0x83, 0xC2, 0xDF, - 0xF5, 0xD5, 0x12, 0x33, 0x08, 0xC4, 0xD3, 0x95, 0x4B, 0x29, 0x5F, 0x37, 0x29, 0x8A, 0x0E, 0x62, - 0x47, 0xA3, 0x51, 0x4A, 0xC5, 0x47, 0x0C, 0x49, 0x56, 0xB2, 0x98, 0x9F, 0xC8, 0x90, 0x04, 0x8C, - 0x45, 0x3C, 0x8C, 0xB2, 0x94, 0x46, 0x99, 0xA8, 0xA4, 0x16, 0x63, 0x21, 0xCC, 0x5E, 0xFA, 0xE7, - 0x9F, 0x8B, 0xC9, 0x7E, 0x5A, 0x0B, 0x96, 0xD3, 0xEB, 0x3D, 0xBF, 0x34, 0xD9, 0xF7, 0x6B, 0x89, - 0xB9, 0x7A, 0xE9, 0xFF, 0x67, 0x4B, 0x21, 0x65, 0x4B, 0xF1, 0xB0, 0x54, 0x2E, 0x62, 0x62, 0x29, - 0xE6, 0xC9, 0x82, 0x91, 0x97, 0x7C, 0x16, 0x0D, 0x1A, 0x2B, 0x25, 0x55, 0x9E, 0x97, 0x7D, 0x95, - 0x43, 0x40, 0x59, 0x71, 0xE5, 0x35, 0x11, 0x06, 0x34, 0xE0, 0x63, 0x64, 0xF2, 0x41, 0xEB, 0xA7, - 0xD1, 0x94, 0x26, 0x87, 0x24, 0xA5, 0x06, 0x24, 0xCD, 0x65, 0xDC, 0x41, 0xA8, 0xE9, 0x04, 0xEB, - 0x76, 0x6D, 0x6E, 0x12, 0x05, 0xCE, 0x33, 0x77, 0xC4, 0xB1, 0x26, 0x03, 0xF9, 0xB2, 0xCA, 0x09, - 0xD4, 0xC6, 0xBE, 0x12, 0xA4, 0x3E, 0x52, 0x25, 0xA8, 0x61, 0x5A, 0xD0, 0x76, 0xC0, 0x35, 0x5F, - 0x26, 0x51, 0x4C, 0xC6, 0xB2, 0x07, 0x83, 0x35, 0x74, 0x0F, 0xA4, 0x66, 0x6D, 0x34, 0x91, 0x60, - 0xA9, 0x73, 0x29, 0xFC, 0x66, 0xD9, 0xC2, 0x70, 0x4B, 0x57, 0xC9, 0xB0, 0xBD, 0xF4, 0xA5, 0x35, - 0x59, 0x83, 0xE0, 0x0B, 0x6C, 0x62, 0xE0, 0x1E, 0x68, 0x64, 0xF2, 0x7B, 0x00, 0x77, 0x6B, 0xB6, - 0xA3, 0x3D, 0xD6, 0x8E, 0x6A, 0x35, 0x53, 0x55, 0xE9, 0xAE, 0x0B, 0x6D, 0x4E, 0x74, 0x23, 0x0B, - 0x4B, 0x10, 0xAA, 0x9A, 0x59, 0x0C, 0x38, 0x1B, 0x81, 0xAA, 0xBA, 0xC0, 0x11, 0xD6, 0x98, 0x66, - 0xA9, 0x23, 0xF1, 0x97, 0x1D, 0xC9, 0x13, 0xB5, 0x07, 0x95, 0xF5, 0x05, 0xD4, 0x31, 0xAB, 0x25, - 0x86, 0x30, 0xD3, 0x29, 0x13, 0xDE, 0x04, 0x03, 0x90, 0x07, 0x5A, 0xD5, 0x05, 0x14, 0xB5, 0x8E, - 0x1C, 0x4D, 0x44, 0xB8, 0x1C, 0x05, 0xF9, 0xF0, 0x6B, 0x9A, 0x0F, 0xBC, 0xB4, 0x18, 0xDD, 0x97, - 0x80, 0x50, 0xD2, 0xE6, 0xE0, 0x88, 0x8F, 0xF2, 0x21, 0xF4, 0xB2, 0x05, 0x9D, 0x02, 0x58, 0xFC, - 0xC6, 0x71, 0x3E, 0x8A, 0x27, 0xC5, 0x68, 0x42, 0xEF, 0x17, 0x78, 0x51, 0x01, 0xF5, 0xA9, 0xEE, - 0x28, 0x1B, 0xDB, 0x68, 0xCE, 0xF3, 0x41, 0x6B, 0x29, 0x7F, 0xF0, 0xFF, 0x28, 0x7F, 0xCC, 0xC7, - 0x85, 0x34, 0x71, 0x31, 0x1A, 0xB3, 0x42, 0x96, 0x61, 0x18, 0xFF, 0x90, 0x93, 0xA4, 0xD4, 0x13, - 0x97, 0x7A, 0x5A, 0xF1, 0xB3, 0xB6, 0x53, 0x98, 0x8E, 0x31, 0xAA, 0xF8, 0xE3, 0xC8, 0xF6, 0xF0, - 0xF7, 0x3C, 0xF2, 0x65, 0x6D, 0x69, 0x5A, 0xA1, 0x31, 0x82, 0x3A, 0x57, 0x37, 0xCB, 0x7E, 0x9A, - 0xFD, 0xB7, 0xAD, 0xE8, 0xD1, 0xF1, 0xE9, 0x71, 0xFF, 0xB8, 0x5C, 0x38, 0x23, 0xE7, 0x25, 0x93, - 0x8A, 0x2B, 0x5D, 0xFA, 0xB2, 0x22, 0x80, 0x02, 0x1B, 0x45, 0x01, 0x7B, 0xDD, 0xDC, 0x54, 0x7E, - 0xF1, 0xB6, 0x77, 0x71, 0x6E, 0xC7, 0x24, 0x01, 0x8F, 0x24, 0x15, 0xE6, 0xC2, 0x82, 0x44, 0xF9, - 0xE0, 0xD7, 0xC7, 0xA5, 0x72, 0x5D, 0x7E, 0x61, 0x70, 0xC4, 0xDC, 0x52, 0xA7, 0xA9, 0x7E, 0x78, - 0xE2, 0x62, 0x5D, 0x99, 0xBF, 0x04, 0x41, 0x72, 0x1A, 0x2D, 0x13, 0x55, 0x11, 0x67, 0x46, 0xE5, - 0x30, 0x2F, 0xEE, 0xB2, 0x75, 0x0D, 0xD3, 0xC8, 0xB4, 0xC4, 0x84, 0xA5, 0xE5, 0x46, 0xA5, 0x12, - 0x14, 0xFE, 0xA2, 0xB6, 0xE7, 0x8B, 0x91, 0x24, 0xB7, 0x5A, 0x73, 0xAB, 0x6F, 0x41, 0x2A, 0x3E, - 0x58, 0x04, 0x23, 0x66, 0x39, 0xDB, 0x16, 0x77, 0xA3, 0x43, 0xEE, 0x61, 0x5C, 0x7F, 0xBA, 0x35, - 0x78, 0xD2, 0x3C, 0x79, 0x61, 0x9E, 0xFC, 0xB1, 0x7B, 0x2E, 0x1C, 0x45, 0xF9, 0xDA, 0xE2, 0x98, - 0xF6, 0x10, 0x58, 0xBB, 0x6D, 0x2F, 0x7D, 0x18, 0x20, 0xD2, 0x83, 0xCB, 0x00, 0xF4, 0x63, 0x58, - 0xFF, 0x4A, 0xEE, 0x88, 0x7A, 0x09, 0xAA, 0xA2, 0xAD, 0x73, 0x54, 0xD8, 0xEE, 0xFD, 0x81, 0xA3, - 0xF2, 0xCE, 0x65, 0x18, 0x48, 0x97, 0xC3, 0x92, 0x37, 0x8B, 0x75, 0xC1, 0x61, 0x19, 0x31, 0x64, - 0x6C, 0x00, 0xE3, 0xCD, 0x5D, 0x49, 0x13, 0xD5, 0x1C, 0xB4, 0xF0, 0x1B, 0x08, 0x8A, 0x4F, 0x39, - 0xCE, 0x9A, 0x38, 0xAD, 0x62, 0x72, 0xC5, 0x23, 0xC8, 0x4A, 0x67, 0x89, 0xC0, 0x6E, 0x10, 0x0D, - 0x0D, 0x7C, 0x64, 0x9A, 0xA1, 0xB6, 0x1D, 0x3E, 0x37, 0xD7, 0xBC, 0xD9, 0x54, 0xFA, 0x4B, 0x62, - 0x79, 0xD5, 0xB0, 0x8B, 0x1C, 0x56, 0xCC, 0x75, 0x7D, 0x1F, 0xF4, 0xA3, 0x4E, 0x29, 0xAF, 0x48, - 0xA4, 0x53, 0xD1, 0x83, 0xC4, 0x86, 0xA2, 0x41, 0xBE, 0x91, 0x40, 0x44, 0x72, 0x4A, 0x33, 0x5D, - 0xC7, 0xCA, 0xD2, 0x0B, 0x28, 0x49, 0x7A, 0xB2, 0x73, 0x95, 0x49, 0x6B, 0x25, 0x06, 0xFE, 0xC8, - 0xD7, 0xF0, 0xC7, 0xA1, 0xD0, 0xA3, 0x83, 0x9B, 0x49, 0x2B, 0x83, 0xA4, 0x23, 0x64, 0x83, 0xA9, - 0x37, 0xE4, 0xBB, 0xA8, 0x2D, 0x2F, 0xCB, 0xB4, 0x16, 0x50, 0x70, 0x71, 0x83, 0xBB, 0x11, 0x30, - 0x52, 0x5A, 0xC4, 0x9E, 0x94, 0xA8, 0xC7, 0x8F, 0x10, 0x1F, 0x53, 0x4A, 0x20, 0x06, 0x20, 0xA6, - 0x40, 0xD0, 0xA7, 0x42, 0x8A, 0x54, 0xE6, 0x92, 0x53, 0x2A, 0x20, 0xCA, 0x48, 0xCD, 0xE2, 0xC1, - 0x85, 0x78, 0xD4, 0x46, 0xD6, 0x80, 0xFD, 0xDC, 0xBD, 0x73, 0x33, 0xDE, 0x90, 0x68, 0x09, 0x56, - 0x36, 0x3D, 0x9A, 0xA6, 0x52, 0x5C, 0x54, 0xC7, 0x19, 0xF8, 0xA8, 0xA1, 0x03, 0x5A, 0x23, 0x84, - 0x11, 0x1E, 0x84, 0x8A, 0x01, 0x40, 0x7F, 0x42, 0xC3, 0x1C, 0x22, 0x70, 0x08, 0x20, 0x82, 0xA0, - 0x7F, 0x49, 0x0D, 0xF7, 0x64, 0x05, 0xC9, 0xF8, 0xD8, 0x6D, 0x35, 0xF0, 0x9D, 0x66, 0x95, 0xEC, - 0x20, 0xA5, 0xBD, 0x68, 0x24, 0xFA, 0x64, 0x98, 0x1A, 0x50, 0x00, 0xAC, 0xD9, 0x01, 0xA0, 0x1E, - 0x24, 0x5E, 0x63, 0x2B, 0x3F, 0xEF, 0x04, 0x2A, 0xBB, 0x00, 0xAB, 0xBB, 0x8E, 0x87, 0x5F, 0x39, - 0x4F, 0x19, 0xA7, 0x39, 0x26, 0x00, 0x7B, 0x93, 0x68, 0x7A, 0x99, 0x30, 0x2E, 0xCE, 0x64, 0x1B, - 0x6A, 0x6C, 0xB4, 0xE4, 0xF5, 0xA9, 0x87, 0x15, 0x79, 0x3F, 0xC5, 0x8B, 0xCB, 0x0C, 0xF3, 0xBA, - 0x53, 0x79, 0x77, 0xB1, 0x86, 0x70, 0x21, 0x50, 0x66, 0x38, 0xB3, 0x29, 0x74, 0xB0, 0xFA, 0xA1, - 0x48, 0x82, 0x7A, 0x4F, 0xB7, 0x42, 0xE2, 0xC1, 0x44, 0xED, 0x81, 0xF9, 0xDC, 0xC2, 0xD8, 0xE1, - 0x94, 0x83, 0x5A, 0x0A, 0xB5, 0x02, 0x45, 0xC6, 0x95, 0xCD, 0x98, 0x35, 0x1D, 0x6A, 0x58, 0x88, - 0x61, 0xE0, 0xAF, 0xFE, 0x05, 0x0F, 0x1E, 0x1C, 0xC8, 0x55, 0x3F, 0xE1, 0x23, 0xE3, 0x7E, 0xF4, - 0x23, 0x3E, 0x3E, 0xAF, 0xF0, 0xF1, 0x79, 0x1D, 0x1F, 0xB4, 0xAA, 0x3C, 0x98, 0x0C, 0x80, 0xEC, - 0x19, 0xE1, 0x64, 0x4C, 0x13, 0x58, 0xC0, 0x43, 0x50, 0x25, 0x7F, 0x8B, 0xB3, 0x84, 0xFE, 0x98, - 0xB3, 0xDE, 0x84, 0x8D, 0xC4, 0x23, 0xFE, 0x8A, 0xD5, 0xFF, 0x82, 0x4B, 0x3C, 0x70, 0x3D, 0x97, - 0x79, 0x6D, 0x5A, 0x49, 0x28, 0x3F, 0x7E, 0x2B, 0x91, 0x7E, 0xE4, 0x42, 0x78, 0xA9, 0x38, 0xC8, - 0xDF, 0xB7, 0xF4, 0x00, 0xBC, 0x11, 0xF8, 0x29, 0x35, 0x75, 0xBC, 0x0B, 0xA5, 0xFC, 0x29, 0x30, - 0x64, 0xA8, 0xC0, 0x47, 0xDD, 0xD9, 0xDC, 0x12, 0xAE, 0x01, 0x8A, 0xF1, 0xA3, 0x29, 0xB0, 0xEA, - 0xC9, 0x02, 0xD7, 0x9E, 0x40, 0x26, 0x04, 0x91, 0xE0, 0x48, 0xC8, 0xA7, 0x8D, 0x2F, 0x07, 0x9B, - 0x37, 0x35, 0xC8, 0x43, 0x2E, 0xFC, 0x98, 0x2E, 0x0C, 0x36, 0x6F, 0xFE, 0x6D, 0x36, 0xC6, 0xCC, - 0x5A, 0x76, 0xA4, 0x96, 0x4C, 0xF6, 0xF4, 0x0B, 0xBF, 0x71, 0x09, 0x48, 0x5D, 0x49, 0x78, 0x45, - 0x34, 0x03, 0x6B, 0x43, 0x61, 0xE1, 0x07, 0xFF, 0x47, 0x09, 0xF8, 0x91, 0x9E, 0x07, 0xCE, 0xBD, - 0xE6, 0x3D, 0x5E, 0x2F, 0x3E, 0x85, 0xE9, 0x56, 0xE9, 0xC1, 0x4A, 0xC7, 0xEF, 0x53, 0x3A, 0x76, - 0x59, 0xA2, 0x14, 0x4A, 0x14, 0x59, 0x88, 0x1A, 0x6A, 0x50, 0x0E, 0x51, 0x98, 0x89, 0x17, 0xCD, - 0x81, 0x02, 0x9B, 0x73, 0x34, 0x5B, 0x3A, 0x02, 0x0F, 0xF4, 0xF5, 0x45, 0xEE, 0xFC, 0x74, 0x76, - 0x7A, 0x22, 0x44, 0x7C, 0xA5, 0x62, 0x22, 0xD0, 0xAA, 0x2E, 0x2C, 0x2F, 0xCF, 0x9C, 0x89, 0xE4, - 0xA1, 0x28, 0x75, 0x30, 0x31, 0x28, 0x87, 0xFE, 0x74, 0x31, 0xFC, 0x0A, 0x71, 0xD6, 0xD0, 0xCF, - 0x52, 0x48, 0x58, 0x5B, 0x36, 0xA2, 0xF7, 0xFB, 0x97, 0xF6, 0xAE, 0xDD, 0x84, 0xBA, 0x00, 0xB4, - 0x0A, 0x69, 0x19, 0xEE, 0x7D, 0xFE, 0xB7, 0x90, 0xB7, 0xFF, 0x1E, 0x32, 0x83, 0xA8, 0x95, 0x42, - 0x58, 0x2A, 0xF0, 0xAB, 0xB8, 0x93, 0x24, 0x9A, 0x4A, 0xB4, 0xE3, 0x24, 0xC1, 0x4B, 0xE9, 0x43, - 0x85, 0xA2, 0x0D, 0x61, 0x31, 0xA5, 0x89, 0xE6, 0x47, 0x34, 0xD5, 0x78, 0x24, 0xB4, 0x34, 0x8B, - 0x63, 0x68, 0x5C, 0x56, 0xF4, 0x61, 0xEB, 0xC5, 0xEB, 0xCB, 0xFB, 0x8C, 0x66, 0xD4, 0xCF, 0x97, - 0x69, 0x52, 0xD1, 0x0B, 0x56, 0x50, 0xDF, 0x10, 0xEE, 0x7E, 0xB9, 0xC9, 0xEB, 0xA9, 0x8C, 0x73, - 0x8C, 0xA2, 0x1B, 0x2D, 0x35, 0x07, 0xE9, 0x26, 0x40, 0xD5, 0xE5, 0x59, 0x10, 0xCC, 0xDB, 0x2B, - 0xB4, 0xA0, 0xF1, 0x8A, 0x44, 0x24, 0x9F, 0xCB, 0x67, 0x7F, 0xE4, 0xC9, 0xA9, 0xE2, 0x82, 0x50, - 0xF2, 0x54, 0xA9, 0x36, 0xAD, 0x0D, 0x63, 0x83, 0x6A, 0x8C, 0xA7, 0x82, 0x70, 0x0F, 0xAF, 0x51, - 0xE9, 0xC2, 0x2C, 0x6A, 0x29, 0xDC, 0xDE, 0x46, 0x5F, 0xCB, 0x6D, 0xE9, 0x89, 0x7C, 0x2A, 0x25, - 0xE3, 0xAE, 0xAE, 0x63, 0x55, 0x45, 0xB1, 0x3E, 0x25, 0x61, 0x5A, 0x26, 0x5B, 0x54, 0x06, 0x26, - 0x77, 0x0B, 0x70, 0x9B, 0x06, 0x29, 0x1C, 0xBD, 0x7E, 0x7F, 0xCE, 0x46, 0xD1, 0xCE, 0x11, 0x80, - 0x69, 0xC5, 0x3E, 0x93, 0xD7, 0xE0, 0x24, 0xCC, 0x73, 0x07, 0x32, 0xE9, 0x4A, 0x03, 0x0E, 0xA9, - 0x98, 0x44, 0xFE, 0x81, 0x7E, 0xA0, 0x3B, 0x3A, 0xFC, 0xBB, 0x09, 0x35, 0x47, 0xCD, 0xA5, 0xD0, - 0xA4, 0xFA, 0x74, 0x70, 0xF5, 0x06, 0xC2, 0x53, 0x0C, 0xA5, 0x01, 0x17, 0x50, 0x34, 0xD7, 0x74, - 0x7C, 0x7A, 0x7D, 0x0C, 0x29, 0xC8, 0x7F, 0x21, 0x37, 0x66, 0xBB, 0xAA, 0x6C, 0xB8, 0xF3, 0xEA, - 0x75, 0x56, 0x2E, 0x03, 0x7A, 0x61, 0x8C, 0x58, 0x0F, 0x29, 0x7E, 0xFB, 0x7B, 0xF4, 0x9E, 0x8D, - 0x15, 0xD2, 0x6A, 0x5D, 0x6F, 0xCE, 0x76, 0x90, 0x67, 0x89, 0xD5, 0x43, 0x2C, 0x70, 0x97, 0x1F, - 0x29, 0x59, 0x95, 0x35, 0xDC, 0xF6, 0x48, 0x10, 0xE0, 0xC7, 0x5A, 0x03, 0x1B, 0x6A, 0x22, 0xB2, - 0xD4, 0x42, 0x22, 0x29, 0x08, 0x90, 0xD2, 0x3E, 0x84, 0x39, 0xD3, 0x92, 0x65, 0x86, 0xB2, 0xA1, - 0xBC, 0xFF, 0xC5, 0x9A, 0xA3, 0x64, 0x46, 0xE8, 0xCE, 0xF9, 0x6C, 0x73, 0x53, 0xD8, 0x85, 0x99, - 0x18, 0x05, 0x52, 0x8A, 0x01, 0x1C, 0x9A, 0x7D, 0x68, 0x2D, 0x8C, 0xB2, 0x90, 0x58, 0xAB, 0x3D, - 0xD2, 0xB6, 0x51, 0x55, 0x03, 0x54, 0x7C, 0x46, 0x01, 0x03, 0xCE, 0xB2, 0x24, 0x80, 0xA8, 0x8B, - 0x39, 0xBA, 0xB2, 0x2D, 0xC5, 0xBA, 0xD0, 0x84, 0x0E, 0xEC, 0x67, 0xC8, 0x12, 0x95, 0x97, 0xAD, - 0xA2, 0x27, 0x12, 0xC5, 0x77, 0x95, 0x9E, 0xC8, 0x6F, 0xE5, 0x84, 0xAA, 0xC8, 0x77, 0x88, 0x2F, - 0x13, 0x5C, 0xD4, 0xD1, 0x13, 0xA0, 0x24, 0x83, 0x52, 0x34, 0x60, 0x2A, 0x2C, 0x37, 0xEE, 0xEB, - 0xD3, 0xE9, 0xB4, 0x8E, 0xDF, 0x6A, 0xEB, 0x70, 0x82, 0xB2, 0x02, 0x5F, 0x5F, 0xC7, 0x21, 0x47, - 0x15, 0x58, 0xF8, 0x6E, 0xE1, 0xAC, 0xBA, 0xE8, 0x42, 0x7F, 0x2B, 0xDE, 0xD4, 0xAA, 0xD2, 0x59, - 0xE1, 0x73, 0x79, 0xDB, 0x7B, 0x3B, 0x2B, 0x20, 0x32, 0xC4, 0xAF, 0xB2, 0x90, 0x69, 0x20, 0x0D, - 0x3B, 0xE5, 0x46, 0x56, 0x25, 0x85, 0x65, 0x5C, 0xB0, 0xE3, 0x2C, 0x9D, 0x18, 0x33, 0x60, 0xDD, - 0x11, 0x96, 0xD2, 0x95, 0x43, 0x2D, 0x65, 0xB7, 0x0E, 0xB7, 0x0A, 0xFB, 0x70, 0x30, 0x83, 0x94, - 0x79, 0xFB, 0xF3, 0x4F, 0x39, 0x5B, 0xDE, 0xF6, 0x92, 0x62, 0x71, 0xE1, 0xF3, 0xFC, 0xA9, 0x35, - 0xAF, 0x69, 0xA5, 0xD1, 0xAF, 0xC4, 0x97, 0xBD, 0x46, 0xFE, 0x19, 0x3B, 0xFF, 0x9C, 0xAD, 0x81, - 0xB1, 0x43, 0x23, 0x2A, 0xDC, 0x4C, 0x8C, 0xEA, 0x2F, 0x34, 0xE6, 0x63, 0x79, 0x29, 0xBF, 0x2D, - 0xA0, 0x54, 0xA9, 0xD3, 0x68, 0x78, 0x3E, 0xFF, 0x9A, 0x42, 0x19, 0x1D, 0x65, 0xFE, 0x28, 0x20, - 0x09, 0xC5, 0x82, 0xA3, 0x41, 0xBE, 0x92, 0xFB, 0x46, 0xC0, 0x86, 0x69, 0x03, 0x93, 0x6D, 0xCB, - 0xDE, 0xB2, 0x77, 0x71, 0x64, 0x7F, 0x4D, 0xF7, 0x57, 0x4F, 0xD8, 0x5F, 0x34, 0x69, 0x58, 0x0B, - 0xE7, 0xB5, 0xAB, 0x8A, 0x4D, 0x6A, 0x83, 0xFB, 0xC4, 0xA7, 0x70, 0x3D, 0x6F, 0xB3, 0xCC, 0xB6, - 0x1A, 0xE4, 0x5F, 0x60, 0xD4, 0x31, 0xBA, 0x95, 0x2F, 0x92, 0xF4, 0x81, 0x7B, 0x18, 0x5B, 0x17, - 0x54, 0x26, 0x70, 0x49, 0xD5, 0x87, 0x34, 0xB9, 0xD3, 0x9C, 0x2F, 0x39, 0xC3, 0xB7, 0x3C, 0xA8, - 0x03, 0xE4, 0x37, 0x9C, 0x72, 0x39, 0xB0, 0xBF, 0x07, 0x5D, 0x33, 0x2A, 0x41, 0x79, 0xB1, 0x26, - 0x9B, 0xE6, 0x7C, 0x02, 0x82, 0x01, 0x70, 0xB1, 0xA3, 0x48, 0xCD, 0x2B, 0xCB, 0x98, 0x9B, 0x57, - 0x96, 0x54, 0xE2, 0x5F, 0x59, 0xCC, 0xDB, 0x9F, 0xFC, 0xDB, 0x4C, 0xF9, 0x7F, 0x5B, 0x28, 0x36, - 0x32, 0xF9, 0xE1, 0x09, 0xF7, 0x56, 0x3F, 0x45, 0xAD, 0x47, 0x51, 0xBB, 0xF7, 0xFF, 0x17, 0x53, - 0xE8, 0x9D, 0x36, 0x92, 0x29, 0x00, 0x00 -}; - -#define SPIFFS_MAXLENGTH_FILEPATH 32 -const char *excludeListFile = "/.exclude.files"; - -typedef struct ExcludeListS { - char *item; - ExcludeListS *next; -} ExcludeList; - -static ExcludeList *excludes = NULL; - -static bool matchWild(const char *pattern, const char *testee) { - const char *nxPat = NULL, *nxTst = NULL; - - while (*testee) { - if (( *pattern == '?' ) || (*pattern == *testee)){ - pattern++;testee++; - continue; - } - if (*pattern=='*'){ - nxPat=pattern++; nxTst=testee; - continue; - } - if (nxPat){ - pattern = nxPat+1; testee=++nxTst; - continue; - } - return false; - } - while (*pattern=='*'){pattern++;} - return (*pattern == 0); -} - -static bool addExclude(const char *item){ - size_t len = strlen(item); - if(!len){ - return false; - } - ExcludeList *e = (ExcludeList *)malloc(sizeof(ExcludeList)); - if(!e){ - return false; - } - e->item = (char *)malloc(len+1); - if(!e->item){ - free(e); - return false; - } - memcpy(e->item, item, len+1); - e->next = excludes; - excludes = e; - return true; -} - -static void loadExcludeList(fs::FS &_fs, const char *filename){ - static char linebuf[SPIFFS_MAXLENGTH_FILEPATH]; - fs::File excludeFile=_fs.open(filename, "r"); - if(!excludeFile){ - //addExclude("/*.js.gz"); - return; - } -#ifdef ESP32 - if(excludeFile.isDirectory()){ - excludeFile.close(); - return; - } -#endif - if (excludeFile.size() > 0){ - uint8_t idx; - bool isOverflowed = false; - while (excludeFile.available()){ - linebuf[0] = '\0'; - idx = 0; - int lastChar; - do { - lastChar = excludeFile.read(); - if(lastChar != '\r'){ - linebuf[idx++] = (char) lastChar; - } - } while ((lastChar >= 0) && (lastChar != '\n') && (idx < SPIFFS_MAXLENGTH_FILEPATH)); - - if(isOverflowed){ - isOverflowed = (lastChar != '\n'); - continue; - } - isOverflowed = (idx >= SPIFFS_MAXLENGTH_FILEPATH); - linebuf[idx-1] = '\0'; - if(!addExclude(linebuf)){ - excludeFile.close(); - return; - } - } - } - excludeFile.close(); -} - -static bool isExcluded(fs::FS &_fs, const char *filename) { - if(excludes == NULL){ - loadExcludeList(_fs, excludeListFile); - } - ExcludeList *e = excludes; - while(e){ - if (matchWild(e->item, filename)){ - return true; - } - e = e->next; - } - return false; -} - -// WEB HANDLER IMPLEMENTATION - -#ifdef ESP32 -SPIFFSEditor::SPIFFSEditor(const fs::FS& fs, const String& username, const String& password) -#else -SPIFFSEditor::SPIFFSEditor(const String& username, const String& password, const fs::FS& fs) -#endif -:_fs(fs) -,_username(username) -,_password(password) -,_authenticated(false) -,_startTime(0) -{} - -bool SPIFFSEditor::canHandle(AsyncWebServerRequest *request){ - if(request->url().equalsIgnoreCase("/edit")){ - if(request->method() == HTTP_GET){ - if(request->hasParam("list")) - return true; - if(request->hasParam("edit")){ - request->_tempFile = _fs.open(request->arg("edit"), "r"); - if(!request->_tempFile){ - return false; - } -#ifdef ESP32 - if(request->_tempFile.isDirectory()){ - request->_tempFile.close(); - return false; - } -#endif - } - if(request->hasParam("download")){ - request->_tempFile = _fs.open(request->arg("download"), "r"); - if(!request->_tempFile){ - return false; - } -#ifdef ESP32 - if(request->_tempFile.isDirectory()){ - request->_tempFile.close(); - return false; - } -#endif - } - request->addInterestingHeader("If-Modified-Since"); - return true; - } - else if(request->method() == HTTP_POST) - return true; - else if(request->method() == HTTP_DELETE) - return true; - else if(request->method() == HTTP_PUT) - return true; - - } - return false; -} - - -void SPIFFSEditor::handleRequest(AsyncWebServerRequest *request){ - if(_username.length() && _password.length() && !request->authenticate(_username.c_str(), _password.c_str())) - return request->requestAuthentication(); - - if(request->method() == HTTP_GET){ - if(request->hasParam("list")){ - String path = request->getParam("list")->value(); -#ifdef ESP32 - File dir = _fs.open(path); -#else - Dir dir = _fs.openDir(path); -#endif - path = String(); - String output = "["; -#ifdef ESP32 - File entry = dir.openNextFile(); - while(entry){ -#else - while(dir.next()){ - fs::File entry = dir.openFile("r"); -#endif - if (isExcluded(_fs, entry.name())) { -#ifdef ESP32 - entry = dir.openNextFile(); -#endif - continue; - } - if (output != "[") output += ','; - output += "{\"type\":\""; - output += "file"; - output += "\",\"name\":\""; - output += String(entry.name()); - output += "\",\"size\":"; - output += String(entry.size()); - output += "}"; -#ifdef ESP32 - entry = dir.openNextFile(); -#else - entry.close(); -#endif - } -#ifdef ESP32 - dir.close(); -#endif - output += "]"; - request->send(200, "application/json", output); - output = String(); - } - else if(request->hasParam("edit") || request->hasParam("download")){ - request->send(request->_tempFile, request->_tempFile.name(), String(), request->hasParam("download")); - } - else { - const char * buildTime = __DATE__ " " __TIME__ " GMT"; - if (request->header("If-Modified-Since").equals(buildTime)) { - request->send(304); - } else { - AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", edit_htm_gz, edit_htm_gz_len); - response->addHeader("Content-Encoding", "gzip"); - response->addHeader("Last-Modified", buildTime); - request->send(response); - } - } - } else if(request->method() == HTTP_DELETE){ - if(request->hasParam("path", true)){ - _fs.remove(request->getParam("path", true)->value()); - request->send(200, "", "DELETE: "+request->getParam("path", true)->value()); - } else - request->send(404); - } else if(request->method() == HTTP_POST){ - if(request->hasParam("data", true, true) && _fs.exists(request->getParam("data", true, true)->value())) - request->send(200, "", "UPLOADED: "+request->getParam("data", true, true)->value()); - else - request->send(500); - } else if(request->method() == HTTP_PUT){ - if(request->hasParam("path", true)){ - String filename = request->getParam("path", true)->value(); - if(_fs.exists(filename)){ - request->send(200); - } else { - fs::File f = _fs.open(filename, "w"); - if(f){ - f.write((uint8_t)0x00); - f.close(); - request->send(200, "", "CREATE: "+filename); - } else { - request->send(500); - } - } - } else - request->send(400); - } -} - -void SPIFFSEditor::handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){ - if(!index){ - if(!_username.length() || request->authenticate(_username.c_str(),_password.c_str())){ - _authenticated = true; - request->_tempFile = _fs.open(filename, "w"); - _startTime = millis(); - } - } - if(_authenticated && request->_tempFile){ - if(len){ - request->_tempFile.write(data,len); - } - if(final){ - request->_tempFile.close(); - } - } -} diff --git a/lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.h b/lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.h deleted file mode 100644 index 3586429e1..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/SPIFFSEditor.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SPIFFSEditor_H_ -#define SPIFFSEditor_H_ -#include - -class SPIFFSEditor: public AsyncWebHandler { - private: - fs::FS _fs; - String _username; - String _password; - bool _authenticated; - uint32_t _startTime; - public: -#ifdef ESP32 - SPIFFSEditor(const fs::FS& fs, const String& username=String(), const String& password=String()); -#else - SPIFFSEditor(const String& username=String(), const String& password=String(), const fs::FS& fs=SPIFFS); -#endif - virtual bool canHandle(AsyncWebServerRequest *request) override final; - virtual void handleRequest(AsyncWebServerRequest *request) override final; - virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final; - virtual bool isRequestHandlerTrivial() override final {return false;} -}; - -#endif diff --git a/lib/libesp32/ESPAsyncWebServer/src/StringArray.h b/lib/libesp32/ESPAsyncWebServer/src/StringArray.h deleted file mode 100644 index 801643967..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/StringArray.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - Asynchronous WebServer library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#ifndef STRINGARRAY_H_ -#define STRINGARRAY_H_ - -#include "stddef.h" -#include "WString.h" - -template -class AsyncLinkedListNode { - T _value; - public: - AsyncLinkedListNode* next; - AsyncLinkedListNode(const T val): _value(val), next(nullptr) {} - ~AsyncLinkedListNode(){} - const T& value() const { return _value; }; - T& value(){ return _value; } -}; - -template class Item = AsyncLinkedListNode> -class AsyncLinkedList { - public: - typedef Item ItemType; - typedef std::function OnRemove; - typedef std::function Predicate; - private: - ItemType* _root; - OnRemove _onRemove; - - class Iterator { - ItemType* _node; - public: - Iterator(ItemType* current = nullptr) : _node(current) {} - Iterator(const Iterator& i) : _node(i._node) {} - Iterator& operator ++() { _node = _node->next; return *this; } - bool operator != (const Iterator& i) const { return _node != i._node; } - const T& operator * () const { return _node->value(); } - const T* operator -> () const { return &_node->value(); } - }; - - public: - typedef const Iterator ConstIterator; - ConstIterator begin() const { return ConstIterator(_root); } - ConstIterator end() const { return ConstIterator(nullptr); } - - AsyncLinkedList(OnRemove onRemove) : _root(nullptr), _onRemove(onRemove) {} - ~AsyncLinkedList(){} - void add(const T& t){ - auto it = new ItemType(t); - if(!_root){ - _root = it; - } else { - auto i = _root; - while(i->next) i = i->next; - i->next = it; - } - } - T& front() const { - return _root->value(); - } - - bool isEmpty() const { - return _root == nullptr; - } - size_t length() const { - size_t i = 0; - auto it = _root; - while(it){ - i++; - it = it->next; - } - return i; - } - size_t count_if(Predicate predicate) const { - size_t i = 0; - auto it = _root; - while(it){ - if (!predicate){ - i++; - } - else if (predicate(it->value())) { - i++; - } - it = it->next; - } - return i; - } - const T* nth(size_t N) const { - size_t i = 0; - auto it = _root; - while(it){ - if(i++ == N) - return &(it->value()); - it = it->next; - } - return nullptr; - } - bool remove(const T& t){ - auto it = _root; - auto pit = _root; - while(it){ - if(it->value() == t){ - if(it == _root){ - _root = _root->next; - } else { - pit->next = it->next; - } - - if (_onRemove) { - _onRemove(it->value()); - } - - delete it; - return true; - } - pit = it; - it = it->next; - } - return false; - } - bool remove_first(Predicate predicate){ - auto it = _root; - auto pit = _root; - while(it){ - if(predicate(it->value())){ - if(it == _root){ - _root = _root->next; - } else { - pit->next = it->next; - } - if (_onRemove) { - _onRemove(it->value()); - } - delete it; - return true; - } - pit = it; - it = it->next; - } - return false; - } - - void free(){ - while(_root != nullptr){ - auto it = _root; - _root = _root->next; - if (_onRemove) { - _onRemove(it->value()); - } - delete it; - } - _root = nullptr; - } -}; - - -class StringArray : public AsyncLinkedList { -public: - - StringArray() : AsyncLinkedList(nullptr) {} - - bool containsIgnoreCase(const String& str){ - for (const auto& s : *this) { - if (str.equalsIgnoreCase(s)) { - return true; - } - } - return false; - } -}; - - - - -#endif /* STRINGARRAY_H_ */ diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.cpp b/lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.cpp deleted file mode 100644 index 45246a196..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* - Asynchronous WebServer library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#include "WebAuthentication.h" -#include -#ifdef ESP32 -#include "mbedtls/md5.h" -#else -#include "md5.h" -#endif - - -// Basic Auth hash = base64("username:password") - -bool checkBasicAuthentication(const char * hash, const char * username, const char * password){ - if(username == NULL || password == NULL || hash == NULL) - return false; - - size_t toencodeLen = strlen(username)+strlen(password)+1; - size_t encodedLen = base64_encode_expected_len(toencodeLen); - if(strlen(hash) != encodedLen) - return false; - - char *toencode = new char[toencodeLen+1]; - if(toencode == NULL){ - return false; - } - char *encoded = new char[base64_encode_expected_len(toencodeLen)+1]; - if(encoded == NULL){ - delete[] toencode; - return false; - } - sprintf(toencode, "%s:%s", username, password); - if(base64_encode_chars(toencode, toencodeLen, encoded) > 0 && memcmp(hash, encoded, encodedLen) == 0){ - delete[] toencode; - delete[] encoded; - return true; - } - delete[] toencode; - delete[] encoded; - return false; -} - -static bool getMD5(uint8_t * data, uint16_t len, char * output){//33 bytes or more -#ifdef ESP32 - mbedtls_md5_context _ctx; -#else - md5_context_t _ctx; -#endif - uint8_t i; - uint8_t * _buf = (uint8_t*)malloc(16); - if(_buf == NULL) - return false; - memset(_buf, 0x00, 16); -#ifdef ESP32 - mbedtls_md5_init(&_ctx); - mbedtls_md5_starts_ret(&_ctx); - mbedtls_md5_update_ret(&_ctx, data, len); - mbedtls_md5_finish_ret(&_ctx, _buf); -#else - MD5Init(&_ctx); - MD5Update(&_ctx, data, len); - MD5Final(_buf, &_ctx); -#endif - for(i = 0; i < 16; i++) { - sprintf(output + (i * 2), "%02x", _buf[i]); - } - free(_buf); - return true; -} - -static String genRandomMD5(){ -#ifdef ESP8266 - uint32_t r = RANDOM_REG32; -#else - uint32_t r = rand(); -#endif - char * out = (char*)malloc(33); - if(out == NULL || !getMD5((uint8_t*)(&r), 4, out)) - return ""; - String res = String(out); - free(out); - return res; -} - -static String stringMD5(const String& in){ - char * out = (char*)malloc(33); - if(out == NULL || !getMD5((uint8_t*)(in.c_str()), in.length(), out)) - return ""; - String res = String(out); - free(out); - return res; -} - -String generateDigestHash(const char * username, const char * password, const char * realm){ - if(username == NULL || password == NULL || realm == NULL){ - return ""; - } - char * out = (char*)malloc(33); - String res = String(username); - res.concat(":"); - res.concat(realm); - res.concat(":"); - String in = res; - in.concat(password); - if(out == NULL || !getMD5((uint8_t*)(in.c_str()), in.length(), out)) - return ""; - res.concat(out); - free(out); - return res; -} - -String requestDigestAuthentication(const char * realm){ - String header = "realm=\""; - if(realm == NULL) - header.concat("asyncesp"); - else - header.concat(realm); - header.concat( "\", qop=\"auth\", nonce=\""); - header.concat(genRandomMD5()); - header.concat("\", opaque=\""); - header.concat(genRandomMD5()); - header.concat("\""); - return header; -} - -bool checkDigestAuthentication(const char * header, const char * method, const char * username, const char * password, const char * realm, bool passwordIsHash, const char * nonce, const char * opaque, const char * uri){ - if(username == NULL || password == NULL || header == NULL || method == NULL){ - //os_printf("AUTH FAIL: missing requred fields\n"); - return false; - } - - String myHeader = String(header); - int nextBreak = myHeader.indexOf(","); - if(nextBreak < 0){ - //os_printf("AUTH FAIL: no variables\n"); - return false; - } - - String myUsername = String(); - String myRealm = String(); - String myNonce = String(); - String myUri = String(); - String myResponse = String(); - String myQop = String(); - String myNc = String(); - String myCnonce = String(); - - myHeader += ", "; - do { - String avLine = myHeader.substring(0, nextBreak); - avLine.trim(); - myHeader = myHeader.substring(nextBreak+1); - nextBreak = myHeader.indexOf(","); - - int eqSign = avLine.indexOf("="); - if(eqSign < 0){ - //os_printf("AUTH FAIL: no = sign\n"); - return false; - } - String varName = avLine.substring(0, eqSign); - avLine = avLine.substring(eqSign + 1); - if(avLine.startsWith("\"")){ - avLine = avLine.substring(1, avLine.length() - 1); - } - - if(varName.equals("username")){ - if(!avLine.equals(username)){ - //os_printf("AUTH FAIL: username\n"); - return false; - } - myUsername = avLine; - } else if(varName.equals("realm")){ - if(realm != NULL && !avLine.equals(realm)){ - //os_printf("AUTH FAIL: realm\n"); - return false; - } - myRealm = avLine; - } else if(varName.equals("nonce")){ - if(nonce != NULL && !avLine.equals(nonce)){ - //os_printf("AUTH FAIL: nonce\n"); - return false; - } - myNonce = avLine; - } else if(varName.equals("opaque")){ - if(opaque != NULL && !avLine.equals(opaque)){ - //os_printf("AUTH FAIL: opaque\n"); - return false; - } - } else if(varName.equals("uri")){ - if(uri != NULL && !avLine.equals(uri)){ - //os_printf("AUTH FAIL: uri\n"); - return false; - } - myUri = avLine; - } else if(varName.equals("response")){ - myResponse = avLine; - } else if(varName.equals("qop")){ - myQop = avLine; - } else if(varName.equals("nc")){ - myNc = avLine; - } else if(varName.equals("cnonce")){ - myCnonce = avLine; - } - } while(nextBreak > 0); - - String ha1 = (passwordIsHash) ? String(password) : stringMD5(myUsername + ":" + myRealm + ":" + String(password)); - String ha2 = String(method) + ":" + myUri; - String response = ha1 + ":" + myNonce + ":" + myNc + ":" + myCnonce + ":" + myQop + ":" + stringMD5(ha2); - - if(myResponse.equals(stringMD5(response))){ - //os_printf("AUTH SUCCESS\n"); - return true; - } - - //os_printf("AUTH FAIL: password\n"); - return false; -} diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.h b/lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.h deleted file mode 100644 index ff68265d9..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/WebAuthentication.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - Asynchronous WebServer library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef WEB_AUTHENTICATION_H_ -#define WEB_AUTHENTICATION_H_ - -#include "Arduino.h" - -bool checkBasicAuthentication(const char * header, const char * username, const char * password); -String requestDigestAuthentication(const char * realm); -bool checkDigestAuthentication(const char * header, const char * method, const char * username, const char * password, const char * realm, bool passwordIsHash, const char * nonce, const char * opaque, const char * uri); - -//for storing hashed versions on the device that can be authenticated against -String generateDigestHash(const char * username, const char * password, const char * realm); - -#endif diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebHandlerImpl.h b/lib/libesp32/ESPAsyncWebServer/src/WebHandlerImpl.h deleted file mode 100644 index 9b7ba1b04..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/WebHandlerImpl.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - Asynchronous WebServer library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#ifndef ASYNCWEBSERVERHANDLERIMPL_H_ -#define ASYNCWEBSERVERHANDLERIMPL_H_ - -#include -#ifdef ASYNCWEBSERVER_REGEX -#include -#endif - -#include "stddef.h" -#include - -class AsyncStaticWebHandler: public AsyncWebHandler { - using File = fs::File; - using FS = fs::FS; - private: - bool _getFile(AsyncWebServerRequest *request); - bool _fileExists(AsyncWebServerRequest *request, const String& path); - uint8_t _countBits(const uint8_t value) const; - protected: - FS _fs; - String _uri; - String _path; - String _default_file; - String _cache_control; - String _last_modified; - AwsTemplateProcessor _callback; - bool _isDir; - bool _gzipFirst; - uint8_t _gzipStats; - public: - AsyncStaticWebHandler(const char* uri, FS& fs, const char* path, const char* cache_control); - virtual bool canHandle(AsyncWebServerRequest *request) override final; - virtual void handleRequest(AsyncWebServerRequest *request) override final; - AsyncStaticWebHandler& setIsDir(bool isDir); - AsyncStaticWebHandler& setDefaultFile(const char* filename); - AsyncStaticWebHandler& setCacheControl(const char* cache_control); - AsyncStaticWebHandler& setLastModified(const char* last_modified); - AsyncStaticWebHandler& setLastModified(struct tm* last_modified); - #ifdef ESP8266 - AsyncStaticWebHandler& setLastModified(time_t last_modified); - AsyncStaticWebHandler& setLastModified(); //sets to current time. Make sure sntp is runing and time is updated - #endif - AsyncStaticWebHandler& setTemplateProcessor(AwsTemplateProcessor newCallback) {_callback = newCallback; return *this;} -}; - -class AsyncCallbackWebHandler: public AsyncWebHandler { - private: - protected: - String _uri; - WebRequestMethodComposite _method; - ArRequestHandlerFunction _onRequest; - ArUploadHandlerFunction _onUpload; - ArBodyHandlerFunction _onBody; - bool _isRegex; - public: - AsyncCallbackWebHandler() : _uri(), _method(HTTP_ANY), _onRequest(NULL), _onUpload(NULL), _onBody(NULL), _isRegex(false) {} - void setUri(const String& uri){ - _uri = uri; - _isRegex = uri.startsWith("^") && uri.endsWith("$"); - } - void setMethod(WebRequestMethodComposite method){ _method = method; } - void onRequest(ArRequestHandlerFunction fn){ _onRequest = fn; } - void onUpload(ArUploadHandlerFunction fn){ _onUpload = fn; } - void onBody(ArBodyHandlerFunction fn){ _onBody = fn; } - - virtual bool canHandle(AsyncWebServerRequest *request) override final{ - - if(!_onRequest) - return false; - - if(!(_method & request->method())) - return false; - -#ifdef ASYNCWEBSERVER_REGEX - if (_isRegex) { - std::regex pattern(_uri.c_str()); - std::smatch matches; - std::string s(request->url().c_str()); - if(std::regex_search(s, matches, pattern)) { - for (size_t i = 1; i < matches.size(); ++i) { // start from 1 - request->_addPathParam(matches[i].str().c_str()); - } - } else { - return false; - } - } else -#endif - if (_uri.length() && _uri.startsWith("/*.")) { - String uriTemplate = String (_uri); - uriTemplate = uriTemplate.substring(uriTemplate.lastIndexOf(".")); - if (!request->url().endsWith(uriTemplate)) - return false; - } - else - if (_uri.length() && _uri.endsWith("*")) { - String uriTemplate = String(_uri); - uriTemplate = uriTemplate.substring(0, uriTemplate.length() - 1); - if (!request->url().startsWith(uriTemplate)) - return false; - } - else if(_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri+"/"))) - return false; - - request->addInterestingHeader("ANY"); - return true; - } - - virtual void handleRequest(AsyncWebServerRequest *request) override final { - if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str())) - return request->requestAuthentication(); - if(_onRequest) - _onRequest(request); - else - request->send(500); - } - virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final { - if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str())) - return request->requestAuthentication(); - if(_onUpload) - _onUpload(request, filename, index, data, len, final); - } - virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final { - if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str())) - return request->requestAuthentication(); - if(_onBody) - _onBody(request, data, len, index, total); - } - virtual bool isRequestHandlerTrivial() override final {return _onRequest ? false : true;} -}; - -#endif /* ASYNCWEBSERVERHANDLERIMPL_H_ */ diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebHandlers.cpp b/lib/libesp32/ESPAsyncWebServer/src/WebHandlers.cpp deleted file mode 100644 index 1f435e68a..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/WebHandlers.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* - Asynchronous WebServer library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#include "ESPAsyncWebServer.h" -#include "WebHandlerImpl.h" - -AsyncStaticWebHandler::AsyncStaticWebHandler(const char* uri, FS& fs, const char* path, const char* cache_control) - : _fs(fs), _uri(uri), _path(path), _default_file("index.htm"), _cache_control(cache_control), _last_modified(""), _callback(nullptr) -{ - // Ensure leading '/' - if (_uri.length() == 0 || _uri[0] != '/') _uri = "/" + _uri; - if (_path.length() == 0 || _path[0] != '/') _path = "/" + _path; - - // If path ends with '/' we assume a hint that this is a directory to improve performance. - // However - if it does not end with '/' we, can't assume a file, path can still be a directory. - _isDir = _path[_path.length()-1] == '/'; - - // Remove the trailing '/' so we can handle default file - // Notice that root will be "" not "/" - if (_uri[_uri.length()-1] == '/') _uri = _uri.substring(0, _uri.length()-1); - if (_path[_path.length()-1] == '/') _path = _path.substring(0, _path.length()-1); - - // Reset stats - _gzipFirst = false; - _gzipStats = 0xF8; -} - -AsyncStaticWebHandler& AsyncStaticWebHandler::setIsDir(bool isDir){ - _isDir = isDir; - return *this; -} - -AsyncStaticWebHandler& AsyncStaticWebHandler::setDefaultFile(const char* filename){ - _default_file = String(filename); - return *this; -} - -AsyncStaticWebHandler& AsyncStaticWebHandler::setCacheControl(const char* cache_control){ - _cache_control = String(cache_control); - return *this; -} - -AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(const char* last_modified){ - _last_modified = String(last_modified); - return *this; -} - -AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(struct tm* last_modified){ - char result[30]; - strftime (result,30,"%a, %d %b %Y %H:%M:%S %Z", last_modified); - return setLastModified((const char *)result); -} - -#ifdef ESP8266 -AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(time_t last_modified){ - return setLastModified((struct tm *)gmtime(&last_modified)); -} - -AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(){ - time_t last_modified; - if(time(&last_modified) == 0) //time is not yet set - return *this; - return setLastModified(last_modified); -} -#endif -bool AsyncStaticWebHandler::canHandle(AsyncWebServerRequest *request){ - if(request->method() != HTTP_GET - || !request->url().startsWith(_uri) - || !request->isExpectedRequestedConnType(RCT_DEFAULT, RCT_HTTP) - ){ - return false; - } - if (_getFile(request)) { - // We interested in "If-Modified-Since" header to check if file was modified - if (_last_modified.length()) - request->addInterestingHeader("If-Modified-Since"); - - if(_cache_control.length()) - request->addInterestingHeader("If-None-Match"); - - DEBUGF("[AsyncStaticWebHandler::canHandle] TRUE\n"); - return true; - } - - return false; -} - -bool AsyncStaticWebHandler::_getFile(AsyncWebServerRequest *request) -{ - // Remove the found uri - String path = request->url().substring(_uri.length()); - - // We can skip the file check and look for default if request is to the root of a directory or that request path ends with '/' - bool canSkipFileCheck = (_isDir && path.length() == 0) || (path.length() && path[path.length()-1] == '/'); - - path = _path + path; - - // Do we have a file or .gz file - if (!canSkipFileCheck && _fileExists(request, path)) - return true; - - // Can't handle if not default file - if (_default_file.length() == 0) - return false; - - // Try to add default file, ensure there is a trailing '/' ot the path. - if (path.length() == 0 || path[path.length()-1] != '/') - path += "/"; - path += _default_file; - - return _fileExists(request, path); -} - -#ifdef ESP32 -#define FILE_IS_REAL(f) (f == true && !f.isDirectory()) -#else -#define FILE_IS_REAL(f) (f == true) -#endif - -bool AsyncStaticWebHandler::_fileExists(AsyncWebServerRequest *request, const String& path) -{ - bool fileFound = false; - bool gzipFound = false; - - String gzip = path + ".gz"; - - if (_gzipFirst) { - request->_tempFile = _fs.open(gzip, "r"); - gzipFound = FILE_IS_REAL(request->_tempFile); - if (!gzipFound){ - request->_tempFile = _fs.open(path, "r"); - fileFound = FILE_IS_REAL(request->_tempFile); - } - } else { - request->_tempFile = _fs.open(path, "r"); - fileFound = FILE_IS_REAL(request->_tempFile); - if (!fileFound){ - request->_tempFile = _fs.open(gzip, "r"); - gzipFound = FILE_IS_REAL(request->_tempFile); - } - } - - bool found = fileFound || gzipFound; - - if (found) { - // Extract the file name from the path and keep it in _tempObject - size_t pathLen = path.length(); - char * _tempPath = (char*)malloc(pathLen+1); - snprintf(_tempPath, pathLen+1, "%s", path.c_str()); - request->_tempObject = (void*)_tempPath; - - // Calculate gzip statistic - _gzipStats = (_gzipStats << 1) + (gzipFound ? 1 : 0); - if (_gzipStats == 0x00) _gzipFirst = false; // All files are not gzip - else if (_gzipStats == 0xFF) _gzipFirst = true; // All files are gzip - else _gzipFirst = _countBits(_gzipStats) > 4; // IF we have more gzip files - try gzip first - } - - return found; -} - -uint8_t AsyncStaticWebHandler::_countBits(const uint8_t value) const -{ - uint8_t w = value; - uint8_t n; - for (n=0; w!=0; n++) w&=w-1; - return n; -} - -void AsyncStaticWebHandler::handleRequest(AsyncWebServerRequest *request) -{ - // Get the filename from request->_tempObject and free it - String filename = String((char*)request->_tempObject); - free(request->_tempObject); - request->_tempObject = NULL; - if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str())) - return request->requestAuthentication(); - - if (request->_tempFile == true) { - String etag = String(request->_tempFile.size()); - if (_last_modified.length() && _last_modified == request->header("If-Modified-Since")) { - request->_tempFile.close(); - request->send(304); // Not modified - } else if (_cache_control.length() && request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag)) { - request->_tempFile.close(); - AsyncWebServerResponse * response = new AsyncBasicResponse(304); // Not modified - response->addHeader("Cache-Control", _cache_control); - response->addHeader("ETag", etag); - request->send(response); - } else { - AsyncWebServerResponse * response = new AsyncFileResponse(request->_tempFile, filename, String(), false, _callback); - if (_last_modified.length()) - response->addHeader("Last-Modified", _last_modified); - if (_cache_control.length()){ - response->addHeader("Cache-Control", _cache_control); - response->addHeader("ETag", etag); - } - request->send(response); - } - } else { - request->send(404); - } -} diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebRequest.cpp b/lib/libesp32/ESPAsyncWebServer/src/WebRequest.cpp deleted file mode 100644 index 20b0b1fe4..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/WebRequest.cpp +++ /dev/null @@ -1,1008 +0,0 @@ -/* - Asynchronous WebServer library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#include "ESPAsyncWebServer.h" -#include "WebResponseImpl.h" -#include "WebAuthentication.h" - -#ifndef ESP8266 -#define os_strlen strlen -#endif - -static const String SharedEmptyString = String(); - -#define __is_param_char(c) ((c) && ((c) != '{') && ((c) != '[') && ((c) != '&') && ((c) != '=')) - -enum { PARSE_REQ_START, PARSE_REQ_HEADERS, PARSE_REQ_BODY, PARSE_REQ_END, PARSE_REQ_FAIL }; - -AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c) - : _client(c) - , _server(s) - , _handler(NULL) - , _response(NULL) - , _temp() - , _parseState(0) - , _version(0) - , _method(HTTP_ANY) - , _url() - , _host() - , _contentType() - , _boundary() - , _authorization() - , _reqconntype(RCT_HTTP) - , _isDigest(false) - , _isMultipart(false) - , _isPlainPost(false) - , _expectingContinue(false) - , _contentLength(0) - , _parsedLength(0) - , _headers(AsyncLinkedList([](AsyncWebHeader *h){ delete h; })) - , _params(AsyncLinkedList([](AsyncWebParameter *p){ delete p; })) - , _pathParams(AsyncLinkedList([](String *p){ delete p; })) - , _multiParseState(0) - , _boundaryPosition(0) - , _itemStartIndex(0) - , _itemSize(0) - , _itemName() - , _itemFilename() - , _itemType() - , _itemValue() - , _itemBuffer(0) - , _itemBufferIndex(0) - , _itemIsFile(false) - , _tempObject(NULL) -{ - c->onError([](void *r, AsyncClient* c, int8_t error){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onError(error); }, this); - c->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onAck(len, time); }, this); - c->onDisconnect([](void *r, AsyncClient* c){ AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onDisconnect(); delete c; }, this); - c->onTimeout([](void *r, AsyncClient* c, uint32_t time){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onTimeout(time); }, this); - c->onData([](void *r, AsyncClient* c, void *buf, size_t len){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onData(buf, len); }, this); - c->onPoll([](void *r, AsyncClient* c){ (void)c; AsyncWebServerRequest *req = ( AsyncWebServerRequest*)r; req->_onPoll(); }, this); -} - -AsyncWebServerRequest::~AsyncWebServerRequest(){ - _headers.free(); - - _params.free(); - _pathParams.free(); - - _interestingHeaders.free(); - - if(_response != NULL){ - delete _response; - } - - if(_tempObject != NULL){ - free(_tempObject); - } - - if(_tempFile){ - _tempFile.close(); - } -} - -void AsyncWebServerRequest::_onData(void *buf, size_t len){ - size_t i = 0; - while (true) { - - if(_parseState < PARSE_REQ_BODY){ - // Find new line in buf - char *str = (char*)buf; - for (i = 0; i < len; i++) { - if (str[i] == '\n') { - break; - } - } - if (i == len) { // No new line, just add the buffer in _temp - char ch = str[len-1]; - str[len-1] = 0; - _temp.reserve(_temp.length()+len); - _temp.concat(str); - _temp.concat(ch); - } else { // Found new line - extract it and parse - str[i] = 0; // Terminate the string at the end of the line. - _temp.concat(str); - _temp.trim(); - _parseLine(); - if (++i < len) { - // Still have more buffer to process - buf = str+i; - len-= i; - continue; - } - } - } else if(_parseState == PARSE_REQ_BODY){ - // A handler should be already attached at this point in _parseLine function. - // If handler does nothing (_onRequest is NULL), we don't need to really parse the body. - const bool needParse = _handler && !_handler->isRequestHandlerTrivial(); - if(_isMultipart){ - if(needParse){ - size_t i; - for(i=0; i end) equal = end; - String name = params.substring(start, equal); - String value = equal + 1 < end ? params.substring(equal + 1, end) : String(); - _addParam(new AsyncWebParameter(urlDecode(name), urlDecode(value))); - start = end + 1; - } -} - -bool AsyncWebServerRequest::_parseReqHead(){ - // Split the head into method, url and version - int index = _temp.indexOf(' '); - String m = _temp.substring(0, index); - index = _temp.indexOf(' ', index+1); - String u = _temp.substring(m.length()+1, index); - _temp = _temp.substring(index+1); - - if(m == "GET"){ - _method = HTTP_GET; - } else if(m == "POST"){ - _method = HTTP_POST; - } else if(m == "DELETE"){ - _method = HTTP_DELETE; - } else if(m == "PUT"){ - _method = HTTP_PUT; - } else if(m == "PATCH"){ - _method = HTTP_PATCH; - } else if(m == "HEAD"){ - _method = HTTP_HEAD; - } else if(m == "OPTIONS"){ - _method = HTTP_OPTIONS; - } - - String g = String(); - index = u.indexOf('?'); - if(index > 0){ - g = u.substring(index +1); - u = u.substring(0, index); - } - _url = urlDecode(u); - _addGetParams(g); - - if(!_temp.startsWith("HTTP/1.0")) - _version = 1; - - _temp = String(); - return true; -} - -bool strContains(String src, String find, bool mindcase = true) { - int pos=0, i=0; - const int slen = src.length(); - const int flen = find.length(); - - if (slen < flen) return false; - while (pos <= (slen - flen)) { - for (i=0; i < flen; i++) { - if (mindcase) { - if (src[pos+i] != find[i]) i = flen + 1; // no match - } else if (tolower(src[pos+i]) != tolower(find[i])) i = flen + 1; // no match - } - if (i == flen) return true; - pos++; - } - return false; -} - -bool AsyncWebServerRequest::_parseReqHeader(){ - int index = _temp.indexOf(':'); - if(index){ - String name = _temp.substring(0, index); - String value = _temp.substring(index + 2); - if(name.equalsIgnoreCase("Host")){ - _host = value; - } else if(name.equalsIgnoreCase("Content-Type")){ - _contentType = value.substring(0, value.indexOf(';')); - if (value.startsWith("multipart/")){ - _boundary = value.substring(value.indexOf('=')+1); - _boundary.replace("\"",""); - _isMultipart = true; - } - } else if(name.equalsIgnoreCase("Content-Length")){ - _contentLength = atoi(value.c_str()); - } else if(name.equalsIgnoreCase("Expect") && value == "100-continue"){ - _expectingContinue = true; - } else if(name.equalsIgnoreCase("Authorization")){ - if(value.length() > 5 && value.substring(0,5).equalsIgnoreCase("Basic")){ - _authorization = value.substring(6); - } else if(value.length() > 6 && value.substring(0,6).equalsIgnoreCase("Digest")){ - _isDigest = true; - _authorization = value.substring(7); - } - } else { - if(name.equalsIgnoreCase("Upgrade") && value.equalsIgnoreCase("websocket")){ - // WebSocket request can be uniquely identified by header: [Upgrade: websocket] - _reqconntype = RCT_WS; - } else { - if(name.equalsIgnoreCase("Accept") && strContains(value, "text/event-stream", false)){ - // WebEvent request can be uniquely identified by header: [Accept: text/event-stream] - _reqconntype = RCT_EVENT; - } - } - } - _headers.add(new AsyncWebHeader(name, value)); - } - _temp = String(); - return true; -} - -void AsyncWebServerRequest::_parsePlainPostChar(uint8_t data){ - if(data && (char)data != '&') - _temp += (char)data; - if(!data || (char)data == '&' || _parsedLength == _contentLength){ - String name = "body"; - String value = _temp; - if(!_temp.startsWith("{") && !_temp.startsWith("[") && _temp.indexOf('=') > 0){ - name = _temp.substring(0, _temp.indexOf('=')); - value = _temp.substring(_temp.indexOf('=') + 1); - } - _addParam(new AsyncWebParameter(urlDecode(name), urlDecode(value), true)); - _temp = String(); - } -} - -void AsyncWebServerRequest::_handleUploadByte(uint8_t data, bool last){ - _itemBuffer[_itemBufferIndex++] = data; - - if(last || _itemBufferIndex == 1460){ - //check if authenticated before calling the upload - if(_handler) - _handler->handleUpload(this, _itemFilename, _itemSize - _itemBufferIndex, _itemBuffer, _itemBufferIndex, false); - _itemBufferIndex = 0; - } -} - -enum { - EXPECT_BOUNDARY, - PARSE_HEADERS, - WAIT_FOR_RETURN1, - EXPECT_FEED1, - EXPECT_DASH1, - EXPECT_DASH2, - BOUNDARY_OR_DATA, - DASH3_OR_RETURN2, - EXPECT_FEED2, - PARSING_FINISHED, - PARSE_ERROR -}; - -void AsyncWebServerRequest::_parseMultipartPostByte(uint8_t data, bool last){ -#define itemWriteByte(b) do { _itemSize++; if(_itemIsFile) _handleUploadByte(b, last); else _itemValue+=(char)(b); } while(0) - - if(!_parsedLength){ - _multiParseState = EXPECT_BOUNDARY; - _temp = String(); - _itemName = String(); - _itemFilename = String(); - _itemType = String(); - } - - if(_multiParseState == WAIT_FOR_RETURN1){ - if(data != '\r'){ - itemWriteByte(data); - } else { - _multiParseState = EXPECT_FEED1; - } - } else if(_multiParseState == EXPECT_BOUNDARY){ - if(_parsedLength < 2 && data != '-'){ - _multiParseState = PARSE_ERROR; - return; - } else if(_parsedLength - 2 < _boundary.length() && _boundary.c_str()[_parsedLength - 2] != data){ - _multiParseState = PARSE_ERROR; - return; - } else if(_parsedLength - 2 == _boundary.length() && data != '\r'){ - _multiParseState = PARSE_ERROR; - return; - } else if(_parsedLength - 3 == _boundary.length()){ - if(data != '\n'){ - _multiParseState = PARSE_ERROR; - return; - } - _multiParseState = PARSE_HEADERS; - _itemIsFile = false; - } - } else if(_multiParseState == PARSE_HEADERS){ - if((char)data != '\r' && (char)data != '\n') - _temp += (char)data; - if((char)data == '\n'){ - if(_temp.length()){ - if(_temp.length() > 12 && _temp.substring(0, 12).equalsIgnoreCase("Content-Type")){ - _itemType = _temp.substring(14); - _itemIsFile = true; - } else if(_temp.length() > 19 && _temp.substring(0, 19).equalsIgnoreCase("Content-Disposition")){ - _temp = _temp.substring(_temp.indexOf(';') + 2); - while(_temp.indexOf(';') > 0){ - String name = _temp.substring(0, _temp.indexOf('=')); - String nameVal = _temp.substring(_temp.indexOf('=') + 2, _temp.indexOf(';') - 1); - if(name == "name"){ - _itemName = nameVal; - } else if(name == "filename"){ - _itemFilename = nameVal; - _itemIsFile = true; - } - _temp = _temp.substring(_temp.indexOf(';') + 2); - } - String name = _temp.substring(0, _temp.indexOf('=')); - String nameVal = _temp.substring(_temp.indexOf('=') + 2, _temp.length() - 1); - if(name == "name"){ - _itemName = nameVal; - } else if(name == "filename"){ - _itemFilename = nameVal; - _itemIsFile = true; - } - } - _temp = String(); - } else { - _multiParseState = WAIT_FOR_RETURN1; - //value starts from here - _itemSize = 0; - _itemStartIndex = _parsedLength; - _itemValue = String(); - if(_itemIsFile){ - if(_itemBuffer) - free(_itemBuffer); - _itemBuffer = (uint8_t*)malloc(1460); - if(_itemBuffer == NULL){ - _multiParseState = PARSE_ERROR; - return; - } - _itemBufferIndex = 0; - } - } - } - } else if(_multiParseState == EXPECT_FEED1){ - if(data != '\n'){ - _multiParseState = WAIT_FOR_RETURN1; - itemWriteByte('\r'); _parseMultipartPostByte(data, last); - } else { - _multiParseState = EXPECT_DASH1; - } - } else if(_multiParseState == EXPECT_DASH1){ - if(data != '-'){ - _multiParseState = WAIT_FOR_RETURN1; - itemWriteByte('\r'); itemWriteByte('\n'); _parseMultipartPostByte(data, last); - } else { - _multiParseState = EXPECT_DASH2; - } - } else if(_multiParseState == EXPECT_DASH2){ - if(data != '-'){ - _multiParseState = WAIT_FOR_RETURN1; - itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); _parseMultipartPostByte(data, last); - } else { - _multiParseState = BOUNDARY_OR_DATA; - _boundaryPosition = 0; - } - } else if(_multiParseState == BOUNDARY_OR_DATA){ - if(_boundaryPosition < _boundary.length() && _boundary.c_str()[_boundaryPosition] != data){ - _multiParseState = WAIT_FOR_RETURN1; - itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); itemWriteByte('-'); - uint8_t i; - for(i=0; i<_boundaryPosition; i++) - itemWriteByte(_boundary.c_str()[i]); - _parseMultipartPostByte(data, last); - } else if(_boundaryPosition == _boundary.length() - 1){ - _multiParseState = DASH3_OR_RETURN2; - if(!_itemIsFile){ - _addParam(new AsyncWebParameter(_itemName, _itemValue, true)); - } else { - if(_itemSize){ - //check if authenticated before calling the upload - if(_handler) _handler->handleUpload(this, _itemFilename, _itemSize - _itemBufferIndex, _itemBuffer, _itemBufferIndex, true); - _itemBufferIndex = 0; - _addParam(new AsyncWebParameter(_itemName, _itemFilename, true, true, _itemSize)); - } - free(_itemBuffer); - _itemBuffer = NULL; - } - - } else { - _boundaryPosition++; - } - } else if(_multiParseState == DASH3_OR_RETURN2){ - if(data == '-' && (_contentLength - _parsedLength - 4) != 0){ - //os_printf("ERROR: The parser got to the end of the POST but is expecting %u bytes more!\nDrop an issue so we can have more info on the matter!\n", _contentLength - _parsedLength - 4); - _contentLength = _parsedLength + 4;//lets close the request gracefully - } - if(data == '\r'){ - _multiParseState = EXPECT_FEED2; - } else if(data == '-' && _contentLength == (_parsedLength + 4)){ - _multiParseState = PARSING_FINISHED; - } else { - _multiParseState = WAIT_FOR_RETURN1; - itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); itemWriteByte('-'); - uint8_t i; for(i=0; i<_boundary.length(); i++) itemWriteByte(_boundary.c_str()[i]); - _parseMultipartPostByte(data, last); - } - } else if(_multiParseState == EXPECT_FEED2){ - if(data == '\n'){ - _multiParseState = PARSE_HEADERS; - _itemIsFile = false; - } else { - _multiParseState = WAIT_FOR_RETURN1; - itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); itemWriteByte('-'); - uint8_t i; for(i=0; i<_boundary.length(); i++) itemWriteByte(_boundary.c_str()[i]); - itemWriteByte('\r'); _parseMultipartPostByte(data, last); - } - } -} - -void AsyncWebServerRequest::_parseLine(){ - if(_parseState == PARSE_REQ_START){ - if(!_temp.length()){ - _parseState = PARSE_REQ_FAIL; - _client->close(); - } else { - _parseReqHead(); - _parseState = PARSE_REQ_HEADERS; - } - return; - } - - if(_parseState == PARSE_REQ_HEADERS){ - if(!_temp.length()){ - //end of headers - _server->_rewriteRequest(this); - _server->_attachHandler(this); - _removeNotInterestingHeaders(); - if(_expectingContinue){ - const char * response = "HTTP/1.1 100 Continue\r\n\r\n"; - _client->write(response, os_strlen(response)); - } - //check handler for authentication - if(_contentLength){ - _parseState = PARSE_REQ_BODY; - } else { - _parseState = PARSE_REQ_END; - if(_handler) _handler->handleRequest(this); - else send(501); - } - } else _parseReqHeader(); - } -} - -size_t AsyncWebServerRequest::headers() const{ - return _headers.length(); -} - -bool AsyncWebServerRequest::hasHeader(const String& name) const { - for(const auto& h: _headers){ - if(h->name().equalsIgnoreCase(name)){ - return true; - } - } - return false; -} - -bool AsyncWebServerRequest::hasHeader(const __FlashStringHelper * data) const { - PGM_P p = reinterpret_cast(data); - size_t n = 0; - while (1) { - if (pgm_read_byte(p+n) == 0) break; - n += 1; - } - char * name = (char*) malloc(n+1); - name[n] = 0; - if (name) { - for(size_t b=0; bname().equalsIgnoreCase(name)){ - return h; - } - } - return nullptr; -} - -AsyncWebHeader* AsyncWebServerRequest::getHeader(const __FlashStringHelper * data) const { - PGM_P p = reinterpret_cast(data); - size_t n = strlen_P(p); - char * name = (char*) malloc(n+1); - if (name) { - strcpy_P(name, p); - AsyncWebHeader* result = getHeader( String(name)); - free(name); - return result; - } else { - return nullptr; - } -} - -AsyncWebHeader* AsyncWebServerRequest::getHeader(size_t num) const { - auto header = _headers.nth(num); - return header ? *header : nullptr; -} - -size_t AsyncWebServerRequest::params() const { - return _params.length(); -} - -bool AsyncWebServerRequest::hasParam(const String& name, bool post, bool file) const { - for(const auto& p: _params){ - if(p->name() == name && p->isPost() == post && p->isFile() == file){ - return true; - } - } - return false; -} - -bool AsyncWebServerRequest::hasParam(const __FlashStringHelper * data, bool post, bool file) const { - PGM_P p = reinterpret_cast(data); - size_t n = strlen_P(p); - - char * name = (char*) malloc(n+1); - name[n] = 0; - if (name) { - strcpy_P(name,p); - bool result = hasParam( name, post, file); - free(name); - return result; - } else { - return false; - } -} - -AsyncWebParameter* AsyncWebServerRequest::getParam(const String& name, bool post, bool file) const { - for(const auto& p: _params){ - if(p->name() == name && p->isPost() == post && p->isFile() == file){ - return p; - } - } - return nullptr; -} - -AsyncWebParameter* AsyncWebServerRequest::getParam(const __FlashStringHelper * data, bool post, bool file) const { - PGM_P p = reinterpret_cast(data); - size_t n = strlen_P(p); - char * name = (char*) malloc(n+1); - if (name) { - strcpy_P(name, p); - AsyncWebParameter* result = getParam(name, post, file); - free(name); - return result; - } else { - return nullptr; - } -} - -AsyncWebParameter* AsyncWebServerRequest::getParam(size_t num) const { - auto param = _params.nth(num); - return param ? *param : nullptr; -} - -void AsyncWebServerRequest::addInterestingHeader(const String& name){ - if(!_interestingHeaders.containsIgnoreCase(name)) - _interestingHeaders.add(name); -} - -void AsyncWebServerRequest::send(AsyncWebServerResponse *response){ - _response = response; - if(_response == NULL){ - _client->close(true); - _onDisconnect(); - return; - } - if(!_response->_sourceValid()){ - delete response; - _response = NULL; - send(500); - } - else { - _client->setRxTimeout(0); - _response->_respond(this); - } -} - -AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(int code, const String& contentType, const String& content){ - return new AsyncBasicResponse(code, contentType, content); -} - -AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(FS &fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){ - if(fs.exists(path) || (!download && fs.exists(path+".gz"))) - return new AsyncFileResponse(fs, path, contentType, download, callback); - return NULL; -} - -AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){ - if(content == true) - return new AsyncFileResponse(content, path, contentType, download, callback); - return NULL; -} - -AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback){ - return new AsyncStreamResponse(stream, contentType, len, callback); -} - -AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){ - return new AsyncCallbackResponse(contentType, len, callback, templateCallback); -} - -AsyncWebServerResponse * AsyncWebServerRequest::beginChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){ - if(_version) - return new AsyncChunkedResponse(contentType, callback, templateCallback); - return new AsyncCallbackResponse(contentType, 0, callback, templateCallback); -} - -AsyncResponseStream * AsyncWebServerRequest::beginResponseStream(const String& contentType, size_t bufferSize){ - return new AsyncResponseStream(contentType, bufferSize); -} - -AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback){ - return new AsyncProgmemResponse(code, contentType, content, len, callback); -} - -AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback){ - return beginResponse_P(code, contentType, (const uint8_t *)content, strlen_P(content), callback); -} - -void AsyncWebServerRequest::send(int code, const String& contentType, const String& content){ - send(beginResponse(code, contentType, content)); -} - -void AsyncWebServerRequest::send(FS &fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){ - if(fs.exists(path) || (!download && fs.exists(path+".gz"))){ - send(beginResponse(fs, path, contentType, download, callback)); - } else send(404); -} - -void AsyncWebServerRequest::send(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){ - if(content == true){ - send(beginResponse(content, path, contentType, download, callback)); - } else send(404); -} - -void AsyncWebServerRequest::send(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback){ - send(beginResponse(stream, contentType, len, callback)); -} - -void AsyncWebServerRequest::send(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){ - send(beginResponse(contentType, len, callback, templateCallback)); -} - -void AsyncWebServerRequest::sendChunked(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){ - send(beginChunkedResponse(contentType, callback, templateCallback)); -} - -void AsyncWebServerRequest::send_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback){ - send(beginResponse_P(code, contentType, content, len, callback)); -} - -void AsyncWebServerRequest::send_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback){ - send(beginResponse_P(code, contentType, content, callback)); -} - -void AsyncWebServerRequest::redirect(const String& url){ - AsyncWebServerResponse * response = beginResponse(302); - response->addHeader("Location",url); - send(response); -} - -bool AsyncWebServerRequest::authenticate(const char * username, const char * password, const char * realm, bool passwordIsHash){ - if(_authorization.length()){ - if(_isDigest) - return checkDigestAuthentication(_authorization.c_str(), methodToString(), username, password, realm, passwordIsHash, NULL, NULL, NULL); - else if(!passwordIsHash) - return checkBasicAuthentication(_authorization.c_str(), username, password); - else - return _authorization.equals(password); - } - return false; -} - -bool AsyncWebServerRequest::authenticate(const char * hash){ - if(!_authorization.length() || hash == NULL) - return false; - - if(_isDigest){ - String hStr = String(hash); - int separator = hStr.indexOf(":"); - if(separator <= 0) - return false; - String username = hStr.substring(0, separator); - hStr = hStr.substring(separator + 1); - separator = hStr.indexOf(":"); - if(separator <= 0) - return false; - String realm = hStr.substring(0, separator); - hStr = hStr.substring(separator + 1); - return checkDigestAuthentication(_authorization.c_str(), methodToString(), username.c_str(), hStr.c_str(), realm.c_str(), true, NULL, NULL, NULL); - } - - return (_authorization.equals(hash)); -} - -void AsyncWebServerRequest::requestAuthentication(const char * realm, bool isDigest){ - AsyncWebServerResponse * r = beginResponse(401); - if(!isDigest && realm == NULL){ - r->addHeader("WWW-Authenticate", "Basic realm=\"Login Required\""); - } else if(!isDigest){ - String header = "Basic realm=\""; - header.concat(realm); - header.concat("\""); - r->addHeader("WWW-Authenticate", header); - } else { - String header = "Digest "; - header.concat(requestDigestAuthentication(realm)); - r->addHeader("WWW-Authenticate", header); - } - send(r); -} - -bool AsyncWebServerRequest::hasArg(const char* name) const { - for(const auto& arg: _params){ - if(arg->name() == name){ - return true; - } - } - return false; -} - -bool AsyncWebServerRequest::hasArg(const __FlashStringHelper * data) const { - PGM_P p = reinterpret_cast(data); - size_t n = strlen_P(p); - char * name = (char*) malloc(n+1); - if (name) { - strcpy_P(name, p); - bool result = hasArg( name ); - free(name); - return result; - } else { - return false; - } -} - - -const String& AsyncWebServerRequest::arg(const String& name) const { - for(const auto& arg: _params){ - if(arg->name() == name){ - return arg->value(); - } - } - return SharedEmptyString; -} - -const String& AsyncWebServerRequest::arg(const __FlashStringHelper * data) const { - PGM_P p = reinterpret_cast(data); - size_t n = strlen_P(p); - char * name = (char*) malloc(n+1); - if (name) { - strcpy_P(name, p); - const String & result = arg( String(name) ); - free(name); - return result; - } else { - return SharedEmptyString; - } - -} - -const String& AsyncWebServerRequest::arg(size_t i) const { - return getParam(i)->value(); -} - -const String& AsyncWebServerRequest::argName(size_t i) const { - return getParam(i)->name(); -} - -const String& AsyncWebServerRequest::pathArg(size_t i) const { - auto param = _pathParams.nth(i); - return param ? **param : SharedEmptyString; -} - -const String& AsyncWebServerRequest::header(const char* name) const { - AsyncWebHeader* h = getHeader(String(name)); - return h ? h->value() : SharedEmptyString; -} - -const String& AsyncWebServerRequest::header(const __FlashStringHelper * data) const { - PGM_P p = reinterpret_cast(data); - size_t n = strlen_P(p); - char * name = (char*) malloc(n+1); - if (name) { - strcpy_P(name, p); - const String & result = header( (const char *)name ); - free(name); - return result; - } else { - return SharedEmptyString; - } -}; - - -const String& AsyncWebServerRequest::header(size_t i) const { - AsyncWebHeader* h = getHeader(i); - return h ? h->value() : SharedEmptyString; -} - -const String& AsyncWebServerRequest::headerName(size_t i) const { - AsyncWebHeader* h = getHeader(i); - return h ? h->name() : SharedEmptyString; -} - -String AsyncWebServerRequest::urlDecode(const String& text) const { - char temp[] = "0x00"; - unsigned int len = text.length(); - unsigned int i = 0; - String decoded = String(); - decoded.reserve(len); // Allocate the string internal buffer - never longer from source text - while (i < len){ - char decodedChar; - char encodedChar = text.charAt(i++); - if ((encodedChar == '%') && (i + 1 < len)){ - temp[2] = text.charAt(i++); - temp[3] = text.charAt(i++); - decodedChar = strtol(temp, NULL, 16); - } else if (encodedChar == '+') { - decodedChar = ' '; - } else { - decodedChar = encodedChar; // normal ascii char - } - decoded.concat(decodedChar); - } - return decoded; -} - - -const char * AsyncWebServerRequest::methodToString() const { - if(_method == HTTP_ANY) return "ANY"; - else if(_method & HTTP_GET) return "GET"; - else if(_method & HTTP_POST) return "POST"; - else if(_method & HTTP_DELETE) return "DELETE"; - else if(_method & HTTP_PUT) return "PUT"; - else if(_method & HTTP_PATCH) return "PATCH"; - else if(_method & HTTP_HEAD) return "HEAD"; - else if(_method & HTTP_OPTIONS) return "OPTIONS"; - return "UNKNOWN"; -} - -const char *AsyncWebServerRequest::requestedConnTypeToString() const { - switch (_reqconntype) { - case RCT_NOT_USED: return "RCT_NOT_USED"; - case RCT_DEFAULT: return "RCT_DEFAULT"; - case RCT_HTTP: return "RCT_HTTP"; - case RCT_WS: return "RCT_WS"; - case RCT_EVENT: return "RCT_EVENT"; - default: return "ERROR"; - } -} - -bool AsyncWebServerRequest::isExpectedRequestedConnType(RequestedConnectionType erct1, RequestedConnectionType erct2, RequestedConnectionType erct3) { - bool res = false; - if ((erct1 != RCT_NOT_USED) && (erct1 == _reqconntype)) res = true; - if ((erct2 != RCT_NOT_USED) && (erct2 == _reqconntype)) res = true; - if ((erct3 != RCT_NOT_USED) && (erct3 == _reqconntype)) res = true; - return res; -} diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebResponseImpl.h b/lib/libesp32/ESPAsyncWebServer/src/WebResponseImpl.h deleted file mode 100644 index 9a64e3a52..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/WebResponseImpl.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - Asynchronous WebServer library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#ifndef ASYNCWEBSERVERRESPONSEIMPL_H_ -#define ASYNCWEBSERVERRESPONSEIMPL_H_ - -#ifdef Arduino_h -// arduino is not compatible with std::vector -#undef min -#undef max -#endif -#include -// It is possible to restore these defines, but one can use _min and _max instead. Or std::min, std::max. - -class AsyncBasicResponse: public AsyncWebServerResponse { - private: - String _content; - public: - AsyncBasicResponse(int code, const String& contentType=String(), const String& content=String()); - void _respond(AsyncWebServerRequest *request); - size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); - bool _sourceValid() const { return true; } -}; - -class AsyncAbstractResponse: public AsyncWebServerResponse { - private: - String _head; - // Data is inserted into cache at begin(). - // This is inefficient with vector, but if we use some other container, - // we won't be able to access it as contiguous array of bytes when reading from it, - // so by gaining performance in one place, we'll lose it in another. - std::vector _cache; - size_t _readDataFromCacheOrContent(uint8_t* data, const size_t len); - size_t _fillBufferAndProcessTemplates(uint8_t* buf, size_t maxLen); - protected: - AwsTemplateProcessor _callback; - public: - AsyncAbstractResponse(AwsTemplateProcessor callback=nullptr); - void _respond(AsyncWebServerRequest *request); - size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); - bool _sourceValid() const { return false; } - virtual size_t _fillBuffer(uint8_t *buf __attribute__((unused)), size_t maxLen __attribute__((unused))) { return 0; } -}; - -#ifndef TEMPLATE_PLACEHOLDER -#define TEMPLATE_PLACEHOLDER '%' -#endif - -#define TEMPLATE_PARAM_NAME_LENGTH 32 -class AsyncFileResponse: public AsyncAbstractResponse { - using File = fs::File; - using FS = fs::FS; - private: - File _content; - String _path; - void _setContentType(const String& path); - public: - AsyncFileResponse(FS &fs, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr); - AsyncFileResponse(File content, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr); - ~AsyncFileResponse(); - bool _sourceValid() const { return !!(_content); } - virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; -}; - -class AsyncStreamResponse: public AsyncAbstractResponse { - private: - Stream *_content; - public: - AsyncStreamResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback=nullptr); - bool _sourceValid() const { return !!(_content); } - virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; -}; - -class AsyncCallbackResponse: public AsyncAbstractResponse { - private: - AwsResponseFiller _content; - size_t _filledLength; - public: - AsyncCallbackResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr); - bool _sourceValid() const { return !!(_content); } - virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; -}; - -class AsyncChunkedResponse: public AsyncAbstractResponse { - private: - AwsResponseFiller _content; - size_t _filledLength; - public: - AsyncChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr); - bool _sourceValid() const { return !!(_content); } - virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; -}; - -class AsyncProgmemResponse: public AsyncAbstractResponse { - private: - const uint8_t * _content; - size_t _readLength; - public: - AsyncProgmemResponse(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback=nullptr); - bool _sourceValid() const { return true; } - virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; -}; - -class cbuf; - -class AsyncResponseStream: public AsyncAbstractResponse, public Print { - private: - cbuf *_content; - public: - AsyncResponseStream(const String& contentType, size_t bufferSize); - ~AsyncResponseStream(); - bool _sourceValid() const { return (_state < RESPONSE_END); } - virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; - size_t write(const uint8_t *data, size_t len); - size_t write(uint8_t data); - using Print::write; -}; - -#endif /* ASYNCWEBSERVERRESPONSEIMPL_H_ */ diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebResponses.cpp b/lib/libesp32/ESPAsyncWebServer/src/WebResponses.cpp deleted file mode 100644 index cc66b00ea..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/WebResponses.cpp +++ /dev/null @@ -1,699 +0,0 @@ -/* - Asynchronous WebServer library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#include "ESPAsyncWebServer.h" -#include "WebResponseImpl.h" -#include "cbuf.h" - -// Since ESP8266 does not link memchr by default, here's its implementation. -void* memchr(void* ptr, int ch, size_t count) -{ - unsigned char* p = static_cast(ptr); - while(count--) - if(*p++ == static_cast(ch)) - return --p; - return nullptr; -} - - -/* - * Abstract Response - * */ -const char* AsyncWebServerResponse::_responseCodeToString(int code) { - switch (code) { - case 100: return "Continue"; - case 101: return "Switching Protocols"; - case 200: return "OK"; - case 201: return "Created"; - case 202: return "Accepted"; - case 203: return "Non-Authoritative Information"; - case 204: return "No Content"; - case 205: return "Reset Content"; - case 206: return "Partial Content"; - case 300: return "Multiple Choices"; - case 301: return "Moved Permanently"; - case 302: return "Found"; - case 303: return "See Other"; - case 304: return "Not Modified"; - case 305: return "Use Proxy"; - case 307: return "Temporary Redirect"; - case 400: return "Bad Request"; - case 401: return "Unauthorized"; - case 402: return "Payment Required"; - case 403: return "Forbidden"; - case 404: return "Not Found"; - case 405: return "Method Not Allowed"; - case 406: return "Not Acceptable"; - case 407: return "Proxy Authentication Required"; - case 408: return "Request Time-out"; - case 409: return "Conflict"; - case 410: return "Gone"; - case 411: return "Length Required"; - case 412: return "Precondition Failed"; - case 413: return "Request Entity Too Large"; - case 414: return "Request-URI Too Large"; - case 415: return "Unsupported Media Type"; - case 416: return "Requested range not satisfiable"; - case 417: return "Expectation Failed"; - case 500: return "Internal Server Error"; - case 501: return "Not Implemented"; - case 502: return "Bad Gateway"; - case 503: return "Service Unavailable"; - case 504: return "Gateway Time-out"; - case 505: return "HTTP Version not supported"; - default: return ""; - } -} - -AsyncWebServerResponse::AsyncWebServerResponse() - : _code(0) - , _headers(AsyncLinkedList([](AsyncWebHeader *h){ delete h; })) - , _contentType() - , _contentLength(0) - , _sendContentLength(true) - , _chunked(false) - , _headLength(0) - , _sentLength(0) - , _ackedLength(0) - , _writtenLength(0) - , _state(RESPONSE_SETUP) -{ - for(auto header: DefaultHeaders::Instance()) { - _headers.add(new AsyncWebHeader(header->name(), header->value())); - } -} - -AsyncWebServerResponse::~AsyncWebServerResponse(){ - _headers.free(); -} - -void AsyncWebServerResponse::setCode(int code){ - if(_state == RESPONSE_SETUP) - _code = code; -} - -void AsyncWebServerResponse::setContentLength(size_t len){ - if(_state == RESPONSE_SETUP) - _contentLength = len; -} - -void AsyncWebServerResponse::setContentType(const String& type){ - if(_state == RESPONSE_SETUP) - _contentType = type; -} - -void AsyncWebServerResponse::addHeader(const String& name, const String& value){ - _headers.add(new AsyncWebHeader(name, value)); -} - -String AsyncWebServerResponse::_assembleHead(uint8_t version){ - if(version){ - addHeader("Accept-Ranges","none"); - if(_chunked) - addHeader("Transfer-Encoding","chunked"); - } - String out = String(); - int bufSize = 300; - char buf[bufSize]; - - snprintf(buf, bufSize, "HTTP/1.%d %d %s\r\n", version, _code, _responseCodeToString(_code)); - out.concat(buf); - - if(_sendContentLength) { - snprintf(buf, bufSize, "Content-Length: %d\r\n", _contentLength); - out.concat(buf); - } - if(_contentType.length()) { - snprintf(buf, bufSize, "Content-Type: %s\r\n", _contentType.c_str()); - out.concat(buf); - } - - for(const auto& header: _headers){ - snprintf(buf, bufSize, "%s: %s\r\n", header->name().c_str(), header->value().c_str()); - out.concat(buf); - } - _headers.free(); - - out.concat("\r\n"); - _headLength = out.length(); - return out; -} - -bool AsyncWebServerResponse::_started() const { return _state > RESPONSE_SETUP; } -bool AsyncWebServerResponse::_finished() const { return _state > RESPONSE_WAIT_ACK; } -bool AsyncWebServerResponse::_failed() const { return _state == RESPONSE_FAILED; } -bool AsyncWebServerResponse::_sourceValid() const { return false; } -void AsyncWebServerResponse::_respond(AsyncWebServerRequest *request){ _state = RESPONSE_END; request->client()->close(); } -size_t AsyncWebServerResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){ (void)request; (void)len; (void)time; return 0; } - -/* - * String/Code Response - * */ -AsyncBasicResponse::AsyncBasicResponse(int code, const String& contentType, const String& content){ - _code = code; - _content = content; - _contentType = contentType; - if(_content.length()){ - _contentLength = _content.length(); - if(!_contentType.length()) - _contentType = "text/plain"; - } - addHeader("Connection","close"); -} - -void AsyncBasicResponse::_respond(AsyncWebServerRequest *request){ - _state = RESPONSE_HEADERS; - String out = _assembleHead(request->version()); - size_t outLen = out.length(); - size_t space = request->client()->space(); - if(!_contentLength && space >= outLen){ - _writtenLength += request->client()->write(out.c_str(), outLen); - _state = RESPONSE_WAIT_ACK; - } else if(_contentLength && space >= outLen + _contentLength){ - out += _content; - outLen += _contentLength; - _writtenLength += request->client()->write(out.c_str(), outLen); - _state = RESPONSE_WAIT_ACK; - } else if(space && space < outLen){ - String partial = out.substring(0, space); - _content = out.substring(space) + _content; - _contentLength += outLen - space; - _writtenLength += request->client()->write(partial.c_str(), partial.length()); - _state = RESPONSE_CONTENT; - } else if(space > outLen && space < (outLen + _contentLength)){ - size_t shift = space - outLen; - outLen += shift; - _sentLength += shift; - out += _content.substring(0, shift); - _content = _content.substring(shift); - _writtenLength += request->client()->write(out.c_str(), outLen); - _state = RESPONSE_CONTENT; - } else { - _content = out + _content; - _contentLength += outLen; - _state = RESPONSE_CONTENT; - } -} - -size_t AsyncBasicResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){ - (void)time; - _ackedLength += len; - if(_state == RESPONSE_CONTENT){ - size_t available = _contentLength - _sentLength; - size_t space = request->client()->space(); - //we can fit in this packet - if(space > available){ - _writtenLength += request->client()->write(_content.c_str(), available); - _content = String(); - _state = RESPONSE_WAIT_ACK; - return available; - } - //send some data, the rest on ack - String out = _content.substring(0, space); - _content = _content.substring(space); - _sentLength += space; - _writtenLength += request->client()->write(out.c_str(), space); - return space; - } else if(_state == RESPONSE_WAIT_ACK){ - if(_ackedLength >= _writtenLength){ - _state = RESPONSE_END; - } - } - return 0; -} - - -/* - * Abstract Response - * */ - -AsyncAbstractResponse::AsyncAbstractResponse(AwsTemplateProcessor callback): _callback(callback) -{ - // In case of template processing, we're unable to determine real response size - if(callback) { - _contentLength = 0; - _sendContentLength = false; - _chunked = true; - } -} - -void AsyncAbstractResponse::_respond(AsyncWebServerRequest *request){ - addHeader("Connection","close"); - _head = _assembleHead(request->version()); - _state = RESPONSE_HEADERS; - _ack(request, 0, 0); -} - -size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){ - (void)time; - if(!_sourceValid()){ - _state = RESPONSE_FAILED; - request->client()->close(); - return 0; - } - _ackedLength += len; - size_t space = request->client()->space(); - - size_t headLen = _head.length(); - if(_state == RESPONSE_HEADERS){ - if(space >= headLen){ - _state = RESPONSE_CONTENT; - space -= headLen; - } else { - String out = _head.substring(0, space); - _head = _head.substring(space); - _writtenLength += request->client()->write(out.c_str(), out.length()); - return out.length(); - } - } - - if(_state == RESPONSE_CONTENT){ - size_t outLen; - if(_chunked){ - if(space <= 8){ - return 0; - } - outLen = space; - } else if(!_sendContentLength){ - outLen = space; - } else { - outLen = ((_contentLength - _sentLength) > space)?space:(_contentLength - _sentLength); - } - - uint8_t *buf = (uint8_t *)malloc(outLen+headLen); - if (!buf) { - // os_printf("_ack malloc %d failed\n", outLen+headLen); - return 0; - } - - if(headLen){ - memcpy(buf, _head.c_str(), _head.length()); - } - - size_t readLen = 0; - - if(_chunked){ - // HTTP 1.1 allows leading zeros in chunk length. Or spaces may be added. - // See RFC2616 sections 2, 3.6.1. - readLen = _fillBufferAndProcessTemplates(buf+headLen+6, outLen - 8); - if(readLen == RESPONSE_TRY_AGAIN){ - free(buf); - return 0; - } - outLen = sprintf((char*)buf+headLen, "%x", readLen) + headLen; - while(outLen < headLen + 4) buf[outLen++] = ' '; - buf[outLen++] = '\r'; - buf[outLen++] = '\n'; - outLen += readLen; - buf[outLen++] = '\r'; - buf[outLen++] = '\n'; - } else { - readLen = _fillBufferAndProcessTemplates(buf+headLen, outLen); - if(readLen == RESPONSE_TRY_AGAIN){ - free(buf); - return 0; - } - outLen = readLen + headLen; - } - - if(headLen){ - _head = String(); - } - - if(outLen){ - _writtenLength += request->client()->write((const char*)buf, outLen); - } - - if(_chunked){ - _sentLength += readLen; - } else { - _sentLength += outLen - headLen; - } - - free(buf); - - if((_chunked && readLen == 0) || (!_sendContentLength && outLen == 0) || (!_chunked && _sentLength == _contentLength)){ - _state = RESPONSE_WAIT_ACK; - } - return outLen; - - } else if(_state == RESPONSE_WAIT_ACK){ - if(!_sendContentLength || _ackedLength >= _writtenLength){ - _state = RESPONSE_END; - if(!_chunked && !_sendContentLength) - request->client()->close(true); - } - } - return 0; -} - -size_t AsyncAbstractResponse::_readDataFromCacheOrContent(uint8_t* data, const size_t len) -{ - // If we have something in cache, copy it to buffer - const size_t readFromCache = std::min(len, _cache.size()); - if(readFromCache) { - memcpy(data, _cache.data(), readFromCache); - _cache.erase(_cache.begin(), _cache.begin() + readFromCache); - } - // If we need to read more... - const size_t needFromFile = len - readFromCache; - const size_t readFromContent = _fillBuffer(data + readFromCache, needFromFile); - return readFromCache + readFromContent; -} - -size_t AsyncAbstractResponse::_fillBufferAndProcessTemplates(uint8_t* data, size_t len) -{ - if(!_callback) - return _fillBuffer(data, len); - - const size_t originalLen = len; - len = _readDataFromCacheOrContent(data, len); - // Now we've read 'len' bytes, either from cache or from file - // Search for template placeholders - uint8_t* pTemplateStart = data; - while((pTemplateStart < &data[len]) && (pTemplateStart = (uint8_t*)memchr(pTemplateStart, TEMPLATE_PLACEHOLDER, &data[len - 1] - pTemplateStart + 1))) { // data[0] ... data[len - 1] - uint8_t* pTemplateEnd = (pTemplateStart < &data[len - 1]) ? (uint8_t*)memchr(pTemplateStart + 1, TEMPLATE_PLACEHOLDER, &data[len - 1] - pTemplateStart) : nullptr; - // temporary buffer to hold parameter name - uint8_t buf[TEMPLATE_PARAM_NAME_LENGTH + 1]; - String paramName; - // If closing placeholder is found: - if(pTemplateEnd) { - // prepare argument to callback - const size_t paramNameLength = std::min(sizeof(buf) - 1, (unsigned int)(pTemplateEnd - pTemplateStart - 1)); - if(paramNameLength) { - memcpy(buf, pTemplateStart + 1, paramNameLength); - buf[paramNameLength] = 0; - paramName = String(reinterpret_cast(buf)); - } else { // double percent sign encountered, this is single percent sign escaped. - // remove the 2nd percent sign - memmove(pTemplateEnd, pTemplateEnd + 1, &data[len] - pTemplateEnd - 1); - len += _readDataFromCacheOrContent(&data[len - 1], 1) - 1; - ++pTemplateStart; - } - } else if(&data[len - 1] - pTemplateStart + 1 < TEMPLATE_PARAM_NAME_LENGTH + 2) { // closing placeholder not found, check if it's in the remaining file data - memcpy(buf, pTemplateStart + 1, &data[len - 1] - pTemplateStart); - const size_t readFromCacheOrContent = _readDataFromCacheOrContent(buf + (&data[len - 1] - pTemplateStart), TEMPLATE_PARAM_NAME_LENGTH + 2 - (&data[len - 1] - pTemplateStart + 1)); - if(readFromCacheOrContent) { - pTemplateEnd = (uint8_t*)memchr(buf + (&data[len - 1] - pTemplateStart), TEMPLATE_PLACEHOLDER, readFromCacheOrContent); - if(pTemplateEnd) { - // prepare argument to callback - *pTemplateEnd = 0; - paramName = String(reinterpret_cast(buf)); - // Copy remaining read-ahead data into cache - _cache.insert(_cache.begin(), pTemplateEnd + 1, buf + (&data[len - 1] - pTemplateStart) + readFromCacheOrContent); - pTemplateEnd = &data[len - 1]; - } - else // closing placeholder not found in file data, store found percent symbol as is and advance to the next position - { - // but first, store read file data in cache - _cache.insert(_cache.begin(), buf + (&data[len - 1] - pTemplateStart), buf + (&data[len - 1] - pTemplateStart) + readFromCacheOrContent); - ++pTemplateStart; - } - } - else // closing placeholder not found in content data, store found percent symbol as is and advance to the next position - ++pTemplateStart; - } - else // closing placeholder not found in content data, store found percent symbol as is and advance to the next position - ++pTemplateStart; - if(paramName.length()) { - // call callback and replace with result. - // Everything in range [pTemplateStart, pTemplateEnd] can be safely replaced with parameter value. - // Data after pTemplateEnd may need to be moved. - // The first byte of data after placeholder is located at pTemplateEnd + 1. - // It should be located at pTemplateStart + numBytesCopied (to begin right after inserted parameter value). - const String paramValue(_callback(paramName)); - const char* pvstr = paramValue.c_str(); - const unsigned int pvlen = paramValue.length(); - const size_t numBytesCopied = std::min(pvlen, static_cast(&data[originalLen - 1] - pTemplateStart + 1)); - // make room for param value - // 1. move extra data to cache if parameter value is longer than placeholder AND if there is no room to store - if((pTemplateEnd + 1 < pTemplateStart + numBytesCopied) && (originalLen - (pTemplateStart + numBytesCopied - pTemplateEnd - 1) < len)) { - _cache.insert(_cache.begin(), &data[originalLen - (pTemplateStart + numBytesCopied - pTemplateEnd - 1)], &data[len]); - //2. parameter value is longer than placeholder text, push the data after placeholder which not saved into cache further to the end - memmove(pTemplateStart + numBytesCopied, pTemplateEnd + 1, &data[originalLen] - pTemplateStart - numBytesCopied); - len = originalLen; // fix issue with truncated data, not sure if it has any side effects - } else if(pTemplateEnd + 1 != pTemplateStart + numBytesCopied) - //2. Either parameter value is shorter than placeholder text OR there is enough free space in buffer to fit. - // Move the entire data after the placeholder - memmove(pTemplateStart + numBytesCopied, pTemplateEnd + 1, &data[len] - pTemplateEnd - 1); - // 3. replace placeholder with actual value - memcpy(pTemplateStart, pvstr, numBytesCopied); - // If result is longer than buffer, copy the remainder into cache (this could happen only if placeholder text itself did not fit entirely in buffer) - if(numBytesCopied < pvlen) { - _cache.insert(_cache.begin(), pvstr + numBytesCopied, pvstr + pvlen); - } else if(pTemplateStart + numBytesCopied < pTemplateEnd + 1) { // result is copied fully; if result is shorter than placeholder text... - // there is some free room, fill it from cache - const size_t roomFreed = pTemplateEnd + 1 - pTemplateStart - numBytesCopied; - const size_t totalFreeRoom = originalLen - len + roomFreed; - len += _readDataFromCacheOrContent(&data[len - roomFreed], totalFreeRoom) - roomFreed; - } else { // result is copied fully; it is longer than placeholder text - const size_t roomTaken = pTemplateStart + numBytesCopied - pTemplateEnd - 1; - len = std::min(len + roomTaken, originalLen); - } - } - } // while(pTemplateStart) - return len; -} - - -/* - * File Response - * */ - -AsyncFileResponse::~AsyncFileResponse(){ - if(_content) - _content.close(); -} - -void AsyncFileResponse::_setContentType(const String& path){ - if (path.endsWith(".html")) _contentType = "text/html"; - else if (path.endsWith(".htm")) _contentType = "text/html"; - else if (path.endsWith(".css")) _contentType = "text/css"; - else if (path.endsWith(".json")) _contentType = "application/json"; - else if (path.endsWith(".js")) _contentType = "application/javascript"; - else if (path.endsWith(".png")) _contentType = "image/png"; - else if (path.endsWith(".gif")) _contentType = "image/gif"; - else if (path.endsWith(".jpg")) _contentType = "image/jpeg"; - else if (path.endsWith(".ico")) _contentType = "image/x-icon"; - else if (path.endsWith(".svg")) _contentType = "image/svg+xml"; - else if (path.endsWith(".eot")) _contentType = "font/eot"; - else if (path.endsWith(".woff")) _contentType = "font/woff"; - else if (path.endsWith(".woff2")) _contentType = "font/woff2"; - else if (path.endsWith(".ttf")) _contentType = "font/ttf"; - else if (path.endsWith(".xml")) _contentType = "text/xml"; - else if (path.endsWith(".pdf")) _contentType = "application/pdf"; - else if (path.endsWith(".zip")) _contentType = "application/zip"; - else if(path.endsWith(".gz")) _contentType = "application/x-gzip"; - else _contentType = "text/plain"; -} - -AsyncFileResponse::AsyncFileResponse(FS &fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback): AsyncAbstractResponse(callback){ - _code = 200; - _path = path; - - if(!download && !fs.exists(_path) && fs.exists(_path+".gz")){ - _path = _path+".gz"; - addHeader("Content-Encoding", "gzip"); - _callback = nullptr; // Unable to process zipped templates - _sendContentLength = true; - _chunked = false; - } - - _content = fs.open(_path, "r"); - _contentLength = _content.size(); - - if(contentType == "") - _setContentType(path); - else - _contentType = contentType; - - int filenameStart = path.lastIndexOf('/') + 1; - char buf[26+path.length()-filenameStart]; - char* filename = (char*)path.c_str() + filenameStart; - - if(download) { - // set filename and force download - snprintf(buf, sizeof (buf), "attachment; filename=\"%s\"", filename); - } else { - // set filename and force rendering - snprintf(buf, sizeof (buf), "inline; filename=\"%s\"", filename); - } - addHeader("Content-Disposition", buf); -} - -AsyncFileResponse::AsyncFileResponse(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback): AsyncAbstractResponse(callback){ - _code = 200; - _path = path; - - if(!download && String(content.name()).endsWith(".gz") && !path.endsWith(".gz")){ - addHeader("Content-Encoding", "gzip"); - _callback = nullptr; // Unable to process gzipped templates - _sendContentLength = true; - _chunked = false; - } - - _content = content; - _contentLength = _content.size(); - - if(contentType == "") - _setContentType(path); - else - _contentType = contentType; - - int filenameStart = path.lastIndexOf('/') + 1; - char buf[26+path.length()-filenameStart]; - char* filename = (char*)path.c_str() + filenameStart; - - if(download) { - snprintf(buf, sizeof (buf), "attachment; filename=\"%s\"", filename); - } else { - snprintf(buf, sizeof (buf), "inline; filename=\"%s\"", filename); - } - addHeader("Content-Disposition", buf); -} - -size_t AsyncFileResponse::_fillBuffer(uint8_t *data, size_t len){ - return _content.read(data, len); -} - -/* - * Stream Response - * */ - -AsyncStreamResponse::AsyncStreamResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback): AsyncAbstractResponse(callback) { - _code = 200; - _content = &stream; - _contentLength = len; - _contentType = contentType; -} - -size_t AsyncStreamResponse::_fillBuffer(uint8_t *data, size_t len){ - size_t available = _content->available(); - size_t outLen = (available > len)?len:available; - size_t i; - for(i=0;iread(); - return outLen; -} - -/* - * Callback Response - * */ - -AsyncCallbackResponse::AsyncCallbackResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback): AsyncAbstractResponse(templateCallback) { - _code = 200; - _content = callback; - _contentLength = len; - if(!len) - _sendContentLength = false; - _contentType = contentType; - _filledLength = 0; -} - -size_t AsyncCallbackResponse::_fillBuffer(uint8_t *data, size_t len){ - size_t ret = _content(data, len, _filledLength); - if(ret != RESPONSE_TRY_AGAIN){ - _filledLength += ret; - } - return ret; -} - -/* - * Chunked Response - * */ - -AsyncChunkedResponse::AsyncChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor processorCallback): AsyncAbstractResponse(processorCallback) { - _code = 200; - _content = callback; - _contentLength = 0; - _contentType = contentType; - _sendContentLength = false; - _chunked = true; - _filledLength = 0; -} - -size_t AsyncChunkedResponse::_fillBuffer(uint8_t *data, size_t len){ - size_t ret = _content(data, len, _filledLength); - if(ret != RESPONSE_TRY_AGAIN){ - _filledLength += ret; - } - return ret; -} - -/* - * Progmem Response - * */ - -AsyncProgmemResponse::AsyncProgmemResponse(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback): AsyncAbstractResponse(callback) { - _code = code; - _content = content; - _contentType = contentType; - _contentLength = len; - _readLength = 0; -} - -size_t AsyncProgmemResponse::_fillBuffer(uint8_t *data, size_t len){ - size_t left = _contentLength - _readLength; - if (left > len) { - memcpy_P(data, _content + _readLength, len); - _readLength += len; - return len; - } - memcpy_P(data, _content + _readLength, left); - _readLength += left; - return left; -} - - -/* - * Response Stream (You can print/write/printf to it, up to the contentLen bytes) - * */ - -AsyncResponseStream::AsyncResponseStream(const String& contentType, size_t bufferSize){ - _code = 200; - _contentLength = 0; - _contentType = contentType; - _content = new cbuf(bufferSize); -} - -AsyncResponseStream::~AsyncResponseStream(){ - delete _content; -} - -size_t AsyncResponseStream::_fillBuffer(uint8_t *buf, size_t maxLen){ - return _content->read((char*)buf, maxLen); -} - -size_t AsyncResponseStream::write(const uint8_t *data, size_t len){ - if(_started()) - return 0; - - if(len > _content->room()){ - size_t needed = len - _content->room(); - _content->resizeAdd(needed); - } - size_t written = _content->write((const char*)data, len); - _contentLength += written; - return written; -} - -size_t AsyncResponseStream::write(uint8_t data){ - return write(&data, 1); -} diff --git a/lib/libesp32/ESPAsyncWebServer/src/WebServer.cpp b/lib/libesp32/ESPAsyncWebServer/src/WebServer.cpp deleted file mode 100644 index 3e2b2e40b..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/WebServer.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - Asynchronous WebServer library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#include "ESPAsyncWebServer.h" -#include "WebHandlerImpl.h" - -bool ON_STA_FILTER(AsyncWebServerRequest *request) { - return WiFi.localIP() == request->client()->localIP(); -} - -bool ON_AP_FILTER(AsyncWebServerRequest *request) { - return WiFi.localIP() != request->client()->localIP(); -} - - -AsyncWebServer::AsyncWebServer(uint16_t port) - : _server(port) - , _rewrites(AsyncLinkedList([](AsyncWebRewrite* r){ delete r; })) - , _handlers(AsyncLinkedList([](AsyncWebHandler* h){ delete h; })) -{ - _catchAllHandler = new AsyncCallbackWebHandler(); - if(_catchAllHandler == NULL) - return; - _server.onClient([](void *s, AsyncClient* c){ - if(c == NULL) - return; - c->setRxTimeout(3); - AsyncWebServerRequest *r = new AsyncWebServerRequest((AsyncWebServer*)s, c); - if(r == NULL){ - c->close(true); - c->free(); - delete c; - } - }, this); -} - -AsyncWebServer::~AsyncWebServer(){ - reset(); - end(); - if(_catchAllHandler) delete _catchAllHandler; -} - -AsyncWebRewrite& AsyncWebServer::addRewrite(AsyncWebRewrite* rewrite){ - _rewrites.add(rewrite); - return *rewrite; -} - -bool AsyncWebServer::removeRewrite(AsyncWebRewrite *rewrite){ - return _rewrites.remove(rewrite); -} - -AsyncWebRewrite& AsyncWebServer::rewrite(const char* from, const char* to){ - return addRewrite(new AsyncWebRewrite(from, to)); -} - -AsyncWebHandler& AsyncWebServer::addHandler(AsyncWebHandler* handler){ - _handlers.add(handler); - return *handler; -} - -bool AsyncWebServer::removeHandler(AsyncWebHandler *handler){ - return _handlers.remove(handler); -} - -void AsyncWebServer::begin(){ - _server.setNoDelay(true); - _server.begin(); -} - -void AsyncWebServer::end(){ - _server.end(); -} - -#if ASYNC_TCP_SSL_ENABLED -void AsyncWebServer::onSslFileRequest(AcSSlFileHandler cb, void* arg){ - _server.onSslFileRequest(cb, arg); -} - -void AsyncWebServer::beginSecure(const char *cert, const char *key, const char *password){ - _server.beginSecure(cert, key, password); -} -#endif - -void AsyncWebServer::_handleDisconnect(AsyncWebServerRequest *request){ - delete request; -} - -void AsyncWebServer::_rewriteRequest(AsyncWebServerRequest *request){ - for(const auto& r: _rewrites){ - if (r->match(request)){ - request->_url = r->toUrl(); - request->_addGetParams(r->params()); - } - } -} - -void AsyncWebServer::_attachHandler(AsyncWebServerRequest *request){ - for(const auto& h: _handlers){ - if (h->filter(request) && h->canHandle(request)){ - request->setHandler(h); - return; - } - } - - request->addInterestingHeader("ANY"); - request->setHandler(_catchAllHandler); -} - - -AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload, ArBodyHandlerFunction onBody){ - AsyncCallbackWebHandler* handler = new AsyncCallbackWebHandler(); - handler->setUri(uri); - handler->setMethod(method); - handler->onRequest(onRequest); - handler->onUpload(onUpload); - handler->onBody(onBody); - addHandler(handler); - return *handler; -} - -AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload){ - AsyncCallbackWebHandler* handler = new AsyncCallbackWebHandler(); - handler->setUri(uri); - handler->setMethod(method); - handler->onRequest(onRequest); - handler->onUpload(onUpload); - addHandler(handler); - return *handler; -} - -AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest){ - AsyncCallbackWebHandler* handler = new AsyncCallbackWebHandler(); - handler->setUri(uri); - handler->setMethod(method); - handler->onRequest(onRequest); - addHandler(handler); - return *handler; -} - -AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, ArRequestHandlerFunction onRequest){ - AsyncCallbackWebHandler* handler = new AsyncCallbackWebHandler(); - handler->setUri(uri); - handler->onRequest(onRequest); - addHandler(handler); - return *handler; -} - -AsyncStaticWebHandler& AsyncWebServer::serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_control){ - AsyncStaticWebHandler* handler = new AsyncStaticWebHandler(uri, fs, path, cache_control); - addHandler(handler); - return *handler; -} - -void AsyncWebServer::onNotFound(ArRequestHandlerFunction fn){ - _catchAllHandler->onRequest(fn); -} - -void AsyncWebServer::onFileUpload(ArUploadHandlerFunction fn){ - _catchAllHandler->onUpload(fn); -} - -void AsyncWebServer::onRequestBody(ArBodyHandlerFunction fn){ - _catchAllHandler->onBody(fn); -} - -void AsyncWebServer::reset(){ - _rewrites.free(); - _handlers.free(); - - if (_catchAllHandler != NULL){ - _catchAllHandler->onRequest(NULL); - _catchAllHandler->onUpload(NULL); - _catchAllHandler->onBody(NULL); - } -} - diff --git a/lib/libesp32/ESPAsyncWebServer/src/edit.htm b/lib/libesp32/ESPAsyncWebServer/src/edit.htm deleted file mode 100644 index 43d498455..000000000 --- a/lib/libesp32/ESPAsyncWebServer/src/edit.htm +++ /dev/null @@ -1,627 +0,0 @@ - - - - -ESP Editor - - - - - - -
-
-
-
- - - - diff --git a/lib/libesp32/gpio_viewer/.gitignore b/lib/libesp32/gpio_viewer/.gitignore deleted file mode 100644 index 7f059b39f..000000000 --- a/lib/libesp32/gpio_viewer/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -build -sounds -secrets.h -.vscode \ No newline at end of file diff --git a/lib/libesp32/gpio_viewer/LICENSE b/lib/libesp32/gpio_viewer/LICENSE deleted file mode 100644 index c868c9b62..000000000 --- a/lib/libesp32/gpio_viewer/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 thelastoutpostworkshop - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/lib/libesp32/gpio_viewer/README.md b/lib/libesp32/gpio_viewer/README.md deleted file mode 100644 index b7291510a..000000000 --- a/lib/libesp32/gpio_viewer/README.md +++ /dev/null @@ -1,94 +0,0 @@ -# GPIOViewer Arduino Library to see live GPIO Pins on ESP32 boards - -**Transforms the way you troubleshoot your microcontroller projects**. - -### Youtube Tutorial -[](https://youtu.be/UxkOosaNohU) - -### Installation Arduino IDE (Version 2) ->ℹ️ Make sure you have the latest ESP32 boards by Espressif Systems in your Board Manager
- -- Install the **GPIOViewer Library with the Arduino IDE Library Manager** or Download the [latest release](https://github.com/thelastoutpostworkshop/gpio_viewer/releases/latest) and install the library in the Arduino IDE : `Sketch > Include Library > Add ZIP Library...` -- Download [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) and install the library in the Arduino IDE `Sketch > Include Library > Add ZIP Library...` -- Install the the [AsyncTCP](https://github.com/dvarrel/AsyncTCP) using the Arduino IDE Library Manager. - -### Installation VSCode + PlatformIO - -Add the following to your platformio.ini file: - -``` -lib_deps = - https://github.com/dvarrel/AsyncTCP.git - https://github.com/me-no-dev/ESPAsyncWebServer.git - https://github.com/thelastoutpostworkshop/gpio_viewer.git -``` - -### Usage ->ℹ️ You can also use get examples provided with the library in the Arduino IDE through the menu `File > Examples > GPIOViewer`
->ℹ️ You only need to include the library, declare the GPIOViewer and call begin() at the end of your setup, and that's it!
->ℹ️ The URL to the web GPIO viewer application is printed on the serial monitor
-```c -#include // Must me the first include in your project -GPIOViewer gpio_viewer; - -void setup() -{ - Serial.begin(115200); - - // Comment the next line, If your code aleady include connection to Wifi - gpio_viewer.connectToWifi("Your SSID network", "Your WiFi Password"); - // gpio_viewer.setPort(5555); // You can set the http port, if not set default port is 8080 - - // Your own setup code start here - - // Must be at the end of your setup - // gpio_viewer.setSamplingInterval(25); // You can set the sampling interval in ms, if not set default is 100ms - gpio_viewer.begin(); -} -``` ->ℹ️ The default HTTP port is **8080** and default sampling interval is **100ms**. - -### GPIO Supported - -- Digital -- Analog -- PWM - -### Library Size - -- The GPIOViewer Library adds 50 KB to your projects. -- No worries! All the assets (ex. board images) of the web application are loaded from github pages and don't add to the size of your projects. - -### Performance -- Ensure you have a strong Wifi signal with a good transfer rate. 25ms sampling interval works great on Wifi 6 with 125 Mbps. -- If you get "ERROR: Too many messages queued" on the Serial Monitor, this means the data is not read fast enough by the web application. The data will still be displayed, but with some latency. Reduce the sampling interval or try to improve your Wifi performance. - -### ESP32 Boards Supported ->ℹ️ You can use the "Generic View" in the GPIO Web Application to see GPIO pin activites live even if your board image is not listed
->ℹ️ You can also request an ESP32 board image addition by [creating a new issue](https://github.com/thelastoutpostworkshop/gpio_viewer/issues). - - -| Description | Image | Pinout | -|--------------------|-------------------------------------|-------------------------------------| -| ESP32 VROOM 32D (38 pins) | ! | | -| ESP32 VROOM 32D (30 pins) | ! || -| ESP32 D1 R32 | ! | | -| ESP32 C3 Wroom-02 | ! || -| ESP32 Wroom-32UE | ! || -| ESP32 EVB | ! || -| ESP32 S3 Wroom-1 | ! || -| Esp32 S2 Mini V1.0.0 | ! || -| ESP32 POE | ! || -| ESP32 C3 Mini | ! || -| ESP32 Pico Kit v4.1 | ! || -| Lilygo T7 Mini32 v1.5 | ! || -| Freenove ESP32-S3 | ! || -| Nano ESP32 | ! || -| StickLite-V3-ESP32S3 | ! || -| XIAO-ESP32-C3 | ! || -| T-Display S3 AMOLED | ! || -| TinyPICO Nano | ! || -| TinyPico V3 | ! || -| Wemos Lolin32 Lite V1 | ! || -| Wemos D1 Mini ESP32 | ! || -| XIAO-ESP32-C3 | ! || diff --git a/lib/libesp32/gpio_viewer/examples/gpioviewer/gpioviewer.ino b/lib/libesp32/gpio_viewer/examples/gpioviewer/gpioviewer.ino deleted file mode 100644 index 66def80f3..000000000 --- a/lib/libesp32/gpio_viewer/examples/gpioviewer/gpioviewer.ino +++ /dev/null @@ -1,30 +0,0 @@ -/*** -This example is intended to demonstrate the use of the GPIO Viewer Library. - -Tutorial : https://youtu.be/UxkOosaNohU -Documentation : https://github.com/thelastoutpostworkshop/gpio_viewer -***/ - -#include // Must me the first include in your project -GPIOViewer gpio_viewer; - -void setup() -{ - Serial.begin(115200); - - // Comment the next line, If your code aleady include connection to Wifi - gpio_viewer.connectToWifi("Your SSID network", "Your WiFi Password"); - // gpio_viewer.setPort(5555); // You can set the http port, if not set default port is 8080 - - // Your own setup code start here - - // Must be at the end of your setup - // gpio_viewer.setSamplingInterval(25); // You can set the sampling interval in ms, if not set default is 100ms - gpio_viewer.begin(); -} - -// You don't need to change your loop function -void loop() { - -} -// The rest of your code here \ No newline at end of file diff --git a/lib/libesp32/gpio_viewer/gpio_viewer.ino b/lib/libesp32/gpio_viewer/gpio_viewer.ino deleted file mode 100644 index 24386c2d3..000000000 --- a/lib/libesp32/gpio_viewer/gpio_viewer.ino +++ /dev/null @@ -1,149 +0,0 @@ -#include "src/gpio_viewer.h" -#include -#include // Install this library with the Arduino IDE Library Manager -#include "secrets.h" - -GPIOViewer gpio_viewer; - -#define ROTARY_PIN_A 23 -#define ROTARY_PIN_B 22 -#define ROTARY_PUSH_BUTTON 22 // Not used -SimpleRotary rotary(ROTARY_PIN_A, ROTARY_PIN_B, ROTARY_PUSH_BUTTON); - -int test_digital_pins[] = {33, 25, 26}; -const int testDigitalPinsCount = sizeof(test_digital_pins) / sizeof(test_digital_pins[0]); -int currentLed = 0; // Start with the first LED - -const int analogPinsCount = 3; -int test_analog_pins[analogPinsCount] = {32, 19, 18}; -int analogValue = 0; - -const int freq = 200; -const int resolution = 16; - -struct PWM_PINS -{ - int pin; - int channel; - uint16_t level; -}; - -PWM_PINS test_pwm_pins[] = {{15, 0}, {2, 1}, {0, 2}, {4, 3}}; -const int testPWMPinsCount = sizeof(test_pwm_pins) / sizeof(test_pwm_pins[0]); - -void setup() -{ - Serial.begin(115200); - - gpio_viewer.connectToWifi(ssid, password); // If your code aleady include connection to Wifi, you can comment this line - // gpio_viewer.setPort(5555); // You can set the http port, if not set default port is 8080 - - // Example - Your own setup code start here - test1_setup(); - - // Must be at the end of your setup - gpio_viewer.setSamplingInterval(75); // You can set the sampling interval in ms, if not set, default is 100ms - gpio_viewer.begin(); -} - -void loop() -{ - test1_loop(); -} - -void test1_setup() -{ - uint16_t amount = 0; - for (int i = 0; i < testPWMPinsCount; i++) - { - amount += (65535 / testPWMPinsCount); - ledcSetup(test_pwm_pins[i].channel, freq, resolution); - ledcAttachPin(test_pwm_pins[i].pin, test_pwm_pins[i].channel); - test_pwm_pins[i].level = amount; - } - for (int i = 0; i < testDigitalPinsCount; i++) - { - pinMode(test_digital_pins[i], OUTPUT); - digitalWrite(test_digital_pins[i], LOW); - } - for (int i = 0; i < analogPinsCount; i++) - { - pinMode(test_analog_pins[i], OUTPUT); - } - xTaskCreate(readRotaryEncoderTask, // Task function - "ReadRotaryEncoder", // Name of the task (for debugging) - 2048, // Stack size (bytes) - NULL, // Parameter to pass to the function - 1, // Task priority - NULL); -} -void test1_loop() -{ - for (int i = 0; i < analogPinsCount; i++) - { - analogValue += (i * 3); - analogWrite(test_analog_pins[i], analogValue++); - } - for (int i = 0; i < testPWMPinsCount; i++) - { - ledcWrite(test_pwm_pins[i].channel, test_pwm_pins[i].level); - delay(150); - } - delay(300); - for (int i = 0; i < testPWMPinsCount; i++) - { - ledcWrite(test_pwm_pins[i].channel, test_pwm_pins[i].level / 2); - delay(150); - } - for (int i = 0; i < testDigitalPinsCount; i++) - { - if (digitalRead(test_digital_pins[i]) == LOW) - { - - digitalWrite(test_digital_pins[i], HIGH); - } - else - { - - digitalWrite(test_digital_pins[i], LOW); - } - } - delay(300); -} - -void updateLeds() -{ - for (int i = 0; i < testDigitalPinsCount; i++) - { - digitalWrite(test_digital_pins[i], i == currentLed ? HIGH : LOW); - } -} - -void readRotaryEncoderTask(void *pvParameters) -{ - for (;;) - { // Infinite loop - readRotaryEncoder(); - vTaskDelay(pdMS_TO_TICKS(10)); // Delay for debouncing, adjust as needed - } -} - -void readRotaryEncoder(void) -{ - byte i; - i = rotary.rotate(); - - if (i == 1) - { - currentLed = (currentLed - 1 + testDigitalPinsCount) % testDigitalPinsCount; - updateLeds(); - Serial.println("CounterClockwise"); - } - - if (i == 2) - { - currentLed = (currentLed + 1) % testDigitalPinsCount; - updateLeds(); - Serial.println("Clockwise"); - } -} diff --git a/lib/libesp32/gpio_viewer/keywords.txt b/lib/libesp32/gpio_viewer/keywords.txt deleted file mode 100644 index 17719d72c..000000000 --- a/lib/libesp32/gpio_viewer/keywords.txt +++ /dev/null @@ -1,16 +0,0 @@ -[Keywords] -####################################### -# Datatypes (KEYWORD1) -####################################### -byte -boolean -uint16_t -int16_t -int -enum - -####################################### -# Methods and Functions (KEYWORD2) -####################################### -begin - diff --git a/lib/libesp32/gpio_viewer/library.properties b/lib/libesp32/gpio_viewer/library.properties deleted file mode 100644 index c65ff1276..000000000 --- a/lib/libesp32/gpio_viewer/library.properties +++ /dev/null @@ -1,11 +0,0 @@ -name=GPIOViewer -version=1.0.4 -author=The Last Outpost Workshop -maintainer=The Last Outpost Workshop -sentence=Web Application to view GPIO pins live! -paragraph=Works ESP32 -category=Other -keywords=keywords.txt -url=https://github.com/thelastoutpostworkshop/gpio_viewer -architectures=esp32 -depends=AsyncTCP \ No newline at end of file diff --git a/lib/libesp32/gpio_viewer/src/gpio_viewer.h b/lib/libesp32/gpio_viewer/src/gpio_viewer.h deleted file mode 100644 index 6a4f1a58d..000000000 --- a/lib/libesp32/gpio_viewer/src/gpio_viewer.h +++ /dev/null @@ -1,360 +0,0 @@ -#ifndef _GPIOVIEWER_ -#define _GPIOVIEWER_ -#ifndef WEBSERVER_H -// Compatiblity with the Wifi Manager if your using it in your project -#include -#endif -#ifndef WiFi_h -#include -#endif -#ifndef _ESPAsyncWebServer_H_ -#include -#endif -#ifndef ASYNCTCP_H_ -#include -#endif -#ifndef INC_FREERTOS_H -#include -#endif -#ifndef INC_TASK_H -#include -#endif -#endif - -// Start Tasmota specific ************************************* -extern int32_t analogGetChannel2(uint32_t pin); -extern uint8_t ledcReadResolution(uint8_t chan); -// Tasmota Logging -extern void AddLog(uint32_t loglevel, PGM_P formatP, ...); -// 0 1 2 3 4 -//enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE}; -// End Tasmota specific *************************************** - -const char *release = "1.0.5"; - -const String baseURL = "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/"; - -#define maxGPIOPins 49 - -// Global variables to capture PMW pins -const int maxChannels = 64; -int ledcChannelPin[maxChannels][2]; -int ledcChannelPinCount = 0; -int ledcChannelResolution[maxChannels][2]; -int ledcChannelResolutionCount = 0; - -enum pinTypes -{ - digitalPin = 0, - PWMPin = 1, - analogPin = 2 -}; - -class GPIOViewer -{ -public: - GPIOViewer() - { - } - - ~GPIOViewer() - { - delete events; - server->end(); - } - - void setPort(uint16_t port) - { - this->port = port; - } - - void setSamplingInterval(unsigned long samplingInterval) - { - this->samplingInterval = samplingInterval; - } - - void begin() - { -// Serial.printf("ESP32 Core Version %d.%d.%d\n", ESP_ARDUINO_VERSION_MAJOR, ESP_ARDUINO_VERSION_MINOR, ESP_ARDUINO_VERSION_PATCH); -// if (ESP_ARDUINO_VERSION_MAJOR < 2) -// { -// Serial.printf("Your ESP32 Core Version is not supported, update your ESP32 boards to the latest version\n"); -// return; -// } - printPWNTraps(); - checkWifiStatus(); - - server = new AsyncWebServer(port); - - // Set CORS headers for global responses - DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*"); - DefaultHeaders::Instance().addHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); - DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "Content-Type"); - - // Initialize and set up the AsyncEventSource - events = new AsyncEventSource("/events"); - events->onConnect([this](AsyncEventSourceClient *client) - { this->resetStatePins(); }); - - server->addHandler(events); - - // Serve the main page - server->on("/", [this](AsyncWebServerRequest *request) - { request->send_P(200, "text/html", generateIndexHTML().c_str()); }); - - server->on("/release", HTTP_GET, [this](AsyncWebServerRequest *request) - { sendMinReleaseVersion(request); }); - - server->begin(); - - // Create a task for monitoring GPIOs - xTaskCreate(&GPIOViewer::monitorTaskStatic, "GPIO Monitor Task", 2048, this, 1, NULL); - } - - static void monitorTaskStatic(void *pvParameter) - { - static_cast(pvParameter)->monitorTask(); - } - -private: - uint32_t lastPinStates[maxGPIOPins]; - uint16_t port = 8080; - unsigned long samplingInterval = 100; - AsyncWebServer *server; - AsyncEventSource *events; - size_t freeHeap = 0; - String freeRAM = formatBytes(ESP.getFreeSketchSpace()); - - void sendMinReleaseVersion(AsyncWebServerRequest *request) - { - String jsonResponse = "{\"release\": \"" + String(release) + "\"}"; - - request->send(200, "application/json", jsonResponse); - } - void checkWifiStatus(void) - { - if (WiFi.status() == WL_CONNECTED) - { - AddLog(2, "IOV: GPIOViewer Web Application URL is http://%s:%d", WiFi.localIP().toString().c_str(), port); - } - else - { - AddLog(2, "IOV: No network connection"); - } - } - - void printPWNTraps() - { - // Start Tasmota specific ************************************* - for (uint32_t pin = 0; pin < SOC_GPIO_PIN_COUNT; pin++) { - int32_t channel = analogGetChannel2(pin); - if (channel > -1) { - ledcChannelPin[ledcChannelPinCount][0] = pin; - ledcChannelPin[ledcChannelPinCount++][1] = channel; - uint8_t resolution = ledcReadResolution(channel); - ledcChannelResolution[ledcChannelResolutionCount][0] = channel; - ledcChannelResolution[ledcChannelResolutionCount++][1] = resolution; - } - } - // End Tasmota specific *************************************** - - AddLog(3, "IOV: %d pins are PWM", ledcChannelPinCount); - for (int i = 0; i < ledcChannelPinCount; i++) - { - AddLog(3, "IOV: pin %d is using channel %d", ledcChannelPin[i][0], ledcChannelPin[i][1]); - } - AddLog(3, "IOV: %d channels are used", ledcChannelResolutionCount); - for (int i = 0; i < ledcChannelResolutionCount; i++) - { - AddLog(3, "IOV: channel %d resolution is %d bits", ledcChannelResolution[i][0], ledcChannelResolution[i][1]); - } - } - - String generateIndexHTML() - { - String html = "ESP32 GPIO State"; - - html += ""; - html += ""; - html += ""; - html += ""; - - html += ""); - html += ""); - html += ""; - - html += "
\n"; - - html += "
"; - html += "
"; - - // Image - html += "
\n"; - html += "
"; - html += "Board Image\n"; - - html += "
"; - - html += "
"; - - // Append the script variables - String portScript = ""; - html += portScript; - - String eventSource = ""; - html += eventSource; - - String ip = ""; - html += ip; - - String sampling = ""; - html += sampling; - - html += ""; - - html += ""; - return html; - } - - void resetStatePins(void) - { - uint32_t originalValue; - pinTypes pintype; - AddLog(2, "IOV: GPIOViewer Connected, sampling interval is %lums", samplingInterval); - - for (int i = 0; i < maxGPIOPins; i++) - { - lastPinStates[i] = readGPIO(i, &originalValue, &pintype); - } - } - - // Monitor GPIO Values - void monitorTask() - { - uint32_t originalValue; - pinTypes pintype; - while (1) - { - String jsonMessage = "{"; - bool hasChanges = false; - - for (int i = 0; i < maxGPIOPins; i++) - { - int currentState = readGPIO(i, &originalValue, &pintype); - - if (originalValue != lastPinStates[i]) - { - if (hasChanges) - { - jsonMessage += ", "; - } - jsonMessage += "\"" + String(i) + "\": {\"s\": " + currentState + ", \"v\": " + originalValue + ", \"t\": " + pintype + "}"; - lastPinStates[i] = currentState; - hasChanges = true; - } - } - - jsonMessage += "}"; - - if (hasChanges) - { - sendGPIOStates(jsonMessage); - } - - size_t heap = esp_get_free_heap_size(); - if (heap != freeHeap) - { - freeHeap = heap; - events->send(formatBytes(freeHeap).c_str(), "free_heap", millis()); - } - - vTaskDelay(pdMS_TO_TICKS(samplingInterval)); - } - } - - int getLedcChannelForPin(int pin) - { - for (int i = 0; i < ledcChannelPinCount; i++) - { - if (ledcChannelPin[i][0] == pin) - { - return ledcChannelPin[i][1]; - } - } - return -1; // Pin not found, return -1 to indicate no channel is associated - } - int getChannelResolution(int channel) - { - for (int i = 0; i < ledcChannelResolutionCount; i++) - { - if (ledcChannelResolution[i][0] == channel) - { - return ledcChannelResolution[i][1]; - } - } - return -1; // Pin not found, return -1 to indicate no channel is associated - } - - int readGPIO(int gpioNum, uint32_t *originalValue, pinTypes *pintype) - { - int channel = getLedcChannelForPin(gpioNum); - int value; - if (channel != -1) - { - // This is a PWM Pin - value = mapLedcReadTo8Bit(channel, originalValue); - *pintype = PWMPin; - return value; - } - uint8_t analogChannel = analogGetChannel(gpioNum); - if (analogChannel != 0 && analogChannel != 255) - { - // This is an analog pin - // Serial.printf("A Pin %d value=%d,channel=%d\n", gpioNum, value,analogChannel); - - value = mapLedcReadTo8Bit(analogChannel, originalValue); - *pintype = analogPin; - return value; - } - else - { - // This is a digital pin - *pintype = digitalPin; - value = digitalRead(gpioNum); - *originalValue = value; - if (value == 1) - { - return 256; - } - return 0; - } - } - - int mapLedcReadTo8Bit(int channel, uint32_t *originalValue) - { - uint32_t maxDutyCycle = (1 << getChannelResolution(channel)) - 1; - *originalValue = ledcRead(channel); - return map(*originalValue, 0, maxDutyCycle, 0, 255); - } - - void sendGPIOStates(const String &states) - { - events->send(states.c_str(), "gpio-state", millis()); - } - - String formatBytes(size_t bytes) - { - if (bytes < 1024) - { - return String(bytes) + " B"; - } - else if (bytes < (1024 * 1024)) - { - return String(bytes / 1024.0, 2) + " KB"; - } - else - { - return String(bytes / 1024.0 / 1024.0, 2) + " MB"; - } - } -}; \ No newline at end of file From 0ed01c3b1d9064a603834890d11bb5a8da0e8a44 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 4 Jan 2024 22:50:41 +0100 Subject: [PATCH 074/303] Revert "Add ESP32 experimental support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled" This reverts commit 9d27f395d8012c4fd1e3d74384d50d215679fecb. --- CHANGELOG.md | 1 - RELEASENOTES.md | 1 - tasmota/tasmota.ino | 15 --------------- 3 files changed, 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6382c1f2..11631b509 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,6 @@ All notable changes to this project will be documented in this file. ## [13.3.0.2] ### Added - HASPmota type `chart` (#20372) -- ESP32 experimental support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled ### Breaking Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index f566b94db..6198b8991 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -124,7 +124,6 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) - Support negative power on BL0942 using index 5..8 [#20322](https://github.com/arendst/Tasmota/issues/20322) - ESP32 used UART information -- ESP32 experimental support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled - Berry `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) - HASPmota type `chart` [#20372](https://github.com/arendst/Tasmota/issues/20372) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index aa8802215..7febc7a3b 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -17,12 +17,6 @@ along with this program. If not, see . */ -//#define USE_ESP32_GPIO_VIEWER -#ifdef USE_ESP32_GPIO_VIEWER -#include // Must me the first include in your project -GPIOViewer gpio_viewer; -#endif // USE_ESP32_GPIO_VIEWER - // Location specific includes #ifndef ESP32_STAGE // ESP32 Stage has no core_version.h file. Disable include via PlatformIO Option #include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_7_1) @@ -898,15 +892,6 @@ void Scheduler(void) { #ifndef SYSLOG_UPDATE_SECOND SyslogAsync(false); #endif // SYSLOG_UPDATE_SECOND - -#ifdef USE_ESP32_GPIO_VIEWER - static bool gpio_viewer_wifi_connected = false; - if (!gpio_viewer_wifi_connected && !TasmotaGlobal.global_state.network_down) { - gpio_viewer_wifi_connected = true; - gpio_viewer.setSamplingInterval(200); // You can set the sampling interval in ms, if not set default is 100ms - gpio_viewer.begin(); - } -#endif // USE_ESP32_GPIO_VIEWER } void loop(void) { From af2b90caac0aff12edaf01de9fac72d186276d79 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Fri, 5 Jan 2024 09:54:18 +0100 Subject: [PATCH 075/303] Berry add support for `tcpclientasync` in `tcpserver` (#20401) --- CHANGELOG.md | 1 + .../berry_tasmota/src/be_tcpserver_class.c | 3 +- .../xdrv_52_3_berry_tcpclientasync.ino | 54 ++++- .../xdrv_52_3_berry_tcpserver.ino | 194 +++++++++++++++++- 4 files changed, 238 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11631b509..1bf7ddb77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. ## [13.3.0.2] ### Added - HASPmota type `chart` (#20372) +- Berry add support for `tcpclientasync` in `tcpserver` ### Breaking Changed diff --git a/lib/libesp32/berry_tasmota/src/be_tcpserver_class.c b/lib/libesp32/berry_tasmota/src/be_tcpserver_class.c index c8aa216d4..292b758ae 100644 --- a/lib/libesp32/berry_tasmota/src/be_tcpserver_class.c +++ b/lib/libesp32/berry_tasmota/src/be_tcpserver_class.c @@ -13,7 +13,7 @@ extern void tcpserver_deinit(void *server_tcp); BE_FUNC_ extern void tcpserver_close(void *server); BE_FUNC_CTYPE_DECLARE(tcpserver_close, "", ".") extern bbool tcpserver_hasclient(void *server); BE_FUNC_CTYPE_DECLARE(tcpserver_hasclient, "b", ".") extern void * tcpserver_accept(struct bvm *vm, void *server); BE_FUNC_CTYPE_DECLARE(tcpserver_accept, "tcpclient", "@.") - +extern void * tcpserver_acceptasync(struct bvm *vm, void *server); BE_FUNC_CTYPE_DECLARE(tcpserver_acceptasync, "tcpclientasync", "@.") #include "be_fixed_be_class_tcpserver.h" @@ -26,6 +26,7 @@ class be_class_tcpserver (scope: global, name: tcpserver) { close, ctype_func(tcpserver_close) hasclient, ctype_func(tcpserver_hasclient) accept, ctype_func(tcpserver_accept) + acceptasync, ctype_func(tcpserver_acceptasync) } @const_object_info_end */ diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino index 720ebfb8d..948351494 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino @@ -47,6 +47,13 @@ public: } + // following is used when accepting a new connection as server + AsyncTCPClient(int fd) : sockfd(fd), state(AsyncTCPState::CONNECTED), _timeout_ms(1), local_port(-1) { + if (sockfd < 0) { + state = AsyncTCPState::REFUSED; + } + } + ~AsyncTCPClient() { this->stop(); } @@ -324,25 +331,58 @@ public: struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&local_address; local_port = ntohs(saddr6->sin6_port); if (T_IN6_IS_ADDR_V4MAPPED(saddr6->sin6_addr.un.u32_addr)) { - local_addr = IPAddress(IPv4, (uint8_t*)saddr6->sin6_addr.s6_addr+12); + local_addr = IPAddress(IPv4, (uint8_t*)saddr6->sin6_addr.s6_addr+12, 0); } else { -#if ESP_IDF_VERSION_MAJOR >= 5 local_addr = IPAddress(IPv6, (uint8_t*)(saddr6->sin6_addr.s6_addr), saddr6->sin6_scope_id); -#else - local_addr = IPAddress(IPv6, (uint8_t*)(saddr6->sin6_addr.s6_addr)); -#endif } } #endif // USE_IPV6 } } + + IPAddress remoteIP() const { + struct sockaddr_storage addr; + socklen_t len = sizeof addr; + getpeername(sockfd, (struct sockaddr*)&addr, &len); + + // IPv4 socket, old way + if (((struct sockaddr*)&addr)->sa_family == AF_INET) { + struct sockaddr_in *s = (struct sockaddr_in *)&addr; + return IPAddress((uint32_t)(s->sin_addr.s_addr)); + } + +#if LWIP_IPV6 + // IPv6, but it might be IPv4 mapped address + if (((struct sockaddr*)&addr)->sa_family == AF_INET6) { + struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&addr; + if (T_IN6_IS_ADDR_V4MAPPED(saddr6->sin6_addr.un.u32_addr)) { + return IPAddress(IPv4, (uint8_t*)saddr6->sin6_addr.s6_addr+12, 0); + } else { + return IPAddress(IPv6, (uint8_t*)(saddr6->sin6_addr.s6_addr), saddr6->sin6_scope_id); + } + } +#endif + return (IPAddress(0,0,0,0)); + + } + uint16_t remotePort() const { + + struct sockaddr_storage addr; + socklen_t len = sizeof addr; + getpeername(sockfd, (struct sockaddr*)&addr, &len); + struct sockaddr_in *s = (struct sockaddr_in *)&addr; + return ntohs(s->sin_port); + } + + const IPAddress localIP() const { return local_addr; } + uint16_t localPort() const { return local_port; } + + public: int sockfd; AsyncTCPState state; uint32_t _timeout_ms; - String remota_addr; // address in numerical format (after DNS resolution), either IPv4 or IPv6 - uint16_t remote_port; // remote port number IPAddress local_addr; int32_t local_port; // -1 if unknown or invalid }; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino index 1040ff255..9ac27ee6e 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino @@ -24,6 +24,176 @@ #include +// WiFiServerAsync can return either `WiFiClient` (sync) or `AsyncTCPClient` (async) +// +class WiFiServerAsync { + protected: + int sockfd; + int _accepted_sockfd = -1; + IPAddress _addr; + uint16_t _port; + uint8_t _max_clients; + bool _listening; + bool _noDelay = false; + + + public: + void listenOnLocalhost(){} + + WiFiServerAsync(uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_addr(),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) { + } + WiFiServerAsync(const IPAddress& addr, uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_addr(addr),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) { + } + ~WiFiServerAsync(){ end();} + WiFiClient available(); + WiFiClient accept(){return available();} + AsyncTCPClient * availableAsync(); + AsyncTCPClient * acceptAsync(){return availableAsync();} + void begin(uint16_t port=0); + void begin(uint16_t port, int reuse_enable); + void setNoDelay(bool nodelay); + bool getNoDelay(); + bool hasClient(); + + void end(); + void close(); + void stop(); + operator bool(){return _listening;} + int setTimeout(uint32_t seconds); + void stopAll(); public: +}; + + +int WiFiServerAsync::setTimeout(uint32_t seconds){ + struct timeval tv; + tv.tv_sec = seconds; + tv.tv_usec = 0; + if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)) < 0) + return -1; + return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval)); +} + +void WiFiServerAsync::stopAll(){} + +WiFiClient WiFiServerAsync::available(){ + if(!_listening) + return WiFiClient(); + int client_sock; + if (_accepted_sockfd >= 0) { + client_sock = _accepted_sockfd; + _accepted_sockfd = -1; + } + else { + struct sockaddr_in6 _client; + int cs = sizeof(struct sockaddr_in6); + client_sock = lwip_accept(sockfd, (struct sockaddr *)&_client, (socklen_t*)&cs); + } + if(client_sock >= 0){ + int val = 1; + if(setsockopt(client_sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(int)) == ESP_OK) { + val = _noDelay; + if(setsockopt(client_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(int)) == ESP_OK) + return WiFiClient(client_sock); + } + } + return WiFiClient(); +} + +// specific Async version +AsyncTCPClient * WiFiServerAsync::availableAsync(){ + if(!_listening) + return new AsyncTCPClient(); + int client_sock; + if (_accepted_sockfd >= 0) { + client_sock = _accepted_sockfd; + _accepted_sockfd = -1; + } + else { + struct sockaddr_in6 _client; + int cs = sizeof(struct sockaddr_in6); + client_sock = lwip_accept(sockfd, (struct sockaddr *)&_client, (socklen_t*)&cs); + } + if(client_sock >= 0){ + int val = 1; + if(setsockopt(client_sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(int)) == ESP_OK) { + val = _noDelay; + if(setsockopt(client_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(int)) == ESP_OK) + return new AsyncTCPClient(client_sock); + } + } + return new AsyncTCPClient(); +} + +void WiFiServerAsync::begin(uint16_t port){ + begin(port, 1); +} + +void WiFiServerAsync::begin(uint16_t port, int enable){ + if(_listening) + return; + if(port){ + _port = port; + } + struct sockaddr_in6 server; + sockfd = socket(AF_INET6 , SOCK_STREAM, 0); + if (sockfd < 0) + return; + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); + server.sin6_family = AF_INET6; + if (_addr.type() == IPv4) { + memcpy(server.sin6_addr.s6_addr+11, (uint8_t*)&_addr[0], 4); + server.sin6_addr.s6_addr[10] = 0xFF; + server.sin6_addr.s6_addr[11] = 0xFF; + } else { + memcpy(server.sin6_addr.s6_addr, (uint8_t*)&_addr[0], 16); + } + memset(server.sin6_addr.s6_addr, 0x0, 16); + server.sin6_port = htons(_port); + if(bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) + return; + if(listen(sockfd , _max_clients) < 0) + return; + fcntl(sockfd, F_SETFL, O_NONBLOCK); + _listening = true; + _noDelay = false; + _accepted_sockfd = -1; +} + +void WiFiServerAsync::setNoDelay(bool nodelay) { + _noDelay = nodelay; +} + +bool WiFiServerAsync::getNoDelay() { + return _noDelay; +} + +bool WiFiServerAsync::hasClient() { + if (_accepted_sockfd >= 0) { + return true; + } + struct sockaddr_in6 _client; + int cs = sizeof(struct sockaddr_in6); + _accepted_sockfd = lwip_accept(sockfd, (struct sockaddr *)&_client, (socklen_t*)&cs); + if (_accepted_sockfd >= 0) { + return true; + } + return false; +} + +void WiFiServerAsync::end(){ + lwip_close(sockfd); + sockfd = -1; + _listening = false; +} + +void WiFiServerAsync::close(){ + end(); +} + +void WiFiServerAsync::stop(){ + end(); +} + /*********************************************************************************************\ * Native functions mapped to Berry functions * @@ -31,7 +201,7 @@ extern "C" { const void* tcpserver_init(struct bvm *vm, int32_t tcp_port) { if (tcp_port > 0 && tcp_port < 65535) { - WiFiServer *server_tcp = new WiFiServer(tcp_port); + WiFiServerAsync *server_tcp = new WiFiServerAsync(tcp_port); server_tcp->begin(); // start TCP server if (!*server_tcp) { be_raise(vm, "network_error", "Failed to open socket"); @@ -45,7 +215,7 @@ extern "C" { } void tcpserver_deinit(void *server) { - WiFiServer *server_tcp = (WiFiServer*) server; + WiFiServerAsync *server_tcp = (WiFiServerAsync*) server; if (server_tcp) { server_tcp->stop(); delete server_tcp; @@ -53,23 +223,23 @@ extern "C" { } void tcpserver_close(void *server) { - WiFiServer *server_tcp = (WiFiServer*) server; + WiFiServerAsync *server_tcp = (WiFiServerAsync*) server; if (server_tcp) { server_tcp->stop(); } } bbool tcpserver_hasclient(void *server) { - WiFiServer *server_tcp = (WiFiServer*) server; + WiFiServerAsync *server_tcp = (WiFiServerAsync*) server; return server_tcp->hasClient(); } void * tcpserver_accept(struct bvm *vm, void *server) { - WiFiServer *server_tcp = (WiFiServer*) server; + WiFiServerAsync *server_tcp = (WiFiServerAsync*) server; WiFiClient * client_ptr = nullptr; if (server_tcp->hasClient()) { WiFiClient new_client = server_tcp->available(); - AddLog(LOG_LEVEL_INFO, "BRY: Got connection from %s", new_client.remoteIP().toString().c_str()); + AddLog(LOG_LEVEL_INFO, "BRY: Got connection from %s:%i local %s:%i", new_client.remoteIP().toString().c_str(), new_client.remotePort(), new_client.localIP().toString().c_str(), new_client.localPort()); client_ptr = new WiFiClient(); *client_ptr = new_client; } else { @@ -78,6 +248,18 @@ extern "C" { return client_ptr; } + void * tcpserver_acceptasync(struct bvm *vm, void *server) { + WiFiServerAsync *server_tcp = (WiFiServerAsync*) server; + AsyncTCPClient * client_ptr = nullptr; + if (server_tcp->hasClient()) { + client_ptr = server_tcp->availableAsync(); + AddLog(LOG_LEVEL_INFO, "BRY: Got connection from %s:%i local %s:%i", client_ptr->remoteIP().toString().c_str(), client_ptr->remotePort(), client_ptr->localIP().toString().c_str(), client_ptr->localPort()); + } else { + be_raise(vm, "internal_error", "tcpserver has no client connected"); + } + return client_ptr; + } + } #endif // USE_BERRY_TCPSERVER From 15b40801d4d5679630eabb8bf61aed3db38a1727 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 6 Jan 2024 17:03:51 +0100 Subject: [PATCH 076/303] Fixes for tcpasync (#20411) --- lib/libesp32/berry_tasmota/solidify_all.be | 2 +- .../berry_tasmota/src/embedded/tasmota_class.be | 3 +-- .../src/solidify/solidified_tasmota_class.h | 10 +++++----- .../xdrv_52_3_berry_tcpclientasync.ino | 3 +-- .../tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino | 9 +++++---- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/lib/libesp32/berry_tasmota/solidify_all.be b/lib/libesp32/berry_tasmota/solidify_all.be index 8961f50af..1a5ffe678 100755 --- a/lib/libesp32/berry_tasmota/solidify_all.be +++ b/lib/libesp32/berry_tasmota/solidify_all.be @@ -12,7 +12,7 @@ import sys sys.path().push('src/embedded') # allow to import from src/embedded # globals that need to exist to make compilation succeed -var globs = "path,ctypes_bytes_dyn,tasmota,ccronexpr,gpio,light,webclient,load,MD5,lv,light_state,udp,I2C_Driver," +var globs = "path,ctypes_bytes_dyn,tasmota,ccronexpr,gpio,light,webclient,load,MD5,lv,light_state,udp,I2C_Driver,tcpserver," "lv_clock,lv_clock_icon,lv_signal_arcs,lv_signal_bars,lv_wifi_arcs_icon,lv_wifi_arcs," "lv_wifi_bars_icon,lv_wifi_bars," "_lvgl," diff --git a/lib/libesp32/berry_tasmota/src/embedded/tasmota_class.be b/lib/libesp32/berry_tasmota/src/embedded/tasmota_class.be index b25620118..981c49482 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/tasmota_class.be +++ b/lib/libesp32/berry_tasmota/src/embedded/tasmota_class.be @@ -557,8 +557,7 @@ class Tasmota # iterate and call each closure var i = 0 - var sz = size(fl) - while i < sz + while i < size(fl) # note: this is not guarded in try/except for performance reasons. The inner function must not raise exceptions fl[i]() i += 1 diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_tasmota_class.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_tasmota_class.h index 6e545efad..471319508 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_tasmota_class.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_tasmota_class.h @@ -110,12 +110,12 @@ be_local_closure(Tasmota_fast_loop, /* name */ 0x600C000C, // 0005 GETGBL R3 G12 0x5C100200, // 0006 MOVE R4 R1 0x7C0C0200, // 0007 CALL R3 1 - 0x14100403, // 0008 LT R4 R2 R3 - 0x78120003, // 0009 JMPF R4 #000E - 0x94100202, // 000A GETIDX R4 R1 R2 - 0x7C100000, // 000B CALL R4 0 + 0x140C0403, // 0008 LT R3 R2 R3 + 0x780E0003, // 0009 JMPF R3 #000E + 0x940C0202, // 000A GETIDX R3 R1 R2 + 0x7C0C0000, // 000B CALL R3 0 0x00080502, // 000C ADD R2 R2 K2 - 0x7001FFF9, // 000D JMP #0008 + 0x7001FFF6, // 000D JMP #0005 0x80000000, // 000E RET 0 }) ) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino index 948351494..eafd5e8df 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino @@ -186,8 +186,7 @@ public: stop(); break; default: - // AddLog(LOG_LEVEL_DEBUG, "BRY: tcpclientasync unexpected: RES: %d, ERR: %d", res, errno); - stop(); + // AddLog(LOG_LEVEL_DEBUG, "BRY: tcpclientasync unexpected: RES: %d, ERR: %d, sockfd=%d", res, errno, sockfd); break; } } else { diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino index 9ac27ee6e..b813dddc8 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino @@ -38,8 +38,6 @@ class WiFiServerAsync { public: - void listenOnLocalhost(){} - WiFiServerAsync(uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_addr(),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) { } WiFiServerAsync(const IPAddress& addr, uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_addr(addr),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) { @@ -117,8 +115,11 @@ AsyncTCPClient * WiFiServerAsync::availableAsync(){ int val = 1; if(setsockopt(client_sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(int)) == ESP_OK) { val = _noDelay; - if(setsockopt(client_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(int)) == ESP_OK) - return new AsyncTCPClient(client_sock); + if(setsockopt(client_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(int)) == ESP_OK) { + if (fcntl(client_sock, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK ) == ESP_OK) { // set non-blocking + return new AsyncTCPClient(client_sock); + } + } } } return new AsyncTCPClient(); From ea6b191378084dd05fdf517a980921b819e50677 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 6 Jan 2024 17:32:50 +0100 Subject: [PATCH 077/303] Berry add `tasmota.urlbecload(url:string) -> bool` (#20412) --- CHANGELOG.md | 1 + lib/libesp32/berry_tasmota/src/be_tasmota_lib.c | 5 +++++ tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino | 3 ++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bf7ddb77..de53ec5f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - HASPmota type `chart` (#20372) - Berry add support for `tcpclientasync` in `tcpserver` +- Berry add `tasmota.urlbecload(url:string) -> bool` ### Breaking Changed diff --git a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c index f023a832f..5a6be0281 100644 --- a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c @@ -6,6 +6,7 @@ #include "be_constobj.h" #include "be_ctypes.h" #include "be_mapping.h" +#include "be_ctypes.h" extern struct TasmotaGlobal_t TasmotaGlobal; extern struct TSettings * Settings; @@ -69,6 +70,9 @@ extern int tasm_apply_str_op(bvm *vm); extern int32_t be_Tasmota_version(void); BE_FUNC_CTYPE_DECLARE(be_Tasmota_version, "i", "-"); +extern bbool BerryBECLoader(const char * url); +BE_FUNC_CTYPE_DECLARE(BerryBECLoader, "b", "s") + #include "solidify/solidified_tasmota_class.h" #include "solidify/solidified_rule_matcher.h" #include "solidify/solidified_trigger_class.h" @@ -177,6 +181,7 @@ class be_class_tasmota (scope: global, name: Tasmota) { time_str, closure(Tasmota_time_str_closure) urlfetch, closure(Tasmota_urlfetch_closure) urlfetch_cmd, closure(Tasmota_urlfetch_cmd_closure) + urlbecload, static_ctype_func(BerryBECLoader) add_cron, closure(Tasmota_add_cron_closure) run_cron, closure(Tasmota_run_cron_closure) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino index 70db00be5..a514baeac 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino @@ -778,6 +778,7 @@ void HandleBerryPartiionWizardLoaderButton(void) { } } +extern "C" bbool BerryBECLoader(const char * url); void HandleBerryPartitionWizardLoader(void) { if (BerryBECLoader(USE_BERRY_PARTITION_WIZARD_URL)) { // All good, redirect @@ -792,7 +793,7 @@ void HandleBerryPartitionWizardLoader(void) { #endif //USE_BERRY_PARTITION_WIZARD // return true if successful -bool BerryBECLoader(const char * url) { +extern "C" bbool BerryBECLoader(const char * url) { bvm *vm = berry.vm; HTTPClientLight cl; From 2f184b394fd8aba4de7d43c0727bdd993b444c33 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 6 Jan 2024 17:54:23 +0100 Subject: [PATCH 078/303] Add GPIO Viewer to see realtime GPIO states. Enable with define USE_GPIO_VIEWER --- CHANGELOG.md | 5 +- RELEASENOTES.md | 4 + .../xdrv_121_gpioviewer.ino | 351 ++++++++++++++++++ 3 files changed, 358 insertions(+), 2 deletions(-) create mode 100644 tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino diff --git a/CHANGELOG.md b/CHANGELOG.md index de53ec5f5..abbff6c0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,9 @@ All notable changes to this project will be documented in this file. ## [13.3.0.2] ### Added - HASPmota type `chart` (#20372) -- Berry add support for `tcpclientasync` in `tcpserver` -- Berry add `tasmota.urlbecload(url:string) -> bool` +- Berry add support for `tcpclientasync` in `tcpserver` (#20401) +- Berry add `tasmota.urlbecload(url:string) -> bool` (#20412) +- GPIO Viewer to see realtime GPIO states. Enable with define USE_GPIO_VIEWER ### Breaking Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6198b8991..de5928873 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -121,10 +121,14 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Support for CST816S touch interface [#20213](https://github.com/arendst/Tasmota/issues/20213) - Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247) - Display of active drivers using command ``status 4`` +- GPIO Viewer to see realtime GPIO states. Enable with define USE_GPIO_VIEWER - NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) - Support negative power on BL0942 using index 5..8 [#20322](https://github.com/arendst/Tasmota/issues/20322) - ESP32 used UART information +- ESP32 experimental support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled - Berry `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) +- Berry add support for `tcpclientasync` in `tcpserver` [#20401](https://github.com/arendst/Tasmota/issues/20401) +- Berry add `tasmota.urlbecload(url:string) -> bool` [#20412](https://github.com/arendst/Tasmota/issues/20412) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) - HASPmota type `chart` [#20372](https://github.com/arendst/Tasmota/issues/20372) - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino new file mode 100644 index 000000000..e2295044d --- /dev/null +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -0,0 +1,351 @@ +/* + xdrv_121_gpioviewer.ino - GPIOViewer for Tasmota + + SPDX-FileCopyrightText: 2024 Theo Arends + + SPDX-License-Identifier: GPL-3.0-only +*/ + +#ifdef USE_GPIO_VIEWER +/*********************************************************************************************\ + * GPIOViewer support + * + * Open webpage :8080 and watch realtime GPIO states +\*********************************************************************************************/ + +#define XDRV_121 121 + +#define GV_PORT 8080 +#define GV_SAMPLING_INTERVAL 100 // Relates to FUNC_EVERY_100_MSECOND + +const char *GVRelease = "1.0.5"; + +#define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" + +#ifdef ESP32 +const int GVMaxGPIOPins = 49; +// Global variables to capture PMW pins +const int GVMaxChannels = 64; +#endif // ESP32 +#ifdef ESP8266 +const int GVMaxGPIOPins = 18; +// Global variables to capture PMW pins +const int GVMaxChannels = MAX_PWMS; +#endif // ESP8266 + +const char HTTP_GV_PAGE[] PROGMEM = + "" + "" + "" + "Tasmota GPIO State" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "
" + "
" + // Image + "
" + "
" + "Board Image" + "
" + "
" + "
" + "
" + "" + ""; + +enum GVPinTypes { + digitalPin = 0, + PWMPin = 1, + analogPin = 2 +}; + +struct { + WiFiClient WebClient; + ESP8266WebServer *WebServer; + int freeHeap; + uint32_t lastPinStates[GVMaxGPIOPins]; + int ledcChannelPin[GVMaxChannels][2]; + int ledcChannelPinCount; + int ledcChannelResolution[GVMaxChannels][2]; + int ledcChannelResolutionCount; + bool first; + bool active; +} GV; + +String GVFormatBytes(size_t bytes) { + if (bytes < 1024) { + return String(bytes) + " B"; + } + else if (bytes < (1024 * 1024)) { + return String(bytes / 1024.0, 2) + " KB"; + } + else { + return String(bytes / 1024.0 / 1024.0, 2) + " MB"; + } +} + +void GVPrintPWNTraps(void) { +#ifdef ESP32 + for (uint32_t pin = 0; pin < GVMaxChannels; pin++) { + int32_t channel = analogGetChannel2(pin); + if (channel > -1) { + GV.ledcChannelPin[GV.ledcChannelPinCount][0] = pin; + GV.ledcChannelPin[GV.ledcChannelPinCount++][1] = channel; + uint8_t resolution = ledcReadResolution(channel); + GV.ledcChannelResolution[GV.ledcChannelResolutionCount][0] = channel; + GV.ledcChannelResolution[GV.ledcChannelResolutionCount++][1] = resolution; + } + } +#endif // ESP32 +#ifdef ESP8266 + uint32_t pwm_range = Settings->pwm_range + 1; + uint32_t resolution = 0; + while (pwm_range) { + resolution++; + pwm_range >>= 1; + } + for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only + if (PinUsed(GPIO_PWM1, i)) { + int32_t channel = i; + GV.ledcChannelPin[GV.ledcChannelPinCount][0] = Pin(GPIO_PWM1, i); + GV.ledcChannelPin[GV.ledcChannelPinCount++][1] = channel; + GV.ledcChannelResolution[GV.ledcChannelResolutionCount][0] = channel; + GV.ledcChannelResolution[GV.ledcChannelResolutionCount++][1] = resolution; + } + } +#endif // ESP8266 + + AddLog(LOG_LEVEL_DEBUG, "IOV: %d pins are PWM", GV.ledcChannelPinCount); + for (int i = 0; i < GV.ledcChannelPinCount; i++) { + AddLog(LOG_LEVEL_DEBUG, "IOV: pin %d is using channel %d", GV.ledcChannelPin[i][0], GV.ledcChannelPin[i][1]); + } + AddLog(LOG_LEVEL_DEBUG, "IOV: %d channels are used", GV.ledcChannelResolutionCount); + for (int i = 0; i < GV.ledcChannelResolutionCount; i++) { + AddLog(LOG_LEVEL_DEBUG, "IOV: channel %d resolution is %d bits", GV.ledcChannelResolution[i][0], GV.ledcChannelResolution[i][1]); + } +} + +int GVGetLedcChannelForPin(int pin) { + for (int i = 0; i < GV.ledcChannelPinCount; i++) { + if (GV.ledcChannelPin[i][0] == pin) { + return GV.ledcChannelPin[i][1]; + } + } + return -1; // Pin not found, return -1 to indicate no channel is associated +} + +int GVGetChannelResolution(int channel) { + for (int i = 0; i < GV.ledcChannelResolutionCount; i++) { + if (GV.ledcChannelResolution[i][0] == channel) { + return GV.ledcChannelResolution[i][1]; + } + } + return -1; // Pin not found, return -1 to indicate no channel is associated +} + +int GVMapLedcReadTo8Bit(int channel, uint32_t *originalValue) { + uint32_t maxDutyCycle = (1 << GVGetChannelResolution(channel)) - 1; + +#ifdef ESP32 + *originalValue = ledcRead(channel); +#endif // ESP32 +#ifdef ESP8266 + if (17 == channel) { + maxDutyCycle = (1 << 10) - 1; // 10 = ANALOG_RESOLUTION + *originalValue = AdcRead(channel, 2); + } else { + *originalValue = (channel < MAX_PWMS_LEGACY) ? Settings->pwm_value[channel] : Settings->pwm_value_ext[channel - MAX_PWMS_LEGACY]; + } +#endif + + return map(*originalValue, 0, maxDutyCycle, 0, 255); +} + +int GVReadGPIO(int gpioNum, uint32_t *originalValue, uint32_t *pintype) { + int channel = GVGetLedcChannelForPin(gpioNum); + int value; + if (channel != -1) { + // This is a PWM Pin + value = GVMapLedcReadTo8Bit(channel, originalValue); + *pintype = PWMPin; + return value; + } +#ifdef ESP32 + uint8_t analogChannel = analogGetChannel2(gpioNum); + if (analogChannel != 0 && analogChannel != 255) { +#endif // ESP32 +#ifdef ESP8266 + uint8_t analogChannel = gpioNum; + if (17 == analogChannel) { +#endif // ESP8266 + // This is an analog pin + // Serial.printf("A Pin %d value=%d,channel=%d\n", gpioNum, value,analogChannel); + + value = GVMapLedcReadTo8Bit(analogChannel, originalValue); + *pintype = analogPin; + return value; + } + else { + // This is a digital pin + *pintype = digitalPin; + value = digitalRead(gpioNum); + *originalValue = value; + if (value == 1) { + return 256; + } + return 0; + } +} + +void GVResetStatePins(void) { + uint32_t originalValue; + uint32_t pintype; + AddLog(LOG_LEVEL_INFO, "IOV: GPIOViewer Connected, sampling interval is " STR(GV_SAMPLING_INTERVAL) "ms"); + + for (int i = 0; i < GVMaxGPIOPins; i++) { + GV.lastPinStates[i] = GVReadGPIO(i, &originalValue, &pintype); + } +} + +//void GVEventsSend(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); +void GVEventsSend(const char *message, const char *event, uint32_t id) { + if (GV.WebClient.connected()) { + // generateEventMessage() in AsyncEventSource.cpp +// GV.WebClient.printf_P(PSTR("retry: 0\r\nid: %u\r\nevent: %s\r\ndata: %s\r\n\r\n"), id, event, message); + GV.WebClient.printf_P(PSTR("id: %u\r\nevent: %s\r\ndata: %s\r\n\r\n"), id, event, message); + } +} + +// Monitor GPIO Values +void GVMonitorTask(void) { + uint32_t originalValue; + uint32_t pintype; + + String jsonMessage = "{"; + bool hasChanges = false; + + for (int i = 0; i < GVMaxGPIOPins; i++) { + int currentState = GVReadGPIO(i, &originalValue, &pintype); + + if (originalValue != GV.lastPinStates[i]) { + if (hasChanges) { + jsonMessage += ", "; + } + jsonMessage += "\"" + String(i) + "\": {\"s\": " + currentState + ", \"v\": " + originalValue + ", \"t\": " + pintype + "}"; + GV.lastPinStates[i] = currentState; + hasChanges = true; + } + } + + jsonMessage += "}"; + + if (hasChanges) { +// events->send(jsonMessage.c_str(), "gpio-state", millis()); + GVEventsSend(jsonMessage.c_str(), "gpio-state", millis()); + } + + uint32_t heap = ESP_getFreeHeap(); + if (heap != GV.freeHeap) { + GV.freeHeap = heap; +// events->send(GVFormatBytes(GV.freeHeap).c_str(), "free_heap", millis()); + GVEventsSend(GVFormatBytes(GV.freeHeap).c_str(), "free_heap", millis()); + } +} + +void GVBegin(void) { + GVPrintPWNTraps(); + + GV.WebServer = new ESP8266WebServer(GV_PORT); + +// GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // the payload can go on forever + + // Set CORS headers for global responses + GV.WebServer->sendHeader("Access-Control-Allow-Origin", "*"); + GV.WebServer->sendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); + GV.WebServer->sendHeader("Access-Control-Allow-Headers", "Content-Type"); + + GV.WebServer->on("/events", GVHandleEvents); + GV.WebServer->on("/", GVHandleRoot); + GV.WebServer->on("/release", GVHandleRelease); + + GV.WebServer->begin(); +} + +void GVHandleEvents(void) { + if (!GV.first) { + GVResetStatePins(); + GV.first = true; + + GV.WebClient = GV.WebServer->client(); + GV.WebClient.setNoDelay(true); +// GV.WebClient.setSync(true); + + GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // The payload can go on forever + GV.WebServer->sendContent_P(PSTR("HTTP/1.1 200 OK\nContent-Type: text/event-stream;\nConnection: keep-alive\nCache-Control: no-cache\nAccess-Control-Allow-Origin: *\n\n")); + } +} + +void GVHandleRoot(void) { + char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, + WiFi.localIP().toString().c_str(), + WiFi.localIP().toString().c_str(), + GVFormatBytes(ESP.getFreeSketchSpace()).c_str()); + if (content == nullptr) { return; } // Avoid crash + + GV.WebServer->send_P(200, "text/html", content); + free(content); +} + +void GVHandleRelease(void) { + String jsonResponse = "{\"release\": \"" + String(GVRelease) + "\"}"; + + GV.WebServer->send(200, "application/json", jsonResponse); +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv121(uint32_t function) { + bool result = false; + + if (GV.active) { + switch (function) { + case FUNC_LOOP: + if (GV.WebServer) { GV.WebServer->handleClient(); } + break; + case FUNC_EVERY_100_MSECOND: + if (GV.first) { GVMonitorTask(); } + break; + case FUNC_ACTIVE: + result = true; + break; + } + } else { + switch (function) { + case FUNC_EVERY_SECOND: + if (!TasmotaGlobal.global_state.network_down) { + GVBegin(); + GV.active = true; + } + break; + } + + } + return result; +} + +#endif // USE_GPIO_VIEWER From 324689ee53b087502522af89463fe086f7bec275 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 6 Jan 2024 21:22:45 +0100 Subject: [PATCH 079/303] Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` (#20414) --- CHANGELOG.md | 1 + .../src/esp8266toEsp32.cpp | 11 +++++++++ .../src/esp8266toEsp32.h | 6 +++++ lib/libesp32/berry_tasmota/src/be_gpio_lib.c | 4 ++++ tasmota/berry/include/be_gpio_defines.h | 14 +++++++++-- .../xdrv_52_3_berry_gpio.ino | 24 +++++++++++++++++++ tools/lv_gpio/lv_gpio_enum.h | 8 +++++++ 7 files changed, 66 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abbff6c0a..d87631f60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file. - Berry add support for `tcpclientasync` in `tcpserver` (#20401) - Berry add `tasmota.urlbecload(url:string) -> bool` (#20412) - GPIO Viewer to see realtime GPIO states. Enable with define USE_GPIO_VIEWER +- Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` ### Breaking Changed diff --git a/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp index d31aaed2b..7e20d9bec 100644 --- a/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp +++ b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp @@ -342,6 +342,17 @@ uint8_t ledcReadResolution(uint8_t chan) { return res; } +// Version of ledcRead that works for both Core2 and Core3 +// Return -1 if pin is not configured as PWM +int32_t ledcRead2(uint8_t pin) { + int32_t chan = analogGetChannel2(pin); + if (chan >= 0) { + uint8_t group=(chan/8), channel=(chan%8); + return ledc_get_duty((ledc_mode_t)group, (ledc_channel_t)channel); + } + return -1; +} + // void analogWrite(uint8_t pin, int val); extern "C" void __wrap__Z11analogWritehi(uint8_t pin, int val) { analogWritePhase(pin, val, 0); // if unspecified, use phase = 0 diff --git a/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h index 8cae8d499..61496ccd2 100644 --- a/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h +++ b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h @@ -98,6 +98,12 @@ void analogWrite(uint8_t pin, int val); // Extended version that also allows to change phase extern void analogWritePhase(uint8_t pin, uint32_t duty, uint32_t phase = 0); +// +// ledcRead2 - read the value of PWM +// +// return -1 if pin is not assigned to ledc +int32_t ledcRead2(uint8_t pin); + // return the channel assigned to a GPIO, or -1 if none extern int32_t analogGetChannel2(uint32_t pin); diff --git a/lib/libesp32/berry_tasmota/src/be_gpio_lib.c b/lib/libesp32/berry_tasmota/src/be_gpio_lib.c index e83347539..0b10ca866 100644 --- a/lib/libesp32/berry_tasmota/src/be_gpio_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_gpio_lib.c @@ -25,6 +25,8 @@ extern int gp_pin(bvm *vm); // esp_err_tledc_set_duty_and_update(ledc_mode_tspeed_mode, ledc_channel_tchannel, uint32_t duty, uint32_t hpoint) extern void gp_set_duty(int32_t pin, int32_t duty, int32_t hpoint); BE_FUNC_CTYPE_DECLARE(gp_set_duty, "", "ii[i]"); +extern int gp_get_duty(int32_t pin); BE_FUNC_CTYPE_DECLARE(gp_get_duty, "i", "i"); +extern int gp_get_duty_resolution(int32_t pin); BE_FUNC_CTYPE_DECLARE(gp_get_duty_resolution, "i", "i"); /* @const_object_info_begin module gpio (scope: global) { @@ -42,6 +44,8 @@ module gpio (scope: global) { pin, func(gp_pin) set_pwm, ctype_func(gp_set_duty) + read_pwm, ctype_func(gp_get_duty) + read_pwm_resolution, ctype_func(gp_get_duty_resolution) } @const_object_info_end */ #include "be_fixed_gpio.h" diff --git a/tasmota/berry/include/be_gpio_defines.h b/tasmota/berry/include/be_gpio_defines.h index 9c5a131cc..4f6ccde55 100644 --- a/tasmota/berry/include/be_gpio_defines.h +++ b/tasmota/berry/include/be_gpio_defines.h @@ -30,6 +30,9 @@ const be_const_member_t lv_gpio_constants[] = { { "AZ_RXD", (int32_t) GPIO_AZ_RXD }, { "AZ_TXD", (int32_t) GPIO_AZ_TXD }, { "BACKLIGHT", (int32_t) GPIO_BACKLIGHT }, + { "BIOPDU_BIT", (int32_t) GPIO_BIOPDU_BIT }, + { "BIOPDU_PZEM016_RX", (int32_t) GPIO_BIOPDU_PZEM016_RX }, + { "BIOPDU_PZEM0XX_TX", (int32_t) GPIO_BIOPDU_PZEM0XX_TX }, { "BL0939_RX", (int32_t) GPIO_BL0939_RX }, { "BL0940_RX", (int32_t) GPIO_BL0940_RX }, { "BL0942_RX", (int32_t) GPIO_BL0942_RX }, @@ -65,6 +68,7 @@ const be_const_member_t lv_gpio_constants[] = { { "DHT11_OUT", (int32_t) GPIO_DHT11_OUT }, { "DHT22", (int32_t) GPIO_DHT22 }, { "DI", (int32_t) GPIO_DI }, + { "DINGTIAN_OE", (int32_t) GPIO_DINGTIAN_OE }, { "DSB", (int32_t) GPIO_DSB }, { "DSB_OUT", (int32_t) GPIO_DSB_OUT }, { "DYP_RX", (int32_t) GPIO_DYP_RX }, @@ -79,10 +83,13 @@ const be_const_member_t lv_gpio_constants[] = { { "FALLING", FALLING }, { "FLOWRATEMETER_SIGNAL", (int32_t) GPIO_FLOWRATEMETER_IN }, { "FTC532", (int32_t) GPIO_FTC532 }, + { "GM861_TX", (int32_t) GPIO_GM861_RX }, { "GPIO_INPUT", (int32_t) GPIO_INPUT }, { "GPS_RX", (int32_t) GPIO_GPS_RX }, { "GPS_TX", (int32_t) GPIO_GPS_TX }, { "HALLEFFECT", (int32_t) GPIO_HALLEFFECT }, + { "HC8_RXD", (int32_t) GPIO_HC8_RXD }, + { "HDMI_CEC", (int32_t) GPIO_HDMI_CEC }, { "HEARTBEAT", (int32_t) GPIO_HEARTBEAT }, { "HEARTBEAT_INV", (int32_t) GPIO_HEARTBEAT_INV }, { "HIGH", HIGH }, @@ -137,12 +144,15 @@ const be_const_member_t lv_gpio_constants[] = { { "LEDLNK_INV", (int32_t) GPIO_LEDLNK_INV }, { "LMT01", (int32_t) GPIO_LMT01 }, { "LOW", LOW }, + { "LOX_O2_RX", (int32_t) GPIO_LOX_O2_RX }, + { "MAGIC_SWITCH", (int32_t) GPIO_MAGIC_SWITCH }, { "MAX31855CLK", (int32_t) GPIO_MAX31855CLK }, { "MAX31855CS", (int32_t) GPIO_MAX31855CS }, { "MAX31855DO", (int32_t) GPIO_MAX31855DO }, { "MAX7219CLK", (int32_t) GPIO_MAX7219CLK }, { "MAX7219CS", (int32_t) GPIO_MAX7219CS }, { "MAX7219DIN", (int32_t) GPIO_MAX7219DIN }, + { "MAX_GPIO", (int32_t) MAX_GPIO_PIN }, { "MAX_RMT", MAX_RMT }, { "MBR_RX", (int32_t) GPIO_MBR_RX }, { "MBR_TX", (int32_t) GPIO_MBR_TX }, @@ -293,10 +303,10 @@ const be_const_member_t lv_gpio_constants[] = { { "TM1638CLK", (int32_t) GPIO_TM1638CLK }, { "TM1638DIO", (int32_t) GPIO_TM1638DIO }, { "TM1638STB", (int32_t) GPIO_TM1638STB }, - { "TUYA_RX", (int32_t) GPIO_TUYA_RX }, - { "TUYA_TX", (int32_t) GPIO_TUYA_TX }, { "TUYAMCUBR_RX", (int32_t) GPIO_TUYAMCUBR_RX }, { "TUYAMCUBR_TX", (int32_t) GPIO_TUYAMCUBR_TX }, + { "TUYA_RX", (int32_t) GPIO_TUYA_RX }, + { "TUYA_TX", (int32_t) GPIO_TUYA_TX }, { "TX2X_TXD_BLACK", (int32_t) GPIO_TX2X_TXD_BLACK }, { "TXD", (int32_t) GPIO_TXD }, { "VINDRIKTNING_RX", (int32_t) GPIO_VINDRIKTNING_RX }, diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_gpio.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_gpio.ino index 7335665b2..e76f70432 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_gpio.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_gpio.ino @@ -302,6 +302,30 @@ extern "C" { int gp_counter_add(bvm *vm) { return gp_counter_set_add(vm, true); } + + // gpio.get_duty(pin:int) -> int + // + // Read the value of a PWM within resolution + // Returns -1 if pin is not a PWM pin + int gp_get_duty(int32_t pin); + int gp_get_duty(int32_t pin) { + return ledcRead2(pin); + } + + // gpio.get_duty_resolution(pin:int) -> int + // + // Read the resolution of a PWM + // Returns -1 if pin is not a PWM pin + int gp_get_duty_resolution(int32_t pin); + int gp_get_duty_resolution(int32_t pin) { + int32_t channel = analogGetChannel2(pin); + if (channel >= 0) { + return (1 << ledcReadResolution(channel)); + } + return -1; + } +// extern void gp_get_duty(int32_t pin); BE_FUNC_CTYPE_DECLARE(gp_get_duty, "i", "i"); +// extern void gp_get_duty_resolution(int32_t pin); BE_FUNC_CTYPE_DECLARE(gp_get_duty_resolution, "i", "i"); } #endif // USE_BERRY diff --git a/tools/lv_gpio/lv_gpio_enum.h b/tools/lv_gpio/lv_gpio_enum.h index 0484e4490..7aa4f3f94 100644 --- a/tools/lv_gpio/lv_gpio_enum.h +++ b/tools/lv_gpio/lv_gpio_enum.h @@ -19,6 +19,8 @@ CHANGE MAX_RMT +MAX_GPIO = MAX_GPIO_PIN + NONE = GPIO_NONE KEY1 = GPIO_KEY1 KEY1_NP = GPIO_KEY1_NP @@ -333,5 +335,11 @@ BIOPDU_PZEM0XX_TX = GPIO_BIOPDU_PZEM0XX_TX BIOPDU_PZEM016_RX = GPIO_BIOPDU_PZEM016_RX BIOPDU_BIT = GPIO_BIOPDU_BIT LOX_O2_RX = GPIO_LOX_O2_RX +GM861_TX = GPIO_GM861_RX +DINGTIAN_OE = GPIO_DINGTIAN_OE +HDMI_CEC = GPIO_HDMI_CEC +HC8_RXD = GPIO_HC8_RXD +I2S_DAC = GPIO_I2S_DAC +MAGIC_SWITCH = GPIO_MAGIC_SWITCH SENSOR_END = GPIO_SENSOR_END From cee219a55f1b375b56b0c7fbce4cc5fbb711f505 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 6 Jan 2024 21:34:15 +0100 Subject: [PATCH 080/303] Minor fixes --- .../xdrv_121_gpioviewer.ino | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index e2295044d..f89d7e324 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -23,12 +23,10 @@ const char *GVRelease = "1.0.5"; #define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" #ifdef ESP32 -const int GVMaxGPIOPins = 49; // Global variables to capture PMW pins const int GVMaxChannels = 64; #endif // ESP32 #ifdef ESP8266 -const int GVMaxGPIOPins = 18; // Global variables to capture PMW pins const int GVMaxChannels = MAX_PWMS; #endif // ESP8266 @@ -49,7 +47,7 @@ const char HTTP_GV_PAGE[] PROGMEM = "var ip='%s';" // WiFi.localIP().toString().c_str() "var source=new EventSource('http://%s:" STR(GV_PORT) "/events');" // WiFi.localIP().toString().c_str() "var sampling_interval='" STR(GV_SAMPLING_INTERVAL) "';" - "var freeSketchSpace='%d';" // GV.freeRAM + "var freeSketchSpace='%s';" // GVFormatBytes(ESP_getFreeSketchSpace()).c_str() "" "" "" @@ -66,6 +64,13 @@ const char HTTP_GV_PAGE[] PROGMEM = "" ""; +const char HTTP_GV_EVENT[] PROGMEM = + "HTTP/1.1 200 OK\n" + "Content-Type: text/event-stream;\n" + "Connection: keep-alive\n" + "Cache-Control: no-cache\n" + "Access-Control-Allow-Origin: *\n\n"; + enum GVPinTypes { digitalPin = 0, PWMPin = 1, @@ -76,12 +81,12 @@ struct { WiFiClient WebClient; ESP8266WebServer *WebServer; int freeHeap; - uint32_t lastPinStates[GVMaxGPIOPins]; + uint32_t lastPinStates[MAX_GPIO_PIN]; int ledcChannelPin[GVMaxChannels][2]; int ledcChannelPinCount; int ledcChannelResolution[GVMaxChannels][2]; int ledcChannelResolutionCount; - bool first; + bool sse_ready; bool active; } GV; @@ -215,7 +220,7 @@ void GVResetStatePins(void) { uint32_t pintype; AddLog(LOG_LEVEL_INFO, "IOV: GPIOViewer Connected, sampling interval is " STR(GV_SAMPLING_INTERVAL) "ms"); - for (int i = 0; i < GVMaxGPIOPins; i++) { + for (int i = 0; i < MAX_GPIO_PIN; i++) { GV.lastPinStates[i] = GVReadGPIO(i, &originalValue, &pintype); } } @@ -237,7 +242,7 @@ void GVMonitorTask(void) { String jsonMessage = "{"; bool hasChanges = false; - for (int i = 0; i < GVMaxGPIOPins; i++) { + for (int i = 0; i < MAX_GPIO_PIN; i++) { int currentState = GVReadGPIO(i, &originalValue, &pintype); if (originalValue != GV.lastPinStates[i]) { @@ -269,44 +274,43 @@ void GVBegin(void) { GVPrintPWNTraps(); GV.WebServer = new ESP8266WebServer(GV_PORT); - -// GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // the payload can go on forever - // Set CORS headers for global responses GV.WebServer->sendHeader("Access-Control-Allow-Origin", "*"); GV.WebServer->sendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); GV.WebServer->sendHeader("Access-Control-Allow-Headers", "Content-Type"); - GV.WebServer->on("/events", GVHandleEvents); GV.WebServer->on("/", GVHandleRoot); GV.WebServer->on("/release", GVHandleRelease); - GV.WebServer->begin(); } void GVHandleEvents(void) { - if (!GV.first) { +// if (!GV.sse_ready) { + GVResetStatePins(); - GV.first = true; GV.WebClient = GV.WebServer->client(); GV.WebClient.setNoDelay(true); // GV.WebClient.setSync(true); GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // The payload can go on forever - GV.WebServer->sendContent_P(PSTR("HTTP/1.1 200 OK\nContent-Type: text/event-stream;\nConnection: keep-alive\nCache-Control: no-cache\nAccess-Control-Allow-Origin: *\n\n")); - } + GV.WebServer->sendContent_P(HTTP_GV_EVENT); + + GV.sse_ready = true; // Ready to +// } } void GVHandleRoot(void) { char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, WiFi.localIP().toString().c_str(), WiFi.localIP().toString().c_str(), - GVFormatBytes(ESP.getFreeSketchSpace()).c_str()); + GVFormatBytes(ESP_getFreeSketchSpace()).c_str()); if (content == nullptr) { return; } // Avoid crash GV.WebServer->send_P(200, "text/html", content); free(content); + + GV.sse_ready = false; // Allow restart on page load } void GVHandleRelease(void) { @@ -328,7 +332,7 @@ bool Xdrv121(uint32_t function) { if (GV.WebServer) { GV.WebServer->handleClient(); } break; case FUNC_EVERY_100_MSECOND: - if (GV.first) { GVMonitorTask(); } + if (GV.sse_ready) { GVMonitorTask(); } break; case FUNC_ACTIVE: result = true; From 11da340c62e6808b1d134d293db320d3eb185266 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 6 Jan 2024 21:35:08 +0100 Subject: [PATCH 081/303] Revert "Minor fixes" This reverts commit cee219a55f1b375b56b0c7fbce4cc5fbb711f505. --- .../xdrv_121_gpioviewer.ino | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index f89d7e324..e2295044d 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -23,10 +23,12 @@ const char *GVRelease = "1.0.5"; #define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" #ifdef ESP32 +const int GVMaxGPIOPins = 49; // Global variables to capture PMW pins const int GVMaxChannels = 64; #endif // ESP32 #ifdef ESP8266 +const int GVMaxGPIOPins = 18; // Global variables to capture PMW pins const int GVMaxChannels = MAX_PWMS; #endif // ESP8266 @@ -47,7 +49,7 @@ const char HTTP_GV_PAGE[] PROGMEM = "var ip='%s';" // WiFi.localIP().toString().c_str() "var source=new EventSource('http://%s:" STR(GV_PORT) "/events');" // WiFi.localIP().toString().c_str() "var sampling_interval='" STR(GV_SAMPLING_INTERVAL) "';" - "var freeSketchSpace='%s';" // GVFormatBytes(ESP_getFreeSketchSpace()).c_str() + "var freeSketchSpace='%d';" // GV.freeRAM "" "" "" @@ -64,13 +66,6 @@ const char HTTP_GV_PAGE[] PROGMEM = "" ""; -const char HTTP_GV_EVENT[] PROGMEM = - "HTTP/1.1 200 OK\n" - "Content-Type: text/event-stream;\n" - "Connection: keep-alive\n" - "Cache-Control: no-cache\n" - "Access-Control-Allow-Origin: *\n\n"; - enum GVPinTypes { digitalPin = 0, PWMPin = 1, @@ -81,12 +76,12 @@ struct { WiFiClient WebClient; ESP8266WebServer *WebServer; int freeHeap; - uint32_t lastPinStates[MAX_GPIO_PIN]; + uint32_t lastPinStates[GVMaxGPIOPins]; int ledcChannelPin[GVMaxChannels][2]; int ledcChannelPinCount; int ledcChannelResolution[GVMaxChannels][2]; int ledcChannelResolutionCount; - bool sse_ready; + bool first; bool active; } GV; @@ -220,7 +215,7 @@ void GVResetStatePins(void) { uint32_t pintype; AddLog(LOG_LEVEL_INFO, "IOV: GPIOViewer Connected, sampling interval is " STR(GV_SAMPLING_INTERVAL) "ms"); - for (int i = 0; i < MAX_GPIO_PIN; i++) { + for (int i = 0; i < GVMaxGPIOPins; i++) { GV.lastPinStates[i] = GVReadGPIO(i, &originalValue, &pintype); } } @@ -242,7 +237,7 @@ void GVMonitorTask(void) { String jsonMessage = "{"; bool hasChanges = false; - for (int i = 0; i < MAX_GPIO_PIN; i++) { + for (int i = 0; i < GVMaxGPIOPins; i++) { int currentState = GVReadGPIO(i, &originalValue, &pintype); if (originalValue != GV.lastPinStates[i]) { @@ -274,43 +269,44 @@ void GVBegin(void) { GVPrintPWNTraps(); GV.WebServer = new ESP8266WebServer(GV_PORT); + +// GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // the payload can go on forever + // Set CORS headers for global responses GV.WebServer->sendHeader("Access-Control-Allow-Origin", "*"); GV.WebServer->sendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); GV.WebServer->sendHeader("Access-Control-Allow-Headers", "Content-Type"); + GV.WebServer->on("/events", GVHandleEvents); GV.WebServer->on("/", GVHandleRoot); GV.WebServer->on("/release", GVHandleRelease); + GV.WebServer->begin(); } void GVHandleEvents(void) { -// if (!GV.sse_ready) { - + if (!GV.first) { GVResetStatePins(); + GV.first = true; GV.WebClient = GV.WebServer->client(); GV.WebClient.setNoDelay(true); // GV.WebClient.setSync(true); GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // The payload can go on forever - GV.WebServer->sendContent_P(HTTP_GV_EVENT); - - GV.sse_ready = true; // Ready to -// } + GV.WebServer->sendContent_P(PSTR("HTTP/1.1 200 OK\nContent-Type: text/event-stream;\nConnection: keep-alive\nCache-Control: no-cache\nAccess-Control-Allow-Origin: *\n\n")); + } } void GVHandleRoot(void) { char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, WiFi.localIP().toString().c_str(), WiFi.localIP().toString().c_str(), - GVFormatBytes(ESP_getFreeSketchSpace()).c_str()); + GVFormatBytes(ESP.getFreeSketchSpace()).c_str()); if (content == nullptr) { return; } // Avoid crash GV.WebServer->send_P(200, "text/html", content); free(content); - - GV.sse_ready = false; // Allow restart on page load } void GVHandleRelease(void) { @@ -332,7 +328,7 @@ bool Xdrv121(uint32_t function) { if (GV.WebServer) { GV.WebServer->handleClient(); } break; case FUNC_EVERY_100_MSECOND: - if (GV.sse_ready) { GVMonitorTask(); } + if (GV.first) { GVMonitorTask(); } break; case FUNC_ACTIVE: result = true; From aea3789f4095b88656075f12082c9b6661d1d048 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 6 Jan 2024 21:46:37 +0100 Subject: [PATCH 082/303] Minor fixes --- CHANGELOG.md | 2 +- RELEASENOTES.md | 1 + .../xdrv_121_gpioviewer.ino | 59 ++++++++++--------- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d87631f60..dd2e9d1d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ All notable changes to this project will be documented in this file. - Berry add support for `tcpclientasync` in `tcpserver` (#20401) - Berry add `tasmota.urlbecload(url:string) -> bool` (#20412) - GPIO Viewer to see realtime GPIO states. Enable with define USE_GPIO_VIEWER -- Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` +- Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` (#20414) ### Breaking Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index de5928873..e13594cf8 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -129,6 +129,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Berry `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) - Berry add support for `tcpclientasync` in `tcpserver` [#20401](https://github.com/arendst/Tasmota/issues/20401) - Berry add `tasmota.urlbecload(url:string) -> bool` [#20412](https://github.com/arendst/Tasmota/issues/20412) +- Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` [#20414](https://github.com/arendst/Tasmota/issues/20414) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) - HASPmota type `chart` [#20372](https://github.com/arendst/Tasmota/issues/20372) - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index e2295044d..b996808f5 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -23,12 +23,10 @@ const char *GVRelease = "1.0.5"; #define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" #ifdef ESP32 -const int GVMaxGPIOPins = 49; // Global variables to capture PMW pins const int GVMaxChannels = 64; #endif // ESP32 #ifdef ESP8266 -const int GVMaxGPIOPins = 18; // Global variables to capture PMW pins const int GVMaxChannels = MAX_PWMS; #endif // ESP8266 @@ -49,7 +47,7 @@ const char HTTP_GV_PAGE[] PROGMEM = "var ip='%s';" // WiFi.localIP().toString().c_str() "var source=new EventSource('http://%s:" STR(GV_PORT) "/events');" // WiFi.localIP().toString().c_str() "var sampling_interval='" STR(GV_SAMPLING_INTERVAL) "';" - "var freeSketchSpace='%d';" // GV.freeRAM + "var freeSketchSpace='%s';" // GVFormatBytes(ESP_getFreeSketchSpace()).c_str() "" "" "" @@ -66,6 +64,13 @@ const char HTTP_GV_PAGE[] PROGMEM = "" ""; +const char HTTP_GV_EVENT[] PROGMEM = + "HTTP/1.1 200 OK\n" + "Content-Type: text/event-stream;\n" + "Connection: keep-alive\n" + "Cache-Control: no-cache\n" + "Access-Control-Allow-Origin: *\n\n"; + enum GVPinTypes { digitalPin = 0, PWMPin = 1, @@ -76,12 +81,12 @@ struct { WiFiClient WebClient; ESP8266WebServer *WebServer; int freeHeap; - uint32_t lastPinStates[GVMaxGPIOPins]; + uint32_t lastPinStates[MAX_GPIO_PIN]; int ledcChannelPin[GVMaxChannels][2]; int ledcChannelPinCount; int ledcChannelResolution[GVMaxChannels][2]; int ledcChannelResolutionCount; - bool first; + bool sse_ready; bool active; } GV; @@ -160,7 +165,7 @@ int GVMapLedcReadTo8Bit(int channel, uint32_t *originalValue) { uint32_t maxDutyCycle = (1 << GVGetChannelResolution(channel)) - 1; #ifdef ESP32 - *originalValue = ledcRead(channel); + *originalValue = ledcRead2(channel); #endif // ESP32 #ifdef ESP8266 if (17 == channel) { @@ -215,13 +220,13 @@ void GVResetStatePins(void) { uint32_t pintype; AddLog(LOG_LEVEL_INFO, "IOV: GPIOViewer Connected, sampling interval is " STR(GV_SAMPLING_INTERVAL) "ms"); - for (int i = 0; i < GVMaxGPIOPins; i++) { + for (int i = 0; i < MAX_GPIO_PIN; i++) { GV.lastPinStates[i] = GVReadGPIO(i, &originalValue, &pintype); } } -//void GVEventsSend(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); -void GVEventsSend(const char *message, const char *event, uint32_t id) { +//void GVEventSend(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); +void GVEventSend(const char *message, const char *event, uint32_t id) { if (GV.WebClient.connected()) { // generateEventMessage() in AsyncEventSource.cpp // GV.WebClient.printf_P(PSTR("retry: 0\r\nid: %u\r\nevent: %s\r\ndata: %s\r\n\r\n"), id, event, message); @@ -237,7 +242,7 @@ void GVMonitorTask(void) { String jsonMessage = "{"; bool hasChanges = false; - for (int i = 0; i < GVMaxGPIOPins; i++) { + for (int i = 0; i < MAX_GPIO_PIN; i++) { int currentState = GVReadGPIO(i, &originalValue, &pintype); if (originalValue != GV.lastPinStates[i]) { @@ -254,14 +259,14 @@ void GVMonitorTask(void) { if (hasChanges) { // events->send(jsonMessage.c_str(), "gpio-state", millis()); - GVEventsSend(jsonMessage.c_str(), "gpio-state", millis()); + GVEventSend(jsonMessage.c_str(), "gpio-state", millis()); } uint32_t heap = ESP_getFreeHeap(); if (heap != GV.freeHeap) { GV.freeHeap = heap; // events->send(GVFormatBytes(GV.freeHeap).c_str(), "free_heap", millis()); - GVEventsSend(GVFormatBytes(GV.freeHeap).c_str(), "free_heap", millis()); + GVEventSend(GVFormatBytes(GV.freeHeap).c_str(), "free_heap", millis()); } } @@ -269,44 +274,40 @@ void GVBegin(void) { GVPrintPWNTraps(); GV.WebServer = new ESP8266WebServer(GV_PORT); - -// GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // the payload can go on forever - // Set CORS headers for global responses GV.WebServer->sendHeader("Access-Control-Allow-Origin", "*"); GV.WebServer->sendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); GV.WebServer->sendHeader("Access-Control-Allow-Headers", "Content-Type"); - GV.WebServer->on("/events", GVHandleEvents); GV.WebServer->on("/", GVHandleRoot); GV.WebServer->on("/release", GVHandleRelease); - GV.WebServer->begin(); } void GVHandleEvents(void) { - if (!GV.first) { - GVResetStatePins(); - GV.first = true; + GVResetStatePins(); - GV.WebClient = GV.WebServer->client(); - GV.WebClient.setNoDelay(true); -// GV.WebClient.setSync(true); + GV.WebClient = GV.WebServer->client(); + GV.WebClient.setNoDelay(true); +// GV.WebClient.setSync(true); - GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // The payload can go on forever - GV.WebServer->sendContent_P(PSTR("HTTP/1.1 200 OK\nContent-Type: text/event-stream;\nConnection: keep-alive\nCache-Control: no-cache\nAccess-Control-Allow-Origin: *\n\n")); - } + GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // The payload can go on forever + GV.WebServer->sendContent_P(HTTP_GV_EVENT); + + GV.sse_ready = true; // Ready for async updates } void GVHandleRoot(void) { char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, WiFi.localIP().toString().c_str(), WiFi.localIP().toString().c_str(), - GVFormatBytes(ESP.getFreeSketchSpace()).c_str()); - if (content == nullptr) { return; } // Avoid crash + GVFormatBytes(ESP_getFreeSketchSpace()).c_str()); + if (content == nullptr) { return; } // Avoid crash GV.WebServer->send_P(200, "text/html", content); free(content); + + GV.sse_ready = false; // Allow restart of updates on page load } void GVHandleRelease(void) { @@ -328,7 +329,7 @@ bool Xdrv121(uint32_t function) { if (GV.WebServer) { GV.WebServer->handleClient(); } break; case FUNC_EVERY_100_MSECOND: - if (GV.first) { GVMonitorTask(); } + if (GV.sse_ready) { GVMonitorTask(); } break; case FUNC_ACTIVE: result = true; From 8e06dcdcc316f58bd3c5e3b18a6139e18129dd8b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 6 Jan 2024 21:49:55 +0100 Subject: [PATCH 083/303] Revert "Minor fixes" This reverts commit aea3789f4095b88656075f12082c9b6661d1d048. --- CHANGELOG.md | 2 +- RELEASENOTES.md | 1 - .../xdrv_121_gpioviewer.ino | 59 +++++++++---------- 3 files changed, 30 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd2e9d1d1..d87631f60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ All notable changes to this project will be documented in this file. - Berry add support for `tcpclientasync` in `tcpserver` (#20401) - Berry add `tasmota.urlbecload(url:string) -> bool` (#20412) - GPIO Viewer to see realtime GPIO states. Enable with define USE_GPIO_VIEWER -- Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` (#20414) +- Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` ### Breaking Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e13594cf8..de5928873 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -129,7 +129,6 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Berry `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) - Berry add support for `tcpclientasync` in `tcpserver` [#20401](https://github.com/arendst/Tasmota/issues/20401) - Berry add `tasmota.urlbecload(url:string) -> bool` [#20412](https://github.com/arendst/Tasmota/issues/20412) -- Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` [#20414](https://github.com/arendst/Tasmota/issues/20414) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) - HASPmota type `chart` [#20372](https://github.com/arendst/Tasmota/issues/20372) - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index b996808f5..e2295044d 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -23,10 +23,12 @@ const char *GVRelease = "1.0.5"; #define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" #ifdef ESP32 +const int GVMaxGPIOPins = 49; // Global variables to capture PMW pins const int GVMaxChannels = 64; #endif // ESP32 #ifdef ESP8266 +const int GVMaxGPIOPins = 18; // Global variables to capture PMW pins const int GVMaxChannels = MAX_PWMS; #endif // ESP8266 @@ -47,7 +49,7 @@ const char HTTP_GV_PAGE[] PROGMEM = "var ip='%s';" // WiFi.localIP().toString().c_str() "var source=new EventSource('http://%s:" STR(GV_PORT) "/events');" // WiFi.localIP().toString().c_str() "var sampling_interval='" STR(GV_SAMPLING_INTERVAL) "';" - "var freeSketchSpace='%s';" // GVFormatBytes(ESP_getFreeSketchSpace()).c_str() + "var freeSketchSpace='%d';" // GV.freeRAM "" "" "" @@ -64,13 +66,6 @@ const char HTTP_GV_PAGE[] PROGMEM = "" ""; -const char HTTP_GV_EVENT[] PROGMEM = - "HTTP/1.1 200 OK\n" - "Content-Type: text/event-stream;\n" - "Connection: keep-alive\n" - "Cache-Control: no-cache\n" - "Access-Control-Allow-Origin: *\n\n"; - enum GVPinTypes { digitalPin = 0, PWMPin = 1, @@ -81,12 +76,12 @@ struct { WiFiClient WebClient; ESP8266WebServer *WebServer; int freeHeap; - uint32_t lastPinStates[MAX_GPIO_PIN]; + uint32_t lastPinStates[GVMaxGPIOPins]; int ledcChannelPin[GVMaxChannels][2]; int ledcChannelPinCount; int ledcChannelResolution[GVMaxChannels][2]; int ledcChannelResolutionCount; - bool sse_ready; + bool first; bool active; } GV; @@ -165,7 +160,7 @@ int GVMapLedcReadTo8Bit(int channel, uint32_t *originalValue) { uint32_t maxDutyCycle = (1 << GVGetChannelResolution(channel)) - 1; #ifdef ESP32 - *originalValue = ledcRead2(channel); + *originalValue = ledcRead(channel); #endif // ESP32 #ifdef ESP8266 if (17 == channel) { @@ -220,13 +215,13 @@ void GVResetStatePins(void) { uint32_t pintype; AddLog(LOG_LEVEL_INFO, "IOV: GPIOViewer Connected, sampling interval is " STR(GV_SAMPLING_INTERVAL) "ms"); - for (int i = 0; i < MAX_GPIO_PIN; i++) { + for (int i = 0; i < GVMaxGPIOPins; i++) { GV.lastPinStates[i] = GVReadGPIO(i, &originalValue, &pintype); } } -//void GVEventSend(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); -void GVEventSend(const char *message, const char *event, uint32_t id) { +//void GVEventsSend(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); +void GVEventsSend(const char *message, const char *event, uint32_t id) { if (GV.WebClient.connected()) { // generateEventMessage() in AsyncEventSource.cpp // GV.WebClient.printf_P(PSTR("retry: 0\r\nid: %u\r\nevent: %s\r\ndata: %s\r\n\r\n"), id, event, message); @@ -242,7 +237,7 @@ void GVMonitorTask(void) { String jsonMessage = "{"; bool hasChanges = false; - for (int i = 0; i < MAX_GPIO_PIN; i++) { + for (int i = 0; i < GVMaxGPIOPins; i++) { int currentState = GVReadGPIO(i, &originalValue, &pintype); if (originalValue != GV.lastPinStates[i]) { @@ -259,14 +254,14 @@ void GVMonitorTask(void) { if (hasChanges) { // events->send(jsonMessage.c_str(), "gpio-state", millis()); - GVEventSend(jsonMessage.c_str(), "gpio-state", millis()); + GVEventsSend(jsonMessage.c_str(), "gpio-state", millis()); } uint32_t heap = ESP_getFreeHeap(); if (heap != GV.freeHeap) { GV.freeHeap = heap; // events->send(GVFormatBytes(GV.freeHeap).c_str(), "free_heap", millis()); - GVEventSend(GVFormatBytes(GV.freeHeap).c_str(), "free_heap", millis()); + GVEventsSend(GVFormatBytes(GV.freeHeap).c_str(), "free_heap", millis()); } } @@ -274,40 +269,44 @@ void GVBegin(void) { GVPrintPWNTraps(); GV.WebServer = new ESP8266WebServer(GV_PORT); + +// GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // the payload can go on forever + // Set CORS headers for global responses GV.WebServer->sendHeader("Access-Control-Allow-Origin", "*"); GV.WebServer->sendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); GV.WebServer->sendHeader("Access-Control-Allow-Headers", "Content-Type"); + GV.WebServer->on("/events", GVHandleEvents); GV.WebServer->on("/", GVHandleRoot); GV.WebServer->on("/release", GVHandleRelease); + GV.WebServer->begin(); } void GVHandleEvents(void) { - GVResetStatePins(); + if (!GV.first) { + GVResetStatePins(); + GV.first = true; - GV.WebClient = GV.WebServer->client(); - GV.WebClient.setNoDelay(true); -// GV.WebClient.setSync(true); + GV.WebClient = GV.WebServer->client(); + GV.WebClient.setNoDelay(true); +// GV.WebClient.setSync(true); - GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // The payload can go on forever - GV.WebServer->sendContent_P(HTTP_GV_EVENT); - - GV.sse_ready = true; // Ready for async updates + GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // The payload can go on forever + GV.WebServer->sendContent_P(PSTR("HTTP/1.1 200 OK\nContent-Type: text/event-stream;\nConnection: keep-alive\nCache-Control: no-cache\nAccess-Control-Allow-Origin: *\n\n")); + } } void GVHandleRoot(void) { char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, WiFi.localIP().toString().c_str(), WiFi.localIP().toString().c_str(), - GVFormatBytes(ESP_getFreeSketchSpace()).c_str()); - if (content == nullptr) { return; } // Avoid crash + GVFormatBytes(ESP.getFreeSketchSpace()).c_str()); + if (content == nullptr) { return; } // Avoid crash GV.WebServer->send_P(200, "text/html", content); free(content); - - GV.sse_ready = false; // Allow restart of updates on page load } void GVHandleRelease(void) { @@ -329,7 +328,7 @@ bool Xdrv121(uint32_t function) { if (GV.WebServer) { GV.WebServer->handleClient(); } break; case FUNC_EVERY_100_MSECOND: - if (GV.sse_ready) { GVMonitorTask(); } + if (GV.first) { GVMonitorTask(); } break; case FUNC_ACTIVE: result = true; From ec754629054f49f82ea66f54478b911104b7f3ab Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 6 Jan 2024 21:57:09 +0100 Subject: [PATCH 084/303] Minor fixes --- CHANGELOG.md | 2 +- RELEASENOTES.md | 1 + .../xdrv_121_gpioviewer.ino | 57 ++++++++++--------- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d87631f60..dd2e9d1d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ All notable changes to this project will be documented in this file. - Berry add support for `tcpclientasync` in `tcpserver` (#20401) - Berry add `tasmota.urlbecload(url:string) -> bool` (#20412) - GPIO Viewer to see realtime GPIO states. Enable with define USE_GPIO_VIEWER -- Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` +- Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` (#20414) ### Breaking Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index de5928873..e13594cf8 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -129,6 +129,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Berry `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) - Berry add support for `tcpclientasync` in `tcpserver` [#20401](https://github.com/arendst/Tasmota/issues/20401) - Berry add `tasmota.urlbecload(url:string) -> bool` [#20412](https://github.com/arendst/Tasmota/issues/20412) +- Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` [#20414](https://github.com/arendst/Tasmota/issues/20414) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) - HASPmota type `chart` [#20372](https://github.com/arendst/Tasmota/issues/20372) - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index e2295044d..18736b74f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -23,12 +23,10 @@ const char *GVRelease = "1.0.5"; #define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" #ifdef ESP32 -const int GVMaxGPIOPins = 49; // Global variables to capture PMW pins const int GVMaxChannels = 64; #endif // ESP32 #ifdef ESP8266 -const int GVMaxGPIOPins = 18; // Global variables to capture PMW pins const int GVMaxChannels = MAX_PWMS; #endif // ESP8266 @@ -49,7 +47,7 @@ const char HTTP_GV_PAGE[] PROGMEM = "var ip='%s';" // WiFi.localIP().toString().c_str() "var source=new EventSource('http://%s:" STR(GV_PORT) "/events');" // WiFi.localIP().toString().c_str() "var sampling_interval='" STR(GV_SAMPLING_INTERVAL) "';" - "var freeSketchSpace='%d';" // GV.freeRAM + "var freeSketchSpace='%s';" // GVFormatBytes(ESP_getFreeSketchSpace()).c_str() "" "" "" @@ -66,6 +64,13 @@ const char HTTP_GV_PAGE[] PROGMEM = "" ""; +const char HTTP_GV_EVENT[] PROGMEM = + "HTTP/1.1 200 OK\n" + "Content-Type: text/event-stream;\n" + "Connection: keep-alive\n" + "Cache-Control: no-cache\n" + "Access-Control-Allow-Origin: *\n\n"; + enum GVPinTypes { digitalPin = 0, PWMPin = 1, @@ -76,12 +81,12 @@ struct { WiFiClient WebClient; ESP8266WebServer *WebServer; int freeHeap; - uint32_t lastPinStates[GVMaxGPIOPins]; + uint32_t lastPinStates[MAX_GPIO_PIN]; int ledcChannelPin[GVMaxChannels][2]; int ledcChannelPinCount; int ledcChannelResolution[GVMaxChannels][2]; int ledcChannelResolutionCount; - bool first; + bool sse_ready; bool active; } GV; @@ -215,13 +220,13 @@ void GVResetStatePins(void) { uint32_t pintype; AddLog(LOG_LEVEL_INFO, "IOV: GPIOViewer Connected, sampling interval is " STR(GV_SAMPLING_INTERVAL) "ms"); - for (int i = 0; i < GVMaxGPIOPins; i++) { + for (int i = 0; i < MAX_GPIO_PIN; i++) { GV.lastPinStates[i] = GVReadGPIO(i, &originalValue, &pintype); } } -//void GVEventsSend(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); -void GVEventsSend(const char *message, const char *event, uint32_t id) { +//void GVEventSend(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); +void GVEventSend(const char *message, const char *event, uint32_t id) { if (GV.WebClient.connected()) { // generateEventMessage() in AsyncEventSource.cpp // GV.WebClient.printf_P(PSTR("retry: 0\r\nid: %u\r\nevent: %s\r\ndata: %s\r\n\r\n"), id, event, message); @@ -237,7 +242,7 @@ void GVMonitorTask(void) { String jsonMessage = "{"; bool hasChanges = false; - for (int i = 0; i < GVMaxGPIOPins; i++) { + for (int i = 0; i < MAX_GPIO_PIN; i++) { int currentState = GVReadGPIO(i, &originalValue, &pintype); if (originalValue != GV.lastPinStates[i]) { @@ -254,14 +259,14 @@ void GVMonitorTask(void) { if (hasChanges) { // events->send(jsonMessage.c_str(), "gpio-state", millis()); - GVEventsSend(jsonMessage.c_str(), "gpio-state", millis()); + GVEventSend(jsonMessage.c_str(), "gpio-state", millis()); } uint32_t heap = ESP_getFreeHeap(); if (heap != GV.freeHeap) { GV.freeHeap = heap; // events->send(GVFormatBytes(GV.freeHeap).c_str(), "free_heap", millis()); - GVEventsSend(GVFormatBytes(GV.freeHeap).c_str(), "free_heap", millis()); + GVEventSend(GVFormatBytes(GV.freeHeap).c_str(), "free_heap", millis()); } } @@ -269,44 +274,40 @@ void GVBegin(void) { GVPrintPWNTraps(); GV.WebServer = new ESP8266WebServer(GV_PORT); - -// GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // the payload can go on forever - // Set CORS headers for global responses GV.WebServer->sendHeader("Access-Control-Allow-Origin", "*"); GV.WebServer->sendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); GV.WebServer->sendHeader("Access-Control-Allow-Headers", "Content-Type"); - GV.WebServer->on("/events", GVHandleEvents); GV.WebServer->on("/", GVHandleRoot); GV.WebServer->on("/release", GVHandleRelease); - GV.WebServer->begin(); } void GVHandleEvents(void) { - if (!GV.first) { - GVResetStatePins(); - GV.first = true; + GVResetStatePins(); - GV.WebClient = GV.WebServer->client(); - GV.WebClient.setNoDelay(true); -// GV.WebClient.setSync(true); + GV.WebClient = GV.WebServer->client(); + GV.WebClient.setNoDelay(true); +// GV.WebClient.setSync(true); - GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // The payload can go on forever - GV.WebServer->sendContent_P(PSTR("HTTP/1.1 200 OK\nContent-Type: text/event-stream;\nConnection: keep-alive\nCache-Control: no-cache\nAccess-Control-Allow-Origin: *\n\n")); - } + GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // The payload can go on forever + GV.WebServer->sendContent_P(HTTP_GV_EVENT); + + GV.sse_ready = true; // Ready for async updates } void GVHandleRoot(void) { char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, WiFi.localIP().toString().c_str(), WiFi.localIP().toString().c_str(), - GVFormatBytes(ESP.getFreeSketchSpace()).c_str()); - if (content == nullptr) { return; } // Avoid crash + GVFormatBytes(ESP_getFreeSketchSpace()).c_str()); + if (content == nullptr) { return; } // Avoid crash GV.WebServer->send_P(200, "text/html", content); free(content); + + GV.sse_ready = false; // Allow restart of updates on page load } void GVHandleRelease(void) { @@ -328,7 +329,7 @@ bool Xdrv121(uint32_t function) { if (GV.WebServer) { GV.WebServer->handleClient(); } break; case FUNC_EVERY_100_MSECOND: - if (GV.first) { GVMonitorTask(); } + if (GV.sse_ready) { GVMonitorTask(); } break; case FUNC_ACTIVE: result = true; From bd9a99caffe3c7faec6518655710e7ce118df62e Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 6 Jan 2024 22:20:22 +0100 Subject: [PATCH 085/303] Berry `gpio.get_pin_type` and `gpio.ger_pin_type_index` (#20415) --- CHANGELOG.md | 2 ++ lib/libesp32/berry_tasmota/src/be_gpio_lib.c | 5 +++++ .../xdrv_52_3_berry_gpio.ino | 21 +++++++++++++++++-- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd2e9d1d1..654c974aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ All notable changes to this project will be documented in this file. - Berry add support for `tcpclientasync` in `tcpserver` (#20401) - Berry add `tasmota.urlbecload(url:string) -> bool` (#20412) - GPIO Viewer to see realtime GPIO states. Enable with define USE_GPIO_VIEWER +- Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` +- Berry `gpio.get_pin_type` and `gpio.ger_pin_type_index` - Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` (#20414) ### Breaking Changed diff --git a/lib/libesp32/berry_tasmota/src/be_gpio_lib.c b/lib/libesp32/berry_tasmota/src/be_gpio_lib.c index 0b10ca866..1742e2baf 100644 --- a/lib/libesp32/berry_tasmota/src/be_gpio_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_gpio_lib.c @@ -22,6 +22,9 @@ extern int gp_counter_add(bvm *vm); extern int gp_pin_used(bvm *vm); extern int gp_pin(bvm *vm); +extern int gp_get_pin(int32_t pin); BE_FUNC_CTYPE_DECLARE(gp_get_pin, "i", "i"); +extern int gp_get_pin_index(int32_t pin); BE_FUNC_CTYPE_DECLARE(gp_get_pin_index, "i", "i"); + // esp_err_tledc_set_duty_and_update(ledc_mode_tspeed_mode, ledc_channel_tchannel, uint32_t duty, uint32_t hpoint) extern void gp_set_duty(int32_t pin, int32_t duty, int32_t hpoint); BE_FUNC_CTYPE_DECLARE(gp_set_duty, "", "ii[i]"); @@ -33,6 +36,8 @@ module gpio (scope: global) { member, func(gp_member) pin_mode, func(gp_pin_mode) + get_pin_type, ctype_func(gp_get_pin) + get_pin_type_index, ctype_func(gp_get_pin_index) digital_write, func(gp_digital_write) digital_read, func(gp_digital_read) dac_voltage, func(gp_dac_voltage) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_gpio.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_gpio.ino index e76f70432..c36dc3c00 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_gpio.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_gpio.ino @@ -324,8 +324,25 @@ extern "C" { } return -1; } -// extern void gp_get_duty(int32_t pin); BE_FUNC_CTYPE_DECLARE(gp_get_duty, "i", "i"); -// extern void gp_get_duty_resolution(int32_t pin); BE_FUNC_CTYPE_DECLARE(gp_get_duty_resolution, "i", "i"); + + // gpio.get_pin_type(phy_gpio:int) -> int + // + // Get the type configured for physical GPIO + // Return 0 if GPIO is not configured + extern int gp_get_pin(int32_t pin); + extern int gp_get_pin(int32_t pin) { + return GetPin(pin) / 32; + } + + // gpio.get_pin_type_index(phy_gpio:int) -> int + // + // Get the sub-index for the type configured for physical GPIO + // Return 0 if GPIO is not configured + extern int gp_get_pin_index(int32_t pin); + extern int gp_get_pin_index(int32_t pin) { + return GetPin(pin) % 32; + } + } #endif // USE_BERRY From 08a769a720b9b886fe2117ce2d68f28a63977fd7 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 6 Jan 2024 22:36:42 +0100 Subject: [PATCH 086/303] GPIO viewer in Berry initial version using async webserver (#20416) --- CHANGELOG.md | 1 + tasmota/berry/gpio_viewer/gpioviewer.bec | Bin 0 -> 10821 bytes tasmota/berry/gpio_viewer/webserver_async.be | 477 ++++++++++++++++++ .../berry/gpio_viewer/webserver_gpioviewer.be | 212 ++++++++ 4 files changed, 690 insertions(+) create mode 100644 tasmota/berry/gpio_viewer/gpioviewer.bec create mode 100644 tasmota/berry/gpio_viewer/webserver_async.be create mode 100644 tasmota/berry/gpio_viewer/webserver_gpioviewer.be diff --git a/CHANGELOG.md b/CHANGELOG.md index 654c974aa..66b447fad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file. - Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` - Berry `gpio.get_pin_type` and `gpio.ger_pin_type_index` - Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` (#20414) +- GPIO viewer in Berry initial version using async webserver ### Breaking Changed diff --git a/tasmota/berry/gpio_viewer/gpioviewer.bec b/tasmota/berry/gpio_viewer/gpioviewer.bec new file mode 100644 index 0000000000000000000000000000000000000000..776f65e90016b9d2dae89dd725b125a9c3a5c29f GIT binary patch literal 10821 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 literal 0 HcmV?d00001 diff --git a/tasmota/berry/gpio_viewer/webserver_async.be b/tasmota/berry/gpio_viewer/webserver_async.be new file mode 100644 index 000000000..61d997274 --- /dev/null +++ b/tasmota/berry/gpio_viewer/webserver_async.be @@ -0,0 +1,477 @@ +# +# webserber_async.be - implements a generic async non-blocking HTTP server +# +# Copyright (C) 2023 Stephan Hadinger & Theo Arends +# +# 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 . +# + +# restrictions for now: +# +# Listen to all interfaces +# - GET only +# - no HTTPS +# - support for limited headers +# - HTTP 1.0 only + +#@ solidify:Webserver_async +#@ solidify:Webserver_async_cnx + +class Webserver_async_cnx + var server # link to server object + var cnx # holds the tcpclientasync instance + var fastloop_cb # cb for fastloop + var buf_in # incoming buffer + var buf_in_offset + var buf_out + var phase # parsing phase: 0/ status line, 1/ headers, 2/ payload + # request + var req_verb + var req_uri + var req_version + var header_host + # response + var resp_headers + var resp_version + var mode_chunked + # conversion + static var CODE_TO_STRING = { + 100: "Continue", + 200: "OK", + 204: "No Content", + 301: "Moved Permanently", + 400: "Bad Request", + 401: "Unauthorized", + 403: "Payment Required", + 404: "Not Found", + 500: "Internal Server Error", + 501: "Not Implemented" + } + + ############################################################# + # init + def init(server, cnx) + self.server = server + self.cnx = cnx + self.buf_in = '' + self.buf_in_offset = 0 + self.buf_out = bytes() + self.phase = 0 + # response + self.resp_headers = '' + self.resp_version = 1 # HTTP 1.1 # TODO + self.mode_chunked = true + # register cb + self.fastloop_cb = def () self.loop() end + tasmota.add_fast_loop(self.fastloop_cb) + end + + def set_mode_chunked(mode_chunked) + self.mode_chunked = bool(mode_chunked) + end + + ############################################################# + # test if connected + def connected() + return self.cnx ? self.cnx.connected() : false + end + ############################################################# + # closing web server + def close() + tasmota.log(f"WEB: closing cnx", 3) + if (self.cnx != nil) self.cnx.close() end + self.cnx = nil + end + + ############################################################# + # called by fastloop + def loop() + if self.cnx == nil # marked for deletion + # mark as closed with self.cnx == nil + tasmota.remove_fast_loop(self.fastloop_cb) + self.fastloop_cb = nil + return + end + + # any incoming data? + var cnx = self.cnx + + if cnx.available() > 0 + var buf_in_new = cnx.read() + if (!self.buf_in) + self.buf_in = buf_in_new + else + self.buf_in += buf_in_new + end + end + + # parse incoming if any + if (self.buf_in) + self.parse() + end + end + + ############################################################# + # parse incoming + # + # pre: self.buf_in is not empty + # post: self.buf_in has made progress (smaller or '') + def parse() + tasmota.log(f"WEB: incoming {bytes().fromstring(self.buf_in).tohex()}", 3) + if self.phase == 0 + self.parse_http_req_line() + elif self.phase == 1 + self.parse_http_headers() + elif self.phase == 2 + self.parse_http_payload() + end + end + + ############################################################# + # parse incoming request + # + # pre: self.buf_in is not empty + # post: self.buf_in has made progress (smaller or '') + def parse_http_req_line() + var m = global._re_http_srv.match2(self.buf_in, self.buf_in_offset) + # Ex: "GET / HTTP/1.1\r\n" + if m + var offset = m[0] + self.req_verb = m[1] # GET/POST... + self.req_uri = m[2] # / + self.req_version = m[3] # "1.0" or "1.1" + self.phase = 1 # proceed to parsing headers + self.buf_in = self.buf_in[offset .. ] # remove what we parsed + tasmota.log(f"WEB: HTTP verb: {self.req_verb} URI: '{self.req_uri}' Version:{self.req_version}", 3) + self.parse_http_headers() + elif size(self.buf_in) > 100 # if no match and we still have 100 bytes, then it fails + tasmota.log("WEB: error invalid request", 3) + self.close() + self.buf_in = '' + end + end + + ############################################################# + # parse incoming headers + def parse_http_headers() + while true + # print("parse_http_headers", "self.buf_in_offset=", self.buf_in_offset) + var m = global._re_http_srv_header.match2(self.buf_in, self.buf_in_offset) + # print("m=", m) + # Ex: [32, 'Content-Type', 'application/json'] + if m + self.event_http_header(m[1], m[2]) + self.buf_in_offset += m[0] + else # no more headers + var m2 = global._re_http_srv_body.match2(self.buf_in, self.buf_in_offset) + if m2 + # end of headers + # we keep \r\n which is used by pattern + self.buf_in = self.buf_in[self.buf_in_offset + m2[0] .. ] # truncate + self.buf_in_offset = 0 + + self.event_http_headers_end() # no more headers + self.phase = 2 + self.parse_http_payload() # continue to parsing payload + end + if size(self.buf_in) > 1024 # we don't accept a single header larger than 1KB + tasmota.log("WEB: error header is bigger than 1KB", 3) + self.close() + self.buf_in = '' + end + return + end + end + + + self.close() + self.buf_in = '' + end + + ############################################################# + # event_http_header + # + # Received header + def event_http_header(header_key, header_value) + tasmota.log(f"WEB: header key '{header_key}' = '{header_value}'") + + if (header_key == "Host") + self.header_host = header_value + end + # import string + # header_key = string.tolower(header_key) + # header_value = string.tolower(header_value) + # print("header=", header_key, header_value) + # if header_key == 'transfer-encoding' && string.tolower(header_value) == 'chunked' + # self.is_chunked = true + # end + end + + ############################################################# + # event_http_headers_end + # + # All headers are received + def event_http_headers_end() + # print("event_http_headers_end") + # truncate to save space + # if self.buf_in_offset > 0 + # self.buf_in = self.buf_in[self.buf_in_offset .. ] + # self.buf_in_offset = 0 + # end + end + + ############################################################# + # parse incoming payload (if any) + def parse_http_payload() + tasmota.log(f"WEB: parsing payload '{bytes().fromstring(self.buf_in).tohex()}'") + # dispatch request before parsing payload + self.server.dispatch(self, self.req_uri, self.req_verb) + end + + + ############################################################# + # Responses + ############################################################# + ############################################################# + # parse incoming payload (if any) + def send_header(name, value, first) + if first + self.resp_headers = f"{name}: {value}\r\n{self.resp_headers}" + else + self.resp_headers = f"{self.resp_headers}{name}: {value}\r\n" + end + end + + def send(code, content_type, content) + var response = f"HTTP/1.{self.resp_version} {code} {self.code_to_string(code)}\r\n" + if (content_type == nil) content_type = "text/html" end + self.send_header("Content-Type", content_type, true) + + # force chunked TODO + self.send_header("Accept-Ranges", "none") + if self.mode_chunked + self.send_header("Transfer-Encoding", "chunked") + end + # cors + self.send_header("Access-Control-Allow-Origin", "*") + self.send_header("Access-Control-Allow-Methods", "*") + self.send_header("Access-Control-Allow-Headers", "*") + # others + self.send_header("Connection", "close") + + response += self.resp_headers + response += "\r\n" + self.resp_headers = nil + + # send + self._write(response) + + if (content) self.write(content) end + end + + static def code_to_string(code) + return _class.CODE_TO_STRING.find(code, "UNKNOWN") + end + + ############################################################# + # async write + def write(s) + # use chunk encoding + if self.mode_chunked + var chunk = f"{size(s):X}\r\n{s}\r\n" + tasmota.log(f"WEB: sending chunk '{bytes().fromstring(chunk).tohex()}'") + self._write(chunk) + else + self._write(s) + end + end + + ############################################################# + # async write + def _write(s) + self.cnx.write(s) # TODO move to async later + end + + def content_stop() + self.write('') + self.close() + end +end + +class Webserver_dispatcher + var uri_prefix # prefix string, must start with '/' + var verb # verb to match, or nil for ANY + var cb_obj + var cb_mth + + def init(uri, cb_obj, cb_mth, verb) + self.uri_prefix = uri + self.cb_obj = cb_obj + self.cb_mth = cb_mth + self.verb = verb + end + + # return true if matched + def dispatch(cnx, uri, verb) + import string + if string.find(uri, self.uri_prefix) == 0 + var match = false + if (self.verb == nil) || (self.verb == verb) + # method is valid + self.cb_mth(self.cb_obj, cnx, uri, verb) + return true + end + end + return false + end +end + +class Webserver_async + var local_port # listening port, 80 is already used by Tasmota + var server # instance of `tcpserver` + var fastloop_cb # closure used by fastloop + var timeout # default timeout for tcp connection + var connections # list of active connections + # var timeout # timeout in ms + # var auth # web authentication string (Basic Auth) or `nil`, in format `user:password` as bade64 + # var cmd # GET url command + var dispatchers + + static var TIMEOUT = 1000 # default timeout: 1000ms + static var HTTP_REQ = "^(\\w+) (\\S+) HTTP\\/(\\d\\.\\d)\r\n" + static var HTTP_HEADER_REGEX = "([A-Za-z0-9-]+): (.*?)\r\n" # extract a header with its 2 parts + static var HTTP_BODY_REGEX = "\r\n" # end of headers + + ############################################################# + # init + def init(port, timeout) + if (timeout == nil) timeout = self.TIMEOUT end + self.connections = [] + self.dispatchers = [] + self.server = tcpserver(port) # throws an exception if port is not available + # TODO what about max_clients ? + self.compile_re() + # register cb + tasmota.add_driver(self) + self.fastloop_cb = def () self.loop() end + tasmota.add_fast_loop(self.fastloop_cb) + end + + ############################################################# + # compile once for all the regex + def compile_re() + import re + if !global.contains("_re_http_srv") + global._re_http_srv = re.compile(self.HTTP_REQ) + global._re_http_srv_header = re.compile(self.HTTP_HEADER_REGEX) + global._re_http_srv_body = re.compile(self.HTTP_BODY_REGEX) + end + end + + ############################################################# + # closing web server + def close() + tasmota.remove_driver(self) + tasmota.remove_fast_loop(self.fastloop_cb) + self.fastloop_cb = nil + self.server.close() + + # close all active connections + for cnx: self.connections + cnx.close() + end + self.connections = nil # and free memory + end + + ############################################################# + # clean connections + # + # Remove any connections that is closed or in error + def clean_connections() + var idx = 0 + while idx < size(self.connections) + var cnx = self.connections[idx] + # remove if not connected + if !cnx.connected() + # tasmota.log("WEB: does not appear to be connected") + cnx.close() + self.connections.remove(idx) + else + idx += 1 + end + end + end + + ############################################################# + # called by fastloop + def loop() + self.clean_connections() + # check if any incoming connection + while self.server.hasclient() + # retrieve new client + var cnx = Webserver_async_cnx(self, self.server.accept()) # TODO move to self.server.acceptasync + self.connections.push(cnx) + tasmota.log(f"WEB: received connection from XXX") + end + end + + ############################################################# + # add to dispatcher + def on(prefix, obj, mth, verb) + var dispatcher = Webserver_dispatcher(prefix, obj, mth, verb) + self.dispatchers.push(dispatcher) + end + + ############################################################# + # add to dispatcher + def dispatch(cnx, uri, verb) + var idx = 0 + while idx < size(self.dispatchers) + if (self.dispatchers[idx].dispatch(cnx, uri, verb)) + return + end + idx += 1 + end + # fallback unsupported request + cnx.send(500, "text/plain") + cnx.write("Unsupported") + cnx.content_stop() + end + +end + +#- Test + +var web = Webserver_async(888) + +def send_more(cnx, i) + cnx.write(f"

Hello world {i}

") + if i < 10 + tasmota.set_timer(1000, def () send_more(cnx, i+1) end) + else + cnx.content_stop() + end +end + +def f(obj, cnx, uri, verb) + cnx.send(200, "text/html") + cnx.write("") + send_more(cnx, 0) + # cnx.write("Hello world") + # cnx.content_stop() +end + +web.on("/hello", nil, f) + +-# diff --git a/tasmota/berry/gpio_viewer/webserver_gpioviewer.be b/tasmota/berry/gpio_viewer/webserver_gpioviewer.be new file mode 100644 index 000000000..a14562925 --- /dev/null +++ b/tasmota/berry/gpio_viewer/webserver_gpioviewer.be @@ -0,0 +1,212 @@ +# +# webserber_gpioviewer.be - implements a generic async non-blocking HTTP server +# +# Copyright (C) 2023 Stephan Hadinger & Theo Arends +# +# 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 . +# + +var gpio_viewer = module('gpio_viewer') + +gpio_viewer.Webserver_async_cnx = Webserver_async_cnx +gpio_viewer.Webserver_dispatcher = Webserver_dispatcher +gpio_viewer.Webserver_async = Webserver_async + +class GPIO_viewer + var web + var sampling_interval + var free_space + var pin_actual # actual value + var last_pin_states # state converted to 0..255 + var new_pin_states # get a snapshot of newest values + var pin_types # array of types + + static var TYPE_DIGITAL = 0 + static var TYPE_PWM = 1 + static var TYPE_ANALOG = 2 + + static var SAMPLING = 100 + static var GPIO_RELEASE = "1.0.7" + static var HTML_HEAD = + "ESP32 GPIO State" + "" + "" + "" + "" + + "" + "" + "" + static var HTML_BODY = + "
\n" + "
" + "
" + # Image + "
\n" + "
" + "Board Image\n" + "
" + "
" + static var HTML_SCRIPT = + # Append the script variables + "" + "" + "" + "" + "" + "" + + def init(port) + self.web = Webserver_async(5555) + self.sampling_interval = self.SAMPLING + self.free_space = 500 + + # pins + import gpio + self.pin_actual = [] + self.pin_actual.resize(gpio.MAX_GPIO) # full of nil + self.last_pin_states = [] + self.last_pin_states.resize(gpio.MAX_GPIO) # full of nil + self.new_pin_states = [] + self.new_pin_states.resize(gpio.MAX_GPIO) # full of nil + self.pin_types = [] + self.pin_types.resize(gpio.MAX_GPIO) # full of nil + + self.web.on("/release", self, self.send_release_page) + self.web.on("/events", self, self.send_events_page) + self.web.on("/", self, self.send_index_page) + end + + def close() + self.web.close() + end + + def send_index_page(cnx, uri, verb) + import string + + cnx.send(200, "text/html") + cnx.write(self.HTML_HEAD) + cnx.write(self.HTML_BODY) + + var host = cnx.header_host + var host_split = string.split(host, ':') # need to make it stronger + var ip = host_split[0] + var port = 80 + if size(host_split) > 1 + port = int(host_split[1]) + end + + var html = format(self.HTML_SCRIPT, port, ip, port, ip, self.sampling_interval, self.free_space) + cnx.write(html) + cnx.content_stop() + end + + def send_release_page(cnx, uri, verb) + var release = f'{{"release":"{self.GPIO_RELEASE}"}}' + cnx.send(200, "application/json", release) + cnx.content_stop() + end + + def send_events_page(cnx, uri, verb) + cnx.set_mode_chunked(false) # no chunking since we use EventSource + cnx.send(200, "text/event-stream") + + self.send_events_tick(cnx) + end + + def send_events_tick(cnx) + import gpio + var max_gpio = gpio.MAX_GPIO + var msg = "{" + var dirty = false + var pin = 0 + self.read_states() + + while pin < max_gpio + var prev = self.last_pin_states[pin] + var val = self.new_pin_states[pin] + if (prev != val) || (val != nil) # TODO for now send everything every time + if dirty msg += "," end + msg += f'"{pin}":{{"s":{val},"v":{prev},"t":{self.pin_types[pin]}}}' + dirty = true + + self.last_pin_states[pin] = val + end + pin += 1 + end + msg += "}" + + if dirty + # prepare payload + var payload = f"id:{tasmota.millis()}\r\n" + "event:gpio-state\r\n" + "data:{msg}\r\n\r\n" + + # tasmota.log(f"GPV: sending '{msg}'", 3) + cnx.write(payload) + end + + # send free heap + var payload = f"id:{tasmota.millis()}\r\n" + "event:free_heap\r\n" + "data:{tasmota.memory().find('heap_free', 0)}\r\n\r\n" + cnx.write(payload) + + tasmota.set_timer(self.sampling_interval, def () self.send_events_tick(cnx) end) + end + + # read all GPIO values, store in `pin_actual` and `new_pin_states` + def read_states() + import gpio + var max_gpio = gpio.MAX_GPIO + var pin = 0 + while pin < max_gpio + # check if PWM + var pwm_resolution = gpio.read_pwm_resolution(pin) + if (pwm_resolution > 0) + var pwm_val = gpio.read_pwm(pin) + var pwm_state = tasmota.scale_uint(pwm_val, 0, pwm_resolution, 0, 255) # bring back to 0..255 + self.pin_actual[pin] = pwm_val + self.new_pin_states[pin] = pwm_state + self.pin_types[pin] = self.TYPE_PWM + elif gpio.get_pin_type(pin) > 0 + # digital read + var digital_val = gpio.digital_read(pin) # returns 0 or 1 + self.pin_actual[pin] = digital_val + self.new_pin_states[pin] = digital_val ? 256 : 0 + self.pin_types[pin] = self.TYPE_DIGITAL + else + self.pin_actual[pin] = nil + self.new_pin_states[pin] = nil + self.pin_types[pin] = self.TYPE_DIGITAL + end + pin += 1 + end + end + +end + +gpio_viewer.GPIO_viewer = GPIO_viewer + +if tasmota + var gpio_viewer = GPIO_viewer(5555) +end + +return gpio_viewer + +#- Test + +var gpio_viewer = GPIO_viewer(5555) + +-# From 2947fd8b061253263f9910f0646e06f43be6feba Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 6 Jan 2024 22:46:16 +0100 Subject: [PATCH 087/303] GPIO viewer fix size (#20417) --- ...{webserver_gpioviewer.be => gpioviewer.be} | 7 +++---- tasmota/berry/gpio_viewer/gpioviewer.bec | Bin 10821 -> 10867 bytes 2 files changed, 3 insertions(+), 4 deletions(-) rename tasmota/berry/gpio_viewer/{webserver_gpioviewer.be => gpioviewer.be} (98%) diff --git a/tasmota/berry/gpio_viewer/webserver_gpioviewer.be b/tasmota/berry/gpio_viewer/gpioviewer.be similarity index 98% rename from tasmota/berry/gpio_viewer/webserver_gpioviewer.be rename to tasmota/berry/gpio_viewer/gpioviewer.be index a14562925..ae379f52d 100644 --- a/tasmota/berry/gpio_viewer/webserver_gpioviewer.be +++ b/tasmota/berry/gpio_viewer/gpioviewer.be @@ -26,7 +26,6 @@ gpio_viewer.Webserver_async = Webserver_async class GPIO_viewer var web var sampling_interval - var free_space var pin_actual # actual value var last_pin_states # state converted to 0..255 var new_pin_states # get a snapshot of newest values @@ -70,7 +69,6 @@ class GPIO_viewer def init(port) self.web = Webserver_async(5555) self.sampling_interval = self.SAMPLING - self.free_space = 500 # pins import gpio @@ -107,7 +105,8 @@ class GPIO_viewer port = int(host_split[1]) end - var html = format(self.HTML_SCRIPT, port, ip, port, ip, self.sampling_interval, self.free_space) + var free_space = f"{tasmota.memory().find('program_free', 0)} KB" + var html = format(self.HTML_SCRIPT, port, ip, port, ip, self.sampling_interval, free_space) cnx.write(html) cnx.content_stop() end @@ -160,7 +159,7 @@ class GPIO_viewer # send free heap var payload = f"id:{tasmota.millis()}\r\n" "event:free_heap\r\n" - "data:{tasmota.memory().find('heap_free', 0)}\r\n\r\n" + "data:{tasmota.memory().find('heap_free', 0)} KB\r\n\r\n" cnx.write(payload) tasmota.set_timer(self.sampling_interval, def () self.send_events_tick(cnx) end) diff --git a/tasmota/berry/gpio_viewer/gpioviewer.bec b/tasmota/berry/gpio_viewer/gpioviewer.bec index 776f65e90016b9d2dae89dd725b125a9c3a5c29f..6c4bbed9480ae7b0d76ec2c97370c472691df6e8 100644 GIT binary patch delta 547 zcmZ8eF>ljg5PkmaByQp+jtL}EOL3`FWw5FY5vl|OZW9HIl!Vq235w)|)~zDdapYJa zBoB-pI#~L|%EZD}HA^=p27Un>J0oIYVBl+L5Mnsp>AiP%x_6(fAJ+Njm0L*wITjgM zy-ve6o*1om6ZE6HDJTRr`b`Z6sB}@mXCQi*WjTjhcM02FB=r!27M4&M$ebQQ zuJ)0w^&xMw{Ggxb9!5~=tgeJS&-x3D6ZBBIs@W{I`OOXbcKxWDKzXV@-jP!XhEvxI zhH?_F<9hyUS-|mVd?ZVl_}+;>bnRo`ap=$WjjV)2ZyY$|z@7%)guW}UWtQ;B+H2W6 z?Rt-%Zxo*1V=F+?mlrp)7Kj)UkeKJhhzKNxn0~K78URwrr%9aPq$rt^&Qgg&1VIY_ zax#g<1xGopn3${RZLQe*R}ZGiuzm@JE>P+(bE^?VDO}*$YdrTKE??vM1NFn@!U)TJ-CRF?)Wu%gyere&J^PnnbuwDyu5b+@n=B-WC7oJJ0s6-a2>V vV0Yi_SnNzRJ7(M7Z?qc5K?C6N%6XB;bm&e_N8=NF#LVr8q~ delta 498 zcmZ8e%SyvQ6g`tho2Fx$K72rHeMXA7DCnY~3nL9RklLUD9~7c!1vjl|mH}O6;UX}< z;0Fj@C+fLnbw;I*MNLx?@vcT4~S+=i*tee-ww18!nD0mf83ZSkup_H3Y*Z5v( zQnC?@k<9?gq92Qu?vUY}Sn`#xTqyax>1~R=70%ez^n6jq`BkgsUSFP^wp5DKPTOm> zJ@?w{Tyi0M*Rr(#z^Yj@9o>pPW{yZ!#6|nU`;LGh38=8{bbhW!WQSKFWcfY=dJIrM zMul*c&>$YCcM>ZXCvW=MNG^a#{a;m12<3rln41v7go z>IYYc@HBFn{(;PZ;BI8uQ*oXCcY=Ksqg4redfm3nof_~nk8MM*@=u{=n+ Date: Sun, 7 Jan 2024 15:10:19 +0100 Subject: [PATCH 088/303] Update GPIOViewer - Add ESP8266 PWM state logging - Add ADC state functions --- .../src/esp8266toEsp32.cpp | 8 + .../src/esp8266toEsp32.h | 6 + tasmota/tasmota_support/support_pwm.ino | 25 ++- tasmota/tasmota_xdrv_driver/xdrv_04_light.ino | 2 +- .../tasmota_xdrv_driver/xdrv_10_scripter.ino | 4 +- .../xdrv_121_gpioviewer.ino | 212 ++++++------------ .../xdrv_23_zigbee_A_impl.ino | 2 +- .../tasmota_xdrv_driver/xdrv_24_buzzer.ino | 2 +- .../tasmota_xdrv_driver/xdrv_27_shutter.ino | 10 +- .../xdrv_35_pwm_dimmer.ino | 2 +- .../tasmota_xlgt_light/xlgt_03_sm16716.ino | 2 +- .../tasmota_xsns_sensor/xsns_02_analog.ino | 13 ++ 12 files changed, 132 insertions(+), 156 deletions(-) diff --git a/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp index 7e20d9bec..dc2908eec 100644 --- a/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp +++ b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp @@ -342,6 +342,14 @@ uint8_t ledcReadResolution(uint8_t chan) { return res; } +int32_t ledcReadDutyResolution(uint8_t pin) { + int32_t chan = analogGetChannel2(pin); + if (chan >= 0) { + return (1 << ledcReadResolution(chan)); + } + return -1; +} + // Version of ledcRead that works for both Core2 and Core3 // Return -1 if pin is not configured as PWM int32_t ledcRead2(uint8_t pin) { diff --git a/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h index 61496ccd2..659e34b55 100644 --- a/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h +++ b/lib/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h @@ -98,6 +98,12 @@ void analogWrite(uint8_t pin, int val); // Extended version that also allows to change phase extern void analogWritePhase(uint8_t pin, uint32_t duty, uint32_t phase = 0); +// +// ledcReadDutyResolution - read the resolution +// +// return -1 if pin is not assigned to ledc +int32_t ledcReadDutyResolution(uint8_t pin); + // // ledcRead2 - read the value of PWM // diff --git a/tasmota/tasmota_support/support_pwm.ino b/tasmota/tasmota_support/support_pwm.ino index f729b628a..0e27a3491 100644 --- a/tasmota/tasmota_support/support_pwm.ino +++ b/tasmota/tasmota_support/support_pwm.ino @@ -17,6 +17,16 @@ along with this program. If not, see . */ +int16_t analog_write_state[MAX_GPIO_PIN] = { -1 }; + +void AnalogWrite(uint8_t pin, int val) { + analog_write_state[pin] = val; + analogWrite(pin, val); +} + +uint32_t AnalogRead(uint8_t pin) { + return analog_write_state[pin]; +} /***********************************************************************\ * PWM Control for ESP32 @@ -223,7 +233,7 @@ void CmndPwm(void) } else { Settings->pwm_value_ext[pwm_index - MAX_PWMS_LEGACY] = XdrvMailbox.payload; } - analogWrite(Pin(GPIO_PWM1, pwm_index), bitRead(TasmotaGlobal.pwm_inverted, pwm_index) ? Settings->pwm_range - XdrvMailbox.payload : XdrvMailbox.payload); + AnalogWrite(Pin(GPIO_PWM1, pwm_index), bitRead(TasmotaGlobal.pwm_inverted, pwm_index) ? Settings->pwm_range - XdrvMailbox.payload : XdrvMailbox.payload); } Response_P(PSTR("{")); MqttShowPWMState(); // Render the PWM status to MQTT @@ -232,18 +242,21 @@ void CmndPwm(void) } void GpioInitPwm(void) { + for (uint32_t pin = 0; pin < MAX_GPIO_PIN; pin++) { + analog_write_state[pin] = -1; // No PWM pin (could be GPIO_PWM or GPIO_LED) + } for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only if (PinUsed(GPIO_PWM1, i)) { pinMode(Pin(GPIO_PWM1, i), OUTPUT); if (i < TasmotaGlobal.light_type) { // force PWM GPIOs to low or high mode if belongs to the light (always <5), see #7165 - analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range : 0); + AnalogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range : 0); } else { TasmotaGlobal.pwm_present = true; if (i < MAX_PWMS_LEGACY) { - analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range - Settings->pwm_value[i] : Settings->pwm_value[i]); + AnalogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range - Settings->pwm_value[i] : Settings->pwm_value[i]); } else { - analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range - Settings->pwm_value_ext[i] : Settings->pwm_value_ext[i]); + AnalogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range - Settings->pwm_value_ext[i] : Settings->pwm_value_ext[i]); } } } @@ -256,8 +269,8 @@ void ResetPwm(void) { for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only if (PinUsed(GPIO_PWM1, i)) { - analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range : 0); -// analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range - Settings->pwm_value[i] : Settings->pwm_value[i]); + AnalogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range : 0); +// AnalogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range - Settings->pwm_value[i] : Settings->pwm_value[i]); } } } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino b/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino index 14799f208..cdeb0caac 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino @@ -2191,7 +2191,7 @@ void LightSetOutputs(const uint16_t *cur_col_10) { // AddLog(LOG_LEVEL_DEBUG_MORE, "analogWrite-%i 0x%03X", i, cur_col); #else // ESP32 if (!Settings->flag4.zerocross_dimmer) { - analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range - cur_col : cur_col); + AnalogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range - cur_col : cur_col); // AddLog(LOG_LEVEL_DEBUG_MORE, "analogWrite-%i 0x%03X", bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range - cur_col : cur_col); } #endif // ESP32 diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino index 0049e0a30..efaf21f5f 100755 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino @@ -6897,12 +6897,12 @@ void esp_pwm(int32_t value, uint32 freq, uint32_t channel) { pwmpin[channel] = -value; pinMode(pwmpin[channel], OUTPUT); analogWriteFreq(freq); - analogWrite(pwmpin[channel], 0); + AnalogWrite(pwmpin[channel], 0); } else { if (value > 1023) { value = 1023; } - analogWrite(pwmpin[channel],value); + AnalogWrite(pwmpin[channel],value); } #endif // ESP32 } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 18736b74f..0420b88ab 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -15,22 +15,13 @@ #define XDRV_121 121 -#define GV_PORT 8080 +#define GV_PORT 5557 #define GV_SAMPLING_INTERVAL 100 // Relates to FUNC_EVERY_100_MSECOND -const char *GVRelease = "1.0.5"; +const char *GVRelease = "1.0.7"; #define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" -#ifdef ESP32 -// Global variables to capture PMW pins -const int GVMaxChannels = 64; -#endif // ESP32 -#ifdef ESP8266 -// Global variables to capture PMW pins -const int GVMaxChannels = MAX_PWMS; -#endif // ESP8266 - const char HTTP_GV_PAGE[] PROGMEM = "" "" @@ -52,6 +43,7 @@ const char HTTP_GV_PAGE[] PROGMEM = "" "" "
" + "" "
" // Image "
" @@ -80,12 +72,10 @@ enum GVPinTypes { struct { WiFiClient WebClient; ESP8266WebServer *WebServer; - int freeHeap; uint32_t lastPinStates[MAX_GPIO_PIN]; - int ledcChannelPin[GVMaxChannels][2]; - int ledcChannelPinCount; - int ledcChannelResolution[GVMaxChannels][2]; - int ledcChannelResolutionCount; + uint32_t resolution; + uint32_t freeHeap; + uint32_t freePSRAM; bool sse_ready; bool active; } GV; @@ -102,117 +92,48 @@ String GVFormatBytes(size_t bytes) { } } -void GVPrintPWNTraps(void) { -#ifdef ESP32 - for (uint32_t pin = 0; pin < GVMaxChannels; pin++) { - int32_t channel = analogGetChannel2(pin); - if (channel > -1) { - GV.ledcChannelPin[GV.ledcChannelPinCount][0] = pin; - GV.ledcChannelPin[GV.ledcChannelPinCount++][1] = channel; - uint8_t resolution = ledcReadResolution(channel); - GV.ledcChannelResolution[GV.ledcChannelResolutionCount][0] = channel; - GV.ledcChannelResolution[GV.ledcChannelResolutionCount++][1] = resolution; - } - } -#endif // ESP32 -#ifdef ESP8266 - uint32_t pwm_range = Settings->pwm_range + 1; - uint32_t resolution = 0; - while (pwm_range) { - resolution++; - pwm_range >>= 1; - } - for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only - if (PinUsed(GPIO_PWM1, i)) { - int32_t channel = i; - GV.ledcChannelPin[GV.ledcChannelPinCount][0] = Pin(GPIO_PWM1, i); - GV.ledcChannelPin[GV.ledcChannelPinCount++][1] = channel; - GV.ledcChannelResolution[GV.ledcChannelResolutionCount][0] = channel; - GV.ledcChannelResolution[GV.ledcChannelResolutionCount++][1] = resolution; - } - } -#endif // ESP8266 - - AddLog(LOG_LEVEL_DEBUG, "IOV: %d pins are PWM", GV.ledcChannelPinCount); - for (int i = 0; i < GV.ledcChannelPinCount; i++) { - AddLog(LOG_LEVEL_DEBUG, "IOV: pin %d is using channel %d", GV.ledcChannelPin[i][0], GV.ledcChannelPin[i][1]); - } - AddLog(LOG_LEVEL_DEBUG, "IOV: %d channels are used", GV.ledcChannelResolutionCount); - for (int i = 0; i < GV.ledcChannelResolutionCount; i++) { - AddLog(LOG_LEVEL_DEBUG, "IOV: channel %d resolution is %d bits", GV.ledcChannelResolution[i][0], GV.ledcChannelResolution[i][1]); - } -} - -int GVGetLedcChannelForPin(int pin) { - for (int i = 0; i < GV.ledcChannelPinCount; i++) { - if (GV.ledcChannelPin[i][0] == pin) { - return GV.ledcChannelPin[i][1]; - } - } - return -1; // Pin not found, return -1 to indicate no channel is associated -} - -int GVGetChannelResolution(int channel) { - for (int i = 0; i < GV.ledcChannelResolutionCount; i++) { - if (GV.ledcChannelResolution[i][0] == channel) { - return GV.ledcChannelResolution[i][1]; - } - } - return -1; // Pin not found, return -1 to indicate no channel is associated -} - -int GVMapLedcReadTo8Bit(int channel, uint32_t *originalValue) { - uint32_t maxDutyCycle = (1 << GVGetChannelResolution(channel)) - 1; - -#ifdef ESP32 - *originalValue = ledcRead(channel); -#endif // ESP32 -#ifdef ESP8266 - if (17 == channel) { - maxDutyCycle = (1 << 10) - 1; // 10 = ANALOG_RESOLUTION - *originalValue = AdcRead(channel, 2); - } else { - *originalValue = (channel < MAX_PWMS_LEGACY) ? Settings->pwm_value[channel] : Settings->pwm_value_ext[channel - MAX_PWMS_LEGACY]; - } -#endif - - return map(*originalValue, 0, maxDutyCycle, 0, 255); -} - int GVReadGPIO(int gpioNum, uint32_t *originalValue, uint32_t *pintype) { - int channel = GVGetLedcChannelForPin(gpioNum); - int value; - if (channel != -1) { - // This is a PWM Pin - value = GVMapLedcReadTo8Bit(channel, originalValue); - *pintype = PWMPin; - return value; - } -#ifdef ESP32 - uint8_t analogChannel = analogGetChannel2(gpioNum); - if (analogChannel != 0 && analogChannel != 255) { -#endif // ESP32 -#ifdef ESP8266 - uint8_t analogChannel = gpioNum; - if (17 == analogChannel) { -#endif // ESP8266 - // This is an analog pin - // Serial.printf("A Pin %d value=%d,channel=%d\n", gpioNum, value,analogChannel); - - value = GVMapLedcReadTo8Bit(analogChannel, originalValue); - *pintype = analogPin; - return value; - } - else { - // This is a digital pin + uint32_t pin_type = GetPin(gpioNum) / 32; +/* + if (GPIO_NONE == pin_type) { *pintype = digitalPin; - value = digitalRead(gpioNum); - *originalValue = value; - if (value == 1) { - return 256; - } + *originalValue = 0; return 0; } +*/ +#ifdef ESP32 + int pwm_resolution = ledcReadDutyResolution(gpioNum); + if (pwm_resolution > 0) { + *pintype = PWMPin; + *originalValue = ledcRead2(gpioNum); + return changeUIntScale(*originalValue, 0, pwm_resolution, 0, 255); // bring back to 0..255 + } +#endif // ESP32 + +#ifdef ESP8266 + int pwm_value = AnalogRead(gpioNum); + if (pwm_value > -1) { + *pintype = PWMPin; + *originalValue = pwm_value; + int pwm_resolution = GV.resolution; + return changeUIntScale(*originalValue, 0, pwm_resolution, 0, 255); // bring back to 0..255 + } +#endif // ESP8266 + + else if (AdcPin(gpioNum)) { + int adc_resolution = (1 << AdcResolution()) - 1; + *originalValue = AdcRead(gpioNum, 2); + *pintype = analogPin; + return changeUIntScale(*originalValue, 0, adc_resolution, 0, 255); // bring back to 0..255 + } + + *pintype = digitalPin; + int value = digitalRead(gpioNum); + *originalValue = value; + if (value == 1) { + return 256; + } + return 0; } void GVResetStatePins(void) { @@ -220,8 +141,8 @@ void GVResetStatePins(void) { uint32_t pintype; AddLog(LOG_LEVEL_INFO, "IOV: GPIOViewer Connected, sampling interval is " STR(GV_SAMPLING_INTERVAL) "ms"); - for (int i = 0; i < MAX_GPIO_PIN; i++) { - GV.lastPinStates[i] = GVReadGPIO(i, &originalValue, &pintype); + for (uint32_t pin = 0; pin < MAX_GPIO_PIN; pin++) { + GV.lastPinStates[pin] = GVReadGPIO(pin, &originalValue, &pintype); } } @@ -236,43 +157,58 @@ void GVEventSend(const char *message, const char *event, uint32_t id) { // Monitor GPIO Values void GVMonitorTask(void) { +#ifdef ESP8266 + // Can change on the fly + uint32_t pwm_range = Settings->pwm_range + 1; + GV.resolution = 0; + while (pwm_range) { + GV.resolution++; + pwm_range >>= 1; + } +#endif // ESP8266 + uint32_t originalValue; uint32_t pintype; String jsonMessage = "{"; bool hasChanges = false; + for (uint32_t pin = 0; pin < MAX_GPIO_PIN; pin++) { + int currentState = GVReadGPIO(pin, &originalValue, &pintype); - for (int i = 0; i < MAX_GPIO_PIN; i++) { - int currentState = GVReadGPIO(i, &originalValue, &pintype); - - if (originalValue != GV.lastPinStates[i]) { - if (hasChanges) { + if (originalValue != GV.lastPinStates[pin]) { + if (hasChanges) { jsonMessage += ", "; - } - jsonMessage += "\"" + String(i) + "\": {\"s\": " + currentState + ", \"v\": " + originalValue + ", \"t\": " + pintype + "}"; - GV.lastPinStates[i] = currentState; - hasChanges = true; + } + jsonMessage += "\"" + String(pin) + "\": {\"s\": " + currentState + ", \"v\": " + originalValue + ", \"t\": " + pintype + "}"; + GV.lastPinStates[pin] = currentState; + hasChanges = true; } } jsonMessage += "}"; if (hasChanges) { -// events->send(jsonMessage.c_str(), "gpio-state", millis()); GVEventSend(jsonMessage.c_str(), "gpio-state", millis()); } uint32_t heap = ESP_getFreeHeap(); if (heap != GV.freeHeap) { GV.freeHeap = heap; -// events->send(GVFormatBytes(GV.freeHeap).c_str(), "free_heap", millis()); GVEventSend(GVFormatBytes(GV.freeHeap).c_str(), "free_heap", millis()); } + +#ifdef ESP32 + if (UsePSRAM()) { + uint32_t psram = ESP.getFreePsram(); + if (psram != GV.freePSRAM) { + GV.freePSRAM = psram; + GVEventSend(GVFormatBytes(GV.freePSRAM).c_str(), "free_psram", millis()); + } + } +#endif // ESP32 } void GVBegin(void) { - GVPrintPWNTraps(); - GV.WebServer = new ESP8266WebServer(GV_PORT); // Set CORS headers for global responses GV.WebServer->sendHeader("Access-Control-Allow-Origin", "*"); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino index 341a82c2f..4870abd00 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino @@ -1735,7 +1735,7 @@ void ZigbeeGlowPermitJoinLight(void) { analogWritePhase(led_pin, led_power, 0); } #else - analogWrite(led_pin, TasmotaGlobal.ledlnk_inverted ? 1023 - led_power : led_power); + AnalogWrite(led_pin, TasmotaGlobal.ledlnk_inverted ? 1023 - led_power : led_power); #endif } } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_24_buzzer.ino b/tasmota/tasmota_xdrv_driver/xdrv_24_buzzer.ino index 8f4c52b3f..f0646af15 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_24_buzzer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_24_buzzer.ino @@ -53,7 +53,7 @@ void BuzzerSet(uint32_t state) { // Set 50% duty cycle for frequency output // Set 0% (or 100% for inverted PWM) duty cycle which turns off frequency output either way #ifdef ESP8266 - analogWrite(Pin(GPIO_BUZZER), (state) ? Settings->pwm_range / 2 : 0); // set duty cycle for frequency output + AnalogWrite(Pin(GPIO_BUZZER), (state) ? Settings->pwm_range / 2 : 0); // set duty cycle for frequency output #else int32_t pin = Pin(GPIO_BUZZER); if (analogAttach(pin, Buzzer.inverted) >= 0) { diff --git a/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino b/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino index b6a11b3bb..2fdc52b07 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino @@ -218,7 +218,7 @@ void ShutterRtc50mS(void) ShutterUpdateVelocity(i); Shutter[i].real_position += Shutter[i].direction > 0 ? Shutter[i].pwm_velocity : (Shutter[i].direction < 0 ? -Shutter[i].pwm_velocity : 0); Shutter[i].pwm_value = SHT_DIV_ROUND((Settings->shutter_pwmrange[1][i]-Settings->shutter_pwmrange[0][i]) * Shutter[i].real_position , Shutter[i].open_max)+Settings->shutter_pwmrange[0][i]; - analogWrite(Pin(GPIO_PWM1, i), Shutter[i].pwm_value); + AnalogWrite(Pin(GPIO_PWM1, i), Shutter[i].pwm_value); break; case SHT_COUNTER: @@ -572,7 +572,7 @@ void ShutterDecellerateForStop(uint8_t i) while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter[i].target_position-Shutter[i].start_position)*Shutter[i].direction*ShutterGlobal.open_velocity_max/RESOLUTION/STEPS_PER_SECOND && missing_steps > 0) { } #ifdef ESP8266 - analogWrite(Pin(GPIO_PWM1, i), 0); // removed with 8.3 because of reset caused by watchog + AnalogWrite(Pin(GPIO_PWM1, i), 0); // removed with 8.3 because of reset caused by watchog #endif #ifdef ESP32 TasmotaGlobal.pwm_value[i] = 0; @@ -629,12 +629,12 @@ void ShutterPowerOff(uint8_t i) switch (ShutterGlobal.position_mode) { case SHT_PWM_VALUE: Shutter[i].pwm_value = SHT_DIV_ROUND((Settings->shutter_pwmrange[1][i]-Settings->shutter_pwmrange[0][i]) * Shutter[i].target_position , Shutter[i].open_max)+Settings->shutter_pwmrange[0][i]; - analogWrite(Pin(GPIO_PWM1, i), Shutter[i].pwm_value); + AnalogWrite(Pin(GPIO_PWM1, i), Shutter[i].pwm_value); AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: PWM final %d"),Shutter[i].pwm_value); char scmnd[20]; #ifdef SHUTTER_CLEAR_PWM_ONSTOP // free the PWM servo lock on stop. - analogWrite(Pin(GPIO_PWM1, i), 0); + AnalogWrite(Pin(GPIO_PWM1, i), 0); #endif break; } @@ -754,7 +754,7 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) case SHT_COUNTER: #ifdef ESP8266 analogWriteFreq(Shutter[i].pwm_velocity); - analogWrite(Pin(GPIO_PWM1, i), 0); + AnalogWrite(Pin(GPIO_PWM1, i), 0); #endif #ifdef ESP32 analogWriteFreq(PWM_MIN,Pin(GPIO_PWM1, i)); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_35_pwm_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_35_pwm_dimmer.ino index d5d2b00d3..8d4d7860d 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_35_pwm_dimmer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_35_pwm_dimmer.ino @@ -194,7 +194,7 @@ void PWMDimmerSetBrightnessLeds(int32_t bri) SetLedPowerIdx(led, bri > level); } else { uint16_t pwm_led_bri = changeUIntScale((bri > level ? bri - level : 0), 0, step, 0, Settings->pwm_range); - analogWrite(Pin(GPIO_LED1, led), bitRead(TasmotaGlobal.led_inverted, led) ? Settings->pwm_range - pwm_led_bri : pwm_led_bri); + AnalogWrite(Pin(GPIO_LED1, led), bitRead(TasmotaGlobal.led_inverted, led) ? Settings->pwm_range - pwm_led_bri : pwm_led_bri); } } } diff --git a/tasmota/tasmota_xlgt_light/xlgt_03_sm16716.ino b/tasmota/tasmota_xlgt_light/xlgt_03_sm16716.ino index 407ed67b9..d13d798bd 100644 --- a/tasmota/tasmota_xlgt_light/xlgt_03_sm16716.ino +++ b/tasmota/tasmota_xlgt_light/xlgt_03_sm16716.ino @@ -124,7 +124,7 @@ bool Sm16716SetChannels(void) for (uint32_t i = 3; i < Light.subtype; i++) { if (PinUsed(GPIO_PWM1, i-3)) { //AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d, Pwm%d %d"), i, cur_col[i], i+1, curcol); - analogWrite(Pin(GPIO_PWM1, i-3), bitRead(TasmotaGlobal.pwm_inverted, i-3) ? Settings->pwm_range - cur_col_10bits[i] : cur_col_10bits[i]); + AnalogWrite(Pin(GPIO_PWM1, i-3), bitRead(TasmotaGlobal.pwm_inverted, i-3) ? Settings->pwm_range - cur_col_10bits[i] : cur_col_10bits[i]); } } */ diff --git a/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino b/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino index 07d28a566..5dee065f8 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino @@ -324,6 +324,19 @@ void AdcInit(void) { } } +uint32_t AdcResolution(void) { + return ANALOG_RESOLUTION; +} + +bool AdcPin(uint32_t pin) { + for (uint32_t idx = 0; idx < Adcs.present; idx++) { + if (pin == Adc[idx].pin) { + return true; + } + } + return false; +} + uint16_t AdcRead(uint32_t pin, uint32_t factor) { // factor 1 = 2 samples // factor 2 = 4 samples From 298ee22ebfd4d522187a7355ada83ec3891f181c Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 7 Jan 2024 15:38:29 +0100 Subject: [PATCH 089/303] Berry add `string` to `bytes()` (#20420) --- CHANGELOG.md | 1 + lib/libesp32/berry/src/be_byteslib.c | 44 +++++++++++++++++++++++----- lib/libesp32/berry/tests/bytes.be | 19 ++++++++++++ 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66b447fad..c3fdbe4c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ All notable changes to this project will be documented in this file. - HASPmota `haspmota.page_show()` to change page (#20333) - Berry `introspect.set()` for class attributes (#20339) - Support negative power on BL0942 using index 5..8 (#20322) +- Berry add `string` to `bytes()` ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds (#20236) diff --git a/lib/libesp32/berry/src/be_byteslib.c b/lib/libesp32/berry/src/be_byteslib.c index c26a45df2..8d351997d 100644 --- a/lib/libesp32/berry/src/be_byteslib.c +++ b/lib/libesp32/berry/src/be_byteslib.c @@ -309,6 +309,17 @@ static size_t buf_add_buf(buf_impl* attr, buf_impl* attr2) return attr->len; } +static size_t buf_add_raw(buf_impl* attr, const void* buf_raw, int32_t len) +{ + uint8_t *buf = (uint8_t*) buf_raw; + if ((len > 0) && (attr->len + len <= attr->size)) { + for (int32_t i = 0; i < len; i++) { + attr->bufptr[attr->len++] = buf[i]; + } + } + return attr->len; +} + static uint8_t buf_get1(buf_impl* attr, int offset) { if ((offset >= 0) && (offset < attr->len)) { @@ -1211,17 +1222,26 @@ static int m_merge(bvm *vm) int argc = be_top(vm); buf_impl attr = m_read_attributes(vm, 1); /* no resize yet */ check_ptr(vm, &attr); - if (argc >= 2 && be_isbytes(vm, 2)) { - buf_impl attr2 = m_read_attributes(vm, 2); - check_ptr(vm, &attr2); + if (argc >= 2 && (be_isbytes(vm, 2) || be_isstring(vm, 2))) { + const uint8_t * buf; + int32_t buf_len; + if (be_isbytes(vm, 2)) { + buf_impl attr2 = m_read_attributes(vm, 2); + check_ptr(vm, &attr2); + buf = attr2.bufptr; + buf_len = attr2.len; + } else { + buf = (const uint8_t *)be_tostring(vm, 2); + buf_len = strlen((const char *)buf); + } /* allocate new object */ - bytes_new_object(vm, attr.len + attr2.len); + bytes_new_object(vm, attr.len + buf_len); buf_impl attr3 = m_read_attributes(vm, -1); check_ptr(vm, &attr3); buf_add_buf(&attr3, &attr); - buf_add_buf(&attr3, &attr2); + buf_add_raw(&attr3, buf, buf_len); m_write_attributes(vm, -1, &attr3); /* update instance */ be_return(vm); /* return self */ @@ -1249,13 +1269,23 @@ static int m_connect(bvm *vm) buf_impl attr = m_read_attributes(vm, 1); check_ptr(vm, &attr); if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); } - if (argc >= 2 && (be_isbytes(vm, 2) || be_isint(vm, 2))) { + if (argc >= 2 && (be_isbytes(vm, 2) || be_isint(vm, 2) || be_isstring(vm, 2))) { if (be_isint(vm, 2)) { bytes_resize(vm, &attr, attr.len + 1); /* resize */ buf_add1(&attr, be_toint(vm, 2)); m_write_attributes(vm, 1, &attr); /* update instance */ be_pushvalue(vm, 1); be_return(vm); /* return self */ + } else if (be_isstring(vm, 2)) { + const char *str = be_tostring(vm, 2); + size_t str_len = strlen(str); + if (str_len > 0) { + bytes_resize(vm, &attr, attr.len + str_len); /* resize */ + buf_add_raw(&attr, str, str_len); + m_write_attributes(vm, 1, &attr); /* update instance */ + } + be_pushvalue(vm, 1); + be_return(vm); /* return self */ } else { buf_impl attr2 = m_read_attributes(vm, 2); check_ptr(vm, &attr2); @@ -1266,7 +1296,7 @@ static int m_connect(bvm *vm) be_return(vm); /* return self */ } } - be_raise(vm, "type_error", "operand must be bytes or int"); + be_raise(vm, "type_error", "operand must be bytes or int or string"); be_return_nil(vm); /* return self */ } diff --git a/lib/libesp32/berry/tests/bytes.be b/lib/libesp32/berry/tests/bytes.be index 6a481d62c..4621747b1 100644 --- a/lib/libesp32/berry/tests/bytes.be +++ b/lib/libesp32/berry/tests/bytes.be @@ -103,6 +103,13 @@ assert(str(b) == "bytes('1122334455')") b = b2 + b1 assert(str(b) == "bytes('3344551122')") +#- + for string -# +b1 = bytes("AA") +b = b1 + '' +assert(str(b) == "bytes('AA')") +b = b1 + '01' +assert(str(b) == "bytes('AA3031')") + #- .. -# b1 = bytes("1122") b2 = bytes("334455") @@ -111,6 +118,13 @@ assert(str(b1) == "bytes('1122334455')") assert(str(b2) == "bytes('334455')") assert(str(b) == "bytes('1122334455')") +#- .. with string -# +b1 = bytes("AA") +b1 .. '' +assert(str(b1) == "bytes('AA')") +b1 .. '01' +assert(str(b1) == "bytes('AA3031')") + #- item -# b = bytes("334455") assert(b[0] == 0x33) @@ -257,3 +271,8 @@ assert(!bytes()) assert(bool(bytes("00")) == true) assert(bytes("01").tobool() == true) assert(bytes("02")) + +# retrieving 3-bytes little/big endian +a = bytes("01020304") +assert(a.get(1, 3) == 0x040302) +assert(a.get(1, -3) == 0x020304) From 82313c65b7be49bf5bb4c19a6428d49e5a201041 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 7 Jan 2024 16:06:31 +0100 Subject: [PATCH 090/303] Add GPIO Viewer button --- tasmota/language/af_AF.h | 1 + tasmota/language/bg_BG.h | 1 + tasmota/language/ca_AD.h | 1 + tasmota/language/cs_CZ.h | 1 + tasmota/language/de_DE.h | 1 + tasmota/language/el_GR.h | 1 + tasmota/language/en_GB.h | 1 + tasmota/language/es_ES.h | 1 + tasmota/language/fr_FR.h | 1 + tasmota/language/fy_NL.h | 1 + tasmota/language/he_HE.h | 1 + tasmota/language/hu_HU.h | 1 + tasmota/language/it_IT.h | 1 + tasmota/language/ko_KO.h | 1 + tasmota/language/nl_NL.h | 1 + tasmota/language/pl_PL.h | 1 + tasmota/language/pt_BR.h | 1 + tasmota/language/pt_PT.h | 1 + tasmota/language/ro_RO.h | 1 + tasmota/language/ru_RU.h | 1 + tasmota/language/sk_SK.h | 1 + tasmota/language/sv_SE.h | 1 + tasmota/language/tr_TR.h | 1 + tasmota/language/uk_UA.h | 1 + tasmota/language/vi_VN.h | 1 + tasmota/language/zh_CN.h | 1 + tasmota/language/zh_TW.h | 1 + .../xdrv_121_gpioviewer.ino | 39 +++++++++++-------- 28 files changed, 49 insertions(+), 17 deletions(-) diff --git a/tasmota/language/af_AF.h b/tasmota/language/af_AF.h index d90ee06c7..eb8ef8734 100644 --- a/tasmota/language/af_AF.h +++ b/tasmota/language/af_AF.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Inligting" #define D_FIRMWARE_UPGRADE "Firmware-opgradering" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konsole" #define D_CONFIRM_RESTART "Bevestig weer te begin" diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index bffd921e2..8d02d6967 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Информация" #define D_FIRMWARE_UPGRADE "Обновяване на софтуера" #define D_MANAGEMENT "Терминали" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Терминал" #define D_CONFIRM_RESTART "Потвърдете рестартиране" diff --git a/tasmota/language/ca_AD.h b/tasmota/language/ca_AD.h index 834481513..51477766f 100644 --- a/tasmota/language/ca_AD.h +++ b/tasmota/language/ca_AD.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Informació" #define D_FIRMWARE_UPGRADE "Actualització de programari" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Consola" #define D_CONFIRM_RESTART "Confirma el Reinici" diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index 9a8197a40..e62539927 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Informace" #define D_FIRMWARE_UPGRADE "Aktualizace firmware" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konzole" #define D_CONFIRM_RESTART "Potvrzení restartu" diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index c3bfe2dd7..c4a3ce265 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Informationen" #define D_FIRMWARE_UPGRADE "Firmware Update" #define D_MANAGEMENT "Konsolen" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konsole" #define D_CONFIRM_RESTART "Wirklich neustarten?" diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h index 1edf65357..7efd379ca 100644 --- a/tasmota/language/el_GR.h +++ b/tasmota/language/el_GR.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Πληροφορίες" #define D_FIRMWARE_UPGRADE "Αναβάθμιση" #define D_MANAGEMENT "Διαχείριση" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Κονσόλα" #define D_CONFIRM_RESTART "Επιβεβαίωση επανεκκίνησης" diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index 139316d74..3f8d89854 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Information" #define D_FIRMWARE_UPGRADE "Firmware Upgrade" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Console" #define D_CONFIRM_RESTART "Confirm Restart" diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h index 8c0ed3475..9e6c0ed8d 100644 --- a/tasmota/language/es_ES.h +++ b/tasmota/language/es_ES.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Información" #define D_FIRMWARE_UPGRADE "Actualizar Firmware" #define D_MANAGEMENT "Consolas" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Consola" #define D_CONFIRM_RESTART "Confirmar Reinicio" diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index 0e89c0560..70515fb04 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Informations" #define D_FIRMWARE_UPGRADE "Mise à jour du Firmware" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Console" #define D_CONFIRM_RESTART "Confirmer le redémarrage" diff --git a/tasmota/language/fy_NL.h b/tasmota/language/fy_NL.h index 436782c93..9d6d146be 100644 --- a/tasmota/language/fy_NL.h +++ b/tasmota/language/fy_NL.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Ynformaasje" #define D_FIRMWARE_UPGRADE "Opwurdearje" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konsole" #define D_CONFIRM_RESTART "Befestigje opnij starte" diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index d489b2f64..23ca7488e 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -275,6 +275,7 @@ #define D_INFORMATION "מידע" #define D_FIRMWARE_UPGRADE "שדרוג קושחה" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "קונסול" #define D_CONFIRM_RESTART "אישור הפעלה מחדש" diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index a9715ef10..b12b037cd 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Információ" #define D_FIRMWARE_UPGRADE "Firmware frissítés" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konzol" #define D_CONFIRM_RESTART "Biztosan újraindítsam a modult?" diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index 29a012781..6f2c978a2 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Informazioni" #define D_FIRMWARE_UPGRADE "Aggiorna firmware" #define D_MANAGEMENT "Console" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Console" #define D_CONFIRM_RESTART "Conferma riavvio" diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index 8fe87643b..07d0aa583 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -275,6 +275,7 @@ #define D_INFORMATION "정보" #define D_FIRMWARE_UPGRADE "펌웨어 업그레이드" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "콘솔" #define D_CONFIRM_RESTART "재시작" diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index 1ad5fa61f..fa6b80c59 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Informatie" #define D_FIRMWARE_UPGRADE "Opwaarderen" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Console" #define D_CONFIRM_RESTART "Bevestig herstart" diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h index 7693b986d..b6d6f9fe7 100644 --- a/tasmota/language/pl_PL.h +++ b/tasmota/language/pl_PL.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Informacje" #define D_FIRMWARE_UPGRADE "Aktualizacja oprogramowania" #define D_MANAGEMENT "Konsole" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konsola" #define D_CONFIRM_RESTART "Potwierdź restart" diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index 0ee9a4433..e8c9c8fd4 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Informação" #define D_FIRMWARE_UPGRADE "Atualização de firmware" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Console" #define D_CONFIRM_RESTART "Confirmar o reinicio" diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index e94a640f2..6dff9cfba 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Informação" #define D_FIRMWARE_UPGRADE "Atualização de Firmware" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Consola" #define D_CONFIRM_RESTART "Confirmar o reinício" diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index b90c3a960..33ab21b5c 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Informație" #define D_FIRMWARE_UPGRADE "Actualizare Firmware" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Consolă" #define D_CONFIRM_RESTART "Confirmare Restart" diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h index 82f01ca3f..4e4a729e7 100644 --- a/tasmota/language/ru_RU.h +++ b/tasmota/language/ru_RU.h @@ -276,6 +276,7 @@ #define D_INFORMATION "Информация" #define D_FIRMWARE_UPGRADE "Обновление прошивки" #define D_MANAGEMENT "Управление" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Консоль" #define D_CONFIRM_RESTART "Перезагрузить устройство?" diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index 5ea1875bd..c20680d07 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Informácie" #define D_FIRMWARE_UPGRADE "Aktualizácia firmware" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konzola" #define D_CONFIRM_RESTART "Potvrdenie reštartu" diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index 99d27f132..0fc002329 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Information" #define D_FIRMWARE_UPGRADE "Uppgradera firmware" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konsol" #define D_CONFIRM_RESTART "Bekräfta omstart" diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index 3377a17f6..caddd0fde 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Bilgi" #define D_FIRMWARE_UPGRADE "Cihaz yazılımını Güncelle" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konsol" #define D_CONFIRM_RESTART "Yeniden Başlatmayı Onayla" diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index d8b33392d..95e6fd6be 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Інформація" #define D_FIRMWARE_UPGRADE "Оновлення прошивки" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Консоль" #define D_CONFIRM_RESTART "Підтвердити перезавантаження" diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h index 990f558a0..a2eae6e99 100644 --- a/tasmota/language/vi_VN.h +++ b/tasmota/language/vi_VN.h @@ -275,6 +275,7 @@ #define D_INFORMATION "Thông tin" #define D_FIRMWARE_UPGRADE "Nâng cấp Firmware" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Dòng Lệnh" #define D_CONFIRM_RESTART "Xác nhận khởi động lại" diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index dc0a6ec4c..af408878a 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -275,6 +275,7 @@ #define D_INFORMATION "信息" #define D_FIRMWARE_UPGRADE "固件升级" #define D_MANAGEMENT "控制台" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "控制台" #define D_CONFIRM_RESTART "确认重启" diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index 992838e00..f9ed358f4 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -275,6 +275,7 @@ #define D_INFORMATION "資訊" #define D_FIRMWARE_UPGRADE "韌體升級" #define D_MANAGEMENT "Consoles" +#define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "控制台" #define D_CONFIRM_RESTART "確認重新啟動" diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 0420b88ab..8402ea149 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -38,7 +38,7 @@ const char HTTP_GV_PAGE[] PROGMEM = "var ip='%s';" // WiFi.localIP().toString().c_str() "var source=new EventSource('http://%s:" STR(GV_PORT) "/events');" // WiFi.localIP().toString().c_str() "var sampling_interval='" STR(GV_SAMPLING_INTERVAL) "';" - "var freeSketchSpace='%s';" // GVFormatBytes(ESP_getFreeSketchSpace()).c_str() + "var freeSketchSpace='%d KB';" // ESP_getFreeSketchSpace() / 1024 "" "" "" @@ -63,6 +63,9 @@ const char HTTP_GV_EVENT[] PROGMEM = "Cache-Control: no-cache\n" "Access-Control-Allow-Origin: *\n\n"; +const char HTTP_BTN_MENU_GV[] PROGMEM = + "

"; + enum GVPinTypes { digitalPin = 0, PWMPin = 1, @@ -80,18 +83,6 @@ struct { bool active; } GV; -String GVFormatBytes(size_t bytes) { - if (bytes < 1024) { - return String(bytes) + " B"; - } - else if (bytes < (1024 * 1024)) { - return String(bytes / 1024.0, 2) + " KB"; - } - else { - return String(bytes / 1024.0 / 1024.0, 2) + " MB"; - } -} - int GVReadGPIO(int gpioNum, uint32_t *originalValue, uint32_t *pintype) { uint32_t pin_type = GetPin(gpioNum) / 32; /* @@ -184,7 +175,6 @@ void GVMonitorTask(void) { hasChanges = true; } } - jsonMessage += "}"; if (hasChanges) { @@ -194,7 +184,9 @@ void GVMonitorTask(void) { uint32_t heap = ESP_getFreeHeap(); if (heap != GV.freeHeap) { GV.freeHeap = heap; - GVEventSend(GVFormatBytes(GV.freeHeap).c_str(), "free_heap", millis()); + char temp[20]; + snprintf_P(temp, sizeof(temp), PSTR("%d KB"), heap / 1024); + GVEventSend(temp, "free_heap", millis()); } #ifdef ESP32 @@ -202,8 +194,12 @@ void GVMonitorTask(void) { uint32_t psram = ESP.getFreePsram(); if (psram != GV.freePSRAM) { GV.freePSRAM = psram; - GVEventSend(GVFormatBytes(GV.freePSRAM).c_str(), "free_psram", millis()); + char temp[20]; + snprintf_P(temp, sizeof(temp), PSTR("%d KB"), psram / 1024); + GVEventSend(temp, "free_psram", millis()); } + } else { + GVEventSend("No PSRAM", "free_psram", millis()); } #endif // ESP32 } @@ -237,7 +233,7 @@ void GVHandleRoot(void) { char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, WiFi.localIP().toString().c_str(), WiFi.localIP().toString().c_str(), - GVFormatBytes(ESP_getFreeSketchSpace()).c_str()); + ESP_getFreeSketchSpace() / 1024); if (content == nullptr) { return; } // Avoid crash GV.WebServer->send_P(200, "text/html", content); @@ -267,6 +263,15 @@ bool Xdrv121(uint32_t function) { case FUNC_EVERY_100_MSECOND: if (GV.sse_ready) { GVMonitorTask(); } break; +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_MANAGEMENT_BUTTON: + if (XdrvMailbox.index) { + XdrvMailbox.index++; + } else { + WSContentSend_P(HTTP_BTN_MENU_GV, WiFi.localIP().toString().c_str()); + } + break; +#endif // USE_WEBSERVER case FUNC_ACTIVE: result = true; break; From 332084723773ef02bf26bf5503a1baa9f6925b94 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 7 Jan 2024 16:15:08 +0100 Subject: [PATCH 091/303] Update changelogs --- CHANGELOG.md | 8 ++++---- RELEASENOTES.md | 7 +++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3fdbe4c4..17715e6b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,10 +9,11 @@ All notable changes to this project will be documented in this file. - Berry add support for `tcpclientasync` in `tcpserver` (#20401) - Berry add `tasmota.urlbecload(url:string) -> bool` (#20412) - GPIO Viewer to see realtime GPIO states. Enable with define USE_GPIO_VIEWER -- Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` -- Berry `gpio.get_pin_type` and `gpio.ger_pin_type_index` - Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` (#20414) -- GPIO viewer in Berry initial version using async webserver +- Berry `gpio.get_pin_type` and `gpio.ger_pin_type_index` (#20415) +- Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` (#20414) +- Berry GPIO viewer initial version using async webserver (#20416) +- Berry add `string` to `bytes()` (#20420) ### Breaking Changed @@ -34,7 +35,6 @@ All notable changes to this project will be documented in this file. - HASPmota `haspmota.page_show()` to change page (#20333) - Berry `introspect.set()` for class attributes (#20339) - Support negative power on BL0942 using index 5..8 (#20322) -- Berry add `string` to `bytes()` ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds (#20236) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e13594cf8..8d26e47ce 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -126,10 +126,13 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Support negative power on BL0942 using index 5..8 [#20322](https://github.com/arendst/Tasmota/issues/20322) - ESP32 used UART information - ESP32 experimental support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled +- Berry GPIO viewer initial version using async webserver [#20416](https://github.com/arendst/Tasmota/issues/20416) - Berry `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) -- Berry add support for `tcpclientasync` in `tcpserver` [#20401](https://github.com/arendst/Tasmota/issues/20401) -- Berry add `tasmota.urlbecload(url:string) -> bool` [#20412](https://github.com/arendst/Tasmota/issues/20412) +- Berry support for `tcpclientasync` in `tcpserver` [#20401](https://github.com/arendst/Tasmota/issues/20401) +- Berry `tasmota.urlbecload(url:string) -> bool` [#20412](https://github.com/arendst/Tasmota/issues/20412) - Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` [#20414](https://github.com/arendst/Tasmota/issues/20414) +- Berry `gpio.get_pin_type` and `gpio.ger_pin_type_index` [#20415](https://github.com/arendst/Tasmota/issues/20415) +- Berry `string` to `bytes()` [#20420](https://github.com/arendst/Tasmota/issues/20420) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) - HASPmota type `chart` [#20372](https://github.com/arendst/Tasmota/issues/20372) - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) From 5c521d300a58c5dcea125359045e5f9a1b26cc78 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 7 Jan 2024 18:10:30 +0100 Subject: [PATCH 092/303] Add gpioviewer startup delay --- .../tasmota_xdrv_driver/xdrv_121_gpioviewer.ino | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 8402ea149..f45e5ae3d 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -18,10 +18,10 @@ #define GV_PORT 5557 #define GV_SAMPLING_INTERVAL 100 // Relates to FUNC_EVERY_100_MSECOND -const char *GVRelease = "1.0.7"; - #define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" +const char *GVRelease = "1.0.7"; + const char HTTP_GV_PAGE[] PROGMEM = "" "" @@ -280,8 +280,14 @@ bool Xdrv121(uint32_t function) { switch (function) { case FUNC_EVERY_SECOND: if (!TasmotaGlobal.global_state.network_down) { - GVBegin(); - GV.active = true; + // Add delay to finish network setup + static uint32_t gv_delay = 3; + if (gv_delay) { + gv_delay--; + } else { + GVBegin(); + GV.active = true; + } } break; } From f0d0cccee612e08b5fb72c47dc8dc25ef35d61c1 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 7 Jan 2024 19:03:56 +0100 Subject: [PATCH 093/303] Berry GPIO Viewer fixes (#20423) --- tasmota/berry/gpio_viewer/gpioviewer.be | 51 ++++-- tasmota/berry/gpio_viewer/gpioviewer.bec | Bin 10867 -> 12122 bytes tasmota/berry/gpio_viewer/webserver_async.be | 169 ++++++++++++++----- 3 files changed, 166 insertions(+), 54 deletions(-) diff --git a/tasmota/berry/gpio_viewer/gpioviewer.be b/tasmota/berry/gpio_viewer/gpioviewer.be index ae379f52d..c0f99af67 100644 --- a/tasmota/berry/gpio_viewer/gpioviewer.be +++ b/tasmota/berry/gpio_viewer/gpioviewer.be @@ -19,10 +19,6 @@ var gpio_viewer = module('gpio_viewer') -gpio_viewer.Webserver_async_cnx = Webserver_async_cnx -gpio_viewer.Webserver_dispatcher = Webserver_dispatcher -gpio_viewer.Webserver_async = Webserver_async - class GPIO_viewer var web var sampling_interval @@ -30,6 +26,7 @@ class GPIO_viewer var last_pin_states # state converted to 0..255 var new_pin_states # get a snapshot of newest values var pin_types # array of types + var payload1, payload2 # temporary object bytes() to avoid reallocation static var TYPE_DIGITAL = 0 static var TYPE_PWM = 1 @@ -67,8 +64,10 @@ class GPIO_viewer "" def init(port) - self.web = Webserver_async(5555) + self.web = webserver_async(5555) self.sampling_interval = self.SAMPLING + self.payload1 = bytes(100) # reserve 100 bytes by default + self.payload2 = bytes(100) # reserve 100 bytes by default # pins import gpio @@ -81,6 +80,8 @@ class GPIO_viewer self.pin_types = [] self.pin_types.resize(gpio.MAX_GPIO) # full of nil + self.web.set_chunked(true) + self.web.set_cors(true) self.web.on("/release", self, self.send_release_page) self.web.on("/events", self, self.send_events_page) self.web.on("/", self, self.send_index_page) @@ -118,7 +119,7 @@ class GPIO_viewer end def send_events_page(cnx, uri, verb) - cnx.set_mode_chunked(false) # no chunking since we use EventSource + cnx.set_chunked(false) # no chunking since we use EventSource cnx.send(200, "text/event-stream") self.send_events_tick(cnx) @@ -127,7 +128,9 @@ class GPIO_viewer def send_events_tick(cnx) import gpio var max_gpio = gpio.MAX_GPIO - var msg = "{" + var payload1 = self.payload1 + payload1.clear() + payload1 .. '{' var dirty = false var pin = 0 self.read_states() @@ -136,24 +139,44 @@ class GPIO_viewer var prev = self.last_pin_states[pin] var val = self.new_pin_states[pin] if (prev != val) || (val != nil) # TODO for now send everything every time - if dirty msg += "," end - msg += f'"{pin}":{{"s":{val},"v":{prev},"t":{self.pin_types[pin]}}}' + if dirty + # msg += "," + payload1 .. "," + end + payload1 .. '"' + payload1 .. str(pin) + payload1 .. '":{"s":' + payload1 .. str(val) + payload1 .. ',"v":' + payload1 .. str(self.pin_actual[pin]) + payload1 .. ',"t":' + payload1 .. str(self.pin_types[pin]) + payload1 .. '}' + # msg += f'"{pin}":{{"s":{val},"v":{prev},"t":{self.pin_types[pin]}}}}' dirty = true self.last_pin_states[pin] = val end pin += 1 end - msg += "}" + payload1 .. '}' + # msg += "}" if dirty # prepare payload - var payload = f"id:{tasmota.millis()}\r\n" - "event:gpio-state\r\n" - "data:{msg}\r\n\r\n" + var payload2 = self.payload2 + payload2.clear() + payload2 .. 'id:' + payload2 .. str(tasmota.millis()) + payload2 .. "\r\nevent:gpio-state\r\ndata:" + payload2 .. payload1 + payload2 .. "\r\n\r\n" + # var payload = f"id:{tasmota.millis()}\r\n" + # "event:gpio-state\r\n" + # "data:{msg}\r\n\r\n" # tasmota.log(f"GPV: sending '{msg}'", 3) - cnx.write(payload) + cnx.write(payload2) end # send free heap diff --git a/tasmota/berry/gpio_viewer/gpioviewer.bec b/tasmota/berry/gpio_viewer/gpioviewer.bec index 6c4bbed9480ae7b0d76ec2c97370c472691df6e8..bc2d96dfa4ea7b6465d613540849e0feb2b39ff0 100644 GIT binary patch delta 3050 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 PA<2F`JlB{y65#& 0 var buf_in_new = cnx.read() if (!self.buf_in) @@ -122,6 +159,39 @@ class Webserver_async_cnx end end + ############################################################# + # try sending what we can immediately + def _send() + # any data waiting to go out? + var cnx = self.cnx + if (cnx == nil) return end + var buf_out = self.buf_out + if size(buf_out) > 0 + if cnx.listening() + var sent = cnx.write(buf_out) + if sent > 0 + # we did sent something + if sent >= size(buf_out) + # all sent + self.buf_out.clear() + else + # remove the first bytes already sent + self.buf_out.setbytes(0, buf_out, sent) + self.byf_out.resize(size(buf_out) - sent) + end + end + end + else + # empty buffer, do the cleaning + self.buf_out.clear() + self.buf_in_offset = 0 + + if self.close_after_send + self.close() + end + end + end + ############################################################# # parse incoming # @@ -209,13 +279,6 @@ class Webserver_async_cnx if (header_key == "Host") self.header_host = header_value end - # import string - # header_key = string.tolower(header_key) - # header_value = string.tolower(header_value) - # print("header=", header_key, header_value) - # if header_key == 'transfer-encoding' && string.tolower(header_value) == 'chunked' - # self.is_chunked = true - # end end ############################################################# @@ -223,12 +286,6 @@ class Webserver_async_cnx # # All headers are received def event_http_headers_end() - # print("event_http_headers_end") - # truncate to save space - # if self.buf_in_offset > 0 - # self.buf_in = self.buf_in[self.buf_in_offset .. ] - # self.buf_in_offset = 0 - # end end ############################################################# @@ -243,7 +300,6 @@ class Webserver_async_cnx ############################################################# # Responses ############################################################# - ############################################################# # parse incoming payload (if any) def send_header(name, value, first) if first @@ -260,13 +316,15 @@ class Webserver_async_cnx # force chunked TODO self.send_header("Accept-Ranges", "none") - if self.mode_chunked + if self.chunked self.send_header("Transfer-Encoding", "chunked") end # cors - self.send_header("Access-Control-Allow-Origin", "*") - self.send_header("Access-Control-Allow-Methods", "*") - self.send_header("Access-Control-Allow-Headers", "*") + if self.cors + self.send_header("Access-Control-Allow-Origin", "*") + self.send_header("Access-Control-Allow-Methods", "*") + self.send_header("Access-Control-Allow-Headers", "*") + end # others self.send_header("Connection", "close") @@ -275,7 +333,7 @@ class Webserver_async_cnx self.resp_headers = nil # send - self._write(response) + self.write_raw(response) if (content) self.write(content) end end @@ -286,26 +344,43 @@ class Webserver_async_cnx ############################################################# # async write - def write(s) + def write(v) + if type(v) == 'string' # if string, convert to bytes + v = bytes().fromstring(v) + end + # use chunk encoding - if self.mode_chunked - var chunk = f"{size(s):X}\r\n{s}\r\n" - tasmota.log(f"WEB: sending chunk '{bytes().fromstring(chunk).tohex()}'") - self._write(chunk) + if self.chunked + var payload1 = self.payload1 + payload1.clear() + payload1 .. f"{size(v):X}\r\n" + payload1 .. v + payload1 .. "\r\n" + + # var chunk = f"{size(v):X}\r\n{v}\r\n" + # tasmota.log(f"WEB: sending chunk '{payload1.tohex()}'") + self._write(payload1) else - self._write(s) + self._write(v) end end - + ############################################################# # async write - def _write(s) - self.cnx.write(s) # TODO move to async later + def write_raw(v) + if (size(v) == 0) return end + + if type(v) == 'string' # if string, convert to bytes + v = bytes().fromstring(v) + end + + self._write(v) end + def content_stop() self.write('') - self.close() + self.close_after_send = true end end @@ -337,7 +412,7 @@ class Webserver_dispatcher end end -class Webserver_async +class webserver_async var local_port # listening port, 80 is already used by Tasmota var server # instance of `tcpserver` var fastloop_cb # closure used by fastloop @@ -347,6 +422,9 @@ class Webserver_async # var auth # web authentication string (Basic Auth) or `nil`, in format `user:password` as bade64 # var cmd # GET url command var dispatchers + # copied in each connection + var chunked # if true enable chunked encoding (default true) + var cors # if true send CORS headers (default true) static var TIMEOUT = 1000 # default timeout: 1000ms static var HTTP_REQ = "^(\\w+) (\\S+) HTTP\\/(\\d\\.\\d)\r\n" @@ -379,6 +457,14 @@ class Webserver_async end end + def set_chunked(chunked) + self.chunked = bool(chunked) + end + + def set_cors(cors) + self.cors = bool(cors) + end + ############################################################# # closing web server def close() @@ -420,9 +506,10 @@ class Webserver_async # check if any incoming connection while self.server.hasclient() # retrieve new client - var cnx = Webserver_async_cnx(self, self.server.accept()) # TODO move to self.server.acceptasync + var cnx = Webserver_async_cnx(self, self.server.acceptasync()) + cnx.set_chunked(self.chunked) + cnx.set_cors(self.cors) self.connections.push(cnx) - tasmota.log(f"WEB: received connection from XXX") end end @@ -451,9 +538,11 @@ class Webserver_async end +#return webserver_async + #- Test -var web = Webserver_async(888) +var web = webserver_async(888) def send_more(cnx, i) cnx.write(f"

Hello world {i}

") From e5a0da06dc9e00881ddeb8f8988d96116f39244d Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 7 Jan 2024 23:19:53 +0100 Subject: [PATCH 094/303] Update GPIO Viewer (#20425) --- tasmota/berry/gpio_viewer/gpioviewer.be | 22 ++++++++++++++++++++-- tasmota/berry/gpio_viewer/gpioviewer.bec | Bin 12122 -> 12614 bytes 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/tasmota/berry/gpio_viewer/gpioviewer.be b/tasmota/berry/gpio_viewer/gpioviewer.be index c0f99af67..91df7624b 100644 --- a/tasmota/berry/gpio_viewer/gpioviewer.be +++ b/tasmota/berry/gpio_viewer/gpioviewer.be @@ -20,6 +20,7 @@ var gpio_viewer = module('gpio_viewer') class GPIO_viewer + var port var web var sampling_interval var pin_actual # actual value @@ -64,6 +65,7 @@ class GPIO_viewer "" def init(port) + self.port = port self.web = webserver_async(5555) self.sampling_interval = self.SAMPLING self.payload1 = bytes(100) # reserve 100 bytes by default @@ -85,9 +87,12 @@ class GPIO_viewer self.web.on("/release", self, self.send_release_page) self.web.on("/events", self, self.send_events_page) self.web.on("/", self, self.send_index_page) + + tasmota.add_driver(self) end def close() + tasmota.remove_driver(self) self.web.close() end @@ -217,15 +222,28 @@ class GPIO_viewer end end + # Add button 'GPIO Viewer' redirects to '/part_wiz?' + def web_add_button() + import webserver + var ip = tasmota.wifi().find('ip') + if (ip == nil) + ip = tasmota.eth().find('ip') + end + if (ip != nil) + webserver.content_send( + f"

") + end + end + end gpio_viewer.GPIO_viewer = GPIO_viewer if tasmota - var gpio_viewer = GPIO_viewer(5555) + global.gpioviewer = GPIO_viewer(5555) end -return gpio_viewer +return global.gpioviewer #- Test diff --git a/tasmota/berry/gpio_viewer/gpioviewer.bec b/tasmota/berry/gpio_viewer/gpioviewer.bec index bc2d96dfa4ea7b6465d613540849e0feb2b39ff0..5000b670fd33186560536a3bfe9ce172028f9944 100644 GIT binary patch delta 1022 zcmZ`&T~E_c7=C+tR=QDUg^moFT0@o^A})G4w;5DK!gLEP2+88;wgL^?+O$VLlA3Y3 z3oc6b3rM*3!rkl_=&hH=OB4TsUYU5#R?sZrqCI)u=k5FPoTuO4eXjZm?&aC--$@MU z2sTh39t-_Xu}BFJ_P9;tv)BU;Iso`&p|`+!cZ4ti$k6L0SNS#uvt^Ru8vuz2Rw>H? z{SZfJp(rgRdI%vOb7BVx$d7@zU4tMV8Nm|$E*iO*1Zf*U@^~5fA}4jiW726Pq;vpF z-W4~E{PFg6WE}a@b=)oFPmFLJ#ZlS>kWyq#7``!rWr}ZtvI!6`PjZP4h>}-eiHw*E z2qhpc#`MK`FCFRIHO3rY8p5a!BvjJ%yW*$AIW=(;~VY0li+Y)E)D{ zZ~(d=?(NE=Ie9!m)U zqDO$D{m@`rDmgtd8=4I#h~*$pWqATGoyOasY>z>lCM3!tr*=S4yvt1n&Iq&lT*ILg z|F;N+LvzQZYwnn>x{ScIWgZN&CrePXTEu9Pifd5j17vnAr>VN+xM5_qy6M^t{Wz^w z8&+-qiKgmCjhI#|tL+hDr&FnNRzRz0iPmP<61=+3S|vRb9u&|CXjE;E!W zw_IE)s2iqnXgHZv5X+=k!(7JBWm0x7xQOo8`B?AA+!wCr+`<$}cUhFG26m{cl_>1ht0c8o@y?2_q1@ zXR}jJ5r;cGkLeZRfgdpQ!#@j5fMYbR10!$&m5u5vU)6!`oO(Vf4kswSeNBJVp_P8l Z+jv$MV7Fma^#*m)u5DTegWU(-_zRGGKJy_tG}s)&k;F2pyewO+8=P>Wg+D=jVr@q&Ub0(O~&N+eGp z_ylGnbT8-&2tI^cx1QK4(#;wE|9o>e^Uq7|W6#To-2Kp3hCo-Cr{|}1R~ZBcbMy?z z#tZ=eZm=&XiTbdvSjGLuM5YqON_o9dT_`SA03G$ClkJ*Z(ho zp&n*HmK_cVb*w|jStnra00X;8k#V6~T_)awT;|^yo#^#HrygP^mhIJIwUjU9vzz%KHTfzG)ne`K^`JSjrUh@)@4}ap MiJ&=qD)pan-*i!7O#lD@ From d51340961fe2487c673b157335cdf85e6d73106c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 8 Jan 2024 09:29:02 +0100 Subject: [PATCH 095/303] Rename "Consoles" to "Tools" --- tasmota/language/af_AF.h | 2 +- tasmota/language/ca_AD.h | 2 +- tasmota/language/cs_CZ.h | 2 +- tasmota/language/en_GB.h | 2 +- tasmota/language/fr_FR.h | 2 +- tasmota/language/fy_NL.h | 2 +- tasmota/language/he_HE.h | 2 +- tasmota/language/hu_HU.h | 2 +- tasmota/language/ko_KO.h | 2 +- tasmota/language/nl_NL.h | 2 +- tasmota/language/pt_BR.h | 2 +- tasmota/language/pt_PT.h | 2 +- tasmota/language/ro_RO.h | 2 +- tasmota/language/sk_SK.h | 2 +- tasmota/language/sv_SE.h | 2 +- tasmota/language/tr_TR.h | 2 +- tasmota/language/uk_UA.h | 2 +- tasmota/language/vi_VN.h | 2 +- tasmota/language/zh_TW.h | 2 +- tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino | 3 ++- 20 files changed, 21 insertions(+), 20 deletions(-) diff --git a/tasmota/language/af_AF.h b/tasmota/language/af_AF.h index eb8ef8734..406c96c45 100644 --- a/tasmota/language/af_AF.h +++ b/tasmota/language/af_AF.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Konfigurasie" #define D_INFORMATION "Inligting" #define D_FIRMWARE_UPGRADE "Firmware-opgradering" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konsole" #define D_CONFIRM_RESTART "Bevestig weer te begin" diff --git a/tasmota/language/ca_AD.h b/tasmota/language/ca_AD.h index 51477766f..55fe18f99 100644 --- a/tasmota/language/ca_AD.h +++ b/tasmota/language/ca_AD.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Configuració" #define D_INFORMATION "Informació" #define D_FIRMWARE_UPGRADE "Actualització de programari" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Consola" #define D_CONFIRM_RESTART "Confirma el Reinici" diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index e62539927..71453c987 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Nastavení" #define D_INFORMATION "Informace" #define D_FIRMWARE_UPGRADE "Aktualizace firmware" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konzole" #define D_CONFIRM_RESTART "Potvrzení restartu" diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index 3f8d89854..8d82a9408 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Configuration" #define D_INFORMATION "Information" #define D_FIRMWARE_UPGRADE "Firmware Upgrade" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Console" #define D_CONFIRM_RESTART "Confirm Restart" diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index 70515fb04..c1063146d 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Configuration" #define D_INFORMATION "Informations" #define D_FIRMWARE_UPGRADE "Mise à jour du Firmware" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Console" #define D_CONFIRM_RESTART "Confirmer le redémarrage" diff --git a/tasmota/language/fy_NL.h b/tasmota/language/fy_NL.h index 9d6d146be..fcf0973a2 100644 --- a/tasmota/language/fy_NL.h +++ b/tasmota/language/fy_NL.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Konfiguraasje" #define D_INFORMATION "Ynformaasje" #define D_FIRMWARE_UPGRADE "Opwurdearje" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konsole" #define D_CONFIRM_RESTART "Befestigje opnij starte" diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index 23ca7488e..fc74df7ff 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "הגדרות" #define D_INFORMATION "מידע" #define D_FIRMWARE_UPGRADE "שדרוג קושחה" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "קונסול" #define D_CONFIRM_RESTART "אישור הפעלה מחדש" diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index b12b037cd..8592a911e 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Beállítások" #define D_INFORMATION "Információ" #define D_FIRMWARE_UPGRADE "Firmware frissítés" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konzol" #define D_CONFIRM_RESTART "Biztosan újraindítsam a modult?" diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index 07d0aa583..e0b6871f6 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "설정 메뉴" #define D_INFORMATION "정보" #define D_FIRMWARE_UPGRADE "펌웨어 업그레이드" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "콘솔" #define D_CONFIRM_RESTART "재시작" diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index fa6b80c59..6cd4b2c2b 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Configuratie" #define D_INFORMATION "Informatie" #define D_FIRMWARE_UPGRADE "Opwaarderen" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Console" #define D_CONFIRM_RESTART "Bevestig herstart" diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index e8c9c8fd4..f73294280 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Configuração" #define D_INFORMATION "Informação" #define D_FIRMWARE_UPGRADE "Atualização de firmware" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Console" #define D_CONFIRM_RESTART "Confirmar o reinicio" diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index 6dff9cfba..d29fd64cf 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Configuração" #define D_INFORMATION "Informação" #define D_FIRMWARE_UPGRADE "Atualização de Firmware" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Consola" #define D_CONFIRM_RESTART "Confirmar o reinício" diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index 33ab21b5c..754f0021c 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Configurație" #define D_INFORMATION "Informație" #define D_FIRMWARE_UPGRADE "Actualizare Firmware" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Consolă" #define D_CONFIRM_RESTART "Confirmare Restart" diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index c20680d07..0bdbc978e 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Nastavenia" #define D_INFORMATION "Informácie" #define D_FIRMWARE_UPGRADE "Aktualizácia firmware" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konzola" #define D_CONFIRM_RESTART "Potvrdenie reštartu" diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index 0fc002329..b702a0054 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Konfigurering" #define D_INFORMATION "Information" #define D_FIRMWARE_UPGRADE "Uppgradera firmware" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konsol" #define D_CONFIRM_RESTART "Bekräfta omstart" diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index caddd0fde..25fdddaa0 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Konfigürasyon" #define D_INFORMATION "Bilgi" #define D_FIRMWARE_UPGRADE "Cihaz yazılımını Güncelle" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konsol" #define D_CONFIRM_RESTART "Yeniden Başlatmayı Onayla" diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index 95e6fd6be..42aa19f92 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Конфігурація" #define D_INFORMATION "Інформація" #define D_FIRMWARE_UPGRADE "Оновлення прошивки" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Консоль" #define D_CONFIRM_RESTART "Підтвердити перезавантаження" diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h index a2eae6e99..175178106 100644 --- a/tasmota/language/vi_VN.h +++ b/tasmota/language/vi_VN.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "Cấu hình" #define D_INFORMATION "Thông tin" #define D_FIRMWARE_UPGRADE "Nâng cấp Firmware" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Dòng Lệnh" #define D_CONFIRM_RESTART "Xác nhận khởi động lại" diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index f9ed358f4..46be35384 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -274,7 +274,7 @@ #define D_CONFIGURATION "設定" #define D_INFORMATION "資訊" #define D_FIRMWARE_UPGRADE "韌體升級" -#define D_MANAGEMENT "Consoles" +#define D_MANAGEMENT "Tools" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "控制台" #define D_CONFIRM_RESTART "確認重新啟動" diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index f45e5ae3d..d758de982 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -26,7 +26,7 @@ const char HTTP_GV_PAGE[] PROGMEM = "" "" "" - "Tasmota GPIO State" + "%s - GPIO State" "" "" "" @@ -231,6 +231,7 @@ void GVHandleEvents(void) { void GVHandleRoot(void) { char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, + SettingsTextEscaped(SET_DEVICENAME).c_str(), WiFi.localIP().toString().c_str(), WiFi.localIP().toString().c_str(), ESP_getFreeSketchSpace() / 1024); From aa1dd392caf6ec2fd394d4316f5b895b89942484 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Mon, 8 Jan 2024 09:30:18 +0100 Subject: [PATCH 096/303] Add Button to dynamically load GPIO Viewer with Berry backend (#20424) --- CHANGELOG.md | 1 + tasmota/my_user_config.h | 2 + .../xdrv_52_0_berry_struct.ino | 40 ++++++++++++ .../tasmota_xdrv_driver/xdrv_52_9_berry.ino | 65 +++++++++++-------- 4 files changed, 82 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17715e6b3..60f716537 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ All notable changes to this project will be documented in this file. - HASPmota `haspmota.page_show()` to change page (#20333) - Berry `introspect.set()` for class attributes (#20339) - Support negative power on BL0942 using index 5..8 (#20322) +- Button to dynamically load GPIO Viewer with Berry backend ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds (#20236) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 22a7fb877..b206af6e1 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -1146,6 +1146,8 @@ #define USE_BERRY_WEBCLIENT_TIMEOUT 2000 // Default timeout in milliseconds //#define USE_BERRY_PARTITION_WIZARD // Add a button to dynamically load the Partion Wizard from a bec file online (+1.3KB Flash) #define USE_BERRY_PARTITION_WIZARD_URL "http://ota.tasmota.com/tapp/partition_wizard.bec" + //#define USE_BERRY_GPIOVIEWER // Add a button to dynamocally load the GPIO Viewer from a bec file online + #define USE_BERRY_GPIOVIEWER_URL "http://ota.tasmota.com/tapp/gpioviewer.bec" #define USE_BERRY_TCPSERVER // Enable TCP socket server (+0.6k) // #define USE_BERRY_ULP // Enable ULP (Ultra Low Power) support (+4.9k) // Berry crypto extensions below: diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_0_berry_struct.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_0_berry_struct.ino index 04dfede34..86098f79f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_0_berry_struct.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_0_berry_struct.ino @@ -96,6 +96,9 @@ public: #ifdef USE_BERRY_PARTITION_WIZARD bool partition_wizard_loaded = false; // did we already load Parition_Wizard #endif // USE_BERRY_PARTITION_WIZARD +#ifdef USE_BERRY_GPIOVIEWER + bool gpviewer_loaded = false; // did we already load GPIOViewer +#endif // USE_BERRY_GPIOVIEWER bool autoexec_done = false; // do we still need to load 'autoexec.be' bool repl_active = false; // is REPL running (activates log recording) // output log is stored as a LinkedList of buffers @@ -107,4 +110,41 @@ BerrySupport berry; // multi-purpose serial logging extern "C" void serial_debug(const char * berry_buf, ...); + +/*********************************************************************************************\ + * Handle dynamic code from Berry bec files + * +\*********************************************************************************************/ +struct BeBECCode_t { + const char * display_name; // display name in Web UI (must be URL encoded) + const char * id; // id in requested URL, also don't load if the global name already exists in Berry + const char * url; // absolute URL to download the bec file + const char * redirect; // relative URI to redirect after loading + bool * loaded; +}; + +const BeBECCode_t BECCode[] = { +#ifdef USE_BERRY_PARTITION_WIZARD + { + "Partition Wizard", + "partition_wizard", + USE_BERRY_PARTITION_WIZARD_URL, + "/part_wiz", + &berry.partition_wizard_loaded + }, +#endif // USE_BERRY_PARTITION_WIZARD + +#ifdef USE_BERRY_GPIOVIEWER + { + "GPIO Viewer", + "gpioviewer", + USE_BERRY_GPIOVIEWER_URL, + "/mn?", + &berry.gpviewer_loaded + }, +#endif // USE_BERRY_GPIOVIEWER + +}; + + #endif // USE_BERRY diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino index a514baeac..a9db89010 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino @@ -764,33 +764,50 @@ void HandleBerryConsole(void) WSContentStop(); } -#ifdef USE_BERRY_PARTITION_WIZARD -// Display a Button to dynamically load the Partition Wizard -void HandleBerryPartiionWizardLoaderButton(void) { + +// const BeBECCode_t BECCode[] = { +// struct BeBECCode_t { +// const char * display_name; // display name in Web UI (must be URL encoded) +// const char * id; // id in requested URL +// const char * url; // absolute URL to download the bec file +// const char * redirect; // relative URI to redirect after loading +// }; + +// Display Buttons to dynamically load bec files +void HandleBerryBECLoaderButton(void) { bvm * vm = berry.vm; - static const char PARTITION_WIZARD_NAME[] = "partition_wizard"; - if (!berry.partition_wizard_loaded) { - if (be_global_find(vm, be_newstr(vm, PARTITION_WIZARD_NAME)) < 0) { // the global name `partition_wizard` doesn't exist - WSContentSend_P("

"); - } else { - berry.partition_wizard_loaded = true; + + for (int32_t i = 0; i < ARRAY_SIZE(BECCode); i++) { + const BeBECCode_t &bec = BECCode[i]; + if (!(*bec.loaded)) { + if (be_global_find(vm, be_newstr(vm, bec.id)) < 0) { // the global name doesn't exist + WSContentSend_P("

", bec.id, bec.display_name); + } else { + *bec.loaded = true; + } } } } extern "C" bbool BerryBECLoader(const char * url); -void HandleBerryPartitionWizardLoader(void) { - if (BerryBECLoader(USE_BERRY_PARTITION_WIZARD_URL)) { - // All good, redirect - Webserver->sendHeader("Location", "/part_wiz", true); - Webserver->send(302, "text/plain", ""); - berry.partition_wizard_loaded = true; - } else { - Webserver->sendHeader("Location", "/mn?", true); - Webserver->send(302, "text/plain", ""); + +void HandleBerryBECLoader(void) { + String n = Webserver->arg("n"); + for (int32_t i = 0; i < ARRAY_SIZE(BECCode); i++) { + const BeBECCode_t &bec = BECCode[i]; + if (n.equals(bec.id)) { + if (BerryBECLoader(bec.url)) { + // All good, redirect + Webserver->sendHeader("Location", bec.redirect, true); + Webserver->send(302, "text/plain", ""); + *bec.loaded = true; + } else { + Webserver->sendHeader("Location", "/mn?", true); + Webserver->send(302, "text/plain", ""); + } + } } } -#endif //USE_BERRY_PARTITION_WIZARD // return true if successful extern "C" bbool BerryBECLoader(const char * url) { @@ -925,9 +942,7 @@ bool Xdrv52(uint32_t function) XdrvMailbox.index++; } else { WSContentSend_P(HTTP_BTN_BERRY_CONSOLE); -#ifdef USE_BERRY_PARTITION_WIZARD - HandleBerryPartiionWizardLoaderButton(); -#endif // USE_BERRY_PARTITION_WIZARD + HandleBerryBECLoaderButton(); // display buttons to load BEC files callBerryEventDispatcher(PSTR("web_add_button"), nullptr, 0, nullptr); callBerryEventDispatcher(PSTR("web_add_console_button"), nullptr, 0, nullptr); } @@ -946,10 +961,8 @@ bool Xdrv52(uint32_t function) callBerryEventDispatcher(PSTR("web_add_handler"), nullptr, 0, nullptr); berry.web_add_handler_done = true; } - WebServer_on(PSTR("/bc"), HandleBerryConsole); -#ifdef USE_BERRY_PARTITION_WIZARD - Webserver->on("/tapp", HTTP_GET, HandleBerryPartitionWizardLoader); -#endif // USE_BERRY_PARTITION_WIZARD + WebServer_on("/bc", HandleBerryConsole); + WebServer_on("/tapp", HandleBerryBECLoader, HTTP_GET); break; #endif // USE_WEBSERVER case FUNC_SAVE_BEFORE_RESTART: From ebe840eba5d4fc208a6f2fbe01cabfc901d5e7e4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 8 Jan 2024 09:40:10 +0100 Subject: [PATCH 097/303] Update changelogs --- CHANGELOG.md | 3 ++- RELEASENOTES.md | 2 ++ tasmota/my_user_config.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60f716537..e0221235e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,10 +14,12 @@ All notable changes to this project will be documented in this file. - Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` (#20414) - Berry GPIO viewer initial version using async webserver (#20416) - Berry add `string` to `bytes()` (#20420) +- Berry button to dynamically load GPIO Viewer with Berry backend (#20424) ### Breaking Changed ### Changed +- Renamed button "Consoles" to "Tools" ### Fixed @@ -35,7 +37,6 @@ All notable changes to this project will be documented in this file. - HASPmota `haspmota.page_show()` to change page (#20333) - Berry `introspect.set()` for class attributes (#20339) - Support negative power on BL0942 using index 5..8 (#20322) -- Button to dynamically load GPIO Viewer with Berry backend ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds (#20236) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 8d26e47ce..12b0c9df2 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -133,6 +133,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Berry `gpio.read_pwm` and `gpio.read_pwm_resolution` [#20414](https://github.com/arendst/Tasmota/issues/20414) - Berry `gpio.get_pin_type` and `gpio.ger_pin_type_index` [#20415](https://github.com/arendst/Tasmota/issues/20415) - Berry `string` to `bytes()` [#20420](https://github.com/arendst/Tasmota/issues/20420) +- Berry button to dynamically load GPIO Viewer with Berry backend [#20424](https://github.com/arendst/Tasmota/issues/20424) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) - HASPmota type `chart` [#20372](https://github.com/arendst/Tasmota/issues/20372) - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) @@ -141,6 +142,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Refactoring of Berry `animate` module for WS2812 Leds [#20236](https://github.com/arendst/Tasmota/issues/20236) ### Changed +- Renamed button "Consoles" to "Tools" - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` [#20260](https://github.com/arendst/Tasmota/issues/20260) ### Fixed diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index b206af6e1..c3baf0b45 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -470,6 +470,7 @@ #define USE_ENHANCED_GUI_WIFI_SCAN // Enable Wi-Fi scan output with BSSID (+0k5 code) // #define USE_WEBSEND_RESPONSE // Enable command WebSend response message (+1k code) // #define USE_WEBGETCONFIG // Enable restoring config from external webserver (+0k6) +// #define USE_GPIO_VIEWER // Enable GPIO Viewer to see realtime GPIO states (+4k code) #define USE_EMULATION_HUE // Enable Hue Bridge emulation for Alexa (+14k code, +2k mem common) #define USE_EMULATION_WEMO // Enable Belkin WeMo emulation for Alexa (+6k code, +2k mem common) // #define USE_CCLOADER // Enable CCLoader FW upgrade tool (for CC25xx devices) From 22d237744252316a4858fb5970a958edefc9a8b8 Mon Sep 17 00:00:00 2001 From: bovirus <1262554+bovirus@users.noreply.github.com> Date: Mon, 8 Jan 2024 15:34:39 +0100 Subject: [PATCH 098/303] Update Italian language (#20428) * Update Italian language * Update it_IT.h --- tasmota/language/it_IT.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index 6f2c978a2..b35a353af 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v9.4.0.1 - Last update 17.12.2023 + * Updated until v9.4.0.1 - Last update 08.01.2024 \*********************************************************************/ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -274,8 +274,8 @@ #define D_CONFIGURATION "Impostazioni" #define D_INFORMATION "Informazioni" #define D_FIRMWARE_UPGRADE "Aggiorna firmware" -#define D_MANAGEMENT "Console" -#define D_GPIO_VIEWER "GPIO Viewer" +#define D_MANAGEMENT "Strumenti" +#define D_GPIO_VIEWER "Visualizzatore GPIO" #define D_CONSOLE "Console" #define D_CONFIRM_RESTART "Conferma riavvio" @@ -1220,7 +1220,6 @@ #define D_NEOPOOL_PUMP_TIME_EXCEEDED "tempo pompa superato" // xsns_106_gdk101.ino -#define D_AVG_RAD_DOSE "Dose media radiazioni" #define D_AVG_RAD_DOSE "Radiazioni" #define D_UNIT_US_H "µSv/h" From 92214ac63301807214d56b1893ff4eb17f0a5601 Mon Sep 17 00:00:00 2001 From: gemu Date: Mon, 8 Jan 2024 16:44:49 +0100 Subject: [PATCH 099/303] ADD FTP server to filesystem (#20402) * add ftp lib * add ftp server --- lib/lib_div/ESPFtpServer/ESPFtpServer.cpp | 1132 +++++++++++++++++ lib/lib_div/ESPFtpServer/ESPFtpServer.h | 125 ++ lib/lib_div/ESPFtpServer/LICENSE | 165 +++ lib/lib_div/ESPFtpServer/README.md | 14 + .../ESPFtpServer/examples/ESPFtpServer.ino | 104 ++ lib/lib_div/ESPFtpServer/library.json | 21 + lib/lib_div/ESPFtpServer/library.properties | 12 + tasmota/include/tasmota_types.h | 3 +- .../xdrv_50_filesystem.ino | 68 +- 9 files changed, 1641 insertions(+), 3 deletions(-) create mode 100755 lib/lib_div/ESPFtpServer/ESPFtpServer.cpp create mode 100755 lib/lib_div/ESPFtpServer/ESPFtpServer.h create mode 100644 lib/lib_div/ESPFtpServer/LICENSE create mode 100644 lib/lib_div/ESPFtpServer/README.md create mode 100644 lib/lib_div/ESPFtpServer/examples/ESPFtpServer.ino create mode 100644 lib/lib_div/ESPFtpServer/library.json create mode 100644 lib/lib_div/ESPFtpServer/library.properties diff --git a/lib/lib_div/ESPFtpServer/ESPFtpServer.cpp b/lib/lib_div/ESPFtpServer/ESPFtpServer.cpp new file mode 100755 index 000000000..c70d17dcf --- /dev/null +++ b/lib/lib_div/ESPFtpServer/ESPFtpServer.cpp @@ -0,0 +1,1132 @@ +/* + * FTP SERVER FOR ESP32/ESP8266 + * based on FTP Server for Arduino Due and Ethernet shield (W5100) or WIZ820io (W5200) + * based on Jean-Michel Gallego's work + * modified to work with esp8266 SPIFFS by David Paiva david@nailbuster.com + * 2017: modified by @robo8080 (ported to ESP32 and SD) + * 2019: modified by @fa1ke5 (use SD card in SD_MMC mode (No SD lib, SD_MMC lib), and added fully fuctional passive mode ftp server) + * 2020: modified by @jmwislez (support generic FS, and re-introduced ESP8266) + * 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 . + */ + + +#include "ESPFtpServer.h" +#include + +#ifdef ESP32 +#define F(A) A +#endif + +void FtpServer::begin (String uname, String pword, FS *ufp) { + + if (is_up) return; + + cfsp = ufp; + + // Tells the ftp server to begin listening for incoming connection + _FTP_USER = uname; + _FTP_PASS = pword; + + ftpServer = new WiFiServer(FTP_CTRL_PORT); + if (!ftpServer) return; + dataServer = new WiFiServer(FTP_DATA_PORT_PASV); + if (!dataServer) return; + + ftpServer->begin (); + delay (10); + dataServer->begin (); + delay (10); + millisTimeOut = (uint32_t)FTP_TIME_OUT * 60 * 1000; + millisDelay = 0; + cmdStatus = 0; + iniVariables (); + is_up = true; +} + +FtpServer::~FtpServer(void) { + ftpServer->close(); + ftpServer->stop(); + delete ftpServer; + dataServer->close(); + dataServer->stop(); + delete dataServer; +} + + +void FtpServer::iniVariables () { + // Default for data port + dataPort = FTP_DATA_PORT_PASV; + + // Default Data connection is Active + dataPassiveConn = false; + + // Set the root directory + strcpy (cwdName, "/"); + + rnfrCmd = false; + transferStatus = 0; +} + +void FtpServer::handleFTP () { + + if (!is_up) return; + + if ((int32_t) (millisDelay - millis ()) > 0) { + return; + } + + if (ftpServer->hasClient ()) { + #ifdef FTP_DEBUG + Serial.println (F("-> disconnecting client")); + #endif + client.stop (); + client = ftpServer->available (); + } + + if (cmdStatus == 0) { + if (client.connected ()) { + disconnectClient (); + } + cmdStatus = 1; + } + else if (cmdStatus == 1) { // Ftp server waiting for connection + abortTransfer (); + iniVariables (); + #ifdef FTP_DEBUG + Serial.println (F("-> ftp server waiting for connection on port ") + String (FTP_CTRL_PORT)); + #endif + cmdStatus = 2; + } + else if (cmdStatus == 2) { // Ftp server idle + if (client.connected ()) { // A client connected + clientConnected (); + millisEndConnection = millis () + 10 * 1000; // wait client id during 10 s. + cmdStatus = 3; + } + } + else if (readChar () > 0) { // got response + if (cmdStatus == 3) { // Ftp server waiting for user identity + if (userIdentity ()) { + cmdStatus = 4; + } + else { + cmdStatus = 0; + } + } + else if (cmdStatus == 4) { // Ftp server waiting for user registration + if (userPassword ()) { + cmdStatus = 5; + millisEndConnection = millis () + millisTimeOut; + } + else { + cmdStatus = 0; + } + } + else if (cmdStatus == 5) { // Ftp server waiting for user command + if (!processCommand ()) { + cmdStatus = 0; + } + else { + millisEndConnection = millis () + millisTimeOut; + } + } + } + else if (!client.connected () || !client) { + cmdStatus = 1; + #ifdef FTP_DEBUG + Serial.println (F("-> client disconnected")); + #endif + } + + if (transferStatus == 1) { // Retrieve data + if (!doRetrieve ()) { + transferStatus = 0; + } + } + else if (transferStatus == 2) { // Store data + if (!doStore ()) { + transferStatus = 0; + } + } + else if (cmdStatus > 2 && ! ((int32_t) (millisEndConnection - millis ()) > 0 )) { + client.println (F("530 Timeout")); + millisDelay = millis () + 200; // delay of 200 ms + cmdStatus = 0; + } +} + +void FtpServer::clientConnected () { + #ifdef FTP_DEBUG + Serial.println (F("-> client connected")); + #endif + client.println (F("220-Welcome to FTP for ESP8266/ESP32")); + client.println (F("220-By David Paiva")); + client.println (F("220-Version ") + String (FTP_SERVER_VERSION)); + client.println (F("220 Put your ftp client in passive mode, and do not attempt more than one connection")); + iCL = 0; +} + +void FtpServer::disconnectClient () { + #ifdef FTP_DEBUG + Serial.println (F("-> disconnecting client")); + #endif + abortTransfer (); + client.println (F("221 Goodbye")); + client.stop (); +} + +boolean FtpServer::userIdentity () { + if (strcmp (command, "USER")) { + client.println (F("500 Syntax error")); + } + if (strcmp (parameters, _FTP_USER.c_str ())) { + client.println (F("530 user not found")); + } + else { + client.println (F("331 OK. Password required")); + strcpy (cwdName, "/"); + return true; + } + millisDelay = millis () + 100; // delay of 100 ms + return false; +} + +boolean FtpServer::userPassword () { + if (strcmp (command, "PASS")) { + client.println (F("500 Syntax error")); + } + else if (strcmp (parameters, _FTP_PASS.c_str ())) { + client.println (F("530 ")); + } + else { + #ifdef FTP_DEBUG + Serial.println (F("-> user authenticated")); + #endif + client.println (F("230 OK.")); + return true; + } + millisDelay = millis () + 100; // delay of 100 ms + return false; +} + +boolean FtpServer::processCommand () { + struct tm * ptm; + time_t ftime; + char buffer[80]; + + /////////////////////////////////////// + // // + // ACCESS CONTROL COMMANDS // + // // + /////////////////////////////////////// + + // + // CDUP - Change to Parent Directory + // + if (!strcmp (command, "CDUP") || (!strcmp (command, "CWD") && !strcmp (parameters, ".."))) { + bool ok = false; + if (strlen (cwdName) > 1) { // do nothing if cwdName is root + // if cwdName ends with '/', remove it (must not append) + if (cwdName[strlen (cwdName) - 1] == '/') { + cwdName[ strlen (cwdName ) - 1 ] = 0; + } + // search last '/' + char * pSep = strrchr (cwdName, '/'); + ok = pSep > cwdName; + // if found, ends the string on its position + if (ok) { + * pSep = 0; + ok = cfsp->exists (cwdName); + } + } + // if an error appends, move to root + if (!ok) { + strcpy (cwdName, "/"); + } + client.println (F("250 Ok. Current directory is ") + String (cwdName)); + } + + // + // CWD - Change Working Directory + // + else if (!strcmp (command, "CWD")) { + char path[FTP_CWD_SIZE]; + if (haveParameter () && makeExistsPath (path)) { + strcpy (cwdName, path); + client.println (F("250 Ok. Current directory is ") + String (cwdName)); + } + } + + // + // PWD - Print Directory + // + else if (!strcmp (command, "PWD")) { + client.println (F("257 \"") + String (cwdName) + F("\" is your current directory")); + } + + // + // QUIT + // + else if (!strcmp (command, "QUIT")) { + disconnectClient (); + return false; + } + + /////////////////////////////////////// + // // + // TRANSFER PARAMETER COMMANDS // + // // + /////////////////////////////////////// + + // + // MODE - Transfer Mode + // + else if (!strcmp (command, "MODE")) { + if (!strcmp (parameters, "S")) { + client.println (F("200 S Ok")); + } + else { + client.println (F("504 Only S (tream) is supported")); + } + } + + // + // PASV - Passive Connection management + // + else if (!strcmp (command, "PASV")) { + if (data.connected ()) { + data.stop (); + #ifdef FTP_DEBUG + Serial.println (F("-> client disconnected from dataserver")); + #endif + } + dataIp = WiFi.localIP (); + dataPort = FTP_DATA_PORT_PASV; + #ifdef FTP_DEBUG + Serial.println (F("-> connection management set to passive")); + Serial.println (F("-> data port set to ") + String (dataPort)); + #endif + client.println (F("227 Entering Passive Mode (") + String (dataIp[0]) + "," + String (dataIp[1]) + "," + String (dataIp[2]) + "," + String (dataIp[3]) + "," + String (dataPort >> 8) + "," + String (dataPort & 255) + ")."); + dataPassiveConn = true; + } + + // + // PORT - Data Port + // + else if (!strcmp (command, "PORT")) { + if (data) { + data.stop (); + #ifdef FTP_DEBUG + Serial.println (F("-> client disconnected from dataserver")); + #endif + } + // get IP of data client + dataIp[0] = atoi (parameters); + char * p = strchr (parameters, ','); + for (uint8_t i = 1; i < 4; i ++) { + dataIp[i] = atoi (++ p); + p = strchr (p, ','); + } + // get port of data client + dataPort = 256 * atoi (++ p); + p = strchr (p, ','); + dataPort += atoi (++ p); + if (p == NULL) { + client.println (F("501 Can't interpret parameters")); + } + else { + client.println (F("200 PORT command successful")); + dataPassiveConn = false; + } + } + + // + // STRU - File Structure + // + else if (!strcmp (command, "STRU")) { + if (!strcmp (parameters, "F")) { + client.println (F("200 F Ok")); + } + else { + client.println (F("504 Only F (ile) is supported")); + } + } + + // + // TYPE - Data Type + // + else if (!strcmp (command, "TYPE")) { + if (!strcmp (parameters, "A")) { + client.println (F("200 TYPE is now ASCII")); + } + else if (!strcmp (parameters, "I" )) { + client.println (F("200 TYPE is now 8-bit binary")); + } + else { + client.println (F("504 Unknown TYPE")); + } + } + + /////////////////////////////////////// + // // + // FTP SERVICE COMMANDS // + // // + /////////////////////////////////////// + + // + // ABOR - Abort + // + else if (!strcmp (command, "ABOR")) { + abortTransfer (); + client.println (F("226 Data connection closed")); + } + + // + // DELE - Delete a File + // + else if (!strcmp (command, "DELE")) { + char path[FTP_CWD_SIZE]; + if (strlen (parameters) == 0) { + client.println (F("501 No file name")); + } + else if (makePath (path)) { + if (!cfsp->exists (path)) { + client.println (F("550 File ") + String (parameters) + F(" not found")); + } + else { + if (cfsp->remove (path)) { + client.println (F("250 Deleted ") + String (parameters)); + // silently recreate the directory if it vanished with the last file it contained + String directory = String (path).substring (0, String(path).lastIndexOf ("/")); + if (!cfsp->exists (directory.c_str())) { + cfsp->mkdir (directory.c_str()); + } + } + else { + client.println (F("450 Can't delete ") + String (parameters)); + } + } + } + } + + // + // LIST - List + // + else if (!strcmp (command, "LIST")) { + if (dataConnect ()) { + client.println (F("150 Accepted data connection")); + uint16_t nm = 0; + + #ifdef ESP8266 + Dir dir = cfsp->openDir (cwdName); + while (dir.next ()) { + String fname, fsize; + fname = dir.fileName (); + time_t ftime = dir.fileTime (); + ptm = gmtime (&ftime); + int pos = fname.lastIndexOf ("/"); //looking for the beginning of the file by the last "/" + fname.remove (0, pos + 1); //Delete everything up to and including the filename + fsize = String (dir.fileSize ()); + if (dir.isDirectory ()){ + sprintf (buffer, "%04d-%02d-%02d %02d:%02d %s", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, fname.c_str()); + } + else { + sprintf (buffer, "%04d-%02d-%02d %02d:%02d %s %s", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, fillSpaces (14, String (fsize)).c_str(), fname.c_str()); + } + data.println (buffer); + nm ++; + } + client.println( "226 " + String (nm) + " matches total"); + #endif + #ifdef ESP32 + File dir = cfsp->open (cwdName); + if ((!dir) || (!dir.isDirectory ())) { + client.println (F("550 Can't open directory ") + String (cwdName)); + } + else { + File file = dir.openNextFile (); + while (file) { + String fname, fsize; + fname = file.name (); + ftime = file.getLastWrite (); + ptm = gmtime (&ftime); + int pos = fname.lastIndexOf ("/"); //looking for the beginning of the file by the last "/" + fname.remove (0, pos + 1); //Delete everything up to and including the filename + #ifdef FTP_DEBUG + Serial.println ("-> " + fname); + #endif + fsize = String (file.size ()); + if (file.isDirectory ()){ + sprintf (buffer, "%04u-%02u-%02u %02u:%02u %s", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, fname.c_str()); + } + else { + sprintf (buffer, "%04u-%02u-%02u %02d:%02u %s %s", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, fillSpaces (14, String (fsize)).c_str(), fname.c_str()); + } + data.println (buffer); + nm ++; + file = dir.openNextFile (); + } + client.println ("226 " + String (nm) + F(" matches total")); + } + #endif + data.stop (); + #ifdef FTP_DEBUG + Serial.println (F("-> client disconnected from dataserver")); + #endif + } + else { + client.println (F("425 No data connection")); + data.stop (); + } + } + + // + // MLSD - Listing for Machine Processing (see RFC 3659) + // + else if (!strcmp (command, "MLSD")) { + if (!dataConnect ()) { + client.println (F("425 No data connection MLSD")); + } + else { + client.println (F("150 Accepted data connection")); + uint16_t nm = 0; + #ifdef ESP8266 + Dir dir = cfsp->openDir (cwdName); + char dtStr[15]; + while (dir.next ()) { + String fn, fs; + fn = dir.fileName (); + int pos = fn.lastIndexOf ("/"); //looking for the beginning of the file by the last "/" + fn.remove (0, pos + 1); //Delete everything up to and including the filename + fs = String (dir.fileSize ()); + ftime = dir.fileTime (); + ptm = gmtime (&ftime); + if (dir.isDirectory ()) { + sprintf (buffer, "Type=dir;Modify=%04u%02u%02u%02u%02u%02u; %s", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, fn.c_str()); + } + else { + sprintf (buffer, "Type=file;Size=%s;Modify=%04u%02u%02u%02u%02u%02u; %s", fs.c_str(), ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, fn.c_str()); + } + data.println (buffer); + nm ++; + } + client.println (F("226-options: -a -l")); + client.println("226 " + String(nm) + F(" matches total")); + #endif + #ifdef ESP32 + File dir = cfsp->open (cwdName); + char dtStr[15]; + if (!cfsp->exists (cwdName)) { + client.println (F("550 Can't open directory ") + String (parameters)); + } + else { + File file = dir.openNextFile (); + while (file) { + String fn, fs; + fn = file.name (); + int pos = fn.lastIndexOf ("/"); // looking for the beginning of the file by the last "/" + fn.remove (0, pos + 1); // delete everything up to and including the filename + fs = String (file.size ()); + ftime = file.getLastWrite (); + ptm = gmtime (&ftime); + if (file.isDirectory ()) { + sprintf (buffer, "Type=dir;Modify=%04u%02u%02u%02u%02u%02u; %s", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, fn.c_str()); + } + else { + sprintf (buffer, "Type=file;Size=%s;Modify=%04u%02u%02u%02u%02u%02u; %s", fs.c_str(), ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, fn.c_str()); + } + data.println (buffer); + nm ++; + file = dir.openNextFile (); + } + client.println (F("226-options: -a -l")); + client.println ("226 " + String (nm) + F(" matches total")); + } + #endif + data.stop (); + #ifdef FTP_DEBUG + Serial.println (F("-> client disconnected from dataserver")); + #endif + } + } + + // + // NLST - Name List + // + else if (!strcmp (command, "NLST" )) { + if (!dataConnect ()) { + client.println (F("425 No data connection")); + } + else { + client.println (F("150 Accepted data connection")); + uint16_t nm = 0; + #ifdef ESP8266 + Dir dir = cfsp->openDir (cwdName); + if (!cfsp->exists (cwdName)) { + client.println (F("550 Can't open directory ") + String (parameters)); + } + else { + while (dir.next ()) { + data.println (dir.fileName ()); + nm ++; + } + client.println ("226 " + String(nm) + F(" matches total")); + } + #endif + #ifdef ESP32 + File dir = cfsp->open (cwdName); + if (!cfsp->exists (cwdName)) { + client.println (F("550 Can't open directory ") + String (parameters)); + } + else { + File file = dir.openNextFile (); + while (file) { + data.println (file.name ()); + nm ++; + file = dir.openNextFile (); + } + client.println ("226 " + String (nm) + F(" matches total")); + } + #endif + data.stop (); + #ifdef FTP_DEBUG + Serial.println (F("-> client disconnected from dataserver")); + #endif + } + } + + // + // NOOP + // + else if (!strcmp (command, "NOOP")) { + client.println (F("200 Zzz...")); + } + + // + // RETR - Retrieve + // + else if (!strcmp (command, "RETR")) { + char path[FTP_CWD_SIZE]; + if (strlen (parameters) == 0) { + client.println (F("501 No file name")); + } + else if (makePath (path)) { + file = cfsp->open (path, "r"); + if (!file) { + client.println (F("550 File ") + String (parameters) + F(" not found")); + } + else if (!file) { + client.println (F("450 Can't open ") + String (parameters)); + } + else if (!dataConnect ()) { + client.println (F("425 No data connection")); + } + else { + #ifdef FTP_DEBUG + Serial.println (F("-> sending ") + String (parameters)); + #endif + client.println (F("150-Connected to port ") + String (dataPort)); + client.println (F("150 ") + String (file.size ()) + F(" bytes to download")); + millisBeginTrans = millis (); + bytesTransferred = 0; + transferStatus = 1; + } + } + } + + // + // STOR - Store + // + else if (!strcmp (command, "STOR")) { + char path[FTP_CWD_SIZE]; + if (strlen (parameters) == 0) { + client.println (F("501 No file name")); + } + else if (makePath (path)) { + file = cfsp->open (path, "w"); + if (!file) { + client.println (F("451 Can't open/create ") + String (parameters)); + } + else if (!dataConnect ()) { + client.println (F("425 No data connection")); + file.close (); + } + else { + #ifdef FTP_DEBUG + Serial.println (F("-> receiving ") + String (parameters)); + #endif + client.println (F("150 Connected to port ") + String (dataPort)); + millisBeginTrans = millis (); + bytesTransferred = 0; + transferStatus = 2; + } + } + } + + // + // MKD - Make Directory + // + + else if (!strcmp (command, "MKD")) { + char path[FTP_CWD_SIZE]; + if (haveParameter () && makePath (path)) { + if (cfsp->exists (path)) { + client.println (F("521 Can't create \"") + String (parameters) + F("\", Directory exists")); + } + else { + if (cfsp->mkdir (path)) { + client.println (F("257 \"") + String (parameters) + F("\" created")); + } + else { + client.println (F("550 Can't create \"") + String (parameters) + "\""); + } + } + } + } + + // + // RMD - Remove a Directory + // + else if (!strcmp (command, "RMD")) { + char path[FTP_CWD_SIZE]; + if (haveParameter () && makePath (path)) { + if (cfsp->rmdir (path)) { + #ifdef FTP_DEBUG + Serial.println (F("-> deleting ") + String (parameters)); + #endif + client.println ("250 \"" + String (parameters) + F("\" deleted")); + } + else { + if (cfsp->exists (path)) { // hack + client.println (F("550 Can't remove \"") + String (parameters) + F("\". Directory not empty?")); + } + else { + #ifdef FTP_DEBUG + Serial.println (F("-> deleting ") + String (parameters)); + #endif + client.println ("250 \"" + String (parameters) + F("\" deleted")); + } + } + } + } + + // + // RNFR - Rename From + // + else if (!strcmp (command, "RNFR")) { + buf[0] = 0; + if (strlen (parameters) == 0) { + client.println (F("501 No file name")); + } + else if (makePath (buf)) { + if (!cfsp->exists (buf)) { + client.println (F("550 File ") + String (parameters) + F(" not found")); + } + else { + #ifdef FTP_DEBUG + Serial.println (F("-> renaming ") + String (buf)); + #endif + client.println (F("350 RNFR accepted - file exists, ready for destination")); + rnfrCmd = true; + } + } + } + + // + // RNTO - Rename To + // + else if (!strcmp (command, "RNTO")) { + char path[FTP_CWD_SIZE]; + char dir[FTP_FIL_SIZE]; + if (strlen (buf ) == 0 || ! rnfrCmd) { + client.println (F("503 Need RNFR before RNTO")); + } + else if (strlen (parameters ) == 0) { + client.println (F("501 No file name")); + } + else if (makePath (path)) { + if (cfsp->exists (path)) { + client.println (F("553 ") + String (parameters) + F(" already exists")); + } + else { + #ifdef FTP_DEBUG + Serial.println (F("-> renaming ") + String (buf) + " to " + String (path)); + #endif + if (cfsp->rename (buf, path)) { + client.println (F("250 File successfully renamed or moved")); + } + else { + client.println (F("451 Rename/move failure")); + } + } + } + rnfrCmd = false; + } + + /////////////////////////////////////// + // // + // EXTENSIONS COMMANDS (RFC 3659) // + // // + /////////////////////////////////////// + + // + // FEAT - New Features + // + else if (!strcmp (command, "FEAT")) { + client.println (F("211-Extensions supported:")); + client.println (F(" MLSD")); + client.println (F("211 End.")); + } + + // + // MDTM - File Modification Time (see RFC 3659) + // + else if (!strcmp (command, "MDTM")) { + client.println (F("550 Unable to retrieve time")); + } + + // + // SIZE - Size of the file + // + else if (!strcmp (command, "SIZE")) { + char path[FTP_CWD_SIZE]; + if (strlen (parameters) == 0) { + client.println (F("501 No file name")); + } + else if (makePath (path)) { + file = cfsp->open (path, "r"); + if (!file) { + client.println (F("450 Can't open ") + String (parameters)); + } + else { + client.println (F("213 ") + String (file.size ())); + file.close (); + } + } + } + + // + // SITE - System command + // + else if (!strcmp (command, "SITE")) { + client.println (F("500 Unknown SITE command ") + String (parameters)); + } + + // + // Unrecognized commands ... + // + else { + client.println (F("500 Unknown command")); + } + return true; +} + +boolean FtpServer::dataConnect () { + unsigned long startTime = millis (); + //wait 5 seconds for a data connection + if (!data.connected ()) { + while (!dataServer->hasClient () && millis () - startTime < 10000) { + yield (); + } + if (dataServer->hasClient ()) { + data.stop (); + #ifdef FTP_DEBUG + Serial.println (F("-> client disconnected from dataserver")); + #endif + data = dataServer->available (); + #ifdef FTP_DEBUG + Serial.println (F("-> client connected to dataserver")); + #endif + } + } + return data.connected (); +} + +boolean FtpServer::doRetrieve () { + if (data.connected ()) { + int16_t nb = file.readBytes (buf, FTP_BUF_SIZE); + if (nb > 0) { + data.write ((uint8_t*)buf, nb); + bytesTransferred += nb; + return true; + } + } + closeTransfer (); + return false; +} + +boolean FtpServer::doStore () { + // Avoid blocking by never reading more bytes than are available + int navail = data.available(); + if (navail > 0) { + // And be sure not to overflow the buffer + if (navail > FTP_BUF_SIZE) { + navail = FTP_BUF_SIZE; + } + int16_t nb = data.read((uint8_t *)buf, navail); + if (nb > 0) { + file.write((uint8_t *)buf, nb); + bytesTransferred += nb; + } + } + if (!data.connected() && (navail <= 0)) { + closeTransfer(); + return false; + } + else { + return true; + } +} + +void FtpServer::closeTransfer () { + uint32_t deltaT = (int32_t) (millis () - millisBeginTrans); + if (deltaT > 0 && bytesTransferred > 0) { + client.println (F("226-File successfully transferred")); + client.println ("226 " + String (deltaT) + " ms, " + String (bytesTransferred / deltaT) + " kbytes/s"); + } + else { + client.println (F("226 File successfully transferred")); + } + file.close (); + data.stop (); + #ifdef FTP_DEBUG + Serial.println (F("-> file successfully transferred")); + Serial.println (F("-> client disconnected from dataserver")); + #endif +} + +void FtpServer::abortTransfer () { + if (transferStatus > 0) { + file.close (); + data.stop (); + #ifdef FTP_DEBUG + Serial.println (F("-> client disconnected from dataserver")); + #endif + client.println (F("426 Transfer aborted")); + #ifdef FTP_DEBUG + Serial.println (F("-> transfer aborted")); + #endif + } + transferStatus = 0; +} + +// Read a char from client connected to ftp server +// +// update cmdLine and command buffers, iCL and parameters pointers +// +// return: +// -2 if buffer cmdLine is full +// -1 if line not completed +// 0 if empty line received +// length of cmdLine (positive) if no empty line received + +int8_t FtpServer::readChar () { + int8_t rc = -1; + + if (client.available ()) { + char c = client.read (); + #ifdef FTP_DEBUG + Serial.print (c); + #endif + if (c == '\\') { + c = '/'; + } + if (c != '\r' ) { + if (c != '\n' ) { + if (iCL < FTP_CMD_SIZE) { + cmdLine[iCL ++] = c; + } + else { + rc = -2; // Line too long + } + } + else { + cmdLine[iCL] = 0; + command[0] = 0; + parameters = NULL; + // empty line? + if (iCL == 0) { + rc = 0; + } + else { + rc = iCL; + // search for space between command and parameters + parameters = strchr (cmdLine, ' '); + if (parameters != NULL) { + if (parameters - cmdLine > 4) { + rc = -2; // Syntax error + } + else { + strncpy (command, cmdLine, parameters - cmdLine); + command[parameters - cmdLine] = 0; + + while (* (++ parameters) == ' ') { + ; + } + } + } + else if (strlen (cmdLine) > 4) { + rc = -2; // Syntax error. + } + else { + strcpy (command, cmdLine); + } + iCL = 0; + } + } + } + if (rc > 0) { + for (uint8_t i = 0; i < strlen (command); i ++) { + command[i] = toupper (command[i]); + } + } + if (rc == -2) { + iCL = 0; + client.println (F("500 Syntax error")); + } + } + return rc; +} + +// Make complete path/name from cwdName and parameters +// +// 3 possible cases: parameters can be absolute path, relative path or only the name +// +// parameters: +// fullName : where to store the path/name +// +// return: +// true, if done + +boolean FtpServer::makePath (char * fullName) { + return makePath (fullName, parameters); +} + +boolean FtpServer::makePath (char * fullName, char * param) { + if (param == NULL) { + param = parameters; + } + // Root or empty? + if (strcmp (param, "/") == 0 || strlen (param) == 0) { + strcpy (fullName, "/"); + return true; + } + // If relative path, concatenate with current dir + if (param[0] != '/' ) { + strcpy (fullName, cwdName); + if (fullName[strlen (fullName) - 1] != '/') { + strncat (fullName, "/", FTP_CWD_SIZE); + } + strncat (fullName, param, FTP_CWD_SIZE); + } + else { + strcpy (fullName, param); + } + // If ends with '/', remove it + uint16_t strl = strlen (fullName) - 1; + if (fullName[strl] == '/' && strl > 1) { + fullName[strl] = 0; + } + if (strlen (fullName) < FTP_CWD_SIZE) { + return true; + } + client.println (F("500 Command line too long")); + return false; +} + +// Calculate year, month, day, hour, minute and second +// from first parameter sent by MDTM command (YYYYMMDDHHMMSS) +// +// parameters: +// pyear, pmonth, pday, phour, pminute and psecond: pointer of +// variables where to store data +// +// return: +// 0 if parameter is not YYYYMMDDHHMMSS +// length of parameter + space + +uint8_t FtpServer::getDateTime (uint16_t * pyear, uint8_t * pmonth, uint8_t * pday, + uint8_t * phour, uint8_t * pminute, uint8_t * psecond) { + char dt[15]; + + // Date/time are expressed as a 14 digits long string + // terminated by a space and followed by name of file + if (strlen (parameters ) < 15 || parameters[14] != ' ') { + return 0; + } + for (uint8_t i = 0; i < 14; i ++) { + if (!isdigit (parameters[i])) { + return 0; + } + } + strncpy (dt, parameters, 14); + dt[14] = 0; + * psecond = atoi (dt + 12); + dt[12] = 0; + * pminute = atoi (dt + 10); + dt[10] = 0; + * phour = atoi (dt + 8); + dt[8] = 0; + * pday = atoi (dt + 6); + dt[6] = 0; + * pmonth = atoi (dt + 4); + dt[4] = 0; + * pyear = atoi (dt); + return 15; +} + +// Create string YYYYMMDDHHMMSS from date and time +// +// parameters: +// date, time +// tstr: where to store the string. Must be at least 15 characters long +// +// return: +// pointer to tstr + +char * FtpServer::makeDateTimeStr (char * tstr, uint16_t date, uint16_t time) { + sprintf (tstr, "%04u%02u%02u%02u%02u%02u", + ((date & 0xFE00) >> 9) + 1980, (date & 0x01E0) >> 5, date & 0x001F, + (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) << 1); + return tstr; +} + +bool FtpServer::haveParameter () { + if (parameters != NULL && strlen (parameters) > 0) { + return true; + } + client.println (F("501 No file name")); + return false; +} + +bool FtpServer::makeExistsPath (char * path, char * param) { + if (!makePath (path, param)) { + return false; + } + if (cfsp->exists (path)) { + return true; + } + client.println (F("550 ") + String (path) + F(" not found.")); + return false; +} + +String FtpServer::fillSpaces (uint8_t length, String input) { + String output; + output = ""; + while (output.length() < length - input.length()) { + output += " "; + } + output += input; + return (output); +} diff --git a/lib/lib_div/ESPFtpServer/ESPFtpServer.h b/lib/lib_div/ESPFtpServer/ESPFtpServer.h new file mode 100755 index 000000000..84f380658 --- /dev/null +++ b/lib/lib_div/ESPFtpServer/ESPFtpServer.h @@ -0,0 +1,125 @@ +/* +* FTP SERVER FOR ESP8266/ESP32 + * based on FTP Server for Arduino Due and Ethernet shield (W5100) or WIZ820io (W5200) + * based on Jean-Michel Gallego's work + * modified to work with esp8266 SPIFFS by David Paiva (david@nailbuster.com) + * 2017: modified by @robo8080 (ported to ESP32 and SD) + * 2019: modified by @fa1ke5 (use SD card in SD_MMC mode (No SD lib, SD_MMC lib), and added fully fuctional passive mode ftp server) + * 2020: modified by @jmwislez (support generic FS, and re-introduced ESP8266) + * 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 . + */ + + +/******************************************************************************* + ** ** + ** DEFINITIONS FOR FTP SERVER ** + ** ** + *******************************************************************************/ + +// Uncomment to print debugging info to console +//#define FTP_DEBUG + +#ifndef FTP_SERVERESP_H +#define FTP_SERVERESP_H + +#include +#include +#ifdef ESP32 + #include +#else + #include +#endif + +#define FTP_SERVER_VERSION "jmwislez/ESP32FtpServer 0.1.0" + +#define FTP_CTRL_PORT 21 // Command port on wich server is listening +#define FTP_DATA_PORT_PASV 50009 // Data port in passive mode + +#define FTP_TIME_OUT 5 // Disconnect client after 5 minutes of inactivity + +#ifdef ESP32 +#define FTP_CMD_SIZE 255 + 8 // max size of a command +#define FTP_CWD_SIZE 255 + 8 // max size of a directory name +#define FTP_FIL_SIZE 255 // max size of a file name +#define FTP_BUF_SIZE 4096 //512 // 700 KByte/s download in AP mode, direct connection. +#endif + +#ifdef ESP8266 +#define FTP_CMD_SIZE 128 // max size of a command +#define FTP_CWD_SIZE 128 // max size of a directory name +#define FTP_FIL_SIZE 64 // max size of a file name +#define FTP_BUF_SIZE 256 // 700 KByte/s download in AP mode, direct connection. +#endif + +class FtpServer { + public: + void begin(String uname, String pword, FS *ufp); + void handleFTP (void); + ~FtpServer(void); + bool is_up = false; + + private: + bool haveParameter (); + bool makeExistsPath (char * path, char * param = NULL); + void iniVariables (); + void clientConnected (); + void disconnectClient (); + boolean userIdentity (); + boolean userPassword (); + boolean processCommand (); + boolean dataConnect (); + boolean doRetrieve (); + boolean doStore (); + void closeTransfer (); + void abortTransfer (); + boolean makePath (char * fullname); + boolean makePath (char * fullName, char * param); + uint8_t getDateTime (uint16_t * pyear, uint8_t * pmonth, uint8_t * pday, + uint8_t * phour, uint8_t * pminute, uint8_t * second); + char * makeDateTimeStr (char * tstr, uint16_t date, uint16_t time); + int8_t readChar (); + String fillSpaces (uint8_t len, String input_str); + + IPAddress dataIp; // IP address of client for data + WiFiClient client; + WiFiClient data; + + WiFiServer *ftpServer; + WiFiServer *dataServer; + + FS *cfsp; + + File file; + + boolean dataPassiveConn; + uint16_t dataPort; + char buf[FTP_BUF_SIZE]; // data buffer for transfers + char cmdLine[FTP_CMD_SIZE]; // where to store incoming char from client + char cwdName[FTP_CWD_SIZE]; // name of current directory + char command[5]; // command sent by client + boolean rnfrCmd; // previous command was RNFR + char * parameters; // point to begin of parameters sent by client + uint16_t iCL; // pointer to cmdLine next incoming char + int8_t cmdStatus, // status of ftp command connexion + transferStatus; // status of ftp data transfer + uint32_t millisTimeOut, // disconnect after 5 min of inactivity + millisDelay, + millisEndConnection, // + millisBeginTrans, // store time of beginning of a transaction + bytesTransferred; // + String _FTP_USER; + String _FTP_PASS; +}; + +#endif // FTP_SERVERESP_H diff --git a/lib/lib_div/ESPFtpServer/LICENSE b/lib/lib_div/ESPFtpServer/LICENSE new file mode 100644 index 000000000..65c5ca88a --- /dev/null +++ b/lib/lib_div/ESPFtpServer/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/lib/lib_div/ESPFtpServer/README.md b/lib/lib_div/ESPFtpServer/README.md new file mode 100644 index 000000000..8976e20d2 --- /dev/null +++ b/lib/lib_div/ESPFtpServer/README.md @@ -0,0 +1,14 @@ +# ESPFtpServer + +The history of this code is as follows: + +* https://github.com/gallegojm/Arduino-Ftp-Server/tree/master/FtpServer: FTP server for Arduino Mega2560 and Due with ethernet module W5100, W5200 or W5500 +* https://github.com/nailbuster/esp8266FTPServer: ported to ESP8266 and SPIFFS file system +* https://github.com/robo8080/ESP32_FTPServer_SD: ported to ESP32 and SD card file system +* https://github.com/fa1ke5/ESP32_FTPServer_SD_MMC: use SD card in SD_MMC mode (No SD lib, SD_MMC lib). Added fully fuctional passive mode ftp server, browse dir, change dir, rename dir/file, delete dir/file, upload and download files, dirs. + +The current repository is forked from fa1ke5, and has the following changes: +* use of any file system file system (like SPIFFS/LittleFS/SD_MMC) +* codebase to work for both ESP8266 and ESP32 +* clean-up of code layout and English +* addition of library description files diff --git a/lib/lib_div/ESPFtpServer/examples/ESPFtpServer.ino b/lib/lib_div/ESPFtpServer/examples/ESPFtpServer.ino new file mode 100644 index 000000000..7fcd1a08c --- /dev/null +++ b/lib/lib_div/ESPFtpServer/examples/ESPFtpServer.ino @@ -0,0 +1,104 @@ +// Uncomment the file system to use for FTP server + +#define FS_LITTLEFS +//#define FS_SPIFFS +//#define FS_SD_MMC + +#ifdef ESP32 +#include +#endif +#ifdef ESP8266 +#include +#endif +#include +#include +#include "ESPFtpServer.h" + +#if defined(FS_LITTLEFS) +#ifdef ESP32 +#include "LITTLEFS.h" +#define FS_ID LITTLEFS +#endif +#ifdef ESP8266 +#include "LittleFS.h" +#define FS_ID LittleFS +#endif +#define FS_NAME "LittleFS" +#elif defined(FS_SPIFFS) +#ifdef ESP32 +#include "SPIFFS.h" +#endif +#define FS_ID SPIFFS +#define FS_NAME "SPIFFS" +#elif defined(FS_SD_MMC) +#include "SD_MMC.h" +#define FS_ID SD_MMC +#define FS_NAME "SD_MMC" +#else +#define FS_ID SD +#define FS_NAME "UNDEF" +#endif + +const char* ssid = "*********************"; +const char* password = "*********************"; + +const char* ntpServer = "pool.ntp.org"; +const long gmtOffset_sec = 3600; +const int daylightOffset_sec = 3600; +struct tm timeinfo; + +FtpServer ftpSrv; //set #define FTP_DEBUG in ESP32FtpServer.h to see ftp verbose on serial + +#ifdef ESP8266 +bool getLocalTime (struct tm * info) { + time_t now; + + time(&now); + localtime_r (&now, info); + + if (info->tm_year > (2016 - 1900)) { + return true; + } + else { + return false; + } +} +#endif + +void setup (void) { + Serial.begin (115200); + + WiFi.begin (ssid, password); + Serial.println (""); + + // Wait for connection + while (WiFi.status () != WL_CONNECTED) { + delay (500); + Serial.print ("."); + } + Serial.println (""); + Serial.print ("Connected to "); + Serial.println (ssid); + Serial.print ("IP address: "); + Serial.println (WiFi.localIP ()); + + configTime (gmtOffset_sec, daylightOffset_sec, ntpServer); + while (!getLocalTime (&timeinfo)) { + delay (500); + Serial.print ("."); + } + Serial.printf ("\nNow is : %d-%02d-%02d %02d:%02d:%02d\n", (timeinfo.tm_year) + 1900, (timeinfo.tm_mon) + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec); + + //FS_ID.format (); + if (FS_ID.begin ()) { + Serial.println ("File system opened (" + String (FS_NAME) + ")"); + ftpSrv.begin ("esp32", "esp32"); //username, password for ftp. set ports in ESPFtpServer.h (default 21, 50009 for PASV) + } + else { + Serial.println ("File system could not be opened; ftp server will not work"); + } +} + +void loop (void){ + ftpSrv.handleFTP (FS_ID); //make sure in loop you call handleFTP()! +} diff --git a/lib/lib_div/ESPFtpServer/library.json b/lib/lib_div/ESPFtpServer/library.json new file mode 100644 index 000000000..9c2bc1525 --- /dev/null +++ b/lib/lib_div/ESPFtpServer/library.json @@ -0,0 +1,21 @@ +{ + "name": "ESPFtpServer", + "keywords": "ftp, littlefs, spiffs, esp32, esp8266", + "description": "ESPFtpServer implements a simple FTP server (passive mode, only one connection at a time) on ESP8266 and ESP32, for any file system (SPIFFS/LittleFS/SD_MMC).", + "homepage": "https://github.com/jmwislez/ESPFtpServer/", + "repository": { + "type": "git", + "url": "https://github.com/jmwislez/ESPFtpServer.git" + }, + "version": "0.1.0", + "authors": { + "name": "Jean-Marc Wislez", + "url": "https://github.com/jmwislez/" + }, + "exclude": [ + ".github", + "extras" + ], + "frameworks": "arduino", + "platforms": ["espressif8266", "espressif32"] +} diff --git a/lib/lib_div/ESPFtpServer/library.properties b/lib/lib_div/ESPFtpServer/library.properties new file mode 100644 index 000000000..e6de7105f --- /dev/null +++ b/lib/lib_div/ESPFtpServer/library.properties @@ -0,0 +1,12 @@ +name=ESPFtpServer +version=0.1.0 +author=Jean-Marc Wislez +maintainer=Jean-Marc Wislez +sentence=A simple FTP server for LittleFS/SPIFFS on ESP8266/ESP32 +paragraph=ESPFtpServer implements a simple FTP server (passive mode, only one connection at a time) on ESP8266 and ESP32, for any file system (SPIFFS/LittleFS/SD_MMC). +category=Network +url=https://github.com/jmwislez/ESPFtpServer/ +architectures=esp8266,esp32 +repository=https://github.com/jmwislez/ESPFtpServer.git +license=GPL +architectures=* diff --git a/tasmota/include/tasmota_types.h b/tasmota/include/tasmota_types.h index 7ed4dbab3..b2df33857 100755 --- a/tasmota/include/tasmota_types.h +++ b/tasmota/include/tasmota_types.h @@ -264,8 +264,7 @@ typedef union { uint32_t spare21 : 1; // bit 21 uint32_t spare22 : 1; // bit 22 uint32_t spare23 : 1; // bit 23 - uint32_t spare24 : 1; // bit 24 - uint32_t spare25 : 1; // bit 25 + uint32_t FTP_Mode : 2; // bit 24, 25 uint32_t tariff_forced : 2; // bit 26..27 (v12.4.0.2) - Energy forced tariff : 0=tariff change on time, 1|2=tariff forced uint32_t sunrise_dawn_angle : 2; // bits 28/29 (v12.1.1.4) - uint32_t temperature_set_res : 2; // bits 30/31 (v9.3.1.4) - (Tuya) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino b/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino index 1a515bd47..f577d5904 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino @@ -48,6 +48,13 @@ ufs fs info ufstype get filesytem type 0=none 1=SD 2=Flashfile ufssize total size in kB ufsfree free size in kB +ufsdelete +ufsrename +ufsrun +ufsServe +ftp start stop ftp server: 0 = OFF, 1 = SDC, 2 = FlashFile + + \*********************************************************************************************/ #define XDRV_50 50 @@ -547,6 +554,9 @@ const char kUFSCommands[] PROGMEM = "Ufs|" // Prefix "|Type|Size|Free|Delete|Rename|Run" #ifdef UFILESYS_STATIC_SERVING "|Serve" +#endif +#ifdef USE_FTP + "|FTP" #endif ; @@ -554,7 +564,10 @@ void (* const kUFSCommand[])(void) PROGMEM = { &UFSInfo, &UFSType, &UFSSize, &UFSFree, &UFSDelete, &UFSRename, &UFSRun #ifdef UFILESYS_STATIC_SERVING ,&UFSServe -#endif +#endif +#ifdef USE_FTP + ,&Switch_FTP +#endif }; void UFSInfo(void) { @@ -1348,17 +1361,70 @@ void UfsEditorUpload(void) { #endif // USE_WEBSERVER + +#ifdef USE_FTP +#include +FtpServer *ftpSrv; + +void FTP_Server(uint32_t mode) { + if (mode > 0) { + if (ftpSrv) { + delete ftpSrv; + } + ftpSrv = new FtpServer; + if (mode == 1) { + ftpSrv->begin(USER_FTP,PW_FTP, ufsp); + } else { + ftpSrv->begin(USER_FTP,PW_FTP, ffsp); + } + AddLog(LOG_LEVEL_INFO, PSTR("UFS: FTP Server started in mode: '%d'"), mode); + } else { + if (ftpSrv) { + delete ftpSrv; + ftpSrv = nullptr; + } + } +} + +void Switch_FTP(void) { + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload >= 0 && XdrvMailbox.payload <= 2) { + FTP_Server(XdrvMailbox.payload); + Settings->mbflag2.FTP_Mode = XdrvMailbox.payload; + } + } + ResponseCmndNumber(Settings->mbflag2.FTP_Mode); +} +#endif // USE_FTP + /*********************************************************************************************\ * Interface \*********************************************************************************************/ + bool Xdrv50(uint32_t function) { bool result = false; switch (function) { case FUNC_LOOP: UfsExecuteCommandFileLoop(); + +#ifdef USE_FTP + if (ftpSrv) { + ftpSrv->handleFTP(); + } +#endif + break; + + case FUNC_NETWORK_UP: +#ifdef USE_FTP + if (Settings->mbflag2.FTP_Mode && !ftpSrv) { + FTP_Server(Settings->mbflag2.FTP_Mode); + } +#endif + break; + /* // Moved to support_tasmota.ino for earlier init to be used by scripter #ifdef USE_SDCARD From 883d34d81ec1b9d481e9718a98a747249fc36559 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 8 Jan 2024 22:16:33 +0100 Subject: [PATCH 100/303] Update xdrv_121_gpioviewer.ino --- .../xdrv_121_gpioviewer.ino | 128 ++++++++++-------- 1 file changed, 69 insertions(+), 59 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index d758de982..b8034af98 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -1,32 +1,35 @@ /* xdrv_121_gpioviewer.ino - GPIOViewer for Tasmota - SPDX-FileCopyrightText: 2024 Theo Arends + SPDX-FileCopyrightText: 2024 Theo Arends, Stephan Hadinger and Charles Giguere SPDX-License-Identifier: GPL-3.0-only */ #ifdef USE_GPIO_VIEWER /*********************************************************************************************\ - * GPIOViewer support + * GPIOViewer support based on work by Charles Giguere * - * Open webpage :8080 and watch realtime GPIO states + * Resources: + * GPIO Viewer: https://github.com/thelastoutpostworkshop/gpio_viewer + * Server Sent Event: https://github.com/esp8266/Arduino/issues/7008 \*********************************************************************************************/ #define XDRV_121 121 #define GV_PORT 5557 -#define GV_SAMPLING_INTERVAL 100 // Relates to FUNC_EVERY_100_MSECOND +#define GV_SAMPLING_INTERVAL 100 // milliseconds - Relates to FUNC_EVERY_100_MSECOND +#define GV_KEEP_ALIVE 1000 // milliseconds - If no activity after this do a heap size event anyway #define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" -const char *GVRelease = "1.0.7"; +const char *GVRelease = "1.0.8"; const char HTTP_GV_PAGE[] PROGMEM = "" "" "" - "%s - GPIO State" + "%s - GPIO Viewer" "" "" "" @@ -38,6 +41,9 @@ const char HTTP_GV_PAGE[] PROGMEM = "var ip='%s';" // WiFi.localIP().toString().c_str() "var source=new EventSource('http://%s:" STR(GV_PORT) "/events');" // WiFi.localIP().toString().c_str() "var sampling_interval='" STR(GV_SAMPLING_INTERVAL) "';" +#ifdef ESP32 + "var psramSize='%d KB';" // ESP.getPsramSize() / 1024 +#endif // ESP32 "var freeSketchSpace='%d KB';" // ESP_getFreeSketchSpace() / 1024 "" "" @@ -67,60 +73,53 @@ const char HTTP_BTN_MENU_GV[] PROGMEM = "

"; enum GVPinTypes { - digitalPin = 0, - PWMPin = 1, - analogPin = 2 + GV_DigitalPin = 0, + GV_PWMPin = 1, + GV_AnalogPin = 2 }; struct { WiFiClient WebClient; ESP8266WebServer *WebServer; uint32_t lastPinStates[MAX_GPIO_PIN]; - uint32_t resolution; + uint32_t lastSentWithNoActivity; uint32_t freeHeap; uint32_t freePSRAM; bool sse_ready; bool active; } GV; -int GVReadGPIO(int gpioNum, uint32_t *originalValue, uint32_t *pintype) { - uint32_t pin_type = GetPin(gpioNum) / 32; +int GVReadGPIO(uint32_t pin, uint32_t *pintype) { + uint32_t pin_type = GetPin(pin) / 32; /* if (GPIO_NONE == pin_type) { - *pintype = digitalPin; - *originalValue = 0; + *pintype = GV_DigitalPin; return 0; } */ #ifdef ESP32 - int pwm_resolution = ledcReadDutyResolution(gpioNum); + int pwm_resolution = ledcReadDutyResolution(pin); if (pwm_resolution > 0) { - *pintype = PWMPin; - *originalValue = ledcRead2(gpioNum); - return changeUIntScale(*originalValue, 0, pwm_resolution, 0, 255); // bring back to 0..255 + *pintype = GV_PWMPin; + return ledcRead2(pin); } #endif // ESP32 #ifdef ESP8266 - int pwm_value = AnalogRead(gpioNum); + int pwm_value = AnalogRead(pin); if (pwm_value > -1) { - *pintype = PWMPin; - *originalValue = pwm_value; - int pwm_resolution = GV.resolution; - return changeUIntScale(*originalValue, 0, pwm_resolution, 0, 255); // bring back to 0..255 + *pintype = GV_PWMPin; + return pwm_value; } #endif // ESP8266 - else if (AdcPin(gpioNum)) { - int adc_resolution = (1 << AdcResolution()) - 1; - *originalValue = AdcRead(gpioNum, 2); - *pintype = analogPin; - return changeUIntScale(*originalValue, 0, adc_resolution, 0, 255); // bring back to 0..255 + else if (AdcPin(pin)) { + *pintype = GV_AnalogPin; + return AdcRead(pin, 2); } - *pintype = digitalPin; - int value = digitalRead(gpioNum); - *originalValue = value; + *pintype = GV_DigitalPin; + int value = digitalRead(pin); if (value == 1) { return 256; } @@ -128,12 +127,11 @@ int GVReadGPIO(int gpioNum, uint32_t *originalValue, uint32_t *pintype) { } void GVResetStatePins(void) { - uint32_t originalValue; - uint32_t pintype; AddLog(LOG_LEVEL_INFO, "IOV: GPIOViewer Connected, sampling interval is " STR(GV_SAMPLING_INTERVAL) "ms"); + uint32_t pintype; for (uint32_t pin = 0; pin < MAX_GPIO_PIN; pin++) { - GV.lastPinStates[pin] = GVReadGPIO(pin, &originalValue, &pintype); + GV.lastPinStates[pin] = GVReadGPIO(pin, &pintype); } } @@ -148,35 +146,19 @@ void GVEventSend(const char *message, const char *event, uint32_t id) { // Monitor GPIO Values void GVMonitorTask(void) { -#ifdef ESP8266 - // Can change on the fly - uint32_t pwm_range = Settings->pwm_range + 1; - GV.resolution = 0; - while (pwm_range) { - GV.resolution++; - pwm_range >>= 1; - } -#endif // ESP8266 - - uint32_t originalValue; uint32_t pintype; - - String jsonMessage = "{"; bool hasChanges = false; + String jsonMessage = "{"; for (uint32_t pin = 0; pin < MAX_GPIO_PIN; pin++) { - int currentState = GVReadGPIO(pin, &originalValue, &pintype); - - if (originalValue != GV.lastPinStates[pin]) { - if (hasChanges) { - jsonMessage += ", "; - } - jsonMessage += "\"" + String(pin) + "\": {\"s\": " + currentState + ", \"v\": " + originalValue + ", \"t\": " + pintype + "}"; + int currentState = GVReadGPIO(pin, &pintype); + if (currentState != GV.lastPinStates[pin]) { + if (hasChanges) { jsonMessage += ","; } + jsonMessage += "\"" + String(pin) + "\":{\"s\":" + currentState + ",\"v\":" + GV.lastPinStates[pin] + ",\"t\":" + pintype + "}"; GV.lastPinStates[pin] = currentState; hasChanges = true; } } jsonMessage += "}"; - if (hasChanges) { GVEventSend(jsonMessage.c_str(), "gpio-state", millis()); } @@ -187,6 +169,7 @@ void GVMonitorTask(void) { char temp[20]; snprintf_P(temp, sizeof(temp), PSTR("%d KB"), heap / 1024); GVEventSend(temp, "free_heap", millis()); + hasChanges = true; } #ifdef ESP32 @@ -197,11 +180,23 @@ void GVMonitorTask(void) { char temp[20]; snprintf_P(temp, sizeof(temp), PSTR("%d KB"), psram / 1024); GVEventSend(temp, "free_psram", millis()); + hasChanges = true; } - } else { - GVEventSend("No PSRAM", "free_psram", millis()); } #endif // ESP32 + + if (!hasChanges) { + uint32_t last_sent = millis() - GV.lastSentWithNoActivity; + if (last_sent > GV_KEEP_ALIVE) { + // No activity, resending for pulse + char temp[20]; + snprintf_P(temp, sizeof(temp), PSTR("%d KB"), heap / 1024); + GVEventSend(temp, "free_heap", millis()); + GV.lastSentWithNoActivity = millis(); + } + } else { + GV.lastSentWithNoActivity = millis(); + } } void GVBegin(void) { @@ -213,6 +208,9 @@ void GVBegin(void) { GV.WebServer->on("/events", GVHandleEvents); GV.WebServer->on("/", GVHandleRoot); GV.WebServer->on("/release", GVHandleRelease); +#ifdef ESP32 + GV.WebServer->on("/free_psram", GVHandleFreePSRam); +#endif // ESP32 GV.WebServer->begin(); } @@ -234,9 +232,11 @@ void GVHandleRoot(void) { SettingsTextEscaped(SET_DEVICENAME).c_str(), WiFi.localIP().toString().c_str(), WiFi.localIP().toString().c_str(), +#ifdef ESP32 + ESP.getPsramSize() / 1024, +#endif // ESP32 ESP_getFreeSketchSpace() / 1024); if (content == nullptr) { return; } // Avoid crash - GV.WebServer->send_P(200, "text/html", content); free(content); @@ -244,8 +244,18 @@ void GVHandleRoot(void) { } void GVHandleRelease(void) { - String jsonResponse = "{\"release\": \"" + String(GVRelease) + "\"}"; + String jsonResponse = "{\"release\":\"" + String(GVRelease) + "\"}"; + GV.WebServer->send(200, "application/json", jsonResponse); +} +void GVHandleFreePSRam(void) { + String jsonResponse = "{\"freePSRAM\":\""; +#ifdef ESP32 + if (UsePSRAM()) { + jsonResponse += String(ESP.getFreePsram() / 1024) + " KB\"}"; + } else +#endif + jsonResponse += "No PSRAM\"}"; GV.WebServer->send(200, "application/json", jsonResponse); } From 8a012452e806db9c592433453139b33fa8f53548 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Mon, 8 Jan 2024 23:15:48 +0100 Subject: [PATCH 101/303] Berry `debug_panel.tapp` to display real-time heap and wifi rssi (#20436) --- CHANGELOG.md | 1 + tasmota/berry/gpio_viewer/autoexec.be | 18 ++ tasmota/berry/gpio_viewer/debug_panel.be | 179 +++++++++++++++++++ tasmota/berry/gpio_viewer/debug_panel.tapp | Bin 0 -> 23076 bytes tasmota/berry/gpio_viewer/webserver_async.be | 8 +- 5 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 tasmota/berry/gpio_viewer/autoexec.be create mode 100644 tasmota/berry/gpio_viewer/debug_panel.be create mode 100644 tasmota/berry/gpio_viewer/debug_panel.tapp diff --git a/CHANGELOG.md b/CHANGELOG.md index e0221235e..9a55c1550 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file. - Berry GPIO viewer initial version using async webserver (#20416) - Berry add `string` to `bytes()` (#20420) - Berry button to dynamically load GPIO Viewer with Berry backend (#20424) +- Berry `debug_panel.tapp` to display real-time heap and wifi rssi ### Breaking Changed diff --git a/tasmota/berry/gpio_viewer/autoexec.be b/tasmota/berry/gpio_viewer/autoexec.be new file mode 100644 index 000000000..d61c44313 --- /dev/null +++ b/tasmota/berry/gpio_viewer/autoexec.be @@ -0,0 +1,18 @@ +# demo for debug panel +# +# rm debug_panel.tapp; zip -j -0 debug_panel.tapp webserver_async.be debug_panel.be autoexec.be +import webserver_async +import debug_panel + +if tasmota.version() >= 0xD030002 + if !tasmota.wifi()['up'] + tasmota.add_rule("Wifi#Connected", def () + global._debug_panel = debug_panel(5550) + tasmota.remove_rule("Wifi#Connected", "debug_panel_start") + end, "debug_panel_start") + else + global._debug_panel = debug_panel(5550) + end +else + log("BRY: 'debug_panel' requires Tasmota v13.3.0.2") +end diff --git a/tasmota/berry/gpio_viewer/debug_panel.be b/tasmota/berry/gpio_viewer/debug_panel.be new file mode 100644 index 000000000..12f7c1c2f --- /dev/null +++ b/tasmota/berry/gpio_viewer/debug_panel.be @@ -0,0 +1,179 @@ +# +# debug_panel.be - implements a small panel on top of the Tasmota UI to view real-time information +# +# Copyright (C) 2023 Stephan Hadinger & Theo Arends +# +# 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 . +# + +class debug_panel + var port + var web + var sampling_interval + # + var payload1, payload2 # temporary object bytes() to avoid reallocation + + static var SAMPLING = 100 + static var HTML_HEAD1 = + "" + static var HTML_URL_F = + "" + static var HTML_HEAD2 = + "" + "" + "" + static var HTML_CONTENT = + '' + '' + '' + '
Free Heap --- KBWifi RSSI --%
' + static var HTML_END = + "" + + def init(port) + self.port = port + self.web = webserver_async(port) + self.sampling_interval = self.SAMPLING + self.payload1 = bytes(100) # reserve 100 bytes by default + self.payload2 = bytes(100) # reserve 100 bytes by default + + self.web.set_chunked(true) + self.web.set_cors(true) + self.web.on("/info_feed", self, self.send_info_feed) + self.web.on("/info", self, self.send_info_page) + + tasmota.add_driver(self) + end + + def close() + tasmota.remove_driver(self) + self.web.close() + end + + def send_info_page(cnx, uri, verb) + import string + + var host = cnx.header_host + var host_split = string.split(host, ':') # need to make it stronger + var ip = host_split[0] + var port = 80 + if size(host_split) > 1 + port = int(host_split[1]) + end + + cnx.send(200, "text/html") + cnx.write(self.HTML_HEAD1) + cnx.write(format(self.HTML_URL_F, ip, port)) + cnx.write(self.HTML_HEAD2) + cnx.write(self.HTML_CONTENT) + cnx.write(self.HTML_END) + + cnx.content_stop() + end + + def send_info_feed(cnx, uri, verb) + cnx.set_chunked(false) # no chunking since we use EventSource + cnx.send(200, "text/event-stream") + self.send_info_tick(cnx) + end + + def send_info_tick(cnx) + if cnx.buf_out_empty() + # if out buffer is not empty, do not send any new information + var payload + # send free heap + payload = f"id:{tasmota.millis()}\r\n" + "event:free_heap\r\n" + "data:{tasmota.memory().find('heap_free', 0)} KB\r\n\r\n" + cnx.write(payload) + + # send wifi rssi + payload = f"id:{tasmota.millis()}\r\n" + "event:wifi_rssi\r\n" + "data:{tasmota.wifi().find('quality', '--')}%\r\n\r\n" + cnx.write(payload) + end + + tasmota.set_timer(self.sampling_interval, def () self.send_info_tick(cnx) end) + end + + # Add button 'GPIO Viewer' redirects to '/part_wiz?' + def web_add_console_button() + self.send_iframe_code() + end + def web_add_main_button() + self.send_iframe_code() + end + def web_add_management_button() + self.send_iframe_code() + end + def web_add_config_button() + self.send_iframe_code() + end + + def send_iframe_code() + import webserver + var ip = tasmota.wifi().find('ip') + if (ip == nil) + ip = tasmota.eth().find('ip') + end + if (ip != nil) + webserver.content_send( + f'
' + '' + '
' + '
') + # f"

") + end + end + +end + +return debug_panel + +# if tasmota +# global.debug_panel = Debug_panel(8887) +# end + +# return global.debug_panel diff --git a/tasmota/berry/gpio_viewer/debug_panel.tapp b/tasmota/berry/gpio_viewer/debug_panel.tapp new file mode 100644 index 0000000000000000000000000000000000000000..31c2f9fc4dbadc001c9a7fa5d179728476da45b4 GIT binary patch literal 23076 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 I&-m^C0C^!5F8}}l literal 0 HcmV?d00001 diff --git a/tasmota/berry/gpio_viewer/webserver_async.be b/tasmota/berry/gpio_viewer/webserver_async.be index 640f79d30..2801484ed 100644 --- a/tasmota/berry/gpio_viewer/webserver_async.be +++ b/tasmota/berry/gpio_viewer/webserver_async.be @@ -198,7 +198,7 @@ class Webserver_async_cnx # pre: self.buf_in is not empty # post: self.buf_in has made progress (smaller or '') def parse() - tasmota.log(f"WEB: incoming {bytes().fromstring(self.buf_in).tohex()}", 3) + # tasmota.log(f"WEB: incoming {bytes().fromstring(self.buf_in).tohex()}", 3) if self.phase == 0 self.parse_http_req_line() elif self.phase == 1 @@ -274,7 +274,7 @@ class Webserver_async_cnx # # Received header def event_http_header(header_key, header_value) - tasmota.log(f"WEB: header key '{header_key}' = '{header_value}'") + # tasmota.log(f"WEB: header key '{header_key}' = '{header_value}'") if (header_key == "Host") self.header_host = header_value @@ -291,7 +291,7 @@ class Webserver_async_cnx ############################################################# # parse incoming payload (if any) def parse_http_payload() - tasmota.log(f"WEB: parsing payload '{bytes().fromstring(self.buf_in).tohex()}'") + # tasmota.log(f"WEB: parsing payload '{bytes().fromstring(self.buf_in).tohex()}'") # dispatch request before parsing payload self.server.dispatch(self, self.req_uri, self.req_verb) end @@ -538,7 +538,7 @@ class webserver_async end -#return webserver_async +return webserver_async #- Test From 2f6ab10146f7ce50a2877e8d671a64f74b20ec46 Mon Sep 17 00:00:00 2001 From: Andrew Klaus Date: Tue, 9 Jan 2024 01:09:36 -0700 Subject: [PATCH 102/303] Fixing logic for SGP4x Sgp4xShow() function (#20439) --- tasmota/tasmota_xsns_sensor/xsns_109_sgp4x.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/tasmota_xsns_sensor/xsns_109_sgp4x.ino b/tasmota/tasmota_xsns_sensor/xsns_109_sgp4x.ino index b58898b50..702e7423a 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_109_sgp4x.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_109_sgp4x.ino @@ -265,9 +265,9 @@ void Sgp4xShow(bool json) if (sgp4x_state == STATE_SGP4X_NORMAL) { if (json) { if (sgp4x_type == TYPE_SGP41) { - ResponseAppend_P(PSTR(",\"SGP40\":{\"VOC_" D_JSON_RAW "\":%d,\"NOX_" D_JSON_RAW "\":%d,\"" D_TVOC "\":%d,\"" D_NOX "\":%d"), srawVoc, srawNox, voc_index_sgp4x, nox_index_sgp4x); + ResponseAppend_P(PSTR(",\"SGP41\":{\"VOC_" D_JSON_RAW "\":%d,\"NOX_" D_JSON_RAW "\":%d,\"" D_TVOC "\":%d,\"" D_NOX "\":%d"), srawVoc, srawNox, voc_index_sgp4x, nox_index_sgp4x); } else { - ResponseAppend_P(PSTR(",\"SGP41\":{\"VOC_" D_JSON_RAW "\":%d,,\"" D_TVOC "\":%d,"), srawVoc, voc_index_sgp4x); + ResponseAppend_P(PSTR(",\"SGP40\":{\"VOC_" D_JSON_RAW "\":%d,,\"" D_TVOC "\":%d,"), srawVoc, voc_index_sgp4x); } ResponseJsonEnd(); #ifdef USE_DOMOTICZ From 81fac808591b3bef0d96514e2cd40f82eec88bc4 Mon Sep 17 00:00:00 2001 From: Christian Baars Date: Tue, 9 Jan 2024 09:10:45 +0100 Subject: [PATCH 103/303] MI32 legacy: add optional argument to BLE.run() (#20431) * add optional argument to BLE.run() * set default of scan response to NO --- lib/libesp32/berry_tasmota/src/be_MI32_lib.c | 4 +- .../esp-nimble-cpp/src/NimBLEAdvertising.cpp | 2 +- tasmota/include/xsns_62_esp32_mi.h | 4 +- .../xdrv_52_3_berry_MI32.ino | 14 ++- .../tasmota_xsns_sensor/xsns_62_esp32_mi.ino | 105 +++++++++++++----- 5 files changed, 94 insertions(+), 35 deletions(-) diff --git a/lib/libesp32/berry_tasmota/src/be_MI32_lib.c b/lib/libesp32/berry_tasmota/src/be_MI32_lib.c index e56ad7ae2..3cddb77dc 100644 --- a/lib/libesp32/berry_tasmota/src/be_MI32_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_MI32_lib.c @@ -64,8 +64,8 @@ BE_FUNC_CTYPE_DECLARE(be_BLE_set_MAC, "", "@(bytes)~[i]"); extern void be_BLE_set_characteristic(struct bvm *vm, const char *Chr); BE_FUNC_CTYPE_DECLARE(be_BLE_set_characteristic, "", "@s"); -extern void be_BLE_run(struct bvm *vm, uint8_t operation, bbool response); -BE_FUNC_CTYPE_DECLARE(be_BLE_run, "", "@i[b]"); +extern void be_BLE_run(struct bvm *vm, uint8_t operation, bbool response, int32_t arg1); +BE_FUNC_CTYPE_DECLARE(be_BLE_run, "", "@i[bi]"); extern void be_BLE_set_service(struct bvm *vm, const char *Svc, bbool discoverAttributes); BE_FUNC_CTYPE_DECLARE(be_BLE_set_service, "", "@s[b]"); diff --git a/lib/libesp32_div/esp-nimble-cpp/src/NimBLEAdvertising.cpp b/lib/libesp32_div/esp-nimble-cpp/src/NimBLEAdvertising.cpp index 50a9e8983..283f26493 100644 --- a/lib/libesp32_div/esp-nimble-cpp/src/NimBLEAdvertising.cpp +++ b/lib/libesp32_div/esp-nimble-cpp/src/NimBLEAdvertising.cpp @@ -67,7 +67,7 @@ void NimBLEAdvertising::reset() { m_advParams.disc_mode = BLE_GAP_DISC_MODE_GEN; m_customAdvData = false; m_customScanResponseData = false; - m_scanResp = true; + m_scanResp = false; m_advDataSet = false; // Set this to non-zero to prevent auto start if host reset before started by app. m_duration = BLE_HS_FOREVER; diff --git a/tasmota/include/xsns_62_esp32_mi.h b/tasmota/include/xsns_62_esp32_mi.h index 09413a9fa..f707bddaf 100644 --- a/tasmota/include/xsns_62_esp32_mi.h +++ b/tasmota/include/xsns_62_esp32_mi.h @@ -156,11 +156,13 @@ struct MI32connectionContextBerry_t{ NimBLEUUID charUUID; uint16_t returnCharUUID; uint16_t handle; - uint8_t MAC[6]; uint8_t * buffer; + uint8_t MAC[6]; uint8_t operation; uint8_t addrType; int error; + int32_t arg1; + bool hasArg1; bool oneOp; bool response; }; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_MI32.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_MI32.ino index 27a8ed9ba..eab484c2b 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_MI32.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_MI32.ino @@ -80,7 +80,7 @@ extern "C" { extern void MI32setBerryAdvCB(void* function, uint8_t *buffer); extern void MI32setBerryConnCB(void* function, uint8_t *buffer); extern void MI32setBerryServerCB(void* function, uint8_t *buffer); - extern bool MI32runBerryConnection(uint8_t operation, bbool response); + extern bool MI32runBerryConnection(uint8_t operation, bbool response, int32_t *arg1); extern bool MI32setBerryCtxSvc(const char *Svc, bbool discoverAttributes); extern bool MI32setBerryCtxChr(const char *Chr); extern bool MI32setBerryCtxMAC(uint8_t *MAC, uint8_t type); @@ -161,13 +161,19 @@ extern "C" { be_raisef(vm, "ble_error", "BLE: could not set characteristic"); } - void be_BLE_run(struct bvm *vm, uint8_t operation, bbool response); - void be_BLE_run(struct bvm *vm, uint8_t operation, bbool response){ + void be_BLE_run(struct bvm *vm, uint8_t operation, bbool response, int32_t arg1); + void be_BLE_run(struct bvm *vm, uint8_t operation, bbool response, int32_t arg1){ + int32_t argc = be_top(vm); // Get the number of arguments bool _response = false; if(response){ _response = response; } - if (MI32runBerryConnection(operation,_response)) return; + int32_t *ptr_arg1 = nullptr; + int32_t _arg1 = arg1; + if(argc == 3){ + ptr_arg1 = &_arg1; + } + if (MI32runBerryConnection(operation, _response, ptr_arg1)) return; be_raisef(vm, "ble_error", "BLE: could not run operation"); } diff --git a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino index 415b2b556..4ca91f3b2 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino @@ -93,6 +93,7 @@ class MI32SensorCallback : public NimBLEClientCallbacks { MI32.infoMsg = MI32_DID_CONNECT; MI32.mode.willConnect = 0; MI32.mode.connected = 1; + pclient->updateConnParams(8,11,0,1000); } void onDisconnect(NimBLEClient* pclient) { MI32.mode.connected = 0; @@ -250,7 +251,7 @@ void MI32notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pD memcpy(item.buffer,pData,length); item.header.returnCharUUID = pRemoteCharacteristic->getUUID().getNative()->u16.value; item.header.handle = pRemoteCharacteristic->getHandle(); - xRingbufferSend(BLERingBufferQueue, (const void*)&item, sizeof(BLERingBufferItem_t) + length , pdMS_TO_TICKS(1)); + xRingbufferSend(BLERingBufferQueue, (const void*)&item, sizeof(BLERingBufferItem_t) + length , pdMS_TO_TICKS(5)); MI32.mode.readingDone = 1; MI32.infoMsg = MI32_GOT_NOTIFICATION; return; @@ -711,9 +712,8 @@ extern "C" { MI32BLELoop(); } - bool MI32runBerryServer(uint16_t operation, bool response){ + bool MI32runBerryServer(uint16_t operation){ MI32.conCtx->operation = operation; - MI32.conCtx->response = response; AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: Berry server op: %d, response: %u"),MI32.conCtx->operation, MI32.conCtx->response); if(MI32.mode.readyForNextServerJob == 0){ MI32.mode.triggerNextServerJob = 0; @@ -724,14 +724,22 @@ extern "C" { return true; } - bool MI32runBerryConnection(uint8_t operation, bool response){ + bool MI32runBerryConnection(uint8_t operation, bool response, int32_t* arg1){ if(MI32.conCtx != nullptr){ + if(arg1 != nullptr){ + MI32.conCtx->arg1 = *arg1; + MI32.conCtx->hasArg1 = true; + AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: arg1: %u"),MI32.conCtx->arg1); + } + else{ + MI32.conCtx->hasArg1 = false; + } + MI32.conCtx->response = response; if(operation > 200){ - return MI32runBerryServer(operation,response); + return MI32runBerryServer(operation); } MI32.conCtx->oneOp = (operation > 9); MI32.conCtx->operation = operation%10; - MI32.conCtx->response = response; AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: Berry connection op: %d, addrType: %d, oneOp: %u, response: %u"),MI32.conCtx->operation, MI32.conCtx->addrType, MI32.conCtx->oneOp, MI32.conCtx->response); if(MI32.conCtx->oneOp){ MI32StartConnectionTask(); @@ -1214,7 +1222,7 @@ bool MI32StartConnectionTask(){ 2, /* Priority of the task */ &MI32.ConnTask, /* Task handle. */ 0); /* Core where the task should run */ - return true; + return true; } void MI32ConnectionTask(void *pvParameters){ @@ -1240,7 +1248,7 @@ void MI32ConnectionTask(void *pvParameters){ timer++; vTaskDelay(10/ portTICK_PERIOD_MS); } - if(MI32.mode.discoverAttributes){ + if(MI32.mode.discoverAttributes || MI32.conCtx->hasArg1){ // explicit or in the first run with selection by handle MI32Client->discoverAttributes(); // solves connection problems on i.e. yeelight dimmer } NimBLERemoteService* pSvc = nullptr; @@ -1271,7 +1279,12 @@ void MI32ConnectionTask(void *pvParameters){ MI32ConnectionGetServices(); } else{ - pSvc = MI32Client->getService(MI32.conCtx->serviceUUID); + if(MI32.conCtx->hasArg1){ + pSvc = nullptr; // invalidate possible dangling service from last operation + } + else{ + pSvc = MI32Client->getService(MI32.conCtx->serviceUUID); + } } if(pSvc) { @@ -1279,9 +1292,12 @@ void MI32ConnectionTask(void *pvParameters){ MI32ConnectionGetCharacteristics(pSvc); } else{ - pChr = pSvc->getCharacteristic(MI32.conCtx->charUUID); + pChr = pSvc->getCharacteristic(MI32.conCtx->charUUID); } } + else if(MI32.conCtx->hasArg1){ + pChr = MI32Client->getCharacteristic(MI32.conCtx->arg1); // get by handle, overriding svc and chr values + } else{ if(MI32.conCtx->operation != 6){ MI32.conCtx->error = MI32_CONN_NO_SERVICE; @@ -1291,12 +1307,13 @@ void MI32ConnectionTask(void *pvParameters){ switch(MI32.conCtx->operation){ case 1: if(pChr->canRead()) { - NimBLEAttValue _val = pChr->readValue(); - MI32.conCtx->buffer[0] = _val.size(); - memcpy( MI32.conCtx->buffer + 1,_val.data(),MI32.conCtx->buffer[0]); + NimBLEAttValue _val = pChr->readValue(); + MI32.conCtx->buffer[0] = _val.size(); + memcpy( MI32.conCtx->buffer + 1,_val.data(),MI32.conCtx->buffer[0]); + MI32.conCtx->handle = pChr->getHandle(); } else{ - MI32.conCtx->error = MI32_CONN_CAN_NOT_READ; + MI32.conCtx->error = MI32_CONN_CAN_NOT_READ; } break; case 2: @@ -1304,6 +1321,7 @@ void MI32ConnectionTask(void *pvParameters){ uint8_t len = MI32.conCtx->buffer[0]; if(pChr->writeValue(MI32.conCtx->buffer + 1,len,MI32.conCtx->response & !pChr->canWriteNoResponse())) { // falls always back to "no response" if server provides both options // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: write op done")); + MI32.conCtx->handle = pChr->getHandle(); } else{ MI32.conCtx->error = MI32_CONN_DID_NOT_WRITE; @@ -1322,15 +1340,31 @@ void MI32ConnectionTask(void *pvParameters){ break; } } - charvector = pSvc->getCharacteristics(true); // always try to subscribe to all characteristics with the same UUID - for (auto &it: *charvector) { - if (it->getUUID() == MI32.conCtx->charUUID) { - if (it->canNotify()) { - if(!it->subscribe(true, MI32notifyCB, MI32.conCtx->response)) { - MI32.conCtx->error = MI32_CONN_CAN_NOT_NOTIFY; // will return the last result only ATM, maybe check differently + if(MI32.conCtx->hasArg1){ // characteristic selected by handle + if (pChr->canNotify()) { + if(!pChr->subscribe(true, MI32notifyCB, MI32.conCtx->response)) { + MI32.conCtx->error = MI32_CONN_CAN_NOT_NOTIFY; // will return the last result only ATM, maybe check differently + } + } + } + else { // characteristic selected by UUID + charvector = pSvc->getCharacteristics(true); // always try to subscribe to all characteristics with the same UUID + uint32_t position = 1; + for (auto &it: *charvector) { + if (it->getUUID() == MI32.conCtx->charUUID) { + if (it->canNotify()) { + if(!it->subscribe(true, MI32notifyCB, MI32.conCtx->response)) { + MI32.conCtx->error = MI32_CONN_CAN_NOT_NOTIFY; // will return the last result only ATM, maybe check differently + } + else{ + MI32.conCtx->buffer[position++] = it->getHandle() >> 8; + MI32.conCtx->buffer[position++] = it->getHandle() & 0xff; + MI32.conCtx->handle = it->getHandle(); + } } } } + MI32.conCtx->buffer[0] = position - 1; } break; default: @@ -1403,7 +1437,7 @@ bool MI32StartServerTask(){ 2, /* Priority of the task */ &MI32.ServerTask, /* Task handle. */ 0); /* Core where the task should run */ - return true; + return true; } void MI32ServerSetAdv(NimBLEServer *pServer, std::vector& servicesToStart, bool &shallStartServices); @@ -1416,6 +1450,15 @@ void MI32ServerSetAdv(NimBLEServer *pServer, std::vector& servic */ void MI32ServerSetAdv(NimBLEServer *pServer, std::vector& servicesToStart, bool &shallStartServices){ NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising(); + /** optional argument arg1 + BLE_GAP_CONN_MODE_NON (0) - not connectable advertising + BLE_GAP_CONN_MODE_DIR (1) - directed connectable advertising + BLE_GAP_CONN_MODE_UND (2) - undirected connectable advertising + */ + if(MI32.conCtx->hasArg1){ + pAdvertising->setAdvertisementType(MI32.conCtx->arg1); + // AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: AdvertisementType: %u"),MI32.conCtx->arg1); + } struct{ BLERingBufferItem_t header; uint8_t buffer[255]; @@ -1447,7 +1490,10 @@ void MI32ServerSetAdv(NimBLEServer *pServer, std::vector& servic adv.addData((char *)&MI32.conCtx->buffer[1], MI32.conCtx->buffer[0]); if(MI32.conCtx->operation == BLE_OP_SET_ADV){ pAdvertising->setAdvertisementData(adv); // replace whole advertisement with our custom data from the Berry side - pAdvertising->start(); + if(pAdvertising->isAdvertising() == false && !shallStartServices){ // first advertisement + vTaskDelay(1000/ portTICK_PERIOD_MS); // work around to prevent crash on start + pAdvertising->start(); + } } else { pAdvertising->setScanResponseData(adv); @@ -1486,11 +1532,16 @@ void MI32ServerSetCharacteristic(NimBLEServer *pServer, std::vectorgetCharacteristic(MI32.conCtx->charUUID); // again retrieve ... if(pCharacteristic == nullptr){ uint32_t _writeRSP = MI32.conCtx->response ? NIMBLE_PROPERTY::WRITE : NIMBLE_PROPERTY::WRITE_NR; + uint32_t _property = NIMBLE_PROPERTY::READ | + _writeRSP | + NIMBLE_PROPERTY::NOTIFY | + NIMBLE_PROPERTY::INDICATE; // default to "all" + if(MI32.conCtx->hasArg1){ + _property = MI32.conCtx->arg1; // override with optional argument + // AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: _property: %u"),_property); + } pCharacteristic = pService->createCharacteristic(MI32.conCtx->charUUID, - NIMBLE_PROPERTY::READ | - _writeRSP | - NIMBLE_PROPERTY::NOTIFY | - NIMBLE_PROPERTY::INDICATE); //... or create characteristic. + _property); //... or create characteristic. if(pCharacteristic == nullptr){ MI32.conCtx->error = MI32_CONN_NO_CHARACTERISTIC; return; @@ -1499,7 +1550,7 @@ void MI32ServerSetCharacteristic(NimBLEServer *pServer, std::vectorsetValue(MI32.conCtx->buffer + 1, MI32.conCtx->buffer[0]); // set value - pCharacteristic->notify(true); // always notify .. for now + pCharacteristic->notify(true); // TODO: fallback to indication struct{ BLERingBufferItem_t header; } item; From 935fa3519ca2ebedfdec915f663950cd2101e593 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Tue, 9 Jan 2024 13:43:26 +0100 Subject: [PATCH 104/303] Fix display of source IP when restarting from UI button (#20443) --- tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino index 20ce791f0..a3ec87e0b 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino @@ -534,7 +534,7 @@ void ShowWebSource(uint32_t source) { if ((source > 0) && (source < SRC_MAX)) { char stemp1[20]; - AddLog(LOG_LEVEL_DEBUG, PSTR("SRC: %s from %_I"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource), (uint32_t)Webserver->client().remoteIP()); + AddLog(LOG_LEVEL_DEBUG, PSTR("SRC: %s from %s"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource), Webserver->client().remoteIP().toString().c_str()); } } @@ -1075,8 +1075,6 @@ void WebRestart(uint32_t type) { WSContentSpaceButton(BUTTON_MAIN); } } - WSContentStop(); - if (!(2 == type)) { AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_RESTART)); ShowWebSource(SRC_WEBGUI); @@ -1085,6 +1083,7 @@ void WebRestart(uint32_t type) { #endif // ESP32 TasmotaGlobal.restart_flag = 2; } + WSContentStop(); } /*********************************************************************************************/ From 451f9ba4ae68d5302d47dcdda8181563a2bfd0b7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 9 Jan 2024 14:58:33 +0100 Subject: [PATCH 105/303] Fix GPIOViewer init and event data --- .../xdrv_121_gpioviewer.ino | 179 +++++++++--------- 1 file changed, 93 insertions(+), 86 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index b8034af98..7caa8becc 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -23,7 +23,7 @@ #define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" -const char *GVRelease = "1.0.8"; +const char *GVRelease = "1.0.7"; const char HTTP_GV_PAGE[] PROGMEM = "" @@ -69,9 +69,6 @@ const char HTTP_GV_EVENT[] PROGMEM = "Cache-Control: no-cache\n" "Access-Control-Allow-Origin: *\n\n"; -const char HTTP_BTN_MENU_GV[] PROGMEM = - "

"; - enum GVPinTypes { GV_DigitalPin = 0, GV_PWMPin = 1, @@ -81,60 +78,14 @@ enum GVPinTypes { struct { WiFiClient WebClient; ESP8266WebServer *WebServer; - uint32_t lastPinStates[MAX_GPIO_PIN]; + int lastPinStates[MAX_GPIO_PIN]; uint32_t lastSentWithNoActivity; uint32_t freeHeap; uint32_t freePSRAM; - bool sse_ready; bool active; + bool sse_ready; } GV; -int GVReadGPIO(uint32_t pin, uint32_t *pintype) { - uint32_t pin_type = GetPin(pin) / 32; -/* - if (GPIO_NONE == pin_type) { - *pintype = GV_DigitalPin; - return 0; - } -*/ -#ifdef ESP32 - int pwm_resolution = ledcReadDutyResolution(pin); - if (pwm_resolution > 0) { - *pintype = GV_PWMPin; - return ledcRead2(pin); - } -#endif // ESP32 - -#ifdef ESP8266 - int pwm_value = AnalogRead(pin); - if (pwm_value > -1) { - *pintype = GV_PWMPin; - return pwm_value; - } -#endif // ESP8266 - - else if (AdcPin(pin)) { - *pintype = GV_AnalogPin; - return AdcRead(pin, 2); - } - - *pintype = GV_DigitalPin; - int value = digitalRead(pin); - if (value == 1) { - return 256; - } - return 0; -} - -void GVResetStatePins(void) { - AddLog(LOG_LEVEL_INFO, "IOV: GPIOViewer Connected, sampling interval is " STR(GV_SAMPLING_INTERVAL) "ms"); - - uint32_t pintype; - for (uint32_t pin = 0; pin < MAX_GPIO_PIN; pin++) { - GV.lastPinStates[pin] = GVReadGPIO(pin, &pintype); - } -} - //void GVEventSend(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); void GVEventSend(const char *message, const char *event, uint32_t id) { if (GV.WebClient.connected()) { @@ -144,17 +95,61 @@ void GVEventSend(const char *message, const char *event, uint32_t id) { } } -// Monitor GPIO Values void GVMonitorTask(void) { + // Monitor GPIO Values + uint32_t originalValue; uint32_t pintype; bool hasChanges = false; + String jsonMessage = "{"; for (uint32_t pin = 0; pin < MAX_GPIO_PIN; pin++) { - int currentState = GVReadGPIO(pin, &pintype); - if (currentState != GV.lastPinStates[pin]) { + int currentState = 0; +/* + uint32_t pin_type = GetPin(pin) / 32; + if (GPIO_NONE == pin_type) { + pintype = GV_DigitalPin; + originalValue = 0; +// currentState = 0; + } +*/ +#ifdef ESP32 + int pwm_resolution = ledcReadDutyResolution(pin); + if (pwm_resolution > 0) { + pintype = GV_PWMPin; + originalValue = ledcRead2(pin); + currentState = changeUIntScale(originalValue, 0, pwm_resolution, 0, 255); // bring back to 0..255 + } +#endif // ESP32 + +#ifdef ESP8266 + int pwm_value = AnalogRead(pin); + if (pwm_value > -1) { + pintype = GV_PWMPin; + originalValue = pwm_value; + currentState = changeUIntScale(originalValue, 0, Settings->pwm_range, 0, 255); // bring back to 0..255 + } +#endif // ESP8266 + + else if (AdcPin(pin)) { + pintype = GV_AnalogPin; + originalValue = AdcRead(pin, 2); + int adc_resolution = (1 << AdcResolution()) - 1; + currentState = changeUIntScale(originalValue, 0, adc_resolution, 0, 255); // bring back to 0..255 + } else { + pintype = GV_DigitalPin; + int value = digitalRead(pin); + originalValue = value; + if (value == 1) { + currentState = 256; +// } else { +// currentState = 0; + } + } + + if (originalValue != GV.lastPinStates[pin]) { if (hasChanges) { jsonMessage += ","; } - jsonMessage += "\"" + String(pin) + "\":{\"s\":" + currentState + ",\"v\":" + GV.lastPinStates[pin] + ",\"t\":" + pintype + "}"; - GV.lastPinStates[pin] = currentState; + jsonMessage += "\"" + String(pin) + "\":{\"s\":" + currentState + ",\"v\":" + originalValue + ",\"t\":" + pintype + "}"; + GV.lastPinStates[pin] = originalValue; hasChanges = true; } } @@ -208,15 +203,11 @@ void GVBegin(void) { GV.WebServer->on("/events", GVHandleEvents); GV.WebServer->on("/", GVHandleRoot); GV.WebServer->on("/release", GVHandleRelease); -#ifdef ESP32 GV.WebServer->on("/free_psram", GVHandleFreePSRam); -#endif // ESP32 GV.WebServer->begin(); } void GVHandleEvents(void) { - GVResetStatePins(); - GV.WebClient = GV.WebServer->client(); GV.WebClient.setNoDelay(true); // GV.WebClient.setSync(true); @@ -259,6 +250,33 @@ void GVHandleFreePSRam(void) { GV.WebServer->send(200, "application/json", jsonResponse); } +/*********************************************************************************************\ + * GUI +\*********************************************************************************************/ +#ifdef USE_WEBSERVER +#define WEB_HANDLE_GV "gv1" + +const char HTTP_BTN_MENU_GV[] PROGMEM = +// "

"; + "

"; + +void GVSetupAndStart(void) { + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_GPIO_VIEWER)); + + if (!GV.active) { + GVBegin(); + GV.active = true; + } + + char redirect[100]; + snprintf_P(redirect, sizeof(redirect), PSTR("http://%s:" STR(GV_PORT) "/"), WiFi.localIP().toString().c_str()); + Webserver->sendHeader(F("Location"), redirect); + Webserver->send(303); +} +#endif // USE_WEBSERVER + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -266,6 +284,20 @@ void GVHandleFreePSRam(void) { bool Xdrv121(uint32_t function) { bool result = false; + switch (function) { +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_MANAGEMENT_BUTTON: + if (XdrvMailbox.index) { + XdrvMailbox.index++; + } else { + WSContentSend_PD(HTTP_BTN_MENU_GV); + } + break; + case FUNC_WEB_ADD_HANDLER: + Webserver->on(PSTR("/" WEB_HANDLE_GV), GVSetupAndStart); + break; +#endif // USE_WEBSERVER + } if (GV.active) { switch (function) { case FUNC_LOOP: @@ -274,35 +306,10 @@ bool Xdrv121(uint32_t function) { case FUNC_EVERY_100_MSECOND: if (GV.sse_ready) { GVMonitorTask(); } break; -#ifdef USE_WEBSERVER - case FUNC_WEB_ADD_MANAGEMENT_BUTTON: - if (XdrvMailbox.index) { - XdrvMailbox.index++; - } else { - WSContentSend_P(HTTP_BTN_MENU_GV, WiFi.localIP().toString().c_str()); - } - break; -#endif // USE_WEBSERVER case FUNC_ACTIVE: result = true; break; } - } else { - switch (function) { - case FUNC_EVERY_SECOND: - if (!TasmotaGlobal.global_state.network_down) { - // Add delay to finish network setup - static uint32_t gv_delay = 3; - if (gv_delay) { - gv_delay--; - } else { - GVBegin(); - GV.active = true; - } - } - break; - } - } return result; } From 52dd206fb73de353dee13cd0934315284fb4331c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 9 Jan 2024 17:08:13 +0100 Subject: [PATCH 106/303] Add GPIOViewer flow control Add GPIOViewer flow control to reduce system load if not used --- .../xdrv_121_gpioviewer.ino | 155 ++++++++++++------ 1 file changed, 102 insertions(+), 53 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 7caa8becc..f687deffa 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -86,12 +86,87 @@ struct { bool sse_ready; } GV; +void GVBegin(void) { + GV.WebServer = new ESP8266WebServer(GV_PORT); + // Set CORS headers for global responses + GV.WebServer->sendHeader("Access-Control-Allow-Origin", "*"); + GV.WebServer->sendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); + GV.WebServer->sendHeader("Access-Control-Allow-Headers", "Content-Type"); + GV.WebServer->on("/events", GVHandleEvents); + GV.WebServer->on("/", GVHandleRoot); + GV.WebServer->on("/release", GVHandleRelease); + GV.WebServer->on("/free_psram", GVHandleFreePSRam); + GV.WebServer->begin(); + + GV.active = true; +} + +void GVStop(void) { + GV.sse_ready = false; + GV.active = false; + + GV.WebServer->stop(); + GV.WebServer = nullptr; +} + +void GVHandleEvents(void) { + GV.WebClient = GV.WebServer->client(); + GV.WebClient.setNoDelay(true); +// GV.WebClient.setSync(true); + + GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // The payload can go on forever + GV.WebServer->sendContent_P(HTTP_GV_EVENT); + + GV.sse_ready = true; // Ready for async updates + + AddLog(LOG_LEVEL_DEBUG, PSTR("IOV: Client connected")); +} + +void GVHandleRoot(void) { + char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, + SettingsTextEscaped(SET_DEVICENAME).c_str(), + WiFi.localIP().toString().c_str(), + WiFi.localIP().toString().c_str(), +#ifdef ESP32 + ESP.getPsramSize() / 1024, +#endif // ESP32 + ESP_getFreeSketchSpace() / 1024); + if (content == nullptr) { return; } // Avoid crash + GV.WebServer->send_P(200, "text/html", content); + free(content); + + GV.sse_ready = false; // Allow restart of updates on page load +} + +void GVHandleRelease(void) { + String jsonResponse = "{\"release\":\"" + String(GVRelease) + "\"}"; + GV.WebServer->send(200, "application/json", jsonResponse); +} + +void GVHandleFreePSRam(void) { + String jsonResponse = "{\"freePSRAM\":\""; +#ifdef ESP32 + if (UsePSRAM()) { + jsonResponse += String(ESP.getFreePsram() / 1024) + " KB\"}"; + } else +#endif + jsonResponse += "No PSRAM\"}"; + GV.WebServer->send(200, "application/json", jsonResponse); +} + //void GVEventSend(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); void GVEventSend(const char *message, const char *event, uint32_t id) { if (GV.WebClient.connected()) { // generateEventMessage() in AsyncEventSource.cpp // GV.WebClient.printf_P(PSTR("retry: 0\r\nid: %u\r\nevent: %s\r\ndata: %s\r\n\r\n"), id, event, message); GV.WebClient.printf_P(PSTR("id: %u\r\nevent: %s\r\ndata: %s\r\n\r\n"), id, event, message); + } else { + if (GV.sse_ready) { + AddLog(LOG_LEVEL_DEBUG, PSTR("IOV: Client disconnected")); + } +// GVStop(); // This will stop the webserver but not all memory will be released resulting in memory leaks + GV.sse_ready = false; // This just stops the event to be restarted by opening root page again + } } @@ -194,60 +269,33 @@ void GVMonitorTask(void) { } } -void GVBegin(void) { - GV.WebServer = new ESP8266WebServer(GV_PORT); - // Set CORS headers for global responses - GV.WebServer->sendHeader("Access-Control-Allow-Origin", "*"); - GV.WebServer->sendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); - GV.WebServer->sendHeader("Access-Control-Allow-Headers", "Content-Type"); - GV.WebServer->on("/events", GVHandleEvents); - GV.WebServer->on("/", GVHandleRoot); - GV.WebServer->on("/release", GVHandleRelease); - GV.WebServer->on("/free_psram", GVHandleFreePSRam); - GV.WebServer->begin(); -} +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ -void GVHandleEvents(void) { - GV.WebClient = GV.WebServer->client(); - GV.WebClient.setNoDelay(true); -// GV.WebClient.setSync(true); +const char kGVCommands[] PROGMEM = "GV|" // Prefix + "Viewer"; - GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // The payload can go on forever - GV.WebServer->sendContent_P(HTTP_GV_EVENT); +void (* const GVCommand[])(void) PROGMEM = { + &CmndGVViewer}; - GV.sse_ready = true; // Ready for async updates -} - -void GVHandleRoot(void) { - char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, - SettingsTextEscaped(SET_DEVICENAME).c_str(), - WiFi.localIP().toString().c_str(), - WiFi.localIP().toString().c_str(), -#ifdef ESP32 - ESP.getPsramSize() / 1024, -#endif // ESP32 - ESP_getFreeSketchSpace() / 1024); - if (content == nullptr) { return; } // Avoid crash - GV.WebServer->send_P(200, "text/html", content); - free(content); - - GV.sse_ready = false; // Allow restart of updates on page load -} - -void GVHandleRelease(void) { - String jsonResponse = "{\"release\":\"" + String(GVRelease) + "\"}"; - GV.WebServer->send(200, "application/json", jsonResponse); -} - -void GVHandleFreePSRam(void) { - String jsonResponse = "{\"freePSRAM\":\""; -#ifdef ESP32 - if (UsePSRAM()) { - jsonResponse += String(ESP.getFreePsram() / 1024) + " KB\"}"; - } else -#endif - jsonResponse += "No PSRAM\"}"; - GV.WebServer->send(200, "application/json", jsonResponse); +void CmndGVViewer(void) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { + uint32_t state = XdrvMailbox.payload; + if (2 == state) { // Toggle + state = GV.active ^1; + } + if (state) { // On + GVBegin(); + } else { // Off + GVStop(); + } + } + if (GV.active) { + Response_P(PSTR("{\"%s\":\"Active on http://%s:" STR(GV_PORT) "/\"}"), XdrvMailbox.command, WiFi.localIP().toString().c_str()); + } else { + ResponseCmndChar_P(PSTR("Stopped")); + } } /*********************************************************************************************\ @@ -257,7 +305,6 @@ void GVHandleFreePSRam(void) { #define WEB_HANDLE_GV "gv1" const char HTTP_BTN_MENU_GV[] PROGMEM = -// "

"; "

"; void GVSetupAndStart(void) { @@ -267,7 +314,6 @@ void GVSetupAndStart(void) { if (!GV.active) { GVBegin(); - GV.active = true; } char redirect[100]; @@ -285,6 +331,9 @@ bool Xdrv121(uint32_t function) { bool result = false; switch (function) { + case FUNC_COMMAND: + result = DecodeCommand(kGVCommands, GVCommand); + break; #ifdef USE_WEBSERVER case FUNC_WEB_ADD_MANAGEMENT_BUTTON: if (XdrvMailbox.index) { From 8712aba3c561450d787fe50d1dd13b0be9fd588e Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Tue, 9 Jan 2024 19:34:07 +0100 Subject: [PATCH 107/303] Header `Host` is now collected by Webserver (#20446) --- CHANGELOG.md | 1 + tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a55c1550..955807727 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to this project will be documented in this file. ### Changed - Renamed button "Consoles" to "Tools" +- Header `Host` is now collected by Webserver ### Fixed diff --git a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino index a3ec87e0b..c2f9619d4 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino @@ -602,7 +602,7 @@ void StartWebserver(int type) if (!Webserver) { Webserver = new ESP8266WebServer((HTTP_MANAGER == type || HTTP_MANAGER_RESET_ONLY == type) ? 80 : WEB_PORT); - const char* headerkeys[] = { "Referer" }; + const char* headerkeys[] = { "Referer", "Host" }; size_t headerkeyssize = sizeof(headerkeys) / sizeof(char*); Webserver->collectHeaders(headerkeys, headerkeyssize); From 85fb54fe8d05c93ec13edf85ee68d9529d45346d Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Tue, 9 Jan 2024 19:34:19 +0100 Subject: [PATCH 108/303] Berry `webserver.header` to read browser sent headers (#20447) --- CHANGELOG.md | 1 + .../berry_tasmota/src/be_webserver_lib.c | 3 +++ .../xdrv_52_3_berry_webserver.ino | 17 +++++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 955807727..045a876d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file. - Berry add `string` to `bytes()` (#20420) - Berry button to dynamically load GPIO Viewer with Berry backend (#20424) - Berry `debug_panel.tapp` to display real-time heap and wifi rssi +- Berry `webserver.header` to read browser sent headers ### Breaking Changed diff --git a/lib/libesp32/berry_tasmota/src/be_webserver_lib.c b/lib/libesp32/berry_tasmota/src/be_webserver_lib.c index 541233893..279b1fb05 100644 --- a/lib/libesp32/berry_tasmota/src/be_webserver_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_webserver_lib.c @@ -34,6 +34,7 @@ extern int w_webserver_arg(bvm *vm); extern int w_webserver_arg_name(bvm *vm); extern int w_webserver_has_arg(bvm *vm); +extern int w_webserver_header(bvm *vm); // To allow a full restart of the Berry VM, we need to supplement the webserver Request Handler // model from Arduino framework. @@ -160,6 +161,8 @@ module webserver (scope: global) { arg, func(w_webserver_arg) arg_name, func(w_webserver_arg_name) has_arg, func(w_webserver_has_arg) + + header, func(w_webserver_header) } @const_object_info_end */ #include "be_fixed_webserver.h" diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webserver.ino index 244e594cf..ca05a02de 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webserver.ino @@ -335,6 +335,23 @@ extern "C" { be_raise(vm, kTypeError, nullptr); } + // Berry: `webserver.header(name:string) -> string or nil` + int32_t w_webserver_header(struct bvm *vm); + int32_t w_webserver_header(struct bvm *vm) { + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 1 && be_isstring(vm, 1)) { + const char * header_name = be_tostring(vm, 1); + String header = Webserver->header(header_name); + if (header.length() > 0) { + be_pushstring(vm, header.c_str()); + be_return(vm); + } else { + be_return_nil(vm); + } + } + be_raise(vm, kTypeError, nullptr); + } + } #endif // USE_WEBSERVER From 69d4e323d6f6446924ed4cfddb57bd916c8dc1b4 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Tue, 9 Jan 2024 19:49:30 +0100 Subject: [PATCH 109/303] Berry provide lightweight options for `tasmota.wifi/eth/memory/rtc` (#20448) --- CHANGELOG.md | 1 + .../berry_mapping/src/be_mapping_utils.c | 105 ++++++++--- .../berry_tasmota/src/be_tasmota_lib.c | 8 +- .../xdrv_52_3_berry_tasmota.ino | 176 ++++++++++-------- 4 files changed, 175 insertions(+), 115 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 045a876d4..3e09349d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ All notable changes to this project will be documented in this file. - Berry button to dynamically load GPIO Viewer with Berry backend (#20424) - Berry `debug_panel.tapp` to display real-time heap and wifi rssi - Berry `webserver.header` to read browser sent headers +- Berry provide lightweight options for `tasmota.wifi/eth/memory/rtc` ### Breaking Changed diff --git a/lib/libesp32/berry_mapping/src/be_mapping_utils.c b/lib/libesp32/berry_mapping/src/be_mapping_utils.c index 51f7388ba..18fad80af 100644 --- a/lib/libesp32/berry_mapping/src/be_mapping_utils.c +++ b/lib/libesp32/berry_mapping/src/be_mapping_utils.c @@ -8,61 +8,104 @@ /* Insert an nil to a key */ void be_map_insert_nil(bvm *vm, const char *key) { - be_pushstring(vm, key); - be_pushnil(vm); - be_data_insert(vm, -3); - be_pop(vm, 2); + if (be_ismap(vm, -1)) { + be_pushstring(vm, key); + be_pushnil(vm); + be_data_insert(vm, -3); + be_pop(vm, 2); + } } /* Insert an int to a key */ +// On stack is either: +// Case 1; (-2) map instance, (-1) map +// Case 2; (-2) nil, (-1) string -> if key matches then update (-2) void be_map_insert_int(bvm *vm, const char *key, bint value) { - be_pushstring(vm, key); - be_pushint(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); + if (be_ismap(vm, -1)) { + be_pushstring(vm, key); + be_pushint(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); + } else if (be_isstring(vm, -1)) { + const char * needle = be_tostring(vm, -1); + if (strcmp(key, needle) == 0) { + be_pushint(vm, value); + be_moveto(vm, -1, -3); + be_pop(vm, 1); + } + } } /* Insert an bbool to a key */ void be_map_insert_bool(bvm *vm, const char *key, bbool value) { - be_pushstring(vm, key); - be_pushbool(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); + if (be_ismap(vm, -1)) { + be_pushstring(vm, key); + be_pushbool(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); + } else if (be_isstring(vm, -1)) { + const char * needle = be_tostring(vm, -1); + if (strcmp(key, needle) == 0) { + be_pushbool(vm, value); + be_moveto(vm, -1, -3); + be_pop(vm, 1); + } + } } /* Insert an real to a key */ /* if value == NAN, ignore */ void be_map_insert_real(bvm *vm, const char *key, breal value) { - if (!isnan(value)) { - be_pushstring(vm, key); - be_pushreal(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); + if (be_ismap(vm, -1)) { + if (!isnan(value)) { + be_pushstring(vm, key); + be_pushreal(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); + } + } else if (be_isstring(vm, -1)) { + const char * needle = be_tostring(vm, -1); + if (strcmp(key, needle) == 0) { + be_pushreal(vm, value); + be_moveto(vm, -1, -3); + be_pop(vm, 1); + } } } /* Insert an C string to a key */ void be_map_insert_str(bvm *vm, const char *key, const char *value) { - be_pushstring(vm, key); - be_pushstring(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); + if (be_ismap(vm, -1)) { + be_pushstring(vm, key); + be_pushstring(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); + } else if (be_isstring(vm, -1)) { + const char * needle = be_tostring(vm, -1); + if (strcmp(key, needle) == 0) { + be_pushstring(vm, value); + be_moveto(vm, -1, -3); + be_pop(vm, 1); + } + } } /* Insert list of bytes as individual integers to a key */ void be_map_insert_list_uint8(bvm *vm, const char *key, const uint8_t *value, size_t size) { - be_pushstring(vm, key); + if (be_ismap(vm, -1)) { + be_pushstring(vm, key); - be_newobject(vm, "list"); - for (uint32_t i=0; i < size; i++) { - be_pushint(vm, value[i]); - be_data_push(vm, -2); - be_pop(vm, 1); + be_newobject(vm, "list"); + for (uint32_t i=0; i < size; i++) { + be_pushint(vm, value[i]); + be_data_push(vm, -2); + be_pop(vm, 1); + } + be_pop(vm, 1); // now list is on top + + be_data_insert(vm, -3); // insert into map, key/value + be_pop(vm, 2); // pop both key and value } - be_pop(vm, 1); // now list is on top - - be_data_insert(vm, -3); // insert into map, key/value - be_pop(vm, 2); // pop both key and value } /*********************************************************************************************\ diff --git a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c index 5a6be0281..528a3b8b8 100644 --- a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c @@ -111,14 +111,14 @@ class be_class_tasmota (scope: global, name: Tasmota) { get_option, func(l_getoption) millis, func(l_millis) time_reached, func(l_timereached) - rtc, func(l_rtc) + rtc, static_func(l_rtc) rtc_utc, func(l_rtc_utc) time_dump, func(l_time_dump) strftime, func(l_strftime) strptime, func(l_strptime) - memory, func(l_memory) - wifi, func(l_wifi) - eth, func(l_eth) + memory, static_func(l_memory) + wifi, static_func(l_wifi) + eth, static_func(l_eth) hostname, func(l_hostname) yield, func(l_yield) delay, func(l_delay) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino index c4df2e318..f82bb0fb9 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino @@ -171,16 +171,20 @@ extern "C" { int32_t l_rtc(struct bvm *vm); int32_t l_rtc(struct bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments - if (top == 1) { // no argument (instance only) + if (top >= 1 && be_isstring(vm, 1)) { // argument is name + be_pushnil(vm); + be_pushvalue(vm, 1); + // (-2) nil, (-1) string -> if key matches then update (-2) + } else { be_newobject(vm, "map"); - be_map_insert_int(vm, "utc", Rtc.utc_time); - be_map_insert_int(vm, "local", Rtc.local_time); - be_map_insert_int(vm, "restart", Rtc.restart_time); - be_map_insert_int(vm, "timezone", Rtc.time_timezone); - be_pop(vm, 1); - be_return(vm); + // (-2) map instance, (-1) map } - be_raise(vm, kTypeError, nullptr); + be_map_insert_int(vm, "utc", Rtc.utc_time); + be_map_insert_int(vm, "local", Rtc.local_time); + be_map_insert_int(vm, "restart", Rtc.restart_time); + be_map_insert_int(vm, "timezone", Rtc.time_timezone); + be_pop(vm, 1); + be_return(vm); } // Berry: tasmota.rtc_utc() -> int @@ -196,28 +200,32 @@ extern "C" { int32_t l_memory(struct bvm *vm); int32_t l_memory(struct bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments - if (top == 1) { // no argument (instance only) + if (top >= 1 && be_isstring(vm, 1)) { // argument is name + be_pushnil(vm); + be_pushvalue(vm, 1); + // (-2) nil, (-1) string -> if key matches then update (-2) + } else { be_newobject(vm, "map"); - be_map_insert_int(vm, "flash", ESP_getFlashChipMagicSize() / 1024); - be_map_insert_int(vm, "flash_real", ESP.getFlashChipSize() / 1024); - be_map_insert_int(vm, "program", ESP_getSketchSize() / 1024); - be_map_insert_int(vm, "program_free", ESP_getFreeSketchSpace() / 1024); - be_map_insert_int(vm, "heap_free", ESP_getFreeHeap() / 1024); - be_map_insert_int(vm, "frag", ESP_getHeapFragmentation()); - // give info about stack size - be_map_insert_int(vm, "stack_size", SET_ESP32_STACK_SIZE / 1024); - be_map_insert_real(vm, "stack_low", ((float)uxTaskGetStackHighWaterMark(nullptr)) / 1024); - if (UsePSRAM()) { - be_map_insert_int(vm, "psram", ESP.getPsramSize() / 1024); - be_map_insert_int(vm, "psram_free", ESP.getFreePsram() / 1024); - } - // IRAM information - int32_t iram_free = (int32_t)heap_caps_get_free_size(MALLOC_CAP_32BIT) - (int32_t)heap_caps_get_free_size(MALLOC_CAP_8BIT); - be_map_insert_int(vm, "iram_free", iram_free / 1024); - be_pop(vm, 1); - be_return(vm); + // (-2) map instance, (-1) map } - be_raise(vm, kTypeError, nullptr); + be_map_insert_int(vm, "flash", ESP_getFlashChipMagicSize() / 1024); + be_map_insert_int(vm, "flash_real", ESP.getFlashChipSize() / 1024); + be_map_insert_int(vm, "program", ESP_getSketchSize() / 1024); + be_map_insert_int(vm, "program_free", ESP_getFreeSketchSpace() / 1024); + be_map_insert_int(vm, "heap_free", ESP_getFreeHeap() / 1024); + be_map_insert_int(vm, "frag", ESP_getHeapFragmentation()); + // give info about stack size + be_map_insert_int(vm, "stack_size", SET_ESP32_STACK_SIZE / 1024); + be_map_insert_real(vm, "stack_low", ((float)uxTaskGetStackHighWaterMark(nullptr)) / 1024); + if (UsePSRAM()) { + be_map_insert_int(vm, "psram", ESP.getPsramSize() / 1024); + be_map_insert_int(vm, "psram_free", ESP.getFreePsram() / 1024); + } + // IRAM information + int32_t iram_free = (int32_t)heap_caps_get_free_size(MALLOC_CAP_32BIT) - (int32_t)heap_caps_get_free_size(MALLOC_CAP_8BIT); + be_map_insert_int(vm, "iram_free", iram_free / 1024); + be_pop(vm, 1); + be_return(vm); } // Berry: tasmota.wifi() -> map @@ -225,38 +233,42 @@ extern "C" { int32_t l_wifi(struct bvm *vm); int32_t l_wifi(struct bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments - if (top == 1) { // no argument (instance only) + if (top >= 1 && be_isstring(vm, 1)) { // argument is name + be_pushnil(vm); + be_pushvalue(vm, 1); + // (-2) nil, (-1) string -> if key matches then update (-2) + } else { be_newobject(vm, "map"); - be_map_insert_str(vm, "mac", WiFi.macAddress().c_str()); - be_map_insert_bool(vm, "up", WifiHasIP()); - if (Settings->flag4.network_wifi) { - int32_t rssi = WiFi.RSSI(); - bool show_rssi = false; -#ifdef USE_IPV6 - String ipv6_addr = WifiGetIPv6Str(); - if (ipv6_addr != "") { - be_map_insert_str(vm, "ip6", ipv6_addr.c_str()); - show_rssi = true; - } - ipv6_addr = WifiGetIPv6LinkLocalStr(); - if (ipv6_addr != "") { - be_map_insert_str(vm, "ip6local", ipv6_addr.c_str()); - show_rssi = true; - } -#endif // USE_IPV6 - if (static_cast(WiFi.localIP()) != 0) { - be_map_insert_str(vm, "ip", IPAddress((uint32_t)WiFi.localIP()).toString().c_str()); // quick fix for IPAddress bug - show_rssi = true; - } - if (show_rssi) { - be_map_insert_int(vm, "rssi", rssi); - be_map_insert_int(vm, "quality", WifiGetRssiAsQuality(rssi)); - } - } - be_pop(vm, 1); - be_return(vm); + // (-2) map instance, (-1) map } - be_raise(vm, kTypeError, nullptr); + be_map_insert_str(vm, "mac", WiFi.macAddress().c_str()); + be_map_insert_bool(vm, "up", WifiHasIP()); + if (Settings->flag4.network_wifi) { + int32_t rssi = WiFi.RSSI(); + bool show_rssi = false; +#ifdef USE_IPV6 + String ipv6_addr = WifiGetIPv6Str(); + if (ipv6_addr != "") { + be_map_insert_str(vm, "ip6", ipv6_addr.c_str()); + show_rssi = true; + } + ipv6_addr = WifiGetIPv6LinkLocalStr(); + if (ipv6_addr != "") { + be_map_insert_str(vm, "ip6local", ipv6_addr.c_str()); + show_rssi = true; + } +#endif // USE_IPV6 + if (static_cast(WiFi.localIP()) != 0) { + be_map_insert_str(vm, "ip", IPAddress((uint32_t)WiFi.localIP()).toString().c_str()); // quick fix for IPAddress bug + show_rssi = true; + } + if (show_rssi) { + be_map_insert_int(vm, "rssi", rssi); + be_map_insert_int(vm, "quality", WifiGetRssiAsQuality(rssi)); + } + } + be_pop(vm, 1); + be_return(vm); } // Berry: tasmota.eth() -> map @@ -264,34 +276,38 @@ extern "C" { int32_t l_eth(struct bvm *vm); int32_t l_eth(struct bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments - if (top == 1) { // no argument (instance only) + if (top >= 1 && be_isstring(vm, 1)) { // argument is name + be_pushnil(vm); + be_pushvalue(vm, 1); + // (-2) nil, (-1) string -> if key matches then update (-2) + } else { be_newobject(vm, "map"); + // (-2) map instance, (-1) map + } #ifdef USE_ETHERNET - be_map_insert_bool(vm, "up", EthernetHasIP()); - String eth_mac = EthernetMacAddress().c_str(); - if (eth_mac != "00:00:00:00:00:00") { - be_map_insert_str(vm, "mac", eth_mac.c_str()); - } - if (static_cast(EthernetLocalIP()) != 0) { - be_map_insert_str(vm, "ip", IPAddress((uint32_t)EthernetLocalIP()).toString().c_str()); // quick fix for IPAddress bug - } + be_map_insert_bool(vm, "up", EthernetHasIP()); + String eth_mac = EthernetMacAddress().c_str(); + if (eth_mac != "00:00:00:00:00:00") { + be_map_insert_str(vm, "mac", eth_mac.c_str()); + } + if (static_cast(EthernetLocalIP()) != 0) { + be_map_insert_str(vm, "ip", IPAddress((uint32_t)EthernetLocalIP()).toString().c_str()); // quick fix for IPAddress bug + } #ifdef USE_IPV6 - String ipv6_addr = EthernetGetIPv6Str(); - if (ipv6_addr != "") { - be_map_insert_str(vm, "ip6", ipv6_addr.c_str()); - } - ipv6_addr = EthernetGetIPv6LinkLocalStr(); - if (ipv6_addr != "") { - be_map_insert_str(vm, "ip6local", ipv6_addr.c_str()); - } + String ipv6_addr = EthernetGetIPv6Str(); + if (ipv6_addr != "") { + be_map_insert_str(vm, "ip6", ipv6_addr.c_str()); + } + ipv6_addr = EthernetGetIPv6LinkLocalStr(); + if (ipv6_addr != "") { + be_map_insert_str(vm, "ip6local", ipv6_addr.c_str()); + } #endif // USE_IPV6 #else // USE_ETHERNET - be_map_insert_bool(vm, "up", bfalse); + be_map_insert_bool(vm, "up", bfalse); #endif // USE_ETHERNET - be_pop(vm, 1); - be_return(vm); - } - be_raise(vm, kTypeError, nullptr); + be_pop(vm, 1); + be_return(vm); } // Berry: tasmota.hostname() -> string From 151e201048d1aaa19c6c3263004ba76e6fb04bfc Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Tue, 9 Jan 2024 19:59:21 +0100 Subject: [PATCH 110/303] Update debug_panel (#20449) --- tasmota/berry/gpio_viewer/debug_panel.be | 90 +++++++++++++------ tasmota/berry/gpio_viewer/debug_panel.tapp | Bin 23076 -> 26546 bytes tasmota/berry/gpio_viewer/gpioviewer.be | 1 + tasmota/berry/gpio_viewer/webserver_async.be | 82 ++++++++++++++++- 4 files changed, 145 insertions(+), 28 deletions(-) diff --git a/tasmota/berry/gpio_viewer/debug_panel.be b/tasmota/berry/gpio_viewer/debug_panel.be index 12f7c1c2f..31759a72f 100644 --- a/tasmota/berry/gpio_viewer/debug_panel.be +++ b/tasmota/berry/gpio_viewer/debug_panel.be @@ -21,8 +21,6 @@ class debug_panel var port var web var sampling_interval - # - var payload1, payload2 # temporary object bytes() to avoid reallocation static var SAMPLING = 100 static var HTML_HEAD1 = @@ -73,8 +71,6 @@ class debug_panel self.port = port self.web = webserver_async(port) self.sampling_interval = self.SAMPLING - self.payload1 = bytes(100) # reserve 100 bytes by default - self.payload2 = bytes(100) # reserve 100 bytes by default self.web.set_chunked(true) self.web.set_cors(true) @@ -110,30 +106,74 @@ class debug_panel cnx.content_stop() end + static class feeder + var cnx # connection object + + def init(cnx) + self.cnx = cnx + tasmota.add_driver(self) + end + + def close() + tasmota.remove_driver(self) + end + + def every_100ms() + self.send_feed() + end + + def send_feed() + var cnx = self.cnx + if !cnx.connected() + self.close() + return + end + + var payload1 = self.cnx.server.payload1 + var payload2 = self.cnx.server.payload2 + var server = self.cnx.server + if cnx.buf_out_empty() + # if out buffer is not empty, do not send any new information + # var payload + # send free heap + payload1.clear() + payload1 .. "id:" + server.bytes_format_int(payload2, tasmota.millis()) + payload1 .. payload2 + payload1 .. "\r\nevent:free_heap\r\ndata:" + server.bytes_format_int(payload2, tasmota.memory('heap_free'), '---') + payload1 .. payload2 + payload1 .. " KB\r\n\r\n" + # payload = f"id:{tasmota.millis()}\r\n" + # "event:free_heap\r\n" + # "data:{tasmota.memory().find('heap_free', 0)} KB\r\n\r\n" + cnx.write(payload1) + + # send wifi rssi + payload1.clear() + payload1 .. "id:" + server.bytes_format_int(payload2, tasmota.millis()) + payload1 .. payload2 + payload1 .. "\r\nevent:wifi_rssi\r\ndata:" + server.bytes_format_int(payload2, tasmota.wifi('quality'), '--') + payload1 .. payload2 + payload1 .. "%\r\n\r\n" + + # payload = f"id:{tasmota.millis()}\r\n" + # "event:wifi_rssi\r\n" + # "data:{tasmota.wifi().find('quality', '--')}%\r\n\r\n" + cnx.write(payload1) + end + end + + end + def send_info_feed(cnx, uri, verb) cnx.set_chunked(false) # no chunking since we use EventSource cnx.send(200, "text/event-stream") - self.send_info_tick(cnx) - end - - def send_info_tick(cnx) - if cnx.buf_out_empty() - # if out buffer is not empty, do not send any new information - var payload - # send free heap - payload = f"id:{tasmota.millis()}\r\n" - "event:free_heap\r\n" - "data:{tasmota.memory().find('heap_free', 0)} KB\r\n\r\n" - cnx.write(payload) - - # send wifi rssi - payload = f"id:{tasmota.millis()}\r\n" - "event:wifi_rssi\r\n" - "data:{tasmota.wifi().find('quality', '--')}%\r\n\r\n" - cnx.write(payload) - end - - tasmota.set_timer(self.sampling_interval, def () self.send_info_tick(cnx) end) + # + var feed = feeder(cnx) + feed.send_feed() # send first values immediately end # Add button 'GPIO Viewer' redirects to '/part_wiz?' diff --git a/tasmota/berry/gpio_viewer/debug_panel.tapp b/tasmota/berry/gpio_viewer/debug_panel.tapp index 31c2f9fc4dbadc001c9a7fa5d179728476da45b4..f7a886133f616d9f9ce805df49345b005539dc8c 100644 GIT binary patch delta 3022 zcmc&$-ES0C6yJ9H0o&L{YNZuOPg!tx(ste57Q3mmrcfGa16{BJ70h~f=5Bjoc4nCm z+EtQGpG@?@$c^w+NRS6#Ow=_#nUJW7G4bO;)bqwf3JrxHuaMU7UTpcSrlROY8LAOY0x* z{XWe97?^C10`F>hO59evS{B1C1)|&4v+djcyEh_l4v57aQBZYa+i-&BZEBsTR!(Df zi8$&qwIb5JXXr+=xOpxxU8$K8yKJbDXe0^?%ghG+bCxL-2{U|D#{`w=x(D<_;*)Tj z$b%~Uz3CyIZF!9UI6YCll0MhW)yS?^xyEm7-o}5My-@AglWpen1N+kk$?FtM3otWz zt1i37S*k(N)F{NMT-P9928|Yot2+w66Pe+!b?i%eYxTbS=a0Sc0LQ703zdUZFHs8$ zuAw^2GysdBhALt)!=X#KL~K~5s}OffXs8k_C<0(R#9^w)0aJ0Pohz7DkvKWDjOT}d z4b{>^V}N`@)hV&!!WDoOAkJW70t{Bs6|oG7MBpF{Eb6$H0hoy<9im_pgE?iujZ)9n zVeEyZ@CQVLVJ7YZ7cWMz9stU9VFn0UqAIHp9XHLUfceAWLq`rBS*U}@6eWH>VNsjC zO5-V+?WyF;7%#axl0={Y8UssM|5>sU-#L=psYE1V4I|@`aGqG8(~2RGq`}HE!<}a^ z=|2Mq6OAn~2W=QUjS-VG($u5STiOe$q=zWV%AeAyQOj=7bN78HiqXHV8CGN+W8hmN zEm+o=tZp;~@z_*MfnkggK=>O1n7RRj6Oan>K^NT9$w?UXk_q-9iUeV!A;YGnVVB7y z13Gp3xZ#-#cBEOHmpTqVoGMYE2zNgv;_4$Qv0jK3*;yjhy4{tji!Cwe5{myk#gb(c z%Y{dfXq~@fxfG)WWCfzFc&ZM9-=*6BTC|nBRhyF1M|~8@Du`Z?9W#=KJacdu8hD8f zr&FV2qnVLsN5^6{wuDd~R^q#TrB#rV2Pyg9;(Mmn33Yr1WXpUSP}9@?y9PArI)d^4 zM!5IXEq|+XxH_HrW>aU+Rpn&I+|5#dUntby$NQ)H+JD7E>-MGf>hn`)!qwIT-?moS z+(5YB*ROXl6(|jwL?}%)R{2^>bP^9E(=ezvq0Rgmyz_>Nn7<4sV;n7mAz)LzkichT z9j{m;Ke1W}dk)Z#&!E0lY zC&qi5F>iM~%4d4I`Ir6Oyr^ueU@izD4&6kFly#G6!R!!~`mfTMbddjFtkeE(32P7M zZd>03+ek#qyM>(TIyqV_Ib~j&-^^F$XSRr)t&1r5`D%U#e@E%#x0J3|m^QxChY@wl zd>c+UF;{|Yhrl6r(R4_n$aI|{VZkOqP*F-8ZGpWAc2n6}L5>Y)ykJp^2PP?iO0PC&+#A#BCr;n;n1*(BH(d}1=)Pr}?jk%0K$s65JV%_p0pd`nir zYbHC#*RtJhDS4Lh%h~^huN78cIm@=$zv4@v#AD}NqT>gJ&(-~@l1znts(N;B5LMGi zz|=32skWmB1yfBaezfO_b~F-Q!e2jf`K74z5Xuuhgxd9beWP>5bA6NH4Dx??wjc}? zm}NVtUEQTPaf?N&G2&3YT>bQDYioGzn8Lp}KG6PI*E;>YYrT5=c&fRx@za?PE)ItA z+nK+=xINQ2p+cd~P_O*j7MJU5KjXKyM)U4cu0#x~C-U^gh1O6QXP9u7!Ma=_*wN8%%)TS%kK$1p)OZVX=aB delta 644 zcmdmVo^i<*Mu`A#W)?065D49-5i#SM@#)+}(G7KrHNu}xW1&Mj7IeJN{p&^_M%pZ#8q<$)z zvsuhLi+OUjiT31;Cia{A{0^{A?lzyc*)K$qd2&qL6!GHJoHV`S)V!4V%)GSx_>#=z zY>ni+ipjB|l3Xy3CfDTJNX5wuB3(4f5{ncH5-W4^6H~Ypz(836q+21aC^c0fBQ>!A zB0RZ0)?o6qXtl`)qCG@_=INCeWtOCBK(%UeaZOf?k)7NTt3P>nEJ%^~;Rh21va)Mu{bxsBoXM|5}-?SQ;Rep&QHuO$jQu02YR6-wWusHM@JzgHBCW76X-Oo zzS9I5sR=X^YO=C|V@irb(&p&+FD%+>JAm=G{^V&8UFlTdBiXjspYJ^YTnWoJQjPc3V=`t3WaU}sxBOqc)BfBF5M$EB-V-BR58R(G7 bQR&j++rt=89RO4Vbim}EbOkoSNRUwg$Zy$= diff --git a/tasmota/berry/gpio_viewer/gpioviewer.be b/tasmota/berry/gpio_viewer/gpioviewer.be index 91df7624b..58bb566a9 100644 --- a/tasmota/berry/gpio_viewer/gpioviewer.be +++ b/tasmota/berry/gpio_viewer/gpioviewer.be @@ -125,6 +125,7 @@ class GPIO_viewer def send_events_page(cnx, uri, verb) cnx.set_chunked(false) # no chunking since we use EventSource + cnx.set_cors(true) cnx.send(200, "text/event-stream") self.send_events_tick(cnx) diff --git a/tasmota/berry/gpio_viewer/webserver_async.be b/tasmota/berry/gpio_viewer/webserver_async.be index 2801484ed..fadbb3196 100644 --- a/tasmota/berry/gpio_viewer/webserver_async.be +++ b/tasmota/berry/gpio_viewer/webserver_async.be @@ -28,6 +28,9 @@ #@ solidify:webserver_async #@ solidify:Webserver_async_cnx +############################################################# +# class Webserver_async_cnx +############################################################# class Webserver_async_cnx var server # link to server object var cnx # holds the tcpclientasync instance @@ -46,7 +49,7 @@ class Webserver_async_cnx var resp_headers var resp_version var chunked # if true enable chunked encoding (default true) - var cors # if true send CORS headers (default true) + var cors # if true send CORS headers (default false) # bytes objects to be reused var payload1 # conversion @@ -79,7 +82,7 @@ class Webserver_async_cnx self.resp_headers = '' self.resp_version = 1 # HTTP 1.1 # TODO self.chunked = true - self.cors = true + self.cors = false # register cb self.fastloop_cb = def () self.loop() end tasmota.add_fast_loop(self.fastloop_cb) @@ -384,6 +387,9 @@ class Webserver_async_cnx end end +############################################################# +# class Webserver_dispatcher +############################################################# class Webserver_dispatcher var uri_prefix # prefix string, must start with '/' var verb # verb to match, or nil for ANY @@ -412,6 +418,11 @@ class Webserver_dispatcher end end +############################################################# +# class webserver_async +# +# This is the main class to call +############################################################# class webserver_async var local_port # listening port, 80 is already used by Tasmota var server # instance of `tcpserver` @@ -424,7 +435,9 @@ class webserver_async var dispatchers # copied in each connection var chunked # if true enable chunked encoding (default true) - var cors # if true send CORS headers (default true) + var cors # if true send CORS headers (default false) + # + var payload1, payload2 # temporary object bytes() to avoid reallocation static var TIMEOUT = 1000 # default timeout: 1000ms static var HTTP_REQ = "^(\\w+) (\\S+) HTTP\\/(\\d\\.\\d)\r\n" @@ -438,6 +451,10 @@ class webserver_async self.connections = [] self.dispatchers = [] self.server = tcpserver(port) # throws an exception if port is not available + self.chunked = true + self.cors = false + self.payload1 = bytes(100) # reserve 100 bytes by default + self.payload2 = bytes(100) # reserve 100 bytes by default # TODO what about max_clients ? self.compile_re() # register cb @@ -457,14 +474,73 @@ class webserver_async end end + ############################################################# + # enable or disable chunked mode (enabled by default) def set_chunked(chunked) self.chunked = bool(chunked) end + ############################################################# + # enable or disable CORS mode (enabled by default) def set_cors(cors) self.cors = bool(cors) end + ############################################################# + # Helper function to encode integer as hex (uppercase) + static def bytes_format_hex(b, i, default) + b.clear() + if (i == nil) b .. default return end + # sanity check + if (i < 0) i = -i end + if (i < 0) return end # special case for MININT + if (i == 0) b.resize(1) b[0] = 0x30 return end # return bytes("30") + + b.resize(8) + var len = 0 + while i > 0 + var digit = i & 0x0F + if (digit < 10) + b[len] = 0x30 + digit + else + b[len] = 0x37 + digit # 0x37 = 0x41 ('A') - 10 + end + len += 1 + i = (i >> 4) + end + # reverse order + b.resize(len) + b.reverse() + end + + ############################################################# + # Helper function to encode integer as int + static def bytes_format_int(b, i, default) + b.clear() + if (i == nil) b .. default return end + var negative = false + # sanity check + if (i < 0) i = -i negative = true end + if (i < 0) return end # special case for MININT + if (i == 0) b.resize(1) b[0] = 0x30 return end # return bytes("30") + + b.resize(11) # max size for 32 bits ints '-2147483647' + var len = 0 + while i > 0 + var digit = i % 10 + b[len] = 0x30 + digit + len += 1 + i = (i / 10) + end + if negative + b[len] = 0x2D + len += 1 + end + # reverse order + b.resize(len) + b.reverse() + end + ############################################################# # closing web server def close() From c00e82171ed1ceb81fbd02d9c2d912a7698c02c9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 9 Jan 2024 20:49:38 +0100 Subject: [PATCH 111/303] platform updates to 2024.01.x0 (#20445) * platform updates to 2024.01.x0 * core uses async udp now --- platformio_tasmota32.ini | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 13b6f35e6..95f4fc058 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -39,7 +39,6 @@ build_flags = ${esp_defaults.build_flags} lib_ignore = HTTPUpdateServer USB - ESP32 Async UDP esp-nimble-cpp NetBIOS Preferences @@ -93,13 +92,13 @@ lib_ignore = [core32] -platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.12.00/platform-espressif32.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.00/platform-espressif32.zip platform_packages = build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} [core32_30] -platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.12.10/platform-espressif32.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.10/platform-espressif32.zip platform_packages = build_unflags = ${core32.build_unflags} build_flags = ${core32.build_flags} From fa959d9f47c922c3fa6b3741a809fc856efc2bba Mon Sep 17 00:00:00 2001 From: btsimonh Date: Tue, 9 Jan 2024 21:06:22 +0000 Subject: [PATCH 112/303] Webcam v2 tweaks 2024 (#20451) * suppress compiler warning about 'used' function * don't stop and start cam webserver every time we save to flash. Only stop the actual cam clock. * change cmds WcMenuVideoon and wcmenuvideooff to be wcmenuvideodisable 0/1 to be more TAS like, and save a little. --- .../xdrv_81_esp32_webcam_task.ino | 36 +++++++++---------- .../xdrv_81_esp32_webcam_task_motion.ino | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam_task.ino b/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam_task.ino index 77636cf8b..9ec245ce0 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam_task.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam_task.ino @@ -108,8 +108,8 @@ As soon as the screenshare ended, back to 53fps at 30mhz clock. * background(4) * e.g. could be used to read pixels, or change pixels from berry. - * WcMenuvideoon = turn on video in main menu - * WcMenuvideooff = turn off video in main menu + * WcMenuvideodisable 0 = turn on video in main menu + * WcMenuvideodisable 1 = turn off video in main menu * WcSetOptionsNN = call WcSetOptions function with (index, payload). * - can oprate many of the functions above, plus: @@ -701,7 +701,9 @@ void WcInterrupt(uint32_t state) { // Stop camera ISR if active to fix TG1WDT_SYS_RESET if (!Wc.up) { return; } - WcSetStreamserver(state); + // why stop/start the server itself here? + // stopping the cam interrupt should be enough? + //WcSetStreamserver(state); if (state) { // Re-enable interrupts cam_start(); @@ -1589,7 +1591,9 @@ uint32_t WcSetStreamserver(uint32_t flag) { WcEndStream(); return 0; } - +#ifdef WEBCAM_DEV_DEBUG + AddLog(LOG_LEVEL_DEBUG, PSTR("WcSetStreamserver %d"), flag); +#endif if (flag) { if (!Wc.CamServer) { TasAutoMutex localmutex(&WebcamMutex, "HandleWebcamMjpeg", 20000); @@ -2251,7 +2255,7 @@ void WcShowStream(void) { WSContentSend_P(HTTP_WEBCAM_MENUVIDEOCONTROL, "wcinit", "Try WCINIT"); } else { if (Settings->webcam_config.spare15) { - WSContentSend_P(HTTP_WEBCAM_MENUVIDEOCONTROL, "wcmenuvideoon", "Turn On Video"); + WSContentSend_P(HTTP_WEBCAM_MENUVIDEOCONTROL, "wcmenuvideodisable%200", "Turn On Video"); } } } @@ -2260,7 +2264,7 @@ void WcShowStream(void) { if (!Settings->webcam_config.spare15 && Settings->webcam_config.stream && Wc.CamServer && Wc.up!=0) { // Give the webcam webserver some time to prepare the stream - catch error in JS WSContentSend_P(PSTR("

Webcam stream

"),(uint32_t)WiFi.localIP()); - WSContentSend_P(HTTP_WEBCAM_MENUVIDEOCONTROL, "wcmenuvideooff", "Turn Off Video"); + WSContentSend_P(HTTP_WEBCAM_MENUVIDEOCONTROL, "wcmenuvideodisable%201", "Turn Off Video"); } } @@ -2331,8 +2335,7 @@ void WcInit(void) { #define D_CMND_WC_STARTTASK "Starttask" #define D_CMND_WC_STOPTASK "Stoptask" -#define D_CMND_WC_MENUVIDEOOFF "Menuvideooff" -#define D_CMND_WC_MENUVIDEOON "Menuvideoon" +#define D_CMND_WC_MENUVIDEODISABLE "MenuVideoDisable" // for testing to see what happens after cam_stop() #define D_CMND_WC_INTERRUPT "Interrupt" @@ -2363,7 +2366,7 @@ const char kWCCommands[] PROGMEM = D_PRFX_WEBCAM "|" // Prefix D_CMND_WC_AGC_GAIN "|" D_CMND_WC_GAINCEILING "|" D_CMND_WC_RAW_GMA "|" D_CMND_WC_LENC "|" D_CMND_WC_WPC "|" D_CMND_WC_DCW "|" D_CMND_WC_BPC "|" D_CMND_WC_COLORBAR "|" D_CMND_WC_FEATURE "|" D_CMND_WC_SETDEFAULTS "|" D_CMND_WC_STATS "|" D_CMND_WC_INIT "|" D_CMND_WC_AUTH "|" D_CMND_WC_CLK "|" - D_CMND_WC_STARTTASK "|" D_CMND_WC_STOPTASK "|" D_CMND_WC_MENUVIDEOOFF "|" D_CMND_WC_MENUVIDEOON "|" + D_CMND_WC_STARTTASK "|" D_CMND_WC_STOPTASK "|" D_CMND_WC_MENUVIDEODISABLE "|" D_CMND_WC_INTERRUPT "|" D_CMND_WC_GETFRAME "|" D_CMND_WC_GETPICSTORE "|" #ifdef USE_WEBCAM_MOTION D_CMND_WC_SETMOTIONDETECT "|" D_CMND_WC_GETMOTIONPIXELS "|" @@ -2385,7 +2388,7 @@ void (* const WCCommand[])(void) PROGMEM = { &CmndWebcamGammaCorrect, &CmndWebcamLensCorrect, &CmndWebcamWPC, &CmndWebcamDCW, &CmndWebcamBPC, &CmndWebcamColorbar, &CmndWebcamFeature, &CmndWebcamSetDefaults, &CmndWebcamStats, &CmndWebcamInit, &CmndWebcamAuth, &CmndWebcamClock, - &CmndWebcamStartTask, &CmndWebcamStopTask, &CmndWebcamMenuVideoOff, &CmndWebcamMenuVideoOn, + &CmndWebcamStartTask, &CmndWebcamStopTask, &CmndWebcamMenuVideoDisable, &CmndWebcamCamStartStop, &CmndWebcamGetFrame, &CmndWebcamGetPicStore, #ifdef USE_WEBCAM_MOTION &CmndWebcamSetMotionDetect, &CmndWebcamGetMotionPixels, @@ -2412,7 +2415,7 @@ void CmndWebcam(void) { D_CMND_WC_AGC_GAIN "\":%d,\"" D_CMND_WC_GAINCEILING "\":%d,\"" D_CMND_WC_RAW_GMA "\":%d,\"" D_CMND_WC_LENC "\":%d,\"" D_CMND_WC_WPC "\":%d,\"" D_CMND_WC_DCW "\":%d,\"" D_CMND_WC_BPC "\":%d,\"" D_CMND_WC_COLORBAR "\":%d,\"" D_CMND_WC_FEATURE "\":%d,\"" D_CMND_WC_AUTH "\":%d,\"" D_CMND_WC_CLK "\":%d,\"" - D_CMND_WC_MENUVIDEOOFF "\":%d" + D_CMND_WC_MENUVIDEODISABLE "\":%d" #ifdef ENABLE_RTSPSERVER ",\"" D_CMND_RTSP "\":%d" #endif // ENABLE_RTSPSERVER @@ -2620,13 +2623,10 @@ void CmdWebcamAppendPic(){ WebcamSavePic(1)? ResponseCmndDone(): ResponseCmndError(); } -void CmndWebcamMenuVideoOff(void) { - Settings->webcam_config.spare15 = 1; - ResponseCmndStateText(Settings->webcam_config.spare15); -} - -void CmndWebcamMenuVideoOn(void) { - Settings->webcam_config.spare15 = 0; +void CmndWebcamMenuVideoDisable(void) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + Settings->webcam_config.spare15 = XdrvMailbox.payload; + } ResponseCmndStateText(Settings->webcam_config.spare15); } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam_task_motion.ino b/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam_task_motion.ino index 8384a7485..49c112350 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam_task_motion.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_81_esp32_webcam_task_motion.ino @@ -544,7 +544,6 @@ bool wc_jpg2rgb888(const uint8_t *src, size_t src_len, struct PICSTORE * out, in } return true; } -#endif bool wc_jpg2rgb565(const uint8_t *src, size_t src_len, struct PICSTORE * out, int scale) @@ -561,6 +560,7 @@ bool wc_jpg2rgb565(const uint8_t *src, size_t src_len, struct PICSTORE * out, in } return true; } +#endif // general jpeg to pixel conversion From 345de0aded09dab9c457a1528ad30a492e343b53 Mon Sep 17 00:00:00 2001 From: Gregory Holder <30503300+blueted2@users.noreply.github.com> Date: Tue, 9 Jan 2024 22:07:30 +0100 Subject: [PATCH 113/303] [Thermostat] Save and restore XdrvMailbox if output relay is switched off (#20405) --- tasmota/tasmota_xdrv_driver/xdrv_39_thermostat.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_39_thermostat.ino b/tasmota/tasmota_xdrv_driver/xdrv_39_thermostat.ino index 3e32ca7dc..a2cbe27fe 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_39_thermostat.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_39_thermostat.ino @@ -1442,7 +1442,9 @@ void CmndThermostatModeSet(void) // Make sure the relay is switched to off once if the thermostat is being disabled, // or it will get stuck on (danger!) Thermostat[ctr_output].status.command_output = IFACE_OFF; + struct XDRVMAILBOX save_XdrvMailbox = XdrvMailbox; ThermostatOutputRelay(ctr_output, Thermostat[ctr_output].status.command_output); + XdrvMailbox = save_XdrvMailbox; } if ((value > THERMOSTAT_OFF) && (value < THERMOSTAT_MODES_MAX)) { DebugControllerParameters(ctr_output); From 453a3462b7ea8186374c173337c03c9666ae6f23 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Tue, 9 Jan 2024 22:30:38 +0100 Subject: [PATCH 114/303] Fixed Zigbee Aqara attributes on ESP32 (#20452) --- CHANGELOG.md | 1 + .../xdrv_23_zigbee_5_2_converters.ino | 61 ++++++++----------- 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e09349d4..d521e1e5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ All notable changes to this project will be documented in this file. - Header `Host` is now collected by Webserver ### Fixed +- Fixed Zigbee Aqara attributes on ESP32 ### Removed diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_2_converters.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_2_converters.ino index 67929f758..4fc87f19a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_2_converters.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_2_converters.ino @@ -1304,42 +1304,36 @@ void ZCLFrame::syntheticAqaraCubeOrButton(class Z_attribute_list &attr_list, cla if (modelId.startsWith(F("lumi.sensor_cube"))) { // only for Aqara cube int32_t val = attr.getInt(); -#ifdef ESP8266 - const __FlashStringHelper *aqara_cube = F("AqaraCube"); - const __FlashStringHelper *aqara_cube_side = F("AqaraCubeSide"); - const __FlashStringHelper *aqara_cube_from_side = F("AqaraCubeFromSide"); -#else - const char *aqara_cube = "AqaraCube"; - const char *aqara_cube_side = "AqaraCubeSide"; - const char *aqara_cube_from_side = "AqaraCubeFromSide"; -#endif + static const char *aqara_cube = PSTR("AqaraCube"); + static const char *aqara_cube_side = PSTR("AqaraCubeSide"); + static const char *aqara_cube_from_side = PSTR("AqaraCubeFromSide"); switch (val) { case 0: - attr_list.addAttribute(aqara_cube).setStr(PSTR("shake")); + attr_list.addAttributePMEM(aqara_cube).setStr(PSTR("shake")); break; case 2: - attr_list.addAttribute(aqara_cube).setStr(PSTR("wakeup")); + attr_list.addAttributePMEM(aqara_cube).setStr(PSTR("wakeup")); break; case 3: - attr_list.addAttribute(aqara_cube).setStr(PSTR("fall")); + attr_list.addAttributePMEM(aqara_cube).setStr(PSTR("fall")); break; case 64 ... 127: - attr_list.addAttribute(aqara_cube).setStr(PSTR("flip90")); - attr_list.addAttribute(aqara_cube_side).setInt(val % 8); - attr_list.addAttribute(aqara_cube_from_side).setInt((val - 64) / 8); + attr_list.addAttributePMEM(aqara_cube).setStr(PSTR("flip90")); + attr_list.addAttributePMEM(aqara_cube_side).setInt(val % 8); + attr_list.addAttributePMEM(aqara_cube_from_side).setInt((val - 64) / 8); break; case 128 ... 132: - attr_list.addAttribute(aqara_cube).setStr(PSTR("flip180")); - attr_list.addAttribute(aqara_cube_side).setInt(val - 128); + attr_list.addAttributePMEM(aqara_cube).setStr(PSTR("flip180")); + attr_list.addAttributePMEM(aqara_cube_side).setInt(val - 128); break; case 256 ... 261: - attr_list.addAttribute(aqara_cube).setStr(PSTR("slide")); - attr_list.addAttribute(aqara_cube_side).setInt(val - 256); + attr_list.addAttributePMEM(aqara_cube).setStr(PSTR("slide")); + attr_list.addAttributePMEM(aqara_cube_side).setInt(val - 256); break; case 512 ... 517: - attr_list.addAttribute(aqara_cube).setStr(PSTR("tap")); - attr_list.addAttribute(aqara_cube_side).setInt(val - 512); + attr_list.addAttributePMEM(aqara_cube).setStr(PSTR("tap")); + attr_list.addAttributePMEM(aqara_cube_side).setInt(val - 512); break; } attr_list.removeAttribute(&attr); @@ -1363,26 +1357,21 @@ void ZCLFrame::syntheticAqaraCubeOrButton(class Z_attribute_list &attr_list, cla // presentValue = x + 512 = double tap while side x is on top } else if (modelId.startsWith(F("lumi.remote")) || modelId.startsWith(F("lumi.sensor_swit"))) { // only for Aqara buttons WXKG11LM & WXKG12LM, 'swit' because of #9923 int32_t val = attr.getInt(); -#ifdef ESP8266 - const __FlashStringHelper *aqara_click = F("click"); // deprecated - const __FlashStringHelper *aqara_action = F("action"); // deprecated -#else - const char *aqara_click = "click"; // deprecated - const char *aqara_action = "action"; // deprecated -#endif + static const char *aqara_click = PSTR("click"); // deprecated + static const char *aqara_action = PSTR("action"); // deprecated Z_attribute & attr_click = attr_list.addAttribute(PSTR("Click"), true); switch (val) { case 0: - attr_list.addAttribute(aqara_action).setStr(PSTR("hold")); // deprecated + attr_list.addAttributePMEM(aqara_action).setStr(PSTR("hold")); // deprecated attr_click.setStr(PSTR("hold")); break; case 1: - attr_list.addAttribute(aqara_click).setStr(PSTR("single")); // deprecated + attr_list.addAttributePMEM(aqara_click).setStr(PSTR("single")); // deprecated attr_click.setStr(PSTR("single")); break; case 2: - attr_list.addAttribute(aqara_click).setStr(PSTR("double")); // deprecated + attr_list.addAttributePMEM(aqara_click).setStr(PSTR("double")); // deprecated attr_click.setStr(PSTR("double")); break; case 3: @@ -1392,23 +1381,23 @@ void ZCLFrame::syntheticAqaraCubeOrButton(class Z_attribute_list &attr_list, cla attr_click.setStr(PSTR("quadruple")); break; case 16: - attr_list.addAttribute(aqara_action).setStr(PSTR("hold")); // deprecated + attr_list.addAttributePMEM(aqara_action).setStr(PSTR("hold")); // deprecated attr_click.setStr(PSTR("hold")); break; case 17: - attr_list.addAttribute(aqara_action).setStr(PSTR("release")); // deprecated + attr_list.addAttributePMEM(aqara_action).setStr(PSTR("release")); // deprecated attr_click.setStr(PSTR("release")); break; case 18: - attr_list.addAttribute(aqara_action).setStr(PSTR("shake")); // deprecated + attr_list.addAttributePMEM(aqara_action).setStr(PSTR("shake")); // deprecated attr_click.setStr(PSTR("shake")); break; case 255: - attr_list.addAttribute(aqara_action).setStr(PSTR("release")); // deprecated + attr_list.addAttributePMEM(aqara_action).setStr(PSTR("release")); // deprecated attr_click.setStr(PSTR("release")); break; default: - attr_list.addAttribute(aqara_click).setUInt(val); + attr_list.addAttributePMEM(aqara_click).setUInt(val); attr_click.setStr(PSTR("release")); break; } From edda5ddc3312034ec9184410002662c63c54e29a Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Wed, 10 Jan 2024 09:08:11 +0100 Subject: [PATCH 115/303] Berry `tasmota.webcolor` (#20454) --- CHANGELOG.md | 1 + .../berry_tasmota/src/be_tasmota_lib.c | 3 +++ .../xdrv_52_3_berry_tasmota.ino | 27 +++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d521e1e5c..556181f29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file. - Berry `debug_panel.tapp` to display real-time heap and wifi rssi - Berry `webserver.header` to read browser sent headers - Berry provide lightweight options for `tasmota.wifi/eth/memory/rtc` +- Berry `tasmota.webcolor` ### Breaking Changed diff --git a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c index 528a3b8b8..54449644d 100644 --- a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c @@ -56,6 +56,8 @@ extern int l_respAppend(bvm *vm); extern int l_webSend(bvm *vm); extern int l_webSendDecimal(bvm *vm); +extern int l_webcolor(bvm *vm); + extern int l_getlight(bvm *vm); extern int l_setlight(bvm *vm); extern int l_getpower(bvm *vm); @@ -143,6 +145,7 @@ class be_class_tasmota (scope: global, name: Tasmota) { response_append, func(l_respAppend) web_send, func(l_webSend) web_send_decimal, func(l_webSendDecimal) + webcolor, static_func(l_webcolor) get_power, func(l_getpower) set_power, func(l_setpower) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino index f82bb0fb9..563abacef 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino @@ -820,6 +820,33 @@ extern "C" { be_raise(vm, kTypeError, nullptr); } + // get webcolors + int32_t l_webcolor(bvm *vm); + int32_t l_webcolor(bvm *vm) { + char tmp[16]; + int32_t top = be_top(vm); // Get the number of arguments + if (top >= 1 && be_isint(vm, 1)) { // argument is int + int32_t idx = be_toint(vm, 1); + if (idx >= 0 && idx < COL_LAST) { + snprintf_P(tmp, sizeof(tmp), PSTR("#%06x"), WebColor(idx)); + be_pushstring(vm, tmp); + be_return(vm); + } else { + be_return_nil(vm); + } + } else { + be_newobject(vm, "list"); + for (uint32_t i = 0; i < COL_LAST; i++) { + snprintf_P(tmp, sizeof(tmp), PSTR("#%06x"), WebColor(i)); + be_pushstring(vm, tmp); + be_data_push(vm, -2); + be_pop(vm, 1); + } + be_pop(vm, 1); + be_return(vm); + } + } + // get power int32_t l_getpower(bvm *vm); int32_t l_getpower(bvm *vm) { From 0b509f60b439d1ae0b438124e9bf197879aacf2a Mon Sep 17 00:00:00 2001 From: chefpro Date: Wed, 10 Jan 2024 09:21:02 +0100 Subject: [PATCH 116/303] Add support for pipsolar inverter (#20408) * Add support for pipsolar inverter * Fix CI-Warnings * Remove unneeded define * Pipsolar: Fix dat result * Add support for the rules engine --------- Co-authored-by: Peter Rustler --- CODE_OWNERS.md | 1 + tasmota/berry/include/be_gpio_defines.h | 2 + tasmota/include/i18n.h | 13 + tasmota/include/tasmota_template.h | 7 + tasmota/language/af_AF.h | 4 + tasmota/language/bg_BG.h | 4 + tasmota/language/ca_AD.h | 4 + tasmota/language/cs_CZ.h | 4 + tasmota/language/de_DE.h | 4 + tasmota/language/el_GR.h | 4 + tasmota/language/en_GB.h | 4 + tasmota/language/es_ES.h | 4 + tasmota/language/fr_FR.h | 4 + tasmota/language/fy_NL.h | 4 + tasmota/language/he_HE.h | 4 + tasmota/language/hu_HU.h | 4 + tasmota/language/it_IT.h | 4 + tasmota/language/ko_KO.h | 4 + tasmota/language/nl_NL.h | 4 + tasmota/language/pl_PL.h | 4 + tasmota/language/pt_BR.h | 4 + tasmota/language/pt_PT.h | 4 + tasmota/language/ro_RO.h | 4 + tasmota/language/ru_RU.h | 4 + tasmota/language/sk_SK.h | 4 + tasmota/language/sv_SE.h | 4 + tasmota/language/tr_TR.h | 4 + tasmota/language/uk_UA.h | 4 + tasmota/language/vi_VN.h | 4 + tasmota/language/zh_CN.h | 4 + tasmota/language/zh_TW.h | 4 + .../tasmota_xdrv_driver/xdrv_92_pipsolar.ino | 1050 +++++++++++++++++ tools/lv_gpio/lv_gpio_enum.h | 2 + 33 files changed, 1183 insertions(+) create mode 100644 tasmota/tasmota_xdrv_driver/xdrv_92_pipsolar.ino diff --git a/CODE_OWNERS.md b/CODE_OWNERS.md index b0d05100f..56a053548 100644 --- a/CODE_OWNERS.md +++ b/CODE_OWNERS.md @@ -100,6 +100,7 @@ In addition to @arendst the following code is mainly owned by: | xdrv_88_esp32_shelly_pro | @arendst | xdrv_89_esp32_dali | @eeak | xdrv_90_esp32_dingtian_relay | @barbudor +| xdrv_92_pipsolar | @chefpro | | | xdrv_122_file_settings_demo | @arendst | xdrv_127_debug | @arendst diff --git a/tasmota/berry/include/be_gpio_defines.h b/tasmota/berry/include/be_gpio_defines.h index 4f6ccde55..452a5414b 100644 --- a/tasmota/berry/include/be_gpio_defines.h +++ b/tasmota/berry/include/be_gpio_defines.h @@ -334,6 +334,8 @@ const be_const_member_t lv_gpio_constants[] = { { "ZIGBEE_RST", (int32_t) GPIO_ZIGBEE_RST }, { "ZIGBEE_RX", (int32_t) GPIO_ZIGBEE_RX }, { "ZIGBEE_TX", (int32_t) GPIO_ZIGBEE_TX }, + { "PIPSOLAR_RX", (int32_t) GPIO_PIPSOLAR_RX }, + { "PIPSOLAR_TX", (int32_t) GPIO_PIPSOLAR_TX }, }; diff --git a/tasmota/include/i18n.h b/tasmota/include/i18n.h index e5cdb2f61..481456201 100644 --- a/tasmota/include/i18n.h +++ b/tasmota/include/i18n.h @@ -809,6 +809,19 @@ // xsns_71_veml7700.ino #define D_JSON_WHITE_CONTENT "WhiteContent" +// xdrv_92_pipsolar.ino +#define D_CMND_PIP_PREFIX "PipSolar" +#define D_CMND_PIP_QT "QT" +#define D_CMND_PIP_QET "QET" +#define D_CMND_PIP_QEY "QEY" +#define D_CMND_PIP_QEM "QEM" +#define D_CMND_PIP_QED "QED" +#define D_CMND_PIP_QEH "QEH" +#define D_CMND_PIP_DAT "DAT" +#define D_CMND_PIP_POLLVALUES "PollValues" +#define D_CMND_PIP_BAUDRATE "BaudRate" +#define D_CMND_PIP_SERIALCONFIG "SerialConfig" + /********************************************************************************************/ // Log message prefix diff --git a/tasmota/include/tasmota_template.h b/tasmota/include/tasmota_template.h index 1d09cb47b..340d1ab21 100644 --- a/tasmota/include/tasmota_template.h +++ b/tasmota/include/tasmota_template.h @@ -215,6 +215,7 @@ enum UserSelectablePins { GPIO_HC8_RXD, // HC8 Serial interface GPIO_I2S_DAC, // Audio DAC support for ESP32 and ESP32S2 GPIO_MAGIC_SWITCH, // MagicSwitch as in Sonoff BasicR4 + GPIO_PIPSOLAR_TX, GPIO_PIPSOLAR_RX, // pipsolar inverter GPIO_SENSOR_END }; // Error as warning to rethink GPIO usage with max 2045 @@ -477,6 +478,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_HC8_RX "|" D_SENSOR_I2S_DAC "|" D_GPIO_MAGIC_SWITCH "|" + D_SENSOR_PIPSOLAR_TX "|" D_SENSOR_PIPSOLAR_RX "|" ; const char kSensorNamesFixed[] PROGMEM = @@ -1150,6 +1152,11 @@ const uint16_t kGpioNiceList[] PROGMEM = { AGPIO(GPIO_MAGIC_SWITCH) + MAX_MAGIC_SWITCH_MODES, #endif +#ifdef USE_PIPSOLAR // xdrv_92_pipsolar.ino + AGPIO(GPIO_PIPSOLAR_TX), // pipsolar inverter Serial interface + AGPIO(GPIO_PIPSOLAR_RX), // pipsolar inverter Serial interface +#endif + /*-------------------------------------------------------------------------------------------*\ * ESP32 specifics \*-------------------------------------------------------------------------------------------*/ diff --git a/tasmota/language/af_AF.h b/tasmota/language/af_AF.h index 406c96c45..7224bd8db 100644 --- a/tasmota/language/af_AF.h +++ b/tasmota/language/af_AF.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "Gemiddelde Stralingsdosis" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_AF_AF_H_ diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index 8d02d6967..54e5b9e52 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "средна доза радиация" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_BG_BG_H_ diff --git a/tasmota/language/ca_AD.h b/tasmota/language/ca_AD.h index 55fe18f99..086e9c732 100644 --- a/tasmota/language/ca_AD.h +++ b/tasmota/language/ca_AD.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "dosi mitjana de radiació" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_CA_AD_H_ diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index 71453c987..1de0dea2a 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "průměrná dávka záření" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_CS_CZ_H_ diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index c4a3ce265..8c5c5e0f6 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "durchschnittliche Strahlendosis" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_DE_DE_H_ diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h index 7efd379ca..ca6c28fd9 100644 --- a/tasmota/language/el_GR.h +++ b/tasmota/language/el_GR.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "μέση δόση ακτινοβολίας" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_EL_GR_H_ diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index 8d82a9408..720f1f169 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -1224,4 +1224,8 @@ #define D_AVG_RAD_DOSE "Radiation" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_EN_GB_H_ diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h index 9e6c0ed8d..bc8e5728f 100644 --- a/tasmota/language/es_ES.h +++ b/tasmota/language/es_ES.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "dosis media de radiación" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_ES_ES_H_ diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index c1063146d..1c3fe23fe 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -1224,4 +1224,8 @@ #define D_AVG_RAD_DOSE "dose moyenne de rayonnement" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_FR_FR_H_ diff --git a/tasmota/language/fy_NL.h b/tasmota/language/fy_NL.h index fcf0973a2..917fa9704 100644 --- a/tasmota/language/fy_NL.h +++ b/tasmota/language/fy_NL.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "gemiddelde stralingsdosis" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_FY_NL_H_ diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index fc74df7ff..978149adc 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "מינון קרינה ממוצע" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_HE_HE_H_ diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index 8592a911e..58fd37d0d 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -1226,4 +1226,8 @@ #define D_AVG_RAD_DOSE "átlagos sugárdózis" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_HU_HU_H_ diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index b35a353af..75a216e10 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "Radiazioni" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_IT_IT_H_ diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index e0b6871f6..c02ce1fc1 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "average radiation dose" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_KO_KO_H_ diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index 6cd4b2c2b..a5dbe04aa 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "gemiddelde stralingsdosis" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_NL_NL_H_ diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h index b6d6f9fe7..d890ab6ed 100644 --- a/tasmota/language/pl_PL.h +++ b/tasmota/language/pl_PL.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "Średnia Dawka Promieniowania" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_PL_PL_D_H_ diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index f73294280..75b176504 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "dose média de radiação" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_PT_BR_H_ diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index d29fd64cf..6f06e7222 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "dose média de radiação" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_PT_PT_H_ diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index 754f0021c..344fe3efe 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "doza medie de radiație" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_RO_RO_H_ diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h index 4e4a729e7..5291fe748 100644 --- a/tasmota/language/ru_RU.h +++ b/tasmota/language/ru_RU.h @@ -1224,4 +1224,8 @@ #define D_AVG_RAD_DOSE "средняя доза облучения" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_RU_RU_H_ diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index 0bdbc978e..9bd615000 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "priemerná dávka žiarenia" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_SK_SK_H_ diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index b702a0054..9f64ab048 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "genomsnittlig stråldos" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_SV_SE_H_ diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index 25fdddaa0..3fc97e797 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "ortalama radyasyon dozu" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_TR_TR_H_ diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index 42aa19f92..e5bcf184a 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "середня доза радіації" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_UK_UA_H_ diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h index 175178106..ce42b275c 100644 --- a/tasmota/language/vi_VN.h +++ b/tasmota/language/vi_VN.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "liều bức xạ trung bình" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_VI_VN_H_ diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index af408878a..54ebf9e0e 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "平均辐射剂量" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_ZH_CN_H_ diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index 46be35384..ee54c65a4 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -1223,4 +1223,8 @@ #define D_AVG_RAD_DOSE "平均輻射劑量" #define D_UNIT_US_H "µSv/h" +// ixrv92_pipsolar.ino +#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" + #endif // _LANGUAGE_ZH_TW_H_ diff --git a/tasmota/tasmota_xdrv_driver/xdrv_92_pipsolar.ino b/tasmota/tasmota_xdrv_driver/xdrv_92_pipsolar.ino new file mode 100644 index 000000000..747704f43 --- /dev/null +++ b/tasmota/tasmota_xdrv_driver/xdrv_92_pipsolar.ino @@ -0,0 +1,1050 @@ +/* + xdrv_92_pipsolar.ino - modbus bridge support for Tasmota + + Copyright (C) 2023 Peter Rustler + + 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 . +*/ + +#if defined(USE_PIPSOLAR) + +#define XDRV_92 92 + +#define PIPSOLAR_RECEIVEBUFFER_SIZE TM_SERIAL_BUFFER_SIZE * 2 // 128 +#define PIPSOLAR_SENDBUFFER_SIZE TM_SERIAL_BUFFER_SIZE // 64 + +#include +#include + +#include + +struct PipSolar +{ + TasmotaSerial *serial; + uint8_t *receiveBuffer; + uint8_t *sendBuffer; + + uint8_t receiveBufferPosition; + enum class CommandType + { + NONE, + QPIGS, // get analog values + //QPIRI, // Device Rating Information (settings) + QMOD, // get mode + QPIWS, // get status/error information + QT, // get inverter time + QET, // energy total + QEY, // energy year + QEM, // energy month + QED, // energy day + QEH, // energy hour + DAT, // set date time + } commandType; + + enum class CommandState { + None, + WaitForResponse, + GotResponse + } commandState; + + uint32_t secondIntervalCounter; + uint16_t commandTimeoutCounter; + bool pollValues; + + uint32_t successPoll; + uint32_t errorPoll; + uint32_t currentErrorPoll; + uint32_t maxCurrentErrorPoll; + + union Value + { + int intValue; + float floatValue; + bool boolValue; + char charValue; + }; + + struct ValueSetting + { + Value value; + enum class Type + { + unknownType, + intType, + intTypeCopy, + floatType, + floatTypeCopy, + boolType, + charType, + stringType, + } const type; + const uint8_t position; + const uint8_t count; + const char name[30]; + const char unit[4]; + const bool publish; + }; + struct QueryCommand { + PipSolar::CommandType commandType; + bool send; + char parameter[20]; + } queryCommand; +} PIPSOLAR; + +struct PIPSOLARPollingValue { + const uint32_t interval; + const PipSolar::CommandType command; + const uint16_t timeout; // *2ms + const uint16_t waitAfterResponse; // *2ms + bool poll; +}; +struct PIPSOLARPollingValue PIPSOLARpollingList[] = { + {3, PipSolar::CommandType::QPIWS, 600, 200, false}, + {3, PipSolar::CommandType::QPIGS, 600, 200, false}, + {3, PipSolar::CommandType::QMOD, 200, 200, false}, + {3, PipSolar::CommandType::QT, 200, 200, false}, + {3, PipSolar::CommandType::QET, 200, 200, false}, + {0, PipSolar::CommandType::QEY, 200, 200, false}, + {0, PipSolar::CommandType::QEM, 200, 200, false}, + {0, PipSolar::CommandType::QED, 200, 200, false}, + {0, PipSolar::CommandType::QEH, 200, 200, false}, + {0, PipSolar::CommandType::DAT, 200, 200, false}, +}; +constexpr uint8_t PIPSOLARpollingListCount = sizeof(PIPSOLARpollingList) / sizeof(PIPSOLARPollingValue); +uint8_t PIPSOLARpollingValuePosition = PIPSOLARpollingListCount; + +// (233.6 50.0 230.2 49.9 0299 0236 005 363 51.80 000 036 0039 00.1 000.0 00.00 00005 00010000 00 00 00000 010 +struct PipSolar::ValueSetting PIPSOLARqpigsValueSettings[] = { + {{}, PipSolar::ValueSetting::Type::floatType, 1, 5, "Grid_voltage", "V", false}, + {{}, PipSolar::ValueSetting::Type::floatType, 7, 4, "Grid_frequency", "Hz", false}, + {{}, PipSolar::ValueSetting::Type::floatType, 12, 5, "AC_output_voltage", "V", false}, + {{}, PipSolar::ValueSetting::Type::floatType, 18, 4, "AC_output_frequency", "Hz", false}, + {{}, PipSolar::ValueSetting::Type::intType, 23, 4, "AC_output_apparent_power", "W", false}, + {{}, PipSolar::ValueSetting::Type::intType, 28, 4, "AC_output_active_power", "W", true}, + {{}, PipSolar::ValueSetting::Type::intType, 33, 3, "Output_load_percent", "%", true}, + {{}, PipSolar::ValueSetting::Type::intType, 37, 3, "BUS_voltage", "V", false}, + {{}, PipSolar::ValueSetting::Type::floatType, 41, 5, "Battery_voltage", "V", true}, + {{}, PipSolar::ValueSetting::Type::intType, 47, 3, "Battery_charging_current", "A", false}, + {{}, PipSolar::ValueSetting::Type::intType, 51, 3, "Battery_capacity", "Ah", false}, + {{}, PipSolar::ValueSetting::Type::intType, 55, 4, "Heat_sink_temperature", "°C", true}, + {{}, PipSolar::ValueSetting::Type::floatType, 60, 4, "PV_Input_current", "A", false}, + {{}, PipSolar::ValueSetting::Type::floatType, 65, 5, "PV_Input_voltage", "V", false}, + {{}, PipSolar::ValueSetting::Type::floatType, 71, 5, "Battery_voltage_from_SCC", "V", false}, + {{}, PipSolar::ValueSetting::Type::intType, 77, 5, "Battery_discharge_current", "A", false}, + // deviceStatus 8x + {{}, PipSolar::ValueSetting::Type::stringType, 83, 8, "Device status", "", false}, + //{{}, PipSolar::ValueSetting::Type::boolType, 83, 1, "a7", "", false}, + //{{}, PipSolar::ValueSetting::Type::boolType, 84, 1, "a6", "", false}, + //{{}, PipSolar::ValueSetting::Type::boolType, 85, 1, "a5", "", false}, + //{{}, PipSolar::ValueSetting::Type::boolType, 86, 1, "a4", "", false}, + //{{}, PipSolar::ValueSetting::Type::boolType, 87, 1, "a3", "", false}, + //{{}, PipSolar::ValueSetting::Type::boolType, 88, 1, "a2", "", false}, + //{{}, PipSolar::ValueSetting::Type::boolType, 89, 1, "a1", "", false}, + //{{}, PipSolar::ValueSetting::Type::boolType, 90, 1, "a0", "", false}, + + {{}, PipSolar::ValueSetting::Type::intType, 92, 2, "Battery_voltage_offset_ffo", "V", false}, + {{}, PipSolar::ValueSetting::Type::intType, 95, 2, "EEPROM_version", "", false}, + {{}, PipSolar::ValueSetting::Type::intType, 98, 5, "PV_Charging_power", "W", true}, + // deviceStatus 3x + {{}, PipSolar::ValueSetting::Type::stringType, 100, 3, "Device status", "", false}, + //{{}, PipSolar::ValueSetting::Type::boolType, 100, 1, "Device_status[8]", ""}, + //{{}, PipSolar::ValueSetting::Type::boolType, 101, 1, "Device_status[9]", ""}, + //{{}, PipSolar::ValueSetting::Type::boolType, 102, 1, "Device_status[10]", ""}, +}; +constexpr uint8_t PIPSOLARqpigsValueSettingsCount = sizeof(PIPSOLARqpigsValueSettings) / sizeof(PipSolar::ValueSetting); + +// (B +struct PipSolar::ValueSetting PIPSOLARqmodValueSettings[] = { + {{}, PipSolar::ValueSetting::Type::charType, 1, 1, "Mode", "", true}, +}; +constexpr uint8_t PIPSOLARqmodValueSettingsCount = sizeof(PIPSOLARqmodValueSettings) / sizeof(PipSolar::ValueSetting); + +// (YYYYMMDDHHMMSS +struct PipSolar::ValueSetting PIPSOLARqtValueSettings[] = { + {{}, PipSolar::ValueSetting::Type::intTypeCopy, 1, 4, "Year", "", false}, + {{}, PipSolar::ValueSetting::Type::intTypeCopy, 5, 2, "Month", "", false}, + {{}, PipSolar::ValueSetting::Type::intTypeCopy, 7, 2, "Day", "", false}, + {{}, PipSolar::ValueSetting::Type::intTypeCopy, 9, 2, "Hour", "", false}, + {{}, PipSolar::ValueSetting::Type::intTypeCopy, 11, 2, "Minute", "", false}, + {{}, PipSolar::ValueSetting::Type::intTypeCopy, 13, 2, "Second", "", false}, +}; +constexpr uint8_t PIPSOLARqtValueSettingsCount = sizeof(PIPSOLARqtValueSettings) / sizeof(PipSolar::ValueSetting); + +struct PipSolar::ValueSetting PIPSOLARqexValueSettings[] = { + {{}, PipSolar::ValueSetting::Type::intType, 1, 8, "Total_Energy", "Wh", true}, +}; +constexpr uint8_t PIPSOLARqexValueSettingsCount = sizeof(PIPSOLARqexValueSettings) / sizeof(PipSolar::ValueSetting); + +/********************************************************************************************/ +bool PIPSOLARSendCommand(PipSolar::CommandType cmd, const char *parameter = nullptr, bool checksum = false); + +bool SetPipSolarSerialBegin(void) { + return PIPSOLAR.serial->begin(Settings->sbaudrate * 300, ConvertSerialConfig(Settings->sserial_config)); // Reinitialize serial port with new baud rate +} + +bool checkNumbersFormat(const char *buffer, int count) +{ + if (count == 0) + return false; + for (int i = 0; i < count; ++i) + if (buffer[i] > '9' || buffer[i] < '0') + return false; + return true; +} + +void CmndPipSolarNoParameter(PipSolar::CommandType commandType) { + if (PIPSOLAR.commandType != PipSolar::CommandType::NONE + && PIPSOLAR.queryCommand.commandType != PipSolar::CommandType::NONE) { + ResponseCmndChar_P(PSTR("Error\", \"Error\": \"Busy")); + } else if (PIPSOLAR.commandType == PipSolar::CommandType::NONE) { + ResponseCmndChar_P(PSTR("Send")); + PIPSOLAR.queryCommand.send = true; + PIPSOLAR.queryCommand.commandType = commandType; + PIPSOLARSendCommand(commandType); + } else { + PIPSOLAR.queryCommand.commandType = commandType; + PIPSOLAR.queryCommand.send = false; + ResponseCmndChar_P(PSTR("Queue")); + } +} +void CmndPipSolarParameter(PipSolar::CommandType commandType) { + if (PIPSOLAR.commandType != PipSolar::CommandType::NONE + && PIPSOLAR.queryCommand.commandType != PipSolar::CommandType::NONE) { + ResponseCmndChar_P(PSTR("Error\", \"Error\": \"Busy")); + } else if (PIPSOLAR.commandType == PipSolar::CommandType::NONE) { + PIPSOLAR.queryCommand.send = true; + strncpy(PIPSOLAR.queryCommand.parameter, XdrvMailbox.data, sizeof(PIPSOLAR.queryCommand.parameter)); + PIPSOLAR.queryCommand.commandType = commandType; + PIPSOLARSendCommand(commandType, PIPSOLAR.queryCommand.parameter); + ResponseCmndChar_P(PSTR("Send")); + } else { + PIPSOLAR.queryCommand.send = false; + strncpy(PIPSOLAR.queryCommand.parameter, XdrvMailbox.data, sizeof(PIPSOLAR.queryCommand.parameter)); + PIPSOLAR.queryCommand.commandType = commandType; + ResponseCmndChar_P(PSTR("Queue")); + } +} + +void CmndPipSolarQT(void) { + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command QT")); + CmndPipSolarNoParameter(PipSolar::CommandType::QT); +} + +void CmndPipSolarQET(void) { + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command QET")); + CmndPipSolarNoParameter(PipSolar::CommandType::QET); +} + +void CmndPipSolarQEY(void) { + if (!checkNumbersFormat(XdrvMailbox.data, XdrvMailbox.data_len)) { + ResponseCmndChar_P(PSTR("Error\", \"Error\": \"No numeric parameter")); + return; + } + if (XdrvMailbox.data_len != 4) { + ResponseCmndChar_P(PSTR("Error\", \"Error\": \"Parameter count")); + return; + } + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command QEY")); + CmndPipSolarParameter(PipSolar::CommandType::QEY); +} + +void CmndPipSolarQEM(void) { + if (!checkNumbersFormat(XdrvMailbox.data, XdrvMailbox.data_len)) { + ResponseCmndChar_P(PSTR("Error\", \"Error\": \"No numeric parameter")); + return; + } + if (XdrvMailbox.data_len != 6) { + ResponseCmndChar_P(PSTR("Error\", \"Error\": \"Parameter count")); + return; + } + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command QEM")); + CmndPipSolarParameter(PipSolar::CommandType::QEM); +} + +void CmndPipSolarQED(void) { + if (!checkNumbersFormat(XdrvMailbox.data, XdrvMailbox.data_len)) { + ResponseCmndChar_P(PSTR("Error\", \"Error\": \"No numeric parameter")); + return; + } + if (XdrvMailbox.data_len != 8) { + ResponseCmndChar_P(PSTR("Error\", \"Error\": \"Parameter count")); + return; + } + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command QED")); + CmndPipSolarParameter(PipSolar::CommandType::QED); +} + +void CmndPipSolarQEH(void) { + if (!checkNumbersFormat(XdrvMailbox.data, XdrvMailbox.data_len)) { + ResponseCmndChar_P(PSTR("Error\", \"Error\": \"No numeric parameter")); + return; + } + if (XdrvMailbox.data_len != 10) { + ResponseCmndChar_P(PSTR("Error\", \"Error\": \"Parameter count")); + return; + } + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command QEH")); + CmndPipSolarParameter(PipSolar::CommandType::QEH); +} + +void CmndPipSolarDAT(void) { + if (!checkNumbersFormat(XdrvMailbox.data, XdrvMailbox.data_len)) { + ResponseCmndChar_P(PSTR("Error\", \"Error\": \"No numeric parameter")); + return; + } + if (XdrvMailbox.data_len != 12) { + ResponseCmndChar_P(PSTR("Error\", \"Error\": \"Parameter count")); + return; + } + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command DAT")); + CmndPipSolarParameter(PipSolar::CommandType::DAT); +} + +void CmndPipSolarPollValues(void) { + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command PollValues")); + char argument[XdrvMailbox.data_len]; + + if (ArgC()==1) { + PIPSOLAR.pollValues = atoi(ArgV(argument, 1)) == 0 ? false : true; + } + Response_P(PSTR("{\"" D_CMND_PIP_PREFIX D_CMND_PIP_POLLVALUES "\": %d}"), PIPSOLAR.pollValues); +} + +void CmndPipSolarBaudRate(void) { + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command BaudRate")); + if (XdrvMailbox.payload >= 300) { + XdrvMailbox.payload /= 300; // Make it a valid baudrate + Settings->sbaudrate = XdrvMailbox.payload; + if (SetPipSolarSerialBegin()) + { + if (PIPSOLAR.serial->hardwareSerial()) + { + ClaimSerial(); + } + } + } + ResponseCmndNumber(Settings->sbaudrate * 300); +} + +void SetPipSolarSerialConfig(uint32_t serial_config) { + if (serial_config > TS_SERIAL_8O2) { + serial_config = TS_SERIAL_8N1; + } + if (serial_config != Settings->sserial_config) { + Settings->sserial_config = serial_config; + SetPipSolarSerialBegin(); + } +} + +void CmndPipSolarSerialConfig(void) { + + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.data_len < 3) { // Use 0..23 as serial config option + if ((XdrvMailbox.payload >= TS_SERIAL_5N1) && (XdrvMailbox.payload <= TS_SERIAL_8O2)) { + SetPipSolarSerialConfig(XdrvMailbox.payload); + } + } + else if ((XdrvMailbox.payload >= 5) && (XdrvMailbox.payload <= 8)) { + int8_t serial_config = ParseSerialConfig(XdrvMailbox.data); + if (serial_config >= 0) { + SetPipSolarSerialConfig(serial_config); + } + } + } + ResponseCmndChar(GetSerialConfig(Settings->sserial_config).c_str()); +} + +const char kPipSolarCommands[] PROGMEM = D_CMND_PIP_PREFIX "|" + D_CMND_PIP_QT "|" + D_CMND_PIP_QET "|" + D_CMND_PIP_QEY "|" + D_CMND_PIP_QEM "|" + D_CMND_PIP_QED "|" + D_CMND_PIP_QEH "|" + D_CMND_PIP_DAT "|" + D_CMND_PIP_POLLVALUES "|" + D_CMND_PIP_BAUDRATE "|" + D_CMND_PIP_SERIALCONFIG; + +void (* const PipSolarCommand[])(void) PROGMEM = { + &CmndPipSolarQT, + &CmndPipSolarQET, + &CmndPipSolarQEY, + &CmndPipSolarQEM, + &CmndPipSolarQED, + &CmndPipSolarQEH, + &CmndPipSolarDAT, + &CmndPipSolarPollValues, + &CmndPipSolarBaudRate, + &CmndPipSolarSerialConfig + }; + + +void PIPSOLARPublishResult(const char *subtopic, const char *payload, const char *parameter) +{ + char buffer[150]; + snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\": {\"value\": \"%s\", \"parameter\": \"%s\"}}"), subtopic, payload, parameter); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: RESULT %s"), (const char*)buffer); + MqttPublishPayloadPrefixTopic_P(RESULT_OR_STAT, subtopic, (const char*)buffer); + XdrvRulesProcess(0, buffer); +} + +void PIPSOLARPublishResult(const char *subtopic, int payload, const char *parameter) +{ + char buffer[150]; + snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\": {\"value\": %d, \"parameter\": \"%s\"}}"), subtopic, payload, parameter); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: RESULT %s"), (const char*)buffer); + MqttPublishPayloadPrefixTopic_P(RESULT_OR_STAT, subtopic, (const char*)buffer); + XdrvRulesProcess(0, buffer); +} + +void PIPSOLARPublishResult(const char *subtopic, const char* payload) +{ + char buffer[150]; + snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\": {\"value\": \"%s\"}}"), subtopic, payload); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: RESULT %s"), (const char*)buffer); + MqttPublishPayloadPrefixTopic_P(RESULT_OR_STAT, subtopic, (const char*)buffer); + XdrvRulesProcess(0, buffer); +} + +void PIPSOLARPublishResult(const char *subtopic, int payload) +{ + char buffer[150]; + snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\": {\"value\": %d}}"), subtopic, payload); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: RESULT %s"), (const char*)buffer); + MqttPublishPayloadPrefixTopic_P(RESULT_OR_STAT, subtopic, (const char*)buffer); + XdrvRulesProcess(0, buffer); +} + +void PIPSOLARPublish(const char *subtopic, const char *payload) +{ + MqttPublishPayloadPrefixTopic_P(STAT, subtopic, payload); + char buffer[150]; + snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\": \"%s\"}"), subtopic, payload); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: PUBLISH %s"), (const char*)buffer); + XdrvRulesProcess(0, buffer); +} + +void PIPSOLARPublishRaw(const char *subtopic, const char *payload) +{ + MqttPublishPayloadPrefixTopic_P(STAT, subtopic, payload); + char buffer[150]; + snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\": %s}"), subtopic, payload); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: PUBLISH %s"), (const char*)buffer); + XdrvRulesProcess(0, buffer); +} + +void PIPSOLARPublish(const char *subtopic, int value) +{ + char buffer[15]; + snprintf(buffer, sizeof(buffer), "%d", value); + PIPSOLARPublishRaw(subtopic, buffer); +} + +void PIPSOLARPublish(const char *subtopic, float value) +{ + char buffer[15]; + snprintf(buffer, sizeof(buffer), "%f", value); + PIPSOLARPublishRaw(subtopic, buffer); +} + +void PIPSOLARPublish(const char *subtopic, char value) +{ + char buffer[2]; + snprintf(buffer, sizeof(buffer), "%c", value); + PIPSOLARPublish(subtopic, buffer); +} + +void PIPSOLARPublish(const char *subtopic, bool value) +{ + char buffer[2]; + snprintf(buffer, sizeof(buffer), "%d", value); + PIPSOLARPublishRaw(subtopic, buffer); +} + +// crc function is from here: https://forum.arduino.cc/t/rs232-read-data-from-mpp-solar-inverter/600960/6 +uint16_t PIPSOLARCalcCrc(const uint8_t *pin, uint8_t len) +{ + uint16_t crc; + uint8_t da; + const uint8_t *ptr; + uint8_t bCRCHign; + uint8_t bCRCLow; + + const unsigned short crc_ta[16] = + { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef}; + + ptr = pin; + crc = 0; + while (len-- != 0) + { + da = ((uint8_t)(crc >> 8)) >> 4; + crc <<= 4; + crc ^= crc_ta[da ^ (*ptr >> 4)]; + da = ((uint8_t)(crc >> 8)) >> 4; + crc <<= 4; + crc ^= crc_ta[da ^ (*ptr & 0x0f)]; + ptr++; + } + bCRCLow = crc; + bCRCHign = (uint8_t)(crc >> 8); + if (bCRCLow == 0x28 || bCRCLow == 0x0d || bCRCLow == 0x0a) + { + bCRCLow++; + } + if (bCRCHign == 0x28 || bCRCHign == 0x0d || bCRCHign == 0x0a) + { + bCRCHign++; + } + crc = ((unsigned short)bCRCHign) << 8; + crc += bCRCLow; + return (crc); +} + +bool PIPSOLARSendCommand(PipSolar::CommandType cmd, const char *parameter, bool checksum) +{ + const char *command; + switch (cmd) + { + case PipSolar::CommandType::NONE: + return false; + case PipSolar::CommandType::QPIGS: + command = PSTR("QPIGS"); + break; + case PipSolar::CommandType::QMOD: + command = PSTR("QMOD"); + break; + case PipSolar::CommandType::QPIWS: + command = PSTR("QPIWS"); + break; + case PipSolar::CommandType::QT: + command = PSTR("QT"); + break; + case PipSolar::CommandType::QET: + command = PSTR("QET"); + break; + case PipSolar::CommandType::QEY: + command = PSTR("QEY"); + break; + case PipSolar::CommandType::QEM: + command = PSTR("QEM"); + break; + case PipSolar::CommandType::QED: + command = PSTR("QED"); + break; + case PipSolar::CommandType::QEH: + command = PSTR("QEH"); + break; + case PipSolar::CommandType::DAT: + command = PSTR("DAT"); + break; + } + PIPSOLAR.commandType = cmd; + PIPSOLAR.commandState = PipSolar::CommandState::WaitForResponse; + PIPSOLAR.commandTimeoutCounter = 0; + + uint8_t len = strlen(command); + memcpy(PIPSOLAR.sendBuffer, command, len); + if (parameter) + { + uint8_t parameterLen = strlen(parameter); + memcpy(PIPSOLAR.sendBuffer + len, parameter, parameterLen); + len += parameterLen; + if (checksum) { + uint8_t checksumValue = 0; + for (uint8_t i = 0; i < len; ++i) + checksumValue += PIPSOLAR.sendBuffer[i]; + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: Checksum %d len %d"), checksumValue, len+3); + sprintf(reinterpret_cast(PIPSOLAR.sendBuffer + len), "%03u", checksumValue); + len += 3; + } + } + + PIPSOLAR.sendBuffer[len] = 0; + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: Send %s"), PIPSOLAR.sendBuffer); + + uint16_t crc16 = PIPSOLARCalcCrc(PIPSOLAR.sendBuffer, len); + PIPSOLAR.sendBuffer[len++] = ((uint8_t)((crc16) >> 8)); + PIPSOLAR.sendBuffer[len++] = ((uint8_t)((crc16)&0xff)); + PIPSOLAR.sendBuffer[len++] = '\r'; + + + // PIPSOLAR.serial->setReadChunkMode(1); // Enable chunk mode introducing possible Hardware Watchdogs + PIPSOLAR.serial->flush(); + PIPSOLAR.serial->write(PIPSOLAR.sendBuffer, len); + PIPSOLAR.commandTimeoutCounter = 0; + return false; +} + +const char* PIPSOLARGetValueString(char *data, int8_t position, uint8_t count) +{ + data[position+count] = 0; + return &data[position]; +} + +static char PIPSOLARGetValueStringCopyString[10]; +const char* PIPSOLARGetValueStringCopy(char *data, int8_t position, uint8_t count) +{ + PIPSOLARGetValueStringCopyString[count] = 0; + memcpy((void*)PIPSOLARGetValueStringCopyString, &data[position], count); + + return PIPSOLARGetValueStringCopyString; +} + +void PIPSOLARInterpret(struct PipSolar::ValueSetting *settings, uint8_t count) +{ + //(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__); + for (uint8_t i = 0; i < count; ++i) + { + auto & setting = settings[i]; + + switch (setting.type) + { + case PipSolar::ValueSetting::Type::intType: { + const char* temp = PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, setting.position, setting.count); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d %s %s"), __LINE__, setting.name, temp); + setting.value.intValue = atoi(temp); + if (setting.publish) + PIPSOLARPublish(setting.name, setting.value.intValue); + break; + } + case PipSolar::ValueSetting::Type::intTypeCopy: { + const char* temp = PIPSOLARGetValueStringCopy((char*)PIPSOLAR.receiveBuffer, setting.position, setting.count); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d %s %s"), __LINE__, setting.name, temp); + setting.value.intValue = atoi(temp); + if (setting.publish) + PIPSOLARPublish(setting.name, setting.value.intValue); + break; + } + case PipSolar::ValueSetting::Type::floatType: { + const char* temp = PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, setting.position, setting.count); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d %s %s"), __LINE__, setting.name, temp); + setting.value.floatValue = atof(temp); + if (setting.publish) + PIPSOLARPublish(setting.name, setting.value.floatValue); + break; + } + case PipSolar::ValueSetting::Type::floatTypeCopy: { + const char* temp = PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, setting.position, setting.count); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d %s %s"), __LINE__, setting.name, temp); + setting.value.floatValue = atof(temp); + if (setting.publish) + PIPSOLARPublish(setting.name, setting.value.floatValue); + break; + } + case PipSolar::ValueSetting::Type::boolType: + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__); + setting.value.boolValue = PIPSOLAR.receiveBuffer[setting.position] == '1'; + if (setting.publish) + PIPSOLARPublish(setting.name, setting.value.boolValue); + break; + case PipSolar::ValueSetting::Type::charType: + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__); + setting.value.charValue = PIPSOLAR.receiveBuffer[setting.position]; + if (setting.publish) + PIPSOLARPublish(setting.name, setting.value.charValue); + break; + case PipSolar::ValueSetting::Type::stringType: + const char* temp = PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, setting.position, setting.count); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__); + if (setting.publish) + PIPSOLARPublish(setting.name, temp); + break; + } + } +} + +void PIPSOLARInterpret(void) +{ + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d %d"), __LINE__, PIPSOLAR.commandType); + if (PIPSOLAR.receiveBuffer[0] != '(') + return; + bool wasQuery = (PIPSOLAR.commandType == PIPSOLAR.queryCommand.commandType && PIPSOLAR.queryCommand.send); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__); + switch (PIPSOLAR.commandType) + { + case PipSolar::CommandType::NONE: + break; + case PipSolar::CommandType::QPIGS: { + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: %s %d %d"), __FUNCTION__, __LINE__, PIPSOLAR.receiveBufferPosition); + if (PIPSOLAR.receiveBufferPosition != 107) + return; + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: %s %d"), __FUNCTION__, __LINE__); + PIPSOLARInterpret(PIPSOLARqpigsValueSettings, PIPSOLARqpigsValueSettingsCount); + int batteryCurrent = PIPSOLARqpigsValueSettings[9].value.intValue - PIPSOLARqpigsValueSettings[15].value.intValue; + PIPSOLARPublish(PSTR("Battery_current"), batteryCurrent); + PIPSOLARPublish(PSTR("Battery_power"), PIPSOLARqpigsValueSettings[8].value.floatValue * batteryCurrent); + char buffer[8+3+1]; + auto &deviceState1 = PIPSOLARqpigsValueSettings[16]; + auto &deviceState2 = PIPSOLARqpigsValueSettings[20]; + snprintf(buffer, sizeof(buffer), "%3s%8s" + , PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, deviceState2.position, deviceState2.count) + , PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, deviceState1.position, deviceState1.count)); + PIPSOLARPublish(PSTR("Device_state"), buffer); + } + break; + case PipSolar::CommandType::QMOD: + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__); + if (PIPSOLAR.receiveBufferPosition != 2) + return; + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__); + PIPSOLARInterpret(PIPSOLARqmodValueSettings, PIPSOLARqmodValueSettingsCount); + break; + case PipSolar::CommandType::QPIWS: + PIPSOLARPublish(PSTR("Device_warning_state"), PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 35)); + break; + case PipSolar::CommandType::QT: + if (wasQuery) + PIPSOLARPublishResult(PSTR("QT"), PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 14)); + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__); + PIPSOLARInterpret(PIPSOLARqtValueSettings, PIPSOLARqtValueSettingsCount); + PIPSOLARPublish(PSTR("Inverter_date_time"), PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 14)); + break; + case PipSolar::CommandType::QET: + if (wasQuery) + PIPSOLARPublishResult(PSTR("QET"), atoi(PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 8))); + PIPSOLARInterpret(PIPSOLARqexValueSettings, PIPSOLARqexValueSettingsCount); + break; + case PipSolar::CommandType::QEY: + if (wasQuery) + PIPSOLARPublishResult(PSTR("QEY"), atoi(PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 8)), PIPSOLAR.queryCommand.parameter); + else + PIPSOLARInterpret(PIPSOLARqexValueSettings, PIPSOLARqexValueSettingsCount); + break; + case PipSolar::CommandType::QEM: + if (wasQuery) + PIPSOLARPublishResult(PSTR("QEM"), atoi(PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 8)), PIPSOLAR.queryCommand.parameter); + else + PIPSOLARInterpret(PIPSOLARqexValueSettings, PIPSOLARqexValueSettingsCount); + break; + case PipSolar::CommandType::QED: + if (wasQuery) + PIPSOLARPublishResult(PSTR("QED"), atoi(PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 8)), PIPSOLAR.queryCommand.parameter); + else + PIPSOLARInterpret(PIPSOLARqexValueSettings, PIPSOLARqexValueSettingsCount); + break; + case PipSolar::CommandType::QEH: + if (wasQuery) + PIPSOLARPublishResult(PSTR("QEH"), atoi(PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 8)), PIPSOLAR.queryCommand.parameter); + else + PIPSOLARInterpret(PIPSOLARqexValueSettings, PIPSOLARqexValueSettingsCount); + break; + case PipSolar::CommandType::DAT: + if (wasQuery) + PIPSOLARPublishResult(PSTR("DAT"), PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 3), PIPSOLAR.queryCommand.parameter); + break; + } + + if (wasQuery) { + PIPSOLAR.queryCommand.commandType = PipSolar::CommandType::NONE; + PIPSOLAR.queryCommand.parameter[0] = 0; + PIPSOLAR.queryCommand.send = false; + } + + PIPSOLAR.receiveBufferPosition = 0; + if (!PIPSOLAR.pollValues) { + PIPSOLAR.commandState = PipSolar::CommandState::None; + PIPSOLAR.commandType = PipSolar::CommandType::NONE; + } +} + +void PIPSOLARInput(void) +{ + while (PIPSOLAR.serial->available()) + { + uint8_t bytesAvailable = PIPSOLAR.serial->read(PIPSOLAR.receiveBuffer + PIPSOLAR.receiveBufferPosition, PIPSOLAR_RECEIVEBUFFER_SIZE - PIPSOLAR.receiveBufferPosition); + PIPSOLAR.receiveBufferPosition += bytesAvailable; + if (PIPSOLAR.receiveBufferPosition == PIPSOLAR_RECEIVEBUFFER_SIZE) { // buffer overflow + ++PIPSOLAR.currentErrorPoll; + PIPSOLAR.maxCurrentErrorPoll = std::max(PIPSOLAR.maxCurrentErrorPoll, PIPSOLAR.currentErrorPoll); + ++PIPSOLAR.errorPoll; + PIPSOLAR.receiveBufferPosition = 0; // we are in trouble, but keep it going + } + } + if (PIPSOLAR.receiveBufferPosition > 2 && PIPSOLAR.receiveBuffer[PIPSOLAR.receiveBufferPosition - 1] == '\r') + { // we hope that we always have a complete reply + bool valid = true; + uint16_t crc16 = PIPSOLARCalcCrc(PIPSOLAR.receiveBuffer, PIPSOLAR.receiveBufferPosition - 3); + uint8_t crcLow = PIPSOLAR.receiveBuffer[PIPSOLAR.receiveBufferPosition - 2]; + uint8_t crcHigh = PIPSOLAR.receiveBuffer[PIPSOLAR.receiveBufferPosition - 3]; + if (((uint8_t)((crc16)&0xff)) != crcLow || ((uint8_t)((crc16) >> 8)) != crcHigh) + valid = false; + + PIPSOLAR.receiveBufferPosition -= 3; // remove crc and \r + PIPSOLAR.receiveBuffer[PIPSOLAR.receiveBufferPosition] = 0; // terminate string + if (valid) + { + PIPSOLAR.currentErrorPoll = 0; + ++PIPSOLAR.successPoll; + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: Received valid data \"%s\" timeout %d"), PIPSOLAR.receiveBuffer, PIPSOLAR.commandTimeoutCounter); + PIPSOLARInterpret(); + PIPSOLAR.commandState = PipSolar::CommandState::GotResponse; + } else { + ++PIPSOLAR.currentErrorPoll; + PIPSOLAR.maxCurrentErrorPoll = std::max(PIPSOLAR.maxCurrentErrorPoll, PIPSOLAR.currentErrorPoll); + ++PIPSOLAR.errorPoll; + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: Received invalid data \"%s\" crc %02x %02x expected %2x %2x timeout %d"), PIPSOLAR.receiveBuffer, crcLow, crcHigh, ((uint8_t)((crc16)&0xff)), ((uint8_t)((crc16) >> 8)), PIPSOLAR.commandTimeoutCounter); + PIPSOLAR.receiveBufferPosition = 0; + PIPSOLAR.commandState = PipSolar::CommandState::None; + PIPSOLAR.commandType = PipSolar::CommandType::NONE; + } + PIPSOLAR.commandTimeoutCounter = -1; + } + if (PIPSOLAR.pollValues && PIPSOLAR.commandType != PipSolar::CommandType::NONE) { + + switch (PIPSOLAR.commandState) { + case PipSolar::CommandState::None: + break; + case PipSolar::CommandState::WaitForResponse: + if (PIPSOLAR.commandTimeoutCounter > PIPSOLARpollingList[PIPSOLARpollingValuePosition].timeout) { + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: timeout WaitForResponse %d"), PIPSOLARpollingValuePosition, PIPSOLAR.commandTimeoutCounter, PIPSOLARpollingList[PIPSOLARpollingValuePosition].timeout); + PIPSOLAR.commandTimeoutCounter = 0; + PIPSOLAR.commandState = PipSolar::CommandState::None; + PIPSOLAR.commandType = PipSolar::CommandType::NONE; + PIPSOLAR.receiveBufferPosition = 0; + ++PIPSOLAR.currentErrorPoll; + PIPSOLAR.maxCurrentErrorPoll = std::max(PIPSOLAR.maxCurrentErrorPoll, PIPSOLAR.currentErrorPoll); + ++PIPSOLAR.errorPoll; + PIPSOLARNextPolling(); + } + break; + case PipSolar::CommandState::GotResponse: + if (PIPSOLAR.commandTimeoutCounter > PIPSOLARpollingList[PIPSOLARpollingValuePosition].waitAfterResponse) { + PIPSOLAR.commandTimeoutCounter = 0; + PIPSOLAR.commandState = PipSolar::CommandState::None; + PIPSOLAR.commandType = PipSolar::CommandType::NONE; + PIPSOLARNextPolling(); + } + break; + } + ++PIPSOLAR.commandTimeoutCounter; + } +} + +/********************************************************************************************/ + +void PIPSOLARNextPolling() { + if (PIPSOLAR.queryCommand.commandType != PipSolar::CommandType::NONE + && !PIPSOLAR.queryCommand.send) { + switch(PIPSOLAR.queryCommand.commandType) { + case PipSolar::CommandType::QT: + case PipSolar::CommandType::QET: + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: query without parameter")); + PIPSOLARSendCommand(PIPSOLAR.queryCommand.commandType); + PIPSOLAR.queryCommand.send = true; + return; + case PipSolar::CommandType::QEY: + case PipSolar::CommandType::QEM: + case PipSolar::CommandType::QED: + case PipSolar::CommandType::QEH: + case PipSolar::CommandType::DAT: + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: query with parameter")); + PIPSOLARSendCommand(PIPSOLAR.queryCommand.commandType, PIPSOLAR.queryCommand.parameter); + PIPSOLAR.queryCommand.send = true; + return; + default: // unsupported query + PIPSOLAR.queryCommand.send = false; + PIPSOLAR.queryCommand.commandType = PipSolar::CommandType::NONE; + PIPSOLAR.queryCommand.parameter[0] = 0; + break; + } + } + while(PIPSOLARpollingValuePosition < PIPSOLARpollingListCount) { + if (!PIPSOLARpollingList[PIPSOLARpollingValuePosition].poll) { + ++PIPSOLARpollingValuePosition; + continue; + } + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: %d"), __LINE__); + auto &command = PIPSOLARpollingList[PIPSOLARpollingValuePosition].command; + switch(command) { // TODO add the others with parameter + case PipSolar::CommandType::QPIWS: + case PipSolar::CommandType::QPIGS: + case PipSolar::CommandType::QMOD: + case PipSolar::CommandType::QT: + case PipSolar::CommandType::QET: + PIPSOLARSendCommand(command); + PIPSOLARpollingList[PIPSOLARpollingValuePosition].poll = false; + break; + case PipSolar::CommandType::NONE: + break; + } + return; + } + PIPSOLARpollingValuePosition = 0; +} + +void PIPSOLAREverySecond(void) +{ + if (PIPSOLAR.pollValues) { + for(int i = 0; i < PIPSOLARpollingListCount; ++i) { + if (PIPSOLARpollingList[i].interval != 0 && (PIPSOLAR.secondIntervalCounter % PIPSOLARpollingList[i].interval) == 0) { + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: schedule %d"), i); + PIPSOLARpollingList[i].poll = true; + } + } + if (PIPSOLAR.commandType == PipSolar::CommandType::NONE) { + PIPSOLARpollingValuePosition = 0; + PIPSOLARNextPolling(); + } + ++PIPSOLAR.secondIntervalCounter; + } +} + +void PIPSOLARInit(void) +{ + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: %s %d"), __FUNCTION__, __LINE__); + if (PinUsed(GPIO_PIPSOLAR_RX) && PinUsed(GPIO_PIPSOLAR_TX)) + { + PIPSOLAR.pollValues = true; + PIPSOLAR.receiveBuffer = (uint8_t *)malloc(PIPSOLAR_RECEIVEBUFFER_SIZE); + PIPSOLAR.sendBuffer = (uint8_t *)malloc(PIPSOLAR_SENDBUFFER_SIZE); + PIPSOLAR.receiveBufferPosition = 0; + PIPSOLAR.secondIntervalCounter = 0; + PIPSOLAR.commandType = PipSolar::CommandType::NONE; + PIPSOLAR.errorPoll = 0; + PIPSOLAR.successPoll = 0; + PIPSOLAR.currentErrorPoll = 0; + PIPSOLAR.queryCommand.commandType = PipSolar::CommandType::NONE; + PIPSOLAR.queryCommand.send = false; + + if (!PIPSOLAR.receiveBuffer || !PIPSOLAR.sendBuffer) + { + return; + } + + PIPSOLAR.receiveBuffer[0] = 0u; + PIPSOLAR.sendBuffer[0] = 0u; + + PIPSOLAR.serial = new TasmotaSerial(Pin(GPIO_PIPSOLAR_RX), Pin(GPIO_PIPSOLAR_TX), 2); + if (SetPipSolarSerialBegin()) + { + if (PIPSOLAR.serial->hardwareSerial()) + { + ClaimSerial(); + } + } + } +} + +/*********************************************************************************************\ + * Presentation +\*********************************************************************************************/ + +void PIPSOLARShowWeb(const PipSolar::ValueSetting &setting) +{ + switch (setting.type) + { + case PipSolar::ValueSetting::Type::intTypeCopy: + case PipSolar::ValueSetting::Type::intType: + WSContentSend_PD(PSTR("{s}%s{m}%d %s{e}"), setting.name, setting.value.intValue, setting.unit); + break; + case PipSolar::ValueSetting::Type::floatTypeCopy: + case PipSolar::ValueSetting::Type::floatType: + WSContentSend_PD(PSTR("{s}%s{m}%f %s{e}"), setting.name, setting.value.floatValue, setting.unit); + break; + case PipSolar::ValueSetting::Type::boolType: + WSContentSend_PD(PSTR("{s}%s{m}%s %s{e}"), setting.name, (setting.value.boolValue ? "true" : "false"), setting.unit); + break; + case PipSolar::ValueSetting::Type::charType: + WSContentSend_PD(PSTR("{s}%s{m}%c %s{e}"), setting.name, setting.value.charValue, setting.unit); + break; + } +} +void PIPSOLARShow(bool json) +{ + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: %s %d"), __FUNCTION__, __LINE__); + if (json) + { // // cm cm cm % % + ResponseAppend_P(PSTR(",\"PIPSOLAR\":1")); +#ifdef USE_WEBSERVER + } + else + { + WSContentSend_PD(PSTR("{s}

QT

{e}")); + WSContentSend_PD(PSTR("{s}InverterTime{m}%02d:%02d:%02d %02d.%02d.%04d{e}"), + PIPSOLARqtValueSettings[3].value.intValue, + PIPSOLARqtValueSettings[4].value.intValue, + PIPSOLARqtValueSettings[5].value.intValue, + PIPSOLARqtValueSettings[2].value.intValue, + PIPSOLARqtValueSettings[1].value.intValue, + PIPSOLARqtValueSettings[0].value.intValue + ); + WSContentSend_PD(PSTR("{s}

QEx

{e}")); + for (int i = 0; i < PIPSOLARqexValueSettingsCount; ++i) + { + auto &setting = PIPSOLARqexValueSettings[i]; + PIPSOLARShowWeb(setting); + } + WSContentSend_PD(PSTR("{s}

QMOD

{e}")); + for (int i = 0; i < PIPSOLARqmodValueSettingsCount; ++i) + { + auto &setting = PIPSOLARqmodValueSettings[i]; + PIPSOLARShowWeb(setting); + } + WSContentSend_PD(PSTR("{s}

QPIGS

{e}")); + for (int i = 0; i < PIPSOLARqpigsValueSettingsCount; ++i) + { + auto &setting = PIPSOLARqpigsValueSettings[i]; + PIPSOLARShowWeb(setting); + } + float percentError = 100.0 * PIPSOLAR.errorPoll / (PIPSOLAR.errorPoll + PIPSOLAR.successPoll); + WSContentSend_PD(PSTR("{s}

ERROR

{m}Success: %u
Error: %u
CurrentError: %u
Max CurrentError: %u
ErrorRate %.2f %%{e}"), PIPSOLAR.successPoll, PIPSOLAR.errorPoll, PIPSOLAR.currentErrorPoll, PIPSOLAR.maxCurrentErrorPoll, percentError); +#endif // USE_WEBSERVER + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv92(uint32_t function) +{ + bool result = true; + + if (PIPSOLAR.serial || function == FUNC_INIT) + { + switch (function) + { + case FUNC_COMMAND: + result = DecodeCommand(kPipSolarCommands, PipSolarCommand); + break; + + case FUNC_INIT: + PIPSOLARInit(); + break; + case FUNC_LOOP: + case FUNC_SLEEP_LOOP: + PIPSOLARInput(); + break; + case FUNC_EVERY_50_MSECOND: + break; + case FUNC_EVERY_SECOND: + PIPSOLAREverySecond(); + break; + case FUNC_JSON_APPEND: + PIPSOLARShow(true); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + PIPSOLARShow(false); + break; +#endif + } + } + return result; +} + +#endif // USE_PIPSOLAR diff --git a/tools/lv_gpio/lv_gpio_enum.h b/tools/lv_gpio/lv_gpio_enum.h index 7aa4f3f94..23649947a 100644 --- a/tools/lv_gpio/lv_gpio_enum.h +++ b/tools/lv_gpio/lv_gpio_enum.h @@ -341,5 +341,7 @@ HDMI_CEC = GPIO_HDMI_CEC HC8_RXD = GPIO_HC8_RXD I2S_DAC = GPIO_I2S_DAC MAGIC_SWITCH = GPIO_MAGIC_SWITCH +PIPSOLAR_TX = GPIO_PIPSOLAR_TX +PIPSOLAR_RX = GPIO_PIPSOLAR_RX SENSOR_END = GPIO_SENSOR_END From af24d689a99a098dd24c39ee7a48a4fb59ee79b7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 10 Jan 2024 10:39:24 +0100 Subject: [PATCH 117/303] Update changelogs --- CHANGELOG.md | 17 +++++++++++------ RELEASENOTES.md | 9 +++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 556181f29..e3ae2ab37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,19 +15,22 @@ All notable changes to this project will be documented in this file. - Berry GPIO viewer initial version using async webserver (#20416) - Berry add `string` to `bytes()` (#20420) - Berry button to dynamically load GPIO Viewer with Berry backend (#20424) -- Berry `debug_panel.tapp` to display real-time heap and wifi rssi -- Berry `webserver.header` to read browser sent headers -- Berry provide lightweight options for `tasmota.wifi/eth/memory/rtc` -- Berry `tasmota.webcolor` +- Berry `debug_panel.tapp` to display real-time heap and wifi rssi (#20436) +- Berry `webserver.header` to read browser sent headers (#20447) +- Berry provide lightweight options for `tasmota.wifi/eth/memory/rtc` (#20448) +- Berry `tasmota.webcolor` (#20454) +- Support for pipsolar inverter (#20408) ### Breaking Changed ### Changed - Renamed button "Consoles" to "Tools" -- Header `Host` is now collected by Webserver +- ESP32 platform update from 2023.12.00 to 2024.01.00 (#20445) +- Header `Host` is now collected by Webserver (#20446) +- Webcam tweaks (#20451) ### Fixed -- Fixed Zigbee Aqara attributes on ESP32 +- ESP32 Zigbee Aqara attributes (#20452) ### Removed @@ -49,6 +52,7 @@ All notable changes to this project will be documented in this file. ### Changed - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` (#20260) +- ESP32 platform update from 2023.11.01 to 2023.12.00 (#20298) - Moved Berry animate to its own `berry_animate` lib (#20309) - Relax checks of Partition Wizard for newest Shelly (#20349) @@ -100,6 +104,7 @@ All notable changes to this project will be documented in this file. - Matter update hierarchy of plugins (#19915) - NeoPool ``NPHydrolysis`` percent and unit (#19924) - Thermostat JSON index from 0 to 1 (#20011) +- ESP32 platform update from 2023.11.00 to 2023.11.01 (#20087) ### Fixed - Scripter timer issue (#19914) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 12b0c9df2..09ffd3afb 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -124,6 +124,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - GPIO Viewer to see realtime GPIO states. Enable with define USE_GPIO_VIEWER - NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) - Support negative power on BL0942 using index 5..8 [#20322](https://github.com/arendst/Tasmota/issues/20322) +- Support for pipsolar inverter [#20408](https://github.com/arendst/Tasmota/issues/20408) - ESP32 used UART information - ESP32 experimental support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled - Berry GPIO viewer initial version using async webserver [#20416](https://github.com/arendst/Tasmota/issues/20416) @@ -134,6 +135,10 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Berry `gpio.get_pin_type` and `gpio.ger_pin_type_index` [#20415](https://github.com/arendst/Tasmota/issues/20415) - Berry `string` to `bytes()` [#20420](https://github.com/arendst/Tasmota/issues/20420) - Berry button to dynamically load GPIO Viewer with Berry backend [#20424](https://github.com/arendst/Tasmota/issues/20424) +- Berry `debug_panel.tapp` to display real-time heap and wifi rssi [#20436](https://github.com/arendst/Tasmota/issues/20436) +- Berry `webserver.header` to read browser sent headers [#20447](https://github.com/arendst/Tasmota/issues/20447) +- Berry provide lightweight options for `tasmota.wifi/eth/memory/rtc` [#20448](https://github.com/arendst/Tasmota/issues/20448) +- Berry `tasmota.webcolor` [#20454](https://github.com/arendst/Tasmota/issues/20454) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) - HASPmota type `chart` [#20372](https://github.com/arendst/Tasmota/issues/20372) - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) @@ -142,14 +147,18 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Refactoring of Berry `animate` module for WS2812 Leds [#20236](https://github.com/arendst/Tasmota/issues/20236) ### Changed +- ESP32 platform update from 2023.11.01 to 2024.01.00 [#20445](https://github.com/arendst/Tasmota/issues/20445) - Renamed button "Consoles" to "Tools" - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` [#20260](https://github.com/arendst/Tasmota/issues/20260) +- Header `Host` is now collected by Webserver [#20446](https://github.com/arendst/Tasmota/issues/20446) +- Webcam tweaks [#20451](https://github.com/arendst/Tasmota/issues/20451) ### Fixed - CVE-2021-36603 Cross Site Scripting (XSS) vulnerability [#12221](https://github.com/arendst/Tasmota/issues/12221) - Syslog server warning caused by lack of field and hostname starting with 'z' [#14689](https://github.com/arendst/Tasmota/issues/14689) - Support for Domoticz floor/room topics. Regression from v12.0.1 [#20299](https://github.com/arendst/Tasmota/issues/20299) - ESP32 piezo ceramic buzzer doesn't buzz [#20118](https://github.com/arendst/Tasmota/issues/20118) +- ESP32 Zigbee Aqara attributes [#20452](https://github.com/arendst/Tasmota/issues/20452) - LVGL fix type for lv_imgbtn [#20354](https://github.com/arendst/Tasmota/issues/20354) - Berry claiming UART0 if needed [#20324](https://github.com/arendst/Tasmota/issues/20324) - Matter Contact sensor was not triggering any update [#20232](https://github.com/arendst/Tasmota/issues/20232) From c2d6bbf2c1f4f1ec58488ed15c2e4d24601924e1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 10 Jan 2024 11:13:19 +0100 Subject: [PATCH 118/303] Code admin --- CODE_OWNERS.md | 14 +++++++++----- tasmota/tasmota_support/support_features.ino | 14 ++++++++++---- ...1_magic_switch.ino => xdrv_71_magic_switch.ino} | 8 ++++---- .../{xdrv_92_pipsolar.ino => xdrv_72_pipsolar.ino} | 8 ++++---- tools/decode-status.py | 4 ++-- 5 files changed, 29 insertions(+), 19 deletions(-) rename tasmota/tasmota_xdrv_driver/{xdrv_91_magic_switch.ino => xdrv_71_magic_switch.ino} (97%) rename tasmota/tasmota_xdrv_driver/{xdrv_92_pipsolar.ino => xdrv_72_pipsolar.ino} (99%) diff --git a/CODE_OWNERS.md b/CODE_OWNERS.md index 56a053548..f8b14ee9f 100644 --- a/CODE_OWNERS.md +++ b/CODE_OWNERS.md @@ -79,11 +79,11 @@ In addition to @arendst the following code is mainly owned by: | xdrv_65_tuyamcubr | David Gwynne | xdrv_66_tm1638 | @arendst | xdrv_67_mcp23xxx | @arendst -| xdrv_68_zerocrossDimmer.ino | @stefanbode +| xdrv_68_zerocrossDimmer | @stefanbode | xdrv_69_pca9557 | @cctweaker -| xdrv_70 | -| xdrv_71 | -| xdrv_72 | +| xdrv_70_1_hdmi_cec | @s-hadinger +| xdrv_71_magic_switch | @barbudor +| xdrv_72_pipsolar | @chefpro | xdrv_73 | | xdrv_74 | | xdrv_75 | @@ -100,8 +100,12 @@ In addition to @arendst the following code is mainly owned by: | xdrv_88_esp32_shelly_pro | @arendst | xdrv_89_esp32_dali | @eeak | xdrv_90_esp32_dingtian_relay | @barbudor -| xdrv_92_pipsolar | @chefpro +| xdrv_91_ | +| xdrv_92_ | +| xdrv_93_ | +| xdrv_94_ | | | +| xdrv_121_gpioviewer | @arendst | xdrv_122_file_settings_demo | @arendst | xdrv_127_debug | @arendst | | diff --git a/tasmota/tasmota_support/support_features.ino b/tasmota/tasmota_support/support_features.ino index 5c0e4e03b..ef586a482 100644 --- a/tasmota/tasmota_support/support_features.ino +++ b/tasmota/tasmota_support/support_features.ino @@ -888,7 +888,7 @@ constexpr uint32_t feature[] = { 0x10000000 | // xsns_113_hc8.ino #endif #ifdef USE_HDMI_CEC - 0x20000000 | // xdrv_70_0_hdmi_cec.ino + 0x20000000 | // xdrv_70_1_hdmi_cec.ino #endif #ifdef USE_BLE_ESP32 0x40000000 | // xdrv_79_esp32_ble.ino @@ -897,9 +897,15 @@ constexpr uint32_t feature[] = { 0x80000000 | // xdrv_52_9_berry.ino #endif 0, -// 0x00000001 | // -// 0x00000002 | // -// 0x00000004 | // +#ifdef USE_MAGIC_SWITCH + 0x00000001 | // xdrv_71_magic_switch.ino +#endif +#ifdef USE_PIPSOLAR + 0x00000002 | // xdrv_72_pipsolar.ino +#endif +#ifdef USE_GPIO_VIEWER + 0x00000004 | // xdrv_121_gpioviewer.ino +#endif // 0x00000008 | // // 0x00000010 | // // 0x00000020 | // diff --git a/tasmota/tasmota_xdrv_driver/xdrv_91_magic_switch.ino b/tasmota/tasmota_xdrv_driver/xdrv_71_magic_switch.ino similarity index 97% rename from tasmota/tasmota_xdrv_driver/xdrv_91_magic_switch.ino rename to tasmota/tasmota_xdrv_driver/xdrv_71_magic_switch.ino index c0c128bcd..a0c097b28 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_91_magic_switch.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_71_magic_switch.ino @@ -1,7 +1,7 @@ /* - xdrv_91_magic_switch.ino - Driver for MagicSwitch as implemented in Sonoff BasicR4 + xdrv_71_magic_switch.ino - Driver for MagicSwitch as implemented in Sonoff BasicR4 - Copyright (C) 2021 Barbudor + Copyright (C) 2023 Barbudor 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 @@ -19,7 +19,7 @@ #ifdef USE_MAGIC_SWITCH -#define XDRV_91 91 +#define XDRV_71 71 /******************************************************************************************************** * Check defines @@ -162,7 +162,7 @@ void CmndMagicSwitchPulse(void) * Interface \*********************************************************************************************/ -bool Xdrv91(uint32_t function) { +bool Xdrv71(uint32_t function) { bool result = false; if (FUNC_SETUP_RING2 == function) { diff --git a/tasmota/tasmota_xdrv_driver/xdrv_92_pipsolar.ino b/tasmota/tasmota_xdrv_driver/xdrv_72_pipsolar.ino similarity index 99% rename from tasmota/tasmota_xdrv_driver/xdrv_92_pipsolar.ino rename to tasmota/tasmota_xdrv_driver/xdrv_72_pipsolar.ino index 747704f43..047a29800 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_92_pipsolar.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_72_pipsolar.ino @@ -1,5 +1,5 @@ /* - xdrv_92_pipsolar.ino - modbus bridge support for Tasmota + xdrv_72_pipsolar.ino - pipsolar support for Tasmota Copyright (C) 2023 Peter Rustler @@ -17,9 +17,9 @@ along with this program. If not, see . */ -#if defined(USE_PIPSOLAR) +#ifdef USE_PIPSOLAR -#define XDRV_92 92 +#define XDRV_72 72 #define PIPSOLAR_RECEIVEBUFFER_SIZE TM_SERIAL_BUFFER_SIZE * 2 // 128 #define PIPSOLAR_SENDBUFFER_SIZE TM_SERIAL_BUFFER_SIZE // 64 @@ -1010,7 +1010,7 @@ void PIPSOLARShow(bool json) * Interface \*********************************************************************************************/ -bool Xdrv92(uint32_t function) +bool Xdrv72(uint32_t function) { bool result = true; diff --git a/tools/decode-status.py b/tools/decode-status.py index 3b8af81b4..922472118 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -302,7 +302,7 @@ a_features = [[ "USE_SGP4X","USE_MAX17043","USE_ENS16x","USE_ENS210", "USE_HC8","USE_HDMI_CEC","USE_BLE_ESP32","USE_MATTER_DEVICE" ],[ - "","","","", + "USE_MAGIC_SWITCH","USE_PIPSOLAR","USE_GPIO_VIEWER","", "","","","", "","","","", "","","","", @@ -337,7 +337,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v13.2.0.2 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v13.3.0.2 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj)) From f30f3f8016c5cb3bac8617c640089c3f8c0fa1ef Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 10 Jan 2024 15:51:19 +0100 Subject: [PATCH 119/303] Add user control over GPIOViewer sampling interval --- tasmota/my_user_config.h | 1 + .../xdrv_121_gpioviewer.ino | 63 ++++++++++++++----- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index c3baf0b45..80f75b0d8 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -471,6 +471,7 @@ // #define USE_WEBSEND_RESPONSE // Enable command WebSend response message (+1k code) // #define USE_WEBGETCONFIG // Enable restoring config from external webserver (+0k6) // #define USE_GPIO_VIEWER // Enable GPIO Viewer to see realtime GPIO states (+4k code) +// #define GV_SAMPLING_INTERVAL 100 // [GvSampling] milliseconds - Use Tasmota Scheduler (100) or Ticker (20..99,101..1000) #define USE_EMULATION_HUE // Enable Hue Bridge emulation for Alexa (+14k code, +2k mem common) #define USE_EMULATION_WEMO // Enable Belkin WeMo emulation for Alexa (+6k code, +2k mem common) // #define USE_CCLOADER // Enable CCLoader FW upgrade tool (for CC25xx devices) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index f687deffa..ca6a87f96 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -17,8 +17,13 @@ #define XDRV_121 121 +#ifndef GV_PORT #define GV_PORT 5557 -#define GV_SAMPLING_INTERVAL 100 // milliseconds - Relates to FUNC_EVERY_100_MSECOND +#endif +#ifndef GV_SAMPLING_INTERVAL +#define GV_SAMPLING_INTERVAL 100 // [GvSampling] milliseconds - Use Tasmota Scheduler (100) or Ticker (20..99,101..1000) +#endif + #define GV_KEEP_ALIVE 1000 // milliseconds - If no activity after this do a heap size event anyway #define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" @@ -40,7 +45,7 @@ const char HTTP_GV_PAGE[] PROGMEM = "var serverPort=" STR(GV_PORT) ";" "var ip='%s';" // WiFi.localIP().toString().c_str() "var source=new EventSource('http://%s:" STR(GV_PORT) "/events');" // WiFi.localIP().toString().c_str() - "var sampling_interval='" STR(GV_SAMPLING_INTERVAL) "';" + "var sampling_interval='%d';" // Gv.sampling #ifdef ESP32 "var psramSize='%d KB';" // ESP.getPsramSize() / 1024 #endif // ESP32 @@ -78,15 +83,21 @@ enum GVPinTypes { struct { WiFiClient WebClient; ESP8266WebServer *WebServer; + Ticker ticker; int lastPinStates[MAX_GPIO_PIN]; uint32_t lastSentWithNoActivity; uint32_t freeHeap; uint32_t freePSRAM; + uint32_t sampling; bool active; bool sse_ready; } GV; void GVBegin(void) { + if (0 == GV.sampling) { + GV.sampling = (GV_SAMPLING_INTERVAL < 20) ? 20 : GV_SAMPLING_INTERVAL; + } + GV.WebServer = new ESP8266WebServer(GV_PORT); // Set CORS headers for global responses GV.WebServer->sendHeader("Access-Control-Allow-Origin", "*"); @@ -103,6 +114,7 @@ void GVBegin(void) { void GVStop(void) { GV.sse_ready = false; + GV.ticker.detach(); GV.active = false; GV.WebServer->stop(); @@ -118,15 +130,18 @@ void GVHandleEvents(void) { GV.WebServer->sendContent_P(HTTP_GV_EVENT); GV.sse_ready = true; // Ready for async updates - - AddLog(LOG_LEVEL_DEBUG, PSTR("IOV: Client connected")); + if (GV.sampling != 100) { + GV.ticker.attach_ms(GV.sampling, GVMonitorTask); // Use Tasmota Scheduler (100) or Ticker (20..99,101..1000) + } + AddLog(LOG_LEVEL_DEBUG, PSTR("IOV: Connected")); } void GVHandleRoot(void) { char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, SettingsTextEscaped(SET_DEVICENAME).c_str(), - WiFi.localIP().toString().c_str(), - WiFi.localIP().toString().c_str(), + WiFi.localIP().toString().c_str(), + WiFi.localIP().toString().c_str(), + GV.sampling, #ifdef ESP32 ESP.getPsramSize() / 1024, #endif // ESP32 @@ -136,6 +151,7 @@ void GVHandleRoot(void) { free(content); GV.sse_ready = false; // Allow restart of updates on page load + GV.ticker.detach(); } void GVHandleRelease(void) { @@ -162,11 +178,11 @@ void GVEventSend(const char *message, const char *event, uint32_t id) { GV.WebClient.printf_P(PSTR("id: %u\r\nevent: %s\r\ndata: %s\r\n\r\n"), id, event, message); } else { if (GV.sse_ready) { - AddLog(LOG_LEVEL_DEBUG, PSTR("IOV: Client disconnected")); + AddLog(LOG_LEVEL_DEBUG, PSTR("IOV: Disconnected")); } // GVStop(); // This will stop the webserver but not all memory will be released resulting in memory leaks GV.sse_ready = false; // This just stops the event to be restarted by opening root page again - + GV.ticker.detach(); } } @@ -216,8 +232,8 @@ void GVMonitorTask(void) { originalValue = value; if (value == 1) { currentState = 256; -// } else { -// currentState = 0; +// } else { +// currentState = 0; } } @@ -274,12 +290,17 @@ void GVMonitorTask(void) { \*********************************************************************************************/ const char kGVCommands[] PROGMEM = "GV|" // Prefix - "Viewer"; + "Viewer|Sampling"; void (* const GVCommand[])(void) PROGMEM = { - &CmndGVViewer}; + &CmndGvViewer, &CmndGvSampling }; -void CmndGVViewer(void) { +void CmndGvViewer(void) { + /* GvViewer - Show current viewer state + GvViewer 0 - Turn viewer off + GvViewer 1 - Turn viewer On + GvViewer 2 - Toggle viewer state + */ if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { uint32_t state = XdrvMailbox.payload; if (2 == state) { // Toggle @@ -298,6 +319,18 @@ void CmndGVViewer(void) { } } +void CmndGvSampling(void) { + /* GvSampling - Show current sampling interval + GvSampling 20 .. 1000 - Set sampling interval + */ + if ((XdrvMailbox.payload >= 20) && (XdrvMailbox.payload <= 1000)) { + GV.sse_ready = false; // Stop current updates + GV.ticker.detach(); + GV.sampling = XdrvMailbox.payload; // 20 - 1000 milliseconds + } + ResponseCmndNumber(GV.sampling); +} + /*********************************************************************************************\ * GUI \*********************************************************************************************/ @@ -353,7 +386,9 @@ bool Xdrv121(uint32_t function) { if (GV.WebServer) { GV.WebServer->handleClient(); } break; case FUNC_EVERY_100_MSECOND: - if (GV.sse_ready) { GVMonitorTask(); } + if (GV.sse_ready && (100 == GV.sampling)) { + GVMonitorTask(); + } break; case FUNC_ACTIVE: result = true; From 20c70d578eaa58841f7a3734c4e82072c53760da Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 10 Jan 2024 17:17:56 +0100 Subject: [PATCH 120/303] Remove padding between tool buttons --- tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino index c2f9619d4..b87aec505 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino @@ -3154,8 +3154,7 @@ void HandleManagement(void) XdrvMailbox.index = 0; XdrvXsnsCall(FUNC_WEB_ADD_CONSOLE_BUTTON); - - WSContentSend_P(PSTR("
")); // 5px padding +// WSContentSend_P(PSTR("
")); // 5px padding XdrvCall(FUNC_WEB_ADD_MANAGEMENT_BUTTON); WSContentSpaceButton(BUTTON_MAIN); From 20c54a36471471155b07f757cb2c8ce4e6b477a4 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 11 Jan 2024 10:02:12 +0100 Subject: [PATCH 121/303] Fix compilation of Zigbee for Core3 (#20464) --- .../tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino | 2 +- tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_2_converters.ino | 2 +- tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_0_commands.ino | 2 +- tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_1_greenpower.ino | 4 ++-- tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino index 8d5a71fb5..a8cfdbbc6 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino @@ -795,7 +795,7 @@ void Z_Device::jsonAddEndpoints(Z_attribute_list & attr_list) const { for (uint32_t i = 0; i < endpoints_max; i++) { uint8_t endpoint = endpoints[i]; if (0x00 == endpoint) { break; } - arr_ep.add(endpoint); + arr_ep.add((uint32_t)endpoint); } attr_list.addAttributePMEM(PSTR("Endpoints")).setStrRaw(arr_ep.toString().c_str()); } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_2_converters.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_2_converters.ino index 4fc87f19a..de0d1862a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_2_converters.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_5_2_converters.ino @@ -931,7 +931,7 @@ void ZCLFrame::parseReadAttributes(uint16_t shortaddr, Z_attribute_list& attr_li Z_attribute_list attr_names; while (len >= 2 + i) { uint16_t attrid = payload.get16(i); - attr_numbers.add(attrid); + attr_numbers.add((uint32_t)attrid); read_attr_ids[i/2] = attrid; // find the attribute name diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_0_commands.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_0_commands.ino index aa30eb15d..53ca8f223 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_0_commands.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_0_commands.ino @@ -454,7 +454,7 @@ void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster, JsonGeneratorArray group_list; for (uint32_t i = 0; i < xyz.y; i++) { - group_list.add(payload.get16(2 + 2*i)); + group_list.add((uint32_t)payload.get16(2 + 2*i)); } attr_list.addAttribute(command_name, true).setStrRaw(group_list.toString().c_str()); } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_1_greenpower.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_1_greenpower.ino index 24a11dec6..abe8ac124 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_1_greenpower.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_1_greenpower.ino @@ -161,7 +161,7 @@ bool convertGPDF_Commissioning(class Z_attribute_list &attr_list, uint16_t short JsonGeneratorArray gpdi_list; for (uint32_t i = 0; i < gpid_len; i++) { if (idx_offset >= payload_len + payload_start) { break; } // end of payload - gpdi_list.add(payload.get8(idx_offset++)); + gpdi_list.add((uint32_t)payload.get8(idx_offset++)); } ResponseAppend_P(PSTR(",\"commandid\":%s"), gpdi_list.toString().c_str()); } @@ -171,7 +171,7 @@ bool convertGPDF_Commissioning(class Z_attribute_list &attr_list, uint16_t short JsonGeneratorArray gpdi_list; for (uint32_t i = 0; i < clust_report_len; i++) { if (idx_offset >= payload_len + payload_start) { break; } // end of payload - gpdi_list.add(payload.get16(idx_offset)); + gpdi_list.add((uint32_t)payload.get16(idx_offset)); idx_offset += 2; } ResponseAppend_P(PSTR(",\"clusterreports\":%s"), gpdi_list.toString().c_str()); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino index fee50f5f7..f684a9a6b 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_zigbee.ino @@ -550,7 +550,7 @@ extern "C" { } else if (mode == 12) { a->setKeyName("array"); a->newJsonArray(); - a->val.arrval->add(-1); + a->val.arrval->add((int32_t)-1); a->val.arrval->addStr("foo"); a->val.arrval->addStr("bar"); a->val.arrval->addStr("bar\"baz\'toto"); From b881b55092b2ad80e438243cd94dfffcb420d827 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 11 Jan 2024 12:35:24 +0100 Subject: [PATCH 122/303] add FTP server to Tasmota-4M (esp8266) (#20465) * add FTP server to esp8266 env > 1MB flash * ftp server only 4M Tasmota --- tasmota/include/tasmota_configurations.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tasmota/include/tasmota_configurations.h b/tasmota/include/tasmota_configurations.h index b55626794..a680dc89a 100644 --- a/tasmota/include/tasmota_configurations.h +++ b/tasmota/include/tasmota_configurations.h @@ -1047,6 +1047,17 @@ #define USE_UFILESYS #define GUI_TRASH_FILE #define GUI_EDIT_FILE + #ifdef ESP8266_4M + #ifndef USE_FTP + #define USE_FTP + #endif + #ifndef USER_FTP + #define USER_FTP "user" + #endif + #ifndef PW_FTP + #define PW_FTP "pass" + #endif + #endif // ESP8266_4M #define USE_SPI #define USE_SDCARD #define USE_PING From 8cc615447824cc101f10f67e2e7410a880271d74 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 11 Jan 2024 15:21:53 +0100 Subject: [PATCH 123/303] Update esp8266 Platformio Platform (#20467) --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- platformio.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index c70982081..61722058f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -6,7 +6,7 @@ - [ ] The pull request is done against the latest development branch - [ ] Only relevant files were touched - [ ] Only one feature/fix was added per PR and the code change compiles without warnings - - [ ] The code change is tested and works with Tasmota core ESP8266 V.2.7.4.9 + - [ ] The code change is tested and works with Tasmota core ESP8266 V.2.7.5 - [ ] The code change is tested and works with Tasmota core ESP32 V.2.0.14 - [ ] I accept the [CLA](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla). diff --git a/platformio.ini b/platformio.ini index de12bf4a9..29fc5a43a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -140,7 +140,7 @@ lib_ignore = [core] ; *** Esp8266 Tasmota modified Arduino core based on core 2.7.4. Added Backport for PWM selection -platform = https://github.com/tasmota/platform-espressif8266/releases/download/2023.04.00/platform-espressif8266.zip +platform = https://github.com/tasmota/platform-espressif8266/releases/download/2024.01.00/platform-espressif8266.zip platform_packages = build_unflags = ${esp_defaults.build_unflags} build_flags = ${esp82xx_defaults.build_flags} From 2165ea549ab1899a6768950e238f42817968fe20 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 11 Jan 2024 15:39:13 +0100 Subject: [PATCH 124/303] Update changelogs --- CHANGELOG.md | 2 ++ RELEASENOTES.md | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3ae2ab37..c2d16fcd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,8 @@ All notable changes to this project will be documented in this file. - ESP32 platform update from 2023.12.00 to 2024.01.00 (#20445) - Header `Host` is now collected by Webserver (#20446) - Webcam tweaks (#20451) +- ESP8266 platform update from 2023.04.00 to 2024.01.00 (#20467) +- ESP8266 Framework (Arduino Core) from v2.7.4.9 to v2.7.5 (#20467) ### Fixed - ESP32 Zigbee Aqara attributes (#20452) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 09ffd3afb..d17e5cb3c 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -34,11 +34,11 @@ While fallback or downgrading is common practice it was never supported due to S ## Supported Core versions -This release will be supported from ESP8266/Arduino library Core version **2.7.4.9** due to reported security and stability issues on previous Core version. This will also support gzipped binaries. +This release will be supported from ESP8266/Arduino library Core version **2.7.5** due to reported security and stability issues on previous Core version. This will also support gzipped binaries. This release will be supported from ESP32/Arduino library Core version **2.0.14**. -Support of ESP8266 Core versions before 2.7.4.9 and ESP32 Core versions before 2.0.14 have been removed. +Support of ESP8266 Core versions before 2.7.5 and ESP32 Core versions before 2.0.14 have been removed. ## Support of TLS @@ -55,7 +55,7 @@ Easy initial installation of Tasmota can be performed using the [Tasmota WebInst ## Provided Binary Downloads ### ESP8266 or ESP8285 based -The following binary downloads have been compiled with ESP8266/Arduino library core version **2.7.4.9**. +The following binary downloads have been compiled with ESP8266/Arduino library core version **2.7.5**. - **tasmota.bin** = The Tasmota version with most drivers for 1M+ flash. **RECOMMENDED RELEASE BINARY** - **tasmota-4M.bin** = The Tasmota version with most drivers and filesystem for 4M+ flash. @@ -147,6 +147,8 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Refactoring of Berry `animate` module for WS2812 Leds [#20236](https://github.com/arendst/Tasmota/issues/20236) ### Changed +- ESP8266 platform update from 2023.04.00 to 2024.01.00 [#20467](https://github.com/arendst/Tasmota/issues/20467) +- ESP8266 Framework (Arduino Core) from v2.7.4.9 to v2.7.5 [#20467](https://github.com/arendst/Tasmota/issues/20467) - ESP32 platform update from 2023.11.01 to 2024.01.00 [#20445](https://github.com/arendst/Tasmota/issues/20445) - Renamed button "Consoles" to "Tools" - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` [#20260](https://github.com/arendst/Tasmota/issues/20260) From b0f4542707546ba7f19822338f54d5b6f1a7fb14 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Fri, 12 Jan 2024 08:29:14 +0100 Subject: [PATCH 125/303] Berry `debug.caller` (#20470) --- CHANGELOG.md | 1 + lib/libesp32/berry/src/be_byteslib.c | 2 ++ lib/libesp32/berry/src/be_debuglib.c | 23 +++++++++++++++++++++++ lib/libesp32/berry/tests/bytes.be | 15 ++++++++++++++- lib/libesp32/berry/tests/debug.be | 27 ++++++++++++++++++++++++++- 5 files changed, 66 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2d16fcd1..879cb98f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ All notable changes to this project will be documented in this file. - Berry provide lightweight options for `tasmota.wifi/eth/memory/rtc` (#20448) - Berry `tasmota.webcolor` (#20454) - Support for pipsolar inverter (#20408) +- Berry `debug.caller` ### Breaking Changed diff --git a/lib/libesp32/berry/src/be_byteslib.c b/lib/libesp32/berry/src/be_byteslib.c index 8d351997d..221e3e2a4 100644 --- a/lib/libesp32/berry/src/be_byteslib.c +++ b/lib/libesp32/berry/src/be_byteslib.c @@ -1768,6 +1768,7 @@ void be_load_byteslib(bvm *vm) { "clear", m_clear }, { "reverse", m_reverse }, { "copy", m_copy }, + { "append", m_connect }, { "+", m_merge }, { "..", m_connect }, { "==", m_equal }, @@ -1815,6 +1816,7 @@ class be_class_bytes (scope: global, name: bytes) { clear, func(m_clear) reverse, func(m_reverse) copy, func(m_copy) + append, func(m_connect) +, func(m_merge) .., func(m_connect) ==, func(m_equal) diff --git a/lib/libesp32/berry/src/be_debuglib.c b/lib/libesp32/berry/src/be_debuglib.c index fac4bfb53..2e4ee9bf4 100644 --- a/lib/libesp32/berry/src/be_debuglib.c +++ b/lib/libesp32/berry/src/be_debuglib.c @@ -13,6 +13,7 @@ #include "be_debug.h" #include "be_map.h" #include "be_vm.h" +#include "be_exec.h" #include #if BE_USE_DEBUG_MODULE @@ -103,6 +104,26 @@ static int m_traceback(bvm *vm) be_return_nil(vm); } +static int m_caller(bvm *vm) +{ + int depth = 1; + if (be_top(vm) >= 1 && be_isint(vm, 1)) { + depth = be_toint(vm, 1); + if (depth < 0) { + depth = -depth; /* take absolute value */ + } + } + bcallframe *cf = (bcallframe*)be_stack_top(&vm->callstack) - depth; + bcallframe *base = be_stack_base(&vm->callstack); + if (cf >= base) { + bvalue *reg = be_incrtop(vm); + var_setval(reg, cf->func); + be_return(vm); + } else { + be_return_nil(vm); + } +} + #if BE_USE_DEBUG_HOOK static int m_sethook(bvm *vm) { @@ -236,6 +257,7 @@ be_native_module_attr_table(debug) { be_native_module_function("varname", m_varname), be_native_module_function("upvname", m_upvname) #endif + be_native_module_function("caller", m_caller), be_native_module_function("gcdebug", m_gcdebug) }; @@ -252,6 +274,7 @@ module debug (scope: global, depend: BE_USE_DEBUG_MODULE) { top, func(m_top) varname, func(m_varname), BE_DEBUG_VAR_INFO upvname, func(m_upvname), BE_DEBUG_VAR_INFO + caller, func(m_caller) // individual counters allocs, func(m_allocs) frees, func(m_frees) diff --git a/lib/libesp32/berry/tests/bytes.be b/lib/libesp32/berry/tests/bytes.be index 4621747b1..c4d4af3f6 100644 --- a/lib/libesp32/berry/tests/bytes.be +++ b/lib/libesp32/berry/tests/bytes.be @@ -110,13 +110,20 @@ assert(str(b) == "bytes('AA')") b = b1 + '01' assert(str(b) == "bytes('AA3031')") -#- .. -# +#- .. and append as synonym-# b1 = bytes("1122") b2 = bytes("334455") b = b1..b2 assert(str(b1) == "bytes('1122334455')") assert(str(b2) == "bytes('334455')") assert(str(b) == "bytes('1122334455')") +# +b1 = bytes("1122") +b2 = bytes("334455") +b = b1.append(b2) +assert(str(b1) == "bytes('1122334455')") +assert(str(b2) == "bytes('334455')") +assert(str(b) == "bytes('1122334455')") #- .. with string -# b1 = bytes("AA") @@ -124,6 +131,12 @@ b1 .. '' assert(str(b1) == "bytes('AA')") b1 .. '01' assert(str(b1) == "bytes('AA3031')") +# +b1 = bytes("AA") +b1.append('') +assert(str(b1) == "bytes('AA')") +b1.append('01') +assert(str(b1) == "bytes('AA3031')") #- item -# b = bytes("334455") diff --git a/lib/libesp32/berry/tests/debug.be b/lib/libesp32/berry/tests/debug.be index 9e732f6c3..88b559d81 100644 --- a/lib/libesp32/berry/tests/debug.be +++ b/lib/libesp32/berry/tests/debug.be @@ -1,4 +1,29 @@ import debug class A end -debug.attrdump(A) #- should not crash -# \ No newline at end of file +debug.attrdump(A) #- should not crash -# + +# debug.caller() +def caller_name_chain() + import debug + import introspect + var i = 1 + var ret = [] + var caller = debug.caller(i) + while caller + ret.push(introspect.name(caller)) + i += 1 + caller = debug.caller(i) + end + return ret +end +var chain = caller_name_chain() +assert(chain[0] == 'caller_name_chain') + +def guess_my_name__() + return caller_name_chain() +end +chain = guess_my_name__() +print(chain) +assert(chain[0] == 'caller_name_chain') +assert(chain[1] == 'guess_my_name__') From fa6d18a505476139c4c645dead46d292121e3c8c Mon Sep 17 00:00:00 2001 From: gemu Date: Fri, 12 Jan 2024 10:04:19 +0100 Subject: [PATCH 126/303] fix memory leak in >w x (#20473) --- .../tasmota_xdrv_driver/xdrv_10_scripter.ino | 130 +++++++++++++++--- 1 file changed, 111 insertions(+), 19 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino index efaf21f5f..9b71d05c5 100755 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino @@ -341,17 +341,10 @@ typedef union { } SCRIPT_TYPE; -#if 1 struct T_INDEX { uint16_t index; SCRIPT_TYPE bits; }; -#else -struct T_INDEX { - uint8_t index; - SCRIPT_TYPE bits; -}; -#endif struct M_FILT { #ifdef LARGE_ARRAYS @@ -570,6 +563,10 @@ struct SCRIPT_MEM { WiFiClient tcp_client; #endif +#ifdef SCRIPT_FULL_WEBPAGE + uint8_t wsp; +#endif + } glob_script_mem; @@ -621,6 +618,7 @@ char *scripter_sub(char *lp, uint8_t fromscriptcmd); char *GetNumericArgument(char *lp,uint8_t lastop,TS_FLOAT *fp, struct GVARS *gv); char *GetStringArgument(char *lp,uint8_t lastop,char *cp, struct GVARS *gv); char *ForceStringVar(char *lp,char *dstr); +char *GetLongIString(char *lp, char **dstr); void send_download(void); uint8_t UfsReject(char *name); #ifdef USE_UFILESYS @@ -755,6 +753,10 @@ char *script; return -7; } +#ifdef SCRIPT_FULL_WEBPAGE + // glob_script_mem.wsp = 0; +#endif + char *vnames = (char*)imemptr; char *vnp[maxvars]; @@ -3522,10 +3524,12 @@ extern void W8960_SetGain(uint8_t sel, uint16_t value); // read file from web lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv); SCRIPT_SKIP_SPACES - char url[SCRIPT_MAXSSIZE]; - lp = ForceStringVar(lp, url); - SCRIPT_SKIP_SPACES - fvar = url2file(fvar, url); + char *url; + lp = GetLongIString(lp, &url); + if (url) { + fvar = url2file(fvar, url); + } + if (url) free(url); goto nfuncexit; } #endif @@ -3788,6 +3792,70 @@ extern void W8960_SetGain(uint8_t sel, uint16_t value); goto nfuncexit; } + if (!strncmp_XP(lp, XPSTR("fcs("), 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv); + uint8_t find = fvar; + SCRIPT_SKIP_SPACES + char delim[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, delim, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &fvar, gv); + SCRIPT_SKIP_SPACES + uint8_t index = fvar; + if (!index) index = 1; + char delimc = 0; + if (*lp != ')') { + // get delimiter + delimc = *lp; + lp++; + } + char fstr[SCRIPT_MAXSSIZE]; + fstr[0] = 0; + bool match = false; + uint8_t dstrlen = strlen(delim); + if (glob_script_mem.file_flags[find].is_open) { + glob_script_mem.files[find].seek(0, SeekSet); + uint8_t first = 0; + uint8_t clen = 0; + while (glob_script_mem.files[find].available()) { + uint8_t buf[1]; + glob_script_mem.files[find].read(buf, 1); + // shift string + memmove(&fstr[0], &fstr[1], dstrlen - 1); + fstr[dstrlen - 1] = buf[0]; + if (!strncmp(delim, fstr, dstrlen)) { + // match + //AddLog(LOG_LEVEL_INFO, PSTR(">>: %s - %s - %d - %d"), delim, fstr, dstrlen, index); + index--; + if (!index) { + match = true; + break; + } + } + } + if (match == true) { + clen = 0; + while (glob_script_mem.files[find].available()) { + uint8_t buf[1]; + glob_script_mem.files[find].read(buf, 1); + if (buf[0] == delimc) { + break; + } + fstr[clen] = buf[0]; + clen++; + if (clen >= sizeof(fstr)) { + break; + } + } + fstr[clen] = 0; + } + if (sp) strlcpy(sp, fstr, glob_script_mem.max_ssize); + } + len = 0; + lp++; + goto strexit; + } + #endif // USE_SCRIPT_FATFS_EXT if (!strncmp_XP(lp, XPSTR("fl1("), 4) || !strncmp_XP(lp, XPSTR("fl2("), 4) ) { uint8_t lknum = *(lp + 2) & 3; @@ -4314,7 +4382,7 @@ extern void W8960_SetGain(uint8_t sel, uint16_t value); tind->bits.is_string = 0; return lp + len; } -#ifdef USE_LVGL +#ifdef xUSE_LVGL if (!strncmp_XP(lp, XPSTR("lvgl("), 5)) { lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv); SCRIPT_SKIP_SPACES @@ -6436,6 +6504,27 @@ struct T_INDEX ind; } } +char *GetLongIString(char *lp, char **dstr) { + while (*lp == ' ') lp++; + if (*lp != '"') { + *dstr = (char*)malloc(SCRIPT_MAXSSIZE); + if (!*dstr) return lp; + lp = GetStringArgument(lp, OPER_EQU, *dstr, 0); + } else { + lp++; + char *cp = strchr(lp, '"'); + if (cp) { + uint16_t slen = (uint32_t)cp - (uint32_t)lp; + *dstr = (char*)calloc(slen + 2, 1); + if (!*dstr) return lp; + memmove(*dstr, lp, slen); + lp = cp + 1; + } else { + // error + } + } + return lp; +} char *ForceStringVar(char *lp, char *dstr) { TS_FLOAT fvar; @@ -6902,7 +6991,7 @@ void esp_pwm(int32_t value, uint32 freq, uint32_t channel) { if (value > 1023) { value = 1023; } - AnalogWrite(pwmpin[channel],value); + AnalogWrite(pwmpin[channel], value); } #endif // ESP32 } @@ -12031,6 +12120,7 @@ int32_t url2file(uint8_t fref, char *url) { HTTPClient http; int32_t httpCode = 0; String weburl = "http://"+UrlEncode(url); + for (uint32_t retry = 0; retry < 3; retry++) { http.begin(http_client, weburl); delay(100); @@ -12121,7 +12211,7 @@ int32_t http_req(char *host, char *request) { glob_script_mem.glob_error = 0; -#endif +#endif // USE_WEBSEND_RESPONSE http.end(); http_client.stop(); @@ -12347,7 +12437,7 @@ uint32_t script_i2c(uint8_t sel, uint16_t val, uint32_t val1) { #endif // USE_SCRIPT_I2C -#ifdef USE_LVGL +#ifdef xUSE_LVGL #include #include "lvgl.h" @@ -12761,8 +12851,12 @@ void script_add_subpage(uint8_t num) { wptr = ScriptFullWebpage7; break; } - sprintf_P(id, PSTR("/sfd%1d"), num); - Webserver->on(id, wptr); + uint8_t flag = 1 << num; + if (!(glob_script_mem.wsp & flag)) { + sprintf_P(id, PSTR("/sfd%1d"), num); + Webserver->on(id, wptr); + glob_script_mem.wsp |= flag; + } WSContentSend_P(HTTP_WEB_FULL_DISPLAY, num, bname); } } @@ -12773,8 +12867,6 @@ void script_add_subpage(uint8_t num) { \*********************************************************************************************/ //const esp_partition_t *esp32_part; - - bool Xdrv10(uint32_t function) { bool result = false; From 03cadd29f3fd4a86182feacf150b1372134396e5 Mon Sep 17 00:00:00 2001 From: gemu Date: Fri, 12 Jan 2024 10:05:25 +0100 Subject: [PATCH 127/303] Sml update (#20474) * add decryption flags * add gcm crypto flags --- lib/lib_div/ams/DataParser.h | 1 + lib/lib_div/ams/GcmParser.cpp | 23 +++++++++++++++------ lib/lib_div/ams/han_Parser.cpp | 3 ++- lib/lib_div/ams/han_Parser.h | 2 +- tasmota/tasmota_xsns_sensor/xsns_53_sml.ino | 14 +++++++++++-- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/lib/lib_div/ams/DataParser.h b/lib/lib_div/ams/DataParser.h index 6aa92faec..0a11e6792 100644 --- a/lib/lib_div/ams/DataParser.h +++ b/lib/lib_div/ams/DataParser.h @@ -23,6 +23,7 @@ struct DataParserContext { uint8_t type; + uint8_t flags; uint16_t length; time_t timestamp; uint8_t system_title[8]; diff --git a/lib/lib_div/ams/GcmParser.cpp b/lib/lib_div/ams/GcmParser.cpp index 12ac94a2b..724d4a094 100644 --- a/lib/lib_div/ams/GcmParser.cpp +++ b/lib/lib_div/ams/GcmParser.cpp @@ -36,13 +36,19 @@ int8_t GCMParser::parse(uint8_t *d, DataParserContext &ctx) { int len = 0; int headersize = 2 + systemTitleLength; ptr += systemTitleLength; - if(((*ptr) & 0xFF) == 0x81) { + + if (ctx.flags & 1) { + len = *ptr; + ptr++; + headersize++; + } else { + if(((*ptr) & 0xFF) == 0x81) { ptr++; len = *ptr; // 1-byte payload length ptr++; headersize += 2; - } else if(((*ptr) & 0xFF) == 0x82) { + } else if(((*ptr) & 0xFF) == 0x82) { GCMSizeDef* h = (GCMSizeDef*) ptr; // 2-byte payload length @@ -50,14 +56,19 @@ int8_t GCMParser::parse(uint8_t *d, DataParserContext &ctx) { ptr += 3; headersize += 3; - } else if(((*ptr) & 0xFF) == 0x4f) { - // ???????? single frame did only decode with this compare + } else if(((*ptr) & 0xFF) == 0x4f) { + // ???????? single frame did only decode with this compare ptr++; headersize++; - } else if(((*ptr) & 0xFF) == 0x5e) { - // ???????? single frame did only decode with this compare + } else if(((*ptr) & 0xFF) == 0x5e) { + // ???????? single frame did only decode with this compare ptr++; headersize++; + } else { + len = *ptr; + ptr++; + headersize++; + } } if(len + headersize > ctx.length) return DATA_PARSE_INCOMPLETE; diff --git a/lib/lib_div/ams/han_Parser.cpp b/lib/lib_div/ams/han_Parser.cpp index 97bd2449c..d15c297b0 100644 --- a/lib/lib_div/ams/han_Parser.cpp +++ b/lib/lib_div/ams/han_Parser.cpp @@ -44,7 +44,7 @@ int16_t Han_Parser::serial_readBytes(uint8_t *buf, uint16_t size) { return size; } -bool Han_Parser::readHanPort(uint8_t **out, uint16_t *size) { +bool Han_Parser::readHanPort(uint8_t **out, uint16_t *size, uint8_t flags) { if (!serial_available()) return false; @@ -56,6 +56,7 @@ bool Han_Parser::readHanPort(uint8_t **out, uint16_t *size) { } DataParserContext ctx = {0}; + ctx.flags = flags; int pos = DATA_PARSE_INCOMPLETE; // For each byte received, check if we have a complete frame we can handle while (serial_available() && pos == DATA_PARSE_INCOMPLETE) { diff --git a/lib/lib_div/ams/han_Parser.h b/lib/lib_div/ams/han_Parser.h index 1847865dd..2011de4cf 100644 --- a/lib/lib_div/ams/han_Parser.h +++ b/lib/lib_div/ams/han_Parser.h @@ -18,7 +18,7 @@ class Han_Parser public: Han_Parser(uint16_t (*)(uint8_t, uint8_t), uint8_t, uint8_t *, uint8_t *); ~Han_Parser(void); - bool readHanPort(uint8_t **out, uint16_t *size); + bool readHanPort(uint8_t **out, uint16_t *size, uint8_t flags); int16_t unwrapData(uint8_t *buf, DataParserContext &context); void printHanReadError(int16_t pos); uint8_t encryptionKey[16]; diff --git a/tasmota/tasmota_xsns_sensor/xsns_53_sml.ino b/tasmota/tasmota_xsns_sensor/xsns_53_sml.ino index a1b81c9b3..89fe8d296 100755 --- a/tasmota/tasmota_xsns_sensor/xsns_53_sml.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_53_sml.ino @@ -186,6 +186,10 @@ on esp8266 2 filter masks 9: on esp32 1 filter on esp8266 6 filters + +A: +decryption flags (8 bits) + */ //#define MODBUS_DEBUG @@ -490,6 +494,7 @@ struct METER_DESC { #ifdef USE_SML_DECRYPT bool use_crypt = false; + uint8_t crypflags; uint8_t last_iob; uint8_t key[SML_CRYPT_SIZE]; Han_Parser *hp; @@ -753,7 +758,7 @@ void dump2log(void) { d_lastms = millis(); uint16_t logsiz; uint8_t *payload; - if (mp->hp->readHanPort(&payload, &logsiz)) { + if (mp->hp->readHanPort(&payload, &logsiz, mp->crypflags)) { if (logsiz > mp->sbsiz) { logsiz = mp->sbsiz; } @@ -1408,7 +1413,7 @@ void sml_shift_in(uint32_t meters, uint32_t shard) { mp->lastms = millis(); uint16_t len; uint8_t *payload; - if (mp->hp->readHanPort(&payload, &len)) { + if (mp->hp->readHanPort(&payload, &len, mp->crypflags)) { if (len > mp->sbsiz) { len = mp->sbsiz; } @@ -2868,6 +2873,10 @@ struct METER_DESC *mp = &meter_desc[mnum]; } break; #endif // USE_SML_AUTHKEY + case 'A': + cp += 2; + mp->crypflags = strtol(cp, &cp, 10); + break; #endif // USE_SML_DECRYPT case '6': cp += 2; @@ -3633,6 +3642,7 @@ next_line: #else mp->hp = new Han_Parser(serial_dispatch, meters, mp->key, nullptr); #endif + mp->crypflags = 0; } #endif } From b69cc802db84659323c477114c5137a4d2ec00e9 Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Fri, 12 Jan 2024 10:06:55 +0100 Subject: [PATCH 128/303] [MI BLE] added support for LYWSD02MMC (#20381) * [MI BLE] added support for LYWSD02MMC - initial support for MI LYWSD02MMC - code rework * Update CHANGELOG.md * Update CHANGELOG.md * [MI BLE] add Mi32Time / bugfixes * [MI BLE] plain read, debug enhanced * [MI BLE] add LYWSD02MMC battery * [MI BLE] improved debug log, code cleanup * [MI BLE] improved debug log, code optimize --- .../tasmota_xdrv_driver/xdrv_79_esp32_ble.ino | 2 +- .../xsns_62_esp32_mi_ble.ino | 418 ++++++++---------- 2 files changed, 188 insertions(+), 232 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_79_esp32_ble.ino b/tasmota/tasmota_xdrv_driver/xdrv_79_esp32_ble.ino index c907868e1..f10061a8c 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_79_esp32_ble.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_79_esp32_ble.ino @@ -2587,7 +2587,7 @@ void CmndBLEAdv(void){ ////////////////////////////////////////////////////////////// -// Determine what to do with advertismaents +// Determine what to do with advertisements // BLEAdv0 -> suppress MQTT about devices found // BLEAdv1 -> send MQTT about devices found after each scan void CmndBLEDebug(void){ diff --git a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino index c286bad38..3cda0633a 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino @@ -19,11 +19,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . - - +*/ +#define MI32_VERSION "V0.9.2.4" +/* -------------------------------------------------------------------------------------------- Version yyyymmdd Action Description -------------------------------------------------------------------------------------------- + 0.9.2.4 20240111 changed - Enhancement of debug log output + ------- + 0.9.2.3 20240101 changed - added initial support for MI LYWSD02MMC + ------- 0.9.2.2 20231123 changed - added support for Avago Tech Bluetooth buttons ------- 0.9.2.1 20210217 changed - make features alos depend on received data - i.e. 'unknown' devices will show what they send. @@ -69,6 +74,9 @@ */ //#undef USE_MI_ESP32 +// Move to language files later +#define D_BATTERY "Battery" + // for testing of BLE_ESP32, we remove xsns_62_MI_ESP32.ino completely, and instead add this modified xsns_52_ibeacon_BLE_ESP32.ino #ifdef USE_BLE_ESP32 @@ -265,12 +273,8 @@ struct mi_beacon_data_payload_data_t { // }; }; - - /////////////////////////////////////////////////////////// - - union mi_bindKey_t{ struct{ uint8_t key[16]; @@ -490,8 +494,9 @@ void (*const MI32_Commands[])(void) PROGMEM = { #define MI_CGDK2 17 #define AT_BTN 18 #define MI_SJWS01LM 19 +#define MI_LYWSD02MMC 20 -#define MI_MI32_TYPES 19 //count this manually +#define MI_MI32_TYPES 20 //count this manually const uint16_t kMI32DeviceID[MI_MI32_TYPES]={ 0x0000, // Unkown @@ -509,10 +514,11 @@ const uint16_t kMI32DeviceID[MI_MI32_TYPES]={ 0x0a1c, // ATC -> this is a fake ID 0x098b, // door/window sensor 0x181d, // Mi Scale V1 - 0x181b, // Mi Scale V2 - 0x066f, // CGDK2 + 0x181b, // Mi Scale V2 + 0x066f, // CGDK2 0x004e, // Avago Tech Bluetooth Buttons (Company Id) - 0x0863 // SJWS01LM + 0x0863, // SJWS01LM + 0x2542 // LYWSD02MMC }; const char kMI32DeviceType0[] PROGMEM = "Unknown"; @@ -534,7 +540,11 @@ const char kMI32DeviceType15[] PROGMEM ="MISCALEV2"; const char kMI32DeviceType16[] PROGMEM ="CGDK2"; const char kMI32DeviceType17[] PROGMEM ="ATBTN"; const char kMI32DeviceType18[] PROGMEM = "SJWS01LM"; -const char * kMI32DeviceType[] PROGMEM = {kMI32DeviceType0,kMI32DeviceType1,kMI32DeviceType2,kMI32DeviceType3,kMI32DeviceType4,kMI32DeviceType5,kMI32DeviceType6,kMI32DeviceType7,kMI32DeviceType8,kMI32DeviceType9,kMI32DeviceType10,kMI32DeviceType11,kMI32DeviceType12,kMI32DeviceType13,kMI32DeviceType14,kMI32DeviceType15,kMI32DeviceType16,kMI32DeviceType17,kMI32DeviceType18}; +const char kMI32DeviceType19[] PROGMEM = "LYWSD02MMC"; +const char * kMI32DeviceType[] PROGMEM = {kMI32DeviceType0, kMI32DeviceType1, kMI32DeviceType2, kMI32DeviceType3, + kMI32DeviceType4, kMI32DeviceType5, kMI32DeviceType6, kMI32DeviceType7, kMI32DeviceType8, kMI32DeviceType9, + kMI32DeviceType10, kMI32DeviceType11, kMI32DeviceType12, kMI32DeviceType13, kMI32DeviceType14, kMI32DeviceType15, + kMI32DeviceType16, kMI32DeviceType17, kMI32DeviceType18, kMI32DeviceType19}; typedef int BATREAD_FUNCTION(int slot); typedef int UNITWRITE_FUNCTION(int slot, int unit); @@ -632,6 +642,19 @@ int toggleUnit(BLE_ESP32::generic_sensor_t *op){ return 0; } +const char *MIaddrStr(const uint8_t *addr, int useAlias = 0) { + static char addrstr[32]; + const char *id = nullptr; + if (useAlias){ + id = BLE_ESP32::getAlias(addr); + } + if (!id || !(*id)){ + id = addrstr; + BLE_ESP32::dump(addrstr, 13, addr, 6); + } + return id; +} + bool MI32Operation(int slot, int optype, const char *svc, const char *charactistic, const char *notifychar = nullptr, const uint8_t *data = nullptr, int datalen = 0, uint8_t *addr = nullptr ) { if (!svc || !svc[0]){ AddLog(LOG_LEVEL_ERROR, PSTR("M32: Op inv svc")); @@ -646,7 +669,7 @@ bool MI32Operation(int slot, int optype, const char *svc, const char *charactist AddLog(LOG_LEVEL_ERROR,PSTR("M32: Can't get a newOperation")); return 0; } else { - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: Got a newOperation")); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: Got a newOperation")); } if (slot >= 0){ @@ -669,7 +692,6 @@ bool MI32Operation(int slot, int optype, const char *svc, const char *charactist return 0; } - if (charactistic && charactistic[0]){ havechar = true; op->characteristicUUID = NimBLEUUID(charactistic); @@ -708,7 +730,7 @@ bool MI32Operation(int slot, int optype, const char *svc, const char *charactist uint32_t context = (optype << 24) | (MIBLEsensors[slot].type << 16) | slot; op->context = (void *)context; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: MI s:%d op:%s"), slot, BLE_ESP32::BLETriggerResponse(op).c_str()); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: MI s:%d op:%s"), slot, BLE_ESP32::BLETriggerResponse(op).c_str()); res = BLE_ESP32::extQueueOperation(&op); if (!res){ @@ -720,8 +742,6 @@ bool MI32Operation(int slot, int optype, const char *svc, const char *charactist return res; } - - int genericBatReadFn(int slot){ int res = 0; @@ -755,15 +775,13 @@ int genericBatReadFn(int slot){ break; } if (res > 0){ - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_INFO, PSTR("M32: Req batt read slot %d type %d queued"), slot, MIBLEsensors[slot].type); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_INFO, PSTR("M32: Req batt read slot %d type %d queued"), slot, MIBLEsensors[slot].type); } else { - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_INFO, PSTR("M32: Req batt read slot %d type %d non-queued res %d"), slot, MIBLEsensors[slot].type, res); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_INFO, PSTR("M32: Req batt read slot %d type %d non-queued res %d"), slot, MIBLEsensors[slot].type, res); } return res; } - - int genericSensorReadFn(int slot, int force){ int res = 0; switch(MIBLEsensors[slot].type) { @@ -780,6 +798,9 @@ int genericSensorReadFn(int slot, int force){ if (MIBLEsensors[slot].needkey == KEY_REQUIRED_AND_FOUND && !force) return -2; res = MI32Operation(slot, OP_READ_HT_LY, LYWSD03_Svc, nullptr, LYWSD03_BattNotifyChar); break; + case MI_LYWSD02MMC: + res = MI32Operation(slot, OP_READ_HT_LY, LYWSD03_Svc, nullptr, LYWSD03_BattNotifyChar); + break; case MI_MHOC401: // don't read if key present and we've decoded at least one advert if (MIBLEsensors[slot].needkey == KEY_REQUIRED_AND_FOUND && !force) return -2; @@ -793,7 +814,6 @@ int genericSensorReadFn(int slot, int force){ return res; } - // called once per second int readOneSensor(){ if (MI32.sensorreader.active){ @@ -812,7 +832,7 @@ int readOneSensor(){ } res = genericSensorReadFn(MI32.sensorreader.slot, 0); - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: genericSensorReadFn slot %d res %d"), MI32.sensorreader.slot, res); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: genericSensorReadFn slot %d res %d"), MI32.sensorreader.slot, res); // if this sensor in this slot does not need to be read via notify, just move on top the next one if (res < 0){ @@ -833,14 +853,12 @@ int readOneSensor(){ // and make it wait until the read/notify is complete // this is cleared in the response callback. MI32.sensorreader.active = 1; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: readOneSensor reading for slot %d res %d"), MI32.sensorreader.slot-1, res); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: readOneSensor reading for slot %d res %d"), MI32.sensorreader.slot-1, res); // started one return 1; } - - // called once per second int readOneBat(){ if (MI32.batteryreader.active){ @@ -858,7 +876,7 @@ int readOneBat(){ if (res < 0){ MI32.batteryreader.slot++; if (MI32.batteryreader.slot >= MIBLEsensors.size()){ - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_INFO, PSTR("M32: Batt loop complete at %d"), MI32.batteryreader.slot); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_INFO, PSTR("M32: Batt loop complete at %d"), MI32.batteryreader.slot); } return 0; } @@ -874,14 +892,12 @@ int readOneBat(){ // this is cleared in the response callback. MI32.batteryreader.active = 1; if (MI32.batteryreader.slot >= MIBLEsensors.size()){ - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_INFO, PSTR("M32: Batt loop will complete at %d"), MI32.batteryreader.slot); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_INFO, PSTR("M32: Batt loop will complete at %d"), MI32.batteryreader.slot); } // started one return 1; } - - ///////////////////////////////////////////////////// // change the unit of measurement? // call with unit == -1 to cause the unit to be toggled. @@ -925,12 +941,12 @@ int genericUnitReadFn(int slot){ return res; } - ///////////////////////////////////////////////////// // write time to a device. genericOpCompleteFn int genericTimeWriteFn(int slot){ int res = 0; switch (MIBLEsensors[slot].type){ + case MI_LYWSD02MMC: case MI_LYWSD02: { union { uint8_t buf[5]; @@ -956,11 +972,10 @@ int genericTimeWriteFn(int slot){ return res; } - int genericOpCompleteFn(BLE_ESP32::generic_sensor_t *op){ uint32_t context = (uint32_t) op->context; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: MI op complete context %x"), context); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: MI op complete context %x"), context); int opType = context >> 24; int devType = (context >> 16) & 0xff; @@ -981,7 +996,7 @@ int genericOpCompleteFn(BLE_ESP32::generic_sensor_t *op){ } if (op->state <= GEN_STATE_FAILED){ - AddLog(LOG_LEVEL_ERROR, PSTR("M32: Operation failed %d for %s"), op->state, slotMAC); + AddLog(LOG_LEVEL_ERROR, PSTR("M32: %s: Operation failed %d"), slotMAC, op->state); fail = true; } @@ -1001,7 +1016,7 @@ int genericOpCompleteFn(BLE_ESP32::generic_sensor_t *op){ switch(opType){ case OP_TIME_WRITE: - AddLog(LOG_LEVEL_DEBUG, PSTR("M32: Time write for %s complete"), slotMAC); + AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: Time write complete"), slotMAC); return 0; // nothing to do case OP_BATT_READ:{ uint8_t *data = nullptr; @@ -1020,33 +1035,33 @@ int genericOpCompleteFn(BLE_ESP32::generic_sensor_t *op){ // allow another... MI32.batteryreader.active = 0; - AddLog(LOG_LEVEL_INFO, PSTR("M32: Batt read slot %d done state %x"), slot, op->state); + AddLog(LOG_LEVEL_INFO, PSTR("M32: %s: Batt read slot %d done state %x"), slotMAC, slot, op->state); } return 0; case OP_UNIT_WRITE: // nothing more to do? - AddLog(LOG_LEVEL_DEBUG, PSTR("M32: Unit write for %s complete"), slotMAC); + AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: Unit write complete"), slotMAC); return 0; case OP_UNIT_READ: { uint8_t currUnit = op->dataRead[0]; - AddLog(LOG_LEVEL_DEBUG, PSTR("M32: Unit read for %s complete %d"), slotMAC, currUnit); + AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: Unit read complete %d"), slotMAC, currUnit); } return 0; case OP_UNIT_TOGGLE: { uint8_t currUnit = op->dataToWrite[0]; - AddLog(LOG_LEVEL_DEBUG, PSTR("M32: Unit toggle for %s complete %d->%d; datasize was %d"), slotMAC, op->dataRead[0], op->dataToWrite[0], op->readlen); + AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: Unit toggle complete %d->%d; datasize was %d"), slotMAC, op->dataRead[0], op->dataToWrite[0], op->readlen); } return 0; case OP_READ_HT_LY: { // allow another... MI32.sensorreader.active = 0; MI32notifyHT_LY(slot, (char*)op->dataNotify, op->notifylen); - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: HT_LY notify for %s complete"), slotMAC); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: HT_LY notify complete"), slotMAC); } return 0; default: - AddLog(LOG_LEVEL_ERROR, PSTR("M32: OpType %d not recognised?"), opType); + AddLog(LOG_LEVEL_ERROR, PSTR("M32: %s: OpType %d not recognised?"), slotMAC, opType); return 0; } @@ -1070,7 +1085,7 @@ int MI32advertismentCallback(BLE_ESP32::ble_advertisment_t *pStruct) } // ATBTN uses manufacturer data and not a service - bit more like an IBeacon - if (memcmp(ATBTN_Addr, addr, 6) == 0) + if (!memcmp(ATBTN_Addr, addr, 6)) { //AddLog(LOG_LEVEL_INFO, PSTR("M32: AvagoBtn: %s"), advertisedDevice->toString().c_str()); MI32ParseATBtn((uint8_t*)advertisedDevice->getManufacturerData().data(), advertisedDevice->getManufacturerData().length(), addr, RSSI); @@ -1092,17 +1107,14 @@ int MI32advertismentCallback(BLE_ESP32::ble_advertisment_t *pStruct) } uint16_t UUID = native->u16.value; - char temp[60]; - BLE_ESP32::dump(temp, 13, addr, 6); - - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: MI:%s svc[0] UUID (%x)"), temp, UUID); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: %s: svc[0] UUID (%x)"), MIaddrStr(addr), UUID); std::string ServiceDataStr = advertisedDevice->getServiceData(0); uint32_t ServiceDataLength = ServiceDataStr.length(); const uint8_t *ServiceData = (const uint8_t *)ServiceDataStr.data(); + char temp[60]; BLE_ESP32::dump(temp, 60, ServiceData, ServiceDataLength); - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: MI:%s"), temp); - + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: %s: SrvData %s"), MIaddrStr(addr), temp); if (UUID){ // this will take and keep the mutex until the function is over @@ -1209,8 +1221,8 @@ int MI32AddKey(char* payload, char* key = nullptr){ } bool unknownKey = true; - for(uint32_t i=0; i 0) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: Search key for MAC: %02x%02x%02x%02x%02x%02x"), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - for(uint32_t i=0; i 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Decryption Key found")); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: Decryption Key found"), MIaddrStr(mac)); foundNoKey = false; break; } } if(foundNoKey){ - AddLog(LOG_LEVEL_DEBUG,PSTR("M32: No Key found")); + AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: No Key found"), MIaddrStr(mac)); return -2; // indicates needs key } @@ -1263,18 +1272,16 @@ int MIDecryptPayload(const uint8_t *macin, const uint8_t *nonce, uint32_t tag, u br_ccm_run(&ctx, 0, payload, len); memcpy(data, payload, len); //back to the packet - // crashed in here - why?, so give it more space to work with? // returns 1 if matched, else 0 - int ret = br_ccm_check_tag(&ctx, &tag); + int ret = br_ccm_check_tag(&ctx, &tag) - 1; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Err:%i, Decrypted : %02x %02x %02x %02x %02x"), ret, payload[1],payload[2],payload[3],payload[4],payload[5]); - return ret-1; // -> -1=fail, 0=success + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: Error %i, Decrypted %02x %02x %02x %02x %02x %02x"), MIaddrStr(mac), ret, payload[0], payload[1], payload[2], payload[3], payload[4], payload[5]); + return ret; // -> -1=fail, 0=success } #endif // USE_MI_DECRYPTION - // packet examples: // MJ_HT_V1 // 5020 AA01 41 3AF4DAA8654C 0A100109 @@ -1296,22 +1303,6 @@ int MIDecryptPayload(const uint8_t *macin, const uint8_t *nonce, uint32_t tag, u // xxyy FFEEDDCCBBAA 0104 TTTTHHHH // xxyy FFEEDDCCBBAA 0201 BB -const char *MIaddrStr(const uint8_t *addr, int useAlias = 0){ - static char addrstr[32]; - - const char *id = nullptr; - if (useAlias){ - id = BLE_ESP32::getAlias(addr); - } - if (!id || !(*id)){ - id = addrstr; - BLE_ESP32::dump(addrstr, 13, addr, 6); - } else { - } - - return id; -} - int MIParsePacket(const uint8_t* slotmac, struct mi_beacon_data_t *parsed, const uint8_t *datain, int len){ uint8_t data[32]; memcpy(data, datain, len); @@ -1357,7 +1348,7 @@ int MIParsePacket(const uint8_t* slotmac, struct mi_beacon_data_t *parsed, const parsed->devicetype = *((uint16_t *)(data + byteindex)); byteindex += 2; parsed->framecnt = data[byteindex]; - //if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: MI frame %d"), parsed->framecnt); + //if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: MI frame %d"), parsed->framecnt); byteindex++; @@ -1371,6 +1362,10 @@ int MIParsePacket(const uint8_t* slotmac, struct mi_beacon_data_t *parsed, const } memcpy(parsed->macdata.mac, &data[byteindex], 6); byteindex += 6; + } else { + // Use slotmac if no MAC in frame + memcpy(parsed->macdata.mac, slotmac, 6); + MI32_ReverseMAC(parsed->macdata.mac); } int decres = 1; @@ -1379,10 +1374,7 @@ int MIParsePacket(const uint8_t* slotmac, struct mi_beacon_data_t *parsed, const if (len < byteindex + 3+4+1){ return 0; } - const uint8_t* mac = slotmac; - if (parsed->framedata.MACFlag){ - mac = parsed->macdata.mac; - } + const uint8_t* mac = parsed->macdata.mac; uint8_t nonce[12]; uint8_t *p = nonce; memcpy(p, mac, 6); @@ -1406,17 +1398,17 @@ int MIParsePacket(const uint8_t* slotmac, struct mi_beacon_data_t *parsed, const break; case 0: // suceeded parsed->needkey = KEY_REQUIRED_AND_FOUND; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32 %s: Payload decrypted"), MIaddrStr(slotmac)); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: Payload decrypted"), MIaddrStr(slotmac)); break; case -1: // key failed to work parsed->needkey = KEY_REQUIRED_AND_INVALID; - AddLog(LOG_LEVEL_ERROR,PSTR("M32 %s: Payload decrypt failed"), MIaddrStr(slotmac)); + AddLog(LOG_LEVEL_ERROR,PSTR("M32: %s: Payload decrypt failed"), MIaddrStr(slotmac)); parsed->payloadpresent = 0; return 0; break; case -2: // key not present parsed->needkey = KEY_REQUIRED_BUT_NOT_FOUND; - AddLog(LOG_LEVEL_ERROR,PSTR("M32 %s: Payload encrypted but no key"), MIaddrStr(slotmac)); + AddLog(LOG_LEVEL_ERROR,PSTR("M32: %s: Payload encrypted but no key"), MIaddrStr(slotmac)); parsed->payloadpresent = 0; return 0; break; @@ -1451,7 +1443,7 @@ int MIParsePacket(const uint8_t* slotmac, struct mi_beacon_data_t *parsed, const } if ((len - byteindex) == 0){ - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32 %s: No payload"), MIaddrStr(slotmac)); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: No payload"), MIaddrStr(slotmac)); parsed->payload.size = 0; parsed->payloadpresent = 0; return 0; @@ -1460,14 +1452,14 @@ int MIParsePacket(const uint8_t* slotmac, struct mi_beacon_data_t *parsed, const // we have payload which did not need decrypt. if (decres == 1){ parsed->needkey = KEY_NOT_REQUIRED; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32 %s: Payload unencrypted"), MIaddrStr(slotmac)); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: Payload unencrypted"), MIaddrStr(slotmac)); } // already decrypted if required parsed->payloadpresent = 1; memcpy(&parsed->payload, (data + byteindex), (len - byteindex)); if (parsed->payload.size != (len - byteindex) - 3){ - AddLog(LOG_LEVEL_DEBUG,PSTR("M32 %s: Payload length mismatch"), MIaddrStr(slotmac)); + AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: Payload length mismatch"), MIaddrStr(slotmac)); } return 1; @@ -1477,7 +1469,6 @@ int MIParsePacket(const uint8_t* slotmac, struct mi_beacon_data_t *parsed, const * common functions \*********************************************************************************************/ - /** * @brief Return the slot number of a known sensor or return create new sensor slot * @@ -1489,7 +1480,7 @@ int MIParsePacket(const uint8_t* slotmac, struct mi_beacon_data_t *parsed, const */ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter, bool ignoreDuplicate = false){ - //AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: %s: will test ID-type: %x"),D_CMND_MI32, _type); + //AddLog(LOG_LEVEL_DEBUG, PSTR("M32: Will test ID-type: %x"), _type); bool _success = false; for (uint32_t i=0; i < MI_MI32_TYPES; i++){ // i < sizeof(kMI32DeviceID) gives compiler warning if(_type == kMI32DeviceID[i]){ @@ -1497,41 +1488,43 @@ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter, _success = true; break; } +/* else { - //AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: %s: ID-type is not: %x"),D_CMND_MI32,kMI32DeviceID[i]); + AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: ID-type is not: %x"), kMI32DeviceID[i]); } +*/ } if(!_success) { _type = 1; // unknown } - //AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: %s: vector size %u"),D_CMND_MI32, MIBLEsensors.size()); + //AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Vector size %u"), MIBLEsensors.size()); for(uint32_t i=0; i 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: %s: slot: %u/%u - ign repeat"),D_CMND_MI32, i, MIBLEsensors.size()); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: %s: Slot %u/[0-%u] - ign repeat"), MIaddrStr(mac), i, MIBLEsensors.size() - 1); if(ignoreDuplicate) return 0xff; // packet received before, stop here } - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Frame %d, last %d"), counter, MIBLEsensors[i].lastCnt); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: Frame %d, last %d"), MIaddrStr(mac), counter, MIBLEsensors[i].lastCnt); MIBLEsensors[i].lastCnt = counter; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: %s: slot: %u/%u"),D_CMND_MI32, i, MIBLEsensors.size()); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: %s: Slot %u/[0-%u]"), MIaddrStr(mac), i, MIBLEsensors.size() - 1); if (MIBLEsensors[i].type != _type){ // this happens on incorrectly configured pvvx ATC firmware - AddLog(LOG_LEVEL_ERROR,PSTR("M32: %s: slot: %u - device type 0x%04x(%s) -> 0x%04x(%s) - check device is only sending one type of advert."),D_CMND_MI32, i, + AddLog(LOG_LEVEL_ERROR, PSTR("M32: %s: Slot %u - device type 0x%04x(%s) -> 0x%04x(%s) - check device is only sending one type of advert."), MIaddrStr(mac), i, kMI32DeviceID[MIBLEsensors[i].type-1], kMI32DeviceType[MIBLEsensors[i].type-1], kMI32DeviceID[_type-1], kMI32DeviceType[_type-1]); MIBLEsensors[i].type = _type; } return i; } - //AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: %s: i: %x %x %x %x %x %x"),D_CMND_MI32, MIBLEsensors[i].MAC[5], MIBLEsensors[i].MAC[4],MIBLEsensors[i].MAC[3],MIBLEsensors[i].MAC[2],MIBLEsensors[i].MAC[1],MIBLEsensors[i].MAC[0]); - //AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: %s: n: %x %x %x %x %x %x"),D_CMND_MI32, mac[5], mac[4], mac[3],mac[2],mac[1],mac[0]); + //AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: i: %x %x %x %x %x %x"), MIBLEsensors[i].MAC[5], MIBLEsensors[i].MAC[4], MIBLEsensors[i].MAC[3], MIBLEsensors[i].MAC[2], MIBLEsensors[i].MAC[1], MIBLEsensors[i].MAC[0]); + //AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: n: %x %x %x %x %x %x"), mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]); } - //AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: %s: new sensor -> slot: %u"),D_CMND_MI32, MIBLEsensors.size()); - //AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: %s: found new sensor"),D_CMND_MI32); + //AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: new sensor -> slot %u"), MIBLEsensors.size()); + //AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: found new sensor")); mi_sensor_t _newSensor; memset(&_newSensor, 0 , sizeof(_newSensor)); memcpy(_newSensor.MAC, mac, 6); @@ -1608,7 +1601,7 @@ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter, break; } MIBLEsensors.push_back(_newSensor); - AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: new %s at slot: %u"),D_CMND_MI32, kMI32DeviceType[_type-1],MIBLEsensors.size()-1); + AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: New %s at slot %u"), MIaddrStr(mac), kMI32DeviceType[_type-1], MIBLEsensors.size() - 1); MI32.mode.shallShowStatusInfo = 1; return MIBLEsensors.size()-1; }; @@ -1638,19 +1631,16 @@ void MI32StatusInfo() { * These are called from main thread only. \*********************************************************************************************/ - int MI32scanCompleteCallback(NimBLEScanResults results){ // we actually don't need to do anything here.... - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Scan complete")); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Scan complete")); return 0; } - /*********************************************************************************************\ * init BLE_32 \*********************************************************************************************/ - void MI32Init(void) { MIBLEsensors.reserve(10); MIBLEbindKeys.reserve(10); @@ -1674,7 +1664,6 @@ AddLog(0,PSTR("MI32Option4: %d"), MI32.option.ignoreBogusBattery); AddLog(0,PSTR("MI32Option5: %d"), MI32.option.onlyAliased); AddLog(0,PSTR("MI32Option6: %d"), MI32.option.MQTTType); - BLE_ESP32::registerForAdvertismentCallbacks((const char *)"MI32", MI32advertismentCallback); BLE_ESP32::registerForScanCallbacks((const char *)"MI32", MI32scanCompleteCallback); // note: for operations, we will set individual callbacks in the operations we request @@ -1686,14 +1675,10 @@ AddLog(0,PSTR("MI32Option6: %d"), MI32.option.MQTTType); return; } - /*********************************************************************************************\ * Task section \*********************************************************************************************/ - - - int MIParseBatt(int slot, uint8_t *data, int len){ int value = data[0]; char slotMAC[13]; @@ -1707,13 +1692,13 @@ int MIParseBatt(int slot, uint8_t *data, int len){ } else { memcpy(MIBLEsensors[slot].firmware, data+2, 5); MIBLEsensors[slot].firmware[5] = '\0'; - AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: FLORA Firmware: %s"),D_CMND_MI32,MIBLEsensors[slot].firmware); + AddLog(LOG_LEVEL_DEBUG,PSTR("M32: FLORA Firmware: %s"), MIBLEsensors[slot].firmware); } } MIBLEsensors[slot].eventType.bat = 1; MIBLEsensors[slot].shallSendMQTT = 1; MI32.mode.shallTriggerTele = 1; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Batt read for %s complete %d"), slotMAC, value); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Batt read for %s complete %d"), slotMAC, value); } else { AddLog(LOG_LEVEL_ERROR,PSTR("M32: Batt read for %s complete but out of range 1-101 (%d)"), slotMAC, value); } @@ -1725,12 +1710,10 @@ int MIParseBatt(int slot, uint8_t *data, int len){ * parse the response from advertisements \*********************************************************************************************/ - void MI32ParseATCPacket(const uint8_t * _buf, uint32_t length, const uint8_t *addr, int RSSI){ ATCPacket_t *_packet = (ATCPacket_t*)_buf; PVVXPacket_t *ppv_packet = (PVVXPacket_t*)_buf; - if (length == 15){ // 19-1-1-2 uint8_t addrrev[6]; memcpy(addrrev, addr, 6); @@ -1744,10 +1727,10 @@ void MI32ParseATCPacket(const uint8_t * _buf, uint32_t length, const uint8_t *ad //uint8_t flags; uint32_t _slot = MIBLEgetSensorSlot(addr, 0x0a1c, ppv_packet->counter); // This must be a hard-coded fake ID - if(_slot==0xff) return; + if(_slot == 0xff) return; if ((_slot >= 0) && (_slot < MIBLEsensors.size())){ - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s:pvvx at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: %s:pvvx at slot %u"), MIaddrStr(addr), kMI32DeviceType[MIBLEsensors[_slot].type-1], _slot); MIBLEsensors[_slot].RSSI=RSSI; MIBLEsensors[_slot].needkey=KEY_NOT_REQUIRED; @@ -1773,7 +1756,6 @@ void MI32ParseATCPacket(const uint8_t * _buf, uint32_t length, const uint8_t *ad } } - uint8_t addrrev[6]; memcpy(addrrev, addr, 6); //MI32_ReverseMAC(addrrev); @@ -1792,10 +1774,10 @@ void MI32ParseATCPacket(const uint8_t * _buf, uint32_t length, const uint8_t *ad uint32_t _slot = MIBLEgetSensorSlot(addr, 0x0a1c, _packet->frameCnt); // This must be a hard-coded fake ID - if(_slot==0xff) return; + if(_slot == 0xff) return; if ((_slot >= 0) && (_slot < MIBLEsensors.size())){ - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1], _slot); MIBLEsensors[_slot].RSSI=RSSI; MIBLEsensors[_slot].needkey=KEY_NOT_REQUIRED; @@ -1809,8 +1791,6 @@ void MI32ParseATCPacket(const uint8_t * _buf, uint32_t length, const uint8_t *ad MIBLEsensors[_slot].shallSendMQTT = 1; MI32.mode.shallTriggerTele = 1; } - } else { - } } @@ -1824,10 +1804,10 @@ void MI32ParseCGDK2Packet(const uint8_t * _buf, uint32_t length, const uint8_t * if (!memcmp(addrrev, cgdk_packet->MAC, 6)){ uint32_t _slot = MIBLEgetSensorSlot(addr, 0x066f, cgdk_packet->counter); // This must be a hard-coded fake ID - if(_slot==0xff) return; + if(_slot == 0xff) return; if ((_slot >= 0) && (_slot < MIBLEsensors.size())){ - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s:pvvx at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s:pvvx at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1], _slot); MIBLEsensors[_slot].RSSI=RSSI; MIBLEsensors[_slot].needkey=KEY_NOT_REQUIRED; MIBLEsensors[_slot].temp = (float)(cgdk_packet->temperature)/10.0f; @@ -1865,10 +1845,10 @@ void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t return; uint32_t _slot = MIBLEgetSensorSlot(addr, UUID, 0); - if (_slot==0xff) return; + if (_slot == 0xff) return; if ((_slot >= 0) && (_slot < MIBLEsensors.size())) { - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1], _slot); MIBLEsensors[_slot].RSSI = RSSI; MIBLEsensors[_slot].needkey = KEY_NOT_REQUIRED; MIBLEsensors[_slot].eventType.scale = 1; @@ -1905,10 +1885,10 @@ void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t return; uint32_t _slot = MIBLEgetSensorSlot(addr, UUID, 0); - if (_slot==0xff) return; + if (_slot == 0xff) return; if ((_slot >= 0) && (_slot < MIBLEsensors.size())) { - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1], _slot); MIBLEsensors[_slot].RSSI = RSSI; MIBLEsensors[_slot].needkey = KEY_NOT_REQUIRED; MIBLEsensors[_slot].eventType.scale = 1; @@ -1963,8 +1943,8 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){ } char tmp[20]; - BLE_ESP32::dump(tmp, 20, (uint8_t*)&(parsed->payload), parsed->payload.size+3); - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: MI%d payload %s"), _slot, tmp); + BLE_ESP32::dump(tmp, 20, (uint8_t*)&(parsed->payload), parsed->payload.size + 3); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: %s: slot %d, payload %s"), MIaddrStr(MIBLEsensors[_slot].MAC), _slot, tmp); // clear this for every payload MIBLEsensors[_slot].pairing = 0; @@ -1995,13 +1975,11 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){ MIBLEsensors[_slot].shallSendMQTT = 1; MIBLEsensors[_slot].feature.lux = 1; MIBLEsensors[_slot].feature.NMT = 1; - MIBLEsensors[_slot].feature.events=1; + MIBLEsensors[_slot].feature.events = 1; // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: PIR: primary"),MIBLEsensors[_slot].lux ); break; - - case 0x1001: // button press MIBLEsensors[_slot].Btn = pld->Btn.num + (pld->Btn.longPress/2)*6; MIBLEsensors[_slot].feature.Btn = 1; @@ -2018,9 +1996,9 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){ MIBLEsensors[_slot].temp=_tempFloat; MIBLEsensors[_slot].feature.temp = 1; MIBLEsensors[_slot].eventType.temp = 1; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 4: temp updated")); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 4: temp updated")); } else { - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 4: temp ignored > 60 (%2_f)"), &_tempFloat); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 4: temp ignored > 60 (%2_f)"), &_tempFloat); } // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 4: U16: %u Temp"), _beacon.temp ); } break; @@ -2031,9 +2009,9 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){ MIBLEsensors[_slot].hum=_tempFloat; MIBLEsensors[_slot].feature.hum = 1; MIBLEsensors[_slot].eventType.hum = 1; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 6: hum updated")); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 6: hum updated")); } else { - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 6: hum ignored > 101 (%2_f)"), &_tempFloat); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 6: hum ignored > 101 (%2_f)"), &_tempFloat); } // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 6: U16: %u Hum"), _beacon.hum); } break; @@ -2050,14 +2028,14 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){ MIBLEsensors[_slot].moisture=pld->moist; MIBLEsensors[_slot].eventType.moist = 1; MIBLEsensors[_slot].feature.moist = 1; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 8: moisture updated")); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 8: moisture updated")); // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 8: U8: %u Moisture"), _beacon.moist); break; case 0x1009: // 'conductivity' / 'Soil EC value' MIBLEsensors[_slot].fertility=pld->fert; MIBLEsensors[_slot].eventType.fert = 1; MIBLEsensors[_slot].feature.fert = 1; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 9: fertility updated")); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 9: fertility updated")); // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 9: U16: %u Fertility"), _beacon.fert); break; case 0x100a:// 'Electricity' @@ -2067,34 +2045,33 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){ break; } } - MIBLEsensors[_slot].feature.bat = 1; - if(pld->bat<101){ + if (pld->bat < 101) { MIBLEsensors[_slot].bat = pld->bat; - MIBLEsensors[_slot].eventType.bat = 1; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode a: bat updated")); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: %s: Mode a: bat updated (%d)"), MIaddrStr(MIBLEsensors[_slot].MAC), pld->bat); } else { MIBLEsensors[_slot].bat = 100; - MIBLEsensors[_slot].eventType.bat = 1; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode a: bat > 100 (%d)"), pld->bat); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: %s: Mode a: bat > 100 (%d)"), MIaddrStr(MIBLEsensors[_slot].MAC), pld->bat); } + MIBLEsensors[_slot].eventType.bat = 1; + MIBLEsensors[_slot].feature.bat = 1; // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode a: U8: %u %%"), _beacon.bat); break; - // 100b-100d -> undefioend in docs. + // 100b-100d -> undefined in docs. case 0x100d:{ // is this right???? MIBLEsensors[_slot].feature.tempHum = 1; float _tempFloat=(float)(pld->HT.temp)/10.0f; if(_tempFloat < 60){ MIBLEsensors[_slot].temp = _tempFloat; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode d: temp updated")); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode d: temp updated")); } else { - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode d: temp ignored > 60 (%2_f)"), &_tempFloat); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode d: temp ignored > 60 (%2_f)"), &_tempFloat); } _tempFloat=(float)(pld->HT.hum)/10.0f; if(_tempFloat < 100){ - MIBLEsensors[_slot].hum = _tempFloat; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode d: hum updated")); + MIBLEsensors[_slot].hum = _tempFloat; + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode d: hum updated")); } else { - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode d: hum ignored > 100 (%2_f)"), &_tempFloat); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode d: hum ignored > 100 (%2_f)"), &_tempFloat); } MIBLEsensors[_slot].eventType.tempHum = 1; // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode d: U16: %x Temp U16: %x Hum"), _beacon.HT.temp, _beacon.HT.hum); @@ -2162,7 +2139,7 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){ //Formaldehyde (new) 0x101D default: { - AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Unknown MI pld type %x %s"), parsed->payload.type, tmp); + AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: Unknown MI pld type: %x - %s"), MIaddrStr(MIBLEsensors[_slot].MAC), parsed->payload.type, tmp); res = 0; } break; } @@ -2217,7 +2194,7 @@ void MI32ParseATBtn(uint8_t *buf, uint16_t bufsize, const uint8_t* addr, int RSS _addr[4] = data->switch1; _addr[5] = data->switch2; uint32_t _slot = MIBLEgetSensorSlot(_addr, kMI32DeviceID[AT_BTN-1], data->counter, true); - if(_slot==0xff) return; + if(_slot == 0xff) return; // AddLog(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), MI32getDeviceName(_slot),_slot); MIBLEsensors[_slot].RSSI=RSSI; @@ -2229,7 +2206,6 @@ void MI32ParseATBtn(uint8_t *buf, uint16_t bufsize, const uint8_t* addr, int RSS MIBLEsensors[_slot].Btn = data->button_id; } - //////////////////////////////////////////////////////////// // this SHOULD parse any MI packet, including encrypted. void MI32ParseResponse(const uint8_t *buf, uint16_t bufsize, const uint8_t* addr, int RSSI) { @@ -2248,17 +2224,16 @@ void MI32ParseResponse(const uint8_t *buf, uint16_t bufsize, const uint8_t* addr addr = addrrev; } - uint16_t _slot = MIBLEgetSensorSlot( addr, parsed.devicetype, parsed.framecnt ); - if(_slot==0xff) return; + uint16_t _slot = MIBLEgetSensorSlot(addr, parsed.devicetype, parsed.framecnt); + if(_slot == 0xff) return; if ((_slot >= 0) && (_slot < MIBLEsensors.size())){ if (parsed.needkey != KEY_REQUIREMENT_UNKNOWN){ MIBLEsensors[_slot].needkey = parsed.needkey; } MIBLEsensors[_slot].RSSI=RSSI; if (!res){ // - if the payload is not valid - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: MIParsePacket returned %d"), res); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: MIParsePacket returned %d"), MIaddrStr(addr), res); return; - } else { } MI32parseMiPayload(_slot, &parsed); } @@ -2267,7 +2242,7 @@ void MI32ParseResponse(const uint8_t *buf, uint16_t bufsize, const uint8_t* addr bool MI32isInBlockList(const uint8_t* MAC){ bool isBlocked = false; for(auto &_blockedMAC : MIBLEBlockList){ - if(memcmp(_blockedMAC.buf,MAC,6) == 0) isBlocked = true; + if(!memcmp(_blockedMAC.buf, MAC, 6)) isBlocked = true; } return isBlocked; } @@ -2277,45 +2252,48 @@ void MI32removeMIBLEsensor(uint8_t* MAC){ TasAutoMutex localmutex(&slotmutex, "Mi32Rem"); MIBLEsensors.erase( std::remove_if( MIBLEsensors.begin() , MIBLEsensors.end(), [MAC]( mi_sensor_t _sensor )->bool - { return (memcmp(_sensor.MAC,MAC,6) == 0); } + { return (!memcmp(_sensor.MAC, MAC, 6)); } ), end( MIBLEsensors ) ); } + /***********************************************************************\ * Read data from connections \***********************************************************************/ -void MI32notifyHT_LY(int slot, char *_buf, int len){ - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: %s: raw data: %x%x%x%x%x%x%x"),D_CMND_MI32,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); +void MI32notifyHT_LY(int _slot, char *_buf, int len){ + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: %s: Raw data %02x%02x%02x%02x%02x%02x%02x"),MIaddrStr(MIBLEsensors[_slot].MAC), _buf[0], _buf[1], _buf[2], _buf[3], _buf[4], _buf[5], _buf[6]); // the value 0b00 is 28.16 C? - if(_buf[0] != 0 || _buf[1] != 0){ - memcpy(&LYWSD0x_HT,(void *)_buf,sizeof(LYWSD0x_HT)); - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: T * 100: %u, H: %u, V: %u"),D_CMND_MI32,LYWSD0x_HT.temp,LYWSD0x_HT.hum, LYWSD0x_HT.volt); - uint32_t _slot = slot; - - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: MIBLE: Sensor slot: %u"), _slot); + if (_buf[0] || _buf[1]){ + memcpy(&LYWSD0x_HT, (void *)_buf, sizeof(LYWSD0x_HT)); + if (BLE_ESP32::BLEDebugMode) { + AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: T * 100: %u, H: %u, V: %u"), MIaddrStr(MIBLEsensors[_slot].MAC), LYWSD0x_HT.temp, LYWSD0x_HT.hum, LYWSD0x_HT.volt); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: %s: Sensor slot %u"), MIaddrStr(MIBLEsensors[_slot].MAC), _slot); + } static float _tempFloat; - _tempFloat=(float)(LYWSD0x_HT.temp)/100.0f; - if(_tempFloat<60){ - MIBLEsensors[_slot].temp=_tempFloat; + _tempFloat = (float)(LYWSD0x_HT.temp) / 100.0f; + if(_tempFloat < 60){ + MIBLEsensors[_slot].temp = _tempFloat; + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: %s: LYWSD0x Temp updated %1_f"), MIaddrStr(MIBLEsensors[_slot].MAC), &MIBLEsensors[_slot].temp); // MIBLEsensors[_slot].showedUp=255; // this sensor is real } _tempFloat=(float)LYWSD0x_HT.hum; - if(_tempFloat<100){ + if(_tempFloat < 100){ MIBLEsensors[_slot].hum = _tempFloat; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: LYWSD0x: hum updated")); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: %s: LYWSD0x Hum updated %1_f"), MIaddrStr(MIBLEsensors[_slot].MAC), &MIBLEsensors[_slot].hum); } MIBLEsensors[_slot].eventType.tempHum = 1; - if (MIBLEsensors[_slot].type == MI_LYWSD03MMC || MIBLEsensors[_slot].type == MI_MHOC401){ + if (MIBLEsensors[_slot].type == MI_LYWSD02MMC || MIBLEsensors[_slot].type == MI_LYWSD03MMC || MIBLEsensors[_slot].type == MI_MHOC401){ // ok, so CR2032 is 3.0v, but drops immediately to ~2.9. // so we'll go with the 2.1 min, 2.95 max. float minVolts = 2100.0; //float maxVolts = 2950.0; //float range = maxVolts - minVolts; //float divisor = range/100; // = 8.5 - float percent = (((float)LYWSD0x_HT.volt) - minVolts)/ 8.5; //divisor; + float percent = (((float)LYWSD0x_HT.volt) - minVolts) / 8.5; //divisor; if (percent > 100) percent = 100; - MIBLEsensors[_slot].bat = (int) percent; + MIBLEsensors[_slot].bat = (int)percent; + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("M32: %s: LYWSD0x Bat updated %d"), MIaddrStr(MIBLEsensors[_slot].MAC), MIBLEsensors[_slot].bat); MIBLEsensors[_slot].eventType.bat = 1; } if(MI32.option.directBridgeMode) { @@ -2325,7 +2303,6 @@ void MI32notifyHT_LY(int slot, char *_buf, int len){ } } - /** * @brief Launch functions from Core 1 to make race conditions less likely * @@ -2372,7 +2349,6 @@ void MI32EverySecond(bool restart){ // MI32.batteryreader.slot < filled and !MI32.batteryreader.active readOneBat(); - // read a sensor if // MI32.sensorreader.slot < filled and !MI32.sensorreader.active // for sensors which need to get data through notify... @@ -2448,7 +2424,6 @@ int findSlot(char *addrOrAlias){ return -1; } - void CmndMi32Time(void) { if (XdrvMailbox.data_len > 0) { int slot = findSlot(XdrvMailbox.data); @@ -2458,7 +2433,7 @@ void CmndMi32Time(void) { if (MIBLEsensors.size() > slot) { int res = genericTimeWriteFn(slot); if (res > 0){ - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: will set Time")); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: will set Time")); ResponseCmndNumber(slot); return; } @@ -2487,7 +2462,6 @@ void CmndMi32Battery(void) { ResponseCmndDone(); } - void CmndMi32Unit(void) { if (XdrvMailbox.data_len > 0) { int slot = findSlot(XdrvMailbox.data); @@ -2499,7 +2473,7 @@ void CmndMi32Unit(void) { // TOGGLE unit? int res = genericUnitWriteFn(slot, -1); if (res > 0){ - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: will toggle Unit")); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("M32: will toggle Unit")); ResponseCmndNumber(slot); return; } @@ -2538,7 +2512,6 @@ void MI32BlockListResp(){ ResponseAppend_P(PSTR("}}")); } - void CmndMi32Block(void){ if (XdrvMailbox.data_len == 0) { switch (XdrvMailbox.index) { @@ -2566,14 +2539,14 @@ void CmndMi32Block(void){ case 0: { //TasAutoMutex localmutex(&slotmutex, "Mi32Block2"); MIBLEBlockList.erase( std::remove_if( begin( MIBLEBlockList ), end( MIBLEBlockList ), [_MACasBytes]( MAC_t& _entry )->bool - { return (memcmp(_entry.buf,_MACasBytes.buf,6) == 0); } + { return (!memcmp(_entry.buf, _MACasBytes.buf, 6)); } ), end( MIBLEBlockList ) ); } break; case 1: { //TasAutoMutex localmutex(&slotmutex, "Mi32Block3"); bool _notYetInList = true; for (auto &_entry : MIBLEBlockList) { - if (memcmp(_entry.buf,_MACasBytes.buf,6) == 0){ + if (!memcmp(_entry.buf, _MACasBytes.buf, 6)){ _notYetInList = false; } } @@ -2660,7 +2633,6 @@ void CmndMi32Topic(void) { ResponseCmndChar(MI32.bleTopic.c_str()); } - void MI32KeyListResp(){ Response_P(PSTR("{\"MIKeys\":{")); for (int i = 0; i < MIBLEbindKeys.size(); i++){ @@ -2677,11 +2649,10 @@ void MI32KeyListResp(){ ResponseAppend_P(PSTR("}}")); } - void CmndMi32Keys(void){ #ifdef BLE_ESP32_ALIASES int op = XdrvMailbox.index; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Key %d %s"), op, XdrvMailbox.data); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Key %d %s"), op, XdrvMailbox.data); int res = -1; switch(op){ @@ -2731,7 +2702,7 @@ void CmndMi32Keys(void){ } while (p); if (added){ - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Added %d Keys"), added); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Added %d Keys"), added); MI32KeyListResp(); } else { MI32KeyListResp(); @@ -2739,7 +2710,7 @@ void CmndMi32Keys(void){ return; } break; case 2:{ // clear - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Keys clearing %d"), MIBLEbindKeys.size()); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Keys clearing %d"), MIBLEbindKeys.size()); for (int i = MIBLEbindKeys.size()-1; i >= 0; i--){ MIBLEbindKeys.pop_back(); } @@ -2751,27 +2722,26 @@ void CmndMi32Keys(void){ #endif } - /*********************************************************************************************\ * Presentation \*********************************************************************************************/ -const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 v0921{m}%u%s / %u{e}"; -const char HTTP_MI32_ALIAS[] PROGMEM = "{s}%s Alias {m}%s{e}"; +const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 " MI32_VERSION "{m}%u%s / %u{e}"; +const char HTTP_MI32_ALIAS[] PROGMEM = "{s}%s Alias{m}%s{e}"; const char HTTP_MI32_MAC[] PROGMEM = "{s}%s %s{m}%s{e}"; const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}"; -const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u %%{e}"; +const char HTTP_BATTERY[] PROGMEM = "{s}%s " D_BATTERY "{m}%u %%{e}"; const char HTTP_LASTBUTTON[] PROGMEM = "{s}%s Last Button{m}%u {e}"; const char HTTP_EVENTS[] PROGMEM = "{s}%s Events{m}%u {e}"; const char HTTP_NMT[] PROGMEM = "{s}%s No motion{m}> %u seconds{e}"; -const char HTTP_MI32_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%u us/cm{e}"; +const char HTTP_MI32_FLORA_DATA[] PROGMEM = "{s}%s Fertility{m}%u us/cm{e}"; const char HTTP_MI32_HL[] PROGMEM = "{s}
{m}
{e}"; -const char HTTP_MI32_LIGHT[] PROGMEM = "{s}%s" " Light" "{m}%d{e}"; -const char HTTP_MISCALE_WEIGHT[] PROGMEM = "{s}%s" " Weight" "{m}%*_f %s{e}"; -const char HTTP_MISCALE_WEIGHT_REMOVED[] PROGMEM = "{s}%s" " Weight removed" "{m}%s{e}"; -const char HTTP_MISCALE_WEIGHT_STABILIZED[] PROGMEM = "{s}%s" " Weight stabilized" "{m}%s{e}"; -const char HTTP_MISCALE_IMPEDANCE[] PROGMEM = "{s}%s" " Impedance" "{m}%u{e}"; -const char HTTP_MISCALE_IMPEDANCE_STABILIZED[] PROGMEM = "{s}%s" " Impedance stabilized" "{m}%s{e}"; +const char HTTP_MI32_LIGHT[] PROGMEM = "{s}%s " D_LIGHT "{m}%d{e}"; +const char HTTP_MISCALE_WEIGHT[] PROGMEM = "{s}%s " D_WEIGHT "{m}%*_f %s{e}"; +const char HTTP_MISCALE_WEIGHT_REMOVED[] PROGMEM = "{s}%s Weight removed{m}%s{e}"; +const char HTTP_MISCALE_WEIGHT_STABILIZED[] PROGMEM = "{s}%s Weight stabilized{m}%s{e}"; +const char HTTP_MISCALE_IMPEDANCE[] PROGMEM = "{s}%s Impedance{m}%u{e}"; +const char HTTP_MISCALE_IMPEDANCE_STABILIZED[] PROGMEM = "{s}%s Impedance stabilized{m}%s{e}"; const char HTTP_SJWS01LM_FLOODING[] PROGMEM = "{s}%s Flooding{m}%u {e}"; //const char HTTP_NEEDKEY[] PROGMEM = "{s}%s = 0 ; i--) { + for (int i = MIBLEsensors.size()-1; i >= 0; i--) { //if (MIBLEsensors[i].MAC[2] || MIBLEsensors[i].MAC[3] || MIBLEsensors[i].MAC[4] || MIBLEsensors[i].MAC[5]){ // Since we use a pseudo MAC for the ATBTN slots we need to ignore these warnings - if (memcmp(MIBLEsensors[i].MAC, ATBTN_Addr, 4) == 0) // Skip pseudo AT BTN addresses + if (!memcmp(MIBLEsensors[i].MAC, ATBTN_Addr, 4)) // Skip pseudo AT BTN addresses continue; if (!BLE_ESP32::devicePresent(MIBLEsensors[i].MAC)){ - uint8_t *mac = MIBLEsensors[i].MAC; - AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Dev no longer present MAC: %02x%02x%02x%02x%02x%02x"), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + AddLog(LOG_LEVEL_DEBUG, PSTR("M32: %s: Dev no longer present"), MIaddrStr(MIBLEsensors[i].MAC)); TasAutoMutex localmutex(&slotmutex, "Mi32Timeout"); MIBLEsensors.erase(MIBLEsensors.begin() + i); } @@ -2855,7 +2821,6 @@ void MI32TimeoutSensors(){ } } - // this assumes that we're adding to a ResponseTime_P void MI32GetOneSensorJson(int slot, int hidename){ mi_sensor_t *p; @@ -3116,7 +3081,7 @@ void MI32ShowSomeSensors(){ } MqttAppendSensorUnits(); ResponseAppend_P(PSTR("}")); - //AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: show some %d %s"),D_CMND_MI32, MI32.mqttCurrentSlot, ResponseData()); + //AddLog(LOG_LEVEL_DEBUG,PSTR("M32: show some %d %s"), MI32.mqttCurrentSlot, ResponseData()); MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR), Settings->flag.mqtt_sensor_retain); #ifdef USE_HOME_ASSISTANT @@ -3171,7 +3136,7 @@ void MI32ShowOneMISensor(bool hidename){ char SensorTopic[TOPSZ]; GetTopic_P(SensorTopic, TELE, MI32.bleTopic.c_str(), id); - //AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: show one %d %s"),D_CMND_MI32, MI32.mqttCurrentSlot, ResponseData()); + //AddLog(LOG_LEVEL_DEBUG,PSTR("M32: show one %d %s"), MI32.mqttCurrentSlot, ResponseData()); MqttPublish(SensorTopic, Settings->flag.mqtt_sensor_retain); if (MI32.option.MQTTType > 1) XdrvRulesProcess(0); @@ -3179,7 +3144,6 @@ void MI32ShowOneMISensor(bool hidename){ MI32.mqttCurrentSingleSlot++; } - /////////////////////////////////////////////// // starts a completely fresh MQTT message. // sends ONE sensor's worth of HA discovery msg @@ -3266,10 +3230,9 @@ const char *classes[] = { // 12 "", //- empty device class "Impedance", - "Ohm", + "Ω", }; - void MI32DiscoveryOneMISensor(){ // don't detect half-added ones here int numsensors = MIBLEsensors.size(); @@ -3283,9 +3246,6 @@ void MI32DiscoveryOneMISensor(){ mi_sensor_t *p; p = &MIBLEsensors[MI32.mqttCurrentSingleSlot]; - - - int datacount = (sizeof(classes)/sizeof(*classes))/3; if (p->nextDiscoveryData >= datacount){ @@ -3448,9 +3408,8 @@ void MI32DiscoveryOneMISensor(){ //vTaskDelay(100/ portTICK_PERIOD_MS); } } // end if hass discovery - //AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: show some %d %s"),D_CMND_MI32, MI32.mqttCurrentSlot, ResponseData()); + //AddLog(LOG_LEVEL_DEBUG,PSTR("M32: show some %d %s"), MI32.mqttCurrentSlot, ResponseData()); #endif //USE_HOME_ASSISTANT - } /////////////////////////////////////////////// @@ -3480,7 +3439,6 @@ void MI32ShowTriggeredSensors(){ hidename = MI32.option.MQTTType < 2; } - do { ResponseTime_P(PSTR("")); int cnt = 0; @@ -3488,7 +3446,7 @@ void MI32ShowTriggeredSensors(){ for (; (sensor < numsensors) && (cnt < maxcnt); sensor++) { p = &MIBLEsensors[sensor]; if(p->eventType.raw == 0) continue; - if(p->shallSendMQTT==0) continue; + if(p->shallSendMQTT == 0) continue; cnt++; ResponseAppend_P(PSTR(",")); @@ -3538,7 +3496,6 @@ void MI32ShowTriggeredSensors(){ } while (sensor < numsensors); } - void MI32Show(bool json) { // don't detect half-added ones here @@ -3563,11 +3520,11 @@ void MI32Show(bool json) if (numsensors-(_page*MI32.perPage)>1 && MI32.perPage!=1) { sprintf_P(stemp,"-%u",j); } - if (numsensors==0) i=-1; // only for the GUI + if (numsensors == 0) i=-1; // only for the GUI - WSContentSend_PD(HTTP_MI32, i+1,stemp,numsensors); + WSContentSend_P(HTTP_MI32, i + 1, stemp, numsensors); for (i; iMAC,6,_MAC,18);//,':'); - WSContentSend_PD(HTTP_MI32_MAC, typeName, D_MAC_ADDRESS, _MAC); + WSContentSend_P(HTTP_MI32_MAC, typeName, D_MAC_ADDRESS, _MAC); WSContentSend_PD(HTTP_RSSI, typeName, p->RSSI); - // for some reason, display flora differently switch(p->type){ case MI_FLORA:{ @@ -3637,8 +3593,8 @@ void MI32Show(bool json) // provides mac and callback address to receive the key, if we had a website which did this // (future work) if (showkey){ - BLE_ESP32::dump(_MAC, 13, p->MAC,6); - WSContentSend_PD(HTTP_NEEDKEY, typeName, _MAC, Webserver->client().localIP().toString().c_str(), tmp ); + BLE_ESP32::dump(_MAC, 13, p->MAC, 6); + WSContentSend_P(HTTP_NEEDKEY, typeName, _MAC, IPGetListeningAddressStr().c_str(), tmp); } #endif //USE_MI_DECRYPTION @@ -3691,7 +3647,7 @@ void MI32Show(bool json) _page++; _counter=0; } - if (MIBLEsensors.size()%MI32.perPage==0 && _page==MIBLEsensors.size()/MI32.perPage) { _page = 0; } + if (MIBLEsensors.size()%MI32.perPage == 0 && _page==MIBLEsensors.size()/MI32.perPage) { _page = 0; } if (_page>MIBLEsensors.size()/MI32.perPage) { _page = 0; } #endif // USE_WEBSERVER } From a13e83e1e69666b19946ec9e3285af65d04aee82 Mon Sep 17 00:00:00 2001 From: Benjamin Nestler <101095581+benjaminnestler@users.noreply.github.com> Date: Fri, 12 Jan 2024 10:08:05 +0100 Subject: [PATCH 129/303] FIX: Reset the 'upload_error' variable after web file upload error (#20340) * FIX: Reset the 'upload_error' variable after signaling the error to enable the next upload action. * ADD: Introduce HandleUploadUFSDone() to display information messages for uploaded files in UFS and handle errors. ADD: Include '?fsz=' web-argument (filesize) in the upload button click function. --- .../xdrv_01_9_webserver.ino | 22 +++++++--- .../xdrv_50_filesystem.ino | 43 +++++++++++++++++-- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino index b87aec505..69bdaddb2 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino @@ -2777,7 +2777,10 @@ void HandleUploadLoop(void) { if (UPLOAD_FILE_START == upload.status) { Web.upload_error = 0; upload_error_signalled = false; - upload_size = 0; + char tmp[16]; + + WebGetArg("fsz", tmp, sizeof(tmp)); // filesize + upload_size = (!strlen(tmp)) ? 0 : atoi(tmp); UploadServices(0); @@ -2785,18 +2788,25 @@ void HandleUploadLoop(void) { Web.upload_error = 1; // No file selected return; } - SettingsSave(1); // Free flash for upload - AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD D_FILE " %s"), upload.filename.c_str()); + AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD D_FILE " %s (%d bytes)"), upload.filename.c_str(), upload_size); #ifdef USE_UFILESYS if (UPL_UFSFILE == Web.upload_file_type) { + const uint32_t freeBytes = (UfsFree() * 1024); + if (upload_size > freeBytes) { + Web.upload_error = 9; // File too large + return; + } + if (!UfsUploadFileOpen(upload.filename.c_str())) { - Web.upload_error = 2; + Web.upload_error = 2; // Not enough space return; } } #endif // USE_UFILESYS + + SettingsSave(1); // Free flash for upload } // ***** Step2: Write upload file @@ -2890,7 +2900,7 @@ void HandleUploadLoop(void) { Web.config_block_count++; } #ifdef USE_UFILESYS - else if (UPL_UFSFILE == Web.upload_file_type) { + else if (!Web.upload_error && UPL_UFSFILE == Web.upload_file_type) { if (!UfsUploadFileWrite(upload.buf, upload.currentSize)) { Web.upload_error = 9; // File too large return; @@ -2925,7 +2935,7 @@ void HandleUploadLoop(void) { } } #ifdef USE_UFILESYS - else if (UPL_UFSFILE == Web.upload_file_type) { + else if (!Web.upload_error && UPL_UFSFILE == Web.upload_file_type) { UfsUploadFileClose(); } #endif // USE_UFILESYS diff --git a/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino b/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino index f577d5904..df3dd7260 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino @@ -803,9 +803,11 @@ const char UFS_FORM_FILE_UPGc2[] PROGMEM = "
"; const char UFS_FORM_FILE_UPG[] PROGMEM = - "
" + "" "

" - "
" + "
" "

"; const char UFS_FORM_SDC_DIRa[] PROGMEM = "
"; @@ -858,6 +860,40 @@ const char HTTP_EDITOR_FORM_END[] PROGMEM = #endif // #ifdef GUI_EDIT_FILE +void HandleUploadUFSDone(void) { + if (!HttpCheckPriviledgedAccess()) { return; } + + HTTPUpload& upload = Webserver->upload(); + + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPLOAD_DONE)); + + WifiConfigCounter(); + UploadServices(1); + + WSContentStart_P(PSTR(D_INFORMATION)); + + WSContentSendStyle(); + WSContentSend_P(PSTR("
" D_UPLOAD " " D_FAILED "

"), WebColor(COL_TEXT_WARNING)); + char error[100]; + if (Web.upload_error < 10) { + GetTextIndexed(error, sizeof(error), Web.upload_error -1, kUploadErrors); + } else { + snprintf_P(error, sizeof(error), PSTR(D_UPLOAD_ERROR_CODE " %d"), Web.upload_error); + } + WSContentSend_P(error); + Web.upload_error = 0; + } else { + WSContentSend_P(PSTR("%06x'>" D_SUCCESSFUL "
"), WebColor(COL_TEXT_SUCCESS)); + } + WSContentSend_P(PSTR("

")); + + XdrvCall(FUNC_WEB_ADD_MANAGEMENT_BUTTON); + + WSContentStop(); +} + void UfsDirectory(void) { if (!HttpCheckPriviledgedAccess()) { return; } @@ -1457,7 +1493,8 @@ bool Xdrv50(uint32_t function) { // Webserver->on(F("/ufsu"), HTTP_POST,[](){Webserver->sendHeader(F("Location"),F("/ufsu"));Webserver->send(303);}, HandleUploadLoop); Webserver->on("/ufsd", UfsDirectory); Webserver->on("/ufsu", HTTP_GET, UfsDirectory); - Webserver->on("/ufsu", HTTP_POST,[](){Webserver->sendHeader(F("Location"),F("/ufsu"));Webserver->send(303);}, HandleUploadLoop); + //Webserver->on("/ufsu", HTTP_POST,[](){Webserver->sendHeader(F("Location"),F("/ufsu"));Webserver->send(303);}, HandleUploadLoop); + Webserver->on("/ufsu", HTTP_POST, HandleUploadUFSDone, HandleUploadLoop); #ifdef GUI_EDIT_FILE Webserver->on("/ufse", HTTP_GET, UfsEditor); Webserver->on("/ufse", HTTP_POST, UfsEditorUpload); From 3e3bfccb584fcae3a274e35c1f461b1c6e8a94f1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 12 Jan 2024 12:17:31 +0100 Subject: [PATCH 130/303] Bump version v13.3.0.3 --- CHANGELOG.md | 25 ++++++++++---- RELEASENOTES.md | 6 +++- tasmota/include/tasmota_version.h | 2 +- tasmota/my_user_config.h | 1 + .../xdrv_121_gpioviewer.ino | 34 ++++++++++++++++--- .../tasmota_xsns_sensor/xsns_02_analog.ino | 21 ++++++------ 6 files changed, 66 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 879cb98f5..f455a6d5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,24 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - Development -## [13.3.0.2] +## [13.3.0.3] +### Added +- Berry `debug.caller` (#20470) +- GPIO Viewer user selection of assets website now defaults to `https://ota.tasmota.com/tasmota|tasmota32/gpio_viewer/assets` + +### Breaking Changed + +### Changed +- SML update (#20474) + +### Fixed +- Scripter memory leak in `>w x` (#20473) +- ESP8266 GPIO Viewer exception 9 on reading Analog GPIO + +### Removed + + +## [13.3.0.2] 20240111 ### Added - HASPmota type `chart` (#20372) - Berry add support for `tcpclientasync` in `tcpserver` (#20401) @@ -20,9 +37,6 @@ All notable changes to this project will be documented in this file. - Berry provide lightweight options for `tasmota.wifi/eth/memory/rtc` (#20448) - Berry `tasmota.webcolor` (#20454) - Support for pipsolar inverter (#20408) -- Berry `debug.caller` - -### Breaking Changed ### Changed - Renamed button "Consoles" to "Tools" @@ -35,9 +49,6 @@ All notable changes to this project will be documented in this file. ### Fixed - ESP32 Zigbee Aqara attributes (#20452) -### Removed - - ## [13.3.0.1] 20240101 ### Added - Support for Sonoff Basic R4 Magic Switch (#20247) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index d17e5cb3c..4ad43ade1 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -116,12 +116,13 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm [Complete list](BUILDS.md) of available feature and sensors. -## Changelog v13.3.0.2 +## Changelog v13.3.0.3 ### Added - Support for CST816S touch interface [#20213](https://github.com/arendst/Tasmota/issues/20213) - Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247) - Display of active drivers using command ``status 4`` - GPIO Viewer to see realtime GPIO states. Enable with define USE_GPIO_VIEWER +- GPIO Viewer user selection of assets website now defaults to `https://ota.tasmota.com/tasmota|tasmota32/gpio_viewer/assets` - NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) - Support negative power on BL0942 using index 5..8 [#20322](https://github.com/arendst/Tasmota/issues/20322) - Support for pipsolar inverter [#20408](https://github.com/arendst/Tasmota/issues/20408) @@ -139,6 +140,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Berry `webserver.header` to read browser sent headers [#20447](https://github.com/arendst/Tasmota/issues/20447) - Berry provide lightweight options for `tasmota.wifi/eth/memory/rtc` [#20448](https://github.com/arendst/Tasmota/issues/20448) - Berry `tasmota.webcolor` [#20454](https://github.com/arendst/Tasmota/issues/20454) +- Berry `debug.caller` [#20470](https://github.com/arendst/Tasmota/issues/20470) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) - HASPmota type `chart` [#20372](https://github.com/arendst/Tasmota/issues/20372) - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) @@ -154,11 +156,13 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` [#20260](https://github.com/arendst/Tasmota/issues/20260) - Header `Host` is now collected by Webserver [#20446](https://github.com/arendst/Tasmota/issues/20446) - Webcam tweaks [#20451](https://github.com/arendst/Tasmota/issues/20451) +- SML update [#20474](https://github.com/arendst/Tasmota/issues/20474) ### Fixed - CVE-2021-36603 Cross Site Scripting (XSS) vulnerability [#12221](https://github.com/arendst/Tasmota/issues/12221) - Syslog server warning caused by lack of field and hostname starting with 'z' [#14689](https://github.com/arendst/Tasmota/issues/14689) - Support for Domoticz floor/room topics. Regression from v12.0.1 [#20299](https://github.com/arendst/Tasmota/issues/20299) +- Scripter memory leak in `>w x` (#20473)[#20473](https://github.com/arendst/Tasmota/issues/20473) - ESP32 piezo ceramic buzzer doesn't buzz [#20118](https://github.com/arendst/Tasmota/issues/20118) - ESP32 Zigbee Aqara attributes [#20452](https://github.com/arendst/Tasmota/issues/20452) - LVGL fix type for lv_imgbtn [#20354](https://github.com/arendst/Tasmota/issues/20354) diff --git a/tasmota/include/tasmota_version.h b/tasmota/include/tasmota_version.h index ac87a0ef4..67c71e010 100644 --- a/tasmota/include/tasmota_version.h +++ b/tasmota/include/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t TASMOTA_VERSION = 0x0D030002; // 13.3.0.2 +const uint32_t TASMOTA_VERSION = 0x0D030003; // 13.3.0.3 #endif // _TASMOTA_VERSION_H_ diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 80f75b0d8..a5b424b0d 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -471,6 +471,7 @@ // #define USE_WEBSEND_RESPONSE // Enable command WebSend response message (+1k code) // #define USE_WEBGETCONFIG // Enable restoring config from external webserver (+0k6) // #define USE_GPIO_VIEWER // Enable GPIO Viewer to see realtime GPIO states (+4k code) +// #define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" // #define GV_SAMPLING_INTERVAL 100 // [GvSampling] milliseconds - Use Tasmota Scheduler (100) or Ticker (20..99,101..1000) #define USE_EMULATION_HUE // Enable Hue Bridge emulation for Alexa (+14k code, +2k mem common) #define USE_EMULATION_WEMO // Enable Belkin WeMo emulation for Alexa (+6k code, +2k mem common) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index ca6a87f96..7d558cc45 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -26,7 +26,19 @@ #define GV_KEEP_ALIVE 1000 // milliseconds - If no activity after this do a heap size event anyway -#define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" +//#define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" +#ifdef ESP8266 +#ifndef GV_BASE_URL +#undef GV_BASE_URL // Fix compiler warning +#define GV_BASE_URL "https://ota.tasmota.com/tasmota/gpio_viewer/assets/" +#endif +#endif // ESP8266 +#ifdef ESP32 +#ifndef GV_BASE_URL +#undef GV_BASE_URL // Fix compiler warning +#define GV_BASE_URL "https://ota.tasmota.com/tasmota32/gpio_viewer/assets/" +#endif +#endif // ESP32 const char *GVRelease = "1.0.7"; @@ -196,6 +208,7 @@ void GVMonitorTask(void) { for (uint32_t pin = 0; pin < MAX_GPIO_PIN; pin++) { int currentState = 0; /* + // Skip unconfigured GPIO uint32_t pin_type = GetPin(pin) / 32; if (GPIO_NONE == pin_type) { pintype = GV_DigitalPin; @@ -204,6 +217,7 @@ void GVMonitorTask(void) { } */ #ifdef ESP32 + // Read PWM GPIO int pwm_resolution = ledcReadDutyResolution(pin); if (pwm_resolution > 0) { pintype = GV_PWMPin; @@ -213,6 +227,7 @@ void GVMonitorTask(void) { #endif // ESP32 #ifdef ESP8266 + // Read PWM GPIO int pwm_value = AnalogRead(pin); if (pwm_value > -1) { pintype = GV_PWMPin; @@ -222,11 +237,22 @@ void GVMonitorTask(void) { #endif // ESP8266 else if (AdcPin(pin)) { + // Read Analog (ADC) GPIO pintype = GV_AnalogPin; +/* +#ifdef ESP32 originalValue = AdcRead(pin, 2); - int adc_resolution = (1 << AdcResolution()) - 1; - currentState = changeUIntScale(originalValue, 0, adc_resolution, 0, 255); // bring back to 0..255 - } else { +#endif // ESP32 +#ifdef ESP8266 + // Fix exception 9 if using ticker - GV.sampling != 100 (CallChain: (phy)pm_wakeup_init, (adc)test_tout, ets_timer_arm_new, delay, AdcRead, String6concat, MonitorTask) + originalValue = (GV.sampling != 100) ? analogRead(pin) : AdcRead(pin, 1); +#endif // ESP8266 +*/ + originalValue = AdcRead1(pin); + currentState = changeUIntScale(originalValue, 0, AdcRange(), 0, 255); // bring back to 0..255 + } + else { + // Read digital GPIO pintype = GV_DigitalPin; int value = digitalRead(pin); originalValue = value; diff --git a/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino b/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino index 5dee065f8..7c4d4c75e 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino @@ -324,8 +324,8 @@ void AdcInit(void) { } } -uint32_t AdcResolution(void) { - return ANALOG_RESOLUTION; +uint32_t AdcRange(void) { + return ANALOG_RANGE; } bool AdcPin(uint32_t pin) { @@ -337,6 +337,14 @@ bool AdcPin(uint32_t pin) { return false; } +uint16_t AdcRead1(uint32_t pin) { +#ifdef ESP32 + return analogReadMilliVolts(pin) / (ANALOG_V33*1000) * ANALOG_RANGE; // go back from mV to ADC +#else + return analogRead(pin); +#endif +} + uint16_t AdcRead(uint32_t pin, uint32_t factor) { // factor 1 = 2 samples // factor 2 = 4 samples @@ -348,17 +356,10 @@ uint16_t AdcRead(uint32_t pin, uint32_t factor) { uint32_t samples = 1 << factor; uint32_t analog = 0; for (uint32_t i = 0; i < samples; i++) { -#ifdef ESP32 - analog += analogReadMilliVolts(pin); // get the value corrected by calibrated values from the eFuses -#else - analog += analogRead(pin); -#endif + analog += AdcRead1(pin); delay(1); } analog >>= factor; -#ifdef ESP32 - analog = analog/(ANALOG_V33*1000) * ANALOG_RANGE; // go back from mV to ADC -#endif return analog; } From f065d74293a5717a3638bbbf830daa0af35c17f5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 12 Jan 2024 13:57:31 +0100 Subject: [PATCH 131/303] Add support for HardwareSerial invert (#15461) --- CHANGELOG.md | 1 + RELEASENOTES.md | 1 + lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.cpp | 7 ++++--- lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.h | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f455a6d5a..90c881e1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - Berry `debug.caller` (#20470) - GPIO Viewer user selection of assets website now defaults to `https://ota.tasmota.com/tasmota|tasmota32/gpio_viewer/assets` +- Support for HardwareSerial invert (#15461) ### Breaking Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 4ad43ade1..965134b73 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -126,6 +126,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) - Support negative power on BL0942 using index 5..8 [#20322](https://github.com/arendst/Tasmota/issues/20322) - Support for pipsolar inverter [#20408](https://github.com/arendst/Tasmota/issues/20408) +- Support for HardwareSerial invert [#15461](https://github.com/arendst/Tasmota/issues/15461) - ESP32 used UART information - ESP32 experimental support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled - Berry GPIO viewer initial version using async webserver [#20416](https://github.com/arendst/Tasmota/issues/20416) diff --git a/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.cpp b/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.cpp index 9bdfb9733..3dd33b95e 100644 --- a/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.cpp +++ b/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.cpp @@ -46,11 +46,12 @@ static uint32_t tasmota_serial_uart_bitmap = 0; // Assigned UARTs #endif // ESP32 -TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fallback, int nwmode, int buffer_size) { +TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fallback, int nwmode, int buffer_size, bool invert) { m_valid = false; m_hardserial = false; m_hardswap = false; m_overflow = false; + m_invert = invert; m_data_bits = 8; m_stop_bits = 1; m_nwmode = nwmode; @@ -155,7 +156,7 @@ bool TasmotaSerial::freeUart(void) { } void TasmotaSerial::Esp32Begin(void) { - TSerial->begin(m_speed, m_config, m_rx_pin, m_tx_pin); + TSerial->begin(m_speed, m_config, m_rx_pin, m_tx_pin, m_invert); // For low bit rate, below 9600, set the Full RX threshold at 10 bytes instead of the default 120 if (m_speed <= 9600) { // At 9600, 10 chars are ~10ms @@ -219,7 +220,7 @@ bool TasmotaSerial::begin(uint32_t speed, uint32_t config) { } #ifdef ESP8266 Serial.flush(); - Serial.begin(speed, (SerialConfig)config); + Serial.begin(speed, (SerialConfig)config, SERIAL_FULL, m_tx_pin, m_invert); if (m_hardswap) { Serial.swap(); } diff --git a/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.h b/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.h index 2f9be0963..66caa4102 100644 --- a/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.h +++ b/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.h @@ -37,7 +37,7 @@ class TasmotaSerial : public Stream { public: - TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fallback = 0, int nwmode = 0, int buffer_size = TM_SERIAL_BUFFER_SIZE); + TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fallback = 0, int nwmode = 0, int buffer_size = TM_SERIAL_BUFFER_SIZE, bool invert = false); virtual ~TasmotaSerial(); void setTransmitEnablePin(int tx_enable_pin); @@ -102,6 +102,7 @@ class TasmotaSerial : public Stream { bool m_overflow; bool m_high_speed = false; bool m_very_high_speed = false; // above 100000 bauds + bool m_invert; uint8_t *m_buffer = nullptr; #ifdef ESP32 uint32_t m_speed; From 61f6c26b03ee4df5c793673ea1a47dfe1b09876c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 12 Jan 2024 16:54:24 +0100 Subject: [PATCH 132/303] Fix GPIO Viewer single instance --- CHANGELOG.md | 1 + .../xdrv_121_gpioviewer.ino | 81 ++++++++++--------- 2 files changed, 45 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90c881e1d..67615e03a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ All notable changes to this project will be documented in this file. ### Fixed - Scripter memory leak in `>w x` (#20473) - ESP8266 GPIO Viewer exception 9 on reading Analog GPIO +- GPIO Viewer single instance ### Removed diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 7d558cc45..2685acfe9 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -105,6 +105,15 @@ struct { bool sse_ready; } GV; +void GVStop(void) { + GV.sse_ready = false; + GV.ticker.detach(); + GV.active = false; + + GV.WebServer->stop(); + GV.WebServer = nullptr; +} + void GVBegin(void) { if (0 == GV.sampling) { GV.sampling = (GV_SAMPLING_INTERVAL < 20) ? 20 : GV_SAMPLING_INTERVAL; @@ -115,40 +124,18 @@ void GVBegin(void) { GV.WebServer->sendHeader("Access-Control-Allow-Origin", "*"); GV.WebServer->sendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); GV.WebServer->sendHeader("Access-Control-Allow-Headers", "Content-Type"); - GV.WebServer->on("/events", GVHandleEvents); GV.WebServer->on("/", GVHandleRoot); GV.WebServer->on("/release", GVHandleRelease); GV.WebServer->on("/free_psram", GVHandleFreePSRam); + GV.WebServer->on("/events", GVHandleEvents); GV.WebServer->begin(); GV.active = true; } -void GVStop(void) { - GV.sse_ready = false; - GV.ticker.detach(); - GV.active = false; - - GV.WebServer->stop(); - GV.WebServer = nullptr; -} - -void GVHandleEvents(void) { - GV.WebClient = GV.WebServer->client(); - GV.WebClient.setNoDelay(true); -// GV.WebClient.setSync(true); - - GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // The payload can go on forever - GV.WebServer->sendContent_P(HTTP_GV_EVENT); - - GV.sse_ready = true; // Ready for async updates - if (GV.sampling != 100) { - GV.ticker.attach_ms(GV.sampling, GVMonitorTask); // Use Tasmota Scheduler (100) or Ticker (20..99,101..1000) - } - AddLog(LOG_LEVEL_DEBUG, PSTR("IOV: Connected")); -} - void GVHandleRoot(void) { + GVCloseEvent(); + char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, SettingsTextEscaped(SET_DEVICENAME).c_str(), WiFi.localIP().toString().c_str(), @@ -161,9 +148,6 @@ void GVHandleRoot(void) { if (content == nullptr) { return; } // Avoid crash GV.WebServer->send_P(200, "text/html", content); free(content); - - GV.sse_ready = false; // Allow restart of updates on page load - GV.ticker.detach(); } void GVHandleRelease(void) { @@ -182,6 +166,34 @@ void GVHandleFreePSRam(void) { GV.WebServer->send(200, "application/json", jsonResponse); } +void GVHandleEvents(void) { + GV.WebClient = GV.WebServer->client(); + GV.WebClient.setNoDelay(true); +// GV.WebClient.setSync(true); + + GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // The payload can go on forever + GV.WebServer->sendContent_P(HTTP_GV_EVENT); + + GV.sse_ready = true; // Ready for async updates + if (GV.sampling != 100) { + GV.ticker.attach_ms(GV.sampling, GVMonitorTask); // Use Tasmota Scheduler (100) or Ticker (20..99,101..1000) + } + AddLog(LOG_LEVEL_DEBUG, PSTR("IOV: Connected")); +} + +void GVEventDisconnected(void) { + if (GV.sse_ready) { + AddLog(LOG_LEVEL_DEBUG, PSTR("IOV: Disconnected")); + } + GV.sse_ready = false; // This just stops the event to be restarted by opening root page again + GV.ticker.detach(); +} + +void GVCloseEvent(void) { + GVEventSend("{}", "close", millis()); // Closes window + GVEventDisconnected(); +} + //void GVEventSend(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); void GVEventSend(const char *message, const char *event, uint32_t id) { if (GV.WebClient.connected()) { @@ -189,12 +201,7 @@ void GVEventSend(const char *message, const char *event, uint32_t id) { // GV.WebClient.printf_P(PSTR("retry: 0\r\nid: %u\r\nevent: %s\r\ndata: %s\r\n\r\n"), id, event, message); GV.WebClient.printf_P(PSTR("id: %u\r\nevent: %s\r\ndata: %s\r\n\r\n"), id, event, message); } else { - if (GV.sse_ready) { - AddLog(LOG_LEVEL_DEBUG, PSTR("IOV: Disconnected")); - } -// GVStop(); // This will stop the webserver but not all memory will be released resulting in memory leaks - GV.sse_ready = false; // This just stops the event to be restarted by opening root page again - GV.ticker.detach(); + GVEventDisconnected(); } } @@ -335,6 +342,7 @@ void CmndGvViewer(void) { if (state) { // On GVBegin(); } else { // Off + GVCloseEvent(); // Stop current updates GVStop(); } } @@ -350,8 +358,7 @@ void CmndGvSampling(void) { GvSampling 20 .. 1000 - Set sampling interval */ if ((XdrvMailbox.payload >= 20) && (XdrvMailbox.payload <= 1000)) { - GV.sse_ready = false; // Stop current updates - GV.ticker.detach(); + GVCloseEvent(); // Stop current updates GV.sampling = XdrvMailbox.payload; // 20 - 1000 milliseconds } ResponseCmndNumber(GV.sampling); @@ -371,7 +378,7 @@ void GVSetupAndStart(void) { AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_GPIO_VIEWER)); - if (!GV.active) { + if (!GV.active) { // WebServer not started GVBegin(); } From 08a14ccc9e86cb4f1df728999f4f9985a6f6d188 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Fri, 12 Jan 2024 19:48:33 +0100 Subject: [PATCH 133/303] LVGL add `lv.str_arr` (#20480) --- CHANGELOG.md | 1 + lib/libesp32/berry/src/be_introspectlib.c | 5 +- .../src/embedded/lvgl_extra.be | 17 +- .../src/solidify/solidified_lvgl_extra.h | 409 +++++++++++------- 4 files changed, 266 insertions(+), 166 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67615e03a..1759ce230 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. - Berry `debug.caller` (#20470) - GPIO Viewer user selection of assets website now defaults to `https://ota.tasmota.com/tasmota|tasmota32/gpio_viewer/assets` - Support for HardwareSerial invert (#15461) +- LVGL add `lv.str_arr` ### Breaking Changed diff --git a/lib/libesp32/berry/src/be_introspectlib.c b/lib/libesp32/berry/src/be_introspectlib.c index 73e2da466..ba3d60aa2 100644 --- a/lib/libesp32/berry/src/be_introspectlib.c +++ b/lib/libesp32/berry/src/be_introspectlib.c @@ -108,7 +108,10 @@ static int m_toptr(bvm *vm) int top = be_top(vm); if (top >= 1) { bvalue *v = be_indexof(vm, 1); - if (var_basetype(v) >= BE_FUNCTION || var_type(v) == BE_COMPTR) { + if (var_type(v) == BE_STRING) { + be_pushcomptr(vm, be_tostring(vm, 1)); + be_return(vm); + } else if (var_basetype(v) >= BE_FUNCTION || var_type(v) == BE_COMPTR) { be_pushcomptr(vm, var_toobj(v)); be_return(vm); } else if (var_type(v) == BE_INT) { diff --git a/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lvgl_extra.be b/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lvgl_extra.be index b12d0093d..71aa1d02b 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lvgl_extra.be +++ b/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lvgl_extra.be @@ -37,7 +37,6 @@ end class lv_point_arr : bytes def init(l) if type(l) != 'instance' || !isinstance(l, list) raise "value_error", "argument must be a list" end - # size of the array is 2x number of elements super(self).init(size(l) * 4) for e: l @@ -51,7 +50,6 @@ end class lv_style_prop_arr : bytes def init(l) if type(l) != 'instance' || !isinstance(l, list) raise "value_error", "argument must be a list" end - # size of the array is 2x number of elements super(self).init(size(l) * 4) for e: l @@ -60,9 +58,23 @@ class lv_style_prop_arr : bytes end end +class lv_str_arr : bytes + var l # keep a copy of the list because we want the pointer to strings to remain valid + def init(l) + self.l = l + super(self).init(size(l) * 4) + + import introspect + for e: l + self.add(int(introspect.toptr(e)), 4) + end + end +end + lv_extra.lv_coord_arr = lv_coord_arr lv_extra.lv_point_arr = lv_point_arr lv_extra.lv_style_prop_arr = lv_style_prop_arr +lv_extra.lv_str_arr = lv_str_arr lv_extra.init = def (m) import global @@ -73,6 +85,7 @@ lv_extra.init = def (m) lv.coord_arr = m.lv_coord_arr lv.point_arr = m.lv_point_arr lv.style_prop_arr = m.lv_style_prop_arr + lv.str_arr = m.lv_str_arr return m end diff --git a/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lvgl_extra.h b/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lvgl_extra.h index 446b427ec..8ac966889 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lvgl_extra.h +++ b/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lvgl_extra.h @@ -4,6 +4,194 @@ \********************************************************************/ #include "be_constobj.h" +extern const bclass be_class_lv_style_prop_arr; + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(lv_style_prop_arr_init, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(instance), + /* K1 */ be_nested_str_weak(value_error), + /* K2 */ be_nested_str_weak(argument_X20must_X20be_X20a_X20list), + /* K3 */ be_nested_str_weak(init), + /* K4 */ be_nested_str_weak(add), + /* K5 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[38]) { /* code */ + 0x60080004, // 0000 GETGBL R2 G4 + 0x5C0C0200, // 0001 MOVE R3 R1 + 0x7C080200, // 0002 CALL R2 1 + 0x20080500, // 0003 NE R2 R2 K0 + 0x740A0004, // 0004 JMPT R2 #000A + 0x6008000F, // 0005 GETGBL R2 G15 + 0x5C0C0200, // 0006 MOVE R3 R1 + 0x60100012, // 0007 GETGBL R4 G18 + 0x7C080400, // 0008 CALL R2 2 + 0x740A0000, // 0009 JMPT R2 #000B + 0xB0060302, // 000A RAISE 1 K1 K2 + 0x60080003, // 000B GETGBL R2 G3 + 0x5C0C0000, // 000C MOVE R3 R0 + 0x7C080200, // 000D CALL R2 1 + 0x8C080503, // 000E GETMET R2 R2 K3 + 0x6010000C, // 000F GETGBL R4 G12 + 0x5C140200, // 0010 MOVE R5 R1 + 0x7C100200, // 0011 CALL R4 1 + 0x54160003, // 0012 LDINT R5 4 + 0x08100805, // 0013 MUL R4 R4 R5 + 0x7C080400, // 0014 CALL R2 2 + 0x60080010, // 0015 GETGBL R2 G16 + 0x5C0C0200, // 0016 MOVE R3 R1 + 0x7C080200, // 0017 CALL R2 1 + 0xA8020008, // 0018 EXBLK 0 #0022 + 0x5C0C0400, // 0019 MOVE R3 R2 + 0x7C0C0000, // 001A CALL R3 0 + 0x8C100104, // 001B GETMET R4 R0 K4 + 0x60180009, // 001C GETGBL R6 G9 + 0x5C1C0600, // 001D MOVE R7 R3 + 0x7C180200, // 001E CALL R6 1 + 0x541E0003, // 001F LDINT R7 4 + 0x7C100600, // 0020 CALL R4 3 + 0x7001FFF6, // 0021 JMP #0019 + 0x58080005, // 0022 LDCONST R2 K5 + 0xAC080200, // 0023 CATCH R2 1 0 + 0xB0080000, // 0024 RAISE 2 R0 R0 + 0x80000000, // 0025 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: lv_style_prop_arr +********************************************************************/ +extern const bclass be_class_bytes; +be_local_class(lv_style_prop_arr, + 0, + &be_class_bytes, + be_nested_map(1, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(init, -1), be_const_closure(lv_style_prop_arr_init_closure) }, + })), + be_str_weak(lv_style_prop_arr) +); + +extern const bclass be_class_lv_point_arr; + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(lv_point_arr_init, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[12]) { /* constants */ + /* K0 */ be_nested_str_weak(instance), + /* K1 */ be_nested_str_weak(value_error), + /* K2 */ be_nested_str_weak(argument_X20must_X20be_X20a_X20list), + /* K3 */ be_nested_str_weak(init), + /* K4 */ be_nested_str_weak(lv), + /* K5 */ be_nested_str_weak(lv_point), + /* K6 */ be_nested_str_weak(elements_X20must_X20be_X20a_X20lv_point), + /* K7 */ be_nested_str_weak(add), + /* K8 */ be_nested_str_weak(x), + /* K9 */ be_const_int(2), + /* K10 */ be_nested_str_weak(y), + /* K11 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[52]) { /* code */ + 0x60080004, // 0000 GETGBL R2 G4 + 0x5C0C0200, // 0001 MOVE R3 R1 + 0x7C080200, // 0002 CALL R2 1 + 0x20080500, // 0003 NE R2 R2 K0 + 0x740A0004, // 0004 JMPT R2 #000A + 0x6008000F, // 0005 GETGBL R2 G15 + 0x5C0C0200, // 0006 MOVE R3 R1 + 0x60100012, // 0007 GETGBL R4 G18 + 0x7C080400, // 0008 CALL R2 2 + 0x740A0000, // 0009 JMPT R2 #000B + 0xB0060302, // 000A RAISE 1 K1 K2 + 0x60080003, // 000B GETGBL R2 G3 + 0x5C0C0000, // 000C MOVE R3 R0 + 0x7C080200, // 000D CALL R2 1 + 0x8C080503, // 000E GETMET R2 R2 K3 + 0x6010000C, // 000F GETGBL R4 G12 + 0x5C140200, // 0010 MOVE R5 R1 + 0x7C100200, // 0011 CALL R4 1 + 0x54160003, // 0012 LDINT R5 4 + 0x08100805, // 0013 MUL R4 R4 R5 + 0x7C080400, // 0014 CALL R2 2 + 0x60080010, // 0015 GETGBL R2 G16 + 0x5C0C0200, // 0016 MOVE R3 R1 + 0x7C080200, // 0017 CALL R2 1 + 0xA8020016, // 0018 EXBLK 0 #0030 + 0x5C0C0400, // 0019 MOVE R3 R2 + 0x7C0C0000, // 001A CALL R3 0 + 0x60100004, // 001B GETGBL R4 G4 + 0x5C140600, // 001C MOVE R5 R3 + 0x7C100200, // 001D CALL R4 1 + 0x20100900, // 001E NE R4 R4 K0 + 0x74120005, // 001F JMPT R4 #0026 + 0x6010000F, // 0020 GETGBL R4 G15 + 0x5C140600, // 0021 MOVE R5 R3 + 0xB81A0800, // 0022 GETNGBL R6 K4 + 0x88180D05, // 0023 GETMBR R6 R6 K5 + 0x7C100400, // 0024 CALL R4 2 + 0x74120000, // 0025 JMPT R4 #0027 + 0xB0060306, // 0026 RAISE 1 K1 K6 + 0x8C100107, // 0027 GETMET R4 R0 K7 + 0x88180708, // 0028 GETMBR R6 R3 K8 + 0x581C0009, // 0029 LDCONST R7 K9 + 0x7C100600, // 002A CALL R4 3 + 0x8C100107, // 002B GETMET R4 R0 K7 + 0x8818070A, // 002C GETMBR R6 R3 K10 + 0x581C0009, // 002D LDCONST R7 K9 + 0x7C100600, // 002E CALL R4 3 + 0x7001FFE8, // 002F JMP #0019 + 0x5808000B, // 0030 LDCONST R2 K11 + 0xAC080200, // 0031 CATCH R2 1 0 + 0xB0080000, // 0032 RAISE 2 R0 R0 + 0x80000000, // 0033 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: lv_point_arr +********************************************************************/ +extern const bclass be_class_bytes; +be_local_class(lv_point_arr, + 0, + &be_class_bytes, + be_nested_map(1, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(init, -1), be_const_closure(lv_point_arr_init_closure) }, + })), + be_str_weak(lv_point_arr) +); + /******************************************************************** ** Solidified function: _anonymous_ ********************************************************************/ @@ -17,7 +205,7 @@ be_local_closure(lv_extra__anonymous_, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ + ( &(const bvalue[10]) { /* constants */ /* K0 */ be_nested_str_weak(global), /* K1 */ be_nested_str_weak(lv), /* K2 */ be_nested_str_weak(lv_coord_arr), @@ -26,10 +214,12 @@ be_local_closure(lv_extra__anonymous_, /* name */ /* K5 */ be_nested_str_weak(point_arr), /* K6 */ be_nested_str_weak(style_prop_arr), /* K7 */ be_nested_str_weak(lv_style_prop_arr), + /* K8 */ be_nested_str_weak(str_arr), + /* K9 */ be_nested_str_weak(lv_str_arr), }), be_str_weak(_anonymous_), &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ + ( &(const binstruction[15]) { /* code */ 0xA4060000, // 0000 IMPORT R1 K0 0x88080301, // 0001 GETMBR R2 R1 K1 0x880C0102, // 0002 GETMBR R3 R0 K2 @@ -42,7 +232,9 @@ be_local_closure(lv_extra__anonymous_, /* name */ 0x900A0A03, // 0009 SETMBR R2 K5 R3 0x880C0107, // 000A GETMBR R3 R0 K7 0x900A0C03, // 000B SETMBR R2 K6 R3 - 0x80040000, // 000C RET 1 R0 + 0x880C0109, // 000C GETMBR R3 R0 K9 + 0x900A1003, // 000D SETMBR R2 K8 R3 + 0x80040000, // 000E RET 1 R0 }) ) ); @@ -219,118 +411,14 @@ be_local_class(lv_coord_arr, be_str_weak(lv_coord_arr) ); -extern const bclass be_class_lv_point_arr; +extern const bclass be_class_lv_str_arr; /******************************************************************** ** Solidified function: init ********************************************************************/ -be_local_closure(lv_point_arr_init, /* name */ +be_local_closure(lv_str_arr_init, /* name */ be_nested_proto( - 8, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[12]) { /* constants */ - /* K0 */ be_nested_str_weak(instance), - /* K1 */ be_nested_str_weak(value_error), - /* K2 */ be_nested_str_weak(argument_X20must_X20be_X20a_X20list), - /* K3 */ be_nested_str_weak(init), - /* K4 */ be_nested_str_weak(lv), - /* K5 */ be_nested_str_weak(lv_point), - /* K6 */ be_nested_str_weak(elements_X20must_X20be_X20a_X20lv_point), - /* K7 */ be_nested_str_weak(add), - /* K8 */ be_nested_str_weak(x), - /* K9 */ be_const_int(2), - /* K10 */ be_nested_str_weak(y), - /* K11 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[52]) { /* code */ - 0x60080004, // 0000 GETGBL R2 G4 - 0x5C0C0200, // 0001 MOVE R3 R1 - 0x7C080200, // 0002 CALL R2 1 - 0x20080500, // 0003 NE R2 R2 K0 - 0x740A0004, // 0004 JMPT R2 #000A - 0x6008000F, // 0005 GETGBL R2 G15 - 0x5C0C0200, // 0006 MOVE R3 R1 - 0x60100012, // 0007 GETGBL R4 G18 - 0x7C080400, // 0008 CALL R2 2 - 0x740A0000, // 0009 JMPT R2 #000B - 0xB0060302, // 000A RAISE 1 K1 K2 - 0x60080003, // 000B GETGBL R2 G3 - 0x5C0C0000, // 000C MOVE R3 R0 - 0x7C080200, // 000D CALL R2 1 - 0x8C080503, // 000E GETMET R2 R2 K3 - 0x6010000C, // 000F GETGBL R4 G12 - 0x5C140200, // 0010 MOVE R5 R1 - 0x7C100200, // 0011 CALL R4 1 - 0x54160003, // 0012 LDINT R5 4 - 0x08100805, // 0013 MUL R4 R4 R5 - 0x7C080400, // 0014 CALL R2 2 - 0x60080010, // 0015 GETGBL R2 G16 - 0x5C0C0200, // 0016 MOVE R3 R1 - 0x7C080200, // 0017 CALL R2 1 - 0xA8020016, // 0018 EXBLK 0 #0030 - 0x5C0C0400, // 0019 MOVE R3 R2 - 0x7C0C0000, // 001A CALL R3 0 - 0x60100004, // 001B GETGBL R4 G4 - 0x5C140600, // 001C MOVE R5 R3 - 0x7C100200, // 001D CALL R4 1 - 0x20100900, // 001E NE R4 R4 K0 - 0x74120005, // 001F JMPT R4 #0026 - 0x6010000F, // 0020 GETGBL R4 G15 - 0x5C140600, // 0021 MOVE R5 R3 - 0xB81A0800, // 0022 GETNGBL R6 K4 - 0x88180D05, // 0023 GETMBR R6 R6 K5 - 0x7C100400, // 0024 CALL R4 2 - 0x74120000, // 0025 JMPT R4 #0027 - 0xB0060306, // 0026 RAISE 1 K1 K6 - 0x8C100107, // 0027 GETMET R4 R0 K7 - 0x88180708, // 0028 GETMBR R6 R3 K8 - 0x581C0009, // 0029 LDCONST R7 K9 - 0x7C100600, // 002A CALL R4 3 - 0x8C100107, // 002B GETMET R4 R0 K7 - 0x8818070A, // 002C GETMBR R6 R3 K10 - 0x581C0009, // 002D LDCONST R7 K9 - 0x7C100600, // 002E CALL R4 3 - 0x7001FFE8, // 002F JMP #0019 - 0x5808000B, // 0030 LDCONST R2 K11 - 0xAC080200, // 0031 CATCH R2 1 0 - 0xB0080000, // 0032 RAISE 2 R0 R0 - 0x80000000, // 0033 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: lv_point_arr -********************************************************************/ -extern const bclass be_class_bytes; -be_local_class(lv_point_arr, - 0, - &be_class_bytes, - be_nested_map(1, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(init, -1), be_const_closure(lv_point_arr_init_closure) }, - })), - be_str_weak(lv_point_arr) -); - -extern const bclass be_class_lv_style_prop_arr; - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(lv_style_prop_arr_init, /* name */ - be_nested_proto( - 8, /* nstack */ + 11, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -339,54 +427,47 @@ be_local_closure(lv_style_prop_arr_init, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(instance), - /* K1 */ be_nested_str_weak(value_error), - /* K2 */ be_nested_str_weak(argument_X20must_X20be_X20a_X20list), - /* K3 */ be_nested_str_weak(init), - /* K4 */ be_nested_str_weak(add), + /* K0 */ be_nested_str_weak(l), + /* K1 */ be_nested_str_weak(init), + /* K2 */ be_nested_str_weak(introspect), + /* K3 */ be_nested_str_weak(add), + /* K4 */ be_nested_str_weak(toptr), /* K5 */ be_nested_str_weak(stop_iteration), }), be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[38]) { /* code */ - 0x60080004, // 0000 GETGBL R2 G4 - 0x5C0C0200, // 0001 MOVE R3 R1 - 0x7C080200, // 0002 CALL R2 1 - 0x20080500, // 0003 NE R2 R2 K0 - 0x740A0004, // 0004 JMPT R2 #000A - 0x6008000F, // 0005 GETGBL R2 G15 - 0x5C0C0200, // 0006 MOVE R3 R1 - 0x60100012, // 0007 GETGBL R4 G18 - 0x7C080400, // 0008 CALL R2 2 - 0x740A0000, // 0009 JMPT R2 #000B - 0xB0060302, // 000A RAISE 1 K1 K2 - 0x60080003, // 000B GETGBL R2 G3 - 0x5C0C0000, // 000C MOVE R3 R0 - 0x7C080200, // 000D CALL R2 1 - 0x8C080503, // 000E GETMET R2 R2 K3 - 0x6010000C, // 000F GETGBL R4 G12 - 0x5C140200, // 0010 MOVE R5 R1 - 0x7C100200, // 0011 CALL R4 1 - 0x54160003, // 0012 LDINT R5 4 - 0x08100805, // 0013 MUL R4 R4 R5 - 0x7C080400, // 0014 CALL R2 2 - 0x60080010, // 0015 GETGBL R2 G16 - 0x5C0C0200, // 0016 MOVE R3 R1 - 0x7C080200, // 0017 CALL R2 1 - 0xA8020008, // 0018 EXBLK 0 #0022 - 0x5C0C0400, // 0019 MOVE R3 R2 - 0x7C0C0000, // 001A CALL R3 0 - 0x8C100104, // 001B GETMET R4 R0 K4 - 0x60180009, // 001C GETGBL R6 G9 - 0x5C1C0600, // 001D MOVE R7 R3 - 0x7C180200, // 001E CALL R6 1 - 0x541E0003, // 001F LDINT R7 4 - 0x7C100600, // 0020 CALL R4 3 - 0x7001FFF6, // 0021 JMP #0019 - 0x58080005, // 0022 LDCONST R2 K5 - 0xAC080200, // 0023 CATCH R2 1 0 - 0xB0080000, // 0024 RAISE 2 R0 R0 - 0x80000000, // 0025 RET 0 + ( &(const binstruction[31]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x60080003, // 0001 GETGBL R2 G3 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C080200, // 0003 CALL R2 1 + 0x8C080501, // 0004 GETMET R2 R2 K1 + 0x6010000C, // 0005 GETGBL R4 G12 + 0x5C140200, // 0006 MOVE R5 R1 + 0x7C100200, // 0007 CALL R4 1 + 0x54160003, // 0008 LDINT R5 4 + 0x08100805, // 0009 MUL R4 R4 R5 + 0x7C080400, // 000A CALL R2 2 + 0xA40A0400, // 000B IMPORT R2 K2 + 0x600C0010, // 000C GETGBL R3 G16 + 0x5C100200, // 000D MOVE R4 R1 + 0x7C0C0200, // 000E CALL R3 1 + 0xA802000A, // 000F EXBLK 0 #001B + 0x5C100600, // 0010 MOVE R4 R3 + 0x7C100000, // 0011 CALL R4 0 + 0x8C140103, // 0012 GETMET R5 R0 K3 + 0x601C0009, // 0013 GETGBL R7 G9 + 0x8C200504, // 0014 GETMET R8 R2 K4 + 0x5C280800, // 0015 MOVE R10 R4 + 0x7C200400, // 0016 CALL R8 2 + 0x7C1C0200, // 0017 CALL R7 1 + 0x54220003, // 0018 LDINT R8 4 + 0x7C140600, // 0019 CALL R5 3 + 0x7001FFF4, // 001A JMP #0010 + 0x580C0005, // 001B LDCONST R3 K5 + 0xAC0C0200, // 001C CATCH R3 1 0 + 0xB0080000, // 001D RAISE 2 R0 R0 + 0x80000000, // 001E RET 0 }) ) ); @@ -394,17 +475,18 @@ be_local_closure(lv_style_prop_arr_init, /* name */ /******************************************************************** -** Solidified class: lv_style_prop_arr +** Solidified class: lv_str_arr ********************************************************************/ extern const bclass be_class_bytes; -be_local_class(lv_style_prop_arr, - 0, +be_local_class(lv_str_arr, + 1, &be_class_bytes, - be_nested_map(1, + be_nested_map(2, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(init, -1), be_const_closure(lv_style_prop_arr_init_closure) }, + { be_const_key_weak(init, -1), be_const_closure(lv_str_arr_init_closure) }, + { be_const_key_weak(l, 0), be_const_var(0) }, })), - be_str_weak(lv_style_prop_arr) + be_str_weak(lv_str_arr) ); /******************************************************************** @@ -412,12 +494,13 @@ be_local_class(lv_style_prop_arr, ********************************************************************/ be_local_module(lv_extra, "lv_extra", - be_nested_map(4, + be_nested_map(5, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(lv_style_prop_arr, -1), be_const_class(be_class_lv_style_prop_arr) }, + { be_const_key_weak(init, -1), be_const_closure(lv_extra__anonymous__closure) }, { be_const_key_weak(lv_coord_arr, -1), be_const_class(be_class_lv_coord_arr) }, + { be_const_key_weak(lv_str_arr, -1), be_const_class(be_class_lv_str_arr) }, { be_const_key_weak(lv_point_arr, -1), be_const_class(be_class_lv_point_arr) }, - { be_const_key_weak(init, 0), be_const_closure(lv_extra__anonymous__closure) }, + { be_const_key_weak(lv_style_prop_arr, 2), be_const_class(be_class_lv_style_prop_arr) }, })) ); BE_EXPORT_VARIABLE be_define_const_native_module(lv_extra); From c1f3561a3e19defb022ca796aadeffe653a0f628 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Fri, 12 Jan 2024 22:34:42 +0100 Subject: [PATCH 134/303] Fix random crash in Zigbee main page (#20481) --- CHANGELOG.md | 1 + tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1759ce230..d4a39d86f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file. - Scripter memory leak in `>w x` (#20473) - ESP8266 GPIO Viewer exception 9 on reading Analog GPIO - GPIO Viewer single instance +- Fix random crash in Zigbee main page ### Removed diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino index 4870abd00..a27b25e2b 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino @@ -2335,8 +2335,11 @@ void ZigbeeShow(bool json) WSContentSend_P(PSTR(" 🔅 %d%%"), changeUIntScale(light.getDimmer(),0,254,0,100)); } if (light.validCT() && ((channels == 2) || (channels == 5))) { - uint32_t ct_k = (((1000000 / light.getCT()) + 25) / 50) * 50; - WSContentSend_P(msg[ZB_WEB_LIGHT_CT], light.getCT(), ct_k); + uint16_t ct = light.getCT(); + if (ct != 0) { // ct == 0 means undefined value + uint32_t ct_k = (((1000000 / ct) + 25) / 50) * 50; + WSContentSend_P(msg[ZB_WEB_LIGHT_CT], light.getCT(), ct_k); + } } if (light.validHue() && light.validSat() && (channels >= 3)) { uint8_t r,g,b; From e68a6fd07895eb362cae99141190dc3c082a838a Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Sat, 13 Jan 2024 10:00:39 +0100 Subject: [PATCH 135/303] Add `D_BATTERY` (#20478) Add `D_BATTERY` to language files --- tasmota/language/af_AF.h | 1 + tasmota/language/bg_BG.h | 1 + tasmota/language/ca_AD.h | 1 + tasmota/language/cs_CZ.h | 1 + tasmota/language/de_DE.h | 3 ++- tasmota/language/el_GR.h | 1 + tasmota/language/en_GB.h | 1 + tasmota/language/es_ES.h | 1 + tasmota/language/fr_FR.h | 1 + tasmota/language/fy_NL.h | 1 + tasmota/language/he_HE.h | 1 + tasmota/language/hu_HU.h | 1 + tasmota/language/it_IT.h | 1 + tasmota/language/ko_KO.h | 1 + tasmota/language/nl_NL.h | 1 + tasmota/language/pl_PL.h | 1 + tasmota/language/pt_BR.h | 1 + tasmota/language/pt_PT.h | 1 + tasmota/language/ro_RO.h | 1 + tasmota/language/ru_RU.h | 1 + tasmota/language/sk_SK.h | 1 + tasmota/language/sv_SE.h | 1 + tasmota/language/tr_TR.h | 1 + tasmota/language/uk_UA.h | 1 + tasmota/language/vi_VN.h | 1 + tasmota/language/zh_CN.h | 1 + tasmota/language/zh_TW.h | 1 + tasmota/tasmota_xsns_sensor/xsns_61_MI_NRF24.ino | 2 +- tasmota/tasmota_xsns_sensor/xsns_62_MI_HM10.ino | 2 +- tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino | 2 +- tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino | 3 --- 31 files changed, 31 insertions(+), 7 deletions(-) diff --git a/tasmota/language/af_AF.h b/tasmota/language/af_AF.h index 7224bd8db..94dde999d 100644 --- a/tasmota/language/af_AF.h +++ b/tasmota/language/af_AF.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "as" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Lading" // Battery charge in % #define D_BLINK "Flits" diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index 54e5b9e52..03a62678e 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -57,6 +57,7 @@ #define D_AP "Точка за достъп" // Access Point #define D_AS "като" #define D_AUTO "АВТОМАТИЧНО" +#define D_BATTERY "Battery" #define D_BATT "Бат." // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Мигане вкл." diff --git a/tasmota/language/ca_AD.h b/tasmota/language/ca_AD.h index 086e9c732..cc50a3eec 100644 --- a/tasmota/language/ca_AD.h +++ b/tasmota/language/ca_AD.h @@ -57,6 +57,7 @@ #define D_AP "PA" // Access Point #define D_AS "com" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Bat" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Espurna" diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index 1de0dea2a..0ec5c815a 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "jako" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Blikání" diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index 8c5c5e0f6..2ca6a99c6 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v13.3.0.1 - Last update 18.12.2023 + * Updated until v13.3.0.3 - Last update 12.01.2024 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "als" #define D_AUTO "AUTO" +#define D_BATTERY "Batterie" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Ladung" // Battery charge in % #define D_BLINK "Blinken" diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h index ca6c28fd9..e75f90599 100644 --- a/tasmota/language/el_GR.h +++ b/tasmota/language/el_GR.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "ως" #define D_AUTO "ΑΥΤΟΜΑΤΟ" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Blink" diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index 720f1f169..f7b69de42 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "as" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Blink" diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h index bc8e5728f..02f02e6cf 100644 --- a/tasmota/language/es_ES.h +++ b/tasmota/language/es_ES.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "como" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Bat" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Blink" diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index 1c3fe23fe..fa46c2866 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "comme" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Blink" // Not better in french diff --git a/tasmota/language/fy_NL.h b/tasmota/language/fy_NL.h index 917fa9704..702ca0f03 100644 --- a/tasmota/language/fy_NL.h +++ b/tasmota/language/fy_NL.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "als" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Lading" // Battery charge in % #define D_BLINK "Blinkje" diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index 978149adc..0a6c1124e 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "-כ" #define D_AUTO "אוטומטי" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "מהבהב" diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index 58fd37d0d..50d0195bc 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "mint" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Villogás" diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index 75a216e10..602782c8a 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "come" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Carica" // Battery charge in % #define D_BLINK "Lampeggia" diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index c02ce1fc1..0cdda28dc 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "as" #define D_AUTO "자동" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "깜박임" diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index a5dbe04aa..de431c6cb 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "als" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Lading" // Battery charge in % #define D_BLINK "Knipper" diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h index d890ab6ed..b6b9f1415 100644 --- a/tasmota/language/pl_PL.h +++ b/tasmota/language/pl_PL.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "jak" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Miganie" diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index 75b176504..6f18f4a03 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -57,6 +57,7 @@ #define D_AP "Ponto de acesso" // Ponto de Acesso #define D_AS "como" #define D_AUTO "Auto" +#define D_BATTERY "Battery" #define D_BATT "Bat" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Piscar" diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index 6f06e7222..66dff8468 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Ponto de Acesso #define D_AS "como" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Piscar" diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index 344fe3efe..01abbb59f 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "as" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Blink" diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h index 5291fe748..737939754 100644 --- a/tasmota/language/ru_RU.h +++ b/tasmota/language/ru_RU.h @@ -58,6 +58,7 @@ #define D_AP "AP" // Access Point #define D_AS "как" #define D_AUTO "АВТО" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Мигать" diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index 9bd615000..bc996bdba 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "ako" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Blikanie" diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index 9f64ab048..80cb7d9db 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "som" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Blinka" diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index 3fc97e797..642a4c236 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "as" #define D_AUTO "OTOMATIK" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Blink" diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index e5bcf184a..c54fc3e02 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -57,6 +57,7 @@ #define D_AP "Точка доступу" // Access Point #define D_AS "як" #define D_AUTO "АВТО" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Блимати" diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h index ce42b275c..bf1518f35 100644 --- a/tasmota/language/vi_VN.h +++ b/tasmota/language/vi_VN.h @@ -57,6 +57,7 @@ #define D_AP "Mạng wifi" // Access Point #define D_AS "với tên gọi" #define D_AUTO "AUTO" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "Blink" diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index 54ebf9e0e..3e881da35 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -57,6 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "名称:" #define D_AUTO "自动" +#define D_BATTERY "Battery" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "闪烁" diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index ee54c65a4..7777b7177 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -57,6 +57,7 @@ #define D_AP "存取點" // Access Point #define D_AS "名稱:" #define D_AUTO "自動" +#define D_BATTERY "Battery" #define D_BATT "電池" // Short for Battery #define D_BATTERY_CHARGE "Charge" // Battery charge in % #define D_BLINK "閃爍" diff --git a/tasmota/tasmota_xsns_sensor/xsns_61_MI_NRF24.ino b/tasmota/tasmota_xsns_sensor/xsns_61_MI_NRF24.ino index e6e4b60ec..c9bbb8ed0 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_61_MI_NRF24.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_61_MI_NRF24.ino @@ -1676,7 +1676,7 @@ bool NRFCmd(void) { * Presentation \*********************************************************************************************/ -const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; +const char HTTP_BATTERY[] PROGMEM = "{s}%s " D_BATTERY "{m}%u%%{e}"; const char HTTP_MINRF_MAC[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; const char HTTP_MINRF_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%dus/cm{e}"; const char HTTP_MINRF_HL[] PROGMEM = "{s}
{m}
{e}"; diff --git a/tasmota/tasmota_xsns_sensor/xsns_62_MI_HM10.ino b/tasmota/tasmota_xsns_sensor/xsns_62_MI_HM10.ino index 80609ff73..406f5ec4c 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_62_MI_HM10.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_62_MI_HM10.ino @@ -1952,7 +1952,7 @@ void CmndHM10Option(void){ const char HTTP_HM10[] PROGMEM = "{s}HM10 FW%u V0960{m}%u%s / %u{e}"; const char HTTP_HM10_MAC[] PROGMEM = "{s}%s %s{m}%s{e}"; -const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; +const char HTTP_BATTERY[] PROGMEM = "{s}%s " D_BATTERY "{m}%u%%{e}"; const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}"; const char HTTP_HM10_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%u us/cm{e}"; const char HTTP_HM10_HL[] PROGMEM = "{s}
{m}
{e}"; diff --git a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino index 4ca91f3b2..5acc0d1b5 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino @@ -2350,7 +2350,7 @@ void MI32HandleWebGUI(void){ const char HTTP_MI32[] PROGMEM = "{s}Mi ESP32 {m} %u devices{e}"; #ifndef USE_MI_EXT_GUI -const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u %%{e}"; +const char HTTP_BATTERY[] PROGMEM = "{s}%s " D_BATTERY "{m}%u %%{e}"; const char HTTP_LASTBUTTON[] PROGMEM = "{s}%s Last Button{m}%u {e}"; const char HTTP_EVENTS[] PROGMEM = "{s}%s Events{m}%u {e}"; const char HTTP_NMT[] PROGMEM = "{s}%s No motion{m}> %u seconds{e}"; diff --git a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino index 3cda0633a..06c3e1092 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino @@ -74,9 +74,6 @@ */ //#undef USE_MI_ESP32 -// Move to language files later -#define D_BATTERY "Battery" - // for testing of BLE_ESP32, we remove xsns_62_MI_ESP32.ino completely, and instead add this modified xsns_52_ibeacon_BLE_ESP32.ino #ifdef USE_BLE_ESP32 From 779fe14c604a5f9433d1adb8e9f8377a13a23fab Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 13 Jan 2024 11:19:56 +0100 Subject: [PATCH 136/303] Update changelogs --- CHANGELOG.md | 8 +++++--- RELEASENOTES.md | 6 +++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4a39d86f..21ac11038 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,18 +8,20 @@ All notable changes to this project will be documented in this file. - Berry `debug.caller` (#20470) - GPIO Viewer user selection of assets website now defaults to `https://ota.tasmota.com/tasmota|tasmota32/gpio_viewer/assets` - Support for HardwareSerial invert (#15461) -- LVGL add `lv.str_arr` +- SML support for IM350 (#20474) +- LVGL `lv.str_arr` (#20480) +- ESP32 MI BLE support for Xiaomi LYWSD02MMC (#20381) ### Breaking Changed ### Changed -- SML update (#20474) ### Fixed - Scripter memory leak in `>w x` (#20473) - ESP8266 GPIO Viewer exception 9 on reading Analog GPIO - GPIO Viewer single instance -- Fix random crash in Zigbee main page +- Zigbee ramdom crash in main page (#20481) +- Web file upload response on upload error (#20340) ### Removed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 965134b73..054ec73d3 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -127,8 +127,10 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Support negative power on BL0942 using index 5..8 [#20322](https://github.com/arendst/Tasmota/issues/20322) - Support for pipsolar inverter [#20408](https://github.com/arendst/Tasmota/issues/20408) - Support for HardwareSerial invert [#15461](https://github.com/arendst/Tasmota/issues/15461) +- SML support for IM350 [#20474](https://github.com/arendst/Tasmota/issues/20474) - ESP32 used UART information - ESP32 experimental support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled +- ESP32 MI BLE support for Xiaomi LYWSD02MMC [#20381](https://github.com/arendst/Tasmota/issues/20381) - Berry GPIO viewer initial version using async webserver [#20416](https://github.com/arendst/Tasmota/issues/20416) - Berry `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) - Berry support for `tcpclientasync` in `tcpserver` [#20401](https://github.com/arendst/Tasmota/issues/20401) @@ -142,6 +144,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Berry provide lightweight options for `tasmota.wifi/eth/memory/rtc` [#20448](https://github.com/arendst/Tasmota/issues/20448) - Berry `tasmota.webcolor` [#20454](https://github.com/arendst/Tasmota/issues/20454) - Berry `debug.caller` [#20470](https://github.com/arendst/Tasmota/issues/20470) +- LVGL `lv.str_arr` [#20480](https://github.com/arendst/Tasmota/issues/20480) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) - HASPmota type `chart` [#20372](https://github.com/arendst/Tasmota/issues/20372) - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) @@ -155,15 +158,16 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - ESP32 platform update from 2023.11.01 to 2024.01.00 [#20445](https://github.com/arendst/Tasmota/issues/20445) - Renamed button "Consoles" to "Tools" - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` [#20260](https://github.com/arendst/Tasmota/issues/20260) +- Web file upload response on upload error [#20340](https://github.com/arendst/Tasmota/issues/20340) - Header `Host` is now collected by Webserver [#20446](https://github.com/arendst/Tasmota/issues/20446) - Webcam tweaks [#20451](https://github.com/arendst/Tasmota/issues/20451) -- SML update [#20474](https://github.com/arendst/Tasmota/issues/20474) ### Fixed - CVE-2021-36603 Cross Site Scripting (XSS) vulnerability [#12221](https://github.com/arendst/Tasmota/issues/12221) - Syslog server warning caused by lack of field and hostname starting with 'z' [#14689](https://github.com/arendst/Tasmota/issues/14689) - Support for Domoticz floor/room topics. Regression from v12.0.1 [#20299](https://github.com/arendst/Tasmota/issues/20299) - Scripter memory leak in `>w x` (#20473)[#20473](https://github.com/arendst/Tasmota/issues/20473) +- Zigbee ramdom crash in main page (#20481)[#20473](https://github.com/arendst/Tasmota/issues/20481) - ESP32 piezo ceramic buzzer doesn't buzz [#20118](https://github.com/arendst/Tasmota/issues/20118) - ESP32 Zigbee Aqara attributes [#20452](https://github.com/arendst/Tasmota/issues/20452) - LVGL fix type for lv_imgbtn [#20354](https://github.com/arendst/Tasmota/issues/20354) From 9fc47b7d908ab6e946ce784b0e7115f27a300c12 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 13 Jan 2024 15:16:34 +0100 Subject: [PATCH 137/303] Tune GPIOViewer --- tasmota/html_compressed/HTTP_GV_PAGE.h | 31 ++++++++ tasmota/html_uncompressed/HTTP_GV_PAGE.h | 33 +++++++++ .../xdrv_121_gpioviewer.ino | 73 +++++++------------ .../tasmota_xsns_sensor/xsns_02_analog.ino | 9 ++- 4 files changed, 97 insertions(+), 49 deletions(-) create mode 100644 tasmota/html_compressed/HTTP_GV_PAGE.h create mode 100644 tasmota/html_uncompressed/HTTP_GV_PAGE.h diff --git a/tasmota/html_compressed/HTTP_GV_PAGE.h b/tasmota/html_compressed/HTTP_GV_PAGE.h new file mode 100644 index 000000000..8c0574ecb --- /dev/null +++ b/tasmota/html_compressed/HTTP_GV_PAGE.h @@ -0,0 +1,31 @@ +///////////////////////////////////////////////////////////////////// +// compressed by tools/unishox/compress-html-uncompressed.py +///////////////////////////////////////////////////////////////////// + +const size_t HTTP_GV_PAGE_SIZE = 806; +const char HTTP_GV_PAGE_COMPRESSED[] PROGMEM = "\x3D\x0F\xE1\x10\x98\x1D\x19\x0C\x64\x88\x51\x51\x0D\x20\x8F\xC3\xD0\x55\x0D\x08" + "\xFC\x3D\x05\x3B\x10\xFC\x3D\x2B\x68\x26\x7E\x1F\x5E\x47\x5A\x21\xE2\x18\x5A\x58" + "\x88\xCF\x58\xFB\xF9\xE8\x76\x02\x0D\x43\xD0\x75\xF9\xA1\x5F\x66\x0F\x87\xD9\xF5" + "\xE3\xEC\xFC\x3D\x02\xDE\x34\x5A\x21\xF0\xFB\x11\x98\xB1\x61\x51\x7A\x8C\x82\x65" + "\xE1\x4D\xD1\xF6\xBE\xC2\x3E\x1F\x7E\xA3\x20\x9F\x81\x06\x68\x20\xE2\x80\x8F\x89" + "\x0E\xCB\xF8\x80\xC1\xB1\x0F\xB0\x8F\x87\xDE\x87\x9C\x08\x75\x4C\x59\x9E\x87\x9C" + "\x74\xD0\xF0\xFB\x54\x64\x31\x9F\x0F\xBD\x1B\x63\xCC\xEC\x36\x1D\x7A\x1E\x71\xF6" + "\x7E\x1E\x9E\x0F\xFA\x32\x97\xBE\x19\xF0\xFB\x04\x19\x07\x60\xFB\x1C\x5E\xC0\xCD" + "\x1D\x1D\x0D\x7E\x3E\xCF\xC3\xD0\xEC\x04\x1A\x60\xA1\x83\x82\x0E\xFA\x3F\xB4\x18" + "\xA7\xF0\x50\xC2\xCF\xC3\x3B\xFA\xF3\xF9\x9B\xF9\x0C\xCF\xD1\xF0\xFA\x10\xF0\x67" + "\x7F\x5A\x30\xF8\x7D\x9F\x5E\x3E\xCF\x06\x77\xF5\xEC\x17\xF0\xD9\xF3\x98\xFA\x26" + "\x66\xFA\x8B\xD8\x2F\xE1\xB3\xBA\x7D\x8A\xAA\x18\x79\x9D\x87\x61\xF5\xE3\xCC\xFA" + "\x10\xEC\x66\x6F\xAB\xC7\xD9\xDE\x04\x1C\x3A\xC6\x8C\x0B\x78\x78\xFD\xEF\x53\xF9" + "\x9D\x84\x7C\x3E\xCF\xA1\x01\x07\x29\x19\xEF\xD8\xD2\xF6\x9B\x59\xF0\xFB\x3E\x84" + "\x44\x68\x43\x81\x06\x91\x8F\xB6\x5E\x34\x74\x18\xA2\xF0\xCB\x0C\x11\x6C\x02\x2F" + "\x01\x47\x60\x20\xF2\x78\x3B\x04\x32\x3F\x0F\x41\x34\xCD\x06\x15\xFB\xC7\xC3\xEC" + "\x7B\xFA\x21\xD6\x1E\x75\x5E\xF3\xF9\xF6\x08\x36\x34\x43\xE1\xF6\x35\xFB\xD6\x3C" + "\xC8\x76\x1B\x0F\xB0\x43\xC2\x01\x0A\x79\xD6\x3B\x0D\x88\x56\x88\x23\xE3\xEC\xFC" + "\x3D\x0E\xC1\x34\xCC\x10\x79\x9A\x7F\x04\x3C\x14\x10\x65\x1F\x60\x85\xA9\x3F\x82" + "\x46\x9D\xA3\x6C\x79\x82\x86\x9F\xA3\x6C\x79\x90\xFF\xEC\x60\xC7\xF0\x44\xD4\x41" + "\x07\x0B\x1F\x04\x2A\x2B\x47\xE1\xE9\xA3\x47\x81\x17\x99\x82\xD1\xB6\x3C\xCF\xB0" + "\x41\xE4\x3C\xFB\x56\x15\x1F\x0F\xB2\x1D\x97\xF1\x10\x20\xD5\x04\x6C\xDF\x84\xD0" + "\xEE\xB3\xFE\x04\x4E\x03\xC1\x06\x10\x23\xC8\x3B\x01\x07\x87\xA3\xB0\x55\x0D\x08" + "\xFC"; + +#define HTTP_GV_PAGE Decompress(HTTP_GV_PAGE_COMPRESSED,HTTP_GV_PAGE_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_uncompressed/HTTP_GV_PAGE.h b/tasmota/html_uncompressed/HTTP_GV_PAGE.h new file mode 100644 index 000000000..4b95ab8bb --- /dev/null +++ b/tasmota/html_uncompressed/HTTP_GV_PAGE.h @@ -0,0 +1,33 @@ +const char HTTP_GV_PAGE[] PROGMEM = + "" + "" + "" + "%s - GPIO Viewer" // SettingsTextEscaped(SET_DEVICENAME).c_str() + "" // GV_BASE_URL + "" + "" + "" + "" + "" + "" + "" + "" + "
" + "" + "
" + "
" + "
" + "Board Image" + "
" + "
" + "
" + "
" + "" + ""; \ No newline at end of file diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 2685acfe9..1ea345d95 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -29,57 +29,27 @@ //#define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" #ifdef ESP8266 #ifndef GV_BASE_URL -#undef GV_BASE_URL // Fix compiler warning +#undef GV_BASE_URL // Fix compiler warning #define GV_BASE_URL "https://ota.tasmota.com/tasmota/gpio_viewer/assets/" #endif #endif // ESP8266 #ifdef ESP32 #ifndef GV_BASE_URL -#undef GV_BASE_URL // Fix compiler warning +#undef GV_BASE_URL // Fix compiler warning #define GV_BASE_URL "https://ota.tasmota.com/tasmota32/gpio_viewer/assets/" #endif #endif // ESP32 const char *GVRelease = "1.0.7"; -const char HTTP_GV_PAGE[] PROGMEM = - "" - "" - "" - "%s - GPIO Viewer" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "
" - "" - "
" - // Image - "
" - "
" - "Board Image" - "
" - "
" - "
" - "
" - "" - ""; +#ifdef USE_UNISHOX_COMPRESSION + #include "./html_compressed/HTTP_GV_PAGE.h" +#else + #include "./html_uncompressed/HTTP_GV_PAGE.h" +#endif const char HTTP_GV_EVENT[] PROGMEM = + // Set CORS headers for global responses "HTTP/1.1 200 OK\n" "Content-Type: text/event-stream;\n" "Connection: keep-alive\n" @@ -121,9 +91,9 @@ void GVBegin(void) { GV.WebServer = new ESP8266WebServer(GV_PORT); // Set CORS headers for global responses - GV.WebServer->sendHeader("Access-Control-Allow-Origin", "*"); - GV.WebServer->sendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); - GV.WebServer->sendHeader("Access-Control-Allow-Headers", "Content-Type"); +// GV.WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*")); +// GV.WebServer->sendHeader(F("Access-Control-Allow-Methods"), F("GET, POST, OPTIONS")); +// GV.WebServer->sendHeader(F("Access-Control-Allow-Headers"), F("Content-Type")); GV.WebServer->on("/", GVHandleRoot); GV.WebServer->on("/release", GVHandleRelease); GV.WebServer->on("/free_psram", GVHandleFreePSRam); @@ -138,11 +108,15 @@ void GVHandleRoot(void) { char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, SettingsTextEscaped(SET_DEVICENAME).c_str(), + GV_BASE_URL, + GV_PORT, WiFi.localIP().toString().c_str(), - WiFi.localIP().toString().c_str(), + WiFi.localIP().toString().c_str(), GV_PORT, GV.sampling, #ifdef ESP32 ESP.getPsramSize() / 1024, +#else + 0, #endif // ESP32 ESP_getFreeSketchSpace() / 1024); if (content == nullptr) { return; } // Avoid crash @@ -185,12 +159,12 @@ void GVEventDisconnected(void) { if (GV.sse_ready) { AddLog(LOG_LEVEL_DEBUG, PSTR("IOV: Disconnected")); } - GV.sse_ready = false; // This just stops the event to be restarted by opening root page again + GV.sse_ready = false; // This just stops the event to be restarted by opening root page again GV.ticker.detach(); } void GVCloseEvent(void) { - GVEventSend("{}", "close", millis()); // Closes window + GVEventSend("{}", "close", millis()); // Closes web page GVEventDisconnected(); } @@ -229,7 +203,7 @@ void GVMonitorTask(void) { if (pwm_resolution > 0) { pintype = GV_PWMPin; originalValue = ledcRead2(pin); - currentState = changeUIntScale(originalValue, 0, pwm_resolution, 0, 255); // bring back to 0..255 + currentState = changeUIntScale(originalValue, 0, pwm_resolution, 0, 255); // Bring back to 0..255 } #endif // ESP32 @@ -239,7 +213,7 @@ void GVMonitorTask(void) { if (pwm_value > -1) { pintype = GV_PWMPin; originalValue = pwm_value; - currentState = changeUIntScale(originalValue, 0, Settings->pwm_range, 0, 255); // bring back to 0..255 + currentState = changeUIntScale(originalValue, 0, Settings->pwm_range, 0, 255); // Bring back to 0..255 } #endif // ESP8266 @@ -251,12 +225,12 @@ void GVMonitorTask(void) { originalValue = AdcRead(pin, 2); #endif // ESP32 #ifdef ESP8266 - // Fix exception 9 if using ticker - GV.sampling != 100 (CallChain: (phy)pm_wakeup_init, (adc)test_tout, ets_timer_arm_new, delay, AdcRead, String6concat, MonitorTask) + // Fix exception 9 if using ticker - GV.sampling != 100 caused by delay(1) in AdcRead() (CallChain: (phy)pm_wakeup_init, (adc)test_tout, ets_timer_arm_new, delay, AdcRead, String6concat, MonitorTask) originalValue = (GV.sampling != 100) ? analogRead(pin) : AdcRead(pin, 1); #endif // ESP8266 */ originalValue = AdcRead1(pin); - currentState = changeUIntScale(originalValue, 0, AdcRange(), 0, 255); // bring back to 0..255 + currentState = changeUIntScale(originalValue, 0, AdcRange(), 0, 255); // Bring back to 0..255 } else { // Read digital GPIO @@ -284,6 +258,7 @@ void GVMonitorTask(void) { uint32_t heap = ESP_getFreeHeap(); if (heap != GV.freeHeap) { + // Send freeHeap GV.freeHeap = heap; char temp[20]; snprintf_P(temp, sizeof(temp), PSTR("%d KB"), heap / 1024); @@ -293,6 +268,7 @@ void GVMonitorTask(void) { #ifdef ESP32 if (UsePSRAM()) { + // Send freePsram uint32_t psram = ESP.getFreePsram(); if (psram != GV.freePSRAM) { GV.freePSRAM = psram; @@ -305,6 +281,7 @@ void GVMonitorTask(void) { #endif // ESP32 if (!hasChanges) { + // Send freeHeap as keepAlive uint32_t last_sent = millis() - GV.lastSentWithNoActivity; if (last_sent > GV_KEEP_ALIVE) { // No activity, resending for pulse diff --git a/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino b/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino index 7c4d4c75e..c60b4e885 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_02_analog.ino @@ -356,10 +356,17 @@ uint16_t AdcRead(uint32_t pin, uint32_t factor) { uint32_t samples = 1 << factor; uint32_t analog = 0; for (uint32_t i = 0; i < samples; i++) { - analog += AdcRead1(pin); +#ifdef ESP32 + analog += analogReadMilliVolts(pin); // get the value corrected by calibrated values from the eFuses +#else + analog += analogRead(pin); +#endif delay(1); } analog >>= factor; +#ifdef ESP32 + analog = analog/(ANALOG_V33*1000) * ANALOG_RANGE; // go back from mV to ADC +#endif return analog; } From 1854b9a0694bb9f2ce6c9097312cf7d46e293409 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 13 Jan 2024 16:11:40 +0100 Subject: [PATCH 138/303] Free some more bytes from GPIOViewer --- .../xdrv_121_gpioviewer.ino | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 1ea345d95..079438c57 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -18,24 +18,24 @@ #define XDRV_121 121 #ifndef GV_PORT -#define GV_PORT 5557 +#define GV_PORT 5557 // SSE webserver port #endif #ifndef GV_SAMPLING_INTERVAL -#define GV_SAMPLING_INTERVAL 100 // [GvSampling] milliseconds - Use Tasmota Scheduler (100) or Ticker (20..99,101..1000) +#define GV_SAMPLING_INTERVAL 100 // [GvSampling] milliseconds - Use Tasmota Scheduler (100) or Ticker (20..99,101..1000) #endif -#define GV_KEEP_ALIVE 1000 // milliseconds - If no activity after this do a heap size event anyway +#define GV_KEEP_ALIVE 1000 // milliseconds - If no activity after this do a heap size event anyway //#define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" #ifdef ESP8266 #ifndef GV_BASE_URL -#undef GV_BASE_URL // Fix compiler warning +#undef GV_BASE_URL // Fix compiler warning #define GV_BASE_URL "https://ota.tasmota.com/tasmota/gpio_viewer/assets/" #endif #endif // ESP8266 #ifdef ESP32 #ifndef GV_BASE_URL -#undef GV_BASE_URL // Fix compiler warning +#undef GV_BASE_URL // Fix compiler warning #define GV_BASE_URL "https://ota.tasmota.com/tasmota32/gpio_viewer/assets/" #endif #endif // ESP32 @@ -49,12 +49,11 @@ const char *GVRelease = "1.0.7"; #endif const char HTTP_GV_EVENT[] PROGMEM = - // Set CORS headers for global responses "HTTP/1.1 200 OK\n" - "Content-Type: text/event-stream;\n" - "Connection: keep-alive\n" - "Cache-Control: no-cache\n" - "Access-Control-Allow-Origin: *\n\n"; + "Content-Type: text/event-stream;\n" // Server Sent Event protocol + "Connection: keep-alive\n" // Permanent connection + "Cache-Control: no-cache\n" // Do not store data into local cache + "Access-Control-Allow-Origin: *\n\n"; // Enable CORS enum GVPinTypes { GV_DigitalPin = 0, @@ -119,7 +118,7 @@ void GVHandleRoot(void) { 0, #endif // ESP32 ESP_getFreeSketchSpace() / 1024); - if (content == nullptr) { return; } // Avoid crash + if (content == nullptr) { return; } // Avoid crash GV.WebServer->send_P(200, "text/html", content); free(content); } @@ -172,8 +171,8 @@ void GVCloseEvent(void) { void GVEventSend(const char *message, const char *event, uint32_t id) { if (GV.WebClient.connected()) { // generateEventMessage() in AsyncEventSource.cpp -// GV.WebClient.printf_P(PSTR("retry: 0\r\nid: %u\r\nevent: %s\r\ndata: %s\r\n\r\n"), id, event, message); - GV.WebClient.printf_P(PSTR("id: %u\r\nevent: %s\r\ndata: %s\r\n\r\n"), id, event, message); +// GV.WebClient.printf_P(PSTR("retry:0\nid:%u\nevent:%s\ndata:%s\n\n"), id, event, message); + GV.WebClient.printf_P(PSTR("id:%u\nevent:%s\ndata:%s\n\n"), id, event, message); } else { GVEventDisconnected(); } @@ -299,7 +298,7 @@ void GVMonitorTask(void) { * Commands \*********************************************************************************************/ -const char kGVCommands[] PROGMEM = "GV|" // Prefix +const char kGVCommands[] PROGMEM = "GV|" // Prefix "Viewer|Sampling"; void (* const GVCommand[])(void) PROGMEM = { @@ -313,13 +312,13 @@ void CmndGvViewer(void) { */ if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { uint32_t state = XdrvMailbox.payload; - if (2 == state) { // Toggle + if (2 == state) { // Toggle state = GV.active ^1; } - if (state) { // On + if (state) { // On GVBegin(); - } else { // Off - GVCloseEvent(); // Stop current updates + } else { // Off + GVCloseEvent(); // Stop current updates GVStop(); } } @@ -335,8 +334,8 @@ void CmndGvSampling(void) { GvSampling 20 .. 1000 - Set sampling interval */ if ((XdrvMailbox.payload >= 20) && (XdrvMailbox.payload <= 1000)) { - GVCloseEvent(); // Stop current updates - GV.sampling = XdrvMailbox.payload; // 20 - 1000 milliseconds + GVCloseEvent(); // Stop current updates + GV.sampling = XdrvMailbox.payload; // 20 - 1000 milliseconds } ResponseCmndNumber(GV.sampling); } From 25cadcbbdca6cc1d4f49b40369923b0a31e86857 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 13 Jan 2024 22:13:27 +0100 Subject: [PATCH 139/303] Prefer using default GPIOViewer board repository --- tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 079438c57..5050d5cb6 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -26,19 +26,23 @@ #define GV_KEEP_ALIVE 1000 // milliseconds - If no activity after this do a heap size event anyway -//#define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" +#ifndef GV_BASE_URL +#define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" +#endif +/* #ifdef ESP8266 #ifndef GV_BASE_URL #undef GV_BASE_URL // Fix compiler warning -#define GV_BASE_URL "https://ota.tasmota.com/tasmota/gpio_viewer/assets/" +#define GV_BASE_URL "https://ota.tasmota.com/tasmota/gpio_viewer/assets/" #endif #endif // ESP8266 #ifdef ESP32 #ifndef GV_BASE_URL #undef GV_BASE_URL // Fix compiler warning -#define GV_BASE_URL "https://ota.tasmota.com/tasmota32/gpio_viewer/assets/" +#define GV_BASE_URL "https://ota.tasmota.com/tasmota32/gpio_viewer/assets/" #endif #endif // ESP32 +*/ const char *GVRelease = "1.0.7"; @@ -171,7 +175,7 @@ void GVCloseEvent(void) { void GVEventSend(const char *message, const char *event, uint32_t id) { if (GV.WebClient.connected()) { // generateEventMessage() in AsyncEventSource.cpp -// GV.WebClient.printf_P(PSTR("retry:0\nid:%u\nevent:%s\ndata:%s\n\n"), id, event, message); +// GV.WebClient.printf_P(PSTR("retry:1000\nid:%u\nevent:%s\ndata:%s\n\n"), id, event, message); GV.WebClient.printf_P(PSTR("id:%u\nevent:%s\ndata:%s\n\n"), id, event, message); } else { GVEventDisconnected(); From be54104676dd6c8f00c9f5b6a5a58bf9959831cd Mon Sep 17 00:00:00 2001 From: Christian Baars Date: Sun, 14 Jan 2024 11:31:04 +0100 Subject: [PATCH 140/303] add remote_addr and _port to info() (#20485) --- tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino index eafd5e8df..3e2812c29 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino @@ -506,6 +506,8 @@ extern "C" { be_map_insert_int(vm, "local_port", tcp->local_port); be_map_insert_str(vm, "local_addr", tcp->local_addr.toString().c_str()); } + be_map_insert_int(vm, "remote_port", tcp->remotePort()); + be_map_insert_str(vm, "remote_addr", tcp->remoteIP().toString().c_str()); } be_pop(vm, 1); be_return(vm); From f14ee6415b7f380d7facee1f9f9840a787361d27 Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Sun, 14 Jan 2024 17:39:15 +0100 Subject: [PATCH 141/303] [EQ3-TRV] View some values in WebUI (#20487) * [EQ3-TRV] View some values in WebUI - View some values in WebUI - code cleanup * [EQ3-TRV] Remove lines --- tasmota/language/af_AF.h | 2 +- tasmota/language/bg_BG.h | 2 +- tasmota/language/ca_AD.h | 2 +- tasmota/language/cs_CZ.h | 2 +- tasmota/language/de_DE.h | 2 +- tasmota/language/el_GR.h | 2 +- tasmota/language/en_GB.h | 2 +- tasmota/language/es_ES.h | 2 +- tasmota/language/fr_FR.h | 2 +- tasmota/language/fy_NL.h | 2 +- tasmota/language/he_HE.h | 2 +- tasmota/language/hu_HU.h | 2 +- tasmota/language/it_IT.h | 2 +- tasmota/language/ko_KO.h | 2 +- tasmota/language/nl_NL.h | 2 +- tasmota/language/pl_PL.h | 2 +- tasmota/language/pt_BR.h | 2 +- tasmota/language/pt_PT.h | 2 +- tasmota/language/ro_RO.h | 2 +- tasmota/language/ru_RU.h | 2 +- tasmota/language/sk_SK.h | 2 +- tasmota/language/sv_SE.h | 2 +- tasmota/language/tr_TR.h | 2 +- tasmota/language/uk_UA.h | 2 +- tasmota/language/vi_VN.h | 2 +- tasmota/language/zh_CN.h | 2 +- tasmota/language/zh_TW.h | 2 +- .../xdrv_85_esp32_ble_eq3_trv.ino | 178 ++++++++++-------- 28 files changed, 125 insertions(+), 107 deletions(-) diff --git a/tasmota/language/af_AF.h b/tasmota/language/af_AF.h index 94dde999d..a0b81d637 100644 --- a/tasmota/language/af_AF.h +++ b/tasmota/language/af_AF.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Invoer" #define D_DEVICE_OUTPUT "Uitvoer" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index 03a62678e..eb460a30e 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Вход" #define D_DEVICE_OUTPUT "Изход" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/ca_AD.h b/tasmota/language/ca_AD.h index cc50a3eec..ab32cab34 100644 --- a/tasmota/language/ca_AD.h +++ b/tasmota/language/ca_AD.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Input" #define D_DEVICE_OUTPUT "Output" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index 0ec5c815a..99b050e9d 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Input" #define D_DEVICE_OUTPUT "Output" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index 2ca6a99c6..f19c601bc 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Eingang" #define D_DEVICE_OUTPUT "Ausgang" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Solltemperatur" #define D_THERMOSTAT_SENSOR "Aktuelle Temperatur" diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h index e75f90599..3355065af 100644 --- a/tasmota/language/el_GR.h +++ b/tasmota/language/el_GR.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Input" #define D_DEVICE_OUTPUT "Output" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index f7b69de42..6748ed35f 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Input" #define D_DEVICE_OUTPUT "Output" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h index 02f02e6cf..e6582e91a 100644 --- a/tasmota/language/es_ES.h +++ b/tasmota/language/es_ES.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Entrada" #define D_DEVICE_OUTPUT "Salida" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index fa46c2866..608e7fbaa 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Entrée" #define D_DEVICE_OUTPUT "Sortie" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/fy_NL.h b/tasmota/language/fy_NL.h index 702ca0f03..86c47c27a 100644 --- a/tasmota/language/fy_NL.h +++ b/tasmota/language/fy_NL.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Yngong" #define D_DEVICE_OUTPUT "Útgong" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index 0a6c1124e..f0ae6001c 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Input" #define D_DEVICE_OUTPUT "Output" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index 50d0195bc..176dddc0b 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Bemenet" #define D_DEVICE_OUTPUT "Kimenet" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index 602782c8a..932252c0c 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Ingresso" #define D_DEVICE_OUTPUT "Uscita" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Termostato" #define D_THERMOSTAT_SET_POINT "Temperatura impostata" #define D_THERMOSTAT_SENSOR "Temperatura attuale" diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index 0cdda28dc..c3248c9f5 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "입력" #define D_DEVICE_OUTPUT "출력" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index de431c6cb..48ff12599 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Ingang" #define D_DEVICE_OUTPUT "Uitgang" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h index b6b9f1415..12ce56032 100644 --- a/tasmota/language/pl_PL.h +++ b/tasmota/language/pl_PL.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Wejście" #define D_DEVICE_OUTPUT "Wyjście" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index 6f18f4a03..e3d5e8694 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Entrada" #define D_DEVICE_OUTPUT "Saída" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index 66dff8468..f396d366f 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Entrada" #define D_DEVICE_OUTPUT "Saída" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index 01abbb59f..9d05f17b2 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Intrare" #define D_DEVICE_OUTPUT "Ieșire" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h index 737939754..bc2598952 100644 --- a/tasmota/language/ru_RU.h +++ b/tasmota/language/ru_RU.h @@ -549,7 +549,7 @@ #define D_DEVICE_INPUT "Вход" #define D_DEVICE_OUTPUT "Выход" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index bc996bdba..256feff7e 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Input" #define D_DEVICE_OUTPUT "Output" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index 80cb7d9db..3c1445193 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Input" #define D_DEVICE_OUTPUT "Output" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index 642a4c236..fd15dd5f4 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Input" #define D_DEVICE_OUTPUT "Output" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index c54fc3e02..bda176a23 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Input" #define D_DEVICE_OUTPUT "Output" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h index bf1518f35..27924e49d 100644 --- a/tasmota/language/vi_VN.h +++ b/tasmota/language/vi_VN.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Đầu vào" #define D_DEVICE_OUTPUT "Đầu ra" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index 3e881da35..5064d894c 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "Input" #define D_DEVICE_OUTPUT "Output" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index 7777b7177..4137357a1 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -548,7 +548,7 @@ #define D_DEVICE_INPUT "輸入" #define D_DEVICE_OUTPUT "輸出" -// xdrv_39_thermostat.ino +// xdrv_39_thermostat.ino, xdrv_85_esp32_ble_eq3_trv.ino #define D_THERMOSTAT "Thermostat" #define D_THERMOSTAT_SET_POINT "Set Point Temperature" #define D_THERMOSTAT_SENSOR "Current Temperature" diff --git a/tasmota/tasmota_xdrv_driver/xdrv_85_esp32_ble_eq3_trv.ino b/tasmota/tasmota_xdrv_driver/xdrv_85_esp32_ble_eq3_trv.ino index 87883192c..978dcab58 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_85_esp32_ble_eq3_trv.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_85_esp32_ble_eq3_trv.ino @@ -19,13 +19,13 @@ -------------------------------------------------------------------------------------------- Version yyyymmdd Action Description -------------------------------------------------------------------------------------------- + 1.0.1.0 20240113 publish - Add some values to WebUI; code cleanup 1.0.0.0 20210910 publish - renamed to xdrv_85, and checked with TAS latest dev branch 0.0.0.0 20201213 created - initial version */ /* - Commands: e.g. trv 001A22092EE0 settemp 22.5 @@ -118,12 +118,8 @@ pin.append(x) x = str((ord(serialno[0]) - ord('A') ^ ord(serialno[6]) - ord('0')) % 10) pin.append(x) print("".join(pin)) - */ - - - //#define VSCODE_DEV #ifdef VSCODE_DEV @@ -172,7 +168,6 @@ void (*const EQ3_Commands[])(void) PROGMEM = { &CmndTrvHideFailedPoll }; - const char *cmdnames[] = { "poll", "raw", @@ -219,6 +214,9 @@ struct eq3_device_tag{ uint8_t lastStatusLen; uint32_t lastStatusTime; // in utc uint8_t nextDiscoveryData; + float TargetTemp; + uint8_t DutyCycle; + bool Battery; } eq3_device_t; /*********************************************************************************************\ @@ -300,8 +298,6 @@ char *topicPrefix(int prefix, const uint8_t *addr, int useAlias){ return stopic; } - - // return 0+ if we find the addr has one of our listed prefixes // return -1 if we don't recognise the mac int matchPrefix(const uint8_t *addr){ @@ -313,19 +309,18 @@ int matchPrefix(const uint8_t *addr){ return -1; } - bool EQ3Operation(const uint8_t *MAC, const uint8_t *data, int datalen, int cmdtype, int retries_in = 0) { BLE_ESP32::generic_sensor_t *op = nullptr; // ALWAYS use this function to create a new one. int res = BLE_ESP32::newOperation(&op); if (!res){ - AddLog(LOG_LEVEL_ERROR,PSTR("EQ3 %s:Can't get a newOperation from BLE"), addrStr(MAC, cmdtype & 0x80)); + AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: %s: Can't get a newOperation from BLE"), addrStr(MAC, cmdtype & 0x80)); retries = 0; return 0; } else { #ifdef EQ3_DEBUG - AddLog(LOG_LEVEL_DEBUG,PSTR("EQ3 %s:got a newOperation from BLE"), addrStr(MAC, cmdtype & 0x80)); + AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: %s: Got a newOperation from BLE"), addrStr(MAC, cmdtype & 0x80)); #endif } @@ -354,7 +349,7 @@ bool EQ3Operation(const uint8_t *MAC, const uint8_t *data, int datalen, int cmdt if (!res){ // if it fails to add to the queue, do please delete it BLE_ESP32::freeOperation(&op); - AddLog(LOG_LEVEL_ERROR,PSTR("EQ3 %s:Failed to queue new operation - deleted"), addrStr(MAC, cmdtype & 0x80)); + AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: %s: Failed to queue new operation - deleted"), addrStr(MAC, cmdtype & 0x80)); retries = 0; } else { if (retries_in){ @@ -372,11 +367,11 @@ int EQ3DoOp(){ if (EQ3Operation(op->addr, op->towrite, op->writelen, op->cmdtype, EQ3Retries)){ opQueue.pop_front(); opInProgress = 1; - AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3 %s:Op dequeued len now %d"), addrStr(op->addr, (op->cmdtype & 0x80)), opQueue.size()); + AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: %s: Op dequeued len now %d"), addrStr(op->addr, (op->cmdtype & 0x80)), opQueue.size()); delete op; return 1; } else { - AddLog(LOG_LEVEL_ERROR, PSTR("EQ3 %s:Op BLE could not start op queue len %d"), addrStr(op->addr, (op->cmdtype & 0x80)), opQueue.size()); + AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: %s: Op BLE could not start op queue len %d"), addrStr(op->addr, (op->cmdtype & 0x80)), opQueue.size()); } } } @@ -391,7 +386,7 @@ int EQ3QueueOp(const uint8_t *MAC, const uint8_t *data, int datalen, int cmdtype newop->cmdtype = cmdtype | (useAlias?0x80:0); opQueue.push_back(newop); int qlen = opQueue.size(); - AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3 %s: Op queued len now %d"), addrStr(newop->addr, (newop->cmdtype & 0x80)), qlen); + AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: %s: Op queued len now %d"), addrStr(newop->addr, (newop->cmdtype & 0x80)), qlen); EQ3DoOp(); return qlen; } @@ -461,10 +456,12 @@ int EQ3ParseOp(BLE_ESP32::generic_sensor_t *op, bool success, int retries){ ResponseAppend_P(PSTR(",\"RSSI\":%d"), eq3->RSSI); } - if ((statlen >= 6) && (status[0] == 2) && (status[1] == 1)){ + if ((statlen >= 6) && (status[0] == 2) && (status[1] == 1)) { ResponseAppend_P(PSTR(",\"stattime\":%u"), stattime); - ResponseAppend_P(PSTR(",\"temp\":%2.1f"), ((float)status[5])/2); - ResponseAppend_P(PSTR(",\"posn\":%d"), status[3]); + eq3->TargetTemp = (float)status[5] / 2; + ResponseAppend_P(PSTR(",\"temp\":%2.1f"), eq3->TargetTemp); + eq3->DutyCycle = status[3]; + ResponseAppend_P(PSTR(",\"posn\":%d"), eq3->DutyCycle); int stat = status[2]; ResponseAppend_P(PSTR(",\"mode\":")); switch (stat & 3){ @@ -499,16 +496,17 @@ int EQ3ParseOp(BLE_ESP32::generic_sensor_t *op, bool success, int retries){ break; } while (0); - ResponseAppend_P(PSTR(",\"boost\":\"%s\""), (stat & 4)?"active":"inactive"); - ResponseAppend_P(PSTR(",\"dst\":\"%s\""), (stat & 8)?"set":"unset"); - ResponseAppend_P(PSTR(",\"window\":\"%s\""), (stat & 16)?"open":"closed"); - ResponseAppend_P(PSTR(",\"state\":\"%s\""), (stat & 32)?"locked":"unlocked"); - ResponseAppend_P(PSTR(",\"battery\":\"%s\""), (stat & 128)?"LOW":"GOOD"); + ResponseAppend_P(PSTR(",\"boost\":\"%s\""), (stat & 4) ? "active" : "inactive"); + ResponseAppend_P(PSTR(",\"dst\":\"%s\""), (stat & 8) ? "set" : "unset"); + ResponseAppend_P(PSTR(",\"window\":\"%s\""), (stat & 16) ? "open" : "closed"); + ResponseAppend_P(PSTR(",\"state\":\"%s\""), (stat & 32) ? "locked" : "unlocked"); + eq3->Battery = stat & 128; + ResponseAppend_P(PSTR(",\"battery\":\"%s\""), eq3->Battery ? "LOW" : "GOOD"); } if ((statlen >= 10) && (status[0] == 2) && (status[1] == 1)){ int mm = status[8] * 30; - int hh = mm/60; + int hh = mm / 60; mm = mm % 60; ResponseAppend_P(PSTR(",\"holidayend\":\"%02d-%02d-%02d %02d:%02d\""), status[7], @@ -518,11 +516,11 @@ int EQ3ParseOp(BLE_ESP32::generic_sensor_t *op, bool success, int retries){ ); if (statlen >= 15) { - ResponseAppend_P(PSTR(",\"windowtemp\":%2.1f"), ((float)status[10])/2); - ResponseAppend_P(PSTR(",\"windowdur\":%d"), ((int)status[11])*5); - ResponseAppend_P(PSTR(",\"day\":%2.1f"), ((float)status[12])/2); - ResponseAppend_P(PSTR(",\"night\":%2.1f"), ((float)status[13])/2); - ResponseAppend_P(PSTR(",\"offset\":%2.1f"), ((float)status[14]-7) /2); + ResponseAppend_P(PSTR(",\"windowtemp\":%2.1f"), ((float)status[10]) / 2); + ResponseAppend_P(PSTR(",\"windowdur\":%d"), ((int)status[11]) * 5); + ResponseAppend_P(PSTR(",\"day\":%2.1f"), ((float)status[12]) / 2); + ResponseAppend_P(PSTR(",\"night\":%2.1f"), ((float)status[13]) / 2); + ResponseAppend_P(PSTR(",\"offset\":%2.1f"), ((float)status[14] - 7) / 2); } } @@ -579,7 +577,7 @@ int EQ3ParseOp(BLE_ESP32::generic_sensor_t *op, bool success, int retries){ // it IS a poll command if (EQ3HideFailedPoll){ if (!success){ - AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3 %s poll fail not sent because EQ3HideFailedPoll"), addrStr(addrev)); + AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: %s: Poll fail not sent because EQ3HideFailedPoll"), addrStr(addrev)); return res; } } @@ -605,17 +603,17 @@ int EQ3GenericOpCompleteFn(BLE_ESP32::generic_sensor_t *op){ if (EQ3Operation(addrev, op->dataToWrite, op->writelen, (int)op->context)){ //EQ3ParseOp(op, false, retries); - AddLog(LOG_LEVEL_ERROR,PSTR("EQ3 %s: trv operation failed - retrying %d"), addrStr(addrev), op->state); + AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: %s: trv operation failed - retrying %d"), addrStr(addrev), op->state); opInProgress = 1; } else { retries = 0; EQ3ParseOp(op, false, 0); - AddLog(LOG_LEVEL_ERROR,PSTR("EQ3 %s: trv operation failed to send op %d"), addrStr(addrev), op->state); + AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: %s: trv operation failed to send op %d"), addrStr(addrev), op->state); } } else { retries = 0; EQ3ParseOp(op, false, 0); - AddLog(LOG_LEVEL_ERROR,PSTR("EQ3 %s: trv operation failed - no more retries %d"), addrStr(addrev), op->state); + AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: %s: trv operation failed - no more retries %d"), addrStr(addrev), op->state); } return 0; } @@ -636,12 +634,12 @@ int ispairing2(const uint8_t *payload, int len, char *name, int namelen, char *s while (len){ int l = *payload; //BLE_ESP32::dump(temp, 40, payload, l+1); - //AddLog(LOG_LEVEL_ERROR,PSTR("EQ3: %s"), temp); + //AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: %s"), temp); payload++; len--; if (len < l){ - //AddLog(LOG_LEVEL_ERROR,PSTR("EQ3: part len er %d<%d"),len, l); + //AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: part len er %d<%d"),len, l); return 0; } switch (*payload){ @@ -655,7 +653,7 @@ int ispairing2(const uint8_t *payload, int len, char *name, int namelen, char *s l--; //char serialstr[20]; //strncpy(serialstr, (const char *)payload, l); - //AddLog(LOG_LEVEL_DEBUG,PSTR("EQ3: adv part FF01 detected %s"), serialstr); + //AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: adv part FF01 detected %s"), serialstr); // we don;t use these, but that's what they seem to be.... uint8_t copylen = (l > seriallen)?seriallen:l; strncpy(serial, (const char *)payload, copylen); @@ -678,7 +676,7 @@ int ispairing2(const uint8_t *payload, int len, char *name, int namelen, char *s l--; //char serialstr[20]; //strncpy(serialstr, (const char *)payload, l); - //AddLog(LOG_LEVEL_DEBUG,PSTR("EQ3: adv part FF01 detected %s"), serialstr); + //AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: adv part FF01 detected %s"), serialstr); // we don;t use these, but that's what they seem to be.... uint8_t copylen = (l > namelen)?namelen:l; strncpy(name, (const char *)payload, copylen); @@ -703,16 +701,16 @@ int ispairing2(const uint8_t *payload, int len, char *name, int namelen, char *s int ispairing(const uint8_t *payload, int len){ //char temp[40]; //BLE_ESP32::dump(temp, 40, payload, len); - //AddLog(LOG_LEVEL_DEBUG,PSTR("EQ3: pair%d %s"), len, temp); + //AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: pair%d %s"), len, temp); while (len){ int l = *payload; //BLE_ESP32::dump(temp, 40, payload, l+1); - //AddLog(LOG_LEVEL_ERROR,PSTR("EQ3: %s"), temp); + //AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: %s"), temp); payload++; len--; if (len < l){ - //AddLog(LOG_LEVEL_ERROR,PSTR("EQ3: part len er %d<%d"),len, l); + //AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: part len er %d<%d"),len, l); return 0; } if (*payload == 0xff){ @@ -725,7 +723,7 @@ int ispairing(const uint8_t *payload, int len){ l--; //char serialstr[20]; //strncpy(serialstr, (const char *)payload, l); - //AddLog(LOG_LEVEL_DEBUG,PSTR("EQ3: adv part FF01 detected %s"), serialstr); + //AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: adv part FF01 detected %s"), serialstr); // we don;t use these, but that's what they seem to be.... const uint8_t *serial = payload; uint8_t seriallen = l; @@ -756,13 +754,13 @@ int TaskEQ3AddDevice(int8_t RSSI, const uint8_t* addr, char *serial){ pairing = 1; } - for(i = 0; i < EQ3_NUM_DEVICESLOTS; i++){ - if(memcmp(addr,EQ3Devices[i].addr,6)==0){ + for(i = 0; i < EQ3_NUM_DEVICESLOTS; i++) { + if(!memcmp(addr, EQ3Devices[i].addr, 6)) { break; } if (EQ3Devices[i].timeoutTime && (EQ3Devices[i].timeoutTime < now)) { #ifdef EQ3_DEBUG - AddLog(LOG_LEVEL_DEBUG,PSTR("EQ3 %s timeout at %d"), addrStr(EQ3Devices[i].addr), i); + AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: %s: timeout at %d"), addrStr(EQ3Devices[i].addr), i); #endif EQ3Devices[i].timeoutTime = 0L; } @@ -777,14 +775,14 @@ int TaskEQ3AddDevice(int8_t RSSI, const uint8_t* addr, char *serial){ if (free >= 0){ i = free; } else { - AddLog(LOG_LEVEL_ERROR,PSTR("EQ3 lost %s: > %d devices"), addrStr(addr), EQ3_NUM_DEVICESLOTS); + AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: %s: lost > %d devices"), addrStr(addr), EQ3_NUM_DEVICESLOTS); return 0; } } #ifdef EQ3_DEBUG if (!EQ3Devices[i].timeoutTime) - AddLog(LOG_LEVEL_INFO,PSTR("EQ3 %s: added at %d"), addrStr(addr), i); + AddLog(LOG_LEVEL_INFO, PSTR("EQ3: %s: added at %d"), addrStr(addr), i); #endif EQ3Devices[i].timeoutTime = now + (1000L*1000L)*EQ3_TIMEOUT; @@ -844,7 +842,7 @@ int TaskEQ3advertismentCallback(BLE_ESP32::ble_advertisment_t *pStruct) if (!found) return 0; #ifdef EQ3_DEBUG - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("EQ3Device: saw %s"),advertisedDevice->getAddress().toString().c_str()); + if (BLE_ESP32::BLEDebugMode) AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: %s: saw device"),advertisedDevice->getAddress().toString().c_str()); #endif uint8_t* payload = advertisedDevice->getPayload(); @@ -861,15 +859,10 @@ int TaskEQ3advertismentCallback(BLE_ESP32::ble_advertisment_t *pStruct) return 0; } - - - /*********************************************************************************************\ * Helper functions \*********************************************************************************************/ - - /*********************************************************************************************\ * init \*********************************************************************************************/ @@ -877,7 +870,7 @@ void EQ3Init(void) { memset(&EQ3Devices, 0, sizeof(EQ3Devices)); BLE_ESP32::registerForAdvertismentCallbacks((const char *)"EQ3", TaskEQ3advertismentCallback); #ifdef EQ3_DEBUG - AddLog(LOG_LEVEL_INFO,PSTR("EQ3: init: request callbacks")); + AddLog(LOG_LEVEL_INFO, PSTR("EQ3: init: request callbacks")); #endif EQ3Period = Settings->tele_period; @@ -915,10 +908,10 @@ void EQ3EverySecond(bool restart){ if (seconds <= 0){ if (EQ3Period){ if (nextEQ3Poll >= EQ3_NUM_DEVICESLOTS){ - AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3 poll cycle starting")); + AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: poll cycle starting")); nextEQ3Poll = 0; } else { - AddLog(LOG_LEVEL_ERROR, PSTR("EQ3 poll overrun, deferred - last loop only got to %d, not %d"), nextEQ3Poll, EQ3_NUM_DEVICESLOTS); + AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: poll overrun, deferred - last loop only got to %d, not %d"), nextEQ3Poll, EQ3_NUM_DEVICESLOTS); } } seconds = EQ3Period; @@ -941,7 +934,7 @@ void EQ3EverySecond(bool restart){ // trvMinRSSI // find the device in BLE to get RSSI if (EQ3Devices[i].RSSI < trvMinRSSI){ - AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3 %s RSSI %d < min %d, poll suppressed"), addrStr(EQ3Devices[i].addr), EQ3Devices[i].RSSI, trvMinRSSI); + AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: %s: RSSI %d < min %d, poll suppressed"), addrStr(EQ3Devices[i].addr), EQ3Devices[i].RSSI, trvMinRSSI); nextEQ3Poll = i+1; continue; } @@ -960,7 +953,6 @@ void EQ3EverySecond(bool restart){ } - /*********************************************************************************************\ * Presentation \*********************************************************************************************/ @@ -996,6 +988,35 @@ int EQ3SendResult(char *requested, const char *result){ return 0; } +#ifdef USE_WEBSERVER +const char HTTP_EQ3_HL[] PROGMEM = "{s}
{m}
{e}"; +const char HTTP_EQ3_ALIAS[] PROGMEM = "{s}EQ3 %d Alias{m}%s{e}"; +const char HTTP_EQ3_MAC[] PROGMEM = "{s}EQ3 %d " D_MAC_ADDRESS "{m}%s{e}"; +const char HTTP_EQ3_RSSI[] PROGMEM = "{s}EQ3 %d " D_RSSI "{m}%d dBm{e}"; +const char HTTP_EQ3_TEMPERATURE[] PROGMEM = "{s}EQ3 %d %s{m}%*_f " D_UNIT_DEGREE "%c{e}"; +const char HTTP_EQ3_DUTY_CYCLE[] PROGMEM = "{s}EQ3 %d " D_THERMOSTAT_DUTY_CYCLE "{m}%d " D_UNIT_PERCENT "{e}"; +const char HTTP_EQ3_BATTERY[] PROGMEM = "{s}EQ3 %d " D_BATTERY "{m}%s{e}"; + +void EQ3Show(void) +{ + char c_unit = D_UNIT_CELSIUS[0]; // ToDo: Check if fahrenheit is possible -> temp_format==TEMP_CELSIUS ? D_UNIT_CELSIUS[0] : D_UNIT_FAHRENHEIT[0]; + + for (int i = 0; i < EQ3_NUM_DEVICESLOTS; i++) { + if (EQ3Devices[i].timeoutTime) { + WSContentSend_P(HTTP_EQ3_HL); + const char *alias = BLE_ESP32::getAlias(EQ3Devices[i].addr); + if (alias && *alias){ + WSContentSend_PD(HTTP_EQ3_ALIAS, i + 1, alias); + } + WSContentSend_P(HTTP_EQ3_MAC, i + 1, addrStr(EQ3Devices[i].addr)); + WSContentSend_PD(HTTP_EQ3_RSSI, i + 1, EQ3Devices[i].RSSI); + WSContentSend_PD(HTTP_EQ3_TEMPERATURE, i + 1, D_THERMOSTAT_SET_POINT, Settings->flag2.temperature_resolution, &EQ3Devices[i].TargetTemp, c_unit); + WSContentSend_P(HTTP_EQ3_DUTY_CYCLE, i + 1, EQ3Devices[i].DutyCycle); + WSContentSend_P(HTTP_EQ3_BATTERY, i + 1, EQ3Devices[i].Battery ? D_NEOPOOL_LOW : D_OK); + } + } +} +#endif // USE_WEBSERVER /*********************************************************************************************\ * Commands @@ -1023,7 +1044,7 @@ int EQ3Send(const uint8_t* addr, const char *cmd, char* param, char* param2, int memset(d, 0, sizeof(d)); int dlen = 0; #ifdef EQ3_DEBUG - AddLog(LOG_LEVEL_INFO,PSTR("EQ3 %s: cmd: [%s] [%s] [%s]"), addrStr(addr), cmd, param, param2); + AddLog(LOG_LEVEL_INFO, PSTR("EQ3: %s: cmd: [%s] [%s] [%s]"), addrStr(addr), cmd, param, param2); #endif /* done on whole string before here. @@ -1042,7 +1063,7 @@ int EQ3Send(const uint8_t* addr, const char *cmd, char* param, char* param2, int } int len = strlen(param) / 2; if (len > 20){ - AddLog(LOG_LEVEL_ERROR,PSTR("EQ3 raw len of %s = %d > 20"), param, len); + AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: raw len of %s = %d > 20"), param, len); return -1; } BLE_ESP32::fromHex(d, param, len); @@ -1380,7 +1401,7 @@ const char *responses[] = { int CmndTrvNext(int index, char *data){ - AddLog(LOG_LEVEL_DEBUG,PSTR("EQ3 cmd index: %d"), index); + AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: cmd index: %d"), index); //simpletolower(data); switch(index){ @@ -1399,14 +1420,14 @@ int CmndTrvNext(int index, char *data){ if (!strcmp(p, "scan")){ #ifdef EQ3_DEBUG - AddLog(LOG_LEVEL_DEBUG,PSTR("EQ3 cmd: %s"), p); + AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: cmd: %s"), p); #endif EQ3SendCurrentDevices(); return 0; } if (!strcmp(p, "devlist")){ #ifdef EQ3_DEBUG - AddLog(LOG_LEVEL_DEBUG,PSTR("EQ3 cmd: %s"), p); + AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: cmd: %s"), p); #endif EQ3SendCurrentDevices(); return 0; @@ -1423,16 +1444,16 @@ int CmndTrvNext(int index, char *data){ int addrres = BLE_ESP32::getAddr(addrbin, p); if (addrres){ if (addrres == 2){ - AddLog(LOG_LEVEL_DEBUG,PSTR("EQ3 addr used alias: %s"), p); + AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: addr used alias: %s"), p); useAlias = 1; } NimBLEAddress addr(addrbin, addrbin[6]); #ifdef EQ3_DEBUG - //AddLog(LOG_LEVEL_INFO,PSTR("EQ3 cmd addr: %s -> %s"), p, addr.toString().c_str()); + //AddLog(LOG_LEVEL_INFO, PSTR("EQ3: cmd addr: %s -> %s"), p, addr.toString().c_str()); #endif } else { - AddLog(LOG_LEVEL_ERROR,PSTR("EQ3 addr invalid: %s"), p); + AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: addr invalid: %s"), p); return 3; } @@ -1450,16 +1471,16 @@ int CmndTrvNext(int index, char *data){ int res = EQ3Send(addrbin, cmd, param, param2, useAlias); if (res > 0) { // succeeded to queue - AddLog(LOG_LEVEL_ERROR,PSTR("EQ3 queued")); + AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: queued")); return 1; } if (res < 0) { // invalid in some way - AddLog(LOG_LEVEL_ERROR,PSTR("EQ3 invalid")); + AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: invalid")); return 3; } - AddLog(LOG_LEVEL_ERROR,PSTR("EQ3 failed to queue")); + AddLog(LOG_LEVEL_ERROR, PSTR("EQ3: failed to queue")); // failed to queue return 4; } break; @@ -1537,7 +1558,7 @@ bool mqtt_direct(){ strncpy(stopic, XdrvMailbox.topic, TOPSZ); XdrvMailbox.topic[TOPSZ-1] = 0; - AddLog(LOG_LEVEL_DEBUG,PSTR("EQ3 mqtt: %s:%s"), stopic, XdrvMailbox.data); + AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: mqtt: %s:%s"), stopic, XdrvMailbox.data); char *items[10]; char *p = stopic; @@ -1550,22 +1571,21 @@ bool mqtt_direct(){ cnt--; // repreents the number of items if (cnt < 4){ // not for us? - //AddLog(LOG_LEVEL_INFO,PSTR("cnt: %d < 4"), cnt); + //AddLog(LOG_LEVEL_INFO, PSTR("cnt: %d < 4"), cnt); return false; } for (int i = 0; i < cnt; i++){ - //AddLog(LOG_LEVEL_INFO,PSTR("cnt %d:%s"), i, items[i]); + //AddLog(LOG_LEVEL_INFO, PSTR("cnt %d:%s"), i, items[i]); } - int EQ3index = 0; int MACindex = 0; int CMDindex = 0; if (strcasecmp_P(items[cnt-3], PSTR(EQ3_TOPIC)) != 0) { - //AddLog(LOG_LEVEL_INFO,PSTR("cnt-3 not %s"), PSTR(EQ3_TOPIC)); + //AddLog(LOG_LEVEL_INFO, PSTR("cnt-3 not %s"), PSTR(EQ3_TOPIC)); if (strcasecmp_P(items[cnt-2], PSTR(EQ3_TOPIC)) != 0) { - //AddLog(LOG_LEVEL_INFO,PSTR("cnt-2 not %s"), PSTR(EQ3_TOPIC)); + //AddLog(LOG_LEVEL_INFO, PSTR("cnt-2 not %s"), PSTR(EQ3_TOPIC)); return false; // not for us } else { EQ3index = cnt-2; @@ -1604,7 +1624,7 @@ bool mqtt_direct(){ remains = 120 - (p-tmp); *(p++) = 0; - AddLog(LOG_LEVEL_DEBUG,PSTR("EQ3:mqtt->cmdstr %s"), tmp); + AddLog(LOG_LEVEL_DEBUG, PSTR("EQ3: mqtt->cmdstr %s"), tmp); res = CmndTrvNext(1, tmp); } @@ -1744,14 +1764,11 @@ void EQ3DiscoveryOneEQ3(){ //vTaskDelay(100/ portTICK_PERIOD_MS); } } // end if hass discovery - //AddLog_P(LOG_LEVEL_DEBUG,PSTR("M32: %s: show some %d %s"),D_CMND_MI32, MI32.mqttCurrentSlot, TasmotaGlobal.mqtt_data); + //AddLog_P(LOG_LEVEL_DEBUG, PSTR("M32: %s: show some %d %s"), D_CMND_MI32, MI32.mqttCurrentSlot, TasmotaGlobal.mqtt_data); #endif //USE_HOME_ASSISTANT } - - - } // end namespace EQ3_ESP32 /*********************************************************************************************\ @@ -1776,13 +1793,14 @@ bool Xdrv85(uint32_t function) result = DecodeCommand(EQ3_ESP32::kEQ3_Commands, EQ3_ESP32::EQ3_Commands); break; case FUNC_MQTT_DATA: - //AddLog(LOG_LEVEL_INFO,PSTR("topic %s"), XdrvMailbox.topic); + //AddLog(LOG_LEVEL_INFO, PSTR("topic %s"), XdrvMailbox.topic); result = EQ3_ESP32::mqtt_direct(); break; case FUNC_JSON_APPEND: break; #ifdef USE_WEBSERVER case FUNC_WEB_SENSOR: + EQ3_ESP32::EQ3Show(); break; #endif // USE_WEBSERVER case FUNC_ACTIVE: From d5b4e962839eed99af77720796aa8b36d7e11d84 Mon Sep 17 00:00:00 2001 From: Christian Baars Date: Sun, 14 Jan 2024 22:30:56 +0100 Subject: [PATCH 142/303] Berry example - FTP server (#20494) --- tasmota/berry/drivers/ftp.be | 564 +++++++++++++++++++++++++++++++++++ 1 file changed, 564 insertions(+) create mode 100644 tasmota/berry/drivers/ftp.be diff --git a/tasmota/berry/drivers/ftp.be b/tasmota/berry/drivers/ftp.be new file mode 100644 index 000000000..7ca279d46 --- /dev/null +++ b/tasmota/berry/drivers/ftp.be @@ -0,0 +1,564 @@ +#- Simple FTP server in Berry by Christian Baars +# supports active and passive mode - but passive is preferred! +# only light error handling +-# + +class PATH # helper class to hold the current directory + var p # path components in a list + + def init() + import string + self.p = [] + end + + def set(p) + import string + import path + + if path.isdir(p) != true + return false + end + + var new = string.split(p,"/") + self.p = [] + for c:new + if c != "" + self.p.push(c) + end + end + return true + end + + def dir_up() + if size(self.p) > 0 + self.p.pop() + end + end + + def get_url() + var url = "/" + for c:self.p + if c != "" + url += f"{c}/" + end + end + return url + end +end + +class FTP : Driver + + var connection, server, client, data_server, data_client, data_ip + var dir, dir_list, dir_pos + var file, file_size, file_rename, retries, chunk_size + var binary_mode, active_ip, active_port, user_input + var data_buf, data_ptr, fast_loop, data_op + static port = 21 + static data_port = 20 # data connection in passive mode + static allow_anonymous = true # allow everything .. + static user = "user" + static password = "pass" + + def init() + self.server = tcpserver(self.port) # connection for control data + self.connection = false + self.data_ip = tasmota.wifi()['ip'] + self.dir = PATH() + self.readDir() + self.data_ptr = 0 + self.active_port = nil + tasmota.add_driver(self) + log(f"FTP: init server on port {self.port}",1) + end + + def deinit() + self.server.deinit() + self.data_server.deinit() + tasmota.remove_driver(self) + end + + def every_50ms() + if self.connection == true + self.loop() + elif self.server.hasclient() + self.client = self.server.acceptasync() + self.sendResponse("220 Welcome") + self.connection = true + self.pubClientInfo() + else + self.connection = false + end + end + + def every_second() + if self.client && self.connection != false + if self.client.connected() == false + self.pubClientInfo() + self.connection = false + self.abortDataOp() + end + end + end + + def pubClientInfo() + import mqtt + var payload = self.client.info().tostring() + mqtt.publish("FTP",format("{'server':%s}", payload)) + end + + def loop() + if self.connection == true + self.handleConnection() + end + end + + def abortDataOp() + if self.data_op == "d" + self.finishDownload(true) + elif self.data_op == "u" + self.finishUpload(true) + elif self.data_op == "dir" + self.finishUpload(false) + end + end + + def download() # ESP -> client + self.data_buf..self.file.readbytes(self.chunk_size) + if size(self.data_buf) == 0 + self.retries -= 1 + if self.retries > 0 + return + end + else + var written = self.data_client.write(self.data_buf) + self.data_buf.clear() + self.data_ptr += written + if self.data_ptr < self.file_size + self.file.seek(self.data_ptr) + if self.retries > 0 + return + end + end + end + self.finishDownload() + end + + def finishDownload(error) + self.data_client.close() + tasmota.remove_fast_loop(self.fast_loop) + self.file.close() + if error + self.sendResponse(f"426 Connection closed; transfer aborted after {self.data_ptr} bytes.") + else + self.sendResponse(f"250 download done with {self.data_ptr} bytes.") + end + self.data_op = nil + tasmota.gc() + end + + def upload() # client -> ESP + self.data_buf..self.data_client.readbytes() + + if size(self.data_buf) > 0 + self.file.write(self.data_buf) + self.data_ptr += size(self.data_buf) + self.data_buf.clear() + else + log(f"FTP: {self.retries} retries",4) + self.retries -= 1 + if self.retries > 0 + return + end + self.finishUpload() + end + end + + def finishUpload(error) + self.data_client.close() + tasmota.remove_fast_loop(self.fast_loop) + self.file.close() + if error + self.sendResponse(f"426 Connection closed; transfer after {self.data_ptr} bytes") + else + self.sendResponse(f"250 upload done with {self.data_ptr} bytes") + end + self.data_op = nil + tasmota.gc() + end + + def transferDir(mode) + import path + var sz, date, isdir + var i = self.dir_list[self.dir_pos] + var url = f"{self.dir.get_url()}{i}" + isdir = path.isdir(url) + if isdir == false + var f = open(url,"r") + sz = f.size() + f.close() + date = path.last_modified(url) + end + if self.data_client.connected() + var dir = "" + if mode == "MLSD" + if isdir + dir = "Type=dir;Perm=edlmp; " + else + date = tasmota.time_dump(date) + var y = str(date['year']) + var m = f"{date['month']:02s}" + var d = f"{date['day']:02s}" + var h = f"{date['hour']:02s}" + var min = f"{date['min']:02s}" + var sec = f"{date['sec']:02s}" + var modif =f"{y}{m}{d}{h}{min}{sec}" + dir = f"Type=file;Perm=rwd;Modify={modif};Size={sz}; " + end + elif mode == "LIST" + var d = "-" + if isdir + d = "d" + date = "" + sz = "" + else + date = tasmota.strftime("%b %d %H:%M", date) + end + dir = f"{d}rw------- 1 all all{sz:14s} {date} " + + elif mode == "NLST" + dir=self.dir.get_url() + end + var entry = f"{dir}{i}" + log(entry,4) + self.data_client.write(entry + "\r\n") + self.dir_pos += 1 + else + self.finishTransferDir(false) + end + if self.dir_pos < size(self.dir_list) + return + end + self.finishTransferDir(true) + end + + def finishTransferDir(success) + self.data_client.close() + if success + var n = size(self.dir_list) + self.sendResponse(f"226 {n} files in {self.dir.get_url()}") + else + self.sendResponse("426 Transfer aborted") + end + self.data_op = nil + tasmota.remove_fast_loop(self.fast_loop) + tasmota.gc() + end + + def readDir() + import path + self.dir_list = path.listdir(self.dir.get_url()) + end + + def openFile(name,mode) + import path + var url = f"{self.dir.get_url()}{name}" + if path.isdir(url) == true + log(f"FTP: {url} is a folder",2) + return false + end + if mode == "r" + if path.exists(url) != true + log(f"FTP: {url} not found",2) + return false + end + end + log(f"FTP: Open file {url} in {mode} mode",3) + self.file = open(f"{url}",mode) + if mode == "a" + if self.data_ptr != 0 + log(f"FTP: Appending file {url} at position {self.data_ptr}",3) + if self.data_ptr != self.file.size() + log(f"FTP: !!! resume position of {self.data_ptr} != file size of {self.file.size()} !!!",2) + end + end + end + return true + end + + def close() + self.sendResponse("221 Closing connection") + self.connection = false + end + + + def deinitConnectServer() + if self.data_server != nil + self.data_server.close() + self.data_server.deinit() + self.data_server = nil + log("FTP: Delete server for passive data connection",2) + end + end + + def initConnectServer() + if self.data_server == nil + self.data_server = tcpserver(self.data_port) + log("FTP: Start server for passive data connection",2) + end + end + + def connectActive() + self.data_client = tcpclientasync() + if self.data_client.connect(self.active_ip,self.active_port) != false + log(f"FTP: Try to connect to {self.active_ip}:{self.active_port}",3) + end + end + + def connectPassive() + if self.data_server.hasclient() + self.data_client = self.data_server.acceptasync() + end + end + + def dataconnect() + if self.data_client != nil + self.data_client.close() + self.data_client.deinit() + end + if self.active_port != nil + self.connectActive() + else + self.connectPassive() + end + if self.data_client == nil + self.sendResponse("425 Data connection failed") + return false + end + self.data_buf = bytes() + self.retries = 10 + self.chunk_size = 5760 + self.sendResponse("150 Ready for data transfer") + return true + end + + def sendResponse(resp) + self.client.write(f"{resp}\r\n") + log(f"FTP: Response: {resp}",3) + end + + def handleConnection() # main loop for incoming commands + import string + import mqtt + import path + var d = self.client.read() + if size(d) == 0 return end + var items = string.split(d," ") + var cmd = items[0] + var arg = "" + var response = "" + if size(items) > 1 + arg = string.split(items[1],'\r\n')[0] + else + cmd = string.split(cmd,'\r\n')[0] + end + + log(f"FTP: Received: {cmd} {arg}",3) + + # connect + if cmd == "USER" + if self.allow_anonymous + response = "230 accept any/anonymous user" + else + self.user_input = arg + response = "331 Password required" + end + elif cmd == "PASS" + if self.user_input == self.user && arg == self.password + response = "230 User accepted" + else + response = "530 Wrong login credentials" + mqtt.publish("FTP","{'login':'wrong credentials'}") + end + elif cmd == "AUTH" + response = f"500 Server does not support {arg}" + elif cmd == "ABOR" + self.abortDataOp() + response = f"200 Aborting" + elif cmd == "QUIT" + self.close() + #options + elif cmd == "FEAT" + self.sendResponse("211-Extensions supported:") + self.sendResponse(" MLSD") + self.sendResponse(" EPSV") + self.sendResponse(" SIZE") + # self.sendResponse(" MDTM") + self.sendResponse(" REST STREAM") + response = "211 End" + elif cmd == "OPTS" + if arg == "UTF8" + response = "200 UTF Ok" + else + response = f"500 Server does not support {arg}" + end + elif cmd == "STRU" + if arg == "F" + response = "200 F Ok" + else + response = "504 Only F (ile) is supported" + end + elif cmd == "SYST" + response = "215 UNIX" + elif cmd == "LPRT" + response = f"501 active connection with long address not supported" + elif cmd == "PORT" + var el = string.split(arg,",") + self.active_ip = f"{el[0]}.{el[1]}.{el[2]}.{el[3]}" + self.active_port = int(el[4])*256 + int(el[5]) + response = f"200 port received {self.active_ip}:{self.active_port}" + self.deinitConnectServer() + # response = f"501 active connection not supported" + elif cmd == "EPRT" + var el = string.split(arg,"|") # |1|192.168.1.54|65519| -> 1 IPV4, 2 IPV6 + self.active_ip = el[2] + self.active_port = int(el[3]) + self.deinitConnectServer() + response = f"200 extended port received {self.active_ip}:{self.active_port}" + elif cmd == "TYPE" + if arg == "I" + response = "200 binary mode" + self.binary_mode = true + elif arg == "A" + response = "200 ascii mode" + self.binary_mode = false + end + elif cmd == "EPSV" + self.active_port = nil + self.initConnectServer() + response = f"229 Entering Extended Passive Mode (|||{self.data_port}|)" + elif cmd == "PASV" + self.active_port = nil + var el = string.split(self.data_ip,".") + var hi = self.data_port >> 8 + var lo = self.data_port & 0xff + self.initConnectServer() + response = f"227 Entering passive mode ({el[0]},{el[1]},{el[2]},{el[3]},{hi},{lo})" + elif cmd == "DELE" + if path.remove(f"{self.dir.get_url()}{arg}") + response = f"250 {self.dir.get_url()}{arg} deleted" + else + response = f"550 Could not delete file {self.dir.get_url()}{arg}" + end + elif cmd == "RMD" + var url = arg + if arg[0] != "/" + url = f"{self.dir.get_url()}{arg}" + end + if path.rmdir(url) + response = f"250 {url} deleted" + else + response = f"550 Could not delete folder {url}" + end + elif cmd == "STOR" + self.dataconnect() + if self.data_client != nil + response = "" + var mode = "w" + if self.data_ptr > 0 + mode = "a" + end + if self.openFile(arg,mode) + self.data_op = "u" + self.fast_loop = /->self.upload() + tasmota.add_fast_loop(self.fast_loop) + else + response = f"550 Could not open file" + end + else + response = f"501 Could not init data connection" + end + elif cmd == "REST" + self.data_ptr = int(arg) + response = f"350 {self.data_ptr}" + elif cmd == "RNFR" + if self.openFile(arg,"r") + self.file_rename = f"{self.dir.get_url()}{arg}" + response = f"350 {arg}" + self.file.close() + else + self.file_rename = nil + response = f"550 Could not open file" + end + elif cmd == "RNTO" + if self.file_rename != nil + tasmota.cmd(f"UfsRename {self.file_rename},{self.dir.get_url()}{arg}") + response = f"250 Renamed {self.file_rename} -> {arg}" + else + response = f"550 Could not rename file" + end + self.file_rename = nil + elif cmd == "SIZE" + if self.openFile(arg,"r") + response = f"213 {self.file.size()}" + self.file.close() + else + response = f"550 Could not open file" + end + elif cmd == "RETR" + self.dataconnect() + if self.data_client != nil + if self.openFile(arg,"r") + self.file_size = self.file.size() + self.data_op = "d" + self.fast_loop = /->self.download() + tasmota.add_fast_loop(self.fast_loop) + else + response = f"550 Could not open file" + end + else + response = f"501 Could not init data connection" + end + # folder + elif cmd == "CDUP" + self.dir.dir_up() + response = "250 okay" + elif cmd == "CWD" + if self.dir.set(arg) + response = "250 okay" + else + response = "550 Failed to change directory." + end + elif cmd == "PWD" + self.readDir() + response = f"250 {self.dir.get_url()}" + elif cmd == "MKD" + path.mkdir(f"{self.dir.get_url()}{arg}") + response = f"250 {self.dir.get_url()}{arg} created" + elif cmd == "LIST" || cmd == "MLSD" || cmd == "NLST" + if arg != "" + self.dir.set(arg) + end + self.readDir() + if self.dataconnect() + if size(self.dir_list) > 0 + self.data_op = "dir" + self.dir_pos = 0 + self.fast_loop = /->self.transferDir(cmd) + tasmota.add_fast_loop(self.fast_loop) + else + self.finishTransferDir(true) + end + else + response = f"501 Could not init data connection" + end + else # any unknown command + response = "202 Command not implemented in Berry FTP" + end + + if response != "" + self.sendResponse(response) + end + end +end + +var ftp = FTP() From 8d83472c01ee161b6d52417cbf58c0a4a5cf9f10 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 14 Jan 2024 22:37:07 +0100 Subject: [PATCH 143/303] LVGL option to add `lv.keyboard` extra widget (#20496) * LVGL option to add `lv.keyboard` extra widget * Don't include keyboard by default --- CHANGELOG.md | 1 + .../generate/be_lv_c_mapping.h | 72 ++++++++++------ .../generate/be_lvgl_widgets_lib.c | 84 ++++++++++++------- .../lv_binding_berry/mapping/lv_funcs.h | 13 +++ .../lv_binding_berry/tools/convert.py | 2 +- .../lv_binding_berry/tools/preprocessor.py | 1 + tasmota/my_user_config.h | 1 + 7 files changed, 120 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21ac11038..63cbba761 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. - SML support for IM350 (#20474) - LVGL `lv.str_arr` (#20480) - ESP32 MI BLE support for Xiaomi LYWSD02MMC (#20381) +- LVGL option to add `lv.keyboard` extra widget ### Breaking Changed diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h index 44bdaf460..be71581c1 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h @@ -656,6 +656,42 @@ const be_ntv_func_def_t lv_imgbtn_func[] = { }; #endif // BE_LV_WIDGET_IMGBTN +/* `lv_keyboard` methods */ +#ifdef BE_LV_WIDGET_KEYBOARD +const be_ntv_func_def_t lv_keyboard_func[] = { + { "get_btn_text", { (const void*) &lv_keyboard_get_btn_text, "s", "(lv.lv_obj)i" } }, + { "get_map_array", { (const void*) &lv_keyboard_get_map_array, "c", "(lv.lv_obj)" } }, + { "get_mode", { (const void*) &lv_keyboard_get_mode, "i", "(lv.lv_obj)" } }, + { "get_selected_btn", { (const void*) &lv_keyboard_get_selected_btn, "i", "(lv.lv_obj)" } }, + { "get_textarea", { (const void*) &lv_keyboard_get_textarea, "lv.lv_obj", "(lv.lv_obj)" } }, + { "set_map", { (const void*) &lv_keyboard_set_map, "", "(lv.lv_obj)i(lv.str_arr)(lv.lv_btnmatrix_ctrl)" } }, + { "set_mode", { (const void*) &lv_keyboard_set_mode, "", "(lv.lv_obj)i" } }, + { "set_popovers", { (const void*) &lv_keyboard_set_popovers, "", "(lv.lv_obj)b" } }, + { "set_textarea", { (const void*) &lv_keyboard_set_textarea, "", "(lv.lv_obj)(lv.lv_obj)" } }, +}; +#endif // BE_LV_WIDGET_KEYBOARD + +/* `lv_btnmatrix` methods */ +#ifdef BE_LV_WIDGET_BTNMATRIX +const be_ntv_func_def_t lv_btnmatrix_func[] = { + { "clear_btn_ctrl", { (const void*) &lv_btnmatrix_clear_btn_ctrl, "", "(lv.lv_obj)ii" } }, + { "clear_btn_ctrl_all", { (const void*) &lv_btnmatrix_clear_btn_ctrl_all, "", "(lv.lv_obj)i" } }, + { "get_btn_text", { (const void*) &lv_btnmatrix_get_btn_text, "s", "(lv.lv_obj)i" } }, + { "get_map", { (const void*) &lv_btnmatrix_get_map, "c", "(lv.lv_obj)" } }, + { "get_one_checked", { (const void*) &lv_btnmatrix_get_one_checked, "b", "(lv.lv_obj)" } }, + { "get_popovers", { (const void*) &lv_btnmatrix_get_popovers, "b", "(lv.lv_obj)" } }, + { "get_selected_btn", { (const void*) &lv_btnmatrix_get_selected_btn, "i", "(lv.lv_obj)" } }, + { "has_btn_ctrl", { (const void*) &lv_btnmatrix_has_btn_ctrl, "b", "(lv.lv_obj)ii" } }, + { "set_btn_ctrl", { (const void*) &lv_btnmatrix_set_btn_ctrl, "", "(lv.lv_obj)ii" } }, + { "set_btn_ctrl_all", { (const void*) &lv_btnmatrix_set_btn_ctrl_all, "", "(lv.lv_obj)i" } }, + { "set_btn_width", { (const void*) &lv_btnmatrix_set_btn_width, "", "(lv.lv_obj)ii" } }, + { "set_ctrl_map", { (const void*) &lv_btnmatrix_set_ctrl_map, "", "(lv.lv_obj)(lv.lv_btnmatrix_ctrl)" } }, + { "set_map", { (const void*) &lv_btnmatrix_set_map, "", "(lv.lv_obj)(lv.str_arr)" } }, + { "set_one_checked", { (const void*) &lv_btnmatrix_set_one_checked, "", "(lv.lv_obj)b" } }, + { "set_selected_btn", { (const void*) &lv_btnmatrix_set_selected_btn, "", "(lv.lv_obj)i" } }, +}; +#endif // BE_LV_WIDGET_BTNMATRIX + /* `lv_led` methods */ #ifdef BE_LV_WIDGET_LED const be_ntv_func_def_t lv_led_func[] = { @@ -815,26 +851,6 @@ const be_ntv_func_def_t lv_btn_func[] = { }; #endif // BE_LV_WIDGET_BTN -/* `lv_btnmatrix` methods */ -#ifdef BE_LV_WIDGET_BTNMATRIX -const be_ntv_func_def_t lv_btnmatrix_func[] = { - { "clear_btn_ctrl", { (const void*) &lv_btnmatrix_clear_btn_ctrl, "", "(lv.lv_obj)ii" } }, - { "clear_btn_ctrl_all", { (const void*) &lv_btnmatrix_clear_btn_ctrl_all, "", "(lv.lv_obj)i" } }, - { "get_btn_text", { (const void*) &lv_btnmatrix_get_btn_text, "s", "(lv.lv_obj)i" } }, - { "get_map", { (const void*) &lv_btnmatrix_get_map, "c", "(lv.lv_obj)" } }, - { "get_one_checked", { (const void*) &lv_btnmatrix_get_one_checked, "b", "(lv.lv_obj)" } }, - { "get_selected_btn", { (const void*) &lv_btnmatrix_get_selected_btn, "i", "(lv.lv_obj)" } }, - { "has_btn_ctrl", { (const void*) &lv_btnmatrix_has_btn_ctrl, "b", "(lv.lv_obj)ii" } }, - { "set_btn_ctrl", { (const void*) &lv_btnmatrix_set_btn_ctrl, "", "(lv.lv_obj)ii" } }, - { "set_btn_ctrl_all", { (const void*) &lv_btnmatrix_set_btn_ctrl_all, "", "(lv.lv_obj)i" } }, - { "set_btn_width", { (const void*) &lv_btnmatrix_set_btn_width, "", "(lv.lv_obj)ii" } }, - { "set_ctrl_map", { (const void*) &lv_btnmatrix_set_ctrl_map, "", "(lv.lv_obj)(lv.lv_btnmatrix_ctrl)" } }, - { "set_map", { (const void*) &lv_btnmatrix_set_map, "", "(lv.lv_obj)(lv.str_arr)" } }, - { "set_one_checked", { (const void*) &lv_btnmatrix_set_one_checked, "", "(lv.lv_obj)b" } }, - { "set_selected_btn", { (const void*) &lv_btnmatrix_set_selected_btn, "", "(lv.lv_obj)i" } }, -}; -#endif // BE_LV_WIDGET_BTNMATRIX - /* `lv_canvas` methods */ #ifdef BE_LV_WIDGET_CANVAS const be_ntv_func_def_t lv_canvas_func[] = { @@ -1042,6 +1058,7 @@ extern const bclass be_class_lv_group; extern const bclass be_class_lv_img; extern const bclass be_class_lv_imgbtn; extern const bclass be_class_lv_indev; +extern const bclass be_class_lv_keyboard; extern const bclass be_class_lv_label; extern const bclass be_class_lv_led; extern const bclass be_class_lv_line; @@ -1102,6 +1119,9 @@ const be_ntv_class_def_t lv_classes[] = { { "lv_imgbtn", &be_class_lv_imgbtn, lv_imgbtn_func, sizeof(lv_imgbtn_func) / sizeof(lv_imgbtn_func[0]) }, #endif // BE_LV_WIDGET_IMGBTN { "lv_indev", &be_class_lv_indev, lv_indev_func, sizeof(lv_indev_func) / sizeof(lv_indev_func[0]) }, +#ifdef BE_LV_WIDGET_KEYBOARD + { "lv_keyboard", &be_class_lv_keyboard, lv_keyboard_func, sizeof(lv_keyboard_func) / sizeof(lv_keyboard_func[0]) }, +#endif // BE_LV_WIDGET_KEYBOARD #ifdef BE_LV_WIDGET_LABEL { "lv_label", &be_class_lv_label, lv_label_func, sizeof(lv_label_func) / sizeof(lv_label_func[0]) }, #endif // BE_LV_WIDGET_LABEL @@ -1178,6 +1198,14 @@ const size_t lv_classes_size = sizeof(lv_classes) / sizeof(lv_classes[0]); #ifdef BE_LV_WIDGET_IMGBTN int be_ntv_lv_imgbtn_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_imgbtn_create, "+_p", "(lv.lv_obj)"); } #endif // BE_LV_WIDGET_IMGBTN + /* `lv_keyboard` methods */ +#ifdef BE_LV_WIDGET_KEYBOARD + int be_ntv_lv_keyboard_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_keyboard_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_KEYBOARD + /* `lv_btnmatrix` methods */ +#ifdef BE_LV_WIDGET_BTNMATRIX + int be_ntv_lv_btnmatrix_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_btnmatrix_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_BTNMATRIX /* `lv_led` methods */ #ifdef BE_LV_WIDGET_LED int be_ntv_lv_led_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_led_create, "+_p", "(lv.lv_obj)"); } @@ -1212,10 +1240,6 @@ const size_t lv_classes_size = sizeof(lv_classes) / sizeof(lv_classes[0]); #ifdef BE_LV_WIDGET_BTN int be_ntv_lv_btn_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_btn_create, "+_p", "(lv.lv_obj)"); } #endif // BE_LV_WIDGET_BTN - /* `lv_btnmatrix` methods */ -#ifdef BE_LV_WIDGET_BTNMATRIX - int be_ntv_lv_btnmatrix_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_btnmatrix_create, "+_p", "(lv.lv_obj)"); } -#endif // BE_LV_WIDGET_BTNMATRIX /* `lv_canvas` methods */ #ifdef BE_LV_WIDGET_CANVAS int be_ntv_lv_canvas_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_canvas_create, "+_p", "(lv.lv_obj)"); } diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c index 614e7f985..52a75bb5c 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c @@ -646,6 +646,36 @@ extern int lvbe_imgbtn_create(bvm *vm); extern int lvbe_imgbtn_set_src(bvm *vm); extern int lvbe_imgbtn_set_state(bvm *vm); +/* `lv_keyboard` external functions definitions */ +extern int lvbe_keyboard_create(bvm *vm); +extern int lvbe_keyboard_set_textarea(bvm *vm); +extern int lvbe_keyboard_set_mode(bvm *vm); +extern int lvbe_keyboard_set_popovers(bvm *vm); +extern int lvbe_keyboard_set_map(bvm *vm); +extern int lvbe_keyboard_get_textarea(bvm *vm); +extern int lvbe_keyboard_get_mode(bvm *vm); +extern int lvbe_keyboard_get_map_array(bvm *vm); +extern int lvbe_keyboard_get_selected_btn(bvm *vm); +extern int lvbe_keyboard_get_btn_text(bvm *vm); + +/* `lv_btnmatrix` external functions definitions */ +extern int lvbe_btnmatrix_get_popovers(bvm *vm); +extern int lvbe_btnmatrix_create(bvm *vm); +extern int lvbe_btnmatrix_set_map(bvm *vm); +extern int lvbe_btnmatrix_set_ctrl_map(bvm *vm); +extern int lvbe_btnmatrix_set_selected_btn(bvm *vm); +extern int lvbe_btnmatrix_set_btn_ctrl(bvm *vm); +extern int lvbe_btnmatrix_clear_btn_ctrl(bvm *vm); +extern int lvbe_btnmatrix_set_btn_ctrl_all(bvm *vm); +extern int lvbe_btnmatrix_clear_btn_ctrl_all(bvm *vm); +extern int lvbe_btnmatrix_set_btn_width(bvm *vm); +extern int lvbe_btnmatrix_set_one_checked(bvm *vm); +extern int lvbe_btnmatrix_get_map(bvm *vm); +extern int lvbe_btnmatrix_get_selected_btn(bvm *vm); +extern int lvbe_btnmatrix_get_btn_text(bvm *vm); +extern int lvbe_btnmatrix_has_btn_ctrl(bvm *vm); +extern int lvbe_btnmatrix_get_one_checked(bvm *vm); + /* `lv_led` external functions definitions */ extern int lvbe_led_create(bvm *vm); extern int lvbe_led_set_color(bvm *vm); @@ -777,23 +807,6 @@ extern int lvbe_bar_get_mode(bvm *vm); /* `lv_btn` external functions definitions */ extern int lvbe_btn_create(bvm *vm); -/* `lv_btnmatrix` external functions definitions */ -extern int lvbe_btnmatrix_create(bvm *vm); -extern int lvbe_btnmatrix_set_map(bvm *vm); -extern int lvbe_btnmatrix_set_ctrl_map(bvm *vm); -extern int lvbe_btnmatrix_set_selected_btn(bvm *vm); -extern int lvbe_btnmatrix_set_btn_ctrl(bvm *vm); -extern int lvbe_btnmatrix_clear_btn_ctrl(bvm *vm); -extern int lvbe_btnmatrix_set_btn_ctrl_all(bvm *vm); -extern int lvbe_btnmatrix_clear_btn_ctrl_all(bvm *vm); -extern int lvbe_btnmatrix_set_btn_width(bvm *vm); -extern int lvbe_btnmatrix_set_one_checked(bvm *vm); -extern int lvbe_btnmatrix_get_map(bvm *vm); -extern int lvbe_btnmatrix_get_selected_btn(bvm *vm); -extern int lvbe_btnmatrix_get_btn_text(bvm *vm); -extern int lvbe_btnmatrix_has_btn_ctrl(bvm *vm); -extern int lvbe_btnmatrix_get_one_checked(bvm *vm); - /* `lv_canvas` external functions definitions */ extern int lvbe_canvas_create(bvm *vm); extern int lvbe_canvas_set_buffer(bvm *vm); @@ -967,6 +980,8 @@ extern int be_ntv_lv_qrcode_init(bvm *vm); extern int be_ntv_lv_chart_init(bvm *vm); extern int be_ntv_lv_colorwheel_init(bvm *vm); extern int be_ntv_lv_imgbtn_init(bvm *vm); +extern int be_ntv_lv_keyboard_init(bvm *vm); +extern int be_ntv_lv_btnmatrix_init(bvm *vm); extern int be_ntv_lv_led_init(bvm *vm); extern int be_ntv_lv_meter_init(bvm *vm); extern int be_ntv_lv_msgbox_init(bvm *vm); @@ -977,7 +992,6 @@ extern int be_ntv_lv_timer_init(bvm *vm); extern int be_ntv_lv_arc_init(bvm *vm); extern int be_ntv_lv_bar_init(bvm *vm); extern int be_ntv_lv_btn_init(bvm *vm); -extern int be_ntv_lv_btnmatrix_init(bvm *vm); extern int be_ntv_lv_canvas_init(bvm *vm); extern int be_ntv_lv_checkbox_init(bvm *vm); extern int be_ntv_lv_dropdown_init(bvm *vm); @@ -1006,6 +1020,7 @@ extern const bclass be_class_lv_group; extern const bclass be_class_lv_img; extern const bclass be_class_lv_imgbtn; extern const bclass be_class_lv_indev; +extern const bclass be_class_lv_keyboard; extern const bclass be_class_lv_label; extern const bclass be_class_lv_led; extern const bclass be_class_lv_line; @@ -1214,6 +1229,28 @@ class be_class_lv_imgbtn (scope: global, name: lv_imgbtn, super: be_class_lv_obj } @const_object_info_end */ +/******************************************************************** +** Solidified class: lv_keyboard +********************************************************************/ +#include "be_fixed_be_class_lv_keyboard.h" +/* @const_object_info_begin +class be_class_lv_keyboard (scope: global, name: lv_keyboard, super: be_class_lv_btnmatrix, strings: weak) { + _class, comptr(&lv_keyboard_class) + init, func(be_ntv_lv_keyboard_init) +} +@const_object_info_end */ + +/******************************************************************** +** Solidified class: lv_btnmatrix +********************************************************************/ +#include "be_fixed_be_class_lv_btnmatrix.h" +/* @const_object_info_begin +class be_class_lv_btnmatrix (scope: global, name: lv_btnmatrix, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_btnmatrix_class) + init, func(be_ntv_lv_btnmatrix_init) +} +@const_object_info_end */ + /******************************************************************** ** Solidified class: lv_led ********************************************************************/ @@ -1304,17 +1341,6 @@ class be_class_lv_btn (scope: global, name: lv_btn, super: be_class_lv_obj, stri } @const_object_info_end */ -/******************************************************************** -** Solidified class: lv_btnmatrix -********************************************************************/ -#include "be_fixed_be_class_lv_btnmatrix.h" -/* @const_object_info_begin -class be_class_lv_btnmatrix (scope: global, name: lv_btnmatrix, super: be_class_lv_obj, strings: weak) { - _class, comptr(&lv_btnmatrix_class) - init, func(be_ntv_lv_btnmatrix_init) -} -@const_object_info_end */ - /******************************************************************** ** Solidified class: lv_canvas ********************************************************************/ diff --git a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h index 1a031f381..1aa1e61c0 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h +++ b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h @@ -665,6 +665,19 @@ lv_obj_t * lv_imgbtn_create(lv_obj_t * parent) void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_imgbtn_state_t state, const void * src_left, const void * src_mid, const void * src_right) void lv_imgbtn_set_state(lv_obj_t * imgbtn, lv_imgbtn_state_t state) +// ../../lvgl/src/extra/widgets/keyboard/lv_keyboard.h +lv_obj_t * lv_keyboard_create(lv_obj_t * parent) +void lv_keyboard_set_textarea(lv_obj_t * kb, lv_obj_t * ta) +void lv_keyboard_set_mode(lv_obj_t * kb, lv_keyboard_mode_t mode) +void lv_keyboard_set_popovers(lv_obj_t * kb, bool en) +void lv_keyboard_set_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const char * map[], const lv_btnmatrix_ctrl_t ctrl_map[]) +lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * kb) +lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * kb) +bool lv_btnmatrix_get_popovers(const lv_obj_t * obj) +static inline const char ** lv_keyboard_get_map_array(const lv_obj_t * kb) +static inline uint16_t lv_keyboard_get_selected_btn(const lv_obj_t * obj) +static inline const char * lv_keyboard_get_btn_text(const lv_obj_t * obj, uint16_t btn_id) + // ../../lvgl/src/extra/widgets/led/lv_led.h lv_obj_t * lv_led_create(lv_obj_t * parent) void lv_led_set_color(lv_obj_t * led, lv_color_t color) diff --git a/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py b/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py index 0e7dc1c3b..80ea5f579 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py +++ b/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py @@ -204,7 +204,7 @@ lv_widgets = ['arc', 'bar', 'btn', 'btnmatrix', 'canvas', 'checkbox', 'dropdown', 'img', 'label', 'line', 'roller', 'slider', 'switch', 'table', 'textarea' ] # extra widgets -lv_widgets = lv_widgets + [ 'chart', 'colorwheel', 'imgbtn', 'led', 'meter', 'msgbox', 'spinbox', 'spinner' ] +lv_widgets = lv_widgets + [ 'chart', 'colorwheel', 'imgbtn', 'led', 'meter', 'msgbox', 'spinbox', 'spinner', 'keyboard' ] # add qrcode lv_widgets = lv_widgets + [ 'qrcode' ] diff --git a/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py b/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py index c829c484b..4fc489daf 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py +++ b/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py @@ -61,6 +61,7 @@ lv_fun_globs = [ "extra/widgets/msgbox/*.h", "extra/widgets/spinbox/*.h", "extra/widgets/spinner/*.h", + "extra/widgets/keyboard/*.h", "extra/themes/default/*.h", "extra/themes/mono/*.h", "extra/layouts/**/*.h", diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index a5b424b0d..c93bfe9cc 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -1207,6 +1207,7 @@ #define BE_LV_WIDGET_MSGBOX #define BE_LV_WIDGET_SPINBOX #define BE_LV_WIDGET_SPINNER + // #define BE_LV_WIDGET_KEYBOARD #define BE_LV_WIDGET_QRCODE From ee4bf86e6aeaed407c6d067db511d77b00ca5bf2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 15 Jan 2024 10:34:14 +0100 Subject: [PATCH 144/303] Fix compilation when USE_ADC is not defined (#20498) --- tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 5050d5cb6..25108f7a6 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -220,6 +220,7 @@ void GVMonitorTask(void) { } #endif // ESP8266 +#ifdef USE_ADC else if (AdcPin(pin)) { // Read Analog (ADC) GPIO pintype = GV_AnalogPin; @@ -235,6 +236,8 @@ void GVMonitorTask(void) { originalValue = AdcRead1(pin); currentState = changeUIntScale(originalValue, 0, AdcRange(), 0, 255); // Bring back to 0..255 } +#endif // USE_ADC + else { // Read digital GPIO pintype = GV_DigitalPin; @@ -403,6 +406,9 @@ bool Xdrv121(uint32_t function) { GVMonitorTask(); } break; + case FUNC_SAVE_BEFORE_RESTART: + GVCloseEvent(); // Stop current updates + break; case FUNC_ACTIVE: result = true; break; From 637fac5ae8d5a045afa5192b54c821aa87b4d2ac Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 15 Jan 2024 15:36:59 +0100 Subject: [PATCH 145/303] Add GUI sensor separators (#20495) --- CHANGELOG.md | 3 ++- RELEASENOTES.md | 2 ++ tasmota/include/i18n.h | 1 + .../xdrv_01_9_webserver.ino | 26 +++++++++++++++++-- .../tasmota_xdrv_driver/xdrv_03_energy.ino | 4 +-- .../xdrv_03_esp32_energy.ino | 4 +-- .../xdrv_86_esp32_sonoff_spm.ino | 4 +-- .../tasmota_xx2c_global/xdrv_interface.ino | 2 ++ .../tasmota_xx2c_global/xsns_interface.ino | 2 ++ 9 files changed, 39 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63cbba761..eac36086e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,8 @@ All notable changes to this project will be documented in this file. - SML support for IM350 (#20474) - LVGL `lv.str_arr` (#20480) - ESP32 MI BLE support for Xiaomi LYWSD02MMC (#20381) -- LVGL option to add `lv.keyboard` extra widget +- LVGL option to add `lv.keyboard` extra widget (#20496) +- GUI sensor separators (#20495) ### Breaking Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 054ec73d3..d0afbb744 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -128,6 +128,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Support for pipsolar inverter [#20408](https://github.com/arendst/Tasmota/issues/20408) - Support for HardwareSerial invert [#15461](https://github.com/arendst/Tasmota/issues/15461) - SML support for IM350 [#20474](https://github.com/arendst/Tasmota/issues/20474) +- GUI sensor separators [#20495](https://github.com/arendst/Tasmota/issues/20495) - ESP32 used UART information - ESP32 experimental support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled - ESP32 MI BLE support for Xiaomi LYWSD02MMC [#20381](https://github.com/arendst/Tasmota/issues/20381) @@ -145,6 +146,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Berry `tasmota.webcolor` [#20454](https://github.com/arendst/Tasmota/issues/20454) - Berry `debug.caller` [#20470](https://github.com/arendst/Tasmota/issues/20470) - LVGL `lv.str_arr` [#20480](https://github.com/arendst/Tasmota/issues/20480) +- LVGL option to add `lv.keyboard` extra widget [#20496](https://github.com/arendst/Tasmota/issues/20496) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) - HASPmota type `chart` [#20372](https://github.com/arendst/Tasmota/issues/20372) - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) diff --git a/tasmota/include/i18n.h b/tasmota/include/i18n.h index 481456201..1455dd7f4 100644 --- a/tasmota/include/i18n.h +++ b/tasmota/include/i18n.h @@ -934,6 +934,7 @@ const float kSpeedConversionFactor[] = {1, // none // xdrv_02_webserver.ino #ifdef USE_WEBSERVER // {s} = , {m} = , {e} = +const char HTTP_SNS_HR[] PROGMEM = "
{e}"; const char HTTP_SNS_F_TEMP[] PROGMEM = "{s}%s " D_TEMPERATURE "{m}%*_f " D_UNIT_DEGREE "%c{e}"; const char HTTP_SNS_F_VOLTAGE[] PROGMEM = "{s}%s " D_VOLTAGE "{m}%*_f " D_UNIT_VOLT "{e}"; const char HTTP_SNS_F_CURRENT_MA[] PROGMEM = "{s}%s " D_CURRENT "{m}%*_f " D_UNIT_MILLIAMPERE "{e}"; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino index 69bdaddb2..dbcc63fbe 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino @@ -833,6 +833,8 @@ void _WSContentSendBuffer(bool decimal, const char * formatP, va_list arg) { int len = strlen(content); if (0 == len) { return; } // No content + WSContentSeparator(2); // Print separator on next WSContentSeparator(1) + if (decimal && (D_DECIMAL_SEPARATOR[0] != '.')) { for (uint32_t i = 0; i < len; i++) { if ('.' == content[i]) { @@ -982,6 +984,24 @@ void WSContentSpaceButton(uint32_t title_index, bool show=true) { WSContentButton(title_index, show); } +void WSContentSeparator(uint32_t state) { + // Send two column separator + static bool request = false; + switch (state) { + case 0: // Print separator (fall through to WSContentSeparator(1)) + request = true; + case 1: // Print separator if needed + if (request) { + WSContentSend_P(HTTP_SNS_HR); //
{e} + request = false; + } + break; + case 2: // Print separator on next WSContentSeparator(1) + request = true; + break; + } +} + void WSContentSend_Temp(const char *types, float f_temperature) { WSContentSend_PD(HTTP_SNS_F_TEMP, types, Settings->flag2.temperature_resolution, &f_temperature, TempUnit()); } @@ -1467,12 +1487,14 @@ bool HandleRootStatusRefresh(void) #else WSContentBegin(200, CT_HTML); #endif // USE_WEB_SSE - WSContentSend_P(PSTR("{t}")); + + WSContentSend_P(PSTR("{t}")); // + WSContentSeparator(0); // Print separator if (Settings->web_time_end) { WSContentSend_P(PSTR("{s}" D_TIMER_TIME "{m}%s{e}"), GetDateAndTime(DT_LOCAL).substring(Settings->web_time_start, Settings->web_time_end).c_str()); + WSContentSeparator(0); // Print separator } XsnsXdrvCall(FUNC_WEB_SENSOR); - WSContentSend_P(PSTR("
")); if (TasmotaGlobal.devices_present) { diff --git a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino index 66bf50acd..a5b0fd3e1 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino @@ -1409,7 +1409,7 @@ void EnergyShow(bool json) { // {s}Head1Head2{e} // {s}Head1Head2Head3{e} // {s}Head1Head2Head3Head4{e} - WSContentSend_P(PSTR("
{t}{s}")); // First column is empty ({t} = , {s} =
) + WSContentSend_P(PSTR("
{t}{s}")); // First column is empty ({t} = , {s} =
) bool label_o = voltage_common; bool no_label = (1 == Energy->phase_count); char number[4]; @@ -1448,7 +1448,7 @@ void EnergyShow(bool json) { WSContentSend_PD(HTTP_SNS_EXPORT_ACTIVE, WebEnergyFmt(Energy->export_active, Settings->flag2.energy_resolution, single)); } XnrgCall(FUNC_WEB_COL_SENSOR); - WSContentSend_P(PSTR("

{t}")); // {t} = - Define for next FUNC_WEB_SENSOR + WSContentSend_P(PSTR("
{t}")); // {t} = - Define for next FUNC_WEB_SENSOR XnrgCall(FUNC_WEB_SENSOR); #endif // USE_WEBSERVER } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino index 228e8b9de..a06c7125f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino @@ -1667,7 +1667,7 @@ void EnergyShow(bool json) { Energy->gui_count = relay_show - Energy->gui_offset; if (Energy->gui_count > Energy->Settings.gui_cols) { Energy->gui_count = Energy->Settings.gui_cols; } - WSContentSend_P(PSTR("

")); // Close current table as we will use different column count + WSContentSend_P(PSTR("")); // Close current table as we will use different column count bool label_o = voltage_common; if (ENERGY_DISPLAY_TABS == Energy->Settings.gui_display) { uint32_t tabs = (relay_show -1 + Energy->Settings.gui_cols) / Energy->Settings.gui_cols; @@ -1731,7 +1731,7 @@ void EnergyShow(bool json) { } XnrgCall(FUNC_WEB_COL_SENSOR); - WSContentSend_P(PSTR("
{t}")); // {t} = - Define for next FUNC_WEB_SENSOR + WSContentSend_P(PSTR("
{t}")); // {t} = - Define for next FUNC_WEB_SENSOR XnrgCall(FUNC_WEB_SENSOR); } #endif // USE_WEBSERVER diff --git a/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino b/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino index e9319da56..a2fa0abc1 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino @@ -2283,7 +2283,7 @@ void SSPMEnergyShow(bool json) { uint32_t offset = (Sspm->rotate >> 2) * 4; uint32_t count = relay_show - offset; if (count > 4) { count = 4; } - WSContentSend_P(PSTR("

")); // Close current table as we will use different column count + WSContentSend_P(PSTR("")); // Close current table as we will use different column count if (SPM_DISPLAY_TABS == Sspm->Settings.flag.display) { uint32_t modules = relay_show / 4; if (modules > 1) { @@ -2317,7 +2317,7 @@ void SSPMEnergyShow(bool json) { WSContentSend_PD(HTTP_SNS_ENERGY_TODAY, SSPMEnergyFormat(value_chr, Sspm->energy_today[0], Settings->flag2.energy_resolution, indirect, offset, count)); WSContentSend_PD(HTTP_SNS_ENERGY_YESTERDAY, SSPMEnergyFormat(value_chr, Sspm->Settings.energy_yesterday[0], Settings->flag2.energy_resolution, indirect, offset, count)); WSContentSend_PD(HTTP_SNS_ENERGY_TOTAL, SSPMEnergyFormat(value_chr, Sspm->energy_total[0], Settings->flag2.energy_resolution, indirect, offset, count)); - WSContentSend_P(PSTR("
{t}")); // {t} = - Define for next FUNC_WEB_SENSOR + WSContentSend_P(PSTR("
{t}")); // {t} = - Define for next FUNC_WEB_SENSOR } #endif // USE_WEBSERVER } diff --git a/tasmota/tasmota_xx2c_global/xdrv_interface.ino b/tasmota/tasmota_xx2c_global/xdrv_interface.ino index 03ff1b2d9..a1dfceea9 100644 --- a/tasmota/tasmota_xx2c_global/xdrv_interface.ino +++ b/tasmota/tasmota_xx2c_global/xdrv_interface.ino @@ -1147,6 +1147,8 @@ bool XdrvCall(uint32_t function) { result = xdrv_func_ptr[x](function); + if (FUNC_WEB_SENSOR == function) { WSContentSeparator(1); } // Show separator if needed + #ifdef USE_PROFILE_FUNCTION #ifdef XFUNC_PTR_IN_ROM uint32_t index = pgm_read_byte(kXdrvList + x); diff --git a/tasmota/tasmota_xx2c_global/xsns_interface.ino b/tasmota/tasmota_xx2c_global/xsns_interface.ino index 2f020b92d..49f5311eb 100644 --- a/tasmota/tasmota_xx2c_global/xsns_interface.ino +++ b/tasmota/tasmota_xx2c_global/xsns_interface.ino @@ -1130,6 +1130,8 @@ bool XsnsCall(uint32_t function) { result = xsns_func_ptr[x](function); + if (FUNC_WEB_SENSOR == function) { WSContentSeparator(1); } // Show separator if needed + #ifdef USE_PROFILE_FUNCTION #ifdef XFUNC_PTR_IN_ROM uint32_t index = pgm_read_byte(kXsnsList + x); From 2c555cf15b87baee91f301a3aa23c80d587ec2c0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 15 Jan 2024 15:51:00 +0100 Subject: [PATCH 146/303] Add thin line as sub-separator --- tasmota/include/i18n.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/include/i18n.h b/tasmota/include/i18n.h index 1455dd7f4..a199861c5 100644 --- a/tasmota/include/i18n.h +++ b/tasmota/include/i18n.h @@ -935,6 +935,7 @@ const float kSpeedConversionFactor[] = {1, // none #ifdef USE_WEBSERVER // {s} = const char HTTP_SNS_HR[] PROGMEM = "
, {m} = , {e} =

{e}"; +const char HTTP_SNS_HR_THIN[] PROGMEM = "

{e}"; const char HTTP_SNS_F_TEMP[] PROGMEM = "{s}%s " D_TEMPERATURE "{m}%*_f " D_UNIT_DEGREE "%c{e}"; const char HTTP_SNS_F_VOLTAGE[] PROGMEM = "{s}%s " D_VOLTAGE "{m}%*_f " D_UNIT_VOLT "{e}"; const char HTTP_SNS_F_CURRENT_MA[] PROGMEM = "{s}%s " D_CURRENT "{m}%*_f " D_UNIT_MILLIAMPERE "{e}"; From f2800dd7707fc67c15daeed906f7e064f5912960 Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Mon, 15 Jan 2024 16:53:34 +0100 Subject: [PATCH 147/303] Modify drivers for GUI sensor separators (#20504) --- .../xdrv_39_thermostat.ino | 3 +- .../xdrv_85_esp32_ble_eq3_trv.ino | 5 ++- .../xsns_62_esp32_mi_ble.ino | 37 +++++++++---------- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_39_thermostat.ino b/tasmota/tasmota_xdrv_driver/xdrv_39_thermostat.ino index a2cbe27fe..97ee43fc2 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_39_thermostat.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_39_thermostat.ino @@ -2054,7 +2054,6 @@ const char HTTP_THERMOSTAT_DUTY_CYCLE[] PROGMEM = "{s}" D_THERMOSTAT_DUTY_CY const char HTTP_THERMOSTAT_CYCLE_TIME[] PROGMEM = "{s}" D_THERMOSTAT_CYCLE_TIME "{m}%d " D_UNIT_MINUTE "{e}"; const char HTTP_THERMOSTAT_CONTROL_METHOD[] PROGMEM = "{s}" D_THERMOSTAT_CONTROL_METHOD "{m}%s{e}"; const char HTTP_THERMOSTAT_PI_AUTOTUNE[] PROGMEM = "{s}" D_THERMOSTAT_PI_AUTOTUNE "{m}%s{e}"; -const char HTTP_THERMOSTAT_HL[] PROGMEM = "{s}
{m}
{e}"; #endif // USE_WEBSERVER @@ -2078,7 +2077,7 @@ void ThermostatShow(uint8_t ctr_output, bool json) } #ifdef USE_WEBSERVER - WSContentSend_P(HTTP_THERMOSTAT_HL); + if (ctr_output) WSContentSend_P(HTTP_SNS_HR_THIN); if (Thermostat[ctr_output].status.thermostat_mode == THERMOSTAT_OFF) { WSContentSend_P(HTTP_THERMOSTAT_INFO, ctr_output + 1, D_DISABLED ); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_85_esp32_ble_eq3_trv.ino b/tasmota/tasmota_xdrv_driver/xdrv_85_esp32_ble_eq3_trv.ino index 978dcab58..7e2f132dd 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_85_esp32_ble_eq3_trv.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_85_esp32_ble_eq3_trv.ino @@ -989,7 +989,6 @@ int EQ3SendResult(char *requested, const char *result){ } #ifdef USE_WEBSERVER -const char HTTP_EQ3_HL[] PROGMEM = "{s}
{m}
{e}"; const char HTTP_EQ3_ALIAS[] PROGMEM = "{s}EQ3 %d Alias{m}%s{e}"; const char HTTP_EQ3_MAC[] PROGMEM = "{s}EQ3 %d " D_MAC_ADDRESS "{m}%s{e}"; const char HTTP_EQ3_RSSI[] PROGMEM = "{s}EQ3 %d " D_RSSI "{m}%d dBm{e}"; @@ -1000,10 +999,12 @@ const char HTTP_EQ3_BATTERY[] PROGMEM = "{s}EQ3 %d " D_BATTERY "{m}%s{e}"; void EQ3Show(void) { char c_unit = D_UNIT_CELSIUS[0]; // ToDo: Check if fahrenheit is possible -> temp_format==TEMP_CELSIUS ? D_UNIT_CELSIUS[0] : D_UNIT_FAHRENHEIT[0]; + bool FirstSensorShown = false; for (int i = 0; i < EQ3_NUM_DEVICESLOTS; i++) { if (EQ3Devices[i].timeoutTime) { - WSContentSend_P(HTTP_EQ3_HL); + if (FirstSensorShown) WSContentSend_P(HTTP_SNS_HR_THIN); + FirstSensorShown = true; const char *alias = BLE_ESP32::getAlias(EQ3Devices[i].addr); if (alias && *alias){ WSContentSend_PD(HTTP_EQ3_ALIAS, i + 1, alias); diff --git a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino index 06c3e1092..55a46729e 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi_ble.ino @@ -2725,32 +2725,31 @@ void CmndMi32Keys(void){ const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 " MI32_VERSION "{m}%u%s / %u{e}"; const char HTTP_MI32_ALIAS[] PROGMEM = "{s}%s Alias{m}%s{e}"; -const char HTTP_MI32_MAC[] PROGMEM = "{s}%s %s{m}%s{e}"; -const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}"; -const char HTTP_BATTERY[] PROGMEM = "{s}%s " D_BATTERY "{m}%u %%{e}"; -const char HTTP_LASTBUTTON[] PROGMEM = "{s}%s Last Button{m}%u {e}"; -const char HTTP_EVENTS[] PROGMEM = "{s}%s Events{m}%u {e}"; -const char HTTP_NMT[] PROGMEM = "{s}%s No motion{m}> %u seconds{e}"; -const char HTTP_MI32_FLORA_DATA[] PROGMEM = "{s}%s Fertility{m}%u us/cm{e}"; -const char HTTP_MI32_HL[] PROGMEM = "{s}
{m}
{e}"; +const char HTTP_MI32_MAC[] PROGMEM = "{s}%s " D_MAC_ADDRESS "{m}%s{e}"; +const char HTTP_MI32_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}"; +const char HTTP_MI32_BATTERY[] PROGMEM = "{s}%s " D_BATTERY "{m}%u %%{e}"; +const char HTTP_MI32_LASTBUTTON[] PROGMEM = "{s}%s Last Button{m}%u{e}"; +const char HTTP_MI32_EVENTS[] PROGMEM = "{s}%s Events{m}%u{e}"; +const char HTTP_MI32_NMT[] PROGMEM = "{s}%s No motion{m}> %u " D_SECONDS "{e}"; +const char HTTP_MI32_FLORA_DATA[] PROGMEM = "{s}%s Fertility{m}%u " D_UNIT_MICROSIEMENS_PER_CM "{e}"; const char HTTP_MI32_LIGHT[] PROGMEM = "{s}%s " D_LIGHT "{m}%d{e}"; const char HTTP_MISCALE_WEIGHT[] PROGMEM = "{s}%s " D_WEIGHT "{m}%*_f %s{e}"; const char HTTP_MISCALE_WEIGHT_REMOVED[] PROGMEM = "{s}%s Weight removed{m}%s{e}"; const char HTTP_MISCALE_WEIGHT_STABILIZED[] PROGMEM = "{s}%s Weight stabilized{m}%s{e}"; const char HTTP_MISCALE_IMPEDANCE[] PROGMEM = "{s}%s Impedance{m}%u{e}"; const char HTTP_MISCALE_IMPEDANCE_STABILIZED[] PROGMEM = "{s}%s Impedance stabilized{m}%s{e}"; -const char HTTP_SJWS01LM_FLOODING[] PROGMEM = "{s}%s Flooding{m}%u {e}"; +const char HTTP_SJWS01LM_FLOODING[] PROGMEM = "{s}%s Flooding{m}%u{e}"; //const char HTTP_NEEDKEY[] PROGMEM = "{s}%s %s{m} {e}"; +// "\">%s{m}{e}"; //const char HTTP_NEEDKEY[] PROGMEM = "{s}%s %s{m} {e}"; +// "\">%s{m}{e}"; const char HTTP_NEEDKEY[] PROGMEM = "{s}%s %s{m} {e}"; + "\">%s{m}{e}"; const char HTTP_PAIRING[] PROGMEM = "{s}%s Pair Button Pressed{m} {e}"; @@ -3521,7 +3520,7 @@ void MI32Show(bool json) WSContentSend_P(HTTP_MI32, i + 1, stemp, numsensors); for (i; iMAC,6,_MAC,18);//,':'); - WSContentSend_P(HTTP_MI32_MAC, typeName, D_MAC_ADDRESS, _MAC); - WSContentSend_PD(HTTP_RSSI, typeName, p->RSSI); + WSContentSend_P(HTTP_MI32_MAC, typeName, _MAC); + WSContentSend_PD(HTTP_MI32_RSSI, typeName, p->RSSI); // for some reason, display flora differently switch(p->type){ @@ -3597,11 +3596,11 @@ void MI32Show(bool json) #endif //USE_MI_DECRYPTION if (p->feature.events){ - WSContentSend_PD(HTTP_EVENTS, typeName, p->events); + WSContentSend_PD(HTTP_MI32_EVENTS, typeName, p->events); } if (p->feature.NMT){ // no motion time - if(p->NMT>0) WSContentSend_PD(HTTP_NMT, typeName, p->NMT); + if(p->NMT>0) WSContentSend_PD(HTTP_MI32_NMT, typeName, p->NMT); } if (p->feature.lux){ @@ -3626,10 +3625,10 @@ void MI32Show(bool json) } } if(p->bat!=0x00){ - WSContentSend_PD(HTTP_BATTERY, typeName, p->bat); + WSContentSend_PD(HTTP_MI32_BATTERY, typeName, p->bat); } if (p->feature.Btn){ - WSContentSend_PD(HTTP_LASTBUTTON, typeName, p->Btn); + WSContentSend_PD(HTTP_MI32_LASTBUTTON, typeName, p->Btn); } if (p->feature.flooding) { From ab2439f6c85a19f73cf46fcbd68769374ce5a9fb Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Mon, 15 Jan 2024 18:24:15 +0100 Subject: [PATCH 148/303] Modify shutter driver for GUI sensor separators (#20506) --- tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino | 3 +++ tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino | 1 + 2 files changed, 4 insertions(+) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino index dbcc63fbe..617dcb62e 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino @@ -999,6 +999,9 @@ void WSContentSeparator(uint32_t state) { case 2: // Print separator on next WSContentSeparator(1) request = true; break; + case 3: // Don't print separator on next WSContentSeparator(1) + request = false; + break; } } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino b/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino index 2fdc52b07..7bf8b4563 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino @@ -1141,6 +1141,7 @@ void ShutterToggle(bool dir) void ShutterShow(){ for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) { WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, (Settings->shutter_options[i] & 1) ? D_OPEN : D_CLOSE,(Settings->shutter_options[i] & 1) ? D_CLOSE : D_OPEN, (Settings->shutter_options[i] & 1) ? (100 - ShutterRealToPercentPosition(-9999, i)) : ShutterRealToPercentPosition(-9999, i), i+1); + WSContentSeparator(3); // Don't print separator on next WSContentSeparator(1) } } From 4f436cdf73158ba49c40473d8cd4cd02db144a6a Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Mon, 15 Jan 2024 18:58:14 +0100 Subject: [PATCH 149/303] Remove first separator (#20507) --- tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino index 617dcb62e..8356f05da 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino @@ -1492,7 +1492,6 @@ bool HandleRootStatusRefresh(void) #endif // USE_WEB_SSE WSContentSend_P(PSTR("{t}")); // - WSContentSeparator(0); // Print separator if (Settings->web_time_end) { WSContentSend_P(PSTR("{s}" D_TIMER_TIME "{m}%s{e}"), GetDateAndTime(DT_LOCAL).substring(Settings->web_time_start, Settings->web_time_end).c_str()); WSContentSeparator(0); // Print separator From 90aa519cbd18ec266935ef42c1a2db45f1566dbe Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 15 Jan 2024 19:23:58 +0100 Subject: [PATCH 150/303] Platform 2024.01.01 (#20508) - core 2.0.14 with compability to IPv6 implementation of espressif Arduino core 3.0.0 --- platformio_tasmota32.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 95f4fc058..1e8b5466e 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -92,7 +92,7 @@ lib_ignore = [core32] -platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.00/platform-espressif32.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.01/platform-espressif32.zip platform_packages = build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} From d0a9f0d15dca000794060f702b0c54b941deef7e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 15 Jan 2024 20:09:19 +0100 Subject: [PATCH 151/303] core3 with espressif IPv6 implementation (#20510) --- platformio_tasmota32.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 1e8b5466e..a735cd6d7 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -98,7 +98,7 @@ build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} [core32_30] -platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.10/platform-espressif32.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.11/platform-espressif32.zip platform_packages = build_unflags = ${core32.build_unflags} build_flags = ${core32.build_flags} From 9045a7da8322bb70a046f8b3b7ac1a6118e2f5bf Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Mon, 15 Jan 2024 21:05:40 +0100 Subject: [PATCH 152/303] IP stack compatible with new Core3 IPv6 implementation (#20509) * IP stack compatible with new Core3 IPv6 implementation * Fix compilation * Forece CI --- CHANGELOG.md | 1 + .../ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp | 22 +++-- .../berry_matter/src/be_matter_misc.cpp | 6 +- tasmota/tasmota_support/support_wifi.ino | 93 +++++++++++-------- tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino | 4 +- .../xdrv_52_3_berry_mdns.ino | 15 +-- .../xdrv_52_3_berry_tcpclientasync.ino | 4 +- .../xdrv_52_3_berry_tcpserver.ino | 4 +- .../xdrv_52_3_berry_udp.ino | 10 +- .../xdrv_82_esp32_ethernet.ino | 25 ++++- 10 files changed, 115 insertions(+), 69 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eac36086e..f5f5fff3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ All notable changes to this project will be documented in this file. ### Breaking Changed ### Changed +- IP stack compatible with new Core3 IPv6 implementation () ### Fixed - Scripter memory leak in `>w x` (#20473) diff --git a/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp index ea288d547..c5cdedc3f 100644 --- a/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp +++ b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp @@ -89,10 +89,12 @@ void WiFiClass32::scrubDNS(void) { const IPAddress ip_dns = IPAddress(dns_getserver(i)); // Step 1. save valid values from DNS if (!ip_addr_isany_val((const ip_addr_t &)ip_dns)) { - if (ip_dns.isV4() && has_v4) { - dns_save4[i] = (ip_addr_t) ip_dns; // dns entry is populated, save it in v4 slot - } else if (ip_dns.isV6() && has_v6) { - dns_save6[i] = (ip_addr_t) ip_dns; // dns entry is populated, save it in v6 slot + if (ip_dns.type() == IPv4 && has_v4) { + ip_dns.to_ip_addr_t(&dns_save4[i]); + // dns_save4[i] = (ip_addr_t) ip_dns; // dns entry is populated, save it in v4 slot + } else if (has_v6) { + ip_dns.to_ip_addr_t(&dns_save6[i]); + // dns_save6[i] = (ip_addr_t) ip_dns; // dns entry is populated, save it in v6 slot } } @@ -213,7 +215,7 @@ static void wifi32_dns_found_callback(const char *name, const ip_addr_t *ipaddr, } // We need this helper method to access protected methods from WiFiGeneric void WiFiClass32::dnsDone(void) { - setStatusBits(WIFI_DNS_DONE_BIT); + setStatusBits(NET_DNS_DONE_BIT); } /** @@ -231,7 +233,7 @@ int WiFiClass32::hostByName(const char* aHostname, IPAddress& aResult, int32_t t scrubDNS(); // internal calls to reconnect can zero the DNS servers, save DNS for future use ip_addr_counter++; // increase counter, from now ignore previous responses - clearStatusBits(WIFI_DNS_IDLE_BIT | WIFI_DNS_DONE_BIT); + clearStatusBits(NET_DNS_IDLE_BIT | NET_DNS_DONE_BIT); uint8_t v4v6priority = LWIP_DNS_ADDRTYPE_IPV4; #ifdef USE_IPV6 v4v6priority = WifiDNSGetIPv6Priority() ? LWIP_DNS_ADDRTYPE_IPV6_IPV4 : LWIP_DNS_ADDRTYPE_IPV4_IPV6; @@ -240,18 +242,18 @@ int WiFiClass32::hostByName(const char* aHostname, IPAddress& aResult, int32_t t // Serial.printf("DNS: dns_gethostbyname_addrtype errg=%i counter=%i\n", err, ip_addr_counter); if(err == ERR_OK && !ip_addr_isany_val(dns_ipaddr)) { #ifdef USE_IPV6 - aResult = dns_ipaddr; + aResult.from_ip_addr_t(&dns_ipaddr); #else // USE_IPV6 aResult = ip_addr_get_ip4_u32(&dns_ipaddr); #endif // USE_IPV6 } else if(err == ERR_INPROGRESS) { - waitStatusBits(WIFI_DNS_DONE_BIT, timer_ms); //real internal timeout in lwip library is 14[s] - clearStatusBits(WIFI_DNS_DONE_BIT); + waitStatusBits(NET_DNS_DONE_BIT, timer_ms); //real internal timeout in lwip library is 14[s] + clearStatusBits(NET_DNS_DONE_BIT); } if (!ip_addr_isany_val(dns_ipaddr)) { #ifdef USE_IPV6 - aResult = dns_ipaddr; + aResult.from_ip_addr_t(&dns_ipaddr); #else // USE_IPV6 aResult = ip_addr_get_ip4_u32(&dns_ipaddr); #endif // USE_IPV6 diff --git a/lib/libesp32/berry_matter/src/be_matter_misc.cpp b/lib/libesp32/berry_matter/src/be_matter_misc.cpp index 0e57c2aa5..32931d6c7 100644 --- a/lib/libesp32/berry_matter/src/be_matter_misc.cpp +++ b/lib/libesp32/berry_matter/src/be_matter_misc.cpp @@ -32,12 +32,14 @@ extern "C" const void* matter_get_ip_bytes(const char* ip_str, size_t* ret_len) IPAddress ip; if (ip.fromString(ip_str)) { #ifdef USE_IPV6 - if (ip.isV4()) { + if (ip.type() == IPv4) { uint32_t ip_32 = ip; memcpy(ip_bytes, &ip_32, 4); *ret_len = 4; } else { - memcpy(ip_bytes, ip.raw6(), 16); + ip_addr_t ip_addr; + ip.to_ip_addr_t(&ip_addr); + memcpy(ip_bytes, &ip_addr.u_addr.ip6, 16); *ret_len = 16; } #else diff --git a/tasmota/tasmota_support/support_wifi.ino b/tasmota/tasmota_support/support_wifi.ino index c76a278a1..fbf6dc1b1 100644 --- a/tasmota/tasmota_support/support_wifi.ino +++ b/tasmota/tasmota_support/support_wifi.ino @@ -209,7 +209,7 @@ void WifiBegin(uint8_t flag, uint8_t channel) { WiFi.persistent(false); // Solve possible wifi init errors (re-add at 6.2.1.16 #4044, #4083) #if defined(USE_IPV6) && defined(ESP32) - WiFi.IPv6(true); + WiFi.enableIPv6(true); #endif #ifdef USE_WIFI_RANGE_EXTENDER @@ -545,6 +545,11 @@ String EthernetGetIPv4Str(void) } #ifdef USE_IPV6 +bool IPv6isLocal(const IPAddress & ip) { + return ip.addr_type() == ESP_IP6_ADDR_IS_LINK_LOCAL; // TODO +} + +#include "lwip/netif.h" // // Scan through all interfaces to find a global or local IPv6 address // Arg: @@ -557,7 +562,7 @@ bool WifiFindIPv6(IPAddress *ip, bool is_local, const char * if_type = "st") { for (uint32_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { ip_addr_t *ipv6 = &intf->ip6_addr[i]; if (IP_IS_V6_VAL(*ipv6) && !ip_addr_isloopback(ipv6) && !ip_addr_isany(ipv6) && ((bool)ip_addr_islinklocal(ipv6) == is_local)) { - if (ip != nullptr) { *ip = *ipv6; } + if (ip != nullptr) { ip->from_ip_addr_t(ipv6); } return true; } } @@ -579,7 +584,7 @@ bool WifiHasIPv6(void) String WifiGetIPv6Str(void) { IPAddress ip; - return WifiGetIPv6(&ip) ? ip.toString() : String(); + return WifiGetIPv6(&ip) ? ip.toString(true) : String(); } bool WifiGetIPv6LinkLocal(IPAddress *ip) @@ -589,7 +594,7 @@ bool WifiGetIPv6LinkLocal(IPAddress *ip) String WifiGetIPv6LinkLocalStr(void) { IPAddress ip; - return WifiGetIPv6LinkLocal(&ip) ? ip.toString() : String(); + return WifiGetIPv6LinkLocal(&ip) ? ip.toString(true) : String(); } @@ -605,7 +610,7 @@ bool EthernetHasIPv6(void) String EthernetGetIPv6Str(void) { IPAddress ip; - return EthernetGetIPv6(&ip) ? ip.toString() : String(); + return EthernetGetIPv6(&ip) ? ip.toString(true) : String(); } bool EthernetGetIPv6LinkLocal(IPAddress *ip) @@ -619,7 +624,7 @@ bool EthernetHasIPv6LinkLocal(void) String EthernetGetIPv6LinkLocalStr(void) { IPAddress ip; - return EthernetGetIPv6LinkLocal(&ip) ? ip.toString() : String(); + return EthernetGetIPv6LinkLocal(&ip) ? ip.toString(true) : String(); } bool DNSGetIP(IPAddress *ip, uint32_t idx) @@ -629,16 +634,16 @@ bool DNSGetIP(IPAddress *ip, uint32_t idx) #endif const ip_addr_t *ip_dns = dns_getserver(idx); if (!ip_addr_isany(ip_dns)) { - if (ip != nullptr) { *ip = *ip_dns; } + if (ip != nullptr) { ip->from_ip_addr_t((ip_addr_t*)ip_dns); } return true; } - if (ip != nullptr) { *ip = *IP4_ADDR_ANY; } + if (ip != nullptr) { ip->from_ip_addr_t((ip_addr_t*)IP4_ADDR_ANY); } return false; } String DNSGetIPStr(uint32_t idx) { IPAddress ip; - return DNSGetIP(&ip, idx) ? ip.toString() : String(F("0.0.0.0")); + return DNSGetIP(&ip, idx) ? ip.toString(true) : String(F("0.0.0.0")); } // @@ -646,15 +651,15 @@ String DNSGetIPStr(uint32_t idx) void WifiDumpAddressesIPv6(void) { for (netif* intf = netif_list; intf != nullptr; intf = intf->next) { - if (!ip_addr_isany_val(intf->ip_addr)) AddLog(LOG_LEVEL_DEBUG, "WIF: '%c%c%i' IPv4 %s", intf->name[0], intf->name[1], intf->num, IPAddress(intf->ip_addr).toString().c_str()); + if (!ip_addr_isany_val(intf->ip_addr)) AddLog(LOG_LEVEL_DEBUG, "WIF: '%c%c%i' IPv4 %s", intf->name[0], intf->name[1], intf->num, IPAddress(&intf->ip_addr).toString(true).c_str()); for (uint32_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (!ip_addr_isany_val(intf->ip6_addr[i])) AddLog(LOG_LEVEL_DEBUG, "IP : '%c%c%i' IPv6 %s %s", intf->name[0], intf->name[1], intf->num, - IPAddress(intf->ip6_addr[i]).toString().c_str(), + IPAddress(&intf->ip6_addr[i]).toString(true).c_str(), ip_addr_islinklocal(&intf->ip6_addr[i]) ? "local" : ""); } } - AddLog(LOG_LEVEL_DEBUG, "IP : DNS: %s %s", IPAddress(dns_getserver(0)).toString().c_str(), IPAddress(dns_getserver(1)).toString().c_str()); + AddLog(LOG_LEVEL_DEBUG, "IP : DNS: %s %s", IPAddress(dns_getserver(0)).toString().c_str(), IPAddress(dns_getserver(1)).toString(true).c_str()); AddLog(LOG_LEVEL_DEBUG, "WIF: v4IP: %_I v6IP: %s mainIP: %s", (uint32_t) WiFi.localIP(), WifiGetIPv6Str().c_str(), WifiGetIPStr().c_str()); #if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET) AddLog(LOG_LEVEL_DEBUG, "ETH: v4IP %_I v6IP: %s mainIP: %s", (uint32_t) EthernetLocalIP(), EthernetGetIPv6Str().c_str(), EthernetGetIPStr().c_str()); @@ -680,8 +685,8 @@ bool IPGetListeningAddress(IPAddress * ip) IPAddress ip_eth; bool has_eth = EthernetGetIP(&ip_eth); if (has_wifi && has_eth) { - if (ip_eth.isV4()) { *ip = ip_eth; return true; } - if (ip_wifi.isV4()) { *ip = ip_wifi; return true; } + if (ip_eth.type() == IPv4) { *ip = ip_eth; return true; } + if (ip_wifi.type() == IPv4) { *ip = ip_wifi; return true; } // both addresses are v6, return ETH *ip = ip_eth; return true; @@ -707,11 +712,11 @@ bool IPGetListeningAddress(IPAddress * ip) String IPGetListeningAddressStr(void) { IPAddress ip; - if (IPGetListeningAddress(&ip)) { - return ip.toString(); - } else { - return String(); - } +#ifdef USE_IPV6 + return IPGetListeningAddress(&ip) ? ip.toString(true) : String(); +#else + return IPGetListeningAddress(&ip) ? ip.toString() : String(); +#endif } // Because of IPv6, we can't test an IP address agains (uint32_t)0L anymore @@ -732,11 +737,11 @@ inline bool IPIsValid(const IPAddress & ip) String IPForUrl(const IPAddress & ip) { #ifdef USE_IPV6 - if (ip.isV4()) { + if (ip.type() == IPv4) { return ip.toString().c_str(); } else { String s('['); - s += ip.toString().c_str(); + s += ip.toString(true).c_str(); s += ']'; return s; } @@ -789,7 +794,11 @@ bool WifiHasIP(void) { String WifiGetIPStr(void) { IPAddress ip; +#ifdef USE_IPV6 + return WifiGetIP(&ip) ? ip.toString(true) : String(); +#else return WifiGetIP(&ip) ? ip.toString() : String(); +#endif } // Has a routable IP, whether IPv4 or IPv6, Wifi or Ethernet @@ -809,9 +818,9 @@ void WifiCheckIp(void) { if (WL_CONNECTED == WiFi.status()) { #ifdef ESP32 if (!Wifi.ipv6_local_link_called) { - WiFi.enableIpV6(); + WiFi.enableIPv6(true); // TODO Wifi.ipv6_local_link_called = true; - // AddLog(LOG_LEVEL_DEBUG, PSTR("WIF: calling enableIpV6")); + // AddLog(LOG_LEVEL_DEBUG, PSTR("WIF: calling enableIPV6")); } #endif } @@ -1279,18 +1288,6 @@ bool WifiHostByName(const char* aHostname, IPAddress& aResult) { uint32_t dns_end = millis(); if (success) { // Host name resolved -#ifdef USE_IPV6 -#if ESP_IDF_VERSION_MAJOR >= 5 - // check if there is a zone-id - // look for '%' in string - const char *s = aHostname; - while (*s && *s != '%') { s++; } - if (*s == '%') { - // we have a zone id - aResult.setZone(netif_name_to_index(s + 1)); - } -#endif -#endif // USE_IPV6 if (0xFFFFFFFF != (uint32_t)aResult) { AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_WIFI "DNS resolved '%s' (%s) in %i ms"), aHostname, aResult.toString().c_str(), dns_end - dns_start); return true; @@ -1376,7 +1373,11 @@ uint64_t WifiGetNtp(void) { uint32_t attempts = 3; while (attempts > 0) { uint32_t port = random(1025, 65535); // Create a random port for the UDP connection. +#ifdef USE_IPV6 + if (udp.begin(IPAddress(IPv6), port) != 0) { +#else if (udp.begin(port) != 0) { +#endif break; } attempts--; @@ -1454,6 +1455,8 @@ uint64_t WifiGetNtp(void) { // Respond to some Arduino/esp-idf events for better IPv6 support // -------------------------------------------------------------------------------- #ifdef ESP32 +extern esp_netif_t* get_esp_interface_netif(esp_interface_t interface); + // typedef void (*WiFiEventSysCb)(arduino_event_t *event); void WifiEvents(arduino_event_t *event) { switch (event->event_id) { @@ -1461,17 +1464,17 @@ void WifiEvents(arduino_event_t *event) { #ifdef USE_IPV6 case ARDUINO_EVENT_WIFI_STA_GOT_IP6: { - ip_addr_t ip_addr6; - ip_addr_copy_from_ip6(ip_addr6, event->event_info.got_ip6.ip6_info.ip); - IPAddress addr(ip_addr6); +// Serial.printf(">>> event ARDUINO_EVENT_WIFI_STA_GOT_IP6 \n"); + IPAddress addr(IPv6, (const uint8_t*)event->event_info.got_ip6.ip6_info.ip.addr, event->event_info.got_ip6.ip6_info.ip.zone); AddLog(LOG_LEVEL_DEBUG, PSTR("%s: IPv6 %s %s"), event->event_id == ARDUINO_EVENT_ETH_GOT_IP6 ? "ETH" : "WIF", - addr.isLocal() ? PSTR("Local") : PSTR("Global"), addr.toString().c_str()); + IPv6isLocal(addr) ? PSTR("Local") : PSTR("Global"), addr.toString(true).c_str()); } break; #endif // USE_IPV6 case ARDUINO_EVENT_WIFI_STA_GOT_IP: { +// Serial.printf(">>> event ARDUINO_EVENT_WIFI_STA_GOT_IP \n"); ip_addr_t ip_addr4; ip_addr_copy_from_ip4(ip_addr4, event->event_info.got_ip.ip_info.ip); AddLog(LOG_LEVEL_DEBUG, PSTR("WIF: IPv4 %_I, mask %_I, gateway %_I"), @@ -1482,6 +1485,18 @@ void WifiEvents(arduino_event_t *event) { break; case ARDUINO_EVENT_WIFI_STA_CONNECTED: + // workaround for the race condition in LWIP, see https://github.com/espressif/arduino-esp32/pull/9016#discussion_r1451774885 + { + uint32_t i = 5; // try 5 times only + while (esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_STA)) != ESP_OK) { + delay(1); + if (i-- == 0) { + break; + } + } + } + + // WiFi.enableIPv6(); // AddLog(LOG_LEVEL_DEBUG, PSTR("WIF: Received ARDUINO_EVENT_WIFI_STA_CONNECTED")); Wifi.ipv6_local_link_called = false; // not sure if this is needed, make sure link-local is restored at each reconnect break; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino b/tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino index 77e8c5b6a..4d76a439a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino @@ -311,7 +311,7 @@ extern "C" { ip_addr_t ip; ip_addr_set_any_val(false, ip); #ifdef USE_IPV6 - ip = (ip_addr_t)ipfull; + ipfull.to_ip_addr_t(&ip); #else ip_addr_set_ip4_u32_val(ip, (uint32_t)ipfull); #endif @@ -384,7 +384,7 @@ void PingResponsePoll(void) { ping->hostname.c_str(), success ? PSTR("true") : PSTR("false"), #ifdef USE_IPV6 - IPAddress(ping->ip).toString().c_str(), + IPAddress(&ping->ip).toString(true).c_str(), #else IPAddress(ip_addr_get_ip4_u32(&ping->ip)).toString().c_str(), #endif diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_mdns.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_mdns.ino index d9f59c756..cfa50cf73 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_mdns.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_mdns.ino @@ -239,12 +239,14 @@ extern "C" { #ifdef USE_IPV6 // - ip_addr_t *ip_addr = (ip_addr_t*) ip; - head->addr.type = ip_addr->type; - if (ip_addr->type == ESP_IPADDR_TYPE_V6) { - memcpy(head->addr.u_addr.ip6.addr, ip_addr->u_addr.ip6.addr, 16); + // ip_addr_t *ip_addr = (ip_addr_t*) ip; + ip_addr_t ip_addr; + ip.to_ip_addr_t(&ip_addr); + head->addr.type = ip_addr.type; + if (ip_addr.type == ESP_IPADDR_TYPE_V6) { + memcpy(head->addr.u_addr.ip6.addr, ip_addr.u_addr.ip6.addr, 16); } else { - head->addr.u_addr.ip4.addr = ip_addr->u_addr.ip4.addr; + head->addr.u_addr.ip4.addr = ip_addr.u_addr.ip4.addr; } #else head->addr.u_addr.ip4.addr = (uint32_t) ip; @@ -332,10 +334,11 @@ extern "C" { } else { continue; } + be_pushstring(vm, IPAddress(&ip_addr).toString(true).c_str()); #else uint32_t ip_addr = a->addr.u_addr.ip4.addr; - #endif be_pushstring(vm, IPAddress(ip_addr).toString().c_str()); + #endif be_data_push(vm, -2); be_pop(vm, 1); } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino index 3e2812c29..69341f1d3 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpclientasync.ino @@ -504,10 +504,10 @@ extern "C" { tcp->update_local_addr_port(); if (tcp->local_port > 0) { be_map_insert_int(vm, "local_port", tcp->local_port); - be_map_insert_str(vm, "local_addr", tcp->local_addr.toString().c_str()); + be_map_insert_str(vm, "local_addr", tcp->local_addr.toString(true).c_str()); } be_map_insert_int(vm, "remote_port", tcp->remotePort()); - be_map_insert_str(vm, "remote_addr", tcp->remoteIP().toString().c_str()); + be_map_insert_str(vm, "remote_addr", tcp->remoteIP().toString(true).c_str()); } be_pop(vm, 1); be_return(vm); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino index b813dddc8..969ec9bd9 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tcpserver.ino @@ -240,7 +240,7 @@ extern "C" { WiFiClient * client_ptr = nullptr; if (server_tcp->hasClient()) { WiFiClient new_client = server_tcp->available(); - AddLog(LOG_LEVEL_INFO, "BRY: Got connection from %s:%i local %s:%i", new_client.remoteIP().toString().c_str(), new_client.remotePort(), new_client.localIP().toString().c_str(), new_client.localPort()); + AddLog(LOG_LEVEL_INFO, "BRY: Got connection from %s:%i local %s:%i", new_client.remoteIP().toString(true).c_str(), new_client.remotePort(), new_client.localIP().toString().c_str(), new_client.localPort()); client_ptr = new WiFiClient(); *client_ptr = new_client; } else { @@ -254,7 +254,7 @@ extern "C" { AsyncTCPClient * client_ptr = nullptr; if (server_tcp->hasClient()) { client_ptr = server_tcp->availableAsync(); - AddLog(LOG_LEVEL_INFO, "BRY: Got connection from %s:%i local %s:%i", client_ptr->remoteIP().toString().c_str(), client_ptr->remotePort(), client_ptr->localIP().toString().c_str(), client_ptr->localPort()); + AddLog(LOG_LEVEL_INFO, "BRY: Got connection from %s:%i local %s:%i", client_ptr->remoteIP().toString(true).c_str(), client_ptr->remotePort(), client_ptr->localIP().toString().c_str(), client_ptr->localPort()); } else { be_raise(vm, "internal_error", "tcpserver has no client connected"); } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_udp.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_udp.ino index ab80735a7..0bdba475d 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_udp.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_udp.ino @@ -51,7 +51,11 @@ extern "C" { // udp.begin(interface:string, port:int) -> bool int32_t be_udp_begin_ntv(WiFiUDP *udp, const char *host, int32_t port) { +#ifdef USE_IPV6 + IPAddress addr(IPv6); +#else IPAddress addr; +#endif // if no host or host is "" then we defult to INADDR_ANY if(host && (*host != 0) && !WifiHostByName(host, addr)){ return 0; @@ -66,7 +70,11 @@ extern "C" { // udp.begin_multicast(address:string, port:int) -> nil int32_t be_udp_begin_mcast_ntv(WiFiUDP *udp, const char *host, int32_t port) { +#ifdef USE_IPV6 + IPAddress addr(IPv6); +#else IPAddress addr; +#endif if(!WifiHostByName(host, addr)){ return 0; } @@ -127,7 +135,7 @@ extern "C" { // set remotet ip IPAddress remote_ip = udp->remoteIP(); - be_pushstring(vm, remote_ip.toString().c_str()); + be_pushstring(vm, remote_ip.toString(true).c_str()); be_setmember(vm, 1, "remote_ip"); be_pop(vm, 1); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino b/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino index 8ae9c8d6a..63e1d7d51 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino @@ -85,6 +85,8 @@ char eth_hostname[sizeof(TasmotaGlobal.hostname)]; uint8_t eth_config_change; +extern esp_netif_t* get_esp_interface_netif(esp_interface_t interface); + void EthernetEvent(arduino_event_t *event); void EthernetEvent(arduino_event_t *event) { switch (event->event_id) { @@ -95,14 +97,27 @@ void EthernetEvent(arduino_event_t *event) { case ARDUINO_EVENT_ETH_CONNECTED: #ifdef USE_IPV6 - ETH.enableIpV6(); // enable Link-Local + ETH.enableIPv6(); // enable Link-Local + // workaround for the race condition in LWIP, see https://github.com/espressif/arduino-esp32/pull/9016#discussion_r1451774885 + { + uint32_t i = 5; // try 5 times only + while (esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_ETH)) != ESP_OK) { + delay(1); + if (i-- == 0) { + AddLog(LOG_LEVEL_INFO, ">>>> HELP"); + break; + } + } + AddLog(LOG_LEVEL_INFO, ">>>> ESP_IF_ETH i=%i", i); + } #endif // USE_IPV6 + AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ETH D_CONNECTED " at %dMbps%s, Mac %s, Hostname %s"), ETH.linkSpeed(), (ETH.fullDuplex()) ? " Full Duplex" : "", ETH.macAddress().c_str(), eth_hostname ); - // AddLog(LOG_LEVEL_DEBUG, D_LOG_ETH "ETH.enableIpV6() -> %i", ETH.enableIpV6()); + // AddLog(LOG_LEVEL_DEBUG, D_LOG_ETH "ETH.enableIPV6() -> %i", ETH.enableIPV6()); break; case ARDUINO_EVENT_ETH_GOT_IP: @@ -128,11 +143,11 @@ void EthernetEvent(arduino_event_t *event) { { ip_addr_t ip_addr6; ip_addr_copy_from_ip6(ip_addr6, event->event_info.got_ip6.ip6_info.ip); - IPAddress addr(ip_addr6); + IPAddress addr(&ip_addr6); AddLog(LOG_LEVEL_DEBUG, PSTR("%s: IPv6 %s %s"), event->event_id == ARDUINO_EVENT_ETH_GOT_IP6 ? "ETH" : "WIF", - addr.isLocal() ? PSTR("Local") : PSTR("Global"), addr.toString().c_str()); - if (!addr.isLocal()) { // declare network up on IPv6 + IPv6isLocal(addr) ? PSTR("Local") : PSTR("Global"), addr.toString().c_str()); + if (!IPv6isLocal(addr)) { // declare network up on IPv6 TasmotaGlobal.rules_flag.eth_connected = 1; TasmotaGlobal.global_state.eth_down = 0; } From 3daea4f8fdd1a408562b37c9b49c9d8a0f5f09ee Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 15 Jan 2024 21:57:15 +0100 Subject: [PATCH 153/303] Update change logs --- CHANGELOG.md | 3 ++- RELEASENOTES.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5f5fff3d..66d325929 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,8 @@ All notable changes to this project will be documented in this file. ### Breaking Changed ### Changed -- IP stack compatible with new Core3 IPv6 implementation () +- ESP32 platform update from 2024.01.00 to 2024.01.01 (#20508) +- IP stack compatible with new Core3 IPv6 implementation (#20509) ### Fixed - Scripter memory leak in `>w x` (#20473) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index d0afbb744..d5e4be0a8 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -157,12 +157,13 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ### Changed - ESP8266 platform update from 2023.04.00 to 2024.01.00 [#20467](https://github.com/arendst/Tasmota/issues/20467) - ESP8266 Framework (Arduino Core) from v2.7.4.9 to v2.7.5 [#20467](https://github.com/arendst/Tasmota/issues/20467) -- ESP32 platform update from 2023.11.01 to 2024.01.00 [#20445](https://github.com/arendst/Tasmota/issues/20445) +- ESP32 platform update from 2023.11.01 to 2024.01.01 [#20473](https://github.com/arendst/Tasmota/issues/20473) - Renamed button "Consoles" to "Tools" - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` [#20260](https://github.com/arendst/Tasmota/issues/20260) - Web file upload response on upload error [#20340](https://github.com/arendst/Tasmota/issues/20340) - Header `Host` is now collected by Webserver [#20446](https://github.com/arendst/Tasmota/issues/20446) - Webcam tweaks [#20451](https://github.com/arendst/Tasmota/issues/20451) +- IP stack compatible with new Core3 IPv6 implementation [#20509](https://github.com/arendst/Tasmota/issues/20509) ### Fixed - CVE-2021-36603 Cross Site Scripting (XSS) vulnerability [#12221](https://github.com/arendst/Tasmota/issues/12221) From b0b2f22e5b26b4964191eb52c63168f57b7830c6 Mon Sep 17 00:00:00 2001 From: gemu Date: Mon, 15 Jan 2024 21:58:46 +0100 Subject: [PATCH 154/303] fix display dimmer (#20491) --- lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp | 4 ++++ lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp index dbeb77601..ce1aa4603 100644 --- a/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp +++ b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp @@ -193,6 +193,10 @@ void RA8876::DisplayOnff(int8_t on) { } } +void RA8876::dim10(uint8_t contrast, uint16_t contrast_gamma) { + dim(contrast / 16); +} + // 0-15 void RA8876::dim(uint8_t contrast) { SPI.beginTransaction(m_spiSettings); diff --git a/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h index 7cf2f031b..4bf711da7 100644 --- a/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h +++ b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h @@ -26,6 +26,8 @@ #include "driver/spi_master.h" #endif +#include "tasmota_options.h" + #undef SPRINT #define SPRINT(A) {char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str);} @@ -147,10 +149,14 @@ enum ExternalFontFamily typedef uint8_t FontFlags; #define RA8876_FONT_FLAG_XLAT_FULLWIDTH 0x01 // Translate ASCII to Unicode fullwidth forms + +#ifndef RA8876_SPI_SPEED // 1MHz. TODO: Figure out actual speed to use // Data sheet section 5.2 says maximum SPI clock is 50MHz. //#define RA8876_SPI_SPEED 10000000 -#define RA8876_SPI_SPEED 25000000 +//#define RA8876_SPI_SPEED 25000000 +#define RA8876_SPI_SPEED 40000000 +#endif // With SPI, the RA8876 expects an initial byte where the top two bits are meaningful. Bit 7 // is A0, bit 6 is WR#. See data sheet section 7.3.2 and section 19. @@ -501,6 +507,7 @@ class RA8876 : public Renderer { void setDrawMode(uint8_t mode); void setDrawMode_reg(uint8_t mode); void dim(uint8_t contrast); + void dim10(uint8_t contrast, uint16_t contrast_gamma); void FastString(uint16_t x,uint16_t y,uint16_t tcolor, const char* str); private: From 5e84d57c2a443aa3346c55e16864d0cbefebc5f0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 15 Jan 2024 22:08:33 +0100 Subject: [PATCH 155/303] Fix compilation without webserver --- tasmota/tasmota_xx2c_global/xdrv_interface.ino | 2 ++ tasmota/tasmota_xx2c_global/xsns_interface.ino | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tasmota/tasmota_xx2c_global/xdrv_interface.ino b/tasmota/tasmota_xx2c_global/xdrv_interface.ino index a1dfceea9..29c53dd67 100644 --- a/tasmota/tasmota_xx2c_global/xdrv_interface.ino +++ b/tasmota/tasmota_xx2c_global/xdrv_interface.ino @@ -1147,7 +1147,9 @@ bool XdrvCall(uint32_t function) { result = xdrv_func_ptr[x](function); +#ifdef USE_WEBSERVER if (FUNC_WEB_SENSOR == function) { WSContentSeparator(1); } // Show separator if needed +#endif // USE_WEBSERVER #ifdef USE_PROFILE_FUNCTION #ifdef XFUNC_PTR_IN_ROM diff --git a/tasmota/tasmota_xx2c_global/xsns_interface.ino b/tasmota/tasmota_xx2c_global/xsns_interface.ino index 49f5311eb..3c01b39c6 100644 --- a/tasmota/tasmota_xx2c_global/xsns_interface.ino +++ b/tasmota/tasmota_xx2c_global/xsns_interface.ino @@ -1130,7 +1130,9 @@ bool XsnsCall(uint32_t function) { result = xsns_func_ptr[x](function); +#ifdef USE_WEBSERVER if (FUNC_WEB_SENSOR == function) { WSContentSeparator(1); } // Show separator if needed +#endif // USE_WEBSERVER #ifdef USE_PROFILE_FUNCTION #ifdef XFUNC_PTR_IN_ROM From 789fd1e055a3ca7da939fdc49417495797a81c50 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 15 Jan 2024 23:58:33 +0100 Subject: [PATCH 156/303] Add command ``TimedPower`` Add command ``TimedPower [,ON|OFF|TOGGLE|BLINK]`` executes ``Power [ON|OFF|TOGGLE|BLINK] `` and after executes ``Power [OFF|ON|TOGGLE|OFF]`` --- CHANGELOG.md | 1 + RELEASENOTES.md | 1 + tasmota/include/i18n.h | 1 + tasmota/include/tasmota.h | 1 + tasmota/tasmota.ino | 7 ++ tasmota/tasmota_support/support_command.ino | 80 ++++++++++++++++++++- 6 files changed, 89 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66d325929..f1ae70cce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ All notable changes to this project will be documented in this file. - ESP32 MI BLE support for Xiaomi LYWSD02MMC (#20381) - LVGL option to add `lv.keyboard` extra widget (#20496) - GUI sensor separators (#20495) +- Command ``TimedPower [,ON|OFF|TOGGLE|BLINK]`` executes ``Power [ON|OFF|TOGGLE|BLINK] `` and after executes ``Power [OFF|ON|TOGGLE|OFF]`` ### Breaking Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index d5e4be0a8..183c4adeb 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -118,6 +118,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ## Changelog v13.3.0.3 ### Added +- Command ``TimedPower [,ON|OFF|TOGGLE|BLINK]`` executes ``Power [ON|OFF|TOGGLE|BLINK] `` and after executes ``Power [OFF|ON|TOGGLE|OFF]`` - Support for CST816S touch interface [#20213](https://github.com/arendst/Tasmota/issues/20213) - Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247) - Display of active drivers using command ``status 4`` diff --git a/tasmota/include/i18n.h b/tasmota/include/i18n.h index a199861c5..e4fb16398 100644 --- a/tasmota/include/i18n.h +++ b/tasmota/include/i18n.h @@ -275,6 +275,7 @@ #define D_STATUS13_SHUTTER "SHT" #define D_CMND_STATE "State" #define D_CMND_POWER "Power" +#define D_CMND_TIMEDPOWER "TimedPower" #define D_CMND_FANSPEED "FanSpeed" #define D_CMND_POWERONSTATE "PowerOnState" #define D_CMND_PULSETIME "PulseTime" diff --git a/tasmota/include/tasmota.h b/tasmota/include/tasmota.h index 1feca3fef..b3fa0cbe4 100644 --- a/tasmota/include/tasmota.h +++ b/tasmota/include/tasmota.h @@ -222,6 +222,7 @@ const uint8_t SENSOR_MAX_MISS = 5; // Max number of missed sensor reads const uint8_t MAX_BACKLOG = 30; // Max number of commands in backlog const uint32_t MIN_BACKLOG_DELAY = 200; // Minimal backlog delay in mSeconds +const uint8_t MAX_TIMED_CMND = 16; // Max number of timed commands const uint32_t SOFT_BAUDRATE = 9600; // Default software serial baudrate const uint32_t APP_BAUDRATE = 115200; // Default serial baudrate diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 7febc7a3b..e7d4c455c 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -292,6 +292,11 @@ HardwareSerial TasConsole = Serial; // Only serial interface char EmptyStr[1] = { 0 }; // Provide a pointer destination to an empty char string +typedef struct { + uint32_t time; + String command; +} tTimedCmnd; + struct TasmotaGlobal_t { uint32_t global_update; // Timestamp of last global temperature and humidity update uint32_t baudrate; // Current Serial baudrate @@ -411,6 +416,7 @@ struct TasmotaGlobal_t { uint8_t backlog_pointer; // Command backlog pointer String backlog[MAX_BACKLOG]; // Command backlog buffer #endif + tTimedCmnd timed_cmnd[MAX_TIMED_CMND]; // Timed command buffer #ifdef MQTT_DATA_STRING String mqtt_data; // Buffer filled by Response functions @@ -851,6 +857,7 @@ void Scheduler(void) { static uint32_t state_50msecond = 0; // State 50msecond timer if (TimeReached(state_50msecond)) { SetNextTimeInterval(state_50msecond, 50); + LoopTimedCmnd(); #ifdef ROTARY_V1 RotaryHandler(); #endif // ROTARY_V1 diff --git a/tasmota/tasmota_support/support_command.ino b/tasmota/tasmota_support/support_command.ino index 2c5828786..89a5ecddd 100644 --- a/tasmota/tasmota_support/support_command.ino +++ b/tasmota/tasmota_support/support_command.ino @@ -23,7 +23,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix // Other commands D_CMND_UPGRADE "|" D_CMND_UPLOAD "|" D_CMND_OTAURL "|" D_CMND_SERIALLOG "|" D_CMND_RESTART "|" #ifndef FIRMWARE_MINIMAL_ONLY - D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_SLEEP "|" + D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_TIMEDPOWER "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_SLEEP "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|" D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SAVEDATA "|" D_CMND_SO "|" D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|" D_CMND_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_WEIGHT_RESOLUTION "|" @@ -63,7 +63,7 @@ SO_SYNONYMS(kTasmotaSynonyms, void (* const TasmotaCommand[])(void) PROGMEM = { &CmndUpgrade, &CmndUpgrade, &CmndOtaUrl, &CmndSeriallog, &CmndRestart, #ifndef FIRMWARE_MINIMAL_ONLY - &CmndBacklog, &CmndDelay, &CmndPower, &CmndStatus, &CmndState, &CmndSleep, + &CmndBacklog, &CmndDelay, &CmndPower, &CmndTimedPower, &CmndStatus, &CmndState, &CmndSleep, &CmndPowerOnState, &CmndPulsetime, &CmndBlinktime, &CmndBlinkcount, &CmndSavedata, &CmndSetoption, &CmndSetoption, &CmndTemperatureResolution, &CmndHumidityResolution, &CmndPressureResolution, &CmndPowerResolution, &CmndVoltageResolution, &CmndFrequencyResolution, &CmndCurrentResolution, &CmndEnergyResolution, &CmndWeightResolution, @@ -493,6 +493,46 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) { /********************************************************************************************/ +bool SetTimedCmnd(uint32_t time, const char *command) { + for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { + if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Free slot + TasmotaGlobal.timed_cmnd[i].time = millis() + time; + if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Skip empty slot flag + TasmotaGlobal.timed_cmnd[i].time++; + } + TasmotaGlobal.timed_cmnd[i].command = command; + return true; + } + } + AddLog(LOG_LEVEL_INFO, PSTR("TIM: No more timer slots left")); + return false; +} + +void ResetTimedCmnd(const char *command) { + for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { + if (TasmotaGlobal.timed_cmnd[i].time != 0) { + if (!strncmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str(), strlen(command))) { + TasmotaGlobal.timed_cmnd[i].time = 0; + TasmotaGlobal.timed_cmnd[i].command = (const char*) nullptr; // Force deallocation of the String internal memory + } + } + } +} + +void LoopTimedCmnd(void) { + uint32_t now = millis(); + for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { + if ((TasmotaGlobal.timed_cmnd[i].time > 0) && (now > TasmotaGlobal.timed_cmnd[i].time)) { + TasmotaGlobal.timed_cmnd[i].time = 0; + String cmd = TasmotaGlobal.timed_cmnd[i].command; + TasmotaGlobal.timed_cmnd[i].command = (const char*) nullptr; // Force deallocation of the String internal memory + ExecuteCommand((char*)cmd.c_str(), SRC_TIMER); + } + } +} + +/********************************************************************************************/ + void CmndBacklog(void) { // Backlog command1;command2;.. Execute commands in sequence with a delay in between set with SetOption34 // Backlog0 command1;command2;.. Execute commands in sequence with no delay @@ -695,6 +735,42 @@ void CmndPower(void) } } +void CmndTimedPower(void) { + /* + TimedPower [,0|1|2|3] + TimedPower0 3000 - Turn all power on and then off after 3 seconds + TimedPower1 2000 - Turn power1 on and then off after 2 seconds + TimedPower2 2000,0 - Turn power2 off and then on after 2 seconds + TimedPower1 2200,1 - Turn power1 on and then off after 2.2 seconds + TimedPower2 2000,2 - Toggle power2 and then toggle again after 2 seconds + TimedPower2 2500,3 - Blink power2 and then turn off after 2.5 seconds + */ + if ((XdrvMailbox.index >= 0) && (XdrvMailbox.index <= TasmotaGlobal.devices_present)) { + if (XdrvMailbox.data_len > 0) { + uint32_t parm[2] = { 0, 0 }; + uint32_t parms = ParseParameters(2, parm); + uint32_t time = parm[0]; + uint32_t start_state = 1; // Default on + if (2 == parms) { + start_state = parm[1] & 0x03; // 0,1,2,3 + } + const uint8_t contra_state[] = { 1, 0, 2, 0 }; + uint32_t end_state = contra_state[start_state]; + + char cmnd[32]; + snprintf_P(cmnd, sizeof(cmnd), PSTR(D_CMND_POWER "%d %d"), XdrvMailbox.index, end_state); + if (SetTimedCmnd(time, cmnd)) { + XdrvMailbox.payload = start_state; + CmndPower(); + } + } else { + // Remove all POWER timed command + ResetTimedCmnd(D_CMND_POWER); + ResponseCmndDone(); + } + } +} + void CmndStatusResponse(uint32_t index) { static String all_status = (const char*) nullptr; From 77d54985d04e30e6c736bcd0ec3d98137d86b06b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 16 Jan 2024 11:02:24 +0100 Subject: [PATCH 157/303] Tune TimedPower --- tasmota/tasmota_support/support_command.ino | 42 ++++++++++++--------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/tasmota/tasmota_support/support_command.ino b/tasmota/tasmota_support/support_command.ino index 89a5ecddd..bee4a2349 100644 --- a/tasmota/tasmota_support/support_command.ino +++ b/tasmota/tasmota_support/support_command.ino @@ -512,6 +512,7 @@ void ResetTimedCmnd(const char *command) { for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { if (TasmotaGlobal.timed_cmnd[i].time != 0) { if (!strncmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str(), strlen(command))) { + // Stored command starts with command TasmotaGlobal.timed_cmnd[i].time = 0; TasmotaGlobal.timed_cmnd[i].command = (const char*) nullptr; // Force deallocation of the String internal memory } @@ -737,35 +738,42 @@ void CmndPower(void) void CmndTimedPower(void) { /* + Allow timed power changes on a 50ms granularity TimedPower [,0|1|2|3] - TimedPower0 3000 - Turn all power on and then off after 3 seconds - TimedPower1 2000 - Turn power1 on and then off after 2 seconds - TimedPower2 2000,0 - Turn power2 off and then on after 2 seconds - TimedPower1 2200,1 - Turn power1 on and then off after 2.2 seconds - TimedPower2 2000,2 - Toggle power2 and then toggle again after 2 seconds - TimedPower2 2500,3 - Blink power2 and then turn off after 2.5 seconds + TimedPower - Clear active power timers + TimedPower 2000 - Turn power1 on and then off after 2 seconds + TimedPower1 - Clear active Power1 timers + TimedPower0 3000 - Turn all power on and then off after 3 seconds + TimedPower1 2000 - Turn power1 on and then off after 2 seconds + TimedPower2 2000,0|off - Turn power2 off and then on after 2 seconds + TimedPower1 2200,1|on - Turn power1 on and then off after 2.2 seconds + TimedPower2 2000,2|toggle - Toggle power2 and then toggle again after 2 seconds + TimedPower2 2500,3|blink - Blink power2 and then turn off after 2.5 seconds */ if ((XdrvMailbox.index >= 0) && (XdrvMailbox.index <= TasmotaGlobal.devices_present)) { if (XdrvMailbox.data_len > 0) { - uint32_t parm[2] = { 0, 0 }; + uint32_t parm[2]; uint32_t parms = ParseParameters(2, parm); - uint32_t time = parm[0]; - uint32_t start_state = 1; // Default on + uint32_t time = (parm[0] < 50) ? 50 : parm[0]; // Lowest is 50ms (state_50msecond) + uint32_t start_state = POWER_ON; // Default on if (2 == parms) { - start_state = parm[1] & 0x03; // 0,1,2,3 + start_state = parm[1] & 0x03; // POWER_OFF, POWER_ON, POWER_TOGGLE, POWER_BLINK } - const uint8_t contra_state[] = { 1, 0, 2, 0 }; - uint32_t end_state = contra_state[start_state]; - + const uint8_t end_state[] = { POWER_ON, POWER_OFF, POWER_TOGGLE, POWER_OFF }; char cmnd[32]; - snprintf_P(cmnd, sizeof(cmnd), PSTR(D_CMND_POWER "%d %d"), XdrvMailbox.index, end_state); - if (SetTimedCmnd(time, cmnd)) { + snprintf_P(cmnd, sizeof(cmnd), PSTR(D_CMND_POWER "%d %d"), XdrvMailbox.index, end_state[start_state]); + if (SetTimedCmnd(time, cmnd)) { // Skip if no more timers left (MAX_TIMED_CMND) XdrvMailbox.payload = start_state; CmndPower(); } } else { - // Remove all POWER timed command - ResetTimedCmnd(D_CMND_POWER); + if (!XdrvMailbox.usridx) { + ResetTimedCmnd(D_CMND_POWER); // Remove all POWER timed command + } else { + char cmnd[32]; + snprintf_P(cmnd, sizeof(cmnd), PSTR(D_CMND_POWER "%d"), XdrvMailbox.index); + ResetTimedCmnd(cmnd); // Remove POWER timed command + } ResponseCmndDone(); } } From 2c5508ee960bad915dad7ff00cd20f51ddebe337 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 16 Jan 2024 12:40:35 +0100 Subject: [PATCH 158/303] Add TimedPower update before end --- tasmota/tasmota_support/support_command.ino | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tasmota/tasmota_support/support_command.ino b/tasmota/tasmota_support/support_command.ino index bee4a2349..86a40ea51 100644 --- a/tasmota/tasmota_support/support_command.ino +++ b/tasmota/tasmota_support/support_command.ino @@ -494,13 +494,28 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) { /********************************************************************************************/ bool SetTimedCmnd(uint32_t time, const char *command) { + uint32_t now = millis(); + // Try to use the same slot if command is already present + for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { + if (TasmotaGlobal.timed_cmnd[i].time != 0) { + if (!strcmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str())) { + // Stored command already present + TasmotaGlobal.timed_cmnd[i].time = now + time; + if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Skip empty slot flag + TasmotaGlobal.timed_cmnd[i].time++; + } + return true; + } + } + } + // Try to find an empty slot and add command for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Free slot - TasmotaGlobal.timed_cmnd[i].time = millis() + time; + TasmotaGlobal.timed_cmnd[i].command = command; + TasmotaGlobal.timed_cmnd[i].time = now + time; if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Skip empty slot flag TasmotaGlobal.timed_cmnd[i].time++; } - TasmotaGlobal.timed_cmnd[i].command = command; return true; } } @@ -743,6 +758,7 @@ void CmndTimedPower(void) { TimedPower - Clear active power timers TimedPower 2000 - Turn power1 on and then off after 2 seconds TimedPower1 - Clear active Power1 timers + TimedPower1 0 - Stop timer and perform timed action TimedPower0 3000 - Turn all power on and then off after 3 seconds TimedPower1 2000 - Turn power1 on and then off after 2 seconds TimedPower2 2000,0|off - Turn power2 off and then on after 2 seconds From 9d00897cb4b1235773046007a64c6e125af10ff7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 16 Jan 2024 15:07:23 +0100 Subject: [PATCH 159/303] Fix TimedPower using state names --- tasmota/tasmota_support/support_command.ino | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/tasmota/tasmota_support/support_command.ino b/tasmota/tasmota_support/support_command.ino index 86a40ea51..fcc5e3725 100644 --- a/tasmota/tasmota_support/support_command.ino +++ b/tasmota/tasmota_support/support_command.ino @@ -768,15 +768,19 @@ void CmndTimedPower(void) { */ if ((XdrvMailbox.index >= 0) && (XdrvMailbox.index <= TasmotaGlobal.devices_present)) { if (XdrvMailbox.data_len > 0) { - uint32_t parm[2]; - uint32_t parms = ParseParameters(2, parm); - uint32_t time = (parm[0] < 50) ? 50 : parm[0]; // Lowest is 50ms (state_50msecond) - uint32_t start_state = POWER_ON; // Default on - if (2 == parms) { - start_state = parm[1] & 0x03; // POWER_OFF, POWER_ON, POWER_TOGGLE, POWER_BLINK + uint32_t time = (XdrvMailbox.payload < 50) ? 50 : XdrvMailbox.payload; + int start_state = POWER_ON; // Default on + if (ArgC() > 1) { + char state_text[XdrvMailbox.data_len]; + ArgV(state_text, 2); + start_state = GetStateNumber(Trim(state_text)); + if (start_state < 0) { + start_state = atoi(state_text); + } + start_state &= 0x03; // POWER_OFF, POWER_ON, POWER_TOGGLE, POWER_BLINK } const uint8_t end_state[] = { POWER_ON, POWER_OFF, POWER_TOGGLE, POWER_OFF }; - char cmnd[32]; + char cmnd[CMDSZ]; snprintf_P(cmnd, sizeof(cmnd), PSTR(D_CMND_POWER "%d %d"), XdrvMailbox.index, end_state[start_state]); if (SetTimedCmnd(time, cmnd)) { // Skip if no more timers left (MAX_TIMED_CMND) XdrvMailbox.payload = start_state; @@ -786,7 +790,7 @@ void CmndTimedPower(void) { if (!XdrvMailbox.usridx) { ResetTimedCmnd(D_CMND_POWER); // Remove all POWER timed command } else { - char cmnd[32]; + char cmnd[CMDSZ]; snprintf_P(cmnd, sizeof(cmnd), PSTR(D_CMND_POWER "%d"), XdrvMailbox.index); ResetTimedCmnd(cmnd); // Remove POWER timed command } From aa2053988a089ff8944720cccc75f43671e274c8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 16 Jan 2024 16:02:36 +0100 Subject: [PATCH 160/303] Skip slicing for Berry --- tasmota/tasmota_xx2c_global/xdrv_interface.ino | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tasmota/tasmota_xx2c_global/xdrv_interface.ino b/tasmota/tasmota_xx2c_global/xdrv_interface.ino index 29c53dd67..277ffa377 100644 --- a/tasmota/tasmota_xx2c_global/xdrv_interface.ino +++ b/tasmota/tasmota_xx2c_global/xdrv_interface.ino @@ -1148,7 +1148,18 @@ bool XdrvCall(uint32_t function) { result = xdrv_func_ptr[x](function); #ifdef USE_WEBSERVER - if (FUNC_WEB_SENSOR == function) { WSContentSeparator(1); } // Show separator if needed + if (FUNC_WEB_SENSOR == function) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t index = pgm_read_byte(kXdrvList + x); +#else + uint32_t index = kXdrvList[x]; +#endif + if (52 == index) { // Skip berry + WSContentSeparator(3); + } else { + WSContentSeparator(1); + } + } // Show separator if needed #endif // USE_WEBSERVER #ifdef USE_PROFILE_FUNCTION From 0cd3d3b003594db72a7014e819747ac436ee2008 Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Tue, 16 Jan 2024 16:14:40 +0100 Subject: [PATCH 161/303] [WebUI] Fix first line seperator (#20518) The separator (request) flag has to be cleared before starting the output of sensors/drivers to ignore previous outputs. So there will no seperator in front of the list. This only appeared, when `WebTime` is off. --- tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino index 8356f05da..a82104452 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino @@ -1492,6 +1492,7 @@ bool HandleRootStatusRefresh(void) #endif // USE_WEB_SSE WSContentSend_P(PSTR("{t}")); //
+ WSContentSeparator(3); // Reset seperator to ignore previous outputs if (Settings->web_time_end) { WSContentSend_P(PSTR("{s}" D_TIMER_TIME "{m}%s{e}"), GetDateAndTime(DT_LOCAL).substring(Settings->web_time_start, Settings->web_time_end).c_str()); WSContentSeparator(0); // Print separator From eac5c6972066ff5961000f66f19453645372f241 Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Tue, 16 Jan 2024 16:25:13 +0100 Subject: [PATCH 162/303] [SolaxX1] Adapting to multi column energy design (#20517) * [SolaxX1] Adapting to multi column energy design * [SolaxX1] optimize --- .../tasmota_xnrg_energy/xnrg_12_solaxX1.ino | 43 ++++++++----------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino b/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino index 5945cf1f6..f74b59b5a 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino @@ -2,7 +2,7 @@ xnrg_12_solaxX1.ino - Solax X1 inverter RS485 support for Tasmota Copyright (C) 2021 by Pablo Zerón - Copyright (C) 2023 by Stefan Wershoven + Copyright (C) 2024 by Stefan Wershoven 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 @@ -514,22 +514,8 @@ bool SolaxX1_cmd(void) } #ifdef USE_WEBSERVER -const char HTTP_SNS_solaxX1_DATA1[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_SOLAR_POWER "{m}%s " D_UNIT_WATT "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_POWER "{m}%s " D_UNIT_WATT "{e}"; -#ifdef SOLAXX1_PV2 -const char HTTP_SNS_solaxX1_DATA2[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_PV2_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}" D_SOLAX_X1 " " D_PV2_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_SOLAX_X1 " " D_PV2_POWER "{m}%s " D_UNIT_WATT "{e}"; -#endif -const char HTTP_SNS_solaxX1_DATA3[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_UPTIME "{m}%d " D_UNIT_HOUR "{e}" - "{s}" D_SOLAX_X1 " " D_STATUS "{m}%s" - "{s}" D_SOLAX_X1 " " D_ERROR "{m}%s" - "{s}" D_SOLAX_X1 " Inverter SN{m}%s"; +const char HTTP_SNS_solaxX1_Num[] PROGMEM = "{s}" D_SOLAX_X1 " %s{m}
%s  %s{e}"; +const char HTTP_SNS_solaxX1_Str[] PROGMEM = "{s}" D_SOLAX_X1 " %s{m}%s{e}"; #endif // USE_WEBSERVER void solaxX1_Show(bool json) @@ -570,15 +556,24 @@ void solaxX1_Show(bool json) #ifdef USE_WEBSERVER } else { - WSContentSend_PD(HTTP_SNS_solaxX1_DATA1, solar_power, pv1_voltage, pv1_current, pv1_power); + String table_align = Settings->flag5.gui_table_align?"right":"left"; + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_SOLAR_POWER, table_align.c_str(), solar_power, D_UNIT_WATT); + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV1_VOLTAGE, table_align.c_str(), pv1_voltage, D_UNIT_VOLT); + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV1_CURRENT, table_align.c_str(), pv1_current, D_UNIT_AMPERE); + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV1_POWER, table_align.c_str(), pv1_power, D_UNIT_WATT); #ifdef SOLAXX1_PV2 - WSContentSend_PD(HTTP_SNS_solaxX1_DATA2, pv2_voltage, pv2_current, pv2_power); + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV2_VOLTAGE, table_align.c_str(), pv2_voltage, D_UNIT_VOLT); + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV2_CURRENT, table_align.c_str(), pv2_current, D_UNIT_AMPERE); + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV2_POWER, table_align.c_str(), pv2_power, D_UNIT_WATT); #endif - WSContentSend_Temp(D_SOLAX_X1, solaxX1.temperature); + char SXTemperature[16]; + dtostrfd(solaxX1.temperature, Settings->flag2.temperature_resolution, SXTemperature); + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_TEMPERATURE, table_align.c_str(), SXTemperature, D_UNIT_DEGREE D_UNIT_CELSIUS); + WSContentSend_P(HTTP_SNS_solaxX1_Num, D_UPTIME, table_align.c_str(), String(solaxX1.runtime_total).c_str(), D_UNIT_HOUR); + WSContentSend_P(HTTP_SNS_solaxX1_Str, D_STATUS, table_align.c_str(), status); char errorCodeString[33]; - WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, solaxX1.runtime_total, status, - GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError), - solaxX1.SerialNumber); + WSContentSend_P(HTTP_SNS_solaxX1_Str, D_ERROR, table_align.c_str(), GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError)); + WSContentSend_P(HTTP_SNS_solaxX1_Str, "Inverter SN", table_align.c_str(), solaxX1.SerialNumber); #endif // USE_WEBSERVER } } @@ -599,7 +594,7 @@ bool Xnrg12(uint32_t function) solaxX1_Show(1); break; #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: + case FUNC_WEB_COL_SENSOR: solaxX1_Show(0); break; #endif // USE_WEBSERVER From 0ac559bf7f304717e546a48ddcc33b0ac29d5038 Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Tue, 16 Jan 2024 16:35:19 +0100 Subject: [PATCH 163/303] [Shutter] Fix html table syntax (#20519) * [Shutter] Fix html table syntax The html code for the slider was placed in a `` but not fenced with `` / ` -const char HTTP_SNS_HR[] PROGMEM = " -const char HTTP_SNS_HR[] PROGMEM = ""; +const char HTTP_SNS_HR_THIN[] PROGMEM = ""; const char HTTP_SNS_F_TEMP[] PROGMEM = "{s}%s " D_TEMPERATURE "{m}%*_f " D_UNIT_DEGREE "%c{e}"; const char HTTP_SNS_F_VOLTAGE[] PROGMEM = "{s}%s " D_VOLTAGE "{m}%*_f " D_UNIT_VOLT "{e}"; const char HTTP_SNS_F_CURRENT_MA[] PROGMEM = "{s}%s " D_CURRENT "{m}%*_f " D_UNIT_MILLIAMPERE "{e}"; From c705c8f89c875b2f54e2a4c853c654be2a5f57fb Mon Sep 17 00:00:00 2001 From: stefanbode Date: Wed, 17 Jan 2024 10:03:42 +0100 Subject: [PATCH 167/303] Fixed DIV/0 (#20524) --- tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino b/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino index 06e5e8a3e..0a617123c 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino @@ -687,7 +687,7 @@ void ShutterInit(void) Shutter[i].min_realPositionChange = 0; break; case SHT_COUNTER: - Shutter[i].min_realPositionChange = SHT_DIV_ROUND(Shutter[i].min_realPositionChange, Shutter[i].motordelay); + Shutter[i].min_realPositionChange = SHT_DIV_ROUND(Shutter[i].min_realPositionChange, Shutter[i].motordelay > 0?Shutter[i].motordelay : 1); break; } From 12ef60a3dfae350384d518538831066d8d477d80 Mon Sep 17 00:00:00 2001 From: Simon Post <2239283+postsi@users.noreply.github.com> Date: Wed, 17 Jan 2024 12:24:43 +0000 Subject: [PATCH 168/303] Modification of convert.py and preprocessor.py to add tabview, list and tileview. Plus fix lv.keyboard enum error (#20513) * Modification of convert.py and preprocessor.py to add tabview, list and tileview. Plus fix lv.keyboard enum error * Amended my_user_config.h per request --------- Co-authored-by: Simon Post --- .../generate/be_lv_c_mapping.h | 55 +++++++++++++++++ .../generate/be_lvgl_module.c | 8 +++ .../generate/be_lvgl_widgets_lib.c | 61 +++++++++++++++++++ .../lv_binding_berry/mapping/lv_enum.h | 8 +++ .../lv_binding_berry/mapping/lv_funcs.h | 22 +++++++ .../lv_binding_berry/tools/convert.py | 2 +- .../lv_binding_berry/tools/preprocessor.py | 5 +- tasmota/my_user_config.h | 3 + 8 files changed, 162 insertions(+), 2 deletions(-) diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h index be71581c1..c880b3918 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h @@ -529,6 +529,8 @@ const be_ntv_func_def_t lv_obj_func[] = { { "set_style_width", { (const void*) &lv_obj_set_style_width, "", "(lv.lv_obj)ii" } }, { "set_style_x", { (const void*) &lv_obj_set_style_x, "", "(lv.lv_obj)ii" } }, { "set_style_y", { (const void*) &lv_obj_set_style_y, "", "(lv.lv_obj)ii" } }, + { "set_tile", { (const void*) &lv_obj_set_tile, "", "(lv.lv_obj)(lv.lv_obj)i" } }, + { "set_tile_id", { (const void*) &lv_obj_set_tile_id, "", "(lv.lv_obj)iii" } }, { "set_user_data", { (const void*) &lv_obj_set_user_data, "", "(lv.lv_obj)." } }, { "set_width", { (const void*) &lv_obj_set_width, "", "(lv.lv_obj)i" } }, { "set_x", { (const void*) &lv_obj_set_x, "", "(lv.lv_obj)i" } }, @@ -704,6 +706,15 @@ const be_ntv_func_def_t lv_led_func[] = { }; #endif // BE_LV_WIDGET_LED +/* `lv_list` methods */ +#ifdef BE_LV_WIDGET_LIST +const be_ntv_func_def_t lv_list_func[] = { + { "add_btn", { (const void*) &lv_list_add_btn, "lv.lv_obj", "(lv.lv_obj).s" } }, + { "add_text", { (const void*) &lv_list_add_text, "lv.lv_obj", "(lv.lv_obj)s" } }, + { "get_btn_text", { (const void*) &lv_list_get_btn_text, "s", "(lv.lv_obj)(lv.lv_obj)" } }, +}; +#endif // BE_LV_WIDGET_LIST + /* `lv_meter` methods */ #ifdef BE_LV_WIDGET_METER const be_ntv_func_def_t lv_meter_func[] = { @@ -762,6 +773,26 @@ const be_ntv_func_def_t lv_spinner_func[] = { }; #endif // BE_LV_WIDGET_SPINNER +/* `lv_tabview` methods */ +#ifdef BE_LV_WIDGET_TABVIEW +const be_ntv_func_def_t lv_tabview_func[] = { + { "add_tab", { (const void*) &lv_tabview_add_tab, "lv.lv_obj", "(lv.lv_obj)s" } }, + { "get_content", { (const void*) &lv_tabview_get_content, "lv.lv_obj", "(lv.lv_obj)" } }, + { "get_tab_act", { (const void*) &lv_tabview_get_tab_act, "i", "(lv.lv_obj)" } }, + { "get_tab_btns", { (const void*) &lv_tabview_get_tab_btns, "lv.lv_obj", "(lv.lv_obj)" } }, + { "rename_tab", { (const void*) &lv_tabview_rename_tab, "", "(lv.lv_obj)is" } }, + { "set_act", { (const void*) &lv_tabview_set_act, "", "(lv.lv_obj)ii" } }, +}; +#endif // BE_LV_WIDGET_TABVIEW + +/* `lv_tileview` methods */ +#ifdef BE_LV_WIDGET_TILEVIEW +const be_ntv_func_def_t lv_tileview_func[] = { + { "add_tile", { (const void*) &lv_tileview_add_tile, "lv.lv_obj", "(lv.lv_obj)iii" } }, + { "get_tile_act", { (const void*) &lv_tileview_get_tile_act, "lv.lv_obj", "(lv.lv_obj)" } }, +}; +#endif // BE_LV_WIDGET_TILEVIEW + /* `lv_anim` methods */ const be_ntv_func_def_t lv_anim_func[] = { { "custom_del", { (const void*) &lv_anim_custom_del, "b", "(lv.lv_anim)c" } }, @@ -1062,6 +1093,7 @@ extern const bclass be_class_lv_keyboard; extern const bclass be_class_lv_label; extern const bclass be_class_lv_led; extern const bclass be_class_lv_line; +extern const bclass be_class_lv_list; extern const bclass be_class_lv_meter; extern const bclass be_class_lv_msgbox; extern const bclass be_class_lv_obj; @@ -1073,8 +1105,10 @@ extern const bclass be_class_lv_spinner; extern const bclass be_class_lv_style; extern const bclass be_class_lv_switch; extern const bclass be_class_lv_table; +extern const bclass be_class_lv_tabview; extern const bclass be_class_lv_textarea; extern const bclass be_class_lv_theme; +extern const bclass be_class_lv_tileview; extern const bclass be_class_lv_timer; @@ -1131,6 +1165,9 @@ const be_ntv_class_def_t lv_classes[] = { #ifdef BE_LV_WIDGET_LINE { "lv_line", &be_class_lv_line, lv_line_func, sizeof(lv_line_func) / sizeof(lv_line_func[0]) }, #endif // BE_LV_WIDGET_LINE +#ifdef BE_LV_WIDGET_LIST + { "lv_list", &be_class_lv_list, lv_list_func, sizeof(lv_list_func) / sizeof(lv_list_func[0]) }, +#endif // BE_LV_WIDGET_LIST #ifdef BE_LV_WIDGET_METER { "lv_meter", &be_class_lv_meter, lv_meter_func, sizeof(lv_meter_func) / sizeof(lv_meter_func[0]) }, #endif // BE_LV_WIDGET_METER @@ -1160,10 +1197,16 @@ const be_ntv_class_def_t lv_classes[] = { #ifdef BE_LV_WIDGET_TABLE { "lv_table", &be_class_lv_table, lv_table_func, sizeof(lv_table_func) / sizeof(lv_table_func[0]) }, #endif // BE_LV_WIDGET_TABLE +#ifdef BE_LV_WIDGET_TABVIEW + { "lv_tabview", &be_class_lv_tabview, lv_tabview_func, sizeof(lv_tabview_func) / sizeof(lv_tabview_func[0]) }, +#endif // BE_LV_WIDGET_TABVIEW #ifdef BE_LV_WIDGET_TEXTAREA { "lv_textarea", &be_class_lv_textarea, lv_textarea_func, sizeof(lv_textarea_func) / sizeof(lv_textarea_func[0]) }, #endif // BE_LV_WIDGET_TEXTAREA { "lv_theme", &be_class_lv_theme, lv_theme_func, sizeof(lv_theme_func) / sizeof(lv_theme_func[0]) }, +#ifdef BE_LV_WIDGET_TILEVIEW + { "lv_tileview", &be_class_lv_tileview, lv_tileview_func, sizeof(lv_tileview_func) / sizeof(lv_tileview_func[0]) }, +#endif // BE_LV_WIDGET_TILEVIEW { "lv_timer", &be_class_lv_timer, lv_timer_func, sizeof(lv_timer_func) / sizeof(lv_timer_func[0]) }, }; const size_t lv_classes_size = sizeof(lv_classes) / sizeof(lv_classes[0]); @@ -1210,6 +1253,10 @@ const size_t lv_classes_size = sizeof(lv_classes) / sizeof(lv_classes[0]); #ifdef BE_LV_WIDGET_LED int be_ntv_lv_led_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_led_create, "+_p", "(lv.lv_obj)"); } #endif // BE_LV_WIDGET_LED + /* `lv_list` methods */ +#ifdef BE_LV_WIDGET_LIST + int be_ntv_lv_list_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_list_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_LIST /* `lv_meter` methods */ #ifdef BE_LV_WIDGET_METER int be_ntv_lv_meter_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_meter_create, "+_p", "(lv.lv_obj)"); } @@ -1226,6 +1273,14 @@ const size_t lv_classes_size = sizeof(lv_classes) / sizeof(lv_classes[0]); #ifdef BE_LV_WIDGET_SPINNER int be_ntv_lv_spinner_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_spinner_create, "+_p", "(lv.lv_obj)ii"); } #endif // BE_LV_WIDGET_SPINNER + /* `lv_tabview` methods */ +#ifdef BE_LV_WIDGET_TABVIEW + int be_ntv_lv_tabview_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_tabview_create, "+_p", "(lv.lv_obj)ii"); } +#endif // BE_LV_WIDGET_TABVIEW + /* `lv_tileview` methods */ +#ifdef BE_LV_WIDGET_TILEVIEW + int be_ntv_lv_tileview_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_tileview_create, "+_p", "(lv.lv_obj)"); } +#endif // BE_LV_WIDGET_TILEVIEW /* `lv_anim` methods */ /* `lv_timer` methods */ /* `lv_arc` methods */ diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c index db62ac304..e040b1212 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c @@ -483,6 +483,14 @@ const be_const_member_t lv0_constants[] = { { "INDEV_TYPE_KEYPAD", be_cconst_int(LV_INDEV_TYPE_KEYPAD) }, { "INDEV_TYPE_NONE", be_cconst_int(LV_INDEV_TYPE_NONE) }, { "INDEV_TYPE_POINTER", be_cconst_int(LV_INDEV_TYPE_POINTER) }, + { "KEYBOARD_MODE_NUMBER", be_cconst_int(LV_KEYBOARD_MODE_NUMBER) }, + { "KEYBOARD_MODE_SPECIAL", be_cconst_int(LV_KEYBOARD_MODE_SPECIAL) }, + { "KEYBOARD_MODE_TEXT_LOWER", be_cconst_int(LV_KEYBOARD_MODE_TEXT_LOWER) }, + { "KEYBOARD_MODE_TEXT_UPPER", be_cconst_int(LV_KEYBOARD_MODE_TEXT_UPPER) }, + { "KEYBOARD_MODE_USER_1", be_cconst_int(LV_KEYBOARD_MODE_USER_1) }, + { "KEYBOARD_MODE_USER_2", be_cconst_int(LV_KEYBOARD_MODE_USER_2) }, + { "KEYBOARD_MODE_USER_3", be_cconst_int(LV_KEYBOARD_MODE_USER_3) }, + { "KEYBOARD_MODE_USER_4", be_cconst_int(LV_KEYBOARD_MODE_USER_4) }, { "KEY_BACKSPACE", be_cconst_int(LV_KEY_BACKSPACE) }, { "KEY_DEL", be_cconst_int(LV_KEY_DEL) }, { "KEY_DOWN", be_cconst_int(LV_KEY_DOWN) }, diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c index 52a75bb5c..3a734f566 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c @@ -541,6 +541,8 @@ extern int lvbe_obj_get_style_grid_cell_row_pos(bvm *vm); extern int lvbe_obj_get_style_grid_cell_row_span(bvm *vm); extern int lvbe_obj_get_style_grid_cell_x_align(bvm *vm); extern int lvbe_obj_get_style_grid_cell_y_align(bvm *vm); +extern int lvbe_obj_set_tile(bvm *vm); +extern int lvbe_obj_set_tile_id(bvm *vm); extern int lvbe_obj_move_foreground(bvm *vm); extern int lvbe_obj_move_background(bvm *vm); extern int lvbe_obj_get_child_id(bvm *vm); @@ -685,6 +687,12 @@ extern int lvbe_led_off(bvm *vm); extern int lvbe_led_toggle(bvm *vm); extern int lvbe_led_get_brightness(bvm *vm); +/* `lv_list` external functions definitions */ +extern int lvbe_list_create(bvm *vm); +extern int lvbe_list_add_text(bvm *vm); +extern int lvbe_list_add_btn(bvm *vm); +extern int lvbe_list_get_btn_text(bvm *vm); + /* `lv_meter` external functions definitions */ extern int lvbe_meter_create(bvm *vm); extern int lvbe_meter_add_scale(bvm *vm); @@ -731,6 +739,20 @@ extern int lvbe_spinbox_decrement(bvm *vm); /* `lv_spinner` external functions definitions */ extern int lvbe_spinner_create(bvm *vm); +/* `lv_tabview` external functions definitions */ +extern int lvbe_tabview_create(bvm *vm); +extern int lvbe_tabview_add_tab(bvm *vm); +extern int lvbe_tabview_rename_tab(bvm *vm); +extern int lvbe_tabview_get_content(bvm *vm); +extern int lvbe_tabview_get_tab_btns(bvm *vm); +extern int lvbe_tabview_set_act(bvm *vm); +extern int lvbe_tabview_get_tab_act(bvm *vm); + +/* `lv_tileview` external functions definitions */ +extern int lvbe_tileview_create(bvm *vm); +extern int lvbe_tileview_add_tile(bvm *vm); +extern int lvbe_tileview_get_tile_act(bvm *vm); + /* `lv_anim` external functions definitions */ extern int lvbe_anim_init(bvm *vm); extern int lvbe_anim_set_var(bvm *vm); @@ -983,10 +1005,13 @@ extern int be_ntv_lv_imgbtn_init(bvm *vm); extern int be_ntv_lv_keyboard_init(bvm *vm); extern int be_ntv_lv_btnmatrix_init(bvm *vm); extern int be_ntv_lv_led_init(bvm *vm); +extern int be_ntv_lv_list_init(bvm *vm); extern int be_ntv_lv_meter_init(bvm *vm); extern int be_ntv_lv_msgbox_init(bvm *vm); extern int be_ntv_lv_spinbox_init(bvm *vm); extern int be_ntv_lv_spinner_init(bvm *vm); +extern int be_ntv_lv_tabview_init(bvm *vm); +extern int be_ntv_lv_tileview_init(bvm *vm); extern int be_ntv_lv_anim_init(bvm *vm); extern int be_ntv_lv_timer_init(bvm *vm); extern int be_ntv_lv_arc_init(bvm *vm); @@ -1024,6 +1049,7 @@ extern const bclass be_class_lv_keyboard; extern const bclass be_class_lv_label; extern const bclass be_class_lv_led; extern const bclass be_class_lv_line; +extern const bclass be_class_lv_list; extern const bclass be_class_lv_meter; extern const bclass be_class_lv_msgbox; extern const bclass be_class_lv_obj; @@ -1035,8 +1061,10 @@ extern const bclass be_class_lv_spinner; extern const bclass be_class_lv_style; extern const bclass be_class_lv_switch; extern const bclass be_class_lv_table; +extern const bclass be_class_lv_tabview; extern const bclass be_class_lv_textarea; extern const bclass be_class_lv_theme; +extern const bclass be_class_lv_tileview; extern const bclass be_class_lv_timer; @@ -1262,6 +1290,17 @@ class be_class_lv_led (scope: global, name: lv_led, super: be_class_lv_obj, stri } @const_object_info_end */ +/******************************************************************** +** Solidified class: lv_list +********************************************************************/ +#include "be_fixed_be_class_lv_list.h" +/* @const_object_info_begin +class be_class_lv_list (scope: global, name: lv_list, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_list_class) + init, func(be_ntv_lv_list_init) +} +@const_object_info_end */ + /******************************************************************** ** Solidified class: lv_meter ********************************************************************/ @@ -1308,6 +1347,28 @@ class be_class_lv_spinner (scope: global, name: lv_spinner, super: be_class_lv_a } @const_object_info_end */ +/******************************************************************** +** Solidified class: lv_tabview +********************************************************************/ +#include "be_fixed_be_class_lv_tabview.h" +/* @const_object_info_begin +class be_class_lv_tabview (scope: global, name: lv_tabview, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_tabview_class) + init, func(be_ntv_lv_tabview_init) +} +@const_object_info_end */ + +/******************************************************************** +** Solidified class: lv_tileview +********************************************************************/ +#include "be_fixed_be_class_lv_tileview.h" +/* @const_object_info_begin +class be_class_lv_tileview (scope: global, name: lv_tileview, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_tileview_class) + init, func(be_ntv_lv_tileview_init) +} +@const_object_info_end */ + /******************************************************************** ** Solidified class: lv_arc ********************************************************************/ diff --git a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h index e2c60d4e4..8828e0c3e 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h +++ b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h @@ -433,6 +433,14 @@ LV_IMGBTN_STATE_CHECKED_PRESSED LV_IMGBTN_STATE_CHECKED_DISABLED // File: ../../lvgl/src/extra/widgets/keyboard/lv_keyboard.h +LV_KEYBOARD_MODE_TEXT_LOWER +LV_KEYBOARD_MODE_TEXT_UPPER +LV_KEYBOARD_MODE_SPECIAL +LV_KEYBOARD_MODE_NUMBER +LV_KEYBOARD_MODE_USER_1 +LV_KEYBOARD_MODE_USER_2 +LV_KEYBOARD_MODE_USER_3 +LV_KEYBOARD_MODE_USER_4 // File: ../../lvgl/src/extra/widgets/led/lv_led.h LV_LED_DRAW_PART_RECTANGLE diff --git a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h index 1aa1e61c0..edfa2f4f5 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h +++ b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h @@ -687,6 +687,12 @@ void lv_led_off(lv_obj_t * led) void lv_led_toggle(lv_obj_t * led) uint8_t lv_led_get_brightness(const lv_obj_t * obj) +// ../../lvgl/src/extra/widgets/list/lv_list.h +lv_obj_t * lv_list_create(lv_obj_t * parent) +lv_obj_t * lv_list_add_text(lv_obj_t * list, const char * txt) +lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * icon, const char * txt) +const char * lv_list_get_btn_text(lv_obj_t * list, lv_obj_t * btn) + // ../../lvgl/src/extra/widgets/meter/lv_meter.h lv_obj_t * lv_meter_create(lv_obj_t * parent) lv_meter_scale_t * lv_meter_add_scale(lv_obj_t * obj) @@ -733,6 +739,22 @@ void lv_spinbox_decrement(lv_obj_t * obj) // ../../lvgl/src/extra/widgets/spinner/lv_spinner.h lv_obj_t * lv_spinner_create(lv_obj_t * parent, uint32_t time, uint32_t arc_length) +// ../../lvgl/src/extra/widgets/tabview/lv_tabview.h +lv_obj_t * lv_tabview_create(lv_obj_t * parent, lv_dir_t tab_pos, lv_coord_t tab_size) +lv_obj_t * lv_tabview_add_tab(lv_obj_t * tv, const char * name) +void lv_tabview_rename_tab(lv_obj_t * obj, uint32_t tab_id, const char * new_name) +lv_obj_t * lv_tabview_get_content(lv_obj_t * tv) +lv_obj_t * lv_tabview_get_tab_btns(lv_obj_t * tv) +void lv_tabview_set_act(lv_obj_t * obj, uint32_t id, lv_anim_enable_t anim_en) +uint16_t lv_tabview_get_tab_act(lv_obj_t * tv) + +// ../../lvgl/src/extra/widgets/tileview/lv_tileview.h +lv_obj_t * lv_tileview_create(lv_obj_t * parent) +lv_obj_t * lv_tileview_add_tile(lv_obj_t * tv, uint8_t col_id, uint8_t row_id, lv_dir_t dir) +void lv_obj_set_tile(lv_obj_t * tv, lv_obj_t * tile_obj, lv_anim_enable_t anim_en) +void lv_obj_set_tile_id(lv_obj_t * tv, uint32_t col_id, uint32_t row_id, lv_anim_enable_t anim_en) +lv_obj_t * lv_tileview_get_tile_act(lv_obj_t * obj) + // ../../lvgl/src/font/lv_font.h const uint8_t * lv_font_get_glyph_bitmap(const lv_font_t * font_p, uint32_t letter) bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_out, uint32_t letter, uint32_t letter_next) diff --git a/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py b/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py index 80ea5f579..2820a7682 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py +++ b/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py @@ -204,7 +204,7 @@ lv_widgets = ['arc', 'bar', 'btn', 'btnmatrix', 'canvas', 'checkbox', 'dropdown', 'img', 'label', 'line', 'roller', 'slider', 'switch', 'table', 'textarea' ] # extra widgets -lv_widgets = lv_widgets + [ 'chart', 'colorwheel', 'imgbtn', 'led', 'meter', 'msgbox', 'spinbox', 'spinner', 'keyboard' ] +lv_widgets = lv_widgets + [ 'chart', 'colorwheel', 'imgbtn', 'led', 'meter', 'msgbox', 'spinbox', 'spinner', 'keyboard' , 'tabview', 'tileview' , 'list'] # add qrcode lv_widgets = lv_widgets + [ 'qrcode' ] diff --git a/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py b/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py index 4fc489daf..356768783 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py +++ b/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py @@ -62,6 +62,9 @@ lv_fun_globs = [ "extra/widgets/spinbox/*.h", "extra/widgets/spinner/*.h", "extra/widgets/keyboard/*.h", + "extra/widgets/tabview/*.h", + "extra/widgets/tileview/*.h", + "extra/widgets/list/*.h", "extra/themes/default/*.h", "extra/themes/mono/*.h", "extra/layouts/**/*.h", @@ -341,7 +344,7 @@ for header_name in headers_names: # item is ready exclude = False for exclude_prefix in ["_", "LV_BIDI_DIR_", "LV_FONT_", "LV_IMG_CF_RESERVED_", "LV_IMG_CF_USER_", - "LV_SIGNAL_", "LV_TEMPL_", "LV_TASK_PRIO_", "LV_THEME_", "LV_KEYBOARD_", + "LV_SIGNAL_", "LV_TEMPL_", "LV_TASK_PRIO_", "LV_THEME_", "LV_LRU_"]: if enum_item.startswith(exclude_prefix): exclude = True if exclude: continue diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index c93bfe9cc..d74edd0cb 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -1208,6 +1208,9 @@ #define BE_LV_WIDGET_SPINBOX #define BE_LV_WIDGET_SPINNER // #define BE_LV_WIDGET_KEYBOARD + // #define BE_LV_WIDGET_TABVIEW + // #define BE_LV_WIDGET_TILEVIEW + // #define BE_LV_WIDGET_LIST #define BE_LV_WIDGET_QRCODE From 2832ed914bbd57b16820f5c3ffd469862bda58f5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 17 Jan 2024 15:55:25 +0100 Subject: [PATCH 169/303] Change command ``TimedPower`` Change command ``TimedPower`` from erasing all timers to showing remaining timers --- CHANGELOG.md | 2 ++ RELEASENOTES.md | 1 + tasmota/tasmota_support/support_command.ino | 27 +++++++++++++++++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1ae70cce..9b76fb816 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ All notable changes to this project will be documented in this file. ### Changed - ESP32 platform update from 2024.01.00 to 2024.01.01 (#20508) - IP stack compatible with new Core3 IPv6 implementation (#20509) +- Command ``TimedPower`` from erasing all timers to showing remaining timers ### Fixed - Scripter memory leak in `>w x` (#20473) @@ -27,6 +28,7 @@ All notable changes to this project will be documented in this file. - GPIO Viewer single instance - Zigbee ramdom crash in main page (#20481) - Web file upload response on upload error (#20340) +- ESP32 shutter exception 6 (divide by zero) on ``ShutterMode 4`` (#20524) ### Removed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 183c4adeb..9d1d594a4 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -173,6 +173,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Scripter memory leak in `>w x` (#20473)[#20473](https://github.com/arendst/Tasmota/issues/20473) - Zigbee ramdom crash in main page (#20481)[#20473](https://github.com/arendst/Tasmota/issues/20481) - ESP32 piezo ceramic buzzer doesn't buzz [#20118](https://github.com/arendst/Tasmota/issues/20118) +- ESP32 shutter exception 6 (divide by zero) on ``ShutterMode 4`` [#20524](https://github.com/arendst/Tasmota/issues/20524) - ESP32 Zigbee Aqara attributes [#20452](https://github.com/arendst/Tasmota/issues/20452) - LVGL fix type for lv_imgbtn [#20354](https://github.com/arendst/Tasmota/issues/20354) - Berry claiming UART0 if needed [#20324](https://github.com/arendst/Tasmota/issues/20324) diff --git a/tasmota/tasmota_support/support_command.ino b/tasmota/tasmota_support/support_command.ino index fcc5e3725..cefea6cb3 100644 --- a/tasmota/tasmota_support/support_command.ino +++ b/tasmota/tasmota_support/support_command.ino @@ -535,6 +535,27 @@ void ResetTimedCmnd(const char *command) { } } +void ShowTimedCmnd(const char *command) { + bool found = false; + uint32_t now = millis(); + Response_P(PSTR("{\"%s\":"), XdrvMailbox.command); + for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { + if (TasmotaGlobal.timed_cmnd[i].time != 0) { + if (!strncmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str(), strlen(command))) { + // Stored command starts with command + ResponseAppend_P(PSTR("%s"), (found) ? "," : "["); + found = true; + ResponseAppend_P(PSTR("{\"" D_JSON_REMAINING "\":%d,\"" D_JSON_COMMAND "\":\"%s\"}"), TasmotaGlobal.timed_cmnd[i].time - now, TasmotaGlobal.timed_cmnd[i].command.c_str()); + } + } + } + if (found) { + ResponseAppend_P(PSTR("]}")); + } else { + ResponseAppend_P(PSTR("\"" D_JSON_EMPTY "\"}")); + } +} + void LoopTimedCmnd(void) { uint32_t now = millis(); for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { @@ -755,7 +776,7 @@ void CmndTimedPower(void) { /* Allow timed power changes on a 50ms granularity TimedPower [,0|1|2|3] - TimedPower - Clear active power timers + TimedPower - Show remaining timers TimedPower 2000 - Turn power1 on and then off after 2 seconds TimedPower1 - Clear active Power1 timers TimedPower1 0 - Stop timer and perform timed action @@ -788,7 +809,9 @@ void CmndTimedPower(void) { } } else { if (!XdrvMailbox.usridx) { - ResetTimedCmnd(D_CMND_POWER); // Remove all POWER timed command +// ResetTimedCmnd(D_CMND_POWER); // Remove all POWER timed command + ShowTimedCmnd(D_CMND_POWER); // Show remaining timers + return; } else { char cmnd[CMDSZ]; snprintf_P(cmnd, sizeof(cmnd), PSTR(D_CMND_POWER "%d"), XdrvMailbox.index); From 9d86ac88166ca8f0e29b5626568499ea42929b25 Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Wed, 17 Jan 2024 17:11:41 +0100 Subject: [PATCH 170/303] Rename "Konsolen" to "Werkzeuge" (#20523) * Rename "Konsolen" to "Tools" * Rename "Konsolen" to "Werkzeuge" --- tasmota/language/de_DE.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index f19c601bc..44ea49961 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -275,7 +275,7 @@ #define D_CONFIGURATION "Einstellungen" #define D_INFORMATION "Informationen" #define D_FIRMWARE_UPGRADE "Firmware Update" -#define D_MANAGEMENT "Konsolen" +#define D_MANAGEMENT "Werkzeuge" #define D_GPIO_VIEWER "GPIO Viewer" #define D_CONSOLE "Konsole" #define D_CONFIRM_RESTART "Wirklich neustarten?" From f28c9b6ea9ace995f036dc376f718be80457d204 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 17 Jan 2024 18:17:46 +0100 Subject: [PATCH 171/303] Slicing GUI information --- .../xdrv_01_9_webserver.ino | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino index a82104452..4bb006d75 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino @@ -2373,8 +2373,24 @@ void HandleRestoreConfiguration(void) #ifndef FIRMWARE_MINIMAL_ONLY -void HandleInformation(void) -{ +void WSContentSeparatorI(uint32_t size) { + WSContentSend_P(PSTR(" gets the `valign' attribute, not
` tags. So the browser placed it "randomly" outside of the table. * [Shutter] revert date --- tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino b/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino index 7bf8b4563..dfba0caab 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino @@ -1,7 +1,7 @@ /* xdrv_27_Shutter.ino - Shutter/Blind support for Tasmota - Copyright (C) 2023 Stefan Bode + Copyright (C) 2023 Stefan Bode 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 @@ -54,8 +54,10 @@ int32_t current_real_position = 0; int32_t current_pwm_velocity = 0; const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM = + "
" "
%s%s
" - "
"; + "
" + "{e}"; const uint8_t MAX_MODES = 8; enum Shutterposition_mode {SHT_UNDEF, SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,SHT_AUTOCONFIG}; From c15ad066d08a6b48e9c453d5c7947ca345655730 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 16 Jan 2024 16:40:57 +0100 Subject: [PATCH 164/303] Sync shutter drivers --- tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino b/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino index c40832657..06e5e8a3e 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino @@ -46,8 +46,10 @@ #define D_ERROR_FILE_NOT_FOUND "SHT: ERROR File system not ready or file not found" const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM = + "
" "
%s%s
" - "
"; + "
" + "{e}"; const uint16_t SHUTTER_VERSION = 0x0100; // Latest driver version (See settings deltas below) @@ -1162,6 +1164,7 @@ void ShutterShow() { for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) { WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, (ShutterGetOptions(i) & 1) ? D_OPEN : D_CLOSE,(ShutterGetOptions(i) & 1) ? D_CLOSE : D_OPEN, (ShutterGetOptions(i) & 1) ? (100 - ShutterRealToPercentPosition(-9999, i)) : ShutterRealToPercentPosition(-9999, i), i+1); + WSContentSeparator(3); // Don't print separator on next WSContentSeparator(1) } } From 34b98f552789b6c881b1b3fc8ed7ef7f9c3dc8ed Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 16 Jan 2024 17:07:23 +0100 Subject: [PATCH 165/303] Make it a smaller slice --- tasmota/include/i18n.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/include/i18n.h b/tasmota/include/i18n.h index e4fb16398..5f6cc8c6d 100644 --- a/tasmota/include/i18n.h +++ b/tasmota/include/i18n.h @@ -935,8 +935,8 @@ const float kSpeedConversionFactor[] = {1, // none // xdrv_02_webserver.ino #ifdef USE_WEBSERVER // {s} =
, {m} = , {e} =

{e}"; -const char HTTP_SNS_HR_THIN[] PROGMEM = "

{e}"; +const char HTTP_SNS_HR[] PROGMEM = "

{e}"; +const char HTTP_SNS_HR_THIN[] PROGMEM = "

{e}"; const char HTTP_SNS_F_TEMP[] PROGMEM = "{s}%s " D_TEMPERATURE "{m}%*_f " D_UNIT_DEGREE "%c{e}"; const char HTTP_SNS_F_VOLTAGE[] PROGMEM = "{s}%s " D_VOLTAGE "{m}%*_f " D_UNIT_VOLT "{e}"; const char HTTP_SNS_F_CURRENT_MA[] PROGMEM = "{s}%s " D_CURRENT "{m}%*_f " D_UNIT_MILLIAMPERE "{e}"; From 5545c82e68037309bcef203770c84ced629d53ac Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 16 Jan 2024 17:52:06 +0100 Subject: [PATCH 166/303] Prep for generic use --- tasmota/include/i18n.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/include/i18n.h b/tasmota/include/i18n.h index 5f6cc8c6d..b7c8a21a0 100644 --- a/tasmota/include/i18n.h +++ b/tasmota/include/i18n.h @@ -935,8 +935,8 @@ const float kSpeedConversionFactor[] = {1, // none // xdrv_02_webserver.ino #ifdef USE_WEBSERVER // {s} =
, {m} = , {e} =

{e}"; -const char HTTP_SNS_HR_THIN[] PROGMEM = "

{e}"; +const char HTTP_SNS_HR[] PROGMEM = "



"), (1 == size)?" size=1":""); +// WSContentSend_P(PSTR("

"), size); +// WSContentSend_P(PSTR("

"), size); +// WSContentSend_P(PSTR("
"), size); +} + +void WSContentSeparatorIFat(void) { +// WSContentSend_P(PSTR("}1}2 ")); // Empty line =
  + WSContentSeparatorI(2); +} + +void WSContentSeparatorIThin(void) { +// WSContentSend_P(PSTR("}1
}2
")); //


+ WSContentSeparatorI(1); +} + +void HandleInformation(void) { if (!HttpCheckPriviledgedAccess()) { return; } float freemem = ((float)ESP_getFreeHeap()) / 1024; @@ -2407,13 +2423,13 @@ void HandleInformation(void) for (uint32_t i = 0; i < maxfn; i++) { WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, SettingsTextEscaped(SET_FRIENDLYNAME1 +i).c_str()); } - WSContentSend_P(PSTR("}1}2 ")); // Empty line + WSContentSeparatorIFat(); bool show_hr = false; if ((WiFi.getMode() >= WIFI_AP) && (static_cast(WiFi.softAPIP()) != 0)) { WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.softAPmacAddress().c_str()); WSContentSend_P(PSTR("}1" D_IP_ADDRESS " (AP)}2%_I"), (uint32_t)WiFi.softAPIP()); WSContentSend_P(PSTR("}1" D_GATEWAY "}2%_I"), (uint32_t)WiFi.softAPIP()); - WSContentSend_P(PSTR("}1
}2
")); + WSContentSeparatorIThin(); } if (Settings->flag4.network_wifi) { int32_t rssi = WiFi.RSSI(); @@ -2424,7 +2440,7 @@ void HandleInformation(void) pgm_read_byte(&kWifiPhyMode[WiFi.getPhyMode() & 0x3]), WiFi.channel(), WiFi.BSSIDstr().c_str()); - WSContentSend_P(PSTR("}1}2 ")); // Empty line + WSContentSeparatorIFat(); WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), TasmotaGlobal.hostname, (Mdns.begun) ? PSTR(".local") : ""); #ifdef USE_IPV6 String ipv6_addr = WifiGetIPv6Str(); @@ -2456,7 +2472,7 @@ void HandleInformation(void) #if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET) if (EthernetHasIP()) { if (show_hr) { - WSContentSend_P(PSTR("}1
}2
")); + WSContentSeparatorIThin(); } WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), EthernetHostname(), (Mdns.begun) ? PSTR(".local") : ""); #ifdef USE_IPV6 @@ -2484,9 +2500,9 @@ void HandleInformation(void) #endif // USE_IPV6 } #endif // USE_ETHERNET - WSContentSend_P(PSTR("}1}2 ")); // Empty line + WSContentSeparatorIFat(); WSContentSend_P(PSTR("}1" D_HTTP_API "}2%s"), Settings->flag5.disable_referer_chk ? PSTR(D_ENABLED) : PSTR(D_DISABLED)); // SetOption 128 - WSContentSend_P(PSTR("}1}2 ")); // Empty line + WSContentSeparatorIFat(); if (Settings->flag.mqtt_enabled) { // SetOption3 - Enable MQTT WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), SettingsTextEscaped(SET_MQTT_HOST).c_str()); WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings->mqtt_port); @@ -2511,11 +2527,12 @@ void HandleInformation(void) } #if defined(USE_EMULATION) || defined(USE_DISCOVERY) - WSContentSend_P(PSTR("}1}2 ")); // Empty line + WSContentSeparatorIFat(); #endif // USE_EMULATION or USE_DISCOVERY #ifdef USE_EMULATION WSContentSend_P(PSTR("}1" D_EMULATION "}2%s"), GetTextIndexed(stopic, sizeof(stopic), Settings->flag2.emulation, kEmulationOptions)); #endif // USE_EMULATION + #ifdef USE_DISCOVERY WSContentSend_P(PSTR("}1" D_MDNS_DISCOVERY "}2%s"), (Settings->flag3.mdns_enabled) ? D_ENABLED : D_DISABLED); // SetOption55 - Control mDNS service if (Settings->flag3.mdns_enabled) { // SetOption55 - Control mDNS service @@ -2527,7 +2544,7 @@ void HandleInformation(void) } #endif // USE_DISCOVERY - WSContentSend_P(PSTR("}1}2 ")); // Empty line + WSContentSeparatorIFat(); WSContentSend_P(PSTR("}1" D_ESP_CHIP_ID "}2%d (%s)"), ESP_getChipId(), GetDeviceHardwareRevision().c_str()); WSContentSend_P(PSTR("}1" D_FLASH_CHIP_ID "}20x%06X (" D_TASMOTA_FLASHMODE ")"), ESP_getFlashChipId()); #ifdef ESP32 @@ -2550,7 +2567,7 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1" D_PSR_MAX_MEMORY "}2%d KB"), ESP.getPsramSize() / 1024); WSContentSend_P(PSTR("}1" D_PSR_FREE_MEMORY "}2%d KB"), ESP.getFreePsram() / 1024); } - WSContentSend_P(PSTR("}1}2 ")); // Empty line + WSContentSeparatorIFat(); uint32_t cur_part = ESP_PARTITION_SUBTYPE_APP_FACTORY; // 0 const esp_partition_t *running_ota = esp_ota_get_running_partition(); if (running_ota) { cur_part = running_ota->subtype; } // 16 - 32 @@ -2590,7 +2607,7 @@ void HandleInformation(void) #else // not ESP32 WSContentSend_PD(PSTR("}1" D_FREE_MEMORY "}2%1_f KB"), &freemem); #ifdef USE_UFILESYS - WSContentSend_P(PSTR("}1}2 ")); // Empty line + WSContentSeparatorIFat(); WSContentSend_P(PSTR("}1" D_FILE_SYSTEM_SIZE "}2%d KB"), UfsSize()); #endif // USE_UFILESYS #endif // ESP32 @@ -2599,7 +2616,7 @@ void HandleInformation(void) WSContentSend_P(HTTP_SCRIPT_INFO_END); WSContentSendStyle(); // WSContentSend_P(PSTR("
 Information ")); - WSContentSend_P(PSTR("" + WSContentSend_P(PSTR("" "
")); // WSContentSend_P(PSTR("
")); WSContentSpaceButton(BUTTON_MAIN); From f2bcff346ad89afa93fe07c33ab49078e3da9898 Mon Sep 17 00:00:00 2001 From: bovirus <1262554+bovirus@users.noreply.github.com> Date: Thu, 18 Jan 2024 10:23:04 +0100 Subject: [PATCH 172/303] Update Italian language (#20526) --- tasmota/language/it_IT.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index 932252c0c..b5d948491 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v9.4.0.1 - Last update 08.01.2024 + * Updated until v9.4.0.1 - Last update 17.01.2024 \*********************************************************************/ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -57,7 +57,7 @@ #define D_AP "AP" // Access Point #define D_AS "come" #define D_AUTO "AUTO" -#define D_BATTERY "Battery" +#define D_BATTERY "Batteria" #define D_BATT "Batt" // Short for Battery #define D_BATTERY_CHARGE "Carica" // Battery charge in % #define D_BLINK "Lampeggia" @@ -1225,7 +1225,7 @@ #define D_UNIT_US_H "µSv/h" // ixrv92_pipsolar.ino -#define D_SENSOR_PIPSOLAR_TX "Pipsolar TX" -#define D_SENSOR_PIPSOLAR_RX "Pipsolar RX" +#define D_SENSOR_PIPSOLAR_TX "Pipsolar - TX" +#define D_SENSOR_PIPSOLAR_RX "Pipsolar - RX" #endif // _LANGUAGE_IT_IT_H_ From 9ccc3f8fdabbe0e57970c1b1ed93de3b9d32aaaa Mon Sep 17 00:00:00 2001 From: gemu Date: Thu, 18 Jan 2024 10:23:21 +0100 Subject: [PATCH 173/303] Universal touch driver (#20492) * add universal touch * add universal touch * add universal touch * add universal touch * Update xdrv_10_scripter.ino * utouch add word address support (gt911) * optimizations * add simple resistive touch --- .../src/renderer.cpp | 16 + .../Display_Renderer-gemu-1.0/src/renderer.h | 4 + lib/lib_display/UDisplay/uDisplay.cpp | 420 ++++++++++++++++++ lib/lib_display/UDisplay/uDisplay.h | 39 ++ .../tasmota_xdrv_driver/xdrv_10_scripter.ino | 2 +- tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino | 60 ++- .../xdsp_17_universal.ino | 8 +- 7 files changed, 539 insertions(+), 10 deletions(-) diff --git a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp index 7ea9aa0e6..0bc75395f 100644 --- a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp +++ b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp @@ -623,6 +623,22 @@ int8_t Renderer::color_type(void) { return 0; } +bool Renderer::utouch_Init(char **name) { + return false; +} + +bool Renderer::touched(void) { + return false; +} + +int16_t Renderer::getPoint_x(void) { + return 0; +} + +int16_t Renderer::getPoint_y(void) { + return 0; +} + void Renderer::Splash(void) { } diff --git a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h index 279ab514d..a63c4a93f 100644 --- a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h +++ b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h @@ -92,6 +92,10 @@ public: virtual void ep_update_mode(uint8_t mode); virtual void ep_update_area(uint16_t xp, uint16_t yp, uint16_t width, uint16_t height, uint8_t mode); virtual uint32_t get_sr_touch(uint32_t xp, uint32_t xm, uint32_t yp, uint32_t ym); + virtual bool utouch_Init(char **); + virtual bool touched(void); + virtual int16_t getPoint_x(); + virtual int16_t getPoint_y(); void setDrawMode(uint8_t mode); uint8_t drawmode; diff --git a/lib/lib_display/UDisplay/uDisplay.cpp b/lib/lib_display/UDisplay/uDisplay.cpp index 6b2262f32..f46032dac 100755 --- a/lib/lib_display/UDisplay/uDisplay.cpp +++ b/lib/lib_display/UDisplay/uDisplay.cpp @@ -37,6 +37,9 @@ extern int Cache_WriteBack_Addr(uint32_t addr, uint32_t size); #define renderer_swap(a, b) { int16_t t = a; a = b; b = t; } +enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE}; +extern void AddLog(uint32_t loglevel, PGM_P formatP, ...); + const uint16_t udisp_colors[]={UDISP_BLACK,UDISP_WHITE,UDISP_RED,UDISP_GREEN,UDISP_BLUE,UDISP_CYAN,UDISP_MAGENTA,\ UDISP_YELLOW,UDISP_NAVY,UDISP_DARKGREEN,UDISP_DARKCYAN,UDISP_MAROON,UDISP_PURPLE,UDISP_OLIVE,\ UDISP_LIGHTGREY,UDISP_DARKGREY,UDISP_ORANGE,UDISP_GREENYELLOW,UDISP_PINK}; @@ -136,6 +139,18 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { lut_cmd[cnt] = 0xff; lut_array[cnt] = 0; } + +#ifdef USE_UNIVERSAL_TOUCH + ut_init_code[0] = UT_RT; + ut_init_code[1] = UT_END; + ut_touch_code[0] = UT_RT; + ut_touch_code[1] = UT_END; + ut_getx_code[0] = UT_RT; + ut_getx_code[1] = UT_END; + ut_gety_code[0] = UT_RT; + ut_gety_code[1] = UT_END; +#endif // USE_UNIVERSAL_TOUCH + lut_partial = 0; lut_full = 0; char linebuff[UDSP_LBSIZE]; @@ -542,6 +557,68 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { case 'b': bpmode = next_val(&lp1); break; +#ifdef USE_UNIVERSAL_TOUCH + case 'U': + if (!strncmp(lp1, "TI", 2)) { + // init + ut_wire = 0; + ut_reset = -1; + ut_irq = -1; + lp1 += 3; + str2c(&lp1, ut_name, sizeof(ut_name)); + if (*lp1 == 'I') { + // i2c mode + lp1++; + uint8_t ut_mode = *lp1 & 0xf; + lp1 += 2; + ut_i2caddr = next_hex(&lp1); + ut_reset = next_val(&lp1); + ut_irq = next_val(&lp1); + + if (ut_mode == 1) { + ut_wire = &Wire; + } else { +#ifdef ESP32 + ut_wire = &Wire1; +#else + ut_wire = &Wire; +#endif + } + } else if (*lp1 == 'S') { + // spi mode + lp1++; + uint8_t ut_mode = *lp1 & 0xf; + lp1 += 2; + ut_reset = -1; + ut_irq = -1; + ut_spi_cs = next_val(&lp1); + ut_reset = next_val(&lp1); + ut_irq = next_val(&lp1); + // assume displays SPI bus + pinMode(ut_spi_cs, OUTPUT); + digitalWrite(ut_spi_cs, HIGH); + + ut_spiSettings = SPISettings(2000000, MSBFIRST, SPI_MODE0); + } else { + // simple resistive touch + lp1++; + } + ut_trans(&lp, ut_init_code, sizeof(ut_init_code)); + } else if (!strncmp(lp1, "TT", 2)) { + lp1 += 2; + // touch + ut_trans(&lp, ut_touch_code, sizeof(ut_touch_code)); + } else if (!strncmp(lp1, "TX", 2)) { + lp1 += 2; + // get x + ut_trans(&lp, ut_getx_code, sizeof(ut_getx_code)); + } else if (!strncmp(lp1, "TY", 2)) { + lp1 += 2; + // get y + ut_trans(&lp, ut_gety_code, sizeof(ut_gety_code)); + } + break; +#endif // USE_UNIVERSAL_TOUCH } } } @@ -1815,6 +1892,52 @@ for(y=h; y>0; y--) { } */ +#ifdef USE_UNIVERSAL_TOUCH + +uint8_t ut_irq_flg; + +void IRAM_ATTR ut_touch_irq(void) { + ut_irq_flg = 1; +} + +// universal touch driver +bool uDisplay::utouch_Init(char **name) { + *name = ut_name; + if (ut_reset >= 0) { + pinMode(ut_reset, OUTPUT); + digitalWrite(ut_reset, HIGH); + delay(10); + digitalWrite(ut_reset, LOW); + delay(5); + digitalWrite(ut_reset, HIGH); + delay(10); + } + if (ut_irq >= 0) { + attachInterrupt(ut_irq, ut_touch_irq, FALLING); + } + + return ut_execute(ut_init_code); +} + +bool uDisplay::touched(void) { + if (ut_irq >= 0) { + if (!ut_irq_flg) { + return false; + } + ut_irq_flg = 0; + } + return ut_execute(ut_touch_code); +} + +int16_t uDisplay::getPoint_x(void) { + return ut_execute(ut_getx_code); +} + +int16_t uDisplay::getPoint_y(void) { + return ut_execute(ut_gety_code); +} +#endif // USE_UNIVERSAL_TOUCH + void uDisplay::Splash(void) { @@ -2461,6 +2584,303 @@ char *uDisplay::devname(void) { return dname; } + + +#ifdef USE_UNIVERSAL_TOUCH + +uint16_t uDisplay::ut_par(char **lp, uint32_t mode) { + char *cp = *lp; + while (*cp != ' ') { + cp++; + } + cp++; + uint16_t result; + if (!mode) { + result = strtol(cp, &cp, 16); + } else { + result = strtol(cp, &cp, 10); + } + *lp = cp; + return result; +} + +void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { + char *cp = *sp; + uint16_t wval; + while (*cp) { + if (*cp == ':' || *cp == '#') { + break; + } + if (!strncmp(cp, "RDWM", 4)) { + // read word many + *ut_code++ = UT_RDWM; + wval = ut_par(&cp, 0); + *ut_code++ = wval>>8; + *ut_code++ = wval; + wval = ut_par(&cp, 1); + if (wval > sizeof(ut_array)) { + wval = sizeof(ut_array); + } + *ut_code++ = wval; + size -= 4; + } else if (!strncmp(cp, "RDW", 3)) { + // read word one + *ut_code++ = UT_RDW; + wval = ut_par(&cp, 0); + *ut_code++ = wval>>8; + *ut_code++ = wval; + size -= 3; + } else if (!strncmp(cp, "RDM", 3)) { + // read many + *ut_code++ = UT_RDM; + *ut_code++ = ut_par(&cp, 0); + wval = ut_par(&cp, 1); + if (wval > sizeof(ut_array)) { + wval = sizeof(ut_array); + } + *ut_code++ = wval; + size -= 3; + } else if (!strncmp(cp, "RD", 2)) { + // read one + *ut_code++ = UT_RD; + *ut_code++ = ut_par(&cp, 0); + size -= 2; + } else if (!strncmp(cp, "CPR", 3)) { + // cmp and set + *ut_code++ = UT_CPR; + *ut_code++ = ut_par(&cp, 0); + size -= 2; + } else if (!strncmp(cp, "CP", 2)) { + // cmp and set + *ut_code++ = UT_CP; + *ut_code++ = ut_par(&cp, 0); + size -= 2; + } else if (!strncmp(cp, "RTF", 3)) { + // return when false + *ut_code++ = UT_RTF; + size -= 1; + } else if (!strncmp(cp, "RTT", 3)) { + // return when true + *ut_code++ = UT_RTT; + size -= 1; + } else if (!strncmp(cp, "MV", 2)) { + // move + *ut_code++ = UT_MV; + *ut_code++ = ut_par(&cp, 1); + *ut_code++ = ut_par(&cp, 1); + size -= 3; + } else if (!strncmp(cp, "RT", 2)) { + // return status + *ut_code++ = UT_RT; + size -= 1; + } else if (!strncmp(cp, "WRW", 3)) { + *ut_code++ = UT_WRW; + wval = ut_par(&cp, 0); + *ut_code++ = wval>>8; + *ut_code++ = wval; + wval = ut_par(&cp, 0); + *ut_code++ = wval; + size -= 4; + } else if (!strncmp(cp, "WR", 2)) { + *ut_code++ = UT_WR; + wval = ut_par(&cp, 0); + *ut_code++ = wval; + wval = ut_par(&cp, 0); + *ut_code++ = wval; + size -= 3; + } else if (!strncmp(cp, "AND", 3)) { + *ut_code++ = UT_AND; + wval = ut_par(&cp, 0); + *ut_code++ = wval>>8; + *ut_code++ = wval; + size -= 3; + } else if (!strncmp(cp, "GSRT", 4)) { + *ut_code++ = UT_GSRT; + wval = ut_par(&cp, 1); + *ut_code++ = wval>>8; + *ut_code++ = wval; + size -= 3; + } else if (!strncmp(cp, "DBG", 3)) { + *ut_code++ = UT_DBG; + wval = ut_par(&cp, 1); + *ut_code++ = wval; + size -= 2; + } + if (size <= 1) { + break; + } + + cp++; + } + *ut_code++ = UT_END; + *sp = cp - 1; +} + +uint8_t *uDisplay::ut_rd(uint8_t *iop, uint32_t len, uint32_t amode) { + if (ut_wire) { + // i2c mode + ut_wire->beginTransmission(ut_i2caddr); + ut_wire->write(*iop++); + if (amode == 2) { + ut_wire->write(*iop++); + } + ut_wire->endTransmission(false); + if (len > 1) { + len = *iop++; + } + ut_wire->requestFrom(ut_i2caddr, (size_t)len); + uint8_t index = 0; + while (ut_wire->available()) { + ut_array[index++] = ut_wire->read(); + } + } else { + // spi mode + uint16_t val = *iop++; + digitalWrite(ut_spi_cs, LOW); + if (spi_nr <= 2) { + uspi->beginTransaction(ut_spiSettings); + val = uspi->transfer16(val); + uspi->endTransaction(); + ut_array[0] = val << 8; + ut_array[1] = val; + } + digitalWrite(ut_spi_cs, HIGH); + } + return iop; +} + +uint8_t *uDisplay::ut_wr(uint8_t *iop, uint32_t amode) { + if (ut_wire) { + // i2c mode + ut_wire->beginTransmission(ut_i2caddr); + ut_wire->write(*iop++); + if (amode == 2) { + ut_wire->write(*iop++); + } + ut_wire->write(*iop++); + ut_wire->endTransmission(true); + } else { + // spi mode + } + return iop; +} + +int16_t uDisplay::ut_execute(uint8_t *ut_code) { +int16_t result = 0; +uint8_t iob, len; +uint16_t wval; + + while (*ut_code != UT_END) { + iob = *ut_code++; + switch (iob) { + case UT_RD: + // read 1 byte + ut_code = ut_rd(ut_code, 1, 1); + break; + case UT_RDM: + // read multiple bytes + ut_code = ut_rd(ut_code, 2, 1); + break; + case UT_RDW: + // read 1 byte + ut_code = ut_rd(ut_code, 1, 2); + break; + case UT_RDWM: + // read multiple bytes + ut_code = ut_rd(ut_code, 2, 2); + break; + case UT_WR: + ut_code = ut_wr(ut_code, 1); + break; + case UT_WRW: + ut_code = ut_wr(ut_code, 2); + break; + case UT_CP: + // compare + iob = *ut_code++; + result = (iob == ut_array[0]); + break; + case UT_CPR: + // compare + iob = *ut_code++; + result = (iob == result); + break; + case UT_RTF: + // return when false + if (result == 0) { + return false; + } + break; + case UT_RTT: + // return when true + if (result > 0) { + return false; + } + break; + case UT_MV: + // move + // source + result = *ut_code++; + iob = *ut_code++; + if (iob == 1) { + result = ut_array[result]; + } else if (iob == 2) { + iob = result; + result = ut_array[iob] << 8; + result |= ut_array[iob + 1]; + } else { + iob = result; + result = ut_array[iob + 1] << 8; + result |= ut_array[iob]; + } + result &= 0xfff; + break; + case UT_AND: + // and + wval = *ut_code++ << 8; + wval |= *ut_code++; + result &= wval; + break; + case UT_RT: + // result + return result; + break; + case UT_GSRT: +#ifdef USE_ESP32_S3 + { uint32_t val = get_sr_touch(SIMPLERS_XP, SIMPLERS_XM, SIMPLERS_YP, SIMPLERS_YM); + if (val == 0) { + return false; + } + uint16_t xp = val >> 16; + uint16_t yp = val; + + wval = *ut_code++ << 8; + wval |= *ut_code++; + if (xp > wval && yp > wval) { + ut_array[0] = val >> 24; + ut_array[1] = val >> 16; + ut_array[2] = val >> 8; + ut_array[3] = val; + return true; + } + return false; + } +#endif // USE_ESP32_S3 + break; + case UT_DBG: + // debug show result + //Serial.printf("UTDBG: %d\n", result); + wval = *ut_code++; + AddLog(LOG_LEVEL_INFO, PSTR("UTDBG %d: %02x : %02x,%02x,%02x,%02x"), wval, result, ut_array[0], ut_array[1], ut_array[2], ut_array[3]); + break; + case UT_END: + break; + } + } + return result; +} +#endif // USE_UNIVERSAL_TOUCH + uint32_t uDisplay::str2c(char **sp, char *vp, uint32_t len) { char *lp = *sp; if (len) len--; diff --git a/lib/lib_display/UDisplay/uDisplay.h b/lib/lib_display/UDisplay/uDisplay.h index 238802dca..21e2eb6f3 100755 --- a/lib/lib_display/UDisplay/uDisplay.h +++ b/lib/lib_display/UDisplay/uDisplay.h @@ -101,6 +101,15 @@ enum uColorType { uCOLOR_BW, uCOLOR_COLOR }; #define GPIO_SET(A) GPIO.out_w1ts = (1 << A) #endif +enum { + UT_RD,UT_RDM,UT_CP,UT_RTF,UT_MV,UT_RT,UT_RTT,UT_RDW,UT_RDWM,UT_WR,UT_WRW,UT_CPR,UT_AND,UT_DBG,UT_GSRT,UT_END +}; + +#define SIMPLERS_XP par_dbl[1] +#define SIMPLERS_XM par_cs +#define SIMPLERS_YP par_rs +#define SIMPLERS_YM par_dbl[0] + #define GPIO_CLR_SLOW(A) digitalWrite(A, LOW) #define GPIO_SET_SLOW(A) digitalWrite(A, HIGH) @@ -190,6 +199,13 @@ class uDisplay : public Renderer { void invertDisplay(boolean i); void SetPwrCB(pwr_cb cb) { pwr_cbp = cb; }; void SetDimCB(dim_cb cb) { dim_cbp = cb; }; +#ifdef USE_UNIVERSAL_TOUCH +// universal touch driver + bool utouch_Init(char **name); + bool touched(void); + int16_t getPoint_x(); + int16_t getPoint_y(); +#endif // USE_UNIVERSAL_TOUCH private: void beginTransaction(SPISettings s); @@ -411,6 +427,29 @@ class uDisplay : public Renderer { void pushPixelsDMA(uint16_t* image, uint32_t len); void pushPixels3DMA(uint8_t* image, uint32_t len); #endif // ESP32 + +#ifdef USE_UNIVERSAL_TOUCH +// universal touch driver + void ut_trans(char **sp, uint8_t *ut_code, int32_t size); + int16_t ut_execute(uint8_t *ut_code); + uint16_t ut_par(char **cp, uint32_t mode); + uint8_t *ut_rd(uint8_t *io, uint32_t len, uint32_t amode); + uint8_t *ut_wr(uint8_t *io, uint32_t amode); + uint32_t ut_result; + uint8_t ut_array[16]; + uint8_t ut_i2caddr; + uint8_t ut_spi_cs; + int8_t ut_reset; + int8_t ut_irq; + TwoWire *ut_wire; + SPISettings ut_spiSettings; + char ut_name[8]; + uint8_t ut_init_code[32]; + uint8_t ut_touch_code[32]; + uint8_t ut_getx_code[16]; + uint8_t ut_gety_code[16]; + +#endif // USE_UNIVERSAL_TOUCH }; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino index 9b71d05c5..76903985e 100755 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino @@ -5875,7 +5875,7 @@ extern char *SML_GetSVal(uint32_t index); goto exit; } #endif // USE_TTGO_WATCH -#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_GT911) +#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_UNIVERSAL_TOUCH) || defined(USE_GT911) if (!strncmp_XP(lp, XPSTR("wtch("), 5)) { lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv); fvar = Touch_Status(fvar); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino index d7738e80a..1801fb3d6 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino @@ -36,11 +36,7 @@ \*******************************************************************************************/ -#if defined(USE_LVGL_TOUCHSCREEN) || defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_GT911) || defined(USE_LILYGO47) || defined(USE_TOUCH_BUTTONS) || defined(SIMPLE_RES_TOUCH) - -#ifdef USE_DISPLAY_LVGL_ONLY -#undef USE_TOUCH_BUTTONS -#endif +#if defined(USE_LVGL_TOUCHSCREEN) || defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_GT911) || defined(USE_LILYGO47) || defined(USE_UNIVERSAL_TOUCH) || defined(USE_TOUCH_BUTTONS) || defined(SIMPLE_RES_TOUCH) #include @@ -76,6 +72,7 @@ bool FT5206_found = false; bool GT911_found = false; bool XPT2046_found = false; bool SRES_found = false; +bool utouch_found = false; #ifndef MAX_TOUCH_BUTTONS #define MAX_TOUCH_BUTTONS 16 @@ -98,7 +95,7 @@ void Touch_SetStatus(uint8_t touches, uint16_t raw_x, uint16_t raw_y, uint8_t ge // return true if succesful, false if not configured bool Touch_GetStatus(uint8_t* touches, uint16_t* x, uint16_t* y, uint8_t* gesture, uint16_t* raw_x, uint16_t* raw_y) { - if (TSGlobal.external_ts || CST816S_found || FT5206_found || XPT2046_found) { + if (TSGlobal.external_ts || CST816S_found || FT5206_found || XPT2046_found || utouch_found) { if (touches) { *touches = TSGlobal.touches; } if (x) { *x = TSGlobal.touch_xp; } if (y) { *y = TSGlobal.touch_yp; } @@ -111,7 +108,7 @@ bool Touch_GetStatus(uint8_t* touches, uint16_t* x, uint16_t* y, uint8_t* gestur } uint32_t Touch_Status(int32_t sel) { - if (TSGlobal.external_ts || CST816S_found || FT5206_found || GT911_found || XPT2046_found || SRES_found) { + if (TSGlobal.external_ts || CST816S_found || FT5206_found || GT911_found || XPT2046_found || utouch_found || SRES_found) { switch (sel) { case 0: return TSGlobal.touched; @@ -242,6 +239,40 @@ bool CST816S_Touch_Init(uint8_t bus, int8_t irq_pin, int8_t rst_pin, int interru } #endif // USE_CST816S + +#ifdef USE_UNIVERSAL_TOUCH + +void utouch_Touch_Init() { + if (renderer) { + char *name; + utouch_found = renderer->utouch_Init(&name); + if (utouch_found) { + AddLog(LOG_LEVEL_INFO, PSTR("UT: %s"), name); + } + } +} + +bool utouch_touched() { + if (renderer) { + return renderer->touched(); + } +} +int16_t utouch_x() { + if (renderer) { + return renderer->getPoint_x(); + } else { + return 0; + } +} +int16_t utouch_y() { + if (renderer) { + return renderer->getPoint_y(); + } else { + return 0; + } +} +#endif // USE_UNIVERSAL_TOUCH + #ifdef USE_FT5206 #include // touch panel controller @@ -370,6 +401,16 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) { } #endif // USE_CST816S +#ifdef USE_UNIVERSAL_TOUCH + if (utouch_found) { + TSGlobal.touched = utouch_touched(); + if (TSGlobal.touched) { + TSGlobal.raw_touch_xp = utouch_x(); + TSGlobal.raw_touch_yp = utouch_y(); + } + } +#endif // USE_UNIVERSAL_TOUCH + #ifdef USE_FT5206 if (FT5206_found) { TSGlobal.touched = FT5206_touched(); @@ -459,6 +500,9 @@ void Touch_MQTT(uint8_t index, const char *cp, uint32_t val) { #ifdef USE_FT5206 if (FT5206_found) ResponseTime_P(PSTR(",\"FT5206\":{\"%s%d\":\"%d\"}}"), cp, index + 1, val); #endif +#ifdef USE_UNIVERSAL_TOUCH + if (utouch_found) ResponseTime_P(PSTR(",\"UTOUCH\":{\"%s%d\":\"%d\"}}"), cp, index + 1, val); +#endif #ifdef USE_XPT2046 if (XPT2046_found) ResponseTime_P(PSTR(",\"XPT2046\":{\"%s%d\":\"%d\"}}"), cp, index + 1, val); #endif // USE_XPT2046 @@ -585,7 +629,7 @@ bool Xdrv55(uint32_t function) { case FUNC_INIT: break; case FUNC_EVERY_100_MSECOND: - if (CST816S_found || FT5206_found || XPT2046_found || GT911_found || SRES_found) { + if (CST816S_found || FT5206_found || XPT2046_found || GT911_found || utouch_found || SRES_found) { Touch_Check(TS_RotConvert); } break; diff --git a/tasmota/tasmota_xdsp_display/xdsp_17_universal.ino b/tasmota/tasmota_xdsp_display/xdsp_17_universal.ino index b9213ed17..02d942eae 100644 --- a/tasmota/tasmota_xdsp_display/xdsp_17_universal.ino +++ b/tasmota/tasmota_xdsp_display/xdsp_17_universal.ino @@ -374,6 +374,7 @@ int8_t cs; #endif // ESP8266 // start digitizer + #ifdef ESP32 if (i2caddr == GT911_address) { #ifdef USE_GT911 @@ -468,13 +469,18 @@ int8_t cs; Settings->display_width = renderer->width(); Settings->display_height = renderer->height(); +#ifdef USE_UNIVERSAL_TOUCH + utouch_Touch_Init(); +#endif + bool iniinv = Settings->display_options.invert; + /* cp = strstr(ddesc, ":n,"); if (cp) { cp+=3; iniinv = strtol(cp, &cp, 10); Settings->display_options.invert = iniinv; - } + }*/ renderer->invertDisplay(iniinv); ApplyDisplayDimmer(); From 0f541a963b1f9b62c9cc87f825f183b11c5f1fa7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 18 Jan 2024 10:38:22 +0100 Subject: [PATCH 174/303] Fix TimedPower blink off --- tasmota/tasmota_support/support_command.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/tasmota_support/support_command.ino b/tasmota/tasmota_support/support_command.ino index cefea6cb3..398fd11cd 100644 --- a/tasmota/tasmota_support/support_command.ino +++ b/tasmota/tasmota_support/support_command.ino @@ -785,7 +785,7 @@ void CmndTimedPower(void) { TimedPower2 2000,0|off - Turn power2 off and then on after 2 seconds TimedPower1 2200,1|on - Turn power1 on and then off after 2.2 seconds TimedPower2 2000,2|toggle - Toggle power2 and then toggle again after 2 seconds - TimedPower2 2500,3|blink - Blink power2 and then turn off after 2.5 seconds + TimedPower2 2500,3|blink - Blink power2 and then stop blink after 2.5 seconds */ if ((XdrvMailbox.index >= 0) && (XdrvMailbox.index <= TasmotaGlobal.devices_present)) { if (XdrvMailbox.data_len > 0) { @@ -800,7 +800,7 @@ void CmndTimedPower(void) { } start_state &= 0x03; // POWER_OFF, POWER_ON, POWER_TOGGLE, POWER_BLINK } - const uint8_t end_state[] = { POWER_ON, POWER_OFF, POWER_TOGGLE, POWER_OFF }; + const uint8_t end_state[] = { POWER_ON, POWER_OFF, POWER_TOGGLE, POWER_BLINK_STOP }; char cmnd[CMDSZ]; snprintf_P(cmnd, sizeof(cmnd), PSTR(D_CMND_POWER "%d %d"), XdrvMailbox.index, end_state[start_state]); if (SetTimedCmnd(time, cmnd)) { // Skip if no more timers left (MAX_TIMED_CMND) From a2c4123d79294c2d961b51b9e6462b6c441c5f6c Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:31:47 +0100 Subject: [PATCH 175/303] Berry add solidification of strings longer than 255 bytes (#20529) --- CHANGELOG.md | 1 + lib/libesp32/berry/src/be_constobj.h | 7 ++++ lib/libesp32/berry/src/be_solidifylib.c | 33 ++++++++++++++++--- lib/libesp32/berry/src/be_string.c | 19 ++++++++--- lib/libesp32/berry/src/be_string.h | 6 ++++ lib/libesp32/berry/tools/coc/block_builder.py | 1 + lib/libesp32/berry/tools/coc/coc | 7 +++- lib/libesp32/berry/tools/coc/coc_parser.py | 9 +++++ lib/libesp32/berry/tools/coc/str_build.py | 14 +++++++- 9 files changed, 86 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b76fb816..ff7287194 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. - LVGL option to add `lv.keyboard` extra widget (#20496) - GUI sensor separators (#20495) - Command ``TimedPower [,ON|OFF|TOGGLE|BLINK]`` executes ``Power [ON|OFF|TOGGLE|BLINK] `` and after executes ``Power [OFF|ON|TOGGLE|OFF]`` +- Berry add solidification of strings longer than 255 bytes ### Breaking Changed diff --git a/lib/libesp32/berry/src/be_constobj.h b/lib/libesp32/berry/src/be_constobj.h index 485bf85e6..34245050a 100644 --- a/lib/libesp32/berry/src/be_constobj.h +++ b/lib/libesp32/berry/src/be_constobj.h @@ -262,6 +262,13 @@ const bntvmodule_t be_native_module(_module) = { \ BE_STRING \ } +/* variant for long strings that does not trigger strtab */ +#define be_nested_str_long(_name_) \ + { \ + { .s=((bstring*)&be_const_str_##_name_) }, \ + BE_STRING \ + } + #define be_nested_str_literal(_name_) \ { \ { .s=(be_nested_const_str(_name_, _hash, sizeof(_name_)-1 ))\ diff --git a/lib/libesp32/berry/src/be_solidifylib.c b/lib/libesp32/berry/src/be_solidifylib.c index b0164ddba..0cafe2a73 100644 --- a/lib/libesp32/berry/src/be_solidifylib.c +++ b/lib/libesp32/berry/src/be_solidifylib.c @@ -16,6 +16,7 @@ #include "be_vm.h" #include "be_decoder.h" #include "be_sys.h" +#include "be_mem.h" #include #include #include @@ -45,6 +46,16 @@ extern const bclass be_class_map; } \ } while (0) +/* minimal version without formatting and without size limit */ +#define lognofmt(__s) \ + do { \ + if (fout) { \ + be_fwrite(fout, __s, strlen(__s)); \ + } else { \ + be_writestring(__s); \ + } \ + } while (0) + /********************************************************************\ * Encode string to identifiers * @@ -200,17 +211,29 @@ static void m_solidify_bvalue(bvm *vm, bbool str_literal, bvalue * value, const { const char * str = str(var_tostr(value)); size_t len = strlen(str); - if (len >= 255) { - be_raise(vm, "internal_error", "Strings greater than 255 chars not supported yet"); - } size_t id_len = toidentifier_length(str); - char id_buf[id_len]; + char id_buf_stack[64]; + char *id_buf = id_buf_stack; + if (id_len >= 64) { + id_buf = be_os_malloc(id_len); + if (!id_buf) { + be_raise(vm, "memory_error", "could not allocated buffer"); + } + } toidentifier(id_buf, str); - if (!str_literal) { + if (len >= 255) { + /* decompose to avoid any size limit */ + lognofmt("be_nested_str_long("); + lognofmt(id_buf); + lognofmt(")"); + } else if (!str_literal) { logfmt("be_nested_str(%s)", id_buf); } else { logfmt("be_nested_str_weak(%s)", id_buf); } + if (id_buf != id_buf_stack) { + be_os_free(id_buf); + } } break; case BE_CLOSURE: diff --git a/lib/libesp32/berry/src/be_string.c b/lib/libesp32/berry/src/be_string.c index c6cb093c2..806e37ff0 100644 --- a/lib/libesp32/berry/src/be_string.c +++ b/lib/libesp32/berry/src/be_string.c @@ -27,6 +27,17 @@ .s = _s \ } +#define be_define_const_str_long(_name, _s, _len) \ + BERRY_LOCAL const bclstring be_const_str_##_name = { \ + .next = (bgcobject *)NULL, \ + .type = BE_STRING, \ + .marked = GC_CONST, \ + .extra = 0, \ + .slen = 255, \ + .llen = _len, \ + .s = _s \ + } + /* const string table */ struct bconststrtab { const bstring* const *table; @@ -279,7 +290,7 @@ void be_gcstrtab(bvm *vm) uint32_t be_strhash(const bstring *s) { - if (gc_isconst(s)) { + if (gc_isconst(s) && (s->slen != 255)) { bcstring* cs = cast(bcstring*, s); if (cs->hash) { /* if hash is null we need to compute it */ return cs->hash; @@ -298,12 +309,12 @@ uint32_t be_strhash(const bstring *s) const char* be_str2cstr(const bstring *s) { be_assert(cast_str(s) != NULL); - if (gc_isconst(s)) { - return cstr(s); - } if (s->slen == 255) { return lstr(s); } + if (gc_isconst(s)) { + return cstr(s); + } return sstr(s); } diff --git a/lib/libesp32/berry/src/be_string.h b/lib/libesp32/berry/src/be_string.h index 51b3fd016..f39ae6c4f 100644 --- a/lib/libesp32/berry/src/be_string.h +++ b/lib/libesp32/berry/src/be_string.h @@ -26,6 +26,12 @@ typedef struct { /* char s[]; */ } blstring; +typedef struct { /* const long string */ + bstring_header; + int llen; + char s[]; +} bclstring; + typedef struct { bstring_header; uint32_t hash; diff --git a/lib/libesp32/berry/tools/coc/block_builder.py b/lib/libesp32/berry/tools/coc/block_builder.py index 6535fd40b..a65ddb720 100644 --- a/lib/libesp32/berry/tools/coc/block_builder.py +++ b/lib/libesp32/berry/tools/coc/block_builder.py @@ -23,6 +23,7 @@ class block_builder: self.block = block() self.strtab = [] self.strtab_weak = [] + self.strtab_long = [] self.block.name = obj.name if depend(obj, macro): diff --git a/lib/libesp32/berry/tools/coc/coc b/lib/libesp32/berry/tools/coc/coc index 1a12c01e6..b80d0ac08 100755 --- a/lib/libesp32/berry/tools/coc/coc +++ b/lib/libesp32/berry/tools/coc/coc @@ -19,6 +19,7 @@ class builder: self.macro = None self.strmap = {} self.strmap_weak = {} + self.strmap_long = {} self.macro = macro_table() for path in self.config: @@ -27,7 +28,7 @@ class builder: for d in self.input: self.scandir(d) - sb = str_build(self.strmap, self.strmap_weak) + sb = str_build(self.strmap, self.strmap_weak, self.strmap_long) sb.build(self.output) def parse_file(self, filename): @@ -42,12 +43,16 @@ class builder: self.strmap[s] = 0 for s in parser.strtab_weak: self.strmap_weak[s] = 0 + for s in parser.strtab_long: + self.strmap_long[s] = 0 for obj in parser.objects: builder = block_builder(obj, self.macro) for s in builder.strtab: self.strmap[s] = 0 for s in builder.strtab_weak: self.strmap_weak[s] = 0 + for s in builder.strtab_long: + self.strmap_long[s] = 0 builder.dumpfile(self.output) def scandir(self, srcpath): diff --git a/lib/libesp32/berry/tools/coc/coc_parser.py b/lib/libesp32/berry/tools/coc/coc_parser.py index c5603ebb7..68c81a2ba 100644 --- a/lib/libesp32/berry/tools/coc/coc_parser.py +++ b/lib/libesp32/berry/tools/coc/coc_parser.py @@ -22,6 +22,7 @@ class coc_parser: self.objects = [] self.strtab = set() self.strtab_weak = set() + self.strtab_long = set() self.text = text self.parsers = { "@const_object_info_begin": self.parse_object, @@ -30,6 +31,7 @@ class coc_parser: "be_nested_str(": self.parse_string, "be_const_key_weak(": self.parse_string_weak, "be_nested_str_weak(": self.parse_string_weak, + "be_nested_str_long(": self.parse_string_long, "be_str_weak(": self.parse_string_weak, } @@ -131,6 +133,13 @@ class coc_parser: self.strtab_weak.add(literal) # print(f"str '{ident}' -> {literal}") + def parse_string_long(self): + if not self.text[0].isalnum() and self.text[0] != '_': return # do not proceed, maybe false positive in solidify + ident = self.parse_word() + literal = unescape_operator(ident) + if not literal in self.strtab: + self.strtab_long.add(literal) + ################################################################################# # Parse a block of definition like module, class... ################################################################################# diff --git a/lib/libesp32/berry/tools/coc/str_build.py b/lib/libesp32/berry/tools/coc/str_build.py index 31caba1d3..b8380bf57 100644 --- a/lib/libesp32/berry/tools/coc/str_build.py +++ b/lib/libesp32/berry/tools/coc/str_build.py @@ -22,9 +22,10 @@ class str_info: self.extra = 0 class str_build: - def __init__(self, map, map_weak): + def __init__(self, map, map_weak, map_long): self.map = map.copy() self.str_weak = [] + self.str_long = [] size = int(len(self.map) / 2) # voluntarily reduce hash size to half if size < 4: size = 4 @@ -44,6 +45,11 @@ class str_build: if not k in self.map: self.str_weak.append(k) + # handle long strings + for k in sorted(map_long.keys()): + if not k in self.map: + self.str_long.append(k) + def build(self, path): prefix = path + "/be_const_strtab" self.writefile(prefix + "_def.h", self.build_table_def()) @@ -121,6 +127,10 @@ class str_build: ostr += escape_operator(k) + ", " + escape_c(k) + ", " ostr += "0u, 0, " + str(len(k)) + ", NULL);\n" + for k in self.str_long: + ostr += "be_define_const_str_long(" + ostr += escape_operator(k) + ", " + escape_c(k) + ", " + str(len(k)) + ");\n" + ostr += "\n" ostr += "static const bstring* const m_string_table[] = {\n" @@ -156,4 +166,6 @@ class str_build: ostr += "\n/* weak strings */\n" for s in self.str_weak: ostr += "extern const bcstring be_const_str_" + escape_operator(s) + ";\n" + for s in self.str_long: + ostr += "extern const bclstring be_const_str_" + escape_operator(s) + ";\n" return ostr From f2f06866011dad8a725e4b444fdd270627d294f6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 18 Jan 2024 13:14:06 +0100 Subject: [PATCH 176/303] rm IPv6 (esp8266) build options, not supported --- platformio.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 29fc5a43a..7516ef8b8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -111,7 +111,6 @@ build_flags = ${esp_defaults.build_flags} ; NONOSDK22x_190703 = 2.2.2-dev(38a443e) -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH - ; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH -DUSE_IPV6 ; enables IPv6 ; VTABLES in Flash -DVTABLES_IN_FLASH ; remove the 4-bytes alignment for PSTR() From db70d9c8cb3543ec78fd87cc27880e2f112e37a0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 18 Jan 2024 15:55:59 +0100 Subject: [PATCH 177/303] Fix GPIOViewer exception 3 --- tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 25108f7a6..96281511c 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -351,7 +351,7 @@ void CmndGvSampling(void) { * GUI \*********************************************************************************************/ #ifdef USE_WEBSERVER -#define WEB_HANDLE_GV "gv1" +#define WEB_HANDLE_GV "gv" const char HTTP_BTN_MENU_GV[] PROGMEM = "

"; @@ -392,7 +392,7 @@ bool Xdrv121(uint32_t function) { } break; case FUNC_WEB_ADD_HANDLER: - Webserver->on(PSTR("/" WEB_HANDLE_GV), GVSetupAndStart); + WebServer_on(PSTR("/" WEB_HANDLE_GV), GVSetupAndStart); break; #endif // USE_WEBSERVER } From c9d0106007b259974e30dfa1b546a253c7a2a2ab Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 18 Jan 2024 16:32:28 +0100 Subject: [PATCH 178/303] Removed max number of 30 backlog entries --- CHANGELOG.md | 7 +- RELEASENOTES.md | 4 +- lib/default/LinkedList-1.2.3/LinkedList.h | 78 +--- .../LinkedList-1.2.3/LinkedList_with_sort.h | 419 ++++++++++++++++++ tasmota/include/tasmota.h | 1 - tasmota/my_user_config.h | 1 + tasmota/tasmota.ino | 24 +- tasmota/tasmota_support/support_command.ino | 25 +- .../tasmota_xdrv_driver/xdrv_07_domoticz.ino | 2 +- tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino | 4 +- 10 files changed, 438 insertions(+), 127 deletions(-) create mode 100644 lib/default/LinkedList-1.2.3/LinkedList_with_sort.h diff --git a/CHANGELOG.md b/CHANGELOG.md index ff7287194..5ec363e55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,8 +13,8 @@ All notable changes to this project will be documented in this file. - ESP32 MI BLE support for Xiaomi LYWSD02MMC (#20381) - LVGL option to add `lv.keyboard` extra widget (#20496) - GUI sensor separators (#20495) -- Command ``TimedPower [,ON|OFF|TOGGLE|BLINK]`` executes ``Power [ON|OFF|TOGGLE|BLINK] `` and after executes ``Power [OFF|ON|TOGGLE|OFF]`` -- Berry add solidification of strings longer than 255 bytes +- Command ``TimedPower [,ON|OFF|TOGGLE|BLINK]`` executes ``Power [ON|OFF|TOGGLE|BLINK] `` and after executes ``Power [OFF|ON|TOGGLE|BLINK_OFF]`` +- Berry solidification of strings longer than 255 bytes (#20529) ### Breaking Changed @@ -30,9 +30,10 @@ All notable changes to this project will be documented in this file. - Zigbee ramdom crash in main page (#20481) - Web file upload response on upload error (#20340) - ESP32 shutter exception 6 (divide by zero) on ``ShutterMode 4`` (#20524) +- GPIOViewer exception 3 ### Removed - +- Max number of 30 backlog entries ## [13.3.0.2] 20240111 ### Added diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 9d1d594a4..8180640b4 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -146,6 +146,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Berry provide lightweight options for `tasmota.wifi/eth/memory/rtc` [#20448](https://github.com/arendst/Tasmota/issues/20448) - Berry `tasmota.webcolor` [#20454](https://github.com/arendst/Tasmota/issues/20454) - Berry `debug.caller` [#20470](https://github.com/arendst/Tasmota/issues/20470) +- Berry solidification of strings longer than 255 bytes [#20529](https://github.com/arendst/Tasmota/issues/20529) - LVGL `lv.str_arr` [#20480](https://github.com/arendst/Tasmota/issues/20480) - LVGL option to add `lv.keyboard` extra widget [#20496](https://github.com/arendst/Tasmota/issues/20496) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) @@ -179,4 +180,5 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Berry claiming UART0 if needed [#20324](https://github.com/arendst/Tasmota/issues/20324) - Matter Contact sensor was not triggering any update [#20232](https://github.com/arendst/Tasmota/issues/20232) -### Removed \ No newline at end of file +### Removed +- Max number of 30 backlog entries diff --git a/lib/default/LinkedList-1.2.3/LinkedList.h b/lib/default/LinkedList-1.2.3/LinkedList.h index 64321cf01..4453126de 100644 --- a/lib/default/LinkedList-1.2.3/LinkedList.h +++ b/lib/default/LinkedList-1.2.3/LinkedList.h @@ -7,6 +7,8 @@ Created by Ivan Seidel Gomes, March, 2013. Released into the public domain. + + 20240118 - Removed sort functions not used by Tasmota (@arendst) */ @@ -39,8 +41,6 @@ protected: ListNode* getNode(int index); - ListNode* findEndOfSortedString(ListNode *p, int (*cmp)(T &, T &)); - public: LinkedList(); LinkedList(int sizeIndex, T _t); //initiate list size and default value @@ -96,11 +96,6 @@ public: */ virtual void clear(); - /* - Sort the list, given a comparison function - */ - virtual void sort(int (*cmp)(T &, T &)); - // add support to array brakets [] operator inline T& operator[](int index); inline T& operator[](size_t& i) { return this->get(i); } @@ -347,73 +342,4 @@ void LinkedList::clear(){ shift(); } -template -void LinkedList::sort(int (*cmp)(T &, T &)){ - if(_size < 2) return; // trivial case; - - for(;;) { - - ListNode **joinPoint = &root; - - while(*joinPoint) { - ListNode *a = *joinPoint; - ListNode *a_end = findEndOfSortedString(a, cmp); - - if(!a_end->next ) { - if(joinPoint == &root) { - last = a_end; - isCached = false; - return; - } - else { - break; - } - } - - ListNode *b = a_end->next; - ListNode *b_end = findEndOfSortedString(b, cmp); - - ListNode *tail = b_end->next; - - a_end->next = NULL; - b_end->next = NULL; - - while(a && b) { - if(cmp(a->data, b->data) <= 0) { - *joinPoint = a; - joinPoint = &a->next; - a = a->next; - } - else { - *joinPoint = b; - joinPoint = &b->next; - b = b->next; - } - } - - if(a) { - *joinPoint = a; - while(a->next) a = a->next; - a->next = tail; - joinPoint = &a->next; - } - else { - *joinPoint = b; - while(b->next) b = b->next; - b->next = tail; - joinPoint = &b->next; - } - } - } -} - -template -ListNode* LinkedList::findEndOfSortedString(ListNode *p, int (*cmp)(T &, T &)) { - while(p->next && cmp(p->data, p->next->data) <= 0) { - p = p->next; - } - - return p; -} - #endif diff --git a/lib/default/LinkedList-1.2.3/LinkedList_with_sort.h b/lib/default/LinkedList-1.2.3/LinkedList_with_sort.h new file mode 100644 index 000000000..64321cf01 --- /dev/null +++ b/lib/default/LinkedList-1.2.3/LinkedList_with_sort.h @@ -0,0 +1,419 @@ +/* + LinkedList.h - V1.1 - Generic LinkedList implementation + Works better with FIFO, because LIFO will need to + search the entire List to find the last one; + + For instructions, go to https://github.com/ivanseidel/LinkedList + + Created by Ivan Seidel Gomes, March, 2013. + Released into the public domain. +*/ + + +#ifndef LinkedList_h +#define LinkedList_h + +#include + +template +struct ListNode +{ + T data; + ListNode *next; +}; + +template +class LinkedList{ + +protected: + int _size; + ListNode *root; + ListNode *last; + + // Helps "get" method, by saving last position + ListNode *lastNodeGot; + int lastIndexGot; + // isCached should be set to FALSE + // everytime the list suffer changes + bool isCached; + + ListNode* getNode(int index); + + ListNode* findEndOfSortedString(ListNode *p, int (*cmp)(T &, T &)); + +public: + LinkedList(); + LinkedList(int sizeIndex, T _t); //initiate list size and default value + ~LinkedList(); + + /* + Returns current size of LinkedList + */ + virtual int size(); + /* + Adds a T object in the specified index; + Unlink and link the LinkedList correcly; + Increment _size + */ + virtual bool add(int index, T); + /* + Adds a T object in the end of the LinkedList; + Increment _size; + */ + virtual bool add(T); + /* + Adds a T object in the start of the LinkedList; + Increment _size; + */ + virtual bool unshift(T); + /* + Set the object at index, with T; + */ + virtual bool set(int index, T); + /* + Remove object at index; + If index is not reachable, returns false; + else, decrement _size + */ + virtual T remove(int index); + /* + Remove last object; + */ + virtual T pop(); + /* + Remove first object; + */ + virtual T shift(); + /* + Get the index'th element on the list; + Return Element if accessible, + else, return false; + */ + virtual T get(int index); + + /* + Clear the entire array + */ + virtual void clear(); + + /* + Sort the list, given a comparison function + */ + virtual void sort(int (*cmp)(T &, T &)); + + // add support to array brakets [] operator + inline T& operator[](int index); + inline T& operator[](size_t& i) { return this->get(i); } + inline const T& operator[](const size_t& i) const { return this->get(i); } + +}; + +// Initialize LinkedList with false values +template +LinkedList::LinkedList() +{ + root=NULL; + last=NULL; + _size=0; + + lastNodeGot = root; + lastIndexGot = 0; + isCached = false; +} + +// Clear Nodes and free Memory +template +LinkedList::~LinkedList() +{ + ListNode* tmp; + while(root!=NULL) + { + tmp=root; + root=root->next; + delete tmp; + } + last = NULL; + _size=0; + isCached = false; +} + +/* + Actualy "logic" coding +*/ + +template +ListNode* LinkedList::getNode(int index){ + + int _pos = 0; + ListNode* current = root; + + // Check if the node trying to get is + // immediatly AFTER the previous got one + if(isCached && lastIndexGot <= index){ + _pos = lastIndexGot; + current = lastNodeGot; + } + + while(_pos < index && current){ + current = current->next; + + _pos++; + } + + // Check if the object index got is the same as the required + if(_pos == index){ + isCached = true; + lastIndexGot = index; + lastNodeGot = current; + + return current; + } + + return NULL; +} + +template +int LinkedList::size(){ + return _size; +} + +template +LinkedList::LinkedList(int sizeIndex, T _t){ + for (int i = 0; i < sizeIndex; i++){ + add(_t); + } +} + +template +bool LinkedList::add(int index, T _t){ + + if(index >= _size) + return add(_t); + + if(index == 0) + return unshift(_t); + + ListNode *tmp = new ListNode(), + *_prev = getNode(index-1); + tmp->data = _t; + tmp->next = _prev->next; + _prev->next = tmp; + + _size++; + isCached = false; + + return true; +} + +template +bool LinkedList::add(T _t){ + + ListNode *tmp = new ListNode(); + tmp->data = _t; + tmp->next = NULL; + + if(root){ + // Already have elements inserted + last->next = tmp; + last = tmp; + }else{ + // First element being inserted + root = tmp; + last = tmp; + } + + _size++; + isCached = false; + + return true; +} + +template +bool LinkedList::unshift(T _t){ + + if(_size == 0) + return add(_t); + + ListNode *tmp = new ListNode(); + tmp->next = root; + tmp->data = _t; + root = tmp; + + _size++; + isCached = false; + + return true; +} + + +template +T& LinkedList::operator[](int index) { + return getNode(index)->data; +} + +template +bool LinkedList::set(int index, T _t){ + // Check if index position is in bounds + if(index < 0 || index >= _size) + return false; + + getNode(index)->data = _t; + return true; +} + +template +T LinkedList::pop(){ + if(_size <= 0) + return T(); + + isCached = false; + + if(_size >= 2){ + ListNode *tmp = getNode(_size - 2); + T ret = tmp->next->data; + delete(tmp->next); + tmp->next = NULL; + last = tmp; + _size--; + return ret; + }else{ + // Only one element left on the list + T ret = root->data; + delete(root); + root = NULL; + last = NULL; + _size = 0; + return ret; + } +} + +template +T LinkedList::shift(){ + if(_size <= 0) + return T(); + + if(_size > 1){ + ListNode *_next = root->next; + T ret = root->data; + delete(root); + root = _next; + _size --; + isCached = false; + + return ret; + }else{ + // Only one left, then pop() + return pop(); + } + +} + +template +T LinkedList::remove(int index){ + if (index < 0 || index >= _size) + { + return T(); + } + + if(index == 0) + return shift(); + + if (index == _size-1) + { + return pop(); + } + + ListNode *tmp = getNode(index - 1); + ListNode *toDelete = tmp->next; + T ret = toDelete->data; + tmp->next = tmp->next->next; + delete(toDelete); + _size--; + isCached = false; + return ret; +} + + +template +T LinkedList::get(int index){ + ListNode *tmp = getNode(index); + + return (tmp ? tmp->data : T()); +} + +template +void LinkedList::clear(){ + while(size() > 0) + shift(); +} + +template +void LinkedList::sort(int (*cmp)(T &, T &)){ + if(_size < 2) return; // trivial case; + + for(;;) { + + ListNode **joinPoint = &root; + + while(*joinPoint) { + ListNode *a = *joinPoint; + ListNode *a_end = findEndOfSortedString(a, cmp); + + if(!a_end->next ) { + if(joinPoint == &root) { + last = a_end; + isCached = false; + return; + } + else { + break; + } + } + + ListNode *b = a_end->next; + ListNode *b_end = findEndOfSortedString(b, cmp); + + ListNode *tail = b_end->next; + + a_end->next = NULL; + b_end->next = NULL; + + while(a && b) { + if(cmp(a->data, b->data) <= 0) { + *joinPoint = a; + joinPoint = &a->next; + a = a->next; + } + else { + *joinPoint = b; + joinPoint = &b->next; + b = b->next; + } + } + + if(a) { + *joinPoint = a; + while(a->next) a = a->next; + a->next = tail; + joinPoint = &a->next; + } + else { + *joinPoint = b; + while(b->next) b = b->next; + b->next = tail; + joinPoint = &b->next; + } + } + } +} + +template +ListNode* LinkedList::findEndOfSortedString(ListNode *p, int (*cmp)(T &, T &)) { + while(p->next && cmp(p->data, p->next->data) <= 0) { + p = p->next; + } + + return p; +} + +#endif diff --git a/tasmota/include/tasmota.h b/tasmota/include/tasmota.h index b3fa0cbe4..3685fbc7e 100644 --- a/tasmota/include/tasmota.h +++ b/tasmota/include/tasmota.h @@ -220,7 +220,6 @@ const uint16_t MAX_LOGSZ = 700; // Max number of characters in log l const uint8_t SENSOR_MAX_MISS = 5; // Max number of missed sensor reads before deciding it's offline -const uint8_t MAX_BACKLOG = 30; // Max number of commands in backlog const uint32_t MIN_BACKLOG_DELAY = 200; // Minimal backlog delay in mSeconds const uint8_t MAX_TIMED_CMND = 16; // Max number of timed commands diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index d74edd0cb..b58adf14a 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -497,6 +497,7 @@ // -- Rules or Script ---------------------------- // Select none or only one of the below defines USE_RULES or USE_SCRIPT #define USE_RULES // Add support for rules (+8k code) +// #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) // #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) // #define SUPPORT_IF_STATEMENT // Add support for IF statement in rules (+4k2 code, -332 bytes mem) // #define USER_RULE1 "" // Add rule1 data saved at initial firmware load or when command reset is executed diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index e7d4c455c..91a2c0b4f 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -411,11 +411,6 @@ struct TasmotaGlobal_t { uint8_t pwm_dimmer_led_bri; // Adjusted brightness LED level #endif // USE_PWM_DIMMER -#ifndef SUPPORT_IF_STATEMENT - uint8_t backlog_index; // Command backlog index - uint8_t backlog_pointer; // Command backlog pointer - String backlog[MAX_BACKLOG]; // Command backlog buffer -#endif tTimedCmnd timed_cmnd[MAX_TIMED_CMND]; // Timed command buffer #ifdef MQTT_DATA_STRING @@ -438,19 +433,15 @@ struct TasmotaGlobal_t { #endif // PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED #ifdef USE_BERRY - bool berry_fast_loop_enabled = false; // is Berry fast loop enabled, i.e. control is passed at each loop iteration + bool berry_fast_loop_enabled = false; // is Berry fast loop enabled, i.e. control is passed at each loop iteration #endif // USE_BERRY } TasmotaGlobal; TSettings* Settings = nullptr; -#ifdef SUPPORT_IF_STATEMENT - #include - LinkedList backlog; // Command backlog implemented with LinkedList - #define BACKLOG_EMPTY (backlog.size() == 0) -#else - #define BACKLOG_EMPTY (TasmotaGlobal.backlog_pointer == TasmotaGlobal.backlog_index) -#endif +#include +LinkedList backlog; // Command backlog implemented with LinkedList +#define BACKLOG_EMPTY (backlog.size() == 0) /*********************************************************************************************\ * Main @@ -794,14 +785,7 @@ void BacklogLoop(void) { bool nodelay_detected = false; String cmd; do { -#ifdef SUPPORT_IF_STATEMENT cmd = backlog.shift(); -#else - cmd = TasmotaGlobal.backlog[TasmotaGlobal.backlog_pointer]; - TasmotaGlobal.backlog[TasmotaGlobal.backlog_pointer] = (const char*) nullptr; // Force deallocation of the String internal memory - TasmotaGlobal.backlog_pointer++; - if (TasmotaGlobal.backlog_pointer >= MAX_BACKLOG) { TasmotaGlobal.backlog_pointer = 0; } -#endif nodelay_detected = !strncasecmp_P(cmd.c_str(), PSTR(D_CMND_NODELAY), strlen(D_CMND_NODELAY)); if (nodelay_detected) { nodelay = true; } } while (!BACKLOG_EMPTY && nodelay_detected); diff --git a/tasmota/tasmota_support/support_command.ino b/tasmota/tasmota_support/support_command.ino index 398fd11cd..8e6158b00 100644 --- a/tasmota/tasmota_support/support_command.ino +++ b/tasmota/tasmota_support/support_command.ino @@ -580,14 +580,7 @@ void CmndBacklog(void) { } char *blcommand = strtok(XdrvMailbox.data, ";"); -#ifdef SUPPORT_IF_STATEMENT - while ((blcommand != nullptr) && (backlog.size() < MAX_BACKLOG)) -#else - uint32_t bl_pointer = (!TasmotaGlobal.backlog_pointer) ? MAX_BACKLOG -1 : TasmotaGlobal.backlog_pointer; - bl_pointer--; - while ((blcommand != nullptr) && (TasmotaGlobal.backlog_index != bl_pointer)) -#endif - { + while (blcommand != nullptr) { // Ignore semicolon (; = end of single command) between brackets {} char *next = strchr(blcommand, '\0') +1; // Prepare for next ; while ((next != nullptr) && (ChrCount(blcommand, "{") != ChrCount(blcommand, "}"))) { // Check for valid {} pair @@ -606,17 +599,7 @@ void CmndBacklog(void) { } // Do not allow command Reset in backlog if ((*blcommand != '\0') && (strncasecmp_P(blcommand, PSTR(D_CMND_RESET), strlen(D_CMND_RESET)) != 0)) { -#ifdef SUPPORT_IF_STATEMENT - if (backlog.size() < MAX_BACKLOG) { - backlog.add(blcommand); - } -#else - TasmotaGlobal.backlog[TasmotaGlobal.backlog_index] = blcommand; - TasmotaGlobal.backlog_index++; - if (TasmotaGlobal.backlog_index >= MAX_BACKLOG) { - TasmotaGlobal.backlog_index = 0; - } -#endif + backlog.add(blcommand); } blcommand = strtok(nullptr, ";"); } @@ -625,11 +608,7 @@ void CmndBacklog(void) { TasmotaGlobal.backlog_timer = millis(); } else { bool blflag = BACKLOG_EMPTY; -#ifdef SUPPORT_IF_STATEMENT backlog.clear(); -#else - TasmotaGlobal.backlog_pointer = TasmotaGlobal.backlog_index; -#endif ResponseCmndChar(blflag ? PSTR(D_JSON_EMPTY) : PSTR(D_JSON_ABORTED)); } } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino b/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino index 4d4c54102..68bccfff7 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_07_domoticz.ino @@ -657,7 +657,7 @@ void DomoticzSaveSettings(void) { snprintf_P(arg_idx, sizeof(arg_idx), PSTR("l%d"), i -1); cmnd += AddWebCommand(cmnd2, arg_idx, PSTR("0")); } - ExecuteWebCommand((char*)cmnd.c_str()); // Note: beware of max number of commands in backlog currently 30 (MAX_BACKLOG) + ExecuteWebCommand((char*)cmnd.c_str()); } #endif // USE_WEBSERVER diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino index 13389b082..81f6ab23d 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino @@ -2066,7 +2066,7 @@ void ExecuteCommandBlock(const char * commands, int len) sCurrentCommand.trim(); /* if (sCurrentCommand.length() > 0 - && backlog.size() < MAX_BACKLOG && !TasmotaGlobal.backlog_mutex) + && !TasmotaGlobal.backlog_mutex) { //Insert into backlog TasmotaGlobal.backlog_mutex = true; @@ -2075,7 +2075,7 @@ void ExecuteCommandBlock(const char * commands, int len) insertPosition++; } */ - if ((sCurrentCommand.length() > 0) && (backlog.size() < MAX_BACKLOG)) { + if (sCurrentCommand.length() > 0) { //Insert into backlog backlog.add(insertPosition, sCurrentCommand); insertPosition++; From 0595130fcf95b9b3cb33322070e01319cc410779 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 18 Jan 2024 16:52:24 +0100 Subject: [PATCH 179/303] Update my_user_config.h --- tasmota/my_user_config.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index b58adf14a..1b2ba3c1b 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -496,15 +496,15 @@ // -- Rules or Script ---------------------------- // Select none or only one of the below defines USE_RULES or USE_SCRIPT -#define USE_RULES // Add support for rules (+8k code) -// #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) -// #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) -// #define SUPPORT_IF_STATEMENT // Add support for IF statement in rules (+4k2 code, -332 bytes mem) +#define USE_RULES // Add support for rules (+13k code, +768 bytes mem) +// #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k7 code) +// #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k3 code) +// #define SUPPORT_IF_STATEMENT // Add support for IF statement in rules (+3k3) // #define USER_RULE1 "" // Add rule1 data saved at initial firmware load or when command reset is executed // #define USER_RULE2 "" // Add rule2 data saved at initial firmware load or when command reset is executed // #define USER_RULE3 "" // Add rule3 data saved at initial firmware load or when command reset is executed -//#define USE_SCRIPT // Add support for script (+17k code) +//#define USE_SCRIPT // Add support for script (+36k code, +1k mem) // #define USE_SCRIPT_FATFS 4 // Script: Add FAT FileSystem Support // #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) From c0a78212a4ee103978a8f404fc159cb2f8959d27 Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Thu, 18 Jan 2024 20:26:18 +0100 Subject: [PATCH 180/303] [VS Code] Make tooltip more clear (#20536) --- .vscode/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index f764ed574..7714ebe96 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -52,7 +52,7 @@ }, { "text": "$(arrow-right)", - "tooltip": "PlatformIO: Upload and Monitor", + "tooltip": "PlatformIO: Build, Upload and Monitor", "commands": "platformio-ide.uploadAndMonitor" }, { From 06c2d78d5f370f181893eb176c8fdf67158384a9 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 18 Jan 2024 22:01:39 +0100 Subject: [PATCH 181/303] Berry assigment to list with negative index (#20537) --- CHANGELOG.md | 1 + lib/libesp32/berry/src/be_api.c | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ec363e55..138793c34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ All notable changes to this project will be documented in this file. - Web file upload response on upload error (#20340) - ESP32 shutter exception 6 (divide by zero) on ``ShutterMode 4`` (#20524) - GPIOViewer exception 3 +- Berry assigment to list with negative index ### Removed - Max number of 30 backlog entries diff --git a/lib/libesp32/berry/src/be_api.c b/lib/libesp32/berry/src/be_api.c index 5cc755929..31755604f 100644 --- a/lib/libesp32/berry/src/be_api.c +++ b/lib/libesp32/berry/src/be_api.c @@ -731,10 +731,13 @@ BERRY_API bbool be_getindex(bvm *vm, int index) static bvalue* list_setindex(blist *list, bvalue *key) { int idx = var_toidx(key); - if (idx < be_list_count(list)) { - return be_list_at(list, idx); + if (idx < 0) { + idx = list->count + idx; } - return NULL; + if (idx < 0 || idx >= list->count) { + return NULL; + } + return be_list_at(list, idx); } BERRY_API bbool be_setindex(bvm *vm, int index) From 2b0d603d0351b37b8a4c6d4f69481a180c3e324e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 18 Jan 2024 22:39:50 +0100 Subject: [PATCH 182/303] Esp8266 ipv6 (#20539) * esp8266 ipv6 compatible framework --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- platformio.ini | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 61722058f..ff5fa0de6 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -6,7 +6,7 @@ - [ ] The pull request is done against the latest development branch - [ ] Only relevant files were touched - [ ] Only one feature/fix was added per PR and the code change compiles without warnings - - [ ] The code change is tested and works with Tasmota core ESP8266 V.2.7.5 + - [ ] The code change is tested and works with Tasmota core ESP8266 V.2.7.6 - [ ] The code change is tested and works with Tasmota core ESP32 V.2.0.14 - [ ] I accept the [CLA](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla). diff --git a/platformio.ini b/platformio.ini index 7516ef8b8..ba61a566b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -111,6 +111,7 @@ build_flags = ${esp_defaults.build_flags} ; NONOSDK22x_190703 = 2.2.2-dev(38a443e) -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH + ; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH -DUSE_IPV6 ; enables IPv6 ; VTABLES in Flash -DVTABLES_IN_FLASH ; remove the 4-bytes alignment for PSTR() @@ -139,7 +140,7 @@ lib_ignore = [core] ; *** Esp8266 Tasmota modified Arduino core based on core 2.7.4. Added Backport for PWM selection -platform = https://github.com/tasmota/platform-espressif8266/releases/download/2024.01.00/platform-espressif8266.zip +platform = https://github.com/tasmota/platform-espressif8266/releases/download/2024.01.01/platform-espressif8266.zip platform_packages = build_unflags = ${esp_defaults.build_unflags} build_flags = ${esp82xx_defaults.build_flags} From 6b4254a014dfeddf4de498183eb509852e506996 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 18 Jan 2024 23:24:18 +0100 Subject: [PATCH 183/303] Berry syntax coloring for Notepad++ (by FransO) (#20541) --- CHANGELOG.md | 1 + .../plugins/Notepad++/TasmotaBerry-udl.xml | 64 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 lib/libesp32/berry/tools/plugins/Notepad++/TasmotaBerry-udl.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index 138793c34..4dec1c853 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file. - GUI sensor separators (#20495) - Command ``TimedPower [,ON|OFF|TOGGLE|BLINK]`` executes ``Power [ON|OFF|TOGGLE|BLINK] `` and after executes ``Power [OFF|ON|TOGGLE|BLINK_OFF]`` - Berry solidification of strings longer than 255 bytes (#20529) +- Berry syntax coloring for Notepad++ (by FransO) ### Breaking Changed diff --git a/lib/libesp32/berry/tools/plugins/Notepad++/TasmotaBerry-udl.xml b/lib/libesp32/berry/tools/plugins/Notepad++/TasmotaBerry-udl.xml new file mode 100644 index 000000000..c535c6d09 --- /dev/null +++ b/lib/libesp32/berry/tools/plugins/Notepad++/TasmotaBerry-udl.xml @@ -0,0 +1,64 @@ + + + + + + + + 00# 01 02 03#- 04-# + + 0x + A B C D E F a b c d e f + + + + .. + - ! ~ * / % + - << >> & ^ | .. < <= > >= == != && || ? ( ) { } [ ] . , : = += -= *= /= %= &= |= ^= <<= >>= + + + + + if do while for def + else elif + end + + + + if elif else while for def end class break continue return true false nil var do import as try except raise static + nil boolean integer real string function class instance module list map range global file math bytes persist + assert print input super type classname classof number int real str bool module size compile issubclass is instance call open + file.write file.read file.readbytes file.readline file.seek file.tell file.size file.close list.tostring list.push list.pop list.insert list.item list.setitem list.size list.resize list.clear list.iter list.keys list.concat list.reverse list.copy map.tostring map.insert map.remove map.item map.setitem map.insert map.contains nap.find map.size map.iter map.keys range.tostring range.iter range.lower range.upper range.incr range.setrange string.count string.split string.find string.hex string.byte string.char string.toupper string.tolower string.tr string.replace string.escape string.format math.pi math.nan math.imin math.imax math.floor math.ceil math.abs math.rand math.srand math.isnan math.sqrt math.cos math.tan math.asin math.acos math.atan math.atan2 math.deg math.rad math.sinh math.cosh math.tanh bytes.size bytes.resize bytes.clear bytes.reverse bytes.copy bytes.ismapped bytes.get bytes.geti bytes.set bytes.seti bytes.add bytes.getfloat bytes.setfloat bytes.getbits bytes.setbits bytes.setbytes bytes.tostring bytes.tohex bytes.fromhex bytes.asstring bytes.tob64 bytes.fromb64 global.contains global.id global.setmember json.load json.dump introspect.members introspect.get introspect.set introspect.name introspect.ismethod introspect.module introspect.setmodule introspect.topr os.getcmd os.chdir os.mkdir os.remove os.listdir os.system os.exit os.path.isdir os.path.isfile os.path.exists os.path.split os.path.splitext persist.save persist.find + + + + + 00" 01\ 02" 03' 04\ 05' 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 30c3165b6f8966f0b57133c3ec4bbdc4e8ca4a31 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 18 Jan 2024 23:35:53 +0100 Subject: [PATCH 184/303] Audio for Core3, MP3Stream and Shine (#20540) --- .../xdrv_42_0_i2s_0_config_idf51.ino | 3 +- .../xdrv_42_0_i2s_audio_idf51.ino | 10 ++- .../xdrv_42_1_i2s_mp3mic.ino | 2 +- .../xdrv_42_1_i2s_mp3mic_idf51.ino | 33 ++++---- .../xdrv_42_2_i2s_mp3stream.ino | 4 +- .../xdrv_42_2_i2s_mp3stream_idf51.ino | 78 +++++++++++++++++++ 6 files changed, 107 insertions(+), 23 deletions(-) create mode 100644 tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream_idf51.ino diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_0_config_idf51.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_0_config_idf51.ino index f724da1f0..414a014ce 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_0_config_idf51.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_0_config_idf51.ino @@ -79,7 +79,8 @@ typedef struct{ uint8_t slot_config = I2S_SLOT_MSB;// B07 - slot configuration MSB = 0, PCM = 1, PHILIPS = 2 uint8_t channels = 2; // B08 - mono/stereo - 1 is added for both bool apll = 1; // B09 - will be ignored on unsupported SOC's - uint8_t spare[6]; // B0A-0F + bool stream_enable = 0; // B0A - enable streaming of MP3 + uint8_t spare[5]; // B0B-0F } tx; struct { uint32_t sample_rate = 16000; // B00-03 diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio_idf51.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio_idf51.ino index 33dae7ec6..e772add39 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio_idf51.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio_idf51.ino @@ -65,6 +65,7 @@ void Cmd_Time(void); void Rtttl(char *buffer); void CmndI2SRtttl(void); void I2sWebRadioStopPlaying(void); +void CmndI2SMP3Stream(void); /*********************************************************************************************\ * More structures @@ -79,7 +80,7 @@ struct AUDIO_I2S_MP3_t { void *mp3ram = NULL; #endif // USE_I2S_MP3 -#if defined(USE_I2S_MP3) || defined(USE_I2S_WEBRADIO) +#if defined(USE_I2S_MP3) || defined(USE_I2S_WEBRADIO) || defined(USE_SHINE) || defined(MP3_MIC_STREAM) AudioGeneratorMP3 *decoder = NULL; TaskHandle_t mp3_task_handle; TaskHandle_t mic_task_handle; @@ -108,6 +109,9 @@ struct AUDIO_I2S_MP3_t { } audio_i2s_mp3; +#define I2S_AUDIO_MODE_MIC 1 +#define I2S_AUDIO_MODE_SPK 2 + /*********************************************************************************************\ * Commands definitions \*********************************************************************************************/ @@ -1033,7 +1037,7 @@ void CmndI2SMicGain(void) { \*********************************************************************************************/ void I2sMp3Loop(void); -void I2sMp3Init(void); +void I2sMp3Init(uint32_t on); void MP3ShowStream(void); bool Xdrv42(uint32_t function) { @@ -1059,7 +1063,7 @@ bool Xdrv42(uint32_t function) { break; case FUNC_WEB_ADD_HANDLER: #if defined(USE_SHINE) && defined(MP3_MIC_STREAM) - audio_i2s.stream_enable = 1; + audio_i2s.Settings->tx.stream_enable = 1; I2sMp3Init(1); #endif #if defined(I2S_BRIDGE) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic.ino index d283abcaa..17974cc6e 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic.ino @@ -18,7 +18,7 @@ */ -#if ESP32 && (ESP_IDF_VERSION_MAJOR < 5) +#if defined(ESP32) && (ESP_IDF_VERSION_MAJOR < 5) #if ( (defined(USE_I2S_AUDIO) && defined(USE_I2S_MIC)) || defined(USE_M5STACK_CORE2) || defined(ESP32S3_BOX) ) uint32_t SpeakerMic(uint8_t spkr) { diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic_idf51.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic_idf51.ino index cfc9ba166..e846d07b6 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic_idf51.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic_idf51.ino @@ -70,14 +70,14 @@ void mic_task(void *arg){ shine_set_config_mpeg_defaults(&config.mpeg); - if (audio_i2s.mic_channels == 1) { + if (audio_i2s.Settings->rx.channels == 1) { config.mpeg.mode = MONO; } else { config.mpeg.mode = STEREO; } config.mpeg.bitr = 128; - config.wave.samplerate = audio_i2s.mic_rate; - config.wave.channels = (channels)audio_i2s.mic_channels; + config.wave.samplerate = audio_i2s.Settings->rx.sample_rate; + config.wave.channels = (channels)audio_i2s.Settings->rx.channels; if (shine_check_config(config.wave.samplerate, config.mpeg.bitr) < 0) { error = 3; @@ -91,7 +91,7 @@ void mic_task(void *arg){ } samples_per_pass = shine_samples_per_pass(s); - bytesize = samples_per_pass * 2 * audio_i2s.mic_channels; + bytesize = samples_per_pass * 2 * audio_i2s.Settings->rx.channels; buffer = (int16_t*)malloc(bytesize); if (!buffer) { @@ -103,17 +103,18 @@ void mic_task(void *arg){ while (!audio_i2s_mp3.mic_stop) { uint32_t bytes_read; - i2s_read(audio_i2s.mic_port, (char *)buffer, bytesize, &bytes_read, (100 / portTICK_RATE_MS)); + bytes_read = audio_i2s.in->readMic((uint8_t*)buffer, bytesize, true /*dc_block*/, false /*apply_gain*/, true /*lowpass*/, nullptr /*peak_ptr*/); + // i2s_read(audio_i2s.mic_port, (char *)buffer, bytesize, &bytes_read, (100 / portTICK_PERIOD_MS)); - if (audio_i2s.mic_gain > 1) { + if (audio_i2s.Settings->rx.gain > 1) { // set gain for (uint32_t cnt = 0; cnt < bytes_read / 2; cnt++) { - buffer[cnt] *= audio_i2s.mic_gain; + buffer[cnt] *= audio_i2s.Settings->rx.gain; } } ucp = shine_encode_buffer_interleaved(s, buffer, &written); - if (!audio_i2s_mp3.use_stream) { + if (!audio_i2s.Settings->tx.stream_enable) { bwritten = mp3_out.write(ucp, written); if (bwritten != written) { break; @@ -152,11 +153,11 @@ exit: audio_i2s_mp3.client.stop(); } - SpeakerMic(MODE_SPK); + SpeakerMic(I2S_AUDIO_MODE_SPK); audio_i2s_mp3.mic_stop = 0; audio_i2s_mp3.mic_error = error; AddLog(LOG_LEVEL_INFO, PSTR("mp3task result code: %d"), error); - audio_i2s.mic_task_h = 0; + audio_i2s_mp3.mic_task_handle = 0; audio_i2s_mp3.recdur = 0; audio_i2s_mp3.stream_active = 0; vTaskDelete(NULL); @@ -166,14 +167,14 @@ exit: int32_t i2s_record_shine(char *path) { esp_err_t err = ESP_OK; - if (audio_i2s.mic_port == 0) { + if (audio_i2s.in) { if (audio_i2s_mp3.decoder || audio_i2s_mp3.mp3) return 0; } - err = SpeakerMic(MODE_MIC); + err = SpeakerMic(I2S_AUDIO_MODE_MIC); if (err) { - if (audio_i2s.mic_port == 0) { - SpeakerMic(MODE_SPK); + if (audio_i2s.in) { + SpeakerMic(I2S_AUDIO_MODE_SPK); } AddLog(LOG_LEVEL_INFO, PSTR("mic init error: %d"), err); return err; @@ -191,7 +192,7 @@ esp_err_t err = ESP_OK; stack = 8000; } - err = xTaskCreatePinnedToCore(mic_task, "MIC", stack, NULL, 3, &audio_i2s.mic_task_h, 1); + err = xTaskCreatePinnedToCore(mic_task, "MIC", stack, NULL, 3, &audio_i2s_mp3.mic_task_handle, 1); return err; } @@ -206,7 +207,7 @@ void Cmd_MicRec(void) { ResponseCmndChar(XdrvMailbox.data); } } else { - if (audio_i2s.mic_task_h) { + if (audio_i2s_mp3.mic_task_handle) { // stop task audio_i2s_mp3.mic_stop = 1; while (audio_i2s_mp3.mic_stop) { diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream.ino index af4a873bf..1fc06477f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream.ino @@ -1,5 +1,5 @@ -#ifdef ESP32 +#if defined(ESP32) && (ESP_IDF_VERSION_MAJOR < 5) #if defined(USE_SHINE) && ( (defined(USE_I2S_AUDIO) && defined(USE_I2S_MIC)) || defined(USE_M5STACK_CORE2) || defined(ESP32S3_BOX) ) #ifdef MP3_MIC_STREAM @@ -61,4 +61,4 @@ void Cmd_MP3Stream(void) { #endif // USE_SHINE -#endif // ESP32 +#endif // defined(ESP32) && (ESP_IDF_VERSION_MAJOR < 5) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream_idf51.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream_idf51.ino new file mode 100644 index 000000000..5a83f0d70 --- /dev/null +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream_idf51.ino @@ -0,0 +1,78 @@ +/* + xdrv_42_2_i2s_mp3stream_idf51.ino - Audio dac support for Tasmota + + Copyright (C) 2024 Gerhard Mutz and Theo Arends + + 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 . +*/ + +#if defined(ESP32) && ESP_IDF_VERSION_MAJOR >= 5 +#if defined(USE_I2S_AUDIO) && defined(USE_SHINE) && defined(MP3_MIC_STREAM) + +#ifndef MP3_STREAM_PORT +#define MP3_STREAM_PORT 81 +#endif + + +void Stream_mp3(void) { + if (!audio_i2s.Settings->tx.stream_enable) { + return; + } + + if (audio_i2s_mp3.stream_active) { + return; + } + AddLog(LOG_LEVEL_INFO, PSTR("I2S: Handle mp3server")); + audio_i2s_mp3.stream_active = 1; + audio_i2s_mp3.client = audio_i2s_mp3.MP3Server->client(); + AddLog(LOG_LEVEL_INFO, PSTR("I2S: Create client")); + i2s_record_shine((char*)"stream.mp3"); +} + +void I2sMp3Loop(void) { + if (audio_i2s_mp3.MP3Server) { + audio_i2s_mp3.MP3Server->handleClient(); + } +} + +void I2sMp3Init(uint32_t on) { + if (on) { + if (!audio_i2s_mp3.MP3Server) { + audio_i2s_mp3.MP3Server = new ESP8266WebServer(MP3_STREAM_PORT); + audio_i2s_mp3.MP3Server->on(PSTR("/stream.mp3"), Stream_mp3); + audio_i2s_mp3.MP3Server->on(PSTR("/stream.m3a"), Stream_mp3); + audio_i2s_mp3.MP3Server->begin(); + AddLog(LOG_LEVEL_INFO, PSTR("MP3: server created on port: %d "), MP3_STREAM_PORT); + } + } else { + if (audio_i2s_mp3.MP3Server) { + audio_i2s_mp3.MP3Server->stop(); + delete audio_i2s_mp3.MP3Server; + audio_i2s_mp3.MP3Server = nullptr; + AddLog(LOG_LEVEL_INFO, PSTR("MP3: server deleted")); + } + } +} + + +void CmndI2SMP3Stream(void) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + audio_i2s_mp3.stream_enable = XdrvMailbox.payload; + } + I2sMp3Init(audio_i2s_mp3.stream_enable); + ResponseCmndNumber(audio_i2s_mp3.stream_enable); +} + +#endif // defined(USE_I2S_AUDIO) && defined(USE_SHINE) && defined(MP3_MIC_STREAM) +#endif // defined(ESP32) && ESP_IDF_VERSION_MAJOR >= 5 From 860f3857d52ae9b078336084667b16e58b4c8395 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Fri, 19 Jan 2024 08:24:17 +0100 Subject: [PATCH 185/303] Berry/Zigbee add web hook per device for customized status display (#20542) --- CHANGELOG.md | 1 + tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dec1c853..a97e229d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file. - Command ``TimedPower [,ON|OFF|TOGGLE|BLINK]`` executes ``Power [ON|OFF|TOGGLE|BLINK] `` and after executes ``Power [OFF|ON|TOGGLE|BLINK_OFF]`` - Berry solidification of strings longer than 255 bytes (#20529) - Berry syntax coloring for Notepad++ (by FransO) +- Berry/Zigbee add web hook per device for customized status display ### Breaking Changed diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino index a27b25e2b..4f96e003c 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino @@ -2211,6 +2211,7 @@ void ZigbeeShow(bool json) uint32_t now = Rtc.utc_time; + // iterate through devices by alphabetical order for (uint32_t i = 0; i < zigbee_num; i++) { const Z_Device &device = zigbee_devices.devicesAt(sorted_idx[i]); uint16_t shortaddr = device.shortaddr; @@ -2365,6 +2366,10 @@ void ZigbeeShow(bool json) } WSContentSend_P(PSTR("{e}")); } +#ifdef USE_BERRY + // Berry hook to display additional customized information + callBerryZigbeeDispatcher("web_device_status", nullptr, nullptr, shortaddr); +#endif // USE_BERRY } WSContentSend_P(msg[ZB_WEB_LINE_END]); // Terminate current multi column table and open new table From 1eb1025c18a102f30ac12f5c6ebbcea369bb88ef Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Fri, 19 Jan 2024 13:28:12 +0100 Subject: [PATCH 186/303] Berry/Zigbee auto `import zigbee` (#20543) --- tasmota/tasmota_xdrv_driver/xdrv_52_7_berry_embedded.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_7_berry_embedded.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_7_berry_embedded.ino index f9e8a3db9..d7dfdfda8 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_7_berry_embedded.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_7_berry_embedded.ino @@ -89,6 +89,10 @@ const char berry_prog[] = "import solidify " #endif +#ifdef USE_ZIGBEE + "import zigbee " +#endif + #ifdef USE_MATTER_DEVICE "import matter " "global.matter_device = matter.Device() " From 0ccd958c6c443140427073922115e925c4ed902c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 19 Jan 2024 18:36:46 +0100 Subject: [PATCH 187/303] refactor Pio filesystem download script (#20544) * refactor FS download Pio script --- pio-tools/custom_target.py | 65 ++++++++++++++------------------------ 1 file changed, 24 insertions(+), 41 deletions(-) diff --git a/pio-tools/custom_target.py b/pio-tools/custom_target.py index 9623105aa..d1c133bcb 100644 --- a/pio-tools/custom_target.py +++ b/pio-tools/custom_target.py @@ -1,9 +1,11 @@ # Written by Maximilian Gerhardt # 29th December 2020 +# and Christian Baars, Johann Obermeier +# 2023 / 2024 # License: Apache # Expanded from functionality provided by PlatformIO's espressif32 and espressif8266 platforms, credited below. -# This script provides functions to download the filesystem (SPIFFS or LittleFS) from a running ESP32 / ESP8266 -# over the serial bootloader using esptool.py, and mklittlefs / mkspiffs for extracting. +# This script provides functions to download the filesystem (LittleFS) from a running ESP32 / ESP8266 +# over the serial bootloader using esptool.py, and mklittlefs for extracting. # run by either using the VSCode task "Custom" -> "Download Filesystem" # or by doing 'pio run -t downloadfs' (with optional '-e ') from the commandline. # output will be saved, by default, in the "unpacked_fs" of the project. @@ -22,10 +24,6 @@ Import("env") platform = env.PioPlatform() board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") -# Hack for using mklittlefs instead of mkspiffs -> needed since littlefs is not supported with this for ESP32 -if env["PIOPLATFORM"] == "espressif32": - #print("Replace MKSPIFFSTOOL with mklittlefs") - env.Replace( MKSPIFFSTOOL=platform.get_package_dir("tool-mklittlefs") + '/mklittlefs' ) class FSType(Enum): @@ -48,30 +46,22 @@ class FSInfo: class LittleFSInfo(FSInfo): def __init__(self, start, length, page_size, block_size): - if env["PIOPLATFORM"] == "espressif32": - #for ESP32: retrieve and evaluate, e.g. to mkspiffs_espressif32_arduino - self.tool = env.subst(env["MKSPIFFSTOOL"]) - else: - self.tool = env["MKFSTOOL"] # from mkspiffs package + self.tool = env["MKFSTOOL"] self.tool = join(platform.get_package_dir("tool-mklittlefs"), self.tool) super().__init__(FSType.LITTLEFS, start, length, page_size, block_size) def __repr__(self): - return f"FS type {self.fs_type} Start {hex(self.start)} Len {self.length} Page size {self.page_size} Block size {self.block_size} Tool: {self.tool}" + return f"{self.fs_type} Start {hex(self.start)} Len {self.length} Page size {self.page_size} Block size {self.block_size}" def get_extract_cmd(self, input_file, output_dir): - return [self.tool, "-b", str(self.block_size), "-p", str(self.page_size), "--unpack", output_dir, input_file] + return [self.tool, "-b", str(self.block_size), "-s", str(self.length), "-p", str(self.page_size), "--unpack", output_dir, input_file] class SPIFFSInfo(FSInfo): def __init__(self, start, length, page_size, block_size): - if env["PIOPLATFORM"] == "espressif32": - #for ESP32: retrieve and evaluate, e.g. to mkspiffs_espressif32_arduino - self.tool = env.subst(env["MKSPIFFSTOOL"]) - else: - self.tool = env["MKFSTOOL"] # from mkspiffs package - self.tool = join(platform.get_package_dir("tool-mkspiffs"), self.tool) + self.tool = env["MKFSTOOL"] + self.tool = join(platform.get_package_dir("tool-mklittlefs"), self.tool) super().__init__(FSType.SPIFFS, start, length, page_size, block_size) def __repr__(self): - return f"FS type {self.fs_type} Start {hex(self.start)} Len {self.length} Page size {self.page_size} Block size {self.block_size} Tool: {self.tool}" + return f"{self.fs_type} Start {hex(self.start)} Len {self.length} Page size {self.page_size} Block size {self.block_size}" def get_extract_cmd(self, input_file, output_dir): return f'"{self.tool}" -b {self.block_size} -p {self.page_size} --unpack "{output_dir}" "{input_file}"' @@ -169,15 +159,15 @@ def esp8266_get_esptoolpy_reset_flags(resetmethod): ## Script interface functions def parse_partition_table(content): entries = [e for e in content.split(b'\xaaP') if len(e) > 0] - print("Partition data:") + #print("Partition data:") for entry in entries: type = entry[1] if type in [0x82,0x83]: # SPIFFS or LITTLEFS offset = int.from_bytes(entry[2:5], byteorder='little', signed=False) size = int.from_bytes(entry[6:9], byteorder='little', signed=False) - print("type:",hex(type)) - print("address:",hex(offset)) - print("size:",hex(size)) + #print("type:",hex(type)) + #print("address:",hex(offset)) + #print("size:",hex(size)) env["SPIFFS_START"] = offset env["SPIFFS_SIZE"] = size env["SPIFFS_PAGE"] = int("0x100", 16) @@ -203,8 +193,8 @@ def get_partition_table(): fs_file ] esptoolpy_cmd = [env["PYTHONEXE"], esptoolpy] + esptoolpy_flags - print("Executing flash download command to read partition table.") - print(esptoolpy_cmd) + #print("Executing flash download command to read partition table.") + #print(esptoolpy_cmd) try: returncode = subprocess.call(esptoolpy_cmd, shell=False) except subprocess.CalledProcessError as exc: @@ -217,14 +207,14 @@ def get_fs_type_start_and_length(): platform = env["PIOPLATFORM"] if platform == "espressif32": print(f"Retrieving filesystem info for {mcu}.") - print("Partition file: " + str(env.subst("$PARTITIONS_TABLE_CSV"))) + #print("Partition file: " + str(env.subst("$PARTITIONS_TABLE_CSV"))) # esp32_fetch_spiffs_size(env) get_partition_table() return SPIFFSInfo(env["SPIFFS_START"], env["SPIFFS_SIZE"], env["SPIFFS_PAGE"], env["SPIFFS_BLOCK"]) elif platform == "espressif8266": print("Retrieving filesystem info for ESP8266.") - filesystem = board.get("build.filesystem", "spiffs") - if filesystem not in ("spiffs", "littlefs"): + filesystem = board.get("build.filesystem", "littlefs") + if filesystem not in ("littlefs"): print("Unrecognized board_build.filesystem option '" + str(filesystem) + "'.") env.Exit(1) # fetching sizes is the same for all filesystems @@ -233,10 +223,7 @@ def get_fs_type_start_and_length(): print("FS_END: " + hex(env["FS_END"])) print("FS_PAGE: " + hex(env["FS_PAGE"])) print("FS_BLOCK: " + hex(env["FS_BLOCK"])) - if filesystem == "spiffs": - print("Recognized SPIFFS filesystem.") - return SPIFFSInfo(env["FS_START"], env["FS_END"] - env["FS_START"], env["FS_PAGE"], env["FS_BLOCK"]) - elif filesystem == "littlefs": + if filesystem == "littlefs": print("Recognized LittleFS filesystem.") return LittleFSInfo(env["FS_START"], env["FS_END"] - env["FS_START"], env["FS_PAGE"], env["FS_BLOCK"]) else: @@ -264,8 +251,8 @@ def download_fs(fs_info: FSInfo): fs_file ] esptoolpy_cmd = [env["PYTHONEXE"], esptoolpy] + esptoolpy_flags - print("Executing flash download command.") - print(esptoolpy_cmd) + print("Download filesystem image") + #print(esptoolpy_cmd) try: returncode = subprocess.call(esptoolpy_cmd, shell=False) # print("Launched download of filesystem binary.") @@ -291,10 +278,10 @@ def unpack_fs(fs_info: FSInfo, downloaded_file: str): os.makedirs(unpack_dir) cmd = fs_info.get_extract_cmd(downloaded_file, unpack_dir) - print("Executing extraction command: " + str(cmd)) + print("Unpack files from filesystem image") + #print("Extraction command: " + str(cmd)) try: returncode = subprocess.call(cmd, shell=True) - print("Unpacked filesystem.") return (True, unpack_dir) except subprocess.CalledProcessError as exc: print("Unpacking filesystem failed with " + str(exc)) @@ -307,11 +294,8 @@ def display_fs(extracted_dir): print("Extracted " + str(file_count) + " file(s) from filesystem.") def command_download_fs(*args, **kwargs): - #print("Entrypoint") - #print(env.Dump()) get_partition_table() info = get_fs_type_start_and_length() - print("Parsed FS info: " + str(info)) download_ok, downloaded_file = download_fs(info) # print("Download was okay: " + str(download_ok) + ". File at: "+ str(downloaded_file)) # this is wrong unpack_ok, unpacked_dir = unpack_fs(info, downloaded_file) @@ -358,4 +342,3 @@ env.AddCustomTarget( title="Flash factory", description="Flash factory firmware" ) - From 6d0c2fa9bcd3c3b8c97574fb9f05e36bb07b22ae Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Fri, 19 Jan 2024 20:06:06 +0100 Subject: [PATCH 188/303] Matter fix support for Alexa (#20545) --- CHANGELOG.md | 1 + .../berry_matter/src/be_matter_module.c | 1 + .../embedded/Matter_Plugin_1_Aggregator.be | 2 +- .../src/embedded/Matter_Plugin_1_Root.be | 4 +- .../src/embedded/Matter_Session_Store.be | 18 +- .../src/embedded/Matter_zz_Device.be | 6 +- .../solidified_Matter_Plugin_1_Aggregator.h | 88 +- .../solidified_Matter_Plugin_1_Root.h | 1189 +++++++++-------- .../solidified_Matter_Session_Store.h | 68 +- .../solidify/solidified_Matter_zz_Device.h | 296 ++-- 10 files changed, 849 insertions(+), 824 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a97e229d8..a91a780ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ All notable changes to this project will be documented in this file. - ESP32 shutter exception 6 (divide by zero) on ``ShutterMode 4`` (#20524) - GPIOViewer exception 3 - Berry assigment to list with negative index +- Matter fix support for Alexa ### Removed - Max number of 30 backlog entries diff --git a/lib/libesp32/berry_matter/src/be_matter_module.c b/lib/libesp32/berry_matter/src/be_matter_module.c index 994703f8d..81b271482 100644 --- a/lib/libesp32/berry_matter/src/be_matter_module.c +++ b/lib/libesp32/berry_matter/src/be_matter_module.c @@ -285,6 +285,7 @@ module matter (scope: global, strings: weak) { _STYLESHEET, comptr(MATTER_STYLESHEET) _ADD_ENDPOINT_JS, comptr(MATTER_ADD_ENDPOINT_HINTS_JS) MATTER_OPTION, int(151) // SetOption151 enables Matter + AGGREGATOR_ENDPOINT, int(0xFE) // for Alexa we need only 8 bits endpoints seconds_to_dhm, ctype_func(matter_seconds_to_dhm) Verhoeff, class(be_class_Matter_Verhoeff) diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Aggregator.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Aggregator.be index 39dd77cc9..395edf39e 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Aggregator.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Aggregator.be @@ -46,7 +46,7 @@ class Matter_Plugin_Aggregator : Matter_Plugin var pl = TLV.Matter_TLV_array() var eps = self.device.get_active_endpoints(true) for ep: eps - if ep < 0xFF00 + if ep < matter.AGGREGATOR_ENDPOINT pl.add_TLV(nil, TLV.U2, ep) # add each endpoint end end diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be index f02fedadf..ae5815ed3 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be @@ -158,7 +158,7 @@ class Matter_Plugin_Root : Matter_Plugin var nocs = nocl.add_struct(nil) nocs.add_TLV(1, TLV.B2, loc_fabric.get_noc()) # NOC nocs.add_TLV(2, TLV.B2, loc_fabric.get_icac()) # ICAC - nocs.add_TLV(0xFE, TLV.U2, loc_fabric.get_fabric_index()) # Label + nocs.add_TLV(matter.AGGREGATOR_ENDPOINT, TLV.U2, loc_fabric.get_fabric_index()) # Label end return nocl elif attribute == 0x0001 # ---------- Fabrics / list[FabricDescriptorStruct] ---------- @@ -312,7 +312,7 @@ class Matter_Plugin_Root : Matter_Plugin var disable_bridge_mode = self.device.disable_bridge_mode for ep: eps # if bridge mode is disabled, don't announce Aggregatore (above 0xFF00) - if !disable_bridge_mode || ep < 0xFF00 + if !disable_bridge_mode || ep < matter.AGGREGATOR_ENDPOINT pl.add_TLV(nil, TLV.U2, ep) # add each endpoint end end diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Session_Store.be b/lib/libesp32/berry_matter/src/embedded/Matter_Session_Store.be index 0c819b906..8aaf531a3 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Session_Store.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Session_Store.be @@ -57,15 +57,19 @@ class Matter_Session_Store ############################################################# # remove fabric def remove_fabric(fabric) - var idx = 0 - while idx < size(self.sessions) - if self.sessions[idx]._fabric == fabric - self.sessions.remove(idx) - else - idx += 1 + if (self.sessions != nil) + var idx = 0 + while idx < size(self.sessions) + if self.sessions[idx]._fabric == fabric + self.sessions.remove(idx) + else + idx += 1 + end end end - self.fabrics.remove(self.fabrics.find(fabric)) # fail safe + if (self.fabrics != nil) + self.fabrics.remove(self.fabrics.find(fabric)) # fail safe + end end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be b/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be index 64aa38ba6..4a3b704e7 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be @@ -837,7 +837,7 @@ class Matter_Device tasmota.log(format("MTR: endpoint = %5i type:%s%s", 0, 'root', ''), 2) # always include an aggregator for dynamic endpoints - self.plugins.push(matter.Plugin_Aggregator(self, 0xFF00, {})) + self.plugins.push(matter.Plugin_Aggregator(self, matter.AGGREGATOR_ENDPOINT, {})) for ep: endpoints if ep == 0 continue end # skip endpoint 0 @@ -859,7 +859,7 @@ class Matter_Device tasmota.log("MTR: Exception" + str(e) + "|" + str(m), 2) end end - tasmota.log(format("MTR: endpoint = %5i type:%s%s", 0xFF00, 'aggregator', ''), 2) + tasmota.log(format("MTR: endpoint = %5i type:%s%s", matter.AGGREGATOR_ENDPOINT, 'aggregator', ''), 2) tasmota.publish_result('{"Matter":{"Initialized":1}}', 'Matter') end @@ -1396,7 +1396,7 @@ class Matter_Device def signal_endpoints_changed() # mark parts lists as changed self.attribute_updated(0x0000, 0x001D, 0x0003, false) - self.attribute_updated(0xFF00, 0x001D, 0x0003, false) + self.attribute_updated(matter.AGGREGATOR_ENDPOINT, 0x001D, 0x0003, false) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Aggregator.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Aggregator.h index c9c2db74a..34df71698 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Aggregator.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Aggregator.h @@ -19,7 +19,7 @@ be_local_closure(Matter_Plugin_Aggregator_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[12]) { /* constants */ + ( &(const bvalue[13]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -28,23 +28,24 @@ be_local_closure(Matter_Plugin_Aggregator_read_attribute, /* name */ /* K5 */ be_nested_str_weak(Matter_TLV_array), /* K6 */ be_nested_str_weak(device), /* K7 */ be_nested_str_weak(get_active_endpoints), - /* K8 */ be_nested_str_weak(add_TLV), - /* K9 */ be_nested_str_weak(U2), - /* K10 */ be_nested_str_weak(stop_iteration), - /* K11 */ be_nested_str_weak(read_attribute), + /* K8 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), + /* K9 */ be_nested_str_weak(add_TLV), + /* K10 */ be_nested_str_weak(U2), + /* K11 */ be_nested_str_weak(stop_iteration), + /* K12 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[55]) { /* code */ + ( &(const binstruction[56]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E001C, // 0004 LDINT R7 29 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0025, // 0006 JMPF R7 #002D + 0x781E0026, // 0006 JMPF R7 #002E 0x1C1C0D04, // 0007 EQ R7 R6 K4 - 0x781E0019, // 0008 JMPF R7 #0023 + 0x781E001A, // 0008 JMPF R7 #0024 0x8C1C0905, // 0009 GETMET R7 R4 K5 0x7C1C0200, // 000A CALL R7 1 0x88200106, // 000B GETMBR R8 R0 K6 @@ -54,43 +55,44 @@ be_local_closure(Matter_Plugin_Aggregator_read_attribute, /* name */ 0x60240010, // 000F GETGBL R9 G16 0x5C281000, // 0010 MOVE R10 R8 0x7C240200, // 0011 CALL R9 1 - 0xA802000A, // 0012 EXBLK 0 #001E + 0xA802000B, // 0012 EXBLK 0 #001F 0x5C281200, // 0013 MOVE R10 R9 0x7C280000, // 0014 CALL R10 0 - 0x542EFEFF, // 0015 LDINT R11 65280 - 0x142C140B, // 0016 LT R11 R10 R11 - 0x782E0004, // 0017 JMPF R11 #001D - 0x8C2C0F08, // 0018 GETMET R11 R7 K8 - 0x4C340000, // 0019 LDNIL R13 - 0x88380909, // 001A GETMBR R14 R4 K9 - 0x5C3C1400, // 001B MOVE R15 R10 - 0x7C2C0800, // 001C CALL R11 4 - 0x7001FFF4, // 001D JMP #0013 - 0x5824000A, // 001E LDCONST R9 K10 - 0xAC240200, // 001F CATCH R9 1 0 - 0xB0080000, // 0020 RAISE 2 R0 R0 - 0x80040E00, // 0021 RET 1 R7 - 0x70020008, // 0022 JMP #002C - 0x601C0003, // 0023 GETGBL R7 G3 - 0x5C200000, // 0024 MOVE R8 R0 - 0x7C1C0200, // 0025 CALL R7 1 - 0x8C1C0F0B, // 0026 GETMET R7 R7 K11 - 0x5C240200, // 0027 MOVE R9 R1 - 0x5C280400, // 0028 MOVE R10 R2 - 0x5C2C0600, // 0029 MOVE R11 R3 - 0x7C1C0800, // 002A CALL R7 4 - 0x80040E00, // 002B RET 1 R7 - 0x70020008, // 002C JMP #0036 - 0x601C0003, // 002D GETGBL R7 G3 - 0x5C200000, // 002E MOVE R8 R0 - 0x7C1C0200, // 002F CALL R7 1 - 0x8C1C0F0B, // 0030 GETMET R7 R7 K11 - 0x5C240200, // 0031 MOVE R9 R1 - 0x5C280400, // 0032 MOVE R10 R2 - 0x5C2C0600, // 0033 MOVE R11 R3 - 0x7C1C0800, // 0034 CALL R7 4 - 0x80040E00, // 0035 RET 1 R7 - 0x80000000, // 0036 RET 0 + 0xB82E0000, // 0015 GETNGBL R11 K0 + 0x882C1708, // 0016 GETMBR R11 R11 K8 + 0x142C140B, // 0017 LT R11 R10 R11 + 0x782E0004, // 0018 JMPF R11 #001E + 0x8C2C0F09, // 0019 GETMET R11 R7 K9 + 0x4C340000, // 001A LDNIL R13 + 0x8838090A, // 001B GETMBR R14 R4 K10 + 0x5C3C1400, // 001C MOVE R15 R10 + 0x7C2C0800, // 001D CALL R11 4 + 0x7001FFF3, // 001E JMP #0013 + 0x5824000B, // 001F LDCONST R9 K11 + 0xAC240200, // 0020 CATCH R9 1 0 + 0xB0080000, // 0021 RAISE 2 R0 R0 + 0x80040E00, // 0022 RET 1 R7 + 0x70020008, // 0023 JMP #002D + 0x601C0003, // 0024 GETGBL R7 G3 + 0x5C200000, // 0025 MOVE R8 R0 + 0x7C1C0200, // 0026 CALL R7 1 + 0x8C1C0F0C, // 0027 GETMET R7 R7 K12 + 0x5C240200, // 0028 MOVE R9 R1 + 0x5C280400, // 0029 MOVE R10 R2 + 0x5C2C0600, // 002A MOVE R11 R3 + 0x7C1C0800, // 002B CALL R7 4 + 0x80040E00, // 002C RET 1 R7 + 0x70020008, // 002D JMP #0037 + 0x601C0003, // 002E GETGBL R7 G3 + 0x5C200000, // 002F MOVE R8 R0 + 0x7C1C0200, // 0030 CALL R7 1 + 0x8C1C0F0C, // 0031 GETMET R7 R7 K12 + 0x5C240200, // 0032 MOVE R9 R1 + 0x5C280400, // 0033 MOVE R10 R2 + 0x5C2C0600, // 0034 MOVE R11 R3 + 0x7C1C0800, // 0035 CALL R7 4 + 0x80040E00, // 0036 RET 1 R7 + 0x80000000, // 0037 RET 0 }) ) ); diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h index a001bfaa2..488d82899 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h @@ -19,7 +19,7 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[92]) { /* constants */ + ( &(const bvalue[93]) { /* constants */ /* K0 */ be_nested_str_weak(string), /* K1 */ be_nested_str_weak(matter), /* K2 */ be_nested_str_weak(TLV), @@ -80,42 +80,43 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ /* K57 */ be_nested_str_weak(B2), /* K58 */ be_nested_str_weak(get_noc), /* K59 */ be_nested_str_weak(get_icac), - /* K60 */ be_nested_str_weak(get_fabric_index), - /* K61 */ be_nested_str_weak(stop_iteration), - /* K62 */ be_nested_str_weak(parse), - /* K63 */ be_nested_str_weak(get_ca), - /* K64 */ be_nested_str_weak(findsubval), - /* K65 */ be_nested_str_weak(get_admin_vendor), - /* K66 */ be_nested_str_weak(get_fabric_id), - /* K67 */ be_nested_str_weak(get_device_id), - /* K68 */ be_nested_str_weak(get_fabric_label), - /* K69 */ be_nested_str_weak(Fabric), - /* K70 */ be_nested_str_weak(_MAX_CASE), - /* K71 */ be_nested_str_weak(count_active_fabrics), - /* K72 */ be_nested_str_weak(_fabric), - /* K73 */ be_nested_str_weak(is_commissioning_open), - /* K74 */ be_nested_str_weak(is_root_commissioning_open), - /* K75 */ be_nested_str_weak(commissioning_admin_fabric), - /* K76 */ be_nested_str_weak(Tasmota), - /* K77 */ be_nested_str_weak(vendorid), - /* K78 */ be_nested_str_weak(DeviceName), - /* K79 */ be_nested_str_weak(FriendlyName), - /* K80 */ be_nested_str_weak(FriendlyName1), - /* K81 */ be_nested_str_weak(XX), - /* K82 */ be_nested_str_weak(Status_X202), - /* K83 */ be_nested_str_weak(StatusFWR), - /* K84 */ be_nested_str_weak(Hardware), - /* K85 */ be_nested_str_weak(Version), - /* K86 */ be_nested_str_weak(_X28), - /* K87 */ be_nested_str_weak(locale), - /* K88 */ be_nested_str_weak(create_TLV), - /* K89 */ be_nested_str_weak(get_active_endpoints), - /* K90 */ be_nested_str_weak(disable_bridge_mode), - /* K91 */ be_nested_str_weak(read_attribute), + /* K60 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), + /* K61 */ be_nested_str_weak(get_fabric_index), + /* K62 */ be_nested_str_weak(stop_iteration), + /* K63 */ be_nested_str_weak(parse), + /* K64 */ be_nested_str_weak(get_ca), + /* K65 */ be_nested_str_weak(findsubval), + /* K66 */ be_nested_str_weak(get_admin_vendor), + /* K67 */ be_nested_str_weak(get_fabric_id), + /* K68 */ be_nested_str_weak(get_device_id), + /* K69 */ be_nested_str_weak(get_fabric_label), + /* K70 */ be_nested_str_weak(Fabric), + /* K71 */ be_nested_str_weak(_MAX_CASE), + /* K72 */ be_nested_str_weak(count_active_fabrics), + /* K73 */ be_nested_str_weak(_fabric), + /* K74 */ be_nested_str_weak(is_commissioning_open), + /* K75 */ be_nested_str_weak(is_root_commissioning_open), + /* K76 */ be_nested_str_weak(commissioning_admin_fabric), + /* K77 */ be_nested_str_weak(Tasmota), + /* K78 */ be_nested_str_weak(vendorid), + /* K79 */ be_nested_str_weak(DeviceName), + /* K80 */ be_nested_str_weak(FriendlyName), + /* K81 */ be_nested_str_weak(FriendlyName1), + /* K82 */ be_nested_str_weak(XX), + /* K83 */ be_nested_str_weak(Status_X202), + /* K84 */ be_nested_str_weak(StatusFWR), + /* K85 */ be_nested_str_weak(Hardware), + /* K86 */ be_nested_str_weak(Version), + /* K87 */ be_nested_str_weak(_X28), + /* K88 */ be_nested_str_weak(locale), + /* K89 */ be_nested_str_weak(create_TLV), + /* K90 */ be_nested_str_weak(get_active_endpoints), + /* K91 */ be_nested_str_weak(disable_bridge_mode), + /* K92 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[937]) { /* code */ + ( &(const binstruction[939]) { /* code */ 0xA4120000, // 0000 IMPORT R4 K0 0xB8160200, // 0001 GETNGBL R5 K1 0x88140B02, // 0002 GETMBR R5 R5 K2 @@ -172,11 +173,11 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x502C0000, // 0035 LDBOOL R11 0 0 0x7C200600, // 0036 CALL R8 3 0x80041000, // 0037 RET 1 R8 - 0x7002036E, // 0038 JMP #03A8 + 0x70020370, // 0038 JMP #03AA 0x54220031, // 0039 LDINT R8 50 0x1C200C08, // 003A EQ R8 R6 R8 0x78220000, // 003B JMPF R8 #003D - 0x7002036A, // 003C JMP #03A8 + 0x7002036C, // 003C JMP #03AA 0x54220032, // 003D LDINT R8 51 0x1C200C08, // 003E EQ R8 R6 R8 0x782200DC, // 003F JMPF R8 #011D @@ -400,11 +401,11 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x502C0000, // 0119 LDBOOL R11 0 0 0x7C200600, // 011A CALL R8 3 0x80041000, // 011B RET 1 R8 - 0x7002028A, // 011C JMP #03A8 + 0x7002028C, // 011C JMP #03AA 0x54220033, // 011D LDINT R8 52 0x1C200C08, // 011E EQ R8 R6 R8 0x78220000, // 011F JMPF R8 #0121 - 0x70020286, // 0120 JMP #03A8 + 0x70020288, // 0120 JMP #03AA 0x54220037, // 0121 LDINT R8 56 0x1C200C08, // 0122 EQ R8 R6 R8 0x7822002B, // 0123 JMPF R8 #0150 @@ -451,15 +452,15 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x5C301000, // 014C MOVE R12 R8 0x7C240600, // 014D CALL R9 3 0x80041200, // 014E RET 1 R9 - 0x70020257, // 014F JMP #03A8 + 0x70020259, // 014F JMP #03AA 0x5422003D, // 0150 LDINT R8 62 0x1C200C08, // 0151 EQ R8 R6 R8 - 0x782200AD, // 0152 JMPF R8 #0201 + 0x782200AE, // 0152 JMPF R8 #0202 0x8C200133, // 0153 GETMET R8 R0 K51 0x5C280400, // 0154 MOVE R10 R2 0x7C200400, // 0155 CALL R8 2 0x1C200F05, // 0156 EQ R8 R7 K5 - 0x78220032, // 0157 JMPF R8 #018B + 0x78220033, // 0157 JMPF R8 #018C 0x8C200B11, // 0158 GETMET R8 R5 K17 0x7C200200, // 0159 CALL R8 1 0x88240534, // 015A GETMBR R9 R2 K52 @@ -477,7 +478,7 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x60280010, // 0166 GETGBL R10 G16 0x5C2C1200, // 0167 MOVE R11 R9 0x7C280200, // 0168 CALL R10 1 - 0xA802001B, // 0169 EXBLK 0 #0186 + 0xA802001C, // 0169 EXBLK 0 #0187 0x5C2C1400, // 016A MOVE R11 R10 0x7C2C0000, // 016B CALL R11 0 0x4C300000, // 016C LDNIL R12 @@ -500,559 +501,561 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x7C440200, // 017D CALL R17 1 0x7C340800, // 017E CALL R13 4 0x8C34190B, // 017F GETMET R13 R12 K11 - 0x543E00FD, // 0180 LDINT R15 254 - 0x88400B0C, // 0181 GETMBR R16 R5 K12 - 0x8C44173C, // 0182 GETMET R17 R11 K60 - 0x7C440200, // 0183 CALL R17 1 - 0x7C340800, // 0184 CALL R13 4 - 0x7001FFE3, // 0185 JMP #016A - 0x5828003D, // 0186 LDCONST R10 K61 - 0xAC280200, // 0187 CATCH R10 1 0 - 0xB0080000, // 0188 RAISE 2 R0 R0 - 0x80041000, // 0189 RET 1 R8 - 0x70020074, // 018A JMP #0200 - 0x1C200F09, // 018B EQ R8 R7 K9 - 0x78220049, // 018C JMPF R8 #01D7 - 0x8C200B11, // 018D GETMET R8 R5 K17 - 0x7C200200, // 018E CALL R8 1 - 0x88240534, // 018F GETMBR R9 R2 K52 - 0x78260005, // 0190 JMPF R9 #0197 - 0x60240012, // 0191 GETGBL R9 G18 - 0x7C240000, // 0192 CALL R9 0 - 0x8C280335, // 0193 GETMET R10 R1 K53 - 0x7C280200, // 0194 CALL R10 1 - 0x4028120A, // 0195 CONNECT R10 R9 R10 - 0x70020003, // 0196 JMP #019B - 0x88240136, // 0197 GETMBR R9 R0 K54 - 0x88241337, // 0198 GETMBR R9 R9 K55 - 0x8C241338, // 0199 GETMET R9 R9 K56 - 0x7C240200, // 019A CALL R9 1 - 0x60280010, // 019B GETGBL R10 G16 - 0x5C2C1200, // 019C MOVE R11 R9 - 0x7C280200, // 019D CALL R10 1 - 0xA8020032, // 019E EXBLK 0 #01D2 - 0x5C2C1400, // 019F MOVE R11 R10 - 0x7C2C0000, // 01A0 CALL R11 0 - 0x4C300000, // 01A1 LDNIL R12 - 0x1C30160C, // 01A2 EQ R12 R11 R12 - 0x78320000, // 01A3 JMPF R12 #01A5 - 0x7001FFF9, // 01A4 JMP #019F - 0x8C300B3E, // 01A5 GETMET R12 R5 K62 - 0x8C38173F, // 01A6 GETMET R14 R11 K63 - 0x7C380200, // 01A7 CALL R14 1 - 0x7C300400, // 01A8 CALL R12 2 - 0x8C341115, // 01A9 GETMET R13 R8 K21 - 0x4C3C0000, // 01AA LDNIL R15 - 0x7C340400, // 01AB CALL R13 2 - 0x8C381B0B, // 01AC GETMET R14 R13 K11 - 0x58400009, // 01AD LDCONST R16 K9 - 0x88440B39, // 01AE GETMBR R17 R5 K57 - 0x8C481940, // 01AF GETMET R18 R12 K64 - 0x54520008, // 01B0 LDINT R20 9 - 0x7C480400, // 01B1 CALL R18 2 - 0x7C380800, // 01B2 CALL R14 4 - 0x8C381B0B, // 01B3 GETMET R14 R13 K11 - 0x5840000D, // 01B4 LDCONST R16 K13 - 0x88440B0C, // 01B5 GETMBR R17 R5 K12 - 0x8C481741, // 01B6 GETMET R18 R11 K65 - 0x7C480200, // 01B7 CALL R18 1 - 0x7C380800, // 01B8 CALL R14 4 - 0x8C381B0B, // 01B9 GETMET R14 R13 K11 - 0x5840000F, // 01BA LDCONST R16 K15 - 0x88440B07, // 01BB GETMBR R17 R5 K7 - 0x8C481742, // 01BC GETMET R18 R11 K66 - 0x7C480200, // 01BD CALL R18 1 - 0x7C380800, // 01BE CALL R14 4 - 0x8C381B0B, // 01BF GETMET R14 R13 K11 - 0x54420003, // 01C0 LDINT R16 4 - 0x88440B07, // 01C1 GETMBR R17 R5 K7 - 0x8C481743, // 01C2 GETMET R18 R11 K67 - 0x7C480200, // 01C3 CALL R18 1 - 0x7C380800, // 01C4 CALL R14 4 - 0x8C381B0B, // 01C5 GETMET R14 R13 K11 - 0x54420004, // 01C6 LDINT R16 5 - 0x88440B16, // 01C7 GETMBR R17 R5 K22 - 0x8C481744, // 01C8 GETMET R18 R11 K68 - 0x7C480200, // 01C9 CALL R18 1 - 0x7C380800, // 01CA CALL R14 4 - 0x8C381B0B, // 01CB GETMET R14 R13 K11 - 0x544200FD, // 01CC LDINT R16 254 - 0x88440B0C, // 01CD GETMBR R17 R5 K12 - 0x8C48173C, // 01CE GETMET R18 R11 K60 - 0x7C480200, // 01CF CALL R18 1 - 0x7C380800, // 01D0 CALL R14 4 - 0x7001FFCC, // 01D1 JMP #019F - 0x5828003D, // 01D2 LDCONST R10 K61 - 0xAC280200, // 01D3 CATCH R10 1 0 - 0xB0080000, // 01D4 RAISE 2 R0 R0 - 0x80041000, // 01D5 RET 1 R8 - 0x70020028, // 01D6 JMP #0200 - 0x1C200F0D, // 01D7 EQ R8 R7 K13 - 0x78220007, // 01D8 JMPF R8 #01E1 - 0x8C200706, // 01D9 GETMET R8 R3 K6 - 0x88280B0E, // 01DA GETMBR R10 R5 K14 - 0xB82E0200, // 01DB GETNGBL R11 K1 - 0x882C1745, // 01DC GETMBR R11 R11 K69 + 0xB83E0200, // 0180 GETNGBL R15 K1 + 0x883C1F3C, // 0181 GETMBR R15 R15 K60 + 0x88400B0C, // 0182 GETMBR R16 R5 K12 + 0x8C44173D, // 0183 GETMET R17 R11 K61 + 0x7C440200, // 0184 CALL R17 1 + 0x7C340800, // 0185 CALL R13 4 + 0x7001FFE2, // 0186 JMP #016A + 0x5828003E, // 0187 LDCONST R10 K62 + 0xAC280200, // 0188 CATCH R10 1 0 + 0xB0080000, // 0189 RAISE 2 R0 R0 + 0x80041000, // 018A RET 1 R8 + 0x70020074, // 018B JMP #0201 + 0x1C200F09, // 018C EQ R8 R7 K9 + 0x78220049, // 018D JMPF R8 #01D8 + 0x8C200B11, // 018E GETMET R8 R5 K17 + 0x7C200200, // 018F CALL R8 1 + 0x88240534, // 0190 GETMBR R9 R2 K52 + 0x78260005, // 0191 JMPF R9 #0198 + 0x60240012, // 0192 GETGBL R9 G18 + 0x7C240000, // 0193 CALL R9 0 + 0x8C280335, // 0194 GETMET R10 R1 K53 + 0x7C280200, // 0195 CALL R10 1 + 0x4028120A, // 0196 CONNECT R10 R9 R10 + 0x70020003, // 0197 JMP #019C + 0x88240136, // 0198 GETMBR R9 R0 K54 + 0x88241337, // 0199 GETMBR R9 R9 K55 + 0x8C241338, // 019A GETMET R9 R9 K56 + 0x7C240200, // 019B CALL R9 1 + 0x60280010, // 019C GETGBL R10 G16 + 0x5C2C1200, // 019D MOVE R11 R9 + 0x7C280200, // 019E CALL R10 1 + 0xA8020032, // 019F EXBLK 0 #01D3 + 0x5C2C1400, // 01A0 MOVE R11 R10 + 0x7C2C0000, // 01A1 CALL R11 0 + 0x4C300000, // 01A2 LDNIL R12 + 0x1C30160C, // 01A3 EQ R12 R11 R12 + 0x78320000, // 01A4 JMPF R12 #01A6 + 0x7001FFF9, // 01A5 JMP #01A0 + 0x8C300B3F, // 01A6 GETMET R12 R5 K63 + 0x8C381740, // 01A7 GETMET R14 R11 K64 + 0x7C380200, // 01A8 CALL R14 1 + 0x7C300400, // 01A9 CALL R12 2 + 0x8C341115, // 01AA GETMET R13 R8 K21 + 0x4C3C0000, // 01AB LDNIL R15 + 0x7C340400, // 01AC CALL R13 2 + 0x8C381B0B, // 01AD GETMET R14 R13 K11 + 0x58400009, // 01AE LDCONST R16 K9 + 0x88440B39, // 01AF GETMBR R17 R5 K57 + 0x8C481941, // 01B0 GETMET R18 R12 K65 + 0x54520008, // 01B1 LDINT R20 9 + 0x7C480400, // 01B2 CALL R18 2 + 0x7C380800, // 01B3 CALL R14 4 + 0x8C381B0B, // 01B4 GETMET R14 R13 K11 + 0x5840000D, // 01B5 LDCONST R16 K13 + 0x88440B0C, // 01B6 GETMBR R17 R5 K12 + 0x8C481742, // 01B7 GETMET R18 R11 K66 + 0x7C480200, // 01B8 CALL R18 1 + 0x7C380800, // 01B9 CALL R14 4 + 0x8C381B0B, // 01BA GETMET R14 R13 K11 + 0x5840000F, // 01BB LDCONST R16 K15 + 0x88440B07, // 01BC GETMBR R17 R5 K7 + 0x8C481743, // 01BD GETMET R18 R11 K67 + 0x7C480200, // 01BE CALL R18 1 + 0x7C380800, // 01BF CALL R14 4 + 0x8C381B0B, // 01C0 GETMET R14 R13 K11 + 0x54420003, // 01C1 LDINT R16 4 + 0x88440B07, // 01C2 GETMBR R17 R5 K7 + 0x8C481744, // 01C3 GETMET R18 R11 K68 + 0x7C480200, // 01C4 CALL R18 1 + 0x7C380800, // 01C5 CALL R14 4 + 0x8C381B0B, // 01C6 GETMET R14 R13 K11 + 0x54420004, // 01C7 LDINT R16 5 + 0x88440B16, // 01C8 GETMBR R17 R5 K22 + 0x8C481745, // 01C9 GETMET R18 R11 K69 + 0x7C480200, // 01CA CALL R18 1 + 0x7C380800, // 01CB CALL R14 4 + 0x8C381B0B, // 01CC GETMET R14 R13 K11 + 0x544200FD, // 01CD LDINT R16 254 + 0x88440B0C, // 01CE GETMBR R17 R5 K12 + 0x8C48173D, // 01CF GETMET R18 R11 K61 + 0x7C480200, // 01D0 CALL R18 1 + 0x7C380800, // 01D1 CALL R14 4 + 0x7001FFCC, // 01D2 JMP #01A0 + 0x5828003E, // 01D3 LDCONST R10 K62 + 0xAC280200, // 01D4 CATCH R10 1 0 + 0xB0080000, // 01D5 RAISE 2 R0 R0 + 0x80041000, // 01D6 RET 1 R8 + 0x70020028, // 01D7 JMP #0201 + 0x1C200F0D, // 01D8 EQ R8 R7 K13 + 0x78220007, // 01D9 JMPF R8 #01E2 + 0x8C200706, // 01DA GETMET R8 R3 K6 + 0x88280B0E, // 01DB GETMBR R10 R5 K14 + 0xB82E0200, // 01DC GETNGBL R11 K1 0x882C1746, // 01DD GETMBR R11 R11 K70 - 0x7C200600, // 01DE CALL R8 3 - 0x80041000, // 01DF RET 1 R8 - 0x7002001E, // 01E0 JMP #0200 - 0x1C200F0F, // 01E1 EQ R8 R7 K15 - 0x78220009, // 01E2 JMPF R8 #01ED - 0x88200136, // 01E3 GETMBR R8 R0 K54 - 0x88201137, // 01E4 GETMBR R8 R8 K55 - 0x8C201147, // 01E5 GETMET R8 R8 K71 - 0x7C200200, // 01E6 CALL R8 1 - 0x8C240706, // 01E7 GETMET R9 R3 K6 - 0x882C0B0E, // 01E8 GETMBR R11 R5 K14 - 0x5C301000, // 01E9 MOVE R12 R8 - 0x7C240600, // 01EA CALL R9 3 - 0x80041200, // 01EB RET 1 R9 - 0x70020012, // 01EC JMP #0200 - 0x54220003, // 01ED LDINT R8 4 - 0x1C200E08, // 01EE EQ R8 R7 R8 - 0x78220000, // 01EF JMPF R8 #01F1 - 0x7002000E, // 01F0 JMP #0200 - 0x54220004, // 01F1 LDINT R8 5 - 0x1C200E08, // 01F2 EQ R8 R7 R8 - 0x7822000B, // 01F3 JMPF R8 #0200 - 0x88200348, // 01F4 GETMBR R8 R1 K72 - 0x8C20113C, // 01F5 GETMET R8 R8 K60 - 0x7C200200, // 01F6 CALL R8 1 - 0x4C240000, // 01F7 LDNIL R9 - 0x1C241009, // 01F8 EQ R9 R8 R9 - 0x78260000, // 01F9 JMPF R9 #01FB - 0x58200005, // 01FA LDCONST R8 K5 - 0x8C240706, // 01FB GETMET R9 R3 K6 - 0x882C0B0E, // 01FC GETMBR R11 R5 K14 - 0x5C301000, // 01FD MOVE R12 R8 - 0x7C240600, // 01FE CALL R9 3 - 0x80041200, // 01FF RET 1 R9 - 0x700201A6, // 0200 JMP #03A8 - 0x5422003B, // 0201 LDINT R8 60 - 0x1C200C08, // 0202 EQ R8 R6 R8 - 0x7822003C, // 0203 JMPF R8 #0241 - 0x1C200F05, // 0204 EQ R8 R7 K5 - 0x78220012, // 0205 JMPF R8 #0219 - 0x88200136, // 0206 GETMBR R8 R0 K54 - 0x8C201149, // 0207 GETMET R8 R8 K73 - 0x7C200200, // 0208 CALL R8 1 - 0x88240136, // 0209 GETMBR R9 R0 K54 - 0x8C24134A, // 020A GETMET R9 R9 K74 - 0x7C240200, // 020B CALL R9 1 - 0x78220004, // 020C JMPF R8 #0212 - 0x78260001, // 020D JMPF R9 #0210 - 0x5828000D, // 020E LDCONST R10 K13 - 0x70020000, // 020F JMP #0211 - 0x58280009, // 0210 LDCONST R10 K9 - 0x70020000, // 0211 JMP #0213 - 0x58280005, // 0212 LDCONST R10 K5 - 0x8C2C0706, // 0213 GETMET R11 R3 K6 - 0x88340B0E, // 0214 GETMBR R13 R5 K14 - 0x5C381400, // 0215 MOVE R14 R10 - 0x7C2C0600, // 0216 CALL R11 3 - 0x80041600, // 0217 RET 1 R11 - 0x70020026, // 0218 JMP #0240 - 0x1C200F09, // 0219 EQ R8 R7 K9 - 0x78220011, // 021A JMPF R8 #022D - 0x88200136, // 021B GETMBR R8 R0 K54 - 0x8820114B, // 021C GETMBR R8 R8 K75 - 0x4C240000, // 021D LDNIL R9 - 0x20241009, // 021E NE R9 R8 R9 - 0x78260006, // 021F JMPF R9 #0227 - 0x8C240706, // 0220 GETMET R9 R3 K6 - 0x882C0B0C, // 0221 GETMBR R11 R5 K12 - 0x8C30113C, // 0222 GETMET R12 R8 K60 - 0x7C300200, // 0223 CALL R12 1 - 0x7C240600, // 0224 CALL R9 3 - 0x80041200, // 0225 RET 1 R9 - 0x70020004, // 0226 JMP #022C - 0x8C240706, // 0227 GETMET R9 R3 K6 - 0x882C0B18, // 0228 GETMBR R11 R5 K24 - 0x4C300000, // 0229 LDNIL R12 - 0x7C240600, // 022A CALL R9 3 - 0x80041200, // 022B RET 1 R9 - 0x70020012, // 022C JMP #0240 - 0x1C200F0D, // 022D EQ R8 R7 K13 - 0x78220010, // 022E JMPF R8 #0240 - 0x88200136, // 022F GETMBR R8 R0 K54 - 0x8820114B, // 0230 GETMBR R8 R8 K75 - 0x4C240000, // 0231 LDNIL R9 - 0x20241009, // 0232 NE R9 R8 R9 - 0x78260006, // 0233 JMPF R9 #023B - 0x8C240706, // 0234 GETMET R9 R3 K6 - 0x882C0B0C, // 0235 GETMBR R11 R5 K12 - 0x8C301141, // 0236 GETMET R12 R8 K65 - 0x7C300200, // 0237 CALL R12 1 - 0x7C240600, // 0238 CALL R9 3 - 0x80041200, // 0239 RET 1 R9 - 0x70020004, // 023A JMP #0240 - 0x8C240706, // 023B GETMET R9 R3 K6 - 0x882C0B18, // 023C GETMBR R11 R5 K24 - 0x4C300000, // 023D LDNIL R12 - 0x7C240600, // 023E CALL R9 3 - 0x80041200, // 023F RET 1 R9 - 0x70020166, // 0240 JMP #03A8 - 0x54220027, // 0241 LDINT R8 40 - 0x1C200C08, // 0242 EQ R8 R6 R8 - 0x782200BA, // 0243 JMPF R8 #02FF - 0x8C200133, // 0244 GETMET R8 R0 K51 - 0x5C280400, // 0245 MOVE R10 R2 - 0x7C200400, // 0246 CALL R8 2 - 0x1C200F05, // 0247 EQ R8 R7 K5 - 0x78220005, // 0248 JMPF R8 #024F - 0x8C200706, // 0249 GETMET R8 R3 K6 - 0x88280B0C, // 024A GETMBR R10 R5 K12 - 0x582C0009, // 024B LDCONST R11 K9 - 0x7C200600, // 024C CALL R8 3 - 0x80041000, // 024D RET 1 R8 - 0x700200AE, // 024E JMP #02FE - 0x1C200F09, // 024F EQ R8 R7 K9 - 0x78220005, // 0250 JMPF R8 #0257 - 0x8C200706, // 0251 GETMET R8 R3 K6 - 0x88280B16, // 0252 GETMBR R10 R5 K22 - 0x582C004C, // 0253 LDCONST R11 K76 - 0x7C200600, // 0254 CALL R8 3 - 0x80041000, // 0255 RET 1 R8 - 0x700200A6, // 0256 JMP #02FE - 0x1C200F0D, // 0257 EQ R8 R7 K13 - 0x78220006, // 0258 JMPF R8 #0260 - 0x8C200706, // 0259 GETMET R8 R3 K6 - 0x88280B0C, // 025A GETMBR R10 R5 K12 - 0x882C0136, // 025B GETMBR R11 R0 K54 - 0x882C174D, // 025C GETMBR R11 R11 K77 - 0x7C200600, // 025D CALL R8 3 - 0x80041000, // 025E RET 1 R8 - 0x7002009D, // 025F JMP #02FE - 0x1C200F0F, // 0260 EQ R8 R7 K15 - 0x7822000A, // 0261 JMPF R8 #026D - 0x8C200706, // 0262 GETMET R8 R3 K6 - 0x88280B16, // 0263 GETMBR R10 R5 K22 - 0xB82E2400, // 0264 GETNGBL R11 K18 - 0x8C2C1726, // 0265 GETMET R11 R11 K38 - 0x5834004E, // 0266 LDCONST R13 K78 - 0x50380200, // 0267 LDBOOL R14 1 0 - 0x7C2C0600, // 0268 CALL R11 3 - 0x942C174E, // 0269 GETIDX R11 R11 K78 - 0x7C200600, // 026A CALL R8 3 - 0x80041000, // 026B RET 1 R8 - 0x70020090, // 026C JMP #02FE - 0x54220003, // 026D LDINT R8 4 - 0x1C200E08, // 026E EQ R8 R7 R8 - 0x78220005, // 026F JMPF R8 #0276 - 0x8C200706, // 0270 GETMET R8 R3 K6 - 0x88280B0C, // 0271 GETMBR R10 R5 K12 - 0x542E7FFF, // 0272 LDINT R11 32768 - 0x7C200600, // 0273 CALL R8 3 - 0x80041000, // 0274 RET 1 R8 - 0x70020087, // 0275 JMP #02FE - 0x54220004, // 0276 LDINT R8 5 - 0x1C200E08, // 0277 EQ R8 R7 R8 - 0x7822000A, // 0278 JMPF R8 #0284 - 0x8C200706, // 0279 GETMET R8 R3 K6 - 0x88280B16, // 027A GETMBR R10 R5 K22 - 0xB82E2400, // 027B GETNGBL R11 K18 - 0x8C2C1726, // 027C GETMET R11 R11 K38 - 0x5834004F, // 027D LDCONST R13 K79 - 0x50380200, // 027E LDBOOL R14 1 0 - 0x7C2C0600, // 027F CALL R11 3 - 0x942C1750, // 0280 GETIDX R11 R11 K80 - 0x7C200600, // 0281 CALL R8 3 - 0x80041000, // 0282 RET 1 R8 - 0x70020079, // 0283 JMP #02FE - 0x54220005, // 0284 LDINT R8 6 - 0x1C200E08, // 0285 EQ R8 R7 R8 - 0x78220005, // 0286 JMPF R8 #028D - 0x8C200706, // 0287 GETMET R8 R3 K6 - 0x88280B16, // 0288 GETMBR R10 R5 K22 - 0x582C0051, // 0289 LDCONST R11 K81 - 0x7C200600, // 028A CALL R8 3 - 0x80041000, // 028B RET 1 R8 - 0x70020070, // 028C JMP #02FE - 0x54220006, // 028D LDINT R8 7 - 0x1C200E08, // 028E EQ R8 R7 R8 - 0x78220005, // 028F JMPF R8 #0296 - 0x8C200706, // 0290 GETMET R8 R3 K6 - 0x88280B0C, // 0291 GETMBR R10 R5 K12 - 0x582C0005, // 0292 LDCONST R11 K5 - 0x7C200600, // 0293 CALL R8 3 - 0x80041000, // 0294 RET 1 R8 - 0x70020067, // 0295 JMP #02FE - 0x54220007, // 0296 LDINT R8 8 - 0x1C200E08, // 0297 EQ R8 R7 R8 - 0x7822000B, // 0298 JMPF R8 #02A5 - 0x8C200706, // 0299 GETMET R8 R3 K6 - 0x88280B16, // 029A GETMBR R10 R5 K22 - 0xB82E2400, // 029B GETNGBL R11 K18 - 0x8C2C1726, // 029C GETMET R11 R11 K38 - 0x58340052, // 029D LDCONST R13 K82 - 0x50380200, // 029E LDBOOL R14 1 0 - 0x7C2C0600, // 029F CALL R11 3 - 0x942C1753, // 02A0 GETIDX R11 R11 K83 + 0x882C1747, // 01DE GETMBR R11 R11 K71 + 0x7C200600, // 01DF CALL R8 3 + 0x80041000, // 01E0 RET 1 R8 + 0x7002001E, // 01E1 JMP #0201 + 0x1C200F0F, // 01E2 EQ R8 R7 K15 + 0x78220009, // 01E3 JMPF R8 #01EE + 0x88200136, // 01E4 GETMBR R8 R0 K54 + 0x88201137, // 01E5 GETMBR R8 R8 K55 + 0x8C201148, // 01E6 GETMET R8 R8 K72 + 0x7C200200, // 01E7 CALL R8 1 + 0x8C240706, // 01E8 GETMET R9 R3 K6 + 0x882C0B0E, // 01E9 GETMBR R11 R5 K14 + 0x5C301000, // 01EA MOVE R12 R8 + 0x7C240600, // 01EB CALL R9 3 + 0x80041200, // 01EC RET 1 R9 + 0x70020012, // 01ED JMP #0201 + 0x54220003, // 01EE LDINT R8 4 + 0x1C200E08, // 01EF EQ R8 R7 R8 + 0x78220000, // 01F0 JMPF R8 #01F2 + 0x7002000E, // 01F1 JMP #0201 + 0x54220004, // 01F2 LDINT R8 5 + 0x1C200E08, // 01F3 EQ R8 R7 R8 + 0x7822000B, // 01F4 JMPF R8 #0201 + 0x88200349, // 01F5 GETMBR R8 R1 K73 + 0x8C20113D, // 01F6 GETMET R8 R8 K61 + 0x7C200200, // 01F7 CALL R8 1 + 0x4C240000, // 01F8 LDNIL R9 + 0x1C241009, // 01F9 EQ R9 R8 R9 + 0x78260000, // 01FA JMPF R9 #01FC + 0x58200005, // 01FB LDCONST R8 K5 + 0x8C240706, // 01FC GETMET R9 R3 K6 + 0x882C0B0E, // 01FD GETMBR R11 R5 K14 + 0x5C301000, // 01FE MOVE R12 R8 + 0x7C240600, // 01FF CALL R9 3 + 0x80041200, // 0200 RET 1 R9 + 0x700201A7, // 0201 JMP #03AA + 0x5422003B, // 0202 LDINT R8 60 + 0x1C200C08, // 0203 EQ R8 R6 R8 + 0x7822003C, // 0204 JMPF R8 #0242 + 0x1C200F05, // 0205 EQ R8 R7 K5 + 0x78220012, // 0206 JMPF R8 #021A + 0x88200136, // 0207 GETMBR R8 R0 K54 + 0x8C20114A, // 0208 GETMET R8 R8 K74 + 0x7C200200, // 0209 CALL R8 1 + 0x88240136, // 020A GETMBR R9 R0 K54 + 0x8C24134B, // 020B GETMET R9 R9 K75 + 0x7C240200, // 020C CALL R9 1 + 0x78220004, // 020D JMPF R8 #0213 + 0x78260001, // 020E JMPF R9 #0211 + 0x5828000D, // 020F LDCONST R10 K13 + 0x70020000, // 0210 JMP #0212 + 0x58280009, // 0211 LDCONST R10 K9 + 0x70020000, // 0212 JMP #0214 + 0x58280005, // 0213 LDCONST R10 K5 + 0x8C2C0706, // 0214 GETMET R11 R3 K6 + 0x88340B0E, // 0215 GETMBR R13 R5 K14 + 0x5C381400, // 0216 MOVE R14 R10 + 0x7C2C0600, // 0217 CALL R11 3 + 0x80041600, // 0218 RET 1 R11 + 0x70020026, // 0219 JMP #0241 + 0x1C200F09, // 021A EQ R8 R7 K9 + 0x78220011, // 021B JMPF R8 #022E + 0x88200136, // 021C GETMBR R8 R0 K54 + 0x8820114C, // 021D GETMBR R8 R8 K76 + 0x4C240000, // 021E LDNIL R9 + 0x20241009, // 021F NE R9 R8 R9 + 0x78260006, // 0220 JMPF R9 #0228 + 0x8C240706, // 0221 GETMET R9 R3 K6 + 0x882C0B0C, // 0222 GETMBR R11 R5 K12 + 0x8C30113D, // 0223 GETMET R12 R8 K61 + 0x7C300200, // 0224 CALL R12 1 + 0x7C240600, // 0225 CALL R9 3 + 0x80041200, // 0226 RET 1 R9 + 0x70020004, // 0227 JMP #022D + 0x8C240706, // 0228 GETMET R9 R3 K6 + 0x882C0B18, // 0229 GETMBR R11 R5 K24 + 0x4C300000, // 022A LDNIL R12 + 0x7C240600, // 022B CALL R9 3 + 0x80041200, // 022C RET 1 R9 + 0x70020012, // 022D JMP #0241 + 0x1C200F0D, // 022E EQ R8 R7 K13 + 0x78220010, // 022F JMPF R8 #0241 + 0x88200136, // 0230 GETMBR R8 R0 K54 + 0x8820114C, // 0231 GETMBR R8 R8 K76 + 0x4C240000, // 0232 LDNIL R9 + 0x20241009, // 0233 NE R9 R8 R9 + 0x78260006, // 0234 JMPF R9 #023C + 0x8C240706, // 0235 GETMET R9 R3 K6 + 0x882C0B0C, // 0236 GETMBR R11 R5 K12 + 0x8C301142, // 0237 GETMET R12 R8 K66 + 0x7C300200, // 0238 CALL R12 1 + 0x7C240600, // 0239 CALL R9 3 + 0x80041200, // 023A RET 1 R9 + 0x70020004, // 023B JMP #0241 + 0x8C240706, // 023C GETMET R9 R3 K6 + 0x882C0B18, // 023D GETMBR R11 R5 K24 + 0x4C300000, // 023E LDNIL R12 + 0x7C240600, // 023F CALL R9 3 + 0x80041200, // 0240 RET 1 R9 + 0x70020167, // 0241 JMP #03AA + 0x54220027, // 0242 LDINT R8 40 + 0x1C200C08, // 0243 EQ R8 R6 R8 + 0x782200BA, // 0244 JMPF R8 #0300 + 0x8C200133, // 0245 GETMET R8 R0 K51 + 0x5C280400, // 0246 MOVE R10 R2 + 0x7C200400, // 0247 CALL R8 2 + 0x1C200F05, // 0248 EQ R8 R7 K5 + 0x78220005, // 0249 JMPF R8 #0250 + 0x8C200706, // 024A GETMET R8 R3 K6 + 0x88280B0C, // 024B GETMBR R10 R5 K12 + 0x582C0009, // 024C LDCONST R11 K9 + 0x7C200600, // 024D CALL R8 3 + 0x80041000, // 024E RET 1 R8 + 0x700200AE, // 024F JMP #02FF + 0x1C200F09, // 0250 EQ R8 R7 K9 + 0x78220005, // 0251 JMPF R8 #0258 + 0x8C200706, // 0252 GETMET R8 R3 K6 + 0x88280B16, // 0253 GETMBR R10 R5 K22 + 0x582C004D, // 0254 LDCONST R11 K77 + 0x7C200600, // 0255 CALL R8 3 + 0x80041000, // 0256 RET 1 R8 + 0x700200A6, // 0257 JMP #02FF + 0x1C200F0D, // 0258 EQ R8 R7 K13 + 0x78220006, // 0259 JMPF R8 #0261 + 0x8C200706, // 025A GETMET R8 R3 K6 + 0x88280B0C, // 025B GETMBR R10 R5 K12 + 0x882C0136, // 025C GETMBR R11 R0 K54 + 0x882C174E, // 025D GETMBR R11 R11 K78 + 0x7C200600, // 025E CALL R8 3 + 0x80041000, // 025F RET 1 R8 + 0x7002009D, // 0260 JMP #02FF + 0x1C200F0F, // 0261 EQ R8 R7 K15 + 0x7822000A, // 0262 JMPF R8 #026E + 0x8C200706, // 0263 GETMET R8 R3 K6 + 0x88280B16, // 0264 GETMBR R10 R5 K22 + 0xB82E2400, // 0265 GETNGBL R11 K18 + 0x8C2C1726, // 0266 GETMET R11 R11 K38 + 0x5834004F, // 0267 LDCONST R13 K79 + 0x50380200, // 0268 LDBOOL R14 1 0 + 0x7C2C0600, // 0269 CALL R11 3 + 0x942C174F, // 026A GETIDX R11 R11 K79 + 0x7C200600, // 026B CALL R8 3 + 0x80041000, // 026C RET 1 R8 + 0x70020090, // 026D JMP #02FF + 0x54220003, // 026E LDINT R8 4 + 0x1C200E08, // 026F EQ R8 R7 R8 + 0x78220005, // 0270 JMPF R8 #0277 + 0x8C200706, // 0271 GETMET R8 R3 K6 + 0x88280B0C, // 0272 GETMBR R10 R5 K12 + 0x542E7FFF, // 0273 LDINT R11 32768 + 0x7C200600, // 0274 CALL R8 3 + 0x80041000, // 0275 RET 1 R8 + 0x70020087, // 0276 JMP #02FF + 0x54220004, // 0277 LDINT R8 5 + 0x1C200E08, // 0278 EQ R8 R7 R8 + 0x7822000A, // 0279 JMPF R8 #0285 + 0x8C200706, // 027A GETMET R8 R3 K6 + 0x88280B16, // 027B GETMBR R10 R5 K22 + 0xB82E2400, // 027C GETNGBL R11 K18 + 0x8C2C1726, // 027D GETMET R11 R11 K38 + 0x58340050, // 027E LDCONST R13 K80 + 0x50380200, // 027F LDBOOL R14 1 0 + 0x7C2C0600, // 0280 CALL R11 3 + 0x942C1751, // 0281 GETIDX R11 R11 K81 + 0x7C200600, // 0282 CALL R8 3 + 0x80041000, // 0283 RET 1 R8 + 0x70020079, // 0284 JMP #02FF + 0x54220005, // 0285 LDINT R8 6 + 0x1C200E08, // 0286 EQ R8 R7 R8 + 0x78220005, // 0287 JMPF R8 #028E + 0x8C200706, // 0288 GETMET R8 R3 K6 + 0x88280B16, // 0289 GETMBR R10 R5 K22 + 0x582C0052, // 028A LDCONST R11 K82 + 0x7C200600, // 028B CALL R8 3 + 0x80041000, // 028C RET 1 R8 + 0x70020070, // 028D JMP #02FF + 0x54220006, // 028E LDINT R8 7 + 0x1C200E08, // 028F EQ R8 R7 R8 + 0x78220005, // 0290 JMPF R8 #0297 + 0x8C200706, // 0291 GETMET R8 R3 K6 + 0x88280B0C, // 0292 GETMBR R10 R5 K12 + 0x582C0005, // 0293 LDCONST R11 K5 + 0x7C200600, // 0294 CALL R8 3 + 0x80041000, // 0295 RET 1 R8 + 0x70020067, // 0296 JMP #02FF + 0x54220007, // 0297 LDINT R8 8 + 0x1C200E08, // 0298 EQ R8 R7 R8 + 0x7822000B, // 0299 JMPF R8 #02A6 + 0x8C200706, // 029A GETMET R8 R3 K6 + 0x88280B16, // 029B GETMBR R10 R5 K22 + 0xB82E2400, // 029C GETNGBL R11 K18 + 0x8C2C1726, // 029D GETMET R11 R11 K38 + 0x58340053, // 029E LDCONST R13 K83 + 0x50380200, // 029F LDBOOL R14 1 0 + 0x7C2C0600, // 02A0 CALL R11 3 0x942C1754, // 02A1 GETIDX R11 R11 K84 - 0x7C200600, // 02A2 CALL R8 3 - 0x80041000, // 02A3 RET 1 R8 - 0x70020058, // 02A4 JMP #02FE - 0x54220008, // 02A5 LDINT R8 9 - 0x1C200E08, // 02A6 EQ R8 R7 R8 - 0x78220005, // 02A7 JMPF R8 #02AE - 0x8C200706, // 02A8 GETMET R8 R3 K6 - 0x88280B0C, // 02A9 GETMBR R10 R5 K12 - 0x582C0009, // 02AA LDCONST R11 K9 - 0x7C200600, // 02AB CALL R8 3 - 0x80041000, // 02AC RET 1 R8 - 0x7002004F, // 02AD JMP #02FE - 0x54220009, // 02AE LDINT R8 10 - 0x1C200E08, // 02AF EQ R8 R7 R8 - 0x78220015, // 02B0 JMPF R8 #02C7 - 0xB8222400, // 02B1 GETNGBL R8 K18 - 0x8C201126, // 02B2 GETMET R8 R8 K38 - 0x58280052, // 02B3 LDCONST R10 K82 - 0x502C0200, // 02B4 LDBOOL R11 1 0 - 0x7C200600, // 02B5 CALL R8 3 - 0x94201153, // 02B6 GETIDX R8 R8 K83 - 0x94201155, // 02B7 GETIDX R8 R8 K85 - 0x8C24091B, // 02B8 GETMET R9 R4 K27 - 0x5C2C1000, // 02B9 MOVE R11 R8 - 0x58300056, // 02BA LDCONST R12 K86 - 0x7C240600, // 02BB CALL R9 3 - 0x24281305, // 02BC GT R10 R9 K5 - 0x782A0002, // 02BD JMPF R10 #02C1 - 0x04281309, // 02BE SUB R10 R9 K9 - 0x402A0A0A, // 02BF CONNECT R10 K5 R10 - 0x9420100A, // 02C0 GETIDX R8 R8 R10 - 0x8C280706, // 02C1 GETMET R10 R3 K6 - 0x88300B16, // 02C2 GETMBR R12 R5 K22 - 0x5C341000, // 02C3 MOVE R13 R8 - 0x7C280600, // 02C4 CALL R10 3 - 0x80041400, // 02C5 RET 1 R10 - 0x70020036, // 02C6 JMP #02FE - 0x5422000E, // 02C7 LDINT R8 15 - 0x1C200E08, // 02C8 EQ R8 R7 R8 - 0x7822000B, // 02C9 JMPF R8 #02D6 - 0x8C200706, // 02CA GETMET R8 R3 K6 - 0x88280B16, // 02CB GETMBR R10 R5 K22 - 0xB82E2400, // 02CC GETNGBL R11 K18 - 0x8C2C1725, // 02CD GETMET R11 R11 K37 - 0x7C2C0200, // 02CE CALL R11 1 - 0x8C2C171B, // 02CF GETMET R11 R11 K27 - 0x5834001C, // 02D0 LDCONST R13 K28 - 0x5838001D, // 02D1 LDCONST R14 K29 - 0x7C2C0600, // 02D2 CALL R11 3 - 0x7C200600, // 02D3 CALL R8 3 - 0x80041000, // 02D4 RET 1 R8 - 0x70020027, // 02D5 JMP #02FE - 0x54220010, // 02D6 LDINT R8 17 - 0x1C200E08, // 02D7 EQ R8 R7 R8 - 0x78220005, // 02D8 JMPF R8 #02DF - 0x8C200706, // 02D9 GETMET R8 R3 K6 - 0x88280B10, // 02DA GETMBR R10 R5 K16 - 0x582C0009, // 02DB LDCONST R11 K9 - 0x7C200600, // 02DC CALL R8 3 - 0x80041000, // 02DD RET 1 R8 - 0x7002001E, // 02DE JMP #02FE - 0x54220011, // 02DF LDINT R8 18 - 0x1C200E08, // 02E0 EQ R8 R7 R8 - 0x7822000B, // 02E1 JMPF R8 #02EE - 0x8C200706, // 02E2 GETMET R8 R3 K6 - 0x88280B16, // 02E3 GETMBR R10 R5 K22 - 0xB82E2400, // 02E4 GETNGBL R11 K18 - 0x8C2C1725, // 02E5 GETMET R11 R11 K37 - 0x7C2C0200, // 02E6 CALL R11 1 - 0x8C2C171B, // 02E7 GETMET R11 R11 K27 - 0x5834001C, // 02E8 LDCONST R13 K28 - 0x5838001D, // 02E9 LDCONST R14 K29 - 0x7C2C0600, // 02EA CALL R11 3 - 0x7C200600, // 02EB CALL R8 3 - 0x80041000, // 02EC RET 1 R8 - 0x7002000F, // 02ED JMP #02FE - 0x54220012, // 02EE LDINT R8 19 - 0x1C200E08, // 02EF EQ R8 R7 R8 - 0x7822000C, // 02F0 JMPF R8 #02FE - 0x8C200B0A, // 02F1 GETMET R8 R5 K10 - 0x7C200200, // 02F2 CALL R8 1 - 0x8C24110B, // 02F3 GETMET R9 R8 K11 - 0x582C0005, // 02F4 LDCONST R11 K5 - 0x88300B0C, // 02F5 GETMBR R12 R5 K12 - 0x5834000F, // 02F6 LDCONST R13 K15 - 0x7C240800, // 02F7 CALL R9 4 - 0x8C24110B, // 02F8 GETMET R9 R8 K11 - 0x582C0009, // 02F9 LDCONST R11 K9 - 0x88300B0C, // 02FA GETMBR R12 R5 K12 - 0x5834000F, // 02FB LDCONST R13 K15 - 0x7C240800, // 02FC CALL R9 4 - 0x80041000, // 02FD RET 1 R8 - 0x700200A8, // 02FE JMP #03A8 - 0x5422003E, // 02FF LDINT R8 63 - 0x1C200C08, // 0300 EQ R8 R6 R8 - 0x78220000, // 0301 JMPF R8 #0303 - 0x700200A4, // 0302 JMP #03A8 - 0x54220029, // 0303 LDINT R8 42 - 0x1C200C08, // 0304 EQ R8 R6 R8 - 0x7822001D, // 0305 JMPF R8 #0324 - 0x1C200F05, // 0306 EQ R8 R7 K5 - 0x78220003, // 0307 JMPF R8 #030C - 0x8C200B11, // 0308 GETMET R8 R5 K17 - 0x7C200200, // 0309 CALL R8 1 - 0x80041000, // 030A RET 1 R8 - 0x70020016, // 030B JMP #0323 - 0x1C200F09, // 030C EQ R8 R7 K9 - 0x78220005, // 030D JMPF R8 #0314 - 0x8C200706, // 030E GETMET R8 R3 K6 - 0x88280B10, // 030F GETMBR R10 R5 K16 - 0x582C0005, // 0310 LDCONST R11 K5 - 0x7C200600, // 0311 CALL R8 3 - 0x80041000, // 0312 RET 1 R8 - 0x7002000E, // 0313 JMP #0323 - 0x1C200F0D, // 0314 EQ R8 R7 K13 - 0x78220005, // 0315 JMPF R8 #031C - 0x8C200706, // 0316 GETMET R8 R3 K6 - 0x88280B0E, // 0317 GETMBR R10 R5 K14 - 0x582C0009, // 0318 LDCONST R11 K9 - 0x7C200600, // 0319 CALL R8 3 - 0x80041000, // 031A RET 1 R8 - 0x70020006, // 031B JMP #0323 - 0x1C200F0F, // 031C EQ R8 R7 K15 - 0x78220004, // 031D JMPF R8 #0323 - 0x8C200706, // 031E GETMET R8 R3 K6 - 0x88280B18, // 031F GETMBR R10 R5 K24 - 0x4C2C0000, // 0320 LDNIL R11 - 0x7C200600, // 0321 CALL R8 3 - 0x80041000, // 0322 RET 1 R8 - 0x70020083, // 0323 JMP #03A8 - 0x5422002A, // 0324 LDINT R8 43 - 0x1C200C08, // 0325 EQ R8 R6 R8 - 0x78220016, // 0326 JMPF R8 #033E - 0x1C200F05, // 0327 EQ R8 R7 K5 - 0x78220007, // 0328 JMPF R8 #0331 - 0x8C200706, // 0329 GETMET R8 R3 K6 - 0x88280B16, // 032A GETMBR R10 R5 K22 - 0xB82E2400, // 032B GETNGBL R11 K18 - 0x8C2C1757, // 032C GETMET R11 R11 K87 - 0x7C2C0200, // 032D CALL R11 1 - 0x7C200600, // 032E CALL R8 3 - 0x80041000, // 032F RET 1 R8 - 0x7002000B, // 0330 JMP #033D - 0x1C200F09, // 0331 EQ R8 R7 K9 - 0x78220009, // 0332 JMPF R8 #033D - 0x8C200B11, // 0333 GETMET R8 R5 K17 - 0x7C200200, // 0334 CALL R8 1 - 0x8C24110B, // 0335 GETMET R9 R8 K11 - 0x4C2C0000, // 0336 LDNIL R11 - 0x88300B16, // 0337 GETMBR R12 R5 K22 - 0xB8362400, // 0338 GETNGBL R13 K18 - 0x8C341B57, // 0339 GETMET R13 R13 K87 - 0x7C340200, // 033A CALL R13 1 - 0x7C240800, // 033B CALL R9 4 - 0x80041000, // 033C RET 1 R8 - 0x70020069, // 033D JMP #03A8 - 0x5422002B, // 033E LDINT R8 44 - 0x1C200C08, // 033F EQ R8 R6 R8 - 0x7822001C, // 0340 JMPF R8 #035E - 0x1C200F05, // 0341 EQ R8 R7 K5 - 0x78220005, // 0342 JMPF R8 #0349 - 0x8C200706, // 0343 GETMET R8 R3 K6 - 0x88280B0E, // 0344 GETMBR R10 R5 K14 - 0x582C0009, // 0345 LDCONST R11 K9 - 0x7C200600, // 0346 CALL R8 3 - 0x80041000, // 0347 RET 1 R8 - 0x70020013, // 0348 JMP #035D - 0x1C200F09, // 0349 EQ R8 R7 K9 - 0x78220005, // 034A JMPF R8 #0351 - 0x8C200706, // 034B GETMET R8 R3 K6 - 0x88280B0E, // 034C GETMBR R10 R5 K14 - 0x542E0003, // 034D LDINT R11 4 - 0x7C200600, // 034E CALL R8 3 - 0x80041000, // 034F RET 1 R8 - 0x7002000B, // 0350 JMP #035D - 0x1C200F0D, // 0351 EQ R8 R7 K13 - 0x78220009, // 0352 JMPF R8 #035D - 0x8C200B11, // 0353 GETMET R8 R5 K17 - 0x7C200200, // 0354 CALL R8 1 - 0x8C24110B, // 0355 GETMET R9 R8 K11 - 0x4C2C0000, // 0356 LDNIL R11 - 0x8C300B58, // 0357 GETMET R12 R5 K88 - 0x88380B0E, // 0358 GETMBR R14 R5 K14 - 0x543E0003, // 0359 LDINT R15 4 - 0x7C300600, // 035A CALL R12 3 - 0x7C240600, // 035B CALL R9 3 - 0x80041000, // 035C RET 1 R8 - 0x70020049, // 035D JMP #03A8 - 0x54220030, // 035E LDINT R8 49 - 0x1C200C08, // 035F EQ R8 R6 R8 - 0x78220010, // 0360 JMPF R8 #0372 - 0x1C200F0F, // 0361 EQ R8 R7 K15 - 0x78220005, // 0362 JMPF R8 #0369 - 0x8C200706, // 0363 GETMET R8 R3 K6 - 0x88280B0E, // 0364 GETMBR R10 R5 K14 - 0x542E001D, // 0365 LDINT R11 30 - 0x7C200600, // 0366 CALL R8 3 - 0x80041000, // 0367 RET 1 R8 - 0x70020007, // 0368 JMP #0371 - 0x5422FFFB, // 0369 LDINT R8 65532 - 0x1C200E08, // 036A EQ R8 R7 R8 - 0x78220004, // 036B JMPF R8 #0371 - 0x8C200706, // 036C GETMET R8 R3 K6 - 0x88280B2A, // 036D GETMBR R10 R5 K42 - 0x542E0003, // 036E LDINT R11 4 - 0x7C200600, // 036F CALL R8 3 - 0x80041000, // 0370 RET 1 R8 - 0x70020035, // 0371 JMP #03A8 - 0x5422001C, // 0372 LDINT R8 29 - 0x1C200C08, // 0373 EQ R8 R6 R8 - 0x78220029, // 0374 JMPF R8 #039F - 0x1C200F0F, // 0375 EQ R8 R7 K15 - 0x7822001D, // 0376 JMPF R8 #0395 - 0x8C200B11, // 0377 GETMET R8 R5 K17 - 0x7C200200, // 0378 CALL R8 1 - 0x88240136, // 0379 GETMBR R9 R0 K54 - 0x8C241359, // 037A GETMET R9 R9 K89 - 0x502C0200, // 037B LDBOOL R11 1 0 - 0x7C240400, // 037C CALL R9 2 - 0x88280136, // 037D GETMBR R10 R0 K54 - 0x8828155A, // 037E GETMBR R10 R10 K90 - 0x602C0010, // 037F GETGBL R11 G16 - 0x5C301200, // 0380 MOVE R12 R9 - 0x7C2C0200, // 0381 CALL R11 1 - 0xA802000C, // 0382 EXBLK 0 #0390 - 0x5C301600, // 0383 MOVE R12 R11 - 0x7C300000, // 0384 CALL R12 0 - 0x5C341400, // 0385 MOVE R13 R10 - 0x78360002, // 0386 JMPF R13 #038A - 0x5436FEFF, // 0387 LDINT R13 65280 - 0x1434180D, // 0388 LT R13 R12 R13 - 0x78360004, // 0389 JMPF R13 #038F - 0x8C34110B, // 038A GETMET R13 R8 K11 - 0x4C3C0000, // 038B LDNIL R15 - 0x88400B0C, // 038C GETMBR R16 R5 K12 - 0x5C441800, // 038D MOVE R17 R12 - 0x7C340800, // 038E CALL R13 4 - 0x7001FFF2, // 038F JMP #0383 - 0x582C003D, // 0390 LDCONST R11 K61 - 0xAC2C0200, // 0391 CATCH R11 1 0 - 0xB0080000, // 0392 RAISE 2 R0 R0 - 0x80041000, // 0393 RET 1 R8 - 0x70020008, // 0394 JMP #039E - 0x60200003, // 0395 GETGBL R8 G3 - 0x5C240000, // 0396 MOVE R9 R0 - 0x7C200200, // 0397 CALL R8 1 - 0x8C20115B, // 0398 GETMET R8 R8 K91 - 0x5C280200, // 0399 MOVE R10 R1 - 0x5C2C0400, // 039A MOVE R11 R2 - 0x5C300600, // 039B MOVE R12 R3 - 0x7C200800, // 039C CALL R8 4 - 0x80041000, // 039D RET 1 R8 - 0x70020008, // 039E JMP #03A8 - 0x60200003, // 039F GETGBL R8 G3 - 0x5C240000, // 03A0 MOVE R9 R0 - 0x7C200200, // 03A1 CALL R8 1 - 0x8C20115B, // 03A2 GETMET R8 R8 K91 - 0x5C280200, // 03A3 MOVE R10 R1 - 0x5C2C0400, // 03A4 MOVE R11 R2 - 0x5C300600, // 03A5 MOVE R12 R3 - 0x7C200800, // 03A6 CALL R8 4 - 0x80041000, // 03A7 RET 1 R8 - 0x80000000, // 03A8 RET 0 + 0x942C1755, // 02A2 GETIDX R11 R11 K85 + 0x7C200600, // 02A3 CALL R8 3 + 0x80041000, // 02A4 RET 1 R8 + 0x70020058, // 02A5 JMP #02FF + 0x54220008, // 02A6 LDINT R8 9 + 0x1C200E08, // 02A7 EQ R8 R7 R8 + 0x78220005, // 02A8 JMPF R8 #02AF + 0x8C200706, // 02A9 GETMET R8 R3 K6 + 0x88280B0C, // 02AA GETMBR R10 R5 K12 + 0x582C0009, // 02AB LDCONST R11 K9 + 0x7C200600, // 02AC CALL R8 3 + 0x80041000, // 02AD RET 1 R8 + 0x7002004F, // 02AE JMP #02FF + 0x54220009, // 02AF LDINT R8 10 + 0x1C200E08, // 02B0 EQ R8 R7 R8 + 0x78220015, // 02B1 JMPF R8 #02C8 + 0xB8222400, // 02B2 GETNGBL R8 K18 + 0x8C201126, // 02B3 GETMET R8 R8 K38 + 0x58280053, // 02B4 LDCONST R10 K83 + 0x502C0200, // 02B5 LDBOOL R11 1 0 + 0x7C200600, // 02B6 CALL R8 3 + 0x94201154, // 02B7 GETIDX R8 R8 K84 + 0x94201156, // 02B8 GETIDX R8 R8 K86 + 0x8C24091B, // 02B9 GETMET R9 R4 K27 + 0x5C2C1000, // 02BA MOVE R11 R8 + 0x58300057, // 02BB LDCONST R12 K87 + 0x7C240600, // 02BC CALL R9 3 + 0x24281305, // 02BD GT R10 R9 K5 + 0x782A0002, // 02BE JMPF R10 #02C2 + 0x04281309, // 02BF SUB R10 R9 K9 + 0x402A0A0A, // 02C0 CONNECT R10 K5 R10 + 0x9420100A, // 02C1 GETIDX R8 R8 R10 + 0x8C280706, // 02C2 GETMET R10 R3 K6 + 0x88300B16, // 02C3 GETMBR R12 R5 K22 + 0x5C341000, // 02C4 MOVE R13 R8 + 0x7C280600, // 02C5 CALL R10 3 + 0x80041400, // 02C6 RET 1 R10 + 0x70020036, // 02C7 JMP #02FF + 0x5422000E, // 02C8 LDINT R8 15 + 0x1C200E08, // 02C9 EQ R8 R7 R8 + 0x7822000B, // 02CA JMPF R8 #02D7 + 0x8C200706, // 02CB GETMET R8 R3 K6 + 0x88280B16, // 02CC GETMBR R10 R5 K22 + 0xB82E2400, // 02CD GETNGBL R11 K18 + 0x8C2C1725, // 02CE GETMET R11 R11 K37 + 0x7C2C0200, // 02CF CALL R11 1 + 0x8C2C171B, // 02D0 GETMET R11 R11 K27 + 0x5834001C, // 02D1 LDCONST R13 K28 + 0x5838001D, // 02D2 LDCONST R14 K29 + 0x7C2C0600, // 02D3 CALL R11 3 + 0x7C200600, // 02D4 CALL R8 3 + 0x80041000, // 02D5 RET 1 R8 + 0x70020027, // 02D6 JMP #02FF + 0x54220010, // 02D7 LDINT R8 17 + 0x1C200E08, // 02D8 EQ R8 R7 R8 + 0x78220005, // 02D9 JMPF R8 #02E0 + 0x8C200706, // 02DA GETMET R8 R3 K6 + 0x88280B10, // 02DB GETMBR R10 R5 K16 + 0x582C0009, // 02DC LDCONST R11 K9 + 0x7C200600, // 02DD CALL R8 3 + 0x80041000, // 02DE RET 1 R8 + 0x7002001E, // 02DF JMP #02FF + 0x54220011, // 02E0 LDINT R8 18 + 0x1C200E08, // 02E1 EQ R8 R7 R8 + 0x7822000B, // 02E2 JMPF R8 #02EF + 0x8C200706, // 02E3 GETMET R8 R3 K6 + 0x88280B16, // 02E4 GETMBR R10 R5 K22 + 0xB82E2400, // 02E5 GETNGBL R11 K18 + 0x8C2C1725, // 02E6 GETMET R11 R11 K37 + 0x7C2C0200, // 02E7 CALL R11 1 + 0x8C2C171B, // 02E8 GETMET R11 R11 K27 + 0x5834001C, // 02E9 LDCONST R13 K28 + 0x5838001D, // 02EA LDCONST R14 K29 + 0x7C2C0600, // 02EB CALL R11 3 + 0x7C200600, // 02EC CALL R8 3 + 0x80041000, // 02ED RET 1 R8 + 0x7002000F, // 02EE JMP #02FF + 0x54220012, // 02EF LDINT R8 19 + 0x1C200E08, // 02F0 EQ R8 R7 R8 + 0x7822000C, // 02F1 JMPF R8 #02FF + 0x8C200B0A, // 02F2 GETMET R8 R5 K10 + 0x7C200200, // 02F3 CALL R8 1 + 0x8C24110B, // 02F4 GETMET R9 R8 K11 + 0x582C0005, // 02F5 LDCONST R11 K5 + 0x88300B0C, // 02F6 GETMBR R12 R5 K12 + 0x5834000F, // 02F7 LDCONST R13 K15 + 0x7C240800, // 02F8 CALL R9 4 + 0x8C24110B, // 02F9 GETMET R9 R8 K11 + 0x582C0009, // 02FA LDCONST R11 K9 + 0x88300B0C, // 02FB GETMBR R12 R5 K12 + 0x5834000F, // 02FC LDCONST R13 K15 + 0x7C240800, // 02FD CALL R9 4 + 0x80041000, // 02FE RET 1 R8 + 0x700200A9, // 02FF JMP #03AA + 0x5422003E, // 0300 LDINT R8 63 + 0x1C200C08, // 0301 EQ R8 R6 R8 + 0x78220000, // 0302 JMPF R8 #0304 + 0x700200A5, // 0303 JMP #03AA + 0x54220029, // 0304 LDINT R8 42 + 0x1C200C08, // 0305 EQ R8 R6 R8 + 0x7822001D, // 0306 JMPF R8 #0325 + 0x1C200F05, // 0307 EQ R8 R7 K5 + 0x78220003, // 0308 JMPF R8 #030D + 0x8C200B11, // 0309 GETMET R8 R5 K17 + 0x7C200200, // 030A CALL R8 1 + 0x80041000, // 030B RET 1 R8 + 0x70020016, // 030C JMP #0324 + 0x1C200F09, // 030D EQ R8 R7 K9 + 0x78220005, // 030E JMPF R8 #0315 + 0x8C200706, // 030F GETMET R8 R3 K6 + 0x88280B10, // 0310 GETMBR R10 R5 K16 + 0x582C0005, // 0311 LDCONST R11 K5 + 0x7C200600, // 0312 CALL R8 3 + 0x80041000, // 0313 RET 1 R8 + 0x7002000E, // 0314 JMP #0324 + 0x1C200F0D, // 0315 EQ R8 R7 K13 + 0x78220005, // 0316 JMPF R8 #031D + 0x8C200706, // 0317 GETMET R8 R3 K6 + 0x88280B0E, // 0318 GETMBR R10 R5 K14 + 0x582C0009, // 0319 LDCONST R11 K9 + 0x7C200600, // 031A CALL R8 3 + 0x80041000, // 031B RET 1 R8 + 0x70020006, // 031C JMP #0324 + 0x1C200F0F, // 031D EQ R8 R7 K15 + 0x78220004, // 031E JMPF R8 #0324 + 0x8C200706, // 031F GETMET R8 R3 K6 + 0x88280B18, // 0320 GETMBR R10 R5 K24 + 0x4C2C0000, // 0321 LDNIL R11 + 0x7C200600, // 0322 CALL R8 3 + 0x80041000, // 0323 RET 1 R8 + 0x70020084, // 0324 JMP #03AA + 0x5422002A, // 0325 LDINT R8 43 + 0x1C200C08, // 0326 EQ R8 R6 R8 + 0x78220016, // 0327 JMPF R8 #033F + 0x1C200F05, // 0328 EQ R8 R7 K5 + 0x78220007, // 0329 JMPF R8 #0332 + 0x8C200706, // 032A GETMET R8 R3 K6 + 0x88280B16, // 032B GETMBR R10 R5 K22 + 0xB82E2400, // 032C GETNGBL R11 K18 + 0x8C2C1758, // 032D GETMET R11 R11 K88 + 0x7C2C0200, // 032E CALL R11 1 + 0x7C200600, // 032F CALL R8 3 + 0x80041000, // 0330 RET 1 R8 + 0x7002000B, // 0331 JMP #033E + 0x1C200F09, // 0332 EQ R8 R7 K9 + 0x78220009, // 0333 JMPF R8 #033E + 0x8C200B11, // 0334 GETMET R8 R5 K17 + 0x7C200200, // 0335 CALL R8 1 + 0x8C24110B, // 0336 GETMET R9 R8 K11 + 0x4C2C0000, // 0337 LDNIL R11 + 0x88300B16, // 0338 GETMBR R12 R5 K22 + 0xB8362400, // 0339 GETNGBL R13 K18 + 0x8C341B58, // 033A GETMET R13 R13 K88 + 0x7C340200, // 033B CALL R13 1 + 0x7C240800, // 033C CALL R9 4 + 0x80041000, // 033D RET 1 R8 + 0x7002006A, // 033E JMP #03AA + 0x5422002B, // 033F LDINT R8 44 + 0x1C200C08, // 0340 EQ R8 R6 R8 + 0x7822001C, // 0341 JMPF R8 #035F + 0x1C200F05, // 0342 EQ R8 R7 K5 + 0x78220005, // 0343 JMPF R8 #034A + 0x8C200706, // 0344 GETMET R8 R3 K6 + 0x88280B0E, // 0345 GETMBR R10 R5 K14 + 0x582C0009, // 0346 LDCONST R11 K9 + 0x7C200600, // 0347 CALL R8 3 + 0x80041000, // 0348 RET 1 R8 + 0x70020013, // 0349 JMP #035E + 0x1C200F09, // 034A EQ R8 R7 K9 + 0x78220005, // 034B JMPF R8 #0352 + 0x8C200706, // 034C GETMET R8 R3 K6 + 0x88280B0E, // 034D GETMBR R10 R5 K14 + 0x542E0003, // 034E LDINT R11 4 + 0x7C200600, // 034F CALL R8 3 + 0x80041000, // 0350 RET 1 R8 + 0x7002000B, // 0351 JMP #035E + 0x1C200F0D, // 0352 EQ R8 R7 K13 + 0x78220009, // 0353 JMPF R8 #035E + 0x8C200B11, // 0354 GETMET R8 R5 K17 + 0x7C200200, // 0355 CALL R8 1 + 0x8C24110B, // 0356 GETMET R9 R8 K11 + 0x4C2C0000, // 0357 LDNIL R11 + 0x8C300B59, // 0358 GETMET R12 R5 K89 + 0x88380B0E, // 0359 GETMBR R14 R5 K14 + 0x543E0003, // 035A LDINT R15 4 + 0x7C300600, // 035B CALL R12 3 + 0x7C240600, // 035C CALL R9 3 + 0x80041000, // 035D RET 1 R8 + 0x7002004A, // 035E JMP #03AA + 0x54220030, // 035F LDINT R8 49 + 0x1C200C08, // 0360 EQ R8 R6 R8 + 0x78220010, // 0361 JMPF R8 #0373 + 0x1C200F0F, // 0362 EQ R8 R7 K15 + 0x78220005, // 0363 JMPF R8 #036A + 0x8C200706, // 0364 GETMET R8 R3 K6 + 0x88280B0E, // 0365 GETMBR R10 R5 K14 + 0x542E001D, // 0366 LDINT R11 30 + 0x7C200600, // 0367 CALL R8 3 + 0x80041000, // 0368 RET 1 R8 + 0x70020007, // 0369 JMP #0372 + 0x5422FFFB, // 036A LDINT R8 65532 + 0x1C200E08, // 036B EQ R8 R7 R8 + 0x78220004, // 036C JMPF R8 #0372 + 0x8C200706, // 036D GETMET R8 R3 K6 + 0x88280B2A, // 036E GETMBR R10 R5 K42 + 0x542E0003, // 036F LDINT R11 4 + 0x7C200600, // 0370 CALL R8 3 + 0x80041000, // 0371 RET 1 R8 + 0x70020036, // 0372 JMP #03AA + 0x5422001C, // 0373 LDINT R8 29 + 0x1C200C08, // 0374 EQ R8 R6 R8 + 0x7822002A, // 0375 JMPF R8 #03A1 + 0x1C200F0F, // 0376 EQ R8 R7 K15 + 0x7822001E, // 0377 JMPF R8 #0397 + 0x8C200B11, // 0378 GETMET R8 R5 K17 + 0x7C200200, // 0379 CALL R8 1 + 0x88240136, // 037A GETMBR R9 R0 K54 + 0x8C24135A, // 037B GETMET R9 R9 K90 + 0x502C0200, // 037C LDBOOL R11 1 0 + 0x7C240400, // 037D CALL R9 2 + 0x88280136, // 037E GETMBR R10 R0 K54 + 0x8828155B, // 037F GETMBR R10 R10 K91 + 0x602C0010, // 0380 GETGBL R11 G16 + 0x5C301200, // 0381 MOVE R12 R9 + 0x7C2C0200, // 0382 CALL R11 1 + 0xA802000D, // 0383 EXBLK 0 #0392 + 0x5C301600, // 0384 MOVE R12 R11 + 0x7C300000, // 0385 CALL R12 0 + 0x5C341400, // 0386 MOVE R13 R10 + 0x78360003, // 0387 JMPF R13 #038C + 0xB8360200, // 0388 GETNGBL R13 K1 + 0x88341B3C, // 0389 GETMBR R13 R13 K60 + 0x1434180D, // 038A LT R13 R12 R13 + 0x78360004, // 038B JMPF R13 #0391 + 0x8C34110B, // 038C GETMET R13 R8 K11 + 0x4C3C0000, // 038D LDNIL R15 + 0x88400B0C, // 038E GETMBR R16 R5 K12 + 0x5C441800, // 038F MOVE R17 R12 + 0x7C340800, // 0390 CALL R13 4 + 0x7001FFF1, // 0391 JMP #0384 + 0x582C003E, // 0392 LDCONST R11 K62 + 0xAC2C0200, // 0393 CATCH R11 1 0 + 0xB0080000, // 0394 RAISE 2 R0 R0 + 0x80041000, // 0395 RET 1 R8 + 0x70020008, // 0396 JMP #03A0 + 0x60200003, // 0397 GETGBL R8 G3 + 0x5C240000, // 0398 MOVE R9 R0 + 0x7C200200, // 0399 CALL R8 1 + 0x8C20115C, // 039A GETMET R8 R8 K92 + 0x5C280200, // 039B MOVE R10 R1 + 0x5C2C0400, // 039C MOVE R11 R2 + 0x5C300600, // 039D MOVE R12 R3 + 0x7C200800, // 039E CALL R8 4 + 0x80041000, // 039F RET 1 R8 + 0x70020008, // 03A0 JMP #03AA + 0x60200003, // 03A1 GETGBL R8 G3 + 0x5C240000, // 03A2 MOVE R9 R0 + 0x7C200200, // 03A3 CALL R8 1 + 0x8C20115C, // 03A4 GETMET R8 R8 K92 + 0x5C280200, // 03A5 MOVE R10 R1 + 0x5C2C0400, // 03A6 MOVE R11 R2 + 0x5C300600, // 03A7 MOVE R12 R3 + 0x7C200800, // 03A8 CALL R8 4 + 0x80041000, // 03A9 RET 1 R8 + 0x80000000, // 03AA RET 0 }) ) ); diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Session_Store.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Session_Store.h index e4ccf468a..64ab0848d 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Session_Store.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Session_Store.h @@ -533,7 +533,7 @@ be_local_closure(Matter_Session_Store_count_active_fabrics, /* name */ ********************************************************************/ be_local_closure(Matter_Session_Store_remove_fabric, /* name */ be_nested_proto( - 8, /* nstack */ + 7, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -542,8 +542,8 @@ be_local_closure(Matter_Session_Store_remove_fabric, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str_weak(sessions), + /* K0 */ be_nested_str_weak(sessions), + /* K1 */ be_const_int(0), /* K2 */ be_nested_str_weak(_fabric), /* K3 */ be_nested_str_weak(remove), /* K4 */ be_const_int(1), @@ -552,33 +552,41 @@ be_local_closure(Matter_Session_Store_remove_fabric, /* name */ }), be_str_weak(remove_fabric), &be_const_str_solidified, - ( &(const binstruction[26]) { /* code */ - 0x58080000, // 0000 LDCONST R2 K0 - 0x600C000C, // 0001 GETGBL R3 G12 - 0x88100101, // 0002 GETMBR R4 R0 K1 - 0x7C0C0200, // 0003 CALL R3 1 - 0x140C0403, // 0004 LT R3 R2 R3 - 0x780E000B, // 0005 JMPF R3 #0012 - 0x880C0101, // 0006 GETMBR R3 R0 K1 - 0x940C0602, // 0007 GETIDX R3 R3 R2 - 0x880C0702, // 0008 GETMBR R3 R3 K2 - 0x1C0C0601, // 0009 EQ R3 R3 R1 - 0x780E0004, // 000A JMPF R3 #0010 - 0x880C0101, // 000B GETMBR R3 R0 K1 - 0x8C0C0703, // 000C GETMET R3 R3 K3 - 0x5C140400, // 000D MOVE R5 R2 - 0x7C0C0400, // 000E CALL R3 2 - 0x70020000, // 000F JMP #0011 - 0x00080504, // 0010 ADD R2 R2 K4 - 0x7001FFEE, // 0011 JMP #0001 - 0x880C0105, // 0012 GETMBR R3 R0 K5 - 0x8C0C0703, // 0013 GETMET R3 R3 K3 - 0x88140105, // 0014 GETMBR R5 R0 K5 - 0x8C140B06, // 0015 GETMET R5 R5 K6 - 0x5C1C0200, // 0016 MOVE R7 R1 - 0x7C140400, // 0017 CALL R5 2 - 0x7C0C0400, // 0018 CALL R3 2 - 0x80000000, // 0019 RET 0 + ( &(const binstruction[34]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x20080403, // 0002 NE R2 R2 R3 + 0x780A0011, // 0003 JMPF R2 #0016 + 0x58080001, // 0004 LDCONST R2 K1 + 0x600C000C, // 0005 GETGBL R3 G12 + 0x88100100, // 0006 GETMBR R4 R0 K0 + 0x7C0C0200, // 0007 CALL R3 1 + 0x140C0403, // 0008 LT R3 R2 R3 + 0x780E000B, // 0009 JMPF R3 #0016 + 0x880C0100, // 000A GETMBR R3 R0 K0 + 0x940C0602, // 000B GETIDX R3 R3 R2 + 0x880C0702, // 000C GETMBR R3 R3 K2 + 0x1C0C0601, // 000D EQ R3 R3 R1 + 0x780E0004, // 000E JMPF R3 #0014 + 0x880C0100, // 000F GETMBR R3 R0 K0 + 0x8C0C0703, // 0010 GETMET R3 R3 K3 + 0x5C140400, // 0011 MOVE R5 R2 + 0x7C0C0400, // 0012 CALL R3 2 + 0x70020000, // 0013 JMP #0015 + 0x00080504, // 0014 ADD R2 R2 K4 + 0x7001FFEE, // 0015 JMP #0005 + 0x88080105, // 0016 GETMBR R2 R0 K5 + 0x4C0C0000, // 0017 LDNIL R3 + 0x20080403, // 0018 NE R2 R2 R3 + 0x780A0006, // 0019 JMPF R2 #0021 + 0x88080105, // 001A GETMBR R2 R0 K5 + 0x8C080503, // 001B GETMET R2 R2 K3 + 0x88100105, // 001C GETMBR R4 R0 K5 + 0x8C100906, // 001D GETMET R4 R4 K6 + 0x5C180200, // 001E MOVE R6 R1 + 0x7C100400, // 001F CALL R4 2 + 0x7C080400, // 0020 CALL R2 2 + 0x80000000, // 0021 RET 0 }) ) ); diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h index aeb9d3b26..7b85512bc 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h @@ -2404,7 +2404,7 @@ be_local_closure(Matter_Device__instantiate_plugins_from_config, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[30]) { /* constants */ + ( &(const bvalue[31]) { /* constants */ /* K0 */ be_nested_str_weak(k2l_num), /* K1 */ be_nested_str_weak(tasmota), /* K2 */ be_nested_str_weak(log), @@ -2419,26 +2419,27 @@ be_local_closure(Matter_Device__instantiate_plugins_from_config, /* name */ /* K11 */ be_nested_str_weak(root), /* K12 */ be_nested_str_weak(), /* K13 */ be_nested_str_weak(Plugin_Aggregator), - /* K14 */ be_nested_str_weak(find), - /* K15 */ be_nested_str_weak(type), - /* K16 */ be_nested_str_weak(MTR_X3A_X20no_X20class_X20name_X2C_X20skipping), - /* K17 */ be_const_int(3), - /* K18 */ be_nested_str_weak(MTR_X3A_X20only_X20one_X20root_X20node_X20allowed), - /* K19 */ be_nested_str_weak(plugins_classes), - /* K20 */ be_nested_str_weak(MTR_X3A_X20unknown_X20class_X20name_X20_X27), - /* K21 */ be_nested_str_weak(_X27_X20skipping), - /* K22 */ be_nested_str_weak(conf_to_log), - /* K23 */ be_nested_str_weak(MTR_X3A_X20Exception), - /* K24 */ be_nested_str_weak(_X7C), - /* K25 */ be_nested_str_weak(stop_iteration), - /* K26 */ be_nested_str_weak(aggregator), - /* K27 */ be_nested_str_weak(publish_result), - /* K28 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Initialized_X22_X3A1_X7D_X7D), - /* K29 */ be_nested_str_weak(Matter), + /* K14 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), + /* K15 */ be_nested_str_weak(find), + /* K16 */ be_nested_str_weak(type), + /* K17 */ be_nested_str_weak(MTR_X3A_X20no_X20class_X20name_X2C_X20skipping), + /* K18 */ be_const_int(3), + /* K19 */ be_nested_str_weak(MTR_X3A_X20only_X20one_X20root_X20node_X20allowed), + /* K20 */ be_nested_str_weak(plugins_classes), + /* K21 */ be_nested_str_weak(MTR_X3A_X20unknown_X20class_X20name_X20_X27), + /* K22 */ be_nested_str_weak(_X27_X20skipping), + /* K23 */ be_nested_str_weak(conf_to_log), + /* K24 */ be_nested_str_weak(MTR_X3A_X20Exception), + /* K25 */ be_nested_str_weak(_X7C), + /* K26 */ be_nested_str_weak(stop_iteration), + /* K27 */ be_nested_str_weak(aggregator), + /* K28 */ be_nested_str_weak(publish_result), + /* K29 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Initialized_X22_X3A1_X7D_X7D), + /* K30 */ be_nested_str_weak(Matter), }), be_str_weak(_instantiate_plugins_from_config), &be_const_str_solidified, - ( &(const binstruction[152]) { /* code */ + ( &(const binstruction[154]) { /* code */ 0x8C080100, // 0000 GETMET R2 R0 K0 0x5C100200, // 0001 MOVE R4 R1 0x7C080400, // 0002 CALL R2 2 @@ -2472,125 +2473,127 @@ be_local_closure(Matter_Device__instantiate_plugins_from_config, /* name */ 0xB8160E00, // 001E GETNGBL R5 K7 0x8C140B0D, // 001F GETMET R5 R5 K13 0x5C1C0000, // 0020 MOVE R7 R0 - 0x5422FEFF, // 0021 LDINT R8 65280 - 0x60240013, // 0022 GETGBL R9 G19 - 0x7C240000, // 0023 CALL R9 0 - 0x7C140800, // 0024 CALL R5 4 - 0x7C0C0400, // 0025 CALL R3 2 - 0x600C0010, // 0026 GETGBL R3 G16 - 0x5C100400, // 0027 MOVE R4 R2 - 0x7C0C0200, // 0028 CALL R3 1 - 0xA802005A, // 0029 EXBLK 0 #0085 - 0x5C100600, // 002A MOVE R4 R3 - 0x7C100000, // 002B CALL R4 0 - 0x1C140909, // 002C EQ R5 R4 K9 - 0x78160000, // 002D JMPF R5 #002F - 0x7001FFFA, // 002E JMP #002A - 0xA8020042, // 002F EXBLK 0 #0073 - 0x60140008, // 0030 GETGBL R5 G8 - 0x5C180800, // 0031 MOVE R6 R4 - 0x7C140200, // 0032 CALL R5 1 - 0x94140205, // 0033 GETIDX R5 R1 R5 - 0x8C180B0E, // 0034 GETMET R6 R5 K14 - 0x5820000F, // 0035 LDCONST R8 K15 - 0x7C180400, // 0036 CALL R6 2 - 0x4C1C0000, // 0037 LDNIL R7 - 0x1C1C0C07, // 0038 EQ R7 R6 R7 - 0x781E0006, // 0039 JMPF R7 #0041 - 0xB81E0200, // 003A GETNGBL R7 K1 - 0x8C1C0F02, // 003B GETMET R7 R7 K2 - 0x58240010, // 003C LDCONST R9 K16 - 0x58280011, // 003D LDCONST R10 K17 - 0x7C1C0600, // 003E CALL R7 3 - 0xA8040001, // 003F EXBLK 1 1 - 0x7001FFE8, // 0040 JMP #002A - 0x1C1C0D0B, // 0041 EQ R7 R6 K11 - 0x781E0006, // 0042 JMPF R7 #004A - 0xB81E0200, // 0043 GETNGBL R7 K1 - 0x8C1C0F02, // 0044 GETMET R7 R7 K2 - 0x58240012, // 0045 LDCONST R9 K18 - 0x58280011, // 0046 LDCONST R10 K17 - 0x7C1C0600, // 0047 CALL R7 3 - 0xA8040001, // 0048 EXBLK 1 1 - 0x7001FFDF, // 0049 JMP #002A - 0x881C0113, // 004A GETMBR R7 R0 K19 - 0x8C1C0F0E, // 004B GETMET R7 R7 K14 - 0x5C240C00, // 004C MOVE R9 R6 - 0x7C1C0400, // 004D CALL R7 2 - 0x4C200000, // 004E LDNIL R8 - 0x1C200E08, // 004F EQ R8 R7 R8 - 0x7822000A, // 0050 JMPF R8 #005C - 0xB8220200, // 0051 GETNGBL R8 K1 - 0x8C201102, // 0052 GETMET R8 R8 K2 - 0x60280008, // 0053 GETGBL R10 G8 - 0x5C2C0C00, // 0054 MOVE R11 R6 - 0x7C280200, // 0055 CALL R10 1 - 0x002A280A, // 0056 ADD R10 K20 R10 - 0x00281515, // 0057 ADD R10 R10 K21 - 0x582C0004, // 0058 LDCONST R11 K4 - 0x7C200600, // 0059 CALL R8 3 - 0xA8040001, // 005A EXBLK 1 1 - 0x7001FFCD, // 005B JMP #002A - 0x5C200E00, // 005C MOVE R8 R7 - 0x5C240000, // 005D MOVE R9 R0 - 0x5C280800, // 005E MOVE R10 R4 - 0x5C2C0A00, // 005F MOVE R11 R5 - 0x7C200600, // 0060 CALL R8 3 - 0x88240105, // 0061 GETMBR R9 R0 K5 - 0x8C241306, // 0062 GETMET R9 R9 K6 - 0x5C2C1000, // 0063 MOVE R11 R8 - 0x7C240400, // 0064 CALL R9 2 - 0xB8260200, // 0065 GETNGBL R9 K1 - 0x8C241302, // 0066 GETMET R9 R9 K2 - 0x602C0018, // 0067 GETGBL R11 G24 - 0x5830000A, // 0068 LDCONST R12 K10 - 0x5C340800, // 0069 MOVE R13 R4 - 0x5C380C00, // 006A MOVE R14 R6 - 0x8C3C0116, // 006B GETMET R15 R0 K22 - 0x5C440A00, // 006C MOVE R17 R5 - 0x7C3C0400, // 006D CALL R15 2 - 0x7C2C0800, // 006E CALL R11 4 - 0x58300004, // 006F LDCONST R12 K4 - 0x7C240600, // 0070 CALL R9 3 - 0xA8040001, // 0071 EXBLK 1 1 - 0x70020010, // 0072 JMP #0084 - 0xAC140002, // 0073 CATCH R5 0 2 - 0x7002000D, // 0074 JMP #0083 - 0xB81E0200, // 0075 GETNGBL R7 K1 - 0x8C1C0F02, // 0076 GETMET R7 R7 K2 - 0x60240008, // 0077 GETGBL R9 G8 - 0x5C280A00, // 0078 MOVE R10 R5 - 0x7C240200, // 0079 CALL R9 1 - 0x00262E09, // 007A ADD R9 K23 R9 - 0x00241318, // 007B ADD R9 R9 K24 - 0x60280008, // 007C GETGBL R10 G8 - 0x5C2C0C00, // 007D MOVE R11 R6 - 0x7C280200, // 007E CALL R10 1 - 0x0024120A, // 007F ADD R9 R9 R10 - 0x58280004, // 0080 LDCONST R10 K4 - 0x7C1C0600, // 0081 CALL R7 3 - 0x70020000, // 0082 JMP #0084 - 0xB0080000, // 0083 RAISE 2 R0 R0 - 0x7001FFA4, // 0084 JMP #002A - 0x580C0019, // 0085 LDCONST R3 K25 - 0xAC0C0200, // 0086 CATCH R3 1 0 - 0xB0080000, // 0087 RAISE 2 R0 R0 - 0xB80E0200, // 0088 GETNGBL R3 K1 - 0x8C0C0702, // 0089 GETMET R3 R3 K2 - 0x60140018, // 008A GETGBL R5 G24 - 0x5818000A, // 008B LDCONST R6 K10 - 0x541EFEFF, // 008C LDINT R7 65280 - 0x5820001A, // 008D LDCONST R8 K26 - 0x5824000C, // 008E LDCONST R9 K12 - 0x7C140800, // 008F CALL R5 4 - 0x58180004, // 0090 LDCONST R6 K4 - 0x7C0C0600, // 0091 CALL R3 3 - 0xB80E0200, // 0092 GETNGBL R3 K1 - 0x8C0C071B, // 0093 GETMET R3 R3 K27 - 0x5814001C, // 0094 LDCONST R5 K28 - 0x5818001D, // 0095 LDCONST R6 K29 - 0x7C0C0600, // 0096 CALL R3 3 - 0x80000000, // 0097 RET 0 + 0xB8220E00, // 0021 GETNGBL R8 K7 + 0x8820110E, // 0022 GETMBR R8 R8 K14 + 0x60240013, // 0023 GETGBL R9 G19 + 0x7C240000, // 0024 CALL R9 0 + 0x7C140800, // 0025 CALL R5 4 + 0x7C0C0400, // 0026 CALL R3 2 + 0x600C0010, // 0027 GETGBL R3 G16 + 0x5C100400, // 0028 MOVE R4 R2 + 0x7C0C0200, // 0029 CALL R3 1 + 0xA802005A, // 002A EXBLK 0 #0086 + 0x5C100600, // 002B MOVE R4 R3 + 0x7C100000, // 002C CALL R4 0 + 0x1C140909, // 002D EQ R5 R4 K9 + 0x78160000, // 002E JMPF R5 #0030 + 0x7001FFFA, // 002F JMP #002B + 0xA8020042, // 0030 EXBLK 0 #0074 + 0x60140008, // 0031 GETGBL R5 G8 + 0x5C180800, // 0032 MOVE R6 R4 + 0x7C140200, // 0033 CALL R5 1 + 0x94140205, // 0034 GETIDX R5 R1 R5 + 0x8C180B0F, // 0035 GETMET R6 R5 K15 + 0x58200010, // 0036 LDCONST R8 K16 + 0x7C180400, // 0037 CALL R6 2 + 0x4C1C0000, // 0038 LDNIL R7 + 0x1C1C0C07, // 0039 EQ R7 R6 R7 + 0x781E0006, // 003A JMPF R7 #0042 + 0xB81E0200, // 003B GETNGBL R7 K1 + 0x8C1C0F02, // 003C GETMET R7 R7 K2 + 0x58240011, // 003D LDCONST R9 K17 + 0x58280012, // 003E LDCONST R10 K18 + 0x7C1C0600, // 003F CALL R7 3 + 0xA8040001, // 0040 EXBLK 1 1 + 0x7001FFE8, // 0041 JMP #002B + 0x1C1C0D0B, // 0042 EQ R7 R6 K11 + 0x781E0006, // 0043 JMPF R7 #004B + 0xB81E0200, // 0044 GETNGBL R7 K1 + 0x8C1C0F02, // 0045 GETMET R7 R7 K2 + 0x58240013, // 0046 LDCONST R9 K19 + 0x58280012, // 0047 LDCONST R10 K18 + 0x7C1C0600, // 0048 CALL R7 3 + 0xA8040001, // 0049 EXBLK 1 1 + 0x7001FFDF, // 004A JMP #002B + 0x881C0114, // 004B GETMBR R7 R0 K20 + 0x8C1C0F0F, // 004C GETMET R7 R7 K15 + 0x5C240C00, // 004D MOVE R9 R6 + 0x7C1C0400, // 004E CALL R7 2 + 0x4C200000, // 004F LDNIL R8 + 0x1C200E08, // 0050 EQ R8 R7 R8 + 0x7822000A, // 0051 JMPF R8 #005D + 0xB8220200, // 0052 GETNGBL R8 K1 + 0x8C201102, // 0053 GETMET R8 R8 K2 + 0x60280008, // 0054 GETGBL R10 G8 + 0x5C2C0C00, // 0055 MOVE R11 R6 + 0x7C280200, // 0056 CALL R10 1 + 0x002A2A0A, // 0057 ADD R10 K21 R10 + 0x00281516, // 0058 ADD R10 R10 K22 + 0x582C0004, // 0059 LDCONST R11 K4 + 0x7C200600, // 005A CALL R8 3 + 0xA8040001, // 005B EXBLK 1 1 + 0x7001FFCD, // 005C JMP #002B + 0x5C200E00, // 005D MOVE R8 R7 + 0x5C240000, // 005E MOVE R9 R0 + 0x5C280800, // 005F MOVE R10 R4 + 0x5C2C0A00, // 0060 MOVE R11 R5 + 0x7C200600, // 0061 CALL R8 3 + 0x88240105, // 0062 GETMBR R9 R0 K5 + 0x8C241306, // 0063 GETMET R9 R9 K6 + 0x5C2C1000, // 0064 MOVE R11 R8 + 0x7C240400, // 0065 CALL R9 2 + 0xB8260200, // 0066 GETNGBL R9 K1 + 0x8C241302, // 0067 GETMET R9 R9 K2 + 0x602C0018, // 0068 GETGBL R11 G24 + 0x5830000A, // 0069 LDCONST R12 K10 + 0x5C340800, // 006A MOVE R13 R4 + 0x5C380C00, // 006B MOVE R14 R6 + 0x8C3C0117, // 006C GETMET R15 R0 K23 + 0x5C440A00, // 006D MOVE R17 R5 + 0x7C3C0400, // 006E CALL R15 2 + 0x7C2C0800, // 006F CALL R11 4 + 0x58300004, // 0070 LDCONST R12 K4 + 0x7C240600, // 0071 CALL R9 3 + 0xA8040001, // 0072 EXBLK 1 1 + 0x70020010, // 0073 JMP #0085 + 0xAC140002, // 0074 CATCH R5 0 2 + 0x7002000D, // 0075 JMP #0084 + 0xB81E0200, // 0076 GETNGBL R7 K1 + 0x8C1C0F02, // 0077 GETMET R7 R7 K2 + 0x60240008, // 0078 GETGBL R9 G8 + 0x5C280A00, // 0079 MOVE R10 R5 + 0x7C240200, // 007A CALL R9 1 + 0x00263009, // 007B ADD R9 K24 R9 + 0x00241319, // 007C ADD R9 R9 K25 + 0x60280008, // 007D GETGBL R10 G8 + 0x5C2C0C00, // 007E MOVE R11 R6 + 0x7C280200, // 007F CALL R10 1 + 0x0024120A, // 0080 ADD R9 R9 R10 + 0x58280004, // 0081 LDCONST R10 K4 + 0x7C1C0600, // 0082 CALL R7 3 + 0x70020000, // 0083 JMP #0085 + 0xB0080000, // 0084 RAISE 2 R0 R0 + 0x7001FFA4, // 0085 JMP #002B + 0x580C001A, // 0086 LDCONST R3 K26 + 0xAC0C0200, // 0087 CATCH R3 1 0 + 0xB0080000, // 0088 RAISE 2 R0 R0 + 0xB80E0200, // 0089 GETNGBL R3 K1 + 0x8C0C0702, // 008A GETMET R3 R3 K2 + 0x60140018, // 008B GETGBL R5 G24 + 0x5818000A, // 008C LDCONST R6 K10 + 0xB81E0E00, // 008D GETNGBL R7 K7 + 0x881C0F0E, // 008E GETMBR R7 R7 K14 + 0x5820001B, // 008F LDCONST R8 K27 + 0x5824000C, // 0090 LDCONST R9 K12 + 0x7C140800, // 0091 CALL R5 4 + 0x58180004, // 0092 LDCONST R6 K4 + 0x7C0C0600, // 0093 CALL R3 3 + 0xB80E0200, // 0094 GETNGBL R3 K1 + 0x8C0C071C, // 0095 GETMET R3 R3 K28 + 0x5814001D, // 0096 LDCONST R5 K29 + 0x5818001E, // 0097 LDCONST R6 K30 + 0x7C0C0600, // 0098 CALL R3 3 + 0x80000000, // 0099 RET 0 }) ) ); @@ -5875,14 +5878,16 @@ be_local_closure(Matter_Device_signal_endpoints_changed, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ + ( &(const bvalue[ 5]) { /* constants */ /* K0 */ be_nested_str_weak(attribute_updated), /* K1 */ be_const_int(0), /* K2 */ be_const_int(3), + /* K3 */ be_nested_str_weak(matter), + /* K4 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), }), be_str_weak(signal_endpoints_changed), &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ + ( &(const binstruction[14]) { /* code */ 0x8C040100, // 0000 GETMET R1 R0 K0 0x580C0001, // 0001 LDCONST R3 K1 0x5412001C, // 0002 LDINT R4 29 @@ -5890,12 +5895,13 @@ be_local_closure(Matter_Device_signal_endpoints_changed, /* name */ 0x50180000, // 0004 LDBOOL R6 0 0 0x7C040A00, // 0005 CALL R1 5 0x8C040100, // 0006 GETMET R1 R0 K0 - 0x540EFEFF, // 0007 LDINT R3 65280 - 0x5412001C, // 0008 LDINT R4 29 - 0x58140002, // 0009 LDCONST R5 K2 - 0x50180000, // 000A LDBOOL R6 0 0 - 0x7C040A00, // 000B CALL R1 5 - 0x80000000, // 000C RET 0 + 0xB80E0600, // 0007 GETNGBL R3 K3 + 0x880C0704, // 0008 GETMBR R3 R3 K4 + 0x5412001C, // 0009 LDINT R4 29 + 0x58140002, // 000A LDCONST R5 K2 + 0x50180000, // 000B LDBOOL R6 0 0 + 0x7C040A00, // 000C CALL R1 5 + 0x80000000, // 000D RET 0 }) ) ); From 6c3f70589a5e69d541c53eb1f9548f63608be50b Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Fri, 19 Jan 2024 23:19:56 +0100 Subject: [PATCH 189/303] Core3 reset GPIOs 16/17 when PSRAM is not used (#20547) * Core3 reset GPIOs 16/17 when PSRAM is not used * clean --- tasmota/tasmota.ino | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 91a2c0b4f..14c9047bc 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -103,7 +103,9 @@ #include "include/tasmota_types.h" #ifdef CONFIG_IDF_TARGET_ESP32 +#include "driver/gpio.h" #include "soc/efuse_reg.h" +#include "bootloader_common.h" #endif /*********************************************************************************************\ @@ -450,22 +452,26 @@ LinkedList backlog; // Command backlog implemented with void setup(void) { #ifdef ESP32 #ifdef CONFIG_IDF_TARGET_ESP32 + #ifdef DISABLE_ESP32_BROWNOUT DisableBrownout(); // Workaround possible weak LDO resulting in brownout detection during Wifi connection #endif // DISABLE_ESP32_BROWNOUT // restore GPIO16/17 if no PSRAM is found - #if ESP_IDF_VERSION_MAJOR < 5 // TODO for esp-idf 5 if (!FoundPSRAM()) { // test if the CPU is not pico +#if (ESP_IDF_VERSION_MAJOR >= 5) + uint32_t pkg_version = bootloader_common_get_chip_ver_pkg(); + if (pkg_version <= 3) { // D0WD, S0WD, D2WD +#else // ESP_IDF_VERSION_MAJOR >= 5 uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG); uint32_t pkg_version = chip_ver & 0x7; if (pkg_version <= 3) { // D0WD, S0WD, D2WD +#endif // ESP_IDF_VERSION_MAJOR >= 5 gpio_reset_pin(GPIO_NUM_16); gpio_reset_pin(GPIO_NUM_17); } } - #endif #endif // CONFIG_IDF_TARGET_ESP32 #endif // ESP32 From 47384e7057db57379c5d30cefde03699ee4a0f16 Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Sat, 20 Jan 2024 11:10:40 +0100 Subject: [PATCH 190/303] [SolaxX1] Improve web presentation (#20535) * [SolaxX1] Improve web presentation * [SolaxX1] delay --- .../tasmota_xnrg_energy/xnrg_12_solaxX1.ino | 130 ++++++++---------- 1 file changed, 61 insertions(+), 69 deletions(-) diff --git a/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino b/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino index f74b59b5a..356c8d65d 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino @@ -108,7 +108,7 @@ struct SOLAXX1_LIVEDATA { float dc2_power = 0; int16_t runMode = 0; uint32_t errorCode = 0; - uint8_t SerialNumber[16] = {0x6e, 0x2f, 0x61}; // "n/a" + uint8_t SerialNumber[16] = {0x00}; } solaxX1; struct SOLAXX1_GLOBALDATA { @@ -127,15 +127,14 @@ struct SOLAXX1_SENDDATA { uint8_t ControlCode[1] = {0x00}; uint8_t FunctionCode[1] = {0x00}; uint8_t DataLength[1] = {0x00}; - uint8_t Payload[16] = {0}; + uint8_t Payload[16] = {0x00}; } solaxX1_SendData; TasmotaSerial *solaxX1Serial; /*********************************************************************************************/ -void solaxX1_RS485Send(void) -{ +void solaxX1_RS485Send(void) { uint8_t message[30]; memcpy(message, solaxX1_SendData.Header, 2); memcpy(message + 2, solaxX1_SendData.Source, 2); @@ -162,8 +161,7 @@ void solaxX1_RS485Send(void) AddLogBuffer(LOG_LEVEL_DEBUG_MORE, message, 9 + solaxX1_SendData.DataLength[0]); } -bool solaxX1_RS485Receive(uint8_t *ReadBuffer) -{ +bool solaxX1_RS485Receive(uint8_t *ReadBuffer) { uint8_t len = 0; while (solaxX1Serial->available() > 0) { ReadBuffer[len++] = (uint8_t)solaxX1Serial->read(); @@ -173,8 +171,7 @@ bool solaxX1_RS485Receive(uint8_t *ReadBuffer) return !(ReadBuffer[len - 1] == lowByte(crc) && ReadBuffer[len - 2] == highByte(crc)); } -uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen) -{ +uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen) { uint8_t i; uint16_t wChkSum = 0; for (i = 0; i < bLen; i++) { @@ -183,8 +180,7 @@ uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen) return wChkSum; } -void solaxX1_ExtractText(uint8_t *DataIn, uint8_t *DataOut, uint8_t Begin, uint8_t End) -{ +void solaxX1_ExtractText(uint8_t *DataIn, uint8_t *DataOut, uint8_t Begin, uint8_t End) { uint8_t i; for (i = Begin; i <= End; i++) { DataOut[i - Begin] = DataIn[i]; @@ -192,8 +188,7 @@ void solaxX1_ExtractText(uint8_t *DataIn, uint8_t *DataOut, uint8_t Begin, uint8 DataOut[End - Begin + 1] = 0; } -void solaxX1_QueryOfflineInverters(void) -{ +void solaxX1_QueryOfflineInverters(void) { solaxX1_SendData.Source[0] = 0x01; solaxX1_SendData.Destination[0] = 0x00; solaxX1_SendData.Destination[1] = 0x00; @@ -203,8 +198,7 @@ void solaxX1_QueryOfflineInverters(void) solaxX1_RS485Send(); } -void solaxX1_SendInverterAddress(void) -{ +void solaxX1_SendInverterAddress(void) { solaxX1_SendData.Source[0] = 0x00; solaxX1_SendData.Destination[0] = 0x00; solaxX1_SendData.Destination[1] = 0x00; @@ -215,8 +209,7 @@ void solaxX1_SendInverterAddress(void) solaxX1_RS485Send(); } -void solaxX1_QueryLiveData(void) -{ +void solaxX1_QueryLiveData(void) { solaxX1_SendData.Source[0] = 0x01; solaxX1_SendData.Destination[0] = 0x00; solaxX1_SendData.Destination[1] = INVERTER_ADDRESS; @@ -226,8 +219,7 @@ void solaxX1_QueryLiveData(void) solaxX1_RS485Send(); } -void solaxX1_QueryIDData(void) -{ +void solaxX1_QueryIDData(void) { solaxX1_SendData.Source[0] = 0x01; solaxX1_SendData.Destination[0] = 0x00; solaxX1_SendData.Destination[1] = INVERTER_ADDRESS; @@ -237,8 +229,7 @@ void solaxX1_QueryIDData(void) solaxX1_RS485Send(); } -void solaxX1_QueryConfigData(void) -{ +void solaxX1_QueryConfigData(void) { solaxX1_SendData.Source[0] = 0x01; solaxX1_SendData.Destination[0] = 0x00; solaxX1_SendData.Destination[1] = INVERTER_ADDRESS; @@ -248,7 +239,7 @@ void solaxX1_QueryConfigData(void) solaxX1_RS485Send(); } -uint8_t solaxX1_ParseErrorCode(uint32_t code){ +uint8_t solaxX1_ParseErrorCode(uint32_t code) { solaxX1_ErrCode.ErrMessage = code; if (code == 0) return 0; if (solaxX1_ErrCode.MainsLostFault) return 1; @@ -264,8 +255,7 @@ uint8_t solaxX1_ParseErrorCode(uint32_t code){ /*********************************************************************************************/ -void solaxX1_250MSecond(void) // Every 250 milliseconds -{ +void solaxX1_250MSecond(void) { // Every 250 milliseconds uint8_t DataRead[80] = {0}; uint8_t TempData[16] = {0}; char TempDataChar[32]; @@ -299,7 +289,8 @@ void solaxX1_250MSecond(void) // Every 250 milliseconds Energy->apparent_power[0] = Energy->active_power[0]; // U*I from inverter is not valid for apparent power; U*I could be lower than active power //temporal = (float)((DataRead[29] << 8) | DataRead[30]) * 0.1f; // Not Used Energy->import_active[0] = ((DataRead[31] << 24) | (DataRead[32] << 16) | (DataRead[33] << 8) | DataRead[34]) * 0.1f; // Energy Total - solaxX1.runtime_total = (DataRead[35] << 24) | (DataRead[36] << 16) | (DataRead[37] << 8) | DataRead[38]; // Work Time Total + uint32_t runtime_total = (DataRead[35] << 24) | (DataRead[36] << 16) | (DataRead[37] << 8) | DataRead[38]; // Work Time Total + if (runtime_total) solaxX1.runtime_total = runtime_total; // Work Time valid solaxX1.runMode = (DataRead[39] << 8) | DataRead[40]; // Work mode //temporal = (float)((DataRead[41] << 8) | DataRead[42]); // Grid voltage fault value 0.1V //temporal = (float)((DataRead[43] << 8) | DataRead[44]); // Gird frequency fault value 0.01Hz @@ -460,12 +451,10 @@ void solaxX1_250MSecond(void) // Every 250 milliseconds } } solaxX1_global.SendRetry_count--; - return; } // end solaxX1_250MSecond -void solaxX1_SnsInit(void) -{ +void solaxX1_SnsInit(void) { AddLog(LOG_LEVEL_INFO, PSTR("SX1: Init - RX-pin: %d, TX-pin: %d, RTS-pin: %d"), Pin(GPIO_SOLAXX1_RX), Pin(GPIO_SOLAXX1_TX), Pin(GPIO_SOLAXX1_RTS)); solaxX1Serial = new TasmotaSerial(Pin(GPIO_SOLAXX1_RX), Pin(GPIO_SOLAXX1_TX), 1); if (solaxX1Serial->begin(SOLAXX1_SPEED)) { @@ -481,15 +470,13 @@ void solaxX1_SnsInit(void) } } -void solaxX1_DrvInit(void) -{ +void solaxX1_DrvInit(void) { if (PinUsed(GPIO_SOLAXX1_RX) && PinUsed(GPIO_SOLAXX1_TX)) { TasmotaGlobal.energy_driver = XNRG_12; } } -bool SolaxX1_cmd(void) -{ +bool SolaxX1_cmd(void) { if (!solaxX1_global.AddressAssigned) { AddLog(LOG_LEVEL_INFO, PSTR("SX1: No inverter registered")); return false; @@ -514,12 +501,11 @@ bool SolaxX1_cmd(void) } #ifdef USE_WEBSERVER -const char HTTP_SNS_solaxX1_Num[] PROGMEM = "{s}" D_SOLAX_X1 " %s{m}
%s  %s{e}"; -const char HTTP_SNS_solaxX1_Str[] PROGMEM = "{s}" D_SOLAX_X1 " %s{m}%s{e}"; +const char HTTP_SNS_solaxX1_Num[] PROGMEM = "{s}" D_SOLAX_X1 " %s{m}%s{m}{m} %s{e}"; +const char HTTP_SNS_solaxX1_Str[] PROGMEM = "{s}" D_SOLAX_X1 " %s{m}%s{e}"; #endif // USE_WEBSERVER -void solaxX1_Show(bool json) -{ +void solaxX1_Show(uint32_t function) { char solar_power[33]; dtostrfd(solaxX1.dc1_power + solaxX1.dc2_power, Settings->flag2.wattage_resolution, solar_power); char pv1_voltage[33]; @@ -539,41 +525,49 @@ void solaxX1_Show(bool json) char status[33]; GetTextIndexed(status, sizeof(status), solaxX1.runMode + 1, kSolaxMode); - if (json) { - ResponseAppend_P(PSTR(",\"" D_JSON_SOLAR_POWER "\":%s,\"" D_JSON_PV1_VOLTAGE "\":%s,\"" D_JSON_PV1_CURRENT "\":%s,\"" D_JSON_PV1_POWER "\":%s"), - solar_power, pv1_voltage, pv1_current, pv1_power); + switch (function) { + case FUNC_JSON_APPEND: + ResponseAppend_P(PSTR(",\"" D_JSON_SOLAR_POWER "\":%s,\"" D_JSON_PV1_VOLTAGE "\":%s,\"" D_JSON_PV1_CURRENT "\":%s,\"" D_JSON_PV1_POWER "\":%s"), + solar_power, pv1_voltage, pv1_current, pv1_power); #ifdef SOLAXX1_PV2 - ResponseAppend_P(PSTR(",\"" D_JSON_PV2_VOLTAGE "\":%s,\"" D_JSON_PV2_CURRENT "\":%s,\"" D_JSON_PV2_POWER "\":%s"), - pv2_voltage, pv2_current, pv2_power); + ResponseAppend_P(PSTR(",\"" D_JSON_PV2_VOLTAGE "\":%s,\"" D_JSON_PV2_CURRENT "\":%s,\"" D_JSON_PV2_POWER "\":%s"), + pv2_voltage, pv2_current, pv2_power); #endif - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%d,\"" D_JSON_RUNTIME "\":%d,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d"), - solaxX1.temperature, solaxX1.runtime_total, status, solaxX1.errorCode); + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%d,\"" D_JSON_RUNTIME "\":%d,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d"), + solaxX1.temperature, solaxX1.runtime_total, status, solaxX1.errorCode); #ifdef USE_DOMOTICZ - // Avoid bad temperature report at beginning of the day (spikes of 1200 celsius degrees) - if (0 == TasmotaGlobal.tele_period && solaxX1.temperature < 100) { DomoticzSensor(DZ_TEMP, solaxX1.temperature); } + // Avoid bad temperature report at beginning of the day (spikes of 1200 celsius degrees) + if (0 == TasmotaGlobal.tele_period && solaxX1.temperature < 100) { DomoticzSensor(DZ_TEMP, solaxX1.temperature); } #endif // USE_DOMOTICZ - + break; #ifdef USE_WEBSERVER - } else { - String table_align = Settings->flag5.gui_table_align?"right":"left"; - WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_SOLAR_POWER, table_align.c_str(), solar_power, D_UNIT_WATT); - WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV1_VOLTAGE, table_align.c_str(), pv1_voltage, D_UNIT_VOLT); - WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV1_CURRENT, table_align.c_str(), pv1_current, D_UNIT_AMPERE); - WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV1_POWER, table_align.c_str(), pv1_power, D_UNIT_WATT); + case FUNC_WEB_COL_SENSOR: { + String table_align = Settings->flag5.gui_table_align?"right":"left"; + static uint32_t LastOnlineTime; + if (solaxX1.runMode != -1) LastOnlineTime = TasmotaGlobal.uptime; + if (TasmotaGlobal.uptime < LastOnlineTime + 300) { // Hide numeric live data, when inverter is offline for more than 5 min + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_SOLAR_POWER, table_align.c_str(), solar_power, D_UNIT_WATT); + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV1_VOLTAGE, table_align.c_str(), pv1_voltage, D_UNIT_VOLT); + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV1_CURRENT, table_align.c_str(), pv1_current, D_UNIT_AMPERE); + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV1_POWER, table_align.c_str(), pv1_power, D_UNIT_WATT); #ifdef SOLAXX1_PV2 - WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV2_VOLTAGE, table_align.c_str(), pv2_voltage, D_UNIT_VOLT); - WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV2_CURRENT, table_align.c_str(), pv2_current, D_UNIT_AMPERE); - WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV2_POWER, table_align.c_str(), pv2_power, D_UNIT_WATT); + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV2_VOLTAGE, table_align.c_str(), pv2_voltage, D_UNIT_VOLT); + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV2_CURRENT, table_align.c_str(), pv2_current, D_UNIT_AMPERE); + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_PV2_POWER, table_align.c_str(), pv2_power, D_UNIT_WATT); #endif - char SXTemperature[16]; - dtostrfd(solaxX1.temperature, Settings->flag2.temperature_resolution, SXTemperature); - WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_TEMPERATURE, table_align.c_str(), SXTemperature, D_UNIT_DEGREE D_UNIT_CELSIUS); - WSContentSend_P(HTTP_SNS_solaxX1_Num, D_UPTIME, table_align.c_str(), String(solaxX1.runtime_total).c_str(), D_UNIT_HOUR); - WSContentSend_P(HTTP_SNS_solaxX1_Str, D_STATUS, table_align.c_str(), status); - char errorCodeString[33]; - WSContentSend_P(HTTP_SNS_solaxX1_Str, D_ERROR, table_align.c_str(), GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError)); - WSContentSend_P(HTTP_SNS_solaxX1_Str, "Inverter SN", table_align.c_str(), solaxX1.SerialNumber); + char SXTemperature[16]; + dtostrfd(solaxX1.temperature, Settings->flag2.temperature_resolution, SXTemperature); + WSContentSend_PD(HTTP_SNS_solaxX1_Num, D_TEMPERATURE, table_align.c_str(), SXTemperature, D_UNIT_DEGREE D_UNIT_CELSIUS); + } + WSContentSend_P(HTTP_SNS_solaxX1_Num, D_UPTIME, table_align.c_str(), String(solaxX1.runtime_total).c_str(), D_UNIT_HOUR); + break; } + case FUNC_WEB_SENSOR: + char errorCodeString[33]; + WSContentSend_P(HTTP_SNS_solaxX1_Str, D_STATUS, status); + WSContentSend_P(HTTP_SNS_solaxX1_Str, D_ERROR, GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError)); + if (solaxX1.SerialNumber[0]) WSContentSend_P(HTTP_SNS_solaxX1_Str, "Inverter SN", solaxX1.SerialNumber); + break; #endif // USE_WEBSERVER } } @@ -582,22 +576,20 @@ void solaxX1_Show(bool json) * Interface \*********************************************************************************************/ -bool Xnrg12(uint32_t function) -{ +bool Xnrg12(uint32_t function) { bool result = false; switch (function) { case FUNC_EVERY_250_MSECOND: solaxX1_250MSecond(); break; - case FUNC_JSON_APPEND: - solaxX1_Show(1); - break; #ifdef USE_WEBSERVER case FUNC_WEB_COL_SENSOR: - solaxX1_Show(0); - break; + case FUNC_WEB_SENSOR: #endif // USE_WEBSERVER + case FUNC_JSON_APPEND: + solaxX1_Show(function); + break; case FUNC_INIT: solaxX1_SnsInit(); break; From 90a4ae0ef5f67d5b537bbfb739b4b675de68b165 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 20 Jan 2024 11:46:51 +0100 Subject: [PATCH 191/303] Update changelogs --- CHANGELOG.md | 14 ++++++++++---- RELEASENOTES.md | 22 +++++++++++++++------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a91a780ab..3c8a74048 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,8 +15,8 @@ All notable changes to this project will be documented in this file. - GUI sensor separators (#20495) - Command ``TimedPower [,ON|OFF|TOGGLE|BLINK]`` executes ``Power [ON|OFF|TOGGLE|BLINK] `` and after executes ``Power [OFF|ON|TOGGLE|BLINK_OFF]`` - Berry solidification of strings longer than 255 bytes (#20529) -- Berry syntax coloring for Notepad++ (by FransO) -- Berry/Zigbee add web hook per device for customized status display +- Berry syntax coloring for Notepad++ by FransO (#20541) +- Berry/Zigbee web hook per device for customized status display (#20542) ### Breaking Changed @@ -24,6 +24,9 @@ All notable changes to this project will be documented in this file. - ESP32 platform update from 2024.01.00 to 2024.01.01 (#20508) - IP stack compatible with new Core3 IPv6 implementation (#20509) - Command ``TimedPower`` from erasing all timers to showing remaining timers +- ESP8266 platform update from 2024.01.00 to 2024.01.01 (#20539) +- ESP8266 Framework (Arduino Core) from v2.7.5 to v2.7.6 (#20539) +- Refactor Pio filesystem download script (#20544) ### Fixed - Scripter memory leak in `>w x` (#20473) @@ -33,8 +36,11 @@ All notable changes to this project will be documented in this file. - Web file upload response on upload error (#20340) - ESP32 shutter exception 6 (divide by zero) on ``ShutterMode 4`` (#20524) - GPIOViewer exception 3 -- Berry assigment to list with negative index -- Matter fix support for Alexa +- Berry assigment to list with negative index (#20537) +- Matter support for Alexa (#20545) +- ESP8266 IPv6 support (#20539) +- ESP32 Audio for Core3, MP3Stream and Shine (#20540) +- ESP32 Core3 reset GPIOs 16/17 when PSRAM is not used (20547) ### Removed - Max number of 30 backlog entries diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 8180640b4..07c154377 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -34,11 +34,11 @@ While fallback or downgrading is common practice it was never supported due to S ## Supported Core versions -This release will be supported from ESP8266/Arduino library Core version **2.7.5** due to reported security and stability issues on previous Core version. This will also support gzipped binaries. +This release will be supported from ESP8266/Arduino library Core version **2.7.6** due to reported security and stability issues on previous Core version. This will also support gzipped binaries. This release will be supported from ESP32/Arduino library Core version **2.0.14**. -Support of ESP8266 Core versions before 2.7.5 and ESP32 Core versions before 2.0.14 have been removed. +Support of ESP8266 Core versions before 2.7.6 and ESP32 Core versions before 2.0.14 have been removed. ## Support of TLS @@ -55,7 +55,7 @@ Easy initial installation of Tasmota can be performed using the [Tasmota WebInst ## Provided Binary Downloads ### ESP8266 or ESP8285 based -The following binary downloads have been compiled with ESP8266/Arduino library core version **2.7.5**. +The following binary downloads have been compiled with ESP8266/Arduino library core version **2.7.6**. - **tasmota.bin** = The Tasmota version with most drivers for 1M+ flash. **RECOMMENDED RELEASE BINARY** - **tasmota-4M.bin** = The Tasmota version with most drivers and filesystem for 4M+ flash. @@ -147,6 +147,8 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Berry `tasmota.webcolor` [#20454](https://github.com/arendst/Tasmota/issues/20454) - Berry `debug.caller` [#20470](https://github.com/arendst/Tasmota/issues/20470) - Berry solidification of strings longer than 255 bytes [#20529](https://github.com/arendst/Tasmota/issues/20529) +- Berry syntax coloring for Notepad++ by FransO [#20541](https://github.com/arendst/Tasmota/issues/20541) +- Berry/Zigbee web hook per device for customized status display [#20542](https://github.com/arendst/Tasmota/issues/20542) - LVGL `lv.str_arr` [#20480](https://github.com/arendst/Tasmota/issues/20480) - LVGL option to add `lv.keyboard` extra widget [#20496](https://github.com/arendst/Tasmota/issues/20496) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) @@ -157,8 +159,8 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Refactoring of Berry `animate` module for WS2812 Leds [#20236](https://github.com/arendst/Tasmota/issues/20236) ### Changed -- ESP8266 platform update from 2023.04.00 to 2024.01.00 [#20467](https://github.com/arendst/Tasmota/issues/20467) -- ESP8266 Framework (Arduino Core) from v2.7.4.9 to v2.7.5 [#20467](https://github.com/arendst/Tasmota/issues/20467) +- ESP8266 platform update from 2023.04.00 to 2024.01.01 [#20539](https://github.com/arendst/Tasmota/issues/20539) +- ESP8266 Framework (Arduino Core) from v2.7.4.9 to v2.7.6 [#20539](https://github.com/arendst/Tasmota/issues/20539) - ESP32 platform update from 2023.11.01 to 2024.01.01 [#20473](https://github.com/arendst/Tasmota/issues/20473) - Renamed button "Consoles" to "Tools" - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` [#20260](https://github.com/arendst/Tasmota/issues/20260) @@ -166,19 +168,25 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Header `Host` is now collected by Webserver [#20446](https://github.com/arendst/Tasmota/issues/20446) - Webcam tweaks [#20451](https://github.com/arendst/Tasmota/issues/20451) - IP stack compatible with new Core3 IPv6 implementation [#20509](https://github.com/arendst/Tasmota/issues/20509) +- Refactor Pio filesystem download script [#20544](https://github.com/arendst/Tasmota/issues/20544) ### Fixed - CVE-2021-36603 Cross Site Scripting (XSS) vulnerability [#12221](https://github.com/arendst/Tasmota/issues/12221) - Syslog server warning caused by lack of field and hostname starting with 'z' [#14689](https://github.com/arendst/Tasmota/issues/14689) - Support for Domoticz floor/room topics. Regression from v12.0.1 [#20299](https://github.com/arendst/Tasmota/issues/20299) -- Scripter memory leak in `>w x` (#20473)[#20473](https://github.com/arendst/Tasmota/issues/20473) -- Zigbee ramdom crash in main page (#20481)[#20473](https://github.com/arendst/Tasmota/issues/20481) +- Scripter memory leak in `>w x` [#20473](https://github.com/arendst/Tasmota/issues/20473) +- Zigbee ramdom crash in main page [#20481](https://github.com/arendst/Tasmota/issues/20481) +- ESP8266 IPv6 support [#20539](https://github.com/arendst/Tasmota/issues/20539) - ESP32 piezo ceramic buzzer doesn't buzz [#20118](https://github.com/arendst/Tasmota/issues/20118) - ESP32 shutter exception 6 (divide by zero) on ``ShutterMode 4`` [#20524](https://github.com/arendst/Tasmota/issues/20524) - ESP32 Zigbee Aqara attributes [#20452](https://github.com/arendst/Tasmota/issues/20452) +- ESP32 Audio for Core3, MP3Stream and Shine [#20540](https://github.com/arendst/Tasmota/issues/20540) +- ESP32 Core3 reset GPIOs 16/17 when PSRAM is not used [#20547](https://github.com/arendst/Tasmota/issues/20547) - LVGL fix type for lv_imgbtn [#20354](https://github.com/arendst/Tasmota/issues/20354) - Berry claiming UART0 if needed [#20324](https://github.com/arendst/Tasmota/issues/20324) +- Berry assigment to list with negative index [#20537](https://github.com/arendst/Tasmota/issues/20537) - Matter Contact sensor was not triggering any update [#20232](https://github.com/arendst/Tasmota/issues/20232) +- Matter support for Alexa [#20545](https://github.com/arendst/Tasmota/issues/20545) ### Removed - Max number of 30 backlog entries From 05014d48cf663ebe8f708a7f6aec13bc4dc643a7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 20 Jan 2024 17:18:03 +0100 Subject: [PATCH 192/303] Refactor backlog from String to char --- tasmota/tasmota.ino | 26 +-- tasmota/tasmota_support/support_command.ino | 204 ++++++++++-------- tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino | 4 +- 3 files changed, 125 insertions(+), 109 deletions(-) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 14c9047bc..9cd999350 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -442,7 +442,7 @@ struct TasmotaGlobal_t { TSettings* Settings = nullptr; #include -LinkedList backlog; // Command backlog implemented with LinkedList +LinkedList backlog; // Command backlog implemented with LinkedList #define BACKLOG_EMPTY (backlog.size() == 0) /*********************************************************************************************\ @@ -788,19 +788,19 @@ void BacklogLoop(void) { if (!BACKLOG_EMPTY && !TasmotaGlobal.backlog_mutex) { TasmotaGlobal.backlog_mutex = true; bool nodelay = false; - bool nodelay_detected = false; - String cmd; do { - cmd = backlog.shift(); - nodelay_detected = !strncasecmp_P(cmd.c_str(), PSTR(D_CMND_NODELAY), strlen(D_CMND_NODELAY)); - if (nodelay_detected) { nodelay = true; } - } while (!BACKLOG_EMPTY && nodelay_detected); - if (!nodelay_detected) { - ExecuteCommand((char*)cmd.c_str(), SRC_BACKLOG); - } - if (nodelay || TasmotaGlobal.backlog_nodelay) { - TasmotaGlobal.backlog_timer = millis(); // Reset backlog_timer which has been set by ExecuteCommand (CommandHandler) - } + char cmd[strlen(backlog.get(0))+1]; // Need to accomodate large commands like Template + BacklogHead(cmd); + if (!strncasecmp_P(cmd, PSTR(D_CMND_NODELAY), strlen(D_CMND_NODELAY))) { + nodelay = true; + } else { + ExecuteCommand(cmd, SRC_BACKLOG); + if (nodelay || TasmotaGlobal.backlog_nodelay) { + TasmotaGlobal.backlog_timer = millis(); // Reset backlog_timer which has been set by ExecuteCommand (CommandHandler) + } + break; + } + } while (!BACKLOG_EMPTY); TasmotaGlobal.backlog_mutex = false; } if (BACKLOG_EMPTY) { diff --git a/tasmota/tasmota_support/support_command.ino b/tasmota/tasmota_support/support_command.ino index 8e6158b00..7c49944c9 100644 --- a/tasmota/tasmota_support/support_command.ino +++ b/tasmota/tasmota_support/support_command.ino @@ -493,82 +493,40 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) { /********************************************************************************************/ -bool SetTimedCmnd(uint32_t time, const char *command) { - uint32_t now = millis(); - // Try to use the same slot if command is already present - for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { - if (TasmotaGlobal.timed_cmnd[i].time != 0) { - if (!strcmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str())) { - // Stored command already present - TasmotaGlobal.timed_cmnd[i].time = now + time; - if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Skip empty slot flag - TasmotaGlobal.timed_cmnd[i].time++; - } - return true; - } - } - } - // Try to find an empty slot and add command - for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { - if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Free slot - TasmotaGlobal.timed_cmnd[i].command = command; - TasmotaGlobal.timed_cmnd[i].time = now + time; - if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Skip empty slot flag - TasmotaGlobal.timed_cmnd[i].time++; - } - return true; - } - } - AddLog(LOG_LEVEL_INFO, PSTR("TIM: No more timer slots left")); - return false; -} - -void ResetTimedCmnd(const char *command) { - for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { - if (TasmotaGlobal.timed_cmnd[i].time != 0) { - if (!strncmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str(), strlen(command))) { - // Stored command starts with command - TasmotaGlobal.timed_cmnd[i].time = 0; - TasmotaGlobal.timed_cmnd[i].command = (const char*) nullptr; // Force deallocation of the String internal memory - } - } +void BacklogAdd(const char* blcommand) { + // Add object at end of list + char* temp = (char*)malloc(strlen(blcommand)+1); + if (temp != nullptr) { + strcpy(temp, blcommand); + backlog.add(temp); } } -void ShowTimedCmnd(const char *command) { - bool found = false; - uint32_t now = millis(); - Response_P(PSTR("{\"%s\":"), XdrvMailbox.command); - for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { - if (TasmotaGlobal.timed_cmnd[i].time != 0) { - if (!strncmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str(), strlen(command))) { - // Stored command starts with command - ResponseAppend_P(PSTR("%s"), (found) ? "," : "["); - found = true; - ResponseAppend_P(PSTR("{\"" D_JSON_REMAINING "\":%d,\"" D_JSON_COMMAND "\":\"%s\"}"), TasmotaGlobal.timed_cmnd[i].time - now, TasmotaGlobal.timed_cmnd[i].command.c_str()); - } - } - } - if (found) { - ResponseAppend_P(PSTR("]}")); - } else { - ResponseAppend_P(PSTR("\"" D_JSON_EMPTY "\"}")); +void BacklogInsert(uint32_t position, const char* blcommand) { + // Add object at position in list + char* temp = (char*)malloc(strlen(blcommand)+1); + if (temp != nullptr) { + strcpy(temp, (char*)blcommand); + backlog.add(position, temp); } } -void LoopTimedCmnd(void) { - uint32_t now = millis(); - for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { - if ((TasmotaGlobal.timed_cmnd[i].time > 0) && (now > TasmotaGlobal.timed_cmnd[i].time)) { - TasmotaGlobal.timed_cmnd[i].time = 0; - String cmd = TasmotaGlobal.timed_cmnd[i].command; - TasmotaGlobal.timed_cmnd[i].command = (const char*) nullptr; // Force deallocation of the String internal memory - ExecuteCommand((char*)cmd.c_str(), SRC_TIMER); - } +void BacklogClear(void) { + // Clear list + while (backlog.size()) { + free(backlog.pop()); } } -/********************************************************************************************/ +char* BacklogHead(char* blcommand) { + // Remove first object from list + char* temp = backlog.shift(); + strcpy(blcommand, temp); + free(temp); + return blcommand; +} + +/*------------------------------------------------------------------------------------------*/ void CmndBacklog(void) { // Backlog command1;command2;.. Execute commands in sequence with a delay in between set with SetOption34 @@ -599,7 +557,7 @@ void CmndBacklog(void) { } // Do not allow command Reset in backlog if ((*blcommand != '\0') && (strncasecmp_P(blcommand, PSTR(D_CMND_RESET), strlen(D_CMND_RESET)) != 0)) { - backlog.add(blcommand); + BacklogAdd(blcommand); } blcommand = strtok(nullptr, ";"); } @@ -608,11 +566,13 @@ void CmndBacklog(void) { TasmotaGlobal.backlog_timer = millis(); } else { bool blflag = BACKLOG_EMPTY; - backlog.clear(); + BacklogClear(); ResponseCmndChar(blflag ? PSTR(D_JSON_EMPTY) : PSTR(D_JSON_ABORTED)); } } +/********************************************************************************************/ + void CmndJson(void) { // Json {"template":{"NAME":"Dummy","GPIO":[320,0,321],"FLAG":0,"BASE":18},"power":2,"HSBColor":"51,97,100","Channel":[100,85,3]} // @@ -648,31 +608,6 @@ void CmndJson(void) { // {"template":"{\"NAME\":\"Dummy\",\"GPIO\":[320,0,321],\"FLAG\":0,\"BASE\":18}","power":2,"HSBColor":"51,97,100","Channel":[100,85,3]} // Output: // template {"NAME":"Dummy","GPIO":[320,0,321],"FLAG":0,"BASE":18};power 2;HSBColor 51,97,100;Channel1 100;Channel2 85;Channel3 3 -/* - String backlog; - for (auto command_key : root) { - const char *command = command_key.getStr(); - JsonParserToken parameters = command_key.getValue(); - if (parameters.isArray()) { - JsonParserArray parameter_arr = parameters.getArray(); - uint32_t index = 1; - for (auto value : parameter_arr) { - backlog = command; - backlog += index++; - backlog += " "; - backlog += value.getStr(); // Channel1 100;Channel2 85;Channel3 3 - ExecuteCommand((char*)backlog.c_str(), SRC_FILE); - } - } else if (parameters.isObject()) { // Should have been escaped -// AddLog(LOG_LEVEL_DEBUG, PSTR("JSN: Object")); - } else { - backlog = command; - backlog += " "; - backlog += parameters.getStr(); // HSBColor 51,97,100 - ExecuteCommand((char*)backlog.c_str(), SRC_FILE); - } - } -*/ String backlog; // We might need a larger string than XdrvMailbox.data_len accomodating decoded arrays for (auto command_key : root) { const char *command = command_key.getStr(); @@ -751,6 +686,85 @@ void CmndPower(void) } } +/********************************************************************************************/ + +bool SetTimedCmnd(uint32_t time, const char *command) { + uint32_t now = millis(); + // Try to use the same slot if command is already present + for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { + if (TasmotaGlobal.timed_cmnd[i].time != 0) { + if (!strcmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str())) { + // Stored command already present + TasmotaGlobal.timed_cmnd[i].time = now + time; + if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Skip empty slot flag + TasmotaGlobal.timed_cmnd[i].time++; + } + return true; + } + } + } + // Try to find an empty slot and add command + for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { + if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Free slot + TasmotaGlobal.timed_cmnd[i].command = command; + TasmotaGlobal.timed_cmnd[i].time = now + time; + if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Skip empty slot flag + TasmotaGlobal.timed_cmnd[i].time++; + } + return true; + } + } + AddLog(LOG_LEVEL_INFO, PSTR("TIM: No more timer slots left")); + return false; +} + +void ResetTimedCmnd(const char *command) { + for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { + if (TasmotaGlobal.timed_cmnd[i].time != 0) { + if (!strncmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str(), strlen(command))) { + // Stored command starts with command + TasmotaGlobal.timed_cmnd[i].time = 0; + TasmotaGlobal.timed_cmnd[i].command = (const char*) nullptr; // Force deallocation of the String internal memory + } + } + } +} + +void ShowTimedCmnd(const char *command) { + bool found = false; + uint32_t now = millis(); + Response_P(PSTR("{\"%s\":"), XdrvMailbox.command); + for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { + if (TasmotaGlobal.timed_cmnd[i].time != 0) { + if (!strncmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str(), strlen(command))) { + // Stored command starts with command + ResponseAppend_P(PSTR("%s"), (found) ? "," : "["); + found = true; + ResponseAppend_P(PSTR("{\"" D_JSON_REMAINING "\":%d,\"" D_JSON_COMMAND "\":\"%s\"}"), TasmotaGlobal.timed_cmnd[i].time - now, TasmotaGlobal.timed_cmnd[i].command.c_str()); + } + } + } + if (found) { + ResponseAppend_P(PSTR("]}")); + } else { + ResponseAppend_P(PSTR("\"" D_JSON_EMPTY "\"}")); + } +} + +void LoopTimedCmnd(void) { + uint32_t now = millis(); + for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { + if ((TasmotaGlobal.timed_cmnd[i].time > 0) && (now > TasmotaGlobal.timed_cmnd[i].time)) { + TasmotaGlobal.timed_cmnd[i].time = 0; + String cmd = TasmotaGlobal.timed_cmnd[i].command; + TasmotaGlobal.timed_cmnd[i].command = (const char*) nullptr; // Force deallocation of the String internal memory + ExecuteCommand((char*)cmd.c_str(), SRC_TIMER); + } + } +} + +/*------------------------------------------------------------------------------------------*/ + void CmndTimedPower(void) { /* Allow timed power changes on a 50ms granularity @@ -801,6 +815,8 @@ void CmndTimedPower(void) { } } +/********************************************************************************************/ + void CmndStatusResponse(uint32_t index) { static String all_status = (const char*) nullptr; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino index 81f6ab23d..550c46463 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino @@ -2070,14 +2070,14 @@ void ExecuteCommandBlock(const char * commands, int len) { //Insert into backlog TasmotaGlobal.backlog_mutex = true; - backlog.add(insertPosition, sCurrentCommand); + BacklogInsert(insertPosition, sCurrentCommand.c_str()); TasmotaGlobal.backlog_mutex = false; insertPosition++; } */ if (sCurrentCommand.length() > 0) { //Insert into backlog - backlog.add(insertPosition, sCurrentCommand); + BacklogInsert(insertPosition, sCurrentCommand.c_str()); insertPosition++; } } From 8223777e4f4195a43787a90956f2d77527d7d3a1 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Sat, 20 Jan 2024 17:29:50 +0100 Subject: [PATCH 193/303] Improve init behavior (#20548) Ensure filesystem init is executed after so80 1. The shutter command will check for proper init and if not done will do it. --- tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino b/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino index 0a617123c..d8d90fdef 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino @@ -2312,6 +2312,11 @@ bool Xdrv27(uint32_t function) XdrvMailbox.index = i; XdrvMailbox.payload = rescue_payload; XdrvMailbox.data_len = rescue_data_len; + if (!ShutterSettings.version) { + ShutterSettingsLoad(0); + ShutterSettings.shutter_startrelay[0] = 1; + ShutterInit(); + } result = DecodeCommand(kShutterCommands, ShutterCommand); } break; From 9608b7513a9f66ed695dd9952bb8d623ab56bce5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 20 Jan 2024 22:45:24 +0100 Subject: [PATCH 194/303] Refactor backlog by removing some str copies --- tasmota/tasmota.ino | 5 +- tasmota/tasmota_support/support_command.ino | 49 +++---------------- tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino | 24 ++++----- 3 files changed, 20 insertions(+), 58 deletions(-) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 9cd999350..4b9643f91 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -789,12 +789,13 @@ void BacklogLoop(void) { TasmotaGlobal.backlog_mutex = true; bool nodelay = false; do { - char cmd[strlen(backlog.get(0))+1]; // Need to accomodate large commands like Template - BacklogHead(cmd); + char* cmd = backlog.shift(); if (!strncasecmp_P(cmd, PSTR(D_CMND_NODELAY), strlen(D_CMND_NODELAY))) { + free(cmd); nodelay = true; } else { ExecuteCommand(cmd, SRC_BACKLOG); + free(cmd); if (nodelay || TasmotaGlobal.backlog_nodelay) { TasmotaGlobal.backlog_timer = millis(); // Reset backlog_timer which has been set by ExecuteCommand (CommandHandler) } diff --git a/tasmota/tasmota_support/support_command.ino b/tasmota/tasmota_support/support_command.ino index 7c49944c9..197568e5a 100644 --- a/tasmota/tasmota_support/support_command.ino +++ b/tasmota/tasmota_support/support_command.ino @@ -491,43 +491,6 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) { TasmotaGlobal.fallback_topic_flag = false; } -/********************************************************************************************/ - -void BacklogAdd(const char* blcommand) { - // Add object at end of list - char* temp = (char*)malloc(strlen(blcommand)+1); - if (temp != nullptr) { - strcpy(temp, blcommand); - backlog.add(temp); - } -} - -void BacklogInsert(uint32_t position, const char* blcommand) { - // Add object at position in list - char* temp = (char*)malloc(strlen(blcommand)+1); - if (temp != nullptr) { - strcpy(temp, (char*)blcommand); - backlog.add(position, temp); - } -} - -void BacklogClear(void) { - // Clear list - while (backlog.size()) { - free(backlog.pop()); - } -} - -char* BacklogHead(char* blcommand) { - // Remove first object from list - char* temp = backlog.shift(); - strcpy(blcommand, temp); - free(temp); - return blcommand; -} - -/*------------------------------------------------------------------------------------------*/ - void CmndBacklog(void) { // Backlog command1;command2;.. Execute commands in sequence with a delay in between set with SetOption34 // Backlog0 command1;command2;.. Execute commands in sequence with no delay @@ -557,7 +520,11 @@ void CmndBacklog(void) { } // Do not allow command Reset in backlog if ((*blcommand != '\0') && (strncasecmp_P(blcommand, PSTR(D_CMND_RESET), strlen(D_CMND_RESET)) != 0)) { - BacklogAdd(blcommand); + char* temp = (char*)malloc(strlen(blcommand)+1); + if (temp != nullptr) { + strcpy(temp, blcommand); + backlog.add(temp); + } } blcommand = strtok(nullptr, ";"); } @@ -566,13 +533,13 @@ void CmndBacklog(void) { TasmotaGlobal.backlog_timer = millis(); } else { bool blflag = BACKLOG_EMPTY; - BacklogClear(); + while (backlog.size()) { + free(backlog.pop()); + } ResponseCmndChar(blflag ? PSTR(D_JSON_EMPTY) : PSTR(D_JSON_ABORTED)); } } -/********************************************************************************************/ - void CmndJson(void) { // Json {"template":{"NAME":"Dummy","GPIO":[320,0,321],"FLAG":0,"BASE":18},"power":2,"HSBColor":"51,97,100","Channel":[100,85,3]} // diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino index 550c46463..1066951be 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino @@ -2062,24 +2062,18 @@ void ExecuteCommandBlock(const char * commands, int len) } //Start to process current command we found //Going to insert the command into backlog - String sCurrentCommand = oneCommand; - sCurrentCommand.trim(); -/* - if (sCurrentCommand.length() > 0 - && !TasmotaGlobal.backlog_mutex) - { + char* blcommand = oneCommand; + Trim(blcommand); + if (strlen(blcommand)) { //Insert into backlog - TasmotaGlobal.backlog_mutex = true; - BacklogInsert(insertPosition, sCurrentCommand.c_str()); - TasmotaGlobal.backlog_mutex = false; - insertPosition++; - } -*/ - if (sCurrentCommand.length() > 0) { - //Insert into backlog - BacklogInsert(insertPosition, sCurrentCommand.c_str()); + char* temp = (char*)malloc(strlen(blcommand)+1); + if (temp != nullptr) { + strcpy(temp, blcommand); + backlog.add(insertPosition, temp); + } insertPosition++; } + } return; } From 76a7ab513163f1512b4eafd7469b056914e036e6 Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Sun, 21 Jan 2024 11:37:04 +0100 Subject: [PATCH 195/303] [Energy] Decoupled `FREQUENCY` and `Energy->type_dc` (#20549) --- tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino | 18 ++++++++---------- .../xdrv_03_esp32_energy.ino | 18 ++++++++---------- .../tasmota_xnrg_energy/xnrg_12_solaxX1.ino | 2 +- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino index a5b0fd3e1..2623a4504 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino @@ -673,7 +673,7 @@ void EnergyEverySecond(void) { Energy->active_power[i] = 0; if (!isnan(Energy->apparent_power[i])) { Energy->apparent_power[i] = 0; } if (!isnan(Energy->reactive_power[i])) { Energy->reactive_power[i] = 0; } - if (!isnan(Energy->frequency[i])) { Energy->frequency[i] = 0; } + if (!isnan(Energy->frequency[i]) && !Energy->type_dc) { Energy->frequency[i] = 0; } if (!isnan(Energy->power_factor[i])) { Energy->power_factor[i] = 0; } if (!isnan(Energy->export_active[i])) { Energy->export_active[i] = 0; } @@ -1345,10 +1345,10 @@ void EnergyShow(bool json) { ResponseAppend_P(PSTR(",\"" D_JSON_POWERFACTOR "\":%s"), EnergyFmt(power_factor, 2)); } - if (!isnan(Energy->frequency[0])) { - ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"), - EnergyFmt(Energy->frequency, Settings->flag2.frequency_resolution, frequency_common)); - } + } + if (!isnan(Energy->frequency[0])) { + ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"), + EnergyFmt(Energy->frequency, Settings->flag2.frequency_resolution, frequency_common)); } if (Energy->voltage_available) { ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s"), @@ -1420,11 +1420,9 @@ void EnergyShow(bool json) { if (Energy->voltage_available) { WSContentSend_PD(HTTP_SNS_VOLTAGE, WebEnergyFmt(Energy->voltage, Settings->flag2.voltage_resolution, voltage_common)); } - if (!Energy->type_dc) { - if (!isnan(Energy->frequency[0])) { - WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"), - WebEnergyFmt(Energy->frequency, Settings->flag2.frequency_resolution, frequency_common)); - } + if (!isnan(Energy->frequency[0])) { + WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"), + WebEnergyFmt(Energy->frequency, Settings->flag2.frequency_resolution, frequency_common)); } if (Energy->current_available) { WSContentSend_PD(HTTP_SNS_CURRENT, WebEnergyFmt(Energy->current, Settings->flag2.current_resolution)); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino index a06c7125f..97010142a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino @@ -893,7 +893,7 @@ void EnergyEverySecond(void) { Energy->active_power[i] = 0; if (!isnan(Energy->apparent_power[i])) { Energy->apparent_power[i] = 0; } if (!isnan(Energy->reactive_power[i])) { Energy->reactive_power[i] = 0; } - if (!isnan(Energy->frequency[i])) { Energy->frequency[i] = 0; } + if (!isnan(Energy->frequency[i]) && !Energy->type_dc) { Energy->frequency[i] = 0; } if (!isnan(Energy->power_factor[i])) { Energy->power_factor[i] = 0; } if (!isnan(Energy->export_active[i])) { Energy->export_active[i] = 0; } @@ -1580,10 +1580,10 @@ void EnergyShow(bool json) { ResponseAppend_P(PSTR(",\"" D_JSON_POWERFACTOR "\":%s"), EnergyFmt(power_factor, 2)); } - if (!isnan(Energy->frequency[0])) { - ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"), - EnergyFmt(Energy->frequency, Settings->flag2.frequency_resolution, frequency_common)); - } + } + if (!isnan(Energy->frequency[0])) { + ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"), + EnergyFmt(Energy->frequency, Settings->flag2.frequency_resolution, frequency_common)); } if (Energy->voltage_available) { ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s"), @@ -1702,11 +1702,9 @@ void EnergyShow(bool json) { if (Energy->voltage_available) { WSContentSend_PD(HTTP_SNS_VOLTAGE, WebEnergyFmt(Energy->voltage, Settings->flag2.voltage_resolution, voltage_common)); } - if (!Energy->type_dc) { - if (!isnan(Energy->frequency[0])) { - WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"), - WebEnergyFmt(Energy->frequency, Settings->flag2.frequency_resolution, frequency_common)); - } + if (!isnan(Energy->frequency[0])) { + WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"), + WebEnergyFmt(Energy->frequency, Settings->flag2.frequency_resolution, frequency_common)); } if (Energy->current_available) { WSContentSend_PD(HTTP_SNS_CURRENT, WebEnergyFmt(Energy->current, Settings->flag2.current_resolution)); diff --git a/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino b/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino index 356c8d65d..ec9ee7cd5 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_12_solaxX1.ino @@ -286,7 +286,6 @@ void solaxX1_250MSecond(void) { // Every 250 milliseconds Energy->voltage[0] = ((DataRead[23] << 8) | DataRead[24]) * 0.1f; // AC Voltage Energy->frequency[0] = ((DataRead[25] << 8) | DataRead[26]) * 0.01f; // AC Frequency Energy->active_power[0] = ((DataRead[27] << 8) | DataRead[28]); // AC Power - Energy->apparent_power[0] = Energy->active_power[0]; // U*I from inverter is not valid for apparent power; U*I could be lower than active power //temporal = (float)((DataRead[29] << 8) | DataRead[30]) * 0.1f; // Not Used Energy->import_active[0] = ((DataRead[31] << 24) | (DataRead[32] << 16) | (DataRead[33] << 8) | DataRead[34]) * 0.1f; // Energy Total uint32_t runtime_total = (DataRead[35] << 24) | (DataRead[36] << 16) | (DataRead[37] << 8) | DataRead[38]; // Work Time Total @@ -473,6 +472,7 @@ void solaxX1_SnsInit(void) { void solaxX1_DrvInit(void) { if (PinUsed(GPIO_SOLAXX1_RX) && PinUsed(GPIO_SOLAXX1_TX)) { TasmotaGlobal.energy_driver = XNRG_12; + Energy->type_dc = true; // Handle like DC, because U*I from inverter is not valid for apparent power; U*I could be lower than active power } } From de91133414cf5f600d8ea1023c16b8fc0ccf8ba6 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 21 Jan 2024 11:42:04 +0100 Subject: [PATCH 196/303] Zigbee ``ZbEmulation`` to selectively exclude some devices from Hue/Alexa emulation (#20552) --- CHANGELOG.md | 1 + tasmota/include/i18n.h | 1 + .../xdrv_23_zigbee_2_devices.ino | 43 ++++++++++++++++- .../xdrv_23_zigbee_2a_devices_impl.ino | 16 ++++++- .../xdrv_23_zigbee_4b_data.ino | 7 ++- .../xdrv_23_zigbee_6_5_hue.ino | 2 +- .../xdrv_23_zigbee_A_impl.ino | 47 +++++++++++++++++-- 7 files changed, 108 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c8a74048..d755c2682 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ All notable changes to this project will be documented in this file. - Berry solidification of strings longer than 255 bytes (#20529) - Berry syntax coloring for Notepad++ by FransO (#20541) - Berry/Zigbee web hook per device for customized status display (#20542) +- Zigbee ``ZbEmulation`` to selectively exclude some devices from Hue/Alexa emulation ### Breaking Changed diff --git a/tasmota/include/i18n.h b/tasmota/include/i18n.h index b7c8a21a0..1437473fa 100644 --- a/tasmota/include/i18n.h +++ b/tasmota/include/i18n.h @@ -700,6 +700,7 @@ #define D_CMND_ZIGBEE_SCAN "Scan" #define D_JSON_ZIGBEE_SCAN "ZbScan" #define D_CMND_ZIGBEE_CIE "CIE" +#define D_CMND_ZIGBEE_EMULATION "Emulation" #define D_CMND_ZIGBEE_ENROLL "Enroll" #define D_CMND_ZIGBEE_LOAD "Load" #define D_CMND_ZIGBEE_LOADDUMP "LoadDump" diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2_devices.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2_devices.ino index 548b4fe9b..5d9b315dd 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2_devices.ino @@ -109,6 +109,19 @@ Output: 00:00:00.231 >>>: v16=65535 out=63000 <> hex=0xFF */ +/*********************************************************************************************\ + * + * Flag to no advertize for Hue (Alexa) or Matter + * +\*********************************************************************************************/ + +enum class Z_no_advertize : uint8_t { + Z_no_ad_default = 0X00, // advertize on all + Z_no_ad_hue = 0x01, // no-advertize on Hue + Z_no_ad_matter = 0x02, // no-advertize on Matter + Z_no_ad_all = 0xFF, // no-advertize on all +}; + enum class Z_Data_Type : uint8_t { Z_Unknown = 0x00, Z_Light = 1, // Lights 1-5 channels @@ -961,7 +974,9 @@ public: uint32_t batt_last_probed; // Time when the device was last probed for batteyr values uint8_t lqi; // lqi from last message, 0xFF means unknown uint8_t batt_percent; // battery percentage (0..100), 0xFF means unknwon - uint16_t reserved_for_alignment; + Z_no_advertize no_advertize; // no advertize for Hue or Matter + uint8_t reserved_for_alignment; + // Debounce informmation when receiving commands // If we receive the same ZCL transaction number from the same device and the same endpoint within 300ms // then discard the second packet @@ -989,7 +1004,8 @@ public: batt_last_probed(0), lqi(0xFF), batt_percent(0xFF), - reserved_for_alignment(0xFFFF), + no_advertize(Z_no_advertize::Z_no_ad_default), + reserved_for_alignment(0xFF), debounce_endpoint(0), debounce_transact(0) { }; @@ -1008,6 +1024,28 @@ public: inline bool validLastSeen(void) const { return 0x0 != last_seen; } inline bool validBattLastSeen(void) const { return (0x0 != batt_last_seen) && (batt_last_seen < 0xFFFFFFF0); } + inline bool isAdvertizeNone(void) const { return (no_advertize == Z_no_advertize::Z_no_ad_all); } // never advertize in bridge mode + inline bool isAdvertizeHue(void) const { return !((uint8_t)no_advertize & (uint8_t)Z_no_advertize::Z_no_ad_hue) ; } // advertize to Alexa/Hue (if a bulb) + inline bool isAdvertizeMatter(void) const { return !((uint8_t)no_advertize & (uint8_t)Z_no_advertize::Z_no_ad_matter) ; } // advertize to Matter (type has to be defined in Matter) + inline bool isAdvertizeAll(void) const { return (no_advertize == Z_no_advertize::Z_no_ad_default) ; } // advertize to all possible (default) + + inline void setAdvertizeNone(void) { no_advertize = Z_no_advertize::Z_no_ad_all; } + inline void setAdvertizeAll(void) { no_advertize = Z_no_advertize::Z_no_ad_default; } + inline void setAdvertizeHue(bool adv) { + if (adv) { + no_advertize = (Z_no_advertize)((uint8_t)no_advertize & ~(uint8_t)Z_no_advertize::Z_no_ad_hue); + } else { + no_advertize = (Z_no_advertize)((uint8_t)no_advertize | (uint8_t)Z_no_advertize::Z_no_ad_hue); + } + } + inline void setAdvertizeMatter(bool adv) { + if (adv) { + no_advertize = (Z_no_advertize)((uint8_t)no_advertize & ~(uint8_t)Z_no_advertize::Z_no_ad_matter); + } else { + no_advertize = (Z_no_advertize)((uint8_t)no_advertize | (uint8_t)Z_no_advertize::Z_no_ad_matter); + } + } + inline void setReachable(bool _reachable) { reachable = _reachable; } inline bool getReachable(void) const { return reachable; } inline bool getPower(uint8_t ep = 0) const; @@ -1053,6 +1091,7 @@ public: void jsonAddModelManuf(Z_attribute_list & attr_list) const; void jsonAddEndpoints(Z_attribute_list & attr_list) const; void jsonAddConfig(Z_attribute_list & attr_list) const; + void jsonAddEmulation(Z_attribute_list & attr_list) const; void jsonAddDataAttributes(Z_attribute_list & attr_list) const; void jsonAddDeviceAttributes(Z_attribute_list & attr_list) const; void jsonDumpSingleDevice(Z_attribute_list & attr_list, uint32_t dump_mode, bool add_name) const; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino index a8cfdbbc6..549af03fc 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_2a_devices_impl.ino @@ -814,6 +814,11 @@ void Z_Device::jsonAddConfig(Z_attribute_list & attr_list) const { } attr_list.addAttributePMEM(PSTR("Config")).setStrRaw(arr_data.toString().c_str()); } +// Add "HueEmulation":false, "Matter":false +void Z_Device::jsonAddEmulation(Z_attribute_list & attr_list) const { + if (!isAdvertizeHue()) { attr_list.addAttributePMEM(PSTR("HueEmulation")).setBool(false); } + if (!isAdvertizeMatter()) { attr_list.addAttributePMEM(PSTR("Matter")).setBool(false); } +} // Add All data attributes void Z_Device::jsonAddDataAttributes(Z_attribute_list & attr_list) const { // show internal data - mostly last known values @@ -824,7 +829,7 @@ void Z_Device::jsonAddDataAttributes(Z_attribute_list & attr_list) const { } } } -// Add "BatteryPercentage", "LastSeen", "LastSeenEpoch", "LinkQuality" +// Add "BatteryPercentage", "LastSeen", "LastSeenEpoch", "LinkQuality", "HueEmulation" (opt) and "Matter" (opt) void Z_Device::jsonAddDeviceAttributes(Z_attribute_list & attr_list) const { attr_list.addAttributePMEM(PSTR("Reachable")).setBool(getReachable()); if (validBatteryPercent()) { attr_list.addAttributePMEM(PSTR("BatteryPercentage")).setUInt(batt_percent); } @@ -879,6 +884,7 @@ void Z_Device::jsonDumpSingleDevice(Z_attribute_list & attr_list, uint32_t dump_ jsonAddModelManuf(attr_list); jsonAddEndpoints(attr_list); jsonAddConfig(attr_list); + jsonAddEmulation(attr_list); } if (dump_mode >= 3) { jsonAddDataAttributes(attr_list); @@ -928,7 +934,7 @@ String Z_Devices::dumpDevice(uint32_t dump_mode, const Z_Device & device) const // 0 : Ok // <0 : Error // -// Ex: {"Device":"0x5ADF","Name":"IKEA_Light","IEEEAddr":"0x90FD9FFFFE03B051","ModelId":"TRADFRI bulb E27 WS opal 980lm","Manufacturer":"IKEA of Sweden","Endpoints":["0x01","0xF2"]} +// Ex: {"Device":"0x5ADF","Name":"IKEA_Light","IEEEAddr":"0x90FD9FFFFE03B051","ModelId":"TRADFRI bulb E27 WS opal 980lm","Manufacturer":"IKEA of Sweden","Endpoints":["0x01","0xF2"],"HueEmulation":false} int32_t Z_Devices::deviceRestore(JsonParserObject json) { // params @@ -1007,6 +1013,12 @@ int32_t Z_Devices::deviceRestore(JsonParserObject json) { } } + // read "HueEmulation" and "Matter" + bool hue_emulation = json.getBool(PSTR("HueEmulation"), false); + bool matter = json.getBool(PSTR("Matter"), false); + device.setAdvertizeHue(hue_emulation); + device.setAdvertizeMatter(matter); + return 0; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_4b_data.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_4b_data.ino index 62f2d7557..d50c3e623 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_4b_data.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_4b_data.ino @@ -50,6 +50,9 @@ int32_t hydrateDeviceWideData(class Z_Device & device, const SBuffer & buf, size if (segment_len >= 10) { device.batt_last_seen = buf.get32(start+7); } + if (segment_len >= 11) { + device.no_advertize = (Z_no_advertize)buf.get8(start+11); + } return segment_len + 1; } @@ -121,12 +124,14 @@ SBuffer hibernateDeviceData(const struct Z_Device & device) { buf.add16(device.shortaddr); // device wide data - buf.add8(10); // 10 bytes + buf.add8(11); // 10 bytes buf.add32(device.last_seen); buf.add8(device.lqi); buf.add8(device.batt_percent); // now storing batt_last_seen buf.add32(device.batt_last_seen); + // now storing no_advertize + buf.add8((uint8_t)device.no_advertize); for (const auto & data_elt : device.data) { size_t item_len = data_elt.DataTypeToLength(data_elt.getType()); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_5_hue.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_5_hue.ino index 58baf9dce..1d60c1111 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_5_hue.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_6_5_hue.ino @@ -144,7 +144,7 @@ void ZigbeeCheckHue(String & response, bool * appending) { uint8_t ep = device.endpoints[i]; if (i > 0 && ep == 0) { break; } int8_t bulbtype = device.getHueBulbtype(ep); - if (bulbtype >= 0) { + if (bulbtype >= 0 && device.isAdvertizeHue()) { // this bulb is advertized if (*appending) { response += ","; } response += "\""; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino index 4f96e003c..c0dfc2306 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_A_impl.ino @@ -42,6 +42,7 @@ const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix D_CMND_ZIGBEE_LIGHT "|" D_CMND_ZIGBEE_OCCUPANCY "|" D_CMND_ZIGBEE_RESTORE "|" D_CMND_ZIGBEE_BIND_STATE "|" D_CMND_ZIGBEE_MAP "|" D_CMND_ZIGBEE_LEAVE "|" D_CMND_ZIGBEE_CONFIG "|" D_CMND_ZIGBEE_DATA "|" D_CMND_ZIGBEE_SCAN "|" D_CMND_ZIGBEE_ENROLL "|" D_CMND_ZIGBEE_CIE "|" + D_CMND_ZIGBEE_EMULATION "|" D_CMND_ZIGBEE_LOAD "|" D_CMND_ZIGBEE_UNLOAD "|" D_CMND_ZIGBEE_LOADDUMP #ifdef ZIGBEE_DOC "|" D_CMND_ZIGBEE_ATTRDUMP @@ -67,7 +68,8 @@ void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZbLight, &CmndZbOccupancy, &CmndZbRestore, &CmndZbBindState, &CmndZbMap, &CmndZbLeave, &CmndZbConfig, &CmndZbData, &CmndZbScan, - &CmndZbenroll, &CmndZbcie, + &CmndZbenroll, &CmndZbCIE, + &CmndZbEmulation, &CmndZbLoad, &CmndZbUnload, &CmndZbLoadDump, #ifdef ZIGBEE_DOC &CmndZbAttrDump, @@ -1518,7 +1520,7 @@ void CmndZbenroll(void) { } } -void CmndZbcie(void) { +void CmndZbCIE(void) { if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } if ((XdrvMailbox.data_len) && (ArgC() > 1)) { // Process parameter entry @@ -1536,6 +1538,38 @@ void CmndZbcie(void) { } } +void CmndZbEmulation(void) { + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + + if ((XdrvMailbox.data_len) && (ArgC() > 1)) { // Process parameter entry + char argument[XdrvMailbox.data_len]; + Z_Device & device = zigbee_devices.parseDeviceFromName(ArgV(argument, 1), nullptr, nullptr, XdrvMailbox.payload); + char * arg_v = ArgV(argument, 2); + int emulation = atoi(arg_v); + if (strlen(arg_v) == 0) { emulation = 255; } + + if (!device.valid()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; } + + if (emulation == 0) { + device.setAdvertizeNone(); + } else if (emulation == 255) { + device.setAdvertizeAll(); + } else if (emulation == 1) { + device.setAdvertizeHue(true); + } else if (emulation == 2) { + device.setAdvertizeMatter(true); + } else if (emulation == -1) { + device.setAdvertizeHue(false); + } else if (emulation == -2) { + device.setAdvertizeMatter(false); + } + + ResponseCmndDone(); + } else { + ResponseCmndError(); + } +} + // Restore a device configuration previously exported via `ZbStatus2`` // Format: // Either the entire `ZbStatus3` export, or an array or just the device configuration. @@ -1755,20 +1789,27 @@ void ZigbeePermitJoinUpdate(void) { // // Command `ZbStatus` // +// Options: +// 0. `ZbStatus0` - Show information about coordinator `{"ZbStatus0":{"Device":"0x0000","IEEEAddr":"0x00124B0026B684E4","TotalDevices":19}}` +// 1.a. `ZbStatus` - Show all devices shortaddr and names `{"ZbStatus1":[{"Device":"0x868E","Name":"Room"}...]}` +// 1.b. `ZbStatus Room` - Show single device shortaddr and name `{"ZbStatus1":[{"Device":"0x868E","Name":"Room"}]}` +// 2. `ZbStatus2 Room` - Show detailed information of device `{"ZbStatus2":[{"Device":"0x868E","Name":"Room","IEEEAddr":"0x90FD9FFFFE03B051","ModelId":"TRADFRI bulb E27 WS opal 980lm","Manufacturer":"IKEA of Sweden","Endpoints":[1,242],"Config":["L01.2","O01"]}]}` void CmndZbStatus(void) { if (ZigbeeSerial) { if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } String dump; - if (0 == XdrvMailbox.index) { + if (0 == XdrvMailbox.index) { // Case 0 dump = zigbee_devices.dumpCoordinator(); } else { Z_Device & device = zigbee_devices.parseDeviceFromName(XdrvMailbox.data, nullptr, nullptr, XdrvMailbox.payload); if (XdrvMailbox.data_len > 0) { if (!device.valid()) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; } + // case 1.b and 2. dump = zigbee_devices.dumpDevice(XdrvMailbox.index, device); } else { if (XdrvMailbox.index >= 2) { ResponseCmndChar_P(PSTR(D_ZIGBEE_UNKNOWN_DEVICE)); return; } + // case 1.a dump = zigbee_devices.dumpDevice(XdrvMailbox.index, device_unk); } } From 4a4fe27cee9301cc7c99f311640a69873f62e023 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 21 Jan 2024 13:16:05 +0100 Subject: [PATCH 197/303] fix esp8266 fs download and extract (#20554) --- pio-tools/custom_target.py | 62 ++++++++------------------------------ 1 file changed, 13 insertions(+), 49 deletions(-) diff --git a/pio-tools/custom_target.py b/pio-tools/custom_target.py index d1c133bcb..0ec9bd105 100644 --- a/pio-tools/custom_target.py +++ b/pio-tools/custom_target.py @@ -27,7 +27,6 @@ mcu = board.get("build.mcu", "esp32") class FSType(Enum): - SPIFFS="spiffs" LITTLEFS="littlefs" FATFS="fatfs" @@ -44,26 +43,15 @@ class FSInfo: def get_extract_cmd(self, input_file, output_dir): raise NotImplementedError() -class LittleFSInfo(FSInfo): +class FS_Info(FSInfo): def __init__(self, start, length, page_size, block_size): self.tool = env["MKFSTOOL"] self.tool = join(platform.get_package_dir("tool-mklittlefs"), self.tool) super().__init__(FSType.LITTLEFS, start, length, page_size, block_size) def __repr__(self): - return f"{self.fs_type} Start {hex(self.start)} Len {self.length} Page size {self.page_size} Block size {self.block_size}" + return f"{self.fs_type} Start {hex(self.start)} Len {hex(self.length)} Page size {hex(self.page_size)} Block size {hex(self.block_size)}" def get_extract_cmd(self, input_file, output_dir): - return [self.tool, "-b", str(self.block_size), "-s", str(self.length), "-p", str(self.page_size), "--unpack", output_dir, input_file] - - -class SPIFFSInfo(FSInfo): - def __init__(self, start, length, page_size, block_size): - self.tool = env["MKFSTOOL"] - self.tool = join(platform.get_package_dir("tool-mklittlefs"), self.tool) - super().__init__(FSType.SPIFFS, start, length, page_size, block_size) - def __repr__(self): - return f"{self.fs_type} Start {hex(self.start)} Len {self.length} Page size {self.page_size} Block size {self.block_size}" - def get_extract_cmd(self, input_file, output_dir): - return f'"{self.tool}" -b {self.block_size} -p {self.page_size} --unpack "{output_dir}" "{input_file}"' + return f'"{self.tool}" -b {self.block_size} -s {self.length} -p {self.page_size} --unpack "{output_dir}" "{input_file}"' # SPIFFS helpers copied from ESP32, https://github.com/platformio/platform-espressif32/blob/develop/builder/main.py # Copyright 2014-present PlatformIO @@ -89,8 +77,6 @@ def _parse_size(value): def _parse_ld_sizes(ldscript_path): assert ldscript_path result = {} - # get flash size from board's manifest - result['flash_size'] = int(env.BoardConfig().get("upload.maximum_size", 0)) # get flash size from LD script path match = re.search(r"\.flash\.(\d+[mk]).*\.ld", ldscript_path) if match: @@ -144,18 +130,6 @@ def esp8266_fetch_fs_size(env): env[k] = _value -def esp8266_get_esptoolpy_reset_flags(resetmethod): - # no dtr, no_sync - resets = ("no_reset_no_sync", "soft_reset") - if resetmethod == "nodemcu": - # dtr - resets = ("default_reset", "hard_reset") - elif resetmethod == "ck": - # no dtr - resets = ("no_reset", "soft_reset") - - return ["--before", resets[0], "--after", resets[1]] - ## Script interface functions def parse_partition_table(content): entries = [e for e in content.split(b'\xaaP') if len(e) > 0] @@ -168,10 +142,10 @@ def parse_partition_table(content): #print("type:",hex(type)) #print("address:",hex(offset)) #print("size:",hex(size)) - env["SPIFFS_START"] = offset - env["SPIFFS_SIZE"] = size - env["SPIFFS_PAGE"] = int("0x100", 16) - env["SPIFFS_BLOCK"] = int("0x1000", 16) + env["FS_START"] = offset + env["FS_SIZE"] = size + env["FS_PAGE"] = int("0x100", 16) + env["FS_BLOCK"] = int("0x1000", 16) def get_partition_table(): esptoolpy = join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py") @@ -193,8 +167,6 @@ def get_partition_table(): fs_file ] esptoolpy_cmd = [env["PYTHONEXE"], esptoolpy] + esptoolpy_flags - #print("Executing flash download command to read partition table.") - #print(esptoolpy_cmd) try: returncode = subprocess.call(esptoolpy_cmd, shell=False) except subprocess.CalledProcessError as exc: @@ -207,10 +179,8 @@ def get_fs_type_start_and_length(): platform = env["PIOPLATFORM"] if platform == "espressif32": print(f"Retrieving filesystem info for {mcu}.") - #print("Partition file: " + str(env.subst("$PARTITIONS_TABLE_CSV"))) - # esp32_fetch_spiffs_size(env) get_partition_table() - return SPIFFSInfo(env["SPIFFS_START"], env["SPIFFS_SIZE"], env["SPIFFS_PAGE"], env["SPIFFS_BLOCK"]) + return FS_Info(env["FS_START"], env["FS_SIZE"], env["FS_PAGE"], env["FS_BLOCK"]) elif platform == "espressif8266": print("Retrieving filesystem info for ESP8266.") filesystem = board.get("build.filesystem", "littlefs") @@ -219,13 +189,13 @@ def get_fs_type_start_and_length(): env.Exit(1) # fetching sizes is the same for all filesystems esp8266_fetch_fs_size(env) - print("FS_START: " + hex(env["FS_START"])) - print("FS_END: " + hex(env["FS_END"])) - print("FS_PAGE: " + hex(env["FS_PAGE"])) - print("FS_BLOCK: " + hex(env["FS_BLOCK"])) + #print("FS_START: " + hex(env["FS_START"])) + #print("FS_SIZE: " + hex(env["FS_END"] - env["FS_START"])) + #print("FS_PAGE: " + hex(env["FS_PAGE"])) + #print("FS_BLOCK: " + hex(env["FS_BLOCK"])) if filesystem == "littlefs": print("Recognized LittleFS filesystem.") - return LittleFSInfo(env["FS_START"], env["FS_END"] - env["FS_START"], env["FS_PAGE"], env["FS_BLOCK"]) + return FS_Info(env["FS_START"], env["FS_END"] - env["FS_START"], env["FS_PAGE"], env["FS_BLOCK"]) else: print("Unrecongized configuration.") pass @@ -252,10 +222,8 @@ def download_fs(fs_info: FSInfo): ] esptoolpy_cmd = [env["PYTHONEXE"], esptoolpy] + esptoolpy_flags print("Download filesystem image") - #print(esptoolpy_cmd) try: returncode = subprocess.call(esptoolpy_cmd, shell=False) - # print("Launched download of filesystem binary.") return (True, fs_file) except subprocess.CalledProcessError as exc: print("Downloading failed with " + str(exc)) @@ -265,7 +233,6 @@ def unpack_fs(fs_info: FSInfo, downloaded_file: str): # by writing custom_unpack_dir = some_dir in the platformio.ini, one can # control the unpack directory unpack_dir = env.GetProjectOption("custom_unpack_dir", "unpacked_fs") - #unpack_dir = "unpacked_fs" if not os.path.exists(downloaded_file): print(f"ERROR: {downloaded_file} with filesystem not found, maybe download failed due to download_speed setting being too high.") assert(0) @@ -279,7 +246,6 @@ def unpack_fs(fs_info: FSInfo, downloaded_file: str): cmd = fs_info.get_extract_cmd(downloaded_file, unpack_dir) print("Unpack files from filesystem image") - #print("Extraction command: " + str(cmd)) try: returncode = subprocess.call(cmd, shell=True) return (True, unpack_dir) @@ -294,10 +260,8 @@ def display_fs(extracted_dir): print("Extracted " + str(file_count) + " file(s) from filesystem.") def command_download_fs(*args, **kwargs): - get_partition_table() info = get_fs_type_start_and_length() download_ok, downloaded_file = download_fs(info) - # print("Download was okay: " + str(download_ok) + ". File at: "+ str(downloaded_file)) # this is wrong unpack_ok, unpacked_dir = unpack_fs(info, downloaded_file) if unpack_ok is True: display_fs(unpacked_dir) From 95f76d623f17d67c55382a78bc5fb4a84ab41ba1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 21 Jan 2024 14:29:44 +0100 Subject: [PATCH 198/303] Changed command ``TimedPower`` refactored from String to LList --- CHANGELOG.md | 3 +- RELEASENOTES.md | 1 + tasmota/include/tasmota.h | 1 - tasmota/tasmota.ino | 7 -- tasmota/tasmota_support/support_command.ino | 88 +++++++++------------ 5 files changed, 40 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d755c2682..581a84b33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ All notable changes to this project will be documented in this file. - Berry solidification of strings longer than 255 bytes (#20529) - Berry syntax coloring for Notepad++ by FransO (#20541) - Berry/Zigbee web hook per device for customized status display (#20542) -- Zigbee ``ZbEmulation`` to selectively exclude some devices from Hue/Alexa emulation +- Zigbee ``ZbEmulation`` to selectively exclude some devices from Hue/Alexa emulation (#20552) ### Breaking Changed @@ -28,6 +28,7 @@ All notable changes to this project will be documented in this file. - ESP8266 platform update from 2024.01.00 to 2024.01.01 (#20539) - ESP8266 Framework (Arduino Core) from v2.7.5 to v2.7.6 (#20539) - Refactor Pio filesystem download script (#20544) +- Command ``TimedPower`` refactored from String to LList ### Fixed - Scripter memory leak in `>w x` (#20473) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 07c154377..978956b2f 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -149,6 +149,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Berry solidification of strings longer than 255 bytes [#20529](https://github.com/arendst/Tasmota/issues/20529) - Berry syntax coloring for Notepad++ by FransO [#20541](https://github.com/arendst/Tasmota/issues/20541) - Berry/Zigbee web hook per device for customized status display [#20542](https://github.com/arendst/Tasmota/issues/20542) +- Zigbee ``ZbEmulation`` to selectively exclude some devices from Hue/Alexa emulation [#20552](https://github.com/arendst/Tasmota/issues/20552) - LVGL `lv.str_arr` [#20480](https://github.com/arendst/Tasmota/issues/20480) - LVGL option to add `lv.keyboard` extra widget [#20496](https://github.com/arendst/Tasmota/issues/20496) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) diff --git a/tasmota/include/tasmota.h b/tasmota/include/tasmota.h index 3685fbc7e..bb23f5c1e 100644 --- a/tasmota/include/tasmota.h +++ b/tasmota/include/tasmota.h @@ -221,7 +221,6 @@ const uint16_t MAX_LOGSZ = 700; // Max number of characters in log l const uint8_t SENSOR_MAX_MISS = 5; // Max number of missed sensor reads before deciding it's offline const uint32_t MIN_BACKLOG_DELAY = 200; // Minimal backlog delay in mSeconds -const uint8_t MAX_TIMED_CMND = 16; // Max number of timed commands const uint32_t SOFT_BAUDRATE = 9600; // Default software serial baudrate const uint32_t APP_BAUDRATE = 115200; // Default serial baudrate diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 4b9643f91..16f6c3a1e 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -294,11 +294,6 @@ HardwareSerial TasConsole = Serial; // Only serial interface char EmptyStr[1] = { 0 }; // Provide a pointer destination to an empty char string -typedef struct { - uint32_t time; - String command; -} tTimedCmnd; - struct TasmotaGlobal_t { uint32_t global_update; // Timestamp of last global temperature and humidity update uint32_t baudrate; // Current Serial baudrate @@ -413,8 +408,6 @@ struct TasmotaGlobal_t { uint8_t pwm_dimmer_led_bri; // Adjusted brightness LED level #endif // USE_PWM_DIMMER - tTimedCmnd timed_cmnd[MAX_TIMED_CMND]; // Timed command buffer - #ifdef MQTT_DATA_STRING String mqtt_data; // Buffer filled by Response functions #else diff --git a/tasmota/tasmota_support/support_command.ino b/tasmota/tasmota_support/support_command.ino index 197568e5a..d763a4130 100644 --- a/tasmota/tasmota_support/support_command.ino +++ b/tasmota/tasmota_support/support_command.ino @@ -655,44 +655,38 @@ void CmndPower(void) /********************************************************************************************/ +typedef struct { + uint32_t time; + char* command; +} tTimedCmnd; +LList timed_cmnd; // Timed command buffer + bool SetTimedCmnd(uint32_t time, const char *command) { - uint32_t now = millis(); - // Try to use the same slot if command is already present - for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { - if (TasmotaGlobal.timed_cmnd[i].time != 0) { - if (!strcmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str())) { - // Stored command already present - TasmotaGlobal.timed_cmnd[i].time = now + time; - if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Skip empty slot flag - TasmotaGlobal.timed_cmnd[i].time++; - } - return true; - } + // Remove command if present + for (auto &elem : timed_cmnd) { + if (strcmp(command, elem.command) == 0) { // Equal + free(elem.command); + timed_cmnd.remove(&elem); + break; } } - // Try to find an empty slot and add command - for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { - if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Free slot - TasmotaGlobal.timed_cmnd[i].command = command; - TasmotaGlobal.timed_cmnd[i].time = now + time; - if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Skip empty slot flag - TasmotaGlobal.timed_cmnd[i].time++; - } - return true; - } + // Add command + char* cmnd = (char*)malloc(strlen(command) +1); + if (cmnd) { + strcpy(cmnd, command); + tTimedCmnd &elem = timed_cmnd.addToLast(); + elem.time = millis() + time; + elem.command = cmnd; + return true; } - AddLog(LOG_LEVEL_INFO, PSTR("TIM: No more timer slots left")); return false; } void ResetTimedCmnd(const char *command) { - for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { - if (TasmotaGlobal.timed_cmnd[i].time != 0) { - if (!strncmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str(), strlen(command))) { - // Stored command starts with command - TasmotaGlobal.timed_cmnd[i].time = 0; - TasmotaGlobal.timed_cmnd[i].command = (const char*) nullptr; // Force deallocation of the String internal memory - } + for (auto &elem : timed_cmnd) { + if (strncmp(command, elem.command, strlen(command)) == 0) { // StartsWith + free(elem.command); + timed_cmnd.remove(&elem); } } } @@ -701,31 +695,23 @@ void ShowTimedCmnd(const char *command) { bool found = false; uint32_t now = millis(); Response_P(PSTR("{\"%s\":"), XdrvMailbox.command); - for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { - if (TasmotaGlobal.timed_cmnd[i].time != 0) { - if (!strncmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str(), strlen(command))) { - // Stored command starts with command - ResponseAppend_P(PSTR("%s"), (found) ? "," : "["); - found = true; - ResponseAppend_P(PSTR("{\"" D_JSON_REMAINING "\":%d,\"" D_JSON_COMMAND "\":\"%s\"}"), TasmotaGlobal.timed_cmnd[i].time - now, TasmotaGlobal.timed_cmnd[i].command.c_str()); - } + for (auto &elem : timed_cmnd) { + if (strncmp(command, elem.command, strlen(command)) == 0) { // StartsWith + ResponseAppend_P(PSTR("%s{\"" D_JSON_REMAINING "\":%d,\"" D_JSON_COMMAND "\":\"%s\"}"), + (found) ? "," : "[", elem.time - now, elem.command); + found = true; } } - if (found) { - ResponseAppend_P(PSTR("]}")); - } else { - ResponseAppend_P(PSTR("\"" D_JSON_EMPTY "\"}")); - } + ResponseAppend_P((found) ? PSTR("]}") : PSTR("\"" D_JSON_EMPTY "\"}")); } void LoopTimedCmnd(void) { - uint32_t now = millis(); - for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) { - if ((TasmotaGlobal.timed_cmnd[i].time > 0) && (now > TasmotaGlobal.timed_cmnd[i].time)) { - TasmotaGlobal.timed_cmnd[i].time = 0; - String cmd = TasmotaGlobal.timed_cmnd[i].command; - TasmotaGlobal.timed_cmnd[i].command = (const char*) nullptr; // Force deallocation of the String internal memory - ExecuteCommand((char*)cmd.c_str(), SRC_TIMER); + for (auto &elem : timed_cmnd) { + if (TimeReached(elem.time)) { + char* command = elem.command; + timed_cmnd.remove(&elem); + ExecuteCommand(command, SRC_TIMER); + free(command); } } } @@ -763,7 +749,7 @@ void CmndTimedPower(void) { const uint8_t end_state[] = { POWER_ON, POWER_OFF, POWER_TOGGLE, POWER_BLINK_STOP }; char cmnd[CMDSZ]; snprintf_P(cmnd, sizeof(cmnd), PSTR(D_CMND_POWER "%d %d"), XdrvMailbox.index, end_state[start_state]); - if (SetTimedCmnd(time, cmnd)) { // Skip if no more timers left (MAX_TIMED_CMND) + if (SetTimedCmnd(time, cmnd)) { // Skip if no more room for timers XdrvMailbox.payload = start_state; CmndPower(); } From 9006386cf22dbd462e75a8db6bf2a7353081e40b Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 21 Jan 2024 18:40:27 +0100 Subject: [PATCH 199/303] Extend LList (#20555) --- lib/default/TasmotaLList/src/LList.h | 33 +++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/lib/default/TasmotaLList/src/LList.h b/lib/default/TasmotaLList/src/LList.h index 82653448b..4af512b93 100644 --- a/lib/default/TasmotaLList/src/LList.h +++ b/lib/default/TasmotaLList/src/LList.h @@ -59,9 +59,9 @@ public: ~LList() { reset(); } // remove elements - void removeHead(void); // remove first element + T * removeHead(void); // remove first element void reset(void); // remove all elements - void remove(const T * val); + const T * remove(const T * val); // read the list inline bool isEmpty(void) const { return (_head == nullptr) ? true : false; } @@ -77,6 +77,7 @@ public: T & addHead(void); T & addHead(const T &val); T & addToLast(void); + T & insertAt(size_t index); // add an element allocated externally // memory is free by us now -- don't free it! T & addHead(LList_elt * elt); @@ -142,17 +143,21 @@ void LList::reset(void) { } template -void LList::removeHead(void) { +T * LList::removeHead(void) { if (_head) { + T & orginal_head = _head.val; LList_elt * next = _head->next(); delete _head; _head = next; + return orginal_head; + } else { + return nullptr; } } template -void LList::remove(const T * val) { - if (nullptr == val) { return; } +const T * LList::remove(const T * val) { + if (nullptr == val) { return val; } // find element in chain and find pointer before LList_elt **curr_ptr = &_head; while (*curr_ptr) { @@ -164,6 +169,7 @@ void LList::remove(const T * val) { } curr_ptr = &((*curr_ptr)->_next); // move to next element } + return val; } template @@ -201,6 +207,23 @@ T & LList::addToLast(void) { return elt->_val; } +template +T & LList::insertAt(size_t index) { + LList_elt **curr_ptr = &_head; + size_t count = 0; + while (*curr_ptr) { + if (count == index) { + LList_elt * elt = new LList_elt(); // create element + elt->next((*curr_ptr)->next()); + (*curr_ptr)->next(elt); + return elt->_val; + } + curr_ptr = &((*curr_ptr)->_next); + count++; + } + return addToLast(); +} + template T & LList::addToLast(LList_elt * elt) { LList_elt **curr_ptr = &_head; From 1ffbbc914daa47cc094c05eba5b623aa61edcd06 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 21 Jan 2024 22:07:49 +0100 Subject: [PATCH 200/303] Refactor backlog from LinkedList to TasmotaLList --- lib/default/TasmotaLList/src/LList.h | 5 ++-- tasmota/tasmota.ino | 29 ++++++++++++++++--- tasmota/tasmota_support/support_command.ino | 8 +++-- tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino | 3 +- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/lib/default/TasmotaLList/src/LList.h b/lib/default/TasmotaLList/src/LList.h index 4af512b93..fc3a7b559 100644 --- a/lib/default/TasmotaLList/src/LList.h +++ b/lib/default/TasmotaLList/src/LList.h @@ -145,14 +145,13 @@ void LList::reset(void) { template T * LList::removeHead(void) { if (_head) { - T & orginal_head = _head.val; + T * orginal_head = &_head->_val; LList_elt * next = _head->next(); delete _head; _head = next; return orginal_head; - } else { - return nullptr; } + return nullptr; } template diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 16f6c3a1e..d7e01c0c8 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -434,9 +434,8 @@ struct TasmotaGlobal_t { TSettings* Settings = nullptr; -#include -LinkedList backlog; // Command backlog implemented with LinkedList -#define BACKLOG_EMPTY (backlog.size() == 0) +LList backlog; // Command backlog implemented with TasmotaLList +#define BACKLOG_EMPTY (backlog.isEmpty()) /*********************************************************************************************\ * Main @@ -782,7 +781,12 @@ void BacklogLoop(void) { TasmotaGlobal.backlog_mutex = true; bool nodelay = false; do { - char* cmd = backlog.shift(); + char* cmd = *backlog.head(); + backlog.removeHead(); +/* + // This adds 32 bytes + char* cmd = *backlog.removeHead(); +*/ if (!strncasecmp_P(cmd, PSTR(D_CMND_NODELAY), strlen(D_CMND_NODELAY))) { free(cmd); nodelay = true; @@ -795,6 +799,23 @@ void BacklogLoop(void) { break; } } while (!BACKLOG_EMPTY); +/* + // This adds 96 bytes + for (auto &cmd : backlog) { + backlog.remove(&cmd); + if (!strncasecmp_P(cmd, PSTR(D_CMND_NODELAY), strlen(D_CMND_NODELAY))) { + free(cmd); + nodelay = true; + } else { + ExecuteCommand(cmd, SRC_BACKLOG); + free(cmd); + if (nodelay || TasmotaGlobal.backlog_nodelay) { + TasmotaGlobal.backlog_timer = millis(); // Reset backlog_timer which has been set by ExecuteCommand (CommandHandler) + } + break; + } + } +*/ TasmotaGlobal.backlog_mutex = false; } if (BACKLOG_EMPTY) { diff --git a/tasmota/tasmota_support/support_command.ino b/tasmota/tasmota_support/support_command.ino index d763a4130..03dcd294a 100644 --- a/tasmota/tasmota_support/support_command.ino +++ b/tasmota/tasmota_support/support_command.ino @@ -523,7 +523,8 @@ void CmndBacklog(void) { char* temp = (char*)malloc(strlen(blcommand)+1); if (temp != nullptr) { strcpy(temp, blcommand); - backlog.add(temp); + char* &elem = backlog.addToLast(); + elem = temp; } } blcommand = strtok(nullptr, ";"); @@ -533,8 +534,9 @@ void CmndBacklog(void) { TasmotaGlobal.backlog_timer = millis(); } else { bool blflag = BACKLOG_EMPTY; - while (backlog.size()) { - free(backlog.pop()); + for (auto &elem : backlog) { + free(elem); + backlog.remove(&elem); } ResponseCmndChar(blflag ? PSTR(D_JSON_EMPTY) : PSTR(D_JSON_ABORTED)); } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino index 1066951be..e1cec3a67 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino @@ -2069,7 +2069,8 @@ void ExecuteCommandBlock(const char * commands, int len) char* temp = (char*)malloc(strlen(blcommand)+1); if (temp != nullptr) { strcpy(temp, blcommand); - backlog.add(insertPosition, temp); + char* &elem = backlog.insertAt(insertPosition); + elem = temp; } insertPosition++; } From 10885fe60dee5f8ca5ebf79a4522be3fae8f928b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 22 Jan 2024 16:57:59 +0100 Subject: [PATCH 201/303] Refactored rules ``Subscribe`` using LList allowing full message size and enabled by default --- CHANGELOG.md | 3 +- RELEASENOTES.md | 3 +- tasmota/my_user_config.h | 2 +- tasmota/tasmota_support/support.ino | 1 + tasmota/tasmota_support/support_command.ino | 6 +- .../tasmota_xdrv_driver/xdrv_03_energy.ino | 2 +- .../xdrv_03_esp32_energy.ino | 2 +- tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino | 235 ++++++++---------- 8 files changed, 123 insertions(+), 131 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 581a84b33..eafd59ca2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,8 +27,9 @@ All notable changes to this project will be documented in this file. - Command ``TimedPower`` from erasing all timers to showing remaining timers - ESP8266 platform update from 2024.01.00 to 2024.01.01 (#20539) - ESP8266 Framework (Arduino Core) from v2.7.5 to v2.7.6 (#20539) -- Refactor Pio filesystem download script (#20544) +- Refactored Pio filesystem download script (#20544) - Command ``TimedPower`` refactored from String to LList +- Refactored rules ``Subscribe`` using LList allowing full message size and enabled by default ### Fixed - Scripter memory leak in `>w x` (#20473) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 978956b2f..57d4428e7 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -164,12 +164,13 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - ESP8266 Framework (Arduino Core) from v2.7.4.9 to v2.7.6 [#20539](https://github.com/arendst/Tasmota/issues/20539) - ESP32 platform update from 2023.11.01 to 2024.01.01 [#20473](https://github.com/arendst/Tasmota/issues/20473) - Renamed button "Consoles" to "Tools" +- Refactored rule ``Subscribe`` using LList allowing full message size and enabled by default - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` [#20260](https://github.com/arendst/Tasmota/issues/20260) - Web file upload response on upload error [#20340](https://github.com/arendst/Tasmota/issues/20340) - Header `Host` is now collected by Webserver [#20446](https://github.com/arendst/Tasmota/issues/20446) - Webcam tweaks [#20451](https://github.com/arendst/Tasmota/issues/20451) - IP stack compatible with new Core3 IPv6 implementation [#20509](https://github.com/arendst/Tasmota/issues/20509) -- Refactor Pio filesystem download script [#20544](https://github.com/arendst/Tasmota/issues/20544) +- Refactored Pio filesystem download script [#20544](https://github.com/arendst/Tasmota/issues/20544) ### Fixed - CVE-2021-36603 Cross Site Scripting (XSS) vulnerability [#12221](https://github.com/arendst/Tasmota/issues/12221) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 1b2ba3c1b..dbb3af1e8 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -497,7 +497,7 @@ // -- Rules or Script ---------------------------- // Select none or only one of the below defines USE_RULES or USE_SCRIPT #define USE_RULES // Add support for rules (+13k code, +768 bytes mem) -// #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k7 code) + #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+1k8 code) // #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k3 code) // #define SUPPORT_IF_STATEMENT // Add support for IF statement in rules (+3k3) // #define USER_RULE1 "" // Add rule1 data saved at initial firmware load or when command reset is executed diff --git a/tasmota/tasmota_support/support.ino b/tasmota/tasmota_support/support.ino index adc2e2fb6..c38ac087f 100755 --- a/tasmota/tasmota_support/support.ino +++ b/tasmota/tasmota_support/support.ino @@ -579,6 +579,7 @@ bool IsNumeric(const char* value) { char* Trim(char* p) { // Remove leading and trailing tab, \n, \v, \f, \r and space + if (p == nullptr) { return p; } if (*p != '\0') { while ((*p != '\0') && isspace(*p)) { p++; } // Trim leading spaces char* q = p + strlen(p) -1; diff --git a/tasmota/tasmota_support/support_command.ino b/tasmota/tasmota_support/support_command.ino index 03dcd294a..3bd08cef3 100644 --- a/tasmota/tasmota_support/support_command.ino +++ b/tasmota/tasmota_support/support_command.ino @@ -251,6 +251,10 @@ void CmndWifiTest(void) #endif // not defined FIRMWARE_MINIMAL_ONLY +void ResponseCmnd(void) { + Response_P(PSTR("{\"%s\":"), XdrvMailbox.command); +} + void ResponseCmndNumber(int value) { Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, value); } @@ -696,7 +700,7 @@ void ResetTimedCmnd(const char *command) { void ShowTimedCmnd(const char *command) { bool found = false; uint32_t now = millis(); - Response_P(PSTR("{\"%s\":"), XdrvMailbox.command); + ResponseCmnd(); // {"TimedPower": for (auto &elem : timed_cmnd) { if (strncmp(command, elem.command, strlen(command)) == 0) { // StartsWith ResponseAppend_P(PSTR("%s{\"" D_JSON_REMAINING "\":%d,\"" D_JSON_COMMAND "\":\"%s\"}"), diff --git a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino index 2623a4504..a294aba4c 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino @@ -959,7 +959,7 @@ void EnergyCommandCalSetResponse(uint32_t cal_type) { void EnergyCommandCalResponse(uint32_t cal_type) { Energy->command_code = cal_type; // Is XxxCal command too if (XnrgCall(FUNC_COMMAND)) { // XxxCal - Response_P(PSTR("{\"%s\":"), XdrvMailbox.command); + ResponseCmnd(); EnergyCommandCalSetResponse(cal_type); } } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino index 97010142a..4c1b22452 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino @@ -1178,7 +1178,7 @@ void EnergyCommandCalSetResponse(uint32_t cal_type) { void EnergyCommandCalResponse(uint32_t cal_type) { Energy->command_code = cal_type; // Is XxxCal command too if (XnrgCall(FUNC_COMMAND)) { // XxxCal - Response_P(PSTR("{\"%s\":"), XdrvMailbox.command); + ResponseCmnd(); EnergyCommandCalSetResponse(cal_type); } } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino index e1cec3a67..0d0df2120 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino @@ -167,16 +167,6 @@ void (* const RulesCommand[])(void) PROGMEM = { #endif }; -#ifdef SUPPORT_MQTT_EVENT - #include // Import LinkedList library - typedef struct { - String Event; - String Topic; - String Key; - } MQTT_Subscription; - LinkedList subscriptions; -#endif // SUPPORT_MQTT_EVENT - struct RULES { String event_value; unsigned long timer[MAX_RULE_TIMERS] = { 0 }; @@ -1156,6 +1146,14 @@ void RulesSetPower(void) } #ifdef SUPPORT_MQTT_EVENT + +typedef struct { + char* event; + char* topic; + char* key; +} MQTT_Subscription; +LList subscriptions; + /********************************************************************************************/ /* * Rules: Process received MQTT message. @@ -1167,68 +1165,90 @@ void RulesSetPower(void) * false - The message is not in our list. */ bool RulesMqttData(void) { - if ((XdrvMailbox.data_len < 1) || (XdrvMailbox.data_len > RULE_MAX_MQTT_EVENTSZ)) { - return false; +/* + XdrvMailbox.topic = topic; + XdrvMailbox.index = strlen(topic); + XdrvMailbox.data = (char*)data; + XdrvMailbox.data_len = data_len; +*/ + if (XdrvMailbox.data_len < 1) { + return false; // Process unchanged data } bool serviced = false; - String sTopic = XdrvMailbox.topic; - String buData = XdrvMailbox.data; - //AddLog(LOG_LEVEL_DEBUG, PSTR("RUL: MQTT Topic %s, Event %s"), XdrvMailbox.topic, XdrvMailbox.data); - MQTT_Subscription event_item; - //Looking for matched topic - char json_event[RULE_MAX_MQTT_EVENTSZ +32]; // Add chars for {"Event":{"": .. } - for (uint32_t index = 0; index < subscriptions.size(); index++) { + String buData = XdrvMailbox.data; // Could be very long SENSOR message - String sData = buData; + // Looking for matched topic + for (auto &event_item : subscriptions) { + char stopic[strlen(event_item.topic)+2]; + strcpy(stopic, event_item.topic); + strcat(stopic, "/"); + if ((strcmp(XdrvMailbox.topic, event_item.topic) == 0) || // Equal + (strncmp(XdrvMailbox.topic, stopic, strlen(XdrvMailbox.topic)) == 0)) { // StartsWith - event_item = subscriptions.get(index); - - //AddLog(LOG_LEVEL_DEBUG, PSTR("RUL: Match MQTT message Topic %s with subscription topic %s"), sTopic.c_str(), event_item.Topic.c_str()); - if ((sTopic == event_item.Topic) || sTopic.startsWith(event_item.Topic+"/")) { - //This topic is subscribed by us, so serve it + // This topic is subscribed by us, so serve it serviced = true; String value; - if (event_item.Key.length() == 0) { //If did not specify Key - value = sData; - } else { //If specified Key, need to parse Key/Value from JSON data + if (strlen(event_item.key) == 0) { // If did not specify Key + value = buData; + } else { // If specified Key, need to parse Key/Value from JSON data + String sData = buData; JsonParser parser((char*)sData.c_str()); JsonParserObject jsonData = parser.getRootObject(); + if (!jsonData) break; // Failed to parse JSON data, ignore this message. - String key1 = event_item.Key; + String key1 = event_item.key; String key2; - if (!jsonData) break; //Failed to parse JSON data, ignore this message. + int dot; if ((dot = key1.indexOf('.')) > 0) { key2 = key1.substring(dot+1); key1 = key1.substring(0, dot); JsonParserToken value_tok = jsonData[key1.c_str()].getObject()[key2.c_str()]; - if (!value_tok) break; //Failed to get the key/value, ignore this message. + if (!value_tok) break; // Failed to get the key/value, ignore this message. value = value_tok.getStr(); // if (!jsonData[key1][key2].success()) break; //Failed to get the key/value, ignore this message. // value = (const char *)jsonData[key1][key2]; } else { JsonParserToken value_tok = jsonData[key1.c_str()]; - if (!value_tok) break; //Failed to get the key/value, ignore this message. + if (!value_tok) break; // Failed to get the key/value, ignore this message. value = value_tok.getStr(); // if (!jsonData[key1].success()) break; // value = (const char *)jsonData[key1]; } } value.trim(); - -/* - //Create an new event. Cannot directly call RulesProcessEvent(). - snprintf_P(Rules.event_data, sizeof(Rules.event_data), PSTR("%s=%s"), event_item.Event.c_str(), value.c_str()); - // 20230107 Superseded by the following code -*/ bool quotes = (value[0] != '{'); - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Event\":{\"%s\":%s%s%s}}"), event_item.Event.c_str(), (quotes)?"\"":"", value.c_str(), (quotes)?"\"":""); - RulesProcessEvent(json_event); + Response_P(PSTR("{\"Event\":{\"%s\":%s%s%s}}"), event_item.event, (quotes)?"\"":"", value.c_str(), (quotes)?"\"":""); + RulesProcessEvent(ResponseData()); } } return serviced; } +bool RuleUnsubscribe(const char* event) { + UpperCase((char*)event, event); + bool do_all = (strcmp(event, "*") == 0); // Wildcard + //Search all subscriptions + for (auto &index : subscriptions) { + if (do_all || // All + (strcmp(event, index.event) == 0)) { // Equal + //If find exists one, remove it. + char stopic[strlen(index.topic)+3]; + strcpy(stopic, index.topic); + strcat(stopic, "/#"); + MqttUnsubscribe(stopic); + free(index.key); + free(index.topic); + free(index.event); + subscriptions.remove(&index); + if (!do_all) { + return true; + } + } + } + return do_all; +} + /********************************************************************************************/ /* * Subscribe a MQTT topic (with or without key) and assign an event name to it @@ -1245,77 +1265,58 @@ bool RulesMqttData(void) { * Return: * A string include subscribed event, topic and key. */ -void CmndSubscribe(void) -{ - MQTT_Subscription subscription_item; - String events; +void CmndSubscribe(void) { if (XdrvMailbox.data_len > 0) { - char parameters[XdrvMailbox.data_len+1]; - memcpy(parameters, XdrvMailbox.data, XdrvMailbox.data_len); - parameters[XdrvMailbox.data_len] = '\0'; - String event_name, topic, key; + char* event = Trim(strtok(XdrvMailbox.data, ",")); + char* topic = Trim(strtok(nullptr, ",")); + char* key = Trim(strtok(nullptr, ",")); - char * pos = strtok(parameters, ","); - if (pos) { - event_name = Trim(pos); - pos = strtok(nullptr, ","); - if (pos) { - topic = Trim(pos); - pos = strtok(nullptr, ","); - if (pos) { - key = Trim(pos); - } - } - } - //AddLog(LOG_LEVEL_DEBUG, PSTR("RUL: Subscribe command with parameters: %s, %s, %s."), event_name.c_str(), topic.c_str(), key.c_str()); - event_name.toUpperCase(); - if (event_name.length() > 0 && topic.length() > 0) { - //Search all subscriptions - for (uint32_t index=0; index < subscriptions.size(); index++) { - if (subscriptions.get(index).Event.equals(event_name)) { - //If find exists one, remove it. - String stopic = subscriptions.get(index).Topic + "/#"; - MqttUnsubscribe(stopic.c_str()); - subscriptions.remove(index); - break; - } - } - //Add "/#" to the topic - if (!topic.endsWith("#")) { - if (topic.endsWith("/")) { - topic.concat("#"); + if (event && topic) { + RuleUnsubscribe(event); + + // Add "/#" to the topic + uint32_t slen = strlen(topic); + char stopic[slen +3]; + strcpy(stopic, topic); + if (stopic[slen-1] != '#') { + if (stopic[slen-1] == '/') { + strcat(stopic, "#"); } else { - topic.concat("/#"); + strcat(stopic, "/#"); } } - //AddLog(LOG_LEVEL_DEBUG, PSTR("RUL: New topic: %s."), topic.c_str()); - //MQTT Subscribe - subscription_item.Event = event_name; - subscription_item.Topic = topic.substring(0, topic.length() - 2); //Remove "/#" so easy to match - subscription_item.Key = key; - subscriptions.add(subscription_item); - if (2 == XdrvMailbox.index) { - topic = subscription_item.Topic; // Do not append "/#"" - } - MqttSubscribe(topic.c_str()); + if (!key) { key = EmptyStr; } - events.concat(event_name + "," + topic - + (key.length()>0 ? "," : "") - + key); - } else { - events = D_JSON_WRONG_PARAMETERS; - } - } else { - //If did not specify the event name, list all subscribed event - for (uint32_t index=0; index < subscriptions.size(); index++) { - subscription_item = subscriptions.get(index); - events.concat(subscription_item.Event + "," + subscription_item.Topic - + (subscription_item.Key.length()>0 ? "," : "") - + subscription_item.Key + "; "); + // MQTT Subscribe + char* hevent = (char*)malloc(strlen(event) +1); + char* htopic = (char*)malloc(strlen(stopic) -1); // Remove "/#" + char* hkey = (char*)malloc(strlen(key) +1); + if (hevent && htopic && hkey) { + strcpy(hevent, event); + strlcpy(htopic, stopic, strlen(stopic)-1); // Remove "/#" so easy to match + strcpy(hkey, key); + MQTT_Subscription &subscription_item = subscriptions.addToLast(); + subscription_item.event = hevent; + subscription_item.topic = htopic; + subscription_item.key = hkey; + char* ftopic = (2 == XdrvMailbox.index)?htopic:stopic; // Subscribe2 + MqttSubscribe(ftopic); + ResponseCmnd(); // {"Subscribe": + ResponseAppend_P(PSTR("\"%s,%s%s%s\"}"), hevent, ftopic, (strlen(hkey))?",":"", EscapeJSONString(hkey).c_str()); + } } + return; // {"Error"} } - ResponseCmndChar(events.c_str()); + // If did not specify the event name, list all subscribed event + bool found = false; + ResponseCmnd(); // {"Subscribe": + for (auto &items : subscriptions) { + ResponseAppend_P(PSTR("%s%s,%s%s%s"), + (found) ? "; " : "\"", items.event, items.topic, (strlen(items.key))?",":"", EscapeJSONString(items.key).c_str()); + found = true; + } + ResponseAppend_P((found) ? PSTR("\"}") : PSTR("\"" D_JSON_EMPTY "\"}")); } /********************************************************************************************/ @@ -1329,32 +1330,16 @@ void CmndSubscribe(void) * Return: * list all the events unsubscribed. */ -void CmndUnsubscribe(void) -{ - MQTT_Subscription subscription_item; - String events; +void CmndUnsubscribe(void) { if (XdrvMailbox.data_len > 0) { - for (uint32_t index = 0; index < subscriptions.size(); index++) { - subscription_item = subscriptions.get(index); - if (subscription_item.Event.equalsIgnoreCase(XdrvMailbox.data)) { - String stopic = subscription_item.Topic + "/#"; - MqttUnsubscribe(stopic.c_str()); - events = subscription_item.Event; - subscriptions.remove(index); - break; - } - } - } else { - // If did not specify the event name, unsubscribe all event - String stopic; - while (subscriptions.size() > 0) { - events.concat(subscriptions.get(0).Event + "; "); - stopic = subscriptions.get(0).Topic + "/#"; - MqttUnsubscribe(stopic.c_str()); - subscriptions.remove(0); + char* event = Trim(XdrvMailbox.data); + if (RuleUnsubscribe(event)) { + ResponseCmndChar(event); } + return; // {"Error"} } - ResponseCmndChar(events.c_str()); + RuleUnsubscribe("*"); + ResponseCmndDone(); } #endif // SUPPORT_MQTT_EVENT From 85c1413eb15c04234d21187529f0d425486ff792 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:03:52 +0100 Subject: [PATCH 202/303] Bump version v13.3.0.4 --- CHANGELOG.md | 17 +++++++++++++---- RELEASENOTES.md | 2 +- tasmota/include/tasmota_version.h | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eafd59ca2..15f78b754 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,19 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - Development -## [13.3.0.3] +## [13.3.0.4] +### Added + +### Breaking Changed + +### Changed +- Refactored rules ``Subscribe`` using LList allowing full message size and enabled by default + +### Fixed + +### Removed + +## [13.3.0.3] 20240122 ### Added - Berry `debug.caller` (#20470) - GPIO Viewer user selection of assets website now defaults to `https://ota.tasmota.com/tasmota|tasmota32/gpio_viewer/assets` @@ -19,8 +31,6 @@ All notable changes to this project will be documented in this file. - Berry/Zigbee web hook per device for customized status display (#20542) - Zigbee ``ZbEmulation`` to selectively exclude some devices from Hue/Alexa emulation (#20552) -### Breaking Changed - ### Changed - ESP32 platform update from 2024.01.00 to 2024.01.01 (#20508) - IP stack compatible with new Core3 IPv6 implementation (#20509) @@ -29,7 +39,6 @@ All notable changes to this project will be documented in this file. - ESP8266 Framework (Arduino Core) from v2.7.5 to v2.7.6 (#20539) - Refactored Pio filesystem download script (#20544) - Command ``TimedPower`` refactored from String to LList -- Refactored rules ``Subscribe`` using LList allowing full message size and enabled by default ### Fixed - Scripter memory leak in `>w x` (#20473) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 57d4428e7..3d4e15fa6 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -116,7 +116,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm [Complete list](BUILDS.md) of available feature and sensors. -## Changelog v13.3.0.3 +## Changelog v13.3.0.4 ### Added - Command ``TimedPower [,ON|OFF|TOGGLE|BLINK]`` executes ``Power [ON|OFF|TOGGLE|BLINK] `` and after executes ``Power [OFF|ON|TOGGLE|OFF]`` - Support for CST816S touch interface [#20213](https://github.com/arendst/Tasmota/issues/20213) diff --git a/tasmota/include/tasmota_version.h b/tasmota/include/tasmota_version.h index 67c71e010..d88cfd5b7 100644 --- a/tasmota/include/tasmota_version.h +++ b/tasmota/include/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t TASMOTA_VERSION = 0x0D030003; // 13.3.0.3 +const uint32_t TASMOTA_VERSION = 0x0D030004; // 13.3.0.4 #endif // _TASMOTA_VERSION_H_ From 780940d5d0df6d4471a11ab3d0f0dbdefa23b657 Mon Sep 17 00:00:00 2001 From: gemu Date: Mon, 22 Jan 2024 18:21:40 +0100 Subject: [PATCH 203/303] Utouch update (#20561) * toched return int16 * add XPT and more opcodes * add guesture * increase code buffer --- .../src/renderer.cpp | 2 +- .../Display_Renderer-gemu-1.0/src/renderer.h | 2 +- lib/lib_display/UDisplay/uDisplay.cpp | 318 +++++++++++++++--- lib/lib_display/UDisplay/uDisplay.h | 43 ++- .../tasmota_xdrv_driver/xdrv_10_scripter.ino | 2 +- tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino | 7 +- 6 files changed, 312 insertions(+), 62 deletions(-) diff --git a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp index 0bc75395f..f44500c51 100644 --- a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp +++ b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp @@ -627,7 +627,7 @@ bool Renderer::utouch_Init(char **name) { return false; } -bool Renderer::touched(void) { +uint16_t Renderer::touched(void) { return false; } diff --git a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h index a63c4a93f..7ef7d86ab 100644 --- a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h +++ b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h @@ -93,7 +93,7 @@ public: virtual void ep_update_area(uint16_t xp, uint16_t yp, uint16_t width, uint16_t height, uint8_t mode); virtual uint32_t get_sr_touch(uint32_t xp, uint32_t xm, uint32_t yp, uint32_t ym); virtual bool utouch_Init(char **); - virtual bool touched(void); + virtual uint16_t touched(void); virtual int16_t getPoint_x(); virtual int16_t getPoint_y(); diff --git a/lib/lib_display/UDisplay/uDisplay.cpp b/lib/lib_display/UDisplay/uDisplay.cpp index f46032dac..cd671c659 100755 --- a/lib/lib_display/UDisplay/uDisplay.cpp +++ b/lib/lib_display/UDisplay/uDisplay.cpp @@ -587,17 +587,13 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { } else if (*lp1 == 'S') { // spi mode lp1++; - uint8_t ut_mode = *lp1 & 0xf; + ut_spi_nr = *lp1 & 0xf; lp1 += 2; - ut_reset = -1; - ut_irq = -1; ut_spi_cs = next_val(&lp1); ut_reset = next_val(&lp1); ut_irq = next_val(&lp1); - // assume displays SPI bus pinMode(ut_spi_cs, OUTPUT); digitalWrite(ut_spi_cs, HIGH); - ut_spiSettings = SPISettings(2000000, MSBFIRST, SPI_MODE0); } else { // simple resistive touch @@ -921,6 +917,17 @@ uint16_t index = 0; delay_arg(args); } } else { + if (spi_dc == -2) { + // pseudo opcodes + switch (iob) { + case UDSP_WRITE_16: + break; + case UDSP_READ_DATA: + break; + case UDSP_READ_STATUS: + break; + } + } ulcd_command(iob); uint8_t args = dsp_cmds[cmd_offset++]; index++; @@ -1913,13 +1920,21 @@ bool uDisplay::utouch_Init(char **name) { delay(10); } if (ut_irq >= 0) { + pinMode(ut_irq, INPUT ); attachInterrupt(ut_irq, ut_touch_irq, FALLING); } + if (ut_spi_nr == spi_nr) { + ut_spi = uspi; + } else { + // not yet + ut_spi = nullptr; + } + return ut_execute(ut_init_code); } -bool uDisplay::touched(void) { +uint16_t uDisplay::touched(void) { if (ut_irq >= 0) { if (!ut_irq_flg) { return false; @@ -2524,7 +2539,7 @@ void uDisplay::dim10(uint8_t dim, uint16_t dim_gamma) { // dimmer with } // the cases are PSEUDO_OPCODES from MODULE_DESCRIPTOR -// and may be exapnded with more opcodes +// and may be expanded with more opcodes void uDisplay::TS_RotConvert(int16_t *x, int16_t *y) { int16_t temp; @@ -2588,22 +2603,38 @@ char *uDisplay::devname(void) { #ifdef USE_UNIVERSAL_TOUCH -uint16_t uDisplay::ut_par(char **lp, uint32_t mode) { +float CharToFloat(const char *str); + +uint32_t uDisplay::ut_par(char **lp, uint32_t mode) { char *cp = *lp; while (*cp != ' ') { + if (!cp) break; cp++; } cp++; - uint16_t result; + uint32_t result; if (!mode) { + // hex result = strtol(cp, &cp, 16); - } else { + } else if (mode == 1) { + // word result = strtol(cp, &cp, 10); + } else { + // float as 32bit integer + float fval = CharToFloat(cp); + result = *(uint32_t*)&fval; + while (*cp) { + if (*cp == ' ' || *cp =='\n') { + break; + } + cp++; + } } *lp = cp; return result; } +// translate pseudo opcodes to tokens void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { char *cp = *sp; uint16_t wval; @@ -2611,6 +2642,16 @@ void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { if (*cp == ':' || *cp == '#') { break; } + if (*cp == ';') { + // skip comment line + while (*cp) { + if (*cp == '\n') { + cp++; + break; + } + cp++; + } + } if (!strncmp(cp, "RDWM", 4)) { // read word many *ut_code++ = UT_RDWM; @@ -2663,6 +2704,12 @@ void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { // return when true *ut_code++ = UT_RTT; size -= 1; + } else if (!strncmp(cp, "MVB", 3)) { + // move + *ut_code++ = UT_MVB; + *ut_code++ = ut_par(&cp, 1); + *ut_code++ = ut_par(&cp, 1); + size -= 3; } else if (!strncmp(cp, "MV", 2)) { // move *ut_code++ = UT_MV; @@ -2691,13 +2738,36 @@ void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { } else if (!strncmp(cp, "AND", 3)) { *ut_code++ = UT_AND; wval = ut_par(&cp, 0); - *ut_code++ = wval>>8; + *ut_code++ = wval >> 8; + *ut_code++ = wval; + size -= 3; + } else if (!strncmp(cp, "SCL", 3)) { + *ut_code++ = UT_SCALE; + wval = ut_par(&cp, 1); + *ut_code++ = wval >> 8; + *ut_code++ = wval; + uint32_t lval = ut_par(&cp, 2); + *ut_code++ = lval >> 24; + *ut_code++ = lval >> 16; + *ut_code++ = lval >> 8; + *ut_code++ = lval; + size -= 7; + } else if (!strncmp(cp, "LIM", 3)) { + *ut_code++ = UT_LIM; + wval = ut_par(&cp, 1); + *ut_code++ = wval >> 8; *ut_code++ = wval; size -= 3; } else if (!strncmp(cp, "GSRT", 4)) { *ut_code++ = UT_GSRT; wval = ut_par(&cp, 1); - *ut_code++ = wval>>8; + *ut_code++ = wval >> 8; + *ut_code++ = wval; + size -= 3; + } else if (!strncmp(cp, "XPT", 3)) { + *ut_code++ = UT_XPT; + wval = ut_par(&cp, 1); + *ut_code++ = wval >> 8; *ut_code++ = wval; size -= 3; } else if (!strncmp(cp, "DBG", 3)) { @@ -2710,6 +2780,9 @@ void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { break; } + + + cp++; } *ut_code++ = UT_END; @@ -2735,16 +2808,20 @@ uint8_t *uDisplay::ut_rd(uint8_t *iop, uint32_t len, uint32_t amode) { } } else { // spi mode - uint16_t val = *iop++; - digitalWrite(ut_spi_cs, LOW); - if (spi_nr <= 2) { - uspi->beginTransaction(ut_spiSettings); - val = uspi->transfer16(val); - uspi->endTransaction(); - ut_array[0] = val << 8; - ut_array[1] = val; + if (amode == 1) { + uint16_t val = *iop++; + uint16_t len = *iop++; + if (ut_spi) { + digitalWrite(ut_spi_cs, LOW); + ut_spi->beginTransaction(ut_spiSettings); + ut_spi->transfer(val); + val = ut_spi->transfer16(0); + ut_spi->endTransaction(); + ut_array[len] = val << 8; + ut_array[len + 1] = val; + digitalWrite(ut_spi_cs, HIGH); + } } - digitalWrite(ut_spi_cs, HIGH); } return iop; } @@ -2765,6 +2842,59 @@ uint8_t *uDisplay::ut_wr(uint8_t *iop, uint32_t amode) { return iop; } + +int16_t uDisplay::besttwoavg( int16_t x , int16_t y , int16_t z ) { + int16_t da, db, dc; + int16_t reta = 0; + if ( x > y ) da = x - y; else da = y - x; + if ( x > z ) db = x - z; else db = z - x; + if ( z > y ) dc = z - y; else dc = y - z; + + if ( da <= db && da <= dc ) reta = (x + y) >> 1; + else if ( db <= da && db <= dc ) reta = (x + z) >> 1; + else reta = (y + z) >> 1; + + return (reta); +} + +uint16_t uDisplay::ut_XPT2046(uint16_t z_th) { + uint16_t result = 0; + if (ut_spi) { + int16_t data[6]; + ut_spi->beginTransaction(ut_spiSettings); + digitalWrite(ut_spi_cs, LOW); + ut_spi->transfer(0xB1 /* Z1 */); + int16_t z1 = ut_spi->transfer16(0xC1 /* Z2 */) >> 3; + int16_t z = z1 + 4095; + int16_t z2 = ut_spi->transfer16(0x91 /* X */) >> 3; + z -= z2; + if (z >= z_th) { + ut_spi->transfer16(0x91 /* X */); // dummy X measure, 1st is always noisy + data[0] = ut_spi->transfer16(0xD1 /* Y */) >> 3; + data[1] = ut_spi->transfer16(0x91 /* X */) >> 3; // make 3 x-y measurements + data[2] = ut_spi->transfer16(0xD1 /* Y */) >> 3; + data[3] = ut_spi->transfer16(0x91 /* X */) >> 3; + result = 1; + } + else { + data[0] = data[1] = data[2] = data[3] = 0; + } + data[4] = ut_spi->transfer16(0xD0 /* Y */) >> 3; // Last Y touch power down + data[5] = ut_spi->transfer16(0) >> 3; + digitalWrite(ut_spi_cs, HIGH); + ut_spi->endTransaction(); + + uint16_t x = besttwoavg( data[0], data[2], data[4] ); + uint16_t y = besttwoavg( data[1], data[3], data[5] ); + + ut_array[0] = x >> 8; + ut_array[1] = x; + ut_array[2] = y >> 8; + ut_array[3] = y; + } + return result; +} + int16_t uDisplay::ut_execute(uint8_t *ut_code) { int16_t result = 0; uint8_t iob, len; @@ -2777,46 +2907,69 @@ uint16_t wval; // read 1 byte ut_code = ut_rd(ut_code, 1, 1); break; + case UT_RDM: // read multiple bytes ut_code = ut_rd(ut_code, 2, 1); break; + case UT_RDW: // read 1 byte ut_code = ut_rd(ut_code, 1, 2); break; + case UT_RDWM: // read multiple bytes ut_code = ut_rd(ut_code, 2, 2); break; + case UT_WR: ut_code = ut_wr(ut_code, 1); break; + case UT_WRW: ut_code = ut_wr(ut_code, 2); break; + case UT_CP: // compare iob = *ut_code++; result = (iob == ut_array[0]); break; + case UT_CPR: // compare iob = *ut_code++; result = (iob == result); break; + case UT_RTF: // return when false if (result == 0) { return false; } break; + case UT_RTT: // return when true if (result > 0) { return false; } - break; + break; + + case UT_MVB: + // move byte from index to high or low result + wval = *ut_code++; + iob = *ut_code++; + if (wval == 0) { + result &= 0xff00; + result |= ut_array[iob]; + } else { + result &= 0x00ff; + result |= (ut_array[iob] << 8); + } + break; + case UT_MV: // move // source @@ -2835,16 +2988,42 @@ uint16_t wval; } result &= 0xfff; break; - case UT_AND: + + case UT_AND: // and wval = *ut_code++ << 8; wval |= *ut_code++; result &= wval; break; + + case UT_SCALE: + { + wval = *ut_code++ << 8; + wval |= *ut_code++; + result -= wval; + uint32_t lval = (uint32_t)*ut_code++ << 24; + lval |= (uint32_t)*ut_code++ << 16; + lval |= (uint32_t)*ut_code++ << 8; + lval |= (uint32_t)*ut_code++; + float fval = *(float*)&lval; + fval *= (float)result; + result = fval; + } + break; + + case UT_LIM: + wval = *ut_code++ << 8; + wval |= *ut_code++; + if (result > wval) { + result = wval; + } + break; + case UT_RT: // result return result; break; + case UT_GSRT: #ifdef USE_ESP32_S3 { uint32_t val = get_sr_touch(SIMPLERS_XP, SIMPLERS_XM, SIMPLERS_YP, SIMPLERS_YM); @@ -2867,12 +3046,20 @@ uint16_t wval; } #endif // USE_ESP32_S3 break; + + case UT_XPT: + wval = *ut_code++ << 8; + wval |= *ut_code++; + result = ut_XPT2046(wval); + break; + case UT_DBG: // debug show result //Serial.printf("UTDBG: %d\n", result); wval = *ut_code++; AddLog(LOG_LEVEL_INFO, PSTR("UTDBG %d: %02x : %02x,%02x,%02x,%02x"), wval, result, ut_array[0], ut_array[1], ut_array[2], ut_array[3]); break; + case UT_END: break; } @@ -2937,38 +3124,57 @@ uint32_t uDisplay::next_hex(char **sp) { // we use our own hardware driver for 9 bit spi void uDisplay::hw_write9(uint8_t val, uint8_t dc) { - uint32_t regvalue = val >> 1; - if (dc) regvalue |= 0x80; - else regvalue &= 0x7f; - if (val & 1) regvalue |= 0x8000; - - REG_SET_BIT(SPI_USER_REG(3), SPI_USR_MOSI); - REG_WRITE(SPI_MOSI_DLEN_REG(3), 9 - 1); - uint32_t *dp = (uint32_t*)SPI_W0_REG(3); - *dp = regvalue; - REG_SET_BIT(SPI_CMD_REG(3), SPI_USR); - while (REG_GET_FIELD(SPI_CMD_REG(3), SPI_USR)); + if (spi_dc < -1) { + // RA8876 mode + if (!dc) { + uspi->write(RA8876_CMD_WRITE); + uspi->write(val); + } else { + uspi->write(RA8876_DATA_WRITE); + uspi->write(val); + } + } else { + uint32_t regvalue = val >> 1; + if (dc) regvalue |= 0x80; + else regvalue &= 0x7f; + if (val & 1) regvalue |= 0x8000; + REG_SET_BIT(SPI_USER_REG(3), SPI_USR_MOSI); + REG_WRITE(SPI_MOSI_DLEN_REG(3), 9 - 1); + uint32_t *dp = (uint32_t*)SPI_W0_REG(3); + *dp = regvalue; + REG_SET_BIT(SPI_CMD_REG(3), SPI_USR); + while (REG_GET_FIELD(SPI_CMD_REG(3), SPI_USR)); + } } #else #include "spi_register.h" void uDisplay::hw_write9(uint8_t val, uint8_t dc) { - uint32_t regvalue; - uint8_t bytetemp; - if (!dc) { - bytetemp = (val>> 1) & 0x7f; + if (spi_dc < -1) { + // RA8876 mode + if (!dc) { + uspi->write(RA8876_CMD_WRITE); + uspi->write(val); + } else { + uspi->write(RA8876_DATA_WRITE); + uspi->write(val); + } } else { - bytetemp = (val >> 1) | 0x80; + uint32_t regvalue; + uint8_t bytetemp; + if (!dc) { + bytetemp = (val>> 1) & 0x7f; + } else { + bytetemp = (val >> 1) | 0x80; + } + regvalue = ((8 & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) | ((uint32)bytetemp); //configure transmission variable,9bit transmission length and first 8 command bit + if (val & 0x01) regvalue |= BIT15; //write the 9th bit + while (READ_PERI_REG(SPI_CMD(1)) & SPI_USR); //waiting for spi module available + WRITE_PERI_REG(SPI_USER2(1), regvalue); //write command and command length into spi reg + SET_PERI_REG_MASK(SPI_CMD(1), SPI_USR); //transmission start } - - regvalue = ((8 & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) | ((uint32)bytetemp); //configure transmission variable,9bit transmission length and first 8 command bit - if (val & 0x01) regvalue |= BIT15; //write the 9th bit - while (READ_PERI_REG(SPI_CMD(1)) & SPI_USR); //waiting for spi module available - WRITE_PERI_REG(SPI_USER2(1), regvalue); //write command and command length into spi reg - SET_PERI_REG_MASK(SPI_CMD(1), SPI_USR); //transmission start - } #endif @@ -2985,6 +3191,26 @@ void USECACHE uDisplay::write8(uint8_t val) { } } +uint8_t uDisplay::writeReg16(uint8_t reg, uint16_t wval) { + hw_write9(reg, 0); + hw_write9(wval, 1); + hw_write9(reg + 1, 0); + hw_write9(wval >> 8, 1); + return 0; +} + +uint8_t uDisplay::readData(void) { + uspi->write(RA8876_DATA_READ); + uint8_t val = uspi->transfer(0); + return val; +} + +uint8_t uDisplay::readStatus(void) { + uspi->write(RA8876_STATUS_READ); + uint8_t val = uspi->transfer(0); + return val; +} + void uDisplay::write8_slow(uint8_t val) { for (uint8_t bit = 0x80; bit; bit >>= 1) { GPIO_CLR_SLOW(spi_clk); diff --git a/lib/lib_display/UDisplay/uDisplay.h b/lib/lib_display/UDisplay/uDisplay.h index 21e2eb6f3..9878e865d 100755 --- a/lib/lib_display/UDisplay/uDisplay.h +++ b/lib/lib_display/UDisplay/uDisplay.h @@ -17,6 +17,25 @@ #endif // ESP_IDF_VERSION_MAJOR >= 5 #endif +enum { + UT_RD,UT_RDM,UT_CP,UT_RTF,UT_MV,UT_MVB,UT_RT,UT_RTT,UT_RDW,UT_RDWM,UT_WR,UT_WRW,UT_CPR,UT_AND,UT_SCALE,UT_LIM,UT_DBG,UT_GSRT,UT_XPT,UT_END +}; + +#define RA8876_DATA_WRITE 0x80 +#define RA8876_DATA_READ 0xC0 +#define RA8876_CMD_WRITE 0x00 +#define RA8876_STATUS_READ 0x40 + +#define UDSP_WRITE_16 0xf0 +#define UDSP_READ_DATA 0xf1 +#define UDSP_READ_STATUS 0xf2 + + +#define SIMPLERS_XP par_dbl[1] +#define SIMPLERS_XM par_cs +#define SIMPLERS_YP par_rs +#define SIMPLERS_YM par_dbl[0] + #ifdef USE_ESP32_S3 #include #include "esp_private/gdma.h" @@ -101,14 +120,7 @@ enum uColorType { uCOLOR_BW, uCOLOR_COLOR }; #define GPIO_SET(A) GPIO.out_w1ts = (1 << A) #endif -enum { - UT_RD,UT_RDM,UT_CP,UT_RTF,UT_MV,UT_RT,UT_RTT,UT_RDW,UT_RDWM,UT_WR,UT_WRW,UT_CPR,UT_AND,UT_DBG,UT_GSRT,UT_END -}; -#define SIMPLERS_XP par_dbl[1] -#define SIMPLERS_XM par_cs -#define SIMPLERS_YP par_rs -#define SIMPLERS_YM par_dbl[0] #define GPIO_CLR_SLOW(A) digitalWrite(A, LOW) @@ -202,7 +214,7 @@ class uDisplay : public Renderer { #ifdef USE_UNIVERSAL_TOUCH // universal touch driver bool utouch_Init(char **name); - bool touched(void); + uint16_t touched(void); int16_t getPoint_x(); int16_t getPoint_y(); #endif // USE_UNIVERSAL_TOUCH @@ -229,6 +241,9 @@ class uDisplay : public Renderer { void write16(uint16_t val); void write32(uint32_t val); void spi_data9(uint8_t d, uint8_t dc); + uint8_t readData(void); + uint8_t readStatus(void); + uint8_t writeReg16(uint8_t reg, uint16_t wval); void WriteColor(uint16_t color); void SetLut(const unsigned char* lut); void SetLuts(void); @@ -432,22 +447,26 @@ class uDisplay : public Renderer { // universal touch driver void ut_trans(char **sp, uint8_t *ut_code, int32_t size); int16_t ut_execute(uint8_t *ut_code); - uint16_t ut_par(char **cp, uint32_t mode); + uint32_t ut_par(char **cp, uint32_t mode); uint8_t *ut_rd(uint8_t *io, uint32_t len, uint32_t amode); uint8_t *ut_wr(uint8_t *io, uint32_t amode); - uint32_t ut_result; + uint16_t ut_XPT2046(uint16_t zh); + int16_t besttwoavg( int16_t x , int16_t y , int16_t z ); + uint8_t ut_array[16]; uint8_t ut_i2caddr; uint8_t ut_spi_cs; int8_t ut_reset; int8_t ut_irq; + uint8_t ut_spi_nr; TwoWire *ut_wire; + SPIClass *ut_spi; SPISettings ut_spiSettings; char ut_name[8]; uint8_t ut_init_code[32]; uint8_t ut_touch_code[32]; - uint8_t ut_getx_code[16]; - uint8_t ut_gety_code[16]; + uint8_t ut_getx_code[20]; + uint8_t ut_gety_code[20]; #endif // USE_UNIVERSAL_TOUCH }; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino index 76903985e..a3753a8ca 100755 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino @@ -5875,7 +5875,7 @@ extern char *SML_GetSVal(uint32_t index); goto exit; } #endif // USE_TTGO_WATCH -#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_UNIVERSAL_TOUCH) || defined(USE_GT911) +#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_UNIVERSAL_TOUCH) || defined(USE_CST816S) || defined(SIMPLE_RES_TOUCH) || defined(USE_GT911) if (!strncmp_XP(lp, XPSTR("wtch("), 5)) { lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv); fvar = Touch_Status(fvar); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino index 1801fb3d6..9a82e7eb8 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino @@ -254,8 +254,13 @@ void utouch_Touch_Init() { bool utouch_touched() { if (renderer) { - return renderer->touched(); + uint16 status = renderer->touched(); + if (status & 1) { + TSGlobal.gesture = status >> 8; + return true; + } } + return false; } int16_t utouch_x() { if (renderer) { From a915fdec529f1c3d156ecfdfee26191afe16b1f4 Mon Sep 17 00:00:00 2001 From: gemu Date: Mon, 22 Jan 2024 18:21:58 +0100 Subject: [PATCH 204/303] modify RA8876 display driver to use internal touch driver (#20562) * integrate utouch driver * modify for utouch driver * touched is now int16 --- .../Xlatb_RA8876-gemu-1.0/RA8876.cpp | 99 +++++++++++++++++++ .../Xlatb_RA8876-gemu-1.0/RA8876.h | 17 +++- .../tasmota_xdsp_display/xdsp_10_RA8876.ino | 36 +------ 3 files changed, 119 insertions(+), 33 deletions(-) diff --git a/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp index ce1aa4603..d050d83ac 100644 --- a/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp +++ b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp @@ -38,6 +38,9 @@ fast picture write // Serial.printf(">%d,\n", stage); // +enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE}; +extern void AddLog(uint32_t loglevel, PGM_P formatP, ...); + const uint16_t RA8876_colors[]={RA8876_BLACK,RA8876_WHITE,RA8876_RED,RA8876_GREEN,RA8876_BLUE,RA8876_CYAN,RA8876_MAGENTA,\ RA8876_YELLOW,RA8876_NAVY,RA8876_DARKGREEN,RA8876_DARKCYAN,RA8876_MAROON,RA8876_PURPLE,RA8876_OLIVE,\ RA8876_LIGHTGREY,RA8876_DARKGREY,RA8876_ORANGE,RA8876_GREENYELLOW,RA8876_PINK}; @@ -1298,6 +1301,102 @@ void RA8876::setDrawMode(uint8_t mode) { setDrawMode_reg(mode); } +//#define RA_FT5206_VENDID 0x11 +#define RA_FT5206_VENDID 0x79 +#define RA_FT5206U_CHIPID 0x64 +#define RA_FT5316_CHIPID 0x0a +#define RA_FT5206_VENDID_REG (0xA8) +#define RA_FT5206_CHIPID_REG (0xA3) +#define RA_FT5206_TOUCHES_REG (0x02) +#define RA_FT5206_MODE_REG (0x00) +#define RA_FT5206_address 0x38 + +int RA8876::_readByte(uint8_t reg, uint8_t nbytes, uint8_t *data) { + _i2cPort->beginTransmission(RA_FT5206_address); + _i2cPort->write(reg); + _i2cPort->endTransmission(); + _i2cPort->requestFrom(RA_FT5206_address, (size_t)nbytes); + uint8_t index = 0; + while (_i2cPort->available()) { + data[index++] = _i2cPort->read(); + } + return 0; +} + +int RA8876::_writeByte(uint8_t reg, uint8_t nbytes, uint8_t *data) { + _i2cPort->beginTransmission(RA_FT5206_address); + _i2cPort->write(reg); + for (uint8_t i = 0; i < nbytes; i++) { + _i2cPort->write(data[i]); + } + _i2cPort->endTransmission(); + return 0; +} + +bool RA8876::utouch_Init(char **name) { + strcpy(ut_name, "FT5316"); + *name = ut_name; + + _i2cPort = &Wire; + + uint8_t val; + _readByte(RA_FT5206_VENDID_REG, 1, &val); + //AddLog(LOG_LEVEL_INFO, PSTR("UTDBG %02x"), val); + + if (val != RA_FT5206_VENDID) { + return false; + } + + _readByte(RA_FT5206_CHIPID_REG, 1, &val); + //AddLog(LOG_LEVEL_INFO, PSTR("UTDBG %02x"), val); + + if (val != RA_FT5316_CHIPID) { + return false; + } + + return true; +} + +uint16_t RA8876::touched(void) { + uint8_t data[16]; + + uint8_t val = 0; + _readByte(RA_FT5206_MODE_REG, 1, &val); + if (val) { + val = 0; + _writeByte(RA_FT5206_MODE_REG, 1, &val); + } + + _readByte(RA_FT5206_MODE_REG, 16, data); + + if (data[2]) { + ut_x = data[3] << 8; + ut_x |= data[4]; + ut_y = data[5] << 8; + ut_y |= data[6]; + ut_x &= 0xfff; + ut_y &= 0xfff; + } + return data[2]; +} + +int16_t RA8876::getPoint_x() { + return ut_x; +} + +int16_t RA8876::getPoint_y() { + return ut_y; +} + +void RA8876::TS_RotConvert(int16_t *x, int16_t *y) { +int16_t temp; + *x = *x * width() / 800; + *y = *y * height() / 480; + + *x = width() - *x; + *y = height() - *y; +} + void RA8876::setDrawMode_reg(uint8_t mode) { SPI.beginTransaction(m_spiSettings); uint8_t ccr1 = readReg(RA8876_REG_CCR1); diff --git a/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h index 4bf711da7..eb986a631 100644 --- a/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h +++ b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h @@ -26,6 +26,8 @@ #include "driver/spi_master.h" #endif +#include + #include "tasmota_options.h" #undef SPRINT @@ -467,7 +469,6 @@ class RA8876 : public Renderer { void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color); void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color); - void drawCircle(int16_t x, int16_t y, int16_t radius, uint16_t color); void fillCircle(int16_t x, int16_t y, int16_t radius, uint16_t color); void drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color); @@ -510,6 +511,11 @@ class RA8876 : public Renderer { void dim10(uint8_t contrast, uint16_t contrast_gamma); void FastString(uint16_t x,uint16_t y,uint16_t tcolor, const char* str); + bool utouch_Init(char **name); + uint16_t touched(void); + int16_t getPoint_x(); + int16_t getPoint_y(); + private: uint8_t tabcolor; void PWM_init(void); @@ -533,6 +539,7 @@ class RA8876 : public Renderer { bool initPLL(void); bool initMemory(SdramInfo *info); bool initDisplay(void); + char ut_name[8]; // Font utils uint8_t internalFontEncoding(enum FontEncoding enc); @@ -547,6 +554,14 @@ class RA8876 : public Renderer { void drawEllipseShape(int x, int y, int xrad, int yrad, uint16_t color, uint8_t cmd); // drawCircle, fillCircle void drawThreePointShape1(int x1, int y1, int x2, int y2, int x3, int y3, uint16_t color, uint8_t reg, uint8_t cmd); + void TS_RotConvert(int16_t *x, int16_t *y); + + TwoWire *_i2cPort; + int _readByte(uint8_t reg, uint8_t nbytes, uint8_t *data); + int _writeByte(uint8_t reg, uint8_t nbytes, uint8_t *data); + uint16_t ut_x; + uint16_t ut_y; + int8_t m_csPin, _mosi, _miso, _sclk, dimmer, _hwspi; uint16_t m_width; uint16_t m_height; diff --git a/tasmota/tasmota_xdsp_display/xdsp_10_RA8876.ino b/tasmota/tasmota_xdsp_display/xdsp_10_RA8876.ino index 33b4fc438..9a7b74de7 100644 --- a/tasmota/tasmota_xdsp_display/xdsp_10_RA8876.ino +++ b/tasmota/tasmota_xdsp_display/xdsp_10_RA8876.ino @@ -80,39 +80,16 @@ void RA8876_InitDriver(void) { FT5206_Touch_Init(Wire); #endif +#ifdef USE_UNIVERSAL_TOUCH + utouch_Touch_Init(); +#endif + ra8876_init_done = true; AddLog(LOG_LEVEL_INFO, PSTR("DSP: RA8876")); } } -#ifdef USE_FT5206 -#ifdef USE_TOUCH_BUTTONS - -// no rotation support -void RA8876_RotConvert(int16_t *x, int16_t *y) { -int16_t temp; - if (renderer) { - *x=*x*renderer->width()/800; - *y=*y*renderer->height()/480; - - *x = renderer->width() - *x; - *y = renderer->height() - *y; - } -} - -// check digitizer hit -void RA8876_CheckTouch(void) { - ra8876_ctouch_counter++; - if (2 == ra8876_ctouch_counter) { - // every 100 ms should be enough - ra8876_ctouch_counter = 0; - Touch_Check(RA8876_RotConvert); - } -} -#endif // USE_TOUCH_BUTTONS -#endif // USE_FT5206 - /* void testall() { ra8876->clearScreen(0); @@ -309,11 +286,6 @@ bool Xdsp10(uint32_t function) case FUNC_DISPLAY_MODEL: result = true; break; - case FUNC_DISPLAY_EVERY_50_MSECOND: -#ifdef USE_FT5206 - if (FT5206_found) RA8876_CheckTouch(); -#endif - break; } } return result; From 669fc1ecfa4c3165259f5d66a4922c4fbee2d312 Mon Sep 17 00:00:00 2001 From: ouinouin Date: Mon, 22 Jan 2024 19:27:44 +0100 Subject: [PATCH 205/303] Create ST7735S_ATOM_S3_diplsay.ini (#20566) inspired from code given by atom, and M5stick display.ini tested and working in all rotations. --- .../displaydesc/ST7735S_ATOM_S3_diplsay.ini | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tasmota/displaydesc/ST7735S_ATOM_S3_diplsay.ini diff --git a/tasmota/displaydesc/ST7735S_ATOM_S3_diplsay.ini b/tasmota/displaydesc/ST7735S_ATOM_S3_diplsay.ini new file mode 100644 index 000000000..09e020b1f --- /dev/null +++ b/tasmota/displaydesc/ST7735S_ATOM_S3_diplsay.ini @@ -0,0 +1,37 @@ +`:H,ST7735S,128,128,16,SPI,1,,,,,,,*,40 + +:I +01,80 +11,E0 +EF,80,5 +B0,1,C0 +B2,1,2F +B3,1,03 +B6,1,19 +B7,1,01 +AC,1,CB +AB,1,0E +B4,1,04 +A8,1,19 +B8,1,08 +E8,1,24 +E9,1,48 +EA,1,22 +C6,1,30 +C7,1,18 +3A,1,05 +F0,14,1F,28,04,3E,2A,2E,20,00,0C,06,00,1C,1F,0f +F1,14,00,2D,2F,3C,6F,1C,0B,00,00,00,07,0D,11,0f +29,0 +:o,28 +:O,29 +:A,2A,2B,2C,16 +:R,36 +:0,CC,02,01,00 +:1,68,01,02,01 +:2,08,02,01,02 +:3,A8,01,02,03 +:i,21,20 +:i,21,20 +;B10,0 +#` From a9a3f5638ca2089948c95e6108f0961537fb9922 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 23 Jan 2024 12:32:12 +0100 Subject: [PATCH 206/303] Fix subscribe rule handling --- tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino index 0d0df2120..1450ed821 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino @@ -1175,15 +1175,17 @@ bool RulesMqttData(void) { return false; // Process unchanged data } bool serviced = false; - String buData = XdrvMailbox.data; // Could be very long SENSOR message + String buData = XdrvMailbox.data; // Distroyed by JsonParser. Could be very long SENSOR message + char ctopic[strlen(XdrvMailbox.topic)+1]; + strcpy(ctopic, XdrvMailbox.topic); // Distroyed by result of following iteration // Looking for matched topic for (auto &event_item : subscriptions) { - char stopic[strlen(event_item.topic)+2]; - strcpy(stopic, event_item.topic); - strcat(stopic, "/"); - if ((strcmp(XdrvMailbox.topic, event_item.topic) == 0) || // Equal - (strncmp(XdrvMailbox.topic, stopic, strlen(XdrvMailbox.topic)) == 0)) { // StartsWith + char etopic[strlen(event_item.topic)+2]; + strcpy(etopic, event_item.topic); + strcat(etopic, "/"); + if ((strcmp(ctopic, event_item.topic) == 0) || // Equal + (strncmp(ctopic, etopic, strlen(etopic)) == 0)) { // StartsWith // This topic is subscribed by us, so serve it serviced = true; From ab39abb7edd4c4a8bbb8fe3caeefb0889d94ee88 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 23 Jan 2024 17:44:56 +0100 Subject: [PATCH 207/303] `LinkedList` not needed any more for safeboot env --- platformio_tasmota32.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index a735cd6d7..06311b29b 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -52,6 +52,7 @@ extra_scripts = pre:pio-tools/add_c_flags.py [safeboot_flags] lib_ignore = ${esp32_defaults.lib_ignore} + LinkedList ESP Mail Client IRremoteESP8266 NeoPixelBus From a7f3a7adad12862997cdb3bb2606ac87e4376b01 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 23 Jan 2024 17:51:13 +0100 Subject: [PATCH 208/303] `Berry animation library` not needed for safeboot env --- platformio_tasmota32.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 06311b29b..fefc60ed4 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -72,6 +72,7 @@ lib_ignore = ${esp32_defaults.lib_ignore} Berry Tasmota mapping Berry int64 implementation for 32 bits architecture Berry Matter protocol implementation + Berry animation library for WS2812 leds Micro-RTSP re1.5 DHT sensor library From dca33c10a39836f5edf36c644aaf55c74a7c4fea Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 23 Jan 2024 18:17:42 +0100 Subject: [PATCH 209/303] Fix subscribe same topic, multiple events And even smaller by unstringifying --- tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino | 72 +++++++++---------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino index 1450ed821..cdbeba531 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino @@ -1175,53 +1175,49 @@ bool RulesMqttData(void) { return false; // Process unchanged data } bool serviced = false; - String buData = XdrvMailbox.data; // Distroyed by JsonParser. Could be very long SENSOR message + String buData = XdrvMailbox.data; // Destroyed by JsonParser. Could be very long SENSOR message char ctopic[strlen(XdrvMailbox.topic)+1]; - strcpy(ctopic, XdrvMailbox.topic); // Distroyed by result of following iteration + strcpy(ctopic, XdrvMailbox.topic); // Destroyed by result of following iteration - // Looking for matched topic - for (auto &event_item : subscriptions) { + for (auto &event_item : subscriptions) { // Looking for all matched topics char etopic[strlen(event_item.topic)+2]; - strcpy(etopic, event_item.topic); - strcat(etopic, "/"); - if ((strcmp(ctopic, event_item.topic) == 0) || // Equal - (strncmp(ctopic, etopic, strlen(etopic)) == 0)) { // StartsWith + strcpy(etopic, event_item.topic); // tele/tasmota/SENSOR + strcat(etopic, "/"); // tele/tasmota/SENSOR/ + if ((strcmp(ctopic, event_item.topic) == 0) || // Equal tele/tasmota/SENSOR + (strncmp(ctopic, etopic, strlen(etopic)) == 0)) { // StartsWith tele/tasmota/SENSOR/ - // This topic is subscribed by us, so serve it - serviced = true; - String value; - if (strlen(event_item.key) == 0) { // If did not specify Key - value = buData; - } else { // If specified Key, need to parse Key/Value from JSON data - String sData = buData; + serviced = true; // This topic is subscribed by us, so serve it + String sData = buData; // sData will be destroyed by JsonParser + char* value = nullptr; + if (strlen(event_item.key) == 0) { // If no key specified + value = (char*)buData.c_str(); // {"DS18B20":{"Id":"0000048EC44C","Temperature":23.3}} + } else { // If key specified, need to parse Key/Value from JSON data JsonParser parser((char*)sData.c_str()); JsonParserObject jsonData = parser.getRootObject(); - if (!jsonData) break; // Failed to parse JSON data, ignore this message. + if (!jsonData) { break; } // Failed to parse JSON data, ignore this message. - String key1 = event_item.key; - String key2; - - int dot; - if ((dot = key1.indexOf('.')) > 0) { - key2 = key1.substring(dot+1); - key1 = key1.substring(0, dot); - JsonParserToken value_tok = jsonData[key1.c_str()].getObject()[key2.c_str()]; - if (!value_tok) break; // Failed to get the key/value, ignore this message. - value = value_tok.getStr(); - // if (!jsonData[key1][key2].success()) break; //Failed to get the key/value, ignore this message. - // value = (const char *)jsonData[key1][key2]; - } else { - JsonParserToken value_tok = jsonData[key1.c_str()]; - if (!value_tok) break; // Failed to get the key/value, ignore this message. - value = value_tok.getStr(); - // if (!jsonData[key1].success()) break; - // value = (const char *)jsonData[key1]; + char ckey1[strlen(event_item.key)+1]; + strcpy(ckey1, event_item.key); // DS18B20.Temperature + char* ckey2 = strchr(ckey1, '.'); + if (ckey2 != nullptr) { // .Temperature + *ckey2++ = '\0'; // Temperature and ckey1 becomes DS18B20 + JsonParserToken val = jsonData[ckey1].getObject()[ckey2]; + if (val) { + value = (char*)val.getStr(); // 23.3 + } + } else { // DS18B20 + JsonParserToken val = jsonData[ckey1]; + if (val) { + value = (char*)val.getStr(); // \0 + } } } - value.trim(); - bool quotes = (value[0] != '{'); - Response_P(PSTR("{\"Event\":{\"%s\":%s%s%s}}"), event_item.event, (quotes)?"\"":"", value.c_str(), (quotes)?"\"":""); - RulesProcessEvent(ResponseData()); + if (value) { + Trim(value); + bool quotes = (value[0] != '{'); + Response_P(PSTR("{\"Event\":{\"%s\":%s%s%s}}"), event_item.event, (quotes)?"\"":"", value, (quotes)?"\"":""); + RulesProcessEvent(ResponseData()); + } } } return serviced; From c6355e02fb0eeaeca822cd6c8e538aef9e18b610 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 23 Jan 2024 18:23:04 +0100 Subject: [PATCH 210/303] Better bailout --- tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino index cdbeba531..ec06ca00d 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino @@ -1171,7 +1171,7 @@ bool RulesMqttData(void) { XdrvMailbox.data = (char*)data; XdrvMailbox.data_len = data_len; */ - if (XdrvMailbox.data_len < 1) { + if ((XdrvMailbox.data_len < 1) || (subscriptions.isEmpty())) { return false; // Process unchanged data } bool serviced = false; From 44b3d99b21e62d906bbe38e106f1a301ccb7faec Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 23 Jan 2024 22:44:27 +0100 Subject: [PATCH 211/303] mp3_shine compiles with c3 (#20572) --- platformio_tasmota_env32.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/platformio_tasmota_env32.ini b/platformio_tasmota_env32.ini index 5b62e0bc6..3874dc9f9 100644 --- a/platformio_tasmota_env32.ini +++ b/platformio_tasmota_env32.ini @@ -167,7 +167,6 @@ lib_ignore = ${env:tasmota32_base.lib_ignore} TTGO TWatch Library Micro-RTSP epdiy - mp3_shine_esp32 [env:tasmota32c3cdc-safeboot] extends = env:tasmota32c3-safeboot From d5315837210ce715789d962ea386e3e946417b75 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Tue, 23 Jan 2024 23:16:24 +0100 Subject: [PATCH 212/303] Clean solidified animate (#20574) --- .../src/solidify/solidified_animate_0.h | 7 - .../src/solidify/solidified_animate_1_core.h | 871 --------- .../solidified_animate_2_animate_effects.h | 450 ----- .../solidify/solidified_animate_9_module.h | 1592 ----------------- .../solidified_leds_frame_be_methods.h | 186 -- 5 files changed, 3106 deletions(-) delete mode 100644 lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0.h delete mode 100644 lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_core.h delete mode 100644 lib/libesp32/berry_tasmota/src/solidify/solidified_animate_2_animate_effects.h delete mode 100644 lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h delete mode 100644 lib/libesp32/berry_tasmota/src/solidify/solidified_leds_frame_be_methods.h diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0.h deleted file mode 100644 index a0a262928..000000000 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_0.h +++ /dev/null @@ -1,7 +0,0 @@ -/* Solidification of animate_0.h */ -/********************************************************************\ -* Generated code, don't edit * -\********************************************************************/ -#include "be_constobj.h" -/********************************************************************/ -/* End of solidification */ diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_core.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_core.h deleted file mode 100644 index 280b7de5c..000000000 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_1_core.h +++ /dev/null @@ -1,871 +0,0 @@ -/* Solidification of animate_1_core.h */ -/********************************************************************\ -* Generated code, don't edit * -\********************************************************************/ -#include "be_constobj.h" - -extern const bclass be_class_Animate_core; - -/******************************************************************** -** Solidified function: clear -********************************************************************/ -be_local_closure(Animate_core_clear, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(stop), - /* K1 */ be_nested_str_weak(strip), - /* K2 */ be_nested_str_weak(clear), - }), - be_str_weak(clear), - &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0x88040101, // 0002 GETMBR R1 R0 K1 - 0x8C040302, // 0003 GETMET R1 R1 K2 - 0x7C040200, // 0004 CALL R1 1 - 0x80000000, // 0005 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_strip_bri -********************************************************************/ -be_local_closure(Animate_core_set_strip_bri, /* name */ - be_nested_proto( - 10, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(strip), - /* K1 */ be_nested_str_weak(set_bri), - /* K2 */ be_nested_str_weak(tasmota), - /* K3 */ be_nested_str_weak(scale_uint), - /* K4 */ be_nested_str_weak(bri), - /* K5 */ be_const_int(0), - }), - be_str_weak(set_strip_bri), - &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0xB80E0400, // 0002 GETNGBL R3 K2 - 0x8C0C0703, // 0003 GETMET R3 R3 K3 - 0x88140104, // 0004 GETMBR R5 R0 K4 - 0x58180005, // 0005 LDCONST R6 K5 - 0x541E0063, // 0006 LDINT R7 100 - 0x58200005, // 0007 LDCONST R8 K5 - 0x542600FE, // 0008 LDINT R9 255 - 0x7C0C0C00, // 0009 CALL R3 6 - 0x7C040400, // 000A CALL R1 2 - 0x80000000, // 000B RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: remove_painter -********************************************************************/ -be_local_closure(Animate_core_remove_painter, /* name */ - be_nested_proto( - 8, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(painters), - /* K1 */ be_nested_str_weak(remove), - /* K2 */ be_nested_str_weak(find), - /* K3 */ be_nested_str_weak(clear), - }), - be_str_weak(remove_painter), - &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x200C0203, // 0002 NE R3 R1 R3 - 0x780E0005, // 0003 JMPF R3 #000A - 0x8C0C0501, // 0004 GETMET R3 R2 K1 - 0x8C140502, // 0005 GETMET R5 R2 K2 - 0x5C1C0200, // 0006 MOVE R7 R1 - 0x7C140400, // 0007 CALL R5 2 - 0x7C0C0400, // 0008 CALL R3 2 - 0x70020001, // 0009 JMP #000C - 0x8C0C0503, // 000A GETMET R3 R2 K3 - 0x7C0C0200, // 000B CALL R3 1 - 0x80000000, // 000C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: stop -********************************************************************/ -be_local_closure(Animate_core_stop, /* name */ - be_nested_proto( - 6, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str_weak(running), - /* K1 */ be_nested_str_weak(animators), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(stop), - /* K4 */ be_const_int(1), - /* K5 */ be_nested_str_weak(tasmota), - /* K6 */ be_nested_str_weak(remove_fast_loop), - /* K7 */ be_nested_str_weak(fast_loop_cb), - }), - be_str_weak(stop), - &be_const_str_solidified, - ( &(const binstruction[19]) { /* code */ - 0x50040000, // 0000 LDBOOL R1 0 0 - 0x90020001, // 0001 SETMBR R0 K0 R1 - 0x88040101, // 0002 GETMBR R1 R0 K1 - 0x58080002, // 0003 LDCONST R2 K2 - 0x600C000C, // 0004 GETGBL R3 G12 - 0x5C100200, // 0005 MOVE R4 R1 - 0x7C0C0200, // 0006 CALL R3 1 - 0x140C0403, // 0007 LT R3 R2 R3 - 0x780E0004, // 0008 JMPF R3 #000E - 0x940C0202, // 0009 GETIDX R3 R1 R2 - 0x8C0C0703, // 000A GETMET R3 R3 K3 - 0x7C0C0200, // 000B CALL R3 1 - 0x00080504, // 000C ADD R2 R2 K4 - 0x7001FFF5, // 000D JMP #0004 - 0xB80E0A00, // 000E GETNGBL R3 K5 - 0x8C0C0706, // 000F GETMET R3 R3 K6 - 0x88140107, // 0010 GETMBR R5 R0 K7 - 0x7C0C0400, // 0011 CALL R3 2 - 0x80000000, // 0012 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_bri -********************************************************************/ -be_local_closure(Animate_core_get_bri, /* name */ - be_nested_proto( - 3, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(bri), - }), - be_str_weak(get_bri), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x80040400, // 0001 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_bri -********************************************************************/ -be_local_closure(Animate_core_set_bri, /* name */ - be_nested_proto( - 4, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(bri), - /* K1 */ be_nested_str_weak(set_strip_bri), - }), - be_str_weak(set_bri), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x8C080101, // 0001 GETMET R2 R0 K1 - 0x7C080200, // 0002 CALL R2 1 - 0x80000000, // 0003 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: add_painter -********************************************************************/ -be_local_closure(Animate_core_add_painter, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(painters), - /* K1 */ be_nested_str_weak(find), - /* K2 */ be_nested_str_weak(push), - }), - be_str_weak(add_painter), - &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x4C0C0000, // 0004 LDNIL R3 - 0x1C080403, // 0005 EQ R2 R2 R3 - 0x780A0003, // 0006 JMPF R2 #000B - 0x88080100, // 0007 GETMBR R2 R0 K0 - 0x8C080502, // 0008 GETMET R2 R2 K2 - 0x5C100200, // 0009 MOVE R4 R1 - 0x7C080400, // 000A CALL R2 2 - 0x80000000, // 000B RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: fast_loop -********************************************************************/ -be_local_closure(Animate_core_fast_loop, /* name */ - be_nested_proto( - 13, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[28]) { /* constants */ - /* K0 */ be_nested_str_weak(running), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(time_reached), - /* K3 */ be_nested_str_weak(fast_loop_next), - /* K4 */ be_nested_str_weak(strip), - /* K5 */ be_nested_str_weak(can_show), - /* K6 */ be_nested_str_weak(frame), - /* K7 */ be_nested_str_weak(fill_pixels), - /* K8 */ be_nested_str_weak(back_color), - /* K9 */ be_const_int(0), - /* K10 */ be_nested_str_weak(millis), - /* K11 */ be_nested_str_weak(FAST_LOOP_MIN), - /* K12 */ be_nested_str_weak(animators), - /* K13 */ be_nested_str_weak(animate), - /* K14 */ be_const_int(1), - /* K15 */ be_nested_str_weak(layer), - /* K16 */ be_nested_str_weak(painters), - /* K17 */ be_const_int(-16777216), - /* K18 */ be_nested_str_weak(paint), - /* K19 */ be_nested_str_weak(blend_pixels), - /* K20 */ be_nested_str_weak(obj), - /* K21 */ be_nested_str_weak(mth), - /* K22 */ be_nested_str_weak(paste_pixels), - /* K23 */ be_nested_str_weak(pixels_buffer), - /* K24 */ be_nested_str_weak(get_bri), - /* K25 */ be_nested_str_weak(get_gamma), - /* K26 */ be_nested_str_weak(dirty), - /* K27 */ be_nested_str_weak(show), - }), - be_str_weak(fast_loop), - &be_const_str_solidified, - ( &(const binstruction[84]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x78060050, // 0001 JMPF R1 #0053 - 0xB8060200, // 0002 GETNGBL R1 K1 - 0x8C040302, // 0003 GETMET R1 R1 K2 - 0x880C0103, // 0004 GETMBR R3 R0 K3 - 0x7C040400, // 0005 CALL R1 2 - 0x7806004B, // 0006 JMPF R1 #0053 - 0x88040104, // 0007 GETMBR R1 R0 K4 - 0x8C040305, // 0008 GETMET R1 R1 K5 - 0x7C040200, // 0009 CALL R1 1 - 0x78060047, // 000A JMPF R1 #0053 - 0x88040106, // 000B GETMBR R1 R0 K6 - 0x8C040307, // 000C GETMET R1 R1 K7 - 0x880C0108, // 000D GETMBR R3 R0 K8 - 0x7C040400, // 000E CALL R1 2 - 0x58040009, // 000F LDCONST R1 K9 - 0xB80A0200, // 0010 GETNGBL R2 K1 - 0x8C08050A, // 0011 GETMET R2 R2 K10 - 0x7C080200, // 0012 CALL R2 1 - 0x880C010B, // 0013 GETMBR R3 R0 K11 - 0x000C0403, // 0014 ADD R3 R2 R3 - 0x90020603, // 0015 SETMBR R0 K3 R3 - 0x600C000C, // 0016 GETGBL R3 G12 - 0x8810010C, // 0017 GETMBR R4 R0 K12 - 0x7C0C0200, // 0018 CALL R3 1 - 0x140C0203, // 0019 LT R3 R1 R3 - 0x780E0006, // 001A JMPF R3 #0022 - 0x880C010C, // 001B GETMBR R3 R0 K12 - 0x940C0601, // 001C GETIDX R3 R3 R1 - 0x8C0C070D, // 001D GETMET R3 R3 K13 - 0x5C140400, // 001E MOVE R5 R2 - 0x7C0C0400, // 001F CALL R3 2 - 0x0004030E, // 0020 ADD R1 R1 K14 - 0x7001FFF3, // 0021 JMP #0016 - 0x58040009, // 0022 LDCONST R1 K9 - 0x880C0106, // 0023 GETMBR R3 R0 K6 - 0x8810010F, // 0024 GETMBR R4 R0 K15 - 0x6014000C, // 0025 GETGBL R5 G12 - 0x88180110, // 0026 GETMBR R6 R0 K16 - 0x7C140200, // 0027 CALL R5 1 - 0x14140205, // 0028 LT R5 R1 R5 - 0x7816000D, // 0029 JMPF R5 #0038 - 0x8C140907, // 002A GETMET R5 R4 K7 - 0x581C0011, // 002B LDCONST R7 K17 - 0x7C140400, // 002C CALL R5 2 - 0x88140110, // 002D GETMBR R5 R0 K16 - 0x94140A01, // 002E GETIDX R5 R5 R1 - 0x8C140B12, // 002F GETMET R5 R5 K18 - 0x5C1C0800, // 0030 MOVE R7 R4 - 0x7C140400, // 0031 CALL R5 2 - 0x78160002, // 0032 JMPF R5 #0036 - 0x8C140713, // 0033 GETMET R5 R3 K19 - 0x5C1C0800, // 0034 MOVE R7 R4 - 0x7C140400, // 0035 CALL R5 2 - 0x0004030E, // 0036 ADD R1 R1 K14 - 0x7001FFEC, // 0037 JMP #0025 - 0x88140114, // 0038 GETMBR R5 R0 K20 - 0x88180115, // 0039 GETMBR R6 R0 K21 - 0x78160003, // 003A JMPF R5 #003F - 0x781A0002, // 003B JMPF R6 #003F - 0x5C1C0C00, // 003C MOVE R7 R6 - 0x5C200A00, // 003D MOVE R8 R5 - 0x7C1C0200, // 003E CALL R7 1 - 0x8C1C010D, // 003F GETMET R7 R0 K13 - 0x7C1C0200, // 0040 CALL R7 1 - 0x881C0106, // 0041 GETMBR R7 R0 K6 - 0x8C1C0F16, // 0042 GETMET R7 R7 K22 - 0x88240104, // 0043 GETMBR R9 R0 K4 - 0x8C241317, // 0044 GETMET R9 R9 K23 - 0x7C240200, // 0045 CALL R9 1 - 0x88280104, // 0046 GETMBR R10 R0 K4 - 0x8C281518, // 0047 GETMET R10 R10 K24 - 0x7C280200, // 0048 CALL R10 1 - 0x882C0104, // 0049 GETMBR R11 R0 K4 - 0x8C2C1719, // 004A GETMET R11 R11 K25 - 0x7C2C0200, // 004B CALL R11 1 - 0x7C1C0800, // 004C CALL R7 4 - 0x881C0104, // 004D GETMBR R7 R0 K4 - 0x8C1C0F1A, // 004E GETMET R7 R7 K26 - 0x7C1C0200, // 004F CALL R7 1 - 0x881C0104, // 0050 GETMBR R7 R0 K4 - 0x8C1C0F1B, // 0051 GETMET R7 R7 K27 - 0x7C1C0200, // 0052 CALL R7 1 - 0x80000000, // 0053 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: remove_animator -********************************************************************/ -be_local_closure(Animate_core_remove_animator, /* name */ - be_nested_proto( - 8, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(animators), - /* K1 */ be_nested_str_weak(remove), - /* K2 */ be_nested_str_weak(find), - /* K3 */ be_nested_str_weak(clear), - }), - be_str_weak(remove_animator), - &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x200C0203, // 0002 NE R3 R1 R3 - 0x780E0005, // 0003 JMPF R3 #000A - 0x8C0C0501, // 0004 GETMET R3 R2 K1 - 0x8C140502, // 0005 GETMET R5 R2 K2 - 0x5C1C0200, // 0006 MOVE R7 R1 - 0x7C140400, // 0007 CALL R5 2 - 0x7C0C0400, // 0008 CALL R3 2 - 0x70020001, // 0009 JMP #000C - 0x8C0C0503, // 000A GETMET R3 R2 K3 - 0x7C0C0200, // 000B CALL R3 1 - 0x80000000, // 000C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: animate -********************************************************************/ -be_local_closure(Animate_core_animate, /* name */ - be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(animate), - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_current -********************************************************************/ -be_local_closure(Animate_core_set_current, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(global), - /* K1 */ be_nested_str_weak(_cur_anim), - }), - be_str_weak(set_current), - &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x90060200, // 0001 SETMBR R1 K1 R0 - 0x80000000, // 0002 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Animate_core_init, /* name */ - be_nested_proto( - 7, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 1]) { - be_nested_proto( - 2, /* nstack */ - 0, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(fast_loop), - }), - be_str_weak(_anonymous_), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x68000000, // 0000 GETUPV R0 U0 - 0x8C000100, // 0001 GETMET R0 R0 K0 - 0x7C000200, // 0002 CALL R0 1 - 0x80000000, // 0003 RET 0 - }) - ), - }), - 1, /* has constants */ - ( &(const bvalue[15]) { /* constants */ - /* K0 */ be_nested_str_weak(animate), - /* K1 */ be_nested_str_weak(strip), - /* K2 */ be_nested_str_weak(bri), - /* K3 */ be_nested_str_weak(set_strip_bri), - /* K4 */ be_nested_str_weak(running), - /* K5 */ be_nested_str_weak(pixel_count), - /* K6 */ be_nested_str_weak(animators), - /* K7 */ be_nested_str_weak(painters), - /* K8 */ be_nested_str_weak(clear), - /* K9 */ be_nested_str_weak(frame), - /* K10 */ be_nested_str_weak(layer), - /* K11 */ be_nested_str_weak(fast_loop_cb), - /* K12 */ be_nested_str_weak(back_color), - /* K13 */ be_const_int(0), - /* K14 */ be_nested_str_weak(set_current), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[37]) { /* code */ - 0xA40E0000, // 0000 IMPORT R3 K0 - 0x90020201, // 0001 SETMBR R0 K1 R1 - 0x4C100000, // 0002 LDNIL R4 - 0x1C100404, // 0003 EQ R4 R2 R4 - 0x78120000, // 0004 JMPF R4 #0006 - 0x540A0031, // 0005 LDINT R2 50 - 0x90020402, // 0006 SETMBR R0 K2 R2 - 0x8C100103, // 0007 GETMET R4 R0 K3 - 0x7C100200, // 0008 CALL R4 1 - 0x50100000, // 0009 LDBOOL R4 0 0 - 0x90020804, // 000A SETMBR R0 K4 R4 - 0x8C100305, // 000B GETMET R4 R1 K5 - 0x7C100200, // 000C CALL R4 1 - 0x90020A04, // 000D SETMBR R0 K5 R4 - 0x60100012, // 000E GETGBL R4 G18 - 0x7C100000, // 000F CALL R4 0 - 0x90020C04, // 0010 SETMBR R0 K6 R4 - 0x60100012, // 0011 GETGBL R4 G18 - 0x7C100000, // 0012 CALL R4 0 - 0x90020E04, // 0013 SETMBR R0 K7 R4 - 0x8C100108, // 0014 GETMET R4 R0 K8 - 0x7C100200, // 0015 CALL R4 1 - 0x8C100709, // 0016 GETMET R4 R3 K9 - 0x88180105, // 0017 GETMBR R6 R0 K5 - 0x7C100400, // 0018 CALL R4 2 - 0x90021204, // 0019 SETMBR R0 K9 R4 - 0x8C100709, // 001A GETMET R4 R3 K9 - 0x88180105, // 001B GETMBR R6 R0 K5 - 0x7C100400, // 001C CALL R4 2 - 0x90021404, // 001D SETMBR R0 K10 R4 - 0x84100000, // 001E CLOSURE R4 P0 - 0x90021604, // 001F SETMBR R0 K11 R4 - 0x9002190D, // 0020 SETMBR R0 K12 K13 - 0x8C10010E, // 0021 GETMET R4 R0 K14 - 0x7C100200, // 0022 CALL R4 1 - 0xA0000000, // 0023 CLOSE R0 - 0x80000000, // 0024 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_cb -********************************************************************/ -be_local_closure(Animate_core_set_cb, /* name */ - be_nested_proto( - 3, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(obj), - /* K1 */ be_nested_str_weak(mth), - }), - be_str_weak(set_cb), - &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x80000000, // 0002 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_back_color -********************************************************************/ -be_local_closure(Animate_core_set_back_color, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(back_color), - }), - be_str_weak(set_back_color), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: add_background_animator -********************************************************************/ -be_local_closure(Animate_core_add_background_animator, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(set_cb), - /* K1 */ be_nested_str_weak(set_back_color), - /* K2 */ be_nested_str_weak(add_animator), - }), - be_str_weak(add_background_animator), - &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x8C080300, // 0000 GETMET R2 R1 K0 - 0x5C100000, // 0001 MOVE R4 R0 - 0x88140101, // 0002 GETMBR R5 R0 K1 - 0x7C080600, // 0003 CALL R2 3 - 0x8C080102, // 0004 GETMET R2 R0 K2 - 0x5C100200, // 0005 MOVE R4 R1 - 0x7C080400, // 0006 CALL R2 2 - 0x80000000, // 0007 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: add_animator -********************************************************************/ -be_local_closure(Animate_core_add_animator, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(animators), - /* K1 */ be_nested_str_weak(find), - /* K2 */ be_nested_str_weak(push), - }), - be_str_weak(add_animator), - &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x4C0C0000, // 0004 LDNIL R3 - 0x1C080403, // 0005 EQ R2 R2 R3 - 0x780A0003, // 0006 JMPF R2 #000B - 0x88080100, // 0007 GETMBR R2 R0 K0 - 0x8C080502, // 0008 GETMET R2 R2 K2 - 0x5C100200, // 0009 MOVE R4 R1 - 0x7C080400, // 000A CALL R2 2 - 0x80000000, // 000B RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: remove -********************************************************************/ -be_local_closure(Animate_core_remove, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(clear), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(remove_fast_loop), - /* K3 */ be_nested_str_weak(fast_loop_cb), - }), - be_str_weak(remove), - &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0xB8060200, // 0002 GETNGBL R1 K1 - 0x8C040302, // 0003 GETMET R1 R1 K2 - 0x880C0103, // 0004 GETMBR R3 R0 K3 - 0x7C040400, // 0005 CALL R1 2 - 0x80000000, // 0006 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: start -********************************************************************/ -be_local_closure(Animate_core_start, /* name */ - be_nested_proto( - 6, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(running), - /* K1 */ be_nested_str_weak(animators), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(start), - /* K4 */ be_const_int(1), - /* K5 */ be_nested_str_weak(fast_loop_next), - /* K6 */ be_nested_str_weak(tasmota), - /* K7 */ be_nested_str_weak(add_fast_loop), - /* K8 */ be_nested_str_weak(fast_loop_cb), - }), - be_str_weak(start), - &be_const_str_solidified, - ( &(const binstruction[20]) { /* code */ - 0x50040200, // 0000 LDBOOL R1 1 0 - 0x90020001, // 0001 SETMBR R0 K0 R1 - 0x88040101, // 0002 GETMBR R1 R0 K1 - 0x58080002, // 0003 LDCONST R2 K2 - 0x600C000C, // 0004 GETGBL R3 G12 - 0x5C100200, // 0005 MOVE R4 R1 - 0x7C0C0200, // 0006 CALL R3 1 - 0x140C0403, // 0007 LT R3 R2 R3 - 0x780E0004, // 0008 JMPF R3 #000E - 0x940C0202, // 0009 GETIDX R3 R1 R2 - 0x8C0C0703, // 000A GETMET R3 R3 K3 - 0x7C0C0200, // 000B CALL R3 1 - 0x00080504, // 000C ADD R2 R2 K4 - 0x7001FFF5, // 000D JMP #0004 - 0x90020B02, // 000E SETMBR R0 K5 K2 - 0xB80E0C00, // 000F GETNGBL R3 K6 - 0x8C0C0707, // 0010 GETMET R3 R3 K7 - 0x88140108, // 0011 GETMBR R5 R0 K8 - 0x7C0C0400, // 0012 CALL R3 2 - 0x80000000, // 0013 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: Animate_core -********************************************************************/ -be_local_class(Animate_core, - 13, - NULL, - be_nested_map(32, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(set_strip_bri, -1), be_const_closure(Animate_core_set_strip_bri_closure) }, - { be_const_key_weak(animators, -1), be_const_var(4) }, - { be_const_key_weak(clear, 0), be_const_closure(Animate_core_clear_closure) }, - { be_const_key_weak(remove, -1), be_const_closure(Animate_core_remove_closure) }, - { be_const_key_weak(mth, -1), be_const_var(9) }, - { be_const_key_weak(stop, 1), be_const_closure(Animate_core_stop_closure) }, - { be_const_key_weak(fast_loop_cb, 30), be_const_var(6) }, - { be_const_key_weak(get_bri, -1), be_const_closure(Animate_core_get_bri_closure) }, - { be_const_key_weak(add_animator, -1), be_const_closure(Animate_core_add_animator_closure) }, - { be_const_key_weak(add_background_animator, -1), be_const_closure(Animate_core_add_background_animator_closure) }, - { be_const_key_weak(fast_loop_next, -1), be_const_var(7) }, - { be_const_key_weak(remove_animator, -1), be_const_closure(Animate_core_remove_animator_closure) }, - { be_const_key_weak(add_painter, 28), be_const_closure(Animate_core_add_painter_closure) }, - { be_const_key_weak(FAST_LOOP_MIN, -1), be_const_int(20) }, - { be_const_key_weak(fast_loop, -1), be_const_closure(Animate_core_fast_loop_closure) }, - { be_const_key_weak(set_back_color, 11), be_const_closure(Animate_core_set_back_color_closure) }, - { be_const_key_weak(animate, 8), be_const_closure(Animate_core_animate_closure) }, - { be_const_key_weak(strip, 24), be_const_var(0) }, - { be_const_key_weak(layer, -1), be_const_var(11) }, - { be_const_key_weak(init, -1), be_const_closure(Animate_core_init_closure) }, - { be_const_key_weak(bri, -1), be_const_var(2) }, - { be_const_key_weak(set_cb, 13), be_const_closure(Animate_core_set_cb_closure) }, - { be_const_key_weak(back_color, 18), be_const_var(12) }, - { be_const_key_weak(pixel_count, 15), be_const_var(1) }, - { be_const_key_weak(set_current, -1), be_const_closure(Animate_core_set_current_closure) }, - { be_const_key_weak(painters, -1), be_const_var(5) }, - { be_const_key_weak(obj, 10), be_const_var(8) }, - { be_const_key_weak(set_bri, 9), be_const_closure(Animate_core_set_bri_closure) }, - { be_const_key_weak(running, -1), be_const_var(3) }, - { be_const_key_weak(remove_painter, 3), be_const_closure(Animate_core_remove_painter_closure) }, - { be_const_key_weak(frame, -1), be_const_var(10) }, - { be_const_key_weak(start, -1), be_const_closure(Animate_core_start_closure) }, - })), - be_str_weak(Animate_core) -); -/*******************************************************************/ - -void be_load_Animate_core_class(bvm *vm) { - be_pushntvclass(vm, &be_class_Animate_core); - be_setglobal(vm, "Animate_core"); - be_pop(vm, 1); -} -/********************************************************************/ -/* End of solidification */ diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_2_animate_effects.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_2_animate_effects.h deleted file mode 100644 index 360e3d2d8..000000000 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_2_animate_effects.h +++ /dev/null @@ -1,450 +0,0 @@ -/* Solidification of animate_2_animate_effects.h */ -/********************************************************************\ -* Generated code, don't edit * -\********************************************************************/ -#include "be_constobj.h" - -extern const bclass be_class_Animate_painter; - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Animate_painter_init, /* name */ - be_nested_proto( - 5, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(global), - /* K1 */ be_nested_str_weak(_cur_anim), - /* K2 */ be_nested_str_weak(add_painter), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x88040301, // 0001 GETMBR R1 R1 K1 - 0x4C080000, // 0002 LDNIL R2 - 0x20080202, // 0003 NE R2 R1 R2 - 0x780A0002, // 0004 JMPF R2 #0008 - 0x8C080302, // 0005 GETMET R2 R1 K2 - 0x5C100000, // 0006 MOVE R4 R0 - 0x7C080400, // 0007 CALL R2 2 - 0x80000000, // 0008 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: paint -********************************************************************/ -be_local_closure(Animate_painter_paint, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(paint), - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: Animate_painter -********************************************************************/ -be_local_class(Animate_painter, - 0, - NULL, - be_nested_map(2, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(paint, -1), be_const_closure(Animate_painter_paint_closure) }, - { be_const_key_weak(init, 0), be_const_closure(Animate_painter_init_closure) }, - })), - be_str_weak(Animate_painter) -); -/*******************************************************************/ - -void be_load_Animate_painter_class(bvm *vm) { - be_pushntvclass(vm, &be_class_Animate_painter); - be_setglobal(vm, "Animate_painter"); - be_pop(vm, 1); -} - -extern const bclass be_class_Animate_pulse; - -/******************************************************************** -** Solidified function: set_pulse_size -********************************************************************/ -be_local_closure(Animate_pulse_set_pulse_size, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(pulse_size), - }), - be_str_weak(set_pulse_size), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_slew_size -********************************************************************/ -be_local_closure(Animate_pulse_set_slew_size, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(slew_size), - }), - be_str_weak(set_slew_size), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_back_color -********************************************************************/ -be_local_closure(Animate_pulse_set_back_color, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(back_color), - }), - be_str_weak(set_back_color), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_pos -********************************************************************/ -be_local_closure(Animate_pulse_set_pos, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(pos), - }), - be_str_weak(set_pos), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_color -********************************************************************/ -be_local_closure(Animate_pulse_set_color, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(color), - }), - be_str_weak(set_color), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Animate_pulse_init, /* name */ - be_nested_proto( - 6, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[10]) { /* constants */ - /* K0 */ be_nested_str_weak(init), - /* K1 */ be_const_int(16777215), - /* K2 */ be_const_int(1), - /* K3 */ be_const_int(0), - /* K4 */ be_nested_str_weak(color), - /* K5 */ be_nested_str_weak(back_color), - /* K6 */ be_const_int(-16777216), - /* K7 */ be_nested_str_weak(pulse_size), - /* K8 */ be_nested_str_weak(slew_size), - /* K9 */ be_nested_str_weak(pos), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[29]) { /* code */ - 0x60100003, // 0000 GETGBL R4 G3 - 0x5C140000, // 0001 MOVE R5 R0 - 0x7C100200, // 0002 CALL R4 1 - 0x8C100900, // 0003 GETMET R4 R4 K0 - 0x7C100200, // 0004 CALL R4 1 - 0x4C100000, // 0005 LDNIL R4 - 0x1C100204, // 0006 EQ R4 R1 R4 - 0x78120000, // 0007 JMPF R4 #0009 - 0x58040001, // 0008 LDCONST R1 K1 - 0x4C100000, // 0009 LDNIL R4 - 0x1C100404, // 000A EQ R4 R2 R4 - 0x78120000, // 000B JMPF R4 #000D - 0x58080002, // 000C LDCONST R2 K2 - 0x4C100000, // 000D LDNIL R4 - 0x1C100604, // 000E EQ R4 R3 R4 - 0x78120000, // 000F JMPF R4 #0011 - 0x580C0003, // 0010 LDCONST R3 K3 - 0x90020801, // 0011 SETMBR R0 K4 R1 - 0x90020B06, // 0012 SETMBR R0 K5 K6 - 0x14100503, // 0013 LT R4 R2 K3 - 0x78120000, // 0014 JMPF R4 #0016 - 0x58080003, // 0015 LDCONST R2 K3 - 0x90020E02, // 0016 SETMBR R0 K7 R2 - 0x14100703, // 0017 LT R4 R3 K3 - 0x78120000, // 0018 JMPF R4 #001A - 0x580C0003, // 0019 LDCONST R3 K3 - 0x90021003, // 001A SETMBR R0 K8 R3 - 0x90021303, // 001B SETMBR R0 K9 K3 - 0x80000000, // 001C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: paint -********************************************************************/ -be_local_closure(Animate_pulse_paint, /* name */ - be_nested_proto( - 22, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[13]) { /* constants */ - /* K0 */ be_nested_str_weak(back_color), - /* K1 */ be_const_int(-16777216), - /* K2 */ be_nested_str_weak(fill_pixels), - /* K3 */ be_nested_str_weak(pos), - /* K4 */ be_nested_str_weak(slew_size), - /* K5 */ be_nested_str_weak(pulse_size), - /* K6 */ be_nested_str_weak(color), - /* K7 */ be_nested_str_weak(pixel_size), - /* K8 */ be_const_int(0), - /* K9 */ be_const_int(1), - /* K10 */ be_nested_str_weak(blend), - /* K11 */ be_nested_str_weak(tasmota), - /* K12 */ be_nested_str_weak(scale_int), - }), - be_str_weak(paint), - &be_const_str_solidified, - ( &(const binstruction[91]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x200C0501, // 0001 NE R3 R2 K1 - 0x780E0002, // 0002 JMPF R3 #0006 - 0x8C0C0302, // 0003 GETMET R3 R1 K2 - 0x5C140400, // 0004 MOVE R5 R2 - 0x7C0C0400, // 0005 CALL R3 2 - 0x880C0103, // 0006 GETMBR R3 R0 K3 - 0x88100104, // 0007 GETMBR R4 R0 K4 - 0x88140105, // 0008 GETMBR R5 R0 K5 - 0x88180106, // 0009 GETMBR R6 R0 K6 - 0x881C0307, // 000A GETMBR R7 R1 K7 - 0x4C200000, // 000B LDNIL R8 - 0x4C240000, // 000C LDNIL R9 - 0x5C200600, // 000D MOVE R8 R3 - 0x00280605, // 000E ADD R10 R3 R5 - 0x5C241400, // 000F MOVE R9 R10 - 0x14281108, // 0010 LT R10 R8 K8 - 0x782A0000, // 0011 JMPF R10 #0013 - 0x58200008, // 0012 LDCONST R8 K8 - 0x28281207, // 0013 GE R10 R9 R7 - 0x782A0000, // 0014 JMPF R10 #0016 - 0x5C240E00, // 0015 MOVE R9 R7 - 0x5C281000, // 0016 MOVE R10 R8 - 0x142C1409, // 0017 LT R11 R10 R9 - 0x782E0002, // 0018 JMPF R11 #001C - 0x98041406, // 0019 SETIDX R1 R10 R6 - 0x00281509, // 001A ADD R10 R10 K9 - 0x7001FFFA, // 001B JMP #0017 - 0x242C0908, // 001C GT R11 R4 K8 - 0x782E003A, // 001D JMPF R11 #0059 - 0x042C0604, // 001E SUB R11 R3 R4 - 0x5C201600, // 001F MOVE R8 R11 - 0x5C240600, // 0020 MOVE R9 R3 - 0x142C1108, // 0021 LT R11 R8 K8 - 0x782E0000, // 0022 JMPF R11 #0024 - 0x58200008, // 0023 LDCONST R8 K8 - 0x282C1207, // 0024 GE R11 R9 R7 - 0x782E0000, // 0025 JMPF R11 #0027 - 0x5C240E00, // 0026 MOVE R9 R7 - 0x5C281000, // 0027 MOVE R10 R8 - 0x142C1409, // 0028 LT R11 R10 R9 - 0x782E000F, // 0029 JMPF R11 #003A - 0x8C2C030A, // 002A GETMET R11 R1 K10 - 0x5C340400, // 002B MOVE R13 R2 - 0x5C380C00, // 002C MOVE R14 R6 - 0xB83E1600, // 002D GETNGBL R15 K11 - 0x8C3C1F0C, // 002E GETMET R15 R15 K12 - 0x5C441400, // 002F MOVE R17 R10 - 0x04480604, // 0030 SUB R18 R3 R4 - 0x04482509, // 0031 SUB R18 R18 K9 - 0x5C4C0600, // 0032 MOVE R19 R3 - 0x545200FE, // 0033 LDINT R20 255 - 0x58540008, // 0034 LDCONST R21 K8 - 0x7C3C0C00, // 0035 CALL R15 6 - 0x7C2C0800, // 0036 CALL R11 4 - 0x9804140B, // 0037 SETIDX R1 R10 R11 - 0x00281509, // 0038 ADD R10 R10 K9 - 0x7001FFED, // 0039 JMP #0028 - 0x002C0605, // 003A ADD R11 R3 R5 - 0x5C201600, // 003B MOVE R8 R11 - 0x002C0605, // 003C ADD R11 R3 R5 - 0x002C1604, // 003D ADD R11 R11 R4 - 0x5C241600, // 003E MOVE R9 R11 - 0x142C1108, // 003F LT R11 R8 K8 - 0x782E0000, // 0040 JMPF R11 #0042 - 0x58200008, // 0041 LDCONST R8 K8 - 0x282C1207, // 0042 GE R11 R9 R7 - 0x782E0000, // 0043 JMPF R11 #0045 - 0x5C240E00, // 0044 MOVE R9 R7 - 0x5C281000, // 0045 MOVE R10 R8 - 0x142C1409, // 0046 LT R11 R10 R9 - 0x782E0010, // 0047 JMPF R11 #0059 - 0x8C2C030A, // 0048 GETMET R11 R1 K10 - 0x5C340400, // 0049 MOVE R13 R2 - 0x5C380C00, // 004A MOVE R14 R6 - 0xB83E1600, // 004B GETNGBL R15 K11 - 0x8C3C1F0C, // 004C GETMET R15 R15 K12 - 0x5C441400, // 004D MOVE R17 R10 - 0x00480605, // 004E ADD R18 R3 R5 - 0x04482509, // 004F SUB R18 R18 K9 - 0x004C0605, // 0050 ADD R19 R3 R5 - 0x004C2604, // 0051 ADD R19 R19 R4 - 0x58500008, // 0052 LDCONST R20 K8 - 0x545600FE, // 0053 LDINT R21 255 - 0x7C3C0C00, // 0054 CALL R15 6 - 0x7C2C0800, // 0055 CALL R11 4 - 0x9804140B, // 0056 SETIDX R1 R10 R11 - 0x00281509, // 0057 ADD R10 R10 K9 - 0x7001FFEC, // 0058 JMP #0046 - 0x502C0200, // 0059 LDBOOL R11 1 0 - 0x80041600, // 005A RET 1 R11 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: Animate_pulse -********************************************************************/ -extern const bclass be_class_Animate_painter; -be_local_class(Animate_pulse, - 5, - &be_class_Animate_painter, - be_nested_map(12, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(paint, -1), be_const_closure(Animate_pulse_paint_closure) }, - { be_const_key_weak(set_slew_size, -1), be_const_closure(Animate_pulse_set_slew_size_closure) }, - { be_const_key_weak(pulse_size, -1), be_const_var(4) }, - { be_const_key_weak(set_back_color, 8), be_const_closure(Animate_pulse_set_back_color_closure) }, - { be_const_key_weak(color, -1), be_const_var(0) }, - { be_const_key_weak(back_color, -1), be_const_var(1) }, - { be_const_key_weak(set_pos, -1), be_const_closure(Animate_pulse_set_pos_closure) }, - { be_const_key_weak(set_color, -1), be_const_closure(Animate_pulse_set_color_closure) }, - { be_const_key_weak(init, 7), be_const_closure(Animate_pulse_init_closure) }, - { be_const_key_weak(pos, -1), be_const_var(2) }, - { be_const_key_weak(slew_size, 5), be_const_var(3) }, - { be_const_key_weak(set_pulse_size, 0), be_const_closure(Animate_pulse_set_pulse_size_closure) }, - })), - be_str_weak(Animate_pulse) -); -/*******************************************************************/ - -void be_load_Animate_pulse_class(bvm *vm) { - be_pushntvclass(vm, &be_class_Animate_pulse); - be_setglobal(vm, "Animate_pulse"); - be_pop(vm, 1); -} -/********************************************************************/ -/* End of solidification */ diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h deleted file mode 100644 index e64059188..000000000 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_animate_9_module.h +++ /dev/null @@ -1,1592 +0,0 @@ -/* Solidification of animate_9_module.h */ -/********************************************************************\ -* Generated code, don't edit * -\********************************************************************/ -#include "be_constobj.h" - -extern const bclass be_class_Animate_animator; - -/******************************************************************** -** Solidified function: is_running -********************************************************************/ -be_local_closure(Animate_animator_is_running, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(running), - }), - be_str_weak(is_running), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x60040017, // 0000 GETGBL R1 G23 - 0x88080100, // 0001 GETMBR R2 R0 K0 - 0x7C040200, // 0002 CALL R1 1 - 0x80040200, // 0003 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: beat -********************************************************************/ -be_local_closure(Animate_animator_beat, /* name */ - be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(beat), - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Animate_animator_init, /* name */ - be_nested_proto( - 5, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(global), - /* K1 */ be_nested_str_weak(_cur_anim), - /* K2 */ be_nested_str_weak(add_animator), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x88040301, // 0001 GETMBR R1 R1 K1 - 0x4C080000, // 0002 LDNIL R2 - 0x20080202, // 0003 NE R2 R1 R2 - 0x780A0002, // 0004 JMPF R2 #0008 - 0x8C080302, // 0005 GETMET R2 R1 K2 - 0x5C100000, // 0006 MOVE R4 R0 - 0x7C080400, // 0007 CALL R2 2 - 0x80000000, // 0008 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: stop -********************************************************************/ -be_local_closure(Animate_animator_stop, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(origin), - /* K1 */ be_nested_str_weak(running), - }), - be_str_weak(stop), - &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x4C040000, // 0000 LDNIL R1 - 0x90020001, // 0001 SETMBR R0 K0 R1 - 0x50040000, // 0002 LDBOOL R1 0 0 - 0x90020201, // 0003 SETMBR R0 K1 R1 - 0x80000000, // 0004 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_duration_ms -********************************************************************/ -be_local_closure(Animate_animator_set_duration_ms, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(duration_ms), - }), - be_str_weak(set_duration_ms), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_cb -********************************************************************/ -be_local_closure(Animate_animator_set_cb, /* name */ - be_nested_proto( - 3, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(obj), - /* K1 */ be_nested_str_weak(mth), - }), - be_str_weak(set_cb), - &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x80000000, // 0002 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: start -********************************************************************/ -be_local_closure(Animate_animator_start, /* name */ - be_nested_proto( - 4, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(duration_ms), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(millis), - /* K3 */ be_nested_str_weak(origin), - /* K4 */ be_nested_str_weak(running), - }), - be_str_weak(start), - &be_const_str_solidified, - ( &(const binstruction[16]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x1C080403, // 0002 EQ R2 R2 R3 - 0x780A0000, // 0003 JMPF R2 #0005 - 0x80000400, // 0004 RET 0 - 0x4C080000, // 0005 LDNIL R2 - 0x1C080202, // 0006 EQ R2 R1 R2 - 0x780A0003, // 0007 JMPF R2 #000C - 0xB80A0200, // 0008 GETNGBL R2 K1 - 0x8C080502, // 0009 GETMET R2 R2 K2 - 0x7C080200, // 000A CALL R2 1 - 0x5C040400, // 000B MOVE R1 R2 - 0x90020601, // 000C SETMBR R0 K3 R1 - 0x50080200, // 000D LDBOOL R2 1 0 - 0x90020802, // 000E SETMBR R0 K4 R2 - 0x80000000, // 000F RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: Animate_animator -********************************************************************/ -be_local_class(Animate_animator, - 5, - NULL, - be_nested_map(12, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(running, 4), be_const_var(0) }, - { be_const_key_weak(is_running, 2), be_const_closure(Animate_animator_is_running_closure) }, - { be_const_key_weak(beat, -1), be_const_closure(Animate_animator_beat_closure) }, - { be_const_key_weak(init, -1), be_const_closure(Animate_animator_init_closure) }, - { be_const_key_weak(mth, -1), be_const_var(4) }, - { be_const_key_weak(stop, -1), be_const_closure(Animate_animator_stop_closure) }, - { be_const_key_weak(duration_ms, -1), be_const_var(1) }, - { be_const_key_weak(origin, -1), be_const_var(2) }, - { be_const_key_weak(set_cb, -1), be_const_closure(Animate_animator_set_cb_closure) }, - { be_const_key_weak(set_duration_ms, 8), be_const_closure(Animate_animator_set_duration_ms_closure) }, - { be_const_key_weak(obj, -1), be_const_var(3) }, - { be_const_key_weak(start, -1), be_const_closure(Animate_animator_start_closure) }, - })), - be_str_weak(Animate_animator) -); -/*******************************************************************/ - -void be_load_Animate_animator_class(bvm *vm) { - be_pushntvclass(vm, &be_class_Animate_animator); - be_setglobal(vm, "Animate_animator"); - be_pop(vm, 1); -} - -extern const bclass be_class_Animate_palette; - -/******************************************************************** -** Solidified function: ptr_to_palette -********************************************************************/ -be_local_closure(Animate_palette_ptr_to_palette, /* name */ - be_nested_proto( - 8, /* nstack */ - 1, /* argc */ - 4, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_const_class(be_class_Animate_palette), - /* K1 */ be_nested_str_weak(ptr), - /* K2 */ be_const_int(1), - /* K3 */ be_const_int(0), - }), - be_str_weak(ptr_to_palette), - &be_const_str_solidified, - ( &(const binstruction[45]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x60080004, // 0001 GETGBL R2 G4 - 0x5C0C0000, // 0002 MOVE R3 R0 - 0x7C080200, // 0003 CALL R2 1 - 0x1C080501, // 0004 EQ R2 R2 K1 - 0x780A0025, // 0005 JMPF R2 #002C - 0x60080015, // 0006 GETGBL R2 G21 - 0x5C0C0000, // 0007 MOVE R3 R0 - 0x541207CF, // 0008 LDINT R4 2000 - 0x7C080400, // 0009 CALL R2 2 - 0x580C0002, // 000A LDCONST R3 K2 - 0x94100503, // 000B GETIDX R4 R2 K3 - 0x20100903, // 000C NE R4 R4 K3 - 0x7812000A, // 000D JMPF R4 #0019 - 0x50100200, // 000E LDBOOL R4 1 0 - 0x78120007, // 000F JMPF R4 #0018 - 0x54120003, // 0010 LDINT R4 4 - 0x08100604, // 0011 MUL R4 R3 R4 - 0x94100404, // 0012 GETIDX R4 R2 R4 - 0x1C100903, // 0013 EQ R4 R4 K3 - 0x78120000, // 0014 JMPF R4 #0016 - 0x70020001, // 0015 JMP #0018 - 0x000C0702, // 0016 ADD R3 R3 K2 - 0x7001FFF5, // 0017 JMP #000E - 0x7002000A, // 0018 JMP #0024 - 0x50100200, // 0019 LDBOOL R4 1 0 - 0x78120008, // 001A JMPF R4 #0024 - 0x54120003, // 001B LDINT R4 4 - 0x08100604, // 001C MUL R4 R3 R4 - 0x94100404, // 001D GETIDX R4 R2 R4 - 0x541600FE, // 001E LDINT R5 255 - 0x1C100805, // 001F EQ R4 R4 R5 - 0x78120000, // 0020 JMPF R4 #0022 - 0x70020001, // 0021 JMP #0024 - 0x000C0702, // 0022 ADD R3 R3 K2 - 0x7001FFF4, // 0023 JMP #0019 - 0x00100702, // 0024 ADD R4 R3 K2 - 0x54160003, // 0025 LDINT R5 4 - 0x08100805, // 0026 MUL R4 R4 R5 - 0x60140015, // 0027 GETGBL R5 G21 - 0x5C180000, // 0028 MOVE R6 R0 - 0x5C1C0800, // 0029 MOVE R7 R4 - 0x7C140400, // 002A CALL R5 2 - 0x80040A00, // 002B RET 1 R5 - 0x80000000, // 002C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: animate -********************************************************************/ -be_local_closure(Animate_palette_animate, /* name */ - be_nested_proto( - 26, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[21]) { /* constants */ - /* K0 */ be_nested_str_weak(duration_ms), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(millis), - /* K3 */ be_nested_str_weak(origin), - /* K4 */ be_const_int(0), - /* K5 */ be_nested_str_weak(scale_uint), - /* K6 */ be_nested_str_weak(slots), - /* K7 */ be_const_int(2), - /* K8 */ be_nested_str_weak(slots_arr), - /* K9 */ be_const_int(1), - /* K10 */ be_nested_str_weak(palette), - /* K11 */ be_nested_str_weak(get), - /* K12 */ be_nested_str_weak(color), - /* K13 */ be_nested_str_weak(set_rgb), - /* K14 */ be_nested_str_weak(bri), - /* K15 */ be_nested_str_weak(set_bri), - /* K16 */ be_nested_str_weak(r), - /* K17 */ be_nested_str_weak(g), - /* K18 */ be_nested_str_weak(b), - /* K19 */ be_nested_str_weak(obj), - /* K20 */ be_nested_str_weak(mth), - }), - be_str_weak(animate), - &be_const_str_solidified, - ( &(const binstruction[193]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x1C080403, // 0002 EQ R2 R2 R3 - 0x780A0000, // 0003 JMPF R2 #0005 - 0x80000400, // 0004 RET 0 - 0x4C080000, // 0005 LDNIL R2 - 0x1C080202, // 0006 EQ R2 R1 R2 - 0x780A0003, // 0007 JMPF R2 #000C - 0xB80A0200, // 0008 GETNGBL R2 K1 - 0x8C080502, // 0009 GETMET R2 R2 K2 - 0x7C080200, // 000A CALL R2 1 - 0x5C040400, // 000B MOVE R1 R2 - 0x88080103, // 000C GETMBR R2 R0 K3 - 0x04080202, // 000D SUB R2 R1 R2 - 0x140C0504, // 000E LT R3 R2 K4 - 0x780E0001, // 000F JMPF R3 #0012 - 0x58080004, // 0010 LDCONST R2 K4 - 0x88040103, // 0011 GETMBR R1 R0 K3 - 0x880C0100, // 0012 GETMBR R3 R0 K0 - 0xB8120200, // 0013 GETNGBL R4 K1 - 0x88100905, // 0014 GETMBR R4 R4 K5 - 0x28140403, // 0015 GE R5 R2 R3 - 0x78160005, // 0016 JMPF R5 #001D - 0x0C180403, // 0017 DIV R6 R2 R3 - 0x08180C03, // 0018 MUL R6 R6 R3 - 0x88140103, // 0019 GETMBR R5 R0 K3 - 0x00140A06, // 001A ADD R5 R5 R6 - 0x90020605, // 001B SETMBR R0 K3 R5 - 0x10080403, // 001C MOD R2 R2 R3 - 0x88140106, // 001D GETMBR R5 R0 K6 - 0x04180B07, // 001E SUB R6 R5 K7 - 0x241C0D04, // 001F GT R7 R6 K4 - 0x781E0006, // 0020 JMPF R7 #0028 - 0x881C0108, // 0021 GETMBR R7 R0 K8 - 0x941C0E06, // 0022 GETIDX R7 R7 R6 - 0x281C0407, // 0023 GE R7 R2 R7 - 0x781E0000, // 0024 JMPF R7 #0026 - 0x70020001, // 0025 JMP #0028 - 0x04180D09, // 0026 SUB R6 R6 K9 - 0x7001FFF6, // 0027 JMP #001F - 0x881C010A, // 0028 GETMBR R7 R0 K10 - 0x8C1C0F0B, // 0029 GETMET R7 R7 K11 - 0x54260003, // 002A LDINT R9 4 - 0x08240C09, // 002B MUL R9 R6 R9 - 0x542A0003, // 002C LDINT R10 4 - 0x7C1C0600, // 002D CALL R7 3 - 0x8820010A, // 002E GETMBR R8 R0 K10 - 0x8C20110B, // 002F GETMET R8 R8 K11 - 0x00280D09, // 0030 ADD R10 R6 K9 - 0x542E0003, // 0031 LDINT R11 4 - 0x0828140B, // 0032 MUL R10 R10 R11 - 0x542E0003, // 0033 LDINT R11 4 - 0x7C200600, // 0034 CALL R8 3 - 0x88240108, // 0035 GETMBR R9 R0 K8 - 0x94241206, // 0036 GETIDX R9 R9 R6 - 0x00280D09, // 0037 ADD R10 R6 K9 - 0x882C0108, // 0038 GETMBR R11 R0 K8 - 0x9428160A, // 0039 GETIDX R10 R11 R10 - 0x5C300800, // 003A MOVE R12 R4 - 0x5C340400, // 003B MOVE R13 R2 - 0x5C381200, // 003C MOVE R14 R9 - 0x5C3C1400, // 003D MOVE R15 R10 - 0x54420007, // 003E LDINT R16 8 - 0x3C400E10, // 003F SHR R16 R7 R16 - 0x544600FE, // 0040 LDINT R17 255 - 0x2C402011, // 0041 AND R16 R16 R17 - 0x54460007, // 0042 LDINT R17 8 - 0x3C441011, // 0043 SHR R17 R8 R17 - 0x544A00FE, // 0044 LDINT R18 255 - 0x2C442212, // 0045 AND R17 R17 R18 - 0x7C300A00, // 0046 CALL R12 5 - 0x5C2C1800, // 0047 MOVE R11 R12 - 0x5C300800, // 0048 MOVE R12 R4 - 0x5C340400, // 0049 MOVE R13 R2 - 0x5C381200, // 004A MOVE R14 R9 - 0x5C3C1400, // 004B MOVE R15 R10 - 0x5442000F, // 004C LDINT R16 16 - 0x3C400E10, // 004D SHR R16 R7 R16 - 0x544600FE, // 004E LDINT R17 255 - 0x2C402011, // 004F AND R16 R16 R17 - 0x5446000F, // 0050 LDINT R17 16 - 0x3C441011, // 0051 SHR R17 R8 R17 - 0x544A00FE, // 0052 LDINT R18 255 - 0x2C442212, // 0053 AND R17 R17 R18 - 0x7C300A00, // 0054 CALL R12 5 - 0x5C340800, // 0055 MOVE R13 R4 - 0x5C380400, // 0056 MOVE R14 R2 - 0x5C3C1200, // 0057 MOVE R15 R9 - 0x5C401400, // 0058 MOVE R16 R10 - 0x54460017, // 0059 LDINT R17 24 - 0x3C440E11, // 005A SHR R17 R7 R17 - 0x544A00FE, // 005B LDINT R18 255 - 0x2C442212, // 005C AND R17 R17 R18 - 0x544A0017, // 005D LDINT R18 24 - 0x3C481012, // 005E SHR R18 R8 R18 - 0x544E00FE, // 005F LDINT R19 255 - 0x2C482413, // 0060 AND R18 R18 R19 - 0x7C340A00, // 0061 CALL R13 5 - 0x8838010C, // 0062 GETMBR R14 R0 K12 - 0x8C3C1D0D, // 0063 GETMET R15 R14 K13 - 0x54460007, // 0064 LDINT R17 8 - 0x3C440E11, // 0065 SHR R17 R7 R17 - 0x544A00FE, // 0066 LDINT R18 255 - 0x2C442212, // 0067 AND R17 R17 R18 - 0x544A000F, // 0068 LDINT R18 16 - 0x3C480E12, // 0069 SHR R18 R7 R18 - 0x544E00FE, // 006A LDINT R19 255 - 0x2C482413, // 006B AND R18 R18 R19 - 0x544E0017, // 006C LDINT R19 24 - 0x3C4C0E13, // 006D SHR R19 R7 R19 - 0x545200FE, // 006E LDINT R20 255 - 0x2C4C2614, // 006F AND R19 R19 R20 - 0x7C3C0800, // 0070 CALL R15 4 - 0x883C1D0E, // 0071 GETMBR R15 R14 K14 - 0x8C401D0D, // 0072 GETMET R16 R14 K13 - 0x544A0007, // 0073 LDINT R18 8 - 0x3C481012, // 0074 SHR R18 R8 R18 - 0x544E00FE, // 0075 LDINT R19 255 - 0x2C482413, // 0076 AND R18 R18 R19 - 0x544E000F, // 0077 LDINT R19 16 - 0x3C4C1013, // 0078 SHR R19 R8 R19 - 0x545200FE, // 0079 LDINT R20 255 - 0x2C4C2614, // 007A AND R19 R19 R20 - 0x54520017, // 007B LDINT R20 24 - 0x3C501014, // 007C SHR R20 R8 R20 - 0x545600FE, // 007D LDINT R21 255 - 0x2C502815, // 007E AND R20 R20 R21 - 0x7C400800, // 007F CALL R16 4 - 0x88401D0E, // 0080 GETMBR R16 R14 K14 - 0x5C440800, // 0081 MOVE R17 R4 - 0x5C480400, // 0082 MOVE R18 R2 - 0x5C4C1200, // 0083 MOVE R19 R9 - 0x5C501400, // 0084 MOVE R20 R10 - 0x5C541E00, // 0085 MOVE R21 R15 - 0x5C582000, // 0086 MOVE R22 R16 - 0x7C440A00, // 0087 CALL R17 5 - 0x8C481D0D, // 0088 GETMET R18 R14 K13 - 0x5C501600, // 0089 MOVE R20 R11 - 0x5C541800, // 008A MOVE R21 R12 - 0x5C581A00, // 008B MOVE R22 R13 - 0x7C480800, // 008C CALL R18 4 - 0x8C481D0F, // 008D GETMET R18 R14 K15 - 0x5C502200, // 008E MOVE R20 R17 - 0x7C480400, // 008F CALL R18 2 - 0x882C1D10, // 0090 GETMBR R11 R14 K16 - 0x88301D11, // 0091 GETMBR R12 R14 K17 - 0x88341D12, // 0092 GETMBR R13 R14 K18 - 0x8848010E, // 0093 GETMBR R18 R0 K14 - 0x544E0063, // 0094 LDINT R19 100 - 0x204C2413, // 0095 NE R19 R18 R19 - 0x784E001A, // 0096 JMPF R19 #00B2 - 0xB84E0200, // 0097 GETNGBL R19 K1 - 0x8C4C2705, // 0098 GETMET R19 R19 K5 - 0x5C541600, // 0099 MOVE R21 R11 - 0x58580004, // 009A LDCONST R22 K4 - 0x545E0063, // 009B LDINT R23 100 - 0x58600004, // 009C LDCONST R24 K4 - 0x5C642400, // 009D MOVE R25 R18 - 0x7C4C0C00, // 009E CALL R19 6 - 0x5C2C2600, // 009F MOVE R11 R19 - 0xB84E0200, // 00A0 GETNGBL R19 K1 - 0x8C4C2705, // 00A1 GETMET R19 R19 K5 - 0x5C541800, // 00A2 MOVE R21 R12 - 0x58580004, // 00A3 LDCONST R22 K4 - 0x545E0063, // 00A4 LDINT R23 100 - 0x58600004, // 00A5 LDCONST R24 K4 - 0x5C642400, // 00A6 MOVE R25 R18 - 0x7C4C0C00, // 00A7 CALL R19 6 - 0x5C302600, // 00A8 MOVE R12 R19 - 0xB84E0200, // 00A9 GETNGBL R19 K1 - 0x8C4C2705, // 00AA GETMET R19 R19 K5 - 0x5C541A00, // 00AB MOVE R21 R13 - 0x58580004, // 00AC LDCONST R22 K4 - 0x545E0063, // 00AD LDINT R23 100 - 0x58600004, // 00AE LDCONST R24 K4 - 0x5C642400, // 00AF MOVE R25 R18 - 0x7C4C0C00, // 00B0 CALL R19 6 - 0x5C342600, // 00B1 MOVE R13 R19 - 0x544E000F, // 00B2 LDINT R19 16 - 0x384C1613, // 00B3 SHL R19 R11 R19 - 0x54520007, // 00B4 LDINT R20 8 - 0x38501814, // 00B5 SHL R20 R12 R20 - 0x304C2614, // 00B6 OR R19 R19 R20 - 0x304C260D, // 00B7 OR R19 R19 R13 - 0x88500113, // 00B8 GETMBR R20 R0 K19 - 0x88540114, // 00B9 GETMBR R21 R0 K20 - 0x78520004, // 00BA JMPF R20 #00C0 - 0x78560003, // 00BB JMPF R21 #00C0 - 0x5C582A00, // 00BC MOVE R22 R21 - 0x5C5C2800, // 00BD MOVE R23 R20 - 0x5C602600, // 00BE MOVE R24 R19 - 0x7C580400, // 00BF CALL R22 2 - 0x80042600, // 00C0 RET 1 R19 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_palette -********************************************************************/ -be_local_closure(Animate_palette_set_palette, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(ptr), - /* K1 */ be_nested_str_weak(ptr_to_palette), - /* K2 */ be_nested_str_weak(palette), - /* K3 */ be_nested_str_weak(slots), - /* K4 */ be_nested_str_weak(duration_ms), - /* K5 */ be_nested_str_weak(set_duration), - /* K6 */ be_nested_str_weak(range_min), - /* K7 */ be_nested_str_weak(range_max), - /* K8 */ be_nested_str_weak(set_range), - }), - be_str_weak(set_palette), - &be_const_str_solidified, - ( &(const binstruction[37]) { /* code */ - 0x60080004, // 0000 GETGBL R2 G4 - 0x5C0C0200, // 0001 MOVE R3 R1 - 0x7C080200, // 0002 CALL R2 1 - 0x1C080500, // 0003 EQ R2 R2 K0 - 0x780A0003, // 0004 JMPF R2 #0009 - 0x8C080101, // 0005 GETMET R2 R0 K1 - 0x5C100200, // 0006 MOVE R4 R1 - 0x7C080400, // 0007 CALL R2 2 - 0x5C040400, // 0008 MOVE R1 R2 - 0x90020401, // 0009 SETMBR R0 K2 R1 - 0x6008000C, // 000A GETGBL R2 G12 - 0x5C0C0200, // 000B MOVE R3 R1 - 0x7C080200, // 000C CALL R2 1 - 0x540E0003, // 000D LDINT R3 4 - 0x0C080403, // 000E DIV R2 R2 R3 - 0x90020602, // 000F SETMBR R0 K3 R2 - 0x88080104, // 0010 GETMBR R2 R0 K4 - 0x4C0C0000, // 0011 LDNIL R3 - 0x20080403, // 0012 NE R2 R2 R3 - 0x780A0003, // 0013 JMPF R2 #0018 - 0x8C080105, // 0014 GETMET R2 R0 K5 - 0x88100104, // 0015 GETMBR R4 R0 K4 - 0x7C080400, // 0016 CALL R2 2 - 0x7002000B, // 0017 JMP #0024 - 0x88080106, // 0018 GETMBR R2 R0 K6 - 0x4C0C0000, // 0019 LDNIL R3 - 0x20080403, // 001A NE R2 R2 R3 - 0x780A0007, // 001B JMPF R2 #0024 - 0x88080107, // 001C GETMBR R2 R0 K7 - 0x4C0C0000, // 001D LDNIL R3 - 0x20080403, // 001E NE R2 R2 R3 - 0x780A0003, // 001F JMPF R2 #0024 - 0x8C080108, // 0020 GETMET R2 R0 K8 - 0x88100106, // 0021 GETMBR R4 R0 K6 - 0x88140107, // 0022 GETMBR R5 R0 K7 - 0x7C080600, // 0023 CALL R2 3 - 0x80000000, // 0024 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: to_css_gradient -********************************************************************/ -be_local_closure(Animate_palette_to_css_gradient, /* name */ - be_nested_proto( - 17, /* nstack */ - 1, /* argc */ - 4, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[10]) { /* constants */ - /* K0 */ be_const_class(be_class_Animate_palette), - /* K1 */ be_nested_str_weak(parse_palette), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(background_X3Alinear_X2Dgradient_X28to_X20right), - /* K4 */ be_nested_str_weak(palette), - /* K5 */ be_nested_str_weak(get), - /* K6 */ be_nested_str_weak(_X2C_X23_X2502X_X2502X_X2502X_X20_X25_X2E1f_X25_X25), - /* K7 */ be_const_real_hex(0x41200000), - /* K8 */ be_const_int(1), - /* K9 */ be_nested_str_weak(_X29_X3B), - }), - be_str_weak(to_css_gradient), - &be_const_str_solidified, - ( &(const binstruction[46]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x5C080200, // 0001 MOVE R2 R1 - 0x5C0C0000, // 0002 MOVE R3 R0 - 0x7C080200, // 0003 CALL R2 1 - 0x8C0C0501, // 0004 GETMET R3 R2 K1 - 0x58140002, // 0005 LDCONST R5 K2 - 0x541A03E7, // 0006 LDINT R6 1000 - 0x7C0C0600, // 0007 CALL R3 3 - 0x58100003, // 0008 LDCONST R4 K3 - 0x58140002, // 0009 LDCONST R5 K2 - 0x6018000C, // 000A GETGBL R6 G12 - 0x5C1C0600, // 000B MOVE R7 R3 - 0x7C180200, // 000C CALL R6 1 - 0x14180A06, // 000D LT R6 R5 R6 - 0x781A001C, // 000E JMPF R6 #002C - 0x94180605, // 000F GETIDX R6 R3 R5 - 0x881C0504, // 0010 GETMBR R7 R2 K4 - 0x8C1C0F05, // 0011 GETMET R7 R7 K5 - 0x54260003, // 0012 LDINT R9 4 - 0x08240A09, // 0013 MUL R9 R5 R9 - 0x542A0003, // 0014 LDINT R10 4 - 0x7C1C0600, // 0015 CALL R7 3 - 0x54220007, // 0016 LDINT R8 8 - 0x3C200E08, // 0017 SHR R8 R7 R8 - 0x542600FE, // 0018 LDINT R9 255 - 0x2C201009, // 0019 AND R8 R8 R9 - 0x5426000F, // 001A LDINT R9 16 - 0x3C240E09, // 001B SHR R9 R7 R9 - 0x542A00FE, // 001C LDINT R10 255 - 0x2C24120A, // 001D AND R9 R9 R10 - 0x542A0017, // 001E LDINT R10 24 - 0x3C280E0A, // 001F SHR R10 R7 R10 - 0x542E00FE, // 0020 LDINT R11 255 - 0x2C28140B, // 0021 AND R10 R10 R11 - 0x602C0018, // 0022 GETGBL R11 G24 - 0x58300006, // 0023 LDCONST R12 K6 - 0x5C341000, // 0024 MOVE R13 R8 - 0x5C381200, // 0025 MOVE R14 R9 - 0x5C3C1400, // 0026 MOVE R15 R10 - 0x0C400D07, // 0027 DIV R16 R6 K7 - 0x7C2C0A00, // 0028 CALL R11 5 - 0x0010080B, // 0029 ADD R4 R4 R11 - 0x00140B08, // 002A ADD R5 R5 K8 - 0x7001FFDD, // 002B JMP #000A - 0x00100909, // 002C ADD R4 R4 K9 - 0x80040800, // 002D RET 1 R4 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_bri -********************************************************************/ -be_local_closure(Animate_palette_set_bri, /* name */ - be_nested_proto( - 4, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(bri), - }), - be_str_weak(set_bri), - &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x60080009, // 0000 GETGBL R2 G9 - 0x5C0C0200, // 0001 MOVE R3 R1 - 0x7C080200, // 0002 CALL R2 1 - 0x90020002, // 0003 SETMBR R0 K0 R2 - 0x80000000, // 0004 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: parse_palette -********************************************************************/ -be_local_closure(Animate_palette_parse_palette, /* name */ - be_nested_proto( - 15, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str_weak(slots), - /* K1 */ be_nested_str_weak(resize), - /* K2 */ be_nested_str_weak(palette), - /* K3 */ be_nested_str_weak(get), - /* K4 */ be_const_int(0), - /* K5 */ be_const_int(1), - /* K6 */ be_nested_str_weak(tasmota), - /* K7 */ be_nested_str_weak(scale_int), - }), - be_str_weak(parse_palette), - &be_const_str_solidified, - ( &(const binstruction[71]) { /* code */ - 0x600C0012, // 0000 GETGBL R3 G18 - 0x7C0C0000, // 0001 CALL R3 0 - 0x88100100, // 0002 GETMBR R4 R0 K0 - 0x8C140701, // 0003 GETMET R5 R3 K1 - 0x5C1C0800, // 0004 MOVE R7 R4 - 0x7C140400, // 0005 CALL R5 2 - 0x88140102, // 0006 GETMBR R5 R0 K2 - 0x8C140B03, // 0007 GETMET R5 R5 K3 - 0x581C0004, // 0008 LDCONST R7 K4 - 0x58200005, // 0009 LDCONST R8 K5 - 0x7C140600, // 000A CALL R5 3 - 0x20140B04, // 000B NE R5 R5 K4 - 0x78160024, // 000C JMPF R5 #0032 - 0x58140004, // 000D LDCONST R5 K4 - 0x58180004, // 000E LDCONST R6 K4 - 0x041C0905, // 000F SUB R7 R4 K5 - 0x141C0C07, // 0010 LT R7 R6 R7 - 0x781E0008, // 0011 JMPF R7 #001B - 0x881C0102, // 0012 GETMBR R7 R0 K2 - 0x8C1C0F03, // 0013 GETMET R7 R7 K3 - 0x54260003, // 0014 LDINT R9 4 - 0x08240C09, // 0015 MUL R9 R6 R9 - 0x58280005, // 0016 LDCONST R10 K5 - 0x7C1C0600, // 0017 CALL R7 3 - 0x00140A07, // 0018 ADD R5 R5 R7 - 0x00180D05, // 0019 ADD R6 R6 K5 - 0x7001FFF3, // 001A JMP #000F - 0x581C0004, // 001B LDCONST R7 K4 - 0x58180004, // 001C LDCONST R6 K4 - 0x14200C04, // 001D LT R8 R6 R4 - 0x78220011, // 001E JMPF R8 #0031 - 0xB8220C00, // 001F GETNGBL R8 K6 - 0x8C201107, // 0020 GETMET R8 R8 K7 - 0x5C280E00, // 0021 MOVE R10 R7 - 0x582C0004, // 0022 LDCONST R11 K4 - 0x5C300A00, // 0023 MOVE R12 R5 - 0x5C340200, // 0024 MOVE R13 R1 - 0x5C380400, // 0025 MOVE R14 R2 - 0x7C200C00, // 0026 CALL R8 6 - 0x980C0C08, // 0027 SETIDX R3 R6 R8 - 0x88200102, // 0028 GETMBR R8 R0 K2 - 0x8C201103, // 0029 GETMET R8 R8 K3 - 0x542A0003, // 002A LDINT R10 4 - 0x08280C0A, // 002B MUL R10 R6 R10 - 0x582C0005, // 002C LDCONST R11 K5 - 0x7C200600, // 002D CALL R8 3 - 0x001C0E08, // 002E ADD R7 R7 R8 - 0x00180D05, // 002F ADD R6 R6 K5 - 0x7001FFEB, // 0030 JMP #001D - 0x70020013, // 0031 JMP #0046 - 0x58140004, // 0032 LDCONST R5 K4 - 0x14180A04, // 0033 LT R6 R5 R4 - 0x781A0010, // 0034 JMPF R6 #0046 - 0x88180102, // 0035 GETMBR R6 R0 K2 - 0x8C180D03, // 0036 GETMET R6 R6 K3 - 0x54220003, // 0037 LDINT R8 4 - 0x08200A08, // 0038 MUL R8 R5 R8 - 0x58240005, // 0039 LDCONST R9 K5 - 0x7C180600, // 003A CALL R6 3 - 0xB81E0C00, // 003B GETNGBL R7 K6 - 0x8C1C0F07, // 003C GETMET R7 R7 K7 - 0x5C240C00, // 003D MOVE R9 R6 - 0x58280004, // 003E LDCONST R10 K4 - 0x542E00FE, // 003F LDINT R11 255 - 0x5C300200, // 0040 MOVE R12 R1 - 0x5C340400, // 0041 MOVE R13 R2 - 0x7C1C0C00, // 0042 CALL R7 6 - 0x980C0A07, // 0043 SETIDX R3 R5 R7 - 0x00140B05, // 0044 ADD R5 R5 K5 - 0x7001FFEC, // 0045 JMP #0033 - 0x80040600, // 0046 RET 1 R3 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_range -********************************************************************/ -be_local_closure(Animate_palette_set_range, /* name */ - be_nested_proto( - 7, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(value_error), - /* K1 */ be_nested_str_weak(min_X20must_X20be_X20lower_X20than_X20mex), - /* K2 */ be_nested_str_weak(range_min), - /* K3 */ be_nested_str_weak(range_max), - /* K4 */ be_nested_str_weak(slots_arr), - /* K5 */ be_nested_str_weak(parse_palette), - }), - be_str_weak(set_range), - &be_const_str_solidified, - ( &(const binstruction[11]) { /* code */ - 0x280C0202, // 0000 GE R3 R1 R2 - 0x780E0000, // 0001 JMPF R3 #0003 - 0xB0060101, // 0002 RAISE 1 K0 K1 - 0x90020401, // 0003 SETMBR R0 K2 R1 - 0x90020602, // 0004 SETMBR R0 K3 R2 - 0x8C0C0105, // 0005 GETMET R3 R0 K5 - 0x5C140200, // 0006 MOVE R5 R1 - 0x5C180400, // 0007 MOVE R6 R2 - 0x7C0C0600, // 0008 CALL R3 3 - 0x90020803, // 0009 SETMBR R0 K4 R3 - 0x80000000, // 000A RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_value -********************************************************************/ -be_local_closure(Animate_palette_set_value, /* name */ - be_nested_proto( - 18, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[13]) { /* constants */ - /* K0 */ be_nested_str_weak(range_min), - /* K1 */ be_nested_str_weak(range_max), - /* K2 */ be_nested_str_weak(tasmota), - /* K3 */ be_nested_str_weak(scale_int), - /* K4 */ be_nested_str_weak(slots), - /* K5 */ be_const_int(2), - /* K6 */ be_const_int(0), - /* K7 */ be_nested_str_weak(slots_arr), - /* K8 */ be_const_int(1), - /* K9 */ be_nested_str_weak(palette), - /* K10 */ be_nested_str_weak(get), - /* K11 */ be_nested_str_weak(obj), - /* K12 */ be_nested_str_weak(mth), - }), - be_str_weak(set_value), - &be_const_str_solidified, - ( &(const binstruction[96]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x1C080403, // 0002 EQ R2 R2 R3 - 0x740A0003, // 0003 JMPT R2 #0008 - 0x88080101, // 0004 GETMBR R2 R0 K1 - 0x4C0C0000, // 0005 LDNIL R3 - 0x1C080403, // 0006 EQ R2 R2 R3 - 0x780A0001, // 0007 JMPF R2 #000A - 0x4C080000, // 0008 LDNIL R2 - 0x80040400, // 0009 RET 1 R2 - 0xB80A0400, // 000A GETNGBL R2 K2 - 0x88080503, // 000B GETMBR R2 R2 K3 - 0x880C0104, // 000C GETMBR R3 R0 K4 - 0x04100705, // 000D SUB R4 R3 K5 - 0x24140906, // 000E GT R5 R4 K6 - 0x78160006, // 000F JMPF R5 #0017 - 0x88140107, // 0010 GETMBR R5 R0 K7 - 0x94140A04, // 0011 GETIDX R5 R5 R4 - 0x28140205, // 0012 GE R5 R1 R5 - 0x78160000, // 0013 JMPF R5 #0015 - 0x70020001, // 0014 JMP #0017 - 0x04100908, // 0015 SUB R4 R4 K8 - 0x7001FFF6, // 0016 JMP #000E - 0x88140109, // 0017 GETMBR R5 R0 K9 - 0x8C140B0A, // 0018 GETMET R5 R5 K10 - 0x541E0003, // 0019 LDINT R7 4 - 0x081C0807, // 001A MUL R7 R4 R7 - 0x54220003, // 001B LDINT R8 4 - 0x7C140600, // 001C CALL R5 3 - 0x88180109, // 001D GETMBR R6 R0 K9 - 0x8C180D0A, // 001E GETMET R6 R6 K10 - 0x00200908, // 001F ADD R8 R4 K8 - 0x54260003, // 0020 LDINT R9 4 - 0x08201009, // 0021 MUL R8 R8 R9 - 0x54260003, // 0022 LDINT R9 4 - 0x7C180600, // 0023 CALL R6 3 - 0x881C0107, // 0024 GETMBR R7 R0 K7 - 0x941C0E04, // 0025 GETIDX R7 R7 R4 - 0x00200908, // 0026 ADD R8 R4 K8 - 0x88240107, // 0027 GETMBR R9 R0 K7 - 0x94201208, // 0028 GETIDX R8 R9 R8 - 0x5C280400, // 0029 MOVE R10 R2 - 0x5C2C0200, // 002A MOVE R11 R1 - 0x5C300E00, // 002B MOVE R12 R7 - 0x5C341000, // 002C MOVE R13 R8 - 0x543A0007, // 002D LDINT R14 8 - 0x3C380A0E, // 002E SHR R14 R5 R14 - 0x543E00FE, // 002F LDINT R15 255 - 0x2C381C0F, // 0030 AND R14 R14 R15 - 0x543E0007, // 0031 LDINT R15 8 - 0x3C3C0C0F, // 0032 SHR R15 R6 R15 - 0x544200FE, // 0033 LDINT R16 255 - 0x2C3C1E10, // 0034 AND R15 R15 R16 - 0x7C280A00, // 0035 CALL R10 5 - 0x5C241400, // 0036 MOVE R9 R10 - 0x5C280400, // 0037 MOVE R10 R2 - 0x5C2C0200, // 0038 MOVE R11 R1 - 0x5C300E00, // 0039 MOVE R12 R7 - 0x5C341000, // 003A MOVE R13 R8 - 0x543A000F, // 003B LDINT R14 16 - 0x3C380A0E, // 003C SHR R14 R5 R14 - 0x543E00FE, // 003D LDINT R15 255 - 0x2C381C0F, // 003E AND R14 R14 R15 - 0x543E000F, // 003F LDINT R15 16 - 0x3C3C0C0F, // 0040 SHR R15 R6 R15 - 0x544200FE, // 0041 LDINT R16 255 - 0x2C3C1E10, // 0042 AND R15 R15 R16 - 0x7C280A00, // 0043 CALL R10 5 - 0x5C2C0400, // 0044 MOVE R11 R2 - 0x5C300200, // 0045 MOVE R12 R1 - 0x5C340E00, // 0046 MOVE R13 R7 - 0x5C381000, // 0047 MOVE R14 R8 - 0x543E0017, // 0048 LDINT R15 24 - 0x3C3C0A0F, // 0049 SHR R15 R5 R15 - 0x544200FE, // 004A LDINT R16 255 - 0x2C3C1E10, // 004B AND R15 R15 R16 - 0x54420017, // 004C LDINT R16 24 - 0x3C400C10, // 004D SHR R16 R6 R16 - 0x544600FE, // 004E LDINT R17 255 - 0x2C402011, // 004F AND R16 R16 R17 - 0x7C2C0A00, // 0050 CALL R11 5 - 0x5432000F, // 0051 LDINT R12 16 - 0x3830120C, // 0052 SHL R12 R9 R12 - 0x54360007, // 0053 LDINT R13 8 - 0x3834140D, // 0054 SHL R13 R10 R13 - 0x3030180D, // 0055 OR R12 R12 R13 - 0x3030180B, // 0056 OR R12 R12 R11 - 0x8834010B, // 0057 GETMBR R13 R0 K11 - 0x8838010C, // 0058 GETMBR R14 R0 K12 - 0x78360004, // 0059 JMPF R13 #005F - 0x783A0003, // 005A JMPF R14 #005F - 0x5C3C1C00, // 005B MOVE R15 R14 - 0x5C401A00, // 005C MOVE R16 R13 - 0x5C441800, // 005D MOVE R17 R12 - 0x7C3C0400, // 005E CALL R15 2 - 0x80041800, // 005F RET 1 R12 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_duration -********************************************************************/ -be_local_closure(Animate_palette_set_duration, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str_weak(value_error), - /* K2 */ be_nested_str_weak(duration_ms_X20must_X20be_X20positive), - /* K3 */ be_nested_str_weak(duration_ms), - /* K4 */ be_nested_str_weak(slots_arr), - /* K5 */ be_nested_str_weak(parse_palette), - /* K6 */ be_const_int(1), - }), - be_str_weak(set_duration), - &be_const_str_solidified, - ( &(const binstruction[14]) { /* code */ - 0x4C080000, // 0000 LDNIL R2 - 0x1C080202, // 0001 EQ R2 R1 R2 - 0x780A0000, // 0002 JMPF R2 #0004 - 0x80000400, // 0003 RET 0 - 0x18080300, // 0004 LE R2 R1 K0 - 0x780A0000, // 0005 JMPF R2 #0007 - 0xB0060302, // 0006 RAISE 1 K1 K2 - 0x90020601, // 0007 SETMBR R0 K3 R1 - 0x8C080105, // 0008 GETMET R2 R0 K5 - 0x58100000, // 0009 LDCONST R4 K0 - 0x04140306, // 000A SUB R5 R1 K6 - 0x7C080600, // 000B CALL R2 3 - 0x90020802, // 000C SETMBR R0 K4 R2 - 0x80000000, // 000D RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Animate_palette_init, /* name */ - be_nested_proto( - 6, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str_weak(init), - /* K1 */ be_nested_str_weak(duration_ms), - /* K2 */ be_nested_str_weak(running), - /* K3 */ be_nested_str_weak(bri), - /* K4 */ be_nested_str_weak(color), - /* K5 */ be_nested_str_weak(light_state), - /* K6 */ be_nested_str_weak(RGB), - /* K7 */ be_nested_str_weak(set_palette), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[19]) { /* code */ - 0x600C0003, // 0000 GETGBL R3 G3 - 0x5C100000, // 0001 MOVE R4 R0 - 0x7C0C0200, // 0002 CALL R3 1 - 0x8C0C0700, // 0003 GETMET R3 R3 K0 - 0x7C0C0200, // 0004 CALL R3 1 - 0x90020202, // 0005 SETMBR R0 K1 R2 - 0x500C0000, // 0006 LDBOOL R3 0 0 - 0x90020403, // 0007 SETMBR R0 K2 R3 - 0x540E0063, // 0008 LDINT R3 100 - 0x90020603, // 0009 SETMBR R0 K3 R3 - 0xB80E0A00, // 000A GETNGBL R3 K5 - 0xB8120A00, // 000B GETNGBL R4 K5 - 0x88100906, // 000C GETMBR R4 R4 K6 - 0x7C0C0200, // 000D CALL R3 1 - 0x90020803, // 000E SETMBR R0 K4 R3 - 0x8C0C0107, // 000F GETMET R3 R0 K7 - 0x5C140200, // 0010 MOVE R5 R1 - 0x7C0C0400, // 0011 CALL R3 2 - 0x80000000, // 0012 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: Animate_palette -********************************************************************/ -extern const bclass be_class_Animate_animator; -be_local_class(Animate_palette, - 7, - &be_class_Animate_animator, - be_nested_map(17, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(color, 13), be_const_var(6) }, - { be_const_key_weak(slots, -1), be_const_var(2) }, - { be_const_key_weak(animate, 11), be_const_closure(Animate_palette_animate_closure) }, - { be_const_key_weak(range_max, 10), be_const_var(4) }, - { be_const_key_weak(set_palette, -1), be_const_closure(Animate_palette_set_palette_closure) }, - { be_const_key_weak(set_bri, -1), be_const_closure(Animate_palette_set_bri_closure) }, - { be_const_key_weak(bri, -1), be_const_var(5) }, - { be_const_key_weak(to_css_gradient, 12), be_const_static_closure(Animate_palette_to_css_gradient_closure) }, - { be_const_key_weak(slots_arr, 1), be_const_var(1) }, - { be_const_key_weak(range_min, 5), be_const_var(3) }, - { be_const_key_weak(set_value, -1), be_const_closure(Animate_palette_set_value_closure) }, - { be_const_key_weak(set_range, -1), be_const_closure(Animate_palette_set_range_closure) }, - { be_const_key_weak(parse_palette, -1), be_const_closure(Animate_palette_parse_palette_closure) }, - { be_const_key_weak(palette, -1), be_const_var(0) }, - { be_const_key_weak(set_duration, -1), be_const_closure(Animate_palette_set_duration_closure) }, - { be_const_key_weak(init, -1), be_const_closure(Animate_palette_init_closure) }, - { be_const_key_weak(ptr_to_palette, 0), be_const_static_closure(Animate_palette_ptr_to_palette_closure) }, - })), - be_str_weak(Animate_palette) -); -/*******************************************************************/ - -void be_load_Animate_palette_class(bvm *vm) { - be_pushntvclass(vm, &be_class_Animate_palette); - be_setglobal(vm, "Animate_palette"); - be_pop(vm, 1); -} - -extern const bclass be_class_Animate_oscillator; - -/******************************************************************** -** Solidified function: set_duty_cycle -********************************************************************/ -be_local_closure(Animate_oscillator_set_duty_cycle, /* name */ - be_nested_proto( - 3, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str_weak(duty_cycle), - }), - be_str_weak(set_duty_cycle), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0x14080300, // 0000 LT R2 R1 K0 - 0x780A0000, // 0001 JMPF R2 #0003 - 0x58040000, // 0002 LDCONST R1 K0 - 0x540A0063, // 0003 LDINT R2 100 - 0x24080202, // 0004 GT R2 R1 R2 - 0x780A0000, // 0005 JMPF R2 #0007 - 0x54060063, // 0006 LDINT R1 100 - 0x90020201, // 0007 SETMBR R0 K1 R1 - 0x80000000, // 0008 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_a -********************************************************************/ -be_local_closure(Animate_oscillator_set_a, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(a), - }), - be_str_weak(set_a), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_b -********************************************************************/ -be_local_closure(Animate_oscillator_set_b, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(b), - }), - be_str_weak(set_b), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_form -********************************************************************/ -be_local_closure(Animate_oscillator_set_form, /* name */ - be_nested_proto( - 3, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_const_int(1), - /* K1 */ be_nested_str_weak(form), - }), - be_str_weak(set_form), - &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ - 0x4C080000, // 0000 LDNIL R2 - 0x1C080202, // 0001 EQ R2 R1 R2 - 0x780A0000, // 0002 JMPF R2 #0004 - 0x58040000, // 0003 LDCONST R1 K0 - 0x90020201, // 0004 SETMBR R0 K1 R1 - 0x80000000, // 0005 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_phase -********************************************************************/ -be_local_closure(Animate_oscillator_set_phase, /* name */ - be_nested_proto( - 3, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str_weak(phase), - }), - be_str_weak(set_phase), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0x14080300, // 0000 LT R2 R1 K0 - 0x780A0000, // 0001 JMPF R2 #0003 - 0x58040000, // 0002 LDCONST R1 K0 - 0x540A0063, // 0003 LDINT R2 100 - 0x24080202, // 0004 GT R2 R1 R2 - 0x780A0000, // 0005 JMPF R2 #0007 - 0x54060063, // 0006 LDINT R1 100 - 0x90020201, // 0007 SETMBR R0 K1 R1 - 0x80000000, // 0008 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Animate_oscillator_init, /* name */ - be_nested_proto( - 7, /* nstack */ - 5, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[10]) { /* constants */ - /* K0 */ be_nested_str_weak(init), - /* K1 */ be_nested_str_weak(phase), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(duty_cycle), - /* K4 */ be_nested_str_weak(a), - /* K5 */ be_nested_str_weak(b), - /* K6 */ be_nested_str_weak(duration_ms), - /* K7 */ be_nested_str_weak(value), - /* K8 */ be_const_int(1), - /* K9 */ be_nested_str_weak(form), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[18]) { /* code */ - 0x60140003, // 0000 GETGBL R5 G3 - 0x5C180000, // 0001 MOVE R6 R0 - 0x7C140200, // 0002 CALL R5 1 - 0x8C140B00, // 0003 GETMET R5 R5 K0 - 0x7C140200, // 0004 CALL R5 1 - 0x90020302, // 0005 SETMBR R0 K1 K2 - 0x54160031, // 0006 LDINT R5 50 - 0x90020605, // 0007 SETMBR R0 K3 R5 - 0x90020801, // 0008 SETMBR R0 K4 R1 - 0x90020A02, // 0009 SETMBR R0 K5 R2 - 0x90020C03, // 000A SETMBR R0 K6 R3 - 0x90020E01, // 000B SETMBR R0 K7 R1 - 0x4C140000, // 000C LDNIL R5 - 0x1C140805, // 000D EQ R5 R4 R5 - 0x78160000, // 000E JMPF R5 #0010 - 0x58100008, // 000F LDCONST R4 K8 - 0x90021204, // 0010 SETMBR R0 K9 R4 - 0x80000000, // 0011 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: animate -********************************************************************/ -be_local_closure(Animate_oscillator_animate, /* name */ - be_nested_proto( - 18, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[20]) { /* constants */ - /* K0 */ be_nested_str_weak(duration_ms), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(millis), - /* K3 */ be_nested_str_weak(origin), - /* K4 */ be_const_int(0), - /* K5 */ be_nested_str_weak(scale_uint), - /* K6 */ be_nested_str_weak(duty_cycle), - /* K7 */ be_nested_str_weak(beat), - /* K8 */ be_nested_str_weak(a), - /* K9 */ be_nested_str_weak(b), - /* K10 */ be_nested_str_weak(value), - /* K11 */ be_nested_str_weak(phase), - /* K12 */ be_nested_str_weak(form), - /* K13 */ be_const_int(1), - /* K14 */ be_nested_str_weak(scale_int), - /* K15 */ be_const_int(2), - /* K16 */ be_const_int(3), - /* K17 */ be_nested_str_weak(sine_int), - /* K18 */ be_nested_str_weak(obj), - /* K19 */ be_nested_str_weak(mth), - }), - be_str_weak(animate), - &be_const_str_solidified, - ( &(const binstruction[141]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x1C080403, // 0002 EQ R2 R2 R3 - 0x780A0000, // 0003 JMPF R2 #0005 - 0x80000400, // 0004 RET 0 - 0x4C080000, // 0005 LDNIL R2 - 0x1C080202, // 0006 EQ R2 R1 R2 - 0x780A0003, // 0007 JMPF R2 #000C - 0xB80A0200, // 0008 GETNGBL R2 K1 - 0x8C080502, // 0009 GETMET R2 R2 K2 - 0x7C080200, // 000A CALL R2 1 - 0x5C040400, // 000B MOVE R1 R2 - 0x88080103, // 000C GETMBR R2 R0 K3 - 0x04080202, // 000D SUB R2 R1 R2 - 0x140C0504, // 000E LT R3 R2 K4 - 0x780E0001, // 000F JMPF R3 #0012 - 0x58080004, // 0010 LDCONST R2 K4 - 0x88040103, // 0011 GETMBR R1 R0 K3 - 0x880C0100, // 0012 GETMBR R3 R0 K0 - 0x4C100000, // 0013 LDNIL R4 - 0xB8160200, // 0014 GETNGBL R5 K1 - 0x8C140B05, // 0015 GETMET R5 R5 K5 - 0x881C0106, // 0016 GETMBR R7 R0 K6 - 0x58200004, // 0017 LDCONST R8 K4 - 0x54260063, // 0018 LDINT R9 100 - 0x58280004, // 0019 LDCONST R10 K4 - 0x5C2C0600, // 001A MOVE R11 R3 - 0x7C140C00, // 001B CALL R5 6 - 0x5C100A00, // 001C MOVE R4 R5 - 0x28140403, // 001D GE R5 R2 R3 - 0x78160007, // 001E JMPF R5 #0027 - 0x0C180403, // 001F DIV R6 R2 R3 - 0x08180C03, // 0020 MUL R6 R6 R3 - 0x88140103, // 0021 GETMBR R5 R0 K3 - 0x00140A06, // 0022 ADD R5 R5 R6 - 0x90020605, // 0023 SETMBR R0 K3 R5 - 0x10080403, // 0024 MOD R2 R2 R3 - 0x8C140107, // 0025 GETMET R5 R0 K7 - 0x7C140200, // 0026 CALL R5 1 - 0x88140108, // 0027 GETMBR R5 R0 K8 - 0x88180109, // 0028 GETMBR R6 R0 K9 - 0x881C010A, // 0029 GETMBR R7 R0 K10 - 0x5C200400, // 002A MOVE R8 R2 - 0x8824010B, // 002B GETMBR R9 R0 K11 - 0x24241304, // 002C GT R9 R9 K4 - 0x7826000B, // 002D JMPF R9 #003A - 0xB8260200, // 002E GETNGBL R9 K1 - 0x8C241305, // 002F GETMET R9 R9 K5 - 0x882C010B, // 0030 GETMBR R11 R0 K11 - 0x58300004, // 0031 LDCONST R12 K4 - 0x54360063, // 0032 LDINT R13 100 - 0x58380004, // 0033 LDCONST R14 K4 - 0x5C3C0600, // 0034 MOVE R15 R3 - 0x7C240C00, // 0035 CALL R9 6 - 0x00201009, // 0036 ADD R8 R8 R9 - 0x24241003, // 0037 GT R9 R8 R3 - 0x78260000, // 0038 JMPF R9 #003A - 0x04201003, // 0039 SUB R8 R8 R3 - 0x8824010C, // 003A GETMBR R9 R0 K12 - 0x1C24130D, // 003B EQ R9 R9 K13 - 0x78260009, // 003C JMPF R9 #0047 - 0xB8260200, // 003D GETNGBL R9 K1 - 0x8C24130E, // 003E GETMET R9 R9 K14 - 0x5C2C1000, // 003F MOVE R11 R8 - 0x58300004, // 0040 LDCONST R12 K4 - 0x0434070D, // 0041 SUB R13 R3 K13 - 0x5C380A00, // 0042 MOVE R14 R5 - 0x5C3C0C00, // 0043 MOVE R15 R6 - 0x7C240C00, // 0044 CALL R9 6 - 0x5C1C1200, // 0045 MOVE R7 R9 - 0x7002003B, // 0046 JMP #0083 - 0x8824010C, // 0047 GETMBR R9 R0 K12 - 0x1C24130F, // 0048 EQ R9 R9 K15 - 0x78260015, // 0049 JMPF R9 #0060 - 0x14241004, // 004A LT R9 R8 R4 - 0x78260009, // 004B JMPF R9 #0056 - 0xB8260200, // 004C GETNGBL R9 K1 - 0x8C24130E, // 004D GETMET R9 R9 K14 - 0x5C2C1000, // 004E MOVE R11 R8 - 0x58300004, // 004F LDCONST R12 K4 - 0x0434090D, // 0050 SUB R13 R4 K13 - 0x5C380A00, // 0051 MOVE R14 R5 - 0x5C3C0C00, // 0052 MOVE R15 R6 - 0x7C240C00, // 0053 CALL R9 6 - 0x5C1C1200, // 0054 MOVE R7 R9 - 0x70020008, // 0055 JMP #005F - 0xB8260200, // 0056 GETNGBL R9 K1 - 0x8C24130E, // 0057 GETMET R9 R9 K14 - 0x5C2C1000, // 0058 MOVE R11 R8 - 0x5C300800, // 0059 MOVE R12 R4 - 0x0434070D, // 005A SUB R13 R3 K13 - 0x5C380C00, // 005B MOVE R14 R6 - 0x5C3C0A00, // 005C MOVE R15 R5 - 0x7C240C00, // 005D CALL R9 6 - 0x5C1C1200, // 005E MOVE R7 R9 - 0x70020022, // 005F JMP #0083 - 0x8824010C, // 0060 GETMBR R9 R0 K12 - 0x1C241310, // 0061 EQ R9 R9 K16 - 0x78260005, // 0062 JMPF R9 #0069 - 0x14241004, // 0063 LT R9 R8 R4 - 0x78260001, // 0064 JMPF R9 #0067 - 0x5C1C0A00, // 0065 MOVE R7 R5 - 0x70020000, // 0066 JMP #0068 - 0x5C1C0C00, // 0067 MOVE R7 R6 - 0x70020019, // 0068 JMP #0083 - 0x8824010C, // 0069 GETMBR R9 R0 K12 - 0x542A0003, // 006A LDINT R10 4 - 0x1C24120A, // 006B EQ R9 R9 R10 - 0x78260015, // 006C JMPF R9 #0083 - 0xB8260200, // 006D GETNGBL R9 K1 - 0x8C24130E, // 006E GETMET R9 R9 K14 - 0x5C2C1000, // 006F MOVE R11 R8 - 0x58300004, // 0070 LDCONST R12 K4 - 0x0434070D, // 0071 SUB R13 R3 K13 - 0x58380004, // 0072 LDCONST R14 K4 - 0x543E7FFE, // 0073 LDINT R15 32767 - 0x7C240C00, // 0074 CALL R9 6 - 0xB82A0200, // 0075 GETNGBL R10 K1 - 0x8C281511, // 0076 GETMET R10 R10 K17 - 0x54321FFF, // 0077 LDINT R12 8192 - 0x0430120C, // 0078 SUB R12 R9 R12 - 0x7C280400, // 0079 CALL R10 2 - 0xB82E0200, // 007A GETNGBL R11 K1 - 0x8C2C170E, // 007B GETMET R11 R11 K14 - 0x5C341400, // 007C MOVE R13 R10 - 0x5439EFFF, // 007D LDINT R14 -4096 - 0x543E0FFF, // 007E LDINT R15 4096 - 0x5C400A00, // 007F MOVE R16 R5 - 0x5C440C00, // 0080 MOVE R17 R6 - 0x7C2C0C00, // 0081 CALL R11 6 - 0x5C1C1600, // 0082 MOVE R7 R11 - 0x90021407, // 0083 SETMBR R0 K10 R7 - 0x88240112, // 0084 GETMBR R9 R0 K18 - 0x88280113, // 0085 GETMBR R10 R0 K19 - 0x78260004, // 0086 JMPF R9 #008C - 0x782A0003, // 0087 JMPF R10 #008C - 0x5C2C1400, // 0088 MOVE R11 R10 - 0x5C301200, // 0089 MOVE R12 R9 - 0x5C340E00, // 008A MOVE R13 R7 - 0x7C2C0400, // 008B CALL R11 2 - 0x80040E00, // 008C RET 1 R7 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: Animate_oscillator -********************************************************************/ -extern const bclass be_class_Animate_animator; -be_local_class(Animate_oscillator, - 6, - &be_class_Animate_animator, - be_nested_map(13, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(animate, -1), be_const_closure(Animate_oscillator_animate_closure) }, - { be_const_key_weak(a, -1), be_const_var(2) }, - { be_const_key_weak(init, 11), be_const_closure(Animate_oscillator_init_closure) }, - { be_const_key_weak(duty_cycle, 10), be_const_var(1) }, - { be_const_key_weak(b, -1), be_const_var(3) }, - { be_const_key_weak(value, -1), be_const_var(5) }, - { be_const_key_weak(set_duty_cycle, 2), be_const_closure(Animate_oscillator_set_duty_cycle_closure) }, - { be_const_key_weak(set_a, -1), be_const_closure(Animate_oscillator_set_a_closure) }, - { be_const_key_weak(set_b, -1), be_const_closure(Animate_oscillator_set_b_closure) }, - { be_const_key_weak(set_form, -1), be_const_closure(Animate_oscillator_set_form_closure) }, - { be_const_key_weak(phase, -1), be_const_var(0) }, - { be_const_key_weak(form, -1), be_const_var(4) }, - { be_const_key_weak(set_phase, 0), be_const_closure(Animate_oscillator_set_phase_closure) }, - })), - be_str_weak(Animate_oscillator) -); -/*******************************************************************/ - -void be_load_Animate_oscillator_class(bvm *vm) { - be_pushntvclass(vm, &be_class_Animate_oscillator); - be_setglobal(vm, "Animate_oscillator"); - be_pop(vm, 1); -} -/********************************************************************/ -/* End of solidification */ diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_leds_frame_be_methods.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_leds_frame_be_methods.h deleted file mode 100644 index 7a565f9f2..000000000 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_leds_frame_be_methods.h +++ /dev/null @@ -1,186 +0,0 @@ -/* Solidification of leds_frame_be_methods.h */ -/********************************************************************\ -* Generated code, don't edit * -\********************************************************************/ -#include "be_constobj.h" - -extern const bclass be_class_Leds_frame_be; - -/******************************************************************** -** Solidified function: setitem -********************************************************************/ -be_local_closure(Leds_frame_be_setitem, /* name */ - be_nested_proto( - 8, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str(set), - }), - &be_const_str_setitem, - &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0x8C0C0100, // 0000 GETMET R3 R0 K0 - 0x54160003, // 0001 LDINT R5 4 - 0x08140205, // 0002 MUL R5 R1 R5 - 0x5C180400, // 0003 MOVE R6 R2 - 0x541E0003, // 0004 LDINT R7 4 - 0x7C0C0800, // 0005 CALL R3 4 - 0x80000000, // 0006 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_pixel -********************************************************************/ -be_local_closure(Leds_frame_be_set_pixel, /* name */ - be_nested_proto( - 11, /* nstack */ - 6, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str(setitem), - }), - &be_const_str_set_pixel, - &be_const_str_solidified, - ( &(const binstruction[26]) { /* code */ - 0x4C180000, // 0000 LDNIL R6 - 0x1C180A06, // 0001 EQ R6 R5 R6 - 0x781A0000, // 0002 JMPF R6 #0004 - 0x58140000, // 0003 LDCONST R5 K0 - 0x541A00FE, // 0004 LDINT R6 255 - 0x2C180A06, // 0005 AND R6 R5 R6 - 0x541E0017, // 0006 LDINT R7 24 - 0x38180C07, // 0007 SHL R6 R6 R7 - 0x541E00FE, // 0008 LDINT R7 255 - 0x2C1C0407, // 0009 AND R7 R2 R7 - 0x5422000F, // 000A LDINT R8 16 - 0x381C0E08, // 000B SHL R7 R7 R8 - 0x30180C07, // 000C OR R6 R6 R7 - 0x541E00FE, // 000D LDINT R7 255 - 0x2C1C0607, // 000E AND R7 R3 R7 - 0x54220007, // 000F LDINT R8 8 - 0x381C0E08, // 0010 SHL R7 R7 R8 - 0x30180C07, // 0011 OR R6 R6 R7 - 0x541E00FE, // 0012 LDINT R7 255 - 0x2C1C0807, // 0013 AND R7 R4 R7 - 0x30180C07, // 0014 OR R6 R6 R7 - 0x8C1C0101, // 0015 GETMET R7 R0 K1 - 0x5C240200, // 0016 MOVE R9 R1 - 0x5C280C00, // 0017 MOVE R10 R6 - 0x7C1C0600, // 0018 CALL R7 3 - 0x80000000, // 0019 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: item -********************************************************************/ -be_local_closure(Leds_frame_be_item, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str(get), - }), - &be_const_str_item, - &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ - 0x8C080100, // 0000 GETMET R2 R0 K0 - 0x54120003, // 0001 LDINT R4 4 - 0x08100204, // 0002 MUL R4 R1 R4 - 0x54160003, // 0003 LDINT R5 4 - 0x7C080600, // 0004 CALL R2 3 - 0x80040400, // 0005 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Leds_frame_be_init, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str(pixel_size), - /* K2 */ be_nested_str(init), - }), - &be_const_str_init, - &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x14080300, // 0000 LT R2 R1 K0 - 0x780A0000, // 0001 JMPF R2 #0003 - 0x44040200, // 0002 NEG R1 R1 - 0x90020201, // 0003 SETMBR R0 K1 R1 - 0x60080003, // 0004 GETGBL R2 G3 - 0x5C0C0000, // 0005 MOVE R3 R0 - 0x7C080200, // 0006 CALL R2 1 - 0x8C080502, // 0007 GETMET R2 R2 K2 - 0x5411FFFB, // 0008 LDINT R4 -4 - 0x08100204, // 0009 MUL R4 R1 R4 - 0x7C080400, // 000A CALL R2 2 - 0x80000000, // 000B RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: Leds_frame_be -********************************************************************/ -be_local_class(Leds_frame_be, - 0, - NULL, - be_nested_map(4, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key(setitem, 1), be_const_closure(Leds_frame_be_setitem_closure) }, - { be_const_key(set_pixel, -1), be_const_closure(Leds_frame_be_set_pixel_closure) }, - { be_const_key(item, -1), be_const_closure(Leds_frame_be_item_closure) }, - { be_const_key(init, -1), be_const_closure(Leds_frame_be_init_closure) }, - })), - (bstring*) &be_const_str_Leds_frame_be -); -/*******************************************************************/ - -void be_load_Leds_frame_be_class(bvm *vm) { - be_pushntvclass(vm, &be_class_Leds_frame_be); - be_setglobal(vm, "Leds_frame_be"); - be_pop(vm, 1); -} -/********************************************************************/ -/* End of solidification */ From a74200d40d2b4b64235460452a711ada2ee676e8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 23 Jan 2024 23:52:18 +0100 Subject: [PATCH 213/303] Refactored rules USE_EXPRESSION and SUPPORT_IF_STATEMENT replacing LinkedList with arrays --- CHANGELOG.md | 1 + RELEASENOTES.md | 1 + tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino | 140 ++++++++++++------ 3 files changed, 98 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15f78b754..978dc618d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file. ### Changed - Refactored rules ``Subscribe`` using LList allowing full message size and enabled by default +- Refactored rules USE_EXPRESSION and SUPPORT_IF_STATEMENT replacing LinkedList with arrays ### Fixed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 3d4e15fa6..6bb3523fa 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -165,6 +165,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - ESP32 platform update from 2023.11.01 to 2024.01.01 [#20473](https://github.com/arendst/Tasmota/issues/20473) - Renamed button "Consoles" to "Tools" - Refactored rule ``Subscribe`` using LList allowing full message size and enabled by default +- Refactored rules USE_EXPRESSION and SUPPORT_IF_STATEMENT replacing LinkedList with arrays - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` [#20260](https://github.com/arendst/Tasmota/issues/20260) - Web file upload response on upload error [#20340](https://github.com/arendst/Tasmota/issues/20340) - Header `Host` is now collected by Webserver [#20446](https://github.com/arendst/Tasmota/issues/20446) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino index ec06ca00d..140a6e95f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino @@ -114,8 +114,6 @@ const char kCompareOperators[] PROGMEM = "=\0>\0<\0|\0==!=>=<=$>$<$|$!$^"; #ifdef USE_EXPRESSION - #include // Import LinkedList library - const char kExpressionOperators[] PROGMEM = "+-*/%^\0"; #define EXPRESSION_OPERATOR_ADD 0 #define EXPRESSION_OPERATOR_SUBTRACT 1 @@ -127,7 +125,6 @@ const char kCompareOperators[] PROGMEM = "=\0>\0<\0|\0==!=>=<=$>$<$|$!$^"; const uint8_t kExpressionOperatorsPriorities[] PROGMEM = {1, 1, 2, 2, 3, 4}; #define MAX_EXPRESSION_OPERATOR_PRIORITY 4 - #define LOGIC_OPERATOR_AND 1 #define LOGIC_OPERATOR_OR 2 @@ -1642,53 +1639,92 @@ float calculateTwoValues(float v1, float v2, uint8_t op) * 2 + 1 * 3 / 2 */ -float evaluateExpression(const char * expression, unsigned int len) -{ +float evaluateExpression(const char * expression, unsigned int len) { char expbuf[len + 1]; memcpy(expbuf, expression, len); expbuf[len] = '\0'; char * scan_pointer = expbuf; - LinkedList object_values; - LinkedList operators; - int8_t op; + float object_values[21]; + int8_t operators[20]; float va; //Find and add the value of first object if (findNextObjectValue(scan_pointer, va)) { - object_values.add(va); + object_values[0] = va; } else { return 0; } - while (*scan_pointer) - { + + uint32_t operators_size = 0; + uint32_t object_values_size = 1; + int8_t op; + while (*scan_pointer) { if (findNextOperator(scan_pointer, op) && *scan_pointer && findNextObjectValue(scan_pointer, va)) { - operators.add(op); - object_values.add(va); + operators[operators_size++] = op; + object_values[object_values_size++] = va; } else { //No operator followed or no more object after this operator, we done. break; } + + if (operators_size >= 20) { + AddLog(LOG_LEVEL_ERROR, PSTR("RUL: Too many arguments")); + } } - //Going to evaluate the whole expression - //Calculate by order of operator priorities. Looking for all operators with specified priority (from High to Low) - for (int32_t priority = MAX_EXPRESSION_OPERATOR_PRIORITY; priority>0; priority--) { + // Going to evaluate the whole expression + // Calculate by order of operator priorities. Looking for all operators with specified priority (from High to Low) + for (int32_t priority = MAX_EXPRESSION_OPERATOR_PRIORITY; priority > 0; priority--) { int index = 0; - while (index < operators.size()) { - if (priority == pgm_read_byte(kExpressionOperatorsPriorities + operators.get(index))) { //need to calculate the operator first - //get current object value and remove the next object with current operator - va = calculateTwoValues(object_values.get(index), object_values.remove(index + 1), operators.remove(index)); + while (index < operators_size) { + if (priority == pgm_read_byte(kExpressionOperatorsPriorities + operators[index])) { //need to calculate the operator first + // Get current object value and remove the next object with current operator + va = calculateTwoValues(object_values[index], object_values[index + 1], operators[index]); + + uint32_t i = index; + while (i <= operators_size) { + operators[i++] = operators[i]; // operators.remove(index) + object_values[i] = object_values[i +1]; // object_values.remove(index + 1) + } + object_values_size--; + operators_size--; + + +/* + uint32_t i = index +1; + while (i <= object_values_size) { + object_values[i++] = object_values[i]; // object_values.remove(index + 1) + } + object_values_size--; + + i = index; + while (i <= operators_size) { + operators[i++] = operators[i]; // operators.remove(index) + } + operators_size--; +*/ +/* + for (uint32_t i = index +1; i <= object_values_size; i++) { + object_values[i] = object_values[i +1]; // object_values.remove(index + 1) + } + object_values_size--; + + for (uint32_t i = index; i <= operators_size; i++) { + operators[i] = operators[i +1]; // operators.remove(index) + } + operators_size--; +*/ //Replace the current value with the result - object_values.set(index, va); + object_values[index] = va; } else { index++; } } } - return object_values.get(0); + return object_values[0]; } #endif // USE_EXPRESSION @@ -1873,58 +1909,74 @@ bool findNextLogicObjectValue(char * &pointer, bool &value) * Return: * boolean - the value of logical expression */ -bool evaluateLogicalExpression(const char * expression, int len) -{ +bool evaluateLogicalExpression(const char * expression, int len) { //Make a copy first char expbuff[len + 1]; memcpy(expbuff, expression, len); expbuff[len] = '\0'; - - //AddLog(LOG_LEVEL_DEBUG, PSTR("EvalLogic: |%s|"), expbuff); char * pointer = expbuff; - LinkedList values; - LinkedList logicOperators; + + bool values[21]; + int8_t logicOperators[20]; + //Find first comparison expression bool bValue; if (findNextLogicObjectValue(pointer, bValue)) { - values.add(bValue); + values[0] = bValue; } else { return false; } + + uint32_t logicOperators_size = 0; + uint32_t values_size = 1; int8_t op; while (*pointer) { if (findNextLogicOperator(pointer, op) && (*pointer) && findNextLogicObjectValue(pointer, bValue)) { - logicOperators.add(op); - values.add(bValue); + logicOperators[logicOperators_size++] = op; + values[values_size++] = bValue; } else { break; } + if (logicOperators_size >= 20) { + AddLog(LOG_LEVEL_ERROR, PSTR("RUL: Too many arguments")); + } } - //Calculate all "AND" first + + // Calculate all "AND" first int index = 0; - while (index < logicOperators.size()) { - if (logicOperators.get(index) == LOGIC_OPERATOR_AND) { - values.set(index, values.get(index) && values.get(index+1)); - values.remove(index + 1); - logicOperators.remove(index); + while (index < logicOperators_size) { + if (logicOperators[index] == LOGIC_OPERATOR_AND) { + values[index] &= values[index +1]; + uint32_t i = index; + while (i <= logicOperators_size) { + logicOperators[i++] = logicOperators[i]; // logicOperators.remove(index); + values[i] = values[i +1]; // values.remove(index + 1); + } + values_size--; + logicOperators_size--; } else { index++; } } - //Then, calculate all "OR" + // Then, calculate all "OR" index = 0; - while (index < logicOperators.size()) { - if (logicOperators.get(index) == LOGIC_OPERATOR_OR) { - values.set(index, values.get(index) || values.get(index+1)); - values.remove(index + 1); - logicOperators.remove(index); + while (index < logicOperators_size) { + if (logicOperators[index] == LOGIC_OPERATOR_OR) { + values[index] |= values[index+1]; + uint32_t i = index; + while (i <= logicOperators_size) { + logicOperators[i++] = logicOperators[i]; // logicOperators.remove(index); + values[i] = values[i +1]; // values.remove(index + 1); + } + values_size--; + logicOperators_size--; } else { index++; } } - return values.get(0); + return values[0]; } /********************************************************************************************/ From 7f5e79415f48425467886ad31b5fc37deb1733f0 Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Wed, 24 Jan 2024 08:27:54 +0100 Subject: [PATCH 214/303] [SML] Fix decimal separator (#20573) --- tasmota/tasmota_xsns_sensor/xsns_53_sml.ino | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tasmota/tasmota_xsns_sensor/xsns_53_sml.ino b/tasmota/tasmota_xsns_sensor/xsns_53_sml.ino index 89fe8d296..9a5968f48 100755 --- a/tasmota/tasmota_xsns_sensor/xsns_53_sml.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_53_sml.ino @@ -2542,7 +2542,7 @@ void SML_Show(boolean json) { tpowstr[i] = 0; // export html //snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s{s}%s{e}", b_mqtt_data,tpowstr); - WSContentSend_PD(PSTR("{s}%s{e}"), tpowstr); + WSContentSend_P(PSTR("
%s{e}"), tpowstr); // rewind, to ensure strchr mp--; mp = strchr(mp, '|'); @@ -2670,7 +2670,10 @@ void SML_Show(boolean json) { } else { // web ui export //snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s{s}%s %s: {m}%s %s{e}", b_mqtt_data,meter_desc[mindex].prefix,name,tpowstr,unit); - if (strcmp(name, "*")) WSContentSend_PD(PSTR("{s}%s %s {m}%s %s{e}"), sml_globs.mp[mindex].prefix, name,tpowstr, unit); + if (strcmp(name, "*")) { + WSContentSend_P(PSTR("{s}%s %s{m}"), sml_globs.mp[mindex].prefix, name); // Do not replace decimal separator in label + WSContentSend_PD(PSTR("%s %s{e}"), tpowstr, unit); // Replace decimal separator in value + } } } } From 79bc9a6b946e638b3610a05cf45e63c20bf53ab0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 24 Jan 2024 14:22:48 +0100 Subject: [PATCH 215/303] Fix LList insertAt skipping one entry --- lib/default/TasmotaLList/src/LList.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/default/TasmotaLList/src/LList.h b/lib/default/TasmotaLList/src/LList.h index fc3a7b559..4c2d2c656 100644 --- a/lib/default/TasmotaLList/src/LList.h +++ b/lib/default/TasmotaLList/src/LList.h @@ -208,6 +208,10 @@ T & LList::addToLast(void) { template T & LList::insertAt(size_t index) { + if (0 == index) { + return addHead(); // insert at the head + } + index--; LList_elt **curr_ptr = &_head; size_t count = 0; while (*curr_ptr) { From cce520417731ebad2abb088e7b2817c155c9f3c2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 24 Jan 2024 14:33:55 +0100 Subject: [PATCH 216/303] Refactored rules USE_EXPRESSION and SUPPORT_IF_STATEMENT replacing LinkedList with arrays and enabled by default --- CHANGELOG.md | 2 +- RELEASENOTES.md | 2 +- tasmota/my_user_config.h | 4 +- tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino | 100 ++++++++---------- 4 files changed, 50 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 978dc618d..222976d9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ All notable changes to this project will be documented in this file. ### Changed - Refactored rules ``Subscribe`` using LList allowing full message size and enabled by default -- Refactored rules USE_EXPRESSION and SUPPORT_IF_STATEMENT replacing LinkedList with arrays +- Refactored rules USE_EXPRESSION and SUPPORT_IF_STATEMENT replacing LinkedList with arrays and enabled by default ### Fixed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6bb3523fa..a9d810e33 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -165,7 +165,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - ESP32 platform update from 2023.11.01 to 2024.01.01 [#20473](https://github.com/arendst/Tasmota/issues/20473) - Renamed button "Consoles" to "Tools" - Refactored rule ``Subscribe`` using LList allowing full message size and enabled by default -- Refactored rules USE_EXPRESSION and SUPPORT_IF_STATEMENT replacing LinkedList with arrays +- Refactored rules USE_EXPRESSION and SUPPORT_IF_STATEMENT replacing LinkedList with arrays and enabled by default - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` [#20260](https://github.com/arendst/Tasmota/issues/20260) - Web file upload response on upload error [#20340](https://github.com/arendst/Tasmota/issues/20340) - Header `Host` is now collected by Webserver [#20446](https://github.com/arendst/Tasmota/issues/20446) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index dbb3af1e8..93da42e15 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -498,8 +498,8 @@ // Select none or only one of the below defines USE_RULES or USE_SCRIPT #define USE_RULES // Add support for rules (+13k code, +768 bytes mem) #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+1k8 code) -// #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k3 code) -// #define SUPPORT_IF_STATEMENT // Add support for IF statement in rules (+3k3) + #define USE_EXPRESSION // Add support for expression evaluation in rules (+1k7 code) + #define SUPPORT_IF_STATEMENT // Add support for IF statement in rules (+2k7) // #define USER_RULE1 "" // Add rule1 data saved at initial firmware load or when command reset is executed // #define USER_RULE2 "" // Add rule2 data saved at initial firmware load or when command reset is executed // #define USER_RULE3 "" // Add rule3 data saved at initial firmware load or when command reset is executed diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino index 140a6e95f..f65484f86 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino @@ -1586,10 +1586,8 @@ bool findNextOperator(char * &pointer, int8_t &op) * true - succeed * false - failed */ -float calculateTwoValues(float v1, float v2, uint8_t op) -{ - switch (op) - { +float calculateTwoValues(float v1, float v2, uint8_t op) { + switch (op) { case EXPRESSION_OPERATOR_ADD: return v1 + v2; case EXPRESSION_OPERATOR_SUBTRACT: @@ -1601,7 +1599,7 @@ float calculateTwoValues(float v1, float v2, uint8_t op) case EXPRESSION_OPERATOR_MODULO: return (0 == v2) ? 0 : (int(v1) % int(v2)); case EXPRESSION_OPERATOR_POWER: - return FastPrecisePow(v1, v2); + return FastPrecisePowf(v1, v2); } return 0; } @@ -1619,7 +1617,7 @@ float calculateTwoValues(float v1, float v2, uint8_t op) * expression - The expression to be evaluated * len - Length of the expression * Return: - * float - result. + * float - result * 0 - if the expression is invalid * An example: * MEM1 = 3, MEM2 = 6, VAR2 = 15, VAR10 = 80 @@ -1638,6 +1636,14 @@ float calculateTwoValues(float v1, float v2, uint8_t op) * 1 % 3 * 2 + 1 * 3 / 2 + * Results in: + * (10 + VAR2 ^2) = 235 + * (MEM1 * 235 - 100) = 605 + * (2 + MEM2) = 8 + * 605 % 10 = 5 + * 3.14 * 5 = 15.7 + * VAR10 / 8 = 80 / 8 = 10 + * 15.7 + 10 = 25.7 <== end result */ float evaluateExpression(const char * expression, unsigned int len) { char expbuf[len + 1]; @@ -1648,7 +1654,7 @@ float evaluateExpression(const char * expression, unsigned int len) { float object_values[21]; int8_t operators[20]; float va; - //Find and add the value of first object + // Find and add the value of first object if (findNextObjectValue(scan_pointer, va)) { object_values[0] = va; } else { @@ -1656,7 +1662,6 @@ float evaluateExpression(const char * expression, unsigned int len) { } uint32_t operators_size = 0; - uint32_t object_values_size = 1; int8_t op; while (*scan_pointer) { if (findNextOperator(scan_pointer, op) @@ -1664,77 +1669,63 @@ float evaluateExpression(const char * expression, unsigned int len) { && findNextObjectValue(scan_pointer, va)) { operators[operators_size++] = op; - object_values[object_values_size++] = va; + object_values[operators_size] = va; } else { - //No operator followed or no more object after this operator, we done. + // No operator followed or no more object after this operator, we done. break; } - if (operators_size >= 20) { AddLog(LOG_LEVEL_ERROR, PSTR("RUL: Too many arguments")); + return 0; } } +// AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: Expression '%s'"), expbuf); + // Going to evaluate the whole expression // Calculate by order of operator priorities. Looking for all operators with specified priority (from High to Low) for (int32_t priority = MAX_EXPRESSION_OPERATOR_PRIORITY; priority > 0; priority--) { int index = 0; while (index < operators_size) { - if (priority == pgm_read_byte(kExpressionOperatorsPriorities + operators[index])) { //need to calculate the operator first + if (priority == pgm_read_byte(kExpressionOperatorsPriorities + operators[index])) { // Need to calculate the operator first // Get current object value and remove the next object with current operator va = calculateTwoValues(object_values[index], object_values[index + 1], operators[index]); - uint32_t i = index; while (i <= operators_size) { operators[i++] = operators[i]; // operators.remove(index) object_values[i] = object_values[i +1]; // object_values.remove(index + 1) } - object_values_size--; operators_size--; + object_values[index] = va; // Replace the current value with the result +// AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: Intermediate '%4_f'"), &object_values[index]); -/* - uint32_t i = index +1; - while (i <= object_values_size) { - object_values[i++] = object_values[i]; // object_values.remove(index + 1) - } - object_values_size--; - - i = index; - while (i <= operators_size) { - operators[i++] = operators[i]; // operators.remove(index) - } - operators_size--; -*/ -/* - for (uint32_t i = index +1; i <= object_values_size; i++) { - object_values[i] = object_values[i +1]; // object_values.remove(index + 1) - } - object_values_size--; - - for (uint32_t i = index; i <= operators_size; i++) { - operators[i] = operators[i +1]; // operators.remove(index) - } - operators_size--; -*/ - //Replace the current value with the result - object_values[index] = va; } else { index++; } } } + +// AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: Result '%4_f'"), &object_values[0]); + return object_values[0]; } #endif // USE_EXPRESSION #ifdef SUPPORT_IF_STATEMENT -void CmndIf(void) -{ +/********************************************************************************************/ +/* + * Process an if command + * Example: + * rule1 on event#test do backlog status 1; status 2; if (var1==10 AND var3==9 OR var4==8) status 3;status 4 endif; status 5; status 6 endon + * + * Notice: + * In case of "if" is true commands ``status 3`` and ``status 4`` will be inserted into the backlog between ``status 2`` and ``status 5`` + */ +void CmndIf(void) { if (XdrvMailbox.data_len > 0) { - char parameters[XdrvMailbox.data_len+1]; - memcpy(parameters, XdrvMailbox.data, XdrvMailbox.data_len); - parameters[XdrvMailbox.data_len] = '\0'; + char parameters[XdrvMailbox.data_len +1]; + strcpy(parameters, XdrvMailbox.data); ProcessIfStatement(parameters); } ResponseCmndDone(); @@ -1928,19 +1919,19 @@ bool evaluateLogicalExpression(const char * expression, int len) { } uint32_t logicOperators_size = 0; - uint32_t values_size = 1; int8_t op; while (*pointer) { if (findNextLogicOperator(pointer, op) && (*pointer) && findNextLogicObjectValue(pointer, bValue)) { logicOperators[logicOperators_size++] = op; - values[values_size++] = bValue; + values[logicOperators_size] = bValue; } else { break; } if (logicOperators_size >= 20) { AddLog(LOG_LEVEL_ERROR, PSTR("RUL: Too many arguments")); + return false; } } @@ -1954,7 +1945,6 @@ bool evaluateLogicalExpression(const char * expression, int len) { logicOperators[i++] = logicOperators[i]; // logicOperators.remove(index); values[i] = values[i +1]; // values.remove(index + 1); } - values_size--; logicOperators_size--; } else { index++; @@ -1964,18 +1954,20 @@ bool evaluateLogicalExpression(const char * expression, int len) { index = 0; while (index < logicOperators_size) { if (logicOperators[index] == LOGIC_OPERATOR_OR) { - values[index] |= values[index+1]; + values[index] |= values[index +1]; uint32_t i = index; while (i <= logicOperators_size) { logicOperators[i++] = logicOperators[i]; // logicOperators.remove(index); values[i] = values[i +1]; // values.remove(index + 1); } - values_size--; logicOperators_size--; } else { index++; } } + +// AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: Expression '%s' = %d"), expbuff, values[0]); + return values[0]; } @@ -2058,7 +2050,6 @@ void ExecuteCommandBlock(const char * commands, int len) memcpy(cmdbuff, commands, len); cmdbuff[len] = '\0'; - //AddLog(LOG_LEVEL_DEBUG, PSTR("ExecCmd: |%s|"), cmdbuff); char oneCommand[len + 1]; //To put one command int insertPosition = 0; //When insert into backlog, we should do it by 0, 1, 2 ... char * pos = cmdbuff; @@ -2099,17 +2090,18 @@ void ExecuteCommandBlock(const char * commands, int len) //Going to insert the command into backlog char* blcommand = oneCommand; Trim(blcommand); + +// AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: Position %d, Command '%s'"), insertPosition, blcommand); + if (strlen(blcommand)) { //Insert into backlog char* temp = (char*)malloc(strlen(blcommand)+1); if (temp != nullptr) { strcpy(temp, blcommand); - char* &elem = backlog.insertAt(insertPosition); + char* &elem = backlog.insertAt(insertPosition++); elem = temp; } - insertPosition++; } - } return; } From 808e598b6dcb5bf6dc47fd725b3935a8bc5a6f84 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 24 Jan 2024 14:47:55 +0100 Subject: [PATCH 217/303] Arduino Core 3.0.0 Platform 2024.01.12 (#20576) * Core 3.0.0 latest support * compability with latest Arduino Core 3.0.0 * Platform 2024.01.12 --- lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.cpp | 8 ++++++++ lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.h | 4 ++++ platformio_tasmota32.ini | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.cpp b/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.cpp index 3dd33b95e..057b66479 100644 --- a/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.cpp +++ b/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.cpp @@ -99,7 +99,11 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fal m_valid = true; } +#if ESP_IDF_VERSION_MAJOR >= 5 +void TasmotaSerial::end() { +#else void TasmotaSerial::end(bool turnOffDebug) { +#endif // ESP_IDF_VERSION_MAJOR >= 5 #ifdef ESP8266 if (m_hardserial) { // Serial.end(); // Keep active for logging @@ -117,7 +121,11 @@ void TasmotaSerial::end(bool turnOffDebug) { #ifdef ESP32 // Serial.printf("TSR: Freeing UART%d\n", m_uart); +#if ESP_IDF_VERSION_MAJOR >= 5 + TSerial->end(); +#else TSerial->end(turnOffDebug); +#endif // ESP_IDF_VERSION_MAJOR >= 5 bitClear(tasmota_serial_uart_bitmap, m_uart); #endif // ESP32 } diff --git a/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.h b/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.h index 66caa4102..f236184e4 100644 --- a/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.h +++ b/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.h @@ -45,7 +45,11 @@ class TasmotaSerial : public Stream { size_t getRxBufferSize() { return serial_buffer_size; } bool begin(uint32_t speed = TM_SERIAL_BAUDRATE, uint32_t config = SERIAL_8N1); + #if ESP_IDF_VERSION_MAJOR >= 5 + void end(); + #else void end(bool turnOffDebug = true); + #endif // ESP_IDF_VERSION_MAJOR >= 5 bool hardwareSerial(void); int peek(void); diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index fefc60ed4..0cb63d36e 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -100,7 +100,7 @@ build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} [core32_30] -platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.11/platform-espressif32.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.12/platform-espressif32.zip platform_packages = build_unflags = ${core32.build_unflags} build_flags = ${core32.build_flags} From 2a9f9634c9bb7d1553bfadc53d8a0cf0b036f4c2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 24 Jan 2024 15:05:37 +0100 Subject: [PATCH 218/303] Update changelogs --- CHANGELOG.md | 3 ++- RELEASENOTES.md | 3 ++- lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.cpp | 10 +--------- lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.h | 6 +----- 4 files changed, 6 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 222976d9a..5c0291203 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. ### Changed - Refactored rules ``Subscribe`` using LList allowing full message size and enabled by default - Refactored rules USE_EXPRESSION and SUPPORT_IF_STATEMENT replacing LinkedList with arrays and enabled by default +- ESP32 Core3 platform update from 2024.01.11 to 2024.01.12 (#20576) ### Fixed @@ -33,7 +34,7 @@ All notable changes to this project will be documented in this file. - Zigbee ``ZbEmulation`` to selectively exclude some devices from Hue/Alexa emulation (#20552) ### Changed -- ESP32 platform update from 2024.01.00 to 2024.01.01 (#20508) +- ESP32 Core2 platform update from 2024.01.00 to 2024.01.01 (#20508) - IP stack compatible with new Core3 IPv6 implementation (#20509) - Command ``TimedPower`` from erasing all timers to showing remaining timers - ESP8266 platform update from 2024.01.00 to 2024.01.01 (#20539) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index a9d810e33..b2717beec 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -162,7 +162,8 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ### Changed - ESP8266 platform update from 2023.04.00 to 2024.01.01 [#20539](https://github.com/arendst/Tasmota/issues/20539) - ESP8266 Framework (Arduino Core) from v2.7.4.9 to v2.7.6 [#20539](https://github.com/arendst/Tasmota/issues/20539) -- ESP32 platform update from 2023.11.01 to 2024.01.01 [#20473](https://github.com/arendst/Tasmota/issues/20473) +- ESP32 Core2 platform update from 2023.11.01 to 2024.01.01 [#20473](https://github.com/arendst/Tasmota/issues/20473) +- ESP32 Core3 platform update from 2024.01.11 to 2024.01.12 [#20576](https://github.com/arendst/Tasmota/issues/20576) - Renamed button "Consoles" to "Tools" - Refactored rule ``Subscribe`` using LList allowing full message size and enabled by default - Refactored rules USE_EXPRESSION and SUPPORT_IF_STATEMENT replacing LinkedList with arrays and enabled by default diff --git a/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.cpp b/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.cpp index 057b66479..72bf19e1d 100644 --- a/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.cpp +++ b/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.cpp @@ -99,11 +99,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fal m_valid = true; } -#if ESP_IDF_VERSION_MAJOR >= 5 -void TasmotaSerial::end() { -#else -void TasmotaSerial::end(bool turnOffDebug) { -#endif // ESP_IDF_VERSION_MAJOR >= 5 +void TasmotaSerial::end(void) { #ifdef ESP8266 if (m_hardserial) { // Serial.end(); // Keep active for logging @@ -121,11 +117,7 @@ void TasmotaSerial::end(bool turnOffDebug) { #ifdef ESP32 // Serial.printf("TSR: Freeing UART%d\n", m_uart); -#if ESP_IDF_VERSION_MAJOR >= 5 TSerial->end(); -#else - TSerial->end(turnOffDebug); -#endif // ESP_IDF_VERSION_MAJOR >= 5 bitClear(tasmota_serial_uart_bitmap, m_uart); #endif // ESP32 } diff --git a/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.h b/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.h index f236184e4..c17da9eb3 100644 --- a/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.h +++ b/lib/default/TasmotaSerial-3.6.0/src/TasmotaSerial.h @@ -45,11 +45,7 @@ class TasmotaSerial : public Stream { size_t getRxBufferSize() { return serial_buffer_size; } bool begin(uint32_t speed = TM_SERIAL_BAUDRATE, uint32_t config = SERIAL_8N1); - #if ESP_IDF_VERSION_MAJOR >= 5 - void end(); - #else - void end(bool turnOffDebug = true); - #endif // ESP_IDF_VERSION_MAJOR >= 5 + void end(void); bool hardwareSerial(void); int peek(void); From 559789b4eca46d22da2f3e32668529c32496692a Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Wed, 24 Jan 2024 23:27:01 +0100 Subject: [PATCH 219/303] HASPmota support for `min` and `max` attribute in `slider` (#20582) --- CHANGELOG.md | 1 + .../berry_tasmota/src/be_lv_haspmota.c | 140 +++++++++++++++++- .../haspmota_src/haspmota_core/haspmota.be | 12 ++ 3 files changed, 151 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c0291203..d0da145f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. ## [13.3.0.4] ### Added +- HASPmota support for `min` and `max` attribute in `slider` ### Breaking Changed diff --git a/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c b/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c index c00dba442..eaa5d97b1 100644 --- a/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c +++ b/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c @@ -5195,6 +5195,72 @@ void be_load_lvh_bar_class(bvm *vm) { extern const bclass be_class_lvh_slider; +/******************************************************************** +** Solidified function: set_max +********************************************************************/ +be_local_closure(lvh_slider_set_max, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(set_range), + /* K2 */ be_nested_str_weak(get_min), + }), + be_str_weak(set_max), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x8C100102, // 0002 GETMET R4 R0 K2 + 0x7C100200, // 0003 CALL R4 1 + 0x60140009, // 0004 GETGBL R5 G9 + 0x5C180200, // 0005 MOVE R6 R1 + 0x7C140200, // 0006 CALL R5 1 + 0x7C080600, // 0007 CALL R2 3 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_min +********************************************************************/ +be_local_closure(lvh_slider_get_min, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(get_min_value), + }), + be_str_weak(get_min), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: set_val ********************************************************************/ @@ -5228,6 +5294,72 @@ be_local_closure(lvh_slider_set_val, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: get_max +********************************************************************/ +be_local_closure(lvh_slider_get_max, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(get_max_value), + }), + be_str_weak(get_max), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_min +********************************************************************/ +be_local_closure(lvh_slider_set_min, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(set_range), + /* K2 */ be_nested_str_weak(get_max), + }), + be_str_weak(set_min), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x60100009, // 0002 GETGBL R4 G9 + 0x5C140200, // 0003 MOVE R5 R1 + 0x7C100200, // 0004 CALL R4 1 + 0x8C140102, // 0005 GETMET R5 R0 K2 + 0x7C140200, // 0006 CALL R5 1 + 0x7C080600, // 0007 CALL R2 3 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified class: lvh_slider ********************************************************************/ @@ -5235,10 +5367,14 @@ extern const bclass be_class_lvh_obj; be_local_class(lvh_slider, 0, &be_class_lvh_obj, - be_nested_map(2, + be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(set_min, 5), be_const_closure(lvh_slider_set_min_closure) }, + { be_const_key_weak(_lv_class, -1), be_const_class(be_class_lv_slider) }, + { be_const_key_weak(get_min, -1), be_const_closure(lvh_slider_get_min_closure) }, { be_const_key_weak(set_val, -1), be_const_closure(lvh_slider_set_val_closure) }, - { be_const_key_weak(_lv_class, 0), be_const_class(be_class_lv_slider) }, + { be_const_key_weak(set_max, 0), be_const_closure(lvh_slider_set_max_closure) }, + { be_const_key_weak(get_max, -1), be_const_closure(lvh_slider_get_max_closure) }, })), be_str_weak(lvh_slider) ); diff --git a/tasmota/berry/haspmota_src/haspmota_core/haspmota.be b/tasmota/berry/haspmota_src/haspmota_core/haspmota.be index 40c5bb438..838a01d11 100644 --- a/tasmota/berry/haspmota_src/haspmota_core/haspmota.be +++ b/tasmota/berry/haspmota_src/haspmota_core/haspmota.be @@ -1238,6 +1238,18 @@ class lvh_slider : lvh_obj def set_val(t) self._lv_obj.set_value(t, 0) # add second parameter - no animation end + def set_min(t) + self._lv_obj.set_range(int(t), self.get_max()) + end + def set_max(t) + self._lv_obj.set_range(self.get_min(), int(t)) + end + def get_min() + return self._lv_obj.get_min_value() + end + def get_max() + return self._lv_obj.get_max_value() + end end #==================================================================== From ab49593f9ff355cb922781ffba8a7987af80d71f Mon Sep 17 00:00:00 2001 From: Barbudor Date: Thu, 25 Jan 2024 08:43:56 +0100 Subject: [PATCH 220/303] Fix QMC5883 and HLC5883 drivers breaking sensor command (#20585) * fix breaking sensor command * fix hmc5883 --- tasmota/tasmota_xsns_sensor/xsns_100_ina3221.ino | 1 + tasmota/tasmota_xsns_sensor/xsns_101_hmc5883l.ino | 6 ++++-- tasmota/tasmota_xsns_sensor/xsns_33_qmc5883l.ino | 9 ++++++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/tasmota/tasmota_xsns_sensor/xsns_100_ina3221.ino b/tasmota/tasmota_xsns_sensor/xsns_100_ina3221.ino index 3ea91a9a2..b2ec980e8 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_100_ina3221.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_100_ina3221.ino @@ -261,6 +261,7 @@ bool Ina3221CmndSensor(void) { int argc = ArgC(); if(argc != 1 && argc != 4) { + AddLog(LOG_LEVEL_DEBUG, PSTR(D_INA3221 ": Not enough arguments (1 or 4)")); return false; } diff --git a/tasmota/tasmota_xsns_sensor/xsns_101_hmc5883l.ino b/tasmota/tasmota_xsns_sensor/xsns_101_hmc5883l.ino index f460b9ba4..839eff5c0 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_101_hmc5883l.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_101_hmc5883l.ino @@ -224,6 +224,8 @@ bool HMC5883L_Command() { bool Xsns101(uint32_t function) { if (!I2cEnabled(XI2C_73)) { return false; } + bool result = false; + if (FUNC_INIT == function) { HMC5883L_Init(); } @@ -231,7 +233,7 @@ bool Xsns101(uint32_t function) { switch (function) { case FUNC_COMMAND_SENSOR: if (XSNS_101 == XdrvMailbox.index) { - return HMC5883L_Command(); // Return true on success + result = HMC5883L_Command(); // Return true on success } break; case FUNC_JSON_APPEND: @@ -247,7 +249,7 @@ bool Xsns101(uint32_t function) { #endif // USE_WEBSERVER } } - return true; + return result; } #endif // USE_HMC5883L #endif // USE_I2C diff --git a/tasmota/tasmota_xsns_sensor/xsns_33_qmc5883l.ino b/tasmota/tasmota_xsns_sensor/xsns_33_qmc5883l.ino index f024da374..b1c0cafd7 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_33_qmc5883l.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_33_qmc5883l.ino @@ -286,11 +286,18 @@ void QMC5883L_Show(uint8_t json) { bool Xsns33(uint32_t function) { if (!I2cEnabled(XI2C_71)) { return false; } + bool result = false; + if (FUNC_INIT == function) { QMC5883L_Init(); } else if (QMC5883L != nullptr) { switch (function) { + // case FUNC_COMMAND_SENSOR: + // if (XSNS_33 == XdrvMailbox.index) { + // result = QMC5883L_CmndSensor(); + // } + // break; case FUNC_JSON_APPEND: QMC5883L_Show(1); break; @@ -304,7 +311,7 @@ bool Xsns33(uint32_t function) { #endif // USE_WEBSERVER } } - return true; + return result; } #endif // USE_QMC5883L #endif // USE_I2C \ No newline at end of file From 758549c4c39f249568368d6e7318c3c8ee7e6e50 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 25 Jan 2024 14:29:12 +0100 Subject: [PATCH 221/303] Fix MLX90614 naming (#20592) --- CHANGELOG.md | 2 +- RELEASENOTES.md | 1 + tasmota/tasmota_xsns_sensor/xsns_46_MLX90614.ino | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0da145f1..b460dc3cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. ## [13.3.0.4] ### Added -- HASPmota support for `min` and `max` attribute in `slider` +- HASPmota support for `min` and `max` attribute in `slider` (#20582) ### Breaking Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index b2717beec..d983584c0 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -154,6 +154,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - LVGL option to add `lv.keyboard` extra widget [#20496](https://github.com/arendst/Tasmota/issues/20496) - HASPmota `haspmota.page_show()` to change page [#20333](https://github.com/arendst/Tasmota/issues/20333) - HASPmota type `chart` [#20372](https://github.com/arendst/Tasmota/issues/20372) +- HASPmota support for `min` and `max` attribute in `slider` [#20582](https://github.com/arendst/Tasmota/issues/20582) - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) ### Breaking Changed diff --git a/tasmota/tasmota_xsns_sensor/xsns_46_MLX90614.ino b/tasmota/tasmota_xsns_sensor/xsns_46_MLX90614.ino index c93ec08b5..96f72242c 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_46_MLX90614.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_46_MLX90614.ino @@ -68,8 +68,8 @@ void MLX90614_Every_Second(void) #ifdef USE_WEBSERVER const char HTTP_IRTMP[] PROGMEM = - "{s}MXL90614 " "OBJ-" D_TEMPERATURE "{m}%s C" "{e}" - "{s}MXL90614 " "AMB-" D_TEMPERATURE "{m}%s C" "{e}"; + "{s}MLX90614 " "OBJ-" D_TEMPERATURE "{m}%s C" "{e}" + "{s}MLX90614 " "AMB-" D_TEMPERATURE "{m}%s C" "{e}"; #endif // USE_WEBSERVER void MLX90614_Show(uint8_t json) From 52f3be51b4c2047197a377fd164867422b568669 Mon Sep 17 00:00:00 2001 From: gemu Date: Fri, 26 Jan 2024 09:11:56 +0100 Subject: [PATCH 222/303] utouch optimizations, rgb i2c init (#20596) --- lib/lib_display/UDisplay/uDisplay.cpp | 192 ++++++++++++++++---------- lib/lib_display/UDisplay/uDisplay.h | 11 +- 2 files changed, 123 insertions(+), 80 deletions(-) diff --git a/lib/lib_display/UDisplay/uDisplay.cpp b/lib/lib_display/UDisplay/uDisplay.cpp index cd671c659..9f2b54216 100755 --- a/lib/lib_display/UDisplay/uDisplay.cpp +++ b/lib/lib_display/UDisplay/uDisplay.cpp @@ -82,6 +82,21 @@ uDisplay::~uDisplay(void) { } } +#ifdef USE_UNIVERSAL_TOUCH + if (ut_init_code) { + free(ut_init_code); + } + if (ut_touch_code) { + free(ut_touch_code); + } + if (ut_getx_code) { + free(ut_getx_code); + } + if (ut_gety_code) { + free(ut_gety_code); + } +#endif // USE_UNIVERSAL_TOUCH + #ifdef USE_ESP32_S3 if (_dmadesc) { heap_caps_free(_dmadesc); @@ -112,6 +127,7 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { lutftime = 350; lut3time = 10; busy_pin = -1; + spec_init = -1; ep_mode = 0; fg_col = 1; bg_col = 0; @@ -140,17 +156,6 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { lut_array[cnt] = 0; } -#ifdef USE_UNIVERSAL_TOUCH - ut_init_code[0] = UT_RT; - ut_init_code[1] = UT_END; - ut_touch_code[0] = UT_RT; - ut_touch_code[1] = UT_END; - ut_getx_code[0] = UT_RT; - ut_getx_code[1] = UT_END; - ut_gety_code[0] = UT_RT; - ut_gety_code[1] = UT_END; -#endif // USE_UNIVERSAL_TOUCH - lut_partial = 0; lut_full = 0; char linebuff[UDSP_LBSIZE]; @@ -186,6 +191,7 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { // collect line and send directly lp1++; spi_nr = 4; + spec_init = _UDSP_SPI; spi_dc = -1; spi_miso = -1; spi_clk = next_val(&lp1); @@ -215,8 +221,30 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { Serial.printf("DSP RESET : %d\n", reset); #endif } - } - + } else if (*lp1 == 'I') { + // pecial case RGB with i2c init, bus nr, i2c addr + lp1++; + if (interface == _UDSP_RGB) { + // collect line and send directly + lp1++; + wire_n = next_val(&lp1); + i2caddr = next_hex(&lp1); +#ifdef UDSP_DEBUG + Serial.printf("I2C_INIT bus : %d\n", wire_n); + Serial.printf("I2C_INIT addr : %02x\n", i2caddr); +#endif + if (wire_n == 1) { + wire = &Wire; + } else { +#ifdef ESP32 + wire = &Wire1; +#else + wire = &Wire; +#endif + } + spec_init = _UDSP_I2C; + } + } } else if (section == 'L') { if (*lp1 >= '1' && *lp1 <= '5') { lut_num = (*lp1 & 0x07); @@ -347,8 +375,8 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { break; case 'I': // init data - if (interface == _UDSP_RGB && spi_nr == 4) { - // special case RGB with SPI init + if (interface == _UDSP_RGB && spec_init > 0) { + // special case RGB with SPI or I2C init // collect line and send directly dsp_ncmds = 0; while (1) { @@ -359,10 +387,26 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { break; } } - interface = _UDSP_SPI; - send_spi_icmds(dsp_ncmds); + if (spec_init == _UDSP_SPI) { + interface = spec_init; + send_spi_icmds(dsp_ncmds); + } else { + if (dsp_ncmds == 2) { + wire->beginTransmission(i2caddr); + wire->write(dsp_cmds[0]); + wire->write(dsp_cmds[1]); + wire->endTransmission(); +#ifdef UDSP_DEBUG + Serial.printf("reg = %02x, val = %02x\n", dsp_cmds[0], dsp_cmds[1]); +#endif + } else { + delay(dsp_cmds[0]); +#ifdef UDSP_DEBUG + Serial.printf("delay = %d ms\n", dsp_cmds[0]); +#endif + } + } interface = _UDSP_RGB; - } else { if (interface == _UDSP_I2C) { dsp_cmds[dsp_ncmds++] = next_hex(&lp1); @@ -599,19 +643,19 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { // simple resistive touch lp1++; } - ut_trans(&lp, ut_init_code, sizeof(ut_init_code)); + ut_trans(&lp, &ut_init_code); } else if (!strncmp(lp1, "TT", 2)) { lp1 += 2; // touch - ut_trans(&lp, ut_touch_code, sizeof(ut_touch_code)); + ut_trans(&lp, &ut_touch_code); } else if (!strncmp(lp1, "TX", 2)) { lp1 += 2; // get x - ut_trans(&lp, ut_getx_code, sizeof(ut_getx_code)); + ut_trans(&lp, &ut_getx_code); } else if (!strncmp(lp1, "TY", 2)) { lp1 += 2; // get y - ut_trans(&lp, ut_gety_code, sizeof(ut_gety_code)); + ut_trans(&lp, &ut_gety_code); } break; #endif // USE_UNIVERSAL_TOUCH @@ -1102,9 +1146,9 @@ Renderer *uDisplay::Init(void) { _panel_config->clk_src = LCD_CLK_SRC_PLL160M; - if (spi_speed > 14) { - spi_speed = 14; - } + //if (spi_speed > 14) { + //spi_speed = 14; + //} _panel_config->timings.pclk_hz = spi_speed*1000000; _panel_config->timings.h_res = gxs; _panel_config->timings.v_res = gys; @@ -1910,28 +1954,30 @@ void IRAM_ATTR ut_touch_irq(void) { // universal touch driver bool uDisplay::utouch_Init(char **name) { *name = ut_name; - if (ut_reset >= 0) { - pinMode(ut_reset, OUTPUT); - digitalWrite(ut_reset, HIGH); - delay(10); - digitalWrite(ut_reset, LOW); - delay(5); - digitalWrite(ut_reset, HIGH); - delay(10); - } - if (ut_irq >= 0) { - pinMode(ut_irq, INPUT ); - attachInterrupt(ut_irq, ut_touch_irq, FALLING); - } + if (ut_init_code) { + if (ut_reset >= 0) { + pinMode(ut_reset, OUTPUT); + digitalWrite(ut_reset, HIGH); + delay(10); + digitalWrite(ut_reset, LOW); + delay(5); + digitalWrite(ut_reset, HIGH); + delay(10); + } + if (ut_irq >= 0) { + pinMode(ut_irq, INPUT ); + attachInterrupt(ut_irq, ut_touch_irq, FALLING); + } - if (ut_spi_nr == spi_nr) { - ut_spi = uspi; - } else { - // not yet - ut_spi = nullptr; + if (ut_spi_nr == spi_nr) { + ut_spi = uspi; + } else { + // not yet + ut_spi = nullptr; + } + return ut_execute(ut_init_code); } - - return ut_execute(ut_init_code); + return false; } uint16_t uDisplay::touched(void) { @@ -1941,15 +1987,24 @@ uint16_t uDisplay::touched(void) { } ut_irq_flg = 0; } - return ut_execute(ut_touch_code); + if (ut_touch_code) { + return ut_execute(ut_touch_code); + } + return 0; } int16_t uDisplay::getPoint_x(void) { - return ut_execute(ut_getx_code); + if (ut_getx_code) { + return ut_execute(ut_getx_code); + } + return 0; } int16_t uDisplay::getPoint_y(void) { - return ut_execute(ut_gety_code); + if (ut_gety_code) { + return ut_execute(ut_gety_code); + } + return 0; } #endif // USE_UNIVERSAL_TOUCH @@ -2635,9 +2690,11 @@ uint32_t uDisplay::ut_par(char **lp, uint32_t mode) { } // translate pseudo opcodes to tokens -void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { +void uDisplay::ut_trans(char **sp, uint8_t **code) { char *cp = *sp; uint16_t wval; + uint8_t tmp_code[64]; + uint8_t *ut_code = tmp_code; while (*cp) { if (*cp == ':' || *cp == '#') { break; @@ -2663,14 +2720,12 @@ void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { wval = sizeof(ut_array); } *ut_code++ = wval; - size -= 4; } else if (!strncmp(cp, "RDW", 3)) { // read word one *ut_code++ = UT_RDW; wval = ut_par(&cp, 0); *ut_code++ = wval>>8; *ut_code++ = wval; - size -= 3; } else if (!strncmp(cp, "RDM", 3)) { // read many *ut_code++ = UT_RDM; @@ -2680,46 +2735,37 @@ void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { wval = sizeof(ut_array); } *ut_code++ = wval; - size -= 3; } else if (!strncmp(cp, "RD", 2)) { // read one *ut_code++ = UT_RD; *ut_code++ = ut_par(&cp, 0); - size -= 2; } else if (!strncmp(cp, "CPR", 3)) { // cmp and set *ut_code++ = UT_CPR; *ut_code++ = ut_par(&cp, 0); - size -= 2; } else if (!strncmp(cp, "CP", 2)) { // cmp and set *ut_code++ = UT_CP; *ut_code++ = ut_par(&cp, 0); - size -= 2; } else if (!strncmp(cp, "RTF", 3)) { // return when false *ut_code++ = UT_RTF; - size -= 1; } else if (!strncmp(cp, "RTT", 3)) { // return when true *ut_code++ = UT_RTT; - size -= 1; } else if (!strncmp(cp, "MVB", 3)) { // move *ut_code++ = UT_MVB; *ut_code++ = ut_par(&cp, 1); *ut_code++ = ut_par(&cp, 1); - size -= 3; } else if (!strncmp(cp, "MV", 2)) { // move *ut_code++ = UT_MV; *ut_code++ = ut_par(&cp, 1); *ut_code++ = ut_par(&cp, 1); - size -= 3; } else if (!strncmp(cp, "RT", 2)) { // return status *ut_code++ = UT_RT; - size -= 1; } else if (!strncmp(cp, "WRW", 3)) { *ut_code++ = UT_WRW; wval = ut_par(&cp, 0); @@ -2727,20 +2773,17 @@ void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { *ut_code++ = wval; wval = ut_par(&cp, 0); *ut_code++ = wval; - size -= 4; } else if (!strncmp(cp, "WR", 2)) { *ut_code++ = UT_WR; wval = ut_par(&cp, 0); *ut_code++ = wval; wval = ut_par(&cp, 0); *ut_code++ = wval; - size -= 3; } else if (!strncmp(cp, "AND", 3)) { *ut_code++ = UT_AND; wval = ut_par(&cp, 0); *ut_code++ = wval >> 8; *ut_code++ = wval; - size -= 3; } else if (!strncmp(cp, "SCL", 3)) { *ut_code++ = UT_SCALE; wval = ut_par(&cp, 1); @@ -2751,42 +2794,41 @@ void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { *ut_code++ = lval >> 16; *ut_code++ = lval >> 8; *ut_code++ = lval; - size -= 7; } else if (!strncmp(cp, "LIM", 3)) { *ut_code++ = UT_LIM; wval = ut_par(&cp, 1); *ut_code++ = wval >> 8; *ut_code++ = wval; - size -= 3; } else if (!strncmp(cp, "GSRT", 4)) { *ut_code++ = UT_GSRT; wval = ut_par(&cp, 1); *ut_code++ = wval >> 8; *ut_code++ = wval; - size -= 3; } else if (!strncmp(cp, "XPT", 3)) { *ut_code++ = UT_XPT; wval = ut_par(&cp, 1); *ut_code++ = wval >> 8; *ut_code++ = wval; - size -= 3; } else if (!strncmp(cp, "DBG", 3)) { *ut_code++ = UT_DBG; wval = ut_par(&cp, 1); *ut_code++ = wval; - size -= 2; } - if (size <= 1) { - break; - } - - - - cp++; } *ut_code++ = UT_END; *sp = cp - 1; + uint16_t memsize = (uint32_t)ut_code - (uint32_t)tmp_code; + // allocate memory + //AddLog(LOG_LEVEL_INFO, PSTR("UT-code: %d bytes"),memsize); +#ifdef UDSP_DEBUG + Serial.printf("Utouch code size : %d\n", memsize); +#endif + uint8_t *mp = (uint8_t*)malloc(memsize + 2); + if (mp) { + memmove(mp, tmp_code, memsize); + *code = mp; + } } uint8_t *uDisplay::ut_rd(uint8_t *iop, uint32_t len, uint32_t amode) { diff --git a/lib/lib_display/UDisplay/uDisplay.h b/lib/lib_display/UDisplay/uDisplay.h index 9878e865d..bf031f5fa 100755 --- a/lib/lib_display/UDisplay/uDisplay.h +++ b/lib/lib_display/UDisplay/uDisplay.h @@ -276,6 +276,7 @@ class uDisplay : public Renderer { uint8_t interface; uint8_t i2caddr; int8_t i2c_scl; + int8_t spec_init; TwoWire *wire; int8_t wire_n; int8_t i2c_sda; @@ -445,7 +446,7 @@ class uDisplay : public Renderer { #ifdef USE_UNIVERSAL_TOUCH // universal touch driver - void ut_trans(char **sp, uint8_t *ut_code, int32_t size); + void ut_trans(char **sp, uint8_t **ut_code); int16_t ut_execute(uint8_t *ut_code); uint32_t ut_par(char **cp, uint32_t mode); uint8_t *ut_rd(uint8_t *io, uint32_t len, uint32_t amode); @@ -463,10 +464,10 @@ class uDisplay : public Renderer { SPIClass *ut_spi; SPISettings ut_spiSettings; char ut_name[8]; - uint8_t ut_init_code[32]; - uint8_t ut_touch_code[32]; - uint8_t ut_getx_code[20]; - uint8_t ut_gety_code[20]; + uint8_t *ut_init_code; + uint8_t *ut_touch_code; + uint8_t *ut_getx_code; + uint8_t *ut_gety_code; #endif // USE_UNIVERSAL_TOUCH }; From 5d06a2591533b331ba30e4bcf2d5c9de8ff7dd01 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 26 Jan 2024 12:13:23 +0100 Subject: [PATCH 223/303] Add ESP32-C3 support for GPIO11 (#18350) --- CHANGELOG.md | 2 ++ RELEASENOTES.md | 2 ++ tasmota/tasmota_support/support.ino | 10 +++++++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b460dc3cb..76e5dbab7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. ## [13.3.0.4] ### Added - HASPmota support for `min` and `max` attribute in `slider` (#20582) +- ESP32-C3 support for GPIO11 (#18350) ### Breaking Changed @@ -13,6 +14,7 @@ All notable changes to this project will be documented in this file. - Refactored rules ``Subscribe`` using LList allowing full message size and enabled by default - Refactored rules USE_EXPRESSION and SUPPORT_IF_STATEMENT replacing LinkedList with arrays and enabled by default - ESP32 Core3 platform update from 2024.01.11 to 2024.01.12 (#20576) +- Utouch optimizations, rgb i2c init (#20596) ### Fixed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index d983584c0..d69d460b4 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -133,6 +133,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - ESP32 used UART information - ESP32 experimental support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled - ESP32 MI BLE support for Xiaomi LYWSD02MMC [#20381](https://github.com/arendst/Tasmota/issues/20381) +- ESP32-C3 support for GPIO11 [#18350](https://github.com/arendst/Tasmota/issues/18350) - Berry GPIO viewer initial version using async webserver [#20416](https://github.com/arendst/Tasmota/issues/20416) - Berry `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) - Berry support for `tcpclientasync` in `tcpserver` [#20401](https://github.com/arendst/Tasmota/issues/20401) @@ -171,6 +172,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Support syslog updates every sleep or every second if `#define SYSLOG_UPDATE_SECOND` [#20260](https://github.com/arendst/Tasmota/issues/20260) - Web file upload response on upload error [#20340](https://github.com/arendst/Tasmota/issues/20340) - Header `Host` is now collected by Webserver [#20446](https://github.com/arendst/Tasmota/issues/20446) +- Utouch optimizations, rgb i2c init [#20596](https://github.com/arendst/Tasmota/issues/20596) - Webcam tweaks [#20451](https://github.com/arendst/Tasmota/issues/20451) - IP stack compatible with new Core3 IPv6 implementation [#20509](https://github.com/arendst/Tasmota/issues/20509) - Refactored Pio filesystem download script [#20544](https://github.com/arendst/Tasmota/issues/20544) diff --git a/tasmota/tasmota_support/support.ino b/tasmota/tasmota_support/support.ino index c38ac087f..8966df9f2 100755 --- a/tasmota/tasmota_support/support.ino +++ b/tasmota/tasmota_support/support.ino @@ -1680,8 +1680,10 @@ bool FlashPin(uint32_t pin) { return (((pin > 5) && (pin < 9)) || (11 == pin)); #endif // ESP8266 #ifdef ESP32 -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 +#if CONFIG_IDF_TARGET_ESP32C2 return (((pin > 10) && (pin < 12)) || ((pin > 13) && (pin < 18))); // ESP32C3 has GPIOs 11-17 reserved for Flash, with some boards GPIOs 12 13 are useable +#elif CONFIG_IDF_TARGET_ESP32C3 + return ((pin > 13) && (pin < 18)); // ESP32C3 has GPIOs 11-17 reserved for Flash, with some boards GPIOs 11 12 13 are useable #elif CONFIG_IDF_TARGET_ESP32C6 return ((pin == 24) || (pin == 25) || (pin == 27) || (pin == 29) || (pin == 30)); // ESP32C6 has GPIOs 24-30 reserved for Flash, with some boards GPIOs 26 28 are useable #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 @@ -1697,8 +1699,10 @@ bool RedPin(uint32_t pin) { // Pin may be dangerous to change, displa return (9 == pin) || (10 == pin); #endif // ESP8266 #ifdef ESP32 -#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 - return (12 == pin) || (13 == pin); // ESP32C3: GPIOs 12 13 are usually used for Flash (mode QIO/QOUT) +#if CONFIG_IDF_TARGET_ESP32C2 + return (12 == pin) || (13 == pin); // ESP32C2: GPIOs 12 13 are usually used for Flash (mode QIO/QOUT) +#elif CONFIG_IDF_TARGET_ESP32C3 + return (11 == pin) || (12 == pin) || (13 == pin); // ESP32C3: GPIOs 11 12 13 are usually used for Flash (mode QIO/QOUT) #elif CONFIG_IDF_TARGET_ESP32C6 return (26 == pin) || (28 == pin); // ESP32C6: GPIOs 26 28 are usually used for Flash (mode QIO/QOUT) #elif CONFIG_IDF_TARGET_ESP32S2 From 4bc7b4ec2f8e77e65fd8bb115a181cb56cd5d383 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 26 Jan 2024 12:26:47 +0100 Subject: [PATCH 224/303] Add ESP32 support for DS18x20 on Shelly Plus Add-On (#20580) --- CHANGELOG.md | 1 + RELEASENOTES.md | 9 +- lib/lib_basic/OneWire-Stickbreaker/OneWire.h | 560 ------------------ .../OneWire.cpp | 346 +++++++++-- lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.h | 171 ++++++ .../README.md | 0 .../DS18x20_Temperature.pde | 0 .../examples/DS2408_Switch/DS2408_Switch.pde | 0 .../examples/DS250x_PROM/DS250x_PROM.pde | 0 .../keywords.txt | 0 .../library.json | 0 .../library.properties | 0 tasmota/include/tasmota_template.h | 2 - .../xsns_05_esp32_ds18x20.ino | 6 +- 14 files changed, 471 insertions(+), 624 deletions(-) delete mode 100644 lib/lib_basic/OneWire-Stickbreaker/OneWire.h rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/OneWire.cpp (70%) create mode 100644 lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.h rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/README.md (100%) rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/examples/DS18x20_Temperature/DS18x20_Temperature.pde (100%) rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/examples/DS2408_Switch/DS2408_Switch.pde (100%) rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/examples/DS250x_PROM/DS250x_PROM.pde (100%) rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/keywords.txt (100%) rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/library.json (100%) rename lib/lib_basic/{OneWire-Stickbreaker => TasmotaOneWire-2.3.3}/library.properties (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76e5dbab7..b14cdd4dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - HASPmota support for `min` and `max` attribute in `slider` (#20582) - ESP32-C3 support for GPIO11 (#18350) +- ESP32 support for DS18x20 on Shelly Plus Add-On (#20580) ### Breaking Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index d69d460b4..eda83d6f7 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -119,20 +119,21 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ## Changelog v13.3.0.4 ### Added - Command ``TimedPower [,ON|OFF|TOGGLE|BLINK]`` executes ``Power [ON|OFF|TOGGLE|BLINK] `` and after executes ``Power [OFF|ON|TOGGLE|OFF]`` -- Support for CST816S touch interface [#20213](https://github.com/arendst/Tasmota/issues/20213) -- Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247) - Display of active drivers using command ``status 4`` - GPIO Viewer to see realtime GPIO states. Enable with define USE_GPIO_VIEWER - GPIO Viewer user selection of assets website now defaults to `https://ota.tasmota.com/tasmota|tasmota32/gpio_viewer/assets` -- NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) +- Support for CST816S touch interface [#20213](https://github.com/arendst/Tasmota/issues/20213) +- Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247) - Support negative power on BL0942 using index 5..8 [#20322](https://github.com/arendst/Tasmota/issues/20322) - Support for pipsolar inverter [#20408](https://github.com/arendst/Tasmota/issues/20408) - Support for HardwareSerial invert [#15461](https://github.com/arendst/Tasmota/issues/15461) +- NeoPool hydrolysis FL1 and Redox flag [#20258](https://github.com/arendst/Tasmota/issues/20258) - SML support for IM350 [#20474](https://github.com/arendst/Tasmota/issues/20474) - GUI sensor separators [#20495](https://github.com/arendst/Tasmota/issues/20495) - ESP32 used UART information -- ESP32 experimental support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled +- ESP32 support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled - ESP32 MI BLE support for Xiaomi LYWSD02MMC [#20381](https://github.com/arendst/Tasmota/issues/20381) +- ESP32 support for DS18x20 on Shelly Plus Add-On [#20580](https://github.com/arendst/Tasmota/issues/20580) - ESP32-C3 support for GPIO11 [#18350](https://github.com/arendst/Tasmota/issues/18350) - Berry GPIO viewer initial version using async webserver [#20416](https://github.com/arendst/Tasmota/issues/20416) - Berry `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) diff --git a/lib/lib_basic/OneWire-Stickbreaker/OneWire.h b/lib/lib_basic/OneWire-Stickbreaker/OneWire.h deleted file mode 100644 index 77910ecb9..000000000 --- a/lib/lib_basic/OneWire-Stickbreaker/OneWire.h +++ /dev/null @@ -1,560 +0,0 @@ -#ifndef OneWire_h -#define OneWire_h - -#include - -#if defined(__AVR__) -#include -#endif - -#if ARDUINO >= 100 -#include "Arduino.h" // for delayMicroseconds, digitalPinToBitMask, etc -#else -#include "WProgram.h" // for delayMicroseconds -#include "pins_arduino.h" // for digitalPinToBitMask, etc -#endif - -// You can exclude certain features from OneWire. In theory, this -// might save some space. In practice, the compiler automatically -// removes unused code (technically, the linker, using -fdata-sections -// and -ffunction-sections when compiling, and Wl,--gc-sections -// when linking), so most of these will not result in any code size -// reduction. Well, unless you try to use the missing features -// and redesign your program to not need them! ONEWIRE_CRC8_TABLE -// is the exception, because it selects a fast but large algorithm -// or a small but slow algorithm. - -// you can exclude onewire_search by defining that to 0 -#ifndef ONEWIRE_SEARCH -#define ONEWIRE_SEARCH 1 -#endif - -// You can exclude CRC checks altogether by defining this to 0 -#ifndef ONEWIRE_CRC -#define ONEWIRE_CRC 1 -#endif - -// Select the table-lookup method of computing the 8-bit CRC -// by setting this to 1. The lookup table enlarges code size by -// about 250 bytes. It does NOT consume RAM (but did in very -// old versions of OneWire). If you disable this, a slower -// but very compact algorithm is used. -#ifndef ONEWIRE_CRC8_TABLE -#define ONEWIRE_CRC8_TABLE 0 -#endif - -// You can allow 16-bit CRC checks by defining this to 1 -// (Note that ONEWIRE_CRC must also be 1.) -#ifndef ONEWIRE_CRC16 -#define ONEWIRE_CRC16 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif - -// Platform specific I/O definitions - -#if defined(__AVR__) -#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin))) -#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) -#define IO_REG_TYPE uint8_t -#define IO_REG_BASE_ATTR asm("r30") -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0) -#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) &= ~(mask)) -#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+1)) |= (mask)) -#define DIRECT_WRITE_LOW(base, mask) ((*((base)+2)) &= ~(mask)) -#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+2)) |= (mask)) - -#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK66FX1M0__) || defined(__MK64FX512__) -#define PIN_TO_BASEREG(pin) (portOutputRegister(pin)) -#define PIN_TO_BITMASK(pin) (1) -#define IO_REG_TYPE uint8_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR __attribute__ ((unused)) -#define DIRECT_READ(base, mask) (*((base)+512)) -#define DIRECT_MODE_INPUT(base, mask) (*((base)+640) = 0) -#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+640) = 1) -#define DIRECT_WRITE_LOW(base, mask) (*((base)+256) = 1) -#define DIRECT_WRITE_HIGH(base, mask) (*((base)+128) = 1) - -#elif defined(__MKL26Z64__) -#define PIN_TO_BASEREG(pin) (portOutputRegister(pin)) -#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) -#define IO_REG_TYPE uint8_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, mask) ((*((base)+16) & (mask)) ? 1 : 0) -#define DIRECT_MODE_INPUT(base, mask) (*((base)+20) &= ~(mask)) -#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+20) |= (mask)) -#define DIRECT_WRITE_LOW(base, mask) (*((base)+8) = (mask)) -#define DIRECT_WRITE_HIGH(base, mask) (*((base)+4) = (mask)) - -#elif defined(__SAM3X8E__) || defined(__SAM3A8C__) || defined(__SAM3A4C__) -// Arduino 1.5.1 may have a bug in delayMicroseconds() on Arduino Due. -// http://arduino.cc/forum/index.php/topic,141030.msg1076268.html#msg1076268 -// If you have trouble with OneWire on Arduino Due, please check the -// status of delayMicroseconds() before reporting a bug in OneWire! -#define PIN_TO_BASEREG(pin) (&(digitalPinToPort(pin)->PIO_PER)) -#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, mask) (((*((base)+15)) & (mask)) ? 1 : 0) -#define DIRECT_MODE_INPUT(base, mask) ((*((base)+5)) = (mask)) -#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+4)) = (mask)) -#define DIRECT_WRITE_LOW(base, mask) ((*((base)+13)) = (mask)) -#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+12)) = (mask)) -#ifndef PROGMEM -#define PROGMEM -#endif -#ifndef pgm_read_byte -#define pgm_read_byte(addr) (*(const uint8_t *)(addr)) -#endif - -#elif defined(__PIC32MX__) -#define PIN_TO_BASEREG(pin) (portModeRegister(digitalPinToPort(pin))) -#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, mask) (((*(base+4)) & (mask)) ? 1 : 0) //PORTX + 0x10 -#define DIRECT_MODE_INPUT(base, mask) ((*(base+2)) = (mask)) //TRISXSET + 0x08 -#define DIRECT_MODE_OUTPUT(base, mask) ((*(base+1)) = (mask)) //TRISXCLR + 0x04 -#define DIRECT_WRITE_LOW(base, mask) ((*(base+8+1)) = (mask)) //LATXCLR + 0x24 -#define DIRECT_WRITE_HIGH(base, mask) ((*(base+8+2)) = (mask)) //LATXSET + 0x28 - -#elif defined(ARDUINO_ARCH_ESP8266) -// Special note: I depend on the ESP community to maintain these definitions and -// submit good pull requests. I can not answer any ESP questions or help you -// resolve any problems related to ESP chips. Please do not contact me and please -// DO NOT CREATE GITHUB ISSUES for ESP support. All ESP questions must be asked -// on ESP community forums. -#define PIN_TO_BASEREG(pin) ((volatile uint32_t*) GPO) -#define PIN_TO_BITMASK(pin) (1 << pin) -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, mask) ((GPI & (mask)) ? 1 : 0) //GPIO_IN_ADDRESS -#define DIRECT_MODE_INPUT(base, mask) (GPE &= ~(mask)) //GPIO_ENABLE_W1TC_ADDRESS -#define DIRECT_MODE_OUTPUT(base, mask) (GPE |= (mask)) //GPIO_ENABLE_W1TS_ADDRESS -#define DIRECT_WRITE_LOW(base, mask) (GPOC = (mask)) //GPIO_OUT_W1TC_ADDRESS -#define DIRECT_WRITE_HIGH(base, mask) (GPOS = (mask)) //GPIO_OUT_W1TS_ADDRESS - -#elif defined(ARDUINO_ARCH_ESP32) -#include -#if ESP_IDF_VERSION_MAJOR >= 5 -#include "soc/gpio_periph.h" -#endif // ESP_IDF_VERSION_MAJOR >= 5 -#define PIN_TO_BASEREG(pin) (0) -#define PIN_TO_BITMASK(pin) (pin) -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR - -static inline __attribute__((always_inline)) -IO_REG_TYPE directRead(IO_REG_TYPE pin) -{ -// return digitalRead(pin); // Works most of the time -// return gpio_ll_get_level(&GPIO, pin); // The hal is not public api, don't use in application code - -//#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 -#if SOC_GPIO_PIN_COUNT <= 32 - return (GPIO.in.val >> pin) & 0x1; -#else // ESP32 with over 32 gpios - if ( pin < 32 ) - return (GPIO.in >> pin) & 0x1; - else - return (GPIO.in1.val >> (pin - 32)) & 0x1; -#endif - return 0; - -} - -static inline __attribute__((always_inline)) -void directWriteLow(IO_REG_TYPE pin) -{ -// digitalWrite(pin, 0); // Works most of the time -// gpio_ll_set_level(&GPIO, pin, 0); // The hal is not public api, don't use in application code - -//#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 -#if SOC_GPIO_PIN_COUNT <= 32 - GPIO.out_w1tc.val = ((uint32_t)1 << pin); -#else // ESP32 with over 32 gpios - if ( pin < 32 ) - GPIO.out_w1tc = ((uint32_t)1 << pin); - else - GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32)); -#endif -} - -static inline __attribute__((always_inline)) -void directWriteHigh(IO_REG_TYPE pin) -{ -// digitalWrite(pin, 1); // Works most of the time -// gpio_ll_set_level(&GPIO, pin, 1); // The hal is not public api, don't use in application code - -//#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 -#if SOC_GPIO_PIN_COUNT <= 32 - GPIO.out_w1ts.val = ((uint32_t)1 << pin); -#else // ESP32 with over 32 gpios - if ( pin < 32 ) - GPIO.out_w1ts = ((uint32_t)1 << pin); - else - GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32)); -#endif - -} - -static inline __attribute__((always_inline)) -void directModeInput(IO_REG_TYPE pin) -{ -// pinMode(pin, INPUT); // Too slow - doesn't work -// gpio_ll_output_disable(&GPIO, pin); // The hal is not public api, don't use in application code - - if ( digitalPinIsValid(pin) ) - { - // Input -//#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 -#if SOC_GPIO_PIN_COUNT <= 32 - GPIO.enable_w1tc.val = ((uint32_t)1 << (pin)); -#else // ESP32 with over 32 gpios - if ( pin < 32 ) - GPIO.enable_w1tc = ((uint32_t)1 << pin); - else - GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32)); -#endif - } - -} - -static inline __attribute__((always_inline)) -void directModeOutput(IO_REG_TYPE pin) -{ -// pinMode(pin, OUTPUT); // Too slow - doesn't work -// gpio_ll_output_enable(&GPIO, pin); // The hal is not public api, don't use in application code - - if ( digitalPinCanOutput(pin) ) - { - // Output -//#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 -#if SOC_GPIO_PIN_COUNT <= 32 - GPIO.enable_w1ts.val = ((uint32_t)1 << (pin)); -#else // ESP32 with over 32 gpios - if ( pin < 32 ) - GPIO.enable_w1ts = ((uint32_t)1 << pin); - else - GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32)); -#endif - } - -} - -#define DIRECT_READ(base, pin) directRead(pin) -#define DIRECT_WRITE_LOW(base, pin) directWriteLow(pin) -#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(pin) -#define DIRECT_MODE_INPUT(base, pin) directModeInput(pin) -#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(pin) - -#elif defined(__SAMD21G18A__) -#define PIN_TO_BASEREG(pin) portModeRegister(digitalPinToPort(pin)) -#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, mask) (((*((base)+8)) & (mask)) ? 1 : 0) -#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) = (mask)) -#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+2)) = (mask)) -#define DIRECT_WRITE_LOW(base, mask) ((*((base)+5)) = (mask)) -#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+6)) = (mask)) - -#elif defined(RBL_NRF51822) -#define PIN_TO_BASEREG(pin) (0) -#define PIN_TO_BITMASK(pin) (pin) -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, pin) nrf_gpio_pin_read(pin) -#define DIRECT_WRITE_LOW(base, pin) nrf_gpio_pin_clear(pin) -#define DIRECT_WRITE_HIGH(base, pin) nrf_gpio_pin_set(pin) -#define DIRECT_MODE_INPUT(base, pin) nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL) -#define DIRECT_MODE_OUTPUT(base, pin) nrf_gpio_cfg_output(pin) - -#elif defined(__arc__) /* Arduino101/Genuino101 specifics */ - -#include "scss_registers.h" -#include "portable.h" -#include "avr/pgmspace.h" - -#define GPIO_ID(pin) (g_APinDescription[pin].ulGPIOId) -#define GPIO_TYPE(pin) (g_APinDescription[pin].ulGPIOType) -#define GPIO_BASE(pin) (g_APinDescription[pin].ulGPIOBase) -#define DIR_OFFSET_SS 0x01 -#define DIR_OFFSET_SOC 0x04 -#define EXT_PORT_OFFSET_SS 0x0A -#define EXT_PORT_OFFSET_SOC 0x50 - -/* GPIO registers base address */ -#define PIN_TO_BASEREG(pin) ((volatile uint32_t *)g_APinDescription[pin].ulGPIOBase) -#define PIN_TO_BITMASK(pin) pin -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR - -static inline __attribute__((always_inline)) -IO_REG_TYPE directRead(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) -{ - IO_REG_TYPE ret; - if (SS_GPIO == GPIO_TYPE(pin)) { - ret = READ_ARC_REG(((IO_REG_TYPE)base + EXT_PORT_OFFSET_SS)); - } else { - ret = MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, EXT_PORT_OFFSET_SOC); - } - return ((ret >> GPIO_ID(pin)) & 0x01); -} - -static inline __attribute__((always_inline)) -void directModeInput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) -{ - if (SS_GPIO == GPIO_TYPE(pin)) { - WRITE_ARC_REG(READ_ARC_REG((((IO_REG_TYPE)base) + DIR_OFFSET_SS)) & ~(0x01 << GPIO_ID(pin)), - ((IO_REG_TYPE)(base) + DIR_OFFSET_SS)); - } else { - MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) &= ~(0x01 << GPIO_ID(pin)); - } -} - -static inline __attribute__((always_inline)) -void directModeOutput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) -{ - if (SS_GPIO == GPIO_TYPE(pin)) { - WRITE_ARC_REG(READ_ARC_REG(((IO_REG_TYPE)(base) + DIR_OFFSET_SS)) | (0x01 << GPIO_ID(pin)), - ((IO_REG_TYPE)(base) + DIR_OFFSET_SS)); - } else { - MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) |= (0x01 << GPIO_ID(pin)); - } -} - -static inline __attribute__((always_inline)) -void directWriteLow(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) -{ - if (SS_GPIO == GPIO_TYPE(pin)) { - WRITE_ARC_REG(READ_ARC_REG(base) & ~(0x01 << GPIO_ID(pin)), base); - } else { - MMIO_REG_VAL(base) &= ~(0x01 << GPIO_ID(pin)); - } -} - -static inline __attribute__((always_inline)) -void directWriteHigh(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) -{ - if (SS_GPIO == GPIO_TYPE(pin)) { - WRITE_ARC_REG(READ_ARC_REG(base) | (0x01 << GPIO_ID(pin)), base); - } else { - MMIO_REG_VAL(base) |= (0x01 << GPIO_ID(pin)); - } -} - -#define DIRECT_READ(base, pin) directRead(base, pin) -#define DIRECT_MODE_INPUT(base, pin) directModeInput(base, pin) -#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(base, pin) -#define DIRECT_WRITE_LOW(base, pin) directWriteLow(base, pin) -#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(base, pin) - -#elif defined(__riscv) - -/* - * Tested on highfive1 - * - * Stable results are achieved operating in the - * two high speed modes of the highfive1. It - * seems to be less reliable in slow mode. - */ -#define PIN_TO_BASEREG(pin) (0) -#define PIN_TO_BITMASK(pin) digitalPinToBitMask(pin) -#define IO_REG_TYPE uint32_t -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR - -static inline __attribute__((always_inline)) -IO_REG_TYPE directRead(IO_REG_TYPE mask) -{ - return ((GPIO_REG(GPIO_INPUT_VAL) & mask) != 0) ? 1 : 0; -} - -static inline __attribute__((always_inline)) -void directModeInput(IO_REG_TYPE mask) -{ - GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask; - GPIO_REG(GPIO_IOF_EN) &= ~mask; - - GPIO_REG(GPIO_INPUT_EN) |= mask; - GPIO_REG(GPIO_OUTPUT_EN) &= ~mask; -} - -static inline __attribute__((always_inline)) -void directModeOutput(IO_REG_TYPE mask) -{ - GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask; - GPIO_REG(GPIO_IOF_EN) &= ~mask; - - GPIO_REG(GPIO_INPUT_EN) &= ~mask; - GPIO_REG(GPIO_OUTPUT_EN) |= mask; -} - -static inline __attribute__((always_inline)) -void directWriteLow(IO_REG_TYPE mask) -{ - GPIO_REG(GPIO_OUTPUT_VAL) &= ~mask; -} - -static inline __attribute__((always_inline)) -void directWriteHigh(IO_REG_TYPE mask) -{ - GPIO_REG(GPIO_OUTPUT_VAL) |= mask; -} - -#define DIRECT_READ(base, mask) directRead(mask) -#define DIRECT_WRITE_LOW(base, mask) directWriteLow(mask) -#define DIRECT_WRITE_HIGH(base, mask) directWriteHigh(mask) -#define DIRECT_MODE_INPUT(base, mask) directModeInput(mask) -#define DIRECT_MODE_OUTPUT(base, mask) directModeOutput(mask) - -#else -#define PIN_TO_BASEREG(pin) (0) -#define PIN_TO_BITMASK(pin) (pin) -#define IO_REG_TYPE unsigned int -#define IO_REG_BASE_ATTR -#define IO_REG_MASK_ATTR -#define DIRECT_READ(base, pin) digitalRead(pin) -#define DIRECT_WRITE_LOW(base, pin) digitalWrite(pin, LOW) -#define DIRECT_WRITE_HIGH(base, pin) digitalWrite(pin, HIGH) -#define DIRECT_MODE_INPUT(base, pin) pinMode(pin,INPUT) -#define DIRECT_MODE_OUTPUT(base, pin) pinMode(pin,OUTPUT) -#warning "OneWire. Fallback mode. Using API calls for pinMode,digitalRead and digitalWrite. Operation of this library is not guaranteed on this architecture." - -#endif - - -class OneWire -{ - private: - IO_REG_TYPE bitmask; - volatile IO_REG_TYPE *baseReg; - -#if ONEWIRE_SEARCH - // global search state - unsigned char ROM_NO[8]; - uint8_t LastDiscrepancy; - uint8_t LastFamilyDiscrepancy; - uint8_t LastDeviceFlag; -#endif - - public: - OneWire( uint8_t pin); - - // Perform a 1-Wire reset cycle. Returns 1 if a device responds - // with a presence pulse. Returns 0 if there is no device or the - // bus is shorted or otherwise held low for more than 250uS - uint8_t reset(void); - - // Issue a 1-Wire rom select command, you do the reset first. - void select(const uint8_t rom[8]); - - // Issue a 1-Wire rom skip command, to address all on bus. - void skip(void); - - // Write a byte. If 'power' is one then the wire is held high at - // the end for parasitically powered devices. You are responsible - // for eventually depowering it by calling depower() or doing - // another read or write. - void write(uint8_t v, uint8_t power = 0); - - void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0); - - // Read a byte. - uint8_t read(void); - - void read_bytes(uint8_t *buf, uint16_t count); - - // Write a bit. The bus is always left powered at the end, see - // note in write() about that. - void write_bit(uint8_t v); - - // Read a bit. - uint8_t read_bit(void); - - // Stop forcing power onto the bus. You only need to do this if - // you used the 'power' flag to write() or used a write_bit() call - // and aren't about to do another read or write. You would rather - // not leave this powered if you don't have to, just in case - // someone shorts your bus. - void depower(void); - -#if ONEWIRE_SEARCH - // Clear the search state so that if will start from the beginning again. - void reset_search(); - - // Setup the search to find the device type 'family_code' on the next call - // to search(*newAddr) if it is present. - void target_search(uint8_t family_code); - - // Look for the next device. Returns 1 if a new address has been - // returned. A zero might mean that the bus is shorted, there are - // no devices, or you have already retrieved all of them. It - // might be a good idea to check the CRC to make sure you didn't - // get garbage. The order is deterministic. You will always get - // the same devices in the same order. - uint8_t search(uint8_t *newAddr, bool search_mode = true); -#endif - -#if ONEWIRE_CRC - // Compute a Dallas Semiconductor 8 bit CRC, these are used in the - // ROM and scratchpad registers. - static uint8_t crc8(const uint8_t *addr, uint8_t len); - -#if ONEWIRE_CRC16 - // Compute the 1-Wire CRC16 and compare it against the received CRC. - // Example usage (reading a DS2408): - // // Put everything in a buffer so we can compute the CRC easily. - // uint8_t buf[13]; - // buf[0] = 0xF0; // Read PIO Registers - // buf[1] = 0x88; // LSB address - // buf[2] = 0x00; // MSB address - // WriteBytes(net, buf, 3); // Write 3 cmd bytes - // ReadBytes(net, buf+3, 10); // Read 6 data bytes, 2 0xFF, 2 CRC16 - // if (!CheckCRC16(buf, 11, &buf[11])) { - // // Handle error. - // } - // - // @param input - Array of bytes to checksum. - // @param len - How many bytes to use. - // @param inverted_crc - The two CRC16 bytes in the received data. - // This should just point into the received data, - // *not* at a 16-bit integer. - // @param crc - The crc starting value (optional) - // @return True, iff the CRC matches. - static bool check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc = 0); - - // Compute a Dallas Semiconductor 16 bit CRC. This is required to check - // the integrity of data received from many 1-Wire devices. Note that the - // CRC computed here is *not* what you'll get from the 1-Wire network, - // for two reasons: - // 1) The CRC is transmitted bitwise inverted. - // 2) Depending on the endian-ness of your processor, the binary - // representation of the two-byte return value may have a different - // byte order than the two bytes you get from 1-Wire. - // @param input - Array of bytes to checksum. - // @param len - How many bytes to use. - // @param crc - The crc starting value (optional) - // @return The CRC16, as defined by Dallas Semiconductor. - static uint16_t crc16(const uint8_t* input, uint16_t len, uint16_t crc = 0); -#endif -#endif -}; - -#endif diff --git a/lib/lib_basic/OneWire-Stickbreaker/OneWire.cpp b/lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.cpp similarity index 70% rename from lib/lib_basic/OneWire-Stickbreaker/OneWire.cpp rename to lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.cpp index 404e8b272..01c65d3d4 100644 --- a/lib/lib_basic/OneWire-Stickbreaker/OneWire.cpp +++ b/lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.cpp @@ -33,6 +33,12 @@ OneWire is now very mature code. No changes other than adding definitions for newer hardware support are anticipated. ======= +Version 2.3.3 Tasmota 26JAN2024 + Add support for Shelly Add-On by Theo Arends + +Version 2.3.3 Tasmota 15AUG2023 + Add support for ESP32 Arduino core 3 by @Jason2866 + Version 2.3.3 ESP32 Stickbreaker 06MAY2019 Add a #ifdef to isolate ESP32 mods Version 2.3.1 ESP32 everslick 30APR2018 @@ -152,19 +158,180 @@ sample code bearing this copyright. #include "OneWire.h" -#ifdef ESP32 +// Platform specific I/O definitions + +#if defined(ARDUINO_ARCH_ESP8266) +// Special note: I depend on the ESP community to maintain these definitions and +// submit good pull requests. I can not answer any ESP questions or help you +// resolve any problems related to ESP chips. Please do not contact me and please +// DO NOT CREATE GITHUB ISSUES for ESP support. All ESP questions must be asked +// on ESP community forums. +#define PIN_TO_BASEREG(pin) ((volatile uint32_t*) GPO) +#define PIN_TO_BITMASK(pin) (1UL << pin) +#define IO_REG_TYPE uint32_t +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR + +static inline __attribute__((always_inline)) +void directModeInput(IO_REG_TYPE mask) +{ + if(mask > 0x8000) + { + GP16FFS(GPFFS_GPIO(16)); + GPC16 = 0; + GP16E &= ~1; + } + else + { + GPE &= ~(mask); + } +} + +static inline __attribute__((always_inline)) +void directModeOutput(IO_REG_TYPE mask) +{ + if(mask > 0x8000) + { + GP16FFS(GPFFS_GPIO(16)); + GPC16 = 0; + GP16E |= 1; + } + else + { + GPE |= (mask); + } +} + +static inline __attribute__((always_inline)) +bool directRead(IO_REG_TYPE mask) +{ + if(mask > 0x8000) + return GP16I & 0x01; + else + return ((GPI & (mask)) ? true : false); +} + +#define DIRECT_READ(base, mask) directRead(mask) +#define DIRECT_MODE_INPUT(base, mask) directModeInput(mask) +#define DIRECT_MODE_OUTPUT(base, mask) directModeOutput(mask) +#define DIRECT_WRITE_LOW(base, mask) (mask > 0x8000) ? GP16O &= ~1 : (GPOC = (mask)) +#define DIRECT_WRITE_HIGH(base, mask) (mask > 0x8000) ? GP16O |= 1 : (GPOS = (mask)) + +#define CRIT_TIMING #define t_noInterrupts() {portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;portENTER_CRITICAL(&mux) #define t_interrupts() portEXIT_CRITICAL(&mux);} -#else -#define t_noInterrupts noInterrupts -#define t_interrupts interrupts + +#elif defined(ARDUINO_ARCH_ESP32) +#include +#if ESP_IDF_VERSION_MAJOR >= 5 +#include "soc/gpio_periph.h" +#endif // ESP_IDF_VERSION_MAJOR >= 5 +#define PIN_TO_BASEREG(pin) (0) +#define PIN_TO_BITMASK(pin) (pin) +#define IO_REG_TYPE uint32_t +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR + +static inline __attribute__((always_inline)) +IO_REG_TYPE directRead(IO_REG_TYPE pin) +{ +#if SOC_GPIO_PIN_COUNT <= 32 + return (GPIO.in.val >> pin) & 0x1; +#else // ESP32 with over 32 gpios + if ( pin < 32 ) + return (GPIO.in >> pin) & 0x1; + else + return (GPIO.in1.val >> (pin - 32)) & 0x1; +#endif + return 0; + +} + +static inline __attribute__((always_inline)) +void directWriteLow(IO_REG_TYPE pin) +{ +#if SOC_GPIO_PIN_COUNT <= 32 + GPIO.out_w1tc.val = ((uint32_t)1 << pin); +#else // ESP32 with over 32 gpios + if ( pin < 32 ) + GPIO.out_w1tc = ((uint32_t)1 << pin); + else + GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32)); +#endif +} + +static inline __attribute__((always_inline)) +void directWriteHigh(IO_REG_TYPE pin) +{ +#if SOC_GPIO_PIN_COUNT <= 32 + GPIO.out_w1ts.val = ((uint32_t)1 << pin); +#else // ESP32 with over 32 gpios + if ( pin < 32 ) + GPIO.out_w1ts = ((uint32_t)1 << pin); + else + GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32)); #endif -OneWire::OneWire(uint8_t pin) +} + +static inline __attribute__((always_inline)) +void directModeInput(IO_REG_TYPE pin) { + if ( digitalPinIsValid(pin) ) + { + // Input +#if SOC_GPIO_PIN_COUNT <= 32 + GPIO.enable_w1tc.val = ((uint32_t)1 << (pin)); +#else // ESP32 with over 32 gpios + if ( pin < 32 ) + GPIO.enable_w1tc = ((uint32_t)1 << pin); + else + GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32)); +#endif + } + +} + +static inline __attribute__((always_inline)) +void directModeOutput(IO_REG_TYPE pin) +{ + if ( digitalPinCanOutput(pin) ) + { + // Output +#if SOC_GPIO_PIN_COUNT <= 32 + GPIO.enable_w1ts.val = ((uint32_t)1 << (pin)); +#else // ESP32 with over 32 gpios + if ( pin < 32 ) + GPIO.enable_w1ts = ((uint32_t)1 << pin); + else + GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32)); +#endif + } + +} + +#define DIRECT_READ(base, pin) directRead(pin) +#define DIRECT_WRITE_LOW(base, pin) directWriteLow(pin) +#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(pin) +#define DIRECT_MODE_INPUT(base, pin) directModeInput(pin) +#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(pin) + +#define CRIT_TIMING IRAM_ATTR +#define t_noInterrupts noInterrupts +#define t_interrupts interrupts + +#endif + +OneWire::OneWire(uint8_t pin, int8_t pin_out) { pinMode(pin, INPUT); bitmask = PIN_TO_BITMASK(pin); baseReg = PIN_TO_BASEREG(pin); + dual_mode = (pin_out > -1); + if (dual_mode) { + pinMode(pin_out, OUTPUT); + bitmask_out = PIN_TO_BITMASK(pin_out); + baseReg_out = PIN_TO_BASEREG(pin_out); + } #if ONEWIRE_SEARCH reset_search(); #endif @@ -177,19 +344,19 @@ OneWire::OneWire(uint8_t pin) // // Returns 1 if a device asserted a presence pulse, 0 otherwise. // -#ifdef ARDUINO_ARCH_ESP32 -uint8_t IRAM_ATTR OneWire::reset(void) -#else -uint8_t OneWire::reset(void) -#endif +uint8_t CRIT_TIMING OneWire::reset(void) { - IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; - volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg; - uint8_t r; - uint8_t retries = 125; + IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; + volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg; + + uint8_t r; + uint8_t retries = 125; + + if (!dual_mode) { t_noInterrupts(); DIRECT_MODE_INPUT(reg, mask); t_interrupts(); + // wait until the wire is high... just in case do { if (--retries == 0) return 0; @@ -204,7 +371,33 @@ uint8_t OneWire::reset(void) delayMicroseconds(70); r = !DIRECT_READ(reg, mask); t_interrupts(); + delayMicroseconds(410); + } else { + IO_REG_TYPE mask_out IO_REG_MASK_ATTR = bitmask_out; + volatile IO_REG_TYPE *reg_out IO_REG_BASE_ATTR = baseReg_out; + + t_noInterrupts(); + DIRECT_WRITE_HIGH(reg_out, mask_out); + t_interrupts(); + + // wait until the wire is high... just in case + do { + if (--retries == 0) return 0; + delayMicroseconds(2); + } while ( !DIRECT_READ(reg, mask)); + + t_noInterrupts(); + DIRECT_WRITE_LOW(reg_out, mask_out); + delayMicroseconds(480); + DIRECT_WRITE_HIGH(reg_out, mask_out); + delayMicroseconds(70); + r = !DIRECT_READ(reg, mask); + t_interrupts(); + + delayMicroseconds(410); + } + return r; } @@ -212,57 +405,84 @@ uint8_t OneWire::reset(void) // Write a bit. Port and bit is used to cut lookup time and provide // more certain timing. // -#ifdef ARDUINO_ARCH_ESP32 -void IRAM_ATTR OneWire::write_bit(uint8_t v) -#else -void OneWire::write_bit(uint8_t v) -#endif +void CRIT_TIMING OneWire::write_bit(uint8_t v) { IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg; - if (v & 1) { - t_noInterrupts(); - DIRECT_WRITE_LOW(reg, mask); - DIRECT_MODE_OUTPUT(reg, mask); // drive output low - delayMicroseconds(10); - DIRECT_WRITE_HIGH(reg, mask); // drive output high - t_interrupts(); - delayMicroseconds(55); - } else { - t_noInterrupts(); - DIRECT_WRITE_LOW(reg, mask); - DIRECT_MODE_OUTPUT(reg, mask); // drive output low - delayMicroseconds(65); - DIRECT_WRITE_HIGH(reg, mask); // drive output high - t_interrupts(); - delayMicroseconds(5); - } + if (!dual_mode) { + if (v & 1) { + t_noInterrupts(); + DIRECT_WRITE_LOW(reg, mask); + DIRECT_MODE_OUTPUT(reg, mask); // drive output low + delayMicroseconds(10); + DIRECT_WRITE_HIGH(reg, mask); // drive output high + t_interrupts(); + delayMicroseconds(55); + } else { + t_noInterrupts(); + DIRECT_WRITE_LOW(reg, mask); + DIRECT_MODE_OUTPUT(reg, mask); // drive output low + delayMicroseconds(65); + DIRECT_WRITE_HIGH(reg, mask); // drive output high + t_interrupts(); + delayMicroseconds(5); + } + } else { + IO_REG_TYPE mask_out IO_REG_MASK_ATTR = bitmask_out; + volatile IO_REG_TYPE *reg_out IO_REG_BASE_ATTR = baseReg_out; + + if (v & 1) { + t_noInterrupts(); + DIRECT_WRITE_LOW(reg_out, mask_out); + delayMicroseconds(10); + DIRECT_WRITE_HIGH(reg_out, mask_out); // drive output high + t_interrupts(); + delayMicroseconds(55); + } else { + t_noInterrupts(); + DIRECT_WRITE_LOW(reg_out, mask_out); + delayMicroseconds(65); + DIRECT_WRITE_HIGH(reg_out, mask_out); // drive output high + t_interrupts(); + delayMicroseconds(5); + } + } } // // Read a bit. Port and bit is used to cut lookup time and provide // more certain timing. // -#ifdef ARDUINO_ARCH_ESP32 -uint8_t IRAM_ATTR OneWire::read_bit(void) -#else -uint8_t OneWire::read_bit(void) -#endif +uint8_t CRIT_TIMING OneWire::read_bit(void) { IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg; uint8_t r; - t_noInterrupts(); - DIRECT_MODE_OUTPUT(reg, mask); - DIRECT_WRITE_LOW(reg, mask); - delayMicroseconds(3); - DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise - delayMicroseconds(10); - r = DIRECT_READ(reg, mask); - t_interrupts(); - delayMicroseconds(53); + if (!dual_mode) { + t_noInterrupts(); + DIRECT_MODE_OUTPUT(reg, mask); + DIRECT_WRITE_LOW(reg, mask); + delayMicroseconds(3); + DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise + delayMicroseconds(10); + r = DIRECT_READ(reg, mask); + t_interrupts(); + delayMicroseconds(53); + } else { + IO_REG_TYPE mask_out IO_REG_MASK_ATTR = bitmask_out; + volatile IO_REG_TYPE *reg_out IO_REG_BASE_ATTR = baseReg_out; + + t_noInterrupts(); + DIRECT_WRITE_LOW(reg_out, mask_out); + delayMicroseconds(3); + DIRECT_WRITE_HIGH(reg_out, mask_out); + delayMicroseconds(10); + r = DIRECT_READ(reg, mask); + t_interrupts(); + delayMicroseconds(53); + } return r; } @@ -280,10 +500,16 @@ void OneWire::write(uint8_t v, uint8_t power /* = 0 */) { OneWire::write_bit( (bitMask & v)?1:0); } if ( !power) { + if (!dual_mode) { t_noInterrupts(); DIRECT_MODE_INPUT(baseReg, bitmask); DIRECT_WRITE_LOW(baseReg, bitmask); t_interrupts(); + } else { +// t_noInterrupts(); +// DIRECT_WRITE_LOW(baseReg_out, bitmask_out); +// t_interrupts(); + } } } @@ -291,10 +517,16 @@ void OneWire::write_bytes(const uint8_t *buf, uint16_t count, bool power /* = 0 for (uint16_t i = 0 ; i < count ; i++) write(buf[i]); if (!power) { - t_noInterrupts(); - DIRECT_MODE_INPUT(baseReg, bitmask); - DIRECT_WRITE_LOW(baseReg, bitmask); - t_interrupts(); + if (!dual_mode) { + t_noInterrupts(); + DIRECT_MODE_INPUT(baseReg, bitmask); + DIRECT_WRITE_LOW(baseReg, bitmask); + t_interrupts(); + } else { +// t_noInterrupts(); +// DIRECT_WRITE_LOW(baseReg_out, bitmask_out); +// t_interrupts(); + } } } @@ -338,9 +570,9 @@ void OneWire::skip() void OneWire::depower() { - t_noInterrupts(); - DIRECT_MODE_INPUT(baseReg, bitmask); - t_interrupts(); +// t_noInterrupts(); +// DIRECT_MODE_INPUT(baseReg, bitmask); +// t_interrupts(); } #if ONEWIRE_SEARCH diff --git a/lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.h b/lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.h new file mode 100644 index 000000000..fcef2bd20 --- /dev/null +++ b/lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.h @@ -0,0 +1,171 @@ +#ifndef OneWire_h +#define OneWire_h + +#include +#include "Arduino.h" // for delayMicroseconds, digitalPinToBitMask, etc + +// You can exclude certain features from OneWire. In theory, this +// might save some space. In practice, the compiler automatically +// removes unused code (technically, the linker, using -fdata-sections +// and -ffunction-sections when compiling, and Wl,--gc-sections +// when linking), so most of these will not result in any code size +// reduction. Well, unless you try to use the missing features +// and redesign your program to not need them! ONEWIRE_CRC8_TABLE +// is the exception, because it selects a fast but large algorithm +// or a small but slow algorithm. + +// you can exclude onewire_search by defining that to 0 +#ifndef ONEWIRE_SEARCH +#define ONEWIRE_SEARCH 1 +#endif + +// You can exclude CRC checks altogether by defining this to 0 +#ifndef ONEWIRE_CRC +#define ONEWIRE_CRC 1 +#endif + +// Select the table-lookup method of computing the 8-bit CRC +// by setting this to 1. The lookup table enlarges code size by +// about 250 bytes. It does NOT consume RAM (but did in very +// old versions of OneWire). If you disable this, a slower +// but very compact algorithm is used. +#ifndef ONEWIRE_CRC8_TABLE +#define ONEWIRE_CRC8_TABLE 0 +#endif + +// You can allow 16-bit CRC checks by defining this to 1 +// (Note that ONEWIRE_CRC must also be 1.) +#ifndef ONEWIRE_CRC16 +#define ONEWIRE_CRC16 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +#define IO_REG_TYPE uint32_t + +class OneWire +{ + private: + IO_REG_TYPE bitmask; + volatile IO_REG_TYPE *baseReg; + bool dual_mode; + IO_REG_TYPE bitmask_out; + volatile IO_REG_TYPE *baseReg_out; + +#if ONEWIRE_SEARCH + // global search state + unsigned char ROM_NO[8]; + uint8_t LastDiscrepancy; + uint8_t LastFamilyDiscrepancy; + uint8_t LastDeviceFlag; +#endif + + public: + OneWire(uint8_t pin, int8_t pin_out = -1); + + // Perform a 1-Wire reset cycle. Returns 1 if a device responds + // with a presence pulse. Returns 0 if there is no device or the + // bus is shorted or otherwise held low for more than 250uS + uint8_t reset(void); + + // Issue a 1-Wire rom select command, you do the reset first. + void select(const uint8_t rom[8]); + + // Issue a 1-Wire rom skip command, to address all on bus. + void skip(void); + + // Write a byte. If 'power' is one then the wire is held high at + // the end for parasitically powered devices. You are responsible + // for eventually depowering it by calling depower() or doing + // another read or write. + void write(uint8_t v, uint8_t power = 0); + + void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0); + + // Read a byte. + uint8_t read(void); + + void read_bytes(uint8_t *buf, uint16_t count); + + // Write a bit. The bus is always left powered at the end, see + // note in write() about that. + void write_bit(uint8_t v); + + // Read a bit. + uint8_t read_bit(void); + + // Stop forcing power onto the bus. You only need to do this if + // you used the 'power' flag to write() or used a write_bit() call + // and aren't about to do another read or write. You would rather + // not leave this powered if you don't have to, just in case + // someone shorts your bus. + void depower(void); + +#if ONEWIRE_SEARCH + // Clear the search state so that if will start from the beginning again. + void reset_search(); + + // Setup the search to find the device type 'family_code' on the next call + // to search(*newAddr) if it is present. + void target_search(uint8_t family_code); + + // Look for the next device. Returns 1 if a new address has been + // returned. A zero might mean that the bus is shorted, there are + // no devices, or you have already retrieved all of them. It + // might be a good idea to check the CRC to make sure you didn't + // get garbage. The order is deterministic. You will always get + // the same devices in the same order. + uint8_t search(uint8_t *newAddr, bool search_mode = true); +#endif + +#if ONEWIRE_CRC + // Compute a Dallas Semiconductor 8 bit CRC, these are used in the + // ROM and scratchpad registers. + static uint8_t crc8(const uint8_t *addr, uint8_t len); + +#if ONEWIRE_CRC16 + // Compute the 1-Wire CRC16 and compare it against the received CRC. + // Example usage (reading a DS2408): + // // Put everything in a buffer so we can compute the CRC easily. + // uint8_t buf[13]; + // buf[0] = 0xF0; // Read PIO Registers + // buf[1] = 0x88; // LSB address + // buf[2] = 0x00; // MSB address + // WriteBytes(net, buf, 3); // Write 3 cmd bytes + // ReadBytes(net, buf+3, 10); // Read 6 data bytes, 2 0xFF, 2 CRC16 + // if (!CheckCRC16(buf, 11, &buf[11])) { + // // Handle error. + // } + // + // @param input - Array of bytes to checksum. + // @param len - How many bytes to use. + // @param inverted_crc - The two CRC16 bytes in the received data. + // This should just point into the received data, + // *not* at a 16-bit integer. + // @param crc - The crc starting value (optional) + // @return True, iff the CRC matches. + static bool check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc = 0); + + // Compute a Dallas Semiconductor 16 bit CRC. This is required to check + // the integrity of data received from many 1-Wire devices. Note that the + // CRC computed here is *not* what you'll get from the 1-Wire network, + // for two reasons: + // 1) The CRC is transmitted bitwise inverted. + // 2) Depending on the endian-ness of your processor, the binary + // representation of the two-byte return value may have a different + // byte order than the two bytes you get from 1-Wire. + // @param input - Array of bytes to checksum. + // @param len - How many bytes to use. + // @param crc - The crc starting value (optional) + // @return The CRC16, as defined by Dallas Semiconductor. + static uint16_t crc16(const uint8_t* input, uint16_t len, uint16_t crc = 0); +#endif +#endif +}; + +#endif diff --git a/lib/lib_basic/OneWire-Stickbreaker/README.md b/lib/lib_basic/TasmotaOneWire-2.3.3/README.md similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker/README.md rename to lib/lib_basic/TasmotaOneWire-2.3.3/README.md diff --git a/lib/lib_basic/OneWire-Stickbreaker/examples/DS18x20_Temperature/DS18x20_Temperature.pde b/lib/lib_basic/TasmotaOneWire-2.3.3/examples/DS18x20_Temperature/DS18x20_Temperature.pde similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker/examples/DS18x20_Temperature/DS18x20_Temperature.pde rename to lib/lib_basic/TasmotaOneWire-2.3.3/examples/DS18x20_Temperature/DS18x20_Temperature.pde diff --git a/lib/lib_basic/OneWire-Stickbreaker/examples/DS2408_Switch/DS2408_Switch.pde b/lib/lib_basic/TasmotaOneWire-2.3.3/examples/DS2408_Switch/DS2408_Switch.pde similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker/examples/DS2408_Switch/DS2408_Switch.pde rename to lib/lib_basic/TasmotaOneWire-2.3.3/examples/DS2408_Switch/DS2408_Switch.pde diff --git a/lib/lib_basic/OneWire-Stickbreaker/examples/DS250x_PROM/DS250x_PROM.pde b/lib/lib_basic/TasmotaOneWire-2.3.3/examples/DS250x_PROM/DS250x_PROM.pde similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker/examples/DS250x_PROM/DS250x_PROM.pde rename to lib/lib_basic/TasmotaOneWire-2.3.3/examples/DS250x_PROM/DS250x_PROM.pde diff --git a/lib/lib_basic/OneWire-Stickbreaker/keywords.txt b/lib/lib_basic/TasmotaOneWire-2.3.3/keywords.txt similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker/keywords.txt rename to lib/lib_basic/TasmotaOneWire-2.3.3/keywords.txt diff --git a/lib/lib_basic/OneWire-Stickbreaker/library.json b/lib/lib_basic/TasmotaOneWire-2.3.3/library.json similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker/library.json rename to lib/lib_basic/TasmotaOneWire-2.3.3/library.json diff --git a/lib/lib_basic/OneWire-Stickbreaker/library.properties b/lib/lib_basic/TasmotaOneWire-2.3.3/library.properties similarity index 100% rename from lib/lib_basic/OneWire-Stickbreaker/library.properties rename to lib/lib_basic/TasmotaOneWire-2.3.3/library.properties diff --git a/tasmota/include/tasmota_template.h b/tasmota/include/tasmota_template.h index 340d1ab21..212bf3cdd 100644 --- a/tasmota/include/tasmota_template.h +++ b/tasmota/include/tasmota_template.h @@ -731,9 +731,7 @@ const uint16_t kGpioNiceList[] PROGMEM = { #endif #ifdef USE_DS18x20 AGPIO(GPIO_DSB) + MAX_DSB, // Single wire DS18B20 or DS18S20 -#ifdef ESP8266 AGPIO(GPIO_DSB_OUT) + MAX_DSB, // Pseudo Single wire DS18B20 or DS18S20 -#endif // ESP8266 #endif // USE_DS18x20 #ifdef USE_LMT01 AGPIO(GPIO_LMT01), // LMT01, count pulses on GPIO diff --git a/tasmota/tasmota_xsns_sensor/xsns_05_esp32_ds18x20.ino b/tasmota/tasmota_xsns_sensor/xsns_05_esp32_ds18x20.ino index 95b5776df..80b6f3c6f 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_05_esp32_ds18x20.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_05_esp32_ds18x20.ino @@ -86,7 +86,11 @@ void Ds18x20Init(void) { DS18X20Data.gpios = 0; for (uint32_t pins = 0; pins < MAX_DSB; pins++) { if (PinUsed(GPIO_DSB, pins)) { - ds18x20_gpios[pins] = new OneWire(Pin(GPIO_DSB, pins)); + int8_t pin_out = -1; + if (PinUsed(GPIO_DSB_OUT, pins)) { + pin_out = Pin(GPIO_DSB_OUT, pins); + } + ds18x20_gpios[pins] = new OneWire(Pin(GPIO_DSB, pins), pin_out); DS18X20Data.gpios++; } } From 908a918b8e9cb4947e17ba562900992b6584def4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 26 Jan 2024 13:58:28 +0100 Subject: [PATCH 225/303] Fix ESP8266 compilation --- lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.cpp b/lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.cpp index 01c65d3d4..2ef1a3102 100644 --- a/lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.cpp +++ b/lib/lib_basic/TasmotaOneWire-2.3.3/OneWire.cpp @@ -218,8 +218,8 @@ bool directRead(IO_REG_TYPE mask) #define DIRECT_WRITE_HIGH(base, mask) (mask > 0x8000) ? GP16O |= 1 : (GPOS = (mask)) #define CRIT_TIMING -#define t_noInterrupts() {portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;portENTER_CRITICAL(&mux) -#define t_interrupts() portEXIT_CRITICAL(&mux);} +#define t_noInterrupts noInterrupts +#define t_interrupts interrupts #elif defined(ARDUINO_ARCH_ESP32) #include @@ -317,8 +317,8 @@ void directModeOutput(IO_REG_TYPE pin) #define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(pin) #define CRIT_TIMING IRAM_ATTR -#define t_noInterrupts noInterrupts -#define t_interrupts interrupts +#define t_noInterrupts() {portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;portENTER_CRITICAL(&mux) +#define t_interrupts() portEXIT_CRITICAL(&mux);} #endif From 5bb9e65a4bf06265d11b0b6f5334e99a5990c1e0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 26 Jan 2024 15:09:44 +0100 Subject: [PATCH 226/303] Update changelogs --- CHANGELOG.md | 3 ++- RELEASENOTES.md | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b14cdd4dc..04e2871d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,12 @@ All notable changes to this project will be documented in this file. ### Added - HASPmota support for `min` and `max` attribute in `slider` (#20582) - ESP32-C3 support for GPIO11 (#18350) -- ESP32 support for DS18x20 on Shelly Plus Add-On (#20580) +- ESP32 support for Shelly Plus Add-On using DS18x20 or DHT11/AM2301/DHT21/DHT22/AM2302/AM2321/SI7021 on GPIO0/1 (#20580) ### Breaking Changed ### Changed +- Library OneWire-Stickbreaker by TasmotaOneWire supporting Shelly Plus Add-On (#20580) - Refactored rules ``Subscribe`` using LList allowing full message size and enabled by default - Refactored rules USE_EXPRESSION and SUPPORT_IF_STATEMENT replacing LinkedList with arrays and enabled by default - ESP32 Core3 platform update from 2024.01.11 to 2024.01.12 (#20576) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index eda83d6f7..4d8387dc5 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -133,7 +133,8 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - ESP32 used UART information - ESP32 support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled - ESP32 MI BLE support for Xiaomi LYWSD02MMC [#20381](https://github.com/arendst/Tasmota/issues/20381) -- ESP32 support for DS18x20 on Shelly Plus Add-On [#20580](https://github.com/arendst/Tasmota/issues/20580) +- ESP32 support for Shelly Plus Add-On using DS18x20 or DHT11/AM2301/DHT21/DHT22/AM2302/AM2321/SI7021 on GPIO0/1 (#20580) + [#20580](https://github.com/arendst/Tasmota/issues/20580) - ESP32-C3 support for GPIO11 [#18350](https://github.com/arendst/Tasmota/issues/18350) - Berry GPIO viewer initial version using async webserver [#20416](https://github.com/arendst/Tasmota/issues/20416) - Berry `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) @@ -167,6 +168,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - ESP8266 Framework (Arduino Core) from v2.7.4.9 to v2.7.6 [#20539](https://github.com/arendst/Tasmota/issues/20539) - ESP32 Core2 platform update from 2023.11.01 to 2024.01.01 [#20473](https://github.com/arendst/Tasmota/issues/20473) - ESP32 Core3 platform update from 2024.01.11 to 2024.01.12 [#20576](https://github.com/arendst/Tasmota/issues/20576) +- Library OneWire-Stickbreaker by TasmotaOneWire supporting Shelly Plus Add-On [#20580](https://github.com/arendst/Tasmota/issues/20580) - Renamed button "Consoles" to "Tools" - Refactored rule ``Subscribe`` using LList allowing full message size and enabled by default - Refactored rules USE_EXPRESSION and SUPPORT_IF_STATEMENT replacing LinkedList with arrays and enabled by default From 04bb28bc20305661fd0ecf9ac8822b7a3224cc66 Mon Sep 17 00:00:00 2001 From: gemu Date: Sat, 27 Jan 2024 09:06:41 +0100 Subject: [PATCH 227/303] fix email32 file system (#20603) * fix file system * fix email attachments * Update MB_FS.h --- .../ESP-Mail-Client/src/extras/MB_FS.h | 962 ++------------ .../ESP-Mail-Client/src/extras/MB_FS_org.h | 1139 +++++++++++++++++ .../xdrv_01_2_webserver_esp32_mail.ino | 2 + 3 files changed, 1230 insertions(+), 873 deletions(-) create mode 100644 lib/libesp32/ESP-Mail-Client/src/extras/MB_FS_org.h diff --git a/lib/libesp32/ESP-Mail-Client/src/extras/MB_FS.h b/lib/libesp32/ESP-Mail-Client/src/extras/MB_FS.h index 96740627b..caed959a9 100644 --- a/lib/libesp32/ESP-Mail-Client/src/extras/MB_FS.h +++ b/lib/libesp32/ESP-Mail-Client/src/extras/MB_FS.h @@ -31,43 +31,10 @@ #define MBFS_CLASS_H #include -#include "MB_MCU.h" - -#define FS_NO_GLOBALS -#if defined(ESP32) || defined(ESP8266) || defined(MB_ARDUINO_PICO) -#if defined(MBFS_FLASH_FS) || defined(MBFS_SD_FS) #include -#endif -#endif #include "MB_FS_Interfaces.h" #include MB_STRING_INCLUDE_CLASS -#if defined(MBFS_FLASH_FS) || defined(MBFS_SD_FS) -#include "SPI.h" -#endif - -#if defined(ESP32) && __has_include() -#ifdef _LITTLEFS_H_ -#define MB_FS_USE_POSIX_STAT -#include -namespace mb_fs_ns -{ - inline bool exists(const char *mountPoint, const char *filename) - { - MB_String path = mountPoint; - path += filename; - struct stat st; - return stat(path.c_str(), &st) == 0; - } -}; -#endif -#endif - -using namespace mb_string; - -#if defined(BOARD_HAS_PSRAM) && defined(MB_STRING_USE_PSRAM) -#include -#endif #define MB_FS_ERROR_FILE_IO_ERROR -300 #define MB_FS_ERROR_FILE_NOT_FOUND -301 @@ -75,6 +42,14 @@ using namespace mb_string; #define MB_FS_ERROR_SD_STORAGE_IS_NOT_READY -303 #define MB_FS_ERROR_FILE_STILL_OPENED -304 + +#define mbfs_file_type mb_fs_mem_storage_type +#define mbfs_flash mb_fs_mem_storage_type_flash +#define mbfs_sd mb_fs_mem_storage_type_sd +#define mbfs_undefined mb_fs_mem_storage_type_undefined + +#define mbfs_type (mbfs_file_type) + typedef enum { mb_fs_mem_storage_type_undefined, @@ -90,733 +65,158 @@ typedef enum mb_fs_open_mode_append } mb_fs_open_mode; -#define mbfs_file_type mb_fs_mem_storage_type -#define mbfs_flash mb_fs_mem_storage_type_flash -#define mbfs_sd mb_fs_mem_storage_type_sd -#define mbfs_undefined mb_fs_mem_storage_type_undefined +extern FS *ufsp; -#define mbfs_type (mbfs_file_type) - -#if defined(ARDUINO_ARCH_SAMD) || defined(__AVR_ATmega4809__) || defined(ARDUINO_NANO_RP2040_CONNECT) -#if !defined(MBFS_SDFAT_ENABLED) -struct mbfs_sd_config_info_t -{ - int ss = -1; -}; -#endif -#elif defined(ESP32) || defined(MBFS_SDFAT_ENABLED) - -#if defined(ESP32) -struct mbfs_sd_mmc_config_info_t -{ - const char *mountpoint = ""; - bool mode1bit = false; - bool format_if_mount_failed = false; -}; -#endif - -struct mbfs_sd_config_info_t -{ - int ss = -1; - int sck = -1; - int miso = -1; - int mosi = -1; - uint32_t frequency = 4000000; - -#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) - - SdSpiConfig *sdFatSPIConfig = nullptr; - SdioConfig *sdFatSDIOConfig = nullptr; - -#endif - -#if defined(ESP32) - -#if defined(MBFS_SD_FS) - SPIClass *spiConfig = nullptr; -#endif - mbfs_sd_mmc_config_info_t sdMMCConfig; -#endif - -#if defined(MBFS_SDFAT_ENABLED) - SPIClass *spiConfig = nullptr; -#endif -}; - -#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) -struct mbfs_sd_config_info_t -{ - int ss = -1; -#if defined(MBFS_SD_FS) - SDFSConfig *sdFSConfig = nullptr; -#endif -}; -#else -struct mbfs_sd_config_info_t -{ - int ss = -1; -}; -#endif - -class MB_FS -{ +class MB_FS { public: MB_FS() {} ~MB_FS() {} - struct mbfs_sd_config_info_t sd_config; - // Assign the SD card interfaces with GPIO pins. - bool sdBegin(int ss = -1, int sck = -1, int miso = -1, int mosi = -1, uint32_t frequency = 4000000) - { - if (sd_rdy) - return true; - -#if defined(MBFS_SD_FS) && defined(MBFS_CARD_TYPE_SD) - sd_config.ss = ss; -#if defined(ESP32) - sd_config.sck = sck; - sd_config.miso = miso; - sd_config.mosi = mosi; - SPI.begin(sck, miso, mosi, ss); - sd_config.frequency = frequency; - return sdSPIBegin(ss, &SPI, frequency); -#elif defined(ESP8266) || defined(ARDUINO_ARCH_SAMD) || defined(__AVR_ATmega4809__) || defined(ARDUINO_NANO_RP2040_CONNECT) - sd_rdy = MBFS_SD_FS.begin(ss); - return sd_rdy; -#elif defined(MB_ARDUINO_PICO) - SDFSConfig c; - c.setCSPin(ss); - c.setSPISpeed(frequency); - MBFS_SD_FS.setConfig(c); - sd_rdy = MBFS_SD_FS.begin(); - return sd_rdy; -#endif - -#endif - return false; + bool sdBegin(int ss = -1, int sck = -1, int miso = -1, int mosi = -1, uint32_t frequency = 4000000) { + mfsp = ufsp; + return true; } -#if defined(ESP32) && defined(MBFS_SD_FS) && defined(MBFS_CARD_TYPE_SD) - - // Assign the SD card interfaces with SPIClass object pointer (ESP32 only). - bool sdSPIBegin(int ss, SPIClass *spiConfig, uint32_t frequency) - { - - if (sd_rdy) - return true; - - sd_config.frequency = frequency; - -#if defined(ESP32) - - sd_config.ss = ss; - - if (spiConfig) - sd_config.spiConfig = spiConfig; - else - sd_config.spiConfig = &SPI; - -#if !defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) - if (ss > -1) - sd_rdy = MBFS_SD_FS.begin(ss, *sd_config.spiConfig, frequency); - else - sd_rdy = MBFS_SD_FS.begin(); -#endif - -#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) - - cfg->_int.sd_config.sck = sck; - - if (ss > -1) - sd_rdy = MBFS_SD_FS.begin(ss); - else - sd_rdy = MBFS_SD_FS.begin(SD_CS_PIN); -#endif - - return sd_rdy; - } - -#endif - -#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) - - // Assign the SD card interfaces with SdSpiConfig object pointer and SPI pins assignment. - bool sdFatBegin(SdSpiConfig *sdFatSPIConfig, int ss, int sck, int miso, int mosi) - { - - if (sd_rdy) - return true; - - if (sdFatSPIConfig) - { - sd_config.sdFatSPIConfig = sdFatSPIConfig; - sd_config.spiConfig = &SPI; - sd_config.ss = ss; - -#if defined(ESP32) - if (ss > -1) - sd_config.spiConfig->begin(sck, miso, mosi, ss); -#endif - - sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSPIConfig); - return sd_rdy; - } - - return false; - } - - // Assign the SD card interfaces with SdioConfig object pointer. - bool sdFatBegin(SdioConfig *sdFatSDIOConfig) - { - - if (sd_rdy) - return true; - -#if defined(HAS_SDIO_CLASS) // Default is 0 (no SDIO) in SdFatConfig.h - -#if HAS_SDIO_CLASS - - if (sdFatSDIOConfig) - { - sd_config.sdFatSDIOConfig = sdFatSDIOConfig; - - sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSDIOConfig); - return sd_rdy; - } -#endif - -#endif - - return false; - } -#endif - -#if (defined(ESP8266) || defined(MB_ARDUINO_PICO)) && defined(MBFS_SD_FS) - // Assign the SD card interfaces with SDFSConfig object pointer (ESP8266 and Pico only). - bool sdFatBegin(SDFSConfig *sdFSConfig) - { - - if (sd_rdy) - return true; - - if (sdFSConfig) - { - sd_config.sdFSConfig = sdFSConfig; - SDFS.setConfig(*sd_config.sdFSConfig); - sd_rdy = SDFS.begin(); - return sd_rdy; - } - - return false; - } -#endif - - // Assign the SD_MMC card interfaces (ESP32 only). - bool sdMMCBegin(const char *mountpoint, bool mode1bit, bool format_if_mount_failed) - { - - if (sd_rdy) - return true; - -#if defined(ESP32) -#if defined(MBFS_CARD_TYPE_SD_MMC) - - sd_config.sdMMCConfig.mountpoint = mountpoint; - sd_config.sdMMCConfig.mode1bit = mode1bit; - sd_config.sdMMCConfig.format_if_mount_failed = format_if_mount_failed; - - sd_rdy = MBFS_SD_FS.begin(mountpoint, mode1bit, format_if_mount_failed); - return sd_rdy; -#endif -#endif - return false; + bool sdSPIBegin(int ss, SPIClass *spiConfig, uint32_t frequency) { + mfsp = ufsp; + return true; } // Check the mounting status of Flash storage. - bool flashReady() - { -#if defined MBFS_FLASH_FS - - if (flash_rdy) - return true; - -#if defined(ESP32) - -#if defined(MBFS_FORMAT_FLASH) - flash_rdy = MBFS_FLASH_FS.begin(true); -#else - flash_rdy = MBFS_FLASH_FS.begin(); -#endif - -#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) - flash_rdy = MBFS_FLASH_FS.begin(); -#endif - -#endif - - return flash_rdy; + bool flashReady() { + return true; } // Check the mounting status of SD storage. - bool sdReady() - { - -#if defined(MBFS_SD_FS) - - if (sd_rdy) - return true; - -#if defined(ESP32) - -#if defined(MBFS_CARD_TYPE_SD) - - if (!sd_config.spiConfig) - { - if (sd_config.ss > -1) - SPI.begin(sd_config.sck, sd_config.miso, sd_config.mosi, sd_config.ss); - sd_config.spiConfig = &SPI; - } - -#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) - - if (!sd_rdy) - { - if (sd_config.sdFatSPIConfig) - sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSPIConfig); - else if (sd_config.sdFatSDIOConfig) - sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSDIOConfig); - } - -#else - if (!sd_rdy) - sd_rdy = sdSPIBegin(sd_config.ss, sd_config.spiConfig, sd_config.frequency); - -#endif - -#elif defined(MBFS_CARD_TYPE_SD_MMC) - if (!sd_rdy) - sd_rdy = sdMMCBegin(sd_config.sdMMCConfig.mountpoint, sd_config.sdMMCConfig.mode1bit, sd_config.sdMMCConfig.format_if_mount_failed); -#endif - -#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) - if (!sd_rdy) - { - if (sd_config.sdFSConfig) - sd_rdy = sdFatBegin(sd_config.sdFSConfig); - else - sd_rdy = sdBegin(sd_config.ss); - } - -#elif defined(ARDUINO_ARCH_SAMD) || defined(__AVR_ATmega4809__) || defined(ARDUINO_NANO_RP2040_CONNECT) - if (!sd_rdy) - sd_rdy = sdBegin(sd_config.ss); -#endif - -#endif - - return sd_rdy; + bool sdReady() { + return true; } // Check the mounting status of Flash or SD storage with mb_fs_mem_storage_type. - bool checkStorageReady(mbfs_file_type type) - { - -#if defined(MBFS_USE_FILE_STORAGE) - if (type == mbfs_flash) - { - if (!flash_rdy) - flashReady(); - return flash_rdy; - } - else if (type == mbfs_sd) - { - if (!sd_rdy) - sdReady(); - return sd_rdy; - } -#endif - - return false; + bool checkStorageReady(mbfs_file_type type) { + return true; } - // Open file for read or write with file name, mb_fs_mem_storage_type and mb_fs_open_mode. - // return size of file (read) or 0 (write) or negative value for error - int open(const MB_String &filename, mbfs_file_type type, mb_fs_open_mode mode) - { - -#if defined(MBFS_USE_FILE_STORAGE) - - if (!checkStorageReady(type)) - { - if (type == mbfs_flash) - return MB_FS_ERROR_FLASH_STORAGE_IS_NOT_READY; - else if (type == mbfs_sd) - return MB_FS_ERROR_SD_STORAGE_IS_NOT_READY; - else - return MB_FS_ERROR_FILE_IO_ERROR; + int open(const MB_String &filename, mbfs_file_type type, mb_fs_open_mode mode) { + char fmode[8]; + switch (mode) { + case mb_fs_open_mode_read: + strcpy(fmode, "r"); + break; + case mb_fs_open_mode_write: + strcpy(fmode, "w"); + break; + case mb_fs_open_mode_append: + strcpy(fmode, "a"); + break; } - - if (mode == mb_fs_open_mode_read) - { - if (!existed(filename.c_str(), type)) - return MB_FS_ERROR_FILE_NOT_FOUND; - } - - int ret = openFile(filename, type, mode); - - if (ret < 0) - return ret; - - if (ready(type)) - return ret; - -#endif - return MB_FS_ERROR_FILE_IO_ERROR; + flash_file = filename; + mfsp = ufsp; + mb_File = mfsp->open(filename.c_str(), fmode); + //Serial.printf(">>> 1 %s, %s, %d ", filename.c_str(), fmode, mb_File); + return mb_File; } - // Check if file is already open. - bool ready(mbfs_file_type type) - { -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - return true; -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - return true; -#endif - return false; + bool ready(mbfs_file_type type) { + return true; } - // Get file for read/write with file name, mb_fs_mem_storage_type and mb_fs_open_mode. - int size(mbfs_file_type type) - { - int size = 0; - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - size = mb_flashFs.size(); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - size = mb_sdFs.size(); -#endif - return size; + int size(mbfs_file_type type) { + return mb_File.size(); } // Check if file is ready to read/write. - int available(mbfs_file_type type) - { - int available = 0; - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - available = mb_flashFs.available(); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - available = mb_sdFs.available(); -#endif - return available; + int available(mbfs_file_type type) { + return mb_File.available(); } // Read byte array. Return the number of bytes that completed read or negative value for error. - int read(mbfs_file_type type, uint8_t *buf, size_t len) - { - int read = 0; -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - read = mb_flashFs.read(buf, len); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - read = mb_sdFs.read(buf, len); -#endif - return read; + int read(mbfs_file_type type, uint8_t *buf, size_t len) { + return mb_File.read(buf, len); } // Print char array. Return the number of bytes that completed write or negative value for error. - int print(mbfs_file_type type, const char *str) - { - int write = 0; -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - write = mb_flashFs.print(str); -#endif -#if defined(MBFS_SD_FS) - - if (type == mbfs_sd && mb_sdFs) - write = mb_sdFs.print(str); -#endif - return write; + int print(mbfs_file_type type, const char *str) { + return mb_File.print(str); } // Print char array with new line. Return the number of bytes that completed write or negative value for error. - int println(mbfs_file_type type, const char *str) - { - int write = print(type, str); - if (write == (int)strlen(str)) - write += print(type, (const char *)MBSTRING_FLASH_MCR("\n")); - return write; + int println(mbfs_file_type type, const char *str) { + return mb_File.print(str); } // Print integer. Return the number of bytes that completed write or negative value for error. - int print(mbfs_file_type type, int v) - { - int write = 0; -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - write = mb_flashFs.print(v); -#endif -#if defined(MBFS_SD_FS) - - if (type == mbfs_sd && mb_sdFs) - write = mb_sdFs.print(v); -#endif - return write; + int print(mbfs_file_type type, int v) { + return mb_File.print(v); } // Print integer with newline. Return the number of bytes that completed write or negative value for error. - int println(mbfs_file_type type, int v) - { - int write = print(type, v); - if (write > 0) - write += print(type, (const char *)MBSTRING_FLASH_MCR("\n")); - return write; + int println(mbfs_file_type type, int v) { + return mb_File.print(v); } - int print(mbfs_file_type type, unsigned int v) - { - int write = 0; -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - write = mb_flashFs.print(v); -#endif -#if defined(MBFS_SD_FS) - - if (type == mbfs_sd && mb_sdFs) - write = mb_sdFs.print(v); -#endif - return write; + int print(mbfs_file_type type, unsigned int v) { + return mb_File.print(v); } // Print integer with newline. Return the number of bytes that completed write or negative value for error. - int println(mbfs_file_type type, unsigned int v) - { - int write = print(type, v); - if (write > 0) - write += print(type, (const char *)MBSTRING_FLASH_MCR("\n")); - return write; + int println(mbfs_file_type type, unsigned int v) { + return mb_File.print(v); } // Write byte array. Return the number of bytes that completed write or negative value for error. - int write(mbfs_file_type type, uint8_t *buf, size_t len) - { - int write = 0; -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - write = mb_flashFs.write(buf, len); -#endif -#if defined(MBFS_SD_FS) - - if (type == mbfs_sd && mb_sdFs) - write = mb_sdFs.write(buf, len); -#endif - return write; + int write(mbfs_file_type type, uint8_t *buf, size_t len) { + return mb_File.write(buf, len); } // Close file. - void close(mbfs_file_type type) - { - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs && flash_opened) - { - mb_flashFs.close(); - flash_filename_crc = 0; - flash_opened = false; - flash_open_mode = mb_fs_open_mode_undefined; - } -#endif - -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs && sd_opened) - { - mb_sdFs.close(); - sd_filename_crc = 0; - sd_opened = false; - sd_open_mode = mb_fs_open_mode_undefined; - } -#endif + void close(mbfs_file_type type) { + mb_File.close(); } // Check file existence. - bool existed(const MB_String &filename, mbfs_file_type type) - { - - if (!checkStorageReady(type)) - return false; - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash) - { - -// The workaround for ESP32 LittleFS when calling vfs_api.cpp open() issue. -// See https://github.com/espressif/arduino-esp32/issues/7615 -#if defined(MB_FS_USE_POSIX_STAT) - return mb_fs_ns::exists("/littlefs", filename.c_str()); -#else - return MBFS_FLASH_FS.exists(filename.c_str()); -#endif - } - -#endif - -#if defined(MBFS_SD_FS) - if (type == mbfs_sd) - { -#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) - MBFS_SD_FILE file; - bool ret = file.open(filename.c_str(), O_RDONLY); - file.close(); - return ret; -#else - return MBFS_SD_FS.exists(filename.c_str()); -#endif - } -#endif - - return false; + bool existed(const MB_String &filename, mbfs_file_type type) { + return mfsp->exists(filename.c_str()); } // Seek to position in file. - bool seek(mbfs_file_type type, int pos) - { - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - return mb_flashFs.seek(pos); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - return mb_sdFs.seek(pos); -#endif - - return false; + bool seek(mbfs_file_type type, int pos) { + return mb_File.seek(pos); } // Read byte. Return the 1 for completed read or negative value for error. - int read(mbfs_file_type type) - { -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - return mb_flashFs.read(); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - return mb_sdFs.read(); -#endif - return -1; + int read(mbfs_file_type type) { + return mb_File.read(); } // Write byte. Return the 1 for completed write or negative value for error. - int write(mbfs_file_type type, uint8_t v) - { -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - return mb_flashFs.write(v); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - return mb_sdFs.write(v); -#endif - return -1; + int write(mbfs_file_type type, uint8_t v) { + return mb_File.write(v); } - bool remove(const MB_String &filename, mbfs_file_type type) - { - if (!checkStorageReady(type)) - return false; - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && !flashReady()) - return false; -#endif - -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && !sdReady()) - return false; -#endif - - if (!existed(filename, type)) - return true; - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash) - return MBFS_FLASH_FS.remove(filename.c_str()); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd) - { -#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) - if (mb_sdFs.open(filename.c_str(), O_RDWR | O_CREAT | O_APPEND)) - { - mb_sdFs.remove(); - mb_sdFs.close(); - return true; - } -#else - return MBFS_SD_FS.remove(filename.c_str()); -#endif - } - -#endif - return false; + bool remove(const MB_String &filename, mbfs_file_type type) { + return mfsp->remove(filename.c_str()); } -// Get the Flash file instance. -#if defined(MBFS_FLASH_FS) - fs::File &getFlashFile() - { - return mb_flashFs; + fs::File &getFlashFile() { + return mb_File; } -#endif - -// Get the SD file instance. -#if defined(MBFS_SD_FS) - MBFS_SD_FILE &getSDFile() - { - return mb_sdFs; - } -#endif // Get name of opened file. - const char *name(mbfs_file_type type) - { -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash && mb_flashFs) - return flash_file.c_str(); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd && mb_sdFs) - return sd_file.c_str(); -#endif - - return ""; + const char *name(mbfs_file_type type) { + return flash_file.c_str(); } // Calculate CRC16 of byte array. - uint16_t calCRC(const char *buf) - { + uint16_t calCRC(const char *buf) { uint8_t x; uint16_t crc = 0xFFFF; int length = (int)strlen(buf); - while (length--) - { + while (length--) { x = crc >> 8 ^ *buf++; x ^= x >> 4; crc = (crc << 8) ^ ((uint16_t)(x << 12)) ^ ((uint16_t)(x << 5)) ^ ((uint16_t)x); @@ -825,19 +225,16 @@ public: } // Free reserved memory at pointer. - void delP(void *ptr) - { + void delP(void *ptr) { void **p = (void **)ptr; - if (*p) - { + if (*p) { free(*p); *p = 0; } } // Allocate memory - void *newP(size_t len, bool clear = true) - { + void *newP(size_t len, bool clear = true) { void *p; size_t newLen = getReservedLen(len); #if defined(BOARD_HAS_PSRAM) && defined(MB_STRING_USE_PSRAM) @@ -872,8 +269,7 @@ public: return p; } - size_t getReservedLen(size_t len) - { + size_t getReservedLen(size_t len) { int blen = len + 1; int newlen = (blen / 4) * 4; @@ -884,20 +280,17 @@ public: return (size_t)newlen; } - void createDirs(MB_String dirs, mbfs_file_type type) - { + void createDirs(MB_String dirs, mbfs_file_type type) { if (!longNameSupported()) return; MB_String dir; int count = 0; int lastPos = 0; - for (size_t i = 0; i < dirs.length(); i++) - { + for (size_t i = 0; i < dirs.length(); i++) { dir.append(1, dirs[i]); count++; - if (dirs[i] == '/' && i > 0) - { + if (dirs[i] == '/' && i > 0) { if (dir.length() > 0) { @@ -936,8 +329,7 @@ public: dir.clear(); } - bool longNameSupported() - { + bool longNameSupported() { #if defined(MBFS_SDFAT_ENABLED) || defined(MBFS_FLASH_FS) return true; @@ -952,186 +344,10 @@ public: private: uint16_t flash_filename_crc = 0; - uint16_t sd_filename_crc = 0; MB_String flash_file, sd_file; - mb_fs_open_mode flash_open_mode = mb_fs_open_mode_undefined; - mb_fs_open_mode sd_open_mode = mb_fs_open_mode_undefined; - bool flash_opened = false; - bool sd_opened = false; - bool sd_rdy = false; - bool flash_rdy = false; - uint16_t loopCount = 0; + FS *mfsp; + File mb_File; -#if defined(MBFS_FLASH_FS) - fs::File mb_flashFs; -#endif -#if defined(MBFS_SD_FS) - MBFS_SD_FILE mb_sdFs; -#endif - - int openFile(const MB_String &filename, mb_fs_mem_storage_type type, mb_fs_open_mode mode) - { - -#if defined(MBFS_FLASH_FS) - if (type == mbfs_flash) - return openFlashFile(filename, mode); -#endif -#if defined(MBFS_SD_FS) - if (type == mbfs_sd) - return openSDFile(filename, mode); -#endif - return MB_FS_ERROR_FILE_IO_ERROR; - } - - int openSDFile(const MB_String &filename, mb_fs_open_mode mode) - { - int ret = MB_FS_ERROR_FILE_IO_ERROR; - -#if defined(MBFS_SD_FS) - - if (mode == mb_fs_open_mode_read || mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) - { - uint16_t crc = calCRC(filename.c_str()); - - if (mode == sd_open_mode && flash_filename_crc == crc && sd_opened) // same sd file opened, leave it - return MB_FS_ERROR_FILE_STILL_OPENED; - - if (sd_opened) - close(mbfs_sd); // sd file opened, close it - - flash_filename_crc = crc; - } - -#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) - - if (mode == mb_fs_open_mode_read) - { - if (mb_sdFs.open(filename.c_str(), O_RDONLY)) - { - sd_file = filename; - sd_opened = true; - sd_open_mode = mode; - ret = mb_sdFs.size(); - } - } - else if (mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) - { - if (mode == mb_fs_open_mode_write) - remove(filename, mb_fs_mem_storage_type_sd); - - createDirs(filename, mb_fs_mem_storage_type_sd); - if (mb_sdFs.open(filename.c_str(), O_RDWR | O_CREAT | O_APPEND)) - { - sd_file = filename; - sd_opened = true; - sd_open_mode = mode; - ret = 0; - } - } - -#else - - if (mode == mb_fs_open_mode_read) - { -#if defined(ESP32) || defined(ESP8266) - mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_READ); -#else - mb_sdFs = MBFS_SD_FS.open(filename.c_str(), "r"); -#endif - if (mb_sdFs) - { - sd_file = filename; - sd_opened = true; - sd_open_mode = mode; - ret = mb_sdFs.size(); - } - } - else if (mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) - { - if (mode == mb_fs_open_mode_write) - remove(filename, mb_fs_mem_storage_type_sd); - - createDirs(filename, mb_fs_mem_storage_type_sd); -#if defined(ESP32) - if (mode == mb_fs_open_mode_write) - mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_WRITE); - else - mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_APPEND); -#elif defined(ESP8266) - mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_WRITE); -#else - if (mode == mb_fs_open_mode_write) - mb_sdFs = MBFS_SD_FS.open(filename.c_str(), "w"); - else - mb_sdFs = MBFS_SD_FS.open(filename.c_str(), "a"); -#endif - - if (mb_sdFs) - { - sd_file = filename; - sd_opened = true; - sd_open_mode = mode; - ret = 0; - } - } -#endif - -#endif - return ret; - } - - int openFlashFile(const MB_String &filename, mb_fs_open_mode mode) - { - int ret = MB_FS_ERROR_FILE_IO_ERROR; - -#if defined(MBFS_FLASH_FS) - - if (mode == mb_fs_open_mode_read || mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) - { - uint16_t crc = calCRC(filename.c_str()); - if (mode == flash_open_mode && sd_filename_crc == crc && flash_opened) // same flash file opened, leave it - return MB_FS_ERROR_FILE_STILL_OPENED; - - if (flash_opened) - close(mbfs_flash); // flash file opened, close it - - sd_filename_crc = crc; - } - - if (mode == mb_fs_open_mode_read) - { - mb_flashFs = MBFS_FLASH_FS.open(filename.c_str(), "r"); - if (mb_flashFs) - { - flash_file = filename; - flash_opened = true; - flash_open_mode = mode; - ret = mb_flashFs.size(); - } - } - else if (mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) - { - if (mode == mb_fs_open_mode_write) - remove(filename, mb_fs_mem_storage_type_flash); - - createDirs(filename, mb_fs_mem_storage_type_flash); - if (mode == mb_fs_open_mode_write) - mb_flashFs = MBFS_FLASH_FS.open(filename.c_str(), "w"); - else - mb_flashFs = MBFS_FLASH_FS.open(filename.c_str(), "a"); - - if (mb_flashFs) - { - flash_file = filename; - flash_opened = true; - flash_open_mode = mode; - ret = 0; - } - } - -#endif - return ret; - } }; #endif diff --git a/lib/libesp32/ESP-Mail-Client/src/extras/MB_FS_org.h b/lib/libesp32/ESP-Mail-Client/src/extras/MB_FS_org.h new file mode 100644 index 000000000..682a3d78e --- /dev/null +++ b/lib/libesp32/ESP-Mail-Client/src/extras/MB_FS_org.h @@ -0,0 +1,1139 @@ +/** + * The MB_FS, filesystems wrapper class v1.0.16 + * + * This wrapper class is for SD and Flash filesystems interface which supports SdFat (//https://github.com/greiman/SdFat) + * + * Created June 14, 2023 + * + * The MIT License (MIT) + * Copyright (c) 2023 K. Suwatchai (Mobizt) + * + * + * Permission is hereby granted, free of charge, to any person returning a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if 0 +#ifndef MBFS_CLASS_H +#define MBFS_CLASS_H + +#include +#include "MB_MCU.h" + +#define FS_NO_GLOBALS +#if defined(ESP32) || defined(ESP8266) || defined(MB_ARDUINO_PICO) +#if defined(MBFS_FLASH_FS) || defined(MBFS_SD_FS) +#include +#endif +#endif +#include "MB_FS_Interfaces.h" +#include MB_STRING_INCLUDE_CLASS + +#if defined(MBFS_FLASH_FS) || defined(MBFS_SD_FS) +#include "SPI.h" +#endif + +#if defined(ESP32) && __has_include() +#ifdef _LITTLEFS_H_ +#define MB_FS_USE_POSIX_STAT +#include +namespace mb_fs_ns +{ + inline bool exists(const char *mountPoint, const char *filename) + { + MB_String path = mountPoint; + path += filename; + struct stat st; + return stat(path.c_str(), &st) == 0; + } +}; +#endif +#endif + +using namespace mb_string; + +#if defined(BOARD_HAS_PSRAM) && defined(MB_STRING_USE_PSRAM) +#include +#endif + +#define MB_FS_ERROR_FILE_IO_ERROR -300 +#define MB_FS_ERROR_FILE_NOT_FOUND -301 +#define MB_FS_ERROR_FLASH_STORAGE_IS_NOT_READY -302 +#define MB_FS_ERROR_SD_STORAGE_IS_NOT_READY -303 +#define MB_FS_ERROR_FILE_STILL_OPENED -304 + +typedef enum +{ + mb_fs_mem_storage_type_undefined, + mb_fs_mem_storage_type_flash, + mb_fs_mem_storage_type_sd +} mb_fs_mem_storage_type; + +typedef enum +{ + mb_fs_open_mode_undefined = -1, + mb_fs_open_mode_read = 0, + mb_fs_open_mode_write, + mb_fs_open_mode_append +} mb_fs_open_mode; + +#define mbfs_file_type mb_fs_mem_storage_type +#define mbfs_flash mb_fs_mem_storage_type_flash +#define mbfs_sd mb_fs_mem_storage_type_sd +#define mbfs_undefined mb_fs_mem_storage_type_undefined + +#define mbfs_type (mbfs_file_type) + +#if defined(ARDUINO_ARCH_SAMD) || defined(__AVR_ATmega4809__) || defined(ARDUINO_NANO_RP2040_CONNECT) +#if !defined(MBFS_SDFAT_ENABLED) +struct mbfs_sd_config_info_t +{ + int ss = -1; +}; +#endif +#elif defined(ESP32) || defined(MBFS_SDFAT_ENABLED) + +#if defined(ESP32) +struct mbfs_sd_mmc_config_info_t +{ + const char *mountpoint = ""; + bool mode1bit = false; + bool format_if_mount_failed = false; +}; +#endif + +struct mbfs_sd_config_info_t +{ + int ss = -1; + int sck = -1; + int miso = -1; + int mosi = -1; + uint32_t frequency = 4000000; + +#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) + + SdSpiConfig *sdFatSPIConfig = nullptr; + SdioConfig *sdFatSDIOConfig = nullptr; + +#endif + +#if defined(ESP32) + +#if defined(MBFS_SD_FS) + SPIClass *spiConfig = nullptr; +#endif + mbfs_sd_mmc_config_info_t sdMMCConfig; +#endif + +#if defined(MBFS_SDFAT_ENABLED) + SPIClass *spiConfig = nullptr; +#endif +}; + +#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) +struct mbfs_sd_config_info_t +{ + int ss = -1; +#if defined(MBFS_SD_FS) + SDFSConfig *sdFSConfig = nullptr; +#endif +}; +#else +struct mbfs_sd_config_info_t +{ + int ss = -1; +}; +#endif + +class MB_FS +{ + +public: + MB_FS() {} + ~MB_FS() {} + + struct mbfs_sd_config_info_t sd_config; + + // Assign the SD card interfaces with GPIO pins. + bool sdBegin(int ss = -1, int sck = -1, int miso = -1, int mosi = -1, uint32_t frequency = 4000000) + { + if (sd_rdy) + return true; + +#if defined(MBFS_SD_FS) && defined(MBFS_CARD_TYPE_SD) + sd_config.ss = ss; +#if defined(ESP32) + sd_config.sck = sck; + sd_config.miso = miso; + sd_config.mosi = mosi; + SPI.begin(sck, miso, mosi, ss); + sd_config.frequency = frequency; + return sdSPIBegin(ss, &SPI, frequency); +#elif defined(ESP8266) || defined(ARDUINO_ARCH_SAMD) || defined(__AVR_ATmega4809__) || defined(ARDUINO_NANO_RP2040_CONNECT) + sd_rdy = MBFS_SD_FS.begin(ss); + return sd_rdy; +#elif defined(MB_ARDUINO_PICO) + SDFSConfig c; + c.setCSPin(ss); + c.setSPISpeed(frequency); + MBFS_SD_FS.setConfig(c); + sd_rdy = MBFS_SD_FS.begin(); + return sd_rdy; +#endif + +#endif + return false; + } + +#if defined(ESP32) && defined(MBFS_SD_FS) && defined(MBFS_CARD_TYPE_SD) + + // Assign the SD card interfaces with SPIClass object pointer (ESP32 only). + bool sdSPIBegin(int ss, SPIClass *spiConfig, uint32_t frequency) + { + + if (sd_rdy) + return true; + + sd_config.frequency = frequency; + +#if defined(ESP32) + + sd_config.ss = ss; + + if (spiConfig) + sd_config.spiConfig = spiConfig; + else + sd_config.spiConfig = &SPI; + +#if !defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) + if (ss > -1) + sd_rdy = MBFS_SD_FS.begin(ss, *sd_config.spiConfig, frequency); + else + sd_rdy = MBFS_SD_FS.begin(); +#endif + +#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) + + cfg->_int.sd_config.sck = sck; + + if (ss > -1) + sd_rdy = MBFS_SD_FS.begin(ss); + else + sd_rdy = MBFS_SD_FS.begin(SD_CS_PIN); +#endif + + return sd_rdy; + } + +#endif + +#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) + + // Assign the SD card interfaces with SdSpiConfig object pointer and SPI pins assignment. + bool sdFatBegin(SdSpiConfig *sdFatSPIConfig, int ss, int sck, int miso, int mosi) + { + + if (sd_rdy) + return true; + + if (sdFatSPIConfig) + { + sd_config.sdFatSPIConfig = sdFatSPIConfig; + sd_config.spiConfig = &SPI; + sd_config.ss = ss; + +#if defined(ESP32) + if (ss > -1) + sd_config.spiConfig->begin(sck, miso, mosi, ss); +#endif + + sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSPIConfig); + return sd_rdy; + } + + return false; + } + + // Assign the SD card interfaces with SdioConfig object pointer. + bool sdFatBegin(SdioConfig *sdFatSDIOConfig) + { + + if (sd_rdy) + return true; + +#if defined(HAS_SDIO_CLASS) // Default is 0 (no SDIO) in SdFatConfig.h + +#if HAS_SDIO_CLASS + + if (sdFatSDIOConfig) + { + sd_config.sdFatSDIOConfig = sdFatSDIOConfig; + + sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSDIOConfig); + return sd_rdy; + } +#endif + +#endif + + return false; + } +#endif + +#if (defined(ESP8266) || defined(MB_ARDUINO_PICO)) && defined(MBFS_SD_FS) + // Assign the SD card interfaces with SDFSConfig object pointer (ESP8266 and Pico only). + bool sdFatBegin(SDFSConfig *sdFSConfig) + { + + if (sd_rdy) + return true; + + if (sdFSConfig) + { + sd_config.sdFSConfig = sdFSConfig; + SDFS.setConfig(*sd_config.sdFSConfig); + sd_rdy = SDFS.begin(); + return sd_rdy; + } + + return false; + } +#endif + + // Assign the SD_MMC card interfaces (ESP32 only). + bool sdMMCBegin(const char *mountpoint, bool mode1bit, bool format_if_mount_failed) + { + + if (sd_rdy) + return true; + +#if defined(ESP32) +#if defined(MBFS_CARD_TYPE_SD_MMC) + + sd_config.sdMMCConfig.mountpoint = mountpoint; + sd_config.sdMMCConfig.mode1bit = mode1bit; + sd_config.sdMMCConfig.format_if_mount_failed = format_if_mount_failed; + + sd_rdy = MBFS_SD_FS.begin(mountpoint, mode1bit, format_if_mount_failed); + return sd_rdy; +#endif +#endif + return false; + } + + // Check the mounting status of Flash storage. + bool flashReady() + { +#if defined MBFS_FLASH_FS + + if (flash_rdy) + return true; + +#if defined(ESP32) + +#if defined(MBFS_FORMAT_FLASH) + flash_rdy = MBFS_FLASH_FS.begin(true); +#else + flash_rdy = MBFS_FLASH_FS.begin(); +#endif + +#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) + flash_rdy = MBFS_FLASH_FS.begin(); +#endif + +#endif + + return flash_rdy; + } + + // Check the mounting status of SD storage. + bool sdReady() + { + +#if defined(MBFS_SD_FS) + + if (sd_rdy) + return true; + +#if defined(ESP32) + +#if defined(MBFS_CARD_TYPE_SD) + + if (!sd_config.spiConfig) + { + if (sd_config.ss > -1) + SPI.begin(sd_config.sck, sd_config.miso, sd_config.mosi, sd_config.ss); + sd_config.spiConfig = &SPI; + } + +#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) + + if (!sd_rdy) + { + if (sd_config.sdFatSPIConfig) + sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSPIConfig); + else if (sd_config.sdFatSDIOConfig) + sd_rdy = MBFS_SD_FS.begin(*sd_config.sdFatSDIOConfig); + } + +#else + if (!sd_rdy) + sd_rdy = sdSPIBegin(sd_config.ss, sd_config.spiConfig, sd_config.frequency); + +#endif + +#elif defined(MBFS_CARD_TYPE_SD_MMC) + if (!sd_rdy) + sd_rdy = sdMMCBegin(sd_config.sdMMCConfig.mountpoint, sd_config.sdMMCConfig.mode1bit, sd_config.sdMMCConfig.format_if_mount_failed); +#endif + +#elif defined(ESP8266) || defined(MB_ARDUINO_PICO) + if (!sd_rdy) + { + if (sd_config.sdFSConfig) + sd_rdy = sdFatBegin(sd_config.sdFSConfig); + else + sd_rdy = sdBegin(sd_config.ss); + } + +#elif defined(ARDUINO_ARCH_SAMD) || defined(__AVR_ATmega4809__) || defined(ARDUINO_NANO_RP2040_CONNECT) + if (!sd_rdy) + sd_rdy = sdBegin(sd_config.ss); +#endif + +#endif + + return sd_rdy; + } + + // Check the mounting status of Flash or SD storage with mb_fs_mem_storage_type. + bool checkStorageReady(mbfs_file_type type) + { + +#if defined(MBFS_USE_FILE_STORAGE) + if (type == mbfs_flash) + { + if (!flash_rdy) + flashReady(); + return flash_rdy; + } + else if (type == mbfs_sd) + { + if (!sd_rdy) + sdReady(); + return sd_rdy; + } +#endif + + return false; + } + + // Open file for read or write with file name, mb_fs_mem_storage_type and mb_fs_open_mode. + // return size of file (read) or 0 (write) or negative value for error + int open(const MB_String &filename, mbfs_file_type type, mb_fs_open_mode mode) + { + +#if defined(MBFS_USE_FILE_STORAGE) + + if (!checkStorageReady(type)) + { + if (type == mbfs_flash) + return MB_FS_ERROR_FLASH_STORAGE_IS_NOT_READY; + else if (type == mbfs_sd) + return MB_FS_ERROR_SD_STORAGE_IS_NOT_READY; + else + return MB_FS_ERROR_FILE_IO_ERROR; + } + + if (mode == mb_fs_open_mode_read) + { + if (!existed(filename.c_str(), type)) + return MB_FS_ERROR_FILE_NOT_FOUND; + } + + int ret = openFile(filename, type, mode); + + if (ret < 0) + return ret; + + if (ready(type)) + return ret; + +#endif + return MB_FS_ERROR_FILE_IO_ERROR; + } + + // Check if file is already open. + bool ready(mbfs_file_type type) + { +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + return true; +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + return true; +#endif + return false; + } + + // Get file for read/write with file name, mb_fs_mem_storage_type and mb_fs_open_mode. + int size(mbfs_file_type type) + { + int size = 0; + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + size = mb_flashFs.size(); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + size = mb_sdFs.size(); +#endif + return size; + } + + // Check if file is ready to read/write. + int available(mbfs_file_type type) + { + int available = 0; + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + available = mb_flashFs.available(); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + available = mb_sdFs.available(); +#endif + return available; + } + + // Read byte array. Return the number of bytes that completed read or negative value for error. + int read(mbfs_file_type type, uint8_t *buf, size_t len) + { + int read = 0; +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + read = mb_flashFs.read(buf, len); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + read = mb_sdFs.read(buf, len); +#endif + return read; + } + + // Print char array. Return the number of bytes that completed write or negative value for error. + int print(mbfs_file_type type, const char *str) + { + int write = 0; +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + write = mb_flashFs.print(str); +#endif +#if defined(MBFS_SD_FS) + + if (type == mbfs_sd && mb_sdFs) + write = mb_sdFs.print(str); +#endif + return write; + } + + // Print char array with new line. Return the number of bytes that completed write or negative value for error. + int println(mbfs_file_type type, const char *str) + { + int write = print(type, str); + if (write == (int)strlen(str)) + write += print(type, (const char *)MBSTRING_FLASH_MCR("\n")); + return write; + } + + // Print integer. Return the number of bytes that completed write or negative value for error. + int print(mbfs_file_type type, int v) + { + int write = 0; +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + write = mb_flashFs.print(v); +#endif +#if defined(MBFS_SD_FS) + + if (type == mbfs_sd && mb_sdFs) + write = mb_sdFs.print(v); +#endif + return write; + } + + // Print integer with newline. Return the number of bytes that completed write or negative value for error. + int println(mbfs_file_type type, int v) + { + int write = print(type, v); + if (write > 0) + write += print(type, (const char *)MBSTRING_FLASH_MCR("\n")); + return write; + } + + int print(mbfs_file_type type, unsigned int v) + { + int write = 0; +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + write = mb_flashFs.print(v); +#endif +#if defined(MBFS_SD_FS) + + if (type == mbfs_sd && mb_sdFs) + write = mb_sdFs.print(v); +#endif + return write; + } + + // Print integer with newline. Return the number of bytes that completed write or negative value for error. + int println(mbfs_file_type type, unsigned int v) + { + int write = print(type, v); + if (write > 0) + write += print(type, (const char *)MBSTRING_FLASH_MCR("\n")); + return write; + } + + // Write byte array. Return the number of bytes that completed write or negative value for error. + int write(mbfs_file_type type, uint8_t *buf, size_t len) + { + int write = 0; +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + write = mb_flashFs.write(buf, len); +#endif +#if defined(MBFS_SD_FS) + + if (type == mbfs_sd && mb_sdFs) + write = mb_sdFs.write(buf, len); +#endif + return write; + } + + // Close file. + void close(mbfs_file_type type) + { + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs && flash_opened) + { + mb_flashFs.close(); + flash_filename_crc = 0; + flash_opened = false; + flash_open_mode = mb_fs_open_mode_undefined; + } +#endif + +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs && sd_opened) + { + mb_sdFs.close(); + sd_filename_crc = 0; + sd_opened = false; + sd_open_mode = mb_fs_open_mode_undefined; + } +#endif + } + + // Check file existence. + bool existed(const MB_String &filename, mbfs_file_type type) + { + + if (!checkStorageReady(type)) + return false; + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash) + { + +// The workaround for ESP32 LittleFS when calling vfs_api.cpp open() issue. +// See https://github.com/espressif/arduino-esp32/issues/7615 +#if defined(MB_FS_USE_POSIX_STAT) + return mb_fs_ns::exists("/littlefs", filename.c_str()); +#else + return MBFS_FLASH_FS.exists(filename.c_str()); +#endif + } + +#endif + +#if defined(MBFS_SD_FS) + if (type == mbfs_sd) + { +#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) + MBFS_SD_FILE file; + bool ret = file.open(filename.c_str(), O_RDONLY); + file.close(); + return ret; +#else + return MBFS_SD_FS.exists(filename.c_str()); +#endif + } +#endif + + return false; + } + + // Seek to position in file. + bool seek(mbfs_file_type type, int pos) + { + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + return mb_flashFs.seek(pos); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + return mb_sdFs.seek(pos); +#endif + + return false; + } + + // Read byte. Return the 1 for completed read or negative value for error. + int read(mbfs_file_type type) + { +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + return mb_flashFs.read(); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + return mb_sdFs.read(); +#endif + return -1; + } + + // Write byte. Return the 1 for completed write or negative value for error. + int write(mbfs_file_type type, uint8_t v) + { +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + return mb_flashFs.write(v); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + return mb_sdFs.write(v); +#endif + return -1; + } + + bool remove(const MB_String &filename, mbfs_file_type type) + { + if (!checkStorageReady(type)) + return false; + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && !flashReady()) + return false; +#endif + +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && !sdReady()) + return false; +#endif + + if (!existed(filename, type)) + return true; + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash) + return MBFS_FLASH_FS.remove(filename.c_str()); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd) + { +#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) + if (mb_sdFs.open(filename.c_str(), O_RDWR | O_CREAT | O_APPEND)) + { + mb_sdFs.remove(); + mb_sdFs.close(); + return true; + } +#else + return MBFS_SD_FS.remove(filename.c_str()); +#endif + } + +#endif + return false; + } + +// Get the Flash file instance. +#if defined(MBFS_FLASH_FS) + fs::File &getFlashFile() + { + return mb_flashFs; + } +#endif + +// Get the SD file instance. +#if defined(MBFS_SD_FS) + MBFS_SD_FILE &getSDFile() + { + return mb_sdFs; + } +#endif + + // Get name of opened file. + const char *name(mbfs_file_type type) + { +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash && mb_flashFs) + return flash_file.c_str(); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd && mb_sdFs) + return sd_file.c_str(); +#endif + + return ""; + } + + // Calculate CRC16 of byte array. + uint16_t calCRC(const char *buf) + { + uint8_t x; + uint16_t crc = 0xFFFF; + + int length = (int)strlen(buf); + + while (length--) + { + x = crc >> 8 ^ *buf++; + x ^= x >> 4; + crc = (crc << 8) ^ ((uint16_t)(x << 12)) ^ ((uint16_t)(x << 5)) ^ ((uint16_t)x); + } + return crc; + } + + // Free reserved memory at pointer. + void delP(void *ptr) + { + void **p = (void **)ptr; + if (*p) + { + free(*p); + *p = 0; + } + } + + // Allocate memory + void *newP(size_t len, bool clear = true) + { + void *p; + size_t newLen = getReservedLen(len); +#if defined(BOARD_HAS_PSRAM) && defined(MB_STRING_USE_PSRAM) + + if (ESP.getPsramSize() > 0) + p = (void *)ps_malloc(newLen); + else + p = (void *)malloc(newLen); + + if (!p) + return NULL; + +#else + +#if defined(ESP8266_USE_EXTERNAL_HEAP) + ESP.setExternalHeap(); +#endif + + p = (void *)malloc(newLen); + bool nn = p ? true : false; + +#if defined(ESP8266_USE_EXTERNAL_HEAP) + ESP.resetHeap(); +#endif + + if (!nn) + return NULL; + +#endif + if (clear) + memset(p, 0, newLen); + return p; + } + + size_t getReservedLen(size_t len) + { + int blen = len + 1; + + int newlen = (blen / 4) * 4; + + if (newlen < blen) + newlen += 4; + + return (size_t)newlen; + } + + void createDirs(MB_String dirs, mbfs_file_type type) + { + if (!longNameSupported()) + return; + + MB_String dir; + int count = 0; + int lastPos = 0; + for (size_t i = 0; i < dirs.length(); i++) + { + dir.append(1, dirs[i]); + count++; + if (dirs[i] == '/' && i > 0) + { + if (dir.length() > 0) + { + + lastPos = dir.length() - 1; + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash) + MBFS_FLASH_FS.mkdir(dir.substr(0, dir.length() - 1).c_str()); +#endif + +#if defined(MBFS_SD_FS) + if (type == mbfs_sd) + MBFS_SD_FS.mkdir(dir.substr(0, dir.length() - 1).c_str()); +#endif + } + count = 0; + } + } + + if (count > 0) + { + if (dir.find('.', lastPos) == MB_String::npos) + { +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash) + MBFS_FLASH_FS.mkdir(dir.c_str()); +#endif + +#if defined(MBFS_SD_FS) + if (type == mbfs_sd) + MBFS_SD_FS.mkdir(dir.c_str()); +#endif + } + } + + dir.clear(); + } + + bool longNameSupported() + { + +#if defined(MBFS_SDFAT_ENABLED) || defined(MBFS_FLASH_FS) + return true; +#endif + +#if defined(MBFS_SD_FS) && (defined(ESP32) || defined(ESP8266) || defined(MB_ARDUINO_PICO)) + return true; +#endif + + return false; + } + +private: + uint16_t flash_filename_crc = 0; + uint16_t sd_filename_crc = 0; + MB_String flash_file, sd_file; + mb_fs_open_mode flash_open_mode = mb_fs_open_mode_undefined; + mb_fs_open_mode sd_open_mode = mb_fs_open_mode_undefined; + bool flash_opened = false; + bool sd_opened = false; + bool sd_rdy = false; + bool flash_rdy = false; + uint16_t loopCount = 0; + +#if defined(MBFS_FLASH_FS) + fs::File mb_flashFs; +#endif +#if defined(MBFS_SD_FS) + MBFS_SD_FILE mb_sdFs; +#endif + + int openFile(const MB_String &filename, mb_fs_mem_storage_type type, mb_fs_open_mode mode) + { + +#if defined(MBFS_FLASH_FS) + if (type == mbfs_flash) + return openFlashFile(filename, mode); +#endif +#if defined(MBFS_SD_FS) + if (type == mbfs_sd) + return openSDFile(filename, mode); +#endif + return MB_FS_ERROR_FILE_IO_ERROR; + } + + int openSDFile(const MB_String &filename, mb_fs_open_mode mode) + { + int ret = MB_FS_ERROR_FILE_IO_ERROR; + +#if defined(MBFS_SD_FS) + + if (mode == mb_fs_open_mode_read || mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) + { + uint16_t crc = calCRC(filename.c_str()); + + if (mode == sd_open_mode && flash_filename_crc == crc && sd_opened) // same sd file opened, leave it + return MB_FS_ERROR_FILE_STILL_OPENED; + + if (sd_opened) + close(mbfs_sd); // sd file opened, close it + + flash_filename_crc = crc; + } + +#if defined(MBFS_ESP32_SDFAT_ENABLED) || defined(MBFS_SDFAT_ENABLED) + + if (mode == mb_fs_open_mode_read) + { + if (mb_sdFs.open(filename.c_str(), O_RDONLY)) + { + sd_file = filename; + sd_opened = true; + sd_open_mode = mode; + ret = mb_sdFs.size(); + } + } + else if (mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) + { + if (mode == mb_fs_open_mode_write) + remove(filename, mb_fs_mem_storage_type_sd); + + createDirs(filename, mb_fs_mem_storage_type_sd); + if (mb_sdFs.open(filename.c_str(), O_RDWR | O_CREAT | O_APPEND)) + { + sd_file = filename; + sd_opened = true; + sd_open_mode = mode; + ret = 0; + } + } + +#else + + if (mode == mb_fs_open_mode_read) + { +#if defined(ESP32) || defined(ESP8266) + mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_READ); +#else + mb_sdFs = MBFS_SD_FS.open(filename.c_str(), "r"); +#endif + if (mb_sdFs) + { + sd_file = filename; + sd_opened = true; + sd_open_mode = mode; + ret = mb_sdFs.size(); + } + } + else if (mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) + { + if (mode == mb_fs_open_mode_write) + remove(filename, mb_fs_mem_storage_type_sd); + + createDirs(filename, mb_fs_mem_storage_type_sd); +#if defined(ESP32) + if (mode == mb_fs_open_mode_write) + mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_WRITE); + else + mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_APPEND); +#elif defined(ESP8266) + mb_sdFs = MBFS_SD_FS.open(filename.c_str(), FILE_WRITE); +#else + if (mode == mb_fs_open_mode_write) + mb_sdFs = MBFS_SD_FS.open(filename.c_str(), "w"); + else + mb_sdFs = MBFS_SD_FS.open(filename.c_str(), "a"); +#endif + + if (mb_sdFs) + { + sd_file = filename; + sd_opened = true; + sd_open_mode = mode; + ret = 0; + } + } +#endif + +#endif + return ret; + } + + int openFlashFile(const MB_String &filename, mb_fs_open_mode mode) + { + int ret = MB_FS_ERROR_FILE_IO_ERROR; + +#if defined(MBFS_FLASH_FS) + + if (mode == mb_fs_open_mode_read || mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) + { + uint16_t crc = calCRC(filename.c_str()); + if (mode == flash_open_mode && sd_filename_crc == crc && flash_opened) // same flash file opened, leave it + return MB_FS_ERROR_FILE_STILL_OPENED; + + if (flash_opened) + close(mbfs_flash); // flash file opened, close it + + sd_filename_crc = crc; + } + + if (mode == mb_fs_open_mode_read) + { + mb_flashFs = MBFS_FLASH_FS.open(filename.c_str(), "r"); + if (mb_flashFs) + { + flash_file = filename; + flash_opened = true; + flash_open_mode = mode; + ret = mb_flashFs.size(); + } + } + else if (mode == mb_fs_open_mode_write || mode == mb_fs_open_mode_append) + { + if (mode == mb_fs_open_mode_write) + remove(filename, mb_fs_mem_storage_type_flash); + + createDirs(filename, mb_fs_mem_storage_type_flash); + if (mode == mb_fs_open_mode_write) + mb_flashFs = MBFS_FLASH_FS.open(filename.c_str(), "w"); + else + mb_flashFs = MBFS_FLASH_FS.open(filename.c_str(), "a"); + + if (mb_flashFs) + { + flash_file = filename; + flash_opened = true; + flash_open_mode = mode; + ret = 0; + } + } + +#endif + return ret; + } +}; + +#endif +#endif \ No newline at end of file diff --git a/tasmota/tasmota_xdrv_driver/xdrv_01_2_webserver_esp32_mail.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_2_webserver_esp32_mail.ino index 3f26baa0d..c1588ec3b 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_01_2_webserver_esp32_mail.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_01_2_webserver_esp32_mail.ino @@ -296,6 +296,8 @@ void attach_File(char *path) { att.descr.mime = "application/octet-stream"; //binary data #if ESP_MAIL_VERSION_NUM<30409 att.file.storage_type = esp_mail_file_storage_type_univ; +#else + att.file.storage_type = esp_mail_file_storage_type_flash; #endif att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64; email_mptr->addAttachment(att); From 19b9960168ad420175a179170d044da085ae529b Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 27 Jan 2024 11:59:45 +0100 Subject: [PATCH 228/303] Berry C mapping, raise an error if too many arguments are sent (#20604) --- CHANGELOG.md | 1 + lib/libesp32/berry_mapping/src/be_class_wrapper.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04e2871d1..d322aa03e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file. - Utouch optimizations, rgb i2c init (#20596) ### Fixed +- Berry C mapping, raise an error if too many arguments are sent ### Removed diff --git a/lib/libesp32/berry_mapping/src/be_class_wrapper.c b/lib/libesp32/berry_mapping/src/be_class_wrapper.c index a1abc23ee..2f29ab95a 100644 --- a/lib/libesp32/berry_mapping/src/be_class_wrapper.c +++ b/lib/libesp32/berry_mapping/src/be_class_wrapper.c @@ -360,6 +360,9 @@ int be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_type, i } } // berry_log_C(">> be_call_c_func arg %i, type %s", i, arg_type_check ? type_short_name : ""); + if (arg_type_check && type_short_name[0] == 0) { + be_raisef(vm, "value_error", "Too many arguments"); + } p[p_idx] = be_convert_single_elt(vm, i + arg_start, arg_type_check ? type_short_name : NULL, (int*)&buf_len); // berry_log_C("< ret[%i]=%i", p_idx, p[p_idx]); p_idx++; From 9454336f3cf7b9d5719bd0762d7d0b95d8a5bdb2 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 27 Jan 2024 13:01:28 +0100 Subject: [PATCH 229/303] Berry allow mapping within module (#20606) --- lib/libesp32/berry_tasmota/src/be_ctypes.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/libesp32/berry_tasmota/src/be_ctypes.c b/lib/libesp32/berry_tasmota/src/be_ctypes.c index cd7650d41..d92ffb183 100644 --- a/lib/libesp32/berry_tasmota/src/be_ctypes.c +++ b/lib/libesp32/berry_tasmota/src/be_ctypes.c @@ -255,11 +255,16 @@ int be_ctypes_member(bvm *vm) { if (member->mapping > 0 && definitions->instance_mapping) { const char * mapping_name = definitions->instance_mapping[member->mapping - 1]; if (mapping_name) { - be_getglobal(vm, mapping_name); // stack: class - be_pushvalue(vm, -2); // stack: class, value - be_pushint(vm, -1); // stack; class, value, -1 - be_call(vm, 2); // call constructor with 2 parameters - be_pop(vm, 2); // leave new instance on top of stack + int32_t found = be_find_global_or_module_member(vm, mapping_name); + if (found == 1) { + // we have found only one element from a module, which is expected + be_pushvalue(vm, -2); // stack: class, value + be_pushint(vm, -1); // stack; class, value, -1 + be_call(vm, 2); // call constructor with 2 parameters + be_pop(vm, 2); // leave new instance on top of stack + } else { + be_raisef(vm, "internal_error", "mapping for '%s' not found", mapping_name); + } } } be_return(vm); From 1e7bbfcc006058981c9061b04b3ab4557d6d8246 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 27 Jan 2024 23:56:55 +0100 Subject: [PATCH 230/303] update changelogs --- CHANGELOG.md | 3 ++- RELEASENOTES.md | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d322aa03e..32e00dc50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,9 +17,10 @@ All notable changes to this project will be documented in this file. - Refactored rules USE_EXPRESSION and SUPPORT_IF_STATEMENT replacing LinkedList with arrays and enabled by default - ESP32 Core3 platform update from 2024.01.11 to 2024.01.12 (#20576) - Utouch optimizations, rgb i2c init (#20596) +- GPIO Viewer update from 1.0.7 to 1.5.0 ### Fixed -- Berry C mapping, raise an error if too many arguments are sent +- Berry C mapping, raise an error if too many arguments are sent (#20604) ### Removed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 4d8387dc5..8aabdf518 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -195,6 +195,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - LVGL fix type for lv_imgbtn [#20354](https://github.com/arendst/Tasmota/issues/20354) - Berry claiming UART0 if needed [#20324](https://github.com/arendst/Tasmota/issues/20324) - Berry assigment to list with negative index [#20537](https://github.com/arendst/Tasmota/issues/20537) +- Berry C mapping, raise an error if too many arguments are sent [#20604](https://github.com/arendst/Tasmota/issues/20604) - Matter Contact sensor was not triggering any update [#20232](https://github.com/arendst/Tasmota/issues/20232) - Matter support for Alexa [#20545](https://github.com/arendst/Tasmota/issues/20545) From af9d4cadd8ef524d3156e9e509ab935d87bf572c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 27 Jan 2024 23:58:00 +0100 Subject: [PATCH 231/303] GPIO Viewer update from 1.0.7 to 1.5.0 --- tasmota/html_compressed/HTTP_GV_PAGE_150.h | 25 +++ tasmota/html_uncompressed/HTTP_GV_PAGE_150.h | 24 +++ tasmota/my_user_config.h | 3 +- tasmota/tasmota_support/support_esp32.ino | 28 +++ tasmota/tasmota_support/support_esp8266.ino | 62 +++++++ .../xdrv_121_gpioviewer.ino | 163 ++++++++++++++---- 6 files changed, 273 insertions(+), 32 deletions(-) create mode 100644 tasmota/html_compressed/HTTP_GV_PAGE_150.h create mode 100644 tasmota/html_uncompressed/HTTP_GV_PAGE_150.h diff --git a/tasmota/html_compressed/HTTP_GV_PAGE_150.h b/tasmota/html_compressed/HTTP_GV_PAGE_150.h new file mode 100644 index 000000000..b0200b768 --- /dev/null +++ b/tasmota/html_compressed/HTTP_GV_PAGE_150.h @@ -0,0 +1,25 @@ +///////////////////////////////////////////////////////////////////// +// compressed by tools/unishox/compress-html-uncompressed.py +///////////////////////////////////////////////////////////////////// + +const size_t HTTP_GV_PAGE_SIZE = 465; +const char HTTP_GV_PAGE_COMPRESSED[] PROGMEM = "\x3D\x0F\xE1\x10\x98\x1D\x19\x0C\x64\x85\x50\xD0\x8F\xC3\xD0\x55\x0D\x09\x05\x7C" + "\x3C\x7C\x3E\xDF\x1F\x67\xE1\xE8\x29\xD8\x87\xE1\xE9\x5B\x41\x33\xF0\xFA\xF2\x3A" + "\xD1\x0F\x10\xC2\xD2\xC4\x46\x7A\xC7\xDF\xCF\x43\xB0\x10\x6A\x1E\x83\x5D\x5A\x0C" + "\x55\xFF\xCE\x8F\x87\xD9\x0B\x2A\x2B\x23\x07\x59\xCF\x9F\x67\xE1\xE8\x43\xAF\xCD" + "\x0A\xFB\x30\x7C\x3E\xCF\xAF\x1F\x67\xE1\xE8\x16\xF1\xA2\xFB\x08\xF8\x7D\xE8\x79" + "\xC7\xD8\x21\x57\x31\x66\x7A\x1E\x71\xD3\x43\xC3\xEC\x10\xB2\x6E\xB1\xAC\xF8\x7D" + "\x99\xEB\x1F\x19\x9F\xA3\xED\x07\x9D\x4F\xA8\xF8\x7D\x8F\xE8\x94\x28\xF8\x23\x33" + "\xD0\xD9\xD6\x3F\xA2\x50\xA3\xA9\x6F\x6D\x6D\x84\x75\xF8\x3B\x09\x9F\x0E\x43\xA3" + "\x3E\xCF\xC3\xD0\xBC\x1F\xF4\x65\x2A\x2B\x32\x18\xCF\x87\xD8\xDC\x10\x58\x4C\xFB" + "\x41\xFF\x3D\xEC\xFE\x8F\x6F\x2F\x7C\x33\xE1\xF6\x43\xC4\x30\xB4\xB0\x10\x78\x25" + "\x23\x31\x6C\xE8\x6B\xF1\xF6\x7E\x1E\x87\x60\x20\xE2\xC0\x8F\xC0\x47\xA8\xC8\x27" + "\xE1\x4D\xD0\x24\xE3\xE0\x83\xC0\xD5\xFB\xCE\xBC\x76\x0D\xBD\xE3\xA0\x7E\xF1\xF6" + "\x7E\x1E\x87\x60\x20\xF1\x1C\x3B\x04\x32\x3F\x0F\x41\x34\xCD\x68\x87\xC3\xEE\xC6" + "\x0C\x3E\xCF\xC3\xD0\xEC\x13\x4C\xC1\x0F\x79\x3F\x07\xF7\x84\xC1\xF3\xA0\xF0\xCD" + "\xC3\xF7\xE7\x55\xBC\x3D\xE4\x7C\x47\xB7\x46\x1E\x67\xD9\xF5\xE3\xEC\xEA\x19\x9F" + "\xA3\xCC\xFB\x3E\x84\x3E\xCE\xA3\x1F\x6C\xBC\x68\xE8\x31\x45\xFB\x1A\x79\x9F\x67" + "\xD0\x88\x8D\x08\x71\xF6\x7B\x8F\x2A\x01\x8B\xC0\x49\xD8\x08\x3A\x49\xD8\x2A\x2B" + "\x86\x84\x7E\x1B"; + +#define HTTP_GV_PAGE Decompress(HTTP_GV_PAGE_COMPRESSED,HTTP_GV_PAGE_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_uncompressed/HTTP_GV_PAGE_150.h b/tasmota/html_uncompressed/HTTP_GV_PAGE_150.h new file mode 100644 index 000000000..8fed388bd --- /dev/null +++ b/tasmota/html_uncompressed/HTTP_GV_PAGE_150.h @@ -0,0 +1,24 @@ +const char HTTP_GV_PAGE[] PROGMEM = + "" + "" + "" + "%s - GPIO Viewer" // SettingsTextEscaped(SET_DEVICENAME).c_str() + "" + "" // GV_BASE_URL + "" + "" + "" + "" + "" + "" + "
" + "" + "" + ""; diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 93da42e15..ce1a1f3f2 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -470,8 +470,7 @@ #define USE_ENHANCED_GUI_WIFI_SCAN // Enable Wi-Fi scan output with BSSID (+0k5 code) // #define USE_WEBSEND_RESPONSE // Enable command WebSend response message (+1k code) // #define USE_WEBGETCONFIG // Enable restoring config from external webserver (+0k6) -// #define USE_GPIO_VIEWER // Enable GPIO Viewer to see realtime GPIO states (+4k code) -// #define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" +// #define USE_GPIO_VIEWER // Enable GPIO Viewer to see realtime GPIO states (+6k code) // #define GV_SAMPLING_INTERVAL 100 // [GvSampling] milliseconds - Use Tasmota Scheduler (100) or Ticker (20..99,101..1000) #define USE_EMULATION_HUE // Enable Hue Bridge emulation for Alexa (+14k code, +2k mem common) #define USE_EMULATION_WEMO // Enable Belkin WeMo emulation for Alexa (+6k code, +2k mem common) diff --git a/tasmota/tasmota_support/support_esp32.ino b/tasmota/tasmota_support/support_esp32.ino index f3e362ee3..365f4d0f7 100644 --- a/tasmota/tasmota_support/support_esp32.ino +++ b/tasmota/tasmota_support/support_esp32.ino @@ -501,6 +501,10 @@ uint32_t ESP_getFreeSketchSpace(void) { return ESP.getFreeSketchSpace(); } +uint32_t ESP_getHeapSize(void) { + return ESP.getHeapSize(); +} + uint32_t ESP_getFreeHeap(void) { // ESP_getFreeHeap() returns also IRAM which we don't use return heap_caps_get_free_size(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); @@ -558,6 +562,18 @@ uint8_t* FlashDirectAccess(void) { return data; } +uint32_t ESP_getPsramSize(void) { + return ESP.getPsramSize(); +} + +uint32_t ESP_getFreePsram(void) { + return ESP.getFreePsram(); +} + +uint32_t ESP_getMaxAllocPsram(void) { + return ESP.getMaxAllocPsram(); +} + extern "C" { #if ESP_IDF_VERSION_MAJOR >= 5 // bool IRAM_ATTR __attribute__((pure)) esp_psram_is_initialized(void) @@ -948,6 +964,18 @@ String GetCodeCores(void) { #endif } +uint32_t ESP_getChipCores(void) { + return ESP.getChipCores(); +} + +uint32_t ESP_getChipRevision(void) { + return ESP.getChipRevision(); +} + +String ESP_getEfuseMac(void) { + return String(ESP.getEfuseMac()); +} + /*********************************************************************************************\ * High entropy hardware random generator * Thanks to DigitalAlchemist diff --git a/tasmota/tasmota_support/support_esp8266.ino b/tasmota/tasmota_support/support_esp8266.ino index 00df1731b..d21184d74 100644 --- a/tasmota/tasmota_support/support_esp8266.ino +++ b/tasmota/tasmota_support/support_esp8266.ino @@ -85,6 +85,10 @@ uint32_t ESP_getSketchSize(void) { return ESP.getSketchSize(); } +uint32_t ESP_getHeapSize(void) { + return 32768; // Using default heap (No PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED) +} + uint32_t ESP_getFreeHeap(void) { return ESP.getFreeHeap(); } @@ -98,6 +102,10 @@ float ESP_getFreeHeap1024(void) { } */ +uint32_t ESP_getMaxAllocHeap(void) { + return ESP.getFreeHeap(); +} + uint32_t ESP_getFlashChipId(void) { return ESP.getFlashChipId(); } @@ -110,6 +118,18 @@ uint32_t ESP_getFlashChipSize(void) { return ESP.getFlashChipSize(); } +uint32_t ESP_getPsramSize(void) { + return 0; +} + +uint32_t ESP_getFreePsram(void) { + return 0; +} + +uint32_t ESP_getMaxAllocPsram(void) { + return 0; +} + void ESP_Restart(void) { // ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 ESP.reset(); @@ -197,6 +217,48 @@ String GetCodeCores(void) { return F(""); } +uint32_t ESP_getChipCores(void) { + return 1; +} + +uint32_t ESP_getChipRevision(void) { + return 1; +} + +String ESP_getEfuseMac(void) { + uint32_t mac0 = *(uint32_t*)(0x3FF00050); + uint32_t mac1 = *(uint32_t*)(0x3FF00054); + uint32_t mac3 = *(uint32_t*)(0x3FF0005C); + + uint32_t mach = 0; + uint32_t macl = 0; + if (mac3 != 0) { + mach = ((mac3 >> 16) & 0xFF) << 16; + mach |= ((mac3 >> 8) & 0xFF) << 8; + mach |= mac3 & 0xFF; + } + else if (((mac1 >> 16) & 0xFF) == 0) { + mach = 0x18FE34; + } + else if (((mac1 >> 16) & 0xFF) == 1) { + mach = 0xACD074; + } + String macStr = ""; + if (mach > 0) { + macl = ((mac1 >> 8) & 0xFF) << 16; + macl |= (mac1 & 0xFF) << 8; + macl |= (mac0 >> 24) & 0xFF; + + uint64_t maca = ((uint64_t)mach << 24) | macl; + // Need uint64ToString with base 10 as ESP8266 WStrings does not support uint64_t + while (maca > 0) { + macStr = String((uint32_t)(maca % 10), 10) + macStr; + maca /= 10; + } + } + return String(macStr); +} + /*********************************************************************************************\ * High entropy hardware random generator * Thanks to DigitalAlchemist diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 96281511c..e7f7508e9 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -17,6 +17,15 @@ #define XDRV_121 121 +//#define GV_INPUT_DETECTION // Report type of digital input + +#define GV_USE_ESPINFO // Provide ESP info +#ifdef ESP32 +#ifndef GV_USE_ESPINFO +#define GV_USE_ESPINFO // Provide ESP info +#endif +#endif + #ifndef GV_PORT #define GV_PORT 5557 // SSE webserver port #endif @@ -27,29 +36,15 @@ #define GV_KEEP_ALIVE 1000 // milliseconds - If no activity after this do a heap size event anyway #ifndef GV_BASE_URL -#define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer/assets/" +#define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer_1_5/" #endif -/* -#ifdef ESP8266 -#ifndef GV_BASE_URL -#undef GV_BASE_URL // Fix compiler warning -#define GV_BASE_URL "https://ota.tasmota.com/tasmota/gpio_viewer/assets/" -#endif -#endif // ESP8266 -#ifdef ESP32 -#ifndef GV_BASE_URL -#undef GV_BASE_URL // Fix compiler warning -#define GV_BASE_URL "https://ota.tasmota.com/tasmota32/gpio_viewer/assets/" -#endif -#endif // ESP32 -*/ -const char *GVRelease = "1.0.7"; +const char *GVRelease = "1.5.0"; #ifdef USE_UNISHOX_COMPRESSION - #include "./html_compressed/HTTP_GV_PAGE.h" + #include "./html_compressed/HTTP_GV_PAGE_150.h" #else - #include "./html_uncompressed/HTTP_GV_PAGE.h" + #include "./html_uncompressed/HTTP_GV_PAGE_150.h" #endif const char HTTP_GV_EVENT[] PROGMEM = @@ -62,7 +57,12 @@ const char HTTP_GV_EVENT[] PROGMEM = enum GVPinTypes { GV_DigitalPin = 0, GV_PWMPin = 1, - GV_AnalogPin = 2 + GV_AnalogPin = 2, +#ifdef GV_INPUT_DETECTION + GV_InputPin = 3, + GV_InputPullUp = 4, + GV_InputPullDn = 5 +#endif // GV_INPUT_DETECTION }; struct { @@ -78,6 +78,26 @@ struct { bool sse_ready; } GV; +#ifdef GV_INPUT_DETECTION + +int GetPinMode(uint8_t pin) { +#ifdef ESP8266 + if (pin > MAX_GPIO_PIN -2) { return -1; } // Skip GPIO16 and Analog0 +#endif // ESP8266 +#ifdef ESP32 + if (pin > MAX_GPIO_PIN) { return -1; } +#endif // ESP32 + + uint32_t bit = digitalPinToBitMask(pin); + uint32_t port = digitalPinToPort(pin); + volatile uint32_t *reg = portModeRegister(port); + if (*reg & bit) { return OUTPUT; } // ESP8266 = 0x01, ESP32 = 0x03 + volatile uint32_t *out = portOutputRegister(port); + return ((*out & bit) ? INPUT_PULLUP : INPUT); // ESP8266 = 0x02 : 0x00, ESP32 = 0x05 : x01 +} + +#endif // GV_INPUT_DETECTION + void GVStop(void) { GV.sse_ready = false; GV.ticker.detach(); @@ -100,6 +120,9 @@ void GVBegin(void) { GV.WebServer->on("/", GVHandleRoot); GV.WebServer->on("/release", GVHandleRelease); GV.WebServer->on("/free_psram", GVHandleFreePSRam); + GV.WebServer->on("/sampling", GVHandleSampling); + GV.WebServer->on("/espinfo", GVHandleEspInfo); + GV.WebServer->on("/partition", GVHandlePartition); GV.WebServer->on("/events", GVHandleEvents); GV.WebServer->begin(); @@ -112,24 +135,21 @@ void GVHandleRoot(void) { char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, SettingsTextEscaped(SET_DEVICENAME).c_str(), GV_BASE_URL, - GV_PORT, WiFi.localIP().toString().c_str(), - WiFi.localIP().toString().c_str(), GV_PORT, - GV.sampling, -#ifdef ESP32 - ESP.getPsramSize() / 1024, -#else - 0, -#endif // ESP32 + GV_PORT, ESP_getFreeSketchSpace() / 1024); if (content == nullptr) { return; } // Avoid crash GV.WebServer->send_P(200, "text/html", content); free(content); } +void GVWebserverSendJson(String &jsonResponse) { + GV.WebServer->send(200, "application/json", jsonResponse); +} + void GVHandleRelease(void) { String jsonResponse = "{\"release\":\"" + String(GVRelease) + "\"}"; - GV.WebServer->send(200, "application/json", jsonResponse); + GVWebserverSendJson(jsonResponse); } void GVHandleFreePSRam(void) { @@ -140,7 +160,85 @@ void GVHandleFreePSRam(void) { } else #endif jsonResponse += "No PSRAM\"}"; - GV.WebServer->send(200, "application/json", jsonResponse); + GVWebserverSendJson(jsonResponse); +} + +void GVHandleSampling(void) { + String jsonResponse = "{\"sampling\": \"" + String(GV.sampling) + "\"}"; + GVWebserverSendJson(jsonResponse); +} + +void GVHandleEspInfo(void) { +#ifdef GV_USE_ESPINFO + const FlashMode_t flashMode = ESP.getFlashChipMode(); // enum + + String jsonResponse = "{\"chip_model\":\"" + GetDeviceHardware(); + jsonResponse += "\",\"cores_count\":\"" + String(ESP_getChipCores()); + jsonResponse += "\",\"chip_revision\":\"" + String(ESP_getChipRevision()); + jsonResponse += "\",\"cpu_frequency\":\"" + String(ESP.getCpuFreqMHz()); + jsonResponse += "\",\"cycle_count\":" + String(ESP.getCycleCount()); + jsonResponse += ",\"mac\":\"" + ESP_getEfuseMac(); + jsonResponse += "\",\"flash_mode\":" + String(flashMode); +#ifdef ESP8266 + jsonResponse += ",\"flash_chip_size\":" + String(ESP.getFlashChipRealSize()); +#else + jsonResponse += ",\"flash_chip_size\":" + String(ESP.getFlashChipSize()); +#endif + jsonResponse += ",\"flash_chip_speed\":" + String(ESP.getFlashChipSpeed()); + jsonResponse += ",\"heap_size\":" + String(ESP_getHeapSize()); + jsonResponse += ",\"heap_max_alloc\":" + String(ESP_getMaxAllocHeap()); + jsonResponse += ",\"psram_size\":" + String(ESP_getPsramSize()); + jsonResponse += ",\"free_psram\":" + String(ESP_getFreePsram()); + jsonResponse += ",\"psram_max_alloc\":" + String(ESP_getMaxAllocPsram()); + jsonResponse += ",\"free_heap\":" + String(ESP_getFreeHeap()); + jsonResponse += ",\"up_time\":\"" + String(millis()); + jsonResponse += "\",\"sketch_size\":" + String(ESP_getSketchSize()); + jsonResponse += ",\"free_sketch\":" + String(ESP_getFreeSketchSpace()); + jsonResponse += "}"; +#else + String jsonResponse = "{\"chip_model\":\"" + GetDeviceHardware() + "\"}"; +#endif // GV_USE_ESPINFO + GVWebserverSendJson(jsonResponse); +} + +void GVHandlePartition(void) { + String jsonResponse = "["; // Start of JSON array +#ifdef ESP32 + bool firstEntry = true; // Used to format the JSON array correctly + + esp_partition_iterator_t iter = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, NULL); +// esp_partition_iterator_t iter = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL); + + // Loop through partitions + while (iter != NULL) { + const esp_partition_t *partition = esp_partition_get(iter); + + // Add comma before the next entry if it's not the first + if (!firstEntry) + { + jsonResponse += ","; + } + firstEntry = false; + + // Append partition information in JSON format + jsonResponse += "{"; + jsonResponse += "\"label\":\"" + String(partition->label) + "\","; + jsonResponse += "\"type\":" + String(partition->type) + ","; + jsonResponse += "\"subtype\":" + String(partition->subtype) + ","; + jsonResponse += "\"address\":\"0x" + String(partition->address, HEX) + "\","; + jsonResponse += "\"size\":" + String(partition->size); + jsonResponse += "}"; + + // Move to next partition + iter = esp_partition_next(iter); + } + + // Clean up the iterator + esp_partition_iterator_release(iter); +#endif // ESP32 + + jsonResponse += "]"; // End of JSON array + GVWebserverSendJson(jsonResponse); } void GVHandleEvents(void) { @@ -240,7 +338,6 @@ void GVMonitorTask(void) { else { // Read digital GPIO - pintype = GV_DigitalPin; int value = digitalRead(pin); originalValue = value; if (value == 1) { @@ -248,6 +345,12 @@ void GVMonitorTask(void) { // } else { // currentState = 0; } +#ifdef GV_INPUT_DETECTION + int pin_mode = GetPinMode(pin); + pintype = (INPUT == pin_mode) ? GV_InputPin : (INPUT_PULLUP == pin_mode) ? GV_InputPullUp : GV_DigitalPin; +#else + pintype = GV_DigitalPin; +#endif } if (originalValue != GV.lastPinStates[pin]) { From 886b453e69e9e56652098b642d959f4c4f7abc42 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 28 Jan 2024 17:34:15 +0100 Subject: [PATCH 232/303] Fix ESP8266 eFuseMac result --- tasmota/html_compressed/HTTP_GV_PAGE.h | 44 ++++++++----------- tasmota/html_compressed/HTTP_GV_PAGE_150.h | 25 ----------- tasmota/html_uncompressed/HTTP_GV_PAGE.h | 43 +++++++----------- tasmota/html_uncompressed/HTTP_GV_PAGE_150.h | 24 ---------- tasmota/tasmota_support/support_esp8266.ino | 21 +++++---- .../xdrv_121_gpioviewer.ino | 9 ++-- 6 files changed, 51 insertions(+), 115 deletions(-) delete mode 100644 tasmota/html_compressed/HTTP_GV_PAGE_150.h delete mode 100644 tasmota/html_uncompressed/HTTP_GV_PAGE_150.h diff --git a/tasmota/html_compressed/HTTP_GV_PAGE.h b/tasmota/html_compressed/HTTP_GV_PAGE.h index 8c0574ecb..b0200b768 100644 --- a/tasmota/html_compressed/HTTP_GV_PAGE.h +++ b/tasmota/html_compressed/HTTP_GV_PAGE.h @@ -2,30 +2,24 @@ // compressed by tools/unishox/compress-html-uncompressed.py ///////////////////////////////////////////////////////////////////// -const size_t HTTP_GV_PAGE_SIZE = 806; -const char HTTP_GV_PAGE_COMPRESSED[] PROGMEM = "\x3D\x0F\xE1\x10\x98\x1D\x19\x0C\x64\x88\x51\x51\x0D\x20\x8F\xC3\xD0\x55\x0D\x08" - "\xFC\x3D\x05\x3B\x10\xFC\x3D\x2B\x68\x26\x7E\x1F\x5E\x47\x5A\x21\xE2\x18\x5A\x58" - "\x88\xCF\x58\xFB\xF9\xE8\x76\x02\x0D\x43\xD0\x75\xF9\xA1\x5F\x66\x0F\x87\xD9\xF5" - "\xE3\xEC\xFC\x3D\x02\xDE\x34\x5A\x21\xF0\xFB\x11\x98\xB1\x61\x51\x7A\x8C\x82\x65" - "\xE1\x4D\xD1\xF6\xBE\xC2\x3E\x1F\x7E\xA3\x20\x9F\x81\x06\x68\x20\xE2\x80\x8F\x89" - "\x0E\xCB\xF8\x80\xC1\xB1\x0F\xB0\x8F\x87\xDE\x87\x9C\x08\x75\x4C\x59\x9E\x87\x9C" - "\x74\xD0\xF0\xFB\x54\x64\x31\x9F\x0F\xBD\x1B\x63\xCC\xEC\x36\x1D\x7A\x1E\x71\xF6" - "\x7E\x1E\x9E\x0F\xFA\x32\x97\xBE\x19\xF0\xFB\x04\x19\x07\x60\xFB\x1C\x5E\xC0\xCD" - "\x1D\x1D\x0D\x7E\x3E\xCF\xC3\xD0\xEC\x04\x1A\x60\xA1\x83\x82\x0E\xFA\x3F\xB4\x18" - "\xA7\xF0\x50\xC2\xCF\xC3\x3B\xFA\xF3\xF9\x9B\xF9\x0C\xCF\xD1\xF0\xFA\x10\xF0\x67" - "\x7F\x5A\x30\xF8\x7D\x9F\x5E\x3E\xCF\x06\x77\xF5\xEC\x17\xF0\xD9\xF3\x98\xFA\x26" - "\x66\xFA\x8B\xD8\x2F\xE1\xB3\xBA\x7D\x8A\xAA\x18\x79\x9D\x87\x61\xF5\xE3\xCC\xFA" - "\x10\xEC\x66\x6F\xAB\xC7\xD9\xDE\x04\x1C\x3A\xC6\x8C\x0B\x78\x78\xFD\xEF\x53\xF9" - "\x9D\x84\x7C\x3E\xCF\xA1\x01\x07\x29\x19\xEF\xD8\xD2\xF6\x9B\x59\xF0\xFB\x3E\x84" - "\x44\x68\x43\x81\x06\x91\x8F\xB6\x5E\x34\x74\x18\xA2\xF0\xCB\x0C\x11\x6C\x02\x2F" - "\x01\x47\x60\x20\xF2\x78\x3B\x04\x32\x3F\x0F\x41\x34\xCD\x06\x15\xFB\xC7\xC3\xEC" - "\x7B\xFA\x21\xD6\x1E\x75\x5E\xF3\xF9\xF6\x08\x36\x34\x43\xE1\xF6\x35\xFB\xD6\x3C" - "\xC8\x76\x1B\x0F\xB0\x43\xC2\x01\x0A\x79\xD6\x3B\x0D\x88\x56\x88\x23\xE3\xEC\xFC" - "\x3D\x0E\xC1\x34\xCC\x10\x79\x9A\x7F\x04\x3C\x14\x10\x65\x1F\x60\x85\xA9\x3F\x82" - "\x46\x9D\xA3\x6C\x79\x82\x86\x9F\xA3\x6C\x79\x90\xFF\xEC\x60\xC7\xF0\x44\xD4\x41" - "\x07\x0B\x1F\x04\x2A\x2B\x47\xE1\xE9\xA3\x47\x81\x17\x99\x82\xD1\xB6\x3C\xCF\xB0" - "\x41\xE4\x3C\xFB\x56\x15\x1F\x0F\xB2\x1D\x97\xF1\x10\x20\xD5\x04\x6C\xDF\x84\xD0" - "\xEE\xB3\xFE\x04\x4E\x03\xC1\x06\x10\x23\xC8\x3B\x01\x07\x87\xA3\xB0\x55\x0D\x08" - "\xFC"; +const size_t HTTP_GV_PAGE_SIZE = 465; +const char HTTP_GV_PAGE_COMPRESSED[] PROGMEM = "\x3D\x0F\xE1\x10\x98\x1D\x19\x0C\x64\x85\x50\xD0\x8F\xC3\xD0\x55\x0D\x09\x05\x7C" + "\x3C\x7C\x3E\xDF\x1F\x67\xE1\xE8\x29\xD8\x87\xE1\xE9\x5B\x41\x33\xF0\xFA\xF2\x3A" + "\xD1\x0F\x10\xC2\xD2\xC4\x46\x7A\xC7\xDF\xCF\x43\xB0\x10\x6A\x1E\x83\x5D\x5A\x0C" + "\x55\xFF\xCE\x8F\x87\xD9\x0B\x2A\x2B\x23\x07\x59\xCF\x9F\x67\xE1\xE8\x43\xAF\xCD" + "\x0A\xFB\x30\x7C\x3E\xCF\xAF\x1F\x67\xE1\xE8\x16\xF1\xA2\xFB\x08\xF8\x7D\xE8\x79" + "\xC7\xD8\x21\x57\x31\x66\x7A\x1E\x71\xD3\x43\xC3\xEC\x10\xB2\x6E\xB1\xAC\xF8\x7D" + "\x99\xEB\x1F\x19\x9F\xA3\xED\x07\x9D\x4F\xA8\xF8\x7D\x8F\xE8\x94\x28\xF8\x23\x33" + "\xD0\xD9\xD6\x3F\xA2\x50\xA3\xA9\x6F\x6D\x6D\x84\x75\xF8\x3B\x09\x9F\x0E\x43\xA3" + "\x3E\xCF\xC3\xD0\xBC\x1F\xF4\x65\x2A\x2B\x32\x18\xCF\x87\xD8\xDC\x10\x58\x4C\xFB" + "\x41\xFF\x3D\xEC\xFE\x8F\x6F\x2F\x7C\x33\xE1\xF6\x43\xC4\x30\xB4\xB0\x10\x78\x25" + "\x23\x31\x6C\xE8\x6B\xF1\xF6\x7E\x1E\x87\x60\x20\xE2\xC0\x8F\xC0\x47\xA8\xC8\x27" + "\xE1\x4D\xD0\x24\xE3\xE0\x83\xC0\xD5\xFB\xCE\xBC\x76\x0D\xBD\xE3\xA0\x7E\xF1\xF6" + "\x7E\x1E\x87\x60\x20\xF1\x1C\x3B\x04\x32\x3F\x0F\x41\x34\xCD\x68\x87\xC3\xEE\xC6" + "\x0C\x3E\xCF\xC3\xD0\xEC\x13\x4C\xC1\x0F\x79\x3F\x07\xF7\x84\xC1\xF3\xA0\xF0\xCD" + "\xC3\xF7\xE7\x55\xBC\x3D\xE4\x7C\x47\xB7\x46\x1E\x67\xD9\xF5\xE3\xEC\xEA\x19\x9F" + "\xA3\xCC\xFB\x3E\x84\x3E\xCE\xA3\x1F\x6C\xBC\x68\xE8\x31\x45\xFB\x1A\x79\x9F\x67" + "\xD0\x88\x8D\x08\x71\xF6\x7B\x8F\x2A\x01\x8B\xC0\x49\xD8\x08\x3A\x49\xD8\x2A\x2B" + "\x86\x84\x7E\x1B"; #define HTTP_GV_PAGE Decompress(HTTP_GV_PAGE_COMPRESSED,HTTP_GV_PAGE_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_compressed/HTTP_GV_PAGE_150.h b/tasmota/html_compressed/HTTP_GV_PAGE_150.h deleted file mode 100644 index b0200b768..000000000 --- a/tasmota/html_compressed/HTTP_GV_PAGE_150.h +++ /dev/null @@ -1,25 +0,0 @@ -///////////////////////////////////////////////////////////////////// -// compressed by tools/unishox/compress-html-uncompressed.py -///////////////////////////////////////////////////////////////////// - -const size_t HTTP_GV_PAGE_SIZE = 465; -const char HTTP_GV_PAGE_COMPRESSED[] PROGMEM = "\x3D\x0F\xE1\x10\x98\x1D\x19\x0C\x64\x85\x50\xD0\x8F\xC3\xD0\x55\x0D\x09\x05\x7C" - "\x3C\x7C\x3E\xDF\x1F\x67\xE1\xE8\x29\xD8\x87\xE1\xE9\x5B\x41\x33\xF0\xFA\xF2\x3A" - "\xD1\x0F\x10\xC2\xD2\xC4\x46\x7A\xC7\xDF\xCF\x43\xB0\x10\x6A\x1E\x83\x5D\x5A\x0C" - "\x55\xFF\xCE\x8F\x87\xD9\x0B\x2A\x2B\x23\x07\x59\xCF\x9F\x67\xE1\xE8\x43\xAF\xCD" - "\x0A\xFB\x30\x7C\x3E\xCF\xAF\x1F\x67\xE1\xE8\x16\xF1\xA2\xFB\x08\xF8\x7D\xE8\x79" - "\xC7\xD8\x21\x57\x31\x66\x7A\x1E\x71\xD3\x43\xC3\xEC\x10\xB2\x6E\xB1\xAC\xF8\x7D" - "\x99\xEB\x1F\x19\x9F\xA3\xED\x07\x9D\x4F\xA8\xF8\x7D\x8F\xE8\x94\x28\xF8\x23\x33" - "\xD0\xD9\xD6\x3F\xA2\x50\xA3\xA9\x6F\x6D\x6D\x84\x75\xF8\x3B\x09\x9F\x0E\x43\xA3" - "\x3E\xCF\xC3\xD0\xBC\x1F\xF4\x65\x2A\x2B\x32\x18\xCF\x87\xD8\xDC\x10\x58\x4C\xFB" - "\x41\xFF\x3D\xEC\xFE\x8F\x6F\x2F\x7C\x33\xE1\xF6\x43\xC4\x30\xB4\xB0\x10\x78\x25" - "\x23\x31\x6C\xE8\x6B\xF1\xF6\x7E\x1E\x87\x60\x20\xE2\xC0\x8F\xC0\x47\xA8\xC8\x27" - "\xE1\x4D\xD0\x24\xE3\xE0\x83\xC0\xD5\xFB\xCE\xBC\x76\x0D\xBD\xE3\xA0\x7E\xF1\xF6" - "\x7E\x1E\x87\x60\x20\xF1\x1C\x3B\x04\x32\x3F\x0F\x41\x34\xCD\x68\x87\xC3\xEE\xC6" - "\x0C\x3E\xCF\xC3\xD0\xEC\x13\x4C\xC1\x0F\x79\x3F\x07\xF7\x84\xC1\xF3\xA0\xF0\xCD" - "\xC3\xF7\xE7\x55\xBC\x3D\xE4\x7C\x47\xB7\x46\x1E\x67\xD9\xF5\xE3\xEC\xEA\x19\x9F" - "\xA3\xCC\xFB\x3E\x84\x3E\xCE\xA3\x1F\x6C\xBC\x68\xE8\x31\x45\xFB\x1A\x79\x9F\x67" - "\xD0\x88\x8D\x08\x71\xF6\x7B\x8F\x2A\x01\x8B\xC0\x49\xD8\x08\x3A\x49\xD8\x2A\x2B" - "\x86\x84\x7E\x1B"; - -#define HTTP_GV_PAGE Decompress(HTTP_GV_PAGE_COMPRESSED,HTTP_GV_PAGE_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_uncompressed/HTTP_GV_PAGE.h b/tasmota/html_uncompressed/HTTP_GV_PAGE.h index 4b95ab8bb..8fed388bd 100644 --- a/tasmota/html_uncompressed/HTTP_GV_PAGE.h +++ b/tasmota/html_uncompressed/HTTP_GV_PAGE.h @@ -1,33 +1,24 @@ const char HTTP_GV_PAGE[] PROGMEM = - "" - "" - "" + "" + "" + "" "%s - GPIO Viewer" // SettingsTextEscaped(SET_DEVICENAME).c_str() + "" "" // GV_BASE_URL - "" - "" - "" - "" - "" - "" + "" "" "" - "
" - "" - "
" - "
" - "
" - "Board Image" - "
" - "
" - "
" - "
" + "
" + "" "" - ""; \ No newline at end of file + ""; diff --git a/tasmota/html_uncompressed/HTTP_GV_PAGE_150.h b/tasmota/html_uncompressed/HTTP_GV_PAGE_150.h deleted file mode 100644 index 8fed388bd..000000000 --- a/tasmota/html_uncompressed/HTTP_GV_PAGE_150.h +++ /dev/null @@ -1,24 +0,0 @@ -const char HTTP_GV_PAGE[] PROGMEM = - "" - "" - "" - "%s - GPIO Viewer" // SettingsTextEscaped(SET_DEVICENAME).c_str() - "" - "" // GV_BASE_URL - "" - "" - "" - "" - "" - "" - "
" - "" - "" - ""; diff --git a/tasmota/tasmota_support/support_esp8266.ino b/tasmota/tasmota_support/support_esp8266.ino index d21184d74..c9ba29078 100644 --- a/tasmota/tasmota_support/support_esp8266.ino +++ b/tasmota/tasmota_support/support_esp8266.ino @@ -229,26 +229,25 @@ String ESP_getEfuseMac(void) { uint32_t mac0 = *(uint32_t*)(0x3FF00050); uint32_t mac1 = *(uint32_t*)(0x3FF00054); uint32_t mac3 = *(uint32_t*)(0x3FF0005C); - uint32_t mach = 0; uint32_t macl = 0; if (mac3 != 0) { - mach = ((mac3 >> 16) & 0xFF) << 16; - mach |= ((mac3 >> 8) & 0xFF) << 8; - mach |= mac3 & 0xFF; + macl = (mac3 >> 16) & 0xFF; + macl |= ((mac3 >> 8) & 0xFF) << 8; + macl |= (mac3 & 0xFF) << 16; } else if (((mac1 >> 16) & 0xFF) == 0) { - mach = 0x18FE34; + macl = 0x34FE18; } else if (((mac1 >> 16) & 0xFF) == 1) { - mach = 0xACD074; + macl = 0x74D0AC; } String macStr = ""; - if (mach > 0) { - macl = ((mac1 >> 8) & 0xFF) << 16; - macl |= (mac1 & 0xFF) << 8; - macl |= (mac0 >> 24) & 0xFF; - + if (macl > 0) { + mach = (mac1 >> 8) & 0xFF; + mach |= (mac1 & 0xFF) << 8; + mach |= ((mac0 >> 24) & 0xFF) << 16; + uint64_t maca = ((uint64_t)mach << 24) | macl; // Need uint64ToString with base 10 as ESP8266 WStrings does not support uint64_t while (maca > 0) { diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index e7f7508e9..3b07b8ecf 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -42,9 +42,9 @@ const char *GVRelease = "1.5.0"; #ifdef USE_UNISHOX_COMPRESSION - #include "./html_compressed/HTTP_GV_PAGE_150.h" + #include "./html_compressed/HTTP_GV_PAGE.h" #else - #include "./html_uncompressed/HTTP_GV_PAGE_150.h" + #include "./html_uncompressed/HTTP_GV_PAGE.h" #endif const char HTTP_GV_EVENT[] PROGMEM = @@ -164,7 +164,7 @@ void GVHandleFreePSRam(void) { } void GVHandleSampling(void) { - String jsonResponse = "{\"sampling\": \"" + String(GV.sampling) + "\"}"; + String jsonResponse = "{\"sampling\":\"" + String(GV.sampling) + "\"}"; GVWebserverSendJson(jsonResponse); } @@ -265,7 +265,8 @@ void GVEventDisconnected(void) { } void GVCloseEvent(void) { - GVEventSend("{}", "close", millis()); // Closes web page +// GVEventSend("{}", "close", millis()); // Closes web page + GVEventSend("{}", "error", millis()); // Closes web page GVEventDisconnected(); } From e15e131ca2d1c338511c275136dcf114fff6576c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 28 Jan 2024 18:32:34 +0100 Subject: [PATCH 233/303] Update xdrv_121_gpioviewer.ino --- tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 3b07b8ecf..b33d8a1a9 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -265,8 +265,7 @@ void GVEventDisconnected(void) { } void GVCloseEvent(void) { -// GVEventSend("{}", "close", millis()); // Closes web page - GVEventSend("{}", "error", millis()); // Closes web page + GVEventSend("{}", "close", millis()); // Closes web page GVEventDisconnected(); } From 87bd890dbf1903446fe2e356bf00ab0838b4fb37 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 28 Jan 2024 19:05:20 +0100 Subject: [PATCH 234/303] Update GH Action versions (#20609) --- .github/workflows/Tasmota_build_devel.yml | 42 +++++++++++----------- .github/workflows/Tasmota_build_master.yml | 34 +++++++++--------- .github/workflows/build_all_the_things.yml | 24 ++++++------- .github/workflows/copy_change.yml | 2 +- 4 files changed, 51 insertions(+), 51 deletions(-) diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml index 9d660b3a1..aada97400 100644 --- a/.github/workflows/Tasmota_build_devel.yml +++ b/.github/workflows/Tasmota_build_devel.yml @@ -20,9 +20,9 @@ jobs: if: github.repository == 'arendst/Tasmota' && github.ref_name == 'development' continue-on-error: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install clang compiler @@ -46,7 +46,7 @@ jobs: run: | cd lib/libesp32_lvgl/lv_binding_berry ../../libesp32/berry/berry -s -g solidify_all.be - - uses: jason2866/upload-artifact@v2.0.2 + - uses: jason2866/upload-artifact@v2.0.3 with: name: '["berry_tasmota", "berry_matter", "berry_animate", "berry_lvgl", "berry_header"]' path: '["./lib/libesp32/berry_tasmota/src/solidify", "./lib/libesp32/berry_matter/src/solidify", "./lib/libesp32/berry_animate/src/solidify", "./lib/libesp32_lvgl/lv_binding_berry/src/solidify", "./lib/libesp32/berry/generate"]' @@ -57,12 +57,12 @@ jobs: if: github.repository == 'arendst/Tasmota' && github.ref_name == 'development' continue-on-error: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - - uses: jason2866/download-artifact@v3 + - uses: jason2866/download-artifact@v3.0.4 with: name: | berry_tasmota @@ -76,7 +76,7 @@ jobs: ./lib/libesp32/berry_animate/src/solidify ./lib/libesp32_lvgl/lv_binding_berry/src/solidify ./lib/libesp32/berry/generate - - uses: stefanzweifel/git-auto-commit-action@v4 + - uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: Solidified Code updated @@ -100,11 +100,11 @@ jobs: - tasmota32c6-safeboot - tasmota32c6cdc-safeboot steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: development - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install dependencies @@ -116,7 +116,7 @@ jobs: - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }} - name: Upload safeboot firmware artifacts - uses: actions/upload-artifact@v3 + uses: jason2866/upload-artifact@v2.0.3 with: name: firmware_safeboot path: ./build_output @@ -140,11 +140,11 @@ jobs: - tasmota-zbbridge - tasmota-zigbee steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: development - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install dependencies @@ -154,7 +154,7 @@ jobs: - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }} - name: Upload firmware artifacts - uses: actions/upload-artifact@v3 + uses: jason2866/upload-artifact@v2.0.3 with: name: firmware path: ./build_output @@ -185,11 +185,11 @@ jobs: - tasmota32c2-arduino30 - tasmota32c6cdc-arduino30 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: development - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install dependencies @@ -199,7 +199,7 @@ jobs: cp ./platformio_tasmota_core3_env_sample.ini ./platformio_tasmota_core3_env.ini cp ./platformio_override_sample.ini ./platformio_override.ini - name: Download safeboot firmwares - uses: actions/download-artifact@v3 + uses: jason2866/download-artifact@v3.0.4 with: name: firmware_safeboot path: ./firmware @@ -209,7 +209,7 @@ jobs: - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }} - name: Upload firmware artifacts - uses: actions/upload-artifact@v3 + uses: jason2866/upload-artifact@v2.0.3 with: name: firmware path: ./build_output @@ -224,11 +224,11 @@ jobs: variant: [ tasmota, tasmota32 ] language: [ AD, AF, BG, BR, CN, CZ, DE, ES, FR, FY, GR, HE, HU, IT, KO, NL, PL, PT, RO, RU, SE, SK, TR, TW, UK, VN ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: development - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install dependencies @@ -238,7 +238,7 @@ jobs: cp ./platformio_tasmota_core3_env_sample.ini ./platformio_tasmota_core3_env.ini cp ./platformio_override_sample.ini ./platformio_override.ini - name: Download safeboot firmwares - uses: actions/download-artifact@v3 + uses: jason2866/download-artifact@v3.0.4 with: name: firmware_safeboot path: ./firmware @@ -248,7 +248,7 @@ jobs: - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }}-${{ matrix.language }} - name: Upload language firmware artifacts - uses: actions/upload-artifact@v3 + uses: jason2866/upload-artifact@v2.0.3 with: name: firmware path: ./build_output diff --git a/.github/workflows/Tasmota_build_master.yml b/.github/workflows/Tasmota_build_master.yml index f735ae5a7..c3d4db1fa 100644 --- a/.github/workflows/Tasmota_build_master.yml +++ b/.github/workflows/Tasmota_build_master.yml @@ -33,11 +33,11 @@ jobs: - tasmota32c6-safeboot - tasmota32c6cdc-safeboot steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: master - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install dependencies @@ -49,7 +49,7 @@ jobs: - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }} - name: Upload safeboot firmware artifacts - uses: actions/upload-artifact@v3 + uses: jason2866/upload-artifact@v2.0.3 with: name: firmware_safeboot path: ./build_output @@ -72,11 +72,11 @@ jobs: - tasmota-zbbridge - tasmota-zigbee steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: master - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install dependencies @@ -86,7 +86,7 @@ jobs: - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }} - name: Upload firmware artifacts - uses: actions/upload-artifact@v3 + uses: jason2866/upload-artifact@v2.0.3 with: name: firmware path: ./build_output @@ -115,11 +115,11 @@ jobs: - tasmota32s3cdc - tasmota32solo1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: master - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install dependencies @@ -127,7 +127,7 @@ jobs: pip install wheel pip install -U platformio - name: Download safeboot firmwares - uses: actions/download-artifact@v3 + uses: jason2866/download-artifact@v3.0.4 with: name: firmware_safeboot path: ./firmware @@ -137,7 +137,7 @@ jobs: - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }} - name: Upload firmware artifacts - uses: actions/upload-artifact@v3 + uses: jason2866/upload-artifact@v2.0.3 with: name: firmware path: ./build_output @@ -152,11 +152,11 @@ jobs: variant: [ tasmota, tasmota32 ] language: [ AD, AF, BG, BR, CN, CZ, DE, ES, FR, FY, GR, HE, HU, IT, KO, NL, PL, PT, RO, RU, SE, SK, TR, TW, UK, VN ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: master - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install dependencies @@ -164,7 +164,7 @@ jobs: pip install wheel pip install -U platformio - name: Download safeboot firmwares - uses: actions/download-artifact@v3 + uses: jason2866/download-artifact@v3.0.4 with: name: firmware_safeboot path: ./firmware @@ -174,7 +174,7 @@ jobs: - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }}-${{ matrix.language }} - name: Upload language firmware artifacts - uses: actions/upload-artifact@v3 + uses: jason2866/upload-artifact@v2.0.3 with: name: firmware path: ./build_output @@ -184,14 +184,14 @@ jobs: runs-on: ubuntu-latest continue-on-error: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Download Tasmota firmwares - uses: actions/download-artifact@v3 + uses: jason2866/download-artifact@v3.0.4 with: name: firmware path: ./mv_firmware - name: Download safeboot firmwares - uses: actions/download-artifact@v3 + uses: jason2866/download-artifact@v3.0.4 with: name: firmware_safeboot path: ./mv_firmware diff --git a/.github/workflows/build_all_the_things.yml b/.github/workflows/build_all_the_things.yml index 2d0d84e61..5215e5f66 100644 --- a/.github/workflows/build_all_the_things.yml +++ b/.github/workflows/build_all_the_things.yml @@ -26,9 +26,9 @@ jobs: variant: - tasmota32-safeboot steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install dependencies @@ -40,7 +40,7 @@ jobs: #platformio update - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }} - - uses: actions/upload-artifact@v3 + - uses: jason2866/upload-artifact@v2.0.3 with: name: firmware path: ./build_output @@ -54,9 +54,9 @@ jobs: variant: - tasmota32-webcam steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install dependencies @@ -68,7 +68,7 @@ jobs: #platformio update - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }} - - uses: actions/upload-artifact@v3 + - uses: jason2866/upload-artifact@v2.0.3 with: name: firmware path: ./build_output @@ -117,9 +117,9 @@ jobs: - tasmota32c6-safeboot - tasmota32c6cdc-safeboot steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install dependencies @@ -133,7 +133,7 @@ jobs: cp ./platformio_override_sample.ini ./platformio_override.ini - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }} - - uses: actions/upload-artifact@v3 + - uses: jason2866/upload-artifact@v2.0.3 with: name: firmware path: ./build_output @@ -147,9 +147,9 @@ jobs: variant: [ tasmota ] language: [ AD, AF, BG, BR, CN, CZ, DE, ES, FR, FY, GR, HE, HU, IT, KO, NL, PL, PT, RO, RU, SE, SK, TR, TW, UK, VN ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install dependencies @@ -161,7 +161,7 @@ jobs: #platformio update - name: Run PlatformIO run: platformio run -e ${{ matrix.variant }}-${{ matrix.language }} - - uses: actions/upload-artifact@v3 + - uses: jason2866/upload-artifact@v2.0.3 with: name: firmware path: ./build_output diff --git a/.github/workflows/copy_change.yml b/.github/workflows/copy_change.yml index da236fc52..9ff05ed09 100644 --- a/.github/workflows/copy_change.yml +++ b/.github/workflows/copy_change.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'arendst/Tasmota' steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Push I2CDevices.md to https://github.com/Tasmota/docs uses: Jason2866/copy_file_to_another_repo_action@main env: From d0fc49462af85dc189bef97aee2aba7698f8fdb9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 28 Jan 2024 19:13:21 +0100 Subject: [PATCH 235/303] Update stale to v9 --- .github/workflows/stale-actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale-actions.yml b/.github/workflows/stale-actions.yml index b99f6f555..e3b6856e0 100644 --- a/.github/workflows/stale-actions.yml +++ b/.github/workflows/stale-actions.yml @@ -8,7 +8,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v6.0.1 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 25 From 6794a91286bf979d08ebd154786c3de102ce057c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 29 Jan 2024 16:56:55 +0100 Subject: [PATCH 236/303] CI check for Berrz --- .github/workflows/build_all_the_things.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build_all_the_things.yml b/.github/workflows/build_all_the_things.yml index 5215e5f66..4776ea8cd 100644 --- a/.github/workflows/build_all_the_things.yml +++ b/.github/workflows/build_all_the_things.yml @@ -7,6 +7,7 @@ on: paths: - '**.c' - '**.cpp' + - '**.be' - '**.h' - '**.hpp' - '**.ino' From 274f75829e2f08c93b4c5d9d256a400b9cfc63e1 Mon Sep 17 00:00:00 2001 From: kubedzero Date: Mon, 29 Jan 2024 10:58:15 -0500 Subject: [PATCH 237/303] Fix typos regarding reboots (#20615) --- tasmota/berry/animate_demo/leds_animation.be | 2 +- tasmota/berry/modules/Partition_Wizard/partition_wizard.be | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/berry/animate_demo/leds_animation.be b/tasmota/berry/animate_demo/leds_animation.be index 96f4d47ea..68ea18495 100644 --- a/tasmota/berry/animate_demo/leds_animation.be +++ b/tasmota/berry/animate_demo/leds_animation.be @@ -46,7 +46,7 @@ class Leds_animation_UI webserver.content_send(string.format("

Step 4: %s

", self.display_step_state(self.test_step_4(p), "flash final firmware"))) webserver.content_send("
") + webserver.content_send("onsubmit='return confirm(\"This will cause multiple restarts.\");'>") var ota_url = tasmota.cmd("OtaUrl").find("OtaUrl", "") webserver.content_send(string.format("
OTA Url

", ota_url)) diff --git a/tasmota/berry/modules/Partition_Wizard/partition_wizard.be b/tasmota/berry/modules/Partition_Wizard/partition_wizard.be index 47a59ef00..e9555286b 100644 --- a/tasmota/berry/modules/Partition_Wizard/partition_wizard.be +++ b/tasmota/berry/modules/Partition_Wizard/partition_wizard.be @@ -577,7 +577,7 @@ class Partition_wizard_UI webserver.content_send(string.format("

Step 4: %s

", self.display_step_state(self.test_step_4(p), "flash final firmware"))) webserver.content_send("") + webserver.content_send("onsubmit='return confirm(\"This will cause multiple restarts.\");'>") var ota_url = tasmota.cmd("OtaUrl").find("OtaUrl", "") webserver.content_send(string.format("
OTA Url

", ota_url)) From bfd44d06f9c9adb4b3dcc09b95c33fbb9a40455f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 29 Jan 2024 17:16:38 +0100 Subject: [PATCH 238/303] Refactor GPIO Viewer --- tasmota/tasmota.ino | 3 +- .../xdrv_121_gpioviewer.ino | 187 +++++++++++------- 2 files changed, 113 insertions(+), 77 deletions(-) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index d7e01c0c8..ca4b0a1f5 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -770,8 +770,6 @@ void setup(void) { if (bitRead(Settings->rule_enabled, 0)) Run_Scripter(">BS",3,0); #endif - XdrvCall(FUNC_ACTIVE); // FUNC_ACTIVE - TasmotaGlobal.rules_flag.system_init = 1; } @@ -887,6 +885,7 @@ void Scheduler(void) { if (TimeReached(state_second)) { SetNextTimeInterval(state_second, 1000); PerformEverySecond(); + XdrvCall(FUNC_ACTIVE); XdrvXsnsCall(FUNC_EVERY_SECOND); } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index b33d8a1a9..a2e16c0dc 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -65,18 +65,20 @@ enum GVPinTypes { #endif // GV_INPUT_DETECTION }; -struct { - WiFiClient WebClient; +typedef struct { ESP8266WebServer *WebServer; Ticker ticker; - int lastPinStates[MAX_GPIO_PIN]; + String baseUrl; uint32_t lastSentWithNoActivity; uint32_t freeHeap; uint32_t freePSRAM; uint32_t sampling; - bool active; + uint16_t port; + int8_t lastPinStates[MAX_GPIO_PIN]; bool sse_ready; -} GV; +} tGV; +tGV* GV = nullptr; +WiFiClient GVWebClient; #ifdef GV_INPUT_DETECTION @@ -98,35 +100,41 @@ int GetPinMode(uint8_t pin) { #endif // GV_INPUT_DETECTION -void GVStop(void) { - GV.sse_ready = false; - GV.ticker.detach(); - GV.active = false; +void GVInit(void) { + if (!GV) { + GV = (tGV*)calloc(sizeof(tGV), 1); + if (GV) { + GV->sampling = (GV_SAMPLING_INTERVAL < 20) ? 20 : GV_SAMPLING_INTERVAL; + GV->baseUrl = GV_BASE_URL; + GV->port = GV_PORT; + } + } +} - GV.WebServer->stop(); - GV.WebServer = nullptr; +void GVStop(void) { + GV->sse_ready = false; + GV->ticker.detach(); + + GV->WebServer->stop(); + GV->WebServer = nullptr; } void GVBegin(void) { - if (0 == GV.sampling) { - GV.sampling = (GV_SAMPLING_INTERVAL < 20) ? 20 : GV_SAMPLING_INTERVAL; + if (GV->WebServer == nullptr) { + GV->WebServer = new ESP8266WebServer(GV->port); + // Set CORS headers for global responses + // GV->WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*")); + // GV->WebServer->sendHeader(F("Access-Control-Allow-Methods"), F("GET, POST, OPTIONS")); + // GV->WebServer->sendHeader(F("Access-Control-Allow-Headers"), F("Content-Type")); + GV->WebServer->on("/", GVHandleRoot); + GV->WebServer->on("/release", GVHandleRelease); + GV->WebServer->on("/free_psram", GVHandleFreePSRam); + GV->WebServer->on("/sampling", GVHandleSampling); + GV->WebServer->on("/espinfo", GVHandleEspInfo); + GV->WebServer->on("/partition", GVHandlePartition); + GV->WebServer->on("/events", GVHandleEvents); + GV->WebServer->begin(); } - - GV.WebServer = new ESP8266WebServer(GV_PORT); - // Set CORS headers for global responses -// GV.WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*")); -// GV.WebServer->sendHeader(F("Access-Control-Allow-Methods"), F("GET, POST, OPTIONS")); -// GV.WebServer->sendHeader(F("Access-Control-Allow-Headers"), F("Content-Type")); - GV.WebServer->on("/", GVHandleRoot); - GV.WebServer->on("/release", GVHandleRelease); - GV.WebServer->on("/free_psram", GVHandleFreePSRam); - GV.WebServer->on("/sampling", GVHandleSampling); - GV.WebServer->on("/espinfo", GVHandleEspInfo); - GV.WebServer->on("/partition", GVHandlePartition); - GV.WebServer->on("/events", GVHandleEvents); - GV.WebServer->begin(); - - GV.active = true; } void GVHandleRoot(void) { @@ -134,17 +142,17 @@ void GVHandleRoot(void) { char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, SettingsTextEscaped(SET_DEVICENAME).c_str(), - GV_BASE_URL, - WiFi.localIP().toString().c_str(), - GV_PORT, + GV->baseUrl.c_str(), + NetworkAddress().toString().c_str(), + GV->port, ESP_getFreeSketchSpace() / 1024); if (content == nullptr) { return; } // Avoid crash - GV.WebServer->send_P(200, "text/html", content); + GV->WebServer->send_P(200, "text/html", content); free(content); } void GVWebserverSendJson(String &jsonResponse) { - GV.WebServer->send(200, "application/json", jsonResponse); + GV->WebServer->send(200, "application/json", jsonResponse); } void GVHandleRelease(void) { @@ -164,7 +172,7 @@ void GVHandleFreePSRam(void) { } void GVHandleSampling(void) { - String jsonResponse = "{\"sampling\":\"" + String(GV.sampling) + "\"}"; + String jsonResponse = "{\"sampling\":\"" + String(GV->sampling) + "\"}"; GVWebserverSendJson(jsonResponse); } @@ -242,39 +250,41 @@ void GVHandlePartition(void) { } void GVHandleEvents(void) { - GV.WebClient = GV.WebServer->client(); - GV.WebClient.setNoDelay(true); -// GV.WebClient.setSync(true); + GVWebClient = GV->WebServer->client(); + GVWebClient.setNoDelay(true); +// GVWebClient.setSync(true); - GV.WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // The payload can go on forever - GV.WebServer->sendContent_P(HTTP_GV_EVENT); + GV->WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // The payload can go on forever + GV->WebServer->sendContent_P(HTTP_GV_EVENT); - GV.sse_ready = true; // Ready for async updates - if (GV.sampling != 100) { - GV.ticker.attach_ms(GV.sampling, GVMonitorTask); // Use Tasmota Scheduler (100) or Ticker (20..99,101..1000) + GV->sse_ready = true; // Ready for async updates + if (GV->sampling != 100) { + GV->ticker.attach_ms(GV->sampling, GVMonitorTask); // Use Tasmota Scheduler (100) or Ticker (20..99,101..1000) } AddLog(LOG_LEVEL_DEBUG, PSTR("IOV: Connected")); } void GVEventDisconnected(void) { - if (GV.sse_ready) { + if (GV->sse_ready) { AddLog(LOG_LEVEL_DEBUG, PSTR("IOV: Disconnected")); } - GV.sse_ready = false; // This just stops the event to be restarted by opening root page again - GV.ticker.detach(); + GV->sse_ready = false; // This just stops the event to be restarted by opening root page again + GV->ticker.detach(); } void GVCloseEvent(void) { - GVEventSend("{}", "close", millis()); // Closes web page - GVEventDisconnected(); + if (GV->WebServer) { + GVEventSend("{}", "close", millis()); // Closes web page + GVEventDisconnected(); + } } //void GVEventSend(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); void GVEventSend(const char *message, const char *event, uint32_t id) { - if (GV.WebClient.connected()) { + if (GVWebClient.connected()) { // generateEventMessage() in AsyncEventSource.cpp -// GV.WebClient.printf_P(PSTR("retry:1000\nid:%u\nevent:%s\ndata:%s\n\n"), id, event, message); - GV.WebClient.printf_P(PSTR("id:%u\nevent:%s\ndata:%s\n\n"), id, event, message); +// GVWebClient.printf_P(PSTR("retry:1000\nid:%u\nevent:%s\ndata:%s\n\n"), id, event, message); + GVWebClient.printf_P(PSTR("id:%u\nevent:%s\ndata:%s\n\n"), id, event, message); } else { GVEventDisconnected(); } @@ -353,10 +363,10 @@ void GVMonitorTask(void) { #endif } - if (originalValue != GV.lastPinStates[pin]) { + if (originalValue != GV->lastPinStates[pin]) { if (hasChanges) { jsonMessage += ","; } jsonMessage += "\"" + String(pin) + "\":{\"s\":" + currentState + ",\"v\":" + originalValue + ",\"t\":" + pintype + "}"; - GV.lastPinStates[pin] = originalValue; + GV->lastPinStates[pin] = originalValue; hasChanges = true; } } @@ -366,9 +376,9 @@ void GVMonitorTask(void) { } uint32_t heap = ESP_getFreeHeap(); - if (heap != GV.freeHeap) { + if (heap != GV->freeHeap) { // Send freeHeap - GV.freeHeap = heap; + GV->freeHeap = heap; char temp[20]; snprintf_P(temp, sizeof(temp), PSTR("%d KB"), heap / 1024); GVEventSend(temp, "free_heap", millis()); @@ -379,8 +389,8 @@ void GVMonitorTask(void) { if (UsePSRAM()) { // Send freePsram uint32_t psram = ESP.getFreePsram(); - if (psram != GV.freePSRAM) { - GV.freePSRAM = psram; + if (psram != GV->freePSRAM) { + GV->freePSRAM = psram; char temp[20]; snprintf_P(temp, sizeof(temp), PSTR("%d KB"), psram / 1024); GVEventSend(temp, "free_psram", millis()); @@ -391,16 +401,16 @@ void GVMonitorTask(void) { if (!hasChanges) { // Send freeHeap as keepAlive - uint32_t last_sent = millis() - GV.lastSentWithNoActivity; + uint32_t last_sent = millis() - GV->lastSentWithNoActivity; if (last_sent > GV_KEEP_ALIVE) { // No activity, resending for pulse char temp[20]; snprintf_P(temp, sizeof(temp), PSTR("%d KB"), heap / 1024); GVEventSend(temp, "free_heap", millis()); - GV.lastSentWithNoActivity = millis(); + GV->lastSentWithNoActivity = millis(); } } else { - GV.lastSentWithNoActivity = millis(); + GV->lastSentWithNoActivity = millis(); } } @@ -409,10 +419,10 @@ void GVMonitorTask(void) { \*********************************************************************************************/ const char kGVCommands[] PROGMEM = "GV|" // Prefix - "Viewer|Sampling"; + "Viewer|Sampling|Port|Url"; void (* const GVCommand[])(void) PROGMEM = { - &CmndGvViewer, &CmndGvSampling }; + &CmndGvViewer, &CmndGvSampling, &CmndGvPort, &CmndGvUrl }; void CmndGvViewer(void) { /* GvViewer - Show current viewer state @@ -420,10 +430,11 @@ void CmndGvViewer(void) { GvViewer 1 - Turn viewer On GvViewer 2 - Toggle viewer state */ + GVInit(); if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { uint32_t state = XdrvMailbox.payload; if (2 == state) { // Toggle - state = GV.active ^1; + state = (GV->WebServer == nullptr) ^1; } if (state) { // On GVBegin(); @@ -432,8 +443,8 @@ void CmndGvViewer(void) { GVStop(); } } - if (GV.active) { - Response_P(PSTR("{\"%s\":\"Active on http://%s:" STR(GV_PORT) "/\"}"), XdrvMailbox.command, WiFi.localIP().toString().c_str()); + if (GV->WebServer) { + Response_P(PSTR("{\"%s\":\"Active on http://%s:%d/\"}"), XdrvMailbox.command, NetworkAddress().toString().c_str(), GV->port); } else { ResponseCmndChar_P(PSTR("Stopped")); } @@ -443,11 +454,38 @@ void CmndGvSampling(void) { /* GvSampling - Show current sampling interval GvSampling 20 .. 1000 - Set sampling interval */ + GVInit(); if ((XdrvMailbox.payload >= 20) && (XdrvMailbox.payload <= 1000)) { GVCloseEvent(); // Stop current updates - GV.sampling = XdrvMailbox.payload; // 20 - 1000 milliseconds + GV->sampling = XdrvMailbox.payload; // 20 - 1000 milliseconds } - ResponseCmndNumber(GV.sampling); + ResponseCmndNumber(GV->sampling); +} + +void CmndGvPort(void) { + /* GvPort - Show vurrent port + GvPort 1 - Select default port + GvPort 5557 - Set port + */ + GVInit(); + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 65536)) { + GVCloseEvent(); // Stop current updates + GV->port = (SC_DEFAULT == XdrvMailbox.payload) ? GV_PORT : XdrvMailbox.payload; + } + ResponseCmndNumber(GV->port); +} + +void CmndGvUrl(void) { + /* GvUrl - Show current url + GvUrl 1 - Select default url + GvUrl https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer_1_5/ + */ + GVInit(); + if (XdrvMailbox.data_len > 0) { + GVCloseEvent(); // Stop current updates + GV->baseUrl = (SC_DEFAULT == XdrvMailbox.payload) ? GV_BASE_URL : XdrvMailbox.data; + } + ResponseCmndChar(GV->baseUrl.c_str()); } /*********************************************************************************************\ @@ -464,12 +502,11 @@ void GVSetupAndStart(void) { AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_GPIO_VIEWER)); - if (!GV.active) { // WebServer not started - GVBegin(); - } + GVInit(); + GVBegin(); // Start WebServer char redirect[100]; - snprintf_P(redirect, sizeof(redirect), PSTR("http://%s:" STR(GV_PORT) "/"), WiFi.localIP().toString().c_str()); + snprintf_P(redirect, sizeof(redirect), PSTR("http://%s:%d/"), NetworkAddress().toString().c_str(), GV->port); Webserver->sendHeader(F("Location"), redirect); Webserver->send(303); } @@ -499,18 +536,18 @@ bool Xdrv121(uint32_t function) { break; #endif // USE_WEBSERVER } - if (GV.active) { + if (GV && (GV->WebServer)) { switch (function) { case FUNC_LOOP: - if (GV.WebServer) { GV.WebServer->handleClient(); } + GV->WebServer->handleClient(); break; case FUNC_EVERY_100_MSECOND: - if (GV.sse_ready && (100 == GV.sampling)) { + if (GV->sse_ready && (100 == GV->sampling)) { GVMonitorTask(); } break; case FUNC_SAVE_BEFORE_RESTART: - GVCloseEvent(); // Stop current updates + GVCloseEvent(); // Stop current updates break; case FUNC_ACTIVE: result = true; From 95b03592dc0b753dfcfa30c1cc17d8e1f2a547f9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 30 Jan 2024 16:57:45 +0100 Subject: [PATCH 239/303] Add ISR logging failsafe --- tasmota/tasmota_support/support.ino | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tasmota/tasmota_support/support.ino b/tasmota/tasmota_support/support.ino index 8966df9f2..766a821dc 100755 --- a/tasmota/tasmota_support/support.ino +++ b/tasmota/tasmota_support/support.ino @@ -2570,6 +2570,15 @@ uint32_t HighestLogLevel() { } void AddLog(uint32_t loglevel, PGM_P formatP, ...) { +#ifdef ESP32 + if (xPortInIsrContext()) { + // When called from an ISR, you should not send out logs. + // Allocating memory from within an ISR is a big no-no. + // Also long-time blocking like sending logs (especially to a syslog server) + // is also really not a good idea from an ISR call. + return; + } +#endif uint32_t highest_loglevel = HighestLogLevel(); // If no logging is requested then do not access heap to fight fragmentation From 083ddad6833a9fcb4e12882b88c34f9add724deb Mon Sep 17 00:00:00 2001 From: Christian Baars Date: Tue, 30 Jan 2024 17:50:03 +0100 Subject: [PATCH 240/303] add BTHOME (#20625) --- tasmota/include/xsns_62_esp32_mi.h | 14 ++- .../tasmota_xsns_sensor/xsns_62_esp32_mi.ino | 95 ++++++++++++++++--- 2 files changed, 96 insertions(+), 13 deletions(-) diff --git a/tasmota/include/xsns_62_esp32_mi.h b/tasmota/include/xsns_62_esp32_mi.h index f707bddaf..ef372036e 100644 --- a/tasmota/include/xsns_62_esp32_mi.h +++ b/tasmota/include/xsns_62_esp32_mi.h @@ -141,6 +141,14 @@ struct ATCPacket_t{ //and PVVX }; }; +struct BTHome_info_t{ + uint8_t encrypted:1; + uint8_t reserved:1; + uint8_t triggered:1; + uint8_t reserved2:2; + uint8_t version:2; +}; + struct BLERingBufferItem_t{ uint16_t returnCharUUID; uint16_t handle; @@ -349,8 +357,9 @@ void (*const MI32_Commands[])(void) PROGMEM = {&CmndMi32Key, &CmndMi32Name,&Cmnd #define PVVX 15 #define YLKG08 16 #define YLAI003 17 +#define BTHOME 18 -#define MI32_TYPES 17 //count this manually +#define MI32_TYPES 18 //count this manually const uint16_t kMI32DeviceID[MI32_TYPES]={ 0x0098, // Flora 0x01aa, // MJ_HT_V1 @@ -369,9 +378,10 @@ const uint16_t kMI32DeviceID[MI32_TYPES]={ 0x0098, // Flora 0x944a, // PVVX -> this is a fake ID 0x03b6, // YLKG08 and YLKG07 - version w/wo mains 0x07bf, // YLAI003 + 0xb770, // BTHome -> fake ID }; -const char kMI32DeviceType[] PROGMEM = {"Flora|MJ_HT_V1|LYWSD02|LYWSD03|CGG1|CGD1|NLIGHT|MJYD2S|YLYK01|MHOC401|MHOC303|ATC|MCCGQ02|SJWS01L|PVVX|YLKG08|YLAI003"}; +const char kMI32DeviceType[] PROGMEM = {"Flora|MJ_HT_V1|LYWSD02|LYWSD03|CGG1|CGD1|NLIGHT|MJYD2S|YLYK01|MHOC401|MHOC303|ATC|MCCGQ02|SJWS01L|PVVX|YLKG08|YLAI003|BTHOME"}; const char kMI32_ConnErrorMsg[] PROGMEM = "no Error|could not connect|did disconnect|got no service|got no characteristic|can not read|can not notify|can not write|did not write|notify time out"; diff --git a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino index 5acc0d1b5..04b31918a 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino @@ -138,10 +138,14 @@ class MI32AdvCallbacks: public NimBLEScanCallbacks { if(UUID==0xfe95) { MI32ParseResponse((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI); } - else if(UUID==0xfdcd) { + else if(UUID==0xfcd2) { + std::string optionalName = advertisedDevice->getName(); + MI32parseBTHomePacket((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI, optionalName.c_str()); + } + else if(UUID==0xfdcd) { // deprecated MI32parseCGD1Packet((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI); } - else if(UUID==0x181a) { //ATC and PVVX + else if(UUID==0x181a) { //ATC and PVVX - deprecated, change FW setting of these devices to BTHome V2 MI32ParseATCPacket((char*)advertisedDevice->getServiceData(0).data(),ServiceDataLength, addr, RSSI); } _mutex = false; @@ -435,7 +439,7 @@ int MI32_decryptPacket(char * _buf, uint16_t _bufSize, uint8_t * _payload, uint3 * @param _type Type number of the sensor * @return uint32_t Known or new slot in the sensors-vector */ -uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, uint8_t counter){ +uint32_t MIBLEgetSensorSlot(uint8_t * _MAC, uint16_t _type, uint8_t counter){ DEBUG_SENSOR_LOG(PSTR("%s: will test ID-type: %x"),D_CMND_MI32, _type); uint16_t _pid = _type; // save for unknown types bool _success = false; @@ -450,7 +454,7 @@ uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, uint8_t counter) DEBUG_SENSOR_LOG(PSTR("%s: vector size %u"),D_CMND_MI32, MIBLEsensors.size()); for(uint32_t i=0; i100.0f) value=100.0f; //clamp it for now - history[_hour] = (((uint8_t)(value/5.0f))+1) + 0b10000000; //lux + history[_hour] = (((value/5.0f) + 1) + 0b10000000); //lux // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: history lux: %u in hour:%u"),history[_hour], _hour); break; #ifdef USE_MI_ESP32_ENERGY case 100: // energy if(value == 0.0f) value = 1.0f; - uint8_t _watt = ((uint8_t)(MI32ln(value))*2) + 0b10000000; //watt + uint8_t _watt = ((MI32ln(value)*2) + 0b10000000); //watt history[_hour] = _watt; // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: history energy: %u for value:%u"),history[_hour], value); //still playing with the mapping break; @@ -997,6 +1000,9 @@ void MI32saveConfig(){ if(_sensor.name != nullptr){ snprintf_P(_name_feat,64,PSTR(",\"name\":\"%s\",\"feat\":%u"),_sensor.name,_sensor.feature.raw); } + else if(_sensor.type == BTHOME && _sensor.name == nullptr){ + snprintf_P(_name_feat,64,PSTR(",\"feat\":%u"),_sensor.feature.raw); + } else{ _name_feat[0] = 0; } @@ -1812,6 +1818,70 @@ if(decryptRet!=0){ if(MI32.option.directBridgeMode) MI32.mode.shallTriggerTele = 1; } +void MI32parseBTHomePacket(char * _buf, uint32_t length, uint8_t addr[6], int RSSI, const char* optionalName){ + uint32_t _slot; + _slot = MIBLEgetSensorSlot(addr, 0xb770, 0); // fake ID, constant fake counter + if (optionalName[0] != '\0'){ + AddLog(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), optionalName,_slot); + } + MIBLEsensors[_slot].RSSI = RSSI; + MIBLEsensors[_slot].lastTime = millis(); + + BTHome_info_t info = (BTHome_info_t)_buf[0]; + MIBLEsensors[_slot].feature.needsKey = info.encrypted; + + uint32_t idx = 1; + while(idx < length - 1){ + switch(_buf[idx]){ + case 0: + if(_buf[idx+1] == MIBLEsensors[_slot].lastCnt){ + return; // known packet + } + MIBLEsensors[_slot].lastCnt = _buf[idx+1]; + idx += 2; + break; + case 1: + MIBLEsensors[_slot].bat = _buf[idx+1]; + MIBLEsensors[_slot].eventType.bat = 1; + MIBLEsensors[_slot].feature.bat = 1; + idx += 2; + break; + case 2: + MIBLEsensors[_slot].temp = (int16_t)(_buf[idx+1]|_buf[idx+2] << 8)/100.0f; + MIBLEsensors[_slot].eventType.temp = 1; + MIBLEsensors[_slot].feature.temp = 1; + MI32addHistory(MIBLEsensors[_slot].temp_history, (float)MIBLEsensors[_slot].temp, 0); + idx += 3; + break; + case 3: + MIBLEsensors[_slot].hum = (uint16_t)(_buf[idx+1]|_buf[idx+2] << 8)/100.0f; + MIBLEsensors[_slot].eventType.hum = 1; + MIBLEsensors[_slot].feature.hum = 1; + MI32addHistory(MIBLEsensors[_slot].hum_history, (float)MIBLEsensors[_slot].hum, 1); + idx += 3; + break; + case 0x0b: + // power ?? + idx += 2; + break; + case 0x0c: + //voltage + idx += 2; + break; + default: + AddLog(LOG_LEVEL_INFO,PSTR("M32: unknown BTHome data type: %u, discard rest of data buffer!"),_buf[idx]); + AddLogBuffer(LOG_LEVEL_DEBUG,(uint8_t*)_buf,length); + idx = length; // "break" + break; + } + } +#ifdef USE_MI_EXT_GUI + bitSet(MI32.widgetSlot,_slot); +#endif //USE_MI_EXT_GUI + MIBLEsensors[_slot].shallSendMQTT = 1; + if(MI32.option.directBridgeMode) MI32.mode.shallTriggerTele = 1; +} + void MI32ParseATCPacket(char * _buf, uint32_t length, uint8_t addr[6], int RSSI){ ATCPacket_t *_packet = (ATCPacket_t*)_buf; bool isATC = (length == 0x0d); @@ -1846,7 +1916,6 @@ void MI32ParseATCPacket(char * _buf, uint32_t length, uint8_t addr[6], int RSSI) #endif //USE_MI_EXT_GUI MIBLEsensors[_slot].shallSendMQTT = 1; if(MI32.option.directBridgeMode) MI32.mode.shallTriggerTele = 1; - } void MI32parseCGD1Packet(char * _buf, uint32_t length, uint8_t addr[6], int RSSI){ // no MiBeacon @@ -2050,6 +2119,10 @@ void CmndMi32Key(void) { } void CmndMi32Name(void) { + if(XdrvMailbox.index > MIBLEsensors.size() - 1){ + ResponseCmndDone(); + return; + } if(MIBLEsensors[XdrvMailbox.index].name != nullptr){ delete []MIBLEsensors[XdrvMailbox.index].name; } From 717873eac7e4f5cb29d346c6a53af497fd3ec3f9 Mon Sep 17 00:00:00 2001 From: Barbudor Date: Tue, 30 Jan 2024 18:45:54 +0100 Subject: [PATCH 241/303] enforce TLL255 on ESP8266 (#20616) --- lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp b/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp index 9a805fb2b..25f1b9a48 100644 --- a/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp +++ b/lib/lib_div/esp-knx-ip-0.5.2/src/esp-knx-ip-send.cpp @@ -78,7 +78,7 @@ void ESPKNXIP::send(address_t const &receiver, knx_command_type_t ct, uint8_t da #endif #ifdef ESP8266 - udp.beginPacketMulticast(MULTICAST_IP, MULTICAST_PORT, WiFi.localIP()); + udp.beginPacketMulticast(MULTICAST_IP, MULTICAST_PORT, WiFi.localIP(), 255); #else if (0 == udp.beginMulticastPacket()) { udp.beginMulticast(MULTICAST_IP, MULTICAST_PORT); From c7a1b3f7caaeff48b96371d32a9919896ff5f49a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 31 Jan 2024 20:07:27 +0100 Subject: [PATCH 242/303] Use Mac ARM GH runner :-) (#20633) --- .github/workflows/build_all_the_things.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_all_the_things.yml b/.github/workflows/build_all_the_things.yml index 4776ea8cd..d85932592 100644 --- a/.github/workflows/build_all_the_things.yml +++ b/.github/workflows/build_all_the_things.yml @@ -47,7 +47,7 @@ jobs: path: ./build_output os-check-mac: - runs-on: macOS-12 + runs-on: macOS-14 if: github.repository == 'arendst/Tasmota' strategy: fail-fast: true @@ -59,7 +59,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.x' + python-version: '3.11' - name: Install dependencies run: | pip install wheel From 6c16a5122a94b4776094ed3755ed643230872604 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 1 Feb 2024 09:52:24 +0100 Subject: [PATCH 243/303] Berry add `introspect.contains` and `bytes.addfloat` (#20635) --- CHANGELOG.md | 1 + lib/libesp32/berry/src/be_byteslib.c | 28 +++++++++++++++++++++++ lib/libesp32/berry/src/be_introspectlib.c | 15 ++++++++++++ 3 files changed, 44 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32e00dc50..04a9da372 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. - HASPmota support for `min` and `max` attribute in `slider` (#20582) - ESP32-C3 support for GPIO11 (#18350) - ESP32 support for Shelly Plus Add-On using DS18x20 or DHT11/AM2301/DHT21/DHT22/AM2302/AM2321/SI7021 on GPIO0/1 (#20580) +- Berry add `introspect.contains` and `bytes.addfloat` ### Breaking Changed diff --git a/lib/libesp32/berry/src/be_byteslib.c b/lib/libesp32/berry/src/be_byteslib.c index 221e3e2a4..1789dca94 100644 --- a/lib/libesp32/berry/src/be_byteslib.c +++ b/lib/libesp32/berry/src/be_byteslib.c @@ -1002,6 +1002,32 @@ static int m_setfloat(bvm *vm) be_return_nil(vm); } +/* + * Add a 32 bits float + * `addfloat(value:real or int [, big_endian:bool]) -> instance` + * + */ +static int m_addfloat(bvm *vm) +{ + int argc = be_top(vm); + buf_impl attr = bytes_check_data(vm, 4); /* we reserve 4 bytes anyways */ + check_ptr(vm, &attr); + if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); } + if (argc >=2 && (be_isint(vm, 2) || be_isreal(vm, 2))) { + float val_f = (float) be_toreal(vm, 2); + int32_t* val_i = (int32_t*) &val_f; + bbool be = bfalse; + if (argc >= 3) { + be = be_tobool(vm, 3); + } + if (be) { buf_add4_be(&attr, *val_i); } else { buf_add4_le(&attr, *val_i); } + be_pop(vm, argc - 1); + m_write_attributes(vm, 1, &attr); /* update attributes */ + be_return(vm); + } + be_return_nil(vm); +} + /* * Fills a buffer with another buffer. * @@ -1761,6 +1787,7 @@ void be_load_byteslib(bvm *vm) { "setbytes", m_setbytes }, { "getfloat", m_getfloat }, { "setfloat", m_setfloat }, + { "addfloat", m_addfloat }, { "item", m_item }, { "setitem", m_setitem }, { "size", m_size }, @@ -1806,6 +1833,7 @@ class be_class_bytes (scope: global, name: bytes) { geti, func(m_geti) getfloat, func(m_getfloat) setfloat, func(m_setfloat) + addfloat, func(m_addfloat) set, func(m_set) seti, func(m_set) setbytes, func(m_setbytes) diff --git a/lib/libesp32/berry/src/be_introspectlib.c b/lib/libesp32/berry/src/be_introspectlib.c index ba3d60aa2..ba54aad25 100644 --- a/lib/libesp32/berry/src/be_introspectlib.c +++ b/lib/libesp32/berry/src/be_introspectlib.c @@ -93,6 +93,19 @@ static int m_findmember(bvm *vm) be_return_nil(vm); } +static int m_contains(bvm *vm) +{ + bbool contains = bfalse; + int top = be_top(vm); + if (top >= 2 && be_isstring(vm, 2) && (be_isinstance(vm, 1) || be_ismodule(vm, 1) || be_isclass(vm, 1))) { + if (be_getmember(vm, 1, be_tostring(vm, 2))) { + contains = btrue; + } + } + be_pushbool(vm, contains); + be_return(vm); +} + static int m_setmember(bvm *vm) { int top = be_top(vm); @@ -225,6 +238,7 @@ be_native_module_attr_table(introspect) { be_native_module_function("get", m_findmember), be_native_module_function("set", m_setmember), + be_native_module_function("contains", m_contains), be_native_module_function("module", m_getmodule), be_native_module_function("setmodule", m_setmodule), @@ -245,6 +259,7 @@ module introspect (scope: global, depend: BE_USE_INTROSPECT_MODULE) { get, func(m_findmember) set, func(m_setmember) + contains, func(m_contains) module, func(m_getmodule) setmodule, func(m_setmodule) From 2a293d6cf99eab85bcf9985e90ac0f03d37b6e3a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 1 Feb 2024 11:50:56 +0100 Subject: [PATCH 244/303] Update `pip` --- .github/workflows/build_all_the_things.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_all_the_things.yml b/.github/workflows/build_all_the_things.yml index d85932592..ef836e12f 100644 --- a/.github/workflows/build_all_the_things.yml +++ b/.github/workflows/build_all_the_things.yml @@ -47,7 +47,7 @@ jobs: path: ./build_output os-check-mac: - runs-on: macOS-14 + runs-on: macos-14 if: github.repository == 'arendst/Tasmota' strategy: fail-fast: true @@ -63,7 +63,7 @@ jobs: - name: Install dependencies run: | pip install wheel - #python -m pip install --upgrade pip + python -m pip install --upgrade pip pip install -U platformio #platformio upgrade --dev #platformio update From a757447e6d5fa0f5536912d789c3ee4853b9f7e7 Mon Sep 17 00:00:00 2001 From: sfromis <47082390+sfromis@users.noreply.github.com> Date: Thu, 1 Feb 2024 14:46:02 +0100 Subject: [PATCH 245/303] Update webserver_async.be (#20638) --- tasmota/berry/gpio_viewer/webserver_async.be | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/berry/gpio_viewer/webserver_async.be b/tasmota/berry/gpio_viewer/webserver_async.be index fadbb3196..dc7801868 100644 --- a/tasmota/berry/gpio_viewer/webserver_async.be +++ b/tasmota/berry/gpio_viewer/webserver_async.be @@ -180,7 +180,7 @@ class Webserver_async_cnx else # remove the first bytes already sent self.buf_out.setbytes(0, buf_out, sent) - self.byf_out.resize(size(buf_out) - sent) + self.buf_out.resize(size(buf_out) - sent) end end end From 9c45a51f671772f120dc0bf99e8b9ac456ae1f95 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:08:31 +0100 Subject: [PATCH 246/303] Next try to upgrade `pip` --- .github/workflows/build_all_the_things.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_all_the_things.yml b/.github/workflows/build_all_the_things.yml index ef836e12f..ab2c99b9f 100644 --- a/.github/workflows/build_all_the_things.yml +++ b/.github/workflows/build_all_the_things.yml @@ -63,7 +63,7 @@ jobs: - name: Install dependencies run: | pip install wheel - python -m pip install --upgrade pip + python -m pip install --upgrade pip --disable-pip-version-check --no-warn-script-location --root-user-action=ignore pip install -U platformio #platformio upgrade --dev #platformio update From c24c0a53c06ec2d70a27b38c561382d3fed90877 Mon Sep 17 00:00:00 2001 From: Christian Baars Date: Fri, 2 Feb 2024 11:09:43 +0100 Subject: [PATCH 247/303] fix compilation with newer Arduino framework (#20641) --- tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_wire.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_wire.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_wire.ino index 1518ce518..f982e9ea4 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_wire.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_wire.ino @@ -164,7 +164,7 @@ extern "C" { myWire.write(value); } else if (be_isstring(vm, 2)) { const char * s = be_tostring(vm, 1); - myWire.write(s); + myWire.write((uint8_t*) s, strlen(s)); } else if ((buf = be_tobytes(vm, 2, &len)) != nullptr) { myWire.write((uint8_t*) buf, len); } else { From f9ffb34e2f1fd1cc4d2d5692cc230ba35a1460e6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 2 Feb 2024 12:59:38 +0100 Subject: [PATCH 248/303] Next try to silence `pip` warning --- .github/workflows/build_all_the_things.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_all_the_things.yml b/.github/workflows/build_all_the_things.yml index ab2c99b9f..3984a31ab 100644 --- a/.github/workflows/build_all_the_things.yml +++ b/.github/workflows/build_all_the_things.yml @@ -59,11 +59,11 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.11' + python-version: '3.12' - name: Install dependencies run: | pip install wheel - python -m pip install --upgrade pip --disable-pip-version-check --no-warn-script-location --root-user-action=ignore + #python -m pip install --upgrade pip pip install -U platformio #platformio upgrade --dev #platformio update From a95314ff969bfc9d2be3a0cbee2fa7cbc16e3b7c Mon Sep 17 00:00:00 2001 From: Christian Baars Date: Fri, 2 Feb 2024 15:17:45 +0100 Subject: [PATCH 249/303] fix build for Core 2 (#20645) --- tasmota/include/xsns_62_esp32_mi.h | 15 +++++++++------ tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino | 3 ++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tasmota/include/xsns_62_esp32_mi.h b/tasmota/include/xsns_62_esp32_mi.h index ef372036e..2b9ec9e99 100644 --- a/tasmota/include/xsns_62_esp32_mi.h +++ b/tasmota/include/xsns_62_esp32_mi.h @@ -141,12 +141,15 @@ struct ATCPacket_t{ //and PVVX }; }; -struct BTHome_info_t{ - uint8_t encrypted:1; - uint8_t reserved:1; - uint8_t triggered:1; - uint8_t reserved2:2; - uint8_t version:2; +union BTHome_info_t{ + struct{ + uint8_t encrypted:1; + uint8_t reserved:1; + uint8_t triggered:1; + uint8_t reserved2:2; + uint8_t version:2; + }; + char byte_value; }; struct BLERingBufferItem_t{ diff --git a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino index 04b31918a..1ee386063 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino @@ -1827,7 +1827,8 @@ void MI32parseBTHomePacket(char * _buf, uint32_t length, uint8_t addr[6], int RS MIBLEsensors[_slot].RSSI = RSSI; MIBLEsensors[_slot].lastTime = millis(); - BTHome_info_t info = (BTHome_info_t)_buf[0]; + BTHome_info_t info; + info.byte_value = _buf[0]; MIBLEsensors[_slot].feature.needsKey = info.encrypted; uint32_t idx = 1; From 58816aa9a2c01f5122bbe14d8ac9d3f191e37b89 Mon Sep 17 00:00:00 2001 From: Mark Fickett Date: Sat, 3 Feb 2024 06:34:24 -0500 Subject: [PATCH 250/303] Lower the minimum temperature to 10C (50F) and make it pick up user-defined values. (#20628) --- tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino b/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino index a51166ae6..6579b27b7 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino @@ -161,8 +161,12 @@ struct miel_hvac_msg_update { #define MIEL_HVAC_UPDATE_MODE_FAN 0x07 #define MIEL_HVAC_UPDATE_MODE_AUTO 0x08 uint8_t temp; -#define MIEL_HVAC_UPDATE_TEMP_MIN 16 +#ifndef MIEL_HVAC_UPDATE_TEMP_MIN +#define MIEL_HVAC_UPDATE_TEMP_MIN 10 +#endif +#ifndef MIEL_HVAC_UPDATE_TEMP_MAX #define MIEL_HVAC_UPDATE_TEMP_MAX 31 +#endif uint8_t fan; #define MIEL_HVAC_UPDATE_FAN_AUTO 0x00 #define MIEL_HVAC_UPDATE_FAN_QUIET 0x01 From 478bd0ce17710342b37944b47f68b1daf42f7081 Mon Sep 17 00:00:00 2001 From: Andrey Osin Date: Sat, 3 Feb 2024 14:35:13 +0300 Subject: [PATCH 251/303] Fix Wi-Fi scan results process when scanning fails. (#20631) --- tasmota/tasmota_support/support_wifi.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/tasmota_support/support_wifi.ino b/tasmota/tasmota_support/support_wifi.ino index fbf6dc1b1..33c5622e3 100644 --- a/tasmota/tasmota_support/support_wifi.ino +++ b/tasmota/tasmota_support/support_wifi.ino @@ -386,7 +386,7 @@ void WifiBeginAfterScan(void) ResponseClear(); - uint32_t initial_item = (Wifi.scan_state - 9)*10; + int32_t initial_item = (Wifi.scan_state - 9)*10; if ( wifi_scan_result > initial_item ) { // Sort networks by RSSI From 55259aa8c50babeb2a67bb6a3d547ff045476c70 Mon Sep 17 00:00:00 2001 From: SteWers <42718143+SteWers@users.noreply.github.com> Date: Sat, 3 Feb 2024 12:37:57 +0100 Subject: [PATCH 252/303] [Energy] Fix frequency handling (#20626) * [Energy] Prepare MQTT subscribe - Prepare energy driver for using MQTT subscribe - Fix handling of frequency * MQTT in xnrg * Revert MQTT --- tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino | 7 +++---- tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino index a294aba4c..b2ca4aada 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino @@ -673,10 +673,9 @@ void EnergyEverySecond(void) { Energy->active_power[i] = 0; if (!isnan(Energy->apparent_power[i])) { Energy->apparent_power[i] = 0; } if (!isnan(Energy->reactive_power[i])) { Energy->reactive_power[i] = 0; } - if (!isnan(Energy->frequency[i]) && !Energy->type_dc) { Energy->frequency[i] = 0; } - if (!isnan(Energy->power_factor[i])) { Energy->power_factor[i] = 0; } - if (!isnan(Energy->export_active[i])) { Energy->export_active[i] = 0; } - + if (!isnan(Energy->frequency[i])) { Energy->frequency[i] = 0; } + if (!isnan(Energy->power_factor[i])) { Energy->power_factor[i] = 0; } + if (!isnan(Energy->export_active[i])) { Energy->export_active[i] = 0; } data_valid--; } } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino index 4c1b22452..bc7b9428b 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino @@ -893,10 +893,9 @@ void EnergyEverySecond(void) { Energy->active_power[i] = 0; if (!isnan(Energy->apparent_power[i])) { Energy->apparent_power[i] = 0; } if (!isnan(Energy->reactive_power[i])) { Energy->reactive_power[i] = 0; } - if (!isnan(Energy->frequency[i]) && !Energy->type_dc) { Energy->frequency[i] = 0; } - if (!isnan(Energy->power_factor[i])) { Energy->power_factor[i] = 0; } - if (!isnan(Energy->export_active[i])) { Energy->export_active[i] = 0; } - + if (!isnan(Energy->frequency[i])) { Energy->frequency[i] = 0; } + if (!isnan(Energy->power_factor[i])) { Energy->power_factor[i] = 0; } + if (!isnan(Energy->export_active[i])) { Energy->export_active[i] = 0; } data_valid--; } } From 92b8bb3c9b3d2a88abdcbc6a95b19c4fa757ebb5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 3 Feb 2024 17:23:07 +0100 Subject: [PATCH 253/303] Update changelogs --- CHANGELOG.md | 4 ++- RELEASENOTES.md | 6 ++-- .../xdrv_121_gpioviewer.ino | 31 +++++++++++-------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04a9da372..10997e198 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,8 @@ All notable changes to this project will be documented in this file. - HASPmota support for `min` and `max` attribute in `slider` (#20582) - ESP32-C3 support for GPIO11 (#18350) - ESP32 support for Shelly Plus Add-On using DS18x20 or DHT11/AM2301/DHT21/DHT22/AM2302/AM2321/SI7021 on GPIO0/1 (#20580) -- Berry add `introspect.contains` and `bytes.addfloat` +- ESP32 MI32 Legacy initial support for sensors using BTHOME packet format (#20625) +- Berry `introspect.contains` and `bytes.addfloat` (#20635) ### Breaking Changed @@ -19,6 +20,7 @@ All notable changes to this project will be documented in this file. - ESP32 Core3 platform update from 2024.01.11 to 2024.01.12 (#20576) - Utouch optimizations, rgb i2c init (#20596) - GPIO Viewer update from 1.0.7 to 1.5.0 +- Miel HVAC lower the minimum temperature to 10C (#20628) ### Fixed - Berry C mapping, raise an error if too many arguments are sent (#20604) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 8aabdf518..0393061ea 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -133,8 +133,8 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - ESP32 used UART information - ESP32 support GPIOViewer when ``define USE_ESP32_GPIO_VIEWER`` is enabled - ESP32 MI BLE support for Xiaomi LYWSD02MMC [#20381](https://github.com/arendst/Tasmota/issues/20381) -- ESP32 support for Shelly Plus Add-On using DS18x20 or DHT11/AM2301/DHT21/DHT22/AM2302/AM2321/SI7021 on GPIO0/1 (#20580) - [#20580](https://github.com/arendst/Tasmota/issues/20580) +- ESP32 support for Shelly Plus Add-On using DS18x20 or DHT11/AM2301/DHT21/DHT22/AM2302/AM2321/SI7021 on GPIO0/1 [#20580](https://github.com/arendst/Tasmota/issues/20580) +- ESP32 MI32 Legacy initial support for sensors using BTHOME packet format [#20625](https://github.com/arendst/Tasmota/issues/20625) - ESP32-C3 support for GPIO11 [#18350](https://github.com/arendst/Tasmota/issues/18350) - Berry GPIO viewer initial version using async webserver [#20416](https://github.com/arendst/Tasmota/issues/20416) - Berry `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) @@ -152,6 +152,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Berry solidification of strings longer than 255 bytes [#20529](https://github.com/arendst/Tasmota/issues/20529) - Berry syntax coloring for Notepad++ by FransO [#20541](https://github.com/arendst/Tasmota/issues/20541) - Berry/Zigbee web hook per device for customized status display [#20542](https://github.com/arendst/Tasmota/issues/20542) +- Berry `introspect.contains` and `bytes.addfloat` [#20635](https://github.com/arendst/Tasmota/issues/20635) - Zigbee ``ZbEmulation`` to selectively exclude some devices from Hue/Alexa emulation [#20552](https://github.com/arendst/Tasmota/issues/20552) - LVGL `lv.str_arr` [#20480](https://github.com/arendst/Tasmota/issues/20480) - LVGL option to add `lv.keyboard` extra widget [#20496](https://github.com/arendst/Tasmota/issues/20496) @@ -176,6 +177,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Web file upload response on upload error [#20340](https://github.com/arendst/Tasmota/issues/20340) - Header `Host` is now collected by Webserver [#20446](https://github.com/arendst/Tasmota/issues/20446) - Utouch optimizations, rgb i2c init [#20596](https://github.com/arendst/Tasmota/issues/20596) +- Miel HVAC lower the minimum temperature to 10C [#20628](https://github.com/arendst/Tasmota/issues/20628) - Webcam tweaks [#20451](https://github.com/arendst/Tasmota/issues/20451) - IP stack compatible with new Core3 IPv6 implementation [#20509](https://github.com/arendst/Tasmota/issues/20509) - Refactored Pio filesystem download script [#20544](https://github.com/arendst/Tasmota/issues/20544) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index a2e16c0dc..0bfbf7644 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -58,24 +58,23 @@ enum GVPinTypes { GV_DigitalPin = 0, GV_PWMPin = 1, GV_AnalogPin = 2, -#ifdef GV_INPUT_DETECTION GV_InputPin = 3, GV_InputPullUp = 4, GV_InputPullDn = 5 -#endif // GV_INPUT_DETECTION }; typedef struct { ESP8266WebServer *WebServer; Ticker ticker; String baseUrl; + int lastPinStates[MAX_GPIO_PIN]; uint32_t lastSentWithNoActivity; uint32_t freeHeap; uint32_t freePSRAM; uint32_t sampling; uint16_t port; - int8_t lastPinStates[MAX_GPIO_PIN]; bool sse_ready; + bool init_done; } tGV; tGV* GV = nullptr; WiFiClient GVWebClient; @@ -94,6 +93,7 @@ int GetPinMode(uint8_t pin) { uint32_t port = digitalPinToPort(pin); volatile uint32_t *reg = portModeRegister(port); if (*reg & bit) { return OUTPUT; } // ESP8266 = 0x01, ESP32 = 0x03 + // Detecting INPUT_PULLUP doesn't function consistently volatile uint32_t *out = portOutputRegister(port); return ((*out & bit) ? INPUT_PULLUP : INPUT); // ESP8266 = 0x02 : 0x00, ESP32 = 0x05 : x01 } @@ -140,6 +140,8 @@ void GVBegin(void) { void GVHandleRoot(void) { GVCloseEvent(); + GV->init_done = false; + char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, SettingsTextEscaped(SET_DEVICENAME).c_str(), GV->baseUrl.c_str(), @@ -299,15 +301,7 @@ void GVMonitorTask(void) { String jsonMessage = "{"; for (uint32_t pin = 0; pin < MAX_GPIO_PIN; pin++) { int currentState = 0; -/* - // Skip unconfigured GPIO - uint32_t pin_type = GetPin(pin) / 32; - if (GPIO_NONE == pin_type) { - pintype = GV_DigitalPin; - originalValue = 0; -// currentState = 0; - } -*/ + #ifdef ESP32 // Read PWM GPIO int pwm_resolution = ledcReadDutyResolution(pin); @@ -371,7 +365,18 @@ void GVMonitorTask(void) { } } jsonMessage += "}"; - if (hasChanges) { + + if (!GV->init_done) { + // Show at least configured GPIOs + for (uint32_t pin = 0; pin < MAX_GPIO_PIN; pin++) { + uint32_t pin_type = GetPin(pin) / 32; + if (pin_type != GPIO_NONE) { + GV->lastPinStates[pin] = -1; + } + } + GV->init_done = true; + } + else if (hasChanges) { GVEventSend(jsonMessage.c_str(), "gpio-state", millis()); } From 110c88e8e143ff13e33f14a2cec986ec52117ab2 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 3 Feb 2024 19:56:29 +0100 Subject: [PATCH 254/303] Matter aggregator relocated to endpoint 1 for Google compatibility, may break existing associations (#20654) --- CHANGELOG.md | 1 + .../berry_matter/src/be_matter_module.c | 3 +- .../src/embedded/Matter_Fabric.be | 12 + .../src/embedded/Matter_Plugin_0.be | 9 - .../embedded/Matter_Plugin_1_Aggregator.be | 64 +- .../src/embedded/Matter_Plugin_1_Device.be | 2 - .../src/embedded/Matter_Plugin_1_Root.be | 13 +- .../src/embedded/Matter_zz_Device.be | 22 +- .../src/solidify/solidified_Matter_Fabric.h | 2128 +++-- .../src/solidify/solidified_Matter_Plugin_0.h | 43 +- .../solidified_Matter_Plugin_1_Aggregator.h | 280 +- .../solidified_Matter_Plugin_1_Device.h | 71 +- .../solidified_Matter_Plugin_1_Root.h | 1736 ++-- .../solidified_Matter_Plugin_2_Light1.h | 3 +- .../solidified_Matter_Plugin_2_OnOff.h | 3 +- ...olidified_Matter_Plugin_2_Sensor_Contact.h | 3 +- ...idified_Matter_Plugin_2_Sensor_Occupancy.h | 3 +- .../solidified_Matter_Plugin_2_Sensor_OnOff.h | 3 +- .../solidified_Matter_Plugin_2_Shutter.h | 3 +- ...solidified_Matter_Plugin_3_Bridge_Light0.h | 3 +- ...ed_Matter_Plugin_3_Bridge_Sensor_Contact.h | 3 +- ..._Matter_Plugin_3_Bridge_Sensor_Occupancy.h | 3 +- .../solidified_Matter_Plugin_3_Light2.h | 3 +- .../solidified_Matter_Plugin_3_Light3.h | 3 +- .../solidified_Matter_Plugin_3_Sensor_Flow.h | 3 +- ...lidified_Matter_Plugin_3_Sensor_Humidity.h | 3 +- ...ified_Matter_Plugin_3_Sensor_Illuminance.h | 3 +- ...lidified_Matter_Plugin_3_Sensor_Pressure.h | 3 +- .../solidified_Matter_Plugin_3_Sensor_Temp.h | 3 +- .../solidified_Matter_Plugin_3_ShutterTilt.h | 3 +- ...solidified_Matter_Plugin_4_Bridge_Light1.h | 3 +- ...ified_Matter_Plugin_4_Bridge_Sensor_Flow.h | 3 +- ...d_Matter_Plugin_4_Bridge_Sensor_Humidity.h | 3 +- ...atter_Plugin_4_Bridge_Sensor_Illuminance.h | 3 +- ...d_Matter_Plugin_4_Bridge_Sensor_Pressure.h | 3 +- ...ified_Matter_Plugin_4_Bridge_Sensor_Temp.h | 3 +- ...solidified_Matter_Plugin_5_Bridge_Light2.h | 3 +- ...solidified_Matter_Plugin_5_Bridge_Light3.h | 3 +- .../solidify/solidified_Matter_zz_Device.h | 8474 +++++++++-------- 39 files changed, 6650 insertions(+), 6283 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10997e198..9816dd5a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file. - Berry `introspect.contains` and `bytes.addfloat` (#20635) ### Breaking Changed +- Matter aggregator relocated to endpoint 1 for Google compatibility, may break existing associations ### Changed - Library OneWire-Stickbreaker by TasmotaOneWire supporting Shelly Plus Add-On (#20580) diff --git a/lib/libesp32/berry_matter/src/be_matter_module.c b/lib/libesp32/berry_matter/src/be_matter_module.c index 81b271482..ebaa2d616 100644 --- a/lib/libesp32/berry_matter/src/be_matter_module.c +++ b/lib/libesp32/berry_matter/src/be_matter_module.c @@ -285,7 +285,8 @@ module matter (scope: global, strings: weak) { _STYLESHEET, comptr(MATTER_STYLESHEET) _ADD_ENDPOINT_JS, comptr(MATTER_ADD_ENDPOINT_HINTS_JS) MATTER_OPTION, int(151) // SetOption151 enables Matter - AGGREGATOR_ENDPOINT, int(0xFE) // for Alexa we need only 8 bits endpoints + AGGREGATOR_ENDPOINT, int(0x0001) // some controllers require aggregator to be endpoint 1 + START_ENDPOINT, int(0x0002) // endpoint where to start devices seconds_to_dhm, ctype_func(matter_seconds_to_dhm) Verhoeff, class(be_class_Matter_Verhoeff) diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Fabric.be b/lib/libesp32/berry_matter/src/embedded/Matter_Fabric.be index 2681197f2..ec25bc7af 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Fabric.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Fabric.be @@ -43,6 +43,7 @@ class Matter_Fabric : Matter_Expirable var _store # reference back to session store # timestamp var created + var deleted # timestamp when the deletion of fabric was requested, and deferred # fabric-index var fabric_index # index number for fabrics, starts with `1` var fabric_parent # index of the parent fabric, i.e. the fabric that triggered the provisioning (if nested) @@ -76,6 +77,7 @@ class Matter_Fabric : Matter_Expirable self._sessions = matter.Expirable_list() self.fabric_label = "" self.created = tasmota.rtc_utc() + # self.deleted = nil # no need to actually set to nil # init group counters self._counter_group_data_snd_impl = matter.Counter() self._counter_group_ctrl_snd_impl = matter.Counter() @@ -276,6 +278,16 @@ class Matter_Fabric : Matter_Expirable return session end + ############################################################# + # Mark for deleteion in the near future + # + def mark_for_deletion() + self.deleted = tasmota.rtc_utc() + end + def is_marked_for_deletion() + return self.deleted != nil + end + ############################################################# # Fabric::tojson() # diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_0.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_0.be index 3e7bb9e42..000d5cfb2 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_0.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_0.be @@ -38,7 +38,6 @@ class Matter_Plugin # Configuration of the plugin: clusters and type static var CLUSTERS = { 0x001D: [0,1,2,3,0xFFFC,0xFFFD], # Descriptor Cluster 9.5 p.453 - 0x0039: [0x11], # Bridged Device Basic Information 9.13 p.485 } # Accepted Update commands for virtual devices static var UPDATE_COMMANDS = [] @@ -266,14 +265,6 @@ class Matter_Plugin return tlv_solo.set(TLV.U4, 1) # "Initial Release" end - # ==================================================================================================== - elif cluster == 0x0039 # ========== Bridged Device Basic Information 9.13 p.485 ========== - - if attribute == 0x0011 # ---------- Reachable / bool ---------- - return tlv_solo.set(TLV.BOOL, 1) # by default we are reachable - else - return super(self).read_attribute(session, ctx, tlv_solo) # rest is handled by 0x0028 - end else return nil end diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Aggregator.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Aggregator.be index 395edf39e..7c0fbc6f4 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Aggregator.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Aggregator.be @@ -26,9 +26,10 @@ import matter class Matter_Plugin_Aggregator : Matter_Plugin static var TYPE = "aggregator" # name of the plug-in in json static var DISPLAY_NAME = "Aggregator" # display name of the plug-in -# static var CLUSTERS = { -# # 0x001D: inherited # Descriptor Cluster 9.5 p.453 -# } + static var CLUSTERS = matter.consolidate_clusters(_class, { + # 0x001D: inherited # Descriptor Cluster 9.5 p.453 + 0x0003: [0,1,0xFFFC,0xFFFD], # Identify 1.2 p.16 + }) static var TYPES = { 0x000E: 1 } # Aggregator ############################################################# @@ -39,14 +40,30 @@ class Matter_Plugin_Aggregator : Matter_Plugin var cluster = ctx.cluster var attribute = ctx.attribute - if cluster == 0x001D # ========== Descriptor Cluster 9.5 p.453 ========== + # ==================================================================================================== + if cluster == 0x0003 # ========== Identify 1.2 p.16 ========== + if attribute == 0x0000 # ---------- IdentifyTime / u2 ---------- + return tlv_solo.set(TLV.U2, 0) # no identification in progress + elif attribute == 0x0001 # ---------- IdentifyType / enum8 ---------- + return tlv_solo.set(TLV.U1, 0) # IdentifyType = 0x00 None + elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- + return tlv_solo.set(TLV.U4, 0) # no features + elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- + return tlv_solo.set(TLV.U4, 4) # "new data model format and notation" + end + elif cluster == 0x001D # ========== Descriptor Cluster 9.5 p.453 ========== + if attribute == 0x0002 # ---------- ClientList / list[cluster-id] ---------- + var pl = TLV.Matter_TLV_array() + # from connectedhome reference implementation + pl.add_TLV(nil, TLV.U2, 0x001E) # Binding + return pl # overwrite PartsList - if attribute == 0x0003 # ---------- PartsList / list[endpoint-no]---------- + elif attribute == 0x0003 # ---------- PartsList / list[endpoint-no]---------- var pl = TLV.Matter_TLV_array() var eps = self.device.get_active_endpoints(true) for ep: eps - if ep < matter.AGGREGATOR_ENDPOINT + if ep != matter.AGGREGATOR_ENDPOINT pl.add_TLV(nil, TLV.U2, ep) # add each endpoint end end @@ -62,6 +79,39 @@ class Matter_Plugin_Aggregator : Matter_Plugin # no match found, return that the attribute is unsupported end + ############################################################# + # Invoke a command + # + # returns a TLV object if successful, contains the response + # or an `int` to indicate a status + def invoke_request(session, val, ctx) + var TLV = matter.TLV + var cluster = ctx.cluster + var command = ctx.command + + # ==================================================================================================== + if cluster == 0x0003 # ========== Identify 1.2 p.16 ========== + + if command == 0x0000 # ---------- Identify ---------- + # ignore + return true + elif command == 0x0001 # ---------- IdentifyQuery ---------- + # create IdentifyQueryResponse + # ID=1 + # 0=Certificate (octstr) + var iqr = TLV.Matter_TLV_struct() + iqr.add_TLV(0, TLV.U2, 0) # Timeout + ctx.command = 0x00 # IdentifyQueryResponse + return iqr + elif command == 0x0040 # ---------- TriggerEffect ---------- + # ignore + return true + end + + else + return super(self).invoke_request(session, val, ctx) + end + end + end matter.Plugin_Aggregator = Matter_Plugin_Aggregator - \ No newline at end of file diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Device.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Device.be index 411cb2255..8ddf9012b 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Device.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Device.be @@ -119,8 +119,6 @@ class Matter_Plugin_Device : Matter_Plugin return tlv_solo.set(TLV.BOOL, 1) # by default we are reachable elif attribute == 0x0012 # ---------- UniqueID / string 32 max ---------- return tlv_solo.set(TLV.UTF1, tasmota.wifi().find("mac", "")) - else - return super(self).read_attribute(session, ctx, tlv_solo) end else diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be index ae5815ed3..5102dd062 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be @@ -154,6 +154,7 @@ class Matter_Plugin_Root : Matter_Plugin var nocl = TLV.Matter_TLV_array() # NOCs, p.711 var fabs = ctx.fabric_filtered ? [session.get_fabric()] : self.device.sessions.active_fabrics() for loc_fabric: fabs + if loc_fabric.is_marked_for_deletion() continue end # fabric is scheduled for deletion if loc_fabric == nil continue end var nocs = nocl.add_struct(nil) nocs.add_TLV(1, TLV.B2, loc_fabric.get_noc()) # NOC @@ -166,6 +167,7 @@ class Matter_Plugin_Root : Matter_Plugin var fabs = ctx.fabric_filtered ? [session.get_fabric()] : self.device.sessions.active_fabrics() for loc_fabric: fabs if loc_fabric == nil continue end + if loc_fabric.is_marked_for_deletion() continue end # fabric is scheduled for deletion var root_ca_tlv = TLV.parse(loc_fabric.get_ca()) var fab = fabrics.add_struct(nil) # encoding see p.303 fab.add_TLV(1, TLV.B2, root_ca_tlv.findsubval(9)) # RootPublicKey @@ -305,14 +307,20 @@ class Matter_Plugin_Root : Matter_Plugin elif cluster == 0x001D # ========== Descriptor Cluster 9.5 p.453 ========== + # overwrite ClientList + if attribute == 0x0002 # ---------- ClientList / list[cluster-id] ---------- + var pl = TLV.Matter_TLV_array() + # from connectedhome reference implementation + pl.add_TLV(nil, TLV.U2, 0x001F) # Access Control Cluster + return pl # overwrite PartsList - if attribute == 0x0003 # ---------- PartsList / list[endpoint-no]---------- + elif attribute == 0x0003 # ---------- PartsList / list[endpoint-no]---------- var pl = TLV.Matter_TLV_array() var eps = self.device.get_active_endpoints(true) var disable_bridge_mode = self.device.disable_bridge_mode for ep: eps # if bridge mode is disabled, don't announce Aggregatore (above 0xFF00) - if !disable_bridge_mode || ep < matter.AGGREGATOR_ENDPOINT + if !disable_bridge_mode || ep != matter.AGGREGATOR_ENDPOINT pl.add_TLV(nil, TLV.U2, ep) # add each endpoint end end @@ -572,6 +580,7 @@ class Matter_Plugin_Root : Matter_Plugin if fab.get_fabric_index() == index # tasmota.log("MTR: removing fabric " + fab.get_fabric_id().copy().reverse().tohex(), 2) # defer actual removal to send a response + fab.mark_for_deletion() # this should not appear anymore in the list tasmota.set_timer(2000, def () self.device.remove_fabric(fab) end) return true # Ok end diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be b/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be index 4a3b704e7..d57ec5869 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be @@ -786,6 +786,7 @@ class Matter_Device if self.plugins_config != nil tasmota.log("MTR: load_config = " + str(self.plugins_config), 3) self.adjust_next_ep() + self.check_config_ep() self.plugins_persist = true end self.plugins_config_remotes = j.find("remotes", {}) @@ -1160,7 +1161,7 @@ class Matter_Device var m = {} # check if we have a light - var endpoint = 1 + var endpoint = matter.START_ENDPOINT var light_present = false import light @@ -1399,6 +1400,25 @@ class Matter_Device self.attribute_updated(matter.AGGREGATOR_ENDPOINT, 0x001D, 0x0003, false) end + ############################################################# + # Check that all ep are valid, i.e. don't collied with root or aggregator + # + def check_config_ep() + # copy into list so we can change the map on the fly + var keys = [] + for k: self.plugins_config.keys() k.push(int(k)) end + for ep: keys + if ep == 0 + tasmota.log("MTR: invalid entry with ep '0'", 2) + self.plugins_config.remove(str(ep)) + elif ep == matter.AGGREGATOR_ENDPOINT + tasmota.log(f"MTR: endpoint {ep} collides wit aggregator, relocating to {self.next_ep}", 2) + self.plugins_config[str(self.next_ep)] = self.plugins_config[str(ep)] + self.plugins_config.remove(str(ep)) + end + end + end + ############################################################# # Adjust next_ep # diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Fabric.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Fabric.h index 046f20836..26a0ed4a2 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Fabric.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Fabric.h @@ -7,11 +7,11 @@ extern const bclass be_class_Matter_Fabric; /******************************************************************** -** Solidified function: counter_group_data_snd_next +** Solidified function: fabric_candidate ********************************************************************/ -be_local_closure(Matter_Fabric_counter_group_data_snd_next, /* name */ +be_local_closure(Matter_Fabric_fabric_candidate, /* name */ be_nested_proto( - 7, /* nstack */ + 4, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -19,51 +19,79 @@ be_local_closure(Matter_Fabric_counter_group_data_snd_next, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[13]) { /* constants */ - /* K0 */ be_nested_str_weak(_counter_group_data_snd_impl), - /* K1 */ be_nested_str_weak(next), - /* K2 */ be_nested_str_weak(tasmota), - /* K3 */ be_nested_str_weak(log), - /* K4 */ be_nested_str_weak(MTR_X3A_X20_X2E_X20_X20_X20_X20_X20_X20_X20_X20_X20_X20Counter_group_data_snd_X3D_X25i), - /* K5 */ be_const_int(3), - /* K6 */ be_nested_str_weak(matter), - /* K7 */ be_nested_str_weak(Counter), - /* K8 */ be_nested_str_weak(is_greater), - /* K9 */ be_nested_str_weak(counter_group_data_snd), - /* K10 */ be_nested_str_weak(_GROUP_SND_INCR), - /* K11 */ be_nested_str_weak(does_persist), - /* K12 */ be_nested_str_weak(save), + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(set_expire_in_seconds), + /* K1 */ be_nested_str_weak(assign_fabric_index), + /* K2 */ be_nested_str_weak(_store), + /* K3 */ be_nested_str_weak(add_fabric), }), - be_str_weak(counter_group_data_snd_next), + be_str_weak(fabric_candidate), &be_const_str_solidified, - ( &(const binstruction[27]) { /* code */ + ( &(const binstruction[10]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x540E0077, // 0001 LDINT R3 120 + 0x7C040400, // 0002 CALL R1 2 + 0x8C040101, // 0003 GETMET R1 R0 K1 + 0x7C040200, // 0004 CALL R1 1 + 0x88040102, // 0005 GETMBR R1 R0 K2 + 0x8C040303, // 0006 GETMET R1 R1 K3 + 0x5C0C0000, // 0007 MOVE R3 R0 + 0x7C040400, // 0008 CALL R1 2 + 0x80000000, // 0009 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_ca +********************************************************************/ +be_local_closure(Matter_Fabric_get_ca, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(root_ca_certificate), + }), + be_str_weak(get_ca), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x7C040200, // 0002 CALL R1 1 - 0xB80A0400, // 0003 GETNGBL R2 K2 - 0x8C080503, // 0004 GETMET R2 R2 K3 - 0x60100018, // 0005 GETGBL R4 G24 - 0x58140004, // 0006 LDCONST R5 K4 - 0x5C180200, // 0007 MOVE R6 R1 - 0x7C100400, // 0008 CALL R4 2 - 0x58140005, // 0009 LDCONST R5 K5 - 0x7C080600, // 000A CALL R2 3 - 0xB80A0C00, // 000B GETNGBL R2 K6 - 0x88080507, // 000C GETMBR R2 R2 K7 - 0x8C080508, // 000D GETMET R2 R2 K8 - 0x5C100200, // 000E MOVE R4 R1 - 0x88140109, // 000F GETMBR R5 R0 K9 - 0x7C080600, // 0010 CALL R2 3 - 0x780A0007, // 0011 JMPF R2 #001A - 0x8808010A, // 0012 GETMBR R2 R0 K10 - 0x00080202, // 0013 ADD R2 R1 R2 - 0x90021202, // 0014 SETMBR R0 K9 R2 - 0x8C08010B, // 0015 GETMET R2 R0 K11 - 0x7C080200, // 0016 CALL R2 1 - 0x780A0001, // 0017 JMPF R2 #001A - 0x8C08010C, // 0018 GETMET R2 R0 K12 - 0x7C080200, // 0019 CALL R2 1 - 0x80040200, // 001A RET 1 R1 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_ipk_epoch_key +********************************************************************/ +be_local_closure(Matter_Fabric_get_ipk_epoch_key, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(ipk_epoch_key), + }), + be_str_weak(get_ipk_epoch_key), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 }) ) ); @@ -112,9 +140,92 @@ be_local_closure(Matter_Fabric_get_ca_pub, /* name */ /******************************************************************** -** Solidified function: get_device_id +** Solidified function: get_ipk_group_key ********************************************************************/ -be_local_closure(Matter_Fabric_get_device_id, /* name */ +be_local_closure(Matter_Fabric_get_ipk_group_key, /* name */ + be_nested_proto( + 10, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str_weak(ipk_epoch_key), + /* K1 */ be_nested_str_weak(fabric_compressed), + /* K2 */ be_nested_str_weak(crypto), + /* K3 */ be_nested_str_weak(HKDF_SHA256), + /* K4 */ be_nested_str_weak(fromstring), + /* K5 */ be_nested_str_weak(_GROUP_KEY), + /* K6 */ be_nested_str_weak(derive), + }), + be_str_weak(get_ipk_group_key), + &be_const_str_solidified, + ( &(const binstruction[25]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x1C040202, // 0002 EQ R1 R1 R2 + 0x74060003, // 0003 JMPT R1 #0008 + 0x88040101, // 0004 GETMBR R1 R0 K1 + 0x4C080000, // 0005 LDNIL R2 + 0x1C040202, // 0006 EQ R1 R1 R2 + 0x78060001, // 0007 JMPF R1 #000A + 0x4C040000, // 0008 LDNIL R1 + 0x80040200, // 0009 RET 1 R1 + 0xA4060400, // 000A IMPORT R1 K2 + 0x8C080303, // 000B GETMET R2 R1 K3 + 0x7C080200, // 000C CALL R2 1 + 0x600C0015, // 000D GETGBL R3 G21 + 0x7C0C0000, // 000E CALL R3 0 + 0x8C0C0704, // 000F GETMET R3 R3 K4 + 0x88140105, // 0010 GETMBR R5 R0 K5 + 0x7C0C0400, // 0011 CALL R3 2 + 0x8C100506, // 0012 GETMET R4 R2 K6 + 0x88180100, // 0013 GETMBR R6 R0 K0 + 0x881C0101, // 0014 GETMBR R7 R0 K1 + 0x5C200600, // 0015 MOVE R8 R3 + 0x5426000F, // 0016 LDINT R9 16 + 0x7C100A00, // 0017 CALL R4 5 + 0x80040800, // 0018 RET 1 R4 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_ca +********************************************************************/ +be_local_closure(Matter_Fabric_set_ca, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(root_ca_certificate), + }), + be_str_weak(set_ca), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_fabric_compressed +********************************************************************/ +be_local_closure(Matter_Fabric_get_fabric_compressed, /* name */ be_nested_proto( 2, /* nstack */ 1, /* argc */ @@ -125,9 +236,9 @@ be_local_closure(Matter_Fabric_get_device_id, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(device_id), + /* K0 */ be_nested_str_weak(fabric_compressed), }), - be_str_weak(get_device_id), + be_str_weak(get_fabric_compressed), &be_const_str_solidified, ( &(const binstruction[ 2]) { /* code */ 0x88040100, // 0000 GETMBR R1 R0 K0 @@ -139,63 +250,26 @@ be_local_closure(Matter_Fabric_get_device_id, /* name */ /******************************************************************** -** Solidified function: add_session +** Solidified function: get_fabric_label ********************************************************************/ -be_local_closure(Matter_Fabric_add_session, /* name */ +be_local_closure(Matter_Fabric_get_fabric_label, /* name */ be_nested_proto( - 8, /* nstack */ - 2, /* argc */ + 2, /* nstack */ + 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str_weak(_sessions), - /* K1 */ be_nested_str_weak(find), - /* K2 */ be_nested_str_weak(_MAX_CASE), - /* K3 */ be_nested_str_weak(get_oldest_session), - /* K4 */ be_nested_str_weak(remove), - /* K5 */ be_nested_str_weak(_store), - /* K6 */ be_nested_str_weak(remove_session), - /* K7 */ be_nested_str_weak(push), + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(fabric_label), }), - be_str_weak(add_session), + be_str_weak(get_fabric_label), &be_const_str_solidified, - ( &(const binstruction[32]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x4C0C0000, // 0004 LDNIL R3 - 0x1C080403, // 0005 EQ R2 R2 R3 - 0x780A0017, // 0006 JMPF R2 #001F - 0x6008000C, // 0007 GETGBL R2 G12 - 0x880C0100, // 0008 GETMBR R3 R0 K0 - 0x7C080200, // 0009 CALL R2 1 - 0x880C0102, // 000A GETMBR R3 R0 K2 - 0x28080403, // 000B GE R2 R2 R3 - 0x780A000D, // 000C JMPF R2 #001B - 0x8C080103, // 000D GETMET R2 R0 K3 - 0x7C080200, // 000E CALL R2 1 - 0x880C0100, // 000F GETMBR R3 R0 K0 - 0x8C0C0704, // 0010 GETMET R3 R3 K4 - 0x88140100, // 0011 GETMBR R5 R0 K0 - 0x8C140B01, // 0012 GETMET R5 R5 K1 - 0x5C1C0400, // 0013 MOVE R7 R2 - 0x7C140400, // 0014 CALL R5 2 - 0x7C0C0400, // 0015 CALL R3 2 - 0x880C0105, // 0016 GETMBR R3 R0 K5 - 0x8C0C0706, // 0017 GETMET R3 R3 K6 - 0x5C140400, // 0018 MOVE R5 R2 - 0x7C0C0400, // 0019 CALL R3 2 - 0x7001FFEB, // 001A JMP #0007 - 0x88080100, // 001B GETMBR R2 R0 K0 - 0x8C080507, // 001C GETMET R2 R2 K7 - 0x5C100200, // 001D MOVE R4 R1 - 0x7C080400, // 001E CALL R2 2 - 0x80000000, // 001F RET 0 + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 }) ) ); @@ -203,9 +277,214 @@ be_local_closure(Matter_Fabric_add_session, /* name */ /******************************************************************** -** Solidified function: get_oldest_session +** Solidified function: assign_fabric_index ********************************************************************/ -be_local_closure(Matter_Fabric_get_oldest_session, /* name */ +be_local_closure(Matter_Fabric_assign_fabric_index, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(get_fabric_index), + /* K1 */ be_nested_str_weak(set_fabric_index), + /* K2 */ be_nested_str_weak(_store), + /* K3 */ be_nested_str_weak(next_fabric_idx), + }), + be_str_weak(assign_fabric_index), + &be_const_str_solidified, + ( &(const binstruction[11]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x4C080000, // 0002 LDNIL R2 + 0x1C040202, // 0003 EQ R1 R1 R2 + 0x78060004, // 0004 JMPF R1 #000A + 0x8C040101, // 0005 GETMET R1 R0 K1 + 0x880C0102, // 0006 GETMBR R3 R0 K2 + 0x8C0C0703, // 0007 GETMET R3 R3 K3 + 0x7C0C0200, // 0008 CALL R3 1 + 0x7C040400, // 0009 CALL R1 2 + 0x80000000, // 000A RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_noc +********************************************************************/ +be_local_closure(Matter_Fabric_get_noc, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(noc), + }), + be_str_weak(get_noc), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: log_new_fabric +********************************************************************/ +be_local_closure(Matter_Fabric_log_new_fabric, /* name */ + be_nested_proto( + 8, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(log), + /* K2 */ be_nested_str_weak(MTR_X3A_X20_X2BFabric_X20_X20_X20_X20fab_X3D_X27_X25s_X27_X20vendorid_X3D_X25s), + /* K3 */ be_nested_str_weak(get_fabric_id), + /* K4 */ be_nested_str_weak(copy), + /* K5 */ be_nested_str_weak(reverse), + /* K6 */ be_nested_str_weak(tohex), + /* K7 */ be_nested_str_weak(get_admin_vendor_name), + /* K8 */ be_const_int(3), + }), + be_str_weak(log_new_fabric), + &be_const_str_solidified, + ( &(const binstruction[18]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x600C0018, // 0002 GETGBL R3 G24 + 0x58100002, // 0003 LDCONST R4 K2 + 0x8C140103, // 0004 GETMET R5 R0 K3 + 0x7C140200, // 0005 CALL R5 1 + 0x8C140B04, // 0006 GETMET R5 R5 K4 + 0x7C140200, // 0007 CALL R5 1 + 0x8C140B05, // 0008 GETMET R5 R5 K5 + 0x7C140200, // 0009 CALL R5 1 + 0x8C140B06, // 000A GETMET R5 R5 K6 + 0x7C140200, // 000B CALL R5 1 + 0x8C180107, // 000C GETMET R6 R0 K7 + 0x7C180200, // 000D CALL R6 1 + 0x7C0C0600, // 000E CALL R3 3 + 0x58100008, // 000F LDCONST R4 K8 + 0x7C040600, // 0010 CALL R1 3 + 0x80000000, // 0011 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_pk +********************************************************************/ +be_local_closure(Matter_Fabric_set_pk, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(no_private_key), + }), + be_str_weak(set_pk), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: mark_for_deletion +********************************************************************/ +be_local_closure(Matter_Fabric_mark_for_deletion, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(deleted), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(rtc_utc), + }), + be_str_weak(mark_for_deletion), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0xB8060200, // 0000 GETNGBL R1 K1 + 0x8C040302, // 0001 GETMET R1 R1 K2 + 0x7C040200, // 0002 CALL R1 1 + 0x90020001, // 0003 SETMBR R0 K0 R1 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: is_marked_for_deletion +********************************************************************/ +be_local_closure(Matter_Fabric_is_marked_for_deletion, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(deleted), + }), + be_str_weak(is_marked_for_deletion), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x20040202, // 0002 NE R1 R1 R2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: fabric_completed +********************************************************************/ +be_local_closure(Matter_Fabric_fabric_completed, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -215,16 +494,28 @@ be_local_closure(Matter_Fabric_get_oldest_session, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(get_old_recent_session), + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(set_no_expiration), + /* K1 */ be_nested_str_weak(set_persist), + /* K2 */ be_nested_str_weak(assign_fabric_index), + /* K3 */ be_nested_str_weak(_store), + /* K4 */ be_nested_str_weak(add_fabric), }), - be_str_weak(get_oldest_session), + be_str_weak(fabric_completed), &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ + ( &(const binstruction[12]) { /* code */ 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x500C0200, // 0001 LDBOOL R3 1 0 - 0x7C040400, // 0002 CALL R1 2 - 0x80040200, // 0003 RET 1 R1 + 0x7C040200, // 0001 CALL R1 1 + 0x8C040101, // 0002 GETMET R1 R0 K1 + 0x500C0200, // 0003 LDBOOL R3 1 0 + 0x7C040400, // 0004 CALL R1 2 + 0x8C040102, // 0005 GETMET R1 R0 K2 + 0x7C040200, // 0006 CALL R1 1 + 0x88040103, // 0007 GETMBR R1 R0 K3 + 0x8C040304, // 0008 GETMET R1 R1 K4 + 0x5C0C0000, // 0009 MOVE R3 R0 + 0x7C040400, // 000A CALL R1 2 + 0x80000000, // 000B RET 0 }) ) ); @@ -232,117 +523,101 @@ be_local_closure(Matter_Fabric_get_oldest_session, /* name */ /******************************************************************** -** Solidified function: fromjson +** Solidified function: before_remove ********************************************************************/ -be_local_closure(Matter_Fabric_fromjson, /* name */ +be_local_closure(Matter_Fabric_before_remove, /* name */ be_nested_proto( - 16, /* nstack */ - 2, /* argc */ - 4, /* varg */ + 7, /* nstack */ + 1, /* argc */ + 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[18]) { /* constants */ - /* K0 */ be_const_class(be_class_Matter_Fabric), - /* K1 */ be_nested_str_weak(string), - /* K2 */ be_nested_str_weak(introspect), - /* K3 */ be_nested_str_weak(matter), - /* K4 */ be_nested_str_weak(Fabric), - /* K5 */ be_nested_str_weak(keys), - /* K6 */ be_const_int(0), - /* K7 */ be_nested_str_weak(_), - /* K8 */ be_nested_str_weak(find), - /* K9 */ be_nested_str_weak(0x), - /* K10 */ be_nested_str_weak(set), - /* K11 */ be_nested_str_weak(fromhex), - /* K12 */ be_const_int(2), - /* K13 */ be_const_int(2147483647), - /* K14 */ be_nested_str_weak(_X24_X24), - /* K15 */ be_nested_str_weak(fromb64), - /* K16 */ be_nested_str_weak(stop_iteration), - /* K17 */ be_nested_str_weak(hydrate_post), + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(log), + /* K2 */ be_nested_str_weak(MTR_X3A_X20_X2DFabric_X20_X20_X20_X20fab_X3D_X27_X25s_X27_X20_X28removed_X29), + /* K3 */ be_nested_str_weak(get_fabric_id), + /* K4 */ be_nested_str_weak(copy), + /* K5 */ be_nested_str_weak(reverse), + /* K6 */ be_nested_str_weak(tohex), + /* K7 */ be_const_int(3), }), - be_str_weak(fromjson), + be_str_weak(before_remove), &be_const_str_solidified, - ( &(const binstruction[76]) { /* code */ - 0x58080000, // 0000 LDCONST R2 K0 - 0xA40E0200, // 0001 IMPORT R3 K1 - 0xA4120400, // 0002 IMPORT R4 K2 - 0xB8160600, // 0003 GETNGBL R5 K3 - 0x8C140B04, // 0004 GETMET R5 R5 K4 - 0x5C1C0000, // 0005 MOVE R7 R0 - 0x7C140400, // 0006 CALL R5 2 - 0x60180010, // 0007 GETGBL R6 G16 - 0x8C1C0305, // 0008 GETMET R7 R1 K5 - 0x7C1C0200, // 0009 CALL R7 1 - 0x7C180200, // 000A CALL R6 1 - 0xA8020039, // 000B EXBLK 0 #0046 - 0x5C1C0C00, // 000C MOVE R7 R6 - 0x7C1C0000, // 000D CALL R7 0 - 0x94200F06, // 000E GETIDX R8 R7 K6 - 0x1C201107, // 000F EQ R8 R8 K7 - 0x78220000, // 0010 JMPF R8 #0012 - 0x7001FFF9, // 0011 JMP #000C - 0x94200207, // 0012 GETIDX R8 R1 R7 - 0x60240004, // 0013 GETGBL R9 G4 - 0x5C281000, // 0014 MOVE R10 R8 - 0x7C240200, // 0015 CALL R9 1 - 0x1C241301, // 0016 EQ R9 R9 K1 - 0x78260027, // 0017 JMPF R9 #0040 - 0x8C240708, // 0018 GETMET R9 R3 K8 - 0x5C2C1000, // 0019 MOVE R11 R8 - 0x58300009, // 001A LDCONST R12 K9 - 0x7C240600, // 001B CALL R9 3 - 0x1C241306, // 001C EQ R9 R9 K6 - 0x7826000A, // 001D JMPF R9 #0029 - 0x8C24090A, // 001E GETMET R9 R4 K10 - 0x5C2C0A00, // 001F MOVE R11 R5 - 0x5C300E00, // 0020 MOVE R12 R7 - 0x60340015, // 0021 GETGBL R13 G21 - 0x7C340000, // 0022 CALL R13 0 - 0x8C341B0B, // 0023 GETMET R13 R13 K11 - 0x403E190D, // 0024 CONNECT R15 K12 K13 - 0x943C100F, // 0025 GETIDX R15 R8 R15 - 0x7C340400, // 0026 CALL R13 2 - 0x7C240800, // 0027 CALL R9 4 - 0x70020015, // 0028 JMP #003F - 0x8C240708, // 0029 GETMET R9 R3 K8 - 0x5C2C1000, // 002A MOVE R11 R8 - 0x5830000E, // 002B LDCONST R12 K14 - 0x7C240600, // 002C CALL R9 3 - 0x1C241306, // 002D EQ R9 R9 K6 - 0x7826000A, // 002E JMPF R9 #003A - 0x8C24090A, // 002F GETMET R9 R4 K10 - 0x5C2C0A00, // 0030 MOVE R11 R5 - 0x5C300E00, // 0031 MOVE R12 R7 - 0x60340015, // 0032 GETGBL R13 G21 - 0x7C340000, // 0033 CALL R13 0 - 0x8C341B0F, // 0034 GETMET R13 R13 K15 - 0x403E190D, // 0035 CONNECT R15 K12 K13 - 0x943C100F, // 0036 GETIDX R15 R8 R15 - 0x7C340400, // 0037 CALL R13 2 - 0x7C240800, // 0038 CALL R9 4 - 0x70020004, // 0039 JMP #003F - 0x8C24090A, // 003A GETMET R9 R4 K10 - 0x5C2C0A00, // 003B MOVE R11 R5 - 0x5C300E00, // 003C MOVE R12 R7 - 0x5C341000, // 003D MOVE R13 R8 - 0x7C240800, // 003E CALL R9 4 - 0x70020004, // 003F JMP #0045 - 0x8C24090A, // 0040 GETMET R9 R4 K10 - 0x5C2C0A00, // 0041 MOVE R11 R5 - 0x5C300E00, // 0042 MOVE R12 R7 - 0x5C341000, // 0043 MOVE R13 R8 - 0x7C240800, // 0044 CALL R9 4 - 0x7001FFC5, // 0045 JMP #000C - 0x58180010, // 0046 LDCONST R6 K16 - 0xAC180200, // 0047 CATCH R6 1 0 - 0xB0080000, // 0048 RAISE 2 R0 R0 - 0x8C180B11, // 0049 GETMET R6 R5 K17 - 0x7C180200, // 004A CALL R6 1 - 0x80040A00, // 004B RET 1 R5 + ( &(const binstruction[16]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x600C0018, // 0002 GETGBL R3 G24 + 0x58100002, // 0003 LDCONST R4 K2 + 0x8C140103, // 0004 GETMET R5 R0 K3 + 0x7C140200, // 0005 CALL R5 1 + 0x8C140B04, // 0006 GETMET R5 R5 K4 + 0x7C140200, // 0007 CALL R5 1 + 0x8C140B05, // 0008 GETMET R5 R5 K5 + 0x7C140200, // 0009 CALL R5 1 + 0x8C140B06, // 000A GETMET R5 R5 K6 + 0x7C140200, // 000B CALL R5 1 + 0x7C0C0400, // 000C CALL R3 2 + 0x58100007, // 000D LDCONST R4 K7 + 0x7C040600, // 000E CALL R1 3 + 0x80000000, // 000F RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_admin_vendor +********************************************************************/ +be_local_closure(Matter_Fabric_get_admin_vendor, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(admin_vendor), + }), + be_str_weak(get_admin_vendor), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_icac +********************************************************************/ +be_local_closure(Matter_Fabric_get_icac, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(icac), + }), + be_str_weak(get_icac), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 }) ) ); @@ -450,9 +725,67 @@ be_local_closure(Matter_Fabric_init, /* name */ /******************************************************************** -** Solidified function: fabric_completed +** Solidified function: get_old_recent_session ********************************************************************/ -be_local_closure(Matter_Fabric_fabric_completed, /* name */ +be_local_closure(Matter_Fabric_get_old_recent_session, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(_sessions), + /* K1 */ be_const_int(0), + /* K2 */ be_nested_str_weak(last_used), + /* K3 */ be_const_int(1), + }), + be_str_weak(get_old_recent_session), + &be_const_str_solidified, + ( &(const binstruction[30]) { /* code */ + 0x6008000C, // 0000 GETGBL R2 G12 + 0x880C0100, // 0001 GETMBR R3 R0 K0 + 0x7C080200, // 0002 CALL R2 1 + 0x1C080501, // 0003 EQ R2 R2 K1 + 0x780A0001, // 0004 JMPF R2 #0007 + 0x4C080000, // 0005 LDNIL R2 + 0x80040400, // 0006 RET 1 R2 + 0x88080100, // 0007 GETMBR R2 R0 K0 + 0x94080501, // 0008 GETIDX R2 R2 K1 + 0x880C0502, // 0009 GETMBR R3 R2 K2 + 0x58100003, // 000A LDCONST R4 K3 + 0x6014000C, // 000B GETGBL R5 G12 + 0x88180100, // 000C GETMBR R6 R0 K0 + 0x7C140200, // 000D CALL R5 1 + 0x14140805, // 000E LT R5 R4 R5 + 0x7816000C, // 000F JMPF R5 #001D + 0x88140100, // 0010 GETMBR R5 R0 K0 + 0x94140A04, // 0011 GETIDX R5 R5 R4 + 0x88140B02, // 0012 GETMBR R5 R5 K2 + 0x78060001, // 0013 JMPF R1 #0016 + 0x14180A03, // 0014 LT R6 R5 R3 + 0x70020000, // 0015 JMP #0017 + 0x24180A03, // 0016 GT R6 R5 R3 + 0x781A0002, // 0017 JMPF R6 #001B + 0x88180100, // 0018 GETMBR R6 R0 K0 + 0x94080C04, // 0019 GETIDX R2 R6 R4 + 0x5C0C0A00, // 001A MOVE R3 R5 + 0x00100903, // 001B ADD R4 R4 K3 + 0x7001FFED, // 001C JMP #000B + 0x80040400, // 001D RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_newest_session +********************************************************************/ +be_local_closure(Matter_Fabric_get_newest_session, /* name */ be_nested_proto( 4, /* nstack */ 1, /* argc */ @@ -462,28 +795,43 @@ be_local_closure(Matter_Fabric_fabric_completed, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(set_no_expiration), - /* K1 */ be_nested_str_weak(set_persist), - /* K2 */ be_nested_str_weak(assign_fabric_index), - /* K3 */ be_nested_str_weak(_store), - /* K4 */ be_nested_str_weak(add_fabric), + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(get_old_recent_session), }), - be_str_weak(fabric_completed), + be_str_weak(get_newest_session), &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ + ( &(const binstruction[ 4]) { /* code */ 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0x8C040101, // 0002 GETMET R1 R0 K1 - 0x500C0200, // 0003 LDBOOL R3 1 0 - 0x7C040400, // 0004 CALL R1 2 - 0x8C040102, // 0005 GETMET R1 R0 K2 - 0x7C040200, // 0006 CALL R1 1 - 0x88040103, // 0007 GETMBR R1 R0 K3 - 0x8C040304, // 0008 GETMET R1 R1 K4 - 0x5C0C0000, // 0009 MOVE R3 R0 - 0x7C040400, // 000A CALL R1 2 - 0x80000000, // 000B RET 0 + 0x500C0000, // 0001 LDBOOL R3 0 0 + 0x7C040400, // 0002 CALL R1 2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_pk +********************************************************************/ +be_local_closure(Matter_Fabric_get_pk, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(no_private_key), + }), + be_str_weak(get_pk), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 }) ) ); @@ -555,9 +903,102 @@ be_local_closure(Matter_Fabric_counter_group_ctrl_snd_next, /* name */ /******************************************************************** -** Solidified function: get_ipk_epoch_key +** Solidified function: set_noc_icac ********************************************************************/ -be_local_closure(Matter_Fabric_get_ipk_epoch_key, /* name */ +be_local_closure(Matter_Fabric_set_noc_icac, /* name */ + be_nested_proto( + 3, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(noc), + /* K1 */ be_nested_str_weak(icac), + }), + be_str_weak(set_noc_icac), + &be_const_str_solidified, + ( &(const binstruction[ 3]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_session +********************************************************************/ +be_local_closure(Matter_Fabric_add_session, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_str_weak(_sessions), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(_MAX_CASE), + /* K3 */ be_nested_str_weak(get_oldest_session), + /* K4 */ be_nested_str_weak(remove), + /* K5 */ be_nested_str_weak(_store), + /* K6 */ be_nested_str_weak(remove_session), + /* K7 */ be_nested_str_weak(push), + }), + be_str_weak(add_session), + &be_const_str_solidified, + ( &(const binstruction[32]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x4C0C0000, // 0004 LDNIL R3 + 0x1C080403, // 0005 EQ R2 R2 R3 + 0x780A0017, // 0006 JMPF R2 #001F + 0x6008000C, // 0007 GETGBL R2 G12 + 0x880C0100, // 0008 GETMBR R3 R0 K0 + 0x7C080200, // 0009 CALL R2 1 + 0x880C0102, // 000A GETMBR R3 R0 K2 + 0x28080403, // 000B GE R2 R2 R3 + 0x780A000D, // 000C JMPF R2 #001B + 0x8C080103, // 000D GETMET R2 R0 K3 + 0x7C080200, // 000E CALL R2 1 + 0x880C0100, // 000F GETMBR R3 R0 K0 + 0x8C0C0704, // 0010 GETMET R3 R3 K4 + 0x88140100, // 0011 GETMBR R5 R0 K0 + 0x8C140B01, // 0012 GETMET R5 R5 K1 + 0x5C1C0400, // 0013 MOVE R7 R2 + 0x7C140400, // 0014 CALL R5 2 + 0x7C0C0400, // 0015 CALL R3 2 + 0x880C0105, // 0016 GETMBR R3 R0 K5 + 0x8C0C0706, // 0017 GETMET R3 R3 K6 + 0x5C140400, // 0018 MOVE R5 R2 + 0x7C0C0400, // 0019 CALL R3 2 + 0x7001FFEB, // 001A JMP #0007 + 0x88080100, // 001B GETMBR R2 R0 K0 + 0x8C080507, // 001C GETMET R2 R2 K7 + 0x5C100200, // 001D MOVE R4 R1 + 0x7C080400, // 001E CALL R2 2 + 0x80000000, // 001F RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_admin_subject +********************************************************************/ +be_local_closure(Matter_Fabric_get_admin_subject, /* name */ be_nested_proto( 2, /* nstack */ 1, /* argc */ @@ -568,9 +1009,9 @@ be_local_closure(Matter_Fabric_get_ipk_epoch_key, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(ipk_epoch_key), + /* K0 */ be_nested_str_weak(admin_subject), }), - be_str_weak(get_ipk_epoch_key), + be_str_weak(get_admin_subject), &be_const_str_solidified, ( &(const binstruction[ 2]) { /* code */ 0x88040100, // 0000 GETMBR R1 R0 K0 @@ -581,6 +1022,140 @@ be_local_closure(Matter_Fabric_get_ipk_epoch_key, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: counter_group_data_snd_next +********************************************************************/ +be_local_closure(Matter_Fabric_counter_group_data_snd_next, /* name */ + be_nested_proto( + 7, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[13]) { /* constants */ + /* K0 */ be_nested_str_weak(_counter_group_data_snd_impl), + /* K1 */ be_nested_str_weak(next), + /* K2 */ be_nested_str_weak(tasmota), + /* K3 */ be_nested_str_weak(log), + /* K4 */ be_nested_str_weak(MTR_X3A_X20_X2E_X20_X20_X20_X20_X20_X20_X20_X20_X20_X20Counter_group_data_snd_X3D_X25i), + /* K5 */ be_const_int(3), + /* K6 */ be_nested_str_weak(matter), + /* K7 */ be_nested_str_weak(Counter), + /* K8 */ be_nested_str_weak(is_greater), + /* K9 */ be_nested_str_weak(counter_group_data_snd), + /* K10 */ be_nested_str_weak(_GROUP_SND_INCR), + /* K11 */ be_nested_str_weak(does_persist), + /* K12 */ be_nested_str_weak(save), + }), + be_str_weak(counter_group_data_snd_next), + &be_const_str_solidified, + ( &(const binstruction[27]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0xB80A0400, // 0003 GETNGBL R2 K2 + 0x8C080503, // 0004 GETMET R2 R2 K3 + 0x60100018, // 0005 GETGBL R4 G24 + 0x58140004, // 0006 LDCONST R5 K4 + 0x5C180200, // 0007 MOVE R6 R1 + 0x7C100400, // 0008 CALL R4 2 + 0x58140005, // 0009 LDCONST R5 K5 + 0x7C080600, // 000A CALL R2 3 + 0xB80A0C00, // 000B GETNGBL R2 K6 + 0x88080507, // 000C GETMBR R2 R2 K7 + 0x8C080508, // 000D GETMET R2 R2 K8 + 0x5C100200, // 000E MOVE R4 R1 + 0x88140109, // 000F GETMBR R5 R0 K9 + 0x7C080600, // 0010 CALL R2 3 + 0x780A0007, // 0011 JMPF R2 #001A + 0x8808010A, // 0012 GETMBR R2 R0 K10 + 0x00080202, // 0013 ADD R2 R1 R2 + 0x90021202, // 0014 SETMBR R0 K9 R2 + 0x8C08010B, // 0015 GETMET R2 R0 K11 + 0x7C080200, // 0016 CALL R2 1 + 0x780A0001, // 0017 JMPF R2 #001A + 0x8C08010C, // 0018 GETMET R2 R0 K12 + 0x7C080200, // 0019 CALL R2 1 + 0x80040200, // 001A RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_fabric_device +********************************************************************/ +be_local_closure(Matter_Fabric_set_fabric_device, /* name */ + be_nested_proto( + 7, /* nstack */ + 5, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(fabric_id), + /* K1 */ be_nested_str_weak(device_id), + /* K2 */ be_nested_str_weak(fabric_compressed), + /* K3 */ be_nested_str_weak(fabric_parent), + /* K4 */ be_nested_str_weak(get_fabric_index), + }), + be_str_weak(set_fabric_device), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x90020403, // 0002 SETMBR R0 K2 R3 + 0x4C140000, // 0003 LDNIL R5 + 0x20140805, // 0004 NE R5 R4 R5 + 0x78160002, // 0005 JMPF R5 #0009 + 0x8C140904, // 0006 GETMET R5 R4 K4 + 0x7C140200, // 0007 CALL R5 1 + 0x70020000, // 0008 JMP #000A + 0x4C140000, // 0009 LDNIL R5 + 0x90020605, // 000A SETMBR R0 K3 R5 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_admin_subject_vendor +********************************************************************/ +be_local_closure(Matter_Fabric_set_admin_subject_vendor, /* name */ + be_nested_proto( + 3, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(admin_subject), + /* K1 */ be_nested_str_weak(admin_vendor), + }), + be_str_weak(set_admin_subject_vendor), + &be_const_str_solidified, + ( &(const binstruction[ 3]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: tojson ********************************************************************/ @@ -751,394 +1326,6 @@ be_local_closure(Matter_Fabric_tojson, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: assign_fabric_index -********************************************************************/ -be_local_closure(Matter_Fabric_assign_fabric_index, /* name */ - be_nested_proto( - 5, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(get_fabric_index), - /* K1 */ be_nested_str_weak(set_fabric_index), - /* K2 */ be_nested_str_weak(_store), - /* K3 */ be_nested_str_weak(next_fabric_idx), - }), - be_str_weak(assign_fabric_index), - &be_const_str_solidified, - ( &(const binstruction[11]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0x4C080000, // 0002 LDNIL R2 - 0x1C040202, // 0003 EQ R1 R1 R2 - 0x78060004, // 0004 JMPF R1 #000A - 0x8C040101, // 0005 GETMET R1 R0 K1 - 0x880C0102, // 0006 GETMBR R3 R0 K2 - 0x8C0C0703, // 0007 GETMET R3 R3 K3 - 0x7C0C0200, // 0008 CALL R3 1 - 0x7C040400, // 0009 CALL R1 2 - 0x80000000, // 000A RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_admin_subject -********************************************************************/ -be_local_closure(Matter_Fabric_get_admin_subject, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(admin_subject), - }), - be_str_weak(get_admin_subject), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_fabric_compressed -********************************************************************/ -be_local_closure(Matter_Fabric_get_fabric_compressed, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(fabric_compressed), - }), - be_str_weak(get_fabric_compressed), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: fabric_candidate -********************************************************************/ -be_local_closure(Matter_Fabric_fabric_candidate, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(set_expire_in_seconds), - /* K1 */ be_nested_str_weak(assign_fabric_index), - /* K2 */ be_nested_str_weak(_store), - /* K3 */ be_nested_str_weak(add_fabric), - }), - be_str_weak(fabric_candidate), - &be_const_str_solidified, - ( &(const binstruction[10]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x540E0077, // 0001 LDINT R3 120 - 0x7C040400, // 0002 CALL R1 2 - 0x8C040101, // 0003 GETMET R1 R0 K1 - 0x7C040200, // 0004 CALL R1 1 - 0x88040102, // 0005 GETMBR R1 R0 K2 - 0x8C040303, // 0006 GETMET R1 R1 K3 - 0x5C0C0000, // 0007 MOVE R3 R0 - 0x7C040400, // 0008 CALL R1 2 - 0x80000000, // 0009 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_fabric_label -********************************************************************/ -be_local_closure(Matter_Fabric_get_fabric_label, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(fabric_label), - }), - be_str_weak(get_fabric_label), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_noc_icac -********************************************************************/ -be_local_closure(Matter_Fabric_set_noc_icac, /* name */ - be_nested_proto( - 3, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(noc), - /* K1 */ be_nested_str_weak(icac), - }), - be_str_weak(set_noc_icac), - &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x80000000, // 0002 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_newest_session -********************************************************************/ -be_local_closure(Matter_Fabric_get_newest_session, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(get_old_recent_session), - }), - be_str_weak(get_newest_session), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x500C0000, // 0001 LDBOOL R3 0 0 - 0x7C040400, // 0002 CALL R1 2 - 0x80040200, // 0003 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: before_remove -********************************************************************/ -be_local_closure(Matter_Fabric_before_remove, /* name */ - be_nested_proto( - 7, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(log), - /* K2 */ be_nested_str_weak(MTR_X3A_X20_X2DFabric_X20_X20_X20_X20fab_X3D_X27_X25s_X27_X20_X28removed_X29), - /* K3 */ be_nested_str_weak(get_fabric_id), - /* K4 */ be_nested_str_weak(copy), - /* K5 */ be_nested_str_weak(reverse), - /* K6 */ be_nested_str_weak(tohex), - /* K7 */ be_const_int(3), - }), - be_str_weak(before_remove), - &be_const_str_solidified, - ( &(const binstruction[16]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x600C0018, // 0002 GETGBL R3 G24 - 0x58100002, // 0003 LDCONST R4 K2 - 0x8C140103, // 0004 GETMET R5 R0 K3 - 0x7C140200, // 0005 CALL R5 1 - 0x8C140B04, // 0006 GETMET R5 R5 K4 - 0x7C140200, // 0007 CALL R5 1 - 0x8C140B05, // 0008 GETMET R5 R5 K5 - 0x7C140200, // 0009 CALL R5 1 - 0x8C140B06, // 000A GETMET R5 R5 K6 - 0x7C140200, // 000B CALL R5 1 - 0x7C0C0400, // 000C CALL R3 2 - 0x58100007, // 000D LDCONST R4 K7 - 0x7C040600, // 000E CALL R1 3 - 0x80000000, // 000F RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_fabric_device -********************************************************************/ -be_local_closure(Matter_Fabric_set_fabric_device, /* name */ - be_nested_proto( - 7, /* nstack */ - 5, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(fabric_id), - /* K1 */ be_nested_str_weak(device_id), - /* K2 */ be_nested_str_weak(fabric_compressed), - /* K3 */ be_nested_str_weak(fabric_parent), - /* K4 */ be_nested_str_weak(get_fabric_index), - }), - be_str_weak(set_fabric_device), - &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x90020403, // 0002 SETMBR R0 K2 R3 - 0x4C140000, // 0003 LDNIL R5 - 0x20140805, // 0004 NE R5 R4 R5 - 0x78160002, // 0005 JMPF R5 #0009 - 0x8C140904, // 0006 GETMET R5 R4 K4 - 0x7C140200, // 0007 CALL R5 1 - 0x70020000, // 0008 JMP #000A - 0x4C140000, // 0009 LDNIL R5 - 0x90020605, // 000A SETMBR R0 K3 R5 - 0x80000000, // 000B RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_ipk_epoch_key -********************************************************************/ -be_local_closure(Matter_Fabric_set_ipk_epoch_key, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(ipk_epoch_key), - }), - be_str_weak(set_ipk_epoch_key), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_ipk_group_key -********************************************************************/ -be_local_closure(Matter_Fabric_get_ipk_group_key, /* name */ - be_nested_proto( - 10, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_nested_str_weak(ipk_epoch_key), - /* K1 */ be_nested_str_weak(fabric_compressed), - /* K2 */ be_nested_str_weak(crypto), - /* K3 */ be_nested_str_weak(HKDF_SHA256), - /* K4 */ be_nested_str_weak(fromstring), - /* K5 */ be_nested_str_weak(_GROUP_KEY), - /* K6 */ be_nested_str_weak(derive), - }), - be_str_weak(get_ipk_group_key), - &be_const_str_solidified, - ( &(const binstruction[25]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x4C080000, // 0001 LDNIL R2 - 0x1C040202, // 0002 EQ R1 R1 R2 - 0x74060003, // 0003 JMPT R1 #0008 - 0x88040101, // 0004 GETMBR R1 R0 K1 - 0x4C080000, // 0005 LDNIL R2 - 0x1C040202, // 0006 EQ R1 R1 R2 - 0x78060001, // 0007 JMPF R1 #000A - 0x4C040000, // 0008 LDNIL R1 - 0x80040200, // 0009 RET 1 R1 - 0xA4060400, // 000A IMPORT R1 K2 - 0x8C080303, // 000B GETMET R2 R1 K3 - 0x7C080200, // 000C CALL R2 1 - 0x600C0015, // 000D GETGBL R3 G21 - 0x7C0C0000, // 000E CALL R3 0 - 0x8C0C0704, // 000F GETMET R3 R3 K4 - 0x88140105, // 0010 GETMBR R5 R0 K5 - 0x7C0C0400, // 0011 CALL R3 2 - 0x8C100506, // 0012 GETMET R4 R2 K6 - 0x88180100, // 0013 GETMBR R6 R0 K0 - 0x881C0101, // 0014 GETMBR R7 R0 K1 - 0x5C200600, // 0015 MOVE R8 R3 - 0x5426000F, // 0016 LDINT R9 16 - 0x7C100A00, // 0017 CALL R4 5 - 0x80040800, // 0018 RET 1 R4 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: hydrate_post ********************************************************************/ @@ -1186,6 +1373,234 @@ be_local_closure(Matter_Fabric_hydrate_post, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: get_oldest_session +********************************************************************/ +be_local_closure(Matter_Fabric_get_oldest_session, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(get_old_recent_session), + }), + be_str_weak(get_oldest_session), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x500C0200, // 0001 LDBOOL R3 1 0 + 0x7C040400, // 0002 CALL R1 2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_device_id +********************************************************************/ +be_local_closure(Matter_Fabric_get_device_id, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(device_id), + }), + be_str_weak(get_device_id), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_ipk_epoch_key +********************************************************************/ +be_local_closure(Matter_Fabric_set_ipk_epoch_key, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(ipk_epoch_key), + }), + be_str_weak(set_ipk_epoch_key), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: fromjson +********************************************************************/ +be_local_closure(Matter_Fabric_fromjson, /* name */ + be_nested_proto( + 16, /* nstack */ + 2, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[18]) { /* constants */ + /* K0 */ be_const_class(be_class_Matter_Fabric), + /* K1 */ be_nested_str_weak(string), + /* K2 */ be_nested_str_weak(introspect), + /* K3 */ be_nested_str_weak(matter), + /* K4 */ be_nested_str_weak(Fabric), + /* K5 */ be_nested_str_weak(keys), + /* K6 */ be_const_int(0), + /* K7 */ be_nested_str_weak(_), + /* K8 */ be_nested_str_weak(find), + /* K9 */ be_nested_str_weak(0x), + /* K10 */ be_nested_str_weak(set), + /* K11 */ be_nested_str_weak(fromhex), + /* K12 */ be_const_int(2), + /* K13 */ be_const_int(2147483647), + /* K14 */ be_nested_str_weak(_X24_X24), + /* K15 */ be_nested_str_weak(fromb64), + /* K16 */ be_nested_str_weak(stop_iteration), + /* K17 */ be_nested_str_weak(hydrate_post), + }), + be_str_weak(fromjson), + &be_const_str_solidified, + ( &(const binstruction[76]) { /* code */ + 0x58080000, // 0000 LDCONST R2 K0 + 0xA40E0200, // 0001 IMPORT R3 K1 + 0xA4120400, // 0002 IMPORT R4 K2 + 0xB8160600, // 0003 GETNGBL R5 K3 + 0x8C140B04, // 0004 GETMET R5 R5 K4 + 0x5C1C0000, // 0005 MOVE R7 R0 + 0x7C140400, // 0006 CALL R5 2 + 0x60180010, // 0007 GETGBL R6 G16 + 0x8C1C0305, // 0008 GETMET R7 R1 K5 + 0x7C1C0200, // 0009 CALL R7 1 + 0x7C180200, // 000A CALL R6 1 + 0xA8020039, // 000B EXBLK 0 #0046 + 0x5C1C0C00, // 000C MOVE R7 R6 + 0x7C1C0000, // 000D CALL R7 0 + 0x94200F06, // 000E GETIDX R8 R7 K6 + 0x1C201107, // 000F EQ R8 R8 K7 + 0x78220000, // 0010 JMPF R8 #0012 + 0x7001FFF9, // 0011 JMP #000C + 0x94200207, // 0012 GETIDX R8 R1 R7 + 0x60240004, // 0013 GETGBL R9 G4 + 0x5C281000, // 0014 MOVE R10 R8 + 0x7C240200, // 0015 CALL R9 1 + 0x1C241301, // 0016 EQ R9 R9 K1 + 0x78260027, // 0017 JMPF R9 #0040 + 0x8C240708, // 0018 GETMET R9 R3 K8 + 0x5C2C1000, // 0019 MOVE R11 R8 + 0x58300009, // 001A LDCONST R12 K9 + 0x7C240600, // 001B CALL R9 3 + 0x1C241306, // 001C EQ R9 R9 K6 + 0x7826000A, // 001D JMPF R9 #0029 + 0x8C24090A, // 001E GETMET R9 R4 K10 + 0x5C2C0A00, // 001F MOVE R11 R5 + 0x5C300E00, // 0020 MOVE R12 R7 + 0x60340015, // 0021 GETGBL R13 G21 + 0x7C340000, // 0022 CALL R13 0 + 0x8C341B0B, // 0023 GETMET R13 R13 K11 + 0x403E190D, // 0024 CONNECT R15 K12 K13 + 0x943C100F, // 0025 GETIDX R15 R8 R15 + 0x7C340400, // 0026 CALL R13 2 + 0x7C240800, // 0027 CALL R9 4 + 0x70020015, // 0028 JMP #003F + 0x8C240708, // 0029 GETMET R9 R3 K8 + 0x5C2C1000, // 002A MOVE R11 R8 + 0x5830000E, // 002B LDCONST R12 K14 + 0x7C240600, // 002C CALL R9 3 + 0x1C241306, // 002D EQ R9 R9 K6 + 0x7826000A, // 002E JMPF R9 #003A + 0x8C24090A, // 002F GETMET R9 R4 K10 + 0x5C2C0A00, // 0030 MOVE R11 R5 + 0x5C300E00, // 0031 MOVE R12 R7 + 0x60340015, // 0032 GETGBL R13 G21 + 0x7C340000, // 0033 CALL R13 0 + 0x8C341B0F, // 0034 GETMET R13 R13 K15 + 0x403E190D, // 0035 CONNECT R15 K12 K13 + 0x943C100F, // 0036 GETIDX R15 R8 R15 + 0x7C340400, // 0037 CALL R13 2 + 0x7C240800, // 0038 CALL R9 4 + 0x70020004, // 0039 JMP #003F + 0x8C24090A, // 003A GETMET R9 R4 K10 + 0x5C2C0A00, // 003B MOVE R11 R5 + 0x5C300E00, // 003C MOVE R12 R7 + 0x5C341000, // 003D MOVE R13 R8 + 0x7C240800, // 003E CALL R9 4 + 0x70020004, // 003F JMP #0045 + 0x8C24090A, // 0040 GETMET R9 R4 K10 + 0x5C2C0A00, // 0041 MOVE R11 R5 + 0x5C300E00, // 0042 MOVE R12 R7 + 0x5C341000, // 0043 MOVE R13 R8 + 0x7C240800, // 0044 CALL R9 4 + 0x7001FFC5, // 0045 JMP #000C + 0x58180010, // 0046 LDCONST R6 K16 + 0xAC180200, // 0047 CATCH R6 1 0 + 0xB0080000, // 0048 RAISE 2 R0 R0 + 0x8C180B11, // 0049 GETMET R6 R5 K17 + 0x7C180200, // 004A CALL R6 1 + 0x80040A00, // 004B RET 1 R5 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_fabric_index +********************************************************************/ +be_local_closure(Matter_Fabric_get_fabric_index, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(fabric_index), + }), + be_str_weak(get_fabric_index), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: get_admin_vendor_name ********************************************************************/ @@ -1235,194 +1650,6 @@ be_local_closure(Matter_Fabric_get_admin_vendor_name, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: set_pk -********************************************************************/ -be_local_closure(Matter_Fabric_set_pk, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(no_private_key), - }), - be_str_weak(set_pk), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_icac -********************************************************************/ -be_local_closure(Matter_Fabric_get_icac, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(icac), - }), - be_str_weak(get_icac), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_admin_subject_vendor -********************************************************************/ -be_local_closure(Matter_Fabric_set_admin_subject_vendor, /* name */ - be_nested_proto( - 3, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(admin_subject), - /* K1 */ be_nested_str_weak(admin_vendor), - }), - be_str_weak(set_admin_subject_vendor), - &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x80000000, // 0002 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: log_new_fabric -********************************************************************/ -be_local_closure(Matter_Fabric_log_new_fabric, /* name */ - be_nested_proto( - 8, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(log), - /* K2 */ be_nested_str_weak(MTR_X3A_X20_X2BFabric_X20_X20_X20_X20fab_X3D_X27_X25s_X27_X20vendorid_X3D_X25s), - /* K3 */ be_nested_str_weak(get_fabric_id), - /* K4 */ be_nested_str_weak(copy), - /* K5 */ be_nested_str_weak(reverse), - /* K6 */ be_nested_str_weak(tohex), - /* K7 */ be_nested_str_weak(get_admin_vendor_name), - /* K8 */ be_const_int(3), - }), - be_str_weak(log_new_fabric), - &be_const_str_solidified, - ( &(const binstruction[18]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x600C0018, // 0002 GETGBL R3 G24 - 0x58100002, // 0003 LDCONST R4 K2 - 0x8C140103, // 0004 GETMET R5 R0 K3 - 0x7C140200, // 0005 CALL R5 1 - 0x8C140B04, // 0006 GETMET R5 R5 K4 - 0x7C140200, // 0007 CALL R5 1 - 0x8C140B05, // 0008 GETMET R5 R5 K5 - 0x7C140200, // 0009 CALL R5 1 - 0x8C140B06, // 000A GETMET R5 R5 K6 - 0x7C140200, // 000B CALL R5 1 - 0x8C180107, // 000C GETMET R6 R0 K7 - 0x7C180200, // 000D CALL R6 1 - 0x7C0C0600, // 000E CALL R3 3 - 0x58100008, // 000F LDCONST R4 K8 - 0x7C040600, // 0010 CALL R1 3 - 0x80000000, // 0011 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_pk -********************************************************************/ -be_local_closure(Matter_Fabric_get_pk, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(no_private_key), - }), - be_str_weak(get_pk), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_admin_vendor -********************************************************************/ -be_local_closure(Matter_Fabric_get_admin_vendor, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(admin_vendor), - }), - be_str_weak(get_admin_vendor), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: get_fabric_id ********************************************************************/ @@ -1450,241 +1677,78 @@ be_local_closure(Matter_Fabric_get_fabric_id, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: set_ca -********************************************************************/ -be_local_closure(Matter_Fabric_set_ca, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(root_ca_certificate), - }), - be_str_weak(set_ca), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_noc -********************************************************************/ -be_local_closure(Matter_Fabric_get_noc, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(noc), - }), - be_str_weak(get_noc), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_fabric_index -********************************************************************/ -be_local_closure(Matter_Fabric_get_fabric_index, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(fabric_index), - }), - be_str_weak(get_fabric_index), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_ca -********************************************************************/ -be_local_closure(Matter_Fabric_get_ca, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(root_ca_certificate), - }), - be_str_weak(get_ca), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_old_recent_session -********************************************************************/ -be_local_closure(Matter_Fabric_get_old_recent_session, /* name */ - be_nested_proto( - 7, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(_sessions), - /* K1 */ be_const_int(0), - /* K2 */ be_nested_str_weak(last_used), - /* K3 */ be_const_int(1), - }), - be_str_weak(get_old_recent_session), - &be_const_str_solidified, - ( &(const binstruction[30]) { /* code */ - 0x6008000C, // 0000 GETGBL R2 G12 - 0x880C0100, // 0001 GETMBR R3 R0 K0 - 0x7C080200, // 0002 CALL R2 1 - 0x1C080501, // 0003 EQ R2 R2 K1 - 0x780A0001, // 0004 JMPF R2 #0007 - 0x4C080000, // 0005 LDNIL R2 - 0x80040400, // 0006 RET 1 R2 - 0x88080100, // 0007 GETMBR R2 R0 K0 - 0x94080501, // 0008 GETIDX R2 R2 K1 - 0x880C0502, // 0009 GETMBR R3 R2 K2 - 0x58100003, // 000A LDCONST R4 K3 - 0x6014000C, // 000B GETGBL R5 G12 - 0x88180100, // 000C GETMBR R6 R0 K0 - 0x7C140200, // 000D CALL R5 1 - 0x14140805, // 000E LT R5 R4 R5 - 0x7816000C, // 000F JMPF R5 #001D - 0x88140100, // 0010 GETMBR R5 R0 K0 - 0x94140A04, // 0011 GETIDX R5 R5 R4 - 0x88140B02, // 0012 GETMBR R5 R5 K2 - 0x78060001, // 0013 JMPF R1 #0016 - 0x14180A03, // 0014 LT R6 R5 R3 - 0x70020000, // 0015 JMP #0017 - 0x24180A03, // 0016 GT R6 R5 R3 - 0x781A0002, // 0017 JMPF R6 #001B - 0x88180100, // 0018 GETMBR R6 R0 K0 - 0x94080C04, // 0019 GETIDX R2 R6 R4 - 0x5C0C0A00, // 001A MOVE R3 R5 - 0x00100903, // 001B ADD R4 R4 K3 - 0x7001FFED, // 001C JMP #000B - 0x80040400, // 001D RET 1 R2 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified class: Matter_Fabric ********************************************************************/ extern const bclass be_class_Matter_Expirable; be_local_class(Matter_Fabric, - 20, + 21, &be_class_Matter_Expirable, - be_nested_map(60, + be_nested_map(63, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(fabric_index, -1), be_const_var(2) }, - { be_const_key_weak(fromjson, -1), be_const_static_closure(Matter_Fabric_fromjson_closure) }, - { be_const_key_weak(root_ca_certificate, -1), be_const_var(6) }, - { be_const_key_weak(ipk_epoch_key, -1), be_const_var(9) }, - { be_const_key_weak(get_ca, 34), be_const_closure(Matter_Fabric_get_ca_closure) }, - { be_const_key_weak(noc, -1), be_const_var(7) }, - { be_const_key_weak(get_device_id, -1), be_const_closure(Matter_Fabric_get_device_id_closure) }, - { be_const_key_weak(add_session, -1), be_const_closure(Matter_Fabric_add_session_closure) }, - { be_const_key_weak(get_oldest_session, 50), be_const_closure(Matter_Fabric_get_oldest_session_closure) }, - { be_const_key_weak(fabric_parent, -1), be_const_var(3) }, - { be_const_key_weak(no_private_key, -1), be_const_var(5) }, - { be_const_key_weak(admin_vendor, 1), be_const_var(19) }, - { be_const_key_weak(fabric_id, -1), be_const_var(10) }, - { be_const_key_weak(device_id, -1), be_const_var(12) }, - { be_const_key_weak(set_fabric_index, -1), be_const_closure(Matter_Fabric_set_fabric_index_closure) }, - { be_const_key_weak(init, -1), be_const_closure(Matter_Fabric_init_closure) }, - { be_const_key_weak(counter_group_ctrl_snd, -1), be_const_var(15) }, - { be_const_key_weak(fabric_label, -1), be_const_var(13) }, - { be_const_key_weak(fabric_completed, -1), be_const_closure(Matter_Fabric_fabric_completed_closure) }, - { be_const_key_weak(created, -1), be_const_var(1) }, - { be_const_key_weak(fabric_compressed, -1), be_const_var(11) }, - { be_const_key_weak(icac, -1), be_const_var(8) }, - { be_const_key_weak(_counter_group_data_snd_impl, 2), be_const_var(16) }, - { be_const_key_weak(_store, 57), be_const_var(0) }, - { be_const_key_weak(get_ca_pub, 32), be_const_closure(Matter_Fabric_get_ca_pub_closure) }, - { be_const_key_weak(_GROUP_KEY, 16), be_nested_str_weak(GroupKey_X20v1_X2E0) }, - { be_const_key_weak(tojson, -1), be_const_closure(Matter_Fabric_tojson_closure) }, - { be_const_key_weak(assign_fabric_index, -1), be_const_closure(Matter_Fabric_assign_fabric_index_closure) }, - { be_const_key_weak(get_admin_subject, -1), be_const_closure(Matter_Fabric_get_admin_subject_closure) }, - { be_const_key_weak(_MAX_CASE, -1), be_const_int(5) }, - { be_const_key_weak(fabric_candidate, -1), be_const_closure(Matter_Fabric_fabric_candidate_closure) }, - { be_const_key_weak(_GROUP_SND_INCR, 36), be_const_int(32) }, - { be_const_key_weak(get_fabric_label, 55), be_const_closure(Matter_Fabric_get_fabric_label_closure) }, - { be_const_key_weak(set_noc_icac, -1), be_const_closure(Matter_Fabric_set_noc_icac_closure) }, - { be_const_key_weak(get_noc, 52), be_const_closure(Matter_Fabric_get_noc_closure) }, - { be_const_key_weak(before_remove, -1), be_const_closure(Matter_Fabric_before_remove_closure) }, - { be_const_key_weak(get_admin_vendor_name, -1), be_const_closure(Matter_Fabric_get_admin_vendor_name_closure) }, - { be_const_key_weak(set_ca, -1), be_const_closure(Matter_Fabric_set_ca_closure) }, + { be_const_key_weak(_GROUP_KEY, -1), be_nested_str_weak(GroupKey_X20v1_X2E0) }, + { be_const_key_weak(counter_group_data_snd, -1), be_const_var(15) }, + { be_const_key_weak(get_ca, -1), be_const_closure(Matter_Fabric_get_ca_closure) }, + { be_const_key_weak(get_ipk_epoch_key, 28), be_const_closure(Matter_Fabric_get_ipk_epoch_key_closure) }, + { be_const_key_weak(device_id, -1), be_const_var(13) }, + { be_const_key_weak(_counter_group_data_snd_impl, -1), be_const_var(17) }, + { be_const_key_weak(fabric_index, 27), be_const_var(3) }, + { be_const_key_weak(no_private_key, 45), be_const_var(6) }, { be_const_key_weak(get_ipk_group_key, -1), be_const_closure(Matter_Fabric_get_ipk_group_key_closure) }, + { be_const_key_weak(set_ca, -1), be_const_closure(Matter_Fabric_set_ca_closure) }, + { be_const_key_weak(get_fabric_compressed, 0), be_const_closure(Matter_Fabric_get_fabric_compressed_closure) }, + { be_const_key_weak(fabric_compressed, -1), be_const_var(12) }, + { be_const_key_weak(get_fabric_label, 48), be_const_closure(Matter_Fabric_get_fabric_label_closure) }, + { be_const_key_weak(admin_vendor, -1), be_const_var(20) }, + { be_const_key_weak(before_remove, -1), be_const_closure(Matter_Fabric_before_remove_closure) }, + { be_const_key_weak(noc, 31), be_const_var(8) }, + { be_const_key_weak(fromjson, -1), be_const_static_closure(Matter_Fabric_fromjson_closure) }, + { be_const_key_weak(log_new_fabric, 40), be_const_closure(Matter_Fabric_log_new_fabric_closure) }, + { be_const_key_weak(_counter_group_ctrl_snd_impl, -1), be_const_var(18) }, + { be_const_key_weak(created, 5), be_const_var(1) }, + { be_const_key_weak(set_pk, 16), be_const_closure(Matter_Fabric_set_pk_closure) }, + { be_const_key_weak(mark_for_deletion, -1), be_const_closure(Matter_Fabric_mark_for_deletion_closure) }, + { be_const_key_weak(_GROUP_SND_INCR, -1), be_const_int(32) }, + { be_const_key_weak(_store, 56), be_const_var(0) }, + { be_const_key_weak(fabric_completed, -1), be_const_closure(Matter_Fabric_fabric_completed_closure) }, + { be_const_key_weak(get_device_id, -1), be_const_closure(Matter_Fabric_get_device_id_closure) }, + { be_const_key_weak(get_noc, 14), be_const_closure(Matter_Fabric_get_noc_closure) }, + { be_const_key_weak(get_oldest_session, -1), be_const_closure(Matter_Fabric_get_oldest_session_closure) }, + { be_const_key_weak(get_icac, -1), be_const_closure(Matter_Fabric_get_icac_closure) }, { be_const_key_weak(hydrate_post, -1), be_const_closure(Matter_Fabric_hydrate_post_closure) }, - { be_const_key_weak(set_ipk_epoch_key, 31), be_const_closure(Matter_Fabric_set_ipk_epoch_key_closure) }, - { be_const_key_weak(set_pk, -1), be_const_closure(Matter_Fabric_set_pk_closure) }, + { be_const_key_weak(admin_subject, -1), be_const_var(19) }, + { be_const_key_weak(fabric_id, -1), be_const_var(11) }, { be_const_key_weak(set_admin_subject_vendor, -1), be_const_closure(Matter_Fabric_set_admin_subject_vendor_closure) }, - { be_const_key_weak(get_fabric_compressed, 42), be_const_closure(Matter_Fabric_get_fabric_compressed_closure) }, - { be_const_key_weak(log_new_fabric, -1), be_const_closure(Matter_Fabric_log_new_fabric_closure) }, - { be_const_key_weak(get_pk, -1), be_const_closure(Matter_Fabric_get_pk_closure) }, - { be_const_key_weak(get_admin_vendor, -1), be_const_closure(Matter_Fabric_get_admin_vendor_closure) }, - { be_const_key_weak(get_fabric_id, -1), be_const_closure(Matter_Fabric_get_fabric_id_closure) }, - { be_const_key_weak(get_icac, 37), be_const_closure(Matter_Fabric_get_icac_closure) }, - { be_const_key_weak(_counter_group_ctrl_snd_impl, -1), be_const_var(17) }, - { be_const_key_weak(set_fabric_device, -1), be_const_closure(Matter_Fabric_set_fabric_device_closure) }, - { be_const_key_weak(admin_subject, 5), be_const_var(18) }, - { be_const_key_weak(counter_group_data_snd, -1), be_const_var(14) }, - { be_const_key_weak(get_newest_session, 29), be_const_closure(Matter_Fabric_get_newest_session_closure) }, - { be_const_key_weak(get_fabric_index, -1), be_const_closure(Matter_Fabric_get_fabric_index_closure) }, - { be_const_key_weak(get_ipk_epoch_key, -1), be_const_closure(Matter_Fabric_get_ipk_epoch_key_closure) }, - { be_const_key_weak(counter_group_data_snd_next, 4), be_const_closure(Matter_Fabric_counter_group_data_snd_next_closure) }, - { be_const_key_weak(counter_group_ctrl_snd_next, -1), be_const_closure(Matter_Fabric_counter_group_ctrl_snd_next_closure) }, + { be_const_key_weak(get_ca_pub, 52), be_const_closure(Matter_Fabric_get_ca_pub_closure) }, + { be_const_key_weak(root_ca_certificate, -1), be_const_var(7) }, + { be_const_key_weak(ipk_epoch_key, -1), be_const_var(10) }, + { be_const_key_weak(icac, -1), be_const_var(9) }, { be_const_key_weak(get_old_recent_session, -1), be_const_closure(Matter_Fabric_get_old_recent_session_closure) }, - { be_const_key_weak(_sessions, 0), be_const_var(4) }, + { be_const_key_weak(counter_group_ctrl_snd_next, -1), be_const_closure(Matter_Fabric_counter_group_ctrl_snd_next_closure) }, + { be_const_key_weak(get_pk, 35), be_const_closure(Matter_Fabric_get_pk_closure) }, + { be_const_key_weak(counter_group_data_snd_next, 13), be_const_closure(Matter_Fabric_counter_group_data_snd_next_closure) }, + { be_const_key_weak(get_newest_session, 38), be_const_closure(Matter_Fabric_get_newest_session_closure) }, + { be_const_key_weak(set_noc_icac, -1), be_const_closure(Matter_Fabric_set_noc_icac_closure) }, + { be_const_key_weak(add_session, -1), be_const_closure(Matter_Fabric_add_session_closure) }, + { be_const_key_weak(set_fabric_index, 46), be_const_closure(Matter_Fabric_set_fabric_index_closure) }, + { be_const_key_weak(get_admin_subject, 18), be_const_closure(Matter_Fabric_get_admin_subject_closure) }, + { be_const_key_weak(_MAX_CASE, -1), be_const_int(5) }, + { be_const_key_weak(set_fabric_device, -1), be_const_closure(Matter_Fabric_set_fabric_device_closure) }, + { be_const_key_weak(deleted, -1), be_const_var(2) }, + { be_const_key_weak(get_admin_vendor, 32), be_const_closure(Matter_Fabric_get_admin_vendor_closure) }, + { be_const_key_weak(tojson, -1), be_const_closure(Matter_Fabric_tojson_closure) }, + { be_const_key_weak(assign_fabric_index, 29), be_const_closure(Matter_Fabric_assign_fabric_index_closure) }, + { be_const_key_weak(init, -1), be_const_closure(Matter_Fabric_init_closure) }, + { be_const_key_weak(_sessions, 6), be_const_var(5) }, + { be_const_key_weak(fabric_candidate, 25), be_const_closure(Matter_Fabric_fabric_candidate_closure) }, + { be_const_key_weak(set_ipk_epoch_key, -1), be_const_closure(Matter_Fabric_set_ipk_epoch_key_closure) }, + { be_const_key_weak(fabric_label, 59), be_const_var(14) }, + { be_const_key_weak(get_fabric_index, -1), be_const_closure(Matter_Fabric_get_fabric_index_closure) }, + { be_const_key_weak(get_admin_vendor_name, -1), be_const_closure(Matter_Fabric_get_admin_vendor_name_closure) }, + { be_const_key_weak(is_marked_for_deletion, 1), be_const_closure(Matter_Fabric_is_marked_for_deletion_closure) }, + { be_const_key_weak(fabric_parent, -1), be_const_var(4) }, + { be_const_key_weak(counter_group_ctrl_snd, -1), be_const_var(16) }, + { be_const_key_weak(get_fabric_id, -1), be_const_closure(Matter_Fabric_get_fabric_id_closure) }, })), be_str_weak(Matter_Fabric) ); diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_0.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_0.h index 6e5811686..f34e08665 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_0.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_0.h @@ -273,7 +273,7 @@ be_local_closure(Matter_Plugin_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[20]) { /* constants */ + ( &(const bvalue[18]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -292,12 +292,10 @@ be_local_closure(Matter_Plugin_read_attribute, /* name */ /* K15 */ be_const_int(2), /* K16 */ be_const_int(3), /* K17 */ be_nested_str_weak(set), - /* K18 */ be_nested_str_weak(BOOL), - /* K19 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[114]) { /* code */ + ( &(const binstruction[92]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 @@ -386,32 +384,10 @@ be_local_closure(Matter_Plugin_read_attribute, /* name */ 0x5828000B, // 0055 LDCONST R10 K11 0x7C1C0600, // 0056 CALL R7 3 0x80040E00, // 0057 RET 1 R7 - 0x70020017, // 0058 JMP #0071 - 0x541E0038, // 0059 LDINT R7 57 - 0x1C1C0A07, // 005A EQ R7 R5 R7 - 0x781E0012, // 005B JMPF R7 #006F - 0x541E0010, // 005C LDINT R7 17 - 0x1C1C0C07, // 005D EQ R7 R6 R7 - 0x781E0005, // 005E JMPF R7 #0065 - 0x8C1C0711, // 005F GETMET R7 R3 K17 - 0x88240912, // 0060 GETMBR R9 R4 K18 - 0x5828000B, // 0061 LDCONST R10 K11 - 0x7C1C0600, // 0062 CALL R7 3 - 0x80040E00, // 0063 RET 1 R7 - 0x70020008, // 0064 JMP #006E - 0x601C0003, // 0065 GETGBL R7 G3 - 0x5C200000, // 0066 MOVE R8 R0 - 0x7C1C0200, // 0067 CALL R7 1 - 0x8C1C0F13, // 0068 GETMET R7 R7 K19 - 0x5C240200, // 0069 MOVE R9 R1 - 0x5C280400, // 006A MOVE R10 R2 - 0x5C2C0600, // 006B MOVE R11 R3 - 0x7C1C0800, // 006C CALL R7 4 - 0x80040E00, // 006D RET 1 R7 - 0x70020001, // 006E JMP #0071 - 0x4C1C0000, // 006F LDNIL R7 - 0x80040E00, // 0070 RET 1 R7 - 0x80000000, // 0071 RET 0 + 0x70020001, // 0058 JMP #005B + 0x4C1C0000, // 0059 LDNIL R7 + 0x80040E00, // 005A RET 1 R7 + 0x80000000, // 005B RET 0 }) ) ); @@ -1303,7 +1279,7 @@ be_local_class(Matter_Plugin, { be_const_key_weak(VIRTUAL, 6), be_const_bool(0) }, { be_const_key_weak(node_label, 34), be_const_var(5) }, { be_const_key_weak(CLUSTERS, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { - be_const_map( * be_nested_map(2, + be_const_map( * be_nested_map(1, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(29, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { be_const_list( * be_nested_list(6, @@ -1314,11 +1290,6 @@ be_local_class(Matter_Plugin, be_const_int(3), be_const_int(65532), be_const_int(65533), - })) ) } )) }, - { be_const_key_int(57, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(1, - ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), })) ) } )) }, })) ) } )) }, { be_const_key_weak(update_shadow_lazy, -1), be_const_closure(Matter_Plugin_update_shadow_lazy_closure) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Aggregator.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Aggregator.h index 34df71698..20f1be289 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Aggregator.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Aggregator.h @@ -19,80 +19,207 @@ be_local_closure(Matter_Plugin_Aggregator_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[13]) { /* constants */ + ( &(const bvalue[19]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), /* K3 */ be_nested_str_weak(attribute), /* K4 */ be_const_int(3), - /* K5 */ be_nested_str_weak(Matter_TLV_array), - /* K6 */ be_nested_str_weak(device), - /* K7 */ be_nested_str_weak(get_active_endpoints), - /* K8 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), - /* K9 */ be_nested_str_weak(add_TLV), - /* K10 */ be_nested_str_weak(U2), - /* K11 */ be_nested_str_weak(stop_iteration), - /* K12 */ be_nested_str_weak(read_attribute), + /* K5 */ be_const_int(0), + /* K6 */ be_nested_str_weak(set), + /* K7 */ be_nested_str_weak(U2), + /* K8 */ be_const_int(1), + /* K9 */ be_nested_str_weak(U1), + /* K10 */ be_nested_str_weak(U4), + /* K11 */ be_const_int(2), + /* K12 */ be_nested_str_weak(Matter_TLV_array), + /* K13 */ be_nested_str_weak(add_TLV), + /* K14 */ be_nested_str_weak(device), + /* K15 */ be_nested_str_weak(get_active_endpoints), + /* K16 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), + /* K17 */ be_nested_str_weak(stop_iteration), + /* K18 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[56]) { /* code */ + ( &(const binstruction[103]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 - 0x541E001C, // 0004 LDINT R7 29 - 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0026, // 0006 JMPF R7 #002E - 0x1C1C0D04, // 0007 EQ R7 R6 K4 - 0x781E001A, // 0008 JMPF R7 #0024 - 0x8C1C0905, // 0009 GETMET R7 R4 K5 - 0x7C1C0200, // 000A CALL R7 1 - 0x88200106, // 000B GETMBR R8 R0 K6 - 0x8C201107, // 000C GETMET R8 R8 K7 - 0x50280200, // 000D LDBOOL R10 1 0 - 0x7C200400, // 000E CALL R8 2 - 0x60240010, // 000F GETGBL R9 G16 - 0x5C281000, // 0010 MOVE R10 R8 - 0x7C240200, // 0011 CALL R9 1 - 0xA802000B, // 0012 EXBLK 0 #001F - 0x5C281200, // 0013 MOVE R10 R9 - 0x7C280000, // 0014 CALL R10 0 - 0xB82E0000, // 0015 GETNGBL R11 K0 - 0x882C1708, // 0016 GETMBR R11 R11 K8 - 0x142C140B, // 0017 LT R11 R10 R11 - 0x782E0004, // 0018 JMPF R11 #001E - 0x8C2C0F09, // 0019 GETMET R11 R7 K9 - 0x4C340000, // 001A LDNIL R13 - 0x8838090A, // 001B GETMBR R14 R4 K10 - 0x5C3C1400, // 001C MOVE R15 R10 - 0x7C2C0800, // 001D CALL R11 4 - 0x7001FFF3, // 001E JMP #0013 - 0x5824000B, // 001F LDCONST R9 K11 - 0xAC240200, // 0020 CATCH R9 1 0 - 0xB0080000, // 0021 RAISE 2 R0 R0 - 0x80040E00, // 0022 RET 1 R7 - 0x70020008, // 0023 JMP #002D - 0x601C0003, // 0024 GETGBL R7 G3 - 0x5C200000, // 0025 MOVE R8 R0 - 0x7C1C0200, // 0026 CALL R7 1 - 0x8C1C0F0C, // 0027 GETMET R7 R7 K12 - 0x5C240200, // 0028 MOVE R9 R1 - 0x5C280400, // 0029 MOVE R10 R2 - 0x5C2C0600, // 002A MOVE R11 R3 - 0x7C1C0800, // 002B CALL R7 4 - 0x80040E00, // 002C RET 1 R7 - 0x70020008, // 002D JMP #0037 - 0x601C0003, // 002E GETGBL R7 G3 - 0x5C200000, // 002F MOVE R8 R0 - 0x7C1C0200, // 0030 CALL R7 1 - 0x8C1C0F0C, // 0031 GETMET R7 R7 K12 - 0x5C240200, // 0032 MOVE R9 R1 - 0x5C280400, // 0033 MOVE R10 R2 - 0x5C2C0600, // 0034 MOVE R11 R3 - 0x7C1C0800, // 0035 CALL R7 4 - 0x80040E00, // 0036 RET 1 R7 - 0x80000000, // 0037 RET 0 + 0x1C1C0B04, // 0004 EQ R7 R5 K4 + 0x781E0021, // 0005 JMPF R7 #0028 + 0x1C1C0D05, // 0006 EQ R7 R6 K5 + 0x781E0005, // 0007 JMPF R7 #000E + 0x8C1C0706, // 0008 GETMET R7 R3 K6 + 0x88240907, // 0009 GETMBR R9 R4 K7 + 0x58280005, // 000A LDCONST R10 K5 + 0x7C1C0600, // 000B CALL R7 3 + 0x80040E00, // 000C RET 1 R7 + 0x70020018, // 000D JMP #0027 + 0x1C1C0D08, // 000E EQ R7 R6 K8 + 0x781E0005, // 000F JMPF R7 #0016 + 0x8C1C0706, // 0010 GETMET R7 R3 K6 + 0x88240909, // 0011 GETMBR R9 R4 K9 + 0x58280005, // 0012 LDCONST R10 K5 + 0x7C1C0600, // 0013 CALL R7 3 + 0x80040E00, // 0014 RET 1 R7 + 0x70020010, // 0015 JMP #0027 + 0x541EFFFB, // 0016 LDINT R7 65532 + 0x1C1C0C07, // 0017 EQ R7 R6 R7 + 0x781E0005, // 0018 JMPF R7 #001F + 0x8C1C0706, // 0019 GETMET R7 R3 K6 + 0x8824090A, // 001A GETMBR R9 R4 K10 + 0x58280005, // 001B LDCONST R10 K5 + 0x7C1C0600, // 001C CALL R7 3 + 0x80040E00, // 001D RET 1 R7 + 0x70020007, // 001E JMP #0027 + 0x541EFFFC, // 001F LDINT R7 65533 + 0x1C1C0C07, // 0020 EQ R7 R6 R7 + 0x781E0004, // 0021 JMPF R7 #0027 + 0x8C1C0706, // 0022 GETMET R7 R3 K6 + 0x8824090A, // 0023 GETMBR R9 R4 K10 + 0x542A0003, // 0024 LDINT R10 4 + 0x7C1C0600, // 0025 CALL R7 3 + 0x80040E00, // 0026 RET 1 R7 + 0x7002003D, // 0027 JMP #0066 + 0x541E001C, // 0028 LDINT R7 29 + 0x1C1C0A07, // 0029 EQ R7 R5 R7 + 0x781E0031, // 002A JMPF R7 #005D + 0x1C1C0D0B, // 002B EQ R7 R6 K11 + 0x781E0008, // 002C JMPF R7 #0036 + 0x8C1C090C, // 002D GETMET R7 R4 K12 + 0x7C1C0200, // 002E CALL R7 1 + 0x8C200F0D, // 002F GETMET R8 R7 K13 + 0x4C280000, // 0030 LDNIL R10 + 0x882C0907, // 0031 GETMBR R11 R4 K7 + 0x5432001D, // 0032 LDINT R12 30 + 0x7C200800, // 0033 CALL R8 4 + 0x80040E00, // 0034 RET 1 R7 + 0x70020025, // 0035 JMP #005C + 0x1C1C0D04, // 0036 EQ R7 R6 K4 + 0x781E001A, // 0037 JMPF R7 #0053 + 0x8C1C090C, // 0038 GETMET R7 R4 K12 + 0x7C1C0200, // 0039 CALL R7 1 + 0x8820010E, // 003A GETMBR R8 R0 K14 + 0x8C20110F, // 003B GETMET R8 R8 K15 + 0x50280200, // 003C LDBOOL R10 1 0 + 0x7C200400, // 003D CALL R8 2 + 0x60240010, // 003E GETGBL R9 G16 + 0x5C281000, // 003F MOVE R10 R8 + 0x7C240200, // 0040 CALL R9 1 + 0xA802000B, // 0041 EXBLK 0 #004E + 0x5C281200, // 0042 MOVE R10 R9 + 0x7C280000, // 0043 CALL R10 0 + 0xB82E0000, // 0044 GETNGBL R11 K0 + 0x882C1710, // 0045 GETMBR R11 R11 K16 + 0x202C140B, // 0046 NE R11 R10 R11 + 0x782E0004, // 0047 JMPF R11 #004D + 0x8C2C0F0D, // 0048 GETMET R11 R7 K13 + 0x4C340000, // 0049 LDNIL R13 + 0x88380907, // 004A GETMBR R14 R4 K7 + 0x5C3C1400, // 004B MOVE R15 R10 + 0x7C2C0800, // 004C CALL R11 4 + 0x7001FFF3, // 004D JMP #0042 + 0x58240011, // 004E LDCONST R9 K17 + 0xAC240200, // 004F CATCH R9 1 0 + 0xB0080000, // 0050 RAISE 2 R0 R0 + 0x80040E00, // 0051 RET 1 R7 + 0x70020008, // 0052 JMP #005C + 0x601C0003, // 0053 GETGBL R7 G3 + 0x5C200000, // 0054 MOVE R8 R0 + 0x7C1C0200, // 0055 CALL R7 1 + 0x8C1C0F12, // 0056 GETMET R7 R7 K18 + 0x5C240200, // 0057 MOVE R9 R1 + 0x5C280400, // 0058 MOVE R10 R2 + 0x5C2C0600, // 0059 MOVE R11 R3 + 0x7C1C0800, // 005A CALL R7 4 + 0x80040E00, // 005B RET 1 R7 + 0x70020008, // 005C JMP #0066 + 0x601C0003, // 005D GETGBL R7 G3 + 0x5C200000, // 005E MOVE R8 R0 + 0x7C1C0200, // 005F CALL R7 1 + 0x8C1C0F12, // 0060 GETMET R7 R7 K18 + 0x5C240200, // 0061 MOVE R9 R1 + 0x5C280400, // 0062 MOVE R10 R2 + 0x5C2C0600, // 0063 MOVE R11 R3 + 0x7C1C0800, // 0064 CALL R7 4 + 0x80040E00, // 0065 RET 1 R7 + 0x80000000, // 0066 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: invoke_request +********************************************************************/ +be_local_closure(Matter_Plugin_Aggregator_invoke_request, /* name */ + be_nested_proto( + 13, /* nstack */ + 4, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_str_weak(matter), + /* K1 */ be_nested_str_weak(TLV), + /* K2 */ be_nested_str_weak(cluster), + /* K3 */ be_nested_str_weak(command), + /* K4 */ be_const_int(3), + /* K5 */ be_const_int(0), + /* K6 */ be_const_int(1), + /* K7 */ be_nested_str_weak(Matter_TLV_struct), + /* K8 */ be_nested_str_weak(add_TLV), + /* K9 */ be_nested_str_weak(U2), + /* K10 */ be_nested_str_weak(invoke_request), + }), + be_str_weak(invoke_request), + &be_const_str_solidified, + ( &(const binstruction[39]) { /* code */ + 0xB8120000, // 0000 GETNGBL R4 K0 + 0x88100901, // 0001 GETMBR R4 R4 K1 + 0x88140702, // 0002 GETMBR R5 R3 K2 + 0x88180703, // 0003 GETMBR R6 R3 K3 + 0x1C1C0B04, // 0004 EQ R7 R5 K4 + 0x781E0016, // 0005 JMPF R7 #001D + 0x1C1C0D05, // 0006 EQ R7 R6 K5 + 0x781E0002, // 0007 JMPF R7 #000B + 0x501C0200, // 0008 LDBOOL R7 1 0 + 0x80040E00, // 0009 RET 1 R7 + 0x70020010, // 000A JMP #001C + 0x1C1C0D06, // 000B EQ R7 R6 K6 + 0x781E0009, // 000C JMPF R7 #0017 + 0x8C1C0907, // 000D GETMET R7 R4 K7 + 0x7C1C0200, // 000E CALL R7 1 + 0x8C200F08, // 000F GETMET R8 R7 K8 + 0x58280005, // 0010 LDCONST R10 K5 + 0x882C0909, // 0011 GETMBR R11 R4 K9 + 0x58300005, // 0012 LDCONST R12 K5 + 0x7C200800, // 0013 CALL R8 4 + 0x900E0705, // 0014 SETMBR R3 K3 K5 + 0x80040E00, // 0015 RET 1 R7 + 0x70020004, // 0016 JMP #001C + 0x541E003F, // 0017 LDINT R7 64 + 0x1C1C0C07, // 0018 EQ R7 R6 R7 + 0x781E0001, // 0019 JMPF R7 #001C + 0x501C0200, // 001A LDBOOL R7 1 0 + 0x80040E00, // 001B RET 1 R7 + 0x70020008, // 001C JMP #0026 + 0x601C0003, // 001D GETGBL R7 G3 + 0x5C200000, // 001E MOVE R8 R0 + 0x7C1C0200, // 001F CALL R7 1 + 0x8C1C0F0A, // 0020 GETMET R7 R7 K10 + 0x5C240200, // 0021 MOVE R9 R1 + 0x5C280400, // 0022 MOVE R10 R2 + 0x5C2C0600, // 0023 MOVE R11 R3 + 0x7C1C0800, // 0024 CALL R7 4 + 0x80040E00, // 0025 RET 1 R7 + 0x80000000, // 0026 RET 0 }) ) ); @@ -106,16 +233,39 @@ extern const bclass be_class_Matter_Plugin; be_local_class(Matter_Plugin_Aggregator, 0, &be_class_Matter_Plugin, - be_nested_map(4, + be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(read_attribute, -1), be_const_closure(Matter_Plugin_Aggregator_read_attribute_closure) }, + { be_const_key_weak(TYPE, -1), be_nested_str_weak(aggregator) }, { be_const_key_weak(TYPES, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { be_const_map( * be_nested_map(1, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(14, -1), be_const_int(1) }, })) ) } )) }, - { be_const_key_weak(TYPE, 3), be_nested_str_weak(aggregator) }, - { be_const_key_weak(read_attribute, 0), be_const_closure(Matter_Plugin_Aggregator_read_attribute_closure) }, { be_const_key_weak(DISPLAY_NAME, -1), be_nested_str_weak(Aggregator) }, + { be_const_key_weak(CLUSTERS, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { + be_const_map( * be_nested_map(2, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_int(29, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + be_const_list( * be_nested_list(6, + ( (struct bvalue*) &(const bvalue[]) { + be_const_int(0), + be_const_int(1), + be_const_int(2), + be_const_int(3), + be_const_int(65532), + be_const_int(65533), + })) ) } )) }, + { be_const_key_int(3, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + be_const_list( * be_nested_list(4, + ( (struct bvalue*) &(const bvalue[]) { + be_const_int(0), + be_const_int(1), + be_const_int(65532), + be_const_int(65533), + })) ) } )) }, + })) ) } )) }, + { be_const_key_weak(invoke_request, -1), be_const_closure(Matter_Plugin_Aggregator_invoke_request_closure) }, })), be_str_weak(Matter_Plugin_Aggregator) ); diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Device.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Device.h index b43be5a83..71adb3df2 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Device.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Device.h @@ -60,7 +60,7 @@ be_local_closure(Matter_Plugin_Device_read_attribute, /* name */ }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[264]) { /* code */ + ( &(const binstruction[254]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 @@ -100,7 +100,7 @@ be_local_closure(Matter_Plugin_Device_read_attribute, /* name */ 0x542A0003, // 0024 LDINT R10 4 0x7C1C0600, // 0025 CALL R7 3 0x80040E00, // 0026 RET 1 R7 - 0x700200DE, // 0027 JMP #0107 + 0x700200D4, // 0027 JMP #00FD 0x541E0003, // 0028 LDINT R7 4 0x1C1C0A07, // 0029 EQ R7 R5 R7 0x781E0016, // 002A JMPF R7 #0042 @@ -126,7 +126,7 @@ be_local_closure(Matter_Plugin_Device_read_attribute, /* name */ 0x542A0003, // 003E LDINT R10 4 0x7C1C0600, // 003F CALL R7 3 0x80040E00, // 0040 RET 1 R7 - 0x700200C4, // 0041 JMP #0107 + 0x700200BA, // 0041 JMP #00FD 0x541E0004, // 0042 LDINT R7 5 0x1C1C0A07, // 0043 EQ R7 R5 R7 0x781E0011, // 0044 JMPF R7 #0057 @@ -147,7 +147,7 @@ be_local_closure(Matter_Plugin_Device_read_attribute, /* name */ 0x542A0003, // 0053 LDINT R10 4 0x7C1C0600, // 0054 CALL R7 3 0x80040E00, // 0055 RET 1 R7 - 0x700200AF, // 0056 JMP #0107 + 0x700200A5, // 0056 JMP #00FD 0x541E001C, // 0057 LDINT R7 29 0x1C1C0A07, // 0058 EQ R7 R5 R7 0x781E003E, // 0059 JMPF R7 #0099 @@ -213,10 +213,10 @@ be_local_closure(Matter_Plugin_Device_read_attribute, /* name */ 0x5C2C0600, // 0095 MOVE R11 R3 0x7C1C0800, // 0096 CALL R7 4 0x80040E00, // 0097 RET 1 R7 - 0x7002006D, // 0098 JMP #0107 + 0x70020063, // 0098 JMP #00FD 0x541E0038, // 0099 LDINT R7 57 0x1C1C0A07, // 009A EQ R7 R5 R7 - 0x781E0061, // 009B JMPF R7 #00FE + 0x781E0057, // 009B JMPF R7 #00F4 0xA41E2E00, // 009C IMPORT R7 K23 0x1C200D04, // 009D EQ R8 R6 K4 0x7822000A, // 009E JMPF R8 #00AA @@ -230,7 +230,7 @@ be_local_closure(Matter_Plugin_Device_read_attribute, /* name */ 0x942C171B, // 00A6 GETIDX R11 R11 K27 0x7C200600, // 00A7 CALL R8 3 0x80041000, // 00A8 RET 1 R8 - 0x70020052, // 00A9 JMP #00FD + 0x70020048, // 00A9 JMP #00F3 0x54220004, // 00AA LDINT R8 5 0x1C200C08, // 00AB EQ R8 R6 R8 0x78220006, // 00AC JMPF R8 #00B4 @@ -240,7 +240,7 @@ be_local_closure(Matter_Plugin_Device_read_attribute, /* name */ 0x7C2C0200, // 00B0 CALL R11 1 0x7C200600, // 00B1 CALL R8 3 0x80041000, // 00B2 RET 1 R8 - 0x70020048, // 00B3 JMP #00FD + 0x7002003E, // 00B3 JMP #00F3 0x54220009, // 00B4 LDINT R8 10 0x1C200C08, // 00B5 EQ R8 R6 R8 0x78220015, // 00B6 JMPF R8 #00CD @@ -265,7 +265,7 @@ be_local_closure(Matter_Plugin_Device_read_attribute, /* name */ 0x5C341000, // 00C9 MOVE R13 R8 0x7C280600, // 00CA CALL R10 3 0x80041400, // 00CB RET 1 R10 - 0x7002002F, // 00CC JMP #00FD + 0x70020025, // 00CC JMP #00F3 0x5422000E, // 00CD LDINT R8 15 0x1C200C08, // 00CE EQ R8 R6 R8 0x7822000B, // 00CF JMPF R8 #00DC @@ -280,7 +280,7 @@ be_local_closure(Matter_Plugin_Device_read_attribute, /* name */ 0x7C2C0600, // 00D8 CALL R11 3 0x7C200600, // 00D9 CALL R8 3 0x80041000, // 00DA RET 1 R8 - 0x70020020, // 00DB JMP #00FD + 0x70020016, // 00DB JMP #00F3 0x54220010, // 00DC LDINT R8 17 0x1C200C08, // 00DD EQ R8 R6 R8 0x78220005, // 00DE JMPF R8 #00E5 @@ -289,10 +289,10 @@ be_local_closure(Matter_Plugin_Device_read_attribute, /* name */ 0x582C0008, // 00E1 LDCONST R11 K8 0x7C200600, // 00E2 CALL R8 3 0x80041000, // 00E3 RET 1 R8 - 0x70020017, // 00E4 JMP #00FD + 0x7002000D, // 00E4 JMP #00F3 0x54220011, // 00E5 LDINT R8 18 0x1C200C08, // 00E6 EQ R8 R6 R8 - 0x7822000B, // 00E7 JMPF R8 #00F4 + 0x7822000A, // 00E7 JMPF R8 #00F3 0x8C200706, // 00E8 GETMET R8 R3 K6 0x88280918, // 00E9 GETMBR R10 R4 K24 0xB82E3200, // 00EA GETNGBL R11 K25 @@ -305,26 +305,16 @@ be_local_closure(Matter_Plugin_Device_read_attribute, /* name */ 0x7C200600, // 00F1 CALL R8 3 0x80041000, // 00F2 RET 1 R8 0x70020008, // 00F3 JMP #00FD - 0x60200003, // 00F4 GETGBL R8 G3 - 0x5C240000, // 00F5 MOVE R9 R0 - 0x7C200200, // 00F6 CALL R8 1 - 0x8C201116, // 00F7 GETMET R8 R8 K22 - 0x5C280200, // 00F8 MOVE R10 R1 - 0x5C2C0400, // 00F9 MOVE R11 R2 - 0x5C300600, // 00FA MOVE R12 R3 - 0x7C200800, // 00FB CALL R8 4 - 0x80041000, // 00FC RET 1 R8 - 0x70020008, // 00FD JMP #0107 - 0x601C0003, // 00FE GETGBL R7 G3 - 0x5C200000, // 00FF MOVE R8 R0 - 0x7C1C0200, // 0100 CALL R7 1 - 0x8C1C0F16, // 0101 GETMET R7 R7 K22 - 0x5C240200, // 0102 MOVE R9 R1 - 0x5C280400, // 0103 MOVE R10 R2 - 0x5C2C0600, // 0104 MOVE R11 R3 - 0x7C1C0800, // 0105 CALL R7 4 - 0x80040E00, // 0106 RET 1 R7 - 0x80000000, // 0107 RET 0 + 0x601C0003, // 00F4 GETGBL R7 G3 + 0x5C200000, // 00F5 MOVE R8 R0 + 0x7C1C0200, // 00F6 CALL R7 1 + 0x8C1C0F16, // 00F7 GETMET R7 R7 K22 + 0x5C240200, // 00F8 MOVE R9 R1 + 0x5C280400, // 00F9 MOVE R10 R2 + 0x5C2C0600, // 00FA MOVE R11 R3 + 0x7C1C0800, // 00FB CALL R7 4 + 0x80040E00, // 00FC RET 1 R7 + 0x80000000, // 00FD RET 0 }) ) ); @@ -597,17 +587,19 @@ be_local_class(Matter_Plugin_Device, be_const_int(65532), be_const_int(65533), })) ) } )) }, - { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + { be_const_key_int(29, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(1), + be_const_int(2), + be_const_int(3), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), @@ -623,13 +615,10 @@ be_local_class(Matter_Plugin_Device, be_const_int(65532), be_const_int(65533), })) ) } )) }, - { be_const_key_int(29, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + { be_const_key_int(4, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + be_const_list( * be_nested_list(3, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), - be_const_int(1), - be_const_int(2), - be_const_int(3), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h index 488d82899..3e8fdd204 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h @@ -19,7 +19,7 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[93]) { /* constants */ + ( &(const bvalue[94]) { /* constants */ /* K0 */ be_nested_str_weak(string), /* K1 */ be_nested_str_weak(matter), /* K2 */ be_nested_str_weak(TLV), @@ -77,46 +77,47 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ /* K54 */ be_nested_str_weak(device), /* K55 */ be_nested_str_weak(sessions), /* K56 */ be_nested_str_weak(active_fabrics), - /* K57 */ be_nested_str_weak(B2), - /* K58 */ be_nested_str_weak(get_noc), - /* K59 */ be_nested_str_weak(get_icac), - /* K60 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), - /* K61 */ be_nested_str_weak(get_fabric_index), - /* K62 */ be_nested_str_weak(stop_iteration), - /* K63 */ be_nested_str_weak(parse), - /* K64 */ be_nested_str_weak(get_ca), - /* K65 */ be_nested_str_weak(findsubval), - /* K66 */ be_nested_str_weak(get_admin_vendor), - /* K67 */ be_nested_str_weak(get_fabric_id), - /* K68 */ be_nested_str_weak(get_device_id), - /* K69 */ be_nested_str_weak(get_fabric_label), - /* K70 */ be_nested_str_weak(Fabric), - /* K71 */ be_nested_str_weak(_MAX_CASE), - /* K72 */ be_nested_str_weak(count_active_fabrics), - /* K73 */ be_nested_str_weak(_fabric), - /* K74 */ be_nested_str_weak(is_commissioning_open), - /* K75 */ be_nested_str_weak(is_root_commissioning_open), - /* K76 */ be_nested_str_weak(commissioning_admin_fabric), - /* K77 */ be_nested_str_weak(Tasmota), - /* K78 */ be_nested_str_weak(vendorid), - /* K79 */ be_nested_str_weak(DeviceName), - /* K80 */ be_nested_str_weak(FriendlyName), - /* K81 */ be_nested_str_weak(FriendlyName1), - /* K82 */ be_nested_str_weak(XX), - /* K83 */ be_nested_str_weak(Status_X202), - /* K84 */ be_nested_str_weak(StatusFWR), - /* K85 */ be_nested_str_weak(Hardware), - /* K86 */ be_nested_str_weak(Version), - /* K87 */ be_nested_str_weak(_X28), - /* K88 */ be_nested_str_weak(locale), - /* K89 */ be_nested_str_weak(create_TLV), - /* K90 */ be_nested_str_weak(get_active_endpoints), - /* K91 */ be_nested_str_weak(disable_bridge_mode), - /* K92 */ be_nested_str_weak(read_attribute), + /* K57 */ be_nested_str_weak(is_marked_for_deletion), + /* K58 */ be_nested_str_weak(B2), + /* K59 */ be_nested_str_weak(get_noc), + /* K60 */ be_nested_str_weak(get_icac), + /* K61 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), + /* K62 */ be_nested_str_weak(get_fabric_index), + /* K63 */ be_nested_str_weak(stop_iteration), + /* K64 */ be_nested_str_weak(parse), + /* K65 */ be_nested_str_weak(get_ca), + /* K66 */ be_nested_str_weak(findsubval), + /* K67 */ be_nested_str_weak(get_admin_vendor), + /* K68 */ be_nested_str_weak(get_fabric_id), + /* K69 */ be_nested_str_weak(get_device_id), + /* K70 */ be_nested_str_weak(get_fabric_label), + /* K71 */ be_nested_str_weak(Fabric), + /* K72 */ be_nested_str_weak(_MAX_CASE), + /* K73 */ be_nested_str_weak(count_active_fabrics), + /* K74 */ be_nested_str_weak(_fabric), + /* K75 */ be_nested_str_weak(is_commissioning_open), + /* K76 */ be_nested_str_weak(is_root_commissioning_open), + /* K77 */ be_nested_str_weak(commissioning_admin_fabric), + /* K78 */ be_nested_str_weak(Tasmota), + /* K79 */ be_nested_str_weak(vendorid), + /* K80 */ be_nested_str_weak(DeviceName), + /* K81 */ be_nested_str_weak(FriendlyName), + /* K82 */ be_nested_str_weak(FriendlyName1), + /* K83 */ be_nested_str_weak(XX), + /* K84 */ be_nested_str_weak(Status_X202), + /* K85 */ be_nested_str_weak(StatusFWR), + /* K86 */ be_nested_str_weak(Hardware), + /* K87 */ be_nested_str_weak(Version), + /* K88 */ be_nested_str_weak(_X28), + /* K89 */ be_nested_str_weak(locale), + /* K90 */ be_nested_str_weak(create_TLV), + /* K91 */ be_nested_str_weak(get_active_endpoints), + /* K92 */ be_nested_str_weak(disable_bridge_mode), + /* K93 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[939]) { /* code */ + ( &(const binstruction[958]) { /* code */ 0xA4120000, // 0000 IMPORT R4 K0 0xB8160200, // 0001 GETNGBL R5 K1 0x88140B02, // 0002 GETMBR R5 R5 K2 @@ -173,11 +174,11 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x502C0000, // 0035 LDBOOL R11 0 0 0x7C200600, // 0036 CALL R8 3 0x80041000, // 0037 RET 1 R8 - 0x70020370, // 0038 JMP #03AA + 0x70020383, // 0038 JMP #03BD 0x54220031, // 0039 LDINT R8 50 0x1C200C08, // 003A EQ R8 R6 R8 0x78220000, // 003B JMPF R8 #003D - 0x7002036C, // 003C JMP #03AA + 0x7002037F, // 003C JMP #03BD 0x54220032, // 003D LDINT R8 51 0x1C200C08, // 003E EQ R8 R6 R8 0x782200DC, // 003F JMPF R8 #011D @@ -401,11 +402,11 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x502C0000, // 0119 LDBOOL R11 0 0 0x7C200600, // 011A CALL R8 3 0x80041000, // 011B RET 1 R8 - 0x7002028C, // 011C JMP #03AA + 0x7002029F, // 011C JMP #03BD 0x54220033, // 011D LDINT R8 52 0x1C200C08, // 011E EQ R8 R6 R8 0x78220000, // 011F JMPF R8 #0121 - 0x70020288, // 0120 JMP #03AA + 0x7002029B, // 0120 JMP #03BD 0x54220037, // 0121 LDINT R8 56 0x1C200C08, // 0122 EQ R8 R6 R8 0x7822002B, // 0123 JMPF R8 #0150 @@ -452,15 +453,15 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x5C301000, // 014C MOVE R12 R8 0x7C240600, // 014D CALL R9 3 0x80041200, // 014E RET 1 R9 - 0x70020259, // 014F JMP #03AA + 0x7002026C, // 014F JMP #03BD 0x5422003D, // 0150 LDINT R8 62 0x1C200C08, // 0151 EQ R8 R6 R8 - 0x782200AE, // 0152 JMPF R8 #0202 + 0x782200B6, // 0152 JMPF R8 #020A 0x8C200133, // 0153 GETMET R8 R0 K51 0x5C280400, // 0154 MOVE R10 R2 0x7C200400, // 0155 CALL R8 2 0x1C200F05, // 0156 EQ R8 R7 K5 - 0x78220033, // 0157 JMPF R8 #018C + 0x78220037, // 0157 JMPF R8 #0190 0x8C200B11, // 0158 GETMET R8 R5 K17 0x7C200200, // 0159 CALL R8 1 0x88240534, // 015A GETMBR R9 R2 K52 @@ -478,584 +479,603 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x60280010, // 0166 GETGBL R10 G16 0x5C2C1200, // 0167 MOVE R11 R9 0x7C280200, // 0168 CALL R10 1 - 0xA802001C, // 0169 EXBLK 0 #0187 + 0xA8020020, // 0169 EXBLK 0 #018B 0x5C2C1400, // 016A MOVE R11 R10 0x7C2C0000, // 016B CALL R11 0 - 0x4C300000, // 016C LDNIL R12 - 0x1C30160C, // 016D EQ R12 R11 R12 + 0x8C301739, // 016C GETMET R12 R11 K57 + 0x7C300200, // 016D CALL R12 1 0x78320000, // 016E JMPF R12 #0170 0x7001FFF9, // 016F JMP #016A - 0x8C301115, // 0170 GETMET R12 R8 K21 - 0x4C380000, // 0171 LDNIL R14 - 0x7C300400, // 0172 CALL R12 2 - 0x8C34190B, // 0173 GETMET R13 R12 K11 - 0x583C0009, // 0174 LDCONST R15 K9 - 0x88400B39, // 0175 GETMBR R16 R5 K57 - 0x8C44173A, // 0176 GETMET R17 R11 K58 - 0x7C440200, // 0177 CALL R17 1 - 0x7C340800, // 0178 CALL R13 4 - 0x8C34190B, // 0179 GETMET R13 R12 K11 - 0x583C000D, // 017A LDCONST R15 K13 - 0x88400B39, // 017B GETMBR R16 R5 K57 - 0x8C44173B, // 017C GETMET R17 R11 K59 - 0x7C440200, // 017D CALL R17 1 - 0x7C340800, // 017E CALL R13 4 - 0x8C34190B, // 017F GETMET R13 R12 K11 - 0xB83E0200, // 0180 GETNGBL R15 K1 - 0x883C1F3C, // 0181 GETMBR R15 R15 K60 - 0x88400B0C, // 0182 GETMBR R16 R5 K12 - 0x8C44173D, // 0183 GETMET R17 R11 K61 - 0x7C440200, // 0184 CALL R17 1 - 0x7C340800, // 0185 CALL R13 4 - 0x7001FFE2, // 0186 JMP #016A - 0x5828003E, // 0187 LDCONST R10 K62 - 0xAC280200, // 0188 CATCH R10 1 0 - 0xB0080000, // 0189 RAISE 2 R0 R0 - 0x80041000, // 018A RET 1 R8 - 0x70020074, // 018B JMP #0201 - 0x1C200F09, // 018C EQ R8 R7 K9 - 0x78220049, // 018D JMPF R8 #01D8 - 0x8C200B11, // 018E GETMET R8 R5 K17 - 0x7C200200, // 018F CALL R8 1 - 0x88240534, // 0190 GETMBR R9 R2 K52 - 0x78260005, // 0191 JMPF R9 #0198 - 0x60240012, // 0192 GETGBL R9 G18 - 0x7C240000, // 0193 CALL R9 0 - 0x8C280335, // 0194 GETMET R10 R1 K53 - 0x7C280200, // 0195 CALL R10 1 - 0x4028120A, // 0196 CONNECT R10 R9 R10 - 0x70020003, // 0197 JMP #019C - 0x88240136, // 0198 GETMBR R9 R0 K54 - 0x88241337, // 0199 GETMBR R9 R9 K55 - 0x8C241338, // 019A GETMET R9 R9 K56 - 0x7C240200, // 019B CALL R9 1 - 0x60280010, // 019C GETGBL R10 G16 - 0x5C2C1200, // 019D MOVE R11 R9 - 0x7C280200, // 019E CALL R10 1 - 0xA8020032, // 019F EXBLK 0 #01D3 - 0x5C2C1400, // 01A0 MOVE R11 R10 - 0x7C2C0000, // 01A1 CALL R11 0 - 0x4C300000, // 01A2 LDNIL R12 - 0x1C30160C, // 01A3 EQ R12 R11 R12 - 0x78320000, // 01A4 JMPF R12 #01A6 - 0x7001FFF9, // 01A5 JMP #01A0 - 0x8C300B3F, // 01A6 GETMET R12 R5 K63 - 0x8C381740, // 01A7 GETMET R14 R11 K64 - 0x7C380200, // 01A8 CALL R14 1 - 0x7C300400, // 01A9 CALL R12 2 - 0x8C341115, // 01AA GETMET R13 R8 K21 - 0x4C3C0000, // 01AB LDNIL R15 - 0x7C340400, // 01AC CALL R13 2 - 0x8C381B0B, // 01AD GETMET R14 R13 K11 - 0x58400009, // 01AE LDCONST R16 K9 - 0x88440B39, // 01AF GETMBR R17 R5 K57 - 0x8C481941, // 01B0 GETMET R18 R12 K65 - 0x54520008, // 01B1 LDINT R20 9 - 0x7C480400, // 01B2 CALL R18 2 - 0x7C380800, // 01B3 CALL R14 4 - 0x8C381B0B, // 01B4 GETMET R14 R13 K11 - 0x5840000D, // 01B5 LDCONST R16 K13 - 0x88440B0C, // 01B6 GETMBR R17 R5 K12 - 0x8C481742, // 01B7 GETMET R18 R11 K66 - 0x7C480200, // 01B8 CALL R18 1 - 0x7C380800, // 01B9 CALL R14 4 - 0x8C381B0B, // 01BA GETMET R14 R13 K11 - 0x5840000F, // 01BB LDCONST R16 K15 - 0x88440B07, // 01BC GETMBR R17 R5 K7 - 0x8C481743, // 01BD GETMET R18 R11 K67 - 0x7C480200, // 01BE CALL R18 1 - 0x7C380800, // 01BF CALL R14 4 - 0x8C381B0B, // 01C0 GETMET R14 R13 K11 - 0x54420003, // 01C1 LDINT R16 4 - 0x88440B07, // 01C2 GETMBR R17 R5 K7 - 0x8C481744, // 01C3 GETMET R18 R11 K68 - 0x7C480200, // 01C4 CALL R18 1 - 0x7C380800, // 01C5 CALL R14 4 - 0x8C381B0B, // 01C6 GETMET R14 R13 K11 - 0x54420004, // 01C7 LDINT R16 5 - 0x88440B16, // 01C8 GETMBR R17 R5 K22 - 0x8C481745, // 01C9 GETMET R18 R11 K69 - 0x7C480200, // 01CA CALL R18 1 - 0x7C380800, // 01CB CALL R14 4 - 0x8C381B0B, // 01CC GETMET R14 R13 K11 - 0x544200FD, // 01CD LDINT R16 254 - 0x88440B0C, // 01CE GETMBR R17 R5 K12 - 0x8C48173D, // 01CF GETMET R18 R11 K61 - 0x7C480200, // 01D0 CALL R18 1 - 0x7C380800, // 01D1 CALL R14 4 - 0x7001FFCC, // 01D2 JMP #01A0 - 0x5828003E, // 01D3 LDCONST R10 K62 - 0xAC280200, // 01D4 CATCH R10 1 0 - 0xB0080000, // 01D5 RAISE 2 R0 R0 - 0x80041000, // 01D6 RET 1 R8 - 0x70020028, // 01D7 JMP #0201 - 0x1C200F0D, // 01D8 EQ R8 R7 K13 - 0x78220007, // 01D9 JMPF R8 #01E2 - 0x8C200706, // 01DA GETMET R8 R3 K6 - 0x88280B0E, // 01DB GETMBR R10 R5 K14 - 0xB82E0200, // 01DC GETNGBL R11 K1 - 0x882C1746, // 01DD GETMBR R11 R11 K70 - 0x882C1747, // 01DE GETMBR R11 R11 K71 - 0x7C200600, // 01DF CALL R8 3 - 0x80041000, // 01E0 RET 1 R8 - 0x7002001E, // 01E1 JMP #0201 - 0x1C200F0F, // 01E2 EQ R8 R7 K15 - 0x78220009, // 01E3 JMPF R8 #01EE - 0x88200136, // 01E4 GETMBR R8 R0 K54 - 0x88201137, // 01E5 GETMBR R8 R8 K55 - 0x8C201148, // 01E6 GETMET R8 R8 K72 - 0x7C200200, // 01E7 CALL R8 1 - 0x8C240706, // 01E8 GETMET R9 R3 K6 - 0x882C0B0E, // 01E9 GETMBR R11 R5 K14 - 0x5C301000, // 01EA MOVE R12 R8 - 0x7C240600, // 01EB CALL R9 3 - 0x80041200, // 01EC RET 1 R9 - 0x70020012, // 01ED JMP #0201 - 0x54220003, // 01EE LDINT R8 4 - 0x1C200E08, // 01EF EQ R8 R7 R8 - 0x78220000, // 01F0 JMPF R8 #01F2 - 0x7002000E, // 01F1 JMP #0201 - 0x54220004, // 01F2 LDINT R8 5 - 0x1C200E08, // 01F3 EQ R8 R7 R8 - 0x7822000B, // 01F4 JMPF R8 #0201 - 0x88200349, // 01F5 GETMBR R8 R1 K73 - 0x8C20113D, // 01F6 GETMET R8 R8 K61 - 0x7C200200, // 01F7 CALL R8 1 - 0x4C240000, // 01F8 LDNIL R9 - 0x1C241009, // 01F9 EQ R9 R8 R9 - 0x78260000, // 01FA JMPF R9 #01FC - 0x58200005, // 01FB LDCONST R8 K5 - 0x8C240706, // 01FC GETMET R9 R3 K6 - 0x882C0B0E, // 01FD GETMBR R11 R5 K14 - 0x5C301000, // 01FE MOVE R12 R8 - 0x7C240600, // 01FF CALL R9 3 - 0x80041200, // 0200 RET 1 R9 - 0x700201A7, // 0201 JMP #03AA - 0x5422003B, // 0202 LDINT R8 60 - 0x1C200C08, // 0203 EQ R8 R6 R8 - 0x7822003C, // 0204 JMPF R8 #0242 - 0x1C200F05, // 0205 EQ R8 R7 K5 - 0x78220012, // 0206 JMPF R8 #021A - 0x88200136, // 0207 GETMBR R8 R0 K54 - 0x8C20114A, // 0208 GETMET R8 R8 K74 - 0x7C200200, // 0209 CALL R8 1 - 0x88240136, // 020A GETMBR R9 R0 K54 - 0x8C24134B, // 020B GETMET R9 R9 K75 - 0x7C240200, // 020C CALL R9 1 - 0x78220004, // 020D JMPF R8 #0213 - 0x78260001, // 020E JMPF R9 #0211 - 0x5828000D, // 020F LDCONST R10 K13 - 0x70020000, // 0210 JMP #0212 - 0x58280009, // 0211 LDCONST R10 K9 - 0x70020000, // 0212 JMP #0214 - 0x58280005, // 0213 LDCONST R10 K5 - 0x8C2C0706, // 0214 GETMET R11 R3 K6 - 0x88340B0E, // 0215 GETMBR R13 R5 K14 - 0x5C381400, // 0216 MOVE R14 R10 - 0x7C2C0600, // 0217 CALL R11 3 - 0x80041600, // 0218 RET 1 R11 - 0x70020026, // 0219 JMP #0241 - 0x1C200F09, // 021A EQ R8 R7 K9 - 0x78220011, // 021B JMPF R8 #022E - 0x88200136, // 021C GETMBR R8 R0 K54 - 0x8820114C, // 021D GETMBR R8 R8 K76 - 0x4C240000, // 021E LDNIL R9 - 0x20241009, // 021F NE R9 R8 R9 - 0x78260006, // 0220 JMPF R9 #0228 - 0x8C240706, // 0221 GETMET R9 R3 K6 - 0x882C0B0C, // 0222 GETMBR R11 R5 K12 - 0x8C30113D, // 0223 GETMET R12 R8 K61 - 0x7C300200, // 0224 CALL R12 1 - 0x7C240600, // 0225 CALL R9 3 - 0x80041200, // 0226 RET 1 R9 - 0x70020004, // 0227 JMP #022D - 0x8C240706, // 0228 GETMET R9 R3 K6 - 0x882C0B18, // 0229 GETMBR R11 R5 K24 - 0x4C300000, // 022A LDNIL R12 - 0x7C240600, // 022B CALL R9 3 - 0x80041200, // 022C RET 1 R9 - 0x70020012, // 022D JMP #0241 - 0x1C200F0D, // 022E EQ R8 R7 K13 - 0x78220010, // 022F JMPF R8 #0241 - 0x88200136, // 0230 GETMBR R8 R0 K54 - 0x8820114C, // 0231 GETMBR R8 R8 K76 - 0x4C240000, // 0232 LDNIL R9 - 0x20241009, // 0233 NE R9 R8 R9 - 0x78260006, // 0234 JMPF R9 #023C - 0x8C240706, // 0235 GETMET R9 R3 K6 - 0x882C0B0C, // 0236 GETMBR R11 R5 K12 - 0x8C301142, // 0237 GETMET R12 R8 K66 - 0x7C300200, // 0238 CALL R12 1 - 0x7C240600, // 0239 CALL R9 3 - 0x80041200, // 023A RET 1 R9 - 0x70020004, // 023B JMP #0241 - 0x8C240706, // 023C GETMET R9 R3 K6 - 0x882C0B18, // 023D GETMBR R11 R5 K24 - 0x4C300000, // 023E LDNIL R12 - 0x7C240600, // 023F CALL R9 3 - 0x80041200, // 0240 RET 1 R9 - 0x70020167, // 0241 JMP #03AA - 0x54220027, // 0242 LDINT R8 40 - 0x1C200C08, // 0243 EQ R8 R6 R8 - 0x782200BA, // 0244 JMPF R8 #0300 - 0x8C200133, // 0245 GETMET R8 R0 K51 - 0x5C280400, // 0246 MOVE R10 R2 - 0x7C200400, // 0247 CALL R8 2 - 0x1C200F05, // 0248 EQ R8 R7 K5 - 0x78220005, // 0249 JMPF R8 #0250 - 0x8C200706, // 024A GETMET R8 R3 K6 - 0x88280B0C, // 024B GETMBR R10 R5 K12 - 0x582C0009, // 024C LDCONST R11 K9 - 0x7C200600, // 024D CALL R8 3 - 0x80041000, // 024E RET 1 R8 - 0x700200AE, // 024F JMP #02FF - 0x1C200F09, // 0250 EQ R8 R7 K9 + 0x4C300000, // 0170 LDNIL R12 + 0x1C30160C, // 0171 EQ R12 R11 R12 + 0x78320000, // 0172 JMPF R12 #0174 + 0x7001FFF5, // 0173 JMP #016A + 0x8C301115, // 0174 GETMET R12 R8 K21 + 0x4C380000, // 0175 LDNIL R14 + 0x7C300400, // 0176 CALL R12 2 + 0x8C34190B, // 0177 GETMET R13 R12 K11 + 0x583C0009, // 0178 LDCONST R15 K9 + 0x88400B3A, // 0179 GETMBR R16 R5 K58 + 0x8C44173B, // 017A GETMET R17 R11 K59 + 0x7C440200, // 017B CALL R17 1 + 0x7C340800, // 017C CALL R13 4 + 0x8C34190B, // 017D GETMET R13 R12 K11 + 0x583C000D, // 017E LDCONST R15 K13 + 0x88400B3A, // 017F GETMBR R16 R5 K58 + 0x8C44173C, // 0180 GETMET R17 R11 K60 + 0x7C440200, // 0181 CALL R17 1 + 0x7C340800, // 0182 CALL R13 4 + 0x8C34190B, // 0183 GETMET R13 R12 K11 + 0xB83E0200, // 0184 GETNGBL R15 K1 + 0x883C1F3D, // 0185 GETMBR R15 R15 K61 + 0x88400B0C, // 0186 GETMBR R16 R5 K12 + 0x8C44173E, // 0187 GETMET R17 R11 K62 + 0x7C440200, // 0188 CALL R17 1 + 0x7C340800, // 0189 CALL R13 4 + 0x7001FFDE, // 018A JMP #016A + 0x5828003F, // 018B LDCONST R10 K63 + 0xAC280200, // 018C CATCH R10 1 0 + 0xB0080000, // 018D RAISE 2 R0 R0 + 0x80041000, // 018E RET 1 R8 + 0x70020078, // 018F JMP #0209 + 0x1C200F09, // 0190 EQ R8 R7 K9 + 0x7822004D, // 0191 JMPF R8 #01E0 + 0x8C200B11, // 0192 GETMET R8 R5 K17 + 0x7C200200, // 0193 CALL R8 1 + 0x88240534, // 0194 GETMBR R9 R2 K52 + 0x78260005, // 0195 JMPF R9 #019C + 0x60240012, // 0196 GETGBL R9 G18 + 0x7C240000, // 0197 CALL R9 0 + 0x8C280335, // 0198 GETMET R10 R1 K53 + 0x7C280200, // 0199 CALL R10 1 + 0x4028120A, // 019A CONNECT R10 R9 R10 + 0x70020003, // 019B JMP #01A0 + 0x88240136, // 019C GETMBR R9 R0 K54 + 0x88241337, // 019D GETMBR R9 R9 K55 + 0x8C241338, // 019E GETMET R9 R9 K56 + 0x7C240200, // 019F CALL R9 1 + 0x60280010, // 01A0 GETGBL R10 G16 + 0x5C2C1200, // 01A1 MOVE R11 R9 + 0x7C280200, // 01A2 CALL R10 1 + 0xA8020036, // 01A3 EXBLK 0 #01DB + 0x5C2C1400, // 01A4 MOVE R11 R10 + 0x7C2C0000, // 01A5 CALL R11 0 + 0x4C300000, // 01A6 LDNIL R12 + 0x1C30160C, // 01A7 EQ R12 R11 R12 + 0x78320000, // 01A8 JMPF R12 #01AA + 0x7001FFF9, // 01A9 JMP #01A4 + 0x8C301739, // 01AA GETMET R12 R11 K57 + 0x7C300200, // 01AB CALL R12 1 + 0x78320000, // 01AC JMPF R12 #01AE + 0x7001FFF5, // 01AD JMP #01A4 + 0x8C300B40, // 01AE GETMET R12 R5 K64 + 0x8C381741, // 01AF GETMET R14 R11 K65 + 0x7C380200, // 01B0 CALL R14 1 + 0x7C300400, // 01B1 CALL R12 2 + 0x8C341115, // 01B2 GETMET R13 R8 K21 + 0x4C3C0000, // 01B3 LDNIL R15 + 0x7C340400, // 01B4 CALL R13 2 + 0x8C381B0B, // 01B5 GETMET R14 R13 K11 + 0x58400009, // 01B6 LDCONST R16 K9 + 0x88440B3A, // 01B7 GETMBR R17 R5 K58 + 0x8C481942, // 01B8 GETMET R18 R12 K66 + 0x54520008, // 01B9 LDINT R20 9 + 0x7C480400, // 01BA CALL R18 2 + 0x7C380800, // 01BB CALL R14 4 + 0x8C381B0B, // 01BC GETMET R14 R13 K11 + 0x5840000D, // 01BD LDCONST R16 K13 + 0x88440B0C, // 01BE GETMBR R17 R5 K12 + 0x8C481743, // 01BF GETMET R18 R11 K67 + 0x7C480200, // 01C0 CALL R18 1 + 0x7C380800, // 01C1 CALL R14 4 + 0x8C381B0B, // 01C2 GETMET R14 R13 K11 + 0x5840000F, // 01C3 LDCONST R16 K15 + 0x88440B07, // 01C4 GETMBR R17 R5 K7 + 0x8C481744, // 01C5 GETMET R18 R11 K68 + 0x7C480200, // 01C6 CALL R18 1 + 0x7C380800, // 01C7 CALL R14 4 + 0x8C381B0B, // 01C8 GETMET R14 R13 K11 + 0x54420003, // 01C9 LDINT R16 4 + 0x88440B07, // 01CA GETMBR R17 R5 K7 + 0x8C481745, // 01CB GETMET R18 R11 K69 + 0x7C480200, // 01CC CALL R18 1 + 0x7C380800, // 01CD CALL R14 4 + 0x8C381B0B, // 01CE GETMET R14 R13 K11 + 0x54420004, // 01CF LDINT R16 5 + 0x88440B16, // 01D0 GETMBR R17 R5 K22 + 0x8C481746, // 01D1 GETMET R18 R11 K70 + 0x7C480200, // 01D2 CALL R18 1 + 0x7C380800, // 01D3 CALL R14 4 + 0x8C381B0B, // 01D4 GETMET R14 R13 K11 + 0x544200FD, // 01D5 LDINT R16 254 + 0x88440B0C, // 01D6 GETMBR R17 R5 K12 + 0x8C48173E, // 01D7 GETMET R18 R11 K62 + 0x7C480200, // 01D8 CALL R18 1 + 0x7C380800, // 01D9 CALL R14 4 + 0x7001FFC8, // 01DA JMP #01A4 + 0x5828003F, // 01DB LDCONST R10 K63 + 0xAC280200, // 01DC CATCH R10 1 0 + 0xB0080000, // 01DD RAISE 2 R0 R0 + 0x80041000, // 01DE RET 1 R8 + 0x70020028, // 01DF JMP #0209 + 0x1C200F0D, // 01E0 EQ R8 R7 K13 + 0x78220007, // 01E1 JMPF R8 #01EA + 0x8C200706, // 01E2 GETMET R8 R3 K6 + 0x88280B0E, // 01E3 GETMBR R10 R5 K14 + 0xB82E0200, // 01E4 GETNGBL R11 K1 + 0x882C1747, // 01E5 GETMBR R11 R11 K71 + 0x882C1748, // 01E6 GETMBR R11 R11 K72 + 0x7C200600, // 01E7 CALL R8 3 + 0x80041000, // 01E8 RET 1 R8 + 0x7002001E, // 01E9 JMP #0209 + 0x1C200F0F, // 01EA EQ R8 R7 K15 + 0x78220009, // 01EB JMPF R8 #01F6 + 0x88200136, // 01EC GETMBR R8 R0 K54 + 0x88201137, // 01ED GETMBR R8 R8 K55 + 0x8C201149, // 01EE GETMET R8 R8 K73 + 0x7C200200, // 01EF CALL R8 1 + 0x8C240706, // 01F0 GETMET R9 R3 K6 + 0x882C0B0E, // 01F1 GETMBR R11 R5 K14 + 0x5C301000, // 01F2 MOVE R12 R8 + 0x7C240600, // 01F3 CALL R9 3 + 0x80041200, // 01F4 RET 1 R9 + 0x70020012, // 01F5 JMP #0209 + 0x54220003, // 01F6 LDINT R8 4 + 0x1C200E08, // 01F7 EQ R8 R7 R8 + 0x78220000, // 01F8 JMPF R8 #01FA + 0x7002000E, // 01F9 JMP #0209 + 0x54220004, // 01FA LDINT R8 5 + 0x1C200E08, // 01FB EQ R8 R7 R8 + 0x7822000B, // 01FC JMPF R8 #0209 + 0x8820034A, // 01FD GETMBR R8 R1 K74 + 0x8C20113E, // 01FE GETMET R8 R8 K62 + 0x7C200200, // 01FF CALL R8 1 + 0x4C240000, // 0200 LDNIL R9 + 0x1C241009, // 0201 EQ R9 R8 R9 + 0x78260000, // 0202 JMPF R9 #0204 + 0x58200005, // 0203 LDCONST R8 K5 + 0x8C240706, // 0204 GETMET R9 R3 K6 + 0x882C0B0E, // 0205 GETMBR R11 R5 K14 + 0x5C301000, // 0206 MOVE R12 R8 + 0x7C240600, // 0207 CALL R9 3 + 0x80041200, // 0208 RET 1 R9 + 0x700201B2, // 0209 JMP #03BD + 0x5422003B, // 020A LDINT R8 60 + 0x1C200C08, // 020B EQ R8 R6 R8 + 0x7822003C, // 020C JMPF R8 #024A + 0x1C200F05, // 020D EQ R8 R7 K5 + 0x78220012, // 020E JMPF R8 #0222 + 0x88200136, // 020F GETMBR R8 R0 K54 + 0x8C20114B, // 0210 GETMET R8 R8 K75 + 0x7C200200, // 0211 CALL R8 1 + 0x88240136, // 0212 GETMBR R9 R0 K54 + 0x8C24134C, // 0213 GETMET R9 R9 K76 + 0x7C240200, // 0214 CALL R9 1 + 0x78220004, // 0215 JMPF R8 #021B + 0x78260001, // 0216 JMPF R9 #0219 + 0x5828000D, // 0217 LDCONST R10 K13 + 0x70020000, // 0218 JMP #021A + 0x58280009, // 0219 LDCONST R10 K9 + 0x70020000, // 021A JMP #021C + 0x58280005, // 021B LDCONST R10 K5 + 0x8C2C0706, // 021C GETMET R11 R3 K6 + 0x88340B0E, // 021D GETMBR R13 R5 K14 + 0x5C381400, // 021E MOVE R14 R10 + 0x7C2C0600, // 021F CALL R11 3 + 0x80041600, // 0220 RET 1 R11 + 0x70020026, // 0221 JMP #0249 + 0x1C200F09, // 0222 EQ R8 R7 K9 + 0x78220011, // 0223 JMPF R8 #0236 + 0x88200136, // 0224 GETMBR R8 R0 K54 + 0x8820114D, // 0225 GETMBR R8 R8 K77 + 0x4C240000, // 0226 LDNIL R9 + 0x20241009, // 0227 NE R9 R8 R9 + 0x78260006, // 0228 JMPF R9 #0230 + 0x8C240706, // 0229 GETMET R9 R3 K6 + 0x882C0B0C, // 022A GETMBR R11 R5 K12 + 0x8C30113E, // 022B GETMET R12 R8 K62 + 0x7C300200, // 022C CALL R12 1 + 0x7C240600, // 022D CALL R9 3 + 0x80041200, // 022E RET 1 R9 + 0x70020004, // 022F JMP #0235 + 0x8C240706, // 0230 GETMET R9 R3 K6 + 0x882C0B18, // 0231 GETMBR R11 R5 K24 + 0x4C300000, // 0232 LDNIL R12 + 0x7C240600, // 0233 CALL R9 3 + 0x80041200, // 0234 RET 1 R9 + 0x70020012, // 0235 JMP #0249 + 0x1C200F0D, // 0236 EQ R8 R7 K13 + 0x78220010, // 0237 JMPF R8 #0249 + 0x88200136, // 0238 GETMBR R8 R0 K54 + 0x8820114D, // 0239 GETMBR R8 R8 K77 + 0x4C240000, // 023A LDNIL R9 + 0x20241009, // 023B NE R9 R8 R9 + 0x78260006, // 023C JMPF R9 #0244 + 0x8C240706, // 023D GETMET R9 R3 K6 + 0x882C0B0C, // 023E GETMBR R11 R5 K12 + 0x8C301143, // 023F GETMET R12 R8 K67 + 0x7C300200, // 0240 CALL R12 1 + 0x7C240600, // 0241 CALL R9 3 + 0x80041200, // 0242 RET 1 R9 + 0x70020004, // 0243 JMP #0249 + 0x8C240706, // 0244 GETMET R9 R3 K6 + 0x882C0B18, // 0245 GETMBR R11 R5 K24 + 0x4C300000, // 0246 LDNIL R12 + 0x7C240600, // 0247 CALL R9 3 + 0x80041200, // 0248 RET 1 R9 + 0x70020172, // 0249 JMP #03BD + 0x54220027, // 024A LDINT R8 40 + 0x1C200C08, // 024B EQ R8 R6 R8 + 0x782200BA, // 024C JMPF R8 #0308 + 0x8C200133, // 024D GETMET R8 R0 K51 + 0x5C280400, // 024E MOVE R10 R2 + 0x7C200400, // 024F CALL R8 2 + 0x1C200F05, // 0250 EQ R8 R7 K5 0x78220005, // 0251 JMPF R8 #0258 0x8C200706, // 0252 GETMET R8 R3 K6 - 0x88280B16, // 0253 GETMBR R10 R5 K22 - 0x582C004D, // 0254 LDCONST R11 K77 + 0x88280B0C, // 0253 GETMBR R10 R5 K12 + 0x582C0009, // 0254 LDCONST R11 K9 0x7C200600, // 0255 CALL R8 3 0x80041000, // 0256 RET 1 R8 - 0x700200A6, // 0257 JMP #02FF - 0x1C200F0D, // 0258 EQ R8 R7 K13 - 0x78220006, // 0259 JMPF R8 #0261 + 0x700200AE, // 0257 JMP #0307 + 0x1C200F09, // 0258 EQ R8 R7 K9 + 0x78220005, // 0259 JMPF R8 #0260 0x8C200706, // 025A GETMET R8 R3 K6 - 0x88280B0C, // 025B GETMBR R10 R5 K12 - 0x882C0136, // 025C GETMBR R11 R0 K54 - 0x882C174E, // 025D GETMBR R11 R11 K78 - 0x7C200600, // 025E CALL R8 3 - 0x80041000, // 025F RET 1 R8 - 0x7002009D, // 0260 JMP #02FF - 0x1C200F0F, // 0261 EQ R8 R7 K15 - 0x7822000A, // 0262 JMPF R8 #026E - 0x8C200706, // 0263 GETMET R8 R3 K6 - 0x88280B16, // 0264 GETMBR R10 R5 K22 - 0xB82E2400, // 0265 GETNGBL R11 K18 - 0x8C2C1726, // 0266 GETMET R11 R11 K38 - 0x5834004F, // 0267 LDCONST R13 K79 - 0x50380200, // 0268 LDBOOL R14 1 0 - 0x7C2C0600, // 0269 CALL R11 3 - 0x942C174F, // 026A GETIDX R11 R11 K79 - 0x7C200600, // 026B CALL R8 3 - 0x80041000, // 026C RET 1 R8 - 0x70020090, // 026D JMP #02FF - 0x54220003, // 026E LDINT R8 4 - 0x1C200E08, // 026F EQ R8 R7 R8 - 0x78220005, // 0270 JMPF R8 #0277 - 0x8C200706, // 0271 GETMET R8 R3 K6 - 0x88280B0C, // 0272 GETMBR R10 R5 K12 - 0x542E7FFF, // 0273 LDINT R11 32768 - 0x7C200600, // 0274 CALL R8 3 - 0x80041000, // 0275 RET 1 R8 - 0x70020087, // 0276 JMP #02FF - 0x54220004, // 0277 LDINT R8 5 - 0x1C200E08, // 0278 EQ R8 R7 R8 - 0x7822000A, // 0279 JMPF R8 #0285 - 0x8C200706, // 027A GETMET R8 R3 K6 - 0x88280B16, // 027B GETMBR R10 R5 K22 - 0xB82E2400, // 027C GETNGBL R11 K18 - 0x8C2C1726, // 027D GETMET R11 R11 K38 - 0x58340050, // 027E LDCONST R13 K80 - 0x50380200, // 027F LDBOOL R14 1 0 - 0x7C2C0600, // 0280 CALL R11 3 - 0x942C1751, // 0281 GETIDX R11 R11 K81 - 0x7C200600, // 0282 CALL R8 3 - 0x80041000, // 0283 RET 1 R8 - 0x70020079, // 0284 JMP #02FF - 0x54220005, // 0285 LDINT R8 6 - 0x1C200E08, // 0286 EQ R8 R7 R8 - 0x78220005, // 0287 JMPF R8 #028E - 0x8C200706, // 0288 GETMET R8 R3 K6 - 0x88280B16, // 0289 GETMBR R10 R5 K22 - 0x582C0052, // 028A LDCONST R11 K82 - 0x7C200600, // 028B CALL R8 3 - 0x80041000, // 028C RET 1 R8 - 0x70020070, // 028D JMP #02FF - 0x54220006, // 028E LDINT R8 7 - 0x1C200E08, // 028F EQ R8 R7 R8 - 0x78220005, // 0290 JMPF R8 #0297 - 0x8C200706, // 0291 GETMET R8 R3 K6 - 0x88280B0C, // 0292 GETMBR R10 R5 K12 - 0x582C0005, // 0293 LDCONST R11 K5 - 0x7C200600, // 0294 CALL R8 3 - 0x80041000, // 0295 RET 1 R8 - 0x70020067, // 0296 JMP #02FF - 0x54220007, // 0297 LDINT R8 8 - 0x1C200E08, // 0298 EQ R8 R7 R8 - 0x7822000B, // 0299 JMPF R8 #02A6 - 0x8C200706, // 029A GETMET R8 R3 K6 - 0x88280B16, // 029B GETMBR R10 R5 K22 - 0xB82E2400, // 029C GETNGBL R11 K18 - 0x8C2C1726, // 029D GETMET R11 R11 K38 - 0x58340053, // 029E LDCONST R13 K83 - 0x50380200, // 029F LDBOOL R14 1 0 - 0x7C2C0600, // 02A0 CALL R11 3 - 0x942C1754, // 02A1 GETIDX R11 R11 K84 - 0x942C1755, // 02A2 GETIDX R11 R11 K85 - 0x7C200600, // 02A3 CALL R8 3 - 0x80041000, // 02A4 RET 1 R8 - 0x70020058, // 02A5 JMP #02FF - 0x54220008, // 02A6 LDINT R8 9 - 0x1C200E08, // 02A7 EQ R8 R7 R8 - 0x78220005, // 02A8 JMPF R8 #02AF - 0x8C200706, // 02A9 GETMET R8 R3 K6 - 0x88280B0C, // 02AA GETMBR R10 R5 K12 - 0x582C0009, // 02AB LDCONST R11 K9 - 0x7C200600, // 02AC CALL R8 3 - 0x80041000, // 02AD RET 1 R8 - 0x7002004F, // 02AE JMP #02FF - 0x54220009, // 02AF LDINT R8 10 - 0x1C200E08, // 02B0 EQ R8 R7 R8 - 0x78220015, // 02B1 JMPF R8 #02C8 - 0xB8222400, // 02B2 GETNGBL R8 K18 - 0x8C201126, // 02B3 GETMET R8 R8 K38 - 0x58280053, // 02B4 LDCONST R10 K83 - 0x502C0200, // 02B5 LDBOOL R11 1 0 - 0x7C200600, // 02B6 CALL R8 3 - 0x94201154, // 02B7 GETIDX R8 R8 K84 - 0x94201156, // 02B8 GETIDX R8 R8 K86 - 0x8C24091B, // 02B9 GETMET R9 R4 K27 - 0x5C2C1000, // 02BA MOVE R11 R8 - 0x58300057, // 02BB LDCONST R12 K87 - 0x7C240600, // 02BC CALL R9 3 - 0x24281305, // 02BD GT R10 R9 K5 - 0x782A0002, // 02BE JMPF R10 #02C2 - 0x04281309, // 02BF SUB R10 R9 K9 - 0x402A0A0A, // 02C0 CONNECT R10 K5 R10 - 0x9420100A, // 02C1 GETIDX R8 R8 R10 - 0x8C280706, // 02C2 GETMET R10 R3 K6 - 0x88300B16, // 02C3 GETMBR R12 R5 K22 - 0x5C341000, // 02C4 MOVE R13 R8 - 0x7C280600, // 02C5 CALL R10 3 - 0x80041400, // 02C6 RET 1 R10 - 0x70020036, // 02C7 JMP #02FF - 0x5422000E, // 02C8 LDINT R8 15 - 0x1C200E08, // 02C9 EQ R8 R7 R8 - 0x7822000B, // 02CA JMPF R8 #02D7 - 0x8C200706, // 02CB GETMET R8 R3 K6 - 0x88280B16, // 02CC GETMBR R10 R5 K22 - 0xB82E2400, // 02CD GETNGBL R11 K18 - 0x8C2C1725, // 02CE GETMET R11 R11 K37 - 0x7C2C0200, // 02CF CALL R11 1 - 0x8C2C171B, // 02D0 GETMET R11 R11 K27 - 0x5834001C, // 02D1 LDCONST R13 K28 - 0x5838001D, // 02D2 LDCONST R14 K29 - 0x7C2C0600, // 02D3 CALL R11 3 - 0x7C200600, // 02D4 CALL R8 3 - 0x80041000, // 02D5 RET 1 R8 - 0x70020027, // 02D6 JMP #02FF - 0x54220010, // 02D7 LDINT R8 17 - 0x1C200E08, // 02D8 EQ R8 R7 R8 - 0x78220005, // 02D9 JMPF R8 #02E0 - 0x8C200706, // 02DA GETMET R8 R3 K6 - 0x88280B10, // 02DB GETMBR R10 R5 K16 - 0x582C0009, // 02DC LDCONST R11 K9 - 0x7C200600, // 02DD CALL R8 3 - 0x80041000, // 02DE RET 1 R8 - 0x7002001E, // 02DF JMP #02FF - 0x54220011, // 02E0 LDINT R8 18 - 0x1C200E08, // 02E1 EQ R8 R7 R8 - 0x7822000B, // 02E2 JMPF R8 #02EF - 0x8C200706, // 02E3 GETMET R8 R3 K6 - 0x88280B16, // 02E4 GETMBR R10 R5 K22 - 0xB82E2400, // 02E5 GETNGBL R11 K18 - 0x8C2C1725, // 02E6 GETMET R11 R11 K37 - 0x7C2C0200, // 02E7 CALL R11 1 - 0x8C2C171B, // 02E8 GETMET R11 R11 K27 - 0x5834001C, // 02E9 LDCONST R13 K28 - 0x5838001D, // 02EA LDCONST R14 K29 - 0x7C2C0600, // 02EB CALL R11 3 - 0x7C200600, // 02EC CALL R8 3 - 0x80041000, // 02ED RET 1 R8 - 0x7002000F, // 02EE JMP #02FF - 0x54220012, // 02EF LDINT R8 19 - 0x1C200E08, // 02F0 EQ R8 R7 R8 - 0x7822000C, // 02F1 JMPF R8 #02FF - 0x8C200B0A, // 02F2 GETMET R8 R5 K10 - 0x7C200200, // 02F3 CALL R8 1 - 0x8C24110B, // 02F4 GETMET R9 R8 K11 - 0x582C0005, // 02F5 LDCONST R11 K5 - 0x88300B0C, // 02F6 GETMBR R12 R5 K12 - 0x5834000F, // 02F7 LDCONST R13 K15 - 0x7C240800, // 02F8 CALL R9 4 - 0x8C24110B, // 02F9 GETMET R9 R8 K11 - 0x582C0009, // 02FA LDCONST R11 K9 - 0x88300B0C, // 02FB GETMBR R12 R5 K12 - 0x5834000F, // 02FC LDCONST R13 K15 - 0x7C240800, // 02FD CALL R9 4 - 0x80041000, // 02FE RET 1 R8 - 0x700200A9, // 02FF JMP #03AA - 0x5422003E, // 0300 LDINT R8 63 - 0x1C200C08, // 0301 EQ R8 R6 R8 - 0x78220000, // 0302 JMPF R8 #0304 - 0x700200A5, // 0303 JMP #03AA - 0x54220029, // 0304 LDINT R8 42 - 0x1C200C08, // 0305 EQ R8 R6 R8 - 0x7822001D, // 0306 JMPF R8 #0325 - 0x1C200F05, // 0307 EQ R8 R7 K5 - 0x78220003, // 0308 JMPF R8 #030D - 0x8C200B11, // 0309 GETMET R8 R5 K17 - 0x7C200200, // 030A CALL R8 1 - 0x80041000, // 030B RET 1 R8 - 0x70020016, // 030C JMP #0324 - 0x1C200F09, // 030D EQ R8 R7 K9 - 0x78220005, // 030E JMPF R8 #0315 - 0x8C200706, // 030F GETMET R8 R3 K6 - 0x88280B10, // 0310 GETMBR R10 R5 K16 - 0x582C0005, // 0311 LDCONST R11 K5 - 0x7C200600, // 0312 CALL R8 3 + 0x88280B16, // 025B GETMBR R10 R5 K22 + 0x582C004E, // 025C LDCONST R11 K78 + 0x7C200600, // 025D CALL R8 3 + 0x80041000, // 025E RET 1 R8 + 0x700200A6, // 025F JMP #0307 + 0x1C200F0D, // 0260 EQ R8 R7 K13 + 0x78220006, // 0261 JMPF R8 #0269 + 0x8C200706, // 0262 GETMET R8 R3 K6 + 0x88280B0C, // 0263 GETMBR R10 R5 K12 + 0x882C0136, // 0264 GETMBR R11 R0 K54 + 0x882C174F, // 0265 GETMBR R11 R11 K79 + 0x7C200600, // 0266 CALL R8 3 + 0x80041000, // 0267 RET 1 R8 + 0x7002009D, // 0268 JMP #0307 + 0x1C200F0F, // 0269 EQ R8 R7 K15 + 0x7822000A, // 026A JMPF R8 #0276 + 0x8C200706, // 026B GETMET R8 R3 K6 + 0x88280B16, // 026C GETMBR R10 R5 K22 + 0xB82E2400, // 026D GETNGBL R11 K18 + 0x8C2C1726, // 026E GETMET R11 R11 K38 + 0x58340050, // 026F LDCONST R13 K80 + 0x50380200, // 0270 LDBOOL R14 1 0 + 0x7C2C0600, // 0271 CALL R11 3 + 0x942C1750, // 0272 GETIDX R11 R11 K80 + 0x7C200600, // 0273 CALL R8 3 + 0x80041000, // 0274 RET 1 R8 + 0x70020090, // 0275 JMP #0307 + 0x54220003, // 0276 LDINT R8 4 + 0x1C200E08, // 0277 EQ R8 R7 R8 + 0x78220005, // 0278 JMPF R8 #027F + 0x8C200706, // 0279 GETMET R8 R3 K6 + 0x88280B0C, // 027A GETMBR R10 R5 K12 + 0x542E7FFF, // 027B LDINT R11 32768 + 0x7C200600, // 027C CALL R8 3 + 0x80041000, // 027D RET 1 R8 + 0x70020087, // 027E JMP #0307 + 0x54220004, // 027F LDINT R8 5 + 0x1C200E08, // 0280 EQ R8 R7 R8 + 0x7822000A, // 0281 JMPF R8 #028D + 0x8C200706, // 0282 GETMET R8 R3 K6 + 0x88280B16, // 0283 GETMBR R10 R5 K22 + 0xB82E2400, // 0284 GETNGBL R11 K18 + 0x8C2C1726, // 0285 GETMET R11 R11 K38 + 0x58340051, // 0286 LDCONST R13 K81 + 0x50380200, // 0287 LDBOOL R14 1 0 + 0x7C2C0600, // 0288 CALL R11 3 + 0x942C1752, // 0289 GETIDX R11 R11 K82 + 0x7C200600, // 028A CALL R8 3 + 0x80041000, // 028B RET 1 R8 + 0x70020079, // 028C JMP #0307 + 0x54220005, // 028D LDINT R8 6 + 0x1C200E08, // 028E EQ R8 R7 R8 + 0x78220005, // 028F JMPF R8 #0296 + 0x8C200706, // 0290 GETMET R8 R3 K6 + 0x88280B16, // 0291 GETMBR R10 R5 K22 + 0x582C0053, // 0292 LDCONST R11 K83 + 0x7C200600, // 0293 CALL R8 3 + 0x80041000, // 0294 RET 1 R8 + 0x70020070, // 0295 JMP #0307 + 0x54220006, // 0296 LDINT R8 7 + 0x1C200E08, // 0297 EQ R8 R7 R8 + 0x78220005, // 0298 JMPF R8 #029F + 0x8C200706, // 0299 GETMET R8 R3 K6 + 0x88280B0C, // 029A GETMBR R10 R5 K12 + 0x582C0005, // 029B LDCONST R11 K5 + 0x7C200600, // 029C CALL R8 3 + 0x80041000, // 029D RET 1 R8 + 0x70020067, // 029E JMP #0307 + 0x54220007, // 029F LDINT R8 8 + 0x1C200E08, // 02A0 EQ R8 R7 R8 + 0x7822000B, // 02A1 JMPF R8 #02AE + 0x8C200706, // 02A2 GETMET R8 R3 K6 + 0x88280B16, // 02A3 GETMBR R10 R5 K22 + 0xB82E2400, // 02A4 GETNGBL R11 K18 + 0x8C2C1726, // 02A5 GETMET R11 R11 K38 + 0x58340054, // 02A6 LDCONST R13 K84 + 0x50380200, // 02A7 LDBOOL R14 1 0 + 0x7C2C0600, // 02A8 CALL R11 3 + 0x942C1755, // 02A9 GETIDX R11 R11 K85 + 0x942C1756, // 02AA GETIDX R11 R11 K86 + 0x7C200600, // 02AB CALL R8 3 + 0x80041000, // 02AC RET 1 R8 + 0x70020058, // 02AD JMP #0307 + 0x54220008, // 02AE LDINT R8 9 + 0x1C200E08, // 02AF EQ R8 R7 R8 + 0x78220005, // 02B0 JMPF R8 #02B7 + 0x8C200706, // 02B1 GETMET R8 R3 K6 + 0x88280B0C, // 02B2 GETMBR R10 R5 K12 + 0x582C0009, // 02B3 LDCONST R11 K9 + 0x7C200600, // 02B4 CALL R8 3 + 0x80041000, // 02B5 RET 1 R8 + 0x7002004F, // 02B6 JMP #0307 + 0x54220009, // 02B7 LDINT R8 10 + 0x1C200E08, // 02B8 EQ R8 R7 R8 + 0x78220015, // 02B9 JMPF R8 #02D0 + 0xB8222400, // 02BA GETNGBL R8 K18 + 0x8C201126, // 02BB GETMET R8 R8 K38 + 0x58280054, // 02BC LDCONST R10 K84 + 0x502C0200, // 02BD LDBOOL R11 1 0 + 0x7C200600, // 02BE CALL R8 3 + 0x94201155, // 02BF GETIDX R8 R8 K85 + 0x94201157, // 02C0 GETIDX R8 R8 K87 + 0x8C24091B, // 02C1 GETMET R9 R4 K27 + 0x5C2C1000, // 02C2 MOVE R11 R8 + 0x58300058, // 02C3 LDCONST R12 K88 + 0x7C240600, // 02C4 CALL R9 3 + 0x24281305, // 02C5 GT R10 R9 K5 + 0x782A0002, // 02C6 JMPF R10 #02CA + 0x04281309, // 02C7 SUB R10 R9 K9 + 0x402A0A0A, // 02C8 CONNECT R10 K5 R10 + 0x9420100A, // 02C9 GETIDX R8 R8 R10 + 0x8C280706, // 02CA GETMET R10 R3 K6 + 0x88300B16, // 02CB GETMBR R12 R5 K22 + 0x5C341000, // 02CC MOVE R13 R8 + 0x7C280600, // 02CD CALL R10 3 + 0x80041400, // 02CE RET 1 R10 + 0x70020036, // 02CF JMP #0307 + 0x5422000E, // 02D0 LDINT R8 15 + 0x1C200E08, // 02D1 EQ R8 R7 R8 + 0x7822000B, // 02D2 JMPF R8 #02DF + 0x8C200706, // 02D3 GETMET R8 R3 K6 + 0x88280B16, // 02D4 GETMBR R10 R5 K22 + 0xB82E2400, // 02D5 GETNGBL R11 K18 + 0x8C2C1725, // 02D6 GETMET R11 R11 K37 + 0x7C2C0200, // 02D7 CALL R11 1 + 0x8C2C171B, // 02D8 GETMET R11 R11 K27 + 0x5834001C, // 02D9 LDCONST R13 K28 + 0x5838001D, // 02DA LDCONST R14 K29 + 0x7C2C0600, // 02DB CALL R11 3 + 0x7C200600, // 02DC CALL R8 3 + 0x80041000, // 02DD RET 1 R8 + 0x70020027, // 02DE JMP #0307 + 0x54220010, // 02DF LDINT R8 17 + 0x1C200E08, // 02E0 EQ R8 R7 R8 + 0x78220005, // 02E1 JMPF R8 #02E8 + 0x8C200706, // 02E2 GETMET R8 R3 K6 + 0x88280B10, // 02E3 GETMBR R10 R5 K16 + 0x582C0009, // 02E4 LDCONST R11 K9 + 0x7C200600, // 02E5 CALL R8 3 + 0x80041000, // 02E6 RET 1 R8 + 0x7002001E, // 02E7 JMP #0307 + 0x54220011, // 02E8 LDINT R8 18 + 0x1C200E08, // 02E9 EQ R8 R7 R8 + 0x7822000B, // 02EA JMPF R8 #02F7 + 0x8C200706, // 02EB GETMET R8 R3 K6 + 0x88280B16, // 02EC GETMBR R10 R5 K22 + 0xB82E2400, // 02ED GETNGBL R11 K18 + 0x8C2C1725, // 02EE GETMET R11 R11 K37 + 0x7C2C0200, // 02EF CALL R11 1 + 0x8C2C171B, // 02F0 GETMET R11 R11 K27 + 0x5834001C, // 02F1 LDCONST R13 K28 + 0x5838001D, // 02F2 LDCONST R14 K29 + 0x7C2C0600, // 02F3 CALL R11 3 + 0x7C200600, // 02F4 CALL R8 3 + 0x80041000, // 02F5 RET 1 R8 + 0x7002000F, // 02F6 JMP #0307 + 0x54220012, // 02F7 LDINT R8 19 + 0x1C200E08, // 02F8 EQ R8 R7 R8 + 0x7822000C, // 02F9 JMPF R8 #0307 + 0x8C200B0A, // 02FA GETMET R8 R5 K10 + 0x7C200200, // 02FB CALL R8 1 + 0x8C24110B, // 02FC GETMET R9 R8 K11 + 0x582C0005, // 02FD LDCONST R11 K5 + 0x88300B0C, // 02FE GETMBR R12 R5 K12 + 0x5834000F, // 02FF LDCONST R13 K15 + 0x7C240800, // 0300 CALL R9 4 + 0x8C24110B, // 0301 GETMET R9 R8 K11 + 0x582C0009, // 0302 LDCONST R11 K9 + 0x88300B0C, // 0303 GETMBR R12 R5 K12 + 0x5834000F, // 0304 LDCONST R13 K15 + 0x7C240800, // 0305 CALL R9 4 + 0x80041000, // 0306 RET 1 R8 + 0x700200B4, // 0307 JMP #03BD + 0x5422003E, // 0308 LDINT R8 63 + 0x1C200C08, // 0309 EQ R8 R6 R8 + 0x78220000, // 030A JMPF R8 #030C + 0x700200B0, // 030B JMP #03BD + 0x54220029, // 030C LDINT R8 42 + 0x1C200C08, // 030D EQ R8 R6 R8 + 0x7822001D, // 030E JMPF R8 #032D + 0x1C200F05, // 030F EQ R8 R7 K5 + 0x78220003, // 0310 JMPF R8 #0315 + 0x8C200B11, // 0311 GETMET R8 R5 K17 + 0x7C200200, // 0312 CALL R8 1 0x80041000, // 0313 RET 1 R8 - 0x7002000E, // 0314 JMP #0324 - 0x1C200F0D, // 0315 EQ R8 R7 K13 + 0x70020016, // 0314 JMP #032C + 0x1C200F09, // 0315 EQ R8 R7 K9 0x78220005, // 0316 JMPF R8 #031D 0x8C200706, // 0317 GETMET R8 R3 K6 - 0x88280B0E, // 0318 GETMBR R10 R5 K14 - 0x582C0009, // 0319 LDCONST R11 K9 + 0x88280B10, // 0318 GETMBR R10 R5 K16 + 0x582C0005, // 0319 LDCONST R11 K5 0x7C200600, // 031A CALL R8 3 0x80041000, // 031B RET 1 R8 - 0x70020006, // 031C JMP #0324 - 0x1C200F0F, // 031D EQ R8 R7 K15 - 0x78220004, // 031E JMPF R8 #0324 + 0x7002000E, // 031C JMP #032C + 0x1C200F0D, // 031D EQ R8 R7 K13 + 0x78220005, // 031E JMPF R8 #0325 0x8C200706, // 031F GETMET R8 R3 K6 - 0x88280B18, // 0320 GETMBR R10 R5 K24 - 0x4C2C0000, // 0321 LDNIL R11 + 0x88280B0E, // 0320 GETMBR R10 R5 K14 + 0x582C0009, // 0321 LDCONST R11 K9 0x7C200600, // 0322 CALL R8 3 0x80041000, // 0323 RET 1 R8 - 0x70020084, // 0324 JMP #03AA - 0x5422002A, // 0325 LDINT R8 43 - 0x1C200C08, // 0326 EQ R8 R6 R8 - 0x78220016, // 0327 JMPF R8 #033F - 0x1C200F05, // 0328 EQ R8 R7 K5 - 0x78220007, // 0329 JMPF R8 #0332 - 0x8C200706, // 032A GETMET R8 R3 K6 - 0x88280B16, // 032B GETMBR R10 R5 K22 - 0xB82E2400, // 032C GETNGBL R11 K18 - 0x8C2C1758, // 032D GETMET R11 R11 K88 - 0x7C2C0200, // 032E CALL R11 1 - 0x7C200600, // 032F CALL R8 3 - 0x80041000, // 0330 RET 1 R8 - 0x7002000B, // 0331 JMP #033E - 0x1C200F09, // 0332 EQ R8 R7 K9 - 0x78220009, // 0333 JMPF R8 #033E - 0x8C200B11, // 0334 GETMET R8 R5 K17 - 0x7C200200, // 0335 CALL R8 1 - 0x8C24110B, // 0336 GETMET R9 R8 K11 - 0x4C2C0000, // 0337 LDNIL R11 - 0x88300B16, // 0338 GETMBR R12 R5 K22 - 0xB8362400, // 0339 GETNGBL R13 K18 - 0x8C341B58, // 033A GETMET R13 R13 K88 - 0x7C340200, // 033B CALL R13 1 - 0x7C240800, // 033C CALL R9 4 - 0x80041000, // 033D RET 1 R8 - 0x7002006A, // 033E JMP #03AA - 0x5422002B, // 033F LDINT R8 44 - 0x1C200C08, // 0340 EQ R8 R6 R8 - 0x7822001C, // 0341 JMPF R8 #035F - 0x1C200F05, // 0342 EQ R8 R7 K5 - 0x78220005, // 0343 JMPF R8 #034A - 0x8C200706, // 0344 GETMET R8 R3 K6 - 0x88280B0E, // 0345 GETMBR R10 R5 K14 - 0x582C0009, // 0346 LDCONST R11 K9 - 0x7C200600, // 0347 CALL R8 3 - 0x80041000, // 0348 RET 1 R8 - 0x70020013, // 0349 JMP #035E - 0x1C200F09, // 034A EQ R8 R7 K9 + 0x70020006, // 0324 JMP #032C + 0x1C200F0F, // 0325 EQ R8 R7 K15 + 0x78220004, // 0326 JMPF R8 #032C + 0x8C200706, // 0327 GETMET R8 R3 K6 + 0x88280B18, // 0328 GETMBR R10 R5 K24 + 0x4C2C0000, // 0329 LDNIL R11 + 0x7C200600, // 032A CALL R8 3 + 0x80041000, // 032B RET 1 R8 + 0x7002008F, // 032C JMP #03BD + 0x5422002A, // 032D LDINT R8 43 + 0x1C200C08, // 032E EQ R8 R6 R8 + 0x78220016, // 032F JMPF R8 #0347 + 0x1C200F05, // 0330 EQ R8 R7 K5 + 0x78220007, // 0331 JMPF R8 #033A + 0x8C200706, // 0332 GETMET R8 R3 K6 + 0x88280B16, // 0333 GETMBR R10 R5 K22 + 0xB82E2400, // 0334 GETNGBL R11 K18 + 0x8C2C1759, // 0335 GETMET R11 R11 K89 + 0x7C2C0200, // 0336 CALL R11 1 + 0x7C200600, // 0337 CALL R8 3 + 0x80041000, // 0338 RET 1 R8 + 0x7002000B, // 0339 JMP #0346 + 0x1C200F09, // 033A EQ R8 R7 K9 + 0x78220009, // 033B JMPF R8 #0346 + 0x8C200B11, // 033C GETMET R8 R5 K17 + 0x7C200200, // 033D CALL R8 1 + 0x8C24110B, // 033E GETMET R9 R8 K11 + 0x4C2C0000, // 033F LDNIL R11 + 0x88300B16, // 0340 GETMBR R12 R5 K22 + 0xB8362400, // 0341 GETNGBL R13 K18 + 0x8C341B59, // 0342 GETMET R13 R13 K89 + 0x7C340200, // 0343 CALL R13 1 + 0x7C240800, // 0344 CALL R9 4 + 0x80041000, // 0345 RET 1 R8 + 0x70020075, // 0346 JMP #03BD + 0x5422002B, // 0347 LDINT R8 44 + 0x1C200C08, // 0348 EQ R8 R6 R8 + 0x7822001C, // 0349 JMPF R8 #0367 + 0x1C200F05, // 034A EQ R8 R7 K5 0x78220005, // 034B JMPF R8 #0352 0x8C200706, // 034C GETMET R8 R3 K6 0x88280B0E, // 034D GETMBR R10 R5 K14 - 0x542E0003, // 034E LDINT R11 4 + 0x582C0009, // 034E LDCONST R11 K9 0x7C200600, // 034F CALL R8 3 0x80041000, // 0350 RET 1 R8 - 0x7002000B, // 0351 JMP #035E - 0x1C200F0D, // 0352 EQ R8 R7 K13 - 0x78220009, // 0353 JMPF R8 #035E - 0x8C200B11, // 0354 GETMET R8 R5 K17 - 0x7C200200, // 0355 CALL R8 1 - 0x8C24110B, // 0356 GETMET R9 R8 K11 - 0x4C2C0000, // 0357 LDNIL R11 - 0x8C300B59, // 0358 GETMET R12 R5 K89 - 0x88380B0E, // 0359 GETMBR R14 R5 K14 - 0x543E0003, // 035A LDINT R15 4 - 0x7C300600, // 035B CALL R12 3 - 0x7C240600, // 035C CALL R9 3 - 0x80041000, // 035D RET 1 R8 - 0x7002004A, // 035E JMP #03AA - 0x54220030, // 035F LDINT R8 49 - 0x1C200C08, // 0360 EQ R8 R6 R8 - 0x78220010, // 0361 JMPF R8 #0373 - 0x1C200F0F, // 0362 EQ R8 R7 K15 - 0x78220005, // 0363 JMPF R8 #036A - 0x8C200706, // 0364 GETMET R8 R3 K6 - 0x88280B0E, // 0365 GETMBR R10 R5 K14 - 0x542E001D, // 0366 LDINT R11 30 - 0x7C200600, // 0367 CALL R8 3 - 0x80041000, // 0368 RET 1 R8 - 0x70020007, // 0369 JMP #0372 - 0x5422FFFB, // 036A LDINT R8 65532 - 0x1C200E08, // 036B EQ R8 R7 R8 - 0x78220004, // 036C JMPF R8 #0372 - 0x8C200706, // 036D GETMET R8 R3 K6 - 0x88280B2A, // 036E GETMBR R10 R5 K42 - 0x542E0003, // 036F LDINT R11 4 - 0x7C200600, // 0370 CALL R8 3 - 0x80041000, // 0371 RET 1 R8 - 0x70020036, // 0372 JMP #03AA - 0x5422001C, // 0373 LDINT R8 29 - 0x1C200C08, // 0374 EQ R8 R6 R8 - 0x7822002A, // 0375 JMPF R8 #03A1 - 0x1C200F0F, // 0376 EQ R8 R7 K15 - 0x7822001E, // 0377 JMPF R8 #0397 - 0x8C200B11, // 0378 GETMET R8 R5 K17 - 0x7C200200, // 0379 CALL R8 1 - 0x88240136, // 037A GETMBR R9 R0 K54 - 0x8C24135A, // 037B GETMET R9 R9 K90 - 0x502C0200, // 037C LDBOOL R11 1 0 - 0x7C240400, // 037D CALL R9 2 - 0x88280136, // 037E GETMBR R10 R0 K54 - 0x8828155B, // 037F GETMBR R10 R10 K91 - 0x602C0010, // 0380 GETGBL R11 G16 - 0x5C301200, // 0381 MOVE R12 R9 - 0x7C2C0200, // 0382 CALL R11 1 - 0xA802000D, // 0383 EXBLK 0 #0392 - 0x5C301600, // 0384 MOVE R12 R11 - 0x7C300000, // 0385 CALL R12 0 - 0x5C341400, // 0386 MOVE R13 R10 - 0x78360003, // 0387 JMPF R13 #038C - 0xB8360200, // 0388 GETNGBL R13 K1 - 0x88341B3C, // 0389 GETMBR R13 R13 K60 - 0x1434180D, // 038A LT R13 R12 R13 - 0x78360004, // 038B JMPF R13 #0391 - 0x8C34110B, // 038C GETMET R13 R8 K11 - 0x4C3C0000, // 038D LDNIL R15 - 0x88400B0C, // 038E GETMBR R16 R5 K12 - 0x5C441800, // 038F MOVE R17 R12 - 0x7C340800, // 0390 CALL R13 4 - 0x7001FFF1, // 0391 JMP #0384 - 0x582C003E, // 0392 LDCONST R11 K62 - 0xAC2C0200, // 0393 CATCH R11 1 0 - 0xB0080000, // 0394 RAISE 2 R0 R0 - 0x80041000, // 0395 RET 1 R8 - 0x70020008, // 0396 JMP #03A0 - 0x60200003, // 0397 GETGBL R8 G3 - 0x5C240000, // 0398 MOVE R9 R0 - 0x7C200200, // 0399 CALL R8 1 - 0x8C20115C, // 039A GETMET R8 R8 K92 - 0x5C280200, // 039B MOVE R10 R1 - 0x5C2C0400, // 039C MOVE R11 R2 - 0x5C300600, // 039D MOVE R12 R3 - 0x7C200800, // 039E CALL R8 4 - 0x80041000, // 039F RET 1 R8 - 0x70020008, // 03A0 JMP #03AA - 0x60200003, // 03A1 GETGBL R8 G3 - 0x5C240000, // 03A2 MOVE R9 R0 - 0x7C200200, // 03A3 CALL R8 1 - 0x8C20115C, // 03A4 GETMET R8 R8 K92 - 0x5C280200, // 03A5 MOVE R10 R1 - 0x5C2C0400, // 03A6 MOVE R11 R2 - 0x5C300600, // 03A7 MOVE R12 R3 - 0x7C200800, // 03A8 CALL R8 4 - 0x80041000, // 03A9 RET 1 R8 - 0x80000000, // 03AA RET 0 + 0x70020013, // 0351 JMP #0366 + 0x1C200F09, // 0352 EQ R8 R7 K9 + 0x78220005, // 0353 JMPF R8 #035A + 0x8C200706, // 0354 GETMET R8 R3 K6 + 0x88280B0E, // 0355 GETMBR R10 R5 K14 + 0x542E0003, // 0356 LDINT R11 4 + 0x7C200600, // 0357 CALL R8 3 + 0x80041000, // 0358 RET 1 R8 + 0x7002000B, // 0359 JMP #0366 + 0x1C200F0D, // 035A EQ R8 R7 K13 + 0x78220009, // 035B JMPF R8 #0366 + 0x8C200B11, // 035C GETMET R8 R5 K17 + 0x7C200200, // 035D CALL R8 1 + 0x8C24110B, // 035E GETMET R9 R8 K11 + 0x4C2C0000, // 035F LDNIL R11 + 0x8C300B5A, // 0360 GETMET R12 R5 K90 + 0x88380B0E, // 0361 GETMBR R14 R5 K14 + 0x543E0003, // 0362 LDINT R15 4 + 0x7C300600, // 0363 CALL R12 3 + 0x7C240600, // 0364 CALL R9 3 + 0x80041000, // 0365 RET 1 R8 + 0x70020055, // 0366 JMP #03BD + 0x54220030, // 0367 LDINT R8 49 + 0x1C200C08, // 0368 EQ R8 R6 R8 + 0x78220010, // 0369 JMPF R8 #037B + 0x1C200F0F, // 036A EQ R8 R7 K15 + 0x78220005, // 036B JMPF R8 #0372 + 0x8C200706, // 036C GETMET R8 R3 K6 + 0x88280B0E, // 036D GETMBR R10 R5 K14 + 0x542E001D, // 036E LDINT R11 30 + 0x7C200600, // 036F CALL R8 3 + 0x80041000, // 0370 RET 1 R8 + 0x70020007, // 0371 JMP #037A + 0x5422FFFB, // 0372 LDINT R8 65532 + 0x1C200E08, // 0373 EQ R8 R7 R8 + 0x78220004, // 0374 JMPF R8 #037A + 0x8C200706, // 0375 GETMET R8 R3 K6 + 0x88280B2A, // 0376 GETMBR R10 R5 K42 + 0x542E0003, // 0377 LDINT R11 4 + 0x7C200600, // 0378 CALL R8 3 + 0x80041000, // 0379 RET 1 R8 + 0x70020041, // 037A JMP #03BD + 0x5422001C, // 037B LDINT R8 29 + 0x1C200C08, // 037C EQ R8 R6 R8 + 0x78220035, // 037D JMPF R8 #03B4 + 0x1C200F0D, // 037E EQ R8 R7 K13 + 0x78220008, // 037F JMPF R8 #0389 + 0x8C200B11, // 0380 GETMET R8 R5 K17 + 0x7C200200, // 0381 CALL R8 1 + 0x8C24110B, // 0382 GETMET R9 R8 K11 + 0x4C2C0000, // 0383 LDNIL R11 + 0x88300B0C, // 0384 GETMBR R12 R5 K12 + 0x5436001E, // 0385 LDINT R13 31 + 0x7C240800, // 0386 CALL R9 4 + 0x80041000, // 0387 RET 1 R8 + 0x70020029, // 0388 JMP #03B3 + 0x1C200F0F, // 0389 EQ R8 R7 K15 + 0x7822001E, // 038A JMPF R8 #03AA + 0x8C200B11, // 038B GETMET R8 R5 K17 + 0x7C200200, // 038C CALL R8 1 + 0x88240136, // 038D GETMBR R9 R0 K54 + 0x8C24135B, // 038E GETMET R9 R9 K91 + 0x502C0200, // 038F LDBOOL R11 1 0 + 0x7C240400, // 0390 CALL R9 2 + 0x88280136, // 0391 GETMBR R10 R0 K54 + 0x8828155C, // 0392 GETMBR R10 R10 K92 + 0x602C0010, // 0393 GETGBL R11 G16 + 0x5C301200, // 0394 MOVE R12 R9 + 0x7C2C0200, // 0395 CALL R11 1 + 0xA802000D, // 0396 EXBLK 0 #03A5 + 0x5C301600, // 0397 MOVE R12 R11 + 0x7C300000, // 0398 CALL R12 0 + 0x5C341400, // 0399 MOVE R13 R10 + 0x78360003, // 039A JMPF R13 #039F + 0xB8360200, // 039B GETNGBL R13 K1 + 0x88341B3D, // 039C GETMBR R13 R13 K61 + 0x2034180D, // 039D NE R13 R12 R13 + 0x78360004, // 039E JMPF R13 #03A4 + 0x8C34110B, // 039F GETMET R13 R8 K11 + 0x4C3C0000, // 03A0 LDNIL R15 + 0x88400B0C, // 03A1 GETMBR R16 R5 K12 + 0x5C441800, // 03A2 MOVE R17 R12 + 0x7C340800, // 03A3 CALL R13 4 + 0x7001FFF1, // 03A4 JMP #0397 + 0x582C003F, // 03A5 LDCONST R11 K63 + 0xAC2C0200, // 03A6 CATCH R11 1 0 + 0xB0080000, // 03A7 RAISE 2 R0 R0 + 0x80041000, // 03A8 RET 1 R8 + 0x70020008, // 03A9 JMP #03B3 + 0x60200003, // 03AA GETGBL R8 G3 + 0x5C240000, // 03AB MOVE R9 R0 + 0x7C200200, // 03AC CALL R8 1 + 0x8C20115D, // 03AD GETMET R8 R8 K93 + 0x5C280200, // 03AE MOVE R10 R1 + 0x5C2C0400, // 03AF MOVE R11 R2 + 0x5C300600, // 03B0 MOVE R12 R3 + 0x7C200800, // 03B1 CALL R8 4 + 0x80041000, // 03B2 RET 1 R8 + 0x70020008, // 03B3 JMP #03BD + 0x60200003, // 03B4 GETGBL R8 G3 + 0x5C240000, // 03B5 MOVE R9 R0 + 0x7C200200, // 03B6 CALL R8 1 + 0x8C20115D, // 03B7 GETMET R8 R8 K93 + 0x5C280200, // 03B8 MOVE R10 R1 + 0x5C2C0400, // 03B9 MOVE R11 R2 + 0x5C300600, // 03BA MOVE R12 R3 + 0x7C200800, // 03BB CALL R8 4 + 0x80041000, // 03BC RET 1 R8 + 0x80000000, // 03BD RET 0 }) ) ); @@ -1240,7 +1260,7 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ ), }), 1, /* has constants */ - ( &(const bvalue[100]) { /* constants */ + ( &(const bvalue[101]) { /* constants */ /* K0 */ be_nested_str_weak(crypto), /* K1 */ be_nested_str_weak(matter), /* K2 */ be_nested_str_weak(TLV), @@ -1326,25 +1346,26 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ /* K82 */ be_nested_str_weak(fabric_index_X3A), /* K83 */ be_nested_str_weak(active_fabrics), /* K84 */ be_nested_str_weak(get_fabric_index), - /* K85 */ be_nested_str_weak(set_timer), - /* K86 */ be_nested_str_weak(stop_iteration), - /* K87 */ be_nested_str_weak(MTR_X3A_X20RemoveFabric_X20fabric_X28), - /* K88 */ be_nested_str_weak(_X29_X20not_X20found), - /* K89 */ be_nested_str_weak(INVALID_ACTION), - /* K90 */ be_nested_str_weak(MTR_X3A_X20OpenCommissioningWindow_X28timeout_X3D_X25i_X2C_X20passcode_X3D_X25s_X2C_X20discriminator_X3D_X25i_X2C_X20iterations_X3D_X25i_X2C_X20salt_X3D_X25s_X29), - /* K91 */ be_nested_str_weak(INVALID_DATA_TYPE), - /* K92 */ be_nested_str_weak(MTR_X3A_X20wrong_X20size_X20for_X20PAKE_X20parameters), - /* K93 */ be_nested_str_weak(CONSTRAINT_ERROR), - /* K94 */ be_nested_str_weak(start_basic_commissioning), - /* K95 */ be_nested_str_weak(get_fabric), - /* K96 */ be_nested_str_weak(MTR_X3A_X20OpenBasicCommissioningWindow_X20commissioning_timeout_X3D), - /* K97 */ be_nested_str_weak(start_root_basic_commissioning), - /* K98 */ be_nested_str_weak(stop_basic_commissioning), - /* K99 */ be_nested_str_weak(invoke_request), + /* K85 */ be_nested_str_weak(mark_for_deletion), + /* K86 */ be_nested_str_weak(set_timer), + /* K87 */ be_nested_str_weak(stop_iteration), + /* K88 */ be_nested_str_weak(MTR_X3A_X20RemoveFabric_X20fabric_X28), + /* K89 */ be_nested_str_weak(_X29_X20not_X20found), + /* K90 */ be_nested_str_weak(INVALID_ACTION), + /* K91 */ be_nested_str_weak(MTR_X3A_X20OpenCommissioningWindow_X28timeout_X3D_X25i_X2C_X20passcode_X3D_X25s_X2C_X20discriminator_X3D_X25i_X2C_X20iterations_X3D_X25i_X2C_X20salt_X3D_X25s_X29), + /* K92 */ be_nested_str_weak(INVALID_DATA_TYPE), + /* K93 */ be_nested_str_weak(MTR_X3A_X20wrong_X20size_X20for_X20PAKE_X20parameters), + /* K94 */ be_nested_str_weak(CONSTRAINT_ERROR), + /* K95 */ be_nested_str_weak(start_basic_commissioning), + /* K96 */ be_nested_str_weak(get_fabric), + /* K97 */ be_nested_str_weak(MTR_X3A_X20OpenBasicCommissioningWindow_X20commissioning_timeout_X3D), + /* K98 */ be_nested_str_weak(start_root_basic_commissioning), + /* K99 */ be_nested_str_weak(stop_basic_commissioning), + /* K100 */ be_nested_str_weak(invoke_request), }), be_str_weak(invoke_request), &be_const_str_solidified, - ( &(const binstruction[712]) { /* code */ + ( &(const binstruction[714]) { /* code */ 0xA4120000, // 0000 IMPORT R4 K0 0xB8160200, // 0001 GETNGBL R5 K1 0x88140B02, // 0002 GETMBR R5 R5 K2 @@ -1445,10 +1466,10 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x80041000, // 0061 RET 1 R8 0x70020000, // 0062 JMP #0064 0xB0063119, // 0063 RAISE 1 K24 K25 - 0x70020260, // 0064 JMP #02C6 + 0x70020262, // 0064 JMP #02C8 0x5422003D, // 0065 LDINT R8 62 0x1C200C08, // 0066 EQ R8 R6 R8 - 0x782201C1, // 0067 JMPF R8 #022A + 0x782201C3, // 0067 JMPF R8 #022C 0x1C200F0E, // 0068 EQ R8 R7 K14 0x7822001D, // 0069 JMPF R8 #0088 0x8C200506, // 006A GETMET R8 R2 K6 @@ -1480,7 +1501,7 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x7C280800, // 0084 CALL R10 4 0x900E0910, // 0085 SETMBR R3 K4 K16 0x80041200, // 0086 RET 1 R9 - 0x700201A0, // 0087 JMP #0229 + 0x700201A2, // 0087 JMP #022B 0x1C200F05, // 0088 EQ R8 R7 K5 0x7822003C, // 0089 JMPF R8 #00C7 0x8C200506, // 008A GETMET R8 R2 K6 @@ -1543,7 +1564,7 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x7C3C0800, // 00C3 CALL R15 4 0x900E0907, // 00C4 SETMBR R3 K4 K7 0x80041C00, // 00C5 RET 1 R14 - 0x70020161, // 00C6 JMP #0229 + 0x70020163, // 00C6 JMP #022B 0x54220003, // 00C7 LDINT R8 4 0x1C200E08, // 00C8 EQ R8 R7 R8 0x7822003C, // 00C9 JMPF R8 #0107 @@ -1607,7 +1628,7 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x54420004, // 0103 LDINT R16 5 0x900E0810, // 0104 SETMBR R3 K4 R16 0x80041E00, // 0105 RET 1 R15 - 0x70020121, // 0106 JMP #0229 + 0x70020123, // 0106 JMP #022B 0x5422000A, // 0107 LDINT R8 11 0x1C200E08, // 0108 EQ R8 R7 R8 0x7822000B, // 0109 JMPF R8 #0116 @@ -1622,7 +1643,7 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x900E3409, // 0112 SETMBR R3 K26 R9 0x4C240000, // 0113 LDNIL R9 0x80041200, // 0114 RET 1 R9 - 0x70020112, // 0115 JMP #0229 + 0x70020114, // 0115 JMP #022B 0x54220005, // 0116 LDINT R8 6 0x1C200E08, // 0117 EQ R8 R7 R8 0x782200B8, // 0118 JMPF R8 #01D2 @@ -1810,7 +1831,7 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x54660007, // 01CE LDINT R25 8 0x900E0819, // 01CF SETMBR R3 K4 R25 0x80043000, // 01D0 RET 1 R24 - 0x70020056, // 01D1 JMP #0229 + 0x70020058, // 01D1 JMP #022B 0x54220008, // 01D2 LDINT R8 9 0x1C200E08, // 01D3 EQ R8 R7 R8 0x7822001E, // 01D4 JMPF R8 #01F4 @@ -1844,10 +1865,10 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x900E3409, // 01F0 SETMBR R3 K26 R9 0x4C240000, // 01F1 LDNIL R9 0x80041200, // 01F2 RET 1 R9 - 0x70020034, // 01F3 JMP #0229 + 0x70020036, // 01F3 JMP #022B 0x54220009, // 01F4 LDINT R8 10 0x1C200E08, // 01F5 EQ R8 R7 R8 - 0x78220031, // 01F6 JMPF R8 #0229 + 0x78220033, // 01F6 JMPF R8 #022B 0x8C200506, // 01F7 GETMET R8 R2 K6 0x58280005, // 01F8 LDCONST R10 K5 0x7C200400, // 01F9 CALL R8 2 @@ -1862,201 +1883,203 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x8C281553, // 0202 GETMET R10 R10 K83 0x7C280200, // 0203 CALL R10 1 0x7C240200, // 0204 CALL R9 1 - 0xA8020010, // 0205 EXBLK 0 #0217 + 0xA8020012, // 0205 EXBLK 0 #0219 0x5C281200, // 0206 MOVE R10 R9 0x7C280000, // 0207 CALL R10 0 0x8C2C1554, // 0208 GETMET R11 R10 K84 0x7C2C0200, // 0209 CALL R11 1 0x1C2C1608, // 020A EQ R11 R11 R8 - 0x782E0008, // 020B JMPF R11 #0215 - 0xB82E4400, // 020C GETNGBL R11 K34 - 0x8C2C1755, // 020D GETMET R11 R11 K85 - 0x543607CF, // 020E LDINT R13 2000 - 0x84380000, // 020F CLOSURE R14 P0 - 0x7C2C0600, // 0210 CALL R11 3 - 0x502C0200, // 0211 LDBOOL R11 1 0 - 0xA0000000, // 0212 CLOSE R0 - 0xA8040001, // 0213 EXBLK 1 1 - 0x80041600, // 0214 RET 1 R11 - 0xA0240000, // 0215 CLOSE R9 - 0x7001FFEE, // 0216 JMP #0206 - 0x58240056, // 0217 LDCONST R9 K86 - 0xAC240200, // 0218 CATCH R9 1 0 - 0xB0080000, // 0219 RAISE 2 R0 R0 - 0xB8264400, // 021A GETNGBL R9 K34 - 0x8C24132C, // 021B GETMET R9 R9 K44 - 0x602C0008, // 021C GETGBL R11 G8 - 0x5C301000, // 021D MOVE R12 R8 - 0x7C2C0200, // 021E CALL R11 1 - 0x002EAE0B, // 021F ADD R11 K87 R11 - 0x002C1758, // 0220 ADD R11 R11 K88 - 0x5830000E, // 0221 LDCONST R12 K14 - 0x7C240600, // 0222 CALL R9 3 - 0xB8260200, // 0223 GETNGBL R9 K1 - 0x88241359, // 0224 GETMBR R9 R9 K89 - 0x900E3409, // 0225 SETMBR R3 K26 R9 - 0x4C240000, // 0226 LDNIL R9 - 0xA0000000, // 0227 CLOSE R0 - 0x80041200, // 0228 RET 1 R9 - 0x7002009B, // 0229 JMP #02C6 - 0x5422003B, // 022A LDINT R8 60 - 0x1C200C08, // 022B EQ R8 R6 R8 - 0x78220085, // 022C JMPF R8 #02B3 - 0x1C200F05, // 022D EQ R8 R7 K5 - 0x78220065, // 022E JMPF R8 #0295 - 0x8C200506, // 022F GETMET R8 R2 K6 - 0x58280005, // 0230 LDCONST R10 K5 - 0x7C200400, // 0231 CALL R8 2 - 0x8C240506, // 0232 GETMET R9 R2 K6 - 0x582C0007, // 0233 LDCONST R11 K7 - 0x7C240400, // 0234 CALL R9 2 - 0x8C280506, // 0235 GETMET R10 R2 K6 - 0x5830000E, // 0236 LDCONST R12 K14 - 0x7C280400, // 0237 CALL R10 2 - 0x8C2C0506, // 0238 GETMET R11 R2 K6 - 0x58340010, // 0239 LDCONST R13 K16 - 0x7C2C0400, // 023A CALL R11 2 - 0x8C300506, // 023B GETMET R12 R2 K6 - 0x543A0003, // 023C LDINT R14 4 - 0x7C300400, // 023D CALL R12 2 - 0xB8364400, // 023E GETNGBL R13 K34 - 0x8C341B2C, // 023F GETMET R13 R13 K44 - 0x603C0018, // 0240 GETGBL R15 G24 - 0x5840005A, // 0241 LDCONST R16 K90 - 0x5C441000, // 0242 MOVE R17 R8 - 0x8C481351, // 0243 GETMET R18 R9 K81 - 0x7C480200, // 0244 CALL R18 1 - 0x5C4C1400, // 0245 MOVE R19 R10 - 0x5C501600, // 0246 MOVE R20 R11 - 0x8C541951, // 0247 GETMET R21 R12 K81 - 0x7C540200, // 0248 CALL R21 1 - 0x7C3C0C00, // 0249 CALL R15 6 - 0x54420003, // 024A LDINT R16 4 - 0x7C340600, // 024B CALL R13 3 - 0x4C340000, // 024C LDNIL R13 - 0x1C34100D, // 024D EQ R13 R8 R13 - 0x7436000B, // 024E JMPT R13 #025B - 0x4C340000, // 024F LDNIL R13 - 0x1C34120D, // 0250 EQ R13 R9 R13 - 0x74360008, // 0251 JMPT R13 #025B - 0x4C340000, // 0252 LDNIL R13 - 0x1C34140D, // 0253 EQ R13 R10 R13 - 0x74360005, // 0254 JMPT R13 #025B - 0x4C340000, // 0255 LDNIL R13 - 0x1C34160D, // 0256 EQ R13 R11 R13 - 0x74360002, // 0257 JMPT R13 #025B - 0x4C340000, // 0258 LDNIL R13 - 0x1C34180D, // 0259 EQ R13 R12 R13 - 0x78360005, // 025A JMPF R13 #0261 - 0xB8360200, // 025B GETNGBL R13 K1 - 0x88341B5B, // 025C GETMBR R13 R13 K91 - 0x900E340D, // 025D SETMBR R3 K26 R13 - 0x4C340000, // 025E LDNIL R13 - 0xA0000000, // 025F CLOSE R0 - 0x80041A00, // 0260 RET 1 R13 - 0x6034000C, // 0261 GETGBL R13 G12 - 0x5C381200, // 0262 MOVE R14 R9 - 0x7C340200, // 0263 CALL R13 1 - 0x543A001F, // 0264 LDINT R14 32 - 0x543E0040, // 0265 LDINT R15 65 - 0x00381C0F, // 0266 ADD R14 R14 R15 - 0x20341A0E, // 0267 NE R13 R13 R14 - 0x7436000B, // 0268 JMPT R13 #0275 - 0x6034000C, // 0269 GETGBL R13 G12 - 0x5C381800, // 026A MOVE R14 R12 - 0x7C340200, // 026B CALL R13 1 - 0x543A000F, // 026C LDINT R14 16 - 0x14341A0E, // 026D LT R13 R13 R14 - 0x74360005, // 026E JMPT R13 #0275 - 0x6034000C, // 026F GETGBL R13 G12 - 0x5C381800, // 0270 MOVE R14 R12 - 0x7C340200, // 0271 CALL R13 1 - 0x543A001F, // 0272 LDINT R14 32 - 0x24341A0E, // 0273 GT R13 R13 R14 - 0x7836000A, // 0274 JMPF R13 #0280 - 0xB8364400, // 0275 GETNGBL R13 K34 - 0x8C341B2C, // 0276 GETMET R13 R13 K44 - 0x583C005C, // 0277 LDCONST R15 K92 - 0x5840000E, // 0278 LDCONST R16 K14 - 0x7C340600, // 0279 CALL R13 3 - 0xB8360200, // 027A GETNGBL R13 K1 - 0x88341B5D, // 027B GETMBR R13 R13 K93 - 0x900E340D, // 027C SETMBR R3 K26 R13 - 0x4C340000, // 027D LDNIL R13 - 0xA0000000, // 027E CLOSE R0 - 0x80041A00, // 027F RET 1 R13 - 0x5436001E, // 0280 LDINT R13 31 - 0x40360A0D, // 0281 CONNECT R13 K5 R13 - 0x9434120D, // 0282 GETIDX R13 R9 R13 - 0x543A001F, // 0283 LDINT R14 32 - 0x40381D40, // 0284 CONNECT R14 R14 K64 - 0x9438120E, // 0285 GETIDX R14 R9 R14 - 0x883C0116, // 0286 GETMBR R15 R0 K22 - 0x8C3C1F5E, // 0287 GETMET R15 R15 K94 - 0x5C441000, // 0288 MOVE R17 R8 - 0x5C481600, // 0289 MOVE R18 R11 - 0x5C4C1400, // 028A MOVE R19 R10 - 0x5C501800, // 028B MOVE R20 R12 - 0x5C541A00, // 028C MOVE R21 R13 - 0x5C581C00, // 028D MOVE R22 R14 - 0x8C5C035F, // 028E GETMET R23 R1 K95 - 0x7C5C0200, // 028F CALL R23 1 - 0x7C3C1000, // 0290 CALL R15 8 - 0x503C0200, // 0291 LDBOOL R15 1 0 - 0xA0000000, // 0292 CLOSE R0 - 0x80041E00, // 0293 RET 1 R15 - 0x7002001C, // 0294 JMP #02B2 - 0x1C200F07, // 0295 EQ R8 R7 K7 - 0x78220012, // 0296 JMPF R8 #02AA - 0x8C200506, // 0297 GETMET R8 R2 K6 - 0x58280005, // 0298 LDCONST R10 K5 - 0x7C200400, // 0299 CALL R8 2 - 0xB8264400, // 029A GETNGBL R9 K34 - 0x8C24132C, // 029B GETMET R9 R9 K44 - 0x602C0008, // 029C GETGBL R11 G8 - 0x5C301000, // 029D MOVE R12 R8 - 0x7C2C0200, // 029E CALL R11 1 - 0x002EC00B, // 029F ADD R11 K96 R11 - 0x58300010, // 02A0 LDCONST R12 K16 - 0x7C240600, // 02A1 CALL R9 3 - 0x88240116, // 02A2 GETMBR R9 R0 K22 - 0x8C241361, // 02A3 GETMET R9 R9 K97 - 0x5C2C1000, // 02A4 MOVE R11 R8 - 0x7C240400, // 02A5 CALL R9 2 - 0x50240200, // 02A6 LDBOOL R9 1 0 - 0xA0000000, // 02A7 CLOSE R0 - 0x80041200, // 02A8 RET 1 R9 - 0x70020007, // 02A9 JMP #02B2 - 0x1C200F0E, // 02AA EQ R8 R7 K14 - 0x78220005, // 02AB JMPF R8 #02B2 - 0x88200116, // 02AC GETMBR R8 R0 K22 - 0x8C201162, // 02AD GETMET R8 R8 K98 - 0x7C200200, // 02AE CALL R8 1 - 0x50200200, // 02AF LDBOOL R8 1 0 - 0xA0000000, // 02B0 CLOSE R0 - 0x80041000, // 02B1 RET 1 R8 - 0x70020012, // 02B2 JMP #02C6 - 0x54220029, // 02B3 LDINT R8 42 - 0x1C200C08, // 02B4 EQ R8 R6 R8 - 0x78220005, // 02B5 JMPF R8 #02BC - 0x1C200F05, // 02B6 EQ R8 R7 K5 - 0x78220002, // 02B7 JMPF R8 #02BB - 0x50200200, // 02B8 LDBOOL R8 1 0 - 0xA0000000, // 02B9 CLOSE R0 - 0x80041000, // 02BA RET 1 R8 - 0x70020009, // 02BB JMP #02C6 - 0x60200003, // 02BC GETGBL R8 G3 - 0x5C240000, // 02BD MOVE R9 R0 - 0x7C200200, // 02BE CALL R8 1 - 0x8C201163, // 02BF GETMET R8 R8 K99 - 0x5C280200, // 02C0 MOVE R10 R1 - 0x5C2C0400, // 02C1 MOVE R11 R2 - 0x5C300600, // 02C2 MOVE R12 R3 - 0x7C200800, // 02C3 CALL R8 4 - 0xA0000000, // 02C4 CLOSE R0 - 0x80041000, // 02C5 RET 1 R8 + 0x782E000A, // 020B JMPF R11 #0217 + 0x8C2C1555, // 020C GETMET R11 R10 K85 + 0x7C2C0200, // 020D CALL R11 1 + 0xB82E4400, // 020E GETNGBL R11 K34 + 0x8C2C1756, // 020F GETMET R11 R11 K86 + 0x543607CF, // 0210 LDINT R13 2000 + 0x84380000, // 0211 CLOSURE R14 P0 + 0x7C2C0600, // 0212 CALL R11 3 + 0x502C0200, // 0213 LDBOOL R11 1 0 + 0xA0000000, // 0214 CLOSE R0 + 0xA8040001, // 0215 EXBLK 1 1 + 0x80041600, // 0216 RET 1 R11 + 0xA0240000, // 0217 CLOSE R9 + 0x7001FFEC, // 0218 JMP #0206 + 0x58240057, // 0219 LDCONST R9 K87 + 0xAC240200, // 021A CATCH R9 1 0 + 0xB0080000, // 021B RAISE 2 R0 R0 + 0xB8264400, // 021C GETNGBL R9 K34 + 0x8C24132C, // 021D GETMET R9 R9 K44 + 0x602C0008, // 021E GETGBL R11 G8 + 0x5C301000, // 021F MOVE R12 R8 + 0x7C2C0200, // 0220 CALL R11 1 + 0x002EB00B, // 0221 ADD R11 K88 R11 + 0x002C1759, // 0222 ADD R11 R11 K89 + 0x5830000E, // 0223 LDCONST R12 K14 + 0x7C240600, // 0224 CALL R9 3 + 0xB8260200, // 0225 GETNGBL R9 K1 + 0x8824135A, // 0226 GETMBR R9 R9 K90 + 0x900E3409, // 0227 SETMBR R3 K26 R9 + 0x4C240000, // 0228 LDNIL R9 + 0xA0000000, // 0229 CLOSE R0 + 0x80041200, // 022A RET 1 R9 + 0x7002009B, // 022B JMP #02C8 + 0x5422003B, // 022C LDINT R8 60 + 0x1C200C08, // 022D EQ R8 R6 R8 + 0x78220085, // 022E JMPF R8 #02B5 + 0x1C200F05, // 022F EQ R8 R7 K5 + 0x78220065, // 0230 JMPF R8 #0297 + 0x8C200506, // 0231 GETMET R8 R2 K6 + 0x58280005, // 0232 LDCONST R10 K5 + 0x7C200400, // 0233 CALL R8 2 + 0x8C240506, // 0234 GETMET R9 R2 K6 + 0x582C0007, // 0235 LDCONST R11 K7 + 0x7C240400, // 0236 CALL R9 2 + 0x8C280506, // 0237 GETMET R10 R2 K6 + 0x5830000E, // 0238 LDCONST R12 K14 + 0x7C280400, // 0239 CALL R10 2 + 0x8C2C0506, // 023A GETMET R11 R2 K6 + 0x58340010, // 023B LDCONST R13 K16 + 0x7C2C0400, // 023C CALL R11 2 + 0x8C300506, // 023D GETMET R12 R2 K6 + 0x543A0003, // 023E LDINT R14 4 + 0x7C300400, // 023F CALL R12 2 + 0xB8364400, // 0240 GETNGBL R13 K34 + 0x8C341B2C, // 0241 GETMET R13 R13 K44 + 0x603C0018, // 0242 GETGBL R15 G24 + 0x5840005B, // 0243 LDCONST R16 K91 + 0x5C441000, // 0244 MOVE R17 R8 + 0x8C481351, // 0245 GETMET R18 R9 K81 + 0x7C480200, // 0246 CALL R18 1 + 0x5C4C1400, // 0247 MOVE R19 R10 + 0x5C501600, // 0248 MOVE R20 R11 + 0x8C541951, // 0249 GETMET R21 R12 K81 + 0x7C540200, // 024A CALL R21 1 + 0x7C3C0C00, // 024B CALL R15 6 + 0x54420003, // 024C LDINT R16 4 + 0x7C340600, // 024D CALL R13 3 + 0x4C340000, // 024E LDNIL R13 + 0x1C34100D, // 024F EQ R13 R8 R13 + 0x7436000B, // 0250 JMPT R13 #025D + 0x4C340000, // 0251 LDNIL R13 + 0x1C34120D, // 0252 EQ R13 R9 R13 + 0x74360008, // 0253 JMPT R13 #025D + 0x4C340000, // 0254 LDNIL R13 + 0x1C34140D, // 0255 EQ R13 R10 R13 + 0x74360005, // 0256 JMPT R13 #025D + 0x4C340000, // 0257 LDNIL R13 + 0x1C34160D, // 0258 EQ R13 R11 R13 + 0x74360002, // 0259 JMPT R13 #025D + 0x4C340000, // 025A LDNIL R13 + 0x1C34180D, // 025B EQ R13 R12 R13 + 0x78360005, // 025C JMPF R13 #0263 + 0xB8360200, // 025D GETNGBL R13 K1 + 0x88341B5C, // 025E GETMBR R13 R13 K92 + 0x900E340D, // 025F SETMBR R3 K26 R13 + 0x4C340000, // 0260 LDNIL R13 + 0xA0000000, // 0261 CLOSE R0 + 0x80041A00, // 0262 RET 1 R13 + 0x6034000C, // 0263 GETGBL R13 G12 + 0x5C381200, // 0264 MOVE R14 R9 + 0x7C340200, // 0265 CALL R13 1 + 0x543A001F, // 0266 LDINT R14 32 + 0x543E0040, // 0267 LDINT R15 65 + 0x00381C0F, // 0268 ADD R14 R14 R15 + 0x20341A0E, // 0269 NE R13 R13 R14 + 0x7436000B, // 026A JMPT R13 #0277 + 0x6034000C, // 026B GETGBL R13 G12 + 0x5C381800, // 026C MOVE R14 R12 + 0x7C340200, // 026D CALL R13 1 + 0x543A000F, // 026E LDINT R14 16 + 0x14341A0E, // 026F LT R13 R13 R14 + 0x74360005, // 0270 JMPT R13 #0277 + 0x6034000C, // 0271 GETGBL R13 G12 + 0x5C381800, // 0272 MOVE R14 R12 + 0x7C340200, // 0273 CALL R13 1 + 0x543A001F, // 0274 LDINT R14 32 + 0x24341A0E, // 0275 GT R13 R13 R14 + 0x7836000A, // 0276 JMPF R13 #0282 + 0xB8364400, // 0277 GETNGBL R13 K34 + 0x8C341B2C, // 0278 GETMET R13 R13 K44 + 0x583C005D, // 0279 LDCONST R15 K93 + 0x5840000E, // 027A LDCONST R16 K14 + 0x7C340600, // 027B CALL R13 3 + 0xB8360200, // 027C GETNGBL R13 K1 + 0x88341B5E, // 027D GETMBR R13 R13 K94 + 0x900E340D, // 027E SETMBR R3 K26 R13 + 0x4C340000, // 027F LDNIL R13 + 0xA0000000, // 0280 CLOSE R0 + 0x80041A00, // 0281 RET 1 R13 + 0x5436001E, // 0282 LDINT R13 31 + 0x40360A0D, // 0283 CONNECT R13 K5 R13 + 0x9434120D, // 0284 GETIDX R13 R9 R13 + 0x543A001F, // 0285 LDINT R14 32 + 0x40381D40, // 0286 CONNECT R14 R14 K64 + 0x9438120E, // 0287 GETIDX R14 R9 R14 + 0x883C0116, // 0288 GETMBR R15 R0 K22 + 0x8C3C1F5F, // 0289 GETMET R15 R15 K95 + 0x5C441000, // 028A MOVE R17 R8 + 0x5C481600, // 028B MOVE R18 R11 + 0x5C4C1400, // 028C MOVE R19 R10 + 0x5C501800, // 028D MOVE R20 R12 + 0x5C541A00, // 028E MOVE R21 R13 + 0x5C581C00, // 028F MOVE R22 R14 + 0x8C5C0360, // 0290 GETMET R23 R1 K96 + 0x7C5C0200, // 0291 CALL R23 1 + 0x7C3C1000, // 0292 CALL R15 8 + 0x503C0200, // 0293 LDBOOL R15 1 0 + 0xA0000000, // 0294 CLOSE R0 + 0x80041E00, // 0295 RET 1 R15 + 0x7002001C, // 0296 JMP #02B4 + 0x1C200F07, // 0297 EQ R8 R7 K7 + 0x78220012, // 0298 JMPF R8 #02AC + 0x8C200506, // 0299 GETMET R8 R2 K6 + 0x58280005, // 029A LDCONST R10 K5 + 0x7C200400, // 029B CALL R8 2 + 0xB8264400, // 029C GETNGBL R9 K34 + 0x8C24132C, // 029D GETMET R9 R9 K44 + 0x602C0008, // 029E GETGBL R11 G8 + 0x5C301000, // 029F MOVE R12 R8 + 0x7C2C0200, // 02A0 CALL R11 1 + 0x002EC20B, // 02A1 ADD R11 K97 R11 + 0x58300010, // 02A2 LDCONST R12 K16 + 0x7C240600, // 02A3 CALL R9 3 + 0x88240116, // 02A4 GETMBR R9 R0 K22 + 0x8C241362, // 02A5 GETMET R9 R9 K98 + 0x5C2C1000, // 02A6 MOVE R11 R8 + 0x7C240400, // 02A7 CALL R9 2 + 0x50240200, // 02A8 LDBOOL R9 1 0 + 0xA0000000, // 02A9 CLOSE R0 + 0x80041200, // 02AA RET 1 R9 + 0x70020007, // 02AB JMP #02B4 + 0x1C200F0E, // 02AC EQ R8 R7 K14 + 0x78220005, // 02AD JMPF R8 #02B4 + 0x88200116, // 02AE GETMBR R8 R0 K22 + 0x8C201163, // 02AF GETMET R8 R8 K99 + 0x7C200200, // 02B0 CALL R8 1 + 0x50200200, // 02B1 LDBOOL R8 1 0 + 0xA0000000, // 02B2 CLOSE R0 + 0x80041000, // 02B3 RET 1 R8 + 0x70020012, // 02B4 JMP #02C8 + 0x54220029, // 02B5 LDINT R8 42 + 0x1C200C08, // 02B6 EQ R8 R6 R8 + 0x78220005, // 02B7 JMPF R8 #02BE + 0x1C200F05, // 02B8 EQ R8 R7 K5 + 0x78220002, // 02B9 JMPF R8 #02BD + 0x50200200, // 02BA LDBOOL R8 1 0 + 0xA0000000, // 02BB CLOSE R0 + 0x80041000, // 02BC RET 1 R8 + 0x70020009, // 02BD JMP #02C8 + 0x60200003, // 02BE GETGBL R8 G3 + 0x5C240000, // 02BF MOVE R9 R0 + 0x7C200200, // 02C0 CALL R8 1 + 0x8C201164, // 02C1 GETMET R8 R8 K100 + 0x5C280200, // 02C2 MOVE R10 R1 + 0x5C2C0400, // 02C3 MOVE R11 R2 + 0x5C300600, // 02C4 MOVE R12 R3 + 0x7C200800, // 02C5 CALL R8 4 0xA0000000, // 02C6 CLOSE R0 - 0x80000000, // 02C7 RET 0 + 0x80041000, // 02C7 RET 1 R8 + 0xA0000000, // 02C8 CLOSE R0 + 0x80000000, // 02C9 RET 0 }) ) ); @@ -2083,9 +2106,26 @@ be_local_class(Matter_Plugin_Root, { be_const_key_weak(write_attribute, -1), be_const_closure(Matter_Plugin_Root_write_attribute_closure) }, { be_const_key_weak(DISPLAY_NAME, -1), be_nested_str_weak(Root_X20node) }, { be_const_key_weak(CLUSTERS, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { - be_const_map( * be_nested_map(15, + be_const_map( * be_nested_map(14, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_int(60, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + { be_const_key_int(56, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + be_const_list( * be_nested_list(3, + ( (struct bvalue*) &(const bvalue[]) { + be_const_int(0), + be_const_int(1), + be_const_int(7), + })) ) } )) }, + { be_const_key_int(29, 11), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + be_const_list( * be_nested_list(6, + ( (struct bvalue*) &(const bvalue[]) { + be_const_int(0), + be_const_int(1), + be_const_int(2), + be_const_int(3), + be_const_int(65532), + be_const_int(65533), + })) ) } )) }, + { be_const_key_int(44, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { be_const_list( * be_nested_list(3, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), @@ -2100,7 +2140,18 @@ be_local_class(Matter_Plugin_Root, be_const_int(3), be_const_int(4), })) ) } )) }, - { be_const_key_int(62, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + { be_const_key_int(60, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + be_const_list( * be_nested_list(3, + ( (struct bvalue*) &(const bvalue[]) { + be_const_int(0), + be_const_int(1), + be_const_int(2), + })) ) } )) }, + { be_const_key_int(63, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + be_const_list( * be_nested_list(0, + ( (struct bvalue*) &(const bvalue[]) { + })) ) } )) }, + { be_const_key_int(62, 13), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), @@ -2110,16 +2161,7 @@ be_local_class(Matter_Plugin_Root, be_const_int(4), be_const_int(5), })) ) } )) }, - { be_const_key_int(48, 9), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(5, - ( (struct bvalue*) &(const bvalue[]) { - be_const_int(0), - be_const_int(1), - be_const_int(2), - be_const_int(3), - be_const_int(4), - })) ) } )) }, - { be_const_key_int(49, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + { be_const_key_int(49, 5), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { be_const_list( * be_nested_list(3, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), @@ -2142,19 +2184,11 @@ be_local_class(Matter_Plugin_Root, be_const_list( * be_nested_list(0, ( (struct bvalue*) &(const bvalue[]) { })) ) } )) }, - { be_const_key_int(29, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + { be_const_key_int(43, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + be_const_list( * be_nested_list(2, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), - be_const_int(2), - be_const_int(3), - be_const_int(65532), - be_const_int(65533), - })) ) } )) }, - { be_const_key_int(63, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(0, - ( (struct bvalue*) &(const bvalue[]) { })) ) } )) }, { be_const_key_int(40, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { be_const_list( * be_nested_list(15, @@ -2175,30 +2209,14 @@ be_local_class(Matter_Plugin_Root, be_const_int(18), be_const_int(19), })) ) } )) }, - { be_const_key_int(56, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, - ( (struct bvalue*) &(const bvalue[]) { - be_const_int(0), - be_const_int(1), - be_const_int(7), - })) ) } )) }, - { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(1, - ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), - })) ) } )) }, - { be_const_key_int(43, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(2, - ( (struct bvalue*) &(const bvalue[]) { - be_const_int(0), - be_const_int(1), - })) ) } )) }, - { be_const_key_int(44, 8), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + { be_const_key_int(48, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + be_const_list( * be_nested_list(5, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), + be_const_int(3), + be_const_int(4), })) ) } )) }, })) ) } )) }, })), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Light1.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Light1.h index d802a1c5f..cdbd20304 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Light1.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Light1.h @@ -761,9 +761,8 @@ be_local_class(Matter_Plugin_Light1, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_OnOff.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_OnOff.h index 20ce2d258..79973bcd2 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_OnOff.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_OnOff.h @@ -484,9 +484,8 @@ be_local_class(Matter_Plugin_OnOff, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h index 4d5b133d2..1017a0d2d 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h @@ -415,9 +415,8 @@ be_local_class(Matter_Plugin_Sensor_Contact, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Occupancy.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Occupancy.h index d49d927cc..b88b02bd3 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Occupancy.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Occupancy.h @@ -432,9 +432,8 @@ be_local_class(Matter_Plugin_Sensor_Occupancy, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_OnOff.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_OnOff.h index b0847cd19..3bc3d3148 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_OnOff.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_OnOff.h @@ -300,9 +300,8 @@ be_local_class(Matter_Plugin_Sensor_OnOff, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Shutter.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Shutter.h index 16c73a9ed..b8d03111b 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Shutter.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Shutter.h @@ -696,9 +696,8 @@ be_local_class(Matter_Plugin_Shutter, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Light0.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Light0.h index c0eb08bcd..4e2bedd20 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Light0.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Light0.h @@ -513,9 +513,8 @@ be_local_class(Matter_Plugin_Bridge_Light0, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Contact.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Contact.h index 5f072e844..85a650a73 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Contact.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Contact.h @@ -372,9 +372,8 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Contact, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Occupancy.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Occupancy.h index f79147599..8961d1881 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Occupancy.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Occupancy.h @@ -392,9 +392,8 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Occupancy, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light2.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light2.h index 8f157b0f3..78bad5ab1 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light2.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light2.h @@ -528,9 +528,8 @@ be_local_class(Matter_Plugin_Light2, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light3.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light3.h index 8d3ee8ad0..1a0b7a981 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light3.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light3.h @@ -690,9 +690,8 @@ be_local_class(Matter_Plugin_Light3, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Flow.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Flow.h index 30208cb57..8510fa70f 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Flow.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Flow.h @@ -219,9 +219,8 @@ be_local_class(Matter_Plugin_Sensor_Flow, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Humidity.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Humidity.h index f4e9ebc3a..4a8ad5775 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Humidity.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Humidity.h @@ -227,9 +227,8 @@ be_local_class(Matter_Plugin_Sensor_Humidity, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Illuminance.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Illuminance.h index 17b96ce22..81d05c19f 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Illuminance.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Illuminance.h @@ -238,9 +238,8 @@ be_local_class(Matter_Plugin_Sensor_Illuminance, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Pressure.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Pressure.h index bcd8a036f..56dcdbd6e 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Pressure.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Pressure.h @@ -227,9 +227,8 @@ be_local_class(Matter_Plugin_Sensor_Pressure, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Temp.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Temp.h index a28ac1196..1b22cb9d1 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Temp.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Temp.h @@ -240,9 +240,8 @@ be_local_class(Matter_Plugin_Sensor_Temp, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_ShutterTilt.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_ShutterTilt.h index c661121a9..9b6b6eea4 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_ShutterTilt.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_ShutterTilt.h @@ -470,9 +470,8 @@ be_local_class(Matter_Plugin_ShutterTilt, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Light1.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Light1.h index 8cdf671bf..09091811a 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Light1.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Light1.h @@ -579,9 +579,8 @@ be_local_class(Matter_Plugin_Bridge_Light1, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Flow.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Flow.h index fb56e9907..bc0401c1a 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Flow.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Flow.h @@ -256,9 +256,8 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Flow, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Humidity.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Humidity.h index 6a2032b50..fc8e54655 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Humidity.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Humidity.h @@ -272,9 +272,8 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Humidity, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Illuminance.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Illuminance.h index 739e203bf..8bd28e910 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Illuminance.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Illuminance.h @@ -275,9 +275,8 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Illuminance, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Pressure.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Pressure.h index 63f96dae4..4edf27096 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Pressure.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Pressure.h @@ -264,9 +264,8 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Pressure, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Temp.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Temp.h index 44b133271..cd3d6572a 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Temp.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Temp.h @@ -282,9 +282,8 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Temp, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light2.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light2.h index 712aa9f6d..c832d9323 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light2.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light2.h @@ -560,9 +560,8 @@ be_local_class(Matter_Plugin_Bridge_Light2, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light3.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light3.h index 18cd5c467..30d57117a 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light3.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light3.h @@ -736,9 +736,8 @@ be_local_class(Matter_Plugin_Bridge_Light3, be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { - be_const_int(17), be_const_int(3), be_const_int(5), be_const_int(10), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h index 7b85512bc..904206b63 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h @@ -7,124 +7,9 @@ extern const bclass be_class_Matter_Device; /******************************************************************** -** Solidified function: bridge_add_endpoint +** Solidified function: is_commissioning_open ********************************************************************/ -be_local_closure(Matter_Device_bridge_add_endpoint, /* name */ - be_nested_proto( - 17, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[21]) { /* constants */ - /* K0 */ be_nested_str_weak(plugins_classes), - /* K1 */ be_nested_str_weak(find), - /* K2 */ be_nested_str_weak(tasmota), - /* K3 */ be_nested_str_weak(log), - /* K4 */ be_nested_str_weak(MTR_X3A_X20unknown_X20class_X20name_X20_X27), - /* K5 */ be_nested_str_weak(_X27_X20skipping), - /* K6 */ be_const_int(3), - /* K7 */ be_nested_str_weak(next_ep), - /* K8 */ be_nested_str_weak(plugins), - /* K9 */ be_nested_str_weak(push), - /* K10 */ be_nested_str_weak(type), - /* K11 */ be_nested_str_weak(keys), - /* K12 */ be_nested_str_weak(stop_iteration), - /* K13 */ be_nested_str_weak(MTR_X3A_X20adding_X20endpoint_X20_X3D_X20_X25i_X20type_X3A_X25s_X25s), - /* K14 */ be_nested_str_weak(conf_to_log), - /* K15 */ be_const_int(2), - /* K16 */ be_nested_str_weak(plugins_config), - /* K17 */ be_nested_str_weak(plugins_persist), - /* K18 */ be_const_int(1), - /* K19 */ be_nested_str_weak(save_param), - /* K20 */ be_nested_str_weak(signal_endpoints_changed), - }), - be_str_weak(bridge_add_endpoint), - &be_const_str_solidified, - ( &(const binstruction[70]) { /* code */ - 0x880C0100, // 0000 GETMBR R3 R0 K0 - 0x8C0C0701, // 0001 GETMET R3 R3 K1 - 0x5C140200, // 0002 MOVE R5 R1 - 0x7C0C0400, // 0003 CALL R3 2 - 0x4C100000, // 0004 LDNIL R4 - 0x1C100604, // 0005 EQ R4 R3 R4 - 0x78120009, // 0006 JMPF R4 #0011 - 0xB8120400, // 0007 GETNGBL R4 K2 - 0x8C100903, // 0008 GETMET R4 R4 K3 - 0x60180008, // 0009 GETGBL R6 G8 - 0x5C1C0200, // 000A MOVE R7 R1 - 0x7C180200, // 000B CALL R6 1 - 0x001A0806, // 000C ADD R6 K4 R6 - 0x00180D05, // 000D ADD R6 R6 K5 - 0x581C0006, // 000E LDCONST R7 K6 - 0x7C100600, // 000F CALL R4 3 - 0x80000800, // 0010 RET 0 - 0x88100107, // 0011 GETMBR R4 R0 K7 - 0x60140008, // 0012 GETGBL R5 G8 - 0x5C180800, // 0013 MOVE R6 R4 - 0x7C140200, // 0014 CALL R5 1 - 0x5C180600, // 0015 MOVE R6 R3 - 0x5C1C0000, // 0016 MOVE R7 R0 - 0x5C200800, // 0017 MOVE R8 R4 - 0x5C240400, // 0018 MOVE R9 R2 - 0x7C180600, // 0019 CALL R6 3 - 0x881C0108, // 001A GETMBR R7 R0 K8 - 0x8C1C0F09, // 001B GETMET R7 R7 K9 - 0x5C240C00, // 001C MOVE R9 R6 - 0x7C1C0400, // 001D CALL R7 2 - 0x601C0013, // 001E GETGBL R7 G19 - 0x7C1C0000, // 001F CALL R7 0 - 0x981E1401, // 0020 SETIDX R7 K10 R1 - 0x60200010, // 0021 GETGBL R8 G16 - 0x8C24050B, // 0022 GETMET R9 R2 K11 - 0x7C240200, // 0023 CALL R9 1 - 0x7C200200, // 0024 CALL R8 1 - 0xA8020004, // 0025 EXBLK 0 #002B - 0x5C241000, // 0026 MOVE R9 R8 - 0x7C240000, // 0027 CALL R9 0 - 0x94280409, // 0028 GETIDX R10 R2 R9 - 0x981C120A, // 0029 SETIDX R7 R9 R10 - 0x7001FFFA, // 002A JMP #0026 - 0x5820000C, // 002B LDCONST R8 K12 - 0xAC200200, // 002C CATCH R8 1 0 - 0xB0080000, // 002D RAISE 2 R0 R0 - 0xB8220400, // 002E GETNGBL R8 K2 - 0x8C201103, // 002F GETMET R8 R8 K3 - 0x60280018, // 0030 GETGBL R10 G24 - 0x582C000D, // 0031 LDCONST R11 K13 - 0x5C300800, // 0032 MOVE R12 R4 - 0x5C340200, // 0033 MOVE R13 R1 - 0x8C38010E, // 0034 GETMET R14 R0 K14 - 0x5C400400, // 0035 MOVE R16 R2 - 0x7C380400, // 0036 CALL R14 2 - 0x7C280800, // 0037 CALL R10 4 - 0x582C000F, // 0038 LDCONST R11 K15 - 0x7C200600, // 0039 CALL R8 3 - 0x88200110, // 003A GETMBR R8 R0 K16 - 0x98200A07, // 003B SETIDX R8 R5 R7 - 0x50200200, // 003C LDBOOL R8 1 0 - 0x90022208, // 003D SETMBR R0 K17 R8 - 0x88200107, // 003E GETMBR R8 R0 K7 - 0x00201112, // 003F ADD R8 R8 K18 - 0x90020E08, // 0040 SETMBR R0 K7 R8 - 0x8C200113, // 0041 GETMET R8 R0 K19 - 0x7C200200, // 0042 CALL R8 1 - 0x8C200114, // 0043 GETMET R8 R0 K20 - 0x7C200200, // 0044 CALL R8 1 - 0x80040800, // 0045 RET 1 R4 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: save_before_restart -********************************************************************/ -be_local_closure(Matter_Device_save_before_restart, /* name */ +be_local_closure(Matter_Device_is_commissioning_open, /* name */ be_nested_proto( 3, /* nstack */ 1, /* argc */ @@ -134,18 +19,16 @@ be_local_closure(Matter_Device_save_before_restart, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(stop_basic_commissioning), - /* K1 */ be_nested_str_weak(mdns_remove_op_discovery_all_fabrics), + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(commissioning_open), }), - be_str_weak(save_before_restart), + be_str_weak(is_commissioning_open), &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0x8C040101, // 0002 GETMET R1 R0 K1 - 0x7C040200, // 0003 CALL R1 1 - 0x80000000, // 0004 RET 0 + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x20040202, // 0002 NE R1 R1 R2 + 0x80040200, // 0003 RET 1 R1 }) ) ); @@ -153,12 +36,12 @@ be_local_closure(Matter_Device_save_before_restart, /* name */ /******************************************************************** -** Solidified function: compute_manual_pairing_code +** Solidified function: MtrInfo_one ********************************************************************/ -be_local_closure(Matter_Device_compute_manual_pairing_code, /* name */ +be_local_closure(Matter_Device_MtrInfo_one, /* name */ be_nested_proto( 9, /* nstack */ - 1, /* argc */ + 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -166,46 +49,236 @@ be_local_closure(Matter_Device_compute_manual_pairing_code, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(root_discriminator), - /* K1 */ be_nested_str_weak(root_passcode), - /* K2 */ be_nested_str_weak(_X251i_X2505i_X2504i), - /* K3 */ be_nested_str_weak(matter), - /* K4 */ be_nested_str_weak(Verhoeff), - /* K5 */ be_nested_str_weak(checksum), + /* K0 */ be_nested_str_weak(find_plugin_by_endpoint), + /* K1 */ be_nested_str_weak(state_json), + /* K2 */ be_nested_str_weak(_X7B_X22MtrInfo_X22_X3A_X25s_X7D), + /* K3 */ be_nested_str_weak(tasmota), + /* K4 */ be_nested_str_weak(publish_result), + /* K5 */ be_nested_str_weak(), }), - be_str_weak(compute_manual_pairing_code), + be_str_weak(MtrInfo_one), &be_const_str_solidified, - ( &(const binstruction[30]) { /* code */ + ( &(const binstruction[20]) { /* code */ + 0x8C080100, // 0000 GETMET R2 R0 K0 + 0x5C100200, // 0001 MOVE R4 R1 + 0x7C080400, // 0002 CALL R2 2 + 0x4C0C0000, // 0003 LDNIL R3 + 0x1C0C0403, // 0004 EQ R3 R2 R3 + 0x780E0000, // 0005 JMPF R3 #0007 + 0x80000600, // 0006 RET 0 + 0x8C0C0501, // 0007 GETMET R3 R2 K1 + 0x7C0C0200, // 0008 CALL R3 1 + 0x780E0008, // 0009 JMPF R3 #0013 + 0x60100018, // 000A GETGBL R4 G24 + 0x58140002, // 000B LDCONST R5 K2 + 0x5C180600, // 000C MOVE R6 R3 + 0x7C100400, // 000D CALL R4 2 + 0xB8160600, // 000E GETNGBL R5 K3 + 0x8C140B04, // 000F GETMET R5 R5 K4 + 0x5C1C0800, // 0010 MOVE R7 R4 + 0x58200005, // 0011 LDCONST R8 K5 + 0x7C140600, // 0012 CALL R5 3 + 0x80000000, // 0013 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: event_fabrics_saved +********************************************************************/ +be_local_closure(Matter_Device_event_fabrics_saved, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(sessions), + /* K1 */ be_nested_str_weak(count_active_fabrics), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(plugins_persist), + /* K4 */ be_nested_str_weak(save_param), + }), + be_str_weak(event_fabrics_saved), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x540A0FFE, // 0001 LDINT R2 4095 - 0x2C040202, // 0002 AND R1 R1 R2 - 0x540A0009, // 0003 LDINT R2 10 - 0x3C040202, // 0004 SHR R1 R1 R2 - 0x88080100, // 0005 GETMBR R2 R0 K0 - 0x540E02FF, // 0006 LDINT R3 768 - 0x2C080403, // 0007 AND R2 R2 R3 - 0x540E0005, // 0008 LDINT R3 6 - 0x38080403, // 0009 SHL R2 R2 R3 - 0x880C0101, // 000A GETMBR R3 R0 K1 - 0x54123FFE, // 000B LDINT R4 16383 - 0x2C0C0604, // 000C AND R3 R3 R4 - 0x30080403, // 000D OR R2 R2 R3 - 0x880C0101, // 000E GETMBR R3 R0 K1 - 0x5412000D, // 000F LDINT R4 14 - 0x3C0C0604, // 0010 SHR R3 R3 R4 - 0x60100018, // 0011 GETGBL R4 G24 - 0x58140002, // 0012 LDCONST R5 K2 - 0x5C180200, // 0013 MOVE R6 R1 - 0x5C1C0400, // 0014 MOVE R7 R2 - 0x5C200600, // 0015 MOVE R8 R3 - 0x7C100800, // 0016 CALL R4 4 - 0xB8160600, // 0017 GETNGBL R5 K3 - 0x88140B04, // 0018 GETMBR R5 R5 K4 - 0x8C140B05, // 0019 GETMET R5 R5 K5 - 0x5C1C0800, // 001A MOVE R7 R4 - 0x7C140400, // 001B CALL R5 2 - 0x00100805, // 001C ADD R4 R4 R5 - 0x80040800, // 001D RET 1 R4 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x24040302, // 0003 GT R1 R1 K2 + 0x78060005, // 0004 JMPF R1 #000B + 0x88040103, // 0005 GETMBR R1 R0 K3 + 0x74060003, // 0006 JMPT R1 #000B + 0x50040200, // 0007 LDBOOL R1 1 0 + 0x90020601, // 0008 SETMBR R0 K3 R1 + 0x8C040104, // 0009 GETMET R1 R0 K4 + 0x7C040200, // 000A CALL R1 1 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start_commissioning_complete +********************************************************************/ +be_local_closure(Matter_Device_start_commissioning_complete, /* name */ + be_nested_proto( + 11, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_str_weak(get_fabric), + /* K1 */ be_nested_str_weak(get_fabric_id), + /* K2 */ be_nested_str_weak(copy), + /* K3 */ be_nested_str_weak(reverse), + /* K4 */ be_nested_str_weak(tohex), + /* K5 */ be_nested_str_weak(get_admin_vendor_name), + /* K6 */ be_nested_str_weak(tasmota), + /* K7 */ be_nested_str_weak(log), + /* K8 */ be_nested_str_weak(MTR_X3A_X20_X2D_X2D_X2D_X20Commissioning_X20complete_X20for_X20Fabric_X20_X27_X25s_X27_X20_X28Vendor_X20_X25s_X29_X20_X2D_X2D_X2D), + /* K9 */ be_const_int(2), + /* K10 */ be_nested_str_weak(stop_basic_commissioning), + }), + be_str_weak(start_commissioning_complete), + &be_const_str_solidified, + ( &(const binstruction[24]) { /* code */ + 0x8C080300, // 0000 GETMET R2 R1 K0 + 0x7C080200, // 0001 CALL R2 1 + 0x8C0C0501, // 0002 GETMET R3 R2 K1 + 0x7C0C0200, // 0003 CALL R3 1 + 0x8C0C0702, // 0004 GETMET R3 R3 K2 + 0x7C0C0200, // 0005 CALL R3 1 + 0x8C0C0703, // 0006 GETMET R3 R3 K3 + 0x7C0C0200, // 0007 CALL R3 1 + 0x8C0C0704, // 0008 GETMET R3 R3 K4 + 0x7C0C0200, // 0009 CALL R3 1 + 0x8C100505, // 000A GETMET R4 R2 K5 + 0x7C100200, // 000B CALL R4 1 + 0xB8160C00, // 000C GETNGBL R5 K6 + 0x8C140B07, // 000D GETMET R5 R5 K7 + 0x601C0018, // 000E GETGBL R7 G24 + 0x58200008, // 000F LDCONST R8 K8 + 0x5C240600, // 0010 MOVE R9 R3 + 0x5C280800, // 0011 MOVE R10 R4 + 0x7C1C0600, // 0012 CALL R7 3 + 0x58200009, // 0013 LDCONST R8 K9 + 0x7C140600, // 0014 CALL R5 3 + 0x8C14010A, // 0015 GETMET R5 R0 K10 + 0x7C140200, // 0016 CALL R5 1 + 0x80000000, // 0017 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: bridge_remove_endpoint +********************************************************************/ +be_local_closure(Matter_Device_bridge_remove_endpoint, /* name */ + be_nested_proto( + 11, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[18]) { /* constants */ + /* K0 */ be_nested_str_weak(json), + /* K1 */ be_nested_str_weak(plugins_config), + /* K2 */ be_nested_str_weak(contains), + /* K3 */ be_nested_str_weak(tasmota), + /* K4 */ be_nested_str_weak(log), + /* K5 */ be_nested_str_weak(MTR_X3A_X20Cannot_X20remove_X20an_X20enpoint_X20not_X20configured_X3A_X20), + /* K6 */ be_const_int(3), + /* K7 */ be_nested_str_weak(MTR_X3A_X20deleting_X20endpoint_X20_X3D_X20_X25i), + /* K8 */ be_const_int(2), + /* K9 */ be_nested_str_weak(remove), + /* K10 */ be_nested_str_weak(plugins_persist), + /* K11 */ be_const_int(0), + /* K12 */ be_nested_str_weak(plugins), + /* K13 */ be_nested_str_weak(get_endpoint), + /* K14 */ be_const_int(1), + /* K15 */ be_nested_str_weak(clean_remotes), + /* K16 */ be_nested_str_weak(save_param), + /* K17 */ be_nested_str_weak(signal_endpoints_changed), + }), + be_str_weak(bridge_remove_endpoint), + &be_const_str_solidified, + ( &(const binstruction[58]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0x600C0008, // 0001 GETGBL R3 G8 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C0C0200, // 0003 CALL R3 1 + 0x4C100000, // 0004 LDNIL R4 + 0x4C140000, // 0005 LDNIL R5 + 0x88180101, // 0006 GETMBR R6 R0 K1 + 0x8C180D02, // 0007 GETMET R6 R6 K2 + 0x5C200600, // 0008 MOVE R8 R3 + 0x7C180400, // 0009 CALL R6 2 + 0x741A0005, // 000A JMPT R6 #0011 + 0xB81A0600, // 000B GETNGBL R6 K3 + 0x8C180D04, // 000C GETMET R6 R6 K4 + 0x00220A03, // 000D ADD R8 K5 R3 + 0x58240006, // 000E LDCONST R9 K6 + 0x7C180600, // 000F CALL R6 3 + 0x80000C00, // 0010 RET 0 + 0xB81A0600, // 0011 GETNGBL R6 K3 + 0x8C180D04, // 0012 GETMET R6 R6 K4 + 0x60200018, // 0013 GETGBL R8 G24 + 0x58240007, // 0014 LDCONST R9 K7 + 0x5C280200, // 0015 MOVE R10 R1 + 0x7C200400, // 0016 CALL R8 2 + 0x58240008, // 0017 LDCONST R9 K8 + 0x7C180600, // 0018 CALL R6 3 + 0x88180101, // 0019 GETMBR R6 R0 K1 + 0x8C180D09, // 001A GETMET R6 R6 K9 + 0x5C200600, // 001B MOVE R8 R3 + 0x7C180400, // 001C CALL R6 2 + 0x50180200, // 001D LDBOOL R6 1 0 + 0x90021406, // 001E SETMBR R0 K10 R6 + 0x5818000B, // 001F LDCONST R6 K11 + 0x601C000C, // 0020 GETGBL R7 G12 + 0x8820010C, // 0021 GETMBR R8 R0 K12 + 0x7C1C0200, // 0022 CALL R7 1 + 0x141C0C07, // 0023 LT R7 R6 R7 + 0x781E000D, // 0024 JMPF R7 #0033 + 0x881C010C, // 0025 GETMBR R7 R0 K12 + 0x941C0E06, // 0026 GETIDX R7 R7 R6 + 0x8C1C0F0D, // 0027 GETMET R7 R7 K13 + 0x7C1C0200, // 0028 CALL R7 1 + 0x1C1C0207, // 0029 EQ R7 R1 R7 + 0x781E0005, // 002A JMPF R7 #0031 + 0x881C010C, // 002B GETMBR R7 R0 K12 + 0x8C1C0F09, // 002C GETMET R7 R7 K9 + 0x5C240C00, // 002D MOVE R9 R6 + 0x7C1C0400, // 002E CALL R7 2 + 0x70020002, // 002F JMP #0033 + 0x70020000, // 0030 JMP #0032 + 0x00180D0E, // 0031 ADD R6 R6 K14 + 0x7001FFEC, // 0032 JMP #0020 + 0x8C1C010F, // 0033 GETMET R7 R0 K15 + 0x7C1C0200, // 0034 CALL R7 1 + 0x8C1C0110, // 0035 GETMET R7 R0 K16 + 0x7C1C0200, // 0036 CALL R7 1 + 0x8C1C0111, // 0037 GETMET R7 R0 K17 + 0x7C1C0200, // 0038 CALL R7 1 + 0x80000000, // 0039 RET 0 }) ) ); @@ -338,102 +411,6 @@ be_local_closure(Matter_Device_mdns_remove_PASE, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: conf_to_log -********************************************************************/ -be_local_closure(Matter_Device_conf_to_log, /* name */ - be_nested_proto( - 9, /* nstack */ - 1, /* argc */ - 4, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_const_class(be_class_Matter_Device), - /* K1 */ be_nested_str_weak(), - /* K2 */ be_nested_str_weak(k2l), - /* K3 */ be_nested_str_weak(type), - /* K4 */ be_nested_str_weak(_X20_X25s_X3A_X25s), - /* K5 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(conf_to_log), - &be_const_str_solidified, - ( &(const binstruction[24]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x58080001, // 0001 LDCONST R2 K1 - 0x600C0010, // 0002 GETGBL R3 G16 - 0x8C100302, // 0003 GETMET R4 R1 K2 - 0x5C180000, // 0004 MOVE R6 R0 - 0x7C100400, // 0005 CALL R4 2 - 0x7C0C0200, // 0006 CALL R3 1 - 0xA802000B, // 0007 EXBLK 0 #0014 - 0x5C100600, // 0008 MOVE R4 R3 - 0x7C100000, // 0009 CALL R4 0 - 0x1C140903, // 000A EQ R5 R4 K3 - 0x78160000, // 000B JMPF R5 #000D - 0x7001FFFA, // 000C JMP #0008 - 0x60140018, // 000D GETGBL R5 G24 - 0x58180004, // 000E LDCONST R6 K4 - 0x5C1C0800, // 000F MOVE R7 R4 - 0x94200004, // 0010 GETIDX R8 R0 R4 - 0x7C140600, // 0011 CALL R5 3 - 0x00080405, // 0012 ADD R2 R2 R5 - 0x7001FFF3, // 0013 JMP #0008 - 0x580C0005, // 0014 LDCONST R3 K5 - 0xAC0C0200, // 0015 CATCH R3 1 0 - 0xB0080000, // 0016 RAISE 2 R0 R0 - 0x80040400, // 0017 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: start_operational_discovery -********************************************************************/ -be_local_closure(Matter_Device_start_operational_discovery, /* name */ - be_nested_proto( - 7, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(crypto), - /* K1 */ be_nested_str_weak(mdns), - /* K2 */ be_nested_str_weak(stop_basic_commissioning), - /* K3 */ be_nested_str_weak(root_w0), - /* K4 */ be_nested_str_weak(root_L), - /* K5 */ be_nested_str_weak(mdns_announce_op_discovery), - }), - be_str_weak(start_operational_discovery), - &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0xA40E0200, // 0001 IMPORT R3 K1 - 0x8C100102, // 0002 GETMET R4 R0 K2 - 0x7C100200, // 0003 CALL R4 1 - 0x4C100000, // 0004 LDNIL R4 - 0x90020604, // 0005 SETMBR R0 K3 R4 - 0x4C100000, // 0006 LDNIL R4 - 0x90020804, // 0007 SETMBR R0 K4 R4 - 0x8C100105, // 0008 GETMET R4 R0 K5 - 0x5C180200, // 0009 MOVE R6 R1 - 0x7C100400, // 000A CALL R4 2 - 0x80000000, // 000B RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: _mdns_announce_hostname ********************************************************************/ @@ -633,6 +610,60 @@ be_local_closure(Matter_Device__mdns_announce_hostname, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: conf_to_log +********************************************************************/ +be_local_closure(Matter_Device_conf_to_log, /* name */ + be_nested_proto( + 9, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_const_class(be_class_Matter_Device), + /* K1 */ be_nested_str_weak(), + /* K2 */ be_nested_str_weak(k2l), + /* K3 */ be_nested_str_weak(type), + /* K4 */ be_nested_str_weak(_X20_X25s_X3A_X25s), + /* K5 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(conf_to_log), + &be_const_str_solidified, + ( &(const binstruction[24]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x58080001, // 0001 LDCONST R2 K1 + 0x600C0010, // 0002 GETGBL R3 G16 + 0x8C100302, // 0003 GETMET R4 R1 K2 + 0x5C180000, // 0004 MOVE R6 R0 + 0x7C100400, // 0005 CALL R4 2 + 0x7C0C0200, // 0006 CALL R3 1 + 0xA802000B, // 0007 EXBLK 0 #0014 + 0x5C100600, // 0008 MOVE R4 R3 + 0x7C100000, // 0009 CALL R4 0 + 0x1C140903, // 000A EQ R5 R4 K3 + 0x78160000, // 000B JMPF R5 #000D + 0x7001FFFA, // 000C JMP #0008 + 0x60140018, // 000D GETGBL R5 G24 + 0x58180004, // 000E LDCONST R6 K4 + 0x5C1C0800, // 000F MOVE R7 R4 + 0x94200004, // 0010 GETIDX R8 R0 R4 + 0x7C140600, // 0011 CALL R5 3 + 0x00080405, // 0012 ADD R2 R2 R5 + 0x7001FFF3, // 0013 JMP #0008 + 0x580C0005, // 0014 LDCONST R3 K5 + 0xAC0C0200, // 0015 CATCH R3 1 0 + 0xB0080000, // 0016 RAISE 2 R0 R0 + 0x80040400, // 0017 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: invoke_request ********************************************************************/ @@ -763,9 +794,9 @@ be_local_closure(Matter_Device_MtrInfo, /* name */ /******************************************************************** -** Solidified function: received_ack +** Solidified function: get_plugin_class_displayname ********************************************************************/ -be_local_closure(Matter_Device_received_ack, /* name */ +be_local_closure(Matter_Device_get_plugin_class_displayname, /* name */ be_nested_proto( 5, /* nstack */ 2, /* argc */ @@ -775,18 +806,24 @@ be_local_closure(Matter_Device_received_ack, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(udp_server), - /* K1 */ be_nested_str_weak(received_ack), + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(plugins_classes), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(DISPLAY_NAME), + /* K3 */ be_nested_str_weak(), }), - be_str_weak(received_ack), + be_str_weak(get_plugin_class_displayname), &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ + ( &(const binstruction[ 9]) { /* code */ 0x88080100, // 0000 GETMBR R2 R0 K0 0x8C080501, // 0001 GETMET R2 R2 K1 0x5C100200, // 0002 MOVE R4 R1 0x7C080400, // 0003 CALL R2 2 - 0x80040400, // 0004 RET 1 R2 + 0x780A0001, // 0004 JMPF R2 #0007 + 0x880C0502, // 0005 GETMBR R3 R2 K2 + 0x70020000, // 0006 JMP #0008 + 0x580C0003, // 0007 LDCONST R3 K3 + 0x80040600, // 0008 RET 1 R3 }) ) ); @@ -794,11 +831,200 @@ be_local_closure(Matter_Device_received_ack, /* name */ /******************************************************************** -** Solidified function: MtrInfo_one +** Solidified function: bridge_add_endpoint ********************************************************************/ -be_local_closure(Matter_Device_MtrInfo_one, /* name */ +be_local_closure(Matter_Device_bridge_add_endpoint, /* name */ + be_nested_proto( + 17, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[21]) { /* constants */ + /* K0 */ be_nested_str_weak(plugins_classes), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(tasmota), + /* K3 */ be_nested_str_weak(log), + /* K4 */ be_nested_str_weak(MTR_X3A_X20unknown_X20class_X20name_X20_X27), + /* K5 */ be_nested_str_weak(_X27_X20skipping), + /* K6 */ be_const_int(3), + /* K7 */ be_nested_str_weak(next_ep), + /* K8 */ be_nested_str_weak(plugins), + /* K9 */ be_nested_str_weak(push), + /* K10 */ be_nested_str_weak(type), + /* K11 */ be_nested_str_weak(keys), + /* K12 */ be_nested_str_weak(stop_iteration), + /* K13 */ be_nested_str_weak(MTR_X3A_X20adding_X20endpoint_X20_X3D_X20_X25i_X20type_X3A_X25s_X25s), + /* K14 */ be_nested_str_weak(conf_to_log), + /* K15 */ be_const_int(2), + /* K16 */ be_nested_str_weak(plugins_config), + /* K17 */ be_nested_str_weak(plugins_persist), + /* K18 */ be_const_int(1), + /* K19 */ be_nested_str_weak(save_param), + /* K20 */ be_nested_str_weak(signal_endpoints_changed), + }), + be_str_weak(bridge_add_endpoint), + &be_const_str_solidified, + ( &(const binstruction[70]) { /* code */ + 0x880C0100, // 0000 GETMBR R3 R0 K0 + 0x8C0C0701, // 0001 GETMET R3 R3 K1 + 0x5C140200, // 0002 MOVE R5 R1 + 0x7C0C0400, // 0003 CALL R3 2 + 0x4C100000, // 0004 LDNIL R4 + 0x1C100604, // 0005 EQ R4 R3 R4 + 0x78120009, // 0006 JMPF R4 #0011 + 0xB8120400, // 0007 GETNGBL R4 K2 + 0x8C100903, // 0008 GETMET R4 R4 K3 + 0x60180008, // 0009 GETGBL R6 G8 + 0x5C1C0200, // 000A MOVE R7 R1 + 0x7C180200, // 000B CALL R6 1 + 0x001A0806, // 000C ADD R6 K4 R6 + 0x00180D05, // 000D ADD R6 R6 K5 + 0x581C0006, // 000E LDCONST R7 K6 + 0x7C100600, // 000F CALL R4 3 + 0x80000800, // 0010 RET 0 + 0x88100107, // 0011 GETMBR R4 R0 K7 + 0x60140008, // 0012 GETGBL R5 G8 + 0x5C180800, // 0013 MOVE R6 R4 + 0x7C140200, // 0014 CALL R5 1 + 0x5C180600, // 0015 MOVE R6 R3 + 0x5C1C0000, // 0016 MOVE R7 R0 + 0x5C200800, // 0017 MOVE R8 R4 + 0x5C240400, // 0018 MOVE R9 R2 + 0x7C180600, // 0019 CALL R6 3 + 0x881C0108, // 001A GETMBR R7 R0 K8 + 0x8C1C0F09, // 001B GETMET R7 R7 K9 + 0x5C240C00, // 001C MOVE R9 R6 + 0x7C1C0400, // 001D CALL R7 2 + 0x601C0013, // 001E GETGBL R7 G19 + 0x7C1C0000, // 001F CALL R7 0 + 0x981E1401, // 0020 SETIDX R7 K10 R1 + 0x60200010, // 0021 GETGBL R8 G16 + 0x8C24050B, // 0022 GETMET R9 R2 K11 + 0x7C240200, // 0023 CALL R9 1 + 0x7C200200, // 0024 CALL R8 1 + 0xA8020004, // 0025 EXBLK 0 #002B + 0x5C241000, // 0026 MOVE R9 R8 + 0x7C240000, // 0027 CALL R9 0 + 0x94280409, // 0028 GETIDX R10 R2 R9 + 0x981C120A, // 0029 SETIDX R7 R9 R10 + 0x7001FFFA, // 002A JMP #0026 + 0x5820000C, // 002B LDCONST R8 K12 + 0xAC200200, // 002C CATCH R8 1 0 + 0xB0080000, // 002D RAISE 2 R0 R0 + 0xB8220400, // 002E GETNGBL R8 K2 + 0x8C201103, // 002F GETMET R8 R8 K3 + 0x60280018, // 0030 GETGBL R10 G24 + 0x582C000D, // 0031 LDCONST R11 K13 + 0x5C300800, // 0032 MOVE R12 R4 + 0x5C340200, // 0033 MOVE R13 R1 + 0x8C38010E, // 0034 GETMET R14 R0 K14 + 0x5C400400, // 0035 MOVE R16 R2 + 0x7C380400, // 0036 CALL R14 2 + 0x7C280800, // 0037 CALL R10 4 + 0x582C000F, // 0038 LDCONST R11 K15 + 0x7C200600, // 0039 CALL R8 3 + 0x88200110, // 003A GETMBR R8 R0 K16 + 0x98200A07, // 003B SETIDX R8 R5 R7 + 0x50200200, // 003C LDBOOL R8 1 0 + 0x90022208, // 003D SETMBR R0 K17 R8 + 0x88200107, // 003E GETMBR R8 R0 K7 + 0x00201112, // 003F ADD R8 R8 K18 + 0x90020E08, // 0040 SETMBR R0 K7 R8 + 0x8C200113, // 0041 GETMET R8 R0 K19 + 0x7C200200, // 0042 CALL R8 1 + 0x8C200114, // 0043 GETMET R8 R0 K20 + 0x7C200200, // 0044 CALL R8 1 + 0x80040800, // 0045 RET 1 R4 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: register_http_remote +********************************************************************/ +be_local_closure(Matter_Device_register_http_remote, /* name */ be_nested_proto( 9, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_str_weak(http_remotes), + /* K1 */ be_nested_str_weak(contains), + /* K2 */ be_nested_str_weak(get_timeout), + /* K3 */ be_nested_str_weak(set_timeout), + /* K4 */ be_nested_str_weak(matter), + /* K5 */ be_nested_str_weak(HTTP_remote), + /* K6 */ be_nested_str_weak(plugins_config_remotes), + /* K7 */ be_nested_str_weak(set_info), + }), + be_str_weak(register_http_remote), + &be_const_str_solidified, + ( &(const binstruction[42]) { /* code */ + 0x880C0100, // 0000 GETMBR R3 R0 K0 + 0x4C100000, // 0001 LDNIL R4 + 0x1C0C0604, // 0002 EQ R3 R3 R4 + 0x780E0002, // 0003 JMPF R3 #0007 + 0x600C0013, // 0004 GETGBL R3 G19 + 0x7C0C0000, // 0005 CALL R3 0 + 0x90020003, // 0006 SETMBR R0 K0 R3 + 0x4C0C0000, // 0007 LDNIL R3 + 0x88100100, // 0008 GETMBR R4 R0 K0 + 0x8C100901, // 0009 GETMET R4 R4 K1 + 0x5C180200, // 000A MOVE R6 R1 + 0x7C100400, // 000B CALL R4 2 + 0x78120009, // 000C JMPF R4 #0017 + 0x88100100, // 000D GETMBR R4 R0 K0 + 0x940C0801, // 000E GETIDX R3 R4 R1 + 0x8C140702, // 000F GETMET R5 R3 K2 + 0x7C140200, // 0010 CALL R5 1 + 0x14140405, // 0011 LT R5 R2 R5 + 0x78160002, // 0012 JMPF R5 #0016 + 0x8C140703, // 0013 GETMET R5 R3 K3 + 0x5C1C0400, // 0014 MOVE R7 R2 + 0x7C140400, // 0015 CALL R5 2 + 0x70020011, // 0016 JMP #0029 + 0xB8120800, // 0017 GETNGBL R4 K4 + 0x8C100905, // 0018 GETMET R4 R4 K5 + 0x5C180000, // 0019 MOVE R6 R0 + 0x5C1C0200, // 001A MOVE R7 R1 + 0x5C200400, // 001B MOVE R8 R2 + 0x7C100800, // 001C CALL R4 4 + 0x5C0C0800, // 001D MOVE R3 R4 + 0x88100106, // 001E GETMBR R4 R0 K6 + 0x8C100901, // 001F GETMET R4 R4 K1 + 0x5C180200, // 0020 MOVE R6 R1 + 0x7C100400, // 0021 CALL R4 2 + 0x78120003, // 0022 JMPF R4 #0027 + 0x8C100707, // 0023 GETMET R4 R3 K7 + 0x88180106, // 0024 GETMBR R6 R0 K6 + 0x94180C01, // 0025 GETIDX R6 R6 R1 + 0x7C100400, // 0026 CALL R4 2 + 0x88100100, // 0027 GETMBR R4 R0 K0 + 0x98100203, // 0028 SETIDX R4 R1 R3 + 0x80040600, // 0029 RET 1 R3 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: add_read_sensors_schedule +********************************************************************/ +be_local_closure(Matter_Device_add_read_sensors_schedule, /* name */ + be_nested_proto( + 5, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -806,37 +1032,29 @@ be_local_closure(Matter_Device_MtrInfo_one, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(find_plugin_by_endpoint), - /* K1 */ be_nested_str_weak(state_json), - /* K2 */ be_nested_str_weak(_X7B_X22MtrInfo_X22_X3A_X25s_X7D), - /* K3 */ be_nested_str_weak(tasmota), - /* K4 */ be_nested_str_weak(publish_result), - /* K5 */ be_nested_str_weak(), + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(probe_sensor_time), + /* K1 */ be_nested_str_weak(probe_sensor_timestamp), + /* K2 */ be_nested_str_weak(matter), + /* K3 */ be_nested_str_weak(jitter), }), - be_str_weak(MtrInfo_one), + be_str_weak(add_read_sensors_schedule), &be_const_str_solidified, - ( &(const binstruction[20]) { /* code */ - 0x8C080100, // 0000 GETMET R2 R0 K0 - 0x5C100200, // 0001 MOVE R4 R1 - 0x7C080400, // 0002 CALL R2 2 - 0x4C0C0000, // 0003 LDNIL R3 - 0x1C0C0403, // 0004 EQ R3 R2 R3 - 0x780E0000, // 0005 JMPF R3 #0007 - 0x80000600, // 0006 RET 0 - 0x8C0C0501, // 0007 GETMET R3 R2 K1 - 0x7C0C0200, // 0008 CALL R3 1 - 0x780E0008, // 0009 JMPF R3 #0013 - 0x60100018, // 000A GETGBL R4 G24 - 0x58140002, // 000B LDCONST R5 K2 - 0x5C180600, // 000C MOVE R6 R3 - 0x7C100400, // 000D CALL R4 2 - 0xB8160600, // 000E GETNGBL R5 K3 - 0x8C140B04, // 000F GETMET R5 R5 K4 - 0x5C1C0800, // 0010 MOVE R7 R4 - 0x58200005, // 0011 LDCONST R8 K5 - 0x7C140600, // 0012 CALL R5 3 - 0x80000000, // 0013 RET 0 + ( &(const binstruction[14]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x1C080403, // 0002 EQ R2 R2 R3 + 0x740A0002, // 0003 JMPT R2 #0007 + 0x88080100, // 0004 GETMBR R2 R0 K0 + 0x24080401, // 0005 GT R2 R2 R1 + 0x780A0005, // 0006 JMPF R2 #000D + 0x90020001, // 0007 SETMBR R0 K0 R1 + 0xB80A0400, // 0008 GETNGBL R2 K2 + 0x8C080503, // 0009 GETMET R2 R2 K3 + 0x5C100200, // 000A MOVE R4 R1 + 0x7C080400, // 000B CALL R2 2 + 0x90020202, // 000C SETMBR R0 K1 R2 + 0x80000000, // 000D RET 0 }) ) ); @@ -844,142 +1062,32 @@ be_local_closure(Matter_Device_MtrInfo_one, /* name */ /******************************************************************** -** Solidified function: start_basic_commissioning +** Solidified function: msg_received ********************************************************************/ -be_local_closure(Matter_Device_start_basic_commissioning, /* name */ +be_local_closure(Matter_Device_msg_received, /* name */ be_nested_proto( - 13, /* nstack */ - 8, /* argc */ + 9, /* nstack */ + 4, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 2]) { - be_nested_proto( - 4, /* nstack */ - 0, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(mdns_announce_PASE), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(remove_rule), - /* K3 */ be_nested_str_weak(Wifi_X23Connected), - }), - be_str_weak(_anonymous_), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0x68000000, // 0000 GETUPV R0 U0 - 0x8C000100, // 0001 GETMET R0 R0 K0 - 0x7C000200, // 0002 CALL R0 1 - 0xB8020200, // 0003 GETNGBL R0 K1 - 0x8C000102, // 0004 GETMET R0 R0 K2 - 0x58080003, // 0005 LDCONST R2 K3 - 0x580C0000, // 0006 LDCONST R3 K0 - 0x7C000600, // 0007 CALL R0 3 - 0x80000000, // 0008 RET 0 - }) - ), - be_nested_proto( - 4, /* nstack */ - 0, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(mdns_announce_PASE), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(remove_rule), - /* K3 */ be_nested_str_weak(Eth_X23Connected), - }), - be_str_weak(_anonymous_), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0x68000000, // 0000 GETUPV R0 U0 - 0x8C000100, // 0001 GETMET R0 R0 K0 - 0x7C000200, // 0002 CALL R0 1 - 0xB8020200, // 0003 GETNGBL R0 K1 - 0x8C000102, // 0004 GETMET R0 R0 K2 - 0x58080003, // 0005 LDCONST R2 K3 - 0x580C0000, // 0006 LDCONST R3 K0 - 0x7C000600, // 0007 CALL R0 3 - 0x80000000, // 0008 RET 0 - }) - ), - }), + 0, /* has sup protos */ + NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[16]) { /* constants */ - /* K0 */ be_nested_str_weak(commissioning_open), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(millis), - /* K3 */ be_nested_str_weak(commissioning_iterations), - /* K4 */ be_nested_str_weak(commissioning_discriminator), - /* K5 */ be_nested_str_weak(commissioning_salt), - /* K6 */ be_nested_str_weak(commissioning_w0), - /* K7 */ be_nested_str_weak(commissioning_L), - /* K8 */ be_nested_str_weak(commissioning_admin_fabric), - /* K9 */ be_nested_str_weak(wifi), - /* K10 */ be_nested_str_weak(up), - /* K11 */ be_nested_str_weak(eth), - /* K12 */ be_nested_str_weak(mdns_announce_PASE), - /* K13 */ be_nested_str_weak(add_rule), - /* K14 */ be_nested_str_weak(Wifi_X23Connected), - /* K15 */ be_nested_str_weak(Eth_X23Connected), + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(message_handler), + /* K1 */ be_nested_str_weak(msg_received), }), - be_str_weak(start_basic_commissioning), + be_str_weak(msg_received), &be_const_str_solidified, - ( &(const binstruction[40]) { /* code */ - 0xB8220200, // 0000 GETNGBL R8 K1 - 0x8C201102, // 0001 GETMET R8 R8 K2 - 0x7C200200, // 0002 CALL R8 1 - 0x542603E7, // 0003 LDINT R9 1000 - 0x08240209, // 0004 MUL R9 R1 R9 - 0x00201009, // 0005 ADD R8 R8 R9 - 0x90020008, // 0006 SETMBR R0 K0 R8 - 0x90020602, // 0007 SETMBR R0 K3 R2 - 0x90020803, // 0008 SETMBR R0 K4 R3 - 0x90020A04, // 0009 SETMBR R0 K5 R4 - 0x90020C05, // 000A SETMBR R0 K6 R5 - 0x90020E06, // 000B SETMBR R0 K7 R6 - 0x90021007, // 000C SETMBR R0 K8 R7 - 0xB8220200, // 000D GETNGBL R8 K1 - 0x8C201109, // 000E GETMET R8 R8 K9 - 0x7C200200, // 000F CALL R8 1 - 0x9420110A, // 0010 GETIDX R8 R8 K10 - 0x74220004, // 0011 JMPT R8 #0017 - 0xB8220200, // 0012 GETNGBL R8 K1 - 0x8C20110B, // 0013 GETMET R8 R8 K11 - 0x7C200200, // 0014 CALL R8 1 - 0x9420110A, // 0015 GETIDX R8 R8 K10 - 0x78220002, // 0016 JMPF R8 #001A - 0x8C20010C, // 0017 GETMET R8 R0 K12 - 0x7C200200, // 0018 CALL R8 1 - 0x7002000B, // 0019 JMP #0026 - 0xB8220200, // 001A GETNGBL R8 K1 - 0x8C20110D, // 001B GETMET R8 R8 K13 - 0x5828000E, // 001C LDCONST R10 K14 - 0x842C0000, // 001D CLOSURE R11 P0 - 0x5830000C, // 001E LDCONST R12 K12 - 0x7C200800, // 001F CALL R8 4 - 0xB8220200, // 0020 GETNGBL R8 K1 - 0x8C20110D, // 0021 GETMET R8 R8 K13 - 0x5828000F, // 0022 LDCONST R10 K15 - 0x842C0001, // 0023 CLOSURE R11 P1 - 0x5830000C, // 0024 LDCONST R12 K12 - 0x7C200800, // 0025 CALL R8 4 - 0xA0000000, // 0026 CLOSE R0 - 0x80000000, // 0027 RET 0 + ( &(const binstruction[ 7]) { /* code */ + 0x88100100, // 0000 GETMBR R4 R0 K0 + 0x8C100901, // 0001 GETMET R4 R4 K1 + 0x5C180200, // 0002 MOVE R6 R1 + 0x5C1C0400, // 0003 MOVE R7 R2 + 0x5C200600, // 0004 MOVE R8 R3 + 0x7C100800, // 0005 CALL R4 4 + 0x80040800, // 0006 RET 1 R4 }) ) ); @@ -1063,9 +1171,270 @@ be_local_closure(Matter_Device_compute_qrcode_content, /* name */ /******************************************************************** -** Solidified function: autoconf_device +** Solidified function: autoconf_device_map ********************************************************************/ -be_local_closure(Matter_Device_autoconf_device, /* name */ +be_local_closure(Matter_Device_autoconf_device_map, /* name */ + be_nested_proto( + 20, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[38]) { /* constants */ + /* K0 */ be_nested_str_weak(json), + /* K1 */ be_nested_str_weak(matter), + /* K2 */ be_nested_str_weak(START_ENDPOINT), + /* K3 */ be_nested_str_weak(light), + /* K4 */ be_nested_str_weak(get), + /* K5 */ be_nested_str_weak(find), + /* K6 */ be_nested_str_weak(channels), + /* K7 */ be_nested_str_weak(), + /* K8 */ be_const_int(0), + /* K9 */ be_const_int(1), + /* K10 */ be_nested_str_weak(type), + /* K11 */ be_nested_str_weak(light1), + /* K12 */ be_const_int(2), + /* K13 */ be_nested_str_weak(light2), + /* K14 */ be_nested_str_weak(light3), + /* K15 */ be_nested_str_weak(tasmota), + /* K16 */ be_nested_str_weak(cmd), + /* K17 */ be_nested_str_weak(Status_X2013), + /* K18 */ be_nested_str_weak(log), + /* K19 */ be_nested_str_weak(MTR_X3A_X20Status_X2013_X20_X3D_X20), + /* K20 */ be_const_int(3), + /* K21 */ be_nested_str_weak(contains), + /* K22 */ be_nested_str_weak(StatusSHT), + /* K23 */ be_nested_str_weak(SHT), + /* K24 */ be_nested_str_weak(MTR_X3A_X20_X27_X25s_X27_X20_X3D_X20_X25s), + /* K25 */ be_nested_str_weak(Relay1), + /* K26 */ be_nested_str_weak(Relay2), + /* K27 */ be_nested_str_weak(push), + /* K28 */ be_nested_str_weak(MTR_X3A_X20relay1_X3D_X25s_X20relay2_X3D_X25s), + /* K29 */ be_nested_str_weak(TiltConfig), + /* K30 */ be_nested_str_weak(shutter_X2Btilt), + /* K31 */ be_nested_str_weak(shutter), + /* K32 */ be_nested_str_weak(get_power), + /* K33 */ be_nested_str_weak(relay), + /* K34 */ be_nested_str_weak(load), + /* K35 */ be_nested_str_weak(read_sensors), + /* K36 */ be_nested_str_weak(autoconf_sensors_list), + /* K37 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(autoconf_device_map), + &be_const_str_solidified, + ( &(const binstruction[199]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x60080013, // 0001 GETGBL R2 G19 + 0x7C080000, // 0002 CALL R2 0 + 0xB80E0200, // 0003 GETNGBL R3 K1 + 0x880C0702, // 0004 GETMBR R3 R3 K2 + 0x50100000, // 0005 LDBOOL R4 0 0 + 0xA4160600, // 0006 IMPORT R5 K3 + 0x8C180B04, // 0007 GETMET R6 R5 K4 + 0x7C180200, // 0008 CALL R6 1 + 0x4C1C0000, // 0009 LDNIL R7 + 0x201C0C07, // 000A NE R7 R6 R7 + 0x781E0024, // 000B JMPF R7 #0031 + 0x601C000C, // 000C GETGBL R7 G12 + 0x8C200D05, // 000D GETMET R8 R6 K5 + 0x58280006, // 000E LDCONST R10 K6 + 0x582C0007, // 000F LDCONST R11 K7 + 0x7C200600, // 0010 CALL R8 3 + 0x7C1C0200, // 0011 CALL R7 1 + 0x24200F08, // 0012 GT R8 R7 K8 + 0x7822001C, // 0013 JMPF R8 #0031 + 0x1C200F09, // 0014 EQ R8 R7 K9 + 0x78220007, // 0015 JMPF R8 #001E + 0x60200008, // 0016 GETGBL R8 G8 + 0x5C240600, // 0017 MOVE R9 R3 + 0x7C200200, // 0018 CALL R8 1 + 0x60240013, // 0019 GETGBL R9 G19 + 0x7C240000, // 001A CALL R9 0 + 0x9826150B, // 001B SETIDX R9 K10 K11 + 0x98081009, // 001C SETIDX R2 R8 R9 + 0x70020010, // 001D JMP #002F + 0x1C200F0C, // 001E EQ R8 R7 K12 + 0x78220007, // 001F JMPF R8 #0028 + 0x60200008, // 0020 GETGBL R8 G8 + 0x5C240600, // 0021 MOVE R9 R3 + 0x7C200200, // 0022 CALL R8 1 + 0x60240013, // 0023 GETGBL R9 G19 + 0x7C240000, // 0024 CALL R9 0 + 0x9826150D, // 0025 SETIDX R9 K10 K13 + 0x98081009, // 0026 SETIDX R2 R8 R9 + 0x70020006, // 0027 JMP #002F + 0x60200008, // 0028 GETGBL R8 G8 + 0x5C240600, // 0029 MOVE R9 R3 + 0x7C200200, // 002A CALL R8 1 + 0x60240013, // 002B GETGBL R9 G19 + 0x7C240000, // 002C CALL R9 0 + 0x9826150E, // 002D SETIDX R9 K10 K14 + 0x98081009, // 002E SETIDX R2 R8 R9 + 0x50100200, // 002F LDBOOL R4 1 0 + 0x000C0709, // 0030 ADD R3 R3 K9 + 0xB81E1E00, // 0031 GETNGBL R7 K15 + 0x8C1C0F10, // 0032 GETMET R7 R7 K16 + 0x58240011, // 0033 LDCONST R9 K17 + 0x50280200, // 0034 LDBOOL R10 1 0 + 0x7C1C0600, // 0035 CALL R7 3 + 0x60200012, // 0036 GETGBL R8 G18 + 0x7C200000, // 0037 CALL R8 0 + 0xB8261E00, // 0038 GETNGBL R9 K15 + 0x8C241312, // 0039 GETMET R9 R9 K18 + 0x602C0008, // 003A GETGBL R11 G8 + 0x5C300E00, // 003B MOVE R12 R7 + 0x7C2C0200, // 003C CALL R11 1 + 0x002E260B, // 003D ADD R11 K19 R11 + 0x58300014, // 003E LDCONST R12 K20 + 0x7C240600, // 003F CALL R9 3 + 0x4C240000, // 0040 LDNIL R9 + 0x20240E09, // 0041 NE R9 R7 R9 + 0x7826004F, // 0042 JMPF R9 #0093 + 0x8C240F15, // 0043 GETMET R9 R7 K21 + 0x582C0016, // 0044 LDCONST R11 K22 + 0x7C240400, // 0045 CALL R9 2 + 0x7826004B, // 0046 JMPF R9 #0093 + 0x941C0F16, // 0047 GETIDX R7 R7 K22 + 0x58240008, // 0048 LDCONST R9 K8 + 0x50280200, // 0049 LDBOOL R10 1 0 + 0x782A0047, // 004A JMPF R10 #0093 + 0x60280008, // 004B GETGBL R10 G8 + 0x5C2C1200, // 004C MOVE R11 R9 + 0x7C280200, // 004D CALL R10 1 + 0x002A2E0A, // 004E ADD R10 K23 R10 + 0x8C2C0F15, // 004F GETMET R11 R7 K21 + 0x5C341400, // 0050 MOVE R13 R10 + 0x7C2C0400, // 0051 CALL R11 2 + 0x742E0000, // 0052 JMPT R11 #0054 + 0x7002003E, // 0053 JMP #0093 + 0x942C0E0A, // 0054 GETIDX R11 R7 R10 + 0xB8321E00, // 0055 GETNGBL R12 K15 + 0x8C301912, // 0056 GETMET R12 R12 K18 + 0x60380018, // 0057 GETGBL R14 G24 + 0x583C0018, // 0058 LDCONST R15 K24 + 0x5C401400, // 0059 MOVE R16 R10 + 0x60440008, // 005A GETGBL R17 G8 + 0x5C481600, // 005B MOVE R18 R11 + 0x7C440200, // 005C CALL R17 1 + 0x7C380600, // 005D CALL R14 3 + 0x583C0014, // 005E LDCONST R15 K20 + 0x7C300600, // 005F CALL R12 3 + 0x8C301705, // 0060 GETMET R12 R11 K5 + 0x58380019, // 0061 LDCONST R14 K25 + 0x543DFFFE, // 0062 LDINT R15 -1 + 0x7C300600, // 0063 CALL R12 3 + 0x8C341705, // 0064 GETMET R13 R11 K5 + 0x583C001A, // 0065 LDCONST R15 K26 + 0x5441FFFE, // 0066 LDINT R16 -1 + 0x7C340600, // 0067 CALL R13 3 + 0x24381908, // 0068 GT R14 R12 K8 + 0x783A0002, // 0069 JMPF R14 #006D + 0x8C38111B, // 006A GETMET R14 R8 K27 + 0x04401909, // 006B SUB R16 R12 K9 + 0x7C380400, // 006C CALL R14 2 + 0x24381B08, // 006D GT R14 R13 K8 + 0x783A0002, // 006E JMPF R14 #0072 + 0x8C38111B, // 006F GETMET R14 R8 K27 + 0x04401B09, // 0070 SUB R16 R13 K9 + 0x7C380400, // 0071 CALL R14 2 + 0xB83A1E00, // 0072 GETNGBL R14 K15 + 0x8C381D12, // 0073 GETMET R14 R14 K18 + 0x60400018, // 0074 GETGBL R16 G24 + 0x5844001C, // 0075 LDCONST R17 K28 + 0x5C481800, // 0076 MOVE R18 R12 + 0x5C4C1A00, // 0077 MOVE R19 R13 + 0x7C400600, // 0078 CALL R16 3 + 0x58440014, // 0079 LDCONST R17 K20 + 0x7C380600, // 007A CALL R14 3 + 0x8C381705, // 007B GETMET R14 R11 K5 + 0x5840001D, // 007C LDCONST R16 K29 + 0x7C380400, // 007D CALL R14 2 + 0x783A0002, // 007E JMPF R14 #0082 + 0x943C1D0C, // 007F GETIDX R15 R14 K12 + 0x243C1F08, // 0080 GT R15 R15 K8 + 0x743E0000, // 0081 JMPT R15 #0083 + 0x503C0001, // 0082 LDBOOL R15 0 1 + 0x503C0200, // 0083 LDBOOL R15 1 0 + 0x60400008, // 0084 GETGBL R16 G8 + 0x5C440600, // 0085 MOVE R17 R3 + 0x7C400200, // 0086 CALL R16 1 + 0x60440013, // 0087 GETGBL R17 G19 + 0x7C440000, // 0088 CALL R17 0 + 0x783E0001, // 0089 JMPF R15 #008C + 0x5848001E, // 008A LDCONST R18 K30 + 0x70020000, // 008B JMP #008D + 0x5848001F, // 008C LDCONST R18 K31 + 0x98461412, // 008D SETIDX R17 K10 R18 + 0x98463E09, // 008E SETIDX R17 K31 R9 + 0x98082011, // 008F SETIDX R2 R16 R17 + 0x000C0709, // 0090 ADD R3 R3 K9 + 0x00241309, // 0091 ADD R9 R9 K9 + 0x7001FFB5, // 0092 JMP #0049 + 0x6024000C, // 0093 GETGBL R9 G12 + 0xB82A1E00, // 0094 GETNGBL R10 K15 + 0x8C281520, // 0095 GETMET R10 R10 K32 + 0x7C280200, // 0096 CALL R10 1 + 0x7C240200, // 0097 CALL R9 1 + 0x58280008, // 0098 LDCONST R10 K8 + 0x78120000, // 0099 JMPF R4 #009B + 0x04241309, // 009A SUB R9 R9 K9 + 0x142C1409, // 009B LT R11 R10 R9 + 0x782E0011, // 009C JMPF R11 #00AF + 0x8C2C1105, // 009D GETMET R11 R8 K5 + 0x5C341400, // 009E MOVE R13 R10 + 0x7C2C0400, // 009F CALL R11 2 + 0x4C300000, // 00A0 LDNIL R12 + 0x1C2C160C, // 00A1 EQ R11 R11 R12 + 0x782E0009, // 00A2 JMPF R11 #00AD + 0x602C0008, // 00A3 GETGBL R11 G8 + 0x5C300600, // 00A4 MOVE R12 R3 + 0x7C2C0200, // 00A5 CALL R11 1 + 0x60300013, // 00A6 GETGBL R12 G19 + 0x7C300000, // 00A7 CALL R12 0 + 0x98321521, // 00A8 SETIDX R12 K10 K33 + 0x00341509, // 00A9 ADD R13 R10 K9 + 0x9832420D, // 00AA SETIDX R12 K33 R13 + 0x9808160C, // 00AB SETIDX R2 R11 R12 + 0x000C0709, // 00AC ADD R3 R3 K9 + 0x00281509, // 00AD ADD R10 R10 K9 + 0x7001FFEB, // 00AE JMP #009B + 0x8C2C0322, // 00AF GETMET R11 R1 K34 + 0xB8361E00, // 00B0 GETNGBL R13 K15 + 0x8C341B23, // 00B1 GETMET R13 R13 K35 + 0x7C340200, // 00B2 CALL R13 1 + 0x7C2C0400, // 00B3 CALL R11 2 + 0x8C300124, // 00B4 GETMET R12 R0 K36 + 0x5C381600, // 00B5 MOVE R14 R11 + 0x7C300400, // 00B6 CALL R12 2 + 0x60340010, // 00B7 GETGBL R13 G16 + 0x5C381800, // 00B8 MOVE R14 R12 + 0x7C340200, // 00B9 CALL R13 1 + 0xA8020007, // 00BA EXBLK 0 #00C3 + 0x5C381A00, // 00BB MOVE R14 R13 + 0x7C380000, // 00BC CALL R14 0 + 0x603C0008, // 00BD GETGBL R15 G8 + 0x5C400600, // 00BE MOVE R16 R3 + 0x7C3C0200, // 00BF CALL R15 1 + 0x98081E0E, // 00C0 SETIDX R2 R15 R14 + 0x000C0709, // 00C1 ADD R3 R3 K9 + 0x7001FFF7, // 00C2 JMP #00BB + 0x58340025, // 00C3 LDCONST R13 K37 + 0xAC340200, // 00C4 CATCH R13 1 0 + 0xB0080000, // 00C5 RAISE 2 R0 R0 + 0x80040400, // 00C6 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: mdns_announce_op_discovery_all_fabrics +********************************************************************/ +be_local_closure(Matter_Device_mdns_announce_op_discovery_all_fabrics, /* name */ be_nested_proto( 6, /* nstack */ 1, /* argc */ @@ -1075,149 +1444,39 @@ be_local_closure(Matter_Device_autoconf_device, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[16]) { /* constants */ - /* K0 */ be_nested_str_weak(json), - /* K1 */ be_nested_str_weak(plugins), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(plugins_persist), - /* K4 */ be_nested_str_weak(plugins_config), - /* K5 */ be_nested_str_weak(autoconf_device_map), - /* K6 */ be_nested_str_weak(plugins_config_remotes), - /* K7 */ be_nested_str_weak(adjust_next_ep), - /* K8 */ be_nested_str_weak(tasmota), - /* K9 */ be_nested_str_weak(log), - /* K10 */ be_nested_str_weak(MTR_X3A_X20autoconfig_X20_X3D_X20), - /* K11 */ be_const_int(3), - /* K12 */ be_nested_str_weak(_instantiate_plugins_from_config), - /* K13 */ be_nested_str_weak(sessions), - /* K14 */ be_nested_str_weak(count_active_fabrics), - /* K15 */ be_nested_str_weak(save_param), + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(sessions), + /* K1 */ be_nested_str_weak(active_fabrics), + /* K2 */ be_nested_str_weak(get_device_id), + /* K3 */ be_nested_str_weak(get_fabric_id), + /* K4 */ be_nested_str_weak(mdns_announce_op_discovery), + /* K5 */ be_nested_str_weak(stop_iteration), }), - be_str_weak(autoconf_device), + be_str_weak(mdns_announce_op_discovery_all_fabrics), &be_const_str_solidified, - ( &(const binstruction[40]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0x6008000C, // 0001 GETGBL R2 G12 - 0x880C0101, // 0002 GETMBR R3 R0 K1 + ( &(const binstruction[22]) { /* code */ + 0x60040010, // 0000 GETGBL R1 G16 + 0x88080100, // 0001 GETMBR R2 R0 K0 + 0x8C080501, // 0002 GETMET R2 R2 K1 0x7C080200, // 0003 CALL R2 1 - 0x24080502, // 0004 GT R2 R2 K2 - 0x780A0000, // 0005 JMPF R2 #0007 - 0x80000400, // 0006 RET 0 - 0x88080103, // 0007 GETMBR R2 R0 K3 - 0x740A000F, // 0008 JMPT R2 #0019 - 0x8C080105, // 0009 GETMET R2 R0 K5 - 0x7C080200, // 000A CALL R2 1 - 0x90020802, // 000B SETMBR R0 K4 R2 - 0x60080013, // 000C GETGBL R2 G19 - 0x7C080000, // 000D CALL R2 0 - 0x90020C02, // 000E SETMBR R0 K6 R2 - 0x8C080107, // 000F GETMET R2 R0 K7 - 0x7C080200, // 0010 CALL R2 1 - 0xB80A1000, // 0011 GETNGBL R2 K8 - 0x8C080509, // 0012 GETMET R2 R2 K9 - 0x60100008, // 0013 GETGBL R4 G8 - 0x88140104, // 0014 GETMBR R5 R0 K4 - 0x7C100200, // 0015 CALL R4 1 - 0x00121404, // 0016 ADD R4 K10 R4 - 0x5814000B, // 0017 LDCONST R5 K11 - 0x7C080600, // 0018 CALL R2 3 - 0x8C08010C, // 0019 GETMET R2 R0 K12 - 0x88100104, // 001A GETMBR R4 R0 K4 - 0x7C080400, // 001B CALL R2 2 - 0x88080103, // 001C GETMBR R2 R0 K3 - 0x740A0008, // 001D JMPT R2 #0027 - 0x8808010D, // 001E GETMBR R2 R0 K13 - 0x8C08050E, // 001F GETMET R2 R2 K14 - 0x7C080200, // 0020 CALL R2 1 - 0x24080502, // 0021 GT R2 R2 K2 - 0x780A0003, // 0022 JMPF R2 #0027 - 0x50080200, // 0023 LDBOOL R2 1 0 - 0x90020602, // 0024 SETMBR R0 K3 R2 - 0x8C08010F, // 0025 GETMET R2 R0 K15 - 0x7C080200, // 0026 CALL R2 1 - 0x80000000, // 0027 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: sort_distinct -********************************************************************/ -be_local_closure(Matter_Device_sort_distinct, /* name */ - be_nested_proto( - 7, /* nstack */ - 1, /* argc */ - 4, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_const_class(be_class_Matter_Device), - /* K1 */ be_const_int(1), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(stop_iteration), - /* K4 */ be_nested_str_weak(remove), - }), - be_str_weak(sort_distinct), - &be_const_str_solidified, - ( &(const binstruction[53]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x60080010, // 0001 GETGBL R2 G16 - 0x600C000C, // 0002 GETGBL R3 G12 - 0x5C100000, // 0003 MOVE R4 R0 - 0x7C0C0200, // 0004 CALL R3 1 - 0x040C0701, // 0005 SUB R3 R3 K1 - 0x400E0203, // 0006 CONNECT R3 K1 R3 - 0x7C080200, // 0007 CALL R2 1 - 0xA8020010, // 0008 EXBLK 0 #001A - 0x5C0C0400, // 0009 MOVE R3 R2 - 0x7C0C0000, // 000A CALL R3 0 - 0x94100003, // 000B GETIDX R4 R0 R3 - 0x5C140600, // 000C MOVE R5 R3 - 0x24180B02, // 000D GT R6 R5 K2 - 0x781A0008, // 000E JMPF R6 #0018 - 0x04180B01, // 000F SUB R6 R5 K1 - 0x94180006, // 0010 GETIDX R6 R0 R6 - 0x24180C04, // 0011 GT R6 R6 R4 - 0x781A0004, // 0012 JMPF R6 #0018 - 0x04180B01, // 0013 SUB R6 R5 K1 - 0x94180006, // 0014 GETIDX R6 R0 R6 - 0x98000A06, // 0015 SETIDX R0 R5 R6 - 0x04140B01, // 0016 SUB R5 R5 K1 - 0x7001FFF4, // 0017 JMP #000D - 0x98000A04, // 0018 SETIDX R0 R5 R4 - 0x7001FFEE, // 0019 JMP #0009 - 0x58080003, // 001A LDCONST R2 K3 - 0xAC080200, // 001B CATCH R2 1 0 - 0xB0080000, // 001C RAISE 2 R0 R0 - 0x58080001, // 001D LDCONST R2 K1 - 0x600C000C, // 001E GETGBL R3 G12 - 0x5C100000, // 001F MOVE R4 R0 - 0x7C0C0200, // 0020 CALL R3 1 - 0x180C0701, // 0021 LE R3 R3 K1 - 0x780E0000, // 0022 JMPF R3 #0024 - 0x80040000, // 0023 RET 1 R0 - 0x940C0102, // 0024 GETIDX R3 R0 K2 - 0x6010000C, // 0025 GETGBL R4 G12 - 0x5C140000, // 0026 MOVE R5 R0 - 0x7C100200, // 0027 CALL R4 1 - 0x14100404, // 0028 LT R4 R2 R4 - 0x78120009, // 0029 JMPF R4 #0034 - 0x94100002, // 002A GETIDX R4 R0 R2 - 0x1C100803, // 002B EQ R4 R4 R3 - 0x78120003, // 002C JMPF R4 #0031 - 0x8C100104, // 002D GETMET R4 R0 K4 - 0x5C180400, // 002E MOVE R6 R2 - 0x7C100400, // 002F CALL R4 2 - 0x70020001, // 0030 JMP #0033 - 0x940C0002, // 0031 GETIDX R3 R0 R2 - 0x00080501, // 0032 ADD R2 R2 K1 - 0x7001FFF0, // 0033 JMP #0025 - 0x80040000, // 0034 RET 1 R0 + 0x7C040200, // 0004 CALL R1 1 + 0xA802000B, // 0005 EXBLK 0 #0012 + 0x5C080200, // 0006 MOVE R2 R1 + 0x7C080000, // 0007 CALL R2 0 + 0x8C0C0502, // 0008 GETMET R3 R2 K2 + 0x7C0C0200, // 0009 CALL R3 1 + 0x780E0005, // 000A JMPF R3 #0011 + 0x8C0C0503, // 000B GETMET R3 R2 K3 + 0x7C0C0200, // 000C CALL R3 1 + 0x780E0002, // 000D JMPF R3 #0011 + 0x8C0C0104, // 000E GETMET R3 R0 K4 + 0x5C140400, // 000F MOVE R5 R2 + 0x7C0C0400, // 0010 CALL R3 2 + 0x7001FFF3, // 0011 JMP #0006 + 0x58040005, // 0012 LDCONST R1 K5 + 0xAC040200, // 0013 CATCH R1 1 0 + 0xB0080000, // 0014 RAISE 2 R0 R0 + 0x80000000, // 0015 RET 0 }) ) ); @@ -1535,11 +1794,276 @@ be_local_closure(Matter_Device_process_attribute_expansion, /* name */ /******************************************************************** -** Solidified function: add_read_sensors_schedule +** Solidified function: register_commands ********************************************************************/ -be_local_closure(Matter_Device_add_read_sensors_schedule, /* name */ +be_local_closure(Matter_Device_register_commands, /* name */ be_nested_proto( 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 3]) { + be_nested_proto( + 10, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(MtrJoin), + }), + be_str_weak(_X3Clambda_X3E), + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x68100000, // 0000 GETUPV R4 U0 + 0x8C100900, // 0001 GETMET R4 R4 K0 + 0x5C180000, // 0002 MOVE R6 R0 + 0x5C1C0200, // 0003 MOVE R7 R1 + 0x5C200400, // 0004 MOVE R8 R2 + 0x5C240600, // 0005 MOVE R9 R3 + 0x7C100A00, // 0006 CALL R4 5 + 0x80040800, // 0007 RET 1 R4 + }) + ), + be_nested_proto( + 10, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(MtrUpdate), + }), + be_str_weak(_X3Clambda_X3E), + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x68100000, // 0000 GETUPV R4 U0 + 0x8C100900, // 0001 GETMET R4 R4 K0 + 0x5C180000, // 0002 MOVE R6 R0 + 0x5C1C0200, // 0003 MOVE R7 R1 + 0x5C200400, // 0004 MOVE R8 R2 + 0x5C240600, // 0005 MOVE R9 R3 + 0x7C100A00, // 0006 CALL R4 5 + 0x80040800, // 0007 RET 1 R4 + }) + ), + be_nested_proto( + 10, /* nstack */ + 4, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(MtrInfo), + }), + be_str_weak(_X3Clambda_X3E), + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x68100000, // 0000 GETUPV R4 U0 + 0x8C100900, // 0001 GETMET R4 R4 K0 + 0x5C180000, // 0002 MOVE R6 R0 + 0x5C1C0200, // 0003 MOVE R7 R1 + 0x5C200400, // 0004 MOVE R8 R2 + 0x5C240600, // 0005 MOVE R9 R3 + 0x7C100A00, // 0006 CALL R4 5 + 0x80040800, // 0007 RET 1 R4 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(add_cmd), + /* K2 */ be_nested_str_weak(MtrJoin), + /* K3 */ be_nested_str_weak(MtrUpdate), + /* K4 */ be_nested_str_weak(MtrInfo), + }), + be_str_weak(register_commands), + &be_const_str_solidified, + ( &(const binstruction[17]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x580C0002, // 0002 LDCONST R3 K2 + 0x84100000, // 0003 CLOSURE R4 P0 + 0x7C040600, // 0004 CALL R1 3 + 0xB8060000, // 0005 GETNGBL R1 K0 + 0x8C040301, // 0006 GETMET R1 R1 K1 + 0x580C0003, // 0007 LDCONST R3 K3 + 0x84100001, // 0008 CLOSURE R4 P1 + 0x7C040600, // 0009 CALL R1 3 + 0xB8060000, // 000A GETNGBL R1 K0 + 0x8C040301, // 000B GETMET R1 R1 K1 + 0x580C0004, // 000C LDCONST R3 K4 + 0x84100002, // 000D CLOSURE R4 P2 + 0x7C040600, // 000E CALL R1 3 + 0xA0000000, // 000F CLOSE R0 + 0x80000000, // 0010 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: update_remotes_info +********************************************************************/ +be_local_closure(Matter_Device_update_remotes_info, /* name */ + be_nested_proto( + 7, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(http_remotes), + /* K1 */ be_nested_str_weak(keys), + /* K2 */ be_nested_str_weak(get_info), + /* K3 */ be_const_int(0), + /* K4 */ be_nested_str_weak(stop_iteration), + /* K5 */ be_nested_str_weak(plugins_config_remotes), + }), + be_str_weak(update_remotes_info), + &be_const_str_solidified, + ( &(const binstruction[33]) { /* code */ + 0x60040013, // 0000 GETGBL R1 G19 + 0x7C040000, // 0001 CALL R1 0 + 0x88080100, // 0002 GETMBR R2 R0 K0 + 0x4C0C0000, // 0003 LDNIL R3 + 0x20080403, // 0004 NE R2 R2 R3 + 0x780A0018, // 0005 JMPF R2 #001F + 0x60080010, // 0006 GETGBL R2 G16 + 0x880C0100, // 0007 GETMBR R3 R0 K0 + 0x8C0C0701, // 0008 GETMET R3 R3 K1 + 0x7C0C0200, // 0009 CALL R3 1 + 0x7C080200, // 000A CALL R2 1 + 0xA802000F, // 000B EXBLK 0 #001C + 0x5C0C0400, // 000C MOVE R3 R2 + 0x7C0C0000, // 000D CALL R3 0 + 0x88100100, // 000E GETMBR R4 R0 K0 + 0x94100803, // 000F GETIDX R4 R4 R3 + 0x8C100902, // 0010 GETMET R4 R4 K2 + 0x7C100200, // 0011 CALL R4 1 + 0x4C140000, // 0012 LDNIL R5 + 0x20140805, // 0013 NE R5 R4 R5 + 0x78160005, // 0014 JMPF R5 #001B + 0x6014000C, // 0015 GETGBL R5 G12 + 0x5C180800, // 0016 MOVE R6 R4 + 0x7C140200, // 0017 CALL R5 1 + 0x24140B03, // 0018 GT R5 R5 K3 + 0x78160000, // 0019 JMPF R5 #001B + 0x98040604, // 001A SETIDX R1 R3 R4 + 0x7001FFEF, // 001B JMP #000C + 0x58080004, // 001C LDCONST R2 K4 + 0xAC080200, // 001D CATCH R2 1 0 + 0xB0080000, // 001E RAISE 2 R0 R0 + 0x90020A01, // 001F SETMBR R0 K5 R1 + 0x80040200, // 0020 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: _compute_pbkdf +********************************************************************/ +be_local_closure(Matter_Device__compute_pbkdf, /* name */ + be_nested_proto( + 13, /* nstack */ + 4, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[10]) { /* constants */ + /* K0 */ be_nested_str_weak(crypto), + /* K1 */ be_nested_str_weak(add), + /* K2 */ be_nested_str_weak(PBKDF2_HMAC_SHA256), + /* K3 */ be_nested_str_weak(derive), + /* K4 */ be_const_int(0), + /* K5 */ be_nested_str_weak(root_w0), + /* K6 */ be_nested_str_weak(EC_P256), + /* K7 */ be_nested_str_weak(mod), + /* K8 */ be_nested_str_weak(root_L), + /* K9 */ be_nested_str_weak(public_key), + }), + be_str_weak(_compute_pbkdf), + &be_const_str_solidified, + ( &(const binstruction[40]) { /* code */ + 0xA4120000, // 0000 IMPORT R4 K0 + 0x60140015, // 0001 GETGBL R5 G21 + 0x7C140000, // 0002 CALL R5 0 + 0x8C140B01, // 0003 GETMET R5 R5 K1 + 0x5C1C0200, // 0004 MOVE R7 R1 + 0x54220003, // 0005 LDINT R8 4 + 0x7C140600, // 0006 CALL R5 3 + 0x8C180902, // 0007 GETMET R6 R4 K2 + 0x7C180200, // 0008 CALL R6 1 + 0x8C180D03, // 0009 GETMET R6 R6 K3 + 0x5C200A00, // 000A MOVE R8 R5 + 0x5C240600, // 000B MOVE R9 R3 + 0x5C280400, // 000C MOVE R10 R2 + 0x542E004F, // 000D LDINT R11 80 + 0x7C180A00, // 000E CALL R6 5 + 0x541E0026, // 000F LDINT R7 39 + 0x401E0807, // 0010 CONNECT R7 K4 R7 + 0x941C0C07, // 0011 GETIDX R7 R6 R7 + 0x54220027, // 0012 LDINT R8 40 + 0x5426004E, // 0013 LDINT R9 79 + 0x40201009, // 0014 CONNECT R8 R8 R9 + 0x94200C08, // 0015 GETIDX R8 R6 R8 + 0x8C240906, // 0016 GETMET R9 R4 K6 + 0x7C240200, // 0017 CALL R9 1 + 0x8C241307, // 0018 GETMET R9 R9 K7 + 0x5C2C0E00, // 0019 MOVE R11 R7 + 0x7C240400, // 001A CALL R9 2 + 0x90020A09, // 001B SETMBR R0 K5 R9 + 0x8C240906, // 001C GETMET R9 R4 K6 + 0x7C240200, // 001D CALL R9 1 + 0x8C241307, // 001E GETMET R9 R9 K7 + 0x5C2C1000, // 001F MOVE R11 R8 + 0x7C240400, // 0020 CALL R9 2 + 0x8C280906, // 0021 GETMET R10 R4 K6 + 0x7C280200, // 0022 CALL R10 1 + 0x8C281509, // 0023 GETMET R10 R10 K9 + 0x5C301200, // 0024 MOVE R12 R9 + 0x7C280400, // 0025 CALL R10 2 + 0x9002100A, // 0026 SETMBR R0 K8 R10 + 0x80000000, // 0027 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: find_plugin_by_friendly_name +********************************************************************/ +be_local_closure(Matter_Device_find_plugin_by_friendly_name, /* name */ + be_nested_proto( + 7, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -1548,28 +2072,312 @@ be_local_closure(Matter_Device_add_read_sensors_schedule, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(probe_sensor_time), - /* K1 */ be_nested_str_weak(probe_sensor_timestamp), - /* K2 */ be_nested_str_weak(matter), - /* K3 */ be_nested_str_weak(jitter), + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_weak(plugins), + /* K2 */ be_nested_str_weak(get_name), + /* K3 */ be_const_int(1), }), - be_str_weak(add_read_sensors_schedule), + be_str_weak(find_plugin_by_friendly_name), &be_const_str_solidified, - ( &(const binstruction[14]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x1C080403, // 0002 EQ R2 R2 R3 - 0x740A0002, // 0003 JMPT R2 #0007 - 0x88080100, // 0004 GETMBR R2 R0 K0 - 0x24080401, // 0005 GT R2 R2 R1 - 0x780A0005, // 0006 JMPF R2 #000D - 0x90020001, // 0007 SETMBR R0 K0 R1 - 0xB80A0400, // 0008 GETNGBL R2 K2 - 0x8C080503, // 0009 GETMET R2 R2 K3 - 0x5C100200, // 000A MOVE R4 R1 - 0x7C080400, // 000B CALL R2 2 - 0x90020202, // 000C SETMBR R0 K1 R2 - 0x80000000, // 000D RET 0 + ( &(const binstruction[35]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x1C080202, // 0001 EQ R2 R1 R2 + 0x740A0004, // 0002 JMPT R2 #0008 + 0x6008000C, // 0003 GETGBL R2 G12 + 0x5C0C0200, // 0004 MOVE R3 R1 + 0x7C080200, // 0005 CALL R2 1 + 0x1C080500, // 0006 EQ R2 R2 K0 + 0x780A0001, // 0007 JMPF R2 #000A + 0x4C080000, // 0008 LDNIL R2 + 0x80040400, // 0009 RET 1 R2 + 0x58080000, // 000A LDCONST R2 K0 + 0x600C000C, // 000B GETGBL R3 G12 + 0x88100101, // 000C GETMBR R4 R0 K1 + 0x7C0C0200, // 000D CALL R3 1 + 0x140C0403, // 000E LT R3 R2 R3 + 0x780E0010, // 000F JMPF R3 #0021 + 0x880C0101, // 0010 GETMBR R3 R0 K1 + 0x940C0602, // 0011 GETIDX R3 R3 R2 + 0x8C100702, // 0012 GETMET R4 R3 K2 + 0x7C100200, // 0013 CALL R4 1 + 0x4C140000, // 0014 LDNIL R5 + 0x20140805, // 0015 NE R5 R4 R5 + 0x78160007, // 0016 JMPF R5 #001F + 0x6014000C, // 0017 GETGBL R5 G12 + 0x5C180800, // 0018 MOVE R6 R4 + 0x7C140200, // 0019 CALL R5 1 + 0x24140B00, // 001A GT R5 R5 K0 + 0x78160002, // 001B JMPF R5 #001F + 0x1C140801, // 001C EQ R5 R4 R1 + 0x78160000, // 001D JMPF R5 #001F + 0x80040600, // 001E RET 1 R3 + 0x00080503, // 001F ADD R2 R2 K3 + 0x7001FFE9, // 0020 JMP #000B + 0x4C0C0000, // 0021 LDNIL R3 + 0x80040600, // 0022 RET 1 R3 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: clean_remotes +********************************************************************/ +be_local_closure(Matter_Device_clean_remotes, /* name */ + be_nested_proto( + 10, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[18]) { /* constants */ + /* K0 */ be_nested_str_weak(introspect), + /* K1 */ be_nested_str_weak(http_remotes), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(stop_iteration), + /* K4 */ be_nested_str_weak(plugins), + /* K5 */ be_nested_str_weak(get), + /* K6 */ be_nested_str_weak(http_remote), + /* K7 */ be_nested_str_weak(find), + /* K8 */ be_const_int(1), + /* K9 */ be_nested_str_weak(keys), + /* K10 */ be_nested_str_weak(push), + /* K11 */ be_nested_str_weak(tasmota), + /* K12 */ be_nested_str_weak(log), + /* K13 */ be_nested_str_weak(MTR_X3A_X20remove_X20unused_X20remote_X3A_X20), + /* K14 */ be_nested_str_weak(addr), + /* K15 */ be_const_int(3), + /* K16 */ be_nested_str_weak(close), + /* K17 */ be_nested_str_weak(remove), + }), + be_str_weak(clean_remotes), + &be_const_str_solidified, + ( &(const binstruction[81]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x88080101, // 0001 GETMBR R2 R0 K1 + 0x780A004C, // 0002 JMPF R2 #0050 + 0x60080013, // 0003 GETGBL R2 G19 + 0x7C080000, // 0004 CALL R2 0 + 0x600C0010, // 0005 GETGBL R3 G16 + 0x88100101, // 0006 GETMBR R4 R0 K1 + 0x7C0C0200, // 0007 CALL R3 1 + 0xA8020003, // 0008 EXBLK 0 #000D + 0x5C100600, // 0009 MOVE R4 R3 + 0x7C100000, // 000A CALL R4 0 + 0x98080902, // 000B SETIDX R2 R4 K2 + 0x7001FFFB, // 000C JMP #0009 + 0x580C0003, // 000D LDCONST R3 K3 + 0xAC0C0200, // 000E CATCH R3 1 0 + 0xB0080000, // 000F RAISE 2 R0 R0 + 0x600C0010, // 0010 GETGBL R3 G16 + 0x88100104, // 0011 GETMBR R4 R0 K4 + 0x7C0C0200, // 0012 CALL R3 1 + 0xA802000F, // 0013 EXBLK 0 #0024 + 0x5C100600, // 0014 MOVE R4 R3 + 0x7C100000, // 0015 CALL R4 0 + 0x8C140305, // 0016 GETMET R5 R1 K5 + 0x5C1C0800, // 0017 MOVE R7 R4 + 0x58200006, // 0018 LDCONST R8 K6 + 0x7C140600, // 0019 CALL R5 3 + 0x4C180000, // 001A LDNIL R6 + 0x20180A06, // 001B NE R6 R5 R6 + 0x781A0005, // 001C JMPF R6 #0023 + 0x8C180507, // 001D GETMET R6 R2 K7 + 0x5C200A00, // 001E MOVE R8 R5 + 0x58240002, // 001F LDCONST R9 K2 + 0x7C180600, // 0020 CALL R6 3 + 0x00180D08, // 0021 ADD R6 R6 K8 + 0x98080A06, // 0022 SETIDX R2 R5 R6 + 0x7001FFEF, // 0023 JMP #0014 + 0x580C0003, // 0024 LDCONST R3 K3 + 0xAC0C0200, // 0025 CATCH R3 1 0 + 0xB0080000, // 0026 RAISE 2 R0 R0 + 0x600C0012, // 0027 GETGBL R3 G18 + 0x7C0C0000, // 0028 CALL R3 0 + 0x60100010, // 0029 GETGBL R4 G16 + 0x8C140509, // 002A GETMET R5 R2 K9 + 0x7C140200, // 002B CALL R5 1 + 0x7C100200, // 002C CALL R4 1 + 0xA8020008, // 002D EXBLK 0 #0037 + 0x5C140800, // 002E MOVE R5 R4 + 0x7C140000, // 002F CALL R5 0 + 0x94180405, // 0030 GETIDX R6 R2 R5 + 0x1C180D02, // 0031 EQ R6 R6 K2 + 0x781A0002, // 0032 JMPF R6 #0036 + 0x8C18070A, // 0033 GETMET R6 R3 K10 + 0x5C200A00, // 0034 MOVE R8 R5 + 0x7C180400, // 0035 CALL R6 2 + 0x7001FFF6, // 0036 JMP #002E + 0x58100003, // 0037 LDCONST R4 K3 + 0xAC100200, // 0038 CATCH R4 1 0 + 0xB0080000, // 0039 RAISE 2 R0 R0 + 0x60100010, // 003A GETGBL R4 G16 + 0x5C140600, // 003B MOVE R5 R3 + 0x7C100200, // 003C CALL R4 1 + 0xA802000E, // 003D EXBLK 0 #004D + 0x5C140800, // 003E MOVE R5 R4 + 0x7C140000, // 003F CALL R5 0 + 0xB81A1600, // 0040 GETNGBL R6 K11 + 0x8C180D0C, // 0041 GETMET R6 R6 K12 + 0x88200B0E, // 0042 GETMBR R8 R5 K14 + 0x00221A08, // 0043 ADD R8 K13 R8 + 0x5824000F, // 0044 LDCONST R9 K15 + 0x7C180600, // 0045 CALL R6 3 + 0x8C180B10, // 0046 GETMET R6 R5 K16 + 0x7C180200, // 0047 CALL R6 1 + 0x88180101, // 0048 GETMBR R6 R0 K1 + 0x8C180D11, // 0049 GETMET R6 R6 K17 + 0x88200B0E, // 004A GETMBR R8 R5 K14 + 0x7C180400, // 004B CALL R6 2 + 0x7001FFF0, // 004C JMP #003E + 0x58100003, // 004D LDCONST R4 K3 + 0xAC100200, // 004E CATCH R4 1 0 + 0xB0080000, // 004F RAISE 2 R0 R0 + 0x80000000, // 0050 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: compute_manual_pairing_code +********************************************************************/ +be_local_closure(Matter_Device_compute_manual_pairing_code, /* name */ + be_nested_proto( + 9, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(root_discriminator), + /* K1 */ be_nested_str_weak(root_passcode), + /* K2 */ be_nested_str_weak(_X251i_X2505i_X2504i), + /* K3 */ be_nested_str_weak(matter), + /* K4 */ be_nested_str_weak(Verhoeff), + /* K5 */ be_nested_str_weak(checksum), + }), + be_str_weak(compute_manual_pairing_code), + &be_const_str_solidified, + ( &(const binstruction[30]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x540A0FFE, // 0001 LDINT R2 4095 + 0x2C040202, // 0002 AND R1 R1 R2 + 0x540A0009, // 0003 LDINT R2 10 + 0x3C040202, // 0004 SHR R1 R1 R2 + 0x88080100, // 0005 GETMBR R2 R0 K0 + 0x540E02FF, // 0006 LDINT R3 768 + 0x2C080403, // 0007 AND R2 R2 R3 + 0x540E0005, // 0008 LDINT R3 6 + 0x38080403, // 0009 SHL R2 R2 R3 + 0x880C0101, // 000A GETMBR R3 R0 K1 + 0x54123FFE, // 000B LDINT R4 16383 + 0x2C0C0604, // 000C AND R3 R3 R4 + 0x30080403, // 000D OR R2 R2 R3 + 0x880C0101, // 000E GETMBR R3 R0 K1 + 0x5412000D, // 000F LDINT R4 14 + 0x3C0C0604, // 0010 SHR R3 R3 R4 + 0x60100018, // 0011 GETGBL R4 G24 + 0x58140002, // 0012 LDCONST R5 K2 + 0x5C180200, // 0013 MOVE R6 R1 + 0x5C1C0400, // 0014 MOVE R7 R2 + 0x5C200600, // 0015 MOVE R8 R3 + 0x7C100800, // 0016 CALL R4 4 + 0xB8160600, // 0017 GETNGBL R5 K3 + 0x88140B04, // 0018 GETMBR R5 R5 K4 + 0x8C140B05, // 0019 GETMET R5 R5 K5 + 0x5C1C0800, // 001A MOVE R7 R4 + 0x7C140400, // 001B CALL R5 2 + 0x00100805, // 001C ADD R4 R4 R5 + 0x80040800, // 001D RET 1 R4 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: autoconf_device +********************************************************************/ +be_local_closure(Matter_Device_autoconf_device, /* name */ + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[16]) { /* constants */ + /* K0 */ be_nested_str_weak(json), + /* K1 */ be_nested_str_weak(plugins), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(plugins_persist), + /* K4 */ be_nested_str_weak(plugins_config), + /* K5 */ be_nested_str_weak(autoconf_device_map), + /* K6 */ be_nested_str_weak(plugins_config_remotes), + /* K7 */ be_nested_str_weak(adjust_next_ep), + /* K8 */ be_nested_str_weak(tasmota), + /* K9 */ be_nested_str_weak(log), + /* K10 */ be_nested_str_weak(MTR_X3A_X20autoconfig_X20_X3D_X20), + /* K11 */ be_const_int(3), + /* K12 */ be_nested_str_weak(_instantiate_plugins_from_config), + /* K13 */ be_nested_str_weak(sessions), + /* K14 */ be_nested_str_weak(count_active_fabrics), + /* K15 */ be_nested_str_weak(save_param), + }), + be_str_weak(autoconf_device), + &be_const_str_solidified, + ( &(const binstruction[40]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x6008000C, // 0001 GETGBL R2 G12 + 0x880C0101, // 0002 GETMBR R3 R0 K1 + 0x7C080200, // 0003 CALL R2 1 + 0x24080502, // 0004 GT R2 R2 K2 + 0x780A0000, // 0005 JMPF R2 #0007 + 0x80000400, // 0006 RET 0 + 0x88080103, // 0007 GETMBR R2 R0 K3 + 0x740A000F, // 0008 JMPT R2 #0019 + 0x8C080105, // 0009 GETMET R2 R0 K5 + 0x7C080200, // 000A CALL R2 1 + 0x90020802, // 000B SETMBR R0 K4 R2 + 0x60080013, // 000C GETGBL R2 G19 + 0x7C080000, // 000D CALL R2 0 + 0x90020C02, // 000E SETMBR R0 K6 R2 + 0x8C080107, // 000F GETMET R2 R0 K7 + 0x7C080200, // 0010 CALL R2 1 + 0xB80A1000, // 0011 GETNGBL R2 K8 + 0x8C080509, // 0012 GETMET R2 R2 K9 + 0x60100008, // 0013 GETGBL R4 G8 + 0x88140104, // 0014 GETMBR R5 R0 K4 + 0x7C100200, // 0015 CALL R4 1 + 0x00121404, // 0016 ADD R4 K10 R4 + 0x5814000B, // 0017 LDCONST R5 K11 + 0x7C080600, // 0018 CALL R2 3 + 0x8C08010C, // 0019 GETMET R2 R0 K12 + 0x88100104, // 001A GETMBR R4 R0 K4 + 0x7C080400, // 001B CALL R2 2 + 0x88080103, // 001C GETMBR R2 R0 K3 + 0x740A0008, // 001D JMPT R2 #0027 + 0x8808010D, // 001E GETMBR R2 R0 K13 + 0x8C08050E, // 001F GETMET R2 R2 K14 + 0x7C080200, // 0020 CALL R2 1 + 0x24080502, // 0021 GT R2 R2 K2 + 0x780A0003, // 0022 JMPF R2 #0027 + 0x50080200, // 0023 LDBOOL R2 1 0 + 0x90020602, // 0024 SETMBR R0 K3 R2 + 0x8C08010F, // 0025 GETMET R2 R0 K15 + 0x7C080200, // 0026 CALL R2 1 + 0x80000000, // 0027 RET 0 }) ) ); @@ -1627,6 +2435,503 @@ be_local_closure(Matter_Device_attribute_updated, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: save_before_restart +********************************************************************/ +be_local_closure(Matter_Device_save_before_restart, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(stop_basic_commissioning), + /* K1 */ be_nested_str_weak(mdns_remove_op_discovery_all_fabrics), + }), + be_str_weak(save_before_restart), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x8C040101, // 0002 GETMET R1 R0 K1 + 0x7C040200, // 0003 CALL R1 1 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: is_root_commissioning_open +********************************************************************/ +be_local_closure(Matter_Device_is_root_commissioning_open, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(commissioning_open), + /* K1 */ be_nested_str_weak(commissioning_admin_fabric), + }), + be_str_weak(is_root_commissioning_open), + &be_const_str_solidified, + ( &(const binstruction[11]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x20040202, // 0002 NE R1 R1 R2 + 0x78060003, // 0003 JMPF R1 #0008 + 0x88040101, // 0004 GETMBR R1 R0 K1 + 0x4C080000, // 0005 LDNIL R2 + 0x1C040202, // 0006 EQ R1 R1 R2 + 0x74060000, // 0007 JMPT R1 #0009 + 0x50040001, // 0008 LDBOOL R1 0 1 + 0x50040200, // 0009 LDBOOL R1 1 0 + 0x80040200, // 000A RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start_commissioning_complete_deferred +********************************************************************/ +be_local_closure(Matter_Device_start_commissioning_complete_deferred, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 1]) { + be_nested_proto( + 3, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 2]) { /* upvals */ + be_local_const_upval(1, 0), + be_local_const_upval(1, 1), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(start_commissioning_complete), + }), + be_str_weak(_X3Clambda_X3E), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x68080001, // 0002 GETUPV R2 U1 + 0x7C000400, // 0003 CALL R0 2 + 0x80040000, // 0004 RET 1 R0 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(set_timer), + /* K2 */ be_const_int(0), + }), + be_str_weak(start_commissioning_complete_deferred), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0xB80A0000, // 0000 GETNGBL R2 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x58100002, // 0002 LDCONST R4 K2 + 0x84140000, // 0003 CLOSURE R5 P0 + 0x7C080600, // 0004 CALL R2 3 + 0xA0000000, // 0005 CLOSE R0 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: adjust_next_ep +********************************************************************/ +be_local_closure(Matter_Device_adjust_next_ep, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(plugins_config), + /* K1 */ be_nested_str_weak(keys), + /* K2 */ be_nested_str_weak(next_ep), + /* K3 */ be_const_int(1), + /* K4 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(adjust_next_ep), + &be_const_str_solidified, + ( &(const binstruction[21]) { /* code */ + 0x60040010, // 0000 GETGBL R1 G16 + 0x88080100, // 0001 GETMBR R2 R0 K0 + 0x8C080501, // 0002 GETMET R2 R2 K1 + 0x7C080200, // 0003 CALL R2 1 + 0x7C040200, // 0004 CALL R1 1 + 0xA802000A, // 0005 EXBLK 0 #0011 + 0x5C080200, // 0006 MOVE R2 R1 + 0x7C080000, // 0007 CALL R2 0 + 0x600C0009, // 0008 GETGBL R3 G9 + 0x5C100400, // 0009 MOVE R4 R2 + 0x7C0C0200, // 000A CALL R3 1 + 0x88100102, // 000B GETMBR R4 R0 K2 + 0x28100604, // 000C GE R4 R3 R4 + 0x78120001, // 000D JMPF R4 #0010 + 0x00100703, // 000E ADD R4 R3 K3 + 0x90020404, // 000F SETMBR R0 K2 R4 + 0x7001FFF4, // 0010 JMP #0006 + 0x58040004, // 0011 LDCONST R1 K4 + 0xAC040200, // 0012 CATCH R1 1 0 + 0xB0080000, // 0013 RAISE 2 R0 R0 + 0x80000000, // 0014 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start +********************************************************************/ +be_local_closure(Matter_Device_start, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(started), + /* K1 */ be_nested_str_weak(autoconf_device), + /* K2 */ be_nested_str_weak(_start_udp), + /* K3 */ be_nested_str_weak(UDP_PORT), + /* K4 */ be_nested_str_weak(start_mdns_announce_hostnames), + }), + be_str_weak(start), + &be_const_str_solidified, + ( &(const binstruction[13]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x78060000, // 0001 JMPF R1 #0003 + 0x80000200, // 0002 RET 0 + 0x8C040101, // 0003 GETMET R1 R0 K1 + 0x7C040200, // 0004 CALL R1 1 + 0x8C040102, // 0005 GETMET R1 R0 K2 + 0x880C0103, // 0006 GETMBR R3 R0 K3 + 0x7C040400, // 0007 CALL R1 2 + 0x8C040104, // 0008 GETMET R1 R0 K4 + 0x7C040200, // 0009 CALL R1 1 + 0x50040200, // 000A LDBOOL R1 1 0 + 0x90020001, // 000B SETMBR R0 K0 R1 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: every_second +********************************************************************/ +be_local_closure(Matter_Device_every_second, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(sessions), + /* K1 */ be_nested_str_weak(every_second), + /* K2 */ be_nested_str_weak(message_handler), + /* K3 */ be_nested_str_weak(commissioning_open), + /* K4 */ be_nested_str_weak(tasmota), + /* K5 */ be_nested_str_weak(time_reached), + }), + be_str_weak(every_second), + &be_const_str_solidified, + ( &(const binstruction[18]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x88040102, // 0003 GETMBR R1 R0 K2 + 0x8C040301, // 0004 GETMET R1 R1 K1 + 0x7C040200, // 0005 CALL R1 1 + 0x88040103, // 0006 GETMBR R1 R0 K3 + 0x4C080000, // 0007 LDNIL R2 + 0x20040202, // 0008 NE R1 R1 R2 + 0x78060006, // 0009 JMPF R1 #0011 + 0xB8060800, // 000A GETNGBL R1 K4 + 0x8C040305, // 000B GETMET R1 R1 K5 + 0x880C0103, // 000C GETMBR R3 R0 K3 + 0x7C040400, // 000D CALL R1 2 + 0x78060001, // 000E JMPF R1 #0011 + 0x4C040000, // 000F LDNIL R1 + 0x90020601, // 0010 SETMBR R0 K3 R1 + 0x80000000, // 0011 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: remove_fabric +********************************************************************/ +be_local_closure(Matter_Device_remove_fabric, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[16]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(log), + /* K2 */ be_nested_str_weak(MTR_X3A_X20removing_X20fabric_X20), + /* K3 */ be_nested_str_weak(get_fabric_id), + /* K4 */ be_nested_str_weak(copy), + /* K5 */ be_nested_str_weak(reverse), + /* K6 */ be_nested_str_weak(tohex), + /* K7 */ be_const_int(2), + /* K8 */ be_nested_str_weak(message_handler), + /* K9 */ be_nested_str_weak(im), + /* K10 */ be_nested_str_weak(subs_shop), + /* K11 */ be_nested_str_weak(remove_by_fabric), + /* K12 */ be_nested_str_weak(mdns_remove_op_discovery), + /* K13 */ be_nested_str_weak(sessions), + /* K14 */ be_nested_str_weak(remove_fabric), + /* K15 */ be_nested_str_weak(save_fabrics), + }), + be_str_weak(remove_fabric), + &be_const_str_solidified, + ( &(const binstruction[33]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x20080202, // 0001 NE R2 R1 R2 + 0x780A0019, // 0002 JMPF R2 #001D + 0xB80A0000, // 0003 GETNGBL R2 K0 + 0x8C080501, // 0004 GETMET R2 R2 K1 + 0x8C100303, // 0005 GETMET R4 R1 K3 + 0x7C100200, // 0006 CALL R4 1 + 0x8C100904, // 0007 GETMET R4 R4 K4 + 0x7C100200, // 0008 CALL R4 1 + 0x8C100905, // 0009 GETMET R4 R4 K5 + 0x7C100200, // 000A CALL R4 1 + 0x8C100906, // 000B GETMET R4 R4 K6 + 0x7C100200, // 000C CALL R4 1 + 0x00120404, // 000D ADD R4 K2 R4 + 0x58140007, // 000E LDCONST R5 K7 + 0x7C080600, // 000F CALL R2 3 + 0x88080108, // 0010 GETMBR R2 R0 K8 + 0x88080509, // 0011 GETMBR R2 R2 K9 + 0x8808050A, // 0012 GETMBR R2 R2 K10 + 0x8C08050B, // 0013 GETMET R2 R2 K11 + 0x5C100200, // 0014 MOVE R4 R1 + 0x7C080400, // 0015 CALL R2 2 + 0x8C08010C, // 0016 GETMET R2 R0 K12 + 0x5C100200, // 0017 MOVE R4 R1 + 0x7C080400, // 0018 CALL R2 2 + 0x8808010D, // 0019 GETMBR R2 R0 K13 + 0x8C08050E, // 001A GETMET R2 R2 K14 + 0x5C100200, // 001B MOVE R4 R1 + 0x7C080400, // 001C CALL R2 2 + 0x8808010D, // 001D GETMBR R2 R0 K13 + 0x8C08050F, // 001E GETMET R2 R2 K15 + 0x7C080200, // 001F CALL R2 1 + 0x80000000, // 0020 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: sort_distinct +********************************************************************/ +be_local_closure(Matter_Device_sort_distinct, /* name */ + be_nested_proto( + 7, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_const_class(be_class_Matter_Device), + /* K1 */ be_const_int(1), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(stop_iteration), + /* K4 */ be_nested_str_weak(remove), + }), + be_str_weak(sort_distinct), + &be_const_str_solidified, + ( &(const binstruction[53]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x60080010, // 0001 GETGBL R2 G16 + 0x600C000C, // 0002 GETGBL R3 G12 + 0x5C100000, // 0003 MOVE R4 R0 + 0x7C0C0200, // 0004 CALL R3 1 + 0x040C0701, // 0005 SUB R3 R3 K1 + 0x400E0203, // 0006 CONNECT R3 K1 R3 + 0x7C080200, // 0007 CALL R2 1 + 0xA8020010, // 0008 EXBLK 0 #001A + 0x5C0C0400, // 0009 MOVE R3 R2 + 0x7C0C0000, // 000A CALL R3 0 + 0x94100003, // 000B GETIDX R4 R0 R3 + 0x5C140600, // 000C MOVE R5 R3 + 0x24180B02, // 000D GT R6 R5 K2 + 0x781A0008, // 000E JMPF R6 #0018 + 0x04180B01, // 000F SUB R6 R5 K1 + 0x94180006, // 0010 GETIDX R6 R0 R6 + 0x24180C04, // 0011 GT R6 R6 R4 + 0x781A0004, // 0012 JMPF R6 #0018 + 0x04180B01, // 0013 SUB R6 R5 K1 + 0x94180006, // 0014 GETIDX R6 R0 R6 + 0x98000A06, // 0015 SETIDX R0 R5 R6 + 0x04140B01, // 0016 SUB R5 R5 K1 + 0x7001FFF4, // 0017 JMP #000D + 0x98000A04, // 0018 SETIDX R0 R5 R4 + 0x7001FFEE, // 0019 JMP #0009 + 0x58080003, // 001A LDCONST R2 K3 + 0xAC080200, // 001B CATCH R2 1 0 + 0xB0080000, // 001C RAISE 2 R0 R0 + 0x58080001, // 001D LDCONST R2 K1 + 0x600C000C, // 001E GETGBL R3 G12 + 0x5C100000, // 001F MOVE R4 R0 + 0x7C0C0200, // 0020 CALL R3 1 + 0x180C0701, // 0021 LE R3 R3 K1 + 0x780E0000, // 0022 JMPF R3 #0024 + 0x80040000, // 0023 RET 1 R0 + 0x940C0102, // 0024 GETIDX R3 R0 K2 + 0x6010000C, // 0025 GETGBL R4 G12 + 0x5C140000, // 0026 MOVE R5 R0 + 0x7C100200, // 0027 CALL R4 1 + 0x14100404, // 0028 LT R4 R2 R4 + 0x78120009, // 0029 JMPF R4 #0034 + 0x94100002, // 002A GETIDX R4 R0 R2 + 0x1C100803, // 002B EQ R4 R4 R3 + 0x78120003, // 002C JMPF R4 #0031 + 0x8C100104, // 002D GETMET R4 R0 K4 + 0x5C180400, // 002E MOVE R6 R2 + 0x7C100400, // 002F CALL R4 2 + 0x70020001, // 0030 JMP #0033 + 0x940C0002, // 0031 GETIDX R3 R0 R2 + 0x00080501, // 0032 ADD R2 R2 K1 + 0x7001FFF0, // 0033 JMP #0025 + 0x80040000, // 0034 RET 1 R0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: _init_basic_commissioning +********************************************************************/ +be_local_closure(Matter_Device__init_basic_commissioning, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(sessions), + /* K1 */ be_nested_str_weak(count_active_fabrics), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(start_root_basic_commissioning), + }), + be_str_weak(_init_basic_commissioning), + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x1C040302, // 0003 EQ R1 R1 K2 + 0x78060001, // 0004 JMPF R1 #0007 + 0x8C040103, // 0005 GETMET R1 R0 K3 + 0x7C040200, // 0006 CALL R1 1 + 0x80000000, // 0007 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: stop +********************************************************************/ +be_local_closure(Matter_Device_stop, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(remove_driver), + /* K2 */ be_nested_str_weak(udp_server), + /* K3 */ be_nested_str_weak(stop), + }), + be_str_weak(stop), + &be_const_str_solidified, + ( &(const binstruction[10]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C040400, // 0003 CALL R1 2 + 0x88040102, // 0004 GETMBR R1 R0 K2 + 0x78060002, // 0005 JMPF R1 #0009 + 0x88040102, // 0006 GETMBR R1 R0 K2 + 0x8C040303, // 0007 GETMET R1 R1 K3 + 0x7C040200, // 0008 CALL R1 1 + 0x80000000, // 0009 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: _trigger_read_sensors ********************************************************************/ @@ -1715,11 +3020,11 @@ be_local_closure(Matter_Device__trigger_read_sensors, /* name */ /******************************************************************** -** Solidified function: start_commissioning_complete +** Solidified function: _instantiate_plugins_from_config ********************************************************************/ -be_local_closure(Matter_Device_start_commissioning_complete, /* name */ +be_local_closure(Matter_Device__instantiate_plugins_from_config, /* name */ be_nested_proto( - 11, /* nstack */ + 18, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -1727,46 +3032,1253 @@ be_local_closure(Matter_Device_start_commissioning_complete, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ - /* K0 */ be_nested_str_weak(get_fabric), - /* K1 */ be_nested_str_weak(get_fabric_id), + ( &(const bvalue[31]) { /* constants */ + /* K0 */ be_nested_str_weak(k2l_num), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(log), + /* K3 */ be_nested_str_weak(MTR_X3A_X20Configuring_X20endpoints), + /* K4 */ be_const_int(2), + /* K5 */ be_nested_str_weak(plugins), + /* K6 */ be_nested_str_weak(push), + /* K7 */ be_nested_str_weak(matter), + /* K8 */ be_nested_str_weak(Plugin_Root), + /* K9 */ be_const_int(0), + /* K10 */ be_nested_str_weak(MTR_X3A_X20_X20_X20endpoint_X20_X3D_X20_X255i_X20type_X3A_X25s_X25s), + /* K11 */ be_nested_str_weak(root), + /* K12 */ be_nested_str_weak(), + /* K13 */ be_nested_str_weak(Plugin_Aggregator), + /* K14 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), + /* K15 */ be_nested_str_weak(find), + /* K16 */ be_nested_str_weak(type), + /* K17 */ be_nested_str_weak(MTR_X3A_X20no_X20class_X20name_X2C_X20skipping), + /* K18 */ be_const_int(3), + /* K19 */ be_nested_str_weak(MTR_X3A_X20only_X20one_X20root_X20node_X20allowed), + /* K20 */ be_nested_str_weak(plugins_classes), + /* K21 */ be_nested_str_weak(MTR_X3A_X20unknown_X20class_X20name_X20_X27), + /* K22 */ be_nested_str_weak(_X27_X20skipping), + /* K23 */ be_nested_str_weak(conf_to_log), + /* K24 */ be_nested_str_weak(MTR_X3A_X20Exception), + /* K25 */ be_nested_str_weak(_X7C), + /* K26 */ be_nested_str_weak(stop_iteration), + /* K27 */ be_nested_str_weak(aggregator), + /* K28 */ be_nested_str_weak(publish_result), + /* K29 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Initialized_X22_X3A1_X7D_X7D), + /* K30 */ be_nested_str_weak(Matter), + }), + be_str_weak(_instantiate_plugins_from_config), + &be_const_str_solidified, + ( &(const binstruction[154]) { /* code */ + 0x8C080100, // 0000 GETMET R2 R0 K0 + 0x5C100200, // 0001 MOVE R4 R1 + 0x7C080400, // 0002 CALL R2 2 + 0xB80E0200, // 0003 GETNGBL R3 K1 + 0x8C0C0702, // 0004 GETMET R3 R3 K2 + 0x58140003, // 0005 LDCONST R5 K3 + 0x58180004, // 0006 LDCONST R6 K4 + 0x7C0C0600, // 0007 CALL R3 3 + 0x880C0105, // 0008 GETMBR R3 R0 K5 + 0x8C0C0706, // 0009 GETMET R3 R3 K6 + 0xB8160E00, // 000A GETNGBL R5 K7 + 0x8C140B08, // 000B GETMET R5 R5 K8 + 0x5C1C0000, // 000C MOVE R7 R0 + 0x58200009, // 000D LDCONST R8 K9 + 0x60240013, // 000E GETGBL R9 G19 + 0x7C240000, // 000F CALL R9 0 + 0x7C140800, // 0010 CALL R5 4 + 0x7C0C0400, // 0011 CALL R3 2 + 0xB80E0200, // 0012 GETNGBL R3 K1 + 0x8C0C0702, // 0013 GETMET R3 R3 K2 + 0x60140018, // 0014 GETGBL R5 G24 + 0x5818000A, // 0015 LDCONST R6 K10 + 0x581C0009, // 0016 LDCONST R7 K9 + 0x5820000B, // 0017 LDCONST R8 K11 + 0x5824000C, // 0018 LDCONST R9 K12 + 0x7C140800, // 0019 CALL R5 4 + 0x58180004, // 001A LDCONST R6 K4 + 0x7C0C0600, // 001B CALL R3 3 + 0x880C0105, // 001C GETMBR R3 R0 K5 + 0x8C0C0706, // 001D GETMET R3 R3 K6 + 0xB8160E00, // 001E GETNGBL R5 K7 + 0x8C140B0D, // 001F GETMET R5 R5 K13 + 0x5C1C0000, // 0020 MOVE R7 R0 + 0xB8220E00, // 0021 GETNGBL R8 K7 + 0x8820110E, // 0022 GETMBR R8 R8 K14 + 0x60240013, // 0023 GETGBL R9 G19 + 0x7C240000, // 0024 CALL R9 0 + 0x7C140800, // 0025 CALL R5 4 + 0x7C0C0400, // 0026 CALL R3 2 + 0x600C0010, // 0027 GETGBL R3 G16 + 0x5C100400, // 0028 MOVE R4 R2 + 0x7C0C0200, // 0029 CALL R3 1 + 0xA802005A, // 002A EXBLK 0 #0086 + 0x5C100600, // 002B MOVE R4 R3 + 0x7C100000, // 002C CALL R4 0 + 0x1C140909, // 002D EQ R5 R4 K9 + 0x78160000, // 002E JMPF R5 #0030 + 0x7001FFFA, // 002F JMP #002B + 0xA8020042, // 0030 EXBLK 0 #0074 + 0x60140008, // 0031 GETGBL R5 G8 + 0x5C180800, // 0032 MOVE R6 R4 + 0x7C140200, // 0033 CALL R5 1 + 0x94140205, // 0034 GETIDX R5 R1 R5 + 0x8C180B0F, // 0035 GETMET R6 R5 K15 + 0x58200010, // 0036 LDCONST R8 K16 + 0x7C180400, // 0037 CALL R6 2 + 0x4C1C0000, // 0038 LDNIL R7 + 0x1C1C0C07, // 0039 EQ R7 R6 R7 + 0x781E0006, // 003A JMPF R7 #0042 + 0xB81E0200, // 003B GETNGBL R7 K1 + 0x8C1C0F02, // 003C GETMET R7 R7 K2 + 0x58240011, // 003D LDCONST R9 K17 + 0x58280012, // 003E LDCONST R10 K18 + 0x7C1C0600, // 003F CALL R7 3 + 0xA8040001, // 0040 EXBLK 1 1 + 0x7001FFE8, // 0041 JMP #002B + 0x1C1C0D0B, // 0042 EQ R7 R6 K11 + 0x781E0006, // 0043 JMPF R7 #004B + 0xB81E0200, // 0044 GETNGBL R7 K1 + 0x8C1C0F02, // 0045 GETMET R7 R7 K2 + 0x58240013, // 0046 LDCONST R9 K19 + 0x58280012, // 0047 LDCONST R10 K18 + 0x7C1C0600, // 0048 CALL R7 3 + 0xA8040001, // 0049 EXBLK 1 1 + 0x7001FFDF, // 004A JMP #002B + 0x881C0114, // 004B GETMBR R7 R0 K20 + 0x8C1C0F0F, // 004C GETMET R7 R7 K15 + 0x5C240C00, // 004D MOVE R9 R6 + 0x7C1C0400, // 004E CALL R7 2 + 0x4C200000, // 004F LDNIL R8 + 0x1C200E08, // 0050 EQ R8 R7 R8 + 0x7822000A, // 0051 JMPF R8 #005D + 0xB8220200, // 0052 GETNGBL R8 K1 + 0x8C201102, // 0053 GETMET R8 R8 K2 + 0x60280008, // 0054 GETGBL R10 G8 + 0x5C2C0C00, // 0055 MOVE R11 R6 + 0x7C280200, // 0056 CALL R10 1 + 0x002A2A0A, // 0057 ADD R10 K21 R10 + 0x00281516, // 0058 ADD R10 R10 K22 + 0x582C0004, // 0059 LDCONST R11 K4 + 0x7C200600, // 005A CALL R8 3 + 0xA8040001, // 005B EXBLK 1 1 + 0x7001FFCD, // 005C JMP #002B + 0x5C200E00, // 005D MOVE R8 R7 + 0x5C240000, // 005E MOVE R9 R0 + 0x5C280800, // 005F MOVE R10 R4 + 0x5C2C0A00, // 0060 MOVE R11 R5 + 0x7C200600, // 0061 CALL R8 3 + 0x88240105, // 0062 GETMBR R9 R0 K5 + 0x8C241306, // 0063 GETMET R9 R9 K6 + 0x5C2C1000, // 0064 MOVE R11 R8 + 0x7C240400, // 0065 CALL R9 2 + 0xB8260200, // 0066 GETNGBL R9 K1 + 0x8C241302, // 0067 GETMET R9 R9 K2 + 0x602C0018, // 0068 GETGBL R11 G24 + 0x5830000A, // 0069 LDCONST R12 K10 + 0x5C340800, // 006A MOVE R13 R4 + 0x5C380C00, // 006B MOVE R14 R6 + 0x8C3C0117, // 006C GETMET R15 R0 K23 + 0x5C440A00, // 006D MOVE R17 R5 + 0x7C3C0400, // 006E CALL R15 2 + 0x7C2C0800, // 006F CALL R11 4 + 0x58300004, // 0070 LDCONST R12 K4 + 0x7C240600, // 0071 CALL R9 3 + 0xA8040001, // 0072 EXBLK 1 1 + 0x70020010, // 0073 JMP #0085 + 0xAC140002, // 0074 CATCH R5 0 2 + 0x7002000D, // 0075 JMP #0084 + 0xB81E0200, // 0076 GETNGBL R7 K1 + 0x8C1C0F02, // 0077 GETMET R7 R7 K2 + 0x60240008, // 0078 GETGBL R9 G8 + 0x5C280A00, // 0079 MOVE R10 R5 + 0x7C240200, // 007A CALL R9 1 + 0x00263009, // 007B ADD R9 K24 R9 + 0x00241319, // 007C ADD R9 R9 K25 + 0x60280008, // 007D GETGBL R10 G8 + 0x5C2C0C00, // 007E MOVE R11 R6 + 0x7C280200, // 007F CALL R10 1 + 0x0024120A, // 0080 ADD R9 R9 R10 + 0x58280004, // 0081 LDCONST R10 K4 + 0x7C1C0600, // 0082 CALL R7 3 + 0x70020000, // 0083 JMP #0085 + 0xB0080000, // 0084 RAISE 2 R0 R0 + 0x7001FFA4, // 0085 JMP #002B + 0x580C001A, // 0086 LDCONST R3 K26 + 0xAC0C0200, // 0087 CATCH R3 1 0 + 0xB0080000, // 0088 RAISE 2 R0 R0 + 0xB80E0200, // 0089 GETNGBL R3 K1 + 0x8C0C0702, // 008A GETMET R3 R3 K2 + 0x60140018, // 008B GETGBL R5 G24 + 0x5818000A, // 008C LDCONST R6 K10 + 0xB81E0E00, // 008D GETNGBL R7 K7 + 0x881C0F0E, // 008E GETMBR R7 R7 K14 + 0x5820001B, // 008F LDCONST R8 K27 + 0x5824000C, // 0090 LDCONST R9 K12 + 0x7C140800, // 0091 CALL R5 4 + 0x58180004, // 0092 LDCONST R6 K4 + 0x7C0C0600, // 0093 CALL R3 3 + 0xB80E0200, // 0094 GETNGBL R3 K1 + 0x8C0C071C, // 0095 GETMET R3 R3 K28 + 0x5814001D, // 0096 LDCONST R5 K29 + 0x5818001E, // 0097 LDCONST R6 K30 + 0x7C0C0600, // 0098 CALL R3 3 + 0x80000000, // 0099 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: mdns_announce_op_discovery +********************************************************************/ +be_local_closure(Matter_Device_mdns_announce_op_discovery, /* name */ + be_nested_proto( + 14, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[27]) { /* constants */ + /* K0 */ be_nested_str_weak(mdns), + /* K1 */ be_nested_str_weak(get_device_id), /* K2 */ be_nested_str_weak(copy), /* K3 */ be_nested_str_weak(reverse), - /* K4 */ be_nested_str_weak(tohex), - /* K5 */ be_nested_str_weak(get_admin_vendor_name), - /* K6 */ be_nested_str_weak(tasmota), - /* K7 */ be_nested_str_weak(log), - /* K8 */ be_nested_str_weak(MTR_X3A_X20_X2D_X2D_X2D_X20Commissioning_X20complete_X20for_X20Fabric_X20_X27_X25s_X27_X20_X28Vendor_X20_X25s_X29_X20_X2D_X2D_X2D), - /* K9 */ be_const_int(2), - /* K10 */ be_nested_str_weak(stop_basic_commissioning), + /* K4 */ be_nested_str_weak(get_fabric_compressed), + /* K5 */ be_nested_str_weak(tohex), + /* K6 */ be_nested_str_weak(_X2D), + /* K7 */ be_nested_str_weak(tasmota), + /* K8 */ be_nested_str_weak(log), + /* K9 */ be_nested_str_weak(MTR_X3A_X20Operational_X20Discovery_X20node_X20_X3D_X20), + /* K10 */ be_const_int(3), + /* K11 */ be_nested_str_weak(eth), + /* K12 */ be_nested_str_weak(find), + /* K13 */ be_nested_str_weak(up), + /* K14 */ be_nested_str_weak(MTR_X3A_X20adding_X20mDNS_X20on_X20_X25s_X20_X27_X25s_X27_X20ptr_X20to_X20_X60_X25s_X2Elocal_X60), + /* K15 */ be_nested_str_weak(hostname_eth), + /* K16 */ be_nested_str_weak(add_service), + /* K17 */ be_nested_str_weak(_matter), + /* K18 */ be_nested_str_weak(_tcp), + /* K19 */ be_nested_str_weak(_I), + /* K20 */ be_nested_str_weak(MTR_X3A_X20adding_X20subtype_X3A_X20), + /* K21 */ be_nested_str_weak(add_subtype), + /* K22 */ be_nested_str_weak(wifi), + /* K23 */ be_nested_str_weak(hostname_wifi), + /* K24 */ be_nested_str_weak(MTR_X3A_X20Exception), + /* K25 */ be_nested_str_weak(_X7C), + /* K26 */ be_const_int(2), }), - be_str_weak(start_commissioning_complete), + be_str_weak(mdns_announce_op_discovery), &be_const_str_solidified, - ( &(const binstruction[24]) { /* code */ - 0x8C080300, // 0000 GETMET R2 R1 K0 - 0x7C080200, // 0001 CALL R2 1 - 0x8C0C0501, // 0002 GETMET R3 R2 K1 + ( &(const binstruction[121]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0xA8020064, // 0001 EXBLK 0 #0067 + 0x8C0C0301, // 0002 GETMET R3 R1 K1 0x7C0C0200, // 0003 CALL R3 1 0x8C0C0702, // 0004 GETMET R3 R3 K2 0x7C0C0200, // 0005 CALL R3 1 0x8C0C0703, // 0006 GETMET R3 R3 K3 0x7C0C0200, // 0007 CALL R3 1 - 0x8C0C0704, // 0008 GETMET R3 R3 K4 - 0x7C0C0200, // 0009 CALL R3 1 - 0x8C100505, // 000A GETMET R4 R2 K5 + 0x8C100304, // 0008 GETMET R4 R1 K4 + 0x7C100200, // 0009 CALL R4 1 + 0x8C140905, // 000A GETMET R5 R4 K5 + 0x7C140200, // 000B CALL R5 1 + 0x00140B06, // 000C ADD R5 R5 K6 + 0x8C180705, // 000D GETMET R6 R3 K5 + 0x7C180200, // 000E CALL R6 1 + 0x00140A06, // 000F ADD R5 R5 R6 + 0xB81A0E00, // 0010 GETNGBL R6 K7 + 0x8C180D08, // 0011 GETMET R6 R6 K8 + 0x00221205, // 0012 ADD R8 K9 R5 + 0x5824000A, // 0013 LDCONST R9 K10 + 0x7C180600, // 0014 CALL R6 3 + 0xB81A0E00, // 0015 GETNGBL R6 K7 + 0x8C180D0B, // 0016 GETMET R6 R6 K11 + 0x7C180200, // 0017 CALL R6 1 + 0x8C180D0C, // 0018 GETMET R6 R6 K12 + 0x5820000D, // 0019 LDCONST R8 K13 + 0x7C180400, // 001A CALL R6 2 + 0x781A0020, // 001B JMPF R6 #003D + 0xB81A0E00, // 001C GETNGBL R6 K7 + 0x8C180D08, // 001D GETMET R6 R6 K8 + 0x60200018, // 001E GETGBL R8 G24 + 0x5824000E, // 001F LDCONST R9 K14 + 0x5828000B, // 0020 LDCONST R10 K11 + 0x5C2C0A00, // 0021 MOVE R11 R5 + 0x8830010F, // 0022 GETMBR R12 R0 K15 + 0x7C200800, // 0023 CALL R8 4 + 0x5824000A, // 0024 LDCONST R9 K10 + 0x7C180600, // 0025 CALL R6 3 + 0x8C180510, // 0026 GETMET R6 R2 K16 + 0x58200011, // 0027 LDCONST R8 K17 + 0x58240012, // 0028 LDCONST R9 K18 + 0x542A15A3, // 0029 LDINT R10 5540 + 0x4C2C0000, // 002A LDNIL R11 + 0x5C300A00, // 002B MOVE R12 R5 + 0x8834010F, // 002C GETMBR R13 R0 K15 + 0x7C180E00, // 002D CALL R6 7 + 0x8C180905, // 002E GETMET R6 R4 K5 + 0x7C180200, // 002F CALL R6 1 + 0x001A2606, // 0030 ADD R6 K19 R6 + 0xB81E0E00, // 0031 GETNGBL R7 K7 + 0x8C1C0F08, // 0032 GETMET R7 R7 K8 + 0x00262806, // 0033 ADD R9 K20 R6 + 0x5828000A, // 0034 LDCONST R10 K10 + 0x7C1C0600, // 0035 CALL R7 3 + 0x8C1C0515, // 0036 GETMET R7 R2 K21 + 0x58240011, // 0037 LDCONST R9 K17 + 0x58280012, // 0038 LDCONST R10 K18 + 0x5C2C0A00, // 0039 MOVE R11 R5 + 0x8830010F, // 003A GETMBR R12 R0 K15 + 0x5C340C00, // 003B MOVE R13 R6 + 0x7C1C0C00, // 003C CALL R7 6 + 0xB81A0E00, // 003D GETNGBL R6 K7 + 0x8C180D16, // 003E GETMET R6 R6 K22 + 0x7C180200, // 003F CALL R6 1 + 0x8C180D0C, // 0040 GETMET R6 R6 K12 + 0x5820000D, // 0041 LDCONST R8 K13 + 0x7C180400, // 0042 CALL R6 2 + 0x781A0020, // 0043 JMPF R6 #0065 + 0xB81A0E00, // 0044 GETNGBL R6 K7 + 0x8C180D08, // 0045 GETMET R6 R6 K8 + 0x60200018, // 0046 GETGBL R8 G24 + 0x5824000E, // 0047 LDCONST R9 K14 + 0x58280016, // 0048 LDCONST R10 K22 + 0x5C2C0A00, // 0049 MOVE R11 R5 + 0x88300117, // 004A GETMBR R12 R0 K23 + 0x7C200800, // 004B CALL R8 4 + 0x5824000A, // 004C LDCONST R9 K10 + 0x7C180600, // 004D CALL R6 3 + 0x8C180510, // 004E GETMET R6 R2 K16 + 0x58200011, // 004F LDCONST R8 K17 + 0x58240012, // 0050 LDCONST R9 K18 + 0x542A15A3, // 0051 LDINT R10 5540 + 0x4C2C0000, // 0052 LDNIL R11 + 0x5C300A00, // 0053 MOVE R12 R5 + 0x88340117, // 0054 GETMBR R13 R0 K23 + 0x7C180E00, // 0055 CALL R6 7 + 0x8C180905, // 0056 GETMET R6 R4 K5 + 0x7C180200, // 0057 CALL R6 1 + 0x001A2606, // 0058 ADD R6 K19 R6 + 0xB81E0E00, // 0059 GETNGBL R7 K7 + 0x8C1C0F08, // 005A GETMET R7 R7 K8 + 0x00262806, // 005B ADD R9 K20 R6 + 0x5828000A, // 005C LDCONST R10 K10 + 0x7C1C0600, // 005D CALL R7 3 + 0x8C1C0515, // 005E GETMET R7 R2 K21 + 0x58240011, // 005F LDCONST R9 K17 + 0x58280012, // 0060 LDCONST R10 K18 + 0x5C2C0A00, // 0061 MOVE R11 R5 + 0x88300117, // 0062 GETMBR R12 R0 K23 + 0x5C340C00, // 0063 MOVE R13 R6 + 0x7C1C0C00, // 0064 CALL R7 6 + 0xA8040001, // 0065 EXBLK 1 1 + 0x70020010, // 0066 JMP #0078 + 0xAC0C0002, // 0067 CATCH R3 0 2 + 0x7002000D, // 0068 JMP #0077 + 0xB8160E00, // 0069 GETNGBL R5 K7 + 0x8C140B08, // 006A GETMET R5 R5 K8 + 0x601C0008, // 006B GETGBL R7 G8 + 0x5C200600, // 006C MOVE R8 R3 + 0x7C1C0200, // 006D CALL R7 1 + 0x001E3007, // 006E ADD R7 K24 R7 + 0x001C0F19, // 006F ADD R7 R7 K25 + 0x60200008, // 0070 GETGBL R8 G8 + 0x5C240800, // 0071 MOVE R9 R4 + 0x7C200200, // 0072 CALL R8 1 + 0x001C0E08, // 0073 ADD R7 R7 R8 + 0x5820001A, // 0074 LDCONST R8 K26 + 0x7C140600, // 0075 CALL R5 3 + 0x70020000, // 0076 JMP #0078 + 0xB0080000, // 0077 RAISE 2 R0 R0 + 0x80000000, // 0078 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: k2l +********************************************************************/ +be_local_closure(Matter_Device_k2l, /* name */ + be_nested_proto( + 8, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_const_class(be_class_Matter_Device), + /* K1 */ be_nested_str_weak(keys), + /* K2 */ be_nested_str_weak(push), + /* K3 */ be_nested_str_weak(stop_iteration), + /* K4 */ be_const_int(1), + /* K5 */ be_const_int(0), + }), + be_str_weak(k2l), + &be_const_str_solidified, + ( &(const binstruction[50]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x60080012, // 0001 GETGBL R2 G18 + 0x7C080000, // 0002 CALL R2 0 + 0x4C0C0000, // 0003 LDNIL R3 + 0x1C0C0003, // 0004 EQ R3 R0 R3 + 0x780E0000, // 0005 JMPF R3 #0007 + 0x80040400, // 0006 RET 1 R2 + 0x600C0010, // 0007 GETGBL R3 G16 + 0x8C100101, // 0008 GETMET R4 R0 K1 + 0x7C100200, // 0009 CALL R4 1 + 0x7C0C0200, // 000A CALL R3 1 + 0xA8020005, // 000B EXBLK 0 #0012 + 0x5C100600, // 000C MOVE R4 R3 + 0x7C100000, // 000D CALL R4 0 + 0x8C140502, // 000E GETMET R5 R2 K2 + 0x5C1C0800, // 000F MOVE R7 R4 + 0x7C140400, // 0010 CALL R5 2 + 0x7001FFF9, // 0011 JMP #000C + 0x580C0003, // 0012 LDCONST R3 K3 + 0xAC0C0200, // 0013 CATCH R3 1 0 + 0xB0080000, // 0014 RAISE 2 R0 R0 + 0x600C0010, // 0015 GETGBL R3 G16 + 0x6010000C, // 0016 GETGBL R4 G12 + 0x5C140400, // 0017 MOVE R5 R2 + 0x7C100200, // 0018 CALL R4 1 + 0x04100904, // 0019 SUB R4 R4 K4 + 0x40120804, // 001A CONNECT R4 K4 R4 + 0x7C0C0200, // 001B CALL R3 1 + 0xA8020010, // 001C EXBLK 0 #002E + 0x5C100600, // 001D MOVE R4 R3 + 0x7C100000, // 001E CALL R4 0 + 0x94140404, // 001F GETIDX R5 R2 R4 + 0x5C180800, // 0020 MOVE R6 R4 + 0x241C0D05, // 0021 GT R7 R6 K5 + 0x781E0008, // 0022 JMPF R7 #002C + 0x041C0D04, // 0023 SUB R7 R6 K4 + 0x941C0407, // 0024 GETIDX R7 R2 R7 + 0x241C0E05, // 0025 GT R7 R7 R5 + 0x781E0004, // 0026 JMPF R7 #002C + 0x041C0D04, // 0027 SUB R7 R6 K4 + 0x941C0407, // 0028 GETIDX R7 R2 R7 + 0x98080C07, // 0029 SETIDX R2 R6 R7 + 0x04180D04, // 002A SUB R6 R6 K4 + 0x7001FFF4, // 002B JMP #0021 + 0x98080C05, // 002C SETIDX R2 R6 R5 + 0x7001FFEE, // 002D JMP #001D + 0x580C0003, // 002E LDCONST R3 K3 + 0xAC0C0200, // 002F CATCH R3 1 0 + 0xB0080000, // 0030 RAISE 2 R0 R0 + 0x80040400, // 0031 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_plugin_class_arg +********************************************************************/ +be_local_closure(Matter_Device_get_plugin_class_arg, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(plugins_classes), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(ARG), + /* K3 */ be_nested_str_weak(), + }), + be_str_weak(get_plugin_class_arg), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x780A0001, // 0004 JMPF R2 #0007 + 0x880C0502, // 0005 GETMBR R3 R2 K2 + 0x70020000, // 0006 JMP #0008 + 0x580C0003, // 0007 LDCONST R3 K3 + 0x80040600, // 0008 RET 1 R3 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: stop_basic_commissioning +********************************************************************/ +be_local_closure(Matter_Device_stop_basic_commissioning, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[13]) { /* constants */ + /* K0 */ be_nested_str_weak(is_root_commissioning_open), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(publish_result), + /* K3 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Commissioning_X22_X3A0_X7D_X7D), + /* K4 */ be_nested_str_weak(Matter), + /* K5 */ be_nested_str_weak(commissioning_open), + /* K6 */ be_nested_str_weak(mdns_remove_PASE), + /* K7 */ be_nested_str_weak(commissioning_iterations), + /* K8 */ be_nested_str_weak(commissioning_discriminator), + /* K9 */ be_nested_str_weak(commissioning_salt), + /* K10 */ be_nested_str_weak(commissioning_w0), + /* K11 */ be_nested_str_weak(commissioning_L), + /* K12 */ be_nested_str_weak(commissioning_admin_fabric), + }), + be_str_weak(stop_basic_commissioning), + &be_const_str_solidified, + ( &(const binstruction[25]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x78060004, // 0002 JMPF R1 #0008 + 0xB8060200, // 0003 GETNGBL R1 K1 + 0x8C040302, // 0004 GETMET R1 R1 K2 + 0x580C0003, // 0005 LDCONST R3 K3 + 0x58100004, // 0006 LDCONST R4 K4 + 0x7C040600, // 0007 CALL R1 3 + 0x4C040000, // 0008 LDNIL R1 + 0x90020A01, // 0009 SETMBR R0 K5 R1 + 0x8C040106, // 000A GETMET R1 R0 K6 + 0x7C040200, // 000B CALL R1 1 + 0x4C040000, // 000C LDNIL R1 + 0x90020E01, // 000D SETMBR R0 K7 R1 + 0x4C040000, // 000E LDNIL R1 + 0x90021001, // 000F SETMBR R0 K8 R1 + 0x4C040000, // 0010 LDNIL R1 + 0x90021201, // 0011 SETMBR R0 K9 R1 + 0x4C040000, // 0012 LDNIL R1 + 0x90021401, // 0013 SETMBR R0 K10 R1 + 0x4C040000, // 0014 LDNIL R1 + 0x90021601, // 0015 SETMBR R0 K11 R1 + 0x4C040000, // 0016 LDNIL R1 + 0x90021801, // 0017 SETMBR R0 K12 R1 + 0x80000000, // 0018 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: every_250ms +********************************************************************/ +be_local_closure(Matter_Device_every_250ms, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(message_handler), + /* K1 */ be_nested_str_weak(every_250ms), + /* K2 */ be_nested_str_weak(read_sensors_scheduler), + /* K3 */ be_const_int(0), + /* K4 */ be_nested_str_weak(plugins), + /* K5 */ be_const_int(1), + }), + be_str_weak(every_250ms), + &be_const_str_solidified, + ( &(const binstruction[18]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x8C040102, // 0003 GETMET R1 R0 K2 + 0x7C040200, // 0004 CALL R1 1 + 0x58040003, // 0005 LDCONST R1 K3 + 0x6008000C, // 0006 GETGBL R2 G12 + 0x880C0104, // 0007 GETMBR R3 R0 K4 + 0x7C080200, // 0008 CALL R2 1 + 0x14080202, // 0009 LT R2 R1 R2 + 0x780A0005, // 000A JMPF R2 #0011 + 0x88080104, // 000B GETMBR R2 R0 K4 + 0x94080401, // 000C GETIDX R2 R2 R1 + 0x8C080501, // 000D GETMET R2 R2 K1 + 0x7C080200, // 000E CALL R2 1 + 0x00040305, // 000F ADD R1 R1 K5 + 0x7001FFF4, // 0010 JMP #0006 + 0x80000000, // 0011 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: _start_udp +********************************************************************/ +be_local_closure(Matter_Device__start_udp, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 1]) { + be_nested_proto( + 8, /* nstack */ + 3, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(msg_received), + }), + be_str_weak(_X3Clambda_X3E), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x680C0000, // 0000 GETUPV R3 U0 + 0x8C0C0700, // 0001 GETMET R3 R3 K0 + 0x5C140000, // 0002 MOVE R5 R0 + 0x5C180200, // 0003 MOVE R6 R1 + 0x5C1C0400, // 0004 MOVE R7 R2 + 0x7C0C0800, // 0005 CALL R3 4 + 0x80040600, // 0006 RET 1 R3 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(udp_server), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(log), + /* K3 */ be_nested_str_weak(MTR_X3A_X20Starting_X20UDP_X20server_X20on_X20port_X3A_X20), + /* K4 */ be_const_int(2), + /* K5 */ be_nested_str_weak(matter), + /* K6 */ be_nested_str_weak(UDPServer), + /* K7 */ be_nested_str_weak(), + /* K8 */ be_nested_str_weak(start), + }), + be_str_weak(_start_udp), + &be_const_str_solidified, + ( &(const binstruction[28]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x780A0000, // 0001 JMPF R2 #0003 + 0x80000400, // 0002 RET 0 + 0x4C080000, // 0003 LDNIL R2 + 0x1C080202, // 0004 EQ R2 R1 R2 + 0x780A0000, // 0005 JMPF R2 #0007 + 0x540615A3, // 0006 LDINT R1 5540 + 0xB80A0200, // 0007 GETNGBL R2 K1 + 0x8C080502, // 0008 GETMET R2 R2 K2 + 0x60100008, // 0009 GETGBL R4 G8 + 0x5C140200, // 000A MOVE R5 R1 0x7C100200, // 000B CALL R4 1 - 0xB8160C00, // 000C GETNGBL R5 K6 - 0x8C140B07, // 000D GETMET R5 R5 K7 - 0x601C0018, // 000E GETGBL R7 G24 - 0x58200008, // 000F LDCONST R8 K8 - 0x5C240600, // 0010 MOVE R9 R3 - 0x5C280800, // 0011 MOVE R10 R4 - 0x7C1C0600, // 0012 CALL R7 3 - 0x58200009, // 0013 LDCONST R8 K9 - 0x7C140600, // 0014 CALL R5 3 - 0x8C14010A, // 0015 GETMET R5 R0 K10 - 0x7C140200, // 0016 CALL R5 1 - 0x80000000, // 0017 RET 0 + 0x00120604, // 000C ADD R4 K3 R4 + 0x58140004, // 000D LDCONST R5 K4 + 0x7C080600, // 000E CALL R2 3 + 0xB80A0A00, // 000F GETNGBL R2 K5 + 0x8C080506, // 0010 GETMET R2 R2 K6 + 0x5C100000, // 0011 MOVE R4 R0 + 0x58140007, // 0012 LDCONST R5 K7 + 0x5C180200, // 0013 MOVE R6 R1 + 0x7C080800, // 0014 CALL R2 4 + 0x90020002, // 0015 SETMBR R0 K0 R2 + 0x88080100, // 0016 GETMBR R2 R0 K0 + 0x8C080508, // 0017 GETMET R2 R2 K8 + 0x84100000, // 0018 CLOSURE R4 P0 + 0x7C080400, // 0019 CALL R2 2 + 0xA0000000, // 001A CLOSE R0 + 0x80000000, // 001B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: k2l_num +********************************************************************/ +be_local_closure(Matter_Device_k2l_num, /* name */ + be_nested_proto( + 9, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_const_class(be_class_Matter_Device), + /* K1 */ be_nested_str_weak(keys), + /* K2 */ be_nested_str_weak(push), + /* K3 */ be_nested_str_weak(stop_iteration), + /* K4 */ be_const_int(1), + /* K5 */ be_const_int(0), + }), + be_str_weak(k2l_num), + &be_const_str_solidified, + ( &(const binstruction[52]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x60080012, // 0001 GETGBL R2 G18 + 0x7C080000, // 0002 CALL R2 0 + 0x4C0C0000, // 0003 LDNIL R3 + 0x1C0C0003, // 0004 EQ R3 R0 R3 + 0x780E0000, // 0005 JMPF R3 #0007 + 0x80040400, // 0006 RET 1 R2 + 0x600C0010, // 0007 GETGBL R3 G16 + 0x8C100101, // 0008 GETMET R4 R0 K1 + 0x7C100200, // 0009 CALL R4 1 + 0x7C0C0200, // 000A CALL R3 1 + 0xA8020007, // 000B EXBLK 0 #0014 + 0x5C100600, // 000C MOVE R4 R3 + 0x7C100000, // 000D CALL R4 0 + 0x8C140502, // 000E GETMET R5 R2 K2 + 0x601C0009, // 000F GETGBL R7 G9 + 0x5C200800, // 0010 MOVE R8 R4 + 0x7C1C0200, // 0011 CALL R7 1 + 0x7C140400, // 0012 CALL R5 2 + 0x7001FFF7, // 0013 JMP #000C + 0x580C0003, // 0014 LDCONST R3 K3 + 0xAC0C0200, // 0015 CATCH R3 1 0 + 0xB0080000, // 0016 RAISE 2 R0 R0 + 0x600C0010, // 0017 GETGBL R3 G16 + 0x6010000C, // 0018 GETGBL R4 G12 + 0x5C140400, // 0019 MOVE R5 R2 + 0x7C100200, // 001A CALL R4 1 + 0x04100904, // 001B SUB R4 R4 K4 + 0x40120804, // 001C CONNECT R4 K4 R4 + 0x7C0C0200, // 001D CALL R3 1 + 0xA8020010, // 001E EXBLK 0 #0030 + 0x5C100600, // 001F MOVE R4 R3 + 0x7C100000, // 0020 CALL R4 0 + 0x94140404, // 0021 GETIDX R5 R2 R4 + 0x5C180800, // 0022 MOVE R6 R4 + 0x241C0D05, // 0023 GT R7 R6 K5 + 0x781E0008, // 0024 JMPF R7 #002E + 0x041C0D04, // 0025 SUB R7 R6 K4 + 0x941C0407, // 0026 GETIDX R7 R2 R7 + 0x241C0E05, // 0027 GT R7 R7 R5 + 0x781E0004, // 0028 JMPF R7 #002E + 0x041C0D04, // 0029 SUB R7 R6 K4 + 0x941C0407, // 002A GETIDX R7 R2 R7 + 0x98080C07, // 002B SETIDX R2 R6 R7 + 0x04180D04, // 002C SUB R6 R6 K4 + 0x7001FFF4, // 002D JMP #0023 + 0x98080C05, // 002E SETIDX R2 R6 R5 + 0x7001FFEE, // 002F JMP #001F + 0x580C0003, // 0030 LDCONST R3 K3 + 0xAC0C0200, // 0031 CATCH R3 1 0 + 0xB0080000, // 0032 RAISE 2 R0 R0 + 0x80040400, // 0033 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_active_endpoints +********************************************************************/ +be_local_closure(Matter_Device_get_active_endpoints, /* name */ + be_nested_proto( + 9, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(plugins), + /* K1 */ be_nested_str_weak(get_endpoint), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(find), + /* K4 */ be_nested_str_weak(push), + /* K5 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(get_active_endpoints), + &be_const_str_solidified, + ( &(const binstruction[28]) { /* code */ + 0x60080012, // 0000 GETGBL R2 G18 + 0x7C080000, // 0001 CALL R2 0 + 0x600C0010, // 0002 GETGBL R3 G16 + 0x88100100, // 0003 GETMBR R4 R0 K0 + 0x7C0C0200, // 0004 CALL R3 1 + 0xA8020011, // 0005 EXBLK 0 #0018 + 0x5C100600, // 0006 MOVE R4 R3 + 0x7C100000, // 0007 CALL R4 0 + 0x8C140901, // 0008 GETMET R5 R4 K1 + 0x7C140200, // 0009 CALL R5 1 + 0x78060002, // 000A JMPF R1 #000E + 0x1C180B02, // 000B EQ R6 R5 K2 + 0x781A0000, // 000C JMPF R6 #000E + 0x7001FFF7, // 000D JMP #0006 + 0x8C180503, // 000E GETMET R6 R2 K3 + 0x5C200A00, // 000F MOVE R8 R5 + 0x7C180400, // 0010 CALL R6 2 + 0x4C1C0000, // 0011 LDNIL R7 + 0x1C180C07, // 0012 EQ R6 R6 R7 + 0x781A0002, // 0013 JMPF R6 #0017 + 0x8C180504, // 0014 GETMET R6 R2 K4 + 0x5C200A00, // 0015 MOVE R8 R5 + 0x7C180400, // 0016 CALL R6 2 + 0x7001FFED, // 0017 JMP #0006 + 0x580C0005, // 0018 LDCONST R3 K5 + 0xAC0C0200, // 0019 CATCH R3 1 0 + 0xB0080000, // 001A RAISE 2 R0 R0 + 0x80040400, // 001B RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: check_config_ep +********************************************************************/ +be_local_closure(Matter_Device_check_config_ep, /* name */ + be_nested_proto( + 10, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[14]) { /* constants */ + /* K0 */ be_nested_str_weak(plugins_config), + /* K1 */ be_nested_str_weak(keys), + /* K2 */ be_nested_str_weak(push), + /* K3 */ be_nested_str_weak(stop_iteration), + /* K4 */ be_const_int(0), + /* K5 */ be_nested_str_weak(tasmota), + /* K6 */ be_nested_str_weak(log), + /* K7 */ be_nested_str_weak(MTR_X3A_X20invalid_X20entry_X20with_X20ep_X20_X270_X27), + /* K8 */ be_const_int(2), + /* K9 */ be_nested_str_weak(remove), + /* K10 */ be_nested_str_weak(matter), + /* K11 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), + /* K12 */ be_nested_str_weak(MTR_X3A_X20endpoint_X20_X25s_X20collides_X20wit_X20aggregator_X2C_X20relocating_X20to_X20_X25s), + /* K13 */ be_nested_str_weak(next_ep), + }), + be_str_weak(check_config_ep), + &be_const_str_solidified, + ( &(const binstruction[73]) { /* code */ + 0x60040012, // 0000 GETGBL R1 G18 + 0x7C040000, // 0001 CALL R1 0 + 0x60080010, // 0002 GETGBL R2 G16 + 0x880C0100, // 0003 GETMBR R3 R0 K0 + 0x8C0C0701, // 0004 GETMET R3 R3 K1 + 0x7C0C0200, // 0005 CALL R3 1 + 0x7C080200, // 0006 CALL R2 1 + 0xA8020007, // 0007 EXBLK 0 #0010 + 0x5C0C0400, // 0008 MOVE R3 R2 + 0x7C0C0000, // 0009 CALL R3 0 + 0x8C100702, // 000A GETMET R4 R3 K2 + 0x60180009, // 000B GETGBL R6 G9 + 0x5C1C0600, // 000C MOVE R7 R3 + 0x7C180200, // 000D CALL R6 1 + 0x7C100400, // 000E CALL R4 2 + 0x7001FFF7, // 000F JMP #0008 + 0x58080003, // 0010 LDCONST R2 K3 + 0xAC080200, // 0011 CATCH R2 1 0 + 0xB0080000, // 0012 RAISE 2 R0 R0 + 0x60080010, // 0013 GETGBL R2 G16 + 0x5C0C0200, // 0014 MOVE R3 R1 + 0x7C080200, // 0015 CALL R2 1 + 0xA802002D, // 0016 EXBLK 0 #0045 + 0x5C0C0400, // 0017 MOVE R3 R2 + 0x7C0C0000, // 0018 CALL R3 0 + 0x1C100704, // 0019 EQ R4 R3 K4 + 0x7812000B, // 001A JMPF R4 #0027 + 0xB8120A00, // 001B GETNGBL R4 K5 + 0x8C100906, // 001C GETMET R4 R4 K6 + 0x58180007, // 001D LDCONST R6 K7 + 0x581C0008, // 001E LDCONST R7 K8 + 0x7C100600, // 001F CALL R4 3 + 0x88100100, // 0020 GETMBR R4 R0 K0 + 0x8C100909, // 0021 GETMET R4 R4 K9 + 0x60180008, // 0022 GETGBL R6 G8 + 0x5C1C0600, // 0023 MOVE R7 R3 + 0x7C180200, // 0024 CALL R6 1 + 0x7C100400, // 0025 CALL R4 2 + 0x7002001C, // 0026 JMP #0044 + 0xB8121400, // 0027 GETNGBL R4 K10 + 0x8810090B, // 0028 GETMBR R4 R4 K11 + 0x1C100604, // 0029 EQ R4 R3 R4 + 0x78120018, // 002A JMPF R4 #0044 + 0xB8120A00, // 002B GETNGBL R4 K5 + 0x8C100906, // 002C GETMET R4 R4 K6 + 0x60180018, // 002D GETGBL R6 G24 + 0x581C000C, // 002E LDCONST R7 K12 + 0x5C200600, // 002F MOVE R8 R3 + 0x8824010D, // 0030 GETMBR R9 R0 K13 + 0x7C180600, // 0031 CALL R6 3 + 0x581C0008, // 0032 LDCONST R7 K8 + 0x7C100600, // 0033 CALL R4 3 + 0x60100008, // 0034 GETGBL R4 G8 + 0x8814010D, // 0035 GETMBR R5 R0 K13 + 0x7C100200, // 0036 CALL R4 1 + 0x88140100, // 0037 GETMBR R5 R0 K0 + 0x60180008, // 0038 GETGBL R6 G8 + 0x5C1C0600, // 0039 MOVE R7 R3 + 0x7C180200, // 003A CALL R6 1 + 0x881C0100, // 003B GETMBR R7 R0 K0 + 0x94180E06, // 003C GETIDX R6 R7 R6 + 0x98140806, // 003D SETIDX R5 R4 R6 + 0x88100100, // 003E GETMBR R4 R0 K0 + 0x8C100909, // 003F GETMET R4 R4 K9 + 0x60180008, // 0040 GETGBL R6 G8 + 0x5C1C0600, // 0041 MOVE R7 R3 + 0x7C180200, // 0042 CALL R6 1 + 0x7C100400, // 0043 CALL R4 2 + 0x7001FFD1, // 0044 JMP #0017 + 0x58080003, // 0045 LDCONST R2 K3 + 0xAC080200, // 0046 CATCH R2 1 0 + 0xB0080000, // 0047 RAISE 2 R0 R0 + 0x80000000, // 0048 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: msg_send +********************************************************************/ +be_local_closure(Matter_Device_msg_send, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(udp_server), + /* K1 */ be_nested_str_weak(send_UDP), + }), + be_str_weak(msg_send), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x80040400, // 0004 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: autoconf_sensors_list +********************************************************************/ +be_local_closure(Matter_Device_autoconf_sensors_list, /* name */ + be_nested_proto( + 10, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[18]) { /* constants */ + /* K0 */ be_nested_str_weak(k2l), + /* K1 */ be_nested_str_weak(contains), + /* K2 */ be_nested_str_weak(Temperature), + /* K3 */ be_nested_str_weak(_X23Temperature), + /* K4 */ be_nested_str_weak(push), + /* K5 */ be_nested_str_weak(type), + /* K6 */ be_nested_str_weak(temperature), + /* K7 */ be_nested_str_weak(filter), + /* K8 */ be_nested_str_weak(stop_iteration), + /* K9 */ be_nested_str_weak(Pressure), + /* K10 */ be_nested_str_weak(_X23Pressure), + /* K11 */ be_nested_str_weak(pressure), + /* K12 */ be_nested_str_weak(Illuminance), + /* K13 */ be_nested_str_weak(_X23Illuminance), + /* K14 */ be_nested_str_weak(illuminance), + /* K15 */ be_nested_str_weak(Humidity), + /* K16 */ be_nested_str_weak(_X23Humidity), + /* K17 */ be_nested_str_weak(humidity), + }), + be_str_weak(autoconf_sensors_list), + &be_const_str_solidified, + ( &(const binstruction[119]) { /* code */ + 0x60080012, // 0000 GETGBL R2 G18 + 0x7C080000, // 0001 CALL R2 0 + 0x600C0010, // 0002 GETGBL R3 G16 + 0x8C100100, // 0003 GETMET R4 R0 K0 + 0x5C180200, // 0004 MOVE R6 R1 + 0x7C100400, // 0005 CALL R4 2 + 0x7C0C0200, // 0006 CALL R3 1 + 0xA8020013, // 0007 EXBLK 0 #001C + 0x5C100600, // 0008 MOVE R4 R3 + 0x7C100000, // 0009 CALL R4 0 + 0x94140204, // 000A GETIDX R5 R1 R4 + 0x6018000F, // 000B GETGBL R6 G15 + 0x5C1C0A00, // 000C MOVE R7 R5 + 0x60200013, // 000D GETGBL R8 G19 + 0x7C180400, // 000E CALL R6 2 + 0x781A000A, // 000F JMPF R6 #001B + 0x8C180B01, // 0010 GETMET R6 R5 K1 + 0x58200002, // 0011 LDCONST R8 K2 + 0x7C180400, // 0012 CALL R6 2 + 0x781A0006, // 0013 JMPF R6 #001B + 0x00180903, // 0014 ADD R6 R4 K3 + 0x8C1C0504, // 0015 GETMET R7 R2 K4 + 0x60240013, // 0016 GETGBL R9 G19 + 0x7C240000, // 0017 CALL R9 0 + 0x98260B06, // 0018 SETIDX R9 K5 K6 + 0x98260E06, // 0019 SETIDX R9 K7 R6 + 0x7C1C0400, // 001A CALL R7 2 + 0x7001FFEB, // 001B JMP #0008 + 0x580C0008, // 001C LDCONST R3 K8 + 0xAC0C0200, // 001D CATCH R3 1 0 + 0xB0080000, // 001E RAISE 2 R0 R0 + 0x600C0010, // 001F GETGBL R3 G16 + 0x8C100100, // 0020 GETMET R4 R0 K0 + 0x5C180200, // 0021 MOVE R6 R1 + 0x7C100400, // 0022 CALL R4 2 + 0x7C0C0200, // 0023 CALL R3 1 + 0xA8020013, // 0024 EXBLK 0 #0039 + 0x5C100600, // 0025 MOVE R4 R3 + 0x7C100000, // 0026 CALL R4 0 + 0x94140204, // 0027 GETIDX R5 R1 R4 + 0x6018000F, // 0028 GETGBL R6 G15 + 0x5C1C0A00, // 0029 MOVE R7 R5 + 0x60200013, // 002A GETGBL R8 G19 + 0x7C180400, // 002B CALL R6 2 + 0x781A000A, // 002C JMPF R6 #0038 + 0x8C180B01, // 002D GETMET R6 R5 K1 + 0x58200009, // 002E LDCONST R8 K9 + 0x7C180400, // 002F CALL R6 2 + 0x781A0006, // 0030 JMPF R6 #0038 + 0x0018090A, // 0031 ADD R6 R4 K10 + 0x8C1C0504, // 0032 GETMET R7 R2 K4 + 0x60240013, // 0033 GETGBL R9 G19 + 0x7C240000, // 0034 CALL R9 0 + 0x98260B0B, // 0035 SETIDX R9 K5 K11 + 0x98260E06, // 0036 SETIDX R9 K7 R6 + 0x7C1C0400, // 0037 CALL R7 2 + 0x7001FFEB, // 0038 JMP #0025 + 0x580C0008, // 0039 LDCONST R3 K8 + 0xAC0C0200, // 003A CATCH R3 1 0 + 0xB0080000, // 003B RAISE 2 R0 R0 + 0x600C0010, // 003C GETGBL R3 G16 + 0x8C100100, // 003D GETMET R4 R0 K0 + 0x5C180200, // 003E MOVE R6 R1 + 0x7C100400, // 003F CALL R4 2 + 0x7C0C0200, // 0040 CALL R3 1 + 0xA8020013, // 0041 EXBLK 0 #0056 + 0x5C100600, // 0042 MOVE R4 R3 + 0x7C100000, // 0043 CALL R4 0 + 0x94140204, // 0044 GETIDX R5 R1 R4 + 0x6018000F, // 0045 GETGBL R6 G15 + 0x5C1C0A00, // 0046 MOVE R7 R5 + 0x60200013, // 0047 GETGBL R8 G19 + 0x7C180400, // 0048 CALL R6 2 + 0x781A000A, // 0049 JMPF R6 #0055 + 0x8C180B01, // 004A GETMET R6 R5 K1 + 0x5820000C, // 004B LDCONST R8 K12 + 0x7C180400, // 004C CALL R6 2 + 0x781A0006, // 004D JMPF R6 #0055 + 0x0018090D, // 004E ADD R6 R4 K13 + 0x8C1C0504, // 004F GETMET R7 R2 K4 + 0x60240013, // 0050 GETGBL R9 G19 + 0x7C240000, // 0051 CALL R9 0 + 0x98260B0E, // 0052 SETIDX R9 K5 K14 + 0x98260E06, // 0053 SETIDX R9 K7 R6 + 0x7C1C0400, // 0054 CALL R7 2 + 0x7001FFEB, // 0055 JMP #0042 + 0x580C0008, // 0056 LDCONST R3 K8 + 0xAC0C0200, // 0057 CATCH R3 1 0 + 0xB0080000, // 0058 RAISE 2 R0 R0 + 0x600C0010, // 0059 GETGBL R3 G16 + 0x8C100100, // 005A GETMET R4 R0 K0 + 0x5C180200, // 005B MOVE R6 R1 + 0x7C100400, // 005C CALL R4 2 + 0x7C0C0200, // 005D CALL R3 1 + 0xA8020013, // 005E EXBLK 0 #0073 + 0x5C100600, // 005F MOVE R4 R3 + 0x7C100000, // 0060 CALL R4 0 + 0x94140204, // 0061 GETIDX R5 R1 R4 + 0x6018000F, // 0062 GETGBL R6 G15 + 0x5C1C0A00, // 0063 MOVE R7 R5 + 0x60200013, // 0064 GETGBL R8 G19 + 0x7C180400, // 0065 CALL R6 2 + 0x781A000A, // 0066 JMPF R6 #0072 + 0x8C180B01, // 0067 GETMET R6 R5 K1 + 0x5820000F, // 0068 LDCONST R8 K15 + 0x7C180400, // 0069 CALL R6 2 + 0x781A0006, // 006A JMPF R6 #0072 + 0x00180910, // 006B ADD R6 R4 K16 + 0x8C1C0504, // 006C GETMET R7 R2 K4 + 0x60240013, // 006D GETGBL R9 G19 + 0x7C240000, // 006E CALL R9 0 + 0x98260B11, // 006F SETIDX R9 K5 K17 + 0x98260E06, // 0070 SETIDX R9 K7 R6 + 0x7C1C0400, // 0071 CALL R7 2 + 0x7001FFEB, // 0072 JMP #005F + 0x580C0008, // 0073 LDCONST R3 K8 + 0xAC0C0200, // 0074 CATCH R3 1 0 + 0xB0080000, // 0075 RAISE 2 R0 R0 + 0x80040400, // 0076 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: find_plugin_by_endpoint +********************************************************************/ +be_local_closure(Matter_Device_find_plugin_by_endpoint, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_const_int(0), + /* K1 */ be_nested_str_weak(plugins), + /* K2 */ be_nested_str_weak(get_endpoint), + /* K3 */ be_const_int(1), + }), + be_str_weak(find_plugin_by_endpoint), + &be_const_str_solidified, + ( &(const binstruction[17]) { /* code */ + 0x58080000, // 0000 LDCONST R2 K0 + 0x600C000C, // 0001 GETGBL R3 G12 + 0x88100101, // 0002 GETMBR R4 R0 K1 + 0x7C0C0200, // 0003 CALL R3 1 + 0x140C0403, // 0004 LT R3 R2 R3 + 0x780E0008, // 0005 JMPF R3 #000F + 0x880C0101, // 0006 GETMBR R3 R0 K1 + 0x940C0602, // 0007 GETIDX R3 R3 R2 + 0x8C100702, // 0008 GETMET R4 R3 K2 + 0x7C100200, // 0009 CALL R4 1 + 0x1C100801, // 000A EQ R4 R4 R1 + 0x78120000, // 000B JMPF R4 #000D + 0x80040600, // 000C RET 1 R3 + 0x00080503, // 000D ADD R2 R2 K3 + 0x7001FFF1, // 000E JMP #0001 + 0x4C0C0000, // 000F LDNIL R3 + 0x80040600, // 0010 RET 1 R3 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start_root_basic_commissioning +********************************************************************/ +be_local_closure(Matter_Device_start_root_basic_commissioning, /* name */ + be_nested_proto( + 13, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[18]) { /* constants */ + /* K0 */ be_nested_str_weak(PASE_TIMEOUT), + /* K1 */ be_nested_str_weak(compute_manual_pairing_code), + /* K2 */ be_nested_str_weak(tasmota), + /* K3 */ be_nested_str_weak(log), + /* K4 */ be_nested_str_weak(MTR_X3A_X20Manual_X20pairing_X20code_X3A_X20_X25s), + /* K5 */ be_const_int(2), + /* K6 */ be_nested_str_weak(compute_qrcode_content), + /* K7 */ be_nested_str_weak(publish_result), + /* K8 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Commissioning_X22_X3A1_X2C_X22PairingCode_X22_X3A_X22_X25s_X22_X2C_X22QRCode_X22_X3A_X22_X25s_X22_X7D_X7D), + /* K9 */ be_nested_str_weak(Matter), + /* K10 */ be_nested_str_weak(_compute_pbkdf), + /* K11 */ be_nested_str_weak(root_passcode), + /* K12 */ be_nested_str_weak(root_iterations), + /* K13 */ be_nested_str_weak(root_salt), + /* K14 */ be_nested_str_weak(start_basic_commissioning), + /* K15 */ be_nested_str_weak(root_discriminator), + /* K16 */ be_nested_str_weak(root_w0), + /* K17 */ be_nested_str_weak(root_L), + }), + be_str_weak(start_root_basic_commissioning), + &be_const_str_solidified, + ( &(const binstruction[40]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x1C080202, // 0001 EQ R2 R1 R2 + 0x780A0000, // 0002 JMPF R2 #0004 + 0x88040100, // 0003 GETMBR R1 R0 K0 + 0x8C080101, // 0004 GETMET R2 R0 K1 + 0x7C080200, // 0005 CALL R2 1 + 0xB80E0400, // 0006 GETNGBL R3 K2 + 0x8C0C0703, // 0007 GETMET R3 R3 K3 + 0x60140018, // 0008 GETGBL R5 G24 + 0x58180004, // 0009 LDCONST R6 K4 + 0x5C1C0400, // 000A MOVE R7 R2 + 0x7C140400, // 000B CALL R5 2 + 0x58180005, // 000C LDCONST R6 K5 + 0x7C0C0600, // 000D CALL R3 3 + 0x8C0C0106, // 000E GETMET R3 R0 K6 + 0x7C0C0200, // 000F CALL R3 1 + 0xB8120400, // 0010 GETNGBL R4 K2 + 0x8C100907, // 0011 GETMET R4 R4 K7 + 0x60180018, // 0012 GETGBL R6 G24 + 0x581C0008, // 0013 LDCONST R7 K8 + 0x5C200400, // 0014 MOVE R8 R2 + 0x5C240600, // 0015 MOVE R9 R3 + 0x7C180600, // 0016 CALL R6 3 + 0x581C0009, // 0017 LDCONST R7 K9 + 0x7C100600, // 0018 CALL R4 3 + 0x8C10010A, // 0019 GETMET R4 R0 K10 + 0x8818010B, // 001A GETMBR R6 R0 K11 + 0x881C010C, // 001B GETMBR R7 R0 K12 + 0x8820010D, // 001C GETMBR R8 R0 K13 + 0x7C100800, // 001D CALL R4 4 + 0x8C10010E, // 001E GETMET R4 R0 K14 + 0x5C180200, // 001F MOVE R6 R1 + 0x881C010C, // 0020 GETMBR R7 R0 K12 + 0x8820010F, // 0021 GETMBR R8 R0 K15 + 0x8824010D, // 0022 GETMBR R9 R0 K13 + 0x88280110, // 0023 GETMBR R10 R0 K16 + 0x882C0111, // 0024 GETMBR R11 R0 K17 + 0x4C300000, // 0025 LDNIL R12 + 0x7C101000, // 0026 CALL R4 8 + 0x80000000, // 0027 RET 0 }) ) ); @@ -1854,9 +4366,768 @@ be_local_closure(Matter_Device_process_attribute_read_solo, /* name */ /******************************************************************** -** Solidified function: start_commissioning_complete_deferred +** Solidified function: start_operational_discovery ********************************************************************/ -be_local_closure(Matter_Device_start_commissioning_complete_deferred, /* name */ +be_local_closure(Matter_Device_start_operational_discovery, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(crypto), + /* K1 */ be_nested_str_weak(mdns), + /* K2 */ be_nested_str_weak(stop_basic_commissioning), + /* K3 */ be_nested_str_weak(root_w0), + /* K4 */ be_nested_str_weak(root_L), + /* K5 */ be_nested_str_weak(mdns_announce_op_discovery), + }), + be_str_weak(start_operational_discovery), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0xA40E0200, // 0001 IMPORT R3 K1 + 0x8C100102, // 0002 GETMET R4 R0 K2 + 0x7C100200, // 0003 CALL R4 1 + 0x4C100000, // 0004 LDNIL R4 + 0x90020604, // 0005 SETMBR R0 K3 R4 + 0x4C100000, // 0006 LDNIL R4 + 0x90020804, // 0007 SETMBR R0 K4 R4 + 0x8C100105, // 0008 GETMET R4 R0 K5 + 0x5C180200, // 0009 MOVE R6 R1 + 0x7C100400, // 000A CALL R4 2 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: load_param +********************************************************************/ +be_local_closure(Matter_Device_load_param, /* name */ + be_nested_proto( + 11, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[36]) { /* constants */ + /* K0 */ be_nested_str_weak(crypto), + /* K1 */ be_nested_str_weak(FILENAME), + /* K2 */ be_nested_str_weak(read), + /* K3 */ be_nested_str_weak(close), + /* K4 */ be_nested_str_weak(json), + /* K5 */ be_nested_str_weak(load), + /* K6 */ be_nested_str_weak(root_discriminator), + /* K7 */ be_nested_str_weak(find), + /* K8 */ be_nested_str_weak(distinguish), + /* K9 */ be_nested_str_weak(root_passcode), + /* K10 */ be_nested_str_weak(passcode), + /* K11 */ be_nested_str_weak(ipv4only), + /* K12 */ be_nested_str_weak(disable_bridge_mode), + /* K13 */ be_nested_str_weak(next_ep), + /* K14 */ be_nested_str_weak(nextep), + /* K15 */ be_nested_str_weak(plugins_config), + /* K16 */ be_nested_str_weak(config), + /* K17 */ be_nested_str_weak(tasmota), + /* K18 */ be_nested_str_weak(log), + /* K19 */ be_nested_str_weak(MTR_X3A_X20load_config_X20_X3D_X20), + /* K20 */ be_const_int(3), + /* K21 */ be_nested_str_weak(adjust_next_ep), + /* K22 */ be_nested_str_weak(check_config_ep), + /* K23 */ be_nested_str_weak(plugins_persist), + /* K24 */ be_nested_str_weak(plugins_config_remotes), + /* K25 */ be_nested_str_weak(remotes), + /* K26 */ be_nested_str_weak(MTR_X3A_X20load_remotes_X20_X3D_X20), + /* K27 */ be_nested_str_weak(io_error), + /* K28 */ be_nested_str_weak(MTR_X3A_X20Session_Store_X3A_X3Aload_X20Exception_X3A), + /* K29 */ be_nested_str_weak(_X7C), + /* K30 */ be_const_int(2), + /* K31 */ be_nested_str_weak(random), + /* K32 */ be_nested_str_weak(get), + /* K33 */ be_const_int(0), + /* K34 */ be_nested_str_weak(generate_random_passcode), + /* K35 */ be_nested_str_weak(save_param), + }), + be_str_weak(load_param), + &be_const_str_solidified, + ( &(const binstruction[129]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0xA802004F, // 0001 EXBLK 0 #0052 + 0x60080011, // 0002 GETGBL R2 G17 + 0x880C0101, // 0003 GETMBR R3 R0 K1 + 0x7C080200, // 0004 CALL R2 1 + 0x8C0C0502, // 0005 GETMET R3 R2 K2 + 0x7C0C0200, // 0006 CALL R3 1 + 0x8C100503, // 0007 GETMET R4 R2 K3 + 0x7C100200, // 0008 CALL R4 1 + 0xA4120800, // 0009 IMPORT R4 K4 + 0x8C140905, // 000A GETMET R5 R4 K5 + 0x5C1C0600, // 000B MOVE R7 R3 + 0x7C140400, // 000C CALL R5 2 + 0x8C180B07, // 000D GETMET R6 R5 K7 + 0x58200008, // 000E LDCONST R8 K8 + 0x88240106, // 000F GETMBR R9 R0 K6 + 0x7C180600, // 0010 CALL R6 3 + 0x90020C06, // 0011 SETMBR R0 K6 R6 + 0x8C180B07, // 0012 GETMET R6 R5 K7 + 0x5820000A, // 0013 LDCONST R8 K10 + 0x88240109, // 0014 GETMBR R9 R0 K9 + 0x7C180600, // 0015 CALL R6 3 + 0x90021206, // 0016 SETMBR R0 K9 R6 + 0x60180017, // 0017 GETGBL R6 G23 + 0x8C1C0B07, // 0018 GETMET R7 R5 K7 + 0x5824000B, // 0019 LDCONST R9 K11 + 0x50280000, // 001A LDBOOL R10 0 0 + 0x7C1C0600, // 001B CALL R7 3 + 0x7C180200, // 001C CALL R6 1 + 0x90021606, // 001D SETMBR R0 K11 R6 + 0x60180017, // 001E GETGBL R6 G23 + 0x8C1C0B07, // 001F GETMET R7 R5 K7 + 0x5824000C, // 0020 LDCONST R9 K12 + 0x50280000, // 0021 LDBOOL R10 0 0 + 0x7C1C0600, // 0022 CALL R7 3 + 0x7C180200, // 0023 CALL R6 1 + 0x90021806, // 0024 SETMBR R0 K12 R6 + 0x8C180B07, // 0025 GETMET R6 R5 K7 + 0x5820000E, // 0026 LDCONST R8 K14 + 0x8824010D, // 0027 GETMBR R9 R0 K13 + 0x7C180600, // 0028 CALL R6 3 + 0x90021A06, // 0029 SETMBR R0 K13 R6 + 0x8C180B07, // 002A GETMET R6 R5 K7 + 0x58200010, // 002B LDCONST R8 K16 + 0x7C180400, // 002C CALL R6 2 + 0x90021E06, // 002D SETMBR R0 K15 R6 + 0x8818010F, // 002E GETMBR R6 R0 K15 + 0x4C1C0000, // 002F LDNIL R7 + 0x20180C07, // 0030 NE R6 R6 R7 + 0x781A000D, // 0031 JMPF R6 #0040 + 0xB81A2200, // 0032 GETNGBL R6 K17 + 0x8C180D12, // 0033 GETMET R6 R6 K18 + 0x60200008, // 0034 GETGBL R8 G8 + 0x8824010F, // 0035 GETMBR R9 R0 K15 + 0x7C200200, // 0036 CALL R8 1 + 0x00222608, // 0037 ADD R8 K19 R8 + 0x58240014, // 0038 LDCONST R9 K20 + 0x7C180600, // 0039 CALL R6 3 + 0x8C180115, // 003A GETMET R6 R0 K21 + 0x7C180200, // 003B CALL R6 1 + 0x8C180116, // 003C GETMET R6 R0 K22 + 0x7C180200, // 003D CALL R6 1 + 0x50180200, // 003E LDBOOL R6 1 0 + 0x90022E06, // 003F SETMBR R0 K23 R6 + 0x8C180B07, // 0040 GETMET R6 R5 K7 + 0x58200019, // 0041 LDCONST R8 K25 + 0x60240013, // 0042 GETGBL R9 G19 + 0x7C240000, // 0043 CALL R9 0 + 0x7C180600, // 0044 CALL R6 3 + 0x90023006, // 0045 SETMBR R0 K24 R6 + 0x88180118, // 0046 GETMBR R6 R0 K24 + 0x781A0007, // 0047 JMPF R6 #0050 + 0xB81A2200, // 0048 GETNGBL R6 K17 + 0x8C180D12, // 0049 GETMET R6 R6 K18 + 0x60200008, // 004A GETGBL R8 G8 + 0x88240118, // 004B GETMBR R9 R0 K24 + 0x7C200200, // 004C CALL R8 1 + 0x00223408, // 004D ADD R8 K26 R8 + 0x58240014, // 004E LDCONST R9 K20 + 0x7C180600, // 004F CALL R6 3 + 0xA8040001, // 0050 EXBLK 1 1 + 0x70020012, // 0051 JMP #0065 + 0xAC080002, // 0052 CATCH R2 0 2 + 0x7002000F, // 0053 JMP #0064 + 0x2010051B, // 0054 NE R4 R2 K27 + 0x7812000C, // 0055 JMPF R4 #0063 + 0xB8122200, // 0056 GETNGBL R4 K17 + 0x8C100912, // 0057 GETMET R4 R4 K18 + 0x60180008, // 0058 GETGBL R6 G8 + 0x5C1C0400, // 0059 MOVE R7 R2 + 0x7C180200, // 005A CALL R6 1 + 0x001A3806, // 005B ADD R6 K28 R6 + 0x00180D1D, // 005C ADD R6 R6 K29 + 0x601C0008, // 005D GETGBL R7 G8 + 0x5C200600, // 005E MOVE R8 R3 + 0x7C1C0200, // 005F CALL R7 1 + 0x00180C07, // 0060 ADD R6 R6 R7 + 0x581C001E, // 0061 LDCONST R7 K30 + 0x7C100600, // 0062 CALL R4 3 + 0x70020000, // 0063 JMP #0065 + 0xB0080000, // 0064 RAISE 2 R0 R0 + 0x50080000, // 0065 LDBOOL R2 0 0 + 0x880C0106, // 0066 GETMBR R3 R0 K6 + 0x4C100000, // 0067 LDNIL R4 + 0x1C0C0604, // 0068 EQ R3 R3 R4 + 0x780E000A, // 0069 JMPF R3 #0075 + 0x8C0C031F, // 006A GETMET R3 R1 K31 + 0x5814001E, // 006B LDCONST R5 K30 + 0x7C0C0400, // 006C CALL R3 2 + 0x8C0C0720, // 006D GETMET R3 R3 K32 + 0x58140021, // 006E LDCONST R5 K33 + 0x5818001E, // 006F LDCONST R6 K30 + 0x7C0C0600, // 0070 CALL R3 3 + 0x54120FFE, // 0071 LDINT R4 4095 + 0x2C0C0604, // 0072 AND R3 R3 R4 + 0x90020C03, // 0073 SETMBR R0 K6 R3 + 0x50080200, // 0074 LDBOOL R2 1 0 + 0x880C0109, // 0075 GETMBR R3 R0 K9 + 0x4C100000, // 0076 LDNIL R4 + 0x1C0C0604, // 0077 EQ R3 R3 R4 + 0x780E0003, // 0078 JMPF R3 #007D + 0x8C0C0122, // 0079 GETMET R3 R0 K34 + 0x7C0C0200, // 007A CALL R3 1 + 0x90021203, // 007B SETMBR R0 K9 R3 + 0x50080200, // 007C LDBOOL R2 1 0 + 0x780A0001, // 007D JMPF R2 #0080 + 0x8C0C0123, // 007E GETMET R3 R0 K35 + 0x7C0C0200, // 007F CALL R3 1 + 0x80000000, // 0080 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: MtrUpdate +********************************************************************/ +be_local_closure(Matter_Device_MtrUpdate, /* name */ + be_nested_proto( + 18, /* nstack */ + 5, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[25]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(resp_cmnd_str), + /* K2 */ be_nested_str_weak(Invalid_X20JSON), + /* K3 */ be_nested_str_weak(find_key_i), + /* K4 */ be_nested_str_weak(Ep), + /* K5 */ be_nested_str_weak(Name), + /* K6 */ be_const_int(0), + /* K7 */ be_nested_str_weak(Invalid_X20_X27Ep_X27_X20attribute), + /* K8 */ be_nested_str_weak(find_plugin_by_endpoint), + /* K9 */ be_nested_str_weak(remove), + /* K10 */ be_nested_str_weak(find_plugin_by_friendly_name), + /* K11 */ be_nested_str_weak(Invalid_X20Device), + /* K12 */ be_nested_str_weak(VIRTUAL), + /* K13 */ be_nested_str_weak(Device_X20is_X20not_X20virtual), + /* K14 */ be_nested_str_weak(consolidate_update_commands), + /* K15 */ be_nested_str_weak(keys), + /* K16 */ be_nested_str_weak(find_list_i), + /* K17 */ be_nested_str_weak(Invalid_X20attribute_X20_X27_X25s_X27), + /* K18 */ be_nested_str_weak(stop_iteration), + /* K19 */ be_nested_str_weak(update_virtual), + /* K20 */ be_nested_str_weak(state_json), + /* K21 */ be_nested_str_weak(_X7B_X22_X25s_X22_X3A_X25s_X7D), + /* K22 */ be_nested_str_weak(resp_cmnd), + /* K23 */ be_nested_str_weak(resp_cmnd_done), + /* K24 */ be_nested_str_weak(Missing_X20_X27Device_X27_X20attribute), + }), + be_str_weak(MtrUpdate), + &be_const_str_solidified, + ( &(const binstruction[126]) { /* code */ + 0x4C140000, // 0000 LDNIL R5 + 0x1C140805, // 0001 EQ R5 R4 R5 + 0x78160004, // 0002 JMPF R5 #0008 + 0xB8160000, // 0003 GETNGBL R5 K0 + 0x8C140B01, // 0004 GETMET R5 R5 K1 + 0x581C0002, // 0005 LDCONST R7 K2 + 0x7C140400, // 0006 CALL R5 2 + 0x80040A00, // 0007 RET 1 R5 + 0xB8160000, // 0008 GETNGBL R5 K0 + 0x8C140B03, // 0009 GETMET R5 R5 K3 + 0x5C1C0800, // 000A MOVE R7 R4 + 0x58200004, // 000B LDCONST R8 K4 + 0x7C140600, // 000C CALL R5 3 + 0xB81A0000, // 000D GETNGBL R6 K0 + 0x8C180D03, // 000E GETMET R6 R6 K3 + 0x5C200800, // 000F MOVE R8 R4 + 0x58240005, // 0010 LDCONST R9 K5 + 0x7C180600, // 0011 CALL R6 3 + 0x74160000, // 0012 JMPT R5 #0014 + 0x781A0064, // 0013 JMPF R6 #0079 + 0x4C1C0000, // 0014 LDNIL R7 + 0x78160010, // 0015 JMPF R5 #0027 + 0x60200009, // 0016 GETGBL R8 G9 + 0x94240805, // 0017 GETIDX R9 R4 R5 + 0x7C200200, // 0018 CALL R8 1 + 0x18241106, // 0019 LE R9 R8 K6 + 0x78260004, // 001A JMPF R9 #0020 + 0xB8260000, // 001B GETNGBL R9 K0 + 0x8C241301, // 001C GETMET R9 R9 K1 + 0x582C0007, // 001D LDCONST R11 K7 + 0x7C240400, // 001E CALL R9 2 + 0x80041200, // 001F RET 1 R9 + 0x8C240108, // 0020 GETMET R9 R0 K8 + 0x5C2C1000, // 0021 MOVE R11 R8 + 0x7C240400, // 0022 CALL R9 2 + 0x5C1C1200, // 0023 MOVE R7 R9 + 0x8C240909, // 0024 GETMET R9 R4 K9 + 0x5C2C0A00, // 0025 MOVE R11 R5 + 0x7C240400, // 0026 CALL R9 2 + 0x781A0009, // 0027 JMPF R6 #0032 + 0x4C200000, // 0028 LDNIL R8 + 0x1C200E08, // 0029 EQ R8 R7 R8 + 0x78220003, // 002A JMPF R8 #002F + 0x8C20010A, // 002B GETMET R8 R0 K10 + 0x94280806, // 002C GETIDX R10 R4 R6 + 0x7C200400, // 002D CALL R8 2 + 0x5C1C1000, // 002E MOVE R7 R8 + 0x8C200909, // 002F GETMET R8 R4 K9 + 0x5C280C00, // 0030 MOVE R10 R6 + 0x7C200400, // 0031 CALL R8 2 + 0x4C200000, // 0032 LDNIL R8 + 0x1C200E08, // 0033 EQ R8 R7 R8 + 0x78220004, // 0034 JMPF R8 #003A + 0xB8220000, // 0035 GETNGBL R8 K0 + 0x8C201101, // 0036 GETMET R8 R8 K1 + 0x5828000B, // 0037 LDCONST R10 K11 + 0x7C200400, // 0038 CALL R8 2 + 0x80041000, // 0039 RET 1 R8 + 0x88200F0C, // 003A GETMBR R8 R7 K12 + 0x74220004, // 003B JMPT R8 #0041 + 0xB8220000, // 003C GETNGBL R8 K0 + 0x8C201101, // 003D GETMET R8 R8 K1 + 0x5828000D, // 003E LDCONST R10 K13 + 0x7C200400, // 003F CALL R8 2 + 0x80041000, // 0040 RET 1 R8 + 0x8C200F0E, // 0041 GETMET R8 R7 K14 + 0x7C200200, // 0042 CALL R8 1 + 0x60240013, // 0043 GETGBL R9 G19 + 0x7C240000, // 0044 CALL R9 0 + 0x60280010, // 0045 GETGBL R10 G16 + 0x8C2C090F, // 0046 GETMET R11 R4 K15 + 0x7C2C0200, // 0047 CALL R11 1 + 0x7C280200, // 0048 CALL R10 1 + 0xA8020016, // 0049 EXBLK 0 #0061 + 0x5C2C1400, // 004A MOVE R11 R10 + 0x7C2C0000, // 004B CALL R11 0 + 0xB8320000, // 004C GETNGBL R12 K0 + 0x8C301910, // 004D GETMET R12 R12 K16 + 0x5C381000, // 004E MOVE R14 R8 + 0x5C3C1600, // 004F MOVE R15 R11 + 0x7C300600, // 0050 CALL R12 3 + 0x4C340000, // 0051 LDNIL R13 + 0x1C34180D, // 0052 EQ R13 R12 R13 + 0x78360008, // 0053 JMPF R13 #005D + 0xB8360000, // 0054 GETNGBL R13 K0 + 0x8C341B01, // 0055 GETMET R13 R13 K1 + 0x603C0018, // 0056 GETGBL R15 G24 + 0x58400011, // 0057 LDCONST R16 K17 + 0x5C441600, // 0058 MOVE R17 R11 + 0x7C3C0400, // 0059 CALL R15 2 + 0x7C340400, // 005A CALL R13 2 + 0xA8040001, // 005B EXBLK 1 1 + 0x80001A00, // 005C RET 0 + 0x9434100C, // 005D GETIDX R13 R8 R12 + 0x9438080B, // 005E GETIDX R14 R4 R11 + 0x98241A0E, // 005F SETIDX R9 R13 R14 + 0x7001FFE8, // 0060 JMP #004A + 0x58280012, // 0061 LDCONST R10 K18 + 0xAC280200, // 0062 CATCH R10 1 0 + 0xB0080000, // 0063 RAISE 2 R0 R0 + 0x8C280F13, // 0064 GETMET R10 R7 K19 + 0x5C301200, // 0065 MOVE R12 R9 + 0x7C280400, // 0066 CALL R10 2 + 0x8C280F14, // 0067 GETMET R10 R7 K20 + 0x7C280200, // 0068 CALL R10 1 + 0x782A000A, // 0069 JMPF R10 #0075 + 0x602C0018, // 006A GETGBL R11 G24 + 0x58300015, // 006B LDCONST R12 K21 + 0x5C340200, // 006C MOVE R13 R1 + 0x5C381400, // 006D MOVE R14 R10 + 0x7C2C0600, // 006E CALL R11 3 + 0xB8320000, // 006F GETNGBL R12 K0 + 0x8C301916, // 0070 GETMET R12 R12 K22 + 0x5C381600, // 0071 MOVE R14 R11 + 0x7C300400, // 0072 CALL R12 2 + 0x80041800, // 0073 RET 1 R12 + 0x70020003, // 0074 JMP #0079 + 0xB82E0000, // 0075 GETNGBL R11 K0 + 0x8C2C1717, // 0076 GETMET R11 R11 K23 + 0x7C2C0200, // 0077 CALL R11 1 + 0x80041600, // 0078 RET 1 R11 + 0xB81E0000, // 0079 GETNGBL R7 K0 + 0x8C1C0F01, // 007A GETMET R7 R7 K1 + 0x58240018, // 007B LDCONST R9 K24 + 0x7C1C0400, // 007C CALL R7 2 + 0x80000000, // 007D RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start_basic_commissioning +********************************************************************/ +be_local_closure(Matter_Device_start_basic_commissioning, /* name */ + be_nested_proto( + 13, /* nstack */ + 8, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 2]) { + be_nested_proto( + 4, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(mdns_announce_PASE), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(remove_rule), + /* K3 */ be_nested_str_weak(Wifi_X23Connected), + }), + be_str_weak(_anonymous_), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x7C000200, // 0002 CALL R0 1 + 0xB8020200, // 0003 GETNGBL R0 K1 + 0x8C000102, // 0004 GETMET R0 R0 K2 + 0x58080003, // 0005 LDCONST R2 K3 + 0x580C0000, // 0006 LDCONST R3 K0 + 0x7C000600, // 0007 CALL R0 3 + 0x80000000, // 0008 RET 0 + }) + ), + be_nested_proto( + 4, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(mdns_announce_PASE), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(remove_rule), + /* K3 */ be_nested_str_weak(Eth_X23Connected), + }), + be_str_weak(_anonymous_), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x7C000200, // 0002 CALL R0 1 + 0xB8020200, // 0003 GETNGBL R0 K1 + 0x8C000102, // 0004 GETMET R0 R0 K2 + 0x58080003, // 0005 LDCONST R2 K3 + 0x580C0000, // 0006 LDCONST R3 K0 + 0x7C000600, // 0007 CALL R0 3 + 0x80000000, // 0008 RET 0 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[16]) { /* constants */ + /* K0 */ be_nested_str_weak(commissioning_open), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(millis), + /* K3 */ be_nested_str_weak(commissioning_iterations), + /* K4 */ be_nested_str_weak(commissioning_discriminator), + /* K5 */ be_nested_str_weak(commissioning_salt), + /* K6 */ be_nested_str_weak(commissioning_w0), + /* K7 */ be_nested_str_weak(commissioning_L), + /* K8 */ be_nested_str_weak(commissioning_admin_fabric), + /* K9 */ be_nested_str_weak(wifi), + /* K10 */ be_nested_str_weak(up), + /* K11 */ be_nested_str_weak(eth), + /* K12 */ be_nested_str_weak(mdns_announce_PASE), + /* K13 */ be_nested_str_weak(add_rule), + /* K14 */ be_nested_str_weak(Wifi_X23Connected), + /* K15 */ be_nested_str_weak(Eth_X23Connected), + }), + be_str_weak(start_basic_commissioning), + &be_const_str_solidified, + ( &(const binstruction[40]) { /* code */ + 0xB8220200, // 0000 GETNGBL R8 K1 + 0x8C201102, // 0001 GETMET R8 R8 K2 + 0x7C200200, // 0002 CALL R8 1 + 0x542603E7, // 0003 LDINT R9 1000 + 0x08240209, // 0004 MUL R9 R1 R9 + 0x00201009, // 0005 ADD R8 R8 R9 + 0x90020008, // 0006 SETMBR R0 K0 R8 + 0x90020602, // 0007 SETMBR R0 K3 R2 + 0x90020803, // 0008 SETMBR R0 K4 R3 + 0x90020A04, // 0009 SETMBR R0 K5 R4 + 0x90020C05, // 000A SETMBR R0 K6 R5 + 0x90020E06, // 000B SETMBR R0 K7 R6 + 0x90021007, // 000C SETMBR R0 K8 R7 + 0xB8220200, // 000D GETNGBL R8 K1 + 0x8C201109, // 000E GETMET R8 R8 K9 + 0x7C200200, // 000F CALL R8 1 + 0x9420110A, // 0010 GETIDX R8 R8 K10 + 0x74220004, // 0011 JMPT R8 #0017 + 0xB8220200, // 0012 GETNGBL R8 K1 + 0x8C20110B, // 0013 GETMET R8 R8 K11 + 0x7C200200, // 0014 CALL R8 1 + 0x9420110A, // 0015 GETIDX R8 R8 K10 + 0x78220002, // 0016 JMPF R8 #001A + 0x8C20010C, // 0017 GETMET R8 R0 K12 + 0x7C200200, // 0018 CALL R8 1 + 0x7002000B, // 0019 JMP #0026 + 0xB8220200, // 001A GETNGBL R8 K1 + 0x8C20110D, // 001B GETMET R8 R8 K13 + 0x5828000E, // 001C LDCONST R10 K14 + 0x842C0000, // 001D CLOSURE R11 P0 + 0x5830000C, // 001E LDCONST R12 K12 + 0x7C200800, // 001F CALL R8 4 + 0xB8220200, // 0020 GETNGBL R8 K1 + 0x8C20110D, // 0021 GETMET R8 R8 K13 + 0x5828000F, // 0022 LDCONST R10 K15 + 0x842C0001, // 0023 CLOSURE R11 P1 + 0x5830000C, // 0024 LDCONST R12 K12 + 0x7C200800, // 0025 CALL R8 4 + 0xA0000000, // 0026 CLOSE R0 + 0x80000000, // 0027 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: received_ack +********************************************************************/ +be_local_closure(Matter_Device_received_ack, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(udp_server), + /* K1 */ be_nested_str_weak(received_ack), + }), + be_str_weak(received_ack), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x80040400, // 0004 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: mdns_remove_op_discovery +********************************************************************/ +be_local_closure(Matter_Device_mdns_remove_op_discovery, /* name */ + be_nested_proto( + 12, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[23]) { /* constants */ + /* K0 */ be_nested_str_weak(mdns), + /* K1 */ be_nested_str_weak(get_device_id), + /* K2 */ be_nested_str_weak(copy), + /* K3 */ be_nested_str_weak(reverse), + /* K4 */ be_nested_str_weak(get_fabric_compressed), + /* K5 */ be_nested_str_weak(tohex), + /* K6 */ be_nested_str_weak(_X2D), + /* K7 */ be_nested_str_weak(tasmota), + /* K8 */ be_nested_str_weak(eth), + /* K9 */ be_nested_str_weak(find), + /* K10 */ be_nested_str_weak(up), + /* K11 */ be_nested_str_weak(log), + /* K12 */ be_nested_str_weak(MTR_X3A_X20remove_X20mDNS_X20on_X20_X25s_X20_X27_X25s_X27), + /* K13 */ be_const_int(3), + /* K14 */ be_nested_str_weak(remove_service), + /* K15 */ be_nested_str_weak(_matter), + /* K16 */ be_nested_str_weak(_tcp), + /* K17 */ be_nested_str_weak(hostname_eth), + /* K18 */ be_nested_str_weak(wifi), + /* K19 */ be_nested_str_weak(hostname_wifi), + /* K20 */ be_nested_str_weak(MTR_X3A_X20Exception), + /* K21 */ be_nested_str_weak(_X7C), + /* K22 */ be_const_int(2), + }), + be_str_weak(mdns_remove_op_discovery), + &be_const_str_solidified, + ( &(const binstruction[80]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0xA802003B, // 0001 EXBLK 0 #003E + 0x8C0C0301, // 0002 GETMET R3 R1 K1 + 0x7C0C0200, // 0003 CALL R3 1 + 0x8C0C0702, // 0004 GETMET R3 R3 K2 + 0x7C0C0200, // 0005 CALL R3 1 + 0x8C0C0703, // 0006 GETMET R3 R3 K3 + 0x7C0C0200, // 0007 CALL R3 1 + 0x8C100304, // 0008 GETMET R4 R1 K4 + 0x7C100200, // 0009 CALL R4 1 + 0x8C140905, // 000A GETMET R5 R4 K5 + 0x7C140200, // 000B CALL R5 1 + 0x00140B06, // 000C ADD R5 R5 K6 + 0x8C180705, // 000D GETMET R6 R3 K5 + 0x7C180200, // 000E CALL R6 1 + 0x00140A06, // 000F ADD R5 R5 R6 + 0xB81A0E00, // 0010 GETNGBL R6 K7 + 0x8C180D08, // 0011 GETMET R6 R6 K8 + 0x7C180200, // 0012 CALL R6 1 + 0x8C180D09, // 0013 GETMET R6 R6 K9 + 0x5820000A, // 0014 LDCONST R8 K10 + 0x7C180400, // 0015 CALL R6 2 + 0x781A000E, // 0016 JMPF R6 #0026 + 0xB81A0E00, // 0017 GETNGBL R6 K7 + 0x8C180D0B, // 0018 GETMET R6 R6 K11 + 0x60200018, // 0019 GETGBL R8 G24 + 0x5824000C, // 001A LDCONST R9 K12 + 0x58280008, // 001B LDCONST R10 K8 + 0x5C2C0A00, // 001C MOVE R11 R5 + 0x7C200600, // 001D CALL R8 3 + 0x5824000D, // 001E LDCONST R9 K13 + 0x7C180600, // 001F CALL R6 3 + 0x8C18050E, // 0020 GETMET R6 R2 K14 + 0x5820000F, // 0021 LDCONST R8 K15 + 0x58240010, // 0022 LDCONST R9 K16 + 0x5C280A00, // 0023 MOVE R10 R5 + 0x882C0111, // 0024 GETMBR R11 R0 K17 + 0x7C180A00, // 0025 CALL R6 5 + 0xB81A0E00, // 0026 GETNGBL R6 K7 + 0x8C180D12, // 0027 GETMET R6 R6 K18 + 0x7C180200, // 0028 CALL R6 1 + 0x8C180D09, // 0029 GETMET R6 R6 K9 + 0x5820000A, // 002A LDCONST R8 K10 + 0x7C180400, // 002B CALL R6 2 + 0x781A000E, // 002C JMPF R6 #003C + 0xB81A0E00, // 002D GETNGBL R6 K7 + 0x8C180D0B, // 002E GETMET R6 R6 K11 + 0x60200018, // 002F GETGBL R8 G24 + 0x5824000C, // 0030 LDCONST R9 K12 + 0x58280012, // 0031 LDCONST R10 K18 + 0x5C2C0A00, // 0032 MOVE R11 R5 + 0x7C200600, // 0033 CALL R8 3 + 0x5824000D, // 0034 LDCONST R9 K13 + 0x7C180600, // 0035 CALL R6 3 + 0x8C18050E, // 0036 GETMET R6 R2 K14 + 0x5820000F, // 0037 LDCONST R8 K15 + 0x58240010, // 0038 LDCONST R9 K16 + 0x5C280A00, // 0039 MOVE R10 R5 + 0x882C0113, // 003A GETMBR R11 R0 K19 + 0x7C180A00, // 003B CALL R6 5 + 0xA8040001, // 003C EXBLK 1 1 + 0x70020010, // 003D JMP #004F + 0xAC0C0002, // 003E CATCH R3 0 2 + 0x7002000D, // 003F JMP #004E + 0xB8160E00, // 0040 GETNGBL R5 K7 + 0x8C140B0B, // 0041 GETMET R5 R5 K11 + 0x601C0008, // 0042 GETGBL R7 G8 + 0x5C200600, // 0043 MOVE R8 R3 + 0x7C1C0200, // 0044 CALL R7 1 + 0x001E2807, // 0045 ADD R7 K20 R7 + 0x001C0F15, // 0046 ADD R7 R7 K21 + 0x60200008, // 0047 GETGBL R8 G8 + 0x5C240800, // 0048 MOVE R9 R4 + 0x7C200200, // 0049 CALL R8 1 + 0x001C0E08, // 004A ADD R7 R7 R8 + 0x58200016, // 004B LDCONST R8 K22 + 0x7C140600, // 004C CALL R5 3 + 0x70020000, // 004D JMP #004F + 0xB0080000, // 004E RAISE 2 R0 R0 + 0x80000000, // 004F RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: read_sensors_scheduler +********************************************************************/ +be_local_closure(Matter_Device_read_sensors_scheduler, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str_weak(probe_sensor_time), + /* K1 */ be_nested_str_weak(probe_sensor_timestamp), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(tasmota), + /* K4 */ be_nested_str_weak(time_reached), + /* K5 */ be_nested_str_weak(_trigger_read_sensors), + /* K6 */ be_nested_str_weak(millis), + }), + be_str_weak(read_sensors_scheduler), + &be_const_str_solidified, + ( &(const binstruction[21]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x1C040202, // 0002 EQ R1 R1 R2 + 0x78060000, // 0003 JMPF R1 #0005 + 0x80000200, // 0004 RET 0 + 0x88040101, // 0005 GETMBR R1 R0 K1 + 0x1C040302, // 0006 EQ R1 R1 K2 + 0x74060004, // 0007 JMPT R1 #000D + 0xB8060600, // 0008 GETNGBL R1 K3 + 0x8C040304, // 0009 GETMET R1 R1 K4 + 0x880C0101, // 000A GETMBR R3 R0 K1 + 0x7C040400, // 000B CALL R1 2 + 0x78060006, // 000C JMPF R1 #0014 + 0x8C040105, // 000D GETMET R1 R0 K5 + 0x7C040200, // 000E CALL R1 1 + 0xB8060600, // 000F GETNGBL R1 K3 + 0x8C040306, // 0010 GETMET R1 R1 K6 + 0x880C0100, // 0011 GETMBR R3 R0 K0 + 0x7C040400, // 0012 CALL R1 2 + 0x90020201, // 0013 SETMBR R0 K1 R1 + 0x80000000, // 0014 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: start_operational_discovery_deferred +********************************************************************/ +be_local_closure(Matter_Device_start_operational_discovery_deferred, /* name */ be_nested_proto( 6, /* nstack */ 2, /* argc */ @@ -1878,7 +5149,7 @@ be_local_closure(Matter_Device_start_commissioning_complete_deferred, /* name NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(start_commissioning_complete), + /* K0 */ be_nested_str_weak(start_operational_discovery), }), be_str_weak(_X3Clambda_X3E), &be_const_str_solidified, @@ -1897,7 +5168,7 @@ be_local_closure(Matter_Device_start_commissioning_complete_deferred, /* name /* K1 */ be_nested_str_weak(set_timer), /* K2 */ be_const_int(0), }), - be_str_weak(start_commissioning_complete_deferred), + be_str_weak(start_operational_discovery_deferred), &be_const_str_solidified, ( &(const binstruction[ 7]) { /* code */ 0xB80A0000, // 0000 GETNGBL R2 K0 @@ -1913,6 +5184,114 @@ be_local_closure(Matter_Device_start_commissioning_complete_deferred, /* name /*******************************************************************/ +/******************************************************************** +** Solidified function: generate_random_passcode +********************************************************************/ +be_local_closure(Matter_Device_generate_random_passcode, /* name */ + be_nested_proto( + 7, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_str_weak(crypto), + /* K1 */ be_nested_str_weak(random), + /* K2 */ be_nested_str_weak(get), + /* K3 */ be_const_int(0), + /* K4 */ be_const_int(134217727), + /* K5 */ be_const_int(99999998), + /* K6 */ be_nested_str_weak(PASSCODE_INVALID), + /* K7 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(generate_random_passcode), + &be_const_str_solidified, + ( &(const binstruction[35]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x500C0200, // 0002 LDBOOL R3 1 0 + 0x780E001D, // 0003 JMPF R3 #0022 + 0x8C0C0301, // 0004 GETMET R3 R1 K1 + 0x54160003, // 0005 LDINT R5 4 + 0x7C0C0400, // 0006 CALL R3 2 + 0x8C0C0702, // 0007 GETMET R3 R3 K2 + 0x58140003, // 0008 LDCONST R5 K3 + 0x541A0003, // 0009 LDINT R6 4 + 0x7C0C0600, // 000A CALL R3 3 + 0x2C0C0704, // 000B AND R3 R3 K4 + 0x5C080600, // 000C MOVE R2 R3 + 0x240C0505, // 000D GT R3 R2 K5 + 0x780E0000, // 000E JMPF R3 #0010 + 0x7001FFF1, // 000F JMP #0002 + 0x600C0010, // 0010 GETGBL R3 G16 + 0x88100106, // 0011 GETMBR R4 R0 K6 + 0x7C0C0200, // 0012 CALL R3 1 + 0xA8020005, // 0013 EXBLK 0 #001A + 0x5C100600, // 0014 MOVE R4 R3 + 0x7C100000, // 0015 CALL R4 0 + 0x1C140404, // 0016 EQ R5 R2 R4 + 0x78160000, // 0017 JMPF R5 #0019 + 0x4C080000, // 0018 LDNIL R2 + 0x7001FFF9, // 0019 JMP #0014 + 0x580C0007, // 001A LDCONST R3 K7 + 0xAC0C0200, // 001B CATCH R3 1 0 + 0xB0080000, // 001C RAISE 2 R0 R0 + 0x4C0C0000, // 001D LDNIL R3 + 0x200C0403, // 001E NE R3 R2 R3 + 0x780E0000, // 001F JMPF R3 #0021 + 0x80040400, // 0020 RET 1 R2 + 0x7001FFDF, // 0021 JMP #0002 + 0x80000000, // 0022 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: MtrJoin +********************************************************************/ +be_local_closure(Matter_Device_MtrJoin, /* name */ + be_nested_proto( + 8, /* nstack */ + 5, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(start_root_basic_commissioning), + /* K1 */ be_nested_str_weak(stop_basic_commissioning), + /* K2 */ be_nested_str_weak(tasmota), + /* K3 */ be_nested_str_weak(resp_cmnd_done), + }), + be_str_weak(MtrJoin), + &be_const_str_solidified, + ( &(const binstruction[13]) { /* code */ + 0x60140009, // 0000 GETGBL R5 G9 + 0x5C180600, // 0001 MOVE R6 R3 + 0x7C140200, // 0002 CALL R5 1 + 0x78160002, // 0003 JMPF R5 #0007 + 0x8C180100, // 0004 GETMET R6 R0 K0 + 0x7C180200, // 0005 CALL R6 1 + 0x70020001, // 0006 JMP #0009 + 0x8C180101, // 0007 GETMET R6 R0 K1 + 0x7C180200, // 0008 CALL R6 1 + 0xB81A0400, // 0009 GETNGBL R6 K2 + 0x8C180D03, // 000A GETMET R6 R6 K3 + 0x7C180200, // 000B CALL R6 1 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: save_param ********************************************************************/ @@ -2050,9 +5429,9 @@ be_local_closure(Matter_Device_save_param, /* name */ /******************************************************************** -** Solidified function: mdns_announce_op_discovery_all_fabrics +** Solidified function: mdns_remove_op_discovery_all_fabrics ********************************************************************/ -be_local_closure(Matter_Device_mdns_announce_op_discovery_all_fabrics, /* name */ +be_local_closure(Matter_Device_mdns_remove_op_discovery_all_fabrics, /* name */ be_nested_proto( 6, /* nstack */ 1, /* argc */ @@ -2067,10 +5446,10 @@ be_local_closure(Matter_Device_mdns_announce_op_discovery_all_fabrics, /* name /* K1 */ be_nested_str_weak(active_fabrics), /* K2 */ be_nested_str_weak(get_device_id), /* K3 */ be_nested_str_weak(get_fabric_id), - /* K4 */ be_nested_str_weak(mdns_announce_op_discovery), + /* K4 */ be_nested_str_weak(mdns_remove_op_discovery), /* K5 */ be_nested_str_weak(stop_iteration), }), - be_str_weak(mdns_announce_op_discovery_all_fabrics), + be_str_weak(mdns_remove_op_discovery_all_fabrics), &be_const_str_solidified, ( &(const binstruction[22]) { /* code */ 0x60040010, // 0000 GETGBL R1 G16 @@ -2101,56 +5480,6 @@ be_local_closure(Matter_Device_mdns_announce_op_discovery_all_fabrics, /* name /*******************************************************************/ -/******************************************************************** -** Solidified function: adjust_next_ep -********************************************************************/ -be_local_closure(Matter_Device_adjust_next_ep, /* name */ - be_nested_proto( - 5, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(plugins_config), - /* K1 */ be_nested_str_weak(keys), - /* K2 */ be_nested_str_weak(next_ep), - /* K3 */ be_const_int(1), - /* K4 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(adjust_next_ep), - &be_const_str_solidified, - ( &(const binstruction[21]) { /* code */ - 0x60040010, // 0000 GETGBL R1 G16 - 0x88080100, // 0001 GETMBR R2 R0 K0 - 0x8C080501, // 0002 GETMET R2 R2 K1 - 0x7C080200, // 0003 CALL R2 1 - 0x7C040200, // 0004 CALL R1 1 - 0xA802000A, // 0005 EXBLK 0 #0011 - 0x5C080200, // 0006 MOVE R2 R1 - 0x7C080000, // 0007 CALL R2 0 - 0x600C0009, // 0008 GETGBL R3 G9 - 0x5C100400, // 0009 MOVE R4 R2 - 0x7C0C0200, // 000A CALL R3 1 - 0x88100102, // 000B GETMBR R4 R0 K2 - 0x28100604, // 000C GE R4 R3 R4 - 0x78120001, // 000D JMPF R4 #0010 - 0x00100703, // 000E ADD R4 R3 K3 - 0x90020404, // 000F SETMBR R0 K2 R4 - 0x7001FFF4, // 0010 JMP #0006 - 0x58040004, // 0011 LDCONST R1 K4 - 0xAC040200, // 0012 CATCH R1 1 0 - 0xB0080000, // 0013 RAISE 2 R0 R0 - 0x80000000, // 0014 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: init ********************************************************************/ @@ -2392,724 +5721,131 @@ be_local_closure(Matter_Device_init, /* name */ /******************************************************************** -** Solidified function: _instantiate_plugins_from_config +** Solidified function: start_mdns_announce_hostnames ********************************************************************/ -be_local_closure(Matter_Device__instantiate_plugins_from_config, /* name */ +be_local_closure(Matter_Device_start_mdns_announce_hostnames, /* name */ be_nested_proto( - 18, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[31]) { /* constants */ - /* K0 */ be_nested_str_weak(k2l_num), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(log), - /* K3 */ be_nested_str_weak(MTR_X3A_X20Configuring_X20endpoints), - /* K4 */ be_const_int(2), - /* K5 */ be_nested_str_weak(plugins), - /* K6 */ be_nested_str_weak(push), - /* K7 */ be_nested_str_weak(matter), - /* K8 */ be_nested_str_weak(Plugin_Root), - /* K9 */ be_const_int(0), - /* K10 */ be_nested_str_weak(MTR_X3A_X20_X20_X20endpoint_X20_X3D_X20_X255i_X20type_X3A_X25s_X25s), - /* K11 */ be_nested_str_weak(root), - /* K12 */ be_nested_str_weak(), - /* K13 */ be_nested_str_weak(Plugin_Aggregator), - /* K14 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), - /* K15 */ be_nested_str_weak(find), - /* K16 */ be_nested_str_weak(type), - /* K17 */ be_nested_str_weak(MTR_X3A_X20no_X20class_X20name_X2C_X20skipping), - /* K18 */ be_const_int(3), - /* K19 */ be_nested_str_weak(MTR_X3A_X20only_X20one_X20root_X20node_X20allowed), - /* K20 */ be_nested_str_weak(plugins_classes), - /* K21 */ be_nested_str_weak(MTR_X3A_X20unknown_X20class_X20name_X20_X27), - /* K22 */ be_nested_str_weak(_X27_X20skipping), - /* K23 */ be_nested_str_weak(conf_to_log), - /* K24 */ be_nested_str_weak(MTR_X3A_X20Exception), - /* K25 */ be_nested_str_weak(_X7C), - /* K26 */ be_nested_str_weak(stop_iteration), - /* K27 */ be_nested_str_weak(aggregator), - /* K28 */ be_nested_str_weak(publish_result), - /* K29 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Initialized_X22_X3A1_X7D_X7D), - /* K30 */ be_nested_str_weak(Matter), - }), - be_str_weak(_instantiate_plugins_from_config), - &be_const_str_solidified, - ( &(const binstruction[154]) { /* code */ - 0x8C080100, // 0000 GETMET R2 R0 K0 - 0x5C100200, // 0001 MOVE R4 R1 - 0x7C080400, // 0002 CALL R2 2 - 0xB80E0200, // 0003 GETNGBL R3 K1 - 0x8C0C0702, // 0004 GETMET R3 R3 K2 - 0x58140003, // 0005 LDCONST R5 K3 - 0x58180004, // 0006 LDCONST R6 K4 - 0x7C0C0600, // 0007 CALL R3 3 - 0x880C0105, // 0008 GETMBR R3 R0 K5 - 0x8C0C0706, // 0009 GETMET R3 R3 K6 - 0xB8160E00, // 000A GETNGBL R5 K7 - 0x8C140B08, // 000B GETMET R5 R5 K8 - 0x5C1C0000, // 000C MOVE R7 R0 - 0x58200009, // 000D LDCONST R8 K9 - 0x60240013, // 000E GETGBL R9 G19 - 0x7C240000, // 000F CALL R9 0 - 0x7C140800, // 0010 CALL R5 4 - 0x7C0C0400, // 0011 CALL R3 2 - 0xB80E0200, // 0012 GETNGBL R3 K1 - 0x8C0C0702, // 0013 GETMET R3 R3 K2 - 0x60140018, // 0014 GETGBL R5 G24 - 0x5818000A, // 0015 LDCONST R6 K10 - 0x581C0009, // 0016 LDCONST R7 K9 - 0x5820000B, // 0017 LDCONST R8 K11 - 0x5824000C, // 0018 LDCONST R9 K12 - 0x7C140800, // 0019 CALL R5 4 - 0x58180004, // 001A LDCONST R6 K4 - 0x7C0C0600, // 001B CALL R3 3 - 0x880C0105, // 001C GETMBR R3 R0 K5 - 0x8C0C0706, // 001D GETMET R3 R3 K6 - 0xB8160E00, // 001E GETNGBL R5 K7 - 0x8C140B0D, // 001F GETMET R5 R5 K13 - 0x5C1C0000, // 0020 MOVE R7 R0 - 0xB8220E00, // 0021 GETNGBL R8 K7 - 0x8820110E, // 0022 GETMBR R8 R8 K14 - 0x60240013, // 0023 GETGBL R9 G19 - 0x7C240000, // 0024 CALL R9 0 - 0x7C140800, // 0025 CALL R5 4 - 0x7C0C0400, // 0026 CALL R3 2 - 0x600C0010, // 0027 GETGBL R3 G16 - 0x5C100400, // 0028 MOVE R4 R2 - 0x7C0C0200, // 0029 CALL R3 1 - 0xA802005A, // 002A EXBLK 0 #0086 - 0x5C100600, // 002B MOVE R4 R3 - 0x7C100000, // 002C CALL R4 0 - 0x1C140909, // 002D EQ R5 R4 K9 - 0x78160000, // 002E JMPF R5 #0030 - 0x7001FFFA, // 002F JMP #002B - 0xA8020042, // 0030 EXBLK 0 #0074 - 0x60140008, // 0031 GETGBL R5 G8 - 0x5C180800, // 0032 MOVE R6 R4 - 0x7C140200, // 0033 CALL R5 1 - 0x94140205, // 0034 GETIDX R5 R1 R5 - 0x8C180B0F, // 0035 GETMET R6 R5 K15 - 0x58200010, // 0036 LDCONST R8 K16 - 0x7C180400, // 0037 CALL R6 2 - 0x4C1C0000, // 0038 LDNIL R7 - 0x1C1C0C07, // 0039 EQ R7 R6 R7 - 0x781E0006, // 003A JMPF R7 #0042 - 0xB81E0200, // 003B GETNGBL R7 K1 - 0x8C1C0F02, // 003C GETMET R7 R7 K2 - 0x58240011, // 003D LDCONST R9 K17 - 0x58280012, // 003E LDCONST R10 K18 - 0x7C1C0600, // 003F CALL R7 3 - 0xA8040001, // 0040 EXBLK 1 1 - 0x7001FFE8, // 0041 JMP #002B - 0x1C1C0D0B, // 0042 EQ R7 R6 K11 - 0x781E0006, // 0043 JMPF R7 #004B - 0xB81E0200, // 0044 GETNGBL R7 K1 - 0x8C1C0F02, // 0045 GETMET R7 R7 K2 - 0x58240013, // 0046 LDCONST R9 K19 - 0x58280012, // 0047 LDCONST R10 K18 - 0x7C1C0600, // 0048 CALL R7 3 - 0xA8040001, // 0049 EXBLK 1 1 - 0x7001FFDF, // 004A JMP #002B - 0x881C0114, // 004B GETMBR R7 R0 K20 - 0x8C1C0F0F, // 004C GETMET R7 R7 K15 - 0x5C240C00, // 004D MOVE R9 R6 - 0x7C1C0400, // 004E CALL R7 2 - 0x4C200000, // 004F LDNIL R8 - 0x1C200E08, // 0050 EQ R8 R7 R8 - 0x7822000A, // 0051 JMPF R8 #005D - 0xB8220200, // 0052 GETNGBL R8 K1 - 0x8C201102, // 0053 GETMET R8 R8 K2 - 0x60280008, // 0054 GETGBL R10 G8 - 0x5C2C0C00, // 0055 MOVE R11 R6 - 0x7C280200, // 0056 CALL R10 1 - 0x002A2A0A, // 0057 ADD R10 K21 R10 - 0x00281516, // 0058 ADD R10 R10 K22 - 0x582C0004, // 0059 LDCONST R11 K4 - 0x7C200600, // 005A CALL R8 3 - 0xA8040001, // 005B EXBLK 1 1 - 0x7001FFCD, // 005C JMP #002B - 0x5C200E00, // 005D MOVE R8 R7 - 0x5C240000, // 005E MOVE R9 R0 - 0x5C280800, // 005F MOVE R10 R4 - 0x5C2C0A00, // 0060 MOVE R11 R5 - 0x7C200600, // 0061 CALL R8 3 - 0x88240105, // 0062 GETMBR R9 R0 K5 - 0x8C241306, // 0063 GETMET R9 R9 K6 - 0x5C2C1000, // 0064 MOVE R11 R8 - 0x7C240400, // 0065 CALL R9 2 - 0xB8260200, // 0066 GETNGBL R9 K1 - 0x8C241302, // 0067 GETMET R9 R9 K2 - 0x602C0018, // 0068 GETGBL R11 G24 - 0x5830000A, // 0069 LDCONST R12 K10 - 0x5C340800, // 006A MOVE R13 R4 - 0x5C380C00, // 006B MOVE R14 R6 - 0x8C3C0117, // 006C GETMET R15 R0 K23 - 0x5C440A00, // 006D MOVE R17 R5 - 0x7C3C0400, // 006E CALL R15 2 - 0x7C2C0800, // 006F CALL R11 4 - 0x58300004, // 0070 LDCONST R12 K4 - 0x7C240600, // 0071 CALL R9 3 - 0xA8040001, // 0072 EXBLK 1 1 - 0x70020010, // 0073 JMP #0085 - 0xAC140002, // 0074 CATCH R5 0 2 - 0x7002000D, // 0075 JMP #0084 - 0xB81E0200, // 0076 GETNGBL R7 K1 - 0x8C1C0F02, // 0077 GETMET R7 R7 K2 - 0x60240008, // 0078 GETGBL R9 G8 - 0x5C280A00, // 0079 MOVE R10 R5 - 0x7C240200, // 007A CALL R9 1 - 0x00263009, // 007B ADD R9 K24 R9 - 0x00241319, // 007C ADD R9 R9 K25 - 0x60280008, // 007D GETGBL R10 G8 - 0x5C2C0C00, // 007E MOVE R11 R6 - 0x7C280200, // 007F CALL R10 1 - 0x0024120A, // 0080 ADD R9 R9 R10 - 0x58280004, // 0081 LDCONST R10 K4 - 0x7C1C0600, // 0082 CALL R7 3 - 0x70020000, // 0083 JMP #0085 - 0xB0080000, // 0084 RAISE 2 R0 R0 - 0x7001FFA4, // 0085 JMP #002B - 0x580C001A, // 0086 LDCONST R3 K26 - 0xAC0C0200, // 0087 CATCH R3 1 0 - 0xB0080000, // 0088 RAISE 2 R0 R0 - 0xB80E0200, // 0089 GETNGBL R3 K1 - 0x8C0C0702, // 008A GETMET R3 R3 K2 - 0x60140018, // 008B GETGBL R5 G24 - 0x5818000A, // 008C LDCONST R6 K10 - 0xB81E0E00, // 008D GETNGBL R7 K7 - 0x881C0F0E, // 008E GETMBR R7 R7 K14 - 0x5820001B, // 008F LDCONST R8 K27 - 0x5824000C, // 0090 LDCONST R9 K12 - 0x7C140800, // 0091 CALL R5 4 - 0x58180004, // 0092 LDCONST R6 K4 - 0x7C0C0600, // 0093 CALL R3 3 - 0xB80E0200, // 0094 GETNGBL R3 K1 - 0x8C0C071C, // 0095 GETMET R3 R3 K28 - 0x5814001D, // 0096 LDCONST R5 K29 - 0x5818001E, // 0097 LDCONST R6 K30 - 0x7C0C0600, // 0098 CALL R3 3 - 0x80000000, // 0099 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: k2l_num -********************************************************************/ -be_local_closure(Matter_Device_k2l_num, /* name */ - be_nested_proto( - 9, /* nstack */ - 1, /* argc */ - 4, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_const_class(be_class_Matter_Device), - /* K1 */ be_nested_str_weak(keys), - /* K2 */ be_nested_str_weak(push), - /* K3 */ be_nested_str_weak(stop_iteration), - /* K4 */ be_const_int(1), - /* K5 */ be_const_int(0), - }), - be_str_weak(k2l_num), - &be_const_str_solidified, - ( &(const binstruction[52]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x60080012, // 0001 GETGBL R2 G18 - 0x7C080000, // 0002 CALL R2 0 - 0x4C0C0000, // 0003 LDNIL R3 - 0x1C0C0003, // 0004 EQ R3 R0 R3 - 0x780E0000, // 0005 JMPF R3 #0007 - 0x80040400, // 0006 RET 1 R2 - 0x600C0010, // 0007 GETGBL R3 G16 - 0x8C100101, // 0008 GETMET R4 R0 K1 - 0x7C100200, // 0009 CALL R4 1 - 0x7C0C0200, // 000A CALL R3 1 - 0xA8020007, // 000B EXBLK 0 #0014 - 0x5C100600, // 000C MOVE R4 R3 - 0x7C100000, // 000D CALL R4 0 - 0x8C140502, // 000E GETMET R5 R2 K2 - 0x601C0009, // 000F GETGBL R7 G9 - 0x5C200800, // 0010 MOVE R8 R4 - 0x7C1C0200, // 0011 CALL R7 1 - 0x7C140400, // 0012 CALL R5 2 - 0x7001FFF7, // 0013 JMP #000C - 0x580C0003, // 0014 LDCONST R3 K3 - 0xAC0C0200, // 0015 CATCH R3 1 0 - 0xB0080000, // 0016 RAISE 2 R0 R0 - 0x600C0010, // 0017 GETGBL R3 G16 - 0x6010000C, // 0018 GETGBL R4 G12 - 0x5C140400, // 0019 MOVE R5 R2 - 0x7C100200, // 001A CALL R4 1 - 0x04100904, // 001B SUB R4 R4 K4 - 0x40120804, // 001C CONNECT R4 K4 R4 - 0x7C0C0200, // 001D CALL R3 1 - 0xA8020010, // 001E EXBLK 0 #0030 - 0x5C100600, // 001F MOVE R4 R3 - 0x7C100000, // 0020 CALL R4 0 - 0x94140404, // 0021 GETIDX R5 R2 R4 - 0x5C180800, // 0022 MOVE R6 R4 - 0x241C0D05, // 0023 GT R7 R6 K5 - 0x781E0008, // 0024 JMPF R7 #002E - 0x041C0D04, // 0025 SUB R7 R6 K4 - 0x941C0407, // 0026 GETIDX R7 R2 R7 - 0x241C0E05, // 0027 GT R7 R7 R5 - 0x781E0004, // 0028 JMPF R7 #002E - 0x041C0D04, // 0029 SUB R7 R6 K4 - 0x941C0407, // 002A GETIDX R7 R2 R7 - 0x98080C07, // 002B SETIDX R2 R6 R7 - 0x04180D04, // 002C SUB R6 R6 K4 - 0x7001FFF4, // 002D JMP #0023 - 0x98080C05, // 002E SETIDX R2 R6 R5 - 0x7001FFEE, // 002F JMP #001F - 0x580C0003, // 0030 LDCONST R3 K3 - 0xAC0C0200, // 0031 CATCH R3 1 0 - 0xB0080000, // 0032 RAISE 2 R0 R0 - 0x80040400, // 0033 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: find_plugin_by_friendly_name -********************************************************************/ -be_local_closure(Matter_Device_find_plugin_by_friendly_name, /* name */ - be_nested_proto( - 7, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str_weak(plugins), - /* K2 */ be_nested_str_weak(get_name), - /* K3 */ be_const_int(1), - }), - be_str_weak(find_plugin_by_friendly_name), - &be_const_str_solidified, - ( &(const binstruction[35]) { /* code */ - 0x4C080000, // 0000 LDNIL R2 - 0x1C080202, // 0001 EQ R2 R1 R2 - 0x740A0004, // 0002 JMPT R2 #0008 - 0x6008000C, // 0003 GETGBL R2 G12 - 0x5C0C0200, // 0004 MOVE R3 R1 - 0x7C080200, // 0005 CALL R2 1 - 0x1C080500, // 0006 EQ R2 R2 K0 - 0x780A0001, // 0007 JMPF R2 #000A - 0x4C080000, // 0008 LDNIL R2 - 0x80040400, // 0009 RET 1 R2 - 0x58080000, // 000A LDCONST R2 K0 - 0x600C000C, // 000B GETGBL R3 G12 - 0x88100101, // 000C GETMBR R4 R0 K1 - 0x7C0C0200, // 000D CALL R3 1 - 0x140C0403, // 000E LT R3 R2 R3 - 0x780E0010, // 000F JMPF R3 #0021 - 0x880C0101, // 0010 GETMBR R3 R0 K1 - 0x940C0602, // 0011 GETIDX R3 R3 R2 - 0x8C100702, // 0012 GETMET R4 R3 K2 - 0x7C100200, // 0013 CALL R4 1 - 0x4C140000, // 0014 LDNIL R5 - 0x20140805, // 0015 NE R5 R4 R5 - 0x78160007, // 0016 JMPF R5 #001F - 0x6014000C, // 0017 GETGBL R5 G12 - 0x5C180800, // 0018 MOVE R6 R4 - 0x7C140200, // 0019 CALL R5 1 - 0x24140B00, // 001A GT R5 R5 K0 - 0x78160002, // 001B JMPF R5 #001F - 0x1C140801, // 001C EQ R5 R4 R1 - 0x78160000, // 001D JMPF R5 #001F - 0x80040600, // 001E RET 1 R3 - 0x00080503, // 001F ADD R2 R2 K3 - 0x7001FFE9, // 0020 JMP #000B - 0x4C0C0000, // 0021 LDNIL R3 - 0x80040600, // 0022 RET 1 R3 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: msg_send -********************************************************************/ -be_local_closure(Matter_Device_msg_send, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(udp_server), - /* K1 */ be_nested_str_weak(send_UDP), - }), - be_str_weak(msg_send), - &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x80040400, // 0004 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_active_endpoints -********************************************************************/ -be_local_closure(Matter_Device_get_active_endpoints, /* name */ - be_nested_proto( - 9, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(plugins), - /* K1 */ be_nested_str_weak(get_endpoint), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(find), - /* K4 */ be_nested_str_weak(push), - /* K5 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(get_active_endpoints), - &be_const_str_solidified, - ( &(const binstruction[28]) { /* code */ - 0x60080012, // 0000 GETGBL R2 G18 - 0x7C080000, // 0001 CALL R2 0 - 0x600C0010, // 0002 GETGBL R3 G16 - 0x88100100, // 0003 GETMBR R4 R0 K0 - 0x7C0C0200, // 0004 CALL R3 1 - 0xA8020011, // 0005 EXBLK 0 #0018 - 0x5C100600, // 0006 MOVE R4 R3 - 0x7C100000, // 0007 CALL R4 0 - 0x8C140901, // 0008 GETMET R5 R4 K1 - 0x7C140200, // 0009 CALL R5 1 - 0x78060002, // 000A JMPF R1 #000E - 0x1C180B02, // 000B EQ R6 R5 K2 - 0x781A0000, // 000C JMPF R6 #000E - 0x7001FFF7, // 000D JMP #0006 - 0x8C180503, // 000E GETMET R6 R2 K3 - 0x5C200A00, // 000F MOVE R8 R5 - 0x7C180400, // 0010 CALL R6 2 - 0x4C1C0000, // 0011 LDNIL R7 - 0x1C180C07, // 0012 EQ R6 R6 R7 - 0x781A0002, // 0013 JMPF R6 #0017 - 0x8C180504, // 0014 GETMET R6 R2 K4 - 0x5C200A00, // 0015 MOVE R8 R5 - 0x7C180400, // 0016 CALL R6 2 - 0x7001FFED, // 0017 JMP #0006 - 0x580C0005, // 0018 LDCONST R3 K5 - 0xAC0C0200, // 0019 CATCH R3 1 0 - 0xB0080000, // 001A RAISE 2 R0 R0 - 0x80040400, // 001B RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: start_root_basic_commissioning -********************************************************************/ -be_local_closure(Matter_Device_start_root_basic_commissioning, /* name */ - be_nested_proto( - 13, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[18]) { /* constants */ - /* K0 */ be_nested_str_weak(PASE_TIMEOUT), - /* K1 */ be_nested_str_weak(compute_manual_pairing_code), - /* K2 */ be_nested_str_weak(tasmota), - /* K3 */ be_nested_str_weak(log), - /* K4 */ be_nested_str_weak(MTR_X3A_X20Manual_X20pairing_X20code_X3A_X20_X25s), - /* K5 */ be_const_int(2), - /* K6 */ be_nested_str_weak(compute_qrcode_content), - /* K7 */ be_nested_str_weak(publish_result), - /* K8 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Commissioning_X22_X3A1_X2C_X22PairingCode_X22_X3A_X22_X25s_X22_X2C_X22QRCode_X22_X3A_X22_X25s_X22_X7D_X7D), - /* K9 */ be_nested_str_weak(Matter), - /* K10 */ be_nested_str_weak(_compute_pbkdf), - /* K11 */ be_nested_str_weak(root_passcode), - /* K12 */ be_nested_str_weak(root_iterations), - /* K13 */ be_nested_str_weak(root_salt), - /* K14 */ be_nested_str_weak(start_basic_commissioning), - /* K15 */ be_nested_str_weak(root_discriminator), - /* K16 */ be_nested_str_weak(root_w0), - /* K17 */ be_nested_str_weak(root_L), - }), - be_str_weak(start_root_basic_commissioning), - &be_const_str_solidified, - ( &(const binstruction[40]) { /* code */ - 0x4C080000, // 0000 LDNIL R2 - 0x1C080202, // 0001 EQ R2 R1 R2 - 0x780A0000, // 0002 JMPF R2 #0004 - 0x88040100, // 0003 GETMBR R1 R0 K0 - 0x8C080101, // 0004 GETMET R2 R0 K1 - 0x7C080200, // 0005 CALL R2 1 - 0xB80E0400, // 0006 GETNGBL R3 K2 - 0x8C0C0703, // 0007 GETMET R3 R3 K3 - 0x60140018, // 0008 GETGBL R5 G24 - 0x58180004, // 0009 LDCONST R6 K4 - 0x5C1C0400, // 000A MOVE R7 R2 - 0x7C140400, // 000B CALL R5 2 - 0x58180005, // 000C LDCONST R6 K5 - 0x7C0C0600, // 000D CALL R3 3 - 0x8C0C0106, // 000E GETMET R3 R0 K6 - 0x7C0C0200, // 000F CALL R3 1 - 0xB8120400, // 0010 GETNGBL R4 K2 - 0x8C100907, // 0011 GETMET R4 R4 K7 - 0x60180018, // 0012 GETGBL R6 G24 - 0x581C0008, // 0013 LDCONST R7 K8 - 0x5C200400, // 0014 MOVE R8 R2 - 0x5C240600, // 0015 MOVE R9 R3 - 0x7C180600, // 0016 CALL R6 3 - 0x581C0009, // 0017 LDCONST R7 K9 - 0x7C100600, // 0018 CALL R4 3 - 0x8C10010A, // 0019 GETMET R4 R0 K10 - 0x8818010B, // 001A GETMBR R6 R0 K11 - 0x881C010C, // 001B GETMBR R7 R0 K12 - 0x8820010D, // 001C GETMBR R8 R0 K13 - 0x7C100800, // 001D CALL R4 4 - 0x8C10010E, // 001E GETMET R4 R0 K14 - 0x5C180200, // 001F MOVE R6 R1 - 0x881C010C, // 0020 GETMBR R7 R0 K12 - 0x8820010F, // 0021 GETMBR R8 R0 K15 - 0x8824010D, // 0022 GETMBR R9 R0 K13 - 0x88280110, // 0023 GETMBR R10 R0 K16 - 0x882C0111, // 0024 GETMBR R11 R0 K17 - 0x4C300000, // 0025 LDNIL R12 - 0x7C101000, // 0026 CALL R4 8 - 0x80000000, // 0027 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: bridge_remove_endpoint -********************************************************************/ -be_local_closure(Matter_Device_bridge_remove_endpoint, /* name */ - be_nested_proto( - 11, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[18]) { /* constants */ - /* K0 */ be_nested_str_weak(json), - /* K1 */ be_nested_str_weak(plugins_config), - /* K2 */ be_nested_str_weak(contains), - /* K3 */ be_nested_str_weak(tasmota), - /* K4 */ be_nested_str_weak(log), - /* K5 */ be_nested_str_weak(MTR_X3A_X20Cannot_X20remove_X20an_X20enpoint_X20not_X20configured_X3A_X20), - /* K6 */ be_const_int(3), - /* K7 */ be_nested_str_weak(MTR_X3A_X20deleting_X20endpoint_X20_X3D_X20_X25i), - /* K8 */ be_const_int(2), - /* K9 */ be_nested_str_weak(remove), - /* K10 */ be_nested_str_weak(plugins_persist), - /* K11 */ be_const_int(0), - /* K12 */ be_nested_str_weak(plugins), - /* K13 */ be_nested_str_weak(get_endpoint), - /* K14 */ be_const_int(1), - /* K15 */ be_nested_str_weak(clean_remotes), - /* K16 */ be_nested_str_weak(save_param), - /* K17 */ be_nested_str_weak(signal_endpoints_changed), - }), - be_str_weak(bridge_remove_endpoint), - &be_const_str_solidified, - ( &(const binstruction[58]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0x600C0008, // 0001 GETGBL R3 G8 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C0C0200, // 0003 CALL R3 1 - 0x4C100000, // 0004 LDNIL R4 - 0x4C140000, // 0005 LDNIL R5 - 0x88180101, // 0006 GETMBR R6 R0 K1 - 0x8C180D02, // 0007 GETMET R6 R6 K2 - 0x5C200600, // 0008 MOVE R8 R3 - 0x7C180400, // 0009 CALL R6 2 - 0x741A0005, // 000A JMPT R6 #0011 - 0xB81A0600, // 000B GETNGBL R6 K3 - 0x8C180D04, // 000C GETMET R6 R6 K4 - 0x00220A03, // 000D ADD R8 K5 R3 - 0x58240006, // 000E LDCONST R9 K6 - 0x7C180600, // 000F CALL R6 3 - 0x80000C00, // 0010 RET 0 - 0xB81A0600, // 0011 GETNGBL R6 K3 - 0x8C180D04, // 0012 GETMET R6 R6 K4 - 0x60200018, // 0013 GETGBL R8 G24 - 0x58240007, // 0014 LDCONST R9 K7 - 0x5C280200, // 0015 MOVE R10 R1 - 0x7C200400, // 0016 CALL R8 2 - 0x58240008, // 0017 LDCONST R9 K8 - 0x7C180600, // 0018 CALL R6 3 - 0x88180101, // 0019 GETMBR R6 R0 K1 - 0x8C180D09, // 001A GETMET R6 R6 K9 - 0x5C200600, // 001B MOVE R8 R3 - 0x7C180400, // 001C CALL R6 2 - 0x50180200, // 001D LDBOOL R6 1 0 - 0x90021406, // 001E SETMBR R0 K10 R6 - 0x5818000B, // 001F LDCONST R6 K11 - 0x601C000C, // 0020 GETGBL R7 G12 - 0x8820010C, // 0021 GETMBR R8 R0 K12 - 0x7C1C0200, // 0022 CALL R7 1 - 0x141C0C07, // 0023 LT R7 R6 R7 - 0x781E000D, // 0024 JMPF R7 #0033 - 0x881C010C, // 0025 GETMBR R7 R0 K12 - 0x941C0E06, // 0026 GETIDX R7 R7 R6 - 0x8C1C0F0D, // 0027 GETMET R7 R7 K13 - 0x7C1C0200, // 0028 CALL R7 1 - 0x1C1C0207, // 0029 EQ R7 R1 R7 - 0x781E0005, // 002A JMPF R7 #0031 - 0x881C010C, // 002B GETMBR R7 R0 K12 - 0x8C1C0F09, // 002C GETMET R7 R7 K9 - 0x5C240C00, // 002D MOVE R9 R6 - 0x7C1C0400, // 002E CALL R7 2 - 0x70020002, // 002F JMP #0033 - 0x70020000, // 0030 JMP #0032 - 0x00180D0E, // 0031 ADD R6 R6 K14 - 0x7001FFEC, // 0032 JMP #0020 - 0x8C1C010F, // 0033 GETMET R7 R0 K15 - 0x7C1C0200, // 0034 CALL R7 1 - 0x8C1C0110, // 0035 GETMET R7 R0 K16 - 0x7C1C0200, // 0036 CALL R7 1 - 0x8C1C0111, // 0037 GETMET R7 R0 K17 - 0x7C1C0200, // 0038 CALL R7 1 - 0x80000000, // 0039 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_plugin_class_displayname -********************************************************************/ -be_local_closure(Matter_Device_get_plugin_class_displayname, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(plugins_classes), - /* K1 */ be_nested_str_weak(find), - /* K2 */ be_nested_str_weak(DISPLAY_NAME), - /* K3 */ be_nested_str_weak(), - }), - be_str_weak(get_plugin_class_displayname), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x780A0001, // 0004 JMPF R2 #0007 - 0x880C0502, // 0005 GETMBR R3 R2 K2 - 0x70020000, // 0006 JMP #0008 - 0x580C0003, // 0007 LDCONST R3 K3 - 0x80040600, // 0008 RET 1 R3 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: update_remotes_info -********************************************************************/ -be_local_closure(Matter_Device_update_remotes_info, /* name */ - be_nested_proto( - 7, /* nstack */ + 6, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(http_remotes), - /* K1 */ be_nested_str_weak(keys), - /* K2 */ be_nested_str_weak(get_info), - /* K3 */ be_const_int(0), - /* K4 */ be_nested_str_weak(stop_iteration), - /* K5 */ be_nested_str_weak(plugins_config_remotes), + 1, /* has sup protos */ + ( &(const struct bproto*[ 2]) { + be_nested_proto( + 4, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(_mdns_announce_hostname), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(remove_rule), + /* K3 */ be_nested_str_weak(Wifi_X23Connected), + /* K4 */ be_nested_str_weak(matter_mdns_host), + }), + be_str_weak(_anonymous_), + &be_const_str_solidified, + ( &(const binstruction[10]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x50080000, // 0002 LDBOOL R2 0 0 + 0x7C000400, // 0003 CALL R0 2 + 0xB8020200, // 0004 GETNGBL R0 K1 + 0x8C000102, // 0005 GETMET R0 R0 K2 + 0x58080003, // 0006 LDCONST R2 K3 + 0x580C0004, // 0007 LDCONST R3 K4 + 0x7C000600, // 0008 CALL R0 3 + 0x80000000, // 0009 RET 0 + }) + ), + be_nested_proto( + 4, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 1]) { /* upvals */ + be_local_const_upval(1, 0), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(_mdns_announce_hostname), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(remove_rule), + /* K3 */ be_nested_str_weak(Eth_X23Connected), + /* K4 */ be_nested_str_weak(matter_mdns_host), + }), + be_str_weak(_anonymous_), + &be_const_str_solidified, + ( &(const binstruction[10]) { /* code */ + 0x68000000, // 0000 GETUPV R0 U0 + 0x8C000100, // 0001 GETMET R0 R0 K0 + 0x50080200, // 0002 LDBOOL R2 1 0 + 0x7C000400, // 0003 CALL R0 2 + 0xB8020200, // 0004 GETNGBL R0 K1 + 0x8C000102, // 0005 GETMET R0 R0 K2 + 0x58080003, // 0006 LDCONST R2 K3 + 0x580C0004, // 0007 LDCONST R3 K4 + 0x7C000600, // 0008 CALL R0 3 + 0x80000000, // 0009 RET 0 + }) + ), }), - be_str_weak(update_remotes_info), + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(wifi), + /* K2 */ be_nested_str_weak(up), + /* K3 */ be_nested_str_weak(_mdns_announce_hostname), + /* K4 */ be_nested_str_weak(add_rule), + /* K5 */ be_nested_str_weak(Wifi_X23Connected), + /* K6 */ be_nested_str_weak(matter_mdns_host), + /* K7 */ be_nested_str_weak(eth), + /* K8 */ be_nested_str_weak(Eth_X23Connected), + }), + be_str_weak(start_mdns_announce_hostnames), &be_const_str_solidified, - ( &(const binstruction[33]) { /* code */ - 0x60040013, // 0000 GETGBL R1 G19 - 0x7C040000, // 0001 CALL R1 0 - 0x88080100, // 0002 GETMBR R2 R0 K0 - 0x4C0C0000, // 0003 LDNIL R3 - 0x20080403, // 0004 NE R2 R2 R3 - 0x780A0018, // 0005 JMPF R2 #001F - 0x60080010, // 0006 GETGBL R2 G16 - 0x880C0100, // 0007 GETMBR R3 R0 K0 - 0x8C0C0701, // 0008 GETMET R3 R3 K1 - 0x7C0C0200, // 0009 CALL R3 1 - 0x7C080200, // 000A CALL R2 1 - 0xA802000F, // 000B EXBLK 0 #001C - 0x5C0C0400, // 000C MOVE R3 R2 - 0x7C0C0000, // 000D CALL R3 0 - 0x88100100, // 000E GETMBR R4 R0 K0 - 0x94100803, // 000F GETIDX R4 R4 R3 - 0x8C100902, // 0010 GETMET R4 R4 K2 - 0x7C100200, // 0011 CALL R4 1 - 0x4C140000, // 0012 LDNIL R5 - 0x20140805, // 0013 NE R5 R4 R5 - 0x78160005, // 0014 JMPF R5 #001B - 0x6014000C, // 0015 GETGBL R5 G12 - 0x5C180800, // 0016 MOVE R6 R4 - 0x7C140200, // 0017 CALL R5 1 - 0x24140B03, // 0018 GT R5 R5 K3 - 0x78160000, // 0019 JMPF R5 #001B - 0x98040604, // 001A SETIDX R1 R3 R4 - 0x7001FFEF, // 001B JMP #000C - 0x58080004, // 001C LDCONST R2 K4 - 0xAC080200, // 001D CATCH R2 1 0 - 0xB0080000, // 001E RAISE 2 R0 R0 - 0x90020A01, // 001F SETMBR R0 K5 R1 - 0x80040200, // 0020 RET 1 R1 + ( &(const binstruction[32]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x94040302, // 0003 GETIDX R1 R1 K2 + 0x78060003, // 0004 JMPF R1 #0009 + 0x8C040103, // 0005 GETMET R1 R0 K3 + 0x500C0000, // 0006 LDBOOL R3 0 0 + 0x7C040400, // 0007 CALL R1 2 + 0x70020005, // 0008 JMP #000F + 0xB8060000, // 0009 GETNGBL R1 K0 + 0x8C040304, // 000A GETMET R1 R1 K4 + 0x580C0005, // 000B LDCONST R3 K5 + 0x84100000, // 000C CLOSURE R4 P0 + 0x58140006, // 000D LDCONST R5 K6 + 0x7C040800, // 000E CALL R1 4 + 0xB8060000, // 000F GETNGBL R1 K0 + 0x8C040307, // 0010 GETMET R1 R1 K7 + 0x7C040200, // 0011 CALL R1 1 + 0x94040302, // 0012 GETIDX R1 R1 K2 + 0x78060003, // 0013 JMPF R1 #0018 + 0x8C040103, // 0014 GETMET R1 R0 K3 + 0x500C0200, // 0015 LDBOOL R3 1 0 + 0x7C040400, // 0016 CALL R1 2 + 0x70020005, // 0017 JMP #001E + 0xB8060000, // 0018 GETNGBL R1 K0 + 0x8C040304, // 0019 GETMET R1 R1 K4 + 0x580C0008, // 001A LDCONST R3 K8 + 0x84100001, // 001B CLOSURE R4 P1 + 0x58140006, // 001C LDCONST R5 K6 + 0x7C040800, // 001D CALL R1 4 + 0xA0000000, // 001E CLOSE R0 + 0x80000000, // 001F RET 0 }) ) ); @@ -3117,11 +5853,11 @@ be_local_closure(Matter_Device_update_remotes_info, /* name */ /******************************************************************** -** Solidified function: start +** Solidified function: signal_endpoints_changed ********************************************************************/ -be_local_closure(Matter_Device_start, /* name */ +be_local_closure(Matter_Device_signal_endpoints_changed, /* name */ be_nested_proto( - 4, /* nstack */ + 7, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -3130,426 +5866,29 @@ be_local_closure(Matter_Device_start, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(started), - /* K1 */ be_nested_str_weak(autoconf_device), - /* K2 */ be_nested_str_weak(_start_udp), - /* K3 */ be_nested_str_weak(UDP_PORT), - /* K4 */ be_nested_str_weak(start_mdns_announce_hostnames), + /* K0 */ be_nested_str_weak(attribute_updated), + /* K1 */ be_const_int(0), + /* K2 */ be_const_int(3), + /* K3 */ be_nested_str_weak(matter), + /* K4 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), }), - be_str_weak(start), + be_str_weak(signal_endpoints_changed), &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x78060000, // 0001 JMPF R1 #0003 - 0x80000200, // 0002 RET 0 - 0x8C040101, // 0003 GETMET R1 R0 K1 - 0x7C040200, // 0004 CALL R1 1 - 0x8C040102, // 0005 GETMET R1 R0 K2 - 0x880C0103, // 0006 GETMBR R3 R0 K3 - 0x7C040400, // 0007 CALL R1 2 - 0x8C040104, // 0008 GETMET R1 R0 K4 - 0x7C040200, // 0009 CALL R1 1 - 0x50040200, // 000A LDBOOL R1 1 0 - 0x90020001, // 000B SETMBR R0 K0 R1 - 0x80000000, // 000C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: k2l -********************************************************************/ -be_local_closure(Matter_Device_k2l, /* name */ - be_nested_proto( - 8, /* nstack */ - 1, /* argc */ - 4, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_const_class(be_class_Matter_Device), - /* K1 */ be_nested_str_weak(keys), - /* K2 */ be_nested_str_weak(push), - /* K3 */ be_nested_str_weak(stop_iteration), - /* K4 */ be_const_int(1), - /* K5 */ be_const_int(0), - }), - be_str_weak(k2l), - &be_const_str_solidified, - ( &(const binstruction[50]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x60080012, // 0001 GETGBL R2 G18 - 0x7C080000, // 0002 CALL R2 0 - 0x4C0C0000, // 0003 LDNIL R3 - 0x1C0C0003, // 0004 EQ R3 R0 R3 - 0x780E0000, // 0005 JMPF R3 #0007 - 0x80040400, // 0006 RET 1 R2 - 0x600C0010, // 0007 GETGBL R3 G16 - 0x8C100101, // 0008 GETMET R4 R0 K1 - 0x7C100200, // 0009 CALL R4 1 - 0x7C0C0200, // 000A CALL R3 1 - 0xA8020005, // 000B EXBLK 0 #0012 - 0x5C100600, // 000C MOVE R4 R3 - 0x7C100000, // 000D CALL R4 0 - 0x8C140502, // 000E GETMET R5 R2 K2 - 0x5C1C0800, // 000F MOVE R7 R4 - 0x7C140400, // 0010 CALL R5 2 - 0x7001FFF9, // 0011 JMP #000C - 0x580C0003, // 0012 LDCONST R3 K3 - 0xAC0C0200, // 0013 CATCH R3 1 0 - 0xB0080000, // 0014 RAISE 2 R0 R0 - 0x600C0010, // 0015 GETGBL R3 G16 - 0x6010000C, // 0016 GETGBL R4 G12 - 0x5C140400, // 0017 MOVE R5 R2 - 0x7C100200, // 0018 CALL R4 1 - 0x04100904, // 0019 SUB R4 R4 K4 - 0x40120804, // 001A CONNECT R4 K4 R4 - 0x7C0C0200, // 001B CALL R3 1 - 0xA8020010, // 001C EXBLK 0 #002E - 0x5C100600, // 001D MOVE R4 R3 - 0x7C100000, // 001E CALL R4 0 - 0x94140404, // 001F GETIDX R5 R2 R4 - 0x5C180800, // 0020 MOVE R6 R4 - 0x241C0D05, // 0021 GT R7 R6 K5 - 0x781E0008, // 0022 JMPF R7 #002C - 0x041C0D04, // 0023 SUB R7 R6 K4 - 0x941C0407, // 0024 GETIDX R7 R2 R7 - 0x241C0E05, // 0025 GT R7 R7 R5 - 0x781E0004, // 0026 JMPF R7 #002C - 0x041C0D04, // 0027 SUB R7 R6 K4 - 0x941C0407, // 0028 GETIDX R7 R2 R7 - 0x98080C07, // 0029 SETIDX R2 R6 R7 - 0x04180D04, // 002A SUB R6 R6 K4 - 0x7001FFF4, // 002B JMP #0021 - 0x98080C05, // 002C SETIDX R2 R6 R5 - 0x7001FFEE, // 002D JMP #001D - 0x580C0003, // 002E LDCONST R3 K3 - 0xAC0C0200, // 002F CATCH R3 1 0 - 0xB0080000, // 0030 RAISE 2 R0 R0 - 0x80040400, // 0031 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: start_operational_discovery_deferred -********************************************************************/ -be_local_closure(Matter_Device_start_operational_discovery_deferred, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 1]) { - be_nested_proto( - 3, /* nstack */ - 0, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 2]) { /* upvals */ - be_local_const_upval(1, 0), - be_local_const_upval(1, 1), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(start_operational_discovery), - }), - be_str_weak(_X3Clambda_X3E), - &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x68000000, // 0000 GETUPV R0 U0 - 0x8C000100, // 0001 GETMET R0 R0 K0 - 0x68080001, // 0002 GETUPV R2 U1 - 0x7C000400, // 0003 CALL R0 2 - 0x80040000, // 0004 RET 1 R0 - }) - ), - }), - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(set_timer), - /* K2 */ be_const_int(0), - }), - be_str_weak(start_operational_discovery_deferred), - &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0xB80A0000, // 0000 GETNGBL R2 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x58100002, // 0002 LDCONST R4 K2 - 0x84140000, // 0003 CLOSURE R5 P0 - 0x7C080600, // 0004 CALL R2 3 - 0xA0000000, // 0005 CLOSE R0 - 0x80000000, // 0006 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: autoconf_device_map -********************************************************************/ -be_local_closure(Matter_Device_autoconf_device_map, /* name */ - be_nested_proto( - 20, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[36]) { /* constants */ - /* K0 */ be_nested_str_weak(json), - /* K1 */ be_const_int(1), - /* K2 */ be_nested_str_weak(light), - /* K3 */ be_nested_str_weak(get), - /* K4 */ be_nested_str_weak(find), - /* K5 */ be_nested_str_weak(channels), - /* K6 */ be_nested_str_weak(), - /* K7 */ be_const_int(0), - /* K8 */ be_nested_str_weak(type), - /* K9 */ be_nested_str_weak(light1), - /* K10 */ be_const_int(2), - /* K11 */ be_nested_str_weak(light2), - /* K12 */ be_nested_str_weak(light3), - /* K13 */ be_nested_str_weak(tasmota), - /* K14 */ be_nested_str_weak(cmd), - /* K15 */ be_nested_str_weak(Status_X2013), - /* K16 */ be_nested_str_weak(log), - /* K17 */ be_nested_str_weak(MTR_X3A_X20Status_X2013_X20_X3D_X20), - /* K18 */ be_const_int(3), - /* K19 */ be_nested_str_weak(contains), - /* K20 */ be_nested_str_weak(StatusSHT), - /* K21 */ be_nested_str_weak(SHT), - /* K22 */ be_nested_str_weak(MTR_X3A_X20_X27_X25s_X27_X20_X3D_X20_X25s), - /* K23 */ be_nested_str_weak(Relay1), - /* K24 */ be_nested_str_weak(Relay2), - /* K25 */ be_nested_str_weak(push), - /* K26 */ be_nested_str_weak(MTR_X3A_X20relay1_X3D_X25s_X20relay2_X3D_X25s), - /* K27 */ be_nested_str_weak(TiltConfig), - /* K28 */ be_nested_str_weak(shutter_X2Btilt), - /* K29 */ be_nested_str_weak(shutter), - /* K30 */ be_nested_str_weak(get_power), - /* K31 */ be_nested_str_weak(relay), - /* K32 */ be_nested_str_weak(load), - /* K33 */ be_nested_str_weak(read_sensors), - /* K34 */ be_nested_str_weak(autoconf_sensors_list), - /* K35 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(autoconf_device_map), - &be_const_str_solidified, - ( &(const binstruction[198]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0x60080013, // 0001 GETGBL R2 G19 - 0x7C080000, // 0002 CALL R2 0 - 0x580C0001, // 0003 LDCONST R3 K1 - 0x50100000, // 0004 LDBOOL R4 0 0 - 0xA4160400, // 0005 IMPORT R5 K2 - 0x8C180B03, // 0006 GETMET R6 R5 K3 - 0x7C180200, // 0007 CALL R6 1 - 0x4C1C0000, // 0008 LDNIL R7 - 0x201C0C07, // 0009 NE R7 R6 R7 - 0x781E0024, // 000A JMPF R7 #0030 - 0x601C000C, // 000B GETGBL R7 G12 - 0x8C200D04, // 000C GETMET R8 R6 K4 - 0x58280005, // 000D LDCONST R10 K5 - 0x582C0006, // 000E LDCONST R11 K6 - 0x7C200600, // 000F CALL R8 3 - 0x7C1C0200, // 0010 CALL R7 1 - 0x24200F07, // 0011 GT R8 R7 K7 - 0x7822001C, // 0012 JMPF R8 #0030 - 0x1C200F01, // 0013 EQ R8 R7 K1 - 0x78220007, // 0014 JMPF R8 #001D - 0x60200008, // 0015 GETGBL R8 G8 - 0x5C240600, // 0016 MOVE R9 R3 - 0x7C200200, // 0017 CALL R8 1 - 0x60240013, // 0018 GETGBL R9 G19 - 0x7C240000, // 0019 CALL R9 0 - 0x98261109, // 001A SETIDX R9 K8 K9 - 0x98081009, // 001B SETIDX R2 R8 R9 - 0x70020010, // 001C JMP #002E - 0x1C200F0A, // 001D EQ R8 R7 K10 - 0x78220007, // 001E JMPF R8 #0027 - 0x60200008, // 001F GETGBL R8 G8 - 0x5C240600, // 0020 MOVE R9 R3 - 0x7C200200, // 0021 CALL R8 1 - 0x60240013, // 0022 GETGBL R9 G19 - 0x7C240000, // 0023 CALL R9 0 - 0x9826110B, // 0024 SETIDX R9 K8 K11 - 0x98081009, // 0025 SETIDX R2 R8 R9 - 0x70020006, // 0026 JMP #002E - 0x60200008, // 0027 GETGBL R8 G8 - 0x5C240600, // 0028 MOVE R9 R3 - 0x7C200200, // 0029 CALL R8 1 - 0x60240013, // 002A GETGBL R9 G19 - 0x7C240000, // 002B CALL R9 0 - 0x9826110C, // 002C SETIDX R9 K8 K12 - 0x98081009, // 002D SETIDX R2 R8 R9 - 0x50100200, // 002E LDBOOL R4 1 0 - 0x000C0701, // 002F ADD R3 R3 K1 - 0xB81E1A00, // 0030 GETNGBL R7 K13 - 0x8C1C0F0E, // 0031 GETMET R7 R7 K14 - 0x5824000F, // 0032 LDCONST R9 K15 - 0x50280200, // 0033 LDBOOL R10 1 0 - 0x7C1C0600, // 0034 CALL R7 3 - 0x60200012, // 0035 GETGBL R8 G18 - 0x7C200000, // 0036 CALL R8 0 - 0xB8261A00, // 0037 GETNGBL R9 K13 - 0x8C241310, // 0038 GETMET R9 R9 K16 - 0x602C0008, // 0039 GETGBL R11 G8 - 0x5C300E00, // 003A MOVE R12 R7 - 0x7C2C0200, // 003B CALL R11 1 - 0x002E220B, // 003C ADD R11 K17 R11 - 0x58300012, // 003D LDCONST R12 K18 - 0x7C240600, // 003E CALL R9 3 - 0x4C240000, // 003F LDNIL R9 - 0x20240E09, // 0040 NE R9 R7 R9 - 0x7826004F, // 0041 JMPF R9 #0092 - 0x8C240F13, // 0042 GETMET R9 R7 K19 - 0x582C0014, // 0043 LDCONST R11 K20 - 0x7C240400, // 0044 CALL R9 2 - 0x7826004B, // 0045 JMPF R9 #0092 - 0x941C0F14, // 0046 GETIDX R7 R7 K20 - 0x58240007, // 0047 LDCONST R9 K7 - 0x50280200, // 0048 LDBOOL R10 1 0 - 0x782A0047, // 0049 JMPF R10 #0092 - 0x60280008, // 004A GETGBL R10 G8 - 0x5C2C1200, // 004B MOVE R11 R9 - 0x7C280200, // 004C CALL R10 1 - 0x002A2A0A, // 004D ADD R10 K21 R10 - 0x8C2C0F13, // 004E GETMET R11 R7 K19 - 0x5C341400, // 004F MOVE R13 R10 - 0x7C2C0400, // 0050 CALL R11 2 - 0x742E0000, // 0051 JMPT R11 #0053 - 0x7002003E, // 0052 JMP #0092 - 0x942C0E0A, // 0053 GETIDX R11 R7 R10 - 0xB8321A00, // 0054 GETNGBL R12 K13 - 0x8C301910, // 0055 GETMET R12 R12 K16 - 0x60380018, // 0056 GETGBL R14 G24 - 0x583C0016, // 0057 LDCONST R15 K22 - 0x5C401400, // 0058 MOVE R16 R10 - 0x60440008, // 0059 GETGBL R17 G8 - 0x5C481600, // 005A MOVE R18 R11 - 0x7C440200, // 005B CALL R17 1 - 0x7C380600, // 005C CALL R14 3 - 0x583C0012, // 005D LDCONST R15 K18 - 0x7C300600, // 005E CALL R12 3 - 0x8C301704, // 005F GETMET R12 R11 K4 - 0x58380017, // 0060 LDCONST R14 K23 - 0x543DFFFE, // 0061 LDINT R15 -1 - 0x7C300600, // 0062 CALL R12 3 - 0x8C341704, // 0063 GETMET R13 R11 K4 - 0x583C0018, // 0064 LDCONST R15 K24 - 0x5441FFFE, // 0065 LDINT R16 -1 - 0x7C340600, // 0066 CALL R13 3 - 0x24381907, // 0067 GT R14 R12 K7 - 0x783A0002, // 0068 JMPF R14 #006C - 0x8C381119, // 0069 GETMET R14 R8 K25 - 0x04401901, // 006A SUB R16 R12 K1 - 0x7C380400, // 006B CALL R14 2 - 0x24381B07, // 006C GT R14 R13 K7 - 0x783A0002, // 006D JMPF R14 #0071 - 0x8C381119, // 006E GETMET R14 R8 K25 - 0x04401B01, // 006F SUB R16 R13 K1 - 0x7C380400, // 0070 CALL R14 2 - 0xB83A1A00, // 0071 GETNGBL R14 K13 - 0x8C381D10, // 0072 GETMET R14 R14 K16 - 0x60400018, // 0073 GETGBL R16 G24 - 0x5844001A, // 0074 LDCONST R17 K26 - 0x5C481800, // 0075 MOVE R18 R12 - 0x5C4C1A00, // 0076 MOVE R19 R13 - 0x7C400600, // 0077 CALL R16 3 - 0x58440012, // 0078 LDCONST R17 K18 - 0x7C380600, // 0079 CALL R14 3 - 0x8C381704, // 007A GETMET R14 R11 K4 - 0x5840001B, // 007B LDCONST R16 K27 - 0x7C380400, // 007C CALL R14 2 - 0x783A0002, // 007D JMPF R14 #0081 - 0x943C1D0A, // 007E GETIDX R15 R14 K10 - 0x243C1F07, // 007F GT R15 R15 K7 - 0x743E0000, // 0080 JMPT R15 #0082 - 0x503C0001, // 0081 LDBOOL R15 0 1 - 0x503C0200, // 0082 LDBOOL R15 1 0 - 0x60400008, // 0083 GETGBL R16 G8 - 0x5C440600, // 0084 MOVE R17 R3 - 0x7C400200, // 0085 CALL R16 1 - 0x60440013, // 0086 GETGBL R17 G19 - 0x7C440000, // 0087 CALL R17 0 - 0x783E0001, // 0088 JMPF R15 #008B - 0x5848001C, // 0089 LDCONST R18 K28 - 0x70020000, // 008A JMP #008C - 0x5848001D, // 008B LDCONST R18 K29 - 0x98461012, // 008C SETIDX R17 K8 R18 - 0x98463A09, // 008D SETIDX R17 K29 R9 - 0x98082011, // 008E SETIDX R2 R16 R17 - 0x000C0701, // 008F ADD R3 R3 K1 - 0x00241301, // 0090 ADD R9 R9 K1 - 0x7001FFB5, // 0091 JMP #0048 - 0x6024000C, // 0092 GETGBL R9 G12 - 0xB82A1A00, // 0093 GETNGBL R10 K13 - 0x8C28151E, // 0094 GETMET R10 R10 K30 - 0x7C280200, // 0095 CALL R10 1 - 0x7C240200, // 0096 CALL R9 1 - 0x58280007, // 0097 LDCONST R10 K7 - 0x78120000, // 0098 JMPF R4 #009A - 0x04241301, // 0099 SUB R9 R9 K1 - 0x142C1409, // 009A LT R11 R10 R9 - 0x782E0011, // 009B JMPF R11 #00AE - 0x8C2C1104, // 009C GETMET R11 R8 K4 - 0x5C341400, // 009D MOVE R13 R10 - 0x7C2C0400, // 009E CALL R11 2 - 0x4C300000, // 009F LDNIL R12 - 0x1C2C160C, // 00A0 EQ R11 R11 R12 - 0x782E0009, // 00A1 JMPF R11 #00AC - 0x602C0008, // 00A2 GETGBL R11 G8 - 0x5C300600, // 00A3 MOVE R12 R3 - 0x7C2C0200, // 00A4 CALL R11 1 - 0x60300013, // 00A5 GETGBL R12 G19 - 0x7C300000, // 00A6 CALL R12 0 - 0x9832111F, // 00A7 SETIDX R12 K8 K31 - 0x00341501, // 00A8 ADD R13 R10 K1 - 0x98323E0D, // 00A9 SETIDX R12 K31 R13 - 0x9808160C, // 00AA SETIDX R2 R11 R12 - 0x000C0701, // 00AB ADD R3 R3 K1 - 0x00281501, // 00AC ADD R10 R10 K1 - 0x7001FFEB, // 00AD JMP #009A - 0x8C2C0320, // 00AE GETMET R11 R1 K32 - 0xB8361A00, // 00AF GETNGBL R13 K13 - 0x8C341B21, // 00B0 GETMET R13 R13 K33 - 0x7C340200, // 00B1 CALL R13 1 - 0x7C2C0400, // 00B2 CALL R11 2 - 0x8C300122, // 00B3 GETMET R12 R0 K34 - 0x5C381600, // 00B4 MOVE R14 R11 - 0x7C300400, // 00B5 CALL R12 2 - 0x60340010, // 00B6 GETGBL R13 G16 - 0x5C381800, // 00B7 MOVE R14 R12 - 0x7C340200, // 00B8 CALL R13 1 - 0xA8020007, // 00B9 EXBLK 0 #00C2 - 0x5C381A00, // 00BA MOVE R14 R13 - 0x7C380000, // 00BB CALL R14 0 - 0x603C0008, // 00BC GETGBL R15 G8 - 0x5C400600, // 00BD MOVE R16 R3 - 0x7C3C0200, // 00BE CALL R15 1 - 0x98081E0E, // 00BF SETIDX R2 R15 R14 - 0x000C0701, // 00C0 ADD R3 R3 K1 - 0x7001FFF7, // 00C1 JMP #00BA - 0x58340023, // 00C2 LDCONST R13 K35 - 0xAC340200, // 00C3 CATCH R13 1 0 - 0xB0080000, // 00C4 RAISE 2 R0 R0 - 0x80040400, // 00C5 RET 1 R2 + ( &(const binstruction[14]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x580C0001, // 0001 LDCONST R3 K1 + 0x5412001C, // 0002 LDINT R4 29 + 0x58140002, // 0003 LDCONST R5 K2 + 0x50180000, // 0004 LDBOOL R6 0 0 + 0x7C040A00, // 0005 CALL R1 5 + 0x8C040100, // 0006 GETMET R1 R0 K0 + 0xB80E0600, // 0007 GETNGBL R3 K3 + 0x880C0704, // 0008 GETMBR R3 R3 K4 + 0x5412001C, // 0009 LDINT R4 29 + 0x58140002, // 000A LDCONST R5 K2 + 0x50180000, // 000B LDBOOL R6 0 0 + 0x7C040A00, // 000C CALL R1 5 + 0x80000000, // 000D RET 0 }) ) ); @@ -3858,445 +6197,9 @@ be_local_closure(Matter_Device_mdns_announce_PASE, /* name */ /******************************************************************** -** Solidified function: clean_remotes +** Solidified function: get_plugin_remote_info ********************************************************************/ -be_local_closure(Matter_Device_clean_remotes, /* name */ - be_nested_proto( - 10, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[18]) { /* constants */ - /* K0 */ be_nested_str_weak(introspect), - /* K1 */ be_nested_str_weak(http_remotes), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(stop_iteration), - /* K4 */ be_nested_str_weak(plugins), - /* K5 */ be_nested_str_weak(get), - /* K6 */ be_nested_str_weak(http_remote), - /* K7 */ be_nested_str_weak(find), - /* K8 */ be_const_int(1), - /* K9 */ be_nested_str_weak(keys), - /* K10 */ be_nested_str_weak(push), - /* K11 */ be_nested_str_weak(tasmota), - /* K12 */ be_nested_str_weak(log), - /* K13 */ be_nested_str_weak(MTR_X3A_X20remove_X20unused_X20remote_X3A_X20), - /* K14 */ be_nested_str_weak(addr), - /* K15 */ be_const_int(3), - /* K16 */ be_nested_str_weak(close), - /* K17 */ be_nested_str_weak(remove), - }), - be_str_weak(clean_remotes), - &be_const_str_solidified, - ( &(const binstruction[81]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0x88080101, // 0001 GETMBR R2 R0 K1 - 0x780A004C, // 0002 JMPF R2 #0050 - 0x60080013, // 0003 GETGBL R2 G19 - 0x7C080000, // 0004 CALL R2 0 - 0x600C0010, // 0005 GETGBL R3 G16 - 0x88100101, // 0006 GETMBR R4 R0 K1 - 0x7C0C0200, // 0007 CALL R3 1 - 0xA8020003, // 0008 EXBLK 0 #000D - 0x5C100600, // 0009 MOVE R4 R3 - 0x7C100000, // 000A CALL R4 0 - 0x98080902, // 000B SETIDX R2 R4 K2 - 0x7001FFFB, // 000C JMP #0009 - 0x580C0003, // 000D LDCONST R3 K3 - 0xAC0C0200, // 000E CATCH R3 1 0 - 0xB0080000, // 000F RAISE 2 R0 R0 - 0x600C0010, // 0010 GETGBL R3 G16 - 0x88100104, // 0011 GETMBR R4 R0 K4 - 0x7C0C0200, // 0012 CALL R3 1 - 0xA802000F, // 0013 EXBLK 0 #0024 - 0x5C100600, // 0014 MOVE R4 R3 - 0x7C100000, // 0015 CALL R4 0 - 0x8C140305, // 0016 GETMET R5 R1 K5 - 0x5C1C0800, // 0017 MOVE R7 R4 - 0x58200006, // 0018 LDCONST R8 K6 - 0x7C140600, // 0019 CALL R5 3 - 0x4C180000, // 001A LDNIL R6 - 0x20180A06, // 001B NE R6 R5 R6 - 0x781A0005, // 001C JMPF R6 #0023 - 0x8C180507, // 001D GETMET R6 R2 K7 - 0x5C200A00, // 001E MOVE R8 R5 - 0x58240002, // 001F LDCONST R9 K2 - 0x7C180600, // 0020 CALL R6 3 - 0x00180D08, // 0021 ADD R6 R6 K8 - 0x98080A06, // 0022 SETIDX R2 R5 R6 - 0x7001FFEF, // 0023 JMP #0014 - 0x580C0003, // 0024 LDCONST R3 K3 - 0xAC0C0200, // 0025 CATCH R3 1 0 - 0xB0080000, // 0026 RAISE 2 R0 R0 - 0x600C0012, // 0027 GETGBL R3 G18 - 0x7C0C0000, // 0028 CALL R3 0 - 0x60100010, // 0029 GETGBL R4 G16 - 0x8C140509, // 002A GETMET R5 R2 K9 - 0x7C140200, // 002B CALL R5 1 - 0x7C100200, // 002C CALL R4 1 - 0xA8020008, // 002D EXBLK 0 #0037 - 0x5C140800, // 002E MOVE R5 R4 - 0x7C140000, // 002F CALL R5 0 - 0x94180405, // 0030 GETIDX R6 R2 R5 - 0x1C180D02, // 0031 EQ R6 R6 K2 - 0x781A0002, // 0032 JMPF R6 #0036 - 0x8C18070A, // 0033 GETMET R6 R3 K10 - 0x5C200A00, // 0034 MOVE R8 R5 - 0x7C180400, // 0035 CALL R6 2 - 0x7001FFF6, // 0036 JMP #002E - 0x58100003, // 0037 LDCONST R4 K3 - 0xAC100200, // 0038 CATCH R4 1 0 - 0xB0080000, // 0039 RAISE 2 R0 R0 - 0x60100010, // 003A GETGBL R4 G16 - 0x5C140600, // 003B MOVE R5 R3 - 0x7C100200, // 003C CALL R4 1 - 0xA802000E, // 003D EXBLK 0 #004D - 0x5C140800, // 003E MOVE R5 R4 - 0x7C140000, // 003F CALL R5 0 - 0xB81A1600, // 0040 GETNGBL R6 K11 - 0x8C180D0C, // 0041 GETMET R6 R6 K12 - 0x88200B0E, // 0042 GETMBR R8 R5 K14 - 0x00221A08, // 0043 ADD R8 K13 R8 - 0x5824000F, // 0044 LDCONST R9 K15 - 0x7C180600, // 0045 CALL R6 3 - 0x8C180B10, // 0046 GETMET R6 R5 K16 - 0x7C180200, // 0047 CALL R6 1 - 0x88180101, // 0048 GETMBR R6 R0 K1 - 0x8C180D11, // 0049 GETMET R6 R6 K17 - 0x88200B0E, // 004A GETMBR R8 R5 K14 - 0x7C180400, // 004B CALL R6 2 - 0x7001FFF0, // 004C JMP #003E - 0x58100003, // 004D LDCONST R4 K3 - 0xAC100200, // 004E CATCH R4 1 0 - 0xB0080000, // 004F RAISE 2 R0 R0 - 0x80000000, // 0050 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: every_250ms -********************************************************************/ -be_local_closure(Matter_Device_every_250ms, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(message_handler), - /* K1 */ be_nested_str_weak(every_250ms), - /* K2 */ be_nested_str_weak(read_sensors_scheduler), - /* K3 */ be_const_int(0), - /* K4 */ be_nested_str_weak(plugins), - /* K5 */ be_const_int(1), - }), - be_str_weak(every_250ms), - &be_const_str_solidified, - ( &(const binstruction[18]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x7C040200, // 0002 CALL R1 1 - 0x8C040102, // 0003 GETMET R1 R0 K2 - 0x7C040200, // 0004 CALL R1 1 - 0x58040003, // 0005 LDCONST R1 K3 - 0x6008000C, // 0006 GETGBL R2 G12 - 0x880C0104, // 0007 GETMBR R3 R0 K4 - 0x7C080200, // 0008 CALL R2 1 - 0x14080202, // 0009 LT R2 R1 R2 - 0x780A0005, // 000A JMPF R2 #0011 - 0x88080104, // 000B GETMBR R2 R0 K4 - 0x94080401, // 000C GETIDX R2 R2 R1 - 0x8C080501, // 000D GETMET R2 R2 K1 - 0x7C080200, // 000E CALL R2 1 - 0x00040305, // 000F ADD R1 R1 K5 - 0x7001FFF4, // 0010 JMP #0006 - 0x80000000, // 0011 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: read_sensors_scheduler -********************************************************************/ -be_local_closure(Matter_Device_read_sensors_scheduler, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_nested_str_weak(probe_sensor_time), - /* K1 */ be_nested_str_weak(probe_sensor_timestamp), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(tasmota), - /* K4 */ be_nested_str_weak(time_reached), - /* K5 */ be_nested_str_weak(_trigger_read_sensors), - /* K6 */ be_nested_str_weak(millis), - }), - be_str_weak(read_sensors_scheduler), - &be_const_str_solidified, - ( &(const binstruction[21]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x4C080000, // 0001 LDNIL R2 - 0x1C040202, // 0002 EQ R1 R1 R2 - 0x78060000, // 0003 JMPF R1 #0005 - 0x80000200, // 0004 RET 0 - 0x88040101, // 0005 GETMBR R1 R0 K1 - 0x1C040302, // 0006 EQ R1 R1 K2 - 0x74060004, // 0007 JMPT R1 #000D - 0xB8060600, // 0008 GETNGBL R1 K3 - 0x8C040304, // 0009 GETMET R1 R1 K4 - 0x880C0101, // 000A GETMBR R3 R0 K1 - 0x7C040400, // 000B CALL R1 2 - 0x78060006, // 000C JMPF R1 #0014 - 0x8C040105, // 000D GETMET R1 R0 K5 - 0x7C040200, // 000E CALL R1 1 - 0xB8060600, // 000F GETNGBL R1 K3 - 0x8C040306, // 0010 GETMET R1 R1 K6 - 0x880C0100, // 0011 GETMBR R3 R0 K0 - 0x7C040400, // 0012 CALL R1 2 - 0x90020201, // 0013 SETMBR R0 K1 R1 - 0x80000000, // 0014 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: mdns_announce_op_discovery -********************************************************************/ -be_local_closure(Matter_Device_mdns_announce_op_discovery, /* name */ - be_nested_proto( - 14, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[27]) { /* constants */ - /* K0 */ be_nested_str_weak(mdns), - /* K1 */ be_nested_str_weak(get_device_id), - /* K2 */ be_nested_str_weak(copy), - /* K3 */ be_nested_str_weak(reverse), - /* K4 */ be_nested_str_weak(get_fabric_compressed), - /* K5 */ be_nested_str_weak(tohex), - /* K6 */ be_nested_str_weak(_X2D), - /* K7 */ be_nested_str_weak(tasmota), - /* K8 */ be_nested_str_weak(log), - /* K9 */ be_nested_str_weak(MTR_X3A_X20Operational_X20Discovery_X20node_X20_X3D_X20), - /* K10 */ be_const_int(3), - /* K11 */ be_nested_str_weak(eth), - /* K12 */ be_nested_str_weak(find), - /* K13 */ be_nested_str_weak(up), - /* K14 */ be_nested_str_weak(MTR_X3A_X20adding_X20mDNS_X20on_X20_X25s_X20_X27_X25s_X27_X20ptr_X20to_X20_X60_X25s_X2Elocal_X60), - /* K15 */ be_nested_str_weak(hostname_eth), - /* K16 */ be_nested_str_weak(add_service), - /* K17 */ be_nested_str_weak(_matter), - /* K18 */ be_nested_str_weak(_tcp), - /* K19 */ be_nested_str_weak(_I), - /* K20 */ be_nested_str_weak(MTR_X3A_X20adding_X20subtype_X3A_X20), - /* K21 */ be_nested_str_weak(add_subtype), - /* K22 */ be_nested_str_weak(wifi), - /* K23 */ be_nested_str_weak(hostname_wifi), - /* K24 */ be_nested_str_weak(MTR_X3A_X20Exception), - /* K25 */ be_nested_str_weak(_X7C), - /* K26 */ be_const_int(2), - }), - be_str_weak(mdns_announce_op_discovery), - &be_const_str_solidified, - ( &(const binstruction[121]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0xA8020064, // 0001 EXBLK 0 #0067 - 0x8C0C0301, // 0002 GETMET R3 R1 K1 - 0x7C0C0200, // 0003 CALL R3 1 - 0x8C0C0702, // 0004 GETMET R3 R3 K2 - 0x7C0C0200, // 0005 CALL R3 1 - 0x8C0C0703, // 0006 GETMET R3 R3 K3 - 0x7C0C0200, // 0007 CALL R3 1 - 0x8C100304, // 0008 GETMET R4 R1 K4 - 0x7C100200, // 0009 CALL R4 1 - 0x8C140905, // 000A GETMET R5 R4 K5 - 0x7C140200, // 000B CALL R5 1 - 0x00140B06, // 000C ADD R5 R5 K6 - 0x8C180705, // 000D GETMET R6 R3 K5 - 0x7C180200, // 000E CALL R6 1 - 0x00140A06, // 000F ADD R5 R5 R6 - 0xB81A0E00, // 0010 GETNGBL R6 K7 - 0x8C180D08, // 0011 GETMET R6 R6 K8 - 0x00221205, // 0012 ADD R8 K9 R5 - 0x5824000A, // 0013 LDCONST R9 K10 - 0x7C180600, // 0014 CALL R6 3 - 0xB81A0E00, // 0015 GETNGBL R6 K7 - 0x8C180D0B, // 0016 GETMET R6 R6 K11 - 0x7C180200, // 0017 CALL R6 1 - 0x8C180D0C, // 0018 GETMET R6 R6 K12 - 0x5820000D, // 0019 LDCONST R8 K13 - 0x7C180400, // 001A CALL R6 2 - 0x781A0020, // 001B JMPF R6 #003D - 0xB81A0E00, // 001C GETNGBL R6 K7 - 0x8C180D08, // 001D GETMET R6 R6 K8 - 0x60200018, // 001E GETGBL R8 G24 - 0x5824000E, // 001F LDCONST R9 K14 - 0x5828000B, // 0020 LDCONST R10 K11 - 0x5C2C0A00, // 0021 MOVE R11 R5 - 0x8830010F, // 0022 GETMBR R12 R0 K15 - 0x7C200800, // 0023 CALL R8 4 - 0x5824000A, // 0024 LDCONST R9 K10 - 0x7C180600, // 0025 CALL R6 3 - 0x8C180510, // 0026 GETMET R6 R2 K16 - 0x58200011, // 0027 LDCONST R8 K17 - 0x58240012, // 0028 LDCONST R9 K18 - 0x542A15A3, // 0029 LDINT R10 5540 - 0x4C2C0000, // 002A LDNIL R11 - 0x5C300A00, // 002B MOVE R12 R5 - 0x8834010F, // 002C GETMBR R13 R0 K15 - 0x7C180E00, // 002D CALL R6 7 - 0x8C180905, // 002E GETMET R6 R4 K5 - 0x7C180200, // 002F CALL R6 1 - 0x001A2606, // 0030 ADD R6 K19 R6 - 0xB81E0E00, // 0031 GETNGBL R7 K7 - 0x8C1C0F08, // 0032 GETMET R7 R7 K8 - 0x00262806, // 0033 ADD R9 K20 R6 - 0x5828000A, // 0034 LDCONST R10 K10 - 0x7C1C0600, // 0035 CALL R7 3 - 0x8C1C0515, // 0036 GETMET R7 R2 K21 - 0x58240011, // 0037 LDCONST R9 K17 - 0x58280012, // 0038 LDCONST R10 K18 - 0x5C2C0A00, // 0039 MOVE R11 R5 - 0x8830010F, // 003A GETMBR R12 R0 K15 - 0x5C340C00, // 003B MOVE R13 R6 - 0x7C1C0C00, // 003C CALL R7 6 - 0xB81A0E00, // 003D GETNGBL R6 K7 - 0x8C180D16, // 003E GETMET R6 R6 K22 - 0x7C180200, // 003F CALL R6 1 - 0x8C180D0C, // 0040 GETMET R6 R6 K12 - 0x5820000D, // 0041 LDCONST R8 K13 - 0x7C180400, // 0042 CALL R6 2 - 0x781A0020, // 0043 JMPF R6 #0065 - 0xB81A0E00, // 0044 GETNGBL R6 K7 - 0x8C180D08, // 0045 GETMET R6 R6 K8 - 0x60200018, // 0046 GETGBL R8 G24 - 0x5824000E, // 0047 LDCONST R9 K14 - 0x58280016, // 0048 LDCONST R10 K22 - 0x5C2C0A00, // 0049 MOVE R11 R5 - 0x88300117, // 004A GETMBR R12 R0 K23 - 0x7C200800, // 004B CALL R8 4 - 0x5824000A, // 004C LDCONST R9 K10 - 0x7C180600, // 004D CALL R6 3 - 0x8C180510, // 004E GETMET R6 R2 K16 - 0x58200011, // 004F LDCONST R8 K17 - 0x58240012, // 0050 LDCONST R9 K18 - 0x542A15A3, // 0051 LDINT R10 5540 - 0x4C2C0000, // 0052 LDNIL R11 - 0x5C300A00, // 0053 MOVE R12 R5 - 0x88340117, // 0054 GETMBR R13 R0 K23 - 0x7C180E00, // 0055 CALL R6 7 - 0x8C180905, // 0056 GETMET R6 R4 K5 - 0x7C180200, // 0057 CALL R6 1 - 0x001A2606, // 0058 ADD R6 K19 R6 - 0xB81E0E00, // 0059 GETNGBL R7 K7 - 0x8C1C0F08, // 005A GETMET R7 R7 K8 - 0x00262806, // 005B ADD R9 K20 R6 - 0x5828000A, // 005C LDCONST R10 K10 - 0x7C1C0600, // 005D CALL R7 3 - 0x8C1C0515, // 005E GETMET R7 R2 K21 - 0x58240011, // 005F LDCONST R9 K17 - 0x58280012, // 0060 LDCONST R10 K18 - 0x5C2C0A00, // 0061 MOVE R11 R5 - 0x88300117, // 0062 GETMBR R12 R0 K23 - 0x5C340C00, // 0063 MOVE R13 R6 - 0x7C1C0C00, // 0064 CALL R7 6 - 0xA8040001, // 0065 EXBLK 1 1 - 0x70020010, // 0066 JMP #0078 - 0xAC0C0002, // 0067 CATCH R3 0 2 - 0x7002000D, // 0068 JMP #0077 - 0xB8160E00, // 0069 GETNGBL R5 K7 - 0x8C140B08, // 006A GETMET R5 R5 K8 - 0x601C0008, // 006B GETGBL R7 G8 - 0x5C200600, // 006C MOVE R8 R3 - 0x7C1C0200, // 006D CALL R7 1 - 0x001E3007, // 006E ADD R7 K24 R7 - 0x001C0F19, // 006F ADD R7 R7 K25 - 0x60200008, // 0070 GETGBL R8 G8 - 0x5C240800, // 0071 MOVE R9 R4 - 0x7C200200, // 0072 CALL R8 1 - 0x001C0E08, // 0073 ADD R7 R7 R8 - 0x5820001A, // 0074 LDCONST R8 K26 - 0x7C140600, // 0075 CALL R5 3 - 0x70020000, // 0076 JMP #0078 - 0xB0080000, // 0077 RAISE 2 R0 R0 - 0x80000000, // 0078 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: MtrJoin -********************************************************************/ -be_local_closure(Matter_Device_MtrJoin, /* name */ - be_nested_proto( - 8, /* nstack */ - 5, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(start_root_basic_commissioning), - /* K1 */ be_nested_str_weak(stop_basic_commissioning), - /* K2 */ be_nested_str_weak(tasmota), - /* K3 */ be_nested_str_weak(resp_cmnd_done), - }), - be_str_weak(MtrJoin), - &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x60140009, // 0000 GETGBL R5 G9 - 0x5C180600, // 0001 MOVE R6 R3 - 0x7C140200, // 0002 CALL R5 1 - 0x78160002, // 0003 JMPF R5 #0007 - 0x8C180100, // 0004 GETMET R6 R0 K0 - 0x7C180200, // 0005 CALL R6 1 - 0x70020001, // 0006 JMP #0009 - 0x8C180101, // 0007 GETMET R6 R0 K1 - 0x7C180200, // 0008 CALL R6 1 - 0xB81A0400, // 0009 GETNGBL R6 K2 - 0x8C180D03, // 000A GETMET R6 R6 K3 - 0x7C180200, // 000B CALL R6 1 - 0x80000000, // 000C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: remove_fabric -********************************************************************/ -be_local_closure(Matter_Device_remove_fabric, /* name */ +be_local_closure(Matter_Device_get_plugin_remote_info, /* name */ be_nested_proto( 6, /* nstack */ 2, /* argc */ @@ -4306,753 +6209,20 @@ be_local_closure(Matter_Device_remove_fabric, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[16]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(log), - /* K2 */ be_nested_str_weak(MTR_X3A_X20removing_X20fabric_X20), - /* K3 */ be_nested_str_weak(get_fabric_id), - /* K4 */ be_nested_str_weak(copy), - /* K5 */ be_nested_str_weak(reverse), - /* K6 */ be_nested_str_weak(tohex), - /* K7 */ be_const_int(2), - /* K8 */ be_nested_str_weak(message_handler), - /* K9 */ be_nested_str_weak(im), - /* K10 */ be_nested_str_weak(subs_shop), - /* K11 */ be_nested_str_weak(remove_by_fabric), - /* K12 */ be_nested_str_weak(mdns_remove_op_discovery), - /* K13 */ be_nested_str_weak(sessions), - /* K14 */ be_nested_str_weak(remove_fabric), - /* K15 */ be_nested_str_weak(save_fabrics), - }), - be_str_weak(remove_fabric), - &be_const_str_solidified, - ( &(const binstruction[33]) { /* code */ - 0x4C080000, // 0000 LDNIL R2 - 0x20080202, // 0001 NE R2 R1 R2 - 0x780A0019, // 0002 JMPF R2 #001D - 0xB80A0000, // 0003 GETNGBL R2 K0 - 0x8C080501, // 0004 GETMET R2 R2 K1 - 0x8C100303, // 0005 GETMET R4 R1 K3 - 0x7C100200, // 0006 CALL R4 1 - 0x8C100904, // 0007 GETMET R4 R4 K4 - 0x7C100200, // 0008 CALL R4 1 - 0x8C100905, // 0009 GETMET R4 R4 K5 - 0x7C100200, // 000A CALL R4 1 - 0x8C100906, // 000B GETMET R4 R4 K6 - 0x7C100200, // 000C CALL R4 1 - 0x00120404, // 000D ADD R4 K2 R4 - 0x58140007, // 000E LDCONST R5 K7 - 0x7C080600, // 000F CALL R2 3 - 0x88080108, // 0010 GETMBR R2 R0 K8 - 0x88080509, // 0011 GETMBR R2 R2 K9 - 0x8808050A, // 0012 GETMBR R2 R2 K10 - 0x8C08050B, // 0013 GETMET R2 R2 K11 - 0x5C100200, // 0014 MOVE R4 R1 - 0x7C080400, // 0015 CALL R2 2 - 0x8C08010C, // 0016 GETMET R2 R0 K12 - 0x5C100200, // 0017 MOVE R4 R1 - 0x7C080400, // 0018 CALL R2 2 - 0x8808010D, // 0019 GETMBR R2 R0 K13 - 0x8C08050E, // 001A GETMET R2 R2 K14 - 0x5C100200, // 001B MOVE R4 R1 - 0x7C080400, // 001C CALL R2 2 - 0x8808010D, // 001D GETMBR R2 R0 K13 - 0x8C08050F, // 001E GETMET R2 R2 K15 - 0x7C080200, // 001F CALL R2 1 - 0x80000000, // 0020 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: _compute_pbkdf -********************************************************************/ -be_local_closure(Matter_Device__compute_pbkdf, /* name */ - be_nested_proto( - 13, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[10]) { /* constants */ - /* K0 */ be_nested_str_weak(crypto), - /* K1 */ be_nested_str_weak(add), - /* K2 */ be_nested_str_weak(PBKDF2_HMAC_SHA256), - /* K3 */ be_nested_str_weak(derive), - /* K4 */ be_const_int(0), - /* K5 */ be_nested_str_weak(root_w0), - /* K6 */ be_nested_str_weak(EC_P256), - /* K7 */ be_nested_str_weak(mod), - /* K8 */ be_nested_str_weak(root_L), - /* K9 */ be_nested_str_weak(public_key), - }), - be_str_weak(_compute_pbkdf), - &be_const_str_solidified, - ( &(const binstruction[40]) { /* code */ - 0xA4120000, // 0000 IMPORT R4 K0 - 0x60140015, // 0001 GETGBL R5 G21 - 0x7C140000, // 0002 CALL R5 0 - 0x8C140B01, // 0003 GETMET R5 R5 K1 - 0x5C1C0200, // 0004 MOVE R7 R1 - 0x54220003, // 0005 LDINT R8 4 - 0x7C140600, // 0006 CALL R5 3 - 0x8C180902, // 0007 GETMET R6 R4 K2 - 0x7C180200, // 0008 CALL R6 1 - 0x8C180D03, // 0009 GETMET R6 R6 K3 - 0x5C200A00, // 000A MOVE R8 R5 - 0x5C240600, // 000B MOVE R9 R3 - 0x5C280400, // 000C MOVE R10 R2 - 0x542E004F, // 000D LDINT R11 80 - 0x7C180A00, // 000E CALL R6 5 - 0x541E0026, // 000F LDINT R7 39 - 0x401E0807, // 0010 CONNECT R7 K4 R7 - 0x941C0C07, // 0011 GETIDX R7 R6 R7 - 0x54220027, // 0012 LDINT R8 40 - 0x5426004E, // 0013 LDINT R9 79 - 0x40201009, // 0014 CONNECT R8 R8 R9 - 0x94200C08, // 0015 GETIDX R8 R6 R8 - 0x8C240906, // 0016 GETMET R9 R4 K6 - 0x7C240200, // 0017 CALL R9 1 - 0x8C241307, // 0018 GETMET R9 R9 K7 - 0x5C2C0E00, // 0019 MOVE R11 R7 - 0x7C240400, // 001A CALL R9 2 - 0x90020A09, // 001B SETMBR R0 K5 R9 - 0x8C240906, // 001C GETMET R9 R4 K6 - 0x7C240200, // 001D CALL R9 1 - 0x8C241307, // 001E GETMET R9 R9 K7 - 0x5C2C1000, // 001F MOVE R11 R8 - 0x7C240400, // 0020 CALL R9 2 - 0x8C280906, // 0021 GETMET R10 R4 K6 - 0x7C280200, // 0022 CALL R10 1 - 0x8C281509, // 0023 GETMET R10 R10 K9 - 0x5C301200, // 0024 MOVE R12 R9 - 0x7C280400, // 0025 CALL R10 2 - 0x9002100A, // 0026 SETMBR R0 K8 R10 - 0x80000000, // 0027 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: _init_basic_commissioning -********************************************************************/ -be_local_closure(Matter_Device__init_basic_commissioning, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(sessions), - /* K1 */ be_nested_str_weak(count_active_fabrics), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(start_root_basic_commissioning), - }), - be_str_weak(_init_basic_commissioning), - &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x7C040200, // 0002 CALL R1 1 - 0x1C040302, // 0003 EQ R1 R1 K2 - 0x78060001, // 0004 JMPF R1 #0007 - 0x8C040103, // 0005 GETMET R1 R0 K3 - 0x7C040200, // 0006 CALL R1 1 - 0x80000000, // 0007 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: msg_received -********************************************************************/ -be_local_closure(Matter_Device_msg_received, /* name */ - be_nested_proto( - 9, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(message_handler), - /* K1 */ be_nested_str_weak(msg_received), + /* K0 */ be_nested_str_weak(plugins_config_remotes), + /* K1 */ be_nested_str_weak(find), }), - be_str_weak(msg_received), + be_str_weak(get_plugin_remote_info), &be_const_str_solidified, ( &(const binstruction[ 7]) { /* code */ - 0x88100100, // 0000 GETMBR R4 R0 K0 - 0x8C100901, // 0001 GETMET R4 R4 K1 - 0x5C180200, // 0002 MOVE R6 R1 - 0x5C1C0400, // 0003 MOVE R7 R2 - 0x5C200600, // 0004 MOVE R8 R3 - 0x7C100800, // 0005 CALL R4 4 - 0x80040800, // 0006 RET 1 R4 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: register_commands -********************************************************************/ -be_local_closure(Matter_Device_register_commands, /* name */ - be_nested_proto( - 5, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 3]) { - be_nested_proto( - 10, /* nstack */ - 4, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(MtrJoin), - }), - be_str_weak(_X3Clambda_X3E), - &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x68100000, // 0000 GETUPV R4 U0 - 0x8C100900, // 0001 GETMET R4 R4 K0 - 0x5C180000, // 0002 MOVE R6 R0 - 0x5C1C0200, // 0003 MOVE R7 R1 - 0x5C200400, // 0004 MOVE R8 R2 - 0x5C240600, // 0005 MOVE R9 R3 - 0x7C100A00, // 0006 CALL R4 5 - 0x80040800, // 0007 RET 1 R4 - }) - ), - be_nested_proto( - 10, /* nstack */ - 4, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(MtrUpdate), - }), - be_str_weak(_X3Clambda_X3E), - &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x68100000, // 0000 GETUPV R4 U0 - 0x8C100900, // 0001 GETMET R4 R4 K0 - 0x5C180000, // 0002 MOVE R6 R0 - 0x5C1C0200, // 0003 MOVE R7 R1 - 0x5C200400, // 0004 MOVE R8 R2 - 0x5C240600, // 0005 MOVE R9 R3 - 0x7C100A00, // 0006 CALL R4 5 - 0x80040800, // 0007 RET 1 R4 - }) - ), - be_nested_proto( - 10, /* nstack */ - 4, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(MtrInfo), - }), - be_str_weak(_X3Clambda_X3E), - &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x68100000, // 0000 GETUPV R4 U0 - 0x8C100900, // 0001 GETMET R4 R4 K0 - 0x5C180000, // 0002 MOVE R6 R0 - 0x5C1C0200, // 0003 MOVE R7 R1 - 0x5C200400, // 0004 MOVE R8 R2 - 0x5C240600, // 0005 MOVE R9 R3 - 0x7C100A00, // 0006 CALL R4 5 - 0x80040800, // 0007 RET 1 R4 - }) - ), - }), - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(add_cmd), - /* K2 */ be_nested_str_weak(MtrJoin), - /* K3 */ be_nested_str_weak(MtrUpdate), - /* K4 */ be_nested_str_weak(MtrInfo), - }), - be_str_weak(register_commands), - &be_const_str_solidified, - ( &(const binstruction[17]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x580C0002, // 0002 LDCONST R3 K2 - 0x84100000, // 0003 CLOSURE R4 P0 - 0x7C040600, // 0004 CALL R1 3 - 0xB8060000, // 0005 GETNGBL R1 K0 - 0x8C040301, // 0006 GETMET R1 R1 K1 - 0x580C0003, // 0007 LDCONST R3 K3 - 0x84100001, // 0008 CLOSURE R4 P1 - 0x7C040600, // 0009 CALL R1 3 - 0xB8060000, // 000A GETNGBL R1 K0 - 0x8C040301, // 000B GETMET R1 R1 K1 - 0x580C0004, // 000C LDCONST R3 K4 - 0x84100002, // 000D CLOSURE R4 P2 - 0x7C040600, // 000E CALL R1 3 - 0xA0000000, // 000F CLOSE R0 - 0x80000000, // 0010 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: is_commissioning_open -********************************************************************/ -be_local_closure(Matter_Device_is_commissioning_open, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(commissioning_open), - }), - be_str_weak(is_commissioning_open), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x4C080000, // 0001 LDNIL R2 - 0x20040202, // 0002 NE R1 R1 R2 - 0x80040200, // 0003 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: event_fabrics_saved -********************************************************************/ -be_local_closure(Matter_Device_event_fabrics_saved, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(sessions), - /* K1 */ be_nested_str_weak(count_active_fabrics), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(plugins_persist), - /* K4 */ be_nested_str_weak(save_param), - }), - be_str_weak(event_fabrics_saved), - &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x7C040200, // 0002 CALL R1 1 - 0x24040302, // 0003 GT R1 R1 K2 - 0x78060005, // 0004 JMPF R1 #000B - 0x88040103, // 0005 GETMBR R1 R0 K3 - 0x74060003, // 0006 JMPT R1 #000B - 0x50040200, // 0007 LDBOOL R1 1 0 - 0x90020601, // 0008 SETMBR R0 K3 R1 - 0x8C040104, // 0009 GETMET R1 R0 K4 - 0x7C040200, // 000A CALL R1 1 - 0x80000000, // 000B RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: MtrUpdate -********************************************************************/ -be_local_closure(Matter_Device_MtrUpdate, /* name */ - be_nested_proto( - 18, /* nstack */ - 5, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[25]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(resp_cmnd_str), - /* K2 */ be_nested_str_weak(Invalid_X20JSON), - /* K3 */ be_nested_str_weak(find_key_i), - /* K4 */ be_nested_str_weak(Ep), - /* K5 */ be_nested_str_weak(Name), - /* K6 */ be_const_int(0), - /* K7 */ be_nested_str_weak(Invalid_X20_X27Ep_X27_X20attribute), - /* K8 */ be_nested_str_weak(find_plugin_by_endpoint), - /* K9 */ be_nested_str_weak(remove), - /* K10 */ be_nested_str_weak(find_plugin_by_friendly_name), - /* K11 */ be_nested_str_weak(Invalid_X20Device), - /* K12 */ be_nested_str_weak(VIRTUAL), - /* K13 */ be_nested_str_weak(Device_X20is_X20not_X20virtual), - /* K14 */ be_nested_str_weak(consolidate_update_commands), - /* K15 */ be_nested_str_weak(keys), - /* K16 */ be_nested_str_weak(find_list_i), - /* K17 */ be_nested_str_weak(Invalid_X20attribute_X20_X27_X25s_X27), - /* K18 */ be_nested_str_weak(stop_iteration), - /* K19 */ be_nested_str_weak(update_virtual), - /* K20 */ be_nested_str_weak(state_json), - /* K21 */ be_nested_str_weak(_X7B_X22_X25s_X22_X3A_X25s_X7D), - /* K22 */ be_nested_str_weak(resp_cmnd), - /* K23 */ be_nested_str_weak(resp_cmnd_done), - /* K24 */ be_nested_str_weak(Missing_X20_X27Device_X27_X20attribute), - }), - be_str_weak(MtrUpdate), - &be_const_str_solidified, - ( &(const binstruction[126]) { /* code */ - 0x4C140000, // 0000 LDNIL R5 - 0x1C140805, // 0001 EQ R5 R4 R5 - 0x78160004, // 0002 JMPF R5 #0008 - 0xB8160000, // 0003 GETNGBL R5 K0 - 0x8C140B01, // 0004 GETMET R5 R5 K1 - 0x581C0002, // 0005 LDCONST R7 K2 - 0x7C140400, // 0006 CALL R5 2 - 0x80040A00, // 0007 RET 1 R5 - 0xB8160000, // 0008 GETNGBL R5 K0 - 0x8C140B03, // 0009 GETMET R5 R5 K3 - 0x5C1C0800, // 000A MOVE R7 R4 - 0x58200004, // 000B LDCONST R8 K4 - 0x7C140600, // 000C CALL R5 3 - 0xB81A0000, // 000D GETNGBL R6 K0 - 0x8C180D03, // 000E GETMET R6 R6 K3 - 0x5C200800, // 000F MOVE R8 R4 - 0x58240005, // 0010 LDCONST R9 K5 - 0x7C180600, // 0011 CALL R6 3 - 0x74160000, // 0012 JMPT R5 #0014 - 0x781A0064, // 0013 JMPF R6 #0079 - 0x4C1C0000, // 0014 LDNIL R7 - 0x78160010, // 0015 JMPF R5 #0027 - 0x60200009, // 0016 GETGBL R8 G9 - 0x94240805, // 0017 GETIDX R9 R4 R5 - 0x7C200200, // 0018 CALL R8 1 - 0x18241106, // 0019 LE R9 R8 K6 - 0x78260004, // 001A JMPF R9 #0020 - 0xB8260000, // 001B GETNGBL R9 K0 - 0x8C241301, // 001C GETMET R9 R9 K1 - 0x582C0007, // 001D LDCONST R11 K7 - 0x7C240400, // 001E CALL R9 2 - 0x80041200, // 001F RET 1 R9 - 0x8C240108, // 0020 GETMET R9 R0 K8 - 0x5C2C1000, // 0021 MOVE R11 R8 - 0x7C240400, // 0022 CALL R9 2 - 0x5C1C1200, // 0023 MOVE R7 R9 - 0x8C240909, // 0024 GETMET R9 R4 K9 - 0x5C2C0A00, // 0025 MOVE R11 R5 - 0x7C240400, // 0026 CALL R9 2 - 0x781A0009, // 0027 JMPF R6 #0032 - 0x4C200000, // 0028 LDNIL R8 - 0x1C200E08, // 0029 EQ R8 R7 R8 - 0x78220003, // 002A JMPF R8 #002F - 0x8C20010A, // 002B GETMET R8 R0 K10 - 0x94280806, // 002C GETIDX R10 R4 R6 - 0x7C200400, // 002D CALL R8 2 - 0x5C1C1000, // 002E MOVE R7 R8 - 0x8C200909, // 002F GETMET R8 R4 K9 - 0x5C280C00, // 0030 MOVE R10 R6 - 0x7C200400, // 0031 CALL R8 2 - 0x4C200000, // 0032 LDNIL R8 - 0x1C200E08, // 0033 EQ R8 R7 R8 - 0x78220004, // 0034 JMPF R8 #003A - 0xB8220000, // 0035 GETNGBL R8 K0 - 0x8C201101, // 0036 GETMET R8 R8 K1 - 0x5828000B, // 0037 LDCONST R10 K11 - 0x7C200400, // 0038 CALL R8 2 - 0x80041000, // 0039 RET 1 R8 - 0x88200F0C, // 003A GETMBR R8 R7 K12 - 0x74220004, // 003B JMPT R8 #0041 - 0xB8220000, // 003C GETNGBL R8 K0 - 0x8C201101, // 003D GETMET R8 R8 K1 - 0x5828000D, // 003E LDCONST R10 K13 - 0x7C200400, // 003F CALL R8 2 - 0x80041000, // 0040 RET 1 R8 - 0x8C200F0E, // 0041 GETMET R8 R7 K14 - 0x7C200200, // 0042 CALL R8 1 - 0x60240013, // 0043 GETGBL R9 G19 - 0x7C240000, // 0044 CALL R9 0 - 0x60280010, // 0045 GETGBL R10 G16 - 0x8C2C090F, // 0046 GETMET R11 R4 K15 - 0x7C2C0200, // 0047 CALL R11 1 - 0x7C280200, // 0048 CALL R10 1 - 0xA8020016, // 0049 EXBLK 0 #0061 - 0x5C2C1400, // 004A MOVE R11 R10 - 0x7C2C0000, // 004B CALL R11 0 - 0xB8320000, // 004C GETNGBL R12 K0 - 0x8C301910, // 004D GETMET R12 R12 K16 - 0x5C381000, // 004E MOVE R14 R8 - 0x5C3C1600, // 004F MOVE R15 R11 - 0x7C300600, // 0050 CALL R12 3 - 0x4C340000, // 0051 LDNIL R13 - 0x1C34180D, // 0052 EQ R13 R12 R13 - 0x78360008, // 0053 JMPF R13 #005D - 0xB8360000, // 0054 GETNGBL R13 K0 - 0x8C341B01, // 0055 GETMET R13 R13 K1 - 0x603C0018, // 0056 GETGBL R15 G24 - 0x58400011, // 0057 LDCONST R16 K17 - 0x5C441600, // 0058 MOVE R17 R11 - 0x7C3C0400, // 0059 CALL R15 2 - 0x7C340400, // 005A CALL R13 2 - 0xA8040001, // 005B EXBLK 1 1 - 0x80001A00, // 005C RET 0 - 0x9434100C, // 005D GETIDX R13 R8 R12 - 0x9438080B, // 005E GETIDX R14 R4 R11 - 0x98241A0E, // 005F SETIDX R9 R13 R14 - 0x7001FFE8, // 0060 JMP #004A - 0x58280012, // 0061 LDCONST R10 K18 - 0xAC280200, // 0062 CATCH R10 1 0 - 0xB0080000, // 0063 RAISE 2 R0 R0 - 0x8C280F13, // 0064 GETMET R10 R7 K19 - 0x5C301200, // 0065 MOVE R12 R9 - 0x7C280400, // 0066 CALL R10 2 - 0x8C280F14, // 0067 GETMET R10 R7 K20 - 0x7C280200, // 0068 CALL R10 1 - 0x782A000A, // 0069 JMPF R10 #0075 - 0x602C0018, // 006A GETGBL R11 G24 - 0x58300015, // 006B LDCONST R12 K21 - 0x5C340200, // 006C MOVE R13 R1 - 0x5C381400, // 006D MOVE R14 R10 - 0x7C2C0600, // 006E CALL R11 3 - 0xB8320000, // 006F GETNGBL R12 K0 - 0x8C301916, // 0070 GETMET R12 R12 K22 - 0x5C381600, // 0071 MOVE R14 R11 - 0x7C300400, // 0072 CALL R12 2 - 0x80041800, // 0073 RET 1 R12 - 0x70020003, // 0074 JMP #0079 - 0xB82E0000, // 0075 GETNGBL R11 K0 - 0x8C2C1717, // 0076 GETMET R11 R11 K23 - 0x7C2C0200, // 0077 CALL R11 1 - 0x80041600, // 0078 RET 1 R11 - 0xB81E0000, // 0079 GETNGBL R7 K0 - 0x8C1C0F01, // 007A GETMET R7 R7 K1 - 0x58240018, // 007B LDCONST R9 K24 - 0x7C1C0400, // 007C CALL R7 2 - 0x80000000, // 007D RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: find_plugin_by_endpoint -********************************************************************/ -be_local_closure(Matter_Device_find_plugin_by_endpoint, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str_weak(plugins), - /* K2 */ be_nested_str_weak(get_endpoint), - /* K3 */ be_const_int(1), - }), - be_str_weak(find_plugin_by_endpoint), - &be_const_str_solidified, - ( &(const binstruction[17]) { /* code */ - 0x58080000, // 0000 LDCONST R2 K0 - 0x600C000C, // 0001 GETGBL R3 G12 - 0x88100101, // 0002 GETMBR R4 R0 K1 - 0x7C0C0200, // 0003 CALL R3 1 - 0x140C0403, // 0004 LT R3 R2 R3 - 0x780E0008, // 0005 JMPF R3 #000F - 0x880C0101, // 0006 GETMBR R3 R0 K1 - 0x940C0602, // 0007 GETIDX R3 R3 R2 - 0x8C100702, // 0008 GETMET R4 R3 K2 - 0x7C100200, // 0009 CALL R4 1 - 0x1C100801, // 000A EQ R4 R4 R1 - 0x78120000, // 000B JMPF R4 #000D - 0x80040600, // 000C RET 1 R3 - 0x00080503, // 000D ADD R2 R2 K3 - 0x7001FFF1, // 000E JMP #0001 - 0x4C0C0000, // 000F LDNIL R3 - 0x80040600, // 0010 RET 1 R3 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: start_mdns_announce_hostnames -********************************************************************/ -be_local_closure(Matter_Device_start_mdns_announce_hostnames, /* name */ - be_nested_proto( - 6, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 2]) { - be_nested_proto( - 4, /* nstack */ - 0, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(_mdns_announce_hostname), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(remove_rule), - /* K3 */ be_nested_str_weak(Wifi_X23Connected), - /* K4 */ be_nested_str_weak(matter_mdns_host), - }), - be_str_weak(_anonymous_), - &be_const_str_solidified, - ( &(const binstruction[10]) { /* code */ - 0x68000000, // 0000 GETUPV R0 U0 - 0x8C000100, // 0001 GETMET R0 R0 K0 - 0x50080000, // 0002 LDBOOL R2 0 0 - 0x7C000400, // 0003 CALL R0 2 - 0xB8020200, // 0004 GETNGBL R0 K1 - 0x8C000102, // 0005 GETMET R0 R0 K2 - 0x58080003, // 0006 LDCONST R2 K3 - 0x580C0004, // 0007 LDCONST R3 K4 - 0x7C000600, // 0008 CALL R0 3 - 0x80000000, // 0009 RET 0 - }) - ), - be_nested_proto( - 4, /* nstack */ - 0, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(_mdns_announce_hostname), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(remove_rule), - /* K3 */ be_nested_str_weak(Eth_X23Connected), - /* K4 */ be_nested_str_weak(matter_mdns_host), - }), - be_str_weak(_anonymous_), - &be_const_str_solidified, - ( &(const binstruction[10]) { /* code */ - 0x68000000, // 0000 GETUPV R0 U0 - 0x8C000100, // 0001 GETMET R0 R0 K0 - 0x50080200, // 0002 LDBOOL R2 1 0 - 0x7C000400, // 0003 CALL R0 2 - 0xB8020200, // 0004 GETNGBL R0 K1 - 0x8C000102, // 0005 GETMET R0 R0 K2 - 0x58080003, // 0006 LDCONST R2 K3 - 0x580C0004, // 0007 LDCONST R3 K4 - 0x7C000600, // 0008 CALL R0 3 - 0x80000000, // 0009 RET 0 - }) - ), - }), - 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(wifi), - /* K2 */ be_nested_str_weak(up), - /* K3 */ be_nested_str_weak(_mdns_announce_hostname), - /* K4 */ be_nested_str_weak(add_rule), - /* K5 */ be_nested_str_weak(Wifi_X23Connected), - /* K6 */ be_nested_str_weak(matter_mdns_host), - /* K7 */ be_nested_str_weak(eth), - /* K8 */ be_nested_str_weak(Eth_X23Connected), - }), - be_str_weak(start_mdns_announce_hostnames), - &be_const_str_solidified, - ( &(const binstruction[32]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x7C040200, // 0002 CALL R1 1 - 0x94040302, // 0003 GETIDX R1 R1 K2 - 0x78060003, // 0004 JMPF R1 #0009 - 0x8C040103, // 0005 GETMET R1 R0 K3 - 0x500C0000, // 0006 LDBOOL R3 0 0 - 0x7C040400, // 0007 CALL R1 2 - 0x70020005, // 0008 JMP #000F - 0xB8060000, // 0009 GETNGBL R1 K0 - 0x8C040304, // 000A GETMET R1 R1 K4 - 0x580C0005, // 000B LDCONST R3 K5 - 0x84100000, // 000C CLOSURE R4 P0 - 0x58140006, // 000D LDCONST R5 K6 - 0x7C040800, // 000E CALL R1 4 - 0xB8060000, // 000F GETNGBL R1 K0 - 0x8C040307, // 0010 GETMET R1 R1 K7 - 0x7C040200, // 0011 CALL R1 1 - 0x94040302, // 0012 GETIDX R1 R1 K2 - 0x78060003, // 0013 JMPF R1 #0018 - 0x8C040103, // 0014 GETMET R1 R0 K3 - 0x500C0200, // 0015 LDBOOL R3 1 0 - 0x7C040400, // 0016 CALL R1 2 - 0x70020005, // 0017 JMP #001E - 0xB8060000, // 0018 GETNGBL R1 K0 - 0x8C040304, // 0019 GETMET R1 R1 K4 - 0x580C0008, // 001A LDCONST R3 K8 - 0x84100001, // 001B CLOSURE R4 P1 - 0x58140006, // 001C LDCONST R5 K6 - 0x7C040800, // 001D CALL R1 4 - 0xA0000000, // 001E CLOSE R0 - 0x80000000, // 001F RET 0 + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x60140013, // 0003 GETGBL R5 G19 + 0x7C140000, // 0004 CALL R5 0 + 0x7C080600, // 0005 CALL R2 3 + 0x80040400, // 0006 RET 1 R2 }) ) ); @@ -5089,1084 +6259,142 @@ be_local_closure(Matter_Device_every_50ms, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: stop -********************************************************************/ -be_local_closure(Matter_Device_stop, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(remove_driver), - /* K2 */ be_nested_str_weak(udp_server), - /* K3 */ be_nested_str_weak(stop), - }), - be_str_weak(stop), - &be_const_str_solidified, - ( &(const binstruction[10]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x5C0C0000, // 0002 MOVE R3 R0 - 0x7C040400, // 0003 CALL R1 2 - 0x88040102, // 0004 GETMBR R1 R0 K2 - 0x78060002, // 0005 JMPF R1 #0009 - 0x88040102, // 0006 GETMBR R1 R0 K2 - 0x8C040303, // 0007 GETMET R1 R1 K3 - 0x7C040200, // 0008 CALL R1 1 - 0x80000000, // 0009 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: mdns_remove_op_discovery -********************************************************************/ -be_local_closure(Matter_Device_mdns_remove_op_discovery, /* name */ - be_nested_proto( - 12, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[23]) { /* constants */ - /* K0 */ be_nested_str_weak(mdns), - /* K1 */ be_nested_str_weak(get_device_id), - /* K2 */ be_nested_str_weak(copy), - /* K3 */ be_nested_str_weak(reverse), - /* K4 */ be_nested_str_weak(get_fabric_compressed), - /* K5 */ be_nested_str_weak(tohex), - /* K6 */ be_nested_str_weak(_X2D), - /* K7 */ be_nested_str_weak(tasmota), - /* K8 */ be_nested_str_weak(eth), - /* K9 */ be_nested_str_weak(find), - /* K10 */ be_nested_str_weak(up), - /* K11 */ be_nested_str_weak(log), - /* K12 */ be_nested_str_weak(MTR_X3A_X20remove_X20mDNS_X20on_X20_X25s_X20_X27_X25s_X27), - /* K13 */ be_const_int(3), - /* K14 */ be_nested_str_weak(remove_service), - /* K15 */ be_nested_str_weak(_matter), - /* K16 */ be_nested_str_weak(_tcp), - /* K17 */ be_nested_str_weak(hostname_eth), - /* K18 */ be_nested_str_weak(wifi), - /* K19 */ be_nested_str_weak(hostname_wifi), - /* K20 */ be_nested_str_weak(MTR_X3A_X20Exception), - /* K21 */ be_nested_str_weak(_X7C), - /* K22 */ be_const_int(2), - }), - be_str_weak(mdns_remove_op_discovery), - &be_const_str_solidified, - ( &(const binstruction[80]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0xA802003B, // 0001 EXBLK 0 #003E - 0x8C0C0301, // 0002 GETMET R3 R1 K1 - 0x7C0C0200, // 0003 CALL R3 1 - 0x8C0C0702, // 0004 GETMET R3 R3 K2 - 0x7C0C0200, // 0005 CALL R3 1 - 0x8C0C0703, // 0006 GETMET R3 R3 K3 - 0x7C0C0200, // 0007 CALL R3 1 - 0x8C100304, // 0008 GETMET R4 R1 K4 - 0x7C100200, // 0009 CALL R4 1 - 0x8C140905, // 000A GETMET R5 R4 K5 - 0x7C140200, // 000B CALL R5 1 - 0x00140B06, // 000C ADD R5 R5 K6 - 0x8C180705, // 000D GETMET R6 R3 K5 - 0x7C180200, // 000E CALL R6 1 - 0x00140A06, // 000F ADD R5 R5 R6 - 0xB81A0E00, // 0010 GETNGBL R6 K7 - 0x8C180D08, // 0011 GETMET R6 R6 K8 - 0x7C180200, // 0012 CALL R6 1 - 0x8C180D09, // 0013 GETMET R6 R6 K9 - 0x5820000A, // 0014 LDCONST R8 K10 - 0x7C180400, // 0015 CALL R6 2 - 0x781A000E, // 0016 JMPF R6 #0026 - 0xB81A0E00, // 0017 GETNGBL R6 K7 - 0x8C180D0B, // 0018 GETMET R6 R6 K11 - 0x60200018, // 0019 GETGBL R8 G24 - 0x5824000C, // 001A LDCONST R9 K12 - 0x58280008, // 001B LDCONST R10 K8 - 0x5C2C0A00, // 001C MOVE R11 R5 - 0x7C200600, // 001D CALL R8 3 - 0x5824000D, // 001E LDCONST R9 K13 - 0x7C180600, // 001F CALL R6 3 - 0x8C18050E, // 0020 GETMET R6 R2 K14 - 0x5820000F, // 0021 LDCONST R8 K15 - 0x58240010, // 0022 LDCONST R9 K16 - 0x5C280A00, // 0023 MOVE R10 R5 - 0x882C0111, // 0024 GETMBR R11 R0 K17 - 0x7C180A00, // 0025 CALL R6 5 - 0xB81A0E00, // 0026 GETNGBL R6 K7 - 0x8C180D12, // 0027 GETMET R6 R6 K18 - 0x7C180200, // 0028 CALL R6 1 - 0x8C180D09, // 0029 GETMET R6 R6 K9 - 0x5820000A, // 002A LDCONST R8 K10 - 0x7C180400, // 002B CALL R6 2 - 0x781A000E, // 002C JMPF R6 #003C - 0xB81A0E00, // 002D GETNGBL R6 K7 - 0x8C180D0B, // 002E GETMET R6 R6 K11 - 0x60200018, // 002F GETGBL R8 G24 - 0x5824000C, // 0030 LDCONST R9 K12 - 0x58280012, // 0031 LDCONST R10 K18 - 0x5C2C0A00, // 0032 MOVE R11 R5 - 0x7C200600, // 0033 CALL R8 3 - 0x5824000D, // 0034 LDCONST R9 K13 - 0x7C180600, // 0035 CALL R6 3 - 0x8C18050E, // 0036 GETMET R6 R2 K14 - 0x5820000F, // 0037 LDCONST R8 K15 - 0x58240010, // 0038 LDCONST R9 K16 - 0x5C280A00, // 0039 MOVE R10 R5 - 0x882C0113, // 003A GETMBR R11 R0 K19 - 0x7C180A00, // 003B CALL R6 5 - 0xA8040001, // 003C EXBLK 1 1 - 0x70020010, // 003D JMP #004F - 0xAC0C0002, // 003E CATCH R3 0 2 - 0x7002000D, // 003F JMP #004E - 0xB8160E00, // 0040 GETNGBL R5 K7 - 0x8C140B0B, // 0041 GETMET R5 R5 K11 - 0x601C0008, // 0042 GETGBL R7 G8 - 0x5C200600, // 0043 MOVE R8 R3 - 0x7C1C0200, // 0044 CALL R7 1 - 0x001E2807, // 0045 ADD R7 K20 R7 - 0x001C0F15, // 0046 ADD R7 R7 K21 - 0x60200008, // 0047 GETGBL R8 G8 - 0x5C240800, // 0048 MOVE R9 R4 - 0x7C200200, // 0049 CALL R8 1 - 0x001C0E08, // 004A ADD R7 R7 R8 - 0x58200016, // 004B LDCONST R8 K22 - 0x7C140600, // 004C CALL R5 3 - 0x70020000, // 004D JMP #004F - 0xB0080000, // 004E RAISE 2 R0 R0 - 0x80000000, // 004F RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: _start_udp -********************************************************************/ -be_local_closure(Matter_Device__start_udp, /* name */ - be_nested_proto( - 7, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 1]) { - be_nested_proto( - 8, /* nstack */ - 3, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 1]) { /* upvals */ - be_local_const_upval(1, 0), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(msg_received), - }), - be_str_weak(_X3Clambda_X3E), - &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0x680C0000, // 0000 GETUPV R3 U0 - 0x8C0C0700, // 0001 GETMET R3 R3 K0 - 0x5C140000, // 0002 MOVE R5 R0 - 0x5C180200, // 0003 MOVE R6 R1 - 0x5C1C0400, // 0004 MOVE R7 R2 - 0x7C0C0800, // 0005 CALL R3 4 - 0x80040600, // 0006 RET 1 R3 - }) - ), - }), - 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(udp_server), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(log), - /* K3 */ be_nested_str_weak(MTR_X3A_X20Starting_X20UDP_X20server_X20on_X20port_X3A_X20), - /* K4 */ be_const_int(2), - /* K5 */ be_nested_str_weak(matter), - /* K6 */ be_nested_str_weak(UDPServer), - /* K7 */ be_nested_str_weak(), - /* K8 */ be_nested_str_weak(start), - }), - be_str_weak(_start_udp), - &be_const_str_solidified, - ( &(const binstruction[28]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x780A0000, // 0001 JMPF R2 #0003 - 0x80000400, // 0002 RET 0 - 0x4C080000, // 0003 LDNIL R2 - 0x1C080202, // 0004 EQ R2 R1 R2 - 0x780A0000, // 0005 JMPF R2 #0007 - 0x540615A3, // 0006 LDINT R1 5540 - 0xB80A0200, // 0007 GETNGBL R2 K1 - 0x8C080502, // 0008 GETMET R2 R2 K2 - 0x60100008, // 0009 GETGBL R4 G8 - 0x5C140200, // 000A MOVE R5 R1 - 0x7C100200, // 000B CALL R4 1 - 0x00120604, // 000C ADD R4 K3 R4 - 0x58140004, // 000D LDCONST R5 K4 - 0x7C080600, // 000E CALL R2 3 - 0xB80A0A00, // 000F GETNGBL R2 K5 - 0x8C080506, // 0010 GETMET R2 R2 K6 - 0x5C100000, // 0011 MOVE R4 R0 - 0x58140007, // 0012 LDCONST R5 K7 - 0x5C180200, // 0013 MOVE R6 R1 - 0x7C080800, // 0014 CALL R2 4 - 0x90020002, // 0015 SETMBR R0 K0 R2 - 0x88080100, // 0016 GETMBR R2 R0 K0 - 0x8C080508, // 0017 GETMET R2 R2 K8 - 0x84100000, // 0018 CLOSURE R4 P0 - 0x7C080400, // 0019 CALL R2 2 - 0xA0000000, // 001A CLOSE R0 - 0x80000000, // 001B RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_plugin_remote_info -********************************************************************/ -be_local_closure(Matter_Device_get_plugin_remote_info, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(plugins_config_remotes), - /* K1 */ be_nested_str_weak(find), - }), - be_str_weak(get_plugin_remote_info), - &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x60140013, // 0003 GETGBL R5 G19 - 0x7C140000, // 0004 CALL R5 0 - 0x7C080600, // 0005 CALL R2 3 - 0x80040400, // 0006 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: register_http_remote -********************************************************************/ -be_local_closure(Matter_Device_register_http_remote, /* name */ - be_nested_proto( - 9, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str_weak(http_remotes), - /* K1 */ be_nested_str_weak(contains), - /* K2 */ be_nested_str_weak(get_timeout), - /* K3 */ be_nested_str_weak(set_timeout), - /* K4 */ be_nested_str_weak(matter), - /* K5 */ be_nested_str_weak(HTTP_remote), - /* K6 */ be_nested_str_weak(plugins_config_remotes), - /* K7 */ be_nested_str_weak(set_info), - }), - be_str_weak(register_http_remote), - &be_const_str_solidified, - ( &(const binstruction[42]) { /* code */ - 0x880C0100, // 0000 GETMBR R3 R0 K0 - 0x4C100000, // 0001 LDNIL R4 - 0x1C0C0604, // 0002 EQ R3 R3 R4 - 0x780E0002, // 0003 JMPF R3 #0007 - 0x600C0013, // 0004 GETGBL R3 G19 - 0x7C0C0000, // 0005 CALL R3 0 - 0x90020003, // 0006 SETMBR R0 K0 R3 - 0x4C0C0000, // 0007 LDNIL R3 - 0x88100100, // 0008 GETMBR R4 R0 K0 - 0x8C100901, // 0009 GETMET R4 R4 K1 - 0x5C180200, // 000A MOVE R6 R1 - 0x7C100400, // 000B CALL R4 2 - 0x78120009, // 000C JMPF R4 #0017 - 0x88100100, // 000D GETMBR R4 R0 K0 - 0x940C0801, // 000E GETIDX R3 R4 R1 - 0x8C140702, // 000F GETMET R5 R3 K2 - 0x7C140200, // 0010 CALL R5 1 - 0x14140405, // 0011 LT R5 R2 R5 - 0x78160002, // 0012 JMPF R5 #0016 - 0x8C140703, // 0013 GETMET R5 R3 K3 - 0x5C1C0400, // 0014 MOVE R7 R2 - 0x7C140400, // 0015 CALL R5 2 - 0x70020011, // 0016 JMP #0029 - 0xB8120800, // 0017 GETNGBL R4 K4 - 0x8C100905, // 0018 GETMET R4 R4 K5 - 0x5C180000, // 0019 MOVE R6 R0 - 0x5C1C0200, // 001A MOVE R7 R1 - 0x5C200400, // 001B MOVE R8 R2 - 0x7C100800, // 001C CALL R4 4 - 0x5C0C0800, // 001D MOVE R3 R4 - 0x88100106, // 001E GETMBR R4 R0 K6 - 0x8C100901, // 001F GETMET R4 R4 K1 - 0x5C180200, // 0020 MOVE R6 R1 - 0x7C100400, // 0021 CALL R4 2 - 0x78120003, // 0022 JMPF R4 #0027 - 0x8C100707, // 0023 GETMET R4 R3 K7 - 0x88180106, // 0024 GETMBR R6 R0 K6 - 0x94180C01, // 0025 GETIDX R6 R6 R1 - 0x7C100400, // 0026 CALL R4 2 - 0x88100100, // 0027 GETMBR R4 R0 K0 - 0x98100203, // 0028 SETIDX R4 R1 R3 - 0x80040600, // 0029 RET 1 R3 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: mdns_remove_op_discovery_all_fabrics -********************************************************************/ -be_local_closure(Matter_Device_mdns_remove_op_discovery_all_fabrics, /* name */ - be_nested_proto( - 6, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(sessions), - /* K1 */ be_nested_str_weak(active_fabrics), - /* K2 */ be_nested_str_weak(get_device_id), - /* K3 */ be_nested_str_weak(get_fabric_id), - /* K4 */ be_nested_str_weak(mdns_remove_op_discovery), - /* K5 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(mdns_remove_op_discovery_all_fabrics), - &be_const_str_solidified, - ( &(const binstruction[22]) { /* code */ - 0x60040010, // 0000 GETGBL R1 G16 - 0x88080100, // 0001 GETMBR R2 R0 K0 - 0x8C080501, // 0002 GETMET R2 R2 K1 - 0x7C080200, // 0003 CALL R2 1 - 0x7C040200, // 0004 CALL R1 1 - 0xA802000B, // 0005 EXBLK 0 #0012 - 0x5C080200, // 0006 MOVE R2 R1 - 0x7C080000, // 0007 CALL R2 0 - 0x8C0C0502, // 0008 GETMET R3 R2 K2 - 0x7C0C0200, // 0009 CALL R3 1 - 0x780E0005, // 000A JMPF R3 #0011 - 0x8C0C0503, // 000B GETMET R3 R2 K3 - 0x7C0C0200, // 000C CALL R3 1 - 0x780E0002, // 000D JMPF R3 #0011 - 0x8C0C0104, // 000E GETMET R3 R0 K4 - 0x5C140400, // 000F MOVE R5 R2 - 0x7C0C0400, // 0010 CALL R3 2 - 0x7001FFF3, // 0011 JMP #0006 - 0x58040005, // 0012 LDCONST R1 K5 - 0xAC040200, // 0013 CATCH R1 1 0 - 0xB0080000, // 0014 RAISE 2 R0 R0 - 0x80000000, // 0015 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_plugin_class_arg -********************************************************************/ -be_local_closure(Matter_Device_get_plugin_class_arg, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(plugins_classes), - /* K1 */ be_nested_str_weak(find), - /* K2 */ be_nested_str_weak(ARG), - /* K3 */ be_nested_str_weak(), - }), - be_str_weak(get_plugin_class_arg), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x780A0001, // 0004 JMPF R2 #0007 - 0x880C0502, // 0005 GETMBR R3 R2 K2 - 0x70020000, // 0006 JMP #0008 - 0x580C0003, // 0007 LDCONST R3 K3 - 0x80040600, // 0008 RET 1 R3 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: generate_random_passcode -********************************************************************/ -be_local_closure(Matter_Device_generate_random_passcode, /* name */ - be_nested_proto( - 7, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str_weak(crypto), - /* K1 */ be_nested_str_weak(random), - /* K2 */ be_nested_str_weak(get), - /* K3 */ be_const_int(0), - /* K4 */ be_const_int(134217727), - /* K5 */ be_const_int(99999998), - /* K6 */ be_nested_str_weak(PASSCODE_INVALID), - /* K7 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(generate_random_passcode), - &be_const_str_solidified, - ( &(const binstruction[35]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0x4C080000, // 0001 LDNIL R2 - 0x500C0200, // 0002 LDBOOL R3 1 0 - 0x780E001D, // 0003 JMPF R3 #0022 - 0x8C0C0301, // 0004 GETMET R3 R1 K1 - 0x54160003, // 0005 LDINT R5 4 - 0x7C0C0400, // 0006 CALL R3 2 - 0x8C0C0702, // 0007 GETMET R3 R3 K2 - 0x58140003, // 0008 LDCONST R5 K3 - 0x541A0003, // 0009 LDINT R6 4 - 0x7C0C0600, // 000A CALL R3 3 - 0x2C0C0704, // 000B AND R3 R3 K4 - 0x5C080600, // 000C MOVE R2 R3 - 0x240C0505, // 000D GT R3 R2 K5 - 0x780E0000, // 000E JMPF R3 #0010 - 0x7001FFF1, // 000F JMP #0002 - 0x600C0010, // 0010 GETGBL R3 G16 - 0x88100106, // 0011 GETMBR R4 R0 K6 - 0x7C0C0200, // 0012 CALL R3 1 - 0xA8020005, // 0013 EXBLK 0 #001A - 0x5C100600, // 0014 MOVE R4 R3 - 0x7C100000, // 0015 CALL R4 0 - 0x1C140404, // 0016 EQ R5 R2 R4 - 0x78160000, // 0017 JMPF R5 #0019 - 0x4C080000, // 0018 LDNIL R2 - 0x7001FFF9, // 0019 JMP #0014 - 0x580C0007, // 001A LDCONST R3 K7 - 0xAC0C0200, // 001B CATCH R3 1 0 - 0xB0080000, // 001C RAISE 2 R0 R0 - 0x4C0C0000, // 001D LDNIL R3 - 0x200C0403, // 001E NE R3 R2 R3 - 0x780E0000, // 001F JMPF R3 #0021 - 0x80040400, // 0020 RET 1 R2 - 0x7001FFDF, // 0021 JMP #0002 - 0x80000000, // 0022 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: is_root_commissioning_open -********************************************************************/ -be_local_closure(Matter_Device_is_root_commissioning_open, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(commissioning_open), - /* K1 */ be_nested_str_weak(commissioning_admin_fabric), - }), - be_str_weak(is_root_commissioning_open), - &be_const_str_solidified, - ( &(const binstruction[11]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x4C080000, // 0001 LDNIL R2 - 0x20040202, // 0002 NE R1 R1 R2 - 0x78060003, // 0003 JMPF R1 #0008 - 0x88040101, // 0004 GETMBR R1 R0 K1 - 0x4C080000, // 0005 LDNIL R2 - 0x1C040202, // 0006 EQ R1 R1 R2 - 0x74060000, // 0007 JMPT R1 #0009 - 0x50040001, // 0008 LDBOOL R1 0 1 - 0x50040200, // 0009 LDBOOL R1 1 0 - 0x80040200, // 000A RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: stop_basic_commissioning -********************************************************************/ -be_local_closure(Matter_Device_stop_basic_commissioning, /* name */ - be_nested_proto( - 5, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[13]) { /* constants */ - /* K0 */ be_nested_str_weak(is_root_commissioning_open), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(publish_result), - /* K3 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Commissioning_X22_X3A0_X7D_X7D), - /* K4 */ be_nested_str_weak(Matter), - /* K5 */ be_nested_str_weak(commissioning_open), - /* K6 */ be_nested_str_weak(mdns_remove_PASE), - /* K7 */ be_nested_str_weak(commissioning_iterations), - /* K8 */ be_nested_str_weak(commissioning_discriminator), - /* K9 */ be_nested_str_weak(commissioning_salt), - /* K10 */ be_nested_str_weak(commissioning_w0), - /* K11 */ be_nested_str_weak(commissioning_L), - /* K12 */ be_nested_str_weak(commissioning_admin_fabric), - }), - be_str_weak(stop_basic_commissioning), - &be_const_str_solidified, - ( &(const binstruction[25]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0x78060004, // 0002 JMPF R1 #0008 - 0xB8060200, // 0003 GETNGBL R1 K1 - 0x8C040302, // 0004 GETMET R1 R1 K2 - 0x580C0003, // 0005 LDCONST R3 K3 - 0x58100004, // 0006 LDCONST R4 K4 - 0x7C040600, // 0007 CALL R1 3 - 0x4C040000, // 0008 LDNIL R1 - 0x90020A01, // 0009 SETMBR R0 K5 R1 - 0x8C040106, // 000A GETMET R1 R0 K6 - 0x7C040200, // 000B CALL R1 1 - 0x4C040000, // 000C LDNIL R1 - 0x90020E01, // 000D SETMBR R0 K7 R1 - 0x4C040000, // 000E LDNIL R1 - 0x90021001, // 000F SETMBR R0 K8 R1 - 0x4C040000, // 0010 LDNIL R1 - 0x90021201, // 0011 SETMBR R0 K9 R1 - 0x4C040000, // 0012 LDNIL R1 - 0x90021401, // 0013 SETMBR R0 K10 R1 - 0x4C040000, // 0014 LDNIL R1 - 0x90021601, // 0015 SETMBR R0 K11 R1 - 0x4C040000, // 0016 LDNIL R1 - 0x90021801, // 0017 SETMBR R0 K12 R1 - 0x80000000, // 0018 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: autoconf_sensors_list -********************************************************************/ -be_local_closure(Matter_Device_autoconf_sensors_list, /* name */ - be_nested_proto( - 10, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[18]) { /* constants */ - /* K0 */ be_nested_str_weak(k2l), - /* K1 */ be_nested_str_weak(contains), - /* K2 */ be_nested_str_weak(Temperature), - /* K3 */ be_nested_str_weak(_X23Temperature), - /* K4 */ be_nested_str_weak(push), - /* K5 */ be_nested_str_weak(type), - /* K6 */ be_nested_str_weak(temperature), - /* K7 */ be_nested_str_weak(filter), - /* K8 */ be_nested_str_weak(stop_iteration), - /* K9 */ be_nested_str_weak(Pressure), - /* K10 */ be_nested_str_weak(_X23Pressure), - /* K11 */ be_nested_str_weak(pressure), - /* K12 */ be_nested_str_weak(Illuminance), - /* K13 */ be_nested_str_weak(_X23Illuminance), - /* K14 */ be_nested_str_weak(illuminance), - /* K15 */ be_nested_str_weak(Humidity), - /* K16 */ be_nested_str_weak(_X23Humidity), - /* K17 */ be_nested_str_weak(humidity), - }), - be_str_weak(autoconf_sensors_list), - &be_const_str_solidified, - ( &(const binstruction[119]) { /* code */ - 0x60080012, // 0000 GETGBL R2 G18 - 0x7C080000, // 0001 CALL R2 0 - 0x600C0010, // 0002 GETGBL R3 G16 - 0x8C100100, // 0003 GETMET R4 R0 K0 - 0x5C180200, // 0004 MOVE R6 R1 - 0x7C100400, // 0005 CALL R4 2 - 0x7C0C0200, // 0006 CALL R3 1 - 0xA8020013, // 0007 EXBLK 0 #001C - 0x5C100600, // 0008 MOVE R4 R3 - 0x7C100000, // 0009 CALL R4 0 - 0x94140204, // 000A GETIDX R5 R1 R4 - 0x6018000F, // 000B GETGBL R6 G15 - 0x5C1C0A00, // 000C MOVE R7 R5 - 0x60200013, // 000D GETGBL R8 G19 - 0x7C180400, // 000E CALL R6 2 - 0x781A000A, // 000F JMPF R6 #001B - 0x8C180B01, // 0010 GETMET R6 R5 K1 - 0x58200002, // 0011 LDCONST R8 K2 - 0x7C180400, // 0012 CALL R6 2 - 0x781A0006, // 0013 JMPF R6 #001B - 0x00180903, // 0014 ADD R6 R4 K3 - 0x8C1C0504, // 0015 GETMET R7 R2 K4 - 0x60240013, // 0016 GETGBL R9 G19 - 0x7C240000, // 0017 CALL R9 0 - 0x98260B06, // 0018 SETIDX R9 K5 K6 - 0x98260E06, // 0019 SETIDX R9 K7 R6 - 0x7C1C0400, // 001A CALL R7 2 - 0x7001FFEB, // 001B JMP #0008 - 0x580C0008, // 001C LDCONST R3 K8 - 0xAC0C0200, // 001D CATCH R3 1 0 - 0xB0080000, // 001E RAISE 2 R0 R0 - 0x600C0010, // 001F GETGBL R3 G16 - 0x8C100100, // 0020 GETMET R4 R0 K0 - 0x5C180200, // 0021 MOVE R6 R1 - 0x7C100400, // 0022 CALL R4 2 - 0x7C0C0200, // 0023 CALL R3 1 - 0xA8020013, // 0024 EXBLK 0 #0039 - 0x5C100600, // 0025 MOVE R4 R3 - 0x7C100000, // 0026 CALL R4 0 - 0x94140204, // 0027 GETIDX R5 R1 R4 - 0x6018000F, // 0028 GETGBL R6 G15 - 0x5C1C0A00, // 0029 MOVE R7 R5 - 0x60200013, // 002A GETGBL R8 G19 - 0x7C180400, // 002B CALL R6 2 - 0x781A000A, // 002C JMPF R6 #0038 - 0x8C180B01, // 002D GETMET R6 R5 K1 - 0x58200009, // 002E LDCONST R8 K9 - 0x7C180400, // 002F CALL R6 2 - 0x781A0006, // 0030 JMPF R6 #0038 - 0x0018090A, // 0031 ADD R6 R4 K10 - 0x8C1C0504, // 0032 GETMET R7 R2 K4 - 0x60240013, // 0033 GETGBL R9 G19 - 0x7C240000, // 0034 CALL R9 0 - 0x98260B0B, // 0035 SETIDX R9 K5 K11 - 0x98260E06, // 0036 SETIDX R9 K7 R6 - 0x7C1C0400, // 0037 CALL R7 2 - 0x7001FFEB, // 0038 JMP #0025 - 0x580C0008, // 0039 LDCONST R3 K8 - 0xAC0C0200, // 003A CATCH R3 1 0 - 0xB0080000, // 003B RAISE 2 R0 R0 - 0x600C0010, // 003C GETGBL R3 G16 - 0x8C100100, // 003D GETMET R4 R0 K0 - 0x5C180200, // 003E MOVE R6 R1 - 0x7C100400, // 003F CALL R4 2 - 0x7C0C0200, // 0040 CALL R3 1 - 0xA8020013, // 0041 EXBLK 0 #0056 - 0x5C100600, // 0042 MOVE R4 R3 - 0x7C100000, // 0043 CALL R4 0 - 0x94140204, // 0044 GETIDX R5 R1 R4 - 0x6018000F, // 0045 GETGBL R6 G15 - 0x5C1C0A00, // 0046 MOVE R7 R5 - 0x60200013, // 0047 GETGBL R8 G19 - 0x7C180400, // 0048 CALL R6 2 - 0x781A000A, // 0049 JMPF R6 #0055 - 0x8C180B01, // 004A GETMET R6 R5 K1 - 0x5820000C, // 004B LDCONST R8 K12 - 0x7C180400, // 004C CALL R6 2 - 0x781A0006, // 004D JMPF R6 #0055 - 0x0018090D, // 004E ADD R6 R4 K13 - 0x8C1C0504, // 004F GETMET R7 R2 K4 - 0x60240013, // 0050 GETGBL R9 G19 - 0x7C240000, // 0051 CALL R9 0 - 0x98260B0E, // 0052 SETIDX R9 K5 K14 - 0x98260E06, // 0053 SETIDX R9 K7 R6 - 0x7C1C0400, // 0054 CALL R7 2 - 0x7001FFEB, // 0055 JMP #0042 - 0x580C0008, // 0056 LDCONST R3 K8 - 0xAC0C0200, // 0057 CATCH R3 1 0 - 0xB0080000, // 0058 RAISE 2 R0 R0 - 0x600C0010, // 0059 GETGBL R3 G16 - 0x8C100100, // 005A GETMET R4 R0 K0 - 0x5C180200, // 005B MOVE R6 R1 - 0x7C100400, // 005C CALL R4 2 - 0x7C0C0200, // 005D CALL R3 1 - 0xA8020013, // 005E EXBLK 0 #0073 - 0x5C100600, // 005F MOVE R4 R3 - 0x7C100000, // 0060 CALL R4 0 - 0x94140204, // 0061 GETIDX R5 R1 R4 - 0x6018000F, // 0062 GETGBL R6 G15 - 0x5C1C0A00, // 0063 MOVE R7 R5 - 0x60200013, // 0064 GETGBL R8 G19 - 0x7C180400, // 0065 CALL R6 2 - 0x781A000A, // 0066 JMPF R6 #0072 - 0x8C180B01, // 0067 GETMET R6 R5 K1 - 0x5820000F, // 0068 LDCONST R8 K15 - 0x7C180400, // 0069 CALL R6 2 - 0x781A0006, // 006A JMPF R6 #0072 - 0x00180910, // 006B ADD R6 R4 K16 - 0x8C1C0504, // 006C GETMET R7 R2 K4 - 0x60240013, // 006D GETGBL R9 G19 - 0x7C240000, // 006E CALL R9 0 - 0x98260B11, // 006F SETIDX R9 K5 K17 - 0x98260E06, // 0070 SETIDX R9 K7 R6 - 0x7C1C0400, // 0071 CALL R7 2 - 0x7001FFEB, // 0072 JMP #005F - 0x580C0008, // 0073 LDCONST R3 K8 - 0xAC0C0200, // 0074 CATCH R3 1 0 - 0xB0080000, // 0075 RAISE 2 R0 R0 - 0x80040400, // 0076 RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: signal_endpoints_changed -********************************************************************/ -be_local_closure(Matter_Device_signal_endpoints_changed, /* name */ - be_nested_proto( - 7, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(attribute_updated), - /* K1 */ be_const_int(0), - /* K2 */ be_const_int(3), - /* K3 */ be_nested_str_weak(matter), - /* K4 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), - }), - be_str_weak(signal_endpoints_changed), - &be_const_str_solidified, - ( &(const binstruction[14]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x580C0001, // 0001 LDCONST R3 K1 - 0x5412001C, // 0002 LDINT R4 29 - 0x58140002, // 0003 LDCONST R5 K2 - 0x50180000, // 0004 LDBOOL R6 0 0 - 0x7C040A00, // 0005 CALL R1 5 - 0x8C040100, // 0006 GETMET R1 R0 K0 - 0xB80E0600, // 0007 GETNGBL R3 K3 - 0x880C0704, // 0008 GETMBR R3 R3 K4 - 0x5412001C, // 0009 LDINT R4 29 - 0x58140002, // 000A LDCONST R5 K2 - 0x50180000, // 000B LDBOOL R6 0 0 - 0x7C040A00, // 000C CALL R1 5 - 0x80000000, // 000D RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: every_second -********************************************************************/ -be_local_closure(Matter_Device_every_second, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(sessions), - /* K1 */ be_nested_str_weak(every_second), - /* K2 */ be_nested_str_weak(message_handler), - /* K3 */ be_nested_str_weak(commissioning_open), - /* K4 */ be_nested_str_weak(tasmota), - /* K5 */ be_nested_str_weak(time_reached), - }), - be_str_weak(every_second), - &be_const_str_solidified, - ( &(const binstruction[18]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x7C040200, // 0002 CALL R1 1 - 0x88040102, // 0003 GETMBR R1 R0 K2 - 0x8C040301, // 0004 GETMET R1 R1 K1 - 0x7C040200, // 0005 CALL R1 1 - 0x88040103, // 0006 GETMBR R1 R0 K3 - 0x4C080000, // 0007 LDNIL R2 - 0x20040202, // 0008 NE R1 R1 R2 - 0x78060006, // 0009 JMPF R1 #0011 - 0xB8060800, // 000A GETNGBL R1 K4 - 0x8C040305, // 000B GETMET R1 R1 K5 - 0x880C0103, // 000C GETMBR R3 R0 K3 - 0x7C040400, // 000D CALL R1 2 - 0x78060001, // 000E JMPF R1 #0011 - 0x4C040000, // 000F LDNIL R1 - 0x90020601, // 0010 SETMBR R0 K3 R1 - 0x80000000, // 0011 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: load_param -********************************************************************/ -be_local_closure(Matter_Device_load_param, /* name */ - be_nested_proto( - 11, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[35]) { /* constants */ - /* K0 */ be_nested_str_weak(crypto), - /* K1 */ be_nested_str_weak(FILENAME), - /* K2 */ be_nested_str_weak(read), - /* K3 */ be_nested_str_weak(close), - /* K4 */ be_nested_str_weak(json), - /* K5 */ be_nested_str_weak(load), - /* K6 */ be_nested_str_weak(root_discriminator), - /* K7 */ be_nested_str_weak(find), - /* K8 */ be_nested_str_weak(distinguish), - /* K9 */ be_nested_str_weak(root_passcode), - /* K10 */ be_nested_str_weak(passcode), - /* K11 */ be_nested_str_weak(ipv4only), - /* K12 */ be_nested_str_weak(disable_bridge_mode), - /* K13 */ be_nested_str_weak(next_ep), - /* K14 */ be_nested_str_weak(nextep), - /* K15 */ be_nested_str_weak(plugins_config), - /* K16 */ be_nested_str_weak(config), - /* K17 */ be_nested_str_weak(tasmota), - /* K18 */ be_nested_str_weak(log), - /* K19 */ be_nested_str_weak(MTR_X3A_X20load_config_X20_X3D_X20), - /* K20 */ be_const_int(3), - /* K21 */ be_nested_str_weak(adjust_next_ep), - /* K22 */ be_nested_str_weak(plugins_persist), - /* K23 */ be_nested_str_weak(plugins_config_remotes), - /* K24 */ be_nested_str_weak(remotes), - /* K25 */ be_nested_str_weak(MTR_X3A_X20load_remotes_X20_X3D_X20), - /* K26 */ be_nested_str_weak(io_error), - /* K27 */ be_nested_str_weak(MTR_X3A_X20Session_Store_X3A_X3Aload_X20Exception_X3A), - /* K28 */ be_nested_str_weak(_X7C), - /* K29 */ be_const_int(2), - /* K30 */ be_nested_str_weak(random), - /* K31 */ be_nested_str_weak(get), - /* K32 */ be_const_int(0), - /* K33 */ be_nested_str_weak(generate_random_passcode), - /* K34 */ be_nested_str_weak(save_param), - }), - be_str_weak(load_param), - &be_const_str_solidified, - ( &(const binstruction[127]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0xA802004D, // 0001 EXBLK 0 #0050 - 0x60080011, // 0002 GETGBL R2 G17 - 0x880C0101, // 0003 GETMBR R3 R0 K1 - 0x7C080200, // 0004 CALL R2 1 - 0x8C0C0502, // 0005 GETMET R3 R2 K2 - 0x7C0C0200, // 0006 CALL R3 1 - 0x8C100503, // 0007 GETMET R4 R2 K3 - 0x7C100200, // 0008 CALL R4 1 - 0xA4120800, // 0009 IMPORT R4 K4 - 0x8C140905, // 000A GETMET R5 R4 K5 - 0x5C1C0600, // 000B MOVE R7 R3 - 0x7C140400, // 000C CALL R5 2 - 0x8C180B07, // 000D GETMET R6 R5 K7 - 0x58200008, // 000E LDCONST R8 K8 - 0x88240106, // 000F GETMBR R9 R0 K6 - 0x7C180600, // 0010 CALL R6 3 - 0x90020C06, // 0011 SETMBR R0 K6 R6 - 0x8C180B07, // 0012 GETMET R6 R5 K7 - 0x5820000A, // 0013 LDCONST R8 K10 - 0x88240109, // 0014 GETMBR R9 R0 K9 - 0x7C180600, // 0015 CALL R6 3 - 0x90021206, // 0016 SETMBR R0 K9 R6 - 0x60180017, // 0017 GETGBL R6 G23 - 0x8C1C0B07, // 0018 GETMET R7 R5 K7 - 0x5824000B, // 0019 LDCONST R9 K11 - 0x50280000, // 001A LDBOOL R10 0 0 - 0x7C1C0600, // 001B CALL R7 3 - 0x7C180200, // 001C CALL R6 1 - 0x90021606, // 001D SETMBR R0 K11 R6 - 0x60180017, // 001E GETGBL R6 G23 - 0x8C1C0B07, // 001F GETMET R7 R5 K7 - 0x5824000C, // 0020 LDCONST R9 K12 - 0x50280000, // 0021 LDBOOL R10 0 0 - 0x7C1C0600, // 0022 CALL R7 3 - 0x7C180200, // 0023 CALL R6 1 - 0x90021806, // 0024 SETMBR R0 K12 R6 - 0x8C180B07, // 0025 GETMET R6 R5 K7 - 0x5820000E, // 0026 LDCONST R8 K14 - 0x8824010D, // 0027 GETMBR R9 R0 K13 - 0x7C180600, // 0028 CALL R6 3 - 0x90021A06, // 0029 SETMBR R0 K13 R6 - 0x8C180B07, // 002A GETMET R6 R5 K7 - 0x58200010, // 002B LDCONST R8 K16 - 0x7C180400, // 002C CALL R6 2 - 0x90021E06, // 002D SETMBR R0 K15 R6 - 0x8818010F, // 002E GETMBR R6 R0 K15 - 0x4C1C0000, // 002F LDNIL R7 - 0x20180C07, // 0030 NE R6 R6 R7 - 0x781A000B, // 0031 JMPF R6 #003E - 0xB81A2200, // 0032 GETNGBL R6 K17 - 0x8C180D12, // 0033 GETMET R6 R6 K18 - 0x60200008, // 0034 GETGBL R8 G8 - 0x8824010F, // 0035 GETMBR R9 R0 K15 - 0x7C200200, // 0036 CALL R8 1 - 0x00222608, // 0037 ADD R8 K19 R8 - 0x58240014, // 0038 LDCONST R9 K20 - 0x7C180600, // 0039 CALL R6 3 - 0x8C180115, // 003A GETMET R6 R0 K21 - 0x7C180200, // 003B CALL R6 1 - 0x50180200, // 003C LDBOOL R6 1 0 - 0x90022C06, // 003D SETMBR R0 K22 R6 - 0x8C180B07, // 003E GETMET R6 R5 K7 - 0x58200018, // 003F LDCONST R8 K24 - 0x60240013, // 0040 GETGBL R9 G19 - 0x7C240000, // 0041 CALL R9 0 - 0x7C180600, // 0042 CALL R6 3 - 0x90022E06, // 0043 SETMBR R0 K23 R6 - 0x88180117, // 0044 GETMBR R6 R0 K23 - 0x781A0007, // 0045 JMPF R6 #004E - 0xB81A2200, // 0046 GETNGBL R6 K17 - 0x8C180D12, // 0047 GETMET R6 R6 K18 - 0x60200008, // 0048 GETGBL R8 G8 - 0x88240117, // 0049 GETMBR R9 R0 K23 - 0x7C200200, // 004A CALL R8 1 - 0x00223208, // 004B ADD R8 K25 R8 - 0x58240014, // 004C LDCONST R9 K20 - 0x7C180600, // 004D CALL R6 3 - 0xA8040001, // 004E EXBLK 1 1 - 0x70020012, // 004F JMP #0063 - 0xAC080002, // 0050 CATCH R2 0 2 - 0x7002000F, // 0051 JMP #0062 - 0x2010051A, // 0052 NE R4 R2 K26 - 0x7812000C, // 0053 JMPF R4 #0061 - 0xB8122200, // 0054 GETNGBL R4 K17 - 0x8C100912, // 0055 GETMET R4 R4 K18 - 0x60180008, // 0056 GETGBL R6 G8 - 0x5C1C0400, // 0057 MOVE R7 R2 - 0x7C180200, // 0058 CALL R6 1 - 0x001A3606, // 0059 ADD R6 K27 R6 - 0x00180D1C, // 005A ADD R6 R6 K28 - 0x601C0008, // 005B GETGBL R7 G8 - 0x5C200600, // 005C MOVE R8 R3 - 0x7C1C0200, // 005D CALL R7 1 - 0x00180C07, // 005E ADD R6 R6 R7 - 0x581C001D, // 005F LDCONST R7 K29 - 0x7C100600, // 0060 CALL R4 3 - 0x70020000, // 0061 JMP #0063 - 0xB0080000, // 0062 RAISE 2 R0 R0 - 0x50080000, // 0063 LDBOOL R2 0 0 - 0x880C0106, // 0064 GETMBR R3 R0 K6 - 0x4C100000, // 0065 LDNIL R4 - 0x1C0C0604, // 0066 EQ R3 R3 R4 - 0x780E000A, // 0067 JMPF R3 #0073 - 0x8C0C031E, // 0068 GETMET R3 R1 K30 - 0x5814001D, // 0069 LDCONST R5 K29 - 0x7C0C0400, // 006A CALL R3 2 - 0x8C0C071F, // 006B GETMET R3 R3 K31 - 0x58140020, // 006C LDCONST R5 K32 - 0x5818001D, // 006D LDCONST R6 K29 - 0x7C0C0600, // 006E CALL R3 3 - 0x54120FFE, // 006F LDINT R4 4095 - 0x2C0C0604, // 0070 AND R3 R3 R4 - 0x90020C03, // 0071 SETMBR R0 K6 R3 - 0x50080200, // 0072 LDBOOL R2 1 0 - 0x880C0109, // 0073 GETMBR R3 R0 K9 - 0x4C100000, // 0074 LDNIL R4 - 0x1C0C0604, // 0075 EQ R3 R3 R4 - 0x780E0003, // 0076 JMPF R3 #007B - 0x8C0C0121, // 0077 GETMET R3 R0 K33 - 0x7C0C0200, // 0078 CALL R3 1 - 0x90021203, // 0079 SETMBR R0 K9 R3 - 0x50080200, // 007A LDBOOL R2 1 0 - 0x780A0001, // 007B JMPF R2 #007E - 0x8C0C0122, // 007C GETMET R3 R0 K34 - 0x7C0C0200, // 007D CALL R3 1 - 0x80000000, // 007E RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified class: Matter_Device ********************************************************************/ be_local_class(Matter_Device, 38, NULL, - be_nested_map(116, + be_nested_map(117, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(bridge_add_endpoint, -1), be_const_closure(Matter_Device_bridge_add_endpoint_closure) }, - { be_const_key_weak(load_param, -1), be_const_closure(Matter_Device_load_param_closure) }, - { be_const_key_weak(compute_manual_pairing_code, 36), be_const_closure(Matter_Device_compute_manual_pairing_code_closure) }, - { be_const_key_weak(ipv4only, -1), be_const_var(29) }, - { be_const_key_weak(conf_to_log, -1), be_const_static_closure(Matter_Device_conf_to_log_closure) }, - { be_const_key_weak(start_operational_discovery, -1), be_const_closure(Matter_Device_start_operational_discovery_closure) }, - { be_const_key_weak(commissioning_w0, -1), be_const_var(15) }, - { be_const_key_weak(every_second, -1), be_const_closure(Matter_Device_every_second_closure) }, - { be_const_key_weak(tick, 96), be_const_var(10) }, - { be_const_key_weak(profiler, 3), be_const_var(6) }, - { be_const_key_weak(MtrInfo, -1), be_const_closure(Matter_Device_MtrInfo_closure) }, + { be_const_key_weak(udp_server, -1), be_const_var(5) }, + { be_const_key_weak(next_ep, 108), be_const_var(31) }, + { be_const_key_weak(is_commissioning_open, -1), be_const_closure(Matter_Device_is_commissioning_open_closure) }, + { be_const_key_weak(MtrInfo_one, -1), be_const_closure(Matter_Device_MtrInfo_one_closure) }, + { be_const_key_weak(invoke_request, -1), be_const_closure(Matter_Device_invoke_request_closure) }, + { be_const_key_weak(start_commissioning_complete, 4), be_const_closure(Matter_Device_start_commissioning_complete_closure) }, + { be_const_key_weak(bridge_remove_endpoint, 23), be_const_closure(Matter_Device_bridge_remove_endpoint_closure) }, + { be_const_key_weak(get_plugin_remote_info, -1), be_const_closure(Matter_Device_get_plugin_remote_info_closure) }, + { be_const_key_weak(probe_sensor_time, 43), be_const_var(36) }, + { be_const_key_weak(vendorid, -1), be_const_var(22) }, + { be_const_key_weak(UDP_PORT, -1), be_const_int(5540) }, + { be_const_key_weak(commissioning_instance_eth, -1), be_const_var(19) }, + { be_const_key_weak(MtrInfo, 17), be_const_closure(Matter_Device_MtrInfo_closure) }, + { be_const_key_weak(mdns_announce_PASE, -1), be_const_closure(Matter_Device_mdns_announce_PASE_closure) }, + { be_const_key_weak(productid, 44), be_const_var(23) }, + { be_const_key_weak(bridge_add_endpoint, 20), be_const_closure(Matter_Device_bridge_add_endpoint_closure) }, + { be_const_key_weak(register_http_remote, -1), be_const_closure(Matter_Device_register_http_remote_closure) }, + { be_const_key_weak(signal_endpoints_changed, -1), be_const_closure(Matter_Device_signal_endpoints_changed_closure) }, + { be_const_key_weak(disable_bridge_mode, -1), be_const_var(30) }, + { be_const_key_weak(get_plugin_class_displayname, 89), be_const_closure(Matter_Device_get_plugin_class_displayname_closure) }, + { be_const_key_weak(start_mdns_announce_hostnames, 69), be_const_closure(Matter_Device_start_mdns_announce_hostnames_closure) }, + { be_const_key_weak(commissioning_instance_wifi, 114), be_const_var(18) }, + { be_const_key_weak(autoconf_device_map, -1), be_const_closure(Matter_Device_autoconf_device_map_closure) }, + { be_const_key_weak(init, -1), be_const_closure(Matter_Device_init_closure) }, + { be_const_key_weak(mdns_announce_op_discovery_all_fabrics, 8), be_const_closure(Matter_Device_mdns_announce_op_discovery_all_fabrics_closure) }, + { be_const_key_weak(sessions, 98), be_const_var(8) }, + { be_const_key_weak(_mdns_announce_hostname, 55), be_const_closure(Matter_Device__mdns_announce_hostname_closure) }, + { be_const_key_weak(commissioning_discriminator, -1), be_const_var(13) }, + { be_const_key_weak(register_commands, 100), be_const_closure(Matter_Device_register_commands_closure) }, + { be_const_key_weak(start, 109), be_const_closure(Matter_Device_start_closure) }, + { be_const_key_weak(_compute_pbkdf, -1), be_const_closure(Matter_Device__compute_pbkdf_closure) }, + { be_const_key_weak(find_plugin_by_friendly_name, 95), be_const_closure(Matter_Device_find_plugin_by_friendly_name_closure) }, + { be_const_key_weak(save_param, -1), be_const_closure(Matter_Device_save_param_closure) }, + { be_const_key_weak(clean_remotes, -1), be_const_closure(Matter_Device_clean_remotes_closure) }, + { be_const_key_weak(MtrJoin, 58), be_const_closure(Matter_Device_MtrJoin_closure) }, + { be_const_key_weak(autoconf_device, -1), be_const_closure(Matter_Device_autoconf_device_closure) }, + { be_const_key_weak(hostname_wifi, 68), be_const_var(20) }, + { be_const_key_weak(_trigger_read_sensors, -1), be_const_closure(Matter_Device__trigger_read_sensors_closure) }, + { be_const_key_weak(root_passcode, 63), be_const_var(28) }, + { be_const_key_weak(save_before_restart, -1), be_const_closure(Matter_Device_save_before_restart_closure) }, + { be_const_key_weak(generate_random_passcode, 64), be_const_closure(Matter_Device_generate_random_passcode_closure) }, + { be_const_key_weak(is_root_commissioning_open, 90), be_const_closure(Matter_Device_is_root_commissioning_open_closure) }, + { be_const_key_weak(start_commissioning_complete_deferred, -1), be_const_closure(Matter_Device_start_commissioning_complete_deferred_closure) }, + { be_const_key_weak(root_iterations, -1), be_const_var(32) }, + { be_const_key_weak(start_operational_discovery_deferred, -1), be_const_closure(Matter_Device_start_operational_discovery_deferred_closure) }, + { be_const_key_weak(probe_sensor_timestamp, -1), be_const_var(37) }, + { be_const_key_weak(ipv4only, 34), be_const_var(29) }, + { be_const_key_weak(mdns_remove_PASE, 29), be_const_closure(Matter_Device_mdns_remove_PASE_closure) }, + { be_const_key_weak(plugins_config_remotes, 103), be_const_var(4) }, + { be_const_key_weak(remove_fabric, -1), be_const_closure(Matter_Device_remove_fabric_closure) }, + { be_const_key_weak(sort_distinct, -1), be_const_static_closure(Matter_Device_sort_distinct_closure) }, + { be_const_key_weak(commissioning_iterations, -1), be_const_var(12) }, + { be_const_key_weak(plugins_config, 40), be_const_var(3) }, + { be_const_key_weak(_init_basic_commissioning, 37), be_const_closure(Matter_Device__init_basic_commissioning_closure) }, + { be_const_key_weak(plugins_persist, -1), be_const_var(2) }, + { be_const_key_weak(hostname_eth, -1), be_const_var(21) }, + { be_const_key_weak(mdns_remove_op_discovery, 77), be_const_closure(Matter_Device_mdns_remove_op_discovery_closure) }, + { be_const_key_weak(received_ack, 76), be_const_closure(Matter_Device_received_ack_closure) }, + { be_const_key_weak(PASE_TIMEOUT, 27), be_const_int(600) }, + { be_const_key_weak(_instantiate_plugins_from_config, -1), be_const_closure(Matter_Device__instantiate_plugins_from_config_closure) }, { be_const_key_weak(mdns_pase_eth, -1), be_const_var(24) }, - { be_const_key_weak(signal_endpoints_changed, 72), be_const_closure(Matter_Device_signal_endpoints_changed_closure) }, - { be_const_key_weak(MtrInfo_one, 58), be_const_closure(Matter_Device_MtrInfo_one_closure) }, - { be_const_key_weak(vendorid, 97), be_const_var(22) }, + { be_const_key_weak(mdns_pase_wifi, -1), be_const_var(25) }, + { be_const_key_weak(commissioning_salt, -1), be_const_var(14) }, + { be_const_key_weak(start_basic_commissioning, 94), be_const_closure(Matter_Device_start_basic_commissioning_closure) }, { be_const_key_weak(commissioning_L, -1), be_const_var(16) }, - { be_const_key_weak(plugins_classes, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { + { be_const_key_weak(message_handler, 36), be_const_var(7) }, + { be_const_key_weak(get_plugin_class_arg, -1), be_const_closure(Matter_Device_get_plugin_class_arg_closure) }, + { be_const_key_weak(process_attribute_expansion, 54), be_const_closure(Matter_Device_process_attribute_expansion_closure) }, + { be_const_key_weak(k2l, -1), be_const_static_closure(Matter_Device_k2l_closure) }, + { be_const_key_weak(compute_manual_pairing_code, -1), be_const_closure(Matter_Device_compute_manual_pairing_code_closure) }, + { be_const_key_weak(root_discriminator, 93), be_const_var(27) }, + { be_const_key_weak(_start_udp, -1), be_const_closure(Matter_Device__start_udp_closure) }, + { be_const_key_weak(k2l_num, -1), be_const_static_closure(Matter_Device_k2l_num_closure) }, + { be_const_key_weak(commissioning_open, -1), be_const_var(11) }, + { be_const_key_weak(add_read_sensors_schedule, 91), be_const_closure(Matter_Device_add_read_sensors_schedule_closure) }, + { be_const_key_weak(check_config_ep, -1), be_const_closure(Matter_Device_check_config_ep_closure) }, + { be_const_key_weak(PASSCODE_INVALID, 107), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + be_const_list( * be_nested_list(12, + ( (struct bvalue*) &(const bvalue[]) { + be_const_int(0), + be_const_int(11111111), + be_const_int(22222222), + be_const_int(33333333), + be_const_int(44444444), + be_const_int(55555555), + be_const_int(66666666), + be_const_int(77777777), + be_const_int(88888888), + be_const_int(99999999), + be_const_int(12345678), + be_const_int(87654321), + })) ) } )) }, + { be_const_key_weak(started, -1), be_const_var(0) }, + { be_const_key_weak(autoconf_sensors_list, -1), be_const_closure(Matter_Device_autoconf_sensors_list_closure) }, + { be_const_key_weak(find_plugin_by_endpoint, -1), be_const_closure(Matter_Device_find_plugin_by_endpoint_closure) }, + { be_const_key_weak(start_root_basic_commissioning, -1), be_const_closure(Matter_Device_start_root_basic_commissioning_closure) }, + { be_const_key_weak(plugins, -1), be_const_var(1) }, + { be_const_key_weak(event_fabrics_saved, 88), be_const_closure(Matter_Device_event_fabrics_saved_closure) }, + { be_const_key_weak(commissioning_w0, 73), be_const_var(15) }, + { be_const_key_weak(compute_qrcode_content, 57), be_const_closure(Matter_Device_compute_qrcode_content_closure) }, + { be_const_key_weak(conf_to_log, 56), be_const_static_closure(Matter_Device_conf_to_log_closure) }, + { be_const_key_weak(start_operational_discovery, -1), be_const_closure(Matter_Device_start_operational_discovery_closure) }, + { be_const_key_weak(load_param, -1), be_const_closure(Matter_Device_load_param_closure) }, + { be_const_key_weak(process_attribute_read_solo, -1), be_const_closure(Matter_Device_process_attribute_read_solo_closure) }, + { be_const_key_weak(msg_received, -1), be_const_closure(Matter_Device_msg_received_closure) }, + { be_const_key_weak(root_w0, -1), be_const_var(34) }, + { be_const_key_weak(get_active_endpoints, -1), be_const_closure(Matter_Device_get_active_endpoints_closure) }, + { be_const_key_weak(FILENAME, -1), be_nested_str_weak(_matter_device_X2Ejson) }, + { be_const_key_weak(PBKDF_ITERATIONS, -1), be_const_int(1000) }, + { be_const_key_weak(every_250ms, -1), be_const_closure(Matter_Device_every_250ms_closure) }, + { be_const_key_weak(attribute_updated, -1), be_const_closure(Matter_Device_attribute_updated_closure) }, + { be_const_key_weak(read_sensors_scheduler, -1), be_const_closure(Matter_Device_read_sensors_scheduler_closure) }, + { be_const_key_weak(MtrUpdate, 45), be_const_closure(Matter_Device_MtrUpdate_closure) }, + { be_const_key_weak(mdns_announce_op_discovery, -1), be_const_closure(Matter_Device_mdns_announce_op_discovery_closure) }, + { be_const_key_weak(http_remotes, -1), be_const_var(26) }, + { be_const_key_weak(VENDOR_ID, -1), be_const_int(65521) }, + { be_const_key_weak(root_salt, -1), be_const_var(33) }, + { be_const_key_weak(PRODUCT_ID, -1), be_const_int(32768) }, + { be_const_key_weak(every_second, -1), be_const_closure(Matter_Device_every_second_closure) }, + { be_const_key_weak(update_remotes_info, 32), be_const_closure(Matter_Device_update_remotes_info_closure) }, + { be_const_key_weak(mdns_remove_op_discovery_all_fabrics, -1), be_const_closure(Matter_Device_mdns_remove_op_discovery_all_fabrics_closure) }, + { be_const_key_weak(profiler, -1), be_const_var(6) }, + { be_const_key_weak(root_L, 102), be_const_var(35) }, + { be_const_key_weak(adjust_next_ep, -1), be_const_closure(Matter_Device_adjust_next_ep_closure) }, + { be_const_key_weak(ui, -1), be_const_var(9) }, + { be_const_key_weak(stop, 14), be_const_closure(Matter_Device_stop_closure) }, + { be_const_key_weak(stop_basic_commissioning, 13), be_const_closure(Matter_Device_stop_basic_commissioning_closure) }, + { be_const_key_weak(plugins_classes, 10), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { be_const_map( * be_nested_map(41, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_weak(aggregator, -1), be_const_class(be_class_Matter_Plugin_Aggregator) }, @@ -6211,120 +6439,10 @@ be_local_class(Matter_Device, { be_const_key_weak(humidity, -1), be_const_class(be_class_Matter_Plugin_Sensor_Humidity) }, { be_const_key_weak(http_flow, -1), be_const_class(be_class_Matter_Plugin_Bridge_Sensor_Flow) }, })) ) } )) }, - { be_const_key_weak(root_L, 28), be_const_var(35) }, - { be_const_key_weak(hostname_eth, -1), be_const_var(21) }, - { be_const_key_weak(autoconf_device, 11), be_const_closure(Matter_Device_autoconf_device_closure) }, - { be_const_key_weak(init, -1), be_const_closure(Matter_Device_init_closure) }, - { be_const_key_weak(root_salt, -1), be_const_var(33) }, - { be_const_key_weak(started, -1), be_const_var(0) }, - { be_const_key_weak(add_read_sensors_schedule, -1), be_const_closure(Matter_Device_add_read_sensors_schedule_closure) }, - { be_const_key_weak(hostname_wifi, 65), be_const_var(20) }, - { be_const_key_weak(disable_bridge_mode, 71), be_const_var(30) }, - { be_const_key_weak(generate_random_passcode, 66), be_const_closure(Matter_Device_generate_random_passcode_closure) }, - { be_const_key_weak(get_active_endpoints, -1), be_const_closure(Matter_Device_get_active_endpoints_closure) }, - { be_const_key_weak(_mdns_announce_hostname, -1), be_const_closure(Matter_Device__mdns_announce_hostname_closure) }, - { be_const_key_weak(productid, 84), be_const_var(23) }, - { be_const_key_weak(plugins_config_remotes, -1), be_const_var(4) }, - { be_const_key_weak(start_commissioning_complete, -1), be_const_closure(Matter_Device_start_commissioning_complete_closure) }, - { be_const_key_weak(bridge_remove_endpoint, -1), be_const_closure(Matter_Device_bridge_remove_endpoint_closure) }, + { be_const_key_weak(tick, 9), be_const_var(10) }, { be_const_key_weak(commissioning_admin_fabric, -1), be_const_var(17) }, - { be_const_key_weak(sort_distinct, 110), be_const_static_closure(Matter_Device_sort_distinct_closure) }, - { be_const_key_weak(mdns_announce_op_discovery_all_fabrics, -1), be_const_closure(Matter_Device_mdns_announce_op_discovery_all_fabrics_closure) }, - { be_const_key_weak(get_plugin_class_displayname, -1), be_const_closure(Matter_Device_get_plugin_class_displayname_closure) }, - { be_const_key_weak(start, -1), be_const_closure(Matter_Device_start_closure) }, - { be_const_key_weak(adjust_next_ep, -1), be_const_closure(Matter_Device_adjust_next_ep_closure) }, - { be_const_key_weak(attribute_updated, 20), be_const_closure(Matter_Device_attribute_updated_closure) }, - { be_const_key_weak(PRODUCT_ID, -1), be_const_int(32768) }, - { be_const_key_weak(_instantiate_plugins_from_config, -1), be_const_closure(Matter_Device__instantiate_plugins_from_config_closure) }, - { be_const_key_weak(PASE_TIMEOUT, 17), be_const_int(600) }, - { be_const_key_weak(commissioning_discriminator, 56), be_const_var(13) }, - { be_const_key_weak(find_plugin_by_friendly_name, -1), be_const_closure(Matter_Device_find_plugin_by_friendly_name_closure) }, - { be_const_key_weak(msg_send, -1), be_const_closure(Matter_Device_msg_send_closure) }, - { be_const_key_weak(save_before_restart, 42), be_const_closure(Matter_Device_save_before_restart_closure) }, - { be_const_key_weak(UDP_PORT, -1), be_const_int(5540) }, - { be_const_key_weak(mdns_pase_wifi, -1), be_const_var(25) }, - { be_const_key_weak(start_root_basic_commissioning, -1), be_const_closure(Matter_Device_start_root_basic_commissioning_closure) }, - { be_const_key_weak(mdns_remove_op_discovery, 32), be_const_closure(Matter_Device_mdns_remove_op_discovery_closure) }, - { be_const_key_weak(invoke_request, 50), be_const_closure(Matter_Device_invoke_request_closure) }, - { be_const_key_weak(probe_sensor_time, 33), be_const_var(36) }, - { be_const_key_weak(commissioning_open, -1), be_const_var(11) }, - { be_const_key_weak(start_basic_commissioning, 101), be_const_closure(Matter_Device_start_basic_commissioning_closure) }, - { be_const_key_weak(commissioning_instance_wifi, -1), be_const_var(18) }, - { be_const_key_weak(read_sensors_scheduler, 27), be_const_closure(Matter_Device_read_sensors_scheduler_closure) }, - { be_const_key_weak(http_remotes, -1), be_const_var(26) }, - { be_const_key_weak(commissioning_iterations, -1), be_const_var(12) }, - { be_const_key_weak(PBKDF_ITERATIONS, -1), be_const_int(1000) }, - { be_const_key_weak(k2l, -1), be_const_static_closure(Matter_Device_k2l_closure) }, - { be_const_key_weak(start_operational_discovery_deferred, 48), be_const_closure(Matter_Device_start_operational_discovery_deferred_closure) }, - { be_const_key_weak(autoconf_device_map, -1), be_const_closure(Matter_Device_autoconf_device_map_closure) }, - { be_const_key_weak(mdns_announce_PASE, -1), be_const_closure(Matter_Device_mdns_announce_PASE_closure) }, - { be_const_key_weak(message_handler, -1), be_const_var(7) }, + { be_const_key_weak(msg_send, 7), be_const_closure(Matter_Device_msg_send_closure) }, { be_const_key_weak(every_50ms, -1), be_const_closure(Matter_Device_every_50ms_closure) }, - { be_const_key_weak(start_mdns_announce_hostnames, -1), be_const_closure(Matter_Device_start_mdns_announce_hostnames_closure) }, - { be_const_key_weak(_trigger_read_sensors, 95), be_const_closure(Matter_Device__trigger_read_sensors_closure) }, - { be_const_key_weak(every_250ms, -1), be_const_closure(Matter_Device_every_250ms_closure) }, - { be_const_key_weak(PASSCODE_INVALID, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(12, - ( (struct bvalue*) &(const bvalue[]) { - be_const_int(0), - be_const_int(11111111), - be_const_int(22222222), - be_const_int(33333333), - be_const_int(44444444), - be_const_int(55555555), - be_const_int(66666666), - be_const_int(77777777), - be_const_int(88888888), - be_const_int(99999999), - be_const_int(12345678), - be_const_int(87654321), - })) ) } )) }, - { be_const_key_weak(udp_server, 81), be_const_var(5) }, - { be_const_key_weak(_init_basic_commissioning, -1), be_const_closure(Matter_Device__init_basic_commissioning_closure) }, - { be_const_key_weak(MtrUpdate, -1), be_const_closure(Matter_Device_MtrUpdate_closure) }, - { be_const_key_weak(probe_sensor_timestamp, 37), be_const_var(37) }, - { be_const_key_weak(mdns_announce_op_discovery, 90), be_const_closure(Matter_Device_mdns_announce_op_discovery_closure) }, - { be_const_key_weak(remove_fabric, -1), be_const_closure(Matter_Device_remove_fabric_closure) }, - { be_const_key_weak(sessions, -1), be_const_var(8) }, - { be_const_key_weak(_compute_pbkdf, -1), be_const_closure(Matter_Device__compute_pbkdf_closure) }, - { be_const_key_weak(msg_received, 18), be_const_closure(Matter_Device_msg_received_closure) }, - { be_const_key_weak(k2l_num, 73), be_const_static_closure(Matter_Device_k2l_num_closure) }, - { be_const_key_weak(process_attribute_read_solo, 78), be_const_closure(Matter_Device_process_attribute_read_solo_closure) }, - { be_const_key_weak(is_commissioning_open, -1), be_const_closure(Matter_Device_is_commissioning_open_closure) }, - { be_const_key_weak(plugins_config, 47), be_const_var(3) }, - { be_const_key_weak(register_commands, -1), be_const_closure(Matter_Device_register_commands_closure) }, - { be_const_key_weak(root_w0, -1), be_const_var(34) }, - { be_const_key_weak(commissioning_salt, -1), be_const_var(14) }, - { be_const_key_weak(event_fabrics_saved, -1), be_const_closure(Matter_Device_event_fabrics_saved_closure) }, - { be_const_key_weak(compute_qrcode_content, 12), be_const_closure(Matter_Device_compute_qrcode_content_closure) }, - { be_const_key_weak(find_plugin_by_endpoint, -1), be_const_closure(Matter_Device_find_plugin_by_endpoint_closure) }, - { be_const_key_weak(update_remotes_info, 26), be_const_closure(Matter_Device_update_remotes_info_closure) }, - { be_const_key_weak(MtrJoin, -1), be_const_closure(Matter_Device_MtrJoin_closure) }, - { be_const_key_weak(start_commissioning_complete_deferred, 64), be_const_closure(Matter_Device_start_commissioning_complete_deferred_closure) }, - { be_const_key_weak(next_ep, -1), be_const_var(31) }, - { be_const_key_weak(stop, -1), be_const_closure(Matter_Device_stop_closure) }, - { be_const_key_weak(mdns_remove_PASE, 55), be_const_closure(Matter_Device_mdns_remove_PASE_closure) }, - { be_const_key_weak(plugins, -1), be_const_var(1) }, - { be_const_key_weak(plugins_persist, -1), be_const_var(2) }, - { be_const_key_weak(commissioning_instance_eth, 105), be_const_var(19) }, - { be_const_key_weak(_start_udp, -1), be_const_closure(Matter_Device__start_udp_closure) }, - { be_const_key_weak(get_plugin_remote_info, -1), be_const_closure(Matter_Device_get_plugin_remote_info_closure) }, - { be_const_key_weak(register_http_remote, -1), be_const_closure(Matter_Device_register_http_remote_closure) }, - { be_const_key_weak(root_passcode, -1), be_const_var(28) }, - { be_const_key_weak(mdns_remove_op_discovery_all_fabrics, -1), be_const_closure(Matter_Device_mdns_remove_op_discovery_all_fabrics_closure) }, - { be_const_key_weak(get_plugin_class_arg, -1), be_const_closure(Matter_Device_get_plugin_class_arg_closure) }, - { be_const_key_weak(FILENAME, -1), be_nested_str_weak(_matter_device_X2Ejson) }, - { be_const_key_weak(root_discriminator, -1), be_const_var(27) }, - { be_const_key_weak(clean_remotes, 21), be_const_closure(Matter_Device_clean_remotes_closure) }, - { be_const_key_weak(is_root_commissioning_open, -1), be_const_closure(Matter_Device_is_root_commissioning_open_closure) }, - { be_const_key_weak(stop_basic_commissioning, -1), be_const_closure(Matter_Device_stop_basic_commissioning_closure) }, - { be_const_key_weak(autoconf_sensors_list, -1), be_const_closure(Matter_Device_autoconf_sensors_list_closure) }, - { be_const_key_weak(save_param, -1), be_const_closure(Matter_Device_save_param_closure) }, - { be_const_key_weak(ui, -1), be_const_var(9) }, - { be_const_key_weak(received_ack, 9), be_const_closure(Matter_Device_received_ack_closure) }, - { be_const_key_weak(VENDOR_ID, 7), be_const_int(65521) }, - { be_const_key_weak(root_iterations, -1), be_const_var(32) }, - { be_const_key_weak(process_attribute_expansion, 1), be_const_closure(Matter_Device_process_attribute_expansion_closure) }, })), be_str_weak(Matter_Device) ); From ded44f7755cf1740c156b557c6ba4c4ec56eab29 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 4 Feb 2024 11:55:14 +0100 Subject: [PATCH 255/303] Update changelogs --- CHANGELOG.md | 2 +- RELEASENOTES.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9816dd5a6..489896af1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ All notable changes to this project will be documented in this file. - Berry `introspect.contains` and `bytes.addfloat` (#20635) ### Breaking Changed -- Matter aggregator relocated to endpoint 1 for Google compatibility, may break existing associations +- Matter aggregator relocated to endpoint 1 for Google compatibility, may break existing associations (#20654) ### Changed - Library OneWire-Stickbreaker by TasmotaOneWire supporting Shelly Plus Add-On (#20580) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0393061ea..4f308222d 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -163,6 +163,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds [#20236](https://github.com/arendst/Tasmota/issues/20236) +- Matter aggregator relocated to endpoint 1 for Google compatibility, may break existing associations [#20654](https://github.com/arendst/Tasmota/issues/20654) ### Changed - ESP8266 platform update from 2023.04.00 to 2024.01.01 [#20539](https://github.com/arendst/Tasmota/issues/20539) From 34553f08121ff44364c8fa9ac7b2cce2570aa0d1 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 4 Feb 2024 12:50:53 +0100 Subject: [PATCH 256/303] Matter fix endpoint adjusment (#20657) --- .../src/embedded/Matter_zz_Device.be | 10 +- .../solidify/solidified_Matter_zz_Device.h | 420 +++++++++--------- 2 files changed, 222 insertions(+), 208 deletions(-) diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be b/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be index d57ec5869..3a6289f22 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be @@ -769,6 +769,7 @@ class Matter_Device # Load Matter Device parameters def load_param() import crypto + var dirty = false try var f = open(self.FILENAME) @@ -786,7 +787,7 @@ class Matter_Device if self.plugins_config != nil tasmota.log("MTR: load_config = " + str(self.plugins_config), 3) self.adjust_next_ep() - self.check_config_ep() + dirty = self.check_config_ep() self.plugins_persist = true end self.plugins_config_remotes = j.find("remotes", {}) @@ -799,7 +800,6 @@ class Matter_Device end end - var dirty = false if self.root_discriminator == nil self.root_discriminator = crypto.random(2).get(0,2) & 0xFFF dirty = true @@ -1403,20 +1403,26 @@ class Matter_Device ############################################################# # Check that all ep are valid, i.e. don't collied with root or aggregator # + # return `true` if configuration was adjusted and needs to be saved def check_config_ep() # copy into list so we can change the map on the fly + var dirty = false var keys = [] for k: self.plugins_config.keys() k.push(int(k)) end for ep: keys if ep == 0 tasmota.log("MTR: invalid entry with ep '0'", 2) self.plugins_config.remove(str(ep)) + dirty = true elif ep == matter.AGGREGATOR_ENDPOINT + dirty = true tasmota.log(f"MTR: endpoint {ep} collides wit aggregator, relocating to {self.next_ep}", 2) self.plugins_config[str(self.next_ep)] = self.plugins_config[str(ep)] self.plugins_config.remove(str(ep)) + self.next_ep += 1 end end + return dirty end ############################################################# diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h index 904206b63..29afc6f0a 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h @@ -3860,7 +3860,7 @@ be_local_closure(Matter_Device_get_active_endpoints, /* name */ ********************************************************************/ be_local_closure(Matter_Device_check_config_ep, /* name */ be_nested_proto( - 10, /* nstack */ + 11, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -3868,7 +3868,7 @@ be_local_closure(Matter_Device_check_config_ep, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ + ( &(const bvalue[15]) { /* constants */ /* K0 */ be_nested_str_weak(plugins_config), /* K1 */ be_nested_str_weak(keys), /* K2 */ be_nested_str_weak(push), @@ -3883,83 +3883,90 @@ be_local_closure(Matter_Device_check_config_ep, /* name */ /* K11 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), /* K12 */ be_nested_str_weak(MTR_X3A_X20endpoint_X20_X25s_X20collides_X20wit_X20aggregator_X2C_X20relocating_X20to_X20_X25s), /* K13 */ be_nested_str_weak(next_ep), + /* K14 */ be_const_int(1), }), be_str_weak(check_config_ep), &be_const_str_solidified, - ( &(const binstruction[73]) { /* code */ - 0x60040012, // 0000 GETGBL R1 G18 - 0x7C040000, // 0001 CALL R1 0 - 0x60080010, // 0002 GETGBL R2 G16 - 0x880C0100, // 0003 GETMBR R3 R0 K0 - 0x8C0C0701, // 0004 GETMET R3 R3 K1 - 0x7C0C0200, // 0005 CALL R3 1 - 0x7C080200, // 0006 CALL R2 1 - 0xA8020007, // 0007 EXBLK 0 #0010 - 0x5C0C0400, // 0008 MOVE R3 R2 - 0x7C0C0000, // 0009 CALL R3 0 - 0x8C100702, // 000A GETMET R4 R3 K2 - 0x60180009, // 000B GETGBL R6 G9 - 0x5C1C0600, // 000C MOVE R7 R3 - 0x7C180200, // 000D CALL R6 1 - 0x7C100400, // 000E CALL R4 2 - 0x7001FFF7, // 000F JMP #0008 - 0x58080003, // 0010 LDCONST R2 K3 - 0xAC080200, // 0011 CATCH R2 1 0 - 0xB0080000, // 0012 RAISE 2 R0 R0 - 0x60080010, // 0013 GETGBL R2 G16 - 0x5C0C0200, // 0014 MOVE R3 R1 - 0x7C080200, // 0015 CALL R2 1 - 0xA802002D, // 0016 EXBLK 0 #0045 - 0x5C0C0400, // 0017 MOVE R3 R2 - 0x7C0C0000, // 0018 CALL R3 0 - 0x1C100704, // 0019 EQ R4 R3 K4 - 0x7812000B, // 001A JMPF R4 #0027 - 0xB8120A00, // 001B GETNGBL R4 K5 - 0x8C100906, // 001C GETMET R4 R4 K6 - 0x58180007, // 001D LDCONST R6 K7 - 0x581C0008, // 001E LDCONST R7 K8 - 0x7C100600, // 001F CALL R4 3 - 0x88100100, // 0020 GETMBR R4 R0 K0 - 0x8C100909, // 0021 GETMET R4 R4 K9 - 0x60180008, // 0022 GETGBL R6 G8 - 0x5C1C0600, // 0023 MOVE R7 R3 - 0x7C180200, // 0024 CALL R6 1 - 0x7C100400, // 0025 CALL R4 2 - 0x7002001C, // 0026 JMP #0044 - 0xB8121400, // 0027 GETNGBL R4 K10 - 0x8810090B, // 0028 GETMBR R4 R4 K11 - 0x1C100604, // 0029 EQ R4 R3 R4 - 0x78120018, // 002A JMPF R4 #0044 - 0xB8120A00, // 002B GETNGBL R4 K5 - 0x8C100906, // 002C GETMET R4 R4 K6 - 0x60180018, // 002D GETGBL R6 G24 - 0x581C000C, // 002E LDCONST R7 K12 - 0x5C200600, // 002F MOVE R8 R3 - 0x8824010D, // 0030 GETMBR R9 R0 K13 - 0x7C180600, // 0031 CALL R6 3 - 0x581C0008, // 0032 LDCONST R7 K8 - 0x7C100600, // 0033 CALL R4 3 - 0x60100008, // 0034 GETGBL R4 G8 - 0x8814010D, // 0035 GETMBR R5 R0 K13 - 0x7C100200, // 0036 CALL R4 1 - 0x88140100, // 0037 GETMBR R5 R0 K0 - 0x60180008, // 0038 GETGBL R6 G8 - 0x5C1C0600, // 0039 MOVE R7 R3 - 0x7C180200, // 003A CALL R6 1 - 0x881C0100, // 003B GETMBR R7 R0 K0 - 0x94180E06, // 003C GETIDX R6 R7 R6 - 0x98140806, // 003D SETIDX R5 R4 R6 - 0x88100100, // 003E GETMBR R4 R0 K0 - 0x8C100909, // 003F GETMET R4 R4 K9 - 0x60180008, // 0040 GETGBL R6 G8 - 0x5C1C0600, // 0041 MOVE R7 R3 - 0x7C180200, // 0042 CALL R6 1 - 0x7C100400, // 0043 CALL R4 2 - 0x7001FFD1, // 0044 JMP #0017 - 0x58080003, // 0045 LDCONST R2 K3 - 0xAC080200, // 0046 CATCH R2 1 0 - 0xB0080000, // 0047 RAISE 2 R0 R0 - 0x80000000, // 0048 RET 0 + ( &(const binstruction[79]) { /* code */ + 0x50040000, // 0000 LDBOOL R1 0 0 + 0x60080012, // 0001 GETGBL R2 G18 + 0x7C080000, // 0002 CALL R2 0 + 0x600C0010, // 0003 GETGBL R3 G16 + 0x88100100, // 0004 GETMBR R4 R0 K0 + 0x8C100901, // 0005 GETMET R4 R4 K1 + 0x7C100200, // 0006 CALL R4 1 + 0x7C0C0200, // 0007 CALL R3 1 + 0xA8020007, // 0008 EXBLK 0 #0011 + 0x5C100600, // 0009 MOVE R4 R3 + 0x7C100000, // 000A CALL R4 0 + 0x8C140902, // 000B GETMET R5 R4 K2 + 0x601C0009, // 000C GETGBL R7 G9 + 0x5C200800, // 000D MOVE R8 R4 + 0x7C1C0200, // 000E CALL R7 1 + 0x7C140400, // 000F CALL R5 2 + 0x7001FFF7, // 0010 JMP #0009 + 0x580C0003, // 0011 LDCONST R3 K3 + 0xAC0C0200, // 0012 CATCH R3 1 0 + 0xB0080000, // 0013 RAISE 2 R0 R0 + 0x600C0010, // 0014 GETGBL R3 G16 + 0x5C100400, // 0015 MOVE R4 R2 + 0x7C0C0200, // 0016 CALL R3 1 + 0xA8020032, // 0017 EXBLK 0 #004B + 0x5C100600, // 0018 MOVE R4 R3 + 0x7C100000, // 0019 CALL R4 0 + 0x1C140904, // 001A EQ R5 R4 K4 + 0x7816000C, // 001B JMPF R5 #0029 + 0xB8160A00, // 001C GETNGBL R5 K5 + 0x8C140B06, // 001D GETMET R5 R5 K6 + 0x581C0007, // 001E LDCONST R7 K7 + 0x58200008, // 001F LDCONST R8 K8 + 0x7C140600, // 0020 CALL R5 3 + 0x88140100, // 0021 GETMBR R5 R0 K0 + 0x8C140B09, // 0022 GETMET R5 R5 K9 + 0x601C0008, // 0023 GETGBL R7 G8 + 0x5C200800, // 0024 MOVE R8 R4 + 0x7C1C0200, // 0025 CALL R7 1 + 0x7C140400, // 0026 CALL R5 2 + 0x50040200, // 0027 LDBOOL R1 1 0 + 0x70020020, // 0028 JMP #004A + 0xB8161400, // 0029 GETNGBL R5 K10 + 0x88140B0B, // 002A GETMBR R5 R5 K11 + 0x1C140805, // 002B EQ R5 R4 R5 + 0x7816001C, // 002C JMPF R5 #004A + 0x50040200, // 002D LDBOOL R1 1 0 + 0xB8160A00, // 002E GETNGBL R5 K5 + 0x8C140B06, // 002F GETMET R5 R5 K6 + 0x601C0018, // 0030 GETGBL R7 G24 + 0x5820000C, // 0031 LDCONST R8 K12 + 0x5C240800, // 0032 MOVE R9 R4 + 0x8828010D, // 0033 GETMBR R10 R0 K13 + 0x7C1C0600, // 0034 CALL R7 3 + 0x58200008, // 0035 LDCONST R8 K8 + 0x7C140600, // 0036 CALL R5 3 + 0x60140008, // 0037 GETGBL R5 G8 + 0x8818010D, // 0038 GETMBR R6 R0 K13 + 0x7C140200, // 0039 CALL R5 1 + 0x88180100, // 003A GETMBR R6 R0 K0 + 0x601C0008, // 003B GETGBL R7 G8 + 0x5C200800, // 003C MOVE R8 R4 + 0x7C1C0200, // 003D CALL R7 1 + 0x88200100, // 003E GETMBR R8 R0 K0 + 0x941C1007, // 003F GETIDX R7 R8 R7 + 0x98180A07, // 0040 SETIDX R6 R5 R7 + 0x88140100, // 0041 GETMBR R5 R0 K0 + 0x8C140B09, // 0042 GETMET R5 R5 K9 + 0x601C0008, // 0043 GETGBL R7 G8 + 0x5C200800, // 0044 MOVE R8 R4 + 0x7C1C0200, // 0045 CALL R7 1 + 0x7C140400, // 0046 CALL R5 2 + 0x8814010D, // 0047 GETMBR R5 R0 K13 + 0x00140B0E, // 0048 ADD R5 R5 K14 + 0x90021A05, // 0049 SETMBR R0 K13 R5 + 0x7001FFCC, // 004A JMP #0018 + 0x580C0003, // 004B LDCONST R3 K3 + 0xAC0C0200, // 004C CATCH R3 1 0 + 0xB0080000, // 004D RAISE 2 R0 R0 + 0x80040200, // 004E RET 1 R1 }) ) ); @@ -4412,7 +4419,7 @@ be_local_closure(Matter_Device_start_operational_discovery, /* name */ ********************************************************************/ be_local_closure(Matter_Device_load_param, /* name */ be_nested_proto( - 11, /* nstack */ + 12, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -4460,136 +4467,137 @@ be_local_closure(Matter_Device_load_param, /* name */ }), be_str_weak(load_param), &be_const_str_solidified, - ( &(const binstruction[129]) { /* code */ + ( &(const binstruction[130]) { /* code */ 0xA4060000, // 0000 IMPORT R1 K0 - 0xA802004F, // 0001 EXBLK 0 #0052 - 0x60080011, // 0002 GETGBL R2 G17 - 0x880C0101, // 0003 GETMBR R3 R0 K1 - 0x7C080200, // 0004 CALL R2 1 - 0x8C0C0502, // 0005 GETMET R3 R2 K2 - 0x7C0C0200, // 0006 CALL R3 1 - 0x8C100503, // 0007 GETMET R4 R2 K3 - 0x7C100200, // 0008 CALL R4 1 - 0xA4120800, // 0009 IMPORT R4 K4 - 0x8C140905, // 000A GETMET R5 R4 K5 - 0x5C1C0600, // 000B MOVE R7 R3 - 0x7C140400, // 000C CALL R5 2 - 0x8C180B07, // 000D GETMET R6 R5 K7 - 0x58200008, // 000E LDCONST R8 K8 - 0x88240106, // 000F GETMBR R9 R0 K6 - 0x7C180600, // 0010 CALL R6 3 - 0x90020C06, // 0011 SETMBR R0 K6 R6 - 0x8C180B07, // 0012 GETMET R6 R5 K7 - 0x5820000A, // 0013 LDCONST R8 K10 - 0x88240109, // 0014 GETMBR R9 R0 K9 - 0x7C180600, // 0015 CALL R6 3 - 0x90021206, // 0016 SETMBR R0 K9 R6 - 0x60180017, // 0017 GETGBL R6 G23 - 0x8C1C0B07, // 0018 GETMET R7 R5 K7 - 0x5824000B, // 0019 LDCONST R9 K11 - 0x50280000, // 001A LDBOOL R10 0 0 - 0x7C1C0600, // 001B CALL R7 3 - 0x7C180200, // 001C CALL R6 1 - 0x90021606, // 001D SETMBR R0 K11 R6 - 0x60180017, // 001E GETGBL R6 G23 - 0x8C1C0B07, // 001F GETMET R7 R5 K7 - 0x5824000C, // 0020 LDCONST R9 K12 - 0x50280000, // 0021 LDBOOL R10 0 0 - 0x7C1C0600, // 0022 CALL R7 3 - 0x7C180200, // 0023 CALL R6 1 - 0x90021806, // 0024 SETMBR R0 K12 R6 - 0x8C180B07, // 0025 GETMET R6 R5 K7 - 0x5820000E, // 0026 LDCONST R8 K14 - 0x8824010D, // 0027 GETMBR R9 R0 K13 - 0x7C180600, // 0028 CALL R6 3 - 0x90021A06, // 0029 SETMBR R0 K13 R6 - 0x8C180B07, // 002A GETMET R6 R5 K7 - 0x58200010, // 002B LDCONST R8 K16 - 0x7C180400, // 002C CALL R6 2 - 0x90021E06, // 002D SETMBR R0 K15 R6 - 0x8818010F, // 002E GETMBR R6 R0 K15 - 0x4C1C0000, // 002F LDNIL R7 - 0x20180C07, // 0030 NE R6 R6 R7 - 0x781A000D, // 0031 JMPF R6 #0040 - 0xB81A2200, // 0032 GETNGBL R6 K17 - 0x8C180D12, // 0033 GETMET R6 R6 K18 - 0x60200008, // 0034 GETGBL R8 G8 - 0x8824010F, // 0035 GETMBR R9 R0 K15 - 0x7C200200, // 0036 CALL R8 1 - 0x00222608, // 0037 ADD R8 K19 R8 - 0x58240014, // 0038 LDCONST R9 K20 - 0x7C180600, // 0039 CALL R6 3 - 0x8C180115, // 003A GETMET R6 R0 K21 - 0x7C180200, // 003B CALL R6 1 - 0x8C180116, // 003C GETMET R6 R0 K22 - 0x7C180200, // 003D CALL R6 1 - 0x50180200, // 003E LDBOOL R6 1 0 - 0x90022E06, // 003F SETMBR R0 K23 R6 - 0x8C180B07, // 0040 GETMET R6 R5 K7 - 0x58200019, // 0041 LDCONST R8 K25 - 0x60240013, // 0042 GETGBL R9 G19 - 0x7C240000, // 0043 CALL R9 0 - 0x7C180600, // 0044 CALL R6 3 - 0x90023006, // 0045 SETMBR R0 K24 R6 - 0x88180118, // 0046 GETMBR R6 R0 K24 - 0x781A0007, // 0047 JMPF R6 #0050 - 0xB81A2200, // 0048 GETNGBL R6 K17 - 0x8C180D12, // 0049 GETMET R6 R6 K18 - 0x60200008, // 004A GETGBL R8 G8 - 0x88240118, // 004B GETMBR R9 R0 K24 - 0x7C200200, // 004C CALL R8 1 - 0x00223408, // 004D ADD R8 K26 R8 - 0x58240014, // 004E LDCONST R9 K20 - 0x7C180600, // 004F CALL R6 3 - 0xA8040001, // 0050 EXBLK 1 1 - 0x70020012, // 0051 JMP #0065 - 0xAC080002, // 0052 CATCH R2 0 2 - 0x7002000F, // 0053 JMP #0064 - 0x2010051B, // 0054 NE R4 R2 K27 - 0x7812000C, // 0055 JMPF R4 #0063 - 0xB8122200, // 0056 GETNGBL R4 K17 - 0x8C100912, // 0057 GETMET R4 R4 K18 - 0x60180008, // 0058 GETGBL R6 G8 - 0x5C1C0400, // 0059 MOVE R7 R2 - 0x7C180200, // 005A CALL R6 1 - 0x001A3806, // 005B ADD R6 K28 R6 - 0x00180D1D, // 005C ADD R6 R6 K29 - 0x601C0008, // 005D GETGBL R7 G8 - 0x5C200600, // 005E MOVE R8 R3 - 0x7C1C0200, // 005F CALL R7 1 - 0x00180C07, // 0060 ADD R6 R6 R7 - 0x581C001E, // 0061 LDCONST R7 K30 - 0x7C100600, // 0062 CALL R4 3 - 0x70020000, // 0063 JMP #0065 - 0xB0080000, // 0064 RAISE 2 R0 R0 - 0x50080000, // 0065 LDBOOL R2 0 0 - 0x880C0106, // 0066 GETMBR R3 R0 K6 - 0x4C100000, // 0067 LDNIL R4 - 0x1C0C0604, // 0068 EQ R3 R3 R4 - 0x780E000A, // 0069 JMPF R3 #0075 - 0x8C0C031F, // 006A GETMET R3 R1 K31 - 0x5814001E, // 006B LDCONST R5 K30 - 0x7C0C0400, // 006C CALL R3 2 - 0x8C0C0720, // 006D GETMET R3 R3 K32 - 0x58140021, // 006E LDCONST R5 K33 - 0x5818001E, // 006F LDCONST R6 K30 - 0x7C0C0600, // 0070 CALL R3 3 - 0x54120FFE, // 0071 LDINT R4 4095 - 0x2C0C0604, // 0072 AND R3 R3 R4 - 0x90020C03, // 0073 SETMBR R0 K6 R3 - 0x50080200, // 0074 LDBOOL R2 1 0 - 0x880C0109, // 0075 GETMBR R3 R0 K9 - 0x4C100000, // 0076 LDNIL R4 - 0x1C0C0604, // 0077 EQ R3 R3 R4 - 0x780E0003, // 0078 JMPF R3 #007D - 0x8C0C0122, // 0079 GETMET R3 R0 K34 - 0x7C0C0200, // 007A CALL R3 1 - 0x90021203, // 007B SETMBR R0 K9 R3 - 0x50080200, // 007C LDBOOL R2 1 0 - 0x780A0001, // 007D JMPF R2 #0080 - 0x8C0C0123, // 007E GETMET R3 R0 K35 - 0x7C0C0200, // 007F CALL R3 1 - 0x80000000, // 0080 RET 0 + 0x50080000, // 0001 LDBOOL R2 0 0 + 0xA8020050, // 0002 EXBLK 0 #0054 + 0x600C0011, // 0003 GETGBL R3 G17 + 0x88100101, // 0004 GETMBR R4 R0 K1 + 0x7C0C0200, // 0005 CALL R3 1 + 0x8C100702, // 0006 GETMET R4 R3 K2 + 0x7C100200, // 0007 CALL R4 1 + 0x8C140703, // 0008 GETMET R5 R3 K3 + 0x7C140200, // 0009 CALL R5 1 + 0xA4160800, // 000A IMPORT R5 K4 + 0x8C180B05, // 000B GETMET R6 R5 K5 + 0x5C200800, // 000C MOVE R8 R4 + 0x7C180400, // 000D CALL R6 2 + 0x8C1C0D07, // 000E GETMET R7 R6 K7 + 0x58240008, // 000F LDCONST R9 K8 + 0x88280106, // 0010 GETMBR R10 R0 K6 + 0x7C1C0600, // 0011 CALL R7 3 + 0x90020C07, // 0012 SETMBR R0 K6 R7 + 0x8C1C0D07, // 0013 GETMET R7 R6 K7 + 0x5824000A, // 0014 LDCONST R9 K10 + 0x88280109, // 0015 GETMBR R10 R0 K9 + 0x7C1C0600, // 0016 CALL R7 3 + 0x90021207, // 0017 SETMBR R0 K9 R7 + 0x601C0017, // 0018 GETGBL R7 G23 + 0x8C200D07, // 0019 GETMET R8 R6 K7 + 0x5828000B, // 001A LDCONST R10 K11 + 0x502C0000, // 001B LDBOOL R11 0 0 + 0x7C200600, // 001C CALL R8 3 + 0x7C1C0200, // 001D CALL R7 1 + 0x90021607, // 001E SETMBR R0 K11 R7 + 0x601C0017, // 001F GETGBL R7 G23 + 0x8C200D07, // 0020 GETMET R8 R6 K7 + 0x5828000C, // 0021 LDCONST R10 K12 + 0x502C0000, // 0022 LDBOOL R11 0 0 + 0x7C200600, // 0023 CALL R8 3 + 0x7C1C0200, // 0024 CALL R7 1 + 0x90021807, // 0025 SETMBR R0 K12 R7 + 0x8C1C0D07, // 0026 GETMET R7 R6 K7 + 0x5824000E, // 0027 LDCONST R9 K14 + 0x8828010D, // 0028 GETMBR R10 R0 K13 + 0x7C1C0600, // 0029 CALL R7 3 + 0x90021A07, // 002A SETMBR R0 K13 R7 + 0x8C1C0D07, // 002B GETMET R7 R6 K7 + 0x58240010, // 002C LDCONST R9 K16 + 0x7C1C0400, // 002D CALL R7 2 + 0x90021E07, // 002E SETMBR R0 K15 R7 + 0x881C010F, // 002F GETMBR R7 R0 K15 + 0x4C200000, // 0030 LDNIL R8 + 0x201C0E08, // 0031 NE R7 R7 R8 + 0x781E000E, // 0032 JMPF R7 #0042 + 0xB81E2200, // 0033 GETNGBL R7 K17 + 0x8C1C0F12, // 0034 GETMET R7 R7 K18 + 0x60240008, // 0035 GETGBL R9 G8 + 0x8828010F, // 0036 GETMBR R10 R0 K15 + 0x7C240200, // 0037 CALL R9 1 + 0x00262609, // 0038 ADD R9 K19 R9 + 0x58280014, // 0039 LDCONST R10 K20 + 0x7C1C0600, // 003A CALL R7 3 + 0x8C1C0115, // 003B GETMET R7 R0 K21 + 0x7C1C0200, // 003C CALL R7 1 + 0x8C1C0116, // 003D GETMET R7 R0 K22 + 0x7C1C0200, // 003E CALL R7 1 + 0x5C080E00, // 003F MOVE R2 R7 + 0x501C0200, // 0040 LDBOOL R7 1 0 + 0x90022E07, // 0041 SETMBR R0 K23 R7 + 0x8C1C0D07, // 0042 GETMET R7 R6 K7 + 0x58240019, // 0043 LDCONST R9 K25 + 0x60280013, // 0044 GETGBL R10 G19 + 0x7C280000, // 0045 CALL R10 0 + 0x7C1C0600, // 0046 CALL R7 3 + 0x90023007, // 0047 SETMBR R0 K24 R7 + 0x881C0118, // 0048 GETMBR R7 R0 K24 + 0x781E0007, // 0049 JMPF R7 #0052 + 0xB81E2200, // 004A GETNGBL R7 K17 + 0x8C1C0F12, // 004B GETMET R7 R7 K18 + 0x60240008, // 004C GETGBL R9 G8 + 0x88280118, // 004D GETMBR R10 R0 K24 + 0x7C240200, // 004E CALL R9 1 + 0x00263409, // 004F ADD R9 K26 R9 + 0x58280014, // 0050 LDCONST R10 K20 + 0x7C1C0600, // 0051 CALL R7 3 + 0xA8040001, // 0052 EXBLK 1 1 + 0x70020012, // 0053 JMP #0067 + 0xAC0C0002, // 0054 CATCH R3 0 2 + 0x7002000F, // 0055 JMP #0066 + 0x2014071B, // 0056 NE R5 R3 K27 + 0x7816000C, // 0057 JMPF R5 #0065 + 0xB8162200, // 0058 GETNGBL R5 K17 + 0x8C140B12, // 0059 GETMET R5 R5 K18 + 0x601C0008, // 005A GETGBL R7 G8 + 0x5C200600, // 005B MOVE R8 R3 + 0x7C1C0200, // 005C CALL R7 1 + 0x001E3807, // 005D ADD R7 K28 R7 + 0x001C0F1D, // 005E ADD R7 R7 K29 + 0x60200008, // 005F GETGBL R8 G8 + 0x5C240800, // 0060 MOVE R9 R4 + 0x7C200200, // 0061 CALL R8 1 + 0x001C0E08, // 0062 ADD R7 R7 R8 + 0x5820001E, // 0063 LDCONST R8 K30 + 0x7C140600, // 0064 CALL R5 3 + 0x70020000, // 0065 JMP #0067 + 0xB0080000, // 0066 RAISE 2 R0 R0 + 0x880C0106, // 0067 GETMBR R3 R0 K6 + 0x4C100000, // 0068 LDNIL R4 + 0x1C0C0604, // 0069 EQ R3 R3 R4 + 0x780E000A, // 006A JMPF R3 #0076 + 0x8C0C031F, // 006B GETMET R3 R1 K31 + 0x5814001E, // 006C LDCONST R5 K30 + 0x7C0C0400, // 006D CALL R3 2 + 0x8C0C0720, // 006E GETMET R3 R3 K32 + 0x58140021, // 006F LDCONST R5 K33 + 0x5818001E, // 0070 LDCONST R6 K30 + 0x7C0C0600, // 0071 CALL R3 3 + 0x54120FFE, // 0072 LDINT R4 4095 + 0x2C0C0604, // 0073 AND R3 R3 R4 + 0x90020C03, // 0074 SETMBR R0 K6 R3 + 0x50080200, // 0075 LDBOOL R2 1 0 + 0x880C0109, // 0076 GETMBR R3 R0 K9 + 0x4C100000, // 0077 LDNIL R4 + 0x1C0C0604, // 0078 EQ R3 R3 R4 + 0x780E0003, // 0079 JMPF R3 #007E + 0x8C0C0122, // 007A GETMET R3 R0 K34 + 0x7C0C0200, // 007B CALL R3 1 + 0x90021203, // 007C SETMBR R0 K9 R3 + 0x50080200, // 007D LDBOOL R2 1 0 + 0x780A0001, // 007E JMPF R2 #0081 + 0x8C0C0123, // 007F GETMET R3 R0 K35 + 0x7C0C0200, // 0080 CALL R3 1 + 0x80000000, // 0081 RET 0 }) ) ); From d29b3b2871905a0670f372f4c7e1772d1dcb4928 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 4 Feb 2024 12:52:50 +0100 Subject: [PATCH 257/303] Tune GPIO Viewer --- .../xdrv_121_gpioviewer.ino | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 0bfbf7644..6b782b2c7 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -72,9 +72,10 @@ typedef struct { uint32_t freeHeap; uint32_t freePSRAM; uint32_t sampling; + uint32_t init_done; uint16_t port; + bool mutex; bool sse_ready; - bool init_done; } tGV; tGV* GV = nullptr; WiFiClient GVWebClient; @@ -140,7 +141,8 @@ void GVBegin(void) { void GVHandleRoot(void) { GVCloseEvent(); - GV->init_done = false; + GV->init_done = 2000 / GV->sampling; // Allow 2 seconds to stabilize on GPIO usage fixing slow browsers + GV->mutex = false; char* content = ext_snprintf_malloc_P(HTTP_GV_PAGE, SettingsTextEscaped(SET_DEVICENAME).c_str(), @@ -261,7 +263,7 @@ void GVHandleEvents(void) { GV->sse_ready = true; // Ready for async updates if (GV->sampling != 100) { - GV->ticker.attach_ms(GV->sampling, GVMonitorTask); // Use Tasmota Scheduler (100) or Ticker (20..99,101..1000) + GV->ticker.attach_ms(GV->sampling, GVMonitorTask); // Use Tasmota Scheduler (100) or Ticker (20..99,101..1000) } AddLog(LOG_LEVEL_DEBUG, PSTR("IOV: Connected")); } @@ -276,7 +278,7 @@ void GVEventDisconnected(void) { void GVCloseEvent(void) { if (GV->WebServer) { - GVEventSend("{}", "close", millis()); // Closes web page + GVEventSend("{}", "close", millis()); // Closes web page GVEventDisconnected(); } } @@ -294,6 +296,9 @@ void GVEventSend(const char *message, const char *event, uint32_t id) { void GVMonitorTask(void) { // Monitor GPIO Values + if (GV->mutex) { return; } + GV->mutex = true; + uint32_t originalValue; uint32_t pintype; bool hasChanges = false; @@ -357,6 +362,10 @@ void GVMonitorTask(void) { #endif } + if (GV->init_done) { + uint32_t pin_type = GetPin(pin) / 32; + GV->lastPinStates[pin] = (pin_type != GPIO_NONE) ? -1 : originalValue; // During init provide configured GPIOs fixing slow browsers + } if (originalValue != GV->lastPinStates[pin]) { if (hasChanges) { jsonMessage += ","; } jsonMessage += "\"" + String(pin) + "\":{\"s\":" + currentState + ",\"v\":" + originalValue + ",\"t\":" + pintype + "}"; @@ -365,21 +374,14 @@ void GVMonitorTask(void) { } } jsonMessage += "}"; - - if (!GV->init_done) { - // Show at least configured GPIOs - for (uint32_t pin = 0; pin < MAX_GPIO_PIN; pin++) { - uint32_t pin_type = GetPin(pin) / 32; - if (pin_type != GPIO_NONE) { - GV->lastPinStates[pin] = -1; - } - } - GV->init_done = true; - } - else if (hasChanges) { + if (hasChanges) { GVEventSend(jsonMessage.c_str(), "gpio-state", millis()); } + if (GV->init_done) { + GV->init_done--; + } + uint32_t heap = ESP_getFreeHeap(); if (heap != GV->freeHeap) { // Send freeHeap @@ -417,6 +419,8 @@ void GVMonitorTask(void) { } else { GV->lastSentWithNoActivity = millis(); } + + GV->mutex = false; } /*********************************************************************************************\ From 16db35c27bc33fa40c753b63e25a7efcd1f3c2da Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 4 Feb 2024 15:59:29 +0100 Subject: [PATCH 258/303] Auto Install Platformio in VSC (#20658) --- .vscode/extensions.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .vscode/extensions.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..080e70d08 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} From 35f28fbdb869376ec63384bbdca0d159d4080a1b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 4 Feb 2024 16:00:47 +0100 Subject: [PATCH 259/303] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index dcc81a15d..6ef9fd6b5 100644 --- a/.gitignore +++ b/.gitignore @@ -39,5 +39,6 @@ lib/libesp32/berry/berry .vscode/c_cpp_properties.json .vscode/launch.json .vscode/settings.json +.vscode/extensions.json *.bak *.code-workspace From 0f0a125cdbd9faa6d6d46e4f4b1f10cbde640920 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 4 Feb 2024 16:19:59 +0100 Subject: [PATCH 260/303] Update comments GPIOViewer --- .../xdrv_121_gpioviewer.ino | 41 +++++++++++++------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 6b782b2c7..40ab97b7f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -13,6 +13,22 @@ * Resources: * GPIO Viewer: https://github.com/thelastoutpostworkshop/gpio_viewer * Server Sent Event: https://github.com/esp8266/Arduino/issues/7008 + * Tasmota hosted: https://ota.tasmota.com/tasmota/release-13.4.0/gpio_viewer_1_5/ + * + * Supported commands: + * GvViewer - Show current viewer state + * GvViewer 0 - Turn viewer off + * GvViewer 1 - Turn viewer on + * GvViewer 2 - Toggle viewer state + * GvSampling - Show current sampling interval in milliseconds + * GvSampling 1 - Select default sampling interval (GV_SAMPLING_INTERVAL) + * GvSampling 20 .. 1000 - Set sampling interval + * GvPort - Show current port + * GvPort 1 - Select default port (GV_PORT) + * GvPort 5557 - Set port + * GvUrl - Show current url + * GvUrl 1 - Select default url (GV_BASE_URL) + * GvUrl https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer_1_5/ \*********************************************************************************************/ #define XDRV_121 121 @@ -21,24 +37,22 @@ #define GV_USE_ESPINFO // Provide ESP info #ifdef ESP32 -#ifndef GV_USE_ESPINFO #define GV_USE_ESPINFO // Provide ESP info #endif -#endif #ifndef GV_PORT -#define GV_PORT 5557 // SSE webserver port +#define GV_PORT 5557 // [GvPort] SSE webserver port #endif #ifndef GV_SAMPLING_INTERVAL #define GV_SAMPLING_INTERVAL 100 // [GvSampling] milliseconds - Use Tasmota Scheduler (100) or Ticker (20..99,101..1000) #endif -#define GV_KEEP_ALIVE 1000 // milliseconds - If no activity after this do a heap size event anyway - #ifndef GV_BASE_URL -#define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer_1_5/" +#define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer_1_5/" // [GvUrl] #endif +#define GV_KEEP_ALIVE 1000 // milliseconds - If no activity after this do a heap size event anyway + const char *GVRelease = "1.5.0"; #ifdef USE_UNISHOX_COMPRESSION @@ -71,8 +85,8 @@ typedef struct { uint32_t lastSentWithNoActivity; uint32_t freeHeap; uint32_t freePSRAM; - uint32_t sampling; - uint32_t init_done; + uint16_t sampling; + uint16_t init_done; uint16_t port; bool mutex; bool sse_ready; @@ -82,7 +96,7 @@ WiFiClient GVWebClient; #ifdef GV_INPUT_DETECTION -int GetPinMode(uint8_t pin) { +int GetPinMode(uint32_t pin) { #ifdef ESP8266 if (pin > MAX_GPIO_PIN -2) { return -1; } // Skip GPIO16 and Analog0 #endif // ESP8266 @@ -436,7 +450,7 @@ void (* const GVCommand[])(void) PROGMEM = { void CmndGvViewer(void) { /* GvViewer - Show current viewer state GvViewer 0 - Turn viewer off - GvViewer 1 - Turn viewer On + GvViewer 1 - Turn viewer on GvViewer 2 - Toggle viewer state */ GVInit(); @@ -461,18 +475,19 @@ void CmndGvViewer(void) { void CmndGvSampling(void) { /* GvSampling - Show current sampling interval + GvSampling 1 - Set default sampling interval GvSampling 20 .. 1000 - Set sampling interval */ GVInit(); - if ((XdrvMailbox.payload >= 20) && (XdrvMailbox.payload <= 1000)) { + if ((SC_DEFAULT == XdrvMailbox.payload) || ((XdrvMailbox.payload >= 20) && (XdrvMailbox.payload <= 1000))) { GVCloseEvent(); // Stop current updates - GV->sampling = XdrvMailbox.payload; // 20 - 1000 milliseconds + GV->sampling = (SC_DEFAULT == XdrvMailbox.payload) ? GV_SAMPLING_INTERVAL : XdrvMailbox.payload; // 20 - 1000 milliseconds } ResponseCmndNumber(GV->sampling); } void CmndGvPort(void) { - /* GvPort - Show vurrent port + /* GvPort - Show current port GvPort 1 - Select default port GvPort 5557 - Set port */ From dec230c19f921d5d3c5684cdbc255033439092cd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 4 Feb 2024 16:31:17 +0100 Subject: [PATCH 261/303] Update xdrv_121_gpioviewer.ino --- tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 40ab97b7f..8308c62ab 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -34,11 +34,7 @@ #define XDRV_121 121 //#define GV_INPUT_DETECTION // Report type of digital input - #define GV_USE_ESPINFO // Provide ESP info -#ifdef ESP32 -#define GV_USE_ESPINFO // Provide ESP info -#endif #ifndef GV_PORT #define GV_PORT 5557 // [GvPort] SSE webserver port @@ -46,7 +42,6 @@ #ifndef GV_SAMPLING_INTERVAL #define GV_SAMPLING_INTERVAL 100 // [GvSampling] milliseconds - Use Tasmota Scheduler (100) or Ticker (20..99,101..1000) #endif - #ifndef GV_BASE_URL #define GV_BASE_URL "https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer_1_5/" // [GvUrl] #endif From 4bdf1aafb58169cc1e92cefa92e4bc1996d248c4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 4 Feb 2024 16:49:35 +0100 Subject: [PATCH 262/303] Update xdrv_121_gpioviewer.ino --- .../tasmota_xdrv_driver/xdrv_121_gpioviewer.ino | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 8308c62ab..5a2da52b8 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -110,15 +110,17 @@ int GetPinMode(uint32_t pin) { #endif // GV_INPUT_DETECTION -void GVInit(void) { +bool GVInit(void) { if (!GV) { GV = (tGV*)calloc(sizeof(tGV), 1); if (GV) { GV->sampling = (GV_SAMPLING_INTERVAL < 20) ? 20 : GV_SAMPLING_INTERVAL; GV->baseUrl = GV_BASE_URL; GV->port = GV_PORT; + return true; } } + return false; } void GVStop(void) { @@ -448,7 +450,7 @@ void CmndGvViewer(void) { GvViewer 1 - Turn viewer on GvViewer 2 - Toggle viewer state */ - GVInit(); + if (!GVInit()) { return; } if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { uint32_t state = XdrvMailbox.payload; if (2 == state) { // Toggle @@ -473,7 +475,7 @@ void CmndGvSampling(void) { GvSampling 1 - Set default sampling interval GvSampling 20 .. 1000 - Set sampling interval */ - GVInit(); + if (!GVInit()) { return; } if ((SC_DEFAULT == XdrvMailbox.payload) || ((XdrvMailbox.payload >= 20) && (XdrvMailbox.payload <= 1000))) { GVCloseEvent(); // Stop current updates GV->sampling = (SC_DEFAULT == XdrvMailbox.payload) ? GV_SAMPLING_INTERVAL : XdrvMailbox.payload; // 20 - 1000 milliseconds @@ -486,7 +488,7 @@ void CmndGvPort(void) { GvPort 1 - Select default port GvPort 5557 - Set port */ - GVInit(); + if (!GVInit()) { return; } if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 65536)) { GVCloseEvent(); // Stop current updates GV->port = (SC_DEFAULT == XdrvMailbox.payload) ? GV_PORT : XdrvMailbox.payload; @@ -499,7 +501,7 @@ void CmndGvUrl(void) { GvUrl 1 - Select default url GvUrl https://thelastoutpostworkshop.github.io/microcontroller_devkit/gpio_viewer_1_5/ */ - GVInit(); + if (!GVInit()) { return; } if (XdrvMailbox.data_len > 0) { GVCloseEvent(); // Stop current updates GV->baseUrl = (SC_DEFAULT == XdrvMailbox.payload) ? GV_BASE_URL : XdrvMailbox.data; @@ -521,7 +523,7 @@ void GVSetupAndStart(void) { AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_GPIO_VIEWER)); - GVInit(); + if (!GVInit()) { return; } GVBegin(); // Start WebServer char redirect[100]; From 08ac7541aa6b53d68f7593b70ea789f50eec5d5f Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 4 Feb 2024 22:54:57 +0100 Subject: [PATCH 263/303] Matter fix Google Home removal of device (#20663) * Matter fix fabrics id type * Fix session removal * add to changelog --- CHANGELOG.md | 1 + .../src/embedded/Matter_Fabric.be | 11 + .../berry_matter/src/embedded/Matter_IM.be | 3 +- .../src/embedded/Matter_Plugin_1_Root.be | 17 +- .../src/solidify/solidified_Matter_Fabric.h | 2298 +++++++++-------- .../src/solidify/solidified_Matter_IM.h | 14 +- .../solidified_Matter_Plugin_1_Root.h | 557 ++-- 7 files changed, 1503 insertions(+), 1398 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 489896af1..486b5ab7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ All notable changes to this project will be documented in this file. ### Fixed - Berry C mapping, raise an error if too many arguments are sent (#20604) +- Matter fixed error when removing device from Google Home ### Removed diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Fabric.be b/lib/libesp32/berry_matter/src/embedded/Matter_Fabric.be index ec25bc7af..a2f3daa00 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Fabric.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Fabric.be @@ -97,6 +97,17 @@ class Matter_Fabric : Matter_Expirable def get_ca() return self.root_ca_certificate end def get_fabric_index() return self.fabric_index end + def get_fabric_id_as_int64() + var i64 = int64() + i64.frombytes(self.fabric_id) + return i64 + end + def get_device_id_as_int64() + var i64 = int64() + i64.frombytes(self.device_id) + return i64 + end + def get_admin_vendor_name() var vnd = self.admin_vendor if vnd == nil return "" end diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_IM.be b/lib/libesp32/berry_matter/src/embedded/Matter_IM.be index 9f4c8613d..628ed5a3c 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_IM.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_IM.be @@ -772,9 +772,10 @@ class Matter_IM attr_name = attr_name ? " (" + attr_name + ")" : "" if res != nil - var res_str = res.to_str_val() # get the value with anonymous tag before it is tagged, for logging if tasmota.loglevel(3) + var res_str = res.to_str_val() # get the value with anonymous tag before it is tagged, for logging tasmota.log(f"MTR: >Read_Attr1({msg.session.local_session_id:6i}) {ctx}{attr_name} - {res_str}", 3) + # tasmota.log(f"MTR: {res.tlv2raw().tohex()}", 3) end # if matter.profiler.active && tasmota.loglevel(3) # tasmota.log(f"MTR: {raw=}", 3) # TODO remove before flight diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be index 5102dd062..19ab8eb22 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be @@ -172,8 +172,8 @@ class Matter_Plugin_Root : Matter_Plugin var fab = fabrics.add_struct(nil) # encoding see p.303 fab.add_TLV(1, TLV.B2, root_ca_tlv.findsubval(9)) # RootPublicKey fab.add_TLV(2, TLV.U2, loc_fabric.get_admin_vendor()) # VendorID - fab.add_TLV(3, TLV.U8, loc_fabric.get_fabric_id()) # FabricID - fab.add_TLV(4, TLV.U8, loc_fabric.get_device_id()) # NodeID + fab.add_TLV(3, TLV.U8, loc_fabric.get_fabric_id_as_int64()) # FabricID + fab.add_TLV(4, TLV.U8, loc_fabric.get_device_id_as_int64()) # NodeID fab.add_TLV(5, TLV.UTF1, loc_fabric.get_fabric_label()) # Label fab.add_TLV(0xFE, TLV.U2, loc_fabric.get_fabric_index()) # idx end @@ -561,7 +561,7 @@ class Matter_Plugin_Root : Matter_Plugin # 2=DebugText (opt) var nocr = TLV.Matter_TLV_struct() nocr.add_TLV(0, TLV.U1, matter.SUCCESS) # Status - nocr.add_TLV(1, TLV.U1, 1) # fabric-index + nocr.add_TLV(1, TLV.U1, new_fabric.get_fabric_index()) # fabric-index ctx.command = 0x08 # NOCResponse return nocr @@ -582,7 +582,16 @@ class Matter_Plugin_Root : Matter_Plugin # defer actual removal to send a response fab.mark_for_deletion() # this should not appear anymore in the list tasmota.set_timer(2000, def () self.device.remove_fabric(fab) end) - return true # Ok + + # create NOCResponse + # 0=StatusCode + # 1=FabricIndex (1-254) (opt) + # 2=DebugText (opt) + var nocr = TLV.Matter_TLV_struct() + nocr.add_TLV(0, TLV.U1, matter.SUCCESS) # Status + nocr.add_TLV(1, TLV.U1, index) # fabric-index + ctx.command = 0x08 # NOCResponse + return nocr end end tasmota.log("MTR: RemoveFabric fabric("+str(index)+") not found", 2) diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Fabric.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Fabric.h index 26a0ed4a2..434360b2f 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Fabric.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Fabric.h @@ -6,6 +6,39 @@ extern const bclass be_class_Matter_Fabric; +/******************************************************************** +** Solidified function: get_device_id_as_int64 +********************************************************************/ +be_local_closure(Matter_Fabric_get_device_id_as_int64, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(int64), + /* K1 */ be_nested_str_weak(frombytes), + /* K2 */ be_nested_str_weak(device_id), + }), + be_str_weak(get_device_id_as_int64), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x7C040000, // 0001 CALL R1 0 + 0x8C080301, // 0002 GETMET R2 R1 K1 + 0x88100102, // 0003 GETMBR R4 R0 K2 + 0x7C080400, // 0004 CALL R2 2 + 0x80040200, // 0005 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: fabric_candidate ********************************************************************/ @@ -44,355 +77,6 @@ be_local_closure(Matter_Fabric_fabric_candidate, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: get_ca -********************************************************************/ -be_local_closure(Matter_Fabric_get_ca, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(root_ca_certificate), - }), - be_str_weak(get_ca), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_ipk_epoch_key -********************************************************************/ -be_local_closure(Matter_Fabric_get_ipk_epoch_key, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(ipk_epoch_key), - }), - be_str_weak(get_ipk_epoch_key), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_ca_pub -********************************************************************/ -be_local_closure(Matter_Fabric_get_ca_pub, /* name */ - be_nested_proto( - 6, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(root_ca_certificate), - /* K1 */ be_nested_str_weak(matter), - /* K2 */ be_nested_str_weak(TLV), - /* K3 */ be_nested_str_weak(parse), - /* K4 */ be_nested_str_weak(findsubval), - }), - be_str_weak(get_ca_pub), - &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x78060008, // 0001 JMPF R1 #000B - 0xB80A0200, // 0002 GETNGBL R2 K1 - 0x88080502, // 0003 GETMBR R2 R2 K2 - 0x8C080503, // 0004 GETMET R2 R2 K3 - 0x5C100200, // 0005 MOVE R4 R1 - 0x7C080400, // 0006 CALL R2 2 - 0x8C0C0504, // 0007 GETMET R3 R2 K4 - 0x54160008, // 0008 LDINT R5 9 - 0x7C0C0400, // 0009 CALL R3 2 - 0x80040600, // 000A RET 1 R3 - 0x80000000, // 000B RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_ipk_group_key -********************************************************************/ -be_local_closure(Matter_Fabric_get_ipk_group_key, /* name */ - be_nested_proto( - 10, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_nested_str_weak(ipk_epoch_key), - /* K1 */ be_nested_str_weak(fabric_compressed), - /* K2 */ be_nested_str_weak(crypto), - /* K3 */ be_nested_str_weak(HKDF_SHA256), - /* K4 */ be_nested_str_weak(fromstring), - /* K5 */ be_nested_str_weak(_GROUP_KEY), - /* K6 */ be_nested_str_weak(derive), - }), - be_str_weak(get_ipk_group_key), - &be_const_str_solidified, - ( &(const binstruction[25]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x4C080000, // 0001 LDNIL R2 - 0x1C040202, // 0002 EQ R1 R1 R2 - 0x74060003, // 0003 JMPT R1 #0008 - 0x88040101, // 0004 GETMBR R1 R0 K1 - 0x4C080000, // 0005 LDNIL R2 - 0x1C040202, // 0006 EQ R1 R1 R2 - 0x78060001, // 0007 JMPF R1 #000A - 0x4C040000, // 0008 LDNIL R1 - 0x80040200, // 0009 RET 1 R1 - 0xA4060400, // 000A IMPORT R1 K2 - 0x8C080303, // 000B GETMET R2 R1 K3 - 0x7C080200, // 000C CALL R2 1 - 0x600C0015, // 000D GETGBL R3 G21 - 0x7C0C0000, // 000E CALL R3 0 - 0x8C0C0704, // 000F GETMET R3 R3 K4 - 0x88140105, // 0010 GETMBR R5 R0 K5 - 0x7C0C0400, // 0011 CALL R3 2 - 0x8C100506, // 0012 GETMET R4 R2 K6 - 0x88180100, // 0013 GETMBR R6 R0 K0 - 0x881C0101, // 0014 GETMBR R7 R0 K1 - 0x5C200600, // 0015 MOVE R8 R3 - 0x5426000F, // 0016 LDINT R9 16 - 0x7C100A00, // 0017 CALL R4 5 - 0x80040800, // 0018 RET 1 R4 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_ca -********************************************************************/ -be_local_closure(Matter_Fabric_set_ca, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(root_ca_certificate), - }), - be_str_weak(set_ca), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_fabric_compressed -********************************************************************/ -be_local_closure(Matter_Fabric_get_fabric_compressed, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(fabric_compressed), - }), - be_str_weak(get_fabric_compressed), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_fabric_label -********************************************************************/ -be_local_closure(Matter_Fabric_get_fabric_label, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(fabric_label), - }), - be_str_weak(get_fabric_label), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: assign_fabric_index -********************************************************************/ -be_local_closure(Matter_Fabric_assign_fabric_index, /* name */ - be_nested_proto( - 5, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(get_fabric_index), - /* K1 */ be_nested_str_weak(set_fabric_index), - /* K2 */ be_nested_str_weak(_store), - /* K3 */ be_nested_str_weak(next_fabric_idx), - }), - be_str_weak(assign_fabric_index), - &be_const_str_solidified, - ( &(const binstruction[11]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0x4C080000, // 0002 LDNIL R2 - 0x1C040202, // 0003 EQ R1 R1 R2 - 0x78060004, // 0004 JMPF R1 #000A - 0x8C040101, // 0005 GETMET R1 R0 K1 - 0x880C0102, // 0006 GETMBR R3 R0 K2 - 0x8C0C0703, // 0007 GETMET R3 R3 K3 - 0x7C0C0200, // 0008 CALL R3 1 - 0x7C040400, // 0009 CALL R1 2 - 0x80000000, // 000A RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_noc -********************************************************************/ -be_local_closure(Matter_Fabric_get_noc, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(noc), - }), - be_str_weak(get_noc), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: log_new_fabric -********************************************************************/ -be_local_closure(Matter_Fabric_log_new_fabric, /* name */ - be_nested_proto( - 8, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(log), - /* K2 */ be_nested_str_weak(MTR_X3A_X20_X2BFabric_X20_X20_X20_X20fab_X3D_X27_X25s_X27_X20vendorid_X3D_X25s), - /* K3 */ be_nested_str_weak(get_fabric_id), - /* K4 */ be_nested_str_weak(copy), - /* K5 */ be_nested_str_weak(reverse), - /* K6 */ be_nested_str_weak(tohex), - /* K7 */ be_nested_str_weak(get_admin_vendor_name), - /* K8 */ be_const_int(3), - }), - be_str_weak(log_new_fabric), - &be_const_str_solidified, - ( &(const binstruction[18]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x600C0018, // 0002 GETGBL R3 G24 - 0x58100002, // 0003 LDCONST R4 K2 - 0x8C140103, // 0004 GETMET R5 R0 K3 - 0x7C140200, // 0005 CALL R5 1 - 0x8C140B04, // 0006 GETMET R5 R5 K4 - 0x7C140200, // 0007 CALL R5 1 - 0x8C140B05, // 0008 GETMET R5 R5 K5 - 0x7C140200, // 0009 CALL R5 1 - 0x8C140B06, // 000A GETMET R5 R5 K6 - 0x7C140200, // 000B CALL R5 1 - 0x8C180107, // 000C GETMET R6 R0 K7 - 0x7C180200, // 000D CALL R6 1 - 0x7C0C0600, // 000E CALL R3 3 - 0x58100008, // 000F LDCONST R4 K8 - 0x7C040600, // 0010 CALL R1 3 - 0x80000000, // 0011 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: set_pk ********************************************************************/ @@ -420,517 +104,6 @@ be_local_closure(Matter_Fabric_set_pk, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: mark_for_deletion -********************************************************************/ -be_local_closure(Matter_Fabric_mark_for_deletion, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(deleted), - /* K1 */ be_nested_str_weak(tasmota), - /* K2 */ be_nested_str_weak(rtc_utc), - }), - be_str_weak(mark_for_deletion), - &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0xB8060200, // 0000 GETNGBL R1 K1 - 0x8C040302, // 0001 GETMET R1 R1 K2 - 0x7C040200, // 0002 CALL R1 1 - 0x90020001, // 0003 SETMBR R0 K0 R1 - 0x80000000, // 0004 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: is_marked_for_deletion -********************************************************************/ -be_local_closure(Matter_Fabric_is_marked_for_deletion, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(deleted), - }), - be_str_weak(is_marked_for_deletion), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x4C080000, // 0001 LDNIL R2 - 0x20040202, // 0002 NE R1 R1 R2 - 0x80040200, // 0003 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: fabric_completed -********************************************************************/ -be_local_closure(Matter_Fabric_fabric_completed, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(set_no_expiration), - /* K1 */ be_nested_str_weak(set_persist), - /* K2 */ be_nested_str_weak(assign_fabric_index), - /* K3 */ be_nested_str_weak(_store), - /* K4 */ be_nested_str_weak(add_fabric), - }), - be_str_weak(fabric_completed), - &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x7C040200, // 0001 CALL R1 1 - 0x8C040101, // 0002 GETMET R1 R0 K1 - 0x500C0200, // 0003 LDBOOL R3 1 0 - 0x7C040400, // 0004 CALL R1 2 - 0x8C040102, // 0005 GETMET R1 R0 K2 - 0x7C040200, // 0006 CALL R1 1 - 0x88040103, // 0007 GETMBR R1 R0 K3 - 0x8C040304, // 0008 GETMET R1 R1 K4 - 0x5C0C0000, // 0009 MOVE R3 R0 - 0x7C040400, // 000A CALL R1 2 - 0x80000000, // 000B RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: before_remove -********************************************************************/ -be_local_closure(Matter_Fabric_before_remove, /* name */ - be_nested_proto( - 7, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 8]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota), - /* K1 */ be_nested_str_weak(log), - /* K2 */ be_nested_str_weak(MTR_X3A_X20_X2DFabric_X20_X20_X20_X20fab_X3D_X27_X25s_X27_X20_X28removed_X29), - /* K3 */ be_nested_str_weak(get_fabric_id), - /* K4 */ be_nested_str_weak(copy), - /* K5 */ be_nested_str_weak(reverse), - /* K6 */ be_nested_str_weak(tohex), - /* K7 */ be_const_int(3), - }), - be_str_weak(before_remove), - &be_const_str_solidified, - ( &(const binstruction[16]) { /* code */ - 0xB8060000, // 0000 GETNGBL R1 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x600C0018, // 0002 GETGBL R3 G24 - 0x58100002, // 0003 LDCONST R4 K2 - 0x8C140103, // 0004 GETMET R5 R0 K3 - 0x7C140200, // 0005 CALL R5 1 - 0x8C140B04, // 0006 GETMET R5 R5 K4 - 0x7C140200, // 0007 CALL R5 1 - 0x8C140B05, // 0008 GETMET R5 R5 K5 - 0x7C140200, // 0009 CALL R5 1 - 0x8C140B06, // 000A GETMET R5 R5 K6 - 0x7C140200, // 000B CALL R5 1 - 0x7C0C0400, // 000C CALL R3 2 - 0x58100007, // 000D LDCONST R4 K7 - 0x7C040600, // 000E CALL R1 3 - 0x80000000, // 000F RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_admin_vendor -********************************************************************/ -be_local_closure(Matter_Fabric_get_admin_vendor, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(admin_vendor), - }), - be_str_weak(get_admin_vendor), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_icac -********************************************************************/ -be_local_closure(Matter_Fabric_get_icac, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(icac), - }), - be_str_weak(get_icac), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_fabric_index -********************************************************************/ -be_local_closure(Matter_Fabric_set_fabric_index, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(fabric_index), - }), - be_str_weak(set_fabric_index), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Matter_Fabric_init, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[17]) { /* constants */ - /* K0 */ be_nested_str_weak(crypto), - /* K1 */ be_nested_str_weak(_store), - /* K2 */ be_nested_str_weak(_sessions), - /* K3 */ be_nested_str_weak(matter), - /* K4 */ be_nested_str_weak(Expirable_list), - /* K5 */ be_nested_str_weak(fabric_label), - /* K6 */ be_nested_str_weak(), - /* K7 */ be_nested_str_weak(created), - /* K8 */ be_nested_str_weak(tasmota), - /* K9 */ be_nested_str_weak(rtc_utc), - /* K10 */ be_nested_str_weak(_counter_group_data_snd_impl), - /* K11 */ be_nested_str_weak(Counter), - /* K12 */ be_nested_str_weak(_counter_group_ctrl_snd_impl), - /* K13 */ be_nested_str_weak(counter_group_data_snd), - /* K14 */ be_nested_str_weak(next), - /* K15 */ be_nested_str_weak(_GROUP_SND_INCR), - /* K16 */ be_nested_str_weak(counter_group_ctrl_snd), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[32]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0x90020201, // 0001 SETMBR R0 K1 R1 - 0xB80E0600, // 0002 GETNGBL R3 K3 - 0x8C0C0704, // 0003 GETMET R3 R3 K4 - 0x7C0C0200, // 0004 CALL R3 1 - 0x90020403, // 0005 SETMBR R0 K2 R3 - 0x90020B06, // 0006 SETMBR R0 K5 K6 - 0xB80E1000, // 0007 GETNGBL R3 K8 - 0x8C0C0709, // 0008 GETMET R3 R3 K9 - 0x7C0C0200, // 0009 CALL R3 1 - 0x90020E03, // 000A SETMBR R0 K7 R3 - 0xB80E0600, // 000B GETNGBL R3 K3 - 0x8C0C070B, // 000C GETMET R3 R3 K11 - 0x7C0C0200, // 000D CALL R3 1 - 0x90021403, // 000E SETMBR R0 K10 R3 - 0xB80E0600, // 000F GETNGBL R3 K3 - 0x8C0C070B, // 0010 GETMET R3 R3 K11 - 0x7C0C0200, // 0011 CALL R3 1 - 0x90021803, // 0012 SETMBR R0 K12 R3 - 0x880C010A, // 0013 GETMBR R3 R0 K10 - 0x8C0C070E, // 0014 GETMET R3 R3 K14 - 0x7C0C0200, // 0015 CALL R3 1 - 0x8810010F, // 0016 GETMBR R4 R0 K15 - 0x000C0604, // 0017 ADD R3 R3 R4 - 0x90021A03, // 0018 SETMBR R0 K13 R3 - 0x880C010A, // 0019 GETMBR R3 R0 K10 - 0x8C0C070E, // 001A GETMET R3 R3 K14 - 0x7C0C0200, // 001B CALL R3 1 - 0x8810010F, // 001C GETMBR R4 R0 K15 - 0x000C0604, // 001D ADD R3 R3 R4 - 0x90022003, // 001E SETMBR R0 K16 R3 - 0x80000000, // 001F RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_old_recent_session -********************************************************************/ -be_local_closure(Matter_Fabric_get_old_recent_session, /* name */ - be_nested_proto( - 7, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(_sessions), - /* K1 */ be_const_int(0), - /* K2 */ be_nested_str_weak(last_used), - /* K3 */ be_const_int(1), - }), - be_str_weak(get_old_recent_session), - &be_const_str_solidified, - ( &(const binstruction[30]) { /* code */ - 0x6008000C, // 0000 GETGBL R2 G12 - 0x880C0100, // 0001 GETMBR R3 R0 K0 - 0x7C080200, // 0002 CALL R2 1 - 0x1C080501, // 0003 EQ R2 R2 K1 - 0x780A0001, // 0004 JMPF R2 #0007 - 0x4C080000, // 0005 LDNIL R2 - 0x80040400, // 0006 RET 1 R2 - 0x88080100, // 0007 GETMBR R2 R0 K0 - 0x94080501, // 0008 GETIDX R2 R2 K1 - 0x880C0502, // 0009 GETMBR R3 R2 K2 - 0x58100003, // 000A LDCONST R4 K3 - 0x6014000C, // 000B GETGBL R5 G12 - 0x88180100, // 000C GETMBR R6 R0 K0 - 0x7C140200, // 000D CALL R5 1 - 0x14140805, // 000E LT R5 R4 R5 - 0x7816000C, // 000F JMPF R5 #001D - 0x88140100, // 0010 GETMBR R5 R0 K0 - 0x94140A04, // 0011 GETIDX R5 R5 R4 - 0x88140B02, // 0012 GETMBR R5 R5 K2 - 0x78060001, // 0013 JMPF R1 #0016 - 0x14180A03, // 0014 LT R6 R5 R3 - 0x70020000, // 0015 JMP #0017 - 0x24180A03, // 0016 GT R6 R5 R3 - 0x781A0002, // 0017 JMPF R6 #001B - 0x88180100, // 0018 GETMBR R6 R0 K0 - 0x94080C04, // 0019 GETIDX R2 R6 R4 - 0x5C0C0A00, // 001A MOVE R3 R5 - 0x00100903, // 001B ADD R4 R4 K3 - 0x7001FFED, // 001C JMP #000B - 0x80040400, // 001D RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_newest_session -********************************************************************/ -be_local_closure(Matter_Fabric_get_newest_session, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(get_old_recent_session), - }), - be_str_weak(get_newest_session), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x500C0000, // 0001 LDBOOL R3 0 0 - 0x7C040400, // 0002 CALL R1 2 - 0x80040200, // 0003 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_pk -********************************************************************/ -be_local_closure(Matter_Fabric_get_pk, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(no_private_key), - }), - be_str_weak(get_pk), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: counter_group_ctrl_snd_next -********************************************************************/ -be_local_closure(Matter_Fabric_counter_group_ctrl_snd_next, /* name */ - be_nested_proto( - 7, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[13]) { /* constants */ - /* K0 */ be_nested_str_weak(_counter_group_ctrl_snd_impl), - /* K1 */ be_nested_str_weak(next), - /* K2 */ be_nested_str_weak(tasmota), - /* K3 */ be_nested_str_weak(log), - /* K4 */ be_nested_str_weak(MTR_X3A_X20_X2E_X20_X20_X20_X20_X20_X20_X20_X20_X20_X20Counter_group_ctrl_snd_X3D_X25i), - /* K5 */ be_const_int(3), - /* K6 */ be_nested_str_weak(matter), - /* K7 */ be_nested_str_weak(Counter), - /* K8 */ be_nested_str_weak(is_greater), - /* K9 */ be_nested_str_weak(counter_group_ctrl_snd), - /* K10 */ be_nested_str_weak(_GROUP_SND_INCR), - /* K11 */ be_nested_str_weak(does_persist), - /* K12 */ be_nested_str_weak(save), - }), - be_str_weak(counter_group_ctrl_snd_next), - &be_const_str_solidified, - ( &(const binstruction[27]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x7C040200, // 0002 CALL R1 1 - 0xB80A0400, // 0003 GETNGBL R2 K2 - 0x8C080503, // 0004 GETMET R2 R2 K3 - 0x60100018, // 0005 GETGBL R4 G24 - 0x58140004, // 0006 LDCONST R5 K4 - 0x5C180200, // 0007 MOVE R6 R1 - 0x7C100400, // 0008 CALL R4 2 - 0x58140005, // 0009 LDCONST R5 K5 - 0x7C080600, // 000A CALL R2 3 - 0xB80A0C00, // 000B GETNGBL R2 K6 - 0x88080507, // 000C GETMBR R2 R2 K7 - 0x8C080508, // 000D GETMET R2 R2 K8 - 0x5C100200, // 000E MOVE R4 R1 - 0x88140109, // 000F GETMBR R5 R0 K9 - 0x7C080600, // 0010 CALL R2 3 - 0x780A0007, // 0011 JMPF R2 #001A - 0x8808010A, // 0012 GETMBR R2 R0 K10 - 0x00080202, // 0013 ADD R2 R1 R2 - 0x90021202, // 0014 SETMBR R0 K9 R2 - 0x8C08010B, // 0015 GETMET R2 R0 K11 - 0x7C080200, // 0016 CALL R2 1 - 0x780A0001, // 0017 JMPF R2 #001A - 0x8C08010C, // 0018 GETMET R2 R0 K12 - 0x7C080200, // 0019 CALL R2 1 - 0x80040200, // 001A RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_noc_icac -********************************************************************/ -be_local_closure(Matter_Fabric_set_noc_icac, /* name */ - be_nested_proto( - 3, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(noc), - /* K1 */ be_nested_str_weak(icac), - }), - be_str_weak(set_noc_icac), - &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x80000000, // 0002 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: add_session ********************************************************************/ @@ -996,9 +169,38 @@ be_local_closure(Matter_Fabric_add_session, /* name */ /******************************************************************** -** Solidified function: get_admin_subject +** Solidified function: get_oldest_session ********************************************************************/ -be_local_closure(Matter_Fabric_get_admin_subject, /* name */ +be_local_closure(Matter_Fabric_get_oldest_session, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(get_old_recent_session), + }), + be_str_weak(get_oldest_session), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x500C0200, // 0001 LDBOOL R3 1 0 + 0x7C040400, // 0002 CALL R1 2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_ipk_epoch_key +********************************************************************/ +be_local_closure(Matter_Fabric_get_ipk_epoch_key, /* name */ be_nested_proto( 2, /* nstack */ 1, /* argc */ @@ -1009,9 +211,9 @@ be_local_closure(Matter_Fabric_get_admin_subject, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(admin_subject), + /* K0 */ be_nested_str_weak(ipk_epoch_key), }), - be_str_weak(get_admin_subject), + be_str_weak(get_ipk_epoch_key), &be_const_str_solidified, ( &(const binstruction[ 2]) { /* code */ 0x88040100, // 0000 GETMBR R1 R0 K0 @@ -1023,11 +225,11 @@ be_local_closure(Matter_Fabric_get_admin_subject, /* name */ /******************************************************************** -** Solidified function: counter_group_data_snd_next +** Solidified function: get_noc ********************************************************************/ -be_local_closure(Matter_Fabric_counter_group_data_snd_next, /* name */ +be_local_closure(Matter_Fabric_get_noc, /* name */ be_nested_proto( - 7, /* nstack */ + 2, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -1035,51 +237,14 @@ be_local_closure(Matter_Fabric_counter_group_data_snd_next, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[13]) { /* constants */ - /* K0 */ be_nested_str_weak(_counter_group_data_snd_impl), - /* K1 */ be_nested_str_weak(next), - /* K2 */ be_nested_str_weak(tasmota), - /* K3 */ be_nested_str_weak(log), - /* K4 */ be_nested_str_weak(MTR_X3A_X20_X2E_X20_X20_X20_X20_X20_X20_X20_X20_X20_X20Counter_group_data_snd_X3D_X25i), - /* K5 */ be_const_int(3), - /* K6 */ be_nested_str_weak(matter), - /* K7 */ be_nested_str_weak(Counter), - /* K8 */ be_nested_str_weak(is_greater), - /* K9 */ be_nested_str_weak(counter_group_data_snd), - /* K10 */ be_nested_str_weak(_GROUP_SND_INCR), - /* K11 */ be_nested_str_weak(does_persist), - /* K12 */ be_nested_str_weak(save), + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(noc), }), - be_str_weak(counter_group_data_snd_next), + be_str_weak(get_noc), &be_const_str_solidified, - ( &(const binstruction[27]) { /* code */ + ( &(const binstruction[ 2]) { /* code */ 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x7C040200, // 0002 CALL R1 1 - 0xB80A0400, // 0003 GETNGBL R2 K2 - 0x8C080503, // 0004 GETMET R2 R2 K3 - 0x60100018, // 0005 GETGBL R4 G24 - 0x58140004, // 0006 LDCONST R5 K4 - 0x5C180200, // 0007 MOVE R6 R1 - 0x7C100400, // 0008 CALL R4 2 - 0x58140005, // 0009 LDCONST R5 K5 - 0x7C080600, // 000A CALL R2 3 - 0xB80A0C00, // 000B GETNGBL R2 K6 - 0x88080507, // 000C GETMBR R2 R2 K7 - 0x8C080508, // 000D GETMET R2 R2 K8 - 0x5C100200, // 000E MOVE R4 R1 - 0x88140109, // 000F GETMBR R5 R0 K9 - 0x7C080600, // 0010 CALL R2 3 - 0x780A0007, // 0011 JMPF R2 #001A - 0x8808010A, // 0012 GETMBR R2 R0 K10 - 0x00080202, // 0013 ADD R2 R1 R2 - 0x90021202, // 0014 SETMBR R0 K9 R2 - 0x8C08010B, // 0015 GETMET R2 R0 K11 - 0x7C080200, // 0016 CALL R2 1 - 0x780A0001, // 0017 JMPF R2 #001A - 0x8C08010C, // 0018 GETMET R2 R0 K12 - 0x7C080200, // 0019 CALL R2 1 - 0x80040200, // 001A RET 1 R1 + 0x80040200, // 0001 RET 1 R1 }) ) ); @@ -1087,12 +252,93 @@ be_local_closure(Matter_Fabric_counter_group_data_snd_next, /* name */ /******************************************************************** -** Solidified function: set_fabric_device +** Solidified function: get_device_id ********************************************************************/ -be_local_closure(Matter_Fabric_set_fabric_device, /* name */ +be_local_closure(Matter_Fabric_get_device_id, /* name */ be_nested_proto( - 7, /* nstack */ - 5, /* argc */ + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(device_id), + }), + be_str_weak(get_device_id), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_icac +********************************************************************/ +be_local_closure(Matter_Fabric_get_icac, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(icac), + }), + be_str_weak(get_icac), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_fabric_index +********************************************************************/ +be_local_closure(Matter_Fabric_set_fabric_index, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(fabric_index), + }), + be_str_weak(set_fabric_index), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: fabric_completed +********************************************************************/ +be_local_closure(Matter_Fabric_fabric_completed, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -1100,26 +346,26 @@ be_local_closure(Matter_Fabric_set_fabric_device, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(fabric_id), - /* K1 */ be_nested_str_weak(device_id), - /* K2 */ be_nested_str_weak(fabric_compressed), - /* K3 */ be_nested_str_weak(fabric_parent), - /* K4 */ be_nested_str_weak(get_fabric_index), + /* K0 */ be_nested_str_weak(set_no_expiration), + /* K1 */ be_nested_str_weak(set_persist), + /* K2 */ be_nested_str_weak(assign_fabric_index), + /* K3 */ be_nested_str_weak(_store), + /* K4 */ be_nested_str_weak(add_fabric), }), - be_str_weak(set_fabric_device), + be_str_weak(fabric_completed), &be_const_str_solidified, ( &(const binstruction[12]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x90020403, // 0002 SETMBR R0 K2 R3 - 0x4C140000, // 0003 LDNIL R5 - 0x20140805, // 0004 NE R5 R4 R5 - 0x78160002, // 0005 JMPF R5 #0009 - 0x8C140904, // 0006 GETMET R5 R4 K4 - 0x7C140200, // 0007 CALL R5 1 - 0x70020000, // 0008 JMP #000A - 0x4C140000, // 0009 LDNIL R5 - 0x90020605, // 000A SETMBR R0 K3 R5 + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x8C040101, // 0002 GETMET R1 R0 K1 + 0x500C0200, // 0003 LDBOOL R3 1 0 + 0x7C040400, // 0004 CALL R1 2 + 0x8C040102, // 0005 GETMET R1 R0 K2 + 0x7C040200, // 0006 CALL R1 1 + 0x88040103, // 0007 GETMBR R1 R0 K3 + 0x8C040304, // 0008 GETMET R1 R1 K4 + 0x5C0C0000, // 0009 MOVE R3 R0 + 0x7C040400, // 000A CALL R1 2 0x80000000, // 000B RET 0 }) ) @@ -1128,28 +374,106 @@ be_local_closure(Matter_Fabric_set_fabric_device, /* name */ /******************************************************************** -** Solidified function: set_admin_subject_vendor +** Solidified function: get_pk ********************************************************************/ -be_local_closure(Matter_Fabric_set_admin_subject_vendor, /* name */ +be_local_closure(Matter_Fabric_get_pk, /* name */ be_nested_proto( - 3, /* nstack */ - 3, /* argc */ + 2, /* nstack */ + 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(admin_subject), - /* K1 */ be_nested_str_weak(admin_vendor), + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(no_private_key), }), - be_str_weak(set_admin_subject_vendor), + be_str_weak(get_pk), &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x80000000, // 0002 RET 0 + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: log_new_fabric +********************************************************************/ +be_local_closure(Matter_Fabric_log_new_fabric, /* name */ + be_nested_proto( + 8, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(log), + /* K2 */ be_nested_str_weak(MTR_X3A_X20_X2BFabric_X20_X20_X20_X20fab_X3D_X27_X25s_X27_X20vendorid_X3D_X25s), + /* K3 */ be_nested_str_weak(get_fabric_id), + /* K4 */ be_nested_str_weak(copy), + /* K5 */ be_nested_str_weak(reverse), + /* K6 */ be_nested_str_weak(tohex), + /* K7 */ be_nested_str_weak(get_admin_vendor_name), + /* K8 */ be_const_int(3), + }), + be_str_weak(log_new_fabric), + &be_const_str_solidified, + ( &(const binstruction[18]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x600C0018, // 0002 GETGBL R3 G24 + 0x58100002, // 0003 LDCONST R4 K2 + 0x8C140103, // 0004 GETMET R5 R0 K3 + 0x7C140200, // 0005 CALL R5 1 + 0x8C140B04, // 0006 GETMET R5 R5 K4 + 0x7C140200, // 0007 CALL R5 1 + 0x8C140B05, // 0008 GETMET R5 R5 K5 + 0x7C140200, // 0009 CALL R5 1 + 0x8C140B06, // 000A GETMET R5 R5 K6 + 0x7C140200, // 000B CALL R5 1 + 0x8C180107, // 000C GETMET R6 R0 K7 + 0x7C180200, // 000D CALL R6 1 + 0x7C0C0600, // 000E CALL R3 3 + 0x58100008, // 000F LDCONST R4 K8 + 0x7C040600, // 0010 CALL R1 3 + 0x80000000, // 0011 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_newest_session +********************************************************************/ +be_local_closure(Matter_Fabric_get_newest_session, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(get_old_recent_session), + }), + be_str_weak(get_newest_session), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x500C0000, // 0001 LDBOOL R3 0 0 + 0x7C040400, // 0002 CALL R1 2 + 0x80040200, // 0003 RET 1 R1 }) ) ); @@ -1327,11 +651,11 @@ be_local_closure(Matter_Fabric_tojson, /* name */ /******************************************************************** -** Solidified function: hydrate_post +** Solidified function: before_remove ********************************************************************/ -be_local_closure(Matter_Fabric_hydrate_post, /* name */ +be_local_closure(Matter_Fabric_before_remove, /* name */ be_nested_proto( - 4, /* nstack */ + 7, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -1339,117 +663,35 @@ be_local_closure(Matter_Fabric_hydrate_post, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(_counter_group_data_snd_impl), - /* K1 */ be_nested_str_weak(reset), - /* K2 */ be_nested_str_weak(counter_group_data_snd), - /* K3 */ be_nested_str_weak(_counter_group_ctrl_snd_impl), - /* K4 */ be_nested_str_weak(counter_group_ctrl_snd), - /* K5 */ be_nested_str_weak(val), + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota), + /* K1 */ be_nested_str_weak(log), + /* K2 */ be_nested_str_weak(MTR_X3A_X20_X2DFabric_X20_X20_X20_X20fab_X3D_X27_X25s_X27_X20_X28removed_X29), + /* K3 */ be_nested_str_weak(get_fabric_id), + /* K4 */ be_nested_str_weak(copy), + /* K5 */ be_nested_str_weak(reverse), + /* K6 */ be_nested_str_weak(tohex), + /* K7 */ be_const_int(3), }), - be_str_weak(hydrate_post), + be_str_weak(before_remove), &be_const_str_solidified, - ( &(const binstruction[17]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 + ( &(const binstruction[16]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x880C0102, // 0002 GETMBR R3 R0 K2 - 0x7C040400, // 0003 CALL R1 2 - 0x88040103, // 0004 GETMBR R1 R0 K3 - 0x8C040301, // 0005 GETMET R1 R1 K1 - 0x880C0104, // 0006 GETMBR R3 R0 K4 - 0x7C040400, // 0007 CALL R1 2 - 0x88040100, // 0008 GETMBR R1 R0 K0 - 0x8C040305, // 0009 GETMET R1 R1 K5 - 0x7C040200, // 000A CALL R1 1 - 0x90020401, // 000B SETMBR R0 K2 R1 - 0x88040103, // 000C GETMBR R1 R0 K3 - 0x8C040305, // 000D GETMET R1 R1 K5 - 0x7C040200, // 000E CALL R1 1 - 0x90020801, // 000F SETMBR R0 K4 R1 - 0x80000000, // 0010 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_oldest_session -********************************************************************/ -be_local_closure(Matter_Fabric_get_oldest_session, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(get_old_recent_session), - }), - be_str_weak(get_oldest_session), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x8C040100, // 0000 GETMET R1 R0 K0 - 0x500C0200, // 0001 LDBOOL R3 1 0 - 0x7C040400, // 0002 CALL R1 2 - 0x80040200, // 0003 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_device_id -********************************************************************/ -be_local_closure(Matter_Fabric_get_device_id, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(device_id), - }), - be_str_weak(get_device_id), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_ipk_epoch_key -********************************************************************/ -be_local_closure(Matter_Fabric_set_ipk_epoch_key, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(ipk_epoch_key), - }), - be_str_weak(set_ipk_epoch_key), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x80000000, // 0001 RET 0 + 0x600C0018, // 0002 GETGBL R3 G24 + 0x58100002, // 0003 LDCONST R4 K2 + 0x8C140103, // 0004 GETMET R5 R0 K3 + 0x7C140200, // 0005 CALL R5 1 + 0x8C140B04, // 0006 GETMET R5 R5 K4 + 0x7C140200, // 0007 CALL R5 1 + 0x8C140B05, // 0008 GETMET R5 R5 K5 + 0x7C140200, // 0009 CALL R5 1 + 0x8C140B06, // 000A GETMET R5 R5 K6 + 0x7C140200, // 000B CALL R5 1 + 0x7C0C0400, // 000C CALL R3 2 + 0x58100007, // 000D LDCONST R4 K7 + 0x7C040600, // 000E CALL R1 3 + 0x80000000, // 000F RET 0 }) ) ); @@ -1575,9 +817,102 @@ be_local_closure(Matter_Fabric_fromjson, /* name */ /******************************************************************** -** Solidified function: get_fabric_index +** Solidified function: set_admin_subject_vendor ********************************************************************/ -be_local_closure(Matter_Fabric_get_fabric_index, /* name */ +be_local_closure(Matter_Fabric_set_admin_subject_vendor, /* name */ + be_nested_proto( + 3, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(admin_subject), + /* K1 */ be_nested_str_weak(admin_vendor), + }), + be_str_weak(set_admin_subject_vendor), + &be_const_str_solidified, + ( &(const binstruction[ 3]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: counter_group_data_snd_next +********************************************************************/ +be_local_closure(Matter_Fabric_counter_group_data_snd_next, /* name */ + be_nested_proto( + 7, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[13]) { /* constants */ + /* K0 */ be_nested_str_weak(_counter_group_data_snd_impl), + /* K1 */ be_nested_str_weak(next), + /* K2 */ be_nested_str_weak(tasmota), + /* K3 */ be_nested_str_weak(log), + /* K4 */ be_nested_str_weak(MTR_X3A_X20_X2E_X20_X20_X20_X20_X20_X20_X20_X20_X20_X20Counter_group_data_snd_X3D_X25i), + /* K5 */ be_const_int(3), + /* K6 */ be_nested_str_weak(matter), + /* K7 */ be_nested_str_weak(Counter), + /* K8 */ be_nested_str_weak(is_greater), + /* K9 */ be_nested_str_weak(counter_group_data_snd), + /* K10 */ be_nested_str_weak(_GROUP_SND_INCR), + /* K11 */ be_nested_str_weak(does_persist), + /* K12 */ be_nested_str_weak(save), + }), + be_str_weak(counter_group_data_snd_next), + &be_const_str_solidified, + ( &(const binstruction[27]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0xB80A0400, // 0003 GETNGBL R2 K2 + 0x8C080503, // 0004 GETMET R2 R2 K3 + 0x60100018, // 0005 GETGBL R4 G24 + 0x58140004, // 0006 LDCONST R5 K4 + 0x5C180200, // 0007 MOVE R6 R1 + 0x7C100400, // 0008 CALL R4 2 + 0x58140005, // 0009 LDCONST R5 K5 + 0x7C080600, // 000A CALL R2 3 + 0xB80A0C00, // 000B GETNGBL R2 K6 + 0x88080507, // 000C GETMBR R2 R2 K7 + 0x8C080508, // 000D GETMET R2 R2 K8 + 0x5C100200, // 000E MOVE R4 R1 + 0x88140109, // 000F GETMBR R5 R0 K9 + 0x7C080600, // 0010 CALL R2 3 + 0x780A0007, // 0011 JMPF R2 #001A + 0x8808010A, // 0012 GETMBR R2 R0 K10 + 0x00080202, // 0013 ADD R2 R1 R2 + 0x90021202, // 0014 SETMBR R0 K9 R2 + 0x8C08010B, // 0015 GETMET R2 R0 K11 + 0x7C080200, // 0016 CALL R2 1 + 0x780A0001, // 0017 JMPF R2 #001A + 0x8C08010C, // 0018 GETMET R2 R0 K12 + 0x7C080200, // 0019 CALL R2 1 + 0x80040200, // 001A RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_fabric_compressed +********************************************************************/ +be_local_closure(Matter_Fabric_get_fabric_compressed, /* name */ be_nested_proto( 2, /* nstack */ 1, /* argc */ @@ -1588,9 +923,9 @@ be_local_closure(Matter_Fabric_get_fabric_index, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(fabric_index), + /* K0 */ be_nested_str_weak(fabric_compressed), }), - be_str_weak(get_fabric_index), + be_str_weak(get_fabric_compressed), &be_const_str_solidified, ( &(const binstruction[ 2]) { /* code */ 0x88040100, // 0000 GETMBR R1 R0 K0 @@ -1601,6 +936,389 @@ be_local_closure(Matter_Fabric_get_fabric_index, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: set_fabric_device +********************************************************************/ +be_local_closure(Matter_Fabric_set_fabric_device, /* name */ + be_nested_proto( + 7, /* nstack */ + 5, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(fabric_id), + /* K1 */ be_nested_str_weak(device_id), + /* K2 */ be_nested_str_weak(fabric_compressed), + /* K3 */ be_nested_str_weak(fabric_parent), + /* K4 */ be_nested_str_weak(get_fabric_index), + }), + be_str_weak(set_fabric_device), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x90020403, // 0002 SETMBR R0 K2 R3 + 0x4C140000, // 0003 LDNIL R5 + 0x20140805, // 0004 NE R5 R4 R5 + 0x78160002, // 0005 JMPF R5 #0009 + 0x8C140904, // 0006 GETMET R5 R4 K4 + 0x7C140200, // 0007 CALL R5 1 + 0x70020000, // 0008 JMP #000A + 0x4C140000, // 0009 LDNIL R5 + 0x90020605, // 000A SETMBR R0 K3 R5 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_ipk_epoch_key +********************************************************************/ +be_local_closure(Matter_Fabric_set_ipk_epoch_key, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(ipk_epoch_key), + }), + be_str_weak(set_ipk_epoch_key), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_ipk_group_key +********************************************************************/ +be_local_closure(Matter_Fabric_get_ipk_group_key, /* name */ + be_nested_proto( + 10, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str_weak(ipk_epoch_key), + /* K1 */ be_nested_str_weak(fabric_compressed), + /* K2 */ be_nested_str_weak(crypto), + /* K3 */ be_nested_str_weak(HKDF_SHA256), + /* K4 */ be_nested_str_weak(fromstring), + /* K5 */ be_nested_str_weak(_GROUP_KEY), + /* K6 */ be_nested_str_weak(derive), + }), + be_str_weak(get_ipk_group_key), + &be_const_str_solidified, + ( &(const binstruction[25]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x1C040202, // 0002 EQ R1 R1 R2 + 0x74060003, // 0003 JMPT R1 #0008 + 0x88040101, // 0004 GETMBR R1 R0 K1 + 0x4C080000, // 0005 LDNIL R2 + 0x1C040202, // 0006 EQ R1 R1 R2 + 0x78060001, // 0007 JMPF R1 #000A + 0x4C040000, // 0008 LDNIL R1 + 0x80040200, // 0009 RET 1 R1 + 0xA4060400, // 000A IMPORT R1 K2 + 0x8C080303, // 000B GETMET R2 R1 K3 + 0x7C080200, // 000C CALL R2 1 + 0x600C0015, // 000D GETGBL R3 G21 + 0x7C0C0000, // 000E CALL R3 0 + 0x8C0C0704, // 000F GETMET R3 R3 K4 + 0x88140105, // 0010 GETMBR R5 R0 K5 + 0x7C0C0400, // 0011 CALL R3 2 + 0x8C100506, // 0012 GETMET R4 R2 K6 + 0x88180100, // 0013 GETMBR R6 R0 K0 + 0x881C0101, // 0014 GETMBR R7 R0 K1 + 0x5C200600, // 0015 MOVE R8 R3 + 0x5426000F, // 0016 LDINT R9 16 + 0x7C100A00, // 0017 CALL R4 5 + 0x80040800, // 0018 RET 1 R4 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_fabric_id_as_int64 +********************************************************************/ +be_local_closure(Matter_Fabric_get_fabric_id_as_int64, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(int64), + /* K1 */ be_nested_str_weak(frombytes), + /* K2 */ be_nested_str_weak(fabric_id), + }), + be_str_weak(get_fabric_id_as_int64), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0xB8060000, // 0000 GETNGBL R1 K0 + 0x7C040000, // 0001 CALL R1 0 + 0x8C080301, // 0002 GETMET R2 R1 K1 + 0x88100102, // 0003 GETMBR R4 R0 K2 + 0x7C080400, // 0004 CALL R2 2 + 0x80040200, // 0005 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_admin_vendor +********************************************************************/ +be_local_closure(Matter_Fabric_get_admin_vendor, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(admin_vendor), + }), + be_str_weak(get_admin_vendor), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_ca_pub +********************************************************************/ +be_local_closure(Matter_Fabric_get_ca_pub, /* name */ + be_nested_proto( + 6, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(root_ca_certificate), + /* K1 */ be_nested_str_weak(matter), + /* K2 */ be_nested_str_weak(TLV), + /* K3 */ be_nested_str_weak(parse), + /* K4 */ be_nested_str_weak(findsubval), + }), + be_str_weak(get_ca_pub), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x78060008, // 0001 JMPF R1 #000B + 0xB80A0200, // 0002 GETNGBL R2 K1 + 0x88080502, // 0003 GETMBR R2 R2 K2 + 0x8C080503, // 0004 GETMET R2 R2 K3 + 0x5C100200, // 0005 MOVE R4 R1 + 0x7C080400, // 0006 CALL R2 2 + 0x8C0C0504, // 0007 GETMET R3 R2 K4 + 0x54160008, // 0008 LDINT R5 9 + 0x7C0C0400, // 0009 CALL R3 2 + 0x80040600, // 000A RET 1 R3 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: is_marked_for_deletion +********************************************************************/ +be_local_closure(Matter_Fabric_is_marked_for_deletion, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(deleted), + }), + be_str_weak(is_marked_for_deletion), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x20040202, // 0002 NE R1 R1 R2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Matter_Fabric_init, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[17]) { /* constants */ + /* K0 */ be_nested_str_weak(crypto), + /* K1 */ be_nested_str_weak(_store), + /* K2 */ be_nested_str_weak(_sessions), + /* K3 */ be_nested_str_weak(matter), + /* K4 */ be_nested_str_weak(Expirable_list), + /* K5 */ be_nested_str_weak(fabric_label), + /* K6 */ be_nested_str_weak(), + /* K7 */ be_nested_str_weak(created), + /* K8 */ be_nested_str_weak(tasmota), + /* K9 */ be_nested_str_weak(rtc_utc), + /* K10 */ be_nested_str_weak(_counter_group_data_snd_impl), + /* K11 */ be_nested_str_weak(Counter), + /* K12 */ be_nested_str_weak(_counter_group_ctrl_snd_impl), + /* K13 */ be_nested_str_weak(counter_group_data_snd), + /* K14 */ be_nested_str_weak(next), + /* K15 */ be_nested_str_weak(_GROUP_SND_INCR), + /* K16 */ be_nested_str_weak(counter_group_ctrl_snd), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[32]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0x90020201, // 0001 SETMBR R0 K1 R1 + 0xB80E0600, // 0002 GETNGBL R3 K3 + 0x8C0C0704, // 0003 GETMET R3 R3 K4 + 0x7C0C0200, // 0004 CALL R3 1 + 0x90020403, // 0005 SETMBR R0 K2 R3 + 0x90020B06, // 0006 SETMBR R0 K5 K6 + 0xB80E1000, // 0007 GETNGBL R3 K8 + 0x8C0C0709, // 0008 GETMET R3 R3 K9 + 0x7C0C0200, // 0009 CALL R3 1 + 0x90020E03, // 000A SETMBR R0 K7 R3 + 0xB80E0600, // 000B GETNGBL R3 K3 + 0x8C0C070B, // 000C GETMET R3 R3 K11 + 0x7C0C0200, // 000D CALL R3 1 + 0x90021403, // 000E SETMBR R0 K10 R3 + 0xB80E0600, // 000F GETNGBL R3 K3 + 0x8C0C070B, // 0010 GETMET R3 R3 K11 + 0x7C0C0200, // 0011 CALL R3 1 + 0x90021803, // 0012 SETMBR R0 K12 R3 + 0x880C010A, // 0013 GETMBR R3 R0 K10 + 0x8C0C070E, // 0014 GETMET R3 R3 K14 + 0x7C0C0200, // 0015 CALL R3 1 + 0x8810010F, // 0016 GETMBR R4 R0 K15 + 0x000C0604, // 0017 ADD R3 R3 R4 + 0x90021A03, // 0018 SETMBR R0 K13 R3 + 0x880C010A, // 0019 GETMBR R3 R0 K10 + 0x8C0C070E, // 001A GETMET R3 R3 K14 + 0x7C0C0200, // 001B CALL R3 1 + 0x8810010F, // 001C GETMBR R4 R0 K15 + 0x000C0604, // 001D ADD R3 R3 R4 + 0x90022003, // 001E SETMBR R0 K16 R3 + 0x80000000, // 001F RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_noc_icac +********************************************************************/ +be_local_closure(Matter_Fabric_set_noc_icac, /* name */ + be_nested_proto( + 3, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(noc), + /* K1 */ be_nested_str_weak(icac), + }), + be_str_weak(set_noc_icac), + &be_const_str_solidified, + ( &(const binstruction[ 3]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x80000000, // 0002 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_ca +********************************************************************/ +be_local_closure(Matter_Fabric_set_ca, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(root_ca_certificate), + }), + be_str_weak(set_ca), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x80000000, // 0001 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: get_admin_vendor_name ********************************************************************/ @@ -1650,6 +1368,243 @@ be_local_closure(Matter_Fabric_get_admin_vendor_name, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: assign_fabric_index +********************************************************************/ +be_local_closure(Matter_Fabric_assign_fabric_index, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(get_fabric_index), + /* K1 */ be_nested_str_weak(set_fabric_index), + /* K2 */ be_nested_str_weak(_store), + /* K3 */ be_nested_str_weak(next_fabric_idx), + }), + be_str_weak(assign_fabric_index), + &be_const_str_solidified, + ( &(const binstruction[11]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0x4C080000, // 0002 LDNIL R2 + 0x1C040202, // 0003 EQ R1 R1 R2 + 0x78060004, // 0004 JMPF R1 #000A + 0x8C040101, // 0005 GETMET R1 R0 K1 + 0x880C0102, // 0006 GETMBR R3 R0 K2 + 0x8C0C0703, // 0007 GETMET R3 R3 K3 + 0x7C0C0200, // 0008 CALL R3 1 + 0x7C040400, // 0009 CALL R1 2 + 0x80000000, // 000A RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_admin_subject +********************************************************************/ +be_local_closure(Matter_Fabric_get_admin_subject, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(admin_subject), + }), + be_str_weak(get_admin_subject), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_fabric_label +********************************************************************/ +be_local_closure(Matter_Fabric_get_fabric_label, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(fabric_label), + }), + be_str_weak(get_fabric_label), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_old_recent_session +********************************************************************/ +be_local_closure(Matter_Fabric_get_old_recent_session, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(_sessions), + /* K1 */ be_const_int(0), + /* K2 */ be_nested_str_weak(last_used), + /* K3 */ be_const_int(1), + }), + be_str_weak(get_old_recent_session), + &be_const_str_solidified, + ( &(const binstruction[30]) { /* code */ + 0x6008000C, // 0000 GETGBL R2 G12 + 0x880C0100, // 0001 GETMBR R3 R0 K0 + 0x7C080200, // 0002 CALL R2 1 + 0x1C080501, // 0003 EQ R2 R2 K1 + 0x780A0001, // 0004 JMPF R2 #0007 + 0x4C080000, // 0005 LDNIL R2 + 0x80040400, // 0006 RET 1 R2 + 0x88080100, // 0007 GETMBR R2 R0 K0 + 0x94080501, // 0008 GETIDX R2 R2 K1 + 0x880C0502, // 0009 GETMBR R3 R2 K2 + 0x58100003, // 000A LDCONST R4 K3 + 0x6014000C, // 000B GETGBL R5 G12 + 0x88180100, // 000C GETMBR R6 R0 K0 + 0x7C140200, // 000D CALL R5 1 + 0x14140805, // 000E LT R5 R4 R5 + 0x7816000C, // 000F JMPF R5 #001D + 0x88140100, // 0010 GETMBR R5 R0 K0 + 0x94140A04, // 0011 GETIDX R5 R5 R4 + 0x88140B02, // 0012 GETMBR R5 R5 K2 + 0x78060001, // 0013 JMPF R1 #0016 + 0x14180A03, // 0014 LT R6 R5 R3 + 0x70020000, // 0015 JMP #0017 + 0x24180A03, // 0016 GT R6 R5 R3 + 0x781A0002, // 0017 JMPF R6 #001B + 0x88180100, // 0018 GETMBR R6 R0 K0 + 0x94080C04, // 0019 GETIDX R2 R6 R4 + 0x5C0C0A00, // 001A MOVE R3 R5 + 0x00100903, // 001B ADD R4 R4 K3 + 0x7001FFED, // 001C JMP #000B + 0x80040400, // 001D RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_ca +********************************************************************/ +be_local_closure(Matter_Fabric_get_ca, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(root_ca_certificate), + }), + be_str_weak(get_ca), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: mark_for_deletion +********************************************************************/ +be_local_closure(Matter_Fabric_mark_for_deletion, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(deleted), + /* K1 */ be_nested_str_weak(tasmota), + /* K2 */ be_nested_str_weak(rtc_utc), + }), + be_str_weak(mark_for_deletion), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0xB8060200, // 0000 GETNGBL R1 K1 + 0x8C040302, // 0001 GETMET R1 R1 K2 + 0x7C040200, // 0002 CALL R1 1 + 0x90020001, // 0003 SETMBR R0 K0 R1 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_fabric_index +********************************************************************/ +be_local_closure(Matter_Fabric_get_fabric_index, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(fabric_index), + }), + be_str_weak(get_fabric_index), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: get_fabric_id ********************************************************************/ @@ -1677,6 +1632,117 @@ be_local_closure(Matter_Fabric_get_fabric_id, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: hydrate_post +********************************************************************/ +be_local_closure(Matter_Fabric_hydrate_post, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(_counter_group_data_snd_impl), + /* K1 */ be_nested_str_weak(reset), + /* K2 */ be_nested_str_weak(counter_group_data_snd), + /* K3 */ be_nested_str_weak(_counter_group_ctrl_snd_impl), + /* K4 */ be_nested_str_weak(counter_group_ctrl_snd), + /* K5 */ be_nested_str_weak(val), + }), + be_str_weak(hydrate_post), + &be_const_str_solidified, + ( &(const binstruction[17]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x880C0102, // 0002 GETMBR R3 R0 K2 + 0x7C040400, // 0003 CALL R1 2 + 0x88040103, // 0004 GETMBR R1 R0 K3 + 0x8C040301, // 0005 GETMET R1 R1 K1 + 0x880C0104, // 0006 GETMBR R3 R0 K4 + 0x7C040400, // 0007 CALL R1 2 + 0x88040100, // 0008 GETMBR R1 R0 K0 + 0x8C040305, // 0009 GETMET R1 R1 K5 + 0x7C040200, // 000A CALL R1 1 + 0x90020401, // 000B SETMBR R0 K2 R1 + 0x88040103, // 000C GETMBR R1 R0 K3 + 0x8C040305, // 000D GETMET R1 R1 K5 + 0x7C040200, // 000E CALL R1 1 + 0x90020801, // 000F SETMBR R0 K4 R1 + 0x80000000, // 0010 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: counter_group_ctrl_snd_next +********************************************************************/ +be_local_closure(Matter_Fabric_counter_group_ctrl_snd_next, /* name */ + be_nested_proto( + 7, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[13]) { /* constants */ + /* K0 */ be_nested_str_weak(_counter_group_ctrl_snd_impl), + /* K1 */ be_nested_str_weak(next), + /* K2 */ be_nested_str_weak(tasmota), + /* K3 */ be_nested_str_weak(log), + /* K4 */ be_nested_str_weak(MTR_X3A_X20_X2E_X20_X20_X20_X20_X20_X20_X20_X20_X20_X20Counter_group_ctrl_snd_X3D_X25i), + /* K5 */ be_const_int(3), + /* K6 */ be_nested_str_weak(matter), + /* K7 */ be_nested_str_weak(Counter), + /* K8 */ be_nested_str_weak(is_greater), + /* K9 */ be_nested_str_weak(counter_group_ctrl_snd), + /* K10 */ be_nested_str_weak(_GROUP_SND_INCR), + /* K11 */ be_nested_str_weak(does_persist), + /* K12 */ be_nested_str_weak(save), + }), + be_str_weak(counter_group_ctrl_snd_next), + &be_const_str_solidified, + ( &(const binstruction[27]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0xB80A0400, // 0003 GETNGBL R2 K2 + 0x8C080503, // 0004 GETMET R2 R2 K3 + 0x60100018, // 0005 GETGBL R4 G24 + 0x58140004, // 0006 LDCONST R5 K4 + 0x5C180200, // 0007 MOVE R6 R1 + 0x7C100400, // 0008 CALL R4 2 + 0x58140005, // 0009 LDCONST R5 K5 + 0x7C080600, // 000A CALL R2 3 + 0xB80A0C00, // 000B GETNGBL R2 K6 + 0x88080507, // 000C GETMBR R2 R2 K7 + 0x8C080508, // 000D GETMET R2 R2 K8 + 0x5C100200, // 000E MOVE R4 R1 + 0x88140109, // 000F GETMBR R5 R0 K9 + 0x7C080600, // 0010 CALL R2 3 + 0x780A0007, // 0011 JMPF R2 #001A + 0x8808010A, // 0012 GETMBR R2 R0 K10 + 0x00080202, // 0013 ADD R2 R1 R2 + 0x90021202, // 0014 SETMBR R0 K9 R2 + 0x8C08010B, // 0015 GETMET R2 R0 K11 + 0x7C080200, // 0016 CALL R2 1 + 0x780A0001, // 0017 JMPF R2 #001A + 0x8C08010C, // 0018 GETMET R2 R0 K12 + 0x7C080200, // 0019 CALL R2 1 + 0x80040200, // 001A RET 1 R1 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified class: Matter_Fabric ********************************************************************/ @@ -1684,71 +1750,73 @@ extern const bclass be_class_Matter_Expirable; be_local_class(Matter_Fabric, 21, &be_class_Matter_Expirable, - be_nested_map(63, + be_nested_map(65, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(_GROUP_KEY, -1), be_nested_str_weak(GroupKey_X20v1_X2E0) }, - { be_const_key_weak(counter_group_data_snd, -1), be_const_var(15) }, - { be_const_key_weak(get_ca, -1), be_const_closure(Matter_Fabric_get_ca_closure) }, - { be_const_key_weak(get_ipk_epoch_key, 28), be_const_closure(Matter_Fabric_get_ipk_epoch_key_closure) }, - { be_const_key_weak(device_id, -1), be_const_var(13) }, - { be_const_key_weak(_counter_group_data_snd_impl, -1), be_const_var(17) }, - { be_const_key_weak(fabric_index, 27), be_const_var(3) }, - { be_const_key_weak(no_private_key, 45), be_const_var(6) }, - { be_const_key_weak(get_ipk_group_key, -1), be_const_closure(Matter_Fabric_get_ipk_group_key_closure) }, - { be_const_key_weak(set_ca, -1), be_const_closure(Matter_Fabric_set_ca_closure) }, - { be_const_key_weak(get_fabric_compressed, 0), be_const_closure(Matter_Fabric_get_fabric_compressed_closure) }, - { be_const_key_weak(fabric_compressed, -1), be_const_var(12) }, - { be_const_key_weak(get_fabric_label, 48), be_const_closure(Matter_Fabric_get_fabric_label_closure) }, + { be_const_key_weak(get_device_id_as_int64, -1), be_const_closure(Matter_Fabric_get_device_id_as_int64_closure) }, { be_const_key_weak(admin_vendor, -1), be_const_var(20) }, - { be_const_key_weak(before_remove, -1), be_const_closure(Matter_Fabric_before_remove_closure) }, - { be_const_key_weak(noc, 31), be_const_var(8) }, - { be_const_key_weak(fromjson, -1), be_const_static_closure(Matter_Fabric_fromjson_closure) }, - { be_const_key_weak(log_new_fabric, 40), be_const_closure(Matter_Fabric_log_new_fabric_closure) }, - { be_const_key_weak(_counter_group_ctrl_snd_impl, -1), be_const_var(18) }, - { be_const_key_weak(created, 5), be_const_var(1) }, - { be_const_key_weak(set_pk, 16), be_const_closure(Matter_Fabric_set_pk_closure) }, - { be_const_key_weak(mark_for_deletion, -1), be_const_closure(Matter_Fabric_mark_for_deletion_closure) }, - { be_const_key_weak(_GROUP_SND_INCR, -1), be_const_int(32) }, - { be_const_key_weak(_store, 56), be_const_var(0) }, - { be_const_key_weak(fabric_completed, -1), be_const_closure(Matter_Fabric_fabric_completed_closure) }, - { be_const_key_weak(get_device_id, -1), be_const_closure(Matter_Fabric_get_device_id_closure) }, - { be_const_key_weak(get_noc, 14), be_const_closure(Matter_Fabric_get_noc_closure) }, - { be_const_key_weak(get_oldest_session, -1), be_const_closure(Matter_Fabric_get_oldest_session_closure) }, - { be_const_key_weak(get_icac, -1), be_const_closure(Matter_Fabric_get_icac_closure) }, - { be_const_key_weak(hydrate_post, -1), be_const_closure(Matter_Fabric_hydrate_post_closure) }, - { be_const_key_weak(admin_subject, -1), be_const_var(19) }, - { be_const_key_weak(fabric_id, -1), be_const_var(11) }, - { be_const_key_weak(set_admin_subject_vendor, -1), be_const_closure(Matter_Fabric_set_admin_subject_vendor_closure) }, - { be_const_key_weak(get_ca_pub, 52), be_const_closure(Matter_Fabric_get_ca_pub_closure) }, - { be_const_key_weak(root_ca_certificate, -1), be_const_var(7) }, - { be_const_key_weak(ipk_epoch_key, -1), be_const_var(10) }, - { be_const_key_weak(icac, -1), be_const_var(9) }, - { be_const_key_weak(get_old_recent_session, -1), be_const_closure(Matter_Fabric_get_old_recent_session_closure) }, { be_const_key_weak(counter_group_ctrl_snd_next, -1), be_const_closure(Matter_Fabric_counter_group_ctrl_snd_next_closure) }, - { be_const_key_weak(get_pk, 35), be_const_closure(Matter_Fabric_get_pk_closure) }, - { be_const_key_weak(counter_group_data_snd_next, 13), be_const_closure(Matter_Fabric_counter_group_data_snd_next_closure) }, - { be_const_key_weak(get_newest_session, 38), be_const_closure(Matter_Fabric_get_newest_session_closure) }, - { be_const_key_weak(set_noc_icac, -1), be_const_closure(Matter_Fabric_set_noc_icac_closure) }, + { be_const_key_weak(hydrate_post, 12), be_const_closure(Matter_Fabric_hydrate_post_closure) }, + { be_const_key_weak(admin_subject, 63), be_const_var(19) }, + { be_const_key_weak(fabric_compressed, 36), be_const_var(12) }, + { be_const_key_weak(noc, -1), be_const_var(8) }, { be_const_key_weak(add_session, -1), be_const_closure(Matter_Fabric_add_session_closure) }, - { be_const_key_weak(set_fabric_index, 46), be_const_closure(Matter_Fabric_set_fabric_index_closure) }, - { be_const_key_weak(get_admin_subject, 18), be_const_closure(Matter_Fabric_get_admin_subject_closure) }, - { be_const_key_weak(_MAX_CASE, -1), be_const_int(5) }, - { be_const_key_weak(set_fabric_device, -1), be_const_closure(Matter_Fabric_set_fabric_device_closure) }, - { be_const_key_weak(deleted, -1), be_const_var(2) }, - { be_const_key_weak(get_admin_vendor, 32), be_const_closure(Matter_Fabric_get_admin_vendor_closure) }, - { be_const_key_weak(tojson, -1), be_const_closure(Matter_Fabric_tojson_closure) }, - { be_const_key_weak(assign_fabric_index, 29), be_const_closure(Matter_Fabric_assign_fabric_index_closure) }, - { be_const_key_weak(init, -1), be_const_closure(Matter_Fabric_init_closure) }, - { be_const_key_weak(_sessions, 6), be_const_var(5) }, - { be_const_key_weak(fabric_candidate, 25), be_const_closure(Matter_Fabric_fabric_candidate_closure) }, - { be_const_key_weak(set_ipk_epoch_key, -1), be_const_closure(Matter_Fabric_set_ipk_epoch_key_closure) }, - { be_const_key_weak(fabric_label, 59), be_const_var(14) }, + { be_const_key_weak(get_oldest_session, 22), be_const_closure(Matter_Fabric_get_oldest_session_closure) }, + { be_const_key_weak(get_ipk_epoch_key, -1), be_const_closure(Matter_Fabric_get_ipk_epoch_key_closure) }, + { be_const_key_weak(log_new_fabric, -1), be_const_closure(Matter_Fabric_log_new_fabric_closure) }, + { be_const_key_weak(fromjson, 64), be_const_static_closure(Matter_Fabric_fromjson_closure) }, { be_const_key_weak(get_fabric_index, -1), be_const_closure(Matter_Fabric_get_fabric_index_closure) }, - { be_const_key_weak(get_admin_vendor_name, -1), be_const_closure(Matter_Fabric_get_admin_vendor_name_closure) }, - { be_const_key_weak(is_marked_for_deletion, 1), be_const_closure(Matter_Fabric_is_marked_for_deletion_closure) }, - { be_const_key_weak(fabric_parent, -1), be_const_var(4) }, + { be_const_key_weak(get_icac, -1), be_const_closure(Matter_Fabric_get_icac_closure) }, + { be_const_key_weak(set_fabric_index, -1), be_const_closure(Matter_Fabric_set_fabric_index_closure) }, { be_const_key_weak(counter_group_ctrl_snd, -1), be_const_var(16) }, + { be_const_key_weak(get_noc, 4), be_const_closure(Matter_Fabric_get_noc_closure) }, + { be_const_key_weak(_counter_group_data_snd_impl, -1), be_const_var(17) }, + { be_const_key_weak(fabric_completed, -1), be_const_closure(Matter_Fabric_fabric_completed_closure) }, + { be_const_key_weak(_sessions, -1), be_const_var(5) }, + { be_const_key_weak(get_pk, -1), be_const_closure(Matter_Fabric_get_pk_closure) }, + { be_const_key_weak(mark_for_deletion, -1), be_const_closure(Matter_Fabric_mark_for_deletion_closure) }, + { be_const_key_weak(_store, 47), be_const_var(0) }, + { be_const_key_weak(get_newest_session, 58), be_const_closure(Matter_Fabric_get_newest_session_closure) }, + { be_const_key_weak(get_fabric_compressed, -1), be_const_closure(Matter_Fabric_get_fabric_compressed_closure) }, + { be_const_key_weak(before_remove, -1), be_const_closure(Matter_Fabric_before_remove_closure) }, + { be_const_key_weak(set_pk, 11), be_const_closure(Matter_Fabric_set_pk_closure) }, + { be_const_key_weak(root_ca_certificate, 37), be_const_var(7) }, + { be_const_key_weak(set_admin_subject_vendor, 29), be_const_closure(Matter_Fabric_set_admin_subject_vendor_closure) }, + { be_const_key_weak(get_old_recent_session, 42), be_const_closure(Matter_Fabric_get_old_recent_session_closure) }, + { be_const_key_weak(get_fabric_label, 10), be_const_closure(Matter_Fabric_get_fabric_label_closure) }, + { be_const_key_weak(tojson, 57), be_const_closure(Matter_Fabric_tojson_closure) }, + { be_const_key_weak(fabric_id, -1), be_const_var(11) }, + { be_const_key_weak(device_id, 24), be_const_var(13) }, + { be_const_key_weak(_counter_group_ctrl_snd_impl, -1), be_const_var(18) }, + { be_const_key_weak(_GROUP_KEY, -1), be_nested_str_weak(GroupKey_X20v1_X2E0) }, + { be_const_key_weak(set_ipk_epoch_key, -1), be_const_closure(Matter_Fabric_set_ipk_epoch_key_closure) }, + { be_const_key_weak(fabric_label, -1), be_const_var(14) }, + { be_const_key_weak(get_ipk_group_key, 2), be_const_closure(Matter_Fabric_get_ipk_group_key_closure) }, + { be_const_key_weak(get_fabric_id_as_int64, -1), be_const_closure(Matter_Fabric_get_fabric_id_as_int64_closure) }, + { be_const_key_weak(no_private_key, -1), be_const_var(6) }, + { be_const_key_weak(get_admin_vendor, -1), be_const_closure(Matter_Fabric_get_admin_vendor_closure) }, + { be_const_key_weak(_MAX_CASE, -1), be_const_int(5) }, + { be_const_key_weak(is_marked_for_deletion, -1), be_const_closure(Matter_Fabric_is_marked_for_deletion_closure) }, + { be_const_key_weak(fabric_index, -1), be_const_var(3) }, + { be_const_key_weak(init, 21), be_const_closure(Matter_Fabric_init_closure) }, + { be_const_key_weak(get_admin_vendor_name, -1), be_const_closure(Matter_Fabric_get_admin_vendor_name_closure) }, + { be_const_key_weak(set_noc_icac, 55), be_const_closure(Matter_Fabric_set_noc_icac_closure) }, + { be_const_key_weak(set_ca, -1), be_const_closure(Matter_Fabric_set_ca_closure) }, + { be_const_key_weak(fabric_parent, -1), be_const_var(4) }, + { be_const_key_weak(fabric_candidate, 46), be_const_closure(Matter_Fabric_fabric_candidate_closure) }, + { be_const_key_weak(counter_group_data_snd, -1), be_const_var(15) }, + { be_const_key_weak(assign_fabric_index, -1), be_const_closure(Matter_Fabric_assign_fabric_index_closure) }, + { be_const_key_weak(get_admin_subject, -1), be_const_closure(Matter_Fabric_get_admin_subject_closure) }, + { be_const_key_weak(created, 30), be_const_var(1) }, + { be_const_key_weak(set_fabric_device, -1), be_const_closure(Matter_Fabric_set_fabric_device_closure) }, + { be_const_key_weak(get_ca, -1), be_const_closure(Matter_Fabric_get_ca_closure) }, + { be_const_key_weak(counter_group_data_snd_next, -1), be_const_closure(Matter_Fabric_counter_group_data_snd_next_closure) }, + { be_const_key_weak(ipk_epoch_key, -1), be_const_var(10) }, + { be_const_key_weak(get_ca_pub, 3), be_const_closure(Matter_Fabric_get_ca_pub_closure) }, + { be_const_key_weak(_GROUP_SND_INCR, -1), be_const_int(32) }, + { be_const_key_weak(deleted, -1), be_const_var(2) }, { be_const_key_weak(get_fabric_id, -1), be_const_closure(Matter_Fabric_get_fabric_id_closure) }, + { be_const_key_weak(get_device_id, -1), be_const_closure(Matter_Fabric_get_device_id_closure) }, + { be_const_key_weak(icac, -1), be_const_var(9) }, })), be_str_weak(Matter_Fabric) ); diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_IM.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_IM.h index 64088807c..ffcbba55c 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_IM.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_IM.h @@ -3140,13 +3140,13 @@ be_local_closure(Matter_IM_process_read_request_solo, /* name */ 0x4C280000, // 00B3 LDNIL R10 0x2028080A, // 00B4 NE R10 R4 R10 0x782A0013, // 00B5 JMPF R10 #00CA - 0x8C280933, // 00B6 GETMET R10 R4 K51 - 0x7C280200, // 00B7 CALL R10 1 - 0xB82E2400, // 00B8 GETNGBL R11 K18 - 0x8C2C1726, // 00B9 GETMET R11 R11 K38 - 0x58340014, // 00BA LDCONST R13 K20 - 0x7C2C0400, // 00BB CALL R11 2 - 0x782E000B, // 00BC JMPF R11 #00C9 + 0xB82A2400, // 00B6 GETNGBL R10 K18 + 0x8C281526, // 00B7 GETMET R10 R10 K38 + 0x58300014, // 00B8 LDCONST R12 K20 + 0x7C280400, // 00B9 CALL R10 2 + 0x782A000D, // 00BA JMPF R10 #00C9 + 0x8C280933, // 00BB GETMET R10 R4 K51 + 0x7C280200, // 00BC CALL R10 1 0xB82E2400, // 00BD GETNGBL R11 K18 0x8C2C170B, // 00BE GETMET R11 R11 K11 0x60340018, // 00BF GETGBL R13 G24 diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h index 3e8fdd204..fe73035b0 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h @@ -88,8 +88,8 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ /* K65 */ be_nested_str_weak(get_ca), /* K66 */ be_nested_str_weak(findsubval), /* K67 */ be_nested_str_weak(get_admin_vendor), - /* K68 */ be_nested_str_weak(get_fabric_id), - /* K69 */ be_nested_str_weak(get_device_id), + /* K68 */ be_nested_str_weak(get_fabric_id_as_int64), + /* K69 */ be_nested_str_weak(get_device_id_as_int64), /* K70 */ be_nested_str_weak(get_fabric_label), /* K71 */ be_nested_str_weak(Fabric), /* K72 */ be_nested_str_weak(_MAX_CASE), @@ -1224,7 +1224,7 @@ be_local_closure(Matter_Plugin_Root_write_attribute, /* name */ ********************************************************************/ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ be_nested_proto( - 30, /* nstack */ + 31, /* nstack */ 4, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -1339,13 +1339,13 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ /* K75 */ be_nested_str_weak(is_PASE), /* K76 */ be_nested_str_weak(set_expire_in_seconds), /* K77 */ be_nested_str_weak(log_new_fabric), - /* K78 */ be_nested_str_weak(set_fabric_label), - /* K79 */ be_nested_str_weak(MTR_X3A_X20_X2E_X20_X20_X20_X20_X20_X20_X20_X20_X20_X20Update_X20fabric_X20_X27_X25s_X27_X20label_X3D_X27_X25s_X27), - /* K80 */ be_nested_str_weak(get_fabric_id), - /* K81 */ be_nested_str_weak(tohex), - /* K82 */ be_nested_str_weak(fabric_index_X3A), - /* K83 */ be_nested_str_weak(active_fabrics), - /* K84 */ be_nested_str_weak(get_fabric_index), + /* K78 */ be_nested_str_weak(get_fabric_index), + /* K79 */ be_nested_str_weak(set_fabric_label), + /* K80 */ be_nested_str_weak(MTR_X3A_X20_X2E_X20_X20_X20_X20_X20_X20_X20_X20_X20_X20Update_X20fabric_X20_X27_X25s_X27_X20label_X3D_X27_X25s_X27), + /* K81 */ be_nested_str_weak(get_fabric_id), + /* K82 */ be_nested_str_weak(tohex), + /* K83 */ be_nested_str_weak(fabric_index_X3A), + /* K84 */ be_nested_str_weak(active_fabrics), /* K85 */ be_nested_str_weak(mark_for_deletion), /* K86 */ be_nested_str_weak(set_timer), /* K87 */ be_nested_str_weak(stop_iteration), @@ -1365,7 +1365,7 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ }), be_str_weak(invoke_request), &be_const_str_solidified, - ( &(const binstruction[714]) { /* code */ + ( &(const binstruction[729]) { /* code */ 0xA4120000, // 0000 IMPORT R4 K0 0xB8160200, // 0001 GETNGBL R5 K1 0x88140B02, // 0002 GETMBR R5 R5 K2 @@ -1466,10 +1466,10 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x80041000, // 0061 RET 1 R8 0x70020000, // 0062 JMP #0064 0xB0063119, // 0063 RAISE 1 K24 K25 - 0x70020262, // 0064 JMP #02C8 + 0x70020271, // 0064 JMP #02D7 0x5422003D, // 0065 LDINT R8 62 0x1C200C08, // 0066 EQ R8 R6 R8 - 0x782201C3, // 0067 JMPF R8 #022C + 0x782201D2, // 0067 JMPF R8 #023B 0x1C200F0E, // 0068 EQ R8 R7 K14 0x7822001D, // 0069 JMPF R8 #0088 0x8C200506, // 006A GETMET R8 R2 K6 @@ -1501,7 +1501,7 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x7C280800, // 0084 CALL R10 4 0x900E0910, // 0085 SETMBR R3 K4 K16 0x80041200, // 0086 RET 1 R9 - 0x700201A2, // 0087 JMP #022B + 0x700201B1, // 0087 JMP #023A 0x1C200F05, // 0088 EQ R8 R7 K5 0x7822003C, // 0089 JMPF R8 #00C7 0x8C200506, // 008A GETMET R8 R2 K6 @@ -1564,7 +1564,7 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x7C3C0800, // 00C3 CALL R15 4 0x900E0907, // 00C4 SETMBR R3 K4 K7 0x80041C00, // 00C5 RET 1 R14 - 0x70020163, // 00C6 JMP #022B + 0x70020172, // 00C6 JMP #023A 0x54220003, // 00C7 LDINT R8 4 0x1C200E08, // 00C8 EQ R8 R7 R8 0x7822003C, // 00C9 JMPF R8 #0107 @@ -1628,7 +1628,7 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x54420004, // 0103 LDINT R16 5 0x900E0810, // 0104 SETMBR R3 K4 R16 0x80041E00, // 0105 RET 1 R15 - 0x70020123, // 0106 JMP #022B + 0x70020132, // 0106 JMP #023A 0x5422000A, // 0107 LDINT R8 11 0x1C200E08, // 0108 EQ R8 R7 R8 0x7822000B, // 0109 JMPF R8 #0116 @@ -1643,10 +1643,10 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x900E3409, // 0112 SETMBR R3 K26 R9 0x4C240000, // 0113 LDNIL R9 0x80041200, // 0114 RET 1 R9 - 0x70020114, // 0115 JMP #022B + 0x70020123, // 0115 JMP #023A 0x54220005, // 0116 LDINT R8 6 0x1C200E08, // 0117 EQ R8 R7 R8 - 0x782200B8, // 0118 JMPF R8 #01D2 + 0x782200B9, // 0118 JMPF R8 #01D3 0xB8224400, // 0119 GETNGBL R8 K34 0x8C20112C, // 011A GETMET R8 R8 K44 0x60280008, // 011B GETGBL R10 G8 @@ -1826,260 +1826,275 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x8C64310A, // 01C9 GETMET R25 R24 K10 0x586C0007, // 01CA LDCONST R27 K7 0x88700B0B, // 01CB GETMBR R28 R5 K11 - 0x58740007, // 01CC LDCONST R29 K7 - 0x7C640800, // 01CD CALL R25 4 - 0x54660007, // 01CE LDINT R25 8 - 0x900E0819, // 01CF SETMBR R3 K4 R25 - 0x80043000, // 01D0 RET 1 R24 - 0x70020058, // 01D1 JMP #022B - 0x54220008, // 01D2 LDINT R8 9 - 0x1C200E08, // 01D3 EQ R8 R7 R8 - 0x7822001E, // 01D4 JMPF R8 #01F4 - 0x8C200506, // 01D5 GETMET R8 R2 K6 - 0x58280005, // 01D6 LDCONST R10 K5 - 0x7C200400, // 01D7 CALL R8 2 - 0x8C24034E, // 01D8 GETMET R9 R1 K78 - 0x5C2C1000, // 01D9 MOVE R11 R8 - 0x7C240400, // 01DA CALL R9 2 - 0xB8264400, // 01DB GETNGBL R9 K34 - 0x8C24132C, // 01DC GETMET R9 R9 K44 - 0x602C0018, // 01DD GETGBL R11 G24 - 0x5830004F, // 01DE LDCONST R12 K79 - 0x88340312, // 01DF GETMBR R13 R1 K18 - 0x8C341B50, // 01E0 GETMET R13 R13 K80 - 0x7C340200, // 01E1 CALL R13 1 - 0x8C341B44, // 01E2 GETMET R13 R13 K68 - 0x7C340200, // 01E3 CALL R13 1 - 0x8C341B45, // 01E4 GETMET R13 R13 K69 - 0x7C340200, // 01E5 CALL R13 1 - 0x8C341B51, // 01E6 GETMET R13 R13 K81 - 0x7C340200, // 01E7 CALL R13 1 - 0x60380008, // 01E8 GETGBL R14 G8 - 0x5C3C1000, // 01E9 MOVE R15 R8 - 0x7C380200, // 01EA CALL R14 1 - 0x7C2C0600, // 01EB CALL R11 3 - 0x58300010, // 01EC LDCONST R12 K16 - 0x7C240600, // 01ED CALL R9 3 - 0xB8260200, // 01EE GETNGBL R9 K1 - 0x8824132B, // 01EF GETMBR R9 R9 K43 - 0x900E3409, // 01F0 SETMBR R3 K26 R9 - 0x4C240000, // 01F1 LDNIL R9 - 0x80041200, // 01F2 RET 1 R9 - 0x70020036, // 01F3 JMP #022B - 0x54220009, // 01F4 LDINT R8 10 - 0x1C200E08, // 01F5 EQ R8 R7 R8 - 0x78220033, // 01F6 JMPF R8 #022B - 0x8C200506, // 01F7 GETMET R8 R2 K6 - 0x58280005, // 01F8 LDCONST R10 K5 - 0x7C200400, // 01F9 CALL R8 2 - 0x60240008, // 01FA GETGBL R9 G8 - 0x5C281000, // 01FB MOVE R10 R8 - 0x7C240200, // 01FC CALL R9 1 - 0x0026A409, // 01FD ADD R9 K82 R9 - 0x900E5809, // 01FE SETMBR R3 K44 R9 - 0x60240010, // 01FF GETGBL R9 G16 - 0x88280116, // 0200 GETMBR R10 R0 K22 - 0x88281530, // 0201 GETMBR R10 R10 K48 - 0x8C281553, // 0202 GETMET R10 R10 K83 - 0x7C280200, // 0203 CALL R10 1 - 0x7C240200, // 0204 CALL R9 1 - 0xA8020012, // 0205 EXBLK 0 #0219 - 0x5C281200, // 0206 MOVE R10 R9 - 0x7C280000, // 0207 CALL R10 0 - 0x8C2C1554, // 0208 GETMET R11 R10 K84 - 0x7C2C0200, // 0209 CALL R11 1 - 0x1C2C1608, // 020A EQ R11 R11 R8 - 0x782E000A, // 020B JMPF R11 #0217 - 0x8C2C1555, // 020C GETMET R11 R10 K85 - 0x7C2C0200, // 020D CALL R11 1 - 0xB82E4400, // 020E GETNGBL R11 K34 - 0x8C2C1756, // 020F GETMET R11 R11 K86 - 0x543607CF, // 0210 LDINT R13 2000 - 0x84380000, // 0211 CLOSURE R14 P0 - 0x7C2C0600, // 0212 CALL R11 3 - 0x502C0200, // 0213 LDBOOL R11 1 0 - 0xA0000000, // 0214 CLOSE R0 - 0xA8040001, // 0215 EXBLK 1 1 - 0x80041600, // 0216 RET 1 R11 - 0xA0240000, // 0217 CLOSE R9 - 0x7001FFEC, // 0218 JMP #0206 - 0x58240057, // 0219 LDCONST R9 K87 - 0xAC240200, // 021A CATCH R9 1 0 - 0xB0080000, // 021B RAISE 2 R0 R0 - 0xB8264400, // 021C GETNGBL R9 K34 - 0x8C24132C, // 021D GETMET R9 R9 K44 - 0x602C0008, // 021E GETGBL R11 G8 - 0x5C301000, // 021F MOVE R12 R8 - 0x7C2C0200, // 0220 CALL R11 1 - 0x002EB00B, // 0221 ADD R11 K88 R11 - 0x002C1759, // 0222 ADD R11 R11 K89 - 0x5830000E, // 0223 LDCONST R12 K14 - 0x7C240600, // 0224 CALL R9 3 - 0xB8260200, // 0225 GETNGBL R9 K1 - 0x8824135A, // 0226 GETMBR R9 R9 K90 - 0x900E3409, // 0227 SETMBR R3 K26 R9 - 0x4C240000, // 0228 LDNIL R9 - 0xA0000000, // 0229 CLOSE R0 - 0x80041200, // 022A RET 1 R9 - 0x7002009B, // 022B JMP #02C8 - 0x5422003B, // 022C LDINT R8 60 - 0x1C200C08, // 022D EQ R8 R6 R8 - 0x78220085, // 022E JMPF R8 #02B5 - 0x1C200F05, // 022F EQ R8 R7 K5 - 0x78220065, // 0230 JMPF R8 #0297 - 0x8C200506, // 0231 GETMET R8 R2 K6 - 0x58280005, // 0232 LDCONST R10 K5 - 0x7C200400, // 0233 CALL R8 2 - 0x8C240506, // 0234 GETMET R9 R2 K6 - 0x582C0007, // 0235 LDCONST R11 K7 - 0x7C240400, // 0236 CALL R9 2 - 0x8C280506, // 0237 GETMET R10 R2 K6 - 0x5830000E, // 0238 LDCONST R12 K14 - 0x7C280400, // 0239 CALL R10 2 - 0x8C2C0506, // 023A GETMET R11 R2 K6 - 0x58340010, // 023B LDCONST R13 K16 - 0x7C2C0400, // 023C CALL R11 2 - 0x8C300506, // 023D GETMET R12 R2 K6 - 0x543A0003, // 023E LDINT R14 4 - 0x7C300400, // 023F CALL R12 2 - 0xB8364400, // 0240 GETNGBL R13 K34 - 0x8C341B2C, // 0241 GETMET R13 R13 K44 - 0x603C0018, // 0242 GETGBL R15 G24 - 0x5840005B, // 0243 LDCONST R16 K91 - 0x5C441000, // 0244 MOVE R17 R8 - 0x8C481351, // 0245 GETMET R18 R9 K81 - 0x7C480200, // 0246 CALL R18 1 - 0x5C4C1400, // 0247 MOVE R19 R10 - 0x5C501600, // 0248 MOVE R20 R11 - 0x8C541951, // 0249 GETMET R21 R12 K81 - 0x7C540200, // 024A CALL R21 1 - 0x7C3C0C00, // 024B CALL R15 6 - 0x54420003, // 024C LDINT R16 4 - 0x7C340600, // 024D CALL R13 3 - 0x4C340000, // 024E LDNIL R13 - 0x1C34100D, // 024F EQ R13 R8 R13 - 0x7436000B, // 0250 JMPT R13 #025D - 0x4C340000, // 0251 LDNIL R13 - 0x1C34120D, // 0252 EQ R13 R9 R13 - 0x74360008, // 0253 JMPT R13 #025D - 0x4C340000, // 0254 LDNIL R13 - 0x1C34140D, // 0255 EQ R13 R10 R13 - 0x74360005, // 0256 JMPT R13 #025D - 0x4C340000, // 0257 LDNIL R13 - 0x1C34160D, // 0258 EQ R13 R11 R13 - 0x74360002, // 0259 JMPT R13 #025D - 0x4C340000, // 025A LDNIL R13 - 0x1C34180D, // 025B EQ R13 R12 R13 - 0x78360005, // 025C JMPF R13 #0263 - 0xB8360200, // 025D GETNGBL R13 K1 - 0x88341B5C, // 025E GETMBR R13 R13 K92 - 0x900E340D, // 025F SETMBR R3 K26 R13 + 0x8C741B4E, // 01CC GETMET R29 R13 K78 + 0x7C740200, // 01CD CALL R29 1 + 0x7C640800, // 01CE CALL R25 4 + 0x54660007, // 01CF LDINT R25 8 + 0x900E0819, // 01D0 SETMBR R3 K4 R25 + 0x80043000, // 01D1 RET 1 R24 + 0x70020066, // 01D2 JMP #023A + 0x54220008, // 01D3 LDINT R8 9 + 0x1C200E08, // 01D4 EQ R8 R7 R8 + 0x7822001E, // 01D5 JMPF R8 #01F5 + 0x8C200506, // 01D6 GETMET R8 R2 K6 + 0x58280005, // 01D7 LDCONST R10 K5 + 0x7C200400, // 01D8 CALL R8 2 + 0x8C24034F, // 01D9 GETMET R9 R1 K79 + 0x5C2C1000, // 01DA MOVE R11 R8 + 0x7C240400, // 01DB CALL R9 2 + 0xB8264400, // 01DC GETNGBL R9 K34 + 0x8C24132C, // 01DD GETMET R9 R9 K44 + 0x602C0018, // 01DE GETGBL R11 G24 + 0x58300050, // 01DF LDCONST R12 K80 + 0x88340312, // 01E0 GETMBR R13 R1 K18 + 0x8C341B51, // 01E1 GETMET R13 R13 K81 + 0x7C340200, // 01E2 CALL R13 1 + 0x8C341B44, // 01E3 GETMET R13 R13 K68 + 0x7C340200, // 01E4 CALL R13 1 + 0x8C341B45, // 01E5 GETMET R13 R13 K69 + 0x7C340200, // 01E6 CALL R13 1 + 0x8C341B52, // 01E7 GETMET R13 R13 K82 + 0x7C340200, // 01E8 CALL R13 1 + 0x60380008, // 01E9 GETGBL R14 G8 + 0x5C3C1000, // 01EA MOVE R15 R8 + 0x7C380200, // 01EB CALL R14 1 + 0x7C2C0600, // 01EC CALL R11 3 + 0x58300010, // 01ED LDCONST R12 K16 + 0x7C240600, // 01EE CALL R9 3 + 0xB8260200, // 01EF GETNGBL R9 K1 + 0x8824132B, // 01F0 GETMBR R9 R9 K43 + 0x900E3409, // 01F1 SETMBR R3 K26 R9 + 0x4C240000, // 01F2 LDNIL R9 + 0x80041200, // 01F3 RET 1 R9 + 0x70020044, // 01F4 JMP #023A + 0x54220009, // 01F5 LDINT R8 10 + 0x1C200E08, // 01F6 EQ R8 R7 R8 + 0x78220041, // 01F7 JMPF R8 #023A + 0x8C200506, // 01F8 GETMET R8 R2 K6 + 0x58280005, // 01F9 LDCONST R10 K5 + 0x7C200400, // 01FA CALL R8 2 + 0x60240008, // 01FB GETGBL R9 G8 + 0x5C281000, // 01FC MOVE R10 R8 + 0x7C240200, // 01FD CALL R9 1 + 0x0026A609, // 01FE ADD R9 K83 R9 + 0x900E5809, // 01FF SETMBR R3 K44 R9 + 0x60240010, // 0200 GETGBL R9 G16 + 0x88280116, // 0201 GETMBR R10 R0 K22 + 0x88281530, // 0202 GETMBR R10 R10 K48 + 0x8C281554, // 0203 GETMET R10 R10 K84 + 0x7C280200, // 0204 CALL R10 1 + 0x7C240200, // 0205 CALL R9 1 + 0xA8020020, // 0206 EXBLK 0 #0228 + 0x5C281200, // 0207 MOVE R10 R9 + 0x7C280000, // 0208 CALL R10 0 + 0x8C2C154E, // 0209 GETMET R11 R10 K78 + 0x7C2C0200, // 020A CALL R11 1 + 0x1C2C1608, // 020B EQ R11 R11 R8 + 0x782E0018, // 020C JMPF R11 #0226 + 0x8C2C1555, // 020D GETMET R11 R10 K85 + 0x7C2C0200, // 020E CALL R11 1 + 0xB82E4400, // 020F GETNGBL R11 K34 + 0x8C2C1756, // 0210 GETMET R11 R11 K86 + 0x543607CF, // 0211 LDINT R13 2000 + 0x84380000, // 0212 CLOSURE R14 P0 + 0x7C2C0600, // 0213 CALL R11 3 + 0x8C2C0B09, // 0214 GETMET R11 R5 K9 + 0x7C2C0200, // 0215 CALL R11 1 + 0x8C30170A, // 0216 GETMET R12 R11 K10 + 0x58380005, // 0217 LDCONST R14 K5 + 0x883C0B0B, // 0218 GETMBR R15 R5 K11 + 0xB8420200, // 0219 GETNGBL R16 K1 + 0x8840212B, // 021A GETMBR R16 R16 K43 + 0x7C300800, // 021B CALL R12 4 + 0x8C30170A, // 021C GETMET R12 R11 K10 + 0x58380007, // 021D LDCONST R14 K7 + 0x883C0B0B, // 021E GETMBR R15 R5 K11 + 0x5C401000, // 021F MOVE R16 R8 + 0x7C300800, // 0220 CALL R12 4 + 0x54320007, // 0221 LDINT R12 8 + 0x900E080C, // 0222 SETMBR R3 K4 R12 + 0xA0000000, // 0223 CLOSE R0 + 0xA8040001, // 0224 EXBLK 1 1 + 0x80041600, // 0225 RET 1 R11 + 0xA0240000, // 0226 CLOSE R9 + 0x7001FFDE, // 0227 JMP #0207 + 0x58240057, // 0228 LDCONST R9 K87 + 0xAC240200, // 0229 CATCH R9 1 0 + 0xB0080000, // 022A RAISE 2 R0 R0 + 0xB8264400, // 022B GETNGBL R9 K34 + 0x8C24132C, // 022C GETMET R9 R9 K44 + 0x602C0008, // 022D GETGBL R11 G8 + 0x5C301000, // 022E MOVE R12 R8 + 0x7C2C0200, // 022F CALL R11 1 + 0x002EB00B, // 0230 ADD R11 K88 R11 + 0x002C1759, // 0231 ADD R11 R11 K89 + 0x5830000E, // 0232 LDCONST R12 K14 + 0x7C240600, // 0233 CALL R9 3 + 0xB8260200, // 0234 GETNGBL R9 K1 + 0x8824135A, // 0235 GETMBR R9 R9 K90 + 0x900E3409, // 0236 SETMBR R3 K26 R9 + 0x4C240000, // 0237 LDNIL R9 + 0xA0000000, // 0238 CLOSE R0 + 0x80041200, // 0239 RET 1 R9 + 0x7002009B, // 023A JMP #02D7 + 0x5422003B, // 023B LDINT R8 60 + 0x1C200C08, // 023C EQ R8 R6 R8 + 0x78220085, // 023D JMPF R8 #02C4 + 0x1C200F05, // 023E EQ R8 R7 K5 + 0x78220065, // 023F JMPF R8 #02A6 + 0x8C200506, // 0240 GETMET R8 R2 K6 + 0x58280005, // 0241 LDCONST R10 K5 + 0x7C200400, // 0242 CALL R8 2 + 0x8C240506, // 0243 GETMET R9 R2 K6 + 0x582C0007, // 0244 LDCONST R11 K7 + 0x7C240400, // 0245 CALL R9 2 + 0x8C280506, // 0246 GETMET R10 R2 K6 + 0x5830000E, // 0247 LDCONST R12 K14 + 0x7C280400, // 0248 CALL R10 2 + 0x8C2C0506, // 0249 GETMET R11 R2 K6 + 0x58340010, // 024A LDCONST R13 K16 + 0x7C2C0400, // 024B CALL R11 2 + 0x8C300506, // 024C GETMET R12 R2 K6 + 0x543A0003, // 024D LDINT R14 4 + 0x7C300400, // 024E CALL R12 2 + 0xB8364400, // 024F GETNGBL R13 K34 + 0x8C341B2C, // 0250 GETMET R13 R13 K44 + 0x603C0018, // 0251 GETGBL R15 G24 + 0x5840005B, // 0252 LDCONST R16 K91 + 0x5C441000, // 0253 MOVE R17 R8 + 0x8C481352, // 0254 GETMET R18 R9 K82 + 0x7C480200, // 0255 CALL R18 1 + 0x5C4C1400, // 0256 MOVE R19 R10 + 0x5C501600, // 0257 MOVE R20 R11 + 0x8C541952, // 0258 GETMET R21 R12 K82 + 0x7C540200, // 0259 CALL R21 1 + 0x7C3C0C00, // 025A CALL R15 6 + 0x54420003, // 025B LDINT R16 4 + 0x7C340600, // 025C CALL R13 3 + 0x4C340000, // 025D LDNIL R13 + 0x1C34100D, // 025E EQ R13 R8 R13 + 0x7436000B, // 025F JMPT R13 #026C 0x4C340000, // 0260 LDNIL R13 - 0xA0000000, // 0261 CLOSE R0 - 0x80041A00, // 0262 RET 1 R13 - 0x6034000C, // 0263 GETGBL R13 G12 - 0x5C381200, // 0264 MOVE R14 R9 - 0x7C340200, // 0265 CALL R13 1 - 0x543A001F, // 0266 LDINT R14 32 - 0x543E0040, // 0267 LDINT R15 65 - 0x00381C0F, // 0268 ADD R14 R14 R15 - 0x20341A0E, // 0269 NE R13 R13 R14 - 0x7436000B, // 026A JMPT R13 #0277 - 0x6034000C, // 026B GETGBL R13 G12 - 0x5C381800, // 026C MOVE R14 R12 - 0x7C340200, // 026D CALL R13 1 - 0x543A000F, // 026E LDINT R14 16 - 0x14341A0E, // 026F LT R13 R13 R14 - 0x74360005, // 0270 JMPT R13 #0277 - 0x6034000C, // 0271 GETGBL R13 G12 - 0x5C381800, // 0272 MOVE R14 R12 - 0x7C340200, // 0273 CALL R13 1 - 0x543A001F, // 0274 LDINT R14 32 - 0x24341A0E, // 0275 GT R13 R13 R14 - 0x7836000A, // 0276 JMPF R13 #0282 - 0xB8364400, // 0277 GETNGBL R13 K34 - 0x8C341B2C, // 0278 GETMET R13 R13 K44 - 0x583C005D, // 0279 LDCONST R15 K93 - 0x5840000E, // 027A LDCONST R16 K14 - 0x7C340600, // 027B CALL R13 3 - 0xB8360200, // 027C GETNGBL R13 K1 - 0x88341B5E, // 027D GETMBR R13 R13 K94 - 0x900E340D, // 027E SETMBR R3 K26 R13 - 0x4C340000, // 027F LDNIL R13 - 0xA0000000, // 0280 CLOSE R0 - 0x80041A00, // 0281 RET 1 R13 - 0x5436001E, // 0282 LDINT R13 31 - 0x40360A0D, // 0283 CONNECT R13 K5 R13 - 0x9434120D, // 0284 GETIDX R13 R9 R13 - 0x543A001F, // 0285 LDINT R14 32 - 0x40381D40, // 0286 CONNECT R14 R14 K64 - 0x9438120E, // 0287 GETIDX R14 R9 R14 - 0x883C0116, // 0288 GETMBR R15 R0 K22 - 0x8C3C1F5F, // 0289 GETMET R15 R15 K95 - 0x5C441000, // 028A MOVE R17 R8 - 0x5C481600, // 028B MOVE R18 R11 - 0x5C4C1400, // 028C MOVE R19 R10 - 0x5C501800, // 028D MOVE R20 R12 - 0x5C541A00, // 028E MOVE R21 R13 - 0x5C581C00, // 028F MOVE R22 R14 - 0x8C5C0360, // 0290 GETMET R23 R1 K96 - 0x7C5C0200, // 0291 CALL R23 1 - 0x7C3C1000, // 0292 CALL R15 8 - 0x503C0200, // 0293 LDBOOL R15 1 0 - 0xA0000000, // 0294 CLOSE R0 - 0x80041E00, // 0295 RET 1 R15 - 0x7002001C, // 0296 JMP #02B4 - 0x1C200F07, // 0297 EQ R8 R7 K7 - 0x78220012, // 0298 JMPF R8 #02AC - 0x8C200506, // 0299 GETMET R8 R2 K6 - 0x58280005, // 029A LDCONST R10 K5 - 0x7C200400, // 029B CALL R8 2 - 0xB8264400, // 029C GETNGBL R9 K34 - 0x8C24132C, // 029D GETMET R9 R9 K44 - 0x602C0008, // 029E GETGBL R11 G8 - 0x5C301000, // 029F MOVE R12 R8 - 0x7C2C0200, // 02A0 CALL R11 1 - 0x002EC20B, // 02A1 ADD R11 K97 R11 - 0x58300010, // 02A2 LDCONST R12 K16 - 0x7C240600, // 02A3 CALL R9 3 - 0x88240116, // 02A4 GETMBR R9 R0 K22 - 0x8C241362, // 02A5 GETMET R9 R9 K98 - 0x5C2C1000, // 02A6 MOVE R11 R8 - 0x7C240400, // 02A7 CALL R9 2 - 0x50240200, // 02A8 LDBOOL R9 1 0 - 0xA0000000, // 02A9 CLOSE R0 - 0x80041200, // 02AA RET 1 R9 - 0x70020007, // 02AB JMP #02B4 - 0x1C200F0E, // 02AC EQ R8 R7 K14 - 0x78220005, // 02AD JMPF R8 #02B4 - 0x88200116, // 02AE GETMBR R8 R0 K22 - 0x8C201163, // 02AF GETMET R8 R8 K99 - 0x7C200200, // 02B0 CALL R8 1 - 0x50200200, // 02B1 LDBOOL R8 1 0 - 0xA0000000, // 02B2 CLOSE R0 - 0x80041000, // 02B3 RET 1 R8 - 0x70020012, // 02B4 JMP #02C8 - 0x54220029, // 02B5 LDINT R8 42 - 0x1C200C08, // 02B6 EQ R8 R6 R8 - 0x78220005, // 02B7 JMPF R8 #02BE - 0x1C200F05, // 02B8 EQ R8 R7 K5 - 0x78220002, // 02B9 JMPF R8 #02BD - 0x50200200, // 02BA LDBOOL R8 1 0 - 0xA0000000, // 02BB CLOSE R0 - 0x80041000, // 02BC RET 1 R8 - 0x70020009, // 02BD JMP #02C8 - 0x60200003, // 02BE GETGBL R8 G3 - 0x5C240000, // 02BF MOVE R9 R0 - 0x7C200200, // 02C0 CALL R8 1 - 0x8C201164, // 02C1 GETMET R8 R8 K100 - 0x5C280200, // 02C2 MOVE R10 R1 - 0x5C2C0400, // 02C3 MOVE R11 R2 - 0x5C300600, // 02C4 MOVE R12 R3 - 0x7C200800, // 02C5 CALL R8 4 - 0xA0000000, // 02C6 CLOSE R0 - 0x80041000, // 02C7 RET 1 R8 - 0xA0000000, // 02C8 CLOSE R0 - 0x80000000, // 02C9 RET 0 + 0x1C34120D, // 0261 EQ R13 R9 R13 + 0x74360008, // 0262 JMPT R13 #026C + 0x4C340000, // 0263 LDNIL R13 + 0x1C34140D, // 0264 EQ R13 R10 R13 + 0x74360005, // 0265 JMPT R13 #026C + 0x4C340000, // 0266 LDNIL R13 + 0x1C34160D, // 0267 EQ R13 R11 R13 + 0x74360002, // 0268 JMPT R13 #026C + 0x4C340000, // 0269 LDNIL R13 + 0x1C34180D, // 026A EQ R13 R12 R13 + 0x78360005, // 026B JMPF R13 #0272 + 0xB8360200, // 026C GETNGBL R13 K1 + 0x88341B5C, // 026D GETMBR R13 R13 K92 + 0x900E340D, // 026E SETMBR R3 K26 R13 + 0x4C340000, // 026F LDNIL R13 + 0xA0000000, // 0270 CLOSE R0 + 0x80041A00, // 0271 RET 1 R13 + 0x6034000C, // 0272 GETGBL R13 G12 + 0x5C381200, // 0273 MOVE R14 R9 + 0x7C340200, // 0274 CALL R13 1 + 0x543A001F, // 0275 LDINT R14 32 + 0x543E0040, // 0276 LDINT R15 65 + 0x00381C0F, // 0277 ADD R14 R14 R15 + 0x20341A0E, // 0278 NE R13 R13 R14 + 0x7436000B, // 0279 JMPT R13 #0286 + 0x6034000C, // 027A GETGBL R13 G12 + 0x5C381800, // 027B MOVE R14 R12 + 0x7C340200, // 027C CALL R13 1 + 0x543A000F, // 027D LDINT R14 16 + 0x14341A0E, // 027E LT R13 R13 R14 + 0x74360005, // 027F JMPT R13 #0286 + 0x6034000C, // 0280 GETGBL R13 G12 + 0x5C381800, // 0281 MOVE R14 R12 + 0x7C340200, // 0282 CALL R13 1 + 0x543A001F, // 0283 LDINT R14 32 + 0x24341A0E, // 0284 GT R13 R13 R14 + 0x7836000A, // 0285 JMPF R13 #0291 + 0xB8364400, // 0286 GETNGBL R13 K34 + 0x8C341B2C, // 0287 GETMET R13 R13 K44 + 0x583C005D, // 0288 LDCONST R15 K93 + 0x5840000E, // 0289 LDCONST R16 K14 + 0x7C340600, // 028A CALL R13 3 + 0xB8360200, // 028B GETNGBL R13 K1 + 0x88341B5E, // 028C GETMBR R13 R13 K94 + 0x900E340D, // 028D SETMBR R3 K26 R13 + 0x4C340000, // 028E LDNIL R13 + 0xA0000000, // 028F CLOSE R0 + 0x80041A00, // 0290 RET 1 R13 + 0x5436001E, // 0291 LDINT R13 31 + 0x40360A0D, // 0292 CONNECT R13 K5 R13 + 0x9434120D, // 0293 GETIDX R13 R9 R13 + 0x543A001F, // 0294 LDINT R14 32 + 0x40381D40, // 0295 CONNECT R14 R14 K64 + 0x9438120E, // 0296 GETIDX R14 R9 R14 + 0x883C0116, // 0297 GETMBR R15 R0 K22 + 0x8C3C1F5F, // 0298 GETMET R15 R15 K95 + 0x5C441000, // 0299 MOVE R17 R8 + 0x5C481600, // 029A MOVE R18 R11 + 0x5C4C1400, // 029B MOVE R19 R10 + 0x5C501800, // 029C MOVE R20 R12 + 0x5C541A00, // 029D MOVE R21 R13 + 0x5C581C00, // 029E MOVE R22 R14 + 0x8C5C0360, // 029F GETMET R23 R1 K96 + 0x7C5C0200, // 02A0 CALL R23 1 + 0x7C3C1000, // 02A1 CALL R15 8 + 0x503C0200, // 02A2 LDBOOL R15 1 0 + 0xA0000000, // 02A3 CLOSE R0 + 0x80041E00, // 02A4 RET 1 R15 + 0x7002001C, // 02A5 JMP #02C3 + 0x1C200F07, // 02A6 EQ R8 R7 K7 + 0x78220012, // 02A7 JMPF R8 #02BB + 0x8C200506, // 02A8 GETMET R8 R2 K6 + 0x58280005, // 02A9 LDCONST R10 K5 + 0x7C200400, // 02AA CALL R8 2 + 0xB8264400, // 02AB GETNGBL R9 K34 + 0x8C24132C, // 02AC GETMET R9 R9 K44 + 0x602C0008, // 02AD GETGBL R11 G8 + 0x5C301000, // 02AE MOVE R12 R8 + 0x7C2C0200, // 02AF CALL R11 1 + 0x002EC20B, // 02B0 ADD R11 K97 R11 + 0x58300010, // 02B1 LDCONST R12 K16 + 0x7C240600, // 02B2 CALL R9 3 + 0x88240116, // 02B3 GETMBR R9 R0 K22 + 0x8C241362, // 02B4 GETMET R9 R9 K98 + 0x5C2C1000, // 02B5 MOVE R11 R8 + 0x7C240400, // 02B6 CALL R9 2 + 0x50240200, // 02B7 LDBOOL R9 1 0 + 0xA0000000, // 02B8 CLOSE R0 + 0x80041200, // 02B9 RET 1 R9 + 0x70020007, // 02BA JMP #02C3 + 0x1C200F0E, // 02BB EQ R8 R7 K14 + 0x78220005, // 02BC JMPF R8 #02C3 + 0x88200116, // 02BD GETMBR R8 R0 K22 + 0x8C201163, // 02BE GETMET R8 R8 K99 + 0x7C200200, // 02BF CALL R8 1 + 0x50200200, // 02C0 LDBOOL R8 1 0 + 0xA0000000, // 02C1 CLOSE R0 + 0x80041000, // 02C2 RET 1 R8 + 0x70020012, // 02C3 JMP #02D7 + 0x54220029, // 02C4 LDINT R8 42 + 0x1C200C08, // 02C5 EQ R8 R6 R8 + 0x78220005, // 02C6 JMPF R8 #02CD + 0x1C200F05, // 02C7 EQ R8 R7 K5 + 0x78220002, // 02C8 JMPF R8 #02CC + 0x50200200, // 02C9 LDBOOL R8 1 0 + 0xA0000000, // 02CA CLOSE R0 + 0x80041000, // 02CB RET 1 R8 + 0x70020009, // 02CC JMP #02D7 + 0x60200003, // 02CD GETGBL R8 G3 + 0x5C240000, // 02CE MOVE R9 R0 + 0x7C200200, // 02CF CALL R8 1 + 0x8C201164, // 02D0 GETMET R8 R8 K100 + 0x5C280200, // 02D1 MOVE R10 R1 + 0x5C2C0400, // 02D2 MOVE R11 R2 + 0x5C300600, // 02D3 MOVE R12 R3 + 0x7C200800, // 02D4 CALL R8 4 + 0xA0000000, // 02D5 CLOSE R0 + 0x80041000, // 02D6 RET 1 R8 + 0xA0000000, // 02D7 CLOSE R0 + 0x80000000, // 02D8 RET 0 }) ) ); From 9502992388998eb7cf86c7fab5661a7ec7165353 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 4 Feb 2024 22:57:11 +0100 Subject: [PATCH 264/303] Gitpod refactoring (#20664) --- .gitpod.Dockerfile | 4 ++-- .gitpod.yml | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile index f16b02389..9e0648c64 100644 --- a/.gitpod.Dockerfile +++ b/.gitpod.Dockerfile @@ -1,3 +1,3 @@ -FROM gitpod/workspace-full - +FROM gitpod/workspace-python-3.11 + USER gitpod diff --git a/.gitpod.yml b/.gitpod.yml index 0425a416b..e85868905 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,11 +1,9 @@ tasks: - - command: pip3 install -U platformio && platformio run -e tasmota + - command: pip install -U platformio && pip install --upgrade pip && platformio run -t clean -e tasmota image: file: .gitpod.Dockerfile vscode: extensions: - - Atishay-Jain.All-Autocomplete - - esbenp.prettier-vscode - shardulm94.trailing-spaces From 26f469f766470d2a3f731eeebc3aca1d3450c8a9 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 4 Feb 2024 23:13:17 +0100 Subject: [PATCH 265/303] Fix UpdateFabricLabel (#20665) --- .../src/embedded/Matter_Plugin_1_Root.be | 13 +- .../solidified_Matter_Plugin_1_Root.h | 631 +++++++++--------- 2 files changed, 335 insertions(+), 309 deletions(-) diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be index 19ab8eb22..8fc3e2b60 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be @@ -555,6 +555,7 @@ class Matter_Plugin_Root : Matter_Plugin # tasmota.log("MTR: fabric=" + matter.inspect(session._fabric), 3) # tasmota.log("MTR: ------------------------------------------", 3) new_fabric.log_new_fabric() # log that we registered a new fabric + new_fabric.assign_fabric_index() # create NOCResponse # 0=StatusCode # 1=FabricIndex (1-254) (opt) @@ -569,8 +570,16 @@ class Matter_Plugin_Root : Matter_Plugin var label = val.findsubval(0) # Label string max 32 session.set_fabric_label(label) tasmota.log(format("MTR: . Update fabric '%s' label='%s'", session._fabric.get_fabric_id().copy().reverse().tohex(), str(label)), 3) - ctx.status = matter.SUCCESS # OK - return nil # trigger a standalone ack + + # create NOCResponse + # 0=StatusCode + # 1=FabricIndex (1-254) (opt) + # 2=DebugText (opt) + var nocr = TLV.Matter_TLV_struct() + nocr.add_TLV(0, TLV.U1, matter.SUCCESS) # Status + nocr.add_TLV(1, TLV.U1, session.get_fabric().get_fabric_index()) # fabric-index + ctx.command = 0x08 # NOCResponse + return nocr elif command == 0x000A # ---------- RemoveFabric ---------- var index = val.findsubval(0) # FabricIndex diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h index fe73035b0..1857edafe 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h @@ -1260,7 +1260,7 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ ), }), 1, /* has constants */ - ( &(const bvalue[101]) { /* constants */ + ( &(const bvalue[102]) { /* constants */ /* K0 */ be_nested_str_weak(crypto), /* K1 */ be_nested_str_weak(matter), /* K2 */ be_nested_str_weak(TLV), @@ -1339,33 +1339,34 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ /* K75 */ be_nested_str_weak(is_PASE), /* K76 */ be_nested_str_weak(set_expire_in_seconds), /* K77 */ be_nested_str_weak(log_new_fabric), - /* K78 */ be_nested_str_weak(get_fabric_index), - /* K79 */ be_nested_str_weak(set_fabric_label), - /* K80 */ be_nested_str_weak(MTR_X3A_X20_X2E_X20_X20_X20_X20_X20_X20_X20_X20_X20_X20Update_X20fabric_X20_X27_X25s_X27_X20label_X3D_X27_X25s_X27), - /* K81 */ be_nested_str_weak(get_fabric_id), - /* K82 */ be_nested_str_weak(tohex), - /* K83 */ be_nested_str_weak(fabric_index_X3A), - /* K84 */ be_nested_str_weak(active_fabrics), - /* K85 */ be_nested_str_weak(mark_for_deletion), - /* K86 */ be_nested_str_weak(set_timer), - /* K87 */ be_nested_str_weak(stop_iteration), - /* K88 */ be_nested_str_weak(MTR_X3A_X20RemoveFabric_X20fabric_X28), - /* K89 */ be_nested_str_weak(_X29_X20not_X20found), - /* K90 */ be_nested_str_weak(INVALID_ACTION), - /* K91 */ be_nested_str_weak(MTR_X3A_X20OpenCommissioningWindow_X28timeout_X3D_X25i_X2C_X20passcode_X3D_X25s_X2C_X20discriminator_X3D_X25i_X2C_X20iterations_X3D_X25i_X2C_X20salt_X3D_X25s_X29), - /* K92 */ be_nested_str_weak(INVALID_DATA_TYPE), - /* K93 */ be_nested_str_weak(MTR_X3A_X20wrong_X20size_X20for_X20PAKE_X20parameters), - /* K94 */ be_nested_str_weak(CONSTRAINT_ERROR), - /* K95 */ be_nested_str_weak(start_basic_commissioning), - /* K96 */ be_nested_str_weak(get_fabric), - /* K97 */ be_nested_str_weak(MTR_X3A_X20OpenBasicCommissioningWindow_X20commissioning_timeout_X3D), - /* K98 */ be_nested_str_weak(start_root_basic_commissioning), - /* K99 */ be_nested_str_weak(stop_basic_commissioning), - /* K100 */ be_nested_str_weak(invoke_request), + /* K78 */ be_nested_str_weak(assign_fabric_index), + /* K79 */ be_nested_str_weak(get_fabric_index), + /* K80 */ be_nested_str_weak(set_fabric_label), + /* K81 */ be_nested_str_weak(MTR_X3A_X20_X2E_X20_X20_X20_X20_X20_X20_X20_X20_X20_X20Update_X20fabric_X20_X27_X25s_X27_X20label_X3D_X27_X25s_X27), + /* K82 */ be_nested_str_weak(get_fabric_id), + /* K83 */ be_nested_str_weak(tohex), + /* K84 */ be_nested_str_weak(get_fabric), + /* K85 */ be_nested_str_weak(fabric_index_X3A), + /* K86 */ be_nested_str_weak(active_fabrics), + /* K87 */ be_nested_str_weak(mark_for_deletion), + /* K88 */ be_nested_str_weak(set_timer), + /* K89 */ be_nested_str_weak(stop_iteration), + /* K90 */ be_nested_str_weak(MTR_X3A_X20RemoveFabric_X20fabric_X28), + /* K91 */ be_nested_str_weak(_X29_X20not_X20found), + /* K92 */ be_nested_str_weak(INVALID_ACTION), + /* K93 */ be_nested_str_weak(MTR_X3A_X20OpenCommissioningWindow_X28timeout_X3D_X25i_X2C_X20passcode_X3D_X25s_X2C_X20discriminator_X3D_X25i_X2C_X20iterations_X3D_X25i_X2C_X20salt_X3D_X25s_X29), + /* K94 */ be_nested_str_weak(INVALID_DATA_TYPE), + /* K95 */ be_nested_str_weak(MTR_X3A_X20wrong_X20size_X20for_X20PAKE_X20parameters), + /* K96 */ be_nested_str_weak(CONSTRAINT_ERROR), + /* K97 */ be_nested_str_weak(start_basic_commissioning), + /* K98 */ be_nested_str_weak(MTR_X3A_X20OpenBasicCommissioningWindow_X20commissioning_timeout_X3D), + /* K99 */ be_nested_str_weak(start_root_basic_commissioning), + /* K100 */ be_nested_str_weak(stop_basic_commissioning), + /* K101 */ be_nested_str_weak(invoke_request), }), be_str_weak(invoke_request), &be_const_str_solidified, - ( &(const binstruction[729]) { /* code */ + ( &(const binstruction[745]) { /* code */ 0xA4120000, // 0000 IMPORT R4 K0 0xB8160200, // 0001 GETNGBL R5 K1 0x88140B02, // 0002 GETMBR R5 R5 K2 @@ -1466,10 +1467,10 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x80041000, // 0061 RET 1 R8 0x70020000, // 0062 JMP #0064 0xB0063119, // 0063 RAISE 1 K24 K25 - 0x70020271, // 0064 JMP #02D7 + 0x70020281, // 0064 JMP #02E7 0x5422003D, // 0065 LDINT R8 62 0x1C200C08, // 0066 EQ R8 R6 R8 - 0x782201D2, // 0067 JMPF R8 #023B + 0x782201E2, // 0067 JMPF R8 #024B 0x1C200F0E, // 0068 EQ R8 R7 K14 0x7822001D, // 0069 JMPF R8 #0088 0x8C200506, // 006A GETMET R8 R2 K6 @@ -1501,7 +1502,7 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x7C280800, // 0084 CALL R10 4 0x900E0910, // 0085 SETMBR R3 K4 K16 0x80041200, // 0086 RET 1 R9 - 0x700201B1, // 0087 JMP #023A + 0x700201C1, // 0087 JMP #024A 0x1C200F05, // 0088 EQ R8 R7 K5 0x7822003C, // 0089 JMPF R8 #00C7 0x8C200506, // 008A GETMET R8 R2 K6 @@ -1564,7 +1565,7 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x7C3C0800, // 00C3 CALL R15 4 0x900E0907, // 00C4 SETMBR R3 K4 K7 0x80041C00, // 00C5 RET 1 R14 - 0x70020172, // 00C6 JMP #023A + 0x70020182, // 00C6 JMP #024A 0x54220003, // 00C7 LDINT R8 4 0x1C200E08, // 00C8 EQ R8 R7 R8 0x7822003C, // 00C9 JMPF R8 #0107 @@ -1628,7 +1629,7 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x54420004, // 0103 LDINT R16 5 0x900E0810, // 0104 SETMBR R3 K4 R16 0x80041E00, // 0105 RET 1 R15 - 0x70020132, // 0106 JMP #023A + 0x70020142, // 0106 JMP #024A 0x5422000A, // 0107 LDINT R8 11 0x1C200E08, // 0108 EQ R8 R7 R8 0x7822000B, // 0109 JMPF R8 #0116 @@ -1643,10 +1644,10 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x900E3409, // 0112 SETMBR R3 K26 R9 0x4C240000, // 0113 LDNIL R9 0x80041200, // 0114 RET 1 R9 - 0x70020123, // 0115 JMP #023A + 0x70020133, // 0115 JMP #024A 0x54220005, // 0116 LDINT R8 6 0x1C200E08, // 0117 EQ R8 R7 R8 - 0x782200B9, // 0118 JMPF R8 #01D3 + 0x782200BB, // 0118 JMPF R8 #01D5 0xB8224400, // 0119 GETNGBL R8 K34 0x8C20112C, // 011A GETMET R8 R8 K44 0x60280008, // 011B GETGBL R10 G8 @@ -1815,286 +1816,302 @@ be_local_closure(Matter_Plugin_Root_invoke_request, /* name */ 0x7C600400, // 01BE CALL R24 2 0x8C601B4D, // 01BF GETMET R24 R13 K77 0x7C600200, // 01C0 CALL R24 1 - 0x8C600B09, // 01C1 GETMET R24 R5 K9 + 0x8C601B4E, // 01C1 GETMET R24 R13 K78 0x7C600200, // 01C2 CALL R24 1 - 0x8C64310A, // 01C3 GETMET R25 R24 K10 - 0x586C0005, // 01C4 LDCONST R27 K5 - 0x88700B0B, // 01C5 GETMBR R28 R5 K11 - 0xB8760200, // 01C6 GETNGBL R29 K1 - 0x88743B2B, // 01C7 GETMBR R29 R29 K43 - 0x7C640800, // 01C8 CALL R25 4 - 0x8C64310A, // 01C9 GETMET R25 R24 K10 - 0x586C0007, // 01CA LDCONST R27 K7 - 0x88700B0B, // 01CB GETMBR R28 R5 K11 - 0x8C741B4E, // 01CC GETMET R29 R13 K78 - 0x7C740200, // 01CD CALL R29 1 - 0x7C640800, // 01CE CALL R25 4 - 0x54660007, // 01CF LDINT R25 8 - 0x900E0819, // 01D0 SETMBR R3 K4 R25 - 0x80043000, // 01D1 RET 1 R24 - 0x70020066, // 01D2 JMP #023A - 0x54220008, // 01D3 LDINT R8 9 - 0x1C200E08, // 01D4 EQ R8 R7 R8 - 0x7822001E, // 01D5 JMPF R8 #01F5 - 0x8C200506, // 01D6 GETMET R8 R2 K6 - 0x58280005, // 01D7 LDCONST R10 K5 - 0x7C200400, // 01D8 CALL R8 2 - 0x8C24034F, // 01D9 GETMET R9 R1 K79 - 0x5C2C1000, // 01DA MOVE R11 R8 - 0x7C240400, // 01DB CALL R9 2 - 0xB8264400, // 01DC GETNGBL R9 K34 - 0x8C24132C, // 01DD GETMET R9 R9 K44 - 0x602C0018, // 01DE GETGBL R11 G24 - 0x58300050, // 01DF LDCONST R12 K80 - 0x88340312, // 01E0 GETMBR R13 R1 K18 - 0x8C341B51, // 01E1 GETMET R13 R13 K81 - 0x7C340200, // 01E2 CALL R13 1 - 0x8C341B44, // 01E3 GETMET R13 R13 K68 + 0x8C600B09, // 01C3 GETMET R24 R5 K9 + 0x7C600200, // 01C4 CALL R24 1 + 0x8C64310A, // 01C5 GETMET R25 R24 K10 + 0x586C0005, // 01C6 LDCONST R27 K5 + 0x88700B0B, // 01C7 GETMBR R28 R5 K11 + 0xB8760200, // 01C8 GETNGBL R29 K1 + 0x88743B2B, // 01C9 GETMBR R29 R29 K43 + 0x7C640800, // 01CA CALL R25 4 + 0x8C64310A, // 01CB GETMET R25 R24 K10 + 0x586C0007, // 01CC LDCONST R27 K7 + 0x88700B0B, // 01CD GETMBR R28 R5 K11 + 0x8C741B4F, // 01CE GETMET R29 R13 K79 + 0x7C740200, // 01CF CALL R29 1 + 0x7C640800, // 01D0 CALL R25 4 + 0x54660007, // 01D1 LDINT R25 8 + 0x900E0819, // 01D2 SETMBR R3 K4 R25 + 0x80043000, // 01D3 RET 1 R24 + 0x70020074, // 01D4 JMP #024A + 0x54220008, // 01D5 LDINT R8 9 + 0x1C200E08, // 01D6 EQ R8 R7 R8 + 0x7822002C, // 01D7 JMPF R8 #0205 + 0x8C200506, // 01D8 GETMET R8 R2 K6 + 0x58280005, // 01D9 LDCONST R10 K5 + 0x7C200400, // 01DA CALL R8 2 + 0x8C240350, // 01DB GETMET R9 R1 K80 + 0x5C2C1000, // 01DC MOVE R11 R8 + 0x7C240400, // 01DD CALL R9 2 + 0xB8264400, // 01DE GETNGBL R9 K34 + 0x8C24132C, // 01DF GETMET R9 R9 K44 + 0x602C0018, // 01E0 GETGBL R11 G24 + 0x58300051, // 01E1 LDCONST R12 K81 + 0x88340312, // 01E2 GETMBR R13 R1 K18 + 0x8C341B52, // 01E3 GETMET R13 R13 K82 0x7C340200, // 01E4 CALL R13 1 - 0x8C341B45, // 01E5 GETMET R13 R13 K69 + 0x8C341B44, // 01E5 GETMET R13 R13 K68 0x7C340200, // 01E6 CALL R13 1 - 0x8C341B52, // 01E7 GETMET R13 R13 K82 + 0x8C341B45, // 01E7 GETMET R13 R13 K69 0x7C340200, // 01E8 CALL R13 1 - 0x60380008, // 01E9 GETGBL R14 G8 - 0x5C3C1000, // 01EA MOVE R15 R8 - 0x7C380200, // 01EB CALL R14 1 - 0x7C2C0600, // 01EC CALL R11 3 - 0x58300010, // 01ED LDCONST R12 K16 - 0x7C240600, // 01EE CALL R9 3 - 0xB8260200, // 01EF GETNGBL R9 K1 - 0x8824132B, // 01F0 GETMBR R9 R9 K43 - 0x900E3409, // 01F1 SETMBR R3 K26 R9 - 0x4C240000, // 01F2 LDNIL R9 - 0x80041200, // 01F3 RET 1 R9 - 0x70020044, // 01F4 JMP #023A - 0x54220009, // 01F5 LDINT R8 10 - 0x1C200E08, // 01F6 EQ R8 R7 R8 - 0x78220041, // 01F7 JMPF R8 #023A - 0x8C200506, // 01F8 GETMET R8 R2 K6 - 0x58280005, // 01F9 LDCONST R10 K5 - 0x7C200400, // 01FA CALL R8 2 - 0x60240008, // 01FB GETGBL R9 G8 - 0x5C281000, // 01FC MOVE R10 R8 - 0x7C240200, // 01FD CALL R9 1 - 0x0026A609, // 01FE ADD R9 K83 R9 - 0x900E5809, // 01FF SETMBR R3 K44 R9 - 0x60240010, // 0200 GETGBL R9 G16 - 0x88280116, // 0201 GETMBR R10 R0 K22 - 0x88281530, // 0202 GETMBR R10 R10 K48 - 0x8C281554, // 0203 GETMET R10 R10 K84 - 0x7C280200, // 0204 CALL R10 1 - 0x7C240200, // 0205 CALL R9 1 - 0xA8020020, // 0206 EXBLK 0 #0228 - 0x5C281200, // 0207 MOVE R10 R9 - 0x7C280000, // 0208 CALL R10 0 - 0x8C2C154E, // 0209 GETMET R11 R10 K78 - 0x7C2C0200, // 020A CALL R11 1 - 0x1C2C1608, // 020B EQ R11 R11 R8 - 0x782E0018, // 020C JMPF R11 #0226 - 0x8C2C1555, // 020D GETMET R11 R10 K85 - 0x7C2C0200, // 020E CALL R11 1 - 0xB82E4400, // 020F GETNGBL R11 K34 - 0x8C2C1756, // 0210 GETMET R11 R11 K86 - 0x543607CF, // 0211 LDINT R13 2000 - 0x84380000, // 0212 CLOSURE R14 P0 - 0x7C2C0600, // 0213 CALL R11 3 - 0x8C2C0B09, // 0214 GETMET R11 R5 K9 - 0x7C2C0200, // 0215 CALL R11 1 - 0x8C30170A, // 0216 GETMET R12 R11 K10 - 0x58380005, // 0217 LDCONST R14 K5 - 0x883C0B0B, // 0218 GETMBR R15 R5 K11 - 0xB8420200, // 0219 GETNGBL R16 K1 - 0x8840212B, // 021A GETMBR R16 R16 K43 - 0x7C300800, // 021B CALL R12 4 - 0x8C30170A, // 021C GETMET R12 R11 K10 - 0x58380007, // 021D LDCONST R14 K7 - 0x883C0B0B, // 021E GETMBR R15 R5 K11 - 0x5C401000, // 021F MOVE R16 R8 - 0x7C300800, // 0220 CALL R12 4 - 0x54320007, // 0221 LDINT R12 8 - 0x900E080C, // 0222 SETMBR R3 K4 R12 - 0xA0000000, // 0223 CLOSE R0 - 0xA8040001, // 0224 EXBLK 1 1 - 0x80041600, // 0225 RET 1 R11 - 0xA0240000, // 0226 CLOSE R9 - 0x7001FFDE, // 0227 JMP #0207 - 0x58240057, // 0228 LDCONST R9 K87 - 0xAC240200, // 0229 CATCH R9 1 0 - 0xB0080000, // 022A RAISE 2 R0 R0 - 0xB8264400, // 022B GETNGBL R9 K34 - 0x8C24132C, // 022C GETMET R9 R9 K44 - 0x602C0008, // 022D GETGBL R11 G8 - 0x5C301000, // 022E MOVE R12 R8 - 0x7C2C0200, // 022F CALL R11 1 - 0x002EB00B, // 0230 ADD R11 K88 R11 - 0x002C1759, // 0231 ADD R11 R11 K89 - 0x5830000E, // 0232 LDCONST R12 K14 - 0x7C240600, // 0233 CALL R9 3 - 0xB8260200, // 0234 GETNGBL R9 K1 - 0x8824135A, // 0235 GETMBR R9 R9 K90 - 0x900E3409, // 0236 SETMBR R3 K26 R9 - 0x4C240000, // 0237 LDNIL R9 - 0xA0000000, // 0238 CLOSE R0 - 0x80041200, // 0239 RET 1 R9 - 0x7002009B, // 023A JMP #02D7 - 0x5422003B, // 023B LDINT R8 60 - 0x1C200C08, // 023C EQ R8 R6 R8 - 0x78220085, // 023D JMPF R8 #02C4 - 0x1C200F05, // 023E EQ R8 R7 K5 - 0x78220065, // 023F JMPF R8 #02A6 - 0x8C200506, // 0240 GETMET R8 R2 K6 - 0x58280005, // 0241 LDCONST R10 K5 - 0x7C200400, // 0242 CALL R8 2 - 0x8C240506, // 0243 GETMET R9 R2 K6 - 0x582C0007, // 0244 LDCONST R11 K7 - 0x7C240400, // 0245 CALL R9 2 - 0x8C280506, // 0246 GETMET R10 R2 K6 - 0x5830000E, // 0247 LDCONST R12 K14 - 0x7C280400, // 0248 CALL R10 2 - 0x8C2C0506, // 0249 GETMET R11 R2 K6 - 0x58340010, // 024A LDCONST R13 K16 - 0x7C2C0400, // 024B CALL R11 2 - 0x8C300506, // 024C GETMET R12 R2 K6 - 0x543A0003, // 024D LDINT R14 4 - 0x7C300400, // 024E CALL R12 2 - 0xB8364400, // 024F GETNGBL R13 K34 - 0x8C341B2C, // 0250 GETMET R13 R13 K44 - 0x603C0018, // 0251 GETGBL R15 G24 - 0x5840005B, // 0252 LDCONST R16 K91 - 0x5C441000, // 0253 MOVE R17 R8 - 0x8C481352, // 0254 GETMET R18 R9 K82 - 0x7C480200, // 0255 CALL R18 1 - 0x5C4C1400, // 0256 MOVE R19 R10 - 0x5C501600, // 0257 MOVE R20 R11 - 0x8C541952, // 0258 GETMET R21 R12 K82 - 0x7C540200, // 0259 CALL R21 1 - 0x7C3C0C00, // 025A CALL R15 6 - 0x54420003, // 025B LDINT R16 4 - 0x7C340600, // 025C CALL R13 3 - 0x4C340000, // 025D LDNIL R13 - 0x1C34100D, // 025E EQ R13 R8 R13 - 0x7436000B, // 025F JMPT R13 #026C - 0x4C340000, // 0260 LDNIL R13 - 0x1C34120D, // 0261 EQ R13 R9 R13 - 0x74360008, // 0262 JMPT R13 #026C - 0x4C340000, // 0263 LDNIL R13 - 0x1C34140D, // 0264 EQ R13 R10 R13 - 0x74360005, // 0265 JMPT R13 #026C - 0x4C340000, // 0266 LDNIL R13 - 0x1C34160D, // 0267 EQ R13 R11 R13 - 0x74360002, // 0268 JMPT R13 #026C - 0x4C340000, // 0269 LDNIL R13 - 0x1C34180D, // 026A EQ R13 R12 R13 - 0x78360005, // 026B JMPF R13 #0272 - 0xB8360200, // 026C GETNGBL R13 K1 - 0x88341B5C, // 026D GETMBR R13 R13 K92 - 0x900E340D, // 026E SETMBR R3 K26 R13 - 0x4C340000, // 026F LDNIL R13 - 0xA0000000, // 0270 CLOSE R0 - 0x80041A00, // 0271 RET 1 R13 - 0x6034000C, // 0272 GETGBL R13 G12 - 0x5C381200, // 0273 MOVE R14 R9 - 0x7C340200, // 0274 CALL R13 1 - 0x543A001F, // 0275 LDINT R14 32 - 0x543E0040, // 0276 LDINT R15 65 - 0x00381C0F, // 0277 ADD R14 R14 R15 - 0x20341A0E, // 0278 NE R13 R13 R14 - 0x7436000B, // 0279 JMPT R13 #0286 - 0x6034000C, // 027A GETGBL R13 G12 - 0x5C381800, // 027B MOVE R14 R12 - 0x7C340200, // 027C CALL R13 1 - 0x543A000F, // 027D LDINT R14 16 - 0x14341A0E, // 027E LT R13 R13 R14 - 0x74360005, // 027F JMPT R13 #0286 - 0x6034000C, // 0280 GETGBL R13 G12 - 0x5C381800, // 0281 MOVE R14 R12 - 0x7C340200, // 0282 CALL R13 1 - 0x543A001F, // 0283 LDINT R14 32 - 0x24341A0E, // 0284 GT R13 R13 R14 - 0x7836000A, // 0285 JMPF R13 #0291 - 0xB8364400, // 0286 GETNGBL R13 K34 - 0x8C341B2C, // 0287 GETMET R13 R13 K44 - 0x583C005D, // 0288 LDCONST R15 K93 - 0x5840000E, // 0289 LDCONST R16 K14 - 0x7C340600, // 028A CALL R13 3 - 0xB8360200, // 028B GETNGBL R13 K1 - 0x88341B5E, // 028C GETMBR R13 R13 K94 - 0x900E340D, // 028D SETMBR R3 K26 R13 - 0x4C340000, // 028E LDNIL R13 - 0xA0000000, // 028F CLOSE R0 - 0x80041A00, // 0290 RET 1 R13 - 0x5436001E, // 0291 LDINT R13 31 - 0x40360A0D, // 0292 CONNECT R13 K5 R13 - 0x9434120D, // 0293 GETIDX R13 R9 R13 - 0x543A001F, // 0294 LDINT R14 32 - 0x40381D40, // 0295 CONNECT R14 R14 K64 - 0x9438120E, // 0296 GETIDX R14 R9 R14 - 0x883C0116, // 0297 GETMBR R15 R0 K22 - 0x8C3C1F5F, // 0298 GETMET R15 R15 K95 - 0x5C441000, // 0299 MOVE R17 R8 - 0x5C481600, // 029A MOVE R18 R11 - 0x5C4C1400, // 029B MOVE R19 R10 - 0x5C501800, // 029C MOVE R20 R12 - 0x5C541A00, // 029D MOVE R21 R13 - 0x5C581C00, // 029E MOVE R22 R14 - 0x8C5C0360, // 029F GETMET R23 R1 K96 - 0x7C5C0200, // 02A0 CALL R23 1 - 0x7C3C1000, // 02A1 CALL R15 8 - 0x503C0200, // 02A2 LDBOOL R15 1 0 - 0xA0000000, // 02A3 CLOSE R0 - 0x80041E00, // 02A4 RET 1 R15 - 0x7002001C, // 02A5 JMP #02C3 - 0x1C200F07, // 02A6 EQ R8 R7 K7 - 0x78220012, // 02A7 JMPF R8 #02BB - 0x8C200506, // 02A8 GETMET R8 R2 K6 - 0x58280005, // 02A9 LDCONST R10 K5 - 0x7C200400, // 02AA CALL R8 2 - 0xB8264400, // 02AB GETNGBL R9 K34 - 0x8C24132C, // 02AC GETMET R9 R9 K44 - 0x602C0008, // 02AD GETGBL R11 G8 - 0x5C301000, // 02AE MOVE R12 R8 - 0x7C2C0200, // 02AF CALL R11 1 - 0x002EC20B, // 02B0 ADD R11 K97 R11 - 0x58300010, // 02B1 LDCONST R12 K16 - 0x7C240600, // 02B2 CALL R9 3 - 0x88240116, // 02B3 GETMBR R9 R0 K22 - 0x8C241362, // 02B4 GETMET R9 R9 K98 - 0x5C2C1000, // 02B5 MOVE R11 R8 - 0x7C240400, // 02B6 CALL R9 2 - 0x50240200, // 02B7 LDBOOL R9 1 0 - 0xA0000000, // 02B8 CLOSE R0 - 0x80041200, // 02B9 RET 1 R9 - 0x70020007, // 02BA JMP #02C3 - 0x1C200F0E, // 02BB EQ R8 R7 K14 - 0x78220005, // 02BC JMPF R8 #02C3 - 0x88200116, // 02BD GETMBR R8 R0 K22 - 0x8C201163, // 02BE GETMET R8 R8 K99 - 0x7C200200, // 02BF CALL R8 1 - 0x50200200, // 02C0 LDBOOL R8 1 0 - 0xA0000000, // 02C1 CLOSE R0 - 0x80041000, // 02C2 RET 1 R8 - 0x70020012, // 02C3 JMP #02D7 - 0x54220029, // 02C4 LDINT R8 42 - 0x1C200C08, // 02C5 EQ R8 R6 R8 - 0x78220005, // 02C6 JMPF R8 #02CD - 0x1C200F05, // 02C7 EQ R8 R7 K5 - 0x78220002, // 02C8 JMPF R8 #02CC - 0x50200200, // 02C9 LDBOOL R8 1 0 - 0xA0000000, // 02CA CLOSE R0 - 0x80041000, // 02CB RET 1 R8 - 0x70020009, // 02CC JMP #02D7 - 0x60200003, // 02CD GETGBL R8 G3 - 0x5C240000, // 02CE MOVE R9 R0 + 0x8C341B53, // 01E9 GETMET R13 R13 K83 + 0x7C340200, // 01EA CALL R13 1 + 0x60380008, // 01EB GETGBL R14 G8 + 0x5C3C1000, // 01EC MOVE R15 R8 + 0x7C380200, // 01ED CALL R14 1 + 0x7C2C0600, // 01EE CALL R11 3 + 0x58300010, // 01EF LDCONST R12 K16 + 0x7C240600, // 01F0 CALL R9 3 + 0x8C240B09, // 01F1 GETMET R9 R5 K9 + 0x7C240200, // 01F2 CALL R9 1 + 0x8C28130A, // 01F3 GETMET R10 R9 K10 + 0x58300005, // 01F4 LDCONST R12 K5 + 0x88340B0B, // 01F5 GETMBR R13 R5 K11 + 0xB83A0200, // 01F6 GETNGBL R14 K1 + 0x88381D2B, // 01F7 GETMBR R14 R14 K43 + 0x7C280800, // 01F8 CALL R10 4 + 0x8C28130A, // 01F9 GETMET R10 R9 K10 + 0x58300007, // 01FA LDCONST R12 K7 + 0x88340B0B, // 01FB GETMBR R13 R5 K11 + 0x8C380354, // 01FC GETMET R14 R1 K84 + 0x7C380200, // 01FD CALL R14 1 + 0x8C381D4F, // 01FE GETMET R14 R14 K79 + 0x7C380200, // 01FF CALL R14 1 + 0x7C280800, // 0200 CALL R10 4 + 0x542A0007, // 0201 LDINT R10 8 + 0x900E080A, // 0202 SETMBR R3 K4 R10 + 0x80041200, // 0203 RET 1 R9 + 0x70020044, // 0204 JMP #024A + 0x54220009, // 0205 LDINT R8 10 + 0x1C200E08, // 0206 EQ R8 R7 R8 + 0x78220041, // 0207 JMPF R8 #024A + 0x8C200506, // 0208 GETMET R8 R2 K6 + 0x58280005, // 0209 LDCONST R10 K5 + 0x7C200400, // 020A CALL R8 2 + 0x60240008, // 020B GETGBL R9 G8 + 0x5C281000, // 020C MOVE R10 R8 + 0x7C240200, // 020D CALL R9 1 + 0x0026AA09, // 020E ADD R9 K85 R9 + 0x900E5809, // 020F SETMBR R3 K44 R9 + 0x60240010, // 0210 GETGBL R9 G16 + 0x88280116, // 0211 GETMBR R10 R0 K22 + 0x88281530, // 0212 GETMBR R10 R10 K48 + 0x8C281556, // 0213 GETMET R10 R10 K86 + 0x7C280200, // 0214 CALL R10 1 + 0x7C240200, // 0215 CALL R9 1 + 0xA8020020, // 0216 EXBLK 0 #0238 + 0x5C281200, // 0217 MOVE R10 R9 + 0x7C280000, // 0218 CALL R10 0 + 0x8C2C154F, // 0219 GETMET R11 R10 K79 + 0x7C2C0200, // 021A CALL R11 1 + 0x1C2C1608, // 021B EQ R11 R11 R8 + 0x782E0018, // 021C JMPF R11 #0236 + 0x8C2C1557, // 021D GETMET R11 R10 K87 + 0x7C2C0200, // 021E CALL R11 1 + 0xB82E4400, // 021F GETNGBL R11 K34 + 0x8C2C1758, // 0220 GETMET R11 R11 K88 + 0x543607CF, // 0221 LDINT R13 2000 + 0x84380000, // 0222 CLOSURE R14 P0 + 0x7C2C0600, // 0223 CALL R11 3 + 0x8C2C0B09, // 0224 GETMET R11 R5 K9 + 0x7C2C0200, // 0225 CALL R11 1 + 0x8C30170A, // 0226 GETMET R12 R11 K10 + 0x58380005, // 0227 LDCONST R14 K5 + 0x883C0B0B, // 0228 GETMBR R15 R5 K11 + 0xB8420200, // 0229 GETNGBL R16 K1 + 0x8840212B, // 022A GETMBR R16 R16 K43 + 0x7C300800, // 022B CALL R12 4 + 0x8C30170A, // 022C GETMET R12 R11 K10 + 0x58380007, // 022D LDCONST R14 K7 + 0x883C0B0B, // 022E GETMBR R15 R5 K11 + 0x5C401000, // 022F MOVE R16 R8 + 0x7C300800, // 0230 CALL R12 4 + 0x54320007, // 0231 LDINT R12 8 + 0x900E080C, // 0232 SETMBR R3 K4 R12 + 0xA0000000, // 0233 CLOSE R0 + 0xA8040001, // 0234 EXBLK 1 1 + 0x80041600, // 0235 RET 1 R11 + 0xA0240000, // 0236 CLOSE R9 + 0x7001FFDE, // 0237 JMP #0217 + 0x58240059, // 0238 LDCONST R9 K89 + 0xAC240200, // 0239 CATCH R9 1 0 + 0xB0080000, // 023A RAISE 2 R0 R0 + 0xB8264400, // 023B GETNGBL R9 K34 + 0x8C24132C, // 023C GETMET R9 R9 K44 + 0x602C0008, // 023D GETGBL R11 G8 + 0x5C301000, // 023E MOVE R12 R8 + 0x7C2C0200, // 023F CALL R11 1 + 0x002EB40B, // 0240 ADD R11 K90 R11 + 0x002C175B, // 0241 ADD R11 R11 K91 + 0x5830000E, // 0242 LDCONST R12 K14 + 0x7C240600, // 0243 CALL R9 3 + 0xB8260200, // 0244 GETNGBL R9 K1 + 0x8824135C, // 0245 GETMBR R9 R9 K92 + 0x900E3409, // 0246 SETMBR R3 K26 R9 + 0x4C240000, // 0247 LDNIL R9 + 0xA0000000, // 0248 CLOSE R0 + 0x80041200, // 0249 RET 1 R9 + 0x7002009B, // 024A JMP #02E7 + 0x5422003B, // 024B LDINT R8 60 + 0x1C200C08, // 024C EQ R8 R6 R8 + 0x78220085, // 024D JMPF R8 #02D4 + 0x1C200F05, // 024E EQ R8 R7 K5 + 0x78220065, // 024F JMPF R8 #02B6 + 0x8C200506, // 0250 GETMET R8 R2 K6 + 0x58280005, // 0251 LDCONST R10 K5 + 0x7C200400, // 0252 CALL R8 2 + 0x8C240506, // 0253 GETMET R9 R2 K6 + 0x582C0007, // 0254 LDCONST R11 K7 + 0x7C240400, // 0255 CALL R9 2 + 0x8C280506, // 0256 GETMET R10 R2 K6 + 0x5830000E, // 0257 LDCONST R12 K14 + 0x7C280400, // 0258 CALL R10 2 + 0x8C2C0506, // 0259 GETMET R11 R2 K6 + 0x58340010, // 025A LDCONST R13 K16 + 0x7C2C0400, // 025B CALL R11 2 + 0x8C300506, // 025C GETMET R12 R2 K6 + 0x543A0003, // 025D LDINT R14 4 + 0x7C300400, // 025E CALL R12 2 + 0xB8364400, // 025F GETNGBL R13 K34 + 0x8C341B2C, // 0260 GETMET R13 R13 K44 + 0x603C0018, // 0261 GETGBL R15 G24 + 0x5840005D, // 0262 LDCONST R16 K93 + 0x5C441000, // 0263 MOVE R17 R8 + 0x8C481353, // 0264 GETMET R18 R9 K83 + 0x7C480200, // 0265 CALL R18 1 + 0x5C4C1400, // 0266 MOVE R19 R10 + 0x5C501600, // 0267 MOVE R20 R11 + 0x8C541953, // 0268 GETMET R21 R12 K83 + 0x7C540200, // 0269 CALL R21 1 + 0x7C3C0C00, // 026A CALL R15 6 + 0x54420003, // 026B LDINT R16 4 + 0x7C340600, // 026C CALL R13 3 + 0x4C340000, // 026D LDNIL R13 + 0x1C34100D, // 026E EQ R13 R8 R13 + 0x7436000B, // 026F JMPT R13 #027C + 0x4C340000, // 0270 LDNIL R13 + 0x1C34120D, // 0271 EQ R13 R9 R13 + 0x74360008, // 0272 JMPT R13 #027C + 0x4C340000, // 0273 LDNIL R13 + 0x1C34140D, // 0274 EQ R13 R10 R13 + 0x74360005, // 0275 JMPT R13 #027C + 0x4C340000, // 0276 LDNIL R13 + 0x1C34160D, // 0277 EQ R13 R11 R13 + 0x74360002, // 0278 JMPT R13 #027C + 0x4C340000, // 0279 LDNIL R13 + 0x1C34180D, // 027A EQ R13 R12 R13 + 0x78360005, // 027B JMPF R13 #0282 + 0xB8360200, // 027C GETNGBL R13 K1 + 0x88341B5E, // 027D GETMBR R13 R13 K94 + 0x900E340D, // 027E SETMBR R3 K26 R13 + 0x4C340000, // 027F LDNIL R13 + 0xA0000000, // 0280 CLOSE R0 + 0x80041A00, // 0281 RET 1 R13 + 0x6034000C, // 0282 GETGBL R13 G12 + 0x5C381200, // 0283 MOVE R14 R9 + 0x7C340200, // 0284 CALL R13 1 + 0x543A001F, // 0285 LDINT R14 32 + 0x543E0040, // 0286 LDINT R15 65 + 0x00381C0F, // 0287 ADD R14 R14 R15 + 0x20341A0E, // 0288 NE R13 R13 R14 + 0x7436000B, // 0289 JMPT R13 #0296 + 0x6034000C, // 028A GETGBL R13 G12 + 0x5C381800, // 028B MOVE R14 R12 + 0x7C340200, // 028C CALL R13 1 + 0x543A000F, // 028D LDINT R14 16 + 0x14341A0E, // 028E LT R13 R13 R14 + 0x74360005, // 028F JMPT R13 #0296 + 0x6034000C, // 0290 GETGBL R13 G12 + 0x5C381800, // 0291 MOVE R14 R12 + 0x7C340200, // 0292 CALL R13 1 + 0x543A001F, // 0293 LDINT R14 32 + 0x24341A0E, // 0294 GT R13 R13 R14 + 0x7836000A, // 0295 JMPF R13 #02A1 + 0xB8364400, // 0296 GETNGBL R13 K34 + 0x8C341B2C, // 0297 GETMET R13 R13 K44 + 0x583C005F, // 0298 LDCONST R15 K95 + 0x5840000E, // 0299 LDCONST R16 K14 + 0x7C340600, // 029A CALL R13 3 + 0xB8360200, // 029B GETNGBL R13 K1 + 0x88341B60, // 029C GETMBR R13 R13 K96 + 0x900E340D, // 029D SETMBR R3 K26 R13 + 0x4C340000, // 029E LDNIL R13 + 0xA0000000, // 029F CLOSE R0 + 0x80041A00, // 02A0 RET 1 R13 + 0x5436001E, // 02A1 LDINT R13 31 + 0x40360A0D, // 02A2 CONNECT R13 K5 R13 + 0x9434120D, // 02A3 GETIDX R13 R9 R13 + 0x543A001F, // 02A4 LDINT R14 32 + 0x40381D40, // 02A5 CONNECT R14 R14 K64 + 0x9438120E, // 02A6 GETIDX R14 R9 R14 + 0x883C0116, // 02A7 GETMBR R15 R0 K22 + 0x8C3C1F61, // 02A8 GETMET R15 R15 K97 + 0x5C441000, // 02A9 MOVE R17 R8 + 0x5C481600, // 02AA MOVE R18 R11 + 0x5C4C1400, // 02AB MOVE R19 R10 + 0x5C501800, // 02AC MOVE R20 R12 + 0x5C541A00, // 02AD MOVE R21 R13 + 0x5C581C00, // 02AE MOVE R22 R14 + 0x8C5C0354, // 02AF GETMET R23 R1 K84 + 0x7C5C0200, // 02B0 CALL R23 1 + 0x7C3C1000, // 02B1 CALL R15 8 + 0x503C0200, // 02B2 LDBOOL R15 1 0 + 0xA0000000, // 02B3 CLOSE R0 + 0x80041E00, // 02B4 RET 1 R15 + 0x7002001C, // 02B5 JMP #02D3 + 0x1C200F07, // 02B6 EQ R8 R7 K7 + 0x78220012, // 02B7 JMPF R8 #02CB + 0x8C200506, // 02B8 GETMET R8 R2 K6 + 0x58280005, // 02B9 LDCONST R10 K5 + 0x7C200400, // 02BA CALL R8 2 + 0xB8264400, // 02BB GETNGBL R9 K34 + 0x8C24132C, // 02BC GETMET R9 R9 K44 + 0x602C0008, // 02BD GETGBL R11 G8 + 0x5C301000, // 02BE MOVE R12 R8 + 0x7C2C0200, // 02BF CALL R11 1 + 0x002EC40B, // 02C0 ADD R11 K98 R11 + 0x58300010, // 02C1 LDCONST R12 K16 + 0x7C240600, // 02C2 CALL R9 3 + 0x88240116, // 02C3 GETMBR R9 R0 K22 + 0x8C241363, // 02C4 GETMET R9 R9 K99 + 0x5C2C1000, // 02C5 MOVE R11 R8 + 0x7C240400, // 02C6 CALL R9 2 + 0x50240200, // 02C7 LDBOOL R9 1 0 + 0xA0000000, // 02C8 CLOSE R0 + 0x80041200, // 02C9 RET 1 R9 + 0x70020007, // 02CA JMP #02D3 + 0x1C200F0E, // 02CB EQ R8 R7 K14 + 0x78220005, // 02CC JMPF R8 #02D3 + 0x88200116, // 02CD GETMBR R8 R0 K22 + 0x8C201164, // 02CE GETMET R8 R8 K100 0x7C200200, // 02CF CALL R8 1 - 0x8C201164, // 02D0 GETMET R8 R8 K100 - 0x5C280200, // 02D1 MOVE R10 R1 - 0x5C2C0400, // 02D2 MOVE R11 R2 - 0x5C300600, // 02D3 MOVE R12 R3 - 0x7C200800, // 02D4 CALL R8 4 - 0xA0000000, // 02D5 CLOSE R0 - 0x80041000, // 02D6 RET 1 R8 - 0xA0000000, // 02D7 CLOSE R0 - 0x80000000, // 02D8 RET 0 + 0x50200200, // 02D0 LDBOOL R8 1 0 + 0xA0000000, // 02D1 CLOSE R0 + 0x80041000, // 02D2 RET 1 R8 + 0x70020012, // 02D3 JMP #02E7 + 0x54220029, // 02D4 LDINT R8 42 + 0x1C200C08, // 02D5 EQ R8 R6 R8 + 0x78220005, // 02D6 JMPF R8 #02DD + 0x1C200F05, // 02D7 EQ R8 R7 K5 + 0x78220002, // 02D8 JMPF R8 #02DC + 0x50200200, // 02D9 LDBOOL R8 1 0 + 0xA0000000, // 02DA CLOSE R0 + 0x80041000, // 02DB RET 1 R8 + 0x70020009, // 02DC JMP #02E7 + 0x60200003, // 02DD GETGBL R8 G3 + 0x5C240000, // 02DE MOVE R9 R0 + 0x7C200200, // 02DF CALL R8 1 + 0x8C201165, // 02E0 GETMET R8 R8 K101 + 0x5C280200, // 02E1 MOVE R10 R1 + 0x5C2C0400, // 02E2 MOVE R11 R2 + 0x5C300600, // 02E3 MOVE R12 R3 + 0x7C200800, // 02E4 CALL R8 4 + 0xA0000000, // 02E5 CLOSE R0 + 0x80041000, // 02E6 RET 1 R8 + 0xA0000000, // 02E7 CLOSE R0 + 0x80000000, // 02E8 RET 0 }) ) ); From fd52aaee148d50f16b205df5c303c5b8f9db6ae1 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Mon, 5 Feb 2024 11:47:37 +0100 Subject: [PATCH 266/303] Matter add human readable names for TimeSync cluster (#20666) --- .../generate/be_matter_clusters.h | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/lib/libesp32/berry_matter/generate/be_matter_clusters.h b/lib/libesp32/berry_matter/generate/be_matter_clusters.h index 350d8b9fc..ce188476f 100644 --- a/lib/libesp32/berry_matter/generate/be_matter_clusters.h +++ b/lib/libesp32/berry_matter/generate/be_matter_clusters.h @@ -648,6 +648,38 @@ const matter_command_t matter_Commands_0037[] = { { 0xFFFF, NULL }, }; +const matter_attribute_t matter_Attributes_0038[] = { + { 0x0000, 0, 0x02, "UTCTime" }, + { 0x0001, 0, 0x02, "Granularity" }, + { 0x0002, 0, 0x02, "TimeSource" }, + { 0x0003, 0, 0x02, "TrustedTimeSource" }, + { 0x0004, 0, 0x02, "DefaultNTP" }, + { 0x0005, 0, 0x02, "TimeZone" }, + { 0x0006, 0, 0x02, "DSTOffset" }, + { 0x0007, 0, 0x02, "LocalTime" }, + { 0x0008, 0, 0x02, "TimeZoneDatabase" }, + { 0x0009, 0, 0x02, "NTPServerAvailable" }, + { 0x000A, 0, 0x02, "TimeZoneListMaxSize" }, + { 0x000B, 0, 0x02, "DSTOffsetListMaxSize" }, + { 0x000C, 0, 0x02, "SupportsDNSResolve" }, + { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, + { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, + { 0xFFFB, 0, 0x02, "AttributeList" }, + { 0xFFFC, 0, 0x02, "FeatureMap" }, + { 0xFFFD, 0, 0x02, "ClusterRevision" }, + { 0xFFFF, 0, 0x00, NULL }, +}; + +const matter_command_t matter_Commands_0038[] = { + { 0x0000, "SetUTCTime" }, + { 0x0001, "SetTrustedTimeSource" }, + { 0x0002, "SetTimeZone" }, + { 0x0003, "SetTimzZoneResponse" }, + { 0x0004, "SetDSTOffset" }, + { 0x0005, "SetDefaultNTP" }, + { 0xFFFF, NULL }, +}; + const matter_attribute_t matter_Attributes_0039[] = { { 0x0001, 0, 0x02, "VendorName" }, { 0x0002, 0, 0x02, "VendorID" }, @@ -1531,6 +1563,7 @@ const matter_cluster_t matterAllClusters[] = { // { 0x0035, "ThreadNetworkDiagnostics", matter_Attributes_0035, matter_Commands_0035 }, { 0x0036, "WiFiNetworkDiagnostics", matter_Attributes_0036, matter_Commands_0036 }, { 0x0037, "EthernetNetworkDiagnostics", matter_Attributes_0037, matter_Commands_0037 }, + { 0x0038, "TimeSync", matter_Attributes_0038, matter_Commands_0038 }, { 0x0039, "BridgedDeviceBasic", matter_Attributes_0039, matter_Commands_0039 }, { 0x003B, "Switch", matter_Attributes_003B, matter_Commands_003B }, { 0x003C, "AdministratorCommissioning", matter_Attributes_003C, matter_Commands_003C }, From 2a4c59dc689fa9a3be69d184940f67c78be0cdc7 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Mon, 5 Feb 2024 11:48:07 +0100 Subject: [PATCH 267/303] Matter fix exception when fabrics is not initialized (#20667) --- .../src/embedded/Matter_Session_Store.be | 6 +++++- .../solidify/solidified_Matter_Session_Store.h | 18 +++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Session_Store.be b/lib/libesp32/berry_matter/src/embedded/Matter_Session_Store.be index 8aaf531a3..e59d35770 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Session_Store.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Session_Store.be @@ -102,7 +102,11 @@ class Matter_Session_Store # Count the number of commissionned fabrics, i.e. persisted def count_active_fabrics() self.remove_expired() # clean before - return self.fabrics.count_persistables() + if self.fabrics != nil + return self.fabrics.count_persistables() + else + return 0 + end end ############################################################# diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Session_Store.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Session_Store.h index 64ab0848d..4747ddfb1 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Session_Store.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Session_Store.h @@ -508,20 +508,28 @@ be_local_closure(Matter_Session_Store_count_active_fabrics, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ + ( &(const bvalue[ 4]) { /* constants */ /* K0 */ be_nested_str_weak(remove_expired), /* K1 */ be_nested_str_weak(fabrics), /* K2 */ be_nested_str_weak(count_persistables), + /* K3 */ be_const_int(0), }), be_str_weak(count_active_fabrics), &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ + ( &(const binstruction[13]) { /* code */ 0x8C040100, // 0000 GETMET R1 R0 K0 0x7C040200, // 0001 CALL R1 1 0x88040101, // 0002 GETMBR R1 R0 K1 - 0x8C040302, // 0003 GETMET R1 R1 K2 - 0x7C040200, // 0004 CALL R1 1 - 0x80040200, // 0005 RET 1 R1 + 0x4C080000, // 0003 LDNIL R2 + 0x20040202, // 0004 NE R1 R1 R2 + 0x78060004, // 0005 JMPF R1 #000B + 0x88040101, // 0006 GETMBR R1 R0 K1 + 0x8C040302, // 0007 GETMET R1 R1 K2 + 0x7C040200, // 0008 CALL R1 1 + 0x80040200, // 0009 RET 1 R1 + 0x70020000, // 000A JMP #000C + 0x80060600, // 000B RET 1 K3 + 0x80000000, // 000C RET 0 }) ) ); From 3b0cb408ba3ea94534679b38db03d03b8888732c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 5 Feb 2024 11:57:00 +0100 Subject: [PATCH 268/303] Update changelogs --- CHANGELOG.md | 4 +++- RELEASENOTES.md | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 486b5ab7a..6f2a557d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file. - ESP32 support for Shelly Plus Add-On using DS18x20 or DHT11/AM2301/DHT21/DHT22/AM2302/AM2321/SI7021 on GPIO0/1 (#20580) - ESP32 MI32 Legacy initial support for sensors using BTHOME packet format (#20625) - Berry `introspect.contains` and `bytes.addfloat` (#20635) +- Matter add human readable names for TimeSync cluster (#20666) ### Breaking Changed - Matter aggregator relocated to endpoint 1 for Google compatibility, may break existing associations (#20654) @@ -25,7 +26,8 @@ All notable changes to this project will be documented in this file. ### Fixed - Berry C mapping, raise an error if too many arguments are sent (#20604) -- Matter fixed error when removing device from Google Home +- Matter error when removing device from Google Home (#20665) +- Matter exception when fabrics is not initialized (#20667) ### Removed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 4f308222d..c1fc8e472 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -160,6 +160,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - HASPmota type `chart` [#20372](https://github.com/arendst/Tasmota/issues/20372) - HASPmota support for `min` and `max` attribute in `slider` [#20582](https://github.com/arendst/Tasmota/issues/20582) - Matter support for password for remote Tasmota devices [#20296](https://github.com/arendst/Tasmota/issues/20296) +- Matter add human readable names for TimeSync cluster [#20666](https://github.com/arendst/Tasmota/issues/20666) ### Breaking Changed - Refactoring of Berry `animate` module for WS2812 Leds [#20236](https://github.com/arendst/Tasmota/issues/20236) @@ -201,6 +202,8 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Berry C mapping, raise an error if too many arguments are sent [#20604](https://github.com/arendst/Tasmota/issues/20604) - Matter Contact sensor was not triggering any update [#20232](https://github.com/arendst/Tasmota/issues/20232) - Matter support for Alexa [#20545](https://github.com/arendst/Tasmota/issues/20545) +- Matter error when removing device from Google Home [#20665](https://github.com/arendst/Tasmota/issues/20665) +- Matter exception when fabrics is not initialized [#20667](https://github.com/arendst/Tasmota/issues/20667) ### Removed - Max number of 30 backlog entries From ff6be70ce1af13cdddf2f628e6c30af13507bb21 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Mon, 5 Feb 2024 12:07:41 +0100 Subject: [PATCH 269/303] LVGL library updated to v9.0.0, some small breaking changes in C, none in HASPmota (#20659) * LVGL library updated to v9.0.0, some small breaking changes in C, none in HASPmota * fix compilation * Move lvgl_berry to LVGL_assets --- CHANGELOG.md | 1 + .../berry_tasmota/include/be_ctypes.h | 3 + lib/libesp32/berry_tasmota/src/be_ctypes.c | 3 + .../berry_tasmota/src/be_lv_haspmota.c | 2788 +++-- .../berry_tasmota/src/embedded/lv_tasmota.be | 15 +- .../src/embedded/lv_tasmota_widgets.be | 82 +- .../src/solidify/solidified_lv_tasmota.h | 301 +- .../solidify/solidified_lv_tasmota_widgets.h | 1068 +- .../Adafruit_LvGL_Glue.cpp | 267 - .../Adafruit_LvGL_Glue.h | 54 - .../Adafruit_LvGL_Glue-shadinger/README.md | 50 - .../code-of-conduct.md | 127 - .../Adafruit_LvGL_Glue-shadinger/library.json | 10 - .../library.properties | 10 - .../Adafruit_LvGL_Glue-shadinger/license.txt | 26 - .../LVGL_assets/TASMOTA_Symbol_64.png | Bin 0 -> 3003 bytes .../LVGL_assets}/fonts/DSEG7/DSEG-LICENSE.txt | 0 .../fonts/DSEG7/DSEG7Classic-Bold.ttf | Bin .../fonts/DSEG7/DSEG7Classic-BoldItalic.ttf | Bin .../fonts/DSEG7/font_files/seg7_10.lvfont | Bin .../fonts/DSEG7/font_files/seg7_12.lvfont | Bin .../fonts/DSEG7/font_files/seg7_14.lvfont | Bin .../fonts/DSEG7/font_files/seg7_16.lvfont | Bin .../fonts/DSEG7/font_files/seg7_18.lvfont | Bin .../fonts/DSEG7/font_files/seg7_20.lvfont | Bin .../fonts/DSEG7/font_files/seg7_24.lvfont | Bin .../fonts/DSEG7/font_files/seg7_28.lvfont | Bin .../fonts/DSEG7/font_files/seg7_36.lvfont | Bin .../fonts/DSEG7/font_files/seg7_48.lvfont | Bin .../fonts/DSEG7/font_files/seg7_8.lvfont | Bin .../fonts/DSEG7/gen_seg7_fonts.bash | 0 .../Berkelium (GEOS)/Berkelium1541.ttf | Bin .../Berkelium (GEOS)/Berkelium64.ttf | Bin .../Berkelium (GEOS)/FreeLicense.txt | 0 .../fonts/pixel_perfect/Berkelium64.lvfont | Bin .../pixel_perfect/Daniel Linssen/m3x6.ttf | Bin .../pixel_perfect/Daniel Linssen/m5x7.ttf | Bin .../PrintChar (Apple II Font)/FreeLicense.txt | 0 .../PrintChar (Apple II Font)/PrintChar21.ttf | Bin .../fonts/pixel_perfect/PrintChar21.lvfont | Bin .../Shaston (GSOS)/FreeLicense.txt | 0 .../Shaston (GSOS)/Shaston320.ttf | Bin .../fonts/pixel_perfect/Shaston320.lvfont | Bin .../fonts/pixel_perfect/m3x6.lvfont | Bin .../fonts/pixel_perfect/m5x7.lvfont | Bin .../fonts/pixel_perfect/pages.jsonl | 0 .../robotocondensed_regular_12_latin1.c | 8 +- .../robotocondensed_regular_14_latin1.c | 8 +- .../robotocondensed_regular_16_latin1.c | 8 +- .../robotocondensed_regular_20_latin1.c | 8 +- .../robotocondensed_regular_22_latin1.c | 8 +- .../robotocondensed_regular_24_latin1.c | 8 +- .../robotocondensed_regular_26_latin1.c | 8 +- .../robotocondensed_regular_28_latin1.c | 8 +- .../robotocondensed_regular_32_latin1.c | 8 +- .../robotocondensed_regular_36_latin1.c | 8 +- .../robotocondensed_regular_38_latin1.c | 8 +- .../robotocondensed_regular_40_latin1.c | 8 +- .../robotocondensed_regular_44_latin1.c | 8 +- .../robotocondensed_regular_48_latin1.c | 8 +- .../LVGL_assets/src/fonts/seg7_10.c | 8 +- .../LVGL_assets/src/fonts/seg7_12.c | 8 +- .../LVGL_assets/src/fonts/seg7_14.c | 8 +- .../LVGL_assets/src/fonts/seg7_16.c | 8 +- .../LVGL_assets/src/fonts/seg7_18.c | 8 +- .../LVGL_assets/src/fonts/seg7_20.c | 8 +- .../LVGL_assets/src/fonts/seg7_24.c | 8 +- .../LVGL_assets/src/fonts/seg7_28.c | 8 +- .../LVGL_assets/src/fonts/seg7_36.c | 8 +- .../LVGL_assets/src/fonts/seg7_48.c | 8 +- .../LVGL_assets/src/fonts/seg7_8.c | 8 +- .../LVGL_assets/src/lv_theme_haspmota.c | 118 +- .../LVGL_assets/src/lv_theme_haspmota.h | 2 +- .../src/tasmota_logo_64_truecolor_alpha.c | 127 + lib/libesp32_lvgl/freetype/CMakeLists.txt | 585 - lib/libesp32_lvgl/freetype/ChangeLog | 10212 +++++++++------- lib/libesp32_lvgl/freetype/ChangeLog.20 | 2613 ---- lib/libesp32_lvgl/freetype/ChangeLog.21 | 9438 -------------- lib/libesp32_lvgl/freetype/ChangeLog.22 | 2837 ----- lib/libesp32_lvgl/freetype/ChangeLog.23 | 7948 ------------ lib/libesp32_lvgl/freetype/ChangeLog.24 | 6360 ---------- lib/libesp32_lvgl/freetype/ChangeLog.25 | 5161 -------- lib/libesp32_lvgl/freetype/ChangeLog.26 | 5711 --------- lib/libesp32_lvgl/freetype/ChangeLog.27 | 2106 ---- lib/libesp32_lvgl/freetype/ChangeLog.28 | 3136 ----- lib/libesp32_lvgl/freetype/ChangeLog.29 | 2352 ---- lib/libesp32_lvgl/freetype/LICENSE.TXT | 6 +- lib/libesp32_lvgl/freetype/Makefile | 34 - lib/libesp32_lvgl/freetype/README | 15 +- lib/libesp32_lvgl/freetype/README.git | 64 +- lib/libesp32_lvgl/freetype/devel/ft2build.h | 3 +- lib/libesp32_lvgl/freetype/devel/ftmodule.h | 2 +- lib/libesp32_lvgl/freetype/devel/ftoption.h | 141 +- lib/libesp32_lvgl/freetype/docs/CHANGES | 5317 -------- lib/libesp32_lvgl/freetype/docs/CMAKE | 2 - lib/libesp32_lvgl/freetype/docs/CUSTOMIZE | 152 - lib/libesp32_lvgl/freetype/docs/DEBUG | 216 - lib/libesp32_lvgl/freetype/docs/DOCGUIDE | 298 - lib/libesp32_lvgl/freetype/docs/FTL.TXT | 169 - lib/libesp32_lvgl/freetype/docs/GPLv2.TXT | 340 - lib/libesp32_lvgl/freetype/docs/INSTALL | 90 - lib/libesp32_lvgl/freetype/docs/INSTALL.ANY | 156 - lib/libesp32_lvgl/freetype/docs/INSTALL.CROSS | 177 - lib/libesp32_lvgl/freetype/docs/INSTALL.GNU | 161 - lib/libesp32_lvgl/freetype/docs/INSTALL.MAC | 32 - lib/libesp32_lvgl/freetype/docs/INSTALL.UNIX | 118 - lib/libesp32_lvgl/freetype/docs/INSTALL.VMS | 62 - lib/libesp32_lvgl/freetype/docs/LICENSE.TXT | 39 - lib/libesp32_lvgl/freetype/docs/MAKEPP | 5 - lib/libesp32_lvgl/freetype/docs/PROBLEMS | 90 - lib/libesp32_lvgl/freetype/docs/README | 35 - lib/libesp32_lvgl/freetype/docs/TODO | 40 - lib/libesp32_lvgl/freetype/docs/VERSIONS.TXT | 130 - lib/libesp32_lvgl/freetype/docs/formats.txt | 208 - .../freetype/docs/freetype-config.1 | 146 - lib/libesp32_lvgl/freetype/docs/raster.txt | 635 - .../freetype/docs/reference/404.html | 1036 -- .../reference/assets/fonts/font-awesome.css | 4 - .../reference/assets/fonts/material-icons.css | 13 - .../assets/fonts/specimen/FontAwesome.ttf | Bin 165548 -> 0 bytes .../assets/fonts/specimen/FontAwesome.woff | Bin 98024 -> 0 bytes .../assets/fonts/specimen/FontAwesome.woff2 | Bin 77160 -> 0 bytes .../fonts/specimen/MaterialIcons-Regular.ttf | Bin 128180 -> 0 bytes .../fonts/specimen/MaterialIcons-Regular.woff | Bin 57620 -> 0 bytes .../specimen/MaterialIcons-Regular.woff2 | Bin 44300 -> 0 bytes .../docs/reference/assets/images/favicon.png | Bin 521 -> 0 bytes .../images/icons/bitbucket.1b09e088.svg | 1 - .../assets/images/icons/github.f0b8504a.svg | 1 - .../assets/images/icons/gitlab.6dd19c00.svg | 1 - .../javascripts/application.c33a9706.js | 60 - .../assets/javascripts/lunr/lunr.ar.js | 20 - .../assets/javascripts/lunr/lunr.da.js | 17 - .../assets/javascripts/lunr/lunr.de.js | 17 - .../assets/javascripts/lunr/lunr.du.js | 17 - .../assets/javascripts/lunr/lunr.es.js | 17 - .../assets/javascripts/lunr/lunr.fi.js | 17 - .../assets/javascripts/lunr/lunr.fr.js | 17 - .../assets/javascripts/lunr/lunr.hu.js | 17 - .../assets/javascripts/lunr/lunr.it.js | 17 - .../assets/javascripts/lunr/lunr.ja.js | 17 - .../assets/javascripts/lunr/lunr.jp.js | 1 - .../assets/javascripts/lunr/lunr.multi.js | 1 - .../assets/javascripts/lunr/lunr.nl.js | 17 - .../assets/javascripts/lunr/lunr.no.js | 17 - .../assets/javascripts/lunr/lunr.pt.js | 17 - .../assets/javascripts/lunr/lunr.ro.js | 17 - .../assets/javascripts/lunr/lunr.ru.js | 17 - .../javascripts/lunr/lunr.stemmer.support.js | 9 - .../assets/javascripts/lunr/lunr.sv.js | 17 - .../assets/javascripts/lunr/lunr.th.js | 17 - .../assets/javascripts/lunr/lunr.tr.js | 17 - .../assets/javascripts/lunr/lunr.vi.js | 17 - .../assets/javascripts/lunr/tinyseg.js | 1 - .../assets/javascripts/lunr/wordcut.js | 1 - .../assets/javascripts/modernizr.86422ebf.js | 1 - .../application-palette.a8b3c06d.css | 1 - .../stylesheets/application.adb8469c.css | 1 - .../docs/reference/ft2-auto_hinter.html | 1158 -- .../docs/reference/ft2-base_interface.html | 5109 -------- .../docs/reference/ft2-basic_types.html | 2299 ---- .../docs/reference/ft2-bdf_fonts.html | 1375 --- .../docs/reference/ft2-bitmap_handling.html | 1504 --- .../freetype/docs/reference/ft2-bzip2.html | 1200 -- .../docs/reference/ft2-cache_subsystem.html | 2344 ---- .../docs/reference/ft2-cff_driver.html | 1166 -- .../docs/reference/ft2-cid_fonts.html | 1314 -- .../docs/reference/ft2-color_management.html | 1457 --- .../docs/reference/ft2-computations.html | 2005 --- .../docs/reference/ft2-error_code_values.html | 1395 --- .../reference/ft2-error_enumerations.html | 1244 -- .../docs/reference/ft2-font_formats.html | 1197 -- .../docs/reference/ft2-gasp_table.html | 1252 -- .../docs/reference/ft2-glyph_management.html | 1821 --- .../docs/reference/ft2-glyph_stroker.html | 2092 ---- .../docs/reference/ft2-glyph_variants.html | 1387 --- .../docs/reference/ft2-gx_validation.html | 1478 --- .../freetype/docs/reference/ft2-gzip.html | 1266 -- .../reference/ft2-header_file_macros.html | 2215 ---- .../docs/reference/ft2-header_inclusion.html | 1161 -- .../docs/reference/ft2-incremental.html | 1507 --- .../freetype/docs/reference/ft2-index.html | 2145 ---- .../docs/reference/ft2-layer_management.html | 1310 -- .../docs/reference/ft2-lcd_rendering.html | 1408 --- .../docs/reference/ft2-list_processing.html | 1624 --- .../freetype/docs/reference/ft2-lzw.html | 1200 -- .../docs/reference/ft2-mac_specific.html | 1486 --- .../docs/reference/ft2-module_management.html | 2159 ---- .../docs/reference/ft2-multiple_masters.html | 2069 ---- .../docs/reference/ft2-ot_validation.html | 1306 -- .../reference/ft2-outline_processing.html | 2250 ---- .../docs/reference/ft2-parameter_tags.html | 1334 -- .../docs/reference/ft2-pcf_driver.html | 1157 -- .../docs/reference/ft2-pfr_fonts.html | 1318 -- .../docs/reference/ft2-properties.html | 1906 --- .../docs/reference/ft2-quick_advance.html | 1297 -- .../freetype/docs/reference/ft2-raster.html | 1706 --- .../docs/reference/ft2-sfnt_names.html | 1405 --- .../docs/reference/ft2-sizes_management.html | 1276 -- .../docs/reference/ft2-system_interface.html | 1549 --- .../docs/reference/ft2-t1_cid_driver.html | 1160 -- .../docs/reference/ft2-truetype_engine.html | 1237 -- .../docs/reference/ft2-truetype_tables.html | 3158 ----- .../docs/reference/ft2-tt_driver.html | 1173 -- .../docs/reference/ft2-type1_tables.html | 2101 ---- .../docs/reference/ft2-user_allocation.html | 1156 -- .../freetype/docs/reference/ft2-version.html | 1332 -- .../docs/reference/ft2-winfnt_fonts.html | 1392 --- .../freetype/docs/reference/images/favico.ico | Bin 1150 -> 0 bytes .../freetype/docs/reference/index.html | 1276 -- .../docs/reference/javascripts/extra.js | 54 - .../docs/reference/search/search_index.json | 1 - .../freetype/docs/reference/sitemap.xml | 207 - .../freetype/docs/reference/sitemap.xml.gz | Bin 219 -> 0 bytes .../docs/reference/stylesheets/extra.css | 183 - lib/libesp32_lvgl/freetype/docs/release | 202 - lib/libesp32_lvgl/freetype/include/dlg/dlg.h | 290 + .../freetype/include/dlg/output.h | 172 + .../include/freetype/config/ftconfig.h | 2 +- .../include/freetype/config/ftheader.h | 14 +- .../include/freetype/config/ftmodule.h | 24 +- .../include/freetype/config/ftoption.h | 154 +- .../include/freetype/config/ftstdlib.h | 28 +- .../include/freetype/config/integer-types.h | 45 +- .../include/freetype/config/mac-support.h | 2 +- .../include/freetype/config/public-macros.h | 20 +- .../freetype/include/freetype/freetype.h | 1490 ++- .../freetype/include/freetype/ftadvanc.h | 2 +- .../freetype/include/freetype/ftbbox.h | 2 +- .../freetype/include/freetype/ftbdf.h | 2 +- .../freetype/include/freetype/ftbitmap.h | 2 +- .../freetype/include/freetype/ftbzip2.h | 2 +- .../freetype/include/freetype/ftcache.h | 78 +- .../freetype/include/freetype/ftchapters.h | 27 +- .../freetype/include/freetype/ftcid.h | 2 +- .../freetype/include/freetype/ftcolor.h | 1356 +- .../freetype/include/freetype/ftdriver.h | 157 +- .../freetype/include/freetype/fterrdef.h | 6 +- .../freetype/include/freetype/fterrors.h | 6 +- .../freetype/include/freetype/ftfntfmt.h | 2 +- .../freetype/include/freetype/ftgasp.h | 2 +- .../freetype/include/freetype/ftglyph.h | 126 +- .../freetype/include/freetype/ftgxval.h | 2 +- .../freetype/include/freetype/ftgzip.h | 2 +- .../freetype/include/freetype/ftimage.h | 139 +- .../freetype/include/freetype/ftincrem.h | 17 +- .../freetype/include/freetype/ftlcdfil.h | 27 +- .../freetype/include/freetype/ftlist.h | 2 +- .../freetype/include/freetype/ftlogging.h | 184 + .../freetype/include/freetype/ftlzw.h | 2 +- .../freetype/include/freetype/ftmac.h | 2 +- .../freetype/include/freetype/ftmm.h | 71 +- .../freetype/include/freetype/ftmodapi.h | 35 +- .../freetype/include/freetype/ftmoderr.h | 3 +- .../freetype/include/freetype/ftotval.h | 2 +- .../freetype/include/freetype/ftoutln.h | 16 +- .../freetype/include/freetype/ftparams.h | 17 +- .../freetype/include/freetype/ftpfr.h | 4 +- .../freetype/include/freetype/ftrender.h | 4 +- .../freetype/include/freetype/ftsizes.h | 2 +- .../freetype/include/freetype/ftsnames.h | 2 +- .../freetype/include/freetype/ftstroke.h | 4 +- .../freetype/include/freetype/ftsynth.h | 25 +- .../freetype/include/freetype/ftsystem.h | 12 +- .../freetype/include/freetype/fttrigon.h | 2 +- .../freetype/include/freetype/fttypes.h | 24 +- .../freetype/include/freetype/ftwinfnt.h | 4 +- .../include/freetype/internal/autohint.h | 2 +- .../include/freetype/internal/cffotypes.h | 2 +- .../include/freetype/internal/cfftypes.h | 4 +- .../freetype/internal/compiler-macros.h | 170 +- .../include/freetype/internal/ftcalc.h | 96 +- .../include/freetype/internal/ftdebug.h | 173 +- .../include/freetype/internal/ftdrv.h | 3 +- .../include/freetype/internal/ftgloadr.h | 3 +- .../include/freetype/internal/ftmemory.h | 25 +- .../include/freetype/internal/ftmmtypes.h | 91 + .../include/freetype/internal/ftobjs.h | 7 +- .../include/freetype/internal/ftpsprop.h | 2 +- .../include/freetype/internal/ftrfork.h | 2 +- .../include/freetype/internal/ftserv.h | 2 +- .../include/freetype/internal/ftstream.h | 136 +- .../include/freetype/internal/fttrace.h | 28 +- .../include/freetype/internal/ftvalid.h | 2 +- .../include/freetype/internal/psaux.h | 6 +- .../include/freetype/internal/pshints.h | 6 +- .../freetype/internal/services/svbdf.h | 2 +- .../freetype/internal/services/svcfftl.h | 2 +- .../freetype/internal/services/svcid.h | 2 +- .../freetype/internal/services/svfntfmt.h | 2 +- .../freetype/internal/services/svgldict.h | 2 +- .../freetype/internal/services/svgxval.h | 2 +- .../freetype/internal/services/svkern.h | 2 +- .../freetype/internal/services/svmetric.h | 12 +- .../include/freetype/internal/services/svmm.h | 158 +- .../freetype/internal/services/svotval.h | 2 +- .../freetype/internal/services/svpfr.h | 2 +- .../freetype/internal/services/svpostnm.h | 2 +- .../freetype/internal/services/svprop.h | 2 +- .../freetype/internal/services/svpscmap.h | 4 +- .../freetype/internal/services/svpsinfo.h | 2 +- .../freetype/internal/services/svsfnt.h | 2 +- .../freetype/internal/services/svttcmap.h | 2 +- .../freetype/internal/services/svtteng.h | 2 +- .../freetype/internal/services/svttglyf.h | 2 +- .../freetype/internal/services/svwinfnt.h | 2 +- .../freetype/include/freetype/internal/sfnt.h | 295 +- .../include/freetype/internal/svginterface.h | 46 + .../include/freetype/internal/t1types.h | 32 +- .../include/freetype/internal/tttypes.h | 157 +- .../include/freetype/internal/wofftypes.h | 6 +- .../freetype/include/freetype/otsvg.h | 336 + .../freetype/include/freetype/t1tables.h | 176 +- .../freetype/include/freetype/ttnameid.h | 4 +- .../freetype/include/freetype/tttables.h | 6 +- .../freetype/include/freetype/tttags.h | 3 +- lib/libesp32_lvgl/freetype/include/ft2build.h | 2 +- lib/libesp32_lvgl/freetype/library.json | 2 +- lib/libesp32_lvgl/freetype/meson.build | 395 - lib/libesp32_lvgl/freetype/meson_options.txt | 46 - lib/libesp32_lvgl/freetype/modules.cfg | 250 - .../freetype/src/autofit/afangles.c | 285 - .../freetype/src/autofit/afangles.h | 7 - .../freetype/src/autofit/afblue.c | 2 +- .../freetype/src/autofit/afblue.cin | 2 +- .../freetype/src/autofit/afblue.dat | 4 +- .../freetype/src/autofit/afblue.h | 2 +- .../freetype/src/autofit/afblue.hin | 2 +- .../freetype/src/autofit/afcjk.c | 162 +- .../freetype/src/autofit/afcjk.h | 22 +- .../freetype/src/autofit/afcover.h | 2 +- .../freetype/src/autofit/afdummy.c | 2 +- .../freetype/src/autofit/afdummy.h | 2 +- .../freetype/src/autofit/aferrors.h | 2 +- .../freetype/src/autofit/afglobal.c | 80 +- .../freetype/src/autofit/afglobal.h | 8 +- .../freetype/src/autofit/afhints.c | 254 +- .../freetype/src/autofit/afhints.h | 36 +- .../freetype/src/autofit/afindic.c | 42 +- .../freetype/src/autofit/afindic.h | 2 +- .../freetype/src/autofit/aflatin.c | 303 +- .../freetype/src/autofit/aflatin.h | 6 +- .../freetype/src/autofit/aflatin2.c | 2428 ---- .../freetype/src/autofit/aflatin2.h | 46 - .../freetype/src/autofit/afloader.c | 48 +- .../freetype/src/autofit/afloader.h | 4 +- .../freetype/src/autofit/afmodule.c | 131 +- .../freetype/src/autofit/afmodule.h | 7 +- .../freetype/src/autofit/afranges.c | 2 +- .../freetype/src/autofit/afranges.h | 2 +- .../freetype/src/autofit/afscript.h | 2 +- .../freetype/src/autofit/afshaper.c | 63 +- .../freetype/src/autofit/afshaper.h | 4 +- .../freetype/src/autofit/afstyles.h | 11 +- .../freetype/src/autofit/aftypes.h | 87 +- .../freetype/src/autofit/afwarp.c | 373 - .../freetype/src/autofit/afwarp.h | 66 - .../freetype/src/autofit/afwrtsys.h | 52 - .../freetype/src/autofit/afws-decl.h | 33 + .../freetype/src/autofit/afws-iter.h | 31 + .../freetype/src/autofit/autofit.c | 6 +- .../freetype/src/autofit/ft-hb.c | 115 + .../freetype/src/autofit/ft-hb.h | 48 + .../freetype/src/autofit/module.mk | 2 +- .../freetype/src/autofit/rules.mk | 22 +- .../freetype/src/base/ftadvanc.c | 8 +- lib/libesp32_lvgl/freetype/src/base/ftbase.c | 2 +- lib/libesp32_lvgl/freetype/src/base/ftbase.h | 3 +- lib/libesp32_lvgl/freetype/src/base/ftbbox.c | 44 +- lib/libesp32_lvgl/freetype/src/base/ftbdf.c | 2 +- .../freetype/src/base/ftbitmap.c | 110 +- lib/libesp32_lvgl/freetype/src/base/ftcalc.c | 153 +- lib/libesp32_lvgl/freetype/src/base/ftcid.c | 2 +- lib/libesp32_lvgl/freetype/src/base/ftcolor.c | 2 +- .../freetype/src/base/ftdbgmem.c | 146 +- lib/libesp32_lvgl/freetype/src/base/ftdebug.c | 334 +- .../freetype/src/base/fterrors.c | 2 +- .../freetype/src/base/ftfntfmt.c | 2 +- .../freetype/src/base/ftfstype.c | 2 +- lib/libesp32_lvgl/freetype/src/base/ftgasp.c | 2 +- .../freetype/src/base/ftgloadr.c | 36 +- lib/libesp32_lvgl/freetype/src/base/ftglyph.c | 274 +- lib/libesp32_lvgl/freetype/src/base/ftgxval.c | 2 +- lib/libesp32_lvgl/freetype/src/base/fthash.c | 2 +- lib/libesp32_lvgl/freetype/src/base/ftinit.c | 10 +- .../freetype/src/base/ftlcdfil.c | 10 +- lib/libesp32_lvgl/freetype/src/base/ftmac.c | 17 +- lib/libesp32_lvgl/freetype/src/base/ftmm.c | 148 +- lib/libesp32_lvgl/freetype/src/base/ftobjs.c | 696 +- lib/libesp32_lvgl/freetype/src/base/ftotval.c | 2 +- lib/libesp32_lvgl/freetype/src/base/ftoutln.c | 96 +- .../freetype/src/base/ftpatent.c | 2 +- lib/libesp32_lvgl/freetype/src/base/ftpfr.c | 2 +- .../freetype/src/base/ftpsprop.c | 6 +- lib/libesp32_lvgl/freetype/src/base/ftrfork.c | 54 +- .../freetype/src/base/ftsnames.c | 6 +- .../freetype/src/base/ftstream.c | 131 +- .../freetype/src/base/ftstroke.c | 68 +- lib/libesp32_lvgl/freetype/src/base/ftsynth.c | 42 +- .../freetype/src/base/ftsystem.c | 13 +- .../freetype/src/base/fttrigon.c | 8 +- lib/libesp32_lvgl/freetype/src/base/fttype1.c | 2 +- lib/libesp32_lvgl/freetype/src/base/ftutil.c | 2 +- lib/libesp32_lvgl/freetype/src/base/ftver.rc | 12 +- .../freetype/src/base/ftwinfnt.c | 2 +- lib/libesp32_lvgl/freetype/src/base/rules.mk | 2 +- lib/libesp32_lvgl/freetype/src/bdf/README | 6 +- lib/libesp32_lvgl/freetype/src/bdf/bdf.h | 4 - lib/libesp32_lvgl/freetype/src/bdf/bdfdrivr.c | 156 +- lib/libesp32_lvgl/freetype/src/bdf/bdflib.c | 551 +- .../freetype/src/bzip2/ftbzip2.c | 75 +- lib/libesp32_lvgl/freetype/src/bzip2/rules.mk | 2 +- .../freetype/src/cache/ftcache.c | 2 +- .../freetype/src/cache/ftcbasic.c | 31 +- .../freetype/src/cache/ftccache.c | 149 +- .../freetype/src/cache/ftccache.h | 23 +- .../freetype/src/cache/ftccback.h | 2 +- .../freetype/src/cache/ftccmap.c | 27 +- .../freetype/src/cache/ftcerror.h | 2 +- .../freetype/src/cache/ftcglyph.c | 48 +- .../freetype/src/cache/ftcglyph.h | 23 +- .../freetype/src/cache/ftcimage.c | 5 +- .../freetype/src/cache/ftcimage.h | 8 +- .../freetype/src/cache/ftcmanag.c | 69 +- .../freetype/src/cache/ftcmanag.h | 2 +- lib/libesp32_lvgl/freetype/src/cache/ftcmru.c | 34 +- lib/libesp32_lvgl/freetype/src/cache/ftcmru.h | 2 +- .../freetype/src/cache/ftcsbits.c | 62 +- .../freetype/src/cache/ftcsbits.h | 15 +- lib/libesp32_lvgl/freetype/src/cache/rules.mk | 2 +- lib/libesp32_lvgl/freetype/src/cff/cff.c | 2 +- lib/libesp32_lvgl/freetype/src/cff/cffcmap.c | 109 +- lib/libesp32_lvgl/freetype/src/cff/cffcmap.h | 2 +- lib/libesp32_lvgl/freetype/src/cff/cffdrivr.c | 503 +- lib/libesp32_lvgl/freetype/src/cff/cffdrivr.h | 2 +- lib/libesp32_lvgl/freetype/src/cff/cfferrs.h | 2 +- lib/libesp32_lvgl/freetype/src/cff/cffgload.c | 100 +- lib/libesp32_lvgl/freetype/src/cff/cffgload.h | 2 +- lib/libesp32_lvgl/freetype/src/cff/cffload.c | 150 +- lib/libesp32_lvgl/freetype/src/cff/cffload.h | 6 +- lib/libesp32_lvgl/freetype/src/cff/cffobjs.c | 61 +- lib/libesp32_lvgl/freetype/src/cff/cffobjs.h | 2 +- lib/libesp32_lvgl/freetype/src/cff/cffparse.c | 278 +- lib/libesp32_lvgl/freetype/src/cff/cffparse.h | 15 +- lib/libesp32_lvgl/freetype/src/cff/cfftoken.h | 2 +- lib/libesp32_lvgl/freetype/src/cff/module.mk | 2 +- lib/libesp32_lvgl/freetype/src/cff/rules.mk | 2 +- lib/libesp32_lvgl/freetype/src/cid/ciderrs.h | 2 +- lib/libesp32_lvgl/freetype/src/cid/cidgload.c | 169 +- lib/libesp32_lvgl/freetype/src/cid/cidgload.h | 10 +- lib/libesp32_lvgl/freetype/src/cid/cidload.c | 171 +- lib/libesp32_lvgl/freetype/src/cid/cidload.h | 4 +- lib/libesp32_lvgl/freetype/src/cid/cidobjs.c | 33 +- lib/libesp32_lvgl/freetype/src/cid/cidobjs.h | 2 +- lib/libesp32_lvgl/freetype/src/cid/cidparse.c | 26 +- lib/libesp32_lvgl/freetype/src/cid/cidparse.h | 4 +- lib/libesp32_lvgl/freetype/src/cid/cidriver.c | 95 +- lib/libesp32_lvgl/freetype/src/cid/cidriver.h | 2 +- lib/libesp32_lvgl/freetype/src/cid/cidtoken.h | 2 +- lib/libesp32_lvgl/freetype/src/cid/module.mk | 2 +- lib/libesp32_lvgl/freetype/src/cid/rules.mk | 2 +- lib/libesp32_lvgl/freetype/src/cid/type1cid.c | 2 +- lib/libesp32_lvgl/freetype/src/dlg/dlg.c | 803 ++ lib/libesp32_lvgl/freetype/src/dlg/dlgwrap.c | 32 + lib/libesp32_lvgl/freetype/src/dlg/rules.mk | 70 + lib/libesp32_lvgl/freetype/src/gxvalid/README | 2 +- .../freetype/src/gxvalid/gxvalid.c | 2 +- .../freetype/src/gxvalid/gxvalid.h | 2 +- .../freetype/src/gxvalid/gxvbsln.c | 2 +- .../freetype/src/gxvalid/gxvcommn.c | 61 +- .../freetype/src/gxvalid/gxvcommn.h | 37 +- .../freetype/src/gxvalid/gxverror.h | 2 +- .../freetype/src/gxvalid/gxvfeat.c | 4 +- .../freetype/src/gxvalid/gxvfeat.h | 2 +- .../freetype/src/gxvalid/gxvfgen.c | 5 +- .../freetype/src/gxvalid/gxvjust.c | 26 +- .../freetype/src/gxvalid/gxvkern.c | 14 +- .../freetype/src/gxvalid/gxvlcar.c | 2 +- .../freetype/src/gxvalid/gxvmod.c | 48 +- .../freetype/src/gxvalid/gxvmod.h | 2 +- .../freetype/src/gxvalid/gxvmort.c | 4 +- .../freetype/src/gxvalid/gxvmort.h | 2 +- .../freetype/src/gxvalid/gxvmort0.c | 2 +- .../freetype/src/gxvalid/gxvmort1.c | 2 +- .../freetype/src/gxvalid/gxvmort2.c | 14 +- .../freetype/src/gxvalid/gxvmort4.c | 2 +- .../freetype/src/gxvalid/gxvmort5.c | 4 +- .../freetype/src/gxvalid/gxvmorx.c | 8 +- .../freetype/src/gxvalid/gxvmorx.h | 2 +- .../freetype/src/gxvalid/gxvmorx0.c | 2 +- .../freetype/src/gxvalid/gxvmorx1.c | 2 +- .../freetype/src/gxvalid/gxvmorx2.c | 30 +- .../freetype/src/gxvalid/gxvmorx4.c | 2 +- .../freetype/src/gxvalid/gxvmorx5.c | 2 +- .../freetype/src/gxvalid/gxvopbd.c | 4 +- .../freetype/src/gxvalid/gxvprop.c | 6 +- .../freetype/src/gxvalid/gxvtrak.c | 6 +- .../freetype/src/gxvalid/module.mk | 2 +- .../freetype/src/gxvalid/rules.mk | 2 +- .../freetype/src/gzip/README.freetype | 23 + lib/libesp32_lvgl/freetype/src/gzip/adler32.c | 188 +- lib/libesp32_lvgl/freetype/src/gzip/crc32.c | 1135 ++ lib/libesp32_lvgl/freetype/src/gzip/crc32.h | 9446 ++++++++++++++ lib/libesp32_lvgl/freetype/src/gzip/ftgzip.c | 110 +- lib/libesp32_lvgl/freetype/src/gzip/ftzconf.h | 545 +- lib/libesp32_lvgl/freetype/src/gzip/gzguts.h | 219 + .../freetype/src/gzip/infblock.c | 392 - .../freetype/src/gzip/infblock.h | 36 - .../freetype/src/gzip/infcodes.c | 254 - .../freetype/src/gzip/infcodes.h | 31 - lib/libesp32_lvgl/freetype/src/gzip/inffast.c | 323 + lib/libesp32_lvgl/freetype/src/gzip/inffast.h | 11 + .../freetype/src/gzip/inffixed.h | 241 +- lib/libesp32_lvgl/freetype/src/gzip/inflate.c | 1840 ++- lib/libesp32_lvgl/freetype/src/gzip/inflate.h | 131 + .../freetype/src/gzip/inftrees.c | 672 +- .../freetype/src/gzip/inftrees.h | 102 +- lib/libesp32_lvgl/freetype/src/gzip/infutil.c | 86 - lib/libesp32_lvgl/freetype/src/gzip/infutil.h | 98 - .../src/gzip/patches/freetype-zlib.diff | 469 + lib/libesp32_lvgl/freetype/src/gzip/rules.mk | 36 +- lib/libesp32_lvgl/freetype/src/gzip/zlib.h | 1965 ++- lib/libesp32_lvgl/freetype/src/gzip/zutil.c | 243 +- lib/libesp32_lvgl/freetype/src/gzip/zutil.h | 210 +- lib/libesp32_lvgl/freetype/src/lzw/ftlzw.c | 6 +- lib/libesp32_lvgl/freetype/src/lzw/ftzopen.c | 13 +- lib/libesp32_lvgl/freetype/src/lzw/ftzopen.h | 2 +- lib/libesp32_lvgl/freetype/src/lzw/rules.mk | 2 +- .../freetype/src/otvalid/module.mk | 2 +- .../freetype/src/otvalid/otvalid.c | 2 +- .../freetype/src/otvalid/otvalid.h | 2 +- .../freetype/src/otvalid/otvbase.c | 2 +- .../freetype/src/otvalid/otvcommn.c | 2 +- .../freetype/src/otvalid/otvcommn.h | 40 +- .../freetype/src/otvalid/otverror.h | 2 +- .../freetype/src/otvalid/otvgdef.c | 2 +- .../freetype/src/otvalid/otvgpos.c | 2 +- .../freetype/src/otvalid/otvgpos.h | 2 +- .../freetype/src/otvalid/otvgsub.c | 22 +- .../freetype/src/otvalid/otvjstf.c | 2 +- .../freetype/src/otvalid/otvmath.c | 4 +- .../freetype/src/otvalid/otvmod.c | 6 +- .../freetype/src/otvalid/otvmod.h | 2 +- .../freetype/src/otvalid/rules.mk | 2 +- lib/libesp32_lvgl/freetype/src/pcf/pcfdrivr.c | 200 +- lib/libesp32_lvgl/freetype/src/pcf/pcfread.c | 110 +- lib/libesp32_lvgl/freetype/src/pcf/pcfutil.c | 52 +- lib/libesp32_lvgl/freetype/src/pfr/module.mk | 2 +- lib/libesp32_lvgl/freetype/src/pfr/pfr.c | 2 +- lib/libesp32_lvgl/freetype/src/pfr/pfrcmap.c | 68 +- lib/libesp32_lvgl/freetype/src/pfr/pfrcmap.h | 2 +- lib/libesp32_lvgl/freetype/src/pfr/pfrdrivr.c | 28 +- lib/libesp32_lvgl/freetype/src/pfr/pfrdrivr.h | 2 +- lib/libesp32_lvgl/freetype/src/pfr/pfrerror.h | 2 +- lib/libesp32_lvgl/freetype/src/pfr/pfrgload.c | 10 +- lib/libesp32_lvgl/freetype/src/pfr/pfrgload.h | 2 +- lib/libesp32_lvgl/freetype/src/pfr/pfrload.c | 99 +- lib/libesp32_lvgl/freetype/src/pfr/pfrload.h | 2 +- lib/libesp32_lvgl/freetype/src/pfr/pfrobjs.c | 41 +- lib/libesp32_lvgl/freetype/src/pfr/pfrobjs.h | 2 +- lib/libesp32_lvgl/freetype/src/pfr/pfrsbit.c | 31 +- lib/libesp32_lvgl/freetype/src/pfr/pfrsbit.h | 2 +- lib/libesp32_lvgl/freetype/src/pfr/pfrtypes.h | 4 +- lib/libesp32_lvgl/freetype/src/pfr/rules.mk | 2 +- .../freetype/src/psaux/afmparse.c | 136 +- .../freetype/src/psaux/afmparse.h | 2 +- .../freetype/src/psaux/cffdecode.c | 35 +- .../freetype/src/psaux/cffdecode.h | 2 +- .../freetype/src/psaux/module.mk | 2 +- .../freetype/src/psaux/psarrst.c | 7 +- .../freetype/src/psaux/psarrst.h | 1 - lib/libesp32_lvgl/freetype/src/psaux/psaux.c | 2 +- .../freetype/src/psaux/psauxerr.h | 2 +- .../freetype/src/psaux/psauxmod.c | 2 +- .../freetype/src/psaux/psauxmod.h | 2 +- .../freetype/src/psaux/psblues.c | 3 +- lib/libesp32_lvgl/freetype/src/psaux/psconv.c | 10 +- lib/libesp32_lvgl/freetype/src/psaux/psconv.h | 2 +- .../freetype/src/psaux/psfixed.h | 6 +- lib/libesp32_lvgl/freetype/src/psaux/psft.c | 10 +- lib/libesp32_lvgl/freetype/src/psaux/psglue.h | 2 +- .../freetype/src/psaux/pshints.c | 70 +- .../freetype/src/psaux/psintrp.c | 69 +- .../freetype/src/psaux/psintrp.h | 2 +- lib/libesp32_lvgl/freetype/src/psaux/psobjs.c | 106 +- lib/libesp32_lvgl/freetype/src/psaux/psobjs.h | 2 +- .../freetype/src/psaux/psstack.c | 8 +- .../freetype/src/psaux/psstack.h | 4 +- lib/libesp32_lvgl/freetype/src/psaux/rules.mk | 2 +- lib/libesp32_lvgl/freetype/src/psaux/t1cmap.c | 143 +- lib/libesp32_lvgl/freetype/src/psaux/t1cmap.h | 2 +- .../freetype/src/psaux/t1decode.c | 33 +- .../freetype/src/psaux/t1decode.h | 2 +- .../freetype/src/pshinter/module.mk | 2 +- .../freetype/src/pshinter/pshalgo.c | 141 +- .../freetype/src/pshinter/pshalgo.h | 32 +- .../freetype/src/pshinter/pshglob.c | 4 +- .../freetype/src/pshinter/pshglob.h | 2 +- .../freetype/src/pshinter/pshinter.c | 2 +- .../freetype/src/pshinter/pshmod.c | 11 +- .../freetype/src/pshinter/pshmod.h | 2 +- .../freetype/src/pshinter/pshnterr.h | 2 +- .../freetype/src/pshinter/pshrec.c | 189 +- .../freetype/src/pshinter/pshrec.h | 2 +- .../freetype/src/pshinter/rules.mk | 2 +- .../freetype/src/psnames/module.mk | 2 +- .../freetype/src/psnames/psmodule.c | 115 +- .../freetype/src/psnames/psmodule.h | 2 +- .../freetype/src/psnames/psnamerr.h | 2 +- .../freetype/src/psnames/psnames.c | 2 +- .../freetype/src/psnames/pstables.h | 2 +- .../freetype/src/psnames/rules.mk | 2 +- .../freetype/src/raster/ftmisc.h | 9 +- .../freetype/src/raster/ftraster.c | 385 +- .../freetype/src/raster/ftraster.h | 2 +- .../freetype/src/raster/ftrend1.c | 23 +- .../freetype/src/raster/ftrend1.h | 2 +- .../freetype/src/raster/module.mk | 2 +- .../freetype/src/raster/raster.c | 2 +- .../freetype/src/raster/rasterrs.h | 2 +- .../freetype/src/raster/rules.mk | 2 +- lib/libesp32_lvgl/freetype/src/sdf/ftbsdf.c | 1350 ++ lib/libesp32_lvgl/freetype/src/sdf/ftsdf.c | 3932 ++++++ lib/libesp32_lvgl/freetype/src/sdf/ftsdf.h | 97 + .../freetype/src/sdf/ftsdfcommon.c | 147 + .../freetype/src/sdf/ftsdfcommon.h | 141 + .../freetype/src/sdf/ftsdferrs.h | 37 + .../freetype/src/sdf/ftsdfrend.c | 603 + .../freetype/src/sdf/ftsdfrend.h | 118 + lib/libesp32_lvgl/freetype/src/sdf/module.mk | 29 + lib/libesp32_lvgl/freetype/src/sdf/rules.mk | 78 + lib/libesp32_lvgl/freetype/src/sdf/sdf.c | 29 + lib/libesp32_lvgl/freetype/src/sfnt/module.mk | 2 +- lib/libesp32_lvgl/freetype/src/sfnt/pngshim.c | 25 +- lib/libesp32_lvgl/freetype/src/sfnt/pngshim.h | 2 +- lib/libesp32_lvgl/freetype/src/sfnt/rules.mk | 3 +- .../freetype/src/sfnt/sfdriver.c | 247 +- .../freetype/src/sfnt/sfdriver.h | 2 +- .../freetype/src/sfnt/sferrors.h | 2 +- lib/libesp32_lvgl/freetype/src/sfnt/sfnt.c | 3 +- lib/libesp32_lvgl/freetype/src/sfnt/sfobjs.c | 158 +- lib/libesp32_lvgl/freetype/src/sfnt/sfobjs.h | 2 +- lib/libesp32_lvgl/freetype/src/sfnt/sfwoff.c | 43 +- lib/libesp32_lvgl/freetype/src/sfnt/sfwoff.h | 5 +- lib/libesp32_lvgl/freetype/src/sfnt/sfwoff2.c | 225 +- lib/libesp32_lvgl/freetype/src/sfnt/sfwoff2.h | 5 +- lib/libesp32_lvgl/freetype/src/sfnt/ttbdf.c | 15 +- lib/libesp32_lvgl/freetype/src/sfnt/ttbdf.h | 4 +- lib/libesp32_lvgl/freetype/src/sfnt/ttcmap.c | 564 +- lib/libesp32_lvgl/freetype/src/sfnt/ttcmap.h | 2 +- lib/libesp32_lvgl/freetype/src/sfnt/ttcmapc.h | 2 +- lib/libesp32_lvgl/freetype/src/sfnt/ttcolr.c | 1509 ++- lib/libesp32_lvgl/freetype/src/sfnt/ttcolr.h | 28 +- lib/libesp32_lvgl/freetype/src/sfnt/ttcpal.c | 4 +- lib/libesp32_lvgl/freetype/src/sfnt/ttcpal.h | 2 +- lib/libesp32_lvgl/freetype/src/sfnt/ttkern.c | 21 +- lib/libesp32_lvgl/freetype/src/sfnt/ttkern.h | 2 +- lib/libesp32_lvgl/freetype/src/sfnt/ttload.c | 123 +- lib/libesp32_lvgl/freetype/src/sfnt/ttload.h | 2 +- lib/libesp32_lvgl/freetype/src/sfnt/ttmtx.c | 6 +- lib/libesp32_lvgl/freetype/src/sfnt/ttmtx.h | 2 +- lib/libesp32_lvgl/freetype/src/sfnt/ttpost.c | 329 +- lib/libesp32_lvgl/freetype/src/sfnt/ttpost.h | 2 +- lib/libesp32_lvgl/freetype/src/sfnt/ttsbit.c | 90 +- lib/libesp32_lvgl/freetype/src/sfnt/ttsbit.h | 2 +- lib/libesp32_lvgl/freetype/src/sfnt/ttsvg.c | 413 + lib/libesp32_lvgl/freetype/src/sfnt/ttsvg.h | 43 + .../freetype/src/sfnt/woff2tags.c | 16 +- .../freetype/src/sfnt/woff2tags.h | 8 +- .../freetype/src/smooth/ftgrays.c | 911 +- .../freetype/src/smooth/ftgrays.h | 2 +- .../freetype/src/smooth/ftsmerrs.h | 2 +- .../freetype/src/smooth/ftsmooth.c | 24 +- .../freetype/src/smooth/ftsmooth.h | 2 +- .../freetype/src/smooth/module.mk | 2 +- .../freetype/src/smooth/rules.mk | 2 +- .../freetype/src/smooth/smooth.c | 2 +- lib/libesp32_lvgl/freetype/src/svg/ftsvg.c | 355 + lib/libesp32_lvgl/freetype/src/svg/ftsvg.h | 35 + lib/libesp32_lvgl/freetype/src/svg/module.mk | 23 + lib/libesp32_lvgl/freetype/src/svg/rules.mk | 70 + lib/libesp32_lvgl/freetype/src/svg/svg.c | 24 + lib/libesp32_lvgl/freetype/src/svg/svgtypes.h | 42 + .../freetype/src/tools/afblue.pl | 551 + .../freetype/src/tools/apinames.c | 556 + .../freetype/src/tools/chktrcmp.py | 119 + .../freetype/src/tools/cordic.py | 32 + .../freetype/src/tools/ftrandom/Makefile | 45 + .../freetype/src/tools/ftrandom/README | 69 + .../freetype/src/tools/ftrandom/ftrandom.c | 720 ++ .../freetype/src/tools/glnames.py | 5533 +++++++++ .../src/tools/make_distribution_archives.py | 208 + .../freetype/src/tools/no-copyright | 66 + .../freetype/src/tools/test_afm.c | 156 + .../freetype/src/tools/test_bbox.c | 187 + .../freetype/src/tools/test_trig.c | 257 + .../freetype/src/tools/update-copyright | 14 + .../freetype/src/tools/update-copyright-year | 157 + .../freetype/src/tools/vms_shorten_symbol.c | 250 + .../freetype/src/truetype/module.mk | 2 +- .../freetype/src/truetype/rules.mk | 5 +- .../freetype/src/truetype/truetype.c | 3 +- .../freetype/src/truetype/ttdriver.c | 158 +- .../freetype/src/truetype/ttdriver.h | 2 +- .../freetype/src/truetype/tterrors.h | 2 +- .../freetype/src/truetype/ttgload.c | 1001 +- .../freetype/src/truetype/ttgload.h | 2 +- .../freetype/src/truetype/ttgxvar.c | 1432 ++- .../freetype/src/truetype/ttgxvar.h | 130 +- .../freetype/src/truetype/ttinterp.c | 1158 +- .../freetype/src/truetype/ttinterp.h | 179 +- .../freetype/src/truetype/ttobjs.c | 187 +- .../freetype/src/truetype/ttobjs.h | 12 +- .../freetype/src/truetype/ttpload.c | 158 +- .../freetype/src/truetype/ttpload.h | 8 +- .../freetype/src/truetype/ttsubpix.c | 1013 -- .../freetype/src/truetype/ttsubpix.h | 110 - .../freetype/src/type1/module.mk | 2 +- lib/libesp32_lvgl/freetype/src/type1/rules.mk | 2 +- lib/libesp32_lvgl/freetype/src/type1/t1afm.c | 29 +- lib/libesp32_lvgl/freetype/src/type1/t1afm.h | 2 +- .../freetype/src/type1/t1driver.c | 82 +- .../freetype/src/type1/t1driver.h | 2 +- .../freetype/src/type1/t1errors.h | 2 +- .../freetype/src/type1/t1gload.c | 6 +- .../freetype/src/type1/t1gload.h | 2 +- lib/libesp32_lvgl/freetype/src/type1/t1load.c | 384 +- lib/libesp32_lvgl/freetype/src/type1/t1load.h | 24 +- lib/libesp32_lvgl/freetype/src/type1/t1objs.c | 28 +- lib/libesp32_lvgl/freetype/src/type1/t1objs.h | 2 +- .../freetype/src/type1/t1parse.c | 65 +- .../freetype/src/type1/t1parse.h | 2 +- .../freetype/src/type1/t1tokens.h | 2 +- lib/libesp32_lvgl/freetype/src/type1/type1.c | 2 +- .../freetype/src/type42/module.mk | 2 +- .../freetype/src/type42/rules.mk | 2 +- .../freetype/src/type42/t42drivr.c | 58 +- .../freetype/src/type42/t42drivr.h | 2 +- .../freetype/src/type42/t42error.h | 2 +- .../freetype/src/type42/t42objs.c | 31 +- .../freetype/src/type42/t42objs.h | 2 +- .../freetype/src/type42/t42parse.c | 162 +- .../freetype/src/type42/t42parse.h | 2 +- .../freetype/src/type42/t42types.h | 2 +- .../freetype/src/type42/type42.c | 2 +- .../freetype/src/winfonts/fnterrs.h | 2 +- .../freetype/src/winfonts/module.mk | 2 +- .../freetype/src/winfonts/rules.mk | 2 +- .../freetype/src/winfonts/winfnt.c | 80 +- .../freetype/src/winfonts/winfnt.h | 2 +- .../generate/LVGL_API_Reference.md | 1514 +++ .../generate/be_lv_c_mapping.h | 2415 ++-- .../generate/be_lvgl_module.c | 696 +- .../generate/be_lvgl_widgets_lib.c | 2304 ++-- .../lv_binding_berry/mapping/lv_enum.h | 794 +- .../lv_binding_berry/mapping/lv_funcs.h | 2273 ++-- .../src/be_lvgl_ctypes_definitions.c | 851 +- .../src/embedded/berry_ctypes.py | 13 +- .../lv_binding_berry/src/embedded/lv.be | 7 + .../src/embedded/lvgl_ctypes.py | 841 +- .../src/embedded/lvgl_extra.be | 81 +- .../src/embedded/lvgl_glob.be | 151 +- .../lv_binding_berry/src/lv_berry.c | 45 +- .../lv_binding_berry/src/lv_berry.h | 14 +- .../lv_binding_berry/src/lv_mem_core_berry.c | 97 + .../src/solidify/solidified_lv.h | 26 +- .../src/solidify/solidified_lvgl_extra.h | 780 +- .../src/solidify/solidified_lvgl_glob.h | 1198 +- .../lv_binding_berry/tools/convert.py | 1045 +- .../lv_binding_berry/tools/preprocessor.py | 134 +- lib/libesp32_lvgl/lvgl/README.md | 566 +- lib/libesp32_lvgl/lvgl/README_Tasmota.md | 6 +- lib/libesp32_lvgl/lvgl/README_pt_BR.md | 206 - lib/libesp32_lvgl/lvgl/README_zh.md | 193 - lib/libesp32_lvgl/lvgl/library.json | 2 +- lib/libesp32_lvgl/lvgl/library.properties | 2 +- lib/libesp32_lvgl/lvgl/lv_conf_template.h | 804 +- lib/libesp32_lvgl/lvgl/lvgl.h | 114 +- lib/libesp32_lvgl/lvgl/src/core/lv_core.mk | 20 - lib/libesp32_lvgl/lvgl/src/core/lv_disp.c | 539 - lib/libesp32_lvgl/lvgl/src/core/lv_disp.h | 264 - lib/libesp32_lvgl/lvgl/src/core/lv_event.c | 527 - lib/libesp32_lvgl/lvgl/src/core/lv_event.h | 363 - lib/libesp32_lvgl/lvgl/src/core/lv_global.h | 229 + lib/libesp32_lvgl/lvgl/src/core/lv_group.c | 115 +- lib/libesp32_lvgl/lvgl/src/core/lv_group.h | 57 +- lib/libesp32_lvgl/lvgl/src/core/lv_indev.c | 1180 -- lib/libesp32_lvgl/lvgl/src/core/lv_indev.h | 176 - lib/libesp32_lvgl/lvgl/src/core/lv_obj.c | 552 +- lib/libesp32_lvgl/lvgl/src/core/lv_obj.h | 255 +- .../lvgl/src/core/lv_obj_class.c | 72 +- .../lvgl/src/core/lv_obj_class.h | 58 +- lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.c | 218 +- lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.h | 74 +- .../lvgl/src/core/lv_obj_event.c | 394 + .../lvgl/src/core/lv_obj_event.h | 212 + .../lvgl/src/core/lv_obj_id_builtin.c | 108 + lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.c | 523 +- lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.h | 113 +- .../lvgl/src/core/lv_obj_property.c | 179 + .../lvgl/src/core/lv_obj_property.h | 128 + .../lvgl/src/core/lv_obj_scroll.c | 307 +- .../lvgl/src/core/lv_obj_scroll.h | 81 +- .../lvgl/src/core/lv_obj_style.c | 628 +- .../lvgl/src/core/lv_obj_style.h | 180 +- .../lvgl/src/core/lv_obj_style_gen.c | 429 +- .../lvgl/src/core/lv_obj_style_gen.h | 696 +- lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.c | 388 +- lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.h | 113 +- lib/libesp32_lvgl/lvgl/src/core/lv_refr.c | 1281 +- lib/libesp32_lvgl/lvgl/src/core/lv_refr.h | 41 +- .../lvgl/src/display/lv_display.c | 1050 ++ .../lvgl/src/display/lv_display.h | 601 + .../lvgl/src/display/lv_display_private.h | 165 + .../lvgl/src/draw/arm2d/lv_draw_arm2d.mk | 6 - .../lvgl/src/draw/arm2d/lv_gpu_arm2d.c | 1574 --- .../lvgl/src/draw/arm2d/lv_gpu_arm2d.h | 51 - lib/libesp32_lvgl/lvgl/src/draw/lv_draw.c | 380 +- lib/libesp32_lvgl/lvgl/src/draw/lv_draw.h | 391 +- lib/libesp32_lvgl/lvgl/src/draw/lv_draw.mk | 25 - lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.c | 117 +- lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.h | 38 +- lib/libesp32_lvgl/lvgl/src/draw/lv_draw_buf.c | 441 + lib/libesp32_lvgl/lvgl/src/draw/lv_draw_buf.h | 251 + .../lvgl/src/draw/lv_draw_image.c | 262 + .../lvgl/src/draw/lv_draw_image.h | 138 + lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.c | 375 - lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.h | 104 - .../lvgl/src/draw/lv_draw_label.c | 440 +- .../lvgl/src/draw/lv_draw_label.h | 133 +- .../lvgl/src/draw/lv_draw_layer.c | 93 - .../lvgl/src/draw/lv_draw_layer.h | 83 - .../lvgl/src/draw/lv_draw_line.c | 25 +- .../lvgl/src/draw/lv_draw_line.h | 30 +- .../lvgl/src/draw/lv_draw_mask.c | 1510 +-- .../lvgl/src/draw/lv_draw_mask.h | 371 +- .../lvgl/src/draw/lv_draw_rect.c | 237 +- .../lvgl/src/draw/lv_draw_rect.h | 107 +- .../lvgl/src/draw/lv_draw_transform.c | 54 - .../lvgl/src/draw/lv_draw_transform.h | 44 - .../lvgl/src/draw/lv_draw_triangle.c | 35 +- .../lvgl/src/draw/lv_draw_triangle.h | 24 +- .../lvgl/src/draw/lv_draw_vector.c | 753 ++ .../lvgl/src/draw/lv_draw_vector.h | 538 + .../lvgl/src/draw/lv_image_buf.c | 92 + .../lvgl/src/draw/lv_image_buf.h | 195 + .../lvgl/src/draw/lv_image_decoder.c | 451 + .../lvgl/src/draw/lv_image_decoder.h | 306 + lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.c | 392 - lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.h | 249 - .../lvgl/src/draw/lv_img_cache.c | 215 - .../lvgl/src/draw/lv_img_cache.h | 78 - .../lvgl/src/draw/lv_img_decoder.c | 730 -- .../lvgl/src/draw/lv_img_decoder.h | 274 - .../lvgl/src/draw/nxp/lv_draw_nxp.mk | 7 - .../lvgl/src/draw/nxp/pxp/lv_draw_buf_pxp.c | 106 + .../lvgl/src/draw/nxp/pxp/lv_draw_nxp_pxp.mk | 9 - .../lvgl/src/draw/nxp/pxp/lv_draw_pxp.c | 602 +- .../lvgl/src/draw/nxp/pxp/lv_draw_pxp.h | 48 +- .../lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.c | 573 - .../lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.h | 130 - .../lvgl/src/draw/nxp/pxp/lv_draw_pxp_fill.c | 147 + .../lvgl/src/draw/nxp/pxp/lv_draw_pxp_img.c | 365 + .../lvgl/src/draw/nxp/pxp/lv_draw_pxp_layer.c | 156 + .../lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.c | 138 - .../lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.h | 166 - .../src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.c | 180 - .../src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.h | 78 - .../lvgl/src/draw/nxp/pxp/lv_pxp_cfg.c | 91 + .../lvgl/src/draw/nxp/pxp/lv_pxp_cfg.h | 102 + .../lvgl/src/draw/nxp/pxp/lv_pxp_osa.c | 165 + .../lvgl/src/draw/nxp/pxp/lv_pxp_osa.h | 60 + .../lvgl/src/draw/nxp/pxp/lv_pxp_utils.c | 145 + .../lvgl/src/draw/nxp/pxp/lv_pxp_utils.h | 80 + .../src/draw/nxp/vglite/lv_draw_buf_vglite.c | 148 + .../src/draw/nxp/vglite/lv_draw_nxp_vglite.mk | 12 - .../lvgl/src/draw/nxp/vglite/lv_draw_vglite.c | 940 +- .../lvgl/src/draw/nxp/vglite/lv_draw_vglite.h | 57 +- .../src/draw/nxp/vglite/lv_draw_vglite_arc.c | 468 +- .../src/draw/nxp/vglite/lv_draw_vglite_arc.h | 83 - .../draw/nxp/vglite/lv_draw_vglite_blend.c | 635 - .../draw/nxp/vglite/lv_draw_vglite_blend.h | 168 - .../draw/nxp/vglite/lv_draw_vglite_border.c | 150 + .../src/draw/nxp/vglite/lv_draw_vglite_fill.c | 237 + .../src/draw/nxp/vglite/lv_draw_vglite_img.c | 401 + .../draw/nxp/vglite/lv_draw_vglite_label.c | 184 + .../draw/nxp/vglite/lv_draw_vglite_layer.c | 159 + .../src/draw/nxp/vglite/lv_draw_vglite_line.c | 131 +- .../src/draw/nxp/vglite/lv_draw_vglite_line.h | 83 - .../src/draw/nxp/vglite/lv_draw_vglite_rect.c | 459 - .../src/draw/nxp/vglite/lv_draw_vglite_rect.h | 97 - .../draw/nxp/vglite/lv_draw_vglite_triangle.c | 179 + .../lvgl/src/draw/nxp/vglite/lv_vglite_buf.c | 97 +- .../lvgl/src/draw/nxp/vglite/lv_vglite_buf.h | 84 +- .../src/draw/nxp/vglite/lv_vglite_matrix.c | 79 + .../src/draw/nxp/vglite/lv_vglite_matrix.h | 78 + .../lvgl/src/draw/nxp/vglite/lv_vglite_path.c | 217 + .../lvgl/src/draw/nxp/vglite/lv_vglite_path.h | 91 + .../src/draw/nxp/vglite/lv_vglite_utils.c | 302 +- .../src/draw/nxp/vglite/lv_vglite_utils.h | 209 +- .../src/draw/renesas/dave2d/lv_draw_dave2d.c | 633 + .../src/draw/renesas/dave2d/lv_draw_dave2d.h | 91 + .../draw/renesas/dave2d/lv_draw_dave2d_arc.c | 194 + .../renesas/dave2d/lv_draw_dave2d_border.c | 433 + .../draw/renesas/dave2d/lv_draw_dave2d_fill.c | 328 + .../renesas/dave2d/lv_draw_dave2d_image.c | 331 + .../renesas/dave2d/lv_draw_dave2d_label.c | 157 + .../draw/renesas/dave2d/lv_draw_dave2d_line.c | 97 + .../dave2d/lv_draw_dave2d_mask_rectangle.c | 59 + .../renesas/dave2d/lv_draw_dave2d_triangle.c | 179 + .../renesas/dave2d/lv_draw_dave2d_utils.c | 140 + .../renesas/dave2d/lv_draw_dave2d_utils.h | 45 + .../lvgl/src/draw/renesas/lv_draw_renesas.mk | 7 - .../src/draw/renesas/lv_gpu_d2_draw_label.c | 292 - .../lvgl/src/draw/renesas/lv_gpu_d2_ra6m3.c | 742 -- .../lvgl/src/draw/renesas/lv_gpu_d2_ra6m3.h | 56 - lib/libesp32_lvgl/lvgl/src/draw/sdl/README.md | 28 - .../lvgl/src/draw/sdl/lv_draw_sdl.c | 409 +- .../lvgl/src/draw/sdl/lv_draw_sdl.h | 86 +- .../lvgl/src/draw/sdl/lv_draw_sdl.mk | 19 - .../lvgl/src/draw/sdl/lv_draw_sdl_arc.c | 245 - .../lvgl/src/draw/sdl/lv_draw_sdl_bg.c | 106 - .../lvgl/src/draw/sdl/lv_draw_sdl_composite.c | 279 - .../lvgl/src/draw/sdl/lv_draw_sdl_composite.h | 84 - .../lvgl/src/draw/sdl/lv_draw_sdl_img.c | 499 - .../lvgl/src/draw/sdl/lv_draw_sdl_img.h | 86 - .../lvgl/src/draw/sdl/lv_draw_sdl_label.c | 189 - .../lvgl/src/draw/sdl/lv_draw_sdl_layer.c | 147 - .../lvgl/src/draw/sdl/lv_draw_sdl_layer.h | 56 - .../lvgl/src/draw/sdl/lv_draw_sdl_line.c | 157 - .../lvgl/src/draw/sdl/lv_draw_sdl_mask.c | 84 - .../lvgl/src/draw/sdl/lv_draw_sdl_mask.h | 51 - .../lvgl/src/draw/sdl/lv_draw_sdl_polygon.c | 139 - .../lvgl/src/draw/sdl/lv_draw_sdl_priv.h | 73 - .../lvgl/src/draw/sdl/lv_draw_sdl_rect.c | 1013 -- .../lvgl/src/draw/sdl/lv_draw_sdl_rect.h | 104 - .../src/draw/sdl/lv_draw_sdl_stack_blur.c | 249 - .../src/draw/sdl/lv_draw_sdl_texture_cache.c | 176 - .../src/draw/sdl/lv_draw_sdl_texture_cache.h | 109 - .../lvgl/src/draw/sdl/lv_draw_sdl_utils.c | 183 - .../lvgl/src/draw/sdl/lv_draw_sdl_utils.h | 65 - .../draw/stm32_dma2d/lv_draw_stm32_dma2d.mk | 6 - .../src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c | 796 -- .../src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h | 67 - .../lvgl/src/draw/sw/arm2d/lv_draw_sw_arm2d.h | 564 + .../src/draw/sw/arm2d/lv_draw_sw_helium.h | 60 + .../src/draw/sw/blend/arm2d/lv_blend_arm2d.h | 1441 +++ .../src/draw/sw/blend/arm2d/lv_blend_helium.h | 58 + .../lvgl/src/draw/sw/blend/lv_draw_sw_blend.c | 151 + .../lvgl/src/draw/sw/blend/lv_draw_sw_blend.h | 93 + .../sw/blend/lv_draw_sw_blend_to_argb8888.c | 655 + .../sw/blend/lv_draw_sw_blend_to_argb8888.h | 45 + .../sw/blend/lv_draw_sw_blend_to_rgb565.c | 675 + .../sw/blend/lv_draw_sw_blend_to_rgb565.h | 45 + .../sw/blend/lv_draw_sw_blend_to_rgb888.c | 606 + .../sw/blend/lv_draw_sw_blend_to_rgb888.h | 45 + .../src/draw/sw/blend/neon/lv_blend_neon.S | 684 ++ .../src/draw/sw/blend/neon/lv_blend_neon.h | 1295 ++ .../lvgl/src/draw/sw/lv_draw_sw.c | 607 +- .../lvgl/src/draw/sw/lv_draw_sw.h | 194 +- .../lvgl/src/draw/sw/lv_draw_sw.mk | 17 - .../lvgl/src/draw/sw/lv_draw_sw_arc.c | 585 +- .../lvgl/src/draw/sw/lv_draw_sw_blend.c | 1061 -- .../lvgl/src/draw/sw/lv_draw_sw_blend.h | 70 - .../lvgl/src/draw/sw/lv_draw_sw_border.c | 332 + .../lvgl/src/draw/sw/lv_draw_sw_box_shadow.c | 729 ++ .../lvgl/src/draw/sw/lv_draw_sw_dither.c | 213 - .../lvgl/src/draw/sw/lv_draw_sw_dither.h | 71 - .../lvgl/src/draw/sw/lv_draw_sw_fill.c | 224 + .../lvgl/src/draw/sw/lv_draw_sw_gradient.c | 302 +- .../lvgl/src/draw/sw/lv_draw_sw_gradient.h | 50 +- .../lvgl/src/draw/sw/lv_draw_sw_img.c | 583 +- .../lvgl/src/draw/sw/lv_draw_sw_layer.c | 150 - .../lvgl/src/draw/sw/lv_draw_sw_letter.c | 564 +- .../lvgl/src/draw/sw/lv_draw_sw_line.c | 350 +- .../lvgl/src/draw/sw/lv_draw_sw_mask.c | 1235 ++ .../lvgl/src/draw/sw/lv_draw_sw_mask.h | 304 + .../lvgl/src/draw/sw/lv_draw_sw_mask_rect.c | 121 + .../lvgl/src/draw/sw/lv_draw_sw_polygon.c | 207 - .../lvgl/src/draw/sw/lv_draw_sw_rect.c | 1436 --- .../lvgl/src/draw/sw/lv_draw_sw_transform.c | 731 +- .../lvgl/src/draw/sw/lv_draw_sw_triangle.c | 197 + .../lvgl/src/draw/sw/lv_draw_sw_vector.c | 464 + .../draw/swm341_dma2d/lv_draw_swm341_dma2d.mk | 6 - .../draw/swm341_dma2d/lv_gpu_swm341_dma2d.c | 241 - .../draw/swm341_dma2d/lv_gpu_swm341_dma2d.h | 64 - .../src/draw/vg_lite/lv_draw_buf_vg_lite.c | 57 + .../lvgl/src/draw/vg_lite/lv_draw_vg_lite.c | 225 + .../lvgl/src/draw/vg_lite/lv_draw_vg_lite.h | 84 + .../src/draw/vg_lite/lv_draw_vg_lite_arc.c | 200 + .../src/draw/vg_lite/lv_draw_vg_lite_border.c | 115 + .../draw/vg_lite/lv_draw_vg_lite_box_shadow.c | 97 + .../src/draw/vg_lite/lv_draw_vg_lite_fill.c | 111 + .../src/draw/vg_lite/lv_draw_vg_lite_img.c | 158 + .../src/draw/vg_lite/lv_draw_vg_lite_label.c | 331 + .../src/draw/vg_lite/lv_draw_vg_lite_layer.c | 63 + .../src/draw/vg_lite/lv_draw_vg_lite_line.c | 211 + .../draw/vg_lite/lv_draw_vg_lite_mask_rect.c | 94 + .../draw/vg_lite/lv_draw_vg_lite_triangle.c | 104 + .../src/draw/vg_lite/lv_draw_vg_lite_type.h | 60 + .../src/draw/vg_lite/lv_draw_vg_lite_vector.c | 338 + .../src/draw/vg_lite/lv_vg_lite_decoder.c | 443 + .../vg_lite/lv_vg_lite_decoder.h} | 25 +- .../lvgl/src/draw/vg_lite/lv_vg_lite_math.c | 60 + .../lvgl/src/draw/vg_lite/lv_vg_lite_math.h | 75 + .../lvgl/src/draw/vg_lite/lv_vg_lite_path.c | 573 + .../lvgl/src/draw/vg_lite/lv_vg_lite_path.h | 124 + .../lvgl/src/draw/vg_lite/lv_vg_lite_utils.c | 1029 ++ .../lvgl/src/draw/vg_lite/lv_vg_lite_utils.h | 181 + lib/libesp32_lvgl/lvgl/src/drivers/README.md | 1 + .../src/drivers/display/drm/lv_linux_drm.c | 837 ++ .../src/drivers/display/drm/lv_linux_drm.h | 46 + .../src/drivers/display/fb/lv_linux_fbdev.c | 290 + .../src/drivers/display/fb/lv_linux_fbdev.h | 46 + .../src/drivers/display/ili9341/lv_ili9341.c | 117 + .../src/drivers/display/ili9341/lv_ili9341.h | 93 + .../drivers/display/lcd/lv_lcd_generic_mipi.c | 340 + .../drivers/display/lcd/lv_lcd_generic_mipi.h | 241 + .../src/drivers/display/st7735/lv_st7735.c | 113 + .../src/drivers/display/st7735/lv_st7735.h | 93 + .../src/drivers/display/st7789/lv_st7789.c | 116 + .../src/drivers/display/st7789/lv_st7789.h | 93 + .../src/drivers/display/st7796/lv_st7796.c | 121 + .../src/drivers/display/st7796/lv_st7796.h | 93 + .../drivers/display/tft_espi/lv_tft_espi.cpp | 83 + .../drivers/display/tft_espi/lv_tft_espi.h | 43 + .../lvgl/src/drivers/evdev/lv_evdev.c | 223 + .../lvgl/src/drivers/evdev/lv_evdev.h | 64 + .../lvgl/src/drivers/lv_drivers.h | 59 + .../lvgl/src/drivers/nuttx/lv_nuttx_cache.c | 77 + .../nuttx/lv_nuttx_cache.h} | 16 +- .../lvgl/src/drivers/nuttx/lv_nuttx_entry.c | 178 + .../lvgl/src/drivers/nuttx/lv_nuttx_entry.h | 81 + .../lvgl/src/drivers/nuttx/lv_nuttx_fbdev.c | 320 + .../lvgl/src/drivers/nuttx/lv_nuttx_fbdev.h | 55 + .../lvgl/src/drivers/nuttx/lv_nuttx_lcd.c | 238 + .../lvgl/src/drivers/nuttx/lv_nuttx_lcd.h | 49 + .../lvgl/src/drivers/nuttx/lv_nuttx_libuv.c | 340 + .../lvgl/src/drivers/nuttx/lv_nuttx_libuv.h | 66 + .../src/drivers/nuttx/lv_nuttx_profiler.c | 96 + .../nuttx/lv_nuttx_profiler.h} | 13 +- .../src/drivers/nuttx/lv_nuttx_touchscreen.c | 165 + .../src/drivers/nuttx/lv_nuttx_touchscreen.h | 57 + .../lvgl/src/drivers/sdl/lv_sdl_keyboard.c | 206 + .../lvgl/src/drivers/sdl/lv_sdl_keyboard.h | 46 + .../lvgl/src/drivers/sdl/lv_sdl_mouse.c | 181 + .../lvgl/src/drivers/sdl/lv_sdl_mouse.h | 43 + .../lvgl/src/drivers/sdl/lv_sdl_mousewheel.c | 142 + .../lvgl/src/drivers/sdl/lv_sdl_mousewheel.h | 43 + .../lvgl/src/drivers/sdl/lv_sdl_window.c | 390 + .../lvgl/src/drivers/sdl/lv_sdl_window.h | 60 + .../src/drivers/windows/lv_windows_context.c | 669 + .../src/drivers/windows/lv_windows_context.h | 123 + .../src/drivers/windows/lv_windows_display.c | 170 + .../src/drivers/windows/lv_windows_display.h | 127 + .../src/drivers/windows/lv_windows_input.c | 828 ++ .../src/drivers/windows/lv_windows_input.h | 83 + .../lvgl/src/drivers/x11/lv_x11.h | 81 + .../lvgl/src/drivers/x11/lv_x11_display.c | 395 + .../lvgl/src/drivers/x11/lv_x11_input.c | 279 + lib/libesp32_lvgl/lvgl/src/extra/README.md | 31 - .../lvgl/src/extra/layouts/grid/lv_grid.h | 194 - .../lvgl/src/extra/libs/bmp/lv_bmp.c | 258 - .../src/extra/libs/freetype/lv_freetype.c | 687 -- .../src/extra/libs/freetype/lv_freetype.h | 83 - .../src/extra/libs/fsdrv/lv_fs_littlefs.c | 332 - .../lvgl/src/extra/libs/gif/lv_gif.h | 58 - .../lvgl/src/extra/libs/png/lodepng.c | 6469 ---------- .../lvgl/src/extra/libs/png/lv_png.c | 278 - .../lvgl/src/extra/libs/qrcode/qrcodegen.c | 1035 -- .../lvgl/src/extra/libs/sjpg/lv_sjpg.c | 917 -- .../lvgl/src/extra/libs/sjpg/tjpgd.c | 1155 -- .../lvgl/src/extra/libs/sjpg/tjpgd.h | 93 - .../src/extra/libs/tiny_ttf/lv_tiny_ttf.c | 284 - lib/libesp32_lvgl/lvgl/src/extra/lv_extra.c | 97 - lib/libesp32_lvgl/lvgl/src/extra/lv_extra.mk | 1 - .../lvgl/src/extra/others/lv_others.h | 45 - .../lvgl/src/extra/others/msg/lv_msg.c | 189 - .../lvgl/src/extra/others/msg/lv_msg.h | 145 - .../src/extra/others/snapshot/lv_snapshot.c | 213 - .../src/extra/others/snapshot/lv_snapshot.h | 84 - .../src/extra/themes/basic/lv_theme_basic.c | 428 - .../extra/themes/default/lv_theme_default.c | 1181 -- .../src/extra/themes/mono/lv_theme_mono.c | 504 - .../src/extra/widgets/animimg/lv_animimg.h | 103 - .../lvgl/src/extra/widgets/chart/lv_chart.c | 1810 --- .../extra/widgets/colorwheel/lv_colorwheel.c | 713 -- .../extra/widgets/colorwheel/lv_colorwheel.h | 142 - .../lvgl/src/extra/widgets/imgbtn/lv_imgbtn.c | 386 - .../lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h | 131 - .../lvgl/src/extra/widgets/list/lv_list.h | 54 - .../lvgl/src/extra/widgets/lv_widgets.h | 56 - .../lvgl/src/extra/widgets/menu/lv_menu.h | 233 - .../lvgl/src/extra/widgets/meter/lv_meter.c | 702 -- .../lvgl/src/extra/widgets/meter/lv_meter.h | 266 - .../lvgl/src/extra/widgets/msgbox/lv_msgbox.c | 212 - .../lvgl/src/extra/widgets/msgbox/lv_msgbox.h | 99 - .../lvgl/src/extra/widgets/span/lv_span.h | 245 - .../src/extra/widgets/tabview/lv_tabview.c | 354 - .../src/extra/widgets/tabview/lv_tabview.h | 65 - lib/libesp32_lvgl/lvgl/src/font/korean.ttf | Bin 3371440 -> 0 bytes .../{lv_font_loader.c => lv_binfont_loader.c} | 188 +- .../lvgl/src/font/lv_binfont_loader.h | 61 + lib/libesp32_lvgl/lvgl/src/font/lv_font.c | 61 +- lib/libesp32_lvgl/lvgl/src/font/lv_font.h | 97 +- lib/libesp32_lvgl/lvgl/src/font/lv_font.mk | 36 - .../font/lv_font_dejavu_16_persian_hebrew.c | 17 +- .../lvgl/src/font/lv_font_fmt_txt.c | 358 +- .../lvgl/src/font/lv_font_fmt_txt.h | 59 +- .../lvgl/src/font/lv_font_montserrat_10.c | 17 +- .../lvgl/src/font/lv_font_montserrat_12.c | 17 +- .../src/font/lv_font_montserrat_12_subpx.c | 3865 ------ .../lvgl/src/font/lv_font_montserrat_14.c | 17 +- .../lvgl/src/font/lv_font_montserrat_16.c | 17 +- .../lvgl/src/font/lv_font_montserrat_18.c | 17 +- .../lvgl/src/font/lv_font_montserrat_20.c | 17 +- .../lvgl/src/font/lv_font_montserrat_22.c | 17 +- .../lvgl/src/font/lv_font_montserrat_24.c | 17 +- .../lvgl/src/font/lv_font_montserrat_26.c | 17 +- .../lvgl/src/font/lv_font_montserrat_28.c | 16 +- .../font/lv_font_montserrat_28_compressed.c | 17 +- .../lvgl/src/font/lv_font_montserrat_30.c | 17 +- .../lvgl/src/font/lv_font_montserrat_32.c | 17 +- .../lvgl/src/font/lv_font_montserrat_34.c | 17 +- .../lvgl/src/font/lv_font_montserrat_36.c | 17 +- .../lvgl/src/font/lv_font_montserrat_38.c | 17 +- .../lvgl/src/font/lv_font_montserrat_40.c | 17 +- .../lvgl/src/font/lv_font_montserrat_42.c | 17 +- .../lvgl/src/font/lv_font_montserrat_44.c | 17 +- .../lvgl/src/font/lv_font_montserrat_46.c | 17 +- .../lvgl/src/font/lv_font_montserrat_48.c | 17 +- .../lvgl/src/font/lv_font_montserrat_8.c | 17 +- .../lvgl/src/font/lv_font_simsun_16_cjk.c | 17 +- .../lvgl/src/font/lv_font_unscii_16.c | 19 +- .../lvgl/src/font/lv_font_unscii_8.c | 19 +- .../lvgl/src/font/lv_symbol_def.h | 1 - lib/libesp32_lvgl/lvgl/src/hal/lv_hal.h | 48 - lib/libesp32_lvgl/lvgl/src/hal/lv_hal.mk | 8 - lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.c | 720 -- lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.h | 373 - lib/libesp32_lvgl/lvgl/src/hal/lv_hal_indev.c | 195 - lib/libesp32_lvgl/lvgl/src/hal/lv_hal_indev.h | 240 - lib/libesp32_lvgl/lvgl/src/hal/lv_hal_tick.h | 69 - lib/libesp32_lvgl/lvgl/src/indev/lv_indev.c | 1594 +++ lib/libesp32_lvgl/lvgl/src/indev/lv_indev.h | 324 + .../lvgl/src/indev/lv_indev_private.h | 119 + .../src/{core => indev}/lv_indev_scroll.c | 379 +- .../src/{core => indev}/lv_indev_scroll.h | 12 +- .../src/{extra => }/layouts/flex/lv_flex.c | 299 +- .../src/{extra => }/layouts/flex/lv_flex.h | 63 +- .../src/{extra => }/layouts/grid/lv_grid.c | 489 +- .../lvgl/src/layouts/grid/lv_grid.h | 102 + .../lvgl/src/layouts/lv_layout.c | 79 + .../lvgl/src/layouts/lv_layout.h | 85 + .../lvgl/src/libs/barcode/code128.c | 582 + .../lvgl/src/libs/barcode/code128.h | 47 + .../lvgl/src/libs/barcode/lv_barcode.c | 225 + .../lvgl/src/libs/barcode/lv_barcode.h | 116 + .../src/libs/bin_decoder/lv_bin_decoder.c | 1136 ++ .../src/libs/bin_decoder/lv_bin_decoder.h | 70 + lib/libesp32_lvgl/lvgl/src/libs/bmp/lv_bmp.c | 235 + .../lvgl/src/{extra => }/libs/bmp/lv_bmp.h | 3 +- .../src/{extra => }/libs/ffmpeg/lv_ffmpeg.c | 192 +- .../src/{extra => }/libs/ffmpeg/lv_ffmpeg.h | 10 +- .../src/{extra => }/libs/freetype/arial.ttf | Bin .../lvgl/src/libs/freetype/ftmodule.h | 33 + .../lvgl/src/libs/freetype/ftoption.h | 964 ++ .../lvgl/src/libs/freetype/lv_freetype.c | 453 + .../lvgl/src/libs/freetype/lv_freetype.h | 144 + .../src/libs/freetype/lv_freetype_glyph.c | 188 + .../src/libs/freetype/lv_freetype_image.c | 180 + .../src/libs/freetype/lv_freetype_outline.c | 368 + .../src/libs/freetype/lv_freetype_private.h | 146 + .../lvgl/src/libs/freetype/lv_ftsystem.c | 291 + .../lvgl/src/libs/fsdrv/lv_fs_cbfs.c | 10 + .../src/{extra => }/libs/fsdrv/lv_fs_fatfs.c | 110 +- .../lvgl/src/libs/fsdrv/lv_fs_memfs.c | 215 + .../src/{extra => }/libs/fsdrv/lv_fs_posix.c | 198 +- .../src/{extra => }/libs/fsdrv/lv_fs_stdio.c | 134 +- .../src/{extra => }/libs/fsdrv/lv_fs_win32.c | 102 +- .../src/{extra => }/libs/fsdrv/lv_fsdrv.h | 20 +- .../lvgl/src/{extra => }/libs/gif/gifdec.c | 585 +- .../lvgl/src/{extra => }/libs/gif/gifdec.h | 33 +- .../lvgl/src/libs/gif/gifdec_mve.h | 140 + .../lvgl/src/{extra => }/libs/gif/lv_gif.c | 55 +- lib/libesp32_lvgl/lvgl/src/libs/gif/lv_gif.h | 87 + .../src/libs/libjpeg_turbo/lv_libjpeg_turbo.c | 459 + .../src/libs/libjpeg_turbo/lv_libjpeg_turbo.h | 48 + .../lvgl/src/libs/libpng/lv_libpng.c | 296 + .../png/lv_png.h => libs/libpng/lv_libpng.h} | 18 +- .../lvgl/src/libs/lodepng/lodepng.c | 7053 +++++++++++ .../libs/png => libs/lodepng}/lodepng.h | 1019 +- .../lvgl/src/libs/lodepng/lv_lodepng.c | 282 + .../lodepng/lv_lodepng.h} | 26 +- lib/libesp32_lvgl/lvgl/src/libs/lz4/LICENSE | 24 + lib/libesp32_lvgl/lvgl/src/libs/lz4/lz4.c | 2761 +++++ lib/libesp32_lvgl/lvgl/src/libs/lz4/lz4.h | 877 ++ .../src/{extra => }/libs/qrcode/lv_qrcode.c | 169 +- .../src/{extra => }/libs/qrcode/lv_qrcode.h | 50 +- .../lvgl/src/libs/qrcode/qrcodegen.c | 1113 ++ .../src/{extra => }/libs/qrcode/qrcodegen.h | 96 +- lib/libesp32_lvgl/lvgl/src/libs/rle/lv_rle.c | 99 + lib/libesp32_lvgl/lvgl/src/libs/rle/lv_rle.h | 46 + .../src/{extra => }/libs/rlottie/lv_rlottie.c | 121 +- .../src/{extra => }/libs/rlottie/lv_rlottie.h | 10 +- .../lvgl/src/libs/thorvg/add_lvgl_if.sh | 13 + .../lvgl/src/libs/thorvg/config.h | 15 + .../lvgl/src/libs/thorvg/thorvg.h | 1925 +++ .../lvgl/src/libs/thorvg/thorvg_capi.h | 2334 ++++ .../lvgl/src/libs/thorvg/tvgAnimation.cpp | 125 + .../lvgl/src/libs/thorvg/tvgArray.h | 192 + .../lvgl/src/libs/thorvg/tvgBezier.cpp | 199 + .../lvgl/src/libs/thorvg/tvgBezier.h | 55 + .../lvgl/src/libs/thorvg/tvgCanvas.cpp | 93 + .../lvgl/src/libs/thorvg/tvgCanvas.h | 152 + .../lvgl/src/libs/thorvg/tvgCapi.cpp | 784 ++ .../lvgl/src/libs/thorvg/tvgCommon.h | 95 + .../lvgl/src/libs/thorvg/tvgCompressor.cpp | 481 + .../lvgl/src/libs/thorvg/tvgCompressor.h | 41 + .../lvgl/src/libs/thorvg/tvgFill.cpp | 256 + .../lvgl/src/libs/thorvg/tvgFill.h | 118 + .../lvgl/src/libs/thorvg/tvgFrameModule.h | 53 + .../lvgl/src/libs/thorvg/tvgInitializer.cpp | 183 + .../src/libs/thorvg/tvgIteratorAccessor.h | 49 + .../lvgl/src/libs/thorvg/tvgLoadModule.h | 64 + .../lvgl/src/libs/thorvg/tvgLoader.cpp | 255 + .../lvgl/src/libs/thorvg/tvgLoader.h | 43 + .../lvgl/src/libs/thorvg/tvgMath.cpp | 108 + .../lvgl/src/libs/thorvg/tvgMath.h | 190 + .../lvgl/src/libs/thorvg/tvgPaint.cpp | 437 + .../lvgl/src/libs/thorvg/tvgPaint.h | 222 + .../lvgl/src/libs/thorvg/tvgPicture.cpp | 153 + .../lvgl/src/libs/thorvg/tvgPicture.h | 317 + .../lvgl/src/libs/thorvg/tvgRawLoader.cpp | 101 + .../lvgl/src/libs/thorvg/tvgRawLoader.h | 49 + .../lvgl/src/libs/thorvg/tvgRender.cpp | 75 + .../lvgl/src/libs/thorvg/tvgRender.h | 342 + .../lvgl/src/libs/thorvg/tvgSaveModule.h | 48 + .../lvgl/src/libs/thorvg/tvgSaver.cpp | 147 + .../lvgl/src/libs/thorvg/tvgScene.cpp | 88 + .../lvgl/src/libs/thorvg/tvgScene.h | 255 + .../lvgl/src/libs/thorvg/tvgShape.cpp | 416 + .../lvgl/src/libs/thorvg/tvgShape.h | 396 + .../lvgl/src/libs/thorvg/tvgStr.cpp | 245 + .../lvgl/src/libs/thorvg/tvgStr.h | 43 + .../lvgl/src/libs/thorvg/tvgSvgCssStyle.cpp | 255 + .../lvgl/src/libs/thorvg/tvgSvgCssStyle.h | 40 + .../lvgl/src/libs/thorvg/tvgSvgLoader.cpp | 3759 ++++++ .../lvgl/src/libs/thorvg/tvgSvgLoader.h | 75 + .../lvgl/src/libs/thorvg/tvgSvgLoaderCommon.h | 576 + .../lvgl/src/libs/thorvg/tvgSvgPath.cpp | 561 + .../lvgl/src/libs/thorvg/tvgSvgPath.h | 36 + .../src/libs/thorvg/tvgSvgSceneBuilder.cpp | 890 ++ .../lvgl/src/libs/thorvg/tvgSvgSceneBuilder.h | 36 + .../lvgl/src/libs/thorvg/tvgSvgUtil.cpp | 76 + .../lvgl/src/libs/thorvg/tvgSvgUtil.h | 36 + .../lvgl/src/libs/thorvg/tvgSwCanvas.cpp | 112 + .../lvgl/src/libs/thorvg/tvgSwCommon.h | 580 + .../lvgl/src/libs/thorvg/tvgSwFill.cpp | 785 ++ .../lvgl/src/libs/thorvg/tvgSwImage.cpp | 164 + .../lvgl/src/libs/thorvg/tvgSwMath.cpp | 335 + .../lvgl/src/libs/thorvg/tvgSwMemPool.cpp | 134 + .../lvgl/src/libs/thorvg/tvgSwRaster.cpp | 1957 +++ .../lvgl/src/libs/thorvg/tvgSwRasterAvx.h | 197 + .../lvgl/src/libs/thorvg/tvgSwRasterC.h | 169 + .../lvgl/src/libs/thorvg/tvgSwRasterNeon.h | 144 + .../lvgl/src/libs/thorvg/tvgSwRasterTexmap.h | 1213 ++ .../lvgl/src/libs/thorvg/tvgSwRenderer.cpp | 866 ++ .../lvgl/src/libs/thorvg/tvgSwRenderer.h | 90 + .../lvgl/src/libs/thorvg/tvgSwRle.cpp | 1134 ++ .../lvgl/src/libs/thorvg/tvgSwShape.cpp | 686 ++ .../lvgl/src/libs/thorvg/tvgSwStroke.cpp | 915 ++ .../lvgl/src/libs/thorvg/tvgTaskScheduler.cpp | 80 + .../lvgl/src/libs/thorvg/tvgTaskScheduler.h | 77 + .../lvgl/src/libs/thorvg/tvgXmlParser.cpp | 591 + .../lvgl/src/libs/thorvg/tvgXmlParser.h | 64 + .../lvgl/src/libs/tiny_ttf/lv_tiny_ttf.c | 396 + .../{extra => }/libs/tiny_ttf/lv_tiny_ttf.h | 18 +- .../{extra => }/libs/tiny_ttf/stb_rect_pack.h | 4 - .../libs/tiny_ttf/stb_truetype_htcw.h | 14 - .../lvgl/src/libs/tjpgd/lv_tjpgd.c | 289 + .../lvgl/src/libs/tjpgd/lv_tjpgd.h | 45 + lib/libesp32_lvgl/lvgl/src/libs/tjpgd/tjpgd.c | 1137 ++ lib/libesp32_lvgl/lvgl/src/libs/tjpgd/tjpgd.h | 103 + .../libs/sjpg => libs/tjpgd}/tjpgdcnf.h | 10 +- lib/libesp32_lvgl/lvgl/src/lv_api_map.h | 218 +- lib/libesp32_lvgl/lvgl/src/lv_conf_internal.h | 2387 ++-- lib/libesp32_lvgl/lvgl/src/lv_conf_kconfig.h | 70 +- lib/libesp32_lvgl/lvgl/src/lv_init.c | 416 + lib/libesp32_lvgl/lvgl/src/lv_init.h | 55 + lib/libesp32_lvgl/lvgl/src/lvgl.h | 2 +- .../{font/lv_font_loader.h => lvgl_private.h} | 13 +- .../lvgl/src/misc/cache/_lv_cache_lru_rb.c | 404 + .../lvgl/src/misc/cache/_lv_cache_lru_rb.h | 44 + .../lvgl/src/misc/cache/lv_cache.c | 217 + .../lvgl/src/misc/cache/lv_cache.h | 67 + .../lvgl/src/misc/cache/lv_cache_entry.c | 167 + .../lvgl/src/misc/cache/lv_cache_entry.h | 55 + .../src/misc/cache/lv_cache_entry_private.h | 51 + .../lvgl/src/misc/cache/lv_cache_private.h | 114 + .../lvgl/src/misc/cache/lv_image_cache.c | 59 + .../cache/lv_image_cache.h} | 22 +- lib/libesp32_lvgl/lvgl/src/misc/lv_anim.c | 408 +- lib/libesp32_lvgl/lvgl/src/misc/lv_anim.h | 237 +- .../lvgl/src/misc/lv_anim_timeline.c | 152 +- .../lvgl/src/misc/lv_anim_timeline.h | 19 +- lib/libesp32_lvgl/lvgl/src/misc/lv_area.c | 223 +- lib/libesp32_lvgl/lvgl/src/misc/lv_area.h | 154 +- lib/libesp32_lvgl/lvgl/src/misc/lv_array.c | 172 + lib/libesp32_lvgl/lvgl/src/misc/lv_array.h | 203 + lib/libesp32_lvgl/lvgl/src/misc/lv_assert.h | 16 +- lib/libesp32_lvgl/lvgl/src/misc/lv_async.c | 31 +- lib/libesp32_lvgl/lvgl/src/misc/lv_async.h | 4 +- lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.c | 156 +- lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.h | 13 +- lib/libesp32_lvgl/lvgl/src/misc/lv_color.c | 295 +- lib/libesp32_lvgl/lvgl/src/misc/lv_color.h | 857 +- .../lvgl/src/misc/{lv_gc.c => lv_color_op.c} | 20 +- lib/libesp32_lvgl/lvgl/src/misc/lv_color_op.h | 112 + lib/libesp32_lvgl/lvgl/src/misc/lv_event.c | 193 + lib/libesp32_lvgl/lvgl/src/misc/lv_event.h | 241 + lib/libesp32_lvgl/lvgl/src/misc/lv_fs.c | 136 +- lib/libesp32_lvgl/lvgl/src/misc/lv_fs.h | 74 +- lib/libesp32_lvgl/lvgl/src/misc/lv_gc.h | 97 - lib/libesp32_lvgl/lvgl/src/misc/lv_ll.c | 98 +- lib/libesp32_lvgl/lvgl/src/misc/lv_ll.h | 7 +- lib/libesp32_lvgl/lvgl/src/misc/lv_log.c | 81 +- lib/libesp32_lvgl/lvgl/src/misc/lv_log.h | 21 +- lib/libesp32_lvgl/lvgl/src/misc/lv_lru.c | 51 +- lib/libesp32_lvgl/lvgl/src/misc/lv_lru.h | 15 +- lib/libesp32_lvgl/lvgl/src/misc/lv_math.c | 304 +- lib/libesp32_lvgl/lvgl/src/misc/lv_math.h | 45 +- lib/libesp32_lvgl/lvgl/src/misc/lv_mem.c | 566 - lib/libesp32_lvgl/lvgl/src/misc/lv_mem.h | 243 - lib/libesp32_lvgl/lvgl/src/misc/lv_misc.mk | 26 - lib/libesp32_lvgl/lvgl/src/misc/lv_palette.c | 130 + lib/libesp32_lvgl/lvgl/src/misc/lv_palette.h | 69 + lib/libesp32_lvgl/lvgl/src/misc/lv_printf.h | 98 - lib/libesp32_lvgl/lvgl/src/misc/lv_profiler.h | 52 + .../lvgl/src/misc/lv_profiler_builtin.c | 168 + .../lvgl/src/misc/lv_profiler_builtin.h | 117 + lib/libesp32_lvgl/lvgl/src/misc/lv_rb.c | 556 + lib/libesp32_lvgl/lvgl/src/misc/lv_rb.h | 80 + lib/libesp32_lvgl/lvgl/src/misc/lv_style.c | 480 +- lib/libesp32_lvgl/lvgl/src/misc/lv_style.h | 432 +- .../lvgl/src/misc/lv_style_gen.c | 565 +- .../lvgl/src/misc/lv_style_gen.h | 585 +- .../lvgl/src/misc/{lv_txt.c => lv_text.c} | 278 +- .../lvgl/src/misc/{lv_txt.h => lv_text.h} | 192 +- .../src/misc/{lv_txt_ap.c => lv_text_ap.c} | 48 +- .../src/misc/{lv_txt_ap.h => lv_text_ap.h} | 14 +- lib/libesp32_lvgl/lvgl/src/misc/lv_timer.c | 282 +- lib/libesp32_lvgl/lvgl/src/misc/lv_timer.h | 121 +- lib/libesp32_lvgl/lvgl/src/misc/lv_types.h | 100 +- lib/libesp32_lvgl/lvgl/src/misc/lv_utils.c | 17 - .../lvgl/src/osal/lv_cmsis_rtos2.c | 190 + .../lvgl/src/osal/lv_cmsis_rtos2.h | 53 + lib/libesp32_lvgl/lvgl/src/osal/lv_freertos.c | 423 + lib/libesp32_lvgl/lvgl/src/osal/lv_freertos.h | 84 + lib/libesp32_lvgl/lvgl/src/osal/lv_os.h | 155 + lib/libesp32_lvgl/lvgl/src/osal/lv_os_none.c | 120 + lib/libesp32_lvgl/lvgl/src/osal/lv_os_none.h | 43 + lib/libesp32_lvgl/lvgl/src/osal/lv_pthread.c | 164 + lib/libesp32_lvgl/lvgl/src/osal/lv_pthread.h | 57 + lib/libesp32_lvgl/lvgl/src/osal/lv_rtthread.c | 184 + .../libs/lv_libs.h => osal/lv_rtthread.h} | 35 +- lib/libesp32_lvgl/lvgl/src/osal/lv_windows.c | 215 + lib/libesp32_lvgl/lvgl/src/osal/lv_windows.h | 54 + .../others/file_explorer/lv_file_explorer.c | 704 ++ .../others/file_explorer/lv_file_explorer.h | 191 + .../src/{extra => }/others/fragment/README.md | 0 .../{extra => }/others/fragment/lv_fragment.c | 35 +- .../{extra => }/others/fragment/lv_fragment.h | 20 +- .../others/fragment/lv_fragment_manager.c | 46 +- .../{extra => }/others/gridnav/lv_gridnav.c | 97 +- .../{extra => }/others/gridnav/lv_gridnav.h | 2 +- .../{extra => }/others/ime/lv_ime_pinyin.c | 338 +- .../{extra => }/others/ime/lv_ime_pinyin.h | 18 +- .../{extra => }/others/imgfont/lv_imgfont.c | 57 +- .../{extra => }/others/imgfont/lv_imgfont.h | 8 +- .../src/{extra => }/others/monkey/lv_monkey.c | 48 +- .../src/{extra => }/others/monkey/lv_monkey.h | 8 +- .../lvgl/src/others/observer/lv_observer.c | 709 ++ .../lvgl/src/others/observer/lv_observer.h | 406 + .../lvgl/src/others/snapshot/lv_snapshot.c | 177 + .../lvgl/src/others/snapshot/lv_snapshot.h | 78 + .../lvgl/src/others/sysmon/lv_sysmon.c | 260 + .../lvgl/src/others/sysmon/lv_sysmon.h | 110 + .../lvgl/src/others/vg_lite_tvg/vg_lite.h | 1379 +++ .../src/others/vg_lite_tvg/vg_lite_matrix.c | 162 + .../src/others/vg_lite_tvg/vg_lite_tvg.cpp | 2407 ++++ .../src/stdlib/builtin/lv_mem_core_builtin.c | 263 + .../builtin/lv_sprintf_builtin.c} | 27 +- .../src/stdlib/builtin/lv_string_builtin.c | 223 + .../src/{misc => stdlib/builtin}/lv_tlsf.c | 15 +- .../src/{misc => stdlib/builtin}/lv_tlsf.h | 19 +- .../lvgl/src/stdlib/clib/lv_mem_core_clib.c | 94 + .../lvgl/src/stdlib/clib/lv_sprintf_clib.c | 58 + .../lvgl/src/stdlib/clib/lv_string_clib.c | 93 + lib/libesp32_lvgl/lvgl/src/stdlib/lv_mem.c | 168 + lib/libesp32_lvgl/lvgl/src/stdlib/lv_mem.h | 143 + .../lvgl/src/stdlib/lv_sprintf.h | 47 + lib/libesp32_lvgl/lvgl/src/stdlib/lv_string.h | 125 + .../micropython/lv_mem_core_micropython.c | 95 + .../stdlib/rtthread/lv_mem_core_rtthread.c | 98 + .../src/stdlib/rtthread/lv_sprintf_rtthread.c | 61 + .../src/stdlib/rtthread/lv_string_rtthread.c | 92 + .../src/themes/default/lv_theme_default.c | 1219 ++ .../themes/default/lv_theme_default.h | 11 +- .../lvgl/src/{core => themes}/lv_theme.c | 43 +- .../lvgl/src/{core => themes}/lv_theme.h | 17 +- .../lvgl/src/themes/mono/lv_theme_mono.c | 531 + .../{extra => }/themes/mono/lv_theme_mono.h | 13 +- .../lvgl/src/themes/simple/lv_theme_simple.c | 437 + .../simple/lv_theme_simple.h} | 28 +- .../src/{hal/lv_hal_tick.c => tick/lv_tick.c} | 81 +- lib/libesp32_lvgl/lvgl/src/tick/lv_tick.h | 93 + .../animimage/lv_animimage.c} | 69 +- .../lvgl/src/widgets/animimage/lv_animimage.h | 136 + .../lvgl/src/widgets/{ => arc}/lv_arc.c | 392 +- .../lvgl/src/widgets/arc/lv_arc.h | 273 + .../lvgl/src/widgets/{ => bar}/lv_bar.c | 413 +- .../lvgl/src/widgets/{ => bar}/lv_bar.h | 52 +- .../widgets/{lv_btn.c => button/lv_button.c} | 25 +- .../widgets/{lv_btn.h => button/lv_button.h} | 20 +- .../lv_buttonmatrix.c} | 570 +- .../lv_buttonmatrix.h} | 132 +- .../widgets/calendar/lv_calendar.c | 138 +- .../widgets/calendar/lv_calendar.h | 56 +- .../calendar/lv_calendar_header_arrow.c | 31 +- .../calendar/lv_calendar_header_arrow.h | 6 +- .../calendar/lv_calendar_header_dropdown.c | 66 +- .../calendar/lv_calendar_header_dropdown.h | 19 +- .../lvgl/src/widgets/canvas/lv_canvas.c | 366 + .../lvgl/src/widgets/canvas/lv_canvas.h | 193 + .../lvgl/src/widgets/chart/lv_chart.c | 1332 ++ .../src/{extra => }/widgets/chart/lv_chart.h | 207 +- .../src/widgets/{ => checkbox}/lv_checkbox.c | 155 +- .../src/widgets/{ => checkbox}/lv_checkbox.h | 22 +- .../src/widgets/{ => dropdown}/lv_dropdown.c | 314 +- .../src/widgets/{ => dropdown}/lv_dropdown.h | 24 +- .../lvgl/src/widgets/image/lv_image.c | 817 ++ .../lvgl/src/widgets/image/lv_image.h | 330 + .../src/widgets/imagebutton/lv_imagebutton.c | 347 + .../src/widgets/imagebutton/lv_imagebutton.h | 134 + .../widgets/keyboard/lv_keyboard.c | 255 +- .../widgets/keyboard/lv_keyboard.h | 85 +- .../lvgl/src/widgets/{ => label}/lv_label.c | 623 +- .../lvgl/src/widgets/{ => label}/lv_label.h | 62 +- .../lvgl/src/{extra => }/widgets/led/lv_led.c | 58 +- .../lvgl/src/{extra => }/widgets/led/lv_led.h | 34 +- .../lvgl/src/widgets/{ => line}/lv_line.c | 83 +- .../lvgl/src/widgets/{ => line}/lv_line.h | 15 +- .../src/{extra => }/widgets/list/lv_list.c | 54 +- .../lvgl/src/widgets/list/lv_list.h | 86 + lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.h | 257 - .../lvgl/src/widgets/lv_canvas.c | 836 -- .../lvgl/src/widgets/lv_canvas.h | 280 - lib/libesp32_lvgl/lvgl/src/widgets/lv_img.c | 692 -- lib/libesp32_lvgl/lvgl/src/widgets/lv_img.h | 234 - .../lvgl/src/widgets/lv_slider.c | 447 - .../lvgl/src/widgets/lv_widgets.mk | 20 - .../src/{extra => }/widgets/menu/lv_menu.c | 222 +- .../lvgl/src/widgets/menu/lv_menu.h | 270 + .../lvgl/src/widgets/msgbox/lv_msgbox.c | 278 + .../lvgl/src/widgets/msgbox/lv_msgbox.h | 153 + .../widgets/{ => objx_templ}/lv_objx_templ.c | 9 +- .../widgets/{ => objx_templ}/lv_objx_templ.h | 2 +- .../lvgl/src/widgets/{ => roller}/lv_roller.c | 391 +- .../lvgl/src/widgets/{ => roller}/lv_roller.h | 32 +- .../lvgl/src/widgets/scale/lv_scale.c | 1444 +++ .../lvgl/src/widgets/scale/lv_scale.h | 286 + .../lvgl/src/widgets/slider/lv_slider.c | 490 + .../lvgl/src/widgets/{ => slider}/lv_slider.h | 37 +- .../src/{extra => }/widgets/span/lv_span.c | 325 +- .../lvgl/src/widgets/span/lv_span.h | 261 + .../{extra => }/widgets/spinbox/lv_spinbox.c | 282 +- .../{extra => }/widgets/spinbox/lv_spinbox.h | 76 +- .../{extra => }/widgets/spinner/lv_spinner.c | 74 +- .../{extra => }/widgets/spinner/lv_spinner.h | 17 +- .../lvgl/src/widgets/{ => switch}/lv_switch.c | 93 +- .../lvgl/src/widgets/{ => switch}/lv_switch.h | 10 +- .../lvgl/src/widgets/{ => table}/lv_table.c | 394 +- .../lvgl/src/widgets/{ => table}/lv_table.h | 75 +- .../lvgl/src/widgets/tabview/lv_tabview.c | 344 + .../lvgl/src/widgets/tabview/lv_tabview.h | 123 + .../src/widgets/{ => textarea}/lv_textarea.c | 300 +- .../src/widgets/{ => textarea}/lv_textarea.h | 30 +- .../widgets/tileview/lv_tileview.c | 101 +- .../widgets/tileview/lv_tileview.h | 12 +- .../lvgl/src/{extra => }/widgets/win/lv_win.c | 24 +- .../lvgl/src/{extra => }/widgets/win/lv_win.h | 11 +- .../haspmota_src/haspmota_core/haspmota.be | 106 +- tasmota/berry/haspmota_src/haspmota_demo.tapp | Bin 193476 -> 201952 bytes .../haspmota_demo/lv_wifi_graph.be | 9 +- .../haspmota_src/haspmota_demo/pages.jsonl | 9 +- .../haspmota_widgets/lv_wifi_graph.be | 9 +- tasmota/lvgl_berry/tasmota_logo_64.h | 110 - .../lvgl_berry/tasmota_logo_64_truecolor.h | 277 - .../tasmota_logo_64_truecolor_alpha.h | 277 - tasmota/lvgl_berry/tasmota_lv_conf.h | 834 +- tasmota/my_user_config.h | 23 +- .../xdrv_52_3_berry_lvgl.ino | 60 +- tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino | 201 +- 1503 files changed, 200499 insertions(+), 243205 deletions(-) delete mode 100755 lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/Adafruit_LvGL_Glue.cpp delete mode 100755 lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/Adafruit_LvGL_Glue.h delete mode 100755 lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/README.md delete mode 100755 lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/code-of-conduct.md delete mode 100644 lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/library.json delete mode 100755 lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/library.properties delete mode 100755 lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/license.txt create mode 100644 lib/libesp32_lvgl/LVGL_assets/TASMOTA_Symbol_64.png rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/DSEG7/DSEG-LICENSE.txt (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/DSEG7/DSEG7Classic-Bold.ttf (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/DSEG7/DSEG7Classic-BoldItalic.ttf (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/DSEG7/font_files/seg7_10.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/DSEG7/font_files/seg7_12.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/DSEG7/font_files/seg7_14.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/DSEG7/font_files/seg7_16.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/DSEG7/font_files/seg7_18.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/DSEG7/font_files/seg7_20.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/DSEG7/font_files/seg7_24.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/DSEG7/font_files/seg7_28.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/DSEG7/font_files/seg7_36.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/DSEG7/font_files/seg7_48.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/DSEG7/font_files/seg7_8.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/DSEG7/gen_seg7_fonts.bash (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/pixel_perfect/Berkelium (GEOS)/Berkelium1541.ttf (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/pixel_perfect/Berkelium (GEOS)/Berkelium64.ttf (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/pixel_perfect/Berkelium (GEOS)/FreeLicense.txt (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/pixel_perfect/Berkelium64.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/pixel_perfect/Daniel Linssen/m3x6.ttf (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/pixel_perfect/Daniel Linssen/m5x7.ttf (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/pixel_perfect/PrintChar (Apple II Font)/FreeLicense.txt (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/pixel_perfect/PrintChar (Apple II Font)/PrintChar21.ttf (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/pixel_perfect/PrintChar21.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/pixel_perfect/Shaston (GSOS)/FreeLicense.txt (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/pixel_perfect/Shaston (GSOS)/Shaston320.ttf (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/pixel_perfect/Shaston320.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/pixel_perfect/m3x6.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/pixel_perfect/m5x7.lvfont (100%) rename {tasmota/lvgl_berry => lib/libesp32_lvgl/LVGL_assets}/fonts/pixel_perfect/pages.jsonl (100%) create mode 100644 lib/libesp32_lvgl/LVGL_assets/src/tasmota_logo_64_truecolor_alpha.c delete mode 100644 lib/libesp32_lvgl/freetype/CMakeLists.txt delete mode 100644 lib/libesp32_lvgl/freetype/ChangeLog.20 delete mode 100644 lib/libesp32_lvgl/freetype/ChangeLog.21 delete mode 100644 lib/libesp32_lvgl/freetype/ChangeLog.22 delete mode 100644 lib/libesp32_lvgl/freetype/ChangeLog.23 delete mode 100644 lib/libesp32_lvgl/freetype/ChangeLog.24 delete mode 100644 lib/libesp32_lvgl/freetype/ChangeLog.25 delete mode 100644 lib/libesp32_lvgl/freetype/ChangeLog.26 delete mode 100644 lib/libesp32_lvgl/freetype/ChangeLog.27 delete mode 100644 lib/libesp32_lvgl/freetype/ChangeLog.28 delete mode 100644 lib/libesp32_lvgl/freetype/ChangeLog.29 delete mode 100644 lib/libesp32_lvgl/freetype/Makefile delete mode 100644 lib/libesp32_lvgl/freetype/docs/CHANGES delete mode 100644 lib/libesp32_lvgl/freetype/docs/CMAKE delete mode 100644 lib/libesp32_lvgl/freetype/docs/CUSTOMIZE delete mode 100644 lib/libesp32_lvgl/freetype/docs/DEBUG delete mode 100644 lib/libesp32_lvgl/freetype/docs/DOCGUIDE delete mode 100644 lib/libesp32_lvgl/freetype/docs/FTL.TXT delete mode 100644 lib/libesp32_lvgl/freetype/docs/GPLv2.TXT delete mode 100644 lib/libesp32_lvgl/freetype/docs/INSTALL delete mode 100644 lib/libesp32_lvgl/freetype/docs/INSTALL.ANY delete mode 100644 lib/libesp32_lvgl/freetype/docs/INSTALL.CROSS delete mode 100644 lib/libesp32_lvgl/freetype/docs/INSTALL.GNU delete mode 100644 lib/libesp32_lvgl/freetype/docs/INSTALL.MAC delete mode 100644 lib/libesp32_lvgl/freetype/docs/INSTALL.UNIX delete mode 100644 lib/libesp32_lvgl/freetype/docs/INSTALL.VMS delete mode 100644 lib/libesp32_lvgl/freetype/docs/LICENSE.TXT delete mode 100644 lib/libesp32_lvgl/freetype/docs/MAKEPP delete mode 100644 lib/libesp32_lvgl/freetype/docs/PROBLEMS delete mode 100644 lib/libesp32_lvgl/freetype/docs/README delete mode 100644 lib/libesp32_lvgl/freetype/docs/TODO delete mode 100644 lib/libesp32_lvgl/freetype/docs/VERSIONS.TXT delete mode 100644 lib/libesp32_lvgl/freetype/docs/formats.txt delete mode 100644 lib/libesp32_lvgl/freetype/docs/freetype-config.1 delete mode 100644 lib/libesp32_lvgl/freetype/docs/raster.txt delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/404.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/font-awesome.css delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/material-icons.css delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/FontAwesome.ttf delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/FontAwesome.woff delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/FontAwesome.woff2 delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/MaterialIcons-Regular.ttf delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/MaterialIcons-Regular.woff delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/MaterialIcons-Regular.woff2 delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/images/favicon.png delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/images/icons/bitbucket.1b09e088.svg delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/images/icons/github.f0b8504a.svg delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/images/icons/gitlab.6dd19c00.svg delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/application.c33a9706.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.ar.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.da.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.de.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.du.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.es.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.fi.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.fr.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.hu.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.it.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.ja.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.jp.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.multi.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.nl.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.no.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.pt.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.ro.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.ru.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.stemmer.support.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.sv.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.th.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.tr.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.vi.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/tinyseg.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/wordcut.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/modernizr.86422ebf.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/stylesheets/application-palette.a8b3c06d.css delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/assets/stylesheets/application.adb8469c.css delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-auto_hinter.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-base_interface.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-basic_types.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-bdf_fonts.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-bitmap_handling.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-bzip2.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-cache_subsystem.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-cff_driver.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-cid_fonts.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-color_management.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-computations.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-error_code_values.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-error_enumerations.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-font_formats.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-gasp_table.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-glyph_management.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-glyph_stroker.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-glyph_variants.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-gx_validation.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-gzip.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-header_file_macros.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-header_inclusion.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-incremental.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-index.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-layer_management.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-lcd_rendering.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-list_processing.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-lzw.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-mac_specific.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-module_management.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-multiple_masters.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-ot_validation.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-outline_processing.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-parameter_tags.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-pcf_driver.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-pfr_fonts.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-properties.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-quick_advance.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-raster.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-sfnt_names.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-sizes_management.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-system_interface.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-t1_cid_driver.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-truetype_engine.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-truetype_tables.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-tt_driver.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-type1_tables.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-user_allocation.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-version.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/ft2-winfnt_fonts.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/images/favico.ico delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/index.html delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/javascripts/extra.js delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/search/search_index.json delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/sitemap.xml delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/sitemap.xml.gz delete mode 100644 lib/libesp32_lvgl/freetype/docs/reference/stylesheets/extra.css delete mode 100644 lib/libesp32_lvgl/freetype/docs/release create mode 100644 lib/libesp32_lvgl/freetype/include/dlg/dlg.h create mode 100644 lib/libesp32_lvgl/freetype/include/dlg/output.h create mode 100644 lib/libesp32_lvgl/freetype/include/freetype/ftlogging.h create mode 100644 lib/libesp32_lvgl/freetype/include/freetype/internal/ftmmtypes.h create mode 100644 lib/libesp32_lvgl/freetype/include/freetype/internal/svginterface.h create mode 100644 lib/libesp32_lvgl/freetype/include/freetype/otsvg.h delete mode 100644 lib/libesp32_lvgl/freetype/meson.build delete mode 100644 lib/libesp32_lvgl/freetype/meson_options.txt delete mode 100644 lib/libesp32_lvgl/freetype/modules.cfg delete mode 100644 lib/libesp32_lvgl/freetype/src/autofit/afangles.c delete mode 100644 lib/libesp32_lvgl/freetype/src/autofit/afangles.h delete mode 100644 lib/libesp32_lvgl/freetype/src/autofit/aflatin2.c delete mode 100644 lib/libesp32_lvgl/freetype/src/autofit/aflatin2.h delete mode 100644 lib/libesp32_lvgl/freetype/src/autofit/afwarp.c delete mode 100644 lib/libesp32_lvgl/freetype/src/autofit/afwarp.h delete mode 100644 lib/libesp32_lvgl/freetype/src/autofit/afwrtsys.h create mode 100644 lib/libesp32_lvgl/freetype/src/autofit/afws-decl.h create mode 100644 lib/libesp32_lvgl/freetype/src/autofit/afws-iter.h create mode 100644 lib/libesp32_lvgl/freetype/src/autofit/ft-hb.c create mode 100644 lib/libesp32_lvgl/freetype/src/autofit/ft-hb.h create mode 100644 lib/libesp32_lvgl/freetype/src/dlg/dlg.c create mode 100644 lib/libesp32_lvgl/freetype/src/dlg/dlgwrap.c create mode 100644 lib/libesp32_lvgl/freetype/src/dlg/rules.mk create mode 100644 lib/libesp32_lvgl/freetype/src/gzip/README.freetype create mode 100644 lib/libesp32_lvgl/freetype/src/gzip/crc32.c create mode 100644 lib/libesp32_lvgl/freetype/src/gzip/crc32.h create mode 100644 lib/libesp32_lvgl/freetype/src/gzip/gzguts.h delete mode 100644 lib/libesp32_lvgl/freetype/src/gzip/infblock.c delete mode 100644 lib/libesp32_lvgl/freetype/src/gzip/infblock.h delete mode 100644 lib/libesp32_lvgl/freetype/src/gzip/infcodes.c delete mode 100644 lib/libesp32_lvgl/freetype/src/gzip/infcodes.h create mode 100644 lib/libesp32_lvgl/freetype/src/gzip/inffast.c create mode 100644 lib/libesp32_lvgl/freetype/src/gzip/inffast.h create mode 100644 lib/libesp32_lvgl/freetype/src/gzip/inflate.h delete mode 100644 lib/libesp32_lvgl/freetype/src/gzip/infutil.c delete mode 100644 lib/libesp32_lvgl/freetype/src/gzip/infutil.h create mode 100644 lib/libesp32_lvgl/freetype/src/gzip/patches/freetype-zlib.diff create mode 100644 lib/libesp32_lvgl/freetype/src/sdf/ftbsdf.c create mode 100644 lib/libesp32_lvgl/freetype/src/sdf/ftsdf.c create mode 100644 lib/libesp32_lvgl/freetype/src/sdf/ftsdf.h create mode 100644 lib/libesp32_lvgl/freetype/src/sdf/ftsdfcommon.c create mode 100644 lib/libesp32_lvgl/freetype/src/sdf/ftsdfcommon.h create mode 100644 lib/libesp32_lvgl/freetype/src/sdf/ftsdferrs.h create mode 100644 lib/libesp32_lvgl/freetype/src/sdf/ftsdfrend.c create mode 100644 lib/libesp32_lvgl/freetype/src/sdf/ftsdfrend.h create mode 100644 lib/libesp32_lvgl/freetype/src/sdf/module.mk create mode 100644 lib/libesp32_lvgl/freetype/src/sdf/rules.mk create mode 100644 lib/libesp32_lvgl/freetype/src/sdf/sdf.c create mode 100644 lib/libesp32_lvgl/freetype/src/sfnt/ttsvg.c create mode 100644 lib/libesp32_lvgl/freetype/src/sfnt/ttsvg.h create mode 100644 lib/libesp32_lvgl/freetype/src/svg/ftsvg.c create mode 100644 lib/libesp32_lvgl/freetype/src/svg/ftsvg.h create mode 100644 lib/libesp32_lvgl/freetype/src/svg/module.mk create mode 100644 lib/libesp32_lvgl/freetype/src/svg/rules.mk create mode 100644 lib/libesp32_lvgl/freetype/src/svg/svg.c create mode 100644 lib/libesp32_lvgl/freetype/src/svg/svgtypes.h create mode 100644 lib/libesp32_lvgl/freetype/src/tools/afblue.pl create mode 100644 lib/libesp32_lvgl/freetype/src/tools/apinames.c create mode 100755 lib/libesp32_lvgl/freetype/src/tools/chktrcmp.py create mode 100644 lib/libesp32_lvgl/freetype/src/tools/cordic.py create mode 100644 lib/libesp32_lvgl/freetype/src/tools/ftrandom/Makefile create mode 100644 lib/libesp32_lvgl/freetype/src/tools/ftrandom/README create mode 100644 lib/libesp32_lvgl/freetype/src/tools/ftrandom/ftrandom.c create mode 100644 lib/libesp32_lvgl/freetype/src/tools/glnames.py create mode 100755 lib/libesp32_lvgl/freetype/src/tools/make_distribution_archives.py create mode 100644 lib/libesp32_lvgl/freetype/src/tools/no-copyright create mode 100644 lib/libesp32_lvgl/freetype/src/tools/test_afm.c create mode 100644 lib/libesp32_lvgl/freetype/src/tools/test_bbox.c create mode 100644 lib/libesp32_lvgl/freetype/src/tools/test_trig.c create mode 100755 lib/libesp32_lvgl/freetype/src/tools/update-copyright create mode 100755 lib/libesp32_lvgl/freetype/src/tools/update-copyright-year create mode 100644 lib/libesp32_lvgl/freetype/src/tools/vms_shorten_symbol.c delete mode 100644 lib/libesp32_lvgl/freetype/src/truetype/ttsubpix.c delete mode 100644 lib/libesp32_lvgl/freetype/src/truetype/ttsubpix.h create mode 100644 lib/libesp32_lvgl/lv_binding_berry/generate/LVGL_API_Reference.md create mode 100644 lib/libesp32_lvgl/lv_binding_berry/src/lv_mem_core_berry.c delete mode 100644 lib/libesp32_lvgl/lvgl/README_pt_BR.md delete mode 100644 lib/libesp32_lvgl/lvgl/README_zh.md delete mode 100644 lib/libesp32_lvgl/lvgl/src/core/lv_core.mk delete mode 100644 lib/libesp32_lvgl/lvgl/src/core/lv_disp.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/core/lv_disp.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/core/lv_event.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/core/lv_event.h create mode 100644 lib/libesp32_lvgl/lvgl/src/core/lv_global.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/core/lv_indev.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/core/lv_indev.h create mode 100644 lib/libesp32_lvgl/lvgl/src/core/lv_obj_event.c create mode 100644 lib/libesp32_lvgl/lvgl/src/core/lv_obj_event.h create mode 100644 lib/libesp32_lvgl/lvgl/src/core/lv_obj_id_builtin.c create mode 100644 lib/libesp32_lvgl/lvgl/src/core/lv_obj_property.c create mode 100644 lib/libesp32_lvgl/lvgl/src/core/lv_obj_property.h create mode 100644 lib/libesp32_lvgl/lvgl/src/display/lv_display.c create mode 100644 lib/libesp32_lvgl/lvgl/src/display/lv_display.h create mode 100644 lib/libesp32_lvgl/lvgl/src/display/lv_display_private.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_draw_arm2d.mk delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_gpu_arm2d.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_gpu_arm2d.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_draw.mk create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_draw_buf.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_draw_buf.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_draw_image.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_draw_image.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_draw_layer.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_draw_layer.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_draw_transform.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_draw_transform.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_draw_vector.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_draw_vector.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_image_buf.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_image_buf.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_image_decoder.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_image_decoder.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_img_cache.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_img_cache.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/lv_draw_nxp.mk create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_buf_pxp.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_nxp_pxp.mk delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_fill.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_img.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_layer.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_cfg.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_cfg.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_osa.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_osa.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_utils.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_utils.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_buf_vglite.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_nxp_vglite.mk delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_border.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_fill.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_img.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_label.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_layer.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_line.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_triangle.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_matrix.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_matrix.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_path.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_path.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_arc.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_border.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_fill.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_image.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_label.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_line.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_mask_rectangle.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_triangle.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_utils.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_utils.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_draw_renesas.mk delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_gpu_d2_draw_label.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_gpu_d2_ra6m3.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_gpu_d2_ra6m3.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/README.md delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.mk delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_arc.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_bg.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_img.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_img.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_label.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_layer.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_layer.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_line.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_mask.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_mask.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_polygon.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_priv.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_rect.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_rect.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_utils.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_utils.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_draw_stm32_dma2d.mk delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/arm2d/lv_draw_sw_arm2d.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/arm2d/lv_draw_sw_helium.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/blend/arm2d/lv_blend_arm2d.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/blend/arm2d/lv_blend_helium.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_argb8888.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_argb8888.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb565.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb565.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb888.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb888.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/blend/neon/lv_blend_neon.S create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/blend/neon/lv_blend_neon.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.mk delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_blend.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_blend.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_border.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_box_shadow.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_dither.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_dither.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_fill.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_layer.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_mask.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_mask.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_mask_rect.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_polygon.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_rect.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_triangle.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_vector.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_draw_swm341_dma2d.mk delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_buf_vg_lite.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_arc.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_border.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_box_shadow.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_fill.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_img.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_label.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_layer.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_line.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_mask_rect.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_triangle.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_type.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_vector.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_decoder.c rename lib/libesp32_lvgl/lvgl/src/{extra/lv_extra.h => draw/vg_lite/lv_vg_lite_decoder.h} (59%) create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_math.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_math.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_path.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_path.h create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_utils.c create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_utils.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/README.md create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/drm/lv_linux_drm.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/drm/lv_linux_drm.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/fb/lv_linux_fbdev.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/fb/lv_linux_fbdev.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/ili9341/lv_ili9341.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/ili9341/lv_ili9341.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/lcd/lv_lcd_generic_mipi.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/lcd/lv_lcd_generic_mipi.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/st7735/lv_st7735.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/st7735/lv_st7735.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/st7789/lv_st7789.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/st7789/lv_st7789.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/st7796/lv_st7796.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/st7796/lv_st7796.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/tft_espi/lv_tft_espi.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/display/tft_espi/lv_tft_espi.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/evdev/lv_evdev.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/evdev/lv_evdev.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/lv_drivers.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_cache.c rename lib/libesp32_lvgl/lvgl/src/{extra/libs/sjpg/lv_sjpg.h => drivers/nuttx/lv_nuttx_cache.h} (72%) create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_entry.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_entry.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_fbdev.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_fbdev.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_lcd.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_lcd.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_libuv.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_libuv.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_profiler.c rename lib/libesp32_lvgl/lvgl/src/{extra/themes/lv_themes.h => drivers/nuttx/lv_nuttx_profiler.h} (69%) create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_touchscreen.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_touchscreen.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_keyboard.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_keyboard.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mouse.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mouse.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mousewheel.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mousewheel.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_window.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_window.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_context.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_context.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_display.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_display.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_input.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_input.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/x11/lv_x11.h create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/x11/lv_x11_display.c create mode 100644 lib/libesp32_lvgl/lvgl/src/drivers/x11/lv_x11_input.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/README.md delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/bmp/lv_bmp.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_littlefs.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/gif/lv_gif.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/lv_sjpg.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgd.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgd.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/tiny_ttf/lv_tiny_ttf.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/lv_extra.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/lv_extra.mk delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/others/lv_others.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/others/msg/lv_msg.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/others/msg/lv_msg.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/animimg/lv_animimg.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/lv_widgets.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/menu/lv_menu.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.h delete mode 100755 lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/font/korean.ttf rename lib/libesp32_lvgl/lvgl/src/font/{lv_font_loader.c => lv_binfont_loader.c} (78%) create mode 100644 lib/libesp32_lvgl/lvgl/src/font/lv_binfont_loader.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/font/lv_font.mk delete mode 100644 lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_12_subpx.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/hal/lv_hal.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/hal/lv_hal.mk delete mode 100644 lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/hal/lv_hal_indev.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/hal/lv_hal_indev.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/hal/lv_hal_tick.h create mode 100644 lib/libesp32_lvgl/lvgl/src/indev/lv_indev.c create mode 100644 lib/libesp32_lvgl/lvgl/src/indev/lv_indev.h create mode 100644 lib/libesp32_lvgl/lvgl/src/indev/lv_indev_private.h rename lib/libesp32_lvgl/lvgl/src/{core => indev}/lv_indev_scroll.c (56%) rename lib/libesp32_lvgl/lvgl/src/{core => indev}/lv_indev_scroll.h (78%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/layouts/flex/lv_flex.c (61%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/layouts/flex/lv_flex.h (50%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/layouts/grid/lv_grid.c (53%) create mode 100644 lib/libesp32_lvgl/lvgl/src/layouts/grid/lv_grid.h create mode 100644 lib/libesp32_lvgl/lvgl/src/layouts/lv_layout.c create mode 100644 lib/libesp32_lvgl/lvgl/src/layouts/lv_layout.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/barcode/code128.c create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/barcode/code128.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/barcode/lv_barcode.c create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/barcode/lv_barcode.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/bin_decoder/lv_bin_decoder.c create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/bin_decoder/lv_bin_decoder.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/bmp/lv_bmp.c rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/bmp/lv_bmp.h (90%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/ffmpeg/lv_ffmpeg.c (83%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/ffmpeg/lv_ffmpeg.h (88%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/freetype/arial.ttf (100%) create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/freetype/ftmodule.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/freetype/ftoption.h create mode 100755 lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype.c create mode 100755 lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_glyph.c create mode 100755 lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_image.c create mode 100755 lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_outline.c create mode 100755 lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_private.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_ftsystem.c create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_cbfs.c rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/fsdrv/lv_fs_fatfs.c (68%) create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_memfs.c rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/fsdrv/lv_fs_posix.c (56%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/fsdrv/lv_fs_stdio.c (67%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/fsdrv/lv_fs_win32.c (81%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/fsdrv/lv_fsdrv.h (70%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/gif/gifdec.c (53%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/gif/gifdec.h (51%) create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/gif/gifdec_mve.h rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/gif/lv_gif.c (74%) create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/gif/lv_gif.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/libjpeg_turbo/lv_libjpeg_turbo.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/libpng/lv_libpng.c rename lib/libesp32_lvgl/lvgl/src/{extra/libs/png/lv_png.h => libs/libpng/lv_libpng.h} (68%) create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/lodepng/lodepng.c rename lib/libesp32_lvgl/lvgl/src/{extra/libs/png => libs/lodepng}/lodepng.h (65%) create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/lodepng/lv_lodepng.c rename lib/libesp32_lvgl/lvgl/src/{draw/sdl/lv_draw_sdl_stack_blur.h => libs/lodepng/lv_lodepng.h} (58%) create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/lz4/LICENSE create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/lz4/lz4.c create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/lz4/lz4.h rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/qrcode/lv_qrcode.c (52%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/qrcode/lv_qrcode.h (51%) create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/qrcode/qrcodegen.c rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/qrcode/qrcodegen.h (82%) create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/rle/lv_rle.c create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/rle/lv_rle.h rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/rlottie/lv_rlottie.c (61%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/rlottie/lv_rlottie.h (82%) create mode 100755 lib/libesp32_lvgl/lvgl/src/libs/thorvg/add_lvgl_if.sh create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/config.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/thorvg.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/thorvg_capi.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgAnimation.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgArray.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgBezier.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgBezier.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCanvas.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCanvas.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCapi.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCommon.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCompressor.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCompressor.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgFill.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgFill.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgFrameModule.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgInitializer.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgIteratorAccessor.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgLoadModule.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgLoader.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgLoader.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgMath.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgMath.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPaint.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPaint.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPicture.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPicture.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRawLoader.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRawLoader.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRender.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRender.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSaveModule.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSaver.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgScene.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgScene.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgShape.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgShape.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgStr.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgStr.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgCssStyle.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgCssStyle.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgLoader.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgLoader.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgLoaderCommon.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgPath.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgPath.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgSceneBuilder.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgSceneBuilder.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgUtil.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgUtil.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwCanvas.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwCommon.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwFill.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwImage.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwMath.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwMemPool.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRaster.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterAvx.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterC.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterNeon.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterTexmap.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRenderer.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRenderer.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRle.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwShape.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwStroke.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgTaskScheduler.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgTaskScheduler.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgXmlParser.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgXmlParser.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/tiny_ttf/lv_tiny_ttf.c rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/tiny_ttf/lv_tiny_ttf.h (75%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/tiny_ttf/stb_rect_pack.h (99%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/libs/tiny_ttf/stb_truetype_htcw.h (99%) create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/tjpgd/lv_tjpgd.c create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/tjpgd/lv_tjpgd.h create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/tjpgd/tjpgd.c create mode 100644 lib/libesp32_lvgl/lvgl/src/libs/tjpgd/tjpgd.h rename lib/libesp32_lvgl/lvgl/src/{extra/libs/sjpg => libs/tjpgd}/tjpgdcnf.h (84%) create mode 100644 lib/libesp32_lvgl/lvgl/src/lv_init.c create mode 100644 lib/libesp32_lvgl/lvgl/src/lv_init.h rename lib/libesp32_lvgl/lvgl/src/{font/lv_font_loader.h => lvgl_private.h} (69%) create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/cache/_lv_cache_lru_rb.c create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/cache/_lv_cache_lru_rb.h create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache.c create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache.h create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_entry.c create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_entry.h create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_entry_private.h create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_private.h create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/cache/lv_image_cache.c rename lib/libesp32_lvgl/lvgl/src/{extra/layouts/lv_layouts.h => misc/cache/lv_image_cache.h} (60%) create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_array.c create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_array.h rename lib/libesp32_lvgl/lvgl/src/misc/{lv_gc.c => lv_color_op.c} (56%) create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_color_op.h create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_event.c create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_event.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_gc.h mode change 100644 => 100755 lib/libesp32_lvgl/lvgl/src/misc/lv_lru.c mode change 100644 => 100755 lib/libesp32_lvgl/lvgl/src/misc/lv_lru.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_mem.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_mem.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_misc.mk create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_palette.c create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_palette.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_printf.h create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_profiler.h create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_profiler_builtin.c create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_profiler_builtin.h create mode 100755 lib/libesp32_lvgl/lvgl/src/misc/lv_rb.c create mode 100755 lib/libesp32_lvgl/lvgl/src/misc/lv_rb.h rename lib/libesp32_lvgl/lvgl/src/misc/{lv_txt.c => lv_text.c} (67%) rename lib/libesp32_lvgl/lvgl/src/misc/{lv_txt.h => lv_text.h} (59%) rename lib/libesp32_lvgl/lvgl/src/misc/{lv_txt_ap.c => lv_text_ap.c} (87%) rename lib/libesp32_lvgl/lvgl/src/misc/{lv_txt_ap.h => lv_text_ap.h} (76%) create mode 100644 lib/libesp32_lvgl/lvgl/src/osal/lv_cmsis_rtos2.c create mode 100644 lib/libesp32_lvgl/lvgl/src/osal/lv_cmsis_rtos2.h create mode 100644 lib/libesp32_lvgl/lvgl/src/osal/lv_freertos.c create mode 100644 lib/libesp32_lvgl/lvgl/src/osal/lv_freertos.h create mode 100644 lib/libesp32_lvgl/lvgl/src/osal/lv_os.h create mode 100644 lib/libesp32_lvgl/lvgl/src/osal/lv_os_none.c create mode 100644 lib/libesp32_lvgl/lvgl/src/osal/lv_os_none.h create mode 100644 lib/libesp32_lvgl/lvgl/src/osal/lv_pthread.c create mode 100644 lib/libesp32_lvgl/lvgl/src/osal/lv_pthread.h create mode 100644 lib/libesp32_lvgl/lvgl/src/osal/lv_rtthread.c rename lib/libesp32_lvgl/lvgl/src/{extra/libs/lv_libs.h => osal/lv_rtthread.h} (53%) create mode 100644 lib/libesp32_lvgl/lvgl/src/osal/lv_windows.c create mode 100644 lib/libesp32_lvgl/lvgl/src/osal/lv_windows.h create mode 100644 lib/libesp32_lvgl/lvgl/src/others/file_explorer/lv_file_explorer.c create mode 100644 lib/libesp32_lvgl/lvgl/src/others/file_explorer/lv_file_explorer.h rename lib/libesp32_lvgl/lvgl/src/{extra => }/others/fragment/README.md (100%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/others/fragment/lv_fragment.c (78%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/others/fragment/lv_fragment.h (94%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/others/fragment/lv_fragment_manager.c (87%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/others/gridnav/lv_gridnav.c (80%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/others/gridnav/lv_gridnav.h (98%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/others/ime/lv_ime_pinyin.c (77%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/others/ime/lv_ime_pinyin.h (89%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/others/imgfont/lv_imgfont.c (62%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/others/imgfont/lv_imgfont.h (72%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/others/monkey/lv_monkey.c (78%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/others/monkey/lv_monkey.h (95%) create mode 100644 lib/libesp32_lvgl/lvgl/src/others/observer/lv_observer.c create mode 100644 lib/libesp32_lvgl/lvgl/src/others/observer/lv_observer.h create mode 100644 lib/libesp32_lvgl/lvgl/src/others/snapshot/lv_snapshot.c create mode 100644 lib/libesp32_lvgl/lvgl/src/others/snapshot/lv_snapshot.h create mode 100644 lib/libesp32_lvgl/lvgl/src/others/sysmon/lv_sysmon.c create mode 100644 lib/libesp32_lvgl/lvgl/src/others/sysmon/lv_sysmon.h create mode 100644 lib/libesp32_lvgl/lvgl/src/others/vg_lite_tvg/vg_lite.h create mode 100644 lib/libesp32_lvgl/lvgl/src/others/vg_lite_tvg/vg_lite_matrix.c create mode 100644 lib/libesp32_lvgl/lvgl/src/others/vg_lite_tvg/vg_lite_tvg.cpp create mode 100644 lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_mem_core_builtin.c rename lib/libesp32_lvgl/lvgl/src/{misc/lv_printf.c => stdlib/builtin/lv_sprintf_builtin.c} (97%) create mode 100644 lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_string_builtin.c rename lib/libesp32_lvgl/lvgl/src/{misc => stdlib/builtin}/lv_tlsf.c (99%) rename lib/libesp32_lvgl/lvgl/src/{misc => stdlib/builtin}/lv_tlsf.h (91%) create mode 100644 lib/libesp32_lvgl/lvgl/src/stdlib/clib/lv_mem_core_clib.c create mode 100644 lib/libesp32_lvgl/lvgl/src/stdlib/clib/lv_sprintf_clib.c create mode 100644 lib/libesp32_lvgl/lvgl/src/stdlib/clib/lv_string_clib.c create mode 100644 lib/libesp32_lvgl/lvgl/src/stdlib/lv_mem.c create mode 100644 lib/libesp32_lvgl/lvgl/src/stdlib/lv_mem.h create mode 100644 lib/libesp32_lvgl/lvgl/src/stdlib/lv_sprintf.h create mode 100644 lib/libesp32_lvgl/lvgl/src/stdlib/lv_string.h create mode 100644 lib/libesp32_lvgl/lvgl/src/stdlib/micropython/lv_mem_core_micropython.c create mode 100644 lib/libesp32_lvgl/lvgl/src/stdlib/rtthread/lv_mem_core_rtthread.c create mode 100644 lib/libesp32_lvgl/lvgl/src/stdlib/rtthread/lv_sprintf_rtthread.c create mode 100644 lib/libesp32_lvgl/lvgl/src/stdlib/rtthread/lv_string_rtthread.c create mode 100644 lib/libesp32_lvgl/lvgl/src/themes/default/lv_theme_default.c rename lib/libesp32_lvgl/lvgl/src/{extra => }/themes/default/lv_theme_default.h (81%) rename lib/libesp32_lvgl/lvgl/src/{core => themes}/lv_theme.c (71%) rename lib/libesp32_lvgl/lvgl/src/{core => themes}/lv_theme.h (89%) create mode 100644 lib/libesp32_lvgl/lvgl/src/themes/mono/lv_theme_mono.c rename lib/libesp32_lvgl/lvgl/src/{extra => }/themes/mono/lv_theme_mono.h (77%) create mode 100644 lib/libesp32_lvgl/lvgl/src/themes/simple/lv_theme_simple.c rename lib/libesp32_lvgl/lvgl/src/{extra/themes/basic/lv_theme_basic.h => themes/simple/lv_theme_simple.h} (57%) rename lib/libesp32_lvgl/lvgl/src/{hal/lv_hal_tick.c => tick/lv_tick.c} (54%) create mode 100644 lib/libesp32_lvgl/lvgl/src/tick/lv_tick.h rename lib/libesp32_lvgl/lvgl/src/{extra/widgets/animimg/lv_animimg.c => widgets/animimage/lv_animimage.c} (65%) create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/animimage/lv_animimage.h rename lib/libesp32_lvgl/lvgl/src/widgets/{ => arc}/lv_arc.c (69%) create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/arc/lv_arc.h rename lib/libesp32_lvgl/lvgl/src/widgets/{ => bar}/lv_bar.c (57%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => bar}/lv_bar.h (72%) rename lib/libesp32_lvgl/lvgl/src/widgets/{lv_btn.c => button/lv_button.c} (65%) rename lib/libesp32_lvgl/lvgl/src/widgets/{lv_btn.h => button/lv_button.h} (67%) rename lib/libesp32_lvgl/lvgl/src/widgets/{lv_btnmatrix.c => buttonmatrix/lv_buttonmatrix.c} (57%) rename lib/libesp32_lvgl/lvgl/src/widgets/{lv_btnmatrix.h => buttonmatrix/lv_buttonmatrix.h} (50%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/calendar/lv_calendar.c (68%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/calendar/lv_calendar.h (64%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/calendar/lv_calendar_header_arrow.c (82%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/calendar/lv_calendar_header_arrow.h (83%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/calendar/lv_calendar_header_dropdown.c (64%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/calendar/lv_calendar_header_dropdown.h (52%) create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/canvas/lv_canvas.c create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/canvas/lv_canvas.h create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/chart/lv_chart.c rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/chart/lv_chart.h (70%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => checkbox}/lv_checkbox.c (53%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => checkbox}/lv_checkbox.h (76%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => dropdown}/lv_dropdown.c (76%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => dropdown}/lv_dropdown.h (91%) create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/image/lv_image.c create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/image/lv_image.h create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/imagebutton/lv_imagebutton.c create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/imagebutton/lv_imagebutton.h rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/keyboard/lv_keyboard.c (52%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/keyboard/lv_keyboard.h (56%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => label}/lv_label.c (67%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => label}/lv_label.h (84%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/led/lv_led.c (78%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/led/lv_led.h (65%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => line}/lv_line.c (64%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => line}/lv_line.h (80%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/list/lv_list.c (61%) create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/list/lv_list.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/lv_img.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/lv_img.h delete mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.c delete mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/lv_widgets.mk rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/menu/lv_menu.c (78%) create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/menu/lv_menu.h create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/msgbox/lv_msgbox.c create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/msgbox/lv_msgbox.h rename lib/libesp32_lvgl/lvgl/src/widgets/{ => objx_templ}/lv_objx_templ.c (95%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => objx_templ}/lv_objx_templ.h (95%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => roller}/lv_roller.c (64%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => roller}/lv_roller.h (77%) create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/scale/lv_scale.c create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/scale/lv_scale.h create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/slider/lv_slider.c rename lib/libesp32_lvgl/lvgl/src/widgets/{ => slider}/lv_slider.h (89%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/span/lv_span.c (73%) create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/span/lv_span.h rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/spinbox/lv_spinbox.c (57%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/spinbox/lv_spinbox.h (58%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/spinner/lv_spinner.c (58%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/spinner/lv_spinner.h (56%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => switch}/lv_switch.c (71%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => switch}/lv_switch.h (75%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => table}/lv_table.c (68%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => table}/lv_table.h (76%) create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/tabview/lv_tabview.c create mode 100644 lib/libesp32_lvgl/lvgl/src/widgets/tabview/lv_tabview.h rename lib/libesp32_lvgl/lvgl/src/widgets/{ => textarea}/lv_textarea.c (80%) rename lib/libesp32_lvgl/lvgl/src/widgets/{ => textarea}/lv_textarea.h (92%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/tileview/lv_tileview.c (57%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/tileview/lv_tileview.h (71%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/win/lv_win.c (81%) rename lib/libesp32_lvgl/lvgl/src/{extra => }/widgets/win/lv_win.h (76%) delete mode 100644 tasmota/lvgl_berry/tasmota_logo_64.h delete mode 100644 tasmota/lvgl_berry/tasmota_logo_64_truecolor.h delete mode 100644 tasmota/lvgl_berry/tasmota_logo_64_truecolor_alpha.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f2a557d6..b94263100 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. ### Breaking Changed - Matter aggregator relocated to endpoint 1 for Google compatibility, may break existing associations (#20654) +- LVGL library updated to v9.0.0, some small breaking changes in C, none in HASPmota ### Changed - Library OneWire-Stickbreaker by TasmotaOneWire supporting Shelly Plus Add-On (#20580) diff --git a/lib/libesp32/berry_tasmota/include/be_ctypes.h b/lib/libesp32/berry_tasmota/include/be_ctypes.h index abaffa8c3..da97971bd 100644 --- a/lib/libesp32/berry_tasmota/include/be_ctypes.h +++ b/lib/libesp32/berry_tasmota/include/be_ctypes.h @@ -8,14 +8,17 @@ enum { ctypes_i32 = 14, + ctypes_i24 = 13, ctypes_i16 = 12, ctypes_i8 = 11, ctypes_u32 = 4, + ctypes_u24 = 3, ctypes_u16 = 2, ctypes_u8 = 1, // big endian ctypes_be_i32 = -14, + ctypes_be_i24 = -13, ctypes_be_i16 = -12, ctypes_be_i8 = -11, ctypes_be_u32 = -4, diff --git a/lib/libesp32/berry_tasmota/src/be_ctypes.c b/lib/libesp32/berry_tasmota/src/be_ctypes.c index d92ffb183..66b119ed2 100644 --- a/lib/libesp32/berry_tasmota/src/be_ctypes.c +++ b/lib/libesp32/berry_tasmota/src/be_ctypes.c @@ -36,14 +36,17 @@ int32_t bin_search_ctypes(const char * needle, const void * table, size_t elt_si enum { ctypes_i32 = 14, + ctypes_i24 = 13, ctypes_i16 = 12, ctypes_i8 = 11, ctypes_u32 = 4, + ctypes_u24 = 3, ctypes_u16 = 2, ctypes_u8 = 1, // big endian ctypes_be_i32 = -14, + ctypes_be_i24 = -13, ctypes_be_i16 = -12, ctypes_be_i8 = -11, ctypes_be_u32 = -4, diff --git a/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c b/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c index eaa5d97b1..10033d3e2 100644 --- a/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c +++ b/lib/libesp32/berry_tasmota/src/be_lv_haspmota.c @@ -9,8 +9,8 @@ extern const bclass be_class_lv_anim; extern const bclass be_class_lv_arc; extern const bclass be_class_lv_bar; -extern const bclass be_class_lv_btn; -extern const bclass be_class_lv_btnmatrix; +extern const bclass be_class_lv_button; +extern const bclass be_class_lv_buttonmatrix; extern const bclass be_class_lv_canvas; extern const bclass be_class_lv_chart; extern const bclass be_class_lv_checkbox; @@ -20,8 +20,8 @@ extern const bclass be_class_lv_disp; extern const bclass be_class_lv_dropdown; extern const bclass be_class_lv_font; extern const bclass be_class_lv_group; -extern const bclass be_class_lv_img; -extern const bclass be_class_lv_imgbtn; +extern const bclass be_class_lv_image; +extern const bclass be_class_lv_imagebutton; extern const bclass be_class_lv_indev; extern const bclass be_class_lv_label; extern const bclass be_class_lv_led; @@ -290,7 +290,7 @@ be_local_closure(lvh_page_show, /* name */ /* K14 */ be_nested_str_weak(show_anim), /* K15 */ be_nested_str_weak(find), /* K16 */ be_nested_str_weak(SCR_LOAD_ANIM_NONE), - /* K17 */ be_nested_str_weak(scr_load_anim), + /* K17 */ be_nested_str_weak(screen_load_anim), }), be_str_weak(show), &be_const_str_solidified, @@ -839,7 +839,7 @@ be_local_closure(lvh_obj_event_cb, /* name */ ( &(const bvalue[22]) { /* constants */ /* K0 */ be_nested_str_weak(_page), /* K1 */ be_nested_str_weak(_oh), - /* K2 */ be_nested_str_weak(code), + /* K2 */ be_nested_str_weak(get_code), /* K3 */ be_nested_str_weak(action), /* K4 */ be_nested_str_weak(), /* K5 */ be_nested_str_weak(lv), @@ -865,32 +865,32 @@ be_local_closure(lvh_obj_event_cb, /* name */ ( &(const binstruction[72]) { /* code */ 0x88080100, // 0000 GETMBR R2 R0 K0 0x88080501, // 0001 GETMBR R2 R2 K1 - 0x880C0302, // 0002 GETMBR R3 R1 K2 - 0x88100103, // 0003 GETMBR R4 R0 K3 - 0x20100904, // 0004 NE R4 R4 K4 - 0x78120008, // 0005 JMPF R4 #000F - 0xB8120A00, // 0006 GETNGBL R4 K5 - 0x88100906, // 0007 GETMBR R4 R4 K6 - 0x1C100604, // 0008 EQ R4 R3 R4 - 0x78120004, // 0009 JMPF R4 #000F - 0xB8120E00, // 000A GETNGBL R4 K7 - 0x8C100908, // 000B GETMET R4 R4 K8 - 0x58180009, // 000C LDCONST R6 K9 - 0x841C0000, // 000D CLOSURE R7 P0 - 0x7C100600, // 000E CALL R4 3 - 0x8810010A, // 000F GETMBR R4 R0 K10 - 0x8C10090B, // 0010 GETMET R4 R4 K11 - 0x5C180600, // 0011 MOVE R6 R3 - 0x7C100400, // 0012 CALL R4 2 - 0x4C140000, // 0013 LDNIL R5 - 0x20140805, // 0014 NE R5 R4 R5 - 0x7816002F, // 0015 JMPF R5 #0046 - 0xA4161800, // 0016 IMPORT R5 K12 - 0x58180004, // 0017 LDCONST R6 K4 - 0x881C0302, // 0018 GETMBR R7 R1 K2 - 0xB8220A00, // 0019 GETNGBL R8 K5 - 0x8820110D, // 001A GETMBR R8 R8 K13 - 0x1C1C0E08, // 001B EQ R7 R7 R8 + 0x8C0C0302, // 0002 GETMET R3 R1 K2 + 0x7C0C0200, // 0003 CALL R3 1 + 0x88100103, // 0004 GETMBR R4 R0 K3 + 0x20100904, // 0005 NE R4 R4 K4 + 0x78120008, // 0006 JMPF R4 #0010 + 0xB8120A00, // 0007 GETNGBL R4 K5 + 0x88100906, // 0008 GETMBR R4 R4 K6 + 0x1C100604, // 0009 EQ R4 R3 R4 + 0x78120004, // 000A JMPF R4 #0010 + 0xB8120E00, // 000B GETNGBL R4 K7 + 0x8C100908, // 000C GETMET R4 R4 K8 + 0x58180009, // 000D LDCONST R6 K9 + 0x841C0000, // 000E CLOSURE R7 P0 + 0x7C100600, // 000F CALL R4 3 + 0x8810010A, // 0010 GETMBR R4 R0 K10 + 0x8C10090B, // 0011 GETMET R4 R4 K11 + 0x5C180600, // 0012 MOVE R6 R3 + 0x7C100400, // 0013 CALL R4 2 + 0x4C140000, // 0014 LDNIL R5 + 0x20140805, // 0015 NE R5 R4 R5 + 0x7816002E, // 0016 JMPF R5 #0046 + 0xA4161800, // 0017 IMPORT R5 K12 + 0x58180004, // 0018 LDCONST R6 K4 + 0xB81E0A00, // 0019 GETNGBL R7 K5 + 0x881C0F0D, // 001A GETMBR R7 R7 K13 + 0x1C1C0607, // 001B EQ R7 R3 R7 0x781E001A, // 001C JMPF R7 #0038 0xA8020015, // 001D EXBLK 0 #0034 0x881C010E, // 001E GETMBR R7 R0 K14 @@ -4147,14 +4147,13 @@ be_local_class(lvh_obj, { be_const_key_weak(set_text_rule, -1), be_const_closure(lvh_obj_set_text_rule_closure) }, { be_const_key_weak(get_enabled, -1), be_const_closure(lvh_obj_get_enabled_closure) }, { be_const_key_weak(_attr_ignore, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(10, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_nested_str_weak(tostring), be_nested_str_weak(obj), be_nested_str_weak(page), be_nested_str_weak(comment), be_nested_str_weak(parentid), - be_nested_str_weak(auto_size), be_nested_str_weak(prev), be_nested_str_weak(next), be_nested_str_weak(back), @@ -4226,8 +4225,8 @@ be_local_class(lvh_obj, be_const_int(327680), be_const_int(327680), be_const_int(262144), + be_const_int(327680), be_const_int(393216), - be_const_int(458752), be_const_int(65536), be_const_int(524288), })) ) } )) }, @@ -4287,11 +4286,11 @@ be_local_class(lvh_obj, { be_const_key_weak(_event_map, 3), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { be_const_map( * be_nested_map(7, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_int(28, 2), be_nested_str_weak(changed) }, - { be_const_key_int(8, 4), be_nested_str_weak(release) }, { be_const_key_int(7, -1), be_nested_str_weak(up) }, - { be_const_key_int(3, -1), be_nested_str_weak(lost) }, + { be_const_key_int(8, 4), be_nested_str_weak(release) }, { be_const_key_int(1, -1), be_nested_str_weak(down) }, + { be_const_key_int(3, -1), be_nested_str_weak(lost) }, + { be_const_key_int(29, 2), be_nested_str_weak(changed) }, { be_const_key_int(5, -1), be_nested_str_weak(long) }, { be_const_key_int(6, -1), be_nested_str_weak(hold) }, })) ) } )) }, @@ -4342,7 +4341,7 @@ be_local_class(lvh_btn, &be_class_lvh_obj, be_nested_map(1, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(_lv_class, -1), be_const_class(be_class_lv_btn) }, + { be_const_key_weak(_lv_class, -1), be_const_class(be_class_lv_button) }, })), be_str_weak(lvh_btn) ); @@ -4526,33 +4525,19 @@ extern const bclass be_class_lvh_spinner; ********************************************************************/ be_local_closure(lvh_spinner_set_angle, /* name */ be_nested_proto( - 4, /* nstack */ + 2, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(_anim_end), - /* K1 */ be_nested_str_weak(start_value), - /* K2 */ be_nested_str_weak(end_value), - }), + 0, /* has constants */ + NULL, /* no const */ be_str_weak(set_angle), &be_const_str_solidified, - ( &(const binstruction[11]) { /* code */ - 0x60080009, // 0000 GETGBL R2 G9 - 0x5C0C0200, // 0001 MOVE R3 R1 - 0x7C080200, // 0002 CALL R2 1 - 0x5C040400, // 0003 MOVE R1 R2 - 0x88080100, // 0004 GETMBR R2 R0 K0 - 0x900A0201, // 0005 SETMBR R2 K1 R1 - 0x88080100, // 0006 GETMBR R2 R0 K0 - 0x540E0167, // 0007 LDINT R3 360 - 0x000C0203, // 0008 ADD R3 R1 R3 - 0x900A0403, // 0009 SETMBR R2 K2 R3 - 0x80000000, // 000A RET 0 + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 }) ) ); @@ -4564,7 +4549,7 @@ be_local_closure(lvh_spinner_set_angle, /* name */ ********************************************************************/ be_local_closure(lvh_spinner_init, /* name */ be_nested_proto( - 11, /* nstack */ + 10, /* nstack */ 4, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -4572,7 +4557,7 @@ be_local_closure(lvh_spinner_init, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[15]) { /* constants */ + ( &(const bvalue[ 9]) { /* constants */ /* K0 */ be_nested_str_weak(_page), /* K1 */ be_nested_str_weak(find), /* K2 */ be_nested_str_weak(angle), @@ -4580,18 +4565,12 @@ be_local_closure(lvh_spinner_init, /* name */ /* K4 */ be_nested_str_weak(_lv_obj), /* K5 */ be_nested_str_weak(lv), /* K6 */ be_nested_str_weak(spinner), - /* K7 */ be_nested_str_weak(post_init), - /* K8 */ be_nested_str_weak(anim_get), - /* K9 */ be_nested_str_weak(_arc_anim_start_angle), - /* K10 */ be_nested_str_weak(_arc_anim_end_angle), - /* K11 */ be_nested_str_weak(_anim_start), - /* K12 */ be_nested_str_weak(anim_ntv), - /* K13 */ be_nested_str_weak(_p), - /* K14 */ be_nested_str_weak(_anim_end), + /* K7 */ be_nested_str_weak(set_anim_params), + /* K8 */ be_nested_str_weak(post_init), }), be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[41]) { /* code */ + ( &(const binstruction[22]) { /* code */ 0x90020002, // 0000 SETMBR R0 K0 R2 0x8C100701, // 0001 GETMET R4 R3 K1 0x58180002, // 0002 LDCONST R6 K2 @@ -4604,68 +4583,16 @@ be_local_closure(lvh_spinner_init, /* name */ 0xB81A0A00, // 0009 GETNGBL R6 K5 0x8C180D06, // 000A GETMET R6 R6 K6 0x5C200200, // 000B MOVE R8 R1 - 0x5C240A00, // 000C MOVE R9 R5 - 0x5C280800, // 000D MOVE R10 R4 - 0x7C180800, // 000E CALL R6 4 - 0x90020806, // 000F SETMBR R0 K4 R6 - 0x8C180107, // 0010 GETMET R6 R0 K7 - 0x7C180200, // 0011 CALL R6 1 - 0xB81A0A00, // 0012 GETNGBL R6 K5 - 0x8C180D08, // 0013 GETMET R6 R6 K8 - 0x88200104, // 0014 GETMBR R8 R0 K4 - 0x88240104, // 0015 GETMBR R9 R0 K4 - 0x88241309, // 0016 GETMBR R9 R9 K9 - 0x7C180600, // 0017 CALL R6 3 - 0xB81E0A00, // 0018 GETNGBL R7 K5 - 0x8C1C0F08, // 0019 GETMET R7 R7 K8 - 0x88240104, // 001A GETMBR R9 R0 K4 - 0x88280104, // 001B GETMBR R10 R0 K4 - 0x8828150A, // 001C GETMBR R10 R10 K10 - 0x7C1C0600, // 001D CALL R7 3 - 0xB8220A00, // 001E GETNGBL R8 K5 - 0x8C20110C, // 001F GETMET R8 R8 K12 - 0x88280D0D, // 0020 GETMBR R10 R6 K13 - 0x7C200400, // 0021 CALL R8 2 - 0x90021608, // 0022 SETMBR R0 K11 R8 - 0xB8220A00, // 0023 GETNGBL R8 K5 - 0x8C20110C, // 0024 GETMET R8 R8 K12 - 0x88280F0D, // 0025 GETMBR R10 R7 K13 - 0x7C200400, // 0026 CALL R8 2 - 0x90021C08, // 0027 SETMBR R0 K14 R8 - 0x80000000, // 0028 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_angle -********************************************************************/ -be_local_closure(lvh_spinner_get_angle, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(_anim_end), - /* K1 */ be_nested_str_weak(start_value), - /* K2 */ be_nested_str_weak(_anim_start), - }), - be_str_weak(get_angle), - &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x88040301, // 0001 GETMBR R1 R1 K1 - 0x88080102, // 0002 GETMBR R2 R0 K2 - 0x88080501, // 0003 GETMBR R2 R2 K1 - 0x04040202, // 0004 SUB R1 R1 R2 - 0x80040200, // 0005 RET 1 R1 + 0x7C180400, // 000C CALL R6 2 + 0x90020806, // 000D SETMBR R0 K4 R6 + 0x88180104, // 000E GETMBR R6 R0 K4 + 0x8C180D07, // 000F GETMET R6 R6 K7 + 0x5C200A00, // 0010 MOVE R8 R5 + 0x5C240800, // 0011 MOVE R9 R4 + 0x7C180600, // 0012 CALL R6 3 + 0x8C180108, // 0013 GETMET R6 R0 K8 + 0x7C180200, // 0014 CALL R6 1 + 0x80000000, // 0015 RET 0 }) ) ); @@ -4677,24 +4604,43 @@ be_local_closure(lvh_spinner_get_angle, /* name */ ********************************************************************/ be_local_closure(lvh_spinner_get_speed, /* name */ be_nested_proto( - 2, /* nstack */ + 1, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(_anim_start), - /* K1 */ be_nested_str_weak(time), - }), + 0, /* has constants */ + NULL, /* no const */ be_str_weak(get_speed), &be_const_str_solidified, - ( &(const binstruction[ 3]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x88040301, // 0001 GETMBR R1 R1 K1 - 0x80040200, // 0002 RET 1 R1 + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_angle +********************************************************************/ +be_local_closure(lvh_spinner_get_angle, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(get_angle), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 }) ) ); @@ -4706,31 +4652,19 @@ be_local_closure(lvh_spinner_get_speed, /* name */ ********************************************************************/ be_local_closure(lvh_spinner_set_speed, /* name */ be_nested_proto( - 4, /* nstack */ + 2, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(_anim_start), - /* K1 */ be_nested_str_weak(time), - /* K2 */ be_nested_str_weak(_anim_end), - }), + 0, /* has constants */ + NULL, /* no const */ be_str_weak(set_speed), &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0x60080009, // 0000 GETGBL R2 G9 - 0x5C0C0200, // 0001 MOVE R3 R1 - 0x7C080200, // 0002 CALL R2 1 - 0x5C040400, // 0003 MOVE R1 R2 - 0x88080100, // 0004 GETMBR R2 R0 K0 - 0x900A0201, // 0005 SETMBR R2 K1 R1 - 0x88080102, // 0006 GETMBR R2 R0 K2 - 0x900A0201, // 0007 SETMBR R2 K1 R1 - 0x80000000, // 0008 RET 0 + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 }) ) ); @@ -4746,13 +4680,13 @@ be_local_class(lvh_spinner, &be_class_lvh_arc, be_nested_map(8, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(set_speed, 1), be_const_closure(lvh_spinner_set_speed_closure) }, - { be_const_key_weak(_lv_class, -1), be_const_class(be_class_lv_spinner) }, - { be_const_key_weak(get_speed, 6), be_const_closure(lvh_spinner_get_speed_closure) }, + { be_const_key_weak(set_speed, 4), be_const_closure(lvh_spinner_set_speed_closure) }, + { be_const_key_weak(_speed, -1), be_const_var(0) }, + { be_const_key_weak(get_angle, 6), be_const_closure(lvh_spinner_get_angle_closure) }, { be_const_key_weak(init, 2), be_const_closure(lvh_spinner_init_closure) }, - { be_const_key_weak(_anim_start, -1), be_const_var(0) }, - { be_const_key_weak(_anim_end, -1), be_const_var(1) }, - { be_const_key_weak(get_angle, -1), be_const_closure(lvh_spinner_get_angle_closure) }, + { be_const_key_weak(_lv_class, -1), be_const_class(be_class_lv_spinner) }, + { be_const_key_weak(_angle, -1), be_const_var(1) }, + { be_const_key_weak(get_speed, -1), be_const_closure(lvh_spinner_get_speed_closure) }, { be_const_key_weak(set_angle, 0), be_const_closure(lvh_spinner_set_angle_closure) }, })), be_str_weak(lvh_spinner) @@ -4790,6 +4724,71 @@ void be_load_lvh_line_class(bvm *vm) { extern const bclass be_class_lvh_img; +/******************************************************************** +** Solidified function: get_angle +********************************************************************/ +be_local_closure(lvh_img_get_angle, /* name */ + be_nested_proto( + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(get_angle), + }), + be_str_weak(get_angle), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x8C040301, // 0001 GETMET R1 R1 K1 + 0x7C040200, // 0002 CALL R1 1 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_auto_size +********************************************************************/ +be_local_closure(lvh_img_set_auto_size, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(set_inner_align), + /* K2 */ be_nested_str_weak(lv), + /* K3 */ be_nested_str_weak(IMAGE_ALIGN_STRETCH), + }), + be_str_weak(set_auto_size), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x78060004, // 0000 JMPF R1 #0006 + 0x88080100, // 0001 GETMBR R2 R0 K0 + 0x8C080501, // 0002 GETMET R2 R2 K1 + 0xB8120400, // 0003 GETNGBL R4 K2 + 0x88100903, // 0004 GETMBR R4 R4 K3 + 0x7C080400, // 0005 CALL R2 2 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: set_angle ********************************************************************/ @@ -4826,29 +4825,23 @@ be_local_closure(lvh_img_set_angle, /* name */ /******************************************************************** -** Solidified function: get_angle +** Solidified function: get_auto_size ********************************************************************/ -be_local_closure(lvh_img_get_angle, /* name */ +be_local_closure(lvh_img_get_auto_size, /* name */ be_nested_proto( - 3, /* nstack */ + 1, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(_lv_obj), - /* K1 */ be_nested_str_weak(get_angle), - }), - be_str_weak(get_angle), + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(get_auto_size), &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x8C040301, // 0001 GETMET R1 R1 K1 - 0x7C040200, // 0002 CALL R1 1 - 0x80040200, // 0003 RET 1 R1 + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 }) ) ); @@ -4862,11 +4855,13 @@ extern const bclass be_class_lvh_obj; be_local_class(lvh_img, 0, &be_class_lvh_obj, - be_nested_map(3, + be_nested_map(5, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(set_angle, -1), be_const_closure(lvh_img_set_angle_closure) }, - { be_const_key_weak(get_angle, 2), be_const_closure(lvh_img_get_angle_closure) }, - { be_const_key_weak(_lv_class, -1), be_const_class(be_class_lv_img) }, + { be_const_key_weak(get_angle, -1), be_const_closure(lvh_img_get_angle_closure) }, + { be_const_key_weak(set_auto_size, -1), be_const_closure(lvh_img_set_auto_size_closure) }, + { be_const_key_weak(set_angle, 4), be_const_closure(lvh_img_set_angle_closure) }, + { be_const_key_weak(get_auto_size, -1), be_const_closure(lvh_img_get_auto_size_closure) }, + { be_const_key_weak(_lv_class, -1), be_const_class(be_class_lv_image) }, })), be_str_weak(lvh_img) ); @@ -5122,7 +5117,7 @@ be_local_class(lvh_btnmatrix, &be_class_lvh_obj, be_nested_map(1, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(_lv_class, -1), be_const_class(be_class_lv_btnmatrix) }, + { be_const_key_weak(_lv_class, -1), be_const_class(be_class_lv_buttonmatrix) }, })), be_str_weak(lvh_btnmatrix) ); @@ -6213,23 +6208,33 @@ void be_load_lvh_dropdown_class(bvm *vm) { extern const bclass be_class_lvh_qrcode; /******************************************************************** -** Solidified function: get_qr_size +** Solidified function: set_dark_color ********************************************************************/ -be_local_closure(lvh_qrcode_get_qr_size, /* name */ +be_local_closure(lvh_qrcode_set_dark_color, /* name */ be_nested_proto( - 1, /* nstack */ - 1, /* argc */ + 7, /* nstack */ + 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(get_qr_size), + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(set_dark_color), + /* K2 */ be_nested_str_weak(parse_color), + }), + be_str_weak(set_dark_color), &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 + ( &(const binstruction[ 7]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x8C100102, // 0002 GETMET R4 R0 K2 + 0x5C180200, // 0003 MOVE R6 R1 + 0x7C100400, // 0004 CALL R4 2 + 0x7C080400, // 0005 CALL R2 2 + 0x80000000, // 0006 RET 0 }) ) ); @@ -6241,131 +6246,26 @@ be_local_closure(lvh_qrcode_get_qr_size, /* name */ ********************************************************************/ be_local_closure(lvh_qrcode_set_qr_size, /* name */ be_nested_proto( - 2, /* nstack */ + 5, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(set_size), + }), be_str_weak(set_qr_size), &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_qr_light_color -********************************************************************/ -be_local_closure(lvh_qrcode_get_qr_light_color, /* name */ - be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(get_qr_light_color), - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_qr_dark_color -********************************************************************/ -be_local_closure(lvh_qrcode_get_qr_dark_color, /* name */ - be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(get_qr_dark_color), - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(lvh_qrcode_init, /* name */ - be_nested_proto( - 13, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[12]) { /* constants */ - /* K0 */ be_nested_str_weak(_page), - /* K1 */ be_nested_str_weak(find), - /* K2 */ be_nested_str_weak(qr_size), - /* K3 */ be_nested_str_weak(parse_color), - /* K4 */ be_nested_str_weak(qr_dark_color), - /* K5 */ be_nested_str_weak(_X23000000), - /* K6 */ be_nested_str_weak(qr_light_color), - /* K7 */ be_nested_str_weak(_X23FFFFFF), - /* K8 */ be_nested_str_weak(_lv_obj), - /* K9 */ be_nested_str_weak(lv), - /* K10 */ be_nested_str_weak(qrcode), - /* K11 */ be_nested_str_weak(post_init), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[28]) { /* code */ - 0x90020002, // 0000 SETMBR R0 K0 R2 - 0x8C100701, // 0001 GETMET R4 R3 K1 - 0x58180002, // 0002 LDCONST R6 K2 - 0x541E0063, // 0003 LDINT R7 100 - 0x7C100600, // 0004 CALL R4 3 - 0x8C140103, // 0005 GETMET R5 R0 K3 - 0x8C1C0701, // 0006 GETMET R7 R3 K1 - 0x58240004, // 0007 LDCONST R9 K4 - 0x58280005, // 0008 LDCONST R10 K5 - 0x7C1C0600, // 0009 CALL R7 3 - 0x7C140400, // 000A CALL R5 2 - 0x8C180103, // 000B GETMET R6 R0 K3 - 0x8C200701, // 000C GETMET R8 R3 K1 - 0x58280006, // 000D LDCONST R10 K6 - 0x582C0007, // 000E LDCONST R11 K7 - 0x7C200600, // 000F CALL R8 3 - 0x7C180400, // 0010 CALL R6 2 - 0xB81E1200, // 0011 GETNGBL R7 K9 - 0x8C1C0F0A, // 0012 GETMET R7 R7 K10 - 0x5C240200, // 0013 MOVE R9 R1 - 0x5C280800, // 0014 MOVE R10 R4 - 0x5C2C0A00, // 0015 MOVE R11 R5 - 0x5C300C00, // 0016 MOVE R12 R6 - 0x7C1C0A00, // 0017 CALL R7 5 - 0x90021007, // 0018 SETMBR R0 K8 R7 - 0x8C1C010B, // 0019 GETMET R7 R0 K11 - 0x7C1C0200, // 001A CALL R7 1 - 0x80000000, // 001B RET 0 + ( &(const binstruction[ 5]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x80000000, // 0004 RET 0 }) ) ); @@ -6377,19 +6277,29 @@ be_local_closure(lvh_qrcode_init, /* name */ ********************************************************************/ be_local_closure(lvh_qrcode_set_qr_light_color, /* name */ be_nested_proto( - 2, /* nstack */ + 7, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(set_light_color), + /* K2 */ be_nested_str_weak(parse_color), + }), be_str_weak(set_qr_light_color), &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 + ( &(const binstruction[ 7]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x8C100102, // 0002 GETMET R4 R0 K2 + 0x5C180200, // 0003 MOVE R6 R1 + 0x7C100400, // 0004 CALL R4 2 + 0x7C080400, // 0005 CALL R2 2 + 0x80000000, // 0006 RET 0 }) ) ); @@ -6397,47 +6307,33 @@ be_local_closure(lvh_qrcode_set_qr_light_color, /* name */ /******************************************************************** -** Solidified function: get_qr_text +** Solidified function: set_light_color ********************************************************************/ -be_local_closure(lvh_qrcode_get_qr_text, /* name */ +be_local_closure(lvh_qrcode_set_light_color, /* name */ be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(get_qr_text), - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_qr_dark_color -********************************************************************/ -be_local_closure(lvh_qrcode_set_qr_dark_color, /* name */ - be_nested_proto( - 2, /* nstack */ + 7, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(set_qr_dark_color), + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(set_light_color), + /* K2 */ be_nested_str_weak(parse_color), + }), + be_str_weak(set_light_color), &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 + ( &(const binstruction[ 7]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x8C100102, // 0002 GETMET R4 R0 K2 + 0x5C180200, // 0003 MOVE R6 R1 + 0x7C100400, // 0004 CALL R4 2 + 0x7C080400, // 0005 CALL R2 2 + 0x80000000, // 0006 RET 0 }) ) ); @@ -6482,6 +6378,239 @@ be_local_closure(lvh_qrcode_set_qr_text, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: get_dark_color +********************************************************************/ +be_local_closure(lvh_qrcode_get_dark_color, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(get_dark_color), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_size +********************************************************************/ +be_local_closure(lvh_qrcode_set_size, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(set_size), + }), + be_str_weak(set_size), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x80000000, // 0004 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_size +********************************************************************/ +be_local_closure(lvh_qrcode_get_size, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(get_size), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_light_color +********************************************************************/ +be_local_closure(lvh_qrcode_get_light_color, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(get_light_color), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_qr_text +********************************************************************/ +be_local_closure(lvh_qrcode_get_qr_text, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(get_qr_text), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_qr_dark_color +********************************************************************/ +be_local_closure(lvh_qrcode_get_qr_dark_color, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(get_qr_dark_color), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_qr_light_color +********************************************************************/ +be_local_closure(lvh_qrcode_get_qr_light_color, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(get_qr_light_color), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_qr_dark_color +********************************************************************/ +be_local_closure(lvh_qrcode_set_qr_dark_color, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(_lv_obj), + /* K1 */ be_nested_str_weak(set_dark_color), + /* K2 */ be_nested_str_weak(parse_color), + }), + be_str_weak(set_qr_dark_color), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x8C100102, // 0002 GETMET R4 R0 K2 + 0x5C180200, // 0003 MOVE R6 R1 + 0x7C100400, // 0004 CALL R4 2 + 0x7C080400, // 0005 CALL R2 2 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_qr_size +********************************************************************/ +be_local_closure(lvh_qrcode_get_qr_size, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(get_qr_size), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified class: lvh_qrcode ********************************************************************/ @@ -6489,18 +6618,23 @@ extern const bclass be_class_lvh_obj; be_local_class(lvh_qrcode, 0, &be_class_lvh_obj, - be_nested_map(10, + be_nested_map(15, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(set_qr_text, -1), be_const_closure(lvh_qrcode_set_qr_text_closure) }, + { be_const_key_weak(set_dark_color, 6), be_const_closure(lvh_qrcode_set_dark_color_closure) }, { be_const_key_weak(set_qr_size, -1), be_const_closure(lvh_qrcode_set_qr_size_closure) }, - { be_const_key_weak(get_qr_light_color, 6), be_const_closure(lvh_qrcode_get_qr_light_color_closure) }, - { be_const_key_weak(set_qr_dark_color, -1), be_const_closure(lvh_qrcode_set_qr_dark_color_closure) }, + { be_const_key_weak(set_qr_light_color, 10), be_const_closure(lvh_qrcode_set_qr_light_color_closure) }, + { be_const_key_weak(set_light_color, 9), be_const_closure(lvh_qrcode_set_light_color_closure) }, + { be_const_key_weak(get_qr_size, 11), be_const_closure(lvh_qrcode_get_qr_size_closure) }, + { be_const_key_weak(get_dark_color, -1), be_const_closure(lvh_qrcode_get_dark_color_closure) }, + { be_const_key_weak(set_size, -1), be_const_closure(lvh_qrcode_set_size_closure) }, + { be_const_key_weak(_lv_class, -1), be_const_class(be_class_lv_qrcode) }, + { be_const_key_weak(get_size, -1), be_const_closure(lvh_qrcode_get_size_closure) }, + { be_const_key_weak(get_qr_dark_color, 5), be_const_closure(lvh_qrcode_get_qr_dark_color_closure) }, { be_const_key_weak(get_qr_text, -1), be_const_closure(lvh_qrcode_get_qr_text_closure) }, - { be_const_key_weak(init, -1), be_const_closure(lvh_qrcode_init_closure) }, - { be_const_key_weak(set_qr_light_color, -1), be_const_closure(lvh_qrcode_set_qr_light_color_closure) }, - { be_const_key_weak(_lv_class, 4), be_const_class(be_class_lv_qrcode) }, - { be_const_key_weak(get_qr_dark_color, 3), be_const_closure(lvh_qrcode_get_qr_dark_color_closure) }, - { be_const_key_weak(get_qr_size, 0), be_const_closure(lvh_qrcode_get_qr_size_closure) }, + { be_const_key_weak(get_light_color, -1), be_const_closure(lvh_qrcode_get_light_color_closure) }, + { be_const_key_weak(get_qr_light_color, -1), be_const_closure(lvh_qrcode_get_qr_light_color_closure) }, + { be_const_key_weak(set_qr_dark_color, -1), be_const_closure(lvh_qrcode_set_qr_dark_color_closure) }, + { be_const_key_weak(set_qr_text, 4), be_const_closure(lvh_qrcode_set_qr_text_closure) }, })), be_str_weak(lvh_qrcode) ); @@ -7021,6 +7155,266 @@ void be_load_lvh_chart_class(bvm *vm) { extern const bclass be_class_HASPmota; +/******************************************************************** +** Solidified function: event_dispatch +********************************************************************/ +be_local_closure(HASPmota_event_dispatch, /* name */ + be_nested_proto( + 9, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_str_weak(introspect), + /* K1 */ be_nested_str_weak(toptr), + /* K2 */ be_nested_str_weak(event), + /* K3 */ be_nested_str_weak(_p), + /* K4 */ be_nested_str_weak(lv), + /* K5 */ be_nested_str_weak(lv_event), + /* K6 */ be_nested_str_weak(get_user_data), + /* K7 */ be_const_int(0), + /* K8 */ be_nested_str_weak(fromptr), + /* K9 */ be_nested_str_weak(instance), + /* K10 */ be_nested_str_weak(event_cb), + }), + be_str_weak(event_dispatch), + &be_const_str_solidified, + ( &(const binstruction[34]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0x8C0C0501, // 0001 GETMET R3 R2 K1 + 0x5C140200, // 0002 MOVE R5 R1 + 0x7C0C0400, // 0003 CALL R3 2 + 0x88100102, // 0004 GETMBR R4 R0 K2 + 0x78120002, // 0005 JMPF R4 #0009 + 0x88100102, // 0006 GETMBR R4 R0 K2 + 0x90120603, // 0007 SETMBR R4 K3 R3 + 0x70020004, // 0008 JMP #000E + 0xB8120800, // 0009 GETNGBL R4 K4 + 0x8C100905, // 000A GETMET R4 R4 K5 + 0x5C180600, // 000B MOVE R6 R3 + 0x7C100400, // 000C CALL R4 2 + 0x90020404, // 000D SETMBR R0 K2 R4 + 0x88100102, // 000E GETMBR R4 R0 K2 + 0x8C100906, // 000F GETMET R4 R4 K6 + 0x7C100200, // 0010 CALL R4 1 + 0x60140009, // 0011 GETGBL R5 G9 + 0x5C180800, // 0012 MOVE R6 R4 + 0x7C140200, // 0013 CALL R5 1 + 0x20140B07, // 0014 NE R5 R5 K7 + 0x7816000A, // 0015 JMPF R5 #0021 + 0x8C140508, // 0016 GETMET R5 R2 K8 + 0x5C1C0800, // 0017 MOVE R7 R4 + 0x7C140400, // 0018 CALL R5 2 + 0x60180004, // 0019 GETGBL R6 G4 + 0x5C1C0A00, // 001A MOVE R7 R5 + 0x7C180200, // 001B CALL R6 1 + 0x1C180D09, // 001C EQ R6 R6 K9 + 0x781A0002, // 001D JMPF R6 #0021 + 0x8C180B0A, // 001E GETMET R6 R5 K10 + 0x88200102, // 001F GETMBR R8 R0 K2 + 0x7C180400, // 0020 CALL R6 2 + 0x80000000, // 0021 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: parse_page +********************************************************************/ +be_local_closure(HASPmota_parse_page, /* name */ + be_nested_proto( + 9, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[14]) { /* constants */ + /* K0 */ be_nested_str_weak(has), + /* K1 */ be_nested_str_weak(page), + /* K2 */ be_nested_str_weak(int), + /* K3 */ be_nested_str_weak(lvh_page_cur_idx), + /* K4 */ be_nested_str_weak(lvh_pages), + /* K5 */ be_nested_str_weak(contains), + /* K6 */ be_nested_str_weak(lvh_page), + /* K7 */ be_nested_str_weak(find), + /* K8 */ be_nested_str_weak(id), + /* K9 */ be_const_int(0), + /* K10 */ be_nested_str_weak(get_page_cur), + /* K11 */ be_nested_str_weak(prev), + /* K12 */ be_nested_str_weak(next), + /* K13 */ be_nested_str_weak(back), + }), + be_str_weak(parse_page), + &be_const_str_solidified, + ( &(const binstruction[54]) { /* code */ + 0x8C080300, // 0000 GETMET R2 R1 K0 + 0x58100001, // 0001 LDCONST R4 K1 + 0x7C080400, // 0002 CALL R2 2 + 0x780A0030, // 0003 JMPF R2 #0035 + 0x60080004, // 0004 GETGBL R2 G4 + 0x940C0301, // 0005 GETIDX R3 R1 K1 + 0x7C080200, // 0006 CALL R2 1 + 0x1C080502, // 0007 EQ R2 R2 K2 + 0x780A002B, // 0008 JMPF R2 #0035 + 0x60080009, // 0009 GETGBL R2 G9 + 0x940C0301, // 000A GETIDX R3 R1 K1 + 0x7C080200, // 000B CALL R2 1 + 0x90020602, // 000C SETMBR R0 K3 R2 + 0x880C0104, // 000D GETMBR R3 R0 K4 + 0x8C0C0705, // 000E GETMET R3 R3 K5 + 0x5C140400, // 000F MOVE R5 R2 + 0x7C0C0400, // 0010 CALL R3 2 + 0x740E0006, // 0011 JMPT R3 #0019 + 0x880C0106, // 0012 GETMBR R3 R0 K6 + 0x88100104, // 0013 GETMBR R4 R0 K4 + 0x5C140600, // 0014 MOVE R5 R3 + 0x5C180400, // 0015 MOVE R6 R2 + 0x5C1C0000, // 0016 MOVE R7 R0 + 0x7C140400, // 0017 CALL R5 2 + 0x98100405, // 0018 SETIDX R4 R2 R5 + 0x8C0C0307, // 0019 GETMET R3 R1 K7 + 0x58140008, // 001A LDCONST R5 K8 + 0x7C0C0400, // 001B CALL R3 2 + 0x1C0C0709, // 001C EQ R3 R3 K9 + 0x780E0016, // 001D JMPF R3 #0035 + 0x8C0C010A, // 001E GETMET R3 R0 K10 + 0x7C0C0200, // 001F CALL R3 1 + 0x60100009, // 0020 GETGBL R4 G9 + 0x8C140307, // 0021 GETMET R5 R1 K7 + 0x581C000B, // 0022 LDCONST R7 K11 + 0x4C200000, // 0023 LDNIL R8 + 0x7C140600, // 0024 CALL R5 3 + 0x7C100200, // 0025 CALL R4 1 + 0x900E1604, // 0026 SETMBR R3 K11 R4 + 0x60100009, // 0027 GETGBL R4 G9 + 0x8C140307, // 0028 GETMET R5 R1 K7 + 0x581C000C, // 0029 LDCONST R7 K12 + 0x4C200000, // 002A LDNIL R8 + 0x7C140600, // 002B CALL R5 3 + 0x7C100200, // 002C CALL R4 1 + 0x900E1804, // 002D SETMBR R3 K12 R4 + 0x60100009, // 002E GETGBL R4 G9 + 0x8C140307, // 002F GETMET R5 R1 K7 + 0x581C000D, // 0030 LDCONST R7 K13 + 0x4C200000, // 0031 LDNIL R8 + 0x7C140600, // 0032 CALL R5 3 + 0x7C100200, // 0033 CALL R4 1 + 0x900E1A04, // 0034 SETMBR R3 K13 R4 + 0x80000000, // 0035 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: parse +********************************************************************/ +be_local_closure(HASPmota_parse, /* name */ + be_nested_proto( + 9, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(json), + /* K1 */ be_nested_str_weak(load), + /* K2 */ be_nested_str_weak(instance), + /* K3 */ be_nested_str_weak(parse_page), + /* K4 */ be_nested_str_weak(parse_obj), + /* K5 */ be_nested_str_weak(lvh_pages), + /* K6 */ be_nested_str_weak(lvh_page_cur_idx), + /* K7 */ be_nested_str_weak(value_error), + /* K8 */ be_nested_str_weak(unable_X20to_X20parse_X20JSON_X20line), + }), + be_str_weak(parse), + &be_const_str_solidified, + ( &(const binstruction[21]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0x8C0C0501, // 0001 GETMET R3 R2 K1 + 0x5C140200, // 0002 MOVE R5 R1 + 0x7C0C0400, // 0003 CALL R3 2 + 0x60100004, // 0004 GETGBL R4 G4 + 0x5C140600, // 0005 MOVE R5 R3 + 0x7C100200, // 0006 CALL R4 1 + 0x1C100902, // 0007 EQ R4 R4 K2 + 0x78120009, // 0008 JMPF R4 #0013 + 0x8C100103, // 0009 GETMET R4 R0 K3 + 0x5C180600, // 000A MOVE R6 R3 + 0x7C100400, // 000B CALL R4 2 + 0x8C100104, // 000C GETMET R4 R0 K4 + 0x5C180600, // 000D MOVE R6 R3 + 0x881C0105, // 000E GETMBR R7 R0 K5 + 0x88200106, // 000F GETMBR R8 R0 K6 + 0x941C0E08, // 0010 GETIDX R7 R7 R8 + 0x7C100600, // 0011 CALL R4 3 + 0x70020000, // 0012 JMP #0014 + 0xB0060F08, // 0013 RAISE 1 K7 K8 + 0x80000000, // 0014 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: fix_lv_version +********************************************************************/ +be_local_closure(HASPmota_fix_lv_version, /* name */ + be_nested_proto( + 6, /* nstack */ + 0, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_const_class(be_class_HASPmota), + /* K1 */ be_nested_str_weak(introspect), + /* K2 */ be_nested_str_weak(get), + /* K3 */ be_nested_str_weak(lv), + /* K4 */ be_nested_str_weak(version), + /* K5 */ be_nested_str_weak(int), + }), + be_str_weak(fix_lv_version), + &be_const_str_solidified, + ( &(const binstruction[15]) { /* code */ + 0x58000000, // 0000 LDCONST R0 K0 + 0xA4060200, // 0001 IMPORT R1 K1 + 0x8C080302, // 0002 GETMET R2 R1 K2 + 0xB8120600, // 0003 GETNGBL R4 K3 + 0x58140004, // 0004 LDCONST R5 K4 + 0x7C080600, // 0005 CALL R2 3 + 0x600C0004, // 0006 GETGBL R3 G4 + 0x5C100400, // 0007 MOVE R4 R2 + 0x7C0C0200, // 0008 CALL R3 1 + 0x200C0705, // 0009 NE R3 R3 K5 + 0x780E0002, // 000A JMPF R3 #000E + 0xB80E0600, // 000B GETNGBL R3 K3 + 0x54120007, // 000C LDINT R4 8 + 0x900E0804, // 000D SETMBR R3 K4 R4 + 0x80000000, // 000E RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: register_event ********************************************************************/ @@ -7097,6 +7491,375 @@ be_local_closure(HASPmota_register_event, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: page_dir_to +********************************************************************/ +be_local_closure(HASPmota_page_dir_to, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(pages_list_sorted), + /* K1 */ be_const_int(0), + /* K2 */ be_const_int(1), + /* K3 */ be_const_int(2), + /* K4 */ be_nested_str_weak(find), + }), + be_str_weak(page_dir_to), + &be_const_str_solidified, + ( &(const binstruction[32]) { /* code */ + 0x8C080100, // 0000 GETMET R2 R0 K0 + 0x58100001, // 0001 LDCONST R4 K1 + 0x7C080400, // 0002 CALL R2 2 + 0x4C0C0000, // 0003 LDNIL R3 + 0x1C0C0403, // 0004 EQ R3 R2 R3 + 0x780E0000, // 0005 JMPF R3 #0007 + 0x80060200, // 0006 RET 1 K1 + 0x600C000C, // 0007 GETGBL R3 G12 + 0x5C100400, // 0008 MOVE R4 R2 + 0x7C0C0200, // 0009 CALL R3 1 + 0x18100702, // 000A LE R4 R3 K2 + 0x78120000, // 000B JMPF R4 #000D + 0x80060200, // 000C RET 1 K1 + 0x1C100703, // 000D EQ R4 R3 K3 + 0x78120000, // 000E JMPF R4 #0010 + 0x80060400, // 000F RET 1 K2 + 0x8C100504, // 0010 GETMET R4 R2 K4 + 0x5C180200, // 0011 MOVE R6 R1 + 0x7C100400, // 0012 CALL R4 2 + 0x4C140000, // 0013 LDNIL R5 + 0x1C140805, // 0014 EQ R5 R4 R5 + 0x78160000, // 0015 JMPF R5 #0017 + 0x80060200, // 0016 RET 1 K1 + 0x00140702, // 0017 ADD R5 R3 K2 + 0x0C140B03, // 0018 DIV R5 R5 K3 + 0x18140805, // 0019 LE R5 R4 R5 + 0x78160001, // 001A JMPF R5 #001D + 0x80060400, // 001B RET 1 K2 + 0x70020001, // 001C JMP #001F + 0x5415FFFE, // 001D LDINT R5 -1 + 0x80040A00, // 001E RET 1 R5 + 0x80000000, // 001F RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: parse_obj +********************************************************************/ +be_local_closure(HASPmota_parse_obj, /* name */ + be_nested_proto( + 20, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[30]) { /* constants */ + /* K0 */ be_nested_str_weak(global), + /* K1 */ be_nested_str_weak(introspect), + /* K2 */ be_nested_str_weak(find), + /* K3 */ be_nested_str_weak(id), + /* K4 */ be_nested_str_weak(obj), + /* K5 */ be_nested_str_weak(get_page_cur), + /* K6 */ be_nested_str_weak(berry_run), + /* K7 */ be_nested_str_weak(nil), + /* K8 */ be_nested_str_weak(HSP_X3A_X20unable_X20to_X20compile_X20berry_X20code_X20_X22_X25s_X22_X20_X2D_X20_X27_X25s_X27_X20_X2D_X20_X25s), + /* K9 */ be_const_int(1), + /* K10 */ be_nested_str_weak(HSP_X3A_X20invalid_X20_X27id_X27_X3A_X20), + /* K11 */ be_nested_str_weak(_X20for_X20_X27obj_X27_X3A), + /* K12 */ be_nested_str_weak(parentid), + /* K13 */ be_nested_str_weak(get_obj), + /* K14 */ be_nested_str_weak(_lv_obj), + /* K15 */ be_nested_str_weak(get_scr), + /* K16 */ be_nested_str_weak(get), + /* K17 */ be_nested_str_weak(lvh_), + /* K18 */ be_nested_str_weak(class), + /* K19 */ be_nested_str_weak(lvh_obj), + /* K20 */ be_nested_str_weak(module), + /* K21 */ be_nested_str_weak(HSP_X3A_X20Cannot_X20find_X20object_X20of_X20type_X20), + /* K22 */ be_nested_str_weak(set_obj), + /* K23 */ be_nested_str_weak(p_X25ib_X25i), + /* K24 */ be_nested_str_weak(function), + /* K25 */ be_nested_str_weak(HSP_X3A_X20unable_X20to_X20run_X20berry_X20code_X20_X22_X25s_X22_X20_X2D_X20_X27_X25s_X27_X20_X2D_X20_X25s), + /* K26 */ be_const_int(0), + /* K27 */ be_nested_str_weak(HSP_X3A_X20cannot_X20specify_X20_X27obj_X27_X20for_X20_X27id_X27_X3A0), + /* K28 */ be_nested_str_weak(keys), + /* K29 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(parse_obj), + &be_const_str_solidified, + ( &(const binstruction[217]) { /* code */ + 0xA40E0000, // 0000 IMPORT R3 K0 + 0xA4120200, // 0001 IMPORT R4 K1 + 0x60140009, // 0002 GETGBL R5 G9 + 0x8C180302, // 0003 GETMET R6 R1 K2 + 0x58200003, // 0004 LDCONST R8 K3 + 0x7C180400, // 0005 CALL R6 2 + 0x7C140200, // 0006 CALL R5 1 + 0x60180008, // 0007 GETGBL R6 G8 + 0x8C1C0302, // 0008 GETMET R7 R1 K2 + 0x58240004, // 0009 LDCONST R9 K4 + 0x7C1C0400, // 000A CALL R7 2 + 0x7C180200, // 000B CALL R6 1 + 0x4C1C0000, // 000C LDNIL R7 + 0x8C200105, // 000D GETMET R8 R0 K5 + 0x7C200200, // 000E CALL R8 1 + 0x60240008, // 000F GETGBL R9 G8 + 0x8C280302, // 0010 GETMET R10 R1 K2 + 0x58300006, // 0011 LDCONST R12 K6 + 0x7C280400, // 0012 CALL R10 2 + 0x7C240200, // 0013 CALL R9 1 + 0x4C280000, // 0014 LDNIL R10 + 0x202C1307, // 0015 NE R11 R9 K7 + 0x782E0012, // 0016 JMPF R11 #002A + 0xA8020005, // 0017 EXBLK 0 #001E + 0x602C000D, // 0018 GETGBL R11 G13 + 0x5C301200, // 0019 MOVE R12 R9 + 0x7C2C0200, // 001A CALL R11 1 + 0x5C281600, // 001B MOVE R10 R11 + 0xA8040001, // 001C EXBLK 1 1 + 0x7002000B, // 001D JMP #002A + 0xAC2C0002, // 001E CATCH R11 0 2 + 0x70020008, // 001F JMP #0029 + 0x60340001, // 0020 GETGBL R13 G1 + 0x60380018, // 0021 GETGBL R14 G24 + 0x583C0008, // 0022 LDCONST R15 K8 + 0x5C401200, // 0023 MOVE R16 R9 + 0x5C441600, // 0024 MOVE R17 R11 + 0x5C481800, // 0025 MOVE R18 R12 + 0x7C380800, // 0026 CALL R14 4 + 0x7C340200, // 0027 CALL R13 1 + 0x70020000, // 0028 JMP #002A + 0xB0080000, // 0029 RAISE 2 R0 R0 + 0x202C0D07, // 002A NE R11 R6 K7 + 0x782E006E, // 002B JMPF R11 #009B + 0x4C2C0000, // 002C LDNIL R11 + 0x202C0A0B, // 002D NE R11 R5 R11 + 0x782E006B, // 002E JMPF R11 #009B + 0x142C0B09, // 002F LT R11 R5 K9 + 0x742E0002, // 0030 JMPT R11 #0034 + 0x542E00FD, // 0031 LDINT R11 254 + 0x242C0A0B, // 0032 GT R11 R5 R11 + 0x782E0008, // 0033 JMPF R11 #003D + 0x602C0001, // 0034 GETGBL R11 G1 + 0x60300008, // 0035 GETGBL R12 G8 + 0x5C340A00, // 0036 MOVE R13 R5 + 0x7C300200, // 0037 CALL R12 1 + 0x0032140C, // 0038 ADD R12 K10 R12 + 0x0030190B, // 0039 ADD R12 R12 K11 + 0x00301806, // 003A ADD R12 R12 R6 + 0x7C2C0200, // 003B CALL R11 1 + 0x80001600, // 003C RET 0 + 0x4C2C0000, // 003D LDNIL R11 + 0x60300009, // 003E GETGBL R12 G9 + 0x8C340302, // 003F GETMET R13 R1 K2 + 0x583C000C, // 0040 LDCONST R15 K12 + 0x7C340400, // 0041 CALL R13 2 + 0x7C300200, // 0042 CALL R12 1 + 0x4C340000, // 0043 LDNIL R13 + 0x2034180D, // 0044 NE R13 R12 R13 + 0x78360006, // 0045 JMPF R13 #004D + 0x8C34110D, // 0046 GETMET R13 R8 K13 + 0x5C3C1800, // 0047 MOVE R15 R12 + 0x7C340400, // 0048 CALL R13 2 + 0x4C380000, // 0049 LDNIL R14 + 0x20381A0E, // 004A NE R14 R13 R14 + 0x783A0000, // 004B JMPF R14 #004D + 0x882C1B0E, // 004C GETMBR R11 R13 K14 + 0x4C340000, // 004D LDNIL R13 + 0x1C34160D, // 004E EQ R13 R11 R13 + 0x78360002, // 004F JMPF R13 #0053 + 0x8C34110F, // 0050 GETMET R13 R8 K15 + 0x7C340200, // 0051 CALL R13 1 + 0x5C2C1A00, // 0052 MOVE R11 R13 + 0x8C340910, // 0053 GETMET R13 R4 K16 + 0x5C3C0000, // 0054 MOVE R15 R0 + 0x00422206, // 0055 ADD R16 K17 R6 + 0x7C340600, // 0056 CALL R13 3 + 0x4C380000, // 0057 LDNIL R14 + 0x4C3C0000, // 0058 LDNIL R15 + 0x1C3C1A0F, // 0059 EQ R15 R13 R15 + 0x783E0010, // 005A JMPF R15 #006C + 0x8C3C0910, // 005B GETMET R15 R4 K16 + 0x5C440600, // 005C MOVE R17 R3 + 0x5C480C00, // 005D MOVE R18 R6 + 0x7C3C0600, // 005E CALL R15 3 + 0x4C400000, // 005F LDNIL R16 + 0x20401E10, // 0060 NE R16 R15 R16 + 0x78420009, // 0061 JMPF R16 #006C + 0x60400004, // 0062 GETGBL R16 G4 + 0x5C441E00, // 0063 MOVE R17 R15 + 0x7C400200, // 0064 CALL R16 1 + 0x1C402112, // 0065 EQ R16 R16 K18 + 0x78420004, // 0066 JMPF R16 #006C + 0x5C401E00, // 0067 MOVE R16 R15 + 0x5C441600, // 0068 MOVE R17 R11 + 0x7C400200, // 0069 CALL R16 1 + 0x5C382000, // 006A MOVE R14 R16 + 0x88340113, // 006B GETMBR R13 R0 K19 + 0x4C3C0000, // 006C LDNIL R15 + 0x1C3C1A0F, // 006D EQ R15 R13 R15 + 0x783E000F, // 006E JMPF R15 #007F + 0x8C3C0914, // 006F GETMET R15 R4 K20 + 0x5C440C00, // 0070 MOVE R17 R6 + 0x7C3C0400, // 0071 CALL R15 2 + 0x4C400000, // 0072 LDNIL R16 + 0x20401E10, // 0073 NE R16 R15 R16 + 0x78420009, // 0074 JMPF R16 #007F + 0x60400004, // 0075 GETGBL R16 G4 + 0x5C441E00, // 0076 MOVE R17 R15 + 0x7C400200, // 0077 CALL R16 1 + 0x1C402112, // 0078 EQ R16 R16 K18 + 0x78420004, // 0079 JMPF R16 #007F + 0x5C401E00, // 007A MOVE R16 R15 + 0x5C441600, // 007B MOVE R17 R11 + 0x7C400200, // 007C CALL R16 1 + 0x5C382000, // 007D MOVE R14 R16 + 0x88340113, // 007E GETMBR R13 R0 K19 + 0x4C3C0000, // 007F LDNIL R15 + 0x1C3C1A0F, // 0080 EQ R15 R13 R15 + 0x783E0006, // 0081 JMPF R15 #0089 + 0x603C0001, // 0082 GETGBL R15 G1 + 0x60400008, // 0083 GETGBL R16 G8 + 0x5C440C00, // 0084 MOVE R17 R6 + 0x7C400200, // 0085 CALL R16 1 + 0x00422A10, // 0086 ADD R16 K21 R16 + 0x7C3C0200, // 0087 CALL R15 1 + 0x80001E00, // 0088 RET 0 + 0x5C3C1A00, // 0089 MOVE R15 R13 + 0x5C401600, // 008A MOVE R16 R11 + 0x5C440400, // 008B MOVE R17 R2 + 0x5C480200, // 008C MOVE R18 R1 + 0x5C4C1C00, // 008D MOVE R19 R14 + 0x7C3C0800, // 008E CALL R15 4 + 0x5C1C1E00, // 008F MOVE R7 R15 + 0x8C3C1116, // 0090 GETMET R15 R8 K22 + 0x5C440A00, // 0091 MOVE R17 R5 + 0x5C480E00, // 0092 MOVE R18 R7 + 0x7C3C0600, // 0093 CALL R15 3 + 0x603C0018, // 0094 GETGBL R15 G24 + 0x58400017, // 0095 LDCONST R16 K23 + 0x8C441103, // 0096 GETMET R17 R8 K3 + 0x7C440200, // 0097 CALL R17 1 + 0x5C480A00, // 0098 MOVE R18 R5 + 0x7C3C0600, // 0099 CALL R15 3 + 0x900C1E07, // 009A SETMBR R3 R15 R7 + 0x4C2C0000, // 009B LDNIL R11 + 0x202C140B, // 009C NE R11 R10 R11 + 0x782E0018, // 009D JMPF R11 #00B7 + 0xA802000B, // 009E EXBLK 0 #00AB + 0x5C2C1400, // 009F MOVE R11 R10 + 0x7C2C0000, // 00A0 CALL R11 0 + 0x60300004, // 00A1 GETGBL R12 G4 + 0x5C341600, // 00A2 MOVE R13 R11 + 0x7C300200, // 00A3 CALL R12 1 + 0x1C301918, // 00A4 EQ R12 R12 K24 + 0x78320002, // 00A5 JMPF R12 #00A9 + 0x5C301600, // 00A6 MOVE R12 R11 + 0x5C340E00, // 00A7 MOVE R13 R7 + 0x7C300200, // 00A8 CALL R12 1 + 0xA8040001, // 00A9 EXBLK 1 1 + 0x7002000B, // 00AA JMP #00B7 + 0xAC2C0002, // 00AB CATCH R11 0 2 + 0x70020008, // 00AC JMP #00B6 + 0x60340001, // 00AD GETGBL R13 G1 + 0x60380018, // 00AE GETGBL R14 G24 + 0x583C0019, // 00AF LDCONST R15 K25 + 0x5C401200, // 00B0 MOVE R16 R9 + 0x5C441600, // 00B1 MOVE R17 R11 + 0x5C481800, // 00B2 MOVE R18 R12 + 0x7C380800, // 00B3 CALL R14 4 + 0x7C340200, // 00B4 CALL R13 1 + 0x70020000, // 00B5 JMP #00B7 + 0xB0080000, // 00B6 RAISE 2 R0 R0 + 0x4C2C0000, // 00B7 LDNIL R11 + 0x1C2C0A0B, // 00B8 EQ R11 R5 R11 + 0x782E0000, // 00B9 JMPF R11 #00BB + 0x80001600, // 00BA RET 0 + 0x1C2C0B1A, // 00BB EQ R11 R5 K26 + 0x782E0005, // 00BC JMPF R11 #00C3 + 0x202C0D07, // 00BD NE R11 R6 K7 + 0x782E0003, // 00BE JMPF R11 #00C3 + 0x602C0001, // 00BF GETGBL R11 G1 + 0x5830001B, // 00C0 LDCONST R12 K27 + 0x7C2C0200, // 00C1 CALL R11 1 + 0x80001600, // 00C2 RET 0 + 0x1C2C0B1A, // 00C3 EQ R11 R5 K26 + 0x782E0005, // 00C4 JMPF R11 #00CB + 0x8C2C0105, // 00C5 GETMET R11 R0 K5 + 0x7C2C0200, // 00C6 CALL R11 1 + 0x8C2C170D, // 00C7 GETMET R11 R11 K13 + 0x5834001A, // 00C8 LDCONST R13 K26 + 0x7C2C0400, // 00C9 CALL R11 2 + 0x5C1C1600, // 00CA MOVE R7 R11 + 0x602C0010, // 00CB GETGBL R11 G16 + 0x8C30031C, // 00CC GETMET R12 R1 K28 + 0x7C300200, // 00CD CALL R12 1 + 0x7C2C0200, // 00CE CALL R11 1 + 0xA8020004, // 00CF EXBLK 0 #00D5 + 0x5C301600, // 00D0 MOVE R12 R11 + 0x7C300000, // 00D1 CALL R12 0 + 0x9434020C, // 00D2 GETIDX R13 R1 R12 + 0x901C180D, // 00D3 SETMBR R7 R12 R13 + 0x7001FFFA, // 00D4 JMP #00D0 + 0x582C001D, // 00D5 LDCONST R11 K29 + 0xAC2C0200, // 00D6 CATCH R11 1 0 + 0xB0080000, // 00D7 RAISE 2 R0 R0 + 0x80000000, // 00D8 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: do_action +********************************************************************/ +be_local_closure(HASPmota_do_action, /* name */ + be_nested_proto( + 6, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_nested_str_weak(lv), + /* K1 */ be_nested_str_weak(EVENT_CLICKED), + /* K2 */ be_nested_str_weak(page_show), + /* K3 */ be_nested_str_weak(_action), + }), + be_str_weak(do_action), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0xB80E0000, // 0000 GETNGBL R3 K0 + 0x880C0701, // 0001 GETMBR R3 R3 K1 + 0x200C0403, // 0002 NE R3 R2 R3 + 0x780E0000, // 0003 JMPF R3 #0005 + 0x80000600, // 0004 RET 0 + 0x8C0C0102, // 0005 GETMET R3 R0 K2 + 0x88140303, // 0006 GETMBR R5 R1 K3 + 0x7C0C0400, // 0007 CALL R3 2 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: pages_list_sorted ********************************************************************/ @@ -7178,11 +7941,99 @@ be_local_closure(HASPmota_pages_list_sorted, /* name */ /******************************************************************** -** Solidified function: parse +** Solidified function: get_page_cur ********************************************************************/ -be_local_closure(HASPmota_parse, /* name */ +be_local_closure(HASPmota_get_page_cur, /* name */ be_nested_proto( - 9, /* nstack */ + 3, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(lvh_pages), + /* K1 */ be_nested_str_weak(lvh_page_cur_idx), + }), + be_str_weak(get_page_cur), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x88080101, // 0001 GETMBR R2 R0 K1 + 0x94040202, // 0002 GETIDX R1 R1 R2 + 0x80040200, // 0003 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: sort +********************************************************************/ +be_local_closure(HASPmota_sort, /* name */ + be_nested_proto( + 7, /* nstack */ + 1, /* argc */ + 4, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_const_class(be_class_HASPmota), + /* K1 */ be_const_int(1), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(sort), + &be_const_str_solidified, + ( &(const binstruction[30]) { /* code */ + 0x58040000, // 0000 LDCONST R1 K0 + 0x60080010, // 0001 GETGBL R2 G16 + 0x600C000C, // 0002 GETGBL R3 G12 + 0x5C100000, // 0003 MOVE R4 R0 + 0x7C0C0200, // 0004 CALL R3 1 + 0x040C0701, // 0005 SUB R3 R3 K1 + 0x400E0203, // 0006 CONNECT R3 K1 R3 + 0x7C080200, // 0007 CALL R2 1 + 0xA8020010, // 0008 EXBLK 0 #001A + 0x5C0C0400, // 0009 MOVE R3 R2 + 0x7C0C0000, // 000A CALL R3 0 + 0x94100003, // 000B GETIDX R4 R0 R3 + 0x5C140600, // 000C MOVE R5 R3 + 0x24180B02, // 000D GT R6 R5 K2 + 0x781A0008, // 000E JMPF R6 #0018 + 0x04180B01, // 000F SUB R6 R5 K1 + 0x94180006, // 0010 GETIDX R6 R0 R6 + 0x24180C04, // 0011 GT R6 R6 R4 + 0x781A0004, // 0012 JMPF R6 #0018 + 0x04180B01, // 0013 SUB R6 R5 K1 + 0x94180006, // 0014 GETIDX R6 R0 R6 + 0x98000A06, // 0015 SETIDX R0 R5 R6 + 0x04140B01, // 0016 SUB R5 R5 K1 + 0x7001FFF4, // 0017 JMP #000D + 0x98000A04, // 0018 SETIDX R0 R5 R4 + 0x7001FFEE, // 0019 JMP #0009 + 0x58080003, // 001A LDCONST R2 K3 + 0xAC080200, // 001B CATCH R2 1 0 + 0xB0080000, // 001C RAISE 2 R0 R0 + 0x80040000, // 001D RET 1 R0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: _load +********************************************************************/ +be_local_closure(HASPmota__load, /* name */ + be_nested_proto( + 17, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -7190,41 +8041,266 @@ be_local_closure(HASPmota_parse, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(json), - /* K1 */ be_nested_str_weak(load), - /* K2 */ be_nested_str_weak(instance), - /* K3 */ be_nested_str_weak(parse_page), - /* K4 */ be_nested_str_weak(parse_obj), + ( &(const bvalue[26]) { /* constants */ + /* K0 */ be_nested_str_weak(string), + /* K1 */ be_nested_str_weak(json), + /* K2 */ be_nested_str_weak(lvh_page_cur_idx), + /* K3 */ be_const_int(1), + /* K4 */ be_nested_str_weak(lvh_page), /* K5 */ be_nested_str_weak(lvh_pages), - /* K6 */ be_nested_str_weak(lvh_page_cur_idx), - /* K7 */ be_nested_str_weak(value_error), - /* K8 */ be_nested_str_weak(unable_X20to_X20parse_X20JSON_X20line), + /* K6 */ be_nested_str_weak(r), + /* K7 */ be_nested_str_weak(read), + /* K8 */ be_nested_str_weak(close), + /* K9 */ be_nested_str_weak(split), + /* K10 */ be_nested_str_weak(_X0A), + /* K11 */ be_const_int(0), + /* K12 */ be_nested_str_weak(load), + /* K13 */ be_nested_str_weak(instance), + /* K14 */ be_nested_str_weak(tasmota), + /* K15 */ be_nested_str_weak(loglevel), + /* K16 */ be_nested_str_weak(log), + /* K17 */ be_nested_str_weak(HSP_X3A_X20parsing_X20line_X20_X27_X25s_X27_X20tasmota_X2Eloglevel_X284_X29_X3D_X25s), + /* K18 */ be_nested_str_weak(parse_page), + /* K19 */ be_nested_str_weak(parse_obj), + /* K20 */ be_nested_str_weak(tr), + /* K21 */ be_nested_str_weak(_X20_X09), + /* K22 */ be_nested_str_weak(), + /* K23 */ be_nested_str_weak(HSP_X3A_X20invalid_X20JSON_X20line_X20_X27_X25s_X27), + /* K24 */ be_const_int(2), + /* K25 */ be_nested_str_weak(remove), }), - be_str_weak(parse), + be_str_weak(_load), &be_const_str_solidified, - ( &(const binstruction[21]) { /* code */ + ( &(const binstruction[89]) { /* code */ 0xA40A0000, // 0000 IMPORT R2 K0 - 0x8C0C0501, // 0001 GETMET R3 R2 K1 - 0x5C140200, // 0002 MOVE R5 R1 - 0x7C0C0400, // 0003 CALL R3 2 - 0x60100004, // 0004 GETGBL R4 G4 - 0x5C140600, // 0005 MOVE R5 R3 - 0x7C100200, // 0006 CALL R4 1 - 0x1C100902, // 0007 EQ R4 R4 K2 - 0x78120009, // 0008 JMPF R4 #0013 - 0x8C100103, // 0009 GETMET R4 R0 K3 - 0x5C180600, // 000A MOVE R6 R3 - 0x7C100400, // 000B CALL R4 2 - 0x8C100104, // 000C GETMET R4 R0 K4 - 0x5C180600, // 000D MOVE R6 R3 - 0x881C0105, // 000E GETMBR R7 R0 K5 - 0x88200106, // 000F GETMBR R8 R0 K6 - 0x941C0E08, // 0010 GETIDX R7 R7 R8 - 0x7C100600, // 0011 CALL R4 3 - 0x70020000, // 0012 JMP #0014 - 0xB0060F08, // 0013 RAISE 1 K7 K8 - 0x80000000, // 0014 RET 0 + 0xA40E0200, // 0001 IMPORT R3 K1 + 0x90020503, // 0002 SETMBR R0 K2 K3 + 0x88100104, // 0003 GETMBR R4 R0 K4 + 0x88140105, // 0004 GETMBR R5 R0 K5 + 0x5C180800, // 0005 MOVE R6 R4 + 0x581C0003, // 0006 LDCONST R7 K3 + 0x5C200000, // 0007 MOVE R8 R0 + 0x7C180400, // 0008 CALL R6 2 + 0x98160606, // 0009 SETIDX R5 K3 R6 + 0x60140011, // 000A GETGBL R5 G17 + 0x5C180200, // 000B MOVE R6 R1 + 0x581C0006, // 000C LDCONST R7 K6 + 0x7C140400, // 000D CALL R5 2 + 0x8C180B07, // 000E GETMET R6 R5 K7 + 0x7C180200, // 000F CALL R6 1 + 0x8C1C0B08, // 0010 GETMET R7 R5 K8 + 0x7C1C0200, // 0011 CALL R7 1 + 0x8C1C0509, // 0012 GETMET R7 R2 K9 + 0x5C240C00, // 0013 MOVE R9 R6 + 0x5828000A, // 0014 LDCONST R10 K10 + 0x7C1C0600, // 0015 CALL R7 3 + 0x4C140000, // 0016 LDNIL R5 + 0x4C180000, // 0017 LDNIL R6 + 0x6020000C, // 0018 GETGBL R8 G12 + 0x5C240E00, // 0019 MOVE R9 R7 + 0x7C200200, // 001A CALL R8 1 + 0x2420110B, // 001B GT R8 R8 K11 + 0x78220038, // 001C JMPF R8 #0056 + 0x8C20070C, // 001D GETMET R8 R3 K12 + 0x94280F0B, // 001E GETIDX R10 R7 K11 + 0x7C200400, // 001F CALL R8 2 + 0x60240004, // 0020 GETGBL R9 G4 + 0x5C281000, // 0021 MOVE R10 R8 + 0x7C240200, // 0022 CALL R9 1 + 0x1C24130D, // 0023 EQ R9 R9 K13 + 0x7826001A, // 0024 JMPF R9 #0040 + 0xB8261C00, // 0025 GETNGBL R9 K14 + 0x8C24130F, // 0026 GETMET R9 R9 K15 + 0x542E0003, // 0027 LDINT R11 4 + 0x7C240400, // 0028 CALL R9 2 + 0x7826000B, // 0029 JMPF R9 #0036 + 0xB8261C00, // 002A GETNGBL R9 K14 + 0x8C241310, // 002B GETMET R9 R9 K16 + 0x602C0018, // 002C GETGBL R11 G24 + 0x58300011, // 002D LDCONST R12 K17 + 0x94340F0B, // 002E GETIDX R13 R7 K11 + 0xB83A1C00, // 002F GETNGBL R14 K14 + 0x8C381D0F, // 0030 GETMET R14 R14 K15 + 0x54420003, // 0031 LDINT R16 4 + 0x7C380400, // 0032 CALL R14 2 + 0x7C2C0600, // 0033 CALL R11 3 + 0x54320003, // 0034 LDINT R12 4 + 0x7C240600, // 0035 CALL R9 3 + 0x8C240112, // 0036 GETMET R9 R0 K18 + 0x5C2C1000, // 0037 MOVE R11 R8 + 0x7C240400, // 0038 CALL R9 2 + 0x8C240113, // 0039 GETMET R9 R0 K19 + 0x5C2C1000, // 003A MOVE R11 R8 + 0x88300105, // 003B GETMBR R12 R0 K5 + 0x88340102, // 003C GETMBR R13 R0 K2 + 0x9430180D, // 003D GETIDX R12 R12 R13 + 0x7C240600, // 003E CALL R9 3 + 0x70020010, // 003F JMP #0051 + 0x6024000C, // 0040 GETGBL R9 G12 + 0x8C280514, // 0041 GETMET R10 R2 K20 + 0x94300F0B, // 0042 GETIDX R12 R7 K11 + 0x58340015, // 0043 LDCONST R13 K21 + 0x58380016, // 0044 LDCONST R14 K22 + 0x7C280800, // 0045 CALL R10 4 + 0x7C240200, // 0046 CALL R9 1 + 0x2424130B, // 0047 GT R9 R9 K11 + 0x78260007, // 0048 JMPF R9 #0051 + 0xB8261C00, // 0049 GETNGBL R9 K14 + 0x8C241310, // 004A GETMET R9 R9 K16 + 0x602C0018, // 004B GETGBL R11 G24 + 0x58300017, // 004C LDCONST R12 K23 + 0x94340F0B, // 004D GETIDX R13 R7 K11 + 0x7C2C0400, // 004E CALL R11 2 + 0x58300018, // 004F LDCONST R12 K24 + 0x7C240600, // 0050 CALL R9 3 + 0x4C200000, // 0051 LDNIL R8 + 0x8C240F19, // 0052 GETMET R9 R7 K25 + 0x582C000B, // 0053 LDCONST R11 K11 + 0x7C240400, // 0054 CALL R9 2 + 0x7001FFC1, // 0055 JMP #0018 + 0x4C1C0000, // 0056 LDNIL R7 + 0x90020503, // 0057 SETMBR R0 K2 K3 + 0x80000000, // 0058 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(HASPmota_init, /* name */ + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(fix_lv_version), + /* K1 */ be_nested_str_weak(re), + /* K2 */ be_nested_str_weak(re_page_target), + /* K3 */ be_nested_str_weak(compile), + /* K4 */ be_nested_str_weak(p_X5Cd_X2B), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x8C040100, // 0000 GETMET R1 R0 K0 + 0x7C040200, // 0001 CALL R1 1 + 0xA4060200, // 0002 IMPORT R1 K1 + 0x8C080303, // 0003 GETMET R2 R1 K3 + 0x58100004, // 0004 LDCONST R4 K4 + 0x7C080400, // 0005 CALL R2 2 + 0x90020402, // 0006 SETMBR R0 K2 R2 + 0x80000000, // 0007 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: page_show +********************************************************************/ +be_local_closure(HASPmota_page_show, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_str_weak(lvh_pages), + /* K1 */ be_nested_str_weak(lvh_page_cur_idx), + /* K2 */ be_nested_str_weak(pages_list_sorted), + /* K3 */ be_const_int(1), + /* K4 */ be_nested_str_weak(prev), + /* K5 */ be_nested_str_weak(next), + /* K6 */ be_nested_str_weak(back), + /* K7 */ be_nested_str_weak(re_page_target), + /* K8 */ be_nested_str_weak(match), + /* K9 */ be_const_int(0), + /* K10 */ be_nested_str_weak(show), + }), + be_str_weak(page_show), + &be_const_str_solidified, + ( &(const binstruction[68]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x880C0100, // 0001 GETMBR R3 R0 K0 + 0x88100101, // 0002 GETMBR R4 R0 K1 + 0x940C0604, // 0003 GETIDX R3 R3 R4 + 0x8C100102, // 0004 GETMET R4 R0 K2 + 0x88180101, // 0005 GETMBR R6 R0 K1 + 0x7C100400, // 0006 CALL R4 2 + 0x6014000C, // 0007 GETGBL R5 G12 + 0x5C180800, // 0008 MOVE R6 R4 + 0x7C140200, // 0009 CALL R5 1 + 0x18140B03, // 000A LE R5 R5 K3 + 0x78160000, // 000B JMPF R5 #000D + 0x80000A00, // 000C RET 0 + 0x1C140304, // 000D EQ R5 R1 K4 + 0x78160009, // 000E JMPF R5 #0019 + 0x60140009, // 000F GETGBL R5 G9 + 0x88180704, // 0010 GETMBR R6 R3 K4 + 0x7C140200, // 0011 CALL R5 1 + 0x5C080A00, // 0012 MOVE R2 R5 + 0x4C140000, // 0013 LDNIL R5 + 0x1C140405, // 0014 EQ R5 R2 R5 + 0x78160001, // 0015 JMPF R5 #0018 + 0x5415FFFE, // 0016 LDINT R5 -1 + 0x94080805, // 0017 GETIDX R2 R4 R5 + 0x70020020, // 0018 JMP #003A + 0x1C140305, // 0019 EQ R5 R1 K5 + 0x78160008, // 001A JMPF R5 #0024 + 0x60140009, // 001B GETGBL R5 G9 + 0x88180705, // 001C GETMBR R6 R3 K5 + 0x7C140200, // 001D CALL R5 1 + 0x5C080A00, // 001E MOVE R2 R5 + 0x4C140000, // 001F LDNIL R5 + 0x1C140405, // 0020 EQ R5 R2 R5 + 0x78160000, // 0021 JMPF R5 #0023 + 0x94080903, // 0022 GETIDX R2 R4 K3 + 0x70020015, // 0023 JMP #003A + 0x1C140306, // 0024 EQ R5 R1 K6 + 0x78160008, // 0025 JMPF R5 #002F + 0x60140009, // 0026 GETGBL R5 G9 + 0x88180706, // 0027 GETMBR R6 R3 K6 + 0x7C140200, // 0028 CALL R5 1 + 0x5C080A00, // 0029 MOVE R2 R5 + 0x4C140000, // 002A LDNIL R5 + 0x1C140405, // 002B EQ R5 R2 R5 + 0x78160000, // 002C JMPF R5 #002E + 0x58080003, // 002D LDCONST R2 K3 + 0x7002000A, // 002E JMP #003A + 0x88140107, // 002F GETMBR R5 R0 K7 + 0x8C140B08, // 0030 GETMET R5 R5 K8 + 0x5C1C0200, // 0031 MOVE R7 R1 + 0x7C140400, // 0032 CALL R5 2 + 0x78160005, // 0033 JMPF R5 #003A + 0x60140009, // 0034 GETGBL R5 G9 + 0x5419FFFE, // 0035 LDINT R6 -1 + 0x401A0606, // 0036 CONNECT R6 K3 R6 + 0x94180206, // 0037 GETIDX R6 R1 R6 + 0x7C140200, // 0038 CALL R5 1 + 0x5C080A00, // 0039 MOVE R2 R5 + 0x4C140000, // 003A LDNIL R5 + 0x20140405, // 003B NE R5 R2 R5 + 0x78160005, // 003C JMPF R5 #0043 + 0x24140509, // 003D GT R5 R2 K9 + 0x78160003, // 003E JMPF R5 #0043 + 0x88140100, // 003F GETMBR R5 R0 K0 + 0x94140A02, // 0040 GETIDX R5 R5 R2 + 0x8C140B0A, // 0041 GETMET R5 R5 K10 + 0x7C140200, // 0042 CALL R5 1 + 0x80000000, // 0043 RET 0 }) ) ); @@ -7393,173 +8469,6 @@ be_local_closure(HASPmota_start, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: page_show -********************************************************************/ -be_local_closure(HASPmota_page_show, /* name */ - be_nested_proto( - 8, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ - /* K0 */ be_nested_str_weak(lvh_pages), - /* K1 */ be_nested_str_weak(lvh_page_cur_idx), - /* K2 */ be_nested_str_weak(pages_list_sorted), - /* K3 */ be_const_int(1), - /* K4 */ be_nested_str_weak(prev), - /* K5 */ be_nested_str_weak(next), - /* K6 */ be_nested_str_weak(back), - /* K7 */ be_nested_str_weak(re_page_target), - /* K8 */ be_nested_str_weak(match), - /* K9 */ be_const_int(0), - /* K10 */ be_nested_str_weak(show), - }), - be_str_weak(page_show), - &be_const_str_solidified, - ( &(const binstruction[68]) { /* code */ - 0x4C080000, // 0000 LDNIL R2 - 0x880C0100, // 0001 GETMBR R3 R0 K0 - 0x88100101, // 0002 GETMBR R4 R0 K1 - 0x940C0604, // 0003 GETIDX R3 R3 R4 - 0x8C100102, // 0004 GETMET R4 R0 K2 - 0x88180101, // 0005 GETMBR R6 R0 K1 - 0x7C100400, // 0006 CALL R4 2 - 0x6014000C, // 0007 GETGBL R5 G12 - 0x5C180800, // 0008 MOVE R6 R4 - 0x7C140200, // 0009 CALL R5 1 - 0x18140B03, // 000A LE R5 R5 K3 - 0x78160000, // 000B JMPF R5 #000D - 0x80000A00, // 000C RET 0 - 0x1C140304, // 000D EQ R5 R1 K4 - 0x78160009, // 000E JMPF R5 #0019 - 0x60140009, // 000F GETGBL R5 G9 - 0x88180704, // 0010 GETMBR R6 R3 K4 - 0x7C140200, // 0011 CALL R5 1 - 0x5C080A00, // 0012 MOVE R2 R5 - 0x4C140000, // 0013 LDNIL R5 - 0x1C140405, // 0014 EQ R5 R2 R5 - 0x78160001, // 0015 JMPF R5 #0018 - 0x5415FFFE, // 0016 LDINT R5 -1 - 0x94080805, // 0017 GETIDX R2 R4 R5 - 0x70020020, // 0018 JMP #003A - 0x1C140305, // 0019 EQ R5 R1 K5 - 0x78160008, // 001A JMPF R5 #0024 - 0x60140009, // 001B GETGBL R5 G9 - 0x88180705, // 001C GETMBR R6 R3 K5 - 0x7C140200, // 001D CALL R5 1 - 0x5C080A00, // 001E MOVE R2 R5 - 0x4C140000, // 001F LDNIL R5 - 0x1C140405, // 0020 EQ R5 R2 R5 - 0x78160000, // 0021 JMPF R5 #0023 - 0x94080903, // 0022 GETIDX R2 R4 K3 - 0x70020015, // 0023 JMP #003A - 0x1C140306, // 0024 EQ R5 R1 K6 - 0x78160008, // 0025 JMPF R5 #002F - 0x60140009, // 0026 GETGBL R5 G9 - 0x88180706, // 0027 GETMBR R6 R3 K6 - 0x7C140200, // 0028 CALL R5 1 - 0x5C080A00, // 0029 MOVE R2 R5 - 0x4C140000, // 002A LDNIL R5 - 0x1C140405, // 002B EQ R5 R2 R5 - 0x78160000, // 002C JMPF R5 #002E - 0x58080003, // 002D LDCONST R2 K3 - 0x7002000A, // 002E JMP #003A - 0x88140107, // 002F GETMBR R5 R0 K7 - 0x8C140B08, // 0030 GETMET R5 R5 K8 - 0x5C1C0200, // 0031 MOVE R7 R1 - 0x7C140400, // 0032 CALL R5 2 - 0x78160005, // 0033 JMPF R5 #003A - 0x60140009, // 0034 GETGBL R5 G9 - 0x5419FFFE, // 0035 LDINT R6 -1 - 0x401A0606, // 0036 CONNECT R6 K3 R6 - 0x94180206, // 0037 GETIDX R6 R1 R6 - 0x7C140200, // 0038 CALL R5 1 - 0x5C080A00, // 0039 MOVE R2 R5 - 0x4C140000, // 003A LDNIL R5 - 0x20140405, // 003B NE R5 R2 R5 - 0x78160005, // 003C JMPF R5 #0043 - 0x24140509, // 003D GT R5 R2 K9 - 0x78160003, // 003E JMPF R5 #0043 - 0x88140100, // 003F GETMBR R5 R0 K0 - 0x94140A02, // 0040 GETIDX R5 R5 R2 - 0x8C140B0A, // 0041 GETMET R5 R5 K10 - 0x7C140200, // 0042 CALL R5 1 - 0x80000000, // 0043 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(HASPmota_init, /* name */ - be_nested_proto( - 5, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(re), - /* K1 */ be_nested_str_weak(re_page_target), - /* K2 */ be_nested_str_weak(compile), - /* K3 */ be_nested_str_weak(p_X5Cd_X2B), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0x8C080302, // 0001 GETMET R2 R1 K2 - 0x58100003, // 0002 LDCONST R4 K3 - 0x7C080400, // 0003 CALL R2 2 - 0x90020202, // 0004 SETMBR R0 K1 R2 - 0x80000000, // 0005 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_page_cur -********************************************************************/ -be_local_closure(HASPmota_get_page_cur, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(lvh_pages), - /* K1 */ be_nested_str_weak(lvh_page_cur_idx), - }), - be_str_weak(get_page_cur), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x88080101, // 0001 GETMBR R2 R0 K1 - 0x94040202, // 0002 GETIDX R1 R1 R2 - 0x80040200, // 0003 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: deinit ********************************************************************/ @@ -7607,743 +8516,60 @@ be_local_closure(HASPmota_deinit, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: event_dispatch -********************************************************************/ -be_local_closure(HASPmota_event_dispatch, /* name */ - be_nested_proto( - 9, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ - /* K0 */ be_nested_str_weak(introspect), - /* K1 */ be_nested_str_weak(toptr), - /* K2 */ be_nested_str_weak(event), - /* K3 */ be_nested_str_weak(_change_buffer), - /* K4 */ be_nested_str_weak(lv), - /* K5 */ be_nested_str_weak(lv_event), - /* K6 */ be_nested_str_weak(user_data), - /* K7 */ be_const_int(0), - /* K8 */ be_nested_str_weak(fromptr), - /* K9 */ be_nested_str_weak(instance), - /* K10 */ be_nested_str_weak(event_cb), - }), - be_str_weak(event_dispatch), - &be_const_str_solidified, - ( &(const binstruction[35]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0x8C0C0501, // 0001 GETMET R3 R2 K1 - 0x5C140200, // 0002 MOVE R5 R1 - 0x7C0C0400, // 0003 CALL R3 2 - 0x88100102, // 0004 GETMBR R4 R0 K2 - 0x78120004, // 0005 JMPF R4 #000B - 0x88100102, // 0006 GETMBR R4 R0 K2 - 0x8C100903, // 0007 GETMET R4 R4 K3 - 0x5C180600, // 0008 MOVE R6 R3 - 0x7C100400, // 0009 CALL R4 2 - 0x70020004, // 000A JMP #0010 - 0xB8120800, // 000B GETNGBL R4 K4 - 0x8C100905, // 000C GETMET R4 R4 K5 - 0x5C180600, // 000D MOVE R6 R3 - 0x7C100400, // 000E CALL R4 2 - 0x90020404, // 000F SETMBR R0 K2 R4 - 0x88100102, // 0010 GETMBR R4 R0 K2 - 0x88100906, // 0011 GETMBR R4 R4 K6 - 0x60140009, // 0012 GETGBL R5 G9 - 0x5C180800, // 0013 MOVE R6 R4 - 0x7C140200, // 0014 CALL R5 1 - 0x20140B07, // 0015 NE R5 R5 K7 - 0x7816000A, // 0016 JMPF R5 #0022 - 0x8C140508, // 0017 GETMET R5 R2 K8 - 0x5C1C0800, // 0018 MOVE R7 R4 - 0x7C140400, // 0019 CALL R5 2 - 0x60180004, // 001A GETGBL R6 G4 - 0x5C1C0A00, // 001B MOVE R7 R5 - 0x7C180200, // 001C CALL R6 1 - 0x1C180D09, // 001D EQ R6 R6 K9 - 0x781A0002, // 001E JMPF R6 #0022 - 0x8C180B0A, // 001F GETMET R6 R5 K10 - 0x88200102, // 0020 GETMBR R8 R0 K2 - 0x7C180400, // 0021 CALL R6 2 - 0x80000000, // 0022 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: do_action -********************************************************************/ -be_local_closure(HASPmota_do_action, /* name */ - be_nested_proto( - 6, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(lv), - /* K1 */ be_nested_str_weak(EVENT_CLICKED), - /* K2 */ be_nested_str_weak(page_show), - /* K3 */ be_nested_str_weak(_action), - }), - be_str_weak(do_action), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0xB80E0000, // 0000 GETNGBL R3 K0 - 0x880C0701, // 0001 GETMBR R3 R3 K1 - 0x200C0403, // 0002 NE R3 R2 R3 - 0x780E0000, // 0003 JMPF R3 #0005 - 0x80000600, // 0004 RET 0 - 0x8C0C0102, // 0005 GETMET R3 R0 K2 - 0x88140303, // 0006 GETMBR R5 R1 K3 - 0x7C0C0400, // 0007 CALL R3 2 - 0x80000000, // 0008 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: sort -********************************************************************/ -be_local_closure(HASPmota_sort, /* name */ - be_nested_proto( - 7, /* nstack */ - 1, /* argc */ - 4, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_const_class(be_class_HASPmota), - /* K1 */ be_const_int(1), - /* K2 */ be_const_int(0), - /* K3 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(sort), - &be_const_str_solidified, - ( &(const binstruction[30]) { /* code */ - 0x58040000, // 0000 LDCONST R1 K0 - 0x60080010, // 0001 GETGBL R2 G16 - 0x600C000C, // 0002 GETGBL R3 G12 - 0x5C100000, // 0003 MOVE R4 R0 - 0x7C0C0200, // 0004 CALL R3 1 - 0x040C0701, // 0005 SUB R3 R3 K1 - 0x400E0203, // 0006 CONNECT R3 K1 R3 - 0x7C080200, // 0007 CALL R2 1 - 0xA8020010, // 0008 EXBLK 0 #001A - 0x5C0C0400, // 0009 MOVE R3 R2 - 0x7C0C0000, // 000A CALL R3 0 - 0x94100003, // 000B GETIDX R4 R0 R3 - 0x5C140600, // 000C MOVE R5 R3 - 0x24180B02, // 000D GT R6 R5 K2 - 0x781A0008, // 000E JMPF R6 #0018 - 0x04180B01, // 000F SUB R6 R5 K1 - 0x94180006, // 0010 GETIDX R6 R0 R6 - 0x24180C04, // 0011 GT R6 R6 R4 - 0x781A0004, // 0012 JMPF R6 #0018 - 0x04180B01, // 0013 SUB R6 R5 K1 - 0x94180006, // 0014 GETIDX R6 R0 R6 - 0x98000A06, // 0015 SETIDX R0 R5 R6 - 0x04140B01, // 0016 SUB R5 R5 K1 - 0x7001FFF4, // 0017 JMP #000D - 0x98000A04, // 0018 SETIDX R0 R5 R4 - 0x7001FFEE, // 0019 JMP #0009 - 0x58080003, // 001A LDCONST R2 K3 - 0xAC080200, // 001B CATCH R2 1 0 - 0xB0080000, // 001C RAISE 2 R0 R0 - 0x80040000, // 001D RET 1 R0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: _load -********************************************************************/ -be_local_closure(HASPmota__load, /* name */ - be_nested_proto( - 14, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[17]) { /* constants */ - /* K0 */ be_nested_str_weak(string), - /* K1 */ be_nested_str_weak(json), - /* K2 */ be_nested_str_weak(lvh_page_cur_idx), - /* K3 */ be_const_int(1), - /* K4 */ be_nested_str_weak(lvh_page), - /* K5 */ be_nested_str_weak(lvh_pages), - /* K6 */ be_nested_str_weak(r), - /* K7 */ be_nested_str_weak(read), - /* K8 */ be_nested_str_weak(close), - /* K9 */ be_nested_str_weak(split), - /* K10 */ be_nested_str_weak(_X0A), - /* K11 */ be_const_int(0), - /* K12 */ be_nested_str_weak(load), - /* K13 */ be_nested_str_weak(instance), - /* K14 */ be_nested_str_weak(parse_page), - /* K15 */ be_nested_str_weak(parse_obj), - /* K16 */ be_nested_str_weak(remove), - }), - be_str_weak(_load), - &be_const_str_solidified, - ( &(const binstruction[54]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0xA40E0200, // 0001 IMPORT R3 K1 - 0x90020503, // 0002 SETMBR R0 K2 K3 - 0x88100104, // 0003 GETMBR R4 R0 K4 - 0x88140105, // 0004 GETMBR R5 R0 K5 - 0x5C180800, // 0005 MOVE R6 R4 - 0x581C0003, // 0006 LDCONST R7 K3 - 0x5C200000, // 0007 MOVE R8 R0 - 0x7C180400, // 0008 CALL R6 2 - 0x98160606, // 0009 SETIDX R5 K3 R6 - 0x60140011, // 000A GETGBL R5 G17 - 0x5C180200, // 000B MOVE R6 R1 - 0x581C0006, // 000C LDCONST R7 K6 - 0x7C140400, // 000D CALL R5 2 - 0x8C180B07, // 000E GETMET R6 R5 K7 - 0x7C180200, // 000F CALL R6 1 - 0x8C1C0B08, // 0010 GETMET R7 R5 K8 - 0x7C1C0200, // 0011 CALL R7 1 - 0x8C1C0509, // 0012 GETMET R7 R2 K9 - 0x5C240C00, // 0013 MOVE R9 R6 - 0x5828000A, // 0014 LDCONST R10 K10 - 0x7C1C0600, // 0015 CALL R7 3 - 0x4C140000, // 0016 LDNIL R5 - 0x4C180000, // 0017 LDNIL R6 - 0x6020000C, // 0018 GETGBL R8 G12 - 0x5C240E00, // 0019 MOVE R9 R7 - 0x7C200200, // 001A CALL R8 1 - 0x2420110B, // 001B GT R8 R8 K11 - 0x78220015, // 001C JMPF R8 #0033 - 0x8C20070C, // 001D GETMET R8 R3 K12 - 0x94280F0B, // 001E GETIDX R10 R7 K11 - 0x7C200400, // 001F CALL R8 2 - 0x60240004, // 0020 GETGBL R9 G4 - 0x5C281000, // 0021 MOVE R10 R8 - 0x7C240200, // 0022 CALL R9 1 - 0x1C24130D, // 0023 EQ R9 R9 K13 - 0x78260008, // 0024 JMPF R9 #002E - 0x8C24010E, // 0025 GETMET R9 R0 K14 - 0x5C2C1000, // 0026 MOVE R11 R8 - 0x7C240400, // 0027 CALL R9 2 - 0x8C24010F, // 0028 GETMET R9 R0 K15 - 0x5C2C1000, // 0029 MOVE R11 R8 - 0x88300105, // 002A GETMBR R12 R0 K5 - 0x88340102, // 002B GETMBR R13 R0 K2 - 0x9430180D, // 002C GETIDX R12 R12 R13 - 0x7C240600, // 002D CALL R9 3 - 0x4C200000, // 002E LDNIL R8 - 0x8C240F10, // 002F GETMET R9 R7 K16 - 0x582C000B, // 0030 LDCONST R11 K11 - 0x7C240400, // 0031 CALL R9 2 - 0x7001FFE4, // 0032 JMP #0018 - 0x4C1C0000, // 0033 LDNIL R7 - 0x90020503, // 0034 SETMBR R0 K2 K3 - 0x80000000, // 0035 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: parse_page -********************************************************************/ -be_local_closure(HASPmota_parse_page, /* name */ - be_nested_proto( - 9, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ - /* K0 */ be_nested_str_weak(has), - /* K1 */ be_nested_str_weak(page), - /* K2 */ be_nested_str_weak(int), - /* K3 */ be_nested_str_weak(lvh_page_cur_idx), - /* K4 */ be_nested_str_weak(lvh_pages), - /* K5 */ be_nested_str_weak(contains), - /* K6 */ be_nested_str_weak(lvh_page), - /* K7 */ be_nested_str_weak(find), - /* K8 */ be_nested_str_weak(id), - /* K9 */ be_const_int(0), - /* K10 */ be_nested_str_weak(get_page_cur), - /* K11 */ be_nested_str_weak(prev), - /* K12 */ be_nested_str_weak(next), - /* K13 */ be_nested_str_weak(back), - }), - be_str_weak(parse_page), - &be_const_str_solidified, - ( &(const binstruction[54]) { /* code */ - 0x8C080300, // 0000 GETMET R2 R1 K0 - 0x58100001, // 0001 LDCONST R4 K1 - 0x7C080400, // 0002 CALL R2 2 - 0x780A0030, // 0003 JMPF R2 #0035 - 0x60080004, // 0004 GETGBL R2 G4 - 0x940C0301, // 0005 GETIDX R3 R1 K1 - 0x7C080200, // 0006 CALL R2 1 - 0x1C080502, // 0007 EQ R2 R2 K2 - 0x780A002B, // 0008 JMPF R2 #0035 - 0x60080009, // 0009 GETGBL R2 G9 - 0x940C0301, // 000A GETIDX R3 R1 K1 - 0x7C080200, // 000B CALL R2 1 - 0x90020602, // 000C SETMBR R0 K3 R2 - 0x880C0104, // 000D GETMBR R3 R0 K4 - 0x8C0C0705, // 000E GETMET R3 R3 K5 - 0x5C140400, // 000F MOVE R5 R2 - 0x7C0C0400, // 0010 CALL R3 2 - 0x740E0006, // 0011 JMPT R3 #0019 - 0x880C0106, // 0012 GETMBR R3 R0 K6 - 0x88100104, // 0013 GETMBR R4 R0 K4 - 0x5C140600, // 0014 MOVE R5 R3 - 0x5C180400, // 0015 MOVE R6 R2 - 0x5C1C0000, // 0016 MOVE R7 R0 - 0x7C140400, // 0017 CALL R5 2 - 0x98100405, // 0018 SETIDX R4 R2 R5 - 0x8C0C0307, // 0019 GETMET R3 R1 K7 - 0x58140008, // 001A LDCONST R5 K8 - 0x7C0C0400, // 001B CALL R3 2 - 0x1C0C0709, // 001C EQ R3 R3 K9 - 0x780E0016, // 001D JMPF R3 #0035 - 0x8C0C010A, // 001E GETMET R3 R0 K10 - 0x7C0C0200, // 001F CALL R3 1 - 0x60100009, // 0020 GETGBL R4 G9 - 0x8C140307, // 0021 GETMET R5 R1 K7 - 0x581C000B, // 0022 LDCONST R7 K11 - 0x4C200000, // 0023 LDNIL R8 - 0x7C140600, // 0024 CALL R5 3 - 0x7C100200, // 0025 CALL R4 1 - 0x900E1604, // 0026 SETMBR R3 K11 R4 - 0x60100009, // 0027 GETGBL R4 G9 - 0x8C140307, // 0028 GETMET R5 R1 K7 - 0x581C000C, // 0029 LDCONST R7 K12 - 0x4C200000, // 002A LDNIL R8 - 0x7C140600, // 002B CALL R5 3 - 0x7C100200, // 002C CALL R4 1 - 0x900E1804, // 002D SETMBR R3 K12 R4 - 0x60100009, // 002E GETGBL R4 G9 - 0x8C140307, // 002F GETMET R5 R1 K7 - 0x581C000D, // 0030 LDCONST R7 K13 - 0x4C200000, // 0031 LDNIL R8 - 0x7C140600, // 0032 CALL R5 3 - 0x7C100200, // 0033 CALL R4 1 - 0x900E1A04, // 0034 SETMBR R3 K13 R4 - 0x80000000, // 0035 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: page_dir_to -********************************************************************/ -be_local_closure(HASPmota_page_dir_to, /* name */ - be_nested_proto( - 7, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(pages_list_sorted), - /* K1 */ be_const_int(0), - /* K2 */ be_const_int(1), - /* K3 */ be_const_int(2), - /* K4 */ be_nested_str_weak(find), - }), - be_str_weak(page_dir_to), - &be_const_str_solidified, - ( &(const binstruction[32]) { /* code */ - 0x8C080100, // 0000 GETMET R2 R0 K0 - 0x58100001, // 0001 LDCONST R4 K1 - 0x7C080400, // 0002 CALL R2 2 - 0x4C0C0000, // 0003 LDNIL R3 - 0x1C0C0403, // 0004 EQ R3 R2 R3 - 0x780E0000, // 0005 JMPF R3 #0007 - 0x80060200, // 0006 RET 1 K1 - 0x600C000C, // 0007 GETGBL R3 G12 - 0x5C100400, // 0008 MOVE R4 R2 - 0x7C0C0200, // 0009 CALL R3 1 - 0x18100702, // 000A LE R4 R3 K2 - 0x78120000, // 000B JMPF R4 #000D - 0x80060200, // 000C RET 1 K1 - 0x1C100703, // 000D EQ R4 R3 K3 - 0x78120000, // 000E JMPF R4 #0010 - 0x80060400, // 000F RET 1 K2 - 0x8C100504, // 0010 GETMET R4 R2 K4 - 0x5C180200, // 0011 MOVE R6 R1 - 0x7C100400, // 0012 CALL R4 2 - 0x4C140000, // 0013 LDNIL R5 - 0x1C140805, // 0014 EQ R5 R4 R5 - 0x78160000, // 0015 JMPF R5 #0017 - 0x80060200, // 0016 RET 1 K1 - 0x00140702, // 0017 ADD R5 R3 K2 - 0x0C140B03, // 0018 DIV R5 R5 K3 - 0x18140805, // 0019 LE R5 R4 R5 - 0x78160001, // 001A JMPF R5 #001D - 0x80060400, // 001B RET 1 K2 - 0x70020001, // 001C JMP #001F - 0x5415FFFE, // 001D LDINT R5 -1 - 0x80040A00, // 001E RET 1 R5 - 0x80000000, // 001F RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: parse_obj -********************************************************************/ -be_local_closure(HASPmota_parse_obj, /* name */ - be_nested_proto( - 20, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[30]) { /* constants */ - /* K0 */ be_nested_str_weak(global), - /* K1 */ be_nested_str_weak(introspect), - /* K2 */ be_nested_str_weak(find), - /* K3 */ be_nested_str_weak(id), - /* K4 */ be_nested_str_weak(obj), - /* K5 */ be_nested_str_weak(get_page_cur), - /* K6 */ be_nested_str_weak(berry_run), - /* K7 */ be_nested_str_weak(nil), - /* K8 */ be_nested_str_weak(HSP_X3A_X20unable_X20to_X20compile_X20berry_X20code_X20_X22_X25s_X22_X20_X2D_X20_X27_X25s_X27_X20_X2D_X20_X25s), - /* K9 */ be_const_int(1), - /* K10 */ be_nested_str_weak(HSP_X3A_X20invalid_X20_X27id_X27_X3A_X20), - /* K11 */ be_nested_str_weak(_X20for_X20_X27obj_X27_X3A), - /* K12 */ be_nested_str_weak(parentid), - /* K13 */ be_nested_str_weak(get_obj), - /* K14 */ be_nested_str_weak(_lv_obj), - /* K15 */ be_nested_str_weak(get_scr), - /* K16 */ be_nested_str_weak(get), - /* K17 */ be_nested_str_weak(lvh_), - /* K18 */ be_nested_str_weak(class), - /* K19 */ be_nested_str_weak(lvh_obj), - /* K20 */ be_nested_str_weak(module), - /* K21 */ be_nested_str_weak(HSP_X3A_X20Cannot_X20find_X20object_X20of_X20type_X20), - /* K22 */ be_nested_str_weak(set_obj), - /* K23 */ be_nested_str_weak(p_X25ib_X25i), - /* K24 */ be_nested_str_weak(function), - /* K25 */ be_nested_str_weak(HSP_X3A_X20unable_X20to_X20run_X20berry_X20code_X20_X22_X25s_X22_X20_X2D_X20_X27_X25s_X27_X20_X2D_X20_X25s), - /* K26 */ be_const_int(0), - /* K27 */ be_nested_str_weak(HSP_X3A_X20cannot_X20specify_X20_X27obj_X27_X20for_X20_X27id_X27_X3A0), - /* K28 */ be_nested_str_weak(keys), - /* K29 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(parse_obj), - &be_const_str_solidified, - ( &(const binstruction[217]) { /* code */ - 0xA40E0000, // 0000 IMPORT R3 K0 - 0xA4120200, // 0001 IMPORT R4 K1 - 0x60140009, // 0002 GETGBL R5 G9 - 0x8C180302, // 0003 GETMET R6 R1 K2 - 0x58200003, // 0004 LDCONST R8 K3 - 0x7C180400, // 0005 CALL R6 2 - 0x7C140200, // 0006 CALL R5 1 - 0x60180008, // 0007 GETGBL R6 G8 - 0x8C1C0302, // 0008 GETMET R7 R1 K2 - 0x58240004, // 0009 LDCONST R9 K4 - 0x7C1C0400, // 000A CALL R7 2 - 0x7C180200, // 000B CALL R6 1 - 0x4C1C0000, // 000C LDNIL R7 - 0x8C200105, // 000D GETMET R8 R0 K5 - 0x7C200200, // 000E CALL R8 1 - 0x60240008, // 000F GETGBL R9 G8 - 0x8C280302, // 0010 GETMET R10 R1 K2 - 0x58300006, // 0011 LDCONST R12 K6 - 0x7C280400, // 0012 CALL R10 2 - 0x7C240200, // 0013 CALL R9 1 - 0x4C280000, // 0014 LDNIL R10 - 0x202C1307, // 0015 NE R11 R9 K7 - 0x782E0012, // 0016 JMPF R11 #002A - 0xA8020005, // 0017 EXBLK 0 #001E - 0x602C000D, // 0018 GETGBL R11 G13 - 0x5C301200, // 0019 MOVE R12 R9 - 0x7C2C0200, // 001A CALL R11 1 - 0x5C281600, // 001B MOVE R10 R11 - 0xA8040001, // 001C EXBLK 1 1 - 0x7002000B, // 001D JMP #002A - 0xAC2C0002, // 001E CATCH R11 0 2 - 0x70020008, // 001F JMP #0029 - 0x60340001, // 0020 GETGBL R13 G1 - 0x60380018, // 0021 GETGBL R14 G24 - 0x583C0008, // 0022 LDCONST R15 K8 - 0x5C401200, // 0023 MOVE R16 R9 - 0x5C441600, // 0024 MOVE R17 R11 - 0x5C481800, // 0025 MOVE R18 R12 - 0x7C380800, // 0026 CALL R14 4 - 0x7C340200, // 0027 CALL R13 1 - 0x70020000, // 0028 JMP #002A - 0xB0080000, // 0029 RAISE 2 R0 R0 - 0x4C2C0000, // 002A LDNIL R11 - 0x1C2C0A0B, // 002B EQ R11 R5 R11 - 0x782E0000, // 002C JMPF R11 #002E - 0x80001600, // 002D RET 0 - 0x202C0D07, // 002E NE R11 R6 K7 - 0x782E006E, // 002F JMPF R11 #009F - 0x4C2C0000, // 0030 LDNIL R11 - 0x202C0A0B, // 0031 NE R11 R5 R11 - 0x782E006B, // 0032 JMPF R11 #009F - 0x142C0B09, // 0033 LT R11 R5 K9 - 0x742E0002, // 0034 JMPT R11 #0038 - 0x542E00FD, // 0035 LDINT R11 254 - 0x242C0A0B, // 0036 GT R11 R5 R11 - 0x782E0008, // 0037 JMPF R11 #0041 - 0x602C0001, // 0038 GETGBL R11 G1 - 0x60300008, // 0039 GETGBL R12 G8 - 0x5C340A00, // 003A MOVE R13 R5 - 0x7C300200, // 003B CALL R12 1 - 0x0032140C, // 003C ADD R12 K10 R12 - 0x0030190B, // 003D ADD R12 R12 K11 - 0x00301806, // 003E ADD R12 R12 R6 - 0x7C2C0200, // 003F CALL R11 1 - 0x80001600, // 0040 RET 0 - 0x4C2C0000, // 0041 LDNIL R11 - 0x60300009, // 0042 GETGBL R12 G9 - 0x8C340302, // 0043 GETMET R13 R1 K2 - 0x583C000C, // 0044 LDCONST R15 K12 - 0x7C340400, // 0045 CALL R13 2 - 0x7C300200, // 0046 CALL R12 1 - 0x4C340000, // 0047 LDNIL R13 - 0x2034180D, // 0048 NE R13 R12 R13 - 0x78360006, // 0049 JMPF R13 #0051 - 0x8C34110D, // 004A GETMET R13 R8 K13 - 0x5C3C1800, // 004B MOVE R15 R12 - 0x7C340400, // 004C CALL R13 2 - 0x4C380000, // 004D LDNIL R14 - 0x20381A0E, // 004E NE R14 R13 R14 - 0x783A0000, // 004F JMPF R14 #0051 - 0x882C1B0E, // 0050 GETMBR R11 R13 K14 - 0x4C340000, // 0051 LDNIL R13 - 0x1C34160D, // 0052 EQ R13 R11 R13 - 0x78360002, // 0053 JMPF R13 #0057 - 0x8C34110F, // 0054 GETMET R13 R8 K15 - 0x7C340200, // 0055 CALL R13 1 - 0x5C2C1A00, // 0056 MOVE R11 R13 - 0x8C340910, // 0057 GETMET R13 R4 K16 - 0x5C3C0000, // 0058 MOVE R15 R0 - 0x00422206, // 0059 ADD R16 K17 R6 - 0x7C340600, // 005A CALL R13 3 - 0x4C380000, // 005B LDNIL R14 - 0x4C3C0000, // 005C LDNIL R15 - 0x1C3C1A0F, // 005D EQ R15 R13 R15 - 0x783E0010, // 005E JMPF R15 #0070 - 0x8C3C0910, // 005F GETMET R15 R4 K16 - 0x5C440600, // 0060 MOVE R17 R3 - 0x5C480C00, // 0061 MOVE R18 R6 - 0x7C3C0600, // 0062 CALL R15 3 - 0x4C400000, // 0063 LDNIL R16 - 0x20401E10, // 0064 NE R16 R15 R16 - 0x78420009, // 0065 JMPF R16 #0070 - 0x60400004, // 0066 GETGBL R16 G4 - 0x5C441E00, // 0067 MOVE R17 R15 - 0x7C400200, // 0068 CALL R16 1 - 0x1C402112, // 0069 EQ R16 R16 K18 - 0x78420004, // 006A JMPF R16 #0070 - 0x5C401E00, // 006B MOVE R16 R15 - 0x5C441600, // 006C MOVE R17 R11 - 0x7C400200, // 006D CALL R16 1 - 0x5C382000, // 006E MOVE R14 R16 - 0x88340113, // 006F GETMBR R13 R0 K19 - 0x4C3C0000, // 0070 LDNIL R15 - 0x1C3C1A0F, // 0071 EQ R15 R13 R15 - 0x783E000F, // 0072 JMPF R15 #0083 - 0x8C3C0914, // 0073 GETMET R15 R4 K20 - 0x5C440C00, // 0074 MOVE R17 R6 - 0x7C3C0400, // 0075 CALL R15 2 - 0x4C400000, // 0076 LDNIL R16 - 0x20401E10, // 0077 NE R16 R15 R16 - 0x78420009, // 0078 JMPF R16 #0083 - 0x60400004, // 0079 GETGBL R16 G4 - 0x5C441E00, // 007A MOVE R17 R15 - 0x7C400200, // 007B CALL R16 1 - 0x1C402112, // 007C EQ R16 R16 K18 - 0x78420004, // 007D JMPF R16 #0083 - 0x5C401E00, // 007E MOVE R16 R15 - 0x5C441600, // 007F MOVE R17 R11 - 0x7C400200, // 0080 CALL R16 1 - 0x5C382000, // 0081 MOVE R14 R16 - 0x88340113, // 0082 GETMBR R13 R0 K19 - 0x4C3C0000, // 0083 LDNIL R15 - 0x1C3C1A0F, // 0084 EQ R15 R13 R15 - 0x783E0006, // 0085 JMPF R15 #008D - 0x603C0001, // 0086 GETGBL R15 G1 - 0x60400008, // 0087 GETGBL R16 G8 - 0x5C440C00, // 0088 MOVE R17 R6 - 0x7C400200, // 0089 CALL R16 1 - 0x00422A10, // 008A ADD R16 K21 R16 - 0x7C3C0200, // 008B CALL R15 1 - 0x80001E00, // 008C RET 0 - 0x5C3C1A00, // 008D MOVE R15 R13 - 0x5C401600, // 008E MOVE R16 R11 - 0x5C440400, // 008F MOVE R17 R2 - 0x5C480200, // 0090 MOVE R18 R1 - 0x5C4C1C00, // 0091 MOVE R19 R14 - 0x7C3C0800, // 0092 CALL R15 4 - 0x5C1C1E00, // 0093 MOVE R7 R15 - 0x8C3C1116, // 0094 GETMET R15 R8 K22 - 0x5C440A00, // 0095 MOVE R17 R5 - 0x5C480E00, // 0096 MOVE R18 R7 - 0x7C3C0600, // 0097 CALL R15 3 - 0x603C0018, // 0098 GETGBL R15 G24 - 0x58400017, // 0099 LDCONST R16 K23 - 0x8C441103, // 009A GETMET R17 R8 K3 - 0x7C440200, // 009B CALL R17 1 - 0x5C480A00, // 009C MOVE R18 R5 - 0x7C3C0600, // 009D CALL R15 3 - 0x900C1E07, // 009E SETMBR R3 R15 R7 - 0x4C2C0000, // 009F LDNIL R11 - 0x202C140B, // 00A0 NE R11 R10 R11 - 0x782E0018, // 00A1 JMPF R11 #00BB - 0xA802000B, // 00A2 EXBLK 0 #00AF - 0x5C2C1400, // 00A3 MOVE R11 R10 - 0x7C2C0000, // 00A4 CALL R11 0 - 0x60300004, // 00A5 GETGBL R12 G4 - 0x5C341600, // 00A6 MOVE R13 R11 - 0x7C300200, // 00A7 CALL R12 1 - 0x1C301918, // 00A8 EQ R12 R12 K24 - 0x78320002, // 00A9 JMPF R12 #00AD - 0x5C301600, // 00AA MOVE R12 R11 - 0x5C340E00, // 00AB MOVE R13 R7 - 0x7C300200, // 00AC CALL R12 1 - 0xA8040001, // 00AD EXBLK 1 1 - 0x7002000B, // 00AE JMP #00BB - 0xAC2C0002, // 00AF CATCH R11 0 2 - 0x70020008, // 00B0 JMP #00BA - 0x60340001, // 00B1 GETGBL R13 G1 - 0x60380018, // 00B2 GETGBL R14 G24 - 0x583C0019, // 00B3 LDCONST R15 K25 - 0x5C401200, // 00B4 MOVE R16 R9 - 0x5C441600, // 00B5 MOVE R17 R11 - 0x5C481800, // 00B6 MOVE R18 R12 - 0x7C380800, // 00B7 CALL R14 4 - 0x7C340200, // 00B8 CALL R13 1 - 0x70020000, // 00B9 JMP #00BB - 0xB0080000, // 00BA RAISE 2 R0 R0 - 0x1C2C0B1A, // 00BB EQ R11 R5 K26 - 0x782E0005, // 00BC JMPF R11 #00C3 - 0x202C0D07, // 00BD NE R11 R6 K7 - 0x782E0003, // 00BE JMPF R11 #00C3 - 0x602C0001, // 00BF GETGBL R11 G1 - 0x5830001B, // 00C0 LDCONST R12 K27 - 0x7C2C0200, // 00C1 CALL R11 1 - 0x80001600, // 00C2 RET 0 - 0x1C2C0B1A, // 00C3 EQ R11 R5 K26 - 0x782E0005, // 00C4 JMPF R11 #00CB - 0x8C2C0105, // 00C5 GETMET R11 R0 K5 - 0x7C2C0200, // 00C6 CALL R11 1 - 0x8C2C170D, // 00C7 GETMET R11 R11 K13 - 0x5834001A, // 00C8 LDCONST R13 K26 - 0x7C2C0400, // 00C9 CALL R11 2 - 0x5C1C1600, // 00CA MOVE R7 R11 - 0x602C0010, // 00CB GETGBL R11 G16 - 0x8C30031C, // 00CC GETMET R12 R1 K28 - 0x7C300200, // 00CD CALL R12 1 - 0x7C2C0200, // 00CE CALL R11 1 - 0xA8020004, // 00CF EXBLK 0 #00D5 - 0x5C301600, // 00D0 MOVE R12 R11 - 0x7C300000, // 00D1 CALL R12 0 - 0x9434020C, // 00D2 GETIDX R13 R1 R12 - 0x901C180D, // 00D3 SETMBR R7 R12 R13 - 0x7001FFFA, // 00D4 JMP #00D0 - 0x582C001D, // 00D5 LDCONST R11 K29 - 0xAC2C0200, // 00D6 CATCH R11 1 0 - 0xB0080000, // 00D7 RAISE 2 R0 R0 - 0x80000000, // 00D8 RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified class: HASPmota ********************************************************************/ be_local_class(HASPmota, 10, NULL, - be_nested_map(45, + be_nested_map(46, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(re_page_target, -1), be_const_var(7) }, - { be_const_key_weak(lvh_pages, -1), be_const_var(5) }, - { be_const_key_weak(lvh_scr, -1), be_const_class(be_class_lvh_scr) }, - { be_const_key_weak(register_event, 44), be_const_closure(HASPmota_register_event_closure) }, - { be_const_key_weak(lvh_line, -1), be_const_class(be_class_lvh_line) }, - { be_const_key_weak(dark, 33), be_const_var(0) }, - { be_const_key_weak(pages_list_sorted, 37), be_const_closure(HASPmota_pages_list_sorted_closure) }, - { be_const_key_weak(parse, -1), be_const_closure(HASPmota_parse_closure) }, - { be_const_key_weak(lvh_page_cur_idx, 19), be_const_var(6) }, - { be_const_key_weak(parse_obj, 23), be_const_closure(HASPmota_parse_obj_closure) }, - { be_const_key_weak(lvh_label, -1), be_const_class(be_class_lvh_label) }, - { be_const_key_weak(start, 10), be_const_closure(HASPmota_start_closure) }, - { be_const_key_weak(lvh_chart, -1), be_const_class(be_class_lvh_chart) }, - { be_const_key_weak(page_show, -1), be_const_closure(HASPmota_page_show_closure) }, - { be_const_key_weak(lvh_checkbox, -1), be_const_class(be_class_lvh_checkbox) }, - { be_const_key_weak(init, -1), be_const_closure(HASPmota_init_closure) }, - { be_const_key_weak(lvh_obj, -1), be_const_class(be_class_lvh_obj) }, - { be_const_key_weak(get_page_cur, -1), be_const_closure(HASPmota_get_page_cur_closure) }, - { be_const_key_weak(hres, 12), be_const_var(1) }, - { be_const_key_weak(parse_page, 17), be_const_closure(HASPmota_parse_page_closure) }, - { be_const_key_weak(_load, 21), be_const_closure(HASPmota__load_closure) }, - { be_const_key_weak(lvh_slider, -1), be_const_class(be_class_lvh_slider) }, - { be_const_key_weak(deinit, -1), be_const_closure(HASPmota_deinit_closure) }, - { be_const_key_weak(lvh_roller, -1), be_const_class(be_class_lvh_roller) }, - { be_const_key_weak(lvh_spinner, 28), be_const_class(be_class_lvh_spinner) }, { be_const_key_weak(event_dispatch, -1), be_const_closure(HASPmota_event_dispatch_closure) }, - { be_const_key_weak(vres, -1), be_const_var(2) }, - { be_const_key_weak(event_cb, 32), be_const_var(9) }, - { be_const_key_weak(event, 38), be_const_var(8) }, + { be_const_key_weak(lvh_slider, -1), be_const_class(be_class_lvh_slider) }, + { be_const_key_weak(parse_page, -1), be_const_closure(HASPmota_parse_page_closure) }, + { be_const_key_weak(page_dir_to, -1), be_const_closure(HASPmota_page_dir_to_closure) }, + { be_const_key_weak(fix_lv_version, -1), be_const_static_closure(HASPmota_fix_lv_version_closure) }, + { be_const_key_weak(register_event, 41), be_const_closure(HASPmota_register_event_closure) }, + { be_const_key_weak(lvh_img, 15), be_const_class(be_class_lvh_img) }, + { be_const_key_weak(parse_obj, 44), be_const_closure(HASPmota_parse_obj_closure) }, + { be_const_key_weak(lvh_switch, 3), be_const_class(be_class_lvh_switch) }, + { be_const_key_weak(event_cb, -1), be_const_var(9) }, + { be_const_key_weak(parse, 7), be_const_closure(HASPmota_parse_closure) }, + { be_const_key_weak(do_action, -1), be_const_closure(HASPmota_do_action_closure) }, + { be_const_key_weak(lvh_roller, 33), be_const_class(be_class_lvh_roller) }, + { be_const_key_weak(lvh_dropdown, 9), be_const_class(be_class_lvh_dropdown) }, + { be_const_key_weak(lvh_pages, -1), be_const_var(5) }, + { be_const_key_weak(start, 20), be_const_closure(HASPmota_start_closure) }, + { be_const_key_weak(pages_list_sorted, -1), be_const_closure(HASPmota_pages_list_sorted_closure) }, + { be_const_key_weak(lvh_spinner, -1), be_const_class(be_class_lvh_spinner) }, + { be_const_key_weak(lvh_scr, -1), be_const_class(be_class_lvh_scr) }, + { be_const_key_weak(re_page_target, -1), be_const_var(7) }, + { be_const_key_weak(init, -1), be_const_closure(HASPmota_init_closure) }, + { be_const_key_weak(lvh_checkbox, -1), be_const_class(be_class_lvh_checkbox) }, + { be_const_key_weak(lvh_page_cur_idx, 31), be_const_var(6) }, + { be_const_key_weak(event, -1), be_const_var(8) }, + { be_const_key_weak(lvh_textarea, -1), be_const_class(be_class_lvh_textarea) }, + { be_const_key_weak(hres, -1), be_const_var(1) }, + { be_const_key_weak(lvh_line, 19), be_const_class(be_class_lvh_line) }, + { be_const_key_weak(scr, -1), be_const_var(3) }, + { be_const_key_weak(lvh_arc, 26), be_const_class(be_class_lvh_arc) }, + { be_const_key_weak(lvh_page, 36), be_const_class(be_class_lvh_page) }, + { be_const_key_weak(get_page_cur, 16), be_const_closure(HASPmota_get_page_cur_closure) }, + { be_const_key_weak(lvh_chart, -1), be_const_class(be_class_lvh_chart) }, { be_const_key_weak(lvh_btn, -1), be_const_class(be_class_lvh_btn) }, + { be_const_key_weak(_load, 30), be_const_closure(HASPmota__load_closure) }, { be_const_key_weak(r16, -1), be_const_var(4) }, - { be_const_key_weak(lvh_arc, -1), be_const_class(be_class_lvh_arc) }, - { be_const_key_weak(lvh_dropdown, 18), be_const_class(be_class_lvh_dropdown) }, - { be_const_key_weak(do_action, 16), be_const_closure(HASPmota_do_action_closure) }, - { be_const_key_weak(def_templ_name, 26), be_nested_str_weak(pages_X2Ejsonl) }, - { be_const_key_weak(lvh_btnmatrix, 9), be_const_class(be_class_lvh_btnmatrix) }, - { be_const_key_weak(sort, 20), be_const_static_closure(HASPmota_sort_closure) }, + { be_const_key_weak(def_templ_name, -1), be_nested_str_weak(pages_X2Ejsonl) }, + { be_const_key_weak(vres, -1), be_const_var(2) }, + { be_const_key_weak(lvh_obj, 6), be_const_class(be_class_lvh_obj) }, + { be_const_key_weak(page_show, -1), be_const_closure(HASPmota_page_show_closure) }, + { be_const_key_weak(sort, 17), be_const_static_closure(HASPmota_sort_closure) }, { be_const_key_weak(lvh_qrcode, -1), be_const_class(be_class_lvh_qrcode) }, { be_const_key_weak(lvh_bar, -1), be_const_class(be_class_lvh_bar) }, - { be_const_key_weak(lvh_page, -1), be_const_class(be_class_lvh_page) }, - { be_const_key_weak(lvh_textarea, -1), be_const_class(be_class_lvh_textarea) }, - { be_const_key_weak(scr, -1), be_const_var(3) }, - { be_const_key_weak(page_dir_to, -1), be_const_closure(HASPmota_page_dir_to_closure) }, - { be_const_key_weak(lvh_switch, -1), be_const_class(be_class_lvh_switch) }, - { be_const_key_weak(lvh_img, -1), be_const_class(be_class_lvh_img) }, + { be_const_key_weak(deinit, -1), be_const_closure(HASPmota_deinit_closure) }, + { be_const_key_weak(dark, -1), be_const_var(0) }, + { be_const_key_weak(lvh_label, -1), be_const_class(be_class_lvh_label) }, + { be_const_key_weak(lvh_btnmatrix, -1), be_const_class(be_class_lvh_btnmatrix) }, })), be_str_weak(HASPmota) ); diff --git a/lib/libesp32/berry_tasmota/src/embedded/lv_tasmota.be b/lib/libesp32/berry_tasmota/src/embedded/lv_tasmota.be index 8e90ccf1b..3edea396c 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/lv_tasmota.be +++ b/lib/libesp32/berry_tasmota/src/embedded/lv_tasmota.be @@ -25,6 +25,18 @@ def init(lv_tasmota) lv.register_button_encoder = lv_tasmota.register_button_encoder lv.screenshot = lv_tasmota.screenshot + # add version information + lv.version = lv.version_major() + # use the following to retrofit the version: + #- + def fix_lv_version() + import introspect + var v = introspect.get(lv, "version") + # if `lv.version` does not exist, v is `module('undefined')` + if type(v) != 'int' lv.version = 8 end + end + -# + # add widgets lv.clock = lv_clock lv.clock_icon = lv_clock_icon @@ -112,8 +124,7 @@ def splash() tas_logo.set_zoom(150) tas_logo.set_style_img_recolor_opa(255, 0) # lv.PART_MAIN | lv.STATE_DEFAULT tas_logo.set_style_img_recolor(white, 0) # lv.PART_MAIN | lv.STATE_DEFAULT - tas_logo.set_align(lv.ALIGN_LEFT_MID) - tas_logo.set_x(-12) + tas_logo.align(lv.ALIGN_LEFT_MID, -12, 0) var tas = lv.label(bg) # tas.set_style_bg_opa(lv.OPA_TRANSP, lv.PART_MAIN | lv.STATE_DEFAULT) diff --git a/lib/libesp32/berry_tasmota/src/embedded/lv_tasmota_widgets.be b/lib/libesp32/berry_tasmota/src/embedded/lv_tasmota_widgets.be index 7c65815e5..2796341bf 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/lv_tasmota_widgets.be +++ b/lib/libesp32/berry_tasmota/src/embedded/lv_tasmota_widgets.be @@ -88,7 +88,7 @@ class lv_obj end # for solidification #@ solidify:lv_signal_arcs,weak class lv_signal_arcs : lv_obj var percentage # value to display, range 0..100 - var p1, p2, area, arc_dsc # instances of objects kept to avoid re-instanciating at each call + var area, arc_dsc # instances of objects kept to avoid re-instanciating at each call def init(parent) # init custom widget (don't call super constructor) @@ -96,8 +96,6 @@ class lv_signal_arcs : lv_obj # own values self.percentage = 100 # pre-allocate buffers - self.p1 = lv.point() - self.p2 = lv.point() self.area = lv.area() self.arc_dsc = lv.draw_arc_dsc() end @@ -105,7 +103,7 @@ class lv_signal_arcs : lv_obj def widget_event(cl, event) # Call the ancestor's event handler if lv.obj_event_base(cl, event) != lv.RES_OK return end - var code = event.code + var code = event.get_code() import math def atleast1(x) if x >= 1 return x else return 1 end end @@ -119,18 +117,20 @@ class lv_signal_arcs : lv_obj #print("inter_bar", inter_bar, "bar", bar, "bar_offset", bar_offset) if code == lv.EVENT_DRAW_MAIN - var draw_ctx = lv.draw_ctx(event.param) + var arc_dsc = self.arc_dsc + var param = event.get_param() + var layer = event.get_layer() # get coordinates of object self.get_coords(self.area) var x_ofs = self.area.x1 var y_ofs = self.area.y1 - lv.draw_arc_dsc_init(self.arc_dsc) # initialize lv.draw_line_dsc structure - self.init_draw_arc_dsc(lv.PART_MAIN, self.arc_dsc) # copy the current values + lv.draw_arc_dsc_init(arc_dsc) # initialize lv.draw_line_dsc structure + self.init_draw_arc_dsc(lv.PART_MAIN, arc_dsc) # copy the current values - self.arc_dsc.rounded = 1 - self.arc_dsc.width = (bar * 3 + 1) / 4 + arc_dsc.rounded = 1 + arc_dsc.width = (bar * 3 + 1) / 4 var on_color = self.get_style_line_color(lv.PART_MAIN | lv.STATE_DEFAULT) var off_color = self.get_style_bg_color(lv.PART_MAIN | lv.STATE_DEFAULT) @@ -144,15 +144,26 @@ class lv_signal_arcs : lv_obj if (angle > 45) angle = 45 end # print("hypotenuse",hypotenuse,"adjacent",adjacent,"angle",angle) - self.p1.x = x_ofs + width / 2 - self.p1.y = y_ofs + height - 1 - bar_offset + arc_dsc.center_x = x_ofs + width / 2 + arc_dsc.center_y = y_ofs + height - 1 - bar_offset - self.arc_dsc.color = self.percentage >= 25 ? on_color : off_color - lv.draw_arc(draw_ctx, self.arc_dsc, self.p1, 0 * (bar + inter_bar) + bar_offset, 0, 360) - self.arc_dsc.color = self.percentage >= 50 ? on_color : off_color - lv.draw_arc(draw_ctx, self.arc_dsc, self.p1, 1 * (bar + inter_bar) + bar_offset - 1, 270 - angle, 270 + angle) - self.arc_dsc.color = self.percentage >= 75 ? on_color : off_color - lv.draw_arc(draw_ctx, self.arc_dsc, self.p1, 2 * (bar + inter_bar) + bar_offset - 2, 270 - angle, 270 + angle) + arc_dsc.color = self.percentage >= 25 ? on_color : off_color + arc_dsc.radius = 0 * (bar + inter_bar) + bar_offset + arc_dsc.start_angle = 0 + arc_dsc.end_angle = 306 + lv.draw_arc(layer, arc_dsc) + + arc_dsc.radius = 1 * (bar + inter_bar) + bar_offset - 1 + arc_dsc.start_angle = 270 - angle + arc_dsc.end_angle = 270 + angle + arc_dsc.color = self.percentage >= 50 ? on_color : off_color + lv.draw_arc(layer, arc_dsc) + + arc_dsc.radius = 2 * (bar + inter_bar) + bar_offset - 2 + arc_dsc.start_angle = 270 - angle + arc_dsc.end_angle = 270 + angle + arc_dsc.color = self.percentage >= 75 ? on_color : off_color + lv.draw_arc(layer, arc_dsc) #elif mode == lv.DESIGN_DRAW_POST # commented since we don't want a frame around this object # self.ancestor_design.call(self, clip_area, mode) @@ -221,7 +232,7 @@ end #@ solidify:lv_signal_bars,weak class lv_signal_bars : lv_obj var percentage # value to display, range 0..100 - var p1, p2, area, line_dsc # instances of objects kept to avoid re-instanciating at each call + var area, line_dsc # instances of objects kept to avoid re-instanciating at each call def init(parent) # init custom widget (don't call super constructor) @@ -229,16 +240,15 @@ class lv_signal_bars : lv_obj # own values self.percentage = 100 # pre-allocate buffers - self.p1 = lv.point() - self.p2 = lv.point() self.area = lv.area() self.line_dsc = lv.draw_line_dsc() end def widget_event(cl, event) # Call the ancestor's event handler + # tasmota.log(f">>>: widget_event {cl=} {event=}") if lv.obj_event_base(cl, event) != lv.RES_OK return end - var code = event.code + var code = event.get_code() def atleast1(x) if x >= 1 return x else return 1 end end # the model is that we have 4 bars and inter-bar (1/4 of width) @@ -250,32 +260,34 @@ class lv_signal_bars : lv_obj var bar_offset = bar / 2 if code == lv.EVENT_DRAW_MAIN - var draw_ctx = lv.draw_ctx(event.param) + var line_dsc = self.line_dsc + var param = event.get_param() + var layer = event.get_layer() # get coordinates of object self.get_coords(self.area) var x_ofs = self.area.x1 var y_ofs = self.area.y1 - lv.draw_line_dsc_init(self.line_dsc) # initialize lv_draw_line_dsc structure - self.init_draw_line_dsc(lv.PART_MAIN, self.line_dsc) # copy the current values + lv.draw_line_dsc_init(line_dsc) # initialize lv_draw_line_dsc structure + self.init_draw_line_dsc(lv.PART_MAIN, line_dsc) # copy the current values - self.line_dsc.round_start = 1 - self.line_dsc.round_end = 1 - self.line_dsc.width = bar + line_dsc.round_start = 1 + line_dsc.round_end = 1 + line_dsc.width = bar var on_color = self.get_style_line_color(lv.PART_MAIN | lv.STATE_DEFAULT) var off_color = self.get_style_bg_color(lv.PART_MAIN | lv.STATE_DEFAULT) - lv.event_send(self, lv.EVENT_DRAW_PART_BEGIN, self.line_dsc) + # lv.event_send(self, lv.EVENT_DRAW_PART_BEGIN, line_dsc) for i:0..3 # 4 bars - self.line_dsc.color = self.percentage >= (i+1)*20 ? on_color : off_color - self.p1.y = y_ofs + height - 1 - bar_offset - self.p1.x = x_ofs + i * (bar + inter_bar) + bar_offset - self.p2.y = y_ofs + ((3 - i) * (height - bar)) / 4 + bar_offset - self.p2.x = self.p1.x - lv.draw_line(draw_ctx, self.line_dsc, self.p1, self.p2) + line_dsc.color = self.percentage >= (i+1)*20 ? on_color : off_color + line_dsc.p1_y = y_ofs + height - 1 - bar_offset + line_dsc.p1_x = x_ofs + i * (bar + inter_bar) + bar_offset + line_dsc.p2_y = y_ofs + ((3 - i) * (height - bar)) / 4 + bar_offset + line_dsc.p2_x = line_dsc.p1_x + lv.draw_line(layer, line_dsc) end - lv.event_send(self, lv.EVENT_DRAW_PART_END, self.line_dsc) + # lv.event_send(self, lv.EVENT_DRAW_PART_END, line_dsc) end end diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_lv_tasmota.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_lv_tasmota.h index 31a6267d5..5ff64c7fd 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_lv_tasmota.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_lv_tasmota.h @@ -17,7 +17,7 @@ be_local_closure(lv_tasmota_init, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[33]) { /* constants */ + ( &(const bvalue[35]) { /* constants */ /* K0 */ be_nested_str_weak(lv), /* K1 */ be_nested_str_weak(start), /* K2 */ be_nested_str_weak(splash_init), @@ -32,29 +32,31 @@ be_local_closure(lv_tasmota_init, /* name */ /* K11 */ be_nested_str_weak(load_freetype_font), /* K12 */ be_nested_str_weak(register_button_encoder), /* K13 */ be_nested_str_weak(screenshot), - /* K14 */ be_nested_str_weak(clock), - /* K15 */ be_nested_str_weak(lv_clock), - /* K16 */ be_nested_str_weak(clock_icon), - /* K17 */ be_nested_str_weak(lv_clock_icon), - /* K18 */ be_nested_str_weak(signal_arcs), - /* K19 */ be_nested_str_weak(lv_signal_arcs), - /* K20 */ be_nested_str_weak(signal_bars), - /* K21 */ be_nested_str_weak(lv_signal_bars), - /* K22 */ be_nested_str_weak(wifi_arcs_icon), - /* K23 */ be_nested_str_weak(lv_wifi_arcs_icon), - /* K24 */ be_nested_str_weak(wifi_arcs), - /* K25 */ be_nested_str_weak(lv_wifi_arcs), - /* K26 */ be_nested_str_weak(wifi_bars_icon), - /* K27 */ be_nested_str_weak(lv_wifi_bars_icon), - /* K28 */ be_nested_str_weak(wifi_bars), - /* K29 */ be_nested_str_weak(lv_wifi_bars), - /* K30 */ be_nested_str_weak(tasmota), - /* K31 */ be_nested_str_weak(get_option), - /* K32 */ be_const_int(0), + /* K14 */ be_nested_str_weak(version), + /* K15 */ be_nested_str_weak(version_major), + /* K16 */ be_nested_str_weak(clock), + /* K17 */ be_nested_str_weak(lv_clock), + /* K18 */ be_nested_str_weak(clock_icon), + /* K19 */ be_nested_str_weak(lv_clock_icon), + /* K20 */ be_nested_str_weak(signal_arcs), + /* K21 */ be_nested_str_weak(lv_signal_arcs), + /* K22 */ be_nested_str_weak(signal_bars), + /* K23 */ be_nested_str_weak(lv_signal_bars), + /* K24 */ be_nested_str_weak(wifi_arcs_icon), + /* K25 */ be_nested_str_weak(lv_wifi_arcs_icon), + /* K26 */ be_nested_str_weak(wifi_arcs), + /* K27 */ be_nested_str_weak(lv_wifi_arcs), + /* K28 */ be_nested_str_weak(wifi_bars_icon), + /* K29 */ be_nested_str_weak(lv_wifi_bars_icon), + /* K30 */ be_nested_str_weak(wifi_bars), + /* K31 */ be_nested_str_weak(lv_wifi_bars), + /* K32 */ be_nested_str_weak(tasmota), + /* K33 */ be_nested_str_weak(get_option), + /* K34 */ be_const_int(0), }), be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[53]) { /* code */ + ( &(const binstruction[56]) { /* code */ 0xA4060000, // 0000 IMPORT R1 K0 0x88080101, // 0001 GETMBR R2 R0 K1 0x90060202, // 0002 SETMBR R1 K1 R2 @@ -82,32 +84,35 @@ be_local_closure(lv_tasmota_init, /* name */ 0x90061802, // 0018 SETMBR R1 K12 R2 0x8808010D, // 0019 GETMBR R2 R0 K13 0x90061A02, // 001A SETMBR R1 K13 R2 - 0xB80A1E00, // 001B GETNGBL R2 K15 - 0x90061C02, // 001C SETMBR R1 K14 R2 - 0xB80A2200, // 001D GETNGBL R2 K17 - 0x90062002, // 001E SETMBR R1 K16 R2 - 0xB80A2600, // 001F GETNGBL R2 K19 - 0x90062402, // 0020 SETMBR R1 K18 R2 - 0xB80A2A00, // 0021 GETNGBL R2 K21 - 0x90062802, // 0022 SETMBR R1 K20 R2 - 0xB80A2E00, // 0023 GETNGBL R2 K23 - 0x90062C02, // 0024 SETMBR R1 K22 R2 - 0xB80A3200, // 0025 GETNGBL R2 K25 - 0x90063002, // 0026 SETMBR R1 K24 R2 - 0xB80A3600, // 0027 GETNGBL R2 K27 - 0x90063402, // 0028 SETMBR R1 K26 R2 - 0xB80A3A00, // 0029 GETNGBL R2 K29 - 0x90063802, // 002A SETMBR R1 K28 R2 - 0xB80A3C00, // 002B GETNGBL R2 K30 - 0x8C08051F, // 002C GETMET R2 R2 K31 - 0x54120086, // 002D LDINT R4 135 - 0x7C080400, // 002E CALL R2 2 - 0x1C080520, // 002F EQ R2 R2 K32 - 0x780A0001, // 0030 JMPF R2 #0033 - 0x8C080302, // 0031 GETMET R2 R1 K2 - 0x7C080200, // 0032 CALL R2 1 - 0x4C080000, // 0033 LDNIL R2 - 0x80040400, // 0034 RET 1 R2 + 0x8C08030F, // 001B GETMET R2 R1 K15 + 0x7C080200, // 001C CALL R2 1 + 0x90061C02, // 001D SETMBR R1 K14 R2 + 0xB80A2200, // 001E GETNGBL R2 K17 + 0x90062002, // 001F SETMBR R1 K16 R2 + 0xB80A2600, // 0020 GETNGBL R2 K19 + 0x90062402, // 0021 SETMBR R1 K18 R2 + 0xB80A2A00, // 0022 GETNGBL R2 K21 + 0x90062802, // 0023 SETMBR R1 K20 R2 + 0xB80A2E00, // 0024 GETNGBL R2 K23 + 0x90062C02, // 0025 SETMBR R1 K22 R2 + 0xB80A3200, // 0026 GETNGBL R2 K25 + 0x90063002, // 0027 SETMBR R1 K24 R2 + 0xB80A3600, // 0028 GETNGBL R2 K27 + 0x90063402, // 0029 SETMBR R1 K26 R2 + 0xB80A3A00, // 002A GETNGBL R2 K29 + 0x90063802, // 002B SETMBR R1 K28 R2 + 0xB80A3E00, // 002C GETNGBL R2 K31 + 0x90063C02, // 002D SETMBR R1 K30 R2 + 0xB80A4000, // 002E GETNGBL R2 K32 + 0x8C080521, // 002F GETMET R2 R2 K33 + 0x54120086, // 0030 LDINT R4 135 + 0x7C080400, // 0031 CALL R2 2 + 0x1C080522, // 0032 EQ R2 R2 K34 + 0x780A0001, // 0033 JMPF R2 #0036 + 0x8C080302, // 0034 GETMET R2 R1 K2 + 0x7C080200, // 0035 CALL R2 1 + 0x4C080000, // 0036 LDNIL R2 + 0x80040400, // 0037 RET 1 R2 }) ) ); @@ -297,7 +302,7 @@ be_local_closure(lv_tasmota_splash, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[42]) { /* constants */ + ( &(const bvalue[43]) { /* constants */ /* K0 */ be_nested_str_weak(display), /* K1 */ be_nested_str_weak(started), /* K2 */ be_nested_str_weak(lv), @@ -323,27 +328,28 @@ be_local_closure(lv_tasmota_splash, /* name */ /* K22 */ be_nested_str_weak(set_zoom), /* K23 */ be_nested_str_weak(set_style_img_recolor_opa), /* K24 */ be_nested_str_weak(set_style_img_recolor), - /* K25 */ be_nested_str_weak(set_align), + /* K25 */ be_nested_str_weak(align), /* K26 */ be_nested_str_weak(ALIGN_LEFT_MID), - /* K27 */ be_nested_str_weak(set_x), - /* K28 */ be_nested_str_weak(label), - /* K29 */ be_nested_str_weak(set_style_text_color), - /* K30 */ be_nested_str_weak(set_text), - /* K31 */ be_nested_str_weak(TASMOTA), - /* K32 */ be_nested_str_weak(get_hor_res), - /* K33 */ be_nested_str_weak(set_style_text_font), - /* K34 */ be_nested_str_weak(driver_name), - /* K35 */ be_nested_str_weak(ALIGN_BOTTOM_MID), - /* K36 */ be_const_int(16777215), - /* K37 */ be_nested_str_weak(refr_now), - /* K38 */ be_nested_str_weak(_splash), - /* K39 */ be_nested_str_weak(tasmota), - /* K40 */ be_nested_str_weak(set_timer), - /* K41 */ be_nested_str_weak(splash_remove), + /* K27 */ be_nested_str_weak(label), + /* K28 */ be_nested_str_weak(set_style_text_color), + /* K29 */ be_nested_str_weak(set_text), + /* K30 */ be_nested_str_weak(TASMOTA), + /* K31 */ be_nested_str_weak(get_hor_res), + /* K32 */ be_nested_str_weak(set_style_text_font), + /* K33 */ be_nested_str_weak(set_align), + /* K34 */ be_nested_str_weak(set_x), + /* K35 */ be_nested_str_weak(driver_name), + /* K36 */ be_nested_str_weak(ALIGN_BOTTOM_MID), + /* K37 */ be_const_int(16777215), + /* K38 */ be_nested_str_weak(refr_now), + /* K39 */ be_nested_str_weak(_splash), + /* K40 */ be_nested_str_weak(tasmota), + /* K41 */ be_nested_str_weak(set_timer), + /* K42 */ be_nested_str_weak(splash_remove), }), be_str_weak(splash), &be_const_str_solidified, - ( &(const binstruction[166]) { /* code */ + ( &(const binstruction[165]) { /* code */ 0xA4020000, // 0000 IMPORT R0 K0 0x8C040101, // 0001 GETMET R1 R0 K1 0x7C040200, // 0002 CALL R1 1 @@ -427,89 +433,88 @@ be_local_closure(lv_tasmota_splash, /* name */ 0x8C180B19, // 0050 GETMET R6 R5 K25 0xB8220400, // 0051 GETNGBL R8 K2 0x8820111A, // 0052 GETMBR R8 R8 K26 - 0x7C180400, // 0053 CALL R6 2 - 0x8C180B1B, // 0054 GETMET R6 R5 K27 - 0x5421FFF3, // 0055 LDINT R8 -12 - 0x7C180400, // 0056 CALL R6 2 - 0xB81A0400, // 0057 GETNGBL R6 K2 - 0x8C180D1C, // 0058 GETMET R6 R6 K28 - 0x5C200200, // 0059 MOVE R8 R1 - 0x7C180400, // 005A CALL R6 2 - 0x8C1C0D1D, // 005B GETMET R7 R6 K29 - 0x5C240800, // 005C MOVE R9 R4 - 0x5828000A, // 005D LDCONST R10 K10 - 0x7C1C0600, // 005E CALL R7 3 - 0x8C1C0D1E, // 005F GETMET R7 R6 K30 - 0x5824001F, // 0060 LDCONST R9 K31 - 0x7C1C0400, // 0061 CALL R7 2 - 0xB81E0400, // 0062 GETNGBL R7 K2 - 0x8C1C0F20, // 0063 GETMET R7 R7 K32 - 0x7C1C0200, // 0064 CALL R7 1 - 0x542200C7, // 0065 LDINT R8 200 - 0x281C0E08, // 0066 GE R7 R7 R8 - 0x781E0007, // 0067 JMPF R7 #0070 - 0x4C1C0000, // 0068 LDNIL R7 - 0x201C0407, // 0069 NE R7 R2 R7 - 0x781E0003, // 006A JMPF R7 #006F - 0x8C1C0D21, // 006B GETMET R7 R6 K33 - 0x5C240400, // 006C MOVE R9 R2 - 0x5828000A, // 006D LDCONST R10 K10 - 0x7C1C0600, // 006E CALL R7 3 - 0x70020006, // 006F JMP #0077 - 0x4C1C0000, // 0070 LDNIL R7 - 0x201C0607, // 0071 NE R7 R3 R7 - 0x781E0003, // 0072 JMPF R7 #0077 - 0x8C1C0D21, // 0073 GETMET R7 R6 K33 - 0x5C240600, // 0074 MOVE R9 R3 - 0x5828000A, // 0075 LDCONST R10 K10 - 0x7C1C0600, // 0076 CALL R7 3 - 0x8C1C0D19, // 0077 GETMET R7 R6 K25 - 0xB8260400, // 0078 GETNGBL R9 K2 - 0x8824131A, // 0079 GETMBR R9 R9 K26 - 0x7C1C0400, // 007A CALL R7 2 - 0x8C1C0D1B, // 007B GETMET R7 R6 K27 - 0x54260029, // 007C LDINT R9 42 - 0x7C1C0400, // 007D CALL R7 2 - 0x8C1C0122, // 007E GETMET R7 R0 K34 - 0x7C1C0200, // 007F CALL R7 1 - 0x4C200000, // 0080 LDNIL R8 - 0x6024000C, // 0081 GETGBL R9 G12 - 0x5C280E00, // 0082 MOVE R10 R7 - 0x7C240200, // 0083 CALL R9 1 - 0x2424130A, // 0084 GT R9 R9 K10 - 0x78260012, // 0085 JMPF R9 #0099 - 0xB8260400, // 0086 GETNGBL R9 K2 - 0x8C24131C, // 0087 GETMET R9 R9 K28 - 0x5C2C0200, // 0088 MOVE R11 R1 - 0x7C240400, // 0089 CALL R9 2 - 0x5C201200, // 008A MOVE R8 R9 - 0x8C241119, // 008B GETMET R9 R8 K25 - 0xB82E0400, // 008C GETNGBL R11 K2 - 0x882C1723, // 008D GETMBR R11 R11 K35 - 0x7C240400, // 008E CALL R9 2 - 0x8C24111D, // 008F GETMET R9 R8 K29 - 0xB82E0400, // 0090 GETNGBL R11 K2 - 0x8C2C1707, // 0091 GETMET R11 R11 K7 - 0x58340024, // 0092 LDCONST R13 K36 - 0x7C2C0400, // 0093 CALL R11 2 - 0x5830000A, // 0094 LDCONST R12 K10 - 0x7C240600, // 0095 CALL R9 3 - 0x8C24111E, // 0096 GETMET R9 R8 K30 - 0x5C2C0E00, // 0097 MOVE R11 R7 - 0x7C240400, // 0098 CALL R9 2 - 0xB8260400, // 0099 GETNGBL R9 K2 - 0x8C241325, // 009A GETMET R9 R9 K37 - 0x582C000A, // 009B LDCONST R11 K10 - 0x7C240400, // 009C CALL R9 2 - 0xB8260400, // 009D GETNGBL R9 K2 - 0x90264C01, // 009E SETMBR R9 K38 R1 - 0xB8264E00, // 009F GETNGBL R9 K39 - 0x8C241328, // 00A0 GETMET R9 R9 K40 - 0x542E1387, // 00A1 LDINT R11 5000 - 0xB8320400, // 00A2 GETNGBL R12 K2 - 0x88301929, // 00A3 GETMBR R12 R12 K41 - 0x7C240600, // 00A4 CALL R9 3 - 0x80000000, // 00A5 RET 0 + 0x5425FFF3, // 0053 LDINT R9 -12 + 0x5828000A, // 0054 LDCONST R10 K10 + 0x7C180800, // 0055 CALL R6 4 + 0xB81A0400, // 0056 GETNGBL R6 K2 + 0x8C180D1B, // 0057 GETMET R6 R6 K27 + 0x5C200200, // 0058 MOVE R8 R1 + 0x7C180400, // 0059 CALL R6 2 + 0x8C1C0D1C, // 005A GETMET R7 R6 K28 + 0x5C240800, // 005B MOVE R9 R4 + 0x5828000A, // 005C LDCONST R10 K10 + 0x7C1C0600, // 005D CALL R7 3 + 0x8C1C0D1D, // 005E GETMET R7 R6 K29 + 0x5824001E, // 005F LDCONST R9 K30 + 0x7C1C0400, // 0060 CALL R7 2 + 0xB81E0400, // 0061 GETNGBL R7 K2 + 0x8C1C0F1F, // 0062 GETMET R7 R7 K31 + 0x7C1C0200, // 0063 CALL R7 1 + 0x542200C7, // 0064 LDINT R8 200 + 0x281C0E08, // 0065 GE R7 R7 R8 + 0x781E0007, // 0066 JMPF R7 #006F + 0x4C1C0000, // 0067 LDNIL R7 + 0x201C0407, // 0068 NE R7 R2 R7 + 0x781E0003, // 0069 JMPF R7 #006E + 0x8C1C0D20, // 006A GETMET R7 R6 K32 + 0x5C240400, // 006B MOVE R9 R2 + 0x5828000A, // 006C LDCONST R10 K10 + 0x7C1C0600, // 006D CALL R7 3 + 0x70020006, // 006E JMP #0076 + 0x4C1C0000, // 006F LDNIL R7 + 0x201C0607, // 0070 NE R7 R3 R7 + 0x781E0003, // 0071 JMPF R7 #0076 + 0x8C1C0D20, // 0072 GETMET R7 R6 K32 + 0x5C240600, // 0073 MOVE R9 R3 + 0x5828000A, // 0074 LDCONST R10 K10 + 0x7C1C0600, // 0075 CALL R7 3 + 0x8C1C0D21, // 0076 GETMET R7 R6 K33 + 0xB8260400, // 0077 GETNGBL R9 K2 + 0x8824131A, // 0078 GETMBR R9 R9 K26 + 0x7C1C0400, // 0079 CALL R7 2 + 0x8C1C0D22, // 007A GETMET R7 R6 K34 + 0x54260029, // 007B LDINT R9 42 + 0x7C1C0400, // 007C CALL R7 2 + 0x8C1C0123, // 007D GETMET R7 R0 K35 + 0x7C1C0200, // 007E CALL R7 1 + 0x4C200000, // 007F LDNIL R8 + 0x6024000C, // 0080 GETGBL R9 G12 + 0x5C280E00, // 0081 MOVE R10 R7 + 0x7C240200, // 0082 CALL R9 1 + 0x2424130A, // 0083 GT R9 R9 K10 + 0x78260012, // 0084 JMPF R9 #0098 + 0xB8260400, // 0085 GETNGBL R9 K2 + 0x8C24131B, // 0086 GETMET R9 R9 K27 + 0x5C2C0200, // 0087 MOVE R11 R1 + 0x7C240400, // 0088 CALL R9 2 + 0x5C201200, // 0089 MOVE R8 R9 + 0x8C241121, // 008A GETMET R9 R8 K33 + 0xB82E0400, // 008B GETNGBL R11 K2 + 0x882C1724, // 008C GETMBR R11 R11 K36 + 0x7C240400, // 008D CALL R9 2 + 0x8C24111C, // 008E GETMET R9 R8 K28 + 0xB82E0400, // 008F GETNGBL R11 K2 + 0x8C2C1707, // 0090 GETMET R11 R11 K7 + 0x58340025, // 0091 LDCONST R13 K37 + 0x7C2C0400, // 0092 CALL R11 2 + 0x5830000A, // 0093 LDCONST R12 K10 + 0x7C240600, // 0094 CALL R9 3 + 0x8C24111D, // 0095 GETMET R9 R8 K29 + 0x5C2C0E00, // 0096 MOVE R11 R7 + 0x7C240400, // 0097 CALL R9 2 + 0xB8260400, // 0098 GETNGBL R9 K2 + 0x8C241326, // 0099 GETMET R9 R9 K38 + 0x582C000A, // 009A LDCONST R11 K10 + 0x7C240400, // 009B CALL R9 2 + 0xB8260400, // 009C GETNGBL R9 K2 + 0x90264E01, // 009D SETMBR R9 K39 R1 + 0xB8265000, // 009E GETNGBL R9 K40 + 0x8C241329, // 009F GETMET R9 R9 K41 + 0x542E1387, // 00A0 LDINT R11 5000 + 0xB8320400, // 00A1 GETNGBL R12 K2 + 0x8830192A, // 00A2 GETMBR R12 R12 K42 + 0x7C240600, // 00A3 CALL R9 3 + 0x80000000, // 00A4 RET 0 }) ) ); diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_lv_tasmota_widgets.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_lv_tasmota_widgets.h index 380bbc756..53063b24d 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_lv_tasmota_widgets.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_lv_tasmota_widgets.h @@ -394,6 +394,336 @@ void be_load_lv_clock_icon_class(bvm *vm) { extern const bclass be_class_lv_signal_arcs; +/******************************************************************** +** Solidified function: widget_event +********************************************************************/ +be_local_closure(lv_signal_arcs_widget_event, /* name */ + be_nested_proto( + 29, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 1, /* has sup protos */ + ( &(const struct bproto*[ 1]) { + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_const_int(1), + }), + be_str_weak(atleast1), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x28040100, // 0000 GE R1 R0 K0 + 0x78060001, // 0001 JMPF R1 #0004 + 0x80040000, // 0002 RET 1 R0 + 0x70020000, // 0003 JMP #0005 + 0x80060000, // 0004 RET 1 K0 + 0x80000000, // 0005 RET 0 + }) + ), + }), + 1, /* has constants */ + ( &(const bvalue[37]) { /* constants */ + /* K0 */ be_nested_str_weak(lv), + /* K1 */ be_nested_str_weak(obj_event_base), + /* K2 */ be_nested_str_weak(RES_OK), + /* K3 */ be_nested_str_weak(get_code), + /* K4 */ be_nested_str_weak(math), + /* K5 */ be_nested_str_weak(get_height), + /* K6 */ be_nested_str_weak(get_width), + /* K7 */ be_const_int(2), + /* K8 */ be_const_int(3), + /* K9 */ be_nested_str_weak(EVENT_DRAW_MAIN), + /* K10 */ be_nested_str_weak(arc_dsc), + /* K11 */ be_nested_str_weak(get_param), + /* K12 */ be_nested_str_weak(get_layer), + /* K13 */ be_nested_str_weak(get_coords), + /* K14 */ be_nested_str_weak(area), + /* K15 */ be_nested_str_weak(x1), + /* K16 */ be_nested_str_weak(y1), + /* K17 */ be_nested_str_weak(draw_arc_dsc_init), + /* K18 */ be_nested_str_weak(init_draw_arc_dsc), + /* K19 */ be_nested_str_weak(PART_MAIN), + /* K20 */ be_nested_str_weak(rounded), + /* K21 */ be_const_int(1), + /* K22 */ be_nested_str_weak(width), + /* K23 */ be_nested_str_weak(get_style_line_color), + /* K24 */ be_nested_str_weak(STATE_DEFAULT), + /* K25 */ be_nested_str_weak(get_style_bg_color), + /* K26 */ be_nested_str_weak(deg), + /* K27 */ be_nested_str_weak(acos), + /* K28 */ be_nested_str_weak(center_x), + /* K29 */ be_nested_str_weak(center_y), + /* K30 */ be_nested_str_weak(color), + /* K31 */ be_nested_str_weak(percentage), + /* K32 */ be_nested_str_weak(radius), + /* K33 */ be_const_int(0), + /* K34 */ be_nested_str_weak(start_angle), + /* K35 */ be_nested_str_weak(end_angle), + /* K36 */ be_nested_str_weak(draw_arc), + }), + be_str_weak(widget_event), + &be_const_str_solidified, + ( &(const binstruction[171]) { /* code */ + 0xB80E0000, // 0000 GETNGBL R3 K0 + 0x8C0C0701, // 0001 GETMET R3 R3 K1 + 0x5C140200, // 0002 MOVE R5 R1 + 0x5C180400, // 0003 MOVE R6 R2 + 0x7C0C0600, // 0004 CALL R3 3 + 0xB8120000, // 0005 GETNGBL R4 K0 + 0x88100902, // 0006 GETMBR R4 R4 K2 + 0x200C0604, // 0007 NE R3 R3 R4 + 0x780E0000, // 0008 JMPF R3 #000A + 0x80000600, // 0009 RET 0 + 0x8C0C0503, // 000A GETMET R3 R2 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0xA4120800, // 000C IMPORT R4 K4 + 0x84140000, // 000D CLOSURE R5 P0 + 0x8C180105, // 000E GETMET R6 R0 K5 + 0x7C180200, // 000F CALL R6 1 + 0x8C1C0106, // 0010 GETMET R7 R0 K6 + 0x7C1C0200, // 0011 CALL R7 1 + 0x5C200A00, // 0012 MOVE R8 R5 + 0x54260007, // 0013 LDINT R9 8 + 0x0C240C09, // 0014 DIV R9 R6 R9 + 0x7C200200, // 0015 CALL R8 1 + 0x5C240A00, // 0016 MOVE R9 R5 + 0x08281107, // 0017 MUL R10 R8 K7 + 0x04280C0A, // 0018 SUB R10 R6 R10 + 0x0C281508, // 0019 DIV R10 R10 K8 + 0x7C240200, // 001A CALL R9 1 + 0x0C281307, // 001B DIV R10 R9 K7 + 0xB82E0000, // 001C GETNGBL R11 K0 + 0x882C1709, // 001D GETMBR R11 R11 K9 + 0x1C2C060B, // 001E EQ R11 R3 R11 + 0x782E0089, // 001F JMPF R11 #00AA + 0x882C010A, // 0020 GETMBR R11 R0 K10 + 0x8C30050B, // 0021 GETMET R12 R2 K11 + 0x7C300200, // 0022 CALL R12 1 + 0x8C34050C, // 0023 GETMET R13 R2 K12 + 0x7C340200, // 0024 CALL R13 1 + 0x8C38010D, // 0025 GETMET R14 R0 K13 + 0x8840010E, // 0026 GETMBR R16 R0 K14 + 0x7C380400, // 0027 CALL R14 2 + 0x8838010E, // 0028 GETMBR R14 R0 K14 + 0x88381D0F, // 0029 GETMBR R14 R14 K15 + 0x883C010E, // 002A GETMBR R15 R0 K14 + 0x883C1F10, // 002B GETMBR R15 R15 K16 + 0xB8420000, // 002C GETNGBL R16 K0 + 0x8C402111, // 002D GETMET R16 R16 K17 + 0x5C481600, // 002E MOVE R18 R11 + 0x7C400400, // 002F CALL R16 2 + 0x8C400112, // 0030 GETMET R16 R0 K18 + 0xB84A0000, // 0031 GETNGBL R18 K0 + 0x88482513, // 0032 GETMBR R18 R18 K19 + 0x5C4C1600, // 0033 MOVE R19 R11 + 0x7C400600, // 0034 CALL R16 3 + 0x902E2915, // 0035 SETMBR R11 K20 K21 + 0x08401308, // 0036 MUL R16 R9 K8 + 0x00402115, // 0037 ADD R16 R16 K21 + 0x54460003, // 0038 LDINT R17 4 + 0x0C402011, // 0039 DIV R16 R16 R17 + 0x902E2C10, // 003A SETMBR R11 K22 R16 + 0x8C400117, // 003B GETMET R16 R0 K23 + 0xB84A0000, // 003C GETNGBL R18 K0 + 0x88482513, // 003D GETMBR R18 R18 K19 + 0xB84E0000, // 003E GETNGBL R19 K0 + 0x884C2718, // 003F GETMBR R19 R19 K24 + 0x30482413, // 0040 OR R18 R18 R19 + 0x7C400400, // 0041 CALL R16 2 + 0x8C440119, // 0042 GETMET R17 R0 K25 + 0xB84E0000, // 0043 GETNGBL R19 K0 + 0x884C2713, // 0044 GETMBR R19 R19 K19 + 0xB8520000, // 0045 GETNGBL R20 K0 + 0x88502918, // 0046 GETMBR R20 R20 K24 + 0x304C2614, // 0047 OR R19 R19 R20 + 0x7C440400, // 0048 CALL R17 2 + 0x04480C09, // 0049 SUB R18 R6 R9 + 0x0C4C0F07, // 004A DIV R19 R7 K7 + 0x044C260A, // 004B SUB R19 R19 R10 + 0x60500009, // 004C GETGBL R20 G9 + 0x54560059, // 004D LDINT R21 90 + 0x8C58091A, // 004E GETMET R22 R4 K26 + 0x8C60091B, // 004F GETMET R24 R4 K27 + 0x6068000A, // 0050 GETGBL R26 G10 + 0x5C6C2600, // 0051 MOVE R27 R19 + 0x7C680200, // 0052 CALL R26 1 + 0x606C000A, // 0053 GETGBL R27 G10 + 0x5C702400, // 0054 MOVE R28 R18 + 0x7C6C0200, // 0055 CALL R27 1 + 0x0C68341B, // 0056 DIV R26 R26 R27 + 0x7C600400, // 0057 CALL R24 2 + 0x7C580400, // 0058 CALL R22 2 + 0x04542A16, // 0059 SUB R21 R21 R22 + 0x7C500200, // 005A CALL R20 1 + 0x5456002C, // 005B LDINT R21 45 + 0x24542815, // 005C GT R21 R20 R21 + 0x78560000, // 005D JMPF R21 #005F + 0x5452002C, // 005E LDINT R20 45 + 0x0C540F07, // 005F DIV R21 R7 K7 + 0x00541C15, // 0060 ADD R21 R14 R21 + 0x902E3815, // 0061 SETMBR R11 K28 R21 + 0x00541E06, // 0062 ADD R21 R15 R6 + 0x04542B15, // 0063 SUB R21 R21 K21 + 0x04542A0A, // 0064 SUB R21 R21 R10 + 0x902E3A15, // 0065 SETMBR R11 K29 R21 + 0x8854011F, // 0066 GETMBR R21 R0 K31 + 0x545A0018, // 0067 LDINT R22 25 + 0x28542A16, // 0068 GE R21 R21 R22 + 0x78560001, // 0069 JMPF R21 #006C + 0x5C542000, // 006A MOVE R21 R16 + 0x70020000, // 006B JMP #006D + 0x5C542200, // 006C MOVE R21 R17 + 0x902E3C15, // 006D SETMBR R11 K30 R21 + 0x00541208, // 006E ADD R21 R9 R8 + 0x08564215, // 006F MUL R21 K33 R21 + 0x00542A0A, // 0070 ADD R21 R21 R10 + 0x902E4015, // 0071 SETMBR R11 K32 R21 + 0x902E4521, // 0072 SETMBR R11 K34 K33 + 0x54560131, // 0073 LDINT R21 306 + 0x902E4615, // 0074 SETMBR R11 K35 R21 + 0xB8560000, // 0075 GETNGBL R21 K0 + 0x8C542B24, // 0076 GETMET R21 R21 K36 + 0x5C5C1A00, // 0077 MOVE R23 R13 + 0x5C601600, // 0078 MOVE R24 R11 + 0x7C540600, // 0079 CALL R21 3 + 0x00541208, // 007A ADD R21 R9 R8 + 0x08562A15, // 007B MUL R21 K21 R21 + 0x00542A0A, // 007C ADD R21 R21 R10 + 0x04542B15, // 007D SUB R21 R21 K21 + 0x902E4015, // 007E SETMBR R11 K32 R21 + 0x5456010D, // 007F LDINT R21 270 + 0x04542A14, // 0080 SUB R21 R21 R20 + 0x902E4415, // 0081 SETMBR R11 K34 R21 + 0x5456010D, // 0082 LDINT R21 270 + 0x00542A14, // 0083 ADD R21 R21 R20 + 0x902E4615, // 0084 SETMBR R11 K35 R21 + 0x8854011F, // 0085 GETMBR R21 R0 K31 + 0x545A0031, // 0086 LDINT R22 50 + 0x28542A16, // 0087 GE R21 R21 R22 + 0x78560001, // 0088 JMPF R21 #008B + 0x5C542000, // 0089 MOVE R21 R16 + 0x70020000, // 008A JMP #008C + 0x5C542200, // 008B MOVE R21 R17 + 0x902E3C15, // 008C SETMBR R11 K30 R21 + 0xB8560000, // 008D GETNGBL R21 K0 + 0x8C542B24, // 008E GETMET R21 R21 K36 + 0x5C5C1A00, // 008F MOVE R23 R13 + 0x5C601600, // 0090 MOVE R24 R11 + 0x7C540600, // 0091 CALL R21 3 + 0x00541208, // 0092 ADD R21 R9 R8 + 0x08560E15, // 0093 MUL R21 K7 R21 + 0x00542A0A, // 0094 ADD R21 R21 R10 + 0x04542B07, // 0095 SUB R21 R21 K7 + 0x902E4015, // 0096 SETMBR R11 K32 R21 + 0x5456010D, // 0097 LDINT R21 270 + 0x04542A14, // 0098 SUB R21 R21 R20 + 0x902E4415, // 0099 SETMBR R11 K34 R21 + 0x5456010D, // 009A LDINT R21 270 + 0x00542A14, // 009B ADD R21 R21 R20 + 0x902E4615, // 009C SETMBR R11 K35 R21 + 0x8854011F, // 009D GETMBR R21 R0 K31 + 0x545A004A, // 009E LDINT R22 75 + 0x28542A16, // 009F GE R21 R21 R22 + 0x78560001, // 00A0 JMPF R21 #00A3 + 0x5C542000, // 00A1 MOVE R21 R16 + 0x70020000, // 00A2 JMP #00A4 + 0x5C542200, // 00A3 MOVE R21 R17 + 0x902E3C15, // 00A4 SETMBR R11 K30 R21 + 0xB8560000, // 00A5 GETNGBL R21 K0 + 0x8C542B24, // 00A6 GETMET R21 R21 K36 + 0x5C5C1A00, // 00A7 MOVE R23 R13 + 0x5C601600, // 00A8 MOVE R24 R11 + 0x7C540600, // 00A9 CALL R21 3 + 0x80000000, // 00AA RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_percentage +********************************************************************/ +be_local_closure(lv_signal_arcs_get_percentage, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(percentage), + }), + be_str_weak(get_percentage), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(lv_signal_arcs_init, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str_weak(_lvgl), + /* K1 */ be_nested_str_weak(create_custom_widget), + /* K2 */ be_nested_str_weak(percentage), + /* K3 */ be_nested_str_weak(area), + /* K4 */ be_nested_str_weak(lv), + /* K5 */ be_nested_str_weak(arc_dsc), + /* K6 */ be_nested_str_weak(draw_arc_dsc), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[16]) { /* code */ + 0xB80A0000, // 0000 GETNGBL R2 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100000, // 0002 MOVE R4 R0 + 0x5C140200, // 0003 MOVE R5 R1 + 0x7C080600, // 0004 CALL R2 3 + 0x540A0063, // 0005 LDINT R2 100 + 0x90020402, // 0006 SETMBR R0 K2 R2 + 0xB80A0800, // 0007 GETNGBL R2 K4 + 0x8C080503, // 0008 GETMET R2 R2 K3 + 0x7C080200, // 0009 CALL R2 1 + 0x90020602, // 000A SETMBR R0 K3 R2 + 0xB80A0800, // 000B GETNGBL R2 K4 + 0x8C080506, // 000C GETMET R2 R2 K6 + 0x7C080200, // 000D CALL R2 1 + 0x90020A02, // 000E SETMBR R0 K5 R2 + 0x80000000, // 000F RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: set_percentage ********************************************************************/ @@ -439,363 +769,22 @@ be_local_closure(lv_signal_arcs_set_percentage, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(lv_signal_arcs_init, /* name */ - be_nested_proto( - 6, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[10]) { /* constants */ - /* K0 */ be_nested_str_weak(_lvgl), - /* K1 */ be_nested_str_weak(create_custom_widget), - /* K2 */ be_nested_str_weak(percentage), - /* K3 */ be_nested_str_weak(p1), - /* K4 */ be_nested_str_weak(lv), - /* K5 */ be_nested_str_weak(point), - /* K6 */ be_nested_str_weak(p2), - /* K7 */ be_nested_str_weak(area), - /* K8 */ be_nested_str_weak(arc_dsc), - /* K9 */ be_nested_str_weak(draw_arc_dsc), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[24]) { /* code */ - 0xB80A0000, // 0000 GETNGBL R2 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100000, // 0002 MOVE R4 R0 - 0x5C140200, // 0003 MOVE R5 R1 - 0x7C080600, // 0004 CALL R2 3 - 0x540A0063, // 0005 LDINT R2 100 - 0x90020402, // 0006 SETMBR R0 K2 R2 - 0xB80A0800, // 0007 GETNGBL R2 K4 - 0x8C080505, // 0008 GETMET R2 R2 K5 - 0x7C080200, // 0009 CALL R2 1 - 0x90020602, // 000A SETMBR R0 K3 R2 - 0xB80A0800, // 000B GETNGBL R2 K4 - 0x8C080505, // 000C GETMET R2 R2 K5 - 0x7C080200, // 000D CALL R2 1 - 0x90020C02, // 000E SETMBR R0 K6 R2 - 0xB80A0800, // 000F GETNGBL R2 K4 - 0x8C080507, // 0010 GETMET R2 R2 K7 - 0x7C080200, // 0011 CALL R2 1 - 0x90020E02, // 0012 SETMBR R0 K7 R2 - 0xB80A0800, // 0013 GETNGBL R2 K4 - 0x8C080509, // 0014 GETMET R2 R2 K9 - 0x7C080200, // 0015 CALL R2 1 - 0x90021002, // 0016 SETMBR R0 K8 R2 - 0x80000000, // 0017 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: widget_event -********************************************************************/ -be_local_closure(lv_signal_arcs_widget_event, /* name */ - be_nested_proto( - 27, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 1]) { - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_const_int(1), - }), - be_str_weak(atleast1), - &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ - 0x28040100, // 0000 GE R1 R0 K0 - 0x78060001, // 0001 JMPF R1 #0004 - 0x80040000, // 0002 RET 1 R0 - 0x70020000, // 0003 JMP #0005 - 0x80060000, // 0004 RET 1 K0 - 0x80000000, // 0005 RET 0 - }) - ), - }), - 1, /* has constants */ - ( &(const bvalue[35]) { /* constants */ - /* K0 */ be_nested_str_weak(lv), - /* K1 */ be_nested_str_weak(obj_event_base), - /* K2 */ be_nested_str_weak(RES_OK), - /* K3 */ be_nested_str_weak(code), - /* K4 */ be_nested_str_weak(math), - /* K5 */ be_nested_str_weak(get_height), - /* K6 */ be_nested_str_weak(get_width), - /* K7 */ be_const_int(2), - /* K8 */ be_const_int(3), - /* K9 */ be_nested_str_weak(EVENT_DRAW_MAIN), - /* K10 */ be_nested_str_weak(draw_ctx), - /* K11 */ be_nested_str_weak(param), - /* K12 */ be_nested_str_weak(get_coords), - /* K13 */ be_nested_str_weak(area), - /* K14 */ be_nested_str_weak(x1), - /* K15 */ be_nested_str_weak(y1), - /* K16 */ be_nested_str_weak(draw_arc_dsc_init), - /* K17 */ be_nested_str_weak(arc_dsc), - /* K18 */ be_nested_str_weak(init_draw_arc_dsc), - /* K19 */ be_nested_str_weak(PART_MAIN), - /* K20 */ be_nested_str_weak(rounded), - /* K21 */ be_const_int(1), - /* K22 */ be_nested_str_weak(width), - /* K23 */ be_nested_str_weak(get_style_line_color), - /* K24 */ be_nested_str_weak(STATE_DEFAULT), - /* K25 */ be_nested_str_weak(get_style_bg_color), - /* K26 */ be_nested_str_weak(deg), - /* K27 */ be_nested_str_weak(acos), - /* K28 */ be_nested_str_weak(p1), - /* K29 */ be_nested_str_weak(x), - /* K30 */ be_nested_str_weak(y), - /* K31 */ be_nested_str_weak(color), - /* K32 */ be_nested_str_weak(percentage), - /* K33 */ be_nested_str_weak(draw_arc), - /* K34 */ be_const_int(0), - }), - be_str_weak(widget_event), - &be_const_str_solidified, - ( &(const binstruction[171]) { /* code */ - 0xB80E0000, // 0000 GETNGBL R3 K0 - 0x8C0C0701, // 0001 GETMET R3 R3 K1 - 0x5C140200, // 0002 MOVE R5 R1 - 0x5C180400, // 0003 MOVE R6 R2 - 0x7C0C0600, // 0004 CALL R3 3 - 0xB8120000, // 0005 GETNGBL R4 K0 - 0x88100902, // 0006 GETMBR R4 R4 K2 - 0x200C0604, // 0007 NE R3 R3 R4 - 0x780E0000, // 0008 JMPF R3 #000A - 0x80000600, // 0009 RET 0 - 0x880C0503, // 000A GETMBR R3 R2 K3 - 0xA4120800, // 000B IMPORT R4 K4 - 0x84140000, // 000C CLOSURE R5 P0 - 0x8C180105, // 000D GETMET R6 R0 K5 - 0x7C180200, // 000E CALL R6 1 - 0x8C1C0106, // 000F GETMET R7 R0 K6 - 0x7C1C0200, // 0010 CALL R7 1 - 0x5C200A00, // 0011 MOVE R8 R5 - 0x54260007, // 0012 LDINT R9 8 - 0x0C240C09, // 0013 DIV R9 R6 R9 - 0x7C200200, // 0014 CALL R8 1 - 0x5C240A00, // 0015 MOVE R9 R5 - 0x08281107, // 0016 MUL R10 R8 K7 - 0x04280C0A, // 0017 SUB R10 R6 R10 - 0x0C281508, // 0018 DIV R10 R10 K8 - 0x7C240200, // 0019 CALL R9 1 - 0x0C281307, // 001A DIV R10 R9 K7 - 0xB82E0000, // 001B GETNGBL R11 K0 - 0x882C1709, // 001C GETMBR R11 R11 K9 - 0x1C2C060B, // 001D EQ R11 R3 R11 - 0x782E008A, // 001E JMPF R11 #00AA - 0xB82E0000, // 001F GETNGBL R11 K0 - 0x8C2C170A, // 0020 GETMET R11 R11 K10 - 0x8834050B, // 0021 GETMBR R13 R2 K11 - 0x7C2C0400, // 0022 CALL R11 2 - 0x8C30010C, // 0023 GETMET R12 R0 K12 - 0x8838010D, // 0024 GETMBR R14 R0 K13 - 0x7C300400, // 0025 CALL R12 2 - 0x8830010D, // 0026 GETMBR R12 R0 K13 - 0x8830190E, // 0027 GETMBR R12 R12 K14 - 0x8834010D, // 0028 GETMBR R13 R0 K13 - 0x88341B0F, // 0029 GETMBR R13 R13 K15 - 0xB83A0000, // 002A GETNGBL R14 K0 - 0x8C381D10, // 002B GETMET R14 R14 K16 - 0x88400111, // 002C GETMBR R16 R0 K17 - 0x7C380400, // 002D CALL R14 2 - 0x8C380112, // 002E GETMET R14 R0 K18 - 0xB8420000, // 002F GETNGBL R16 K0 - 0x88402113, // 0030 GETMBR R16 R16 K19 - 0x88440111, // 0031 GETMBR R17 R0 K17 - 0x7C380600, // 0032 CALL R14 3 - 0x88380111, // 0033 GETMBR R14 R0 K17 - 0x903A2915, // 0034 SETMBR R14 K20 K21 - 0x88380111, // 0035 GETMBR R14 R0 K17 - 0x083C1308, // 0036 MUL R15 R9 K8 - 0x003C1F15, // 0037 ADD R15 R15 K21 - 0x54420003, // 0038 LDINT R16 4 - 0x0C3C1E10, // 0039 DIV R15 R15 R16 - 0x903A2C0F, // 003A SETMBR R14 K22 R15 - 0x8C380117, // 003B GETMET R14 R0 K23 - 0xB8420000, // 003C GETNGBL R16 K0 - 0x88402113, // 003D GETMBR R16 R16 K19 - 0xB8460000, // 003E GETNGBL R17 K0 - 0x88442318, // 003F GETMBR R17 R17 K24 - 0x30402011, // 0040 OR R16 R16 R17 - 0x7C380400, // 0041 CALL R14 2 - 0x8C3C0119, // 0042 GETMET R15 R0 K25 - 0xB8460000, // 0043 GETNGBL R17 K0 - 0x88442313, // 0044 GETMBR R17 R17 K19 - 0xB84A0000, // 0045 GETNGBL R18 K0 - 0x88482518, // 0046 GETMBR R18 R18 K24 - 0x30442212, // 0047 OR R17 R17 R18 - 0x7C3C0400, // 0048 CALL R15 2 - 0x04400C09, // 0049 SUB R16 R6 R9 - 0x0C440F07, // 004A DIV R17 R7 K7 - 0x0444220A, // 004B SUB R17 R17 R10 - 0x60480009, // 004C GETGBL R18 G9 - 0x544E0059, // 004D LDINT R19 90 - 0x8C50091A, // 004E GETMET R20 R4 K26 - 0x8C58091B, // 004F GETMET R22 R4 K27 - 0x6060000A, // 0050 GETGBL R24 G10 - 0x5C642200, // 0051 MOVE R25 R17 - 0x7C600200, // 0052 CALL R24 1 - 0x6064000A, // 0053 GETGBL R25 G10 - 0x5C682000, // 0054 MOVE R26 R16 - 0x7C640200, // 0055 CALL R25 1 - 0x0C603019, // 0056 DIV R24 R24 R25 - 0x7C580400, // 0057 CALL R22 2 - 0x7C500400, // 0058 CALL R20 2 - 0x044C2614, // 0059 SUB R19 R19 R20 - 0x7C480200, // 005A CALL R18 1 - 0x544E002C, // 005B LDINT R19 45 - 0x244C2413, // 005C GT R19 R18 R19 - 0x784E0000, // 005D JMPF R19 #005F - 0x544A002C, // 005E LDINT R18 45 - 0x884C011C, // 005F GETMBR R19 R0 K28 - 0x0C500F07, // 0060 DIV R20 R7 K7 - 0x00501814, // 0061 ADD R20 R12 R20 - 0x904E3A14, // 0062 SETMBR R19 K29 R20 - 0x884C011C, // 0063 GETMBR R19 R0 K28 - 0x00501A06, // 0064 ADD R20 R13 R6 - 0x04502915, // 0065 SUB R20 R20 K21 - 0x0450280A, // 0066 SUB R20 R20 R10 - 0x904E3C14, // 0067 SETMBR R19 K30 R20 - 0x884C0111, // 0068 GETMBR R19 R0 K17 - 0x88500120, // 0069 GETMBR R20 R0 K32 - 0x54560018, // 006A LDINT R21 25 - 0x28502815, // 006B GE R20 R20 R21 - 0x78520001, // 006C JMPF R20 #006F - 0x5C501C00, // 006D MOVE R20 R14 - 0x70020000, // 006E JMP #0070 - 0x5C501E00, // 006F MOVE R20 R15 - 0x904E3E14, // 0070 SETMBR R19 K31 R20 - 0xB84E0000, // 0071 GETNGBL R19 K0 - 0x8C4C2721, // 0072 GETMET R19 R19 K33 - 0x5C541600, // 0073 MOVE R21 R11 - 0x88580111, // 0074 GETMBR R22 R0 K17 - 0x885C011C, // 0075 GETMBR R23 R0 K28 - 0x00601208, // 0076 ADD R24 R9 R8 - 0x08624418, // 0077 MUL R24 K34 R24 - 0x0060300A, // 0078 ADD R24 R24 R10 - 0x58640022, // 0079 LDCONST R25 K34 - 0x546A0167, // 007A LDINT R26 360 - 0x7C4C0E00, // 007B CALL R19 7 - 0x884C0111, // 007C GETMBR R19 R0 K17 - 0x88500120, // 007D GETMBR R20 R0 K32 - 0x54560031, // 007E LDINT R21 50 - 0x28502815, // 007F GE R20 R20 R21 - 0x78520001, // 0080 JMPF R20 #0083 - 0x5C501C00, // 0081 MOVE R20 R14 - 0x70020000, // 0082 JMP #0084 - 0x5C501E00, // 0083 MOVE R20 R15 - 0x904E3E14, // 0084 SETMBR R19 K31 R20 - 0xB84E0000, // 0085 GETNGBL R19 K0 - 0x8C4C2721, // 0086 GETMET R19 R19 K33 - 0x5C541600, // 0087 MOVE R21 R11 - 0x88580111, // 0088 GETMBR R22 R0 K17 - 0x885C011C, // 0089 GETMBR R23 R0 K28 - 0x00601208, // 008A ADD R24 R9 R8 - 0x08622A18, // 008B MUL R24 K21 R24 - 0x0060300A, // 008C ADD R24 R24 R10 - 0x04603115, // 008D SUB R24 R24 K21 - 0x5466010D, // 008E LDINT R25 270 - 0x04643212, // 008F SUB R25 R25 R18 - 0x546A010D, // 0090 LDINT R26 270 - 0x00683412, // 0091 ADD R26 R26 R18 - 0x7C4C0E00, // 0092 CALL R19 7 - 0x884C0111, // 0093 GETMBR R19 R0 K17 - 0x88500120, // 0094 GETMBR R20 R0 K32 - 0x5456004A, // 0095 LDINT R21 75 - 0x28502815, // 0096 GE R20 R20 R21 - 0x78520001, // 0097 JMPF R20 #009A - 0x5C501C00, // 0098 MOVE R20 R14 - 0x70020000, // 0099 JMP #009B - 0x5C501E00, // 009A MOVE R20 R15 - 0x904E3E14, // 009B SETMBR R19 K31 R20 - 0xB84E0000, // 009C GETNGBL R19 K0 - 0x8C4C2721, // 009D GETMET R19 R19 K33 - 0x5C541600, // 009E MOVE R21 R11 - 0x88580111, // 009F GETMBR R22 R0 K17 - 0x885C011C, // 00A0 GETMBR R23 R0 K28 - 0x00601208, // 00A1 ADD R24 R9 R8 - 0x08620E18, // 00A2 MUL R24 K7 R24 - 0x0060300A, // 00A3 ADD R24 R24 R10 - 0x04603107, // 00A4 SUB R24 R24 K7 - 0x5466010D, // 00A5 LDINT R25 270 - 0x04643212, // 00A6 SUB R25 R25 R18 - 0x546A010D, // 00A7 LDINT R26 270 - 0x00683412, // 00A8 ADD R26 R26 R18 - 0x7C4C0E00, // 00A9 CALL R19 7 - 0x80000000, // 00AA RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_percentage -********************************************************************/ -be_local_closure(lv_signal_arcs_get_percentage, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(percentage), - }), - be_str_weak(get_percentage), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified class: lv_signal_arcs ********************************************************************/ extern const bclass be_class_lv_obj; be_local_class(lv_signal_arcs, - 5, + 3, &be_class_lv_obj, - be_nested_map(9, + be_nested_map(7, ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(widget_event, 2), be_const_closure(lv_signal_arcs_widget_event_closure) }, + { be_const_key_weak(get_percentage, 3), be_const_closure(lv_signal_arcs_get_percentage_closure) }, + { be_const_key_weak(set_percentage, 6), be_const_closure(lv_signal_arcs_set_percentage_closure) }, + { be_const_key_weak(arc_dsc, -1), be_const_var(2) }, { be_const_key_weak(percentage, -1), be_const_var(0) }, - { be_const_key_weak(area, 4), be_const_var(3) }, - { be_const_key_weak(p2, -1), be_const_var(2) }, - { be_const_key_weak(get_percentage, -1), be_const_closure(lv_signal_arcs_get_percentage_closure) }, - { be_const_key_weak(p1, -1), be_const_var(1) }, - { be_const_key_weak(arc_dsc, -1), be_const_var(4) }, - { be_const_key_weak(init, 5), be_const_closure(lv_signal_arcs_init_closure) }, - { be_const_key_weak(widget_event, -1), be_const_closure(lv_signal_arcs_widget_event_closure) }, - { be_const_key_weak(set_percentage, 3), be_const_closure(lv_signal_arcs_set_percentage_closure) }, + { be_const_key_weak(init, -1), be_const_closure(lv_signal_arcs_init_closure) }, + { be_const_key_weak(area, -1), be_const_var(1) }, })), be_str_weak(lv_signal_arcs) ); @@ -1140,57 +1129,26 @@ be_local_closure(lv_signal_bars_set_percentage, /* name */ /******************************************************************** -** Solidified function: init +** Solidified function: get_percentage ********************************************************************/ -be_local_closure(lv_signal_bars_init, /* name */ +be_local_closure(lv_signal_bars_get_percentage, /* name */ be_nested_proto( - 6, /* nstack */ - 2, /* argc */ + 2, /* nstack */ + 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[10]) { /* constants */ - /* K0 */ be_nested_str_weak(_lvgl), - /* K1 */ be_nested_str_weak(create_custom_widget), - /* K2 */ be_nested_str_weak(percentage), - /* K3 */ be_nested_str_weak(p1), - /* K4 */ be_nested_str_weak(lv), - /* K5 */ be_nested_str_weak(point), - /* K6 */ be_nested_str_weak(p2), - /* K7 */ be_nested_str_weak(area), - /* K8 */ be_nested_str_weak(line_dsc), - /* K9 */ be_nested_str_weak(draw_line_dsc), + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(percentage), }), - be_str_weak(init), + be_str_weak(get_percentage), &be_const_str_solidified, - ( &(const binstruction[24]) { /* code */ - 0xB80A0000, // 0000 GETNGBL R2 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100000, // 0002 MOVE R4 R0 - 0x5C140200, // 0003 MOVE R5 R1 - 0x7C080600, // 0004 CALL R2 3 - 0x540A0063, // 0005 LDINT R2 100 - 0x90020402, // 0006 SETMBR R0 K2 R2 - 0xB80A0800, // 0007 GETNGBL R2 K4 - 0x8C080505, // 0008 GETMET R2 R2 K5 - 0x7C080200, // 0009 CALL R2 1 - 0x90020602, // 000A SETMBR R0 K3 R2 - 0xB80A0800, // 000B GETNGBL R2 K4 - 0x8C080505, // 000C GETMET R2 R2 K5 - 0x7C080200, // 000D CALL R2 1 - 0x90020C02, // 000E SETMBR R0 K6 R2 - 0xB80A0800, // 000F GETNGBL R2 K4 - 0x8C080507, // 0010 GETMET R2 R2 K7 - 0x7C080200, // 0011 CALL R2 1 - 0x90020E02, // 0012 SETMBR R0 K7 R2 - 0xB80A0800, // 0013 GETNGBL R2 K4 - 0x8C080509, // 0014 GETMET R2 R2 K9 - 0x7C080200, // 0015 CALL R2 1 - 0x90021002, // 0016 SETMBR R0 K8 R2 - 0x80000000, // 0017 RET 0 + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 }) ) ); @@ -1234,24 +1192,24 @@ be_local_closure(lv_signal_bars_widget_event, /* name */ ), }), 1, /* has constants */ - ( &(const bvalue[38]) { /* constants */ + ( &(const bvalue[35]) { /* constants */ /* K0 */ be_nested_str_weak(lv), /* K1 */ be_nested_str_weak(obj_event_base), /* K2 */ be_nested_str_weak(RES_OK), - /* K3 */ be_nested_str_weak(code), + /* K3 */ be_nested_str_weak(get_code), /* K4 */ be_nested_str_weak(get_height), /* K5 */ be_nested_str_weak(get_width), /* K6 */ be_const_int(3), /* K7 */ be_const_int(2), /* K8 */ be_nested_str_weak(EVENT_DRAW_MAIN), - /* K9 */ be_nested_str_weak(draw_ctx), - /* K10 */ be_nested_str_weak(param), - /* K11 */ be_nested_str_weak(get_coords), - /* K12 */ be_nested_str_weak(area), - /* K13 */ be_nested_str_weak(x1), - /* K14 */ be_nested_str_weak(y1), - /* K15 */ be_nested_str_weak(draw_line_dsc_init), - /* K16 */ be_nested_str_weak(line_dsc), + /* K9 */ be_nested_str_weak(line_dsc), + /* K10 */ be_nested_str_weak(get_param), + /* K11 */ be_nested_str_weak(get_layer), + /* K12 */ be_nested_str_weak(get_coords), + /* K13 */ be_nested_str_weak(area), + /* K14 */ be_nested_str_weak(x1), + /* K15 */ be_nested_str_weak(y1), + /* K16 */ be_nested_str_weak(draw_line_dsc_init), /* K17 */ be_nested_str_weak(init_draw_line_dsc), /* K18 */ be_nested_str_weak(PART_MAIN), /* K19 */ be_nested_str_weak(round_start), @@ -1261,22 +1219,19 @@ be_local_closure(lv_signal_bars_widget_event, /* name */ /* K23 */ be_nested_str_weak(get_style_line_color), /* K24 */ be_nested_str_weak(STATE_DEFAULT), /* K25 */ be_nested_str_weak(get_style_bg_color), - /* K26 */ be_nested_str_weak(event_send), - /* K27 */ be_nested_str_weak(EVENT_DRAW_PART_BEGIN), - /* K28 */ be_const_int(0), - /* K29 */ be_nested_str_weak(color), - /* K30 */ be_nested_str_weak(percentage), - /* K31 */ be_nested_str_weak(p1), - /* K32 */ be_nested_str_weak(y), - /* K33 */ be_nested_str_weak(x), - /* K34 */ be_nested_str_weak(p2), - /* K35 */ be_nested_str_weak(draw_line), - /* K36 */ be_nested_str_weak(stop_iteration), - /* K37 */ be_nested_str_weak(EVENT_DRAW_PART_END), + /* K26 */ be_const_int(0), + /* K27 */ be_nested_str_weak(color), + /* K28 */ be_nested_str_weak(percentage), + /* K29 */ be_nested_str_weak(p1_y), + /* K30 */ be_nested_str_weak(p1_x), + /* K31 */ be_nested_str_weak(p2_y), + /* K32 */ be_nested_str_weak(p2_x), + /* K33 */ be_nested_str_weak(draw_line), + /* K34 */ be_nested_str_weak(stop_iteration), }), be_str_weak(widget_event), &be_const_str_solidified, - ( &(const binstruction[138]) { /* code */ + ( &(const binstruction[115]) { /* code */ 0xB80E0000, // 0000 GETNGBL R3 K0 0x8C0C0701, // 0001 GETMET R3 R3 K1 0x5C140200, // 0002 MOVE R5 R1 @@ -1287,134 +1242,111 @@ be_local_closure(lv_signal_bars_widget_event, /* name */ 0x200C0604, // 0007 NE R3 R3 R4 0x780E0000, // 0008 JMPF R3 #000A 0x80000600, // 0009 RET 0 - 0x880C0503, // 000A GETMBR R3 R2 K3 - 0x84100000, // 000B CLOSURE R4 P0 - 0x8C140104, // 000C GETMET R5 R0 K4 - 0x7C140200, // 000D CALL R5 1 - 0x8C180105, // 000E GETMET R6 R0 K5 - 0x7C180200, // 000F CALL R6 1 - 0x5C1C0800, // 0010 MOVE R7 R4 - 0x5422000E, // 0011 LDINT R8 15 - 0x0C200C08, // 0012 DIV R8 R6 R8 - 0x7C1C0200, // 0013 CALL R7 1 - 0x5C200800, // 0014 MOVE R8 R4 - 0x08240F06, // 0015 MUL R9 R7 K6 - 0x04240C09, // 0016 SUB R9 R6 R9 - 0x542A0003, // 0017 LDINT R10 4 - 0x0C24120A, // 0018 DIV R9 R9 R10 - 0x7C200200, // 0019 CALL R8 1 - 0x0C241107, // 001A DIV R9 R8 K7 - 0xB82A0000, // 001B GETNGBL R10 K0 - 0x88281508, // 001C GETMBR R10 R10 K8 - 0x1C28060A, // 001D EQ R10 R3 R10 - 0x782A0069, // 001E JMPF R10 #0089 - 0xB82A0000, // 001F GETNGBL R10 K0 - 0x8C281509, // 0020 GETMET R10 R10 K9 - 0x8830050A, // 0021 GETMBR R12 R2 K10 - 0x7C280400, // 0022 CALL R10 2 - 0x8C2C010B, // 0023 GETMET R11 R0 K11 - 0x8834010C, // 0024 GETMBR R13 R0 K12 - 0x7C2C0400, // 0025 CALL R11 2 - 0x882C010C, // 0026 GETMBR R11 R0 K12 - 0x882C170D, // 0027 GETMBR R11 R11 K13 - 0x8830010C, // 0028 GETMBR R12 R0 K12 - 0x8830190E, // 0029 GETMBR R12 R12 K14 - 0xB8360000, // 002A GETNGBL R13 K0 - 0x8C341B0F, // 002B GETMET R13 R13 K15 - 0x883C0110, // 002C GETMBR R15 R0 K16 - 0x7C340400, // 002D CALL R13 2 - 0x8C340111, // 002E GETMET R13 R0 K17 - 0xB83E0000, // 002F GETNGBL R15 K0 - 0x883C1F12, // 0030 GETMBR R15 R15 K18 - 0x88400110, // 0031 GETMBR R16 R0 K16 - 0x7C340600, // 0032 CALL R13 3 - 0x88340110, // 0033 GETMBR R13 R0 K16 - 0x90362714, // 0034 SETMBR R13 K19 K20 - 0x88340110, // 0035 GETMBR R13 R0 K16 - 0x90362B14, // 0036 SETMBR R13 K21 K20 - 0x88340110, // 0037 GETMBR R13 R0 K16 - 0x90362C08, // 0038 SETMBR R13 K22 R8 - 0x8C340117, // 0039 GETMET R13 R0 K23 - 0xB83E0000, // 003A GETNGBL R15 K0 - 0x883C1F12, // 003B GETMBR R15 R15 K18 - 0xB8420000, // 003C GETNGBL R16 K0 - 0x88402118, // 003D GETMBR R16 R16 K24 - 0x303C1E10, // 003E OR R15 R15 R16 - 0x7C340400, // 003F CALL R13 2 - 0x8C380119, // 0040 GETMET R14 R0 K25 - 0xB8420000, // 0041 GETNGBL R16 K0 - 0x88402112, // 0042 GETMBR R16 R16 K18 - 0xB8460000, // 0043 GETNGBL R17 K0 - 0x88442318, // 0044 GETMBR R17 R17 K24 - 0x30402011, // 0045 OR R16 R16 R17 - 0x7C380400, // 0046 CALL R14 2 - 0xB83E0000, // 0047 GETNGBL R15 K0 - 0x8C3C1F1A, // 0048 GETMET R15 R15 K26 - 0x5C440000, // 0049 MOVE R17 R0 - 0xB84A0000, // 004A GETNGBL R18 K0 - 0x8848251B, // 004B GETMBR R18 R18 K27 - 0x884C0110, // 004C GETMBR R19 R0 K16 - 0x7C3C0800, // 004D CALL R15 4 - 0x603C0010, // 004E GETGBL R15 G16 - 0x40423906, // 004F CONNECT R16 K28 K6 - 0x7C3C0200, // 0050 CALL R15 1 - 0xA802002C, // 0051 EXBLK 0 #007F - 0x5C401E00, // 0052 MOVE R16 R15 - 0x7C400000, // 0053 CALL R16 0 - 0x88440110, // 0054 GETMBR R17 R0 K16 - 0x8848011E, // 0055 GETMBR R18 R0 K30 - 0x004C2114, // 0056 ADD R19 R16 K20 - 0x54520013, // 0057 LDINT R20 20 - 0x084C2614, // 0058 MUL R19 R19 R20 - 0x28482413, // 0059 GE R18 R18 R19 - 0x784A0001, // 005A JMPF R18 #005D - 0x5C481A00, // 005B MOVE R18 R13 - 0x70020000, // 005C JMP #005E - 0x5C481C00, // 005D MOVE R18 R14 - 0x90463A12, // 005E SETMBR R17 K29 R18 - 0x8844011F, // 005F GETMBR R17 R0 K31 - 0x00481805, // 0060 ADD R18 R12 R5 - 0x04482514, // 0061 SUB R18 R18 K20 - 0x04482409, // 0062 SUB R18 R18 R9 - 0x90464012, // 0063 SETMBR R17 K32 R18 - 0x8844011F, // 0064 GETMBR R17 R0 K31 - 0x00481007, // 0065 ADD R18 R8 R7 - 0x08482012, // 0066 MUL R18 R16 R18 - 0x00481612, // 0067 ADD R18 R11 R18 - 0x00482409, // 0068 ADD R18 R18 R9 - 0x90464212, // 0069 SETMBR R17 K33 R18 - 0x88440122, // 006A GETMBR R17 R0 K34 - 0x044A0C10, // 006B SUB R18 K6 R16 - 0x044C0A08, // 006C SUB R19 R5 R8 - 0x08482413, // 006D MUL R18 R18 R19 - 0x544E0003, // 006E LDINT R19 4 - 0x0C482413, // 006F DIV R18 R18 R19 - 0x00481812, // 0070 ADD R18 R12 R18 - 0x00482409, // 0071 ADD R18 R18 R9 - 0x90464012, // 0072 SETMBR R17 K32 R18 - 0x88440122, // 0073 GETMBR R17 R0 K34 - 0x8848011F, // 0074 GETMBR R18 R0 K31 - 0x88482521, // 0075 GETMBR R18 R18 K33 - 0x90464212, // 0076 SETMBR R17 K33 R18 - 0xB8460000, // 0077 GETNGBL R17 K0 - 0x8C442323, // 0078 GETMET R17 R17 K35 - 0x5C4C1400, // 0079 MOVE R19 R10 - 0x88500110, // 007A GETMBR R20 R0 K16 - 0x8854011F, // 007B GETMBR R21 R0 K31 - 0x88580122, // 007C GETMBR R22 R0 K34 - 0x7C440A00, // 007D CALL R17 5 - 0x7001FFD2, // 007E JMP #0052 - 0x583C0024, // 007F LDCONST R15 K36 - 0xAC3C0200, // 0080 CATCH R15 1 0 - 0xB0080000, // 0081 RAISE 2 R0 R0 - 0xB83E0000, // 0082 GETNGBL R15 K0 - 0x8C3C1F1A, // 0083 GETMET R15 R15 K26 - 0x5C440000, // 0084 MOVE R17 R0 - 0xB84A0000, // 0085 GETNGBL R18 K0 - 0x88482525, // 0086 GETMBR R18 R18 K37 - 0x884C0110, // 0087 GETMBR R19 R0 K16 - 0x7C3C0800, // 0088 CALL R15 4 - 0x80000000, // 0089 RET 0 + 0x8C0C0503, // 000A GETMET R3 R2 K3 + 0x7C0C0200, // 000B CALL R3 1 + 0x84100000, // 000C CLOSURE R4 P0 + 0x8C140104, // 000D GETMET R5 R0 K4 + 0x7C140200, // 000E CALL R5 1 + 0x8C180105, // 000F GETMET R6 R0 K5 + 0x7C180200, // 0010 CALL R6 1 + 0x5C1C0800, // 0011 MOVE R7 R4 + 0x5422000E, // 0012 LDINT R8 15 + 0x0C200C08, // 0013 DIV R8 R6 R8 + 0x7C1C0200, // 0014 CALL R7 1 + 0x5C200800, // 0015 MOVE R8 R4 + 0x08240F06, // 0016 MUL R9 R7 K6 + 0x04240C09, // 0017 SUB R9 R6 R9 + 0x542A0003, // 0018 LDINT R10 4 + 0x0C24120A, // 0019 DIV R9 R9 R10 + 0x7C200200, // 001A CALL R8 1 + 0x0C241107, // 001B DIV R9 R8 K7 + 0xB82A0000, // 001C GETNGBL R10 K0 + 0x88281508, // 001D GETMBR R10 R10 K8 + 0x1C28060A, // 001E EQ R10 R3 R10 + 0x782A0051, // 001F JMPF R10 #0072 + 0x88280109, // 0020 GETMBR R10 R0 K9 + 0x8C2C050A, // 0021 GETMET R11 R2 K10 + 0x7C2C0200, // 0022 CALL R11 1 + 0x8C30050B, // 0023 GETMET R12 R2 K11 + 0x7C300200, // 0024 CALL R12 1 + 0x8C34010C, // 0025 GETMET R13 R0 K12 + 0x883C010D, // 0026 GETMBR R15 R0 K13 + 0x7C340400, // 0027 CALL R13 2 + 0x8834010D, // 0028 GETMBR R13 R0 K13 + 0x88341B0E, // 0029 GETMBR R13 R13 K14 + 0x8838010D, // 002A GETMBR R14 R0 K13 + 0x88381D0F, // 002B GETMBR R14 R14 K15 + 0xB83E0000, // 002C GETNGBL R15 K0 + 0x8C3C1F10, // 002D GETMET R15 R15 K16 + 0x5C441400, // 002E MOVE R17 R10 + 0x7C3C0400, // 002F CALL R15 2 + 0x8C3C0111, // 0030 GETMET R15 R0 K17 + 0xB8460000, // 0031 GETNGBL R17 K0 + 0x88442312, // 0032 GETMBR R17 R17 K18 + 0x5C481400, // 0033 MOVE R18 R10 + 0x7C3C0600, // 0034 CALL R15 3 + 0x902A2714, // 0035 SETMBR R10 K19 K20 + 0x902A2B14, // 0036 SETMBR R10 K21 K20 + 0x902A2C08, // 0037 SETMBR R10 K22 R8 + 0x8C3C0117, // 0038 GETMET R15 R0 K23 + 0xB8460000, // 0039 GETNGBL R17 K0 + 0x88442312, // 003A GETMBR R17 R17 K18 + 0xB84A0000, // 003B GETNGBL R18 K0 + 0x88482518, // 003C GETMBR R18 R18 K24 + 0x30442212, // 003D OR R17 R17 R18 + 0x7C3C0400, // 003E CALL R15 2 + 0x8C400119, // 003F GETMET R16 R0 K25 + 0xB84A0000, // 0040 GETNGBL R18 K0 + 0x88482512, // 0041 GETMBR R18 R18 K18 + 0xB84E0000, // 0042 GETNGBL R19 K0 + 0x884C2718, // 0043 GETMBR R19 R19 K24 + 0x30482413, // 0044 OR R18 R18 R19 + 0x7C400400, // 0045 CALL R16 2 + 0x60440010, // 0046 GETGBL R17 G16 + 0x404A3506, // 0047 CONNECT R18 K26 K6 + 0x7C440200, // 0048 CALL R17 1 + 0xA8020024, // 0049 EXBLK 0 #006F + 0x5C482200, // 004A MOVE R18 R17 + 0x7C480000, // 004B CALL R18 0 + 0x884C011C, // 004C GETMBR R19 R0 K28 + 0x00502514, // 004D ADD R20 R18 K20 + 0x54560013, // 004E LDINT R21 20 + 0x08502815, // 004F MUL R20 R20 R21 + 0x284C2614, // 0050 GE R19 R19 R20 + 0x784E0001, // 0051 JMPF R19 #0054 + 0x5C4C1E00, // 0052 MOVE R19 R15 + 0x70020000, // 0053 JMP #0055 + 0x5C4C2000, // 0054 MOVE R19 R16 + 0x902A3613, // 0055 SETMBR R10 K27 R19 + 0x004C1C05, // 0056 ADD R19 R14 R5 + 0x044C2714, // 0057 SUB R19 R19 K20 + 0x044C2609, // 0058 SUB R19 R19 R9 + 0x902A3A13, // 0059 SETMBR R10 K29 R19 + 0x004C1007, // 005A ADD R19 R8 R7 + 0x084C2413, // 005B MUL R19 R18 R19 + 0x004C1A13, // 005C ADD R19 R13 R19 + 0x004C2609, // 005D ADD R19 R19 R9 + 0x902A3C13, // 005E SETMBR R10 K30 R19 + 0x044E0C12, // 005F SUB R19 K6 R18 + 0x04500A08, // 0060 SUB R20 R5 R8 + 0x084C2614, // 0061 MUL R19 R19 R20 + 0x54520003, // 0062 LDINT R20 4 + 0x0C4C2614, // 0063 DIV R19 R19 R20 + 0x004C1C13, // 0064 ADD R19 R14 R19 + 0x004C2609, // 0065 ADD R19 R19 R9 + 0x902A3E13, // 0066 SETMBR R10 K31 R19 + 0x884C151E, // 0067 GETMBR R19 R10 K30 + 0x902A4013, // 0068 SETMBR R10 K32 R19 + 0xB84E0000, // 0069 GETNGBL R19 K0 + 0x8C4C2721, // 006A GETMET R19 R19 K33 + 0x5C541800, // 006B MOVE R21 R12 + 0x5C581400, // 006C MOVE R22 R10 + 0x7C4C0600, // 006D CALL R19 3 + 0x7001FFDA, // 006E JMP #004A + 0x58440022, // 006F LDCONST R17 K34 + 0xAC440200, // 0070 CATCH R17 1 0 + 0xB0080000, // 0071 RAISE 2 R0 R0 + 0x80000000, // 0072 RET 0 }) ) ); @@ -1422,26 +1354,46 @@ be_local_closure(lv_signal_bars_widget_event, /* name */ /******************************************************************** -** Solidified function: get_percentage +** Solidified function: init ********************************************************************/ -be_local_closure(lv_signal_bars_get_percentage, /* name */ +be_local_closure(lv_signal_bars_init, /* name */ be_nested_proto( - 2, /* nstack */ - 1, /* argc */ + 6, /* nstack */ + 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(percentage), + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str_weak(_lvgl), + /* K1 */ be_nested_str_weak(create_custom_widget), + /* K2 */ be_nested_str_weak(percentage), + /* K3 */ be_nested_str_weak(area), + /* K4 */ be_nested_str_weak(lv), + /* K5 */ be_nested_str_weak(line_dsc), + /* K6 */ be_nested_str_weak(draw_line_dsc), }), - be_str_weak(get_percentage), + be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 + ( &(const binstruction[16]) { /* code */ + 0xB80A0000, // 0000 GETNGBL R2 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100000, // 0002 MOVE R4 R0 + 0x5C140200, // 0003 MOVE R5 R1 + 0x7C080600, // 0004 CALL R2 3 + 0x540A0063, // 0005 LDINT R2 100 + 0x90020402, // 0006 SETMBR R0 K2 R2 + 0xB80A0800, // 0007 GETNGBL R2 K4 + 0x8C080503, // 0008 GETMET R2 R2 K3 + 0x7C080200, // 0009 CALL R2 1 + 0x90020602, // 000A SETMBR R0 K3 R2 + 0xB80A0800, // 000B GETNGBL R2 K4 + 0x8C080506, // 000C GETMET R2 R2 K6 + 0x7C080200, // 000D CALL R2 1 + 0x90020A02, // 000E SETMBR R0 K5 R2 + 0x80000000, // 000F RET 0 }) ) ); @@ -1453,19 +1405,17 @@ be_local_closure(lv_signal_bars_get_percentage, /* name */ ********************************************************************/ extern const bclass be_class_lv_obj; be_local_class(lv_signal_bars, - 5, + 3, &be_class_lv_obj, - be_nested_map(9, + be_nested_map(7, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(percentage, 4), be_const_var(0) }, - { be_const_key_weak(p1, 5), be_const_var(1) }, - { be_const_key_weak(p2, -1), be_const_var(2) }, + { be_const_key_weak(set_percentage, 3), be_const_closure(lv_signal_bars_set_percentage_closure) }, { be_const_key_weak(get_percentage, -1), be_const_closure(lv_signal_bars_get_percentage_closure) }, - { be_const_key_weak(line_dsc, -1), be_const_var(4) }, - { be_const_key_weak(area, -1), be_const_var(3) }, + { be_const_key_weak(percentage, -1), be_const_var(0) }, + { be_const_key_weak(area, 6), be_const_var(1) }, + { be_const_key_weak(line_dsc, 2), be_const_var(2) }, { be_const_key_weak(init, -1), be_const_closure(lv_signal_bars_init_closure) }, { be_const_key_weak(widget_event, -1), be_const_closure(lv_signal_bars_widget_event_closure) }, - { be_const_key_weak(set_percentage, 3), be_const_closure(lv_signal_bars_set_percentage_closure) }, })), be_str_weak(lv_signal_bars) ); diff --git a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/Adafruit_LvGL_Glue.cpp b/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/Adafruit_LvGL_Glue.cpp deleted file mode 100755 index 2e433ee9e..000000000 --- a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/Adafruit_LvGL_Glue.cpp +++ /dev/null @@ -1,267 +0,0 @@ -#include "Adafruit_LvGL_Glue.h" -#include -#include "lv_berry.h" - -// ARCHITECTURE-SPECIFIC TIMER STUFF --------------------------------------- - -extern void lv_flush_callback(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p); - -// Tick interval for LittlevGL internal timekeeping; 1 to 10 ms recommended -static const int lv_tick_interval_ms = 5; - -static void lv_tick_handler(void) { lv_tick_inc(lv_tick_interval_ms); } - -// TOUCHSCREEN STUFF ------------------------------------------------------- - - -uint32_t Touch_Status(int32_t sel); - -static void touchscreen_read(lv_indev_drv_t *indev_drv, lv_indev_data_t *data) { - data->point.x = Touch_Status(1); // Last-pressed coordinates - data->point.y = Touch_Status(2); - data->state = Touch_Status(0) ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; - data->continue_reading = false; /*No buffering now so no more data read*/ - // keep data for TS calibration - lv_ts_calibration.state = data->state; - if (data->state == LV_INDEV_STATE_PRESSED) { // if not pressed, the data may be invalid - lv_ts_calibration.x = data->point.x; - lv_ts_calibration.y = data->point.y; - lv_ts_calibration.raw_x = Touch_Status(-1); - lv_ts_calibration.raw_y = Touch_Status(-2); - } -} - -// OTHER LITTLEVGL VITALS -------------------------------------------------- - -#if LV_COLOR_DEPTH != 16 -#pragma error("LV_COLOR_DEPTH must be 16") -#endif -// This isn't necessarily true, don't mention it for now. See notes later. -//#if LV_COLOR_16_SWAP != 0 -// #pragma message("Set LV_COLOR_16_SWAP to 0 for best display performance") -//#endif - -// Actual RAM usage will be 2X these figures, since using 2 DMA buffers... -#define LV_BUFFER_ROWS 60 // Most others have a bit more space - - -// // This is the flush function required for LittlevGL screen updates. -// // It receives a bounding rect and an array of pixel data (conveniently -// // already in 565 format, so the Earth was lucky there). -// static void lv_flush_callback(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) { -// // Get pointer to glue object from indev user data -// Adafruit_LvGL_Glue *glue = (Adafruit_LvGL_Glue *)disp->user_data; - -// uint16_t width = (area->x2 - area->x1 + 1); -// uint16_t height = (area->y2 - area->y1 + 1); - -// // check if we are currently doing a screenshot -// if (glue->getScreenshotFile() != nullptr) { -// // save pixels to file -// int32_t btw = (width * height * LV_COLOR_DEPTH + 7) / 8; -// while (btw > 0) { -// int32_t ret = glue->getScreenshotFile()->write((const uint8_t*) color_p, btw); -// if (ret >= 0) { -// btw -= ret; -// } else { -// btw = 0; // abort -// } -// } -// lv_disp_flush_ready(disp); -// return; // ok -// // } - -// Renderer *display = glue->display; - -// if (!glue->first_frame) { -// //display->dmaWait(); // Wait for prior DMA transfer to complete -// //display->endWrite(); // End transaction from any prior call -// } else { -// glue->first_frame = false; -// } - -// display->setAddrWindow(area->x1, area->y1, area->x1+width, area->y1+height); -// display->pushColors((uint16_t *)color_p, width * height, true); -// display->setAddrWindow(0,0,0,0); - -// lv_disp_flush_ready(disp); - -// } - -// #if (LV_USE_LOG) -// // Optional LittlevGL debug print function, writes to Serial if debug is -// // enabled when calling glue begin() function. -// static void lv_debug(lv_log_level_t level, const char *file, uint32_t line, const char *fname, -// const char *dsc) { -// Serial.print(file); -// Serial.write('@'); -// Serial.print(line); -// Serial.print(":"); -// Serial.print(fname); -// Serial.write("->"); -// Serial.println(dsc); -// } -// #endif - - -// GLUE LIB FUNCTIONS ------------------------------------------------------ - -// Constructor -/** - * @brief Construct a new Adafruit_LvGL_Glue::Adafruit_LvGL_Glue object, - * initializing minimal variables - * - */ -Adafruit_LvGL_Glue::Adafruit_LvGL_Glue(void) - : first_frame(true), lv_pixel_buf(NULL) { -} - -// Destructor -/** - * @brief Destroy the Adafruit_LvGL_Glue::Adafruit_LvGL_Glue object, freeing any - * memory previously allocated within this library. - * - */ -Adafruit_LvGL_Glue::~Adafruit_LvGL_Glue(void) { - delete[] lv_pixel_buf; - // Probably other stuff that could be deallocated here -} - -// begin() function is overloaded for STMPE610 touch, ADC touch, or none. - -// Pass in POINTERS to ALREADY INITIALIZED display & touch objects (user code -// should have previously called corresponding begin() functions and checked -// return states before invoking this), -// they are NOT initialized here. Debug arg is -// touch arg can be NULL (or left off) if using LittlevGL as a passive widget -// display. - -/** - * @brief Configure the glue layer and the underlying LvGL code to use the given - * TFT display driver instance and touchscreen controller - * - * @param tft Pointer to an **already initialized** display object instance - * @param touch Pointer to an **already initialized** `Adafruit_STMPE610` - * touchscreen controller object instance - * @param debug Debug flag to enable debug messages. Only used if LV_USE_LOG is - * configured in LittleLVGL's lv_conf.h - * @return LvGLStatus The status of the initialization: - * * LVGL_OK : Success - * * LVGL_ERR_TIMER : Failure to set up timers - * * LVGL_ERR_ALLOC : Failure to allocate memory - */ -// LvGLStatus Adafruit_LvGL_Glue::begin(uDisplay_lvgl *tft, -// Adafruit_STMPE610 *touch, bool debug) { -// is_adc_touch = false; -// return begin(tft, (void *)touch, debug); -// } -/** - * @brief Configure the glue layer and the underlying LvGL code to use the given - * TFT display driver and touchscreen controller instances - * - * @param tft Pointer to an **already initialized** display object instance - * @param touch Pointer to an **already initialized** `TouchScreen` touchscreen - * controller object instance - * @param debug Debug flag to enable debug messages. Only used if LV_USE_LOG is - * configured in LittleLVGL's lv_conf.h - * @return LvGLStatus The status of the initialization: - * * LVGL_OK : Success - * * LVGL_ERR_TIMER : Failure to set up timers - * * LVGL_ERR_ALLOC : Failure to allocate memory - */ -// LvGLStatus Adafruit_LvGL_Glue::begin(uDisplay_lvgl *tft, TouchScreen *touch, -// bool debug) { -// is_adc_touch = true; -// return begin(tft, (void *)touch, debug); -// } -/** - * @brief Configure the glue layer and the underlying LvGL code to use the given - * TFT display driver and touchscreen controller instances - * - * @param tft Pointer to an **already initialized** display object instance - * @param debug Debug flag to enable debug messages. Only used if LV_USE_LOG is - * configured in LittleLVGL's lv_conf.h - * @return LvGLStatus The status of the initialization: - * * LVGL_OK : Success - * * LVGL_ERR_TIMER : Failure to set up timers - * * LVGL_ERR_ALLOC : Failure to allocate memory - */ -LvGLStatus Adafruit_LvGL_Glue::begin(Renderer *tft, bool debug) { - return begin(tft, (void *)NULL, debug); -} - -LvGLStatus Adafruit_LvGL_Glue::begin(Renderer *tft, void *touch, bool debug) { - - lv_init(); - - // Allocate LvGL display buffer (x2 because DMA double buffering) - LvGLStatus status = LVGL_ERR_ALLOC; - // if ((lv_pixel_buf = new lv_color_t[LV_HOR_RES_MAX * LV_BUFFER_ROWS * 2])) { - - uint32_t lvgl_buffer_size; - - //lvgl_buffer_size = LV_HOR_RES_MAX * LV_BUFFER_ROWS; - uint8_t flushlines = tft->lvgl_pars()->fluslines; - lvgl_buffer_size = tft->width() * (flushlines ? flushlines:LV_BUFFER_ROWS); - if (tft->lvgl_pars()->use_dma) { - lvgl_buffer_size /= 2; - if (lvgl_buffer_size < 1000000) { - lv_pixel_buf2 = new lv_color_t[lvgl_buffer_size]; - } - if (!lv_pixel_buf2) { - return status; - } - } else { - lv_pixel_buf2 = nullptr; - } - - if ((lv_pixel_buf = new lv_color_t[lvgl_buffer_size])) { - - display = tft; - touchscreen = (void *)touch; - - // // Initialize LvGL display buffers - // lv_disp_buf_init( - // &lv_disp_buf, lv_pixel_buf, // 1st half buf - // &lv_pixel_buf[LV_HOR_RES_MAX * LV_BUFFER_ROWS], // 2nd half buf - // LV_HOR_RES_MAX * LV_BUFFER_ROWS); - - // Initialize LvGL display buffers - lv_disp_draw_buf_init( - &lv_disp_buf, lv_pixel_buf, // 1st half buf - lv_pixel_buf2, // 2nd half buf - lvgl_buffer_size); - - // Initialize LvGL display driver - lv_disp_drv_init(&lv_disp_drv); - lv_disp_drv.hor_res = tft->width(); - lv_disp_drv.ver_res = tft->height(); - lv_disp_drv.flush_cb = lv_flush_callback; - lv_disp_drv.draw_buf = &lv_disp_buf; - lv_disp_drv.user_data = (void*)this; - lv_disp_drv_register(&lv_disp_drv); - - // Initialize LvGL input device (touchscreen already started) - if (touch) { // Can also pass NULL if passive widget display - lv_indev_drv_init(&lv_indev_drv); // Basic init - lv_indev_drv.type = LV_INDEV_TYPE_POINTER; // Is pointer dev - lv_indev_drv.read_cb = touchscreen_read; // Read callback - lv_indev_drv.user_data = (void*)this; - lv_input_dev_ptr = lv_indev_drv_register(&lv_indev_drv); - } - - // TIMER SETUP is architecture-specific ---------------------------- - - // ESP 32------------------------------------------------ - tick.attach_ms(lv_tick_interval_ms, lv_tick_handler); - status = LVGL_OK; - // ----------------------------------------- - } - - if (status != LVGL_OK) { - delete[] lv_pixel_buf; - lv_pixel_buf = NULL; - } - - return status; -} diff --git a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/Adafruit_LvGL_Glue.h b/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/Adafruit_LvGL_Glue.h deleted file mode 100755 index 2074e0c7a..000000000 --- a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/Adafruit_LvGL_Glue.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef _ADAFRUIT_LVGL_GLUE_H_ -#define _ADAFRUIT_LVGL_GLUE_H_ - -#include // LittlevGL core lib -#include -#include // ESP32-specific timer lib -#include - -typedef enum { - LVGL_OK, - LVGL_ERR_ALLOC, - LVGL_ERR_TIMER, -} LvGLStatus; - -/** - * @brief Class to act as a "glue" layer between the LvGL graphics library and - * most of Adafruit's TFT displays - * - */ - -class Adafruit_LvGL_Glue { -public: - Adafruit_LvGL_Glue(void); - ~Adafruit_LvGL_Glue(void); - // Different begin() funcs for STMPE610, ADC or no touch - // LvGLStatus begin(uDisplay_lvgl *tft, Adafruit_STMPE610 *touch, - // bool debug = false); - // LvGLStatus begin(uDisplay_lvgl *tft, TouchScreen *touch, - // bool debug = false); - LvGLStatus begin(Renderer *tft, bool debug = false); - LvGLStatus begin(Renderer *tft, void *touch, bool debug); - // These items need to be public for some internal callbacks, - // but should be avoided by user code please! - Renderer *display; ///< Pointer to the SPITFT display instance - void *touchscreen; ///< Pointer to the touchscreen object to use - bool is_adc_touch; ///< determines if the touchscreen controlelr is ADC based - bool first_frame; ///< Tracks if a call to `lv_flush_callback` needs to wait - ///< for DMA transfer to complete - void setScreenshotFile(File *f) { screenshot = f; } - File * getScreenshotFile(void) const { return screenshot; } - void stopScreenshot(void) { screenshot = nullptr; } - -private: - lv_disp_drv_t lv_disp_drv; - lv_disp_draw_buf_t lv_disp_buf; - lv_color_t *lv_pixel_buf; - lv_color_t *lv_pixel_buf2; - lv_indev_drv_t lv_indev_drv; - lv_indev_t *lv_input_dev_ptr; - Ticker tick; - File * screenshot = nullptr; -}; - -#endif // _ADAFRUIT_LVGL_GLUE_H_ diff --git a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/README.md b/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/README.md deleted file mode 100755 index 61a79f988..000000000 --- a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# Adafruit LvGL Glue [![Build Status](https://github.com/adafruit/Adafruit_LvGL_Glue/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_LvGL_Glue/actions) - -This Arduino library provides a layer between LittlevGL (a UI library for -embedded systems) and most of Adafruit's color TFT displays (anything that's -a subclass of SPITFT). - -Examples show basic use on PyPortal, FeatherWing, CLUE and TFT Gizmo. -Use these as a starting point, see LittlevGL documentation at -docs.littlevgl.com for a thorough explanation of capabilities and use. - -# Dependencies - * [LittlevGL](https://github.com/littlevgl/lvgl) - * [Adafruit GFX Library](https://github.com/adafruit/Adafruit-GFX-Library) - * [Adafruit HX8357 Library](https://github.com/adafruit/Adafruit_HX8357_Library) - * [Adafruit ILI9341](https://github.com/adafruit/Adafruit_ILI9341) - * [Adafruit ST7735 and ST7789 Library](https://github.com/adafruit/Adafruit-ST7735-Library) - * [Adafruit STMPE610](https://github.com/adafruit/Adafruit_STMPE610) - * [Adafruit TouchScreen](https://github.com/adafruit/Adafruit_TouchScreen) - * [Adafruit Zero DMA Library](https://github.com/adafruit/Adafruit_ZeroDMA) - * [Adafruit ZeroTimer Library](https://github.com/adafruit/Adafruit_ZeroTimer) - -# Compatibility -Version 2.0.0 is a breaking change, mostly due to significant structural -changes in the LittlevGL library for Arduino. If you were previously using -an earlier version of this library and/or LittlevGL, both will need updating, -and you should skim the examples and read through the hello_changes example -specifically. - -Use on M0 (SAMD21) boards isn't recommended anymore, as LittlevGL has grown. -Simple programs might still work, but it's better to move up to a device -with more RAM -- M4 (SAMD51), nRF52 and ESP32 are currently supported. - -# Contributing -Contributions are welcome! Please read our [Code of Conduct](https://github.com/adafruit/Adafruit_LvGL_Glue/blob/master/CODE_OF_CONDUCT.md>) -before contributing to help this project stay welcoming. - -## Documentation and doxygen -Documentation is produced by doxygen. Contributions should include documentation for any new code added. - -Some examples of how to use doxygen can be found in these guide pages: - -https://learn.adafruit.com/the-well-automated-arduino-library/doxygen - -https://learn.adafruit.com/the-well-automated-arduino-library/doxygen-tips - -Written by Phil Burgess aka Paint Your Dragon for Adafruit Industries. -BSD license, check license.txt for more information -All text above must be included in any redistribution - -To install, use the Arduino Library Manager and search for "Adafruit LvGL Glue Library" and install the library. diff --git a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/code-of-conduct.md b/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/code-of-conduct.md deleted file mode 100755 index 8ee6e4498..000000000 --- a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/code-of-conduct.md +++ /dev/null @@ -1,127 +0,0 @@ -# Adafruit Community Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and leaders pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level or type of -experience, education, socio-economic status, nationality, personal appearance, -race, religion, or sexual identity and orientation. - -## Our Standards - -We are committed to providing a friendly, safe and welcoming environment for -all. - -Examples of behavior that contributes to creating a positive environment -include: - -* Be kind and courteous to others -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Collaborating with other community members -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and sexual attention or advances -* The use of inappropriate images, including in a community member's avatar -* The use of inappropriate language, including in a community member's nickname -* Any spamming, flaming, baiting or other attention-stealing behavior -* Excessive or unwelcome helping; answering outside the scope of the question - asked -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate - -The goal of the standards and moderation guidelines outlined here is to build -and maintain a respectful community. We ask that you don’t just aim to be -"technically unimpeachable", but rather try to be your best self. - -We value many things beyond technical expertise, including collaboration and -supporting others within our community. Providing a positive experience for -other community members can have a much more significant impact than simply -providing the correct answer. - -## Our Responsibilities - -Project leaders are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project leaders have the right and responsibility to remove, edit, or -reject messages, comments, commits, code, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any community member for other behaviors that they deem -inappropriate, threatening, offensive, or harmful. - -## Moderation - -Instances of behaviors that violate the Adafruit Community Code of Conduct -may be reported by any member of the community. Community members are -encouraged to report these situations, including situations they witness -involving other community members. - -You may report in the following ways: - -In any situation, you may send an email to . - -On the Adafruit Discord, you may send an open message from any channel -to all Community Helpers by tagging @community helpers. You may also send an -open message from any channel, or a direct message to @kattni#1507, -@tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or -@Andon#8175. - -Email and direct message reports will be kept confidential. - -In situations on Discord where the issue is particularly egregious, possibly -illegal, requires immediate action, or violates the Discord terms of service, -you should also report the message directly to Discord. - -These are the steps for upholding our community’s standards of conduct. - -1. Any member of the community may report any situation that violates the -Adafruit Community Code of Conduct. All reports will be reviewed and -investigated. -2. If the behavior is an egregious violation, the community member who -committed the violation may be banned immediately, without warning. -3. Otherwise, moderators will first respond to such behavior with a warning. -4. Moderators follow a soft "three strikes" policy - the community member may -be given another chance, if they are receptive to the warning and change their -behavior. -5. If the community member is unreceptive or unreasonable when warned by a -moderator, or the warning goes unheeded, they may be banned for a first or -second offense. Repeated offenses will result in the community member being -banned. - -## Scope - -This Code of Conduct and the enforcement policies listed above apply to all -Adafruit Community venues. This includes but is not limited to any community -spaces (both public and private), the entire Adafruit Discord server, and -Adafruit GitHub repositories. Examples of Adafruit Community spaces include -but are not limited to meet-ups, audio chats on the Adafruit Discord, or -interaction at a conference. - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. As a community -member, you are representing our community, and are expected to behave -accordingly. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 1.4, available at -, -and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html). - -For other projects adopting the Adafruit Community Code of -Conduct, please contact the maintainers of those projects for enforcement. -If you wish to use this code of conduct for your own project, consider -explicitly mentioning your moderation policy or making a copy with your -own moderation policy so as to avoid confusion. diff --git a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/library.json b/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/library.json deleted file mode 100644 index c6c7aff6c..000000000 --- a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/library.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "Adafruit LittlevGL Glue Library", - "description": "This library works in conjunction with LittlevGL (an embedded system GUI library) and Adafruit display-specific libraries to provide nice user interfaces on PyPortal, TFT FeatherWings, and more.", - "version": "2.0.0", - "homepage": "https://github.com/adafruit/Adafruit_LvGL_Glue", - "frameworks": "*", - "build": { - "flags": [ "-Wno-deprecated-enum-enum-conversion" ] - } -} diff --git a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/library.properties b/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/library.properties deleted file mode 100755 index c09ddcace..000000000 --- a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/library.properties +++ /dev/null @@ -1,10 +0,0 @@ -name=Adafruit LittlevGL Glue Library -version=2.0.0 -author=Adafruit -maintainer=Adafruit -sentence=Simplifies use of LittlevGL library with Adafruit displays. -paragraph=This library works in conjunction with LittlevGL (an embedded system GUI library) and Adafruit display-specific libraries to provide nice user interfaces on PyPortal, TFT FeatherWings, and more. -category=Display -url=https://github.com/adafruit/Adafruit_LvGL_Glue -architectures=samd, nrf52, esp32 -depends=Adafruit GFX Library, Adafruit TouchScreen, Adafruit STMPE610, Adafruit Zero DMA Library, Adafruit HX8357 Library, Adafruit ILI9341, Adafruit ZeroTimer Library, Adafruit ST7735 and ST7789 Library, lvgl diff --git a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/license.txt b/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/license.txt deleted file mode 100755 index a61cb1df4..000000000 --- a/lib/libesp32_lvgl/Adafruit_LvGL_Glue-shadinger/license.txt +++ /dev/null @@ -1,26 +0,0 @@ -Software License Agreement (BSD License) - -Copyright (c) 2020 Phil Burgess aka Paint Your Dragon for Adafruit Industries -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: -1. Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. -3. Neither the name of the copyright holders nor the -names of its contributors may be used to endorse or promote products -derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/libesp32_lvgl/LVGL_assets/TASMOTA_Symbol_64.png b/lib/libesp32_lvgl/LVGL_assets/TASMOTA_Symbol_64.png new file mode 100644 index 0000000000000000000000000000000000000000..c17a80cb773336fa9133aa4200a9d40c561807cc GIT binary patch literal 3003 zcmY*bc|4SD7k&mqgixeVk`Y(bAzAjs45hXM+A!%%uB`R?VdUH$I|OxDo1eF(}zLPv#uuYb--aB=*%lDqe>wrCAPkG?=*0E1hE>yEKpo`1`% z^x!4uh0J)~O3Jd?a$xmM+hx9Qe4|6F%>ky>3pc2F#(pmqz^`aYA@Hw`i0LfV0*v%5AHF&xvpzkGp@-QORLtqnxSq&pAYwqEHq6 z1Tk?R1p;qVCabfT%kq&9_I%GS-ZrINC<&Az>hbr7XzVqHCTe`S;};#^KHwg~8tfLj zHijTkFRpZyzf#k_?rSE=T;Q&hFuG<_lbQz*rz66KT^Hjn9pGh+(dE5%WltJE1) zBFmQ_pT6{2WsF_ibaO1;(9}3dds-udJzz##jEHcK;i|}P;5`$flV=$xj?%2AF`P$~ z47Fp}#`i$-q8Fmr>z-hVSW1@I2jBba?RL%7qJz7<=x?RTf>c{8t9s;823jwX2g!I4 z6_t7NV>)+W%IH<}yx(fyCW2C2_k?P-r`m-SAeG?tcnB+WJ-BN~hy zOi#q|zglEwMGlF#Z$wT$C4Ah-zPpQDe3Y%Z@%7!Ox%d#>zzYAO;jkdA`sUTRrP!7e zw>Q~ElXhU>I{nZ_H=vtOV0jb4mD6Xge1Y2i)^{}zO(uW!#Zo{_Qm1zr`vj^EQbTU8 zGcFB+vR-S#R3NH8rNcd;`wya0F)nGb`{e*Af)fZ?7igI^drgIC-{c5LqtdE}Hy_N3g`&R{d4>|Pgi|Hh09>zfGPdjP3{8xVu zvp?J+PECIA^{ur=reW<>v05V8h9ExXPHE8<4SB!(5+YbqPx6SOC)rVn1tv51B)hD* z<6_|@9O{EX5`n(gRbQUAhBhZ=se?=76Ygr1VP1gd%=nfkws#k5AVRHCGGAhz1em@ z#zAkl(UohK!yuGprXH(+q*O{3ZBRr2%i%B^wx(?YYasrLDQNAjDx^NDxEYT@ znxG}bM{CnZ3Lif@)%hT;ptl6%PvHo=z8b61%luiy`gtK$9yC8XTf6p!$ljRtV~>+- zM0+lO-Obu2yV*IvlpMK$4058}eFd>}6?@UwRv26vkvQOl9PXX;vY46(*9F3{dn0ur z)*&gg0&c$PGNzX8nYErR44u3g89wEU;FQn{(L8TY?K3TiL z>fd?GMWkiewWf*^IMJ~UAD3Q_STyjWI2q$GKg4CAa6{uYm|V``sC;81&lJVeexEB? zBc{^3^859AJAzOW#7?)c)+wh~_N`vIN$~lCKIKsEyyyZI_f~ntw)?hd^hr_>Oupl+ z(Ad-GMqfm%n_azvxI|-24*1c9qL7R;i)T2)?3egHNHbqkEOhKpxf;FUgUAit|8{ft zoRZjEk@!%w<+C}ZfHm9R>9q~L?}|)?=3Xql_l$cf-zkdX(g5eRV&1nW@3qZPP@-) zT%hB?PK`%lKyevW1jM+dYmTh0XULlwn;^&($d!6`RY9;*^tQq0yP)bZ@5?qTX(%b> z^qn7ZsFnIu4~F1pysmY+zK&Xll}iN<3#ZC#qwmis$dswk#xyYHm(1|4=Nuj#OFywb zoY7M6qMyxD8o9I>b-hFN#vU(+z61yZ{x0nQZ0ZF7iA?x}nf%&*4ZnXa-aw^Qq)H(Y z$~|?G3K%U&0J!uA)K~H{3WmMttX7!NE)Y z9Sb|j-Q25LlPe0a(83Q;5MxMW^KKs}mM&dmTPIL^;?)>;Xv1`?+M4+tNxJnsS+%;u z1{167j_^Ar4Camxv4K>(p~zsISVDg5-~D!DENym^J-IcY#HXq5NQIY&b;%O}x4bW| zn0nCcsLI?xCZ6-B>uq~^VP|SSr9>Yj;ChzVLo2Tni2wNnVqI0 TW{F3?>42`LfkrXX?(Tm8t$|q$ literal 0 HcmV?d00001 diff --git a/tasmota/lvgl_berry/fonts/DSEG7/DSEG-LICENSE.txt b/lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/DSEG-LICENSE.txt similarity index 100% rename from tasmota/lvgl_berry/fonts/DSEG7/DSEG-LICENSE.txt rename to lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/DSEG-LICENSE.txt diff --git a/tasmota/lvgl_berry/fonts/DSEG7/DSEG7Classic-Bold.ttf b/lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/DSEG7Classic-Bold.ttf similarity index 100% rename from tasmota/lvgl_berry/fonts/DSEG7/DSEG7Classic-Bold.ttf rename to lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/DSEG7Classic-Bold.ttf diff --git a/tasmota/lvgl_berry/fonts/DSEG7/DSEG7Classic-BoldItalic.ttf b/lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/DSEG7Classic-BoldItalic.ttf similarity index 100% rename from tasmota/lvgl_berry/fonts/DSEG7/DSEG7Classic-BoldItalic.ttf rename to lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/DSEG7Classic-BoldItalic.ttf diff --git a/tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_10.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_10.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_10.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_10.lvfont diff --git a/tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_12.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_12.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_12.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_12.lvfont diff --git a/tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_14.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_14.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_14.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_14.lvfont diff --git a/tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_16.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_16.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_16.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_16.lvfont diff --git a/tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_18.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_18.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_18.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_18.lvfont diff --git a/tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_20.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_20.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_20.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_20.lvfont diff --git a/tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_24.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_24.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_24.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_24.lvfont diff --git a/tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_28.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_28.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_28.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_28.lvfont diff --git a/tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_36.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_36.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_36.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_36.lvfont diff --git a/tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_48.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_48.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_48.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_48.lvfont diff --git a/tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_8.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_8.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/DSEG7/font_files/seg7_8.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/font_files/seg7_8.lvfont diff --git a/tasmota/lvgl_berry/fonts/DSEG7/gen_seg7_fonts.bash b/lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/gen_seg7_fonts.bash similarity index 100% rename from tasmota/lvgl_berry/fonts/DSEG7/gen_seg7_fonts.bash rename to lib/libesp32_lvgl/LVGL_assets/fonts/DSEG7/gen_seg7_fonts.bash diff --git a/tasmota/lvgl_berry/fonts/pixel_perfect/Berkelium (GEOS)/Berkelium1541.ttf b/lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Berkelium (GEOS)/Berkelium1541.ttf similarity index 100% rename from tasmota/lvgl_berry/fonts/pixel_perfect/Berkelium (GEOS)/Berkelium1541.ttf rename to lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Berkelium (GEOS)/Berkelium1541.ttf diff --git a/tasmota/lvgl_berry/fonts/pixel_perfect/Berkelium (GEOS)/Berkelium64.ttf b/lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Berkelium (GEOS)/Berkelium64.ttf similarity index 100% rename from tasmota/lvgl_berry/fonts/pixel_perfect/Berkelium (GEOS)/Berkelium64.ttf rename to lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Berkelium (GEOS)/Berkelium64.ttf diff --git a/tasmota/lvgl_berry/fonts/pixel_perfect/Berkelium (GEOS)/FreeLicense.txt b/lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Berkelium (GEOS)/FreeLicense.txt similarity index 100% rename from tasmota/lvgl_berry/fonts/pixel_perfect/Berkelium (GEOS)/FreeLicense.txt rename to lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Berkelium (GEOS)/FreeLicense.txt diff --git a/tasmota/lvgl_berry/fonts/pixel_perfect/Berkelium64.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Berkelium64.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/pixel_perfect/Berkelium64.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Berkelium64.lvfont diff --git a/tasmota/lvgl_berry/fonts/pixel_perfect/Daniel Linssen/m3x6.ttf b/lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Daniel Linssen/m3x6.ttf similarity index 100% rename from tasmota/lvgl_berry/fonts/pixel_perfect/Daniel Linssen/m3x6.ttf rename to lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Daniel Linssen/m3x6.ttf diff --git a/tasmota/lvgl_berry/fonts/pixel_perfect/Daniel Linssen/m5x7.ttf b/lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Daniel Linssen/m5x7.ttf similarity index 100% rename from tasmota/lvgl_berry/fonts/pixel_perfect/Daniel Linssen/m5x7.ttf rename to lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Daniel Linssen/m5x7.ttf diff --git a/tasmota/lvgl_berry/fonts/pixel_perfect/PrintChar (Apple II Font)/FreeLicense.txt b/lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/PrintChar (Apple II Font)/FreeLicense.txt similarity index 100% rename from tasmota/lvgl_berry/fonts/pixel_perfect/PrintChar (Apple II Font)/FreeLicense.txt rename to lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/PrintChar (Apple II Font)/FreeLicense.txt diff --git a/tasmota/lvgl_berry/fonts/pixel_perfect/PrintChar (Apple II Font)/PrintChar21.ttf b/lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/PrintChar (Apple II Font)/PrintChar21.ttf similarity index 100% rename from tasmota/lvgl_berry/fonts/pixel_perfect/PrintChar (Apple II Font)/PrintChar21.ttf rename to lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/PrintChar (Apple II Font)/PrintChar21.ttf diff --git a/tasmota/lvgl_berry/fonts/pixel_perfect/PrintChar21.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/PrintChar21.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/pixel_perfect/PrintChar21.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/PrintChar21.lvfont diff --git a/tasmota/lvgl_berry/fonts/pixel_perfect/Shaston (GSOS)/FreeLicense.txt b/lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Shaston (GSOS)/FreeLicense.txt similarity index 100% rename from tasmota/lvgl_berry/fonts/pixel_perfect/Shaston (GSOS)/FreeLicense.txt rename to lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Shaston (GSOS)/FreeLicense.txt diff --git a/tasmota/lvgl_berry/fonts/pixel_perfect/Shaston (GSOS)/Shaston320.ttf b/lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Shaston (GSOS)/Shaston320.ttf similarity index 100% rename from tasmota/lvgl_berry/fonts/pixel_perfect/Shaston (GSOS)/Shaston320.ttf rename to lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Shaston (GSOS)/Shaston320.ttf diff --git a/tasmota/lvgl_berry/fonts/pixel_perfect/Shaston320.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Shaston320.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/pixel_perfect/Shaston320.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/Shaston320.lvfont diff --git a/tasmota/lvgl_berry/fonts/pixel_perfect/m3x6.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/m3x6.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/pixel_perfect/m3x6.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/m3x6.lvfont diff --git a/tasmota/lvgl_berry/fonts/pixel_perfect/m5x7.lvfont b/lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/m5x7.lvfont similarity index 100% rename from tasmota/lvgl_berry/fonts/pixel_perfect/m5x7.lvfont rename to lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/m5x7.lvfont diff --git a/tasmota/lvgl_berry/fonts/pixel_perfect/pages.jsonl b/lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/pages.jsonl similarity index 100% rename from tasmota/lvgl_berry/fonts/pixel_perfect/pages.jsonl rename to lib/libesp32_lvgl/LVGL_assets/fonts/pixel_perfect/pages.jsonl diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_12_latin1.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_12_latin1.c index b9b8dae13..d3e11753b 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_12_latin1.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_12_latin1.c @@ -2084,9 +2084,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -2100,9 +2099,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 3, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -2111,7 +2107,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t robotocondensed_regular_12_latin1 = { #else lv_font_t robotocondensed_regular_12_latin1 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_14_latin1.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_14_latin1.c index 194954f87..1c173bff7 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_14_latin1.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_14_latin1.c @@ -2335,9 +2335,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -2351,9 +2350,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 3, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -2362,7 +2358,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t robotocondensed_regular_14_latin1 = { #else lv_font_t robotocondensed_regular_14_latin1 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_16_latin1.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_16_latin1.c index 56666d4af..b905c14c3 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_16_latin1.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_16_latin1.c @@ -2536,9 +2536,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -2552,9 +2551,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 3, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -2563,7 +2559,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t robotocondensed_regular_16_latin1 = { #else lv_font_t robotocondensed_regular_16_latin1 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_20_latin1.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_20_latin1.c index 6198d0448..347d18f96 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_20_latin1.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_20_latin1.c @@ -3076,9 +3076,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -3092,9 +3091,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 3, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -3103,7 +3099,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t robotocondensed_regular_20_latin1 = { #else lv_font_t robotocondensed_regular_20_latin1 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_22_latin1.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_22_latin1.c index 1ec74432d..baaefe4cb 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_22_latin1.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_22_latin1.c @@ -3371,9 +3371,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -3387,9 +3386,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 3, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -3398,7 +3394,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t robotocondensed_regular_22_latin1 = { #else lv_font_t robotocondensed_regular_22_latin1 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_24_latin1.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_24_latin1.c index 70b8e27d7..b0f597095 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_24_latin1.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_24_latin1.c @@ -3527,9 +3527,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -3543,9 +3542,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 3, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -3554,7 +3550,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t robotocondensed_regular_24_latin1 = { #else lv_font_t robotocondensed_regular_24_latin1 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_26_latin1.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_26_latin1.c index 83dd586a5..e451f4421 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_26_latin1.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_26_latin1.c @@ -3952,9 +3952,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -3968,9 +3967,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 3, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -3979,7 +3975,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t robotocondensed_regular_26_latin1 = { #else lv_font_t robotocondensed_regular_26_latin1 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_28_latin1.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_28_latin1.c index 63bd194cc..fb4b659e5 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_28_latin1.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_28_latin1.c @@ -4309,9 +4309,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -4325,9 +4324,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 3, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -4336,7 +4332,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t robotocondensed_regular_28_latin1 = { #else lv_font_t robotocondensed_regular_28_latin1 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_32_latin1.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_32_latin1.c index 0e02875c7..6b40bec58 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_32_latin1.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_32_latin1.c @@ -4930,9 +4930,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -4946,9 +4945,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 3, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -4957,7 +4953,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t robotocondensed_regular_32_latin1 = { #else lv_font_t robotocondensed_regular_32_latin1 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_36_latin1.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_36_latin1.c index 80bdaf56c..b643f81af 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_36_latin1.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_36_latin1.c @@ -5714,9 +5714,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -5730,9 +5729,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 3, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -5741,7 +5737,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t robotocondensed_regular_36_latin1 = { #else lv_font_t robotocondensed_regular_36_latin1 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_38_latin1.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_38_latin1.c index 5f0aadd5c..f88b71d12 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_38_latin1.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_38_latin1.c @@ -6059,9 +6059,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -6075,9 +6074,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 3, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -6086,7 +6082,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t robotocondensed_regular_38_latin1 = { #else lv_font_t robotocondensed_regular_38_latin1 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_40_latin1.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_40_latin1.c index 6babc76ed..6fc146666 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_40_latin1.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_40_latin1.c @@ -6422,9 +6422,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -6438,9 +6437,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 3, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -6449,7 +6445,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t robotocondensed_regular_40_latin1 = { #else lv_font_t robotocondensed_regular_40_latin1 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_44_latin1.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_44_latin1.c index 581484546..d7df39045 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_44_latin1.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_44_latin1.c @@ -7114,9 +7114,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -7130,9 +7129,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 3, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -7141,7 +7137,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t robotocondensed_regular_44_latin1 = { #else lv_font_t robotocondensed_regular_44_latin1 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_48_latin1.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_48_latin1.c index 1f33d5fb6..d07465afa 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_48_latin1.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/roboto-latin1/robotocondensed_regular_48_latin1.c @@ -7613,9 +7613,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -7629,9 +7628,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 3, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -7640,7 +7636,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t robotocondensed_regular_48_latin1 = { #else lv_font_t robotocondensed_regular_48_latin1 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_10.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_10.c index 6539b03df..37f5e160d 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_10.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_10.c @@ -119,9 +119,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -135,9 +134,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 1, .kern_classes = 0, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -146,7 +142,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t seg7_10 = { #else lv_font_t seg7_10 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_12.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_12.c index 2f1415af4..531cc9320 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_12.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_12.c @@ -128,9 +128,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -144,9 +143,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 1, .kern_classes = 0, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -155,7 +151,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t seg7_12 = { #else lv_font_t seg7_12 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_14.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_14.c index 88ada73fd..4be4afd7d 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_14.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_14.c @@ -134,9 +134,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -150,9 +149,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 1, .kern_classes = 0, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -161,7 +157,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t seg7_14 = { #else lv_font_t seg7_14 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_16.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_16.c index 589ccb458..e679280b8 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_16.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_16.c @@ -137,9 +137,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -153,9 +152,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 1, .kern_classes = 0, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -164,7 +160,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t seg7_16 = { #else lv_font_t seg7_16 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_18.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_18.c index aee89f557..0298ae451 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_18.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_18.c @@ -143,9 +143,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -159,9 +158,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 1, .kern_classes = 0, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -170,7 +166,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t seg7_18 = { #else lv_font_t seg7_18 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_20.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_20.c index 3817fe7d0..6a9447c9b 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_20.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_20.c @@ -167,9 +167,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -183,9 +182,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 2, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -194,7 +190,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t seg7_20 = { #else lv_font_t seg7_20 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_24.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_24.c index 9e4e97689..c98bb056f 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_24.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_24.c @@ -183,9 +183,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -199,9 +198,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 2, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -210,7 +206,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t seg7_24 = { #else lv_font_t seg7_24 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_28.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_28.c index 9955fda17..caadd5f69 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_28.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_28.c @@ -210,9 +210,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -226,9 +225,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 2, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -237,7 +233,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t seg7_28 = { #else lv_font_t seg7_28 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_36.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_36.c index 41756ce93..9a32b1dfc 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_36.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_36.c @@ -257,9 +257,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -273,9 +272,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 2, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -284,7 +280,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t seg7_36 = { #else lv_font_t seg7_36 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_48.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_48.c index a09f554a6..05b106671 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_48.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_48.c @@ -316,9 +316,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -332,9 +331,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 2, .kern_classes = 0, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -343,7 +339,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t seg7_48 = { #else lv_font_t seg7_48 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_8.c b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_8.c index 296fa8d75..c98fa9e7c 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_8.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/fonts/seg7_8.c @@ -119,9 +119,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -135,9 +134,6 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 1, .kern_classes = 0, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; @@ -146,7 +142,7 @@ static lv_font_fmt_txt_dsc_t font_dsc = { *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t seg7_8 = { #else lv_font_t seg7_8 = { diff --git a/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_haspmota.c b/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_haspmota.c index 96f4c4c5e..6d891a1b5 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_haspmota.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_haspmota.c @@ -9,13 +9,13 @@ #include "../lvgl.h" /*To see all the widgets*/ #include "lv_theme_haspmota.h" -#include "misc/lv_gc.h" +// #include "misc/lv_gc.h" TODO /********************* * DEFINES *********************/ #define MODE_DARK 1 -#define RADIUS_DEFAULT (disp_size == DISP_LARGE ? lv_disp_dpx(theme.disp, 12) : lv_disp_dpx(theme.disp, 8)) +#define RADIUS_DEFAULT (disp_size == DISP_LARGE ? lv_display_dpx(theme.disp, 12) : lv_display_dpx(theme.disp, 8)) /*SCREEN*/ #define LIGHT_COLOR_SCR lv_palette_lighten(LV_PALETTE_GREY, 4) @@ -28,12 +28,12 @@ #define DARK_COLOR_GREY lv_color_hex(0x2f3237) #define TRANSITION_TIME LV_THEME_DEFAULT_TRANSITION_TIME -#define BORDER_WIDTH lv_disp_dpx(theme.disp, 2) -#define OUTLINE_WIDTH lv_disp_dpx(theme.disp, 3) +#define BORDER_WIDTH lv_display_dpx(theme.disp, 2) +#define OUTLINE_WIDTH lv_display_dpx(theme.disp, 3) -#define PAD_DEF (disp_size == DISP_LARGE ? lv_disp_dpx(theme.disp, 24) : disp_size == DISP_MEDIUM ? lv_disp_dpx(theme.disp, 20) : lv_disp_dpx(theme.disp, 16)) -#define PAD_SMALL (disp_size == DISP_LARGE ? lv_disp_dpx(theme.disp, 14) : disp_size == DISP_MEDIUM ? lv_disp_dpx(theme.disp, 12) : lv_disp_dpx(theme.disp, 10)) -#define PAD_TINY (disp_size == DISP_LARGE ? lv_disp_dpx(theme.disp, 8) : disp_size == DISP_MEDIUM ? lv_disp_dpx(theme.disp, 6) : lv_disp_dpx(theme.disp, 2)) +#define PAD_DEF (disp_size == DISP_LARGE ? lv_display_dpx(theme.disp, 24) : disp_size == DISP_MEDIUM ? lv_display_dpx(theme.disp, 20) : lv_display_dpx(theme.disp, 16)) +#define PAD_SMALL (disp_size == DISP_LARGE ? lv_display_dpx(theme.disp, 14) : disp_size == DISP_MEDIUM ? lv_display_dpx(theme.disp, 12) : lv_display_dpx(theme.disp, 10)) +#define PAD_TINY (disp_size == DISP_LARGE ? lv_display_dpx(theme.disp, 8) : disp_size == DISP_MEDIUM ? lv_display_dpx(theme.disp, 6) : lv_display_dpx(theme.disp, 2)) // OpenHASP specific /*BUTTON*/ @@ -261,7 +261,7 @@ static void style_init(void) LV_STYLE_BG_OPA, LV_STYLE_BG_COLOR, LV_STYLE_TRANSFORM_WIDTH, LV_STYLE_TRANSFORM_HEIGHT, LV_STYLE_TRANSLATE_Y, LV_STYLE_TRANSLATE_X, - LV_STYLE_TRANSFORM_ZOOM, LV_STYLE_TRANSFORM_ANGLE, + /*LV_STYLE_TRANSFORM_ZOOM_X, LV_STYLE_TRANSFORM_ZOOM_Y,*/ LV_STYLE_TRANSFORM_ANGLE, LV_STYLE_COLOR_FILTER_OPA, LV_STYLE_COLOR_FILTER_DSC, 0 }; @@ -286,9 +286,9 @@ static void style_init(void) style_init_reset(&styles->scrollbar); lv_style_set_bg_color(&styles->scrollbar, (theme.flags & MODE_DARK) ? lv_palette_darken(LV_PALETTE_GREY, 2) : lv_palette_main(LV_PALETTE_GREY)); lv_style_set_radius(&styles->scrollbar, LV_RADIUS_CIRCLE); - lv_style_set_pad_right(&styles->scrollbar, lv_disp_dpx(theme.disp, 7)); - lv_style_set_pad_top(&styles->scrollbar, lv_disp_dpx(theme.disp, 7)); - lv_style_set_size(&styles->scrollbar, lv_disp_dpx(theme.disp, 5)); + lv_style_set_pad_right(&styles->scrollbar, lv_display_dpx(theme.disp, 7)); + lv_style_set_pad_top(&styles->scrollbar, lv_display_dpx(theme.disp, 7)); + lv_style_set_size(&styles->scrollbar, lv_display_dpx(theme.disp, 5), lv_display_dpx(theme.disp, 5)); lv_style_set_bg_opa(&styles->scrollbar, LV_OPA_40); lv_style_set_transition(&styles->scrollbar, &trans_normal); @@ -316,7 +316,7 @@ static void style_init(void) lv_style_set_pad_row(&styles->card, PAD_SMALL); lv_style_set_pad_column(&styles->card, PAD_SMALL); lv_style_set_line_color(&styles->card, lv_palette_main(LV_PALETTE_GREY)); - lv_style_set_line_width(&styles->card, lv_disp_dpx(theme.disp, 1)); + lv_style_set_line_width(&styles->card, lv_display_dpx(theme.disp, 1)); style_init_reset(&styles->outline_primary); lv_style_set_outline_color(&styles->outline_primary, theme.color_primary); @@ -330,19 +330,19 @@ static void style_init(void) lv_style_set_outline_opa(&styles->outline_secondary, LV_OPA_50); style_init_reset(&styles->btn); - lv_style_set_radius(&styles->btn, (disp_size == DISP_LARGE ? lv_disp_dpx(theme.disp, 16) : disp_size == DISP_MEDIUM ? lv_disp_dpx(theme.disp, 12) : lv_disp_dpx(theme.disp, 8))); + lv_style_set_radius(&styles->btn, (disp_size == DISP_LARGE ? lv_display_dpx(theme.disp, 16) : disp_size == DISP_MEDIUM ? lv_display_dpx(theme.disp, 12) : lv_display_dpx(theme.disp, 8))); lv_style_set_bg_opa(&styles->btn, LV_OPA_COVER); lv_style_set_bg_color(&styles->btn, color_grey); // if(!(theme.flags & MODE_DARK)) { // OpenHASP // lv_style_set_shadow_color(&styles->btn, lv_palette_lighten(LV_PALETTE_GREY, 3)); // lv_style_set_shadow_width(&styles->btn, 1); - // lv_style_set_shadow_ofs_y(&styles->btn, lv_disp_dpx(theme.disp, 4)); + // lv_style_set_shadow_ofs_y(&styles->btn, lv_display_dpx(theme.disp, 4)); // } lv_style_set_text_color(&styles->btn, color_text); lv_style_set_pad_hor(&styles->btn, PAD_DEF); lv_style_set_pad_ver(&styles->btn, PAD_SMALL); - lv_style_set_pad_column(&styles->btn, lv_disp_dpx(theme.disp, 5)); - lv_style_set_pad_row(&styles->btn, lv_disp_dpx(theme.disp, 5)); + lv_style_set_pad_column(&styles->btn, lv_display_dpx(theme.disp, 5)); + lv_style_set_pad_row(&styles->btn, lv_display_dpx(theme.disp, 5)); lv_style_set_text_font(&styles->btn, theme.font_normal); static lv_color_filter_dsc_t dark_filter; @@ -372,11 +372,11 @@ static void style_init(void) lv_style_set_pad_gap(&styles->pad_small, PAD_SMALL); style_init_reset(&styles->pad_gap); - lv_style_set_pad_row(&styles->pad_gap, lv_disp_dpx(theme.disp, 10)); - lv_style_set_pad_column(&styles->pad_gap, lv_disp_dpx(theme.disp, 10)); + lv_style_set_pad_row(&styles->pad_gap, lv_display_dpx(theme.disp, 10)); + lv_style_set_pad_column(&styles->pad_gap, lv_display_dpx(theme.disp, 10)); style_init_reset(&styles->line_space_large); - lv_style_set_text_line_space(&styles->line_space_large, lv_disp_dpx(theme.disp, 20)); + lv_style_set_text_line_space(&styles->line_space_large, lv_display_dpx(theme.disp, 20)); style_init_reset(&styles->text_align_center); lv_style_set_text_align(&styles->text_align_center, LV_TEXT_ALIGN_CENTER); @@ -429,14 +429,14 @@ static void style_init(void) #if LV_THEME_DEFAULT_GROW style_init_reset(&styles->grow); - lv_style_set_transform_width(&styles->grow, lv_disp_dpx(theme.disp, 3)); - lv_style_set_transform_height(&styles->grow, lv_disp_dpx(theme.disp, 3)); + lv_style_set_transform_width(&styles->grow, lv_display_dpx(theme.disp, 3)); + lv_style_set_transform_height(&styles->grow, lv_display_dpx(theme.disp, 3)); #endif style_init_reset(&styles->knob); lv_style_set_bg_color(&styles->knob, theme.color_primary); lv_style_set_bg_opa(&styles->knob, LV_OPA_COVER); - lv_style_set_pad_all(&styles->knob, lv_disp_dpx(theme.disp, 6)); + lv_style_set_pad_all(&styles->knob, lv_display_dpx(theme.disp, 6)); lv_style_set_radius(&styles->knob, LV_RADIUS_CIRCLE); style_init_reset(&styles->anim); @@ -445,7 +445,7 @@ static void style_init(void) #if LV_USE_ARC style_init_reset(&styles->arc_indic); lv_style_set_arc_color(&styles->arc_indic, color_grey); - lv_style_set_arc_width(&styles->arc_indic, lv_disp_dpx(theme.disp, 18)); // OpenHASP + lv_style_set_arc_width(&styles->arc_indic, lv_display_dpx(theme.disp, 18)); // OpenHASP lv_style_set_arc_rounded(&styles->arc_indic, true); style_init_reset(&styles->arc_indic_primary); @@ -455,7 +455,7 @@ static void style_init(void) style_init_reset(&styles->arc_knob); lv_style_set_bg_color(&styles->arc_knob, theme.color_primary); lv_style_set_bg_opa(&styles->arc_knob, LV_OPA_COVER); - lv_style_set_pad_all(&styles->arc_knob, lv_disp_dpx(theme.disp, 4)); + lv_style_set_pad_all(&styles->arc_knob, lv_display_dpx(theme.disp, 4)); lv_style_set_radius(&styles->arc_knob, LV_RADIUS_CIRCLE); #endif @@ -465,7 +465,7 @@ static void style_init(void) #endif #if LV_USE_CHECKBOX style_init_reset(&styles->cb_marker); - lv_style_set_pad_all(&styles->cb_marker, lv_disp_dpx(theme.disp, 3)); + lv_style_set_pad_all(&styles->cb_marker, lv_display_dpx(theme.disp, 3)); lv_style_set_border_width(&styles->cb_marker, BORDER_WIDTH); lv_style_set_border_color(&styles->cb_marker, theme.color_primary); lv_style_set_bg_color(&styles->cb_marker, color_card); @@ -473,14 +473,14 @@ static void style_init(void) lv_style_set_radius(&styles->cb_marker, RADIUS_DEFAULT / 2); style_init_reset(&styles->cb_marker_checked); - lv_style_set_bg_img_src(&styles->cb_marker_checked, LV_SYMBOL_OK); + lv_style_set_bg_image_src(&styles->cb_marker_checked, LV_SYMBOL_OK); lv_style_set_text_color(&styles->cb_marker_checked, lv_color_white()); lv_style_set_text_font(&styles->cb_marker_checked, theme.font_small); #endif #if LV_USE_SWITCH style_init_reset(&styles->switch_knob); - lv_style_set_pad_all(&styles->switch_knob, - lv_disp_dpx(theme.disp, 4)); + lv_style_set_pad_all(&styles->switch_knob, - lv_display_dpx(theme.disp, 4)); lv_style_set_bg_color(&styles->switch_knob, lv_color_white()); #endif @@ -493,45 +493,45 @@ static void style_init(void) #if LV_USE_CHART style_init_reset(&styles->chart_bg); lv_style_set_border_post(&styles->chart_bg, false); - lv_style_set_pad_column(&styles->chart_bg, lv_disp_dpx(theme.disp, 10)); + lv_style_set_pad_column(&styles->chart_bg, lv_display_dpx(theme.disp, 10)); lv_style_set_line_color(&styles->chart_bg, color_grey); style_init_reset(&styles->chart_series); - lv_style_set_line_width(&styles->chart_series, lv_disp_dpx(theme.disp, 3)); - lv_style_set_radius(&styles->chart_series, lv_disp_dpx(theme.disp, 3)); - lv_style_set_size(&styles->chart_series, lv_disp_dpx(theme.disp, 8)); - lv_style_set_pad_column(&styles->chart_series, lv_disp_dpx(theme.disp, 2)); + lv_style_set_line_width(&styles->chart_series, lv_display_dpx(theme.disp, 3)); + lv_style_set_radius(&styles->chart_series, lv_display_dpx(theme.disp, 3)); + lv_style_set_size(&styles->chart_series, lv_display_dpx(theme.disp, 8), lv_display_dpx(theme.disp, 8)); + lv_style_set_pad_column(&styles->chart_series, lv_display_dpx(theme.disp, 2)); style_init_reset(&styles->chart_indic); lv_style_set_radius(&styles->chart_indic,LV_RADIUS_CIRCLE); - lv_style_set_size(&styles->chart_indic, lv_disp_dpx(theme.disp, 8)); + lv_style_set_size(&styles->chart_indic, lv_display_dpx(theme.disp, 8), lv_display_dpx(theme.disp, 8)); lv_style_set_bg_color(&styles->chart_indic, theme.color_primary); lv_style_set_bg_opa(&styles->chart_indic, LV_OPA_COVER); style_init_reset(&styles->chart_ticks); - lv_style_set_line_width(&styles->chart_ticks, lv_disp_dpx(theme.disp, 1)); + lv_style_set_line_width(&styles->chart_ticks, lv_display_dpx(theme.disp, 1)); lv_style_set_line_color(&styles->chart_ticks, color_text); - lv_style_set_pad_all(&styles->chart_ticks, lv_disp_dpx(theme.disp, 2)); + lv_style_set_pad_all(&styles->chart_ticks, lv_display_dpx(theme.disp, 2)); lv_style_set_text_color(&styles->chart_ticks, lv_palette_main(LV_PALETTE_GREY)); #endif #if LV_USE_METER style_init_reset(&styles->meter_marker); - lv_style_set_line_width(&styles->meter_marker, lv_disp_dpx(theme.disp, 5)); + lv_style_set_line_width(&styles->meter_marker, lv_display_dpx(theme.disp, 5)); lv_style_set_line_color(&styles->meter_marker, color_text); - lv_style_set_size(&styles->meter_marker, lv_disp_dpx(theme.disp, 20)); - lv_style_set_pad_left(&styles->meter_marker, lv_disp_dpx(theme.disp, 15)); + lv_style_set_size(&styles->meter_marker, lv_display_dpx(theme.disp, 20)); + lv_style_set_pad_left(&styles->meter_marker, lv_display_dpx(theme.disp, 15)); style_init_reset(&styles->meter_indic); lv_style_set_radius(&styles->meter_indic, LV_RADIUS_CIRCLE); lv_style_set_bg_color(&styles->meter_indic, color_text); lv_style_set_bg_opa(&styles->meter_indic, LV_OPA_COVER); - lv_style_set_size(&styles->meter_indic, lv_disp_dpx(theme.disp, 15)); + lv_style_set_size(&styles->meter_indic, lv_display_dpx(theme.disp, 15)); #endif #if LV_USE_TABLE style_init_reset(&styles->table_cell); - lv_style_set_border_width(&styles->table_cell, lv_disp_dpx(theme.disp, 1)); + lv_style_set_border_width(&styles->table_cell, lv_display_dpx(theme.disp, 1)); lv_style_set_border_color(&styles->table_cell, color_grey); lv_style_set_border_side(&styles->table_cell, LV_BORDER_SIDE_TOP | LV_BORDER_SIDE_BOTTOM ); #endif @@ -539,8 +539,8 @@ static void style_init(void) #if LV_USE_TEXTAREA style_init_reset(&styles->ta_cursor); lv_style_set_border_color(&styles->ta_cursor, color_text); - lv_style_set_border_width(&styles->ta_cursor, lv_disp_dpx(theme.disp, 2)); - lv_style_set_pad_left(&styles->ta_cursor, lv_disp_dpx(theme.disp, 1)); + lv_style_set_border_width(&styles->ta_cursor, lv_display_dpx(theme.disp, 2)); + lv_style_set_pad_left(&styles->ta_cursor, lv_display_dpx(theme.disp, 1)); lv_style_set_border_side(&styles->ta_cursor, LV_BORDER_SIDE_LEFT); lv_style_set_anim_time(&styles->ta_cursor, 400); @@ -555,7 +555,7 @@ static void style_init(void) lv_style_set_radius(&styles->calendar_bg, 0); style_init_reset(&styles->calendar_day); - lv_style_set_border_width(&styles->calendar_day, lv_disp_dpx(theme.disp, 1)); + lv_style_set_border_width(&styles->calendar_day, lv_display_dpx(theme.disp, 1)); lv_style_set_border_color(&styles->calendar_day, color_grey); lv_style_set_bg_color(&styles->calendar_day, color_card); lv_style_set_bg_opa(&styles->calendar_day, LV_OPA_20); @@ -563,13 +563,13 @@ static void style_init(void) #if LV_USE_COLORWHEEL style_init_reset(&styles->colorwheel_main); - lv_style_set_arc_width(&styles->colorwheel_main, lv_disp_dpx(theme.disp, 10)); + lv_style_set_arc_width(&styles->colorwheel_main, lv_display_dpx(theme.disp, 10)); #endif #if LV_USE_MSGBOX /*To add space for for the button shadow*/ style_init_reset(&styles->msgbox_btn_bg); - lv_style_set_pad_all(&styles->msgbox_btn_bg, lv_disp_dpx(theme.disp, 4)); + lv_style_set_pad_all(&styles->msgbox_btn_bg, lv_display_dpx(theme.disp, 4)); style_init_reset(&styles->msgbox_bg); lv_style_set_max_width(&styles->msgbox_bg, lv_pct(100)); @@ -598,7 +598,7 @@ static void style_init(void) lv_style_set_clip_corner(&styles->list_bg, true); style_init_reset(&styles->list_btn); - lv_style_set_border_width(&styles->list_btn, lv_disp_dpx(theme.disp, 1)); + lv_style_set_border_width(&styles->list_btn, lv_display_dpx(theme.disp, 1)); lv_style_set_border_color(&styles->list_btn, color_grey); lv_style_set_border_side(&styles->list_btn, LV_BORDER_SIDE_BOTTOM); lv_style_set_pad_all(&styles->list_btn, PAD_SMALL); @@ -615,9 +615,9 @@ static void style_init(void) lv_style_set_bg_color(&styles->led, lv_color_white()); lv_style_set_bg_grad_color(&styles->led, lv_palette_main(LV_PALETTE_GREY)); lv_style_set_radius(&styles->led, LV_RADIUS_CIRCLE); - lv_style_set_shadow_width(&styles->led, lv_disp_dpx(theme.disp, 15)); + lv_style_set_shadow_width(&styles->led, lv_display_dpx(theme.disp, 15)); lv_style_set_shadow_color(&styles->led, lv_color_white()); - lv_style_set_shadow_spread(&styles->led, lv_disp_dpx(theme.disp, 5)); + lv_style_set_shadow_spread(&styles->led, lv_display_dpx(theme.disp, 5)); #endif } @@ -625,15 +625,15 @@ static void style_init(void) * GLOBAL FUNCTIONS **********************/ -lv_theme_t * lv_theme_haspmota_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font) +lv_theme_t * lv_theme_haspmota_init(lv_display_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font) { /*This trick is required only to avoid the garbage collection of *styles' data if LVGL is used in a binding (e.g. Micropython) *In a general case styles could be in simple `static lv_style_t my_style...` variables*/ if(!inited) { - LV_GC_ROOT(_lv_theme_default_styles) = lv_mem_alloc(sizeof(my_theme_styles_t)); - styles = (my_theme_styles_t *)LV_GC_ROOT(_lv_theme_default_styles); + // LV_GC_ROOT(_lv_theme_default_styles) = lv_mem_alloc(sizeof(my_theme_styles_t)); + styles = (my_theme_styles_t *)malloc(sizeof(my_theme_styles_t)); // TODO LVGL } if(LV_HOR_RES <= 320) disp_size = DISP_SMALL; @@ -693,13 +693,13 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) #if LV_USE_WIN /*Header*/ - if(lv_obj_get_child_id(obj) == 0 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { + if(lv_obj_get_index(obj) == 0 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { lv_obj_add_style(obj, &styles->bg_color_grey, 0); lv_obj_add_style(obj, &styles->pad_tiny, 0); return; } /*Content*/ - else if(lv_obj_get_child_id(obj) == 1 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { + else if(lv_obj_get_index(obj) == 1 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { lv_obj_add_style(obj, &styles->scr, 0); lv_obj_add_style(obj, &styles->pad_normal, 0); lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); @@ -711,8 +711,8 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); } - #if LV_USE_BTN - else if(lv_obj_check_type(obj, &lv_btn_class)) { +#if LV_USE_BUTTON + else if(lv_obj_check_type(obj, &lv_button_class)) { lv_obj_add_style(obj, &styles->btn, 0); lv_obj_add_style(obj, &styles->bg_color_primary, 0); lv_obj_add_style(obj, &styles->transition_delayed, 0); @@ -733,8 +733,8 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) } #endif -#if LV_USE_BTNMATRIX - else if(lv_obj_check_type(obj, &lv_btnmatrix_class)) { +#if LV_USE_BUTTONMATRIX + else if(lv_obj_check_type(obj, &lv_buttonmatrix_class)) { #if LV_USE_MSGBOX if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_msgbox_class)) { lv_obj_add_style(obj, &styles->msgbox_btn_bg, 0); @@ -862,7 +862,7 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); lv_obj_add_style(obj, &styles->chart_series, LV_PART_ITEMS); lv_obj_add_style(obj, &styles->chart_indic, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->chart_ticks, LV_PART_TICKS); + lv_obj_add_style(obj, &styles->chart_ticks, LV_PART_ITEMS); lv_obj_add_style(obj, &styles->chart_series, LV_PART_CURSOR); } #endif @@ -996,7 +996,7 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) lv_obj_add_style(obj, &styles->bg_color_grey, 0); lv_obj_add_style(obj, &styles->list_item_grow, 0); } - else if(lv_obj_check_type(obj, &lv_list_btn_class)) { + else if(lv_obj_check_type(obj, &lv_list_button_class)) { lv_obj_add_style(obj, &styles->bg_color_white, 0); lv_obj_add_style(obj, &styles->list_btn, 0); lv_obj_add_style(obj, &styles->bg_color_primary, LV_STATE_FOCUS_KEY); diff --git a/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_haspmota.h b/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_haspmota.h index 7276f485d..ef40ba742 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_haspmota.h +++ b/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_haspmota.h @@ -40,7 +40,7 @@ typedef enum { * @param font pointer to a font to use. * @return a pointer to reference this theme later */ -lv_theme_t * lv_theme_haspmota_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font); +lv_theme_t * lv_theme_haspmota_init(lv_display_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font); bool lv_theme_haspmota_is_inited(void); diff --git a/lib/libesp32_lvgl/LVGL_assets/src/tasmota_logo_64_truecolor_alpha.c b/lib/libesp32_lvgl/LVGL_assets/src/tasmota_logo_64_truecolor_alpha.c new file mode 100644 index 000000000..cc5a2af1f --- /dev/null +++ b/lib/libesp32_lvgl/LVGL_assets/src/tasmota_logo_64_truecolor_alpha.c @@ -0,0 +1,127 @@ +// Command: +// python3 LVGLImage.py --ofmt C --cf RGB565A8 TASMOTA_Symbol_64.png + +#include "lvgl.h" + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_DUST +#define LV_ATTRIBUTE_IMG_DUST +#endif + +static const +LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_DUST +uint8_t TASMOTA_Symbol_64_map[] = { + + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x8c,0x8e,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x00,0x7f,0xff,0xff,0x81,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x80,0xff,0xfc,0xfc,0xff,0x83,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x00,0x7f,0xff,0xfc,0xfd,0xfd,0xfc,0xff,0x82,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x00,0x7f,0xff,0xfd,0xfd,0xff,0xff,0xfd,0xfd,0xff,0x82,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x80,0xff,0xfd,0xfd,0xff,0xfb,0xfb,0xff,0xfe,0xfd,0xff,0x83,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x7f,0xff,0xfc,0xfd,0xff,0xfb,0xff,0xff,0xfb,0xff,0xfd,0xfc,0xff,0x82,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x00,0x7f,0xff,0xfd,0xfd,0xff,0xfa,0xff,0xb9,0xb8,0xff,0xfa,0xff,0xfd,0xfd,0xff,0x81,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x80,0xff,0xfd,0xfe,0xff,0xf9,0xff,0xc4,0x02,0x01,0xc1,0xff,0xf9,0xff,0xfe,0xfd,0xff,0x83,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x7f,0xff,0xfc,0xfd,0xff,0xf9,0xff,0xc2,0x06,0x00,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfd,0xfc,0xff,0x82,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x00,0x7f,0xff,0xfd,0xfd,0xff,0xf9,0xff,0xc3,0x05,0x00,0x04,0x04,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfd,0xfd,0xff,0x82,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x80,0xff,0xfd,0xfe,0xff,0xf9,0xff,0xc2,0x05,0x00,0x04,0x00,0x00,0x04,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfe,0xfd,0xff,0x83,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x7f,0xff,0xfc,0xfd,0xff,0xf9,0xff,0xc2,0x06,0x00,0x05,0x00,0x00,0x00,0x00,0x04,0x00,0x05,0xc0,0xff,0xf9,0xff,0xfd,0xfc,0xff,0x82,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x00,0x7f,0xff,0xfd,0xfd,0xff,0xf9,0xff,0xc3,0x05,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfd,0xfd,0xff,0x82,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x80,0xff,0xfd,0xfe,0xff,0xf9,0xff,0xc2,0x05,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfe,0xfd,0xff,0x83,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x7f,0xff,0xfc,0xfd,0xff,0xf9,0xff,0xc2,0x06,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x05,0xc0,0xff,0xf9,0xff,0xfd,0xfc,0xff,0x82,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x00,0x7f,0xff,0xfd,0xfd,0xff,0xf9,0xff,0xc3,0x05,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfd,0xfd,0xff,0x82,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x80,0xff,0xfd,0xfd,0xff,0xf9,0xff,0xc2,0x05,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfe,0xfd,0xff,0x83,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x7f,0xff,0xfc,0xfd,0xff,0xf9,0xff,0xc2,0x06,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x05,0xc0,0xff,0xf9,0xff,0xfd,0xfc,0xff,0x82,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x00,0x7f,0xff,0xfd,0xfd,0xff,0xf9,0xff,0xc3,0x05,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfd,0xfd,0xff,0x82,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x80,0xff,0xfd,0xfd,0xff,0xf9,0xff,0xc2,0x05,0x00,0x04,0x00,0x00,0x00,0x00,0x01,0x03,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x03,0x01,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfe,0xfd,0xff,0x83,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x7f,0xff,0xfc,0xfd,0xff,0xf9,0xff,0xc2,0x06,0x00,0x04,0x00,0x00,0x00,0x02,0x06,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x06,0x02,0x00,0x00,0x00,0x04,0x00,0x05,0xc0,0xff,0xf9,0xff,0xfd,0xfc,0xff,0x82,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x00,0x7f,0xff,0xfd,0xfd,0xff,0xf9,0xff,0xc3,0x05,0x00,0x05,0x00,0x00,0x02,0x04,0x00,0x00,0x00,0x09,0x29,0x49,0x5e,0x69,0x69,0x5e,0x49,0x29,0x09,0x00,0x00,0x00,0x05,0x02,0x00,0x00,0x05,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfd,0xfd,0xff,0x82,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x80,0xff,0xfd,0xfd,0xff,0xf9,0xff,0xc2,0x05,0x00,0x05,0x00,0x02,0x04,0x00,0x00,0x0d,0x55,0xa2,0xda,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,0xf9,0xd9,0xa5,0x59,0x0c,0x00,0x00,0x05,0x02,0x00,0x05,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfe,0xfd,0xff,0x83,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x7f,0xff,0xfc,0xfd,0xff,0xf9,0xff,0xc2,0x06,0x00,0x05,0x00,0x03,0x00,0x00,0x13,0x81,0xe3,0xff,0xff,0xff,0xff,0xfe,0xfc,0xfb,0xfb,0xfc,0xfe,0xff,0xff,0xff,0xff,0xe2,0x83,0x14,0x00,0x00,0x04,0x00,0x04,0x00,0x05,0xc0,0xff,0xf9,0xff,0xfd,0xfc,0xff,0x82,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x7f,0xff,0xfd,0xfd,0xff,0xf9,0xff,0xc3,0x05,0x00,0x05,0x00,0x04,0x00,0x00,0x66,0xe9,0xff,0xff,0xfc,0xfb,0xfb,0xfc,0xfd,0xfe,0xff,0xff,0xfe,0xfd,0xfc,0xfc,0xfb,0xfc,0xff,0xff,0xea,0x69,0x00,0x00,0x05,0x00,0x05,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfd,0xfd,0xff,0x82,0x00,0x01,0x02,0x00,0x00,0x00, + 0x00,0x00,0x02,0x02,0x00,0x80,0xff,0xfd,0xfd,0xff,0xf9,0xff,0xc2,0x05,0x00,0x05,0x00,0x06,0x00,0x12,0xb5,0xff,0xff,0xf9,0xfd,0xfe,0xfb,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xfb,0xfe,0xfd,0xf9,0xff,0xff,0xb8,0x14,0x00,0x06,0x00,0x04,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfe,0xfd,0xff,0x83,0x00,0x02,0x02,0x00,0x00,0x00,0x02,0x02,0x00,0x7f,0xff,0xfc,0xfd,0xff,0xf9,0xff,0xc2,0x06,0x00,0x04,0x00,0x05,0x00,0x29,0xe1,0xff,0xfa,0xfb,0xff,0xfb,0xfd,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xfe,0xfa,0xff,0xfb,0xfa,0xff,0xe2,0x2a,0x00,0x05,0x00,0x04,0x00,0x05,0xc0,0xff,0xf9,0xff,0xfd,0xfc,0xff,0x82,0x00,0x02,0x02,0x00, + 0x01,0x01,0x00,0x7f,0xff,0xfd,0xfd,0xff,0xf9,0xff,0xc3,0x05,0x00,0x05,0x00,0x05,0x00,0x2e,0xf0,0xff,0xf9,0xff,0xfe,0xfb,0xff,0xff,0xcb,0x7c,0x25,0xa0,0xff,0xfc,0xfc,0xff,0xa1,0x25,0x7c,0xcb,0xff,0xff,0xfb,0xfe,0xff,0xf8,0xff,0xf0,0x2e,0x00,0x05,0x00,0x05,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfd,0xfd,0xff,0x82,0x00,0x01,0x02,0x01,0x00,0x80,0xff,0xfd,0xfe,0xff,0xf9,0xff,0xc2,0x05,0x00,0x05,0x00,0x04,0x00,0x1d,0xea,0xff,0xf9,0xff,0xfc,0xff,0xff,0xca,0x4b,0x00,0x00,0x00,0x92,0xff,0xfb,0xfb,0xff,0x94,0x00,0x00,0x00,0x49,0xca,0xff,0xff,0xfc,0xff,0xf9,0xff,0xea,0x1d,0x00,0x04,0x00,0x05,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfe,0xfd,0xff,0x83,0x00,0x01, + 0x00,0x7f,0xff,0xfc,0xfd,0xff,0xf9,0xff,0xc2,0x06,0x00,0x04,0x00,0x01,0x00,0x01,0xc8,0xff,0xf8,0xff,0xfb,0xff,0xff,0x7c,0x00,0x00,0x00,0x09,0x00,0x97,0xff,0xfb,0xfb,0xff,0x98,0x00,0x09,0x00,0x00,0x00,0x7b,0xff,0xff,0xfb,0xff,0xf8,0xff,0xc8,0x01,0x00,0x01,0x00,0x04,0x00,0x05,0xc0,0xff,0xf9,0xff,0xfd,0xfc,0xff,0x81,0x00,0x8b,0xff,0xfc,0xfd,0xff,0xf9,0xff,0xc3,0x06,0x00,0x05,0x00,0x00,0x04,0x00,0x85,0xff,0xf8,0xff,0xfc,0xff,0xfb,0x4d,0x00,0x00,0x05,0x02,0x04,0x00,0x95,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x02,0x05,0x00,0x00,0x4c,0xfa,0xff,0xfc,0xff,0xf8,0xff,0x84,0x00,0x04,0x00,0x00,0x05,0x00,0x04,0xc0,0xff,0xf9,0xff,0xfd,0xfc,0xff,0x8e, + 0x8a,0xff,0xfc,0xfd,0xf9,0xff,0xc2,0x05,0x00,0x05,0x00,0x00,0x04,0x00,0x2e,0xfe,0xff,0xfe,0xfd,0xff,0xff,0x46,0x00,0x06,0x01,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x01,0x06,0x00,0x45,0xff,0xff,0xfd,0xfe,0xff,0xfe,0x2e,0x00,0x04,0x00,0x00,0x05,0x00,0x04,0xc0,0xff,0xf9,0xfd,0xfc,0xff,0x8c,0x00,0x7f,0xff,0xf9,0xff,0xc2,0x06,0x00,0x04,0x00,0x00,0x01,0x02,0x00,0xac,0xff,0xfa,0xff,0xfc,0xff,0x66,0x00,0x07,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x07,0x00,0x66,0xff,0xfc,0xff,0xfa,0xff,0xab,0x00,0x02,0x01,0x00,0x00,0x04,0x00,0x05,0xc0,0xff,0xf9,0xff,0x81,0x00, + 0x01,0x00,0x7d,0xff,0xc1,0x05,0x00,0x05,0x00,0x00,0x00,0x04,0x00,0x2e,0xfd,0xff,0xfd,0xfa,0xff,0xad,0x00,0x03,0x01,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x01,0x03,0x00,0xad,0xff,0xfa,0xfd,0xff,0xfc,0x2e,0x00,0x04,0x00,0x00,0x00,0x05,0x00,0x04,0xbf,0xff,0x7f,0x00,0x01,0x02,0x00,0x00,0x61,0x15,0x00,0x05,0x00,0x00,0x00,0x00,0x04,0x00,0x8a,0xff,0xfa,0xfe,0xff,0xf8,0x26,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x27,0xf8,0xff,0xfe,0xfa,0xff,0x89,0x00,0x04,0x00,0x00,0x00,0x00,0x05,0x00,0x14,0x61,0x00,0x00,0x02, + 0x00,0x01,0x02,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x01,0x00,0x05,0xd4,0xff,0xfb,0xfb,0xff,0x9d,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x9e,0xff,0xfb,0xfb,0xff,0xd3,0x05,0x00,0x01,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x02,0x01,0x00,0x00,0x00,0x01,0x04,0x02,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x30,0xff,0xff,0xfe,0xfe,0xff,0x3e,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x3f,0xff,0xfe,0xfd,0xff,0xff,0x2f,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x02,0x04,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x62,0xff,0xfc,0xfc,0xff,0xdb,0x08,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x09,0xdc,0xff,0xfc,0xfb,0xff,0x62,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x8c,0xff,0xfa,0xfa,0xff,0xaa,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0xaa,0xff,0xfa,0xfa,0xff,0x8c,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0xa9,0xff,0xfa,0xfb,0xff,0x83,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x83,0xff,0xfb,0xfa,0xff,0xa8,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xb8,0xff,0xfb,0xfb,0xff,0x6c,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x6d,0xff,0xfb,0xfb,0xff,0xb6,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xbc,0xff,0xfb,0xfb,0xff,0x66,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x67,0xff,0xfb,0xfb,0xff,0xbb,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xb4,0xff,0xfa,0xfb,0xff,0x71,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x72,0xff,0xfb,0xfa,0xff,0xb3,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0xa1,0xff,0xfa,0xfa,0xff,0x8f,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x90,0xff,0xfa,0xfa,0xff,0xa0,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x81,0xff,0xfa,0xfa,0xff,0xba,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xbb,0xff,0xfa,0xfa,0xff,0x80,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x51,0xff,0xfc,0xfd,0xff,0xec,0x16,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x16,0xed,0xff,0xfd,0xfc,0xff,0x50,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x20,0xf4,0xff,0xfd,0xfc,0xff,0x5b,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x5c,0xff,0xfc,0xfd,0xff,0xf3,0x1f,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xbe,0xff,0xfa,0xfc,0xff,0xc1,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0xc2,0xff,0xfc,0xfa,0xff,0xbd,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x6a,0xff,0xfb,0xfe,0xfd,0xff,0x4e,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x4f,0xff,0xfd,0xfe,0xfb,0xff,0x69,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x13,0xe8,0xff,0xfc,0xfb,0xff,0xdb,0x09,0x00,0x04,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x04,0x00,0x09,0xdb,0xff,0xfb,0xfc,0xff,0xe7,0x13,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x7f,0xff,0xfa,0xff,0xfa,0xff,0xa5,0x00,0x01,0x03,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x03,0x01,0x00,0xa6,0xff,0xfa,0xff,0xfa,0xff,0x7f,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x0c,0xe0,0xff,0xfc,0xff,0xfb,0xff,0x8c,0x00,0x00,0x05,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x05,0x00,0x00,0x8c,0xff,0xfb,0xff,0xfc,0xff,0xdf,0x0b,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x4c,0xff,0xfd,0xfd,0xfe,0xfc,0xff,0x9c,0x00,0x00,0x02,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x02,0x00,0x00,0x9a,0xff,0xfc,0xfe,0xfd,0xfd,0xff,0x4c,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x8b,0xff,0xf8,0xff,0xfe,0xfc,0xff,0xcb,0x33,0x00,0x02,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x02,0x00,0x33,0xca,0xff,0xfc,0xfe,0xff,0xf8,0xff,0x8a,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0xae,0xff,0xf9,0xff,0xff,0xf9,0xff,0xe5,0x0b,0x00,0x06,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x06,0x00,0x0b,0xe5,0xff,0xf9,0xff,0xff,0xf8,0xff,0xae,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0xb1,0xff,0xfb,0xfc,0xfd,0xff,0xe3,0x11,0x00,0x07,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x07,0x00,0x11,0xe3,0xff,0xfd,0xfc,0xfb,0xff,0xb3,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x99,0xff,0xff,0xf7,0xff,0xe3,0x0f,0x00,0x07,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x06,0x00,0x0f,0xe3,0xff,0xf7,0xff,0xff,0x9b,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x64,0xf2,0xff,0xff,0xde,0x0f,0x00,0x06,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x06,0x00,0x10,0xde,0xff,0xff,0xf2,0x65,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x1f,0x9f,0xff,0xf4,0x10,0x00,0x07,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x07,0x00,0x10,0xf4,0xff,0x9e,0x1f,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x33,0x80,0x10,0x00,0x06,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x06,0x00,0x0f,0x84,0x36,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x03,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x96,0xff,0xfb,0xfb,0xff,0x97,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + +}; + +const lv_img_dsc_t TASMOTA_Symbol_64 = { + .header.magic = LV_IMAGE_HEADER_MAGIC, + .header.cf = LV_COLOR_FORMAT_RGB565A8, + .header.flags = 0, + .header.w = 64, + .header.h = 64, + .header.stride = 128, + .data_size = 12288, + .data = TASMOTA_Symbol_64_map, +}; diff --git a/lib/libesp32_lvgl/freetype/CMakeLists.txt b/lib/libesp32_lvgl/freetype/CMakeLists.txt deleted file mode 100644 index ffb7c4801..000000000 --- a/lib/libesp32_lvgl/freetype/CMakeLists.txt +++ /dev/null @@ -1,585 +0,0 @@ -# CMakeLists.txt -# -# Copyright (C) 2013-2021 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# Written originally by John Cary -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. -# -# -# The following will 1. create a build directory and 2. change into it and -# call cmake to configure the build with default parameters as a static -# library. See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html -# for information about Debug, Release, etc. builds. -# -# cmake -B build -D CMAKE_BUILD_TYPE=Release -# -# For a dynamic library, use -# -# cmake -B build -D BUILD_SHARED_LIBS=true -D CMAKE_BUILD_TYPE=Release -# -# For a framework on OS X, use -# -# cmake -E chdir build cmake -G Xcode -D BUILD_FRAMEWORK:BOOL=true .. -# -# For an iOS static library, use -# -# cmake -E chdir build cmake -G Xcode -D IOS_PLATFORM=OS .. -# -# or -# -# cmake -E chdir build cmake -G Xcode -D IOS_PLATFORM=SIMULATOR .. -# -# or -# -# cmake -E chdir build cmake -G Xcode -D IOS_PLATFORM=SIMULATOR64 .. -# -# Finally, build the project with: -# -# cmake --build build -# -# Install it with -# -# (sudo) cmake --build build --target install -# -# A binary distribution can be made with -# -# cmake --build build --config Release --target package -# -# Please refer to the cmake manual for further options, in particular, how -# to modify compilation and linking parameters. -# -# Some notes. -# -# . `cmake' creates configuration files in -# -# /include/freetype/config -# -# which should be further modified if necessary. -# -# . You can use `cmake' directly on a freshly cloned FreeType git -# repository. -# -# . `CMakeLists.txt' is provided as-is since it is normally not used by the -# developer team. -# -# . Set the `FT_WITH_ZLIB', `FT_WITH_BZIP2', `FT_WITH_PNG', -# `FT_WITH_HARFBUZZ', and `FT_WITH_BROTLI' CMake variables to `ON' to -# force using a dependency. Leave a variable undefined (which is the -# default) to use the dependency only if it is available. Example: -# -# cmake -B build -D FT_WITH_ZLIB=ON \ -# -D FT_WITH_BZIP2=ON \ -# -D FT_WITH_PNG=ON \ -# -D FT_WITH_HARFBUZZ=ON \ -# -D FT_WITH_BROTLI=ON [...] -# -# Set `CMAKE_DISABLE_FIND_PACKAGE_XXX=TRUE' to disable a dependency completely -# (where `XXX' is a CMake package name like `BZip2'). Example for disabling all -# dependencies: -# -# cmake -B build -D CMAKE_DISABLE_FIND_PACKAGE_ZLIB=TRUE \ -# -D CMAKE_DISABLE_FIND_PACKAGE_BZip2=TRUE \ -# -D CMAKE_DISABLE_FIND_PACKAGE_PNG=TRUE \ -# -D CMAKE_DISABLE_FIND_PACKAGE_HarfBuzz=TRUE \ -# -D CMAKE_DISABLE_FIND_PACKAGE_BrotliDec=TRUE [...] -# -# . Installation of FreeType can be controlled with the CMake variables -# `SKIP_INSTALL_HEADERS', `SKIP_INSTALL_LIBRARIES', and `SKIP_INSTALL_ALL' -# (this is compatible with the same CMake variables in zlib's CMake -# support). - -# FreeType explicitly marks the API to be exported and relies on the compiler -# to hide all other symbols. CMake supports a C_VISBILITY_PRESET property -# starting with 2.8.12. -cmake_minimum_required(VERSION 2.8.12) - -if (NOT CMAKE_VERSION VERSION_LESS 3.3) - # Allow symbol visibility settings also on static libraries. CMake < 3.3 - # only sets the property on a shared library build. - cmake_policy(SET CMP0063 NEW) -endif () - -include(CheckIncludeFile) - -# CMAKE_TOOLCHAIN_FILE must be set before `project' is called, which -# configures the base build environment and references the toolchain file -if (APPLE) - if (DEFINED IOS_PLATFORM) - if (NOT "${IOS_PLATFORM}" STREQUAL "OS" - AND NOT "${IOS_PLATFORM}" STREQUAL "SIMULATOR" - AND NOT "${IOS_PLATFORM}" STREQUAL "SIMULATOR64") - message(FATAL_ERROR - "IOS_PLATFORM must be set to either OS, SIMULATOR, or SIMULATOR64") - endif () - if (NOT "${CMAKE_GENERATOR}" STREQUAL "Xcode") - message(AUTHOR_WARNING - "You should use Xcode generator with IOS_PLATFORM enabled to get Universal builds.") - endif () - if (BUILD_SHARED_LIBS) - message(FATAL_ERROR - "BUILD_SHARED_LIBS can not be on with IOS_PLATFORM enabled") - endif () - if (BUILD_FRAMEWORK) - message(FATAL_ERROR - "BUILD_FRAMEWORK can not be on with IOS_PLATFORM enabled") - endif () - - # iOS only uses static libraries - set(BUILD_SHARED_LIBS OFF) - - set(CMAKE_TOOLCHAIN_FILE - ${CMAKE_SOURCE_DIR}/builds/cmake/iOS.cmake) - endif () -else () - if (DEFINED IOS_PLATFORM) - message(FATAL_ERROR "IOS_PLATFORM is not supported on this platform") - endif () -endif () - - -project(freetype C) - -set(VERSION_MAJOR "2") -set(VERSION_MINOR "10") -set(VERSION_PATCH "4") - -# Generate LIBRARY_VERSION and LIBRARY_SOVERSION. -set(LIBTOOL_REGEX "version_info='([0-9]+):([0-9]+):([0-9]+)'") -file(STRINGS "${PROJECT_SOURCE_DIR}/builds/unix/configure.raw" - VERSION_INFO - REGEX ${LIBTOOL_REGEX}) -string(REGEX REPLACE - ${LIBTOOL_REGEX} "\\1" - LIBTOOL_CURRENT "${VERSION_INFO}") -string(REGEX REPLACE - ${LIBTOOL_REGEX} "\\2" - LIBTOOL_REVISION "${VERSION_INFO}") -string(REGEX REPLACE - ${LIBTOOL_REGEX} "\\3" - LIBTOOL_AGE "${VERSION_INFO}") - -# This is what libtool does internally on Unix platforms. -math(EXPR LIBRARY_SOVERSION "${LIBTOOL_CURRENT} - ${LIBTOOL_AGE}") -set(LIBRARY_VERSION "${LIBRARY_SOVERSION}.${LIBTOOL_AGE}.${LIBTOOL_REVISION}") - -# External dependency library detection is automatic. See the notes at the top -# of this file, for how to force or disable dependencies completely. -option(FT_WITH_ZLIB "Use system zlib instead of internal library." OFF) -option(FT_WITH_BZIP2 "Support bzip2 compressed fonts." OFF) -option(FT_WITH_PNG "Support PNG compressed OpenType embedded bitmaps." OFF) -option(FT_WITH_HARFBUZZ "Improve auto-hinting of OpenType fonts." OFF) -option(FT_WITH_BROTLI "Support compressed WOFF2 fonts." OFF) - - -# Disallow in-source builds -if ("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") - message(FATAL_ERROR - "In-source builds are not permitted! Make a separate folder for" - " building, e.g.,\n" - " cmake -E make_directory build\n" - " cmake -E chdir build cmake ..\n" - "Before that, remove the files created by this failed run with\n" - " cmake -E remove CMakeCache.txt\n" - " cmake -E remove_directory CMakeFiles") -endif () - - -# Add local cmake modules -list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/builds/cmake) - - -if (BUILD_FRAMEWORK) - if (NOT "${CMAKE_GENERATOR}" STREQUAL "Xcode") - message(FATAL_ERROR - "You should use Xcode generator with BUILD_FRAMEWORK enabled") - endif () - set(CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_64_BIT)") - set(BUILD_SHARED_LIBS ON) -endif () - - -# Find dependencies -set(HARFBUZZ_MIN_VERSION "2.0.0") -if (FT_WITH_HARFBUZZ) - find_package(HarfBuzz ${HARFBUZZ_MIN_VERSION} REQUIRED) -else () - find_package(HarfBuzz ${HARFBUZZ_MIN_VERSION}) -endif () - -if (FT_WITH_PNG) - find_package(PNG REQUIRED) -else () - find_package(PNG) -endif () - -if (FT_WITH_ZLIB) - find_package(ZLIB REQUIRED) -else () - find_package(ZLIB) -endif () - -if (FT_WITH_BZIP2) - find_package(BZip2 REQUIRED) -else () - find_package(BZip2) -endif () - -if (FT_WITH_BROTLI) - find_package(BrotliDec REQUIRED) -else () - find_package(BrotliDec) -endif () - -# Create the configuration file -if (UNIX) - check_include_file("unistd.h" HAVE_UNISTD_H) - check_include_file("fcntl.h" HAVE_FCNTL_H) - - file(READ "${PROJECT_SOURCE_DIR}/builds/unix/ftconfig.h.in" - FTCONFIG_H) - if (HAVE_UNISTD_H) - string(REGEX REPLACE - "#undef +(HAVE_UNISTD_H)" "#define \\1 1" - FTCONFIG_H "${FTCONFIG_H}") - endif () - if (HAVE_FCNTL_H) - string(REGEX REPLACE - "#undef +(HAVE_FCNTL_H)" "#define \\1 1" - FTCONFIG_H "${FTCONFIG_H}") - endif () -else () - file(READ "${PROJECT_SOURCE_DIR}/include/freetype/config/ftconfig.h" - FTCONFIG_H) -endif () - -set(FTCONFIG_H_NAME "${PROJECT_BINARY_DIR}/include/freetype/config/ftconfig.h") -if (EXISTS "${FTCONFIG_H_NAME}") - file(READ "${FTCONFIG_H_NAME}" ORIGINAL_FTCONFIG_H) -else () - set(ORIGINAL_FTCONFIG_H "") -endif () -if (NOT (ORIGINAL_FTCONFIG_H STREQUAL FTCONFIG_H)) - file(WRITE "${FTCONFIG_H_NAME}" "${FTCONFIG_H}") -endif () - - -# Create the options file -file(READ "${PROJECT_SOURCE_DIR}/include/freetype/config/ftoption.h" - FTOPTION_H) -if (ZLIB_FOUND) - string(REGEX REPLACE - "/\\* +(#define +FT_CONFIG_OPTION_SYSTEM_ZLIB) +\\*/" "\\1" - FTOPTION_H "${FTOPTION_H}") -endif () -if (BZIP2_FOUND) - string(REGEX REPLACE - "/\\* +(#define +FT_CONFIG_OPTION_USE_BZIP2) +\\*/" "\\1" - FTOPTION_H "${FTOPTION_H}") -endif () -if (PNG_FOUND) - string(REGEX REPLACE - "/\\* +(#define +FT_CONFIG_OPTION_USE_PNG) +\\*/" "\\1" - FTOPTION_H "${FTOPTION_H}") -endif () -if (HARFBUZZ_FOUND) - string(REGEX REPLACE - "/\\* +(#define +FT_CONFIG_OPTION_USE_HARFBUZZ) +\\*/" "\\1" - FTOPTION_H "${FTOPTION_H}") -endif () -if (BROTLIDEC_FOUND) - string(REGEX REPLACE - "/\\* +(#define +FT_CONFIG_OPTION_USE_BROTLI) +\\*/" "\\1" - FTOPTION_H "${FTOPTION_H}") -endif () - -set(FTOPTION_H_NAME "${PROJECT_BINARY_DIR}/include/freetype/config/ftoption.h") -if (EXISTS "${FTOPTION_H_NAME}") - file(READ "${FTOPTION_H_NAME}" ORIGINAL_FTOPTION_H) -else () - set(ORIGINAL_FTOPTION_H "") -endif () -if (NOT (ORIGINAL_FTOPTION_H STREQUAL FTOPTION_H)) - file(WRITE "${FTOPTION_H_NAME}" "${FTOPTION_H}") -endif () - - -file(GLOB PUBLIC_HEADERS "include/ft2build.h" "include/freetype/*.h") -file(GLOB PUBLIC_CONFIG_HEADERS "include/freetype/config/*.h") -file(GLOB PRIVATE_HEADERS "include/freetype/internal/*.h") - - -set(BASE_SRCS - src/autofit/autofit.c - src/base/ftbase.c - src/base/ftbbox.c - src/base/ftbdf.c - src/base/ftbitmap.c - src/base/ftcid.c - src/base/ftfstype.c - src/base/ftgasp.c - src/base/ftglyph.c - src/base/ftgxval.c - src/base/ftinit.c - src/base/ftmm.c - src/base/ftotval.c - src/base/ftpatent.c - src/base/ftpfr.c - src/base/ftstroke.c - src/base/ftsynth.c - src/base/fttype1.c - src/base/ftwinfnt.c - src/bdf/bdf.c - src/bzip2/ftbzip2.c - src/cache/ftcache.c - src/cff/cff.c - src/cid/type1cid.c - src/gzip/ftgzip.c - src/lzw/ftlzw.c - src/pcf/pcf.c - src/pfr/pfr.c - src/psaux/psaux.c - src/pshinter/pshinter.c - src/psnames/psnames.c - src/raster/raster.c - src/sdf/sdf.c - src/sfnt/sfnt.c - src/smooth/smooth.c - src/truetype/truetype.c - src/type1/type1.c - src/type42/type42.c - src/winfonts/winfnt.c -) - -if (UNIX) - list(APPEND BASE_SRCS "builds/unix/ftsystem.c") -elseif (WIN32) - list(APPEND BASE_SRCS "builds/windows/ftsystem.c") -else () - list(APPEND BASE_SRCS "src/base/ftsystem.c") -endif () - -if (WIN32) - enable_language(RC) - list(APPEND BASE_SRCS builds/windows/ftdebug.c - src/base/ftver.rc) -elseif (WINCE) - list(APPEND BASE_SRCS builds/wince/ftdebug.c) -else () - list(APPEND BASE_SRCS src/base/ftdebug.c) -endif () - -if (BUILD_FRAMEWORK) - list(APPEND BASE_SRCS builds/mac/freetype-Info.plist) -endif () - - -if (NOT DISABLE_FORCE_DEBUG_POSTFIX) - set(CMAKE_DEBUG_POSTFIX d) -endif () - - -add_library(freetype - ${PUBLIC_HEADERS} - ${PUBLIC_CONFIG_HEADERS} - ${PRIVATE_HEADERS} - ${BASE_SRCS} -) - -set_target_properties( - freetype PROPERTIES - C_VISIBILITY_PRESET hidden) - -target_compile_definitions( - freetype PRIVATE FT2_BUILD_LIBRARY) - -if (WIN32) - target_compile_definitions( - freetype PRIVATE _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_WARNINGS) - if (BUILD_SHARED_LIBS) - target_compile_definitions( - freetype PRIVATE DLL_EXPORT) - endif () -endif () - -if (BUILD_SHARED_LIBS) - set_target_properties(freetype PROPERTIES - VERSION ${LIBRARY_VERSION} - SOVERSION ${LIBRARY_SOVERSION}) -endif () - -# Pick up ftconfig.h and ftoption.h generated above, first. -target_include_directories( - freetype - PUBLIC - $ - $ - $ - PRIVATE - ${CMAKE_CURRENT_BINARY_DIR}/include - ${CMAKE_CURRENT_SOURCE_DIR}/include - - # Make available for builds/unix/ftsystem.c. - ${CMAKE_CURRENT_BINARY_DIR}/include/freetype/config -) - - -if (BUILD_FRAMEWORK) - set_property(SOURCE ${PUBLIC_CONFIG_HEADERS} - PROPERTY MACOSX_PACKAGE_LOCATION Headers/config - ) - set_target_properties(freetype PROPERTIES - FRAMEWORK TRUE - MACOSX_FRAMEWORK_INFO_PLIST builds/mac/freetype-Info.plist - PUBLIC_HEADER "${PUBLIC_HEADERS}" - XCODE_ATTRIBUTE_INSTALL_PATH "@rpath" - ) -endif () - - -set(PKG_CONFIG_REQUIRED_PRIVATE "") -set(PKG_CONFIG_LIBS_PRIVATE "") - -if (ZLIB_FOUND) - target_link_libraries(freetype PRIVATE ${ZLIB_LIBRARIES}) - target_include_directories(freetype PRIVATE ${ZLIB_INCLUDE_DIRS}) - list(APPEND PKG_CONFIG_REQUIRED_PRIVATE "zlib") -endif () -if (BZIP2_FOUND) - target_link_libraries(freetype PRIVATE ${BZIP2_LIBRARIES}) - target_include_directories(freetype PRIVATE ${BZIP2_INCLUDE_DIR}) # not BZIP2_INCLUDE_DIRS - list(APPEND PKG_CONFIG_LIBS_PRIVATE "-lbz2") -endif () -if (PNG_FOUND) - target_link_libraries(freetype PRIVATE ${PNG_LIBRARIES}) - target_compile_definitions(freetype PRIVATE ${PNG_DEFINITIONS}) - target_include_directories(freetype PRIVATE ${PNG_INCLUDE_DIRS}) - list(APPEND PKG_CONFIG_REQUIRED_PRIVATE "libpng") -endif () -if (HARFBUZZ_FOUND) - target_link_libraries(freetype PRIVATE ${HARFBUZZ_LIBRARIES}) - target_include_directories(freetype PRIVATE ${HARFBUZZ_INCLUDE_DIRS}) - list(APPEND PKG_CONFIG_REQUIRED_PRIVATE "harfbuzz >= ${HARFBUZZ_MIN_VERSION}") -endif () -if (BROTLIDEC_FOUND) - target_link_libraries(freetype PRIVATE ${BROTLIDEC_LIBRARIES}) - target_compile_definitions(freetype PRIVATE ${BROTLIDEC_DEFINITIONS}) - target_include_directories(freetype PRIVATE ${BROTLIDEC_INCLUDE_DIRS}) - list(APPEND PKG_CONFIG_REQUIRED_PRIVATE "libbrotlidec") -endif () - - -# Installation -include(GNUInstallDirs) - -if (NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL) - install( - # Note the trailing slash in the argument to `DIRECTORY'! - DIRECTORY ${PROJECT_SOURCE_DIR}/include/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/freetype2 - COMPONENT headers - PATTERN "internal" EXCLUDE - PATTERN "ftconfig.h" EXCLUDE - PATTERN "ftoption.h" EXCLUDE) - install( - FILES ${PROJECT_BINARY_DIR}/include/freetype/config/ftconfig.h - ${PROJECT_BINARY_DIR}/include/freetype/config/ftoption.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/freetype2/freetype/config - COMPONENT headers) -endif () - -if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL) - # Generate the pkg-config file - file(READ "${PROJECT_SOURCE_DIR}/builds/unix/freetype2.in" FREETYPE2_PC_IN) - - string(REPLACE ";" ", " PKG_CONFIG_REQUIRED_PRIVATE "${PKG_CONFIG_REQUIRED_PRIVATE}") - - string(REPLACE "%prefix%" ${CMAKE_INSTALL_PREFIX} - FREETYPE2_PC_IN ${FREETYPE2_PC_IN}) - string(REPLACE "%exec_prefix%" "\${prefix}" - FREETYPE2_PC_IN ${FREETYPE2_PC_IN}) - string(REPLACE "%libdir%" "\${prefix}/${CMAKE_INSTALL_LIBDIR}" - FREETYPE2_PC_IN ${FREETYPE2_PC_IN}) - string(REPLACE "%includedir%" "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}" - FREETYPE2_PC_IN ${FREETYPE2_PC_IN}) - string(REPLACE "%ft_version%" "${LIBTOOL_CURRENT}.${LIBTOOL_REVISION}.${LIBTOOL_AGE}" - FREETYPE2_PC_IN ${FREETYPE2_PC_IN}) - string(REPLACE "%REQUIRES_PRIVATE%" "${PKG_CONFIG_REQUIRED_PRIVATE}" - FREETYPE2_PC_IN ${FREETYPE2_PC_IN}) - string(REPLACE "%LIBS_PRIVATE%" "${PKG_CONFIG_LIBS_PRIVATE}" - FREETYPE2_PC_IN ${FREETYPE2_PC_IN}) - - set(FREETYPE2_PC_IN_NAME "${PROJECT_BINARY_DIR}/freetype2.pc") - if (EXISTS "${FREETYPE2_PC_IN_NAME}") - file(READ "${FREETYPE2_PC_IN_NAME}" ORIGINAL_FREETYPE2_PC_IN) - else () - set(ORIGINAL_FREETYPE2_PC_IN "") - endif () - if (NOT (ORIGINAL_FREETYPE2_PC_IN STREQUAL FREETYPE2_PC_IN)) - file(WRITE "${FREETYPE2_PC_IN_NAME}" ${FREETYPE2_PC_IN}) - endif () - - install( - FILES ${PROJECT_BINARY_DIR}/freetype2.pc - DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig - COMPONENT pkgconfig) - - include(CMakePackageConfigHelpers) - write_basic_package_version_file( - ${PROJECT_BINARY_DIR}/freetype-config-version.cmake - VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} - COMPATIBILITY SameMajorVersion) - - install( - TARGETS freetype - EXPORT freetype-targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - FRAMEWORK DESTINATION Library/Frameworks - COMPONENT libraries) - install( - EXPORT freetype-targets - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/freetype - FILE freetype-config.cmake - COMPONENT headers) - install( - FILES ${PROJECT_BINARY_DIR}/freetype-config-version.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/freetype - COMPONENT headers) -endif () - - -# Packaging -set(CPACK_PACKAGE_NAME ${CMAKE_PROJECT_NAME}) -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The FreeType font rendering library.") -set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") -set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.TXT") - -set(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR}) -set(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR}) -set(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH}) -set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") - -if (WIN32) - set(CPACK_GENERATOR ZIP) -else () - set(CPACK_GENERATOR TGZ) -endif () - -set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries") -set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C/C++ Headers") -set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION - "Library used to build programs which use FreeType") -set(CPACK_COMPONENT_HEADERS_DESCRIPTION - "C/C++ header files for use with FreeType") -set(CPACK_COMPONENT_HEADERS_DEPENDS libraries) -set(CPACK_COMPONENT_LIBRARIES_GROUP "Development") -set(CPACK_COMPONENT_HEADERS_GROUP "Development") - -include(CPack) diff --git a/lib/libesp32_lvgl/freetype/ChangeLog b/lib/libesp32_lvgl/freetype/ChangeLog index 42f7c34ba..ca58f007a 100644 --- a/lib/libesp32_lvgl/freetype/ChangeLog +++ b/lib/libesp32_lvgl/freetype/ChangeLog @@ -1,5066 +1,6562 @@ -2020-10-20 Werner Lemberg +2023-08-25 Werner Lemberg - * Version 2.10.4 released. + * Version 2.13.2 released. ========================== + Tag sources with `VER-2-13-2'. - Tag sources with `VER-2-10-4'. - - * docs/VERSION.TXT: Add entry for version 2.10.4. + * docs/VERSION.TXT: Add entry for version 2.13.2. * docs/CHANGES: Updated. + * docs/release, docs/README, builds/macs/README: Updated. * README, src/base/ftver.rc, builds/windows/vc2010/index.html, - builds/windows/visualc/index.html, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/index.html, docs/freetype-config.1: - s/2.10.3/2.10.4/, s/2103/2104/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 4. - - * builds/unix/configure.raw (version_info): Set to 23:4:17. - * CMakeLists.txt (VERSION_PATCH): Set to 4. - -2020-10-19 Werner Lemberg - - [sfnt] Fix heap buffer overflow (#59308). - - This is CVE-2020-15999. - - * src/sfnt/pngshim.c (Load_SBit_Png): Test bitmap size earlier. - -2020-10-17 Alexei Podtelezhnikov - - * src/sfnt/tt{colr,cpal}.c: Fix signedness warnings from VC++. - -2020-10-17 Alexei Podtelezhnikov - - * src/sfnt/sfwoff2.c (Read255UShort): Tweak types to please VC++. - -2020-10-10 Werner Lemberg - - * Version 2.10.3 released. - ========================== - - - Tag sources with `VER-2-10-3'. - - * docs/VERSION.TXT: Add entry for version 2.10.3. - - * README, src/base/ftver.rc, builds/windows/vc2010/index.html, - builds/windows/visualc/index.html, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/index.html, docs/freetype-config.1: - s/2.10.2/2.10.3/, s/2102/2103/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 3. - - * builds/unix/configure.raw (version_info): Set to 23:3:17. - * CMakeLists.txt (VERSION_PATCH): Set to 3. - -2020-09-25 Werner Lemberg - - [autofit] Synchronize with ttfautohint. - - This corresponds to the following commits in the ttfautohint git - repository: - - bb6842bd3bd437b7b4a7921b0376c860f5e73d18 Typo, formatting. - d5c91ddb1cb310257a3dfe9a8e20e1fc51335faa Add Medefaidrin script. - - * src/autofit/afblue.dat: Add blue zone data for Medefaidrin. - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Medefaidrin standard characters. - - * src/autofit/afranges.c, src/autofit/afstyles.h: Add Medefaidrin - data. - -2020-09-25 Werner Lemberg - - Move `scripts/make_distribution_archives.py` to `src/tools`. - - * scr/tools/scripts/make_distribution_archives.py: (_TOP_DIR, - _SCRIPT_DIR): Updated to new location. - (main): s/shutils.copyfile/shutils.copy/ to preserve file - permissions. - (main): Prefix source file paths with `git_dir` while copying files - to allow calls of the script from other places than the top-level - directory. - -2020-09-24 Werner Lemberg - - * src/cff/cffgload.c (cff_slot_load): Scale `vertBearingY`. - - Towards the end of the the function there is a call to - `FT_Outline_Get_CBox` that retrieves the glyph bbox in scaled units. - That sets `horiBearing{X,Y}` and `vertBearingX` but `vertBearingY` - is left alone, and is not scaled. - - Patch from Eric Muller . - -2020-09-24 Werner Lemberg - - * src/base/ftobjs.c (FT_Load_Glyph): Trace glyph metrics. - -2020-09-22 Werner Lemberg - - [meson] Move auxiliary scripts to `builds/meson`. - - Suggested by Alexei. - - * scripts/*.py: Move meson scripts to... - * builds/meson/*.py: ... this new location. - - * meson.build: Updated. - -2020-09-21 David Turner - - Add python script for building tarballs. - - * scripts/make_distribution_archives.py: New file. - - This standalone Python script should be equivalent to running `make - dist` with the Make-based build system, with the following minor - differences: - - - Since `make distclean` doesn't always clean up `objs/` properly, - `make dist` archives may contain some stale binaries like - `objs/.libs/libfreetype.so.6` or others. - - - `config.guess` and `config.sub` are not updated unless option - `--gnu-config-dir=DIR` is used to specify the location of these - files. - - - Some bits of the auto-generated reference documentation may - appear in slightly different order, probably due to issues related - to mkdocs and docwriter. - - As an example, the call - - scripts/make_distribution_archives.py /tmp/freetype2-dist - - creates the following files under `/tmp/freetype2-dist`: - - freetype-.tar.gz - freetype-.tar.xz - ft.zip - -2020-09-21 Werner Lemberg - - * scripts/extract_freetype_version.py: Fix regex typos. - -2020-09-21 David Turner - - Add Meson build project file. - - Example usage: - - # Configure Meson build in directory `build-meson` to generate - # release binaries comparable to to the ones from the - # autotools/make build system. - meson setup build-meson \ - --prefix=/usr/local \ - --buildtype=debugoptimized \ - --strip \ - -Db_ndebug=true - - # After configuring the Meson build with the above command, - # compile and install to `/usr/local/`; this includes a pkg-config - # file. - ninja -C build-meson install - - # Alternatively, compile and install to `/tmp/aa/usr/local/...` - # for packaging. - DESTDIR=/tmp/aa ninja -C build-meson install - - # Generate documentation under `build-meson/docs`. - ninja -C build-meson docs - - Library size comparison for stripped `libfreetype.so` generated by - all three build systems: - - - Default build (autotools + libtool): 712 KiB - - CMake build (RelWithDebInfo): 712 KiB - - Meson build: 712 KiB - - - * meson.build: New top-level Meson build file for the library. - - * meson_options.txt: New file. It holds user-selectable options for - the build, which can be printed with `meson configure`, and selected - at `meson setup` or `meson --reconfigure` time with - `-D
. - (print_html_field_list): Ditto. - (index_exit): Don't use
...
but `align=center' - table attribute. - (section_enter): Ditto. - (toc_exit): Don't emit
. - (block_enter): Use

, not

. - (__init__): Fix tag order in self.html_footer. - -2003-07-25 David Turner - - This change reimplements fix from 2003-05-30 without breaking - binary compatibility. - - * include/freetype/t1tables.h (PS_FontInfoRec): `italic_angle', - `is_fixed_pitch', `underline_position', `underline_thickness' are - reverted to be normal values. - - * include/freetype/internal/psaux.h (T1_FieldType): Remove - `T1_FIELD_TYPE_BOOL_P', `T1_FIELD_TYPE_INTEGER_P', - `T1_FIELD_TYPE_FIXED_P', `T1_FIELD_TYPE_FIXED_1000_P'. - (T1_FIELD_TYPE_BOOL_P, T1_FIELD_NUM_P, T1_FIELD_FIXED_P, - T1_FIELD_FIXED_1000_P): Removed. - (T1_FIELD_TYPE_BOOL): Renamed to... - (T1_FIELD_BOOL): New macro. Updated all callers. - - * src/type42/t42parse.c: `italic_angle', `is_fixed_pitch', - `underline_position', `underline_thickness', `paint_type', - `stroke_width' are reverted to be normal values. - (T42_KEYWORD_COUNT): New macro. - (t42_parse_dict): New array `keyword_flags' to mark that a value has - already been assigned to a dictionary entry. - * src/type42/t42objs.c (T42_Face_Init, T42_Face_Done): Updated. - - * src/cid/cidtoken.h: `italic_angle', `is_fixed_pitch', - `underline_position', `underline_thickness' are reverted to be - normal values. - * src/cid/cidobjs.c (cid_face_done, cid_face_init): Updated. - - * src/psaux/psobjs.c (ps_parser_load_field): Updated. - - * src/type1/t1tokens.h: `italic_angle', `is_fixed_pitch', - `underline_position', `underline_thickness', `paint_type', - `stroke_width' are reverted to be normal values. - * src/type1/t1objs.c (T1_Face_Done, T1_Face_Init): Updated. - * src/type1/t1load.c (T1_FIELD_COUNT): New macro. - (parse_dict): Add parameter for keyword flags. - Record only first instance of a field. - (T1_Open_Face): New array `keyword_flags'. - -2003-07-24 Werner Lemberg - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 5. - * builds/unix/configure.ac (version_info): Set to 10:0:3. - * builds/unix/configure: Updated. - * builds/freetype.mk (refdoc): Fix --title. - - * docs/CHANGES, docs/VERSION.DLL, README: Updated. - - * src/tools/docmaker/sources.py (re_crossref): Fix regular - expression to handle trailing punctuation characters. - * src/tools/docmaker/tohtml.py (make_html_word): Updated. - - * docs/release: New file. - -2003-07-23 YAMANO-UCHI Hidetoshi - - * include/freetype/internal/psaux.h (PS_Parser_FuncsRec): New - member function `to_bytes'. - - * src/psaux/psauxmod.c (ps_parser_funcs): New member - `ps_parser_to_bytes'. - (psaux_module_class): Increase version to 0x20000L. - - * src/psaux/psobjs.c (IS_T1_LINESPACE): Add \f. - (IS_T1_NULLSPACE): New macro. - (IS_T1_SPACE): Add it. - (skip_spaces, skip_alpha): New functions. - (ps_parser_skip_spaces, ps_parser_skip_alpha): Use them. - (ps_tobytes, ps_parser_to_bytes): New functions. - -2003-07-07 Werner Lemberg - - * builds/freetype.mk (DOC_DIR): New variable. - (refdoc): Use *_DIR variables. - (distclean): Remove documentation files. - - * builds/detect.mk (std_setup, dos_setup): Mention `make refdoc'. - - * configure: Set DOC_DIR variable. - -2003-07-07 Patrik Hägglund - - * builds/freetype.mk (refdoc): New target to build the - documentation. - (.PHONY): Updated. - - * include/freetype/freetype.h: Improve documentation of FT_CharMap. - * include/freetype/ftimage,h: Fix documentation of FT_OUTLINE_FLAGS. - * include/freetype/tttables.h: Document FT_Sfnt_Tag. - -2003-07-06 Werner Lemberg - - * src/bdf/bdfdrivr.c (BDF_Face_Init), src/pcf/pcfread.c - (pcf_load_font): Fix computation of height if PIXEL_SIZE property is - missing. - -2003-07-01 Werner Lemberg - - * src/cache/ftcsbits.c (ftc_sbit_node_compare): Only add `size' if - there is no error. Reported by Knut St. Osmundsen - . - -2003-06-30 Werner Lemberg - - A new try to synchronize bitmap font access. - - * include/freetype/freetype.h (FT_Bitmap_Size): `height' is now - defined to return the baseline-to-baseline distance. This was - already the value returned by the BDF and PCF drivers. - - The `width' field now gives the average width. I wasn't able to - find something better. It should be taken as informative only. - - New fields `size', `x_ppem', and `y_ppem'. - - * src/pcf/pcfread.c (pcf_load_font): Updated to properly fill - FT_Bitmap_Size. - Do proper rounding and conversion from 72.27 to 72 points. - - * src/bdf/bdfdrivr.c (BDF_Face_Init): Updated to properly fill - FT_Bitmap_Size. - Do proper rounding and conversion from 72.27 to 72 points. - - * src/sfnt/sfobjs.c (sfnt_load_face): Updated to properly fill - FT_Bitmap_Size. - - * src/winfonts/winfnt.c (FNT_Face_Init): Updated to properly fill - FT_Bitmap_Size. - -2003-06-29 Werner Lemberg - - Redesigning the FNT driver to return multiple faces, not multiple - strikes. At least one font (app850.fon from WinME) contains - different FNT charmaps for its subfonts. Consequently, the previous - design of having multiple bitmap strikes in a single font face fails - since we have only one charmap per face. - - * include/freetype/internal/fnttypes.h (FNT_Size_Rec): Removed. - (FNT_FaceRec): Remove `num_fonts' field and replace `fonts' with - `font'. - - * src/base/ftwinfnt.c (FT_Get_WinFNT_Header): Updated. - - * src/winfonts/winfnt.c (fnt_font_load): Don't set pixel_width equal - to pixel_height. - (fnt_face_done_fonts): Removed. - (fnt_face_get_dll_fonts): Renamed to... - (fnt_face_get_dll_font): This. Add second function argument to - select face index. - Updated to load just one subfont. - (fnt_font_done, FNT_Face_Done): Updated. - (FNT_Face_Init): Handle `face_index'. - Updated. - (FNT_Size_Set_Pixels): Simplified; similar to BDF and PCF, the - bitmap width is now ignored. - (FNT_Load_Glyph): Updated. - Fix glyph index computation. - (winfnt_driver_class): Updated. - -2003-06-25 Owen Taylor - - * src/sfnt/ttload.c (tt_face_load_hdmx): Don't assign - num_records until we actually decide to load the table, - otherwise, we'll segfault in tt_face_free_hdmx. - -2003-06-24 Werner Lemberg - - * src/cff/cffdrivr.c (cff_get_glyph_name): Protect against zero - glyph name pointer. Reported by Mikey Anbary . - -2003-06-23 Werner Lemberg - - * src/tools/glnames.py: Updated to AGL 2.0. - * src/psnames/pstables.h: Regenerated. - -2003-06-22 Werner Lemberg - - * include/freetype/cache/ftcglyph.h, include/freetype/ttnameid.h, - src/base/ftcalc.c, src/base/fttrigon.c, src/cff/cffgload.c, - src/otlayout/otlgsub.c, src/pshinter/pshrec.c, - src/psnames/psmodule.c, src/sfnt/sfobjs.c, src/truetype/ttdriver.c: - Decorate constants with `U' and `L' if appropriate. - - * include/freetype/ftmoderr.h: Updated to include recent module - additions. - - * src/pshinter/pshnterr.h (FT_ERR_BASE): Define as - `FT_Mod_Err_PShinter'. - * src/type42/t42error.h (FT_ERR_BASE): Define as - `FT_Mod_Err_Type42'. - - * src/pshinter/pshrec.h (PS_HINTS_MAGIC): Removed. Not used. - - * include/freetype/config/ftconfig.h [__MWERKS__]: Define FT_LONG64 - and FT_INT64. - -2003-06-21 Werner Lemberg - - * src/winfonts/winfnt.c (FNT_Load_Glyph): Use first_char in - computation of glyph_index. - (FNT_Size_Set_Pixels): To find a strike, first check pixel_height - only, then try to find a better hit by comparing pixel_width also. - Without this fix it isn't possible to access all strikes. - Also compute metrics.max_advance to be in sync with other bitmap - drivers. - - * src/base/ftobjs.c (FT_Set_Char_Size): Remove redundant code. - (FT_Set_Pixel_Sizes): Assign value to `metrics' after validation of - arguments. - -2003-06-20 Werner Lemberg - - Synchronize computation of height and width for bitmap strikes. The - `width' field in the FT_Bitmap_Size structure is now only useful to - enumerate different strikes. The `max_advance' field of the - FT_Size_Metrics structure should be used to get the (maximum) width - of a strike. - - * src/bdf/bdfdrivr.c (BDF_Face_Init): Don't use AVERAGE_WIDTH for - computing `available_sizes->width' but make it always equal to - `available_sizes->height'. - - * src/pcf/pcfread.c (pcf_load_font): Don't use RESOLUTION_X for - computing `available_sizes->width' but make it always equal to - `available_sizes->height'. - - * src/truetype/ttdriver.c (Set_Pixel_Sizes): Pass only single - argument to function. - - * src/psnames/psmodule.c (ps_unicode_value): Handle `.' after - `uniXXXX' and `uXXXX[X[X]]'. - -2003-06-19 Werner Lemberg - - * src/bdf/bdfdrivr.c: s/FT_Err_/BDF_Err/. - * src/cache/ftccache.c, src/cache/ftcsbits.c, src/cache/ftlru.c: - s/FT_Err_/FTC_Err_/. - * src/cff/cffcmap.c: s/FT_Err_/CFF_Err_/. - * src/pcf/pcfdrivr.c: s/FT_Err_/PCF_Err_/. - * src/psaux/t1cmap.c: Include psauxerr.h. - s/FT_Err_/PSaux_Err_/. - * src/pshinter/pshnterr.h: New file. - * src/pshinter/rules.mk: Updated. - * src/pshinter/pshalgo.c, src/pshinter/pshrec.c: Include pshnterr.h. - s/FT_Err_/PSH_Err_/. - * src/pfr/pfrdrivr.c, src/pfr/pfrobjs.c, src/pfr/pfrsbit.c: - s/FT_Err_/PFR_Err_/. - * src/sfnt/sfdriver.c, src/sfnt/sfobjs.c, src/sfnt/ttcmap0.c, - src/sfnt/ttload.c: s/FT_Err_/SFNT_Err_/. - * src/truetype/ttgload.c: s/FT_Err_/TT_Err_/. - * src/gzip/ftgzip.c: Load FT_MODULE_ERRORS_H and define - FT_ERR_PREFIX and FT_ERR_BASE. - s/FT_Err_/Gzip_Err_/. - -2003-06-19 Dirck Blaskey - - * src/cff/cffload (cff_encoding_load): `nleft' must be FT_UInt, - otherwise adding 1 might wrap the result. - -2003-06-18 Werner Lemberg - - * src/psnames/psmodule.c (ps_unicode_value): Add support to - recognize `uXXXX[X[X]]' glyph names. - Don't handle glyph names starting with `uni' which have more than - four digits. - -2003-06-16 Werner Lemberg - - * include/freetype/freetype.h (FT_Open_Flags): Replaced with - #defines for the constants. - (FT_Open_Args): Change type of `flags' to FT_UInt. - (FT_GlyphSlot): Move `flags' to FT_Slot_Internal. - - * include/freetype/ftimage.h (FT_Outline_Flags, FT_Raster_Flag): - Replaced with #defines for the constants. - - * include/freetype/internal/ftobjs.h (FT_Slot_Internal): New - field `flags' (from FT_GlyphSlot). - Updated all affected source files. - (FT_GLYPH_OWN_BITMAP): New macro (from ftgloadr.h). - - * include/freetype/internal/ftgloadr.h (FT_GLYPH_OWN_BITMAP): Moved - to ftobjs.h. - - * src/base/ftglyph.c (FT_Glyph_To_Bitmap): Use dummy - FT_GlyphSlot_Internal object. - -2003-06-15 Werner Lemberg - - * builds/compiler/gcc.mk, builds/compiler/gcc-dev.mk (CFLAGS): - Add -fno-strict-aliasing to get rid of zillion warnings from gcc - version 3.3. - -2003-06-14 Werner Lemberg - - * include/freetype/ftglyph.h (ft_glyph_bbox_unscaled, - ft_glyph_bbox_subpixels, ft_glyph_bbox_gridfit, - ft_glyph_bbox_truncate, ft_glyph_bbox_pixels): Replaced with - FT_GLYPH_BBOX_UNSCALED, FT_GLYPH_BBOX_SUBPIXELS, - FT_GLYPH_BBOX_GRIDFIT, FT_GLYPH_BBOX_TRUNCATE, FT_GLYPH_BBOX_PIXELS. - The lowercase variants are now (deprecated aliases) to the uppercase - versions. - Updated all other files. - - * include/freetype/ftmodule.h (ft_module_font_driver, - ft_module_renderer, ft_module_hinter, ft_module_styler, - ft_module_driver_scalable, ft_module_driver_no_outlines, - ft_module_driver_has_hinter): Replaced with FT_MODULE_FONT_DRIVER, - FT_MODULE_RENDERER, FT_MODULE_HINTER, FT_MODULE_STYLER, - FT_MODULE_DRIVER_SCALABLE, FT_MODULE_DRIVER_NO_OUTLINES, - FT_MODULE_DRIVER_HAS_HINTER. - The lowercase variants are now (deprecated aliases) to the uppercase - versions. - Updated all other files. - - * src/base/ftglyph.c (FT_Glyph_Get_CBox): Handle bbox_mode better - as enumeration. - - * src/pcf/pcfdrivr.c (pcf_driver_class), src/winfonts/winfnt.c - (winfnt_driver_class), src/bdf/bdfdrivr.c (bdf_driver_class): Add - the FT_MODULE_DRIVER_NO_OUTLINES flag. - -2003-06-13 Detlef Würkner - - * src/pfr/pfrobjs.c (pfr_slot_load): Apply font matrix. - -2003-06-13 Werner Lemberg - - * builds/dos/detect.mk: Test not only for `Dos' but for `DOS' also. - - * builds/dos/dos-emx.mk, builds/compiler/emx.mk: New files for - EMX gcc compiler. - * builds/dos/detect.mk: Add target `emx'. - - * builds/compiler/watcom.mk (LINK_LIBRARY): GNU Make for DOS doesn't - like a trailing semicolon; add a dummy command. - - * src/cid/cidload.c: Remove parse_font_bbox code (already enclosed - with #if 0 ... #endif). - - * src/type1/t1tokens.h: Handle /FontName. - * src/type1/t1load.c (parse_font_name): Removed. - Remove parse_font_bbox code (already enclosed with #if 0 ... - #endif). - - * src/type42/t42parse.c (t42_parse_font_name): Removed. - Remove t42_parse_font_bbox code (already enclosed with #if 0 ... - #endif). - (t42_keywords): Handle /FontName with T1_FIELD_KEY. - -2003-06-12 Werner Lemberg - - * include/freetype/internal/psaux.h (T1_FieldType): Add - T1_FIELD_TYPE_KEY. - (T1_FIELD_KEY): New macro. - * src/psaux/psobjs.c (ps_parser_load_field): Handle - T1_FIELD_TYPE_KEY. - - * src/cid/cidtoken.h: Use T1_FIELD_KEY for /CIDFontName. - -2003-06-11 Alexander Malmberg - - * src/cache/ftlru.c (FT_LruList_Remove_Selection): Decrease - number of nodes. - (FT_LruList_Lookup): Fix assertion for out-of-memory case. - -2003-06-11 Werner Lemberg - - * src/cid/cidload.c (cid_decrypt): Removed. - (cid_read_subrs): Use t1_decrypt from psaux module. - * src/cid/cidload.h: Updated. - * src/cid/cidgload.c (cid_load_glyph): Use t1_decrypt from psaux - module. - -2003-06-10 Werner Lemberg - - * src/cid/cidobjs.c: Apply change 2003-05-31 from . - Compute style flags. - Fix computation of root->height. - * src/cid/cidtoken.h: Handle FontBBox. - * src/cid/cidload.c (cid_load_keyword): Handle - T1_FIELD_LOCATION_BBOX. - (parse_font_bbox): Commented out. - (cid_field_records): Comment out element for parsing FontBBox. - - * src/type42/t42parse.c (t42_parse_font_bbox): Commented out. - (t42_keywords): Handle FontBBox with T1_FIELD_BBOX, not with - T1_FIELD_CALLBACK. - (t42_parse_font_bbox): Commented out. - (t42_load_keyword): Handle T1_FIELD_LOCATION_BBOX. - * src/type42/t42objs.c (T42_Face_Init): Apply change 2003-05-31 - from . - -2003-06-09 George Williams - - * src/truetype/ttinterp.c (SetSuperRound) <0x30>: Follow Apple's - TrueType specification. - (Ins_MDRP, Ins_MIRP): Fix single width cut-in test. - -2003-06-09 Detlef Würkner - - * src/gzip/ftgzip.c: (inflate_mask): Replaced with... - (NO_INFLATE_MASK): This. - * src/gzip/infutil.h: Declare `inflate_mask' conditionally by - NO_INFLATE_MASK. - -2003-06-09 Alexis S. L. Carvalho - - * src/gzip/ftgzip.c (ft_gzip_file_fill_output): Handle Z_STREAM_END - correctly. - -2003-06-09 Wolfgang Domröse - - * src/pshinter/pshglob.c (psh_globals_new): Change calculation of - dim->stdw.count to avoid compiler problem. - - * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Move the block - variables to the beginning of the function to avoid compiler - problems. - Add casts necessary for 16bit compilers. - -2003-06-09 Werner Lemberg - - * src/pfr/rules.mk (PFR_DRV_SRC): Add pfrsbit.c. - (PFR_DRV_H): Add pfrtypes.h. - - * include/freetype/config/ftconfig.h: s/__MWKS__/__MWERKS__/. - -2003-06-08 Karl Schultz - - * src/pfr/pfrsbit.c (pfr_bitwriter_init): Change type of third - argument to FT_Bool. - (pfr_lookup_bitmap_data): Change type of third and fourth argument - to FT_UInt. Updated caller. - (pfr_load_bitmap_bits): Change type of fourth argument to FT_Bool. - -2003-06-08 Werner Lemberg - - Completely revised FreeType's make management. - - . In all makefiles `/' is used as the path separator. The - conversion to the real path separators is done as late as - possible using $(subst ...). - - . $(HOSTSEP) no longer exists. Now, $(SEP) gives the path separator - for the operating system, and the new $(COMPILER_SEP) the path - separator for the compiler tools. - - . $(BUILD) has been renamed to $(BUILD_DIR). In general, all - directory variables end with `_DIR'. The variants ending in `_' - (like `BASE_' have been removed). - - The following ChangeLog entries only describe changes which are - not related to the redesign. - - * builds/beos/beos-def.mk (BUILD_DIR): Fix typo. - * builds/compiler/watcom.mk (LINK_LIBRARY): Fix linker call to avoid - overlong arguments as suggested by J. Ali Harlow - . - * builds/dos/dos-wat.mk: New file. - * builds/freetype.mk (FREETYPE_H): Include header files from the - `devel' subdirectory. - - * builds/os2/os2-dev.mk, builds/unix/unixddef.mk, - builds/unix/unixddef.mk, builds/win32/w32-bccd.mk, - builds/win32/w32-dev.mk (BUILD_DIR): Fix path. - - * builds/unix/configure.ac, builds/unix/configure: Updated. - * builds/unix/unix-def.in (DISTCLEAN): Add `freetype2.pc'. - -2003-06-07 Werner Lemberg - - * src/base/ftmac.c (FT_New_Face_From_SFNT): s/rlen/sfnt_size/ to - make it compile. - - * devel/ftoption.h: Updated. - -2003-06-07 Detlef Würkner - - * include/freetype/internal/psaux.h, src/truetype/ttgload.h: - s/index/idx/ to fix compiler warnings. - - * src/sfnt/ttcmap0.c (tt_face_build_cmaps): Use more `volatile' to - fix compiler warning. - - * src/gzip/ftgzip.c (BUILDFIXED): Removed. - * src/gzip/inftrees.c (inflate_trees_fixed) [!BUILDFIXED]: Use - FT_UNUSED to remove compiler warning. - -2003-06-06 Werner Lemberg - - * include/freetype/ftstroker.h: Renamed to... - * include/freetype/ftstroke.h: This. - - * src/base/ftstroker.c: Renamed to... - * src/base/ftstroke.c: This. - - * include/freetype/config/ftheader.h (FT_STROKER_H): Updated. - - * src/base/descrip.mms, src/base/Jamfile, src/base/rules.mk: - Updated. - - * src/pcf/pcfdriver.c: Renamed to... - * src/pcf/pcfdrivr.c: This. - * src/pcf/pcfdriver.h: Renamed to... - * src/pcf/pcfdrivr.h: This. - - * src/pcf/Jamfile, src/pcf/rules.mk: Updated. - -2003-06-05 Wenlin Institute (Tom Bishop) - - * src/base/ftmac.c (file_spec_from_path) [TARGET_API_MAC_CARBON]: - Add `#if !defined(__MWERKS__)'. - -2003-06-05 Werner Lemberg - - * include/freetype/internal/psaux.h (T1_FieldType): Add - T1_FIELD_TYPE_FIXED_1000 and T1_FIELD_TYPE_FIXED_1000_P. - (T1_FIELD_FIXED_1000, T1_FIELD_FIXED_1000_P): New macros. - * src/psaux/psobjs.c (ps_parser_load_field): Handle - T1_FIELD_TYPE_FIXED_1000 and T1_FIELD_TYPE_FIXED_1000_P. - - * src/cff/cffparse.c (cff_kind_fixed_thousand): New enumeration. - (CFF_FIELD_FIXED_1000): New macro. - (cff_parser_run): Handle cff_kind_fixed_thousand. - * src/cff/cfftoken.h: Use CFF_FIELD_FIXED_1000 for blue_scale. - * src/cff/cffload (cff_subfont_load): Fix default values of - expansion_factor and blue_scale. - - * src/cid/cidtoken.h, src/type1/t1tokens.h: Use T1_FIELD_FIXED_1000 - for blue_scale. - - * src/pshinter/pshglob.c (psh_globals_new): Fix default value of - blue_scale. - -2003-06-04 Wolfgang Domröse - - * include/freetype/internal/ftdriver.h, - include/freetype/internal/ftobjs.h, - include/freetype/internal/psaux.h, src/cid/cidgload.c, - src/psaux/psobjs.c, src/psaux/t1decode.c, src/psaux/psobjs.h, - src/pshinter/pshrec.c, src/pshinter/pshalgo.c, - src/psnames/psmodule.c, src/raster/ftraster.c, src/sfnt/sfobjs.c, - src/smooth/ftgrays.c, src/smooth/ftsmooth.c, src/truetype/ttobjs.c, - src/truetype/ttdriver.c, src/truetype/ttgload.c, src/type1/t1afm.c, - src/type1/t1gload.c, src/type1/t1gload.h, src/type1/t1load.c, - src/type1/t1objs.c, src/type42/t42parse.c, src/type42/t42parse.h: - Many casts and slight argument type changes to make it work with - a 16bit compiler. - -2003-06-04 Werner Lemberg - - * include/freetype/config/ftoption.h: Defining - TT_CONFIG_OPTION_FORCE_UNPATENTED_HINTING by default is a bad idea - since some fonts (e.g. Arial) produce worse results than without - hinting. Reverted. - -2003-06-04 Werner Lemberg - - * src/truetype/ttgload.c (load_truetype_glyph) - [TT_CONFIG_OPTION_BYTECODE_INTERPRETER]: Call - FT_GlyphLoader_CheckPoints before adding phantom points. This fixes - a segfault bug with fonts (e.g. htst3.ttf) which have nested - subglyphs more than one level deep. Reported by Anthony Fok. - - * include/freetype/config/ftoption.h: Define - TT_CONFIG_OPTION_BYTECODE_INTERPRETER, - TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING, and - TT_CONFIG_OPTION_FORCE_UNPATENTED_HINTING to make it the new - default. - -2003-06-03 Werner Lemberg - - * src/autohint/ahhint.c (ah_hinter_hint_edges): Removed. Just a - wrapper for ah_hint_edges. - (ah_hint_edges): Renamed to... - (ah_hinter_hint_edges): This. - - * src/base/ftobjs.c (FT_Set_Hint_Flags): Removed. Unused. - - * include/freetype/internal/ftobjs.h (FT_Face_InternalRec), - include/freetype/internal/psaux.h (T1_DecoderRec), - src/cff/cffgload.h (CFF_Builder): Remove `hint_flags' field. - Unused. - - * src/cff/cffgload.c (cff_builder_init): Updated. - (cff_decoder_parse_charstrings) : Call hinter->apply - with decoder->hint_mode instead of builder->hint_flags. - * src/psaux/t1decode.c (t1_decoder_init): Updated. - - * src/base/ftstroker.c (ft_stroke_border_export): s/index/idx/. - - * src/sfnt/sfobjs.c (sfnt_load_face): Commented out code which - increased root->height by 15% if the line gap was zero. There exist - fonts (containing e.g. form drawing characters) which intentionally - have a zero line gap value. - - * src/truetype/ttinterp.c (Free_Project, CUR_Func_freeProj): - Removed. Unused. - Updated all callers. - -2003-06-02 Werner Lemberg - - * src/cff/cffobjs.c (cff_face_init): Use symbolic names for - Adobe specific encoding IDs (there was a wrong EID value for custom - encoding). - - * src/cff/cffcmap.h (CFF_CMapStdRec): Remove `count'. - * src/cff/cffcmap.c (cff_cmap_encoding_init, - cff_cmap_encoding_done): Updated. - (cff_cmap_encoding_char_index, cff_cmap_encoding_char_next): Use - 256 as limit for character code. - -2003-06-01 Werner Lemberg - - * src/winfonts/winfnt.c (FNT_Load_Glyph): Revert change from - 2003-03-20. - -2003-05-31 Werner Lemberg - - * include/freetype/fttrigon.h (FT_Vector_Normalize): Removed. - -2003-05-31 - - * src/type1/t1objs.c (T1_Face_Init): Improve algorithm for guessing - the font style by ignoring spaces and hyphens. - - * builds/unix/freetype2.in: Fix `Version' field. - -2003-05-30 Werner Lemberg - - Avoid overwriting of numeric font dictionary entries for synthetic - fonts. Additionally, some entries were handled as `integer' instead - of `number'. - - * include/freetype/internal/psaux.h (T1_FieldType): Add - T1_FIELD_TYPE_BOOL_P, T1_FIELD_TYPE_INTEGER_P, and - T1_FIELD_TYPE_FIXED_P. - (T1_FIELD_BOOL_P, T1_FIELD_NUM_P, T1_FIELD_FIXED_P): New macros. - * src/psaux/psobjs.c (ps_parser_load_field): Handle new field types. - - * include/freetype/internal/cfftypes.h (CFF_FontRecDict), - src/cff/cfftoken.h: Change type of underline_position and - underline_thickness to FT_Fixed. - * src/cff/cffload.c (cff_subfont_load): Fix default values of - underline_position and underline_thickness. - * src/cff/cffobjs.c (cff_face_init): Set underline_position - and underline_thickness in `root'. - - * include/freetype/internal/t1types.h (T1_Font): Change point_type - and stroke_width to pointers. - * include/freetype/t1tables.h (PS_FontInfo): Change italic_angle, - is_fixed_pitch, underline_position, and underline_thickness to - pointers. - * src/type1/t1tokens.h: Change italic_angle, is_fixed_pitch, - underline_position, and underline_thickness to pointers. Change - the type of the latter two to `fixed'. - Change type of stroke_width to `fixed' and make it a pointer. - Change paint_type to pointer. - * src/type1/t1objs.c (T1_Face_Done): Updated. - (T1_Face_Init): Updated. - Fix assignment of underline_position and underline_thickness. - - * src/cid/cidtoken.h: Change italic_angle, is_fixed_pitch, - underline_position, and underline_thickness to pointers. Change - the type of the latter two to `fixed'. - Change type of stroke_width to `fixed'. - * src/cid/cidobjs.c (cid_face_done): Updated. - (cid_face_init): Updated. - Fix assignment of underline_position and underline_thickness. - - * src/type42/t42parse.c: Change italic_angle, is_fixed_pitch, - underline_position, and underline_thickness to pointers. Change the - type of the latter two to `fixed'. - Change type of stroke_width to `fixed' and make it a pointer. - Change paint_type to pointer. - * src/type42/t42objs.c (T42_Face_Init): Updated. - Fix assignment of underline_position and underline_thickness. - (T42_Face_Done): Updated. - - * src/base/ftobjs.c (open_face_from_buffer): Fix compiler warning. - * src/pshinter/pshglob.c, src/pshinter/pshglob.h - (psh_globals_set_scale): Make it a local function. - - * test/gview.c: Fix renaming ps3->ps typo. - Formatting. - -2003-05-29 Werner Lemberg - - * src/pshinter/pshalgo1.[ch], src/pshinter/pshalgo2.[ch]: Removed. - * src/pshinter/pshalgo.h: Removed. - - * src/pshinter/pshalgo3.[ch]: Renamed to... - * src/pshinter/pshalgo.[ch]: New files. - s/PSH3/PSH/. - s/psh3/psh/. - s/ps3/ps/. - - * src/pshinter/pshrec.c, src/pshinter/pshinter.c: Updated. - * src/pshinter/rules.mk, src/pshinter/Jamfile: Updated. - - * src/pshinter/pshglob.[ch] (psh_dimension_snap_width): Commented - out. - - * tests/gview.c: Remove code for pshalgo1 and pshalgo2. - Updated. - -2003-05-28 Martin Zinser - - * vms_make.com: Reworked support for shareable images on VMS. The - first version was kind of a hack; the current implementation of the - procedure to extract the required symbols is much cleaner. - - Reworked creation of MMS files, avoiding a number of temporary files - which were created in the previous version. - - Further work on creating descrip.mms files on the fly. - - * builds/vms/descrip.mms, src/autohint/descrip.mms, - src/type1/descrip.mms: Removed. - -2003-05-28 Werner Lemberg - - * src/pshinter/pshalgo3.c (psh3_glyph_compute_extrema): Skip - contours with only a single point to avoid segfault. - - * src/base/ftglyph.c (FT_Glyph_To_Bitmap): Activate code for - handling `origin'. - -2003-05-24 Werner Lemberg - - * src/autohint/ahtypes.h (AH_OPTION_NO_STRONG_INTERPOLATION): - Removed since unused. - -2003-05-21 Werner Lemberg - - * include/freetype/config/ftstdlib.h (ft_strcat): New wrapper macro - for strcat. - - * src/base/ftmac.c (create_lwfn_name): s/isupper/ft_isupper/. - (parse_font): s/memcpy/ft_memcpy/. - (is_dfont) [TARGET_API_MAC_CARBON]: s/memcmp/ft_memcmp/. - * src/base/ftobjs.c (load_mac_face) [FT_MACINTOSH]: - s/strlen/ft_strlen/. - s/strcat/ft_strcat/. - s/strcpy/ft_strcpy/. - * src/gzip/zutil.h: s/memset/ft_memset/. - s/memcmp/ft_memcmp/. - - * src/bdf/bdfdrivr.c (BDF_Face_Init), src/pcf/pcfdriver.c - (PCF_Face_Init): Test for charset registry case-insensitively. - - * src/gzip/ftgzip.c (ft_gzip_file_io): Revert change from yesterday; - it has already been fixed differently. - - * src/truetype/ttinterp.c (DO_SFVTL): Add missing braces around - if-clause. - -2003-05-21 Martin Zinser - - * t1load.c (parse_blend_axis_types): Fix compiler warning. - - * descrip.mms: Removed. Now created by... - - * vms_make.com: New file. - -2003-05-21 Weiqi Gao - - * src/gzip/ftgzip.c (ft_gzip_file_io): Avoid zero value of `delta' - to prevent infinite loop. - -2003-05-21 Lars Clausen - - * docs/VERSION.DLL: Provide better autoconf snippet to check - FreeType version. - -2003-05-21 Werner Lemberg - - * src/base/ftobjs.c (open_face): Free `internal' not - `face->internal' in case of error to avoid possible segfault. - - * src/pshinter/pshalgo3.c (ps3_hints_apply): Check whether we - actually have an outline. - -2003-05-20 David Chester - - * src/pshinter/pshalgo3.c (ps3_hints_apply): Try to optimize - y_scale so that the top of non-capital letters is aligned on a pixel - boundary whenever possible. - - * src/autohint/ahhint.c (ah_hint_edges): Make sure that lowercase - m's maintain their symmetry. - -2003-05-20 Werner Lemberg - - * src/autohint/ahhint.c (ah_hinter_load_glyph): Oops! David's - patch from yesterday has been resolved already in a different - way. Reverted. - -2003-05-19 David Chester - - * src/autohint/ahhint.c (ah_hinter_load_glyph): Don't scale - y_scale locally but face->size->metrics.y_scale. - -2003-05-19 David Turner - - * src/sfnt/ttcmap0.c (tt_cmap4_char_next): Select proper start - value for `hi' to avoid infinite loop. - -2003-05-18 Yong Sun - - * src/raster/ftraster.c (Insert_Y_Turn): Fix overflow test. - -2003-05-18 Werner Lemberg - - * include/freetype/config/ftoption.h [FT_CONFIG_OPTION_MAC_FONTS]: - New macro. - * src/base/ftobjs.c: Use it to control mac font support on non-mac - platforms. - -2003-05-17 George Williams - - Implement partial support of Mac fonts on non-Mac platforms. - - * src/base/ftobjs.c (memory_stream_close, new_memory_stream, - open_face_from_buffer, Mac_Read_POST_Resource, - Mac_Read_sfnt_Resource, IsMacResource, IsMacBinary, load_mac_face) - [!FT_MACINTOSH]: New functions. - (FT_Open_Face) [!FT_MACINTOSH]: Use load_mac_face. - -2003-05-17 Werner Lemberg - - * src/base/ftobjs.c (FT_Load_Glyph): Scale linear advance width only - if FT_FACE_FLAG_SCALABLE is set (otherwise we have a division by - zero since FNT and friends don't define `face->units_per_EM'). - -2003-05-15 David Turner - - * src/base/fttrigon.c (FT_Vector_Rotate): Avoid rounding errors - for small values. - -2003-05-15 Werner Lemberg - - * src/autohint/ahtypes.h (AH_PointRec): Remove unused `in_angle' - and `out_angle' fields. - -2003-05-14 George Williams - - * src/base/ftmac.c (FT_New_Face_From_SFNT): Handle CFF files also. - -2003-05-14 Werner Lemberg - - * include/freetype/freetype.h: Fix typo in comment - (FT_HAS_FIXED_SIZES). - -2003-05-10 Dan Williams - - * builds/unix/aclocal.m4: Comment out definition of - `allow_undefined_flag' for Darwin 1.3. - * builds/unix/configure.ac: Add option --with-old-mac-fonts. - * builds/unix/ltmain.sh: Fix version numbering for Darwin 1.3. - * builds/unix/configure: Regenerated. - - * include/freetype/config/ftconfig.h: Fix conditions for defining - `FT_MACINTOSH'. - * src/base/ftbase.c: Include `ftmac.c' conditionally. - * src/base/ftmac.c: Handle __GNUC__. - -2003-05-07 YAMANO-UCHI Hidetoshi - - * src/cid/cidload.c (is_alpha): Removed. - (cid_parse_dict): Use `cid_parser_skip_alpha' instead of `is_alpha'. - -2003-05-07 Werner Lemberg - - * src/autohint/ahoptim.c, src/autohint/ahoptim.h: Obsolete, removed. - -2003-05-07 David Turner - - * src/autohint/ahglyph.c (ah_setup_uv): Exchange `for' loop and - `switch' statement to make it run faster. - (ah_outline_compute_segments): Reset `segment->score' and - `segment->link'. - (ah_outline_link_segments): Provide alternative code which does - the same but runs much faster. - Handle major direction also. - (ah_outline_compute_edges): Scale `edge_distance_threshold' down - after rounding instead of scaling comparison value in loop. - - * src/autohint/ahhint.c (ah_hinter_align_strong_points): Provide - alternative code which runs faster. - Handle `before->scale == 0'. - - * src/autohint/ahtypes.h (AH_SegmentRec): Move some fields down. - (AH_EdgeRec): Move some fields in structure. - New field `scale'. - - * src/sfnt/ttcmap0.c (tt_cmap4_char_next): Use binary search. - -2003-05-02 Werner Lemberg - - * src/autohint/ahoptim.c (LOG): Renamed to... - (AH_OPTIM_LOG): This. - (AH_Dump_Springs): Fix log message format. - - * src/autohint/ahhint.c (ah_hint_edges_3): Renamed to... - (ah_hint_edges): This. - -2002-05-02 Keith Packard - - * src/bdf/bdfdrivr.c (BDF_Set_Pixel_Size): Initialize `max_advance'. - -2003-05-01 Werner Lemberg - - * src/autohint/ahglyph.c (ah_test_extrema): Renamed to... - (ah_test_extremum): This. - -2003-04-28 Werner Lemberg - - * builds/unix/configure.ac: Generate `freetype.pc' from - `freetype.in'. - * builds/unix/configure: Regenerated. - * builds/unix/install.mk (install, uninstall): Handle `freetype.pc'. - -2003-04-28 Gustavo J. A. M. Carneiro - - * builds/unix/freetype2.in: New file. Contains building information - for the `pkg-config' package. - -2003-04-28 David Turner - - * src/base/ftobjs.c (FT_Load_Glyph): Fix boundary check for - `glyph_index'. - -2003-04-25: Graham Asher - - Added the optional unpatented hinting system for TrueType. It - allows typefaces which need hinting to produce correct glyph forms - (e.g., Chinese typefaces from Dynalab) to work acceptably without - infringing Apple patents. This system is compiled only if - TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING is defined in - ftoption.h. - - * include/freetype/ttunpat.h: New file. Defines - FT_PARAM_TAG_UNPATENTED_HINTING. - - * include/freetype/config/ftheader.h (FT_TRUETYPE_UNPATENTED_H): New - macro to use when including ttunpat.h. - - * include/freetype/config/ftoption.h - (TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING, - TT_CONFIG_OPTION_FORCE_UNPATENTED_HINTING): New configuration macros - (not defined, but in comments) for the unpatented hinting system. - - * include/freetype/internal/tttypes.h (TT_FaceRec) - [TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING]: New element `FT_Bool - unpatented_hinting'. - - * src/truetype/ttinterp.c (NO_APPLE_PATENT, APPLE_THRESHOLD): - Removed. - (GUESS_VECTOR): New macro. - (TT_Run_Context) [TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING]: - Set `both_x_axis'. - (tt_default_graphics_state) - [TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING]: Updated. - (Current_Ratio) [TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING]: - Handle `unpatented_hinting'. - (Direct_Move) [NO_APPLE_PATENT]: Removed. - [TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING]: Insert assertion. - (Project, FreeProject) - [TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING]: Insert assertion. - (Compute_Funcs) [TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING]: - Implement unpatented hinting. - (DO_SPVTCA, DO_SFVTCA, DO_SPVTL, DO_SFVTL, DO_SPVFS, DO_SFVFS, - Ins_SDPVTL): Call `GUESS_VECTOR'. - (DO_GPV, DO_GFV) [TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING]: - Handle `unpatented_hinting'. - (Compute_Point_Displacement) [NO_APPLE_PATENT]: Removed. - [TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING]: Implement unpatented - hinting. - (Move_Zp2_Point, Ins_SHPIX, Ins_DELTAP, Ins_DELTAC) - [TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING]: Implement unpatented - hinting. - (TT_RunIns): Updated. - - * src/truetype/ttobjs.c - [TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING]: Include - FT_TRUETYPE_UNPATENTED_H. - (tt_face_init) [TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING, - TT_CONFIG_OPTION_FORCE_UNPATENTED_HINTING]: Check - FT_PARAM_TAG_UNPATENTED_HINTING. - - * src/truetype/ttobjs.h (TT_GraphicsState) - [TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING]: Add `both_x_axis'. - -2003-04-25 Werner Lemberg - - * src/bdf/bdflib.c (hash_bucket, hash_lookup): Use `const' for first - argument. - (bdf_get_font_property): Use `const' for third argument. - Updated all callers. - * src/bdf/bdfdrivr.c (BDF_Face_Init): Set pixel width and height - similar to the PCF driver. - * src/bdf/bdf.h (_hashnode): Use `const' for `key'. - Updated. - - * src/gzip/ftgzip.c: C++ doesn't like that the array `inflate_mask' - is declared twice. It is perhaps better to modify the zlib source - files directly instead of this hack. - (zcalloc, zfree, ft_gzip_stream_close, ft_gzip_stream_io): Add casts - to make build with g++ successful. - -2003-04-24 Manish Singh - - * src/cid/cidobjs.c (cid_face_init), src/type1/t1objs.c - (T1_Face_Init), src/type42/t42objs.c (T42_Face_Init): Split on `-' - also for searching the style name. - -2003-04-24 David Turner - - * src/pcf/pcfread.c (pcf_load_font): Fixed the computation of - face->num_glyphs. We must increase the value by 1 to respect the - convention that glyph index 0 always corresponds to the `missing - glyph'. - -2003-04-24 Werner Lemberg - - * builds/unix/unix-cc.in (CFLAGS): Add @CPPFLAGS@. - -2003-04-24 Dieter Baron - - * builds/unix/freetype-config.in (cflags): Emit FreeType 2's include - files first. Otherwise there are conflicts with FreeType 1 - installed simultaneously. - -2003-04-23 Werner Lemberg - - Fixing bugs reported by Nelson Beebe. - - * src/base/ftstroker.c (FT_Stroker_ParseOutline): Remove unused - variable `in_path'. - - * src/base/ftobjs (ft_glyphslot_set_bitmap): Change type of - second argument to `FT_Byte*'. - * include/freetype/internal/ftobjs.h: Updated. - - * src/bdf/bdflib.c (_bdf_readstream): Remove unused variable `res'. - (_bdf_parse_glyphs): Remove unused variable `next'. - Mark `call_data' as unused. - - * src/cache/ftlru.c (FT_LruList_Lookup): Remove unused variable - `plast'. - - * src/pcf/pcfread.c (pcf_seek_to_table_type): Slight recoding to - actually use `error'. - (pcf_load_font): Remove unused variable `avgw'. - - * src/pfr/pfrobjs.c (pfr_face_get_kerning): Change return type - to `void'. - Mark `error' as unused. - * src/pfr/pfrobjs.h: Updated. - * src/pfr/pfrdrivr.c (pfr_get_kerning): Updated. - - * src/sfnt/ttload.c (sfnt_dir_check): Remove unused variable - `format_tag'. - - * src/sfnt/ttcmap0.c (tt_cmap6_validate, tt_cmap10_validate): Remove - unused variable `start'. - (tt_cmap10_char_next): Remove unused variable `result' - - * src/sfnt/sfobjs.c (tt_face_get_name): Mark `error' as unused. - - * src/sfnt/sfdriver.c (get_sfnt_postscript_name): Mark `error' as - unused. - - * src/type1/t1objs.c (T1_Face_Init): Remove unused variable - `pshinter'. - - * src/type1/t1gload.c (T1_Load_Glyph): Use `glyph_data_loaded' - only for FT_CONFIG_OPTION_INCREMENTAL. - -2003-04-23 Akito Hirai - - * src/sfnt/ttcmap0.c (tt_cmap4_validate): Provide a weak variant - of the glyph ID bounding check if FT_VALIDATE_TIGHT is not active. - Without this change, many CJK fonts from Dynalab are rejected. - -2003-04-23 Joe Marcus Clarke - - * src/base/ftbdf.c (FT_Get_BDF_Property): Check for valid - `get_interface'. - -2003-04-23 Paul Miller - - * src/base/ftmac.c (parse_fond): Fix handling of style names. - -2003-04-23 Werner Lemberg - - * src/pfr/pfrload.c (pfr_extra_item_load_font_id): Use FT_PtrDist - instead of FT_UInt for `len'. - -2003-04-22 Werner Lemberg - - * src/gzip/ftgzip.c (zcalloc) [!FT_CONFIG_OPTION_SYSTEM_ZLIB]: - Convert K&R format to modern C usage. - (FT_Stream_OpenGzip): Use long constant. - -2003-04-21 Werner Lemberg - - * src/cache/ftccache.c (ftc_cache_lookup): Remove shadow declaration - of `manager'. - -2003-04-20 Werner Lemberg - - * doc/INSTALL.UNX: Cleaned up. - -2003-04-09 Torrey Lyons - - * src/base/ftmac.c (open_face_from_buffer): Removed a double-free - bug that had nasty consequences when trying to open an `invalid' - font on a Mac. - -2003-04-09 Mike Fabian - - * src/bdf/bdfdrivr.h (BDF_encoding_el), src/pcf/pcf.h - (PCF_EncodingRec): Changed FT_Short to FT_UShort in order to be able - to access more than 32768 glyphs in fonts. - -2003-04-08 David Turner - - - * Version 2.1.4 released. - ========================= - - -2003-04-03 Martin Muskens - - * src/type1/t1load.c (T1_Open_Face): Fixed the code to make it - handle special cases where a font only contains a `.notdef' glyph - (happens in PDF-embedded fonts). Otherwise, FT_Panic was called. - -2003-03-27 David Turner - - * README: Updated. - - * README.UNX: Removed (now replaced by docs/INSTALL.UNX). - - * src/pshinter/pshalgo3.c: The hinter now performs as in 2.1.3 and - will ignore stem quantization only when FT_LOAD_TARGET_SMOOTH is - used. - (psh3_dimension_quantize_len): Enabled. - (psh3_hint_align): Enable commented code. - (psh3_hint_align_light): Commented out. - - * src/base/ftobjs.c (FT_Set_Char_Size): Changed the default - computations to include rounding in all cases; this is required to - provide accurate kerning data when native TrueType hinting is - enabled. - - * src/type1/t1load.c (is_name_char): The Type 1 loader now accepts - more general names according to the PostScript specification (the - previous one was too restrictive). - (parse_font_name, parse_encoding, parse_charstrings, parse_dict): - Use `is_name_char'. - (parse_subrs): Handle empty arrays. - -2003-03-20 David Turner - - Serious rewriting of the documentation. - - * docs/BUGS, docs/BUILD: Removed. - * docs/DEBUG.TXT: Renamed to... - * docs/DEBUG: This. - * docs/CUSTOMIZE, docs/TRUETYPE, docs/UPGRADE.UNX: New files. - * docs/INSTALL.ANY, docs/INSTALL.UNX, docs/INSTALL.GNU New files, - containing platform specific information previously in INSTALL. - * docs/readme.vms: Renamed to... - * docs/INSTALL.VMS: This. - - * docs/*: Updated. - - Introduced three new functions to deal with glyph bitmaps within - FT_GlyphSlot objects: - - ft_glyphslot_free_bitmap - ft_glyphslot_alloc_bitmap - ft_glyphslot_set_bitmap - - These functions are much more convenient to use than managing the - FT_GLYPH_OWN_BITMAP flag manually. - - * include/freetype/internal/ftobjs.h (ft_glyphslot_free_bitmap, - ft_glyphslot_alloc_bitmap, ft_glyphslot_set_bitmap): New functions. - * src/base/ftobjs.c: Implement them. - (ft_glyphslot_done): Use ft_glyphslot_free_bitmap. - - * src/bdf/bdfdrivr.c (BDF_Glyph_Load), src/pcf/pcfdriver.c - (PCF_Glyph_Load): Remove unused variable `memory'. - Use `ft_glyphslot_*' functions. - Don't set `FT_GLYPH_OWN_BITMAP'. - - * src/pfr/pfrsbit.c (pfr_slot_load_bitmap): Use - `ft_glyphslot_alloc_bitmap'. - - * src/sfnt/ttsbit.c (Load_SBit_Image): Change 5th argument to type - `FT_GlyphSlot'. - Adding argument `depth' to handle recursive calls. - Use `ft_glyphslot_alloc_bitmap'. - (tt_face_load_sbit_image): Remove unused variable `memory'. - Don't handle `FT_GLYPH_OWN_BITMAP'. - Update call to Load_SBit_Image. - - * src/type42/t42objs.c (ft_glyphslot_clear): Renamed to... - (t42_glyphslot_clear): This. Updated caller. - Call `ft_glyphslot_free_bitmap'. - - * src/winfonts/winfnt.c (FNT_Load_Glyph): Use - `ft_glyphslot_set_bitmap'. - Don't handle `FT_GLYPH_OWN_BITMAP'. - - * src/cache/ftlru.c (FT_LruList_Lookup): Fixed an invalid assertion - check. - - * src/autohint/ahglyph.c (ah_outline_load): Add two scaling - arguments. - * src/autohint/ahglyph.h: Updated. - * src/autohint/ahhint.c (ah_hinter_load): Updated. - * src/autohint/ahglobal.c (ah_hinter_compute_widths): Updated. - - * src/cache/ftccache.c (ftc_family_done): Fixed small bug that could - crash the cache in rare circumstances (mostly with broken fonts). - -2003-03-15 David Turner - - * src/truetype/ttdriver.c (Set_Char_Sizes): Fixed a small rounding - bug. Actually, it seems that previous versions of FreeType didn't - perform TrueType rounding exactly as appropriate. - -2003-03-14 David Turner - - * src/truetype/ttdriver.c (Set_Char_Sizes): Fixing the small - TrueType native rendering glitches; they came from a small rounding - error. - -2003-03-13 David Turner - - Added new environment variables to control memory debugging with - FreeType. See the description of `FT2_DEBUG_MEMORY', - `FT2_ALLOC_TOTAL_MAX' and `FT2_ALLOC_COUNT_MAX' in DEBUG.TXT. - - * src/base/ftdbgmem.c (FT_MemTableRec): Add `alloc_count', - `bound_total', `alloc_total_max', `bound_count', `alloc_count_max'. - (ft_mem_debug_alloc): Handle new variables. - (ft_mem_debug_init): s/FT_DEBUG_MEMORY/FT2_DEBUG_MEMORY/. - Handle new environment variables. - * docs/DEBUG.TXT: Updated. - - Fixed the cache sub-system to correctly deal with out-of-memory - conditions. - - * src/cache/ftccache.c (ftc_node_destroy): Comment out generic - check. - (ftc_cache_lookup): Implement loop. - * src/cache/ftccmap.c: Define FT_COMPONENT. - * src/cache/ftcsbits.c (ftc_sbit_node_load): Handle - FT_Err_Out_Of_Memory. - * src/cache/ftlru.c: Include FT_INTERNAL_DEBUG_H. - (FT_LruList_Lookup): Implement loop. - - * src/pfr/pfrobjs.c (pfr_face_done): Fix memory leak. - (pfr_face_init): Fixing compiler warnings. - - * src/psaux/psobjs.c (reallocate_t1_table): Fixed a bug (memory - leak) that only happened when a try to resize an array would end in - an out-of-memory condition. - - * src/smooth/ftgrays.c (gray_convert_glyph): Removed compiler - warnings / volatile bug. - - * src/truetype/ttobjs.c (tt_glyphzone_done): Removed segmentation - fault that happened in tight memory environments. - -2003-02-28 Pixel - - * src/gzip/ftgzip.c (ft_gzip_file_done): Fixed memory leak: The ZLib - stream was not properly finalized. - -2003-02-25 Anthony Fok - - * src/cache/ftccmap.c: Include FT_TRUETYPE_IDS_H. - (ftc_cmap_family_init): The cmap cache now - supports UCS-4 charmaps when available in Asian fonts. - - * src/sfnt/ttload.c, src/base/ftobjs.c: Changed `asian' to `Asian' - in comments. - -2003-02-25 David Turner - - * src/gzip/ftgzip.c (ft_gzip_file_fill_output): Fixed a bug that - caused FreeType to loop endlessly when trying to read certain - compressed gzip files. The following test reveals the bug: - - touch 0123456789 ; gzip 0123456789 ; ftdump 0123456789.gz - - Several fixes to the PFR font driver: - - - The list of available embedded bitmaps was not correctly set in - the root FT_FaceRec structure describing the face. - - - The glyph loader always tried to load the outlines when - FT_LOAD_SBITS_ONLY was specified. - - - The table loaded now scans for *undocumented* elements of a - physical font's auxiliary data record. This is necessary to - retrieve the `real' family and style names. - - NOTE THAT THESE CHANGES THE FAMILY NAME OF MANY PFR FONTS! - - * src/pfr/pfrload.c (pfr_aux_name_load): New function. - (pfr_phy_font_done): Free `family_name' and `style_name' also. - Remove unused variables. - (pfr_phy_font_load): Extract useful information from the auxiliary - bytes. - - * src/pfr/pfrobjs.c (pfr_face_done): Set pointers to NULL. - (pfr_face_init): Provide fallback values for `family_name' and - `style_name'. - Handle strikes. - (pfr_slot_load): Handle FT_LOAD_SBITS_ONLY. - * src/pfr/pfrtypes.h (PFR_PhyFontRec): Add fields `ascent', - `descent', `leading', `family_name', and `style_name'. - - * src/truetype/ttdriver.c (Set_Char_Sizes): Fixed a rounding bug - when computing the scale factors for a given character size in - points with resolution. - - * devel/ft2build.h, devel/ftoption.h: New files (in a new directory) - which are special development versions of include/ft2build.h and - include/freetype/config/ftoption.h, respectively. - -2003-02-18 David Turner - - Fixing the slight distortion problem that occurred due to the latest - auto-hinter changes. - - * src/base/ftobjs.c (ft_recompute_scaled_metrics): Fix rounding. - - * src/truetype/ttdriver.c (Set_Char_Sizes): New variable `metrics2'. - [!TT_CONFIG_OPTION_BYTECODE_INTERPRETER]: Removed. - - * src/truetype/ttobjs.h (TT_SizeRec): New field `metrics'. - * src/truetype/ttobjs.c (Reset_Outline_Size): Fix initialization of - `metrics'. - [FT_CONFIG_CHESTER_ASCENDER]: Code removed. - (Reset_SBit_Size): Fix initialization of `metrics'. - - * src/truetype/ttinterp.c (TT_Load_Context): Fix initialization of - `exec->metrics'. - - * src/autohint/ahhint.c (ah_hinter_load): Disabled the advance width - `correction' which seemed to provide more trouble than benefits. - -2003-02-13 Graham Asher - - Changed the incremental loading interface in a way that makes it - simpler and allows glyph metrics to be changed (e.g., by adding a - constant, as required by CFF fonts) rather than just overridden. - This was required to make the GhostScript-to-FreeType bridge work. - - * src/cff/cffgload.c (cff_slot_load) [FT_CONFIG_OPTION_INCREMENTAL]: - Allow metrics to be overridden. - * src/cid/cidgload.c (cid_load_glyph) [FT_CONFIG_OPTION_INCREMENTAL]: - Ditto. - - * src/truetype/ttgload.c (load_truetype_glyph) - [FT_CONFIG_OPTION_INCREMENTAL]: Simplify. - (compute_glyph_metrics) [FT_CONFIG_OPTION_INCREMENTAL]: Code block - moved down. - - * src/type1/t1gload.c (T1_Parse_Glyph_And_Get_Char_String) - [FT_CONFIG_OPTION_INCREMENTAL]: Updated. - - * include/freetype/ftincrem.h: Updated. - -2003-01-31 David Turner - - * docs/CHANGES, docs/VERSION.DLL, docs/TODO: Updating documentation - for the 2.1.4 release. - - * builds/win32/visualc/freetype.dsp, - builds/win32/visualc/index.html: Updating the project file for - 2.1.4. - - * src/gzip/adler32.c, src/gzip/ftgzip.c, src/gzip/infblock.c, - src/gzip/infcodes.c, src/gzip/inflate.c, src/gzip/inftrees.c, - src/gzip/infutil.c: Removed old-style (K&R)function definitions. - This avoids warnings with Visual C++ at its most pedantic mode. - - * src/pfr/pfrsbit.c: Removed compiler warnings. - - * src/cache/ftccmap.c (ftc_cmap_family_init): Changed an FT_ERROR - into an FT_TRACE1 since it caused `ftview' and others to dump too - much junk when trying to display a waterfall with a font without a - Unicode charmap (e.g. SYMBOL.TTF). - - Implemented FT_CONFIG_CHESTER_BLUE_SCALE, corresponding to the last - patch from David Chester, but with a much simpler (and saner) - implementation. - - * src/autohint/ahhint.c (ah_hinter_load_glyph) - [FT_CONFIG_CHESTER_BLUE_SCALE]: Try to optimize the y_scale so that - the top of non-capital letters is aligned on a pixel boundary - whenever possible. - - * src/base/ftobjs.c (FT_Set_Char_Size) - [FT_CONFIG_CHESTER_BLUE_SCALE]: Round differently. - * src/truetype/ttdriver.c (Set_Char_Sizes) - [TT_CONFIG_OPTION_BYTECODE_INTERPRETER]: Do some rounding only - if this macro is defined. - - * src/truetype/ttobjs.c (Reset_Outline_Size) - [FT_CONFIG_CHESTER_ASCENDER]: Round differently. - - * src/pshinter/pshalgo3.c: Improved the Postscript hinter. Getting - rid of stem snapping seems to work well here (though the stems are - still slightly moved to increase contrast). - (psh3_dimension_quantize_len): Commented out. - (psh3_hint_align_light): New function. - (psh3_hint_align): Comment out some code. - - THIS IMPROVES ANTI-ALIASED RENDERING, BUT MONOCHROME AND LCD MODES - STILL SUCK. - -2003-01-22 David Chester - - * src/autohint/ahhint.c (ah_compute_stem_width): Small fix to the - stem width optimization. - -2003-01-22 David Turner - - Adding a new API `FT_Get_BDF_Property' to retrieve the BDF - properties of a given PCF or BDF font. - - * include/freetype/ftbdf.h (BDF_PropertyType): New enumeration. - (BDF_Property, BDF_PropertyRec): New structure. - FT_Get_BDF_Property): New function. - * include/freetype/internal/bdftypes.h: Include FT_BDF_H. - (BDF_GetPropertyFunc): New function pointer. - - * src/base/ftbdf.c (test_font_type): New helper function. - (FT_Get_BDF_Charset_ID): Use `test_font_type'. - (FT_Get_BDF_Property): New function. - - * src/bdf/bdfdrivr.c: Include FT_BDF_H. - (bdf_get_bdf_property, bdf_driver_requester): New functions. - (bdf_driver_class): Use `bdf_driver_requester'. - - * src/pcf/pcfdrivr.c: Include FT_BDF_H. - (pcf_get_bdf_property, pcf_driver_requester): New functions - (pcf_driver_class): Use `pcf_driver_requester'. - - * src/pcf/pcfread.c: Include `pcfread.h'. - (pcf_find_property): Decorate it with FT_LOCAL_DEF. - * src/pcf/pcfread.h: New file, providing `pcf_find_property'. - - * src/sfnt/ttload.c (sfnt_dir_check): Relaxed the `head' table size - verification to accept a few broken fonts who pad the size - incorrectly (the table should be padded, but its `size' field - shouldn't according to the specification). - -2003-01-18 Werner Lemberg - - * builds/unix/ltmain.sh: Regenerated with `libtoolize --force - --copy' from libtool 1.4.3. - * builds/unix/aclocal.m4: Regenerated with `aclocal -I .' from - automake 1.7.1. - * builds/unix/configure: Regenerated with autoconf 2.54. - * builds/unix/config.guess, builds/unix/config.sub: Updated from - `config' CVS module at subversions.gnu.org. - * builds/unix/install-sh, builds/unix/mkinstalldirs: Updated from - `automake' CVS module at subversions.gnu.org. - -2003-01-15 David Turner - - * include/freetype/freetype.h: Fixed documentation for - FT_Size_Metrics. - -2003-01-15 James Su - - * src/gzip/ftgzip.c (ft_gzip_check_header): Bugfix: couldn't read - certain gzip-ed font files (typo: `&&' -> `&'). - -2003-01-15 Huw D M Davies - - Added a Windows .FNT specific API (mostly for Wine). Also fixed a - nasty bug in the header loader which would cause invalid memory - overwrites. - - * include/freetype/config/ftheader.h (FT_WINFONTS_H): New macro - for ftwinfnt.h. - * include/freetype/internal/fnttypes.h: Include FT_WINFONTS_H. - (FNT_FontRec): Updated. - Move Windows FNT definition to... - * include/freetype/ftwinfnt.h: This new file. - (FT_WinFNT_HeaderRec): Rename `reserved2' to `reserved1'. - * src/base/ftwinfnt.c: New file, providing `FT_Get_WinFNT_Header'. - * src/winfonts/winfnt.c (winfnt_header_fields): Updated. - Rename `reserved2' to `reserved1'. - (fnt_font_load): Updated. - - * src/base/Jamfile, src/base/descrip.mms, src/base/rules.mk: - Updated. - -2003-01-14 Graham Asher - - * include/freetype/ftglyph.h, src/base/ftglyph.c: Added `const' to - the type of the first argument to FT_Matrix_Multiply, which isn't - changed -- this adds documentation and convenience. - -2003-01-13 Graham Asher - - * src/sfnt/ttload.c (tt_face_load_metrics) - [FT_CONFIG_OPTION_INCREMENTAL]: TrueType typefaces without - horizontal metrics (without the `hmtx' table) are now tolerated if - an incremental interface has been specified that has a - get_glyph_metrics function, implying that metrics will be supplied - from outside. This happens for certain Type 42 fonts passed from - GhostScript. - -2003-01-11 David Chester - - Patches to the auto-hinter in order to slightly improve the output. - Note that everything is controlled through the new - FT_CONFIG_OPTION_CHESTER_HINTS defined in `ftoption.h'. There are - also individual FT_CONFIG_CHESTER_XXX macros to control individual - `features'. - - Note that all improvements are enabled by default, but can be - tweaked for optimization and testing purposes. The configuration - macros will most likely disappear in the short future. - - * include/freetype/config/ftoption.h - (FT_CONFIG_OPTION_CHESTER_HINTS): New macro. - (FT_CONFIG_CHESTER_{SMALL_F,ASCENDER,SERIF,STEM,BLUE_SCALE}) - [FT_CONFIG_OPTION_CHESTER_HINTS]: New macros to control individual - features. - - * src/autohint/ahglobal.c (blue_chars) [FT_CONFIG_CHESTER_SMALL_F]: - Add blue zone for `fijkdbh'. - * src/autohint/ahglobal.h (AH_IS_TOP_BLUE) - [FT_CONFIG_CHESTER_SMALL_F]: Use `AH_BLUE_SMALL_F_TOP'. - * src/autohint/ahglyph.c (ah_outline_compute_edges) - [FT_CONFIG_CHESTER_SERIF]: Use `AH_EDGE_SERIF'. - (ah_outline_compute_blue_edges) [FT_CONFIG_CHESTER_SMALL_F]: - Increase threshold for `best_dist'. - * src/autohint/ahhint.c (ah_compute_stem_width) - [FT_CONFIG_CHESTER_SERIF]: Provide new version for improved serif - handling. - (ah_align_linked_edge) [FT_CONFIG_CHESTER_SERIF]: Use special - version of `ah_compute_stem_width'. - (ah_hint_edges_3) [FT_CONFIG_CHESTER_STEM]: A new algorithm for stem - alignment when stem widths are less than 1.5 pixels wide centers the - stem slightly off-center of the center of a pixel (this increases - sharpness and consistency). - [FT_CONFIG_CHESTER_SERIF]: Use special version of - `ah_compute_stem_width'. - * src/autohint/ahtypes.h [FT_CONFIG_CHESTER_SMALL_F]: Add - `AH_BLUE_SMALL_F_TOP'. - -2003-01-11 David Turner - - * include/freetype/internal/fnttypes.h (WinFNT_HeaderRec): Increase - size of `reserved2' to avoid memory overwrites. - -2003-01-08 Huw Davies - - * src/winfonts/winfnt.c (winfnt_header_fields): Read 16 bytes into - `reserved2', not `reserved'. - - * src/base/ftobjs.c (find_unicode_charmap): Fixed the error code - returned when the font doesn't contain a Unicode charmap. This - allows FT2 to load `symbol.ttf' and a few others correctly since the - last release. - (open_face): Fix return value. - -2003-01-08 Owen Taylor - - Implemented the FT_RENDER_MODE_LIGHT hinting mode in the auto and - postscript hinters. - - * src/autohint/ahtypes.h (AH_HinterRec): Add `do_stem_adjust'. - * src/autohint/ahhint.c (ah_compute_stem_width): Handle - hinter->do_stem_adjust. - (ah_hinter_load_glyph): Set hinter->do_stem_adjust. - - * src/pshinter/pshalgo3.h (PSH3_GlyphRec): Add `do_stem_adjust'. - * src/pshinter/pshalgo3.c (psh3_hint_align): Use `do_stem_adjust'. - (ps3_hints_apply): Handle FT_RENDER_MODE_LIGHT. - - * include/freetype/freetype.h (FT_Render_Mode): Add - FT_RENDER_MODE_LIGHT. - - * src/truetype/ttgload.c: Fixing the TrueType loader to handle - invalid composites correctly by limiting the recursion depth. - (TT_MAX_COMPOSITE_RECURSE): New macro. - (load_truetype_glyph): Add argument `recurse_count'. - Load a composite only if the numbers of contours is -1, emit error - otherwise. - (TT_Load_Glyph): Updated. - -2003-01-08 David Turner - - * Jamrules, Jamfile, Jamfile.in, src/*/Jamfile: Small changes to - support the compilation of FreeType 2 as part of larger projects - with their own configuration options (only with Jam). - -2003-01-07 David Turner - - * src/base/ftstroker.c: Probably the last bug-fixes to the stroker; - the API is likely to change, however. - (ft_stroke_border_close): Don't record empty paths. - (ft_stroke_border_get_counts): Increase `num_points' also in for loop. - (ft_stroke_border_export): Don't increase `write' twice in for loops. - (ft_stroker_outside): Handle `phi' together with `theta'. - (FT_Stroker_ParseOutline): New function. - - * src/base/fttrigon.c (FT_Angle_Diff): Fixing function: It returned - invalid values for large negative angle differences (resulting in - incorrect stroker computations, among other things). - - * src/cache/ftccache.c (ftc_node_hash_unlink): Removing incorrect - assertion, and changing code to avoid hash table size contraction. - - * src/base/Jamfile, src/base/rules.mk, src/base/descrip.mms: Adding - `ftstroker' to default build, as optional component. - -2002-12-26 David Turner - - * src/gzip/adler32.c, src/gzip/infblock.c, src/gzip/inflate.c, - src/gzip/inftrees.c, src/gzip/zconf.h, src/gzip/zlib.h, - src/gzip/zutil.h: Updates to allow compilation without compiler - warnings with LCC-Win32. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 4. - * builds/unix/configure.ac (version_info): Increased to 9:3:3. - * builds/unix/configure: Regenerated. - * docs/VERSION.DLL: Updated. - -2002-12-23 Anthony Fok - - * builds/unix/configure.ac, builds/unix/unix-cc.in (LINK_LIBRARY), - builds/unix/unix-def.in (SYSTEM_ZLIB): Small fix to configure - sub-system on Unix to allow other programs to correctly link with - zlib when needed. - -2002-12-19 David Turner - - * include/freetype/internal/sfnt.h (SFNT_Load_Table_Func): New - function pointer. - - * include/freetype/tttables.h (FT_Load_Sfnt_Table): New function. - * src/base/ftobjs.c: Implement it. - - * src/sfnt/sfdriver.c (sfnt_get_interface): Handle `load_sfnt' - module request. - -2002-12-17 David Turner - - * src/base/ftobjs.c (find_unicode_charmap): Added some comments to - better explain what's happening there. - (open_face): Included Graham Asher's fix to prevent faces without - Unicode charmaps from loading. - - * src/winfonts/winfnt.c: Included George Williams's fix to support - version 2 fonts correctly. - (winfnt_header_fields): Updated. - (fnt_font_load): Handle version 2 fonts. - (FNT_Load_Glyph): Updated. - -2002-12-16 David Turner - - * docs/VERSION.DLL: Updating document to better explain the - differences between the three version numbers being used on Unix, as - well as providing an autoconf fragment provided by Lars Clausen. - - * src/smooth/ftgrays.c (gray_render_conic): Fixed small bug that - prevented Bézier arcs with negative vertical coordinates to be - rendered appropriately. - -2002-12-02 Antoine Leca - - * src/base/ftobjs.c: Modified the logic to get Unicode charmaps. - Now it loads UCS-4 charmaps when there is one. - (find_unicode_charmap): New function. - (open_face): Refer to the above one. - (FT_Select_Charmap): Idem. - -2002-11-29 Antoine Leca - - * include/freetype/ftgzip.h: Correct the name of the controlling - macro (was __FTXF86_H__ ...). - -2002-11-27 Vincent Caron - - * builds/unix/unix-def.in, builds/unix/freetype-config.in, - builds/unix/configure.ac, src/gzip/rules.mk, src/gzip/ftgzip.c - [FT_CONFIG_OPTION_SYSTEM_ZLIB]: Adding support for system zlib - installations if available on the target platform (Unix only). - -2002-11-23 David Turner - - * src/cff/cffload.c (cff_charset_load, cff_encoding_load): Modified - charset loader to accept pre-defined charsets, even when the font - contains fewer glyphs. Also enforced more checks to ensure that we - never overflow the character codes array in the encoding. - -2002-11-22 Antoine Leca - - * include/freetype/ttnameid.h: Updated to latest OpenType - specification. - -2002-11-18 David Turner - - - * Version 2.1.3 released. - ========================= - - -2002-11-07 David Turner - - * src/cache/ftcsbits.c (ftc_sbit_node_load): Fixed a small bug that - caused problems with embedded bitmaps. - - * src/otlayout/otlayout.h, src/otlayout/otlconf.h, - src/otlayout/otlgsub.c, src/otlayout/otlgsub.h, - src/otlayout/otlparse.c, src/otlayout/otlparse.h, - src/otlayout/otlutils.h: Updating the OpenType Layout code, adding - support for the first GSUB lookups. Nothing that really compiles - for now though. - - * src/autohint/ahhint.c (ah_align_serif_edge): Disabled serif stem - width quantization. It produces slightly better shapes though this - is not distinguishable with many fonts. - Remove other dead code. - - * src/Jamfile, src/*/Jamfile: Simplified. - Use $(FT2_SRC_DIR). - -2002-11-06 David Turner - - * include/freetype/freetype.h (FT_LOAD_TARGET_LIGHT): New macro. - (FT_LOAD_TARGET, FT_LOAD_TARGET_MODE): Use `& 15' instead of `& 7'. - -2002-11-05 David Turner - - * include/freetype/config/ftoption.h, src/gzip/ftgzip.c: Added - support for the FT_CONFIG_OPTION_SYSTEM_ZLIB option, used to specify - the use of system-wide zlib. - - Note that this macro, as well as - TT_CONFIG_OPTION_BYTECODE_INTERPRETER, is not #undef-ed anymore. - This allows the build system to define them depending on the - configuration (typically by adding -D flags at compile time). - - * src/sfnt/ttcmap0.c (tt_face_build_cmaps): Removed compiler - warnings in optimized mode relative to the `volatile' local - variables. This was not a compiler bug after all, but the fact that - a pointer to a volatile variable is not the same as a volatile - pointer to a variable :-) - - The fix was to change - `volatile FT_Byte* p' - into - `FT_Byte* volatile p'. - - * src/pfr/pfrload.c (pfr_phy_font_load), src/pfr/pfrdrivr.c - (pfr_get_metrics), src/gzip/inftrees.c: Removed compiler warnings in - optimized modes. - - * src/gzip/*.[hc]: Modified our zlib copy in order to prevent - exporting any zlib function names outside of the component. This - prevents linking problems on some platforms, when applications want - to link FreeType _and_ zlib together. - -2002-11-05 Juliusz - - * src/psaux/psobjs.c (ps_table_add): Modified increment loop in - order to implement exponential behaviour. - -2002-11-01 David Turner - - Added PFR-specific public API. Fixed the kerning retrieval routine - (it returned invalid values when the outline and metrics resolution - differ). - - * include/freetype/ftpfr.h, include/freetype/internal/pfr.h: New - files. - - * include/freetype/internal/internal.h (FT_INTERNAL_PFR_H): New - macro for pfr.h. - - * src/base/ftpfr.c: New file. - * src/base/Jamfile, src/base/descrip.mms: Updated. - - * src/pfr/pfrdrivr.c: Include FT_INTERNAL_PFR_H. - (pfr_get_kerning, pfr_get_advance, pfr_get_metrics): New functions. - (pfr_service_rec): New format interface. - (pfr_driver_class): Use `pfr_service_rec'. - Replace `pfr_face_get_kerning' with `pfr_get_kerning'. - * src/pfr/pfrobjs.c: Remove dead code. - - * src/base/ftobjs.c (ft_glyphslot_clear): Small internal fix to - better support bitmap-based font formats. - - * src/base/ftsynth.c (FT_GlyphSlot_Embolden): Fix handling of - `scale'. - Fix arguments to `FT_Vector_From_Polar'. - -2002-10-31 David Turner - - Add support for automatic handling of gzip-compressed PCF files. - - * src/gzip/*: New files, taken from the zlib package (except - ftgzip.c). - - * include/freetype/ftgzip.h, src/gzip/ftgzip.c: New files. - * include/freetype/config/ftheader.h (FT_GZIP_H): New macro for - `ftgzip.h'. - - * src/pcf/pcfdriver.c: Include FT_GZIP_H and FT_ERRORS_H. - (PCF_Face_Init): If normal open fails, try to open gzip stream. - (PCF_Face_Done): Close gzip stream. - - * include/freetype/internal/pcftypes.h (PCF_Public_FaceRec), - src/pcf/pcf.h (PCF_FaceRec): Add `gzip_stream' and `gzip_source'. - - * include/freetype/config/ftoption.h (FT_CONFIG_OPTION_USE_ZLIB): - New macro. - (T1_CONFIG_OPTION_DISABLE_HINTER, FT_CONFIG_OPTION_USE_CMAPS - FT_CONFIG_OPTION_NO_CONVENIENCE_FUNCS, - FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS): Removed. - - (FT_EXPORT, FT_EXPORT_DEF, FT_DEBUG_LEVEL_ERROR, - FT_DEBUG_LEVEL_TRACE, FT_DEBUG_MEMORY): Comment out definitions so - that platform specific configuration file can override. - - * include/freetype/internal/ftstream.h: Include FT_SYSTEM_H. - -2002-10-30 David Turner - - * FreeType 2.1.3rc3 released. - -2002-10-25 David Turner - - * include/freetype/ftcache.h (FT_POINTER_TO_ULONG): New macro. - (FTC_FACE_ID_HASH): Rewritten, using FT_POINTER_TO_ULONG. - -2002-10-22 Giuseppe Ghibò - - * include/freetype/freetype.h (FT_Encoding): Fix entry for latin-2. - -2002-10-07 Werner Lemberg - - * include/freetype/freetype.h (FT_Open_Face): Use `const' for `args' - (suggested by Graham). - * src/base/ftobjs.c (FT_Open_Face): Updated. - (ft_input_stream_new): Ditto. - -2002-10-05 David Turner - - Adding support for embedded bitmaps to the PFR driver, and rewriting - its kerning loader/handler to use all kerning pairs in a physical - font (and not just the first item). - - * src/pfr/pfr.c: Include `pfrsbit.c'. - * src/pfr/pfrgload.c: Include `pfrsbit.h'. - * src/pfr/pfrload.c (pfr_extra_item_load_kerning_pairs): Rewritten. - (pfr_phy_font_done, pfr_phy_font_load): Updated. - * src/pfr/pfrobjs.c: Include `pfrsbit.h'. - (pfr_face_init): Handle kerning and embedded bitmaps. - (pfr_slot_load): Load embedded bitmaps. - (PFR_KERN_INDEX): Removed. - (pfr_face_get_kerning): Rewritten. - * src/pfr/pfrsbit.c, src/pfr/pfrsbit.h: New files. - * src/pfr/pfrtypes.h (PFR_KernItemRec): New structure. - (PFR_KERN_INDEX): New macro. - (PFR_PhyFontRec): Add items for kerning and embedded bitmaps. - * src/pfr/Jamfile (_sources) [FT2_MULTI]: Add `pfrsbit'. - - * src/base/ftobjs.c (FT_Load_Glyph): Don't load bitmap fonts if - FT_LOAD_NO_RECURSE is set. - Load embedded bitmaps only if FT_LOAD_NO_BITMAP isn't set. - - * src/tools/docmaker/content.py, src/tools/docmaker/sources.py, - src/tools/docmaker/tohtml.py: Fixing a few nasty bugs. - - * src/sfnt/ttcmap0.c (tt_cmap4_validate): The validator for format 4 - sub-tables is now capable of dealing with invalid `length' fields at - the start of the sub-table. This allows fonts like `mg______.ttf' - (i.e. Marriage) to return accurate charmaps. - - * docs/CHANGES: Updated. - -2002-10-05 Werner Lemberg - - * src/smooth/ftgrays.c (SUBPIXELS): Add cast to `TPos'. - Update all callers. - (TRUNC): Add cast to `TCoord'. - Update all callers. - (TRaster): Use `TPos' for min_ex, max_ex, min_ey, max_ey, and - last_ey. - Update all casts. - (gray_render_line): Fix casts for `p' and `first'. - -2002-10-02 Detlef Würkner - - * src/bdf/bdflib.c (bdf_load_font): Allocate the _bdf_parse_t - structure with FT_ALLOC instead of using the stack. - -2002-09-27 Werner Lemberg - - * src/include/freetype/internal/tttypes.h (num_sbit_strikes, - num_sbit_scales): Use `FT_ULong'. - * src/sfnt/sfobjs.c (sfnt_load_face): Updated accordingly. - * src/sfnt/ttsbit.c (tt_face_set_sbit_strike): Ditto. - (find_sbit_image): Remove cast. - * src/raster/ftrend1.c (ft_raster1_render): Fix cast. - -2002-09-27 Wolfgang Domröse - - * src/sfnt/ttload.c (tt_face_load_names): Use cast. - * src/sfnt/ttcmap.c (code_to_next2): Use long constant. - (code_to_index4): Use cast. - (code_to_index8_12): Fix cast. - * src/sfnt/ttcmap0.c (tt_cmap4_char_next, tt_cmap8_char_index, - tt_cmap12_char_index): Use cast for `result'. - (tt_face_build_cmaps): Use cast. - * src/sfnt/sfobjs.c (tt_name_entry_ascii_from_ucs4): Use cast for - `code'. - (sfnt_load_face): Use FT_Int32 for `flags'. - - * src/smooth/ftgrays.c (gray_render_scanline, gray_render_line, - gray_compute_cbox, gray_convert_glyph, gray_raster_reset): Add casts - to `TCoord' and `int'. - More 16bit fixes. - s/FT_Pos/TPos/. - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Add casts. - -2002-09-26 Werner Lemberg - - * src/sfnt/ttpost.c (load_post_names, tt_face_free_ps_names, - tt_face_get_ps_name): Replace switch statement with if clauses to - make it more portable. - - * src/cff/cffobjs.c (cff_face_init): Ditto. - - * include/freetype/ftmodule.h (FT_Module_Class): Use `FT_Long' for - `module_size'. - * include/freetype/ftrender.h (FT_Glyph_Class_): Use `FT_Long' for - `glyph_size'. - - * src/base/ftobjs.c (FT_Render_Glyph): Change second parameter to - `FT_Render_Mode'. - (FT_Render_Glyph_Internal): Change third parameter to - `FT_Render_Mode'. - * src/base/ftglyph.c (FT_Glyph_To_Bitmap): Change second parameter - to `FT_Render_Mode'. - - * src/raster/ftrend1.c (ft_raster1_render): Change third parameter - to `FT_Render_Mode'. - * src/smooth/ftsmooth.c (ft_smooth_render, ft_smooth_render_lcd, - ft_smooth_render_lcd_v): Ditto. - (ft_smooth_render_generic): Change third and fifth parameter to - `FT_Render_Mode'. - - * include/freetype/freetype.h, include/freetype/internal/ftobjs.h, - include/freetype/ftglyph.h: Updated. - - * src/cff/cffdrivr.c (Load_Glyph), src/pcf/pcfdriver.c - (PCF_Glyph_Load), src/pfr/pfrobjs.c (pfr_slot_load), - src/winfonts/winfnt.c (FNT_Load_Glyph), src/t42/t42objs.c - (T42_GlyphSlot_Load), src/bdf/bdfdrivr.c (BDF_Glyph_Load): Change - fourth parameter to `FT_Int32'. - - * src/pfr/pfrobjs.c (pfr_face_init): Add two missing parameters - and declare them as unused. - - * src/cid/cidparse.h (CID_Parser): Use FT_Long for `postscript_len'. - - * src/psnames/psnames.h (PS_Unicode_Value_Func): Change return - value to FT_UInt32. - * src/psnames/psmodule.c (ps_unicode_value, ps_build_unicode_table): - Updated accordingly. - -2002-09-26 Wolfgang Domröse - - * src/cff/cffdrivr.c (Get_Kerning): Use FT_Long for `middle'. - (cff_get_glyph_name): Use cast for result of ft_strlen. - * src/cff/cffparse.c (cff_parse_real): User cast for assigning - `exp'. - * src/cff/cffload.c (cff_index_get_pointers): Use FT_ULong for - some local variables. - (cff_charset_load, cff_encoding_load): Use casts to FT_UInt for some - switch statements. - (cff_font_load): Use cast in call to CFF_Load_FD_Select. - * src/cff/cffobjs.c (cff_size_init): Use more casts. - (cff_face_init): Use FT_Int32 for `flags'. - * src/cff/cffgload.c (cff_operator_seac): Use cast for assigning - `adx' and `ady'. - (cff_decoder_parse_charstrings): Use FT_ULong for third parameter. - Use more casts. - * src/cff/cffcmap.c (cff_cmap_unicode_init): Use cast for `count'. - - * src/cid/cidload.c (cid_read_subrs): Use FT_ULong for `len'. - * src/cid/cidgload.c (cid_load_glyph): Add missing cast for - `cid_get_offset'. - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings) <18>: Use - cast for `num_points'. - (t1_decoder_init): Use cast for assigning `decoder->num_glyphs'. - - * src/base/ftdebug.c (ft_debug_init): Use FT_Int. - * include/freetype/internal/ftdriver.h (FT_Slot_LoadFunc): Use - `FT_Int32' for fourth parameter. - * src/base/ftobjs.c (open_face): Use cast for calling - clazz->init_face. - - * src/raster/ftraster.c (Set_High_Precision): Use `1' instead of - `1L'. - (Finalize_Profile_Table, Line_Up, ft_black_init): Use casts. - * src/raster/ftrend1.c (ft_raster1_render): Ditto. - - * src/sfnt/sfnt_dir_check: Compare `magic' with unsigned long - constant. - -2002-09-26 Detlef Würkner - - * builds/amiga/include/freetype/config/ftmodule.h: Updated. - -2002-09-25 David Turner - - * src/autohint/ahtypes.h (AH_HINT_METRICS): Disabling metrics - hinting in the auto-hinter. This produces much better anti-aliased - text. - - * docs/CHANGES: Updating the changes documentation. - -2002-09-25 Anthony Fok - - * src/sfnt/ttcmap0.c (tt_cmap4_validate, tt_cmap4_char_index, - tt_cmap4_char_next): Added support for opens___.ttf (it contains a - charmap that uses offset=0xFFFFU instead of 0x0000 to indicate a - missing glyph). - -2002-09-21 Wolfgang Domröse - - * src/truetype/ttdriver.c (Load_Glyph): Fourth parameter must be - FT_Int32. - * src/truetype/ttgload.c, src/truetype/ttgload.h (TT_Load_Glyph): - Ditto. - -2002-09-19 Wolfgang Domröse - - More 16bit fixes. - - * src/autohint/ahglobal.c (sort_values): Use FT_Pos for `swap'. - (ah_hinter_compute_widths): Use FT_Pos for `dist'. - Use AH_MAX_WIDTHS. - * src/autohint/ahglyph.c (ah_outline_scale_blue_edges): Use FT_Pos - for `delta'. - (ah_outline_compute_edges): Replace some ints with FT_Int and - FT_Pos. - (ah_test_extrema): Clean up code. - (ah_get_orientation): Use 4 FT_Int variables instead of FT_BBox to - hold indices. - * src/autohint/ahtypes.h (AH_SegmentRec): Change type of `score' - to FT_Pos. - -2002-09-19 Werner Lemberg - - * builds/unix/config.guess, builds/unix/config.sub: Updated to - recent versions. - -2002-09-18 David Turner - - * src/base/ftobjs.c (FT_Library_Version): Bugfix. - - * FreeType 2.1.3rc2 (release candidate 2) is released! - -2002-09-17 David Turner - - * include/freetype/freetype.h, include/freetype/ftimage.h, - include/freetype/ftstroker.h, include/freetype/ftsysio.h, - include/freetype/ftsysmem.h, include/freetype/ttnameid.h: Updating - the in-source documentation. - - * src/tools/docmaker/tohtml.py: Updating the HTML formatter in the - DocMaker tool. - - * src/tools/docmaker.py: Removed. - -2002-09-17 Werner Lemberg - - More 16bit fixes. - - * src/psaux/psobjs.c (reallocate_t1_table): Use FT_Long for - second parameter. - -2002-09-16 Werner Lemberg - - 16bit fixes from Wolfgang Domröse. - - * src/type1/t1parse.h (T1_ParserRec): Change type of `base_len' - and `private_len' to FT_Long. - * src/type1/t1parse.c (T1_Get_Private_Dict): Remove cast for - `private_len'. - * src/type1/t1load.c: Use FT_Int cast for most calls of T1_ToInt. - Use FT_PtrDist where appropriate. - (parse_encoding): Use FT_Long for `count' and `n'. - (read_binary_data): Use FT_Long* for second parameter. - * src/type1/t1afm.c (afm_atoindex): Use FT_PtrDist. - - * src/cache/ftcsbits.c (ftc_sbit_node_load): Remove unused label. - * src/pshinter/pshalgo3.c (psh3_hint_align): Remove unused variable. - -2002-09-14 Werner Lemberg - - Making ftgrays.c compile stand-alone again. - - * include/freetype/ftimage.h: Include ft2build.h only if _STANDALONE_ - isn't defined. - * src/smooth/ftgrays.c [_STANDALONE_]: Define ft_memset, - FT_BEGIN_HEADER, FT_END_HEADER. - (FT_MEM_ZERO): Define. - (TRaster) [GRAYS_USE_GAMMA]: Use `unsigned char' instead of FT_Byte. - (gray_render_span, gray_init_gamma): Don't use `FT_UInt'. - Don't cast with `FT_Byte'. - (grays_init_gamma): Don't use `FT_UInt'. - -2002-09-14 Werner Lemberg - - * src/base/ftinit.c (FT_Add_Default_Modules): Improve error message. - * src/pcf/pcfdriver.c (PCF_Face_Done): Improve tracing message. - * include/freetype/config/ftoption.h (FT_MAX_MODULES): Increased - to 32. - -2002-09-10 Werner Lemberg - - * builds/unix/configure.ac (version_info): Set to 9:2:3. - * builds/unix/configure: Regenerated. - * docs/VERSION.DLL: Updated. - -2002-09-09 David Turner - - * src/pshinter/pshalgo2.c (psh2_glyph_find_strong_points), - src/pshinter/pshalgo3.c (psh3_glyph_find_strong_points): Adding fix - to prevent segfault when hints are provided in an empty glyph. - - * src/cache/ftccache.i (GEN_CACHE_LOOKUP) [FT_DEBUG_LEVEL_ERROR]: - Removed conditional code. This fixes a bug that prevented - compilation in debug mode of template instantiation. - - * include/freetype/ftimage.h: Removed incorrect `zft_' definitions - and updated constants documentation comments. - - * src/cff/cffparse.c (cff_parser_run): Fixed the CFF table loader. - It didn't accept empty arrays, and this prevented the loading of - certain fonts. - - * include/freetype/freetype.h (FT_FaceRec): Updating documentation - comment. The `descender' value is always *negative*, not positive. - -2002-09-09 Owen Taylor - - * src/pcf/pcfdriver.c (PCF_Glyph_Load): Fixing incorrect computation - of bitmap metrics. - -2002-09-08 David Turner - - Various updates to correctly support subpixel rendering. - - * include/freetype/config/ftmodule.h: Add two renderers for LCD. - - * src/base/ftobjs.c (FT_Load_Glyph): Updated. - - * src/smooth/ftsmooth.c (ft_smooth_render_lcd, - ft_smooth_render_lcd_v): Set FT_PIXEL_MODE_LCD and - FT_PIXEL_MODE_LCD_V, respectively. - - * include/freetype/cache/ftcimage.h (FTC_ImageTypeRec): New - structure. - Updated all users. - (FTC_ImageDesc): Removed. - (FTC_ImageCache_Lookup): Second parameter is now of type - `FTC_ImageType'. - Updated all users. - (FTC_IMAGE_DESC_COMPARE): Updated and renamed to... - (FTC_IMAGE_TYPE_COMPARE): This. - (FTC_IMAGE_DESC_HASH): Updated and renamed to... - (FTC_IMAGE_TYPE_HASH): This. - - * include/freetype/cache/ftcsbits.h (FTC_SBitRec): Field `num_grays' - replaced with `max_grays'. - `pitch' is now FT_Short. - (FTC_SBitCache_Lookup): Second parameter is now of type - `FTC_ImageType'. - Updated all users. - - * src/cache/ftcimage.c (FTC_ImageQueryRec, FTC_ImageFamilyRec): - Updated. - (ftc_image_node_init): Updated. - Moved code to convert type flags to load flags to... - (FTC_Image_Cache_Lookup): This function. - (ftc_image_family_init): Updated. - - * src/cache/ftcsbits.c (FTC_SBitQueryRec, FTC_SBitFamilyRec): - Updated. - (ftc_sbit_node_load): Updated. - Moved code to convert type flags to load flags to... - (FTC_SBitCache_Lookup): This function. - - * src/autohint/ahtypes.h (AH_HinterRec): Replace `no_*_hints' with - `do_*_snapping'. - Update all users (with negation). - * src/autohint/ahhint.c (ah_compute_stem_width): Fix threshold for - `dist' for `delta' < 40. - - * src/pshinter/pshalgo3.h (PSH3_GlyphRec): Replace `no_*_hints' with - `do_*_snapping'. - Update all users (with negation). - * src/pshinter/pshalgo3.c (psh3_dimension_quantize_len): New - function. - (psh3_hint_align): Use it. - Improve hinting code. - [STRONGER]: Removed. - (STRONGER): Removed. - - * include/freetype/freetype.h (FT_Set_Hint_Flags, FT_HINT_*): - Removed. - -2002-09-05 Werner Lemberg - - * src/cid/cidobjs.c (CID_Size_Init): Renamed to... - (cid_size_init): This. - * src/psaux/psobjs.c (T1_Builder_Add_Point1): Renamed to... - (t1_builder_add_point1): This. - - Updated all affected code. - - * src/pshinter/pshalgo3.c (psh3_hint_align): Fix compiler warnings. - * src/type1/t1gload.c (T1_Compute_Max_Advance): Ditto. - -2002-09-04 David Turner - - * include/freetype/freetype.h: Corrected the definition of - ft_encoding_symbol to be FT_ENCODING_MS_SYMBOL (instead of - the erroneous FT_ENCODING_SYMBOL). - - * builds/unix/unix-def.in (datadir): Initialize it (thanks to - Anthony Fok). - -2002-08-29 David Turner - - Slight modification to the Postscript hinter to slightly increase - the contrast of smooth hinting. This is very similar to what the - auto-hinter does when it comes to stem width computations. However, - it produces better results with well-hinted fonts. - - * include/freetype/internal/psaux.h (T1_Decoder_FuncsRec): Add hint - mode to `init' member function. - (T1_DecoderRec): Add hint mode. - * include/freetype/internal/pshints (T1_Hints_ApplyFunc, - T2_Hints_ApplyFunc): Pass `hint_mode', not `hint_flags'. - * src/psaux/t1decode.c (t1_decoder_init): Add hint mode argument. - * src/pshinter/pshalgo1.c (ps1_hints_apply): Pass hint mode, not - hint flags. - * src/pshinter/pshalgo2.c (ps2_hints_apply): Ditto. - * src/pshinter/pshalgo3.c (ps3_hints_apply): Ditto. - (STRONGER): New macro. - (psh3_hint_align, psh3_hint_table_align_hints): Pass `glyph' instead - of `hint_flags'. - Implement announced changes. - * src/pshinter/pshalgo3.h (PSH3_GlyphRec): Add flags to control - vertical and horizontal hints and snapping. - - * README, docs/CHANGES: Updating for the 2.1.3 release. - -2002-08-27 David Turner - - * Massive re-formatting changes to many, many source files. I don't - want to list them all here. The operations performed were all - logical transformations of the sources: - - - trying to convert all enums and constants to CAPITALIZED_STYLE, - #with define definitions like - - #define my_old_constants MY_NEW_CONSTANT - - - big, big update of the documentation comments - - * include/freetype/freetype.h, src/base/ftobjs.c, - src/smooth/ftsmooth.c, include/freetype/ftimage.h: Adding support - for LCD-optimized rendering though the new constants/enums: - - FT_RENDER_MODE_LCD, FT_RENDER_MODE_LCD_V - FT_PIXEL_MODE_LCD, FT_PIXEL_MODE_LCD_V - - This is still work in progress, don't expect everything to work - correctly though most of the features have been implemented. - - * Adding new FT_LOAD_XXX flags, used to specify both hinting and - rendering targets: - - FT_LOAD_TARGET_NORMAL :: anti-aliased hinting & rendering - FT_LOAD_TARGET_MONO :: monochrome bitmaps - FT_LOAD_TARGET_LCD :: horizontal RGB/BGR decimated - hinting & rendering - FT_LOAD_TARGET_LCD_V :: vertical RGB/BGR decimated - hinting & rendering - - Note that FT_LOAD_TARGET_NORMAL is 0, which means that the default - behaviour of the font engine is _unchanged_. - - * include/freetype/ftimage.h - (FT_Outline_{Move,Line,Conic,Cubic}To_Func): Renamed to... - (FT_Outline_{Move,Line,Conic,Cubic}ToFunc): This. - (FT_Raster_Span_Func): Renamed to ... - (FT_SpanFunc): This. - (FT_Raster_{New,Done,Reset,Set_Mode,Render}_Func): Renamed to ... - (FT_Raster_{New,Done,Reset,SetMode,Render}Func}: This. - - Updated all affected code. - - * include/freetype/ftrender.h - (FT_Glyph_{Init,Done,Transform,BBox,Copy,Prepare}_Func): Renamed - to ... - (FT_Glyph_{Init,Done,Transform,GetBBox,Copy,Prepare}Func): This. - (FTRenderer_{render,transform,getCBox,setMode}): Renamed to ... - (FT_Renderer_{RenderFunc,TransformFunc,GetCBoxFunc,SetModeFunc}): - This. - - Updated all affected code. - - * src/autohint/ahtypes.h (AH_Point, AH_Segment, AH_Edge, AH_Globals, - AH_Face_Globals, AH_Outline, AH_Hinter): These typedefs are now - pointers to the corresponding `*Rec' structures. All source files - have been updated accordingly. - - * src/cff/cffgload.c (cff_decoder_init): Add hint mode as parameter. - * src/cff/cffgload.h (CFF_Decoder): Add `hint_mode' element. - - * src/cid/cidgload.c (CID_Compute_Max_Advance): Renamed to... - (cid_face_compute_max_advance): This. - (CID_Load_Glyph): Renamed to... - (cid_slot_load_glyph): This. - * src/cid/cidload.c (CID_Open_Face): Renamed to... - (cid_face_open): This. - * src/cid/cidobjs.c (CID_GlyphSlot_{Done,Init}): Renamed to... - (cid_slot_{done,init}): This. - (CID_Size_{Get_Globals_Funcs,Done,Reset): Renamed to... - (cid_size_{get_globals_funcs,done,reset): This. - (CID_Face_{Done,Init}): Renamed to... - (cid_face_{done,init}): This. - (CID_Driver_{Done,Init}: Renamed to... - (cid_driver_{done,init}: This. - * src/cid/cidparse.c (CID_{New,Done}_Parser): Renamed to... - (cid_parser_{new,done}): This. - * src/cid/cidparse.h (CID_Skip_{Spaces,Alpha}): Renamed to... - (cid_parser_skip_{spaces,alpha}): This. - (CID_To{Int,Fixed,CoordArray,FixedArray,Token,TokenArray}): Renamed - to... - (cid_parser_to_{int,fixed,coord_array,fixed_array,token,token_array}): - This. - (CID_Load_{Field,Field_Table): Renamed to... - (cid_parser_load_{field,field_table}): This. - * src/cid/cidriver.c (CID_Get_Interface): Renamed to... - (cid_get_interface): This. - - Updated all affected code. - - * src/psaux/psobjs.c (PS_Table_*): Renamed to... - (ps_table_*): This. - (T1_Builder_*): Renamed to... - (t1_builder_*): This. - * src/psaux/t1decode.c (T1_Decoder_*): Renamed to... - (t1_decoder_*): This. - - * src/psnames/psmodule.c (PS_*): Renamed to... - (ps_*): This. - - Updated all affected code. - - * src/sfnt/sfdriver (SFNT_Get_Interface): Renamed to... - (sfnt_get_interface): This. - * src/sfnt/sfobjs.c (SFNT_*): Renamed to... - (sfnt_*): This. - * src/sfnt/ttcmap.c (TT_CharMap_{Load,Free}): Renamed to... - (tt_face_{load,free}_charmap): This. - * src/sfnt/ttcmap0.c (TT_Build_CMaps): Renamed to... - (tt_face_build_cmaps): This. - * src/sfnt/ttload.c (TT_*): Renamed to... - (tt_face_*): This. - * src/sfnt/ttpost.c (TT_Post_Default_Names): Renamed to... - (tt_post_default_names): This. - (Load_*): Renamed to... - (load_*): This. - (TT_*): Renamed to... - (tt_face_*): This. - * src/sfnt/ttsbit.c (TT_*): Renamed to... - (tt_face_*): This. - ({Find,Load,Crop}_*): Renamed to... - ({find,load,crop}_*): This. - - Updated all affected code. - - * src/smooth/ftsmooth.c (ft_smooth_render): Renamed to... - (ft_smooth_render_generic): This. - Make function more generic by adding vertical and horizontal scaling - factors. - (ft_smooth_render, ft_smooth_render_lcd, ft_smooth_render_lcd_v): - New functions. - - (ft_smooth_lcd_renderer_class, ft_smooth_lcdv_renderer_class): New - classes. - - * src/truetype/ttobjs.c (TT_{Done,New}_GlyphZone): Renamed to... - (tt_glyphzone_{done,new}): This. - (TT_{Face,Size,Driver}_*): Renamed to... - (tt_{face,size,driver}_*): This. - * src/truetype/ttpload.c (TT_Load_Locations): Renamed to... - (tt_face_load_loca): This. - (TT_Load_Programs): Renamed to... - (tt_face_load_fpgm): This. - (TT_*): Renamed to... - (tt_face_*): This. - -2002-08-27 Werner Lemberg - - * docs/VERSION.DLL: New file. - -2002-08-23 Graham Asher - - * src/cff/cffgload.c (cff_operator_seac) - [FT_CONFIG_OPTION_INCREMENTAL]: Incremental fonts (actually not - incremental in the case of CFF but just using callbacks to get glyph - recipes) pass the character code, not the glyph index, to the - get_glyph_data function; they have no valid charset table. - - * src/cff/cffload.c (cff_font_load): Removed special cases for - FT_CONFIG_OPTION_INCREMENTAL, which are no longer necessary; CFF - fonts provided via the incremental interface now have to conform - more closely to the CFF font format. - - * src/cff/cffload.h (cff_font_load): Removed argument now unneeded. - - * src/cff/cffobjs.c (cff_face_init): Changed call to cff_font_load - to conform with new signature. - -2002-08-22 David Turner - - * src/base/ftobject.c, src/base/ftsynth.c, src/base/ftstroker.c, - src/bdf/bdfdrivr.c: Removed compiler warnings. - -2002-08-21 Werner Lemberg - - * src/pshinter/pshalgo3.c (psh3_glyph_compute_inflections, - psh3_glyph_compute_extrema, psh3_hint_table_find_strong_point): Fix - compiler warnings and resolve shadowing of local variables. - -2002-08-21 David Turner - - The automatic and Postscript hinter now automatically detect - inflection points in glyph outlines and treats them specially. This - is very useful to prevent nasty effect like the disappearing - diagonals of `S' and `s' in many, many fonts. - - * src/autohint/ahtypes.h (ah_flag_inflection): New macro. - * src/autohint/ahangles.c (ah_angle_diff): New function. - * src/autohint/ahangles.h: Updated. - * src/autohint/ahglyph.c (ah_outline_compute_inflections): New - function. - (ah_outline_detect_features): Use it. - * src/autohint/ahhint.c (ah_hinter_align_strong_points) - [!AH_OPTION_NO_WEAK_INTERPOLATION]: Handle inflection. - - * src/tools/docmaker/docmaker.py, src/tools/docmaker/utils.py, - src/tools/docmaker/tohtml.py: Updating the DocMaker tool. - - * include/freetype/freetype.h: Changing the type of the `load_flags' - parameter from `FT_Int' to `FT_Int32', this in order to support more - options. This should only break binary and/or source compatibility - on 16-bit platforms (Atari?). - (FT_LOAD_NO_AUTOHINT): New macro. - - * src/base/ftobjs.c (FT_Load_Glyph): Updated. - Handle FT_LOAD_NO_AUTOHINT. - (FT_Load_Char): Updated. - - * src/pshinter/pshalgo3.c, src/base/ftobjs.c, src/base/ftobject.c, - src/autohint/ahglyph.c, include/freetype/freetype.h: Fixing typos - and removing compiler warnings. - -2002-08-20 Werner Lemberg - - * src/truetype/ttgload.c (TT_Get_Metrics): Add guard for k = 0. - -2002-08-20 David Turner - - * src/pshinter/pshalgo1.c, src/pshinter/pshalgo2.c, - src/pshinter/pshglob.c, src/pshinter/pshrec.c, - src/autohint/ahmodule.c [DEBUG_HINTER]: Removing compiler warnings - (only used in development builds anyway). - - Improve support of local extrema and stem edge points. - - * src/pshinter/pshalgo3.h (PSH3_Hint_TableRec): Use PSH3_ZoneRec - for `zones'. - (PSH3_DIR_UP, PSH3_DIR_DOWN): Exchange values. - (PSH3_DIR_HORIZONTAL, PSH3_DIR_VERTICAL): New macros. - (PSH3_DIR_COMPARE, PSH3_DIR_IS_HORIZONTAL, PSH3_IS_VERTICAL): New - macros. - (PSH3_POINT_INFLEX): New enum. - (psh3_point_{is,set}_{off,inflex}): New macros. - (PSH3_POINT_{EXTREMUM,POSITIVE,NEGATIVE,EDGE_MIN,EDGE_MAX): New - enum values. - (psh3_point_{is,set}_{extremum,positive,negative,edge_min,edge_max}): - New macros. - (PSH3_PointRec): New members `flags2' and `org_v'. - (PSH3_POINT_EQUAL_ARG, PSH3_POINT_ANGLE): New macros. - - * src/pshinter/pshalgo3.c [DEBUG_HINTER]: Removing compiler - warnings. - (COMPUTE_INFLEXS): New macro. - (psh3_hint_align): Simplify some basic arithmetic computations. - (psh3_point_is_extremum): Removed. - (psh3_glyph_compute_inflections) [COMPUTE_INFLEXS]: New function. - (psh3_glyph_init) [COMPUTE_INFLEXS]: Use it. - (psh3_glyph_compute_extrema): New function. - (PSH3_STRONG_THRESHOLD): Increased to 30. - (psh3_hint_table_find_strong_point): Improved. - (psh3_glyph_find_strong_points, - psh3_glyph_interpolate_strong_points): Updated. - (psh3_hints_apply): Use psh3_glyph_compute_extrema. - - * test/gview.c (draw_ps3_hint, ps3_draw_control_points): New - functions. - Other small updates. - - * Jamfile: Small updates. - -2002-08-18 Arkadiusz Miskiewicz - - * builds/unix/install.mk (install, uninstall): Add $(DESTDIR) to - make life easier for package maintainers. - -2002-08-18 Werner Lemberg - - * src/pcf/pcfdriver.c (PCF_Glyph_Load): Fix computation of - horiBearingX. - * src/bdf/bdfdrivr.c (BDF_Glyph_Load): Fix computation of - horiBearingY. - -2002-08-16 George Williams - - Add support for Apple composite glyphs. - - * include/freetype/config/ftoption.h - (TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED): New macro. - - * src/truetype/ttgload.c (OVERLAP_COMPOUND, SCALED_COMPONENT_OFFSET, - UNSCALED_COMPONENT_OFFSET): New macros for additional OpenType - glyph loading flags. - (load_truetype_glyph): Implement it. - -2002-08-16 Werner Lemberg - - * src/cff/cffgload.c (cff_free_glyph_data), - src/cff/cffload.c (cff_font_load): Use FT_UNUSED. - -2002-08-15 Werner Lemberg - - * src/base/ftglyph.c (FT_Glyph_To_Bitmap): Initialize `error'. - * src/sfnt/sfobjs.c (SFNT_Load_Face): Fix compiler warning. - -2002-08-15 Graham Asher - - Implemented the incremental font loading system for the CFF driver. - Tested using the GhostScript-to-FreeType bridge (under development). - - * src/cff/cffgload.c (cff_get_glyph_data, cff_free_glyph_data): New - functions. - (cff_operator_seac, cff_compute_max_advance, cff_slot_load): Use - them. - * src/cff/cffload.c (cff_font_load): Add `face' parameter. - Load charset and encoding only if there are glyphs. - [FT_CONFIG_OPTION_INCREMENTAL]: Incremental fonts don't need - character recipes. - * src/cff/cffload.h, src/cff/cffobjs.c: Updated. - - * src/cid/cidgload.c (cid_load_glyph) - [FT_CONFIG_OPTION_INCREMENTAL]: Corrected the incremental font - loading implementation to use the new system introduced on - 2002-08-01. - -2002-08-06 Werner Lemberg - - * src/cff/cffcmap.c: Remove compiler warnings. - * src/cache/ftccache.c, src/cache/ftccache.i, - src/pfr/pfrload.c, src/pfr/pfrgload.c: s/index/idx/. - * src/cff/cffload.c: s/select/fdselect/. - * src/raster/ftraster.c: s/wait/waiting/. - -2002-08-01 Graham Asher - - * src/type1/t1load.c (T1_Open_Face): Tolerate a face with no - charstrings if there is an incremental loading interface. Type 1 - faces supplied by PostScript interpreters like GhostScript will - typically not provide any charstrings at load time, so this is - essential if they are to work. - -2002-08-01 Graham Asher - - Modified incremental loading interface to be closer to David's - preferences. The header freetype.h is not now affected, the - interface is specified via an FT_Parameter, the pointer to the - interface is hidden in an internal part of the face record, and all - the definitions are in ftincrem.h. - - * include/freetype/freetype.h [FT_CONFIG_OPTION_INCREMENTAL]: - Removed. - * include/freetype/internal/ftobjs.h [FT_CONFIG_OPTION_INCREMENTAL]: - Include FT_INCREMENTAL_H. - (FT_Face_InternalRec) [FT_CONFIG_OPTION_INCREMENTAL]: Add - `incremental_interface'. - - * src/base/ftobjs.c (open_face, FT_Open_Face) - [FT_CONFIG_OPTION_INCREMENTAL]: Updated. - * src/sfnt/sfobjs.c (SFNT_Load_Face) [FT_CONFIG_OPTION_INCREMENTAL]: - Updated. - - * src/truetype/ttgload.c (load_truetype_glyph) - [FT_CONFIG_OPTION_INCREMENTAL]: Updated. - Free loaded glyph data properly. - (compute_glyph_metrics, TT_Load_Glyph) - [FT_CONFIG_OPTION_INCREMENTAL]: Updated. - * src/truetype/ttobjs.c (TT_Face_Init) - [FT_CONFIG_OPTION_INCREMENTAL]: Updated. - - * src/type1/t1gload.c (T1_Parse_Glyph_And_Get_Char_String) - [FT_CONFIG_OPTION_INCREMENTAL]: Updated. - (T1_Parse_Glyph) [FT_CONFIG_OPTION_INCREMENTAL]: Updated. - Free loaded glyph data properly. - (T1_Load_Glyph): Updated. - [FT_CONFIG_OPTION_INCREMENTAL]: Free loaded glyph data properly. - -2002-07-30 David Turner - - * include/freetype/ftincrem.h: Adding new experimental header file - to demonstrate a `cleaner' API to support incremental font loading. - - * include/freetype/config/ftheader.h (FT_INCREMENTAL_H): New macro. - - * src/tools/docmaker/*: Adding new (more advanced) version of - the DocMaker tool, using Python's sophisticated regexps. - -2002-07-28 Werner Lemberg - - s/ft_memset/FT_MEM_SET/. - s/FT_MEM_SET/FT_MEM_ZERO/ where appropriate. - -2002-07-27 Werner Lemberg - - * src/sfnt/ttload.c (sfnt_dir_check): Make it work with TTCs. - -2002-07-26 Werner Lemberg - - * src/truetype/ttgload.c (load_truetype_glyph) - [FT_CONFIG_OPTION_INCREMENTAL]: s/memset/ft_memset/. - - * src/autohint/ahhint.c (ah_hint_edges_3): Fix compiler warning. - * src/cff/cffload.c (cff_encoding_load): Remove `memory' variable. - * src/cff/cffcmap.c (cff_cmap_encoding_init): Remove `psnames' - variable. - * src/truetype/ttgload.c (load_truetype_glyph): Remove statement - without effect. - * src/truetype/ttdriver (Get_Char_Index, Get_Next_Char): Removed. - - * src/pshinter/pshalgo3.c (psh3_hint_table_record, - psh3_hint_table_init, psh3_hint_table_activate_mask): Fix error - message. - -2002-07-24 Graham Asher - - * src/truetype/ttobjs.c: Fix for bug reported by Sven Neumann - [sven@gimp.org] on the FreeType development forum: `If - FT_CONFIG_OPTION_INCREMENTAL is undefined (this is the default), the - TrueType loader crashes in line 852 of src/truetype/ttgload.c when - it tries to access face->glyph_locations.' - -2002-07-18 Graham Asher - - Added types and structures to support incremental typeface loading. - The FT_Incremental_Interface structure, defined in freetype.h, is - designed to be passed to FT_Open_Face to provide callback functions - to obtain glyph recipes and metrics, for fonts like those passed - from PostScript that do not necessarily provide all, or any, glyph - information, when first opened. - - * include/freetype/config/ftoption.h (FT_CONFIG_OPTION_INCREMENTAL): - New configuration macro to enable incremental face loading. By - default it is not defined. - - * include/freetype/freetype.h (FT_Basic_Glyph_Metrics, - FT_Get_Glyph_Data_Func, FT_Get_Glyph_Metrics_Func, - FT_Incremental_Interface_Funcs, FT_Incremental_Interface) - [FT_CONFIG_OPTION_INCREMENTAL]: New. - (FT_Open_Args, FT_FaceRec) [FT_CONFIG_OPTION_INCREMENTAL]: New field - `incremental_interface'. - (FT_Open_Flags) [FT_CONFIG_OPTION_INCREMENTAL]: New enum - `ft_open_incremental'. - - * include/freetype/fttypes.h: Include FT_CONFIG_CONFIG_H. - (FT_Data): New structure to represent binary data. - - * src/base/ftobjs.c (open_face) [FT_CONFIG_OPTION_INCREMENTAL]: - Add parameter for incremental loading. - (FT_Open_Face) [FT_CONFIG_OPTION_INCREMENTAL]: Use incremental - interface. - - * src/truetype/ttgload.c (load_truetype_glyph) - [FT_CONFIG_OPTION_INCREMENTAL]: Added the incremental loading system - for the TrueType driver. - (compute_glyph_metrics): Return FT_Error. - [FT_CONFIG_OPTION_INCREMENTAL]: Check for overriding metrics. - (TT_Load_Glyph) [FT_CONFIG_OPTION_INCREMENTAL]: Don't look for - the glyph table while handling an incremental font. - Get glyph offset. - - * src/truetype/ttobjs.c (TT_Face_Init) - [FT_CONFIG_OPTION_INCREMENTAL]: Added the incremental loading - system for the TrueType driver. - - * src/cid/cidgload.c (cid_load_glyph) - [FT_CONFIG_OPTION_INCREMENTAL]: Added the incremental loading system - for the CID driver. - - * src/sfnt/sfobjs.c (SFNT_Load_Face) [FT_CONFIG_OPTION_INCREMENTAL]: - Changes to support incremental Type 42 fonts: Assume a font has - glyphs if it has an incremental interface object. - - * src/type1/t1gload.c (T1_Parse_Glyph): Renamed to... - (T1_Parse_Glyph_And_Get_Char_String): This. - [FT_CONFIG_OPTION_INCREMENTAL]: Added support for incrementally - loaded Type 1 faces. - (T1_Parse_Glyph): New function. - (T1_Load_Glyph): Updated. - -2002-07-17 David Turner - - Cleaning up the cache sub-system code; linear hashing is now the - default. - - * include/freetype/cache/ftccache.h, src/cache/ftccache.i, - src/cache/ftccache.c [!FTC_CACHE_USE_LINEAR_HASHING]: Removed. - (FTC_CACHE_USE_LINEAR_HASHING): Removed also. - - FT_CONFIG_OPTION_USE_CMAPS is now the default. - - * include/freetype/internal/ftdriver.h (FT_Driver_ClassRec): Remove - `get_char_index' and `get_next_char'. - - * include/freetype/config/ftoption.h, - include/freetype/internal/tttypes.h, src/base/ftobjs.c, - src/bdf/bdfdrivr.c, src/cff/cffobjs.c, src/pcf/pcfdrivr.c, - src/pfr/pfrdrivr.c, src/sfnt/sfobjs.c, src/sfnt/ttcmap0.c, - src/sfnt/ttcmap0.h, src/sfnt/ttload.c, src/type1/t1objs.c, - src/type42/t42objs.c, src/winfonts/winfnt.c - [!FT_CONFIG_OPTION_USE_CMAPS]: Removed. The new cmap code is now - the default. - - * src/type42/t42objs.c (T42_CMap_CharIndex, T42_CMap_CharNext): - Removed. - * src/type42/t42objs.h: Updated. - - * src/cid/cidriver.c (Cid_Get_Char_Index, Cid_Get_Next_Char): - Removed. - (t1cid_driver_class): Updated. - * src/truetype/ttdriver.c (tt_driver_class): Updated. - * src/type1/t1driver.c (Get_Char_Index, Get_Next_Char): Removed - (t1_driver_class): Updated. - * src/type42/t42drivr.c (t42_driver_class): Updated. - - * src/base/ftobjs.c (open_face): Select Unicode cmap by default. - - * src/sfnt/ttload.c (TT_Load_SFNT_Header): Fixed a recent bug that - prevented OpenType fonts to be recognized by FreeType. - -2002-07-11 David Turner - - Changing the SFNT loader to check for SFNT-based font files - differently. We now ignore the range `helper' fields and check the - `head' table's magic number instead. - - * include/freetype/internal/tttypes.h (SFNT_HeaderRec): Add `offset' - field. - - * src/sfnt/ttload.c (sfnt_dir_check): New function. - (TT_Load_SFNT_HeaderRec): Renamed to... - (TT_Load_SFNT_Header): This. - Implement new functionality. - * src/sfnt/ttload.h: Updated. - * src/sfnt/sfdriver.c (sfnt_interface): Updated. - - * src/base/ftobject.c, src/base/fthash.c: Updated object sub-system - and dynamic hash table implementation (still experimental, don't - use). - * include/freetype/internal/fthash.h: Updated. - * include/freetype/internal/ftobjs.h (FT_LibraryRec): New member - `meta_class'. - - Fixing a bug in the Type 1 loader that prevented valid font bounding - boxes to be loaded from multiple master fonts. - - * include/freetype/t1tables.h (PS_BlendRec): Add `bboxes' field. - - * include/freetype/internal/psaux.h (T1_FieldType): Add - `T1_FIELD_TYPE_BBOX'. - (T1_FieldLocation): Add `T1_FIELD_LOCATION_BBOX'. - (T1_FIELD_BBOX): New macro. - - * src/psaux/psobjs.c (PS_Parser_LoadField): Handle T1_FIELD_TYPE_BBOX. - * src/type1/t1load.c (t1_allocate_blend): Create blend->bboxes. - (T1_Done_Blend): Free blend->bboxes. - (t1_load_keyword): Handle T1_FIELD_LOCATION_BBOX. - (parse_font_bbox): Commented out. - (t1_keywords): Comment out `parse_font_bbox'. - * src/type1/t1tokens.h: Define `FontBBox' field. - -2002-07-10 David Turner - - * src/cff/cffobjs.c: Small fix to select the Unicode charmap by - default when needed. - Small fix to allow OpenType fonts to support Adobe charmaps when - needed. - - * src/cff/cffcmap.c, src/cff/cffcmap.h: New files to support - charmaps for CFF fonts. - - * src/cff/cff.c, src/cff/Jamfile, src/cff/rules.mk: Updated. - - * include/freetype/internal/cfftypes.h (CFF_EncodingRec): Use - fixed-length arrays for `sids' and `codes'. Add `count' member. - (CFF_FontRec): Add `psnames' member. - - * src/cff/cffdrivr.c, src/cff/cffload.c, src/cff/cffload.h, - src/cff/cffobjs.c, src/cff/cffobjs.h, src/cff/cffparse.c, - src/cffparse.h, src/cff/cffgload.c, src/cff/cffgload.h: Adding - support for CFF charmaps, reformatting the sources, and removing - some bugs in the Encoding and Charset loaders. - Many fonts renamed to use lowercase only: - - CFF_Builder_Init -> cff_builder_init - CFF_Builder_Done -> cff_builder_done - CFF_Init_Decoder -> cff_decoder_init - CFF_Parse_CharStrings -> cff_decoder_parse_charstrings - CFF_Load_Glyph -> cff_slot_load - CFF_Init_Decoder -> cff_decoder_init - CFF_Prepare_Decoder -> cff_decoder_prepare - CFF_Get_Standard_Encoding -> cff_get_standard_encoding - CFF_Access_Element -> cff_index_access_element - CFF_Forget_Element -> cff_index_forget_element - CFF_Get_Name -> cff_index_get_name - CFF_Get_String -> cff_index_get_sid_string - CFF_Get_FD -> cff_fd_select_get - CFF_Done_Charset -> cff_charset_done - CFF_Load_Charset -> cff_charset_load - CFF_Done_Encoding -> cff_encoding_done - CFF_Load_Encoding -> cff_encoding_load - CFF_Done_SubFont -> cff_subfont_done - CFF_Load_Font -> cff_font_load - CFF_Done_Font -> cff_font_done - CFF_Size_Get_Globals_Funcs -> cff_size_get_globals_funcs - CFF_Size_Done -> cff_size_done - CFF_Size_Init -> cff_size_init - CFF_Size_Reset -> cff_size_reset - CFF_GlyphSlot_Done -> cff_slot_done - CFF_GlyphSlot_Init -> cff_slot_init - CFF_StrCopy -> cff_strcpy - CFF_Face_Init -> cff_face_init - CFF_Face_Done -> cff_face_done - CFF_Driver_Init -> cff_driver_init - CFF_Driver_Done -> cff_driver_done - CFF_Parser_Init -> cff_parser_init - CFF_Parser_Run -> cff_parser_run - - add_point -> cff_builder_add_point - add_point1 -> cff_builder_add_point1 - add_contour -> cff_builder_add_contour - close_contour -> cff_builder_close_contour - cff_explicit_index -> cff_index_get_pointers - -2002-07-09 Owen Taylor - - * src/pshinter/pshglob.c (psh_globals_new): Fixed a bug that - prevented the hinter from using correct standard width and height - values, resulting in hinting bugs with certain fonts (e.g. Utopia). - -2002-07-07 David Turner - - * src/base/ftglyph.c (FT_Glyph_To_Bitmap): Added code to return - successfully when the function is called with a bitmap glyph (the - previous code simply returned with an error). - - * docs/DEBUG.TXT: Adding debugging support documentation. - - * src/base/ftdebug.c (ft_debug_init), builds/win32/ftdebug.c - (ft_debug_init), builds/amiga/src/ftdebug.c (ft_debug_init): Changed - the syntax of the FT2_DEBUG environment variable used to control - debugging output (i.e. logging and error messages). It must now - look like: - - any:6 memory:4 io:3 or - any:6,memory:4,io:3 or - any:6;memory:4;io:3 - -2002-07-07 Owen Taylor - - * src/pshinter/pshglob.c (psh_blues_snap_stem): Adding support for - blue fuzz. - * src/pshinter/pshglob.h (PSH_BluesRec): Add `blue_fuzz' field. - * src/type1/t1load.c (T1_Open_Face): Initialize `blue_fuzz'. - - Adding support for hinter-specific bit flags, and the new - FT_Set_Hint_Flags high-level API. - - * include/freetype/freetype.h (FT_Set_Hint_Flags): New function. - (FT_HINT_NO_INTEGER_STEM, FT_HINT_NO_HSTEM_ALIGN, - FT_HINT_NO_VSTEM_ALIGN): New macros. - - * include/freetype/internal/ftobjs.h (FT_Face_InternalRec): Add - `hint_flags' member. - - * src/base/ftobjs.c (FT_Set_Hint_Flags): New function. - - * include/freetype/internal/psaux.h (T1_DecoderRec): Add `hint_flags' - member. - - * include/freetype/internal/pshints.h (T1_Hints_ApplyFunc, - T2_Hints_ApplyFunc): Add parameter to pass hint flags. - - * src/psaux/t1decode.c (T1_Decoder_Parse_Charstrings, - T1_Decoder_Init): Use decoder->hint_flags. - * src/cff/cffgload.h (CFF_Builder): Add `hint_flags' field. - * src/cff/cffgload.c (CFF_Builder_Init): Set builder->hint_flags. - (CFF_Parse_CharStrings): Updated. - * src/pshinter/pshalgo1.c (ps1_hints_apply): Add parameter to handle - hint flags (unused). - * src/pshinter/pshalgo1.h: Updated. - * src/pshinter/pshalgo2.c (ps2_hints_apply): Add parameter to handle - hint flags (unused). - * src/pshinter/pshalgo2.h: Updated. - * src/pshinter/pshalgo3.c (ps3_hints_apply): Add parameter to handle - hint flags. - * src/pshinter/pshalgo3.h: Updated. - -2002-07-04 David Turner - - * src/pfr/pfrobjs.c (pfr_slot_load): Fixed a small bug that returned - incorrect advances when the outline resolution was different from - the metrics resolution. - - * src/autohint/ahhint.c: Removing compiler warnings. - - * src/autohint/ahglyph.c: s/FT_MEM_SET/FT_ZERO/ where appropriate. - (ah_outline_link_segments): Slight improvements to the serif - detection code. More work is needed though. - -2002-07-03 David Turner - - Small improvements to the automatic hinter. Uneven stem-widths have - now disappeared and everything looks much better, even if there are - still issues with serifed fonts. - - * src/autohint/ahtypes.h (AH_Globals): Added `stds' array. - * src/autohint/ahhint.c (OPTIM_STEM_SNAP): New #define. - (ah_snap_width): Commented out. - (ah_align_linked_edge): Renamed to... - (ah_compute_stem_width): This. - Don't allow uneven stem-widths. - (ah_align_linked_edge): New function. - (ah_align_serifed_edge): Don't strengthen serifs. - (ah_hint_edges_3, ah_hinter_scale_globals): Updated. - -2002-07-03 Owen Taylor - - Adding new algorithm based on Owen Taylor's recent work. - - * src/pshinter/pshalgo3.c, src/pshinter/pshalgo3.h: New files. - * src/pshinter/pshalgo.h: Updated. - Use pshalgo3 by default. - * src/pshinter/pshinter.c: Include pshalgo3.c. - - * src/pshinter/Jamfile, src/pshinter/rules.mk: Updated. - -2002-07-01 Owen Taylor - - * src/pshinter/pshalgo2.c (psh2_glyph_find_strong_points): Fix a bug - where, if a glyph has more than hint mask, the second mask gets - applied to points that should have been covered by the first mask. - -2002-07-01 Keith Packard - - * src/sfnt/ttcmap0.c (tt_cmap8_char_next, tt_cmap12_char_next): - Fixing the cmap 8 and 12 parsing routines. - -2002-07-01 David Turner - - * src/base/ftsynth.c: Include FT_TRIGONOMETRY_H. - (FT_Outline_Embolden): Renamed to... - (FT_GlyphSlot_Embolden): This. - Updated to new trigonometric functions. - (FT_Outline_Oblique): Renamed to... - (FT_GlyphSlot_Oblique): This. - (ft_norm): Removed. - * include/freetype/ftsynth.h: Updated. - -2002-06-26 David Turner - - * include/freetype/internal/ftobject.h: Updating the object - sub-system definitions (still experimental). - - * src/base/fthash.c (ft_hash_remove): Fixing a small reallocation - bug. - - * src/base/fttrigon.c (FT_Vector_From_Polar, FT_Angle_Diff): New - functions. - * include/freetype/fttrigon.h: Updated. - - - Adding path stroker component (work in progress). - - * include/freetype/ftstroker.h, src/base/ftstroker.c: New files. - * src/base/Jamfile: Updated. - - * include/freetype/config/ftheader.h (FT_STROKER_H): New macro. - - - * src/truetype/ttgload.c (TT_Load_Composite_Glyph), - src/base/ftoutln.c (FT_Vector_Transform): Fixed Werner's latest fix. - FT_Vector_Transform wasn't buggy, the TrueType composite loader was. - -2002-06-24 Werner Lemberg - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 3. - -2002-06-21 David Turner - - - * Version 2.1.2 released. - ========================= - - -2002-06-21 Roberto Alameda . - - * include/freetype/internal/t42types.h (T42_Font): Removed since - it is already in t42objs.h. - (T42_Face): Use T1_FontRec. - - * src/base/fttype1.c (FT_Get_PS_Font_Info): Updated. - (FT_Has_PS_Glyph_Names): Check for type42 driver name also. - * src/type42/t42objs.h: Include FT_INTERNAL_TYPE42_TYPES_H. - (T42_Face): Removed since it is already in t42types.h. - -2002-06-21 Detlef Würkner - - * src/pfrgload.c (pfr_glyph_load_compound): Fix loading of composite - glyphs. - -2002-06-21 Sven Neumann - - * src/pfr/pfrtypes.h (PFR_KernPair): New structure. - (PFR_PhyFont): Use it. - (PFR_KernFlags): New enumeration. - * src/pfr/pfrload.c (pfr_extra_item_load_kerning_pairs): New - function. - (pfr_phy_font_extra_items): Use it. - (pfr_phy_font_done): Updated. - * src/pfr/pfrobjs.c (pfr_face_init): Set kerning flag conditionally. - (pfr_face_get_kerning): New function. - * src/pfr/pfrobjs.h: Updated. - * src/pfr/pfrdrivr.c (pfr_driver_class): Updated. - -2002-06-21 David Turner - - * README, docs/CHANGES: Preparing the 2.1.2 release. - -2002-06-19 Detlef Würkner - - * src/base/fttype1.c: Include FT_INTERNAL_TYPE42_TYPES_H. - (t1_face_check_cast): Removed. - (FT_Get_PS_Font_Info): Make it work with CID and Type 42 drivers - also. - -2002-06-19 Sebastien BARRE - - * src/type42/t42parse.c (t42_parse_sfnts): Fix compiler warning. - -2002-06-19 Werner Lemberg - - * src/base/ftoutln.c (FT_Vector_Transform): Fix serious typo - (xy <-> yx). - * src/truetype/ttgload.c (load_truetype_glyph): Replace `|' with - `||' to make code easier to read. - -2002-06-18 Roberto Alameda . - - * src/type42/t42objs.c (t42_check_size_change): Removed. - (T42_Size_SetChars, T42_Size_SetPixels): Use FT_Activate_Size - instead. - (T42_GlyphSlot_Load): Remove call to t42_check_size_change. - -2002-06-18 Detlef Würkner - - * src/psaux/t1cmap.c (t1_cmap_custom_char_index, - t1_cmap_custom_char_next): Fix index computation -- indices start - with 0 and not with cmap->first. - - Provide default charmaps. - - * src/bdf/bdfdrivr.c (BDF_Face_Init), src/pcf/pcfdriver.c - (PCF_Face_Init), src/pfr/pfrobjs.c (pfr_face_init), - src/type1/t1objs (T1_Face_Init), src/winfonts/winfnt.c - (FNT_Face_Init): Implement it. - -2002-06-17 Sven Neumann - - * src/pfr/pfrobjs.c (pfr_face_init): Fix typo. - -2002-06-16 Leonard Rosenthol - - Updated Win32/VC++ projects to include the new PFR driver. - - * builds/win32/visualc/freetype.dsp: Updated. - -2002-06-16 Anthony Fok - - Install freetype2.m4. - - * builds/unix/install.mk (install, uninstall): Handle it. - -2002-06-16 Detlef Würkner - - Same fix for PFR driver. - - * src/pfr/pfrcmap.c (pfr_cmap_char_index, pfr_cmap_char_next): - Increase return value by 1. - * src/pfr/pfrobjs.c (pfr_slot_load): Decrease index by 1. - -2002-06-15 Detlef Würkner - - Fix glyph indices to make index zero always the undefined glyph. - - * src/bdf/bdfdrivr.c (bdf_cmap_init): Don't decrease - cmap->num_encodings. - (bdf_cmap_char_index, bdf_cmap_char_next, BDF_Get_Char_Index): - Increase result by 1 for normal cases. - (BDF_Glyph_Load): Decrease index by 1. - - * src/pcf/pcfdriver.c (pcf_cmap_char_index, pcf_cmap_char_next, - PCF_Char_Get_Index): Increase result by 1 for normal cases. - (PCF_Glyph_Load): Decrease index by 1. - * src/pcf/pcfread.c (pcf_get_encodings): Don't decrease j for - allocating `encoding'. - - * src/base/ftobjs.c (FT_Load_Glyph, FT_Get_Glyph_Name): Fix - bounding tests. - -2002-06-14 Detlef Würkner - - Add new cmap support to BDF driver. - - * src/bdf/bdfdrivr.c (BDF_CMapRec) [FT_CONFIG_OPTION_USE_CMAPS]: - New structure. - (bdf_cmap_init, bdf_cmap_done, bdf_cmap_char_index, - bdf_cmap_char_next) [FT_CONFIG_OPTION_USE_CMAPS]: New functions. - (BDF_Get_Char_Index) [!FT_CONFIG_OPTION_USE_CMAPS]: Use only - conditionally. - (BDF_Face_Init): Handle `AVERAGE_WIDTH' and `POINT_SIZE' keywords. - Implement new cmap handling. - (bdf_driver_class): Updated. - -2002-06-14 Werner Lemberg - - * Makefile, configure, */*.mk, builds/unix/unix-def.in, - docs/CHANGES, docs/INSTALL: s/TOP/TOP_DIR/. - -2002-06-12 Werner Lemberg - - * src/bdf/bdflib.c: s/FT_Short/short/ for consistency. - -2002-06-11 David Turner - - * builds/win32/ftdebug.c: Added a missing #endif. - - * src/sfnt/ttload.c, src/bdf/bdflib.c: Removing compiler warnings. - - Removed the bug in Type 42 driver that prevented un-hinted outlines - to be loaded. - - * src/type42/t42objs.c (T42_Face_Init): Call FT_Done_Size. - (T42_Size_Init): Call FT_Activate_Size. - (t42_check_size_change): New function. - (T42_Size_SetChars, T42_Size_SetPixels): Use it. - (ft_glyphslot_clear): Replace FT_MEM_SET with FT_ZERO. - (T42_GlyphSlot_Load): Use t42_check_size_change. - Initialize more fields of `glyph'. - - * builds/win32/visualc/freetype.dsp: Updated. - -2002-06-09 David Turner - - - * Version 2.1.1 released. - ========================= - - -2002-06-08 Juliusz Chroboczek - - * include/freetype/internal/ftobjs.h, src/autohint/ahglyph.c, - src/base/ftobjs.c, src/sfnt/ttcmap0.c, src/smooth/ftgrays.c: Don't - use `setjmp', `longjmp', and `jmp_buf' but `ft_setjmp', `ft_longjmp', - and `ft_jmp_buf'. - Removed direct references to and when - appropriate, to eventually replace them with a - FT_CONFIG_STANDARD_LIBRARY_H. Useful for the XFree86 Font Server - backend based on FT2. - - * src/base/fttype1.c (FT_Has_PS_Glyph_Names): Fix return value. - -2002-06-08 David Turner - - * src/pcf/pcfdriver.c (pcf_cmap_char_next): Fixed a bug that caused - the function to return invalid values. - - * src/cache/ftccache.i: Removing a typo that prevented - the source's compilation. - - * src/cache/ftccache.c (ftc_node_hash_unlink): Fixed a - bug that caused nasty memory overwrites. The hash table's - buckets array wasn't correctly resized when shrunk. - -2002-06-08 Detlef Würkner - - * builds/amiga/smakefile, builds/amiga/makefile: Updated. - -2002-06-08 Werner Lemberg - - * src/cache/ftccache.c (ftc_node_hash_unlink, ftc_node_hash_link) - [FTC_CACHE_USE_LINEAR_HASHING]: Fix returned error code. - Fix debugging messages. - * src/cache/ftccache.i (GEN_CACHE_LOOKUP): Move declaration of - `family' and `hash' up to make it compilable with g++. - - * src/type42/t42error.h: New file. - * src/type42/t42drivr.c, src/type42/t42objs.c, - src/type42/t42parse.c: Use t42 error codes. - * src/type42/rules.mk: Updated. - - * src/base/ftnames.c: Include FT_INTERNAL_STREAM_H. - -2002-06-08 David Turner - - * src/cache/ftccmap.c: GEN_CACHE_FAMILY_COMPARE, - GEN_CACHE_NODE_COMPARE, GEN_CACHE_LOOKUP) [FTC_CACHE_USE_INLINE]: - New macros. - (ftc_cmap_cache_lookup) [!FTC_CACHE_USE_INLINE]: Typedef to - ftc_cache_lookup. - (FTC_CMapCache_Lookup): Updated. - - Adding various experimental optimizations to the cache manager. - - * include/freetype/cache/ftccache.h (FTC_CACHE_USE_INLINE, - FTC_CACHE_USE_LINEAR_HASHING): New options. - (FTC_CacheRec) [FTC_CACHE_USE_LINEAR_HASHING]: New elements `p', - `mask', and `slack'. - - * src/cache/ftccache.c (FTC_HASH_MAX_LOAD, FTC_HASH_MIN_LOAD, - FTC_HASH_SUB_LOAD) [FTC_CACHE_USE_LINEAR_HASHING, - FTC_HASH_INITIAL_SIZE]: New macros. - (ftc_node_mru_link, ftc_node_mru_up): Optimized. - (ftc_node_hash_unlink, ftc_node_hash_link) - [FTC_CACHE_USE_LINEAR_HASHING]: New variants. - (FTC_PRIMES_MIN, FTC_PRIMES_MAX, ftc_primes, ftc_prime_closest, - FTC_CACHE_RESIZE_TEST, ftc_cache_resize) - [!FTC_CACHE_USE_LINEAR_HASHING]: Define it conditionally. - (ftc_cache_init, ftc_cache_clear) [FTC_CACHE_USE_LINEAR_HASHING]: - Updated. - (ftc_cache_lookup) [FTC_CACHE_USE_LINEAR_HASHING]: Implement it. - - * src/cache/ftccache.i: New file. - - * src/cache/ftcsbits.c (GEN_CACHE_FAMILY_COMPARE, - GEN_CACHE_NODE_COMPARE, GEN_CACHE_LOOKUP) [FTC_CACHE_USE_INLINE]: - New macros. - (ftc_sbit_cache_lookup) [!FTC_CACHE_USE_INLINE]: Typedef to - ftc_cache_lookup. - (FTC_SBitCache_Lookup): Updated. - - * src/type42/t42parse.c: Removing duplicate function. - -2002-06-07 Graham Asher - - * src/base/ftobjs.c (FT_Render_Glyph_Internal): Changed definition - from FT_EXPORT_DEF to FT_BASE_DEF. - -2002-06-07 David Turner - - Fixed the bug that prevented the correct display of fonts with - `ftview'. - - * src/type42/t42drivr.c: Split into... - * src/type42/t42drivr.h, src/type42/t42parse.c, - src/type42/t42parse.h, src/type42/t42objs.h, src/type42/t42objs.c, - src/type42/type42.c: New files. - - (t42_get_glyph_name, t42_get_ps_name, t42_get_name_index): Use - `face->type1'. - - (Get_Interface): Renamed to... - (T42_Get_Interface): This. - Updated. - (T42_Open_Face, T42_Face_Done): Updated. - (T42_Face_Init): Add new cmap support. - Updated. - (T42_Driver_Init, T42_Driver_Done, T42_Size_Init, T42_Size_Done, - T42_GlyphSlot_Init, T42_GlyphSlot_Done): Updated. - (Get_Char_Index, Get_Next_Char): Renamed to... - (T42_CMap_CharIndex, T42_CMap_CharNext): This. - Updated. - (T42_Char_Size, T42_Pixel_Size): Renamed to... - (T42_Size_SetChars, T42_Size_SetPixels): This. - (T42_Load_Glyph): Renamed to... - (T42_GlyphSlot_Load): This. - - (t42_init_loader, t42_done_loader): Renamed to... - (t42_loader_init, t42_loader_done): This. - (T42_New_Parser, T42_Finalize_Parser): Renamed to... - (t42_parser_init, t42_parser_done): This. - (parse_dict): Renamed to... - (t42_parse_dict): This. - (is_alpha, is_space, hexval): Renamed to... - (t42_is_alpha, t42_is_space, t42_hexval): This. - (parse_font_name, parse_font_bbox, parse_font_matrix, - parse_encoding, parse_sfnts, parse_charstrings, parse_dict): - Renamed to... - (t42_parse_font_name, t42_parse_font_bbox, t42_parse_font_matrix, - t42_parse_encoding, t42_parse_sfnts, t42_parse_charstrings, - t42_parse_dict): This. - Updated. - - (t42_keywords): Updated. - - * src/type42/Jamfile, src/type42/descrip.mms: Updated. - -2002-06-03 Werner Lemberg - - Add 8bpp support to BDF driver. - - * src/bdf/bdflib.c (_bdf_parse_start): Handle 8bpp. - * src/bdf/bdfdrivr.c (BDF_Glyph_Load): Ditto. - * src/bdf/README: Updated. - -2002-06-02 Detlef Würkner - - * src/pfr/pfrload.c (pfr_phy_font_done): Free `blue_values' array. - -2002-05-29 Detlef Würkner - - * src/bdf/bdflib.c (_bdf_readstream): Allocate `buf' dynamically. - (_bdf_parse_glyphs): Use correct size for allocating - `font->unencoded'. - (bdf_load_font): Free array conditionally. - Return proper error code in case of failure. - * src/bdf/bdfdrivr.c (BDF_Face_Init): Make it more robust against - unusual fonts. - -2002-05-29 Werner Lemberg - - * src/bdf/descrip.mms, src/type42/descrip.mms: New files. - * descrip.mms (all): Updated. - - * src/bdf/bdflib.c (_bdf_parse_glyphs): Fix typo which prevented - compilation. - * src/pshglob.c (psh_blues_scale_zones): Fix compiler warning. - -2002-05-28 Detlef Würkner - - * builds/amiga/makefile, builds/amiga/smakefile, - amiga/include/freetype/config/ftmodule.h: Updated to include - support for BDF and Type42 drivers. - - * docs/modules.txt: Updated. - -2005-05-28 David Turner - - * docs/CHANGES: Updating file for next release (2.1.1). - - * src/bdf/bdflib.c: Removing compiler warnings. - - * include/freetype/ftxf86.h, src/base/ftxf86.c: New files. - They provide a new API (FT_Get_X11_Font_Format) to retrieve an - X11-compatible string describing the font format of a given face. - This was put in a new optional base source file, corresponding to a - new public header (named FT_XFREE86_H since this function should - only be used within the XFree86 font server IMO). - - * include/freetype/config/ftheader.h (FT_XFREE86_H): New macro (not - documented yet). - - * src/base/fttype1.c: New file, providing two new API functions - (FT_Get_PS_Font_Info and FT_Has_PS_Glyph_Names). - * include/freetype/t1tables.h: Updated. - - * src/base/Jamfile, src/base/rules.mk, src/base/descrip.mms: - Updating build control files for the new files `ftxf86.c' and - `fttype1.c' in src/base. - - * src/pshinter/pshglob.c (psh_blues_scale_zones): Fixed a bug that - prevented family blue zones substitution from happening correctly. - - * include/freetype/ftbdf.h FT_Get_BDF_Charset_ID): Adding - documentation comment. - -2002-05-28 Werner Lemberg - - * src/base/ftnames.c (FT_Get_Sfnt_Name): Don't use FT_STREAM_READ_AT - but FT_STREAM_READ. - Declare `stream' variable. - - * src/bdf/bdflib.c (_bdf_parse_glyphs): Replace floating point math - with calls to `FT_MulDiv'. - -2002-05-28 David Turner - - Fixing the SFNT name table loader to support various buggy fonts. - It now ignores empty name entries, entries with invalid pointer - Offsets and certain fonts containing tables with broken - `storageOffset' fields. - - Name strings are now loaded on demand, which reduces the memory - requirements for a given FT_Face tremendously (for example, the name - table of Arial.ttf is about 10Kb and contains 70 names). - - This is a temporary fix. The whole name table loader and interface - will be rewritten in a much more cleanly way shortly, once CSEH have - been introduced in the sources. - - * include/freetype/internal/tttypes.h (TT_NameEntryRec): Change - type of `stringOffset' to FT_ULong. - (TT_NameTableRec): Change type of `numNameRecords' and - `storageOffset' to FT_UInt. - Replace `storage' with `stream'. - * src/base/ftnames.c (FT_Get_Sfnt_Name): Load name on demand. - * src/sfnt/sfdriver.c (get_sfnt_postscript_name): Ditto. - Make code more robust. - * src/sfnt/sfobjs.c (TT_NameEntry_ConvertFunc): New typedef. - (tt_face_get_name): Use it. - Make code more robust. - * src/sfnt/ttload.c (TT_Load_Names): Use `static' for arrays. - Handle invalid `storageOffset' data better. - Set length fields to zero for invalid or ignored data. - Remove code within FT_DEBUG_LEVEL_TRACE. - (TT_Free_Names): Updated. - -2002-05-24 Tim Mooney - - * builds/unix/ft-munmap.m4: New file, extracted FT_MUNMAP_DECL and - FT_MUNMAP_PARAM from aclocal.m4 into here, so aclocal.m4 can be - rebuilt from sources. Set macro serial to 1, and use third argument - to AC_DEFINE for our two custom symbols, so ftconfig.in could one day - be rebuilt with autoheader (not recommended now, ftconfig.in is a - custom source file) - -2002-05-22 Werner Lemberg - - * include/freetype/config/ftheader.h (FT_BEZIER_H): Removed. - (FT_BDF_H): New macro for accessing `ftbdf.h'. - - * src/type42/t42drivr.c (hexval): Fix typo. - -2002-05-21 Martin Muskens - - * src/psaux/psobjs.c (T1Radix): New function. - (t1_toint): Use it to handle numbers in radix format. - - * src/psaux/t1decode.c (T1_Decoder_Parse_Charstrings): Add dummy - for undocumented, obsolete opcode 15. - -2002-05-21 David Turner - - * src/bdf/bdflib.c: Removed compiler warning, and changed all tables - to the `static const' storage specifier (instead of simply - `static'). - - * src/type42/t42drivr.c (hexval): Use more efficient code. - Removing compiler warnings. - * src/bdf/bdfdrivr.c: Removing compiler warnings. - - * include/freetype/internal/ftbdf.h, src/base/ftbdf.c, - src/base/descrip.mms, src/base/Jamfile, src/base/rules.mk - (FT_Get_BDF_Charset_ID): New API to retrieve BDF-specific strings - from a face. This is much cleaner than accessing the internal types - `BDF_Public_Face' defined in FT_INTERNAL_BDF_TYPES_H. - -2002-05-21 Werner Lemberg - - * src/bdf/README: Mention Microsoft's SBIT tool. - - * src/cff/cffdrivr.c, src/cid/cidriver.c, src/pcf/pcfdriver.c, - src/truetype/ttdriver.c, src/type1/t1driver.c, - src/winfonts/winfnt.c, src/type42/t42drivr.c, src/bdf/bdfdrivr.c - [FT_CONFIG_OPTION_DYNAMIC_DRIVERS]: Completely removed. It has - been never used. - -2002-05-21 Roberto Alameda . - - * src/type42/t42drivr.c: s/T42_ENCODING_TYPE_/T1_ENCODING_TYPE_/. - (parse_font_matrix): Remove unnecessary code. - (parse_sfnts): Initialize some variables. - (t42_driver_class) [TT_CONFIG_OPTION_BYTECODE_INTERPRETER]: Use - ft_module_driver_has_hinter conditionally. - Moved some type 42 specific structure definitions to... - * include/freetype/internal/t42types.h: New file. - * include/freetype/internal/internal.h (FT_INTERNAL_T42_TYPES_H): - New macro. - -2002-05-20 Werner Lemberg - - * include/freetype/cache/ftcsbits.h (FTC_SBit): Added a new field - `num_grays' for specifying the number of used gray levels. - * src/cache/ftcsbits.c (ftc_sbit_node_load): Initialize it. - -2002-05-19 Werner Lemberg - - Adding a driver for BDF fonts written by Francesco Zappa Nardelli - . Heavily modified by me to - better adapt it to FreeType, removing unneeded stuff. Additionally, - it now supports Mark Leisher's BDF extension for anti-aliased - bitmap glyphs with 2 and 4 bpp. - - * src/bdf/*: New driver. - * include/freetype/internal/bdftypes.h: New file. - * include/freetype/internal/fttrace.h: Added BDF driver components. - * include/freetype/fterrdef.h: Added error codes for BDF driver. - * include/freetype/config/ftmodule.h, src/Jamfile: Updated. - * include/freetype/internal/internal.h (FT_INTERNAL_BDF_TYPES_H): - New macro. - - * include/freetype/config/ftstdlib.h (ft_sprintf): New alias for - sprintf. - -2002-05-18 Werner Lemberg - - * include/freetype/internal/fttrace.h: Added Type 42 driver - component. - * src/type42/t42drivr.c: Use it. - - * include/freetype/internal/internal.h (FT_INTERNAL_PCF_TYPES_H): - New macro. - -2002-05-17 Werner Lemberg - - * src/type42/Jamfile: New file. - -2002-05-14 Werner Lemberg - - Adding a driver for Type42 fonts written by Roberto Alameda - . - - * src/type42/*: New driver. - * include/freetype/config/ftmodule.h, src/Jamfile: Updated. - * include/freetype/config/ftstdlib.h (ft_xdigit, ft_memcmp, - ft_atoi): New aliases for xdigit, memcmp, and atoi, respectively. - -2002-05-12 Owen Taylor - - * src/sfnt/ttload.c (TT_LookUp_Table): Protect against tables - with a zero length value. - -2002-05-12 Michael Pfeiffer - - * builds/beos/beos.mk: Include `link-std.mk'. - -2002-05-12 Werner Lemberg - - * src/type1/t1load.h (T1_Loader): Renamed to... - (T1_LoaderRec): This. - (T1_Loader): Now pointer to T1_LoaderRec. - * src/type1/t1load.c: Updated. - - * include/freetype/internal/t1types.h, src/type1/t1load.c, - src/type1/t1objs.c: - s/T1_ENCODING_TYPE_EXPORT/T1_ENCODING_TYPE_EXPERT/. - -2002-05-06 Werner Lemberg - - * README: Add a note regarding libttf vs. libfreetype. - -2002-05-05 Werner Lemberg - - FreeType 2 can now be built in an external directory with the - configure script also. - - * builds/freetype.mk (INCLUDES): Add `OBJ_DIR'. - - * builds/unix/detect.mk (have_mk): New variable to test for - external build. - (unix-def.mk): Defined according to value of `have_mk'. - * builds/unix/unix.mk (have_mk): New variable to test for - external build. - Select include paths for unix-def.mk and unix-cc.mk according - to value of `have_mk'. - * builds/unix/unix-def.in (OBJ_BUILD): New variable. - (DISTCLEAN): Use it. - * builds/unix/unix-cc.in (LIBTOOL): Define default value only - if not yet defined. - * builds/unix/install.mk (install): Use `OBJ_BUILD' for installing - freetype-config. - - * configure: Don't depend on bash features. - (ft2_dir, abs_curr_dir, abs_ft2_dir): New variables (code - partially taken from Autoconf). - Build a dummy Makefile if not building in source tree. - - * docs/INSTALL: Document it. - -2002-05-04 David Turner - - * src/truetype/ttgload.c (TT_Load_Glyph): Finally fixing the last - bug that prevented FreeType 2.x and FreeType 1.x to produce - bit-by-bit identical monochrome glyph bitmaps with native TrueType - hinting. The culprit was a single-bit flag that wasn't set - correctly by the TrueType glyph loader. - - * src/otlayout/otlayout.h, src/otlayout/otlbase.c, - src/otlayout/otlbase.h, src/otlayout/otlconf.h, - src/otlayout/otlgdef.c, src/otlayout/otlgdef.h, - src/otlayout/otlgpos.c, src/otlayout/otlgpos.h, - src/otlayout/otlgsub.c, src/otlayout/otlgsub.h, - src/otlayout/otljstf.c, src/otlayout/otljstf.h, - src/otlayout/otltable.c, src/otlayout/otltable.h, - src/otlayout/otltags.h: New OpenType Layout source files. The - module is still incomplete. - -2002-05-02 Werner Lemberg - - * src/sfnt/ttcmap0.c (tt_cmap4_char_index): Fix serious typo - (0xFFFU -> 0xFFFFU). - -2002-05-01 Werner Lemberg - - * docs/INSTALL: Fix URL of makepp. - -2002-05-01 David Turner - - * src/sfnt/sfobjs.c (tt_face_get_name): Fixing a bug that caused - FreeType to crash when certain broken fonts (e.g. `hya6gb.ttf') - were opened. - - * src/sfnt/ttload.c (TT_Load_Names): Applied a small work-around to - manage fonts containing a broken name table (e.g. `hya6gb.ttf'). - - * src/sfnt/ttcmap0.c (tt_cmap4_validate): Fixed over-restrictive - validation test. The charmap validator now accepts overlapping - ranges in format 4 charmaps. - - * src/sfnt/ttcmap0.c (tt_cmap4_char_index): Switched to a binary - search algorithm. Certain fonts contain more than 170 distinct - segments! - - * include/freetype/config/ftstdlib.h: Adding an alias for the `exit' - function. This will be used in the near future to panic in case of - unexpected exception (which shouldn't happen in theory). - - * include/freetype/internal/fthash.h, src/base/fthash.c: New files. - This is generic implementation of dynamic hash tables using a linear - algorithm (to get rid of `stalls' during resizes). In the future - this will be used in at least three parts of the library: the cache - sub-system, the object sub-system, and the memory debugger. - - * src/base/Jamfile: Updated. - - * include/freetype/internal/internal.h (FT_INTERNAL_HASH_H, - FT_INTERNAL_OBJECT_H): New macros. - - * include/freetype/internal/ftcore.h: New file to group all new - definitions related to exception handling and memory management. It - is very likely that this file will disappear or be renamed in the - future. - - * include/freetype/internal/ftobject.h, include/freetype/ftsysmem.h: - Adding comments to better explain the object sub-system as well as - the new memory manager interface. - -2002-04-30 Wenlin Institute (Tom Bishop) - - * src/base/ftmac.c (p2c_str): Removed. - (file_spec_from_path) [TARGET_API_MAC_CARBON]: Added support for - OS X. - (is_dfont) [TARGET_API_MAC_CARBON]: Define only for OS X. - Handle `nameLen' <= 6 also. - (parse_fond): Remove unused variable `name_table'. - Use functionality of old p2c_str directly. - Add safety checks. - (read_lwfn): Initialize `size_p'. - Check for size_p == NULL. - (new_memory_stream, open_face_from_buffer): Updated to FreeType 2.1. - (FT_New_Face_From_LWFN): Remove unused variable `memory'. - Remove some dead code. - (FT_New_Face_From_SFNT): Remove unused variable `stream'. - (FT_New_Face_From_dfont) [TARGET_API_MAC_CARBON]: Define only for - OS X. - (FT_New_Face_From_FOND): Remove unused variable `error'. - (ResourceForkSize): New function. - (FT_New_Face): Use it. - Handle empty resource forks. - Conditionalize some code for OS X. - Add code to call normal loader as a fallback. - -2002-04-30 Werner Lemberg - - `interface' is reserved on the Mac. - - * include/freetype/ftoutln.h, include/freetype/internal/sfnt.h, - src/base/ftoutln.c: s/interface/func_interface/. - * src/base/ftbbox.c (FT_Outline_Get_BBox): - s/interface/bbox_interface/. - * src/cff/cffdrivr.c: s/interface/module_interface/. - * src/cff/cffload.c, src/cff/cffload.h: - s/interface/psnames_interface/. - * src/cid/cidriver.c: s/interface/cid_interface/. - * src/sfnt/sfdriver.c: s/interface/module_interface/. - * src/smooth/ftgrays.c: s/interface/func_interface/. - * src/truetype/ttdriver.c: s/interface/tt_interface/. - * src/type1/t1driver.c: s/interface/t1_interface/. - - Some more variable renames to avoid troubles on the Mac. - - * src/raster/ftraster.c: - s/Unknown|Ascending|Descending|Flat/\1_State/. - * src/smooth/ftgrays.c: s/TScan/TCoord/. - - Other changes for the Mac. - - * include/freetype/config/ftconfig.h: Define FT_MACINTOSH for - Mac platforms. - * src/base/ftobjs.c: s/macintosh/FT_MACINTOSH/. - - * src/raster/ftrend1.c (ft_raster1_render): Make `pitch' always - an even number. - -2002-04-29 Jouk Jansen - - * descrip.mms (all): Add pfr driver. - -2002-04-28 Werner Lemberg - - * src/pfr/pfrerror.h: New file. - * include/freetype/ftmoderr.h: Add PFR error codes. - * src/pfr/pfrgload.c: Include pfrerror.h. - Use PCF error codes. - (pfr_extra_item_load_stem_snaps): Fix debug message. - * src/pfr/pfrgload.c: Include pfrerror.h. - Use PCF error codes. - (pfr_extra_item_load_bitmap_info, pfr_glyph_load_simple, - pfr_glyph_load_compound): Fix debug message. - * src/pfr/pfrobjs.c: Include pfrerror.h. - Use PCF error codes. - (pfr_face_init): Return PFR_Err_Unknown_File_Format. - * src/pfr/rules.mk (PFR_DRV_H): Include pfrerror.h. - - * src/pcf/pcfdriver.c (PCF_Face_Init) [!FT_CONFIG_OPTION_USE_CMAPS]: - `root' -> `face->root'. - * src/sfnt/ttcmap0.c (TT_Build_CMaps) [!FT_CONFIG_OPTION_USE_CMAPS]: - Removed. - * src/sfnt/ttcmap0.c: Declare TT_Build_CMaps only for - FT_CONFIG_OPTION_USE_CMAPS. - -2002-04-27 Werner Lemberg - - * src/cache/ftccache.c (ftc_cache_lookup), - src/cache/ftccmap.c (ftc_cmap_family_init), - src/cache/ftcmanag.c (ftc_family_table_alloc), - src/cache/ftcsbits.c (FTC_SBit_Cache_Lookup): Use FTC_Err_*. - src/cache/ftcimage.c (FTC_Image_Cache_Lookup): Use FTC_Err_*. - (FTC_ImageCache_Lookup): Fix handling of invalid arguments. - -2002-04-22 Werner Lemberg - - * builds/unix/configure.ac: Set `version_info' to 9:1:3 (FT2 - version 2.0.9 has 9:0:3). - * builds/unix/configure: Regenerated (using autoconf 2.53). - -2002-04-19 Werner Lemberg - - * src/pfr/pfrload.c (pfr_extra_items_parse): Fix debug message. - (pfr_phy_font_load): s/size/Size/ for local variable to avoid - compiler warning. - * src/pfr/pfrobjs.c (pfr_face_init): Fix debug message. - (pfr_slot_load): Remove redundant local variable. - -2002-04-19 David Turner - - Adding a PFR font driver to the FreeType sources. Note that it - doesn't support embedded bitmaps or kerning tables yet. - - src/pfr/*: New files. - - * include/freetype/config/ftmodule.h, - include/freetype/internal/fttrace.h, src/Jamfile: Updated. - - * src/type1/t1gload.h (T1_Load_Glyph), src/type1/t1gload.c - (T1_Load_Glyph): Fixed incorrect parameter sign-ness in callback - function. - - * include/freetype/internal/ftmemory.h (FT_MEM_ZERO, FT_ZERO): New - macros. - - * include/freetype/internal/ftstream.h (FT_NEXT_OFF3, FT_NEXT_UOFF3, - FT_NEXT_OFF3_LE, FT_NEXT_UOFF3_LE): New macros to parse in-memory - 24-bit integers. - -2002-04-18 David Turner - - * src/base/ftobjs.c, builds/win32/ftdebug.c, - builds/amiga/src/base/ftdebug.c: Version 2.1.0 couldn't be linked - against applications in Win32 and Amiga builds due to changes to - `src/base/ftdebug.c' that were not properly propagated to - `builds/win32' and `builds/amiga'. This has been fixed. - - * include/freetype/internal/ftobject.h, - include/freetype/internal/ftexcept.h, include/freetype/ftsysmem.h, - include/freetype/ftsysio.h, src/base/ftsysmem.c, src/base/ftsysio.c: - New experimental files. - -2002-04-17 David Turner - - - * Version 2.1.0 released. - ========================= - - -2002-04-17 Michael Jansson - - * src/type1/t1gload.c (T1_Compute_Max_Advance): Fixed a small bug - that prevented the function to return the correct value. - -2002-04-16 Francesco Zappa Nardelli - - * src/pcf/pcfread.c (pcf_get_accel): Fix parsing of accelerator - tables. - -2002-04-15 David Turner - - * docs/FTL.txt: Formatting. - - * include/freetype/config/ftoption.h: Reduce the size of the - render pool from 32kByte to 16kByte. - - * src/pcf/pcfread.c (pcf_seek_to_table_type): Remove compiler - warning. - - * include/freetype/config/ftoption.h (FT_MAX_EXTENSIONS): Removed. - - * docs/CHANGES: Preparing 2.1.0 release. - -2002-04-13 Werner LEMBERG - - * src/cff/cffgload.c (CFF_Parse_CharStrings): s/rand/Rand/ to avoid - compiler warning. - -2002-04-12 David Turner - - * README.UNX: Updated the Unix-specific quick-compilation guide to - warn about the GNU Make requirement at compile time. - - * include/freetype/config/ftstdlib.h, - include/freetype/config/ftconfig.h, - include/freetype/config/ftheader.h, - include/freetype/internal/ftmemory.h, - include/freetype/internal/ftobjs.h, - - src/autohint/ahoptim.c, - - src/base/ftdbgmem.c, src/base/ftdebug.c, src/base/ftmac.c, - src/base/ftobjs.c, src/base/ftsystem.c, - - src/cache/ftcimage.c, src/cache/ftcsbits.c, - - src/cff/cffdrivr.c, src/cff/cffload.c, src/cff/cffobjs.c, - - src/cid/cidload.c, src/cid/cidparse.c, src/cid/cidriver.c, - - src/pcf/pcfdriver.c, src/pcf/pcfread.c, - - src/psaux/t1cmap.c, src/psaux/t1decode.c, - - src/pshinter/pshalgo1.c, src/pshinter/pshalgo2.c, - src/pshinter/pshrec.c, - - src/psnames/psmodule.c, - - src/raster/ftraster.c, - - src/sfnt/sfdriver.c, src/sfnt/ttload.c, - - src/smooth/ftgrays.c, - - src/type1/t1afm.c, src/type1/t1driver.c, src/type1/t1gload.c, - src/type1/t1load.c, src/type1/t1objs.c, src/type1/t1parse.c, - - builds/unix/ftconfig.in, builds/vms/ftconfig.h, - - builds/amiga/src/base/ftdebug.c: - - Added the new configuration file `ftstdlib.h' used to define - aliases for all ISO C library functions used by the engine - (e.g. strlen, qsort, setjmp, etc.). - - This eases the porting of FreeType 2 to environments like - XFree86 modules/extensions. - - Also removed many #include , #include , etc. - from the engine's sources where they are not needed. - - * src/sfnt/ttpost.c: Use macro name for psnames.h. - -2002-04-12 Vincent Caron - - * configure, builds/detect.mk: Updated the build system to print - a warning message in case GNU Make isn't used to build the library. - -2002-04-11 David Turner - - * README, docs/CHANGES, Jamfile.in: Updates for the 2.1.0 release. - - * docs/FTL.txt: Updated license text to provide a preferred - disclaimer and adjust copyright dates/extents. - - * include/freetype/cache/ftcglyph.h: Removing obsolete (and - confusing) comment. - - * Jamfile.in: New file. - -2002-04-11 Maxim Shemanarev - - * src/smooth/ftgrays.c (gray_hline): Minor optimization. - -2002-04-02 Werner Lemberg - - Fixes from the stable branch: - - * include/freetype/config/ftoption.h (FT_CONFIG_OPTION_OLD_CALCS): - Removed. - [FT_CONFIG_OPTION_OLD_CALCS]: Removed. - * include/freetype/internal/ftcalc.h, src/base/ftcalc.c - [FT_CONFIG_OPTION_OLD_CALCS]: Removed. - - * src/base/fttrigon.c (FT_Vector_Length): Change algorithm to match - output of FreeType 1. - - * src/pshinter/pshglob.c (psh_globals_scale_widths): Fixed a small - bug that created un-even stem widths when hinting Postscript fonts. - - * src/type1/t1driver.c, src/type1/t1parse.c: 16bit fixes. - -2002-04-01 Werner Lemberg - - * src/truetype/ttgload.c: 16bit fixes. - (TT_Load_Simple_Glyph): Improve debug messages. - (load_truetype_glyph): Remove dead code. - * src/truetype/ttinterp.c: 16bit fixes. - * src/truetype/ttobjs.c: Ditto. - - * include/freetype/ftsnames.h, include/freetype/internal/sfnt.h, - src/cff/cffload.h, src/psaux/psobjs.h, src/truetype/ttinterp.[ch], - src/sfnt/ttpost.h: s/index/idx/. - -2002-03-31 Yao Zhang - - * src/truetype/ttobjs.c (TT_Size_Init): Fix typo. - -2002-03-31 Werner Lemberg - - * src/otlayout/otlcommn.c, src/otlayout/otlcommn.h: s/index/idx/. - * src/psaux/t1cmap.c: Ditto. - * src/sfnt/ttcmap0.c: Ditto. - - * include/freetype/internal/tttypes.h, - include/freetype/internal/sfnt.h (TT_Goto_Table_Func): Renamed to ... - (TT_Loader_GotoTableFunc): This. - * src/psaux/t1decode.c (T1_Decoder_Parse_Charstrings): Fix debug - messages. - * src/psnames/psmodule.c (psnames_interface) - [!FT_CONFIG_OPTION_ADOBE_GLYPH_LIST]: Fix typo. - * src/sfnt/sfdriver.c (get_sfnt_table): 16bit fix. - * src/sfnt/ttcmap.c: 16bit fixes (0xFFFF -> 0xFFFFU). - * src/sfnt/ttcmap0.c: 16bit fixes. - (TT_Build_CMaps): Simplify debug messages. - (tt_cmap12_char_next): Fix offset. - * src/sfnt/ttload.c (TT_Load_Names, TT_Load_CMap): Fix debug - messages. - (TT_Load_OS2): 16bit fix. - -2002-03-30 David Turner - - * include/freetype/internal/tttypes.h: Adding comments to some of - the TT_FaceRec fields. - - * src/sfnt/ttcmap0.c (TT_Build_CMaps): Removed compiler warnings. - - * src/sfnt/sfobjs.c (tt_name_entry_ascii_from_{utf16,ucs4,other}: - New functions. - (tt_face_get_name): Use them to properly extract an ascii font name. - -2002-03-30 Werner Lemberg - - * include/freetype/t1tables.h (t1_blend_max): Fix typo. - * src/base/ftstream.c: Simplify FT_ERROR calls. - * src/cff/cffdrivr.c (cff_get_glyph_name): Fix debug message. - - * src/cff/cffobjs.c (CFF_Driver_Init, CFF_Driver_Done) - [TT_CONFIG_OPTION_EXTEND_ENGINE]: Removed. - * src/cff/sfobjs.c (SFNT_Load_Face) - [TT_CONFIG_OPTION_EXTEND_ENGINE]: Ditto. - * src/truetype/ttobjs.c (TT_Init_Driver, TT_Done_Driver) - [TT_CONFIG_OPTION_EXTEND_ENGINE]: Ditto. - - * src/truetype/ttdriver.c, src/truetype/ttobjs.c, - src/truetype/ttobjs.h: Renaming driver functions to the - FT__ scheme: - - TT_Init_Driver => TT_Driver_Init - TT_Done_Driver => TT_Driver_Done - TT_Init_Face => TT_Face_Init - TT_Done_Face => TT_Face_Done - TT_Init_Size => TT_Size_Init - TT_Done_Size => TT_Size_Done - TT_Reset_Size => TT_Size_Reset - -2002-03-29 Werner Lemberg - - * builds/vms/ftconfig.h: Rename LOCAL_DEF and LOCAL_FUNC to - FT_LOCAL and FT_LOCAL_DEF, respectively, as with other ftconfig.h - files. - * builds/unix/ftconfig.in: Add argument to FT_LOCAL and - FT_LOCAL_DEF. - * src/truetype/ttinterp.c: s/FT_Assert/FT_ASSERT/. - * builds/unix/configure.ac: Temporarily deactivate creation of - ../../Jamfile. - * builds/unix/configure: Updated. - -2002-03-28 KUSANO Takayuki - - * src/sfnt/sfdriver.c (get_sfnt_postscript_name): Fix serious typos. - -2002-03-28 Werner Lemberg - - * include/freetype/internal/psaux.h (PSAux_ServiceRec): Fix - compiler warnings. - * include/freetype/internal/t1types.h (T1_FaceRec): Use `const' for - some members. - * src/base/ftapi.c (FT_New_Memory_Stream): Fix typos. - * src/psaux/t1cmap.c (t1_cmap_std_init, t1_cmap_unicode_init): Add - cast. - (t1_cmap_{standard,expert,custom,unicode}_class_rec): Use - `FT_CALLBACK_TABLE_DEF'. - * src/psaux/t1cmap.h: Updated. - * src/sfnt/ttcmap0.c (TT_Build_CMaps): Use `ft_encoding_none' - instead of zero. - * src/type1/t1objs.c (T1_Face_Init): Use casts. - -2002-03-26 David Turner - - * src/sfnt/sfdriver.c, src/sfnt/sfobjs.c, src/sfnt/ttcmap0.c: - Fixed a small bug in the FT_CMaps support code. - -2002-03-25 David Turner - - * src/truetype/ttinterp.c (Norm): Replaced with... - (TT_VecLen): This. - (TT_MulFix14, TT_DotFix14): New functions. - (Project, Dual_Project, Free_Project, Compute_Point_Displacement, - Ins_SHPIX, Ins_MIAP, Ins_MIRP): Use them. - [FT_CONFIG_OPTION_OLD_CALCS]: Removed all code. - -2002-03-22 David Turner - - * src/base/ftobjs.c, src/sfnt/ttcmap0.c, src/type1/t1objs.c: - Various fixes to make the FT_CMaps support work correctly (more - tests are still needed). - - * include/freetype/internal/ftobjs.h, src/sfnt/Jamfile, - src/sfnt/rules.mk, src/sfnt/sfnt.c, src/sfnt/sfobjs.c, - src/sfnt/ttload.c, src/sfnt/ttcmap0.c, src/sfnt/ttcmap0.h: Updated - the SFNT charmap support to use FT_CMaps. - - * include/freetype/fterrdef.h: New file. - * include/freetype/fterrors.h: Include it. It contains all error - codes. - * include/freetype/config/ftheader.h (FT_ERROR_DEFINITIONS_H): New - macro. - - * include/freetype/internal/ftmemory.h, and a lot of other files: - Changed the names of memory macros. Examples: - - MEM_Set => FT_MEM_SET - MEM_Copy => FT_MEM_COPY - MEM_Move => FT_MEM_MOVE - - ALLOC => FT_ALLOC - FREE => FT_FREE - REALLOC = >FT_REALLOC - - FT_NEW was introduced to allocate a new object from a _typed_ - pointer. - - Note that ALLOC_ARRAY and REALLOC_ARRAY have been replaced by - FT_NEW_ARRAY and FT_RENEW_ARRAY which take _typed_ pointer - arguments. - - This results in _lots_ of sources being changed, but makes the code - more generic and less error-prone. - - * include/freetype/internal/ftstream.h, src/base/ftstream.c, - src/cff/cffload.c, src/pcf/pcfread.c, src/sfnt/ttcmap.c, - src/sfnt/ttcmap0.c, src/sfnt/ttload.c, src/sfnt/ttpost.c, - src/sfnt/ttsbit.c, src/truetype/ttgload.c, src/truetype/ttpload.c, - src/winfonts/winfnt.c: Changed the definitions of stream macros. - Examples: - - NEXT_Byte => FT_NEXT_BYTE - NEXT_Short => FT_NEXT_SHORT - NEXT_UShortLE => FT_NEXT_USHORT_LE - READ_Short => FT_READ_SHORT - GET_Long => FT_GET_LONG - etc. - - Also introduced the FT_PEEK_XXXX functions. - - * src/cff/cffobjs.c (CFF_Build_Unicode_Charmap): Removed commented - out function. - (find_encoding): Removed. - (CFF_Face_Init): Remove charmap support. - - * include/freetype/config/ftoption.h (FT_CONFIG_OPTION_USE_CMAPS, - TT_CONFIG_CMAP_FORMAT{0,2,4,6,8,10,12}): New macros to fine-tune - support of cmaps. - -2002-03-21 David Turner - - * src/base/ftobjs.c, src/pcf/pcfdriver.c, src/pcf/pcfread.c: Updated - to new FT_CMap definitions. - - * src/psaux/t1cmap.h, src/psaux/t1cmap.c, src/type1/t1cmap.h, - src/type1/t1cmap.c: Updating and moving the Type 1 FT_CMap support - from `src/type1' to `src/psaux' since it is going to be shared by - the Type 1 and CID font drivers. - - * src/psaux/Jamfile, src/psaux/psaux.c, src/psaux/psauxmod.c, - src/psaux/rules.mk, include/freetype/internal/psaux.h: Added support - for Type 1 FT_CMaps. - -2002-03-20 David Turner - - * src/base/ftgloadr.c (FT_GlyphLoader_CheckSubGlyphs): Fixed a - memory allocation bug that was due to un-careful renaming of the - FT_SubGlyph type. - - * src/base/ftdbgmem.c (ft_mem_table_destroy): Fixed a small bug that - caused the library to crash with Electric Fence when memory - debugging is used. - - * Renaming stream macros. Examples: - - FILE_Skip => FT_STREAM_SKIP - FILE_Read => FT_STREAM_READ - ACCESS_Frame => FT_FRAME_ENTER - FORGET_Frame => FT_FRAME_EXIT - etc. - - * src/sfnt/sfdriver.c (get_sfnt_postscript_name): Fixed memory leak. - - * include/freetype/internal/ftobjs.h: Changing the definition of - FT_CMap_CharNextFunc slightly. - - * src/cff/*.c: Updating CFF type definitions. - -2002-03-14 David Turner - - * include/freetype/internal/autohint.h, src/autohint/ahmodule.c, - src/base/ftapi.c, src/base/ftobjs.c: Updating the type definitions - for the auto-hinter module. - - FT_AutoHinter_Interface => FT_AutoHinter_ServiceRec - FT_AutoHinter_Interface* => FT_AutoHinter_Service - etc. - - FT_AutoHinter_Get_Global_Func => FT_AutoHinter_GlobalGetFunc - FT_AutoHinter_Done_Global_Func => FT_AutoHinter_GlobalDoneFunc - etc. - - * ahloader.h [_STANDALONE_]: Removed all conditional code. - - * include/freetype/internal/cfftypes.h, src/cff/*.c: Updating the - type definitions of the CFF font driver. - - CFF_Font => CFF_FontRec - CFF_Font* => CFF_Font - etc. - - * include/freetype/internal/fnttypes.h, src/winfonts/*.c: Updating - type definitions of the Windows FNT font driver. - - * include/freetype/internal/ftdriver.h, - include/freetype/internal/ftobjs.h, src/base/ftapi.c, - src/base/ftobjs.c, src/cff/cffdrivr.c, src/cff/cffdrivr.h, - src/cid/cidriver.c, src/cid/cidriver.h, src/pcf/pcfdriver.c, - src/pcf/pcfdriver.h, src/truetype/ttdriver.c, - src/truetype/ttdriver.h, src/type1/t1driver.c, src/type1/t1driver.h, - src/winfonts/winfnt.c, src/winfonts/winfnt.h: Updating type - definitions for font drivers. - - FTDriver_initFace => FT_Face_InitFunc - FTDriver_initGlyphSlot => FT_Slot_InitFunc - etc. - - * src/cid/cidobjs.c (CID_Face_Init): Remove dead code. - - * include/freetype/internal/ftobjs.h, src/base/ftobjs.c: Updated a - few face method definitions: - - FT_PSName_Requester => FT_Face_GetPostscriptNameFunc - FT_Glyph_Name_Requester => FT_Face_GetGlyphNameFunc - FT_Name_Index_Requester => FT_Face_GetGlyphNameIndexFunc - - * src/base/ftapi.c: New file. It contains backward compatibility - functions. - - * include/freetype/internal/psaux.h, src/cid/cidload.c, - src/cidtoken.h, src/psaux/psobjs.c, src/psaux/psobjs.h, - src/psaux/t1decode.c, src/type1/t1load.c, src/type1/t1tokens.h: - Updated common PostScript type definitions. - Renamed all enumeration values like to uppercase variants: - - t1_token_any => T1_TOKEN_TYPE_ANY - t1_field_cid_info => T1_FIELD_LOCATION_CID_INFO - etc. - - * include/freetype/internal/psglobal.h: Removed. - * include/freetype/internal/pshints.h, src/pshinter/pshglob.h: - Updated. - - * include/freetype/internal/tttypes.h, - include/freetype/internal/sfnt.h, src/base/ftnames.c, - src/cff/cffdrivr.c, src/sfnt/*.c, src/truetype/*.c: Updated - SFNT/TrueType type definitions. - - * include/freetype/freetype.h, include/freetype/internal/ftgloadr.h: - Updating type definitions for the glyph loader. - -2002-03-13 Antoine Leca - - * include/freetype/config/ftoption.h: Changed the automatic - detection of Microsoft C compilers to automatically support 64-bit - integers only since revision 9.00 (i.e. >= Visual C++ 2.0). - -2002-03-08 Werner Lemberg - - * src/base/ftutil.c (FT_Realloc): Use MEM_Set instead of memset. - -2002-03-07 Werner Lemberg - - * src/base/ftdbgmem.c (ft_mem_table_resize, ft_mem_table_new, - ft_mem_table_set, ft_mem_debug_alloc, ft_mem_debug_free, - ft_mem_debug_realloc, ft_mem_debug_done, FT_Alloc_Debug, - FT_Realloc_Debug, FT_Free_Debug): Fix compiler warnings. - * src/base/ftcalc.c (FT_MulFix): Ditto. - * src/cff/cffdrivr.c (cff_get_name_index): Ditto. - * src/cff/cffobjs.c (CFF_Size_Get_Globals_Funcs, CFF_Size_Init, - CFF_GlyphSlot_Init): Ditto. - * src/cid/cidobjs.c (CID_GlyphSlot_Init, - CID_Size_Get_Globals_Funcs): Ditto. - * src/type1/t1objs.c (T1_Size_Get_Globals_Funcs, T1_GlyphSlot_Init): - Ditto. - * src/pshinter/pshmod.c (pshinter_interface): Use `static const'. - * src/winfonts/winfnt.c (FNT_Get_Next_Char): Remove unused - variables. - - * include/freetype/internal/psaux.h (T1_Builder_Funcs): Renamed - to... - (T1_Builder_FuncsRec): This. - (T1_Builder_Funcs): New typedef. - (PSAux_Interface): Remove compiler warnings. - * src/psaux/psauxmod.c (t1_builder_funcs), src/psaux/psobjs.h - (t1_builder_funcs): Updated. - - * src/pshinter/pshglob.h (PSH_Blue_Align): Replaced with ... - (PSH_BLUE_ALIGN_{NONE,TOP,BOT}): New defines. - (PSH_AlignmentRec): Updated. - - * include/freetype/internal/ftstream.h (GET_Char, GET_Byte): Fix - typo. - * include/freetype/internal/ftgloadr.h (FT_SubGlyph): Ditto. - * src/base/ftstream (FT_Get_Char): Rename to... - (FT_Stream_Get_Char): This. - - * src/base/ftnames.c (FT_Get_Sfnt_Name): s/index/idx/ -- `index' is - a built-in function in gcc, causing warning messages with gcc 3.0. - * src/autohint/ahglyph.c (ah_outline_load): Ditto. - * src/autohint/ahglobal.c (ah_hinter_compute_blues): Ditto. - * src/cache/ftcmanag.c (ftc_family_table_alloc, - ftc_family_table_free, FTC_Manager_Done, FTC_Manager_Register_Cache): - Ditto. - * src/cff/cffload.c (cff_new_index, cff_done_index, - cff_explicit_index, CFF_Access_Element, CFF_Forget_Element, - CFF_Get_Name, CFF_Get_String, CFF_Load_SubFont, CFF_Load_Font, - CFF_Done_Font): Ditto. - * src/psaux/psobjs.c (PS_Table_Add, PS_Parser_LoadField): Ditto. - * src/psaux/t1decode.c (T1_Decoder_Parse_Charstrings): Ditto. - * src/pshinter/pshrec.c (ps_mask_test_bit, ps_mask_clear_bit, - ps_mask_set_bit, ps_dimension_add_t1stem, ps_hints_t1stem3, - * src/pshinter/pshalgo1.c (psh1_hint_table_record, - psh1_hint_table_record_mask, psh1_hint_table_activate_mask): Ditto. - * src/pshinter/pshalgo2.c (psh2_hint_table_record, - psh2_hint_table_record_mask, psh2_hint_table_activate_mask): Ditto. - * src/sfnt/ttpost.c (Load_Format_20, Load_Format_25, - TT_Get_PS_Name): Ditto. - * src/truetype/ttgload.c (TT_Get_Metrics, Get_HMetrics, - load_truetype_glyph): Ditto. - * src/type1/t1load.c (parse_subrs, T1_Open_Face): Ditto. - * src/type1/t1afm.c (T1_Get_Kerning): Ditto. - * include/freetype/cache/ftcmanag.h (ftc_family_table_free): Ditto. - -2002-03-06 David Turner - - * src/type1/t1objs.c (T1_Face_Init), src/cid/cidobjs.c - (CID_Face_Init): Fixed another bug related to the - ascender/descender/text height of Postscript fonts. - - * src/pshinter/pshalgo2.c (print_zone): Renamed to ... - (psh2_print_zone): This. - * src/pshinter/pshalgo1.c (print_zone): Renamed to ... - (psh1_print_zone): This. - - * include/freetype/freetype.h, include/freetype/internal/ftobjs.h, - src/base/ftobjs.c: Adding the new FT_Library_Version API to return - the library's current version in dynamic links. - * src/base/ftinit.c (FT_Init_FreeType): Updated. - -2002-03-06 Werner Lemberg - - * src/pshinter/pshglob.h (PSH_DimensionRec): s/std/stdw/. - * src/pshinter/pshglob.c (psh_global_scale_widths, - psh_dimension_snap_width, psh_globals_destroy, psh_globals_new): - Ditto. - -2002-03-05 David Turner - - * src/type1/t1objs.c (T1_Face_Init), src/cff/cffobjs.c - (CFF_Face_Init), src/cid/cidobjs.c (CID_Face_Init): Removing the bug - that returned global BBox values in 16.16 fixed format (instead of - integer font units). - - * src/cid/cidriver.c (cid_get_postscript_name): Fixed a bug that - caused the CID driver to return Postscript font names with a leading - slash (`/') as in `/MOEKai-Regular'. - - * src/sfnt/ttload.c (TT_Load_Names), src/sfnt/sfobjs.c (Get_Name), - src/sfnt/sfdriver.c (get_sfnt_postscript_name): Fixed the loader so - that it accepts broken fonts like `foxjump.ttf', which made FreeType - crash when trying to load them. - - Also improved the name table parser to be able to load - Windows-encoded entries before Macintosh or Unicode ones, since it - seems some fonts don't have reliable values here anyway. - - * include/freetype/internal/psnames.h: Add typedef for - `PSNames_Service'. - -2002-03-05 Werner Lemberg - - * builds/unix/aclocal.m4, builds/unix/ltmain.sh: Update to libtool - 1.4.2. - Apply a small patch for AIX to make shared libraries work (this - patch is already in the CVS version of libtool). - - * builds/unix/config.sub, builds/unix/config.guess: Updated to - recent versions. - - * builds/unix/configure.ac: Fix typo - (AC_CONFIG_FILE->AC_CONFIG_FILES). - - * builds/unix/configure: Regenerated. - -2002-02-28 David Turner - - * include/freetype/ftconfig.h: Changed `FT_LOCAL xxxx' to - `FT_LOCAL( xxxx )' everywhere in the source. The same goes for - `FT_LOCAL_DEF xxxx' which is translated to `FT_LOCAL_DEF( xxxxx )'. - - * include/freetype/freetype.h (FREETYPE_MINOR, FREETYPE_PATCH): - Changing version to 2.1.0 to indicate an unstable branch. - Added the declarations of FT_Get_First_Char and FT_Get_Next_Char. - - * src/base/ftobjs.c: Implement FT_Get_First_Char and - FT_Get_Next_Char. - - * include/freetype/t1tables.h: Renaming structure types. This - - typedef T1_Struct_ - { - } T1_Struct; - - becomes - - typedef PS_StructRec_ - { - } PS_StructRec, *PS_Struct; - - typedef PS_StructRec T1_Struct; /* backward compatibility */ - - Hence, we increase the coherency of the source code by effectively - using the `Rec' prefix for structure types. - -2002-02-27 David Turner - - * src/sfnt/ttload.c (TT_Load_Names): Simplifying and securing the - names table loader. Invalid individual name entries are now handled - correctly. This allows the loading of very buggy fonts like - `foxjump.ttf' without allocating tons of memory and causing crashes. - - * src/otlayout/otlcommon.h, src/otlayout/otlcommon.c: Adding (still - experimental) code for OpenType Layout tables validation and - parsing. - - * src/type1/t1cmap.h, src/type1/t1cmap.c: Adding (still - experimental) code for Type 1 charmap processing. - - * src/sfnt/ttcmap0.c: New file. It contains a new, still - experimental SFNT charmap processing support. - - * include/freetype/internal/ftobjs.h: Adding validation support as - well as internal charmap object definitions (FT_CMap != FT_CharMap). - -2002-02-24 David Turner - - * Renaming stream functions to the FT__ scheme: - - FT_Seek_Stream => FT_Stream_Seek - FT_Skip_Stream => FT_Stream_Skip - FT_Read_Stream => FT_Stream_Read - FT_Read_Stream_At => FT_Stream_Read_At - FT_Access_Frame => FT_Stream_Enter_Frame - FT_Forget_Frame => FT_Stream_Exit_Frame - FT_Extract_Frame => FT_Stream_Extract_Frame - FT_Release_Frame => FT_Stream_Release_Frame - FT_Get_XXXX => FT_Stream_Get_XXXX - FT_Read_XXXX => FT_Stream_Read_XXXX - - FT_New_Stream( filename, stream ) => - FT_Stream_Open( stream, filename ) - - (The function doesn't create the FT_Stream structure, it simply - initializes it for reading.) - - FT_New_Memory_Stream( library, FT_Byte* base, size, stream ) => - FT_Stream_Open_Memory( stream, const FT_Byte* base, size ) - - FT_Done_Stream => FT_Stream_Close - FT_Stream_IO => FT_Stream_IOFunc - FT_Stream_Close => FT_Stream_CloseFunc - - ft_close_stream => ft_ansi_stream_close (in base/ftsystem.c only) - ft_io_stream => ft_ansi_stream_io (in base/ftsystem.c only) - - * src/base/ftutil.c: New file. Contains all memory and list - management code (previously in `ftobjs.c' and `ftlist.c', - respectively). - - * include/freetype/internal/ftobjs.h: Moving all code related to - glyph loaders to ... - * include/freetype/internal/ftgloadr.h: This new file. - `FT_GlyphLoader' is now a pointer to the structure - `FT_GlyphLoaderRec'. - (ft_glyph_own_bitmap): Renamed to ... - (FT_GLYPH_OWN_BITMAP): This. - * src/base/ftobjs.c: Moving all code related to glyph loaders - to ... - * src/base/ftgloadr.c: This new file. - -2002-02-22 Werner Lemberg - - * include/freetype/internal/ftdebug.h (FT_Trace): Remove comma in - enum to avoid compiler warnings. - -2002-02-21 David Turner - - Modified the debug sub-system initialization. Trace levels can now - be specified within the `FT2_DEBUG' environment variable. See the - comments within `ftdebug.c' for more details. - - * src/base/ftdebug.c: (FT_SetTraceLevel): Removed. - (ft_debug_init): New function. - (ft_debug_dummy): Removed. - Updated to changes in ftdebug.h - - * include/freetype/internal/ftdebug.h: Always define - FT_DEBUG_LEVEL_ERROR if FT_DEBUG_LEVEL_TRACE is defined. - (FT_Assert): Renamed to ... - (FT_ASSERT): This. - Some stuff from ftdebug.h has been moved to ... - - * include/freetype/internal/fttrace.h: New file, to define the trace - levels used for debugging. It is used both to define enums and - toggle names for FT2_DEBUG. - - * include/freetype/internal/internal.h: Updated. - - * src/base/ftobjs.c, src/base/ftstream.c: Updated. - - * include/freetype/internal/ftextend.h, src/base/ftextend.c: - Removed. Both files are now completely obsolete. - * src/base/Jamfile, src/base/rules.mk: Updated. - - * include/freetype/fterrors.h: Adding `#undef FT_ERR_CAT' and - `#undef FT_ERR_XCAT' to avoid warnings with certain compilers (like - LCC). - - * src/pshinter/pshalgo2.c (print_zone): Renamed to ... - (psh2_print_zone): This to avoid errors during compilation of debug - library. - - * src/smooth/ftgrays.c (FT_COMPONENT): Change definition to as - `trace_smooth'. - -2002-02-20 David Turner - - * README: Adding `devel@freetype.org' address for bug reports. - -2002-02-20 Werner Lemberg - - * builds/unix/install.mk (check): New dummy target. - (.PHONY): Add it. - -2002-02-19 Werner Lemberg - - * builds/freetype.mk (FT_CFLAGS): Use $(INCLUDE_FLAGS) first. - - * src/cache/ftccache.c (ftc_cache_resize): Mark `error' as unused - to avoid compiler warning. - * src/cff/cffload.c (CFF_Get_String): Ditto. - * src/cff/cffobjs.c (CFF_StrCopy): Ditto. - * src/psaux/psobjs.c (PS_Table_Done): Ditto. - * src/pcf/pcfread.c (pcf_seek_to_table_type): Ditto. - * src/sfnt/sfdriver.c (get_sfnt_postscript_name): Ditto. - (pcf_get_bitmaps): The same for `sizebitmaps'. - * src/psaux/t1decode.c (T1_Decoder_Parse_Charstrings): The same for - `orig_y'. - (t1operator_seac): Comment out more dead code. - * src/pshinter/pshalgo2.c (ps2_hints_apply): Add `DEBUG_HINTER' - conditional. - * src/truetype/ttgload.c (TT_Process_Simple_Glyph, - load_truetype_glyph): Add `TT_CONFIG_OPTION_BYTECODE_INTERPRETER' - conditional. - -2002-02-18 Werner Lemberg - - * src/autohint/ahglyph.c (ah_outline_link_segments): Remove unused - variables. - * src/autohint/ahhint.c (ah_align_serif_edge): Use FT_UNUSED instead - of UNUSED. - * src/autohint/ahmodule.c (ft_autohinter_reset): Ditto. - * src/pshinter/pshrec.c (ps_mask_table_merge): Fix typo in variable - swapping code. - * src/pshinter/pshglob.h (PSH_Blue_Align): Add PSH_BLUE_ALIGN_NONE. - * src/pshinter/pshglob.c (psh_blues_snap_stem): Use it. - * src/pshinter/pshalgo1.c (psh1_hint_table_optimize): Ditto. - * src/pshinter/pshalgo2.c (psh2_hint_align): Ditto. - * include/freetype/internal/ftobjs.h (UNUSED): Removed. - -2002-02-10 Roberto Alameda - - Add support for ISOLatin1 PS encoding. - - * include/freetype/freetype.h (ft_encoding_latin_1): New tag - (`lat1'). - * include/freetype/internal/t1types.h (T1_Encoding_Type): Add - `t1_encoding_isolatin1'. - * src/type1/t1driver.c (Get_Char_Index, Get_Next_Char): Handle - ft_encoding_latin_1. - * src/type1/t1load.c (parse_encoding): Handle `ISOLatin1Encoding'. - * src/type1/t1objs.c (T1_Face_Init): Handle `t1_encoding_isolatin1'. - ----------------------------------------------------------------------------- - -Copyright (C) 2002-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, modified, -and distributed under the terms of the FreeType project license, -LICENSE.TXT. By continuing to use, modify, or distribute this file you -indicate that you have read the license and understand and accept it -fully. - - -Local Variables: -version-control: never -coding: utf-8 -End: diff --git a/lib/libesp32_lvgl/freetype/ChangeLog.22 b/lib/libesp32_lvgl/freetype/ChangeLog.22 deleted file mode 100644 index 86662f6e3..000000000 --- a/lib/libesp32_lvgl/freetype/ChangeLog.22 +++ /dev/null @@ -1,2837 +0,0 @@ -2006-05-12 Werner Lemberg - - - * Version 2.2.1 released. - ========================= - - - Tag sources with `VER-2-2-1'. - -2006-05-12 Werner Lemberg - - * src/tools/docmaker/sources.py (re_source_keywords): Add word - boundary markers. - * src/tools/docmaker/content.py (re_field): Allow `.' in field names - (but not at the beginning or end). - * src/tools/docmaker/tohtml.py (html_header_1): Use `utf-8' charset. - (block_footer): Split into... - (block_footer_start, block_footer_middle, block_footer_end): This to - add navigation buttons. - (HtmlFormatter::block_exit): Updated. - - * include/freetype/*: Many minor documentation improvements (adding - links, spelling errors, etc.). - -2006-05-11 Werner Lemberg - - * README: Minor updates. - - * include/freetype/*: s/scale/scaling value/ where appropriate. - Many other minor documentation improvements. - - * src/tools/docmaker/sources.py (re_italic, re_bold): Handle - trailing punctuation. - * src/tools/docmaker/tohtml.py (HtmlFormatter::make_html_word): Add - warning message for undefined cross references. - Update handling of re_italic and re_bold. - -2006-05-11 Masatake YAMATO - - * builds/unix/ftsystem.c (FT_Stream_Open): Check errno only if - read system call returns -1. - Remove a redundant parenthesis. - -2006-05-10 Werner Lemberg - - * builds/unix/ftsystem.c (FT_Stream_Open): Avoid infinite loop if - given an empty, un-mmap()able file. Reported and suggested fix in - Savannah bug #16555. - - * builds/freetype.mk (refdoc): Write-protect the `docmaker' - directory to suppress generation of .pyc files. According to the - Python docs there isn't a more elegant solution (currently). - - * builds/toplevel.mk (dist): New target which builds .tar.gz, - .tar.bz2, and .zip files. Note that the version number is still - hard-coded. - (do-dist): Sub-target of `dist'. - (CONFIG_GUESS, CONFIG_SUB): New variables. - (.PHONY): Updated. - -2006-05-09 Rajeev Pahuja - - * builds/win32/visualc/freetype.sln, - builds/win32/visualc/freetype.vcproj: Upgraded to VS.NET 2005 from - VS.NET 2003 - Added files ftbbox.c, fttype1.c, ftwinfnt.c, ftsynth.c. - - * builds/win32/visualc/index.html: Updated. - -2006-05-07 Werner Lemberg - - Put version information into the configure script. Reported by Paul - Watson . - - * builds/unix/configure.ac: Renamed to... - * builds/unix/configure.raw: This which now serves (with appropriate - modifications) as a template for configure.ac. - - * version.sed: New script. - - * autogen.sh: Generate configure.ac from configure.raw, using - FREETYPE_MAJOR, FREETYPE_MINOR, and FREETYPE_PATCH from freetype.h. - -2006-05-06 Werner Lemberg - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 1. - - * builds/unix/configure.ac (version_info): Set to 9:10:3. - - * builds/win32/visualc/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, builds/freetype.mk (refdoc), - Jamfile (RefDoc), README: s/220/221/, s/2.2.0/2.2.1/. - Minor updates. - - * docs/CHANGES, docs/VERSION.DLL, docs/PROBLEMS, README.CVS: - Updated. - - * builds/unix/install-sh: Updated from `texinfo' CVS module at - savannah.gnu.org. - - * devel/ftoption.h: Synchronize with - include/freetype/config/ftoption.h. - -2006-05-04 Werner Lemberg - - * src/lzw/ftlzw2.c: Renamed to... - * src/lzw/ftlzw.c: This. - - * src/lzw/Jamfile, src/lzw/rules.mk: Updated. - - * builds/mac/FreeType.m68k_cfm.make.txt, - builds/mac/FreeType.m68k_far.make.txt, - builds/mac/FreeType.ppc_carbon.make.txt, - builds/mac/FreeType.ppc_classic.make.txt: Updated. - -2006-05-03 David Turner - - Allow compilation again with C++ compilers. - - * include/freetype/internal/ftmemory.h (FT_ASSIGNP, - FT_ASSIGNP_INNER): New macros which do the actual assignment, and - which exist in two variants (for C and C++). - Update callers accordingly. - -2006-05-03 Werner Lemberg - - * include/freetype/config/ftoption.h (FT_STRICT_ALIASING): Removed. - -2006-05-02 Werner Lemberg - - * include/freetype/internal/ftmemory.h: s/new/newsz/ (for C++). - (FT_ALLOC): Remove redundant redefinition. - - * builds/compiler/gcc-dev.mk (CFLAGS) [g++]: Don't use - `-Wstrict-prototypes'. - - * src/base/ftstream.c (FT_Stream_EnterFrame): Add cast. - - * include/freetype/config/ftconfig.h (FT_BASE_DEF) [__cplusplus]: - Remove `extern'. - -2006-05-02 David Turner - - Update the memory management functions and macros to safely deal - with array size buffer overflows. This corresponds to attempts to - allocate arrays that are too large. For an example, consider the - following code: - - count = read_uint32_from_file(); array = malloc( sizeof ( Item ) * - count ); for ( nn = 0; nn < count; nn++ ) - array[nn] = read_item_from_file(); - - If `count' is larger than `FT_UINT_MAX/sizeof(Item)', the - multiplication overflows, and the array allocated os smaller than - the data read from the file. In this case, the heap will be - trashed, and this can be used as a denial-of-service attack, or make - the engine crash later. - - The FT_ARRAY_NEW and FT_ARRAY_RENEW macros now ensure that the new - count is no larger than `FT_INT_MAX/item_size', otherwise a new - error code `FT_Err_Array_Too_Large' will be returned. - - Note that the memory debugger now works again when FT_DEBUG_MEMORY - is defined. FT_STRICT_ALIASING has disappeared; the corresponding - code is now the default. - - - * include/freetype/config/ftconfig.h (FT_BASE_DEF) [!__cplusplus]: - Don't use `extern'. - - * include/freetype/fterrdef.h (FT_Err_Array_Too_Large): New error - code. - - * include/freetype/internal/ftmemory.h (FT_DEBUG_INNER) - [FT_DEBUG_MEMORY]: New macro. - (ft_mem_realloc, ft_mem_qrealloc): Pass new object size count also. - (ft_mem_alloc_debug, ft_mem_qalloc_debug, ft_mem_realloc_debug, - ft_mem_qrealloc_debug, ft_mem_free_debug): Removed. - (FT_MEM_ALLOC, FT_MEM_REALLOC, FT_MEM_QALLOC, FT_MEM_QREALLOC, - FT_MEM_FREE): Redefine. - (FT_MEM_NEW_ARRAY, FT_MEM_RENEW_ARRAY, FT_MEM_QNEW_ARRAY, - FT_MEM_QRENEW_ARRAY): Redefine. - (FT_ALLOC_MULT, FT_REALLOC_MULT, FT_MEM_QALLOC_MULT, - FT_MEM_QREALLOC_MULT): New macros. Update callers where - appropriate. - (FT_MEM_SET_ERROR): Slightly redefine. - - - * src/base/ftdbgmem.c (_ft_debug_file, _ft_debug_lineno) - [FT_DEBUG_MEMORY]: New global variables, replacing... - (FT_MemTableRec) [FT_DEBUG_MEMORY]: Remove `filename' and - `line_no'. Update all callers. - (ft_mem_debug_alloc) [FT_DEBUG_MEMORY]: Avoid possible integer - overflow. - (ft_mem_alloc_debug, ft_mem_realloc_debug, ft_mem_qalloc_debug, - ft_mem_qrealloc_debug, ft_mem_free_debug): Removed. - - * src/base/ftmac.c (read_lwfn): Catch integer overflow. - * src/base/ftrfork.c (raccess_guess_darwin_hfsplus): Ditto. - * src/base/ftutil.c: Remove special code for FT_STRICT_ALIASING. - (ft_mem_alloc, ft_mem_realloc, ft_mem_qrealloc): Rewrite. - - - * include/freetype/ftstream.h (FT_FRAME_ENTER, FT_FRAME_EXIT, - FT_FRAME_EXTRACT, FT_FRAME_RELEASE): Use FT_DEBUG_INNER to report the - place where the frames were entered, extracted, exited or released - in the memory debugger. - - * src/base/ftstream.c (FT_Stream_ReleaseFrame) [FT_DEBUG_MEMORY]: - Call ft_mem_free. - (FT_Stream_EnterFrame) [FT_DEBUG_MEMORY]: Use ft_mem_qalloc. - (FT_Stream_ExitFrame) [FT_DEBUG_MEMORY]: Use ft_mem_free. - -2006-04-30 suzuki toshiya - - * src/base/ftobjs.c (Mac_Read_POST_Resource): Correct pfb_pos - initialization, remove extra cast to copy to pfb_lenpos. This fixes - parsing of PFB fonts with MacOS resource fork (bug introduced - 2003-09-11). Patch provided by Huib-Jan Imbens . - -2006-04-29 Werner Lemberg - - Further C library abstraction. Based on a patch from - msn2@bidyut.com. - - * include/freetype/config/ftstdlib.h (FT_CHAR_BIT, FT_FILE, - ft_fopen, ft_fclose, ft_fseek, ft_ftell, ft_fread, ft_smalloc, - ft_scalloc, ft_srealloc, ft_sfree, ft_labs): New wrapper macros for - C library functions. Update all users accordingly (and catch some - other places where the C library function was used instead of the - wrapper functions). - - * src/base/ftsystem.c: Don't include stdio.h and stdlib.h. - * src/gzip/zutil.h [MSDOS && !(__TURBOC__ || __BORLANDC__)]: Don't - include malloc.h. - - - * builds/unix/unix-def.in (datarootdir): Define, for autoconf 2.59c - and forthcoming versions. - -2006-04-28 Werner Lemberg - - * src/lzw/ftlzw.c, src/lzw/zopen.c, src/lzw/zopen.h: Removed, - obsolete. - -2006-04-27 yi luo - - * builds/win32/visualc/freetype.vcproj: Updated. - -2006-04-26 David Turner - - - * Version 2.2 released. - ======================= - - - Tag sources with `VER-2-2-0'. - -2006-04-26 Werner Lemberg - - * src/psaux/psobjs.c (shift_elements): Don't use FT_Long but - FT_PtrDist for `delta'. Reported by Céline PILLET - . - -2006-04-21 David Turner - - * include/freetype/ftincrem.h: Documentation updates. - (FT_Incremental_Interface): New typedef. - - * include/freetype/ftmodapi.h, include/freetype/ftglyph.h: - Documentation updates. - - * include/freetype/freetype.h: Documentation update. - (FT_HAS_FAST_GLYPHS): Always set to 0. - - * include/freetype/ftstroke.h, src/base/ftstroke.c (FT_Stroker_New): - Take an FT_Library argument instead of FT_Memory. - - * src/sfnt/ttcmap.c: Remove compiler warnings (gcc-4.0.2). - -2006-04-13 David Turner - - * src/autofit/afloader.c (af_loader_init, af_loader_load_g): Remove - superfluous code in the auto-fitter's loader. - -2006-04-05 Detlef Würkner - - * builds/amiga/makefile, builds/amiga/makefile.os4, - builds/amiga/smakefile: Added FT2_BUILD_LIBRARY define. - -2006-04-03 luoyi - - * builds/compiler/intelc.mk (TE): New variable. - (ANSIFLAGS): Updated. - -2006-04-03 Werner Lemberg - - * builds/exports.mk (clean_symbols_list, clean_apinames): Removed. - (CLEAN): Add $(EXPORTS_LIST) and $(APINAMES_EXE). - (.PHONY): Updated. - - * configure.ac: Minor fixes to improve --help output. - - - * docs/PROBLEMS: New file. - -2006-04-01 David Turner - - * docs/CHANGES: Updated. - - * include/freetype/ftcache.h, include/freetype/config/ftheader.h: - Update documentation comments. - -2006-04-01 Werner Lemberg - - * builds/unix/install.mk (uninstall): Don't handle `cache' - directory which no longer exists. - -2006-03-29 Detlef Würkner - - * src/psaux/psconv.c: Changed some variables which are expected to - hold negative values from `char' to `FT_Char' to allow building with - a compiler where `char' is unsigned by default. - -2006-03-27 David Turner - - * src/sfnt/ttkern.c (tt_face_get_kerning): Fix a serious bug that - causes some programs to go into an infinite loop when dealing with - fonts that don't have a properly sorted kerning sub-table. - -2006-03-26 Werner Lemberg - - * src/bdf/bdflib.c (ERRMSG4): New macro. - (_bdf_parse_glyphs): Handle invalid BBX values. - - * include/freetype/fterrdef.h (FT_Err_Bbx_Too_Big): New error - macro. - -2006-03-23 Werner Lemberg - - * docs/CHANGES: Updated. - - - * src/tools/docmaker/tohtml.py (html_header_2): Add horizontal - padding between table elements. - (html_header_1): The `DOCTYPE' comment must be in uppercase. - (make_html_para): Convert `...' quotations into real left and - right single quotes. - Use `para_header' and `para_footer'. - - * src/tools/docmaker/sources.py (re_bold, re_italic): Accept "'" - also. - -2006-03-23 David Turner - - Add FT_Get_SubGlyph_Info API to retrieve subglyph data. Note that - we do not expose the FT_SubGlyphRec structure. - - * include/freetype/internal/ftgloadr.h (FT_SUBGLYPH_FLAGS_*): Moved - to... - * include/freetype/freetype.h (FT_SUBGLYPH_FLAGS_*): Here. - (FT_Get_SubGlyph_Info): New declaration. - - * src/base/ftobjs.c (FT_Get_SubGlyph_Info): New function. - - - * src/autofit/afloader.c (af_loader_load_g): Compute lsb_delta and - rsb_delta correctly in edge cases. - -2006-03-22 Werner Lemberg - - * src/cache/ftccache.c, (ftc_node_mru_up, FTC_Cache_Lookup) - [!FTC_INLINE]: Compile conditionally. - * src/cache/ftccache.h: Updated. - - * src/cache/ftcglyph.c (FTC_GNode_Init, FTC_GNode_UnselectFamily, - FTC_GNode_Done, FTC_GNode_Compare, FTC_Family_Init, FTC_GCache_New): - s/FT_EXPORT/FT_LOCAL/. - (FTC_GCache_Init, FTC_GCache_Done): Commented out. - (FTC_GCache_Lookup) [!FTC_INLINE]: Compile conditionally. - s/FT_EXPORT/FT_LOCAL/. - * src/cache/ftcglyph.h: Updated. - - * src/cache/ftcimage.c (FTC_INode_Free, FTC_INode_New): - s/FT_EXPORT/FT_LOCAL/. - (FTC_INode_Weight): Commented out. - * src/cache/ftcimage.h: Updated. - - * src/cache/ftcmanag.c (FTC_Manager_Compress, - FTC_Manager_RegisterCache, FTC_Manager_FlushN): - s/FT_EXPORT/FT_LOCAL/. - * src/cache/ftcmanag.h: Updated. - - * src/cache/ftcsbits.c (FTC_SNode_Free, FTC_SNode_New, - FTC_SNode_Compare): s/FT_EXPORT/FT_LOCAL/. - (FTC_SNode_Weight): Commented out. - * src/cache/ftcsbits.h: Updated. - -2006-03-22 Werner Lemberg - - * src/cache/ftccache.c, src/cache/ftccache.h (FTC_Node_Destroy): - Remove, unused. - - * src/cache/ftccmap.h: Remove, unused. - - * src/cache/rules.mk (CACHE_DRV_H): Remove ftccmap.h. - -2006-03-21 Zhe Su - - * src/base/ftoutln.c (FT_Outline_Get_Orientation): Improve - algorithm. - -2006-03-21 Werner Lemberg - - * src/cff/cfftypes.h (CFF_CharsetRec): Add `max_cid' member. - - * src/cff/cffload.c (cff_charset_load): Set `charset->max_cid'. - - * src/cff/cffgload.c (cff_slot_load): Change type of third parameter - to `FT_UInt'. - Check range of `glyph_index'. - * src/cff/cffgload.h: Updated. - - - * src/sfnt/ttcmap.c (tt_face_build_cmaps): Handle invalid offset - correctly. - - - * builds/freetype.mk (refdoc), docs/CHANGES, Jamfile (RefDoc), - README: s/2.1.10/2.2/. - -2006-03-21 David Turner - - * src/autofit/aflatin.c (af_latin_metrics_scale): Fix small bug - that crashes the auto-hinter (introduced by previous patch). - -2006-03-20 Werner Lemberg - - * builds/freetype.mk (CACHE_DIR, CACHE_H): Remove. - (FREETYPE_H): Updated. - - * src/cache/rules.mk (CACHE_H_DIR): Remove. - (CACHE_DRV_H): Updated. - -2006-03-20 David Turner - - * include/freetype/cache/ftccache.h, - include/freetype/cache/ftccmap.h, include/freetype/cache/ftcglyph.h - include/freetype/cache/ftcimage.h include/freetype/cache/ftcmanag.h - include/freetype/cache/ftcmru.h include/freetype/cache/ftcsbits.h: - Move to... - - * src/cache/ftccache.h, src/cache/ftcglyph.h, src/cache/ftcimage.h, - src/cache/ftcsbits.h, src/cache/ftcmanag.h, src/cache/ftccmap.h, - src/cache/ftcmru.h: This new location. - Update declarations according to the changes in the corresponding - source files. - - Note that these files are not used by FreeType clients; all public - APIs of the cache module have been already moved to - `include/freetype/ftcache.h', and all FT_CACHE_INTERNAL_XXXX_H - macros resolve to it. - - Reason for the move is to allow modifications of the internals - without interferences with rogue clients. Note that there are no - known clients that access the cache internals at the moment. - - * builds/unix/install.mk (install): Don't install headers from - $(CACHE_H). - Remove `freetype/cache' from the target directory. - - * include/freetype/config/ftheader.h (FT_CACHE_MANAGER_H, - FT_CACHE_INTERNAL_MRU_H, FT_CACHE_INTERNAL_MANAGER_H, - FT_CACHE_INTERNAL_CACHE_H, FT_CACHE_INTERNAL_GLYPH_H, - FT_CACHE_INTERNAL_IMAGE_H, FT_CACHE_INTERNAL_SBITS_H): Point to - FT_CACHE_H. - - * src/cache/ftcbasic.c, src/cache/ftccache.h, src/cache/ftccback.h, - src/cache/ftccmap.c, src/cache/ftcglyph.c, src/cache/ftcglyph.h, - src/cache/ftcimage.c, src/cache/ftcimage.h, src/cache/ftcmanag.c, - src/cache/ftcmanag.h, src/cache/ftcmru.h, src/cache/ftcsbits.c, - src/cache/ftcsbits.h: Don't use the FT_CACHE_INTERNAL_XXX_H macros - but include the headers directly (which are now in `src/cache'). - - * src/cache/ftccache.c: Don't use the FT_CACHE_INTERNAL_XXX_H - macros but include the headers directly. - (FTC_Cache_Init, FTC_Cache_Done, FTC_Cache_NewNode, - FTC_Cache_Lookup, FTC_Cache_RemoveFaceID): Declare as FT_LOCAL_DEF. - - * src/cache/ftccache.c: Don't use the FT_CACHE_INTERNAL_XXX_H - macros but include the headers directly. - (FTC_MruNode_Prepend, FTC_MruNode_Up, FTC_MruNode_Remove, - FTC_MruList_Init, FTC_MruList_Reset, FTC_MruList_Done, - FTC_MruList_New, FTC_MruList_Remove, FTC_MruList_RemoveSelection): - Declare as FT_LOCAL_DEF. - (FTC_MruList_Find, FTC_MruList_Lookup) [!FTC_INLINE]: Compile - conditionally. - Declare as FT_LOCAL_DEF. - - - * builds/win32/visualc/freetype.dsp: Update project file, add - missing base source files (ftstroke.c, ftxf86.c, etc.). - - - * src/autofit/afcjk.c, src/autofit/aflatin.c, src/base/ftobjs.c, - src/cff/cffobjs.c, src/cid/cidobjs.c, src/pfr/pfrobjs.c, - src/sfnt/sfobjs.c, src/sfnt/ttmtx.c, src/type1/t1afm.c, - src/type1/t1objs.c: Remove compiler warnings when building with - Visual C++ 6 and /W4. - - * src/autofit/aflatin.c (af_latin_hints_init): Disable horizontal - hinting for italic/oblique fonts. - - - - * src/truetype/ttpload.c, src/truetype/ttpload.h - (tt_face_get_device_metrics): Change second argument to `FT_UInt'. - -2006-03-06 David Turner - - * src/cache/ftcmanag.c (FTC_Manager_Lookup_Size): Prevent crashes in - Mozilla/FireFox print preview in Ubuntu Hoary. - -2006-02-28 Chia-I Wu - - * src/base/ftutil.c (ft_mem_qalloc) [FT_STRICT_ALIASING]: Do not - return error when size == 0. - -2006-02-28 Chia-I Wu - - * src/base/ftobjs.c (FT_Done_Library): Remove modules in reverse - order so that type42 module is removed before truetype module. This - avoids double free in some occasions. - -2006-02-28 David Turner - - * Release candidate VER-2-2-0-RC4. - ---------------------------------- - - * docs/CHANGES: Documentation updates. - -2006-02-28 suzuki toshiya - - * modules.cfg (BASE_EXTENSIONS): Compile in ftgxval.c by default to - build ftvalid in ft2demos. It works as dummy ABI if gxvalid is not - built. - -2006-02-27 Werner Lemberg - - * include/freetype/cache/ftccache.h - [FT_CONFIG_OPTION_OLD_INTERNALS]: Remove declaration of - ftc_node_done. - - * src/cache/ftccache.c (ftc_node_destroy) - [!FT_CONFIG_OPTION_OLD_INTERNALS]: Mark as FT_LOCAL_DEF. This - should now fix all possible compilation options. - -2006-02-27 David Turner - - * src/base/ftutil.c (ft_mem_alloc, ft_mem_qalloc, ft_mem_realloc, - ft_mem_qrealloc): Return an error if a negative size is passed in - parameters. - - * src/cache/ftccache.c (ftc_node_destroy): Mark as FT_BASE_DEF since - it needs to be exported for rogue clients. - - * src/pshinter/pshglob.c (psh_blues_set_zones_0): Prevent problems - with malformed fonts which have an odd number of blue values (these - are broken according to the specs). - - * src/cff/cffload.c (cff_subfont_load), src/type1/t1load.c - (T1_Open_Face): Modify the loaders to force even-ness of - `num_blue_values'. - - (cff_index_access_element): Ignore invalid entries in index files. - -2006-02-27 Chia-I Wu - - * src/base/ftobjs.c (FT_Set_Char_Size): Check the case where width - or height is 0. - -2006-02-27 suzuki toshiya - - * builds/mac/FreeType.m68k_cfm.make.txt, - builds/mac/FreeType.m68k_far.make.txt, - builds/mac/FreeType.ppc_carbon.make.txt, - builds/mac/FreeType.ppc_classic.make.txt: Update to new header - inclusion introduced on 2006-02-16. - -2006-02-27 Chia-I Wu - - * src/base/ftobjs.c (GRID_FIT_METRICS): New macro. - (ft_glyphslot_grid_fit_metrics, FT_Load_Glyph) [GRID_FIT_METRICS]: - Re-enable glyph metrics grid-fitting. It is now done in the base - layer. - (FT_Set_Char_Size, FT_Set_Pixel_Sizes): Make sure the width and - height are not too small or too large, just like we were doing in - 2.1.10. - - * src/autofit/afloader.c (af_loader_load_g): The vertical metrics - are not scaled. - -2006-02-26 Werner Lemberg - - * docs/release: Minor additions and clarifications. - - * docs/CHANGES: Updated to reflect many fixes for backward - compatibility. Still incomplete. - -2006-02-26 David Turner - - * src/base/ftobjs.c (ft_recompute_scaled_metrics): Re-enable - conservative rounding of metrics to avoid breaking clients like - Pango (see https://bugzilla.gnome.org/show_bug.cgi?id=327852). - -2006-02-25 Werner Lemberg - - * devel/ftoption.h: Synchronize with - include/freetype/config/ftoption.h. - - * src/cache/ftccache.c (ftc_node_destroy): Use FT_LOCAL_DEF (again). - -2006-02-25 David Turner - - Fix compiler warnings as well as C++ compilation problems. - Add missing prototypes. - - * src/autofit/afcjk.c, src/base/ftobjs.c, src/base/ftutil.c, - src/bdf/bdfdrivr.c, src/cff/cffcmap.c, src/cff/cffobjs.c, - src/psaux/afmparse.c,, src/psaux/t1cmap.c, src/smooth/ftgrays.c - src/tools/apinames.c, src/truetype/ttdriver.c: Add various casts, - initialize variables, and decorate functions with FT_CALLBACK_DEF, - etc., to fix compiler warnings (and C++ compiling errors). - - * src/cache/ftcbasic.c: Fix `-Wmissing-prototypes' warnings with - gcc. - - * builds/unix/ftsystem.c: Don't include FT_INTERNAL_OBJECTS_H but - FT_INTERNAL_STREAM_H. - - * src/base/ftsystem.c: Include FT_INTERNAL_STREAM_H. - - * include/freetype/config/ftheader.h (FT_PFR_H): New macro. - - * include/freetype/config/ftoption.h (FT_STRICT_ALIASING): Don't - define for C++. - - * include/freetype/internal/services/svotval.h: Don't include - FT_OPENTYPE_VALIDATE_H but FT_INTERNAL_VALIDATE_H. - - * include/freetype/internal/services/svpfr.h: Include FT_PFR_H. - - * src/gzip/ftgzip.c: Include FT_GZIP_H. - - * src/lzw/ftlzw.c, src/lzw/ftlzw2.c: Include FT_LZW_H. - - * src/sfnt/ttbdf.c (tt_face_load_bdf_props): Rearrange code. - -2006-02-24 Chia-I Wu - - * src/base/ftoutln.c (FT_OUTLINE_GET_CONTOUR, ft_contour_has, - ft_contour_enclosed, ft_outline_get_orientation): Commented out. We - have to wait until `FT_GlyphSlot_Own_Bitmap' is stabilized. - (FT_Outline_Embolden): Use `FT_Outline_Get_Orientation'. - -2006-02-24 Chia-I Wu - - * include/freetype/ftbitmap.h (FT_Bitmap_Embolden): Update - documentation. - - * include/freetype/ftsynth.h (FT_GlyphSlot_Own_Bitmap), - src/base/ftsynth.c (FT_GlyphSlot_Own_Bitmap): New function to make - sure a glyph slot owns its bitmap. It is also marked experimental - and due to change. - (FT_GlyphSlot_Embolden): Undo the last change. It turns out that - rendering the outline confuses some applications. - -2006-02-24 David Turner - - * Release candidate VER-2-2-0-RC3. - ---------------------------------- - - * src/cache/ftcbasic.c: Correct compatibility hack bug. - -2006-02-24 Chia-I Wu - - * include/freetype/freetype.h (FT_Size_RequestRec): Change the type - of `width' and `height' to `FT_Long'. - (enum FT_Size_Request_Type), src/base/ftobjs.c (FT_Request_Metrics): - New request type `FT_SIZE_REQUEST_TYPE_SCALES' to specify the scales - directly. - -2006-02-23 David Turner - - Two BDF patches from Debian libfreetype6 for 2.1.10. - - * src/bdf/bdflib.c (_bdf_parse_glyphs): Fix a bug with zero-width - glyphs. - Fix a problem with large encodings. - - - Fix binary compatibility issues for gnustep-back (GNUstep backend - module) which still crashes under Sarge. - - * src/cache/ftccmap.c (FTC_OldCMapType, FTC_OldCMapIdRec, - FTC_OldCMapDesc) [FT_CONFIG_OPTION_OLD_INTERNALS]: New data - structures and enumerations. - (FTC_CMapCache_Lookup) [FT_CONFIG_OPTION_OLD_INTERNALS]: New - compatibility code. - - * src/cache/ftcbasic.c: Fix a silly bug that prevented our `hack' to - support rogue clients compiled against 2.1.7 to work correctly. - This probably explains the GNUstep crashes with the second release - candidate. - -2006-02-23 Chia-I Wu - - * include/freetype/ftoutln.h (enum FT_Orientation): New value - `FT_ORIENTATION_NONE'. - - * src/base/ftoutln.c (FT_OUTLINE_GET_CONTOUR, ft_contour_has, - ft_contour_enclosed, ft_outline_get_orientation): Another version of - `FT_Outline_Get_Orientation'. This version differs from the public - one in that each part (contour not enclosed in another contour) of the - outline is checked for orientation. - (FT_Outline_Embolden): Use `ft_outline_get_orientation'. - - * src/base/ftsynth.c (FT_GlyphSlot_Embolden): Render the outline and - use bitmap's embolden routine when the outline one failed. - -2006-02-22 Chia-I Wu - - * modules.cfg: Compile in ftotval.c and ftxf86.c by default for ABI - compatibility. - - * src/sfnt/sfobjs.c (sfnt_done_face): Fix a memory leak. - - * src/sfnt/ttsbit0.c (tt_sbit_decoder_load_bit_aligned, - tt_sbit_decoder_load_byte_aligned) [FT_OPTIMIZE_MEMORY]: Fix sbit - loading. (Only tested with bit aligned sbit with x_pos == 0.) - - * src/truetype/ttpload.c (tt_face_load_hdmx, - tt_face_get_device_metrics) [FT_OPTIMIZE_MEMORY]: `hdmx' is not - actually used. - -2006-02-21 David Turner - - Add a new API named FT_Get_TrueType_Engine_Type to determine whether - we have a patented, unpatented, or unimplemented TrueType bytecode - interpreter. - - The FT_Get_Module_Flags API was removed consequently. - - * include/freetype/ftmodapi.h (FT_Module_Get_Flags): Removed. - Replaced with... - (FT_Get_TrueType_Engine_Type): This. - (FT_TrueTypeEngineType): New enumeration. - - * include/freetype/internal/ftserv.h (FT_SERVICE_TRUETYPE_ENGINE_H): - New macro. - - * src/base/ftobjs.c: Include FT_SERVICE_TRUETYPE_ENGINE_H. - (FT_Module_Get_Flags): Removed. Replaced with... - (FT_Get_TrueType_Engine_Type): This. - - * src/truetype/ttdriver.c: Include FT_SERVICE_TRUETYPE_ENGINE_H. - (tt_service_truetype_engine): New service structure. - (tt_services): Register it. - - * include/freetype/internal/services/svtteng.h: New file. - - - * src/sfnt/sfobjs.c (sfnt_load_face): Fix silly bug that prevented - embedded bitmaps from being correctly listed and used. - - - * src/sfnt/ttmtx.c (tt_face_load_hmtx): Disable memory optimization - if FT_CONFIG_OPTION_OLD_INTERNALS is used. The is necessary because - libXfont is directly accessing the HMTX data, unfortunately. - Fix some compiler warnings. - (tt_face_get_metrics): Ditto. - - - * src/pfr/pfrsbit.c (pfr_slot_load_bitmap): Fix handling of - character advances. - -2006-02-20 David Turner - - Support binary compatibility with the X.Org server's Xfont library. - Note that this change unfortunately prevents memory optimizations - for the embedded bitmap loader. - - * include/freetype/internal/sfnt.h (SFNT_Interface): Move - `set_sbit_strike' and `load_sbit_metrics' fields to the location of - version 2.1.8. - - * src/sfnt/sfdriver.c (tt_face_set_sbit_strike_stub): Call - FT_Size_Request. - (sfnt_interface): Updated. - - * src/sfnt/ttsbit.c [FT_CONFIG_OPTION_OLD_INTERNALS]: Don't load - ttsbit0.c. - (tt_load_sbit_metrics): Make `sbit_small_metrics_fields' static. - - * src/sfnt/ttsbit.h: Updated. - -2006-02-17 David Turner - - * builds/unix/unix-cc.in (LINK_LIBRARY): Don't filter out exported - functions anymore. This ensures that all FT_BASE internal functions - are available for dynamic linking. - - * include/freetype/ftcache.h (FTC_IMAGE_TYPE_COMPARE, - FTC_IMAGE_TYPE_HASH), src/cache/ftcbasic.c (FTC_OldFontRec, - FTC_OldImageDescRec, FTC_ImageCache_Lookup, FTC_Image_Cache_New, - FTC_OldImageDesc, FTC_OLD_IMAGE_FORMAT, ftc_old_image_xxx, - ftc_image_type_from_old_desc, FTC_Image_Cache_Lookup, - FTC_SBitCache_Lookup, FTC_SBit_Cache_New, FTC_SBit_Cache_Lookup) - [FT_CONFIG_OPTION_OLD_INTERNALS]: Try to revive old functions of the - cache sub-system. We try to recognize old legacy signatures with a - gross hack (hope it works). - -2006-02-17 Werner Lemberg - - * devel/ftoption.h: Synchronize with - include/freetype/config/ftoption.h. - -2006-02-16 David Turner - - Massive changes to the internals to respect the internal object - layouts and exported functions of FreeType 2.1.7. Note that the - cache sub-system cannot be fully retrofitted, unfortunately. - - * include/freetype/config/ftoption.h - (FT_CONFIG_OPTION_OLD_INTERNALS): New macro. - - * include/freetype/ftcache.h, include/freetype/cache/ftccache.h, - include/freetype/cache/ftccmap.h, - include/freetype/internal/ftcalc.h, - include/freetype/internal/ftdriver.h, - include/freetype/internal/ftmemory.h, - include/freetype/internal/ftobjs.h, - include/freetype/internal/psaux.h, include/freetype/internal/sfnt.h, - include/freetype/internal/t1types.h, - include/freetype/internal/tttypes.h, src/base/ftcalc.c, - src/base/ftdbgmem.c, src/base/ftobjs.c, src/base/ftutil.c, - src/bdf/bdfdrivr.c, src/cache/ftccache.c, src/cache/ftccback.h, - src/cache/ftcmanag.c, src/cff/cffdrivr.c, src/cid/cidriver.c, - src/pcf/pcfdrivr.c, src/pfr/pfrdrivr.c, src/psaux/psauxmod.c, - src/sfnt/sfdriver.c, src/truetype/ttdriver.c, src/type1/t1driver.c, - src/type1/t1objs.c, src/type42/t42drivr.c, src/winfonts/winfnt.c: - Use FT_CONFIG_OPTION_OLD_INTERNALS to revive old functions and data - structures. - - Move newly added structure elements to the end of the affected - structure and add stub fields (if FT_CONFIG_OPTION_OLD_INTERNALS is - defined) to assure binary compatibility with older FreeType - versions. - Use FT_CONFIG_OPTION_OLD_INTERNALS to add function stubs for old - functions: - - ft_stub_set_char_sizes - ft_stub_set_pixel_sizes - - Rename the following internal functions to provide the old function - names as stubs: - - FT_Alloc -> ft_mem_alloc - FT_QAlloc -> ft_mem_qalloc - FT_Realloc -> ft_mem_realloc - FT_QRealloc -> ft_mem_qrealloc - FT_Free -> ft_mem_free - FT_Alloc_Debug -> ft_mem_alloc_debug - FT_QAlloc_Debug -> ft_mem_qalloc_debug - FT_Realloc_Debug -> ft_mem_realloc_debug - FT_QRealloc_Debug -> ft_mem_qrealloc_debug - FT_Free_Debug -> ft_mem_free_debug - -2006-02-15 Chia-I Wu - - * include/freetype/internal/ftobjs.h (FT_Face_InternalRec): Remove - unused `max_points' and `max_contours'. - - * src/cid/cidobjs.c (cid_face_init), src/type1/t1objs.c - (T1_Face_Init), src/type42/t42objs.c (T42_Face_Init): Update. - - * include/freetype/internal/tttypes.h (TT_FaceRec): Remove unused - `max_components'. - - * src/truetype/ttinterp.h (TT_ExecContextRec): Remove unused - `loadSize' and `loadStack'. - - * src/truetype/ttinterp.c (TT_Done_Context, TT_Load_Context), - src/sfnt/ttload.c (tt_face_load_maxp): Update. - - * src/cff/cffobjs.h (cff_size_select), src/sfnt/sfdriver.c - (sfnt_interface), src/truetype/ttdriver.c (tt_size_request): Fix - compiler errors/warnings when TT_CONFIG_OPTION_EMBEDDED_BITMAPS is not - defined. - - * src/sfnt/ttmtx.c (tt_face_load_hmtx, tt_face_get_metrics): Fix - possible segment faults for the non-FT_OPTIMIZE_MEMORY'ed versions. - (finally!) - - - For most OpenType tables, `tt_face_load_xxxx' simply loads the table - and `face->root' is set later in `sfnt_load_face'. Here, we try to - make this work for _all_ tables. Also improve tracing messages. - - * src/sfnt/ttsbit.c, src/sfnt/ttsbit0.c, src/sfnt/ttload.c, - src/sfnt/ttmtx.c: all `tt_face_load_xxxx' should load the table and - then exit. Error handling or setting face->root is done later in - `sfnt_load_face'. - - * src/sfnt/sfobjs.c (sfnt_load_face): Work harder. - Mac bitmap-only fonts are not scalable. - Check that `face->header.Units_Per_EM' is not zero. - (LOAD_, LOADM_): Emit pretty trace messages. - - * src/sfnt/ttsbit0.c (tt_face_load_strike_metrics): Read metrics - from `eblc'. - - * src/sfnt/ttcmap.c (tt_face_build_cmaps), src/sfnt/ttpost.c - (load_format_20, load_format_25, tt_face_get_ps_name): Use - face->max_profile.numGlyphs, instead of face->root.num_glyphs. - -2006-02-14 Werner Lemberg - - * include/freetype/ftoutln.h (FT_Outline_Embolden): Mention in - documentation that negative strength values are possible. - Give an example call. - - * include/freetype/freetype.h (FT_GlyphSlotRec): Improve - documentation of `outline' field. - - * src/sfnt/sfobjs.c: Include FT_INTERNAL_DEBUG_H. - * src/sfnt/sfdriver.c: Include ttmtx.h. - - * src/autofit/afcjk.c: Include aftypes.h and aflatin.h. - -2006-02-14 Chia-I Wu - - * src/sfnt/ttmtx.c (tt_face_get_metrics): Typo. - -2006-02-14 Chia-I Wu - - * src/sfnt/ttmtx.c (tt_face_load_hhea, tt_face_load_hmtx): Simply - return error if table is missing. - Check table length in non-FT_OPTIMIZE_MEMORY'ed `tt_face_load_hmtx'. - - * src/sfnt/sfobjs.c (sfnt_load_face): Take care of missing metrics - tables. The last change makes Mac bitmap-only font not load and - this fixes it. - - * src/truetype/ttgload.c (load_truetype_glyph): Fix compilation - error when FT_CONFIG_OPTION_INCREMENTAL is defined. - -2006-02-13 Chia-I Wu - - Clean up the SFNT_Interface. In this final pass, `load_hmtx' is - split from `load_hhea'. - - * include/freetype/internal/sfnt.h, src/sfnt/sfdriver.c, - src/sfnt/ttmtx.c, src/sfnt/ttmtx.h: Split `hmtx' from `hhea'. - - * src/sfnt/sfobjs.c (sfnt_load_face): Update. - -2006-02-13 Chia-I Wu - - * src/sfnt/ttmtx.h, src/sfnt/ttmtx.c: Why are there two copies of - code... - -2006-02-13 Chia-I Wu - - Clean up the SFNT_Interface. In this pass, we want to treat the - font directory (offset table and table directory) as a normal table - like the others. This also means that TTCs are no longer recognized - there but in `init_face'. - - * include/freetype/internal/sfnt.h (SFNT_Interface), - src/sfnt/sfdriver.c: `load_sfnt_header' and `load_directory' are - combined and renamed to `load_font_dir'. - - * src/sfnt/ttload.h, src/sfnt/ttload.c: - s/sfnt_dir_check/check_table_dir/. - `sfnt_init' is moved to sfobjs.c and renamed to `sfnt_open_font'. - `tt_face_load_sfnt_header' and `tt_face_load_directory' are combined - and renamed to `tt_face_load_font_dir'. - - * src/sfnt/sfobjs.c (sfnt_init_face): Recognize TTC here. - -2006-02-13 Chia-I Wu - - Clean up the SFNT_Interface. Table loading functions are now named - after the tables' tags; `hdmx' is TrueType-specific and thus the - code is moved to the truetype module; `get_metrics' is moved here - from the truetype module so that the code can be shared with the cff - module. - - This pass involves no real changes. That is, the code is moved - verbatim mostly. The only exception is the return value of - `tt_face_get_metrics'. - - * include/freetype/internal/sfnt.h, src/sfnt/rules.mk, - src/sfnt/sfdriver.c, src/sfnt/sfnt.c, src/sfnt/sfobjs.c, - src/sfnt/ttload.c, src/sfnt/ttload.h, src/sfnt/ttsbit.c, - src/sfnt/ttsbit.h, src/sfnt/ttsbit0.c: Clean up the SFNT_Interface. - - * src/sfnt/ttmtx.c, src/sfnt/ttmtx.h: New files. Metrics-related - tables' loading and parsing code is moved to here. - Move `tt_face_get_metrics' here from the truetype module. The - return value is changed from `void' to `FT_Error'. - - * include/freetype/internal/fttrace.h: New trace: ttmtx. - - * src/truetype/ttpload.c, src/truetype/ttpload.h: `hdmx' loading and - parsing code is moved here. - New function `tt_face_load_prep' split from `tt_face_load_fpgm'. - `tt_face_load_fpgm' returns `FT_Err_Ok' if `fpgm' doesn't exist. - - * src/cff/cffgload.c, src/cff/cffobjs.c: Update. - - * src/truetype/ttgload.c, src/truetype/ttobjs.c: Update. - -2006-02-11 Chia-I Wu - - * src/autofit/afcjk.c (af_cjk_metrics_init): Fix a stupid bug... - - * src/autofit/aflatin.c (af_latin_metrics_init_widths): Use - AF_LatinMetricsRec as the dummy metrics because we cast the metrics - to it later in `af_latin_hints_link_segments'. - -2006-02-11 Chia-I Wu - - * include/freetype/config/ftoption.h (AF_CONFIG_OPTION_CJK): #define - to enable autofit CJK script support. (#define'd by default.) - - * src/autofit/aflatin.h (AF_LATIN_CONSTANT): New macro. - - * src/autofit/aflatin.c (af_latin_metrics_init_widths): Make sure - that `edge_distance_threshold' is always set. - (af_latin_hints_link_segments): Potential divide-by-zero bug. - Use latin constant in the scoring formula. - - * src/autofit/afcjk.c: Minor updates due to the above three changes. - - * docs/TODO, docs/CHANGES: Updated. - -2006-02-09 Chia-I Wu - - Introduce experimental autofit CJK module based on akito's autohint - patch. You need to #define AF_MOD_CJK in afcjk.c to enable it. - - * src/autofit/afglobal.c, src/autofit/afcjk.h, src/autofit/afcjk.c, - src/autofit/rules.mk, src/autofit/autofit.c, src/autofit/aftypes.h: - Add CJK module based on akito's autohint patch. - - * src/autofit/afhints.h (AF_SegmentRec): New field `len' for the - overlap length of the segments. - (AF_SEGMENT_LEN, AF_SEGMENT_DIST): New macros. - - * src/autofit/aflatin.h (af_latin_metrics_init_widths), - src/autofit/aflatin.c (af_latin_metrics_init_widths): Made - `FT_LOCAL'. - Use the character given by the caller. - (af_latin_metrics_init_widths, af_latin_hints_link_segments): Scale - the thresholds. - - * src/autofit/afloader.c (af_loader_load_g): Respect - AF_SCALER_FLAG_NO_ADVANCE. - -2006-02-09 Werner Lemberg - - * src/cid/cidparse.c (cid_parse_new): Remove shadowing variable. - -2006-02-09 suzuki toshiya - - * src/cid/cidparse.c (cid_parse_new): Fix for abnormally short or - broken CIDFont. Reported by Taek Kwan(TK) Lee (see ft-devel - 2005-11-02). - -2006-02-08 suzuki toshiya - - * builds/unix/configure.ac: Fix bug for `--with-old-mac-fonts' - option on UNIX platform. It has been broken since 2006-01-11. - -2006-02-01 Werner Lemberg - - * src/otvalid/module.mk: s/otvalid_module_class/otv_module_class/. - * src/gxvalid/module.mk: s/gxvalid_module_class/gxv_module_class/. - - * builds/unix/unixddef.mk: Actually do define PLATFORM (fixing - change from 2006-01-31). - (TOP_DIR, OBJ_DIR): Update. - - * builds/unix/install.mk (install): Fix path for ftmodule.h. - - * Makefile, *.mk, builds/unix/unix-cc.in, builds/unix-def.in: Use - `?=' where appropriate. - - * builds/detect.mk (TOP_DIR), builds/os2/os2-dev.mk (TOP_DIR), - builds/win32/w32-dev.mk (TOP_DIR): Removed. Defined elsewhere. - -2006-01-31 Werner Lemberg - - Implement new, simplified module selection. With GNU make it is now - sufficient to modify a single file, `modules.cfg', to control the - inclusion of modules and base extension files. - - This change also fixes the creation of ftmodule.h; it now depends on - `modules.cfg' and thus is rebuilt only if necessary. - - Finally, a version of `ftoption.h' in OBJ_DIR is preferred over the - default location. - - * modules.cfg: New file. - - * builds/freetype.mk: Don't include `modules.mk'. - Include all `rules.mk' files as specified in `modules.cfg'. - (FTOPTION_FLAG, FTOPTION_H): New variables. - (FT_CFLAGS): Add macro definition for FT_CONFIG_MODULES_H. - Add FTOPTION_FLAG. - ($(FT_INIT_OBJ)): Don't use FT_MODULE_LIST. - (CONFIG_H): Add FTMODULE_H and FTOPTION_H. - (INCLUDES): Add DEVEL_DIR. - (INCLUDE_FLAGS, FTSYS_SRC, FTSYS_OBJ, FTDEBUG_SRC, FTDEBUG_OBJ, - OBJ_M, OBJ_S): Use `:=', not `='. - (remove_ftmodule_h): New phony target to delete `ftmodule.h'. - (distclean): Add remove_ftmodule_h. - - * builds/modules.mk: (MODULE_LIST): Removed. - (make_module_list, clean_module_list): Replace targets - with... - (FTMODULE_H_INIT, FTMODULE_H_CREATE, FTMODULE_H_DONE): New - variables. Reason for the change is that it is not possible to have - a phony prerequisite which is run only if the target file must be - rebuilt (phony prerequisites act like subroutines and are *always* - executed). We only want to rebuild `ftmodule.h' if `module.cfg' is - changed. - Update all callers. - ($FTMODULE_H)): Rule to create `ftmodule.h', depending on - `modules.cfg'. - - * builds/toplevel.mk: Rewrite and simplify module handling. - (MODULES_CFG, FTMODULE_H): New variables. - Include MODULES_CFG. - (MODULES): New variable to include all `module.mk' and `rules.mk' - files. We no longer use make's `wildcard' function for this. - - * Makefile (USE_MODULES): Remove. Update all users. - (OBJ_DIR): Define it here. - - * src/*/module.mk: Change - - make_module_list: foo - foo: ... - - to - - FTMODULE_H_COMMANDS += FOO - define FOO - ... - endef - - in all files. `FTMODULE_H_COMMANDS' is used in `FTMODULE_H_CREATE'. - - * src/base/rules.mk (BASE_EXT_SRC): Use BASE_EXTENSIONS. - - * builds/unix/detect.mk (setup): Always execute `configure' script. - (have_mk): Rename to... - (have_Makefile): This. - Don't use `strip' function. - - * builds/unix/unix.mk: Include `install.mk' only if BUILD_PROJECT is - defined. - (have_mk): Don't use `strip' function. - Test for unix-def.mk in OBJ_DIR, not BUILD_DIR (and invert the test - accordingly). - - * builds/unix/install.mk (install, uninstall): Handle `ftmodule.h'. - - * builds/os2/os2-dev.mk, builds/unix/unix-dev.mk, - builds/win32/w32-bccd.mk, builds/win32/w32-dev.mk: Don't define - BUILD_DIR but DEVEL_DIR for development header files. - - * builds/ansi/ansi-def.mk (TOP_DIR, OBJ_DIR), - builds/beos/beos-def.mk (TOP_DIR, OBJ_DIR), builds/unix/unix-def.in - (TOP_DIR, OBJ_DIR): Removed. Defined elsewhere. - - * builds/dos/dos-def.mk (OBJ_DIR), builds/os2/os2-def.mk (OBJ_DIR), - builds/win32/win32-def.mk (OBJ_DIR): Removed. Defined elsewhere. - - * builds/unix/unixddef.mk: Don't define BUILD_DIR but DEVEL_DIR for - development header files. - Don't define PLATFORM. - - * configure: Copy `modules.cfg' to builddir if builddir != srcdir. - Update snippet taken from autoconf's m4sh.m4 to current CVS version. - Be more verbose. - - * include/freetype/config/ftmodule.h: Add comments -- this file is - no longer used if FreeType is built with GNU make. - - * docs/CHANGES, docs/CUSTOMIZE, docs/INSTALL, docs/INSTALL.ANY, - docs/INSTALL.GNU, docs/INSTALL.UNX: Document new build mechanism. - Other minor updates. - - * modules.txt: Removed. Contents included in `modules.cfg'. - - - * include/freetype/internal/ftmemory.h (FT_QAlloc_Debug, - FT_Free_Debug) [FT_STRICT_ALIASING]: Fix typos. - - * src/base/ftdbgmem.c (FT_Alloc_Debug, FT_Realloc_Debug, - FT_QAlloc_Debug, FT_QRealloc_Debug, FT_Free_Debug) - [FT_STRICT_ALIASING]: Implement. - -2006-01-31 Chia-I Wu - - * src/cff/cffobjs.c (cff_face_init), src/cid/cidobjs.c - (cid_face_init), src/pfr/pfrobjs.c (pfr_face_init), - src/type1/t1objs.c (T1_Face_Init): Set face->height to MAX(1.2 * - units_per_EM, ascender - descender). - -2006-01-31 Chia-I Wu - - * include/freetype/internal/t1types.h (AFM_FontInfo), - src/psaux/afmparse.c, src/tools/test_afm.c: Read `FontBBox', - `Ascender', and `Descender' from an AFM. - - * src/type1/t1afm.c (T1_Read_Metrics): Use the metrics from the AFM. - - * include/freetype/freetype.h (FT_FaceRec): Mention that fields may - be changed after file attachment. - -2006-01-28 Werner Lemberg - - * src/*/module.mk (.PHONY): Add. - -2006-01-27 Werner Lemberg - - * README, docs/FTL.TXT: Fix email address for bug reports. - Other minor formatting. - - * devel/ftoption.h: Synchronize with - include/freetype/config/ftoption.h. - - * src/autofit/module.mk (add_autofit_module), src/bdf/module.mk - (add_bdf_module), src/type42/module.mk (add_type42_driver): Fix - whitespace. - - * src/smooth/module.mk (add_smooth_renderer): Add lcd and lcdv - renderer classes. - -2006-01-27 David Turner - - * builds/unix/configure.ac: Fix build problem on Cygwin. - - * builds/unix/install.mk (install): Don't install the internal - headers, and remove existing ones if found in the target install - directory. - - * src/autofit/afwarp.c: Add simple #ifdef to prevent compilation - if the warp hinter isn't active (it shouldn't, still experimental). - - * Jamfile, include/freetype/config/ftmodule.h: Remove `gxvalid' - and `otvalid' from the list of modules that are linked statically - to a given FreeType library. Functionality has been moved to the - `ftvalid' CVS module. - - Note also that current Make-based build system still compiles the - modules though. - - * include/freetype/config/ftoption.h (FT_STRICT_ALIASING): New macro - which controls the definitions of the memory management functions to - avoid warnings with recent versions of GCC. This macro is only here - to be disabled, in case we detect problems with the new scheme. - - NOTE: Disable macro to use the memory debugger -- this will be fixed - later! - - * include/freetype/internal/ftmemory.h, src/base/ftutil.c (FT_Alloc, - FT_QAlloc, FT_Realloc, FT_QRealloc, FT_Free) [FT_STRICT_ALIASING]: - New versions. - - - * builds/win32/visualc/freetype.dsp: Updating project file to - define FT2_BUILD_LIBRARY, and remove gxvalid + otvalid modules from - compilation. - - - * builds/freetype.mk (FT_CFLAGS), Jamfile (DEFINES): Define the - macro FT2_BUILD_LIBRARY when compiling the library. - - * include/freetype/config/ftheader.h: Remove inclusions of internal - headers except if the macro FT2_BUILD_LIBRARY is defined. - - - * include/freetype/internal/psaux.h (AFM_KernPair, AFM_TrackKern, - AFM_FontInfo): Move structure declarations to... - * include/freetype/internal/t1types.h: This file. - - - * (many files): Fix compiler warnings. - Various minor reorganizations. - - - * src/cff/cffload.c (cff_font_done): Don't free static array - `subfonts'. - - * src/otvalid/otvcommn.c (otv_ClassDef_validate), - src/otvalid/otvgpos.c (otv_x_sxy): Fix debugging information. - - - Get rid of writable static variables (i.e., the string table) in - afmparse, and fix compilation in FT2_MULTI mode. - - * src/psaux/afmparse.c: Include ft2build.h and FT_FREETYPE_H. - (AFM_MAX_ARGUMENTS): Define... - * src/psaux/afmparse.h: Here. - * src/psaux/Jamfile (_sources): Add afmparse. - - * src/psaux/psconv.c: Include psconv.h. - - * src/type1/t1afm.c: Don't include FT_INTERNAL_TYPE1_TYPES_H but - FT_INTERNAL_POSTSCRIPT_AUX_H. - * src/type1/t1afm.h: Include FT_INTERNAL_TYPE1_TYPES_H. - -2006-01-23 Chia-I Wu - - * include/freetype/freetype.h (FT_Select_Size): Rename the second - argument from `idx' to `strike_index'. - (FT_Size_Request_Type): Add FT_SIZE_REQUEST_TYPE_MAX to the end of - this enum. - - * include/freetype/internal/ftobjs.h (FT_REQUEST_WIDTH, - FT_REQUEST_HEIGHT): New macros to get the width and height of a - request, in fractional pixels. - - * include/freetype/internal/ftobjs.h (FT_Select_Metrics, - FT_Request_Metrics), src/base/ftobjs.c (FT_Select_Metrics, - FT_Request_Metrics): New base functions to set the font metrics. They - were part of FT_Select_Size/FT_Request_Size and are made independent - functions so that metrics are not set again and again. - - * src/base/ftobjs.c (FT_Select_Size, FT_Request_Size): Metrics are set - only when driver's size_select/size_request is NULL. That is, drivers - should set the metrics themselves. - (FT_Match_Size): Round before matching. This was what we did and it - does cause some problems without rounding. - - * src/cff/cffobjs.c (cff_size_select), src/truetype/ttdriver.c - (tt_size_select): Set the font metrics. - s/index/strike_index/. - The scaled metrics are always preferred over strikes' metrics, even - when some strike is selected. This is done because the strikes' - metrics are not reliable, e.g., the sign of the descender is wrong for - some fonts. - - * src/cff/cffobjs.c (cff_size_request), src/truetype/ttdriver.c - (tt_size_request): Set the font metrics. - Call cff_size_select/tt_size_select when some strike is matched. - - * src/bdf/bdfdrivr.c, src/cff/cffobjs.c, src/cid/cidobjs.c, - src/pcf/pcfdrivr.c, src/truetype/ttdriver.c, src/type1/t1objs.c, - src/type1/t1objs.h, src/type42/t42objs.c, src/winfonts/winfnt.c: - Set the font metrics. - s/index/strike_index/. - - * src/tools/test_afm.c, src/psaux/psconv.c: Older versions of these - files were committed. Just a catch-up. - (PS_Conv_ToFixed): Remove the `goto'. - (PS_Conv_ASCIIHexDecode, PS_Conv_EexecDecode): Speed up a little. - - * src/sfnt/ttsbit.c (tt_face_load_sbit_strikes, - tt_face_load_strike_metrics), src/sfnt/ttsbit0.c - (tt_face_load_sbit_strikes, tt_face_load_strike_metrics): The - advertised metrics in `available_sizes' are different from those - actually used. - -2006-01-23 Chia-I Wu - - * src/psaux/psaux.c src/psaux/psauxmod.c src/type1/t1driver.c: Make - AFM parser optional, controlled by `T1_CONFIG_OPTION_NO_AFM'. - -2006-01-22 Werner Lemberg - - * builds/unix/install-sh, builds/unix/mkinstalldirs: Updated from - `texinfo' CVS module at savannah.gnu.org. - -2006-01-21 Werner Lemberg - - * src/autofit/rules.mk (AUTOF_DRV_SRC): Add afwarp.c. - - * src/autofit/afloader.c (af_loader_load_g): Move AF_USE_WARPER up - to avoid compiler warnings. - - * src/autofit/afwarp.c (af_warper_compute_line_best): Remove - shadowing variable declarations. - Fix warning parameters and replace printf with AF_LOG. - (af_warper_compute): Remove unused variable. - -2006-01-20 David Turner - - Adding experimental implementation of `warp hinting' (new hinting - algorithm for gray-level and LCD rendering). It is disabled by - default, you need to #define AF_USE_WARPER in aftypes.h. - - * src/autofit/afhints.c (af_glyph_hints_scale_dim) [AF_USE_WARPER]: - New function. - * src/autofit/afhints.h: Updated. - - * src/autofit/aflatin.c [AF_USE_WARPER]: Include afwarp.h. - (af_latin_hints_init) [AF_USE_WARPER]: Reset mode to - FT_RENDER_MODE_NORMAL if an LCD mode is selected. - (af_latin_hints_apply) [AF_USE_WARPER]: Call af_warper_compute - appropriately. - - * src/autofit/afloader.c (af_loader_load_g) [!AF_USER_WARPER]: - Isolate code for adjusting metrics. - - * src/autofit/aftypes.h (AF_USE_WARPER): New macro (commented out by - default). - - * src/autofit/afwarp.c, src/autofit/afwarp.h: New files. - - * src/autofit/autofit.c [AF_USE_WARPER]: Include afwarp.c. - - * src/autofit/Jamfile (_sources): Add afwarp. - -2006-01-19 David Turner - - * src/sfnt/ttsbit0.c (tt_face_load_strike_metrics): Fix small bug - that prevented compilation when FT_OPTIMIZE_MEMORY is defined. - -2006-01-19 Brian Weed - - * builds/win32/visualc/freetype.dsp: Updated. - -2006-01-17 Werner Lemberg - - Use pscmap service in CFF module. - - * src/cff/cffcmap.c (cff_cmap_uni_pair_compare): Removed. - (cff_sid_to_glyph_name): New function. - (cff_cmap_unicode_init, cff_cmap_unicode_done, - cff_cmap_unicode_char_index, cff_cmap_unicode_char next): Use pscmap - service. - (cff_cmap_unicode_class_rec): Updated. - * src/cff/cffcmap.h (CFF_CMapUnicode, CFF_CMap_UniPair): Removed. - - - * src/psnames/psmodule.c (ps_unicodes_char_next): Fix `unicode' - return value. - - - * src/psaux/afmparse.c (afm_parser_read_vals): Use double casting - to avoid compiler warnings regarding type-punning. - -2006-01-16 Chia-I Wu - - * src/psaux/afmparse.c, src/psaux/afmparse.h: New files which - implement an AFM parser. - - * src/psaux/psconv.c, src/psaux/psconv.h: New files to provide - conversion functions (e.g., PS real number => FT_Fixed) for the - PS_Parser and AFM_Parser. Some of the functions are taken, with - some modifications, from the file psobjs.c. - - * src/psaux/psobjs.c: Use functions from psconv.c. - - * include/freetype/internal/psaux.h, src/psaux/psauxmod.c: Add - `AFM_Parser' to the `psaux' service. - - * src/psaux/psaux.c, src/psaux/rules.mk (PSAUX_DRV_SRC): Include - those new files. - - * src/tools/test_afm.c: A test program for AFM parser. - - * include/freetype/internal/services/svkern.h: New file providing a - `Kerning' service. It is currently only used to get the track - kerning information. - - * include/freetype/internal/ftserv.h (FT_SERVICE_KERNING_H): New - macro. - - * src/type1/t1driver.c, src/type1/t1objs.c, src/type1/t1afm.c, - src/type1/t1afm.h: Update to use the AFM parser. - Provide the `Kerning' service. - - * include/freetype/freetype.h, src/base/ftobjs.c: New API - `FT_Get_Track_Kerning'. - -2006-01-15 Chia-I Wu - - * include/freetype/internal/ftobjs.h, src/base/ftobjs.c, - src/bdf/bdfdrivr.c, src/cff/cffgload.c, src/cid/cidgload.c, - src/pcf/pcfdrivr.c, src/type1/t1gload.c, src/winfonts/winfnt.c: - s/ft_fake_vertical_metrics/ft_synthesize_vertical_metrics/. - - * docs/CHANGES: Mention that vertical metrics are synthesized for - fonts not having this info. - -2006-01-15 Chia-I Wu - - * include/freetype/internal/ftobjs.h (ft_fake_vertical_metrics), - src/base/ftobjs.c (ft_fake_vertical_metrics): New function to fake - vertical metrics. - - * src/cff/cffgload.c, src/cid/cidgload.c, src/pcf/pcfdrivr.c, - src/type1/t1gload.c, src/winfonts/winfnt.c: Fake vertical metrics, - which are monotone. - - * src/truetype/ttgload.c (compute_glyph_metrics): Some fixes and - formattings in vertical metrics faking. There is still room for - improvements (and so does the CFF module). - -2006-01-15 Chia-I Wu - - * src/bdf/bdfdrivr.c (BDF_Glyph_Load), src/pcf/pcfdrivr.c - (PCF_Glyph_Load), src/winfonts/winfnt.c (FNT_Load_Glyph): Don't set - the linear advance fields as they are only used by the outline - glyphs. - - * include/freetype/freetype.h: Documentation updates and - clarifications. - The meaning of FT_LOAD_FORCE_AUTOHINT is changed so that no real - change need be made to the code. - - * src/base/ftobjs.c (FT_Load_Glyph): Resolve flag dependencies and - decide whether to use the auto-hinter according to documentation. - There should to be no real difference. - Some checks (e.g., is text height positive?) after the glyph is - loaded. - (FT_Select_Size, FT_Request_Size): Scales are set to wrong values. - Be careful that scales won't be negative. - -2006-01-14 Chia-I Wu - - * docs/CHANGES: Mention the size selection change. - - * src/bdf/bdfdrivr.c (BDF_Size_Request, BDF_Size_Select), - src/pcf/pcfdrivr.c (PCF_Size_Request, PCF_Size_Select), - src/winfonts/winfnt.c (FNT_Size_Request, FNT_Size_Select): Do size - matching for requests of type NOMINAL and REAL_DIM. - - * src/winfonts/winfnt.c (FNT_Face_Init): Print trace message when - `pixel_height' is used for nominal height. - - * src/base/ftobjs.c (FT_Request_Size): Call `FT_Match_Size' if the - face is bitmap only and driver doesn't provide `request_size'. This - is added merely for completion as no driver satisfies the conditions. - -2006-01-13 Chia-I Wu - - Introduce new size selection interface. - - * include/freetype/internal/ftdriver.h (struct FT_Driver_ClassRec): - Replace `set_char_sizes' and `set_pixel_sizes' by `request_size' and - `select_size'. - - * include/freetype/freetype.h (FT_Select_Size, FT_Size_Request_Type, - FT_Size_Request, FT_Request_Size, FT_Select_Size), src/base/ftobjs.c - (FT_Select_Size, FT_Request_Size): API additions to export the new - size selection interface. - - * src/base/ftobjs.c (FT_Set_Char_Size, FT_Set_Pixel_Sizes): Use - `FT_Request_Size'. - - * include/freetype/internal/ftobjs.h (FT_Match_Size), - src/base/ftobjs.c (FT_Match_Size): New function to match a size - request against `available_sizes'. Drivers supporting bitmap strikes - can use this function to implement `request_size'. - - * src/bdf/bdfdrivr.c, src/cid/cidobjs.c, src/cid/cidobjs.h, - src/cid/cidriver.c, src/pcf/pcfdrivr.c, src/type1/t1driver.c, - src/type1/t1objs.c, src/type1/t1objs.h, src/type42/t42drivr.c, - src/type42/t42objs.c, src/type42/t42objs.h, src/winfonts/winfnt.c: - Update to new size selection interface. - - * src/cff/cffdrivr.c, src/cff/cffgload.c, src/cff/cffobjs.c, - src/cff/cffobjs.h, src/truetype/ttdriver.c, src/truetype/ttgload.c, - src/truetype/ttobjs.c, src/truetype/ttobjs.h: Update to new size - selection interface. - Make `strike_index' FT_ULong and always defined. - Use `load_strike_metrics' provided by SFNT interface. - -2006-01-13 Chia-I Wu - - * include/freetype/internal/sfnt.h (SFNT_Interface): New method - `load_strike_metrics' used to load the strike's metrics. - - * src/sfnt/sfdriver.c, src/sfnt/ttsbit.c, src/sfnt/ttsbit.h, - src/sfnt/ttsbit0.c: New function `tt_face_load_strike_metrics'. - - * src/pfr/pfrobjs.c (pfr_face_init): Set FT_Bitmap_Size correctly. - - * src/winfonts/winfnt.c (FNT_Face_Init): Use `nominal_point_size' for - nominal size unless it is obviously incorrect. - - * include/freetype/freetype.h (FT_Bitmap_Size): Update the comments on - FNT driver. - -2006-01-12 Werner Lemberg - - Prepare use of pscmap service within CFF module. - - * include/freetype/internal/services/svpscmap.h: Include - FT_INTERNAL_OBJECTS_H. - (PS_Unicode_Index_Func): Removed. Unused. - (PS_Macintosh_Name_Func): Renamed to... - (PS_Macintosh_NameFunc): This. - Update all callers. - (PS_Adobe_Std_Strings_Func): Renamed to... - (PS_Adobe_Std_StringsFunc): This. - Update all callers. - (PS_UnicodesRec): This is the former `PS_Unicodes' structure. - Add `cmap' member. - Update all callers. - (PS_Unicodes): This is now a typedef'd pointer to PS_UnicodesRec. - Update all callers. - (PS_Glyph_NameFunc): New typedef. - (PS_Unicodes_InitFunc): Change arguments to expect a function - and generic data pointer which returns a glyph name from a given - index. - - * src/psnames/psmodule.c (ps_unicodes_init, ps_unicodes_char_index, - ps_unicodes_char_next, pscmaps_interface): Updated. - - * include/freetype/internal/t1types.h (T1_FaceRec): Updated. - - * src/psaux/t1cmap.h (T1_CMapStdRec): Updated. - (T1_CMapUnicode, T1_CMapUnicodeRec): Removed. - - * src/psaux/t1cmap.c (t1_get_glyph_name): New callback function. - (t1_cmap_unicode_init, t1_cmap_unicode_done, - t1_cmap_unicode_char_index, t1_cmap_unicode_char_next, - t1_cmap_unicode_class_rec): Updated. - - * src/type42/t42types.h (T42_FaceRec): Updated. - -2006-01-11 suzuki toshiya - - * include/freetype/ftmac.h: Add declaration of new functions - FT_New_Face_From_FSRef and FT_GetFile_From_Mac_ATS_Name that - were introduced by the jumbo patch on 2006-01-11. - -2006-01-11 Werner Lemberg - - Fix Savannah bug #15056 and use pscmap service in psaux module. - - * include/freetype/internal/services/svpscmap.h (PS_UniMap): Use - FT_UInt32 for `glyph_index'. - (PS_Unicodes_InitFunc): Use FT_String for `glyph_names'. - (PS_Unicodes_CharIndexFunc): Use FT_UInt32 for `unicode'. - (PS_Unicodes_CharNextFunc): Make second argument a pointer to - FT_UInt32. - - * src/psnames/psmodule.c (VARIANT_BIT, BASE_GLYPH): New macros. - (ps_unicode_value): Set VARIANT_BIT in return value if glyph is a - variant glyph (this is, it has non-leading `.' in its name). - (compare_uni_maps): Sort base glyphs before variant glyphs. - (ps_unicodes_init): Use FT_String for `glyph_names' argument. - Reallocate only if number of used entries is much smaller. - Updated to handle variant glyphs. - (ps_unicodes_char_index, ps_unicodes_char_next): Prefer base glyphs - over variant glyphs. - Simplify code. - - * src/psaux/t1cmap.c (t1_cmap_uni_pair_compare): Removed. - (t1_cmap_unicode_init, t1_cmap_unicode_char_index, - t1_cmap_unicode_char_next): Use pscmap service. - (t1_cmap_unicode_done): Updated. - - * src/psaux/t1cmap.h (T1_CMapUniPair): Removed. - (T1_CMapUnicode): Use PS_Unicodes structure. - -2006-01-11 suzuki toshiya - - Jumbo patch to fix `deprecated' warning of cross-build for Tiger on - Intel, as reported by Sean McBride on - 2005-08-24. - - * src/base/ftmac.c: Heavy change to build without deprecated Carbon - functions on Tiger. - - * builds/unix/configure.ac: Add options and autochecks for Carbon - functions availabilities, for MacOS X. - - * builds/mac/ascii2mpw.py: Add converter for character `\305'. - * builds/mac/FreeType.m68k_{far|cfm}.make.txt: Add conditional - macros to avoid unavailable functions. - ftmac.c must be compiled without `-strict ansi', because it disables - cpp macro to use ToolBox system call. - - * builds/mac/FreeType.ppc_{classic|carbon}.make.txt: Add conditional - macros to avoid unavailable functions. - - * builds/mac/README: Detailed notes on function availabilities. - - * docs/CHANGES: Notes about (possible) incompatibilities. - -2006-01-08 Werner Lemberg - - * docs/CHANGES: Updated. - -2006-01-08 Huw D M Davies - - * include/freetype/ftmodapi.h (FT_Module_Get_Flags): New - declaration. - - * src/base/ftobjs.c (FT_Module_Get_Flags): New function. - -2006-01-07 Werner Lemberg - - * src/pcf/pcfread.c (pcf_get_bitmaps): Remove unused variable - `bitmaps'. Reported by Yu Lei . - - * src/base/ftutil.c (ft_highpow2): s/FT_BASE/FT_BASE_DEF/. - Reported by Niels Boldt . - -2005-12-28 suzuki toshiya - - * src/sfnt/sfnt/ttbdf.c: Add newline '\n' to the end of file, for - MPW compiler. - -2005-12-23 David Turner - - * Jamfile (RefDoc), docs/reference/README: Fix it so that `jam - refdoc' works correctly to generate the API reference in - `docs/reference'. - - * src/tools/docmaker/tohtml.py (print_html_field, - print_html_field_list): Update to output nicer fields lists in the - API reference. - - * src/base/ftobjs.c (FT_Load_Glyph): FT_LOAD_TARGET_LIGHT now - forces auto-hinting. - - * freetype/freetype.h: Updating the documentation for - FT_LOAD_TARGET_XXX and FT_Render_Mode values. - -2005-12-23 suzuki toshiya - - * src/base/ftmac.c (FT_New_Face_From_Suitcase): Count scalable faces - in supported formats (sfnt, LWFN) only, and ignore bitmap faces in - unsupported formats (fbit, NFNT). The number of available faces are - passed via face->num_faces. If bitmap faces are embedded in sfnt - resource, face->num_fixed_size is correctly set. In public API, - FT_New_Face() and FT_New_Face_From_FSSpec() count the faces as - FT_GetFile_From_Mac_Name(), which ignores NFNT resources. - - * doc/CHANGES: Mention the changes. - -2005-12-17 Chia-I Wu - - * src/truetype/ttinterp.c (Update_Max): Set current size of buffer - correctly (so that memory debug system won't panic). - -2005-12-16 Chia-I Wu - - * include/freetype/internal/ftobjs.h (ft_glyphslot_grid_fit_metrics), - src/base/ftobjs.c (ft_glyphslot_grid_fit_metrics): Removed. - - * src/base/ftobjs.c (ft_recompute_scaled_metrics): Do not round. - - * src/cff/cffgload.c (cff_slot_load), src/cid/cidgload.c - (cid_slot_load_glyph), src/truetype/ttgload.c (compute_glyph_metrics), - src/type1/t1gload.c (T1_Load_Glyph): Do not round glyph metrics. - - * doc/CHANGES: Mention the changes. - -2005-12-13 David Turner - - Change the implementation of the LIGHT hinting mode to completely - disable horizontal hinting. This is an experimental effort to - integrate David Chester's latest patch without affecting the other - hinting modes as well. - - Note that this doesn't force auto-hinting for all fonts, however. - - * src/autofit/afhints.c (af_glyph_hints_reload): Don't set - scaler_flags here but... - (af_glyph_hints_rescale): Here. - - * src/autofit/aflatin.c (af_latin_hints_init): Disable horizontal - hinting for `light' hinting mode. - - - * Jamfile: Small fix to ensure that ftexport.sym is placed into the - same location as other generated objects (i.e., within the `objs' - directory of the current directory). - - - Add support for an embedded `BDF ' table within SFNT-based bitmap - font files. This is used to store atoms & properties from the - original BDF fonts that were used to generate the font file. - - The feature is controlled by TT_CONFIG_OPTION_BDF within - `ftoption.h' and is used to implement FT_Get_BDF_Property for these - font files. - - At the moment, this is still experimental, the BDF table format - isn't cast into stone yet. - - * include/freetype/config/ftoption.h (TT_CONFIG_OPTION_BDF): New - macro. - - * include/freetype/config/ftstdlib.h (ft_memchr): New macro. - - * include/freetype/internal/tttypes.h (TT_BDFRec, TT_BDF) - [TT_CONFIG_OPTION_BDF]: New structure. - (TT_FaceRec) [TT_CONFIG_OPTION_BDF]: New member `bdf'. - - * include/freetype/tttags.h (TTAG_BDF): New macro. - - * src/sfnt/Jamfile (_sources): Add ttbdf. - - * src/sfnt/rules.mk (SFNT_DRV_SRC): Add ttbdf.c. - - * src/sfnt/sfdriver.c [TT_CONFIG_OPTION_BDF]: Include ttbdf.h and - FT_SERVICE_BDF_H. - (sfnt_get_charset_it) [TT_CONFIG_OPTION_BDF]: New function. - (sfnt_service_bdf) [TT_CONFIG_OPTION_BDF]: New service. - (sfnt_services) [TT_CONFIG_OPTION_BDF]: Add sfnt_service_bdf. - - * src/sfnt/sfnt.c [TT_CONFIG_OPTION_BDF]: Include ttbdf.c. - - * src/sfnt/sfobjs.c [TT_CONFIG_OPTION_BDF]: Include ttbdf.h. - (sfnt_done_face) [TT_CONFIG_OPTION_BDF]: Call - tt_face_free_bdf_props. - - * src/sfnt/ttbdf.h, src/sfnt/ttbdf.c: New files. - -2005-12-07 Werner Lemberg - - * src/sfnt/sfobjs.c (sfnt_init_face): Move tag check to... - * src/sfnt/ttload.c (sfnt_init): Here, before handling TTCs. - -2005-12-06 Chia-I Wu - - * src/truetype/ttobjs.c (tt_size_init): size->ttmetrics.valid is - initialized twice. - size->strike_index is not initialized. - -2005-12-02 Taek Kwan(TK) Lee - - * src/type42/t42objs.c (T42_Face_Init): Replace call to - FT_New_Memory_Face with call to FT_Open_Face to pass `params'. - -2005-11-30 Werner Lemberg - - * docs/CHANGES: Document ftdump's `-v' option. - Document latest charmap code changes. - - * src/sfnt/ttcmap.c, src/sfnt/ttcmap.h: - s/TT_CMAP_FLAG_OVERLAPPED/TT_CMAP_FLAG_OVERLAPPING/. - -2005-11-30 Chia-I Wu - - * src/sfnt/ttcmap.c (tt_cmap4_char_map_binary, - tt_cmap12_char_map_binary): Fix compiler warnings. - -2005-11-29 Chia-I Wu - - Major update to distinguish between unsorted and overlapping - segments for cmap format 4. For overlapping but sorted segments, - which is previously considered unsorted, we still use binary search. - - * src/sfnt/ttcmap.h (TT_CMapRec_): Replace `unsorted' by `flags'. - (TT_CMAP_FLAG_UNSORTED, TT_CMAP_FLAG_OVERLAPPED): New macros. - - * src/sfnt/ttcmap.c (OPT_CMAP4): Removed as it is always defined. - (TT_CMap4Rec_): Remove `old_charcode' and `table_length'. - (tt_cmap4_reset): Removed. - (tt_cmap4_init): Updated accordingly. - (tt_cmap4_next): Updated accordingly. - Take care of overlapping segments. - (tt_cmap4_validate): Make sure the subtable is large enough. - Do not check glyph_ids because some fonts set the length wrongly. - Also, if all segments have offset 0, glyph_ids is always invalid. - It does not cause any problem so far only because the check misses - equality. - Distinguish between unsorted and overlapping segments. - (tt_cmap4_char_map_linear, tt_cmap4_char_map_binary): New functions - to do `charcode => glyph index' by linear/binary search. - (tt_cmap4_char_index, tt_cmap4_char_next): Use - tt_cmap4_char_map_linear and tt_cmap4_char_map_binary. - (tt_face_build_cmaps): Treat the return value of validator as flags - for cmap. - -2005-11-29 Chia-I Wu - - * src/sfnt/ttcmap.c (TT_CMap12Rec_, tt_cmap12_init, tt_cmap12_next): - New structures and functions for fast `next char'. - (tt_cmap12_char_map_binary): New function to do `charcode => glyph - index' by binary search. - (tt_cmap12_char_index, tt_cmap12_char_next): Use - tt_cmap12_char_map_binary. - (tt_face_build_cmaps): Check table and offset correctly (equality is - missing). - -2005-11-15 Detlef Würkner - - * builds/amiga/smakefile: Adjusted the compiler options - to the current sources, now really builds the gxvalid, gzip - and psnames modules. - - * builds/amiga/src/base/ftsystem.c: The assumed Seek() position - in the file cache was off by one byte which could cause false - errors in font files. - -2005-11-24 suzuki toshiya - - * builds/mac/FreeType.m68k_far.make.txt, - builds/mac/FreeType.m68k_cfm.make.txt, - builds/mac/FreeType.ppc_classic.make.txt, - builds/mac/FreeType.ppc_carbon.make.txt: - Updated for MPW to build all available modules. - -2005-11-21 Håvard Wall - - * src/bdf/bdfdrivr.c (bdf_interpret_style, BDF_Face_Done): Fix small - memory leak. - -2005-11-21 Werner Lemberg - - * src/sfnt/ttload.c (sfnt_init): Add tracing message. - -2005-11-21 Chia-I Wu - - * src/sfnt/ttsbit0.c (tt_sbit_decoder_load_image): Image_offset was - added twice to image_start if image_format was 2 or 5. - -2005-11-21 Chia-I Wu - - * src/sfnt/sfobjs.c (sfnt_init_face): Check that format_tag is known - before loading the table directory. - - * src/sfnt/ttload.c (tt_face_load_sfnt_header, - tt_face_load_directory): Delay sfnt_dir_check from - tt_face_load_sfnt_header to tt_face_load_directory. - -2005-11-20 Chia-I Wu - - * src/sfnt/ttload.c (sfnt_dir_check): Clean up and return correct - error code. - (sfnt_init): New function to fill in face->ttc_header. A non-TTC font - is synthesized into a TTC font with one offset table. - (tt_face_load_sfnt_header): Use sfnt_init. - Fix an invalid access if the font is TTC and face_index is -1. - -2005-11-18 Werner Lemberg - - * src/sfnt/ttload.c (tt_face_load_metrics): Ignore excess number - of metrics instead of aborting. Patch suggested by Derek Noonburg. - - * src/cff/cffgload.c (cff_slot_load), src/cid/cidgload.c - (cid_slot_load_glyph), src/type1/t1gload.c (T1_Load_Glyph): Scale - the glyph properly if no hinter is available. - - * docs/CHANGES: Mention scaling bug. - -2005-11-18 suzuki toshiya - - * include/freetype/ftgxval.h, src/base/ftgxval.c - (FT_TrueTypeGX_Free, FT_ClassicKern_Free): New functions to free - buffers allocated by gxvalid module. - * include/freetype/ftotval.h, src/base/ftotval.c - (FT_OpenType_Free): New function to free buffer allocated by - otvalid module. - -2005-11-18 Chia-I Wu - - * builds/unix/ftsystem.c (FT_Stream_Open, FT_New_Memory, - FT_Done_Memory), builds/vms/ftsystem.c (FT_Stream_Open, FT_New_Memory, - FT_Done_Memory), builds/win32/ftdebug.c (FT_Message, FT_Panic): - s/FT_EXPORT/FT_BASE/. - -2005-11-17 Detlef Würkner - - * builds/amiga/src/base/ftdebug.c (FT_Trace_Get_Count, - FT_Trace_Get_Name, FT_Message, FT_Panic), - builds/amiga/src/base/ftsystem.c (FT_New_Memory, FT_Done_Memory, - FT_Stream_Open): s/FT_EXPORT/FT_BASE/. - -2005-11-17 Detlef Würkner - - * builds/amiga/makefile, builds/amiga/makefile.os4, - builds/amiga/smakefile, - builds/amiga/include/freetype/config/ftmodule.h: Updated the Amiga - build files (added support for the gxvalid module). - -2005-11-17 Werner Lemberg - - Add vertical metrics support to OpenType CFF outlines. Based on a - patch from Mike Moening . - - * src/cff/cffgload.c (cff_face_get_vertical_metrics): New function. - (cff_slot_load): Use cff_face_get_vertical_metrics. - - * docs/CHANGES: Updated. - -2005-11-17 Chia-I Wu - - * src/base/ftcalc.c (FT_MulTo64): Commented out. - - * include/freetype/internal/ftcalc.h (FT_SqrtFixed), - src/base/ftcalc.c (FT_SqrtFixed), - include/freetype/internal/ftdebug.h (FT_Trace_Get_Count, - FT_Trace_Get_Name, FT_Message, FT_Panic), src/base/ftdebug.c - (FT_Trace_Get_Count, FT_Trace_Get_Name, FT_Message, FT_Panic), - include/freetype/internal/ftobjs.h (FT_New_Memory, FT_Done_Memory), - include/freetype/internal/ftstream.h (FT_Stream_Open), - src/base/ftsystem.c (FT_New_Memory, FT_Done_Memory, FT_Stream_Open): - s/FT_EXPORT/FT_BASE/. - - * builds/exports.mk: Manually add TT_New_Context to EXPORTS_LIST - too. - -2005-11-15 David Turner - - * src/base/fttrigon.c (ft_trig_prenorm): Fix a bug that created - invalid computations, resulting in very weird bugs in TrueType - bytecode hinted fonts. - - * src/truetype/ttinterp.c (FT_UNUSED_EXEC): Don't perform a - structure copy each time. - -2005-11-11 Werner Lemberg - - * src/cache/ftccache.c (FTC_Cache_Clear), src/cache/ftcmanag.c - (FTC_Manager_Check): Remove FT_EXPORT_DEF tag. - - * src/base/ftcalc.c (FT_Add64): Remove FT_EXPORT_DEF tag. - (FT_Div64by32, FT_Sqrt32): Commented out. Unused. - - * include/freetype/internal/ftcalc.h (SQRT_32): Removed. Unused. - (FT_Sqrt32): Commented out. Unused. - - * include/freetype/cache/ftccache.h: - s/ftc_node_destroy/FTC_Node_Destroy/. - - * src/cache/ftccback.h (ftc_node_destroy): New declaration. - - * src/cache/ftccache.c (ftc_node_destroy): Use FT_LOCAL_DEF tag. - (FTC_Node_Destroy): New exported wrapper function for - ftc_node_destroy. - - * src/cache/ftcmanag.c: Include ftccback.c. - -2005-11-10 Werner Lemberg - - * src/autofit/afangles.c, src/autofit/aftypes.h (af_angle_diff): - Comment out. Unused. - - * builds/exports.mk ($(EXPORTS_LIST)): Add TT_RunIns. - -2005-11-10 Christian Biesinger - - * builds/beos/beos.mk: Call beos-def.mk before anything else to - define the separator. - - * builds/unix/unix-cc.in (LINK_LIBRARY): Add `-no-undefined' flag. - -2005-11-07 Werner Lemberg - - * src/type1/t1afm.c (T1_Read_PFM): Zero offset means `no kerning - table available'. From Sergey Tolstov . - -2005-11-03 Ville Syrjälä - - * src/base/ftobjs.c (FT_Open_Face): Avoid possible memory leak. - -2005-11-02 Werner Lemberg - - Make compiling instructions in docs/CUSTOMIZE work again. - - * builds/unix/unix-cc.in (CPPFLAGS): New variable. - (CFLAGS): Don't include @CPPFLAGS@. - * builds/freetype.mk (FT_CFLAGS): Add CPPFLAGS. - -2005-10-28 David Turner - - Update build system to support the generation of a list of exported - symbols or Windows .DEF files by parsing the public headers with the - `apinames' tool located in src/tools/apinames.c. - - Only tested on Unix at the moment. On Windows, the .DEF file is - generated but isn't used yet to generate a DLL. - - * builds/exports.mk: New file. - - * builds/freetype.mk: Include exports.mk. - (dll): New target. - (clean_project_dos): Fix rule. - - * builds/compiler/visualc.mk (TE), builds/dos/dos-def.mk (E), - builds/os2/os2-def.mk (E), builds/win32/win32-def.mk (E): New - variables for controlling executable extensions. - - * builds/unix/unix-cc.in (EXPORTS_LIST, CCexe), - builds/win32/w32-bcc.mk, builds/win32/w32-gcc.mk, - builds/win32/w32-icc.mk, builds/win32/w32-icc.mk, - builds/win32/w32-mingw32.mk, builds/win32/w32-vcc, - builds/win32/w32-wat.mk (EXPORTS_LIST, EXPORT_OPTIONS, - APINAMES_OPTIONS): New targets for controlling the `apinames' tool. - - * Jamfile (GenExportSymbols): Updated. - - - * src/pfr/pfrtypes.h, src/pfr/pfrload.c, src/pfr/pfrobjs.c - [!FT_OPTIMIZE_MEMORY]: Fold memory optimization code into - FT_OPTIMIZE_MEMORY chunks for better maintainability and simplicity. - - - * src/base/fttrigon.c (ft_trig_prenorm), src/base/ftcalc.c - (FT_MulFix): Performance optimizations. - - - * include/freetype/internal/ftgloadr.h (FT_GLYPHLOADER_CHECK_P, - FT_GLYPHLOADER_CHECK_C, FT_GLYPHLOADER_CHECK_POINTS): New macros for - checking points and contours. Update callers to use - FT_GLYPHLOADER_CHECK_POINTS instead of FT_GlyphLoader_CheckPoints - at profile-detected hot-spots. - - * src/base/ftgloadr.c (FT_GlyphLoader_CheckPoints): Set `adjust' - to 0 to not call `AdjustPoints' every time. - - - * src/autofit/aftypes.h (AF_ANGLE_DIFF): New macro to inline - FT_Angle_Diff. - - * src/autofit/afhints.c (af_direction_compute): Re-implement. - (af_glyph_hints_compute_inflections, af_glyph_hints_reload): Use - AF_ANGLE_DIFF to speed up the detection of inflexions. - - - * src/tools/apinames.c: Include . - (OutputFormat): New enumeration. - (names_dump): Add two parameters to control output format and DLL - name. - (names_dump_windef): Removed. Code folded into `names_dump'. - (read_header_file): Use isalnum, not isalpha. Otherwise function - names with digits aren't read correctly. - (usage): Updated. - (main): New option `-o' to control output file name. - New option `-d' to indicate DLL file name. - Extend `-w' flag to handle Borland and Watcom compilers and linkers. - -2005-10-28 suzuki toshiya - - * builds/mac/ftlib.prj, builds/mac/freetype.mak: Removed. - ftlib.prj is unmaintained and incompatible with current tree. - freetype.mak is unrecoverably broken. - - * builds/mac/ftlib.prj.xml: Added. - Generated by Metrowerks CodeWarrior 9.0. - - * builds/mac/FreeType.m68k_far.make.txt, - builds/mac/FreeType.m68k_cfm.make.txt, - builds/mac/FreeType.ppc_classic.make.txt, - builds/mac/FreeType.ppc_carbon.make.txt: Added. - Skeleton files of MPW makefiles. - - * builds/mac/ascii2mpw.py: Added. - Python script to make MPW makefile from skeleton. - - * builds/mac/README: Updated. - Almost rewritten to use new files. - -2005-10-28 suzuki toshiya - - * src/base/ftmac.c: Fix invalid casts from NULL to integer typed - variables. Advised by David Turner, Masatake YAMATO, Sean McBride, - and George Williams. - -2005-10-27 Werner Lemberg - - * include/freetype/ftsysmem.h, include/freetype/ftsysio.h: Removed. - Obsolete. - -2005-10-25 Werner Lemberg - - * src/sfnt/sfdriver.c (sfnt_interface): Move out - `tt_face_get_kerning' from a #ifdef clause. Reported by Tony J. - Ibbs . - -2005-10-23 Werner Lemberg - - * src/base/ftdbgmem.c (ft_mem_debug_realloc): Make it compile with - C++. - -2005-10-21 David Turner - - * src/base/ftdbgmem.c (ft_mem_table_set, ft_mem_debug_realloc): - Another realloc memory counting bug fix. - - * src/tools/Jamfile: Add missing file. - - * src/lzw/Jamfile: Fix incorrect source file reference. - -2005-10-20 David Turner - - * src/base/ftdbgmem.c (ft_mem_table_set, ft_mem_table_remove, - ft_mem_debug_alloc, ft_mem_debug_free, ft_mem_debug_realloc): Fixes - to better account for memory reallocations. - - * src/lzw/ftlzw2.c, src/lzw/ftzopen.h, src/lzw/ftzopen.c, - src/lzw/rules.mk: First version of LZW loader re-implementation. - Apparently, this saves about 330 KB of heap memory when loading - timR24.pcf.Z. - -2005-10-20 Chia-I Wu - - * include/freetype/ftbitmap.h (FT_Bitmap_Copy, FT_Bitmap_Embolden), - src/base/ftbdf.c (FT_Get_BDF_Property), src/cache/ftcmru.c - (FTC_MruList_Reset, FTC_MruList_Done, FTC_MruList_Lookup): Fix - FT_EXPORT/FT_EXPORT_DEF tagging. - -2005-10-19 Chia-I Wu - - * src/truetype/ttgload.c (TT_Load_Glyph): Allow size->ttmetrics to - be invalid when FT_LOAD_NO_SCALE is set. - -2005-10-17 David Turner - - * src/base/ftobjs.c (FT_Open_Face): Don't call FT_New_GlyphSlot and - FT_New_Size if we are opening a face with face_index < 0 (which is - only used for testing the format). - - * src/gxvalid/gxvmort0.c (gxv_mort_subtable_type0_entry_validate): - Remove compiler warning. - -2005-10-16 David Turner - - * src/tools/apinames.c: Add new tool to extract public API function - names from header files. - -2005-10-05 Werner Lemberg - - Add FT_FACE_FLAG_HINTER to indicate that a specific font driver has - a hinting engine of its own. - - * include/freetype/freetype.h (FT_FACE_FLAG_HINTER): New macro. - - * src/cff/cffobjs.c (cff_face_init), src/cid/cidobjs.c - (cid_face_init), src/truetype/ttobjs.c (tt_face_init) - [TT_CONFIG_OPTION_BYTECODE_INTERPRETER], src/type1/t1objs.c - (T1_Face_Init), src/type42/t42objs.c (T42_Face_Init) - [TT_CONFIG_OPTION_BYTECODE_INTERPRETER]: Update face flags. - - * docs/CHANGES: Document it. - -2005-09-27 Werner Lemberg - - * builds/unix/freetype2.m4: Add license exception so that the file - can be used in any other autoconf script. - -2005-09-26 David Turner - - * src/autofit/aflatin.c (af_latin_compute_stem_width): Fix bad - computation of the `vertical' flag, causing ugly things in LCD mode - and others. - -2005-09-23 David Turner - - * src/autofit/aflatin.c (af_latin_hints_init): Fix a bug that - prevented internal hint mode bitflags from being computed correctly. - - * src/base/Jamfile: Adding src/base/ftgxval.c. - - * src/gxvalid/gxvbsln.c, src/gxvalid/gxvcommn.c, - src/gxvalid/gxvfeat.c, src/gxvalid/gxvjust.c, src/gxvalid/gxvkern.c, - src/gxvalid/gxvlcar.c, src/gxvalid/gxvmort.c, - src/gxvalid/gxvmort0.c, src/gxvalid/gxvmort1.c, - src/gxvalid/gxvmort2.c, src/gxvalid/gxvmort4.c, - src/gxvalid/gxvmort5.c, src/gxvalid/gxvmorx.c, - src/gxvalid/gxvmorx0.c, src/gxvalid/gxvmorx1.c, - src/gxvalid/gxvmorx2.c, src/gxvalid/gxvmorx5.c, - src/gxvalid/gxvopbd.c, src/gxvalid/gxvprop.c, - src/truetype/ttgload.c: Remove _many_ compiler warnings when - compiling with Visual C++ at maximum level (/W4). - - * src/autofit/afangles.c (af_angle_atan): Replaced CORDIC-based - implementation with one using lookup tables. This simple thing - speeds up glyph loading by 18%, according to ftbench! - - * src/sfnt/sfdriver.c (sfnt_get_interface): Don't check for - `get_sfnt' and `load_sfnt' module interfaces. - -2005-09-22 Werner Lemberg - - * docs/CHANGES: Mention SING Glyphlet support. - -2005-09-22 David Turner - - * src/base/Jamfile: Disable compilation of ftgxval module - temporarily. - -2005-09-19 David Somers - - * src/sfnt/ttload.c (sfnt_dir_check): Modified to allow a - font to have no `head' table if tables `SING' and `META' are - present; this is to support `SING Glyphlet'. - - `SING Glyphlet' is an extension to OpenType developed by Adobe - primarily to facilitate adding supplemental glyphs to an OpenType - font (with emphasis on, but not necessarily limited to, gaiji to a - CJK font). A SING Glyphlet Font is an OpenType font that contains - the outline(s), either in a `glyf' or `CFF' table, for a glyph; - `cmap', `BASE', and `GSUB' tables are present with the same format - and functionality as a regular OpenType font; there are no `name', - `head', `OS/2', and `post' tables; there are two new tables, `SING' - which contains details about the glyphlet, and `META' which contains - metadata. - - Further information on the SING Glyphlet format can be found at: - - https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5148.SING_Tutorial.pdf - - * include/freetype/tttags.h (TTAG_SING, TTAG_META): New macros for - the OpenType tables `SING' and `META'. These two tables are used in - SING Glyphlet Format fonts. - -2005-09-09 Werner Lemberg - - * src/sfnt/sfobjs.c (sfnt_load_face): Reactivate code to set - FT_FACE_FLAG_KERNING which has been commented out erroneously. - - * docs/CHANGES: Document it. - -2005-09-05 Werner Lemberg - - Fixes for `make multi' and using C++ compiler. - - * src/gxvalid/gxvcommn.c (gxv_set_length_by_ushort_offset, - gxv_set_length_by_ulong_offset, gxv_array_getlimits_byte, - gxv_array_getlimits_ushort): Declare with FT_LOCAL_DEF. - (gxv_compare_ranges): Make it static. - (gxv_LookupTable_fmt0_validate, gxv_LookupTable_fmt2_validate, - gxv_LookupTable_fmt4_validate, gxv_LookupTable_fmt6_validate, - gxv_LookupTable_fmt8_validate, gxv_LookupTable_validate): Improve - trace messages. - (gxv_StateArray_validate, gxv_XStateArray_validate): s/class/clazz/. - (GXV_STATETABLE_HEADER_SIZE, GXV_STATEHEADER_SIZE, - GXV_XSTATETABLE_HEADER_SIZE, GXV_XSTATEHEADER_SIZE): Move to - gxvcommn.h. - - * src/gxvalid/gxvcommn.h: Add prototypes for - gxv_StateTable_subtable_setup, gxv_XStateTable_subtable_setup, - gxv_XStateTable_validate, gxv_array_getlimits_byte, - gxv_array_getlimits_ushort, gxv_set_length_by_ushort_offset, - gxv_set_length_by_ulong_offset, gxv_odtect_add_range, - gxv_odtect_validate. - (GXV_STATETABLE_HEADER_SIZE, GXV_STATEHEADER_SIZE, - GXV_XSTATETABLE_HEADER_SIZE, GXV_XSTATEHEADER_SIZE): Moved from - gxvcommn.c. - - * src/gxvalid/gxvbsln.c (gxv_bsln_LookupValue_validate, - gxv_bsln_parts_fmt1_validate): Improve trace messages. - - * src/gxvalid/gxvfeat.c: Split off predefined registry stuff to... - * src/gxvalid/gxvfeat.h: New file. - - * src/gxvalid/gxvjust.c (gxv_just_wdc_entry_validate): Improve trace - message. - - * src/gxvalid/gxvkern.c (GXV_kern_Dialect): Add KERN_DIALECT_UNKNOWN. - (gxv_kern_subtable_fmt1_valueTable_load, - gxv_kern_subtable_fmt1_subtable_setup, - gxv_kern_subtable_fmt1_entry_validate): Fix C++ compiler errors. - (gxv_kern_coverage_validate): Use KERN_DIALECT_UNKNOWN. - Improve trace message. - (gxv_kern_validate_generic): Fix C++ compiler error. - Improve trace message. - (gxv_kern_validate_classic): Fix C++ compiler error. - - * src/gxvalid/gxvmort0.c (gxv_mort_subtable_type0_validate): Declare - with FT_LOCAL_DEF. - - * src/gxvalid/gxvmort1.c - (gxv_mort_subtable_type1_substitutionTable_load, - gxv_mort_subtable_type1_subtable_setup): Fix C++ compiler errors. - (gxv_mort_subtable_type1_substTable_validate): Improve trace - message. - (gxv_mort_subtable_type1_validate): Declare with FT_LOCAL_DEF. - - * src/gxvalid/gxvmort2.c (gxv_mort_subtable_type2_opttable_load, - gxv_mort_subtable_type2_subtable_setup, - gxv_mort_subtable_type2_ligActionOffset_validate, - gxv_mort_subtable_type2_ligatureTable_validate): Fix C++ compiler - errors. - (gxv_mort_subtable_type2_validate): Declare with FT_LOCAL_DEF. - - * src/gxvalid/gxvmort4.c (gxv_mort_subtable_type4_validate): Declare - with FT_LOCAL_DEF. - - * src/gxvalid/gxvmort5.c (gxv_mort_subtable_type5_subtable_setup, - gxv_mort_subtable_type5_InsertList_validate): Fix C++ compiler - errors. - (gxv_mort_subtable_type5_validate): Declare with FT_LOCAL_DEF. - - * src/gxvalid/gxvmort.c: Include gxvfeat.h. - (gxv_mort_featurearray_validate, gxv_mort_coverage_validate): - Declare with FT_LOCAL_DEF. - (gxv_mort_subtables_validate, gxv_mort_validate): Improve trace - messages. - - * src/gxvalid/gxvmort.h (gxv_mort_feature_validate): Remove. - - * src/gxvalid/gxvmorx0.c (gxv_morx_subtable_type0_validate): Declare - with FT_LOCAL_DEF. - - * src/gxvalid/gxvmorx1.c - (gxv_morx_subtable_type1_substitutionTable_load, - gxv_morx_subtable_type1_subtable_setup, - gxv_morx_subtable_type1_entry_validate, - gxv_morx_subtable_type1_substitutionTable_validate): Fix C++ - compiler errors. - (gxv_morx_subtable_type1_validate): Declare with FT_LOCAL_DEF. - - * src/gxvalid/gxvmorx2.c (gxv_morx_subtable_type2_opttable_load, - gxv_morx_subtable_type2_subtable_setup, - gxv_morx_subtable_type2_ligActionIndex_validate, - gxv_morx_subtable_type2_ligatureTable_validate): Fix C++ compiler - errors. - (gxv_morx_subtable_type2_validate): Declare with FT_LOCAL_DEF. - Fix typo. - - * src/gxvalid/gxvmorx4.c (gxv_morx_subtable_type4_validate): Declare - with FT_LOCAL_DEF. - - * src/gxvalid/gxvmorx5.c (gxv_morx_subtable_type5_insertionGlyph_load, - gxv_morx_subtable_type5_subtable_setup): Fix C++ compiler error. - (gxv_morx_subtable_type5_validate): Declare with FT_LOCAL_DEF. - - * src/gxvalid/gxvmorx.c (gxv_morx_subtables_validate, - gxv_morx_validate): Improve trace message. - - * src/gxvalid/gxvopbd.c (gxv_opbd_LookupFmt4_transit): Fix compiler - warnings. - (gxv_opbd_validate): Improve trace message. - - * src/gxvalid/gxvprop.c: Decorate constants with `U' and `L' where - appropriate. - (gxv_prop_zero_advance_validate, gxv_prop_validate): Improve trace - message. - - * src/gxvalid/gxvtrak.c (gxv_trak_trackTable_validate): Remove unused - parameter. Update all callers. - (gxv_trak_validate): Improve trace message. - - * rules.mk (GXV_DRV_H): Add gxvfeat.h. - -2005-09-01 Werner Lemberg - - * src/gxvalid/gxvbsln.c (GXV_BSLN_VALUE_EMPTY): Add `U'. - - * src/gxvalid/gxvmort1.c (GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE), - src/gxvalid/gxvmort2.c (GXV_MORT_SUBTABLE_TYPE2_HEADER_SIZE): Fix - typo. - - * src/gxvalid/gxvmorx0.c, src/gxvalid/gxvmorx1.c, - src/gxvalid/gxvmorx2.c, src/gxvalid/gxvmorx4.c, - src/gxvalid/gxvmorx5.c, src/gxvalid/gxvmort.c: Improve trace - messages. - Decorate constants with `U' and `L' where appropriate. - Fix compiler warnings. - -2005-08-31 Werner Lemberg - - * src/truetype/ttgload.c (load_truetype_glyph): Fix typo. - - * src/gxvalid/gxvbsln.c (gxv_bsln_validate): Fix trace message. - - * src/gxvalid/gxvcommn.c (gxv_odtect_add_range): Use `const'. - - * src/gxvalid/gxvfeat.c, src/gxvalid/gxvjust.c, - src/gxvalid/gxvkern.c, src/gxvalid/gxvlcar.c, src/gxvalid/gxvmod.c, - src/gxvalid/gxvmort0.c, src/gxvalid/gxvmort1.c, - src/gxvalid/gxvmort2.c, src/gxvalid/gxvmort4.c, - src/gxvalid/gxvmort5.c, src/gxvalid/gxvmort.c: Improve trace - messages. - Decorate constants with `U' and `L' where appropriate. - Fix compiler warnings. - -2005-08-30 Werner Lemberg - - * src/gxvalid/README: Revised. - * src/gxvalid/gxvbsln.c: Fix compiler warnings. - * src/gxvalid/gxvcommn.c: Fix compiler warnings. - (gxv_XEntryTable_validate, gxv_compare_ranges): Remove unused - parameter. Update all callers. - Improve trace messages. - Some formatting. - -2005-08-29 Werner Lemberg - - * include/freetype/freetype.h, include/freetype/ftchapters.h: Add - a preliminary section with some explanations about user allocation. - - * src/tools/docmaker/tohtml.py (HtmlFormatter.section_enter): - Don't abort if there are no data types, functions, etc., in a - section. - Print synopsis only if we have a data type, function, etc. - - * docs/INSTALL.ANY, docs/INSTALL, docs/INSTALL.UNX, docs/CUSTOMIZE, - docs/INSTALL.GNU, docs/TRUETYPE, docs/DEBUG, docs/UPGRADE.UNX, - docs/VERSION.DLL, docs/formats.txt: Revised, formatted. - -2005-08-28 George Williams - - * src/truetype/ttgload.c [TT_MAX_COMPOSITE_RECURSE]: Removed. - (load_truetype_glyph): Limit recursion depth by `maxComponentDepth'. - -2005-08-25 J. Ali Harlow - - * builds/unix/freetype2.in (CFlags): Add missing directory. - -2005-08-24 Werner Lemberg - - * docs/CHANGES: Mention gxvalid module. - -2005-08-23 Werner Lemberg - - * src/autofit/aflatin.c (af_latin_metrics_scale): Initialize - render mode properly. Reported by chris@dokein.co.uk. - -2005-08-23 suzuki toshiya - - Add gxvalid module to validate TrueType GX/AAT tables. - - Modifications on existing files: - - * Jamfile: Register gxvalid module. - * src/base/Jamfile: Register ftgxval.c. - * src/base/rule.mk: Register ftgxval.c. - * docs/INSTALL.ANY: Register gxvalid/gxvalid.c. - - * include/freetype/config/ftheader.h (FT_GX_VALIDATE_H): New macro - to include gxvalid header file. - * include/freetype/config/ftmodule.h: Register gxv_module_class. - - * include/freetype/ftchapters.h: Add comment about gx_validation. - * include/freetype/ftotval.h: Change keyword FT_VALIDATE_XXX - to FT_VALIDATE_OTXXX to co-exist with gxvalid. - * include/freetype/tttags.h: Add tags for TrueType GX/AAT tables. - - * include/freetype/internal/ftserv.h (FT_SERVICE_GX_VALIDATE_H): New - macro for gxvalid service. - * include/freetype/internal/fttrace.h: Add trace facilities for - gxvalid. - - New files on existing directories: - - * include/freetype/internal/services/svgxval.h: Registration of - validation service for TrueType GX/AAT and classic kern table. - * include/freetype/ftgxval.h: Public API definition to use gxvalid. - * src/base/ftgxval.c: Public API of gxvalid. - - New files under src/gxvalid/: - - * src/gxvalid/Jamfile src/gxvalid/README src/gxvalid/module.mk - src/gxvalid/rules.mk src/gxvalid/gxvalid.c src/gxvalid/gxvalid.h - src/gxvalid/gxvbsln.c src/gxvalid/gxvcommn.c src/gxvalid/gxvcommn.h - src/gxvalid/gxverror.h src/gxvalid/gxvfeat.c src/gxvalid/gxvfgen.c - src/gxvalid/gxvjust.c src/gxvalid/gxvkern.c src/gxvalid/gxvlcar.c - src/gxvalid/gxvmod.c src/gxvalid/gxvmod.h src/gxvalid/gxvmort.c - src/gxvalid/gxvmort.h src/gxvalid/gxvmort0.c src/gxvalid/gxvmort1.c - src/gxvalid/gxvmort2.c src/gxvalid/gxvmort4.c src/gxvalid/gxvmort5.c - src/gxvalid/gxvmorx.c src/gxvalid/gxvmorx.h src/gxvalid/gxvmorx0.c - src/gxvalid/gxvmorx1.c src/gxvalid/gxvmorx2.c src/gxvalid/gxvmorx4.c - src/gxvalid/gxvmorx5.c src/gxvalid/gxvopbd.c src/gxvalid/gxvprop.c - src/gxvalid/gxvtrak.c: New files, gxvalid body. - -2005-08-21 Werner Lemberg - - * src/truetype/ttgload.c (TT_Load_Glyph): Only translate outline - to (0,0) if bit 1 of the `head' table isn't set. This improves - rendering of buggy fonts. - -2005-08-20 Chia I Wu - - * src/truetype/ttdriver.c (Load_Glyph): Don't check the validity of - ttmetrics here. TrueType fonts with only sbits always have - ttmetrics.valid set to false. - - * src/truetype/ttgload.c (TT_Load_Glyph): Check that ttmetrics is - valid before loading outline glyph. - - * src/cache/ftcimage.c (FTC_INode_New): Fix a memory leak. - -2005-08-20 Werner Lemberg - - * src/sfnt/ttload.c (tt_face_load_metrics_header): Ignore missing - `hhea' table for SFNT Mac fonts. Change based on a patch by - mpsuzuki@hiroshima-u.ac.jp. - -2005-08-20 Masatake YAMATO - - * src/otvalid/otvmod.c (otv_validate): Use ft_validator_run instead - of ft_setjmp. - -2005-08-19 Werner Lemberg - - * src/truetype/ttgload.c (load_truetype_glyph): Fix compiler - warnings. - -2005-08-16 Chia I Wu - - * src/truetype/ttinterp.c, src/truetype/ttinterp.h: Update copyright - messages. - -2005-08-16 Chia I Wu - - * src/truetype/ttinterp.c, src/truetype/ttinterp.h: Remove original - TT_Done_Context and rename TT_Destroy_Context to TT_Done_Context - with slight changes. - Update all callers. - (TT_New_Context): Now takes TT_Driver argument directly. - Update all callers. - - * src/truetype/ttobjs.h (tt_slot_init): New function. - * src/truetype/ttobjs.c (tt_driver_init): Initialize execution - context here. - (tt_slot_init): New function to create extra points for the internal - glyph loader. We then use it directly, instead of face's glyph - loader, when loading glyph. - - * src/truetype/ttdriver.c (tt_driver_class): Use tt_slot_init for - glyph slot initialization. - (Load_Glyph): Load flag dependencies are handled here. Return error - if size is NULL. - - * src/truetype/ttgload.c: Heavy cleanup and refactoring. - (org_to_cur): Removed. - (TT_Load_Simple_Glyph): Call FT_GlyphLoader_CheckPoints. - (TT_Hint_Glyph): New function to hint a zone, prepared by caller. - (TT_Process_Simple_Glyph): s/load/loader/. - Use loader->pp values instead of recalculation. - Use TT_Hint_Glyph. - No need to save/restore loader->stream before and after - TT_Vary_Get_Glyph_Deltas now. - (TT_LOADER_SET_PP): New macro to calculate and set the four phantom - points. - (load_truetype_glyph): Never set exec->glyphSize to 0. This closes - Savannah bug #13107. - Forget glyph frame before calling TT_Process_Simple_Glyph. - Use TT_LOADER_SET_PP. - Scale all four phantom points. - Split off some functionality to ... - (TT_Process_Composite_Component, TT_Process_Composite_Glyph): These - new functions. - (TT_Load_Glyph): Set various fields of `glyph' here, not in - load_truetype_glyph and compute_glyph_metrics. - Split off some functionality to ... - (load_sbit_image, tt_loader_init): These new functions. - (compute_glyph_metrics): Call FT_Outline_Get_CBox. - -2005-08-08 Werner Lemberg - - * docs/INSTALL.ANY: Updated. - -2005-08-05 Werner Lemberg - - * src/cff/cffgload.c (cff_builder_close_contour), - src/psaux/psobjs.c (t1_builder_close_contour): Protect against - zero `outline' pointer. - - * src/base/ftgloadr.c (FT_GlyphLoader_Add): Protect against zero - `loader' address. - -2005-08-03 Werner Lemberg - - * src/sfnt/sfdriver.c (sfnt_interface) [FT_OPTIMIZE_MEMORY]: - Reactivate pointers to tt_find_sbit_image and tt_load_sbit_metrics - to make X work again. - -2005-08-02 Werner Lemberg - - * src/otvalid/otvcommn.h: Remove dead code. - -2005-07-31 Chia I Wu - - * src/truetype/ttobjs.h (tt_size_run_fpgm, tt_size_run_prep): New - functions. - - * src/truetype/ttobjs.c (tt_size_run_fpgm, tt_size_run_prep): New - functions. - (tt_size_init): Add 4, instead of 2, (phantom) points to twilight - zone. - Move code that runs fpgm to tt_size_run_fpgm. - (Reset_Outline_Size): Move code that runs prep to tt_size_run_prep. - (tt_glyphzone_new): Allocate right size of arrays. - Set max_points and max_contours properly. - -2005-07-26 Chia I Wu - - * src/truetype/ttdriver.c (Set_Char_Sizes): Avoid unnecessary - computations and clean up. - - * src/truetype/ttobjs.h (struct TT_SizeRec_): Comment on the - internal copy of metrics. - -2005-07-12 Werner Lemberg - - * include/freetype/ftoutln.h (FT_Outline_Embolden): Fix prototype. - Reported by Xerxes. - -2005-07-04 Werner Lemberg - - * include/freetype/internal/ftmemory.h (FT_REALLOC_ARRAY): Fix typo. - Reported by Brett Hutley. - -2005-06-30 David Turner - - * src/sfnt/ftbitmap.c, src/truetype/ttgload.c, src/sfnt/ttcmap.c: - Removing compiler warnings (Visual C++ /W4). - - - Implement a work-around for broken C preprocessor in Visual C++ (it - has been confirmed by the MS developers that it is indeed a bug - which won't be fixed in the very near future). - - * Jamfile (FT2_COMPONENTS): Include otvalid (again). - - * src/otvalid/otvcommn.h (OTV_NAME, OTV_FUNC): New macros. - (OTV_NEST1, OTV_NEST2, OTV_NEST3): Use OTV_NAME and OTV_FUNC to - avoid argument expansion by argument prescan. - Append `Func' to all affected macros and change them to take just a - single argument. Example: `AttachList' is renamed to - `AttachListFunc'. - - * src/otvalid/otvgdef.c, src/otvalid/otvgpos.c, - src/otvalid/otvgsub.c, src/otvjstf.c: Append `Func' to macros - affected by the changes to OTV_NESTx and modify them to take just a - single argument. - -2005-06-20 Chia I Wu - - * include/freetype/internal/ftobjs.h, src/base/ftobjs.c: New function - ft_glyphslot_grid_fit_metrics. - - * src/truetype/ttgload.c (compute_glyph_metrics): Use - ft_glyphslot_grid_fit_metrics. - - * src/cff/cffgload.c (cff_slot_load), src/cid/cidgload.c - (cid_slot_load_glyph), src/type1/t1gload.c (T1_Load_Glyph): Use - ft_glyphslot_grid_fit_metrics. - FT_Outline_Get_CBox is called twice. - - * src/base/ftsynth.c (FT_GlyphSlot_Embolden): Modify metrics to more - reasonable values when emboldening outline glyphs. The theoretic - ones are unrealistic. - -2005-06-16 Chia I Wu - - * src/base/ftoutln.c (FT_Outline_Embolden): Strength should be - halved. - - * src/base/ftsynth.c (FT_GlyphSlot_Embolden): Change the default - strength. - Don't increase slot->advance.y. - -2005-06-16 Werner Lemberg - - * include/freetype/freetype.h (FREETYPE_MINOR): Set to 2. - (FREETYPE_PATCH): Set to 0. - - * builds/unix/configure.ac (version_info): Set to 9:9:3. - Currently, we are still binary compatible. - - * builds/win32/visualc/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj: s/219/2110/, s/2.1.9/2.1.10/. - - * builds/freetype.mk (refdoc), README, Jamfile (RefDoc): - s/2.1.9/2.1.10/. - - * docs/CHANGES, docs/VERSION.DLL: Updated. - - * ChangeLog: Split off older entries into... - * ChangeLog.20, ChangeLog.21: These new files. - -2005-06-15 Kirill Smelkov - - The next release will be 2.2.0, so don't worry about source code - backward compatibility. - - * include/freetype/ftimage.h (FT_Outline_MoveToFunc, - FT_Outline_LineToFunc, FT_Outline_ConicToFunc, - FT_Outline_CubicToFunc, FT_SpanFunc, FT_Raster_RenderFunc), - include/freetype/ftrender.h (FT_Glyph_TransformFunc, - FT_Renderer_RenderFunc, FT_Renderer_TransformFunc): Decorate - parameters with `const' where appropriate. - -2005-06-15 Chia I Wu - - * src/sfnt/ttsbit.c (tt_face_load_sbit_image): Compute vertBearingY - to make glyphs centered vertically. - - * src/truetype/ttgload.c (compute_glyph_metrics): Compute - vertBearingY to make glyphs centered vertically. - Fix some bugs in vertical metrics: - - . loader->pp3.y and loader->pp4.y are in 26.6 format, not in font - units. - . As we use the glyph's cbox to calculate the top bearing now - there is no need to adjust `top'. - -2005-06-15 Werner Lemberg - - * src/otvalid/otvcommn.h (OTV_OPTIONAL_TABLE): Use FT_UShort to be - in sync with OTV_OPTIONAL_OFFSET. Reported by YAMATO Masatake. - -2005-06-13 Werner Lemberg - - * docs/release: Update. - ----------------------------------------------------------------------------- - -Copyright (C) 2005-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, modified, -and distributed under the terms of the FreeType project license, -LICENSE.TXT. By continuing to use, modify, or distribute this file you -indicate that you have read the license and understand and accept it -fully. - - -Local Variables: -version-control: never -coding: utf-8 -End: diff --git a/lib/libesp32_lvgl/freetype/ChangeLog.23 b/lib/libesp32_lvgl/freetype/ChangeLog.23 deleted file mode 100644 index 4c80504c1..000000000 --- a/lib/libesp32_lvgl/freetype/ChangeLog.23 +++ /dev/null @@ -1,7948 +0,0 @@ -2010-02-13 Werner Lemberg - - * Version 2.3.12 released. - ========================== - - - Tag sources with `VER-2-3-12'. - - * docs/CHANGES: Updated. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.3.12. - - * README, Jamfile (RefDoc), - builds/win32/vc2005/freetype.vcproj, builds/win32/vc2005/index.html, - builds/win32/vc2008/freetype.vcproj, builds/win32/vc2008/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualc/index.html, builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj, - builds/win32/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.3.11/2.3.12/, s/2311/2312/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 12. - - * builds/unix/configure.raw (version_info): Set to 10:0:4. - -2010-02-12 suzuki toshiya - - Improve autotool version checking to work with beta releases. - - * autogen.sh (check_tool_version): Improve the extraction of version - number from "tool --version" output. Some beta releases of - autotools have extra strings before version number. - -2010-02-12 suzuki toshiya - - Fix overallocating bug in FT_Outline_New_Internal(). - - * src/base/ftoutln.c (FT_Outline_New_Internal): The length of - FT_Outline->points[] should be numPoints, not 2 * numPoints. - Found by Paul Messmer, see - https://lists.gnu.org/archive/html/freetype-devel/2010-02/msg00003.html - -2010-02-10 Ken Sharp - - Really fix Savannah bug #28678 (part 2). - - Since we consider `sbw' for the horizontal direction only, we still have - to synthesize vertical metrics if the user wants to use the vertical - writing direction. - - * src/cff/cffgload.c (cff_slot_load), src/cid/cidgload.c - (cid_slot_load_glyph), src/type1/t1gload.c (T1_Load_Glyph): - Synthesize vertical metrics (only) if FT_LOAD_VERTICAL_LAYOUT is - set. - -2010-02-10 Ken Sharp - - Really fix Savannah bug #28678 (part 1). - - After long discussion, we now consider the character width vector - (wx,wy) returned by the `sbw' Type 1 operator as being part of *one* - direction only. For example, if you are using the horizontal - writing direction, you get the horizontal and vertical components of - the advance width for this direction. Note that OpenType and CFF fonts - don't have such a vertical component; instead, the GPOS table can be - used to generate two-dimensional advance widths (but this isn't - handled by FreeType). - - * include/freetype/ftincrem.h (FT_Incremental_MetricsRec): Add - `advance_v' field to hold the vertical component of the advance - value. - - * src/truetype/ttgload.c (tt_get_metrics), src/cff/cffgload.c - (cff_slot_load), src/type1/t1gload.c - (T1_Parse_Glyph_And_Get_Char_String), src/cid/cidgload.c - (cid_load_glyph): Use it. - -2010-02-08 Werner Lemberg - - * devel/ftoption.h [FT_CONFIG_OPTION_PIC]: Define. - -2010-02-04 suzuki toshiya - - Prevent NULL pointer dereference passed to FT_Module_Requester. - - * src/sfnt/sfdriver.c (sfnt_get_interface): Don't use `module'. - * src/psnames/psmodule.c (psnames_get_interface): Ditto. - - * src/cff/cffdrivr.c (cff_get_interface): Check NULL `driver'. - * src/truetype/ttdriver.c (tt_get_interface): Ditto. - -2010-01-29 suzuki toshiya - - Fix memory leaks in previous patch. - - * src/sfnt/sfobjs.c (sfnt_load_face): Don't overwrite the strings - allocated for face->root.family_name and style_name. - -2010-01-29 suzuki toshiya - - New parameters for FT_Open_Face() to ignore preferred family names. - - Preferred family names should be used for legacy systems that - can hold only a few faces (<= 4) for a family name. Suggested by - Andreas Heinrich. - https://lists.gnu.org/archive/html/freetype/2010-01/msg00001.html - - * include/freetype/ftsnames.h (FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY, - FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY): Define. - - * src/sfnt/sfobjs.c (sfnt_load_face): Check the arguments and - ignore preferred family and subfamily names if requested. - -2010-01-27 Ken Sharp - - Fix Savannah bug #28678. - - * src/cff/cffgload.c (cff_slot_load), src/cid/cidgload.c - (cid_load_glyph): Handle vertical metrics correctly. - - * src/type1/t1gload.c (T1_Parse_Glyph_And_Get_Char_String): Handle - vertical metrics correctly. - (T1_Load_Glyph): Don't synthesize vertical metrics. - -2010-01-14 Werner Lemberg - - Make FT_Set_Transform work if no renderer is available. - - * src/base/ftobjs.c (FT_Load_Glyph): Apply `standard' transformation - if no renderer is compiled into the library. - -2010-01-14 Werner Lemberg - - Fix compilation warning. - - * src/base/ftbase.h: s/LOCAL_DEF/LOCAL/. - * src/base/ftobjs.c: Include ftbase.h conditionally. - -2010-01-11 Kwang Yul Seo - - Provide inline assembly code for RVCT compiler. - This is Savannah patch #7059. - - * include/freetype/config/ftconfig.h (FT_MULFIX_ASSEMBLER, - FT_MulFix_arm) [__CC_ARM || __ARM_CC]: Define. - -2010-01-08 Ken Sharp - - Fix Savannah bug #28521. - - Issue #28226 involved a work-around for a font which used the - `setcurrentpoint' operator in an invalid way; this operator is only - supposed to be used with the result of OtherSubrs, and the font used - it directly. The supplied patch removed the block of code which - checked this usage entirely. - - This turns out to be a Bad Thing. If `setcurrentpoint' is being - used correctly it should reset the flex flag in the decoder. If we - don't do this then the flag never gets reset and we omit any further - contours from the glyph (at least until we close the path or - similar). - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings) - : Handle `flex_state' correctly. - -2010-01-05 Werner Lemberg - - Apply reports from clang static analyzer. - - * src/lzw/ftlzw.c (ft_lzw_file_init), src/base/ftstroke.c - (FT_Stroker_ParseOutline), src/base/ftsynth.c - (FT_GlyphSlot_Embolden): Remove dead code. - - * src/base/ftpatent.c (_tt_check_patents_in_table): Initialize - `offset_i' and `length_i'. - -2010-01-05 Ralph Giles - - Enable the incremental font interface by default. - - Ghostscript requires the incremental font interface for handling - some Postscript documents. It is moving to using FreeType as its - primary renderer; supporting this in the default build makes it - Ghostscript to be linked against the system FreeType when one is - available. - - * include/freetype/config/ftoption.h (FT_CONFIG_OPTION_INCREMENTAL): - Uncomment. - -2010-01-05 Werner Lemberg - - Fix Savannah bug #28395. - - * src/truetype/ttdriver.c (Load_Glyph), src/type1/t1gload.c - (T1_Load_Glyph): Don't check `num_glyphs' if incremental interface - is used. - -2010-01-05 Ken Sharp - - Make Type 1 `seac' operator work with incremental interface. - This fixes Savannah bug #28480. - - * src/psaux/t1decode.c (t1operator_seac): Don't check `glyph_names' - if incremental interface is used. - -2010-01-04 Ken Sharp - - Make incremental interface work with TrueType fonts. - This fixes Savannah bug #28478. - - * src/truetype/ttgload.c (load_truetype_glyph): Don't check - `glyf_offset' if incremental interface is used. - -2009-12-31 Lars Abrahamsson - - Make compilation with FT_CONFIG_OPTION_PIC work again. - - * src/base/ftglyph.c (FT_Glyph_To_Bitmap) [FT_CONFIG_OPTION_PIC]: - Declare `library' for FT_BITMAP_GLYPH_CLASS_GET. - - * src/base/ftinit.c (ft_destroy_default_module_classes, - ft_create_default_module_classes): Use proper casts (needed for C++ - compilation). - - * src/sfnt/ttcmap.c (tt_cmap13_class_rec): Use FT_DEFINE_TT_CMAP. - -2009-12-22 Marc Kleine-Budde - - Make freetype-config aware of $SYSROOT. - This is Savannah patch #7040. - - * builds/unix/freetype-config.in: Decorate with ${SYSROOT} where - appropriate. - -2009-12-20 Werner Lemberg - - Fix compiler warning. - Reported by Sean. - - * src/base/ftdbgmem.c [!FT_DEBUG_MEMORY]: ANSI C doesn't like empty - source files; however, some compilers warn about an unused variable - declaration. This is now replaced with a typedef. - -2009-12-18 Werner Lemberg - - Fix Savannah bug #28320. - - There exist corrupt, subsetted fonts (embedded in PDF files) which - contain a private dict that ends with an unterminated floating point - number (no operator following). We now ignore this error (as - acrobat does). - - * src/cff/cffparse.c (cff_parser_run): Don't emit a syntax error for - unterminated floating point numbers. - -2009-12-16 Werner Lemberg - - Really fix compiler warnings. - Reported by Sean. - - * src/truetype/ttgxvar.c (GX_PT_POINTS_ARE_WORDS, - GX_PT_POINT_RUN_COUNT_MASK): Convert enum values to macros. - -2009-12-16 suzuki toshiya - - Improve configure.raw to copy some options from CFLAGS to LDFLAGS. - The linker of Mac OS X 10.6 is sensitive to the architecture. If - the architectures are specified explicitly for the C compiler, the - linker requires the architecture specifications too. - - * builds/unix/configure.raw: Replace `-isysroot' option parser by - more generic argument parser. - -2009-12-15 Werner Lemberg - - Fix compiler warnings. - Reported by Sean. - - * src/truetype/ttgxvar.c (ft_var_readpackeddeltas): Fix counter data - type. - -2009-12-14 Ken Sharp - - Ignore invalid `setcurrentpoint' operations in Type 1 fonts. - This fixes Savannah bug #28226. - - At least two wild PostScript files of unknown provenance contain - Type 1 fonts, apparently converted from TrueType fonts in earlier - PDF versions of the files, which use the `setcurrentpoint' operator - inappropriately. - - FreeType currently throws an error in this case, but Ghostscript and - Adobe Distiller both accept the fonts and ignore the problem. This - commit #ifdefs out the check so PostScript interpreters using - FreeType can render these files. - - The specification says `setcurrentpoint' should only be used to set - the point after a `Subr' call, but these fonts use it to set the - initial point to (0,0). Unnecessarily so, as they correctly use an - `hsbw' operation which implicitly sets the initial point. - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings) - : Comment out code. - -2009-12-14 Bram Tassyns - - Fix parsing of /CIDFontVersion. - This fixes Savannah bug #28287. - - * src/cid/cidtoken.h: `cid_version' in CID_FaceInfoRec (in - t1tables.h) is of type FT_Fixed. - -2009-12-14 Werner Lemberg - - Trace glyph index in CID module. - Suggested in Savannah patch #7023. - - * src/cid/cidgload.c (cid_load_glyph): Add tracing message. - -2009-12-03 Werner Lemberg - - Fix compiler warnings. - - * src/truetype/ttgload.c (tt_get_metrics): Put `Exit' label into the - proper preprocessor conditional. - * src/pfr/pfrobjs.c (pfr_slot_load): Pacify gcc. - -2009-11-25 John Tytgat - - Better handling of start of `eexec' section. - This fixes Savannah bug #28090. - - * src/type1/t1parse.c (T1_Get_Private_Dict): Skip all whitespace - characters before start of `eexec' section. - -2009-11-20 Werner Lemberg - - Fix Savannah bug #27742. - - * src/base/ftstroke.c (ft_stroker_outside): Avoid silent division by - zero, using a threshold for `theta'. - -2009-11-20 Werner Lemberg - - Fix Savannah bug #28036. - - * src/type1/t1afm.c (t1_get_index): Fix comparison. - -2009-11-16 Werner Lemberg - - Fix compiler warnings. - Reported by Kevin Blenkinsopp . - - * src/sfnt/ttload.c (check_table_dir): Use proper data type. - -2009-11-15 Werner Lemberg - - Really fix FreeDesktop bug #21197. - This also fixes Savannah bug #28021. - - * src/autofit/aflatin.c (af_latin_metrics_check_digits), - src/autofit/aflatin2.c (af_latin2_metrics_check_digits): Fix loop. - -2009-11-15 Werner Lemberg - - Add tracing messages for advance values. - - * src/base/ftobjs.c (FT_Load_Glyph), src/truetype/ttgload.c - (TT_Get_HMetrics, TT_Get_VMetrics): Do it. - -2009-11-08 Werner Lemberg - - Fix compiler warning. - Reported by Jeremy Manson . - - * src/truetype/ttgload.c (load_truetype_glyph): Initialize `error'. - -2009-11-04 Werner Lemberg - - Remove compiler warning. - Reported by Sean McBride . - - * src/tools/apinames.c (read_header_file): Use a cast to - `int', as specified in the printf(3) man page. - -2009-11-04 Werner Lemberg - - Fix Savannah bug #27921. - - * src/cff/cffobjs.c (cff_face_init), src/cid/cidobjs.c - (cid_face_init), src/type1/t1afm.c (T1_Read_Metrics), - src/type1/t1objs.c (T1_Face_Init): Don't use unsigned constant - values for rounding if the argument can be negative. - -2009-11-03 Bram Tassyns - - Add basic support for Type1 charstrings in CFF. - This fixes Savannah bug #27922. - - * src/cff/cffgload.c (CFF_Operator, cff_argument_counts): Handle - `seac', `sbw', and `setcurrentpoint' opcodes. - (cff_compute_bias): Add parameter to indicate the charstring type. - Update all callers. - (cff_operator_seac): Add parameter for side bearing. - (cff_decoder_parse_charstrings): Updated for more Type1 support. - -2009-11-03 Werner Lemberg - - Return correct `linearHoriAdvance' value for embedded TT bitmaps too. - Reported by Jeremy Manson . - - src/truetype/ttgload.c (load_truetype_glyph): Add parameter to - quickly load the glyph header only. - Update all callers. - (tt_loader_init): Add parameter to quickly load the `glyf' table - only. - Update all callers. - (TT_Load_Glyph): Compute linear advance values for embedded bitmap - glyphs too. - -2009-11-03 Werner Lemberg - - Improve code readability. - - * src/ttgload.c (load_truetype_glyph): Move metrics calculation - to... - (tt_get_metrics): This new function. - -2009-10-26 Bram Tassyns - - Fix Savannah bug #27811. - - * src/truetype/ttxgvar.c (ft_var_readpackeddeltas): Fix - signed/unsigned mismatch. - -2009-10-19 Ning Dong - - Fix handling of `get' and `put' CFF instructions. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings) : Appendix B of Adobe Technote #5177 limits the number of - elements for the `get' and `put' operators to 32. - * src/cff/cffgload.h (CFF_MAX_TRANS_ELEMENTS): Define. - (CFF_Decoder): Use it for `buildchar' and remove `len_buildchar'. - -2009-10-18 Werner Lemberg - - Fix handling of `dup' CFF instruction. - Problem and solution reported by Ning Dong . - - * src/cff/cffgload.c (cff_decoder_parse_charstrings) : - Increase `args' by 2, not 1. - -2009-10-10 Werner Lemberg - - * Version 2.3.11 released. - ========================== - - - Tag sources with `VER-2-3-11'. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.3.11. - - * README, Jamfile (RefDoc), builds/win32/visualc/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualce/index.html, - builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj: s/2.3.10/2.3.11/, s/2310/2311/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 11. - - * builds/unix/configure.raw (version_info): Set to 9:22:3. - -2009-10-10 Werner Lemberg - - * docs/CHANGES, docs/release: Updated. - -2009-10-10 suzuki toshiya - - * src/pcf/pcfread.c (pcf_get_properties): Fix a bug in the nprops - truncation. Reported by Martin von Gagern and Peter Volkov. - https://bugs.gentoo.org/288357 and https://bugs.gentoo.org/288256 - -2009-10-06 Werner Lemberg - - * Version 2.3.10 released. - ========================== - - - Tag sources with `VER-2-3-10'. - - * builds/toplevel.mk (major, minor, patch): Fix regexp to allow more - than a single digit. - (dist): We now use git. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.3.10. - - * README, Jamfile (RefDoc), builds/win32/visualc/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualce/index.html, - builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj: s/2.3.9/2.3.10/, s/239/2310/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 10. - - * builds/unix/configure.raw (version_info): Set to 9:21:3. - -2009-10-06 Werner Lemberg - - Fix `make multi'. - - * src/cache/ftccache.c, src/cache/ftcsbits.c (FT_COMPONENT): Define. - - * src/sfnt/sfdriver.c: Include FT_INTERNAL_DEBUG_H. - -2009-09-27 suzuki toshiya - - [cache] Fix Savannah bug #27441, clean up Redhat bugzilla #513582. - Tricky casts in FTC_{CACHE,GCACHE,MRULIST}_LOOKUP_CMP() are removed. - Now these functions should be called with FTC_Node or FTC_MruNode - variable, and the caller should cast them to appropriate pointers to - concrete data. These tricky casts can GCC-4.4 optimizer (-O2) - confused and the crashing binaries are generated. - - * src/cache/ftcmru.h (FTC_MRULIST_LOOKUP_CMP): Drop tricky cast. - Now the 4th argument `node' of this function should be typed as - FTC_MruNode. - - * src/cache/ftcglyph.h (FTC_GCACHE_LOOKUP_CMP): For inline - implementation, new temporal variable FTC_MruNode `_mrunode' to take - the pointer from FTC_MRULIST_LOOKUP_CMP(). For non-inline - implementation, tricky cast is dropped. - - * src/cache/ftcmanag.c (FTC_SIZE_NODE): New macro casting - to FTC_SizeNode. - (FTC_Manager_LookupSize): Replace FTC_SizeNode `node' by FTC_MruNode - `mrunode', and FTC_SIZE_NODE() is inserted. - (FTC_FACE_NODE): New macro casting to FTC_FaceNode. - (FTC_Manager_LookupFace) Replace FTC_FaceNode `node' by FTC_MruNode - `mrunode', and FTC_FACE_NODE() is inserted. - - * src/cache/ftcbasic.c (FTC_ImageCache_Lookup): Change the type of - `node' from FTC_INode to FTC_Node. Extra casting macro FTC_NODE() - is dropped. - (FTC_ImageCache_LookupScaler): Ditto. - (FTC_SBitCache_Lookup): Change the type of `node' from FTC_SNode to - FTC_Node. Extra casting macro FTC_NODE() is dropped. FTC_SNODE() - is inserted. - (FTC_SBitCache_LookupScaler): Ditto. - - * src/cache/ftccmap.c (FTC_CMapCache_Lookup): Change the type of - `node' from FTC_CMapNode to FTC_Node. Extra casting macro - FTC_NODE() is dropped, FTC_CMAP_NODE() is inserted. - -2009-09-25 suzuki toshiya - - [cache, psaux, type1] Fix for multi build. - In multi build, some cpp functions are left as unresolved symbols. - - * src/cache/ftcbasic.c: Include FT_INTERNAL_DEBUG_H for FT_TRACE1(). - - * src/psaux/t1decode.c: Include FT_INTERNAL_CALC_H for - FIXED_TO_INT(). - * src/type1/t1gload.c: Ditto. - * src/type1/t1objs.c: Ditto. - -2009-09-25 suzuki toshiya - - [autofit] Fix for multi build. - - * src/autofit/afmodule.h: Include FT_INTERNAL_OBJECTS_H to use - FT_DECLARE_MODULE() macro in multi build. - - * src/autofit/aflatin.c: Include to handle - FT_ADVANCES_H correctly in multi build. - -2009-09-24 suzuki toshiya - - [cache] Check the face filled by FTC_Manager_LookupFace(). - - * src/cache/ftcbasic.c (ftc_basic_family_get_count): Return - immediately if FTC_Manager_LookupFace() fills face by NULL. Such - case can occur when the code is optimized by GCC-4.2.x. - -2009-09-23 Werner Lemberg - - * docs/CHANGES: Updated. - -2009-09-12 Werner Lemberg - - [raster] Fix 5-levels grayscale output. - This was broken since version 2.3.0. - - * src/raster/ftraster.c (count_table): Use pre-2.3.0 values (which - were then computed dynamically). - (Vertical_Gray_Sweep_Step): Updated. - - (ft_black_render): Initialize `worker->gray_lines' (problem found by - valgrind). - - (FT_RASTER_OPTION_ANTI_ALIASING, DEBUG_RASTER): Don't #undef, just - comment out. - -2009-09-12 suzuki toshiya - - Improve configure.raw for cross build. - - * builds/unix/configure.raw: Remove temporal files created by the - suffix checking for CC_BUILD. Set XX_ANSIFLAGS and XX_CFLAGS when - cross compiler is GCC. AC_PROG_CC checks whether the cross compiler - is GCC, its result is stored in GCC. - -2009-09-12 suzuki toshiya - - [BDF] Modify hash API to take size_t value instead of void *. - - The hash API in BDF driver is designed to be generic, it takes - void * typed data. But BDF driver always gives an unsigned long - integer (the index to a property). To reduce non-essential - casts from unsigned long to void* and from void* to unsigned - long, the hash API is changed to take size_t integer. - The issue of incompatible cast between unsigned long and void* - on LLP64 platform is reported by NightStrike from MinGW-Win64 - project. See - https://lists.gnu.org/archive/html/freetype/2009-09/msg00000.html - - * src/bdf/bdf.h: The type of hashnode->data is changed from - void* to size_t. - - * src/bdf/bdflib.c (hash_insert): Get size_t data, instead of - void* data. - (bdf_create_property): Get the name length of new property by - size_t variable, with a cut-off at FT_ULONG_MAX. - (_bdf_set_default_spacing): Get the name length of the face by - size_t variable, with a cut-off at 256. - (bdf_get_property): Get the property id by size_t variable to - reduce the casts between 32-bit prop ID & hashnode->data during - simple copying. - (_bdf_add_property): Ditto. - (_bdf_parse_start): Calculate the index to the property array - by size_t variable. - (bdf_get_font_property): Drop a cast to unsigned long. - -2009-09-10 suzuki toshiya - - [Win64] Improve the computation of random seed from stack address. - - On LLP64 platform, the conversion from pointer to FT_Fixed need - to drop higher 32-bit. Explicit casts are required. Reported by - NightStrike from MinGW-w64 project. See - https://lists.gnu.org/archive/html/freetype/2009-09/msg00000.html - - * src/cff/cffgload.c: Convert the pointers to FT_Fixed explicitly. - - * src/psaux/t1decode.c: Ditto. - - -2009-09-03 Werner Lemberg - - [raster] Improvements for stand-alone mode. - - * src/raster/rules.mk: Don't handle ftmisc.h. It is needed for - stand-alone mode only. - - * src/raster/ftmisc.h (FT_MemoryRec, FT_Alloc_Func, FT_Free_Func, - FT_Realloc_Func): Copy declarations from ftsystem.h. - -2009-09-02 Bram Tassyns - - Improve vertical metrics calculation (Savannah bug #27364). - - The calculation of `vertBearingX' is not defined in the OTF font - spec so FreeType does a `best effort' attempt. However, this value - is defined in the PDF and PostScript specs, and that algorithm is - better than the one FreeType currently uses: - - FreeType: Use the middle of the bounding box as the X coordinate - of the vertical origin. - - Adobe PDF spec: Use the middle of the horizontal advance vector as - the X coordinate of the vertical origin. - - FreeType's algorithm goes wrong if you have a really small glyph - (like the full-width, circle-like dot at the end of the sentence, as - used in CJK scripts) with large bearings. With the FreeType - algorithm this dot gets centered on the baseline; with the PDF - algorithm it gets the correct location (in the top right). Note - that this is a serious issue, it's like printing the dot at the end - of a Roman sentence at the center of the textline instead of on the - baseline like it should. So i believe the PDF spec's algorithm - should be used in FreeType as well. - - The `vertBearingY' value for such small glyphs is also very strange - if no `vmtx' information is present, since the height of the bbox is - not representable for the height of the glyph visually (the - whitespace up to the baseline is part of the glyph). The fix also - includes some code for a better estimate of `vertBearingY'. - - * src/base/ftobjs.c (ft_synthesize_vertical_metrics): `vertBearingX' - is now calculated as described by the Adobe PDF Spec. Estimate for - `vertBearingY' now works better for small glyphs completely above or - below the baseline into account. - - * src/cff/cffgload.c (cff_slot_load): `vertBearingX' is now - calculated as described by the Adobe PDF Spec. Vertical metrics - information was always ignored when FT_CONFIG_OPTION_OLD_INTERNALS - was not defined. - - * src/truetype/ttgload.c (compute_glyph_metrics): `vertBearingX' is - now calculated as described by the Adobe PDF Spec. - -2009-09-01 John Tytgat - - Fix custom cmap for empty Type 1 font (Savannah bug #27294). - - * include/freetype/internal/t1types.h (T1_EncodingRecRec_): Update - comment to reflect revised code_last meaning. - * src/type1/t1load.c (T1_Open_Face), src/type42/t42objs.c - (T42_Open_Face): Assign max_char as highest character code + 1 and - use this for T1_EncodingRecRec_::code_last. - * src/psaux/t1cmap.c (t1_cmap_custom_init): Follow revised - T1_EncodingRecRec_::code_last meaning. - -2009-08-25 Werner Lemberg - - Fix rendering of horizontally compressed CFFs. - Bug reported by Ivan Nincic . - - * src/cff/cffgload.c (cff_slot_load): Thinko: Check `xx' element of - `font_matrix' also. - - * docs/CHANGES: Updated. - -2009-08-03 suyu0925@gmail.com - - Don't call `ft_fseek' every time when executing `ft_fread'. - - * src/base/ftstream.c (FT_Stream_Seek), src/base/ftsystem.c - (ft_ansi_stream_io): Implement it. - -2009-07-31 suzuki toshiya - - sfnt: Cast a charcode to 32-bit in cmap format 14 parser. - - * src/sfnt/ttcmap.c (tt_cmap14_char_var_index, - tt_cmap14_char_var_isdefault, tt_cmap14_char_variants, - tt_cmap14_variant_chars): Correct mismatches from - FT_CMap_CharVarIndexFunc prototype, FT_ULong arguments - are replaced by FT_UInt32 arguments. - -2009-07-31 suzuki toshiya - - sfnt: Cast a charcode to 32-bit in cmap format 12 parser. - - * src/sfnt/ttcmap.c (tt_cmap12_char_next): - Insert explicit cast from FT_UFast to FT_UInt32 - for return value. - -2009-07-31 suzuki toshiya - - psaux: Fix a few casts to FT_Int32 value. - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings): - Fix a few casts setting `value' from FT_Long to FT_Int32, - because `value' is typed as FT_Int32 since 2009-06-22. - -2009-07-31 suzuki toshiya - - sfnt: Fix a data type mismatching with its source. - - * src/sfnt/ttcmap.c (tt_cmap13_char_next): Fix the - type of `gindex' from FT_ULong to FT_UInt because - it is set by FT_UInt tt_cmap13_char_map_binary() or - TT_CMap13->cur_gindex. - -2009-07-31 suzuki toshiya - - sfnt: Extend a few local variables to load 32-bit values. - - * src/sfnt/ttkern.c (tt_face_load_kern): Extend `count' - and `kern' to load 32-bit values. - -2009-07-31 suzuki toshiya - - pfr: Extend `num_aux' to take 32-bit value. - - * src/pfr/pfrload.c (pfr_phy_font_load): Extend - `num_aux' to load 32-bit value. - -2009-07-31 suzuki toshiya - - pcf: Truncate FT_ULong `nprops' to fit to int PCF_Face->nprops. - - * src/pcf/pcfread.c (pcf_get_properties): Load `nprops' - as FT_ULong value from PCF file, but truncate it as - int to fit PCF_Face->nprops. The number of truncated - properties is shown in the trace message. - -2009-07-31 suzuki toshiya - - gxvalid: Extend a few local variables to reduce the casts. - - * src/gxvalid/gxvmorx.c (gxv_morx_subtables_validate): - Extend `type' and `rest' to take FT_ULong values. - -2009-07-31 suzuki toshiya - - gxvalid: Extend `settingTable' to take 32-bit offset. - - * src/gxvalid/gxvfeat.c (gxv_feat_name_validate): - Extend `settingTable' to take 32-bit offset. - -2009-07-31 suzuki toshiya - - autofit: Cast FT_Long glyph_count to compare with FT_UInt GID. - - * src/autofit/afglobal.c (af_face_globals_is_digit, - af_face_globals_compute_script_coverage): Cast FT_Long - globals->glyph_count to FT_ULong, to compare with FT_UInt - gindex. - -2009-07-31 suzuki toshiya - - smooth: Exclude 16-bit system in invalid pitch/height check. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): - pitch and height are typed as FT_UInt but checked to fit - 16-bit range, to avoid the overflows. On 16-bit system, - this checking inserts a conditional that never occurs. - -2009-07-03 suzuki toshiya - - cff: Type large constants > 0x7FFF as long for 16-bit systems. - - * src/cff/cffload.c (cff_charset_load): Type large - constants > 0x7FFF as long, because normal constants - are typed signed integer that is less than 0x8000 on - 16-bit systems. - -2009-07-31 suzuki toshiya - - base: Remove an unused variable. - - * src/base/ftglyph.c (FT_Glyph_To_Bitmap): Remove an - unused variable `library'. glyph->library is used. - -2009-07-31 suzuki toshiya - - cache: Check higher bits in flags for non ILP32 systems. - - 4 public functions ought to take FT_ULong flags, but take - FT_UInt flags. To keep binary compatibility, we drop higher - bits on non ILP32 platforms, - ILP64 systems: No drop occurs. - LP64 systems: Higher bits are not used. - 16-bit systems: Drop can occur. - See - https://lists.gnu.org/archive/html/freetype-devel/2008-12/msg00065.html - These functions will be refined to take FT_ULong flags in - next bump with incompatible API change. - - * src/cache/ftcbasic.c (FTC_ImageCache_Lookup): - Check `flags' in `type', the 2nd argument. - (FTC_SBitCache_Lookup): Ditto. - (FTC_ImageCache_LookupScaler): Check `load_flags', - the 3rd argument. - (FTC_SBitCache_LookupScaler): Ditto. - -2009-07-31 suzuki toshiya - - sfnt: Ignore invalid GIDs in glyph name lookup. - - * include/freetype/internal/fttrace.h: - New trace module for sfdriver.c is added. - - * src/sfnt/sfdriver.c (sfnt_get_name_index): - Restrict glyph name lookup to FT_UInt GID. - Genuine TrueType can hold 16-bit glyphs. - -2009-07-31 suzuki toshiya - - pcf: Fix a comparison between FT_Long and FT_ULong. - - * src/pcf/pcfread.c (pcf_get_bitmaps): Return an error - if PCF_Face->nmetrics is negative. - -2009-07-31 suzuki toshiya - - gxvalid: Guarantee `nFeatureFlags' size up to 32-bit. - - * src/gxvalid/gxvmort.c (gxv_mort_featurearray_validate): - Extend the 3rd argument `nFeatureFlags' to FT_ULong. - * src/gxvalid/gxvmort.h: Ditto. - -2009-07-31 suzuki toshiya - - sfnt: Insert explicit cast for LP64 system. - - * src/sfnt/ttkern.c (tt_face_load_kern): Insert - cast from unsigned long to FT_UInt32. - -2009-07-31 suzuki toshiya - - gxvalid: Guarantee `just' table size upto 32-bit. - - * src/gxvalid/gxvjust.c (gxv_just_validate): - The type of `offset' is changed from FT_UInt to - FT_Offset, for 16-bit platforms. - -2009-07-31 suzuki toshiya - - gxvalid: Guarantee `trak' table size upto 32-bit. - - * src/gxvalid/gxvtrak.c (gxv_trak_validate): - The type of `offset' is changed from FT_UInt to - FT_Offset, for 16-bit platforms. - -2009-07-31 suzuki toshiya - - type1: Fix a data type mismatching with its source. - - * include/freetype/internal/t1types.h: The type of - T1_Face->buildchar is matched with T1_Decoder->top. - -2009-07-31 suzuki toshiya - - pfr: Fix a data type mismatching with its source. - - * src/pfr/pfrtypes.h: The type of PFR_KernItem->offset - is extended from FT_UInt32 to FT_Offset, because it is - calculated with the pointer difference, in - pfr_extra_item_load_kerning_pairs(). - -2009-07-31 suzuki toshiya - - pfr: Fix a data type mismatching with its source. - - * src/pfr/pfrtypes.h: The type of PFR_PhyFont->chars_offset - is extended from FT_UInt32 to FT_Offset, because it is - calculated with the pointer difference in pfr_phy_font_load(). - -2009-07-31 suzuki toshiya - - pfr: Fix a data type mismatching with its source. - - * src/pfr/pfrtypes.h: The type of PFR_PhyFont->bct_offset - is extended from FT_UInt32 to FT_Long, because it is - loaded by FT_STREAM_POS() in pfr_phy_font_load(). - -2009-07-31 suzuki toshiya - - smooth: Improve the format in debug message. - - * src/smooth/ftgrays.c (gray_dump_cells): Improve the - format specifications to dump variables. - -2009-07-31 suzuki toshiya - - sfnt: Fix a data type mismatching with its source. - - * src/sfnt/sfobjs.c (sfnt_load_face): The type of - local `flags' is matched with FT_Face->face_flags. - -2009-07-31 suzuki toshiya - - psaux: Fix a data type mismatching with its source. - - * include/freetype/internal/psaux.h: The type of - T1_DecoderRec.buildchar is matched with - T1_DecoderRec.top. - -2009-07-31 suzuki toshiya - - truetype: Extend TrueType GX packed deltas to FT_Offset. - - * src/truetype/ttgxvar.c (ft_var_readpackeddeltas): - The type of 2nd argument `delta_cnt' is changed from - FT_Int to FT_Offset, because its source can be cvt - table size calculated from stream position. - -2009-07-31 suzuki toshiya - - truetype: Extend mmvar_len to hold size_t values. - - * src/truetype/ttgxvar.h: The type of - GX_BlendRec.mmvar_len is changed from FT_Int to - FT_Offset, because TT_Get_MM_Var() calculates it - by sizeof() results. - -2009-07-31 suzuki toshiya - - truetype: Check invalid function number in IDEF instruction. - - * src/truetype/ttinterp.c (Ins_IDEF): Check - if the operand fits to 8-bit opcode limitation. - -2009-07-31 suzuki toshiya - - truetype: Check invalid function number in FDEF instruction. - - * src/truetype/ttinterp.c (Ins_FDEF): Check - if the operand fits 16-bit function number. - -2009-07-31 suzuki toshiya - - truetype: Truncate the deltas of composite glyph at 16-bit values. - - * src/truetype/ttgload.c (load_truetype_glyph): - Insert cast from FT_Long (deltas[i].{x,y}) to - FT_Int16 in the summation of deltas[] for composite - glyphs. Because deltas[i] is typed as FT_Pos, - its component x, y are typed as FT_Long, but - their sources are always FT_Int16 when they are - loaded by ft_var_readpackeddeltas(). However, - the limitation about the summed deltas is unclear. - -2009-07-31 suzuki toshiya - - truetype: Truncate the instructions upto 16-bit per a glyph. - - * src/truetype/ttgload.c (TT_Hint_Glyph): Truncate - the instructions upto 16-bit length per a glyph. - -2009-07-31 suzuki toshiya - - truetype: Cast the numerical operands to 32-bit for LP64 systems. - - * src/truetype/ttinterp.c (Ins_SPHIX, INS_MIAP, - Ins_MIRP): Insert cast from long (args[], the - operands passed to TrueType operator) to FT_Int32 - (the argument of TT_MulFix14()). - -2009-07-31 suzuki toshiya - - truetype: Cast the project vector to 32-bit for LP64 system. - - * src/truetype/ttinterp.c (Project, DualProject): - Insert casts from FT_Pos (the arguments `dx', `dy') - to FT_UInt32 (the argument to TT_DotFix14()). - -2009-07-31 suzuki toshiya - - truetype: Cast the scaling params to 32-bit for LP64 system. - - * src/truetype/ttgload.c (TT_Process_Composite_Component): - Insert casts from long (return value of FT_MulFix()) to - FT_Int32 (the argument to FT_SqrtFixed()). - -2009-07-31 suzuki toshiya - - sfnt: Cast a character code to FT_UInt32 for LP64 system. - - * src/sfnt/ttcmap.c (tt_cmap14_char_map_nondef_binary, - tt_cmap14_variants, tt_cmap14_char_variants, - tt_cmap14_def_char_count, tt_cmap14_get_def_chars, - tt_cmap14_get_nondef_chars, tt_cmap14_variant_chars) - Insert casts when FT_UInt32 variable is loaded by - TT_NEXT_{UINT24|ULONG}. Because most of them are - compared with FT_UInt32 values in public API, replacing - FT_UFast is not recommended. - -2009-07-31 suzuki toshiya - - sfnt: Cast a character code to FT_UInt32 for LP64 system. - - * src/sfnt/ttcmap.c (tt_cmap4_init, tt_cmap4_next): - Insert the casts from unsigned long constant to - FT_UInt32. - -2009-07-31 suzuki toshiya - - sfnt: Extend TT_BDF->strings_size to FT_ULong for huge BDF. - - * include/freetype/internal/tttypes.h: The type - of TT_BDF->string_size is extended from FT_UInt32 - to FT_ULong, because BDF specification does not - restrict the length of string. - * src/sfnt/ttbdf.c: The scratch variable `strings' - to load TT_BDF->string_size is matched with - TT_BDF->string_size. - -2009-07-31 suzuki toshiya - - psaux: Handle the string length by FT_Offset variables. - - * src/psaux/afmparse.c (afm_parser_next_key, - afm_tokenize, afm_parse_track_kern, - afm_parse_kern_pairs, afm_parse_kern_data, - afm_parser_skip_section, afm_parser_parse): - The length of key is handled by FT_Offset, - instead of FT_UInt. Although the length of - PostScript strings or name object is 16-bit, - AFM_STREAM_KEY_LEN() calculates the length - from the pointer difference. - - * src/psaux/afmparse.h (afm_parser_next_key): - Ditto. - -2009-07-31 suzuki toshiya - - pcf: Fix some data types mismatching with their sources. - - * src/pcf/pcfread.c (pcf_get_bitmaps): The types - of `nbitmaps', `i', `sizebitmaps' are matched with - the type of area FT_Bitmap.pitch * FT_Bitmap.rows. - -2009-07-31 suzuki toshiya - - pcf: Handle the string length by size_t variables. - - * src/pcf/pcfread.c (pcf_interpret_style): The types - of nn, len, lengths[4] are changed to size_t, because - they are loaded by (or compared with) ft_strlen(). - - * src/pcf/pcfutil.c (BitOrderInvert, TwoByteSwap, - FourByteSwap): The type of the 2nd argument `nbytes' - is changed to size_t, for similarity with ANSI C - string functions. - - * src/pcf/pcfdrivr.c (PCF_Glyph_Load): The type of - `bytes' is changed to FT_Offset, because it is passed - to FT_ALLOC(), via ft_glyphslot_alloc_bitmap(). At - least, using unsigned type is better. - -2009-07-31 suzuki toshiya - - pcf: Fix some data types mismatching with their sources. - - * src/pcf/pcfread.c (pcf_seek_to_table_type, - pcf_has_table_type): The type of 3rd argument - `ntables' is matched with PCF_Toc->count. - -2009-07-31 suzuki toshiya - - otvalid: Truncate the glyph index to 16-bit. - - * src/otvalid/otvalid.c (otv_validate): Checks - face->num_glyphs does not exceed 16-bit limit, - pass FT_UInt num_glyphs to backend functions - otv_{GPOS|GSUB|GDEF|JSTF|MATH}_validate(). - -2009-07-31 suzuki toshiya - - cache: Insert explicit casts for LP64 systems. - - * src/cache/ftcbasic.c (FTC_ImageCache_Lookup, - FTC_SBitCache_Lookup): The type of FTC_ImageType->width - is FT_Int, so the cast to unsigned larger type FT_ULong - is introduced for the comparisons with 0x10000L for - LP64 platform. - -2009-07-31 suzuki toshiya - - cache: Fix some data types mismatching with their sources. - - * src/cache/ftccache.h: The type of return value - by FTC_Node_WeightFunc function is changed to - FT_Offset. The type of FTC_CacheClass->cache_size - is changed to FT_Offset, too. - - * src/cache/ftccback.h (ft_inode_weight, - ftc_snode_weight): Ditto. - - * src/cache/ftccmap.c (ftc_cmap_node_weight): Ditto. - - * src/cache/ftcimage.c (ftc_inode_weight, - FTC_INode_Weight): Ditto. - - * src/cache/ftcsbits.c (ftc_snode_weight, - FTC_SNode_Weight): Ditto. - - * src/cache/ftcmru.h: The type of - FTC_MruListClass->node_size is changed to FT_Offset, - because it is passed to FT_ALLOC() to specify the - size of buffer. - -2009-07-31 suzuki toshiya - - XXX_cmap_encoding_char_next() return FT_UInt32 values. - - * include/freetype/internal/services/svpscmap.h: - The size of the charcode value returned by - the function typed PS_Unicodes_CharNextFunc is - matched with its input charcode value. - - * src/cff/cffmap.c (cff_cmap_encoding_char_next, - cff_cmap_unicode_char_next): Ditto. - - * src/pfr/pfrmap.c (pfr_cmap_encoding_char_next): - Ditto. - - * src/psaux/t1cmap.c (t1_cmap_std_char_next, - t1_cmap_custom_char_next, t1_cmap_unicode_char_next): - Ditto. - - * src/psnames/psmodule.c (ps_unicodes_char_next): - Ditto. - - * src/winfonts/winfnt.c (fnt_cmap_char_next): - Ditto. - - * src/sfnt/ttcmap.c (tt_cmap0_char_next, - tt_cmap2_char_next, tt_cmap4_char_next, - tt_cmap6_char_next, tt_cmap10_char_next, - tt_cmap12_char_next, tt_cmap13_char_next): Ditto. - (tt_cmap14_char_variants): Handle base unicode - codepoint by FT_UInt32 variable to avoid overflow - on 16-bit platforms. - (tt_cmap14_ensure): The type of `num_results' is - extend to FT_UInt32, to cover unsigned 32-bit - `numVarSelectorRecords' in cmap14 table header. - -2009-07-31 suzuki toshiya - - truetype: Extend TT_Face->num_locations for broken TTFs. - - * include/freetype/internal/tttypes.h: - TT_Face->num_locations are extended from FT_UInt - to FT_ULong, to stand with broken huge loca table. - Some people insists there are broken TTF including - the glyphs over 16-bit limitation, in PRC market. - * src/truetype/ttpload.c (tt_face_load_loca): - Remove unrequired 16-bit truncation for FT_UInt - TT_Face->num_locations. - -2009-07-31 suzuki toshiya - - smooth: Fix some data types mismatching with their sources. - - * src/smooth/ftgrays.c: The type of `TCoord' is - matched to `TPos', because they are mixed in - gray_set_cell(). The type of TCell->x is extended - to `TPos', because gray_find_cell() sets it by - TWorker.ex. The type of TCell->cover is extended - to `TCoord', because gray_render_scanline() adds - TCoord value to it. The type of TWork.cover is matched - with TCell->cover. The types of - TWork.{max_cells,num_cells} are changed to FT_PtrDist, - because they are calculated from the memory addresses. - The type of TWork.ycount is changed to TPos, because - it is calculated from TPos variables. - (gray_find_cell): The type of `x' is matched with - its initial value ras.ex. - (gray_render_scanline): The types of `mod', `lift' - and `rem' are changed to TCoord, because their values - are set with explicit casts to TCoord. When ras.area - is updated by the differential values including - `delta', they are explicitly cast to TArea, because - the type of `delta' is not TArea but TCoord. - (gray_render_line): The type of `mod' is extended - from int to TCoord, because (TCoord)dy is added to mod. - (gray_hline): The argument `acount' is extended to - TCoord, to match with the parameters in the callers. - -2009-07-31 suzuki toshiya - - cff: Fix some data types mismatching with their sources. - - * src/cff/cffobjs.c (cff_face_init): The type of - `scaling' is matched with the scaling parameter - in FT_Matrix_Multiply_Scaled() and - FT_Vector_Transform_Scaled(). - - * src/cff/cffparse.c (cff_parse_real): The type of - `power_ten', `scaling', `exponent_add', - `integer_length', `fraction_length', - `new_fraction_length' and `shift' are matched with - the type of `exponent' to avoid unexpected truncation. - (cff_parse_fixed_scaled): The type of `scaling' is - matched with the `scaling' argument to - cff_parse_real(). - (cff_parse_fixed_dynamic): Ditto. - (cff_parse_font_matrix): The type of `scaling' is - matched with the `scaling' argument to - cff_parse_dynamic(). - -2009-07-31 suzuki toshiya - - autofit: Fix some data types mismatching with their sources. - - * src/autofit/afglobal.c: Correct the type of - AF_FaceGlobalsRec.glyph_count to match with - FT_Face->num_glyphs. - (af_face_globals_compute_script_coverage): - Insert explicit cast to compare - FT_Long AF_FaceGlobalsRec.glyph_count versus - FT_UInt gindex. The type of `nn' is changed - to scan glyph index upto AF_FaceGlobalsRec.glyph_count. - (af_face_globals_get_metrics): The type of `script_max' - is changed to cover size_t value. Insert explicit cast - to compare FT_Long AF_FaceGlobalsRec.glyph_count versus - FT_UInt gindex. - - * src/autofit/afhints.c (af_axis_hints_new_segment): - Insert explicit cast to calculate `big_max' from - integer and size_t values. - (af_axis_hints_new_edge): Ditto. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): - The type of `best_y' is matched to FT_Vector.y. - (af_latin_compute_stem_width): The type of `delta' is - matched to `dist' and `org_dist'. - -2009-07-31 suzuki toshiya - - autofit: Count the size of the memory object by ptrdiff_t. - - * src/autofit/afcjk.c (af_cjk_hint_edges): The - number of edges `n_edges' should be counted by - FT_PtrDist variable instead of FT_Int. - - * src/autofit/aflatin.c (af_latin_hint_edges): - Ditto. - - * src/autofit/aftypes.h: In AF_ScriptClassRec, - the size of metric `script_metrics_size' should - be counted by FT_Offset variable instead of FT_UInt. - - * src/autofit/afhints.c - (af_glyph_hints_align_strong_points): The cursors - for the edges `min', `max', `mid' in the memory - buffer should be typed FT_PtrDist. - -2009-07-31 suzuki toshiya - - autofit: Fix for unused variable `first'. - - * src/autofit/afhints.c (af_glyph_hints_reload): Insert - FT_UNUSED() to hide the unused variable warning. - -2009-07-31 suzuki toshiya - - Improve bitmap size or pixel variables for 16-bit systems. - - * include/freetype/config/ftstdlib.h: Introduce - FT_INT_MIN, to use in signed integer overflow in - 16-bit and 64-bit platforms. - - * include/freetype/internal/fttrace.h: Add a tracer - to ftsynth.c. - - * src/base/ftbitmap.c (FT_Bitmap_Embolden): Check - invalid strength causing integer overflow on 16-bit - platform. - - * src/base/ftcalc.c (ft_corner_orientation): Change - the internal calculation from FT_Int to FT_Long, to - avoid an overflow on 16-bit platforms. The caller of - this function should use only the sign of result, - so the cast to FT_Int is acceptable. - - * src/base/ftsynth.c: Introduce a tracer for synth module. - (FT_GlyphSlot_Embolden): Check invalid strength causing - integer overflow on 16-bit platform. - - * src/bdf/bdfdrivr.c (BDF_Face_Init): The glyph index - in FT2 API is typed as FT_UInt, although BDF driver - can handle unsigned long glyph index internally. To - avoid integer overflow on 16-bit platform, too large - glyph index should be excluded. - (BDF_Glyph_Load): The glyph pitch in FT2 is typed as - FT_UInt, although BDF driver can handle unsigned long - glyph pitch internally. To avoid integer overflow on - 16-bit platform, too large glyph pitch should not be - returned. - - * src/pfr/pfrsbit.c (pfr_slot_load_bitmap): The glyph - pitch in FT2 is typed as FT_UInt, although PFR font - format can include huge bitmap glyph with 24-bit pitch - (however, a glyph spends 16.7 pixel, it's not realistic). - To avoid integer overflow on 16-bit platform, huge - bitmap glyph should be excluded. - - * src/smooth/ftgrays.c (gray_hline): As FT_Span.x is - truncated to fit its type (16-bit short), FT_Span.y - should be truncated to fit its type (FT_Int). - - * src/cff/cffdrivr.c (cff_get_ros): CFF specification - defines the supplement in ROS as a real number. - Truncate it to fit public FT2 API. - - * src/cff/cffparse.c (cff_parse_cid_ros): Warn the - supplement if it is truncated or rounded in cff_get_ros(). - - * src/cff/cfftypes.h: Change the type of internal variable - `supplement' from FT_Long to FT_ULong to fit the signedness - to the type in public API. - -2009-07-31 suzuki toshiya - - psaux: Prevent invalid arguments to afm_parser_read_vals(). - - * src/psaux/afmparse.c (afm_parser_read_vals): Change - the type of `n' to prevent negative number how many - arguments should be parsed. - - * src/psaux/afmparse.h (afm_parser_read_vals): Ditto. - -2009-07-31 suzuki toshiya - - base: Prevent some overflows on LP64 systems. - - * src/base/ftadvanc.c (FT_Get_Advances): Cast the - unsigned long constant FT_LOAD_ADVANCE_ONLY to FT_UInt32 - for LP64 platforms. - - * src/base/ftcalc.c (FT_Sqrt32): All internal variables - are changed to FT_UInt32 from FT_ULong. - (FT_MulDiv): Insert casts to FT_Int32 for LP64 platforms. - This function is designed for 32-bit integer, although - their arguments and return value are FT_Long. - - * src/base/ftobjs.c (FT_Get_Char_Index): Check `charcode' - is within unsigned 32-bit integer for LP64 platforms. - (FT_Face_GetCharVariantIndex): Check `charcode' and - `variantSelector' are within 32-bit integer for LP64 - platforms. - (FT_Face_GetCharsOfVariant): Check `variantSelector' is - within unsigned 32-bit integer for LP64 platforms. - - * src/base/fttrigon.c (ft_trig_downscale): The FT_Fixed - variable `val' and unsigned long constant FT_TRIG_SCALE - are cast to FT_UInt32, when calculates FT_UInt32. - (FT_Vector_Rotate): The long constant 1L is cast to - FT_Int32 to calculate FT_Int32 `half'. - -2009-07-31 suzuki toshiya - - cff: Cast the long variables to 32-bit for LP64 systems. - - * src/cff/cffdrivr.c (cff_get_advances): Insert - explicit cast to modify a 32-bit flag by unsigned - long constant. - - * src/cff/cffobjs.c (cff_face_init): Ditto. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings): - Replace the casts to FT_Long by the casts to FT_Int32 - for LP64 platforms. - -2009-07-31 suzuki toshiya - - pcf: Improve PCF_PropertyRec.value names on LP64 platforms. - - * src/pcf/pcf.h: In PCF_PropertyRec.value, the member - `integer' is replaced by `l', `cardinal' is replaced - by `ul', to fix the difference between the name and - the types on LP64 platforms. - - * src/pcf/pcfdrivr.c (pcf_get_bdf_property): Reflect - PCF_PropertyRec.value change, with appropriate casts - to FT_Int32/FT_UInt32. Their destinations - BDF_PropertyRec.{integer|cardinal} are public and - explicitly defined as FT_Int32/FT_UInt32. - - * src/pcf/pcfread.c (pcf_get_properties, pcf_load_font): - Reflect PCF_PropertyRec.value change. - -2009-07-31 suzuki toshiya - - pcf: Fix some data types mismatching with their sources. - - * src/pcf/pcfdrivr.c (pcf_cmap_char_index): The type of - `code' is matched to PCF_Encoding->enc. - (pcf_cmap_char_next): The type of `charcode' is matched - to PCF_Encoding->enc. When *acharcode is set by charcode, - an overflow is checked and cast to unsigned 32-bit - integer. - -2009-07-31 suzuki toshiya - - bdf: Improve bdf_property_t.value names for LP64 platforms. - - * src/bdf/bdf.h: In bdf_property_t.value, the member - `int32' is replaced by `l', `card32' is replaced by - `ul', to fix the difference between the name and the - types on LP64 platforms. - - * src/bdf/bdfdrivr.c (BDF_Face_Init): Reflect - bdf_property_t.value change. - (bdf_get_bdf_property): Reflect bdf_property_t.value - change, with appropriate casts to FT_Int32/FT_UInt32. - Their destinations BDF_PropertyRec.{integer|cardinal} - are public and explicitly defined as FT_Int32/FT_UInt32. - - * src/bdf/bdflib.c (_bdf_add_property): Reflect - bdf_property_t.value change. - -2009-07-31 suzuki toshiya - - bdf: Fix some data types mismatching with their sources. - - * src/bdf/bdfdrivr.c (bdf_cmap_char_index): The type - of `code' is matched with BDF_encoding_el->enc. - (bdf_cmap_char_next): The type of `charcode' is - matched with BDF_encoding_el->enc. When *acharcode - is set by charcode, an overflow is checked and - cast to unsigned 32-bit integer. - -2009-07-31 suzuki toshiya - - autofit: Improve Unicode range definitions. - - * src/autofit/aftypes.h (AF_UNIRANGE_REC): New macro - to declare a range by two unsigned 32-bit integer, - to avoid 64-bit range definition on LP64 platforms. - - * src/autofit/aflatin.c (af_latin_uniranges): Ditto. - - * src/autofit/aflatin2.c (af_latin2_uniranges): Ditto. - - * src/autofit/afindic.c (af_indic_uniranges): Ditto. - - * src/autofit/afcjk.c (af_cjk_uniranges): Declare - the ranges by AF_UNIRANGE_REC. - -2009-07-31 suzuki toshiya - - smooth: Fix a data type mismatching with its source. - - * src/smooth/ftgrays.c (gray_sweep): The type of - `area' is matched with the 3rd argument `area' - of gray_hline(). - -2009-07-31 suzuki toshiya - - smooth: Fix a data type mismatching with its source. - - * src/smooth/ftgrays.c (gray_render_line): The type - of `area' is matched with TWorker.area. - -2009-07-31 suzuki toshiya - - cache: Disable the legacy compatibility if 16-bit system. - - * src/cache/ftcbasic.c (FTC_ImageCache_Lookup): Exclude - the legacy behaviour from 16-bit platform, because the - current hack cannot detect the caller uses this function - via legacy convention. - (FTC_SBitCache_Lookup): Ditto. - -2009-07-31 suzuki toshiya - - cache: Check 32-bit glyph index on 16-bit systems. - - * src/cache/ftcbasic.c (ftc_basic_family_get_count): - Check overflow caused by the face including large - number of glyphs > 64k. - -2009-07-31 suzuki toshiya - - cache: Fix some data types mismatching with their sources. - - * src/cache/ftccache.c (ftc_cache_resize): The types of - `p', `mask', `count' are matched with FTC_Cache->{p,mask}. - (FTC_Cache_Clear): The type of `old_index' is matched to - FTC_Cache->{p,mask}. - - * src/cache/ftccache.h (FTC_CACHE_LOOKUP_CMP): The type - of `_idx' is matched with FTC_Cache->{p,mask}. - -2009-07-31 suzuki toshiya - - cache: Fix some data types mismatching with their sources. - - * src/cache/ftcsbits.c (ftc_snode_load): The types - of `xadvance' and `yadvance' are matched with - FT_GlyphSlot->advance.{x|y}. - -2009-07-31 suzuki toshiya - - cache: Cast NULL to a required function type explicitly. - - * src/cache/ftcmanag.c (FTC_Manager_RemoveFaceID): - Insert explicit cast from NULL to function type. - -2009-07-31 suzuki toshiya - - fttypes.h: Cast FT_MAKE_TAG output to FT_Tag explicitly. - - * include/freetype/fttypes.h (FT_MAKE_TAG): - Cast the result to FT_Tag. - -2009-07-31 suzuki toshiya - - psnames: Handle Unicode codepoints by FT_UInt32 variables. - - * src/psnames/psmodule.c (BASE_GLYPH): Cast the result - to unsigned 32-bit integer for LP64 platform. - (ps_unicode_value): Return the value by unsigned 32-bit - integer instead of unsigned long. - -2009-07-31 suzuki toshiya - - psaux: Use size_t variable to pass the buffer size. - - * src/psaux/psaux.h (to_bytes): The type of `max_bytes' - (the argument to pass the buffer size) is changed to - size_t, to match with ANSI C string functions. - - * src/psaux/psconv.h (PS_Conv_StringDecode, - PS_Conv_ASCIIHexDecode, PS_Conv_EexecDecode): Ditto. - - * src/psaux/psconv.c (PS_Conv_StringDecode, - PS_Conv_ASCIIHexDecode, PS_Conv_EexecDecode): Ditto. - - * src/psaux/psobjs.h (ps_parser_to_bytes): Ditto. - - * src/psaux/psobjs.c (ps_parser_to_bytes): Ditto. - -2009-07-31 suzuki toshiya - - type1: Use size_t variable to pass the string length. - - * psaux.h: The type of `len' (the argument to pass - the buffer size to the function in AFM_ParserRec) - is changed to size_t, to match with ANSI C string - functions. - - * t1afm.c (t1_get_index): Ditto. - - * test_afm.c (dummy_get_index): Ditto. - - * afmparse.c (afm_parser_read_vals): To call - AFM_ParserRec.get_index, the length of token - `len' is cast to size_t. - -2009-07-31 suzuki toshiya - - cid: Fix some data types mismatching with their sources. - - * src/cid/cidparse.c (cid_parser_new): The types of - `read_len' and `stream_len' are matched to - FT_Stream->size. Unrequired cast is removed. - -2009-07-31 suzuki toshiya - - cff: Fix for unused variable `rest'. - - * src/cff/cffparse.c (cff_parse_real): Insert - FT_UNUSED() to hide the unused variable warning. - -2009-07-31 suzuki toshiya - - cff: Fix some data types mismatching with their sources. - - * src/cff/cffgload.c (cff_slot_load): The types of - `top_upm' and `sub_upm' are matched with - CFF_FontRecDict->units_per_em. - - * src/cff/cffobjs.c (cff_size_select): Ditto. - (cff_size_request): Ditto. - -2009-07-31 suzuki toshiya - - bdf: Fix some data types mismatching with their sources. - - * bdflib.c (_bdf_list_ensure): The type of `num_items' - is matched with _bdf_list_t.used. Also the types of - `oldsize', `newsize', `bigsize' are matched too. - (_bdf_readstream): `cursor' is used as an offset to - the pointer, it should be typed as FT_Offset. Also - the types of `bytes', `start', `end', `avail' are matched. - - * bdfdrivr.c: The type of BDF_CMap->num_encodings is - matched with FT_CMap->clazz->size. - (bdf_cmap_char_index): The types of `min', `max', `mid' - are matched with BDF_CMap->num_encodings. The type of - `result' is matched with encoding->glyph. - (bdf_cmap_char_next): Ditto, the type of `code' is - matched with BDF_encoding_el.enc. - (bdf_interpret_style): The type of `lengths' is changed - to size_t, to take the value by ft_strlen(). Also the - types of `len', `nn', `mm' are matched. - -2009-07-31 suzuki toshiya - - sfnt: Count the size of the memory object by ptrdiff_t. - - * src/sfnt/ttbdf.c (tt_face_find_bdf_prop): The type of - `property_len' is changed from FT_UInt to FT_Offset, - to match with size_t, which is appropriate type for the - object in the memory buffer. - -2009-07-31 suzuki toshiya - - lzw: Count the size of the memory object by ptrdiff_t. - - * src/lzw/ftzopen.h: The types of FT_LzwState->{buf_total, - stack_size} are changed from FT_UInt to FT_Offset, to match - with size_t, which is appropriate type for the object in - the memory buffer. - - * src/lzw/ftzopen.c (ft_lzwstate_stack_grow): The types of - `old_size' and `new_size' are changed from FT_UInt to - FT_Offset, to match with size_t, which is appropriate type - for the object in the memory buffer. - -2009-07-31 suzuki toshiya - - otvalid: Count the table size on memory by ptrdiff_t. - - * src/otvalid/otvgpos.c (otv_ValueRecord_validate): - Change the type of table size from FT_UInt to - FT_PtrDist because it is calculated by the memory - addresses. - -2009-07-31 suzuki toshiya - - otvalid: Prevent an overflow by GPOS/GSUB 32b-bit offset. - - * src/otvalid/otvgpos.c (otv_ExtensionPos_validate): - Extend ExtensionOffset from FT_UInt to FT_ULong, to - cover 32-bit offset on 16-bit platform. - - * src/otvalid/otvgsub.c (otv_ExtensionSubst_validate): - Ditto. - -2009-07-31 suzuki toshiya - - ftobjs.c: Prevent an overflow in glyph index handling. - - * src/base/ftobjs.c (FT_Face_GetCharsOfVariant): - Improve the cast in comparison to avoid the truncation. - -2009-07-31 suzuki toshiya - - Improve the variable types in raccess_make_file_name(). - - * src/base/ftrfork.c (raccess_make_file_name): - Change the type of cursor variable `tmp' to const char*, - to prevent the unexpected modification of original pathname. - (raccess_make_file_name): Change the type of new_length - to size_t. - -2009-07-31 suzuki toshiya - - ftpatent.c: Fix for unused variable `error'. - - * src/base/ftpatent.c (_tt_check_patents_in_range): - Fix warning for unused variable `error'. - -2009-07-31 suzuki toshiya - - type1: Check invalid string longer than PostScript limit. - - * src/type1/t1afm.c (t1_get_index): Check invalid string - which exceeds the limit of PostScript string/name objects. - -2009-07-31 suzuki toshiya - - gzip: Use FT2 zcalloc() & zfree() in ftgzip.c by default. - - * src/gzip/ftgzip.c (zcalloc, zcfree): Disable all - zcalloc() & zfree() by zlib in zutil.c, those in - ftgzip.c by FT2 are enabled by default. To use - zlib zcalloc() & zfree(), define USE_ZLIB_ZCALLOC. - See discussion: - https://lists.gnu.org/archive/html/freetype-devel/2009-02/msg00000.html - -2009-07-31 suzuki toshiya - - gzip: Distinguish PureC from TurboC on MSDOS. - - * src/gzip/zutil.c (zcalloc, zcfree): Enable only for - MSDOS platform. - -2009-07-31 suzuki toshiya - - gxvalid: Insert PureC pragma to allow unevaluated variables. - - * builds/atari/ATARI.H: Insert PureC pragma not to - warn against set-but-unevaluated variable in gxvalid - module. - -2009-07-31 suzuki toshiya - - gxvalid: Pass the union by the pointer instead of the value. - - * src/gxvalid/gxvcommn.h: - - Declare new type `GXV_LookupValueCPtr'. - - Update the type of the 2nd argument to pass GXV_LookupValueDesc - data to the function prototyped as GXV_Lookup_Value_Validate_Func, - from GXV_LookupValueDesc to GXV_LookupValueCPtr. - - Likewise for the function prototyped as - GXV_Lookup_Fmt4_Transit_Func. - - - Declare new type `GXV_StateTable_GlyphOffsetCPtr'. - - Update the type of the 3rd argument to pass - GXV_StateTable_GlyphOffsetDesc data to the function prototyped - as GXV_StateTable_Entry_Validate_Func, from - GXV_StateTable_GlyphOffsetDesc to GXV_StateTable_GlyphOffsetCPtr. - - - Declare new type `GXV_XStateTable_GlyphOffsetCPtr'. - - Update the type of the 3rd argument to pass - GXV_XStateTable_GlyphOffsetDesc data to the function prototyped - as GXV_XStateTable_Entry_Validate_Func, - from GXV_XStateTable_GlyphOffsetDesc - to GXV_XStateTable_GlyphOffsetCPtr. - - * src/gxvalid/gxvcommn.c (gxv_LookupTable_fmt0_validate, - gxv_XClassTable_lookupval_validate, - gxv_XClassTable_lookupfmt4_transit): - Update from GXV_LookupValueDesc to GXV_LookupValueCPtr. - - * src/gxvalid/gxvbsln.c (gxv_bsln_LookupValue_validate, - gxv_bsln_LookupFmt4_transit): Ditto. - - * src/gxvalid/gxvjust.c - (gxv_just_pcTable_LookupValue_entry_validate, - gxv_just_classTable_entry_validate, - gxv_just_wdcTable_LookupValue_validate): Ditto. - - * src/gxvalid/gxvkern.c - (gxv_kern_subtable_fmt1_entry_validate): Ditto. - - * src/gxvalid/gxvlcar.c (gxv_lcar_LookupValue_validate, - gxv_lcar_LookupFmt4_transit): Ditto. - - * src/gxvalid/gxvopbd.c (gxv_opbd_LookupValue_validate, - gxv_opbd_LookupFmt4_transit): Ditto. - - * src/gxvalid/gxvprop.c (gxv_prop_LookupValue_validate, - gxv_prop_LookupFmt4_transit): Ditto. - - * src/gxvalid/gxvmort4.c - (gxv_mort_subtable_type4_lookupval_validate): Ditto. - - * src/gxvalid/gxvmort0.c - (gxv_mort_subtable_type0_entry_validate): Update - from GXV_StateTable_GlyphOffsetDesc - to GXV_StateTable_GlyphOffsetCPtr. - - * src/gxvalid/gxvmort1.c - (gxv_mort_subtable_type1_entry_validate): Ditto. - - * src/gxvalid/gxvmort2.c - (gxv_mort_subtable_type2_entry_validate): Ditto. - - * src/gxvalid/gxvmort5.c - (gxv_mort_subtable_type5_entry_validate): Ditto. - - * src/gxvalid/gxvmorx2.c - (gxv_morx_subtable_type2_entry_validate): Ditto. - - * src/gxvalid/gxvmorx5.c - (gxv_morx_subtable_type5_entry_validate): Ditto. - - * src/gxvalid/gxvmorx1.c - (gxv_morx_subtable_type1_entry_validate): Ditto. - (gxv_morx_subtable_type1_LookupValue_validate, - gxv_morx_subtable_type1_LookupFmt4_transit): - Update from GXV_LookupValueDesc to GXV_LookupValueCPtr. - - * src/gxvalid/gxvmorx0.c - (gxv_morx_subtable_type0_entry_validate): Update - from GXV_XStateTable_GlyphOffsetDesc - to GXV_XStateTable_GlyphOffsetCPtr. - -2009-07-29 Fabrice Bellet - - Fix Redhat bugzilla #513582 and Savannah bug #26849. - - * src/cache/ftccache.h (FTC_CACHE_LOOKUP_CMP) : Fix - aliasing bug. - -2009-07-19 Werner Lemberg - - Document recent library changes. - - * docs/CHANGES: Do it. - -2009-07-17 Werner Lemberg - - Fix Savannah bug #23786. - - * src/truetype/ttobjs.c (tt_size_init_bytecode): Don't reset x_ppem - and y_ppem. Otherwise the `*_CVT_Stretched' functions in ttinterp.c - get never called. - An anonymous guy suggested this change on Savannah, and it seems to - be the right solution. - -2009-07-15 Werner Lemberg - - * docs/release: Updated. - -2009-07-15 Werner Lemberg - - README.CVS -> README.git - - * README.CVS: Renamed to... - * README.git: This. - Updated. - -2009-07-15 suzuki toshiya - - Borland C++ compiler patch proposed by Mirco Babin. - https://lists.gnu.org/archive/html/freetype/2009-07/msg00016.html. - - * builds/exports.mk: Delete unused flags, CCexe_{CFLAGS,LDFLAGS}. - Fix APINAMES_C and APINAMES_EXE pathnames to reflect the platform - specific pathname syntax. - * builds/compiler/bcc.mk: Remove unused flag, CCexe_LDFLAGS. - Define TE = `-e' separately (bcc32 cannot specify the pathname of - binary executable by T = `-o'). - Extend the large page size in linking freetype.lib. - Add extra CLEAN target to delete bcc specific temporary files. - * builds/compiler/bcc-dev.mk: Ditto. - -2009-07-14 Werner Lemberg - - Fix Savannah bug #27026. - - * builds/win32/vc2005/freetype.sln: Use correct version number. - -2009-07-12 suzuki toshiya - - Add a script to check the undefined and unused trace macros. - - * src/tools/chktrcmp.py: A script to check trace_XXXX macros - that are used in C source but undefined in fttrace.h, or - defined in fttrace.h but unused in C sources. See - https://lists.gnu.org/archive/html/freetype-devel/2009-07/msg00013.html. - * docs/DEBUG: Mention on chktrcmp.py. - * docs/release: Ditto. - -2009-07-09 Werner Lemberg - - [ftraster] Make it compile again with -D_STANDALONE_. - - * src/raster/ftraster.c [_STANDALONE_]: Define - FT_CONFIG_STANDARD_LIBRARY_H. - Include `string.h'. - Don't include `rastpic.h'. - Define FT_DEFINE_RASTER_FUNCS. - -2009-07-09 suzuki toshiya - - smooth: Check glyph size by width/height, instead of pitch/height. - Suggested by der Mouse . - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Improve - the check for too large glyph. Replace the pair of `pitch' and - `height' by the pair of `width' and `height'. `pitch' cannot - be greater than `height'. The required is checking the product - `pitch' * `height' <= FT_ULONG_MAX, but we use cheap checks for - the realistic case only. - -2009-07-09 suzuki toshiya - - Register 2 missing trace components, t1afm and ttbdf. - - * include/freetype/internal/fttrace.h: Add FT_TRACE_DEF( t1afm ) - and FT_TRACE_DEF( ttbdf ). See - https://lists.gnu.org/archive/html/freetype-devel/2009-07/msg00013.html - -2009-07-09 suzuki toshiya - - Register a trace component for ftgloadr.c. - - * include/freetype/internal/fttrace.h: Add FT_TRACE_DEF( gloader ). - The macro `trace_gloader' was already used in the initial version - on 2002-02-24. - -2009-07-08 suzuki toshiya - - Prevent the overflows by a glyph with too many points or contours. - The bug is reported by Boris Letocha . See - https://lists.gnu.org/archive/html/freetype-devel/2009-06/msg00031.html - https://lists.gnu.org/archive/html/freetype-devel/2009-07/msg00002.html - - * include/freetype/ftimage.h (FT_OUTLINE_CONTOURS_MAX, - FT_OUTLINE_POINTS_MAX): New macros to declare the maximum - values of FT_Outline.{n_contours,n_points}. - * src/base/ftgloadr.c (FT_GlyphLoader_CheckPoints): Check the - total numbers of points and contours cause no overflows in - FT_Outline.{n_contours,n_points}. - - * include/freetype/internal/ftgloadr.h (FT_GLYPHLOADER_CHECK_P, - FT_GLYPHLOADER_CHECK_C): Compare the numbers of points and - contours as unsigned long number, instead of signed int, to - prevent the overflows on 16-bit systems. - -2009-07-05 Bram Tassyns - - Improve compatibility to Acroread. - This fixes Savannah bug #26944. - - * src/cff/cffload.c (cff_charset_compute_cids): For multiple GID to - single CID mappings, make the lowest value win. - -2009-06-28 suzuki toshiya - - ftpatent: Fix a bug by wrong usage of service->table_info(). - https://lists.gnu.org/archive/html/freetype-devel/2008-12/msg00039.html - - * include/freetype/internal/services/svsfnt.h: Extend - FT_SFNT_TableInfoFunc() to take new argument to obtain the offset - to the specified table. - * src/sfnt/sfdriver.c (sfnt_table_info): Extend to return the - table-offset to the caller function. - * src/base/ftpatent.c (_tt_check_patents_in_table): Use new - service->table_info(). - * src/base/ftobjs.c (FT_Sfnt_Table_Info): Synchronize to new - service->table_info(). - -2009-06-28 Werner Lemberg - - [psaux, cff] Protect against nested `seac' calls. - - * include/freetype/internal/psaux.h (T1_Decoder), src/cff/cffgload.h - (CFF_Decoder): Add `seac' boolean variable. - - * src/cff/cffgload.c (cff_operator_seac), src/psaux/t1decode.c - (t1operator_seac): Use it. - -2009-06-28 Werner Lemberg - - Thinko. - - * src/psaux/t1decode.c (t1operator_seac) - [FT_CONFIG_OPTION_INCREMENTAL]: Test for existence of incremental - interface. - -2009-06-28 Werner Lemberg - - * devel/ftoption.h [FT_CONFIG_OPTION_INCREMENTAL]: Define. - -2009-06-27 suzuki toshiya - - Add tools to preprocess the source files for AtariST PureC. - - * builds/atari/deflinejoiner.awk: New file to filter C source files - for broken C preprocessor of PureC compiler. - - * builds/atari/gen-purec-patch.sh: New file to generate a patch set - for PureC, by using deflinejoiner.awk. - -2009-06-27 suzuki toshiya - - Keep existing modules.cfg in the building tree. - - * configure: If `configure' is executed outside of the source tree, - an existing `modules.cfg' file in the build directory should be - kept, not overwritten by the version in the source tree. - -2009-06-27 suzuki toshiya - - Filter --srcdir= option before invoking builds/unix/configure. - - * configure: If builds/unix/configure is invoked with --srcdir - option, the option should take `builds/unix' directory instead of - the top source directory. Thus the configure script in the top - directory should modify the --srcdir= option if - `builds/unix/configure' is invoked. - -2009-06-27 suzuki toshiya - - Improve configure.raw for cross-building on exe-suffixed systems. - - * builds/unix/configure.raw: Fix a bug in sed script to extract - native suffix for binary executables, patch by Peter Breitenlohner. - https://lists.gnu.org/archive/html/freetype-devel/2009-04/msg00036.html - -2009-06-26 Werner Lemberg - - [truetype] Remove TT_SubGlyphRec. - - * src/truetype/ttobjs.h (TT_SubGlyphRec): Removed, unused. - -2009-06-26 Werner Lemberg - - * */*: For warning messages, replace FT_ERROR with FT_TRACE0. - - FT_ERROR is now used only if a function produces a non-zero `error' - value. - - Formatting, improving and harmonizing debug strings. - -2009-06-25 Werner Lemberg - - Provide version information better. - - * src/base/ftinit.c (FT_Init_FreeType): Don't set version here - but... - * src/base/ftobjs.c (FT_New_Library): Here. - -2009-06-22 Werner Lemberg - - Use 16.16 format while parsing Type 1 charstrings. - This fixes Savannah bug #26867. - - Previously, only integers have been used which can lead to serious - rounding errors. - - However, fractional values are only used internally; after the - charstrings (of either Type 1 or 2) have been processed, the - resulting coordinates get rounded to integers currently -- before - applying scaling. This should be fixed; at the same time a new load - flag should be introduced, to be used in combination with - FT_LOAD_NO_SCALE, which indicates that font units are returned in - 16.16 format. Similarly, the incremental interface should be - extended to allow fractional values for metrics. - - * include/freetype/internal/psaux.h (T1_BuilderRec): Remove `shift' - field. - * include/freetype/internal/pshints.h (T1_Hints_SetStemFunc, - T1_Hints_SetStem3Func): Use FT_Fixed for coordinates. - - * src/psaux/psobjs.c: Include FT_INTERNAL_CALC_H. - (t1_build_add_point): Always convert fixed to integer. - * src/psaux/t1decode.c (t1_decoder_parse_charstrings): - Use 16.16 format everywhere (except for large integers followed by a - `div'). - [CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS]: Remove #ifdef and activate - code unconditionally. - Add support for random numbers and update remaining code - accordingly; this should work now. - (t1operator_seac): Updated. - * src/psaux/pshrec.c: Include FT_INTERNAL_CALC_H. - (ps_hints_t1stem3, t1_hints_stem): Updated. - - * src/cid/cidgload.c: Include FT_INTERNAL_CALC_H. - (cid_load_glyph) [FT_CONFIG_OPTION_INCREMENTAL], - (cid_face_compute_max_advance, cid_slot_load_glyph): Updated. - - * src/type1/t1gload.c (T1_Parse_Glyph_And_Get_Char_String) - [FT_CONFIG_OPTION_INCREMENTAL], (T1_Get_Advances, T1_Load_Glyph): - Updated. - * src/type1/t1load.c: Include FT_INTERNAL_CALC_H. - * src/type1/t1objs.c (T1_Face_Init): Updated. - -2009-06-21 Werner Lemberg - - * src/pshinter/pshrec.c: Use PSH_Err_Ok. - -2009-06-21 Werner Lemberg - - Code beautification. - - * src/type1/t1load.c (FT_INT_TO_FIXED): Removed. - Replace everywhere with INT_TO_FIXED. - (FT_FIXED_TO_INT): Move to ... - * include/freetype/internal/ftcalc.h (FIXED_TO_INT): Here. - Update all users. - -2009-06-20 Werner Lemberg - - Remove unused variables. - - * include/freetype/internal/psaux.h (T1_BuilderRec), - src/cff/cffgload.h (CFF_Builder): Remove `last'. - Update all users. - -2009-06-20 Werner Lemberg - - [psaux] Check large integers while parsing charstrings. - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings): Large - integers must be followed by a `div' operator. - -2009-06-20 Werner Lemberg - - [cff] Revert last change. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings): Do it. - Next time, don't confuse Type 2 charstring opcodes with TOP DICT - values... - -2009-06-20 Werner Lemberg - - * src/autofit/aflatin.c (af_latin_metrics_check_digits): Fix - compiler warning. - -2009-06-20 Werner Lemberg - - * builds/compiler/gcc.mk (CFLAGS): Use -O3, not -O6. - -2009-06-19 Werner Lemberg - - [cff] Fix handling of reserved byte 0xFF. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings): Abort if byte - 0xFF is encountered. - -2009-06-19 Werner Lemberg - - Improve debug messages for Type1 charstrings. - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings): Emit newlines - after instructions. - Prettify output. - -2009-06-19 Werner Lemberg - - More ftgray fixes for FT_STATIC_RASTER. - Problems reported by suyu@cooee.cn. - - * src/smooth/ftgrays.c (gray_move_to, gray_raster_render): Use - RAS_VAR. - -2009-06-18 Werner Lemberg - - * docs/CHANGES: Updated. - -2009-06-18 Werner Lemberg - - Fix B/W rasterization of subglyphs with different drop-out modes. - - Normally, the SCANMODE instruction (if present) to set the drop-out - mode in a TrueType font is located in the `prep' table only and thus - valid for all glyphs. However, there are fonts like `pala.ttf' - which additionally contain this instruction in the hinting code of - some glyphs (but not all). As a result it can happen that a - composite glyph needs multiple drop-out modes for its subglyphs - since the rendering state gets reset for each subglyph. - - FreeType collects the hinted outlines from all subglyphs, then it - sends the data to the rasterizer. It also sends the drop-out mode - -- after hinting has been applied -- and here is the error: It sends - the drop-out mode of the last subglyph only; drop-out modes of all - other subglyphs are lost. - - This patch fixes the problem; it adds a second, alternative - mechanism to pass the drop-out mode: For each contour, the - rasterizer now checks the first `tags' array element. If bit 2 is - set, bits 5-7 contain the contour's drop-out mode, overriding the - global drop-out mode. - - * include/freetype/ftimage.h (FT_CURVE_TAG_HAS_SCANMODE): New macro. - - * src/truetype/ttgload.c (TT_Hint_Glyph): Store drop-out mode in - `tags[0]'. - - * src/raster/ftraster.c (Flow_Up, Overshoot_Top, Overshoot_Bottom): - Use bits 3-5 instead of 0-2. - (New_Profile): Set the drop-out mode in the profile's `flags' field. - (Decompose_Curve): Check `tags[0]' and set `dropOutControl' if - necessary. - (Vertical_Sweep_Drop, Horizontal_Sweep_Drop, - Horizontal_Gray_Sweep_Drop, Draw_Sweep): Use the profile's drop-out - mode. - -2009-06-16 Werner Lemberg - - Improve scan conversion rules 4 and 6. - - Two new constraints are introduced to better identify a `stub' -- a - concept which is only vaguely described in the OpenType - specification. The old code was too rigorous and suppressed more - pixel than it should. - - . The intersection of the two profiles with the scanline is less - than a half pixel. Code related to this was already present in - the sources but has been commented out. - - . The endpoint of the original contour forming a profile has a - distance (`overshoot') less than half a pixel to the scanline. - - Note that the two additional conditions fix almost all differences - to the Windows rasterizer, but some problematic cases remain. - - * src/raster/ftraster.c (Overshoot_Top, Overshoot_Bottom): New - macros for the `flags' field in the `TProfile' structure. - (IS_BOTTOM_OVERSHOOT, IS_TOP_OVERSHOOT): New macros. - (New_Profile, End_Profile): Pass overshoot flag as an argument and - set it accordingly. - Update callers. - (Vertical_Sweep_Drop, Horizontal_Sweep_Drop): Implement the two new - constraints. - -2009-06-11 Werner Lemberg - - Increase precision for B/W rasterizer. - - * src/raster/ftraster.c (Set_High_Precision): Add two more bits to - the precision. This corrects rendering of some small glyphs, for - example, glyph `xi' in verdana.ttf at 13 ppem. Testing with ftbench - on my GNU/Linux box I don't see a performance degradation. - -2009-06-08 Michael Zucchi - - Handle FT_STROKER_LINECAP_BUTT. - This fixes Savannah bug #26757. - - * src/base/ftstroke.c (ft_stroker_cap): Implement it. - -2009-06-07 Harald Fernengel - - Fix some potential out-of-memory crashes. - - * src/base/ftobjs.c (ft_glyphslot_done): Check `slot->internal'. - * src/base/ftstream.c (FT_Stream_ReleaseFrame): Check `stream'. - * src/truetype/ttinterp.c (TT_New_Context): Avoid double-free of - `exec' in case of failure. - -2009-06-07 Werner Lemberg - - Simplify math. - Suggested by Alexei Podtelezhnikov . - - * src/raster/ftraster.c (Vertical_Sweep_Drop, Horizontal_Sweep_Drop, - Horizontal_Gray_Sweep_Drop): Do it. - -2009-06-04 Werner Lemberg - - Preparation for fixing scan conversion rules 4 and 6. - - * src/raster/ftraster.c (TFlow): Replace enumeration with... - (Flow_Up): This macro. - (TProfile): Replace `flow' member with `flags' bit field. - Update all affected code. - -2009-05-29 James Cloos - - Enable autohinting for glyphs rotated by multiples of 90°. - - * src/base/ftobjs.c (FT_Load_Glyph): Alter check for permitted - matrices to allow rotations by multiples of 90°, not only unrotated, - possibly slanted matrices. - -2009-05-28 Werner Lemberg - - Remove compiler warning. - Reported by Krzysztof Kowalczyk . - - * src/autofit/aflatin2.c (af_latin2_hint_edges): Move declaration of - `n_edges' into `#if' block. - -2009-05-28 Werner Lemberg - - Make compilation work with FT_CONFIG_OPTION_USE_ZLIB not defined. - Reported by Krzysztof Kowalczyk . - - * src/pcf/pcfdrivr.c (PCF_Face_Init) [!FT_CONFIG_OPTION_USE_ZLIB]: - Make it work. - Simplify #ifdef logic. - -2009-05-22 Werner Lemberg - - Improve b/w rasterizer. - Problem reported by Krzysztof Kotlenga . - - * src/raster/raster.c (Vertical_Sweep_Drop, Horizontal_Sweep_Drop, - Horizontal_Gray_Sweep_Drop): For smart drop-out mode, if - intersections are equally distant relative to next pixel center, - select the left pixel, not the right one. - -2009-05-19 Werner Lemberg - - Fix Savannah bug #26600. - - * src/type42/t42parse.c (t42_load_keyword): Handle - T1_FIELD_LOCATION_FONT_EXTRA. - -2009-04-30 Werner Lemberg - - Document recent changes to ftview. - - * docs/CHANGES: Do it. - -2009-04-27 Werner Lemberg - - autohinter: Don't change digit widths if all widths are the same. - This fixes FreeDesktop bug #21197. - - * src/autofit/afglobal.c (AF_DIGIT): New macro. - (af_face_globals_compute_script_coverage): Mark ASCII digits in - `glyph_scripts' array. - (af_face_globals_get_metrics): Updated. - (af_face_globals_is_digit): New function. - * src/autofit/afglobal.h: Updated. - (AF_ScriptMetricsRec): Add `digits_have_same_width' flag. - - * src/autofit/aflatin.c: Include FT_ADVANCES_H. - (af_latin_metrics_check_digits): New function. - (af_latin_metrics_init): Use it. - * src/autofit/aflatin.h: Updated. - * src/autofit/afcjk.c (af_cjk_metrics_init): Updated. - - * src/autofit/aflatin2.c: Similar changes as with aflatin.c. - - * src/autofit/afloader.c (af_loader_load_g): Test digit width. - - * docs/CHANGES: Document it. - -2009-04-26 Werner Lemberg - - Make ftgrays compile with _STANDALONE_ and FT_STATIC_RASTER again. - Problems reported by suyu@cooee.cn. - - * src/smooth/ftgrays.c (FT_DEFINE_OUTLINE_FUNCS, - FT_DEFINE_RASTER_FUNCS) [_STANDALONE_]: Define. - [!_STANDALONE_]: Include ftspic.h only here. - (ras): Define/declare after definition of `TWorker'. - Use `RAS_VAR_' where necessary. - -2009-04-21 Karl Berry - - Fix AC_CHECK_FT2. - - * builds/unix/freetype2.m4: Only check PATH for freetype-config if - we did not already find it from a prefix option. - -2009-04-05 Oran Agra - - Add #error to modules and files that do not support PIC yet. - - When FT_CONFIG_OPTION_PIC is defined the following files will - create #error: - * src/bdf/bdfdrivr.h - * src/cache/ftcmanag.c - * src/cid/cidriver.h - * src/gxvalid/gxvmod.h - * src/gzip/ftgzip.c - * src/lzw/ftlzw.c - * src/otvalid/otvmod.h - * src/pcf/pcfdrivr.h - * src/pfr/pfrdrivr.h - * src/psaux/psauxmod.h - * src/type1/t1driver.h - * src/type42/t42drivr.h - * src/winfonts/winfnt.h - -2009-04-05 Oran Agra - - Position Independent Code (PIC) support in autofit module. - - * include/freetype/internal/autohint.h add macros to init - instances of FT_AutoHinter_ServiceRec. - - * src/autofit/afmodule.h declare autofit_module_class - using macros from ftmodapi.h, - when FT_CONFIG_OPTION_PIC is defined create and destroy - functions will be declared. - * src/autofit/afmodule.c when FT_CONFIG_OPTION_PIC is defined - af_autofitter_service and autofit_module_class structs - will have functions to init or create and destroy them - instead of being allocated in the global scope. - And macros will be used from afpic.h in order to access them. - - * src/autofit/aftypes.h add macros to init and declare - instances of AF_ScriptClassRec. - - * src/autofit/afcjk.h declare af_cjk_script_class - using macros from aftypes.h, - when FT_CONFIG_OPTION_PIC is defined init function will be declared. - * src/autofit/afcjk.c when FT_CONFIG_OPTION_PIC is defined - af_cjk_script_class struct will have function to init it instead of - being allocated in the global scope. - - * src/autofit/afdummy.h declare af_dummy_script_class - using macros from aftypes.h, - when FT_CONFIG_OPTION_PIC is defined init function will be declared. - * src/autofit/afdummy.c when FT_CONFIG_OPTION_PIC is defined - af_dummy_script_class struct will have function to init it instead of - being allocated in the global scope. - - * src/autofit/afindic.h declare af_indic_script_class - using macros from aftypes.h, - when FT_CONFIG_OPTION_PIC is defined init function will be declared. - * src/autofit/afindic.c when FT_CONFIG_OPTION_PIC is defined - af_indic_script_class struct will have function to init it instead of - being allocated in the global scope. - - * src/autofit/aflatin.h declare af_latin_script_class - using macros from aftypes.h, - when FT_CONFIG_OPTION_PIC is defined init function will be declared. - * src/autofit/aflatin.c when FT_CONFIG_OPTION_PIC is defined - af_latin_script_class struct will have function to init it instead of - being allocated in the global scope. - Change af_latin_blue_chars to be PIC-compatible by being a two - dimensional array rather than array of pointers. - - - * src/autofit/aflatin2.h declare af_latin2_script_class - using macros from aftypes.h, - when FT_CONFIG_OPTION_PIC is defined init function will be declared. - * src/autofit/aflatin2.c when FT_CONFIG_OPTION_PIC is defined - af_latin2_script_class struct will have function to init it instead of - being allocated in the global scope. - Change af_latin2_blue_chars to be PIC-compatible by being a two - dimensional array rather than array of pointers. - - * src/autofit/afglobal.c when FT_CONFIG_OPTION_PIC is defined - af_script_classes array initialization was moved to afpic.c and - is later referred using macros defined in afpic.h. - - New Files: - * src/autofit/afpic.h declare struct to hold PIC globals for autofit - module and macros to access them. - * src/autofit/afpic.c implement functions to allocate, destroy and - initialize PIC globals for autofit module. - - * src/autofit/autofit.c add new file to build: afpic.c. - * src/autofit/jamfile add new files to FT2_MULTI build: afpic.c. - -2009-04-05 Oran Agra - - Position Independent Code (PIC) support in pshinter module. - - * include/freetype/internal/pshints.h add macros to init - instances of PSHinter_Interface. - - * src/pshinter/pshmod.h declare pshinter_module_class - using macros from ftmodapi.h, - when FT_CONFIG_OPTION_PIC is defined create and destroy - functions will be declared. - * src/pshinter/pshmod.c when FT_CONFIG_OPTION_PIC is defined - pshinter_interface and pshinter_module_class structs - will have functions to init or create and destroy them - instead of being allocated in the global scope. - And macros will be used from pshpic.h in order to access them. - - New Files: - * src/pshinter/pshpic.h declare struct to hold PIC globals for pshinter - module and macros to access them. - * src/pshinter/pshpic.c implement functions to allocate, destroy and - initialize PIC globals for pshinter module. - - * src/pshinter/pshinter.c add new file to build: pshpic.c. - * src/pshinter/jamfile add new files to FT2_MULTI build: pshpic.c. - -2009-04-05 Oran Agra - - Position Independent Code (PIC) support in psnames module. - - * include/freetype/internal/services/svpscmap.h add macros to init - instances of FT_Service_PsCMapsRec. - - * src/psnames/psmodule.h declare psnames_module_class - using macros from ftmodapi.h, - when FT_CONFIG_OPTION_PIC is defined create and destroy - functions will be declared. - * src/psnames/psmodule.c when FT_CONFIG_OPTION_PIC is defined - pscmaps_interface and pscmaps_services structs - and psnames_module_class array - will have functions to init or create and destroy them - instead of being allocated in the global scope. - And macros will be used from pspic.h in order to access them. - - New Files: - * src/psnames/pspic.h declare struct to hold PIC globals for psnames - module and macros to access them. - * src/psnames/pspic.c implement functions to allocate, destroy and - initialize PIC globals for psnames module. - - * src/psnames/psnames.c add new file to build: pspic.c. - * src/psnames/jamfile add new files to FT2_MULTI build: pspic.c. - -2009-04-05 Oran Agra - - Position Independent Code (PIC) support in raster renderer. - - * src/raster/ftrend1.h declare ft_raster1_renderer_class - and ft_raster5_renderer_class - using macros from ftrender.h, - when FT_CONFIG_OPTION_PIC is defined create and destroy - functions will be declared. - * src/smooth/ftrend1.c when FT_CONFIG_OPTION_PIC is defined - ft_raster1_renderer_class and ft_raster5_renderer_class structs - will have functions to init or create and destroy them - instead of being allocated in the global scope. - Macros will be used from rastpic.h in order to access - ft_standard_raster from the pic_container (allocated in ftraster.c). - In ft_raster1_render when PIC is enabled, the last letter of - module_name is used to verify the renderer class rather than the - class pointer. - - * src/raster/ftraster.c when FT_CONFIG_OPTION_PIC is defined - ft_standard_raster struct will have function to init it - instead of being allocated in the global scope. - - New Files: - * src/raster/rastpic.h declare struct to hold PIC globals for raster - renderer and macros to access them. - * src/raster/rastpic.c implement functions to allocate, destroy and - initialize PIC globals for raster renderer. - - * src/raster/raster.c add new file to build: rastpic.c. - * src/raster/jamfile add new files to FT2_MULTI build: rastpic.c. - -2009-04-05 Oran Agra - - Position Independent Code (PIC) support in smooth renderer. - - * src/smooth/ftsmooth.h declare ft_smooth_renderer_class, - ft_smooth_lcd_renderer_class and ft_smooth_lcdv_renderer_class - using macros from ftrender.h, - when FT_CONFIG_OPTION_PIC is defined create and destroy - functions will be declared. - * src/smooth/ftsmooth.c when FT_CONFIG_OPTION_PIC is defined - the following structs: - ft_smooth_renderer_class, ft_smooth_lcd_renderer_class - and ft_smooth_lcdv_renderer_class - will have functions to init or create and destroy them - instead of being allocated in the global scope. - And macros will be used from ftspic.h in order to access - ft_grays_raster from the pic_container (allocated in ftgrays.c). - - * src/smooth/ftgrays.h include FT_CONFIG_CONFIG_H - * src/smooth/ftgrays.c when FT_CONFIG_OPTION_PIC is NOT defined - func_interface was moved from gray_convert_glyph_inner function - to the global scope. - When FT_CONFIG_OPTION_PIC is defined - func_interface and ft_grays_raster structs - will have functions to init them - instead of being allocated in the global scope. - And func_interface will be allocated on the stack of - gray_convert_glyph_inner. - - New Files: - * src/smooth/ftspic.h declare struct to hold PIC globals for smooth - renderer and macros to access them. - * src/smooth/ftspic.c implement functions to allocate, destroy and - initialize PIC globals for smooth renderer. - - * src/smooth/smooth.c add new file to build: ftspic.c. - * src/smooth/jamfile add new files to FT2_MULTI build: ftspic.c. - -2009-04-05 Oran Agra - - Position Independent Code (PIC) support in cff driver. - - * include/freetype/internal/services/svcid.h add macros to init - instances of FT_Service_CIDRec. - * include/freetype/internal/services/svpsinfo.h add macros to init - instances of FT_Service_PsInfoRec. - - * src/cff/cffcmap.h declare cff_cmap_encoding_class_rec - and cff_cmap_unicode_class_rec using macros from - ftobjs.h, when FT_CONFIG_OPTION_PIC is defined create and destroy - functions will be declared. - * src/cff/cffcmap.c when FT_CONFIG_OPTION_PIC is defined - the following structs: - cff_cmap_encoding_class_rec and cff_cmap_unicode_class_rec - will have functions to init or create and destroy them - instead of being allocated in the global scope. - - * src/cff/cffdrivr.h declare cff_driver_class using macros from - ftdriver.h, when FT_CONFIG_OPTION_PIC is defined create and destroy - functions will be declared. - * src/cff/cffdrivr.c when FT_CONFIG_OPTION_PIC is defined - the following structs: - cff_service_glyph_dict, cff_service_ps_info, cff_service_ps_name - cff_service_get_cmap_info, cff_service_cid_info, cff_driver_class, - and cff_services array - will have functions to init or create and destroy them - instead of being allocated in the global scope. - And macros will be used from cffpic.h in order to access them - from the pic_container. - Use macros from cffpic.h in order to access the - structs allocated in cffcmap.c - - * src/cff/cffobjs.c Use macros from cffpic.h in order to access the - structs allocated in cffcmap.c - - * src/cff/parser.c when FT_CONFIG_OPTION_PIC is defined - implement functions to create and destroy cff_field_handlers array - instead of being allocated in the global scope. - And macros will be used from cffpic.h in order to access it - from the pic_container. - - New Files: - * src/cff/cffpic.h declare struct to hold PIC globals for cff - driver and macros to access them. - * src/cff/cffpic.c implement functions to allocate, destroy and - initialize PIC globals for cff driver. - - * src/cff/cff.c add new file to build: cffpic.c. - * src/cff/jamfile add new files to FT2_MULTI build: cffpic.c. - -2009-04-05 Oran Agra - - Position Independent Code (PIC) support in sfnt driver. - - * include/freetype/internal/services/svbdf.h add macros to init - instances of FT_Service_BDFRec. - * include/freetype/internal/services/svgldict.h add macros to init - instances of FT_Service_GlyphDictRec. - * include/freetype/internal/services/svpostnm.h add macros to init - instances of FT_Service_PsFontNameRec. - * include/freetype/internal/services/svsfnt.h add macros to init - instances of FT_Service_SFNT_TableRec. - * include/freetype/internal/services/svttcmap.h add macros to init - instances of FT_Service_TTCMapsRec. - * include/freetype/internal/sfnt.h add macros to init - instances of SFNT_Interface. - - * src/sfnt/sfdriver.h declare sfnt_module_class using macros from - ftmodapi.h, when FT_CONFIG_OPTION_PIC is defined create and destroy - functions will be declared. - * src/sfnt/sfdriver.c when FT_CONFIG_OPTION_PIC is defined - the following structs: - sfnt_service_sfnt_table, sfnt_service_glyph_dict, sfnt_service_ps_name - tt_service_get_cmap_info, sfnt_service_bdf, sfnt_interface, - sfnt_module_class, and sfnt_services array - will have functions to init or create and destroy them - instead of being allocated in the global scope. - And macros will be used from sfntpic.h in order to access them - from the pic_container. - - * src/sfnt/ttcmap.h add macros to init - instances of TT_CMap_ClassRec. - * src/sfnt/ttcmap.c when FT_CONFIG_OPTION_PIC is defined - the following structs: - tt_cmap0_class_rec, tt_cmap2_class_rec, tt_cmap4_class_rec - tt_cmap6_class_rec, tt_cmap8_class_rec, tt_cmap10_class_rec, - tt_cmap12_class_rec, tt_cmap14_class_rec and tt_cmap_classes array - will have functions to init or create and destroy them - instead of being allocated in the global scope. - And macros will be used from sfntpic.h in order to access them - from the pic_container. - The content of tt_cmap_classes is now described in the - new file 'ttcmapc.h'. - - New Files: - * src/sfnt/sfntpic.h declare struct to hold PIC globals for sfnt - driver and macros to access them. - * src/sfnt/sfntpic.c implement functions to allocate, destroy and - initialize PIC globals for sfnt driver. - * src/sfnt/ttcmapc.h describing the content of - tt_cmap_classes allocated in ttcmap.c - - * src/sfnt/sfnt.c add new file to build: sfntpic.c. - * src/sfnt/jamfile add new files to FT2_MULTI build: sfntpic.c. - -2009-04-05 Oran Agra - - Position Independent Code (PIC) support in truetype driver. - - * include/freetype/internal/services/svmm.h add macros to init - instances of FT_Service_MultiMastersRec. - * include/freetype/internal/services/svttglyf.h add macros to init - instances of FT_Service_TTGlyfRec. - - * src/truetype/ttdriver.h declare tt_driver_class using macros from - ftdriver.h, when FT_CONFIG_OPTION_PIC is defined create and destroy - functions will be declared. - * src/truetype/ttdriver.c when FT_CONFIG_OPTION_PIC is defined - the following structs: - tt_service_gx_multi_masters, tt_service_truetype_glyf, tt_driver_class - and tt_services array, - will have functions to init or create and destroy them - instead of being allocated in the global scope. - And macros will be used from ttpic.h in order to access them - from the pic_container. - * src/truetype/ttobjs.c change trick_names array to be - PIC-compatible by being a two dimensional array rather than array - of pointers. - - New Files: - * src/truetype/ttpic.h declare struct to hold PIC globals for truetype - driver and macros to access them. - * src/truetype/ttpic.c implement functions to allocate, destroy and - initialize PIC globals for truetype driver. - - * src/truetype/truetype.c add new file to build: ttpic.c. - * src/truetype/jamfile add new files to FT2_MULTI build: ttpic.c. - -2009-04-05 Oran Agra - - Position Independent Code (PIC) support and infrastructure in base. - - * include/freetype/config/ftoption.h add FT_CONFIG_OPTION_PIC - * include/freetype/internal/ftobjs.h Add pic_container member to - FT_LibraryRec. - Add macros to declare and init instances of FT_CMap_ClassRec. - Add macros to init instances of FT_Outline_Funcs and FT_Raster_Funcs. - Add macros to declare, allocate and initialize modules - (FT_Module_Class). - Add macros to declare, allocate and initialize renderers - (FT_Renderer_Class). - Add macro to init instances of FT_Glyph_Class. - Add macros to declare, allocate and initialize drivers - (FT_Driver_ClassRec). - * include/freetype/internal/ftpic.h new file to declare the - FT_PIC_Container struct and the functions to allocate and destroy it. - * include/freetype/internal/ftserv.h add macros to allocate and - destroy arrays of FT_ServiceDescRec. - * include/freetype/internal/internal.h define macro to include - ftpic.h. - - New Files: - * src/base/ftpic.c implement functions to allocate and destroy the - global pic_container. - * src/base/basepic.h declare struct to hold PIC globals for base and - macros to access them. - * src/base/basepic.c implement functions to allocate, destroy and - initialize PIC globals for base. - - * src/base/ftinit.c when FT_CONFIG_OPTION_PIC is defined implement - functions that allocate and destroy ft_default_modules according to - FT_CONFIG_MODULES_H in the pic_container instead of the global scope - and use macro from basepic.h to access it. - * src/base/ftobjs.c add calls to the functions that allocate and - destroy the global pic_container when the library is created and - destroyed. - - * src/base/jamfile add new files to FT2_MULTI build: - ftpic.c and basepic.c. - * src/base/ftbase.c add new files to build: - ftpic.c and basepic.c. - - * src/base/ftglyph.c when FT_CONFIG_OPTION_PIC is defined - ft_bitmap_glyph_class and ft_outline_glyph_class will be allocated - in the pic_container instead of the global scope and use macros from - basepic.h to access them. - * src/base/ftbbox.c allocate bbox_interface struct on the stack - instead of the global scope when FT_CONFIG_OPTION_PIC is defined. - * src/base/ftstroke.c access ft_outline_glyph_class allocated in - ftglyph.c via macros from basepic.h - -2009-04-05 Oran Agra - - Preparing changes in cff parser later needed for PIC version. - - * src/cff/cffload.c, src/cff/cffload.h, src/cff/cffobjs.c, - src/cff/cffparse.c, src/cff/cffparse.h: Add library pointer to - 'CFF_ParserRec' set by `cff_parser_init'. - Route library pointer from 'cff_face_init' to 'cff_subfont_load' - for `cff_parser_init'. - - * src/cff/cffparse.c (CFF_Field_Handler): Move it to... - * src/cff/cffparse.h: This file, to be used by other C files. - -2009-04-05 Oran Agra - - Minor change in ftstroke.c. - - * src/base/ftstroke.c (FT_StrokerRec): Replace `memory' member with - `library' needed for PIC version. - Update all callers. - -2009-04-04 Werner Lemberg - - ftnames.c -> ftsnames.c - - * src/base/ftnames.c: Rename to... - * src/base/ftsnames.c: This. - * src/base/Jamfile, src/base/rules.mk, src/base/ftbase.c: Updated. - -2009-04-04 Werner Lemberg - - Add support for cmap type 13. - - * devel/ftoption.h, include/freetype/config/ftoption.h - (TT_CONFIG_CMAP_FORMAT_13): New macro. - - * src/sfnt/ttcmap.c (TT_CMap13Rec, tt_cmap13_init, - tt_cmap13_validate, tt_cmap13_char_index, tt_cmap13_char_next, - tt_cmap13_get_info, tt_cmap13_char_map_def_binary, - tt_cmap14_class_rec): New functions and structures for cmap 13 - support. - (tt_cmap_classes): Register tt_cmap13_class_rec. - - * docs/CHANGES: Mention cmap 13 support. - -2009-04-01 Werner Lemberg - - Ignore empty contours in CFF glyphs. - - Problem reported by Albert Astals Cid . - - * src/cff/cffgload.c (cff_builder_close_contour): Synchronize with - t1_builder_close_contour. - -2009-03-21 Werner Lemberg - - Another redundant header inclusion. - - * src/truetype/ttgxvar.c: Fix Ghostscript Coverity issue #4041. - -2009-03-21 Werner Lemberg - - Remove redundant header inclusions. - - This covers many Ghostscript Coverity issues. - - * src/*: Do it. - -2009-03-21 Werner Lemberg - - Fix Ghostscript Coverity issue #3904. - - * src/truetype/ttgxvar.c (ft_var_readpackedpoints): Protect against - invalid values of `runcnt'. - -2009-03-20 Werner Lemberg - - Fix `make multi' run. - - * src/smooth/ftsmooth.h: Include FT_INTERNAL_DEBUG_H. - -2009-03-20 Werner Lemberg - - Fix Savannah bug #25923. - - * src/cache/ftccmap.c (FTC_CMAP_HASH): Fix typo. - -2009-03-20 Werner Lemberg - - Protect against too large glyphs. - - Problem reported by Tavis Ormandy . - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Don't allow - `pitch' or `height' to be larger than 0xFFFF. - -2009-03-20 Werner Lemberg - Tavis Ormandy - - Fix validation for various cmap table formats. - - * src/sfnt/ttcmap.c (tt_cmap8_validate, tt_cmap10_validate, - tt_cmap12_validate): Check `length' correctly. - (tt_cmap_14_validate): Check `length' and `numMappings' correctly. - -2009-03-20 Werner Lemberg - - Protect against malformed compressed data. - - * src/lzw/ftzopen.c (ft_lzwstate_io): Test whether `state->prefix' is - zero. - -2009-03-20 Werner Lemberg - - Protect against invalid SID values in CFFs. - - Problem reported by Tavis Ormandy . - - * src/cff/cffload.c (cff_charset_load): Reject SID values larger - than 64999. - -2009-03-19 Vincent Richomme - - Update WinCE Visual C project files. - - * builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2008-ce/freetype.vcproj: Add missing base extension - files. - -2009-03-19 Werner Lemberg - - Remove unused Win32 code. - - * builds/wince/ftdebug.c: Remove code guarded with `!_WIN32_WCE'. - Since Win32 is handled separately this is no longer needed. - -2009-03-19 Vincent Richomme - - Make `gzip' module compile on WinCE. - - * src/gzip/zconf.h [_WIN32_WCE]: Define NO_ERRNO_H. - -2009-03-19 Werner Lemberg - - Remove unused WinCE code. - - * builds/win32/ftdebug.c: Remove code guarded with `_WIN32_WCE'. - Since WinCE is handled separately this is no longer needed. - -2009-03-16 Werner Lemberg - - docmaker: Don't ignore single-line code blocks. - - * src/tools/docmaker/content.py (DocBlock::_init__): Fix change from - 2009-01-31. - -2009-03-15 Steve Langasek - - Use __asm__ for declaring assembly instead of asm. - - * builds/unix/ftconfig.in (FT_MulFix_arm): Use __asm__ instead of - asm on arm, fixing a build failure on armel with -pedantic. - -2009-03-14 Werner Lemberg - - Fix valgrind warning. - - * src/sfnt/ttsbit0.c (tt_sbit_decoder_load_bit_aligned): Don't read - past the end of the frame. - -2009-03-12 Werner Lemberg - - * Version 2.3.9 released. - ========================= - - - Tag sources with `VER-2-3-9'. - -2009-03-12 Werner Lemberg - - * builds/unix/freetype2.in: Move @FT2_EXTRA_LIBS@ to `Libs.private'. - -2009-03-12 Werner Lemberg - - Fix some FreeType Coverity issues as reported for Ghostscript. - - * src/base/ftobjs.c (FT_New_Face, FT_New_Memory_Face): Initialize - `args.stream' (#3874, #3875). - (open_face_PS_from_sfnt_stream): Improve error management (#3786). - * src/base/ftmm.c (ft_face_get_mm_service): Fix check of `aservice' - (#3870). - * src/base/ftstroke.c (ft_stroke_border_get_counts): Remove dead - code (#3790). - * src/base/ftrfork.c (raccess_guess_apple_generic): Check error - value of `FT_Stream_Skip' (#3784). - - * src/type1/t1gload.c (T1_Load_Glyph): Check `size' before accessing - it (#3872) - - * src/pcf/pcfdrivr.c (PCF_Glyph_Load): Check `face' before accessing - it (#3871). - * src/pcf/pcfread.c (pcf_get_metrics): Handle return value of - `pcf_get_metric' (#3789, #3782). - (pcf_get_properties): Use FT_STREAM_SKIP (#3783). - - * src/cache/ftcmanag.c (FTC_Manager_RegisterCache): Fix check of - `acache' (#3797) - - * src/cff/cffdrivr.c (cff_ps_get_font_info): Fix check of `cff' - (#3796). - * src/cff/cffgload.c (cff_decoder_prepare): Check `size' (#3795). - * src/cff/cffload.c (cff_index_get_pointers): Add comment (#3794). - - * src/bdf/bdflib.c (_bdf_add_property): Check `fp->value.atom' - (#3793). - (_bdf_parse_start): Add comment (#3792). - - * src/raster/ftraster.c (Finalize_Profile_Table): Check - `ras.fProfile' (#3791). - - * src/sfnt/ttsbit.c (Load_SBit_Image): Use FT_STREAM_SKIP (#3785). - - * src/gzip/ftgzip.c (ft_gzip_get_uncompressed_size): Properly ignore - seek error (#3781). - -2009-03-11 Michael Toftdal - - Extend CID service functions to handle CID-keyed CFFs as CID fonts. - - * include/freetype/ftcid.h (FT_Get_CID_Is_Internally_CID_keyed, - FT_Get_CID_From_Glyph_Index): New functions. - - * include/freetype/internal/services/svcid.h - (FT_CID_GetIsInternallyCIDKeyedFunc, - FT_CID_GetCIDFromGlyphIndexFunc): New function typedefs. - (CID Service): Use them. - - * src/base/ftcid.c: Include FT_CID_H. - (FT_Get_CID_Is_Internally_CID_keyed, FT_Get_CID_From_Glyph_Index): - New functions. - - * src/cff/cffdrivr.c (cff_get_is_cid, cff_get_cid_from_glyph_index): - New functions. - (cff_service_cid_info): Add them. - * src/cff/cffload.c (cff_font_load): Don't free `font->charset.sids' - -- it is needed for access as a CID-keyed font. It gets deleted - later on. - - * src/cid/cidriver.c (cid_get_is_cid, cid_get_cid_from_glyph_index): - New functions. - (cid_service_cid_info): Add them. - - * docs/CHANGES: Updated. - -2009-03-11 Bram Tassyns - - Fix Savannah bug #25597. - - * src/cff/cffparse.c (cff_parse_real): Don't allow fraction_length - to become larger than 9. - -2009-03-11 Werner Lemberg - - Fix Savannah bug #25814. - - * builds/unix/freetype2.in: As suggested in the bug report, move - @LIBZ@ to `Libs.private'. - -2009-03-11 Werner Lemberg - - Fix Savannah bug #25781. - We now simply check for a valid `offset', no longer handling `delta - = 1' specially. - - * src/sfnt/ttcmap.c (tt_cmap4_validate): Don't check `delta' for - last segment. - (tt_cmap4_set_range, tt_cmap4_char_map_linear, - tt_cmap4_char_map_binary): Check offset. - -2009-03-11 Werner Lemberg - - * src/base/Jamfile: Fix handling of ftadvanc.c. - Reported by Oran Agra . - -2009-03-10 Vincent Richomme - - Restructure Win32 and Wince compiler support. - - * src/builds/win32: Remove files for WinCE. - Move VC 2005 support to a separate directory. - Add directory for VC 2008 support. - - * src/builds/wince: New directory hierarchy for WinCE compilers - (VC 2005 and VC 2008). - -2009-03-09 Werner Lemberg - - More preparations for 2.3.9 release. - - * docs/CHANGES: Updated. - - * Jamfile, README: s/2.3.8/2.3.9/, s/238/239/. - -2009-03-09 Werner Lemberg - - * src/sfnt/rules.mk (SFNT_DRV_H): Add ttsbit0.c. - -2009-03-09 Alexey Kryukov - - Fix handling of EBDT formats 8 and 9 (part 2). - - This patch fixes the following problems in ttsbit0.c: - - . Bitmaps for compound glyphs were never allocated. - - . `SBitDecoder' refused to load metrics if some other metrics have - already been loaded. This condition certainly makes no sense for - recursive calls, so I've just disabled it. Another possibility - would be resetting `decoder->metrics_loaded' to false before - loading each composite component. However, we must restore the - original metrics after finishing the recursion; otherwise we can - get a misaligned glyph. - - . `tt_sbit_decoder_load_bit_aligned' incorrectly handled `x_pos', - causing some glyph components to be shifted too far to the right - (especially noticeable for small sizes). - - Note that support for grayscale bitmaps (not necessarily compound) is - completely broken in ttsbit0.c. - - * src/sfnt/tt_sbit_decoder_load_metrics: Always load metrics. - (tt_sbit_decoder_load_bit_aligned): Handle `x_pos' correctly in case - of `h == height'. - (tt_sbit_decoder_load_compound): Reset metrics after loading - components. - Allocate bitmap. - -2009-03-09 Werner Lemberg - - * builds/unix/configure.raw (version_info): Set to 9:20:3. - -2009-03-03 David Turner - - Protect SFNT kerning table parser against malformed tables. - - This closes Savannah BUG #25750. - - * src/sfnt/ttkern.c (tt_face_load_kern, tt_face_get_kerning): Fix a - bug where a malformed table would be successfully loaded but later - crash the engine during parsing. - -2009-03-03 David Turner - - Update documentation and bump version number to 2.3.9. - - * include/freetype/freetype.h: Bump patch version to 9. - * docs/CHANGES: Document the ABI break in 2.3.8. - * docs/VERSION.DLL: Update version numbers table for 2.3.9. - -2009-03-03 David Turner - - Remove ABI-breaking field in public PS_InfoFontRec definition. - - Instead, we define a new internal PS_FontExtraRec structure to - hold the additional field, then place it in various internal - positions of the corresponding FT_Face derived objects. - - * include/freetype/t1tables.h (PS_FontInfoRec): Remove the - `fs_type' field from the public structure. - * include/freetype/internal/psaux.h (T1_FieldLocation): New - enumeration `T1_FIELD_LOCATION_FONT_EXTRA'. - * include/freetype/internal/t1types.h (PS_FontExtraRec): New - structure. - (T1_FontRec, CID_FaceRec): Add it. - - * src/cid/cidload.c (cid_load_keyword): Handle - T1_FIELD_LOCATION_FONT_EXTRA. - * src/cid/cidtoken.h, src/type1/t1tokens.h, src/type42/t42parse.c: - Adjust FT_STRUCTURE and T1CODE properly to handle `FSType'. - * src/type1/t1load.c (t1_load_keyword): Handle - T1_FIELD_LOCATION_FONT_EXTRA. - - * include/freetype/internal/services/svpsinfo.h (PsInfo service): - Add `PS_GetFontExtraFunc' function typedef. - - * src/base/ftfstype.c: Include FT_INTERNAL_SERVICE_H and - FT_SERVICE_POSTSCRIPT_INFO_H. - (FT_Get_FSType_Flags): Use POSTSCRIPT_INFO service. - - * src/cff/cffdrivr.c (cff_service_ps_info): Updated. - * src/cid/cidriver.c (cid_ps_get_font_extra): New function. - (cid_service_ps_info): Updated. - * src/type1/t1driver.c (t1_ps_get_font_extra): New function. - (t1_service_ps_info): Updated. - * src/type42/t42drivr.c (t42_ps_get_font_extra): New function. - (t42_service_ps_info): Updated. - -2009-03-02 Alexey Kryukov - - Fix handling of EBDT formats 8 and 9. - - The main cycle in `blit_sbit' makes too many iterations: it actually - needs the count of lines in the source bitmap rather than in the - target image. - - * src/sfnt/ttsbit.c (blit_sbit) [FT_CONFIG_OPTION_OLD_INTERNALS]: - Add parameter `source_height' and use it for main loop. - (Load_SBit_Single) [FT_CONFIG_OPTION_OLD_INTERNALS]: Updated. - -2009-02-23 Werner Lemberg - - Fix Savannah bug #25669. - - * src/base/ftadvanc.h (FT_Get_Advances): Fix serious typo. - - * src/base/ftobjs.c (FT_Select_Metrics, FT_Request_Metrics): Fix - scaling factor for non-scalable fonts. - - * src/cff/cffdrivr.c (cff_get_advances): Use correct advance width - value to prevent incorrect scaling. - - * docs/CHANGES: Document it. - -2009-02-15 Matt Godbolt - - Fix Savannah bug #25588. - - * builds/unix/ftconfig.in (FT_MulFix_arm): Use correct syntax for - `orr' instruction. - -2009-02-11 Werner Lemberg - - * src/truetype/ttobjs.c (tt_check_trickyness): Add `DFKaiShu'. - Reported by David Bevan . - -2009-02-09 Werner Lemberg - - Fix Savannah bug #25495. - - * src/sfnt/sfobjs.c (sfnt_load_face): Test for bitmap strikes before - setting metrics and bbox values. This ensures that the check for a - font with neither a `glyf' table nor bitmap strikes can be performed - early enough to set metrics and bbox values too. - -2009-02-04 Werner Lemberg - - Fix Savannah bug #25480. - - * builds/unix/freetype-config.in: For --ftversion, don't use $prefix - but $includedir. - -2009-01-31 Werner Lemberg - - Minor docmaker improvements. - - * src/tools/docmaker/content.py (DocBlock::__init__): Ignore empty - code blocks. - -2009-01-25 Werner Lemberg - - Fix SCANCTRL handling in TTFs. - Problem reported by Alexey Kryukov . - - * src/truetype/ttinterp.c (Ins_SCANCTRL): Fix threshold handling. - -2009-01-23 Werner Lemberg - - Move FT_Get_FSType_Flags to a separate file. - Problem reported by Mickey Gabel . - - * src/base/ftobjs.c (FT_Get_FSType_Flags): Move to... - * src/base/ftfstype.c: This new file. - - * modules.cfg (BASE_EXTENSION): Add ftfstype.c. - - * docs/INSTALL.ANY: Updated. - - * builds/mac/*.txt, builds/amiga/*makefile*, - builds/win32/{visualc,visualce}/freetype.*, builds/symbian/*: - Updated. - -2009-01-22 suzuki toshiya - - * builds/unix/ftsystem.c (FT_Stream_Open): Fix 2 error - messages ending without "\n". - -2009-01-22 suzuki toshiya - - Fix Savannah bug #25347. - - * src/base/ftobjs.c (open_face_PS_from_sfnt_stream): Rewind - the stream to the original position passed to this function, - when ft_lookup_PS_in_sfnt_stream() failed. - (Mac_Read_sfnt_Resource): Rewind the stream to the head of - sfnt resource body, when open_face_PS_from_sfnt_stream() - failed. - -2009-01-19 Michael Lotz - - Fix Savannah bug #25355. - - * include/freetype/config/ftconfig.h (FT_MulFix_i386): Make - assembler code work with gcc 2.95.3 (as used by the Haiku project). - Add `cc' register to the clobber list. - -2009-01-18 Werner Lemberg - - Protect FT_Get_Next_Char. - - * src/sfnt/ttcmap.c (tt_cmap4_set_range): Apply fix similar to - change from 2008-07-22. - - Patch from Ronen Ghoshal . - -2009-01-18 Werner Lemberg - - Implement FT_Get_Name_Index for SFNT driver. - - * src/sfnt/sfdriver.c (sfnt_get_name_index): New function. - (sfnt_service_glyph_dict): Use it. - - Problem reported by Truc Truong . - -2009-01-18 Werner Lemberg - - * include/freetype/ftstroke.h (FT_Outline_GetInsideBorder): Fix - documentation. Problem reported by Truc Truong . - - * docs/CHANGES: Updated. - -2009-01-14 Werner Lemberg - - * Version 2.3.8 released. - ========================= - - - Tag sources with `VER-2-3-8'. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.3.8. - - * README, Jamfile (RefDoc), builds/win32/visualc/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualce/index.html, - builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj: s/2.3.7/2.3.8/, s/237/238/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 8. - - * builds/unix/configure.raw (version_info): Set to 9:19:3. - - * docs/release: Updated. - -2009-01-14 Werner Lemberg - - * builds/toplevel.mk (dist): Compress better. - -2009-01-13 Werner Lemberg - - * src/base/ftobjs.c (FT_Get_FSType_Flags): Cast for compilation - with C++. - -2009-01-13 Werner Lemberg - - Don't use stdlib.h and friends directly. - Reported by Mickey Gabel . - - * src/base/ftdbgmem.c: s//FT_CONFIG_STANDARD_LIBRARY_H/. - - * src/gzip/ftgzip.c, src/lzw/ftlzw.c, src/raster/ftmisc.h: - s//FT_CONFIG_STANDARD_LIBRARY_H/. - - * src/autofit/aftypes.h, src/autofit/afhints.c, - src/pshinter/pshalgo.c: s//FT_CONFIG_STANDARD_LIBRARY_H/ - - * src/lzw/ftlzw.c, src/base/ftdbgmem.c: Don't include stdio.h. - -2009-01-12 Werner Lemberg - - Avoid compiler warnings. - - * */*: s/do ; while ( 0 )/do { } while ( 0 )/. - Reported by Sean McBride . - -2009-01-12 Werner Lemberg - - Fix stdlib dependencies. - - Problem reported by Mickey Gabel . - - * include/freetype/config/ftstdlib.h (ft_exit): Removed. Unused. - - * src/autofit/afhints.c, src/base/ftlcdfil.c, src/smooth/ftsmooth.c: - s/memcpy/ft_memcpy/. - * src/psaux/t1decode.c: s/memset/ft_memset/, s/memcpy/ft_memcpy/. - -2009-01-11 Werner Lemberg - - * docs/formats.txt: Add link to PCF specification. - - * include/freetype/ftbdf.h (FT_Get_BDF_Property): Improve - documentation. - -2009-01-09 suzuki toshiya - - * src/base/ftadvanc.c (_ft_face_scale_advances, FT_Get_Advance, - FT_Get_Advances): Change the type of load_flags from FT_UInt32 to - FT_Int32, to match with the flags for FT_Load_Glyph(). - * src/cff/cffdrivr.c (cff_get_advances): Ditto. - * src/truetype/ttdriver.c (tt_get_advances): Ditto. - * include/freetype/ftadvanc.h (FT_Get_Advance, FT_Get_Advances): - Ditto. - * include/freetype/internal/ftdriver.h (FT_Face_GetAdvancesFunc): - Ditto. - -2009-01-09 Daniel Zimmermann - - * src/gxvalid/gxvmort.c (gxv_mort_feature_validate): Fix wrong - length check. From Savannah patch #6682. - -2009-01-09 Werner Lemberg - - Fix problem with T1_FIELD_{NUM,FIXED}_TABLE2. - - * src/psaux/psobjs.c (ps_parser_load_field_table): Don't handle - `count_offset' if it is zero (i.e., unused). Otherwise, the first - element of the structure which holds the data is erroneously - modified. Problem reported by Chi Nguyen . - -2009-01-09 suzuki toshiya - - * src/base/ftadvanc.c (_ft_face_scale_advances, FT_Get_Advance, - FT_Get_Advances): Extend the type of load_flags from FT_UInt to - FT_UInt32, to pass 32-bit flags on 16bit platforms. - * src/cff/cffdrivr.c (cff_get_advances): Ditto. - * src/truetype/ttdriver.c (tt_get_advances): Ditto. - * include/freetype/ftadvanc.h (FT_Get_Advance, FT_Get_Advances): - Ditto. - * include/freetype/internal/ftdriver.h (FT_Face_GetAdvancesFunc): - Ditto. - -2009-01-09 suzuki toshiya - - * src/base/ftobjs.c (FT_Done_Library): Issue an error message when - FT_Done_Face() cannot free all faces. If the list of the opened - faces includes broken face which FT_Done_Face() cannot free, - FT_Done_Library() retries FT_Done_Face() and it can fall into - an endless loop. See the discussion: - https://lists.gnu.org/archive/html/freetype-devel/2008-09/msg00047.html - https://lists.gnu.org/archive/html/freetype-devel/2008-10/msg00000.html - -2009-01-07 Werner Lemberg - - * docs/CHANGES: Document new key `a' in ftdiff. - -2009-01-06 Werner Lemberg - - * autogen.sh: Don't use GNUisms while calling sed. Problem reported - by Sean McBride. - -2009-01-06 Werner Lemberg - - * src/base/ftbitmap.c (FT_Bitmap_Convert): Handle FT_PIXEL_MODE_LCD - and FT_PIXEL_MODE_LCD_V. Problem reported by Chi Nguyen - . - -2009-01-06 Diego Pettenò - - * builds/unix/configure.raw: Don't call AC_CANONICAL_BUILD and - AC_CANONICAL_TARGET and use $host_os only. A nice explanation for - this change can be found at - https://blog.flameeyes.eu/s/canonical-target. - - From Savannah patch #6712. - -2009-01-06 Sean McBride - - * src/base/ftdbgmem.c (_debug_mem_dummy): Make it static. - - * src/base/ftmac.c: Remove some #undefs. - -2008-12-26 Werner Lemberg - - Set `face_index' field in FT_Face for all font formats. - - * cff/cffobjs.c (cff_face_init), winfonts/winfnt.c (FNT_Face_Init), - sfnt/sfobjs.c (sfnt_init_face): Do it. - - * docs/CHANGES: Document it. - -2008-12-22 Steve Grubb - - * builds/unix/ftsystem.c (FT_Stream_Open): Reject zero-length files. - Patch from Savannah bug #25151. - -2008-12-21 Werner Lemberg - - * src/pfr/pfrdrivr.c, src/winfonts/winfnt.c, src/cache/ftcmanag.c, - src/smooth/ftgrays.c, src/base/ftobjs.c, src/sfobjs.c: - s/_Err_Bad_Argument/_Err_Invalid_Argument/. The former is for - errors in the bytecode interpreter only. - -2008-12-21 Werner Lemberg - - * src/base/ftpfr.c (FT_Get_PFR_Metrics): Protect against NULL - arguments. - Fix return value for non-PFR fonts. Both problems reported by Chi - Nguyen . - -2008-12-21 anonymous - - FT_USE_MODULE declares things as: - - extern const FT_Module_Class - - (or similar for C++). However, the actual types of the variables - being declared are often different, e.g., FT_Driver_ClassRec or - FT_Renderer_Class. (Some are, indeed, FT_Module_Class.) - - This works with most C compilers (since those structs begin with an - FT_Module_Class struct), but technically it's undefined behavior. - - To quote the ISO/IEC 9899:TC2 final committee draft, section 6.2.7 - paragraph 2: - - All declarations that refer to the same object or function shall - have compatible type; otherwise, the behavior is undefined. - - (And they are not compatible types.) - - Most C compilers don't reject (or even detect!) code which has this - issue, but the GCC LTO development branch compiler does. (It - outputs the types of the objects while generating .o files, along - with a bunch of other information, then compares them when doing the - final link-time code generation pass.) - - Patch from Savannah bug #25133. - - * src/base/ftinit.c (FT_USE_MODULE): Include variable type. - - * builds/amiga/include/freetype/config/ftmodule.h, - include/freetype/config/ftmodule.h, */module.mk: Updated to declare - pass correct types to FT_USE_MODULE. - -2008-12-21 Hongbo Ni - - * src/autofit/aflatin.c (af_latin_hint_edges), - src/autofit/aflatin2.c (af_latin2_hint_edges), src/autofit/afcjk.c - (af_cjk_hint_edges): Protect against division by zero. This fixes - Savannah bug #25124. - -2008-12-18 Werner Lemberg - - * docs/CHANGES: Updated. - -2008-12-18 David Bevan - - Provide API for accessing embedding and subsetting restriction - information. - - * include/freetype.h (FT_FSTYPE_INSTALLABLE_EMBEDDING, - FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING, - FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING, FT_FSTYPE_EDITABLE_EMBEDDING, - FT_FSTYPE_NO_SUBSETTING, FT_FSTYPE_BITMAP_EMBEDDING_ONLY): New - macros. - (FT_Get_FSType_Flags): New function declaration. - - * src/base/ftobjs.c (FT_Get_FSType_Flags): New function. - - * src/cid/cidtoken.h, src/type1/t1tokens.h, src/type42/t42parse.c - (t42_keywords): Handle `FSType'. - - * include/freetype/t1tables.h (PS_FontInfoRec): Add `fs_type' field. - -2008-12-17 Werner Lemberg - - * src/base/ftsynth.c (FT_GlyphSlot_Embolden): Don't use internal - macros so that copying the source code into an application works - out of the box. - -2008-12-17 Werner Lemberg - - * include/freetype/ftsynth.h, src/base/ftsynth.c: Move - FT_GlyphSlot_Own_Bitmap to... - * include/freetype/ftbitmap.h, src/base/ftbitmap.c: These files. - - * docs/CHANGES: Document it. - -2008-12-10 Werner Lemberg - - Generalize the concept of `tricky' fonts by introducing - FT_FACE_FLAG_TRICKY to indicate that the font format's hinting - engine is necessary for correct rendering. - - At the same time, slightly modify the behaviour of tricky fonts: - FT_LOAD_NO_HINTING is now ignored. To really force raw loading - of tricky fonts (without hinting), both FT_LOAD_NO_HINTING and - FT_LOAD_NO_AUTOHINT must be used. - - Finally, tricky TrueType fonts always use the bytecode interpreter - even if the patented code is used. - - * include/freetype/freetype.h (FT_FACE_FLAG_TRICKY, FT_IS_TRICKY): - New macros. - - * src/truetype/ttdriver.c (Load_Glyph): Handle new load flags - semantics as described above. - - * src/truetype/ttobjs.c (tt_check_trickyness): New function, using - code of ... - (tt_face_init): This function, now simplified and updated to new - semantics. - - * src/base/ftobjs.c (FT_Load_Glyph): Don't use autohinter for tricky - fonts. - - * docs/CHANGES: Document it. - -2008-12-09 Werner Lemberg - - Really fix Savannah bug #25010: An SFNT font with neither outlines - nor bitmaps can be considered as containing space `glyphs' only. - - * src/truetype/ttpload.c (tt_face_load_loca): Handle the case where - a `glyf' table is missing. - - * src/truetype/ttgload.c (load_truetype_glyph): Abort if we have no - `glyf' table but a non-zero `loca' entry. - (tt_loader_init): Handle missing `glyf' table. - - * src/base/ftobjs.c (FT_Load_Glyph): Undo change 2008-12-05. - - * src/sfnt/sfobjs.c (sfnt_load_face): A font with neither outlines - nor bitmaps is scalable. - -2008-12-05 Werner Lemberg - - * src/autofit/aflatin.c (af_latin_uniranges): Add more ranges. This - fixes Savannah bug #21190 which also provides a basic patch. - -2008-12-05 Werner Lemberg - - * include/freetype/freetype.h (FT_LOAD_ADVANCE_ONLY): Use value - 0x100 instead of 0x10000; the latter value is already occupied by - FT_LOAD_TARGET_LIGHT. Bug reported by James Cloos. - - - Handle SFNT with neither outlines nor bitmaps. This fixes Savannah - bug #25010. - - * src/base/ftobjs.c (FT_Load_Glyph): Reject fonts with neither - outlines nor bitmaps. - - * src/sfnt/sfobjs.c (sfnt_load_face): Don't return an error if there - is no table with glyphs. - - - * src/sfnt/ttload.c (tt_face_lookup_table): Improve debugging - message. - -2008-12-01 Werner Lemberg - - GDEF tables need `glyph_count' too for validation. Problem reported - by Chi Nguyen . - - * src/otvalid/otvgdef.c (otv_GDEF_validate), src/otvalid/otvalid.h - (otv_GDEF_validate), src/otvalid/otvmod.c (otv_validate): Pass - `glyph_count'. - -2008-11-29 Werner Lemberg - - * src/autofit/afcjk.c, src/base/ftoutln.c, src/base/ftrfork.c, - src/bdf/bdfdrivr.c, src/gxvalid/gxvmorx.c, src/otvalid/otvmath.c, - src/pcf/pcfdrivr.c, src/psnames/pstables.h, src/smooth/ftgrays.c, - src/tools/glnames.py, src/truetype/ttinterp.c, src/type1/t1load.c, - src/type42/t42objs.c, src/winfonts/winfnt.c: Fix compiler warnings - (Atari PureC). - -2008-11-29 James Cloos - - * src/type/t1load.c (mm_axis_unmap): Revert previous patch and fix - it correctly by using FT_INT_TO_FIXED (FreeType expects 16.16 values - in the /BlendDesignMap space). - -2008-11-29 James Cloos - - * src/type1/t1load.c (mm_axis_unmap): `blend_points' is FT_Fixed*, - whereas `design_points' is FT_Long*. Therefore, return blend rather - than design points. - -2008-11-27 Werner Lemberg - - * src/cff/cffparse.c (cff_parse_real): Handle more than nine - significant digits correctly. This fixes Savannah bug #24953. - -2008-11-25 Daniel Zimmermann - - * src/base/ftstream.c (FT_Stream_ReadFields): Don't access stream - before the NULL check. From Savannah patch #6681. - -2008-11-24 Werner Lemberg - - Fixes from the gnuwin32 port. - - * src/base/ftlcdfil.c: s/EXPORT/EXPORT_DEF/. - - * src/base/ftotval.c: Include FT_OPENTYPE_VALIDATE_H. - - * src/psaux/psobjs.c (ps_table_add): Check `length'. - -2008-11-15 Werner Lemberg - - * src/truetype/ttinterp.c (tt_default_graphics_state): The default - value for `scan_type' is zero, as confirmed by Greg Hitchcock from - Microsoft. Problem reported by Michal Nowakowski - . - -2008-11-12 Tor Andersson - - * src/cff/cffdrivr.c (cff_get_cmap_info): Initialize `format' field. - This fixes Savannah bug #24819. - -2008-11-08 Werner Lemberg - - * src/sfnt/sfobjs.c (sfnt_load_face): Remove #if 0/#endif guards - since OpenType version 1.5 has been released. - - * include/ttnameid.h (TT_NAME_ID_WWS_FAMILY, - TT_NAME_ID_WWS_SUBFAMILY): New macros for OpenType 1.5. - (TT_URC_COPTIC, TT_URC_VAI, TT_URC_NKO, TT_URC_BALINESE, - TT_URC_PHAGSPA, TT_URC_NON_PLANE_0, TT_URC_PHOENICIAN, - TT_URC_TAI_LE, TT_URC_NEW_TAI_LUE, TT_URC_BUGINESE, - TT_URC_GLAGOLITIC, TT_URC_YIJING, TT_URC_SYLOTI_NAGRI, - TT_URC_LINEAR_B, TT_URC_ANCIENT_GREEK_NUMBERS, TT_URC_UGARITIC, - TT_URC_OLD_PERSIAN, TT_URC_SHAVIAN, TT_URC_OSMANYA, - TT_URC_CYPRIOT_SYLLABARY, TT_URC_KHAROSHTHI, TT_URC_TAI_XUAN_JING, - TT_URC_CUNEIFORM, TT_URC_COUNTING_ROD_NUMERALS, TT_URC_SUNDANESE, - TT_URC_LEPCHA, TT_URC_OL_CHIKI, TT_URC_SAURASHTRA, TT_URC_KAYAH_LI, - TT_URC_REJANG, TT_URC_CHAM, TT_URC_ANCIENT_SYMBOLS, - TT_URC_PHAISTOS_DISC, TT_URC_OLD_ANATOLIAN, TT_URC_GAME_TILES): New - macros for OpenType 1.5. - -2008-11-08 Wenlin Institute - - * src/base/ftobjs.c (ft_glyphslot_free_bitmap): Protect against - slot->internal == NULL. Reported by Graham Asher. - -2008-11-08 Werner Lemberg - - * src/sfnt/sfobjs.c (tt_face_get_name): Modified to return an error - code so that memory allocation problems can be distinguished from - missing table entries. Reported by Graham Asher. - (GET_NAME): New macro. - (sfnt_load_face): Use it. - -2008-11-05 Werner Lemberg - - * devel/ftoption.h, include/freetype/config/ftoption.h - [TT_CONFIG_OPTION_BYTECODE_INTERPRETER]: Undefine - TT_CONFIG_OPTION_UNPATENTED_HINTING. This fixes the return value of - `FT_Get_TrueType_Engine_Type' (and makes it work as documented). - Reported in bug #441638 of bugzilla.novell.com. - - * docs/CHANGES: Document it. - -2008-11-03 Werner Lemberg - - * src/type1/t1load.c (parse_subrs): Use an endless loop. There are - fonts (like HELVI.PFB version 003.001, used on OS/2) which define - some `subrs' elements more than once. Problem reported by Peter - Weilbacher . - -2008-10-15 Graham Asher - - * src/sfnt/ttpost.c (tt_post_default_names): Add `const'. - -2008-10-15 David Turner - - * src/truetype/ttgxvar.c (TT_Set_MM_Blend): Disambiguate for - meddlesome compilers' warning against `for ( ...; ...; ...) ;'. - -2008-10-14 Werner Lemberg - - * src/cff/cffobjs.c (cff_face_init): Remove compiler warning. - Suggested by Bram Tassyns in Savannah patch #6651. - -2008-10-12 Graham Asher - - * src/sfnt/sfobjs.c (sfnt_load_face): Fix computation of - `underline_position'. - -2008-10-12 Werner Lemberg - - * docs/CHANGES: Updated. - -2008-10-09 suzuki toshiya - - Fix Savannah bug #24468. - - According to include/freetype/internal/ftobjs.h, the appropriate - type to interchange single character codepoint is FT_UInt32. It - should be distinguished from FT_UInt which can be 16bit integer. - - * src/sfnt/ttcmap.c (tt_cmap4_char_map_linear): Change the type - of the second argument `pcharcode' from FT_UInt* to FT_UInt32*. - (tt_cmap4_char_map_binary): Ditto. - (tt_cmap14_get_nondef_chars): Change the type of return value - from FT_UInt* to FT_UInt32*. - -2008-10-08 John Tytgat - - Fix Savannah bug #24485. - - * src/type1/t1load.c (parse_charstrings): Assure that we always have - a .notdef glyph. - -2008-10-05 suzuki toshiya - - * src/base/ftmac.c: Include FT_TRUETYPE_TAGS_H for multi build. - * builds/mac/ftmac.c: Ditto. - -2008-10-05 suzuki toshiya - - * include/freetype/tttags.h (TTAG_TYP1, TTAG_typ1): Fix definitions. - * src/base/ftobjs.c: Include FT_TRUETYPE_TAGS_H. - -2008-10-05 suzuki toshiya - - * src/sfnt/sfobjs.c (sfnt_open_font): Allow `typ1' version tag in - the beginning of sfnt container. - * src/sfnt/ttload.c (check_table_dir): Return - `SFNT_Err_Table_Missing' when sfnt table directory structure is - correct but essential tables for TrueType fonts (`head', `bhed' or - `SING') are missing. Other errors are returned by - SFNT_Err_Unknown_File_Format. - - * src/base/ftobjs.c (FT_Open_Face): When TrueType driver returns - `FT_Err_Table_Missing', try `open_face_PS_from_sfnt_stream'. It is - enabled only when old mac font support is configured. - -2008-10-04 suzuki toshiya - - * include/freetype/tttags.h (TTAG_CID, TTAG_FOND, TTAG_LWFN, - TTAG_POST, TTAG_sfnt, TTAG_TYP1, TTAG_typ1): New tags to simplify - the repeated calculations of these values in ftobjs.c and ftmac.c. - * src/base/ftobjs.c: Replace all FT_MAKE_TAG by new tags. - * src/base/ftmac.c: Ditto. - * builds/mac/ftmac.c: Ditto. - -2008-10-04 suzuki toshiya - - * src/base/ftobjs.c (ft_lookup_PS_in_sfnt_stream): Remove wrong - initialization of *is_sfnt_cid. - -2008-10-04 Werner Lemberg - - * src/base/ftobjs.c (open_face_PS_from_sfnt_stream): Remove compiler - warnings. - -2008-10-04 suzuki toshiya - - * src/base/ftobjs.c (ft_lookup_PS_in_sfnt): Replaced by... - (ft_lookup_PS_in_sfnt_stream): This. - (open_face_PS_from_sfnt_stream): New function. It checks whether - the stream is sfnt-wrapped Type1 PS font or sfnt-wrapped CID-keyed - font, then try to open a face for given face_index. - (Mac_Read_sfnt_Resource): Replace the combination of - `ft_lookup_PS_in_sfnt' and `open_face_from_buffer' by - `open_face_PS_from_sfnt_stream'. - * src/base/ftmac.c (FT_New_Face_From_SFNT): Ditto. - * builds/mac/ftmac.c (FT_New_Face_From_SFNT): Ditto. - * src/base/ftbase.h: Remove `ft_lookup_PS_in_sfnt' and add - `open_face_PS_from_sfnt_stream'. - -2008-10-03 suzuki toshiya - - * src/base/ftobjs.c (ft_lookup_PS_in_sfnt): Set *is_sfnt_cid to - FALSE if neither `CID ' nor `TYP1' is found in the sfnt container. - -2008-10-03 suzuki toshiya - - * include/freetype/config/ftconfig.h: Define FT_MACINTOSH when SC or - MrC compiler of MPW is used. These compilers do not define the - macro __APPLE__ by themselves. - * builds/unix/ftconfig.in: Ditto. - * builds/vms/ftconfig.h: Ditto. - * src/base/ftbase.c: Use FT_MACINTOSH instead of __APPLE__, to - include ftmac.c if FreeType 2 is built by MPW. - * src/base/ftobjs.c: Use FT_MACINTOSH instead of __APPLE__, to - enable shared functions for ftmac.c if FreeType 2 is built by MPW. - - * builds/mac/ftmac.c: Include ftbase.h. - (memory_stream_close): Removed. - (new_memory_stream): Ditto. - (open_face_from_buffer): Removed. Use the implementation in - ftobjs.c. - (ft_lookup_PS_in_sfnt): Ditto. - - * builds/mac/FreeType.m68k_far.make.txt: Build ftmac.c as an - included part of ftbase.c, to share the functions in ftobjs.c. The - rule compiling ftmac.c separately is removed and the rule copying - ftbase.c from src/base/ftbase.c to builds/mac/ftbase.c is added. - * builds/mac/FreeType.m68k_cfm.make.txt: Ditto. - * builds/mac/FreeType.ppc_classic.make.txt: Ditto. - * builds/mac/FreeType.ppc_carbon.make.txt: Ditto. - -2008-10-02 Bram Tassyns - - * src/cff/cffgload.c (cff_slot_load): Map CID 0 to GID 0. This - fixes Savannah bug #24430. - -2008-10-02 Werner Lemberg - - * builds/freetype.mk (BASE_H): Rename to... - (INTERNAL_H): This. - (FREETYPE_H): Updated. - * src/base/rules.mk: (BASE_OBJ_S, OBJ_DIR/%.$O): Add BASE_H. - * src/bdf/rules.mk (BDF_DRV_H): Add bdferror.h. - * src/cache/rules.mk (CACHE_DRV_H): Add ftccache.h and ftcsbits.h. - * src/pcf/rules.mk (PCF_DRV_H): Add pcfread.h. - * src/raster/rules.mk (RASTER_DRV_H): Add ftmisc.h. - * src/type42/rules.mk (T42_DRV_H): Add t42types.h. - -2008-10-02 suzuki toshiya - - * src/base/ftbase.h: New file to declare the private utility - functions shared by the sources of base modules. Currently, - `ft_lookup_PS_in_sfnt' and `open_face_from_buffer' are declared to - share between ftobjs.c and ftmac.c. - - * src/base/rule.mk: Add ftbase.h. - - * src/base/ftobjs.c: Include ftbase.h. - (memory_stream_close): Build on any platform when old MacOS font - support is enabled. - (new_memory_stream): Ditto. - (open_face_from_buffer): Build on any platform when old MacOS font - support is enabled. The counting of the face in a font file is - slightly different between Carbon-dependent parser and Carbon-free - parser. They are merged with the platform-specific conditional. - (ft_lookup_PS_in_sfnt): Ditto. - - * src/base/ftmac.c: Include ftbase.h. - (memory_stream_close): Removed. - (new_memory_stream): Ditto. - (open_face_from_buffer): Removed. Use the implementation in - ftobjs.c. - (ft_lookup_PS_in_sfnt): Ditto. - -2008-10-02 Werner Lemberg - - * src/sfnt/sfobjs.c (sfnt_load_face): `psnames_error' is only needed - if TT_CONFIG_OPTION_POSTSCRIPT_NAMES is defined. - -2008-10-01 Werner Lemberg - - * src/truetype/ttobjs.c (tt_face_done), src/cff/cffobjs.c - (cff_face_done), src/pfr/pfrobjs.c (pfr_face_done), - src/pcf/pcfdrivr.c (PCF_Face_Done), src/cid/cidobjs.c - (cid_face_done), src/bdf/bdfdrivr. (BDF_Face_Done), - src/sfnt/sfobjs.c (sfnt_face_done): Protect against face == 0. - Reported by Graham Asher. - -2008-09-30 suzuki toshiya - - * src/base/rules.mk: Add conditional source to BASE_SRC, for `make - multi' on Mac OS X. If the macro $(ftmac_c) is defined, - $(BASE_DIR)/$(ftmac_c) is added to BASE_SRC. In a normal build, the - lack of ftmac.c in BASE_SRC is not serious because ftbase.c includes - ftmac.c. - * builds/unix/unix-def.in: Add a macro definition of $(ftmac_c). - * builds/unix/configure.raw: Add procedure to set up appropriate - value of $(ftmac_c) with the consideration of the availability of - Carbon framework. - -2008-09-30 suzuki toshiya - - * src/base/Jamfile: Add target for multi build by jam on Mac OS X. - * src/base/ftobjs.c (FT_New_Face): Fix the condition to include this - function for MPW building. It is synchronized the condition to - include ftmac.c source into ftbase.c. - -2008-09-22 Werner Lemberg - - * src/cff/cffgload.c (CFF_Operator, cff_argument_counts, - cff_decoder_parse_charstrings): Handle (invalid) - `callothersubr' and `pop' instructions. - -2008-09-22 John Tytgat - - Fix Savannah bug #24307. - - * include/freetype/internal/t1types.h (CID_FaceRec), - src/type42/t42types.h (T42_FaceRec): Comment out `afm_data'. - -2008-09-21 Werner Lemberg - - * src/smooth/ftgrays.c (gray_raster_render): Don't dereference - `target_map' if FT_RASTER_FLAG_DIRECT is set. Problem reported by - Stephan T. Lavavej . - -2008-09-21 suzuki toshiya - - * src/otvalid/Jamfile: Add missing target `otvmath' for multi build - by jam. - * src/sfnt/Jamfile: Add missing target `ttmtx' for multi build by - jam. - -2008-09-20 Werner Lemberg - - * src/smooth/ftgrays.c (gray_find_cell): Fix threshold. The values - passed to this function are already `normalized'. Problem reported - by Stephan T. Lavavej . - - * docs/CHANGES: Document it. - -2008-09-20 Werner Lemberg - - * src/base/ftoutln.c: Include FT_INTERNAL_DEBUG_H. - (FT_Outline_Decompose): Decorate with tracing messages. - - * src/smooth/ftgrays.c [DEBUG_GRAYS]: Replace with - FT_DEBUG_LEVEL_TRACE. - [_STANDALONE_ && FT_DEBUG_LEVEL_TRACE]: Include stdio.h and - stdarg.h. - - (FT_TRACE) [_STANDALONE_]: Remove. - (FT_Message) [_STANDALONE_ && FT_DEBUG_LEVEL_TRACE]: New function. - (FT_TRACE5, FT_TRACE7) [_STANDALONE_]: New macros. - (FT_ERROR) [_STANDALONE_]: Updated. - - (gray_hline) [FT_DEBUG_LEVEL_TRACE]: Fix condition. - Use FT_TRACE7. - (gray_dump_cells): Make it `static void'. - (gray_convert_glyph): Use FT_TRACE7. - - (FT_Outline_Decompose) [_STANDALONE_]: Synchronize with version in - ftoutln.c. - - * src/base/ftadvanc.c (FT_Get_Advance, FT_Get_Advances): Use - FT_ERROR_BASE. - - * docs/formats.txt: Updated. - -2008-09-19 suzuki toshiya - - * src/base/ftmac.c: Import sfnt-wrapped Type1 and sfnt-wrapped - CID-keyed font support. - * builds/mac/ftmac.c: Ditto. - -2008-09-19 suzuki toshiya - - * src/base/ftobjs.c (Mac_Read_sfnt_Resource): Fix double free bug in - sfnt-wrapped Type1 and sfnt-wrapped CID-keyed font support code. - `open_face_from_buffer' frees the passed buffer if it cannot open a - face from the buffer, so the caller must not free it. - -2008-09-19 suzuki toshiya - - * src/base/ftobjs.c (Mac_Read_sfnt_Resource): Add initial support - for sfnt-wrapped Type1 and sfnt-wrapped CID-keyed font. - (ft_lookup_PS_in_sfnt): New function to look up `TYP1' or `CID ' - table in sfnt table directory. It is used before loading TrueType - font driver. - - * docs/CHANGES: Add note about the current status of sfnt-wrapped - Type1 and sfnt-wrapped CID-keyed font support. - -2008-09-18 Werner Lemberg - - * src/base/ftsystem.c (FT_Done_Memory): Use ft_sfree directly for - orthogonality (ft_free and ft_sfree could belong to different memory - pools). This fixes Savannah bug #24297. - -2008-09-18 suzuki toshiya - - * src/cff/cffobjs.c (cff_face_init): Use TTAG_OTTO defined - in tttags.h instead of numerical value 0x4F54544FL. - -2008-09-16 Werner Lemberg - - * src/cff/cffgload.h, src/cff/cffgload.c - (cff_decoder_set_width_only): Eliminate function call. - -2008-09-15 George Williams - - Fix Savannah bug #24179, reported by Bram Tassyns. - - * src/type1/t1load.c (mm_axis_unmap, T1_Get_MM_Var): Fix computation - of default values. - -2008-09-15 Werner Lemberg - - * src/tools/glnames.py (main): Surround `ft_get_adobe_glyph_index' - and `ft_adobe_glyph_list' with FT_CONFIG_OPTION_ADOBE_GLYPH_LIST to - prevent unconditional definition. This fixes Savannah bug #24241. - - * src/psnames/pstables.h: Regenerated. - -2008-09-13 Werner Lemberg - - * autogen.sh, builds/unix/configure.raw, - include/freetype/config/ftconfig.h, builds/unix/ftconfig.in: Minor - beautifying. - - * include/freetype/ftadvanc.h, include/freetype/ftgasp.h, - include/freetype/ftlcdfil.h: Protect against FreeType 1. - Some other minor fixes. - - * devel/ftoption.h: Synchronize with - include/freetype/config/ftoption.h. - -2008-09-11 Werner Lemberg - - * src/base/ftbase.c: Include ftadvanc.c. - -2008-09-11 suzuki toshiya - - * builds/unix/ftconfig.in: Duplicate the cpp computation of - FT_SIZEOF_{INT|LONG} from include/freetype/config/ftconfig.h. - (FT_USE_AUTOCONF_SIZEOF_TYPES): New macro. If defined, the cpp - computation is disabled and the statically configured sizes are - used. This fixes Savannah bug #21250. - - * builds/unix/configure.raw: Add the checks to compare the cpp - computation results of the bit length of int and long versus the - sizes detected by running `configure'. If the results are - different, FT_USE_AUTOCONF_SIZEOF_TYPES is defined to prioritize the - results. - New option --{enable|disable}-biarch-config is added to define or - undefine FT_USE_AUTOCONF_SIZEOF_TYPES manually. - -2008-09-05 suzuki toshiya - - * builds/unix/configure.raw: Clear FT2_EXTRA_LIBS when Carbon or - ApplicationServices framework is missing. Although this value is not - used in building of FreeType2, it is written in `freetype2.pc' and - `freetype-config'. - -2008-09-01 David Turner - - * src/cache/ftccmap.c (FTC_CMapCache_Lookup): Accept a negative cmap - index to mean `use default cached FT_Face's charmap'. This fixes - Savannah bug #22625. - * include/freetype/ftcache.h: Document it. - - - Make FT_MulFix an inlined function. This is done to speed up - FreeType a little (on x86 3% when loading+hinting, 10% when - rendering, ARM savings are more important though). Disable this by - undefining FT_CONFIG_OPTION_INLINE_MULFIX. - - Use of assembler code can now be controlled with - FT_CONFIG_OPTION_NO_ASSEMBLER. - - * include/freetype/config/ftconfig.h, builds/unix/ftconfig.in - [!FT_CONFIG_OPTION_NO_ASSEMBLER] (FT_MulFix_arm): New assembler - implementation. - [!FT_CONFIG_OPTION_NO_ASSEMBLER] (FT_MulFix_i386): Assembler - implementation taken from `ftcalc.c'. - [!FT_CONFIG_OPTION_NO_ASSEMBLER] (FT_MULFIX_ASSEMBLER): New macro - which is defined to the platform-specific assembler implementation - of FT_MulFix. - [FT_CONFIG_OPTION_INLINE_MULFIX && FT_MULFIX_ASSEMBLER] - (FT_MULFIX_INLINED): New macro. - - * include/freetype/config/ftoption.h (FT_CONFIG_OPTION_NO_ASSEMBLER, - FT_CONFIG_OPTION_INLINE_MULFIX): New macros. - - * include/freetype/freetype.h: Updated to handle FT_MULFIX_INLINED. - - * src/base/ftcalc.c: Updated to use FT_MULFIX_ASSEMBLER and - FT_MULFIX_INLINED. - - - Add a new header named FT_ADVANCES_H declaring some new APIs to - extract the advances of one or more glyphs without necessarily - loading their outlines. Also provide `fast loaders' for the - TrueType, Type1, and CFF font drivers (more to come later). - - * src/base/ftadvanc.c, include/freetype/ftadvanc.h: New files. - - * include/freetype/config/ftheader.h (FT_ADVANCES_H): New macro. - * include/freetype/freetype.h (FT_LOAD_ADVANCE_ONLY): New macro. - - * include/freetype/internal/ftdriver.h (FT_Face_GetAdvancesFunc): - `flags' and `advances' are now of type `FT_UInt' and `FT_Fixed', - respectively. - - * src/base/Jamfile (_sources), src/base/rules.mk (BASE_SRC): Add - ftadvanc.c. - - * src/cff/cffdrivr.c (cff_get_advances): New function. - (cff_driver_class): Register it. - - * src/cff/cffgload.c (cff_decoder_set_width_only): New function. - (cff_decoder_parse_charstrings): Handle `width_only'. - (cff_slot_load): Handle FT_LOAD_ADVANCE_ONLY. - - * src/cff/cffgload.h (cff_decoder): New element `width_only'. - (cff_decoder_set_width_only): New declaration. - - * src/truetype/ttdriver.c (tt_get_advances): New function. - (tt_driver_class): Register it. - - * src/truetype/ttgload.c (Get_HMetrics, Get_VMetrics): Renamed to... - (TT_Get_HMetrics, TT_Get_VMetrics): This. - Update callers. - * src/truetype/ttgload.h: Declare them. - - * src/type1/t1gload.h, src/type1/t1gload.c (T1_Get_Advances): New - function. - * src/type1/t1driver.c (t1_driver_class): Register T1_Get_Advances. - - - Add checks for minimum version of the `autotools' stuff. - - * autogen.sh: Implement it. - (get_major_version, get_minor_version, get_patch_version, - compare_to_minimum_version, check_tool_version): New auxiliary - functions. - - * README.CVS: Document it. - -2008-08-29 suzuki toshiya - - * src/sfnt/sfobjs.c (sfnt_open_font): Use TTAG_OTTO defined in - tttags.h instead of FT_MAKE_TAG( 'O', 'T', 'T', 'O' ). - -2008-08-28 Werner Lemberg - - * src/type1/t1load.c (parse_encoding): Protect against infinite - loop. This fixes Savannah bug #24150 (where a patch has been posted - too). - -2008-08-23 Werner Lemberg - - * src/type/t1afm.c (compare_kern_pairs), src/psaux/afmparse.c - (afm_compare_kern_pairs): Fix comparison. This fixes Savannah bug - #24119. - -2008-08-19 suzuki toshiya - - * src/base/ftobjs.c (FT_Stream_New): Initialize *astream always, - even if passed library or arguments are invalid. This fixes a bug - that an uninitialized stream is freed when an invalid library handle - is passed. Originally proposed by Mike Fabian, 2008/08/18 on - freetype-devel. - (FT_Open_Face): Ditto (stream). - (load_face_in_embedded_rfork): Ditto (stream2). - -2008-08-18 suzuki toshiya - - * src/base/ftmac.c: Add a fallback to guess the availability of the - `ResourceIndex' type. It is used when built without configure - (e.g., a build with Jam). - * builds/mac/ftmac.c: Ditto. - * builds/unix/configure.raw: Set HAVE_TYPE_RESOURCE_INDEX to 1 or 0 - explicitly, even if `ResourceIndex' is unavailable. - -2008-08-18 suzuki toshiya - - * builds/unix/configure.raw: In checking of Mac OS X features, - all-in-one header file `Carbon.h' is replaced by the minimum - header file `CoreServices.h', similar to current src/base/ftmac.c. - -2008-08-18 suzuki toshiya - - * src/sfnt/ttcmap.c (tt_cmap2_validate): Skip the validation of - sub-header when its code_count is 0. Many Japanese Dynalab fonts - include such an empty sub-header (code_count == 0, first_code == 0 - delta == 0, but offset != 0) as the second sub-header in SJIS cmap. - -2008-08-04 Werner Lemberg - - * src/type1/t1tokens.h: Handle `ForceBold' keyword. This fixes - Savannah bug #23995. - - * src/cid/cidload.c (parse_expansion_factor): New callback function. - (cid_field_records): Use it for `ExpansionFactor'. - * src/cod/cidtoken.h: Handle `ForceBold' keyword. - Don't handle `ExpansionFactor'. - -2008-08-04 Bram Tassyns - - * src/cff/cffparse.c (cff_parse_fixed_scaled): Fix thinko which - resulted in incorrect scaling. This fixes Savannah bug #23973. - -2008-08-04 Werner Lemberg - - Be more tolerant w.r.t. invalid entries in SFNT table directory. - - * src/sfnt/ttload.c (check_table_dir): Ignore invalid entries and - adjust table count. - Add more trace messages. - (tt_face_load_font_dir): Updated. - -2008-07-30 Werner Lemberg - - * src/cff/cffgload.c (cff_decoder_parse_charstrings): No longer - assume that the first argument on the stack is the bottom-most - element. Two reasons: - - o According to people from Adobe it is missing in the Type 2 - specification that pushing of additional, superfluous arguments - on the stack is prohibited. - - o Acroread in general handles fonts differently, namely by popping - the number of arguments needed for a particular operand (as a PS - interpreter would do). In case of buggy fonts this causes a - different interpretation which of the elements on the stack are - superfluous and which not. - - Since there are CFF subfonts (embedded in PDFs) which rely on - Acroread's behaviour, FreeType now does the same. - -2008-07-27 Werner Lemberg - - Add extra mappings for `Tcommaaccent' and `tcommaaccent'. This - fixes Savannah bug #23940. - - * src/psnames/psmodule.c (WGL_EXTRA_LIST_SIZE): Rename to... - (EXTRA_GLYPH_LIST_SIZE): This. - Increase by 2. - (ft_wgl_extra_unicodes): Rename to... - (ft_extra_glyph_unicodes): This. - Add two code values. - (ft_wgl_extra_glyph_names): Rename to... - (ft_extra_glyph_names): This. - Add two glyphs. - (ft_wgl_extra_glyph_name_offsets): Rename to... - (ft_extra_glyph_name_offsets): This. - Add two offsets. - - (ps_check_wgl_name, ps_check_wgl_unicode): Rename to... - (ps_check_extra_glyph_name, ps_check_extra_glyph_unicode): This. - Updated. - (ps_unicodes_init): Updated. - -2008-07-26 Werner Lemberg - - * src/cff/cffgload.c (cff_decoder_prepare, - cff_decoder_parse_charstrings): Improve debug output. - -2008-07-22 Martin McBride - - * src/sfnt/ttcmap.c (tt_cmap4_validate, tt_cmap4_char_map_linear, - tt_cmap4_char_map_binary): Handle fonts which treat the last segment - specially. According to the specification, such fonts would be - invalid but acroread accepts them. - -2008-07-16 Jon Foster - - * src/pfr/pfrdrivr.c (pfr_get_advance): Fix off-by-one error. - - * src/base/ftcalc.c (FT_MulFix): Fix portability issue. - - * src/sfnt/ttpost.c (MAC_NAME) [!FT_CONFIG_OPTION_POSTSCRIPT_NAMES]: - Fix compiler warning. - -2008-07-16 Werner Lemberg - - Handle CID-keyed fonts wrapped in an SFNT (with cmaps) correctly. - - * src/cff/cffload.c (cff_font_load): Pass `pure_cff'. - Invert sids table only if `pure_cff' is set. - * src/cff/cffload.h: Updated. - - * src/cff/cffobjs.c (cff_face_init): Updated. - Set FT_FACE_FLAG_CID_KEYED only if pure_cff is set. - - * docs/CHANGES: Updated. - -2008-07-09 Werner Lemberg - - * src/truetype/ttpload.c (tt_face_load_loca): Handle buggy fonts - where num_locations < num_glyphs. Problem reported by Ding Li. - -2008-07-05 Werner Lemberg - - Since FreeType uses `$(value ...)', we now need GNU make 3.80 or - newer. This fixes Savannah bug #23648. - - * configure: zsh doesn't like ${1+"$@"}. - Update needed GNU make version. - * builds/toplevel.mk: Check for `$(eval ...)'. - * docs/INSTALL.GNU, docs/INSTALL.CROSS, docs/INSTALL.UNIX: Document - it. - -2008-07-04 Werner Lemberg - - * src/raster/ftraster.c (Draw_Sweep): If span is smaller than one - pixel, only check for dropouts if neither start nor end point lies - on a pixel center. This fixes Savannah bug #23762. - -2008-06-29 Werner Lemberg - - * Version 2.3.7 released. - ========================= - - - Tag sources with `VER-2-3-7'. - - * docs/CHANGES, docs/VERSION.DLL: Update documentation and bump - version number to 2.3.7. - - * README, Jamfile (RefDoc), builds/win32/visualc/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualce/index.html, - builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj: s/2.3.6/2.3.7/, s/236/237/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 7. - - * builds/unix/configure.raw (version_info): Set to 9:18:3. - - * docs/release: Updated. - -2008-06-28 Werner Lemberg - - * src/ftglyph.c (FT_Matrix_Multiply, FT_Matrix_Invert): Move to... - * src/ftcalc.c: Here. This fixes Savannah bug #23729. - -2008-06-27 Werner Lemberg - - * src/raster/ftraster.c (Vertical_Sweep_Drop, Horizontal_Sweep_Drop, - Horizontal_Gray_Sweep_Drop): Test for intersections which - degenerate to a single point can be ignored; this has been confirmed - by Greg Hitchcock from Microsoft. (This was commented out code.) - -2008-06-26 Werner Lemberg - - Improve navigation in API reference. - - * src/tools/docmaker/tohtml.py (html_header_3): Renamed to... - (html_header_6): This. - (html_header_3, html_header_3i, html_header_4, html_header_5, - html_header_5t): New strings. - (toc_footer_start, toc_footer_end): New strings. - (HtmlFormatter::html_header): Updated. - (HtmlFormatter::html_index_header, HtmlFormatter::html_toc_header): - New strings. - (HtmlFormatter::index_enter): Use `html_index_header'. - (HtmlFormatter::index_exit): Print `html_footer'. - (HtmlFormatter::toc_enter): Use `html_toc_header'. - (HtmlFormatter::toc_exit): Print proper footer. - - Convert ~ to non-breakable space. - - * src/tools/docmaker/tohtml.py (make_html_para): Implement it. - Update header files accordingly. - -2008-06-24 suzuki toshiya - - * builds/unix/configure.raw: Check type `ResourceIndex' explicitly - and define HAVE_TYPE_RESOURCE_INDEX if it is defined. Mac OS X 10.5 - bundles 10.4u SDK with MAC_OS_X_VERSION_10_5 macro but without - ResourceIndex type definition. The macro does not inform the type - availability. - * src/base/ftmac.c: More parentheses are inserted to clarify the - conditionals to disable legacy APIs in `10.5 and later' cases. If - HAVE_TYPE_RESOURCE_INDEX is not defined, ResourceIndex is defined. - -2008-06-24 Werner Lemberg - - * src/truetype/ttinterp.c (Ins_SCANTYPE): Don't check rendering - mode. - - * src/raster/ftraster.c (Render_Glyph, Render_Gray_Glyph, - Draw_Sweep): No-dropout mode is value 2, not value 0. - (Draw_Sweep): Really skip dropout handling for no-dropout mode. - -2008-06-24 Werner Lemberg - - * src/psaux/psobjs.c (t1_builder_close_contour): Don't add contour - if it consists of one point only. Based on a patch from Savannah - bug #23683 (from John Tytgat). - -2008-06-22 Werner Lemberg - - * src/truetype/ttgload.c (TT_Load_Glyph): Protect bytecode stuff - with IS_HINTED. - - * docs/CHANGES: Updated. - -2008-06-22 suzuki toshiya - - * builds/unix/configure.raw: If CFLAGS has `-isysroot XXX' option - but LDFLAGS does not, import it to LDFLAGS. The option is used to - specify non-default SDK on Mac OS X (e.g., universal binary SDK for - Mac OS X 10.4 on PowerPC platform). Although Apple TechNote 2137 - recommends to add the option only to CFLAGS, LDFLAGS should include - it because libfreetype.la is built with -no-undefined. This fixes a - bug reported by Ryan Schmidt in MacPorts, - https://trac.macports.org/ticket/15331. - -2008-06-21 Werner Lemberg - - Enable access to the various dropout rules of the B&W rasterizer. - Pass dropout rules from the TT bytecode interpreter to the - rasterizer. - - * include/freetype/ftimage.h (FT_OUTLINE_SMART_DROPOUTS, - FT_OUTLINE_EXCLUDE_STUBS): New flags for FT_Outline. - - * src/raster/ftraster.c (Vertical_Sweep_Drop, Horizontal_Sweep_Drop, - Horizontal_Gray_Sweep_Drop): Use same mode numbers as given in the - OpenType specification. - Fix mode 4 computation. - (Render_Glyph, Render_Gray_Glyph): Handle new outline flags. - - * src/truetype/ttgload.c (TT_Load_Glyph) Convert scan conversion - mode to FT_OUTLINE_XXX flags. - - * src/truetype/ttinterp.c (Ins_SCANCTRL): Enable ppem check. - -2008-06-19 Werner Lemberg - - * src/cff/cffobjs.c (cff_face_init): Compute final - `dict->units_per_em' value before assigning it to - `cffface->units_per_EM'. Otherwise, CFFs without subfonts are - scaled incorrectly if the font matrix is non-standard. This fixes - Savannah bug #23630. - - * docs/CHANGES: Updated. - -2008-06-19 Werner Lemberg - - * src/type/t1objs.c (T1_Face_Init): Slightly improve algorithm fix - from 2008-06-19. - -2008-06-18 Werner Lemberg - - * src/type/t1objs.c (T1_Face_Init): Fix change from 2008-03-21. - Reported by Peter Weilbacher . - - * docs/CHANGES: Updated. - -2008-06-15 George Williams - - * src/otvalid/otvgpos.c (otv_MarkBasePos_validate): Set - `valid->extra2' to 1. This is undocumented in the OpenType 1.5 - specification. - -2008-06-15 Werner Lemberg - - * src/base/ftcalc.c (FT_MulFix) : Protect registers correctly - from clobbering. Patch from Savannah bug report #23556. - - * docs/CHANGES: Document it. - -2008-06-10 Werner Lemberg - - * autogen.sh: Add option `--install' to libtoolize. - -2008-06-10 Werner Lemberg - - * Version 2.3.6 released. - ========================= - - - Tag sources with `VER-2-3-6'. - - * docs/CHANGES, docs/VERSION.DLL: Update documentation and bump - version number to 2.3.6. - - * README, Jamfile (RefDoc), builds/win32/visualc/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualce/index.html, - builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj: s/2.3.5/2.3.6/, s/235/236/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 6. - - * builds/unix/configure.raw (version_info): Set to 9:17:3. - - - * include/freetype/internal/psaux.h (T1_BuilderRec): Remove `scale_x' - and `scale_y'. - * src/cff/cffgload.h (CFF_Builder): Remove `scale_x' and `scale_y'. - - - * src/cff/cffparse.c: Include FT_INTERNAL_DEBUG_H. - * src/cff/cffobjs.h: Include FT_INTERNAL_POSTSCRIPT_HINTS_H. - -2008-06-10 Werner Lemberg - - * src/base/ftobjs.c (open_face): Check `clazz->init_face' and - `clazz->done_face'. - -2008-06-09 VaDiM - - Support debugging on WinCE. From Savannah patch #6536; this fixes - bug #23497. - - * builds/win32/ftdebug.c (OutputDebugStringEx): New function/macro - as a replacement for OutputDebugStringA (which WinCE doesn't have). - Update all callers. - (ft_debug_init) [_WIN32_CE]: WinCE apparently doesn't have - environment variables. - -2008-06-09 Werner Lemberg - - * README.CVS: Updated. - - * builds/unix/configure.raw, builds/unix/freetype-config.in: Updated - for newer versions of autoconf and friends. - -2008-06-08 Werner Lemberg - - * src/type1/t1parse.h (T1_ParserRec): Make `base_len' and - `private_len' unsigned. - - * src/type1/t1parse.c (read_pfb_tag): Make `asize' unsigned and read - it as such. - (T1_New_Parser, T1_Get_Private_Dict): Make `size' unsigned. - - - * src/base/ftstream.c (FT_Stream_Skip): Reject negative values. - - - * src/type1/t1load.c (parse_blend_design_positions): Check `n_axis' - for sane value. - Fix typo. - - - * src/psaux/psobjs.c (ps_table_add): Check `idx' correctly. - - - * src/truetype/ttinterp (Ins_SHC): Use BOUNDS() to check - `last_point'. - - - * src/sfnt/ttload.c (tt_face_load_max_profile): Limit - `maxTwilightPoints'. - -2008-06-06 Werner Lemberg - - * src/truetype/ttinterp.c (Ins_IP): Handle case `org_dist == 0' - correctly. This fixes glyphs `t' and `h' of Arial Narrow at 12ppem. - -2008-06-03 Werner Lemberg - - * include/freetype/ftcache.h (FTC_FaceID): Change type back to - FT_Pointer. Reported by Ian Britten . - -2008-06-02 Werner Lemberg - - Emit header info for defined FreeType objects in reference. - - * src/tools/docmaker/content.py (re_header_macro): New regexp. - (ContentProcessor::__init__): Initialize new dictionary `headers'. - (DocBlock::__init__): Collect macro header definitions. - - * src/tools/docmaker/tohtml.py (header_location_header, - header_location_footer): New strings. - (HtmlFormatter::__init__): Pass `headers' dictionary. - (HtmlFormatter::print_html_field): Don't emit paragraph tags. - (HtmlFormatter::print_html_field_list): Emit empty paragraph. - (HtmlFormatter::block_enter): Emit header info. - -2008-06-01 Werner Lemberg - - * include/freetype/config/ftheader.h (FT_UNPATENTED_HINTING_H, - FT_INCREMENTAL_H): Added. - -2008-05-28 Werner Lemberg - - * src/tools/docmaker/sources.py (SourceBlock::__init__): While - looking for markup tags, return immediately as soon a single one is - found. - -2008-05-28 Werner Lemberg - - * src/truetype/ttinterp.c (Ins_MD): The MD instruction also uses - original, unscaled input values. Confirmed by Greg Hitchcock from - Microsoft. - -2008-05-27 Werner Lemberg - - * src/tools/docmaker/tohtml.py (block_footer_start, - block_footer_middle): Beautify output. - -2008-05-25 Werner Lemberg - - * src/raster/ftraster.c (fc_black_render): Return 0 when we are - trying to render into a zero-width/height bitmap, not an error code. - - * src/truetype/ttgload.c (load_truetype_glyph): Move initialization - of the graphics state for subglyphs to... - (TT_Hint_Glyph): This function. - Hinting instructions for a composite glyph apparently refer to the - just hinted subglyphs, not the unhinted, unscaled outline. This - seems to fix Savannah bugs #20973 and (at least partially) #23310. - -2008-05-20 suzuki toshiya - - * src/base/ftmac.c (FT_New_Face_From_Suitcase): Check if valid - `aface' is returned by FT_New_Face_From_FOND(). The patch was - proposed by an anonymous reporter of Savannah bug #23204. - -2008-05-18 Werner Lemberg - - * src/pshinter/pshalgo.c (ps_hints_apply): Reset scale values after - correction for pixel boundary. Without this patch, the effect can - be cumulative under certain circumstances, making glyphs taller and - taller after each call. This fixes Savannah bug #19976. - -2008-05-18 Werner Lemberg - - * src/base/ftdebug.c (FT_Message, FT_Panic): Send output to stderr. - This fixes Savannah bug #23280. - - * docs/CHANGES: Updated. - -2008-05-18 David Turner - - * src/psnames/psmodule.c (ft_wgl_extra_unicodes, - ft_wgl_extra_glyph_names, ft_wgl_extra_glyph_name_offsets, - ps_check_wgl_name, ps_check_wgl_unicode): Use `static' to make - declarations non-global. - - * src/type1/t1load.c: Add missing comment. - -2008-05-17 Sam Hocevar - - * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Handle zero-contour - glyphs correctly. Patch from Savannah bug #23277. - -2008-05-16 Werner Lemberg - - * docs/CHANGES: Updated. - -2008-05-16 Sergey Tolstov - - Improve support for WGL4 encoded fonts. - - * src/psnames/psmodule.c (WGL_EXTRA_LIST_SIZE): New macro. - (ft_wgl_extra_unicodes, ft_wgl_extra_glyph_names, - ft_wgl_extra_glyph_name_offsets): New arrays. - (ps_check_wgl_name, ps_check_wgl_unicode): New functions. - (ps_unicodes_init): Use them to add additional Unicode mappings. - -2008-05-15 Werner Lemberg - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings) - : `closepath' without a path is a no-op, not an error - (cf. the PS reference manual). - - Reported by Martin McBride. - -2008-05-15 Werner Lemberg - - * builds/toplevel.mk (CONFIG_GUESS, CONFIG_SUB): Updated. - -2008-05-15 Werner Lemberg - - * src/type1/t1load.c (parse_subrs): Accept fonts with a subrs array - which contains a single but empty entry. This is technically - invalid (since it must end with `return'), but... - - Reported by Martin McBride. - -2008-05-14 Werner Lemberg - - Finish fix of scaling bug of CID-keyed CFF subfonts. - - * include/freetype/internal/ftcalc.h, src/base/ftcalc.c - (FT_Matrix_Multiply_Scaled, FT_Vector_Transform_Scaled): New - functions. - - * src/cff/cffobjs.h (CFF_Internal): New struct. It is used to - provide global hinting data for both the top-font and all subfonts - (with proper scaling). - - * src/cff/cffobjs.c (cff_make_private_dict): New function, using - code from `cff_size_init'. - (cff_size_init, cff_size_done, cff_size_select, cff_size_request): - Use CFF_Internal and handle subfonts. - (cff_face_init): Handle top-dict and subfont matrices correctly; - apply some heuristic in case of unlikely matrix concatenation - results. This has been discussed with people from Adobe (thanks - goes mainly to David Lemon) who confirm that the CFF specs are fuzzy - and not correct. - - * src/cff/cffgload.h (cff_decoder_prepare): Add `size' argument. - - * src/cff/cffgload.c (cff_builder_init): Updated. - (cff_decoder_prepare): Handle hints globals for subfonts. - Update all callers. - (cff_slot_load): Handling scaling of subfonts properly. - - * src/cff/cffparse.c (cff_parse_fixed_dynamic): New function. - (cff_parse_font_matrix): Use it. - - * src/cff/cfftypes.h (CFF_FontDictRec): Make `units_per_em' - FT_ULong. - - * docs/CHANGES: Document it. - -2008-05-13 Werner Lemberg - - * src/winfonts/winfnt.c (fnt_face_get_dll_font, FNT_Face_Init): - Handle case `face_index < 0'. - * docs/CHANGES: Document it. - -2008-05-04 Werner Lemberg - - First steps to fix the scaling bug of CID-keyed CFF subfonts, - reported by Ding Li on 2008/03/28 on freetype-devel. - - * src/base/cff/cffparse.c (power_tens): New array. - (cff_parse_real): Rewritten to introduce a fourth parameter which - returns the `scaling' of the real number so that we have no - precision loss. This is not used yet. - Update all callers. - (cff_parse_fixed_thousand): Replace with... - (cff_parse_fixed_scaled): This function. Update all callers. - -2008-05-03 Werner Lemberg - - * src/base/ftobjs.c (FT_Load_Glyph): Call the auto-hinter without - transformation since it recursively calls FT_Load_Glyph. This fixes - Savannah bug #23143. - -2008-04-26 Werner Lemberg - - * include/freetype/internal/psaux.h (T1_BuilderRec): Mark `scale_x' - and `scale_y' as obsolete since they aren't used. - * src/psaux/psobjs.c (t1_builder_init): Updated. - - * src/cff/cffgload.h (CFF_Builder): Mark `scale_x' and `scale_y' as - obsolete since they aren't used. - * src/cff/cffgload.c (cff_builder_init): Updated. - -2008-04-14 Werner Lemberg - - * src/pcf/pcfdrivr.c (PCF_Face_Init): Protect call to - `FT_Stream_OpenLZW' with `FT_CONFIG_OPTION_USE_LZW'. From Savannah - bug #22909. - -2008-04-13 Werner Lemberg - - * src/psaux/psconv.c (PS_Conv_ToFixed): Increase precision if - integer part is zero. - -2008-04-01 Werner Lemberg - - Fix compilation with g++ 4.1 (with both `single' and `multi' - targets). - - * src/base/ftobjs.c (FT_Open_Face): Don't define a variable in block - which is crossed by a `goto'. - - * src/otvalid/otvalid.h (otv_MATH_validate): Add prototype. - -2008-03-31 Werner Lemberg - - Fix support for subsetted CID-keyed CFFs. - - * include/freetype/freetype.h (FT_FACE_FLAG_CID_KEYED, - FT_IS_CID_KEYED): New macros. - - * src/cff/cffobjs.c (cff_face_init): Set number of glyphs to the - maximum CID value in CID-keyed CFFs. - Handle FT_FACE_FLAG_CID_KEYED flag. - - * docs/CHANGES: Document it. - - - Fix CFF font matrix calculation and improve precision. - - * src/cff/cffparse.c (cff_parse_real): Increase precision if integer - part is zero. - (cff_parse_font_matrix): Simplify computation of `units_per_em'; - this prevents overflow also. - - - Support FT_Get_CID_Registry_Ordering_Supplement for PS CID fonts. - - * src/cid/cidriver.c: Include FT_SERVICE_CID_H. - (cid_get_ros): New function. - (cid_service_cid_info): New service structure. - (cid_services): Register it. - -2008-03-23 Werner Lemberg - - Adjustments for Visual C++ 8.0, as reported by Rainer Deyke. - - * builds/compiler/visualc.mk (CFLAGS): Remove /W5. - (ANSIFLAGS): Add _CRT_SECURE_NO_DEPRECATE. - -2008-03-21 Laurence Darby - - * src/type1/t1objs.c (T1_Face_Init): Use `/Weight'. Patch from - Savannah bug #22675. - -2008-03-13 Derek Clegg - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Fix named style loop. - Patch from Savannah bug #22541. - -2008-03-03 Masatoshi Kimura - - * src/sfnt/ttcmap.c (tt_cmap14_char_map_nondef_binary, - tt_cmap14_find_variant): Return correct value. - (tt_cmap14_variant_chars): Fix check for `di'. - -2008-02-29 Werner Lemberg - - * docs/CHANGES: Updated. - -2008-02-29 Wolf - - Add build support for symbian platform. From Savannah bug #22440. - - * builds/symbian/*: New files. - -2008-02-21 suzuki toshiya - - * src/base/ftmac.c (parse_fond): Fix a bug of PostScript font name - synthesis. For any face of a specified FOND, always the name for - the first face was used. Except of a FOND that refers multiple - Type1 font files, wrong synthesized font names are not used at all, - so this is an invisible bug. A few limit checks are added too. - - * builds/mac/ftmac.c: Ditto. - -2008-02-21 suzuki toshiya - - * builds/unix/configure.raw: Split compiler option to link Carbon - frameworks to one option for CoreServices framework and another - option for ApplicationServices framework. The split options can be - managed by GNU libtool to avoid unrequired duplication when FreeType - is linked with other applications. Suggested by Daniel Macks, - Savannah bug #22366. - -2008-02-18 Victor Stinner - - * src/truetype/ttinterp.c (Ins_IUP): Check number of points. Fix - from Savannah bug #22356. - -2008-02-17 Jonathan Blow - - * src/autofit/afloader.c (af_loader_load_g, af_loader_load_glyph): - Check for valid callback pointers. - -2008-02-15 suzuki toshiya - - * src/base/ftmac.c (FT_New_Face_From_SFNT): Check the sfnt resource - handle by its value instead of ResError(), fix provided by Deron - Kazmaier. According to the Resource Manager Reference, - GetResource(), Get1Resource(), GetNamedResource(), - Get1NamedResource() and RGetResource() set noErr but return NULL - handle when they can not find the requested resource. These - functions never return undefined values, so it is sufficient to - check if the handle is not NULL. - - * builds/mac/ftmac.c (FT_New_Face_From_SFNT): Ditto. - -2008-02-14 suzuki toshiya - - * src/base/ftbase.c: is replaced by "ftmac.c" as other - inclusion styles. Now it always includes src/base/ftmac.c; - builds/mac/ftmac.c is never included in any configuration. - - * builds/unix/configure.raw: Print warning if configure is executed - with options to specify Carbon functionalities explicitly. - - * docs/INSTALL.MAC: Note that legacy builds/mac/ftmac.c is not - included automatically and manual replacement is required. - -2008-02-11 Werner Lemberg - - * builds/modules.mk (CLOSE_MODULE, REMOVE_MODULE), builds/detect.mk - (dos_setup), builds/freetype.mk (clean_project_dos, - distclean_project_dos): Don't use \ but $(SEP). Reported by Duncan - Murdoch. - -2008-01-18 Sylvain Pasche - - * src/base/ftlcdfil.c (_ft_lcd_filter_legacy): Updated comment to - mention intra-pixel algorithm. - - * include/freetype/freetype.h (FT_Render_Mode): Mention that - FT_Library_SetLcdFilter can be used to reduce fringes. - -2008-01-16 Werner Lemberg - - * src/raster/ftraster.c (ft_black_render): Check `outline' before - using it. Reported by Allan Yang. - -2008-01-12 Werner Lemberg - - * src/raster/ftraster.c (FT_CONFIG_OPTION_5_GRAY_LEVELS): Remove. - -2008-01-12 Allan Yang, Jian Hua - SH - - * src/raster/ftraster.c (ft_black_init) - [FT_RASTER_OPTION_ANTI_ALIASING]: Fix compilation. - -2008-01-10 Werner Lemberg - - * src/truetype/ttgload.c (load_truetype_glyph): Handle the case - where the number of contours in a simple glyph is zero (and which - does contain an entry in the `glyf' table). This fixes Savannah bug - #21990. - -2008-01-04 suzuki toshiya - - Formatting suggested by Sean McBride. - - * builds/mac/ftmac.c: Formatting (tab expanded). - * src/autofit/afindic.c: Ditto. - * src/base/ftcid.c: Ditto. - * src/base/ftmac.c: Ditto. - -2007-12-30 Werner Lemberg - - * src/smooth/ftgrays.c (gray_raster_render): Check `outline' - correctly. - -2007-12-21 suzuki toshiya - - Improvement of POSIX resource-fork accessor to load unsorted - references in a resource. In HelveLTMM (resource-fork PostScript - Type1 font bundled with Mac OS X since 10.3.x), the appearance order - of PFB chunks is not sorted; sorting the chunks by reference IDs is - required. - - * include/freetype/internal/ftrfork.h (FT_RFork_Ref): New structure - type to store a pair of reference ID and offset to the chunk. - - * src/base/ftrfork.c (ft_raccess_sort_ref_by_id): New function to - sort FT_RFork_Ref by their reference IDs. - - (FT_Raccess_Get_DataOffsets): Returns an array of offsets that is - sorted by reference ID. - -2007-12-14 Werner Lemberg - - * src/cff/cffparse.c (cff_parse_real): Don't apply `power_ten' - division too early; otherwise the most significant digit(s) of the - final result are lost as the value is truncated to an integer. This - fixes Savannah bug #21794 (where the patch has been posted too). - -2007-12-06 Fix <4d876b82@gmail.com> - - Pass options from one configure script to another as-is (not - expanded). This is needed for options like - --includedir='${prefix}/include'. - - * builds/unix/detect.mk, configure: Prevent argument expansion in - call to the (real) `configure' script. - -2007-12-06 Werner Lemberg - - * src/truetype/ttgload.c (load_truetype_glyph): Fix compilation if - TT_USE_BYTECODE_INTERPRETER isn't defined. - -2007-12-06 Werner Lemberg - - There exist CFFs which contain opcodes for the Type 1 operators - `hsbw' and `closepath' which are both invalid in Type 2 charstrings. - However, it doesn't harm to support them. - - * src/cff/cffgload.c (CFF_Operator): Add `cff_op_hsbw' and - `cff_op_closepath.' - (cff_argument_counts): Ditto. - - (cff_decoder_parse_charstrings): Handle Type 1 opcodes 9 (closepath) - and 13 (hsbw) which are invalid in Type 2 charstrings. - -2007-12-06 suzuki toshiya - - * src/base/ftrfork.c (raccess_guess_darwin_newvfs): New function to - support new pathname syntax `..namedfork/rsrc' to access a resource - fork on Mac OS X. The legacy syntax `/rsrc' does not work on - case-sensitive HFS+. - (raccess_guess_darwin_hfsplus): Fix a bug in the calculation of - buffer size to store a pathname. - * include/freetype/internal/ftrfork.h: Increment the number of - resource fork guessing rule. - -2007-12-06 suzuki toshiya - - * builds/unix/configure.raw: Improve the compile tests to search - Carbon functions. - * builds/mac/ftmac.c: Import fixes for Carbon incompatibilities - proposed by Sean McBride from src/base/ftmac.c (see 2007-11-16). - -2007-12-06 suzuki toshiya - - The documents and comments for Mac OS X are improved by Sean - McBride. - - * src/base/ftmac.c: Fix a comment. - * include/freetype/ftmac.h: Ditto. - * docs/INSTALL.MAC: Improve English and add comment on lowest - system version specified by MACOSX_DEPLOYMENT_TARGET. - -2007-12-04 Werner Lemberg - - * src/cff/cffload.c (cff_subfont_load): Don't use logical OR to - concatenate error codes. - * src/sfnt/ttsbit.c (Load_SBit_Range): Ditto. - -2007-12-04 Graham Asher - - * src/truetype/ttobjs.c (tt_face_init): Don't use logical OR to - concatenate error codes. - -2007-12-04 Sean McBride - - * src/pfr/pfrgload.c (pfr_glyph_load_compound): Remove compiler - warning. - -2007-11-20 suzuki toshiya - - Fix MacOS legacy font support by Masatake Yamato on Mac OS X. It is - not working since 2.3.5. In FT_Open_New(), if FT_New_Stream() - cannot mmap() the specified file and cannot seek to head of the - specified file, it returns NULL stream and FT_Open_New() returns the - error immediately. On MacOS, most legacy MacOS fonts fall into such - a scenario because their data forks are zero-sized and cannot be - sought. To proceed to guessing of resource fork fonts, the - functions for legacy MacOS font must properly handle the NULL stream - returned by FT_New_Stream(). - - * src/base/ftobjs.c (IsMacBinary): Return error - FT_Err_Invalid_Stream_Operation immediately when NULL stream is - passed. - (FT_Open_Face): Even when FT_New_Stream() returns an error, proceed - to fallback. Originally, legacy MacOS font is tested in the cases - of FT_Err_Invalid_Stream_Operation (occurs when data fork is empty) - or FT_Err_Unknown_File_Format (occurs when AppleSingle header or - .dfont header is combined). Now the case of - FT_Err_Cannot_Open_Stream is included. - - * src/base/ftrfork.c (FT_Raccess_Guess): When passed stream is NULL, - skip FT_Stream_Seek(), which seeks to the head of stream, and - proceed to unit testing of raccess_guess_XXX(). FT_Stream_Seek() - for a NULL stream causes a Bus error on Mac OS X. - (raccess_guess_apple_double): Return FT_Err_Cannot_Open_Stream - immediately if passed stream is NULL. - (raccess_guess_apple_single): Ditto. - -2007-11-16 suzuki toshiya - - Fix for Carbon incompatibilities since Mac OS X 10.5, - proposed by Sean McBride. - - * doc/INSTALL.MAC: Comment on MACOSX_DEPLOYMENT_TARGET. - - * include/freetype/ftmac.h: Deprecate FT_New_Face_From_FOND and - FT_GetFilePath_From_Mac_ATS_Name. Since Mac OS X 10.5, calling - Carbon functions from a forked process is classified as unsafe - by Apple. All Carbon-dependent functions should be deprecated. - - * src/base/ftmac.c: Use essential header files - and - instead of - all-in-one header file . - - Include and replace HFS_MAXPATHLEN by Apple - genuine macro PATH_MAX. - - Add fallback macro for kATSOptionFlagsUnRestrictedScope which - is not found in Mac OS X 10.0. - - Multi-character constants ('POST', 'sfnt' etc) are replaced by - 64bit constants calculated by FT_MAKE_TAG() macro. - - For the index in the segment of resource fork, new portable - type ResourceIndex is introduced for better compatibility. - This type is since Mac OS X 10.5, so it is defined as short - when built on older platforms. - - (FT_ATSFontGetFileReference): If build target is only the systems - 10.5 and newer, it calls Apple genuine ATSFontGetFileReference(). - - (FT_GetFile_From_Mac_ATS_Name): Return an error if system is 10.5 - and newer or 64bit platform, because legacy type FSSpec type is - removed completely. - - (FT_New_Face_From_FSSpec): Ditto. - -2007-11-01 Werner Lemberg - - * src/sfnt/sfobjs.c (sfnt_done_face): Check `sfnt' everywhere. This - fixes Savannah bug #21485. - -2007-10-29 Daniel Svoboda - - * src/winfonts/winfnt.c (FNT_Face_Init): Check first that the driver - can handle the font at all, then check `face_index'. Otherwise, the - driver might return the wrong error code. This fixes Savannah bug - #21468. - -2007-10-21 Werner Lemberg - - * src/sfnt/sfobjs.c (sfnt_load_face): Support bit 9 and prepare - support for bit 8 of the `fsSelection' field in the `OS/2' table. - MS is already using this; hopefully, this becomes part of OpenType - 1.5. - Prepare also support for `name' IDs 21 (WWS_FAMILY) and 22 - (WWS_SUBFAMILY). - -2007-10-20 Werner Lemberg - - * src/tools/docmaker/tohtml.py (html_header_2): Fix typo. - Add `td.left' element to CSS. - (toc_section_enter): Use it. - -2007-10-18 David Turner - - * include/freetype/freetype.h, src/base/ftobjs.c: Rename API - functions related to cmap type 14 support to the - `FT_Object_ActionName' scheme: - - FT_Get_Char_Variant_Index -> FT_Face_GetCharVariantIndex - FT_Get_Char_Variant_IsDefault -> FT_Face_GetCharVariantIsDefault - FT_Get_Variant_Selectors -> FT_Face_GetVariantSelectors - FT_Get_Variants_Of_Char -> FT_Face_GetVariantsOfChar - FT_Get_Chars_Of_Variant -> FT_Face_GetCharsOfVariant - - Update documentation accordingly. - - * src/sfnt/ttcmap.c: Stronger cmap 14 validation. - Make the code a little more consistent with FreeType coding - conventions and modify the cmap14 functions that returned a newly - allocated array to use a persistent vector from the TT_CMap14 object - instead. - - (TT_CMap14Rec): Provide array and auxiliary data for result. - (tt_cmap14_done, tt_cmap14_ensure): New functions. - - (tt_cmap14_init, tt_cmap14_validate, tt_cmap14_char_map_def_binary, - tt_cmap14_char_map_nondef_binary, tt_cmap14_find_variant, - tt_cmap14_char_var_index, tt_cmap14_variants, - tt_cmap14_char_variants, tt_cmap14_def_char_count, - tt_cmap14_get_def_chars, tt_cmap14_get_nondef_chars, - tt_cmap14_variant_chars, tt_cmap14_class_rec): Updated and improved. - -2007-10-15 George Williams - - Add support for cmap type 14. - - * devel/ftoption.h, include/freetype/config/ftoption.h - (TT_CONFIG_CMAP_FORMAT_14): New macro. - - * include/freetype/internal/ftobjs.h (FT_CMap_CharVarIndexFunc, - FT_CMap_CharVarIsDefaultFunc, FT_CMap_VariantListFunc, - FT_CMap_CharVariantListFunc, FT_CMap_VariantCharListFunc): New - support function prototypes. - (FT_CMap_ClassRec): Add them. - Update all users. - - * include/freetype/ttnameid.h (TT_APPLE_ID_VARIANT_SELECTOR): New - macro. - - * include/freetype/freetype.h (FT_Get_Char_Variant_Index, - FT_Get_Char_Variant_IsDefault, FT_Get_Variant_Selectors, - FT_Get_Variants_Of_Char, FT_Get_Chars_Of_Variant): New API - functions. - - * src/base/ftobjs.c (find_variant_selector_charmap): New auxiliary - function. - (FT_Set_Charmap): Disallow cmaps of type 14. - (FT_Get_Char_Variant_Index, FT_Get_Char_Variant_IsDefault, - FT_Get_Variant_Selectors, FT_Get_Variants_Of_Char, - FT_Get_Chars_Of_Variant): New API functions. - - * src/sfnt/ttcmap.c (TT_PEEK_UINT24, TT_NEXT_UINT24): New macros. - - (TT_CMap14Rec, tt_cmap14_init, tt_cmap14_validate, - tt_cmap14_char_index, tt_cmap14_char_next, tt_cmap14_get_info, - tt_cmap14_char_map_def_binary, tt_cmap14_char_map_nondef_binary, - tt_cmap14_find_variant, tt_cmap14_char_var_index, - tt_cmap14_char_var_isdefault, tt_cmap14_variants, - tt_cmap14_char_variants, tt_cmap14_def_char_count, - tt_cmap14_get_def_chars, tt_cmap14_get_nondef_chars, - tt_cmap14_variant_chars, tt_cmap14_class_rec): New functions and - structures for cmap 14 support. - (tt_cmap_classes): Register tt_cmap14_class_rec. - (tt_face_build_cmaps): One more error message. - - * docs/CHANGES: Mention cmap 14 support. - -2007-10-01 Werner Lemberg - - * src/base/ftobjs.c (find_unicode_charmap): If search for a UCS-4 - charmap fails, do the loop again while searching a UCS-2 charmap. - This favours MS charmaps over Apple ones. - -2007-08-29 suzuki toshiya - - * src/base/ftmac.c: Introduction of abstract `short' data types, - ResFileRefNum and ResID. These types were introduced for Copland, - then backported to MPW. The variables exchanged with FileManager - QuickDraw frameworks are redefined by these data types. Patch was - proposed by Sean McBride. - * builds/mac/ftmac.c: Ditto. - -2007-08-18 Werner Lemberg - - * src/otvalid/otvcommn.c (otv_x_y_ux_sy): Skip context glyphs. Found - by Imran Yousaf. Fixes Savannah bug #20773. - - (otv_Lookup_validate): Correct handling of LookupType. Found by - Imran Yousaf. Fixes Savannah bug #20782. - -2007-08-17 George Williams - - * src/otvalid/otvgsub.c (otv_SingleSubst_validate): Fix handling of - SingleSubstFormat1. - -2007-08-11 suzuki toshiya - - * builds/unix/configure.raw: Fix a bug which sets CC_BUILD by - ${build-gcc} (unchecked) instead of by ${build}-gcc (checked). - Found by Ryan Hill. - -2007-08-11 George Williams - - * src/otvalid/otvcommn.c, src/otvalid/otvcommn.h - (otv_Coverage_validate): Add fourth argument to pass an expected - count value. Update all users. - Check glyph IDs. - (otv_ClassDef_validate): Check `StartGlyph'. - - * src/otvalid/otvgsub.c (otv_SingleSubst_validate): More glyph ID - checks. - - * src/otvalid/otvmath.c (otv_MathConstants_validate): There are only - 56 constants. - (otv_GlyphAssembly_validate, otv_MathGlyphConstruction_validate): - Check glyph IDs. - -2007-08-08 Werner Lemberg - - * src/otvalid/otvbase.c, src/otvalid/otvcommn.c, - src/otvalid/otvgdef.c, src/otvalid/otvgpos.c, src/otvalid/otvgsub.c, - src/otvalid/otvjstf.c: s/FT_INVALID_DATA/FT_INVALID_FORMAT/ where - appropriate. Reported by George. - - * include/freetype/internal/fttrace.h: Define `trace_otvmath'. - - * src/otvalid/rules.mk (OTV_DRV_SRC): Add otvmath.c. - - * docs/CHANGES: Updated. - -2007-08-08 George Williams - - Add `MATH' validating support to otvalid module. - - * include/freetype/tttags.h (TTAG_MATH): New macro. - * include/freetype/ftotval.h (FT_VALIDATE_MATH): New macro. - (FT_VALIDATE_OT): Updated. - - * src/otvalid/otvmath.c: New file. - - * src/otvalid/otvalid.c: Include otvmath.c. - * src/otvalid/otvmod.c (otv_validate): Handle `MATH' table. - -2007-08-04 Werner Lemberg - - * builds/unix/configure.raw: Add call to AC_LIBTOOL_WIN32_DLL. - Fixes Savannah bug #20686. - -2007-08-03 Werner Lemberg - - * src/psnames/psmodule.c: Fix usage of - FT_CONFIG_OPTION_POSTSCRIPT_NAMES macro. Reported by Graham Asher. - -2007-07-31 suzuki toshiya - - * src/base/ftmac.c (open_face_from_buffer): The argument - `driver_name' is typed as `const char*' to match with the - callers in FT_New_Face_From_LWFN and FT_New_Face_From_SFNT. - This is same with open_face_from_buffer in src/base/ftobjs.c. - Found and fixed by Sean McBride. - -2007-07-28 Werner Lemberg - - * src/raster/ftraster.c (count_table): Make it conditional. - * src/base/ftobjs.c (FT_New_Library): Check FT_RENDER_POOL_SIZE with - a preprocessor statement. - -2007-07-27 Werner Lemberg - - * src/base/ftoutln.c (FT_Outline_Translate): Check `outline' before - first usage. From Savannah patch #6115. - -2007-07-16 Werner Lemberg - - * docs/CHANGES: Updated. - -2007-07-16 Derek Clegg - - Add new service for getting the ROS from a CID font. - - * include/freetype/config/ftheader.h (FT_CID_H): New macro. - * include/freetype/ftcid.h: New file. - - * include/freetype/internal/ftserv.h (FT_SERVICE_CID_H): New macro. - * include/freetype/internal/services/svcid.h: New file. - - * src/base/ftcid.c: New file. - - * src/cff/cffdrivr.c: Include FT_SERVICE_CID_H. - (cff_get_ros): New function. - (cff_service_cid_info): New service structure. - (cff_services): Register it. - - * src/cff/cffload.c (cff_font_done): Free registry and ordering. - - * src/cff/cfftypes.h (CFF_FontRec): Add `registry' and `ordering'. - - * modules.cfg (BASE_EXTENSIONS): Add ftcid.c. - -2007-07-11 Derek Clegg - - Add support for postscript name service to CFF driver. - - * src/cff/cffdrivr.c: Include FT_SERVICE_POSTSCRIPT_NAME_H. - (cff_get_ps_name): New function. - (cff_service_ps_name): New service structure. - (cff_services): Register it. - -2007-07-07 Werner Lemberg - - * src/base/ftglyph.c (FT_Glyph_Copy): Fix initialization of - `target'. Reported by Sean McBride. - -2007-07-06 Werner Lemberg - - * src/pfr/pfrcmap.c: Include pfrerror.h. - - * src/autofit/afindic.c: Add some external declarations to pacify - `make multi' compilation. - - * src/cid/cidgload.c (cid_load_glyph): Pacify compiler. - - * src/cff/cffdrivr.c (cff_ps_get_font_info), src/cff/cffobjs.c - (cff_strcpy), include/freetype/internal/ftmemory.h (FT_MEM_STRDUP), - src/autofit/aflatin.c (af_latin_hints_compute_edges), - src/autofit/afcjk.c (af_cjk_hints_compute_edges), src/sfnt/ttmtx.c - (tt_face_get_metrics), src/base/ftobjs.c (open_face) - [FT_CONFIG_OPTION_INCREMENTAL]: Fix compilation with C++ compiler. - - * docs/release: Mention test compilation targets. - -2007-07-04 Werner Lemberg - - * docs/PROBLEMS: Mention that some PS based fonts can't be - handled correctly by FreeType. - - * src/truetype/ttgload.c (load_truetype_glyph): Always allow a - recursion depth of 1. This was the maximum value in TrueType 1.0, - and some older fonts don't set this field correctly. - - * src/gxvalid/gxvmort1.c - (gxv_mort_subtable_type1_substTable_validate): Fix tracing message. - -2007-07-03 Werner Lemberg - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Initialize - `round' to pacify compiler. - -2007-07-02 Werner Lemberg - - - * Version 2.3.5 released. - ========================= - - - Tag sources with `VER-2-3-5'. - - * docs/CHANGES, docs/VERSION.DLL: Update documentation and bump - version number to 2.3.5. - - * README, Jamfile (RefDoc), builds/win32/visualc/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualce/index.html, - builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj: s/2.3.4/2.3.5/, s/234/235/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 5. - - * builds/unix/configure.raw (version_info): Set to 9:16:3. - -2007-07-01 David Turner - - * include/freetype/freetype.h, src/base/ftpatent.c - (FT_Face_SetUnpatentedHinting): New function to dynamically change - the setting after a face is created. - - * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Fix a small bug - that created distortions in the bytecode interpreter results. - -2007-06-30 David Turner - - * src/truetype/ttinterp.c (Ins_IUP): Add missing variable - initialization. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Get rid of an - infinite loop in the case of degenerate fonts. - -2007-06-26 Rahul Bhalerao - - Add autofit module for Indic scripts. This currently just reuses - the CJK-specific functions. - - * include/freetype/config/ftoption.h (AF_CONFIG_OPTION_INDIC): New - macro. - * devel/ftoption.h: Synchronize with - include/freetype/config/ftoption.h. - - * src/autofit/afindic.c, src/autofit/afindic.h: New files. - - * src/autofit/afglobal.c, src/autofit/aftypes.h, - src/autofit/autofit.c: Updated. - - * src/autofit/Jamfile (_sources), * src/autofit/rules.mk - (AUTOF_DRV_SRC): Updated. - -2007-06-23 David Turner - - * src/truetype/ttgload.c (TT_Load_Simple): Fix change from - 2007-06-16 that prevented the TrueType module from loading most - glyphs. - -2007-06-20 Werner Lemberg - - * src/cff/cffgload.c (cff_slot_load): Fix logic of 2007-05-28 - change. - -2007-06-19 Werner Lemberg - - * src/type1/t1load.c (parse_encoding): Handle one more error. - -2007-06-19 Dmitry Timoshkov - - * src/winfonts/winfnt.c (fnt_face_get_dll_font): Return error - FNT_Err_Invalid_File_Format if file format was recognized but - the file doesn't contain any FNT(NE) or RT_FONT(PE) resources. - Add verbose debug logs to make it easier to debug failing load - attempts. - (FNT_Face_Init): A single FNT font can't contain more than 1 face, - so return an error if requested face index is > 0. - Do not do further attempt to load fonts if a previous attempt has - failed but returned error FNT_Err_Invalid_File_Format, i.e., the - file format has been recognized but no fonts found in the file. - -2007-07-19 suzuki toshiya - - * src/base/ftmac.c: Apply patches proposed by Sean McBride. - (FT_GetFile_From_Mac_Name): Insert FT_UNUSED macros to fix - the compiler warnings against unused arguments. - (FT_ATSFontGetFileReference): Ditto. - (FT_GetFile_From_Mac_ATS_Name): Ditto. - (FT_New_Face_From_FSSpec): Ditto. - (lookup_lwfn_by_fond): Fix wrong comment. - Replace `const StringPtr' by more appropriate type - `ConstStr255Param'. - FSRefMakePathPath always returns UTF8 POSIX pathname in - Mach-O, thus HFS pathname support is dropped. - (count_faces): Remove HLock and HUnlock which is not - required on Mac OS X anymore. - (FT_New_Face_From_SFNT): Ditto. - (FT_New_Face_From_FOND): Ditto. - * builds/mac/ftmac.c: Synchronize to src/base/ftmac.c, - except of HFS pathname support and HLock/HUnlock. - They are required on classic CFM environment. - -2007-06-18 Werner Lemberg - - * src/psaux/psobjs.c (ps_parser_skip_PS_token): Remove incorrect - assertion. - (ps_parser_to_bytes): Fix error message. - - * src/type42/t42objs.c (T42_Open_Face): Handle one more error. - * src/type42/t42parse.c (t42_parse_sfnts): s/alloc/allocated/. - Don't allow mixed binary and hex strings. - Handle string_size == 0 and string_buf == 0. - (t42_parse_encoding): Handle one more error. - -2007-06-18 Werner Lemberg - - * src/psaux/psobjs.c (ps_tofixedarray, ps_tocoordarray): Fix exit - logic. - (ps_parser_load_field) : Skip delimiters - correctly. - (ps_parser_load_field_table): Use `fields->array_max' instead of - T1_MAX_TABLE_ELEMENTS to limit the number of arguments. - - * src/cff/cffgload.c (cff_decoder_prepare): Fix change from - 2007-06-06. - -2007-06-17 Werner Lemberg - - * src/tools/ftrandom.c (font_size): New global variable. - (TestFace): Use it. - (main): Handle new option `--size' to set `font_size'. - (Usage): Updated. - - * src/winfonts/winfnt.c (fnt_face_get_dll_font): Exit in case of - invalid font. - (FNT_Load_Glyph): Protect against invalid bitmap width. - -2007-06-16 David Turner - - * src/smooth/ftgrays.c (gray_find_cell, gray_set_cell, gray_hline): - Prevent integer overflows when rendering very large outlines. - - * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Check the - well-formedness of the contours array when loading a glyph. - - * src/truetype/ttinterp.c (TT_Load_Context): Initialize `zp0', `zp1', - and `zp2'. - (Ins_IP): Check argument ranges to reject bogus operations properly. - (IUP_WorkerRec): Add `max_points' member. - (_iup_worker_interpolate): Check argument ranges. - (Ins_IUP): Ignore empty outlines. - -2007-06-16 Dmitry Timoshkov - - * src/winfonts/winfnt.h: Add necessary structures for PE resource - parsing. - (WinPE32_HeaderRec): New structure. - (WinPE32_SectionRec): New structure. - (WinPE_RsrcDirRec): New structure. - (WinPE_RsrcDirEntryRec): New structure. - (WinPE_RsrcDataEntryRec): New structure. - (FNT_FontRec): Remove unused `size_shift' field. - - * src/winfonts/winfnt.c (fnt_face_get_dll_font): Add support for - loading bitmap .fon files in PE format. - -2007-06-15 Dmitry Timoshkov - - * builds/win32/ftdebug.c: Unify debug level handling with other - platforms. - -2007-06-14 Dmitry Timoshkov - - * builds/win32/ftdebug.c (FT_Message): Send debug output to the - console as well as to the debugger. - -2007-06-14 Werner Lemberg - - * src/autofit/aflatin.c (af_latin_uniranges): Expand structure to - cover all ranges which could possibly be handled by the aflatin - module (since the default fallback for unknown ranges is now the - afcjk module). It might be necessary to fine-tune this further by - splitting off modules for Greek, Cyrillic, or other blocks. - -2007-06-11 David Turner - - * src/autofit/aflatin.c (af_latin_hints_link_segments): Fix - incorrect segment linking computation. This was the root cause of - Savannah bug #19565. - - - * src/autofit/* [FT_OPTION_AUTOFIT2]: Some very experimental changes - to improve the Latin auto-hinter. Note that the new code is - disabled by default since it is not stabilized yet. - - * src/autofit/aflatin2.c, src/autofit/aflatin2.h: New files - (disabled currently). - - * src/autofit/afhints.c: Remove dead code. - (af_axis_hints_new_edge): Add argument to handle segment directions. - (af_edge_flags_to_string): New function. - (af_glyph_hints_dump_segments, af_glyph_hints_dump_edges): Handle - option flags. - (af_glyph_hints_reload): Add argument to handle inflections. - Simplify. - (af_direction_compute): Fine tuning. - (af_glyph_hints_align_edge_points): Fix logic. - (af_glyph_hints_align_strong_points): Do linear search for small - edge counts. - (af_glyph_hints_align_weak_points): Skip any touched neighbors. - (af_iup_shift): Handle zero `delta'. - - * src/autofit/afhints.h: Updated. - (AF_SORT_SEGMENTS): New macro (disabled). - (AF_AxisHintsRec) [AF_SORT_SEGMENTS]: New member `mid_segments'. - - * src/autofit/afglobal.c (af_face_globals_get_metrics): Add - argument to pass option flags for handling scripts. - * src/autofit/afglobal.h: Updated. - - * src/autofit/afcjk.c: Updated. - * src/autofit/aflatin.c: Updated. - (af_latin_metrics_scale_dim): Don't reduce scale by 2%. - - (af_latin_hints_compute_segments) [AF_HINT_METRICS]: Remove dead code. - (af_latin_hints_compute_edges) [AF_HINT_METRICS]: Remove dead code. - Don't set `edge->dir' - (af_latin_hint_edges): Add more logging. - - * src/autofit/afloader.c: Updated. - -2007-06-11 Werner Lemberg - - * docs/CHANGES: Document FT_Face_CheckTrueTypePatents. - -2007-06-10 David Turner - - * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Slight speed-up to - the TrueType glyph loader. - - * include/freetype/config/ftoption.h: Clarify documentation - regarding unpatented hinting. - - - Add new `FT_Face_CheckTrueTypePatents' API. - - * include/freetype/freetype.h (FT_Face_CheckTrueTypePatents): New - declaration. - - * include/freetype/internal/services/svttglyf.h, - src/base/ftpatent.c: New files. - - * include/freetype/internal/ftserv.h (FT_SERVICE_TRUETYPE_GLYF_H): - New macro. - - * src/truetype/ttdriver.c: Include FT_SERVICE_TRUETYPE_GLYF_H and - `ttpload.h'. - (tt_service_truetype_glyf): New service structure. - (tt_services): Register it. - - * modules.cfg (BASE_EXTENSIONS), src/base/Jamfile (_sources): Add - `ftpatent.c'. - -2007-06-08 Werner Lemberg - - * src/sfnt/sfobjs.c (sfnt_load_face): Undo change from 2007-04-28. - Fonts without a cmap must be handled correctly by FreeType (anything - else would be a bug). - - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings) - [FT_DEBUG_LEVEL_TRACE]: Improve tracing message. - -2007-06-07 Werner Lemberg - - * src/sfnt/ttsbit0.c (tt_sbit_decoder_init, - tt_sbit_decoder_load_image): Protect against integer overflows. - - - * src/pfr/pfrgload.c (pfr_glyph_load_simple): More bounding checks - for `x_control' and `y_control'. - -2007-06-06 Werner Lemberg - - * src/base/ftoutln.c (FT_Outline_Decompose): Check `last'. - - - * src/pfr/pfrcmap.c (pfr_cmap_init): Convert assertion into normal - FreeType error. - - - * src/winfonts/winfnt.c (fnt_face_get_dll_font): Do a rough check of - `font_count'. - - - * src/type1/t1load.c (parse_font_matrix): Check `temp_scale'. - - - * src/cff/cffgload.c (cff_decoder_prepare): Change return type to - `FT_Error'. - Check `fd_index'. - (cff_slot_load): Updated. - * src/cff/cffgload.h: Updated. - -2007-06-05 Werner Lemberg - - * src/pfr/pfrgload.c (pfr_glyph_done): Comment out unused code. - (pfr_glyph_load_simple): Convert assertion into normal FreeType - error. - Check `idx'. - (pfr_glyph_load_compound, pfr_glyph_curve_to, pfr_glyph_line_to): - Convert assertion into normal FreeType error. - - * src/pfr/pfrtypes.h (PFR_GlyphRec): Comment out unused code. - - - * src/winfonts/winfnt.c (FNT_Face_Init): Check `family_size'. - - - * src/psaux/psobjs.c (ps_tocoordarray, ps_tofixedarray): Return -1 - in case of parsing error. - (ps_parser_load_field): Updated. - - * src/type1/t1load.c (parse_font_matrix): Updated. - -2007-06-04 Werner Lemberg - - * src/cid/cidgload.c (cid_load_glyph): Check `fd_select'. - - * src/tools/ftrandom/Makefile: Depend on `libfreetype.a'. - -2007-06-03 Werner Lemberg - - * src/tools/ftrandom/*: Add the `ftrandom' test program written by - George Williams (with some modifications). - -2007-06-03 Werner Lemberg - - * src/base/ftobjs.c (destroy_charmaps), src/type1/t1objs.c - (T1_Face_Done), src/winfonts/winfnt.c (FNT_Face_Done): Check for - face == NULL. Suggested by Graham Asher. - -2007-06-03 Ismail Dönmez - - * src/base/ftobjs.c (FT_Request_Metrics): Fix compiler warning. - -2007-06-02 Werner Lemberg - - * include/freetype/fterrdef.h (FT_Err_Corrupted_Font_Header, - FT_Err_Corrupted_Font_Glyphs): New error codes for BDF files. - - * src/bdf/bdflib.c (bdf_load_font): Use them. - - * src/bdf/bdflib.c (_bdf_parse_start): Check `FONT' better. - -2007-06-01 Werner Lemberg - - * src/base/ftobjs.c (FT_Request_Metrics), src/cache/ftccmap.c - (FTC_CMapCache_Lookup): Remove unused code. - -2007-06-01 Sean McBride - - * src/truetype/ttinterp.c (Null_Vector, NULL_Vector): Removed, - unused. - -2007-06-01 Werner Lemberg - - * src/cid/cidparse.c (cid_parser_new): Don't continue second search - pass for `StartData' if an error has occurred. - Exit properly if no `StartData' has been seen at all. - - * builds/unix/ftsystem.c (FT_Stream_Open): Don't use ULONG_MAX but - LONG_MAX to avoid compiler warning. Suggested by Sean McBride. - -2007-05-30 Werner Lemberg - - * src/type1/t1load.c (parse_subrs, parse_charstrings): Protect - against too small binary data strings. - - * src/bdf/bdflib.c (_bdf_parse_glyphs): Check `STARTCHAR' better. - -2007-05-28 David Turner - - * src/cff/cffgload.c (cff_slot_load): Do not apply the identity - transformation. This significantly reduces the loading time of CFF - glyphs. - - * docs/CHANGES: Updated. - - * src/autofit/afglobal.c (AF_SCRIPT_LIST_DEFAULT): Change default - hinting script to CJK, since it works well with more scripts than - latin. Thanks to Rahul Bhalerao for pointing - this out! - -2007-05-25 Werner Lemberg - - * docs/CHANGES: Updated. - -2007-05-24 Werner Lemberg - - * src/truetype/ttobjs.h (tt_size_ready_bytecode): Move declaration - into TT_USE_BYTECODE_INTERPRETER preprocessor block. - -2007-05-24 Graham Asher - - * src/truetype/ttobjs.c (tt_size_ready_bytecode) - [!TT_USE_BYTECODE_INTERPRETER]: Removed. Unused. - -2007-05-22 David Turner - - * src/truetype/ttgload.c (load_truetype_glyph): Fix last change to - avoid crashes in case the bytecode interpreter is not used. - - - Avoid heap blowup with very large .Z font files. This fixes - Savannah bug #19910. - - * src/lzw/ftzopen.h (FT_LzwStateRec): Remove `in_cursor', - `in_limit', `pad', `pad_bits', and `in_buff' members. - Add `buf_tab', `buf_offset', `buf_size', `buf_clear', and - `buf_total' members. - - * src/lzw/ftzopen.c (ft_lzwstate_get_code): Rewritten. It now takes - only one argument. - (ft_lzwstate_refill, ft_lzwstate_reset, ft_lzwstate_io): Updated. - -2007-05-20 Ismail Dönmez - - * src/pshinter/pshrec.c (ps_mask_table_set_bits): Add `const'. - (ps_dimension_set_mask_bits): Remove `const'. - -2007-05-19 Werner Lemberg - - * src/sfnt/ttmtx.c (tt_face_get_metrics) - [!FT_CONFIG_OPTION_OLD_INTERNALS]: Another type-punning fix. - -2007-05-19 Derek Clegg - - Savannah patch #5929. - - * include/freetype/tttables.h, src/base/ftobjs.c - (FT_Get_CMap_Format): New function. - - * include/freetype/internal/services/svttcmap.c (TT_CMapInfo): Add - `format' member. - * src/sfnt/ttcmap.c (tt_cmap{0,2,4,6,8,10,12}_get_info): Set - cmap_info->format. - -2007-05-19 Werner Lemberg - - * src/truetype/ttgload.c (load_truetype_glyph): Save graphics state - before handling subglyphs so that it can be reinitialized each time. - This fixes Savannah bug #19859. - -2007-05-16 Werner Lemberg - - * src/cache/ftccache.c (ftc_node_mru_link, ftc_node_mru_unlink), - src/cache/ftccache.h (FTC_CACHE_LOOKUP_CMP), src/cache/ftcglyph.h - (FTC_GCACHE_LOOKUP_CMP), src/pshinter/pshmod.c (ps_hinter_init), - src/sfnt/ttmtx.c (tt_face_load_hmtx, tt_face_load_hhea, - tt_face_get_metrics): Fix type-punning issues. - -2007-05-15 David Turner - - * include/freetype/config/ftstdlib.h, - include/freetype/internal/ftobjs.h: As suggested by Graham Asher, - ensure that ft_isalnum, ft_isdigit, etc., use hard-coded values - instead of relying on the locale-dependent functions provided by - . - -2007-05-15 Graham Asher - - * src/autofit/afcjk.c (af_cjk_hints_compute_edges): Remove unused - variable. - * src/autofit/afloader.c (af_loader_load_g): Ditto. - - * src/base/ftobjs.c (ft_validator_error): Use `ft_jmp_buf'. - (open_face_from_buffer): Initialize `stream'. - (FT_Request_Metrics): Remove unused variable. - Remove redundant `break' statements. - (FT_Get_Track_Kerning): Remove unused variable. - - * src/psaux/afmparse.c (afm_parse_track_kern, afm_parse_kern_pairs, - afm_parse_kern_data): Remove redundant - `break' statements. - (afm_parser_parse): Ditto. - Don't use uninitialized variables. - - * src/psnames/psmodule.c (VARIANT_BIT): Define as unsigned long. - Use `|' operator instead of `^' to set it. - Update all users. - - * src/sfnt/ttcmap.c (tt_face_build_cmaps): Use `ft_jmp_buf'. - * src/sfnt/ttkern.c (tt_face_load_kern): Remove unused variable. - - * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Remove redundant - comparison. - (TT_Process_Simple_Glyph): Use FT_UInt for `n_points' and `i'. - (TT_Load_Glyph): Remove unused variable. - -2007-05-13 Derek Clegg - - * src/base/ftobjs.c (FT_New_Library): Only allocate rendering pool - if FT_RENDER_POOL_SIZE is > 0. From Savannah patch #5928. - -2007-05-11 David Turner - - * src/cache/ftcbasic.c, include/freetype/ftcache.h - (FTC_ImageCache_LookupScaler, FTC_SBit_Cache_LookupScaler): Two new - functions that allow us to look up glyphs using an FTC_Scaler object - to specify the size, making it possible to use fractional pixel - sizes. - - * src/truetype/ttobjs.c (tt_size_ready_bytecode): Set - `size->cvt_ready'. Reported by Boris Letocha. - -2007-05-09 Graham Asher - - * src/truetype/ttinterp.c (Ins_IP), src/autofit/aflatin.c - (af_latin_metrics_scale_dim): Fix compiler warnings. - -2007-05-06 Werner Lemberg - - * builds/win32/visualce/freetype.sln: Removed, as requested by - Vincent. - -2007-05-04 Vincent RICHOMME - - * builds/win32/visualce/*: Add Visual C++ project files for Pocket - PC targets. - - * docs/CHANGES: Document them. - -2007-05-04 - - * builds/unix/ftsystem.c (FT_Stream_Open): Handle return value 0 of - mmap (which might happen on some RTOS). From Savannah patch #5909. - -2007-05-03 Werner Lemberg - - * src/base/ftobjs.c (FT_Set_Char_Size): Simplify code. - * include/freetype/freetype.h (FT_Set_Char_Size): Update - documentation. - -2007-04-28 Victor Stinner - - * src/sfnt/sfobjs.c (sfnt_load_face): Check error code after loading - `cmap'. - -2007-04-27 Werner Lemberg - - * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Check for negative - number of points in contours. Problem reported by Victor Stinner - . - (TT_Process_Simple_Glyph): Synchronize variable types. - -2007-04-26 Werner Lemberg - - * src/base/ftglyph.c (FT_Glyph_Copy): Always set second argument to - zero in case of error. This fixes Savannah bug #19689. - -2007-04-25 Boris Letocha - - * src/truetype/ttobjs.c: Fix a typo that created a speed regression - in the TrueType bytecode loader. - -2007-04-10 Martin Horak - - * src/sfnt/sfobjs.c (sfnt_load_face) [FT_CONFIG_OPTION_INCREMENTAL]: - Ignore `hhea' table. This fixes Savannah bug #19261. - -2007-04-09 Werner Lemberg - - - * Version 2.3.4 released. - ========================= - - - Tag sources with `VER-2-3-4'. - - * docs/CHANGES, docs/VERSION.DLL: Update documentation and bump - version number to 2.3.4. - - * README, Jamfile (RefDoc), builds/win32/visualc/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj: s/2.3.3/2.3.4/, s/233/234/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 4. - - * builds/unix/configure.raw (version_info): Set to 9:15:3. - -2007-04-09 Martin Horak - - * src/truetype/ttgload.c (load_truetype_glyph): Save and restore - memory stream to avoid a crash with the incremental memory - interface (Savannah bug #19260). - -2007-04-06 David Turner - - * src/base/ftbitmap.c (ft_bitmap_assure_buffer): Fix buffer-overwrite - bug (Savannah bug #19536). - -2007-04-04 Werner Lemberg - - - * Version 2.3.3 released. - ========================= - - - Tag sources with `VER-2-3-3'. - - * docs/CHANGES: Mention CVE-2007-1351. - -2007-04-03 David Turner - - * src/base/ftobjs.c (FT_Set_Char_Size): As suggested by James Cloos, - if one of the resolution values is 0, treat it as if it were the - same as the other value. - -2007-04-02 David Turner - - Add special code to detect `extra-light' fonts and do not snap their - stem widths too much to avoid bizarre hinting effects. - - * src/autofit/aflatin.h (AF_LatinAxisRec): Add `standard_width' and - `extra_light' members. - - * src/autofit/aflatin.c (af_latin_metrics_init_widths): Initialize - them. - (af_latin_metrics_scale_dim): Set `extra_light'. - (af_latin_compute_stem_width): Use `extra_light'. - -2007-03-28 David Turner - - * src/base/ftbitmap.c (ft_bitmap_assure_buffer): Fix zero-ing of the - padding. - -2007-03-28 Werner Lemberg - - * src/bdf/bdflib.c (setsbit, sbitset): Handle values >= 128 - gracefully. - (_bdf_set_default_spacing): Increase `name' buffer size to 256 and - issue an error for longer names. This fixes CVE-2007-1351. - (_bdf_parse_glyphs): Limit allowed number of glyphs in font to the - number of code points in Unicode. - - * builds/win32/visualc/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, README: s/2.3.2/2.3.3/, - s/232/233/. - - * docs/CHANGES: Mention ftdiff. - -2007-03-26 David Turner - - * src/truetype/ttinterp.c [FIX_BYTECODE]: Remove it and - corresponding code. - (Ins_MD): Last regression fix. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Fix blues - computations in order to ignore single-point contours. These are - never rasterized and correspond in certain fonts to mark-attach - points that are very far from the glyph's real outline, ruining the - computation. - - * src/autofit/afloader.c (af_loader_load_g): In the case of - monospaced fonts, always set `rsb_delta' and `lsb_delta' to 0. - Otherwise code that uses them will most certainly ruin the fixed - advance property. - - * docs/CHANGES, docs/VERSION.DLL, README, Jamfile (RefDoc): Update - documentation and bump version number to 2.3.3. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 3. - - * builds/unix/configure.raw (version_info): Set to 9:14:3. - -2007-03-26 suzuki toshiya - - * builds/unix/ftconfig.in: Disable Carbon framework dependency on - 64bit ABI on Mac OS X 10.4.x (ppc & i386). Found by Sean McBride. - * builds/vms/ftconfig.h: Ditto. - * include/freetype/config/ftconfig.h: Ditto. - -2007-03-22 suzuki toshiya - - * builds/unix/ftsystem.c (FT_Stream_Open): Temporary fix to prevent - 32bit unsigned long overflow by 64bit filesize on LP64 platform, as - proposed by Sean McBride: - https://lists.gnu.org/archive/html/freetype-devel/2007-03/msg00032.html - -2007-03-22 suzuki toshiya - - * builds/unix/ftconfig.in: Suppress SGI compiler's warning against - setjmp, proposed by Sean McBride: - https://lists.gnu.org/archive/html/freetype-devel/2007-03/msg00032.html - -2007-03-19 suzuki toshiya - - * builds/unix/configure.raw: Dequote `OS_INLINE' in comment of - conftest.c, to avoid unexpected shell evaluation. Possibly it is a - bug or undocumented behaviour of autoconf. - -2007-03-18 David Turner - - * src/truetype/ttinterp.c (Ins_MDRP): Another bytecode regression - fix; testing still needed. - - * src/truetype/ttinterp.c (Ins_MD): Another bytecode regression fix. - -2007-03-17 David Turner - - * src/truetype/ttinterp.c (Ins_IP): Fix wrong handling of the - (undocumented) twilight zone special case. - -2007-03-09 Werner Lemberg - - - * Version 2.3.2 released. - ========================= - - - Tag sources with `VER-2-3-2'. - - * builds/win32/visualc/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, README: s/2.3.1/2.3.2/, - s/231/232/. - -2007-03-08 David Turner - - * docs/CHANGES, docs/VERSION.DLL: Updated for upcoming release. - - * builds/unix/configure.raw (version_info): Set to 9:13:3. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 2. - - * README, Jamfile (RefDoc): s/2.3.1/2.3.2/. - - * src/base/ftutil.c (ft_mem_strcpyn): Fix a bug that prevented the - function to work properly, over-writing user-provided buffers in - some cases. Reported by James Cloos . - - -2007-03-05 Werner Lemberg - - * include/freetype/config/ftstdlib.h (ft_strstr): New wrapper - macro for `strstr'. - - * src/truetype/ttobjs.c (tt_face_init): Use ft_strstr for scanning - `trick_names', as suggested by Ivan Nincic. - -2007-03-05 David Turner - - * src/base/ftinit.c (FT_Init_FreeType): Fix a small memory leak in - case FT_Init_FreeType fails for some reason. Problem reported by - Maximilian Schwerin . - - * src/truetype/ttobjs.c (tt_size_init_bytecode): Clear the `x_ppem' - and `y_ppem' fields of the `TT_Size.metrics' structure, not those of - `TT_Size.root.metrics'. Problem reported by Daniel Glöckner - . - - * src/type1/t1afm.c (T1_Read_PFM): Read kerning values as 16-bit - signed values, not unsigned ones. Problem reported by Johannes - Walther . - -2007-02-21 David Turner - - * src/pshinter/pshalgo.c (psh_hint_align): Fix a bug in the hinting - of small and ghost stems in the Postscript interpreter. - -2007-02-20 suzuki toshiya - - * src/base/ftmac.c (FT_GetFileRef_From_Mac_ATS_Name): Fix memory - leak, patch by "Jjgod Jiang" . - * builds/mac/ftmac.c (FT_GetFileRef_From_Mac_ATS_Name): Ditto. - -2007-02-16 Werner Lemberg - - * src/truetype/ttinterp.c (Ins_MD): Remove unused variable. - * src/autofit/aflatin.c (af_latin_hints_link_segments): Ditto. - -2007-02-14 David Turner - - It seems that the following changes fix most of the known - interpreter problems with my fonts, but more testing is needed, - though. - - * src/truetype/ttinterp.c (FIX_BYTECODE): Activate. - (TT_MulFix14): Rewrite. - (Ins_MD, Ins_MDRP, Ins_IP) [FIX_BYTECODE]: Improved and updated. - (Ins_MIRP): Ditto. - -2007-02-12 Werner Lemberg - - * src/truetype/ttinterp.c (Project_x, Project_y): Remove compiler - warnings. - - * src/pcf/pcfread.c (pcf_interpret_style), src/bdf/bdfdrivr.c - (bdf_interpret_style): Ditto. - -2007-02-12 David Turner - - Simplify projection and dual-projection code interface. - - * src/truetype/ttinterp.h (TT_Project_Func): Use `FT_Pos', not - FT_Vector' as argument type. - * src/truetype/ttinterp.c (CUR_Func_project, CUR_Func_dualproj): - Updated. - (CUR_fast_project, CUR_fast_dualproj): New macros. - (Project, Dual_Project, Project_x, Project_y): Updated. - (Ins_GC, Ins_SCFS, Ins_MDAP, Ins_MIAP, Ins_IP): Use new `fast' - macros. - - - * src/autofit/afloader.c (af_loader_load_g): Improve spacing - adjustments for the non-light auto-hinted modes. Gets rid of - `inter-letter spacing is too wide' problems. - - * src/autofit/aflatin.c (af_latin_hints_link_segments, - af_latin_hints_compute_edges): Slight optimization of the segment - linker and better handling of serif segments to get rid of broken - `9' in Arial at 9pt (96dpi). - - - Introduce new string functions and the corresponding macros to get - rid of various uses of strcpy and other `evil' functions, as well as - to simplify a few things. - - * include/freetype/internal/ftmemory.h (ft_mem_strdup, ft_mem_dup, - ft_mem_strcpyn): New declarations. - (FT_MEM_STRDUP, FT_STRDUP, FT_MEM_DUP, FT_DUP, FT_STRCPYN): New - macros. - * src/base/ftutil.c (ft_mem_dup, ft_mem_strdup, ft_mem_strcpyn): New - functions. - - * src/bdf/bdfdrivr.c (bdf_interpret_style, BDF_Face_Init), - src/bdf/bdflib.c (_bdf_add_property), src/pcf/pcfread.c - (pcf_get_properties, pcf_interpret_style, pcf_load_font), - src/cff/cffdrivr.c (cff_get_glyph_name), src/cff/cffload.c - (cff_index_get_sid_string), src/cff/cffobjs.c (cff_strcpy), - src/sfnt/sfdriver.c (sfnt_get_glyph_name), src/type1/t1driver.c - (t1_get_glyph_name), src/type42/t42drivr.c (t42_get_glyph_name, - t42_get_name_index): Use new functions and simplify code. - - * builds/mac/ftmac.c (FT_FSPathMakeSpec): Don't use FT_MIN. - -2007-02-11 Werner Lemberg - - * src/autofit/afloader.c (af_loader_load_g): Don't change width for - non-spacing glyphs. - -2007-02-07 Tom Parker - - * src/cff/cffdrivr.c (cff_get_name_index): Protect against NULL - pointer. - -2007-02-05 suzuki toshiya - - * include/freetype/ftmac.h (FT_DEPRECATED_ATTRIBUTE): - Introduce __attribute((deprecated))__ to warn functions - which use non-ANSI data types in its interfaces. - (FT_GetFile_From_Mac_Name): Deprecated, using FSSpec. - (FT_GetFile_From_Mac_ATS_Name): Deprecated, using FSSpec. - (FT_New_Face_From_FSSpec): Deprecated, using FSSpec. - (FT_New_Face_From_FSRef): Deprecated, using FSRef. - - * src/base/ftmac.c: Predefine FT_DEPRECATED_ATTRIBUTE as void - to avoid warning in building FreeType. - * builds/mac/ftmac.c: Ditto. - -2007-02-05 suzuki toshiya - - * src/base/ftbase.c: Fix to use builds/mac/ftmac.c, if configured - `--with-fsspec' etc. Replace #include "ftmac.c" with - #include . - -2007-02-05 suzuki toshiya - - * include/freetype/ftmac.h (FT_GetFilePath_From_Mac_ATS_Name): - Introduced as replacement of FT_GetFile_From_Mac_ATS_Name. - * src/base/ftmac.c (FT_GetFilePath_From_Mac_ATS_Name): Ditto. - (FT_GetFile_From_Mac_ATS_Name): Rewritten as wrapper of - FT_GetFilePath_From_Mac_ATS_Name. - * builds/mac/ftmac.c: Ditto. - -2007-02-05 suzuki toshiya - - * include/freetype/ftmac.h: Fixed wrong comment: FSSpec of - FT_GetFile_From_Mac_Name, FT_GetFile_From_Mac_ATS_Name are - for passing to FT_New_Face_From_FSSpec. - -2007-02-05 suzuki toshiya - - * builds/unix/configure.raw: Check whether Mac OS X system headers - can be built under ANSI C mode. - - * src/base/ftmac.c (OS_INLINE): Redefine OS_INLINE by a version - compatible to ANSI C in case system headers are ANSI C incompatible. - * builds/mac/ftmac.c (OS_INLINE): Ditto. - -2007-02-01 Werner Lemberg - - * include/freetype/ttnameid.h (TT_MS_LANGID_DZONGHKA_BHUTAN): - Explain why applications shouldn't use it. Found by Alexei. - -2007-02-01 Alexei Podtelezhnikov - - * builds/unix/freetype2.m4 (AC_CHECK_FT2): Fix spelling of warning - message. - - * src/gxvalid/gxvmort1.c - (gxv_mort_subtable_type1_substTable_validate): Fix debugging - message. - -2007-01-31 Werner Lemberg - - - * Version 2.3.1 released. - ========================= - - - Tag sources with `VER-2-3-1-FINAL'. - - * builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj: s/230/231/. - * builds/win32/visualc/index.html: s/221/231/. - - * vms_make.com: Add `ftgasp'. - -2007-01-30 David Turner - - Tag sources with VER-2-3-1 to prepare release. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 1. - - * docs/VERSION.DLL, docs/release, README, Jamfile (RefDoc): - s/2.3.0/2.3.1/. - - * builds/unix/configure.raw (version_info): Set to 9:12:3. - - - * src/autofit/aftypes.h (AF_USE_WARPER), src/autofit/afloader.c - (af_loader_load_g): Disable the warper (i.e., the light hinting - improvements) to make a 2.3.1 bugfix release before introducing a - new feature. This should give us more time to tune and improve the - warper for the next release. - - * docs/CHANGES: Update accordingly. - -2007-01-25 David Turner - - For light auto-hinting, improve glyph advance widths and resurrect - normal/full hinting to its normal quality. - - * src/autofit/afhints.h (AF_GlyphHintsRec): New members `xmin_delta' - and `xmax_delta'. - * src/autofit/afhints.c (af_glyph_hints_reload): Reset `xmin_delta' - and `xmax_delta'. - - * src/autofit/afloader.c (af_loader_load_g) : Replace - preprocessor conditional with if-clause, handling both light and - normal mode. - - * src/autofit/afwarp.c (AF_WarpScore): Fine-tune again. - (af_warper_compute): Handle `xmin_delta' and `xmax_delta'. - -2007-01-25 Werner Lemberg - - * docs/release: Updated -- Savannah uses a new uploading scheme. - -2007-01-25 David Turner - - * src/cff/cffload.c (cff_index_get_pointers): Improve previous fix. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings) - : Fix sanity check for empty - functions. - - * docs/CHANGES: Document light auto-hinting improvement. - -2007-01-25 Werner Lemberg - - * src/cff/cffload.c (cff_index_get_pointers): Handle last entry - correctly in a sanity check. Since this function is only used to - load local and global functions, any charstring that called the last - local/global function would fail otherwise. This fixes Savannah bug - #18867. - - * docs/CHANGES: Document it. - -2007-01-23 David Turner - - * src/truetype/ttobjs.c (tt_size_ready_bytecode): Fix typo that - prevented compilation when disabling both the unpatented and the - bytecode interpreter in the TrueType font driver. - - - Fix and enable the warper to improve `light' hinting mode. This is - not necessarily a final version, but it seems to work well. - - * src/autofit/aflatin.c (af_latin_hints_init) [AF_USE_WARPER]: - Disable code. - (af_latin_hints_apply) [AF_USE_WARPER]: Handle FT_RENDER_MODE_LIGHT. - * src/autofit/aftypes.h: Activate AF_USE_WARPER. - - * src/autofit/afwarp.c (AF_WarpScore): Tune table. - (af_warper_compute_line_best): Fix array size of `scores'. - (af_warper_compute): Better handling of border cases. - * src/autofit/afwarp.h (AF_WarperRec): Remove unused members `X1' - and `X2'. - -2007-01-21 Werner Lemberg - - * ChangeLog: Split off older entries into... - * ChangeLog.22: This new file. - -2007-01-21 Werner Lemberg - - * docs/CHANGES: Document SHZ fix. - -2007-01-21 George Williams - - * src/truetype/ttinterp.c (Ins_SHZ): SHZ doesn't move phantom - points. - -2007-01-21 Werner Lemberg - - * src/sfnt/ttmtx.c (tt_face_get_metrics) - [!FT_CONFIG_OPTION_OLD_INTERNALS]: Fix limit check. - -2007-01-17 Werner Lemberg - - - * Version 2.3.0 released. - ========================= - - - Tag sources with `VER-2-3-0-FINAL'. - -2007-01-17 Werner Lemberg - - * docs/release: Updated. - -2007-01-16 David Turner - - * src/autofit/aflatin.c (af_latin_hints_compute_segments), - src/cff/cffdrivr.c (cff_ps_get_font_info), src/truetype/ttobjs.c - (tt_face_init), src/truetype/ttinterp.c (Ins_SHC): Fix compiler - warnings. - -2007-01-15 Detlef Würkner - - * builds/amiga/makefile, builds/amiga/makefile.os4, - builds/amiga/smakefile: Add `ftgasp.c' and `ftlcdfil.c'. - - * builds/amiga/include/freetype/config/ftconfig.h: Synchronize. - -2007-01-14 Detlef Würkner - - Fix various compiler warnings. - - * src/truetype/ttdriver.c (tt_size_select), src/cff/cffobjs.h, - src/cff/cffobjs.c (cff_size_request), src/type42/t42objs.h: - s/index/strike_index/. - * src/base/ftobjs.c (FT_Match_Size): s/index/size_index/. - - * src/gxvalid/gxvmorx5.c - (gxv_morx_subtable_type5_InsertList_validate): s/index/table_index/. - - * src/truetype/ttinterp.c (Compute_Point_Displacement), - src/pcf/pcfread.c (pcf_seek_to_table_type): Avoid possibly - uninitialized variables. - -2007-01-13 suzuki toshiya - - * docs/CHANGES, docs/INSTALL.MAC: Improvements. - -2007-01-13 Werner Lemberg - - * src/type1/t1afm.c (T1_Read_Metrics): MS Windows allows PFM - versions up to 0x3FF without complaining. - -2007-01-13 Derek Clegg - - Add FT_Get_PS_Font_Info interface to CFF driver. - - * src/cff/cfftypes.h: Include FT_TYPE1_TABLES_H. - (CFF_FontRec): Add `font_info' field. - - * src/cff/cffload.c: Include FT_TYPE1_TABLES_H. - (cff_font_done): Free font->font_info if necessary. - - * src/cff/cffdrivr.c (cff_ps_get_font_info): New function. - (cff_service_ps_info): Register cff_ps_get_font_info. - -2007-01-13 Werner Lemberg - - * src/base/ftoutln.c (FT_Outline_Get_Orientation): Fix compilation - with C++ compiler. - - * src/autofit/afhints.c (af_glyph_hints_dump_segments, - af_glyph_hints_dump_edges): Ditto. - - * src/base/rules.mk (BASE_SRC): Remove ftgasp.c (it's already in - `modules.cfg'). - - * src/sfnt/ttsbit0.h: Remove. - - * src/sfnt/rules.mk (SFNT_DRV_SRC): Don't include ttsbit0.c. - -2007-01-12 David Turner - - * src/base/ftbitmap.c (ft_bitmap_assure_buffer): Fix memory stomping - bug in the bitmap emboldener if the pitch of the source bitmap is - much larger than its width. - - * src/truetype/ttinterp.c (Update_Max): Fix aliasing-related - compilation warning. - -2007-01-12 Werner Lemberg - - * builds/unix/install-sh, builds/unix/mkinstalldirs: Updated from - `automake' CVS module from sources.redhat.com. - -2007-01-11 Werner Lemberg - - * src/type1/t1load.c (is_space): Removed. - (parse_encoding, parse_charstrings): Use IS_PS_DELIM. - (parse_charstrings): Use IS_PS_TOKEN. - - - * autogen.sh: Avoid bash specific syntax. - -2007-01-11 David Turner - - * docs/CHANGES: Small update. - - * builds/unix/configure.raw (version_info): Set to 9:11:3. - - * src/base/ftobjs.c (IsMacResource): Fix a small bug that caused a - crash with some Mac OS X .dfont files. Submitted by Masatake - Yamato. - - * autogen.sh: Small fix to get it working on Mac OS X properly: - The issue is that GNU libtool is called `glibtool' on this platform, - and we must call `glibtoolize', since `libtoolize' doesn't exist. - -2007-01-10 David Turner - - * all-sources: Tag all sources with VER-2-3-0-RC1 and - VER-2-3-0. - - * Jamfile (RefDoc), README, builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, docs/VERSION.DLL: Update - version number to 2.3.0. - - * include/freetype/freetype.h (FREETYPE_MINOR): Set to 3. - (FREETYPE_PATCH): Set to 0. - - * include/freetype/ftchapters.h, include/freetype/ftgasp.h, - include/freetype/ftlcdfil.h: Update reference documentation with - GASP support and LCD filtering sections. - - * src/pshinter/pshalgo.c (psh_glyph_compute_inflections): Fix a typo - which created an endless loop with some malformed font files. - -2007-01-10 Derek Clegg - - * src/type1/t1load.c (T1_Get_MM_Var): Always return fixed-point - values. - -2007-01-08 David Turner - - * docs/CHANGES: Updated. - - * include/freetype/ftgasp.h, src/base/ftgasp.c: New files which add - a new API `FT_Get_Gasp' to return entries of the `gasp' table - corresponding to a given character pixel size. - - * src/sfnt/ttload.c (tt_face_load_gasp): Add version check for the - `gasp' table, in order to avoid potential problems with later - versions. - - * include/freetype/config/ftheader.h (FT_GASP_H): New macro for - . - - * src/base/rules.mk (BASE_SRC), src/base/Jamfile (_sources), - modules.cfg (BASE_EXTENSIONS), builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj: Add src/base/ftgasp.c to the - default build. - -2007-01-07 Werner Lemberg - - * src/cid/cidparse.c (cid_parser_new): Improve error message for - Type 11 fonts. - Scan for `/sfnts' token. - -2007-01-07 Werner Lemberg - - * src/cid/cidparse.c (cid_parser_new): Reject Type 11 fonts. - -2007-01-06 Werner Lemberg - - * src/cff/cffload.c (cff_index_init): Remove unused variable. - (cff_index_read_offset): s/perror/errorp/ to avoid global shadowing. - -2007-01-04 David Turner - - * src/pfr/pfrobjs.c (pfr_face_init): Detect non-scalable fonts - correctly. This fixes Savannah bug #17876. - - - Do not allocate interpreter-specific tables in memory if we are not - going to load glyphs with the bytecode interpreter anyway. - - * src/truetype/ttgload.c (tt_loader_init): Load execution context - only if glyph is hinted. - Updated. - * src/truetype/ttobjs.h (TT_SizeRec): Add members `bytecode_ready' - and `cvs_ready'. - Add `tt_size_ready_bytecode' declaration. - * src/truetype/ttobjs.c (tt_size_done_bytecode, - tt_size_init_bytecode, tt_size_ready_bytecode): New functions. - (tt_size_init): Move most code into `tt_size_init_bytecode'. - (tt_size_done): Move most code into `tt_size_done_bytecode'. - (tt_size_reset): Move some code to `tt_size_ready_bytecode'. - - - Don't extract the metrics table from the SFNT font file. Instead, - reparse it on each glyph load. The runtime difference is not - noticeable, and it can save a lot of heap memory when memory-mapped - files are not used. - - * include/freetype/internal/tttypes.h (TT_FaceRec): Add members - `horz_metrics_offset' and `vert_metrics_offset'. - * src/sfnt/ttmtx.c (tt_face_load_hmtx, tt_face_get_metrics): - Updated. - - - * src/sfnt/ttcmap.c (tt_cmap4_validate): Slight optimization. - - - Do not load the CFF index offsets into memory, since this wastes a - *lot* of heap memory with large Asian CFF fonts. There is no - significant performance loss. - - * src/cff/cffload.h: Add `cff_charset_cid_to_gindex' declaration. - * src/cff/cfftypes.h (CFF_IndexRec): Add fields `start' and - `data_size'. - (CFF_CharsetRec): Add field `num_glyphs'. - - * src/cff/cffload.c (cff_index_read_offset, cff_index_load_offsets, - cff_charset_cid_to_gindex): New functions. - (cff_new_index): Renamed to... - (cff_index_init): This. Update all callers. - Updated -- some code has been moved to `cff_index_load_offsets'. - (cff_done_index): Renamed to... - (cff_index_done): This. Update all callers. - (cff_index_get_pointers, cff_index_access_element): Updated to use - stream offsets. - (cff_charset_compute_cids): Set `num_glyphs' field. - (cff_encoding_load): Updated. - - * src/cff/cffgload.c (cff_slot_load): Updated. - -2007-01-04 David Turner - - * docs/INSTALL.UNIX: Simplify some parts, add reference to - autogen.sh and pointer to README.CVS. - - * README.CVS: Add common problem description and solution - when running autogen.sh. - - * docs/INSTALL: Add reference to MacOS X. - - * docs/MAKEPP, docs/INSTALL.MAC: New documentation files. - - * docs/TODO: Remove obsolete items. - - * src/raster/ftraster.c: (TRaster_Instance): Replace it with... - (TWorker): This. - Remove `count_table' and `memory'. - Make `grays' a pointer. - (TRaster): New structure. - (count_table): New static array. - (RAS_ARGS, RAS_ARG, RAS_VARS, RAS_VAR, FT_UNUSED_RASTER, cur_ras, - Vertical_Gray_Sweep_Step, ft_black_new, ft_black_done, - ft_black_set_mode, ft_black_render): Updated. - (ft_black_init): Don't initialize `count_table'. - (ft_black_reset): Use the render pool. This saves about 6KB of - heap space for each FT_Library instance. - - * src/smooth/ftgrays.c (TRaster): Replaced with... - (TWorker): This. - Remove `memory'. - (TRaster): New structure. - - (RAS_ARG_, RAS_ARG, RAS_VAR_, RAS_VAR, ras, gray_render_line, - gray_move_to, gray_line_to, gray_conic_to, gray_cubic_to, - gray_render_span, gray_raster_render): Updated. - (gray_raster_reset): Use the render pool. This saves about 6KB of - heap space for each FT_Library instance. - - * src/sfnt/sfobjs.c, src/sfnt/ttkern.c, src/sfnt/ttkern.h, - src/sfnt/ttmtx.c, src/sfnt/ttsbit.c, src/sfnt/ttsbit.h, - src/truetype/ttpload.c, include/freetype/config/ftoption.h: Remove - FT_OPTIMIZE_MEMORY macro (and code for !FT_OPTIMIZE_MEMORY) since - the optimization is no longer experimental. - - * src/pshinter/pshalgo.c (psh_glyph_interpolate_normal_points): - Remove a typo that results in no hinting and a memory leak with some - large Asian CFF fonts. - - * src/base/ftobjs.c (FT_Done_Library): Remove a subtle memory leak - which happens when FT_Done_Library is called with still opened - CFF_Faces in it. We need to close all faces before destroying the - modules, or else some bad things (memory leaks) may happen. - -2007-01-02 Werner Lemberg - - * src/gxvalid/gxvkern.c (gxv_kern_subtable_fmt0_pairs_validate): - Remove compiler warning. - -2007-01-02 David Turner - - * src/sfnt/sfobjs.c: Add documentation comment. - -2006-12-31 Masatake YAMATO - - * src/gxvalid/gxvkern.c (gxv_kern_subtable_fmt0_pairs_validate): New - function. - Check uniqueness of the gid pairs. - (gxv_kern_subtable_fmt0_validate): Move some code to - `gxv_kern_subtable_fmt0_pairs_validate'. - -2006-12-22 David Turner - - * src/autofit/aflatin.c, src/truetype/ttgload.c: Remove compiler - warnings. - - * builds/win32/visualc/freetype.vcproj: Add _CRT_SECURE_NO_DEPRECATE - to avoid deprecation warnings with Visual C++ 8. - -2006-12-16 Anders Kaseorg - - * src/base/ftlcdfil.c (FT_Library_SetLcdFilter) - [FT_FORCE_LIGHT_LCD_FILTER]: Fix typo. - -2006-12-15 suzuki toshiya - - * include/freetype/internal/services/svotval.h: Add `volatile' to - sync with the modification by Jens Claudius on 2006-08-22; cf. - https://cvs.savannah.gnu.org/viewcvs/freetype/freetype2/src/otvalid/otvmod.c?r1=1.4&r2=1.5 - -2006-12-15 suzuki toshiya - - * src/base/ftmac.c: Specialized for Mac OS X only. - * builds/unix/ftconfig.in: Fixed for ppc64 missing Carbon framework. - * builds/unix/configure.raw: Ditto. When explicit switches for - FSSpec/FSRef/QuickDraw/ATS availability are given to configure, - builds/mac/ftmac.c is used instead of default src/base/ftmac.c. - -2006-12-15 suzuki toshiya - - * builds/mac/ftmac.c: Copied src/base/ftmac.c for legacy system. - * builds/mac/FreeType.m68k_cfm.make.txt: Fix to use builds/mac/ftmac.c - instead of src/base/ftmac.c - * builds/mac/FreeType.ppc_carbon.make.txt: Ditto. - * builds/mac/FreeType.ppc_classic.make.txt: Ditto. - * builds/mac/FreeType.m68k_far.make.txt: Ditto, and exclude gxvalid.c - that cannot be built at present. - -2006-12-15 suzuki toshiya - - * src/base/ftobjs.c: Improvement of resource fork handler for - POSIX, cf. - https://lists.gnu.org/archive/html/freetype-devel/2006-10/msg00025.html - (Mac_Read_sfnt_Resource): Count only `sfnt' resource of suitcase font - format or .dfont, to simulate the face index number counted by ftmac.c. - (IsMacResource): Return the number of scalable faces correctly. - -2006-12-10 Werner Lemberg - - * builds/toplevel.mk (version): Protect against `distclean' target. - -2006-12-09 Werner Lemberg - - * builds/*/*def.mk, builds/*/detect.mk (CAT): Define to either `cat' - or `type'. - - * builds/freetype.mk (version): Extracted from freetype.h, using - GNU make's built-in string functions. - (refdoc): Use $(version) instead of static version number. - -2006-12-08 Werner Lemberg - - * builds/toplevel.mk (dist): Extract version number from freetype.h. - -2006-12-08 Vladimir Volovich - - * src/tools/apinames.c (State): Remove final comma in structure -- - xlc v5 under AIX 4.3 doesn't like this. - -2006-12-07 David Turner - - * src/autofit/afloader.c (af_loader_load_g): Small adjustment - to the spacing of auto-fitted glyphs. This only impacts rare - cases (e.g., Arial Bold at rather small character sizes). - -2006-12-03 Werner Lemberg - - * src/sfnt/rules.mk (SFNT_DRV_SRC): Add ttsbit0.c. - -2006-12-01 Werner Lemberg - - * src/sfnt/sfobjs.c (tt_face_get_name): All Unicode strings are - encoded in UTF-16BE. Patch from Rajeev Pahuja . - (tt_name_entry_ascii_from_ucs4): Removed. - - - * include/freetype/ftxf86.h: Fix and extend comment so that it - appears in the documentation. - - * include/freetype/ftchapters.h: Add `font_format' section. - - - * src/tools/docmaker/tohtml.py (HtmlFormatter::index_exit): Add link - to TOC in index page. - -2006-11-28 David Turner - - * src/smooth/ftgrays.c (gray_raster_render): Return 0 when we are - trying to render into a zero-width/height bitmap, not an error code. - - * src/truetype/ttobjs.c (tt_face_init): Fix typo in previous patch. - - * src/smooth/ftgrays.c: Remove hard-coded error values; use FreeType - ones instead. - - * src/autofit/afhints.c (af_glyph_hints_dump_segments): Remove unused - variable. - -2006-11-26 Pierre Hanser - - * src/truetype/ttobjs.c (tt_face_init): Protect against NULL pointer. - -2006-11-25 David Turner - - * src/autofit/afhints.c (af_glyph_hints_dump_points, - af_glyph_hints_dump_segments, af_glyph_hints_dumpedges) [!AF_DEBUG]: - Add stubs to link the `ftgrid' test program when debugging is - disabled in the auto-hinter. - -2006-11-23 David Turner - - * src/autofit/afhints.c, src/autofit/afhints.h, src/autofit/aflatin.c, - src/autofit/aftypes.h: Miscellaneous auto-hinter improvements. - - * src/autofit/afhints.c (af_glyph_hints_dump_segments) [AF_DEBUG]: - Emit more sensible information. - - * src/autofit/afhints.h (AF_SegmentRec): Add `height' member. - - * src/autofit/aflatin.c (af_latin_metrics_scale_dim): Improve - rounding of blue values. - (af_latin_hints_compute_segments): Hint segment heights. - (af_latin_hints_link_segments): Reduce `len_score' value. - (af_latin_hints_compute_edges): Increase `segment_length_threshold' - value and use `height' member for comparisons. - (af_latin_hint_edges): Extend logging message. - Improve handling of remaining edges. - -2006-11-22 Werner Lemberg - - Fix Savannah bug #15553. - - * src/truetype/ttgload.c (tt_loader_init): Re-execute the CVT - program after a change from mono to grayscaling (and vice versa). - Use correct constant for comparison to get `exec->grayscale'. - -2006-11-18 Werner Lemberg - - Because FT_Load_Glyph expects CID values for CID-keyed fonts, the - test for a valid glyph index must be deferred to the font drivers. - This patch fixes Savannah bug #18301. - - * src/base/ftobjs.c (FT_Load_Glyph): Don't check `glyph_index'. - * src/bdf/bdfdrivr.c (BDF_Glyph_Load), src/cff/cffgload.c - (cff_slot_load), src/cid/cidgload.c (cid_slot_load_glyph), - src/pcf/pcfdrivr.c (PCF_Glyph_Load), src/pfr/pfrobjs.c - (pfr_slot_load), src/truetype/ttdriver.c (Load_Glyph), - src/type1/t1gload.c (T1_Load_Glyph), src/winfonts/winfnt.c - (FNT_Load_Glyph): Check validity of `glyph_index'. - -2006-11-13 David Turner - - * src/truetype/ttinterp.c (FIX_BYTECODE): Undefine. The interpreter - `enhancements' are still too buggy for general use. - - * src/base/ftlcdfil.c: Add support for FT_FORCE_LIGHT_LCD_FILTER and - FT_FORCE_LEGACY_LCD_FILTER at compile time. Define these macros - when building the library to change the default LCD filter to be - used. This is only useful for experimentation. - - * include/freetype/ftlcdfil.h: Update documentation. - -2006-11-10 David Turner - - * src/smooth/ftsmooth.c: API change for the LCD - filter. The FT_LcdFilter value is an enumeration describing which - filter to apply, with new values FT_LCD_FILTER_LIGHT and - FT_LCD_FILTER_LEGACY (the latter implements the LibXft original - algorithm which produces strong color fringes for everything - except very-well hinted text). - - * include/freetype/ftlcdfil.h (FT_Library_SetLcdFilter): Change - second parameter to an enum type. - - * src/base/ftlcdfil.c (USE_LEGACY): Define. - (_ft_lcd_filter): Rename to... - (_ft_lcd_filter_fir): This. - Update parameters. - (_ft_lcd_filter_legacy) [USE_LEGACY]: New filter function. - (FT_Library_SetLcdFilter): Update parameters. - Handle new filter modes. - - * include/internal/ftobjs.h: Include FT_LCD_FILTER_H. - (FT_Bitmap_LcdFilterFunc): Change third argument to `FT_Library'. - (FT_LibraryRec) [FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Add filtering - callback and update other fields. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic) - [FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Update. - Other minor improvements. - - * src/autofit/aflatin.c: Various tiny improvements that drastically - improve the handling of serif fonts and of LCD/LCD_V hinting modes. - (af_latin_hints_compute_edges): Fix typo. - (af_latin_compute_stem_width): Take better care of diagonal stems. - -2006-11-09 David Turner - - * src/pshinter/pshalgo.c (psh_glyph_compute_inflections): Fix - typo which created a variable-used-before-initialized bug. - -2006-11-07 Zhe Su - - * src/base/ftsynth.c (FT_GlyphSlot_Embolden): Handle vertical layout - also. - -2006-11-03 Werner Lemberg - - * src/base/ftcalc.c: Don't use `long long' but `FT_Int64'. - -2006-11-02 David Turner - - Add a few tweaks to better handle serif fonts. - Add more debugging messages. - - * src/autofit/aflatin.c (af_latin_hints_compute_edges): Ignore - segments that are less than 1.5 pixels high. This gets rid of - *many* corner cases with serifs. - (af_latin_align_linked_edge): Add logging message. - (af_latin_hint_edges): Use AF_HINTS_DO_BLUES. - Add logging messages. - Handle AF_EDGE_FLAG flag specially. - - * src/autofit/afmodule.c [AF_DEBUG]: Add _af_debug, - _af_debug_disable_blue_hints, and _af_debug_hints variables. - - * src/autofit/aftypes.h (AF_LOG) [AF_DEBUG]: Use _af_debug. - Update external declarations. - (af_corner_orientation, af_corner_is_flat): Replaced by... - - * include/freetype/internal/ftcalc.h (ft_corner_orientation, - ft_corner_is_flat): These declarations. - - * src/autofit/afangles.c (af_corner_orientation, af_corner_is_flat): - Comment out. Replaced by... - - * src/base/ftcalc.h (ft_corner_orientation, ft_corner_is_flat): - These functions. Update all callers. - (FT_Add64) [!FT_LONG64]: Simplify. - - * src/autofit/afhints.c: Include FT_INTERNAL_CALC_H. - (af_direction_compute): Add a missing FT_ABS call. This bug caused - production of garbage by missing lots of segments. - - * src/autofit/afhints.h (AF_HINTS_DO_BLUES): New macro. - - * src/autofit/afloader.c (af_loader_init, af_loader_done) - [AF_DEBUG]: Set _af_debug_hints. - - - * src/pshinter/pshalgo.c: Include FT_INTERNAL_CALC_H. - (psh_corner_is_flat, psh_corner_orientation): Use ft_corner_is_flat - and ft_corner_orientation. - - - * src/gzip/inftrees.c (huft_build): Remove compiler warning. - -2006-10-24 Werner Lemberg - - * src/cff/cffload.c (cff_encoding_load): Remove unused variable. - - * src/base/ftobjs.c (FT_Select_Charmap): Disallow FT_ENCODING_NONE - as argument. - -2006-10-23 Zhe Su - - * src/base/ftoutln.c (FT_Outline_Get_Orientation): Re-implement to - better deal with broken Asian fonts with strange glyphs, having - self-intersections and other peculiarities. The used algorithm is - based on the nonzero winding rule. - -2006-10-23 David Turner - - Speed up the CFF font loader. With some large CFF fonts, - FT_Open_Face is now more than three times faster. - - * src/cff/cffload.c (cff_get_offset): Removed. - (cff_new_index): Inline functionality of `cff_get_offset'. - (cff_charset_compute_cids, cff_charset_free_cids): New functions. - (cff_charset_done): Call `cff_charset_free_cids'. - (cff_charset_load): Call `cff_charset_compute_cids'. - (cff_encoding_load) : Ditto, to replace inefficient loop. - - * src/sfnt/ttmtx.c (tt_face_load_hmtx): Replace calls to FT_GET_XXX - with FT_NEXT_XXX. - - - Speed up the Postscript hinter, with more than 100% speed increase - on my machine. - - * src/pshinter/pshalgo.c (psh_corner_is_flat, - psh_corner_orientation): New functions. - (psh_glyph_compute_inflections): Merge loops for efficiency. - Use `psh_corner_orientation'. - (psh_glyph_init): Use `psh_corner_is_flat'. - (psh_hint_table_find_strong_point): Renamed to... - (psh_hint_table_find_strong_points): This. - Rewrite, adding argument to handle all points at once. - Update all callers. - (PSH_MAX_STRONG_INTERNAL): New macro. - (psh_glyph_interpolate_normal_points): Rewrite for efficiency. - -2006-10-15 suzuki toshiya - - * src/base/ftmac.c (FT_New_Face_From_FOND): Initialize variable - `error' with FT_Err_Ok. - -2006-10-14 suzuki toshiya - - * docs/INSTALL.CROSS: New document file for cross-building. - - * builds/unix/configure.raw: Preliminary cross-building support. - Find native C compiler and pass it by CC_BUILD, and - find suffix for native executable and pass it by EXEEXT_BUILD. - Also suffix for target executable is passed by EXEEXT. - - * builds/unix/unix-cc.in (CCraw_build, E_BUILD): New variables to - build `apinames' which runs on building system. They are set by - CC_BUILD and EXEEXT_BUILD. - - * builds/exports.mk (APINAMES_EXE): Change the extension for - apinames from the suffix for target (E) to that for building host - (E_BUILD). - -2006-10-12 Werner Lemberg - - * docs/INSTALL.UNX, docs/UPGRADE.UNX: Renamed to... - * docs/INSTALL.UNIX, docs/UPGRADE.UNIX: This. Update all documents - which reference those files. - -2006-10-12 suzuki toshiya - - * builds/unix/configure.raw (FT2_EXTRA_LIBS): New variable. It is - embedded in freetype2.pc and freetype-config. Use it to record - Carbon dependency of MacOSX. - - * builds/unix/freetype2.in: Embed FT2_EXTRA_LIBS. - - * builds/unix/freetype-config.in: Ditto. - -2006-10-11 Werner Lemberg - - * devel/ftoption.h (FT_CONFIG_OPTION_SUBPIXEL_RENDERING): Define for - development. - -2006-10-03 Jens Claudius - - * include/freetype/config/ftstdlib.h: Cast away volatileness from - argument to ft_setjmp. - - * include/freetype/internal/ftvalid.h: Add comment that - ft_validator_run must not be used. - -2006-10-01 Werner Lemberg - - * src/base/ftbase.c: Undo change from 2006-09-30. - - * src/base/rules.mk (BASE_SRC): Remove `ftlcdfil.c'. - -2006-09-30 David Turner - - * include/freetype/internal/ftobjs.h (FT_Face_InternalRec): - s/unpatented_hinting/ignore_unpatented_hinter/. - Update all callers. - - * src/base/ftobjs.c (FT_Load_Glyph): Refine the algorithm whether - auto-hinting shall be used or not. - - * src/truetype/ttobjs.c (tt_face_init): Ditto. - -2006-09-30 Werner Lemberg - - * src/base/rules.mk (BASE_SRC): Remove `ftapi.c' (which is no longer - in use). - - * src/base/ftbase.c: Include `ftlcdfil.c'. - -2006-09-29 Werner Lemberg - - * src/sfnt/ttcmap.c (tt_cmap4_char_map_binary): Fix algorithm for - overlapping segments. Bug reported by Stefan Koch. - -2006-09-28 David Turner - - Fix a bug in the automatic unpatented hinting support which prevents - normal bytecode hinting to work properly. - - * include/freetype/internal/ftobjs.h (FT_Face_InternalRec): - s/force_autohint/unpatented_hinting/. Update all callers. - - * src/base/ftobjs.c (FT_Load_Glyph): Updated code. - - * src/autofit/aftypes.h (AF_DEBUG): Undefine to get rid of traces. - -2006-09-27 David Turner - - * include/freetype/freetype.h (FT_FREETYPE_PATCH): Set to 2. - - - Add a new API to support color filtering of subpixel glyph bitmaps. - In a default build, the function `FT_Library_SetLcdFilter' returns - `FT_Err_Unimplemented_Feature'; you need to #define - FT_CONFIG_OPTION_SUBPIXEL_RENDERING in ftoption.h to compile the - real implementation. - - * include/freetype/ftlcdfil.h, src/base/ftlcdfil.c: New files. - - * include/freetype/internal/ftobjs.h (FT_Bitmap_LcdFilterFunc): New - typedef. - (FT_LibraryRec) [FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: New members - `lcd_filter_weights' and `lcd_filter'. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Remove arguments - `hmul' and `vmul'. - - Handle subpixel rendering. - Simplify function. - (ft_smooth_render_lcd): Use `FT_RENDER_MODE_LCD'. - (ft_smooth_render_lcd_v): Use `FT_RENDER_MODE_LCD_V'. - - * include/freetype/config/ftheader.h (FT_LCD_FILTER_H): New macro, - pointing to . - - * src/base/Jamfile (_sources), src/base/rules.mk (BASE_SRC), - vms_make.com: Add `ftlcdfil.c' to the list of compiled source files. - - * modules.cfg (BASE_EXTENSIONS): Add ftlcdfil.c. - -2006-09-26 David Bustin - - * src/pfr/pfrobjs.c (pfr_face_get_kerning): Skip adjustment bytes - correctly. Reported as Savannah bug #17843. - -2006-09-26 David Turner - - * src/autofit/afhints.h (AF_HINTS_DO_HORIZONTAL, - AF_HINTS_DO_VERTICAL, AF_HINTS_DO_ADVANCE): New macros to disable - horizontal and vertical hinting for the purpose of debugging the - auto-fitter. - - * src/autofit/afmodule.c (_af_debug_disable_horz_hints, - _af_debug_disable_vert_hints) [AF_DEBUG]: New global variables. - - * src/autofit/aftypes.h [AF_DEBUG]: Declare above variables. - - * include/freetype/config/ftoption.h, devel/ftoption.h - (FT_CONFIG_OPTION_SUBPIXEL_RENDERING): New macro to control whether - we want to compile LCD-optimized rendering code (à la ClearType) or - not. The macro *must* be disabled in default builds of the library - for patent reasons. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Disable - LCD-specific rendering when FT_CONFIG_OPTION_SUBPIXEL_RENDERING - isn't defined at compile time. This only changes the content of the - rendered glyph to match the one of normal gray-level rendering, - hence clients should not need to be modified. - - * docs/CHANGES: Updated. - -2006-09-18 Garrick Meeker - - * src/base/ftmac.c (FT_New_Face_From_FOND): Fall back to SFNT if - LWFN fails and both are available. - -2006-09-11 David Turner - - * src/sfnt/sfobjs.c (tt_face_get_name): Support some fonts which - report their English names through an Apple Roman - (platform,encoding) pair, with language_id != English. - - If the font uses another name entry with language_id == English, it - will be selected correctly, though. - - * src/truetype/ttobjs.c (tt_face_init): Add unpatented hinting - selection for `mingli.ttf'. - -2006-09-05 Werner Lemberg - - * src/truetype/ttpload.c (tt_face_load_hdmx): Handle `record_size' - values which have the upper two bytes set to 0xFF instead of 0x00 - (as it happens in at least two CJKV fonts, `HAN NOM A.ttf' and - `HAN NOM B.ttf'). - - * src/smooth/ftgrays.c [GRAYS_USE_GAMMA]: Really remove all code. - -2006-09-05 David Turner - - Minor source cleanups and optimizations. - - * src/smooth/ftgrays.c (GRAYS_COMPACT): Removed. - (TRaster): Remove `count_ex' and `count_ey'. - (gray_find_cell): Remove 2nd and 3rd argument. - (gray_alloc_cell): Merged with `gray_find_cell'. - (gray_record_cell): Simplify. - (gray_set_cell): Rewrite. - (gray_start_cell): Apply offsets to `ras.ex' and `ras.ey'. - (gray_render_span): Don't use FT_MEM_SET for small values. - (gray_dump_cells) [DEBUG_GRAYS]: New function. - (gray_sweep): Avoid buffer overwrites when to drawing the end of a - bitmap scanline. - (gray_convert_glyph): Fix speed-up. - -2006-09-04 David Turner - - * src/smooth/ftgrays.c (gray_convert_glyphs): Make it work with - 64bit processors. - -2006-09-03 Werner Lemberg - - * devel/ftoption.h: Synchronize with - include/freetype/config/ftoption.h. - - * src/smooth/ftgrays.c (gray_record_cell): Remove shadowing - variable declaration. - (gray_convert_glyph): Fix compiler warnings. - -2006-09-01 David Turner - - * src/truetype/ttobjs.c (tt_face_init): Update the TrueType loader - to recognize a few fonts that require the automatic unpatented - loader. - - * src/smooth/ftgrays.c: Optimize the performance of the anti-aliased - rasterizer. The speed improvement is between 15% and 25%, depending - on the font data. - - (GRAYS_USE_GAMMA, GRAYS_COMPACT): Removed, and all associated code. - (TCell): Redefine. - (TRaster): New members `buffer', `buffer_size', `ycells', `ycount'. - (gray_init_cells): Updated. - (gray_find_cell, gray_alloc_cell): New functions. - (gray_record_cell): Rewritten to use `gray_find_cell' and - `gray_alloc_cell'. - (PACK, LESS_THAN, SWAP_CELLS, DEBUG_SORT, QUICK_SORT, SHELL_SORT, - QSORT_THRESHOLD): - Removed. - (gray_shell_sort, gray_quick_sort, gray_check_sort, - gray_dump_cells): Removed. - (gray_sweep): Rewritten. - (gray_convert_glyph): Rewrite code which used one of the sorting - functions. - (gray_raster_render): Updated. - -2006-08-29 Dr. Werner Fink - - * configure: Make it possible to handle configure options which - have strings containing spaces. - -2006-08-27 David Turner - - * include/freetype/config/ftoption.h (TT_USE_BYTECODE_INTERPRETER): - New macro, defined if either TT_CONFIG_OPTION_BYTECODE_INTERPRETER - or TT_CONFIG_OPTION_UNPATENTED_HINTING is defined. - - * include/freetype/internal/ftcalc.h, src/base/ftcalc.c, - src/truetype/truetype.c, src/truetype/ttdriver.c, - src/truetype/ttgload.c, src/truetype/ttgload.h, - src/truetype/ttinterp.c, src/truetype/ttobjs.c, - src/truetype/ttobjs.h, src/truetype/ttpload.c, src/type42/t42drivr.c: - s/TT_CONFIG_OPTION_BYTECODE_INTERPRETER/TT_USE_BYTECODE_INTERPRETER/. - - * include/freetype/internal/ftobjs.h (FT_Face_InternalRec): New - member `force_autohint'. - - * src/base/ftobjs.c (FT_Load_Glyph): Use `force_autohint'. - - * src/truetype/ttobjs.c (tt_face_init): Prepare code for testing - against a list of font names which need the bytecode interpreter. - -2006-08-27 Jens Claudius - - Fix miscellaneous compiler warnings. - - * include/freetype/internal/ftobjs.h: Close comment with `*/' to - avoid `/* in comment' compiler warning. - - * src/base/ftdbgmem.c (ft_mem_table_get_source): Turn cast - `(FT_UInt32)(void*)' into `(FT_UInt32)(FT_PtrDist)(void*)' since on - 64-bit platforms void* is larger than FT_UInt32. - - * src/base/ftobjs.c (t_validator_error): Cast away - volatileness of argument to ft_longjmp. Spotted by Werner - `Putzfrau' Lemberg. - - * src/bdf/bdflib.c (bdf_load_font): Initialize local - variable `lineno'. - - * src/gxvalid/gxvmod.c (classic_kern_validate): Mark local variable - `error' as volatile. - -2006-08-27 Werner Lemberg - - * builds/unix/ftconfig.in: Synchronize with main ftconfig.h. - Reported by Jens. - -2006-08-22 Jens Claudius - - Fix for previous commit, which caused many compiler warnings/errors - about addresses of volatile objects passed as function arguments as - non-volatile pointers. - - * include/freetype/internal/ftvalid.h: Make FT_Validator typedef a - pointer to a volatile object. - - * src/gxvalid/gxvmod.c (gxv_load_table): Make function argument - `table' a pointer to a volatile object. - - * src/otvalid/otvmod.c (otv_load_table): Make function argument - `table' a pointer to a volatile object. - -2006-08-18 Jens Claudius - - * src/gxvalid/gxvmod.c (GXV_TABLE_DECL): Mark local variable `_sfnt' - as volatile since it must keep its value across a call to ft_setjmp. - (gxv_validate): Same for local variables `memory' and `valid'. - (classic_kern_validate): Same for local variables `memory', - `ckern', and `valid'. - - * src/otvalid/otvmod.c (otv_validate): Same for function parameter - `face' and local variables `base', `gdef', `gpos', `gsub', `jstf', - and 'valid'. - - * src/sfnt/ttcmap.c (tt_face_build_cmaps): Same for local variable - `cmap'. - -2006-08-16 David Turner - - * src/cid/cidgload.c (cid_slot_load_glyph): Remove compiler - warnings. - - * src/base/ftobjs.c (ft_validator_run): Disable function; it is - buggy by design. Always return -1. - - - Improvements to native TrueType hinting. This is a first try, - controlled by the FIX_BYTECODE macro in src/truetype/ttinterp.c. - - * include/freetype/internal/ftgloadr.h (FT_GlyphLoadRec): Add member - `extra_points2'. - - * include/freetype/internal/tttypes.h (TT_GlyphZoneRec): Add member - `orus'. - - * src/base/ftgloadr.c (FT_GlyphLoader_Reset, - FT_GlyphLoader_Adjust_Points, FT_GlyphLoader_CreateExtra, - FT_GlyphLoader_CheckPoints, FT_GlyphLoader_CopyPoints): Updated to - handle `extra_points2'. - - * src/truetype/ttgload.c (tt_prepare_zone): Handle `orus'. - Remove compiler warning. - (cur_to_arg): Remove macro. - (TT_Hint_Glyph): Updated. - (TT_Process_Simple_Glyph): Handle `orus'. - - * src/truetype/ttinterp.c (FIX_BYTECODE): New macro. - (Ins_MD, Ins_MDRP, Ins_IP) [FIX_BYTECODE]: Handle `orus'. - (LOC_Ins_IUP): Renamed to... - (IUP_WorkerRec): This. - Add `orus' member. - (Shift): Renamed to... - (_iup_worker_shift): This. - Updated. - (Interp): Renamed to... - (_iup_worker_interpolate): This. - Updated to handle `orus'. - (Ins_IUP): Updated. - - * src/truetype/ttobjs.c (tt_glyphzone_done, tt_glyphzone_new): - Handle `orus'. - -2006-08-15 suzuki toshiya - - * modules.cfg (BASE_EXTENSIONS): Compile in ftgxval.c by default to - build ftvalid in ft2demos. This has been inadvertently changed - 2006-08-13. - -2006-08-15 suzuki toshiya - - `ft_validator_run' wrapping `setjmp' can cause a crash, as found by - Jens: - https://lists.gnu.org/archive/html/freetype-devel/2006-08/msg00004.htm. - - * src/otvalid/otvmod.c: Replace `ft_validator_run' by `ft_setjmp'. - It reverts the change introduced on 2005-08-20. - - * src/gxvalid/gxvmod.c: Ditto. - -2006-08-13 Jens Claudius - - * finclude/freetype/internal/psaux.h: (T1_TokenType): Add - T1_TOKEN_TYPE_KEY. - (T1_FieldRec): Add `dict'. - (T1_FIELD_DICT_FONTDICT, T1_FIELD_DICT_PRIVATE): New macros. - (T1_NEW_XXX, T1_FIELD_XXX): Update to take the dictionary where a PS - keyword is expected as an additional argument. - - * src/cid/cidload.c: (cid_field_records): Adjust invocations of - T1_FIELD_XXX. - - * src/cid/cidtoken.h: Adjust invocations of T1_FIELD_XXX. - - * src/psaux/psobjs.c: Add macro FT_COMPONENT for tracing. - (ps_parser_to_token): Report a PostScript key as T1_TOKEN_TYPE_KEY, - not T1_TOKEN_TYPE_ANY. - (ps_parser_load_field): Make sure a token that should be a string or - name is really a string or name. - Avoid memory leak if a keyword has been already encountered and its - value is overwritten. - * src/type1/t1load.c: (t1_keywords): Adjust invocations of - T1_FIELD_XXX. - (parse_dict): Ignore keywords that occur in the wrong dictionary - (e.g., in `Private' instead of `FontDict'). - - * src/type1/t1tokens.h: Adjust invocations of T1_FIELD_XXX. - - * src/type42/t42parse.c: (t42_keywords): Adjust invocations of - T1_FIELD_XXX. - -2006-07-18 Jens Claudius - - Move creation of field `buildchar' of T1_DecoderRec out of - `t1_decoder_init' and let the caller of `t1_decoder_init' take care - of it. - - Call the finisher for T1_Decoder in `cid_face_compute_max_advance' - and `T1_Compute_Max_Advance'. - - * include/freetype/internal/psaux.h (T1_DecoderRec): Remove field - `face', add `len_buildchar'. - - * include/freetype/internal/t1types.h (T1_FaceRec): Add field - `buildchar'. - - * src/cid/cidgload.c (cid_face_compute_max_advance): Call finisher - for T1_Decoder. - (cid_slot_load_glyph): Do not ignore failure when initializing the - T1_Decoder. - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings): Updated. - (t1_decoder_init): Remove initialization of fields `buildchar' and - `len_buildchar'. - (t1_decoder_done): Remove deallocation of field `buildchar'. - - * freetype/src/type1/t1gload.c (T1_Compute_Max_Advance): Initialize - T1_Decoder's `buildchar' and `len_buildchar'; call finisher for - T1_Decoder. - (T1_Load_Glyph): Initialize T1_Decoder's `buildchar' and - `len_buildchar'; make sure to call finisher for T1_Decoder even in - case of error. - - * src/type1/t1load.c (T1_Open_Face): Allocate new field `buildchar' - of T1_FaceRec. - - * src/type1/t1objs.c (T1_Face_Done): Free new field `buildchar' of - T1_FaceRec. - -2006-07-14 Jens Claudius - - * include/freetype/internal/psaux.h: New macros IS_PS_NEWLINE, - IS_PS_SPACE, IS_PS_SPECIAL, IS_PS_DELIM, IS_PS_DIGIT, IS_PS_XDIGIT, - and IS_PS_BASE85 (from src/psaux/psconv.h). - (T1_FieldLocation): Add T1_FIELD_LOCATION_LOADER, - T1_FIELD_LOCATION_FACE, and T1_FIELD_LOCATION_BLEND. - (T1_DecoderRec): New fields `buildchar' and `face'. - (IS_PS_TOKEN): New macro. - - * include/freetype/internal/t1types.h (T1_FaceRec): New fields - `ndv_idx', `cdv_idx', and `len_buildchar'. - - * include/freetype/t1tables.h (PS_BlendRec): New fields - `default_design_vector' and `num_default_design_vector'. - - * src/psaux/psconv.h: Move macros IS_PS_NEWLINE, IS_PS_SPACE, - IS_PS_SPECIAL, IS_PS_DELIM, IS_PS_DIGIT, IS_PS_XDIGIT, and - IS_PS_BASE85 to include/freetype/internal/psaux.h. - - * src/psaux/psobjs.c (ps_parser_to_token_array): Allow `token' - argument to be NULL if we want only to count the number of tokens. - (ps_tocoordarray): Allow `coords' argument to be NULL if we just - want to skip the array. - (ps_tofixedarray): Allow `values' argument to be NULL if we just - want to skip the array. - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings): Add support - for (partially commented out) othersubrs 19-25, 27, and 28. - (t1_decoder_init): Initialize new fields `face' and `buildchar'. - (t1_decoder_done): Release new field `buildchar'. - - * src/type1/t1load.c (parse_buildchar, parse_private): New - functions. - (t1_keywords): Register them. - (t1_allocate_blend): Updated. - (t1_load_keyword): Handle field types T1_FIELD_LOCATION_LOADER, - T1_FIELD_LOCATION_FACE and T1_FIELD_LOCATION_BLEND. - (parse_dict): Remove `keyword_flags' argument. - Use new macro IS_PS_TOKEN. - Changed function so that later PostScript definitions override - earlier ones. - (t1_init_loader): Initialize new field `keywords_encountered'. - (T1_Open_Face): Initialize new fields `ndv_idx', `cdv_idx', and - `len_buildchar'. - Remove `keywords_flags'. - - * src/type1/t1load.h (T1_LoaderRec): New field - `keywords_encountered'. - (T1_PRIVATE, T1_FONTDIR_AFTER_PRIVATE): New macros. - - * src/type1/t1tokens.h [!T1_CONFIG_OPTION_NO_MM_SUPPORT]: New - entries for parsing /NDV, /CDV, and /DesignVector. - -2006-07-07 Werner Lemberg - - Add many checks to protect against malformed PCF files. - - * src/pcf/pcfdrivr.c (PCF_Face_Done): Protect against NULL pointers. - (PCF_Face_Init): Add calls to PCF_Face_Done in case of errors. - - * src/pcf/pcfread.c (pcf_read_TOC): Protect against malformed table - data and check that tables don't overlap (using a simple - bubblesort). - (PCF_METRIC_SIZE, PCF_COMPRESSED_METRIC_SIZE, PCF_PROPERTY_SIZE): - New macros which give the size of data structures in the data - stream. - (pcf_get_properties): Use rough estimates to get array size limits. - Assign `face->nprops' and `face->properties' earlier so that a call - to PCF_Face_Done can do the clean-up in case of error. - Protect against invalid string offsets. - (pcf_get_metrics): Clean up code. - Adjust tracing message levels. - Use rough estimate to get array size limit. - (pcf_get_bitmaps): Clean up code. - Adjust tracing message levels. - Use rough estimates to get offset limits. - (pcf_get_encodings): Adjust tracing message level. - (pcf_get_accel): Clean up code. - -2006-06-26 Werner Lemberg - - * src/bdf/bdfdrivr.c (BDF_Face_Init): Handle fonts correctly which - don't have a POINT_SIZE property. This fixes Savannah bug #16914. - -2006-06-26 Jens Claudius - - * src/psaux/t1decode.c (T1_Operator, t1_args_count): Add opcode 15. - (t1_decoder_parse_charstrings): Operator with - opcode 15 pops its two arguments. - Handle the case where the pops of an othersubr may be part of a - subroutine. - Handle unknown othersubrs gracefully: count their operands and let - the following pop operators push the operands as the results onto - the Type1 stack. - Improve handling of setcurrentpoint opcode. - -2006-06-25 Jens Claudius - - The Type 1 parser now skips over top-level procedures as required - for a `Simplified Parser'. This makes the parser more robust as it - doesn't poke around in PostScript code. Additionally, it makes the - FontDirectory hackery in src/type1/t1load.c unnecessary. - - * src/psaux/psobjs.c (IS_OCTAL_DIGIT): New macro. - (skip_literal_string): Add FT_Error as return value. - Handle escapes better. - (skip_string): Add FT_Error as return value. - Don't set `parser->error' but return error code directly. - (skip_procedure): New function. - (ps_parser_skip_PS_token): Handle procedures. - Update code. - (ps_parser_to_token): Update code. - (ps_parser_load_field_table): Handle bbox entries also. - - * src/type1/t1load.c (parse_dict): Remove FontDirectory hackery. - Add commented-out code for synthetic fonts. - -2006-06-24 Eugeniy Meshcheryakov - - Fix two hinting bugs as reported in - https://lists.gnu.org/archive/html/freetype-devel/2006-06/msg00057.html. - - * include/freetype/internal/tttypes.h (TT_GlyphZoneRec): Add - `first_point' member. - - * src/truetype/ttgload.c (tt_prepare_zone): Initialize - `first_point'. - (TT_Process_Composite_Glyph): Always untouch points. - - * src/truetype/ttinterp.c (Ins_SHC): Fix computation of - `first_point' and `last_point' in case of composite glyphs. - (Ins_IUP): Fix computation of `end_point'. - -2006-06-22 suzuki toshiya - - Insert EndianS16_BtoN and EndianS32_BtoN as workaround for Intel - Mac. The original patch was written by David Sachitano and Lawrence - Coopet, and modified by Sean McBride for MPW compatibility. Only - required data are converted; unused data are left in big endian. - - * src/base/ftmac.c: Include for byteorder macros for non - Mac OS X platforms. - (OS_INLINE): Undefine before definition. - (count_faces_sfnt): Insert EndianS16_BtoN to parse the header of - FontAssociation table in FOND resource. - (count_faces_scalable): Insert EndianS16_BtoN to parse the header - and fontSize at each entry of FontAssociation table in FOND - resource. - (parse_fond): Insert EndianS16_BtoN and EndianS32_BtoN to parse - ffStylOff of FamilyRecord header of FOND resource, the header, - fontSize, fontID at each entry of FontAssociation table, and - StyleMapping table. - (count_faces): Call `HUnlock' after all FOND utilization. - -2006-06-08 suzuki toshiya - - Public API of TrueTypeGX, OpenType, and classic kern table validator - should return `FT_Err_Unimplemented_Feature' if validation service - is unavailable (disabled in `modules.cfg'). It is originally - suggested by David Turner, cf. - https://lists.gnu.org/archive/html/freetype-devel/2005-11/msg00078.html - - * src/base/ftgxval.c (FT_TrueTypeGX_Validate): Return - FT_Err_Unimplemented_Feature if TrueTypeGX validation service is - unavailable. - (FT_ClassicKern_Validate): Return FT_Err_Unimplemented_Feature if - classic kern table validation service is unavailable. - - * src/base/ftotval.c (FT_OpenType_Validate): Return - FT_Err_Unimplemented_Feature if OpenType validation service is - unavailable. - -2006-06-08 Werner Lemberg - - * src/bdf/bdflib.c (bdf_load_font): Fix memory leaks in case of - errors. - -2006-06-07 David Turner - - * src/type1/t1afm.c (KERN_INDEX): Make it more robust. - (T1_Read_Metrics): Fix memory leak which happened when the metrics - file doesn't have kerning pairs. This fixes Savannah bug #16768. - -2006-06-06 David Turner - - Fix memory leak described in Savannah bug #16759. - - We change `ps_unicodes_init' so that it also takes a - `free_glyph_name' callback to release the glyph names returned by - `get_glyph_name' - - * include/freetype/internal/services/svpscmap.h (PS_Glyph_NameFunc): - Renamed to ... - (PS_GetGlyphNameFunc): This. - (PS_FreeGlyphNameFunc): New typedef. - (PS_Unicodes_InitFunc): Add variable for PS_FreeGlyphNameFunc. - - * src/cff/cffcmap.c (cff_sid_to_glyph_name): Use `TT_Face' for first - argument. - (cff_sid_free_glyph_name): New function. - (cff_cmap_unicode_init): Updated. - - * src/psaux/t1cmap.c (t1_cmap_unicode_init): Updated. - - * src/psnames/psmodule.c (ps_unicodes_init): Add variable for - PS_FreeGlyphNameFunc and use it. - - -2006-06-04 David Turner - - * src/base/ftutil.c (ft_mem_qrealloc): Fix the function to accept - `item_size == 0' as well -- though this sounds weird, it can - theoretically happen. This fixes Savannah bug #16669. - - * src/pfr/pfrobjs.c (pfr_face_init): Fix the computation - of `face->num_glyphs' which missed the last glyph, due to - the offset-by-1 computation, since the PFR format doesn't - guarantee that glyph index 0 corresponds to the `missing - glyph. This fixes Savannah bug #16668. - -2006-05-25 Werner Lemberg - - * builds/unix/unix-cc.in (LINK_LIBRARY): Don't comment out - `-no-undefined'. Reported by Christian Biesinger. - -2006-05-19 Brian Weed - - * builds/win32/visualc/freetype.dsp: Release libraries no longer - have debug information, and debug libraries use `C7 compatible' - debug info. - -2006-05-19 suzuki toshiya - - Apply patch by Derek Clegg to fix two memory leaks in the MacOS - resource fork handler. This fixes Savannah bug #16631. - - * src/base/ftobjs.c (load_face_in_embedded_rfork): Replace - `FT_Stream_Close' by `FT_Stream_Free' to fix memory leak. - - * src/base/ftrfork.c (raccess_guess_linux_double_from_file_name): - Replace `FT_Stream_Close' by `FT_Stream_Free' to fix memory leak. - -2006-05-19 suzuki toshiya - - * build/unix/configure.raw: Add a fallback to disable Carbon - dependency, if configured with no options on Mac OS X. - -2006-05-19 suzuki toshiya - - * src/base/ftmac.c (open_face_from_buffer): Deallocate stream when - its content cannot be parsed as supported font. This fixes - the second part of Savannah bug #16590. - -2006-05-18 Werner Lemberg - - * src/truetype/ttgload.c (TT_Load_Composite_Glyph) - [TT_CONFIG_OPTION_BYTECODE_INTERPRETER]: Make it compilable again. - -2006-05-17 David Turner - - This is a major patch used to drastically improve the performance of - loading glyphs. This both speeds up loading the glyph vectors - themselves and the auto-fitter module. - - We now use inline assembler code with GCC to implement `FT_MulFix', - which is probably the most important function related to the - engine's performance. - - The resulting speed-up is about 25%. - - - * include/freetype/internal/tttypes.h (TT_LoaderRec): Add fields - `cursor' and `limit'. - - * src/autofit/afangles.c (af_corner_is_flat, af_corner_orientation): - New functions. - (AF_ATAN_BITS, af_arctan, af_angle_atan): Comment out. - [TEST]: Remove. - - * src/autofit/afcjk.c (AF_Script_UniRangeRec): Comment out test - code. - - * src/autofit/afhints.c (af_axis_hints_new_segment): Don't call - `FT_ZERO' - (af_direction_compute, af_glyph_hints_compute_inflections): Rewritten. - (af_glyph_hints_reload: Rewrite recognition of weak points. - - * src/autofit/aflatin.c (af_latin_hints_compute_segments): Move - constant values out of the loops. - - * src/autofit/aftypes.h: Updated. - - * src/base/ftcalc.c (FT_MulFix): Use inline assembler code. - - * src/base/ftoutln.c (FT_Outline_Get_Orientation): Use vector - product to get orientation. - - * src/gzip/ftgzip.c (ft_get_uncompressed_size): New function. - (FT_Stream_OpenGzip): Use it to handle small files directly in - memory. - - * src/psaux/psconv.c (PS_Conv_ASCIIHexDecode, PS_Conv_EexecDecode): - Improve performance. - - * src/truetype/ttgload.c (TT_Access_Glyph_Frame): Set `cursor' and - `limit'. - - (TT_Load_Glyph_Header, TT_Load_Simple_Glyph, - TT_Load_Composite_Glyph): Updated. Add threshold to protect against - exceedingly large values of number of contours. Speed up by - reducing the number of loops. - - * src/type1/t1gload.c (T1_Load_Glyph): Don't apply unit matrix. - - - * src/cache/ftccmap.c (FTC_CMapCache_Lookup): Change the threshold - used to detect rogue clients from 4 to 16. This is to prevent some - segmentation faults with fonts like `KozMinProVI-Regular.otf' which - comes from the Japanese Adobe Reader Asian Font pack. - -2007-05-17 Werner Lemberg - - * src/cff/cffload.c (cff_font_done): Deallocate subfont array. This - fixes the first part of Savannah bug #16590. - -2006-05-16 Werner Lemberg - - * docs/PROBLEMS: Updated icl issues. - ----------------------------------------------------------------------------- - -Copyright (C) 2006-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, modified, -and distributed under the terms of the FreeType project license, -LICENSE.TXT. By continuing to use, modify, or distribute this file you -indicate that you have read the license and understand and accept it -fully. - - -Local Variables: -version-control: never -coding: utf-8 -End: diff --git a/lib/libesp32_lvgl/freetype/ChangeLog.24 b/lib/libesp32_lvgl/freetype/ChangeLog.24 deleted file mode 100644 index 17e98c484..000000000 --- a/lib/libesp32_lvgl/freetype/ChangeLog.24 +++ /dev/null @@ -1,6360 +0,0 @@ -2013-05-08 Werner Lemberg - - * Version 2.4.12 released. - ========================== - - - Tag sources with `VER-2-4-12'. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.4.12. - - * README, Jamfile (RefDoc), - builds/win32/vc2005/freetype.vcproj, builds/win32/vc2005/index.html, - builds/win32/vc2008/freetype.vcproj, builds/win32/vc2008/index.html, - builds/win32/vc2010/freetype.vcxproj, builds/win32/vc2010/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualc/index.html, builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj, - builds/win32/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.4.11/2.4.12/, s/2411/2412/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 12. - - * builds/unix/configure.raw (version_info): Set to 16:1:10. - -2013-05-08 Werner Lemberg - - * docs/CHANGES: Updated. - -2013-05-08 Werner Lemberg - - * src/autofit/aflatin.c (af_latin_metrics_scale_dim): Typo. - -2013-05-05 Werner Lemberg - - Synchronize `ftconfig.h'. - - * builds/unix/ftconfig.in: Updated. - -2013-05-05 Werner Lemberg - - Fix compilation with C++. - - * src/base/md5.c (body): Use proper cast. - -2013-05-05 Werner Lemberg - - Fix 64bit compilation issues. - - * include/freetype/config/ftconfig.h [FT_LONG64]: Typedef - `FT_Int64' here. - - * src/base/ftcalc.c: Remove typedef of `FT_Int64'. - (FT_DivFix): Fix cast. - * src/base/fttrigon.c: Remove typedef of `FT_Int64'. - -2013-05-05 Werner Lemberg - - [raster] Fix clang issues. - - Fix suggested by . - - * src/raster/ftraster.c (ULong): New typedef. - (SCALED): Add proper cast. - -2013-05-04 Werner Lemberg - - Fix clang fixes. - - * src/base/fttrigon.c (ft_trig_prenorm, FT_Vector_Rotate): Use - correct types. - - * src/cff/cf2intrp.c (cf2_interpT2CharString) : Force - unsigned for computations. - * src/cff/cffgload.c (cff_decoder_parse_charstrings): Ditto. - * src/cff/cffparse.c (cff_parse_integer): Ditto. - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings): Ditto. - -2013-05-04 Werner Lemberg - - [cff] Make Adobe CFF engine work correctly on 64bit hosts. - - Reported by numerous people on the `freetype-devel' list. Without - this fix, glyphs aren't properly aligned on a common baseline. - - On 64bit systems, `FT_Pos' expands to `long int', having a width of - 64bit. `CF2_Fixed' expands to `int' which is normally 32bit wide on - 64bit hosts also. Wrong casts filled up the blues arrays with - incorrect values. Note that all blues values are accessed with the - `cf2_blueToFixed' macro which handles the 64bit to 32bit conversion. - - * src/cff/cf2ft.h (cf2_getBlueValues, cf2_getOtherBlues, - cf2_getFamilyBlues, cf2_getFamilyOtherBlues): Use `FT_Pos' for - `data', not `CF2_Fixed'. - * src/cff/cf2ft.c (cf2_getBlueValues, cf2_getOtherBlues, - cf2_getFamilyBlues, cf2_getFamilyOtherBlues): Updated. - * src/cff/cf2blues.c (cf2_blues_init): Updated. - -2013-05-04 Werner Lemberg - - More fixes for clang's `sanitize' feature. - - * src/base/ftcalc.c (FT_DivFix): Use unsigned values for - computations which use the left shift operator and convert to signed - as the last step. - * src/base/fttrigon.c (ft_trig_prenorm, FT_Vector_Rotate, - FT_Vector_Length, FT_Vector_Polarize): Ditto. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings): Simplify. - * src/cff/cffload.c (cff_subfont_load): Fix constant. - * src/cff/cffparse.c (cff_parse_integer, cff_parse_real, do_fixed, - cff_parse_fixed_dynamic): Use unsigned values for computations which - use the left shift operator and convert to signed as the last step. - - * src/cid/cidload.c (cid_get_offset): Ditto. - - * src/psaux/psconv.c (PS_Conv_ToFixed): Ditto. - * src/psaux/t1decode.c (t1_decoder_parse_charstrings): Ditto. - - * src/truetype/ttinterp.c (TT_MulFix14, TT_DotFix14): Ditto. - -2013-05-04 Werner Lemberg - - Fix errors reported by clang's `sanitize' feature. - - * include/freetype/internal/ftstream.h: Simplify and fix integer - extraction macros. - (FT_INT8_, FT_BYTE_I16, FT_BYTE_I32, FT_INT8_I16, FT_INT8_I32, - FT_INT8_I32, FT_INT8_U32): Removed. - (FT_PEEK_SHORT, FT_PEEK_LONG, FT_PEEK_OFF3, FT_PEEK_SHORT_LE, - FT_PEEK_LONG_LE, FT_PEEK_OFF3_LE): Use unsigned values for - computations and convert to signed as the last step. - - * src/cff/cf2fixed.h (cf2_intToFixed, cf2_fixedToInt, - cf2_fracToFixed): Avoid shifts of negative values. - (cf2_intToFrac, cf2_fixedToFrac, cf2_fixedTo26Dot6): Removed, - unused. - - * src/cff/cf2intrp.c (cf2_interpT2CharString) : Use unsigned values for computations and convert to signed - as the last step. - Use proper types in tracing messages. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings): Use unsigned - values for computation of operands and convert to signed as the last - step. - Use proper type in tracing message. - -2013-05-03 Werner Lemberg - - * src/cff/cf2blues.c: Remove dead code. - -2013-05-02 Chris Liddell - - * src/cff/cffgload.c: Include FT_CFF_DRIVER_H. - -2013-04-27 Werner Lemberg - - * docs/CHANGES: Updated. - * README: Improved. - -2013-04-13 Werner Lemberg - - [cff] Add a new Type 2 interpreter and hinter. - - This work, written by Dave Arnold and fully - integrated into FreeType by me, is a donation by Adobe in - collaboration with Google. It is vastly superior to the old CFF - engine, and it will replace it soon. Right now, it is still off by - default, and you have to explicitly select it using the new - `hinting-engine' property of the cff driver. - - For convenience, (most of) the new files are committed separately. - - * include/freetype/config/ftheader.h (FT_CFF_DRIVER_H): New macro. - * include/freetype/ftcffdrv.h: New file to access CFF driver - properties. - * include/freetype/fterrdef.h (FT_Err_Glyph_Too_Big): New error - code. - * include/freetype/internal/fttrace.h: Add `cf2blues', `cf2hints', - and `cf2interp'. - - * src/cff/cffgload.h (CFF_SubFont): New member `current_subfont'. - * src/cff/cffobjs.h (CFF_DriverRec): New members `hinting_engine' - and `no_stem_darkening'. - * src/cff/cfftypes.h (CFF_FontRec): New member `cf2_instance'. - - * src/cff/cff.c: Include new files. - * src/cff/cffdrivr.c (cff_property_set, cff_property_get): Handle - `hinting-engine' and `no-stem-darkening' properties (only the Adobe - engine listens to them). - * src/cff/cffgload.c: Include `cf2ft.h'. - (cff_decoder_prepare): Initialize `current_subfont'. - (cff_build_add_point): Handle Adobe engine which uses 16.16 - coordinates. - (cff_slot_load): Handle FT_LOAD_NO_SCALE and FT_LOAD_NO_HINTING - separately. - Choose rendering engine based on `hinting_engine' property. - * src/cff/cffload.c (cff_font_done): Call finalizer of the Adobe - engine. - * src/cff/cffobjs.c: Include FT_CFF_DRIVER_H. - (cff_driver_init): Set default property values. - - * src/cff/rules.mk (CFF_DRV_SRC, CFF_DRV_H): Add new files. - - * src/cff/cf2*.*: New files, containing the Adobe engine. - -2013-04-12 Werner Lemberg - - [cff] Minor code administration issues. - - * src/cff/cffgload.c (check_points): Rename to... - (cff_check_points): ...this and make it FT_LOCAL. - (cff_builder_add_point, cff_builder_add_point1, - cff_builder_start_point, cff_builder_close_contour, - cff_lookup_glyph_by_stdcharcode, cff_get_glyph_data, - cff_free_glyph_data): Make them FT_LOCAL. - - * src/cff/cffgload.h: Updated. - -2013-04-12 Werner Lemberg - - Add output bitmap checksums. - - Use `FT2_DEBUG=bitmap:3' for tracing. - - * src/base/md5.c, src/base/md5.h: New files, taken from - - https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 - - * include/freetype/internal/fttrace.h: Add `bitmap'. - - * src/base/ftobjs.c [FT_DEBUG_LEVEL_TRACE]: Include `md5.c' - - (FT_Render_Glyph_Internal) [FT_DEBUG_LEVEL_TRACE]: For tracing, - convert resulting bitmap to a uniform format and compute a checksum. - Use `bitmap' category for the tracing message. - - * src/base/rules.mk (BASE_H): Updated. - - * docs/LICENSE.TXT: Updated. - -2013-04-12 Werner Lemberg - - [cff] Add framework for CFF properties. - - * include/freetype/internal/ftserv.h (FT_DEFINE_SERVICEDESCREC7): - New macro. - - * src/cff/cffdrivr.c: Include FT_SERVICE_PROPERTIES_H. - (cff_property_set, cff_property_get): New functions, still empty. - Define `cff_service_properties' service. - Update `cff_services'. - - * src/cff/cffpic.h: Include FT_SERVICE_PROPERTIES_H. - (CFF_SERVICE_PROPERTIES_GET): New macro. - (CffModulePIC): Add `cff_service_properties'. - -2013-04-03 Werner Lemberg - - [bdf] Fix Savannah bug #38589. - - * src/bdf/bdflib.c (_bdf_readstream): Thinko. - -2013-03-31 Werner Lemberg - - * configure: Use egrep, not grep. - - Problem reported Mojca Miklavec . - -2013-03-29 Werner Lemberg - - * include/freetype/ftlcdfil.h: Add description of color filtering. - - Based on a contribution from Antti S. Lankila - (Savannah bug #38607). - -2013-03-23 Werner Lemberg - - [autofit] Minor. - - * src/autofit/afmodule.c (af_property_set): Typo. - (af_autofitter_init, af_autofitter_done): Use cast. - -2013-03-21 Werner Lemberg - - * configure: Automatically test for `gmake' also. - - Suggested by Mojca Miklavec . - -2013-03-21 Peter Breitenlohner - - Respect CONFIG_SHELL from the environment. - - Some large packages using FreeType have to use a broken (deficient) - /bin/sh. The configure scripts (as generated by Autoconf) are - clever enough to find a better shell and put that one into the - environment variable CONFIG_SHELL. If that environment variable is - already set the script skips the test and assumes to be already - running under a good shell. - - * builds/unix/detect.mk: Honour CONFIG_SHELL. - * builds/unix/unix-def.in (SHELL): Define. - -2013-03-21 Werner Lemberg - - Fix Savannah patch #7971. - - * configure: Handle MAKE environment variable also. - -2013-03-17 Werner Lemberg - - Fix Savannah bug #38538. - - * builds/amiga/src/base/ftdebug.c, builds/win32/ftdebug.c, - builds/wince/ftdebug.c (FT_Throw): Add function. - -2013-03-17 Werner Lemberg - - [raster] Remove dead code. - - * src/raster/rastpic.c (ft_raster1_renderer_class_pic_init) - src/smooth/ftspic.c (ft_smooth_renderer_class_pic_init): Do it. - -2013-03-17 Werner Lemberg - - * src/pshinter/pshpic.h (GET_PIC): Use correct container. - -2013-03-15 Werner Lemberg - - * include/freetype/ftmoderr.h: Fix commit from 2013-03-11. - - The previous version was not backward compatible. Reported by - Behdad. - -2013-03-14 Werner Lemberg - - */*: Use FT_ERR_EQ, FT_ERR_NEQ, and FT_ERR where appropriate. - - FT_Err_XXX and friends are no longer directly used in the source - code. - -2013-03-14 Werner Lemberg - - New error management macros. - - * include/freetype/fterrors.h (FT_ERR_XCAT, FT_ERR_CAT): Move to... - * include/freetype/fttypes.h: ... this file. - (FT_ERR, FT_ERR_EQ, FT_ERR_NEQ, FT_MODERR_EQ, FT_MODERR_NEQ): New - macros. - - * include/freetype/freetype.h: Updated. - -2013-03-14 Werner Lemberg - - */*: Use FT_Err_Ok only. - - This is a purely mechanical conversion. - -2013-03-14 Werner Lemberg - - */*: Use `FT_THROW'. - - This is essentially a mechanical conversion, adding inclusion of - `FT_INTERNAL_DEBUG_H' where necessary, and providing the macros for - stand-alone compiling modes of the rasterizer modules. - - To convert the remaining occurrences of FT_Err_XXX and friends it is - necessary to rewrite the code. Note, however, that it doesn't harm - if some cases are not handled since FT_THROW is a no-op. - -2013-03-13 Werner Lemberg - - Introduce `FT_THROW' macro. - - The idea is to replace code like - - return FT_Err_Foo_Bar; - - or - - return CFF_Err_Foo_Bar; - - with - - return FT_THROW( Foo_Bar ); - - The FT_THROW macro has two functions: - - . It hides the module specific prefix. - - . In debug mode, it calls the empty function `FT_Throw' which can - be thus used to set a breakpoint. - - * include/freetype/internal/ftdebug.h (FT_THROW): New macro. - (FT_Throw): New prototype. - * src/base/ftdebug.c (FT_Throw): New function. - -2013-03-12 Werner Lemberg - - Remove `FT_KEEP_ERR_PREFIX'. - - The idea is to always have FT_ERR_PREFIX available internally. - - * include/freetype/fterrors.h: Use FT2_BUILD_LIBRARY to guard - undefinition of FT_ERR_PREFIX - - * src/gxvalid/gxverror.h, src/otvalid/otverror.h, - src/sfnt/sferrors.h: Updated. - -2013-03-11 Werner Lemberg - - [gxvalid] Fix module error. - - * src/gxvalid/gxverror.h (FT_ERR_BASE): Define as - FT_Mod_Err_GXvalid. - * include/freetype/ftmoderr.h: Add module error for `GXvalid'. - -2013-03-11 Werner Lemberg - - Always use module related error codes. - - * src/cff/cffobjs.c (cff_face_init), src/type1/t1objs.c - (T1_Face_Init), src/type42/t42objs.c (T42_Face_Init): Use - `FT_ERROR_BASE'. - - * src/type1/t1load.c (parse_encoding): Use - T1_Err_Unknown_File_Format. - -2013-03-08 Werner Lemberg - - [cff] Set `linear{Hori,Vert}Advance' for embedded bitmaps also. - - Problem reported by Khaled Hosny . - - * src/cff/cffgload.c (cff_slot_load): Implement it. - -2013-02-23 Alexei Podtelezhnikov - - [base] Fix commit ab02d9e8. - - * src/base/ftbbox.c (BBox_Cubic_Check): Change scaling to msb of 22. - -2013-02-19 Alexei Podtelezhnikov - - [base] New bisecting BBox_Cubic_Check (disabled). - - * src/base/ftbbox.c (BBox_Cubic_Check): New bisecting algorithm - for extremum search built around simple condition that defines - which half contains the extremum. - -2013-02-18 Alexei Podtelezhnikov - - [tools] Update BBox testing tool. - - * src/tools/test_bbox.c: Add another cubic outline with exact BBox. - (REPEAT): Increase the number of benchmarking cycles. - (profile_outline): Tweak output formatting. - -2013-02-02 Werner Lemberg - - Fix Savannah bug #38235. - - * builds/unix/configure.raw: Don't generate `freetype-config' and - `freetype.pc'. - - * builds/unix/unix-def.in (FT2_EXTRA_LIBS, LIBBZ2, LIBZ, - build_libtool_libs, ft_version): New variables to be substituted. - (freetype-config, freetype.pc): New rules to generate those files. - - * builds/unix/freetype-config.in: Remove code for handling `rpath'. - The use of $rpath has been accidentally removed in a patch from - 2009-12-22, and apparently noone has missed it since. - Use `%' instead of `@' as a variable substitution marker. - Use quotes. - - * builds/unix/freetype.in: Use `%' instead of `@' as a variable - substitution marker. - Use quotes. - -2013-02-07 Werner Lemberg - - * src/truetype/ttobjs.c (tt_size_run_prep): Reset more GS variables. - - BTW, Greg agrees that the OpenType specification is missing the list - of GS variables which will always be reset to the default values - after the `prep' table has been executed. - -2013-02-06 Werner Lemberg - - * src/truetype/ttobjs.c (tt_size_run_prep): Reset reference points. - - Up to now, we simply took a snapshot of the Graphics State after the - `prep' table has been executed, and right before a glyph's bytecode - was run it got reloaded. However, as Greg Hitchcock has told us in - private communication, reference points get reset to zero in the MS - rasterizer and we follow in due course. While reasonable, this is - undocumented behaviour. - - Most notably, this fixes the rendering of Arial's `x' glyph in - subpixel hinting mode. - -2013-02-05 Werner Lemberg - - [truetype] A better fix for Savannah bug #38211. - - * src/truetype/ttinterp.c (Ins_IP): Implement identical behaviour to - MS rasterizer if rp1 == rp2 (confirmed by Greg Hitchcock). - -2013-02-01 Alexei Podtelezhnikov - - [pcf] Streamline parsing of PCF encoding table. - - * src/pcf/pcfread.c (pcf_get_encodings): Use simpler double for-loop. - Reallocate array instead of using temporary storage. - -2013-02-01 Werner Lemberg - - Fix Savannah bug #38227. - - * builds/unix/freetype-config.in: Set LC_ALL. - -2013-02-01 Werner Lemberg - - Fix Savannah bug #38221. - - This complements commit 83c0ebab. - - * src/base/ftcalc.c (FT_MulDiv_No_Round): Don't enclose with - `TT_USE_BYTECODE_INTERPRETER'. - -2013-02-01 Werner Lemberg - - [truetype] Fix Savannah bug #38211. - - * src/truetype/ttinterp.c (Ins_IP): Make FreeType behave identical - to other interpreters if rp1 == rp2 (which is invalid). - -2013-01-28 Alexei Podtelezhnikov - - [base] Small optimization of BBox calculation. - - * src/base/ftbbox.c (BBox_Cubic_Check): Use FT_MSB function in - scaling algorithm. - -2013-01-26 Infinality - - [truetype] Minor formatting fix. - - * src/truetype/ttinterp.c: Updated. - (DO_RS): Fix indentation. - -2013-01-26 Infinality - - [truetype] Fix rasterizer_version logic in sph. - - * src/truetype/ttsubpix.c: Updated. - (ALWAYS_SKIP_DELTAP_Rules): Remove rule for Trebuchet MS. - (sph_set_tweaks): Fix `rasterizer_version' logic. - -2013-01-26 Infinality - - [truetype] Align more to ClearType whitepaper for sph. - - * include/freetype/internal/tttypes.h (TT_FaceRec): Add flags - for detected opcode patterns and compatibility mode. - - * src/truetype/ttgload.c (tt_loader_init): Complete conditional. - - * src/truetype/ttinterp.c: Updated. - Remove SPH_DEBUG and replace with FT_TRACE7. - (DO_RS): More conditions. - (Ins_FDEF): Add more opcode detection patterns. - More specific conditions when flagging an fdef. - Make compatibility mode only turn on when delta fdefs are found. - (Ins_CALL, Ins_LOOPCALL): Set flags for currently executed fdef. - (Ins_SHPIX): Remove logic to handle ttfautohinted fonts. - Simplify conditionals where possible. - Use `&' instead of `%' operator for dumb compilers. - (Ins_MIAP): Adjust twilight zone conditional. - Ensure `ignore_x_mode' is on when testing sph conditionals. - (Ins_MIRP): Ensure `ignore_x_mode' is on when testing sph - conditionals. - Do cvt cutin always when `ignore_x_mode' is active. - Remove test for ttfautohinted fonts. - (Ins_DELTAP): Ensure `ignore_x_mode' is on when testing sph - conditionals. - Do cvt cutin always when `ignore_x_mode' is active. - Remove test for ttfautohinted fonts. - Use `&' instead of `%' operator for dumb compilers. - (Ins_GETINFO): Remove SPH_DEBUG and replace with FT_TRACE7. - - * src/truetype/ttinterp.h: Updated. - (TT_ExecContextRec): Remove compatibility_mode variable. - Add variable to indicate when executing in special fdefs for sph. - - * src/truetype/ttobjs.h: Updated. - (TT_DefRecord): Add flags to identify special fdefs for sph. - (TT_SizeRec): Remove unnecessary ttfautohinted variable. - - * src/truetype/ttsubpix.c: Updated. - (COMPATIBILITY_MODE_Rules): Remove all. Auto-detected now. - (PIXEL_HINTING_Rules): Remove all. Unnecessary after fixes. - (SKIP_NONPIXEL_Y_MOVES_Rules): Remove Ubuntu. - (SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions): Add Arial Bold `N'. - (SKIP_OFFPIXEL_Y_MOVES_Rules): Remove all. Happens automatically - now. - (ROUND_NONPIXEL_Y_MOVES_Rules): Remove Ubuntu. - (ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions): Remove all. - (NORMAL_ROUND_Rules): Remove Verdana. - (NO_DELTAP_AFTER_IUP_Rules): Remove all. - (sph_set_tweaks): Performance fix. Don't run prep always. - Adjust conditional for sph_compatibility_mode. - - * src/truetype/ttsubpix.h: Add new fdef flags for sph. - -2013-01-23 Alexei Podtelezhnikov - - [base] Fix broken emboldening at small sizes. - - * src/base/ftoutln.c (FT_Outline_EmboldenXY): Do not attempt to - normalize zero-length vectors. - -2013-01-25 Werner Lemberg - - Fix Savannah bug #38167. - - This fixes commit 83c0ebab from 2012-06-27. - - * src/truetype/ttinterp.h: - s/TT_CONFIG_OPTION_BYTECODE_INTERPRETER/TT_USE_BYTECODE_INTERPRETER/. - -2013-01-25 Xi Wang - - [sfnt] Fix broken pointer overflow checks. - - Many compilers such as gcc and clang optimize away pointer overflow - checks `p + n < p', because pointer overflow is undefined behavior. - Use a safe form `n > p_limit - p' instead. - - Also avoid possible integer overflow issues, for example, using - `num_glyphs > ( p_limit - p ) / 2' rather than `num_glyphs * 2' - given a large `num_glyphs'. - - * src/sfnt/ttsbit0.c (tt_sbit_decoder_load_image): Implement it. - -2013-01-25 Werner Lemberg - - [base] Fix `make multi'. - - * src/base/ftoutln.c, src/base/fttrigon.c: Include - FT_INTERNAL_CALC_H. - -2013-01-25 David 'Digit' Turner - - [truetype] Fix C++ compilation. - - * src/truetype/ttsubpix.h: Updated. - (SPH_X_SCALING_RULES_SIZE): Moved and renamed to... - * src/truetype/ttsubpix.c (X_SCALING_RULES_SIZE): This. - (sph_X_SCALING_Rules): Removed. - (scale_test_tweak): Make function static. - (sph_test_tweak_x_scaling): New function. - - * src/truetype/ttgload.c (TT_Process_Simple_Glyph): Updated. - -2013-01-23 Werner Lemberg - - [base] Make `FT_Hypot' really internal. - - * include/freetype/fttrigon.h (FT_Hypot): Move to... - * include/freetype/internal/ftcalc.h: This file. - - * src/base/fttrigon.c (FT_Hypot): Move to... - * src/base/ftcalc.c: This file. - Include FT_TRIGONOMETRY_H. - - * src/truetype/ttgload.c: Don't include FT_TRIGONOMETRY_H. - -2013-01-23 Werner Lemberg - - [truetype] Revert change from 2013-01-22. - - FreeType's `height' value is the baseline-to-baseline distance... - - * src/truetype/ttobjs.c (tt_size_reset): Undo. - -2013-01-23 Alexei Podtelezhnikov - - [base, truetype] New internal `FT_Hypot' function. - - * include/freetype/fttrigon.h (FT_Hypot): Declare it. - * src/base/fttrigon.c (FT_Hypot): Define it. - * src/truetype/ttgload.c (TT_Process_Composite_Component): Use it - instead of explicit expressions. - * src/truetype/ttinterp.c (Current_Ratio, Normalize): Use it instead - of TT_VecLen. - (TT_VecLen): Removed. - -2013-01-23 Alexei Podtelezhnikov - - [base] Fix integer overflow. - - * src/base/ftoutln.c (FT_Outline_EmboldenXY): Normalize incoming and - outgoing vectors and use fixed point arithmetic. - -2013-01-23 Alexei Podtelezhnikov - - [base] Fix integer overflow. - - * src/base/ftoutln.c (FT_Outline_Get_Orientation): Scale the - coordinates down to avoid overflow. - -2013-01-23 Alexei Podtelezhnikov - - [base] Split out MSB function. - - * src/base/fttrigon.c (ft_trig_prenorm): Borrow from here. - * include/freetype/internal/ftcalc.h (FT_MSB): Declare here. - * src/base/ftcalc.c (FT_MSB): Define here. - -2013-01-22 Werner Lemberg - - [truetype] Fix font height. - - * src/truetype/ttobjs.c (tt_size_reset): The Windows rendering - engine uses rounded values of the ascender and descender to compute - the TrueType font height. - -2013-01-16 Behdad Esfahbod - - [sfnt] Fix optimized sbit loader. - - It was not taking bit_depth into consideration when blitting! - - * src/sfnt/ttsbit0.c (tt_sbit_decoder_load_byte_aligned, - * tt_sbit_decoder_load_bit_aligned): Handle bit - depth. - -2013-01-16 David 'Digit' Turner - - [truetype] Improve subpixel code. - - This patches fixes many issues with the ttsubpix implementation. - - 1. Data tables are defined, instead of declared, in the header, and - thus copied into each source file that includes it. - - 2. These tables were defined as global, mutable, visible variables, - and thus costing private RAM to every process that loads the - library (> 50 KB / process, this is huge!). - - Additionally, this also made the library export the symbols - completely needlessly. - - 3. Missing `sph_' and `SPH_' prefixes to some of the definitions. - - Note that this doesn't try to fix the incredibly inefficient storage - format for the data tables used by the code. This one will require - another pass in the future. - - * src/truetype/ttinterp.h (MAX_NAME_SIZE, MAX_CLASS_MEMBERS): - Renamed to... - (SPH_MAX_NAME_SIZE, SPH_MAX_CLASS_MEMBERS): This. - Update all users. - - (SPH_TweakRule, SPH_ScaleRule): Decorate with `const' where - appropriate. - - (Font_Class): Rename to... - (SPH_Font_Class): This. Decorate with `const' where appropriate. - - * src/truetype/ttsubpix.h (scale_test_tweak, sph_test_tweak): - Decorate arguments with `const' where appropriate. - - Move font tweaking tables to... - - * src/truetype/ttsubpix.c: This file and decorate them with `static' - and `const' where appropriate. - - (X_SCALING_Rules, X_SCALING_RULES_SIZE): Renamed to... - (sph_X_SCALING_Rules, SPH_X_SCALING_RULES_SIZE): This. - Update all users. - -2013-01-12 Alexei Podtelezhnikov - - [truetype] Improve accuracy of normalization of short vectors. - - Unit vector components are stored as 2.14 fixed-point numbers. In - order to calculate all 14 bits accurately, a short vector to be - normalized has to be upscaled to at least 14 bits before its length - is calculated. This has been safe since accurate CORDIC algorithms - were adopted. - - * src/truetype/ttinterp.c (Normalize): Scale short vectors by 0x4000. - -2013-01-12 Alexei Podtelezhnikov - - [truetype] Kill very old vector normalization hacks. - - Back in the days, vector length calculations were not very accurate - and the vector normalization function, Normalize, had to meticulously - correct the errors for long vectors [commit b7ef2b096867]. It was no - longer necessary after accurate CORDIC algorithms were adopted, but - the code remained. It is time to kill it. - - * src/truetype/ttinterp.c (Normalize): Remove error compensation. - (TT_VecLen): Remove any mention of old less accurate implementation. - -2013-01-11 Werner Lemberg - - Disable FT_CONFIG_OPTION_OLD_INTERNALS. - - After the next release we are going to remove the code completely. - - * devel/ftoption.h, include/freetype/config/ftoption.h - (FT_CONFIG_OPTION_OLD_INTERNALS): Comment out. - * docs/CHANGES: Document it. - -2013-01-10 Alexei Podtelezhnikov - - [base] Update the overflow protection bit. - - The recent optimizations of CORDIC iterations drastically reduce the - expansion factor. Vector components with MSB of 29 are now safe - from overflow. - - * src/base/fttrigon.c (FT_TRIG_SAFE_MSB): New macro. - (ft_trig_prenorm): Use it and remove dead code. - -2013-01-09 Alexei Podtelezhnikov - - [base, pshinter] Use FT_ABS, FT_MIN, and FT_MAX for readability. - - * src/base/ftbbox.c: Updated. - * src/base/ftobjs.c: Updated. - * src/base/fttrigon.c: Updated. - * src/pshinter/pshalgo.c: Updated. - * src/pshinter/pshrec.c: Updated. - -2013-01-08 Alexei Podtelezhnikov - - [base] Clean up trigonometric core. - - * src/base/fttrigon.c: Document the algorithm in a large comment. - (FT_TRIG_COSCALE): Remove macro. - (FT_Tan: Use `FT_TRIG_SCALE' instead. - (FT_Cos, FT_Vector_Unit): Ditto and round the return values. - -2013-01-02 Alexei Podtelezhnikov - - [base] Use rounding in CORDIC iterations. - - * src/base/fttrigon.c (ft_trig_pseudo_rotate, - ft_trig_pseudo_polarize): Improve accuracy by rounding. - -2013-01-02 Alexei Podtelezhnikov - - [base] Reduce trigonometric algorithms. - - After we get within 45 degrees by means of true 90-degree rotations, - we can remove initial 45-degree CORDIC iteration and start from - atan(1/2) pseudorotation, reducing expansion factor thereby. - - * src/base/fttrigon.c (FT_TRIG_SCALE, FT_TRIG_COSCALE): Update macros. - (ft_trig_pseudo_rotate, ft_trig_pseudo_polarize): Update. - - * src/tools/cordic.py: Bring up to date with trigonometric core. - - * docs/CHANGES: Old typo. - -2013-01-02 Alexei Podtelezhnikov - - * src/pshinter/pshalgo.h: Remove unused code. - -2012-12-27 Werner Lemberg - - * src/truetype/ttgload.c (tt_loader_init): Add more tracing. - -2012-12-23 Werner Lemberg - - [type1] Fix handling of /FontBBox in MM fonts. - Problem reported by Del Merritt - - If we have - - /FontBBox { { 11 12 13 14 15 16 17 18 } - { 21 22 23 24 25 26 27 28 } - { 31 32 33 34 35 36 37 38 } - { 41 42 43 44 45 46 47 48 } } - - in the /Blend dictionary, then the first BBox is { 11 21 31 41 }, - the second { 12 22 32 42 }, etc. - - * include/freetype/internal/psaux.h (T1_FieldType): Add - `T1_FIELD_TYPE_MM_BBOX' (for temporary use). - - * src/psaux/psobjs.c (ps_parser_load_field) : - Implement it. - -2012-12-21 Alexei Podtelezhnikov - - * src/tools/cordic.py: Bring up to date with trigonometric core. - -2012-12-21 Werner Lemberg - - Check parameters of `FT_Outline_New'. - Problem reported by Robin Watts . - - * src/base/ftoutln.c (FT_Outline_New_Internal): Ensure that - `numContours' and `numPoints' fit into FT_Outline's `n_points' and - `n_contours', respectively. - -2012-12-20 Werner Lemberg - - * Version 2.4.11 released. - ========================== - - - Tag sources with `VER-2-4-11'. - - * docs/CHANGES, docs/release: Updated. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.4.11. - - * README, Jamfile (RefDoc), - builds/win32/vc2005/freetype.vcproj, builds/win32/vc2005/index.html, - builds/win32/vc2008/freetype.vcproj, builds/win32/vc2008/index.html, - builds/win32/vc2010/freetype.vcxproj, builds/win32/vc2010/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualc/index.html, builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj, - builds/win32/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.4.10/2.4.11/, s/2410/2411/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 11. - - * builds/unix/configure.raw (version_info): Set to 16:0:10. - - * builds/toplevel.mk (dist): Don't include `.mailmap'. - -2012-12-20 Alexei Podtelezhnikov - - [base] Improve trigonometric core. - - FreeType used to rely on a 24-step iteration CORDIC algorithm to - calculate trigonometric functions and rotate vectors. It turns out - that once the vector is in the right half-plane, the initial rotation - by 63 degrees is not necessary. The algorithm is perfectly capable - to converge to any angle starting from the second 45 degree rotation. - This patch removes the first rotation and makes it a 23-step CORDIC - algorithm. - - * src/base/fttrigon.c (FT_TRIG_SCALE, FT_TRIG_COSCALE): Update macro - values. - (ft_trig_pseudo_rotate, ft_trig_pseudo_polarize): Remove initial - rotation. - -2012-12-19 Werner Lemberg - - * src/base/ftobjs.c (ft_property_do): Fix compiler warning. - -2012-12-19 Alexei Podtelezhnikov - - * src/base/ftrfork.c (FT_Raccess_Guess): Switch to FT_Int counters. - -2012-12-19 Alexei Podtelezhnikov - - [base] Clean up trigonometric core. - - * src/base/fttrigon.c (ft_trig_pseudo_polarize): Align algorithm - with `ft_trig_pseudo_rotate'. - -2012-12-18 Infinality - - [truetype] Minor performance enhancement. - - * src/truetype/ttgload.c: (TT_Process_Simple_Glyph): Use FT_MulFix - instead of FT_MulDiv. - -2012-12-17 Infinality - - [truetype] Remove unused code and variables. - - * src/truetype/ttinterp.c: Updated. - (Ins_FDEF): Remove opcode patterns that are not being used. - -2012-12-16 Werner Lemberg - - Various compiler warning fixes. - - * include/freetype/internal/ftserv.h (FT_SERVICE_UNAVAILABLE): Use - `logical not' operator instead of negation. The idea is that `~' - returns exactly the data type enforced by the cast to a pointer (be - it 32bit or 64bit or whatever), while a negative integer has not - this flexibility. - * src/cache/ftccmap.c (FTC_CMAP_UNKNOWN): Ditto. - * src/truetype/ttgxvar.c (ALL_POINTS, TT_Get_MM_Var): Ditto. - * src/type/t1load.c (T1_Get_MM_Var): Ditto. - (parse_blend_axis_types): Use cast. - * src/bdf/bdflib.c (_bdf_readstream): Use cast. - -2012-12-16 Infinality - - [truetype] Remove unused code and variables. Add minor fixes. - - * src/truetype/ttsubpix.h: Updated. - (SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions): Add Trebuchet MS. - (ALLOW_X_DMOVEX_Rules): Remove Arial characters. - (ALLOW_X_DMOVE_Rules): Remove Arial characters. - (RASTERIZER_35_Rules): Verdana no longer needs to be here. - (SKIP_IUP_Rules): Formatting fix. - (DELTAP_SKIP_EXAGGERATED_VALUES_Rules): Remove Segoe UI. - (COMPATIBLE_WIDTHS_Rules): Add Monaco and Trebuchet MS. - (X_SCALING_Rules): Add misc. corrective fixes. - - * src/truetype/ttgload.c: (TT_Process_Simple_Glyph): Adjust correction - factor for emboldening during scaling. - - * src/truetype/ttinterp.h: Updated. - (TT_ExecContextRec): Remove unused variables. - - * src/truetype/ttobjs.h: Updated. - (TT_SizeRec): Add ttfautohinted variable. - - * src/truetype/ttinterp.c: Updated. - (Ins_FDEF): Rework code to fix bugs and add more detection. - (Ins_CALL): Remove unused code. - (Ins_LOOPCALL): Remove unused code. - (TT_RunIns): Remove unused code. - (Ins_SHPIX): Add logic to handle ttfautohinted fonts. - (Ins_MIRP): Don't round x in cut-in calculation. Add logic to handle - ttfautohinted fonts. - -2012-12-16 Werner Lemberg - - [sfnt] Fix Savannah bug #37936. - - * src/sfnt/ttload.c (tt_face_load_gasp): Avoid memory leak. - -2012-12-15 Alexei Podtelezhnikov - - [base] Fix 11-year old bug. - - Since the initial commit (ebe85f59) the value of FT_TRIG_SCALE has - always been slightly less than the correct value, which has been - given in the comment as a hexadecimal. As a result, vector lengths - were underestimated and rotated vectors were shortened. - - * src/base/fttrigon.c (FT_TRIG_SCALE): Fix macro value. - -2012-12-15 Werner Lemberg - - [bdf] Fix Savannah bug #37907. - - * src/bdf/bdflib.c (_bdf_parse_glyphs) : Normalize - negative second parameter of `ENCODING' field also. - -2012-12-15 Werner Lemberg - - [bdf] Fix Savannah bug #37906. - - * src/bdf/bdflib.c (_bdf_parse_glyphs) : Use correct array - size for checking `glyph_enc'. - -2012-12-15 Werner Lemberg - - [bdf] Fix Savannah bug #37905. - - * src/bdf/bdflib.c (_bdf_parse_start) : Reset - `props_size' to zero in case of allocation error; this value gets - used in a loop in `bdf_free_font'. - -2012-12-10 Alexei Podtelezhnikov - - [truetype] Scale F_dot_P down. - - The dot product between freeVector and projVector or cosine of - the angle between these FT_F2Dot14 unit vectors used to be scaled up - by 4 and routinely occupied 32 bits in an FT_Long field F_dot_P. - This patch scales the value down by 2^14 instead, which simplifies - its use throughout the bytecode interpreter. - - This does not lead to the loss of precision because the lower bits - are unreliable anyway. Consider two unit vectors (1,0) and (.6,.8) - for which the true value of F_dot_P is .6 * 0x40000000 = 0x26666666. - These vectors are stored as (0x4000,0) and (0x2666,0x3333) after - rounding and F_dot_P is assigned 0x26660000. The lower bits were - already lost while rounding the unit vector components. - - Besides code simplification, this change can lead to better - performance when FT_MulDiv with the scaled-down F_dot_P is less - likely to use the costly 64-bit path. We are not changing the type - of F_dot_P to FT_F2Dot14 at this point. - - * src/truetype/ttinterp.c (Compute_Funcs): Scale F_dot_P down by 14 - bits and modify its use accordingly. - (Direct_Move, Direct_Move_Orig, Compute_Point_Displacement): Modify - the use of F_dot_P field. - * src/truetype/ttobjs.c (tt_size_run_fpgm): Change arbitrary - assignment of F_dot_P to its theoretical maximum in case we decide - to scale back its type later. - -2012-12-09 Johnson Y. Yan - - [type1] Another fix for 2012-09-17 commit. - - * src/type1/t1parse.c (T1_Get_Private_Dict) : Correctly set - `limit' value. - -2012-12-06 Alexei Podtelezhnikov - - [truetype] Tweak the previous commit. - - * src/truetype/ttinterp.c (Current_Ratio): Put unit vector - components as the second TT_MulFix14 arguments. This is required - on 16-bit systems. - -2012-12-06 Alexei Podtelezhnikov - - [truetype] Microoptimizations in bytecode interpreter. - - * src/truetype/ttinterp.c (TT_DivFix14): New macro. - (Normalize): Use it here. - (Current_Ratio): Use TT_MulFix14 instead of FT_MulDiv. - (Ins_SHPIX): Cancel out two TT_MulFix14 calls. - -2012-12-05 Alexei Podtelezhnikov - - [truetype] Cosmetic improvement in bytecode interpreter. - - * src/truetype/ttinterp.c: Use explicit calls to FT_MulDiv, - FT_MulFix, and FT_DivFix instead of macros. - -2012-12-03 John Tytgat - - [pshinter] Clamp BlueScale value. - - This is Savannah bug #37856. - - * src/pshinter/pshglob.c (psh_calc_max_height): New function. - (psh_globals_new): Use it to limit BlueScale value to - `1 / max_of_blue_zone_heights'. - -2012-12-01 Alexei Podtelezhnikov - - [truetype, type1] Revise the use of FT_MulDiv. - - * src/truetype/ttgxvar.c: Updated. - * src/truetype/ttobjs.c: Updated. - * src/type1/t1load.c: Updated. - -2012-11-30 Werner Lemberg - - [configure] Preserve customized `ftoption.h'. - - Problem reported by Del Merritt . - - * builds/unix/configure.raw : Don't - remove existing FreeType configuration files. - -2012-11-29 John Tytgat - - [type1] Fix Savannah bug #37831. - - The bug report also contains a patch. - - * src/type1/t1parse.c (T1_Get_Private_Dict) : Really fix - change from 2012-09-17. - -2012-11-28 Alexei Podtelezhnikov - - [truetype] Fix formatting and typo. - -2012-11-27 Alexei Podtelezhnikov - - [cid, type1, type42] Clean up units_per_EM calculations. - - * src/cid/cidload.c (cid_parse_font_matrix): Updated. - * src/type1/t1load.c (t1_parse_font_matrix): Updated. - * src/type42/t42parse.c (t42_parse_font_matrix): Updated. - -2012-11-27 Alexei Podtelezhnikov - - [ftstroke] Minor improvement. - - * src/base/ftstroke.c: Replace nested FT_DivFix and FT_MulFix with - FT_MulDiv. - -2012-11-17 Werner Lemberg - - * src/base/fttrigon.c (ft_trig_downscale): Make 64bit version work. - -2012-11-15 Alexei Podtelezhnikov - - [base] Fix integer overflows in dd5718c7d67a. - - * src/base/ftoutln.c (FT_Outline_EmboldenXY): Use FT_MulDiv. - -2012-11-15 Werner Lemberg - - [autofit] Trace stem widths. - - * src/autofit/aflatin.c (af_latin_metrics_init_widths): Add some - FT_TRACE calls. - -2012-11-13 Werner Lemberg - - [cff] Add support for OpenType Collections (OTC). - - * src/cff/cffload.c (cff_font_load): Separate subfont and face - index handling to load both pure CFFs with multiple subfonts and - OTCs (with multiple faces where each face holds exactly one - subfont). - * src/cff/cffobjs.c (cff_face_init): Updated. - -2012-11-12 Werner Lemberg - - [autofit] Minor improvement. - - * src/autofit/aflatin.c (af_latin_hints_compute_blue_edges): Fix - loop. - -2012-11-10 Werner Lemberg - - [autofit] Improve tracing. - - * src/autofit/aflatin.c (af_latin_hint_edges) - [FT_DEBUG_LEVEL_TRACE]: Count number of actions and emit something - if there weren't any. - -2012-11-04 Alexei Podtelezhnikov - - [base] Fortify emboldening code against egregious distortions. - - * src/base/ftoutln.c (FT_Outline_EmboldenXY): Threshold emboldening - strength when it leads to segment collapse. - -2012-11-03 Alexei Podtelezhnikov - - [base] Clean up emboldening code and improve comments there. - - * src/base/ftoutln.c (FT_Outline_EmboldenXY): Replace sequential - calls to FT_MulFix and FT_DivFix with FT_MulDiv. - Mention that bisectors are used to figure out the shift direction. - -2012-10-24 Werner Lemberg - - [autofit] Add standard character to `AF_ScriptClassRec' structure. - - * src/autofit/aftypes.h (AF_ScriptClassRec): Add `standard_char' - member. - (AF_DEFINE_SCRIPT_CLASS): Updated. - - * src/autofit/aflatin.c (af_latin_metrics_init_widths): Use it. - (af_latin_metrics_init, af_latin_script_class): Updated. - - * src/autofit/aflatin.c (af_latin2_metrics_init_widths): Use it. - (af_latin2_metrics_init, af_latin2_script_class): Updated. - - * src/autofit/afcjk.c (af_cjk_metrics_init_widths): Use it. - (af_cjk_metrics_init, af_cjk_script_class): Updated. - - * src/autofit/afindic.c (af_indic_metrics_init, - af_indic_script_class): Updated. - - * src/autofit/afcjk.h, src/autofit/aflatin.h: Updated. - - * src/autofit/afdummy.c: Updated. - -2012-10-24 Werner Lemberg - - [autofit] Only use Unicode CMap. - - * src/autofit/aflatin.c (af_latin_metrics_init): Implement it, to be - in sync with `af_face_globals_compute_script_coverage'. - -2012-10-21 Werner Lemberg - - [psaux] Improve parsing of invalid numbers. - - * src/psaux/psconv.c (PS_Conv_Strtol): Always parse complete number, - even in case of overflow. - (PS_Conv_ToInt): Only increase cursor if parsing was successful. - (PS_Conv_ToFixed): Ditto. - Trace underflow and data error. - -2012-10-21 Werner Lemberg - - [smooth] Improve tracing. - - * src/smooth/ftgrays.c (gray_sweep): Trace last sweep line of - current band also. - -2012-10-20 Alexei Podtelezhnikov - - [truetype] Cheaper way to threshold angles between vectors. - - * src/truetype/ttinterp.c (Ins_ISECT): Thresholding tangent is a lot - cheaper than thresholding sine. - -2012-10-20 Werner Lemberg - - [cff] Improve parsing of invalid real numbers. - - * src/cff/cffparse.c (cff_parse_real): Always parse complete number, - even in case of overflow or underflow. - Also trace one more underflow. - -2012-10-20 Andreas Pehnack - - [sfnt] Load pure CFF fonts wrapped in SFNT container. - - Such fonts only have a `cmap' and a `CFF' table. - - * src/sfnt/ttload.c (tt_face_load_font_dir): Don't call - `check_table_dir' if font signature is `OTTO'. - -2012-10-20 Werner Lemberg - - [psaux] Fix some value overflows and improve tracing. - - * src/psaux/psconv.c: Include FT_INTERNAL_DEBUG_H. - (FT_COMPONENT): Define. - (PS_Conv_Strtol): Return FT_Long. - Handle bad data and overflow. - Emit some tracing messages in case of error. - (PS_Conv_ToInt): Return FT_Long. - (PS_Conv_ToFixed): Updated. - * src/psaux/psconv.h: Updated. - - * include/freetype/internal/fttrace.h: Add `psconv'. - -2012-10-20 Werner Lemberg - - [autofit] Fix `make multi CC=c++'. - - * src/autofit/aflatin.c, src/autofit/aflatin2.c: Include - `afglobal.h'. - * src/autofit/afloader.c: Fix order of header files. - * src/autofit/afmodule.c: Include `afglobal.h' and `aferrors.h'. - -2012-10-19 Werner Lemberg - - [cff] Fix more value errors and improve tracing. - - * src/cff/cffparse.c (cff_parse_integer): Emit tracing message in - case of error. - (cff_parse_real): Handle and trace overflow, underflow, and bad data - consistently. - (do_fixed): New helper function, handling and tracing overflow. - (cff_parse_fixed, cff_parse_fixed_scaled): Use `do_fixed'. - -2012-10-17 Werner Lemberg - - [psaux] Fix some value overflows. - - * src/psaux/psconv.c (PS_Conv_ToFixed): Implement it. - -2012-10-17 Bram Tassyns - - [cff] Fix value overflow. - - * src/cff/cffparse.c (cff_parse_fixed_scaled): Implement it. - -2012-10-17 Werner Lemberg - - [truetype] Fix Savannah bug #37572. - - * src/truetype/ttinterp.c (Ins_ISECT): Use angle between vectors to - avoid grazing intersections. The previous threshold was too coarse, - incorrectly rejecting short but valid vectors. - -2012-09-30 Gilles Espinasse - - Remove useless `rm' detection. - - `rm -f' is directly used in the `configure' script created by - autoconf, thus no availability test is necessary. - - * builds/unix/configure.raw (RMF): Remove test. - * builds/unix/unix-def.in (DELETE): Updated. - -2012-09-29 Werner Lemberg - - [autofit] Minor optimization. - - * src/autofit/afglobal.c (af_face_globals_compute_script_coverage): - Add loop condition. - -2012-09-29 Werner Lemberg - - [autofit] Fix thinko. - - * src/autofit/aftypes.h (AF_SCRIPT): - s/AF_SCRIPT_NONE/AF_SCRIPT_DUMMY/. We already use `AF_SCRIPT_NONE' - as a bit mask. - - * src/autofit/afdummy.c: Updated. - -2012-09-18 Werner Lemberg - - [autofit] Implement `increase-x-height' property. - - * include/freetype/ftautoh.h (FT_Prop_IncreaseXHeight): New - structure. - - * include/autofit/afmodule.c (af_property_get_face_globals): New - function, re-using code from `af_property_get'. - (af_property_set, af_property_get): Handle `increase-x-height'. - Updated. - -2012-09-18 Werner Lemberg - - [autofit] Implement Infinality's `increase glyph heights'. - - This is an improved version of a similar fix contained in the - so-called `Infinality patch', taken from - - http://www.infinality.net/fedora/linux/zips/freetype-infinality-2.4.10-20120616_01-x86_64.tar.bz2 - - which addresses various enhancements of the auto-hinter. Without - properties to control a module's metadata it wasn't possible to - adapt the patches because everything was originally controlled by - environment variables which I consider not suitable in general. - - A patch to control `increase_x_height' follows. - - * src/autofit/afglobal.h (AF_PROP_INCREASE_X_HEIGHT_MIN, - AF_PROP_INCREASE_X_HEIGHT_MAX): New macros. - (AF_FaceGlobalsRec): Add `increase_x_height' member. - * src/autofit/afglobal.c (af_face_globals_new): Initialize it. - - * src/autofit/aflatin.c (af_latin_metrics_scale_dim), - * src/autofit/aflatin2.c (af_latin2_metrics_scale_dim): Implement - handling of `increase_x_height'. - -2012-09-18 Werner Lemberg - - [autofit] Add hierarchical property access to some structures. - - * src/autofit/afglobal.h: Include `afmodule.h'. - (AF_FaceGlobalsRec): Add `module' member. - (AF_FaceGlobals): Typedef moved to... - * src/autofit/aftypes.h: Here. - (AF_ScriptMetricsRec): Add `globals' member. - - * src/autofit/afglobal.c (af_face_globals_new, - af_face_globals_compute_script_coverage, - af_face_globals_get_metrics): Updated. - - * src/autofit/afloader.c (af_loader_reset), src/autofit/afmodule.c - (af_property_get): Updated. - -2012-09-17 Werner Lemberg - - [type1] Fix Savannah bug #37350. - - * src/type1/t1parse.c (T1_Get_Private_Dict) : Check for ASCII - storage only if we actually have at least four bytes. - -2012-09-15 Werner Lemberg - - [autofit] Implement `fallback-script' property. - - * src/autofit/afglobal.c: s/default_script/fallback_script/. - * src/autofit/afglobal.h: s/AF_SCRIPT_DEFAULT/AF_SCRIPT_FALLBACK/. - - * src/autofit/afmodule.c: s/default_script/fallback_script/. - (af_property_set, af_property_get): Implement `fallback-script'. - * src/autofit/afmodule.h: s/default_script/fallback_script/. - - * include/freetype/ftautoh.h: Document it. - -2012-09-15 Werner Lemberg - - [autofit] Correct previous Unicode 6.1.0 change. - - The auto-hinter's latin module only handles latin ligatures in the - `Alphabetical Presentation Forms' block. - - * src/autofit/aflatin.c (af_latin_uniranges): Fix it. - -2012-09-15 Werner Lemberg - - * src/autofit/afmodule.c: s/FT_Err_/AF_Err_/. - -2012-09-15 Werner Lemberg - - [autofit] Make default script a global property. - - * src/autofit/afmodule.h (AF_ModuleRec): Add `default_script' field. - - * src/autofit/afglobal.c (af_face_globals_compute_script_coverage, - af_face_globals_new), src/autofit/afloader.c (af_loader_reset), - src/autofit/afmodule.c (af_property_get) , - af_autofitter_init: - Handle default script. - - * src/autofit/afglobal.h: Updated. - -2012-09-15 Werner Lemberg - - Use `FT_Module' instead of `FT_Library' argument in property funcs. - - This internal change simplifies access to global module data. - - * include/freetype/internal/services/svprop.h - (FT_Properties_SetFunc, FT_Properties_GetFunc): Change accordingly. - - * src/base/ftobjs.c (ft_property_do), src/autofit/afmodule.c - (af_property_set, af_property_get): Updated. - -2012-09-14 Werner Lemberg - - [autofit] Update to Unicode 6.1.0. - - * src/autofit/afcjk.c (af_cjk_uniranges), src/autofit/aflatin.c - (af_latin_uniranges): Add and fix ranges. - -2012-09-14 Werner Lemberg - - [autofit] Pass `AF_Module' instead of `AF_Loader'. - - We want to access the (not yet existing) module's global data later - on. - - * src/autofit/afloader.c: Include `afmodule.h'. - (af_loader_init, af_loader_reset, af_loader_done, - af_loader_load_glyph): Change accordingly. - * src/autofit/afmodule.c (AF_ModuleRec): Move to `afmodule.h'. - Updated. - - * src/autofit/afmodule.h: Include `afloader.h'. - (AF_ModuleRec): Define here. - * src/autofit/afloader.h (AF_Module): Define here. - Updated. - -2012-09-14 Werner Lemberg - - [autofit] Fix `make multi'. - - * include/freetype/internal/fttrace.h: Add `afmodule'. - * src/autofit/afmodule.c: Include FT_INTERNAL_DEBUG_H. - (FT_COMPONENT): Define. - -2012-09-14 Werner Lemberg - - * src/autofit/afmodule.c: s/FT_Autofitter/AF_Module/. - -2012-09-12 Werner Lemberg - - [autofit] Minor reorganization. - - * src/autofit/afglobal.c (AF_SCRIPT_LIST_DEFAULT, - AF_SCRIPT_LIST_NONE, AF_DIGIT): Move to... - * src/autofit/afglobal.h (AF_SCRIPT_DEFAULT, AF_SCRIPT_LIST_NONE, - AF_DIGIT): This and update code. - -2012-09-01 Werner Lemberg - - [autofit] Implement `glyph-to-script-map' property. - - * include/freetype/ftautoh.h: New public header file. - * include/freetype/config/ftheader.h (FT_AUTOHINTER_H): New macro. - - * src/autofit/afglobal.c (AF_FaceGlobalsRec): Move structure to... - * src/autofit/afglobal.h: This header file. - * src/autofit/afmodule.c: Include FT_AUTOHINTER_H. - (af_property_get): Handle `glyph-to-script-map'. - -2012-08-31 Werner Lemberg - - [autofit] Implement properties service framework. - - No properties are added yet. - - * src/autofit/afmodule.c: Include FT_SERVICE_PROPERTIES_H. - (af_property_set, af_property_get): New dummy functions. - (af_service_properties, af_services, af_get_interface): Provide - service setup. - (autofit_moduleclass): Add service interface. - - * src/autofit/afpic.c: Add necessary forward declarations. - (autofit_module_class_pic_init): Add code for service addition. - (autofit_module_pic_free): Add code for service removal. - * src/autofit/afpic.h (AF_SERVICES_GET, AF_SERVICE_PROPERTIES_GET): - New macros which provide necessary syntactical sugar for PIC - support. - -2012-08-30 Werner Lemberg - - Implement properties to control FreeType modules. - - * include/freetype/fterrdef.h (FT_Err_Missing_Property): New error - code. - * include/freetype/ftmodapi.h (FT_Property_Set, FT_Property_Get): - New API. - - * include/freetype/internal/services/svprop.h: New file. - * include/freetype/internal/ftserv.h (FT_SERVICE_PROPERTIES_H): New - macro. - - * src/base/ftobjs.c: Include FT_SERVICE_PROPERTIES_H. - (ft_property_do, FT_Property_Set, FT_Property_Get): New functions. - -2012-08-29 Werner Lemberg - - [docmaker] Allow `-' in tags and identifiers. - - * src/tools/docmaker/content.py (re_identifier), - src/tools/docmaker/sources.py (re_markup_tag1, re_markup_tag2, - re_crossref): Add `-' in patterns. - -2012-08-27 Werner Lemberg - - [FT_CONFIG_OPTION_PIC] Fix g++ 4.6.2 compiler warnings. - - * include/freetype/internal/ftdriver.h (FT_DEFINE_DRIVER), - include/freetype/internal/ftobjs.h (FT_DEFINE_RENDERER, - FT_DEFINE_MODULE), include/freetype/internal/ftserv.h - (FT_DEFINE_SERVICEDESCREC1, FT_DEFINE_SERVICEDESCREC2, - FT_DEFINE_SERVICEDESCREC3, FT_DEFINE_SERVICEDESCREC4, - FT_DEFINE_SERVICEDESCREC5, FT_DEFINE_SERVICEDESCREC6), - src/autofit/afpic.c (autofit_module_class_pic_init), - src/base/basepic.c (ft_base_pic_init), src/base/ftinit.c - (ft_create_default_module_classes), src/cff/cffparse.c - (FT_Create_Class_cff_field_handlers), src/cff/cffpic.c - (cff_driver_class_pic_init), src/pshinter/pshpic.c - (pshinter_module_class_pic_init), src/psnames/pspic.c - (psnames_module_class_pic_init), src/raster/rastpic.c - (ft_raster1_renderer_class_pic_init), src/sfnt/sfntpic.c - (sfnt_module_class_pic_init), src/sfnt/ttcmap.c - (FT_Create_Class_tt_cmap_classes), src/smooth/ftspic.c - (ft_smooth_renderer_class_pic_init), src/truetype/ttpic.c - (tt_driver_class_pic_init): Initialize allocation variable. - -2012-08-27 Werner Lemberg - - [truetype] Fix compilation warning. - - * src/truetype/ttgload.c (IS_HINTED): Move macro to... - * src/truetype/ttobjs.h: This header file. - -2012-08-27 Werner Lemberg - - [autofit, cff, pshinter, psnames] More renamings for orthogonality. - - * src/autofit/afmodule.c, src/autofit/afpic.h: - s/AF_AUTOFITTER_/AF_/. - - * src/cff/cffdrivr.c, src/cff/cffobjs.c, src/cff/cffparse.c, - src/cff/cffpic.h: s/FT_CFF_/CFF_/. - - * src/pshinter/pshmod.c, src/pshinter/pshpic.h: - s/FT_PSHINTER_/PSHINTER_/. - - * src/psnames/psmodule.c, src/psnames/pspic.h: - s/FT_PSCMAPS/PSCMAPS_/. - -2012-08-27 Werner Lemberg - - [sfnt, truetype] More renamings for orthogonality. - - * src/sfnt/sfdriver.c, src/sfnt/sfntpic.h, src/sfnt/ttcmap.c, - src/truetype/ttdriver.c, src/truetype/ttpic.h: s/FT_SFNT_/SFNT_/, - s/FT_TT_/TT_/, s/GET_CMAP_INFO_GET/CMAP_INFO_GET/. - -2012-08-27 Werner Lemberg - - [autofit] Some macro and variable renamings for orthogonality. - - * include/freetype/internal/autohint.h, src/base/ftobjs.c, - src/autofit/afmodule.c, src/autofit/afpic.c, src/autofit/afpic.h: - s/SERVICE/INTERFACE/, s/service/interface/, s/Service/Interface/. - -2012-08-26 Werner Lemberg - - Fix Savannah bug #37178. - - * src/base/ftobjs.c (FT_Open_Face): Initialize `error' with - `FT_Err_Missing_Module' before loop to indicate `no valid drivers'. - -2012-08-17 Werner Lemberg - - * src/base/ftsynth.c (FT_GlyphSlot_Oblique): Fix shear angle. - - The old value was far too large (more than 20°). The new one - corresponds to 12°, quite common in typography. - -2012-08-12 Alexei Podtelezhnikov - - [smooth] Fix Savannah bug #37017. - - * src/smooth/ftgrays.c (gray_render_cubic): Use a different set of - checks when detecting super curvy splines to be split. - -2012-08-05 Werner Lemberg - - [autofit] Improve recognition of flat segments. - - Problem reported by Brad Dunzer . - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): We have - a flat segment if the horizontal distance of best on-points is - larger than a given threshold. - -2012-08-05 Werner Lemberg - - [autofit] Variable renamings. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Replace - `glyph' with `outline'. - s/best_first/best_contour_first/. - s/best_last/best_contour_last/. - -2012-07-31 Werner Lemberg - - [type1] Fix Savannah bug #37000. - - * src/type1/t1load.c (parse_encoding): Fix order of checks. - -2012-07-17 Werner Lemberg - - [psaux] Fix Savannah bug #36833. - - * src/psaux/t1decode.c (t1operator_seac): `seac' is not a valid - operator if we want metrics only. - -2012-07-16 Werner Lemberg - - [type1] Fix Savannah bug #36832. - - * src/type1/t1load.c (parse_charstrings): Reject negative number of - glyphs. - -2012-07-13 Werner Lemberg - - [type1] Fix Savannah bug #36829. - - * src/type1/t1load.c (parse_encoding): Check cursor position after - call to T1_Skip_PS_Token. - -2012-07-12 Alexei Podtelezhnikov - - Revert the last commit 45337b07. - - * src/base/ftstroke.c (FT_Stroker_New): Revert the previous change. - -2012-07-11 Alexei Podtelezhnikov - - [ftstroke] Fix uninitialized return value. - - * src/base/ftstroke.c (FT_Stroker_New): Return FT_Err_Ok instead. - -2012-07-11 Werner Lemberg - - [smooth] Avoid memory leak in case of failure. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Use flags to - indicate what to clean up after finishing the function, with and - without errors. - -2012-07-09 Werner Lemberg - - Fix compilation with MSVC 5.0. - - Problem reported by Peter Breitenlohner and Akira Kakuto. - - * include/freetype/config/ftstdlib.h (ft_setjmp): Updated. - * src/sfnt/ttcmap.c (tt_face_build_cmaps): Remove cast. - -2012-07-09 Werner Lemberg - - [autofit] Improve debugging messages; do some code cleanup. - - * src/autofit/aflatin.c (af_latin_align_linked_edge, - af_latin_hint_edges): Synchronize with formatting used in the - ttfautohint project. - -2012-07-07 Gilles Espinasse - - Fix strict-aliasing warning. - - * src/base/ftglyph.c (FT_Glyph_To_Bitmap): Avoid double cast. - -2012-07-07 Dave Thomas - - [ARM] Fix FT_MulFix_arm. - - * include/freetype/config/ftconfig.h (FT_MulFix_arm) [__arm__]: - Avoid ADDS instruction to clobber condition codes. - -2012-07-06 Werner Lemberg - - [autofit] Do some code cleanup. - - * src/autofit/afglobal.c (af_face_globals_new): Simplify. - - * src/autofit/afhints.c: Use `FT_TRACE7' instead of `printf' - everywhere. - (FT_COMPONENT): New macro. - (af_glyph_hints_done): Simplify. - - * include/freetype/internal/fttrace.h: Updated. - -2012-07-05 Werner Lemberg - - [autofit] Improve output of debugging information. - - * src/autofit/afhints.c (af_glyph_hints_dump_segments): Print more - data; report no data. - (af_glyph_hints_dump_edges): Report no data. - -2012-07-04 Werner Lemberg - - [autofit] Fix Savannah bug #36091. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues), - src/autofit/aflatin2.c (af_latin2_metrics_init_blues): Change the - constraint for testing round vs. flat segment: Accept either a - small distance or a small angle. - -2012-07-04 Werner Lemberg - - [autofit] Beautify blue zone tracing. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues), - src/autofit/aflatin2.c (af_latin2_metrics_init_blues): Implement it. - -2012-07-03 Werner Lemberg - - [autofit] Quantize stem widths. - - * src/autofit/afangles.c (af_sort_widths): Rename to... - (af_sort_and_quantize_widths): This. - Add code to avoid stem widths which are almost identical. - * src/autofit/aftypes.h, src/autofit/aflatin.c, src/autofit/afcjk.c: - Updated. - -2012-07-03 Werner Lemberg - - [autofit] Minor speed-up. - - * src/autofit/afangles (af_sort_pos, af_sort_widths): Don't swap - elements if they are equal. - -2012-06-30 Gilles Espinasse - - Fix `checking if gcc static flag -static works' test. - - On my linux build tree, I receive yes answer in every package I - build except FreeType for this test checking if gcc static flag - `-static' works - - In FreeType, no is received, unless bzip2 and zlib are disabled using - - ./configure --without-bzip2 --without-zlib - - The reason is that bzip2 and zlib tests add `-lz' and `-lbz2' to - LDFLAGS and this broke static flag test. - - * builds/unix/configure.raw: Update CFLAGS and LDFLAGS only after - LT_INIT has run. - -2012-06-28 Infinality - - [truetype] Fix various artifacts. - - Verdana was broken in the original Infinality commit. Also - includes other minor fixes. - - * src/truetype/ttsubpix.h: Updated. Removed unused macros. - (RASTERIZER_35_Rules): Add Verdana. - (SKIP_NONPIXEL_Y_MOVES_Rules): Add Tahoma `s'. - (MIRP_CVT_ZERO_Rules): Remove Verdana. - (ALWAYS_SKIP_DELTAP_Rules): Add Russian char 0x438. - (COMPATIBLE_WIDTHS_Rules): Rearrange some rules. - (X_SCALING_Rules): Adjust Verdana `a' at 12 and 13 ppem. - - * src/truetype/ttsubpix.c: Updated. - (sph_set_tweaks): Re-execute fpgm always. - -2012-06-28 Gilles Espinasse - - Fix CFLAGS and LDFLAGS share configure test. - - * builds/unix/configure.raw: Fix typo. - -2012-06-28 Werner Lemberg - - [truetype] Set the `subpixel_positioned' flag unconditionally. - - This is how the code currently behaves. - - * src/truetype/ttgload.c (tt_loader_init): Do it. - -2012-06-27 Werner Lemberg - - Fix conditional compilation. - - * src/base/basepic.c: Use FT_CONFIG_OPTION_MAC_FONTS. - -2012-06-27 Werner Lemberg - - Fix conditional compilation. - - * include/freetype/internal/ftcalc.h (FT_MulDiv_No_Round): Don't - enclose with `TT_USE_BYTECODE_INTERPRETER'; we now need the function - elsewhere also. - - * src/autofit/afcjk.h: Use AF_CONFIG_OPTION_CJK. - - * src/truetype/ttgload.c (tt_loader_init): Fix compiler warning. - - * src/truetype/ttinterp.c (Ins_MSIRP): Fix compiler warning. - - * src/truetype/ttinterp.h: Use - TT_CONFIG_OPTION_BYTECODE_INTERPRETER. - -2012-06-26 Infinality - - [truetype] Remove unused rounding functionality. - - The subpixel hinting patch contained the concept of an adjustable - number of gridlines per pixel. This is no longer used due to x - being completely ignored instead. This will return some of the - code to its existing state prior to the original Infinality - commit. - - * include/freetype/internal/ftobjs.h (FT_PIX_FLOOR_GRID, - FT_PIX_ROUND_GRID, FT_PIX_CEIL_GRID): Removed. - - * src/truetype/ttinterp.c: Updated. - (Round_None, Round_To_Grid, Round_To_Half_Grid, Round_Down_To_Grid, - Round_Up_To_Grid, Round_To_Double_Grid, Round_Super, Round_Super_45, - SetSuperRound): Remove parameter to handle the number of grid lines per - pixel. - (SET_SuperRound, ROUND_None, CUR_Func_round): Updated. - (DO_SROUND, DOS45ROUND, DO_ODD, DO_EVEN): Updated. - (DO_ROUND, DO_NROUND): Updated. - (Move_Zp2_Point, Ins_SHPIX, Ins_MSIRP, Ins_MDAP, Ins_MIAP, - Ins_MDRP, Ins_MIRP): Perform Round_None instead of calling a modified - rounding function. Remove gridlines_per_pixel. Create a local - variable to store control value cutin. Simplify the conditional for - ignore_x_mode. Adjust rounding calls to pass only two values. - -2012-06-25 Werner Lemberg - - [cff] Fix Savannah bug #36705. - - Handle numbers like 2.001 correctly. - - * src/cff/cffparse.c (cff_parse_real): Avoid negative values for - `shift'. - -2012-06-18 Infinality - - [truetype] Support subpixel hinting. - - This is the large, famous `Infinality' patch to support ClearType - bytecode which has been available from - http://www.infinality.net/blog/ for some time, and which has been - refined over the last years. While still experimental, it is now - mature enough to be included directly into FreeType. - - Most of the code is based on the ClearType whitepaper written by - Greg Hitchcock - - https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx - - which gives a detailed overview of the necessary changes to the - Microsoft rasterizer so that older fonts are supported. However, a - lot of details are still missing, and this patches provides a - framework to easily handle rendering issues down to the glyph level - of certain fonts. - - Note that ClearType support is not completely implemented! In - particular, full support for the options `compatible_widths', - `symmetrical_smoothing, and `bgr' (via the GETINFO bytecode - instruction) is missing. - - * src/truetype/ttsubpix.c: New file, providing code to handle - `tweaks', this is, rules for certain glyphs in certain fonts - (including wildcards) which need a special treatment. - - * src/truetype/ttsubpix.h: New file, holding the tweaking rules. - - * include/freetype/config/ftoption.h, src/devel/ftoption.h - (TT_CONFIG_OPTION_SUBPIXEL_HINTING): New macro. - - * include/freetype/internal/ftobjs.h (FT_PIX_FLOOR_GRID, - FT_PIX_ROUND_GRID, FT_PIX_CEIL_GRID): New macros. - - * src/truetype/truetype.c [TT_USE_BYTECODE_INTERPRETER]: Include - `ttsubpix.c'. - - * src/truetype/ttgload.c: Include `ttsubpix.h'. - [All changes below are guarded by TT_CONFIG_OPTION_SUBPIXEL_HINTING.] - - (tt_get_metrics): Set tweak flags. - (TT_Hint_Glyph): Call `FT_Outline_EmboldenXY' if necessary. - (TT_Process_Simple_Glyph): Compensate emboldening if necessary. - (compute_glyph_metrics): Handle `compatible widths' option. - (tt_loader_init): Handle ClearType GETINFO information bits. - - * src/truetype/rules.mk (TT_DRV_SRC): Updated. - - * src/truetype/ttinterp.c: Include `ttsubpix.h'. - [Where necessary, changes below are guarded by - TT_CONFIG_OPTION_SUBPIXEL_HINTING.] - - (Direct_Move, Direct_Move_X): Extended. - (Round_None, Round_To_Grid, Round_To_Half_Grid, Round_Down_To_Grid, - Round_Up_To_Grid, Round_To_Double_Grid, Round_Super, Round_Super_45, - SetSuperRound): Add parameter to handle the number of grid lines per - pixel. - (SET_SuperRound, ROUND_None, CUR_Func_round): Updated. - (DO_SROUND, DOS45ROUND, DO_ODD, DO_EVEN): Updated. - (DO_ROUND, DO_NROUND): Updated. - (DO_RS): Take care of `Typeman' bytecode patterns. - (Ins_FDEF): Add some debugging code. Commented out. - (Ins_ENDF): Restore state. - (Ins_CALL, Ins_LOOPCALL): Handle inline delta functions. - (Ins_MD): Handle `Vacuform' rounds. - (Move_Zp2_Point, Ins_SHPIX, Ins_MSIRP, Ins_MDAP, Ins_MIAP, - Ins_MDRP, Ins_MIRP): Handle tweaks. - (Ins_ALIGNRP): Add tweak guard. - (Ins_IUP, Ins_DELTAP): Handle tweaks. - (Ins_GETINFO): Handle new ClearType bits. - (TT_RunIns): Handle tweaks. - - * src/truetype/ttinterp.h: Updated. - (SPH_TweakRule, SPH_ScaleRule): New structures for tweaks. - (TT_ExecContextRec): Add members for subpixel hinting support. - - * src/truetype/ttobjs.h (TT_DefRecord): Add `inline_delta' member. - -2012-06-15 Werner Lemberg - - * Version 2.4.10 released. - ========================= - - - Tag sources with `VER-2-4-10'. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.4.10. - - * README, Jamfile (RefDoc), - builds/win32/vc2005/freetype.vcproj, builds/win32/vc2005/index.html, - builds/win32/vc2008/freetype.vcproj, builds/win32/vc2008/index.html, - builds/win32/vc2010/freetype.vcxproj, builds/win32/vc2010/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualc/index.html, builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj, - builds/win32/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.4.9/2.4.10/, s/249/2410/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 10. - - * builds/unix/configure.raw (version_info): Set to 15:0:9. - -2012-06-15 Alexei Podtelezhnikov - - * src/base/ftsynth.c (FT_GlyphSlot_Embolden): Improve spacing. - - * docs/CHANGES: Updated. - -2012-06-14 suzuki toshiya - - * builds/exports.mk: Add CCexe_CFLAGS and CCexe_LDFLAGS. - - to pass special compiler/linker flags under cross development. - Suggested by Savannah bug #36367. - - ChangeLog on 2010-07-15 saying as they were removed was wrong - for the official trunk of FreeType2. This commit is the first - introduction of them. - -2012-06-14 Werner Lemberg - - * docs/CHANGES: Updated. - -2012-06-14 suzuki toshiya - - [truetype] Add new versions of NEC FA family to tricky font list. - - NEC FA family dated in 1996 have different checksum. - Reported by Johnson Y. Yan ; see - - https://lists.gnu.org/archive/html/freetype-devel/2012-06/msg00023.html - - * src/truetype/ttobjs.c (tt_check_trickyness_sfnt_ids): 4 sets - of fpgm & prep table checksums for FA-Gothic, FA-Minchou, - FA-RoundedGothicM, FA-RoundedGothicB are added. The family - names in sample PDF are truncated, thus the list of the - family names in tt_check_trickyness_family() is not updated yet. - -2012-06-06 Werner Lemberg - - [ftraster] Fix rounding issue causing visual artifacts. - - Problem reported by jola ; see - - https://lists.gnu.org/archive/html/freetype-devel/2012-05/msg00036.html - - * src/raster/ftraster.c (SMulDiv_No_Round): New macro. - (Line_Up): Use it. - * src/raster/ftmisc.h (FT_MulDiv_No_Round): Copied from `ftcalc.c'. - -2012-05-28 Alexei Podtelezhnikov - - * src/base/ftoutln.c (FT_Outline_Get_Orientation): Simplify. - - We now use the cross product of the direction vectors to compute the - outline's orientation. - -2012-05-28 Werner Lemberg - - * docs/CHANGES: Updated. - -2012-05-28 Alexei Podtelezhnikov - - New function FT_Outline_EmboldenXY. - - * include/freetype/ftoutln.h (FT_Outline_EmboldenXY): Define it. - - * src/base/ftoutln.c (FT_Outline_EmboldenXY): Implement it, using a - simplified emboldening algorithm. - (FT_Outline_Embolden): Make it a special case of - `FT_Outline_EmboldenXY' - -2012-05-07 Werner Lemberg - - [type1] Fix Savannah bug #36386. - - * src/type1/t1load.c (t1_load_keyword): Ignore keyword if context is - not valid. - -2012-04-07 Werner Lemberg - - Remove compiler warning. - - * src/truetype/ttgload.c (TT_Load_Glyph) - [!TT_CONFIG_OPTION_EMBEDDED_BITMAPS]: Access `glyph->face' directly. - -2012-03-28 Werner Lemberg - - [autofit] Properly copy scaler flags to script metrics object. - - Without this patch, only the dummy and cjk autohinter modules get - them (since they copy the whole scaler object). - - * src/autofit/aflatin.c (af_latin_metrics_scale), - src/autofit/aflatin2.c (af_latin2_metrics_scale): Implement it. - -2012-03-22 Alexei Podtelezhnikov - - [bdflib] Remove redundant macro. - - * src/bdf/bdflib.c (isdigok): Remove and replace with sbitset, which - is exactly the same. - -2012-03-20 suzuki toshiya - - [configure] Fix Savannah bug #35644. - - * builds/unix/configure.raw: Check `-ansi' flag works even if gcc - is used. Bionic libc headers for Android lose the consistency - when they are parsed with __STDC_VERSION__ older than 199901L or - __STRICT_ANSI__. - -2012-03-20 Werner Lemberg - - [bdf] Improvement to Savannah bug #35656. - - * src/bdf/bdflib.c (isdigok): Add cast, as suggested in report. - -2012-03-17 Chris Liddell - - [type1] Fix Savannah bug #35847. - - * src/type1/t1load.c (parse_subrs): Fix the loop exit condition; - we want to exit when we have run out of data. - -2012-03-16 Werner Lemberg - - [bdf] Really fix Savannah bug #35658. - - * src/bdf/bdflib.c (_bdf_list_split): Add one more `field' initializer. - -2012-03-14 Yann Droneaud - - [sfnt] Make arrays static like all others. - - * src/sfnt/ttload.c (tt_face_load_maxp, tt_face_load_os2), - src/sfnt/ttmtx.c (tt_face_load_hhea): Add `static' keyword to frame - fields. - -2012-03-14 Huw Davies - - [sfnt] A refinement of the previous commit. - - * src/sfnt/sfobjs.c (tt_name_entry_ascii_from_utf16, - tt_name_entry_ascii_from_other): Stop at null byte. - -2012-03-14 Huw Davies - - [sfnt] Add `name' table compatibility to MS Windows. - - * src/sfnt/sfobjs.c (tt_name_entry_ascii_from_utf16, - tt_name_entry_ascii_from_other): Don't replace `\0' with question - marks when converting strings. - -2012-03-14 Werner Lemberg - - [type1] Fix Savannah bug #35833. - - Based on the patch given in the bug report. - - * src/type1/t1load.c (IS_INCREMENTAL): New macro. - (read_binary_data): Add parameter `incremental'. - Update all callers using `IS_INCREMENTAL'. - -2012-03-11 Werner Lemberg - - [autofit] Return correct linear advance width values. - - This was quite a subtle bug which accidentally showed up with glyph - `afii10023' of arial.ttf (version 2.76). This glyph is a composite; - the first component, `E', has an advance width of 1366 font units, - while the advance width of the composite itself (which looks like - uppercase `E' with dieresis) is 1367 font units. I think this is - actually a bug in the font itself, because there is no reason that - this glyph has not the same width as uppercase `E' without the - dieresis. Anyway, it helped identify this problem. - - Using the TrueType hinter, the correct value (1367) of `afii10023' - was returned, but the autohinter mysteriously returned 1366. - - Digging in the code showed that the autohinter recursively calls - FT_Load_Glyph to load the glyph, adding the FT_LOAD_NO_SCALE load - flag. However, the `linearHoriAdvance' field is still returned as a - scaled value. To avoid scaling twice, the old code in autofit reset - `linearHoriAdvance', using the `horiAdvance' field. This seemed to - work since FT_LOAD_NO_SCALE was in use, but it failed actually, - because `horiAdvance' is defined as the distance of the first - subglyph's phantom points, which in turn are initialized using the - advance width of the first subglyph. And as the given example - shows, these widths can differ. - - * src/autofit/afloader.c (af_loader_load_g): Temporarily set - FT_LOAD_LINEAR_DESIGN while calling FT_Load_Glyph to get unscaled - values for the linear advance widths. - -2012-03-10 Werner Lemberg - - [truetype] Fix SSW instruction. - - * src/truetype/ttinterp.c (DO_SSW): SSW *does* use font units. For - verification, it took some time to find a font which actually uses - this instruction. - -2012-03-09 Vinnie Falco - - Prepare source code for amalgamation. - - * include/freetype/freetype.h: Swap order of preprocessor blocks. - -2012-03-08 Werner Lemberg - - * Version 2.4.9 released. - ========================= - - - Tag sources with `VER-2-4-9'. - - * docs/CHANGES: Updated. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.4.9. - - * README, Jamfile (RefDoc), - builds/win32/vc2005/freetype.vcproj, builds/win32/vc2005/index.html, - builds/win32/vc2008/freetype.vcproj, builds/win32/vc2008/index.html, - builds/win32/vc2010/freetype.vcxproj, builds/win32/vc2010/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualc/index.html, builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj, - builds/win32/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.4.8/2.4.9/, s/248/249/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 9. - - * builds/unix/configure.raw (version_info): Set to 14:1:8. - -2012-03-08 Werner Lemberg - - [bdf] Add missing overflow check. - - * src/bdf/bdflib.c (_bdf_parse_glyphs) : Add threshold for - `glyph->bpr'. - -2012-03-07 Vinnie Falco - - Prepare source code for amalgamation. - - * src/autofit/aferrors.h, src/bdf/bdferror.h, src/bzip2/ftbzip2.c, - src/cache/ftcerror.h, src/cff/cfferrs.h, src/cid/ciderrs.h, - src/gxvalid/gxverror.h, src/gzip/ftgzip.c, src/lzw/ftlzw.c, - src/otvalid/otverror.h, src/pcf/pcferror.h, src/pfr/pfrerror.h, - src/psaux/psauxerr.h, src/pshinter/pshnterr.h, - src/psnames/psnamerr.h, src/raster/rasterrs.h, src/sfnt/sferrors.h, - src/smooth/ftsmerrs.h, src/truetype/tterrors.h, - src/type1/t1errors.h, src/type42/t42error.h, src/winfonts/fnterrs.h: - Add #undef FT_ERR_PREFIX before #define FT_ERR_PREFIX. - -2012-03-03 Werner Lemberg - - Fix Savannah bug #35660. - - For some divisions, we use casts to 32bit entities. Always guard - against division by zero with these casts also. - - * src/base/ftcalc.c (ft_div64by32): Remove redundant cast. - (FT_MulDiv, FT_MulDiv_No_Round): Add 32bit cast. - (FT_DivFix): Add 32bit cast (this omission triggered the bug). - -2012-03-03 Werner Lemberg - - [psaux] Fix handling of track kerning. - - * src/psaux/afmparse.c (afm_parse_track_kern): Don't inverse sign - for `min_kern'. It is indeed quite common that track kerning - *increases* spacing for very small sizes. - -2012-03-02 Werner Lemberg - - [truetype] Fix Savannah bug #35689. - - * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Check first outline - point. - -2012-03-01 Werner Lemberg - - [bdf] Fix Savannah bug #35656. - - * src/bdf/bdflib.c (_bdf_parse_glyphs) <_BDF_BITMAP>: Check validity - of nibble characters instead of accessing `a2i' array. - -2012-03-01 Werner Lemberg - - [winfonts] Fix Savannah bug #35659. - - * src/winfonts/winfnt.c (FNT_Face_Init): Check number of glyphs. - -2012-03-01 Werner Lemberg - - [bdf] Fix Savannah bug #35658. - - * src/bdf/bdflib.c (_bdf_list_split): Initialize `field' elements - properly. - -2012-03-01 Werner Lemberg - - [psaux] Fix Savannah bug #35657. - - If in function `skip_spaces' the routine `skip_comment' comes to the - end of buffer, `cur' is still increased by one, so we need to check - for `p >= limit' and not `p == limit'. - - * src/psaux/psconv.c (PS_Conv_Strtol, PS_Conv_ToFixed, - PS_Conv_ASCIIHexDecode, PS_Conv_EexecDecode): Fix boundary checking. - -2012-03-01 Werner Lemberg - - [truetype] Fix Savannah bug #35646. - - * src/truetype/ttinterp.c (Ins_MIRP): Typo, present since ages. The - code is now in sync with the other operators (e.g. MSIRP) which - modify twilight points. - -2012-03-01 Werner Lemberg - - [bdf] Fix Savannah bug #35643. - - * src/bdf/bdflib.c (_bdf_list_ensure): Bring code in sync with - comment before `_bdf_list_split', this is, really allocate at least - five `field' elements. - -2012-03-01 Werner Lemberg - - [bdf] Fix Savannah bug #35641. - - * src/bdf/bdflib.c (_bdf_parse_glyphs) : Abort if - _BDF_ENCODING isn't set. We need this because access to the `glyph' - variable might be undefined otherwise. - -2012-03-01 Werner Lemberg - - [truetype] Fix Savannah bug #35640. - - * src/truetype/ttinterp.c (SkipCode, TT_RunIns): Fix boundary check - for NPUSHB and NPUSHW instructions. - -2012-02-29 Werner Lemberg - - [truetype] Fix Savannah bug #35601. - - * src/truetype/ttinterp.c (Ins_SHZ): Use number of points instead of - last point for loop. - Also remove redundant boundary check. - -2012-02-29 Werner Lemberg - - [truetype] Remove redundant check. - - * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Remove redundant - second check for ordered contour start points. - -2012-02-29 Werner Lemberg - - [truetype] Make SHC instruction behave similar to MS rasterizer. - - * src/truetype/ttinterp.c (Ins_SHC): Handle virtual contour in - twilight zone. - -2012-02-29 Alexei Podtelezhnikov - - Avoid modulo operators against a power-of-two denominator. - - * src/afcjk.c (af_hint_normal_stem), src/base/ftoutln.c - (ft_contour_has), src/cff/cffgload.c (cff_decoder_parse_charstrings) - , - src/gxvalid/gxvcommn.c (GXV_32BIT_ALIGNMENT_VALIDATE), - src/gxvalid/gxvfeat.c (gxv_feat_setting_validate): Replace `%' with - `&' operator. - -2012-02-29 Werner Lemberg - - [autofit] Don't synchronize digit widths for light rendering mode. - - We don't hint horizontally in this mode. - - * src/autofit/afloader.c (af_loader_load_g) : - Implement it. - -2012-02-26 Alexei Podtelezhnikov - - [type42] Minor code optimization (again). - - * src/type42/t42parse.c (t42_parse_sfnts): Simplify previous change. - -2012-02-26 Mateusz Jurczyk - Werner Lemberg - - [smooth] Fix Savannah bug #35604. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Use `FT_Pos' - instead of `FT_UInt' for some variables and update comparisons - accordingly. A detailed analysis can be found in the bug report. - -2012-02-26 Alexei Podtelezhnikov - - [type42] Minor code optimization. - - * src/type42/t42parse.c (t42_parse_sfnts): Use bitmask instead of - modulo operator. - -2012-02-26 Werner Lemberg - - * docs/CHANGES: Updated. - -2012-02-26 Werner Lemberg - - [type1] Fix Savannah bug #35608. - - * src/type1/t1parse.c (T1_Get_Private_Dict): Reject too short - dictionaries. - -2012-02-26 Werner Lemberg - - [bdf] Support `ENCODING -1 ' format. - - * src/bdf/bdflib.c (_bdf_parse_glyphs) : Implement it. - -2012-02-26 Werner Lemberg - - [bdf] Fix Savannah bug #35607. - - * src/bdf/bdflib.c (_bdf_parse_glyphs) : Normalize - negative encoding values. - -2012-02-26 Werner Lemberg - - [type1] Fix Savannah bug #35606. - - * src/type1/t1load.c (parse_subrs): Add proper guards for `strncmp'. - - * src/psaux/psobjs.c (ps_parser_skip_PS_token): Emit error message - only if cur < limit. - -2012-02-25 Werner Lemberg - - [pcf] Fix Savannah bug #35603. - - * src/pcf/pcfread.c (pcf_get_properties): Assure final zero byte in - `strings' array. - -2012-02-25 Werner Lemberg - - [type42] Fix Savannah bug #35602. - - * src/type42/t42parse.c (t42_parse_sfnts): Check `string_size' more - thoroughly. - -2012-02-25 Werner Lemberg - - [bdf] Fix Savannah bugs #35599 and #35600. - - * src/bdf/bdflib.c (ACMSG16): New warning message. - (_bdf_parse_glyphs) <_BDF_BITMAP>: Check line length. - -2012-02-24 Werner Lemberg - - [bdf] Fix Savannah bugs #35597 and #35598. - - * src/bdf/bdflib.c (_bdf_is_atom): Fix handling of property value. - -2012-02-24 Vinnie Falco - - Prepare source code for amalgamation (6/6). - - * src/cff/cffdrivr.c: s/Load_Glyph/cff_glyph_load/. - - * src/cid/cidload.c: s/parse_font_matrix/cid_parse_font_matrix/. - s/t1_init_loader/cid_init_loader/. - s/t1_done_loader/cid_done_loader/. - - * src/psaux/t1cmap.c: s/t1_get_glyph_name/psaux_get_glyph_name/. - - * src/truetype/ttdriver.c: s/Load_Glyph/tt_glyph_load/. - - * src/type1/t1load.c: s/parse_font_matrix/t1_parse_font_matrix/. - -2012-02-24 Vinnie Falco - - Prepare source code for amalgamation (5/6). - - * include/freetype/fterrors.h: Undefine FT_KEEP_ERR_PREFIX after - using it. - -2012-02-22 Vinnie Falco - - Prepare source code for amalgamation (4/6). - - * src/smooth/ftgrays.c, src/raster/ftraster.c: Undefine RAS_ARG, - RAS_ARGS, RAS_VAR, and RAS_VARS before defining it. - - * src/smooth/ftgrays.c: s/TRaster/black_TRaster/, - s/PRaster/black_PRaster/. - * src/raster/ftraster.c: s/TRaster/gray_TRaster/, - s/PRaster/gray_PRaster/. - -2012-02-20 Vinnie Falco - - Prepare source code for amalgamation (3/6). - - * src/smooth/ftgrays.c: s/TWorker/black_TWorker/, - s/PWorker/black_PWorker/. - * src/raster/ftraster.c: s/TWorker/gray_TWorker/, - s/PWorker/gray_PWorker/. - -2012-02-20 Vinnie Falco - - Prepare source code for amalgamation (2/6). - - * src/smooth/ftgrays.c, src/raster/ftraster.c: Undefine FLOOR, - CEILING, TRUNC, and SCALED before defining it. - -2012-02-20 Vinnie Falco - - Prepare source code for amalgamation (1/6). - - See discussion starting at - - https://lists.gnu.org/archive/html/freetype-devel/2012-01/msg00037.html - - * src/smooth/ftgrays.c: s/TBand/gray_TBand/. - * src/raster/ftraster.c: s/TBand/black_TBand/. - -2012-02-17 Alexei Podtelezhnikov - - [autofit] Fix outline flags. - - * src/autofit/afloader.c (af_loader_load_g): Don't reassign - `outline.flags' so that this information is preserved. See - discussion starting at - - https://lists.gnu.org/archive/html/freetype-devel/2012-02/msg00046.html - -2012-02-11 Werner Lemberg - - [truetype] Fix Savannah bug #35466. - - Jump instructions are now bound to the current function. The MS - Windows rasterizer behaves the same, as confirmed by Greg Hitchcock. - - * src/truetype/ttinterp.h (TT_CallRec): Add `Cur_End' element. - * src/truetype/ttobjs.h (TT_DefRecord): Add `end' element. - - * src/truetype/ttinterp.c (DO_JROT, DO_JMPR, DO_JROF): Check upper - bound of jump address. - (Ins_FDEF, Ins_CALL, Ins_LOOPCALL, Ins_UNKNOWN, TT_RunIns): Updated. - -2012-02-11 Werner Lemberg - - We don't use `extensions'. - - * include/freetype/internal/ftobjs.h (FT_DriverRec): Remove - `extensions' field. - -2012-02-11 Werner Lemberg - - Clean up `generic' fields. - - * include/freetype/internal/ftobjs.h (FT_ModuleRec, FT_LibraryRec): - Remove `generic' field since users can't access it. - - * src/base/ftobjs.c (FT_Done_GlyphSlot): Call `generic.finalizer' as - advertised in the documentation of FT_Generic. - (Destroy_Module, FT_Done_Library): Updated to changes in `ftobjs.h'. - -2012-02-07 Werner Lemberg - - [autofit] Harmonize function arguments. - - * src/autofit/afloader.c, src/autofit/afloader.h: Use `FT_Int32' for - `load_flags'. - -2012-02-07 Werner Lemberg - - * src/cff/cffobjs.c (cff_face_init): Remove unnecessary casts. - -2012-01-17 suzuki toshiya - - [gxvalid] Fix Savannah bug #35286. - - Patch submitted by anonymous reporter. - - * src/gxvalid/gxvcommn.c (gxv_XStateTable_subtable_setup): - gxv_set_length_by_ulong_offset() must be called with 3, not 4, - the number of the subtables in the state tables; classTable, - stateArray, entryTable. - -2012-01-17 suzuki toshiya - - [raccess] Modify for PIC build. - - Based on the patch provided by Erik Dahlstrom , - https://lists.gnu.org/archive/html/freetype-devel/2012-01/msg00010.html - - Also `raccess_guess_table[]' and `raccess_rule_by_darwin_vfs()' - are renamed with `ft_' suffixes. - - * src/base/ftbase.h: `raccess_rule_by_darwin_vfs()' is renamed - to `ft_raccess_rule_by_darwin_vfs()'. - * src/base/ftobjs.c: Ditto. - - * src/base/ftrfork.c: Declarations of FT_RFork_Rule, - raccess_guess_rec, are moved to... - * include/freetype/internal/ftrfork.h: Here. - - * include/freetype/internal/ftrfork.h: - FT_RFORK_RULE_ARRAY_{BEGIN,ENTRY,END} macros are defined - to replace raccess_guess_table[] in both of PIC and non-PIC - modes. - * src/base/ftrfork.c: raccess_guess_table[] array is rewritten - by FT_RFORK_RULE_ARRAY_{BEGIN,ENTRY,END}. - - * src/base/basepic.h (BasePIC): Add `ft_raccess_guess_table' - storage. (FT_RACCESS_GUESS_TABLE_GET): New macro to retrieve - the function pointer from `ft_raccess_guess_table' storage in - `BasePIC' structure. - * src/base/ftrfork.c (FT_Raccess_Guess): Rewritten with - FT_RACCESS_GUESS_TABLE_GET. - (raccess_get_rule_type_from_rule_index): Add `library' as the - first argument to the function, to retrieve the storage of - `ft_raccess_guess_table' from it. Also `raccess_guess_table' - is replaced by FT_RACCESS_GUESS_TABLE_GET. - (ft_raccess_rule_by_darwin_vfs): Ditto. - -2012-01-16 suzuki toshiya - - Remove trailing spaces. - -2012-01-16 suzuki toshiya - - Formatting PIC related sources. - - * src/autofit/afpic.c: Harmonize to FT2 coding conventions. - * src/base/basepic.c: Ditto. - * src/base/ftpic.c: Ditto. - * src/cff/cffpic.c: Ditto. - * src/pshinter/pshpic.c: Ditto. - * src/psnames/pspic.c: Ditto. - * src/raster/rastpic.c: Ditto. - * src/sfnt/sfntpic.c: Ditto. - * src/smooth/ftspic.c: Ditto. - * src/truetype/ttpic.c: Ditto. - -2012-01-16 suzuki toshiya - - [autofit] Fix the inclusion of `aflatin2.h' in PIC file. - - * src/autofit/afpic.c: Include `aflatin2.h' when - FT_OPTION_AUTOFIT2 is defined, as afglobal.c does so. - Unconditionally inclusion causes declared but unimplemented - warning by GCC 4.6. - -2012-01-16 suzuki toshiya - - [cff] Remove redundant declarations of cff_cmap_XXX_class_rec. - - * src/cff/cffpic.c: The declarations of - FT_Init_Class_cff_cmap_encoding_class_rec() and - FT_Init_Class_cff_cmap_unicode_class_rec() are removed. - They can be obtained by the inclusion of cffcmap.h. - cffcmap.h invokes FT_DECLARE_CMAP_CLASS() and it declares - FT_Init_Class_cff_cmap_encoding_class_rec() etc in PIC mode. - -2012-01-15 suzuki toshiya - - Fix redundant declaration warning in PIC mode. - - Originally FT_DEFINE_{DRIVER,MODULE,RENDERER}() macros were - designed to declare xxx_pic_{free,init} by themselves. - Because these macros are used at the end of the module - interface (e.g. ttdriver.c) and the wrapper source to build - a module as a single object (e.g. truetype.c) includes - the PIC file (e.g. ttpic.c) before the module interface, - these macros are expanded AFTER xxx_pic_{free,init} body - when the modules are built as single object. - The declaration after the implementation causes the redundant - declaration warnings, so the declarations are moved to module - PIC headers (e.g. ttpic.h). Separating to other header files - are needed for multi build. - - * include/freetype/internal/ftdriver.h (FT_DEFINE_DRIVER): - Remove class_##_pic_free and class_##_pic_init declarations. - * include/freetype/internal/ftobjs.h (FT_DEFINE_RENDERER, - FT_DEFINE_MODULE): Ditto. - - * src/base/basepic.h: Insert a comment and fix coding style. - * src/autofit/afpic.h: Declare autofit_module_class_pic_{free, - init}. - * src/cff/cffpic.h: Declare cff_driver_class_pic_{free,init}. - * src/pshinter/pshpic.h: Declare pshinter_module_class_pic_{free, - init}. - * src/psnames/pspic.h: Declare psnames_module_class_pic_{free, - init}. - * src/raster/rastpic.h: Declare - ft_raster{1,5}_renderer_class_pic_{free,init} - * src/sfnt/sfntpic.h: Declare sfnt_module_class_pic_{free,init}. - * src/smooth/ftspic.h: Declare - ft_smooth_{,lcd_,lcdv_}renderer_class_pic_{free,init}. - * src/truetype/ttpic.h: Declare tt_driver_class_pic_{free,init}. - -2012-01-15 suzuki toshiya - - Make pspic.c to include module error header to fix multi build. - - * src/psnames/pspic.c: Include `psnamerr.h'. - -2012-01-14 suzuki toshiya - - [base] Fix a dereference of uninitialized variable in PIC mode. - - * src/base/ftglyph.c (FT_Glyph_To_Bitmap): `glyph' must be - set before dereferring to obtain `library'. The initialization - of `clazz', `glyph', `library' and NULL pointer check are - reordered to minimize PIC conditionals. - -2012-01-14 suzuki toshiya - - [base] Insert explicit cast for GCC 4.6 in PIC mode. - - * src/base/ftinit.c (FT_Add_Default_Modules): Under PIC - configuration, FT_DEFAULT_MODULES_GET returns - FT_Module_Class** pointer, GCC 4.6 warns that - const FT_Module_Class* const* variable is warned as - inappropriate to store it. To calm it, explicit cast is - inserted. Also `library' is checked to prevent the NULL - pointer dereference in FT_DEFAULT_MODULES_GET. - -2012-01-13 suzuki toshiya - - Fix PIC build broken by d9145241fe378104ba4c12a42534549faacc92e6. - - Under PIC configuration, FT_{CFF,PSCMAPS,SFNT,TT}_SERVICES_GET - take no arguments but derefer the variable named `library' - internally. - - * src/cff/cffdrivr.c (cff_get_interface): Declare `library' and - set it if non-NULL driver is passed. - * src/truetype/ttdriver.c (tt_get_interface): Ditto. - - * src/sfnt/sfdriver.c (sfnt_get_interface): Declare `library' - under PIC configuration, and set it if non-NULL module is given. - * src/psnames/psmodule.c (psnames_get_interface): Ditto. - -2012-01-13 suzuki toshiya - - Make PIC files include module error headers, to use the error codes - with per-module prefix. - - * src/autofit/afpic.c: Include `aferrors.h'. - * src/cff/cffpic.c: Include `cfferrs.h'. - * src/pshinter/pshpic.c: Include `pshnterr.h'. - * src/raster/rastpic.c: Include `rasterrs.h'. - * src/sfnt/sfntpic.c: Include `sferrors.h'. - * src/smooth/ftspic.c: Include `ftsmerrs.h'. - * src/truetype/ttpic.c: Include `tterrors.h'. - -2012-01-04 Tobias Ringström - - [truetype] Fix IP instruction if x_ppem != y_ppem. - - * src/truetype/ttinterp.c (Ins_IP): Scale `orus' coordinates - properly. - -2012-01-02 Werner Lemberg - - Fix tracing message for `loca' table. - - * src/truetype/ttpload.c (tt_face_get_location): Don't emit a - warning message if the last `loca' entry references an empty glyph. - -2011-12-10 Werner Lemberg - - Add some variable initializations. - Reported by Richard COOK . - - * src/type1/t1driver.c (t1_ps_get_font_value): Initialize `val'. - * src/smooth/ftgrays.c (gray_render_conic): Initialize `levels' - earlier. - -2011-12-08 Werner Lemberg - - Fix serious scaling bug in `FT_Get_Advances'. - - * src/base/ftadvanc.c (FT_Get_Advances): Advance values returned by - `FT_Load_Glyph' must be simply multiplied by 1024. - -2011-12-08 Werner Lemberg - - * src/bdf/bdflib.c (_bdf_parse_start): Drop redundant error tracing. - -2011-12-02 suzuki toshiya - - [mac] Unify DARWIN_NO_CARBON with FT_MACINTOSH. - - Originally FT_MACINTOSH was a pure auto macro and DARWIN_NO_CARBON - was a configurable macro to disable Carbon-dependent code. Because - now configure script sets DARWIN_NO_CARBON by default and disables - Darwin & Carbon-dependent codes, these macros can be unified. - FT_MACINTOSH (undefined by default) is kept and DARWIN_NO_CARBON - (defined by default) is removed, because DARWIN_NO_CARBON violates - FT_XXX naming convention of public macros, and a macro configured by - default is not portable for the building without configure (e.g. - make devel). - - * builds/unix/configure.raw: Define FT_MACINTOSH if Carbon-based - old Mac font support is requested and Carbon is available. - * builds/unix/ftconfig.in: Undefine FT_MACINTOSH when the support - for Mac OS X without Carbon (e.g. Mac OS X 10.4 for ppc64) is - requested. - * include/freetype/config/ftconfig.in: Ditto. - * builds/vms/ftconfig.h: Ditto. - - * src/base/ftbase.h: Remove DARWIN_NO_CARBON. - * src/base/ftbase.c: Ditto. - * src/base/ftobjs.c: Ditto. - * src/base/ftrfork.c: Ditto. - - * src/base/ftmac.c: Compile the body if FT_MACINTOSH is defined - (same with TT_USE_BYTECODE_INTERPRETER in ttinterp.c). - * builds/mac/ftmac.c: Ditto. - - * builds/mac/FreeType.m68k_cfm.make.txt: Define FT_MACINTOSH. - * builds/mac/FreeType.m68k_far.make.txt: Ditto. - * builds/mac/FreeType.ppc_classic.make.txt: Ditto. - * builds/mac/FreeType.ppc_carbon.make.txt: Ditto. - -2011-11-30 suzuki toshiya - - Fix Savannah bug #34728 (`make devel' on Mac OS X). - - * builds/toplevel.mk: Check `/dev/null' to identify the Unix- - like systems without `init' nor `hurd' (e.g. Mac OS X >= 10.4). - * builds/unix/detect.mk: Ditto. - -2011-11-30 suzuki toshiya - - [apinames] Fix the overflow of signed integer hash. - - * src/tools/apinames.c (names_add): Change the type of `h' from - int to unsigned int, to prevent undefined behaviour in the - overflow of signed integers (overflow of unsigned int is defined - to be wrap around). Found by clang test suggested by Sean - McBride. - -2011-11-30 Werner Lemberg - - [winfonts] Remove casts. - - * src/winfonts/winfnt.c (winfnt_driver_class): Remove all casts and - update affected functions. - (FNT_Size_Select): Fix number of arguments. - -2011-11-30 Werner Lemberg - - [type42] Remove casts. - - * src/type42/t42drivr.c (t42_driver_class): Remove all casts and - update affected functions. - - * src/type42/t42objs.c, src/type42/t42objs.h: Updated for t42 driver - changes. - -2011-11-30 Werner Lemberg - - [type1] Remove casts. - - * src/type1/t1driver.c (t1_driver_class): Remove all casts and - update affected functions. - - * src/type1/t1gload.c, src/type1/t1gload.h, src/type1/t1objs.c: - Updated for t1driver changes. - src/type1/t1objs.h (T1_Driver): Remove unused typedef. - Updated for t1driver changes. - -2011-11-27 Werner Lemberg - - [bdf] Fix Savannah bug #34896. - - ENCODING now covers the whole Unicode range. - - Note, however, that this change is quite expensive since it - increases the size of three arrays by almost 400kByte in total. The - right fix is to replace the logic with something smarter. - Additionally, there exist very old BDFs for three-byte CCCII - encoding which exceeds the range of Unicode (another reason to have - a smarter logic). - - * src/bdf/bdf.h (bdf_font_t): Increase size of `nmod' and `umod' - arrays. - * src/bdf/bdflib.c (bdf_parse_t): Increase size of `have' array. - -2011-11-27 Werner Lemberg - - [bdf] Improve tracing. - - * src/bdf/bdflib.c (DBGMSG1, DBGMSG2): New macros. - (_bdf_parse_glyphs): Use them. - -2011-11-26 Werner Lemberg - - Improve tracing. - - * src/bdf/bdfdrivr.c (BDF_Face_Done), src/pcf/pcfdrivr.c - (PCF_Face_Done): Remove tracing message. - - * src/bdf/bdfdrivr.c (BDF_Face_Init), src/cff/cffobjs.c - (cff_face_init), src/cid/cidobjs.c (cid_face_init), - src/pfr/pfrobjs.c (pfr_face_init), src/sfnt/sfobjs.c - (sfnt_init_face), src/truetype/ttobjs.c (tt_face_init), - src/type1/t1objs.c (T1_Face_Init), src/type42/t42objs.c - (T42_Face_Init), src/winfonts/winfnt.c (FNT_Face_Init): Add - `greeting' message. - - * src/sfnt/sfobjs.c (sfnt_open_font), src/type42/t42objs.c - (T42_Open_Face): Improve tracing. - -2011-11-26 Werner Lemberg - - [cid] Fix error code. - - * src/cid/cidparse.c (cid_parser_new): Do it. - -2011-11-26 Werner Lemberg - - [cff] Fix error code. - - * src/cff/cffload.c (cff_font_load): Do it. - -2011-11-26 Werner Lemberg - - Add new error code FT_Err_Missing_Module. - - Previously, FreeType misleadingly returned - FT_Err_Unknown_File_Format if a module was missing (or a test was - missing completely). - - * include/freetype/fterrdef.h (FT_Err_Missing_Module): Define. - - * src/cff/cffobjs.c (cff_face_init), src/cff/cffdrivr.c - (cff_get_glyph_name), src/cid/cidobjs.c (cid_face_init), - src/sfnt/sfobjs.c (sfnt_init_face), src/truetype/ttobjs.c - (tt_face_init), src/type1/t1objs.c (T1_Face_Init), - src/type42/t42objs.c (T42_Face_Init, T42_Driver_Init): Updated. - - * src/type1/t1afm.c (T1_Read_Metrics), src/type/t1objs.c - (T1_Face_Init), src/type42/t42objs.c (T42_Face_Init): Remove now - redundant test for `psaux'. - -2011-11-25 Werner Lemberg - - [bdf] Add more error messages. - - * src/bdf/bdflib.c (_bdf_set_default_spacing, _bdf_add_property): - Add line number argument. - Update all callers. - (ERRMSG5, ERRMSG6, ERRMSG7, ERRMSG8, ERRMSG9): New macros. - (_bdf_readstream, _bdf_set_default_spacing, _bdf_add_property, - _bdf_parse_glyphs, _bdf_parse_start): Add error messages. - -2011-11-24 Werner Lemberg - - * include/freetype/fterrors.h: Remove dead code. - -2011-11-15 Werner Lemberg - - * docs/releases: Updated. - -2011-11-15 Werner Lemberg - - * Version 2.4.8 released. - ========================= - - - Tag sources with `VER-2-4-8'. - - * docs/CHANGES: Updated. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.4.8. - - * README, Jamfile (RefDoc), - builds/win32/vc2005/freetype.vcproj, builds/win32/vc2005/index.html, - builds/win32/vc2008/freetype.vcproj, builds/win32/vc2008/index.html, - builds/win32/vc2010/freetype.vcxproj, builds/win32/vc2010/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualc/index.html, builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj, - builds/win32/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.4.7/2.4.8/, s/247/248/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 8. - - * builds/unix/configure.raw (version_info): Set to 14:0:8. - -2011-11-13 Chris Liddell - - Add FT_Get_PS_Font_Value() API. - - This allows a Type 1 font face to be interrogated to retrieve most - of the dictionary keys (keys not relevant to FreeType's Type 1 - interpreter are not available). - - * include/freetype/internal/services/svpsinfo.h - (PS_GetFontValueFunc): New typedef. - (PSInfo): Add `ps_get_font_value'. - (FT_DEFINE_SERVICE_PSINFOREC): Updated. - - * include/freetype/internal/t1types.h (T1_EncodingType): Moved to... - * include/freetype/t1tables.h: Here. - (PS_Dict_Keys): New enumeration. - (FT_Get_PS_Font_Value): New declaration. - - * src/base/fttype1.c (FT_Get_PS_Font_Value): New function. - - * src/type1/t1driver.c (t1_ps_get_font_value): This new function - does the real job. - (t1_service_ps_info): Add it. - - * src/cff/cffdrivr.c (cff_service_ps_info), src/cid/cidriver.c - (cid_service_ps_info), src/type42/t42drivr.c (t42_service_ps_info): - Updated. - -2011-11-08 Braden Thomas - - [cid] Various loading fixes. - - * src/cid/cidload.c (cid_load_keyword) , - (parse_font_matrix, parse_expansion_factor): Correctly check number - of dictionaries. - (cid_read_subrs): Protect against invalid values of `num_subrs'. - Assure that the elements of the `offsets' array are ascending. - -2011-11-05 Werner Lemberg - - * README: We use copyright ranges also. - - According to - - https://www.gnu.org/prep/maintain/html_node/Copyright-Notices.html - - this should be mentioned explicitly. - -2011-10-30 suzuki toshiya - - [raccess] Supplement for previous fix. - - * src/base/ftbase.h (raccess_rule_by_darwin_vfs): Do not declare - it on native Mac OS X. - * src/base/ftrfork.c (raccess_get_rule_type_from_rule_index): - Hide raccess_get_rule_type_from_rule_index() on native Mac OS X - too. - -2011-10-30 suzuki toshiya - - [raccess] Hide raccess_rule_by_darwin_vfs() on native Mac OS X. - - * src/base/ftrfork.c (raccess_rule_by_darwin_vfs): Do not - compile on native Mac OS X because it is not used. - -2011-10-25 Werner Lemberg - - [truetype] Fix MD instruction for twilight zone. - - * src/truetype/ttinterp.c (Ins_MD): Without this fix, the MD - instruction applied to original coordinates of twilight points - always returns zero. - -2011-10-18 Werner Lemberg - - * Version 2.4.7 released. - ========================= - - - Tag sources with `VER-2-4-7'. - - * docs/CHANGES: Updated. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.4.7. - - * README, Jamfile (RefDoc), - builds/win32/vc2005/freetype.vcproj, builds/win32/vc2005/index.html, - builds/win32/vc2008/freetype.vcproj, builds/win32/vc2008/index.html, - builds/win32/vc2010/freetype.vcxproj, builds/win32/vc2010/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualc/index.html, builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj, - builds/win32/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.4.6/2.4.7/, s/246/247/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 7. - - * builds/unix/configure.raw (version_info): Set to 13:2:7. - -2011-10-15 Kal Conley - - Fix handling of transformations if no renderer is present. - - * src/base/ftobjs.c (FT_Load_Glyph): Thinko. - -2011-10-15 Kal Conley - - Fix conditions for autohinting. - - * src/base/ftobjs.c (FT_Load_Glyph): Handle - FT_LOAD_IGNORE_TRANSFORM. - -2011-10-07 suzuki toshiya - - [gxvalid] Fix a bug to detect too large offset in morx table. - - * src/gxvalid/gxvmorx2.c - (gxv_morx_subtable_type2_ligActionIndex_validate): Fix a bug - that too large positive offset cannot be detected. - -2011-10-01 Braden Thomas - - Handle some border cases. - - * include/freetype/config/ftstdlib.h (FT_USHORT_MAX): New macro. - - * src/base/ftbitmap.c (FT_Bitmap_Convert): Protect against invalid - value of `target->rows'. - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings): Add check for - flex start. - - * src/raster/ftrend1.c (ft_raster1_render): Check `width' and - `height'. - - * src/truetype/ttgxvar.c (TT_Vary_Get_Glyph_Deltas): Protect against - invalid values in `localpoints' array. - -2011-10-01 Werner Lemberg - - [psnames] Handle zapfdingbats. - Problem reported by Nicolas Rougier . - - * src/tools/glnames.py (adobe_glyph_list): Add data from AGL's - `zapfdingbats.txt' file. - - * src/psnames/pstables.h: Regenerated. - -2011-09-27 Simon Bünzli - - [type1] Fix Savannah bug #34189. - - * src/type1/t1load.c (T1_Open_Face): Initialize - `face->len_buildchar'. - -2011-09-26 Werner Lemberg - - [cff] Dump SIDs while tracing. - - * src/cff/cffobjs.c (cff_face_init): Do it. - - * src/cff/cffparse.c (cff_parser_run) [FT_DEBUG_LEVEL_TRACE] - : Identify as SID. - -2011-09-17 Werner Lemberg - - Remove unused FT_ALIGNMENT macro. - - * builds/unix/ftconfig.in, builds/vms/ftconfig.h, - include/freetype/config/ftconfig.h: Do it. - -2011-09-17 Alexei Podtelezhnikov - - [smooth] Slightly optimize conic and cubic flatteners. - - * src/smooth/ftgrays.c (gray_render_conic, gray_render_cubic): Move - out some code from the main loop to speed it up. - -2011-09-11 Tomas Hoger - - Slightly improve LZW_CLEAR handling. - - * src/lzw/ftzopen.c (ft_lzwstate_io) : - Ensure that subsequent (modulo garbage byte(s)) LZW_CLEAR codes are - handled as clear codes. This also re-sets old_code and old_char to - predictable values, which is a little better than using `random' - ones if the code following LZW_CLEAR is invalid. - -2011-09-11 Tomas Hoger - - Add explicit LZW decompression stack size limit. - - Stack larger than 1<prefix[code - 256] - when traversing prefix table. Such check is less efficient and - should not be required if prefix table is constructed correctly in - the first place. - - * src/lzw/ftzopen.c (ft_lzwstate_stack_grow): Implement it. - -2011-09-11 Tomas Hoger - - Protect against loops in the prefix table. - - LZW decompressor did not sufficiently check codes read from the - input LZW stream. A specially-crafted or corrupted input could - create a loop in the prefix table, which leads to memory usage - spikes, as there's no decompression stack size limit. - - * src/lzw/ftzopen.c (ft_lzwstate_io) : First - code in valid LZW stream must be 0..255. - : In the special KwKwK case, code == free_ent, - code > free_ent is invalid. - -2011-09-09 Werner Lemberg - - Better tracing of metrics. - - * src/base/ftobjs.c (FT_Request_Size, FT_Select_Size): Decorate with - FT_TRACE. - -2011-09-07 Werner Lemberg - - [cff] Fix Savannah bug #33816. - - * src/cff/cfftypes.h (CFF_FontRecDictRec): New member - `has_font_matrix'. - * src/cff/cffparse.c (cff_parse_font_matrix): Set it. - Update tracing output. - * src/cff/cffobjs.c (cff_face_init): Use it so that the heuristics - can be removed. - -2011-08-30 Werner Lemberg - - Better tracing of metrics. - - * src/base/ftobjs.c (FT_Select_Metrics, FT_Request_Metrics): - Decorate with FT_TRACE. - -2011-08-25 Werner Lemberg - - [cff] Better tracing of the parsing process. - - * src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with - FT_TRACE. - - * src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox, - cff_parse_private_dict, cff_parse_cid_ros): Updated. - (CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000, - CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD, - CFF_FIELD_DELTA): Add argument for ID. - (cff_parser_run): Decorate with FT_TRACE. - - * src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add - `id' member. - - * src/cff/cfftoken.h: Add IDs to all fields. - -2011-08-16 Werner Lemberg - - Fix Savannah bug #34022. - - * README, docs/INSTALL: Remove references to UPGRADE.UNIX. - -2011-08-15 Werner Lemberg - - Fix Savannah bug #34018. - - * docs/UPGRADE.UNIX: Removed. Obsolete. - -2011-08-15 David Bevan - - Fix Savannah bug #33992. - - * src/base/ftstroke.c (FT_Stroker_ParseOutline): Fix border case. - -2011-08-12 Werner Lemberg - - [cff] Fix Savannah bug #33975. - - * src/cff/cffparse.c (cff_parse_font_matrix): Fix typo. - -2011-07-29 Werner Lemberg - - * Version 2.4.6 released. - ========================= - - - Tag sources with `VER-2-4-6'. - - * docs/CHANGES: Updated. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.4.6. - - * README, Jamfile (RefDoc), - builds/win32/vc2005/freetype.vcproj, builds/win32/vc2005/index.html, - builds/win32/vc2008/freetype.vcproj, builds/win32/vc2008/index.html, - builds/win32/vc2010/freetype.vcxproj, builds/win32/vc2010/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualc/index.html, builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj, - builds/win32/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.4.5/2.4.6/, s/245/246/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 6. - - * builds/unix/configure.raw (version_info): Set to 13:1:7. - -2011-07-29 Werner Lemberg - - [cff] Add some more tracing infos. - - * src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox, - cff_parse_cid_ros): Add tracing. - -2011-07-22 Dirk Müller - - [psaux, type1] Fix null pointer dereferences. - - Found with font fuzzying. - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings): Check - `decoder->buildchar'. - - * src/type1/t1load.c (t1_load_keyword): Check `blend->num_designs'. - -2011-07-20 Chris Morgan - - Add FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT. - - Useful for embedded systems which don't need file stream support. - - * src/base/ftsystem.c, src/base/ftobjs.c (FT_Stream_New): Implement - it. - -2011-07-20 Elton Chung - - * src/base/ftpatent.c (FT_Face_SetUnpatentedHinting): Fix typo. - -2011-07-16 Steven Chu - - [truetype] Fix metrics on size request for scalable fonts. - - * src/truetype/ttdriver.c (tt_size_request): Fix copying metrics - from TT_Size to FT_Size if scalable font. - - See - - https://lists.gnu.org/archive/html/freetype-devel/2011-07/msg00049.html - - for some comparison images. - -2011-07-14 Matthias Drochner . - - [psaux] Fix potential sign extension problems. - - When shifting right a signed value, it is not defined by the - C standard whether one gets a sign extension or not. Use a macro to - do an explicit cast from a signed short (assuming that this is - 16bit) to an int. - - * src/psaux/t1decode.c (Fix2Int): New macro. - Use it where appropriate. - -2011-07-14 Werner Lemberg - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings) - : Better handling of subroutine index 0. - From Matthias Drochner . - -2011-07-10 Алексей Подтележников - - [psaux] Optimize previous commit. - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings) - : Move error check down to avoid testing twice for - good cases. - -2011-07-08 Werner Lemberg - - [psaux] Add better argument check for `callothersubr'. - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings) - : Reject negative arguments. - -2011-07-07 Werner Lemberg - - [sfnt] Try harder to find non-zero values for ascender and descender. - - * src/sfnt/sfobjs.c (sfnt_load_face): Consult `OS/2' table in case - the `hhea' table's values are zero. - -2011-07-03 Werner Lemberg - - Fix previous commit. - - We want to unset FT_FACE_FLAG_SCALABLE only if there are bitmap - strikes in the font. - - * src/truetype/ttobjs.c (tt_face_init): Implement it. - - * docs/CHANGES: Updated. - -2011-07-02 Just Fill Bugs - - [truetype] Fix Savannah bug #33246. - - * src/truetype/ttobjs.c (tt_check_single_notdef): New function. - (tt_face_init): Use it to test FT_FACE_FLAG_SCALABLE. - -2011-07-02 Werner Lemberg - - * docs/CHANGES: Updated. - -2011-07-02 David Bevan - - [ftstroke] Major revision. - - The main problems - ----------------- - - o If FT_STROKER_LINEJOIN_BEVEL was specified, unlimited miter - joins (not bevel joins) were generated. Indeed, the meanings of - `miter' and `bevel' were incorrectly reversed (consistently) in - both the code and comments. - - o The way bevel joins were constructed (whether specified - explicitly, or created as a result of exceeding the miter limit) - did not match what is required for stroked text in PostScript or - PDF. - - The main fixes - -------------- - - o The behaviour of FT_STROKER_LINEJOIN_BEVEL has been corrected. - - o A new line join style, FT_STROKER_LINEJOIN_MITER_FIXED, has been - introduced to support PostScript and PDF miter joins. - - o FT_STROKER_LINEJOIN_MITER_VARIABLE has been introduced as an - alias for FT_STROKER_LINEJOIN_MITER. - - Additionally, a variety of stroking errors have been fixed. These - would cause various artifacts (including points `at infinity'), - especially when stroking poor quality fonts. - - See - - https://lists.gnu.org/archive/html/freetype-devel/2011-07/msg00001.html - - for example documents. The FreeType stroker now produces results - very similar to that produced by GhostScript and Distiller for these - fonts. - - Other problems - -------------- - - The following problems have been resolved: - - o Inside corners could be generated incorrectly. Intersecting the - inside corner could cause a missing triangular area and other - effects. - - The intersection point can only be used if the join is between - two lines and both lines are long enough. The `optimization' - condition in `ft_stroker_inside' has been corrected; this - requires the line length to be passed into various functions and - stored in `FT_StrokerRec'. - - o Incorrect cubic curves could be generated. The angle - calculations in `FT_Stroker_CubicTo' have been corrected to - handle the case of the curve crossing the +/-PI direction. - - o If the border radius was greater than the radius of curvature of - a curve, then the negative sector would end up outside (not - inside) the border. This situation is now recognized and the - negative sector is circumnavigated in the opposite direction. - (If round line joins are being used, this code is disabled - because the line join will always cover the negative sector.) - - o When a curve is split, the arcs may not join smoothly (especially - if the curve turns sharply back on itself). Changes in - direction between adjacent arcs were not handled. A round - corner is now added if the deviation from one arc to the next is - greater than a suitable threshold. - - o The current direction wasn't retained if a the outline contained - a zero length lineto or a curve that was determined to be - `basically a point'. This could cause a spurious join to be - added. - - o Cubics with close control points could be mishandled. All eight - cases are now distinguished correctly. - - Other improvements - ------------------ - - o Borders for cubic curves could be too `flat'. - FT_SMALL_CUBIC_THRESHOLD has been reduced a little to prevent - this. - - o The handling and use of movable points has been simplified a - little. - - o Various values are now computed only if the results are actually - needed. - - o The directions of the outer and inner borders have been swapped, - as recommended by Graham Asher. - - * src/base/ftstroke.c: Revised. - * include/freetype/ftstroke.h: Updated. - -2011-06-30 İsmail Dönmez - - * builds/toplevel.mk: We use git, not CVS, thus skip `.gitignore'. - -2011-06-29 Werner Lemberg - - [bdf] Fix Savannah bug #33663. - - * src/bdf/bdflib.c (_bdf_parse_glyphs): Handle negative values for - ENCODING correctly. - - * docs/CHANGES: Document it. - -2011-06-24 Werner Lemberg - - * Version 2.4.5 released. - ========================= - - - Tag sources with `VER-2-4-5'. - - * docs/CHANGES: Updated. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.4.5 - - * README, Jamfile (RefDoc), - builds/win32/vc2005/freetype.vcproj, builds/win32/vc2005/index.html, - builds/win32/vc2008/freetype.vcproj, builds/win32/vc2008/index.html, - builds/win32/vc2010/freetype.vcxproj, builds/win32/vc2010/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualc/index.html, builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj, - builds/win32/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.4.4/2.4.5/, s/244/245/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 5. - - * builds/unix/configure.raw (version_info): Set to 13:0:7. - -2011-06-20 Werner Lemberg - - * src/autofit/aflatin.c (af_latin_metrics_scale_dim): Fix change - from 2011-05-04. - -2011-06-19 suzuki toshiya - - [gxvalid] make the `prop' validation tracing verbose. - - * src/gxvalid/gxvprop.c: Add tracing messages for errors. - -2011-06-19 suzuki toshiya - - [autogen.sh] Reflect environment variable LIBTOOLIZE. - -2011-06-18 Werner Lemberg - - Update license documentation. - - * docs/GPL.TXT: Renamed to... - * docs/GPLv2.TXT: This. - - * docs/LICENSE.TXT: Updated. - -2011-06-14 suzuki toshiya - - Fix g++4.6 compiler warnings in module drivers. - - The background is same with previous commit. - - * src/truetype/ttgxvar.c (ft_var_readpackedpoints): - Init `points'. (TT_Vary_Get_Glyph_Deltas): Init - `delta_xy'. (TT_Get_MM_Var): Init `mmvar'. - * src/type1/t1load.c (T1_Get_MM_Var): Ditto. - * src/cff/cffdrivr.c (cff_ps_get_font_info): Init - `font_info'. - * src/cff/cffload.c (cff_index_get_pointers): Init `t'. - (cff_font_load): Init `sub'. - * src/cff/cffobjs.c (cff_size_init): Init `internal'. - (cff_face_init): Init `cff'. - * src/pfr/pfrload.c (pfr_extra_item_load_stem_snaps): - Init `snaps'. - * src/pcf/pcfread.c (pcf_get_properties): Init `properties'. - (pcf_get_bitmaps): Init `offsets'. (pcf_get_encodings): - Init `tmpEncoding'. - * src/sfnt/ttload.c (tt_face_load_gasp): Init `gaspranges'. - * src/sfnt/ttsbit.c (Load_SBit_Image): Init `components'. - * src/cache/ftcmru.c (FTC_MruList_New): Init `node'. - * src/gzip/ftgzip.c (FT_Stream_OpenGzip): Init `zip' and - `zip_buff'. - * src/lzw/ftlzw.c (FT_Stream_OpenLZW): Init `zip'. - * src/bzip2/ftbzip2.c (FT_Stream_OpenBzip2): Init `zip'. - -2011-06-14 suzuki toshiya - - [base] Fix g++4.6 compiler warnings in src/base/*.c. - - Passing uninitialized pointer to FT_NEW() families is - not problematic theoretically (as far as the returned - pointer is checked before writing), but g++4.6 dislikes - it and warns by -Wuninitialized. Initialize them by NULL. - - * src/base/ftobjs.c (FT_Stream_New): Init `stream'. - (new_memory_stream): Ditto. - (FT_New_GlyphSlot): Init `slot'. - (FT_CMap_New): Init `cmap'. - (open_face_PS_from_sfnt_stream): Init `sfnt_ps'. - (Mac_Read_POST_Resource): Init `pfb_data'. - (Mac_Read_sfnt_Resource): Init `sfnt_data'. - * src/base/ftrfork.c (FT_Raccess_Get_DataOffsets): - Init `offsets_internal' and `ref'. - (raccess_guess_darwin_hfsplus): Init `newpath'. - (raccess_guess_darwin_newvfs): Ditto. - * src/base/ftbitmap.c (ft_bitmap_assure_buffer): - Init `buffer'. - * src/base/ftstroke.c (FT_Stroker_New): Init `stroker'. - -2011-06-14 suzuki toshiya - - [gxvalid] Cleanup. - - Some invalid, overrunning, unrecommended non-zero values - are cared in paranoid validation mode only. There are - many lines looking like: - - if ( valid->root->level >= FT_VALIDATE_PARANOID ) - FT_INVALID_xxx; - - To simplify them, GXV_SET_ERR_IF_PARANOID( err ) is - introduced for more paranoid validation in future. - - * src/gxvalid/gxvcommn.h (IS_PARANOID_VALIDATION): - New macro to assure valid->root->level is more or - equal to FT_VALIDATE_PARANOID. (GXV_SET_ERR_IF_PARANOID): - New macro to raise an error if in paranoid validation. - * src/gxvalid/gxvcommn.c: Use GXV_SET_ERR_IF_PARANOID(). - * src/gxvalid/gxvfeat.c: Ditto. - * src/gxvalid/gxvjust.c: Ditto. - * src/gxvalid/gxvkern.c: Ditto. - * src/gxvalid/gxvmort.c: Ditto. - * src/gxvalid/gxvmort0.c: Ditto. - * src/gxvalid/gxvmort1.c: Ditto. - * src/gxvalid/gxvmort2.c: Ditto. - * src/gxvalid/gxvmorx1.c: Ditto. - * src/gxvalid/gxvmorx2.c: Ditto. - -2011-06-14 suzuki toshiya - - [gxvalid] Fix gcc4.6 compiler warnings in gxvtrak.c. - - * src/gxvalid/gxvtrak.c (gxv_trak_trackTable_validate): - Check different entries pointing same tracking value. - (gxv_trak_validate): Remove unused variable `table_size'. - -2011-06-14 suzuki toshiya - - [gxvalid] Fix gcc4.6 compiler warnings in gxvmorx*.c. - - * src/gxvalid/gxvmorx.c (gxv_morx_subtables_validate): - Conditionalize unvalidated variable `subFeatureFlags'. - (gxv_morx_chain_validate): Conditionalize unvalidated - variable `defaultFlags'. - - * src/gxvalid/gxvmorx0.c - (gxv_morx_subtable_type0_entry_validate): - Conditionalize unvalidated variables; `markFirst', - `dontAdvance', `markLast', `verb'. - - * src/gxvalid/gxvmorx1.c - (gxv_morx_subtable_type1_entry_validate): Conditionalize - unvalidated variables; `setMark', `dontAdvance'. - - * src/gxvalid/gxvmorx2.c - (gxv_morx_subtable_type2_ligActionOffset_validate): - Conditionalize unvalidated variables; `last', `store'. - Checking for overrunning offset is added. - (gxv_morx_subtable_type2_entry_validate): - Conditionalize unvalidated variables; `setComponent', - `dontAdvance', `performAction'. - (gxv_morx_subtable_type2_ligatureTable_validate): - Check if the GID for ligature does not exceed the - max GID in `maxp' table. - - * src/gxvalid/gxvmort5.c - (gxv_morx_subtable_type5_InsertList_validate): - Conditionalize unvalidated loading of `insert_glyphID' - array. (gxv_morx_subtable_type5_entry_validate): - Conditionalize unvalidated variables; `setMark', - `dontAdvance', `currentIsKashidaLike', - `markedIsKashidaLike', `currentInsertBefore', - `markedInsertBefore'. - -2011-06-14 suzuki toshiya - - [gxvalid] Fix gcc4.6 compiler warnings in gxvmort*.c. - - * src/gxvalid/gxvmort.c (gxv_mort_subtables_validate): - Conditionalize unvalidated variable `subFeatureFlags'. - (gxv_mort_chain_validate): Conditionalize unvalidated - variable `defaultFlags'. - - * src/gxvalid/gxvmort0.c - (gxv_mort_subtable_type0_entry_validate): Check the - conflict of the marks for the glyphs. - - * src/gxvalid/gxvmort1.c - (gxv_mort_subtable_type1_offset_to_subst_validate): - Local variables `min_gid', `max_gid' are replaced by - variables in the validator. - (gxv_mort_subtable_type1_entry_validate): Conditionalize - unvalidated variables; `setMark', `dontAdvance'. - (gxv_mort_subtable_type1_substTable_validate): - Validate the GID by the min/max GIDs in the validator. - - * src/gxvalid/gxvmort2.c - (gxv_mort_subtable_type2_ligActionOffset_validate): - Conditionalize unvalidated variables; `last', `store'. - Checking for overrunning offset is added. - (gxv_mort_subtable_type2_entry_validate): - Conditionalize unvalidated variables; `setComponent', - `dontAdvance'. - (gxv_mort_subtable_type2_ligatureTable_validate): - Check if the GID for ligature does not exceed the - max GID in `maxp' table. - - * src/gxvalid/gxvmort5.c - (gxv_mort_subtable_type5_InsertList_validate): - Conditionalize unvalidated loading of `insert_glyphID' - array. (gxv_mort_subtable_type5_entry_validate): - Conditionalize unvalidated variables; `setMark', - `dontAdvance', `currentIsKashidaLike', - `markedIsKashidaLike', `currentInsertBefore', - `markedInsertBefore'. - -2011-06-14 suzuki toshiya - - [gxvalid] Fix gcc4.6 compiler warnings in gxvkern.c. - - * src/gxvalid/gxvkern.c - (gxv_kern_subtable_fmt0_pairs_validate): Conditionalize - unvalidated variable `kernValue'. - (gxv_kern_subtable_fmt1_entry_validate): Conditionalize - unvalidated variables; `push', `dontAdvance', `kernAction', - `kernValue'. - (gxv_kern_coverage_new_apple_validate): Conditionalize - trace-only variables; `kernVertical', `kernCrossStream', - `kernVariation'. - (gxv_kern_coverage_classic_apple_validate): Conditionalize - trace-only variables; `horizontal', `cross_stream'. - (gxv_kern_coverage_classic_microsoft_validate): - Conditionalize trace-only variables; `horizontal', - `minimum', `cross_stream', `override'. - (gxv_kern_subtable_validate): Conditionalize trace-only - variables; `version', `tupleIndex'. - -2011-06-14 suzuki toshiya - - [gxvalid] Fix gcc4.6 compiler warnings in gxvjust.c. - - * src/gxvalid/gxvjust.c (gxv_just_check_max_gid): - New function to unify the checks of too large GID. - (gxv_just_wdp_entry_validate): Conditionalize unvalidated - variables; `beforeGrowLimit', `beforeShrinkGrowLimit', - `afterGrowLimit', `afterShrinkGrowLimit', `growFlags', - `shrinkFlags'. Additional check for non-zero values in - unused storage `justClass' is added. - (gxv_just_actSubrecord_type0_validate): Conditionalize - unvalidated variable `order'. GID is checked by - gxv_just_check_max_gid(). Additional check for upside-down - relationship between `lowerLimit' and `upperLimit' is added. - (gxv_just_actSubrecord_type1_validate): GID is checked by - gxv_just_check_max_gid(). - (gxv_just_actSubrecord_type2_validate): Conditionalize - unvalidated variable `substThreshhold'. GID is checked by - gxv_just_check_max_gid(). - (gxv_just_actSubrecord_type5_validate): GID is checked by - gxv_just_check_max_gid(). - (gxv_just_classTable_entry_validate): Conditionalize - unvalidated variables; `setMark', `dontAdvance', - `markClass', `currentClass'. - -2011-06-14 suzuki toshiya - - [gxvalid] Preparation to fix gcc4.6 compiler warnings. - - * src/gxvalid/gxvcommn.h (GXV_LOAD_TRACE_VARS): New macro to - conditionalize the variable which is only used for trace messages. - Automatically set by FT_DEBUG_LEVEL_TRACE. - (GXV_LOAD_UNUSED_VARS): New macro to conditionalize the loading of - unvalidated variables. Undefined by default to calm gcc4.6 warning. - (GXV_ValidatorRec.{min_gid,max_gid}): New variables to hold defined - GID ranges, for the comparison of GID ranges in different subtables. - -2011-06-08 Werner Lemberg - - [autofit] Remove unused structure member. - - * src/autofit/afhints.h (AF_SegmentRec): Remove `contour'. - * src/autofit/aflatin.c (af_latin_hints_compute_segments), - src/autofit/aflatin2.c (af_latin2_hints_compute_segments): Updated. - -2011-05-30 Werner Lemberg - - Fix g++ 4.6 compilation. - - * src/autofit/afhints.c (af_glyph_hints_dump_segments, - af_glyph_hints_dump_edges): Use cast. - -2011-05-30 Werner Lemberg - - Fix gcc 4.6 compiler warnings. - - * src/autofit/afcjk.c (af_cjk_metrics_init_blues): Use casts and - remove unused variables. - * src/autofit/aflatin.c (af_latin_hints_compute_edges): Comment out - `up_dir'. - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Use `height_org' - and `width_org' conditionalized. - -2011-05-28 suzuki toshiya - - [mac] Conditionalize the inclusion of `AvailabilityMacros.h'. - - The native SDK on earliest Mac OS X (10.0-10.1) did not have - `AvailabilityMacros.h'. To prevent the inclusion of missing - header file, ECANCELED (introduced in 10.2) in POSIX header - file is checked to detect the system version. - - * include/freetype/config/ftconfig.h: Conditionalize the - inclusion of `AvailabilityMacros.h'. - * builds/unix/ftconfig.in: Ditto. - * builds/vms/ftconfig.h: Ditto. - -2011-05-27 Werner Lemberg - - [autofit] Improve tracing of hinting process. - - * src/autofit/aflatin.c (af_latin_hint_edges): Add tracing message - `ADJUST'. - -2011-05-26 Werner Lemberg - - [autofit] Fix trace message. - - * src/autofit/aflatin.c (af_latin_hint_edges): Show correct value in - tracing message. - -2011-05-24 Daniel Zimmermann - - Reduce warnings for MS Visual Studio 2010. - - * src/autofit/afhints.c (af_glyph_hints_get_num_segments, - af_glyph_hints_get_segment_offset) [!FT_DEBUG_AUTOFIT]: Provide - return value. - * src/cff/cffgload.c (cff_slot_load): Add cast. - * src/truetype/ttobjs.c (tt_check_trickyness_sfnt_ids): Use proper - loop variable type. - -2011-05-16 suzuki toshiya - - Automake component `builds/unix/install-sh' is removed. - - * builds/unix/install-sh: Removed. It is not needed to - include repository, because autogen.sh installs it. - * builds/unix/.gitignore: Register install-sh. - -2011-05-12 suzuki toshiya - - [autofit] Make trace message for CJK bluezone more verbose. - -2011-05-08 Just Fill Bugs - suzuki toshiya - - [autofit] Add bluezones for CJK Ideographs. - - To remove extrema of vertical strokes of CJK Ideographs at - low resolution and make the top and bottom horizontal stems - aligned, bluezones for CJK Ideographs are calculated from - sample glyphs. At present, vertical bluezones (bluezones - to align vertical stems) are disabled by default. For detail, see - https://lists.gnu.org/archive/html/freetype-devel/2011-04/msg00070.html - https://lists.gnu.org/archive/html/freetype-devel/2011-04/msg00092.html - https://lists.gnu.org/archive/html/freetype-devel/2011-05/msg00001.html - - * include/freetype/internal/fttrace.h: New trace component `afcjk'. - * src/autofit/afcjk.h (AF_CJK{Blue,Axis,Metric}Rec): Add CJK version - for AF_Latin{Blue,Axis,Metric}Rec. - (af_cjk_metrics_check_digits): Ditto, shared with Indic module. - (af_cjk_metrics_init_widths): Ditto. - (af_cjk_metrics_init): Take AF_CJKMetric instead of AF_LatinMetric. - (af_cjk_metrics_scale): Ditto (declaration). - (af_cjk_hints_init): Ditto (declaration). - (af_cjk_hints_apply): Ditto (declaration). - * src/autofit/afcjk.c (af_cjk_metrics_scale): Ditto (body). - (af_cjk_hints_init): Ditto (body). - (af_cjk_hints_apply): Ditto (body). - (af_cjk_metrics_init_widths): Duplicate af_latin_metrics_init_widths. - (af_cjk_metrics_check_digits): Duplicate af_latin_metrics_check_digits. - (af_cjk_metrics_init): Call CJK bluezone initializer. - (af_cjk_metrics_scale_dim): Add code to scale bluezones. - (af_cjk_hints_compute_blue_edges): New function, CJK version of - af_latin_hints_compute_blue_edges. - (af_cjk_metrics_init_blues): New function, CJK version of - af_latin_metrics_init_blues. - (af_cjk_hint_edges): Add code to align the edge stems to blue zones. - - * src/autofit/afindic.c (af_indic_metrics_init): Take AF_CJKMetric - instead of AF_LatinMetric, and initialize as af_cjk_metrics_init. - However bluezones are not initialized. - (af_indic_metrics_scale): Take AF_CJKMetric instead of AF_LatinMetric. - (af_indic_hints_init): Ditto. - (af_indic_hints_apply): Ditto. - - * docs/CHANGES: Note about CJK bluezone support. - -2011-05-06 Werner Lemberg - - [autofit] Remove unused struct member. - - * src/autofit/aflatin.h (AF_LatinAxis): Remove `control_overshoot'. - -2011-05-04 Werner Lemberg - - * src/autofit/aflatin.c (af_latin_metrics_scale_dim): Simplify. - -2011-05-01 Just Fill Bugs - Werner Lemberg - - [autofit] Add more debugging functions. - - * src/autofit/afhints.c (af_glyph_hints_get_num_segments, - af_glyph_hints_get_segment_offset): New functions. - -2011-05-01 suzuki toshiya - - Add new option `--disable-mmap' to configure script. - - * builds/unix/configure.raw: New option `--disable-mmap' - is added. It is for the developers to simulate the systems - without mmap() (like 4.3BSD, minix etc) on POSIX systems. - -2011-04-30 suzuki toshiya - - [truetype] Always recalculate the sfnt table checksum. - - * src/truetype/ttobjs.c (tt_get_sfnt_checksum): Recalculate - the sfnt table checksum even if non-zero value is written in - the TrueType font header. Some bad PDF generators write - wrong values. For details see examples and benchmark tests - of the latency by recalculation: - https://lists.gnu.org/archive/html/freetype-devel/2011-04/msg00091.html - https://lists.gnu.org/archive/html/freetype-devel/2011-04/msg00096.html - -2011-04-30 suzuki toshiya - - [truetype] Register a set of tricky fonts, NEC FA family. - - * src/truetype/ttobjs.c (tt_check_trickyness_sfnt_ids): - Add 8 checksum sets for NEC FA family. For the tricky fonts - without some tables (e.g. NEC FA fonts lack cvt table), - extra check is added to assure that a zero-length table in the - registry is not included in the font. - -2011-04-29 suzuki toshiya - - [truetype] Fix a bug in the sfnt table checksum getter. - - * src/truetype/ttobjs.c (tt_get_sfnt_checksum): Check the - return value of face->goto_table() correctly. - -2011-04-28 Werner Lemberg - - [autofit] Improve tracing messages. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues, - af_latin_align_linked_edge, af_latin_hint_edges): Do it. - -2011-04-25 Kan-Ru Chen - - [truetype] Always check the checksum to identify tricky fonts. - - Because some PDF generators mangle the family name badly, - the trickyness check by the checksum should be invoked always. - For sample PDF, see - https://lists.gnu.org/archive/html/freetype-devel/2011-04/msg00073.html - - * src/truetype/ttobjs.c (tt_check_trickyness): Even when - tt_check_trickyness_family() finds no trickyness, - tt_check_trickyness_sfnt_ids() is invoked. - -2011-04-22 suzuki toshiya - - [autofit] Add more Indic scripts with hanging baseline. - - * src/autofit/afindic.c (af_indic_uniranges): Tibetan, Limbu, - Sundanese, Meetei Mayek, Syloti Nagri and Sharada scripts are - added. - -2011-04-21 Behdad Esfahbod - - Always ignore global advance. - - This makes FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH redundant, - deprecated, and ignored. The new behavior is what every major user - of FreeType has been requesting. Global advance is broken in many - CJK fonts. Just ignoring it by default makes most sense. - - * src/truetype/ttdriver.c (tt_get_advances), - src/truetype/ttgload.c (TT_Get_HMetrics, TT_Get_VMetrics, - tt_get_metrics, compute_glyph_metrics, TT_Load_Glyph), - src/truetype/ttgload.h: Implement it. - - * docs/CHANGES: Updated. - -2011-04-21 rainy6144 - - [autofit] Blur CJK stems if too many to preserve their gaps. - - When there are too many stems to preserve their gaps in the - rasterization of CJK Ideographs at a low resolution, blur the - stems instead of showing clumped stems. See - https://lists.gnu.org/archive/html/freetype-devel/2011-02/msg00011.html - https://lists.gnu.org/archive/html/freetype-devel/2011-04/msg00046.html - for details. - - * src/autofit/afcjk.c (af_cjk_hint_edges): Store the position of - the previous stem by `has_last_stem' and `last_stem_pos', and skip - a stem if the current and previous stem are too near to preserve - the gap. - -2011-04-18 Werner Lemberg - - Integrate autofitter debugging stuff. - - * devel/ftoption.h, include/freetype/config/ftoption.h - (FT_DEBUG_AUTOFIT): New macro. - - * include/freetype/internal/fttrace.h: Add trace components for - autofitter. - - * src/autofit/aftypes.h (AF_LOG): Removed. - (_af_debug): Removed. - - * src/autofit/*: s/AF_DEBUG/FT_DEBUG_AUTOFIT/. - s/AF_LOG/FT_TRACE5/. - Define FT_COMPONENT where necessary. - -2011-04-18 Werner Lemberg - - Synchronize config files. - - * builds/unix/ftconfig.in: Copy missing assembler routines from - include/freetype/config/ftconfig.h. - -2011-04-13 Werner Lemberg - - [psaux] Fix Savannah bug #33047. - - Patch submitted by anonymous reporter. - - * src/psaux/psobjs.c (ps_table_add): Use FT_PtrDist for pointer - difference. - -2011-04-11 Kan-Ru Chen - - Fix reading of signed integers from files on 64bit platforms. - - Previously, signed integers were converted to unsigned integers, but - this can fail because of sign extension. For example, 0xa344a1eb - becomes 0xffffffffa344a1eb. - - We now do the reverse which is always correct because the integer - size is the same during the cast from unsigned to signed. - - * include/freetype/internal/ftstream.h, src/base/ftstream.c - (FT_Stream_Get*): Replace with... - (FT_Stream_GetU*): Functions which read unsigned integers. - Update all macros accordingly. - - * src/gzip/ftgzip.c (ft_gzip_get_uncompressed_size): Updated. - -2011-04-07 Werner Lemberg - - Update Unicode ranges for CJK autofitter; in particular, add Hangul. - - * src/autofit/afcjk.c (af_cjk_uniranges): Update to Unicode 6.0. - -2011-04-04 Werner Lemberg - - Fix formatting of autofit debug dumps. - - * src/autofit/afhints.c (af_glyph_hints_dump_points, - af_glyph_hints_dump_segments, af_glyph_hints_dump_edges): Adjust - column widths. - -2011-03-30 Werner Lemberg - - * src/autofit/aftypes.h (AF_OutlineRec): Removed, unused. - -2011-03-24 Werner Lemberg - - * src/cff/cfftypes.h (CFF_MAX_CID_FONTS): Increase to 256. - This limit is given on p. 37 of Adobe Technical Note #5014. - -2011-03-23 Werner Lemberg - - * src/truetype/ttpload.c (tt_face_load_loca): Fix mismatch warning. - -2011-03-20 Werner Lemberg - - * src/sfnt/sfobjs.c (sfnt_open_font): Check number of TTC subfonts. - -2011-03-19 Werner Lemberg - - More C++ compilation fixes. - - * src/autofit/afhints.c (af_glyph_hints_dump_points, - af_glyph_hints_dump_segments, af_glyph_hints_dump_edges) - [__cplusplus]: Protect with `extern "C"'. - -2011-03-18 Werner Lemberg - - C++ compilation fixes. - - * src/autofit/aflatin.c (af_latin_hints_apply), src/autofit/afcjk.c - (af_cjk_hints_apply): Use cast for `dim'. - -2011-03-17 Alexei Podtelezhnikov - - A better fix for Savannah bug #32671. - - * src/smooth/ftgrays.c (gray_render_conic): Clean up code and - replace WHILE loop with a more natural DO-WHILE construct. - -2011-03-16 Werner Lemberg . - - * src/base/ftstroke.c (FT_StrokerRec): Remove unused `valid' field. - Suggested by Graham Asher. - -2011-03-09 Werner Lemberg - - Make FT_Sfnt_Table_Info return the number of SFNT tables. - - * src/sfnt/sfdriver.c (sfnt_table_info): Implement it. - * include/freetype/tttables.h: Update documentation. - * docs/CHANGES: Updated. - -2011-03-07 Bram Tassyns - - [cff] Fix Savannah bug #27988. - - * src/cff/cffobjs.c (remove_style): New function. - (cff_face_init): Use it to strip off the style part of the family - name. - -2011-03-07 Werner Lemberg - - * docs/CHANGES: Updated. - -2011-03-07 Alexei Podtelezhnikov - - Quick fix for Savannah bug #32671. - - This isn't the optimal solution yet, but it restores the previous - rendering quality (more or less). - - * src/smooth/ftgrays.c (gray_render_conic): Do more splitting. - -2011-03-06 Werner Lemberg - - Fix autohinting fallback. - - * src/base/ftobjs.c (FT_Load_Glyph): Assure that we only check TTFs, - ignoring CFF-based OTFs. - -2011-02-27 Werner Lemberg - - Add AF_CONFIG_OPTION_USE_WARPER to control the autofit warper. - - * devel/ftoption.h, include/freetype/config/ftoption.h - (AF_CONFIG_OPTION_USE_WARPER): New macro. - * src/autofit/aftypes.h (AF_USE_WARPER): Remove. - - * src/autofit/*: s/AF_USE_WARPER/AF_CONFIG_OPTION_USE_WARPER/. - - * src/autofit/afwarp.c [!AF_CONFIG_OPTION_USE_WARPER]: Replace dummy - variable assignment with a typedef. - -2011-02-26 Werner Lemberg - - [autofit] Slight simplifications. - - * src/autofit/aflatin.c (af_latin_hints_link_segments): Remove - test which always returns false. - (af_latin_hints_compute_blue_edges): Remove redundant assignment. - -2011-02-24 Werner Lemberg - - * docs/PROBLEMS: Mention rendering differences on different - platforms. - Suggested and worded by Jason Owen . - -2011-02-24 Werner Lemberg - - [autofit] Comment out unused code. - - * src/autofit/aflatin.c, src/autofit/aflatin2.c - (af_latin_hints_compute_edges): Do it. - -2011-02-24 Werner Lemberg - - * src/autofit/afhints.h (AF_GlyphHints): Remove unused field. - -2011-02-20 suzuki toshiya - - [cache] Fix an off-by-one bug in `FTC_Manager_RemoveFaceID'. - Found by , see detail in - - https://lists.gnu.org/archive/html/freetype/2011-01/msg00023.html - - * src/cache/ftccache.c (FTC_Cache_RemoveFaceID): Check the node - buckets[cache->p + cache->mask] too. - -2011-02-19 Kevin Kofler - - Fall back to autohinting if a TTF/OTF doesn't contain any bytecode. - This is Savannah patch #7471. - - * src/base/ftobjs.c (FT_Load_Glyph): Implement it. - -2011-02-19 John Tytgat - - [cff] Fix subset prefix removal. - This is Savannah patch #7465. - - * src/cff/cffobjs.c (remove_subset_prefix): Update length after - subset prefix removal. - -2011-02-13 Bradley Grainger - - Add inline assembly version of FT_MulFix for MSVC. - - * include/freetype/config/ftconfig.h: Ported the FT_MulFix_i386 - function from GNU inline assembly syntax (see #ifdef __GNUC__ block - above) to MASM syntax for Microsoft Visual C++. - -2011-02-13 Bradley Grainger - - Add project and solution files in Visual Studio 2010 format. - - * builds/win32/.gitignore: Ignore user-specific cache files. - * builds/win32/vc2010/: Add VS2010 project & solution files, created - by upgrading builds/win32/vc2008/freetype.vcproj. - * objs/.gitignore: Ignore Visual Studio output files. - -2011-02-01 Werner Lemberg - - * src/autofit/afdummy.c: Include `aferrors.h'. - Problem reported by Chris Liddell . - -2011-02-01 Werner Lemberg - - [cff] Ignore unknown operators in charstrings. - Patch suggested by Miles.Lau . - - * src/cff/cffgload.c (cff_decoder_parse_charstrings): Emit tracing - message for unknown operators and continue instead of exiting with a - syntax error. - -2011-02-01 Werner Lemberg - - [truetype] FT_LOAD_PEDANTIC now affects `prep' and `fpgm' also. - - * src/truetype/ttgload.c (tt_loader_init): Handle - `FT_LOAD_PEDANTIC'. - * src/truetype/ttobjs.c (tt_size_run_fpgm, tt_size_run_prep, - tt_size_init_bytecode, tt_size_ready_bytecode): New argument to - handle pedantic mode. - * src/truetype/ttobjs.h: Updated. - -2011-01-31 Werner Lemberg - - [truetype] Protect jump instructions against endless loops. - - * src/truetype/interp.c (DO_JROT, DO_JMPR, DO_JROF): Exit with error - if offset is zero. - -2011-01-31 Werner Lemberg - - [truetype] Improve handling of invalid references. - - * src/truetype/interp.c: Set even more TT_Err_Invalid_Reference - error codes only if pedantic hinting is active. At the same time, - try to provide sane values which hopefully allow useful - continuation. Exception to this is CALL and LOOPCALL – due to - possible stack corruption it is necessary to bail out. - -2011-01-31 Werner Lemberg - - [truetype] Improve handling of stack underflow. - - * src/truetype/ttinterp.c (TT_RunIns, Ins_FLIPPT, Ins_DELTAP, - Ins_DELTAC): Exit with error only if `pedantic_hinting' is set. - Otherwise, try to do something sane. - -2011-01-30 Werner Lemberg - - * src/sfnt/ttmtx.c (tt_face_load_hmtx): Fix tracing message. - -2011-01-30 LIU Sun-Liang - - [truetype]: Fix behaviour of MIAP for invalid arguments. - - * src/truetype/ttinterp.c (Ins_MIAP): Set reference points even in - case of error. - -2011-01-18 Werner Lemberg - - [truetype] Fix handling of MIRP instruction. - - Thanks to Greg Hitchcock who explained the issue. - - * src/truetype/ttinterp.c (Ins_MIRP): Replace a `>=' operator with - `>' since the description in the specification is incorrect. - This fixes, for example, glyph `two' in font `Helvetica Neue LT Com - 65 medium' at 15ppem. - -2011-01-15 suzuki toshiya - - Fix ARM assembly code in include/freetype/config/ftconfig.h. - - * include/freetype/config/ftconfig.h (FT_MulFix_arm): - Copy the maintained code from builds/unix/ftconfig.in. - Old GNU binutils could not accept the reduced syntax - `orr %0, %2, lsl #16'. Un-omitted syntax like RVCT, - `orr %0, %0, %2, lsl #16' is better. Reported by - Johnson Y. Yan. The bug report by Qt developers is - considered too. - - https://bugreports.qt.io/browse/QTBUG-6521 - -2011-01-15 Werner Lemberg - - [raster] Make bbox handling the same as with Microsoft's rasterizer. - - Right before B/W rasterizing, the bbox gets simply rounded to - integers. This fixes, for example, glyph `three' in font `Helvetica - Neue LT Com 65 Medium' at 11ppem. - - Thanks to Greg Hitchcock who explained this behaviour. - - * src/raster/ftrend1.c (ft_raster1_render): Implement it. - -2011-01-15 suzuki toshiya - - Copy -mcpu=* & -march=* options from CFLAGS to LDFLAGS. - - * builds/unix/configure.raw: Consider recent gcc-standard - flags to specify architecture in CFLAGS & LDFLAGS - harmonization. Requested by Savannah bug #32114, to - support multilib feature of BuildRoot SDK correctly. - -2011-01-15 suzuki toshiya - - Fix off-by-one bug in CFLAGS & LDFLAGS harmonizer. - - * builds/unix/configure.raw: Some important options that - included in CFLAGS but not in LDFLAGS are copied to - LDFLAGS, but the last option in CFLAGS was not checked. - -2011-01-13 Werner Lemberg - - [raster] Add undocumented drop-out rule to the other bbox side also. - - * src/raster/ftraster.c (Vertical_Sweep_Drop, - Horizontal_Sweep_Drop): Implement it. - -2011-01-13 Werner Lemberg - - [raster] Reduce jitter value. - - This catches a rendering problem with glyph `x' from Tahoma at - 10ppem. It seems that the increase of the precision in the change - from 2009-06-11 makes a larger jitter value unnecessary. - - * src/raster/ftraster.c (Set_High_Precision): Implement it. - -2011-01-13 Werner Lemberg - - [raster] Handle drop-outs at glyph borders according to Microsoft. - - If a drop-out rule would switch on a pixel outside of the glyph's - bounding box, use the right (or top) pixel instead. This is an - undocumented feature, but some fonts like `Helvetica Neue LT Com 65 - Medium' heavily rely on it. - - Thanks to Greg Hitchcock who explained this behaviour. - - * src/raster/ftraster.c (Vertical_Sweep_Drop, - Horizontal_Sweep_Drop): Implement it. - -2011-01-09 suzuki toshiya - - [cache] Fix Savannah bug #31923, patch drafted by Harsha. - - When a node comparator changes the cached nodes during the - search of a node matching with queried properties, the - pointers obtained before the function should be updated to - prevent the dereference to freed or reallocated nodes. - To minimize the rescan of the linked list, the update is - executed when the comparator notifies the change of cached - nodes. This change depends previous change: - 38b272ffbbdaae276d636aec4ef84af407d16181 - - * src/cache/ftccache.h (FTC_CACHE_LOOKUP_CMP): Rescan the - top node if the cached nodes are changed. - * src/cache/ftccache.c (FTC_Cache_Lookup): Ditto. - -2011-01-09 suzuki toshiya - - [cache] Notice if a cache query induced the node list change. - - Some node comparators (comparing the cache node contents and the - properties specified by the query) can flush the cache node to - prevent the cache inflation. The change may invalidate the pointers - to the node obtained before the node comparison, so it should be - noticed to the caller. The problem caused by the cache node - changing is reported by Harsha, see Savannah bug #31923. - - * src/cache/ftccache.h (FTC_Node_CompareFunc): Add new argument - `FT_Bool* list_changed' to indicate the change of the cached nodes - to the caller. - (FTC_CACHE_LOOKUP_CMP): Watch the change of the cached nodes by - `_list_changed'. - (FTC_CACHE_TRYLOOP_END): Take new macro argument `_list_changed' - and update it when `FTC_Manager_FlushN' flushes any nodes. - - * src/cache/ftccback.h (ftc_snode_compare): Updated to fit with new - FTC_Node_CompareFunc type. - (ftc_gnode_compare): Ditto. - - * src/cache/ftcbasic.c: Include FT_INTERNAL_OBJECTS_H to use - TRUE/FALSE macros. - (ftc_basic_gnode_compare_faceid): New argument `FT_Bool* - list_changed' to indicate the change of the cache nodes (anyway, it - is always FALSE). - - * src/cache/ftccmap.c: Include FT_INTERNAL_OBJECTS_H to use - TRUE/FALSE macros. - (ftc_cmap_node_compare): New argument `FT_Bool* list_changed' to - indicate the change of the cache nodes (anyway, it is always FALSE). - (ftc_cmap_node_remove_faceid): Ditto. - - * src/cache/ftccache.c (FTC_Cache_NewNode): Pass a NULL pointer to - `FTC_CACHE_TRYLOOP_END', because the result is not needed. - (FTC_Cache_Lookup): Watch the change of the cache nodes by - `list_changed'. - (FTC_Cache_RemoveFaceID): Ditto. - - * src/cache/ftcglyph.c: Include FT_INTERNAL_OBJECTS_H to use - TRUE/FALSE macros. - (ftc_gnode_compare): New argument `FT_Bool* list_changed' to - indicate the change of the cache nodes (anyway, it is always FALSE). - (FTC_GNode_Compare): New argument `FT_Bool* list_changed' to be - passed to `ftc_gnode_compare'. - * src/cache/ftcglyph.h (FTC_GNode_Compare): Ditto. - - * src/cache/ftcsbits.c (ftc_snode_compare): New argument `FT_Bool* - list_changed' to indicate the change of the cache nodes, anyway. It - is updated by `FTC_CACHE_TRYLOOP'. - (FTC_SNode_Compare): New argument `FT_Bool* list_changed' to be - passed to `ftc_snode_compare'. - * src/cache/ftcsbits.h (FTC_SNode_Compare): Ditto. - -2011-01-09 suzuki toshiya - - [cache] Fit `FTC_GNode_Compare' to `FTC_Node_CompareFunc'. - - * src/cache/ftcglyph.h (FTC_GNode_Compare): Add the 3rd - argument `FTC_Cache cache' to fit FTC_Node_CompareFunc - prototype. - * src/cache/ftcglyph.c (FTC_GNode_Compare): Ditto. Anyway, - `cache' is not used by its child `ftc_gnode_compare'. - -2011-01-09 suzuki toshiya - - [cache] Deduplicate the code to get the top node by a hash. - - There are several duplicated code fragments getting the top node - from a cache by a given hash, like: - - idx = hash & cache->mask; - if ( idx < cache->p ) - idx = hash & ( cache->mask * 2 + 1 ); - pnode = cache->buckets + idx; - - To remove duplication, a cpp-macro to do same work - `FTC_NODE__TOP_FOR_HASH' is introduced. For non-inlined - configuration, non-`ftc_get_top_node_for_hash' is also introduced. - - * src/cache/ftccache.h (FTC_NODE__TOP_FOR_HASH): Declare - and implement inlined version. - (FTC_CACHE_LOOKUP_CMP): Use `FTC_NODE__TOP_FOR_HASH'. - * src/cache/ftccache.c (ftc_get_top_node_for_hash): Non-inlined - version. - (ftc_node_hash_unlink): Use `FTC_NODE__TOP_FOR_HASH'. - (ftc_node_hash_link): Ditto. - (FTC_Cache_Lookup): Ditto. - -2011-01-09 suzuki toshiya - - [cache] inline-specific functions are conditionalized. - - * src/cache/ftcglyph.c (FTC_GNode_Compare): Conditionalized for - inlined configuration. This function is a thin wrapper of - `ftc_gnode_compare' for inlined `FTC_CACHE_LOOKUP_CMP' (see - `nodecmp' argument). Under non-inlined configuration, - `ftc_gnode_compare' is invoked by `FTC_Cache_Lookup', via - `FTC_Cache->clazz.node_compare'. - - * src/cache/ftcglyph.h (FTC_GNode_Compare): Ditto. - * src/cache/ftcsbits.c (FTC_SNode_Compare): Ditto, for - `ftc_snode_compare'. - * src/cache/ftcsbits.h (FTC_SNode_Compare): Ditto. - -2011-01-09 suzuki toshiya - - [cache] Correct a type mismatch under non-inlined config. - - * src/cache/ftcglyph.h (FTC_GCACHE_LOOKUP_CMP): `FTC_GCache_Lookup' - takes the node via a pointer `FTC_Node*', differently from cpp-macro - `FTC_CACHE_LOOKUP_CMP'. - -2011-01-06 suzuki toshiya - - Update Jamfile to include Bzip2 support. - - * Jamfile: Include src/bzip2 to project. - Comments for lzw, gzip, bzip2 are changed to clarify that - they are for compressed PCF fonts, not others. - (e.g. compressed BDF fonts are not supported yet) - -2011-01-05 suzuki toshiya - - Update Symbian project files to include Bzip2 support. - - Currently, it provides `FT_Stream_OpenBzip2' that returns - unimplemented error always, to prevent unresolved symbol - error for the applications designed for Unix systems. - - * builds/symbian/bld.inf: Include ftbzip2.h. - * builds/symbian/freetype.mmp: Include ftbzip2.c. - -2011-01-05 suzuki toshiya - - Update classic MacOS makefiles to include Bzip2 support. - - Currently, it provides `FT_Stream_OpenBzip2' that returns - unimplemented error always, to prevent unresolved symbol - error for the applications designed for Unix systems. - - * builds/mac/FreeType.m68k_cfm.make.txt: Include ftbzip2.c.o. - * builds/mac/FreeType.m68k_far.make.txt: Ditto. - * builds/mac/FreeType.ppc_carbon.make.txt: Include ftbzip2.c.x. - * builds/mac/FreeType.ppc_classic.make.txt: Ditto. - -2011-01-05 suzuki toshiya - - Update Amiga makefiles to include Bzip2 support. - - Currently, it provides `FT_Stream_OpenBzip2' that returns - unimplemented error always, to prevent unresolved symbol - error for the applications designed for Unix systems. - - * builds/amiga/makefile: Include bzip2.ppc.o built from ftbzip2.c. - * builds/amiga/makefile.os4: Include bzip2.o built from ftbzip2.c. - * builds/amiga/smakefile: Ditto. - -2011-01-05 suzuki toshiya - - Update pkg-config tools to reflect Bzip2 support. - - * builds/unix/freetype-config.in: Include `-lbz2' to - --libs output, if built with Bzip2 support. - * builds/unix/freetype2.in: Ditto. - -2011-01-05 suzuki toshiya - - * builds/unix/configure.raw: Remove `SYSTEM_BZ2LIB' macro. - - SYSTEM_ZLIB is used to switch the builtin zlib source - or system zlib source out of FreeType2. But ftbzip2 - module has no builtin bzip2 library and always requires - system bzip2 library. Thus SYSTEM_BZ2LIB is always yes, - it is not used. - -2011-01-03 Werner Lemberg - - */rules.mk: Handle `*pic.c' files. - -2010-12-31 Werner Lemberg - - * src/cff/cfftypes.h (CFF_MAX_CID_FONTS): Increase to 64. - Problem reported by Tom Bishop . - -2010-12-31 Werner Lemberg - - Improve bzip2 support. - - * include/freetype/ftmoderr.h: Add bzip2. - - * docs/INSTALL.ANY, docs/CHANGES: Updated. - - * src/pcf/README: Updated. - * include/freetype/internal/pcftypes.h: Obsolete, removed. - -2010-12-31 Joel Klinghed - - Add bzip2 compression support to handle *.pcf.bz2 files. - - * builds/unix/configure.raw: Test for libbz2 library. - - * devel/ftoption.h, include/freetype/config/ftoption.h - (FT_CONFIG_OPTION_USE_BZIP2): Define. - * include/freetype/config/ftheader.h (FT_BZIP2_H): Define. - - * include/freetype/ftbzip2.h: New file. - - * src/bzip2/*: New files. - - * src/pcf/pcf.h: s/gzip_/comp_/. - * src/pcf/pcfdrivr.c: Include FT_BZIP2_H. - s/gzip_/comp_/. - (PCF_Face_Init): Handle bzip2 compressed files. - - * docs/formats.txt, modules.cfg: Updated. - -2010-12-25 Harsha - - Apply Savannah patch #7422. - - If we encounter a space in a string then the sbit buffer is NULL, - height and width are 0s. So the check in ftc_snode_compare will - always pass for spaces (comparison with 255). Here the comments - above the condition are proper but the implementation is not. When - we create an snode I think it is the proper way to initialize the - width to 255 and then put a check for being equal to 255 in snode - compare function. - - * src/cache/ftcsbits.c (FTC_SNode_New): Initialize sbit widths with - value 255. - (ftc_snode_compare): Fix condition. - -2010-12-13 Werner Lemberg - - Fix parameter handling of `FT_Set_Renderer'. - Reported by Kirill Tishin . - - * src/base/ftobjs.c (FT_Set_Renderer): Increment `parameters'. - -2010-12-09 Werner Lemberg - - [cff] Allow `hlineto' and `vlineto' without arguments. - - We simply ignore such instructions. This is invalid, but it doesn't - harm; and indeed, there exist such subsetted fonts in PDFs. - - Reported by Albert Astals Cid . - - * src/cff/cffgload.c (cff_decoder_parse_charstrings) - [cff_op_hlineto]: Ignore instruction if there aren't any arguments - on the stack. - -2010-11-28 Werner Lemberg - - * Version 2.4.4 released. - ========================= - - - Tag sources with `VER-2-4-4'. - - * docs/CHANGES: Updated. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.4.4 - - * README, Jamfile (RefDoc), - builds/win32/vc2005/freetype.vcproj, builds/win32/vc2005/index.html, - builds/win32/vc2008/freetype.vcproj, builds/win32/vc2008/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualc/index.html, builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj, - builds/win32/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.4.3/2.4.4/, s/243/244/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 4. - - * builds/unix/configure.raw (version_info): Set to 12:2:6. - -2010-11-28 Alexei Podtelezhnikov - - [ftsmooth]: Minor code simplification. - - * src/smooth/ftgrays (gray_render_cubic): Do only one comparison - instead of two. - -2010-11-26 Johnson Y. Yan - - [truetype] Better multi-threading support. - - * src/truetype/ttinterp.c (TT_Load_Context): Reset glyph zone - references. - -2010-11-23 John Tytgat - - * src/psaux/t1decode.c (t1_decoder_parse_charstring): Expand - start_point, check_points, add_point, add_point1, close_contour - macros. - Remove add_contour macro. - Return error code from t1_builder_start_point and - t1_builder_check_points when there was one (instead of returning 0). - -2010-11-22 suzuki toshiya - - [truetype] Identify the tricky fonts by cvt/fpgm/prep checksums. - Some Latin TrueType fonts are still expected to be unhinted. - Fix Savannah bug #31645. - - * src/truetype/ttobjs.c (tt_check_trickyness): Divided to... - (tt_check_trickyness_family): this checking family name, and - (tt_check_trickyness_sfnt_ids): this checking cvt/fpgm/prep. - (tt_get_sfnt_checksum): Function to retrieve the sfnt checksum - for specified subtable even if cleared by lazy PDF generators. - (tt_synth_sfnt_checksum): Function to calculate the checksum. - -2010-11-18 Werner Lemberg - - [truetype] Fix `loca' handling for inconsistent number of glyphs. - Reported by Johnson Y. Yan . - - * src/truetype/ttpload.c (tt_face_load_loca): While sanitizing, - handle case where `loca' is the last table in the font. - -2010-11-18 Werner Lemberg - - [sfnt] Ignore all errors while loading `OS/2' table. - Suggested by Johnson Y. Yan . - - * src/sfnt/sfobjs.c (sfnt_load_face): Do it. - -2010-11-18 Johnson Y. Yan - - [type1] Fix matrix normalization. - - * src/type1/t1load.c (parse_font_matrix): Handle sign of scaling - factor. - -2010-11-18 Werner Lemberg - - [type1] Improve guard against malformed data. - Based on a patch submitted by Johnson Y. Yan - - - * src/type1/t1load.c (read_binary_data): Check `size'. - -2010-11-17 Werner Lemberg - - [sfnt] While tracing, output table checksums also. - - * src/sfnt/ttload.c (tt_face_load_font_dir): Do it. - -2010-11-04 suzuki toshiya - - [UVS] Fix `find_variant_selector_charmap', Savannah bug #31545. - - Since 2010-07-04, `find_variant_selector_charmap' returns - the first cmap subtable always under rogue-compatible - configuration, it causes NULL pointer dereference and - make UVS-related functions crashed. - - * src/base/ftobjs.c (Fix find_variant_selector_charmap): - Returns UVS cmap correctly. - -2010-11-01 Alexei Podtelezhnikov - - [ftsmooth] Improve rendering. - - * src/smooth/ftsmooth.c (gray_render_conic): Since version 2.4.3, - cubic deviations have been estimated _after_ UPSCALE, whereas - conic ones have been evaluated _before_ UPSCALE, which produces - inferior rendering results. Fix this. - Partially undo change from 2010-10-15 by using ONE_PIXEL/4; this has - been tested with demo images sent to the mailing list. See - - https://lists.gnu.org/archive/html/freetype-devel/2010-10/msg00055.html - - and later mails in this thread. - -2010-10-28 Werner Lemberg - - [ftraster] Minor fixes. - - Reported by Tom Bishop . - - * src/raster/ftraster.c (ULong): Remove unused typedef. - (TWorker): Remove unused variable `precision_mask'. - -2010-10-28 Werner Lemberg - - [ftraster] Fix rendering. - - Problem reported by Tom Bishop ; see - thread starting with - - https://lists.gnu.org/archive/html/freetype/2010-10/msg00049.html - - * src/raster/ftraster.c (Line_Up): Replace FMulDiv with SMulDiv - since the involved multiplication exceeds 32 bits. - -2010-10-25 suzuki toshiya - - Revert a change of `_idx' type in `FTC_CACHE_LOOKUP_CMP'. - - * src/cache/ftccache.h (FTC_CACHE_LOOKUP_CMP): Revert - the type of `_idx' from FT_PtrDist (by previous change) - to original FT_UFast, to match with FT_CacheRec. - -2010-10-24 suzuki toshiya - - [cache] Change the hash types to FT_PtrDist. - - On LLP64 platforms (e.g. Win64), FT_ULong (32-bit) - variables are inappropriate to calculate hash values - from the memory address (64-bit). The hash variables - are extended from FT_ULong to FT_PtrDist and new - hashing macro functions are introduced. The hash - values on 16-bit memory platforms are changed, but - ILP32 and LP64 are not changed. The hash value in - the cache subsystem is not reverted to the memory - address, so using signed type FT_PtrDist is safe. - - * src/cache/ftccache.h (_FTC_FACE_ID_HASH): New hash - function to replace `FTC_FACE_ID_HASH' for portability. - * src/cache/ftcmanag.h (FTC_SCALER_HASH): Replace - `FTC_FACE_ID_HASH' by `_FTC_FACE_ID_HASH'. - * src/cache/ftccmap.c (FTC_CMAP_HASH): Ditto. - - * src/cache/ftccache.h (FTC_NodeRec): The type of the - member `hash' is changed from FT_UInt32 to FT_PtrDist. - - * src/cache/ftccache.h (FTC_Cache_Lookup): The type of the - argument `hash' is changed from FT_UInt32 to FT_PtrDist. - (FTC_Cache_NewNode): Ditto. - * src/cache/ftccache.c (ftc_cache_add): Ditto. - (FTC_Cache_Lookup): Ditto. (FTC_Cache_NewNode): Ditto. - * src/cache/ftcglyph.h (FTC_GCache_Lookup): Ditto. - * src/cache/ftcglyph.c (FTC_GCache_Lookup): Ditto. - - * src/cache/ftcbasic.c (FTC_ImageCache_Lookup): The type - of the internal variable `hash' is changed to FT_PtrDist - from FT_UInt32. (FTC_ImageCache_LookupScaler): Ditto. - (FTC_SBitCache_Lookup): Ditto. - (FTC_SBitCache_LookupScaler): Ditto. - * src/cache/ftccmap.c (FTC_CMapCache_Lookup): Ditto. - * src/cache/ftccache.h (FTC_CACHE_LOOKUP_CMP): Ditto. - Also the type of the internal variable `_idx' is changed to - FT_PtrDist from FT_UFast for better pointer calculation. - -2010-10-24 suzuki toshiya - - [cache] Hide internal macros incompatible with LLP64. - - `FT_POINTER_TO_ULONG', `FTC_FACE_ID_HASH', and - `FTC_IMAGE_TYPE_HASH' are enclosed by - FT_CONFIG_OPTION_OLD_INTERNALS and hidden from - normal clients. - - For the history of these macros, see the investigation: - https://lists.gnu.org/archive/html/freetype/2010-10/msg00022.html - -2010-10-24 suzuki toshiya - - Change the type of `FT_MEM_VAL' from FT_ULong to FT_PtrDist. - - On LLP64 platforms (e.g. Win64), unsigned long (32-bit) - cannot cover the memory address (64-bit). `FT_MEM_VAL' is - used for hashing only and not dereferred, so using signed - type FT_PtrDist is safe. - - * src/base/ftdbgmem.c (FT_MEM_VAL): Change the type of the - return value from FT_ULong to FT_PtrDist. - (ft_mem_table_resize): The type of hash is changed to - FT_PtrDist. (ft_mem_table_get_nodep): Ditto. - -2010-10-24 suzuki toshiya - - Replace "%lx" for memory address by "%p", LLP64 platforms. - - On LLP64 platforms (e.g. Win64), long (32-bit) cannot cover - the memory address (64-bit). Also the casts from the pointer - type to long int should be removed to preserve the address - correctly. - - * src/raster/ftraster.c (New_Profile): Replace "%lx" by "%p". - (End_Profile) Ditto. - * src/truetype/ttinterp.c (Init_Context): Ditto. - -2010-10-15 Alexei Podtelezhnikov - - Fix thinko in spline flattening. - - FT_MAX_CURVE_DEVIATION is dependent on the value of ONE_PIXEL. - - * src/smooth/ftgrays.c (FT_MAX_CURVE_DEVIATION): Remove it and - replace it everywhere with ONE_PIXEL/8. - -2010-10-13 suzuki toshiya - - [raccess] Skip unrequired resource access rules by Darwin VFS. - - When a resource fork access rule by Darwin VFS could open the - resource fork but no font is found in it, the rest of rules - by Darwin VFS are skipped. It reduces the warnings of the - deprecated resource fork access method by recent Darwin kernel. - Fix MacPorts ticket #18859: - https://trac.macports.org/ticket/18859 - - * src/base/ftobjs.c (load_face_in_embedded_rfork): - When `FT_Stream_New' returns FT_Err_Cannot_Open_Stream, it - means that the file is possible to be `fopen'-ed but zero-sized. - Also there is a case that the resource fork is not zero-sized, - but no supported font exists in it. If a rule by Darwin VFS - falls into such cases, there is no need to try other Darwin VFS - rules anymore. Such cases are marked by vfs_rfork_has_no_font. - If it is TRUE, the Darwin VFS rules are skipped. - -2010-10-13 suzuki toshiya - - [raccess] Grouping resource access rules based on Darwin VFS. - - MacOS X/Darwin kernel supports a few tricky methods to access - a resource fork via ANSI C or POSIX interface. Current resource - fork accessor tries all possible methods to support all kernels. - But if a method could open a resource fork but no font is found, - there is no need to try other methods older than tested method. - To determine whether the rule index is for Darwin VFS, a local - function `ftrfork.c::raccess_rule_by_darwin_vfs' is introduced. - To use this function in ftobjs.c etc but it should be inlined, - it is exposed by ftbase.h. - - * src/base/ftrfork.c (FT_RFork_Rule): New enum type to identify - the rules to access the resource fork. - (raccess_guess_rec): New structure to bind the rule function and - rule enum type. - (FT_Raccess_Guess): The list of the rule functions is replaced by - (raccess_guess_table): This. This is exposed to be used by other - intra module functions. - (raccess_rule_by_darwin_vfs): A function to return a boolean - if the rule specified by the rule index is based on Darwin VFS. - -2010-10-13 suzuki toshiya - - Prevent to open a FT_Stream for zero-sized file on non-Unix. - - builds/unix/ftsystem.c prevents to open an useless stream from - zero-sized file and returns FT_Err_Cannot_Open_Stream, but the - stream drivers for ANSI C, Amiga and VMS return useless streams. - For cross-platform consistency, all stream drivers should act - same. - - * src/base/ftsystem.c (FT_Stream_Open): If the size of the opened - file is zero, FT_Err_Cannot_Open_Stream is returned. - * builds/amiga/src/base/ftsystem.c (FT_Stream_Open): Ditto. - * src/vms/ftsystem.c (FT_Stream_Open): Ditto. - -2010-10-12 Werner Lemberg - - [truetype] Fix Savannah bug #31310. - - * src/truetype/ttgxvar.c (ft_var_readpackedpoints): Protect against - invalid `runcnt' values. - -2010-10-08 Chris Liddell - - [sfnt] Fix Savannah bug #31275. - - * src/sfnt/ttpost.c: Include FT_INTERNAL_DEBUG_H. - -2010-10-06 Werner Lemberg - - [truetype] Improve error handling of `SHZ' bytecode instruction. - Problem reported by Chris Evans . - - * src/truetype/ttinterp.c (Ins_SHZ): Check `last_point'. - -2010-10-05 Werner Lemberg - - Fix Savannah bug #31253. - Patch submitted by an anonymous reporter. - - * configure: Use `awk' instead of `sed' to manipulate output of `ls - -id'. - -2010-10-03 Werner Lemberg - - * Version 2.4.3 released. - ========================= - - - Tag sources with `VER-2-4-3'. - - * docs/CHANGES: Updated. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.4.3 - - * README, Jamfile (RefDoc), - builds/win32/vc2005/freetype.vcproj, builds/win32/vc2005/index.html, - builds/win32/vc2008/freetype.vcproj, builds/win32/vc2008/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualc/index.html, builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj, - builds/win32/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.4.2/2.4.3/, s/242/243/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 3. - - * builds/unix/configure.raw (version_info): Set to 12:1:6. - -2010-10-03 Werner Lemberg - - Avoid `configure' issues with symbolic links. - Based on a patch from Alexander Stohr . - - * configure: Compare directories using `ls -id'. - Check existence of `reference' subdirectory before creating it. - -2010-10-02 Werner Lemberg - - [sfnt] Fix Savannah bug #31088 (sort of). - - * src/sfnt/ttload.c (tt_face_load_maxp): Always allocate at least 64 - function entries. - -2010-10-02 Werner Lemberg - - [smooth] Fix splitting of cubics for negative values. - - Reported by Róbert Márki ; see - https://lists.gnu.org/archive/html/freetype/2010-09/msg00019.html. - - * src/smooth/ftgrays.c (gray_render_cubic): Fix thinko. - -2010-10-01 suzuki toshiya - - [truetype] Fix Savannah bug #31040. - - * src/truetype/ttinterp.c (free_buffer_in_size): Remove. - (TT_RunIns): Updated. - -2010-09-20 suzuki toshiya - - [sfnt] Make error message filling NULL names less verbose. - - * src/sfnt/ttpost.c (load_format_20): Showing 1 summary message - when we fill `post' names by NULL, instead of per-entry message. - -2010-09-20 Graham Asher - David Bevan - - [smooth] Fix and improve spline flattening. - - This fixes the flattening of cubic, S-shaped curves and speeds up - the handling of both the conic and cubic arcs. - - See the discussions on the freetype-devel mailing list in late - August and September 2010 for details. - - * src/smooth/ftgrays.c (FT_MAX_CURVE_DEVIATION): New macro. - (TWorker): Remove `conic_level' and `cubic_level' elements. - (gray_render_conic): Simplify algorithm. - (gray_render_cubic): New algorithm; details are given in the code - comments. - (gray_convert_glyph): Remove heuristics. - -2010-09-19 Werner Lemberg - - Minor fixes. - - * src/cff/cffload.c (cff_charset_compute_cids): `charset->sids[i]' - is `FT_UShort'. - (cff_index_access_element): Don't use additions in comparison. - * src/sfnt/ttpost.c (load_format_20): Make `post_limit' of type - `FT_Long'. - Don't use additions in comparison. - Improve tracing messages. - (load_format_25, load_post_names): Make `post_limit' of type - `FT_Long'. - -2010-09-19 suzuki toshiya - - [cff] Truncate the element length at the end of the stream. - See Savannah bug #30975. - - * src/cff/cffload.c (cff_index_access_element): `off2', the offset - to the next element is truncated at the end of the stream to prevent - invalid I/O. As `off1', the offset to the requested element has - been checked by `FT_STREAM_SEEK', `off2' should be checked - similarly. - -2010-09-19 suzuki toshiya - - [cff] Ignore CID > 0xFFFFU. - See Savannah bug #30975. - - * src/cff/cffload.c (cff_charset_compute_cids): Ignore CID if - greater than 0xFFFFU. CFF font spec does not mention maximum CID in - the font, but PostScript and PDF spec define that maximum CID is - 0xFFFFU. - -2010-09-19 suzuki toshiya - - [cff] Make trace message in` cff_charset_load' verbose. - See Savannah bug #30975. - - * src/cff/cffload.c (cff_charset_load): Report the original `nleft' - and truncated `nleft'. - -2010-09-19 suzuki toshiya - - [cff] Correct `max_cid' from CID array length to max CID. - See Savannah bug #30975. - - * src/cff/cffload.c (cff_charset_compute_cids): Don't increment - max_cid after detecting max CID. The array CFF_Charset->cids is - allocated by max_cid + 1. - (cff_charset_cid_to_gindex): Permit CID is less than or equal to - CFF_Charset->max_cid. - * src/cff/cffobjs.c (cff_face_init): FT_Face->num_glyphs is - calculated as CFF_Charset->max_cid + 1. - -2010-09-19 suzuki toshiya - - [truetype] Sanitize the broken offsets in `loca'. - See Savannah bug #31040. - - * src/truetype/ttpload.c (tt_face_get_location): If `pos1', the - offset to the requested entry in `glyf' exceeds the end of the - table, return offset=0, length=0. If `pos2', the offset to the next - entry in `glyf' exceeds the end of the table, truncate the entry - length at the end of `glyf' table. - -2010-09-19 suzuki toshiya - - [sfnt] Prevent overrunning in `post' table parser. - See Savannah bug #31040. - - * src/sfnt/ttpost.c (load_post_names): Get the length of `post' - table and pass the limit of `post' table to `load_format_20' and - `load_format_25'. - (load_format_20): Stop the parsing when we reached at the limit of - `post' table. If more glyph names are required, they are filled by - NULL names. - -2010-09-17 suzuki toshiya - - [truetype] Don't duplicate size->twilight structure to be freed. - See Savannah bug #31040 for detail. - - * src/truetype/ttinterp.c (free_buffer_in_size): Don't duplicate - FT_GlyphZoneRec size->twilight to be freed. If duplicated, - `FT_FREE' erases the duplicated pointers only and leave original - pointers. They can cause the double-free crash when the burst - errors occur in TrueType interpreter and `free_buffer_in_size' is - invoked repeatedly. - -2010-09-15 Werner Lemberg - - Make bytecode debugging with FontForge work again. - - * src/truetype/ttinterp.c (TT_RunIns): Don't call - `free_buffer_in_size' in case of error if a debugger is active. - -2010-09-14 Werner Lemberg - - Improve tracing messages. - - * src/truetype/ttinterp.c (TT_RunIns): Improve wording of tracing - message. - * src/truetype/ttobjs.c (tt_size_run_fpgm, tt_size_run_prep): Add - tracing message. - * src/truetype/ttgload.c (tt_loader_init): Add tracing message. - * src/cache/ftcsbits.c (ftc_snode_load): Emit tracing message if - glyph doesn't fit into a small bitmap container. - -2010-09-13 Werner Lemberg - - Fix minor issues reported by . - - * src/autofit/aflatin.c (af_latin_compute_stem_width): Remove - redundant conditional check. - * src/base/ftsynth.c (FT_GlyphSlot_Embolden): Ditto. - * src/cff/cffload.c (cff_encoding_load): Remove conditional check - which always evaluates to `true'. - * src/pshinter/pshalgo.c (ps_glyph_interpolate_strong_points): - Ditto. - * src/truetype/ttinterp.c (Ins_IUP): Ditto. - * src/cid/cidgload.c (cid_slot_load_glyph): Don't check for NULL if - value is already dereferenced. - * src/winfonts/winfnt.c (FNT_Load_Glyph): Fix check of `face'. - -2010-08-31 suzuki toshiya - - Ignore the environmental setting of LIBTOOL. - Patch is suggested by Adrian Bunk, to prevent unexpected - reflection of environmental LIBTOOL. See: - https://savannah.nongnu.org/patch/?7290 - - * builds/unix/unix-cc.in: LIBTOOL is unconditionally set to - $(FT_LIBTOOL_DIR)/libtool. FT_LIBTOOL_DIR is set to $(BUILD_DIR) - by default. - * configure: When configured for the building out of source tee, - FT_LIBTOOL_DIR is set to $(OBJ_DIR). - -2010-08-31 suzuki toshiya - - [truetype] Decrease the trace level catching the interpreter error. - - * src/truetype/ttinterp.c (TT_RunIns): Decrease the trace level - showing the error when the interpreter returns with an error, - from` FT_TRACE7' to `FT_TRACE1'. - -2010-08-30 suzuki toshiya - - [truetype] Prevent bytecode reuse after the interpretation error. - - * src/truetype/ttinterp.c (free_buffer_in_size): New function to - free the buffer allocated during the interpretation of this glyph. - (TT_RunIns): Unset FT_Face->size->{cvt_ready,bytecode_ready} if - an error occurs in the bytecode interpretation. The interpretation - of invalid bytecode may break the function definitions and referring - them in later interpretation is danger. By unsetting these flags, - `fpgm' and `prep' tables are executed again in next interpretation. - - This fixes Savannah bug #30798, reported by Robert Święcki. - -2010-08-29 Werner Lemberg - - [ftraster] Pacify compiler. - - * src/raster/ftraster.c (ft_black_new) [_STANDALONE_]: `memory' is - not used. - -2010-08-29 Werner Lemberg - - [cff] Allow SIDs >= 65000. - - * src/cff/cffload.c (cff_charset_load): Fix change from 2009-03-20: - The threshold for SIDs is not applicable here. I misinterpreted the - `SID values 65000 and above are available for implementation use' - sentence in the CFF specification. - - Problem reported by Ivan Ninčić . - -2010-08-28 suzuki toshiya - - Force hinting when the font lacks its familyname. - - In Type42 or Type11 font embedded in PostScript & PDF, TrueType sfnt - stream may lack `name' table because they are not required. Hinting - for nameless fonts is safer for PDFs including embedded Chinese - fonts. Written by David Bevan, see: - - https://lists.gnu.org/archive/html/freetype-devel/2010-08/msg00021.html - https://lists.freedesktop.org/archives/poppler/2010-August/006310.html - - * src/truetype/ttobjs.c (tt_check_trickyness): If a NULL pointer by - nameless font is given, TRUE is returned to enable hinting. - -2010-08-28 suzuki toshiya - - Register yet another tricky TrueType font. - - * src/truetype/ttobjs.c (tt_check_trickyness): Add `HuaTianKaiTi?', - a Kaishu typeface paired with `HuaTianSongTi?' by Huatian - Information Industry. - -2010-08-17 Teijo Kinnunen - - [cache] Fix Savannah bug #30788. - - * src/cache/ftccache.c (FTC_Cache_Clear): Check `cache->buckets' for - NULL too. - -2010-08-10 Werner Lemberg - - Try to fix Savannah bug #30717 (and probably #30719 too). - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Add another - overflow test for `width' and `height'. - -2010-08-06 Werner Lemberg - - * Version 2.4.2 released. - ========================= - - - Tag sources with `VER-2-4-2'. - - * docs/CHANGES: Updated. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.4.2 - - * README, Jamfile (RefDoc), - builds/win32/vc2005/freetype.vcproj, builds/win32/vc2005/index.html, - builds/win32/vc2008/freetype.vcproj, builds/win32/vc2008/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualc/index.html, builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj, - builds/win32/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.4.1/2.4.2/, s/241/242/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 2. - - * builds/unix/configure.raw (version_info): Set to 12:0:6. - -2010-08-06 suzuki toshiya - - Fix Savannah bug #30648. - - * src/base/ftobjs.c (FT_Done_Library): Specify the order of font - drivers during the face closing process. Type42 faces should be - closed before TrueType faces, because a Type42 face refers to - another internal TrueType face which is created from sfnt[] array on - the memory. - -2010-08-06 Yuriy Kaminskiy - - [raster] Fix valgrind warning. - - * src/raster/ftraster.c (Decompose_Curve) : Access point[0] - only if we don't hit `limit'. - -2010-08-06 suzuki toshiya - - Fix Savannah bug #30658. - - * src/base/ftobjs.c (Mac_Read_POST_Resource): Check that the total - length of collected POST segments does not overrun the allocated - buffer. - -2010-08-06 Yuriy Kaminskiy - - Fix conditional usage of FT_MulFix_i386. - With -ansi flag, gcc does not define `i386', only `__i386__'. - - * include/freetype/config/ftconfig.h, builds/unix/ftconfig.in: - s/i386/__i386__/. - -2010-08-05 Werner Lemberg - - [truetype] Fix Savannah bug #30657. - - * src/truetype/ttinterp.c (BOUNDSL): New macro. - Change `BOUNDS' to `BOUNDSL' where appropriate. - - * src/truetype/ttinterp.h (TT_ExecContextRec): Fix type of - `cvtSize'. - -2010-08-05 Werner Lemberg - - [type42] Fix Savannah bug #30656. - - * src/type42/t42parse.c (t42_parse_sfnts): Protect against negative - string_size. - Fix comparison. - -2010-08-05 suzuki toshiya - - [cff] Don't use any values in decoder after parsing error. - - * src/cff/cffgload.c (cff_slot_load): Skip the evaluations - of the values in decoder, if `cff_decoder_parse_charstrings' - returns any error. - -2010-08-04 Werner Lemberg - - Fix Savannah bug #30644. - - * src/base/ftstream.c (FT_Stream_EnterFrame): Fix comparison. - -2010-08-04 Werner Lemberg - - `make devel' fails if FT_CONFIG_OPTION_OLD_INTERNALS is set. - - * devel/ftoption.h: Synchronize with - include/freetype/config/ftoption.h. - -2010-08-04 suzuki toshiya - - [cff] Improve stack overflow test. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings): Check stack - after execution of operations too. - -2010-07-18 Werner Lemberg - - Add reference counters and to FT_Library and FT_Face objects. - - * include/freetype/freetype.h (FT_Reference_Face): New function. - * include/freetype/ftmodapi.h (FT_Reference_Library): New function. - - * include/freetype/internal/ftobjs.h (FT_Face_InternalRec, - FT_LibraryRec): New field `refcount'. - - * src/base/ftobjs.c (FT_Open_Face, FT_New_Library): Handle - `refcount'. - (FT_Reference_Face, FT_Reference_Library): Implement new functions. - (FT_Done_Face, FT_Done_Library): Handle `refcount'. - - * docs/CHANGES: Updated. - -2010-07-18 Werner Lemberg - - * Version 2.4.1 released. - ========================= - - - Tag sources with `VER-2-4-1'. - - * docs/CHANGES: Updated. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.4.1. - - * README, Jamfile (RefDoc), - builds/win32/vc2005/freetype.vcproj, builds/win32/vc2005/index.html, - builds/win32/vc2008/freetype.vcproj, builds/win32/vc2008/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualc/index.html, builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj, - builds/win32/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.4.0/2.4.1/, s/240/241/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 1. - - * builds/unix/configure.raw (version_info): Set to 11:1:5. - -2010-07-17 Werner Lemberg - - [cff] Final try to fix `hintmask' and `cntrmask' limit check. - - Problem reported by Tobias Wolf . - - * src/cff/cffgload.c (cff_decoder_parse_charstrings) - : Sigh. I'm apparently too silly to fix this - correctly in less than three tries. - -2010-07-12 Werner Lemberg - - * Version 2.4.0 released. - ========================= - - - Tag sources with `VER-2-4-0'. - - * docs/CHANGES: Updated. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.4.0. - - * README, Jamfile (RefDoc), - builds/win32/vc2005/freetype.vcproj, builds/win32/vc2005/index.html, - builds/win32/vc2008/freetype.vcproj, builds/win32/vc2008/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualc/index.html, builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj, - builds/win32/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.3.12/2.4.0/, s/2312/240/. - - * include/freetype/freetype.h (FREETYPE_MINOR): Set to 4. - (FREETYPE_PATCH): Set to 0. - - * builds/unix/configure.raw (version_info): Set to 11:0:5. - -2010-07-12 Werner Lemberg - - Remove C++ warnings. - - */*: Initialize pointers where necessary to make g++ happy. - -2010-07-12 malc - Richard Henderson - - Fix type-punning issues with C++. - - * include/freetype/internal/ftmemory.h (FT_ASSIGNP) [__cplusplus]: - Emulate a `typeof' operator with an inline template which uses - `static_cast'. - -2010-07-11 Werner Lemberg - - Fix C++ compilation issue. - - * src/tools/apinames.c (names_dump) : Fix - type of `dot' variable. - -2010-07-10 suzuki toshiya - - Fix another case reported in Savannah bug #30373. - Permit a face for Type1, Type42 and CFF without charmap, - patch by Tor Andersson. - - * src/type1/t1objs.c (T1_Face_Init): Reset the error if it - is FT_Err_No_Unicode_Glyph_Name. - * src/type42/t42objs.c (T42_Face_Init): Ditto. - * src/cff/cffobjs.c (cff_face_init): Ditto. - -2010-07-09 suzuki toshiya - - Use defined macros to set {platform,encoding}_id. - - * src/bdf/bdfdrivr.c: Include ttnameid.h and use macros to - set charmap.{platform,encoding}_id. - * src/pcf/pcfdrivr.c: Ditto. - * src/winfonts/winfnt.c: Ditto. - * src/type1/t1objs.c: Ditto. - * src/type42/t42objs.c: Ditto. - * src/cff/cffobjs.c: Ditto. - * src/pfr/pfrobjs.c: Ditto. - -2010-07-09 suzuki toshiya - - Fix Savannah bug #30373. - Too serious check of errors by `FT_CMap_New' since 2010-07-04 - is fixed. Reported by Tor Andersson. - - * include/freetype/fterrdef.h - (PSnames_Err_No_Unicode_Glyph_Name): New error code to - indicate the Unicode charmap synthesis failed because - no Unicode glyph name is found. - - * src/psnames/psmodule.c (ps_unicodes_init): Return - PSnames_Err_No_Unicode_Glyph_Name when no Unicode glyph name - is found in the font. - * src/cff/cffcmap.c (cff_cmap_unicode_init): Return - CFF_Err_No_Unicode_Glyph_Name when no SID is available. - - * src/type1/t1objs.c (T1_Face_Init): Proceed if `FT_CMap_New' - is failed by the lack of Unicode glyph name. - * src/type42/t42objs.c (T42_Face_Init): Ditto. - * src/cff/cffobjs.c (cff_face_init): Ditto. - -2010-07-09 Ken Sharp - - Make ftraster.c compile in stand-alone mode with MSVC compiler. - - * src/raster/ftmisc.h (FT_Int64) [_WIN32, _WIN64]: Fix typedef - since there is no `inttypes.h' for MSVC. - -2010-07-08 Werner Lemberg - - [truetype] Fix Savannah bug #30361. - - * src/truetype/ttinterp.c (Ins_IUP): Fix bounds check. - -2010-07-06 Werner Lemberg - - Pacify compiler. - - * src/cff/cffload.c (cff_index_get_pointers): Initialize - `new_bytes'. - -2010-07-05 Eugene A. Shatokhin - - Fix Savannah bug #27648. - - * src/base/ftobjs.c (ft_remove_renderer, FT_Add_Module): Call - `raster_done' only if we have an outline glyph format. - -2010-07-05 Werner Lemberg - - Fix Savannah bug #30030. - - * builds/win32/*/freetype.vcproj: Add ftxf86.c. - -2010-07-05 Werner Lemberg - - [cff] Next try to fix `hintmask' and `cntrmask' limit check. - - Problem reported by malc . - - * src/cff/cffgload.c (cff_decoder_parse_charstrings) - : It is possible that there is just a single byte - after the `hintmask' or `cntrmask', e.g., a `return' instruction. - -2010-07-04 suzuki toshiya - - Restrict the number of the charmaps in a rogue-compatible mode. - Fix for Savannah bug #30059. - - * src/cache/ftccmap.c (FTC_CMapCache_Lookup): Replace `16' the - minimum character code passed by a legacy rogue client by... - * include/freetype/config/ftoption.h (FT_MAX_CHARMAP_CACHEABLE): - This. It is undefined when FT_CONFIG_OPTION_OLD_INTERNALS is - undefined (thus the rogue client compatibility is not required). - - * src/cff/cffobjs.c (cff_face_init): Abort the automatic - selection or synthesis of Unicode cmap subtable when the charmap - index exceeds FT_MAX_CHARMAP_CACHEABLE. - * src/sfnt/ttcmap.c (tt_face_build_cmaps): Issue error message - when the charmap index exceeds FT_MAX_CHARMAP_CACHEABLE. - - * src/base/ftobjs.c (find_unicode_charmap): When Unicode charmap - is found after FT_MAX_CHARMAP_CACHEABLE, ignore it and search - earlier one. - (find_variant_selector_charmap): When UVS charmap is found after - FT_MAX_CHARMAP_CACHEABLE, ignore it and search earlier one. - (FT_Select_Charmap): When a charmap matching with requested - encoding but after FT_MAX_CHARMAP_CACHEABLE, ignore and search - earlier one. - (FT_Set_Charmap): When a charmap matching with requested - charmap but after FT_MAX_CHARMAP_CACHEABLE, ignore and search - earlier one. - (FT_Get_Charmap_Index): When a requested charmap is found - after FT_MAX_CHARMAP_CACHEABLE, return the inverted charmap - index. - -2010-07-04 Werner Lemberg - - TrueType hinting is no longer patented. - - * include/freetype/config/ftoption.h, devel/ftoption.h - (TT_CONFIG_OPTION_BYTECODE_INTERPRETER): Define. - (TT_CONFIG_OPTION_UNPATENTED_HINTING): Undefine. - - * docs/CHANGES, docs/INSTALL, include/freetype/freetype.h: Updated. - * docs/TRUETYPE, docs/PATENTS: Removed. - -2010-07-04 suzuki toshiya - - Check error value by `FT_CMap_New'. - - * src/cff/cffobjs.c (cff_face_init): Check error value by - `FT_CMap_New'. - * src/pfr/pfrobjs.c (pfr_face_init): Ditto. - * src/type1/t1objs.c (T1_Face_Init): Ditto. - * src/type42/t42objs.c (T42_Face_Init): Ditto. - -2010-07-03 Werner Lemberg - - Make ftgrays.c compile stand-alone again. - - * src/smooth/ftgrays.c [_STANDALONE_]: Include `stddef.h'. - (FT_INT_MAX, FT_PtrDist)[_STANDALONE_]: Define. - -2010-07-02 suzuki toshiya - - Additional fix for Savannah bug #30306. - - * src/base/ftobjs.c (Mac_Read_POST_Resource): If the type of the - POST fragment is 0, the segment is completely ignored. The declared - length of the segment is not cared at all. According to Adobe - Technical Note 5040, type 0 segment is a comment only and should not - be loaded for the interpreter. Reported by Robert Święcki. - -2010-07-01 Werner Lemberg - - [truetype] Protect against code range underflow. - - * src/truetype/ttinterp.c (DO_JROT, DO_JMPR, DO_JROF): Don't allow - negative IP values. - -2010-07-01 Werner Lemberg - - [truetype] Add rudimentary tracing for bytecode instructions. - - * src/truetype/ttinterp.c (opcode_name) [FT_DEBUG_LEVEL_TRACE]: New - array. - (TT_RunIns): Trace opcodes. - -2010-06-30 Werner Lemberg - - [smooth] Fix Savannah bug #30263. - - * src/smooth/ftgrays.c (gray_render_span): Use cast to `unsigned - int' to avoid integer overflow. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Use smaller - threshold values for `width' and `height'. This is not directly - related to the bug fix but makes sense anyway. - -2010-07-01 suzuki toshiya - - Initial fix for Savannah bug #30306. - - * src/base/ftobjs.c (Mac_Read_POST_Resource): Check `rlen', the - length of fragment declared in the POST fragment header, and prevent - an underflow in length calculation. Some fonts set the length to - zero in spite of the existence of a following 16bit `type'. - Reported by Robert Święcki. - -2010-07-01 suzuki toshiya - - Additional fix for Savannah bug #30248 and #30249. - - * src/base/ftobjs.c (Mac_Read_POST_Resource): Check the buffer size - during gathering PFB fragments embedded in LaserWriter PS font for - Macintosh. Reported by Robert Święcki. - -2010-06-30 Alexei Podtelezhnikov - - Minor optimizations by avoiding divisions. - - * src/sfnt/ttkern.c (tt_face_load_kern, tt_face_get_kerning): - Replace divisions with multiplication in comparisons. - -2010-06-29 Werner Lemberg - - Fix minor tracing issues. - - * src/cff/cffgload.c, src/truetype/ttgload.c: Adjust tracing levels. - -2010-06-27 Werner Lemberg - - [cff] Really fix `hintmask' and `cntrmask' limit check. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings) - : Fix thinko and handle tracing also. - -2010-06-27 Werner Lemberg - - Fix valgrind warning. - - * src/base/ftoutln.c (FT_Outline_Get_Orientation): Initialize - `result' array. - -2010-06-27 Werner Lemberg - - [cff] Fix memory leak. - - * src/cff/cffgload.c (cff_operator_seac): Free charstrings even in - case of errors. - -2010-06-27 Werner Lemberg - - [cff] Protect against invalid `hintmask' and `cntrmask' operators. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings) - : Ensure that we don't exceed `limit' while parsing - the bit masks of the `hintmask' and `cntrmask' operators. - -2010-06-26 Werner Lemberg - - Fix PFR change 2010-06-24. - - * src/pfr/pfrgload.c (pfr_glyph_load_simple): Really protect against - invalid indices. - -2010-06-26 Werner Lemberg - - Improve PFR tracing messages. - - * src/pfr/pfrgload.c (pfr_glyph_load_rec): Emit tracing messages for - simple and compound glyph offsets. - -2010-06-26 Werner Lemberg - - Fix last PFR change. - - * src/pfr/pfrobjs.c (pfr_face_init): Fix rejection logic. - -2010-06-26 Werner Lemberg - - [sfnt] Fix Savannah bug #30262. - - * src/sfnt/ttload.c (tt_face_load_maxp): Limit `maxComponentDepth' - arbitrarily to 100 to avoid stack exhaustion. - -2010-06-26 Werner Lemberg - - Add some memory checks (mainly for debugging). - - * src/base/ftstream.c (FT_Stream_EnterFrame): Exit with error - if the frame size is larger than the stream size. - - * src/base/ftsystem.c (ft_ansi_stream_io): Exit with error if - seeking a position larger than the stream size. - -2010-06-25 Werner Lemberg - - [pfr] Fix Savannah bug #30261. - - * src/pfr/pfrobjs.c (pfr_face_init): Reject fonts which contain - neither outline nor bitmap glyphs. - -2010-06-25 Werner Lemberg - - [cff] Fix Savannah bug #30254. - - * src/cff/cffload.c (cff_index_get_pointers): Do sanity check for - first offset also. - -2010-06-25 suzuki toshiya - - Initial fix for Savannah bug #30248 and #30249. - - * src/base/ftobjs.c (Mac_Read_POST_Resource): Check the error during - reading a PFB fragment embedded in LaserWriter PS font for Macintosh. - Reported by Robert Święcki. - -2010-06-24 Werner Lemberg - - [pcf] Fix Savannah bug #30247. - - * src/pcf/pcfread.c (pcf_get_metrics): Disallow (invalid) fonts with - zero metrics. - -2010-06-24 Graham Asher - - * src/smooth/ftgrays.c (gray_render_cubic): Fix algorithm. - The previous version was too aggressive, as demonstrated in - https://lists.gnu.org/archive/html/freetype-devel/2010-06/msg00020.html. - -2010-06-24 Werner Lemberg - - */*: Use module specific error names where appropriate. - -2010-06-24 Werner Lemberg - - [sfnt] Fix Savannah bug #30236. - - * src/sfnt/ttcmap.c (tt_face_build_cmaps): Improve check for pointer - to `cmap_table'. - -2010-06-24 Werner Lemberg - - [pfr] Fix Savannah bug #30235. - - * src/pfr/pfrgload.c (pfr_glyph_load_simple): Protect against - invalid indices if there aren't any coordinates for indexing. - -2010-06-24 Werner Lemberg - - [bdf]: Font properties are optional. - - * src/bdf/bdflib.c (_bdf_readstream): Use special error code to - indicate a redo operation. - (_bdf_parse_start): Handle `CHARS' keyword here too and pass current - input line to `_bdf_parse_glyph'. - -2010-06-23 Werner Lemberg - - [bdf] Fix Savannah bug #30220. - - * include/freetype/fterrdef.h - (BDF_Err_Missing_Fontboundingbox_Field): New error code. - - * src/bdf/bdflib.c (_bdf_parse_start): Check for missing - `FONTBOUNDINGBOX' field. - Avoid memory leak if there are multiple `FONT' lines (which is - invalid but doesn't hurt). - -2010-06-21 Werner Lemberg - - [pfr] Fix Savannah bug #30168. - - * src/pfr/pfrgload.c (pfr_glyph_load_compound): Limit the number of - subglyphs to avoid endless recursion. - -2010-06-20 Werner Lemberg - - [psaux] Fix Savannah bug #30145. - - * src/psaux/psobjs.c (t1_builder_add_contour): Protect against - `outline == NULL' which might happen in invalid fonts. - -2010-06-19 Werner Lemberg - - [bdf] Fix Savannah bug #30135. - - * src/bdf/bdflib.c (_bdf_list_join): Don't modify value in static - string `empty'. - (_bdf_parse_glyph): Avoid memory leak in case of error. - -2010-06-15 Werner Lemberg - - [autofit] Fix Savannah bug #30108. - - * src/autofit/afglobal.c (af_face_globals_compute_script_coverage): - Properly mask AF_DIGIT bit in comparison. - -2010-06-11 Werner Lemberg - - [pshinter] Fix Savannah bug #30106. - - Point numbers for FreeType's implementation of hinting masks are - collected before the final number of points of a glyph has been - determined; in particular, the code for handling the `endchar' - opcode can reduce the number of points. - - * src/pshinter/pshalgo.c (psh_glyph_find_strong_points): Assure that - `end_point' is not larger than `glyph->num_points'. - -2010-06-11 Werner Lemberg - - [cff]: Improve debugging output. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings) - : Implement it. - -2010-06-10 Graham Asher - - ftgrays: Speed up rendering of small cubic splines. - - * src/smooth/ftgrays.c (gray_render_cubic): Implement new, - simplified algorithm to find out whether the spline can be replaced - with two straight lines. See this thread for more: - - https://lists.gnu.org/archive/html/freetype-devel/2010-06/msg00000.html - -2010-06-09 Werner Lemberg - - [cff] Fix Savannah bug #30082. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings) - : Protect against stack underflow. - -2010-06-08 Werner Lemberg - - [cff] Fix Savannah bug #30053. - - * src/cff/cffparse.c (cff_parse_real): Handle border case where - `fraction_length' has value 10. - -2010-06-07 Werner Lemberg - - Fix Savannah bug #30052. - This bug has been introduced with commit 2415cbf3. - - * src/base/ftobjs.c (FT_Get_First_Char, FT_Get_Next_Char): Protect - against endless loop in case of corrupted font header data. - -2010-05-26 Werner Lemberg - - Remove unused variable. - Found by Graham. - - * src/autofit/afhints.c (af_glyph_hints_reload): Remove unused - variable `first' in first block. - -2010-05-22 Werner Lemberg - - Fix various memory problems found by linuxtesting.org. - - * src/base/ftgxval.c (FT_TrueTypeGX_Free, FT_ClassicKern_Free), - src/base/ftotval.c (FT_OpenType_Free), src/base/ftpfr.c - (ft_pfr_check): Check `face'. - - * src/base/ftobjs.c (FT_Get_Charmap_Index): Check `charmap' and - `charmap->face'. - (FT_Render_Glyph): Check `slot->face'. - (FT_Get_SubGlyph_Info): Check `glyph->subglyphs'. - -2010-05-22 Werner Lemberg - - autofit: Remove dead code. - Suggested by Graham. - - * src/autofit/afhints.c (af_glyph_hints_compute_inflections): - Removed. - (af_glyph_hints_reload): Remove third argument. - Update all callers. - -2010-05-21 Bram Tassyns - - [cff] Fix Savannah bug #27987. - - * src/cff/cffobjs.c (remove_subset_prefix): New function. - (cff_face_init): Use it to adjust `cffface->family_name'. - -2010-05-20 Werner Lemberg - - TrueType: Make FreeType ignore maxSizeOfInstructions in `maxp'. - - Acroread does the same. - - * src/truetype/ttgload.c (TT_Process_Composite_Glyph): Call - `Update_Max' to adjust size of instructions array if necessary and - add a rough safety check. - - (load_truetype_glyph): Save `loader->byte_len' before recursive - call. - - * src/truetype/ttinterp.h, src/truetype/ttinterp.c (Update_Max): - Declare it as FT_LOCAL. - -2010-05-18 Hongbo Ni - - Apply Savannah patch #7196. - - * src/cff/cffgload.c (cff_slot_load): Prevent crash if CFF subfont - index is out of range. - -2010-05-11 Werner Lemberg - - * docs/formats.txt: Give pointer to PCF documentation. - Information provided by Alan Coopersmith - . - -2010-05-10 Ken Sharp - - [psaux] Fix Savannah bug #29846. - - Previously we discovered fonts which used `setcurrentpoint' to set - the initial point of a contour to 0,0. This caused FreeType to - raise an error, because the `setcurrentpoint' operator is only - supposed to be used with the results from an OtherSubr subroutine. - - This was fixed by simply ignoring the error and carrying on. - - Now we have found a font which uses setcurrentpoint to actually - establish a non-zero point for a contour during the course of a - glyph program. FWIW, these files may be produced by an application - called `Intaglio' on the Mac, when converting TrueType fonts to - Type 1. - - The fix allows the new invalid behaviour, the old invalid behaviour - and real proper usage of the operator to work the same way as Adobe - interpreters apparently do. - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings): Make - `setcurrentpoint' use the top two elements of the stack to establish - unconditionally the current x and y coordinates. - - Make the `flex' subroutine handling (OtherSubr 0) put the current - x,y coordinates onto the stack, instead of two dummy uninitialised - values. - -2010-04-14 Ken Sharp - - [psaux] Fix Savannah bug #29444. - - * src/psaux/psobjs.c (t1_builder_start_point): Accept (invalid) - `lineto' immediately after `hsbw', in accordance with Acrobat, GS, - and others. - -2010-04-14 Michał Cichoń - - [psaux] Fix Savannah bug #27999. - - * src/cache/ftcmanag.c (FTC_Manager_RemoveFaceID): Only remove - selected entry, not all. - -2010-04-06 Jonathan Kew - - [truetype] Add overflow check to `fvar' table. - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Check axis and instance - count. - -2010-04-05 Ken Sharp - - [raster] Fix Savannah bug #29335. - - * src/raster/ftraster.c (Line_Up): Use slow multiplication to - prevent overflow. This shouldn't have any serious impact on speed, - however. - -2010-04-05 Werner Lemberg - - Add new function `FT_Library_SetLcdFilterWeights'. - - This is based on code written by Lifter - . It fixes - FreeDesktop bug #27386. - - * src/base/ftlcdfil.c (FT_Library_SetLcdFilterWeights): New - function. - - * include/freetype/ftlcdfil.h: Updated. - - * docs/CHANGES: Updated. - -2010-04-01 John Tytgat - - [truetype] Fix Savannah bug #29404. - - * src/truetype/ttgload.c: Revert change 2752bd1a (check on bit 1 - of `head' table of TrueType fonts). - -2010-03-14 suzuki toshiya - - Fix `multi build' for Tytgat's CFF driver improvement. - - * src/base/cffload.h (cff_index_get_name): Added. - -2010-03-12 suzuki toshiya - - Remove duplicated inclusion of `FT_OUTLINE_H' in ftobjs.c. - - * src/base/ftobjs.c: Remove 2nd inclusion of `FT_OUTLINE_H'. - -2010-03-11 Chris Liddell - - [raster] Fix Savannah bug #27442. - - * src/raster/ftraster.c (ft_black_reset): Fix `buffer_size'. - -2010-03-09 Werner Lemberg - - [cff] Remove unused variable. - Reported by Graham. - - * src/cff/cffparse.c (cff_parse_real): Remove `rest'. - -2010-03-02 John Tytgat - - [cff] Improve CFF string (especially glyphname) lookup performance. - - We do this by avoiding memory allocation and file I/O. This is - Savannah patch #7104. - - * src/cff/cfftypes.h: Include PS cmaps service and - FT_INTERNAL_POSTSCRIPT_HINTS_H. - (CFF_SubFontRec): Remove `num_local_subrs'. - (CFF_FontRec): Add `num_strings', `strings', and `string_pool' - fields. - Remove `string_index' and `num_global_subrs' fields. - Use real types instead of `void' for `pshinter' and `psnames' fields. - - * src/cff/cffload.c: Don't include PS cmaps service. - (cff_index_get_pointers): Add `pool' parameter which allows inserting - an extra NUL character for each String INDEX entry. - (cff_index_get_name): Make it a local function. - (cff_index_get_string): New function. - (cff_subfont_load): Updated. - (cff_font_load): Initialize `num_strings', `strings', and - `string_pool' fields in the `CFF_FontRec' structure. - (cff_index_get_sid_string): Use `cff_index_get_string' instead of - `cff_index_get_name'. - (cff_font_done): Updated. - - * src/cff/cffload.h: Don't include PS cmaps service. - (cff_index_get_string): Added. - (cff_index_get_sid_string): Updated. - - * src/cff/cffobjs.c: Don't include PS cmaps service and - FT_INTERNAL_POSTSCRIPT_HINTS_H. - (cff_size_get_globals_funcs, cff_slot_init): Updated. - (cff_face_init): Follow `cff_index_get_name', - `cff_index_get_string', and `cff_index_get_sid_string' changes. - - * src/cff/cffcmap.c (cff_sid_free_glyph_name): Removed. - (cff_sid_to_glyph_name): Use `cff_index_get_cid_string'. - (cff_cmap_unicode_init): Updated. - - * src/cff/cffdrivr.c: Don't include PS cmap service. - (cff_get_glyph_name): Avoid unnecessary lookup for POSTSCRIPT_CMAPS - service. - (cff_get_glyph_name, cff_ps_get_font_info, cff_get_ros): Follow API - `cff_index_get_sid_string' change. - (cff_get_name_index): Use `cff_index_get_string' instead of - `cff_index_get_name'. - - * src/cff/cffgload.c: Don't include FT_INTERNAL_POSTSCRIPT_HINTS_H. - (cff_decoder_init, cff_decoder_prepare): Updated. - -2010-02-27 Werner Lemberg - - Simplify code. - Suggested by Behdad. - - * src/base/ftobjs.c (FT_Get_First_Char): Don't use a loop since we - call FT_Get_Next_Char anyway if necessary. - -2010-02-26 Behdad Esfahbod - - Improve handling of invalid glyph indices in char->index functions. - - * src/base/ftobjs.c (FT_Get_First_Char, FT_Get_Next_Char): Use a - loop. - -2010-02-18 Chris Liddell - - [truetype] Fix Savannah bug #28905. - - Initialize phantom points before calling the incremental interface - to update glyph metrics. - - * src/truetype/ttgload.c (tt_get_metrics_incr_overrides) - [FT_CONFIG_OPTION_INCREMENTAL]: New function, split off from... - (tt_get_metrics): This. - Updated. - (load_truetype_glyph): Use tt_get_metrics_incr_overrides. - ----------------------------------------------------------------------------- - -Copyright (C) 2010-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, modified, -and distributed under the terms of the FreeType project license, -LICENSE.TXT. By continuing to use, modify, or distribute this file you -indicate that you have read the license and understand and accept it -fully. - - -Local Variables: -version-control: never -coding: utf-8 -End: diff --git a/lib/libesp32_lvgl/freetype/ChangeLog.25 b/lib/libesp32_lvgl/freetype/ChangeLog.25 deleted file mode 100644 index 6e04427e8..000000000 --- a/lib/libesp32_lvgl/freetype/ChangeLog.25 +++ /dev/null @@ -1,5161 +0,0 @@ -2014-12-30 Werner Lemberg - - * Version 2.5.5 released. - ========================= - - - Tag sources with `VER-2-5-5'. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.5.5. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.5.4/2.5.5/, s/254/255/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 5. - - * builds/unix/configure.raw (version_info): Set to 17:4:11. - * CMakeLists.txt (VERSION_PATCH): Set to 5. - * docs/CHANGES: Updated. - - * builds/toplevel.mk (dist): Fix typos. - -2014-12-24 Alexei Podtelezhnikov - - [base] Formatting and nanooptimizations. - - * src/base/ftcalc.c, - * src/base/fttrigon.c: Revise sign restoration. - -2014-12-13 Werner Lemberg - - * src/pcf/pcfread.c (pcf_read_TOC): Improve fix from 2014-12-08. - -2014-12-11 Werner Lemberg - - * builds/toplevel.mk (dist): Use older POSIX standard for `tar'. - - Apparently, BSD tar isn't capable yet of handling POSIX-1.2001 - (contrary to GNU tar), so force the POSIX-1.1988 format. - - Problem reported by Stephen Fisher . - -2014-12-11 Werner Lemberg - - * src/type42/t42parse.c (t42_parse_sfnts): Reject invalid TTF size. - -2014-12-11 Werner Lemberg - - * src/base/ftobjs.c (FT_Get_Glyph_Name): Fix off-by-one check. - - Problem reported by Dennis Felsing . - -2014-12-11 Werner Lemberg - - * src/type42/t42parse.c (t42_parse_sfnts): Check `string_size'. - - Problem reported by Dennis Felsing . - -2014-12-09 suzuki toshiya - - [gxvalid] Fix a naming convention conflicting with ftvalid. - - See previous changeset for otvalid. - - * src/gxvalid/{gxvcommn.h, gxvmort.h, gxvmorx.h}: Replace - `valid' by `gxvalid'. - * src/gxvalid/{gxvbsln.c, gxvcommn.c, gxvfeat.c, gxvjust.c, - gxvkern.c, gxvlcar.c, gxvmort.c, gxvmort0.c, gxvmort1.c, - gxvmort2.c, gxvmort4.c, gxvmort5.c, gxvmorx.c, gxvmorx0.c, - gxvmorx1.c, gxvmorx2.c, gxvmorx4.c, gxvmorx5.c, gxvopbd.c, - gxvprop.c, gxvtrak.c}: Replace `valid' by `gxvalid' if - it is typed as GXV_Validator. - -2014-12-09 suzuki toshiya - - [otvalid] Fix a naming convention conflicting with ftvalid. - - Some prototypes in ftvalid.h use `valid' for the variables - typed as FT_Validator. Their implementations in src/base/ - ftobjs.c and utilizations in src/sfnt/ttcmap.c do similar. - - Some macros in otvcommn.h assume the exist of the variable - `valid' typed as OTV_Validator in the caller. - - Mixing these two conventions cause invalid pointer conversion - and unexpected SEGV in longjmp. To prevent it, all variables - typed as OTV_Validator are renamed to `otvalid'. - - * src/otvalid/otvcommn.h: Replace `valid' by `otvalid'. - * src/otvalid/{otvcommn.c, otvbase.c, otvgdef.c, otvgpos.c, - otvgsub.c, otvjstf.c, otvmath.c}: Replace `valid' by `otvalid' - if it is typed as OTV_Validator. - -2014-12-09 suzuki toshiya - - [ftvalid] Introduce FT_THROW() in FT_INVALID_XXX macros. - - Original patch is designed by Werner Lemberg. Extra part - for otvalid and gxvalid are added by suzuki toshiya, see - discussion: - https://lists.nongnu.org/archive/html/freetype-devel/2014-12/msg00002.html - https://lists.nongnu.org/archive/html/freetype-devel/2014-12/msg00007.html - - * include/internal/ftvalid.h: Introduce FT_THROW() in FT_INVALID_(). - * src/gxvalid/gxvcommn.h: Ditto. - * src/otvalid/otvcommn.h: Ditto. - -2014-12-08 Werner Lemberg - - [pcf] Fix Savannah bug #43774. - - Work around `features' of X11's `pcfWriteFont' and `pcfReadFont' - functions. Since the PCF format doesn't have an official - specification, we have to exactly follow these functions' behaviour. - - The problem was unveiled with a patch from 2014-11-06, fixing issue - #43547. - - * src/pcf/pcfread.c (pcf_read_TOC): Don't check table size for last - element. Instead, assign real size. - -2014-12-07 Werner Lemberg - - Work around a bug in Borland's C++ compiler. - - See - - http://qc.embarcadero.com/wc/qcmain.aspx?d=118998 - - for Borland's bug tracker entry. - - Reported by Yuliana Zigangirova , - https://lists.gnu.org/archive/html/freetype-devel/2014-04/msg00001.html. - - * include/internal/ftvalid.h (FT_ValidatorRec), src/smooth/ftgrays.c - (gray_TWorker_): Move `ft_jmp_buf' field to be the first element. - -2014-12-07 Werner Lemberg - - */*: Decorate hex constants with `U' and `L' where appropriate. - -2014-12-07 Werner Lemberg - - [truetype] Prevent memory leak for buggy fonts. - - * src/truetype/ttobjs.c (tt_size_done): Unconditionally call - `tt_size_done_bytecode'. - -2014-12-06 Werner Lemberg - - * Version 2.5.4 released. - ========================= - - - Tag sources with `VER-2-5-4'. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.5.4. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.5.3/2.5.4/, s/253/254/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 4. - - * builds/unix/configure.raw (version_info): Set to 17:3:11. - * CMakeLists.txt (VERSION_PATCH): Set to 4. - * docs/CHANGES: Updated. - -2014-12-04 Werner Lemberg - - docs/CHANGES: Updated, formatted. - -2014-12-04 Dave Arnold - - [cff] Modify an FT_ASSERT. - - * src/cff/cf2hints.c (cf2_hintmap_map): After the fix for Savannah - bug #43661, the test font `...aspartam.otf' still triggers an - FT_ASSERT. Since hintmap still works with count==0, ... - (cf2_glyphpath_lineTo, cf2_glyphpath_curveTo): ... add that term to - suppress the assert. - -2014-12-04 Dave Arnold - - [cff] Fix Savannah bug #43661. - - * src/cff/cf2intrp.c (cf2_interpT2CharString) : Don't append to stem arrays after - hintmask is constructed. - - * src/cff/cf2hints.c (cf2_hintmap_build): Add defensive code to - avoid reading past end of hintmask. - -2014-12-03 Werner Lemberg - - docs/CHANGES: Updated. - -2014-12-03 Werner Lemberg - - [autofit] Better fix for conversion specifiers in debug messages. - - Using `%ld' for pointer differences causes warnings on 32bit - platforms. The correct type would be (the relatively new) `%td', - however, this is missing on some important platforms. - - This patch improves the change from 2014-11-28. - - * src/autofit/afhints.c (AF_INDEX_NUM): Use `int' typecast. Our - pointer differences are always sufficiently small. - (af_glyph_hints_dump_points, af_glyph_hints_dump_segments, - af_glyph_hints_dump_edge): Revert to `%d' and use `AF_INDEX_NUM'. - -2014-12-03 Werner Lemberg - - FT_Sfnt_Tag: s/ft_sfnt_xxx/FT_SFNT_XXX/ for orthogonality. - - All public FreeType enumeration and flag values are uppercase... - - * include/tttables.h (FT_Sfnt_Tag): Implement it. For backward - compatibility, retain the old values as macros. - - * src/base/ftfstype.c (FT_Get_FSType_Flags), src/sfnt/sfdriver.c - (get_sfnt_table): Updated. - -2014-12-02 Werner Lemberg - - * include/*: Improve structure of documentation. - - . Add and update many `' tags. - . Apply various documentation fixes. - . Remove details to deprecated (or never implemented) data. - -2014-12-02 Werner Lemberg - - [docmaker] Always handle `' section elements. - - Previously, those elements were handled only for sections present in - a `' chapter element. - - * src/tools/docmaker/content.py (ContentProcessor::finish): - Implement it. - -2014-12-02 Werner Lemberg - - [docmaker] Properly handle empty rows in Synopsis. - - * src/tools/docmaker/tohtml.py (HtmlFormatter::section_enter): Emit - ` ' for empty fields. - -2014-12-02 Werner Lemberg - - [docmaker] Thinko. - - * src/tools/docmaker/content.py (DocBlock::get_markup_words_all): - Emit `/empty/' string for first element also. - -2014-12-02 Werner Lemberg - - [docmaker] Honour empty lines in `' section element. - - This greatly improves the readability of the `Synopsis' links. - - * src/tools/docmaker/content.py (DocBlock::get_markup_words_all): - Insert string `/empty/' between items. - - * src/tools/docmaker/formatter.py (Formatter::section_dump): Make it - robust against nonexistent keys. - - * src/tools/docmaker/tohtml.py (HtmlFormatter::section_enter): Emit - empty

elements for `/empty/'. - -2014-12-02 Werner Lemberg - - [docmaker] Ensure Python 3 compatibility. - - * src/tools/docmaker/content.py (ContentProcessor::set_section, - ContentProcessor::finish): Replace `has_key' function with `in' - keyword. - - * src/tools/docmaker/formatter.py (Formatter::__init__): Replace - sorting function with a key generator. - (Formatter::add_identifier): Replace `has_key' function with `in' - keyword. - - * src/tools/docmaker/tohtml.py (HtmlFormatter::html_source_quote): - Replace `has_key' function with `in' keyword. - (HtmlFormatter::index_exit, HtmlFormatter::section_enter): Use - integer division. - s/<>/>/. - - * src/tools/docmaker/utils.py: Import `itertools'. - (index_sort): Replaced by... - (index_key): ... this new key generator (doing exactly the same). - -2014-11-29 Werner Lemberg - - [docmaker] Don't output a block multiple times. - - This bug was hidden by not processing all lines of `' blocks. - - * src/tools/docmaker/formatter.py (Formatter::section_dump): Filter - out field names. - -2014-11-29 Werner Lemberg - - [docmaker] Use field values as HTML link targets where possible. - - * src/tools/docmaker/tohtml.py (HtmlFormatter::make_block_url): - Accept second, optional argument to specify a name. - (HtmlFormatter::html_source_quote): Link to field ID if possible. - (HtmlFormatter::print_html_field_list): Emit `id' attribute. - -2014-11-29 Werner Lemberg - - [docmaker] Allow empty lines in `' blocks. - - Before this patch, the suggested order of entries stopped at the - first empty line. - - Obviously, nobody noticed that this problem caused a much reduced - set of links in the `Synopsis' sections; in particular, the - `' blocks contain a lot of entries that wouldn't be listed - otherwise... - - * src/tools/docmaker/content.py (DocBlock::get_markup_words_all): - New function to iterate over all items. - (DocSection::process): Use it. - -2014-11-29 Werner Lemberg - - * src/tools/docmaker/sources.py (column) [Format 2]: Fix regexp. - - After the single asterisk there must be no other immediately following - asterisk. - -2014-11-29 Werner Lemberg - - * src/tools/docmaker/tohtml.py: Improve CSS for vertical spacing. - -2014-11-29 Werner Lemberg - - [docmaker] Improve HTML code for table of contents. - - * src/tools/docmaker/tohtml.py: Introduce a new table class `toc', - together with proper CSS. - -2014-11-29 Werner Lemberg - - [docmaker] Provide higher-level markup and simplify HTML. - - * src/tools/docmaker/tohtml.py: Instead of using extraneous `
' - elements, use CSS descendants (of class `section') to format the - data. - - Also remove redundant

and
elements, replacing them with - proper CSS. - - Globally reduce page width to 75%. - - (block_header): Rename

class to `section'. - -2014-11-29 Werner Lemberg - - [docmaker] Add `top' links after blocks. - - * src/tools/docmaker/tohtml.py (block_footer_middle): Implement it. - -2014-11-29 Werner Lemberg - - * src/tools/docmaker/tohtml.py: Improve CSS for fields. - - Make fields align horizontally relative to full line width. - -2014-11-29 Werner Lemberg - - * src/tools/docmaker/tohtml.py: Fix index and TOC templates. - - This thinko was introduced 2014-11-27. - -2014-11-28 Werner Lemberg - - [docmaker] Format field lists with CSS. - - This also simplifies the inserted HTML code. - - * src/tools/docmaker/tohtml.py - (HtmlFormatter::print_html_field_list): Do it. - -2014-11-28 suzuki toshiya - - Fix compiler warning to the comparison between signed and - unsigned variable. - - * src/pfr/pfrsbit.c (pfr_slot_load_bitmap): Fix the comparison - between `ypos + ysize' and FT_INT_{MAX,MIN}. - -2014-11-28 Werner Lemberg - - [docmaker] Replace empty `
' with CSS. - - * src/tools/docmaker/tohtml.py (HtmlFormatter::section_enter): Do - it. - -2014-11-28 Werner Lemberg - - [docmaker] Replace some `' tags with `

' and `
'. - - * src/tools/docmaker/tohtml.py (marker_*): Use `

'. - (source_*): Use `
'. - (HtmlFormatter::block_enter): s/

/

/. - -2014-11-28 suzuki toshiya - - Fix compiler warning to conversion specifiers in debug messages. - - * src/autofit/afhints.c (af_glyph_hints_dump_points): Add length - modifier to dump long integers. - (af_glyph_hints_dump_segments, af_glyph_hints_dump_edges): Ditto. - -2014-11-27 Werner Lemberg - - * src/tools/docmaker/tohtml.py: Use more CSS for index. - -2014-11-27 Werner Lemberg - - [docmaker] Replace `name' attribute of `' with `id'. - - * src/tools/docmaker/tohtml.py (HtmlFormatter::block_enter): Do it. - -2014-11-27 Werner Lemberg - - * src/tools/docmaker/tohtml.py: Remove remaining `width' attributes. - - For `Index' and `TOC' links, we now simply use the `text-align' CSS - property of `

' to enforce flush-left and flush-right, - eliminating the hack with an empty, full-width `' element - inbetween. - - The change also enforces the same (smaller) size for all index and - TOC links. - -2014-11-27 suzuki toshiya - - * src/cff/cf2font.c: Include `ftcalc.h' to use FT_MSB(), - cf2font.c could not find it under `make multi' build. - -2014-11-27 suzuki toshiya - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Remove - unrequired negative value check for `width' and `height'. - -2014-11-27 Werner Lemberg - - * src/tools/docmaker/tohtml.py: More HTML table refactoring. - - Replace some `' tags with `
' to simplify structure. - - Move `bgcolor' attribute to CSS. - - Replace most `width' attributes with CSS. The remaining instances - (providing a similar effect as LaTeX's `\hfill' command) are removed - in a later patch. - -2014-11-27 Werner Lemberg - - * src/tools/docmaker/tohtml.py: Replace with CSS. - -2014-11-27 Werner Lemberg - - * src/tools/docmaker/tohtml.py: Center
with CSS. - -2014-11-27 Werner Lemberg - - * src/tools/docmaker/tohtml.py: Replace `
' with `
'. - -2014-11-27 Werner Lemberg - - * src/tools/docmaker/tohtml.py: Remove redundant `
' tags. - - This starts a series of commits into the direction of generating - valid HTML 5 code, especially using much more CSS. - -2014-11-27 suzuki toshiya - - Prevent too negative values (< FT_INT_MIN) in bitmap metrics, - suggested by Alexei. - - * src/pfr/pfrsbit.c (pfr_slot_load_bitmap): Prevent too - negative values in `xpos' and `ypos + ysize'. - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Prevent - too negative values in `x_left' and `y_top'. Either negative - values in `width' and `height' are checked. - -2014-11-27 Werner Lemberg - - [docmaker] Produce better HTML code. - - * src/tools/docmaker/tohtml.py: Always use double quotes for - attribute values. - (source_footer): Close `td' and `tr' groups. - -2014-11-27 Werner Lemberg - - Use better way to disable creation of .pyc files for `make refdoc'. - - Python 2.6 was released in 2008... - - * builds/freetype.mk (refdoc): Use python's `-B' option. - - * builds/detect.mk (std_setup, dos_setup): Mention required python - version for `refdoc' target. - -2014-11-27 Werner Lemberg - - * src/tools/docmaker/sources.py (re_bold, re_italic): Use - non-grouping parentheses. - * src/tools/docmaker/tohtml.py (HtmlFormatter::make_html_word): - Updated. - -2014-11-27 Werner Lemberg - - * src/base/ftobjs.c (FT_Get_Glyph_Name): Fix compiler warning. - - Introduced in previous change. Reported by Alexei. - -2014-11-26 Werner Lemberg - - * src/*: Add checks for parameters of API functions where missing. - - `API functions' are functions tagged with `FT_EXPORT_DEF'. - - Besides trivial fixes, the following changes are included, too. - - * src/base/ftbdf.c (FT_Get_BDF_Charset_ID, FT_Get_BDF_Property): Set - error code if no service is available. - - * src/base/ftinit.c (FT_Done_FreeType): Change return value for - invalid `library' parameter to `Invalid_Library_Handle'. - - * src/base/ftobjs.c (FT_New_Size): Change return value for invalid - `asize' parameter to `Invalid_Argument'. - - * src/base/ftoutln.c (FT_Outline_Copy): Change return value for - invalid `source' and `target' parameters to `Invalid_Outline'. - (FT_Outline_Done_Internal): Change return value for invalid - `outline' parameter to `Invalid_Outline'. - -2014-11-26 Werner Lemberg - - * src/cache/ftcbasic.c: Use single calls to `FT_TRACE'. - -2014-11-26 suzuki toshiya - - * src/base/ftobjs.c (Mac_Read_POST_Resource): Additional - overflow check in the summation of POST fragment lengths, - suggested by Mateusz Jurczyk . - -2014-11-26 suzuki toshiya - - * src/base/ftobjs.c (Mac_Read_POST_Resource): Insert comments - and fold too long tracing messages. - -2014-11-26 suzuki toshiya - - Fix Savannah bug #43540. - - * src/base/ftmac.c (parse_fond): Prevent a buffer overrun - caused by a font including too many (> 63) strings to store - names[] table. - -2014-11-26 suzuki toshiya - - * src/base/ftobjs.c (Mac_Read_POST_Resource): Use unsigned long - variables to read the lengths in POST fragments. Suggested by - Mateusz Jurczyk . - -2014-11-26 suzuki toshiya - - Fix Savannah bug #43539. - - * src/base/ftobjs.c (Mac_Read_POST_Resource): Fix integer overflow - by a broken POST table in resource-fork. - -2014-11-26 suzuki toshiya - - Fix Savannah bug #43538. - - * src/base/ftobjs.c (Mac_Read_POST_Resource): Fix integer overflow - by a broken POST table in resource-fork. - -2014-11-26 suzuki toshiya - - * src/base/ftobjs.c (Mac_Read_POST_Resource): Avoid memory leak - by a broken POST table in resource-fork. Return after freeing - the buffered POST table when it is found to be broken. - -2014-11-25 Werner Lemberg - - */*: s/Invalid_Argument/Invalid_Size_Handle/ where appropriate. - -2014-11-25 Werner Lemberg - - */*: s/Invalid_Argument/Invalid_Stream_Handle/ where appropriate. - -2014-11-25 Werner Lemberg - - */*: s/Invalid_Argument/Invalid_Library_Handle/ where appropriate. - -2014-11-25 Werner Lemberg - - */*: s/Invalid_Argument/Invalid_Outline/ where appropriate. - -2014-11-25 Werner Lemberg - - */*: s/Invalid_Argument/Invalid_Face_Handle/ where appropriate. - -2014-11-24 Werner Lemberg - - [Savannah bug #43682] Adjust some renderer callbacks. - - * src/raster/ftraster.c (ft_black_set_mode): Change return type to - `int' to stay in sync with `FT_Renderer_SetModeFunc' prototype. - - * src/smooth/ftgrays.c (gray_raster_set_mode): New dummy function - for orthogonality. - (ft_grays_raster): Use it. - -2014-11-25 Werner Lemberg - - [Savannah bug #43682] Properly handle missing return errors. - - The functions in this patch *do* return non-trivial errors that must - be taken care of. - - * src/autofit/afloader.c (af_loader_load_g), src/base/ftobjs.c - (FT_Render_Glyph_Internal), src/base/ftoutln.c (FT_Outline_Render), - src/cff/cffgload.c (cff_decoder_parse_charstrings) , - src/psaux/psobjs.c (ps_parser_load_field_table), src/psaux/t1decode - (t1_decoder_parse_charstrings) , src/truetype/ttgload.c - (load_truetype_glyph , tt_loader_init, - TT_Load_Glyph), src/truetype/ttgxvar.c (TT_Set_MM_Blend), - src/truetype/ttobjs.c (tt_size_run_fpgm, tt_size_run_prep): Do it. - -2014-11-25 Werner Lemberg - - [Savannah bug #43682] Add/remove `void' casts to some functions. - - We use a cast to indicate that we intentionally ignore a function's - return value. However, this doesn't apply to API functions where - errors can only happen for trivially invalid input. - - * src/base/ftstroke.c (FT_Glyph_Stroke, FT_Glyph_StrokeBorder), - src/base/ftsynth.c (FT_GlyphSlot_Embolden), src/cff/cffgload.c - (cff_slot_load), src/pfr/pfrdrivr.c (pfr_get_kerning), - src/type1/t1load.c (parse_encoding), src/type42/t42parse.c - (t42_parse_encoding): Do it. - -2014-11-25 Werner Lemberg - - [Savannah bug #43682] Change some signatures to `void' return type. - - * include/internal/pshints.h (PSH_Globals_SetScaleFunc), - include/internal/sfnt.h (TT_Get_Metrics_Func), - src/pshinter/pshglob.c (psh_globals_set_scale), - src/pshinter/pshrec.c (ps_hints_init), src/sfnt/ttmtx.c - (tt_face_get_metrics), src/truetype/ttinterp.c (TT_Goto_CodeRange, - TT_Set_CodeRange, TT_Clear_CodeRange, TT_Done_Context, - TT_Save_Context): Do it. - - * src/pshinter/pshglob.h, src/pshinter/pshrec.h, src/sfnt/ttmtx.h, - src/truetype/ttgload.c (TT_Hint_Glyph), src/truetype/ttinterp.c - (TT_Run_Context), src/truetype/ttinterp.h, src/truetype/ttobjs.c - (tt_size_run_fpgm, tt_size_run_prep): Updated. - -2014-11-24 Werner Lemberg - - Remove all code related to FT_MAX_CHARMAP_CACHEABLE. - - This is no longer used. - - * src/base/ftobjs.c, src/cache/ftccmap.c, src/cff/cffobjs.c, - src/sfnt/ttcmap.c: Do it. - -2014-11-24 Werner Lemberg - - [sfnt] Fix Savannah bug #43680. - - This adds an additional constraint to make the fix from 2013-01-25 - really work. - - * src/sfnt/ttsbit.c (tt_sbit_decoder_load_image) : - Check `p' before `num_glyphs'. - -2014-11-24 Werner Lemberg - - [truetype] Fix Savannah bug #43679. - - * src/truetype/ttpload.c (tt_face_load_hdmx): Check minimum size of - `record_size'. - -2014-11-24 Jarkko Pöyry - - [cff, pfr, psaux, winfonts] Fix Savannah bug #43676. - - Don't cast cmap init function pointers to an incompatible type. - - Without this patch, the number of parameters between declaration and - the real signature differs. Calling such a function results in - undefined behavior. - - ISO/IEC 9899:TC3 (Committee Draft September 7, 2007) - 6.5.2.2 Function calls - 9 If the function is defined with a type that is not - compatible with the type (of the expression) pointed to by - the expression that denotes the called function, the - behavior is undefined. - - On certain platforms (c -> js with emscripten) this causes - termination of execution or invalid calls because in the emscripten - implementation, function pointers of different types are stored in - different pointer arrays. Incorrect pointer type here results in - indexing of an incorrect array. - - * src/cff/cffcmap.c (cff_cmap_encoding_init, cff_cmap_unicode_init), - src/pfr/pfrcmap.c (pfr_cmap_init), src/psaux/t1cmap.c - t1_cmap_standard_init, t1_cmap_expert_init, t1_cmap_custom_init, - t1_cmap_unicode_init), src/winfonts/winfnt.c (fnt_cmap_init): Fix - signature. - -2014-11-24 Werner Lemberg - - [sfnt] Fix Savannah bug #43672. - - * src/sfnt/ttkern.c (tt_face_load_kern): Use correct value for - minimum table length test. - -2014-11-24 Werner Lemberg - - [type1, type42] Another fix for Savannah bug #43655. - - * src/type1/t1load.c (parse_charstrings), src/type42/t42parse.c - (t42_parse_charstrings): Add another boundary testing. - -2014-11-24 Werner Lemberg - - [docmaker] Formatting, copyright, improved documentation. - - * src/tools/docmaker/*: No code changes besides trivial - modifications. - -2014-11-22 Werner Lemberg - - [bdf] Fix Savannah bug #43660. - - * src/bdf/bdflib.c (_bdf_parse_glyphs) <"ENDFONT">: Check - `_BDF_GLYPH_BITS'. - -2014-11-22 Werner Lemberg - - [type42] Allow only embedded TrueType fonts. - - This is a follow-up to Savannah bug #43659. - - * src/type42/t42objs.c (T42_Face_Init): Exclusively use the - `truetype' font driver for loading the font contained in the `sfnts' - array. - -2014-11-22 Werner Lemberg - - [type42] Fix Savannah bug #43659. - - * src/type42/t42objs.c (T42_Open_Face): Initialize `face->ttf_size'. - - * src/type42/t42parse.c (t42_parse_sfnts): Always set - `face->ttf_size' directly. This ensures a correct stream size in - the call to `FT_Open_Face', which follows after parsing, even for - buggy input data. - Fix error messages. - -2014-11-22 Werner Lemberg - - [cff] Fix Savannah bug #43658. - - * src/cff/cf2ft.c (cf2_builder_lineTo, cf2_builder_cubeTo): Handle - return values of point allocation routines. - -2014-11-22 Werner Lemberg - - [sfnt] Fix Savannah bug #43656. - - * src/sfnt/ttcmap.c (tt_cmap4_validate): Fix order of validity - tests. - -2014-11-21 Werner Lemberg - - [type1, type42] Fix Savannah bug #43655. - - * src/type1/t1load.c (parse_charstrings), src/type42/t42parse.c - (t42_parse_charstrings): Fix boundary testing. - -2014-11-21 Werner Lemberg - - * src/pcf/pcfread.c (pcf_get_metrics): Sanitize invalid metrics. - -2014-11-21 Werner Lemberg - - [ftlcdfil] Obey flow direction. - - * src/base/ftlcdfil.c (_ft_lcd_filter_fir, _ft_lcd_filter_legacy): - Handle `up' flow. - -2014-11-21 Werner Lemberg - - * src/base/ftbitmap.c (FT_Bitmap_Convert): Improve. - - This commit completes argument checks and adds support for different - flow directions. - -2014-11-21 Werner Lemberg - - * src/base/ftbitmap.c (FT_Bitmap_Copy): Improve. - - This commit adds argument checks and support for different flow - directions. - -2014-11-20 Werner Lemberg - - * src/base/ftbitmap.c (FT_Bitmap_New): Check argument. - -2014-11-19 Werner Lemberg - - Change some fields in `FT_Bitmap' to unsigned type. - - This doesn't break ABI. - - * include/ftimage.h (FT_Bitmap): Make `rows', `width', `num_grays', - `pixel_mode', and `palette_mode' unsigned types. - - * src/base/ftbitmap.c: Updated. - (FT_Bitmap_Copy): Fix casts. - - * src/cache/ftcsbits.c, src/raster/ftraster.c, src/sfnt/pngshim.c: - Updated. - -2014-11-19 Werner Lemberg - - Make `FT_Bitmap_Convert' correctly handle negative `pitch' values. - - * src/base/ftbitmap.c (FT_Bitmap_Convert): Always use positive value - for the pitch while copying data. - Correctly set pitch sign in target bitmap. - -2014-11-19 Werner Lemberg - - Minor code improvement in `FT_Bitmap_Embolden'. - - * src/base/ftbitmap.c (FT_Bitmap_Embolden) : - Fix thinko. - -2014-11-19 Alexei Podtelezhnikov - - * src/base/fttrigon.c: Use dedicated `FT_Angle' for arctan table. - -2014-11-19 Behdad Esfahbod - - Avoid compiler warnings on x86-64 for `FT_MulFix'. - - `FT_MulFix' takes `FT_Long' parameters as defined in `freetype.h', - but several inline implementations of it in `ftcalc.h' take - `FT_Int32' arguments. This is causing compiler warnings on x86-64: - If parameters of type `FT_Fixed' (= `FT_Long') are passed to the - inline implementation of this function, integer values are truncated - from 64bit to 32bit. - - * include/internal/ftcalc.h (FT_MulFix) [FT_MULFIX_ASSEMBLER]: Add - casts. - -2014-11-15 Werner Lemberg - - [sfnt] Fix Savannah bug #43597. - - * src/sfnt/pngshim.c (Load_SBit_Png): Protect against too large - bitmaps. - -2014-11-12 Werner Lemberg - - [sfnt] Fix Savannah bug #43591. - - * src/sfnt/ttsbit.c (tt_sbit_decoder_init): Protect against addition - and multiplication overflow. - -2014-11-12 Werner Lemberg - - [sfnt] Fix Savannah bug #43590. - - * src/sfnt/ttload.c (check_table_dir, tt_face_load_font_dir): - Protect against addition overflow. - -2014-11-12 Werner Lemberg - - [sfnt] Fix Savannah bug #43589. - - * src/sfnt/sfobjs.c (woff_open_font): Protect against addition - overflow. - -2014-11-12 Werner Lemberg - - [sfnt] Fix Savannah bug #43588. - - * src/sfnt/ttcmap.c (tt_cmap8_validate, tt_cmap10_validate, - tt_cmap12_validate, tt_cmap13_validate, tt_cmap14_validate): Protect - against overflow in additions and multiplications. - -2014-11-10 Alexei Podtelezhnikov - - [base] CORDIC improvements. - - The scaling between the hypotenuse and its CORDIC approximation is - based on regression analysis. The smaller padding for `theta' is - justified by its maximum error of less than 6. - - * src/base/fttrigon.c (ft_trig_downscale): Borrow code from - ./ftcalc.c (ft_multo64), change linear intercept. - (ft_trig_pseudo_polarize): Decrease `theta' padding. - -2014-11-09 Werner Lemberg - - * src/base/ftstroke.c (ft_stroker_inside): Fix border intersections. - - One more place to check whether `radius' is zero. - - Problem reported by Marco Wertz . - -2014-11-07 Werner Lemberg - - [bdf] Fix Savannah bug #43535. - - * src/bdf/bdflib.c (_bdf_strncmp): New macro that checks one - character more than `strncmp'. - s/ft_strncmp/_bdf_strncmp/ everywhere. - -2014-11-06 Werner Lemberg - - [pcf] Fix Savannah bug #43548. - - * src/pcf/pcfread.c (pcf_get_encodings): Add sanity checks for row - and column values. - -2014-11-06 Werner Lemberg - - [pcf] Fix Savannah bug #43547. - - * src/pcf/pcfread.c (pcf_read_TOC): Check `size' and `offset' - values. - -2014-11-06 Werner Lemberg - - * src/pcf/pcfread.c (pcf_read_TOC): Avoid memory leak. - -2014-11-03 Infinality - - * src/truetype/ttsubpix.c (COMPATIBILITY_MODE_Rules): Updated. - - The previous commit deteriorates rendering of DejaVu and similar - fonts; this gets compensated with this rule. - -2014-11-03 Werner Lemberg - - * src/truetype/ttinterp.c (Ins_DELTAP): Fix subpixel hinting. - - Before this patch, it was impossible to ever call DELTAP[123] in - subpixel hinting mode as described in the ClearType whitepaper; it - only worked if in `compatibility mode'. However, compatibility mode - essentially disables SHPIX, completely ruining hinting of - ttfautohint output, for example. - - We now follow the whitepaper more closely so that DELTAP[123] - instructions for touched points in the non-subpixel direction are - executed. - -2014-10-31 Alexei Podtelezhnikov - - [smooth] Improve code readability. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Rearrange code. - -2014-10-31 Alexei Podtelezhnikov - - [smooth] Reduce outline translations during rendering. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Translate origin - virtually by modifying cbox, actually translate outline if cumulative - shift is not zero. - -2014-10-30 Alexei Podtelezhnikov - - [smooth] Fix Savannah bug #35604 (cont'd). - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Remove checks and - casts that became unnecessary after the variable type upgrades. - -2014-10-29 Alexei Podtelezhnikov - - [smooth] Improve code readability. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Rearrange code. - -2014-10-29 Alexei Podtelezhnikov - - Unify hypotenuse approximations. - - * include/internal/ftcalc.h (FT_HYPOT): Move macro from here... - * include/internal/ftobjs.h: ... to here, next to required `FT_ABS'. - * src/smooth/ftgrays.c (gray_render_cubic): Use it here. - -2014-10-25 Werner Lemberg - - [cff] Test valid darkening parameter macros in `ftoption.h'. - - We no longer need an otherwise unused typedef that can cause a gcc - warning. - Problem reported by Alexei. - - * src/cff/cffobjs.c (cff_driver_init): Use - `CFF_CONFIG_OPTION_DARKENING_PARAMETER_XXX' macros directly. - (SET_DARKENING_PARAMETERS): Removed. - Compile time tests are now ... - - * devel/ftoption.h, include/config/ftoption.h: ... here. - -2014-10-25 Alexei Podtelezhnikov - - Improve flat corner definition. - - * include/internal/ftcalc.h (FT_HYPOT): Macro to approximate Euclidean - distance with the alpha max plus beta min algorithm. - * src/base/ftcalc.c (ft_corner_is_flat): Use it instead of Taxicab - metric. - -2014-10-23 David Weiß - - [build] Improve property file for vc2010. - - User-defined properties should be empty by default to prevent linker - failures. - - * builds/windows/vc2010/freetype.user.props, - builds/windows/vc2010/freetype.vcxproj: - s/OptionsDirectory/UserOptionDirectory/. - Comment out all user options. - -2014-10-23 Werner Lemberg - - [cff] Work around bug in preprocessor of MSVC 2010. - - We have been hit by - - https://connect.microsoft.com/VisualStudio/feedback/details/718976/msvc-pr - - * devel/ftoption.h, include/config/ftoption.h: Replace - `CFF_CONFIG_OPTION_DARKENING_PARAMETERS' with eight macros - `CFF_CONFIG_OPTION_DARKENING_PARAMETER_{X,Y}{1,2,3,4}'. - - * src/cff/cffobjs.c (SET_DARKENING_PARAMETERS): Removed. We no - longer need double expansion. - (SET_DARKENING_PARAMETERS_0): Renamed to ... - (SET_DARKENING_PARAMETERS): ... this. - Update call. - -2014-10-20 Werner Lemberg - - [sbit] Minor fixes. - - * src/sfnt/ttsbit.c (tt_face_load_sbit) [TT_SBIT_TABLE_TYPE_SBIX]: - Accept overlay format also, but emit warning message in that case. - (tt_sbit_decoder_load_metrics): Add missing newline to error - message. - (tt_sbit_load_sbix_image): Add `rgbl' graphic type (as used on iOS - 7.1) to the list of unsupported formats. - -2014-10-19 Alexei Podtelezhnikov - - [truetype] Clean up bytecode rounding. - - Zero distance does not have to be treated specially if you follow - specifications and check the sign as the very last step of rounding. - - * src/truetype/ttinterp.c (Round_None, Round_To_Grid, - Round_Down_To_Grid, Round_Up_To_Grid, Round_To_Double_Grid): Use - macros when available, do not check for non-zero distance. - (Round_To_Half_Grid, Round_Super, Round_Super_45): Ditto, return phase - if sign changed. - -2014-10-18 Alexei Podtelezhnikov - - [truetype] Unwrap engine compensation settings. - - * src/truetype/ttobjs.c (tt_size_init_bytecode): Updated. - -2014-10-18 David Weiß - - [build] Add property file to vc2010 project. - - This simplifies custom build configurations, especially for - automated build environments. - - * builds/windows/vc2010/freetype.user.props: New configuration file. - - * builds/windows/vc2010/freetype.vcxproj: Include - `freetype.user.props' and use its data fields. - - * builds/windows/vc2010/index.html: Updated. - -2014-10-18 Werner Lemberg - - [autofit] Add blue-zone support for Telugu. - - This essentially moves the Telugu script from the `Indic' hinter to - the `Latin' hinter. - - Note that this is a first shot and quite certainly needs - refinements. - - * src/autofit/afblue.dat: Add blue zone data for Telugu. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Telugu standard characters and move - data out of AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afranges.c: Move Telugu data out of - AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afstyles.h: Update Telugu data; in particular, use - AF_WRITING_SYSTEM_LATIN. - -2014-10-18 David Wimsey - - [cmake] Add iOS build support. - From Savannah patch #8497. - - * builds/cmake/iOS.cmake: New file. Universal binaries are built - with both 32 and 64 bit arm architectures. - - * CMakeLists.txt (IOS_PLATFORM): New variable for running the iOS - toolchain. Possible values are `OS' to build on iOS, or - `SIMULATOR' to build on APPLE. - -2014-10-16 Behdad Esfahbod - Werner Lemberg - - [cff] Add `CFF_CONFIG_OPTION_DARKENING_PARAMETERS' config macro. - - * devel/ftoption.h, include/config/ftoption.h - (CFF_CONFIG_OPTION_DARKENING_PARAMETERS): New macro. - - * src/cff/cffobjs.c (SET_DARKENING_PARAMETERS, - SET_DARKENING_PARAMETERS_0): New macros. - (cff_driver_init): Use new macros. - -2014-10-14 Alexei Podtelezhnikov - - [truetype] Limit delta shift range. - - The valid range for delta shift is zero through six. Negative values - are invalid according to - - https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#delta%20shift - - * src/truetype/ttobjs.h (delta_shift, delta_base): Make unsigned. - * src/truetype/ttinterp.h (DO_SDS): Throw an error if `delta_shift' - is out of range. - (Ins_DELTAP, Ins_DELTAC): Optimize for valid `delta_shift'. - -2014-10-16 Werner Lemberg - - A better fix for Savannah bug #43392. - Suggested by Doug Felt . - - * src/sfnt/ttsbit.c (tt_sbit_decoder_load_metrics): Set - `vertAdvance' to zero... - - * src/truetype/ttgload.c (TT_Load_Glyph): ... and set here a default - value for `vertAdvance' based on `linearVertAdvance' in case - `vertAdvance' is zero. Note that the previous computed ad-hoc value - for `linearVertAdvance' was apparently not tested in a real-life - situation. - -2014-10-14 David Weiß - - [build] Better optimization settings for vc2010 solution file. - - * builds/windows/vc2010/freetype.sln, - builds/windows/vc2010/freetype.vcxproj: Updated. - -2014-10-14 Werner Lemberg - - [autofit] Adjust Devanagari character range. - - * src/autofit/afranges.c (af_deva_uniranges): Omit characters that - are common to all other Indic scripts. - -2014-10-12 Werner Lemberg - - [sfnt] Fix Savannah bug #43392. - - * src/sfnt/ttsbit.c (tt_sbit_decoder_load_metrics): Don't let - vertical metrics uninitialized. - -2014-10-11 Alexei Podtelezhnikov - - [base] Small bbox correction. - - * src/base/ftbbox.c (FT_Outline_Get_BBox): Start from nonsense bbox - instead of initial point that could be `off' in conic outlines. - -2014-10-08 Alexei Podtelezhnikov - - [base] Fix Savannah bug #43356. - - * src/base/ftbbox.c (BBox_Move_To, BBox_Conic_To): Update bbox in case - of implicit `to'. - (BBox_Line_To): New emitter that does not update bbox. - -2014-10-08 Alexei Podtelezhnikov - - [base] Introduce and use new macro `FT_UPDATE_BBOX' - - * src/base/ftbbox.c (FT_UPDATE_BBOX): New macro. - (FT_Outline_Get_BBox): Use it here. - -2014-10-02 Alexei Podtelezhnikov - - [base] Significant optimization of `ft_div64by32' - - We shift as many bits as we can into the high register, perform - 32-bit division with modulo there, then work through the remaining - bits with long division. This optimization is especially noticeable - for smaller dividends that barely use the high register. - - * src/base/ftcalc.c (ft_div64by32): Updated. - -2014-10-02 Dave Arnold - - [cff] Fix Savannah bug #43271. - - * src/cff/cf2font.c (cf2_computeDarkening): Change overflow - detection to use logarithms and clamp `scaledStem'. - -2014-10-01 Alexei Podtelezhnikov - - * src/base/ftcalc.c: Remove miscellaneous type casts. - -2014-10-01 Alexei Podtelezhnikov - - [base] Use more common `FT_MSB' implementation with masks. - - * src/base/ftcalc.c (FT_MSB): Updated. - -2014-09-30 Alexei Podtelezhnikov - - [base] Clean up. - - * src/base/ftcalc.c (FT_MOVE_SIGN): New macro for frequently used - code. - -2014-09-25 Alexei Podtelezhnikov - - [base] Avoid unnecessary long division. - - This applies to `FT_MulDiv' but not to `FT_DivFix', where overflows or - lack thereof are predicted accurately. - - * src/base/ftcalc.c (ft_div64by32): Improve readability. - (FT_MulDiv, FT_MulDiv_No_Round) [!FT_LONG64]: Use straight division - when multiplication stayed within 32 bits. - -2014-09-24 Werner Lemberg - - [autofit] Minor clean-ups. - - * src/autofit/afhints.c (AF_FLAGS): Remove obsolete values. - - * src/autofit/afhints.c (af_glyph_hints_dump_points, - af_glyph_hints_align_strong_points): Updated. - - * src/autofit/aflatin.c (af_latin_hints_link_segments, - af_latin_hints_compute_segments), src/autofit/afcjk.c - (af_cjk_hints_link_segments), src/autofit/aflatin2.c - (af_latin2_hints_link_segments, af_latin2_hints_compute_segments): - There are no longer fake segments since more than 10 years... - -2014-09-22 Werner Lemberg - - [autofit] Minor code streamlining. - - * src/autofit/afhints.c (af_axis_hints_new_edge): Remove redundant - initialization. - -2014-09-19 Alexei Podtelezhnikov - - * src/base/ftcalc.c: Harmonize code. - -2014-09-15 Alexei Podtelezhnikov - - [base] Tighten the overflow check in `FT_MulDiv'. - - * src/base/ftcalc.c (FT_MulDiv) [!FT_LONG64]: Updated. - -2014-09-08 Alexei Podtelezhnikov - - Fix Savannah bug #43153. - - * src/psaux/psconv.c (PS_Conv_ToFixed): Add protection against - overflow in `divider'. - -2014-09-03 Alexei Podtelezhnikov - - [base] Tighten the overflow check in `FT_DivFix'. - - This fixes a 13-year old bug. The original overflow check should have - been updated when rounding was introduced into this function - (c2cd00443b). - - * src/base/ftcalc.c (FT_DivFix) [!FT_LONG64]: Updated. - * include/freetype.h (FT_DivFix): Updated documentation. - -2014-09-03 Alexei Podtelezhnikov - - [base] Tighten the overflow check in `FT_MulFix'. - - * src/base/ftcalc.c (FT_MulFix) [!FT_LONG64]: Updated. - -2014-09-02 Alexei Podtelezhnikov - - [truetype] Shortcut ppem calculations for square pixels. - - * src/truetype/ttinterp.h (TT_ExecContextRec): New field - `cur_ppem_func' with a function pointer. - * src/truetype/ttinterp.c (TT_RunIns): Initialize `cur_ppem_func' - depending on the pixel geometry to either... - (Current_Ppem_Stretched): ... this for stretched pixels. - (Current_Ppem): ... or this for square pixels. - (DO_MPPEM, DO_MPS, Ins_DELTAP, Ins_DELTAC): Use `cur_ppem_func'. - -2014-08-31 Behdad Esfahbod - - Don't use `register' keyword. Fixes compiler warnings. - - * src/base/ftcalc.c (FT_Add64) [!FT_LONG64]: Do it. - * src/gzip/inftrees.c (huft_build): Ditto. - * src/truetype/ttinterp.c (TT_MulFix14_arm): Ditto. - -2014-08-24 Alexei Podtelezhnikov - - [truetype] Optimize DELTAP and DELTAC. - - * src/truetype/ttinterp.c (Ins_DELTAP, Ins_DELTAC): Move ppem - calculations outside of the loop. - -2014-08-21 Alexei Podtelezhnikov - - Fix Savannah bug #43033. - - * include/config/ftconfig.h, builds/unix/ftconfig.in, - builds/vms/ftconfig.h [FT_LONG64]: Do not disable the macro when - 64-bit type is `long'. - -2014-08-20 Alexei Podtelezhnikov - - [base] Small optimization of `FT_MulFix'. - - * src/base/ftcalc.c (FT_MulFix): Loosen up the condition for direct - 32-bit calculations. - -2014-08-19 Alexei Podtelezhnikov - - [base] Use unsigned calculation in `FT_MulDiv'. - - * src/base/ftcalc.c (FT_MulDiv): Updated to expand 32-bit range. - -2014-08-18 Alexei Podtelezhnikov - - [base] Remove truncation in `FT_DivFix'. - - * src/base/ftcalc.c (FT_DivFix): Updated. - -2014-08-14 Alexei Podtelezhnikov - - Minor refactoring. - - * src/base/ftcalc.c (FT_MulDiv, FT_MulDiv_No_Round): Updated. - -2014-08-14 Alexei Podtelezhnikov - - Turn FT_MSB into a macro when using gcc builtins. - - * src/base/ftcalc.c, include/internal/ftcalc.h: Updated. - -2014-08-12 Alexei Podtelezhnikov - - [base] Avoid undefined FT_MSB in `BBox_Cubic_Check'. - - * src/base/ftbbox.c (BBox_Cubic_Check): Update. - (update_cubic_max): Replace with... - (cubic_peak): ... this, which now handles upscaling. - -2014-08-11 Alexei Podtelezhnikov - - [base] Handle collapsed outlines to avoid undefined FT_MSB. - - * src/base/ftoutln.c (FT_Outline_Get_Orientation): Update. - -2014-08-11 Alexei Podtelezhnikov - - [base] Restore FT_MulFix inlining. - - * include/freetype.h (FT_MulFix): Unconditionally defined. - - * src/base/ftcalc.c [FT_MULFIX_ASSEMBLER]: Move code from here... - - * include/internal/ftcalc.h [FT_MULFIX_ASSEMBLER]: ... to here, - which conditionally replaces the function with an inline version - through the macro. - -2014-08-08 Alexei Podtelezhnikov - - * src/base/ftbitmap.c (ft_gray_for_premultiplied_srgb_bgra): Refactor. - -2014-07-26 Werner Lemberg - - [cff] Fix typo. - - * src/cff/cf2hints.c (cf2_glyphpath_computeOffset): Use correct - offsets in third quadrant. - - Reported by maks . - -2014-07-17 Werner Lemberg - - Fix Savannah bug #42788. - - * src/pfr/pfrobjs.c: Include `ftcalc.h'. - -2014-07-16 Alexei Podtelezhnikov - - Replace `ft_highpow2' function. - - * src/pfr/pfrobjs.c (pfr_face_get_kerning): Use `FT_MSB' instead of - `ft_highpow2'. - - * src/base/ftutil.c, include/internal/ftobjs.h (ft_highpow2): Remove - it. - -2014-07-15 Alexei Podtelezhnikov - - * src/base/ftcalc.c (FT_MSB): Utilize gcc builtins. - -2014-07-15 Alexei Podtelezhnikov - - [base] Move assembler code back in the source file. - - FT_MulFix assembler used to reside in ftcalc.c before f47d263f1b. - - * include/config/ftconfig.h, builds/unix/ftconfig.in, - builds/vms/ftconfig.h [FT_MULFIX_ASSEMBLER]: Move code from here... - - * src/base/ftcalc.c [FT_MULFIX_ASSEMBLER]: ... to here. - -2014-07-14 Alexei Podtelezhnikov - - [base] Further clean up color bitmap conversion. - - * src/base/ftbitmap.c (ft_gray_for_premultiplied_srgb_bgra): Stop - using FT_MulFix and FT_DivFix since all calculations fit into 32 bits. - -2014-07-13 Werner Lemberg - - [truetype] Improve handling of buggy `prep' tables. - - In case of an error in the `prep' table, no longer try to execute it - again and again. This makes FreeType handle endless loops in buggy - fonts much faster. - - * src/truetype/ttobjs.h (TT_SizeRec): The fields `bytecode_ready' - and `cvt_ready' are now negative if not initialized yet, otherwise - they indicate the error code of the last run. - - * src/truetype/ttobjs.c (tt_size_run_fpgm, tt_size_run_prep, - tt_size_done_bytecode, tt_size_init_bytecode, - tt_size_ready_bytecode, tt_size_init, tt_size_done, tt_size_reset): - Updated. - - * src/truetype/ttgload.c (tt_loader_init): Updated. - * src/truetype/ttinterp.c (TT_RunIns): Force reexecution of `fpgm' - and `prep' only if we are in the `glyf' table. - -2014-07-12 Werner Lemberg - - * builds/vms/ftconfig.h: Synchronize. - Problem reported by Alexei. - -2014-07-11 Alexei Podtelezhnikov - - [base] Clean up bitmap conversion. - - * src/base/ftbitmap.c (ft_gray_for_premultiplied_srgb_bgra): Use - appropriate FT_DivFix and remove superfluous upscaling. - -2014-07-04 Alexei Podtelezhnikov - - [base] Small optimization of the ancient code. - - * src/base/ftcalc.c (FT_MulDiv, FT_MulDiv_No_Round): Loosen up the - condition for direct 32-bit calculations. - -2014-06-27 Werner Lemberg - - Fix Apple standard glyph names. - - * src/sfnt/ttpost.c (tt_post_default_names): Synchronize with - `tools/glnames.py' - - Problem reported by Adam Twardoch . - -2014-06-17 Werner Lemberg - - Partially revert commit from 2014-06-13. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Move - declaration of `p_first' and `p_last' out of the loop. - -2014-06-17 Werner Lemberg - - * builds/unix/freetype2.m4: s/AC_PATH_PROG/AC_PATH_TOOL/. - - This simplifies cross-compiling. - -2014-06-13 Werner Lemberg - - Fix more compiler warnings. - Reported by Wojciech Mamrak . - - * src/autofit/afglobal.c (af_face_globals_compute_style_coverage): - Make integer constant unsigned. - - * src/sfnt/ttsbit.c (tt_face_load_strike_metrics) - : Fix types. - (tt_sbit_decoder_load_compound, tt_face_load_sbix_image): Add proper - casts. - -2014-06-13 Werner Lemberg - - Fix compiler warnings. - Reported by Wojciech Mamrak . - - * src/autofit/afglobal.c (af_face_globals_compute_style_coverage), - src/autofit/afmodule.c (af_property_set): Fix `signed' vs. - `unsigned' issues. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Make compiler - happy. - - * src/base/ftlcdfil.c (_ft_lcd_filter_fir): Use only four elements - for `fir'. - Fix `signed' vs. `unsigned' issues. - - * src/sfnt/sfobjs.c (WRITE_BYTE): Removed, unused. - (WRITE_USHORT, WRITE_ULONG): Add proper casts. - - * src/truetype/ttgload.c (TT_Get_VMetrics): Add proper casts. - - * src/truetype/ttinterp.c (Ins_DELTAP): Add proper casts for `B1' - and `B2'. - -2014-05-16 Alexey Petruchik - - [cmake] Add option to build OS X framework. - - * CMakeLists.txt: Update accordingly. - - * builds/mac/freetype-Info.plist: New file. - -2014-05-13 Pavel Koshevoy - - * CMakeLists.txt (BASE_SRCS): Add missing `ftbdf.c'. - -2014-05-11 Werner Lemberg - - [autofit] Fix variable initializations. - - * src/autofit/afhints.c (af_glyph_hints_reload): Assign default - values to `in_dir' and `out_dir' for all points. - -2014-05-11 Werner Lemberg - - [autofit] Fix crash with font `CabinSketch-Bold.ttf'. - - Problem reported by Ralf S. Engelschall . - - * src/autofit/afhints.c (af_glyph_hints_reload): Fix threshold for - finding first non-near point. - Properly initialize non-near point deltas. - -2014-05-01 Werner Lemberg - - [autofit] Add blue-zone support for Devanagari. - - This essentially moves the Devanagari script from the `Indic' hinter - to the `Latin' hinter. Thanks to Girish Dalvi - for guidance with blue zone characters! - - * src/autofit/afblue.dat: Add blue zone data for Devanagari. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Devanagari standard characters and - move data out of AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afranges.c: Move Devanagari data out of - AF_CONFIG_OPTION_INDIC block. - Move U+20B9, (new) Rupee sign, from Latin to Devanagari. - - * src/autofit/afstyles.h: Update Devanagari data; in particular, use - AF_WRITING_SYSTEM_LATIN. - -2014-05-01 Werner Lemberg - - [autofit] Fix handling of neutral blue zones in stems. - - * src/autofit/afhints.h (AF_Edge_Flags): New value - `AF_EDGE_NEUTRAL'. - - * src/autofit/aflatin.c (af_latin_hints_compute_blue_edges): Trace - neutral blue zones with AF_EDGE_NEUTRAL. - (af_latin_hint_edges): Skip neutral blue zones if necessary. - -2014-04-28 Werner Lemberg - - [autofit] Introduce neutral blue zones to the latin module. - - Such blue zones match either the top or the bottom of a contour. We - need them for scripts where accent-like elements directly touch the - base character (for example, some vowel signs in Devanagari, cf. - U+0913 or U+0914). - - * src/autofit/afblue.hin (AF_BLUE_PROPERTY_LATIN_NEUTRAL): New - property. - - * src/autofit/afblue.h: Regenerated. - - * src/autofit/aflatin.h (AF_LATIN_IS_NEUTRAL_BLUE): New macro. - (AF_LATIN_BLUE_NEUTRAL): New enumeration value. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues, - af_latin_hints_compute_blue_edges): Handle neutral blue zones. - -2014-04-25 Werner Lemberg - - * src/autofit/hbshim.c: Partially revert commit from 2014-04-17. - - Using input glyph coverage data is simply wrong. - - Problem reported by Nikolaus Waxweiler and - Mantas Mikulėnas . - -2014-04-23 Werner Lemberg - - * src/raster/ftraster.c (Vertical_Sweep_Span): Use drop-out mode. - - This spot has been missed while introducing support for various - drop-out modes years ago (including no drop-out mode, which this - commit fixes). - - Problem reported by Patrick Thomas . - -2014-04-22 Werner Lemberg - - * src/sfnt/pngshim.c (error_callback): s/longjmp/ft_longjmp/. - -2014-04-20 Werner Lemberg - - [autofit] Fix Savannah bug #42148. - - The adaptation of the cjk auto-hinter module to blue stringsets in - 2013-08-25 had three severe bugs. Mea culpa. - - 1. Contrary to the latin auto-hinter, characters for reference and - overshoot values of a blue zone are specified separately. Due to - the screwed-up change it didn't work at all. - - 2. A boolean comparison was erroneously replaced with a cast, - causing invalid results with the `^' operator later on. The - visual artifact caused by this problem is the topic of the bug - report. - - 3. Two flag values were inverted, causing incorrect assignment of - reference and overshoot values. - - * src/autofit/afblue.dat: Fix CJK bluestrings, introducing a new - syntax to have both reference and overshoot characters in a single - string. This is error #1. - Add extensive comments. - - * src/autofit/afblue.hin (AF_BLUE_PROPERTY_CJK_FILL): Removed, no - longer used. - (AF_BLUE_PROPERTY_CJK_TOP, AF_BLUE_PROPERTY_CJK_HORIZ): Fix values. - This is error #3. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afcjk.c (af_cjk_metrics_init_blues): Correct error #1. - Use character `|' to separate characters for reference and overshoot - values. - Improve tracing messages, synchronizing them with the latin - auto-hinter. - (af_cjk_hints_compute_blue_edges): Fix value of `is_top_right_blue'. - This is error #2. - (af_cjk_align_linked_edge): Add tracing message. - - * src/autofit/afcjk.h (AF_CJK_IS_FILLED_BLUE): Removed, no longer - used. - -2014-04-17 Werner Lemberg - - [autofit] More coverage fixes for complex scripts. - - * src/autofit/hbshim.c (af_get_coverage): Merge input glyph coverage - of GSUB lookups into output coverage. Otherwise, ligatures are not - handled properly. - Don't check blue zone characters for default coverage. - -2014-04-17 Werner Lemberg - - Make `FT_Get_SubGlyph_Info' actually work. - - * src/base/ftobjs.c (FT_Get_SubGlyph_Info): Return FT_Err_Ok - if there is no error. - -2014-04-15 Werner Lemberg - - [afblue.pl]: Minor improvements. - - * src/tools/afblue.pl: Allow whitespace before comments. - Ignore whitespace in strings. - -2014-04-14 Werner Lemberg - - [autofit] Improve coverage handling. - - * src/autofit/hbshim.c (af_get_coverage): Don't exclude glyphs - appearing in the GPOS table if we are processing the default - coverage. - -2014-04-13 David Weber - - [smooth] Fix stand-alone compilation. - - * src/smooth/ftgrays.c (FT_BEGIN_STMNT, FT_END_STMNT): Define. - -2014-04-12 Werner Lemberg - - [autofit] Redesign the recognition algorithm of strong points. - - In particular, local extrema without horizontal or vertical segments - are better recognized: - - + A + D - \ / - \ / - \ / - \ / - \ + C - \ / - B +/ - - If the distances AB and CD are large, point B wasn't previously - detected as an extremum since the `ft_corner_is_flat' function - `swallowed' BC regardless of its direction, tagging point B as weak. - The next iteration started at B and made `ft_corner_is_flat' swallow - point C, tagging it as weak also, et voilà. - - To improve that, another pass gets now performed before calling - `ft_corner_is_flat' to improve the `topology' of an outline: A - sequence of non-horizontal or non-vertical vectors that point into - the same quadrant are handled as a single, large vector. - - Additionally, distances of near points are now accumulated, which - makes the auto-hinter handle them as if they were prepended to the - next non-near vector. - - This generally improves the auto-hinter's rendering results. - - * src/autofit/afhints.c (af_glyph_hints_reload): Implement it. - - * src/autofit/afhints.h (AF_FLAGS): Remove no longer used flag - `AF_FLAG_NEAR'. - -2014-04-05 Werner Lemberg - - [autofit] Improve scoring algorithm for identifying stems. - - Problem reported by Karsten Lücke . - - The new algorithm takes care of the width of stems: If the distance - between two segments is larger than the largest stem width, the - demerits quickly increase for larger distances. This improves - hinting of slanted fonts (especially if the inner parts of serifs - have non-horizontal `shoulders'), avoiding false stem links. - - * src/autofit/aflatin.c (af_latin_hints_link_segments): Use largest - stem width (if available) to compute better demerits for distances - between stems. - (af_latin_hints_detect_features): Pass stem width array and array - size. - (af_latin_metrics_init_widths): Updated to use original algorithm. - (af_latin_hints_apply): Updated to use new algorithm. - - * src/autofit/aflatin.h: Updated. - * src/autofit/afcjk.c: Updated. - -2014-04-03 Werner Lemberg - - Don't require `gzip' module for `sfnt'. - - Reported by Preet . - - * src/sfnt/sfobjs.c (woff_open_font): Guard use of - FT_Gzip_Uncompress with FT_CONFIG_OPTION_USE_ZLIB. - -2014-03-27 Werner Lemberg - - Fix Savannah bug #38235. - - Work around a bug in pkg-config version 0.28 and earlier: If a - variable value gets surrounded by doublequotes (in particular values - for the `prefix' variable), the prefix override mechanism fails. - - * builds/unix/freetype2.in: Don't use doublequotes. - * builds/unix/unix-def.in (freetype.pc): Escape spaces in directory - names with backslashes. - -2014-03-24 Werner Lemberg - - Fix Savannah bug #41946. - - Based on a patch from Marek Kašík . - - * builds/unix/configure.raw (LIBS_CONFIG): Remove. - * builds/unix/freetype-config.in (libs): Hard-code value. - * builds/unix/unix-def.in: Updated. - -2014-03-22 Werner Lemberg - - Another revert for the change from 2014-03-18. - - Problem reported by Nikolaus Waxweiler . - - * src/base/ftcalc.c (FT_MulFix): Ensure that an `FT_MulFix' symbol - gets always exported. - -2014-03-20 Werner Lemberg - - CMakeLists.txt: Another fix for include directories. - - Problem reported by Taylor Holberton . - -2014-03-19 Werner Lemberg - - CMakeLists.txt: Fix include directories. - - Problem reported by Taylor Holberton . - -2014-03-19 Werner Lemberg - - Partially revert last commit. - - Found by Alexei. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Initializing - those variables is plain wrong, since we are in a loop. - -2014-03-18 Sean McBride - Werner Lemberg - - Fix clang warnings. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Initialize - some variables. - - * src/base/ftcalc.c (FT_MulFix): Only use code if - `FT_MULFIX_INLINED' is not defined. - - * src/bdf/bdfdrivr.c (bdf_cmap_class), src/cache/ftcbasic.c - (ftc_basic_image_family_class, ftc_basic_image_cache_class, - ftc_basic_sbit_family_class, ftc_basic_sbit_cache_class), - src/cache/ftccmap.c (ftc_cmap_cache_class), src/cache/ftcmanag.c - (ftc_size_list_class, ftc_face_list_class), src/pcf/pcfdrivr.c - (pcf_cmap_class), src/pfr/pfrdrivr.c (pfr_metrics_service_rec): Make - function static. - - * src/type1/t1driver.c (t1_ps_get_font_value): Remove redundant - code. - -2014-03-17 Werner Lemberg - - Fix Savannah bug #41869. - - This works around a problem with HarfBuzz (<= 0.9.26), which doesn't - validate glyph indices returned by - `hb_ot_layout_lookup_collect_glyphs'. - - * src/autofit/hbshim.c (af_get_coverage): Guard `idx'. - - * docs/CHANGES: Updated. - -2014-03-14 Werner Lemberg - - * builds/unix/configure.raw: Don't show error messages of `which'. - -2014-03-09 Alan Coopersmith - - Fix cppcheck 1.64 warning. - - * src/autofit/afglobal.c (af_face_globals_new): Catch NULL pointer - dereference in case of error. - -2014-03-09 Sean McBride - - * src/sfnt/ttcmap.c (tt_face_build_cmaps): Remove clang warning. - -2014-03-06 Werner Lemberg - - * Version 2.5.3 released. - ========================= - - - Tag sources with `VER-2-5-3'. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.5.3. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.5.2/2.5.3/, s/252/253/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 3. - - * builds/unix/configure.raw (version_info): Set to 17:2:11. - * CMakeLists.txt (VERSION_PATCH): Set to 3. - * docs/CHANGES: Updated. - -2014-03-06 Werner Lemberg - - Fixes for compilation with C++. - - * src/autofit/hbshim.c (scripts): Change type to `hb_script_t'. - (af_get_coverage): Updated. - (COVERAGE): Add cast. - -2014-03-06 Sean McBride - - Remove more clang analyzer warnings. - - * src/bdf/bdflib.c (_bdf_readstream), src/truetype/ttgload.c - (TT_Load_Glyph): Remove dead stores. - -2014-03-05 Werner Lemberg - - * builds/unix/configure.raw: Simplify. - -2014-03-05 suzuki toshiya - - Fix a bug in configure in library dependency setting - Reported in https://bugs.freedesktop.org/show_bug.cgi?id=75652. - - * builds/unix/configure.raw: Use `x"${xxx}" != xno' style. - -2014-03-04 Werner Lemberg - - Minor fix for `make devel'. - - * builds/freetype.mk (INCLUDE_FLAGS) [DEVEL_DIR]: Don't use - pkg-config for bzip2 since not all GNU/Linux distributions have - `bzip2.pc' (and the header file `bzlib.h' is located in /usr/include - normally). - -2014-03-04 Sean McBride - - Fix several clang static analyzer dead store warnings. - - * src/autofit/afhints.c (af_glyph_hints_reload, - af_glyph_hints_align_weak_points): Remove unnecessary assignments. - - * src/bdf/bdflib.c (bdf_font_load): Ditto. - - * src/pshinter/pshalgo.c (psh_glyph_compute_extrema, - psh_glyph_interpolate_other_points): Ditto. - - * src/type1/t1load.c (T1_Set_MM_Blend): Ditto. - -2014-03-03 Werner Lemberg - - Rewrite library option handling in `configure'. - - o Introduce `auto' value for `--with-XXX' library options; this is - now the default. - - o First use `pkg-config' for library detection, then fall back to - other tests. - - * builds/unix/configure.raw (--with-zlib, --with-bzip2, --with-png, - --with-harfbuzz): Rewrite. - Use new `xxx_reqpriv', `xxx_libpriv', and `xxx_libstaticconf' - variables to collect data for `freetype2.pc' and `freetype-config'. - (FT2_EXTRA_LIBS): Renamed to ... - (ft2_extra_libs): This since it gets no longer substituted. - (REQUIRES_PRIVATE, LIBS_PRIVATE, LIBS_CONFIG, LIBSSTATIC_CONFIG): - New output variables, replacing `XXX_PKG' and `LIBXXX'. - Add notice at the end of `configure' showing the library - configuration. - - * builds/unix/freetype-config.in (--static): New command line - option. - (libs): Updated. - (staticlibs): New variable, to be used if `--static' is given. - * docs/freetype-config.1: Document `--static'. - - * builds/unix/freetype2.in, builds/unix/unix-def.in: Updated. - -2014-03-01 Werner Lemberg - - Avoid `long long' warnings with older gcc compilers. - Problem reported by Hin-Tak Leung . - - * builds/unix/configure.raw: Don't use gcc's `-pedantic' flag for - versions < 4.6. This is especially needed for Max OS X since this - OS runs a gcc variant (or emulation) based on version 4.2.1. - -2014-03-01 Werner Lemberg - - * docs/INSTALL.CROSS: Revised and updated. - -2014-03-01 Werner Lemberg - - Make `make clean' remove `freetype2.pc'. - - This is a generated file at build time, not configure time. - - * builds/unix/unix-def.in (DISTCLEAN): Move `freetype2.pc' to ... - (CLEAN): This variable. - -2014-03-01 Werner Lemberg - - Use pkg-config for detecting libpng and libbz2 also. - - * builds/unix/configure.raw (HAVE_PKG): New variable. - Search for libbz2 using `pkg-config'; s/BZ2/BZIP2/. - Search for libpng using `pkg-config'. - Fix definition of `LIBHARFBUZZ' variable. - * builds/unix/freetype-config.in ($libs): Updated. - * builds/unix/freetype2.in: Add `URL' field. - Update `Requires.private' and `Libs.private'. - * builds/unix/unix-def.in: Updated. - -2014-03-01 Werner Lemberg - - Add configure support for HarfBuzz. - - * builds/unix/pkg.m4: New file. - * builds/unix/configure.raw: Search for libharfbuzz using - `pkg-config'. - Add `--without-harfbuzz' option. - * builds/unix/freetype-config.in, builds/unix/freetype2.in, - builds/unix/unix-def.in (freetype-config, freetype2.pc): Handle - HarfBuzz. - - * docs/INSTALL.UNIX: Document interdependency of FreeType with - HarfBuzz. - -2014-02-28 Alexei Podtelezhnikov - - [cff] Math simplifications. - - * src/cf2blues.c (cf2_blues_init): Use `FT_MulDiv'. - * src/cf2ft.c (cf2_getScaleAndHintFlag): Use simple division. - -2014-02-28 Dave Arnold - - [cff] Fix Savannah bug #41697, part 2. - - * src/cff/cf2ft.c (cf2_initLocalRegionBuffer, - cf2_initGlobalRegionBuffer): It is possible for a charstring to call - a subroutine if no subroutines exist. This is an error but should - not trigger an assert. Split the assert to account for this. - -2014-02-28 Dave Arnold - - [cff] Fix Savannah bug #41697, part 1. - - * src/cff/cf2hints.c (cf2_hintmap_build): Return when `hintMask' is - invalid. In this case, it is not safe to use the length of - `hStemHintArray'; the exception has already been recorded in - `hintMask'. - -2014-02-26 Werner Lemberg - - [sfnt] Fix Savannah bug #41696. - - * src/sfnt/ttcmap.c (tt_cmap0_validate, tt_cmap2_validate, - tt_cmap4_validate, tt_cmap14_validate): Fix limit tests. - -2014-02-26 Werner Lemberg - - [winfnt] Fix Savannah bug #41694. - - * src/winfonts/winfnt.c (FNT_Load_Glyph): Check glyph offset. - -2014-02-26 Werner Lemberg - - [cff] Fix Savannah bug #41693. - - * src/cff/cffload.c (CFF_Load_FD_Select): Reject empty array. - -2014-02-26 Werner Lemberg - - [bdf] Fix Savannah bug #41692. - - bdflib puts data from the input stream into a buffer in chunks of - 1024 bytes. The data itself gets then parsed line by line, simply - increasing the current pointer into the buffer; if the search for - the final newline character exceeds the buffer size, more data gets - read. - - However, in case the current line's end is very near to the buffer - end, and the keyword to compare with is longer than the current - line's length, an out-of-bounds read might happen since `memcmp' - doesn't stop properly at the string end. - - * src/bdf/bdflib.c: s/ft_memcmp/ft_strncmp/ to make comparisons - stop at string ends. - -2014-02-17 suzuki toshiya - - [autofit] Fix `make multi' compilation. - - * src/autofit/hbshim.c: Include `afglobal.h' and `aftypes.h'. - -2014-02-19 Werner Lemberg - Simon Bünzli - - Fix Savannah bug #32902. - - Patch taken from - - https://code.google.com/p/sumatrapdf/source/browse/trunk/ext/_patches/freetype2.patch?spec=svn8620&r=8620#87 - - with slight modifications. - - * src/type1/t1parse.c (T1_Get_Private_Dict): Add heuristic test to - handle fonts that incorrectly use \r at the beginning of an eexec - block. - -2014-02-19 Simon Bünzli - - Fix Savannah bug #41590. - - * src/type1/t1load.c (parse_encoding): Protect against invalid - number. - -2014-02-12 Dave Arnold - - [cff] Optimize by using `FT_MulDiv'. - Suggested by Alexei. - - * src/cff/cf2font.c (cf2_computeDarkening): Do it. - -2014-02-12 Werner Lemberg - - Fix Savannah bug #41465. - - * builds/unix/unix-def.in (CLEAN): Add `freetype-config'. - (DISTCLEAN): Remove `freetype-config'. - -2014-02-08 Sean McBride - - Fix clang static analyzer and compiler warnings. - - * src/autofit/afhints.c (af_glyph_hints_align_weak_points), - src/autofit/afloader (af_loader_load_g) , - src/base/ftcalc.c (FT_MSB), src/base/ftoutln.c - (FT_Outline_Decompose), src/bdf/bdfdrivr.c (bdf_interpret_style), - src/cff/cffparse.c (cff_parse_integer), src/cid/cidparse.c - (cid_parser_new), src/pfr/pfrload.c (pfr_phy_font_load), - src/raster/ftraster.c (Decompose_Curve), src/sfnt/sfdriver.c - (sfnt_get_ps_name), src/sfnt/ttcmap.c (tt_cmap12_next, - tt_cmap13_next), src/smooth/ftgrays.c (gray_hline): Remove dead - code. - - * src/autofit/afmodule.c (af_property_get_face_globals, - af_property_set, af_property_get), src/base/ftbitmap.c - (ft_gray_for_premultiplied_srgb_bgra): Make functions static. - - * src/base/ftobjs.c (ft_remove_renderer): Protect against - library == NULL. - (ft_property_do): Make function static. - - * src/base/ftrfork.c: Include `ftbase.h'. - - * src/sfnt/ttsbit.c (tt_face_load_sbix_image) - [!FT_CONFIG_OPTION_USE_PNG], src/type1/t1gload.c - (T1_Compute_Max_Advance): Avoid compiler warning. - - * src/truetype/ttinterp.c (TT_New_Context): Reduce scope of - variable. - -2014-02-08 Werner Lemberg - - Fix Windows build directories. - - The build target is now `windows' instead of `win32'. - - Problem reported by Nickolas George . - - * builds/modules.mk: Don't use `win32' and `win16' (!) but - `windows'. - - * builds/windows/detect.mk, builds/windows/win32-def.mk: - s/win32/windows/. - -2014-02-08 Eugen Sawin - - Fix Savannah bug #41507. - - * src/sfnt/ttsbit.c (tt_sbit_decoder_load_bitmap) - [!FT_CONFIG_OPTION_USE_PNG] <17, 17, 19>: Fix error handling. - -2014-02-08 Dave Arnold - - [cff] Fix minor performance bug. - - * src/cff/cf2font.c (cf2_font_setup): Darkening amount and blue zone - calculations are now cached and not recomputed on each glyph. - -2014-02-05 Werner Lemberg - - Fix problems with perl 5.8.8 as distributed with current MinGW. - - * src/tools/afblue.pl: Work-around for Perl bug #63402. - (string_re): Avoid `possessive quantifiers', which have been - introduced in Perl version 5.10. - -2014-02-04 Werner Lemberg - - Fix compilation with MinGW. - - Right now, compilation out of the box with latest MinGW is broken - due to bugs in header files of mingwrt 4.0.3 in strict ANSI mode, - cf. - - https://sourceforge.net/p/mingw/bugs/2024/ - https://sourceforge.net/p/mingw/bugs/2046/ - - * builds/unix/configure.raw: Don't set `-ansi' flag for MinGW. - -2014-02-04 Werner Lemberg - - [autofit] Minor fix. - - * src/autofit/afcjk.c (af_cjk_metrics_init_widths), - src/autofit/aflatin.c (af_latin_metrics_init_widths): Fix handling - of alternative standard characters. - This also fixes a compilation warning in non-debug mode. - -2014-02-03 Werner Lemberg - - [cff] Fix Savannah bug #41363. - - * src/cff/cf2ft.c (cf2_checkTransform): Convert assertion into - parameter check. - (cf2_decoder_parse_charstrings): Call `cf2_checkTransform' only if - we are scaling the outline. - (cf2_getPpemY): Remove problematic assertion. - -2014-01-26 Werner Lemberg - - [autofit] Introduce two more slots for standard characters. - - This is useful for OpenType features like `c2sc' (caps to small - caps) that don't have lowercase letters by definition, or other - features that mainly operate on numerals. - - * src/autofit/afscript.h: Add more standard characters. - - * src/autofit/aftypes.h: Update use of `SCRIPT' macro. - (AF_ScriptClassRec): Add members to hold two more standard - characters. - (AF_DEFINE_SCRIPT_CLASS): Updated. - - * src/autofit/afglobal.c, src/autofit/afglobal.h, - * src/autofit/afpic.c, src/autofit/afranges.h, src/autofit/hbshim.c: - Update use of `SCRIPT' macro. - - * src/autofit/afcjk.c (af_cjk_metrics_init_widths), - src/autofit/aflatin.c (af_latin_metrics_init_widths): Scan two more - standard characters. - -2014-01-24 Werner Lemberg - - Fix Savannah bug #41320. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues) - : Avoid negative index of `last'. - -2014-01-23 Werner Lemberg - - Fix Savannah bug #41310. - - * src/sfnt/ttsbit.c (tt_sbit_decoder_load_bitmap) : - Don't check metrics, which this format doesn't have. - This is another correction to the commit from 2013-11-21. - -2014-01-23 Werner Lemberg - - Fix Savannah bug #41309. - - * src/type1/t1load.c (t1_parse_font_matrix): Properly handle result - of `T1_ToFixedArray'. - - * src/cid/cidload.c (cid_parse_font_matrix): Synchronize with - `t1_parse_font_matrix'. - - * src/type42/t42parse.c (t42_parse_font_matrix): Synchronize with - `t1_parse_font_matrix'. - (t42_parse_encoding): Synchronize with `t1_parse_encoding'. - - * src/psaux/psobjs.c (ps_parser_load_field) , - : Properly handle result of `ps_tofixedarray'. - -2014-01-22 Werner Lemberg - - * src/autofit/hbshim.c (af_get_coverage): Fix memory leaks. - -2014-01-16 Werner Lemberg - - [autofit] Improve tracing of style coverages. - - * include/internal/fttrace.h: Add `afglobal' for tracing style - coverages. - - * src/autofit/afglobal.c: Include FT_INTERNAL_DEBUG_H. - (FT_COMPONENT): Define. - (af_face_globals_compute_style_coverage): Trace `gstyles' array - data. - -2014-01-09 Werner Lemberg - - Fix Savannah bug #41158. - - * builds/unix/install.mk (install): Create man page directory. - -2014-01-08 Chongyu Zhu - - [arm] Fix Savannah bug #41138, part 2. - - * builds/unix/ftconfig.in (FT_MulFix_arm), include/config/ftconfig.h - (FT_MulFix_arm), src/truetype/ttinterp.c (TT_MulFix14_arm): Fix - preprocessor conditionals for `add.w'. - -2014-01-08 Werner Lemberg - - [autofit] Fix Savannah bug #41138, part 1. - - * src/tools/afblue.pl : Produce correct auxiliary - enumeration names for generated `#else'. - - * src/autofit/afblue.h: Regenerated. - -2014-01-06 Werner Lemberg - - Add manual page for `freetype-config'. - Contributed by Nis Martensen . - - * docs/freetype-config.1: New file. - - * builds/unix/unix-def.in (mandir): Define. - * builds/unix/install.mk (install, uninstall): Handle manpage. - -2014-01-05 Werner Lemberg - - [autofit] Minor fixes for `afblue.pl'. - - * src/tools/afblue.pl (aux_name): Don't use `reverse'. - : Use proper indentation for generated `#else'. - - * src/autofit/afblue.h: Regenerated. - -2014-01-04 Werner Lemberg - - [autofit] Fix Indic scripts. - - Split the single, incorrect Indic entry into separate scripts so - that the covered ranges are the same: Bengali, Devanagari, Gujarati, - Gurmukhi, Kannada, Limbu, Malayalam, Oriya, Sinhala, Sundanese, - Syloti Nagri, Tamil, Telugu, and Tibetan. At the same time, remove - entries for Meetei Mayek and Sharada – the Unicode ranges were - incorrect (and nobody has complained about that), fonts are scarce - for those scripts, and the Indic auto-hinter support is rudimentary - anyways. - - * src/autofit/afscript.h: Updated, using AF_CONFIG_OPTION_INDIC and - AF_CONFIG_OPTION_CJK. - - * src/autofit/afstyles.h (STYLE_DEFAULT_INDIC): New auxiliary macro. - Use it, together with AF_CONFIG_OPTION_INDIC and - AF_CONFIG_OPTION_CJK, to update. - - * src/autofit/afranges.c [AF_CONFIG_OPTION_INDIC]: Updated. - [!AF_CONFIG_OPTION_INDIC, !AF_CONFIG_OPTION_CJK]: Removed. - Sort entries by tags. - -2014-01-03 Werner Lemberg - - [autofit] Thinko. - - * src/autofit/hbshim.c (af_get_char_index): Similar to - `af_get_coverage', reject glyphs which are not substituted. - -2014-01-03 Werner Lemberg - - [autofit] Fix handling of default coverages. - - With this commit, the implementation of coverage handling is - completed. - - * src/autofit/hbshim.c (af_get_coverage): Exit early if nothing to - do. - Reject coverages which don't contain appropriate glyphs for blue - zones. - -2014-01-03 Werner Lemberg - - [autofit] Fix handling of default coverages. - - * src/autofit/afglobal.c (af_face_globals_compute_style_coverage): - First handle non-default coverages, then the default coverage of the - default script, and finally the other default coverages. - -2014-01-03 Werner Lemberg - - [autofit] Fix scaling of HarfBuzz shaping. - - * src/autofit/hbshim.c (af_get_char_index): Scale to units per EM. - -2014-01-03 Werner Lemberg - - [autofit] Better ftgrid support. - - * src/autofit/afhints.c (af_glyph_hints_get_segment_offset): Add - parameters `is_blue' and `blue_offset'. - -2014-01-01 Werner Lemberg - - [autofit] Remove some styles. - - * src/autofit/afcover.h: Remove coverages for alternative fractions, - denominators, numerators, and fractions. - - * src/autofit/afstyles.h (META_STYLE_LATIN): Updated. - -2014-01-01 Werner Lemberg - - [autofit] Add more styles. - - * src/autofit/afstyles.h (STYLE_LATIN, META_STYLE_LATIN): New - auxiliary macros; use them to define styles for Cyrillic, Greek, and - Latin. - - * src/autofit/afcover.h: Remove coverage for oldstyle figures. - Since those digits are used in combination with ordinary letters, it - makes no sense to handle them separately. - - * src/autofit/afglobal.c (af_face_globals_get_metrics): Don't limit - `options' parameter to 4 bits. - -2014-01-01 Werner Lemberg - - [autofit] Fix style assignments to glyphs. - - * src/autofit/hbshim.c (af_get_coverage) - [FT_CONFIG_OPTION_USE_HARFBUZZ]: Scan GPOS coverage of features also - so that we can skip glyphs that have both GSUB and GPOS data. - -2014-01-01 Werner Lemberg - - * src/autofit/hbshim.c: s/{lookups,glyphs}/gsub_{lookups,glyphs}/. - -2014-01-01 Werner Lemberg - - [autofit] Implement and use `af_get_char_index' with HarfBuzz. - - * src/autofit/hbshim.c (COVERAGE) [FT_CONFIG_OPTION_USE_HARFBUZZ]: - Redefine to construct HarfBuzz features. - (af_get_char_index) [FT_CONFIG_OPTION_USE_HARFBUZZ]: Rewritten. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Use - `y_offset' to adjust `best_y'. - -2013-12-31 Werner Lemberg - - [autofit] s/AF_STYLE_...._DEFAULT/AF_STYLE_...._DFLT/i. - -2013-12-31 Werner Lemberg - - [autofit] Fix interface of `af_get_char_index'. - - * src/autofit/hbshim.c (af_get_char_index): Return error value. - Add argument for y offset (to be used in a yet-to-come patch). - - * src/autofit/hbshim.h, src/autofit/afcjk.c, - src/autofit/aflatin.c: Updated. - -2013-12-30 Werner Lemberg - - [autofit] Don't combine multiple features into one set. - - Combining them, as originally envisioned, would lead to much more - complicated code, as investigations have shown meanwhile. The major - drawback is that we run out of available style slots much earlier. - However, this is only a theoretical issue since we don't support a - large number of scripts currently. - - * src/autofit/afcover.h: Replace `COVERAGE_{1,2,3}' macros with - a single-element `COVERAGE' macro, sort the elements by the feature - tags, and add entry for `ruby'. - - * src/autofit/aftypes.h: Updated. - * src/autofit/hbshim.c: Updated. - -2013-12-28 Werner Lemberg - - [autofit] Code shuffling to reduce use of cpp macros. - - * src/autofit/afglobal.c (af_face_globals_compute_style_coverage): - Call `af_get_coverage' unconditionally. - - * src/autofit/autofit.c: Include `hbshim.c' unconditionally. - - * src/autofit/hbshim.c (af_get_coverage) - [!FT_CONFIG_OPTION_USE_HARFBUZZ]: Provide dummy function. - - * src/autofit/hbshim.h: Provide function declarations - unconditionally. - -2013-12-28 Werner Lemberg - - [autofit] Add wrapper function for `FT_Get_Char_Index'. - - Yet-to-come changes will provide HarfBuzz functionality for the new - function. - - * src/autofit/hbshim.c (af_get_char_index): New function. - * src/autofit/hbshim.h: Updated. - - * src/autofit/afcjk.c (af_cjk_metrics_init_widths, - af_cjk_metrics_init_blues, af_cjk_metrics_check_digits): Updated. - - * src/autofit/aflatin.c (af_latin_metrics_init_widths, - af_latin_metrics_init_blues, af_latin_metrics_check_digits): - Updated. - -2013-12-28 Werner Lemberg - - [autofit] Use `global' HarfBuzz font object. - - We now use `hb_font' instead of `hb_face' since yet-to-come changes - need this. - - * src/autofit/afglobal.h: Include `hbshim.h'. - (AF_FaceGlobalsRec) [FT_CONFIG_OPTION_USE_HARFBUZZ]: New member - `hb_font'. - - * src/autofit/afglobal.c (af_face_globals_new) - [FT_CONFIG_OPTION_USE_HARFBUZZ]: Create `hb_font'. - (af_face_globals_free) [FT_CONFIG_OPTION_USE_HARFBUZZ]: Destroy - `hb_font'. - - * src/autofit/hbshim.h: Include HarfBuzz headers. - - * src/autofit/hbshim.c: Include `hbshim.h' instead of HarfBuzz - headers. - (af_get_coverage): Updated. - -2013-12-27 Werner Lemberg - - [autofit] Handle `DFLT' OpenType script for coverages. - - * include/ftautoh.h: Document new `default-script' property. - - * src/autofit/hbshim.c (af_get_coverage): Use `AF_FaceGlobals' for - type of first parameter. - (script_tags): Add one more element. - (af_get_coverage): Adjust `script_tags' to handle `DFLT' script tag. - - * src/autofit/hbshim.h: Updated. - - * src/autofit/afglobal.c (af_face_globals_compute_style_coverage): - Updated. - - * src/autofit/afglobal.h (AF_SCRIPT_DEFAULT): New macro. - - * src/autofit/afmodule.h (AF_ModuleRec): New `default_script' - member. - - * src/autofit/afmodule.c (af_property_set, af_property_get): Handle - `default-script' property. - (af_autofitter_init): Updated. - -2013-12-27 suzuki toshiya - - [ftrfork] Fix the face order difference between POSIX and Carbon. - - The fragmented resources in Suitcase and .dfont should be reordered - when `POST' resource for Type1 is being restored, but reordering of - sfnt resources induces the different face order. Now the ordering - is restricted to `POST' resource only, to prevent the different - order issue (e.g. the face index in the fontconfig cache generated - with Carbon framework is incompatible with that by FreeType 2 - without Carbon framework.) Found by Khaled Hosny and Hin-Tak Leung. - - https://lists.gnu.org/archive/html/freetype-devel/2013-02/msg00035.html - https://lists.gnu.org/archive/html/freetype-devel/2013-12/msg00027.html - - * src/base/ftrfork.c (FT_Raccess_Get_DataOffsets): Add a switch - `sort_by_res_id' to control the fragmented resource ordering. - * include/internal/ftrfork.h: Declare new switch. - * src/base/ftobjs.c (IsMacResource): Enable the sorting for `POST' - resource, and disable the sorting for `sfnt' resource. - -2013-12-25 Werner Lemberg - - Fix Savannah bug #40997. - - * src/bdf/bdfdrivr.c (BDF_Face_Init): Only use OR operator to - adjust face flags since FT_FACE_FLAG_EXTERNAL_STREAM might already - be set. - * src/cff/cffobjs.c (cff_face_init): Ditto. - * src/cid/cidobjs.c (cid_face_init): Ditto. - * src/pcf/pcfread.c (pcf_load_font): Ditto. - * src/pfr/pfrobjs.c (pfr_face_init): Ditto. - * src/type1/t1objs.c (T1_Face_Init): Ditto. - * src/type42/t42objs.c (T42_Face_Init): Ditto. - * src/winfonts/winfnt.c (FNT_Face_Init): Ditto. - -2013-12-21 Werner Lemberg - - [autofit] Introduce `coverages'. - - Coverages are the interface to the HarfBuzz library to access - OpenType features for handling glyphs not addressable by the cmap. - - Right now, compilation of HarfBuzz is only added to the development - build. A solution for standard build mode will be delayed until - HarfBuzz gets split into two libraries to avoid mutual dependencies - between FreeType and HarfBuzz. - - Note that this is only a first step in handling coverages, basically - providing the framework only. Code for handling selected OpenType - features (this is, actually using the data in `afcover.h') will - follow. - - * devel/ftoption.h, include/config/ftoption.h - (FT_CONFIG_OPTION_USE_HARFBUZZ): New macro. - - * src/autofit/hbshim.c, src/autofit/hbshim.h, src/autofit/afcover.h: - New files. - - * src/autofit/afscript.h: Add HarfBuzz script name tags. - - * src/autofit/afstyles.h: Add default coverage enumeration values. - - * src/autofit/aftypes.h: Update use of `SCRIPT' and `STYLE' macros. - (AF_Coverage): New enumeration (generated by `afcover.h'). - (AF_StyleClassRec): New member `coverage'. - (AF_DEFINE_STYLE_CLASS): Updated. - - * include/internal/fttrace.h: Add `afharfbuzz' for tracing coverage - data. - - * src/autofit/afglobal.h: Update use of `SCRIPT' and `STYLE' macros. - (AF_SCRIPT_FALLBACK): Renamed to ... - (AF_STYLE_FALLBACK): ... this. - - * src/autofit/afglobal.c: Include `hbshim.c'. - Update use of `SCRIPT' and `STYLE' macros. - (af_face_globals_compute_style_coverage) - [FT_CONFIG_OPTION_USE_HARFBUZZ]: Call `af_get_coverage'. - Update. - - * src/autofit/afmodule.h (AF_ModuleRec): - s/fallback_script/fallback_style/. - - * src/autofit/afmodule.c (af_property_set): Adapt handling of - `fallback-script' property to set a fallback style. - (af_property_get, af_autofitter_init): Updated. - - * src/autofit/afpic.c: Update use of `SCRIPT' and `STYLE' macros. - - * src/autofit/afranges.h: Update use of `SCRIPT' macro. - - * src/autofit/autofit.c [FT_CONFIG_OPTION_USE_HARFBUZZ]: Include - `hbshim.c'. - - * src/autofit/rules.mk (AUTOF_DRV_SRC): Add `hbshim.c'. - (AUTOF_DRV_H): Add `afcover.h'. - - * builds/freetype.mk (INCLUDE_FLAGS) [DEVEL_DIR]: Use pkg-config for - all libraries needed by FreeType. - -2013-12-21 Werner Lemberg - - Fix Savannah bug #40975 (sort of). - - * src/truetype/ttinterp.c (Ins_IP): Fix sign typo to make FreeType - behave the same as the Windows TrueType engine for the invalid case. - -2013-12-21 Werner Lemberg - - [autofit] Make PIC mode work actually. - - * src/autofit/afpic.h (AFModulePIC): Fix array sizes to fit the - enumeration values automatically generated by including `afscript.h' - and friends. - - * src/autofit/afpic.c (autofit_module_class_pic_init): Updated. - -2013-12-21 Werner Lemberg - - Fix PIC linking. - - * include/internal/ftrfork.h (CONST_FT_RFORK_RULE_ARRAY_BEGIN): Fix - generated function name. - - * src/base/basepic.c (FT_Init_Table_raccess_guess_table): Rename - to ... - (FT_Init_Table_ft_raccess_guess_table): ... this so that the - function name correctly corresponds to what the macro framework - expects. - - * src/psnames/rules.mk (PSNAMES_DRV_SRC_S): Use correct file name so - that PIC functions are compiled also. - -2013-12-21 Werner Lemberg - - [base] Add missing dependencies to Makefile. - - * src/base/rules.mk (BASE_SRC): Add `basepic.c' and `ftpic.c'. - (BASE_H): Add `basepic.h'. - -2013-12-20 Werner Lemberg - - [autofit] Fix PIC compilation. - - * src/autofit/afcjk.c (af_cjk_metrics_init_widths), - src/autofit/aflatin.c (af_latin_metrics_init_widths) - [FT_CONFIG_OPTION_PIC]: Declare `globals'. - - * src/autofit/afglobal.c: Always call AF_DEFINE_SCRIPT_CLASS, and - AF_DEFINE_STYLE_CLASS. - - * src/autofit/afpic.c: Include `afglobal.h'. - (autofit_module_class_pic_init): Typo. - - * src/autofit/aftypes.h (AF_DEFINE_SCRIPT_CLASS, - AF_DEFINE_STYLE_CLASS): Don't use the same identifier for macro - parameter and structure member. - -2013-12-20 Werner Lemberg - - [autofit] Introduce `styles'. - - This is the new top-level structure for handling glyph input data; - scripts are now defined separately. - - * src/autofit/aftypes.h (SCRIPT): Updated. - (AF_ScriptClassRec): Move `blue_stringset' and `writing_system' - members to ... - (AF_Style_ClassRec): ... this new structure. - (AF_Style): New enumeration. - (AF_StyleMetricsRec): Replace `script' enumeration with - `style_class' pointer. - (AF_DEFINE_SCRIPT_CLASS, AF_DECLARE_SCRIPT_CLASS): Updated. - (AF_DEFINE_STYLE_CLASS, AF_DECLARE_STYLE_CLASS): New macros. - - * src/autofit/afstyles.h: New file, using data from `afscript.h'. - * src/autofit/afscript.h: Updated. - - * src/autofit/afcjk.c (af_cjk_metrics_init_widths, - af_cjk_metrics_init_blues, af_cjk_hint_edges): Updated. - - * src/autofit/afglobal.c (SCRIPT): Updated. - (STYLE): Redefine macro to load `afstyles.h'. - (af_script_names) [FT_DEBUG_LEVEL_TRACE]: Replace with... - (af_style_names): ... this array. - (af_face_globals_compute_script_coverage): Renamed to... - (af_face_globals_compute_style_coverage): ... this. - Updated. - (af_face_globals_new, af_face_globals_free, - af_face_globals_get_metrics): Updated. - - * src/autofit/afglobal.h (SCRIPT): Updated. - (STYLE): Redefine macro to load `afstyles.h'. - (AF_SCRIPT_FALLBACK): Update definition. This will get more - refinements with later on. - (AF_SCRIPT_UNASSIGNED): Replace with... - (AF_STYLE_UNASSIGNED): ... this macro. - (AF_FaceGlobalsRec): Updated. - - * src/autofit/aflatin.c (af_latin_metrics_init_widths, - af_latin_metrics_init_blues, af_latin_metrics_scale_dim, - af_latin_hint_edges): Updated. - - * src/autofit/aflatin2.c (af_latin2_metrics_init_widths): Updated. - (af_ltn2_uniranges): Removed. - - * src/autofit/afloader.c (af_loader_load_g, af_loader_load_glyph): - Updated. - - * src/autofit/afpic.c (autofit_module_class_pic_init): Updated. - * src/autofit/afpic.h (AF_STYLE_CLASSES_GET): New macro. - (AFModulePIC): Add `af_style_classes' and `af_style_classes_rec' - members. - - * src/autofit/afranges.h: Updated. - - * src/autofit/rules.mk (AUTOF_DRV_H): Add `afstyles.h'. - -2013-12-19 Werner Lemberg - - [autofit] Factor scripts and uniranges out of writing system files. - - * src/autofit/afranges.c, src/autofit/afranges.h: New files. - - * src/autofit/afscript.h: Extend `SCRIPT' macro with more - parameters, taking data from the writing system files. - - * src/autofit/aftypes.h: Updated. - - * src/autofit/afglobal.c: Include `afranges.h'. - Load `afscript.h' to call AF_DEFINE_SCRIPT_CLASS. - * src/autofit/afglobal.c: Include `afranges.h'. - Load `afscript.h' to call AF_DECLARE_SCRIPT_CLASS. - - * src/autofit/afcjk.c, src/autofit/afcjk.h: Updated. - * src/autofit/afdummy.c, src/autofit/afdummy.h: Updated. - * src/autofit/afindic.c, src/autofit/afindic.h: Updated. - * src/autofit/aflatin.c, src/autofit/aflatin.h: Updated. - * src/autofit/aflatin2.c, src/autofit/aflatin2.h: Updated. - - * src/autofit/afpic.c: Updated. - - * src/autofit/autofit.c: Include `afranges.c'. - * src/autofit/rules.mk (AUTOF_DRV_SRC): Add `afranges.c'. - -2013-12-18 Werner Lemberg - - [autofit] More code orthogonality. - - * src/autofit/aftypes.h (AF_StyleMetrics): Replace `script_class' - pointer to an `AF_ScriptClass' structure with `script' index of type - `AF_Script'. - Move some code around. - - * src/autofit/afcjk.c: Include `afpic.h'. - (af_cjk_metrics_init_widths, af_cjk_metrics_init_blues, - af_cjk_hint_edges): Updated. - - * src/autofit/aflatin.c: Include `afpic.h'. - (af_latin_metrics_init_widths, af_latin_metrics_init_blues, - af_latin_metrics_scale_dim, af_latin_hint_edges): Updated. - - * src/autofit/afglobal.c (af_face_globals_get_metrics): Updated. - - * src/autofit/afloader.c (af_loader_load_g, af_loader_load_glyph): - Updated. - -2013-12-18 Werner Lemberg - - [autofit] s/ScriptMetrics/StyleMetrics/. - -2013-12-18 Werner Lemberg - - [autofit] s/script_{metrics,hints}/style_{metrics,hints}/ - -2013-12-18 Werner Lemberg - - [autofit] s/gscripts/gstyles/. - -2013-12-18 Werner Lemberg - - [autofit] s/glyph_scripts/glyph_styles/. - - This is the first commit of a series to create a new top-level - structure (a `style') for handling scripts, writing_systems, and - soon-to-be-added coverages. - -2013-12-17 Werner Lemberg - - [autofit] s/AF_Script_/AF_WritingSystem_/ where appropriate. - -2013-12-11 Infinality - - [truetype] Simplify logic of rendering modes. - - This patch unifies the subpixel and non-subpixel cases. - - * src/truetype/ttinterp.h (TT_ExecContextRec): Remove - `grayscale_hinting'; all code should refer to `grayscale' instead. - Remove unused `native_hinting' member. - Rename `subpixel_hinting' member to `subpixel. - - * src/truetype/ttgload.c (TT_LOADER_SET_PP): Updated. - (tt_loader_init): Updated. - - * src/truetype/ttinterp.c (Ins_GETINFO): Simplify. - Updated. - -2013-12-11 Werner Lemberg - - [documentation] Add section how to include FreeType header files. - Problem reported by David Kastrup . - - Surprisingly, a description how to do that was completely missing in - the API reference. - - * include/freetype.h, include/ftchapters.h: New documentation - section `header_inclusion'. - -2013-12-10 Werner Lemberg - - [autofit] s/DFLT/NONE/, s/dflt/none/. - -2013-12-10 Werner Lemberg - - [autofit] s/AF_SCRIPT_NONE/AF_SCRIPT_UNASSIGNED/. - -2013-12-10 Werner Lemberg - - [truetype] Fix scaling of vertical phantom points. - - * src/truetype/ttgload.c (load_truetype_glyph): Scale pp3.x and - pp4.x also. - -2013-12-10 Werner Lemberg - - [truetype] Fix positioning of composite glyphs. - Problem reported by Nigel Tao . - - * src/truetype/ttgload.c (TT_Hint_Glyph): Remove code that shifts - the glyph (component) by a fractional value computed from the LSB - phantom point. This is wrong, since the horizontal phantom points - get rounded horizontally later on. - -2013-12-08 Werner Lemberg - - * Version 2.5.2 released. - ========================= - - - Tag sources with `VER-2-5-2'. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.5.2. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.5.1/2.5.2/, s/251/252/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 2. - - * builds/unix/configure.raw (version_info): Set to 17:1:11. - * CMakeLists.txt (VERSION_PATCH): Set to 2. - * docs/CHANGES: Updated. - -2013-12-07 Werner Lemberg - - [truetype] Next round in phantom point handling. - - Greg Hitchcock provided very interesting insights into the - complicated history of the horizontal positions of the TSB and BSB - phantom points. - - * src/truetype/ttgload.c (TT_LOADER_SET_PP) - [TT_CONFIG_OPTION_SUBPIXEL_HINTING]: Use `subpixel_hinting' and - `grayscale_hinting' flags as conditionals for the x position of TSB - and BSB. - -2013-12-05 Werner Lemberg - - * builds/freetype.mk (FT_CC): Removed. Unused. - -2013-12-04 Werner Lemberg - - [sfnt] Fix handling of embedded bitmap strikes. - - This corrects the commit from 2013-11-21. Problem reported by - Andrey Panov . - - * src/sfnt/ttsbit.c (tt_sbit_decoder_load_bitmap): Fix logic to - detect excessive bytes for bit-aligned bitmaps. - -2013-12-03 Werner Lemberg - - [truetype] Remove dead code. - - Reported by Nigel Tao . - - * include/internal/tttypes.h (TT_LoaderRec): Remove unused - `preserve_pps' field. - * src/truetype/ttgload.c (TT_Hint_Glyph): Updated. - -2013-12-03 Werner Lemberg - - [truetype] Fix phantom point handling. - - This is a further improvement to the changes from 2013-11-06. - - * src/truetype/ttgload.c (TT_Hint_Glyph): Horizontal phantom points - are rounded horizontally, vertical ones are rounded vertically. - (TT_LOADER_SET_PP): The horizontal position of vertical phantom - points in pre-ClearType mode is zero, as shown in the OpenType - specification. - -2013-12-02 Werner Lemberg - - [truetype] Fix change from 2013-11-20. - - Problem reported by Akira Kakuto . - - * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Protect call to - `Update_Max' with both a TT_USE_BYTECODE_INTERPRETER guard and a - `IS_HINTED' clause. - Also remove redundant check using `maxSizeOfInstructions' – in - simple glyphs, the bytecode data comes before the outline data, and - a validity test for this is already present. - -2013-11-27 Werner Lemberg - - [autofit] Fix use of dumping functions in `ftgrid' demo program. - - * src/autofit/afhints.c (AF_DUMP) [FT_DEBUG_AUTOFIT]: New macro. - (af_glyph_hints_dump_points, af_glyph_hints_dump_segments, - af_glyph_hints_dump_edges) [FT_DEBUG_AUTOFIT]: Add parameter to - handle output to stdout. - Use AF_DUMP. - (af_glyph_hints_dump_points, af_glyph_hints_dump_segments, - af_glyph_hints_dump_edges) [!FT_DEBUG_AUTOFIT]: Removed. - -2013-11-25 Werner Lemberg - - * Version 2.5.1 released. - ========================= - - - Tag sources with `VER-2-5-1'. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.5.1. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.5.0/2.5.1/, s/250/251/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 1. - - * builds/unix/configure.raw (version_info): Set to 17:0:11. - * CMakeLists.txt (VERSION_PATCH): Set to 1. - * docs/CHANGES, docs/release: Updated. - -2013-11-23 Werner Lemberg - - [truetype]: Add tricky font names `hkscsiic.ttf' and `iicore.ttf'. - - * src/truetype/ttobjs.c (TRICK_NAMES_MAX_CHARACTERS, - TRICK_NAMES_COUNT): Updated. - (trick_names): Add family name for the two fonts. - -2013-11-23 Werner Lemberg - - * src/sfnt/ttsbit.c (tt_sbit_decoder_load_bitmap): Typo. - -2013-11-21 Werner Lemberg - - [sfnt] Typo. - - Problem reported by Hin-Tak Leung . - - * src/sfnt/sfobjs.c (sfnt_load_face): Return correct `bsize->width' - value if the font lacks an `OS/2' table. - -2013-11-21 Werner Lemberg - - [sfnt] Improve handling of buggy embedded bitmap strikes. - - We are now able to successfully load `AppleMyoungJo.ttf'. - Problem reported by Hin-Tak Leung . - - * src/sfnt/ttsbit.c (tt_sbit_decoder_load_bitmap): Don't trust glyph - format. - -2013-11-20 Werner Lemberg - - [truetype] Don't trust `maxp's `maxSizeOfInstructions'. - - Problem reported by Hin-Tak Leung ; see - - https://lists.nongnu.org/archive/html/freetype-devel/2013-08/msg00005.html - - for details. - - * src/base/ftobjs.c (FT_Load_Glyph): Check size of `fpgm' and `prep' - tables also for setting `autohint'. - - * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Use code from - `TT_Process_Composite_Glyph' for handling unreliable values of - `maxSizeOfInstructions'. - -2013-11-16 Werner Lemberg - - [sfnt] Fix `OS/2' table version 5 support. - - We now follow the `official' announcement from Microsoft (on the - OpenType mailing list, which unfortunately hasn't a public archive). - - * include/freetype/tttables.h (TT_OS2): - s/usLowerPointSize/usLowerOpticalPointSize/, - s/usUpperPointSize/usUpperOpticalPointSize/. - - * src/sfnt/ttload.c (tt_face_load_os2): Update, and set correct - default values. - -2013-11-13 Werner Lemberg - - * builds/unix/ft2unix.h: Remove. No longer necessary. - - * builds/unix/install.mk (install): Updated. - -2013-11-13 Werner Lemberg - - Simplify header file hierarchy. - - This large patch changes the header file directory layout from - `include/freetype/...' to `include/...', effectively removing one - level. Since the file `ft2build.h' is also located in `include' - (and it stays there even after installation), all FreeType header - files are now in a single directory. - - Applications that use (a) `freetype-config' or FreeType's - `pkg-config' file to get the include directory for the compiler, and - (b) the documented way for header inclusion like - - #include - #include FT_FREETYPE_H - ... - - don't need any change to the source code. - - * include/freetype/*: Move up to... - * include/*: ... this directory. - - * builds/amiga/include/freetype/*: Move up to... - * builds/amiga/include/*: ... this directory. - - */*: Essentially do `s@/freetype/@/@' where appropriate. - - * CMakeLists.txt: Simplify. - * builds/unix/freetype-config.in, builds/unix/freetype2.in: For - `--cflags', return a single directory. - * builds/unix/install.mk (install): No longer try to remove `cache' - and `internal' subdirectories; instead, remove the `freetype' - subdirectory. - -2013-11-12 Werner Lemberg - - [truetype] Fix last `truetype' commit. - - * src/truetype/ttgload.c (tt_get_metrics): Preserve stream position. - Return error value. - (load_truetype_glyph): Updated. - -2013-11-10 Werner Lemberg - - * docs/CMAKE: New dummy file. - -2013-11-08 Dave Arnold - - [cff] Fix for hints that touch. - - * src/cff/cf2hints.c (cf2_hintmap_insertHint): Fix condition for - finding index value of insertion point. - -2013-11-06 Werner Lemberg - - [truetype] Fix handling of phantom points in composite glyphs. - Problem reported by Nigel Tao . - - This is a follow-up commit to the previous one. - - * src/truetype/ttgload.c (load_truetype_glyph): Call - `tt_get_metrics' after loading the glyph header. - -2013-11-06 Werner Lemberg - - [truetype] Improve emulation of vertical metrics. - - This commit also improves the start values of vertical phantom - points. Kudos to Greg Hitchcock for help. - - * src/truetype/ttgload.c (TT_Get_VMetrics): Add parameter to pass - `yMax' value. Replace code with fixed Microsoft definition. - (tt_get_metrics): Updated. - (TT_LOADER_SET_PP): Add explanation how to initialize phantom - points, taken from both the OpenType specification and private - communication with Greg (which will eventually be added to the - standard). - Fix horizontal position of `pp3' and `pp4'. - - * src/truetype/ttgload.h: Updated. - - * src/truetype/ttdriver.c (tt_get_advances): Updated. - - * docs/CHANGES: Updated. - -2013-11-05 Werner Lemberg - - * builds/windows/vc2010/freetype.vcxproj: s/v110/v100/. - PlatformToolSet version 110 is for VC2012. - - Problem reported (with solution) by Dave Arnold . - -2013-11-05 Werner Lemberg - - [truetype] Correctly reset point tags for glyph components. - Problem reported by Nigel Tao . - - * src/truetype/ttgload.c (TT_Process_Composite_Glyph): Fix loop. - -2013-11-02 Werner Lemberg - - [truetype] Fix GETINFO opcode handling of subpixel hinting bits. - - * src/truetype/ttinterp.c (Ins_GETINFO): Don't request bit 6 set to - get info on subpixel hinting. - - * docs/CHANGES: Updated. - -2013-11-02 Werner Lemberg - - Fix Savannah bug #40451. - - Simply apply the patch from the bug report. - - * builds/unix/ftconfig.in, builds/vms/ftconfig.h, - include/freetype/config/ftconfig.h: The used #pragma directives only - work with gcc versions 4.6 and higher. - -2013-11-01 Werner Lemberg - - * docs/CHANGES: Updated. - -2013-11-01 Werner Lemberg - - [truetype] Minor code refactoring. - - Two benefits: The allocated FDEF (and IDEF) array gets slightly - smaller, and the `ttdebug' demo program has access to function - numbers without additional costs. - - Fortunately, no changes to FontForge are necessary – this is the - only external TrueType debugger I know of, but others may exist and - should check the code accordingly. - - * src/truetype/ttinterp.h (TT_CallRec): Replace `Cur_Restart' and - `Cur_End' with a pointer to the corresponding `TT_DefRecord' - structure. - - * src/truetype/ttinterp.c (DO_JROT, DO_JMPR, DO_JROF, Ins_ENDF, - Ins_CALL, Ins_LOOPCALL, Ins_UNKNOWN, TT_RunIns ): - Updated. - -2013-10-27 Werner Lemberg - - [sfnt] Implement support for `OS/2' table version 5. - - See - - http://typedrawers.com/discussion/470/new-microsoft-size-specific-design-selection-mechanism - - for the announcement. - - * include/freetype/tttables.h (TT_OS2): Add fields - `usLowerPointSize' and `usUpperPointSize'. Since FreeType returns - this structure only as a pointer through `FT_Get_Sfnt_Table', there - shouldn't be any ABI problems. - - * src/sfnt/ttload.c (tt_face_load_os2): Implement it. - - * docs/CHANGES: Updated. - -2013-10-24 Werner Lemberg - - * README.git, docs/CHANGES, docs/INSTALL: Updated. - -2013-10-24 John Cary - - Provide cmake support. - - * CMakeLists.txt: New file. - -2013-10-23 Kenneth Miller - Werner Lemberg - - Provide support for x64 builds in Visual C++ project files. - - * src/builds/win32: Renamed to... - * src/builds/windows: This. - - * src/builds/windows/vc2010/*: Updated to handle x64 target. - - * src/builds/windows/*.mk, docs/INSTALL.GNU: s/win32/windows/ where - appropriate. - -2013-10-22 Werner Lemberg - - * src/base/md5.c, src/base/md5.h: Updated to recent version. - - * src/base/ftobjs.c: Updated; `md5.c' no longer uses `free'. - - The canonical URL to get updates for this file is - - https://cvsweb.openwall.com/cgi/cvsweb.cgi/Owl/packages/popa3d/popa3d/md5/ - - as the author told me in private communication. - -2013-10-19 Werner Lemberg - - [autofit] s/SMALL_TOP/X_HEIGHT/. - - * src/autofit/afblue.dat: Updated. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/aflatin.c, src/autofit/aflatin.h, - src/autofit/aflatin2.c: Updated. - -2013-10-19 Werner Lemberg - - * src/autofit/afblue.dat: s/MINOR/DESCENDER/. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - -2013-10-16 Werner Lemberg - - [autofit] Add description strings to script entries. - - Currently, this is unused. - - * src/autofit/afscript.h: Do it. - * src/autofit/afglobal.c, src/autofit/afpic.c, - src/autofit/aftypes.h: Updated. - -2013-10-16 Werner Lemberg - - [autofit] Improve tracing message for extra light flag. - - * src/autofit/aflatin.c (af_latin_metrics_scale_dim): Do it. - -2013-10-15 Chongyu Zhu - - [arm] Fix thumb2 inline assembly under LLVM. - - When using `ADD' with an immediate operand, the instruction is - actually `ADD Rd, Rn, #', that is, the maximum of the - immediate operand cannot exceed 4095. It will fail to compile with - LLVM. - - However, in GCC, due to some legacy compatibility considerations, - `ADD.W' will be automatically emitted when the immediate operand is - larger than 4095. - - * builds/unix/ftconfig.in, include/freetype/config/ftconfig.h - (FT_MulFix_arm) [__GNUC__]: Support clang compiler. - - * src/truetype/ttinterp.c (TT_MulFix14_arm) [__GNUC__]: Ditto. - -2013-10-12 Werner Lemberg - - [autofit] Improve tracing of `latin' hinter. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Report blue - zone types. - (af_latin_metrics_scale_dim): Report scaling changes due to x height - alignment. - Report scaled stroke width and blue zone values. - -2013-10-03 Dave Arnold - - * src/cff/cf2font.c (cf2_computeDarkening): Avoid division by zero. - - Note that the old code avoided using a region of the piecewise - linear function where the slope was zero. The recovery was to use a - different section of the function, which produced a different, - incorrect amount of darkening. - -2013-10-02 Darrell Bellert - - * src/sfnt/ttload.c (tt_face_load_pclt): Fix `pclt_fields'. - -2013-10-02 Dave Arnold - - * src/cff/cf2font.c (cf2_computeDarkening): Initialize darkenAmount. - - This line was lost in commit 89ca1fd6 (from 2013-06-25). The effect - is to use a previous darkening amount when producing an unhinted, - unscaled outline. This can cause autohint samples in ftgrid and - ftview to be based on darkened CFF outlines instead of unhinted, - undarkened ones. - -2013-09-29 Dave Arnold - - Fix Savannah bug #39295. - - The bug was caused by switching to the initial hintmap (the one in - effect when `moveto' executes) just before drawing the final element - in the charstring. This ensured that the path was closed (in both - Character Space and Device Space). But if the final element was a - curve and if the final hintmap was different enough from the initial - one, then the curve was visibly distorted. - - The first part of the fix is to draw the final curve using the final - hintmap as specified by the charstring. This corrects the - distortion but does not ensure closing in Device Space. It may - require the rasterizer to automatically generate an extra closing - line. Depending on the hintmap differences, this line could be from - zero to a couple pixels in length. - - The second part of the fix covers the case where the charstring - subpath is closed with an explicit line. We now modify that line's - end point to avoid the distortion. - - Some glyphs in the bug report font (TexGyreHeros-Regular) that show - the change are: - - 25ppem S (98) - 24ppem eight (52) - 25.5ppem p (85) - - Curves at the *end* of a subpath are no longer distorted. However, - some of these glyphs have bad hint substitutions in the middle of a - subpath, and these are not affected. - - The patch has been tested with a set of 106 fonts that shipped with - Adobe Creative Suite 4, together with 756 Open Source CFF fonts from - Google Fonts. There are 1.5 million glyphs, of which some 20k are - changed with the fix. A sampling of a few hundred of these changes - have been examined more closely, and the changes look good (or at - least acceptable). - - * src/cff/cf2hints.h (CF2_GlyphPathRec): New element `pathIsClosing' - to indicate that we synthesize a closepath line. - - * src/cff/cf2hints.c (cf2_glyphpath_init): Updated. - (cf2_glyphpath_pushPrevElem): If closing, use first hint map (for - `lineto' operator) and adjust hint zone. - For synthesized closing lines, use end point in first hint zone. - (cf2_glyphpath_lineTo): Take care of synthesized closing lines. In - particular, shift the detection of zero-length lines from character - space to device space. - (cf2_glyphpath_closeOpenPath): Remove assertion. - Updated. - -2013-09-25 Werner Lemberg - - * src/autofit/aflatin.c (af_{grek,cyrl}_uniranges): Fix arrays. - -2013-09-25 suzuki toshiya - - [bdf, pcf] Refuse non-zero face_index. - - Suggested by Akira Tagoh, see - - https://lists.gnu.org/archive/html/freetype/2013-09/msg00030.html - - * src/bdf/bdfdrivr.c (BDF_Face_Init): Return `Invalid_Argument' - error if the font could be opened but non-zero `face_index' is - given. - * src/pcf/pcfdrivr.c (PCF_Face_Init): Ditto. - - * src/type42/t42objs.c (T42_Face_Init): Remove unrequired FT_UNUSED - macro for `face_index' because it is validated later. - -2013-09-23 Werner Lemberg - - Fix Savannah bug #40090. - - * src/autofit/afcjk.c (af_cjk_metrics_scale): Revert commit - 306f8c5d (from 2013-08-25) affecting this function. - -2013-09-22 Werner Lemberg - - [autofit] Disunify Cyrillic and Greek handling from Latin. - - * src/autofit/afscript.h: Add Cyrillic and Greek. - - * src/autofit/afblue.dat (AF_BLUE_STRINGSET_GREK, - AF_BLUE_STRINGSET_CYRL): Add blue zones for Greek and Cyrillic. - (AF_BLUE_STRINGSET_LATN): Fix typo. - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/aflatin.c (af_grek_uniranges, af_cyrl_uniranges): New - arrays. - (af_grek_script_class, af_cyrl_script_class): New scripts. - * src/autofit/aflatin.h: Updated. - -2013-09-20 Werner Lemberg - - * docs/CHANGES: Updated. - -2013-09-20 Behdad Esfahbod - - Fix vertical size of emboldened glyphs. - - Cf. https://bugzilla.gnome.org/show_bug.cgi?id=686709 - - * src/base/ftsynth.c (FT_GlyphSlot_Embolden): Adjust `horiBearingY' - also. - -2013-09-11 Alexei Podtelezhnikov - - * include/freetype/ftoutln.h: Correct FT_Outline_Get_Orientation - algorithm description. - -2013-09-11 Werner Lemberg - - [autofit] Improve Hebrew rendering. - - This change introduces a new blue zone property - `AF_BLUE_PROPERTY_LATIN_LONG' to make the auto-hinter ignore short - top segments. - - * src/autofit/afblue.dat: Fix Hebrew blue strings. - Use AF_BLUE_PROPERTY_LATIN_LONG for AF_BLUE_STRING_HEBREW_TOP. - - * src/autofit/afblue.hin (AF_BLUE_PROPERTY_LATIN_LONG): New macro. - - * src/autofit/afblue.c, src/autofit/afblue.h: Updated. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Handle - `AF_LATIN_IS_LONG_BLUE'. - - * src/autofit/aflatin.h (AF_LATIN_IS_LONG_BLUE): New macro. - -2013-08-28 Behdad Esfahbod - - [sfnt] Fix frame access while reading WOFF table directory. - - * src/sfnt/sfobjs.c (woff_open_font): Using single memory frame - while reading the directory entries for the whole loop. - -2013-08-29 Werner Lemberg - Behdad Esfahbod - - Implement support for WOFF containers. - - We simply synthesize a SFNT from the WOFF, create a memory stream - for the new data, and load the SFNT as usual. - - Does NOT add any API to access WOFF metadata or private blocks. - - * include/freetype/internal/tttypes.h (WOFF_HeaderRec, - WOFF_TableRec): New structures. - - * include/freetype/tttags.h (TTAG_wOFF): New macro. - - * src/base/ftobjs.c (FT_Open_Face): Set `stream' after calling - `open_face'. - - * src/sfnt/sfobjs.c [FT_CONFIG_OPTION_SYSTEM_ZLIB]: Include - `FT_GZIP_H'. - (WRITE_BYTE, WRITE_USHORT, WRITE_ULONG): New temporary macros for - writing to a stream. - (sfnt_stream_close, compare_offsets, woff_open_font): New functions. - (sfnt_open_font): Handle `TTAG_wOFF'. - (sfnt_init_face): Set `stream' after calling `sfnt_open_font'. - - * src/truetype/ttobjs.c (tt_face_init): Set `stream' after calling - `sfnt->init_face'. - - * src/base/ftobjs.c (open_face): Use a pointer to FT_Stream as an - argument so that a changed stream survives. - Update callers. - -2013-08-28 Werner Lemberg - - [gzip] New function `FT_Gzip_Uncompress'. - - This is modeled after zlib's `uncompress' function. We need this - for WOFF support. - - * include/freetype/ftgzip.h, src/gzip/ftgzip.c (FT_Gzip_Uncompress): - New function. - - * src/gzip/rules.mk: Rewrite to better reflect dependencies. - -2013-08-28 Werner Lemberg - - [autofit] Fix `make multi' compilation. - - * src/autofit/afblue.cin, src/autofit/afblue.c: Don't include - `afblue.h' but `aftypes.h'. - * src/autofit/afcjk.c: Don't include `aftypes.h' but `afglobal.h'. - -2013-08-28 Werner Lemberg - - [autofit] Fix C++ compilation. - - * src/autofit/afglobal.c (af_face_globals_get_metrics), - src/autofit/afdummy.c (af_dflt_script_class), src/autofit/afindic.c - (af_deva_script_class): Use proper casts. - -2013-08-27 Behdad Esfahbod - - * src/sfnt/ttload.c (tt_face_load_font_dir): Fix sign typos. - -2013-08-27 Behdad Esfahbod - - FT_Open_Face: Improve external stream handling. - - If the font's `clazz->init_face' function wants to swap to new - stream, handling of whether original stream was external could - result to either memory leak or double free. Mark externality into - face flags before calling `init_face' such that the clazz can handle - external streams properly. - - * src/base/ftobjs.c (FT_Open_Face): Move code to set - FT_FACE_FLAG_EXTERNAL_STREAM to... - (open_face): This function. - -2013-08-27 Werner Lemberg - - Remove `FT_SqrtFixed' function. - - It's no longer used. - - * include/freetype/internal/ftcalc.h, src/base/ftcalc.c: Do it. - -2013-08-27 Werner Lemberg - - [autofit] While tracing, report script names instead of ID values. - - * src/autofit/afglobal.c (af_script_names) [FT_DEBUG_LEVEL_TRACE]: - New array. - * src/autofit/afglobal.h: Updated. - - * src/autofit/afcjk.c (af_cjk_metrics_init_widths, - af_cjk_hint_edges): Use `af_script_names'. - * src/autofit/aflatin.c (af_latin_metrics_init_widths, - af_latin_hint_edges): Ditto. - -2013-08-26 Werner Lemberg - - [autofit] Report used script while hinting a glyph. - - * src/autofit/afcjk.c (af_cjk_hint_edges), src/autofit/aflatin.c - (af_latin_hint_edges): Implement it. - -2013-08-26 Werner Lemberg - - [autofit] Add support for Hebrew script. - - * src/autofit/afblue.dat: Add blue strings for Hebrew. - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/aflatin.c (af_hebr_uniranges): New array. - (af_hebr_script_class): New script. - * src/autofit/aflatin.h, src/autofit/afscript.h: Updated. - -2013-08-26 Werner Lemberg - - [autofit] Improve tracing messages. - - * src/autofit/afcjk.c (af_cjk_metrics_init_widths): Mention script - ID in tracing message. - (af_cjk_metrics_init_blues): Initialize `axis' outside of the inner - loop. - Improve tracing messages. - (af_cjk_hint_edges) [FT_DEBUG_LEVEL_TRACE]: New variable - `num_actions' to count hinting actions. - Improve tracing messages. - - * src/autofit/aflatin.c (af_latin_metrics_init_widths): Mention - script ID in tracing message. - (af_latin_metrics_init_blues, af_latin_hint_edges): Improve tracing - messages. - -2013-08-26 Werner Lemberg - - Better tracing of loaded glyphs. - - Previously, the loading of a glyph was traced at level 4, if at all. - With this change, all font loading routines emit a tracing message - at level 1, making it easier to select tracing output (for example - using F2_DEBUG="any:1 afhints:7 aflatin:7"). - - * src/bdf/bdfdrivr.c (BDF_Glyph_Load): Add tracing message. - * src/cff/cffdrivr.c (cff_glyph_load): Ditto. - * src/cff/cffgload.c (cff_decoder_prepare): Improve tracing - messages. - * src/cid/cidgload.c (cid_load_glyph): Use level 1 for tracing - message. - * src/pcf/pcfdrivr.c (PCF_Glyph_Load): Ditto. - * src/pfr/pfrobjs.c (pfr_slot_load): Add tracing message. - * src/truetype/ttgload.c (TT_Load_Glyph): Ditto. - * src/type1/t1gload.c (T1_Load_Glyph): Ditto. - * src/type42/t42objs.c (T42_GlyphSlot_Load): Ditto. - * src/winfonts/winfnt.c (FNT_Load_Glyph): Ditto. - -2013-08-26 Werner Lemberg - - [autofit] Fix script selection. - - * src/autofit/afglobal.c (af_face_globals_get_metrics): Use - `AF_SCRIPT_DFLT', not value 0. - Simplify code. - - * src/autofit/afscript.h: Sort by script name. - -2013-08-26 Werner Lemberg - - [autofit] Make `dummy' hinter work as expected. - - * src/autofit/afdummy.c (af_dummy_hints_init): Properly set scaling - information. - (af_dummy_hints_apply): Scale the glyphs. - -2013-08-25 Werner Lemberg - - [autofit] Make `cjk' module use blue stringsets. - - * src/autofit/afcjk.c (AF_CJK_MAX_TEST_CHARACTERS): Removed. - (af_cjk_hani_blue_chars): Removed. - (AF_CJK_BLUE_TYPE_*): Removed. - (af_cjk_metrics_init_blues): Replace AF_CJK_MAX_TEST_CHARACTERS with - AF_BLUE_STRING_MAX_LEN. - Change loops to use offsets (in file `afblue.h') into the new arrays - `af_blue_stringsets' and `af_blue_strings' (in file `afblue.c'). - Instead of three dimensions (as used in the old blue string array) - we now use properties to do the same, saving one loop nesting level. - - * src/autofit/afcjk.h: Remove old enumeration values superseded by - the new data in `afblue.h'. - (AF_CJK_IS_TOP_BLUE, AF_CJK_IS_HORIZ_BLUE, AF_CJK_IS_FILLED_BLUE, - AF_CJK_IS_RIGHT_BLUE): New macros, to be used in - `af_cjk_metrics_init_blues'. - (AF_CJK_BLUE_IS_RIGHT): Remove this now redundant enum value. - (AF_CJK_BLUE_IS_TOP): Renamed to... - (AF_CJK_BLUE_TOP): This. - (AF_CJK_MAX_BLUES): Remove. - (AF_CJKAxisRec): Updated. - -2013-08-25 Werner Lemberg - - [autofit] Typo. - - * src/autofit/afblue.hin, src/autofit/afblue.c (GET_UTF8_CHAR): Use - cast. - -2013-08-25 Werner Lemberg - - [autofit] Synchronize `cjk' with `latin' module (and vice versa). - - * src/autofit/afcjk.c (af_cjk_metrics_init_widths): Add tracing - messages. - (af_cjk_metrics_init_blues): Don't pass blue string array as - argument but use the global array directly. - Use `outline' directly. - Update and add tracing messages. - (af_cjk_metrics_init): Simplify code. - (af_cjk_metrics_scale_dim): Improve tracing message. - (af_cjk_metrics_scale): Synchronize. - - * src/autofit/aflatin.c (af_latin_metrics_init_widths, - af_latin_metrics_init_blues): Improve and add tracing messages. - -2013-08-25 Werner Lemberg - - [autofit] Make `latin' module use blue stringsets. - - * src/autofit/aflatin.c (AF_LATIN_MAX_TEST_CHARACTERS): Removed. - (af_latin_blue_chars): Removed. - (af_latin_metrics_init_blues): Replace AF_LATIN_MAX_TEST_CHARACTERS - with AF_BLUE_STRING_MAX_LEN. - Change loops to use offsets (in file `afblue.h') into the new arrays - `af_blue_stringsets' and `af_blue_strings' (in file `afblue.c'). - Use `AF_LATIN_IS_SMALL_TOP_BLUE' macro. - - * src/autofit/aflatin.h: Remove old enumeration values superseded by - the new data in `afblue.h'. - (AF_LATIN_IS_TOP_BLUE): Updated definition. - (AF_LATIN_IS_SMALL_TOP_BLUE): New macro. - (AF_LATIN_MAX_BLUES): Remove. - (AF_LatinAxisRec): Updated. - -2013-08-25 Werner Lemberg - - [autofit] Add blue stringsets. - - * src/autofit/aftypes.h: Include `afblue.h'. - (AF_ScriptClassRec): Add `blue_stringset' field. - (AF_DEFINE_SCRIPT_CLASS): Updated. - - * src/autofit/autofit.c: Include `afblue.c'. - - * src/autofit/afcjk.c (af_hani_script_class), src/autofit/afdummy.c - (af_dflt_script_class), src/autofit/afindic.c - (af_deva_script_class), src/autofit/aflatin.c - (af_latn_script_class), src/autofit/aflatin2.c - (af_ltn2_script_class): Updated. - - * src/autofit/rules.mk (AUTOF_DRV_SRC): Add `afblue.c'. - -2013-08-25 Werner Lemberg - - [autofit] Introduce data file for blue strings. - - The idea is to have a central file which gets processed by a Perl - script to create proper `.c' and `.h' files using templates. There - are two other reasons to do that: - - . The data file should be easily readable. We use UTF-8 encoding - which then gets converted to single bytes. - - . Since the number of supported scripts will increase soon, the - current usage of blue string arrays is a waste of space. Using - the Perl script it is possible to imitate jagged arrays, - defining enumeration constants as offsets into the arrays. - - This commit only adds files without changing any functionality. - - * src/autofit/afblue.dat: New data file. - * src/tools/afblue.pl: New Perl script for processing `afblue.dat'. - - * src/autofit/afblue.cin, src/autofit/afblue.hin: New template files - for... - * src/autofit/afblue.c, src/autofit/afblue.c: New source files. - To avoid a dependency on Perl, we add them too. - -2013-08-19 Alexei Podtelezhnikov - - [base] Enable new algorithm for `BBox_Cubic_Check'. - - * src/base/ftbbox.c: Enable new BBox_Cubic_Check algorithm, remove - the old one. - Improve comments. - -2013-08-18 Werner Lemberg - - * builds/unix/unix-def.in (freetype2.pc): Don't set executable bit. - -2013-08-18 Werner Lemberg - - Fix Savannah bug #39804. - - * builds/unix/configure.raw (LIBPNG): Define and export. - * builds/unix/freetype-config.in, builds/unix/freetype2.in: Handle - libpng. - -2013-08-17 Alexei Podtelezhnikov - - [base] Clean up BBox_Conic_Check. - - * src/base/ftbbox.c (BBox_Conic_Check): Remove redundant checks for - extremum at the segment ends, which are already within the bbox. - Slightly modify calculations. - -2013-08-15 Alexei Podtelezhnikov - - [base] Finish experimental (disabled) BBox_Cubic_Check implementation. - - * src/base/ftbbox.c (BBox_Cubic_Check): Scale arguments to improve - accuracy and avoid overflows. - -2013-08-13 Alexei Podtelezhnikov - - [base] Refactor experimental (disabled) BBox_Cubic_Check. - - * src/base/ftbbox.c (BBox_Cubic_Check): Implement the minimum search - as the mirror image of the maximum search implemented here... - (update_max): New function. - -2013-08-06 John Tytgat - - Fix Savannah bug #39702. - - * src/cff/cffload.c (cff_index_get_pointers): Check for `cur_offset - != 0'; this stronger test is mandated by the CFF specification. - Fix test for INDEX structures which have one or more empty entries - at the end. - -2013-08-05 Werner Lemberg - - Fix gcc pragmas, part 2. - - * src/truetype/ttinterp.c (TT_MulFix14_long_long, - TT_DotFix14_long_long): `#pragma gcc diagnostic {push,pop}' has been - introduced with gcc version 4.6. - -2013-08-05 Werner Lemberg - - Fix gcc pragmas. - - * src/truetype/ttinterp.c (TT_MulFix14_long_long, - TT_DotFix14_long_long): Older gcc versions don't accept diagnostic - pragmas within a function body. - -2013-08-05 Werner Lemberg - - Fix Savannah bug #39700. - - * builds/unix/ftconfig.h: Synchronize with - `include/freetype/config/ftconfig.h'. - - * builds/vms/ftconfig.h: Ditto. - Make the differences to the master `ftconfig.h' file as small as - possible for easier maintenance. - -2013-08-05 Werner Lemberg - - [autofit] Improve handling of `near' points. - - Points which are very near to each other are now marked as such. - The `weak' flag is then computed by using the `in' vector of the - first and the `out' vector of the last point of a group of near - points. - - For example, this fixes the rendering of glyph `Oslash' in - `Roboto-Thin.ttf'. - - * src/autofit/afhints.h (AF_Flags): New value `AF_FLAGS_NEAR'. - - * src/autofit/afhints.c (af_glyph_hints_reload): Introduce - the heuristic value `near_limit' to decide whether the current point - is near to the previous one, then set `AF_FLAG_NEAR' accordingly. - Store good `in' vector (of last non-near point) in - `last_good_in_{x,y}' and use it as an argument to - `ft_corner_is_flat' if necessary. - -2013-08-02 Werner Lemberg - - * include/freetype/ftcffdrv.h: Improve documentation. - This is based on blog entries from David Lemon and Dave Arnold (both - from Adobe) with kind permission. Dave also helped in - proof-reading. - -2013-08-02 Werner Lemberg - - [autofit] Move declaration of scripts into separate file. - - This has the benefit that we don't need to duplicate the data at - different places. - - * src/autofit/afscript.h: New file. - - * src/autofit/aftypes.h (AF_Script): Include `afscript.h' to define - the enumeration values. - - * src/autofit/afglobal.c: Include `afscript.h' to get the script - specific header files. - (af_script_classes): Include `afscript.h' to fill this array. - - * src/autofit/afpic.c: Include `afscript.h' to get the script - specific header files. - (autofit_module_class_pic_init): Include `afscript.h' for - initialization. - * src/autofit/afpic.h (AF_SCRIPT_CLASSES_COUNT, - AF_SCRIPT_CLASSES_REC_COUNT): Removed. Use `AF_SCRIPT_MAX' instead. - - * src/autofit/rules.mk (AUTOF_DRV_H): Updated. - -2013-08-02 Werner Lemberg - - [autofit] Move declaration of writing systems into separate file. - - This has the benefit that we don't need to duplicate the data at - different places. - - * src/autofit/afwrtsys.h: New file. - - * src/autofit/aftypes.h (AF_WritingSystem): Include `afwrtsys.h' to - define the enumeration values. - - * src/autofit/afglobal.c: Include `afwrtsys.h' to get the writing - system specific header files. - Include `afpic.h'. - (af_writing_system_classes): Include `afwrtsys.h' to fill this - array. - - * src/autofit/afpic.c: Include `afwrtsys.h' to get the writing - system specific header files. - (autofit_module_class_pic_init): Include `afwrtsys.h' for - initialization. - * src/autofit/afpic.h (AF_WRITING_SYSTEM_CLASSES_COUNT, - AF_WRITING_SYSTEM_CLASSES_REC_COUNT): Removed. Use - `AF_WRITING_SYSTEM_MAX' instead. - -2013-08-02 Werner Lemberg - - [sfnt] Fix compilation with g++. - - * src/sfnt/pngshim.c (error_callback, read_data_from_FT_stream): Use - cast. - (Load_SBit_Png): Pacify compiler. - -2013-08-02 suzuki toshiya - Werner Lemberg - - [autofit] Fix `make multi'. - - * include/freetype/config/ftconfig.h (FT_LOCAL_ARRAY, - FT_LOCAL_ARRAY_DEF): New macros. - - * src/autofit/afglobal.c (af_writing_system_classes, - af_script_classes): Use FT_LOCAL_ARRAY_DEF. - * src/autofit/afglobal.h: Declare `af_writing_system_classes' and - `af_script_classes'. - * src/autofit/afloader.c: Include `afpic.h'. - -2013-08-01 Werner Lemberg - - Another round of cppcheck nitpicks. - - The call was (from the top-level of the FreeType tree): - - cppcheck --force \ - --enable=all \ - -I /usr/include \ - -I /usr/local/include \ - -I /usr/lib/gcc/i586-suse-linux/4.7/include \ - -I include \ - -I include/freetype \ - -I include/freetype/config \ - -I include/freetype/internal \ - -DFT2_BUILD_LIBRARY \ - . &> cppcheck.log - - using cppcheck git commit f7e93f99. - - Note that cppcheck still can't handle `#include FOO' (with `FOO' a - macro). - - */* Improve variable scopes. - */* Remove redundant initializations which get overwritten. - - * src/gxvalid/*: Comment out redundant code or guard it with - FT_DEBUG_LEVEL_TRACE. - -2013-07-30 Werner Lemberg - - [autofit] Introduce `writing systems'. - - This patch adds a new top level to the auto-hinter's script class - hierarchy. It defines `writing systems' which can contain multiple - scripts. - - For example, the `latin' writing system (in file `aflatin.c') is - able to support scripts like Latin, Cyrillic, Armenian, etc., which - can be handled similarly. - - Scripts are now named using four-letter OpenType tags. - - * src/autofit/aftypes.h (AF_ScriptClassRec): Move relevant members - to... - (AF_WritingSystemClassRec): This new structure. It holds pointers - to functions which can be shared among related scripts. - (AF_WritingSystem): New enumeration. - (AF_Script): Revised values using four-letter tags. - (AF_DEFINE_WRITING_SYSTEM_CLASS): New macro. - (AF_DEFINE_SCRIPT_CLASS): Updated. - - * src/autofit/afglobal.c (af_writing_system_classes): New global, - constant array. - (af_script_classes): Updated. - (af_face_globals_free): Updated. - Remove assertion. - (af_face_globals_get_metrics): Updated. - - * src/autofit/afglobal.h (AF_SCRIPT_FALLBACK) - [!AF_CONFIG_OPTION_CJK]: Handle this case. - - * src/autofit/afloader.c (af_loader_load_g, af_loader_load_glyph): - Updated. - - * src/autofit/afpic.c (autofit_module_class_pic_init): Updated; - initialize structures for both writing systems and scripts. - * src/autofit/afpic.h: Updated. - (AF_WRITING_SYSTEM_CLASSES_GET): New macro. - - * src/autofit/afcjk.c (af_cjk_writing_system_class): New writing - system. - (af_cjk_uniranges): Renamed to... - (af_hani_uniranges): This. - (af_cjk_script_class): Reduced and renamed to... - (af_hani_script_class): This. - * src/autofit/afcjk.h: Updated. - - * src/autofit/afdummy.c (af_dummy_writing_system_class): New writing - system. - (af_dummy_script_class): Reduced and renamed to... - (af_dflt_script_class): This. - * src/autofit/afdummy.h: Updated. - - * src/autofit/afindic.c (af_indic_writing_system_class): New writing - system. - (af_indic_uniranges): Renamed to... - (af_deva_uniranges): This. - (af_indic_script_class): Reduced and renamed to... - (af_deva_script_class): This. - * src/autofit/afcjk.h: Updated. - - * src/autofit/aflatin.c (af_latin_writing_system_class): New writing - system. - (af_latin_uniranges): Renamed to... - (af_latn_uniranges): This. - (af_latin_script_class): Reduced and renamed to... - (af_latn_script_class): This. - * src/autofit/aflatin.h: Updated. - - * src/autofit/aflatin2.c (af_latin2_writing_system_class): New - writing system. - (af_latin2_uniranges): Renamed to... - (af_ltn2_uniranges): This. - Synchronize ranges with `latin'. - (af_latin2_script_class): Reduced and renamed to... - (af_ltn2_script_class): This. - * src/autofit/aflatin2.h: Updated. - -2013-07-30 Werner Lemberg - - [autofit] Variable renaming. - - * src/autofit/aftypes.h (AF_ScriptMetricsRec): - s/clazz/script_class/. - Update all users. - -2013-07-30 suzuki toshiya - - Ignore libpng-config under cross-building configuration, - because it will return the flags for the hosting environment. - - * builds/unix/configure.raw: Ignore libpng-config when - `cross_compiling' == yes. - -2013-07-30 Behdad Esfahbod - - Prevent division by zero by a transparent color. - - * src/base/ftbitmap.c (ft_gray_for_premultiplied_srgb_bgra): - Return 0 immediately, when alpha channel is zero. - -2013-07-25 Behdad Esfahbod - - Add FT_FACE_FLAG_COLOR and FT_HAS_COLOR. - - Also disambiguate Google's color bitmap tables. - - * include/freetype/freetype.h (FT_FACE_FLAG_COLOR, FT_HAS_COLOR): - New macros. - - * include/freetype/internal/tttypes.h (TT_SbitTableType): Add - TT_SBIT_TABLE_TYPE_CBLC. - - * src/sfnt/sfobjs.c (sfnt_load_face): Handle FT_FACE_FLAG_COLOR. - - * src/sfnt/ttsbit.c (tt_face_load_sbit, - tt_face_load_strike_metrics, tt_face_load_sbit_image): Handle - TT_SBIT_TABLE_TYPE_CBLC. - -2013-07-24 suzuki toshiya - - [sfnt] Fix for `make multi' target. - - * src/sfnt/pngshim.c (Load_SBit_Png): Use FT_LOCAL_DEF(). - -2013-07-20 Werner Lemberg - - * docs/INSTALL.GNU: Updated. - -2013-07-20 Behdad Esfahbod - - [sfnt] Fix `sbix' table version handling. - - * src/sfnt/ttsbit.c (tt_face_load_sbit) [TT_SBIT_TABLE_TYPE_SBIX]: - USHORT version numbers are to be considered as `minor'. - -2013-07-19 Werner Lemberg - - [autofit] Fix segment classification for blue zones. - - The old code (essentially unchanged since the very beginning) - incorrectly handled this configuration - - x -o- x - / \ - / \ - / \ - o o - - as flat and this - - o o - / / - x| x| - | | - o---------------o - - as round. (`o' and `x' are on and off points, respectively). - - This is a major change which should improve the rendering results - enormously for many TrueType fonts, especially in the range approx. - 20-40ppem, fixing the appearance of many overshoots. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Look at the - first and last points of the segment, not the points right before - and after. - -2013-07-19 Behdad Esfahbod - - [sfnt] `sbix' fix-ups. - - * src/sfnt/sfobjs.c (sfnt_load_face): Apple's `sbix' color bitmaps - are rendered scaled and then the `glyf' outline rendered on top. We - don't support that yet, so just ignore the `glyf' outline and - advertise it as a bitmap-only font. - - * src/sfnt/ttsbit.c (tt_face_load_strike_metrics) - [TT_SBIT_TABLE_TYPE_SBIX]: Return metrics in 26.6 units. - (tt_face_load_sbix_image): Typo. - -2013-07-18 Behdad Esfahbod - - [sfnt] Add support for Apple's `sbix' color bitmap table. - - * include/freetype/internal/tttypes.h (TT_SBit_MetricsRec): Widen - fields to FT_Short and FT_UShort, respectively. - (TT_SbitTableType): New enumeration. - (TT_FaceRec): Add `sbit_table_type' field. - - * include/freetype/tttags.h (TTAG_sbix): New macro. - - * src/sfnt/pngshim.c (Load_SBit_Png): Pass a more generic - FT_GlyphSlot argument instead FT_Bitmap. - Add flag to control map and metrics handling. - Update all users. - - * src/sfnt/ttsbit.c: Include `ttmtx.h'. - (tt_face_load_eblc): Renamed to... - (tt_face_load_sbit): This. - Handle `sbix' bitmaps. - (tt_face_free_eblc): Renamed to... - (tt_face_load_sbit): This. - Updated. - (tt_face_load_strike_metrics): Handle `sbix' bitmaps. - (tt_face_load_sbix_image): New function. - (tt_sbit_decoder_alloc_bitmap, tt_sbit_decoder_load_image, - tt_sbit_decoder_load_byte_aligned, tt_sbit_decoder_load_bit_aligned, - tt_sbit_decoder_load_compound, tt_sbit_decoder_load_png, - tt_sbit_decoder_load_image, tt_sbit_decoder_load_bitmap): Don't pass - and handle load flags. - (tt_sbit_decoder_load_bitmap) [!FT_CONFIG_OPTION_USE_PNG]: Better - handle formats 17-19. - Move color to grayscale conversion to... - (tt_face_load_sbit_image): Here. - Handle `sbix' bitmaps. - - * src/sfnt/pngshim.h: Updated. - * src/sfnt/ttsbit.h: Updated. - * src/sfnt/sfdriver.c: Updated. - -2013-07-18 Werner Lemberg - - [sfnt] Ignore invalid magic number in `head' or `bhed'. - - Other font engines seem to ignore it also. Problem reported by - Hin-Tak Leung . - - * src/sfnt/ttload.c (check_table_dir): Don't abort but warn only if - we have an invalid magic number. - -2013-07-16 Werner Lemberg - - [smooth] Fix segfault caused by previous commit. - - * src/smooth/ftgrays.c (gray_set_cell): Always compute - `ras.invalid'. - -2013-07-16 David Turner - - [smooth] Improve performance. - - Provide a work-around for an ARM-specific performance bug in GCC. - This speeds up the rasterizer by more than 5%. - - Also slightly optimize `set_gray_cell' and `gray_record_cell' (which - also improves performance on other platforms by a tiny bit (<1%). - - * src/smooth/ftgrays.c (FT_DIV_MOD): New macro. - Use it where appropriate. - - (gray_record_cell, gray_set_cell, gray_move_to, - gray_convert_glyph_inner): Streamline condition handling. - -2013-07-16 David Turner - - [truetype] Add assembler code for TT_MulFix14 and TT_DotFix14. - - This patch provides slightly optimized versions for ARM, x86, and - x86_64 CPUs if built with GCC. - - Also remove some dead code. - - * src/truetype/ttinterp.c (TT_MulFix14_arm, TT_MulFix14_long_long, - TT_DotFix14_long_long): New functions. - -2013-07-16 David Turner - - Optimize FT_MulFix for x86_64 GCC builds. - - This patch provides an optimized `FT_MulFix' implementation for - x86_64 machines when FreeType is built with GCC, or compatible - compilers like Clang. - - Example: - bin/ftbench -p -t 5 -s 14 -f 0008 Arial.ttf - - Before: - - Load 4.863 us/op - Load_Advances (Normal) 4.816 us/op - Load_Advances (Fast) 0.028 us/op - Render 2.753 us/op - Get_Glyph 0.463 us/op - Get_CBox 0.077 us/op - Get_Char_Index 0.023 us/op - Iterate CMap 13.898 us/op - New_Face 12.368 us/op - Embolden 0.028 us/op - Get_BBox 0.302 us/op - - After: - - Load 4.617 us/op - Load_Advances (Normal) 4.645 us/op - Load_Advances (Fast) 0.027 us/op - Render 2.789 us/op - Get_Glyph 0.460 us/op - Get_CBox 0.077 us/op - Get_Char_Index 0.024 us/op - Iterate CMap 13.403 us/op - New_Face 12.278 us/op - Embolden 0.028 us/op - Get_BBox 0.301 us/op - - * builds/unix/ftconfig.in, include/freetype/config/ftconfig.h - (FT_MulFix_x86_64): New function. - -2013-07-16 David Turner - - Speed up ARMv7 support. - - When building for ARMv7 with thumb2 instructions, the optimized - `FT_MulFix_arm' assembly routine was not being used. - - The reason for this is in the `ftconfig.h' header, namely: - - - The assembly routine uses the `smull' instruction which is not - available when generating Thumb-1 machine code. It is available - in Thumb-2 mode, though. - - - The header was written a long time ago before Thumb-2 became - widely popular (e.g. with Android). So it simply doesn't use the - assembly routine if the `__thumb__' built-in macro is defined. - - - When compiling in Thumb-2 mode, the compiler will define both - `__thumb__' and `__thumb2__'. - - By checking for `(__thumb2__ || !__thumb__)', we ensure that the - assembly routine is only avoided when generating Thumb-1 code. - - Given that this is performance-sensitive function, this improves - `ftbench' as follows on a Galaxy Nexus: - - Before (us/op) After (us/op) - - - loading Arial.ttf glyphs at 14 ppem [1] - - Load 34.285 33.098 - - - same operation with the light auto-hinter [2] - - Load 31.317 29.590 - - - same operation without hinting [3] - - Load 6.143 5.376 - - - loading Arial.ttf advances at 14 ppem [4] - - Load_Advances (normal) 34.216 33.016 - Load_Advances (fast) 0.176 0.176 - - [1] ftbench -t 5 -p -s 14 -b a -f 0008 Arial.ttf - [2] ftbench -t 5 -p -s 14 -b a -r 1 -f 0028 Arial.ttf - [3] ftbench -t 5 -p -s 14 -b a -f 000a Arial.ttf - [4] ftbench -t 5 -p -s 14 -b b -f 0008 Arial.ttf - - * builds/unix/ftconfig.in, include/freetype/config/ftconfig.h - (FT_MULFIX_ASSEMBLER): Fix handling for ARMv7. - -2013-06-28 Werner Lemberg - - * docs/CHANGES: Updated. - -2013-06-27 Werner Lemberg - - * src/winfonts/winfnt.c (FNT_Load_Glyph): Fix bitmap width guard. - -2013-06-25 Werner Lemberg - - [cff] Add darkening limit to `darkening-parameters'. - - * src/cff/cffdrivr.c (cff_property_set): Add check. - -2013-06-25 Werner Lemberg - - [cff] Add `darkening-parameters' property. - - * include/freetype/ftcffdrv.h: Document it. - - * src/cff/cffdrivr.c (cff_property_set, cff_property_get): Handle - `darkening-parameters' property. - - * src/cff/cf2font.h (CF2_FontRec): Add `darkenParams' array. - - * src/cff/cf2font.c (cf2_computeDarkening): Add `darkenParams' - argument and use it. - Update all callers. - - * src/cff/cf2ft.c (cf2_decoder_parse_charstrings): Copy - `darken_params' values. - - * src/cff/cffobjs.h (CFF_DriverRec): Add `darken_params' array. - - * src/cff/cffobjs.c (cff_driver_init): Set default values for - `darken_params'. - -2013-06-25 Werner Lemberg - - [docmaker] Code shuffling. - - * src/tools/docmaker/tohtml.py (re_url): Move regexp... - * src/tools/docmaker/sources.py: ... to this file. - -2013-06-25 Werner Lemberg - - [docmaker] Remove unused functions. - - * src/tools/docmaker/content.py (DocMarkup.get_start, - DocBlock.get_markup_name): Removed. - * src/tools/docmaker/tohtml.py (html_quote0, dump_html_code, - HtmlFormatter.make_html_words): Removed. - -2013-06-25 Werner Lemberg - - * builds/freetype.mk (dll): Remove target. - - Problem reported by Jörg Günnewig . - -2013-06-25 Werner Lemberg - - [docmaker] Recognise URLs. - - * src/tools/docmaker/tohtml.py (re_url): New regular expression. - (make_html_para): Use it. - -2013-06-19 Werner Lemberg - - * Version 2.5.0.1 released. - =========================== - - - Tag sources with `VER-2-5-0-1'. - - * include/freetype/config/ftoption.h: Undefine - CFF_CONFIG_OPTION_OLD_ENGINE. - * devel/ftoption.h: Define CFF_CONFIG_OPTION_OLD_ENGINE. - -2013-06-19 Werner Lemberg - - * builds/unix/install.mk (install): Don't create `cache' directory. - - Found by Peter Breitenlohner . - -2013-06-19 Werner Lemberg - - * Version 2.5.0 released. - ========================= - - - Tag sources with `VER-2-5-0'. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.5.0. - - * README, Jamfile (RefDoc), - builds/win32/vc2005/freetype.vcproj, builds/win32/vc2005/index.html, - builds/win32/vc2008/freetype.vcproj, builds/win32/vc2008/index.html, - builds/win32/vc2010/freetype.vcxproj, builds/win32/vc2010/index.html, - builds/win32/visualc/freetype.dsp, - builds/win32/visualc/freetype.vcproj, - builds/win32/visualc/index.html, builds/win32/visualce/freetype.dsp, - builds/win32/visualce/freetype.vcproj, - builds/win32/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.4.12/2.5.0/, s/2412/250/. - - * include/freetype/freetype.h (FREETYPE_MINOR): Set to 5. - (FREETYPE_PATCH): Set to 0. - - * builds/unix/configure.raw (version_info): Set to 16:2:10. - - * src/base/ftobjs.c (FT_Open_Face): Pacify compiler. - * src/truetype/ttinterp.c (Ins_MSIRP, Ins_MIRP): Ditto. - -2013-06-18 Werner Lemberg - - Fix Savannah bug #39269. - - * src/base/ftgloadr.c (FT_GlyphLoader_CheckPoints): Free memory in - case of reallocation failures. - -2013-06-18 Andrew Church - - Fix Savannah bug #39266. - - If memory allocations fail at certain points while opening a font, - FreeType can either crash due to a NULL dereference or leak memory. - - * include/freetype/internal/ftobjs.c (FT_Face_InternalRec, - FT_LibraryRec): Make `refcount' a signed integer. If, for example, - FT_Open_Face() fails in a memory allocation before the face's - reference count is set to 1, a subsequent `FT_Done_Library' call - would otherwise loop over `FT_Done_Face' 2^32 times before freeing - the face. - - * src/base/ftobjs.c (open_face): Initialize `stream' and friends - earlier. - (FT_Open_Face) : Behave correctly if `node' is NULL. - (FT_Destroy_Module) : Check that `renderer_clazz' is valid. - -2013-06-14 Werner Lemberg - - * src/smooth/ftgrays.c One final pragma to silence 64-bit MSVC. - -2013-06-06 Dave Arnold - Werner Lemberg - - [cff] Add code to Adobe's engine to handle ppem > 2000. - - * src/cff/cffgload.c (cff_slot_load): If we get - FT_Err_Glyph_Too_Big, retry unhinted and scale up later on. - -2013-06-12 Werner Lemberg - - Another try on pragmas. - - * include/freetype/internal/ftdebug.h: Move pragmas to... - * include/freetype/internal/internal.h: ... this file since it gets - included by all source files. - * include/freetype/internal/ftserv.h: Remove pragma which has no - effect. - -2013-06-12 Werner Lemberg - - * include/freetype/internal/ftdebug.h: Disable MSVC warning C4127. - - This partially undoes commit 3f6e0e0c. - -2013-06-12 Werner Lemberg - - More compiler warning fixes. - - */*: Use cast to `FT_Bool' (or `Bool') where appropriate. - -2013-06-10 Werner Lemberg - - [truetype] Improve handling of broken sbit advance widths. - - * src/truetype/ttgload.c (TT_Load_Glyph): Use the glyph's (scaled) - `linearHoriAdvance' if the sbit's `horiAdvance' value is zero. - - Cf. font `Fixedsys Excelsior' v3.01 (FSEX300.ttf), glyph A, 16ppem. - -2013-06-10 Werner Lemberg - - [sfnt] Improve embedded bitmap tracing. - - * src/base/ftobjs.c (FT_Request_Size): Move trace message regarding - bitmap strike match to... - (FT_Match_Size): This function. - - * src/sfnt/ttsbit.c (tt_sbit_decoder_load_metrics, - tt_sbit_decoder_load_byte_aligned, tt_sbit_decoder_load_bit_aligned, - tt_sbit_decoder_load_compound, tt_sbit_decoder_load_png, - tt_sbit_decoder_load_image): Decorate with tracing messages. - -2013-06-10 Werner Lemberg - - Fix Savannah bug #39160. - - * src/truetype/ttinterp.c (Ins_SDPVTL): Set projection vector too - for the degenerate case. - -2013-06-09 David Turner - - * src/cache/ftcmanag.c (FTC_Manager_Reset): Add missing cache flush. - - This code, present since eight(!) years in the unused `CACHE' - branch, has been forgotten to apply to the master branch. It's - really amazing that noone has ever complained since - `FTC_Manager_Reset' is pretty useless without flushing the cache. - -2013-06-07 Werner Lemberg - - Add and improve pragmas for MSVC compiler. - - * include/freetype/internal/ftdebug.h: Remove pragmas. - * include/freetype/internal/ftserv.h: Use push and pop for pragmas. - * include/freetype/internal/ftvalid.h: Handle warning C4324. - * src/base/ftobjs.c: Use push and pop for pragmas. - * src/gzip/ftgzip.c: Handle warning C4244. - -2013-06-07 Werner Lemberg - - [cff] s/cf2_getGlyphWidth/cf2_getGlyphOutline/. - - * src/cff/cf2font.c, src/cff/cf2font.h, src/cff/cf2ft.c: Do it. - -2013-06-06 Dave Arnold - - [cff] Add early exit feature for width-only calls. - - This is for `FT_Get_Advance'. - - There are 7 places where the spec says the width can be defined: - - hstem/hstemhm - vstem/vstemhm - cntrmask/hintmask - hmoveto - vmoveto - rmoveto - endchar - - * src/cff/cf2intrp.c (cf2_doStems): Exit early for width-only calls, - if possible. - - (cf2_interpT2CharString) , , - , , , - , : Exit early for width-only calls. - -2013-06-06 Werner Lemberg - - Next round of compiler fixes. - - * builds/win32/ftdebug.c, builds/wince/ftdebug.c (ft_debug_init): - Add proper cast. - - * include/freetype/internal/ftserv.h (FT_SERVICE_UNAVAILABLE): Fix - cast. - * include/freetype/internal/ftstream.h: Decorate stream and frame - macros with `FT_Long' and `FT_ULong' as appropriate. - - * src/base/ftrfork.c (raccess_guess_darwin_hfsplus, - raccess_guess_darwin_newvfs): Use cast. - - * src/bdf/bdflib.c (_bdf_set_default_spacing): Use cast. - - * src/cache/ftcmanag.c (FTC_Manager_Check): Fix cast. - * src/cache/ftcmanag.h (FTC_ManagerRec): Ditto. - - * src/cff/cf2arrst.c (cf2_arrstack_setNumElements): Use cast. - * src/cff/cf2ft.c (cf2_freeSeacComponent): Ditto. - * src/cff/cffobjs.c (remove_subset_prefix, remove_style): Ditto. - - * src/cid/cidparse.c (cid_parser_new): Use cast. - - * src/pcf/pcfdrivr.c (PCF_Glyph_Load): Use cast. - - * src/psaux/psobjs.c (reallocate_t1_table): Fix argument type. - - * src/raster/ftraster.c (ft_black_reset): Use cast. - - * src/truetype/ttgxvar.c (FT_Stream_FTell): Use cast. - (ALL_POINTS): Fix cast. - - * src/type1/t1driver.c (t1_ps_get_font_value): Add casts. - * src/type1/t1parse.c (T1_Get_Private_Dict): Add cast. - -2013-06-05 Dave Arnold - - Fix more MSVC Win32 compiler warnings. - - * src/base/ftobjs.c: Fix typo in MS pragma. - - * src/base/bdflib.c (_bdf_set_default_spacing, _bdf_add_property): - `lineno' is only used in debug mode. - - * src/cff/cf2ft.c (cf2_builder_moveTo): `params' is only used in - debug mode. - -2013-06-05 Werner Lemberg - - Fix compiler warnings. - - * include/freetype/internal/ftmemory.h: Decorate memory allocation - macros with `FT_Long' where appropriate. - Remove duplicate of FT_MEM_QRENEW_ARRAY definition. - - * src/base/ftbitmap.c (ft_gray_for_premultiplied_srgb_bgra): Use - cast. - - * src/base/ftobjs.c: Add warning disabling pragma for MSVC while - including `md5.c'. - - * src/cff/cf2intrp.c (cf2_interpT2CharString) : Add - cast. - - * src/sfnt/ttsbit.c (tt_sbit_decoder_load_compound): Fix casts. - (tt_sbit_decoder_load_bitmap): Beautification. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Initialize - variables (earlier). - - * src/truetype/ttgload.c (TT_Process_Simple_Glyph): Pacify compiler. - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Use unsigned constants - where appropriate. - - * src/type1/t1load.c (T1_Get_MM_Var): Ditto. - -2013-06-04 Werner Lemberg - - * src/cff/cf2font.c (cf2_getGlyphWidth): Initialize `advWidth'. - - Problem reported by Ingmar Sittl . - -2013-06-04 Werner Lemberg - - Apply fixes for cppcheck nitpicks. - - https://cppcheck.sourceforge.net/ - - The call was (from the top-level of the FreeType tree): - - cppcheck --force \ - --enable=all \ - -I include \ - -I include/freetype/ \ - -I include/freetype/config/ \ - -I include/freetype/internal/ \ - . &> cppcheck.log - - Note that the current version heavily chokes on FreeType, delivering - many wrong results. I will report those issues to the cppcheck team - so that a newer version gives improved results hopefully. - - */* Improve variable scopes. - */* Remove redundant initializations which get overwritten. - - * src/base/ftmac.c, builds/mac/ftmac.c (count_faces_scalable): - Remove unused variable. - - * src/base/ftdbgmem.c (ft_mem_table_destroy): `table' can't be zero. - - * src/gxvalid/gxvkern.c (gxv_kern_subtable_fmt1_entry_validate): - Remove functionless code. - - * src/tools/ftrandom.c (main): Fix memory leak. - -2013-06-03 Werner Lemberg - - Add CFF_CONFIG_OPTION_OLD_ENGINE configuration option. - - This controls whether the old FreeType CFF engine gets compiled into - FreeType. It is now disabled by default. - - * devel/ftoption.h, include/freetype/config/ftoption.h - (CFF_CONFIG_OPTION_OLD_ENGINE): New macro. - - * src/cff/cffdrivr.c (cff_property_set), src/cff/cffgload.c - (CFF_Operator, cff_argument_counts, cff_builder_add_point, - cff_operator_seac, cff_decoder_parse_charstrings, cff_slot_load), - src/cff/cffgload.h, src/cff/cffobjs.c (cff_driver_init): Use - CFF_CONFIG_OPTION_OLD_ENGINE to guard the affected code. - - * docs/CHANGES: Updated. - -2013-06-02 Werner Lemberg - - Fix PNG library handling. - - * builds/unix/configure.raw: Don't use LIBPNG_LIBS but - LIBPNG_LDFLAGS. - -2013-05-23 Behdad Esfahbod - - Add support for color embedded bitmaps (eg. color emoji). - - A new load flag, FT_LOAD_COLOR, makes FreeType load color - embedded-bitmaps, following this draft specification - - https://color-emoji.googlecode.com/git/specification/v1.html - - which defines two new SFNT tables, `CBDT' and `CBLC' (named and - modeled after `EBDT' and `EBLC', respectively). The color bitmaps - are stored in the new FT_PIXEL_MODE_BGRA format to represent BGRA - pre-multiplied sRGB images. If PNG support is available, PNG color - images as defined in the same proposed specification are supported - also. - - Note that color bitmaps are converted to grayscale if client didn't - ask for color. - - * builds/unix/configure.raw: Search for libpng. - Add `--without-png' option. - - * devel/ftoption.h, include/freetype/config/ftoption.h - (FT_CONFIG_OPTION_USE_PNG): New macro. - - * include/freetype/freetype.h (FT_LOAD_COLOR): New load flag. - - * include/freetype/ftimage.h (FT_Pixel_Mode): Add - `FT_PIXEL_MODE_BGRA'. - - * include/freetype/tttags.h (TTAG_CBDT, TTAG_CBLC): New tags. - - * src/base/ftbitmap.c (FT_Bitmap_Embolden): Updated. - (ft_gray_for_premultiplied_srgb_bgra): New function. - (FT_Bitmap_Convert): Handle FT_PIXEL_MODE_BGRA. - - * src/sfnt/pngshim.c, src/sfnt/pngshim.h: New files. - - * src/sfnt/sfnt.c: Include `pngshim.c'. - - * src/sfnt/ttsbit.c: Include FT_BITMAP_H and `pngshim.h' - (tt_face_load_eblc): Load `CBLC'. - (tt_sbit_decoder_init): Load `CBDT'. - (tt_sbit_decoder_alloc_bitmap): Pass load flags to select between - color and grayscale bitmaps. - Set `num_grays'. This is used by `ftview' to choose the blending - algorithm. - (tt_sbit_decoder_load_byte_aligned, - tt_sbit_decoder_load_bit_aligned, tt_sbit_decoder_load_compound, - tt_sbit_decoder_load_image): Pass load flag. - s/write/pwrite/. - Don't call `tt_sbit_decoder_alloc_bitmap'. - Updated. - (tt_sbit_decoder_load_png) [FT_CONFIG_OPTION_USE_PNG]: New function. - (tt_sbit_decoder_load_bitmap): Pass load flag. - Handle new glyph formats 17, 18, and 19. - Call `tt_sbit_decoder_alloc_bitmap'. - Flatten color bitmaps if necessary. - (tt_face_load_sbit_image): Updated. - - * src/sfnt/rules.mk (SFNT_DRV_SRC): Add `pngshim.c'. - - * docs/CHANGES: Updated. - -2013-05-24 Guenter - - Apply Savannah patch #8055. - - Make `apinames' create an import file for NetWare. - - * src/tools/apinames.c (PROGRAM_VERSION): Set to 0.2. - (OutputFormat): Add `OUTPUT_NETWARE_IMP'. - (names_dump): Handle it. - (usage): Updated. - (main): Handle new command line flag `-wN'. - -2013-05-23 Behdad Esfahbod - - Compilation fix. - - * src/truetype/ttinterp.c (TT_RunIns) - [!TT_CONFIG_OPTION_SUBPIXEL_HINTING]: Make it work. - -2013-05-22 Infinality - - [truetype] Formatting and an additional subpixel tweak. - - * src/truetype/ttinterp.c (Ins_SHPIX): Formatting fix. - * src/truetype/ttsubpix.c (SKIP_NONPIXEL_Y_MOVES_Rules): - Revert previous modification for Verdana clones. - -2013-05-22 Infinality - - [truetype] Adjust subpixel zp2 moves and tweak rules. - - These modifications fix thin diagonal stems in some legacy fonts. - - * src/truetype/ttinterp.c (Direct_Move_X): Remove unused macro. - (Move_Zp2_Point): Don't always disable x moves for subpixel rendering. - (Ins_SHP): Disable x moves here for subpixel rendering. - (Ins_SHPIX): Only disable x moves in compatibility mode. - Split out zp2 move reversals and reorder conditional respectively. - - * src/truetype/ttsubpix.c (SKIP_NONPIXEL_Y_MOVES_Rules): Fix oversight. - Only adjust Verdana clones for 17 ppem. - (SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions): Add Courier New. - (ALWAYS_SKIP_DELTAP_Rules): Found additional cases for Arial `s'. - -2013-05-20 Infinality - - [truetype] Simplify and improve subpixel function detection. - - Some small enhancements have allowed the removal of many macros and - the simplification of existing rules in `ttsubpix.c'. - - * src/truetype/ttsubpix.h (SPH_TWEAK_ALLOW_X_DMOVEX, - SPH_TWEAK_ALLOW_X_MOVE_ZP2, - SPH_TWEAK_DELTAP_SKIP_EXAGGERATED_VALUES, - SPH_TWEAK_SKIP_INLINE_DELTAS, SPH_TWEAK_MIRP_CVT_ZERO): Removed. - (SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP): New rule macro. - - * src/truetype/ttsubpix.c: Updated affected rules. - - * src/truetype/ttinterp.c (Direct_Move_X): Updated. - (INS_FDEF): Add additional function detection. - (INS_ENDF): Set runtime flag. - (Ins_CALL): Skip the call under certain conditions. - Remove bad code. - (Ins_LOOPCALL): Skip the call under certain conditions. - Remove bad code. - (Move_Zp2_Point): Updated. - (Ins_SHPIX): Updated. - Skip the move under some situations. - (Ins_MIAP): Improve conditions. - (Ins_MIRP): Updated. - (Ins_DELTAP): Skip move under certain conditions. - Simplify conditions. - (TT_RunIns): Updated. - Add code to handle new function detection. - Trace messages. - -2013-05-17 Werner Lemberg - - Update more FT_Err_XXX macros using FT_ERR and FT_THROW; - - * builds/amiga/src/base/ftsystem.c, builds/mac/ftmac.c, - builds/unix/ftsystem.c, builds/vms/ftsystem.c: Do it. - -2013-05-15 Werner Lemberg - - [truetype] Add `interpreter-version' property. - - This makes the option TT_CONFIG_OPTION_SUBPIXEL_HINTING controllable - at runtime. - - * include/freetype/ftttdrv.h: New file. - - * include/freetype/config/ftheader.h (FT_TRUETYPE_DRIVER_H): New - macro. - - * src/truetype/ttdriver.c: Include FT_TRUETYPE_DRIVER_H. - (tt_property_set, tt_property_get): Fill templates. - - * src/truetype/ttobjs.h (TT_DriverRec): Add `interpreter_version' - member. - Remove unused `extension_component' member. - - * src/truetype/ttgload.c: Include FT_TRUETYPE_DRIVER_H. - (tt_get_metrics, TT_Hint_Glyph, TT_Process_Simple_Glyph, - compute_glyph_metrics, tt_loader_init): Use `interpreter_version'. - - * src/truetype/ttinterp.c: Include FT_TRUETYPE_DRIVER_H. - (SUBPIXEL_HINTING): New macro to check `interpreter_version' flag. - Update all affected functions to use it. - Use TT_INTERPRETER_VERSION_XXX where appropriate. - - * src/truetype/ttobjs.c: Include FT_TRUETYPE_DRIVER_H. - (tt_driver_init): Initialize `interpreter_version'. - - * src/truetype/ttsubpix.c: Include FT_TRUETYPE_DRIVER_H. - Use TT_INTERPRETER_VERSION_XXX where appropriate. - -2013-05-13 Werner Lemberg - - [truetype] Avoid empty source file. - - * src/truetype/ttsubpix.c [!TT_CONFIG_OPTION_SUBPIXEL_HINTING]: - Provide dummy typedef. - -2013-05-13 Werner Lemberg - - * src/cff/cf2font.c (cf2_getGlyphWidth): Fix uninitialized variable. - - Fix suggested by Vaibhav Nagarnaik . - -2013-05-13 Brian Nixon - - Fix Savannah bug #38970. - - * src/base/ftdebug.c, builds/win32/ftdebug.c, - builds/wince/ftdebug.c, builds/amiga/src/base/ftdebug.c - (ft_debug_init): Don't read past the environment variable FT2_DEBUG. - -2013-05-12 Werner Lemberg - - [truetype] Add framework for TrueType properties. - - * src/truetype/ttdriver.c: Include FT_SERVICE_PROPERTIES_H. - (tt_property_set, tt_property_get): New functions, still empty. - Define `tt_service_properties' service. - Update `tt_services'. - - * src/truetype/ttpic.h: Include FT_SERVICE_PROPERTIES_H. - (TT_SERVICE_PROPERTIES_GET): New macro. - (TTModulePIC): Add `tt_service_properties'. - -2013-05-12 Werner Lemberg - - Fix Savannah bug #38967. - - * src/base/ftcalc.c (FT_DivFix) [FT_LONG64]: Fix cast. - -2013-05-12 Werner Lemberg - - Introduce unsigned 64bit type (if available). - - * include/freetype/config/ftconfig.h: Define FT_UINT64 if available. - [FT_LONG64]: Provide FT_UInt64. - - * builds/unix/ftconfig.in: Synchronized. - -2013-05-12 Werner Lemberg - - Fix Savannah bug #38968. - - * include/freetype/ftmodapi.h: Add `FT_EXPORT' to - FT_Property_{Set,Get}. - * src/base/ftobjs.c: Add `FT_EXPORT_DEF' to - FT_Property_{Set,Get}. - -2013-05-10 Werner Lemberg - - [sfnt] Clean up bitmap code. - - * src/sfnt/ttsbit.c: Deleted. - * src/sfnt/ttsbit0.c: Renamed to `ttsbit.c'. - * rules.mk (SFNT_DRV_H): Updated. - -2013-05-10 Werner Lemberg - - */* [FT_CONFIG_OPTION_OLD_INTERNALS]: Remove macro and guarded code. - ----------------------------------------------------------------------------- - -Copyright (C) 2013-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, modified, -and distributed under the terms of the FreeType project license, -LICENSE.TXT. By continuing to use, modify, or distribute this file you -indicate that you have read the license and understand and accept it -fully. - - -Local Variables: -version-control: never -coding: utf-8 -End: diff --git a/lib/libesp32_lvgl/freetype/ChangeLog.26 b/lib/libesp32_lvgl/freetype/ChangeLog.26 deleted file mode 100644 index a4fc06063..000000000 --- a/lib/libesp32_lvgl/freetype/ChangeLog.26 +++ /dev/null @@ -1,5711 +0,0 @@ -2016-07-12 Werner Lemberg - - * Version 2.6.5 released. - ========================= - - - Tag sources with `VER-2-6-5'. - - This commit immediately follows `[mac] Fix ftexport.sym target in - Jamfile.' on a separate branch, which was then merged with master - after the release. - - * include/freetype/config/ftoption.h - (TT_CONFIG_OPTION_SUBPIXEL_HINTING): Comment out. - - * docs/VERSION.TXT: Add entry for version 2.6.5. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.6.4/2.6.5/, s/264/265/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 5. - - * builds/unix/configure.raw (version_info): Set to 18:5:12. - * CMakeLists.txt (VERSION_PATCH): Set to 5. - - * docs/CHANGES: Updated. - -2016-07-11 Werner Lemberg - - Conditionally compile environment support. - - * include/freetype/internal/ftobjs.h, src/autofit/afmodule.c, - src/base/ftobjs.c, src/cff/cffdrivr.c, src/truetype/ttdriver.c: - Decorate with `FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES' where - necessary. - -2016-07-11 Werner Lemberg - - Handle properties in `FREETYPE_PROPERTIES' environment variable. - - This commit covers the most important one. - - * src/autofit/afmodule.c (af_property_set): Handle `warping', - `darkening-parameters', and `no-stem-darkening'. - - * src/cff/cffdrivr.c (cff_property_set): Handle - `darkening-parameters', `hinting-engine', and `no-stem-darkening'. - - * src/truetype/ttdriver.c (tt_property_set): Handle - `interpreter-version'. - -2016-07-11 Werner Lemberg - - Replace calls to `atol' with `strtol'. - - We later on need strtol's `endptr' feature. - - * include/freetype/config/ftstdlib.h (ft_atol): Replace with... - (ft_strtol): ... this. - - * src/base/ftdbgmem.c (ft_mem_debug_init): Updated. - * src/cid/cidparse.c (cid_parser_new): Ditto. - * src/type42/t42drivr.c (t42_get_name_index), src/type42/t42objs.c - (T42_GlyphSlot_Load): Ditto. - -2016-07-10 Werner Lemberg - - Implement handling of `FREETYPE_PROPERTIES' environment variable. - - Recognizing properties follows in another commit. - - * devel/ftoption.h, include/freetype/config/ftoption.h - (FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES): New macro. - - * include/freetype/config/ftstdlib.h (ft_getenv): New macro. - - * src/base/ftinit.c (ft_set_default_properties): New function to - parse `FREETYPE_PROPERTIES' and calling `ft_property_string_set'. - (FT_Init_FreeType): Updated. - -2016-07-09 Werner Lemberg - - Add function `ft_property_string_set'. - - This is a preparation for handling an `FREETYPE_PROPERTIES' - environment variable to control (some) driver properties. - - No change in functionality. - - * src/base/ftobjs.c (ft_property_do): Add `value_is_string' - parameter. - (ft_property_string_set): New function. - (FT_Property_Set, FT_Property_Get): Updated. - - * include/freetype/internal/ftobjs.h: Updated. - - * include/freetype/internal/services/svprop.h - (FT_Properties_SetFunc): Add `value_is_string' parameter. - - * src/autofit/afmodule.c (af_property_set), src/cff/cffdrivr.c - (cff_property_set), src/truetype/ttdriver.c (tt_property_set): - Updated, emitting an error currently if `value_is_string' is set. - -2016-07-09 suzuki toshiya - - [mac] Fix ftexport.sym target in Jamfile. - - * Jamfile: Update the directories of the header files scanned for - ftexport.sym. They were incorrect since the migration of the - header files, on 2015-06-22. Either inexisting include/cache - (removed on 2006-03-20) is not needed to be listed explicitly. - Now ftmac.h is scanned only in the case of Mac OS & Mac OS X. - -2016-07-08 Alexei Podtelezhnikov - - [smooth] Sub-banding protocol revision. - - Rasterization sub-banding is utilized at large sizes while using a - rather small fixed memory pool. Indeed it is possible to make an - educated guess how much memory is necessary at a given size for a - given glyph. It turns out that, for a large majority of European - glyphs, you should store about 8 times more boundary pixels than - their height. Or, vice versa, if your memory pool can hold 800 - pixels the band height should be 100 and you should sub-band - anything larger than that. Should you still run out of memory, - FreeType bisects the band but you have wasted some time. This is - what has been implemented in FreeType since the beginning. - - It was overlooked, however, that the top band could grow to twice - the default band size leading to unnecessary memory overflows there. - This commit fixes that. Now the bands are distributed more evenly - and cannot exceed the default size. - - Now the magic number 8 is really suitable for rather simple European - scripts. For complex Chinese logograms the magic number should be - 13 but that is subject for another day. - - * src/smooth/ftgrays.c (gray_convert_glyph): Revise sub-banding - protocol. - -2016-07-07 suzuki toshiya - - [mac] Fix Savannah bug #48417. - - Mac OS X linker throws errors when `-exported_symbol_list' input - file includes non-existing symbols. Reported by Ryan Schmidt. - - * builds/exports.mk: Exclude ftmac.h from the headers for apinames - by default. Include it when ftmac.c would be compiled. - -2016-07-06 Werner Lemberg - - * src/truetype/ttinterp.c (TInstruction_Function): Removed, unused. - -2016-07-05 Werner Lemberg - - * Version 2.6.4 released. - ========================= - - - Tag sources with `VER-2-6-4'. - - * docs/VERSION.TXT: Update documentation and bump version number to - 2.6.4. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.6.3/2.6.4/, s/263/264/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 4. - - * builds/unix/configure.raw (version_info): Set to 18:4:12. - * CMakeLists.txt (VERSION_PATCH): Set to 4. - - * docs/CHANGES: Updated. - -2016-07-05 Werner Lemberg - - * src/pfr/pfrsbit.c (pfr_lookup_bitmap_data): Fix compiler warning. - -2016-07-04 Alexei Podtelezhnikov - - [smooth] Variable type revision (part 2). - - * src/smooth/ftgrays.c (TArea): Restore original definition as `int'. - (gray_render_line) [FT_LONG64]: Updated. - (gray_convert_glyph): 32-bit band bisection stack should be 32 bands. - (gray_convert_glyph_inner): Trace successes and failures. - -2016-07-04 Werner Lemberg - - [autofit] Handle single-point contours as segments. - - Doing so allows us to link them to edges – some fonts like - `NotoSansGurmukhi-Regular' have such isolated points sitting exactly - on other outlines. - - * src/autofit/aflatin.c (af_latin_hints_compute_segments): Don't - ignore one-point contours but handle them specially as one-point - segments. - (af_latin_hints_compute_edges): Append one-point segments to edges - if possible. - -2016-07-02 Werner Lemberg - - [autofit] Remove unused structure members. - - * src/autofit/afhints.h (AF_SegmentRec, AF_EdgeRec): Remove - `num_linked'. - - * src/autofit/afcjk.c (af_cjk_hints_link_segments): Updated. - -2016-07-02 Werner Lemberg - - [autofit] Update to Unicode 9.0.0. - - * src/autofit/afranges.c (af_arab_nonbase_uniranges, - af_cyrl_uniranges): Add new data. - -2016-07-01 Alexei Podtelezhnikov - - [smooth] Variable type revision (part 1). - - This patch restores original `TCoord' definition as `int' so that the - rendering pool is used more efficiently on LP64 platforms (unix). - - * src/smooth/ftgrays.c (gray_TWorker, TCell, gray_TBand): Switch some - fields to `TCoord'. - (gray_find_cell, gray_render_scanline, gray_render_line, gray_hline, - gray_sweep, gray_convert_glyph): Updated. - -2016-06-28 Alexei Podtelezhnikov - - [smooth] Minor clean-ups. - - * src/smooth/ftgrays.c (gray_TWorker): Remove redundant `ycount'. - (gray_sweep, gray_convert_glyph, gray_dump_cells): Updated. - -2016-06-27 Alexei Podtelezhnikov - - [smooth] Minor clean-ups. - - * src/smooth/ftgrays.c (gray_convert_glyph): Do not use volatile - qualifier. - (gray_raster_render): Move span initializations from here. - (gray_sweep): ... to here and remove unused `target' argument. - -2016-06-26 Alexei Podtelezhnikov - - [pcf] Fix handling of very large fonts (#47708). - - * src/pcf/pcfread.c (pcf_get_encodings): Make `encodingOffset' an - unsigned short. - Only reject `0xFFFF' as an invalid encoding offset. - -2016-06-25 Werner Lemberg - - [truetype] Really fix deallocation in case of error (#47726). - - * src/truetype/ttgload.c (load_truetype_glyph): Thinko; initialize - `outline.points' also. - -2016-06-23 Alexei Podtelezhnikov - - [smooth] Consolidate memory management. - - * src/smooth/ftgrays.c (gray_init_cells): Remove function. - (gray_TWorker): Remove fields that become local variables. - (gray_raster_render): Move rendering buffer declaration from here. - (gray_convert_glyph): ... to here and update accordingly. - -2016-06-22 Alexei Podtelezhnikov - - [smooth] Consolidate boundary checks. - - Removing the checks from `gray_hline' shaves 1% off rendering speed. - - * src/smooth/ftgrays.c [STANDALONE_]: Duplicate `FT_MIN' and `FT_MAX'. - (gray_TWorker): No need to store `clip_box'. - (gray_hline): Remove unnecessary boundary checks. - (gray_convert_glyph): Move boundary checks from here. - (gray_raster_render): ... to here and consolidate. - -2016-06-21 Alexei Podtelezhnikov - - [smooth] Use `FT_Outline_Get_CBox'. - - * src/smooth/ftgrays.c [STANDALONE_]: Duplicate `FT_Outline_Get_CBox'. - (gray_compute_cbox): Remove this function. - (gray_convert_glyph): Update to use `FT_Outline_Get_CBox'. - -2016-06-20 Werner Lemberg - - [smooth] Remove compiler warnings. - - * src/smooth/ftgrays.c (gray_convert_glyph): Fix reports from clang. - -2016-06-20 Alexei Podtelezhnikov - - [smooth] Sanitize memory management. - - * src/smooth/ftgrays.c (gray_convert_glyph): Cleaned up. - -2016-06-18 Alexei Podtelezhnikov - - [smooth] Remove `band_shoot' that never worked. - - * src/smooth/ftgrays.c (gray_TWorker): Remove `band_shoot'. - (gray_convert_glyph): Updated. - -2016-06-17 Alexei Podtelezhnikov - - [raster, smooth] Handle FT_RENDER_POOL_SIZE better. - - * src/raster/ftraster.c (FT_MAX_BLACK_POOL): New macro. - (ft_black_render): Updated. - * src/smooth/ftgrays.c (FT_MAX_GRAY_POOL): New macro. - (gray_raster_render): Updated. - -2016-06-16 Werner Lemberg - - * src/base/md5.c: Updated to recent version. - -2016-06-14 Alexei Podtelezhnikov - - * src/smooth/ftgrays.c (gray_hline): Optimize if-condition. - -2016-06-13 Werner Lemberg - - [autofit] Add support for Cherokee script. - - * src/autofit/afblue.dat: Add blue zone data for Cherokee. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Cherokee standard characters. - - * src/autofit/afranges.c: Add Cherokee data. - - * src/autofit/afstyles.h: Add Cherokee data. - -2016-06-09 David Capello - - [cmake] Avoid modifying `ftconfig.h' and `ftoption.h' files. - - * CMakeLists.txt: Each time cmake is run those files are - modified and the whole FreeType library is recompiled. With this - change we change the files only if there are real modifications, so - we can avoid recompilations. - -2016-06-09 Werner Lemberg - - [bdf] Check number of properties (#48166). - - * src/bdf/bdflib.c (_bdf_parse_start): Implement. - -2016-06-08 Alexei Podtelezhnikov - - [smooth] Re-enable new line renderer on 64-bit archs. - - * src/smooth/ftgrays.c (gray_render_line): Conditionally re-enable new - implementation, where it is safe from overflows. - -2016-06-08 Alexei Podtelezhnikov - - [smooth] Minor clean-ups. - - * src/smooth/ftgrays.c (gray_dump_cells): Move out of the way. - (gray_render_span): Remove spurious casts and streamline. - -2016-06-07 Werner Lemberg - - [autofit] Add support for Ethiopic script. - - * src/autofit/afblue.dat: Add blue zone data for Ethiopic. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Ethiopic standard characters. - - * src/autofit/afranges.c: Add Ethiopic data. - - * src/autofit/afstyles.h: Add Ethiopic data. - -2016-06-07 Werner Lemberg - - [autofit] Fix compilation with VS2016 (#48126). - - This compiler doesn't recognize the end-of-comment sequence `*/' if - it immediately follows non-ASCII characters. - - * src/autofit/afscript.h: Ensure whitespace before `*/'. - -2016-06-04 Werner Lemberg - - Fix a test for named instances (#48122). - - This was missed while giving negative face indices an extended - meaning. - - * src/base/ftobjs.c (Mac_Read_sfnt_Resource): Implement. - -2016-05-31 Nikolaus Waxweiler - - [truetype] Let SHPIX move points in the twilight zone in v40. - - * src/truetype/ttinterp.c (Ins_SHPIX): Allow SHPIX to move points in - the twilight zone. Otherwise, treat SHPIX the same as DELTAP. - Unbreaks various fonts such as older versions of Rokkitt and DTL - Argo T Light that would glitch severely after calling ALIGNRP after a - blocked SHPIX. - -2016-05-30 Werner Lemberg - - [type42] Support `CharStrings' entry format as created by LilyPond. - - * src/type42/t42parse.c (t42_parse_charstrings): Handle entries - having the format - - (foo) cvn 12345 def - -2016-05-28 Werner Lemberg - - * src/autofit/afranges.c: Remove `UL' postfix from hex numbers. - - Suggested by Alexei. `UL' is only needed for 16bit compilers, but - it seems noone is using this anymore (and we no longer test whether - FreeType compiles in such an environment). Otherwise, it is easy to - add the postfix to the `AF_UNICODE_RANGE' macro. - -2016-05-26 Alexei Podtelezhnikov - - [smooth] Shrink bisection stack. - - The convergence of Bézier flatteners is fast with the deviation - from straight line being asymptotically cut 4-fold on each bisection. - This justifies smaller bisection stack size. - - * src/smooth/ftgrays.c (gray_TWorker): Remove common `bez_stack'. - (gray_render_conic): Create and use conic `bez_stack'. Move back the - band analysis from... - (gray_conic_to): ... here. - (gray_render_cubic): Create and use cubic `bez_stack'. Move back the - band analysis from... - (gray_cubic_to): ... here. - (gray_move_to): Updated. - -2016-05-25 Werner Lemberg - - [autofit] Fixes for Armenian and Gujarati ranges. - - * src/autofit/afranges.c (af_armn_uniranges): Corrected. - (af_guru_nonbase_uniranges): Make U+0A3E a base character. - -2016-05-24 Werner Lemberg - - [autofit] Add support for Armenian script. - - * src/autofit/afblue.dat: Add blue zone data for Armenian. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Armenian standard characters. - - * src/autofit/afranges.c: Add Armenian data. - - * src/autofit/afstyles.h: Add Armenian data. - -2016-05-23 Werner Lemberg - - * builds/unix/unix-cc.in (LINK_LIBRARY): Use `-export-symbols'. - - This was commented about 10 years ago – I think the reason then to - disable libtool's `-export-symbols' option was to give some badly - programmed applications access to internal FreeType functions. - - I believe that we should no longer take care of such programs; the - number of symbols exported should be rather restricted as much as - possible. - -2016-05-22 Werner Lemberg - - [autofit] Add blue-zone support for Gurmukhi script. - - This essentially moves the Gurmukhi script from the `Indic' hinter to - the `Latin' hinter. - - * src/autofit/afblue.dat: Add blue zone data for Gurmukhi. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Gurmukhi standard characters and move - data out of AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afranges.c: Move Gurmukhi data out of - AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afstyles.h: Update Gurmukhi data; in particular, use - AF_WRITING_SYSTEM_LATIN. - -2016-05-21 Werner Lemberg - - Minor clang++ fixes. - - * src/base/ftobjs.c (FT_Add_Module), src/psaux/psobjs.c - (ps_parser_load_field), src/type1/t1load.c (parse_subrs): Add - initializer. - - * src/cache/ftccache.h (FTC_CACHE_TRYLOOP_END): Avoid implicit - conversion from NULL to boolean. - -2016-05-21 Werner Lemberg - - Work around a bug of the C 8.0.0.1 compiler on AIX 5.3 (#47955). - - * include/freetype/internal/ftmemory.h (cplusplus_typeof): Use - braces for `extern "C++"'. - -2016-05-17 Nikolaus Waxweiler - - [truetype] Make TT_LOADER_SET_PP support subpixel hinting [3/3]. - - * src/truetype/ttgload.c (TT_LOADER_SET_PP): Replace macro with... - (tt_loader_set_pp): ... this new function. - Update all callers. - -2016-05-17 Nikolaus Waxweiler - - [truetype] New implementation of v38 bytecode interpreter [2/3]. - - This patch actually modifies the bytecode interpreter. - - See added comments in `ttinterp.h' for more information on this and - the following commit in the series. - - * src/truetype/ttinterp.c (SUBPIXEL_HINTING): Replaced by... - (NO_SUBPIXEL_HINTING, SUBPIXEL_HINTING_INFINALITY, - SUBPIXEL_HINTING_MINIMAL): ...new macros. - (Direct_Move, Direct_Move_X, Direct_Move_Y): Handle backward - compatibility. - Updated. - (Ins_RS, Ins_FDEF, Ins_ENDF, Ins_CALL, Ins_LOOPCALL, Ins_MD): - Updated. - (Ins_INSTCTRL): Handle native ClearType mode flag. - Updated. - (Ins_FLIPPT, Ins_FLIPRGON, Ins_FLIPRGOFF): Handle backward - compatibility. - (Move_Zp2_Point): Ditto. - (Ins_SHP): Updated. - (Ins_SHPIX): Handle backward compatibility. - Updated. - (Ins_MSIRP, Ins_MDAP, Ins_MIAP, Ins_MDRP, Ins_MIRP): Updated. - (Ins_ALIGNRP): Updated. - (Ins_IUP, Ins_DELTAP): Handle backward compatibility. - Updated. - (Ins_GETINFO): Handle v38 flags. - Updated. - (TT_RunIns): Handle backward compatibility mode. - Updated. - -2016-05-17 Nikolaus Waxweiler - - [truetype] New implementation of v38 bytecode interpreter [1/3]. - - This patch prepares data structures and the like. - - See added comments in `ttinterp.h' for more information on this and - the following commits in the series. - - * devel/ftoption.h, include/freetype/config/ftoption.h - (TT_CONFIG_OPTION_SUBPIXEL_HINTING): Assign values to differentiate - between subpixel versions. - (TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY, - TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL): New macros. - - * include/freetype/ftttdrv.h (TT_INTERPRETER_VERSION_40): New macro. - - * include/freetype/internal/tttypes.h (TT_FaceRec): Updated. - - * src/truetype/ttinterp.h (TT_ExecContextRec): Define new fields - `subpixel_hinting_lean', `vertical_lcd_lean', - `backward_compatibility', `iupx_called', iupy_called', and - `grayscale_cleartype' for new hinting mode. - - * src/truetype/ttdriver.c (tt_property_set): Handle v38 and v40 - interpreters conditionally. - - * src/truetype/ttgload.c (TT_Hint_Glyph): Save phantom points unless - in v38 backward compatibility mode. - Updated. - (compute_glyph_metrics): Add v38 backward compatibility mode - constraint for adjusting advance widths. - Updated. - (tt_loader_init): Handle new flags `subpixel_hinting_lean', - `grayscale_cleartype', and `vertical_lcd_lean'. - Updated. - (tt_get_metrics, TT_Process_Simple_Glyph, TT_LOADER_SET_PP): - Updated. - - * src/truetype/ttobjs.c (tt_driver_init): Conditionally set - default interpreter version number. - - * src/truetype/ttsubpix.c, src/truetype/ttsubpix.h: Updated. - -2016-05-17 Werner Lemberg - - [cff] Fix matrix scaling (#47848). - - * include/freetype/config/ftstdlib.h (FT_LONG_MIN): New macro. - - * src/cff/cffparse.c (cff_parse_font_matrix): Use largest scaling - value of all matrix coefficients to scale matrix. - - * src/cff/cffobjs.c (cff_face_init): Use `matrix->yx' member for - matrix normalization if `matrix->yy' is zero. - -2016-05-16 Werner Lemberg - - [base] Reject invalid sfnt Mac resource (#47891). - - * src/base/ftobjs.c (open_face_PS_from_sfnt_stream): Check validity - of `CID ' and `TYPE1' table offset and length. - -2016-05-16 Werner Lemberg - - [cid] Fix scanning for `StartData' and `/sfnts' (#47892). - - * src/cid/cidparse.c (STARTDATA, STARTDATA_LEN, SFNTS, SFNTS_LEN): - New macros. - (cid_parser_new): Fix and document algorithm. - -2016-05-16 suzuki toshiya - - [truetype] Improve the recursive reference detector. - - The previous fix for #46372 misunderstood a composite glyph referring - same component twice as a recursive reference. See the discussion - - https://lists.gnu.org/archive/html/freetype/2016-05/msg00000.html - - Thanks to Khaled Hosny for finding this issue. - - * src/truetype/ttgload.c (ft_list_get_node_at): A function to get - the i-th node from FT_List. - (load_truetype_glyph): In the traversal scan of the reference tree - in the composite glyph, we clear the nodes filled by previous - sibling chain. - -2016-05-07 Werner Lemberg - - [cache] Allow value 0 for face ID. - - We never dereference `face_id', and some implementations might use a - running number instead of a pointer. Additionally, disallowing - value zero was undocumented. - - * src/cache/ftccmap.c (FTC_CMapCache_Lookup), src/cache/ftcmanag.c - (FTC_Manager_LookupFace, FTC_Manager_RemoveFaceID): Remove test for - `face_id'. - -2016-05-05 Alexei Podtelezhnikov - - [smooth] More efficient accounting of conic splits and draws. - - A single decrement counter of segments to draw, instead of an array, - contains all the information necessary to decide when to split and - when to draw a conic segment. The number of splits before each draw is - equal to the number of trailing zeros in the counter. - - * src/smooth/ftgrays.c (gray_TWorker): Remove `lev_stack'. - (gray_render_conic): Updated to use decrement counter of segments. - -2016-05-05 Werner Lemberg - - [cff, truetype] Fix logic for `FT_Property_Set'. - - Otherwise some properties could be set to arbitrary values, which is - harmless, but querying could give wrong positive results. - - * src/cff/cffdrivr.c (cff_property_set) [hinting-engine], - * src/truetype/ttdriver.c (tt_property_set) [interpreter-version]: - Only allow defined values. - -2016-04-25 Werner Lemberg - - [autofit] Add blue-zone support for Gujarati script. - - This essentially moves the Gujarati script from the `Indic' hinter to - the `Latin' hinter. - - * src/autofit/afblue.dat: Add blue zone data for Gujarati. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Gujarati standard characters and move - data out of AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afranges.c: Move Gujarati data out of - AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afstyles.h: Update Gujarati data; in particular, use - AF_WRITING_SYSTEM_LATIN. - -2016-04-24 Werner Lemberg - - Minor. - - * include/freetype/freetype.h (FT_HAS_*, FT_IS_*): Protect macro - argument with parentheses. - -2016-04-24 Werner Lemberg - - [truetype] Fix deallocation in case of error (#47726). - - * src/truetype/ttgload.c (load_truetype_glyph): Initialize fields in - `outline' that are going to be deallocated in case of error. - -2016-04-23 Werner Lemberg - - [autofit] Improve Georgian blue zone characters. - - Suggested by Akaki Razmadze . - - * src/autofit/afblue.dat (AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM): - Updated. - - * src/autofit/afblue.c: Regenerated. - -2016-04-16 David Capello - - [cmake] Honor SKIP_INSTALL_* settings (as used in zlib). - - As FreeType depends on zlib, if we don't install zlib (e.g., because - we defined SKIP_INSTALL_ALL), FreeType cannot be installed, too - (cmake triggers an error saying that FreeType cannot be installed - because zlib target isn't in the export set). - - * CMakeLists.txt: Honor `SKIP_INSTALL_HEADERS', - `SKIP_INSTALL_LIBRARIES', and `SKIP_INSTALL_ALL' settings. - -2016-04-16 Behdad Esfahbod - - [truetype] Another fix for non-intermediate GX tuples. - - * src/truetype/ttgxvar.c (ft_var_apply_tuple): Add some missing - cases. - -2016-04-12 Alexei Podtelezhnikov - - Remove forgotten macro. - - * include/freetype/internal/internal.h - [FT_INTERNAL_POSTSCRIPT_GLOBALS_H]: Remove. - -2016-04-09 Werner Lemberg - - [autofit] Add support for Georgian scripts. - - Georgian is problematic, since `uppercase' forms of Mkhedruli - (called Mtavruli) are not yet defined in Unicode, which means that - proper blue zones can't be defined. However, there is already a - proposal submitted to Unicode; see - - https://www.unicode.org/L2/L2016/16034-n4707-georgian.pdf - - Additionally, due to historical reasons, Unicode treats Khutsuri as - the same script as Mkhedruli, and so does OpenType. However, since - the two scripts have completely different shapes it can happen that - blue zones differ considerably. The tag `geok' used here (derived - from ISO 15924) to differentiate the two scripts is not an OpenType - tag in use. If we now have a font that contains both glyphs for - Mkhedruli and Khutsuri, and it uses OpenType features for both also, - HarfBuzz unavoidably treats all glyphs as `geor'. As a consequence, - blue zones for `geok' are not used for glyphs involved in the - OpenType features. - - An issue not yet resolved is which OpenType feature should be used - to access Mtavruli glyph shapes; right now, FreeType doesn't set up - support for them, but it is easy to add them later on as soon as - more information is available. - - * src/autofit/afblue.dat: Add blue zone data for Georgian. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Georgian standard characters. - - * src/autofit/afranges.c: Add Georgian data. - - * src/autofit/afstyles.h: Add Georgian data. - -2016-04-05 Werner Lemberg - - [autofit] Provide dummy blue zone for pseudo script `none'. - - Even if the dummy hinter is used as the handler for `none' (which - doesn't use blue zones), it is more consistent than the old value - (which was 0), pointing to Arabic... - - * src/autofit/afblue.dat: Add `AF_BLUE_STRINGSET_NONE'. - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afstyles.h (none_dflt): Use AF_BLUE_STRINGSET_NONE. - -2016-03-30 Werner Lemberg - - * src/pfr/pfrload.c (pfr_aux_name_load): Thinko (#47567). - -2016-03-30 Werner Lemberg - - * src/pfr/pfrload.c (pfr_log_font_count): Better font size estimate. - -2016-03-30 Werner Lemberg - - * src/pfr/pfrload.c (pfr_aux_name_load): Fix memory leak (#47567). - -2016-03-29 Werner Lemberg - - * src/base/ftadvanc.c (FT_Get_Advances): Fix invalid left shift. - -2016-03-29 Werner Lemberg - - [pfr] Fix binary search (#47514). - - * src/pfr/pfrsbit.c (pfr_lookup_bitmap_data): Handle border - conditions correctly. - -2016-03-29 Werner Lemberg - - [pfr] Minor. - - * src/pfr/pfrsbit.c (pfr_lookup_bitmap_data): Replace `left', - `right', and `middle' with `min', `max', and `mid' as used in other - FreeType binary search code. - (pfr_load_bitmap_metrics): Fix invalid left shift. - -2016-03-29 Werner Lemberg - - * src/pfr/pfrtypes.h: Replace all enums with macros. - - We need `~FOO' to unset bits, and only with unsigned values (which - `enum' isn't normally) this works cleanly. - -2016-03-26 Werner Lemberg - - [pfr] Robustify bitmap strike handling (#47514). - - We did a binary search for a charcode without ensuring that the - searched data is ordered. Validating the order is now done lazily, - this is, the first access to a bitmap glyph triggers the order check - in the corresponding bitmap strike. - - * src/pfr/pfrtypes.h (PFR_BitmapFlags): New values - `PFR_BITMAP_VALID_CHARCODES' and `PFR_BITMAP_CHARCODES_VALIDATED'. - - * src/pfr/pfrsbit.c (pfr_lookup_bitmap_data): Make `flags' argument - a pointer. Handle new PFR_BITMAP_XXX flags. - (pfr_slot_load_bitmap): Updated. - -2016-03-26 Werner Lemberg - - [pfr] Fix handling of compound glyphs. - - Extra items are indicated with different bit positions. - - * src/pfr/pfrtypes.h (PFR_GlyphFlags): Replace - `PFR_GLYPH_EXTRA_ITEMS' with `PFR_GLYPH_SIMPLE_EXTRA_ITEMS' and - `PFR_GLYPH_COMPOUND_EXTRA_ITEMS'. - - * src/pfr/pfrgload.c (pfr_glyph_load_simple, - pfr_glyph_load_compound): Use them. - -2016-03-25 Werner Lemberg - - [pfr] Minor. - - * src/pfr/pfrsbit.c, src/pfr/pfrobjs.c: Use flag names instead of - bare numbers. - -2016-03-25 Werner Lemberg - - [pfr] Various clang sanitizer fixes. - - * src/pfr/pfrsbit.c (pfr_load_bitmap_metrics): Correctly handle - signed nibbles. - (pfr_slot_load_bitmap): Correctly exit frame in case of error. - Fix invalid left shifts. - -2016-03-23 Werner Lemberg - - Rename `VERSION.DLL' (#47472). - - * docs/VERSION.DLL: Renamed to... - * docs/VERSIONS.TXT: ...this. - -2016-03-23 Werner Lemberg - - [raster, smooth] Directly test outline size (#47500). - - This improves stand-alone compilation. - - * src/base/ftoutln.c (FT_Outline_Render): Move cbox size test to... - - * src/raster/ftraster.c (ft_black_render), src/smooth/ftgrays.c - (gray_raster_render): ...these functions. - -2016-03-23 Werner Lemberg - - [raster, smooth] Fix some clang sanitizer runtime issues. - - * src/raster/ftraster.c (ft_black_reset, ft_black_set_mode, - ft_black_render): Harmonize signatures with `ftimage.h'. - - * src/smooth/ftgrays.c (gray_raster_render, gray_raster_reset): - Ditto. - -2016-03-22 Werner Lemberg - - * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Minor. - - This fixes an AddressSanitizer issue: - - ttgload.c:430:7: runtime error: null pointer passed as argument 1, - which is declared to never be null - -2016-03-21 Werner Lemberg - - * src/autofit/afhints.c (af_glyph_hints_reload): Thinko. - - This fixes the previous commit to this file. - -2016-03-21 Alexei Podtelezhnikov - - [smooth] Partly revert recent changes. - - * src/smooth/ftgrays.c (gray_conic_to, gray_cubic_to): Rework - conditions to fix rendering issues. - -2016-03-20 Werner Lemberg - - [autofit] Show `near' points in tracing. - - * src/autofit/afhints.h (AF_FLAG_NEAR): New macro. - - * src/autofit/afhints.c (af_glyph_hints_dump_points): Implement it. - (af_glyph_hints_reload): Handle AF_FLAG_NEAR. - -2016-03-18 Alexei Podtelezhnikov - - [smooth] Minor refactoring and microoptimizations. - - * src/smooth/ftgrays.c (gray_render_conic, gray_render_cubic): Move - band clipping from here. - (gray_conic_to, gray_cubic_to): ... to here. - (gray_render_line, gray_render_scanline): Initialize variables closer - to their use. - -2016-03-17 Alexei Podtelezhnikov - - [smooth] Minor refactoring. - - * src/smooth/ftgrays.c (gray_render_conic, gray_render_cubic): Move - upscaling from here. - (gray_conic_to, gray_cubic_to): ... to here. - -2016-03-15 Werner Lemberg - - * src/autofit/aflatin.c (af_latin_compute_stem_width): Optimize. - -2016-03-14 Alexei Podtelezhnikov - - [smooth] Temporarily revert 6eb6158dd787 (#47114). - - * src/smooth/ftgrays.c (gray_render_line): Old implementation. - -2016-03-12 Werner Lemberg - - [ftfuzzer] Improve coverage of rasterfuzzer. - - * src/tools/ftfuzzer/rasterfuzzer.cc (LLVMFuzzerTestOneInput): Use - input data for `tags' array also. - Trim input data to get more positive hits. - -2016-03-11 Pavlo Denysov - - Fix CMake issues for iOS (patch #8941). - - * CMakeLists.txt (CMAKE_TOOLCHAIN_FILE): Fix directory. - * builds/cmake/iOS.cmake: No longer enforce gcc. - -2016-03-09 Behdad Esfahbod - - [truetype] Fix handling of non-intermediate GX tuples. - - We probably did not notice this as all fonts we tested had only - tuple_coords[i] be +1 or -1 for non-intermediate tuples. - - * src/truetype/ttgxvar.c (ft_var_apply_tuple): Implement it. - -2016-03-06 Alexei Podtelezhnikov - - [base] Refuse to render enormous outlines (#47114). - - The goal is to avoid integer overflows in the rendering algorithms. - The limit is chosen arbitrarily at some 2^18 pixels, which should be - enough for modern devices including printers. - - * src/base/ftoutln.c (FT_Outline_Render): Check CBox and reject - enormous outlines. - -2016-03-06 Alexei Podtelezhnikov - - [smooth] Replace left shifts with multiplications (#47114). - - * src/smooth/ftgrays.c (SUBPIXELS, UPSCALE, DOWNSCALE): Do it. - -2016-03-05 Werner Lemberg - - [autofit] Avoid excessive stem length rounding (#25392). - - * src/autofit/aflatin.c (af_latin_compute_stem_width): Add argument - to pass difference between hinted and unhinted position of base - point; use this to adjust the stem width depending on the PPEM so - that it doesn't become too large under certain circumstances. - Update all callers using value 0 for this argument except... - (af_latin_align_linked_edge): Pass position delta of base point to - `af_latin_compute_stem_width'. - -2016-03-05 J Raynor - - Make FreeType compile on AIX out of the box. - - * builds/unix/configure.raw (XX_ANSIFLAGS): Don't use `-ansi' on - AIX. - -2016-03-01 Werner Lemberg - Kostya Serebryany - - [ftfuzzer] Add unit for testing smooth and black rasterizers. - - * src/tools/ftfuzzer/rasterfuzzer.cc: New file. - -2016-03-01 Werner Lemberg - - [autofit] Fix reallocation error introduced in 2016-02-27 (#47310). - - * src/autofit/aflatin.c (af_latin_hints_compute_segments): Reassign - `prev_segment' after reallocation. - -2016-03-01 Werner Lemberg - - Fix clang warnings. - - * src/autofit/aflatin.c (af_latin_hints_compute_segments): Use - FT_UShort for `min_flags' and `max_flags'. - Initialize `prev_*' variables. - - * src/cff/cffobjs.c (cff_face_init) [FT_DEBUG_LEVEL_TRACE]: Fix - types of local variables. - - * src/smooth/ftgrays.c (gray_dump_cells) [FT_DEBUG_LEVEL_TRACE]: - Update `printf' format string. - - * src/tools/ftfuzzer/ftfuzzer.cc (setIntermediateAxis): Add cast. - (LLVMFuzzerTestOneInput): Fix loop type. - -2016-02-29 Werner Lemberg - - [autofit] Add blue-zone support for Sinhala script. - - This essentially moves the Sinhala script from the `Indic' hinter to - the `Latin' hinter. - - * src/autofit/afblue.dat: Add blue zone data for Sinhala. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Sinhala standard character and move data - out of AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afranges.c: Move Sinhala data out of - AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afstyles.h: Update Sinhala data; in particular, use - AF_WRITING_SYSTEM_LATIN. - -2016-02-27 Werner Lemberg - - [autofit] Properly handle spikes pointing to the x-axis. - - An example that gets better rendered is glyph `uusignTaml' (glyph - index 2286) in font `FreeSerif.ttf' (Version 0412.2263) at 22ppem. - - * src/autofit/aflatin.c (af_latin_hints_compute_segments): Properly - handle segments where the last point of the first segment is - identical to the first point in the second one. This can happen for - malformed fonts or spikes. We either merge the new segment with the - previous one (both segments point into the same direction), or we - discard the shorter segment if they point into different directions. - -2016-02-27 Werner Lemberg - - [autofit] Minor code clean-up. - - * src/autofit/aflatin.c (af_latin_hints_compute_segments): Change - some local variable names to better differentiate between values - along a segment and values orthogonal to it. - -2016-02-26 Werner Lemberg - - [autofit] Improve BOUND action. - - In complex glyph shapes, the original logic was too simple to cater - for situations that would actually need something similar to PS Hint - masks. This fix should alleviate the worst cases. - - * src/autofit/aflatin.c (af_latin_hint_edges): Don't allow - complete disappearance of stems. - -2016-02-25 Werner Lemberg - - [autofit] Add blue-zone support for Tamil script. - - This essentially moves the Tamil script from the `Indic' hinter to - the `Latin' hinter. - - * src/autofit/afblue.dat: Add blue zone data for Tamil. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Tamil standard character and move data - out of AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afranges.c: Move Tamil data out of - AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afstyles.h: Update Tamil data; in particular, use - AF_WRITING_SYSTEM_LATIN. - -2016-02-18 Werner Lemberg - - [autofit] Add blue-zone support for Malayalam script. - - This essentially moves the Malayalam script from the `Indic' hinter - to the `Latin' hinter. - - * src/autofit/afblue.dat: Add blue zone data for Malayalam. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Malayalam standard characters and move - data out of AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afranges.c: Move Malayalam data out of - AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afstyles.h: Update Malayalam data; in particular, use - AF_WRITING_SYSTEM_LATIN. - -2016-02-16 Alexei Podtelezhnikov - - [smooth] Fix integer overflow (#47114). - - * src/smooth/ftgrays.c (TArea): Make it unconditionally `long'. - -2016-02-15 Werner Lemberg - - * src/cff/cffparse.c (cff_parse_multiple_master): Improve tracing. - -2016-02-15 Werner Lemberg - - [cff] Handle T2 operator only with old CFF engine (#47157). - - * src/cff/cffparse.c (cff_parser_run) : Enclose with - #ifdef CFF_CONFIG_OPTION_OLD_ENGINE...#endif. - -2016-02-15 Werner Lemberg - - [cff] Partially handle `load' and `store' ops in old CFF engine. - - Now all glyphs of MM CFFs like `ITCGaramondMM-It.otf' can be - displayed. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings) : Partially implement it. - - * src/cff/cffparse.c (cff_parser_init): Add new parameter to pass - the number of Multiple Master axes. - Update all callers. - (cff_parse_multiple_master): Get number of axes. - (cff_parser_run) : Updated. - * src/cff/cffparse.h: Updated. - (CFF_ParserRec): Add `num_axes' field. - - * src/cff/cffload.c: Updated. - - * src/cff/cfftypes.h (CFF_FontRecDictRec): Add `num_axes' field. - -2016-02-15 Werner Lemberg - - [cff] Correctly trace SIDs that contain NULL bytes. - - We need this to properly trace Multiple Master CFFs, which contain - two SIDs that are charstrings. - - This commit makes FreeType also show the last SID, omitted - previously due to a bug. - - * src/cff/cfftypes.h (CFF_FontRec): Add `string_pool_size' field. - - * src/cff/cffload.c (cff_index_get_pointers): Add argument to return - the pool size. - Update all callers. - - * src/cff/cffobjs.c (cff_face_init) [FT_DEBUG_LEVEL_TRACE]: Directly - access `cff->strings' to display the non-default strings. - -2016-02-14 Werner Lemberg - - * src/base/fthash.c: Include FT_INTERNAL_MEMORY_H. - -2016-02-14 Werner Lemberg - - * src/cff/cffparse.c: Include `cffgload.h'. - - Problem reported by Colin Walters . - -2016-02-14 Werner Lemberg - - [cff] Make old CFF engine show MM CFFs (without variations). - - The new code only displays the first master in the font. - - * src/cff/cffgload.c (cff_decode_parse_charstrings): Add new - parameter to allow function calls from dictionaries also. - : Partially implement it. - Update all callers. - * src/cff/cffgload.h: Updated. - - * src/cff/cffparse.c (cff_parser_init): Add new parameter to pass the - number of Multiple Master designs. - Update all callers. - (cff_parse_multiple_master): New function to rudimentarily parse - operator. - (cff_parser_run): Handle `T2' operator. - * src/cff/cffparse.h: Updated. - (CFF_ParserRec): Add `num_designs' field. - - * src/cff/cffload.c: Updated. - - * src/cff/cfftoken.h: Handle `MultipleMaster' operator. - - * src/cff/cfftypes.h (CFF_FontRecDictRec): Add `num_designs' field. - - * src/sfnt/sfobjs.c (sfnt_init_face): Don't handle `fvar' table for - MM CFFs. - -2016-02-09 Werner Lemberg - - [docmaker] Don't emit trailing newlines. - - * src/tools/docmaker/tohtml.py (HtmlFormatter::make_html_code): - Use `rstrip'. - -2016-02-07 Werner Lemberg - - * Version 2.6.3 released. - ========================= - - - Tag sources with `VER-2-6-3'. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.6.3. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.6.2/2.6.3/, s/262/263/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 3. - - * builds/unix/configure.raw (version_info): Set to 18:3:12. - * CMakeLists.txt (VERSION_PATCH): Set to 3. - - * docs/CHANGES: Updated. - -2016-02-07 Werner Lemberg - - Fix another runtime error found by clang's sanitizer (#47082). - - * src/base/ftstroke.c (ft_stroke_border_export): Properly handle - empty input buffer. - -2016-02-07 Werner Lemberg - - Fix runtime errors found by clang's sanitizer (#47082). - - * src/base/ftobjs.c (FT_Render_Glyph_Internal), src/base/ftoutln.c - (FT_Outline_Copy), src/cache/ftcsbits.c (ftc_sbit_copy_bitmap): - Properly handle empty input buffer. - -2016-02-07 Werner Lemberg - - [cff] Minor. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings) : - Remove dead code. - -2016-02-07 Werner Lemberg - - [cff] Implement missing operators in new engine (except `random'). - - * src/cff/cf2font.h (CF2_STORAGE_SIZE): New macro. - - * src/cff/cf2intrp.c (cf2_interpT2CharString): Implement the - following operators: abs, add, and, div, drop, dup, eq, exch, get, - ifelse, index, mul, neg, not, or, put, roll, sqrt, sub. - - * src/cff/cf2stack.h, src/cff/cf2stack.c (cf2_stack_roll): New - auxiliary function for `roll' operator. - -2016-02-06 Werner Lemberg - - [cff] Fix some Type 2 operators in old CFF engine. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings): Fix `eq' - operator, add `not' and (unsupported) `blend' operators. - -2016-02-05 Sebastian Rasmussen - - Make direct call of `make install' work (#47072). - - * builds/unix/unix-def.in (freetype-config): Make sure - `freetype-config' is generated for both make targets (`all' and - `install'). - -2016-02-05 Werner Lemberg - - [base] Fix advance width loading for MM and GX fonts (#47064). - - * src/base/ftadvanc.c (LOAD_ADVANCE_FAST_CHECK): Return false for - MM and GX fonts. - Update callers. - -2016-02-03 Werner Lemberg - - [cff] Fix handling of face_index == -1 for pure CFF. - - * src/cff/cffobjs.c (cff_face_init): Return correct number of faces. - -2016-01-30 Werner Lemberg - - [autofit] Minor tracing improvement. - - * src/autofit/afhints.c (af_glyph_hints_dump_points): Insert newline - at the start of a new contour. - -2016-01-28 Nikolaus Waxweiler - - Remove unpatented hinter (3/3). - - * include/freetype/config/ftoption.h - (TT_CONFIG_OPTION_UNPATENTED_HINTING): Remove. - - * include/freetype/internal/ftobjs.h (FT_Face_InternalRec): Remove - `ignore_unpatented_hinter' field. - Update users. - (FT_DEBUG_HOOK_UNPATENTED_HINTING): Remove. - Update users. - - * include/freetype/internal/tttypes.h (TT_FaceRec): Remove - `unpatented_hinting' field. - Update users. - - * src/base/ftpatent.c (_tt_check_patents_in_range, - _tt_check_patents_in_table, _tt_face_check_patents): Remove. - (FT_Face_CheckTrueTypePatents, FT_Face_SetUnpatentedHinting): - Replace code with dummies. - - * src/truetype/ttobjs.c (tt_face_init): Remove now defunct code. - * src/truetype/ttobjs.h (TT_GraphicsState): Remove `both_x_axis' - field. - -2016-01-28 Nikolaus Waxweiler - - Remove unpatented hinter (2/3). - - * devel/ftoption.h (TT_CONFIG_OPTION_UNPATENTED_HINTING): Remove. - -2016-01-28 Nikolaus Waxweiler - - Remove unpatented hinter (1/3). - - * src/truetype/ttinterp.c [TT_CONFIG_OPTION_UNPATENTED_HINTING]: - Remove all code related to this macro. - -2016-01-28 Werner Lemberg - - [autofit] Add blue-zone support for Kannada script. - - This essentially moves the Kannada script from the `Indic' hinter to - the `Latin' hinter. - - * src/autofit/afblue.dat: Add blue zone data for Kannada. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Kannada standard characters and move - data out of AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afranges.c: Move Kannada data out of - AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afstyles.h: Update Kannada data; in particular, use - AF_WRITING_SYSTEM_LATIN. - -2016-01-22 Alexei Podtelezhnikov - - Better access to 64-bit integers for C99 compilers. - - * include/freetype/config/ftconfig.h [FT_LONG64]: Use - __STDC_VERSION__ to define 64-bit integers. - * builds/unix/ftconfig.in [FT_LONG64]: Ditto. - * builds/vms/ftconfig.h [FT_LONG64]: Ditto. - -2016-01-21 Werner Lemberg - - [gxvalid] Remove commented out code. - - * src/gxvalid/gxvcommn.c (gxv_EntryTable_validate): Do it. - -2016-01-20 Werner Lemberg - - [autofit] Complete last autofit commit. - - Problem reported by Kostya Serebryany . - - * src/autofit/afshaper.c (af_shaper_get_coverage) - [!FT_CONFIG_OPTION_USE_HARFBUZZ]: Update signature. - -2016-01-20 Werner Lemberg - - Still handle `__FTERRORS_H__'. - - We need this for backward compatibility. - - Problem reported by John Emmas . - - * include/freetype/fterrors.h: Fix inclusion guard so that - undefining either `FTERRORS_H_' or `__FTERRORS_H__' works as - expected. - -2016-01-19 Werner Lemberg - - [autofit] Fix handling of default script. - - Patch taken from ttfautohint, commit - 071ae2c00e0d67f9d19418f4fade1c23d27dc185. - - There were two bugs. - - - We now use non-standard script tags like `khms' for special - purposes. However, HarfBuzz maps such tags to `DFLT', and - without this commit the associated lookups were incorrectly - assigned to the non-standard tags. - - - Let's assume we have a Bengali font, and the font's `DFLT' - script tag handles the necessary lookups for Bengali, too. - Without this commit, the `DFLT' lookups were assigned to - ttfautohint's default script (usually `latn') before the - standard lookups for Bengali were handled. - - We now have the following order while searching for covered - glyph indices. - - special features of scripts (e.g. `sups' for Cyrillic) - Unicode mappings of scripts - remaining features of scripts (especially important for Indic - scripts) - default features of default script - - * src/autofit/afshaper.c, src/autofit/afshaper.h - (af_shaper_get_coverage): Add boolean parameter to indicate default - script. - Update all callers. - - * src/autofit/afglobal.c (af_face_globals_compute_style_coverage): - Fix search order for coverages. - -2016-01-19 Werner Lemberg - - Various minor clang fixes. - - * src/autofit/afcjk.c (af_cjk_metrics_init_widths), - src/autofit/aflatin.c (af_latin_metrics_init_widths): Initialize - `ch'. - - * src/base/ftcalc.c (FT_MulFix) [FT_LONG64]: Add cast. - - * src/base/ftdbgmem.c (ft_mem_table_destroy): Add cast. - - * src/base/fthash.c (hash_num_lookup): Add cast. - - * src/base/fttrigon.c (ft_trig_downscale) [FT_LONG64]: Fix cast. - - * src/gxvalid/gxvcommn.c (gxv_EntryTable_validate): Comment out - redundant code. - - * src/type1/t1driver.c (t1_get_ps_font_value) : Add - cast. - - * src/type1/t1load.c (parse_subrs): Fix type of `count'. - -2016-01-19 Derek B. Noonburg - - [truetype] Add another tricky font. - - * src/truetype/ttobjs.c (TRICK_SFNT_IDS_NUM_FACES): Increase. - (sfnt_id): Add variant of `DFKaiShu'. - -2016-01-14 Alexei Podtelezhnikov - - [base] Empower `FT_Library_SetLcdFilterWeights'. - - * src/base/ftlcdfil.c (FT_Library_SetLcdFilterWeights): Enable filter - in addition to setting weights. - (FT_Library_SetLcdFilter): Clean out FT_FORCE_LIGHT_LCD_FILTER and - FT_FORCE_LEGACY_LCD_FILTER. - * include/freetype/ftlcdfil.h: Documentation update. - -2016-01-12 Werner Lemberg - - Don't use macro names that start with `_[A-Z]' [3/3]. - - Such macro names are reserved for both C and C++. - - * src/cache/ftccache.h: s/_FTC_FACE_ID_HASH/FTC_FACE_ID_HASH/. - Update all callers. - (FTC_CACHE_LOOKUP_CMP): Replace `_XXX' with `XXX_'. - * src/cache/ftcmru.c (FTC_MRULIST_LOOKUP_CMP): Ditto. - -2016-01-12 Werner Lemberg - - Don't use macro names that start with `_[A-Z]' [2/3]. - - Such macro names are reserved for both C and C++. - - * include/freetype/ftimage.h, src/raster/ftraster.c, - src/smooth/ftgrays.c, src/smooth/ftgrays.h: - s/_STANDALONE_/STANDALONE_/. - -2016-01-12 Werner Lemberg - - Don't use macro names that start with `_[A-Z]' [1/3]. - - Such macro names are reserved for both C and C++. - - * src/bdf/bdflib.c: Replace macros of the form `_BDF_XXX' with - `BDF_XXX_'. - -2016-01-12 Werner Lemberg - - Don't use macro names that contain `__' [2/2]. - - Such macro names are reserved for both C and C++. - - * src/cache/*: s/__/_/. - -2016-01-12 Werner Lemberg - - Don't use macro names that contain `__' [1/2]. - - Such macro names are reserved for both C and C++. - - * */*: Replace macros of the form `__XXX_H__' with `XXX_H_'. - -2016-01-10 Jered Gray - - [cff] Fix usage of `|' operator. - - * src/cff/cf2intrp.c (cf2_interpT2CharString) [cf2_cmdEXTENDEDNMBR, - default]: `|' is not guaranteed to be processed from left to right - by the compiler. However, the code repeatedly calls - `cf2_buf_readByte' to get the arguments to `|' ... Fix this. - -2015-12-25 Werner Lemberg - - [autofit] Make top-to-bottom hinting work in latin auto-hinter. - - This improves rendering of scripts like Bengali or Devanagari. - - * src/autofit/afhints.c (af_axis_hints_new_edge): Add parameter to - pass top-to-bottom hinting flag. This makes the function sort edges - in descending vertical position. - - * src/autofit/afhints.c: Updated. - - * src/autofit/aflatin.c (af_latin_hints_compute_edges, - af_latin_hint_edges): Use `top_to_bottom_hinting' flag. - - * src/autofit/afcjk.c (af_cjk_hints_compute_edges), - src/autofit/aflatin2.c (af_latin2_hints_compute_edges): Updated. - -2015-12-24 Werner Lemberg - - [autofit] Add hinting direction to `AF_ScriptClassRec'. - - Still unused. - - * src/autofit/afglobal.c (SCRIPT): Handle hinting direction. - - * src/autofit/aftypes.h (AF_ScriptClassRec): Add - `top_to_bottom_hinting' field. - (AF_HINTING_BOTTOM_TO_TOP, AF_HINTING_TOP_TO_BOTTOM): New macros. - (AF_DEFINE_SCRIPT_CLASS): Updated. - -2015-12-23 Werner Lemberg - - [autofit] Start implementing hinting direction (up/down, down/up). - - Right now, it does nothing. - - * src/autofit/afscript.h: Add another parameter to `SCRIPT', - specifying hinting direction. - - * src/autofit/afglobal.c, src/autofit/afglobal.h, - src/autofit/afpic.c, src/autofit/afranges.h, src/autofit/afshaper.c, - src/autofit/aftypes.h: Extend `SCRIPT' definitions. - -2015-12-22 Werner Lemberg - - * src/type1/t1load.c (parse_subrs): Fix memory leak (#46744). - -2015-12-22 Werner Lemberg - - [base] Make hash interface symmetric. - - Use `num' and `str' infixes everywhere. - - * src/base/fthash.c (ft_hash_init): Renamed to... - (hash_init): ... This. - (ft_hash_str_init, ft_hash_num_init): New functions. - (ft_hash_free): Renamed to... - (ft_hash_str_free): ... This. - - * include/freetype/internal/fthash.h: Updated. - - * src/bdf/bdflib.c, src/type1/t1load.c, src/type1/t1objs.c: Updated. - -2015-12-21 Werner Lemberg - - [type1] Avoid shift of negative numbers (#46732). - - * src/type1/t1load.c (parse_subrs): Do it. - -2015-12-20 Werner Lemberg - - [type1, psaux] Handle large values of num_subrs correctly (#46692). - - We now use a hash to map from subr indices to array elements holding - the subroutines, if necessary. - - * include/freetype/internal/t1types.h: Include FT_INTERNAL_HASH_H. - (T1_FontRec): Add `subrs_hash' field. - - * include/freetype/internal/psaux.h: Include FT_INTERNAL_HASH_H. - (T1_DecoderRec): Add `subrs_hash' field. - - * src/type1/t1load.h (T1_LoaderRec): Add `subrs_hash' field. - - * src/type1/t1driver.c: Include FT_INTERNAL_HASH_H. - (t1_ps_get_font_value) [PS_DICT_SUBR]: Look up hash if necessary. - - * src/type1/t1load.c: Include FT_INTERNAL_HASH_H. - (parse_subrs): Use hash for subr indices that exceed the allocated - number of subr slots. - (t1_init_loader): Remove unnecessary code. - (t1_done_loader, T1_Open_Face): Updated. - - * src/type1/t1gload.c (T1_Compute_Max_Advance, T1_Get_Advances, - T1_Load_Glyph): Updated. - - * src/type1/t1objs.c (T1_Face_Done): Updated. - - * src/psaux/t1decode.c: Include FT_INTERNAL_HASH_H. - (t1_decoder_parse_charstrings) [op_callsubr]: Look up hash if - necessary. - - * src/cid/cidgload.c (cid_load_glyph): Updated. - -2015-12-20 Werner Lemberg - - [base] Thinko: Remove free function pointer. - - We don't copy keys or values while hashing. - - * include/freetype/internal/fthash.h (FT_Hash_FreeFunc): Removed. - (FT_HashRec): Remove `free' field. - - * src/base/fthash.c (hash_str_free): Removed. - (ft_hash_init, ft_hash_free): Updated. - -2015-12-20 Werner Lemberg - - [base, bdf] Don't expose `FT_Hashnode' in hash functions. - - * src/base/fthash.c (hash_lookup, ft_hash_str_lookup, - ft_hash_num_lookup): Return pointer to `size_t' instead of - `FT_Hashnode'. - - * include/freetype/internal/fthash.h: Updated. - - * src/bdf/bdflib.c (bdf_get_property, _bdf_add_property, - bdf_get_font_property): Updated. - -2015-12-20 Werner Lemberg - - [base, bdf] Add number hashing. - - * src/base/fthash.c (hash_num_lookup, hash_num_compare): New - functions. - (ft_hash_init): Add argument to select between number and string - hashing. - (ft_hash_num_insert, ft_hash_num_lookup): New functions. - - * include/freetype/internal/fthash.h: Updated. - - * src/bdf/bdflib.c (_bdf_parse_start): Updated. - -2015-12-20 Werner Lemberg - - [base] Introduce hash lookup, compare, and free function pointers. - - * include/freetype/internal/fthash.c (FT_Hash_LookupFunc, - FT_Hash_CompareFunc, FT_Hash_FreeFunc): New typedefs. - (FT_HashRec): Add `lookup', `compare', and `free' fields. - - * src/base/fthash.c (hash_str_lookup, hash_str_compare, - hash_str_free): New functions. - (ft_hash_init): Set function pointers. - (hash_bucket, ft_hash_free): Use them. - -2015-12-20 Werner Lemberg - - [base, bdf] Use a union as a hash key. - - We want to support both an integer and a string key later on. - - * include/freetype/internal/fthash.h (FT_Hashkey): New union. - (FT_HashnodeRec): Updated. - (ft_hash_insert, ft_hash_lookup): Renamed to ... - (ft_hash_str_insert, ft_hash_str_lookup): ... this. - - * src/base/fthash.c (hash_bucket): Updated. - (ft_hash_insert, ft_hash_lookup): Renamed to ... - (hash_insert, hash_lookup): ... this. - (ft_hash_str_insert, ft_hash_str_lookup): New wrapper functions. - - * src/bdf/bdflib.c: Updated. - -2015-12-19 Werner Lemberg - - [bdf] Use new hash functions. - - * src/bdf/bdf.h: Include FT_INTERNAL_HASH_H. - (hashnode, hashtable): Removed. - (bdf_font_t): Use `FT_HashRec' type for `proptbl'. - - * src/bdf/bdflib.c: Remove all hash functions. - Update code for new hash structure and function names. - -2015-12-19 Werner Lemberg - - [bdf, base] Lift hash functions from bdf driver to base module. - - * src/base/fthash.c, include/freetype/internal/fthash.h: New files, - containing (massaged) code from `bdflib.c' and `bdf.h'. - - * include/freetype/internal/internal.h (FT_INTERNAL_HASH_H): New - macro. - - * src/base/ftbase.c: Include `fthash.c'. - - * src/base/Jamfile (_sources): Add `fthash'. - - * src/base/rules.mk (BASE_SRC): Add `fthash.c'. - - * docs/LICENSE.TXT: Updated. - -2015-12-15 Werner Lemberg - - [autofit] Add blue-zone support for Bengali script. - - This essentially moves the Bengali script from the `Indic' hinter to - the `Latin' hinter. - - * src/autofit/afblue.dat: Add blue zone data for Bengali. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Bengali standard characters and move - data out of AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afranges.c: Move Bengali data out of - AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afstyles.h: Update Bengali data; in particular, use - AF_WRITING_SYSTEM_LATIN. - -2015-12-14 Ben Wagner - - [bdf] Remove dead code (#46625). - - The BDF specification only allows decimal numbers, no octal or - hexadecimal decoding is needed. - - * src/bdf/bdflib.c (_bdf_atoul, _bdf_atol, _bdf_atous, - _bdf_atos): Remove unused code and parameters. - Update all callers. - (odigits): Remove. - -2015-12-14 Werner Lemberg - - [base] Fix calls to `FT_Stream_Seek'. - - * src/base/ftobjs.c (Mac_Read_sfnt_Resource, FT_Open_Face): Set - `error'. - -2015-12-14 Ben Wagner - - [base] Check error when seeking to data supplied offset (#46635). - - * src/base/ftobjs.c (open_face_PS_from_sfnt_stream): - `ft_lookup_PS_in_sfnt_stream' returns offset and length from - user supplied data. Use of this these values must be checked. - -2015-12-13 Werner Lemberg - - [autofit] Add support for Myanmar script. - - * src/autofit/afblue.dat: Add blue zone data for Myanmar. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Myanmar standard characters. - - * src/autofit/afranges.c: Add Myanmar data. - - * src/autofit/afstyles.h: Add Myanmar data. - -2015-12-12 Werner Lemberg - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Minor. - -2015-12-12 Werner Lemberg - - * src/autofit/afscript.h: Avoid potential crash. - -2015-12-10 Werner Lemberg - - [autofit] Restore OpenType feature check. - - This was removed while rewriting the HarfBuzz interface. - - * src/autofit/afglobal.h (AF_FaceGlobalsRec): Add `hb_buf' field to - hold internal HarfBuzz buffer, needed for feature comparison. - - * src/autofit/afglobal.c (af_face_globals_new, - af_face_globals_free): Initialize and destroy `hb_buf'. - - * src/autofit/afshaper.c (af_shaper_get_cluster): Compare character - (cluster) with and without applied feature. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Fix tracing - message. - -2015-12-10 Werner Lemberg - - [autofit] Remove redundant code. - - * src/autofit/aflatin.c (af_latin_metrics_init_widths): Do it. - -2015-12-09 Werner Lemberg - - [autofit] Thinko. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Don't count - empty blue zones (bug introduced 2015-12-06). - -2015-12-09 Werner Lemberg - - [autofit] Introduce subscript top blue zones. - - This feature is mainly for Khmer: The idea is to avoid a clash - between the top of subscript glyphs and the bottom of normal - baseline glyphs. - - This only works for character clusters mapped to multiple glyphs. - - * src/autofit/afblue.dat: Add subscript top blue zone for Khmer. - - * src/autofit/afblue.hin (AF_BLUE_PROPERTY_LATIN_SUB_TOP): New - macro. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/aflatin.h (AF_LATIN_IS_SUB_TOP_BLUE, - AF_LATIN_BLUE_SUB_TOP): New macros. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Handle new - blue zone property. - Update tracing messages. - (af_latin_metrics_scale_dim): Handle new blue zone property. - (af_latin_hints_compute_blue_edges): Updated. - -2015-12-09 Werner Lemberg - - [autofit] Fix tracing message. - - * src/autofit/aflatin.c (af_latin_metrics_scale_dim): Display - inactive blue zones also. - -2015-12-06 Werner Lemberg - - * src/autofit/afblue.dat: Add more Khmer clusters. - - Some fonts have incorrect ligatures; we need more samples to get a - good mean value. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - -2015-12-06 Werner Lemberg - - [autofit] Typos. - - * src/autofit/afshaper.c (af_shaper_buf_create, af_shaper_get_elem) - [!FT_CONFIG_OPTION_USE_HARFBUZZ]: Make it compile. - -2015-12-06 Werner Lemberg - - [autofit] Add support for Khmer script. - - We split Khmer into two auto-hinter scripts: `Khmer' (`khmr') and - `Khmer symbols' (`khms', U+19E0-U+19FF). - - * src/autofit/afblue.dat: Add blue zone data for Khmer. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Khmer standard characters. - - * src/autofit/afranges.c: Add Khmer data. - - * src/autofit/afstyles.h: Add Khmer data. - -2015-12-06 Werner Lemberg - - [autofit] Rewrite HarfBuzz interface to support character clusters. - - Scripts like Khmer have blue zones that can't be directly - represented by Unicode characters. Instead, it is necessary to let - HarfBuzz convert character clusters into proper glyph representation - forms, then deriving the blue zone information from the resulting - glyphs. - - * src/autofit/hbshim.c, src/autofit/hbshim.h: Replaced by... - * src/autofit/afshaper.c, src/autofit/afshaper.h: ... these two new - files, providing a new API to access HarfBuzz. - - The new API manages a HarfBuzz buffer with `af_shaper_buf_create' - and `af_shaper_buf_destroy'. The buffer receives a UTF8 encoded - string with function `af_shaper_get_cluster', and the resulting - glyph data (indices, advance widths, vertical offsets) can be - iteratively accessed with function `af_shaper_get_elem'. - - * src/autofit/afcjk.c (af_cjk_metrics_init_widths, - af_cjk_metrics_init_blues, af_cjk_metrics_check_digits): Updated. - - * src/autofit/aflatin.c (af_latin_metrics_init_widths, - af_latin_metrics_init_blues, af_latin_metrics_check_digits): - Updated. - - * include/freetype/internal/fttrace.h: s/afharfbuzz/afshaper/. - - * src/autofit/afglobal.c: s/hbshim.h/afshaper.h/. - (af_face_globals_compute_style_coverage): Updated. - - * src/autofit/afglobal.h: s/hbshim.h/afshaper.h/. - - * src/autofit/autofit.c: s/hbshim.c/afshaper.c/. - - * src/autofit/Jamfile, src/autofit/rules.mk (AUTOF_DRV_SRC): - Updated. - -2015-12-06 Werner Lemberg - - [autofit] Prepare forthcoming changes. - - This makes it easier to control the commits. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Add dummy - loop. No functional change. - -2015-12-06 Werner Lemberg - - [autofit] Use string of standard characters. - - This is more flexible; additionally, it would allow character - clusters. - - * src/autofit/aftypes.h (SCRIPT, AF_DEFINE_SCRIPT_CLASS): Updated. - (AF_ScriptClassRec): Replace `standard_char[123]' with - `standard_charstring'. - - * src/autofit/afscript.h: Replace last three character arguments - of the `SCRIPT' calls with a string parameter, holding the standard - characters (in UTF-8 encoding) separated with spaces. - - * src/autofit/afglobal.c, src/autofit/afglobal.h, - src/autofit/afpic.c, src/autofit/afranges.c, src/autofit/hbshim.c - (SCRIPT): Updated. - - * src/autofit/afcjk.c (af_cjk_metrics_init_widths), - src/autofit/aflatin.c (af_latin_metrics_init_widths): Updated. - -2015-12-05 Werner Lemberg - - * src/autofit/afblue.dat: Separate blue zone characters with spaces. - - Another preparation for character cluster support. - - * src/autofit/afblue.c, src/autofit.afblue.h: Regenerated. - -2015-12-05 Werner Lemberg - - * src/tools/afblue.pl (convert_ascii_chars): Don't ignore spaces. - - Instead, reduce multiple spaces to a single one. We need this later - for supporting character clusters in `afblue.dat'. - -2015-12-05 Werner Lemberg - - * src/autofit/afblue.hin (GET_UTF8_CHAR): Use `do...while(0)'. - - * src/autofit/afblue.h: Regenerated. - -2015-12-05 Werner Lemberg - - * src/autofit/afwarp.c: s/INT_MIN/FT_INT_MIN/. - -2015-12-03 Werner Lemberg - - * builds/unix/install.mk (install): Remove stale `ft2build.h'. - -2015-12-01 Werner Lemberg - - [type1] Avoid dangling pointer (#46572). - - * src/type1/t1afm.c (T1_Read_Metrics): Properly reset - `face->afm_data'. - -2015-11-28 Alexei Podtelezhnikov - - * include/freetype/ftlcdfil.h: Documentation tweak. - -2015-11-28 Werner Lemberg - - * Version 2.6.2 released. - ========================= - - - Tag sources with `VER-2-6-2'. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.6.2. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.6.1/2.6.2/, s/261/262/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 2. - - * builds/unix/configure.raw (version_info): Set to 18:2:12. - * CMakeLists.txt (VERSION_PATCH): Set to 2. - - * docs/CHANGES: Updated. - -2015-11-28 Werner Lemberg - - Fix C++ compilation. - - * src/autofit/afloader.c: Include FT_INTERNAL_CALC_H. - - * src/truetype/ttgload.c (load_truetype_glyph): Pacify compiler. - -2015-11-28 Nikolaus Waxweiler - - Change default LCD filter to be normalized and color-balanced. - - * src/base/ftlcdfil.c (FT_Library_SetLcdFilter): Update - `default_filter'. - -2015-11-28 Werner Lemberg - - [docmaker] Allow references to section names. - - In the reference, we show the section's title enclosed in single - quotes. - - * src/tools/docmaker/formatter.py (Formatter::__init__): Collect - section names as identifiers. - - * src/tools/docmaker/tohtml.py (section_title_header): Split into... - (section_title_header1, section_title_header2): ... these two - strings. - (HtmlFormatter::make_block_url, make_html_word, html_source_quote): - Handle sections. - (HtmlFormatter::section_enter): Updated to add `id' HTML attribute. - -2015-11-27 Tamas Kenez - - [cmake] Add script to test the config module. - - * builds/cmake/testbuild.sh: New file. - -2015-11-27 Tamas Kenez - - * CMakeLists.txt: Create `freetype-config.cmake' config module. - -2015-11-27 Tamas Kenez - - * CMakeLists.txt: Set CMAKE_DEBUG_POSTFIX to `d'. - -2015-11-27 Tamas Kenez - - [cmake] Add better control of library dependencies. - - * CMakeLists.txt: Add `WITH_*' variables to force/auto/omit - ZLIB/BZip2/PNG/HarfBuzz. - -2015-11-27 Tamas Kenez - - [cmake] Make `FindHarfBuzz' observe the REQUIRED option. - - * builds/cmake/FindHarfBuzz.cmake: Implement it. - -2015-11-27 Werner Lemberg - - [cmake] Collect files specific to cmake in `builds/cmake'. - - * builds/FindHarfBuzz.cmake: Move to ... - * builds/cmake/FindHarfBuzz.cmake: ... this place. - - * CMakeLists.txt (CMAKE_MODULE_PATH): Updated. - -2015-11-27 Alexander Bock - - CMakeLists.txt: Honour new command line flag `FREETYPE_NO_DIST'. - -2015-11-26 Werner Lemberg - - [docmaker] Allow `foo[bar]' as identifier. - - We need this to handle equally named properties in different - modules. - - * src/tools/docmaker/content.py (re_identifier), - src/tools/docmaker/sources.py (re_crossref): Allow `foo[bar]'. - - * src/tools/docmaker/tohtml.py (HtmlFormatter::make_html_word, - HtmlFormatter::index_exit, HtmlFormatter::section_enter, - HtmlFormatter::block_enter): Handle `foo[bar]'. - -2015-11-25 Werner Lemberg - - * src/bdf/bdflib.c (bdf_load_font): Fix small memory leak (#46480). - - (_bdf_parse_glyphs): Always reset `p->glyph_name' after moving its - contents. - -2015-11-21 Werner Lemberg - - * include/freetype/internal/ftcalc.h: Don't use `register' keyword. - - This fixes compiler warnings. - - Reported by Behdad. - -2015-11-20 Werner Lemberg - - Add `FT_LCD_FILTER_LEGACY1' enum value. - - This does the same as `FT_LCD_FILTER_LEGACY'. - - See - - https://bugs.freedesktop.org/show_bug.cgi?id=92981 - - for the reasoning. - - * include/freetype/ftlcdfil.h (FT_LcdFilter): New value - `FT_LCD_FILTER_LEGACY1'. - - * src/base/ftlcdfil.c (FT_Library_SetLcdFilter): Use it. - -2015-11-15 Werner Lemberg - - * src/autofit/afhints.c (af_get_segment_index): Fix it. - - The old code was too simple, returning invalid values in most cases - where a segment crosses the contour start. - -2015-11-15 Werner Lemberg - - * src/bdf/bdflib.c (bdf_load_font): Fix small memory leak (#46439). - -2015-11-11 Werner Lemberg - - [cff, autofit] Switch off stem darkening by default. - - * src/autofit/afmodule.c (af_autofitter_init), src/cff/cffobjs.c - (cff_driver_init): Do it. - -2015-11-10 Jan Alexander Steffens (heftig) - - Allow native CFF hinter in FT_RENDER_MODE_LIGHT. - - Both the native CFF hinter and the auto-hinter now have a very - similar rendering style. - - * include/freetype/freetype.h: Mention that FT_LOAD_TARGET_LIGHT no - longer implies FT_LOAD_FORCE_AUTOHINT. - - * include/freetype/ftmodapi.h (FT_MODULE_DRIVER_HINTS_LIGHTLY): New - macro. - - * include/freetype/internal/ftobjs.h (FT_DRIVER_HINTS_LIGHTLY): New - macro. - - * src/cff/cffdrivr.c (cff_driver_class): Use it. - - * src/base/ftobjs.c (FT_Load_Glyph): Update auto-hinter selection - logic. - -2015-11-09 Werner Lemberg - - * src/cid/cidload.c (cid_face_open): Fix GDBytes guard (#46408). - -2015-11-09 Werner Lemberg - - [truetype] Remove integer to pointer conversion compiler warning. - - Problem reported by Alexei. - - * src/truetype/ttgload.c (load_truetype_glyph): Use a solution found - in the glib library to fix the issue. - -2015-11-08 Behdad Esfahbod - - [sfnt] Accept version 3 of `EBLC' and `CBLC' tables also. - - * src/sfnt/ttsbit.c (tt_face_load_sbit): Implement it. - -2015-11-08 Philipp Knechtges - - [autofit] Don't distort (latin) glyphs too much (#46195). - - * src/autofit/aflatin.h (AF_LatinBlueRec): Add `ascender' and - `descender' fields. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Collect - ascender and descender data for blue zones. - (af_latin_metrics_scale_dim): Reject vertical scaling values that - change the result by more than two pixels. - -2015-11-05 Werner Lemberg - - [sfnt] Ignore embedded bitmaps with zero size (#46379). - - * src/sfnt/ttsbit.c (tt_sbit_decoder_load_bit_aligned): Implement - it. - -2015-11-04 Werner Lemberg - - [truetype] Catch infinite recursion in subglyphs (#46372). - - * include/freetype/internal/tttypes.h (TT_LoaderRec): New field - `composites'. - - * src/truetype/ttgload.c: Include FT_LIST_H. - (load_truetype_glyph): Add composite subglyph index to a list; - abort if index is already in list. - (tt_loader_init): Updated. - (tt_loader_done): New function. - (TT_Load_Glyph): Call `tt_loader_done'. - -2015-11-04 Werner Lemberg - - [truetype] Better tracing of composite glyphs. - - * src/truetype/ttgload.c (TT_Load_Composite_Glyph, - load_truetype_glyph): Implement it. - -2015-11-03 Werner Lemberg - - [sfnt] Protect against zero-size bitmaps (#46345). - - * src/sfnt/ttsbit.c (tt_sbit_decoder_load_bitmap): Check - `glyph_size'. - -2015-11-02 Nikolaus Waxweiler - - * src/autofit/afloader.c (af_loader_load_g): Implement emboldening. - -2015-11-02 Nikolaus Waxweiler - - [autofit] Implement darkening computation function. - - This is a crude adaption of the original `cf2_computeDarkening' - function. - - * src/autofit/afloader.c (af_intToFixed, af_fixedToInt, - af_floatToFixed): New macros, taken from `cf2fixed.h'. - (af_loader_compute_darkening): New function. - * src/autofit/afloader.h: Updated. - -2015-11-02 Nikolaus Waxweiler - - [autofit] Add functions to get standard widths for writing systems. - - We need the computed standard horizontal and vertical widths for the - emboldening calculation. This method provides a convenient way to - extract it from writing-system-specific metrics structures, which - all script definitions must implement. - - * src/autofit/aftypes.h (AF_WritingSystem_GetStdWidthsFunc): New - function type. - (AF_WritingSystemClassRec): New member `style_metrics_getstdw'. - (AF_DEFINE_WRITING_SYSTEM_CLASS): Updated. - - * src/autofit/afcjk.c (af_cjk_get_standard_width): New function. - (af_cjk_writing_system_class): Updated. - * src/autofit/afdummy.c (af_dummy_writing_system_class): Updated. - * src/autofit/afindic.c (af_cjk_get_standard_width): New function. - (af_indic_writing_system_class): Updated. - * src/autofit/aflatin.c (af_latin_get_standard_width): New function. - (af_indic_writing_system_class): Updated. - * src/autofit/aflatin.c (af_latin_get_standard_width): New function. - (af_indic_writing_system_class): Updated. - -2015-11-02 Nikolaus Waxweiler - - [autofit] Extend `AF_FaceGlobalsRec' to hold emboldening data. - - * src/autofit/afglobal.h (AF_FaceGlobalsRec): Add fields. - - * src/autofit/afglobal.c (af_face_globals_new): Initialize new - fields. - (af_face_globals_free): Reset new fields. - -2015-11-02 Nikolaus Waxweiler - - [autofit] Add stem-darkening properties. - - Actual code follows in a later commit. - - * include/freetype/ftautoh.h: Document `no-stem-darkening' and - `darkening-parameters'. - - * src/autofit/afmodule.h: New fields `no_stem_darkening' and - `darken_params'. - - * src/autofit/afmodule.c (af_property_set, af_property_get): - Handle them. - (af_autofitter_init): Initialize them. - -2015-11-02 Ben Wagner - - [ftfuzzer] Add support for multiple files (patch #8779). - - Currently, libFuzzer only supports mutation of a single file. We - circumvent this problem by using an uncompressed tar archive as - multiple-file input for the fuzzer. - - This patch enables tests of `FT_Attach_Stream' and AFM/PFM parsing; - a constructed tarball should contain a font file as the first - element, and files to be attached as further elements. - - * src/tools/ftfuzzer/ftfuzzer.cc: Include libarchive headers. - (archive_read_entry_data, parse_data): New functions. - (LLVMFuzzerTestOneInput): Updated. - - * src/tools/ftfuzzer/ftmutator.cc: New file, providing a custom - mutator for libFuzzer that can mutate tarballs in a sensible way. - -2015-10-31 Werner Lemberg - - [sfnt] Fix cmap 14 validation (#46346). - - * src/sfnt/ttcmap.c (tt_cmap14_validate): Check limit before - accessing `numRanges' and `numMappings'. - Fix size check for non-default UVS table. - -2015-10-31 Werner Lemberg - - [sfnt] Handle infinite recursion in bitmap strikes (#46344). - - * src/sfnt/ttsbit.c (TT_SBitDecoder_LoadFunc, - tt_sbit_decoder_load_bitmap, tt_sbit_decoder_load_byte_aligned, - tt_sbit_decoder_load_bit_aligned, tt_sbit_decoder_load_png): Add - argument for recursion depth. - (tt_sbit_decoder_load_compound): Add argument for recursion depth. - Increase recursion counter for recursive call. - (tt_sbit_decoder_load_image): Add argument for recursion depth. - Check recurse depth. - (tt_face_load_sbit_image): Updated. - -2015-10-29 Werner Lemberg - - * src/autofit/afhints.c (af_glyph_hints_dump_points): Minor. - -2015-10-29 Werner Lemberg - - * CMakeLists.txt: Remove code to set MSVC's /FD compiler switch. - - Problem reported by David Capello ; see - - https://lists.nongnu.org/archive/html/freetype-devel/2015-10/msg00108.html - - for details. - -2015-10-27 Werner Lemberg - - [pfr] Add some safety guards (#46302). - - * src/pfr/pfrload.h (PFR_CHECK): Rename to... - (PFR_CHECK_SIZE): ... this. - (PFR_SIZE): [!PFR_CONFIG_NO_CHECKS]: Define to PFR_CHECK_SIZE. - - * src/pfr/pfrload.c (pfr_log_font_count): Check `count'. - (pfr_extra_item_load_kerning_pairs): Remove tracing message. - (pfr_phy_font_load): Use PFR_CHECK_SIZE where appropriate. - Allocate `chars' after doing a size checks. - - * src/pfr/pfrsbit.c (pfr_load_bitmap_bits): Move test for invalid - bitmap format to... - (pfr_slot_load_bitmap): ... this function. - Check bitmap size. - -2015-10-26 Werner Lemberg - - [truetype] Fix sanitizing logic for `loca' (#46223). - - * src/truetype/ttpload.c (tt_face_load_loca): A thinko caused an - incorrect adjustment of the number of glyphs, most often using far - too large values. - -2015-10-25 Werner Lemberg - - [autofit] Improve tracing. - - * src/autofit/afhints.c (af_print_idx, af_get_segment_index, - af_get_edge_index): New functions. - - (af_glyph_hints_dump_points): Remove unnecessary `|', `[', and `]'. - Add segment and edge index for each point. - Slightly change printing order of some elements. - Don't print `-1' but `--' for missing elements. - - (af_glyph_hints_dump_segments, af_glyph_hints_dump_edges): Remove - unnecessary `|', `[', and `]'. - Don't print `-1' but `--' for missing elements. - -2015-10-24 Werner Lemberg - - [sfnt] Sanitize bitmap strike glyph height. - - Problem reported by Nikolay Sivov . - - * src/sfnt/ttsbit.c (tt_face_load_strike_metrics): Avoid zero value - for `metrics->height' by applying some heuristics. - -2015-10-22 Werner Lemberg - - [sfnt, type42] Fix clang compiler warnings. - - * src/sfnt/sfobjs.c (sfnt_init_face): Initialize `offset'. - - * src/type42/t42parse.c (t42_parse_sfnts): Use proper cast. - -2015-10-22 Dave Arnold - Werner Lemberg - - [cff] Avoid overflow/module arithmetic. - - This modifies the addition of subroutine number to subroutine bias - from unsigned to signed, but does not change any results. - - * src/cff/cf2ft.c (cf2_initGlobalRegionBuffer, - cf2_initLocalRegionBuffer): Change variable names from (unsigned) - `idx' to (signed) `subrNum', since it is not an index until after - the bias is added. - * src/cff/cf2ft.h: Updated. - - * src/cff/cf2intrp.c (cf2_interpT2CharString) : - Updated similarly. - -2015-10-22 Werner Lemberg - - [cid] Better check of `SubrCount' dictionary entry (#46272). - - * src/cid/cidload.c (cid_face_open): Add more sanity tests for - `fd_bytes', `gd_bytes', `sd_bytes', and `num_subrs'. - -2015-10-21 Werner Lemberg - - [base] Pacify compiler (#46266). - - * src/base/ftoutln.c (FT_Outline_EmboldenXY): Initialize `in' and - `anchor'. - -2015-10-21 Werner Lemberg - - [type42] Fix heap buffer overflow (#46269). - - * src/type42/t42parse.c (t42_parse_sfnts): Fix off-by-one error in - bounds checking. - -2015-10-21 Dave Arnold - - [cff] Fix limit in assert for max hints. - - * src/cff/cf2interp.c (cf2_hintmask_setAll): Allow mask equal to the - limit (96 bits). - -2015-10-21 Dave Arnold - - [cff] Remove an assert (#46107). - - * src/cff/cf2hints.c (cf2_hintmap_insertHint): Ignore paired edges - in wrong order. - -2015-10-21 Werner Lemberg - - [sfnt] Avoid unnecessarily large allocation for WOFFs (#46257). - - * src/sfnt/sfobjs.c (woff_open_font): Use WOFF's `totalSfntSize' - only after thorough checks. - Add tracing messages. - -2015-10-21 Werner Lemberg - - [type42] Better check invalid `sfnts' array data (#46255). - - * src/type42/t42parse.c (t42_parse_sfnts): Table lengths must be - checked individually against available data size. - -2015-10-20 Werner Lemberg - - [cid] Add a bunch of safety checks. - - * src/cid/cidload.c (parse_fd_array): Check `num_dicts' against - stream size. - (cid_read_subrs): Check largest offset against stream size. - (cid_parse_dict): Move safety check to ... - (cid_face_open): ... this function. - Also test length of binary data and values of `SDBytes', - `SubrMapOffset', `SubrCount', `CIDMapOffset', and `CIDCount'. - -2015-10-20 Werner Lemberg - - [cid] Avoid segfault with malformed input (#46250). - - * src/cid/cidload.c (cid_read_subrs): Return a proper error code for - unsorted offsets. - -2015-10-20 StudioEtrange - - * CMakeLists.txt: Enable shared library builds on MinGW (#46233). - -2015-10-20 Werner Lemberg - - * src/type1/t1afm.c (T1_Read_Metrics): Fix memory leak (#46229). - -2015-10-19 Ben Wagner - - [cid] Better handle invalid glyph stream offsets (#46221). - - * src/cid/cidgload.c (cid_load_glyph): Check minimum size of glyph - length. - -2015-10-18 Werner Lemberg - - [psaux] Fix tracing of negative numbers. - - Due to incorrect casting negative numbers were shown as very large - (positive) integers on 64bit systems. - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings) : - Use division instead of shift. - -2015-10-18 Werner Lemberg - - [truetype] Improve TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES (#46223). - - * devel/ftoption.h, include/freetype/config/ftoption.h: Surround it - with #ifndef ... #endif, as suggested in the tracker issue. - -2015-10-18 Werner Lemberg - - [truetype] Better protection against malformed `fpgm' (#46223). - - * src/truetype/ttobjs.c (tt_size_init_bytecode): Don't execute a - malformed `fpgm' table more than once. - -2015-10-17 Werner Lemberg - - * src/cid/cidgload.c (cid_load_glyph): Fix memory leak. - - Reported by Kostya Serebryany . - -2015-10-17 Werner Lemberg - - [bdf] Prevent memory leak (#46217). - - * src/bdf/bdflib.c (_bdf_parse_glyphs) : Check - _BDF_GLYPH_BITS. - -2015-10-17 Werner Lemberg - - [bdf] Use stream size to adjust number of glyphs. - - * src/bdf/bdflib.c (ACMSG17): New message macro. - (_bdf_parse_t): Add member `size'. - (bdf_load_font): Set `size'. - (_bdf_parse_glyphs): Adjust `cnt' if necessary. - -2015-10-17 Werner Lemberg - - * src/cid/cidload.c (cid_parse_dict): Check `[FG]DBytes' size. - -2015-10-17 Werner Lemberg - - * src/cid/cidgload.c (cid_glyph_load): Check file offsets (#46222). - -2015-10-17 Werner Lemberg - - [psaux] Fix heap buffer overflow (#46221). - - * src/psaux/t1decode.c (t1_decoder_parse_charstring) : - Fix limit check. - -2015-10-17 Werner Lemberg - - * src/cid/cidload.c (cid_parse_dict): Handle invalid input (#46220). - -2015-10-15 Kostya Serebryany - - [ftfuzzer] Add README. - - * src/tools/ftfuzzer/README: New file. - -2015-10-15 Ben Wagner - - [bdf] Fix memory leak (#46213). - - * src/bdf/bdflib.c (bdf_load_font): Always go to label `Fail' in - case of error. - -2015-10-15 Werner Lemberg - - [truetype] Add TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES (#46208). - - * devel/ftoption.h, include/freetype/config/ftoption.h - (TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES): New configuration macro. - - * src/truetype/ttinterp.c (MAX_RUNNABLE_OPCODES): Removed. - (TT_RunIns): Updated. - -2015-10-15 Werner Lemberg - - * src/truetype/ttinterp.c (TT_RunIns): Fix bytecode stack tracing. - - The used indices were off by 1. - -2015-10-15 Ben Wagner - Werner Lemberg - - * src/tools/ftfuzzer/ftfuzzer.cc: Handle fixed sizes (#46211). - -2015-10-15 Werner Lemberg - - [base] Compute MD5 checksums only if explicitly requested. - - This improves profiling accuracy. - - * src/base/ftobjs.c (FT_Render_Glyph_Internal): Implement it. - -2015-10-14 Werner Lemberg - - [base] Use `FT_' namespace for MD5 functions (#42366). - - * src/base/ftobjs.c (MD5_*): Define as `FT_MD5_*'. - Undefine HAVE_OPENSSL. - -2015-10-13 Werner Lemberg - - [type1] Correctly handle missing MM axis names (#46202). - - * src/type1/t1load.c (T1_Get_MM_Var): Implement it. - -2015-10-13 Werner Lemberg - - [pcf] Quickly exit if font index < 0. - - Similar to other font formats, this commit makes the parser no - longer check the whole PCF file but only the header and the TOC if - we just want to get the number of available faces (and a proper - recognition of the font format). - - * src/pcf/pcfdrivr.c (PCF_Face_Init): Updated. - Exit quickly if face_index < 0. - - * src/pcfread.c (pcf_load_font): Add `face_index' argument. - Exit quickly if face_index < 0. - - * src/pcf/pcf.h: Updated. - -2015-10-13 Werner Lemberg - - [ftfuzzer] Handle TTCs and MM/GX variations. - - This patch also contains various other improvements. - - * src/tools/ftfuzzer/ftfuzzer.cc: Add preprocessor guard to reject - pre-C++11 compilers. - (FT_Global): New class. Use it to provide a global constructor and - destructor for the `FT_Library' object. - (setIntermediateAxis): New function to select an (arbitrary) - instance. - (LLVMFuzzerTestOneInput): Loop over all faces and named instances. - Also call `FT_Set_Char_Size'. - -2015-10-13 Werner Lemberg - - [truetype] Refine some GX sanity tests. - - Use the `gvar' table size instead of the remaining bytes in the - stream. - - * src/truetype/ttgxvar.h (GX_BlendRec): New field `gvar_size'. - - * src/truetype/ttgxvar.c (ft_var_load_gvar): Set `gvar_size'. - (ft_var_readpackedpoints, ft_var_readpackeddeltas: New argument - `size'. - (tt_face_vary_cvt, TT_Vary_Apply_Glyph_Deltas): Updated. - -2015-10-13 Werner Lemberg - - [truetype] Another GX sanity test. - - * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Check - `tupleCount'. - Add tracing message. - -2015-10-13 Werner Lemberg - - [truetype] Fix memory leak for broken GX fonts (#46188). - - * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Fix scope of - deallocation. - -2015-10-13 Werner Lemberg - - [truetype] Fix commit from 2015-10-10. - - * src/truetype/ttgxvar.c (ft_var_load_gvar): Add missing error - handling body to condition. - -2015-10-12 Werner Lemberg - - [unix] Make MKDIR_P actually work. - - * builds/unix/configure.raw: Fix underquoting of `INSTALL' and - `MKDIR_P'. - - Problem reported by Dan Liddell . - -2015-10-11 Werner Lemberg - - [sfnt] Improve extraction of number of named instances. - - * src/sfnt/sfobjs.c (sfnt_init_face) - [TT_CONFIG_OPTION_GX_VAR_SUPPORT]: Check number of instances against - `fvar' table size. - -2015-10-10 Alexei Podtelezhnikov - - * src/base/ftoutln.c (FT_Outline_Get_Orientation): Fix overflow - (#46149). - -2015-10-10 Werner Lemberg - - [sfnt] Fix infinite loops with broken cmaps (#46167). - - * src/sfnt/ttcmap.c (tt_cmap8_char_next, tt_cmap12_next): Take care - of border conditions (i.e., if the loops exit naturally). - -2015-10-10 Werner Lemberg - - [truetype] More sanity tests for GX handling. - - These tests should mainly help avoid unnecessarily large memory - allocations in case of malformed fonts. - - * src/truetype/ttgxvar.c (ft_var_readpackedpoints, - ft_var_readpackeddeltas): Check number of points against stream - size. - (ft_var_load_avar): Check `pairCount' against table length. - (ft_var_load_gvar): Check `globalCoordCount' and `glyphCount' - against table length. - (tt_face_vary_cvt): Check `tupleCount' and `offsetToData'. - Fix trace. - (TT_Vary_Apply_Glyph_Deltas): Fix trace. - Free `sharedpoints' to avoid memory leak. - -2015-10-10 Werner Lemberg - - [truetype] Better protection against malformed GX data (#46166). - - * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Correctly - handle empty `localpoints' array. - -2015-10-10 Werner Lemberg - - * src/pcf/pcfread.c (pcf_read_TOC): Check stream size (#46162). - -2015-10-09 Werner Lemberg - - * src/gzip/ftgzip.c (FT_Stream_OpenGzip): Use real stream size. - -2015-10-08 Werner Lemberg - - [pcf] Protect against invalid number of TOC entries (#46159). - - * src/pcf/pcfread.c (pcf_read_TOC): Check number of TOC entries - against size of data stream. - -2015-10-08 Werner Lemberg - - [type42] Protect against invalid number of glyphs (#46159). - - * src/type42/t42parse.c (t42_parse_charstrings): Check number of - `CharStrings' dictionary entries against size of data stream. - -2015-10-08 Werner Lemberg - - [sfnt] Fix some signed overflows (#46149). - - * src/sfnt/ttsbit.c (tt_face_load_strike_metrics) - : Use `FT_MulDiv'. - -2015-10-08 Werner Lemberg - - [type1] Protect against invalid number of subroutines (#46150). - - * src/type1/t1load.c (parse_subrs): Check number of - `Subrs' dictionary entries against size of data stream. - -2015-10-07 Kostya Serebryany - - [ftfuzzer] Add support for LLVM's LibFuzzer. - - * src/tools/ftfuzzer/ftfuzzer.cc, src/tools/runinput.cc: New files. - -2015-10-06 Alexei Podtelezhnikov - - [smooth] Faster alternative line renderer. - - This implementation renders the entire line segment at once without - subdividing it into scanlines. The main speed improvement comes from - reducing the number of divisions to just two per line segment, which - is a bare minimum to calculate cell coverage in a smooth rasterizer. - Notably, the progression from cell to cell does not itself require any - divisions at all. The speed improvement is more noticeable at larger - sizes. - - * src/smooth/ftgrays.c (gray_render_line): New implementation. - -2015-10-06 Werner Lemberg - - [cff] Return correct PS names from pure CFF (#46130). - - * src/cff/cffdrivr.c (cff_get_ps_name): Use SFNT service only for - SFNT. - -2015-10-04 Werner Lemberg - - [base] Replace left shifts with multiplication (#46118). - - * src/base/ftglyph.c (ft_bitmap_glyph_bbox, FT_Get_Glyph): Do it. - -2015-10-04 Werner Lemberg - - * Version 2.6.1 released. - ========================= - - - Tag sources with `VER-2-6-1'. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.6.1. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.6/2.6.1/, s/26/261/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 1. - - * builds/unix/configure.raw (version_info): Set to 18:1:12. - * CMakeLists.txt (VERSION_PATCH): Set to 1. - - * src/autofit/afmodule.c [AF_DEBUG_AUTOFIT]: Ensure C linking for - dumping functions. - -2015-10-04 Werner Lemberg - - [bzip2, gzip] Avoid access of uninitialized memory (#46109). - - * src/bzip2/ftbzip2.c (ft_bzip2_file_fill_input), src/gzip/ftgzip.c - (ft_gzip_file_fill_input): In case of an error, adjust the limit to - avoid copying uninitialized memory. - -2015-10-03 Werner Lemberg - - [bzip2, gzip] Avoid access of uninitialized memory (#46109). - - * src/bzip2/ftbzip2.c (ft_bzip2_file_fill_output), src/gzip/ftgzip.c - (ft_gzip_file_fill_output): In case of an error, adjust the limit to - avoid copying uninitialized memory. - -2015-10-01 Alexei Podtelezhnikov - - [smooth] Clean up worker. - - * src/smooth/ftgrays.c (gray_TWorker): Remove never used fields. - -2015-10-01 Werner Lemberg - - [sfnt] Make `tt_cmap4_char_map_linear' more robust (#46078). - - * src/sfnt/ttcmap.c (tt_cmap4_char_map_linear): Take care of - border conditions (i.e., if the loop exits naturally). - -2015-10-01 Werner Lemberg - - * src/autofit/afranges.c (af_deva_nonbase_uniranges): Fix ranges. - They should be a subset of `af_deva_uniranges'. - -2015-10-01 Werner Lemberg - - [sfnt] Make `tt_cmap4_char_map_linear' faster (#46078). - - * src/sfnt/ttcmap.c (tt_cmap4_char_map_linear): Use inner loop to - reject too large glyph indices. - -2015-09-30 Alexei Podtelezhnikov - - [smooth] Clean up worker. - - * src/smooth/ftgrays.c (gray_TWorker): Remove lightly used `last_ey'. - (gray_start_cell, gray_render_line): Update. - -2015-09-30 Werner Lemberg - - [autofit] Replace `no-base' with `non-base'. - - * src/autofit/*: Do it. - -2015-09-30 Werner Lemberg - - [sfnt] Rewrite `tt_cmap4_char_map_linear' (#46078). - - * src/sfnt/ttcmap.c (tt_cmap4_char_map_linear): Add code to better - skip invalid segments. - If searching the next character, provide a more efficient logic to - speed up the code. - -2015-09-30 Werner Lemberg - - [truetype] Adjust number of glyphs for malformed `loca' tables. - - * src/truetype/ttpload.c (tt_face_load_loca): Implement it. - -2015-09-29 Werner Lemberg - - [pshinter] Avoid harmless overflow (#45984). - - * src/pshinter/pshglob.c (psh_blues_set_zones): Fix it. - -2015-09-28 Werner Lemberg - - [autofit] Add support for Lao script. - - Thanks to Danh Hong for guidance with blue zone - characters! - - * src/autofit/afblue.dat: Add blue zone data for Lao. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Lao standard characters. - - * src/autofit/afranges.c: Add Lao data. - - * src/autofit/afstyles.h: Add Lao data. - -2015-09-27 suzuki toshiya - - [base] Fix a leak by broken sfnt-PS or resource fork (#46028). - - open_face_from_buffer() frees passed buffer if valid font - is not found. But if copying to the buffer is failed, - the allocated buffer should be freed within the caller. - - * src/base/ftobjs.c (open_face_PS_from_sfnt_stream): Free - the buffer `sfnt_ps' if an error caused before calling - open_face_from_buffer(). - (Mac_Read_sfnt_Resource): Free the buffer `sfnt_data' if - an error caused before calling open_face_from_buffer(); - -2015-09-27 suzuki toshiya - - [mac] Fix buffer size calculation for LWFN font. - - * src/base/ftmac.c (read_lwfn): Cast post_size to FT_ULong - to prevent confused copy by too large chunk size. - -2015-09-26 Alexei Podtelezhnikov - - * src/smooth/ftgrays.c (PIXEL_MASK): Remove unused macro. - -2015-09-26 Werner Lemberg - - [autofit] Minor tracing improvement. - - * src/autofit/aflatin.c (af_latin_metrics_scale_dim): Don't emit - blue zones header line if there are no blue zones. - -2015-09-26 Werner Lemberg - - [bzip2, gzip, lzw] Harmonize function signatures with prototype. - - Suggested by Hin-Tak Leung. - - * src/bzip2/ftbzip2.c (ft_bzip2_stream_io), src/gzip/ftgzip.c - (ft_gzip_stream_io), src/lzw/ftlzw.c (ft_lzw_stream_io): Do it. - -2015-09-26 Hin-Tak Leung - - Add new FT_LOAD_COMPUTE_METRICS load flag. - - * include/freetype/freetype.h (FT_LOAD_COMPUTE_METRICS): New macro. - * src/truetype/ttgload.c (compute_glyph_metrics): Usage. - -2015-09-26 Werner Lemberg - - * src/base/ftobjs.c (Mac_Read_sfnt_Resource): Add cast. - -2015-09-25 Werner Lemberg - - [type1] Protect against invalid number of glyphs (#46029). - - * src/type1/t1load.c (parse_charstrings): Check number of - `CharStrings' dictionary entries against size of data stream. - -2015-09-23 Werner Lemberg - - [sfnt] Better checks for invalid cmaps (2/2) (#46019). - - While the current code in `FT_Get_Next_Char' correctly rejects - out-of-bounds glyph indices, it can be extremely slow for malformed - cmaps that use 32bit values. This commit tries to improve that. - - * src/sfnt/ttcmap.c (tt_cmap8_char_next, tt_cmap12_next, - tt_cmap12_char_map_binary, tt_cmap13_next, - tt_cmap13_char_map_binary): Reject glyph indices larger than or - equal to the number of glyphs. - -2015-09-23 Werner Lemberg - - [base, sfnt] Better checks for invalid cmaps (1/2). - - * src/base/ftobjs.c (FT_Get_Char_Index): Don't return out-of-bounds - glyph indices. - (FT_Get_First_Char): Updated. - - * src/sfnt/ttcmap.c (tt_cmap6_char_next): Don't return character - codes greater than 0xFFFF. - - (tt_cmap8_char_index): Avoid integer overflow in computation of - glyph index. - (tt_cmap8_char_next): Avoid integer overflows in computation of - both next character code and glyph index. - - (tt_cmap10_char_index): Fix unsigned integer logic. - (tt_cmap10_char_next): Avoid integer overflow in computation of - next character code. - - (tt_cmap12_next): Avoid integer overflows in computation of both - next character code and glyph index. - (tt_cmap12_char_map_binary): Ditto. - (tt_cmap12_char_next): Simplify. - - (tt_cmap13_char_map_binary): Avoid integer overflow in computation - of next character code. - (tt_cmap13_char_next): Simplify. - -2015-09-21 suzuki toshiya - - [base] Check too long POST and sfnt resource (#45919). - - * src/base/ftbase.h (FT_MAC_RFORK_MAX_LEN): Maximum length of the - resource fork for Mac OS. Resource forks larger than 16 MB can be - written but can't be handled correctly, at least in Carbon routine. - See https://support.microsoft.com/en-us/kb/130437. - - * src/base/ftobjs.c (Mac_Read_POST_Resource): No need to use `0x' - prefix for `%p' formatter. - - * src/base/ftbase.c (Mac_Read_POST_Resource): Check the fragment and - total size of the concatenated POST resource before buffer - allocation. - (Mac_Read_sfnt_Resource): Check the declared size of sfnt resource - before buffer allocation. - - * src/base/ftmac.c (read_lwfn, FT_New_Face_From_SFNT): Check the - total resource size before buffer allocation. - -2015-09-19 Werner Lemberg - - [sfnt] Improve handling of invalid SFNT table entries (#45987). - - This patch fixes weaknesses in function `tt_face_load_font_dir'. - - - It incorrectly assumed that valid tables are always at the - beginning. As a consequence, some valid tables after invalid - entries (which are ignored) were never seen. - - - Duplicate table entries (this is, having the same tag) were not - rejected. - - - The number of valid tables was sometimes too large, leading to - access of invalid tables. - - * src/sfnt/ttload.c (check_table_dir): Add argument to return number - of valid tables. - Add another tracing message. - (tt_face_load_font_dir): Only allocate table array for valid - entries as returned by `check_table_dir'. - Reject duplicate tables and adjust number of valid tables - accordingly. - -2015-09-19 Werner Lemberg - - [pcf] Improve `FT_ABS' fix from 2015-09-17 (#45999). - - * src/pcf/pcfread.c (pcf_load_font): Do first the cast to FT_Short, - then take the absolute value. - Also apply FT_ABS to `height'. - -2015-09-17 Werner Lemberg - - [type42] Fix memory leak (#45989). - - * src/type42/t42parse.c (t42_parse_charstrings): Allow only a single - `CharStrings' array. - -2015-09-17 Werner Lemberg - - [psaux] Fix memory leak (#45986). - - * src/psaux/psobjs.c (ps_parser_load_field) : - Free `temp' in case of error. - -2015-09-17 Werner Lemberg - - [psaux] Improve tracing message. - - * src/psaux/psobjs.c (ps_parser_load_field) : - Handle plural correctly. - -2015-09-17 Werner Lemberg - - [pcf] Fix integer overflows (#45985). - - * src/pcf/pcfread.c (pcf_load_font): Use FT_MulDiv. - -2015-09-17 Werner Lemberg - - [pcf] Use FT_ABS for some property values (#45893). - - * src/pcf/pcfread.c (pcf_load_font): Take absolute values for - AVERAGE_WIDTH, POINT_SIZE, PIXEL_SIZE, RESOLUTION_X, and - RESOLUTION_Y. In tracing mode, add warnings. - -2015-09-16 Werner Lemberg - - Minor fixes for some clang warnings. - - * src/base/ftoutln.c (FT_Outline_EmboldenXY): Cast, possible missing - initialization. - - * src/truetype/ttgload.c (TT_Process_Composite_Component): Cast. - -2015-09-15 Werner Lemberg - - [type1, type42] Fix memory leaks (#45966). - - * src/type1/t1load.c (parse_blend_axis_types): Handle multiple axis - names. - (parse_blend_design_map): Allow only a single design map. - (parse_encoding): Handle multiple encoding vectors. - - * src/type42/t42parse.c (t42_parse_encoding): Handle multiple - encoding vectors. - -2015-09-15 Werner Lemberg - - [truetype] Fix integer type (#45965). - - * src/truetype/ttobjs.c (tt_synth_sfnt_checksum): Implement it. - -2015-09-15 Werner Lemberg - - * src/pcf/pcfread.c (pcf_load_font): Fix integer overflow (#45964). - -2015-09-15 Werner Lemberg - - [type1, type42] Check encoding array size (#45961). - - * src/type1/t1load.c (parse_encoding), src/type42/t42parse.c - (t42_parse_encoding): Do it. - -2015-09-14 Alexei Podtelezhnikov - - * src/base/ftcalc.c (FT_MulFix) [FT_LONG64]: Improve. - -2015-09-14 Werner Lemberg - - [type1] Fix another potential buffer overflow (#45955). - - * src/type1/t1parse (T1_Get_Private_Dict): Assure that check for - `eexec' doesn't exceed `limit'. - -2015-09-13 Werner Lemberg - - Replace `mkinstalldirs' with AC_PROG_MKDIR_P. - - * builds/unix/mkinstalldirs: Removed, no longer needed. - - * builds/unix/configure.raw: Call `AC_PROG_MKDIR_P'. - Update pwd call for `$INSTALL'. - - * builds/unix/unix-def.in (MKINSTALLDIRS): Use `@MKDIR_P@'. - - * autogen.sh: Updated. - -2015-09-13 Werner Lemberg - - [winfonts] Check alignment shift count for resource data (#45938). - - * src/winfonts/winfnt.c (fnt_face_get_dll_font): Implement it. - -2015-09-13 Werner Lemberg - - [type1] Fix potential buffer overflow (#45923). - - * src/type1/t1parse.c (T1_Get_Private_Dict): Assure `cur' doesn't - point to end of file buffer. - -2015-09-13 Werner Lemberg - - [gzip] Fix access of small compressed files (#45937). - - * src/gzip/ftgzip.c (ft_gzip_stream_close): Avoid memory leak. - - (ft_gzip_get_uncompressed_file): Correct byte order while reading - unsigned long value. Without this change, the whole optimization of - accessing small files in `FT_Stream_OpenGzip' is never executed! As - a consequence, access to PCF files in general (which are normally - small files) should be much improved now as originally intended. - -2015-09-11 Werner Lemberg - - [psaux] Fix potential buffer overflow (#45922). - - * src/psaux/psobjs.c (ps_parser_skip_PS_token): If a token is - enclosed in balanced expressions, ensure that the cursor position - doesn't get larger than the current limit. - -2015-09-11 Werner Lemberg - - [base] Avoid crash while tracing `load_mac_face'. - - Reported in Savannah bug #45919. - - * src/base/ftobjs.c (load_mac_face): Honour FT_OPEN_MEMORY while - tracing. - -2015-09-11 Werner Lemberg - - [type42] Fix endless loop (#45920). - - * src/type42/t42parse.c (t42_parse_encoding): Synchronize with - type1's `parse_encoding'. - -2015-09-10 Werner Lemberg - - [docmaker] Allow `-' in bold and italic markup. - - * src/tools/docmaker/sources.py (re_italic, re_bold): Adjust - accordingly. - -2015-09-09 Alexei Podtelezhnikov - - * src/base/ftcalc.c (FT_RoundFix): Improve. - -2015-09-09 Wojciech Mamrak - - * src/base/ftcalc.c (FT_CeilFix, FT_FloorFix): Normalize. - - This commit makes the functions behave as expected, this is, - rounding towards plus or minus infinity. - -2015-09-07 Alexei Podtelezhnikov - - * src/smooth/ftgrays.c (gray_render_line): Simplify clipping. - -2015-09-04 Alexei Podtelezhnikov - - [raster,smooth] Microoptimizations. - - * src/raster/ftraster.c (Insert_Y_Turn, Finalize_Profile_Table, - Bezier_Up): Use do-while loops. - - * src/smooth/ftgrays.c (gray_render_scanline, gray_render_line, - gray_convert_glyph): Ditto. - -2015-09-04 Werner Lemberg - - [autofit] Redesign code ranges (2/2). - - This commit adds two fallback scripts (`latb', `latp') and - implements support for the no-base character ranges introduced in - the previous commit. - - * src/autofit/aftypes.h (AF_ScriptClassRec): Add - `script_uni_nobase_ranges' field. - (AF_DEFINE_SCRIPT_CLASS): Updated. - - * src/autofit/afscript.h, src/autofit/afstyles.h: Add `latb' and - `latp' fallback scripts. - - * src/autofit/afblue.dat: Add blue zones for Latin subscript and - superscript fallback scripts. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afglobal.h (AF_NOBASE): New style flag for no-base - characters. - (AF_STYLE_MASK): Updated. - - * src/autofit/afglobal.c (SCRIPT): Updated. - (af_face_globals_compute_style_coverage): Handle new style flag. - - * src/autofit/aflatin.c (af_latin_hints_apply): Handle new style - flag. - - * src/autofit/afranges.h (SCRIPT): Use it to export no-base ranges. - -2015-09-04 Werner Lemberg - - [autofit] Redesign code ranges (1/2). - - This patch introduces auxiliary code ranges that identify no-base - characters; they refer to glyphs of a script that should be hinted - without alignments to blue zones (mostly diacritics). - - It also splits off ranges for fallback scripts that handle subscript - and superscript characters not covered by OpenType features. For - example, this greatly helps improve the hinting of various phonetic - alphabets, which contain a large amount characters that look like - superscript glyphs. - - Finally, code ranges are updated to Unicode 8.0, and enclosed - characters are removed in general since they normally look better if - they stay unhinted. - - * src/autofit/afranges.c (af_latn_uniranges): Updated to Unicode - 8.0. - Split off superscript-like and subscript-like glyphs into... - - (af_latb_uniranges, af_latp_uniranges): ... these two new arrays. - - (af_xxxx_nobase_uniranges): New arrays that hold no-base characters - of the corresponding character ranges. - -2015-09-03 Werner Lemberg - - [autofit] Pass glyph index to hinting function. - - No functionality change yet. - - * src/autofit/aftypes.h (AF_WritingSystem_ApplyHintsFunc): Pass - glyph index. - - * src/autofit/afcjk.c, src/autofit/afcjk.h (af_cjk_hints_apply), - src/autofit/afdummy.c (af_dummy_hints_apply), src/autofit/afindic.c - (af_indic_hints_apply), src/autofit/aflatin.c - (af_latin_hints_apply), src/autofit/aflatin2.c - (af_latin2_hints_apply), src/autofit/afloader.c (af_loader_load_g): - Updated. - -2015-08-30 Werner Lemberg - - [autofit] Code clean-up. - - * src/autofit/afglobal.h (AF_STYLE_MASK): New macro. - (AF_STYLE_UNASSIGNED): Use AF_STYLE_MASK for definition. - - * src/autofit/afglobal.c (af_face_globals_compute_style_coverage): - Updated. - -2015-08-30 Werner Lemberg - - [autofit] Make glyph style array use 16bit values. - - * include/freetype/ftautoh.h (FT_Prop_GlyphToScriptMap): Use - `FT_UShort' for `map' field. - - * src/autofit/afglobal.c (af_face_globals_compute_style_coverage, - af_face_globals_new), src/autofit/hbshim.c, src/autofit/hbshim.h - (af_get_coverage): Use FT_UShort for `glyph_styles' array. - - * src/autofit/afglobal.h (AF_STYLE_UNASSIGNED, AF_DIGIT): Extend to - 16 bits. - (AF_FaceGlobalsRec): Use `FT_UShort' for `glyph_styles' field. - -2015-08-26 Werner Lemberg - - * builds/unix/configure.raw: Need harfbuzz >= 0.9.21 (#45828). - -2015-08-25 Werner Lemberg - - [base] Improve kerning tracing and documentation. - - * src/base/ftobjs.c (FT_Get_Kerning): Emit tracing message if - scaled-down kerning values differ. - -2015-08-18 Werner Lemberg - - [raster] Remove last remnants of `raster5' driver. - - * src/raster/ftrend1.h (ft_raster5_renderer_class): Removed. - - * src/raster/rastpic.c, src/raster/rastpic.h - (ft_raster5_renderer_class_pic_init, - ft_raster5_renderer_class_pic_free): Removed. - -2015-08-17 Alexei Podtelezhnikov - - [base] Improve emboldener (#45596). - - * src/base/ftoutln.c (FT_Outline_EmboldenXY): Correct displacement - of zero-length segments. - -2015-08-16 Alexei Podtelezhnikov - - [base] Reoptimize arithmetic. - - * src/base/ftcalc.c (FT_MulDiv, FT_MulFix) [!FT_LONG64]: Remove - special cases that slow down the general use. - -2015-08-15 pazer - - Fix C++ compilation (#45762). - - * src/base/ftstroke.c (ft_outline_glyph_class): Use - FT_CALLBACK_TABLE. - -2015-08-14 Alexei Podtelezhnikov - - [truetype] Clean up. - - * src/truetype/ttgload.c (TT_Process_Composite_Component): Use - `FT_Outline_Transform' and `FT_Outline_Translate'. - (translate_array): Dropped. - -2015-08-14 Andreas Enge - - * builds/unix/detect.mk (CONFIG_SHELL): Don't handle it (#44261). - -2015-08-13 Werner Lemberg - - [truetype] Introduce named instance access to GX fonts. - - For functions querying a face, bits 16-30 of the face index can hold - the named instance index if we have a GX font. The indices start - with value 1; value 0 indicates font access without GX variation - data. - - * include/freetype/freetype.h (FT_FaceRec): Update documentation. - * include/freetype/internal/sfnt.h: Ditto. - - * src/sfnt/sfobjs.c (sfnt_init_face) - [TT_CONFIG_OPTION_GX_VAR_SUPPORT]: Get number of named instances and - do argument checks. - (sfnt_load_face): Updated. - - * src/truetype/ttobjs.c (tt_face_init) - [TT_CONFIG_OPTION_GX_VAR_SUPPORT]: Use named instance, overwriting - the style name. - - * src/base/ftobjs.c (open_face_from_buffer, - open_face_PS_from_sfnt_stream): Updated. - * src/bdf/bdfdrivr.c (BDF_Face_Init): Updated. - * src/cff/cffload.c (cff_font_load): Updated. - - * src/cff/cffobjs.c (cff_face_init): Make function exit early for - pure CFF fonts if `font_index < 0'. - Updated. - - * src/cid/cidobjs.c (cid_face_init): Updated. - * src/pcf/pcfdrivr.c (PCF_Face_Init): Updated. - * src/pfr/pfrobjs.c (pfr_face_init): Updated. - * src/type1/t1objs.c (T1_Face_Init): Updated. - * src/type42/t42objs.c (T42_Face_Init): Updated. - * src/winfonts/winfnt.c (fnt_face_get_dll_font, FNT_Face_Init): - Updated. - - * docs/CHANGES: Updated. - -2015-08-12 Alexei Podtelezhnikov - - [type1,cff,cid] Streamline font matrix application. - - * src/type1/t1gload.c (T1_Load_Glyph): Directly modify advances only - if font matrix is not trivial. - * src/cff/cffgload.c (cff_slot_load): Ditto. - * src/cid/cidgload.c (cid_slot_load_glyph): Ditto for advances and the - entire outline. - -2015-08-11 Werner Lemberg - - [builds/unix] Minor. - - * builds/unix/configure.raw: - s/lib{priv,staticconf}/libs{priv,staticconf}/ for orthogonality with - similarly named uppercase variables. - -2015-08-10 Alexei Podtelezhnikov - - [type1,cid,type42] Minor improvements. - - * src/type1/t1load.c (t1_parse_font_matrix): Scale units per EM only - when necessary. Refresh comments. - * src/cid/cidload.c (cid_parse_font_matrix): Ditto. - * src/type42/t42parse.c (t42_parse_font_matrix): Refresh comments. - -2015-08-08 Werner Lemberg - - [type42] Fix glyph access. - - This is a severe bug: We've missed one level of indirection, as - described in the Type 42 specification. As a result, ftview - sometimes showed incorrect glyphs for given glyph names, and even - displayed `error 0x0006' (invalid argument!) in case the number of - glyph indices differed between the Type 42 font and the embedded - TTF. - - Apparently, noone ever noticed it; this shows how much Type 42 fonts - are in use... - - * src/type42/t42objs.c (T42_GlyphSlot_Load): Map Type 42 glyph index - to embedded TTF's glyph index. - -2015-08-08 Werner Lemberg - - [type42] Minor clean-up. - - * src/type42/t42parse.c (t42_parse_font_matrix): Remove unused - variable. - -2015-08-06 Alexei Podtelezhnikov - - [type42] Parse FontMatrix according to specifications. - - * src/type42/t42parse.c (t42_parse_font_matrix): Type 42 FontMatrix - does not need scaling by 1000. Units_per_EM are taken from the - embedded TrueType. - -2015-08-06 Werner Lemberg - - [autofit] Improve Arabic hinting. - - Problem reported by Titus Nemeth (by using - ttfautohint). - - * src/autofit/afblue.dat: Add neutral blue zone for the tatweel - character. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - -2015-08-05 Alexei Podtelezhnikov - - [truetype] Clean up types. - - * src/truetype/ttobjs.c (TT_Size): Move declaration from here. - * include/freetype/internal/tttypes.h (TT_Size): ... to here. - (TT_LoaderRec): Switch to appropriate types for `face' and `size'. - * src/truetype/ttgload.c: Remove corresponding type casts. - * src/truetype/ttsubpix.c: Ditto. - -2015-08-05 Werner Lemberg - - [autofit] Improve recognition of flat vs. rounded segments. - - Lower the flatness threshold from upem/8 to upem/14, making the - auto-hinter accept shorter elements. - - Synchronize flat/round stem selection algorithm with blue zone code. - - * src/autofit/aflatin.c (FLAT_THRESHOLD): New macro. - (af_latin_metrics_init_blues): Use it. - (af_latin_hints_compute_segments): Collect information on maximum - and minimum coordinates of `on' points; use this to add a constraint - for the flat/round decision similar to - `af_latin_metrics_init_blues'. - -2015-08-04 Werner Lemberg - - Another left-shift bug (#45681). - - * src/base/ftobjs.c (IsMacBinary): Only accept positive values for - `dlen'. - -2015-08-03 Alexei Podtelezhnikov - - [base] Fix `ft_corner_orientation'. - - Remove casting from `FT_Long' to `FT_Int' that might change the sign - of the return value and make it faster too. - - * src/base/ftcalc.c (ft_corner_orientation): On 32-bit systems, stay - with 32-bit arithmetic when safe. Use plain math on 64-bit systems. - * src/pshinter/pshalgo.c: Remove old unused code. - -2015-08-03 Werner Lemberg - - * src/truetype/ttgload.c (load_truetype_glyph) - [TT_CONFIG_OPTION_GX_VAR_SUPPORT]: Fix crash for composite glyphs - having a depth greater than 1. - -2015-08-03 Werner Lemberg - - Fix typo in clang bug from 2015-07-31 (#45678). - - * src/base/ftrfork.c (FT_Raccess_Get_HeaderInfo): Fix inequality. - -2015-08-02 Werner Lemberg - - * CMakeLists.txt: Improve shared library support. - - Based on a patch from John Cary . - -2015-08-02 Werner Lemberg - - * builds/unix/freetype-config.in (enable_shared): Remove. Unused. - -2015-08-02 Werner Lemberg - - Fix more invalid left-shifts. - - * src/pfr/pfrgload.c (pfr_glyph_load_compound): Use multiplication, - not left-shift. - - * src/truetype/ttgxvar.c (ft_var_load_avar, ft_var_load_gvar, - tt_face_vary_cvt, TT_Vary_Apply_Glyph_Deltas): Use multiplication, - not left-shift. - -2015-07-31 Werner Lemberg - - Fix some bugs found by clang's `-fsanitize=undefined' (#45661). - - * src/base/ftrfork.c (FT_Raccess_Get_HeaderInfo): Only accept - positive values from header. - Check overflow. - - * src/base/ftoutln.c (SCALED): Correctly handle left-shift of - negative values. - - * src/bdf/bdf.h (_bdf_glyph_modified, _bdf_set_glyph_modified, - _bdf_clear_glyph_modified): Use unsigned long constant. - - * src/bdf/bdfdrivr.c (BDF_Size_Select, BDF_Glyph_Load): Don't - left-shift values that can be negative. - - * src/pcf/pcfdrivr.c (PCF_Size_Select, PCF_Glyph_Load): Don't - left-shift values that can be negative. - - * src/raster/ftraster.c (SCALED): Correctly handle left-shift of - negative values. - - * src/sfnt/ttsbit.c (tt_face_load_strike_metrics): Don't left-shift - values that can be negative. - - * src/truetype/ttgload.c (TT_Load_Composite_Glyph, - compute_glyph_metrics, load_sbit_image): Don't left-shift values - that can be negative. - -2015-07-31 Werner Lemberg - - Define FT_LONG_MAX. - - * include/freetype/config/ftstdlib.h (FT_LONG_MAX): New macro. - * src/cff/cf2arrst.c (cf2_arrstack_setNumElements): Use it. - -2015-07-28 Alexei Podtelezhnikov - - * src/base/ftcalc.c (FT_Vector_NormLen): Clarify. - -2015-07-27 Alexei Podtelezhnikov - - * src/base/ftcalc.c (FT_Vector_NormLen): Explicate type conversions. - -2015-07-26 Matthias Clasen - - [cff] Don't use `hmtx' table for LSB (#45520). - - * src/cff/cffgload.c (cff_slot_load): Use `htmx' table for advance - width only. Bug introduced 2015-04-10. - -2015-07-09 Werner Lemberg - - Better support of user-supplied C++ namespaces. - - See - - https://lists.nongnu.org/archive/html/freetype-devel/2015-07/msg00008.html - - for a rationale. - - * src/autofit/afpic.h, src/base/basepic.h, src/cff/cffpic.h, - src/pshinter/pshpic.h, src/psnames/pspic.h, src/raster/rastpic.h, - src/sfnt/sfntpic.h, src/smooth/ftspic.h, src/truetype/ttpic.h - (FT_BEGIN_HEADER, FT_END_HEADER): Move macro calls to not enclose - header files that contain FT_{BEGIN,END}_HEADER macros by - themselves. - - * src/autofit/aftypes.h [FT_DEBUG_AUTOFIT]: Include - FT_CONFIG_STANDARD_LIBRARY_H earlier. - - * src/truetype/ttpic.h: Include FT_INTERNAL_PIC_H. - -2015-07-07 Werner Lemberg - - [sfnt] Make `tt_face_get_name' member of the SFNT interface. - - * include/freetype/internal/sfnt.h (TT_Get_Name_Func): New - prototype. - (SFNT_Interface, FT_DEFINE_SFNT_INTERFACE): New member `get_name'. - - * src/sfnt/sfdriver.c (sfnt_interface): Updated. - - * src/sfnt/sfobjs.c (tt_face_get_name): Tag it with `LOCAL_DEF'. - * src/sfnt/sfobjs.h: Add prototype for it. - -2015-06-30 Werner Lemberg - - Fix some clang compiler warnings. - - * src/base/ftoutln.c (FT_Outline_EmboldenXY), src/cff/cf2intrp.c - (cf2_interpT2CharString), src/truetype/ttgload.c - (load_truetype_glyph), src/truetype/ttgxvar.c (tt_handle_deltas), - src/truetype/ttinterp.c (Ins_INSTCTRL): Fix signedness issues. - -2015-06-29 Alexei Podtelezhnikov - - [truetype] Speed up bytecode interpreter. - - * src/truetype/ttinterp.c (Normalize): Use `FT_Vector_NormLen'. - -2015-06-29 Alexei Podtelezhnikov - - [base] Speed up emboldening. - - * src/base/ftoutln.c (FT_Outline_EmboldenXY): Use - `FT_Vector_NormLen'. - -2015-06-29 Alexei Podtelezhnikov - - [base] Implement fast vector normalization. - - The function uses Newton's iterations instead of dividing vector - components by its length, which needs a square root. This is, - literally, a bit less accurate but a lot faster. - - * src/base/ftcalc.c (FT_Vector_NormLen): New function. - -2015-06-28 Werner Lemberg - - * CMakeLists.txt: Always create `ftconfig.h'. - - For non-UNIX builds, the file stays unmodified. However, it's - better to have the main configuration files at the same place - regardless of the OS. - -2015-06-28 Werner Lemberg - - * CMakeLists.txt: Improve MSVC support (#43737). - -2015-06-28 Werner Lemberg - - [cmake] Check for libraries and create `ftoption.h'. - - * builds/FindHarfBuzz.cmake: New file, taken from - - https://trac.webkit.org/browser/trunk/Source/cmake/FindHarfBuzz.cmake - - * CMakeLists.Txt: Add path to local cmake modules. - Find dependencies for zlib, bzip2, libpng, and harfbuzz. - Create `ftoption.h' file. - Set up include and linker stuff for libraries. - -2015-06-28 Werner Lemberg - - * CMakeLists.txt: Fix creation of `ftconfig.h'. - Check for UNIX header files using `check_include_file'. - Set up correct header include directories. - -2015-06-28 Werner Lemberg - - * CMakeLists.txt: Disallow in-source builds. - -2015-06-27 Werner Lemberg - - * src/tools/docmaker/utils.py (check_output): Add missing `\n'. - -2015-06-26 Werner Lemberg - - * CMakeLists.txt: Select platform-dependent `ftdebug.c'. - -2015-06-25 Werner Lemberg - - * CMakeLists.txt: Use cmake functions for generating `ftconfig.h'. - Additionally, do this for UNIX only. - -2015-06-25 Werner Lemberg - - * CMakeLists.txt (BASE_SRCS): Use `ftbase.c' and `psnames.c'. - -2015-06-25 Werner Lemberg - - Another adjustment to header locations. - - This change is a result of a discussion thread on freetype-devel - - https://lists.nongnu.org/archive/html/freetype-devel/2015-06/msg00041.html - - Re-introduce the `freetype2' subdirectory for all FreeType header - files after installation, and rename the `freetype2' subdirectory in - the git repository to `freetype'. - - * include/freetype2: Renamed to... - * include/freetype: This. - - * CMakeLists.txt (PUBLIC_HEADERS, PUBLIC_CONFIG_HEADERS, - PRIVATE_HEADERS): Updated. - Update creation of `ftconfig.h'. - Install generated `ftconfig.h'. - - * Jamfile (HDRMACRO, RefDoc), autogen.sh: Updated. - - * builds/amiga/include/config/ftconfig.h, builds/freetype.mk - (PUBLIC_DIR), builds/symbian/bld.inf, builds/toplevel.mk (work), - builds/unix/freetype2.in: Updated. - - * builds/unix/freetype-config.in: Updated. - * builds/unix/configure.raw: Don't check for `rmdir'. - * builds/unix/unix-def.in (DELDIR): Use `rm -rf', which is portable - according to the autoconf info manual. - * builds/unix/install.mk (install, uninstall, - distclean_project_unix): Update and simplify. - - * builds/wince/*, builds/windows/*: Updated. - - * devel/ft2build.h, include/ft2build.h: Updated. - - * include/freetype2/config/ftheader.h, - include/freetype2/internal/ftserv.h, - include/freetype2/internal/internal.h: Update all header file - macros. - - * src/tools/chktrcmp.py (TRACE_DEF_FILES): Updated. - - * docs/*: Updated. - -2015-06-24 Alexei Podtelezhnikov - - * src/bdf/bdflib.c (_bdf_parse_start): Disallow 0 bpp. - -2015-06-24 Alexei Podtelezhnikov - - * src/bdf/bdflib.c (_bdf_parse_start): Simplify bpp parsing. - -2015-06-23 Werner Lemberg - - s/TYPEOF/FT_TYPEOF/ (#45376). - - * builds/unix/ftconfig.in, builds/vms/ftconfig.in, - include/freetype2/config/ftconfig.h, - include/freetype2/internal/ftobjs.h, src/autofit/afwarp.h: Do it. - -2015-06-22 Werner Lemberg - - Fix Savannah bug #45097. - - We no longer `pollute' the namespace of possible header file names; - instead we move `ft2build.h' up by one level so that it gets - installed in the default include directory (e.g., - /usr/local/include). After this commit, only `ft2build.h' stays in - the compiler's include path. - - No visible changes for the user who follows the standard FreeType - header inclusion rules. - - * include/*: Move to ... - * include/freetype2/*: This directory, except `ft2build.h'. - - * CMakeLists.txt (PUBLIC_HEADERS, PUBLIC_CONFIG_HEADERS, - PRIVATE_HEADERS), Jamfile (HDRMACRO, RefDoc), autogen.sh: Updated. - - * builds/amiga/include/config/ftconfig.h, builds/freetype.mk - (PUBLIC_DIR), builds/symbian/bld.inf, builds/toplevel.mk (work), - builds/unix/install.mk (install, uninstall), - builds/unix/freetype2.in: Updated. - - * builds/unix/freetype-config.in: Updated. - Emit -I directory only if it is not `/usr/include'. - - * builds/wince/*, builds/windows/*: Updated. - - * devel/ft2build.h, include/ft2build.h: Updated. - - * include/freetype2/config/ftheader.h, - include/freetype2/internal/ftserv.h, - include/freetype2/internal/internal.h: Update all header file - macros. - - * src/tools/chktrcmp.py (TRACE_DEF_FILES): Updated. - -2015-06-21 Werner Lemberg - - Make Jam support work again. - - This is just very basic stuff and just a little bit tested on - GNU/Linux only. I won't delve into this since I'm not a Jam user. - - * Jamfile: Call `HDRMACRO' for `ftserv.h' also. - (DEFINES): Replace with... - (CCFLAGS): ... this. - - * src/Jamfile: Don't call `HDRMACRO' for `internal.h'; this is - already handled in the top-level Jamfile. - - * src/autofit/Jamfile (DEFINES): Replace with... - (CCFLAGS): ... this. - (_sources): Add missing files. - - * src/cache/Jamfile: Don't call `HDRMACRO' for `ftcache.h'; it no - longer contains macro header definitions. - - * src/base/Jamfile, src/cff/Jamfile, src/sfnt/Jamfile, - src/truetype/Jamfile (_sources): Add missing files. - -2015-06-16 Werner Lemberg - - Fix Savannah bug #45326. - - * src/sfnt/sfntpic.h (SFNT_SERVICES_GET): Remove duplicate - definitions. - -2015-06-07 Werner Lemberg - - * Version 2.6 released. - ======================= - - - Tag sources with `VER-2-6'. - - * docs/VERSION.DLL: Update documentation and bump version number to - 2.6. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.5.5/2.6/, s/255/26/. - - * include/freetype/freetype.h (FREETYPE_MINOR): Set to 6. - (FREETYPE_PATCH): Set to 0. - - * builds/unix/configure.raw (version_info): Set to 18:0:12. - * CMakeLists.txt (VERSION_MINOR): Set to 6. - (VERSION_PATCH): Set to 0. - - * src/autofit/afmodule.c [!FT_MAKE_OPTION_SINGLE_OBJECT]: Add - declarations for dumping functions. - - * src/truetype/ttinterp.c (TT_New_Context): Pacify compiler. - - * builds/toplevel.mk: Use `freetype.mk's code to compute the version - string. - Don't include a zero patch level in version string. - * builds/freetype.mk: Remove code for computing the version string. - -2015-06-06 Ashish Azad - - Fix Savannah bug #45260. - - * src/pfr/pfrdrivr.c (pfr_get_kerning): Fix typo. - -2015-06-03 Werner Lemberg - - [truetype] Fix memory leak. - - Problem reported by Grissiom ; in - - https://lists.nongnu.org/archive/html/freetype/2015-05/msg00013.html - - there is an example code to trigger the bug. - - * src/truetype/ttobjs.c (tt_size_init_bytecode): Free old `size' - data before allocating again. Bug most probably introduced four - years ago in version 2.4.3. - -2015-06-02 Werner Lemberg - - [raster] Add more tracing. - - * src/raster/ftraster.c (FT_TRACE7) [_STANDALONE_]: Define. - (Vertical_Sweep_Span, Vertical_Sweep_Drop, Horizontal_Sweep_Span, - Horizontal_Sweep_Drop, Render_Glyph): Add tracing calls. - -2015-06-01 Werner Lemberg - - [truetype] While tracing opcodes, show code position and stack. - - * src/truetype/ttinterp.c: Change all existing TRACE7 calls to - TRACE6. - (opcode_name): Add string lengths. - (TT_RunIns): Implement display of code position and stack. - -2015-05-31 Werner Lemberg - - [truetype] In GX, make private point numbers work correctly. - - This is completely missing in Apple's documentation: If a `gvar' - tuple uses private point numbers (this is, deltas are specified for - some points only), the uncovered points must be interpolated for - this tuple similar to the IUP bytecode instruction. Examples that - need this functionality are glyphs `Oslash' and `Q' in Skia.ttf. - - * src/truetype/ttgxvar.c (tt_delta_shift, tt_delta_interpolate, - tt_handle_deltas): New functions. - (TT_Vary_Get_Glyph_Deltas): Renamed to... - (TT_Vary_Apply_Glyph_Deltas): ... this; it directly processes the - points and does no longer return an array of deltas. - Add tracing information. - Call `tt_handle_deltas' to interpolate missing deltas. - Also fix a minor memory leak in case of error. - - * src/truetype/ttgxvar.h: Updated. - - * src/truetype/ttgload.c (TT_Process_Simple_Glyph, - load_truetype_glyph): Updated. - -2015-05-31 Werner Lemberg - - [truetype] In GX, make intermediate tuplets work at extrema. - - * src/truetype/ttgxvar.c (ft_var_apply_tuple): Fix range condition. - -2015-05-31 Werner Lemberg - - [truetype] Add tracing information to GX code. - - * src/truetype/ttgxvar.c (ft_var_load_avar, ft_var_load_gvar, - ft_var_apply_tuple, TT_Get_MM_Var, TT_Set_MM_Blend, - TT_Set_Var_Design, tt_face_vary_cvt): Do it. - -2015-05-28 Werner Lemberg - - * src/tools/apinames.c (names_dump): Fix invalid reference. - - Problem reported by Guzman Mosqueda, Jose R - . - -2015-05-24 Werner Lemberg - - [truetype] Fix commit from 2015-05-22. - - * src/truetype/ttgload.c, src/truetype/ttinterp.c: Guard new code - with `TT_CONFIG_OPTION_SUBPIXEL_HINTING'. - - Problem reported by Nikolaus Waxweiler . - -2015-05-23 Werner Lemberg - - [truetype] Fix return values of GETINFO bytecode instruction. - - * src/truetype/ttinterp.h (TT_ExecContextRec): New fields - `vertical_lcd' and `gray_cleartype'. - - * src/truetype/ttgload.c (tt_loader_init): Initialize new fields. - Change `symmetrical smoothing' to TRUE, since FreeType produces - exactly this. - - * src/truetype/ttinterp.c (Ins_GETINFO): Fix selector/return bit - values for symmetrical smoothing, namely 11/18. - Handle bits for vertical LCD subpixels (8/15) and Gray ClearType - (12/19). - -2015-05-23 Werner Lemberg - - [truetype] Minor. - - * src/truetype/ttinterp.h (TT_ExecContext): - s/subpixel/subpixel_hinting. - - * src/truetype/ttgload.c, src/truetype/ttgload.h: Updated. - -2015-05-22 Werner Lemberg - - [truetype] Support selector index 3 of the INSTCTRL instruction. - - This flag activates `native ClearType hinting', disabling backward - compatibility mode as described in Greg Hitchcocks whitepaper. In - other words, it enables unrestricted functionality of all TrueType - instructions in ClearType. - - * src/truetype/ttgload.c (tt_get_metrics): Call `sph_set_tweaks' - unconditionally. - (tt_loader_init): Unset `ignore_x_mode' flag if bit 2 of - `GS.instruct_control' is active. - - * src/truetype/ttinterp.c (Ins_INSTCTRL): Handle selector index 3. - (Ins_GETINFO): Updated. - - * docs/CHANGES: Document it. - -2015-05-20 Werner Lemberg - - [truetype] Minor. - - * src/truetype/ttinterp.h (SetSuperRound): Fix type of `GridPeriod' - argument. - -2015-05-17 Werner Lemberg - - [truetype] Fix loading of composite glyphs. - - * src/truetype/ttgload.c (TT_Load_Composite_Glyph): If the - ARGS_ARE_XY_VALUES flag is not set, handle argument values as - unsigned. I trust `ttx' (which has exactly such code) that it does - the right thing here... - - The reason that noone has ever noticed this bug is probably the fact - that point-aligned subglyphs are rare, as are subglyphs with a - number of points in the range [128;255], which is quite large (or - even in the range [32768;65535], which is extremely unlikely). - -2015-05-12 Chris Liddell - - [cff] Make the `*curveto' operators more tolerant. - - * src/cff/cf2intrp.c (cf2_interpT2CharString): The opcodes - `vvcurveto', `hhcurveto', `vhcurveto', and `hvcurveto' all iterate, - pulling values off the stack until the stack is exhausted. - Implicitly the stack must be a multiple (or for subtly different - behaviour) a multiple plus a specific number of extra values deep. - If that's not the case, enforce it (as the old code did). - -2015-05-12 Chris Liddell - - [cff] fix incremental interface with new cff code. - - * src/cff/cf2ft.c (cf2_getSeacComponent): When using the incremental - interface to retrieve glyph data for a SEAC, it be left to the - incremental interface callback to apply the encoding to raw - character index (as it was in the previous code). - -2015-04-29 Alexei Podtelezhnikov - - [autofit] Speed up IUP. - - * src/autofit/afhints.c (af_iup_interp): Separate trivial snapping to - the same position from true interpolation, use `scale' to reduce - divisions. - -2015-04-28 Werner Lemberg - - [cff] Use `name' table for PS name if we have a SFNT-CFF. - - This follows the OpenType 1.7 specification. See - - https://tug.org/pipermail/tex-live/2015-April/036634.html - - for a discussion. - - * src/cff/cffdrivr.c (cff_get_ps_name): Use the `sfnt' service if we - have an SFNT. - -2015-04-27 Alexei Podtelezhnikov - - [truetype] Speed up IUP. - - * src/truetype/ttinterp.c (_iup_worker_interpolate): Separate trivial - snapping to the same position from true interpolation. - -2015-04-21 Werner Lemberg - - [autofit] By default, enable warping code but switch off warping. - - Suggested by Behdad. - - * include/config/ftoption.h: Define AF_CONFIG_OPTION_USE_WARPER. - - * src/autofit/afmodule.c (af_autofitter_init): Initialize `warping' - with `false'. - -2015-04-21 Werner Lemberg - - * docs/CHANGES: Updated. - -2015-04-21 Werner Lemberg - - [autofit] Introduce `warping' property. - - This code replaces the debugging hook from the previous commit with - a better, more generic solution. - - * include/ftautoh.h: Document it. - - * src/autofit/afmodule.h (AF_ModuleRec) - [AF_CONFIG_OPTION_USE_WARPER]: Add `warping' field. - - * src/autofit/afmodule.c (_af_debug_disable_warper): Remove. - (af_property_set, af_property_get, af_autofitter_init) - [AF_CONFIG_OPTION_USE_WARPER]: Handle `warping' option. - - * src/autofit/afhints.h (AF_HINTS_DO_WARP): Remove use of the no - longer existing `_af_debug_disable_warper'. - - * src/autofit/afcjk.c (af_cjk_hints_init), src/autofit/aflatin.c - (af_latin_hints_init), src/autofit/aflatin2.c (af_latin2_hints_init) - [AF_CONFIG_OPTION_USE_WARPER]: Add `AF_SCALER_FLAG_NO_WARPER' to the - scaler flags if warping is off. - - * src/autofit/aftypes.h: Updated. - -2015-04-16 Werner Lemberg - - [autofit] Add debugging hook to disable warper. - - * src/autofit/afmodule.c (_af_debug_disable_warper) - [FT_DEBUG_AUTOFIT]: New global variable. - - * src/autofit/aftypes.h: Updated. - (AF_SCALER_FLAG_NO_WARPER): New macro (not actively used yet). - - * src/autofit/afhints.h (AF_HINTS_DO_WARP): New macro. - - * src/autofit/aflatin.c (af_latin_hints_apply) - [AF_CONFIG_OPTION_USE_WARPER]: Use `AF_HINTS_DO_WARP' to control use - of warper. - - * src/autofit/afcjk.c (af_cjk_hints_init, af_cjk_hints_apply) - [AF_CONFIG_OPTION_USE_WARPER]: Synchronize with `aflatin.c'. - - * src/autofit/aflatin2.c (af_latin2_hints_apply) - [AF_CONFIG_OPTION_USE_WARPER]: Synchronize with `aflatin.c'. - -2015-04-10 Werner Lemberg - - [cff] Update advance width handling to OpenType 1.7. - - Problem reported by Behdad. - - * src/cff/cffdrivr.c (cff_get_advances): Handle SFNT case - separately. - - * src/cff/cffgload.c (cff_slot_load): Use advance width and side - bearing values from `hmtx' table if present. - -2015-04-03 Alexei Podtelezhnikov - - * src/autofit/afhints.c (af_glyph_hints_reload): Use do-while loop. - -2015-04-02 Alexei Podtelezhnikov - - * src/autofit/aflatin.c (af_latin_hint_edges): Reduce logic. - -2015-04-01 Alexei Podtelezhnikov - - [autofit] Finish the thought. - - * src/autofit/afhints.c (af_direction_compute): make sure the long arm - is never negative so that its `FT_ABS' is not necessary. - -2015-04-01 Werner Lemberg - - [autofit] Call dumper functions for tracing. - - * src/autofit/afcjk.c (af_cjk_hints_apply): Remove dead code. - * src/autofit/afhints.c (af_glyph_hints_dump_points): Minor - improvement. - * src/autofit/afmodule.c (af_autofitter_load_glyph): Implement it. - -2015-04-01 Werner Lemberg - - [autofit] Make debugging stuff work again. - - The interface to ftgrid was broken in the series of commits starting - with - - [autofit] Allocate AF_Loader on the stack instead of AF_Module. - - from 2015-01-14. - - * src/autofit/afmodule.c (_af_debug_hints_rec) [FT_DEBUG_AUTOFIT]: - Use a global AF_GlyphHintsRec object for debugging. - (af_autofitter_done, af_autofitter_load_glyph): Updated. - - * src/autofit/afloader.c (af_loader_init, af_loader_done): Updated. - -2015-04-01 Werner Lemberg - - * src/autofit/afhints.c (af_glyph_hints_done): Fix minor thinko. - -2015-03-29 Werner Lemberg - - [cff] Fix Savannah bug #44629. - - * src/cff/cf2font.h (CF2_MAX_SUBR), src/cff/cffgload.h - (CFF_MAX_SUBRS_CALLS): Set to 16. - -2015-03-29 Werner Lemberg - - [type1, truetype] Make the MM API more flexible w.r.t. `num_coords'. - - This commit allows `num_coords' to be larger or smaller than the - number of available axes while selecting a design instance, either - ignoring excess data or using defaults if data is missing. - - * src/truetype/ttgxvar.c (TT_Set_MM_Blend, TT_Set_Var_Design): - Implement it. - - * src/type1/t1load.c (T1_Set_MM_Blend, T1_Set_MM_Design, - T1_Set_Var_Design): Ditto. - -2015-03-29 Werner Lemberg - - [type1] Minor. - - * src/type1/t1load.c (T1_Set_MM_Blend, T1_Set_MM_Design): Use - FT_THROW. - (T1_Set_Var_Design): Use T1_MAX_MM_AXIS and FT_THROW. - -2015-03-27 Werner Lemberg - - [cff] Trace charstring nesting levels. - - * src/cff/cf2intrp.c (cf2_interpT2CharString) : Implement it. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings) - : Ditto. - -2015-03-21 Alexei Podtelezhnikov - - [base] Optimize `FT_Angle_Diff'. - - Under normal circumstances we are usually close to the desired range - of angle values, so that the remainder is not really necessary. - - * src/base/fttrigon.c (FT_Angle_Diff): Use loops instead of remainder. - - * src/autofit/aftypes.h (AF_ANGLE_DIFF): Ditto in the unused macro. - -2015-03-21 Werner Lemberg - - [truetype] Improve `gvar' handling. - - * src/truetype/ttgxvar.c (ft_var_readpackedpoints): Correctly handle - single-element runs. Cf. glyph `Q' in Skia.ttf with weights larger - than the default. - -2015-03-20 Alexei Podtelezhnikov - - * src/base/fttrigon.c (FT_Vector_Rotate): Minor refactoring. - -2015-03-17 Alexei Podtelezhnikov - - Fix Savannah bug #44412 (part 2). - - * src/base/fttrigon.c (FT_Sin, FT_Cos, FT_Tan): Call `FT_Vector_Unit'. - -2015-03-11 Werner Lemberg - - [autofit] Add support for Arabic script. - - Thanks to Titus Nemeth for guidance! - - * src/autofit/afblue.dat: Add blue zone data for Arabic. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Arabic standard characters. - - * src/autofit/afranges.c: Add Arabic data. - - * src/autofit/afstyles.h: Add Arabic data. - - * docs/CHANGES: Document it. - -2015-03-11 Werner Lemberg - - Rename `svxf86nm.h' to `svfntfmt.h'; update related symbols. - - * include/internal/ftserv.h (FT_SERVICE_XFREE86_NAME_H): Renamed - to... - (FT_SERVICE_FONT_FORMAT_H): This. - - * include/internal/services/svfntfmt.h (FT_XF86_FORMAT_*): Renamed - to ... - (FT_FONT_FORMAT_*): This. - - src/base/ftfntfmt.c, src/bdf/bdfdrivr.c, src/cff/cffdrivr.c, - src/cid/cidriver.c, src/pcf/pcfdrivr.c, src/pfr/pfrdrivr.c, - src/truetype/ttdriver.c, src/type1/t1driver.c, - src/type42/t42drivr.c, src/winfonts/winfnt.c: Updated. - -2015-03-11 Werner Lemberg - - [base] Rename `FT_XFREE86_H' to `FT_FONT_FORMATS_H'. - - * include/config/ftheader.h: Implement it. - * src/base/ftfntfmt.c, docs/CHANGES: Updated. - -2015-03-11 Werner Lemberg - - [base] Rename `FT_Get_X11_Font_Format' to `FT_Get_Font_Format'. - - * include/ftfntfmt.h, src/base/ftfntfmt.c: Implement it. - - * docs/CHANGES: Updated. - -2015-03-11 Werner Lemberg - - Fix automatic copyright updating. - - * src/tools/update-copyright: Make scanning of `no-copyright' - actually work. - - * src/tools/no-copyright: Don't include README in general. - -2015-03-11 Werner Lemberg - - Rename `ftxf86.[ch]' to `ftfntfmt.[ch]'. - - CMakeLists.txt, builds/amiga/makefile, builds/amiga/makefile.os4, - builds/amiga/smakefile, builds/mac/FreeType.m68k_cfm.make.txt, - builds/mac/FreeType.m68k_far.make.txt, - builds/mac/FreeType.ppc_carbon.make.txt, - builds/mac/FreeType.ppc_classic.make.txt, builds/symbian/bld.inf, - builds/symbian/freetype.mmp, builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2008-ce/freetype.vcproj, - builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/freetype.vcxproj.filters, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, docs/INSTALL.ANY, - include/config/ftheader.h, include/ftfntfmt.h, modules.cfg, - src/base/ftfntfmt.c, vms_make.com: Updated. - -2015-03-10 Alexei Podtelezhnikov - - Fix Savannah bug #44412 (part 1). - - * src/base/ftstroke.c (ft_stroker_inside): Handle near U-turns. - -2015-03-10 Werner Lemberg - - [base] Rename `FT_Bitmap_New' to `FT_Bitmap_Init'. - - * include/ftbitmap.h, src/base/ftbitmap.c: Implement it. - Update all callers. - - * docs/CHANGES: Updated. - -2015-03-06 Werner Lemberg - - * src/sfnt/ttload.c (tt_face_load_font_dir): Fix compiler warning. - - Found by Alexei. - -2015-03-05 Alexei Podtelezhnikov - - * src/base/ftstroke.c: Simplify. - -2015-03-04 Werner Lemberg - - [truetype] Some fixes and code refactoring in `ttgxvar.c'. - - * src/truetype/ttgxvar.c (ft_var_readpackedpoints): Fix return value - of `point_cnt' if two bytes are read. - Use a more vertical coding style. - (ft_var_readpackeddeltas): Use FT_UInt for `delta_cnt' parameter. - Use a more vertical coding style. - -2015-03-03 Werner Lemberg - - [autofit] Fix Savannah bug #44241. - - * src/autofit/aflatin.c (af_latin_metrics_init_blues): Reject glyphs - with less than 3 points. - -2015-03-02 Werner Lemberg - - Simplify `TYPEOF' macro. - - No need for two arguments. - - * include/config/ftconfig.h, builds/unix/ftconfig.in, - builds/vms/ftconfig.h (TYPEOF): Updated. - - * include/internal/ftobjs.h (FT_PAD_FLOOR, FT_PIX_FLOOR), - src/autofit/afwarp.h (AF_WARPER_FLOOR): Updated. - -2015-03-01 Werner Lemberg - - Various compiler warning fixes for `make multi'. - - * src/autofit/afcjk.c (af_cjk_hints_compute_blue_edges), - src/autofit/aflatin.c (af_latin_hint_compute_blue_edges, - af_latin_hint_edges), src/autofit/aflatin2.c - (af_latin2_hints_compute_blue_edges, af_latin2_hint_edges): Declare - as `static'. - - * src/cache/ftccmap.c (FTC_CMAP_QUERY_HASH, FTC_CMAP_NODE_HASH): - Removed. Unused. - * src/cache/ftcimage.c: Include FT_INTERNAL_OBJECTS_H. - * src/cache/ftcmanag.c (FTC_LRU_GET_MANAGER): Removed. Unused. - - * src/cff/cf2intrp.c: Include `cf2intrp.h'. - * src/cff/cffdrivr.c (PAIR_TAG): Removed. Unused. - - * src/gzip/ftgzip.c (NO_DUMMY_DECL): Removed. Unused. - - * src/psaux/afmparse.c (afm_parser_read_int): Declare as `static'. - - * src/pshinter/pshalgo.c (STRONGER, PSH_ZONE_MIN, PSH_ZONE_MAX): - Removed. Unused. - - * src/raster/ftraster.c (Render_Glyph): Declare as `static'. - - * src/sfnt/ttpost.c (load_format_20): Fix signedness warning. - - * src/truetype/ttdriver.c (PAIR_TAG): Removed. Unused. - * src/truetype/ttsubpix.c (is_member_of_family_class, - is_member_of_style_class): Declare as `static'. - - * src/type1/t1gload.c (T1_Parse_Glyph_And_Get_Char_String): Declare - as `static'. - * src/type1/t1load.c (mm_axis_unmap, mm_weights_unmap): Declare as - `static'. - (T1_FIELD_COUNT): Removed. Unused. - * src/type1/t1parse.h (T1_Done_Table): Removed. Unused. - - * src/type42/t42parse.c (T1_Done_Table): Removed. Unused. - -2015-02-25 Werner Lemberg - - [psaux] Signedness fixes. - - * include/internal/psaux.h, src/psaux/afmparse.c, - src/psaux/afmparse.h, src/psaux/psconv.c, src/psaux/psobjs.c, - src/psaux/t1cmap.c, src/psaux/t1decode.c: Apply. - -2015-02-25 Werner Lemberg - - [otvalid] Signedness fixes. - - * src/otvalid/otvcommn.c, src/otvalid/otvgdef.c, - src/otvalid/otvgpos.c, src/otvalid/otvgsub.c, src/otvalid/otvmath.c: - Apply. - -2015-02-25 Werner Lemberg - - * src/bzip2/ftbzip2.c (ft_bzip2_alloc): Signedness fix. - -2015-02-25 Werner Lemberg - - [lzw] Signedness fixes. - - * src/lzw/ftzopen.c, src/lzw/ftzopen.h: Apply. - -2015-02-25 Werner Lemberg - - [gxvalid] Signedness fixes. - - * src/gxvalid/gxvbsln.c, src/gxvalid/gxvcommn.c, - src/gxvalid/gxvcommn.h, src/gxvalid/gxvjust.c, - src/gxvalid/gxvkern.c, src/gxvalid/gxvlcar.c, src/gxvalid/gxvmort.c, - src/gxvalid/gxvmort1.c, src/gxvalid/gxvmort2.c, - src/gxvalid/gxvmorx.c, src/gxvalid/gxvmorx1.c, - src/gxvalid/gxvmorx2.c, src/gxvalid/gxvopbd.c, - src/gxvalid/gxvprop.c, src/gxvalid/gxvtrak.c: Apply. - -2015-02-25 Werner Lemberg - - [cache] Signedness fixes. - - * src/cache/ftcbasic.c, src/cache/ftccmap.c, src/cache/ftcimage.c, - src/cache/ftcmanag.c, src/cache/ftcsbits.c: Apply. - -2015-02-25 Werner Lemberg - - Change dimension fields in `FTC_ImageTypeRec' to unsigned type. - - This doesn't break ABI. - - * include/ftcache.h (FTC_ImageTypeRec): Use unsigned types for - `width' and `height'. - - * docs/CHANGES: Document it. - -2015-02-25 Werner Lemberg - - [cache] Don't use `labs'. - - This is the only place in FreeType where this function was used. - - * include/config/ftstdlib.h (ft_labs): Remove. - - * src/cache/ftcimage.c (ftc_inode_weight): Replace `ft_labs' with - `FT_ABS'. - -2015-02-23 Werner Lemberg - - [cache] Replace `FT_PtrDist' with `FT_Offset'. - - * src/cache/ftccache.h (FTC_NodeRec): `FT_Offset' (a.k.a. `size_t') - is a better choice for `hash' to hold a pointer than `FT_PtrDist' - (a.k.a. `ptrdiff_t'), especially since the latter is signed, - causing zillions of signedness warnings. [Note that `hash' was of - type `FT_UInt32' before the change to `FT_PtrDist'.] - Update all users. - - * src/cache/ftcbasic.c, src/cache/ftccache.c, src/cache/ftccmap.c, - src/cache/ftcglyph.c, src/cache/ftcglyph.h: Updated. - -2015-02-23 Werner Lemberg - - [smooth, raster] Re-enable standalone compilation. - - * src/raster/ftraster.c (FT_RENDER_POOL_SIZE, FT_MAX) - [_STANDALONE_]: Define macros. - - * src/smooth/ftgrays.c (FT_RENDER_POOL_SIZE, FT_MAX, FT_ABS, - FT_HYPOT) [_STANDALONE_]: Define macros. - -2015-02-22 Werner Lemberg - - [smooth] Signedness fixes. - - * src/smooth/ftgrays.c, src/smooth/ftsmooth.c: Apply. - -2015-02-22 Werner Lemberg - - * src/raster/ftraster.c: Use the file's typedefs everywhere. - -2015-02-22 Werner Lemberg - - * src/sfnt/ttpost.c (load_format_20): Fix error tracing message. - - Bug introduced 6 commits earlier. - -2015-02-22 Werner Lemberg - - [pshinter] Fix thinko. - - * src/pshinter/pshalgo.c (psh_glyph_find_strong_points): Correctly - check `count'. - Bug introduced two commits earlier. - -2015-02-22 Werner Lemberg - - [raster] Signedness fixes. - - * src/raster/ftraster.c, src/raster/ftrend1.c: Apply. - -2015-02-22 Werner Lemberg - - [pshinter] Signedness fixes. - - * src/pshinter/pshalgo.c, src/pshinter/pshglob.c, - src/pshinter/pshrec.c: Apply. - -2015-02-22 Werner Lemberg - - [pshinter] Use macros for (unsigned) flags, not enumerations. - - * src/pshinter/pshalgo.h (PSH_Hint_Flags): Replace with macros. - Updated. - * src/pshinter/pshrec.h (PS_Hint_Flags): Replace with macros. - -2015-02-22 Werner Lemberg - - * src/pshinter/pshrec.c: Simplify. - (ps_hints_open, ps_hints_stem): Remove switch statement. - -2015-02-22 Werner Lemberg - - [sfnt] Signedness fixes. - - * src/sfnt/pngshim.c, src/sfnt/sfobjs.c, src/sfnt/ttcmap.c, - src/sfnt/ttkern.c, src/sfnt/ttload.c, src/sfnt/ttpost.c, - src/sfnt/ttsbit.c: Apply. - * src/sfnt/sfdriver.c: Apply. - (sfnt_get_ps_name): Simplify. - -2015-02-22 Werner Lemberg - - [bdf] Signedness fixes. - - * src/bdf/bdf.h, src/bdf/bdfdrivr.c, src/bdf/bdfdrivr.h, - src/bdf/bdflib.c: Apply. - -2015-02-22 Werner Lemberg - - * src/bdf/bdflib.c (_bdf_atous): New function. - (_bdf_parse_glyphs, _bdf_parse_start): Use it. - -2015-02-22 Werner Lemberg - - [pcf] Signedness fixes. - - * src/pcf/pcf.h, src/pcf/pcfdrivr.c: Apply. - * src/pcf/pcfread.c: Apply. - (pcf_get_encodings): Ignore invalid negative encoding offsets. - -2015-02-21 Werner Lemberg - - * src/winfonts/winfnt.c: Signedness fixes. - -2015-02-21 Werner Lemberg - - [type42] Signedness fixes. - - * src/type42/t42parse.c, src/type42/t42parse.h, - src/type42/t42types.h: Apply. - -2015-02-21 Werner Lemberg - - [pfr] Signedness fixes. - - * src/pfr/pfrdrivr.c, src/pfr/pfrgload.c, src/pfr/pfrload.c, - src/pfr/pfrload.h, src/pfr/pfrobjs.c, src/pfr/pfrsbit.c, - src/pfr/pfrtypes.h: Apply. - -2015-02-21 Werner Lemberg - - [cff] Minor signedness fixes related to last commit. - - * src/cff/cf2ft.c, src/cff/cf2intrp.c, src/cff/cffgload.c: Apply. - -2015-02-20 Werner Lemberg - - [cff] Thinkos in bias handling. - - Only the final result is always positive. - - Bug introduced three commits earlier. - - * src/cff/cffgload.c, src/cff/cffgload.h: Apply. - -2015-02-20 Werner Lemberg - - [cid] Fix signedness issues and emit some better error codes. - - * src/cid/cidgload.c, src/cid/cidload.h, src/cid/cidobjs.c, - src/cid/cidparse.h: Apply. - * src/cid/cidload.c: Apply. - (parse_fd_array): Reject negative values for number of dictionaries. - * src/cid/cidparse.c: Apply. - (cid_parser_new): Reject negative values for hex data length. - -2015-02-20 Werner Lemberg - - [cff] Signedness fixes for new engine. - - * src/cff/cf2arrst.c, src/cff/cf2fixed.h, src/cff/cf2ft.c, - src/cff/cf2ft.h, src/cff/cf2hints.c, src/cff/cf2intrp.c: Apply. - -2015-02-20 Werner Lemberg - - [cff] Signedness fixes for basic infrastructure and old engine. - - * include/internal/pshints.h, src/cff/cffdrivr.c, - src/cff/cffgload.c, src/cff/cffgload.h, src/cff/cffload.c, - src/cff/cffobjs.c, src/cff/cffparse.c, src/pshinter/pshrec.c: Apply. - -2015-02-19 Werner Lemberg - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Ignore `countSizePairs'. - - This is hard-coded to value 2 in `fvar' version 1.0 (and no newer - version exists), but some fonts set it incorrectly. - - Problem reported by Adam Twardoch . - -2015-02-19 Werner Lemberg - - [cff] Emit better error code for invalid private dict size. - - * src/cff/cffparse.c (cff_parse_private_dict): Reject negative - values for size and offset. - -2015-02-19 Werner Lemberg - - [autofit] Fix signedness issues. - - * src/autofit/afangles.c, src/autofit/afcjk.c, - src/autofit/afglobal.c, src/autofit/afhints.c, - src/autofit/aflatin.c, src/autofit/aflatin2.c, src/autofit/afwarp.c, - src/autofit/hbshim.c: Apply. - -2015-02-19 Werner Lemberg - - [autofit] Use macros for (unsigned) flags, not enumerations. - - This harmonizes with other code in FreeType (and reduces the number - of necessary casts to avoid compiler warnings). - - * src/autofit/afblue.hin: Make flag macros unsigned. - * src/autofit/afblue.h: Regenerated. - - * src/autofit/afcjk.h: Replace flag enumeration with macros. - * src/autofit/afcjk.c: Updated. - - * src/autofit/afhints.h (AF_Flags, AF_Edge_Flags): Replace with - macros. - * src/autofit/afhints.c: Updated. - - * src/autofit/aflatin.h: Replace flag enumerations with macros. - * src/autofit/aflatin.c, src/autofit/aflatin2.c: Updated. - - * src/autofit/aftypes.h (AF_ScalerFlags): Replace with macros. - -2015-02-18 Werner Lemberg - - [type1] Fix signedness issues. - - * include/internal/psaux.h, include/internal/t1types.h, - src/psaux/psobjs.c, src/psaux/psobjs.h, src/psaux/t1decode.c, - src/type1/t1gload.c, src/type1/t1load.c, src/type1/t1parse.c: Apply. - -2015-02-18 Werner Lemberg - - [psaux, type1] Fix minor AFM issues. - - * include/internal/t1types.h (AFM_KernPairRec): Make indices - unsigned. - Update users. - (AFM_FontInfoRec): Make element counters unsigned. - Update users. - * src/psaux/afmparse.h (AFM_ValueRec): Add union member for unsigned - int. - - * src/psaux/afmparse.c (afm_parse_track_kern, afm_parse_kern_pairs): - Reject negative values for number of kerning elements. - - * src/type1/t1afm.c, src/tools/test_afm.c: Updated. - -2015-02-18 Werner Lemberg - - Don't use `FT_PtrDist' for lengths. - - Use FT_UInt instead. - - * include/internal/psaux.h (PS_Table_FuncsRec, PS_TableRec, - T1_DecoderRec): Do it. - - * include/internal/t1types.h (T1_FontRec): Ditto. - - * src/cid/cidload.c (cid_parse_dict): Updated. - * src/pfr/pfrload.c (pfr_extra_item_load_font_id): Ditto. - * src/psaux/psobjs.c (ps_table_add), src/psaux/psobjs.h: Ditto. - * src/type1/t1load.c (parse_blend_axis_types, parse_encoding, - parse_charstrings, parse_dict): Ditto. - * src/type42/t42parse.c (t42_parse_encoding, t42_parse_charstrings, - t42_parse_dict): Ditto. - -2015-02-18 Werner Lemberg - - * src/type1/t1driver.c (t1_ps_get_font_value): Clean up. - This handles negative values better, avoiding many casts. - -2015-02-17 Werner Lemberg - - [base] Fix Savannah bug #44284. - - * src/base/ftcalc.c (FT_MulFix): Typos. - -2015-02-17 Werner Lemberg - - [truetype] Finish compiler warning fixes for signedness issues. - - * src/truetype/ttgxvar.c, src/truetype/ttsubpix.c, - src/truetype/ttsubpix.h: Apply. - -2015-02-17 Werner Lemberg - - * src/truetype/ttsubpix.c: Adding missing `static' keywords. - -2015-02-17 Werner Lemberg - - [truetype] More signedness fixes. - - * include/internal/tttypes.h, src/truetype/ttinterp.h, - src/truetype/ttobjs.h, src/truetype/ttinterp.c, - src/truetype/ttobjs.c: Apply. - -2015-02-17 Werner Lemberg - - [truetype] Various signedness fixes. - - * include/internal/ftgloadr.h, src/truetype/ttpload.c: Apply. - - * src/truetype/ttgload.c: Apply. - (TT_Get_VMetrics): Protect against invalid ascenders and descenders - while constructing advance height. - -2015-02-16 Werner Lemberg - - [base] Finish compiler warning fixes for signedness issues. - - * src/base/ftglyph.c, src/base/ftlcdfil.c, src/base/ftstroke.c: - Apply. - -2015-02-16 Werner Lemberg - - * include/tttables.h (TT_OS2): `fsType' must be FT_UShort. - -2015-02-16 Werner Lemberg - - More minor signedness warning fixes. - - * src/base/ftbbox.c, src/base/ftbitmap.c, src/base/fttrigon.c, - src/base/ftutil.c: Apply. - -2015-02-16 Werner Lemberg - - Next round of minor compiler warning fixes. - - * include/internal/ftrfork.h (FT_RFork_Ref): Change `offset' member - type to `FT_Long'. - (CONST_FT_RFORK_RULE_ARRAY_BEGIN): Add `static' keyword. - - * include/internal/ftstream.h (FT_Stream_Pos): Return `FT_ULong'. - - * src/base/ftoutln.c, src/base/ftrfork.c, src/base/ftstream.c: - Signedness fixes. - -2015-02-16 Werner Lemberg - - Various minor signedness fixes. - - * include/ftadvanc.h, include/internal/ftobjs.h, - src/base/ftgloadr.c, src/base/ftobjs.c: Apply. - -2015-02-16 Werner Lemberg - - New `TYPEOF' macro. - - This helps suppress signedness warnings, avoiding issues with - implicit conversion changes. - - * include/config/ftconfig.h, builds/unix/ftconfig.in, - builds/vms/ftconfig.h (TYPEOF): Define. - - * include/internal/ftobjs.h (FT_PAD_FLOOR, FT_PIX_FLOOR), - src/autofit/afwarp.h (AF_WARPER_FLOOR): Use it. - -2015-02-16 Werner Lemberg - - * src/base/ftsystem.c: Use casts in standard C function wrappers. - (ft_alloc, ft_realloc, ft_ansi_stream_io, FT_Stream_Open): Do it. - -2015-02-16 Werner Lemberg - - Fix Savannah bug #44261. - - * builds/unix/detect.mk (setup) [unix]: Set `CONFIG_SHELL' in the - environment also while calling the configure script. - -2015-02-16 Werner Lemberg - - * include/internal/ftmemory.h: Add some `FT_Offset' casts. - (FT_MEM_SET, FT_MEM_COPY, FT_MEM_MOVE, FT_ARRAY_ZERO, FT_ARRAY_COPY, - FT_MEM_MOVE): Do it. - -2015-02-15 Werner Lemberg - - [base] Clean up signedness issues in `ftdbgmem.c'. - - Also fix other minor issues. - - * src/base/ftdbgmem.c (FT_MemTableRec): Replace all FT_ULong types - with FT_Long for consistency. - (ft_mem_primes): Change type to `FT_Int'. - (ft_mem_closest_prime, ft_mem_table_set): Updated. - - (ft_mem_debug_panic, ft_mem_debug_alloc, ft_mem_debug_free, - ft_mem_debug_realloc): Use `static' keyword and fix signedness - warnings where necessary. - - (ft_mem_table_resize, ft_mem_table_new, ft_mem_table_destroy, - ft_mem_table_get_nodep, ft_mem_debug_init, FT_DumpMemory): Fix types - and add or remove casts to avoid signedness warnings. - -2015-02-15 Werner Lemberg - - [base] Clean up signedness in arithmetic functions. - - This makes the code more readable and reduces compiler warnings. - - * src/base/ftcalc.c (FT_MulDiv, FT_MulDiv_No_Round, FT_MulFix, - FT_DivFix): Convert input parameters to unsigned, do the - computation, then convert the result back to signed. - (ft_corner_orientation): Fix casts. - -2015-02-07 Werner Lemberg - - [sfnt] Fix Savannah bug #44184. - - * src/sfnt/ttload.c (check_table_dir, tt_face_load_font_dir): No - longer reject `htmx' and `vmtx' tables with invalid length but - sanitize them. - -2015-02-06 Jon Anderson - - [truetype] Fix regression in the incremental glyph loader. - - * src/truetype/ttgload.c (load_truetype_glyph): For incremental - fonts, the glyph index may be greater than the number of glyphs - indicated, so guard the check with a preprocessor conditional. - -2015-02-06 Werner Lemberg - - [autofit] Fix potential memory leak. - - While this doesn't show up with FreeType, exactly the same code - leaks with ttfautohint's modified auto-hinter code (which gets used - in a slightly different way). - - It certainly doesn't harm since it is similar to already existing - checks in the code for embedded arrays. - - * src/autofit/afhints.c (af_glyph_hints_reload): Set `max_contours' - and `max_points' for all cases. - -2015-01-31 Werner Lemberg - - [autofit] Add support for Thai script. - - Thanks to Ben Mitchell for guidance with blue - zone characters! - - * src/autofit/afblue.dat: Add blue zone data for Thai. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Thai standard characters. - - * src/autofit/afranges.c: Add Thai data. - - * src/autofit/afstyles.h: Add Thai data. - -2015-01-23 Behdad Esfahbod - - [raster] Handle `FT_RASTER_FLAG_AA' correctly. - - This fixes a breakage caused by the commit `[raster] Remove - 5-level gray AA mode from monochrome rasterizer.'. - - Problem reported by Markus Trippelsdorf . - - * src/raster/ftraster.c (ft_black_render): Handle - `FT_RASTER_FLAG_AA'. - - * src/raster/ftrend1.c (ft_raster1_render): Remove gray AA mode - remnants. - -2015-01-18 Werner Lemberg - - * src/base/ftobjs.c (FT_New_Library): Fix compiler warning. - -2015-01-18 Chris Liddell - - [raster] Fix Savannah bug #44022. - - Add fallback for glyphs with degenerate bounding boxes. - - If a glyph has only one very narrow feature, the bbox can end up - with either the width or height of the bbox being 0, in which case - no raster memory is allocated and no attempt is made to render the - glyph. This is less than ideal when the drop-out compensation in - the rendering code would actually result in the glyph being - rendered. - - This problem can be observed with the `I' glyph (gid 47) in the - Autodesk RomanS TrueType font. - - * src/raster/ftrend1.c (ft_raster1_render): Add a fallback if either - dimension is zero to explicitly round up/down (instead of simply - round). - -2015-01-17 Werner Lemberg - - Add some tools to handle yearly copyright notice updates. - - We are now following the GNU guidelines: A new release automatically - means that the copyright year of all affected files gets updated; it - is no longer used to track years of modification changes. - - * src/tools/update-copyright-year: New Perl script. - * src/tools/update-copyright: New shell script that calls - `update-copyright-year' on all files. - * src/tools/no-copyright: Exceptions that should not be handled by - `update-copyright' - -2015-01-14 Werner Lemberg - - * docs/CHANGES: Updated, using a description from Behdad. - -2015-01-14 Behdad Esfahbod - - * src/autofit/afmodule.c (af_autofitter_done): Fix compiler warning. - -2015-01-14 Behdad Esfahbod - - [autofit] Add embedded array of segments and edges. - - Avoids multiple mallocs per typical glyphs. - - With this and recent changes to avoid mallocs, the thread-safe - stack-based loader is now as fast as the previous model that had one - cached singleton. - - * src/autofit/afhints.h (AF_SEGMENTS_EMBEDDED, AF_EDGES_EMBEDDED): - New macros. - (AF_AxisHintsRec): Add two arrays for segments and edges. - - * src/autofit/afhints.c (af_axis_hints_new_segment): Only allocate - data if number of segments exceeds given threshold value. - (af_axis_hints_new_edge): Only allocate data if number of edges - exceeds given threshold value. - (af_glyph_hints_done): Updated. - -2015-01-14 Behdad Esfahbod - - [autofit] Add embedded arrays for points and contours. - - This avoids at least two malloc calls for typical glyphs. - - * src/autofit/afhints.h (AF_POINTS_EMBEDDED, AF_CONTOURS_EMBEDDED): - New macros. - (AF_GlyphHintsRec): Add two arrays for contours and points. - - * src/autofit/afhints.c (af_glyph_hints_init, af_glyph_hints_done): - Updated. - (af_glyph_hints_reload): Only allocate data if number of contours or - points exceeds given threshold values. - -2015-01-14 Behdad Esfahbod - - [autofit] Allocate hints object on the stack. - - This avoids one malloc per load. - - * src/autofit/afloader.h (AF_LoaderRec): Change type of `hints' to - `AF_GlyphHints'. - Update prototype. - - * src/autofit/afloader.c (af_loader_init): Use `AF_GlyphHints' - parameter instead of `FT_Memory'. - (af_loader_done): Directly reset `load_hints'. - (af_loader_load_g): Updated. - - * src/autofit/afmodule.c (af_autofitter_load_glyph): Use local - `hints' object. - -2015-01-14 Behdad Esfahbod - - [autofit] Reuse slot glyph loader. - - No need to create a new glyph loader; we can reuse the one from - `slot->internal->loader'. It's hard to tell why it was written that - way originally, but new code looks sound and correct to me, and - avoids lots of allocations. - - * src/autofit/afloader.c (af_loader_init): Change return type to - `void'. - Don't call `FT_GlyphLoader_New'. - (af_loader_reset): Don't call `FT_GlyphLoader_Rewind'. - (af_loader_load_g): Update code to use `internal->loader', which - doesn't need copying of data. - - * src/autofit/afloader.h (AF_LoaderRec): Remove `gloader' member. - Update prototype. - - * src/autofit/afmodule.c (af_autofitter_load_glyph): Updated. - -2015-01-14 Behdad Esfahbod - - [autofit] Remove (unused) support for composite glyphs. - - We never have to deal with composite glyphs in the autohinter, as - those will be loaded into FORMAT_OUTLINE by the recursed - `FT_Load_Glyph' function. - - In the rare cases that FT_LOAD_NO_RECURSE is set, it will imply - FT_LOAD_NO_SCALE as per `FT_Load_Glyph', which then implies - FT_LOAD_NO_HINTING: - - /* resolve load flags dependencies */ - - if ( load_flags & FT_LOAD_NO_RECURSE ) - load_flags |= FT_LOAD_NO_SCALE | - FT_LOAD_IGNORE_TRANSFORM; - - if ( load_flags & FT_LOAD_NO_SCALE ) - { - load_flags |= FT_LOAD_NO_HINTING | - FT_LOAD_NO_BITMAP; - - load_flags &= ~FT_LOAD_RENDER; - } - - and as such the auto-hinter is never called. Thus, the recursion in - `af_loader_load_g' never actually happens. So remove the depth - counter as well. - - * src/autofit/afloader.c (af_loader_load_g): Remove `depth' - parameter. - : Remove associated code. - (af_loader_load_glyph): Updated. - -2015-01-14 Behdad Esfahbod - - [raster] Fix uninitialized memory access. - - Apparently `ras.cProfile' might be uninitialized. This will be the - case if `ras.top == ras.cProfile->offset', as can be seen in - `End_Profile'. The overshoot code introduced in a change `Fix B/W - rasterization of subglyphs with different drop-out modes.' (from - 2009-06-18) violated this, accessing `ras.cProfile->flags' - unconditionally just before calling `End_Profile' (which then - detected that `cProfile' is uninitialized and didn't touch it). - - This was harmless, and was not detected by valgrind before because - the objects were allocated on the `raster_pool', which was always - initialized. With recent change to allocate raster buffers on the - stack, valgrind now reported this invalid access. - - * src/raster/ftraster.c (Convert_Glyph): Don't access an - uninitialized `cProfile'. - -2015-01-14 Behdad Esfahbod - - [smooth] Fix uninitialized memory access. - - Looks like `ras.span_y' could always be used without initialization. - This was never detected by valgrind before because the library-wide - `raster_pool' was used for the worker object and `raster_pool' was - originally zero'ed. But subsequent reuses of it were using `span_y' - uninitialized. With the recent change to not use `render_pool' and - allocate worker and buffer on the stack, valgrind now detects this - uninitialized access. - - * src/smooth/ftgrays.c (gray_raster_render): Initialize - `ras.span_y'. - -2015-01-14 Behdad Esfahbod - - [base] Don't initialize unused `driver->glyph_loader'. - - * src/base/ftobjs.c (Destroy_Driver): Don't call - `FT_GlyphLoader_Done'. - (FT_Add_Module): Don't call `FT_GlyphLoader_New'. - -2015-01-14 Behdad Esfahbod - - [base] Don't allocate `library->raster_pool' anymore. - - It's unused after the following commits: - - [raster] Allocate render pool for mono rasterizer on the stack. - [raster] Remove 5-level gray AA mode from monochrome rasterizer. - - The value of FT_RENDER_POOL_SIZE still serves the purpose it used to - serve, which is, to adjust the pool size. But the pool is now - allocated on the stack on demand. - - * src/base/ftobjs.c (FT_New_Library, FT_Done_Library): Implement. - -2015-01-14 Behdad Esfahbod - - [base] Do not reorder library->renderers upon use. - - Instead of keeping `library->renderers' in a MRU order, just leave - it as-is. The MRU machinery wasn't thread-safe. - - With this patch, rasterizing glyphs from different faces from - different threads doesn't fail choosing rasterizer - (FT_Err_Cannot_Render_Glyph). - - Easiest to see that crash was to add a `printf' (or otherwise let - thread yield in FT_Throw with debugging enabled). - - * src/base/ftobjs.c (FT_Render_Glyph_Internal), src/base/ftoutln.c - (FT_Outline_Render): Don't call `FT_Set_Renderer'. - -2015-01-14 Behdad Esfahbod - - [raster] Allocate render pool for mono rasterizer on the stack. - - Instead of using the `render_pool' member of `FT_Library' that is - provided down to the rasterizer, completely ignore that and allocate - needed objects on the stack instead. - - With this patch, rasterizing glyphs from different faces from - different threads doesn't crash in the monochrome rasterizer. - - * src/raster/ftraster.c (black_TRaster): Remove `buffer', - `buffer_size', and `worker' members. - - (ft_black_render): Create `buffer' locally. - (ft_black_reset): Updated. - -2015-01-14 Behdad Esfahbod - - [raster] Remove 5-level gray AA mode from monochrome rasterizer. - - It was off by default and couldn't be turned on at runtime. And the - smooth rasterizer superseded it over ten years ago. No point in - keeping. Comments suggested that it was there for compatibility - with FreeType 1. - - 550 lines down. - - * src/raster/ftraster.c (FT_RASTER_OPTION_ANTI_ALIASING, - RASTER_GRAY_LINES): Remove macros and all associated code. - - (black_TWorker): Remove `gray_min_x' and `gray_max_x'. - (black_TRaster): Remove `grays' and `gray_width'. - - (Vertical_Sweep_Init, Vertical_Sweep_Span, Vertical_Sweep_Drop, - ft_black_render): Updated. - - * src/raster/ftrend1.c (ft_raster1_render): Simplify code. - (ft_raster5_renderer_class): Removed. - -2015-01-14 Behdad Esfahbod - - [smooth] Allocate render pool for smooth rasterizer on the stack. - - Instead of using the `render_pool' member of `FT_Library' that is - provided down to the rasterizer, completely ignore that and allocate - needed objects on the stack instead. - - With this patch, rasterizing glyphs from different faces from - different threads doesn't crash in the smooth rasterizer. - - Bugs: - - https://bugzilla.redhat.com/show_bug.cgi?id=678397 - https://bugzilla.redhat.com/show_bug.cgi?id=1004315 - https://bugzilla.redhat.com/show_bug.cgi?id=1165471 - https://bugs.freedesktop.org/show_bug.cgi?id=69034 - - * src/smooth/ftgrays.c (gray_TRaster): Remove `buffer', - `buffer_size', `band_size', and `worker' members. - - (gray_raster_render): Create `buffer', `buffer_size', and - `band_size' locally. - (gray_raster_reset): Updated. - -2015-01-14 Behdad Esfahbod - - [truetype] Allocate TT_ExecContext in TT_Size instead of TT_Driver. - - Previously the code had stipulation for using a per-TT_Size exec - context if `size->debug' was true. But there was no way that - `size->debug' could *ever* be true. As such, the code was always - using the singleton `TT_ExecContext' that was stored in `TT_Driver'. - This was, clearly, not threadsafe. - - With this patch, loading glyphs from different faces from different - threads doesn't crash in the bytecode loader code. - - * src/truetype/ttobjs.h (TT_SizeRec): Remove `debug' member. - (TT_DriverRec): Remove `context' member. - - * src/truetype/ttobjs.c (tt_size_run_fpgm, tt_size_run_prep): Remove - `TT_ExecContext' code related to a global `TT_Driver' object. - - (tt_driver_done): Don't remove `TT_ExecContext' object here but ... - (tt_size_done_bytecode): ... here. - - (tt_driver_init): Don't create `TT_ExecContext' object here but ... - (tt_size_init_bytecode): ... here, only on demand. - - * src/truetype/ttinterp.c (TT_Run_Context): Remove defunct debug - code. - (TT_New_Context): Remove `TT_ExecContext' code related to a global - `TT_Driver' object. - - * src/truetype/ttinterp.h: Updated. - - * src/truetype/ttgload.c (TT_Hint_Glyph, tt_loader_init): Updated. - -2015-01-14 Behdad Esfahbod - - [autofit] Allocate AF_Loader on the stack instead of AF_Module. - - Stop sharing a global `AF_Loader'. Allocate one on the stack during - glyph load. - - Right now this results in about 25% slowdown, to be fixed in a - following commit. - - With this patch loading glyphs from different faces from different - threads doesn't immediately crash in the autohinting loader code. - - Bugs: - - https://bugzilla.redhat.com/show_bug.cgi?id=1164941 - - * src/autofit/afloader.c (af_loader_init): Pass - `AF_Loader' and `FT_Memory' instead of `AF_Module' as arguments. - (af_loader_reset, af_loader_load_glyph): Also pass `loader' as - argument. - (af_loader_done): Use `AF_Loader' instead of `AF_Module' as - argument. - - * src/autofit/afmodule.c (af_autofitter_init): Don't call - `af_loader_init'. - (af_autofitter_done): Don't call `af_loader_done'. - (af_autofitter_load_glyph): Use a local `AF_Loader' object. - - * src/autofit/afloader.h: Include `afmodule.h'. - Update prototypes. - Move typedef for `AF_Module' to... - - * src/autofit/afmodule.h: ... this place. - No longer include `afloader.h'. - -2015-01-14 Behdad Esfahbod - - * src/type42/t42objs.h (T42_DriverRec): Remove unused member. - -2015-01-12 Werner Lemberg - - Fix Savannah bug #43976. - - Assure that FreeType's internal include directories are found before - `CPPFLAGS' (which might be set by the user in the environment), and - `CPPFLAGS' before `CFLAGS'. - - * builds/freetype.mk (FT_CFLAGS): Don't add `INCLUDE_FLAGS'. - (FT_COMPILE): Make this a special variable for compiling only the - files handled in `freetype.mk'. - (.c.$O): Removed, unused. - - * src/*/rules.mk (*_COMPILE): Fix order of include directories. - -2015-01-11 Werner Lemberg - - [truetype] Prettifying. - - * src/truetype/ttinterp.c (project, dualproj, fast_project, - fast_dualproj): Rename to... - (PROJECT, DUALPROJ, FAST_PROJECT, FAST_DUALPROJ): ... this. - -2015-01-11 Werner Lemberg - - * src/truetype/ttinterp.c (Ins_JROT, Ins_JROF): Simplify. - - Based on a patch from Behdad. - -2015-01-11 Werner Lemberg - - * src/truetype/ttinterp.c (Ins_SxVTL): Simplify function call. - -2015-01-11 Werner Lemberg - - * src/truetype/ttinterp.c (Normalize): Remove unused argument. - -2015-01-11 Werner Lemberg - - [truetype] More macro expansions. - - * src/truetype/ttinterp.c (FT_UNUSED_EXEC): Remove macro by - expansion. - -2015-01-11 Werner Lemberg - - [truetype] More macro expansions. - - * src/truetype/ttinterp.c (INS_ARG): Remove macro by expansion, - adjusting function calls where necessary. - (FT_UNUSED_ARG): Removed, no longer needed. - -2015-01-10 Werner Lemberg - - [truetype] More macro expansions. - - Based on a patch from Behdad. - - * src/truetype/ttinterp.c (DO_*): Expand macros into corresponding - `Ins_*' functions. - (TT_RunIns): Replace `DO_*' macros with `Ins_*' function calls. - (ARRAY_BOUND_ERROR): Remove second definition, which is no longer - needed. - (Ins_SVTCA, Ins_SPVTCA, Ins_SFVTCA): Replaced with... - (Ins_SxyTCA): New function. - -2015-01-10 Werner Lemberg - - [truetype] Remove TT_CONFIG_OPTION_INTERPRETER_SWITCH. - - Behdad suggested this code simplification, and nobody objected... - - * include/config/ftoption.h, devel/ftoption.h - (TT_CONFIG_OPTION_INTERPRETER_SWITCH): Remove. - - * src/truetype/ttinterp.c [TT_CONFIG_OPTION_INTERPRETER_SWITCH]: - Remove related code. - (ARRAY_BOUND_ERROR): Use do-while loop. - -2015-01-10 Werner Lemberg - - [truetype] More macro expansions. - - * src/truetype/ttinterp.c, src/truetype/ttinterp.h (EXEC_ARG_, - EXEC_ARG): Remove by replacing with expansion. - -2015-01-10 Werner Lemberg - - [truetype] More macro expansions. - - Based on a patch from Behdad. - - * src/truetype/ttinterp.c (SKIP_Code, GET_ShortIns, NORMalize, - SET_SuperRound, ROUND_None, INS_Goto_CodeRange, CUR_Func_move, - CUR_Func_move_orig, CUR_Func_round, CUR_Func_cur_ppem, - CUR_Func_read_cvt, CUR_Func_write_cvt, CUR_Func_move_cvt, - CURRENT_Ratio, INS_SxVTL, COMPUTE_Funcs, COMPUTE_Round, - COMPUTE_Point_Displacement, MOVE_Zp2_Point): Remove by replacing - with expansion. - - (Cur_Func_project, CUR_Func_dualproj, CUR_fast_project, - CUR_fast_dualproj): Replace with macros `project', `dualproj', - `fast_project', `fast_dualproj'. - -2015-01-10 Werner Lemberg - - [truetype] More macro expansions. - - * src/truetype/ttinterp.c (EXEC_OP_, EXEC_OP): Remove by replacing - with expansion. - -2015-01-10 Werner Lemberg - - [truetype] Remove code for static TrueType interpreter. - - This is a follow-up patch. - - * src/truetype/ttinterp.c, src/truetype/ttinterp.h - [TT_CONFIG_OPTION_STATIC_INTERPRETER, - TT_CONFIG_OPTION_STATIC_RASTER]: Remove macros and related code. - -2015-01-10 Werner Lemberg - - * src/truetype/ttinterp.c (CUR): Remove by replacing with expansion. - - This starts a series of patches that simplifies the code of the - bytecode interpreter. - - ----------------------------------------------------------------------------- - -Copyright (C) 2015-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, modified, -and distributed under the terms of the FreeType project license, -LICENSE.TXT. By continuing to use, modify, or distribute this file you -indicate that you have read the license and understand and accept it -fully. - - -Local Variables: -version-control: never -coding: utf-8 -End: diff --git a/lib/libesp32_lvgl/freetype/ChangeLog.27 b/lib/libesp32_lvgl/freetype/ChangeLog.27 deleted file mode 100644 index c59ed7b80..000000000 --- a/lib/libesp32_lvgl/freetype/ChangeLog.27 +++ /dev/null @@ -1,2106 +0,0 @@ -2016-12-30 Werner Lemberg - - * Version 2.7.1 released. - ========================= - - - Tag sources with `VER-2-7-1'. - - * docs/VERSION.TXT: Add entry for version 2.7.1. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.7/2.7.1/, s/27/271/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 1. - - * builds/unix/configure.raw (version_info): Set to 19:0:13. - * CMakeLists.txt (VERSION_PATCH): Set to 1. - -2016-12-30 Werner Lemberg - - [ftfuzzer] Replace `rand' with an xorshift algorithm. - - * src/tools/ftfuzzer/ftfuzzer.cc: Don't include `stdlib.h'. - (Random): Implement and use a 32bit `xorshift' algorithm. - -2016-12-30 Werner Lemberg - - [ftfuzzer] Restrict number of tested bitmap strikes. - - Malformed fonts often have large values for the number of bitmap - strikes, and FreeType doesn't check the validity of all bitmap - strikes in advance. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=353 - - * src/tools/ftfuzzer/ftfuzzer.cc: Include `stdlib.h' for `rand'. - (Random): Small class to provide n randomly selected numbers - (without repetition) out of the value set [1,N]. - (LLVMFuzzerTestOneInput): Use it to test only up to 10 bitmap - strikes. - -2016-12-29 Werner Lemberg - - [truetype] Variation font API stability issues. - - Make some functions work before a call to `TT_Set_MM_Blend'. - - * src/truetype/ttgxvar.c (tt_hadvance_adjust): Exit immediately if - we don't blend. - (TT_Get_MM_Blend, TT_Get_Var_Design): Return default values if we - don't blend. - -2016-12-29 Werner Lemberg - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Check axis data. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=348 - -2016-12-29 Werner Lemberg - - [truetype] Tracing fixes. - - * src/truetype/ttgxvar.c (tt_hadvance_adjust): Emit correct - information. - (TT_Set_Var_Design): Fix typo. - (TT_Get_Var_Design): Fix typos. - -2016-12-29 Werner Lemberg - - */*: Use `0.5f' for tracing 16.16 numbers. - -2016-12-29 Werner Lemberg - - [pcf] Protect against gzip bombs. - - Fix suggested by Kostya; reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=345 - - * src/pcf/pcfread.c (pcf_read_TOC): Limit number of TOC entries to - 1024. - -2016-12-28 Werner Lemberg - - [psnames] Only declare, not define, data in `pstables.h' (#49949). - - Pdfium includes `pstables.h' a second time; moving the definition - from `pstables.h' to `psmodule.c' saves more than 60kByte data - segment space for this case. - - * src/tools/glnames.py (StringTable::dump, - StringTable::dump_sublist, dump_encoding, dump_array): Emit - additional code to only define tables if `DEFINE_PS_TABLES' is set. - - * src/psnames/pstables.h: Regenerated. - * src/psnames/psmodule.c (DEFINE_PS_TABLES): Define. - -2016-12-28 Werner Lemberg - - [cff] Catch `blend' op in non-variant fonts. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=334 - - * src/cff/cf2intrp.c (cf2_interpT2CharString) : Don't - allow `blend' op for non-variant fonts. - -2016-12-28 Werner Lemberg - - [cff] Better check of number of blends. - - * src/cff/cf2intrp.c (cf2_interpT2CharString) , - src/cff/cffparse.c (cff_parse_blend): Compare number of blends with - stack size. - -2016-12-27 Werner Lemberg - - Documentation updates. - - * docs/CHANGES: Add missing information. - - * docs/formats.txt: Rewritten and updated. - -2016-12-27 Werner Lemberg - - [truetype, type1] Implement `FT_Get_Var_Design_Coordinates'. - - * src/truetype/ttgxvar.c (TT_Get_Var_Design): Implement. - (TT_Set_Var_Design): Fix tracing. - - * src/type1/t1load.c (T1_Get_Var_Design): Implement. - -2016-12-24 Werner Lemberg - - * src/truetype/ttpload.c (tt_face_load_hdmx): Ignore `version'. - - Problem reported by 張俊芝 <418092625@qq.com>. - -2016-12-24 Werner Lemberg - - * src/sfnt/ttsbit.c (tt_face_load_sbit): Allow more version values. - - Some fonts seem to have the `version' field in the wrong byte order. - - Problem reported by 張俊芝 <418092625@qq.com>. - -2016-12-24 Werner Lemberg - - * src/truetype/ttpload.c (tt_face_load_loca): Sanitize table length. - - This trivial fix allows us to accept more fonts. - - Problem reported by 張俊芝 <418092625@qq.com>. - -2016-12-24 Werner Lemberg - - * src/sfnt/sfobjs.c (sfnt_init_face): Fix tracing. - -2016-12-22 Werner Lemberg - - * CMakeLists.txt: Make it work with cmake 2.8.11.2 (#49909). - -2016-12-22 Werner Lemberg - - Ensure used preprocessor symbols are defined (#49790). - - * builds/unix/ftconfig.in, builds/vms/ftconfig.h, - include/freetype/config/ftconfig.h: Check `__GNUC__', `__IBMC__', - and `__SUNPRO_C' correctly. - -2016-12-22 Werner Lemberg - - * src/base/ftrfork.c (FT_Raccess_Get_DataOffsets): Check `count'. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=308 - -2016-12-22 Werner Lemberg - - [cff] Protect against invalid `vsindex' and `blend' values. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=305 - - * src/cff/cf2intrp.c (cf2_interpT2CharString) : Implement it. - -2016-12-22 Werner Lemberg - - [ftfuzzer] Always use Adobe CFF engine. - - * src/tools/ftfuzzer/ftfuzzer.cc (FT_Global::FT_Global): Implement - it. - -2016-12-21 Werner Lemberg - - * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Thinko. - - I should really stop coding late in the evening... - - Thanks again to Ben for checking. - -2016-12-21 Werner Lemberg - - [autofit] Support variation fonts. - - (This ChangeLog entry was added later on.) - - * src/autofit/afglobal.c (af_face_globals_free): Remove useless - code. - - * src/base/ftmm.c (FT_Set_MM_Design_Coordinates, - * FT_Set_Var_Design_Coordinates, FT_Set_MM_Blend_Coordinates, - FT_Set_Var_Blend_Coordinates): Finalize - auto-hinter data to enforce recomputation. Note that this is a - brute-force method which should be improved. - -2016-12-21 Werner Lemberg - - * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Thinko. - - Don't apply deltas twice for non-phantom points. - - Spotted by Ben Wagner. - -2016-12-21 Werner Lemberg - - [cff, truetype] Another try for #49829. - - * src/cff/cffdrivr.c: Don't include - `FT_SERVICE_METRICS_VARIATIONS_H'. - (cff_get_advances): Use `ttface->variation_support'. - - * src/truetype/ttdriver.c (tt_get_advances): Use - `ttface->variation_support'. - - * src/truetype/ttgload.c (TT_Process_Simple_Glyph, - load_truetype_glyph): Use `ttface->variation_support'. - -2016-12-21 Werner Lemberg - - [truetype, sfnt] Introduce font variation flags to `TT_Face'. - - * include/freetype/internal/tttypes.h (TT_FACE_FLAG_VAR_XXX): - New macros describing available functionality of various OpenType - tables related to font variation. - (TT_Face): New fields `variation_support' and `mvar_support', - replacing and extending `use_fvar'. - - * src/sfnt/sfobjs.c (sfnt_init_face, sfnt_load_face): Use - `variation_support'. - - * src/truetype/ttgxvar.c (ft_var_load_hvar): Set `variation_support' - field. - (TT_Vary_Apply_Glyph_Deltas): Updated. - -2016-12-21 Werner Lemberg - - [base] Improve sanity check for Mac resources (#49888). - - * src/base/ftobjs.c (Mac_Read_sfnt_Resource): Abort if `rlen' is not - positive. - -2016-12-20 Werner Lemberg - - [base] More sanity checks for Mac resources. - - We use - - https://github.com/kreativekorp/ksfl/wiki/Macintosh-Resource-File-Format - - and - - https://developer.apple.com/legacy/library/documentation/mac/pdf/MoreMacintoshToolbox.pdf#page=151 - - as references. - - * include/freetype/internal/ftrfork.h (FT_RFork_Ref): Use FT_Short - for `res_id'. - - * src/base/ftrfork.c (FT_Raccess_Get_HeaderInfo): Extract map length - and use it to improve sanity checks. - Follow the specification more closely;in particular, all data types - are signed, not unsigned. - (FT_Raccess_Get_DataOffsets): Follow the specification more closely; - in particular, all data types are signed, not unsigned. - Add some sanity checks. - -2016-12-20 Werner Lemberg - - [truetype] Improve logic for getting fast advance widths. - - * src/cff/cffdrivr.c (cff_get_advances), src/truetype/ttdriver.c - (tt_get_advances): Use `is_default_instance' for test; this gets - recomputed after changing blend coordinates. - -2016-12-20 Ben Wagner - Werner Lemberg - - [truetype] Fix linear metrics of GX variation fonts (#49829). - - When asking for an unhinted non-default variations, - `linearVertAdvance' is currently the value from the `hmtx' table - instead of the actual value after applying the variation. `HVAR' - support fixes this, but fonts will exist without that table and will - need sane fallback. - - Problem also reported as - - https://bugs.chromium.org/p/skia/issues/detail?id=5917 - - * src/truetype/ttgload.c (TT_Process_Simple_Glyph, - load_truetype_glyph): Implement linear advance adjustments if `HVAR' - or `VVAR' tables are missing. - -2016-12-20 Werner Lemberg - - [cff, truetype] Fast advance width retrieval for fonts with HVAR. - - Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT. - - * src/base/ftadvanc.c (LOAD_ADVANCE_FAST_CHECK): Don't handle MM. - - * src/cff/cffdrivr.c: Include FT_SERVICE_METRICS_VARIATIONS_H. - (cff_get_advances): Test for HVAR and VVAR. - - * src/truetype/ttdriver.c (tt_get_advances): Test for HVAR and VVAR. - -2016-12-18 Werner Lemberg - - [base] Fix invalid mac font recursion. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=304 - - * src/base/ftobjs.c (FT_Open_Face): Code moved to... - (ft_open_face_internal): ... this function. - Add a parameter to control whether we try special Mac font handling - in case of failure. - (FT_Open_Face, FT_New_Face, FT_New_Memory_Face, - open_face_from_buffer): Use `ft_open_face_internal'. - -2016-12-18 Werner Lemberg - - * src/cff/cffobjs.c (cff_face_init): Make named instances work. - -2016-12-18 Werner Lemberg - - [truetype, cff] Extend `get_var_blend' function of MM service. - - In particular, we need access to named instance data. - - * include/freetype/internal/services/svmm.h (FT_Get_Var_Blend_Func): - Add argument for `FT_MM_Var'. - - * src/cff/cffload.c (cff_get_var_blend): Updated. - * src/cff/cffload.h: Updated. - - * src/cff/cf2ft.c (cf2_getNormalizedVector): Updated. - - * src/truetype/ttgxvar.c (tt_get_var_blend): Updated. - Accept value `NULL' for arguments. - * src/truetype/ttgxvar.h: Updated. - -2016-12-18 Werner Lemberg - - [sfnt] Handle `fvar' with zero axes as a non-MM font. - - This is better behaviour than exiting with an error. - - * include/freetype/internal/tttypes.h (TT_Face): Add `use_fvar' - field. - - * src/sfnt/sfobjs.c (sfnt_init_face): Compute `use_fvar', also - updating the validation code. - Use `use_fvar' to compute FT_FACE_FLAG_MULTIPLE_MASTERS. - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Remove `fvar' validation - code. - -2016-12-18 Werner Lemberg - - Minor GX code shuffling. - - * include/freetype/internal/tttypes.h (TT_Face): Move - `is_default_instance' into TT_CONFIG_OPTION_GX_VAR_SUPPORT - block. - - * src/sfnt/sfobjs.c (sfnt_init_face): Updated. - * src/truetype/ttgload.c (IS_DEFAULT_INSTANCE): New macro. - (TT_Load_Glyph): Use it. - -2016-12-18 Werner Lemberg - - [cff] Better handling of non-CFF font formats. - - * src/cff/cffload.c (cff_font_load): Pure CFFs don't have a - signature, so return `FT_Err_Unknown_File_Format' more often. - -2016-12-17 Werner Lemberg - - * src/cff/cffload.c (cff_build_blend_vector): Remove redundant code. - -2016-12-17 Werner Lemberg - - * src/truetype/ttobjs.c (tt_face_init): Simplify conditional code. - -2016-12-17 Werner Lemberg - - [sfnt, truetype] Various sanitizing fixes. - - * src/sfnt/sfobjs.c (sfnt_init_face): If the axis count in `fvar' is - zero, set `num_instances' to zero. - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Handle `fvar' table with - zero axes as invalid. - - * src/truetype/ttobjs.c (tt_face_init): Improve logic of loading - `loca', `cvt', `fpgm', and `prep' table. - -2016-12-17 Werner Lemberg - - Improve tracing of `FT_Open_Face'. - - * src/base/ftobjs.c (FT_Open_Face): Return info on number of - available faces and numbered instances, or the indices of the - requested face and numbered instance. - - * src/sfnt/sfobjs. (sfnt_open_font): Trace number of subfonts. - -2016-12-17 Werner Lemberg - - * src/cff/cffload.c (cff_load_private_dict): Always init `blend'. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=295 - -2016-12-16 Werner Lemberg - - [truetype] Fix `cvar' sanity test. - - Reported by Dave Arnold. - - * src/truetype/ttgxvar.c (tt_face_vary_cvt): Use tuple count mask. - -2016-12-16 Werner Lemberg - - [cff, truetype] Remove compiler warnings; fix `make multi'. - - * src/cff/cf2font.h: Include `cffload.h'. - - * src/cff/cffload.c: Include FT_MULTIPLE_MASTERS_H and - FT_SERVICE_MULTIPLE_MASTERS_H. - (cff_vstore_load): Eliminate `vsSize'. - (cff_load_private_dict): Tag as `FT_LOCAL_DEF'. - - * src/cff/cffload.h: Include `cffobjs.h'. - Provide declaration for `cff_load_private_dict'. - - * src/truetype/ttgxvar.c (ft_var_load_hvar): Eliminate - `minorVersion' and `map_offset'. - -2016-12-16 Werner Lemberg - - [cff] Fix heap buffer overflow (#49858). - - * src/cff/cffparse.c (cff_parser_run): Add one more stack size - check. - -2016-12-15 Werner Lemberg - - Fix clang warnings. - - * src/cff/cffload.c (cff_blend_doBlend): Add cast. - (cff_subfont_load): Set `error' correctly. - - * src/sfnt/ttmtx.c (tt_face_get_metrics): Typo. - -2016-12-15 Dave Arnold - Werner Lemberg - - [cff] Implement CFF2 support (2/2). - - The font variation code. All parts dependent on the GX code in the - `truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT. - In other words, you can still compile the `cff' module without - defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2 - support without font variation). - - * src/cff/cf2font.c (cf2_font_setup): Add support for font - variation. - * src/cff/cf2font.h (CF2_Font): Add fields for variation data. - - * src/cff/cf2ft.c (cf2_free_instance): Free blend data. - (cf2_getVStore, cf2_getNormalizedVector): New functions. - * src/cff/cf2ft.h: Updated. - - * src/cff/cf2intrp.c: Include `cffload.h'. - (cf2_cmdRESERVED_15, cf2_cmdRESERVED_16): Replace with... - (cf2_cmdVSINDEX, cf2_cmdBLEND): ... this new enum values. - (cf2_doBlend): New function. - (cf2_interpT2CharString): Handle `vsindex' and `blend' opcodes. - - * src/cff/cffload.c (FT_fdot14ToFixed): New macro. - (cff_vstore_done, cff_vstore_load): New functions. - (cff_blend_clear, cff_blend_doBlend, cff_blend_build_vector, - cff_blend_check_vector): New functions. - (cff_load_private_dict): Add arguments for blend vector. - Handle blend data. - (cff_subfont_load, cff_subfont_done): Updated. - (cff_font_load): Handle CFF2 variation store data. - (cff_font_done): Updated. - * src/cff/cffload.h: Include `cffparse.h'. - Updated. - - * src/cff/cffobjs.c (cff_face_done): Updated. - - * src/cff/cffparse.c: Include `cffload.h'. - (cff_parse_num): Handle internal value 255. - (cff_parse_vsindex, cff_parse_blend): New functions. - (CFF_FIELD_BLEND): New macro. - (cff_parser_run): Updated. - * src/cff/cffparse.h (cff_kind_blend): New enum value. - - * src/cff/cfftoken.h: Handle `vstore', `vsindex', and `blend' - dictionary values. - - * src/cff/cfftypes.h (CFF_VarData, CFF_AxisCoords, CFF_VarRegion, - CFF_VStore, CFF_Blend): New structures. - (CFF_FontRecDict): Add `vstore_offset' field. - (CFF_Private): Add `vsindex' field. - (CFF_SubFont): Add fields for blend data. - (CFF_Font): Add `vstore' field. - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): `CFF2' is equal to `gvar', - since glyph variation data is directly embedded. - (TT_Set_MM_Blend): Don't load `gvar' table for CFF2 fonts. - -2016-12-15 Dave Arnold - Werner Lemberg - - [cff] Implement CFF2 support (1/2). - - This commit does not contain the blend code for font variation - support, which follows in another commit. - - You should ignore whitespace while inspecting this commit. - - * include/freetype/internal/tttypes.h (TT_Face): Add `isCFF2' - member. - - * src/cff/cf2font.h (CF2_Font): Add `isCFF2' member. - - * src/cff/cf2ft.c (cf2_decoder_parse_charstrings): Handle `isCFF2' - flag. - (cf2_getMaxstack): New function. - * src/cff/cf2ft.h: Updated. - - * src/cff/cf2intrp.c (cf2_escRESERVED_38): New enum. - (cf2_interpT2CharString): Handle CFF2 differences. - Add tracing message for errors. - - * src/cff/cffdrivr.c (cff_get_glyph_name, cff_get_name_index): - Update for CFF2. - - * src/cff/cffload.c (FT_FIXED_ONE): New macro. - (cff_index_init, cff_index_load_offsets, cff_index_access_element, - cff_index_get_name, cff_ft_select_get, cff_load_private_dict, - cff_subfont_load, cff_font_load): Handle CFF2. - * src/cff/cffload.h: Updated. - - * src/cff/cffobjs.c (cff_face_init): Handle CFF2. - - * src/cff/cffparse.c (cff_parse_maxstack): New function. - (CFFCODE_TOPDICT, CFFCODE_PRIVATE): Removed - * src/cff/cffparse.h (CFF2_MAX_STACK, CFF2_DEFAULT_STACK): New - macros. - (CFF2_CODE_TOPDICT, CFF2_CODE_FONTDICT, CFF2_CODE_PRIVATE): New - macros. - - * src/cff/cfftoken.h: Add fields for CFF2 dictionaries (but no blend - stuff). - - * src/cff/cfftypes.h (CFF_Index): Add `hdr_size' field. - (CFF_FontRecDict): Add `maxstack' field. - (CFF_Private): Add `subfont' field. - (CFF_Font): Add `top_dict_length' and `cff2' fields. - - * src/sfnt/sfobjs.c (sfnt_load_face): Handle `CFF2' table. - -2016-12-15 Werner Lemberg - Dave Arnold - - [truetype] Provide HVAR advance width variation as a service. - - Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT. - - * src/truetype/ttdriver.c (tt_service_metrics_variations): Updated. - - * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Prevent - double adjustment of advance width. - - * src/sfnt/ttmtx.c: Include FT_SERVICE_METRICS_VARIATIONS_H. - (tt_face_get_metrics): Apply metrics variations. - -2016-12-15 Dave Arnold - Werner Lemberg - - [truetype] Provide function to apply `HVAR' advance width variation. - - Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT. - - * src/truetype/ttgxvar.c (tt_hadvance_adjust): New function. - * src/truetype/ttgxvar.h: Updated. - -2016-12-15 Dave Arnold - Werner Lemberg - - [truetype] Add `HVAR' table parsing. - - Note that this is not complete yet; it only handles advance width - variation. - - Activation of the code follows in another commit. - - Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT. - - * include/freetype/ftmm.h (FT_Var_Named_Style): Add `psid' member. - - * src/truetype/ttgxvar.h (GX_HVarData, GX_AxisCoords, GX_HVarRegion, - GX_HVStore, GX_WidthMap): New auxiliary structures for... - (GX_HVarTable): ... HVAR main structure. - (GX_BlendRec): Add data for HVAR loading. - - * src/truetype/ttgxvar.c (FT_FIXED_ONE, FT_fdot14ToFixed, - FT_intToFixed, FT_fixedToInt): New macros. - (ft_var_load_hvar): New function. - (TT_Get_MM_Var): Updated. - (tt_done_blend): Deallocate HVAR data. - -2016-12-15 Dave Arnold - - [cff] Extend number parsing. - - The forthcoming CFF2 support needs a dynamic parsing limit. - - * src/cff/cffparse.c (cff_parse_num, do_fixed, cff_parse_fixed, - cff_parse_fixed_scaled, cff_parse_fixed_dynamic): Add argument for - parser. - (cff_parse_font_matrix, cff_parse_font_bbox, cff_parse_private_dict, - cff_parse_multiple_master, cff_parse_cid_ros, cff_parser_run): Updated. - - * src/cff/cffparse.h (cff_parse_num): Export locally. - -2016-12-15 Dave Arnold - - [cff] Implement dynamic stack size for Adobe engine. - - This also adds `cf2_stack_setReal' and `cf2_stack_pop', needed for - the forthcoming CFF2 support. - - * src/cff/cf2stack.c (cf2_stack_init): Add argument for stack size. - (cf2_stack_free): Deallocate stack. - (cf2_stack_count, cf2_stack_pushInt, cf2_stack_pushFixed, - cf2_stack_popInt, cf2_stack_popFixed, cf2_stack_getReal, - cf2_stack_clear): Updated. - (cf2_stack_setReal, cf2_stack_pop): New functions. - - * src/cff/cf2stack.h (CF2_Stack): Add `stackSize' member. - Update function declarations. - - * src/cff/cf2intrp.c (cf2_interpT2CharString): Updated. - - * src/cff/cffparse.c (cff_parser_init): Add parameter for stack - size; return error code. - (cff_parser_done): New function. - (cff_parser_run): Updated. - - * src/cff/cffparse.h (CFF_Parser): Add `stackSize' member and make - `stack' a pointer. - Update function declarations. - - * src/cff/cffload.c (cff_load_private_dict, cff_subfont_load): - Updated. - -2016-12-15 Dave Arnold - Werner Lemberg - - [cff] Code shuffling. - - * src/cff/cfftypes.h (CFF_Font): Add `library' and `base_offset' - fields. - - * src/cff/cffload.c (cff_subfont_load): Change last argument to - `CFF_Font' - Split off parsing of private dictionary into... - (cff_load_private_dict): ...this new function. - (cff_font_load): Updated. - -2016-12-14 Werner Lemberg - - [sfnt, truetype] Add framework for Metrics Variations service. - - No effect yet; service functions will be implemented later on. - - Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT. - - * include/freetype/internal/services/svmetric.h: New file. - - * include/freetype/internal/ftserv.h - (FT_SERVICE_METRICS_VARIATIONS_H): New macro. - - * include/freetype/internal/tttypes.h (TT_Face): New field `var'. - - * src/sfnt/sfobjs.c: Include FT_SERVICE_METRICS_VARIATIONS_H. - (sfnt_init_face): Initialize `face->var'. - - * src/truetype/ttdriver.c: Include FT_SERVICE_METRICS_VARIATIONS_H. - (tt_service_metrics_variations): New service. - (tt_services): Updated. - - * src/truetype/ttpic.h: Updated. - -2016-12-14 Werner Lemberg - - [cff] Add Multiple Masters service. - - The code simply uses the MM functions from the `truetype' module. - - Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT. - - * include/freetype/internal/tttypes.h (TT_Face): New field `mm'. - - * src/cff/cffdrivr.c: Include FT_SERVICE_MULTIPLE_MASTERS_H. - (cff_set_mm_blend, cff_get_mm_blend, cff_get_mm_var, - cff_set_var_design, cff_get_var_design): New functions. - (cff_service_multi_masters): New service. - (cff_services): Updated. - - * src/cff/cffload.c (cff_get_var_blend, cff_done_blend): New - functions. - * src/cff/cffload.h: Updated. - - * src/cff/cffpic.h (CFF_SERVICE_MULTI_MASTERS_GET): New macro. - - * src/sfnt/sfobjs.c: Include FT_SERVICE_MULTIPLE_MASTERS_H. - (sfnt_init_face): Initialize `face->mm'. - -2016-12-14 Werner Lemberg - - Extend functionality of `ft_module_get_service'. - - It can now differentiate between local and global searches. - - * src/base/ftobjs.c (ft_module_get_service): Add `global' argument. - (FT_Get_TrueType_Engine_Type): Updated. - - * src/cff/cffdrivr.c (cff_get_ps_name, cff_get_cmap_info): Updated. - - * include/freetype/internal/ftobjs.h: Updated. - * include/freetype/internal/ftserv.h (FT_FACE_FIND_GLOBAL_SERVICE): - Updated. - -2016-12-14 Werner Lemberg - - * src/truetype/ttgxvar.c (tt_get_var_blend): Fix compiler warning. - -2016-12-14 Dave Arnold - Werner Lemberg - - [sfnt, cff] Minor preparations. - - * include/freetype/tttags.h (TTAG_CFF2, TTAG_HVAR, TTAG_MVAR, - TTAG_VVAR): New SFNT table tags. - - * src/cff/cf2fixed.h (CF2_FIXED_ONE, CF2_FIXED_EPSILON): Add cast. - -2016-12-10 Werner Lemberg - - [truetype, type1] Add `get_var_blend' to MM service. - - For internal use; we want to share code between the forthcoming CFF2 - support and TrueType. - - * include/freetype/internal/services/svmm.h (FT_Get_Var_Blend_Func): - New typedef. - (MultiMasters): Add `get_var_blend'. - (FT_Service_MultiMasters): Updated. - - * src/truetype/ttgxvar.c (tt_get_var_blend): New function. - * src/truetype/ttgxvar.h: Updated. - - * src/truetype/ttdriver.c (tt_service_gx_multi_masters): Updated. - * src/type1/t1driver.c (t1_service_multi_masters): Updated. - -2016-12-10 Werner Lemberg - - [truetype, type1] Add `done_blend' to MM service. - - For internal use; we want to share code between the forthcoming CFF2 - support and TrueType. - - * include/freetype/internal/services/svmm.h (FT_Done_Blend_Func): - New typedef. - (MultiMasters): Add `done_blend'. - (FT_Service_MultiMasters): Updated. - - * src/truetype/ttgxvar.c (tt_done_blend): Use `TT_Face' as argument. - * src/truetype/ttgxvar.h: Updated. - - * src/truetype/ttobjs.c (TT_Face_Done): Updated. - - * src/truetype/ttdriver.c (tt_service_gx_multi_masters): Updated. - * src/type1/t1driver.c (t1_service_multi_masters): Updated. - -2016-12-09 Werner Lemberg - - [sfnt] Revert change from 2016-12-08. - - I missed the functionality of `ft_module_get_service', which makes - the change unnecessary. - -2016-12-08 Werner Lemberg - - Add framework to support services with 8 functions. - - We will need this for CFF variation font support. - - * include/freetype/internal/ftserv.h (FT_DEFINE_SERVICEDESCREC8): - New macro. - -2016-12-08 Werner Lemberg - - [sfnt] Add `get_glyph_name' and `get_name_index' to SFNT interface. - - CFF2 fonts will need access to those two functions. - - * include/freetype/internal/sfnt.h: Include FT_SERVICE_GLYPH_DICT_H. - (SFNT_Interface): Add `get_glyph_name' and `get_name_index' members. - (FT_DEFINE_SFNT_INTERFACE): Updated. - - * src/sfnt/sfdriver.c (sfnt_get_glyph_name, sfnt_get_name_index): - Fix signatures to exactly correspond to the glyph dict service - function typedefs. - (sfnt_interface): Updated. - -2016-12-06 Dave Arnold - - Add `FT_Get_Var_Design_Coordinates' function. - - Note that the low-level functions aren't implemented yet. - - * include/freetype/ftmm.h: Declare. - - * include/freetype/internal/services/svmm.h - (FT_Get_Var_Design_Func): New typedef. - (MultiMasters): New MM service function `get_var_design'. - (FT_DEFINE_SERVICE_MULTIMASTERSREC): Updated. - Update all callers. - - * src/base/ftmm.c (FT_Get_Var_Design_Coordinates): Implement. - - * src/truetype/ttdriver.c: Updated. - - * src/truetype/ttgxvar.c (TT_Get_Var_Design): New dummy function to - handle `get_var_design' service. - * src/truetype/ttgxvar.h: Updated. - - * src/type1/t1driver.c: Updated. - - * src/type1/t1load.c (T1_Get_Var_Design): New dump function to - handle `get_var_design' service. - * src/type1/t1load.h: Updated. - -2016-12-06 Werner Lemberg - - * src/type1/t1load.c (parse_subrs): Fix memory leak. - - The `subrs' keyword might erroneously occur multiple times. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=231 - -2016-12-01 Werner Lemberg - - [gzip] Improve building with external zlib (#49673). - - Building FreeType with external zlib 1.2.8 makes msvc 14 stop with - the following error. - - ftgzip.c - zlib-1.2.8\zlib.h(86): error C2061: - syntax error: identifier 'z_const' - zlib-1.2.8\zlib.h(94): error C2054: - expected '(' to follow 'z_const' - zlib-1.2.8\zlib.h(94): error C2085: - 'msg': not in formal parameter list - ... - zlib-1.2.8\zlib.h(877): fatal error C1003: - error count exceeds 100; stopping compilation - - The error happens because FreeType keeps an own copy of zlib-1.1.4 - under `src/gzip'. When building `src/gzip/ftgzip.c' with - FT_CONFIG_OPTION_SYSTEM_ZLIB defined, it uses - - #include - - which correctly finds an external `zlib.h', but `zlib.h' itself has - a line - - #include "zconf.h" - - which makes Visual Studio 2015 find `src/gzip/zconf.h' while - compiling the files in `src/gzip'. - - * src/gzip/zconf.h: Rename to... - * src/gzip/ftzconf.h: ... this. - * src/gzip/zlib.h, src/gzip/rules.mk (GZIP_DRV_SRCS): Updated. - -2016-12-01 Oleksandr Chekhovskyi - - [autofit] Fix Emscripten crash (patch #9180). - - Function calls through pointers must use a matching signature to - work on Emscripten, since such calls are dispatched through lookup - tables grouped by signature. - - * src/autofit/aftypes.h (AF_WritingSystem_ApplyHintsFunc): Fix - typedef. - -2016-11-29 Werner Lemberg - - [smooth] Revert previous commit. Already fixed with 6ca54c64. - -2016-11-29 Werner Lemberg - - [smooth] Avoid conditional jump on uninitialized value (#49711). - - * src/smooth/ftgrays.c (gray_raster_render): Initialize `worker'. - -2016-11-27 Nikolaus Waxweiler - - [autofit] Code shuffling. - - Also improve some comments and remove unused code. - - No functional change. - - * src/autofit/afloader.c (af_loader_load_g): Merged with... - (af_loader_load_glyph): ...this function. - Split off emboldening code into... - (af_loader_embolden_glyph_in_slot): ... this function. - -2016-11-17 Werner Lemberg - - Better support of LLP64 systems with gcc (and clang). - - * builds/unix/configure.raw: Call `AC_TYPE_LONG_LONG_INT'. - - * builds/unix/ftconfig.in (FT_LONG64): Enable for LLP64 systems (and - suppress warnings) even without `FT_CONFIG_OPTION_FORCE_INT64'. - -2016-11-10 Werner Lemberg - - Fix `lcd_weights' array size. - - * include/freetype/internal/ftobjs.h (FT_LibraryRec): Do it. - - Reported by Nikolaus. - -2016-11-06 Werner Lemberg - - * src/base/ftobjs.c (FT_Render_Glyph_Internal): Fix tracing. - -2016-11-06 Werner Lemberg - - [sfnt] Improve FT_LOAD_BITMAP_METRICS_ONLY for `sbix' format. - - It's unavoidable to call the PNG engine, but to get the metrics it - is sufficient to read the PNG image's header only. - - * src/sfnt/pngshim.c (Load_SBit_Png): Add argument to control the - allocation of the glyph slot. - * src/sfnt/pngshim.h: Updated. - * src/sfnt/ttsbit.c (tt_sbit_decoder_load_png, - tt_face_load_sbix_image, tt_face_load_sbit_image): Updated. - -2016-11-06 Werner Lemberg - - [sfnt] Speed up `sbix' lookup. - - This also fixes a bug introduced in 2016-10-01 which prevents - display of embedded bitmap fonts that use the `sbix' format. - - * src/sfnt/ttsbit.c (tt_face_load_sbit): Store `sbix' size and - offset also in `ebdt_size' and `ebdt_start', respectively. This - makes the test for an embedded bitmap data table succeed for this - format. - - (tt_face_load_strike_metrics) : Use - `ebdt_size' and `ebdt_start' - (tt_face_load_sbix_image): Ditto. - -2016-11-06 Seigo Nonaka - Werner Lemberg - - Introduce a way of quickly retrieving (embedded) bitmap metrics. - - `FT_Load_Glyph' doesn't generate a bitmap for a non-bitmap glyph - until the user calls `FT_Render_Glyph'. However, it always - allocates memory for bitmaps and copies or decodes the contents of a - bitmap glyph, which can be quite slow for PNG data. - - * include/freetype/freetype.h (FT_LOAD_BITMAP_METRICS_ONLY): New - macro. - - * src/base/ftobjs.c (FT_Load_Glyph): Unset FT_LOAD_RENDER if - FT_LOAD_BITMAP_METRICS_ONLY is used. - - * src/sfnt/ttsbit.c (tt_sbit_decoder_alloc_bitmap, - tt_sbit_decoder_load_bitmap): Add argument to control allocation of - the glyph slot. - (tt_sbit_decoder_load_image, tt_sbit_decoder_load_compound, - tt_face_load_sbit_image): Updated. - - * src/pcf/pcfdrivr.c (PCF_Glyph_Load): Quickly exit if - `FT_LOAD_BITMAP_METRICS_ONLY' is set. - - * src/pfr/pfrsbit.c, src/pfr/pfrsbit.h (pfr_slot_load_bitmap): Add - argument to control allocation of the glyph slot. - * src/pfr/pfrobjs (pfr_slot_load): Updated. - - * src/winfonts/winfnt.c (FNT_Load_Glyph): Ditto. - - * docs/CHANGES: Updated. - -2016-11-06 Werner Lemberg - - Synchronize with gnulib (#49448). - - * include/freetype/config/ftconfig.h, builds/unix/ftconfig.in, - builds/vms/ftconfig.h (FT_TYPEOF): Update code to use definition in - current version of `intprops.h'. - Other minor synchronization to reduce code differences between the - three files. - -2016-11-03 Behdad Esfahbod - - [truetype] Clamp variation requests to valid range. - - This is required by OpenType 1.8; it also avoids rounding surprises. - - * src/truetype/ttgxvar.c (TT_Set_Var_Design): Clamp design coordinates - outside of the allowed range to always stay within the range instead - of producing an error. - -2016-10-29 Werner Lemberg - - [truetype] Remove clang warnings. - - * src/truetype/ttinterp.h (TT_ExecContextRec): Using `FT_ULong' for - loop counter handling. - - * src/truetype/ttinterp.c: Updated. - (Ins_SCANTYPE): Use signed constant. - (TT_RunIns): Ensure `num_twilight_points' is 16bit. - -2016-10-27 Werner Lemberg - - [truetype] Fix commit from 2014-11-24. - - Problem reported by Hin-Tak Leung . - - * src/truetype/ttpload.c (tt_face_load_hdmx): Fix file checking - logic. - -2016-10-26 Werner Lemberg - - Add `FT_Get_{MM,Var}_Blend_Coordinates' functions. - - * include/freetype/ftmm.h: Declare. - - * include/freetype/internal/services/svmm.h (FT_Get_MM_Blend_Func): - New typedef. - (MultiMasters): New MM service function `get_mm_blend'. - (FT_DEFINE_SERVICE_MULTIMASTERSREC): Updated. - Update all callers. - - * src/base/ftmm.c (FT_Get_MM_Blend_Coordinates, - FT_Get_Var_Blend_Coordinates): Implement. - - * src/truetype/ttdriver.c: Updated. - - * src/truetype/ttgxvar.c (TT_Get_MM_Blend): New function to handle - `get_mm_blend' service. - * src/truetype/ttgxvar.h: Updated. - - * src/type1/t1driver.c: Updated. - - * src/type1/t1load.c (T1_Get_MM_Blend): New function to handle - `get_mm_blend' service. - * src/type1/t1load.h: Updated. - - * docs/CHANGES: Document. - -2016-10-26 Werner Lemberg - - * src/type1/t1load.c (parse_subrs): Fix limit check. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=81 - -2016-10-25 Alexei Podtelezhnikov - - [cff] Correct cmap format reporting (#24819). - - * src/cff/cffdrivr.c (cff_get_cmap_info): Throw an error on synthetic - charmap instead of guessing its format and language. - -2016-10-22 Werner Lemberg - - [truetype] Fix SCANTYPE instruction (#49394). - - * src/truetype/ttinterp.c (Ins_SCANTYPE): Only use lower 16bits. - -2016-10-22 Werner Lemberg - - [sfnt] Improve handling of invalid post 2.5 tables [#49393]. - - * src/sfnt/ttpost.c (load_format_25): We need at least a single - table entry. - -2016-10-14 Werner Lemberg - - [truetype] Fix handling of `cvar' table data. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=53 - - * src/truetype/ttgxvar.c (tt_face_vary_cvt): Ignore invalid CVT - indices. - -2016-10-11 Werner Lemberg - - [psaux] Fix handling of invalid flex subrs. - - Problem reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=52 - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings) - : Set `flex_state' after error checking. - -2016-10-11 Werner Lemberg - - * src/truetype/ttgxvar.c (tt_done_blend): Fix deallocation. - -2016-10-08 Werner Lemberg - - * src/cid/cidload.c (cid_face_open): Properly propagate `error'. - -2016-10-08 Werner Lemberg - - [cid] Fix parsing of subr offsets. - - Bug introduced 2016-05-16. - - * src/cid/cidparse.c (cid_parser_new): Fix off-by-one error. - -2016-10-01 Werner Lemberg - - [sfnt] Disable bitmap strikes if we don't have a bitmap data table. - - * src/sfnt/ttsbit.c (tt_face_load_sbit): Check whether we have - a bitmap data table. - -2016-10-01 Alexei Podtelezhnikov - - [smooth] Remove impossibility. - - * src/smooth/ftgrays.c (TWorker): Rearrange fields. - (gray_convert_glyph): Remove impossible condition and clean up. - -2016-09-29 Werner Lemberg - - [pcf] Enrich family name with foundry name and glyph width info. - - This is a very old patch from openSuSE (from 2006, submitted to - FreeType in 2011) that I forgot to apply. - - https://build.opensuse.org/package/view_file/openSUSE:Factory/freetype2/freetype2-bitmap-foundry.patch - - Prepend the foundry name plus a space to the family name. There are - many fonts just called `Fixed' which look completely different, and - which have nothing to do with each other. When selecting `Fixed' in - KDE or Gnome one gets results that appear rather random, the style - changes often if one changes the size and one cannot select some - fonts at all. - - We also check whether we have `wide' characters; all put together, - we get family names like `Sony Fixed' or `Misc Fixed Wide'. - - * src/pcf/pcfread.c (pcf_load_font): Implement it. - - * docs/CHANGES: Document it. - -2016-09-29 Werner Lemberg - - [ftfuzzer] Speed up. - - * src/tools/ftfuzzer/ftfuzzer.cc (LLVMFuzzerTestOneInput): Don't - check for embedded bitmaps if we have a non-default instance. - -2016-09-29 Werner Lemberg - - [truetype] Disallow bitmap strikes for non-default instances. - - Also speed up access of default instances if GX variations are - active. - - * include/freetype/internal/tttypes.h (TT_FaceRec): Add - `is_default_instance' member. - - * src/sfnt/sfobjs.c (sfnt_init_face): Initialize - `is_default_instance'. - - * src/truetype/ttgload.c (TT_Process_Simple_Glyph, - load_truetype_glyph): Add test for default instance. - (TT_Load_Glyph): Load embedded bitmaps for default instance only. - - * src/truetype/ttgxvar.c (TT_Set_MM_Blend): Compute - `is_default_instance'. - -2016-09-29 Werner Lemberg - - [truetype] Clean up `TT_Face' structure. - - * include/freetype/internal/tttypes.h (TT_FaceRec): Remove unused - fields `horz_metrics' and `vert_metrics'. - Update documentation. - - * src/sfnt/sfobjs.c (sfnt_done_face): Updated. - -2016-09-28 Werner Lemberg - - More FT_ZERO usage. - - * src/gxvalid/gxvcommn.c (gxv_ClassTable_validate): - s/ft_memset/FT_MEM_ZERO/. - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings): - s/ft_memset/FT_ARRAY_ZERO/. - - * src/raster/ftraster.c (FT_ZERO): Define. - (ft_black_new): Use it. - * src/raster/ftrend1.c (ft_raster1_get_cbox): - s/FT_MEM_ZERO/FT_ZERO/. - - * src/smooth/ftgrays.c (FT_ZERO): Define. - (gray_raster_new): Use it. - * src/smooth/ftsmooth.c (ft_smooth_get_cbox): - s/FT_MEM_ZERO/FT_ZERO/. - -2016-09-28 Werner Lemberg - - */*: s/FT_MEM_ZERO/FT_ZERO/ where appropriate. - -2016-09-27 Werner Lemberg - - [truetype] Trace number of executed opcodes. - - * src/truetype/ttinterp.c (TT_RunIns): Implement it. - -2016-09-27 Werner Lemberg - - [truetype] Speed up `TT_Load_Glyph'. - - This avoids additional calls to `tt_face_lookup_table' for the - `glyf' table, which can be expensive. - - * include/freetype/internal/tttypes.h (TT_LoaderRec): Move - `glyf_offset' field to ... - (TT_FaceRec): ... this structure. - * src/truetype/ttgload.c (load_truetype_glyph): Updated. - (tt_loader_init): Move initialization of `glyf_offset' to ... - * src/truetype/ttpload.c (tt_face_load_loca): ... this function. - -2016-09-27 Werner Lemberg - - [truetype] Introduce dynamic limits for some bytecode opcodes. - - This speeds up FreeType's handling of malformed fonts. - - * src/truetype/ttinterp.c (TT_RunIns): Set up limits for the number - of twilight points, the total number of negative jumps, and the - total number of loops in LOOPCALL opcodes. The values are based on - the number of points and entries in the CVT table. - (Ins_JMPR): Test negative jump counter. - (Ins_LOOPCALL): Test loopcall counter. - - * src/truetype/ttinterp.h (TT_ExecContext): Updated. - - * docs/CHANGES: Updated. - -2016-09-25 Werner Lemberg - - [truetype] Sanitize only last entry of `loca' table. - - Without this patch, a loca sequence like `0 100000 0 100000 ...', - where value 100000 is larger than the `glyf' table size, makes - FreeType handle the whole `glyf' table as a single glyph again and - again, which is certainly invalid (and can be very slow, too). - - * src/truetype/ttpload.c (tt_face_get_location): Implement. - Improve tracing messages. - -2016-09-25 Werner Lemberg - - * src/tools/ftfuzzer/ftfuzzer.cc (LLVMFuzzerTestOneInput): Fix typo. - -2016-09-24 Werner Lemberg - - [autofit] Tracing fixes. - - * src/autofit/afmodule.c (af_autofitter_load_glyph): Call dumping - functions only if we actually do tracing. - -2016-09-22 Alexei Podtelezhnikov - - [smooth] Reduce divisions in the line renderer. - - We don't need some divisions if a line segments stays within a single - row or a single column of pixels. - - * src/smooth/ftgrays.c (gray_render_line) [FT_LONG64]: Make divisions - conditional. - -2016-09-15 Alexei Podtelezhnikov - - * src/smooth/ftgrays.c (gray_sweep): Remove check for empty table. - -2016-09-14 Alexei Podtelezhnikov - - [smooth] Another tiny speed-up. - - * src/smooth/ftgrays.c (gray_find_cell): Merge into... - (gray_record_cell): ... this function. - -2016-09-11 Alexei Podtelezhnikov - - * src/smooth/ftgrays.c (gray_{find,set}_cell): Remove dubious code. - -2016-09-11 Alexei Podtelezhnikov - - [smooth] Fix valgrind warning and reoptimize. - - The algorithm calls `gray_set_cell' at the start of each new contour - or when the contours cross the cell boundaries. Double-checking for - that is wasteful. - - * src/smooth/ftgrays.c (gray_set_cell): Remove check for a new cell. - (gray_convert_glyph): Remove initialization introduced by 44b172e88. - -2016-09-10 Werner Lemberg - - [sfnt] Fix previous commit. - - Problems reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=40 - - We now map the strike index right before accessing the physical - data, not earlier. - - * src/sfnt/sfobjs.c (sfnt_load_face): Set `face->sbit_strike_map' - after creating the map so that... - - * src/sfnt/ttsbit.c (tt_face_load_strike_metrics): ... this function - can be used before and after setting up `sbit_strike_map'. - (tt_face_set_sbit_strike): Revert change. - (tt_sbit_decoder_init, tt_face_load_sbix_image): Map strike index. - - * src/truetype/ttdriver.c (tt_size_select): Revert change. - -2016-09-09 Werner Lemberg - - [ftfuzzer] Minor improvements. - - * src/tools/ftfuzzer/ftfuzzer.cc (LLVMFuzzerTestOneInput): Ignore - invalid strikes. - Use better values for call to `FT_Set_Char_Size'. - -2016-09-09 Werner Lemberg - - [sfnt] Don't provide (completely) broken strike data. - - FreeType tries to sanitize strike header data; we now reject - completely broken ones. - - * include/freetype/internal/tttypes.h (TT_FaceRec): New - `sbit_strike_map' array pointer. - - * src/base/ftobjs.c (FT_Match_Size): Reject matches where either - width or height would be zero. - Add tracing message in case of error. - - * src/sfnt/sfobjs.c (sfnt_load_face): Populate `sbit_strike_map', - only using (more or less) valid strike header data for - FT_Face's `available_sizes' array. - (sfnt_done_face): Updated. - - * src/sfnt/ttsbit.c (tt_face_set_sbit_strike): Use - `sbit_strike_map'. - (tt_face_load_strike_metrics): Improve tracing. - - * src/truetype/ttdriver.c (tt_size_select): Use `sbit_strike_map'. - -2016-09-08 Werner Lemberg - - * Version 2.7 released. - ======================= - - - Tag sources with `VER-2-7'. - - * docs/VERSION.TXT: Add entry for version 2.7. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.6.5/2.7/, s/265/27/. - - * include/freetype/freetype.h (FREETYPE_MINOR): Set to 7. - (FREETYPE_PATCH): Set to 0. - - * builds/unix/configure.raw (version_info): Set to 18:6:12. - * CMakeLists.txt (VERSION_MINOR): Set to 7. - (VERSION_PATCH): Set to 0. - - * docs/CHANGES: Updated. - -2016-09-08 Werner Lemberg - - * src/truetype/ttinterp.c: Include `ttgxvar.h'. - - This fixes the `multi' build. - -2016-09-08 Werner Lemberg - - [autofit] Another improvement to Armenian support. - - Suggested by Hrant H Papazian . - - * src/autofit/afscript.h: Use better suited characters to derive - default stem widths. - -2016-09-07 Alexei Podtelezhnikov - - * src/smooth/ftgrays.c (gray_hline): Micro-optimize. - -2016-09-06 Alexei Podtelezhnikov - - [smooth] Operate in absolute bitmap coordinates. - - Simpler bitmap addressing improves performance by 1.5%. - - * src/smooth/ftgrays.c (gray_TWorker): Remove count fields. - (gray_dump_cells, gray_find_cell, gray_set_cell, gray_hline, - gray_sweep, gray_convert_glyph, gray_raster_render): Updated. - -2016-09-06 Alexei Podtelezhnikov - - [smooth] Improve contour start (take 2). - - * src/smooth/ftgrays.c (gray_move_to): Call `gray_set_cell' directly - instead of... - (gray_start_cell): ... this function, which is removed. - (gray_convert_glyph): Make initial y-coordinate invalid. - -2016-09-06 Werner Lemberg - - [type1] MM fonts support exactly zero named instances (#48748). - - * src/type1/t1load.c (T1_Get_MM_Var): Set `num_namedstyles' to zero. - -2016-09-06 Jonathan Kew - - [cff] Fix uninitialized memory. - - Problem reported as - - https://bugzilla.mozilla.org/show_bug.cgi?id=1270288 - - * src/cff/cf2intrp.c (cf2_interpT2CharString): Initialize `storage' - array to handle a `get' opcode without a previous `put'. - -2016-09-05 Alexei Podtelezhnikov - - * src/smooth/ftgrays.c (gray_move_to, gray_start_cell): Revert. - -2016-09-05 Alexei Podtelezhnikov - - [smooth] Improve contour start. - - * src/smooth/ftgrays.c (gray_move_to): Call `gray_set_cell' directly - instead of... - (gray_start_cell): ... this function, which is removed. - -2016-09-05 Werner Lemberg - - [cff] Fix memory initialization. - - * src/cff/cf2stack.c (cf2_stack_init): Use `FT_NEW'. The `Q' - variants of FreeType's memory allocation macros don't do zeroing. - -2016-09-05 Werner Lemberg - - [ftrandom] Minor improvements. - - * src/tools/ftrandom/ftrandom.c (_XOPEN_SOURCE): New macro, set to - 500. - - * src/tools/ftrandom/Makefile (CFLAGS): Split off include - directories to ... - (INCLUDES): ... this new variable. - (LDFLAGS): New variable. - (ftrandom.o, ftrandom): Updated. - -2016-09-05 Werner Lemberg - - [autofit] Improve Armenian support. - - Thanks to Hrant H Papazian for help. - - * src/autofit/afblue.dat (AF_BLUE_STRING_ARMENIAN_*): Improve - selection of characters. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - -2016-09-04 Werner Lemberg - - [ftrandom] Improve Makefile. - - It now supports both a normal build (`./configure && make') and a - development build (`make devel'). - - * src/tools/ftrandom/Makefile (VPATH): Set it so that - `libfreetype.a' gets searched in both `objs' (for the development - build) and `objs/.libs' (for a normal build which uses libtool). - (LIBS): Add missing libraries. - (ftrandom.o): New rule. - (ftrandom): Use automatic variables. - -2016-09-03 Werner Lemberg - - [truetype] More fixes for handling of GX deltas. - - Problems reported by Bob Taylor . - - * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Fix rough - sanity test for glyph variation array header size. - Always set stream position before reading packed x and y deltas. - Fix thinko w.r.t. `localpoints' array. - -2016-09-03 Werner Lemberg - - [ftrandom] Various fixes. - - * src/tools/ftrandom/ftrandom.c (GOOD_FONTS_DIR): Provide better - default. - (error_fraction): Make it of type `double' to work as advertized – - this was completely broken. - Update all related code. - (error_count, fcnt): Make it unsigned to fix compiler warnings. - Update all related code. - (fontlist): Change `len' member to `long' to fix compiler warnings. - (FT_MoveTo, FT_LineTo, FT_ConicTo, FT_CubicTo, abort_test): Tag - unused variables. - (TestFace, FindFonts, copyfont, do_test): Fix compiler warnings. - (ExecuteTest): Ditto. - Call `FT_Done_FreeType'. - (getErrorCnt): Replace `ceil' with an ordinary cast to `unsigned - int'. - (usage): Improve output. - (main): Fix compiler warnings. - - * src/tools/ftrandom/README: Updated. - -2016-09-03 Werner Lemberg - - [base] Avoid negative bitmap strike dimensions (#48985). - - * src/base/ftobjs.c (FT_Open_Face): Check whether negation was - actually successful. For example, this can fail for value - -32768 if the type is `signed short'. If there are problems, - disable the strike. - -2016-09-03 Werner Lemberg - - [cff] Avoid null pointer passed to FT_MEM_COPY (#48984). - - * src/cff/cffload.c (cff_index_get_name): Check `byte_len'. - -2016-09-02 Werner Lemberg - - [unix] Enable 64bit support in file system access (#48962). - - * builds/unix/configure.raw: Call `AC_SYS_LARGEFILE'. - -2016-09-02 Werner Lemberg - - [sfnt] Avoid left shift of negative value (#48980). - - * src/sfnt/ttsbit.c (tt_sbit_decoder_load_bit_aligned): Use unsigned - constant. - -2016-09-02 Werner Lemberg - - * src/smooth/ftgrays.c (gray_hline): Fix clang compiler warnings. - -2016-09-02 Werner Lemberg - - Some preparations for the next release. - - * include/freetype/config/ftoption.h - (TT_CONFIG_OPTION_SUBPIXEL_HINTING): Enable. - - * docs/CHANGES: Updated. - -2016-09-01 Alexei Podtelezhnikov - - [smooth] Simplify span rendering more. - - It turns out that there is significant cost associated with `FT_Span' - creation and calls to `gray_render_span' because it happens so - frequently. This removes these steps from our internal use but leaves - it alone for `FT_RASTER_FLAG_DIRECT" to preserve API. The speed gain - is about 5%. - - * src/smooth/ftgrays.c (gray_render_span): Removed. The code is - migrated to... - (gray_hline): ... here. - -2016-08-30 Alexei Podtelezhnikov - - [smooth] Streamline pixmap drawing a bit more. - - Zero coverage is unlikely (1 out of 256) to warrant checking. This - gives 0.5% speed improvement in rendering simple glyphs. - - * src/smooth/ftgrays.c (gray_hline, gray_render_span): Remove checks. - -2016-08-29 Alexei Podtelezhnikov - - [smooth] Streamline pixmap drawing. - - This gives 2% speed improvement in rendering simple glyphs. - - * src/smooth/ftgrays.c (TPixmap): Reduced pixmap descriptor with a - pointer to its bottom-left and pitch to be used in... - (gray_TWorker): ... here. - (gray_render_span): Move pixmap flow check from here... - (gray_raster_render): .. to here. - -2016-08-27 Alexei Podtelezhnikov - - [smooth] Reduce stack of band boundaries. - - * src/smooth/ftgrays.c (gray_TBand): Removed. - (gray_convert_glyph): Updated to stack band boundaries concisely. - -2016-08-26 Werner Lemberg - - * src/cid/cidload.c (cid_face_open): Improve handling of `SDBytes'. - -2016-08-26 Werner Lemberg - - [cid] Fix commit from 2016-05-16. - - * src/cid/cidparse.c (cid_parser_new): Fix off-by-one errors. - -2016-08-26 Werner Lemberg - - [sfnt] Cache offset and size to bitmap data table. - - This commit avoids `EBDT' and friends being looked up again and - again while loading a single embedded bitmap. - - * include/freetype/internal/tttypes.h (TT_FaceRec) - [TT_CONFIG_OPTION_EMBEDDED_BITMAPS]: New fields `ebdt_start' and - `ebdt_size'. - - * src/sfnt/ttsbit.c (tt_sbit_decoder_init): Move table lookup to ... - (tt_face_load_sbit): ... this function; also store the table size - and offset. - -2016-08-26 Alexei Podtelezhnikov - - * src/smooth/ftgrays.c (gray_raster_render): Minor tweaks. - -2016-08-26 Werner Lemberg - - [type1] Fix heap buffer overflow. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=36 - - * src/type1/t1load.c (parse_charstrings): Reject fonts that don't - contain glyph names. - -2016-08-25 Werner Lemberg - - [sfnt] Fix previous commit (#48901). - - * src/sfnt/ttcmap.c (tt_cmap4_char_map_binary): Thinkos. - -2016-08-25 Werner Lemberg - - [sfnt] Speed up handling of invalid format 4 cmaps. - - * src/sfnt/ttcmap.c (tt_cmap4_next, tt_cmap4_char_map_binary): Add - tests for `num_glyph' from `tt_cmap4_char_map_linear'. - -2016-08-25 Werner Lemberg - - * include/freetype/internal/ftdriver.h: Remove unused typedefs. - -2016-08-22 Alexei Podtelezhnikov - - [smooth] Simplify span rendering. - - This removes unnecessary complexity of span merging and buffering. - Instead, the spans are rendered as they come, speeding up the - rendering by about 5% as a result. - - * src/smooth/ftgrays.c [FT_MAX_GRAY_SPANS]: Macro removed. - (gray_TWorker): Remove span buffer and related fields. - (gray_sweep, gray_hline): Updated. - - * include/freetype/ftimage.h: Remove documentation note about - `FT_MAX_GRAY_SPANS', which was never in `ftoption.h' and is now gone. - -2016-08-16 Werner Lemberg - - [truetype] Fix `MPS' instruction. - - According to Greg Hitchcock, MPS in DWrite really returns the point - size. - - * src/truetype/ttobjs.h (TT_SizeRec): Add `point_size' member. - - * src/truetype/ttdriver.c (tt_size_request): Set `point_size'. - - * src/truetype/ttinterp.h (TT_ExecContextRec): Add `pointSize' - member. - - * src/truetype/ttinterp.c (TT_Load_Context): Updated. - (Ins_MPS): Fix instruction. - -2016-08-16 Werner Lemberg - - [lzw] Optimize last commit. - - * src/lzw/ftzopen.c (ft_lzwstate_get_code): Move check into - conditional clause. - -2016-08-16 Werner Lemberg - - [lzw] Avoid invalid left shift. - - Reported as - - https://bugzilla.mozilla.org/show_bug.cgi?id=1295366 - - * src/lzw/ftzopen.c (ft_lzwstate_get_code): Limit `num_bits'. - -2016-08-16 Werner Lemberg - - [lzw] Avoid buffer overrun. - - Reported as - - https://bugzilla.mozilla.org/show_bug.cgi?id=1273283 - - * src/lzw/ftzopen.c (ft_lzwstate_refill): Ensure `buf_size' doesn't - underflow. - -2016-08-16 Werner Lemberg - - [truetype] Fix compiler warning. - - * src/truetype/ttgload.c (load_truetype_glyph): Add cast. - -2016-08-13 Werner Lemberg - - [winfonts] Avoid zero bitmap width and height. - - Reported as - - https://bugzilla.mozilla.org/show_bug.cgi?id=1272173 - - * src/winfonts/winfnt.c (FNT_Face_Init): Check zero pixel height. - (FNT_Load_Glyph): Check for zero pitch. - -2016-08-11 Alexei Podtelezhnikov - - * src/truetype/ttinterp.c (Pop_Push_Count): Revert changes. - -2016-08-11 Alexei Podtelezhnikov - - * src/truetype/ttinterp.c (TT_RunIns): Minor and formatting. - -2016-08-11 Alexei Podtelezhnikov - - * src/truetype/ttinterp.c (Pop_Push_Count): Fix some entries. - -2016-08-10 Peter Klotz - - * src/smooth/ftgrays.c (gray_hline): Fix uninitialized access. - -2016-08-10 Werner Lemberg - - [sfnt] Use correct type for `italicAngle' field (#48732). - - * src/sfnt/ttload.c (tt_face_load_post): Fix types. - -2016-08-06 Jon Spencer - - [sfnt] Fix `FT_Get_Advance' for bitmap strikes. - - `FT_Get_Advance' returns 0 for bitmap fonts. It first gets the - advance value from the font table and then scales it by the - `font->size->metrics->x_scale' field. But `FT_Select_Size' doesn't - set that value for bitmap fonts and the advance gets scaled to zero. - - Taken from - - https://github.com/behdad/harfbuzz/issues/252 - - * src/sfnt/ttsbit.c (tt_face_load_strike_metrics) - : Set scale values. - -2016-08-06 Behdad Esfahbod - - [truetype] Fix GX variation handling of composites. - - * src/truetype/ttgload.c (load_truetype_glyph) - [TT_CONFIG_OPTION_GX_VAR_SUPPORT]: Check `ARGS_ARE_XY_VALUES' flag. - -2016-08-05 Alexei Podtelezhnikov - - [smooth] Minor refactoring. - - * src/smooth/ftgrays.c (gray_render_scanline, gray_render_line): - Updated. - -2016-07-29 Werner Lemberg - - [sfnt, truetype] Don't abort on invalid `maxComponentDepth'. - - Since 2016-05-16 we detect infinite recursion directly. - - * src/sfnt/ttload.c (tt_face_load_maxp): Don't adjust - `maxComponentDepth'. - * src/truetype/ttgload.c (load_truetype_glyph): Don't abort if - `maxComponentDepth' is not valid. Instead, simply adjust its value - and emit a tracing message. - -2016-07-26 Werner Lemberg - - * src/autofit/aflatin.c (af_latin_metrics_scale_dim): Minor. - - No functional change. - -2016-07-22 Hin-Tak Leung - - [truetype] Record the end of IDEFs. - - To match the logic in FDEF. The value of the end is only used for - bound-checking in `Ins_JMPR', so it may not have been obvious that - it was not recorded. Tested (as part of Font Validator 2.0) all the - fonts on Fedora and did not see any change. - - * src/truetype/ttinterp.c (Ins_IDEF): Updated. - -2016-07-19 Werner Lemberg - - [truetype] Sanitizer fix, second try. - - * src/truetype/ttgxvar.c (ft_var_readpackedpoints): Fix boundary - tests and use only one slot more. - -2016-07-19 Werner Lemberg - - [truetype] Sanitizer fix. - - * src/truetype/ttgxvar.c (ft_var_readpackedpoints): Increase array - to fix nested loops. - -2016-07-18 Werner Lemberg - - [truetype] Make GETDATA work only for GX fonts. - - * src/truetype/ttinterp.c (opcode_name): Updated. - (Ins_GETDATA): Only define for `TT_CONFIG_OPTION_GX_VAR_SUPPORT'. - (TT_RunIns): Updated. - -2016-07-17 Werner Lemberg - - [truetype] Add support for Apple's - - GETDATA[], opcode 0x92 - - bytecode instruction. It always returns 17, and we have absolutely - no idea what it is good for... - - * src/truetype/ttinterp.c (Pop_Push_Count, opcode_name): Updated. - (Ins_GETDATA): New function. - (TT_RunIns): Add it. - -2016-07-16 Werner Lemberg - - [truetype] Add bytecode support for GX variation fonts. - - This commit implements undocumented (but confirmed) stuff from - Apple's old bytecode engine. - - GETVARIATION[], opcode 0x91 - This opcode pushes normalized variation coordinates for all axes - onto the stack (in 2.14 format). Coordinate of first axis gets - pushed first. - - GETINFO[], selector bit 3 - If GX variation support is enabled, bit 10 of the result is set - to 1. - - * src/truetype/ttinterp.c: Include FT_MULTIPLE_MASTERS_H. - (opcode_name) [TT_CONFIG_OPTION_GX_VAR_SUPPORT]: Updated. - (Ins_GETINFO) [TT_CONFIG_OPTION_GX_VAR_SUPPORT]: Handle selector - bit 3, checking support for variation glyph hinting. - (Ins_GETVARIATION) [TT_CONFIG_OPTION_GX_VAR_SUPPORT]: New function - to implement opcode 0x91. - (TT_RunIns) [TT_CONFIG_OPTION_GX_VAR_SUPPORT]: Handle opcode 0x91. - -2016-07-16 Werner Lemberg - - [truetype] Fix GETINFO bytecode instruction. - - * src/truetype/ttinterp.c (Ins_GETINFO): Fix return value for - stretching information. - -2016-07-16 Behdad Esfahbod - - [truetype] Make all glyphs in `Zycon' GX font work. - - * src/truetype/ttgxvar.c (ft_var_readpackedpoints): Fix boundary - tests. - -2016-07-16 Werner Lemberg - - [truetype] Fix GX delta tracing. - - * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Trace - relative point movements. - -2016-07-16 Behdad Esfahbod - - [truetype] More fixes for GX. - - This finally fixes the rendering of the cyclist and the lizard in - the `Zycon' font. - - * src/truetype/ttgxvar.c (ft_var_readpackedpoints): `first' point - index is always cumulative. - - (tt_handle_deltas): Rename to... - (tt_interpolate_deltas): ... This. - Add new parameter for output point array. - Update caller. - - (TT_Vary_Apply_Glyph_Deltas): Add `points_out' array; it now holds - the intermediate results of `tt_interpolate_deltas' that are to be - added to `outline->points'. - -2016-07-15 Werner Lemberg - - * src/autofit/aflatin.c (af_latin_hints_compute_segments): Thinko. - - `max_pos' is always larger than `min_pos' so `FT_ABS' is not needed. - - Reported by Alexei. - -2016-07-16 Nikolaus Waxweiler - - * src/truetype/ttinterp.c (Ins_MIRP): Fix copy-and-paste error. - - Problem reported by Hin-Tak Leung. - -2016-07-15 Werner Lemberg - - [autofit] Update and improve segment and edge tracing. - - * src/autofit/afhints.c (af_glyph_hints_dump_segments): Trace - `delta' also. - Don't show first point of segment as a replacement for `pos'; this - is (a) misleading, since the difference to `pos' can be almost - arbitrarily large in corner cases, and (b) it is better to have all - segment data in font units instead of a single value given in output - space coordinates. - Improve layout. - (af_glyph_hints_dump_edges): Show px->units and units->px conversion - values for convenience. - Improve layout. - -2016-07-15 Werner Lemberg - - [autofit] For edges, reject segments wider than 1px (#41334). - - * src/autofit/afhints.h (AF_SegmentRec): New member `delta'. - - * src/autofit/aflatin.c (af_latin_hints_compute_segments): Compute - `delta'. - (af_latin_hints_compute_edges): Reject segments with a delta larger - than 0.5px. - -2016-07-14 Werner Lemberg - - * include/freetype/freetype.h (FT_IS_NAMED_INSTANCE): New macro. - -2016-07-14 Werner Lemberg - - [sfnt] Fix `face_index' value in `FT_Face' for named instances. - - * src/sfnt/sfobjs.c (sfnt_init_face): Don't strip off higher 16bits. - -2016-07-14 Werner Lemberg - - * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Fix tracing. - -2016-07-14 Behdad Esfahbod - - [truetype] Fix gxvar delta interpolation. - - The coordinates of the base font should be used for interpolation - purposes, NOT the current points (i.e., the result of accumulation - of previous deltas). - - * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Initialize - `points_org' before looping over all tuples. - - ----------------------------------------------------------------------------- - -Copyright (C) 2016-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, modified, -and distributed under the terms of the FreeType project license, -LICENSE.TXT. By continuing to use, modify, or distribute this file you -indicate that you have read the license and understand and accept it -fully. - - -Local Variables: -version-control: never -coding: utf-8 -End: diff --git a/lib/libesp32_lvgl/freetype/ChangeLog.28 b/lib/libesp32_lvgl/freetype/ChangeLog.28 deleted file mode 100644 index b17a751dc..000000000 --- a/lib/libesp32_lvgl/freetype/ChangeLog.28 +++ /dev/null @@ -1,3136 +0,0 @@ -2017-09-16 Werner Lemberg - - * Version 2.8.1 released. - ========================= - - - Tag sources with `VER-2-8-1'. - - * docs/VERSION.TXT: Add entry for version 2.8.1. - * docs/CHANGES: Updated. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.8/2.8.1/, s/28/281/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 1. - - * builds/unix/configure.raw (version_info): Set to 21:0:15. - * CMakeLists.txt (VERSION_PATCH): Set to 1. - -2017-09-13 suzuki toshiya - - [sfnt] lowest gcc for vectors (e1d0249e) is changed to 4.7. - - __builtin_shuffle() was introduced in gcc-4.7. The lowest - gcc to enable vector operation is delayed from 4.6 to 4.7. - - * src/sfnt/pngshim.c (premultiply_data): Fix cpp-macro to - enable the vector operation, to change the lowest gcc version - from 4.6 to 4.7. - -2017-09-13 suzuki toshiya - - [cache] Fix a possible overflow by signed integer comparison. - - Improve the code by 5d3ff05615dda6d1325ed612381a17a0df04c975 , - issues are found by Behdad Esfahbod and Werner Lemberg. - - * src/cache/ftcbasic.c (FTC_ImageCache_Lookup): Replace - a subtraction to check higher bit by a bit operation, - and cpp-conditionalize for appropriate systems. Add better - documentation to the comment. - (FTC_ImageCache_LookupScaler): Ditto. - (FTC_SBitCache_Lookup): Ditto. - (FTC_SBitCache_LookupScaler): Ditto. - -2017-09-13 Werner Lemberg - - [autofit] Really fix #41334 (#52000). - - * src/autofit/aflatin.c (af_latin_hints_compute_segments): Set - `segment->delta' everywhere. - -2017-09-12 suzuki toshiya - - [autofit, sfnt] Fix for `make multi'. - - * src/autofit/afshaper.c: Include FT_ADVANCE_H, to use - FT_Get_Advance() in it. - * src/sfnt/ttcmap.c: Include FT_SERVICE_POSTSCRIPT_CMAPS_H - to use PS_Unicodes in it, also include `ttpost.h' to use - tt_face_get_ps_name() in it. - -2017-09-11 Azzuro - - [build] Improve builds with different MS Visual Studio versions. - - * builds/windows/vc2010/freetype.vcxproj: Switch platform toolset - according to the Visual Studio version. - -2017-09-11 Werner Lemberg - - * src/sfnt/ttkern.c (tt_face_load_kern): Reject format 2 tables. - - Reported by Behdad. - -2017-09-09 Werner Lemberg - - [autofit] Improve communication with ftgrid. - - * src/autofit/afhints.c (af_glyph_hints_get_segment_offset): - Provide values in font units. - -2017-09-08 suzuki toshiya - - [base] Remove a check for resource ID in the resource fork driver. - - LastResort.dfont has a marginal resource ID 0xFFFF for sfnt - resource. Inside Macintosh: More Macintosh Toolbox, `Resource IDs' - (1-46), tells that some IDs are reserved and should not be used. - FreeType2 just uses resource ID to sort the fragmented resource. - To accept the marginal fonts, the checking is removed. - - * src/base/ftrfork.c (FT_Raccess_Get_DataOffsets): Remove res_id - validity check, fix a trace message format. - -2017-09-08 suzuki toshiya - - [sfnt, truetype] Register the tags for marginal fonts. - - The first 32bit of standard TrueType variants is 0x00010000, - `OTTO', `ttcf', `true' or `typ1'. 2 marginal dfonts on legacy Mac - OS X, Keyboard.dfont and LastResort.dfont, have the sfnt resources - starting 0xA5 followed by `kbd' or `lst'. Considering the following - data could be parsed as conventional TrueType fonts, the header - checking is updated to allow these tags. It seems that recent Mac - OS X has already switched to normal TTF for these fonts. - - See the discussion at - http://u88.n24.queensu.ca/exiftool/forum/index.php?topic=3931.0 - - * include/freetype/tttags.h (TTAG_0xA5kbd, TTAG_0xA5lst): New header - tags for Keyboard.dfont and LastResort.dfont. - * src/sfnt/sfobjs.c (sfnt_open_font): Accept the sfnt resource - starts with TTAG_0xA5kbd or TTAG_0xA5lst. - * src/truetype/ttobjs.c (tt_face_init): Accept the face with the - format tag is TTAG_0xA5kbd or TTAG_0xA5lst. - -2017-09-05 Werner Lemberg - - Fix multiple calls of `FT_Bitmap_Convert'. - - The documentation of `FT_Bitmap_Convert' says that multiple calls do - proper reallocation of the target FT_Bitmap object. However, this - failed for the sequence - - non-empty bitmap - empty bitmap - non-empty bitmap - - Reason was that `FT_Bitmap_Convert' only reallocated the bitmap - buffer if it became too small; it didn't make the buffer smaller. - For an empty bitmap following a non-empty one, only the buffer - dimension got set to zero, without deallocation. If the next call - was a non-empty buffer again, an assertion in `ft_mem_qrealloc' was - triggered. - - * src/base/ftbitmap.c (FT_Bitmap_Convert): Always reallocate target - buffer to the correct size. - - * docs/CHANGES: Document it. - -2017-09-05 Werner Lemberg - - [bdf] Fix size and resolution handling. - - * src/bdf/bdfdrivr.c (BDF_Face_Init): Use `SIZE' values if - `POINT_SIZE', `RESOLUTION_X', or `RESOLUTION_Y' properties are - missing. - - * docs/CHANGES: Document it. - -2017-08-25 Alexei Podtelezhnikov - - Swap `ALLOC_MULT' arguments (#51833). - - * src/base/ftbitmap.c (ft_bitmap_assure_buffer): Updated. - * src/winfonts/winfnt.c (FNT_Load_Glyph): Updated. - * src/raster/ftrend1.c (ft_raster1_render): Updated. - -2017-08-23 Werner Lemberg - - [sfnt] Fix clang compilation (#51788). - - * src/sfnt/pngshim.c (premultiply_data): Use vectors instead of - scalars. - (vector_shuffle): New macro to take care of a different built-in - function name on clang. - -2017-08-22 Werner Lemberg - - [base] Don't zero out allocated memory twice (#51816). - - Patch applied from bug report. - - * src/base/ftutil.c (ft_mem_qrealloc): Use low-level allocation to - avoid unnecessary overhead. - -2017-08-22 Werner Lemberg - - [truetype] Integer overflow. - - Changes triggered by - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3107 - - * src/truetype/ttinterp.c (Ins_MDRP, Ins_MIRP, Ins_ALIGNPTS): Use - NEG_LONG. - -2017-08-17 Alexei Podtelezhnikov - - [sfnt] Avoid synthetic unicode for symbol fonts with PUA. - - Reported as - - https://bugs.chromium.org/p/chromium/issues/detail?id=754574 - - * src/sfnt/sfobjs.c (sfnt_load_face): Check for FT_ENCODING_MS_SYMBOL. - -2017-08-16 Werner Lemberg - - * src/sfnt/pngshim.c (premultiply_data): Fix compiler warnings. - -2017-08-15 Behdad Esfahbod - - [sfnt] Speed up PNG image loading. - - This reduces the overhead of `premultiply_data' by 60%. - - * src/sfnt/pngshim.c (premultiply_data): Provide code which uses - gcc's (and clang's) `vector_byte' attribute to process 4 pixels at a - time. - -2017-08-11 Werner Lemberg - - [sfnt, truetype] Improve handling of missing sbits. - - Requested by Behdad. - - Modern bitmap-only SFNTs like `NotoColorEmoji.ttf' don't contain - entries in the bitmap strike(s) for empty glyphs. Instead, they - rely that a space glyph gets created from the font's metrics data. - This commit makes FreeType behave accordingly. - - * include/freetype/fterrdef.h (FT_Err_Missing_Bitmap): New error - code. - - * src/sfnt/ttsbit.c (tt_sbit_decoder_load_image): Change error codes - to make a distinction between a missing bitmap in a composite and a - simple missing bitmap. - - * src/truetype/ttgload.c (TT_Load_Glyph): For a missing bitmap (in a - bitmap-only font), synthesize an empty bitmap glyph if metrics are - available. - -2017-08-10 Werner Lemberg - - [base] Minor API improvement for default variation axis setting. - - * src/base/ftmm.c (FT_Set_MM_Design_Coordinates, - FT_Set_Var_Design_Coordinates, FT_Set_MM_Blend_Coordinates, - FT_Set_Var_Blend_Coordinates): Allow coords==NULL if num_coords==0. - - * docs/CHANGES: Updated. - -2017-08-08 Werner Lemberg - - [psnames] Really fix issue #49949. - - We now use a separate preprocessor macro to handle both definition - and declaration of the glyph name arrays. - - * src/psnames/psmodule.c (DEFINE_PS_TABLE_DATA): New macro. - - * src/tools/glnames.py (StringTable::dump, - StringTable::dump_sublist): Use `DEFINE_PS_TABLE_DATA'. - (dump_encoding): Ditto. - (main): Use `wb' mode for writing the output file, which works on - Windows also. - - * src/psnames/pstables.h: Regenerated. - -2017-08-08 Alexei Podtelezhnikov - - [smooth] Harmony LCD rendering. - - This is a new technology for LCD-optimized rendering. It capitalizes - on the fact that each color channel grid is shifted by a third of a - pixel. Therefore it is logical to render 3 separate monochrome - bitmaps shifting the outline by 1/3 pixel, and then combine them. - Importantly, the resulting output does not require additional LCD - filtering. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic) - [!FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Implement new LCD-optimized - rendering. - - * include/freetype/ftlcdfil.h, include/freetype/freetype.h, - include/freetype/config/ftoption.h, devel/ftoption.h: Updated - documentation. - -2017-08-08 Alexei Podtelezhnikov - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Clean up. - -2017-08-08 Alexei Podtelezhnikov - - * src/sfnt/ttpost.c (format): Use otspec-compliant versions. - -2017-08-05 Werner Lemberg - - [truetype] Integer overflow. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2868 - - * src/truetype/ttinterp.c (Ins_ALIGNRP): Use NEG_LONG. - -2017-08-05 Werner Lemberg - - [base, truetype] New function `FT_Get_Var_Axis_Flags'. - - The reserved `flags' field got a value in OpenType version 1.8.2; - unfortunately, the public `FT_Var_Axis' structure misses the - corresponding element. Since we can't add a new field, we add an - access function. - - * src/base/ftmm.c (FT_Get_Var_Axis_Flags): New function. - - * include/freetype/ftmm.h (FT_VAR_AXIS_FLAG_HIDDEN): New macro. - Updated. - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Increase allocated memory - of `mmvar' to hold axis flags. - Fill the axis flags array. - - * docs/CHANGES: Updated. - -2017-08-03 Nikolaus Waxweiler - - [truetype] Fix metrics of B/W hinting in v40 mode. - - Phantom points are now saved outside v40 backwards compatibility - mode. This fixes the jumping glyphs when switching between v35 and - v40 monochrome mode. - - * src/truetype/ttgload.c (TT_Hint_Glyph): Fix inversed bool logic. - -2017-08-03 Nikolaus Waxweiler - - [truetype] Do not set any ClearType flags in v40 monochrome mode. - - This fixes weird behavior of instructions that resulted in rendering - differences between v35 and v40 in monochrome mode, e.g., in - `timesbi.ttf'. - - * src/truetype/ttinterp.c (Ins_GETINFO) - [TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL]: Check - `subpixel_hinting_lean'. - -2017-08-01 Werner Lemberg - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Fix thinko. - -2017-08-01 Behdad Esfahbod - - [truetype] Fix loading of named instances. - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Preserve file position - while loading the `avar' table. - -2017-08-01 Werner Lemberg - - [sfnt, truetype] Minor adjustments for OpenType 1.8.2. - - * src/sfnt/sfobjs.c (sfnt_load_face): The units per EM value has now - (tighter) limits. - - * src/truetype/ttgload.c (load_truetype_glyph): The new OpenType - version explicitly allows all negative values for the number of - contours if we have a composite glyph (this is for better backwards - compatibility I guess), but it still recommends value -1. - -2017-07-26 Werner Lemberg - - [cff] Integer overflow. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2738 - - * src/cff/cf2hints.c (cf2_glyphpath_computeOffset, - cf2_glyphpath_curveTo): Use ADD_INT32. - -2017-07-13 Werner Lemberg - - [base] Fix memory leak. - - Reported as - - https://bugs.chromium.org/p/chromium/issues/detail?id=738362 - - * src/base/ftglyph.c (FT_Get_Glyph): Do proper deallocation in case - of error. - -2017-07-12 Werner Lemberg - - [base] Integer overflow. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2573 - - * src/base/ftobjs.c (ft_glyphslot_grid_fit_metrics): Use - FT_PIX_CEIL_LONG and FT_PIX_ROUND_LONG. - -2017-07-12 Werner Lemberg - - * src/truetype/ttpload.c (tt_face_get_location): Off-by-one typo. - - Also improve tracing message. - - Problem reported as - - https://bugs.chromium.org/p/chromium/issues/detail?id=738919 - -2017-07-07 Werner Lemberg - - [cff] Integer overflow. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2517 - - * src/cff/cf2blues.c (cf2_blues_capture): Use SUB_INT32. - -2017-07-05 Werner Lemberg - - * src/sfnt/ttcmap.c (tt_cmap_unicode_class_rec): Fix warning. - -2017-07-05 Werner Lemberg - - * src/truetype/ttgxvar.c (FT_Stream_SeekSet): Fix warning (#51395). - -2017-07-04 Werner Lemberg - - [truetype] Prevent address overflow (#51365). - - * src/truetype/ttgxvar.c (FT_Stream_SeekSet): Add guard. - -2017-07-03 Alexei Podtelezhnikov - - * src/base/ftlcdfil.c (ft_lcd_filter_fir): Improve code. - -2017-07-03 Werner Lemberg - - [truetype] Integer overflow. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2455 - - * src/truetype/ttinterp.c (Ins_SCFS): Use SUB_LONG. - -2017-07-01 Alexei Podtelezhnikov - - * src/sfnt/sfobjs.c (sfnt_load_face): Ignore No_Unicode_Glyph_Name. - -2017-06-28 Ben Wagner - - Avoid Microsoft compiler warnings (#51331). - - While clang's sanitizer recommends a cast to unsigned for safe - negation (to handle -INT_MIN), both MSVC and Visualc emit warning - C4146 if an unsigned value gets negated. - - * include/freetype/internal/ftcalc.h (NEG_LONG, NEG_INT32), - src/base/ftcalc.c (FT_MOVE_SIGN): Replace negation with a - subtraction. - -2017-06-27 Werner Lemberg - - * src/cff/cffparse.c (do_fixed): Fix typo. - - Spotted by chris . - -2017-06-27 Werner Lemberg - - [truetype] Integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2384 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2391 - - * src/base/ftcalc.c (FT_MulDiv, FT_MulDiv_No_Round, FT_DivFix): Use - NEG_LONG. - - * src/truetype/ttinterp.c (Ins_SxVTL): Use NEG_LONG. - -2017-06-24 Werner Lemberg - - [truetype] Integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2364 - - * src/truetype/ttinterp.c (Ins_ISECT): Use NEG_LONG. - -2017-06-22 Werner Lemberg - - [cff, truetype] Integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2323 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2328 - - * src/cff/cf2blues.c (cf2_blues_capture): Use ADD_INT32 and - SUB_INT32. - - * src/truetype/ttinterp.c (Ins_SDPVTL): Use SUB_LONG and NEG_LONG. - -2017-06-21 Alexei Podtelezhnikov - - [sfnt] Synthesize a Unicode charmap if one is missing. - - * src/sfnt/ttcmap.h (tt_cmap_unicode_class_rec): Declare it. - * src/sfnt/ttcmap.c (tt_get_glyph_name, tt_cmap_unicode_init, - tt_cmap_unicode_done, tt_cmap_unicode_char_index, - tt_cmap_unicode_char_next, tt_cmap_unicode_class_rec): Implement - synthetic Unicode charmap class. - (tt_get_cmap_info): Make sure the callback is available. - - * src/sfnt/sfobjs.c (sfnt_load_face) - [FT_CONFIG_OPTION_POSTSCRIPT_NAMES]: If Unicode charmap is missing, - synthesize one. - - * include/freetype/config/ftoption.h: Document it. - * devel/ftoption.h: Ditto. - -2017-06-20 Tony Theodore - - Fix pkg-config in freetype-config for cross-compiling (#51274). - - * builds/unix/unix-def.in (PKG_CONFIG): New variable. - (freetype-config): Use it in sed expression. - - * builds/unix/freetype-config.in: s/pkg-config/%PKG_CONFIG%/. - -2017-06-20 Werner Lemberg - - [cff, truetype] Integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2300 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2313 - - * src/cff/cf2hints.c (cf2_hintmap_adjustHints): Use ADD_INT32. - - * src/truetype/ttinterp.c (Ins_ABS): Avoid FT_ABS. - -2017-06-17 Alexei Podtelezhnikov - - [base, smooth] LCD filtering cleanups. - - * src/base/ftlcdfil.c (ft_lcd_filter_fir, _ft_lcd_filter_legacy): - Clean up, start filtering from the bottom-left origin. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Updated. - -2017-06-16 Werner Lemberg - - [truetype] Integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2270 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2276 - - * src/truetype/ttinterp.c (Ins_MDRP, _iup_worker_interpolate): Use - ADD_LONG and SUB_LONG. - -2017-06-15 Werner Lemberg - - [bdf, cff] Integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2244 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2261 - - * src/bdf/bdfdrivr.c (BDF_Face_Init): Replace calls to FT_ABS with - direct code to avoid value negation. - - * src/cff/cf2blues.c (cf2_blues_capture): Use SUB_INT32 and - ADD_INT32. - -2017-06-13 Werner Lemberg - - * src/winfonts/winfnt.c (FNT_Face_Init): Don't set active encoding. - - FreeType only sets a default active encoding for Unicode. - -2017-06-13 Werner Lemberg - - [cff, truetype] Integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2216 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2218 - - * src/cff/cf2fixed.h (cf2_fixedAbs): Use NEG_INT32. - - * src/truetype/ttinterp.c (Ins_IP): Use SUB_LONG. - -2017-06-11 Werner Lemberg - - [cff] Integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2200 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2210 - - * src/cff/cf2hints.c (cf2_hintmap_insertHint): Use SUB_INT32 and - ADD_INT32. - - * src/cff/cf2intrp.c (cf2_interpT2CharString) : Use - ADD_INT32. - -2017-06-10 Werner Lemberg - - [truetype] Fix TT_Set_Var_Design. - - Reported by Nikolaus Waxweiler . - - * src/truetype/ttgxvar.c (TT_Set_Var_Design): Correctly handle the - case where we have less input coordinates than axes. - -2017-06-10 Werner Lemberg - - * src/base/ftcalc.c (FT_DivFix): Fix embarrassing typo. - - Bug introduced 2017-05-28. - -2017-06-09 Werner Lemberg - - [cff, truetype] Integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2144 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2151 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2153 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2173 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2186 - - * src/cff/cf2blues.c (cf2_blues_init): Use SUB_INT32. - - * src/truetype/ttinterp.c (Round_None, Round_To_Grid, - Round_To_Half_Grid, Round_Down_To_Grid, Round_Up_To_Grid, - Round_To_Double_Grid, Round_Super, Round_Super_45): Use ADD_LONG, - SUB_LONG, NEG_LONG, FT_PIX_ROUND_LONG, FT_PIX_CEIL_LONG, - FT_PAD_ROUND_LONG - (Ins_SxVTL, Ins_MIRP): Use SUB_LONG. - (_iup_worker_shift): Use SUB_LONG and ADD_LONG. - -2017-06-09 Werner Lemberg - - Provide more macros for flooring, ceiling, and rounding. - - These versions don't produce run-time errors due to integer - overflow. - - * include/freetype/internal/ftobjs.h: Include FT_INTERNAL_CALC_H. - (FT_PAD_ROUND_LONG, FT_PAD_CEIL_LONG, FT_PIX_ROUND_LONG, - FT_PIX_CEIL_LONG): New macros. - (FT_PAD_ROUND_INT32, FT_PAD_CEIL_INT32, FT_PIX_ROUND_INT32, - FT_PIX_CEIL_INT32): New macros. - -2017-06-09 Werner Lemberg - - Remove unused macros. - - * include/freetype/internal/ftcalc.h (ADD_INT, SUB_INT, MUL_INT, - NEG_INT): Deleted. - -2017-06-09 Werner Lemberg - - */*: Remove `OVERFLOW_' prefix. - - This increases readability. - -2017-06-07 Werner Lemberg - - [cff, truetype] Integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2133 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2137 - - * src/cff/cf2hints.c (cf2_hint_init): Use OVERFLOW_SUB_INT32. - - * src/truetype/ttinterp.c (PROJECT, DUALPROJ): Use - OVERFLOW_SUB_LONG. - -2017-06-06 Werner Lemberg - - [cff] Integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2109 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2110 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2122 - - * src/cff/cf2blues.c (cf2_blues_init): Use OVERFLOW_SUB_INT32. - - * src/cff/cf2hints.c (cf2_hintmap_map): Synchronize if-else - branches. - -2017-06-05 Werner Lemberg - - [cff] Integer overflow. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2089 - - * src/cff/cffload.c (cff_blend_doBlend): User OVERFLOW_ADD_INT32. - -2017-06-04 Werner Lemberg - - [cff, truetype] Integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2075 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2088 - - * src/cff/cf2font.c (cf2_font_setup): Use OVERFLOW_MUL_INT32. - - * src/truetype/ttinterp.c (Ins_ISECT): Use OVERFLOW_MUL_LONG, - OVERFLOW_ADD_LONG, and OVERFLOW_SUB_LONG. - -2017-06-03 Werner Lemberg - - [base, cff, truetype] Integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2060 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2062 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2063 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2068 - - * src/base/ftobjs.c (ft_glyphslot_grid_fit_metrics): Use - OVERFLOW_ADD_LONG and OVERFLOW_SUB_LONG. - - * src/cff/cf2blues.c (cf2_blues_capture), src/cff/cf2hints.c - (cf2_hintmap_adjustHints): Use OVERFLOW_SUB_INT32. - - * src/truetype/ttgload.c (compute_glyph_metrics): User - OVERFLOW_SUB_LONG. - - * src/truetype/ttinterp.c (Direct_Move, Direct_Move_Orig, - Direct_Move_X, Direct_Move_Y, Direct_Move_Orig_X, - Direct_Move_Orig_Y, Move_Zp2_Point, Ins_MSIRP): Use - OVERFLOW_ADD_LONG and OVERFLOW_SUB_LONG. - -2017-06-03 Werner Lemberg - - * builds/unix/freetype-config.in: Fix pkg-config test (#51162). - - Patch directly taken from bug report. - -2017-06-03 Werner Lemberg - - [bdf] Synchronize sanity checks with pcf driver. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2054 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2058 - - * src/bdf/bdfdrivr.c (BDF_Face_Init): Check font ascent and descent. - Check AVERAGE_WIDTH, POINT_SIZE, PIXEL_SIZE, RESOLUTION_X, and - RESOLUTION_Y properties. - -2017-06-03 Werner Lemberg - - [cff, truetype] Integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2047 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2057 - - * src/cff/cf2hints.c (cf2_hintmap_map): Use OVERFLOW_SUB_INT32. - - * src/truetype/ttinterp.c (Ins_ADD): Use OVERFLOW_ADD_LONG. - (Ins_SUB): Use OVERFLOW_SUB_LONG. - (Ins_NEG): Use NEG_LONG. - -2017-06-03 Werner Lemberg - - ftcalc.h: Avoid left-shift of negative numbers. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2055 - - * include/freetype/internal/ftcalc.h (INT_TO_F26DOT6, - INT_TO_F2DOT14, INT_TO_FIXED, F2DOT14_TO_FIXED): Use multiplication. - -2017-06-02 Werner Lemberg - - [cff] Even more integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2046 - - * src/cff/cf2intrp.c (cf2_doStems, cf2_interpT2CharString): Use - OVERFLOW_ADD_INT32. - -2017-06-02 Werner Lemberg - - [cff] More integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2032 - - * src/cff/cf2blues.c (cf2_blues_init): Use OVERFLOW_SUB_INT32. - -2017-06-02 Werner Lemberg - - [bdf] Don't left-shift negative numbers. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2031 - - * src/bdf/bdfdrivr.c (BDF_Face_Init): Use multiplication. - -2017-06-02 Werner Lemberg - - [bdf] Fix integer scanning routines. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2029 - - * src/bdf/bdflib.c (_bdf_atoul, _bdf_atol, _bdf_atous, _bdf_atos): - Stop scanning if result would overflow. - -2017-06-02 Werner Lemberg - - [cff] Fix integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2027 - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2028 - - * src/cff/cf2hints.c (cf2_hintmap_insertHint), src/cff/cf2intrp.c - (cf2_doFlex): Use OVERFLOW_ADD_INT32 and OVERFLOW_SUB_INT32. - -2017-06-01 Werner Lemberg - - [smooth] Some 32bit integer overflow run-time errors. - - * src/smooth/ftgrays.c [STANDALONE] (OVERFLOW_ADD_LONG, - OVERFLOW_SUB_LONG, OVERFLOW_MUL_LONG, NEG_LONG): New macros. - [!STANDALONE]: Include FT_INTERNAL_CALC_H. - (gray_render_cubic): Use those macros where appropriate. - -2017-06-01 Werner Lemberg - - * src/base/ftglyph.c (FT_Get_Glyph): Check `slot->advance'. - -2017-06-01 Werner Lemberg - - [psaux] 32bit integer overflow tun-time errors (#46149). - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings): Use - OVERFLOW_ADD_LONG and OVERFLOW_SUB_LONG where appropriate. - -2017-06-01 Werner Lemberg - - * src/truetype/ttinterp.c (TT_RunIns): Adjust loop counter again. - - Problem reported by Marek Kašík . - - The problematic font that exceeds the old limit is Padauk-Bold, - version 3.002, containing bytecode generated by a buggy version of - ttfautohint. - -2017-05-31 Werner Lemberg - - [cff] 32bit integer overflow run-time errors 2/2 (#46149). - - This commit handles the new engine. - - * include/freetype/internal/ftcalc.h (OVERFLOW_ADD_INT32, - OVERFLOW_SUB_INT32, OVERFLOW_MUL_INT32, NEG_INT, NEG_LONG, - NEG_INT32): New macros. - - * src/cff/cf2ft.c (cf2_getScaleAndHintFlag): Use OVERFLOW_ADD_INT32. - - * src/cff/cf2hints.c (cf2_getWindingMomentum, cf2_hint_init, - cf2_hintmap_map, cf2_glyphpath_hintPoint, - cf2_glyphpath_computeIntersection, cf2_glyphpath_computeOffset, - cf2_glyphpath_lineTo, cf2_glyphpath_curveTo): Use - OVERFLOW_ADD_INT32, OVERFLOW_SUB_INT32, OVERFLOW_MUL_INT32, and - NEG_INT32 where appropriate. - - * src/cff/cf2intrp.c (cf2_doFlex, cf2_doBlend, - cf2_interpT2CharString): Ditto. - Also add some other code where needed to avoid overflow. - -2017-05-30 Werner Lemberg - - [cff] 32bit integer overflow run-time errors 1/2 (#46149). - - This commit handles the old engine. - - * src/cff/cffgload.c: Include FT_INTERNAL_CALC_H. - (cff_decoder_parse_charstrings): Use OVERFLOW_ADD_LONG and - OVERFLOW_SUB_LONG where needed. - - * src/cff/cffparse.c: Include FT_INTERNAL_CALC_H. - (power_ten_limits): New static array. - (do_fixed): Use it to prevent multiplication overflow. - (cff_parser_run): Use OVERFLOW_ADD_LONG. - -2017-05-30 Werner Lemberg - - [psaux] Correctly handle sequences of multiple number signs. - - * src/psaux/psconv.c (PS_Conv_Strtol, PS_Conv_ToFixed): Return zero - if we encounter more than a single sign. - -2017-05-29 Werner Lemberg - - [pcf] 32bit integer overflow run-time errors (#46149). - - * src/pcf/pcfread.c (pcf_get_accel): Add sanity checks for - `fontAscent' and `fontDescent'. - (pcf_load_font): Add sanity checks for global height. - Add sanity checks for AVERAGE_WIDTH, POINT_SIZE, PIXEL_SIZE, - RESOLUTION_X, and RESOLUTION_Y properties. - -2017-05-29 Werner Lemberg - - Handle some integer overflow run-time errors (#46149, #48979). - - This commit (mainly for 32bit CPUs) is the first of a series of - similar commits to handle known integer overflows. Basically, all - of them are harmless, since they affect rendering of glyphs only, - not posing security threats. It is expected that fuzzying will show - up more overflows, to be fixed in due course. - - The idea is to mark places where overflows can occur, using macros - that simply cast to unsigned integers, because overflow arithmetic - is well defined in this case. Doing so suppresses run-time errors - of sanitizers without adding computational overhead. - - * include/freetype/internal/ftcalc.h (OVERFLOW_ADD_INT, - OVERFLOW_SUB_INT, OVERFLOW_MUL_INT, OVERFLOW_ADD_LONG, - OVERFLOW_SUB_LONG, OVERFLOW_MUL_LONG): New macros. - - * src/base/ftcalc.c (FT_RoundFix, FT_CeilFix, FT_Matrix_Multiply, - FT_Matrix_Multiply_Scaled, FT_Vector_Transform_Scaled, - ft_corner_orientation): Use new macros. - - * src/base/ftoutln.c (FT_Outline_Get_Orientation): Use new macros. - -2017-05-28 Werner Lemberg - - * include/freetype/internal/ftcalc.h (FLOAT_TO_FIXED): Remove. - - This macro is not used. - -2017-05-28 Werner Lemberg - - [cff] s/cf2_floatToFixed/cf2_doubleToFixed/. - - The new name better describes what the macro actually does; - additionally, we don't need a trailing `f' for literals (there was - only a single such instance in the code, but this caused a clang - warning because the macro itself uses `double' literals). - - * src/cff/cf2blues.c, src/cff/cf2blues.h, src/cff/cf2fixed.h, - src/cff/cf2font.c, src/cff/cf2hints.c: Updated. - -2017-05-28 Werner Lemberg - - Fix negation of INT_MIN and LONG_MIN (#46149). - - * src/base/ftcalc.c (FT_MOVE_SIGN): Add argument to pass unsigned - value, to be used as the result. - (FT_MulDiv, FT_MulDiv_No_Round, FT_DivFix, FT_MulFix, - FT_Vector_NormLen): Updated. - -2017-05-27 Werner Lemberg - - [truetype] Fix handling of design coordinates (#51127). - - * src/truetype/ttgxvar.c (tt_set_mm_blend): Compute all design - coordinates if we have to create the `blends->coord' array. - (TT_Get_MM_Blend, TT_Get_Var_Design): Select default instance - coordinates if no instance is selected yet. - -2017-05-24 Werner Lemberg - - [bdf, pcf] Support ISO646.1991-IRV character encoding (aka ASCII). - - Problem reported by Marek Kašík , cf. - - https://bugzilla.redhat.com/show_bug.cgi?id=1451795 - - * src/bdf/bdfdrivr.c (BDF_Face_Init), src/pcf/pcfdrivr.c - (PCF_Face_Init): Implement it. - -2017-05-20 Nikolaus Waxweiler - - [truetype] Always use interpreter v35 for B/W rendering (#51051). - - * src/truetype/ttgload.c (tt_loader_init) - [TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL]: Adjust - `subpixel_hinting_lean', `grayscale_cleartype', and - `vertical_lcd_lean' accordingly. - - * src/truetype/ttinterp.c (Ins_GETINFO): Updated. - (TT_RunIns): Update `backward_compatibility' flag. - -2017-05-20 Alexei Podtelezhnikov - - [smooth] Implement minimal dynamic padding for LCD filtering. - - Extra bitmap padding for LCD filtering depends on the filter. The - default 5-tap filter needs 2 extra subpixels. The light 3-tap filter - needs only 1 extra subpixel. This space could be already available - due to rounding. In order to optimize the padding, we now expand - CBox for the given filter weights before rounding. - - This change breaks current Skia (and Firefox). - - * include/freetype/internal/ftobjs.h (FT_LibraryRec) - [FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Remove `lcd_extra' field. - - * src/base/ftlcdfil.c (FT_Library_SetLcdFilterWeights, - FT_Library_SetLcdFilter): Remove `lcd_extra' initializations. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Implement dymanic - LCD padding. - -2017-05-15 Werner Lemberg - - [sfnt] Return proper scaling values for SBIX bitmaps. - - Problem reported by Hin-Tak Leung . - - * src/sfnt/ttsbit.c (tt_face_load_strike_metrics): Implement it. - -2017-05-15 Werner Lemberg - - [truetype] Fix error handling for embedded bitmaps. - - Problem reported by Hin-Tak Leung . - - * src/truetype/ttgload.c (TT_Load_Glyph) - [TT_CONFIG_OPTION_EMBEDDED_BITMAPS]: Handle error if font is not - scalable. - -2017-05-15 Alexei Podtelezhnikov - - [autofit] Make autohint warping NORMAL option. - - This moves warping option from LIGHT to NORMAL mode. This makes LIGHT - truly void of hinting in x-direction, with left side bearing never - changed and right side bearing only altered by advance rounding. - Therefore, LIGHT is now ready to return fractional advance. As a - NORMAL option, warping substitutes normal hinting. - - * src/autofit/afcjk.c (af_cjk_hints_apply): Updated. - * src/autofit/aflatin.c (af_latin_hints_apply): Updated. - * src/autofit/aflatin2.c (af_latin2_hints_apply): Updated. - - * src/autofit/afloader.c (af_loader_load_glyph): Handle warping - phantom points as normal. - -2017-05-14 Werner Lemberg - - Remove remnants of raster pool. - - * include/freetype/internal/ftobjs.h (FT_LibraryRec): Remove - `raster_pool' and `raster_pool_size' fields. - - * src/base/ftobjs.c (FT_New_Library), src/raster/ftrend1.c - (ft_raster1_init), src/smooth/ftsmooth.c (ft_smooth_init): Updated. - -2017-05-13 Werner Lemberg - - * Version 2.8 released. - ======================= - - - Tag sources with `VER-2-8'. - - * docs/VERSION.TXT: Add entry for version 2.8. - * docs/CHANGES: Updated. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.7.1/2.8/, s/271/28/. - - * include/freetype/freetype.h (FREETYPE_MINOR): Set to 8. - (FREETYPE_PATCH): Set to 0. - - * builds/unix/configure.raw (version_info): Set to 20:0:14. - * CMakeLists.txt (VERSION_MINOR): Set to 8. - (VERSION_PATCH): Set to 0. - -2017-05-12 Hin-Tak Leung - - Fix `FT_UINT_TO_POINTER' macro for Windows. - - * builds/unix/ftconfig.in, builds/vms/ftconfig.h, - include/freetype/config/ftconfig.h (FT_UINT_TO_POINTER) [_WIN64]: - Fix definition. - -2017-05-11 Sascha Brawer - Werner Lemberg - Werner Lemberg - Werner Lemberg - Werner Lemberg - Werner Lemberg - Werner Lemberg - Werner Lemberg - Werner Lemberg - Werner Lemberg - Werner Lemberg - - [truetype] Add tricky font `DFGirl-W6-WIN-BF' (from Dynalab). - - Reported by Roy Tam . - - * src/truetype/ttobjs.c (tt_check_trickyness_family): Implement it. - -2017-05-07 Roy Tam - Werner Lemberg - - [truetype] More tricky fonts (mainly from Dynalab). - - * src/truetype/ttobjs.c (tt_check_trickyness_family, - tt_check_trickyness_sfnt_ids): Add them. - -2017-05-07 Werner Lemberg - - [truetype] Add tricky font `DLCHayMedium' (from Dynalab). - - Reported by Roy Tam . - - * src/truetype/ttobjs.c (tt_check_trickyness_family): Implement it. - -2017-05-03 Werner Lemberg - - */*: s/backwards compatibility/backward compatibility/. - -2017-05-03 Sascha Brawer - Werner Lemberg - Werner Lemberg - - [autofit] Add blue-zone support for Sundanese script. - - This essentially moves the Sundanese script from the `Indic' hinter - to the `Latin' hinter. - - * src/autofit/afblue.dat: Add blue zone data for Sundanese. - - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Sundanese standard character and move - data out of AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afranges.c: Move Sundanese data out of - AF_CONFIG_OPTION_INDIC block. - - * src/autofit/afstyles.h: Update Sundanese data; in particular, use - AF_WRITING_SYSTEM_LATIN. - -2017-05-03 Sascha Brawer - Werner Lemberg - - [truetype] Make `IUP' gvar deltas do the same as Apple (#50832). - - When points are not touched by gvar interpolation deltas, FreeType - gave a slightly different result than Apple's CoreText. - - The OpenType working group will update the specification to document - the following behaviour: If the two points with deltas to the `left' - and `right' of the untouched point have the same coordinate, then - the inferred delta for the untouched point should be zero. - - * src/truetype/ttgxvar.c (tt_delta_interpolate): Implement new - behaviour. - -2017-05-02 Werner Lemberg - - [autofit] Remove `slight' auto-hint mode again. - - A poll on freetype-devel favoured changes directly applied to - `light'. - - * include/freetype/freetype.h (FT_LOAD_TARGET_SLIGHT, - FT_RENDER_MODE_SLIGHT): Removed. - - * src/autofit/afcjk.c (af_cjk_hints_init), src/autofit/aflatin.c - (af_latin_hints_init), src/autofit/aflatin2.c - (af_latin2_hints_init): Revert change from 2017-04-22. - - * src/autofit/afloader.c (af_loader_load_glyph) Remove references to - FT_RENDER_MODE_SLIGHT. - [AF_CONFIG_OPTION_TT_SIZE_METRICS]: Enable TrueType-like metrics - unconditionally. - - * src/base/ftadvanc.c (LOAD_ADVANCE_FAST_CHECK): Revert change from - 2017-04-22. - - * src/base/ftobjs.c (FT_Load_Glyph): Revert change from 2017-04-22. - - * src/pshinter/pshalgo.c (ps_hints_apply): Revert change from - 2017-04-22. - - * src/smooth/ftsmooth.c (ft_smooth_render): Revert change from - 2017-04-22. - - * docs/CHANGES: Updated. - -2017-04-30 Werner Lemberg - - [autofit] Fix metrics computation. - - Problem reported by Markus Trippelsdorf and - Nikolaus Waxweiler . - - * src/base/ftobjs.c (FT_Request_Size): Trigger recomputation of - auto-hinter metrics. Without this change, multiple size changing - calls for a single face fail. - -2017-04-29 Werner Lemberg - - * src/truetype/ttdriver.c (tt_size_request): Properly check `error'. - - Reported by Earnestly in - - https://lists.nongnu.org/archive/html/freetype/2017-04/msg00031.html - -2017-04-27 Werner Lemberg - - Introduce AF_CONFIG_OPTION_TT_SIZE_METRICS configuration option. - - * include/freetype/config/ftoption.h - (AF_CONFIG_OPTION_TT_SIZE_METRICS): New option, commented out by - default. - - * src/autofit/afloader.c (af_loader_load_glyph): Use - AF_CONFIG_OPTION_TT_SIZE_METRICS to guard the corresponding code. - -2017-04-26 Werner Lemberg - - * include/freetype/freetype.h (FT_Render_Mode): Fix order. - - This retains backward compatibility. - - Noted by Alexei. - -2017-04-22 Werner Lemberg - - [truetype] Do linear scaling for FT_LOAD_NO_HINTING (#50470). - - * src/truetype/ttobjs.h (TT_SizeRec): Add field `hinted_metrics' to - hold hinted metrics. - Make `metrics' a pointer so that `tt_glyph_load' can easily switch - between metrics. - - * src/truetype/ttdriver.c (tt_size_request): Updated. - (tt_glyph_load): Use top-level metrics if FT_LOAD_NO_HINTING is - used. - - * src/truetype/ttgload.c (TT_Hint_Glyph, TT_Process_Simple_Glyph, - TT_Process_Composite_Component, load_truetype_glyph, - compute_glyph_metrics, TT_Load_Glyph): Updated. - - * src/truetype/ttinterp.c (TT_Load_Context): Updated. - - * src/truetype/ttobjs.c (tt_size_reset): Updated. - - * src/truetype/ttsubpix.c (sph_set_tweaks): Updated. - -2017-04-22 Werner Lemberg - - Add new `slight' auto-hinting mode. - - This mode uses fractional advance widths and doesn't scale glyphs - horizontally, only applying vertical scaling and hinting. - - At the same time, the behaviour of the `light' auto-hinter gets - restored for backward compatibility: Both vertical and horizontal - scaling is again based on rounded metrics values (this was changed - in a commit from 2017-03-30 as a side effect). To be more precise, - the behaviour is restored for TrueType fonts only; for other font - formats like Type 1, this is a new feature of the `light' hinting - mode. - - * include/freetype/freetype.h (FT_LOAD_TARGET_SLIGHT): New macro. - (FT_RENDER_MODE_SLIGHT): New render mode. - - * include/freetype/internal/ftobjs.h (FT_Size_InternalRec): Add - `autohint_mode' and `autohint_metrics' fields. - - * src/autofit/afcjk.c (af_cjk_hints_init), src/autofit/aflatin.c - (af_latin_hints_init), src/autofit/aflatin2 (af_latin2_hints_init): - Updated. - - * src/autofit/afloader.c (af_loader_embolden_glyph_in_slot): Use - `autohint_metrics'. - (af_loader_load_glyph): s/internal/slot_internal/. - Initialize `autohint_metrics' and `autohint_mode' depending on - current auto-hint mode. - Use `autohint_metrics'. - Updated. - - * src/base/ftadvanc.c (LOAD_ADVANCE_FAST_CHECK): Updated. - - * src/base/ftobjs.c (FT_Load_Glyph): Updated. - (FT_New_Size): Allocate `internal' object. - - * src/pshinter/pshalgo.c (ps_hints_apply): Updated. - - * src/smooth/ftsmooth.c (ft_smooth_render): Updated. - -2017-04-22 Werner Lemberg - - Introduce `FT_Size_InternalRec' structure. - - We are going to extend this later on. - - * include/freetype/internal/ftobjs.h (FT_Size_InternalRec): New - structure with a single field `module_data'. - - * src/base/ftobjs.c (FT_New_Size): Allocate `internal' field of - `FT_Size' structure. - - * src/cff/cffgload.c (cff_builder_init, cff_decoder_prepare): Use - `size->internal->module_data' instead of `size->internal'. - - * src/cff/cffobjs.c (cff_size_done): Deallocate `module_data'. - (cff_size_init, cff_size_select, cff_size_request): Use - `size->internal->module_data' instead of `size->internal'. - - * src/cif/cidobjs.c (cid_size_done, cid_size_init, - cid_size_request): Use `size->internal->module_data' instead of - `size->internal'. - - * src/psaux/psobjs.c (t1_builder_ini): Use - `size->internal->module_data' instead of `size->internal'. - - * src/type1/t1objs.c (T1_Size_Done, T1_Size_Init, T1_Size_Request): - Use `size->internal->module_data' instead of `size->internal'. - -2017-04-21 Alexei Podtelezhnikov - - * src/smooth/ftsmooth.h: Remove unused guards and declaration. - -2017-04-16 Hin-Tak Leung - - Fix tracing messages. - - * src/base/ftobjs.c (FT_Face_GetCharVariantIndex, - FT_Face_GetCharVariantIsDefault, FT_Face_GetVariantsOfChar): Print - correct function name. - -2017-04-08 Sascha Brawer - Werner Lemberg - Werner Lemberg - Werner Lemberg - Werner Lemberg - - [autofit] Fix invalid character range description (#50745). - - Also reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1034 - - * src/autofit/afranges.c (af_glag_nonbase_uniranges): Fix typo in - recent commit. - -2017-04-07 Werner Lemberg - - [ftfuzzer] Fix clang warnings. - - * src/tools/ftfuzzer/ftfuzzer.cc (LLVMFuzzerTestOneInput): Add - casts. - -2017-04-06 Sascha Brawer - Werner Lemberg - Werner Lemberg - Werner Lemberg - Werner Lemberg - Werner Lemberg - Werner Lemberg - - [autofit] Add support for Adlam script. - - * src/autofit/afblue.dat: Add blue zone data for Adlam. - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Adlam standard characters. - - * src/autofit/afranges.c, src/autofit/afstyles.h: Add Adlam data. - -2017-04-06 Sascha Brawer - - [autofit] Add support for Ol Chiki script. - - * src/autofit/afblue.dat: Add blue zone data for Ol Chiki. - * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. - - * src/autofit/afscript.h: Add Ol Chiki standard character. - - * src/autofit/afranges.c, src/autofit/afstyles.h: Add Ol Chiki data. - -2017-04-03 Werner Lemberg - - [truetype] Avoid reexecution of `fpgm' and `prep' in case of error. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=981 - - * include/freetype/fterrdef.h (FT_Err_DEF_In_Glyf_Bytecode): New - error code. - - * src/truetype/ttinterp.c (Ins_FDEF, Ins_IDEF): Prohibit execution - of these two opcodes in `glyf' bytecode. - (TT_RunIns): Don't enforce reexecution of `fpgm' and `prep' bytecode - in case of error since function tables can no longer be modified - (due to the changes in `Ins_FDEF' and `Ins_IDEF'). This change can - enormously speed up handling of broken fonts. - -2017-04-02 Alexei Podtelezhnikov - - [autofit] Disable metrics adjustment for `FT_LOAD_TARGET_LCD'. - - * src/autofit/aflatin.c (af_latin_hints_init): Updated. - * src/autofit/aflatin2.c (af_latin2_hints_init): Ditto. - -2017-04-01 Werner Lemberg - - * src/truetype/ttgload.c: Include FT_CONFIG_CONFIG_H. - - Otherwise FT_UINT_TO_POINTER might not be defined. - - Problem reported by Alexei. - -2017-03-31 Alexei Podtelezhnikov - - [autofit] Disable stem adjustment for `FT_LOAD_TARGET_LCD'. - - * include/freetype/freetype.h (FT_LOAD_TARGET_LCD): Document it. - * src/autofit/afcjk.c (af_cjk_hints_init): Updated. - * src/autofit/aflatin.c (af_latin_hints_init): Ditto. - * src/autofit/aflatin2.c (af_latin2_hints_init): Ditto. - -2017-03-31 Werner Lemberg - - * src/cff/cffload.c (cff_font_load): Improve fix from 2017-01-04. - - Allow CFFs containing a single font to have an empty font name. - - Problem reported by 張俊芝 <418092625@qq.com> in - - https://lists.nongnu.org/archive/html/freetype-devel/2017-03/msg00074.html - -2017-03-30 Werner Lemberg - - * src/cff/cffparse.h (CFF2_DEFAULT_STACK): Set to 513 also. - - Requested by Dave Arnold. - -2017-03-30 Werner Lemberg - - [truetype] Fix HVAR and VVAR handling (#50678). - - * src/truetype/ttgxvar.c (tt_hvadvance_adjust): Handle - glyph indices larger than `mapCount' as described in the - specification. - -2017-03-30 Werner Lemberg - - [truetype] Allow linear scaling for unhinted rendering (#50470). - - * src/truetype/ttdriver.c (tt_size_request): Revert change from - 2011-07-16; the intended metrics fix seems now to be implemented in - a different way, making the patch unnecessary. Note that this - change was usually patched out by all major GNU/Linux distributions - due to heavy side effects. - - * src/truetype/ttgload.c (compute_glyph_metrics, TT_Load_Glyph): - Refer to the metrics of the `TT_Size' object. - -2017-03-29 Werner Lemberg - - [truetype] Fix thinko related to PS name of default named instance. - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): `strid' and `psid' are - name ID values, not indices into the array of name entries. - -2017-03-27 Werner Lemberg - - [cid, truetype] Don't use `index' as a variable name. - - At least on FreeBSD there is a global declaration of `index' in file - `/usr/include/strings.h'. - - * src/cff/cf2intrp.c, src/truetype/ttgload.c: s/index/idx/ where - appropriate. - -2017-03-27 Wojciech Mamrak - - [sfnt] Minor improvement for handling kern tables. - - * src/sfnt/ttkern.c (tt_face_load_kern): Don't check for - cross-stream kerning tables since we reject format 2 tables later - on anyways. - Modify code for limit test... - (tt_face_get_kerning): ... to avoid a limit test here. - -2017-03-27 Werner Lemberg - - [pcf] Fix compiler warnings. - - Reported by Alexander Hedges . - - * src/pcf/pcfdrivr.c (pcf_property_set, pcf_property_get): Tag - `property_name' with `FT_UNUSED' where necessary. - -2017-03-26 Werner Lemberg - - * src/psaux/psobjs.c (t1_builder_close_contour): Add safety guard. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=941 - -2017-03-23 Werner Lemberg - - [psaux] Better protect `flex' handling. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=935 - - * src/psaux/t1decode.c (t1_decoder_parse_charstrings) - : Since there is not a single flex operator but a - series of subroutine calls, malformed fonts can call arbitrary other - operators after the start of a flex, possibly adding points. For - this reason we have to check the available number of points before - inserting a point. - -2017-03-23 Werner Lemberg - - [sfnt] Fix check for default named instance. - - * src/sfnt/sfobjs.c (sfnt_init_face): A `fixed' number needs four - bytes, not two... - -2017-03-23 Werner Lemberg - - Make MM fonts work (again). - - * src/base/ftmm.c (FT_Set_Var_Design_Coordinates, - FT_Set_MM_Blend_Coordinates, FT_Set_Var_Blend_Coordinates): Ignore - return value of `ft_face_get_mvar_service'; instead, check whether a - service is actually returned. - -2017-03-20 Werner Lemberg - - [truetype] Some variable renamings. - - Too much local variables holding different structures were called - `metrics'. - - * src/truetype/ttdriver.c (tt_size_select): s/metrics/size_metrics/. - - * src/truetype/ttgload.c (tt_get_metrics_incr_overrides, - compute_glyph_metrics): s/metrics/incr_metrics/. - (load_sbit_image): s/metrics/sbit_metrics/. - - * src/truetype/ttobjs.c (tt_size_run_fpgm): s/metrics/size_metrics/. - (tt_size_init_bytecode): s/metrics/tt_metrics/. - (tt_size_reset): s/metrics/size_metrics/. - -2017-03-20 Werner Lemberg - - [sfnt] Don't add instances to non-variation fonts. - - * src/sfnt/sfobjs.c (sfnt_init_face): Fix it. - -2017-03-20 Werner Lemberg - - * src/cff/cffgload.c (cff_builder_init): Add safety guard (#50578). - -2017-03-18 Werner Lemberg - - Introduce FT_UINT_TO_POINTER macro (#50560). - - We have to make a separate case for Windows 64's LLP64 data model. - - * builds/unix/ftconfig.in, builds/vms/ftconfig.h, - include/freetype/config/ftconfig.h (FT_UINT_TO_POINTER): New macro. - - * src/truetype/ttgload.c (load_truetype_glyph): Use it. - -2017-03-18 Werner Lemberg - - * src/truetype/ttinterp.c (TT_RunIns): Adjust loop counter (#50573). - - The problematic font that exceeds the old limit is Lato-Regular, - version 2.007, containing bytecode generated by a buggy version of - ttfautohint. - -2017-03-18 Werner Lemberg - - [truetype] Another limitation for bytecode loop count maximum. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=900 - - * src/truetype/ttinterp.c (TT_RunIns): Limit `loopcall_counter_max' - by number of glyphs also. - -2017-03-18 Werner Lemberg - - [ftfuzzer] Minor improvement. - - * src/tools/ftfuzzer/ftfuzzer.cc: Don't set intermediate axis if - bitmap strikes are active. - -2017-03-18 Werner Lemberg - - Improve `make multi'. - - * src/autofit/aflatin2.c: Guard file with FT_OPTION_AUTOFIT2. - - * src/base/ftmac.c: Guard more parts of the file with FT_MACINTOSH. - - * src/psaux/afmparse.c: Guard file with T1_CONFIG_OPTION_NO_AFM. - - * src/sfnt/pngshim.c: Guard file with - TT_CONFIG_OPTION_EMBEDDED_BITMAPS also. - - * src/sfnt/ttbdf.c: Avoid empty source file. - * src/sfnt/ttpost.c: Guard file with - TT_CONFIG_OPTION_POSTSCRIPT_NAMES. - * src/sfnt/ttsbit.c: Guard file with - TT_CONFIG_OPTION_EMBEDDED_BITMAPS. - - * src/truetype/ttgxvar.c, src/truetype/ttinterp.c: Avoid empty - source file. - - * src/truetype/ttsubpix.c: Guard file with - TT_USE_BYTECODE_INTERPRETER also. - - * src/type1/t1afm.c: Guard file with T1_CONFIG_OPTION_NO_AFM. - - * src/autofit/autofit.c, src/base/ftbase.c, src/cache/ftcache.c, - src/cff/cff.c, src/cid/type1cid.c, src/gxvalid/gxvalid.c, - src/pcf/pcf.c, src/pfr/pfr.c, src/psaux/psaux.c, - src/pshinter/pshinter.c, src/psnames/psnames.c, src/raster/raster.c, - src/sfnt/sfnt.c, src/smooth/smooth.c, src/truetype/truetype.c, - src/type1/type1.c, src/type42/type42.c: Remove conditionals; sort - entries. - -2017-03-17 Werner Lemberg - - Fixes for conditional compilation. - - * src/autofit/afcjk.c, src/autofit/afindic.c: Include `afcjk.h' - earlier. - - * src/sfnt/sfobjs.c (sfnt_init_face): Put `memory' variable into - TT_CONFIG_OPTION_GX_VAR_SUPPORT block. - (sfnt_done_face): Protect some code with - TT_CONFIG_OPTION_GX_VAR_SUPPORT. - - * src/sfnt/ttsbit.c (tt_face_load_sbix_image): Remove compiler - warning. - - * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Put `tmp' variable - into TT_USE_BYTECODE_INTERPRETER block. - - (tt_loader_init): Put `error' variable into - TT_USE_BYTECODE_INTERPRETER block. - -2017-03-17 Werner Lemberg - - Fix preprocessor warning. - - * devel/ftoption.h, include/freetype/config/ftoption.h: Test whether - TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined before checking its - value. - -2017-03-17 Werner Lemberg - - `make multi' fixes; compiler warnings. - - * src/base/ftsnames.c: Include FT_INTERNAL_DEBUG_H. - - * src/cff/cffobjs.c [TT_CONFIG_OPTION_GX_VAR_SUPPORT]: Include - FT_MULTIPLE_MASTERS_H and FT_SERVICE_MULTIPLE_MASTERS_H. - - * src/sfnt/sfdriver.c [TT_CONFIG_OPTION_GX_VAR_SUPPORT]: Include - FT_MULTIPLE_MASTERS_H and FT_SERVICE_MULTIPLE_MASTERS_H. - (get_win_string, get_apple_string): Initialize `result'. - -2017-03-17 Dave Arnold - - [cff] Fix potential bugs in default NDV for CFF2. - - * src/cff/cffload.c (cff_blend_build_vector): Explicitly build blend - vector when `lenNDV' is zero; don't rely on zero-init. - Save `lenNDV' as part of cache key even when `lenNDV' is zero. - -2017-03-17 Dave Arnold - - [cff] Fix CFF2 stack allocation. - - * src/cff/cffparse.c (cff_parser_init) add 1 for operator. - -2017-03-16 Werner Lemberg - - * src/truetype/ttgxvar.c (tt_done_blend): Free `vvar_table'. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=883 - -2017-03-15 Werner Lemberg - - Remove clang compiler warnings (#50548). - - * include/freetype/internal/tttypes.h (TT_FaceRec): Make - `var_postscript_prefix_len' unsigned. - - * src/autofit/afwarp.c (af_warper_compute_line_best): Remove - redundant assignment. - - * src/cff/cffload.c (cff_subfont_load): Add casts. - - * src/cff/cffparse.c (cff_parse_blend): Remove redundant assignment. - - * src/sfnt/sfdriver.c (fmix32, murmur_hash_3_128): Add `static' - keyword. - Add casts. - (fixed2float): Add cast. - (sfnt_get_var_ps_name): Make `p' always initialized. - Add casts. - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Add casts. - -2017-03-15 Werner Lemberg - - [ftfuzzer] Limit number of tested faces and instances. - - This is inspired by the discussion in and analysis of - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=859 - - * src/tools/ftfuzzer/ftfuzzer.cc (LLVMFuzzerTestOneInput): Use only - up to 20 face indices. - Use only up to 20 instance indices. - -2017-03-15 Werner Lemberg - - * src/tools/ftfuzzer/ftfuzzer.cc: Improve readability; formatting. - -2017-03-14 Werner Lemberg - - [sfnt] Implement PS names for font instances [3/3]. - - Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT. - - * include/freetype/internal/tttypes.h (TT_FaceRec): New fields - `var_postscript_prefix' and `var_postscript_prefix_len'. - - * src/sfnt/sfdriver.c: Include FT_TRUETYPE_IDS_H. - (sfnt_is_alphanumeric): New wrapperfunction for `ft_isalnum'. - (get_win_string, get_apple_string): Remove `const' from return - value. - (MAX_VALUE_DESCRIPTOR_LEN, MAX_PS_NAME_LEN): New macros. - (hexdigits): New array. - (sfnt_get_var_ps_name): New function, implementing Adobe TechNote - 5902 to construct a PS name for a variation font instance. - (sfnt_get_ps_name): Call `sfnt_get_var_ps_name' for font instances. - - * src/sfnt/sfobjs.c (sfnt_done_face): Updated. - - * src/truetype/ttgxvar.c (tt_set_mm_blend): Reset - `face->postscript_name' to trigger recalculation for new instance - parameters. - -2017-03-14 Werner Lemberg - - [sfnt] Implement PS names for font instances [2/3]. - - * src/sfnt/sfdriver.c (fix2float) [TT_CONFIG_OPTION_GX_VAR_SUPPORT]: - New function to find the shortest representation of a 16.16 - fractional number. - -2017-03-14 Werner Lemberg - - [sfnt] Implement PS names for font instances [1/3]. - - Add 128bit MurmurHash 3 function. - - Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT. - - * src/sfnt/sfdriver.c (ROTL32): New macro. - (fmix32, murmur_hash_3_128): New functions. - -2017-03-13 Werner Lemberg - - [truetype] Ignore invalid MVAR tags. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=838 - - * src/truetype/ttgxvar.c (ft_var_load_mvar): Ignore value and emit - warning for invalid tags. - (tt_apply_mvar): Ignore invalid tags. - -2017-03-12 Werner Lemberg - - [truetype] Store and use design coordinates also. - - * include/freetype/internal/services/svmm.h (FT_Get_Var_Blend_Func): - Add `normalizedcoords' argument. - - * src/truetype/ttgxvar.h (GX_BlendRec): Add `coords' field to store - the design coordinates of the current instance. - Updated. - - * src/truetype/ttgxvar.c (TT_Set_MM_Blend): Move functionality to... - (tt_set_mm_blend): ... New function. - Convert data in `normalizedcoords' array to `coords' array on - demand. - (TT_Set_Var_Design): Store argument data in `coords' array. - (TT_Get_Var_Design): Get data from `coords' array. - (tt_get_var_blend): Updated. - (tt_done_blend): Updated. - - * src/cff/cffload.c, src/cff/cffload.h (cff_get_var_blend): Updated. - - * src/cff/cf2ft.c (cf2_getNormalizedVector): Updated. - - * src/cff/cffobjs.c (cff_face_init): Updated. - -2017-03-12 Werner Lemberg - - src/truetype/ttgxvar.[ch]: s/avar_checked/avar_loaded/. - -2017-03-08 Werner Lemberg - - [sfnt] Another fix for buggy variation fonts. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=759 - - * src/sfnt/sfobjs.c (sfnt_init_face): While setting number of - instances to zero for `CFF' fonts table, ensure that there is no - `CFF2' present also (which gets priority). - -2017-03-07 Werner Lemberg - - [sfnt] Improve handling for buggy variation fonts. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=738 - - * src/sfnt/sfobjs.c (sfnt_init_face): While setting number of - instances to zero for `CFF' fonts table, ensure that there is no - `glyf' table present also (which gets priority). - -2017-03-06 Werner Lemberg - - [sfnt, truetype] Always provide default instance. - - As documented in the OpenType specification, an entry for the - default instance may be omitted in the named instance table. In - particular this means that even if there is no named instance table - in the font we actually do have a named instance, namely the default - instance. - - For consistency, we always want the default instance in our list of - named instances. If it is missing, we try to synthesize it. - - * src/sfnt/sfobjs.c (sfnt_init_face): Check whether the default - instance is in the table of named instances. Otherwise adjust - number of instances. - - * src/truetype/ttgxvar.c: Include FT_TRUETYPE_IDS_H. - (TT_Get_MM_Var): Use `face->root.style_flags' as the number of named - instances. - Sythesize a named instance entry if necessary. - (tt_done_blend): Free `normalized_stylecoords'. - -2017-03-05 Werner Lemberg - - [sfnt] Remove redundant code. - - * src/sfnt/sfobjs.c (sfnt_init_face): Remove second test for - `num_instances', which will always succeed. - -2017-03-04 Werner Lemberg - - [sfnt] Add `get_name_id' service. - - * include/freetype/internal/sfnt.h (TT_Get_Name_ID_Func): New - typedef. - (SFNT_Interface): Add `get_name_id' field. - (FT_DEFINE_SFNT_INTERFACE): Updated. - - * src/sfnt/sfdriver.c (search_name_id): Rename to... - (sfnt_get_name_id): ... this. - (sfnt_get_ps_name, sfnt_interface): Updated. - -2017-03-04 Werner Lemberg - - [truetype] Make `TT_Set_MM_Blend' set named instance index. - - * src/truetype/ttgxvar.h (GX_Blend): New array - `normalized_stylecoords'. - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Allocate and fill - `normalized_stylecoords'. - (TT_Set_MM_Blend): Check instance tuple and adjust `face_index' - accordingly. - -2017-03-02 Werner Lemberg - - [truetype] Split off designer/normalized conversion routines. - - * src/truetype/ttgxvar.c (TT_Set_Var_Design): Split off conversion - code designer->normalized coordinates to... - (ft_var_to_normalized): ... New function. - (TT_Get_Var_Design): Split off conversion code normalized->designer - coordinates to... - (ft_var_to_design): ... New function. - -2017-02-28 Werner Lemberg - - [sfnt] Further generalize `sfnt_get_ps_name'; report invalid data. - - * src/sfnt/sfdriver.c (sfnt_ps_map): New array. - (sfnt_is_postscript): New function. - (char_type_func): New typedef. - (get_win_string, get_apple_string): Add argument to specify - character checking function. - Add argument whether argument checking failures should be reported. - Update callers. - (search_name_id): Fix return value. - -2017-02-23 Werner Lemberg - - [sfnt] Split off another bit of `sfnt_get_ps_name'. - - * src/sfnt/sfdriver.c (sfnt_get_ps_name): Split off some - functionality into... - (search_name_id): ... New function. - -2017-02-23 Werner Lemberg - - [sfnt] Modularize `sfnt_get_ps_name'. - - * src/sfnt/sfdriver.c (sfnt_get_ps_name): Split off some - functionality into... - (IS_WIN, IS_APPLE): ... New macros. - (get_win_string, get_apple_string): ... New functions. - -2017-02-23 Werner Lemberg - - [truetype] Minor improvement. - - * src/truetype/ttgload.c (TT_Process_Simple_Glyph, - load_truetype_glyph): Remove unnecessary tests. - -2017-02-23 Werner Lemberg - - * include/freetype/internal/tttypes.h (TT_Face): s/isCFF2/is_cff2/. - - For orthogonality with other structure field names. - - Update all users. - -2017-02-22 Alexei Podtelezhnikov - - * src/smooth/ftgrays.c (gray_hline): Improve code. - -2017-02-20 Dominik Röttsches - - Fix some `ttnameid.h' entries (#50313). - - * include/freetype/ttnameid.h: - s/TT_MS_LANGID_SPANISH_INTERNATIONAL_SORT/TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT/, - s/TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIA/TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN/. - -2017-02-20 Werner Lemberg - - [cff] Finish support for `random' operator. - - * src/cff/cfftypes.h (CFF_SubFontRec): Add `random' field. - - * src/cff/cffobjs.c: Updated. - (cff_driver_init): Initialize random seed value. - - * src/cff/cffload.c (cff_random): New function. - (cff_subfont_load): Add `face' argument. - Update all callers. - Initialize random number generator with a proper seed value. - (cff_font_load): Add `face' argument. - Update all callers. - - * src/cff/cffload.h: Updated. - - * src/cff/cf2intrp.c (CF2_FIXME): Removed. - (cf2_interpT2CharString) : Implement opcode. - - * src/cff/cffgload.c (cff_decoder_parse_charstrings): Don't - initialize random seed value. - : Use new random seed framework. - -2017-02-20 Werner Lemberg - - [cff] Sanitize `initialRandomSeed'. - - * src/cff/cffload.c (cff_load_private_dict): Make - `initial_random_seed' value always positive. - -2017-02-20 Werner Lemberg - - [cff] Introduce `random-seed' property (2/2). - - * src/base/ftobjs.c: Include `FT_CFF_DRIVER_H'. - (open_face): Initialize `face->internal->random_seed'. - (FT_Face_Properties): Handle `FT_PARAM_TAG_RANDOM_SEED'. - - * src/cff/cffdrivr.c (cff_property_set): Handle `random-seed' - property. - -2017-02-20 Werner Lemberg - - [cff] Introduce `random-seed' property (1/2). - - We need this for support of the `random' operator. - - * include/freetype/ftcffdrv.h (FT_PARAM_TAG_RANDOM_SEED): New macro. - - * include/freetype/internal/ftobjs.h (FT_Face_InternalRec): New - field `random_seed'. - - * src/cff/cffobjs.h (CFF_DriverRec): New field `random_seed'. - -2017-02-17 Werner Lemberg - - Remove clang warnings. - - * src/autofit/aflatin.c (af_latin_sort_blue): Add missing `static' - keyword. - - * src/base/ftmm.c (FT_Set_Var_Design_Coordinates, - FT_Set_MM_Blend_Coordinates, FT_Set_Var_Blend_Coordinates): - Initialize some variables. - -2017-02-16 Nikolaus Waxweiler - Werner Lemberg - - Add face property for stem darkening. - - * include/freetype/ftautoh.h (FT_PARAM_TAG_STEM_DARKENING): New - macro. - - * include/freetype/internal/ftobjs.h (FT_Face_InternalRec): Add - `no_stem_darkening' field. - - * src/autofit/afloader.c (af_loader_load_glyph), - src/autofit/afmodule.c (af_property_set): Updated. - - * src/base/ftobjs.c: Include FT_AUTOHINTER_H. - (ft_open_face_internal): Updated. - (FT_Face_Properties): Handle FT_PARAM_TAG_STEM_DARKENING. - - * src/cff/cf2ft.c (cf2_decoder_parse_charstrings): Updated. - - * src/cff/cffdrivr.c (cff_property_set): Updated. - -2017-02-16 Nikolaus Waxweiler - Werner Lemberg - - Add face property for LCD filter weights. - - * include/freetype/ftlcdfil.h (FT_PARAM_TAG_LCD_FILTER_WEIGHTS, - FT_LCD_FILTER_FIVE_TAPS): New macros. - (FT_LcdFiveTapFilter): New typedef. - - * include/freetype/ftobjs.h (FT_Face_InternalRec) - [FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Add `lcd_weights' field. - (FT_Bitmap_LcdFilterFunc): Change third argument to weights array. - (ft_lcd_filter_fir): New prototype. - (FT_LibraryRec): Updated. - - * src/base/ftlcdfil.c (_ft_lcd_filter_fir): Renamed to... - (ft_lcd_filter_fir): ... this base function. - Updated. - (_ft_lcd_filter_legacy): Updated. - (FT_Library_SetLcdFilterWeights, FT_Library_SetLcdFilter): Updated. - - * src/base/ftobjs.c (ft_open_face_internal): Updated. - (FT_Face_Properties): Handle FT_PARAM_TAG_LCD_FILTER_WEIGHTS. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic) - [FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Handle LCD weights from - `FT_Face_Internal'. - -2017-02-14 Nikolaus Waxweiler - Werner Lemberg - - Add new function `FT_Face_Properties'. - - This commit provides the framework, to be filled with something - useful in the next commits. - - * include/freetype/freetype.h (FT_Face_Properties): Declare. - - * src/base/ftobjs.c (FT_Face_Properties): New function. - -2017-02-13 Werner Lemberg - - [autofit] Prevent overlapping blue zones. - - Problem reported as - - https://github.com/google/fonts/issues/632 - - The font in question (Nunito) has values 705 and 713 for the - reference and overshoot values, respectively, of the first blue - zone. Blue zone 2, however, has value 710 for both the reference - and overshoot. At 12ppem, reference and overshoot of blue zone 0 - becomes 8px, while blue zone 2 becomes 9px. - - A peculiarity of this font is that the tops of isolated vertical - stems like `N' have a slight overshoot also. The auto-hinter tries - to find the nearest blue zone using the *original* coordinates. For - vertical stems, this is value 713. For normal horizontal tops like - in character `E', this is value 710. Since value 713 is mapped to - 8px but value 710 to 9px, `N' and similar characters are one pixel - higher than `E', which looks very bad. - - This commit sanitizes blue zones to avoid such a behaviour. - - * src/autofit/aflatin.c (af_latin_sort_blue): New function. - (af_latin_metrics_init_blues): Sort blue values and remove overlaps. - -2017-02-12 Alexei Podtelezhnikov - - * src/smooth/ftgrays.c (gray_sweep): Improve code. - -2017-02-06 Werner Lemberg - - [truetype] Implement `VVAR' table support. - - * src/truetype/ttgxvar.h (GX_HVarTable): Renamed to... - (GX_HVVarTable): ...This. - (GX_Blend): Add fields for `VVAR' table handling. - Other minor updates. - - * src/truetype/ttgxvar.c (ft_var_load_hvar): Renamed to... - (ft_var_load_hvvar): ...This. - Handle VVAR loading also (controlled by an additional parameter). - (tt_hadvance_adjust): Renamed to... - (tt_hvadvance_adjust): ...This. - Handle application of advance height also (controlled by an - additional parameter). - (tt_hadvance_adjust, tt_vadvance_adjust): Wrappers for - `tt_hvadvance_adjust'. - - * src/truetype/ttdriver.c (tt_service_metrics_variations): Updated. - -2017-02-05 Werner Lemberg - - [autofit] Use better blue zone characters for lowercase latin. - - The number of lowercase characters for computing the top flat blue - zone value was too small (in most cases only `x' and `z'). If one - of the two characters has a large serif, say, it can happen that - FreeType must select between two different values, having a 50% - chance to use the wrong one. As a result, rendering at larger PPEM - values could yield uneven lowercase glyph heights. - - Problem reported by Christoph Koeberlin . - - * src/autofit/afblue.dat (AF_BLUE_STRING_LATIN_SMALL): Replaced - with... - (AF_BLUE_STRING_LATIN_SMALL_TOP, AF_BLUE_STRING_LATIN_SMALL_BOTTOM): - ... New, extended sets. - (AF_BLUE_STRINGSET_LATN): Updated. - - * src/autofit/afblue.c, scr/autofit/afblue.h: Regenerated. - -2017-02-04 Werner Lemberg - - Make `freetype-config' a wrapper of `pkg-config' if possible. - - Based on ideas taken from - - https://pkgs.fedoraproject.org/cgit/rpms/freetype.git/tree/freetype-multilib.patch - https://pkgs.fedoraproject.org/cgit/rpms/freetype.git/tree/freetype-2.5.3-freetype-config-prefix.patch - - * builds/unix/freetype-config.in: Rewritten. Use `pkg-config' to - set output variables if program is available. - - * docs/CHANGES, docs/freetype-config.1: Updated. - -2017-02-04 Werner Lemberg - - * builds/unix/unix-def.in (freetype-config): Fix permissions. - -2017-02-03 Werner Lemberg - - * src/autofit/afglobal.c (af_face_globals_free): Erase useless code. - -2017-02-03 Werner Lemberg - - * include/freetype/ftgasp.h (FT_GASP_SYMMETRIC_GRIDFIT): Fix value. - - Reported by Behdad. - -2017-02-02 Werner Lemberg - - [truetype] Fix MVAR post-action handling. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=509 - - * src/truetype/ttobjs.c (tt_size_reset): Do nothing for CFF2. This - is important to make `tt_size_reset_iterator' (called in - `tt_apply_mvar') always work. - -2017-02-02 Werner Lemberg - - Make compilation with FT_CONFIG_OPTION_PIC work again. - - All code committed here is guarded with `FT_CONFIG_OPTION_PIC'. - - * include/freetype/internal/services/svmetric.h - (FT_DEFINE_SERVICE_METRICSVARIATIONSREC): Remove trailing semicolon. - - * src/autofit/aflatin.c (af_latin_hints_compute_edges, - af_latin_hint_edges): Provide `globals' variable. - - * src/autofit/afloader.c (af_loader_load_glyph): Remove shadowing - variable. - - * src/autofit/afmodule.c (AF_SCRIPT_CLASSES_GET, - AF_STYLE_CLASSES_GET): Redefine. - - * src/autofit/aftypes.h (AF_DEFINE_WRITING_SYSTEM_CLASS): Fix typo. - - * src/cff/cffparse.c (CFF_FIELD_BLEND): Provide it. - - * src/cff/cffpic.h (CffModulePIC): Fix typo. - -2017-01-31 Alexei Podtelezhnikov - - * src/smooth/ftgrays.c (gray_render_scanline): Improve code. - -2017-01-31 Werner Lemberg - - [cff] Provide metrics variation service interface (#50196). - - Only now I've got an OTF with an HVAR table for testing... - - The code in `ftmm.c' uses `FT_FACE_LOOKUP_SERVICE' to get the - metrics variations interface. However, this didn't work with - `FT_FACE_FIND_GLOBAL_SERVICE' used in `sfnt_init_face'. - - * src/cff/cffdrivr.c: Include FT_SERVICE_METRICS_VARIATIONS_H. - (cff_hadvance_adjust, cff_metrics_adjust): Wrapper functions for - metric service functions from the `truetype' module. - (cff_service_metrics_variations): New service. - (cff_services): Updated. - - * src/cff/cffpic.h (CFF_SERVICE_METRICS_VAR_GET): New macro. - [FT_CONFIG_OPTION_PIC]: Synchronize code. - - * src/sfnt/sfobjs.c (sfnt_init_face): Replace call to - FT_FACE_FIND_GLOBAL_SERVICE with `ft_module_get_service' to always - load the service from the `truetype' module. - -2017-01-31 Werner Lemberg - - Add framework to support services with 9 functions. - - * include/freetype/internal/ftserv.h (FT_DEFINE_SERVICEDESCREC9): - New macro. - -2017-01-31 Werner Lemberg - - [base] Fix error handing in MM functions. - - * src/base/ftmm.c (FT_Set_Var_Design_Coordinates, - FT_Set_MM_Blend_Coordinates, FT_Set_Var_Blend_Coordinates): - Implement it. - -2017-01-31 Werner Lemberg - - [truetype] Fix sanity check for `gvar' table (#50184). - - * src/truetype/ttgxvar.c (ft_var_load_gvar): There might be missing - variation data for some glyphs. - -2017-01-31 Werner Lemberg - - [autofit] Avoid uninitialized jumps (#50191). - - * src/autofit/afcjk.c (af_cjk_metrics_check_digits), - src/autofit/aflatin.c (af_latin_metrics_check_digits): Initialize - `advance'. - -2017-01-27 Werner Lemberg - - s/GB2312/PRC/. - - * include/freetype/freetype.h (FT_ENCODING_PRC): New enum value. - (FT_ENCODING_GB2312): Deprecated. - - * include/freetype/ttnameid.h (TT_MS_ID_PRC): New macro. - (TT_MS_ID_GB2312): Deprecated. - - * src/sfnt/sfobjs.c (sfnt_find_encoding): Updated. - - * docs/CHANGES: Updated. - -2017-01-26 Werner Lemberg - - [base] Add `FT_Get_Sfnt_LangTag' function. - - * include/freetype/ftsnames.h (FT_SfntLangTag): New structure. - (FT_Get_Sfnt_LangTag): New declaration. - - * src/base/ftsnames.c (FT_Get_Sfnt_LangTag): New function. - - * docs/CHANGES: Updated. - -2017-01-26 Werner Lemberg - - [sfnt] Support `name' table format 1. - - * include/freetype/internal/tttypes.h (TT_LangTagRec): New - structure. - (TT_NameTableRec): Add fields `numLangTagRecords' and `langTags'. - - * src/sfnt/ttload.c (tt_face_load_name): Add support for language - tags. - Reduce array size of name strings in case of invalid entries. - (tt_face_free_name): Updated. - - * docs/CHANGES: Updated. - -2017-01-25 Werner Lemberg - - [sfnt] s/TT_NameEntry/TT_Name/. - - * include/freetype/internal/tttypes.h (TT_NameEntryRec): Renamed - to... - (TT_NameRec): This. - (TT_NameTableRec): Updated. - - * src/base/ftsnames.c (FT_Get_Sfnt_Name): Updated. - - * src/sfnt/sfdriver.c (sfnt_get_ps_name): Updated. - - * src/sfnt/sfobjs.c (tt_name_entry_ascii_from_utf16, - tt_name_entry_ascii_from_other): Renamed to... - (tt_name_ascii_from_utf16, tt_name_entry_ascii_from_other): This, - respectively. - (TT_NameEntry_ConvertFunc): Renamed to... - (TT_Name_ConvertFunc): This. - (tt_face_get_name): Updated. - - * src/sfnt/ttload.c (tt_face_load_name, tt_face_free_name): - Updated. - -2017-01-24 Werner Lemberg - - [sfnt] Fix Postscript name service for symbol fonts. - - * src/sfnt/sfdriver.c (sfnt_get_ps_name): Accept PID/EID=3/0 - entries also. - -2017-01-24 Werner Lemberg - - [truetype] For OpenType 1.7: s/preferred/typographic/ (sub)family. - - * include/freetype/ftsnames.h - (FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY, - FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY): New macros. - (FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY, - FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY): Deprecated. - - * include/freetype/ttnameid.h (TT_NAME_ID_TYPOGRAPHIC_FAMILY, - TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY): New macros. - (TT_NAME_ID_PREFERRED_FAMILY, TT_NAME_ID_PREFERRED_SUBFAMILY): - Deprecated. - - * src/sfnt/sfobjs.c (sfnt_load_face): Updated. - - * docs/CHANGES: Updated. - -2017-01-23 Werner Lemberg - - [base] Add `FT_Set_Default_Properties' (#49187). - - * include/freetype/ftmodapi.h: Add declaration. - - * src/base/ftinit.c (ft_set_default_properties): Renamed to... - (FT_Set_Default_Properties): ... this. - (FT_Init_FreeType): Updated. - - * docs/CHANGES: Updated. - -2017-01-23 Werner Lemberg - - [truetype] Minor updates for OpenType 1.8.1. - - * src/truetype/ttgxvar.h (GX_MVarTable): `axisCount' has been - removed from the specification; it is now reserved. - - * src/truetype/ttgxvar.c (ft_var_load_mvar): Updated. - (GX_FVar_Head): Remove `countSizePairs'; the corresponding data - field in the `MVAR' table is now reserved. - (fvar_fields): Updated. - -2017-01-23 Werner Lemberg - - [truetype] Avoid segfault for invalid variation data. - - * src/truetype/ttgxvar.c (ft_var_load_item_variation_store): Assure - `itemCount' is not zero. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=441 - -2017-01-20 Werner Lemberg - - * src/truetype/ttinterp.c (TT_RunIns): Adjust loop detector limits. - -2017-01-17 Werner Lemberg - - * include/freetype/ttnameid.h: Updated to OpenType 1.8.1. - - (TT_APPLE_ID_FULL_UNICODE): New macro. - - (TT_MS_LANGID_BOSNIAN_BOSNIA_HERZ_CYRILLIC, - TT_MS_LANGID_UPPER_SORBIAN_GERMANY, - TT_MS_LANGID_LOWER_SORBIAN_GERMANY, TT_MS_LANGID_IRISH_IRELAND, - TT_MS_LANGID_INUKTITUT_CANADA_LATIN, TT_MS_LANGID_BASHKIR_RUSSIA, - TT_MS_LANGID_LUXEMBOURGISH_LUXEMBOURG, - TT_MS_LANGID_GREENLANDIC_GREENLAND, TT_MS_LANGID_MAPUDUNGUN_CHILE, - TT_MS_LANGID_MOHAWK_MOHAWK, TT_MS_LANGID_BRETON_FRANCE, - TT_MS_LANGID_OCCITAN_FRANCE, TT_MS_LANGID_CORSICAN_FRANCE, - TT_MS_LANGID_ALSATIAN_FRANCE, TT_MS_LANGID_YAKUT_RUSSIA, - TT_MS_LANGID_KICHE_GUATEMALA, TT_MS_LANGID_KINYARWANDA_RWANDA, - TT_MS_LANGID_WOLOF_SENEGAL, TT_MS_LANGID_DARI_AFGHANISTAN): New - macros. - - (TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC): Fix value. - - (TT_MS_LANGID_GERMAN_LIECHTENSTEIN, TT_MS_LANGID_CATALAN_CATALAN, - TT_MS_LANGID_CHINESE_MACAO, TT_MS_LANGID_SPANISH_SPAIN_MODERN_SORT, - TT_MS_LANGID_KOREAN_KOREA, TT_MS_LANGID_ROMANSH_SWITZERLAND, - TT_MS_LANGID_SLOVENIAN_SLOVENIA, TT_MS_LANGID_BASQUE_BASQUE, - TT_MS_LANGID_SETSWANA_SOUTH_AFRICA, - TT_MS_LANGID_ISIXHOSA_SOUTH_AFRICA, - TT_MS_LANGID_ISIZULU_SOUTH_AFRICA, TT_MS_LANGID_KAZAKH_KAZAKHSTAN, - TT_MS_LANGID_KYRGYZ_KYRGYZSTAN, TT_MS_LANGID_KISWAHILI_KENYA, - TT_MS_LANGID_TATAR_RUSSIA, TT_MS_LANGID_ODIA_INDIA, - TT_MS_LANGID_MONGOLIAN_PRC, TT_MS_LANGID_TIBETAN_PRC, - TT_MS_LANGID_WELSH_UNITED_KINGDOM, TT_MS_LANGID_GALICIAN_GALICIAN, - TT_MS_LANGID_SINHALA_SRI_LANKA, TT_MS_LANGID_TAMAZIGHT_ALGERIA, - TT_MS_LANGID_SESOTHO_SA_LEBOA_SOUTH_AFRICA, TT_MS_LANGID_YI_PRC, - TT_MS_LANGID_UIGHUR_PRC): New aliases. - - Remove commented out code. - - (TT_NAME_ID_LIGHT_BACKGROUND, TT_NAME_ID_DARK_BACKGROUND, - TT_NAME_ID_VARIATIONS_PREFIX): New macros. - - (HAVE_LIMIT_ON_IDENTS): Remove macro (which was useless since many - years), use guarded long macros by default and define short versions - as aliases for the long ones. - -2017-01-15 Werner Lemberg - - * src/truetype/ttgxvar.c (tt_apply_var): Handle underline parameters - also. - -2017-01-11 Werner Lemberg - - * src/base/ftobjs.c (ft_open_face_internal): Improve tracing. - -2017-01-11 Werner Lemberg - - [truetype] Actually use metrics variation service. - - * src/base/ftmm.c: Include FT_SERVICE_METRICS_VARIATIONS_H. - (ft_face_get_mvar_service): New auxiliary function to look up - metrics variation service. - (FT_Set_Var_Design_Coordinates, FT_Set_MM_Blend_Coordinates, - FT_Set_Var_Blend_Coordinates): Call metrics variation service. - - * src/truetype/ttobjs.c (tt_face_init): Use metrics variations for - named instances. - -2017-01-11 Werner Lemberg - - [truetype] Provide metrics variation service. - - * include/freetype/internal/services/svmetric.h - (FT_Metrics_Adjust_Func): Reduce number of necessary parameters. - - * src/truetype/ttgxvar.c: Include FT_LIST_H. - (tt_size_reset_iterator): New auxiliary function for... - (tt_apply_var): New function. - - * src/truetype/ttgxvar.h: Updated. - - * src/truetype/ttdriver.c (tt_service_metrics_variations): Add - `tt_apply_mvar'. - - * include/freetype/internal/ftserv.h (FT_ServiceCache): Add metrics - variation service. - -2017-01-11 Werner Lemberg - - [truetype] Parse `MVAR' table. - - * src/truetype/ttgxvar.h (MVAR_TAG_XXX): New macros for MVAR tags. - (GX_Value, GX_MVarTable): New structures. - (GX_Blend): Add it. - - * src/truetype/ttgxvar.c (GX_VALUE_SIZE, GX_VALUE_CASE, - GX_GASP_CASE): New macros. - (ft_var_get_value_pointer): New auxiliary function to get a pointer - to a value from various SFNT tables already stored in `TT_Face'. - (ft_var_load_mvar): New function. - (TT_Get_MM_Var): Call it. - (tt_done_blend): Updated. - -2017-01-11 Werner Lemberg - - [truetype] More preparations for MVAR support. - - * src/truetype/ttobjs.c (tt_size_reset): Add argument to make - function only recompute ascender, descender, and height. - - * src/truetype/ttobjs.h: Updated. - - * src/truetype/ttdriver.c (tt_size_select, tt_size_request): - Updated. - -2017-01-09 Werner Lemberg - - [pcf] Disable long family names by default. - - * include/freetype/config/ftoption.h - (PCF_CONFIG_OPTION_LONG_FAMILY_NAMES): Comment out. - -2017-01-09 Werner Lemberg - - [pcf] Make long family names configurable. - - The change from 2016-09-29 was too radical (except for people using - the openSuSE GNU/Linux distribution). To ameliorate the situation, - PCF_CONFIG_OPTION_LONG_FAMILY_NAMES gets introduced which controls - the feature; if set, a new PCF property option - `no-long-family-names' can be used to switch this feature off. - - * include/freetype/config/ftoption.h, devel/ftoption.h - (PCF_CONFIG_OPTION_LONG_FAMILY_NAMES): New option. - - * include/freetype/ftpcfdrv.h: New header file (only containing - comments currently, used for building the documentation). - - * include/freetype/config/ftheader.h (FT_PCF_DRIVER_H): New macro. - - * src/pcf/pcf.h (PCF_Driver): Add `no_long_family_names' field. - - * src/pcf/pcfdrivr.c: Include FT_SERVICE_PROPERTIES_H and - FT_PCF_DRIVER_H. - (pcf_property_set, pcf_property_get): New functions. - (pcf_service_properties): New service. - (pcf_services): Updated. - (pcf_driver_init) [PCF_CONFIG_OPTION_LONG_FAMILY_NAMES]: Handle - `no_long_family_names'. - - * src/pcf/pcfread.c (pcf_load_font): Handle `no_long_family_names' - and PCF_CONFIG_OPTION_LONG_FAMILY_NAMES. - - * docs/CHANGES: Updated. - -2017-01-09 Werner Lemberg - - [pcf] Introduce a driver structure. - - To be filled later on with something useful. - - * src/pcf/pcf.h (PCF_Driver): New structure. - - * src/pcf/pcfdrivr.c (pcf_driver_init, pcf_driver_done): New dummy - functions. - (pcf_driver_class): Updated. - -2017-01-08 Werner Lemberg - - [truetype] Again some GX code shuffling. - - We need this later on for MVAR also. - - * src/truetype/ttgxvar.c (tt_hadvance_adjust): Split off computing - an item store variation delta into... - (ft_var_get_item_delta): ...new function. - -2017-01-08 Werner Lemberg - - [truetype] Adjust font variation flags for MVAR. - - * include/freetype/internal/tttypes.h (TT_FACE_FLAG_VAR_XXX): - Remove all flags related to MVAR; replace it with... - (TT_FACE_FLAG_VAR_MVAR): ...this new macro. - (TT_Face): Remove `mvar_support' field (which was still unused). - -2017-01-06 Werner Lemberg - - [truetype] More GX code shuffling. - - We need this later on for MVAR also. - - * src/truetype/ttgxvar.c (tt_done_blend): Split off handling of item - variation store into... - (ft_var_done_item_variation_store): ...new function. - -2017-01-06 Werner Lemberg - - [truetype] More generalization of GX stuff. - - We need this later on for MVAR also. - - * src/truetype/ttgxvar.c (ft_var_load_delta_set_index_mapping): Add - parameters for delta-set index mapping and item variation store. - (ft_var_load_item_variation_store): Add parameter for item variation - store. - s/hvarData/varData/. - Move allocation of `hvar_table' to... - (ft_var_load_hvar): ...this function. - Updated. - -2017-01-06 Werner Lemberg - - [truetype] Some GX structure renames for generalization. - - We need this later on for MVAR also. - - * src/truetype/ttgxvar.h (GX_HVarData): Renamed to... - (GX_ItemVarData): ...this. - (GX_HVarRegion): Renamed to... - (GX_VarRegion): ...this. - (GX_HVStore): Renamed to... - (GX_ItemVarStore): ...this. - (GX_WidthMap): Renamed to... - (GX_DeltaSetIdxMap): ...this. - - (GX_HVarTable): Updated. - - * src/truetype/ttgxvar.c: Updated. - -2017-01-06 Werner Lemberg - - [truetype] Code shuffling. - - * src/truetype/ttgxvar.c (ft_var_load_hvar): Split off loading of - item variation store and delta set index mapping into... - (ft_var_load_item_variation_store, - ft_var_load_delta_set_index_mapping): ...new functions. - -2017-01-06 Werner Lemberg - - [truetype] Add HVAR access without advance width map. - - * src/truetype/ttgxvar.c (ft_var_load_hvar): Handle case where - `offsetToAdvanceWidthMapping' is zero. - (tt_hadvance_adjust): Implement direct deltaSet access by glyph - index. - -2017-01-06 Werner Lemberg - - [pcf] Revise driver. - - This commit improves tracing and handling of malformed fonts. In - particular, the changes to `pcf_get_properties' fix - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=379 - - * src/pcf/pcfread.c (tableNames): Use long names for better - readability. - (pcf_read_TOC): Allow at most 9 tables. - (pcf_get_properties): Allow at most 256 properties. - Limit strings array length to 256 * (65536 + 1) bytes. - Better tracing. - (pcf_get_metric): Trace metric data. - (pcf_get_metrics): Allow at most 65536 metrics. - Fix comparison of `metrics->ascent' and `metrics->descent' to avoid - potential overflow. - Better tracing. - (pcf_get_bitmaps): Allow at most 65536 bitmaps. - Better tracing. - (pcf_get_encodings, pcf_get_accel): Better tracing. - - * src/pcf/pcfdrivr.c (PCF_Glyph_Load): Don't trace `format' details. - These are now shown by `pcf_get_bitmaps'. - -2017-01-04 Werner Lemberg - - * src/pcf/pcfdrivr.c (PCF_Face_Init): Trace compression format. - -2017-01-04 Werner Lemberg - - [cff] More consistency checks for pure CFFs. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=378 - - * src/cff/cffload.c (cff_font_load): Check element number and size - of Name and Top DICT indices. - -2017-01-04 Werner Lemberg - - [cff, truetype] Minor tracing improvement. - - * src/cff/cffobjs.c (cff_face_init), src/truetype/ttobjs.c - (tt_face_init): Indent first tracing message from SFNT driver. - -2017-01-03 Werner Lemberg - - [truetype] Various minor fixes. - - * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Check instruction - size only if we do native hinting. - (TT_Load_Glyph): Trace returned error code. - - * src/truetype/ttobjs.c (tt_size_run_fpgm, tt_size_run_prep): Trace - returned error code. - (tt_size_ready_bytecode): Don't run `prep' table if `fpgm' table is - invalid. - -2017-01-03 Werner Lemberg - - [sfnt] Don't fail if PCLT, EBLC (and similar tables) are invalid. - - These tables are optional. - - * src/sfnt/sfobjs.c (sfnt_load_face): Implement it. - -2017-01-03 Werner Lemberg - - * src/cff/cffparse.c (cff_parse_num): Simplify. - -2017-01-03 Werner Lemberg - - Various fixes for clang's undefined behaviour sanitizer. - - * src/cff/cffload.c (FT_fdot14ToFixed): Fix casting. - (cff_blend_doBlend): Don't left-shift negative numbers. - Handle 5-byte numbers byte by byte to avoid alignment issues. - - * src/cff/cffparse.c (cff_parse_num): Handle 5-byte numbers byte by - byte to avoid alignment issues. - - * src/cid/cidload (cid_read_subrs): Do nothing if we don't have any - subrs. - - * src/psaux/t1decode.c (t1_decode_parse_charstring): Fix tracing. - - * src/tools/glnames.py (main): Put `DEFINE_PSTABLES' guard around - definition of `ft_get_adobe_glyph_index'. - - * src/psnames/pstables.h: Regenerated. - - * src/psnames/psmodule.c: Include `pstables.h' twice to get both - declaration and definition. - - * src/truetype/ttgxvar.c (FT_fdot14ToFixed, FT_intToFixed): Fix - casting. - -2017-01-01 Werner Lemberg - - [cff] Handle multiple `blend' operators in a row correctly. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=368 - - * src/cff/cffload.c (cff_blend_doBlend): Adjust `parser->stack' - pointers into `subFont->blend_stack' after reallocation. - -2017-01-01 Werner Lemberg - - [sfnt] Return correct number of named instances for TTCs. - - Without this patch, requesting information for face index N returned - the data for face index N+1 (or index 0). - - * src/sfnt/sfobjs.c (sfnt_init_face): Correctly adjust `face_index' - for negative `face_instance_index' values. - -2016-12-31 Werner Lemberg - - */*: Use hex numbers for errors in tracing messages. - -2016-12-31 Werner Lemberg - - [truetype] Check axis count in HVAR table. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=362 - - * src/truetype/ttgxvar.c (ft_var_load_hvar): Check axis count. - (ft_var_load_avar): Fix tracing message. - - ----------------------------------------------------------------------------- - -Copyright (C) 2016-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, modified, -and distributed under the terms of the FreeType project license, -LICENSE.TXT. By continuing to use, modify, or distribute this file you -indicate that you have read the license and understand and accept it -fully. - - -Local Variables: -version-control: never -coding: utf-8 -End: diff --git a/lib/libesp32_lvgl/freetype/ChangeLog.29 b/lib/libesp32_lvgl/freetype/ChangeLog.29 deleted file mode 100644 index 251c056e5..000000000 --- a/lib/libesp32_lvgl/freetype/ChangeLog.29 +++ /dev/null @@ -1,2352 +0,0 @@ -2018-05-01 Werner Lemberg - - * Version 2.9.1 released. - ========================= - - - Tag sources with `VER-2-9-1'. - - * docs/VERSION.TXT: Add entry for version 2.9.1. - * docs/CHANGES: Updated. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - src/base/ftver.rc, builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.9/2.9.1/, s/29/291/. - - * include/freetype/freetype.h (FREETYPE_PATCH): Set to 1. - - * builds/unix/configure.raw (version_info): Set to 22:1:16. - * CMakeLists.txt (VERSION_PATCH): Set to 1. - - * include/freetype/ftgasp.h: Use FT_BEGIN_HEADER and FT_END_HEADER. - -2018-04-26 Werner Lemberg - - Another fix for handling invalid format 2 cmaps. - - Sigh. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=8003 - - * src/sfnt/ttcmap.c (tt_cmap2_char_next): Adjust condition to avoid - an endless loop. - -2018-04-24 Ben Wagner - - [base] Avoid undefined behaviour in lcd filtering code (#53727). - - * src/base/ftlcdfil.c (ft_lcd_filter_fir, _ft_lcd_filter_legacy): - Ensure `height > 0'. - -2018-04-22 Werner Lemberg - - * src/base/ftoutln.c (FT_Outline_Decompose): Improve error tracing. - -2018-04-22 Alexei Podtelezhnikov - - [base] Fix bitmap emboldening. - - Bug introduced after release 2.8. - - * src/base/ftbitmap.c (ft_bitmap_assure_buffer): We use - `FT_QALLOC_MULT', which doesn't zero out the buffer. Adjust the - bitmap copying code to take care of this fact. - -2018-04-22 Werner Lemberg - - Another fix for handling invalid format 2 cmaps. - - The previous commit was incomplete. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=7928 - - * src/sfnt/ttcmap.c (tt_cmap2_char_next): Adjust condition to avoid - an endless loop. - -2018-04-19 Werner Lemberg - - Fix handling of invalid format 2 cmaps. - - The problem was introduced after the last release. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=7828 - - * src/sfnt/ttcmap.c (tt_cmap2_char_next): Avoid endless loop. - -2018-04-17 Werner Lemberg - - [truetype] Integer overflow issues. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=7739 - - * src/truetype/ttinterp.c (Ins_CEILING): Use FT_PIX_CEIL_LONG. - -2018-04-16 Werner Lemberg - - [truetype] Integer overflow issues. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=7718 - - * src/truetype/ttinterp.c (Ins_MIRP): Use ADD_LONG. - -2018-04-15 Alexei Podtelezhnikov - - [build] Use `info' function of make 3.81. - - * configure, docs/INSTALL, docs/INSTALL.CROSS, docs/INSTALL.GNU, - docs/INSTALL.UNIX, docs/MAKEPP: Bump make version requirements. - - * builds/detect.mk (std_setup): Replace `echo' with `info'. - (dos_setup): Removed. - * builds/unix/install.mk, builds/modules.mk, builds/dos/detect.mk, - builds/windows/detect.mk, builds/os2/detect.mk: Updated. - * builds/newline: No longer needed. - -2018-04-15 Werner Lemberg - - [truetype]: Limit `SLOOP' bytecode argument to 16 bits. - - This fixes - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=7707 - - * src/truetype/ttinterp.c (Ins_SLOOP): Do it. - -2018-04-14 Werner Lemberg - - [truetype] Integer overflow issues. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=7652 - - * src/truetype/ttinterp.c (Ins_MDAP): Use SUB_LONG. - -2018-04-14 Werner Lemberg - - [autofit] Update to Unicode 11.0.0. - - But no support new scripts (volunteers welcomed). - - * src/autofit/afranges.c (af_arab_nonbase_uniranges, - af_beng_nonbase_uniranges, af_cakm_nonbase_uniranges, - af_deva_nonbase_uniranges, af_geor_uniranges, - af_gujr_nonbase_uniranges, af_mlym_nonbase_uniranges, - af_nkoo_nonbase_uniranges, af_telu_nonbase_uniranges, - af_hani_uniranges): Add new data. - -2018-04-10 Nikolaus Waxweiler - - * CMakeLists.txt, builds/cmake/FindHarfBuzz.cmake: Extensive - modernization measures. - - This brings up the minimum required CMake version to 2.8.12. - - The installation paths follow the GNU defaults now, e.g. installing on a - 64 bit host will place binaries into the lib64/ folder on e.g. Fedora. - - Symbols are hidden by default (e.g. `-fvisibility=hidden' on GCC). - - CMake will no longer look for a C++ compiler. - - Library and .so version now match the Autotools build. - - Comments in the build file and informational messages now use platform - agnostic example commands. - - ftoption.h and ftconfig.h are written directly without a redundant `-new' - copy. - - External dependencies are expressed as option()s and will turn up as such - in cmake-gui. - - Internal: Properties such as dependencies and include directories are now - privately set on the freetype library instead of globally. - - The CPack definitions have been cleaned up, the `make dist' has been - removed. Source packages generated with CPack don't contain Autotools - files and aren't used by the maintainers anyway. - - On Windows, src/base/ftver.rc is compiled to decorate the library with - version and copyright information. - - A pkg-config file is now generated and installed. - -2018-04-09 Werner Lemberg - - [truetype] Integer overflow issues. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=7453 - - * src/truetype/ttinterp.c (Round_Super, Round_Super_45): Use - ADD_LONG and SUB_LONG. - -2018-04-06 Alexei Podtelezhnikov - - [windows, wince] Clean up legacy project files. - - * builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2008-ce/freetype.vcproj, - builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2008/freetype.vcproj, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/freetype.dsp: Remove per-file compile flags. - -2018-04-04 Werner Lemberg - - [cff, type1] Sanitize `BlueFuzz' and `BlueShift'. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=7371 - - * src/cff/cffload.c (cff_load_private_dict): Sanitize - `priv->blue_shift' and `priv->blue_fuzz' to avoid overflows later - on. - - * src/type1/t1load.c (T1_Open_Face): Ditto. - -2018-04-04 Ben Wagner - - * src/truetype/ttobjs.c (trick_names): Add 3 tricky fonts (#53554), - `DFHei-Md-HK-BF', `DFKaiShu-Md-HK-BF' and `DFMing-Bd-HK-BF'. - (tt_check_trickyness_sfnt_ids): Add checksums for 3 tricky fonts - in above. - -2018-04-01 Werner Lemberg - - * builds/toplevel.mk (work): Use $(SEP). - - This fixes the `make refdoc' using Cygwin: $(CAT) is `type' on this - platform, and this program only understands backslashes in paths. - - Reported by Nikhil Ramakrishnan . - -2018-03-30 Werner Lemberg - - [truetype] Fix memory leak (only if tracing is on). - - * src/truetype/ttgxvar.c (TT_Get_MM_Var) [FT_DEBUG_LEVEL_TRACE}: Fix - it. - -2018-03-23 Ben Wagner - - [sfnt] Correctly handle missing bitmaps in sbix format (#53404). - - * src/sfnt/ttfsbit.c (tt_face_load_sbix_image): Fix return value. - -2018-03-23 Ben Wagner - - [truetype] Fix advance of empty glyphs in bitmap fonts (#53393). - - * src/truetype/ttgload.c (TT_Load_Glyph): Apply scaling to metrics - for empty bitmaps. - -2018-03-22 Werner Lemberg - - Remove `ftlcdfil.c' and `ftfntfmt.c' from build files (#53415). - - builds/amiga/makefile, builds/amiga/makefile.os4, - builds/amiga/smakefile, builds/mac/FreeType.m68k_cfm.make.txt, - builds/mac/FreeType.m68k_far.make.txt, - builds/mac/FreeType.ppc_carbon.make.txt, - builds/mac/FreeType.ppc_classic.make.txt, - builds/symbian/freetype.mmp, builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2008-ce/freetype.vcproj, - builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/freetype.vcxproj.filters, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, vms_make.com: Do it. - -2018-03-13 Werner Lemberg - - * src/sfnt/ttcmap.c (tt_cmap2_validate): Fix potential numeric - overflow. - -2018-03-13 Werner Lemberg - - Fix cmap format 2 handling (#53320). - - The patch introduced for #52646 was not correct. - - * src/sfnt/ttcmap.c (tt_cmap2_char_next): Adjust condition. - -2018-03-10 Nikolaus Waxweiler - - * CMakeLists.txt (BASE_SRCS): Update to changes from 2018-03-05. - -2018-03-09 Chun-wei Fan - - * CMakeLists.txt [win32]: Allow MSVC DLL builds (#53287). - - Do not limit DLL builds to MinGW, since we already have - `__declspec(dllexport)' directives in `ftconfig.h'. - Also suppress more warnings for POSIX functions. - -2018-03-08 Hugh McMaster - - Make installation of `freetype-config' optional (#53093). - - * builds/unix/configure.raw: Add option `--enable-freetype-config' - and set `INSTALL_FT2_CONFIG'. - * builds/unix/unix-def.in (INSTALL_FT2_CONFIG): Define. - * builds/unix/install.mk (install): Handle it. - -2018-03-05 Werner Lemberg - - Make `ftlcdfil.c' part of the `base' module. - - `ftobjs.c' needs `ft_lcd_padding'. - - Problem reported by duhuanpeng <548708880@qq.com>. - - * modules.cfg (BASE_EXTENSIONS): Don't include `ftlcdfil.c'. - - * src/base/ftbase.c: Include `ftlcdfil.c'. - * src/base/rules.mk (BASE_SRC): Add `ftlcdfil.c'. - * src/base/Jamfile (_sources): Adjusted. - - * docs/INSTALL.ANY: Updated. - -2018-03-05 Werner Lemberg - - Make `ftfntfmt.c' part of the `base' module. - - `ftobjs.c' needs `FT_Get_Font_Format'. - - Problem reported by duhuanpeng <548708880@qq.com>. - - * modules.cfg (BASE_EXTENSIONS): Don't include `ftfntfmt.c'. - - * src/base/ftbase.c: Include `ftfntfmt.c'. - * src/base/rules.mk (BASE_SRC): Add `ftfntfmt.c'. - * src/base/Jamfile (_sources): Adjusted. - - * docs/INSTALL.ANY: Updated. - -2018-03-01 Werner Lemberg - - * src/truetype/ttinterp.c (TT_RunIns): Fix tracing arguments. - -2018-02-23 Werner Lemberg - - * builds/unix/configure.raw: Need HarfBuzz 1.3.0 or newer. - - Problem reported by Alan Coopersmith . - -2018-02-17 Werner Lemberg - - [sfnt] Prefer `CBDT'/`CBLC' over `glyf' table (#53154). - -2018-02-06 Werner Lemberg - - [truetype] Integer overflow issues. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=6027 - - * src/truetype/ttinterp.c (Ins_MSIRP, Ins_MIAP, Ins_MIRP): Use - SUB_LONG; avoid FT_ABS. - -2018-02-04 Alexei Podtelezhnikov - - [unix] Use -fvisibility=hidden. - - It is now widely recommended that ELF shared libraries hide symbols - except those with explicit __attribute__((visibility("default"))). - This is supported by all major compilers and should rather be an - option in libtool. - - * builds/unix/configure.raw: Add -fvisibility=hidden to CFLAGS. - * builds/unix/ftconfig.in, builds/vms/ftconfig.h, - include/freetype/config/ftconfig.h (FT_EXPORT): Use visibility - attribute. - -2018-01-27 Werner Lemberg - - [truetype] Better protection against invalid VF data. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=5739 - - Bug introduced in commit 08cd62deedefe217f2ea50e392923ce8b5bc7ac7. - - * src/truetype/ttgxvar.c (TT_Set_Var_Design): Always initialize - `normalizedcoords'. - -2018-01-27 Werner Lemberg - - * src/truetype/ttinterp.c (Ins_GETVARIATION): Avoid NULL reference. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=5736 - -2018-01-27 Werner Lemberg - - * src/truetype/ttgxvar.c (tt_set_mm_blend): Minor. - -2018-01-27 Werner Lemberg - - [truetype] Better trace VF instances. - - * src/truetype/ttgxvar.c (ft_var_to_normalized): Don't emit number - of coordinates. - (TT_Get_MM_Var): Trace instance indices names. - (TT_Set_Var_Design): Updated. - -2018-01-27 Werner Lemberg - - [truetype] Beautify tracing of VF axis records. - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Show axis records in a - table-like manner. - -2018-01-26 Ben Wagner - - [truetype] Fix multiple calls of `FT_Get_MM_Var' (#52955). - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Set - `face->blend->num_axis' in case we have to initialize the - `face->blend'. - -2018-01-23 Alexei Podtelezhnikov - - [apinames] Anonymous version map for GNU linker. - - * src/tools/apinames.c (PROGRAM_VERSION): Set to 0.3. - (OutputFormat): Add `OUTPUT_GNU_VERMAP'. - (names_dump): Handle it. - (usage): Updated. - (main): Handle new command line flag `-wL'. - -2018-01-21 Alexei Podtelezhnikov - - [unix] Call libtool to clean up. - - * builds/unix/install.mk (clean_project_unix, distclean_project_unix): - Use libtool. - * builds/freetype.mk: Minor. - -2018-01-18 Alexei Podtelezhnikov - - * src/base/ftver.rc: Fix mingw-w64 compilation. - -2018-01-18 Alexei Podtelezhnikov - - [build] Enable VERSIONINFO resource for Cygwin/MinGW. - - * builds/unix/configure.raw: Check for resource compiler. - * builds/unix/unix-cc.in: Conditionally set up resource compiler. - * builds/freetype.mk: Add conditional rule for `ftver.rc'. - * src/base/ftver.rc: Copyright notice and year update. - -2018-01-18 Alexei Podtelezhnikov - - [build] Move VERSIONINFO resource. - - * builds/windows/vc2010/freetype.vcxproj: Updated. - * builds/windows/ftver.rc: Move file from here... - * src/base/ftver.rc: ... to here. - -2018-01-12 Alexei Podtelezhnikov - - [build] Expand dllexport/dllimport to Cygwin/MinGW. - - * include/freetype/config/ftconfig.h: Respect DLL_EXPORT, - s/_MSC_VER/_WIN32/. - * builds/unix/ftconfig.in: Replicate here. - * builds/vms/ftconfig.h: Replicate here. - -2018-01-12 Alexei Podtelezhnikov - - [build] Improve and document MSVC build. - - * include/freetype/config/ftconfig.h: Guard dllexport/dllimport - attributes with _DLL and FT2_DLLIMPORT. - * builds/windows/vc2010/index.html: Update documentation. - -2018-01-10 Steve Robinson - - * CMakeLists.txt [win32]: Suppress warnings for POSIX functions. - -2018-01-10 Ewald Hew - - [psaux] Correctly handle Flex features (#52846). - - * src/psaux/psintrp.c (cf2_interpT2CharString) : Do not move if doing Flex. - -2018-01-09 Alexei Podtelezhnikov - - * builds/windows/vc2010/freetype.sln: Synchronize with the project. - -2018-01-08 Werner Lemberg - - * Version 2.9 released. - ======================= - - - Tag sources with `VER-2-9'. - - * docs/VERSION.TXT: Add entry for version 2.9. - - * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj, - builds/windows/vc2005/index.html, - builds/windows/vc2008/freetype.vcproj, - builds/windows/vc2008/index.html, - builds/windows/vc2010/freetype.vcxproj, - builds/windows/vc2010/index.html, - builds/windows/visualc/freetype.dsp, - builds/windows/visualc/freetype.vcproj, - builds/windows/visualc/index.html, - builds/windows/visualce/freetype.dsp, - builds/windows/visualce/freetype.vcproj, - builds/windows/visualce/index.html, - builds/windows/ftver.rc, - builds/wince/vc2005-ce/freetype.vcproj, - builds/wince/vc2005-ce/index.html, - builds/wince/vc2008-ce/freetype.vcproj, - builds/wince/vc2008-ce/index.html: s/2.8.1/2.9/, s/281/29/. - - * include/freetype/freetype.h (FREETYPE_MINOR): Set to 9. - (FREETYPE_PATCH): Set to 0. - - * builds/unix/configure.raw (version_info): Set to 22:0:16. - * CMakeLists.txt (VERSION_PATCH): Set to 0. - -2018-01-07 Werner Lemberg - - Add check for librt, needed for `ftbench' (#52824). - - * builds/unix/configure.raw (LIB_CLOCK_GETTIME): Define; this will - hold `-lrt' if necessary. - - * builds/unix/unix-cc.in (LIB_CLOCK_GETTIME): New variable. - -2018-01-07 Ewald Hew - - [psaux] Fix Type 1 glyphs with too many stem hints. - - According to the CFF specification, charstrings can have up to 96 stem - hints. Due to hint replacement routines in Type 1 charstrings, some - glyphs are rejected by the Adobe engine, which implements the above - limit. This fix turns off hinting for such glyphs. - - * src/psaux/pshints.c (cf2_hintmap_build): Reset the error from calling - `cf2_hintmask_setAll' on a problematic Type 1 charstring and turn off - hinting. - -2018-01-06 Werner Lemberg - - Add `FT_Done_MM_Var'. - - This is necessary in case the application's memory routines differ - from FreeType. A typical example is a Python application on Windows - that calls FreeType compiled as a DLL via the `ctypes' interface. - - * include/freetype/ftmm.h, src/base/ftmm.c (FT_Done_MM_Var): Declare - and define. - - * docs/CHANGES: Updated. - -2018-01-03 Werner Lemberg - - [truetype] Round offsets of glyph components only if hinting is on. - - * src/truetype/ttgload.c (TT_Process_Composite_Component): Implement - it. - -2018-01-03 Werner Lemberg - - * src/truetype/ttgxvar.c (ft_var_to_design): Remove dead code. - - This is a better fix than the previous commit, which is now - reverted. - -2018-01-03 Alexei Podtelezhnikov - - Move internal LCD-related declarations. - - * include/freetype/ftlcdfil.h (ft_lcd_padding, ft_lcd_filter_fir): - Move from here... - * include/freetype/internal/ftobjs.h: ... to here. - -2018-01-03 Alexei Podtelezhnikov - - * include/freetype/config/ftconfig.h (FT_EXPORT, FT_EXPORT_DEF) - [_MSC_VER]: Limit Visual C++ attributes. - -2018-01-03 Werner Lemberg - - [truetype] Make blend/design coordinate round-tripping work. - - Behdad reported that setting blend coordinates, then getting design - coordinates did incorrectly return the default instance's - coordinates. - - * src/truetype/ttgxvar.c (tt_set_mm_blend): Fix it. - -2017-12-31 Werner Lemberg - - * src/sfnt/ttcmap.c (tt_cmap2_char_next): Fix endless loop. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=4838 - -2017-12-31 Werner Lemberg - - Synchronize other Windows project files. - - * builds/windows/*: Add missing files. - -2017-12-31 Werner Lemberg - - Update Visual C 2010 project files. - - Problem reported by Hin-Tak. - - * builds/windows/vc2010/freetype.vcxproj: Add files `ftbdf.c' and - `ftcid.c'. - Sort entries. - * builds/windows/vc2010/freetype.vcxproj.filter: Ditto. - Fix members of `FT_MODULE' group. - -2017-12-30 Werner Lemberg - - * builds/vms/ftconfig.h: Synchronize with unix `ftconfig.in' file. - -2017-12-28 Werner Lemberg - - * builds/unix/ftconfig.in: Synchronize with main `ftconfig.h' file. - - Reported by Nikolaus. - -2017-12-27 Werner Lemberg - - Fix compiler warnings. - - * src/base/ftbitmap.c (ft_bitmap_assure_buffer): Make `pitch' and - `new_pitch' unsigned. - - * src/base/ftpsprop.c: Include FT_INTERNAL_POSTSCRIPT_PROPS_H. - -2017-12-27 Werner Lemberg - - Fixes for `make multi'. - - * include/freetype/internal/ftpsprop.h: Use `FT_BASE_CALLBACK'. - (ps_property_get): Harmonize declaration with corresponding - function typedef. - - * include/freety[e/internal/fttrace.h: Add `trace_psprops'. - - * src/base/ftpsprop.c: Include necessary header files. - (FT_COMPONENT): Define. - (ps_property_set): Tag with `FT_BASE_CALLBACK_DEF'. - (ps_property_get): Tag with `FT_BASE_CALLBACK_DEF'. - Harmonize declaration with corresponding function typedef. - -2017-12-27 Werner Lemberg - - Provide support for intra-module callback functions. - - This is needed especially for `make multi' with C++. - - * include/freetype/config/ftconfig.h (FT_BASE_CALLBACK, - FT_BASE_CALLBACK_DEF): New macros. - -2017-12-25 Ewald Hew - - Move PostScript drivers' property handlers to `base'. - - This reduces the amount of duplicated code across PostScript - drivers. - - * src/cff/cffdrivr.c, src/cid/cidriver.c, src/type1/t1driver.c - ({cff,cid,t1}_property_{get,set}): Moved to... - * include/freetype/internal/ftpsprop.h: ...this new file. - (ps_property_{get,set}): New functions to replace moved ones. - - * src/base/ftpsprop.c: New file that implements above functions. - - * include/freetype/internal/internal.h - (FT_INTERNAL_POSTSCRIPT_PROPS_H): New macro. - - * src/cff/cffdrivr.c, src/cid/cidriver.c, src/type1/t1driver.c: - Updated. - - * src/base/Jamfile, src/base/rules.mk (BASE_SRC), src/base/ftbase.c: - Updated. - -2017-12-20 Werner Lemberg - - Speed up FT_Set_Var_{Design,Blend}_Coordinates if curr == new. - - We exit early if the current design or blend coordinates are - identical to the new ones. - - * src/truetype/ttgxvar.c (tt_set_mm_blend, TT_Set_Var_Design): - Implement it, returning internal error code -1 if there will be no - variation change. - - * src/type1/t1load.c (t1_set_mm_blend): Ditto. - - * src/base/ftmm.c (FT_Set_Var_Design_Coordinates, - FT_Set_MM_Blend_Coordinates, FT_Set_Var_Blend_Coordinates): Updated. - -2017-12-18 Werner Lemberg - - [sfnt] Fix charmap type 2 iterator (#52646). - - The subsetted demo font of the report that exhibits the bug has a - very unusual type 2 cmap for Unicode(!): It contains only two - sub-headers, one for one-byte characters (covering the range 0x20 to - 0xFA), and a second one for higher byte 0x01 (just for character - code U+0131). - - Before this commit, the iterator wasn't able to correctly handle a - sub-header for higher byte 0x01. - - * src/sfnt/ttcmap.c (tt_cmap2_char_next): Fix character increment - for outer loop. - -2017-12-18 Matthias Clasen - - [truetype] Fix clamping, minor tracing code beautification. - - * src/truetype/ttgxvar.c (ft_var_to_normalized): Trace number of - design coordinates. - Use clamped value. - -2017-12-18 Werner Lemberg - - * src/*/*: Only use `ft_' and `FT_' variants of stdc library stuff. - -2017-12-18 Werner Lemberg - - * src/truetype/ttgxvar.c (tt_face_vary_cvt): Add size guard (#52688). - -2017-12-18 Werner Lemberg - - [truetype] Fix previous commit. - - * src/truetype/ttgload.c (TT_Process_Simple_Glyph): Correctly handle - unhinted phantom points, which must be properly scaled. - -2017-12-18 Werner Lemberg - - [truetype] Don't apply HVAR and VVAR deltas twice (#52683). - - * src/truetype/ttgload.c (TT_Process_Simple_Glyph): Always adjust - `pp1' to `pp4', except if we have an HVAR and/or VVAR table. - - * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Handle - alternative code branch identically w.r.t. presence of an HVAR - and/or VVAR table. - -2017-12-17 Jonathan Kew - - [truetype] Correctly handle variation font phantom points (#52683). - - * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Fix phantom - point indices. - -2017-12-17 Jonathan Kew - - Fix incorrect advance width scaling (#52683). - - * src/base/ftadvance.c (FT_Get_Advances): Always respect the - FT_LOAD_NO_SCALE flag if present. - -2017-12-16 Alexei Podtelezhnikov - - * builds/windows/vc2010/freetype.vcxproj: AfterBuild copy. - * objs/.gitignore: Ignore almost everything. - -2017-12-11 Werner Lemberg - - Fix compiler warning (#52640). - - * src/base/ftbitmap.c (ft_bitmap_assure_buffer): Remove unused - variable. - -2017-12-08 Azzuro - - * builds/windows/vc2010/freetype.vcxproj: Adjust output directory. - - This allows builds with different configurations in parallel. - -2017-12-08 Werner Lemberg - - Fix `make setup dos', second try (#52622). - - * builds/detect.mk (dos_setup): Don't use literal `>' character at - all. Mixing the different escaping rules from make, dos, and - windows is too fragile. - -2017-12-08 Werner Lemberg - - [docmaker] Fix code section parsing. - - Stuff like - - { - - } - - confused the parser, which incorrectly treated `' as a markup - tag. - - * src/tools/docmaker/content.py (ContentProcessor::process_content): - Apply `re_markup_tags' only outside of code sections. - -2017-12-08 Werner Lemberg - - New `ftdriver.h' file, covering all driver modules. - - This reduces redundancy and increases synergy; it also reduces the - number of header files. - - * include/freetype/config/ftheader.h (FT_DRIVER_H): New macro. - (FT_AUTOHINTER_H, FT_CFF_DRIVER_H, FT_TRUETYPE_DRIVER_H, - FT_PCF_DRIVER_H, FT_TYPE1_DRIVER_H): Make them aliases to - FT_DRIVER_H. - - * include/freetype/ftautoh.h, include/freetype/ftcffdrv.h, - include/freetype/ftpcfdrv.h, include/freetype/ftt1drv.h, - include/freetype/ftttdrv.h: Replaced with... - * include/freetype/ftdriver.h: ...this new file. - (FT_CFF_HINTING_ADOBE, FT_T1_HINTING_ADOBE): Renamed to... - (FT_HINTING_ADOBE): ... this new macro. - (FT_CFF_HINTING_FREETYPE, FT_T1_HINTING_FREETYPE): Renamed to... - (FT_HINTING_FREETYPE): ... this new macro. - - * src/*/*: Updated accordingly. - -2017-12-08 Werner Lemberg - - Move `ftdriver.h' to `ftdrv.h'. - - * include/freetype/internal/ftdriver.h: Renamed to... - * include/freetype/internal/ftdrv.h: ... this name. - - * include/freetype/internal/internal.h (FT_INTERNAL_DRIVER_H): - Updated. - -2017-12-08 Werner Lemberg - - Fix access to uninitalized memory (#52613). - - Also reported as - - https://bugs.chromium.org/p/chromium/issues/detail?id=791317 - - * src/base/ftbitmap.c (ft_bitmap_assure_buffer): If increasing the - bitmap size needs a larger bitmap buffer, assure that the new memory - areas are initialized also. - -2017-12-08 Werner Lemberg - - Fix `make setup dos' (#52622). - - * builds/detect.mk (dos_setup): Properly escape literal `>' - character. - -2017-12-07 Werner Lemberg - - Fix C++ compilation. - - * src/psaux/psauxmod.h: Use FT_CALLBACK_TABLE macro where necessary. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Fix warning. - -2017-12-07 Werner Lemberg - - Fix `make multi'. - - * include/freetype/internal/fttrace.h: Remove unused tracing macros. - s/pshalgo2/pshalgo/. - Add `trace_cffdecode'. - * src/pshinter/pshalgo.c (FT_COMPONENT): Updated. - - * src/cff/cffload.c: Include FT_INTERNAL_POSTSCRIPT_AUX_H. - * src/cff/cffobjs.c: Include FT_SERVICE_METRICS_VARIATIONS_H and - FT_SERVICE_CFF_TABLE_LOAD_H. - - * src/cid/cidriver.c: Include FT_INTERNAL_POSTSCRIPT_AUX_H. - - * src/psaux/cffdecode.c: Include FT_FREETYPE_H and - FT_INTERNAL_DEBUG_H. - (FT_COMPONENT): Define. - * src/psaux/cffdecode.h: Include FT_INTERNAL_POSTSCRIPT_AUX_H. - * src/psaux/psauxmod.h: Include FT_INTERNAL_POSTSCRIPT_AUX_H. - Declare `cff_builder_funcs' and `ps_builder_funcs'. - * src/psaux/psft.c: Include `psobjs.h' and `cffdecode.h'. - * src/psaux/psobjs.c : Include `psauxmod.h'. - -2017-12-07 Werner Lemberg - - * include/freetype/config/ftheader.h: Some clean-up. - - This commit removes documentation of deprecated macros and does some - minor streamlining. - -2017-12-06 Werner Lemberg - - * builds/symbian/bld.inf: Updated. - -2017-12-06 Werner Lemberg - - New header file `ftparams.h' that collects all parameter tags. - - * include/freetype/config/ftheader.h (FT_PARAMETER_TAGS_H): New - macro. - (FT_TRUETYPE_UNPATENTED_H, FT_UNPATENTED_HINTING_H): Define it to - `ftparams.h'. - - * include/freetype/ftautoh.h, include/freetype/ftcffdrv.h, - include/freetype/ftincrem.h, include/freetype/ftlcdfil.h, - include/freetype/ftsnames.h, include/freetype/ftt1drv.h: Include - FT_PARAMETER_TAGS_H. - Move FT_PARAM_TAG_XXX definitions to... - * include/freetype/ftparams.h: ...this new file. - - * include/freetype/ttunpat.h: Remove. No longer needed. - -2017-12-05 Werner Lemberg - - Improve tracing messages by using singular and plural forms. - - * src/*/*.c: Implement it. - -2017-12-04 Werner Lemberg - - [truetype] Allow shared points in `cvar' table (#52532). - - * src/truetype/ttgxvar.c (tt_face_vary_cvt): Implement it by copying - and adjusting the corresponding code from - `TT_Vary_Apply_Glyph_Deltas'. - -2017-11-28 Werner Lemberg - - [truetype] Improving tracing of composite glyphs. - - * src/truetype/ttgload.c (TT_Load_Composite_Glyph) - [FT_DEBUG_LEVEL_TRACE]: Show composite glyph information. - -2017-11-27 Werner Lemberg - - [type1] Allow (again) `/Encoding' with >256 elements (#52464). - - In version 2.6.1, this has been disallowed to better reject - malformed fonts; however, this restriction was too strong. This - time, we only take the first 256 elements into account, since - encoding arrays are always accessed with a 8bit integer, according - to the PostScript Language Reference. - - * src/type1/t1load.c (parse_encoding): Implement it. - -2017-11-27 Jan Alexander Steffens (heftig) - - Fix last commit (#52522). - - * builds/freetype.mk: Set `FT_OPTION_H' and `FTOPTION_FLAG' - properly if we have `ftoption.h' in `BUILD_DIR'. - -2017-11-24 Werner Lemberg - - [unix] Install a massaged `ftoption.h' file (#51780). - - * builds/unix/configure.raw (ftoption_set, ftoption_unset): New - auxiliary functions to construct... - (FTOPTION_H_SED): ... this new variable. - Apply it as a sed argument while copying `ftoption.h' to the - `builds/unix' directory (using `AC_CONFIG_FILES'). - Simplify code of test that checks cpp's computation of bit length - (the test previously created an empty `ftoption.h' file and deleted - it immediately afterwards); without this change, it can happen on my - GNU/Linux box that `configure's execution of `config.status' doesn't - create `ftoption.h' (no idea why this happens). - - * builds/unix/install.mk (install): Install - `builds/unix/ftoption.h'. - - * builds/unix/unix-def.in (DISTCLEAN): Updated. - - * builds/unix/.gitignore: Updated. - -2017-11-23 Tor Andersson - - Silence unused function warnings (#52465). - - Some static function declarations cause unused function warnings if - certain config options are turned off via `ftoption.h'. - - * src/base/ftbase.h, src/base/ftrfork.c, src/sfnt/ttbdf.h, - src/truetype/ttgxvar.h: Add #ifdef guards around these sections. - -2017-11-22 Ewald Hew - - * src/psaux/psft.c (cf2_setGlyphWidth): Check format before setting. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=4377 - -2017-11-22 Ewald Hew - - [psaux] Fix CFF advance widths. (#52466) - - Glyph advance widths were being written to the new `PS_Decoder' but not - saved to the underlying format specific decoder. This caused pure CFF - fonts to have bad advance width. - - * include/freetype/internal/psaux.h (PS_Decoder): Change `glyph_width' - field to pointer. - Remove unused fields. - * src/psaux/psobjs.c (ps_decoder_init): Change `glyph_width' from copy - to reference. - Remove unused. - * src/psaux/psft.c (cf2_setGlyphWidth): Update code. - -2017-11-15 Vlad Tsyrklevich - - * include/freetype/ftrender.h: Fix `FT_Renderer_RenderFunc' type. - -2017-11-14 Nikolaus Waxweiler - - Use Adobe hinting engine for `light' hinting of both CFF and Type 1. - - Since Ewald Hew factored the Adobe hinting engine out of the CFF - driver code, we can now use it on Type 1 (and CID) font formats, as - both have the same hinting philosophy. - - This change activates the Adobe hinter when in LIGHT mode, and - therefore always unless explicitly asking for the auto-hinter. This - makes LIGHT behavior consistent with CFF fonts. As of this commit, - the hinting engine table looks as follows. - - LIGHT NORMAL - ------------------------- - TrueType Auto v40 - CFF Adobe Adobe - Type 1 Adobe Adobe - -2017-11-10 Yuri Levchenko - - * CMakeLists.txt: Add `DISABLE_FORCE_DEBUG_PREFIX' option. - -2017-11-06 Alexei Podtelezhnikov - - * src/base/ftobjs.c (FT_Load_Glyph): Relocate condition. - -2017-11-06 Alexei Podtelezhnikov - - * src/smooth/ftgrays.c (gray_set_cell): Fix uninitialized variables. - -2017-11-03 Ewald Hew - - [psaux] Fix PostScript interpreter rewinding in Type 1 mode. (#52251) - - The interpreter in Type 1 mode rewinds the charstring after collecting - all hints for building the initial hintmap (commit d52dd7f). However, - some charstrings use `endchar' in a final subroutine call, rewinding to - the start of that subroutine, and only a small section of the actual - glyph is drawn. - - * src/psaux/psintrp.c (cf2_interpT2CharString) : - Ensure we are on the top level charstring before rewinding. - -2017-11-03 suzuki toshiya - - [truetype] Add more tricky fonts. - - See the report by Yang Yinsen. - https://lists.gnu.org/archive/html/freetype-devel/2017-11/msg00000.html - - * src/truetype/ttobjs.c (trick_names): Add `DFGothic-EB', - `DFGyoSho-Lt', `DFHSGothic-W5', `DFHSMincho-W3' and `DFHSMincho-W7'. - (tt_check_trickyness_sfnt_ids): Add checksums for DFGothic-EB, - DFGyoSho-Lt, DFHSGothic-W5, DFHSMincho-W3 and DFHSMincho-W7. Also - add checksums for DLCLiShu and DLCHayBold which their family names - were already listed but their checksums were previously unknown. - -2017-11-01 Alexei Podtelezhnikov - - [smooth] Fix complex rendering at high ppem. - - We used to split large glyphs into horizontal bands and continue - bisecting them still horizontally if that was not enough. This is - guaranteed to fail when a single scanline cannot fit into the - rendering memory pool. Now we bisect the bands vertically so that - the smallest unit is a column of the band height, which is guranteed - to fit into memory. - - * src/smooth/ftgrays.c (gray_convert_glyph): Implement it. - -2017-10-20 Alexei Podtelezhnikov - - [smooth] Improve complex rendering at high ppem. - - At large sizes almost but not exactly horizontal segments can quickly - drain the rendering pool. This patch at least avoids filling the pool - with trivial cells. Beyond this, we can only increase the pool size. - - Reported, analyzed, and tested by Colin Fahey. - - * src/smooth/ftgrays.c (gray_set_cell): Do not record trivial cells. - -2017-10-20 Alexei Podtelezhnikov - - [base] Improve tracing in FT_Load_Glyph, FT_*_Size. - - * src/base/ftobjs.c (FT_Load_Glyph): Tag tracing messages with - function name, glyph index, and load flags. - (FT_Select_Metrics, FT_Request_Metrics): Remove all tracing. - (FT_Select_Size, FT_Request_Size): Improve tracing. - -2017-10-18 Alexei Podtelezhnikov - - [base] Improve tracing in FT_Render_Glyph. - - * src/base/ftobjs.c (FT_Render_Glyph_Internal): Add total coverage - calculations and downgrade Netpbm dump to bitmap:7. - -2017-10-15 Ewald Hew - - [cff] Fix segfault on missing `psaux' (#52218) - - * src/cff/cffload.c (cff_done_blend): Add a check for possible nullptr. - - * modules.cfg: Update dependency list. - -2017-10-15 Alexei Podtelezhnikov - - [base, cff] Fix MSVC warnings. - - * src/base/ftobjs.c (FT_New_Library): C4702: unreachable code. - (ft_glyphslot_preset_bitmap): C4244: possible loss of data. - * src/cff/cffload.c (cff_blend_doBlend): C4244: possible loss of data. - Turn `sum' into unsigned. - -2017-10-14 Alexei Podtelezhnikov - - [base] Netpbm image tracing. - - * src/base/ftobjs.c (FT_Load_Glyph): Trace bitmap size. - (FT_Render_Glyph_Internal): Trace bitmap in Netpbm format. - - * src/smooth/ftgrays.c (gray_sweep): Sweep remnants of span tracing. - -2017-10-14 Alexei Podtelezhnikov - - * builds/windows/ftdebug.c (FT_Message): Print to stderr. - * builds/wince/ftdebug.c (FT_Message): Ditto. - -2017-10-14 Behdad Esfahbod - - [afshaper] Delay creating `hb_set' objects until needed. - - In runs on Noto Naskh Arabic, this results in 89 sets created - instead of 340 before. Makes auto-hinter setup with HarfBuzz - enabled 20% to 30% faster. - - * src/autofit/afshaper.c (af_shaper_get_coverage): Implement it. - -2017-10-12 Ewald Hew - - [type1, cid] Add hinting engine switch. - - Implement property service in `type1' and `cid' drivers to allow - switching between FreeType or Adobe hinting engine when both are - available. - - * src/cid/cidriver.c (cid_property_{set,get}, cid_services), - src/type1/t1driver.c (t1_property_{set,get}, t1_services): Add - Properties service. - - * src/cid/cidobjs.c (cid_driver_init), src/type1/t1objs.c - (T1_Driver_Init): Add default property values. - -2017-10-12 Ewald Hew - - Add T1_CONFIG_OPTION_OLD_ENGINE configuration option. - - This controls whether the old Type 1 engine gets compiled into FreeType. - It is disabled by default. - - * devel/ftoption.h, include/freetype/config/ftoption.h - (T1_CONFIG_OPTION_OLD_ENGINE): New macro. - - * include/freetype/internal/psaux.h (PS_Decoder): Remove unused field. - * include/freetype/internal/psaux.h, src/cid/cidgload.c - (cid_load_glyph), src/psaux/psauxmod.c, src/psaux/psobjs.c - (ps_builder_add_point), src/psaux/t1decode.c - (t1_lookup_glyph_by_stdcharcode, t1_decoder_parse_glyph, - t1operator_seac, t1_decoder_parse_charstrings), src/psaux/t1decode.h, - src/type1/t1gload.c (T1_Parse_Glyph_And_Get_Char_String): Surround - relevant code with macro. - Minor code changes. - -2017-10-12 Ewald Hew - - Extract width parsing from Type 1 parser. - - Duplicate the fast advance width calculations from the old parser. - This is to facilitate adding options for compiling out the old parser. - - * src/psaux/t1decode.{c,h} (t1_decoder_parse_metrics): New function. - * include/freetype/internal/psaux.h (T1_Decoder_Funcs): New entry - `parse_metrics'. - * src/psaux/psauxmod.c: Set the new entry. - - * src/type1/t1gload.c (T1_Parse_Glyph_And_Get_Char_String), - src/cid/cidgload.c (cid_load_glyph): Separate - conditional for selecting engine. - -2017-10-09 Werner Lemberg - - * src/base/ftoutln.c (FT_Outline_Translate): Fix integer overflow. - - Reported as - - https://bugs.chromium.org/p/chromium/issues/detail?id=772775 - -2017-10-08 Werner Lemberg - - * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): Integer overflows. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3579 - -2017-10-07 Werner Lemberg - - [sfnt] Adjust behaviour of PS font names for variation fonts. - - * src/sfnt/sfdriver.c (sfnt_get_var_ps_name): Use a named instance's - PS name only if no variation is applied. - -2017-10-07 Werner Lemberg - - [cff, truetype] Adjust behaviour of named instances. - - This commit completely separates the interaction between named - instances and variation functions. In particular, resetting the - variation returns to the current named instance (if set) and not to - the base font. - - As a side effect, variation functions no longer change the named - instance index. - - * src/cff/cffobjs.c (cff_face_init): Use MM service's `set_instance' - function. - Also apply `MVAR' table to named instances. - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Add cast. - (tt_set_mm_blend): No longer check whether requested variation - coincides with a named instance. - (TT_Set_Var_Design): Use current named instance for default - coordinates. - * src/truetype/ttobjs.c (tt_face_init): Use `TT_Set_Named_Instance'. - -2017-10-07 Werner Lemberg - - Make `FT_Set_Named_Instance' work. - - * src/cff/cffdrivr.c (cff_set_instance): New function. - (cff_service_multi_masters): Register it. - - * src/truetype/ttgxvar.c (TT_Set_Named_Instance): New function. - * src/truetype/ttgxvar.h: Updated. - * src/truetype/ttdriver.c (tt_service_gx_multi_masters): Register - it. - - * src/type1/t1load.c (T1_Reset_MM_Blend): New function. - * src/type1/t1load.h: Updated. - * src/type1/t1driver.c (t1_service_multi_masters): Register it. - -2017-10-07 Werner Lemberg - - Make `FT_FACE_FLAG_VARIATION' work. - - * include/freetype/internal/tttypes.h (TT_Face): Remove - `is_default_instance'; this can be replaced with a combination of - `FT_IS_VARIATION' and `FT_IS_INSTANCE'. - - * src/cff/cffdrivr.c (cff_get_advances): Updated. - - * src/sfnt/sfdriver.c (sfnt_get_ps_name), src/sfnt/sfobjs.c - (sfnt_init_face): Updated. - - * src/truetype/ttdriver.c (tt_get_advances), src/truetype/ttgload.c - (TT_Process_Simple_Glyph, load_truetype_glyph, IS_DEFAULT_INSTANCE), - src/truetype/ttgxvar.c (tt_set_mm_blend): Updated. - * src/truetype/ttgxvar.c (TT_Set_MM_Blend, TT_Set_Var_Design): - Handle `FT_FACE_FLAG_VARIATION'. - - * src/type1/t1load.c (T1_Set_MM_Blend, T1_Set_MM_Design): Handle - `FT_FACE_FLAG_VARIATION'. - -2017-10-07 Werner Lemberg - - New function `FT_Set_Named_Instance'. - - No effect yet. - - * src/base/ftmm.c (FT_Set_Named_Instance): New function. - - * include/freetype/ftmm.h: Updated. - -2017-10-07 Werner Lemberg - - Add macros for checking whether a font variation is active. - - * include/freetype/freetype.h (FT_FACE_FLAG_VARIATION, - FT_IS_VARIATION): New macros. - No effect yet. - -2017-10-07 Werner Lemberg - - Add framework for setting named instance in MM service. - - * include/freetype/internal/services/svmm.h (FT_Set_Instance_Func): - New function typedef. - (MultiMasters): Add `set_instance' member. - (FT_DEFINE_SERVICE_MULTIMASTERSREC): Updated. - - * src/cff/cffdrivr.c (cff_service_multi_masters), - src/truetype/ttdriver (tt_service_gx_multi_masters), - src/type1/t1driver.c (t1_service_multi_masters): Updated. - -2017-10-07 Werner Lemberg - - [type1] Minor code shuffling. - - * src/type1/t1load.c (T1_Set_MM_Blend): Make it a wrapper of... - (t1_set_mm_blend): ...this new function. - (T1_Set_MM_Design): Use `t1_set_mm_blend'. - -2017-10-05 Werner Lemberg - - * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): Fix integer - overflow. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3539 - -2017-10-05 Werner Lemberg - - Fix compiler warnings. - - * src/cff/cffdrivr.c (cff_ps_get_font_extra): Avoid code that relies - on numeric overflow. - Add cast. - - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Fix variable - types, add cast. - -2017-10-04 John Tytgat - - [cff] Add support for `FSType'. - - * include/freetype/internal/cfftypes.h (CFF_FontRec): Add - `font_extra' entry. - - * src/cff/cffdrivr.c (cff_ps_get_font_extra): New function to - retrieve FSType info from the embedded PostScript data. - (cff_service_ps_info): Register function. - - * src/cff/cffload.c (cff_font_done): Free `font_extra'. - -2017-09-30 Alexei Podtelezhnikov - - Signedness fixes in bitmap presetting. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3514. - - * src/raster/ftrend1.c (ft_raster1_render): Explicitly signed height. - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Ditto. - * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): Explicitly unsigned - subtraction. - -2017-09-29 Alexei Podtelezhnikov - - Bitmap metrics presetting [2/2]. - - * src/base/ftobjs.c (FT_Load_Glyph): Preset the bitmap metrics when - appropriate but `FT_Render_Glyph' is not called. - * include/freetype/freetype.h (FT_GlyphSlotRec): Document the change. - -2017-09-28 Alexei Podtelezhnikov - - [smooth, raster] Miscellaneous cleanups. - - * src/raster/ftrend1.c (ft_raster1_render): Clean up the exit. - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Reduce - translations and clean up the exit. - (ft_smooth_render_lcd, ft_smooth_render_lcd): Remove unused `error'. - -2017-09-28 Ben Wagner - - [truetype] Really, really fix #52082. - - * src/truetype/ttinterp.c (Ins_MDRP): Correct conditional. - -2017-09-28 Werner Lemberg - - * src/psaux/psintrp.c (cf2_doStems): Fix integer overflow. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3510 - -2017-09-28 Ewald Hew - - * src/cid/cidgload.c (cid_slot_load_glyph): Fix memory leak. - - Reported as - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3489 - -2017-09-28 Alexei Podtelezhnikov - - Bitmap metrics presetting [1/2]. - - This mainly just extracts the code for presetting the bitmap metrics - from the monochrome, grayscale, and LCD renderers into a separate - function. - - * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): New function that - calculates prospective bitmap metrics for the given rendering mode. - * include/freetype/internal/ftobjs.h (ft_glyphslot_preset_bitmap): - Declare it. - - * src/base/ftlcdfil.c (ft_lcd_padding): New helper function that adds - padding to CBox taking into account pecularities of LCD rendering. - * include/freetype/ftlcdfil.h (ft_lcd_padding): Declare it. - - * src/raster/ftrend1.c (ft_raster1_render): Reworked to use - `ft_glyphslot_preset_bitmap'. - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Ditto. - (ft_smooth_render_lcd, ft_smooth_render_lcd): The pixel_mode setting - is moved to `ft_glyphslot_preset_bitmap'. - -2017-09-28 Ewald Hew - - [psaux] Fix compiler warning. - - * src/psaux/pshints.c (cf2_hintmap_dump): Add switch for tracing - code. - -2017-09-27 Werner Lemberg - - * src/sfnt/ttload.c (tt_face_load_font_dir): Fix compiler warning. - -2017-09-25 Werner Lemberg - - [psaux] Fix compiler warnings. - - * src/psaux/psft.c (cf2_initLocalRegionBuffer): Remove redundant - test. - - * src/psaux/psintrp.c (cf2_interpT2CharString) - : Add casts. - - * src/psaux/psobjs.c (ps_decoder_init): Add cast. - -2017-09-25 Ewald Hew - - [psaux] Minor fixes. - - * include/freetype/internal/psaux.h, src/psaux/psobjs.{c,h}: - Rearrange `ps_builder_init' arguments to conventional order. - - * src/psaux/psft.c (cf2_decoder_parse_charstrings): Add a check and - notice for `SubFont' in Type 1 mode. - -2017-09-25 Ewald Hew - - [psaux] Move `psdecode' into `psobjs'. - - As the former only contains a single procedure, move it into - `psobjs' for simplicity. Also change the parameter order to the - conventional one. - - * src/psaux/psdecode.c (ps_decoder_init): Moved to... - * src/psaux/psobjs.c: ...Here. - * src/psaux/psdecode.h, src/psaux/psobjs.h: Ditto. - - * include/freetype/internal/psaux.h (PSAux_ServiceRec): Update - `ps_decoder_init' function signature. - - * src/cff/cffgload.c, src/cid/cidgload.c, src/type1/t1gload.c: - Update calls. - - * src/psaux/psaux.c, src/psaux/psauxmod.c: Update includes. - - * src/psaux/Jamfile (_sources), src/psaux/rules.mk (PSAUX_DRV_SRC): - Update file references. - -2017-09-25 Ewald Hew - - [psaux] Fix Type 1 hinting. - - Type 1 hinting breaks sometimes when mid-charstring hints should - have been in the initial hintmap. This fix adds a preprocessing - pass that reads all hints and builds the correct initial hintmap - first, before proceeding to build the glyph outline. - - * src/psaux/psintrp.c (cf2_interpT2CharString): New - `initial_map_ready' boolean flag. - Ignore outline commands and hint changes on first pass. - : Add section to build hintmap and rewind. - -2017-09-25 Ewald Hew - - [psaux] Add tracing for hints. - - * src/psaux/pshints.c (cf2_hintmap_dump): New function. - (cf2_hintmap_insertHint): Trace incoming and inserted hints. - (cf2_hintmap_build): Dump hintmap before and after hint adjustment. - -2017-09-25 Ewald Hew - - [psaux] Minor fixes. - - * src/psaux/psintrp.c (cf2_interpT2CharString): Fix check for pop - results. - s/font->decoder/decoder/ where necessary. - : Use - offset parameter in `cf2_doStems' instead of doing correction for - left-sidebearing. - -2017-09-25 Ewald Hew - - [cid] Use the new engine. - - * src/cid/cidgload.c: Update includes. - (cid_load_glyph, cid_slot_load_glyph): Implement changes to glyph - loading code as with `type1' module. - -2017-09-25 Ewald Hew - - [cid] Add Adobe engine configuration. - - This is similar to what was done in the `type1' module. - - * src/cid/cidriver.c (t1cid_driver_class): Update declaration. - * src/cid/cidobjs.c: Include FT_TYPE1_DRIVER_H. - (cid_driver_init): Update code. - -2017-09-25 Ewald Hew - - [psaux] Change subfont synthesis for CID fonts. - - Change `t1_make_subfont' to take in the Private dict record as an - argument. This is because Type 1 and CID font records in FreeType - have this in different places. - - * src/psaux/psobjs.c (t1_make_subfont): Change `T1_Face' to - `FT_Face' so that CID is also accepted. - Take `PS_Private' as an argument and let caller figure out where the - Private dict actually is. - Update references. - - * include/freetype/internal/psaux.h, src/psaux/psobjs.h: Update - declaration. - - * src/type1/t1gload.c (T1_Parse_Glyph_And_Get_Char_String): Update - call. - -2017-09-25 Ewald Hew - - [type1] Switch to Adobe engine. - - * src/type1/t1objs.c (T1_Driver_Init): Set default to Adobe engine. - -2017-09-25 Ewald Hew - - [psaux] Extend Adobe interpreter (seac). - - This concludes the changes needed to add Type 1 support. - - * src/psaux/psintrp.c: Update includes. - (cf2_interpT2CharString) : Implement this similarly to - implied seac for CFF. - - * src/psaux/t1decode.c (t1_lookup_glyph_by_stdcharcode_ps): New - function to look up the glyph index. - - * src/psaux/psft.c (cf2_getT1SeacComponent, - cf2_freeT1SeacComponent): New functions to get the charstrings for - seac components. - - * src/psaux/t1decode.h, src/psaux/psft.h: Update declarations. - -2017-09-25 Ewald Hew - - [psaux] Extend Adobe interpreter (flex in callothersubr). - - * src/psaux/psintrp.c (cf2_interpT2CharString) - : Fix Flex feature handling (OtherSubrs 0, 1, - 2). - : Do not actually move the `glyphPath' while doing - flex. This is to avoid closing the current contour. - -2017-09-25 Ewald Hew - - [psaux] Extend Adobe interpreter (callothersubr). - - * src/psaux/psintrp.c (cf2_interpT2CharString) - : Copy code from - `t1_decoder_parse_charstrings' (in `t1decode.c'). - OtherSubr 3 (change hints) should reset the hintmask, so that the - new hints are applied. - Fix function calls and stack access. - -2017-09-25 Ewald Hew - - [psaux] Extend Adobe interpreter (pop). - - * src/psaux/psintrp.c (cf2_interpT2CharString): Change how unhandled - OtherSubr results are stored. Implement the PostScript stack using - an array. - : Ensure that the stack is not cleared after getting - `OtherSubr' results. - Fix stack access. - -2017-09-25 Ewald Hew - - [psaux] Extend Adobe interpreter (callsubr). - - * src/psaux/psintrp.c (cf2_interpT2CharString) : - Type 1 mode. - - * src/psaux/psft.c (cf2_initLocalRegionBuffer): Add Type 1 mode. - -2017-09-25 Ewald Hew - - [psaux] Extend Adobe interpreter (div, four-byte numbers). - - * src/psaux/psintrp.c (cf2_interpT2CharString) : Add - Type 1 mode. Type 1 requires large integers to be followed by - `div'; cf. `Adobe Type 1 Font Format', section 6.2. - : Push Type 1 four-byte numbers as `Int' always. This is - to ensure `div' and `callsubr' get values they can use. - -2017-09-25 Ewald Hew - - [psaux] Extend Adobe interpreter (hints). - - * src/psaux/psintrp.c (cf2_interpT2CharString) : Add correction for left sidebearing in Type 1 mode. - Allow adding hints mid-charstring. - : Translate into equivalent commands - for three normal stem hints. This requires some recalculation of - stem positions. - Correction for left sidebearing. - -2017-09-25 Ewald Hew - - [psaux] Extend Adobe interpreter (hsbw, sbw). - - * src/psaux/psintrp.c (cf2_doStems): `hsbw' or `sbw' must be the - first operation in a Type 1 charstring. - (cf2_interpT2CharString): Remove unused variables. - : `hsbw' or `sbw' - must be the first operation in a Type 1 charstring. - : Fix data access and add correction for - left sidebearing. - -2017-09-25 Ewald Hew - - [psaux] Extend Adobe interpreter (setcurrentpoint). - - * src/psaux/psintrp.c (cf2_interpT2CharString) - : Fix stack access. - -2017-09-25 Ewald Hew - - [psaux] Extend Adobe interpreter (closepath). - - * src/psaux/psintrp.c (cf2_interpT2CharString) : - Use the right builder function. We can use the `haveWidth' boolean - already present, instead of implementing `parse_state'. - -2017-09-25 Ewald Hew - - [psaux] Add Type 1 operations to Adobe CFF interpreter. - - The following Type 1 specific ops have been added (copied from - `t1decode'): - - closepath - vstem3 - hstem3 - seac - sbw - callothersubr - pop - setcurrentpoint - hsbw - - The following require a Type 1 mode, because of differences in - specification: - - hstem - vstem - vmoveto - callsubr - div - rmoveto - hmoveto - Numbers - - The subsequent commits will implement these changes and adapt - accesses of data and objects to the new interpreter. - - NOTE: Will not compile in the meantime! - - * src/psaux/psintrp.c: Add opcodes to enum. - (cf2_interpT2CharString): Copy relevant code over from - `t1_decoder_parse_charstrings' (in `t1decode.c'). - -2017-09-25 Ewald Hew - - [type1] Fixes for rendering. - - The Type 1 advance width calculation passes null for glyph slot, - etc, which can cause null pointer access in the new interpreter. - Fall back to the old one for now. - - Fix the large glyph retry code and ensure hinting and scaling flags - are set properly. - - * src/type1/t1gload.c (T1_Parse_Glyph_And_Get_Char_String): Add a - check for metrics_only. - Set the `force_scaling' flag. - (T1_Parse_Glyph): Updated. - (T1_Load_Glyph): Add `hinting' and `scaled' flags. - -2017-09-25 Ewald Hew - - [psaux] Add missing objects (2/2). - - Synthesize a `SubFont' object for Type 1 fonts. This is used in the - interpreter to access Private dict data, which are stored in - different places for Type 1 and CFF. This allows the same data to - be used in either mode. - - * src/psaux/psobjs.c (t1_make_subfont): New procedure to copy - required values to a dummy `CFF_SubFont' object. This is similar to - `cff_make_private_dict'. - * src/psaux/psobjs.h: Add the new declaration. - - * include/freetype/internal/psaux.h, src/psaux/psauxmod.c: Ditto. - Add this to the PSAux Service for future use with CID fonts. - - * src/type1/t1gload.c: Include FT_INTERNAL_CFF_TYPES_H. - (T1_Parse_Glyph_And_Get_Char_String): Add the call. - -2017-09-25 Ewald Hew - - [psaux] Add missing objects for Type 1 (1/2). - - Move `CF2_Font' instance to `PS_Decoder'. This is the context for - the interpreter and since it is currently stored in `CFF_Font', is - unavailable in Type 1 mode. - - * include/freetype/internal/psaux.h (T1_Decoder, PS_Decoder): New - `cf2_instance' field. - - * src/psaux/psdecode.c (ps_decoder_init): Copy `cf2_instance' to - `PS_Decoder'. - - * src/psaux/t1decode.c (t1_decoder_done): Add finalization code. - - * src/psaux/psft.c (cf2_decoder_parse_charstrings): Update accesses. - -2017-09-25 Ewald Hew - - Allow `type1' module to use the Adobe engine. - - Add the callback and some conditionals to switch between the two - engines. - - * include/freetype/internal/psaux.h (T1_Decoder_FuncsRec): Change - function declarations. - * src/psaux/psauxmod.c (T1_Decoder_FuncsRec): Register the - callbacks. - - * src/psaux/psobjs.c (ps_builder_add_point): Add conditionals for - number conversion. - - * src/type1/t1gload.c (T1_Parse_Glyph_And_Get_Char_String): Add code - to choose which renderer to use. - - * src/cid/cidgload.c (cid_load_glyph): Update call. - * src/base/ftobjs.c, src/psaux/psobjs.c, src/type1/t1gload.c: Update - includes. - -2017-09-25 Ewald Hew - - [type1] Add Adobe engine configuration. - - Use the previously changed PS_Driver in type1 module to store - hinting engine configuration. - - * include/freetype/ftt1drv.h: New file. - Duplicate and rename config options from CFF. - * include/freetype/config/ftheader.h (FT_TYPE1_DRIVER_H): New macro. - - * src/type1/t1driver.c (t1_driver_class): Update declaration. - * src/type1/t1objs.c: Include FT_TYPE1_DRIVER_H. - (T1_Driver_Init): Update code. - -2017-09-25 Ewald Hew - - [cff] Move and rename `CFF_Driver'. - - This is so that we can use the same hinting engine parameters for - Type 1. - - * include/freetype/internal/cffotypes.h (CFF_Driver): Rename and - move to... - * include/freetype/internal/psaux.h (PS_Driver): ...here. - - * src/cff/cffdrivr.c, src/cff/cffgload.c, src/cff/cffload.c, - src/cff/cffobjs.c, src/cff/cffobjs.h, src/psaux/psft.c, - src/psaux/psobjs.c: Update references. - -2017-09-25 Ewald Hew - - [psaux, type1] Reorganize object fields. - - Make some fields more generic, so that we can access them the same - way regardless of Type 1 or CFF. - - * include/freetype/internal/psaux.h (PS_Builder): Change `TT_Face' - to `FT_Face'. - Remove unused fields. - - * src/psaux/psft.c: Update all accesses of `PS_Builder.face'. - Add some asserts to guard against casting `T1_Face' as `TT_Face'. - - * src/type1/t1objs.h (T1_GlyphSlot): Reorder fields to follow - `CFF_GlyphSlot', so that we can pretend they are the same in the - interpreter. - - * src/psaux/psobjs.c (ps_builder_init, ps_builder_add_point): - Updated with above changes. - -2017-09-25 Ewald Hew - - [psaux] Prepare for Type 1 mode. - - Add some checks for Type 1 data passing through. - - * src/psaux/psfont.h (CF2_Font): Add `isT1' flag. - * src/psaux/psfont.c (cf2_font_setup): Skip the variations and blend - code which is not applicable for Type 1. - - * src/psaux/psft.c (cf2_decoder_parse_charstrings): Avoid accessing - `decoder->cff' in Type 1 mode. - Copy `is_t1' flag to `CF2_Font'. - -2017-09-25 Ewald Hew - - [psaux, cff] Use the new objects. - - * include/freetype/internal/psaux.h, src/psaux/psauxmod.c: Fix - switching between new and old engines. - - * src/cff/cffgload.c, src/cff/cffparse.c: Update calls. - - * src/psaux/psblues.c, src/psaux/psfont.c, src/psaux/psfont.h, - src/psaux/psft.c, src/psaux/psft.h, src/psaux/psintrp.c: Update all - to use new objects. - -2017-09-24 Ewald Hew - - [psaux] Objects for new interpreter (part 2). - - Make the new objects copy over values. They are essentially wrapper - types for the different decoders/builders. - - * include/freetype/internal/psaux.h: Update declarations. - (PS_Builder): Add `is_t1' flag. - (PS_Decoder_{Get,Free}_Glyph_Callback): Renamed to... - (CFF_Decoder_{Get,Free}_Glyph_Callback: ... this. - (PS_Decoder): Updated. - Add `t1_parse_callback' member. - (PSAux_ServiceRec): Add `ps_decoder_init' member. - - * src/psaux/psdecode.h, src/psaux/psobjs.h: Update declarations. - - * src/psaux/psdecode.c, src/psaux/psobjs.c: Implement copy with two - modes. - - * src/psaux/psauxmod.c: Add builder and decoder functions to `PSAux' - service. - -2017-09-24 Ewald Hew - - [psaux] Add objects for new interpreter. - - Introduce `PS_Decoder' and `PS_Builder' which include all fields - from either Type 1 or CFF decoders/builders. - - * include/freetype/internal/psaux.h (PS_Builder, PS_Decoder): New - structs. - - * src/psaux/psobjs.c, src/psaux/psobjs.h: Add `PS_Builder' - functions. - - * src/psaux/psdecode.c, src/psaux/psdecode.h: New files to hold - `PS_Decoder' initialization functions. - - * src/psaux/psaux.c, src/psaux/Jamfile (_sources), - src/psaux/rules.mk (PSAUX_DRV_SRC): Updated. - -2017-09-24 Ewald Hew - - [psaux] Rename files. - - Replace the `cf2' file name prefix with `ps' as the Adobe engine - will be used for both PostScript Types 1 and 2 (CFF) instead of just - CFF. - - s/cf2/ps/ for all following. - - * src/psaux/cf2*: Rename files. - * src/psaux/*: Update includes. - - * src/psaux/Jamfile (_sources), src/psaux/rules.mk (PSAUX_DRC_SRC, - PSAUX_DRV_H): Update file references. - -2017-09-24 Ewald Hew - - [psaux] Minor fix. - - Use `MultiMasters' service in `psaux' instead of a call to `cff'. - The project builds if CFF_CONFIG_OPTION_OLD_ENGINE is not defined. - - * src/psaux/cf2ft.c: Update includes. - (cf2_getNormalizedVector): Use `mm->get_var_blend' instead of - `cff_get_var_blend'. - -2017-09-24 Ewald Hew - - [psaux, cff] Move `cff_random' into `psaux' service. - - NOTE: Does not compile! - - Minor fix to allow both `cff' and `psaux' to use `cff_random'. - - * src/cff/cffload.c (cff_random): Move to... - * src/psaux/psobjs.c: Here. - * src/cff/cffload.h: Move corresponding declaration to - `src/psaux/psobjs.h'. - - * include/freetype/internal/psaux.h (PSAux_ServiceRec): Register the - function here... - * src/psaux/psauxmod.c: And here. - - * src/cff/cffload.c, src/psaux/cf2intrp.c: Update code. - -2017-09-24 Ewald Hew - - [cff] Move struct declarations to `freetype/internal'. - - NOTE: Does not compile! - - This is so that the CFF functions moved to `psaux' can access the - same structs that they need. - - * src/cff/cfftypes.h: Moved to... - * include/freetype/internal/cfftypes.h: ...Here. - - * src/cff/cffobjs.h: Moved the struct declarations to... - * include/freetype/internal/cffotypes.h: ... this new file. - - * include/freetype/internal/internal.h (FT_INTERNAL_CFF_TYPES_H, - FT_INTERNAL_CFF_OBJECT_TYPES_H): New macros. - - * src/cff/cffcmap.h, src/cff/cffdrivr.c, src/cff/cffgload.c, - src/cff/cffgload.h, src/cff/cffload.h, src/cff/cffobjs.c, - src/cff/cffobjs.h, src/cff/cffparse.h, src/psaux/psobjs.h, - include/freetype/internal/psaux.h, - include/freetype/internal/services/svcfftl.h: Update includes. - - * src/cff/rules.mk (CFF_DRV_H): Updated. - -2017-09-24 Ewald Hew - - [psaux, cff] Add new service for inter-module calls. - - NOTE: Does not compile! - - This is to allow CFF functions moved to `psaux' to call functions - declared in `src/cff/cffload.h'. - - * include/freetype/internal/services/svcfftl.h: New file, setting up - a `CFFLoad' service. - - * include/freetype/internal/ftserv.h (FT_DEFINE_SERVICEDESCREC10, - FT_DEFINE_SERVICEDESCREC): New macros. - (FT_SERVICE_CFF_TABLE_LOAD_H): New macro. - - * src/cff/cffdrivr.c, src/cff/cffpic.h: Register the new service. - - * src/cff/cfftypes.h (CFF_FontRec), src/psaux/cf2font.h - (CF2_FontRec): Add service interface. - - * src/cff/cffobjs.c, src/psaux/cf2font.c, src/psaux/cf2ft.c, - src/psaux/cf2intrp.c, src/psaux/cffdecode.c: Use the new service. - -2017-09-24 Ewald Hew - - [psaux, cff] Add callbacks for inter-module calls. - - NOTE: Does not compile! - - * include/freetype/internal/psaux.h: Add function pointer - declarations. - - * src/psaux/cffdecode.c (cff_decoder_init): Update to take in - callbacks. - * src/psaux/cffdecode.h: Ditto. - - * src/cff/cffgload.c (cff_compute_max_advance, cff_slot_load): - Update calls to pass in callbacks. - * src/psaux/cf2ft.c, src/psaux/cffdecode.c: Use them. - -2017-09-24 Ewald Hew - - [psaux, cff] Create new `PSAux' service interface entries. - - NOTE: Does not compile! - - * include/freetype/internal/psaux.h: Include - FT_INTERNAL_TRUETYPE_TYPES_H. - (CFF_Builder_FuncsRec, CFF_Decocer_FuncsRec): New function tables. - (CFF_Builder): Updated. - Fix for forward declaration. - (PSAux_ServiceRec): New field `cff_decoder_funcs'. - - * src/psaux/psauxmod.c (cff_builder_funcs, cff_decoder_funcs): New - function tables. - (PSAux_Interface): Updated. - - * include/freetype/internal/tttypes.h (TT_FaceRec): Add `psaux' - service interface. - - * src/cff/cffgload.c, src/cff/cffobjs.c, src/cff/cffparse.c: Update - function calls to use psaux service. - -2017-09-24 Ewald Hew - - [psaux, cff] Move CFF builder components into `psaux' module. - - NOTE: Does not compile! - - * src/cff/cffgload.c - (cff_builder_{init,done,add_point,add_point1,add_contour,start_point,close_contour}, - cff_check_points): Move to... - * src/psaux/psobjs.c: Here. - - * src/cff/cffgload.h: Move corresponding declarations to - `src/psaux/psobjs.h'. - - * src/cff/cffgload.h (CFF_Builder): Move struct declaration to... - * include/freetype/internal/psaux.h: Here. - -2017-09-24 Ewald Hew - - [psaux, cff] Move CFF decoder components into `psaux' module. - - NOTE: Does not compile! - - * src/cff/cffgload.c (CFF_Operator, - CFF_COUNT_{CHECK_WIDTH,EXACT,CLEAR_STACK}, cff_argument_counts, - cff_operator_seac, cff_compute_bias, - cff_lookup_glyph_by_stdcharcode, - cff_decoder_{parse_charstrings,init,prepare}): Move to... - * src/psaux/cffdecode.c: This new file. - - * src/cff/cffgload.h: Move corresponding declarations to... - * src/psaux/cffdecode.h: This new file. - - * src/cff/cffgload.h (CFF_MAX_{OPERANDS,SUBRS_CALLS,TRANS_ELEMENTS}, - CFF_Decoder_Zone, CFF_Decoder): Move declarations to... - * include/freetype/internal/psaux.h: Here. - - * src/psaux/cf2ft.h: Update include. - - * src/psaux/psaux.c, src/psaux/rules.mk (PSAUX_DRV_SRC): Update with - the new file. - -2017-09-24 Ewald Hew - - [psaux, cff] Move Adobe's engine components into `psaux' module. - - This is the first patch of a sequence to move the Type 2 charstring - processing capability from the `cff' module to the `psaux' module. - - NOTE: Does not compile! - - * src/cff/cf2*: Move these files to... - * src/psaux/cf2*: Here. - - * src/cff/Jamfile (_sources), src/cff/rules.mk (CFF_DRV_SRC, - CFF_DRV_H), src/cff/cff.c, src/cff/cffgload.c: Remove file - references. - - * src/psaux/Jamfile (_sources), src/psaux/rules.mk, src/psaux/psaux.c - (PSAUX_DRV_SRC, PSAUX_DRV_H): Add file references. - -2017-09-24 Alexei Podtelezhnikov - - Tweak per-face LCD filtering controls. - - Thing are simpler with a NULL-function pointer. - - * include/freetype/internal/ftobjs.h (FT_Face_InternalRec): New - pointer to the filter function. - (FT_LibraryRec): Remove unused `lcd_filter'. - (FT_Bitmap_LcdFilterFunc, ft_lcd_filter_fir): Move from here... - * include/freetype/ftlcdfil.h (FT_Bitmap_LcdFilterFunc, - ft_lcd_filter_fir): ... to here. - - * src/base/ftobjs.c (ft_open_face_internal): NULL-initialize the - per-face filter. - (FT_Face_Properties): Set it. - * src/smooth/ftsmooth.c (ft_smooth_render_generic): Simplify. - - * src/base/ftlcdfil.c (ft_lcd_filter_fir, FT_Libary_SetLcdFilter): - Minor. - -2017-09-24 Jonathan Kew - - [sfnt] Fix `premultiply_data' (#52092). - - * src/sfnt/pngshim.c (premultiply_data): Don't use vector extension - if we have less than 16 bytes of data. - -2017-09-24 Werner Lemberg - - [otvalid] Fix handling of ValueRecords. - - For GPOS pair positioning format 1 the description of ValueRecords - in the OpenType specification (1.8.2, from today) is wrong – the - offset has to be taken from the parent structure; in this case the - `PairSet' table. - - * src/otvalid/otvgpos.c (otv_PairSet_validate): Set `extra3'. - (otv_PairPos_validate): Adjust. - -2017-09-23 Werner Lemberg - - [otvalid] Handle `GSUB' and `GPOS' v1.1 tables. - - * src/otvalid/otvgsub.c (otv_GSUB_validate), src/otvalid/otvgpos.c - (otv_GPOS_validate): Implement it. - -2017-09-23 Werner Lemberg - - [otvalid] Update common table handling to OpenType 1.8.2. - - * src/otvalid/otvcommn.c (otv_Device_validate): Handle - VariationIndex subtable. - (otv_Lookup_validate): Handle MarkFilteringSet. - -2017-09-23 Alexei Podtelezhnikov - - [build] Windows-style DLL versioning. - - * build/windows/ftver.rc: New VERSIONINFO resource. - * build/windows/vc2010/freetype.vcxproj: Further improvements. - -2017-09-23 Ben Wagner - - [truetype] Really fix #52082. - - * src/truetype/ttinterp.c (Ins_MDRP): Correct conditional. - -2017-09-23 Werner Lemberg - - [otvalid] Handle `GDEF' v1.2 and v1.3 tables. - - No validation of variation stuff yet. - - * src/otvalid/otvgdef.c (otv_MarkGlyphSets_validate): New function. - (otv_GDEF_validate): Implement it. - -2017-09-22 Werner Lemberg - - [otvalid] Handle `BASE' v1.1 table. - - No validation of variation stuff yet. - - * src/otvalid/otvbase.c (otv_BASE_validate): Implement it. - -2017-09-22 Werner Lemberg - - [otvalid] Macros for 32bit offset support. - - * src/otvalid/otvcommn.h (OTV_OPTIONAL_TABLE32, - OTV_OPTIONAL_OFFSET32, OTV_SIZE_CHECK32): New macros. - -2017-09-21 Alexei Podtelezhnikov - - [build] Simplify Visual C++ 2010 project. - - * build/windows/vc2010/freetype.vcxproj: Remove fake singlethreaded - configurations and tweak. - -2017-09-21 Werner Lemberg - - [truetype] Integer overflow (#52082). - - * src/truetype/ttinterp.c (Ins_MDRP): Avoid FT_ABS. - -2017-09-21 Werner Lemberg - - [sfnt] Fix postscript name for default instance of variation fonts. - - Problem reported by Behdad. - - * src/sfnt/sfdriver.c (sfnt_get_ps_name): Test - `is_default_instance'. - -2017-09-21 Werner Lemberg - - [truetype] Fix `mmvar' array pointers, part 2. - - The previous commit was incomplete. - - * src/truetype/ttgxvar.c: Properly initialize sub-array offsets for - `master' also. - -2017-09-21 Werner Lemberg - - [truetype] Fix `mmvar' array pointers. - - Without this change, clang's AddressSanitizer reports many runtime - errors due to misaligned addresses. - - * src/truetype/ttgxvar.c (TT_Get_MM_Var): Use multiples of pointer - size for sub-array offsets into `mmvar'. - -2017-09-20 Werner Lemberg - - [truetype] Integer overflows. - - Changes triggered by - - https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3429 - - * src/truetype/ttinterp.c (Ins_SHPIX, Ins_DELTAP): Use NEG_LONG. - (Ins_MIAP): Use SUB_LONG. - -2017-09-19 Alexei Podtelezhnikov - - [build] Fix DLL builds in Visual C++ project. - - * build/windows/vc2010/freetype.vcxproj: Use DynamicLibrary in Debug - and Release configurations. - * include/freetype/config/ftconfig.h (FT_EXPORT, FT_EXPORT_DEF) - [_DLL]: Use Visual C++ extensions. - -2017-09-19 John Tytgat - - [cff] Fix family name logic of pure CFF fontdata (#52056). - - 1. If `FamilyName' is present in the CFF font, use this for - FT_Face's `family_name'. - 2. Otherwise, use the face name and chop off any subset prefix. - 3. If at this point FT_Face's `family_name' is set, use this - together with the full name to determine the style. - 4. Otherwise, use `CIDFontName' as FT_Face's `family_name'. - 5. If we don't have a valid style, use "Regular". - - Previously, FT_Face's `family_name' entry for pure CFF fontdata - nearly always was the fontname itself, instead of the `FamilyName' - entry in the CFF font (assuming there is one). - - * src/cff/cffobjs.c (cff_face_init) [pure_cff]: Implement it. - -2017-09-18 Alexei Podtelezhnikov - - [build] Declutter Visual C++ 2010-2017 project. - - * build/windows/vc2010/freetype.vcxproj: Use MaxSpeed (/02) - optimization for Release configuration throughout the project. - - ----------------------------------------------------------------------------- - -Copyright (C) 2017-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, modified, -and distributed under the terms of the FreeType project license, -LICENSE.TXT. By continuing to use, modify, or distribute this file you -indicate that you have read the license and understand and accept it -fully. - - -Local Variables: -version-control: never -coding: utf-8 -End: diff --git a/lib/libesp32_lvgl/freetype/LICENSE.TXT b/lib/libesp32_lvgl/freetype/LICENSE.TXT index b1def65dd..8b9ce9e2e 100644 --- a/lib/libesp32_lvgl/freetype/LICENSE.TXT +++ b/lib/libesp32_lvgl/freetype/LICENSE.TXT @@ -29,12 +29,16 @@ The contributed BDF and PCF drivers come with a license similar to that of the X Window System. It is compatible to the above two licenses (see files `src/bdf/README` and `src/pcf/README`). The same holds for the source code files `src/base/fthash.c` and -`include/freetype/internal/fthash.h`; they wer part of the BDF driver +`include/freetype/internal/fthash.h`; they were part of the BDF driver in earlier FreeType versions. The gzip module uses the zlib license (see `src/gzip/zlib.h`) which too is compatible to the above two licenses. +The files `src/autofit/ft-hb.c` and `src/autofit/ft-hb.h` contain code +taken almost verbatim from the HarfBuzz file `hb-ft.cc`, which uses +the 'Old MIT' license, compatible to the above two licenses. + The MD5 checksum support (only used for debugging in development builds) is in the public domain. diff --git a/lib/libesp32_lvgl/freetype/Makefile b/lib/libesp32_lvgl/freetype/Makefile deleted file mode 100644 index f12841709..000000000 --- a/lib/libesp32_lvgl/freetype/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# -# FreeType 2 build system -- top-level Makefile -# - - -# Copyright (C) 1996-2021 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - - -# Project names -# -PROJECT := freetype -PROJECT_TITLE := FreeType - -# The variable TOP_DIR holds the path to the topmost directory in the project -# engine source hierarchy. If it is not defined, default it to `.'. -# -TOP_DIR ?= . - -# The variable OBJ_DIR gives the location where object files and the -# FreeType library are built. -# -OBJ_DIR ?= $(TOP_DIR)/objs - - -include $(TOP_DIR)/builds/toplevel.mk - -# EOF diff --git a/lib/libesp32_lvgl/freetype/README b/lib/libesp32_lvgl/freetype/README index faad25133..cd4c1d7d1 100644 --- a/lib/libesp32_lvgl/freetype/README +++ b/lib/libesp32_lvgl/freetype/README @@ -1,4 +1,4 @@ -FreeType 2.10.4 +FreeType 2.13.2 =============== Homepage: https://www.freetype.org @@ -16,7 +16,9 @@ Read the files `docs/INSTALL*` for installation instructions; see the file `docs/LICENSE.TXT` for the available licenses. For using FreeType's git repository instead of a distribution bundle, -please read file `README.git`. +please read file `README.git`. Note that you have to actually clone +the repository; using a snapshot will not work (in other words, don't +use gitlab's 'Download' button). The FreeType 2 API reference is located in directory `docs/reference`; use the file `index.html` as the top entry point. [Please note that @@ -30,9 +32,9 @@ sites. Go to and download one of the following files. - freetype-doc-2.10.4.tar.xz - freetype-doc-2.10.4.tar.gz - ftdoc2104.zip + freetype-doc-2.13.2.tar.xz + freetype-doc-2.13.2.tar.gz + ftdoc2132.zip To view the documentation online, go to @@ -88,12 +90,11 @@ Details on the process can be found here: Enjoy! - The FreeType Team ---------------------------------------------------------------------- -Copyright (C) 2006-2021 by +Copyright (C) 2006-2023 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/README.git b/lib/libesp32_lvgl/freetype/README.git index b8ba9b4c3..117d74f0d 100644 --- a/lib/libesp32_lvgl/freetype/README.git +++ b/lib/libesp32_lvgl/freetype/README.git @@ -1,5 +1,9 @@ README.git ----------- +========== + + +repository issues +----------------- FreeType's official repository site is @@ -23,7 +27,10 @@ digit '2' for historical reasons. freetype-demos -The git archive doesn't contain pre-built configuration scripts for +standard builds with `configure` +-------------------------------- + +The git repository doesn't contain pre-built configuration scripts for UNIXish platforms. To generate them say sh autogen.sh @@ -38,54 +45,51 @@ The versions given in parentheses are known to work. Newer versions should work too, of course. Note that `autogen.sh` also sets up proper file permissions for the `configure` and auxiliary scripts. -The `autogen.sh` script now checks the versions of the above three -packages whether they match the numbers above. Otherwise it will -complain and suggest either upgrading or using an environment variable -to point to a more recent version of the required tool(s). +The `autogen.sh` script checks whether the versions of the above three +tools match the numbers above. Otherwise it will complain and suggest +either upgrading or using environment variables to point to more +recent versions of the required tools. Note that `aclocal` is provided by the 'automake' package on Linux, and that `libtoolize` is called `glibtoolize` on Darwin (OS X). +alternative build methods +------------------------- + For static builds that don't use platform-specific optimizations, no configure script is necessary at all; saying make setup ansi make -should work on all platforms that have GNU `make` (or `makepp`). -Similarly, a build with `cmake` or `meson` can be done directly from -the git repository. +should work on all platforms that have GNU `make` (or `makepp`). + +A build with `cmake` or `meson` can be done directly from the git +repository. However, if you want to use the `FT_DEBUG_LOGGING` macro +(see file `docs/DEBUG` for more information) it is currently mandatory +to execute `autogen.sh` in advance; this script clones the 'dlg' git +submodule and copies some files into FreeType's source tree. -For using the `FT_DEBUG_LOGGING` macro while debugging (see file -`docs/DEBUG` for more information) the following git commands are -necessary to check out the 'dlg' library as a git submodule. +Code of Conduct +--------------- - git submodule init - git submodule update +Please note that this project is released with a Contributor Code of +Conduct (CoC). By participating in this project you agree to abide by +its terms, which you can find in the following link: + https://www.freedesktop.org/wiki/CodeOfConduct -If you want to contribute to FreeType it is recommended to install the -`git-merge-changelog` program – we use a `ChangeLog` file, which often -prevents simple merging due to conflicts. Most GNU/Linux -distributions have a package for this program; otherwise you can -install it via the 'gnulib' git repository. Detailed instructions can -be found at the beginning of - - https://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/git-merge-changelog.c - -To make it actually work, add to file `.git/config` in the FreeType -git repository (or to your `$HOME/.gitconfig` file) the lines - - [merge "merge-changelog"] - name = GNU-style ChangeLog merge driver - driver = /usr/local/bin/git-merge-changelog %O %A %B +CoC issues may be raised to the project maintainers at the following +address: + wl@gnu.org + apodtele@gmail.com ---------------------------------------------------------------------- -Copyright (C) 2005-2021 by +Copyright (C) 2005-2023 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/devel/ft2build.h b/lib/libesp32_lvgl/freetype/devel/ft2build.h index 41adefc23..82fdb30f6 100644 --- a/lib/libesp32_lvgl/freetype/devel/ft2build.h +++ b/lib/libesp32_lvgl/freetype/devel/ft2build.h @@ -4,7 +4,7 @@ * * FreeType 2 build and setup macros (development version). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -32,7 +32,6 @@ #define FT_CONFIG_MODULES_H #define FT_CONFIG_OPTIONS_H -#define FT_CONFIG_STANDARD_LIBRARY_H #include diff --git a/lib/libesp32_lvgl/freetype/devel/ftmodule.h b/lib/libesp32_lvgl/freetype/devel/ftmodule.h index da826d9a3..2fa130f3e 100644 --- a/lib/libesp32_lvgl/freetype/devel/ftmodule.h +++ b/lib/libesp32_lvgl/freetype/devel/ftmodule.h @@ -25,6 +25,6 @@ FT_USE_MODULE( FT_Driver_ClassRec, tt_driver_class ) // FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class ) FT_USE_MODULE( FT_Module_Class, sfnt_module_class ) FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class ) -// FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class ) +FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class ) /* EOF */ diff --git a/lib/libesp32_lvgl/freetype/devel/ftoption.h b/lib/libesp32_lvgl/freetype/devel/ftoption.h index 8ae198c22..b306335e7 100644 --- a/lib/libesp32_lvgl/freetype/devel/ftoption.h +++ b/lib/libesp32_lvgl/freetype/devel/ftoption.h @@ -1,10 +1,10 @@ /**************************************************************************** * - * ftoption.h + * ftoption.h (for development) * * User-selectable configuration macros (specification only). * - * Copyright (C) 1996-2021 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -15,6 +15,7 @@ * */ + #ifndef FTOPTION_H_ #define FTOPTION_H_ @@ -104,8 +105,7 @@ FT_BEGIN_HEADER * * ``` * FREETYPE_PROPERTIES=truetype:interpreter-version=35 \ - * cff:no-stem-darkening=1 \ - * autofitter:warping=1 + * cff:no-stem-darkening=1 * ``` * */ @@ -219,6 +219,10 @@ FT_BEGIN_HEADER * If you use a build system like cmake or the `configure` script, * options set by those programs have precedence, overwriting the value * here with the configured one. + * + * If you use the GNU make build system directly (that is, without the + * `configure` script) and you define this macro, you also have to pass + * `SYSTEM_ZLIB=yes` as an argument to make. */ /* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */ @@ -457,9 +461,9 @@ FT_BEGIN_HEADER * while compiling in 'release' mode): * * ``` - * _af_debug_disable_horz_hints - * _af_debug_disable_vert_hints - * _af_debug_disable_blue_hints + * af_debug_disable_horz_hints_ + * af_debug_disable_vert_hints_ + * af_debug_disable_blue_hints_ * ``` * * Additionally, the following functions provide dumps of various @@ -476,7 +480,7 @@ FT_BEGIN_HEADER * As an argument, they use another global variable: * * ``` - * _af_debug_hints + * af_debug_hints_ * ``` * * Please have a look at the `ftgrid` demo program to see how those @@ -520,7 +524,21 @@ FT_BEGIN_HEADER * * More details can be found in the files `ftmoderr.h` and `fterrors.h`. */ -/* #undef FT_CONFIG_OPTION_USE_MODULE_ERRORS */ +#undef FT_CONFIG_OPTION_USE_MODULE_ERRORS + + + /************************************************************************** + * + * OpenType SVG Glyph Support + * + * Setting this macro enables support for OpenType SVG glyphs. By + * default, FreeType can only fetch SVG documents. However, it can also + * render them if external rendering hook functions are plugged in at + * runtime. + * + * More details on the hooks can be found in file `otsvg.h`. + */ +// #define FT_CONFIG_OPTION_SVG /************************************************************************** @@ -566,12 +584,12 @@ FT_BEGIN_HEADER /************************************************************************** * * Define `TT_CONFIG_OPTION_POSTSCRIPT_NAMES` if you want to be able to - * load and enumerate the glyph Postscript names in a TrueType or OpenType + * load and enumerate Postscript names of glyphs in a TrueType or OpenType * file. * - * Note that when you do not compile the 'psnames' module by undefining the - * above `FT_CONFIG_OPTION_POSTSCRIPT_NAMES`, the 'sfnt' module will - * contain additional code used to read the PS Names table from a font. + * Note that if you do not compile the 'psnames' module by undefining the + * above `FT_CONFIG_OPTION_POSTSCRIPT_NAMES` macro, the 'sfnt' module will + * contain additional code to read the PostScript name table from a font. * * (By default, the module uses 'psnames' to extract glyph names.) */ @@ -643,36 +661,12 @@ FT_BEGIN_HEADER * not) instructions in a certain way so that all TrueType fonts look like * they do in a Windows ClearType (DirectWrite) environment. See [1] for a * technical overview on what this means. See `ttinterp.h` for more - * details on the LEAN option. + * details on this option. * - * There are three possible values. - * - * Value 1: - * This value is associated with the 'Infinality' moniker, contributed by - * an individual nicknamed Infinality with the goal of making TrueType - * fonts render better than on Windows. A high amount of configurability - * and flexibility, down to rules for single glyphs in fonts, but also - * very slow. Its experimental and slow nature and the original - * developer losing interest meant that this option was never enabled in - * default builds. - * - * The corresponding interpreter version is v38. - * - * Value 2: - * The new default mode for the TrueType driver. The Infinality code - * base was stripped to the bare minimum and all configurability removed - * in the name of speed and simplicity. The configurability was mainly - * aimed at legacy fonts like 'Arial', 'Times New Roman', or 'Courier'. - * Legacy fonts are fonts that modify vertical stems to achieve clean - * black-and-white bitmaps. The new mode focuses on applying a minimal - * set of rules to all fonts indiscriminately so that modern and web - * fonts render well while legacy fonts render okay. - * - * The corresponding interpreter version is v40. - * - * Value 3: - * Compile both, making both v38 and v40 available (the latter is the - * default). + * The new default mode focuses on applying a minimal set of rules to all + * fonts indiscriminately so that modern and web fonts render well while + * legacy fonts render okay. The corresponding interpreter version is v40. + * The so-called Infinality mode (v38) is no longer available in FreeType. * * By undefining these, you get rendering behavior like on Windows without * ClearType, i.e., Windows XP without ClearType enabled and Win9x @@ -687,9 +681,7 @@ FT_BEGIN_HEADER * [1] * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */ -/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */ -#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2 -/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING ( 1 | 2 ) */ +#define TT_CONFIG_OPTION_SUBPIXEL_HINTING /************************************************************************** @@ -721,12 +713,30 @@ FT_BEGIN_HEADER // #define TT_CONFIG_OPTION_GX_VAR_SUPPORT + /************************************************************************** + * + * Define `TT_CONFIG_OPTION_NO_BORING_EXPANSION` if you want to exclude + * support for 'boring' OpenType specification expansions. + * + * https://github.com/harfbuzz/boring-expansion-spec + * + * Right now, the following features are covered: + * + * - 'avar' version 2.0 + * + * Most likely, this is a temporary configuration option to be removed in + * the near future, since it is assumed that eventually those features are + * added to the OpenType standard. + */ +/* #define TT_CONFIG_OPTION_NO_BORING_EXPANSION */ + + /************************************************************************** * * Define `TT_CONFIG_OPTION_BDF` if you want to include support for an * embedded 'BDF~' table within SFNT-based bitmap formats. */ -// #define TT_CONFIG_OPTION_BDF +#define TT_CONFIG_OPTION_BDF /************************************************************************** @@ -790,7 +800,7 @@ FT_BEGIN_HEADER * into an existing face. Note that if set, the Type~1 driver will be * unable to produce kerning distances. */ -/* #undef T1_CONFIG_OPTION_NO_AFM */ +// #undef T1_CONFIG_OPTION_NO_AFM /************************************************************************** @@ -798,7 +808,7 @@ FT_BEGIN_HEADER * Define this configuration macro if you want to prevent the compilation * of the Multiple Masters font support in the Type~1 driver. */ -/* #undef T1_CONFIG_OPTION_NO_MM_SUPPORT */ +// #undef T1_CONFIG_OPTION_NO_MM_SUPPORT /************************************************************************** @@ -808,7 +818,7 @@ FT_BEGIN_HEADER * switch between the two engines using the `hinting-engine` property of * the 'type1' driver module. */ -/* #define T1_CONFIG_OPTION_OLD_ENGINE */ +// #define T1_CONFIG_OPTION_OLD_ENGINE /*************************************************************************/ @@ -850,7 +860,7 @@ FT_BEGIN_HEADER * between the two engines using the `hinting-engine` property of the 'cff' * driver module. */ -/* #define CFF_CONFIG_OPTION_OLD_ENGINE */ +// #define CFF_CONFIG_OPTION_OLD_ENGINE /*************************************************************************/ @@ -877,7 +887,7 @@ FT_BEGIN_HEADER * If this option is activated, it can be controlled with the * `no-long-family-names` property of the 'pcf' driver module. */ -/* #define PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ +// #define PCF_CONFIG_OPTION_LONG_FAMILY_NAMES /*************************************************************************/ @@ -908,24 +918,6 @@ FT_BEGIN_HEADER #endif - /************************************************************************** - * - * Compile 'autofit' module with warp hinting. The idea of the warping - * code is to slightly scale and shift a glyph within a single dimension so - * that as much of its segments are aligned (more or less) on the grid. To - * find out the optimal scaling and shifting value, various parameter - * combinations are tried and scored. - * - * You can switch warping on and off with the `warping` property of the - * auto-hinter (see file `ftdriver.h` for more information; by default it - * is switched off). - * - * This experimental option is not active if the rendering mode is - * `FT_RENDER_MODE_LIGHT`. - */ -// #define AF_CONFIG_OPTION_USE_WARPER - - /************************************************************************** * * Use TrueType-like size metrics for 'light' auto-hinting. @@ -959,21 +951,14 @@ FT_BEGIN_HEADER /* - * The next three macros are defined if native TrueType hinting is + * The next two macros are defined if native TrueType hinting is * requested by the definitions above. Don't change this. */ #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER #define TT_USE_BYTECODE_INTERPRETER - #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING -#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 1 -#define TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY -#endif - -#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 2 #define TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL #endif -#endif #endif @@ -1020,8 +1005,8 @@ FT_BEGIN_HEADER #error "Invalid CFF darkening parameters!" #endif -FT_END_HEADER +FT_END_HEADER #endif /* FTOPTION_H_ */ diff --git a/lib/libesp32_lvgl/freetype/docs/CHANGES b/lib/libesp32_lvgl/freetype/docs/CHANGES deleted file mode 100644 index 3bd5291ae..000000000 --- a/lib/libesp32_lvgl/freetype/docs/CHANGES +++ /dev/null @@ -1,5317 +0,0 @@ -CHANGES BETWEEN 2.10.3 and 2.10.4 - - I. IMPORTANT BUG FIXES - - - A heap buffer overflow has been found in the handling of embedded - PNG bitmaps, introduced in FreeType version 2.6. - - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-15999 - - If you use option FT_CONFIG_OPTION_USE_PNG you should upgrade - immediately. - - -====================================================================== - -CHANGES BETWEEN 2.10.2 and 2.10.3 - - I. IMPORTANT CHANGES - - - New flag `FT_OUTLINE_OVERLAP'. If set, make the smooth rasterizer - do 4x4 oversampling to mitigate artifacts in pixels partially - covered by overlapping contours. Note that this at least - quadruples the rendering time. - - If a glyph in a TrueType font has the `OVERLAP_SIMPLE' or - `OVERLAP_COMPOUND' bit set, FreeType automatically selects this - rendering mode. - - - II. MISCELLANEOUS - - - Using the arcane method of including FreeType header files with - macros like `FT_FREETYPE_H' is no longer mandatory (but retained - as an optional feature for backward compatibility). - - - Support for building the library with Meson. Building the demo - programs with Meson will follow in a forthcoming release. - - - Minor improvements to the B/W rasterizer. - - - Auto-hinter support for Medefaidrin script. - - - Fix various memory leaks (mainly for CFF) and other issues that - might cause crashes in rare circumstances. - - - Jam support has been removed. - - - In `ftview', custom LCD filter values are now normalized and - balanced. Unorthodox filters are still available through the `-L' - command line option. - - - The GUI demo programs can now be resized. - - - Demo programs that accept command line option `-k' can now handle - function keys, too. The corresponding character codes start with - 0xF1. As an example, the POSIX shell syntax (accepted by bash, - ksh, and zsh) - - -k $'\xF3q' - - emulates the pressing of function key `F3' followed by key `q'. - - -====================================================================== - -CHANGES BETWEEN 2.10.1 and 2.10.2 - - I. IMPORTANT CHANGES - - - Support of WOFF2 fonts. This code contribution was Nikhil - Ramakrishnan's GSoC 2019 project. - - - II. MISCELLANEOUS - - - Function `FT_Get_Var_Axis_Flags' returned random data for Type 1 - MM fonts. - - - Type 1 fonts with non-integer metrics are now supported by the new - (CFF) engine introduced in FreeType 2.9. - - - Drop support for Python 2 in Freetype's API reference generator - `docwriter' (Python >= 3.5 is required for targets `make refdoc' - and `make refdoc-venv'). - - - Auto-hinter support for Hanifi Rohingya. - - - Document the `FT2_KEEP_ALIVE' debugging environment variable. - - - The Visual C++ (and Visual C) project files for Windows builds no - longer generate libraries that contain the FreeType version in its - filenames. Instead, a resource file gets used to make the - libraries contain the corresponding information. - - - The next release will remove Jam build support. - - - The `ftbench' demo program has a new test for testing the - `FT_Glyph_Stroke' functionality. - - -====================================================================== - -CHANGES BETWEEN 2.10.0 and 2.10.1 - - I. IMPORTANT BUG FIXES - - - The bytecode hinting of OpenType variation fonts was flawed, since - the data in the `CVAR' table wasn't correctly applied. - - - II. MISCELLANEOUS - - - Auto-hinter support for Mongolian. - - - For distribution, `.tar.bz2' packages are replaced with `.tar.xz' - bundles. - - - The handling of the default character in PCF fonts as introduced - in version 2.10.0 was partially broken, causing premature abortion - of charmap iteration for many fonts. - - - If `FT_Set_Named_Instance' was called with the same arguments - twice in a row, the function returned an incorrect error code the - second time. - - - Direct rendering using FT_RASTER_FLAG_DIRECT crashed (bug - introduced in version 2.10.0). - - - Increased precision while computing OpenType font variation - instances. - - - The flattening algorithm of cubic Bezier curves was slightly - changed to make it faster. This can cause very subtle rendering - changes, which aren't noticeable by the eye, however. - - - The auto-hinter now disables hinting if there are blue zones - defined for a `style' (i.e., a certain combination of a script and - its related typographic features) but the font doesn't contain any - characters needed to set up at least one blue zone. - - - The `ftmulti' demo program now supports multiple hidden axes with - the same name tag. - - - `ftview', `ftstring', and `ftgrid' got a `-k' command line option - to emulate a sequence of keystrokes at start-up. - - - `ftview', `ftstring', and `ftgrid' now support screen dumping to a - PNG file. - - - The bytecode debugger, `ttdebug', now supports variation TrueType - fonts; a variation font instance can be selected with the new `-d' - command line option. - - -====================================================================== - -CHANGES BETWEEN 2.9.1 and 2.10.0 - - I. IMPORTANT CHANGES - - - A bunch of new functions has been added to access and process - COLR/CPAL data of OpenType fonts with color-layered glyphs. - - FT_Palette_Data_Get - Retrieve color palette data. - FT_Palette_Select - Select and activate a color palette for color-layered - glyphs. - FT_Palette_Set_Foreground_Color - Set text foreground color for palette index 0xFFFF. - - FT_Get_Color_Glyph_Layer - Get color layers for a given glyph (using an interator - object). - - FT_Bitmap_Blend - Blend one bitmap onto another with a given color. - - - An experimental feature is the new behaviour of the - `FT_LOAD_COLOR' load flag for color-layered glyphs: Internally - it sets a flag so that if `FT_Render_Glyph' is called with - `FT_RENDER_MODE_NORMAL' (or `FT_Load_Glyph' with - `FT_LOAD_RENDER'), a default blending of the color glyph layers - will happen automatically for convenience. - - - As a GSoC 2018 project, Nikhil Ramakrishnan completely - overhauled and modernized the API reference. - - - II. MISCELLANEOUS - - - The logic for computing the global ascender, descender, and - height of OpenType fonts has been slightly adjusted for - consistency. - - . If the `useTypoMetrics' flag (i.e., bit 7 in the `fsSelection' - field) in the `OS/2' table is set, use the `sTypo' fields in - `OS/2' unconditionally. - . Otherwise use the metrics data from the `hhea' table (if not - zero). - . Otherwise use the `sTypo' fields from the `OS/2' table (if not - zero). - . Otherwise use the `usWin' data from the `OS/2' table as a last - resort. - - Variable fonts will apply the `MVAR' deltas to whichever metrics - were picked. - - - `TT_Set_MM_Blend' could fail if call repeatedly with the same - arguments. - - - The precision of handling deltas in Variation Fonts has been - increased. The problem did only show up with multidimensional - designspaces. - - - New function `FT_Library_SetLcdGeometry' to set up the geometry - of LCD subpixels. - - - FreeType now uses the `defaultChar' property of PCF fonts to set - the glyph for the undefined character at glyph index 0 (as - FreeType already does for all other supported font formats). As - a consequence, the order of glyphs of a PCF font if accessed - with FreeType can be different now compared to previous - versions. - - This change doesn't affect PCF font access with cmaps. - - - `FT_Select_Charmap' has been changed to allow parameter value - `FT_ENCODING_NONE', which is valid for BDF, PCF, and Windows FNT - formats to access built-in cmaps that don't have a predefined - `FT_Encoding' value. - - - A previously reserved field in the `FT_GlyphSlotRec' structure - now holds the glyph index. - - - On Win32 platforms, the use of `_DLL' to build the library has - been replaced with `DLL_EXPORT' and `DLL_IMPORT'. - - - The usual round of fuzzer bug fixes to better reject malformed - fonts. - - - `FT_Outline_New_Internal' and `FT_Outline_Done_Internal' have - been removed. These two functions were public by oversight only - and were never documented. - - - A new function `FT_Error_String' returns descriptions of error - codes if configuration macro FT_CONFIG_OPTION_ERROR_STRINGS is - defined. - - - `FT_Set_MM_WeightVector' and `FT_Get_MM_WeightVector' are new - functions limited to Adobe MultiMaster fonts to directly set and - get the weight vector. - - - Support for Position Independent Code as needed by systems that - prohibit automatic address fixups, such as BREW, has been - removed. [Compilation with modern compilers that use flags like - `-fPIC' or `-fPIE' is not affected.] - - - The `ftdump' demo program has new options `-c' and `-C' to - display charmaps in compact and detailed format, respectively. - Option `-V' has been removed. - - - The `ftview', `ftstring', and `ftgrid' demo programs use a new - command line option `-d' to specify the program window's width, - height, and color depth. - - - The `ftview' demo program now displays red boxes for zero-width - glyphs. - - - `ftglyph' has limited support to display fonts with - color-layered glyphs. This will be improved later on. - - - `ftgrid' can now display bitmap fonts also. - - - The `ttdebug' demo program has a new option `-f' to select a - member of a TrueType collection (TTC). - - - Other various improvements to the demo programs. - - -====================================================================== - -CHANGES BETWEEN 2.9 and 2.9.1 - - I. IMPORTANT BUG FIXES - - - Type 1 fonts containing flex features were not rendered - correctly (bug introduced in version 2.9). - - - CVE-2018-6942: Older FreeType versions can crash with certain - malformed variation fonts. - - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-6942 - - - II. MISCELLANEOUS - - - Bug fix: Multiple calls to `FT_Get_MM_Var' returned garbage. - - - The base extensions `ftlcdfil' and `ftfntfmt' are now part of - the base module (and thus no longer configurable in file - `modules.cfg'). - - - Emboldening of bitmaps didn't work correctly sometimes, showing - various artifacts (bug introduced in version 2.8.1). - - - Use of the `freetype-config' script to get compilation and - linking options is deprecated since it doesn't support - cross-compiling, among other deficiencies. Instead, you should - use the `pkg-config' interface. - - The `configure' script no longer installs `freetype-config' by - default. For backward compatibility, a new configure option - `--enable-freetype-config' is provided that reverts this - decision. - - - The auto-hinter script ranges have been updated for Unicode 11. - No support for new scripts have been added, however, with the - exception of Georgian Mtavruli. - - - Support for cmake has been improved. - - - The next release will remove support for Position Independent - Code as needed by systems that prohibit automatic address - fixups, such as BREW. [Compilation with modern compilers that - use flags like `-fPIC' or `-fPIE' is not affected.] - - -====================================================================== - -CHANGES BETWEEN 2.8.1 and 2.9 - - I. IMPORTANT BUG FIXES - - - Advance width values of variation fonts were often wrong. - - - More fixes for variation font support; you should update to this - version if you want to support them. - - - II. IMPORTANT CHANGES - - - As a GSoC project, Ewald Hew extended the new (Adobe) CFF engine - to handle Type 1 fonts also, thus greatly improving the - rendering of this format. This is the new default. The old - engine is still available if the configuration macro - `T1_CONFIG_OPTION_OLD_ENGINE' gets defined; using the - `hinting-engine' property of the `type1' driver module you can - then switch between the two engines. - - - A new function, `FT_Set_Named_Instance', can be used to set or - change the current named instance. - - - Starting with this FreeType version, resetting variation - coordinates will return to the currently selected named - instance. Previously, FreeType returned to the base font (i.e., - no instance set). - - - III. MISCELLANEOUS - - - The `face_flags' field of the `FT_Face' structure has a new bit, - `FT_FACE_FLAG_VARIATION', which is set if a variation font has - been altered with `FT_Set_MM_Design_Coordinates', - `FT_Set_Var_Design_Coordinates', or - `FT_Set_Var_Blend_Coordinates'. - - - If the current face is a named instance, the new macro - `FT_IS_NAMED_INSTANCE' returns true. - - - `FT_IS_VARIATION' is a new macro that returns true whenever a - face object has been altered by `FT_Set_MM_Design_Coordinates', - `FT_Set_Var_Design_Coordinates', or - `FT_Set_Var_Blend_Coordinates'. - - - Changing the design coordinates of a variation font with - `FT_Set_Var_Design_Coordinates' or - `FT_Set_Var_Blend_Coordinates' does not influence the named - instance index value (only `FT_Set_Named_Instance' does that). - - - Special PostScript names for named instances are only returned - if the named instance is set with `FT_Set_Named_Instance' (and - the font has corresponding entries in its `fvar' table). If - `FT_IS_VARIATION' returns true, the algorithmically derived - PostScript name is provided, not looking up special entries for - named instances. - - - A new function `FT_Done_MM_Var' is provided to free the memory - returned in a call to `FT_Get_MM_Var'. - - - On platforms using the `configure' script, the installed - `ftoption.h' file now correctly reflects configuration options - like `--with-harfbuzz'. - - - Better support to build FreeType as a DLL on Windows using - Visual C. - - - All data specific to driver modules is now collected in a single - file, `FT_DRIVER_H'. Consequently, the macros - `FT_AUTOHINTER_H', `FT_CFF_DRIVER_H', `FT_TRUETYPE_DRIVER_H', - and `FT_PCF_DRIVER_H' still work but are deprecated. - - - Some fuzzer fixes to better reject malformed fonts. - - - The `ftbench' demo program has a new test for opening a new face - and loading some glyphs. - - - The `ftbench' demo program has a new option `-j' to specify the - last glyph index to be used in the tests. - - - The `ftgrid' demo program has a new option `-n' to suppress - display of named instances of variation fonts. - - - The `ttdebug' demo program can now show a stack trace (key `K') - and switch between hexadecimal and decimal display of integers - (key `I'). - - -====================================================================== - -CHANGES BETWEEN 2.8 and 2.8.1 - - I. IMPORTANT BUG FIXES - - - B/W hinting of TrueType fonts didn't work properly if - interpreter version 38 or 40 was selected. - - - Some severe problems within the handling of TrueType Variation - Fonts were found and fixed. - - - Function `FT_Set_Var_Design_Coordinates' didn't correctly handle - the case with less input coordinates than axes. - - - II. IMPORTANT CHANGES - - - By default, FreeType now offers high quality LCD-optimized - output without resorting to ClearType techniques of resolution - tripling and filtering. In this method, called Harmony, each - color channel is generated separately after shifting the glyph - outline, capitalizing on the fact that the color grids on LCD - panels are shifted by a third of a pixel. This output is - indistinguishable from ClearType with a light 3-tap filter. - - - III. MISCELLANEOUS - - - Using the new function `FT_Get_Var_Axis_Flags', an application - can access the `flags' field of a variation axis (introduced in - OpenType version 1.8.2) - - - More sanity checks. - - - The internal representation of buffers for LCD rendering has - changed (to be more precise, the amount of padding gets computed - differently). Applications that use the FreeType API are not - affected. - - - To reset all design axis values of a variation font to its - default values you can now say - - error = FT_Set_Var_Design_Coordinates( face, 0, NULL ); - - This also works with functions `FT_Set_MM_Design_Coordinates' - and `FT_Set_MM_Blend_Coordinates'. - - - FreeType now synthesizes a missing Unicode cmap for (older) - TrueType fonts also if glyph names are available. - - - FreeType has improved handling of BDF fonts without the - `POINT_SIZE', `RESOLUTION_X', or `RESOLUTION_Y' properties; the - library now uses the values of the `SIZE' keyword if they are - missing. Previously, `SIZE' was completely ignored, and - FreeType used heuristic values instead. - - - Multiple calls to `FT_Bitmap_Convert' do work now as advertised. - Previously, they failed with an assertion error if there was an - empty bitmap between non-empty ones. - - - The warping option has moved from `light' to `normal' hinting - where it replaces the original hinting algorithm. The `light' - mode is now always void of any hinting in x-direction. - - - 16bit compiler support is now officially ended. We didn't - provide any maintenance since many years, and given that there - were no error or problem reports either it seems that it is no - longer needed. - - - The `ftgrid' demo program can now toggle the display of grid - lines with the `G' key. - - - The `ftgrid' demo program can toggle a different set of colors - (suitable to color-blind people) with the `C' key. - - - The `ftgrid' demo program now supports the `-e' command line - option to select a cmap. - - - The `ftdump' demo program has a new command line option `-t' to - output the SFNT table list. - - -====================================================================== - -CHANGES BETWEEN 2.7.1 and 2.8 - - I. IMPORTANT CHANGES - - - Support for OpenType Variation Fonts is now complete. The last - missing part was handling the `VVAR' and `MVAR' tables, which is - available with this release. - - - A new function `FT_Face_Properties' allows the control of some - module and library properties per font. Currently, the - following properties can be handled: stem darkening, LCD filter - weights, and the random seed for the `random' CFF operator. - - - The PCF change to show more `colorful' family names (introduced - in version 2.7.1) was too radical; it can now be configured with - PCF_CONFIG_OPTION_LONG_FAMILY_NAMES at compile time. If - activated, it can be switched off at run time with the new pcf - property `no-long-family-names'. If the `FREETYPE_PROPERTIES' - environment variable is available, you can say - - FREETYPE_PROPERTIES=pcf:no-long-family-names=1 - - - Support for the following scripts has been added to the - auto-hinter. - - Adlam, Avestan, Bamum, Buhid, Carian, Chakma, Coptic, Cypriot, - Deseret, Glagolitic, Gothic, Kayah, Lisu, N'Ko, Ol Chiki, Old - Turkic, Osage, Osmanya, Saurashtra, Shavian, Sundanese, Tai - Viet, Tifinagh, Unified Canadian Syllabics, Vai - - - II. IMPORTANT BUG FIXES - - - `Light' auto-hinting mode no longer uses TrueType metrics for - TrueType fonts. This bug was introduced in version 2.4.6, - causing horizontal scaling also. Almost all GNU/Linux - distributions (with Fedora as a notable exception) disabled the - corresponding patch for good reasons; chances are thus high that - you won't notice a difference. - - If optical backward compatibility for legacy applications is - necessary, you might enable the AF_CONFIG_OPTION_TT_SIZE_METRICS - configuration option. However, it is strongly recommended to - avoid that, adjusting font sizes instead. - - - Global size metrics values in the `FT_Size_Metrics' structure - can be different for TrueType fonts. Reason is that in older - FreeType versions the metrics were rounded differently to - integer pixels compared to all other font formats, yielding an - inconsistent behaviour if you used non-native hinting. Starting - with this version, global size metrics for TrueType fonts are - handled the same as other font formats: `ascender' gets rounded - up, `descender' gets rounded down, `height' gets normally - rounded, and `max_advance' gets normally rounded, too. - - If you need more precise values of (global) ascender, descender, - height, or `max_advance', please take the corresponding values - from the `FT_Face' structure and scale them manually. - - - If a TrueType font gets loaded with FT_LOAD_NO_HINTING, FreeType - now scales the font linearly again (bug introduced in version - 2.4.6). - - - CVE-2017-8105, CVE-2017-8287: Older FreeType versions have - out-of-bounds writes caused by heap-based buffer overflows - related to Type 1 fonts. - - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-8105 - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-8287 - - - III. MISCELLANEOUS - - - A new function `FT_Set_Default_Properties' has been added to - parse the `FREETYPE_PROPERTIES' environment variable - (previously, it was internal only). `FT_Init_FreeType' always - call this function, but `FT_New_Library' does not (similar to - `FT_Add_Default_Modules'). - - - To be in sync with OpenType version 1.7 and newer, macros - - FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY, - FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY, - TT_NAME_ID_PREFERRED_FAMILY - TT_NAME_ID_PREFERRED_SUBFAMILY - - are renamed to - - FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY, - FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY, - TT_NAME_ID_TYPOGRAPHIC_FAMILY - TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY - - The old macro names are deprecated (but still available). - - - Support for SFNT `name' tables has been improved. - - . Format 1 `name' tables are now supported. Use new function - `FT_Get_Sfnt_LangTag' to access associated language tags. - - . Language, encoding, and name IDs have been updated to OpenType - version 1.8.1. - - - The new CFF engine now handles the `random' operator. All CFF - opcodes are now supported. - - - The CFF module has a new property `random-seed' to control the - pseudo-random number generation for the `random' operator. - - - The `freetype-config' script is now a wrapper of `pkg-config' if - this program is available in the path. - - - FT_LOAD_TARGET_LCD is now a variant of FT_LOAD_TARGET_LIGHT; - this should provide better rendering results. - - - A mode to display light auto-hinting with subpixel positioning - has been added to `ftdiff'. - - -====================================================================== - -CHANGES BETWEEN 2.7 and 2.7.1 - - I. IMPORTANT CHANGES - - - Support for the new CFF2 font format as introduced with OpenType - 1.8 has been contributed by Dave Arnolds from Adobe. - - - Preliminary support for variation fonts as specified in OpenType - 1.8 (in addition to the already existing support for Adobe's MM - and Apple's GX formats). Dave Arnolds contributed handling of - advance width change variation; more will come in the next - version. - - - II. IMPORTANT BUG FIXES - - - Handling of raw CID fonts was partially broken (bug introduced - in 2.6.4). - - - CVE-2016-10328: Older FreeType versions had an out-of-bounds - write caused by a heap-based buffer overflow related to the CFF - fonts. - - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-10328 - - - III. MISCELLANEOUS - - - Some limits for TrueType bytecode execution have been tightened - to speed up FreeType's handling of malformed fonts, in - particular to quickly abort endless loops. - - - The number of twilight points can no longer be set to an - arbitrarily large value. - - - The total number of jump opcode instructions (like JMPR) with - negative arguments is dynamically restricted; the same holds - for the total number of iterations in LOOPCALL opcodes. - - The dynamic limits are based on the number of points in a glyph - and the number of CVT entries. Please report if you encounter a - font where the selected values are not adequate. - - - PCF family names are made more `colorful'; they now include the - foundry and information whether they contain wide characters. - For example, you no longer get `Fixed' but rather `Sony Fixed' - or `Misc Fixed Wide'. - - - A new function `FT_Get_Var_Blend_Coordinates' (with its alias - name `FT_Get_MM_Blend_Coordinates') to retrieve the normalized - blend coordinates of the currently selected variation instance - has been added to the Multiple Masters interface. - - - A new function `FT_Get_Var_Design_Coordinates' to retrieve the - design coordinates of the currently selected variation instance - has been added to the Multiple Masters interface. - - - A new load flag `FT_LOAD_BITMAP_METRICS_ONLY' to retrieve bitmap - information without loading the (embedded) bitmap itself. - - - Retrieving advance widths from bitmap strikes (using - `FT_Get_Advance' and `FT_Get_Advances') have been sped up. - - - The usual round of fuzzer fixes to better reject malformed - fonts. - - - The `ftmulti' demo program can now switch engines with key `H'. - - - The `ftstring' demo program can now show some built-in, - non-latin sample strings (to be selected with the TAB key). - - - The `ftview' demo program can now switch between a font's - charmaps using the TAB key. - - -====================================================================== - -CHANGES BETWEEN 2.6.5 and 2.7 - - I. IMPORTANT CHANGES - - - As announced earlier, the 2.7.x series now uses the new subpixel - hinting mode as the default, emulating a modern version of - ClearType. - - This change inevitably leads to different rendering results, and - you might change the `TT_CONFIG_OPTION_SUBPIXEL_HINTING' - configuration option to adapt it to your taste (or use the new - `FREETYPE_PROPERTIES' environment variable). See the - corresponding entry below for version 2.6.4, which gives more - information. - - - A new option `FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES' has been - introduced. If set (which is the default), an environment - variable `FREETYPE_PROPERTIES' can be used to control driver - properties. Example: - - FREETYPE_PROPERTIES=truetype:interpreter-version=35 \ - cff:no-stem-darkening=1 \ - autofitter:warping=1 - - This allows to select, say, the subpixel hinting mode at runtime - for a given application. See file `ftoption.h' for more. - - - II. IMPORTANT BUG FIXES - - - After loading a named instance of a GX variation font, the - `face_index' value in the returned `FT_Face' structure now - correctly holds the named instance index in the upper 16bits as - documented. - - - III. MISCELLANEOUS - - - A new macro `FT_IS_NAMED_INSTANCE' to test whether a given face - is a named instance. - - - More fixes to GX font handling. - - - Apple's `GETVARIATION' bytecode operator (needed for GX - variation font support) has been implemented. - - - Another round of fuzzer fixes, mainly to reject invalid fonts - faster. - - - Handling of raw CID fonts was broken (bug introduced in version - 2.6.4). - - - The smooth rasterizer has been streamlined to make it faster by - approx. 20%. - - - The `ftgrid' demo program now understands command line option - `-d' to give start-up design coordinates. - - - The `ftdump' demo program has a new command line option `-p' to - dump TrueType bytecode instructions. - - -====================================================================== - -CHANGES BETWEEN 2.6.4 and 2.6.5 - - I. IMPORTANT BUG FIXES - - - Compilation works again on Mac OS X (bug introduced in version - 2.6.4). - - - II. IMPORTANT CHANGES - - - The new subpixel hinting mode is now disabled by default; it - will be enabled by default in the forthcoming 2.7.x series. - Main reason for reverting this feature is the principle of least - surprise: a sudden change in appearance of all fonts (even if - the rendering improves for almost all recent fonts) should not - be expected in a new micro version of a series. - - -====================================================================== - -CHANGES BETWEEN 2.6.3 and 2.6.4 - - I. IMPORTANT CHANGES - - - A new subpixel hinting mode has been contributed by Nikolaus - Waxweiler, which is now the default rendering mode for TrueType - fonts. It implements (almost everything of) version 40 of the - bytecode engine. - - The existing code base in FreeType (the `Infinality code') was - stripped to the bare minimum and all configurability removed in - the name of speed and simplicity. The configurability was - mainly aimed at legacy fonts like Arial, Times New Roman, or - Courier. [Legacy fonts are fonts that modify vertical stems to - achieve clean black-and-white bitmaps.] The new mode focuses on - applying a minimal set of rules to all fonts indiscriminately so - that modern and web fonts render well while legacy fonts render - okay. - - Activation of the subpixel hinting support can be controlled - with the `TT_CONFIG_OPTION_SUBPIXEL_HINTING' configuration - option at compile time: If set to value 1, you get the old - Infinality mode (which was never the default due to its - slowness). Value 2 activates the new subpixel hinting mode, and - value 3 activates both. The default is value 2. - - At run time, you can select the subpixel hinting mode with the - `interpreter-version' property (provided you have compiled in - the corresponding hinting mode); see `ftttdrv.h' for more. - - - Support for the following scripts has been added to the - auto-hinter. - - Armenian, Cherokee, Ethiopic, Georgian, Gujarati, Gurmukhi, - Malayalam, Sinhala, Tamil - - - II. MISCELLANEOUS - - - Type 42 fonts as created by LilyPond are now supported. - - - Minor rendering improvements in the auto-hinter. - - - For experimental reasons, the old CFF engine now supports all - CFF operators except `random', including the deprecated Multiple - Masters instructions. This allows the display of fonts like - `ITCGaramondMM-It.otf' (without font variations, though). - - - Another round of fixes to improve handling of invalid fonts. - - - The `ftgrid' demo program now displays the rendered pixels also; - this can be switched off with the `b' key. Selection of various - LCD filtering modes can be done with the `L' key. - - - The demo programs have been extended to allow selection of all - available TrueType bytecode engines. - - - A very early beta version of a new, Qt based demo program called - `ftinspect' is part of the source code bundle; it will - eventually supersede the other demo programs. Currently, you - have to compile it manually with `qmake; make'; note that many - features are still missing. - - -====================================================================== - -CHANGES BETWEEN 2.6.2 and 2.6.3 - - I. IMPORTANT CHANGES - - - Khmer, Myanmar, Bengali, and Kannada script support has been - added to the auto-hinter. - - - II. MISCELLANEOUS - - - Better support of Indic scripts like Devanagari by using a - top-to-bottom hinting flow. - - - All FreeType macros starting with two underscores have been - renamed to avoid a violation of both the C and C++ standards. - Example: Header macros of the form `__FOO_H__' are now called - `FOO_H_'. In most cases, this should be completely transparent - to the user. The exception to this is `__FTERRORS_H__', which - must be sometimes undefined by the user to get FreeType error - strings: Both this form and the new `FTERRORS_H_' macro are - accepted for backward compatibility. - - - Minor improvements mainly to the Type 1 driver. - - - The new CFF engine now supports all Type 2 operators except - `random'. - - - The macro `_STANDALONE_', used for compiling the B/W and smooth - rasterizers as stand-alone modules, has been renamed to - `STANDALONE_', since macro names starting with an underscore and - followed by an uppercase letter are reserved in both C and C++. - - - Function `FT_Library_SetLcdFilterWeights' now also activates - custom LCD filter weights (instead of just adjusting them). - - - Support for `unpatented hinting' has been completely removed: - Consequently, the two functions `FT_Face_CheckTrueTypePatents' - and `FT_Face_SetUnpatentedHinting' now return always false, - doing nothing. - - - The `ftgamma' demo program has been modernized; the gamma grid - display has been moved from `ftview' to this program. - - - In `ftview', it is now possible to cycle through the available - LCD filtering modes. - - -====================================================================== - -CHANGES BETWEEN 2.6.1 and 2.6.2 - - I. IMPORTANT CHANGES - - - The auto-hinter now supports stem darkening, to be controlled by - the new `no-stem-darkening' and `darkening-parameters' - properties. This is an experimental feature contributed by - Nikolaus Waxweiler, and the interface might change in a future - release. - - - By default, stem darkening is now switched off (for both the CFF - engine and the auto-hinter). The main reason is that you need - linear alpha blending and gamma correction to get correct - rendering results, and the latter is not yet available in most - freely available rendering stacks like X11. Applying stem - darkening without proper gamma correction leads to far too dark - rendering results. - - - The meaning of `FT_RENDER_MODE_LIGHT' has been slightly - modified. It now essentially means `no hinting along the - horizontal axis'; in particular, no change of glyph advance - widths. Consequently, the auto-hinter is used for all scalable - font formats except for CFF. It is planned that other - font-specific rendering engines (TrueType, Type 1) will follow. - - - II. MISCELLANEOUS - - - The default LCD filter has been changed to be normalized and - color-balanced. - - - For better compatibility with FontConfig, function - `FT_Library_SetLcdFilter' accepts a new enumeration value - `FT_LCD_FILTER_LEGACY1' (which has the same meaning as - `FT_LCD_FILTER_LEGACY'). - - - A large number of bugs have been detected by using the libFuzzer - framework, which should further improve handling of invalid - fonts. Thanks again to Kostya Serebryany and Bungeman! - - - `TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES', a new configuration - option, controls the maximum number of executed opcodes within a - bytecode program. You don't want to change this except for very - special situations (e.g., making a library fuzzer spend less - time to handle broken fonts). - - - The smooth renderer has been made faster. - - - The `ftstring' demo program now supports subpixel rendering; use - key `l' to cycle through the LCD modes. - - - The `ftstring' demo program now supports color rendering; use - the `space' key to cycle through various color combinations. - - - The graphical demo programs now use a default gamma value of 1.8 - (instead of 1.2). - - -====================================================================== - -CHANGES BETWEEN 2.6 and 2.6.1 - - I. IMPORTANT BUG FIXES - - - It turned out that for CFFs only the advance widths should be - taken from the `htmx' table, not the side bearings. This bug, - introduced in version 2.6.0, makes it necessary to upgrade if - you are using CFFs; otherwise, you get cropped glyphs with GUI - interfaces like GTK or Qt. - - - Accessing Type 42 fonts returned incorrect results if the glyph - order of the embedded TrueType font differs from the glyph order - of the Type 42 charstrings table. - - - II. IMPORTANT CHANGES - - - The header file layout has been changed (again), moving all - header files except `ft2build.h' into a subdirectory tree. - - Doing so reduces the possibility of header file name clashes - (e.g., FTGL's `FTGlyph.h' with FreeType's `ftglyph.h') on case - insensitive file systems like Mac OS X or Windows. - - Applications that use (a) the `freetype-config' script or - FreeType's `freetype2.pc' file for pkg-config to get the include - directory for the compiler, and (b) the documented way for - header inclusion like - - #include - #include FT_FREETYPE_H - ... - - don't need any change to the source code. - - - Simple access to named instances in GX variation fonts is now - available (in addition to the previous method via FreeType's MM - interface). In the `FT_Face' structure, bits 16-30 of the - `face_index' field hold the current named instance index for the - given face index, and bits 16-30 of `style_flags' contain the - number of instances for the given face index. `FT_Open_Face' - and friends also understand the extended bits of the face index - parameter. - - You need to enable TT_CONFIG_OPTION_GX_VAR_SUPPORT for this new - feature. Otherwise, bits 16-30 of the two fields are zero (or - are ignored). - - - Lao script support has been added to the auto-hinter. - - - III. MISCELLANEOUS - - - The auto-hinter's Arabic script support has been enhanced. - - - Superscript-like and subscript-like glyphs as used by various - phonetic alphabets like the IPA are now better supported by the - auto-hinter. - - - The TrueType bytecode interpreter now runs slightly faster. - - - Improved support for builds with cmake. - - - The function `FT_CeilFix' now always rounds towards plus - infinity. - - - The function `FT_FloorFix' now always rounds towards minus - infinity. - - - A new load flag `FT_LOAD_COMPUTE_METRICS' has been added; it - makes FreeType ignore pre-computed metrics, as needed by font - validating or font editing programs. Right now, only the - TrueType module supports it to ignore data from the `hdmx' - table. - - - Another round of bug fixes to better handle broken fonts, found - by Kostya Serebryany . - - -====================================================================== - -CHANGES BETWEEN 2.5.5 and 2.6 - - I. IMPORTANT CHANGES - - - Behdad Esfahbod contributed code for improved thread-safety, - which results in the following model. - - * An `FT_Face' object can only be safely used from one thread at - a time. - - * An `FT_Library' object can now be used without modification - from multiple threads at the same time. - - * `FT_Face' creation and destruction with the same `FT_Library' - object can only be done from one thread at a time. - - One can use a single `FT_Library' object across threads as long - as a mutex lock is used around `FT_New_Face' and `FT_Done_Face'. - Any calls to `FT_Load_Glyph' and similar API are safe and do not - need the lock to be held as long as the same `FT_Face' is not - used from multiple threads at the same time. - - - Thai script support has been added to the auto-hinter. - - - Arabic script support has been added to the auto-hinter. - - - Following OpenType version 1.7, advance widths and side bearing - values in CFFs (wrapped in an SFNT structure) are now always - taken from the `hmtx' table. - - - Following OpenType version 1.7, the PostScript font name of a - CFF font (wrapped in an SFNT structure) is now always taken from - the `name' table. This is also true for OpenType Collections - (i.e., TTCs using CFFs subfonts instead of TTFs), where it may - have a significant difference. - - - Fonts natively hinted for ClearType are now supported, properly - handling selector index 3 of the INSTCTRL bytecode instruction. - - - Major improvements to the GX TrueType variation font handling. - - - II. MISCELLANEOUS - - - A new auto-hinter property `warping' can switch on and off the - warping code if this experimental feature is compiled in (by - defining the AF_CONFIG_OPTION_USE_WARPER configuration option; - by default this option is now enabled but warping is switched - off). - - The AF_CONFIG_OPTION_USE_WARPER option itself is an old feature, - available since 2006. Warping only works in `light' - auto-hinting mode. The idea of the code is to slightly scale - and shift a glyph along the non-hinted dimension (which is - usually the horizontal axis) so that as much of its segments are - aligned (more or less) to the grid. To find out a glyph's - optimal scaling and shifting value, various parameter - combinations are tried and scored. - - See file `ftautoh.h' for more; the demo programs `ftdiff', - `ftview', and `ftgrid' can toggle warping with key `w'. - - - Some fields in the `FTC_ImageTypeRec' structure have been - changed from signed to unsigned type, which better reflects the - actual usage. It is also an additional means to protect against - malformed input. - - This change doesn't break the ABI; however, it might cause - compiler warnings. - - - Function `FT_Bitmap_New' has been renamed to `FT_Bitmap_Init', - since this name better reflects its function. For backward - compatibility, the old function name is still available. - - - Function `FT_Get_X11_Font_Format' has been renamed to - `FT_Get_Font_Format', since this name better reflects its - function. For backward compatibility, the old function name is - still available. - - Additionally, the header file macro for this function has been - renamed to `FT_FONT_FORMATS_H' (the old name `FT_XFREE86_H' is - retained for backward compatibility). - - - Various improvements to the `ftgrid' demo program. - - . It can now display GX and MM fonts while interactively - manipulating the axes (with keys F2, F3, and F4). - - . Anti-aliasing rendering modes can now be selected (with keys - F5 and F6). - - . The display of point numbers can be toggled with key `D'. - - - Various improvements to the `ftdump' demo program. - - . It now displays information on MM and GX variation axes. - - . New command line option `-u' makes it output data in utf-8 - encoding. - - - The `ftmulti' demo program can now handle up to six MM or GX - axes. - - -====================================================================== - -CHANGES BETWEEN 2.5.4 and 2.5.5 - - I. IMPORTANT BUG FIXES - - - Handling of uncompressed PCF files works again (bug introduced - in version 2.5.4). - - -====================================================================== - -CHANGES BETWEEN 2.5.3 and 2.5.4 - - I. IMPORTANT BUG FIXES - - - A variant of vulnerability CVE-2014-2240 was identified - (cf. https://savannah.nongnu.org/bugs/?43661) and fixed in the - new CFF driver. All users should upgrade. - - - The new auto-hinter code using HarfBuzz crashed for some invalid - fonts. - - - Many fixes to better protect against malformed input. - - - II. IMPORTANT CHANGES - - - Full auto-hinter support of the Devanagari script. - - - Experimental auto-hinter support of the Telugu script. - - - CFF stem darkening behaviour can now be controlled at build time - using the eight macros - - CFF_CONFIG_OPTION_DARKENING_PARAMETER_{X,Y}{1,2,3,4} . - - - Some fields in the `FT_Bitmap' structure have been changed from - signed to unsigned type, which better reflects the actual usage. - It is also an additional means to protect against malformed - input. - - This change doesn't break the ABI; however, it might cause - compiler warnings. - - - III. MISCELLANEOUS - - - Improvements to the auto-hinter's algorithm to recognize stems - and local extrema. - - - Function `FT_Get_SubGlyph_Info' always returned an error even in - case of success. - - - Version 2.5.1 introduced major bugs in the cjk part of the - auto-hinter, which are now fixed. - - - The `FT_Sfnt_Tag' enumeration values have been changed to - uppercase, e.g. `FT_SFNT_HEAD'. The lowercase variants are - deprecated. This is for orthogonality with all other - enumeration (and enumeration-like) values in FreeType. - - - `cmake' now supports builds of FreeType as an OS X framework and - for iOS. - - - Improved project files for vc2010, introducing a property file. - - - The documentation generator for the API reference has been - updated to produce better HTML code (with proper CSS). At the - same time, the documentation got a better structure. - - - The FT_LOAD_BITMAP_CROP flag is obsolete; it is not used by any - driver. - - - The TrueType DELTAP[123] bytecode instructions now work in - subpixel hinting mode as described in the ClearType whitepaper - (i.e., for touched points in the non-subpixel direction). - - - Many small improvements to the internal arithmetic routines. - - -====================================================================== - -CHANGES BETWEEN 2.5.2 and 2.5.3 - - I. IMPORTANT BUG FIXES - - - A vulnerability (CVE-2014-2240) was identified and fixed in the - new CFF driver (cf. https://savannah.nongnu.org/bugs/?41697). - All users should upgrade. - - - More bug fixes related to correct positioning of composite - glyphs. - - - Many fixes to better protect against malformed input. - - - II. IMPORTANT CHANGES - - - FreeType can now use the HarfBuzz library to greatly improve the - auto-hinting of fonts that use OpenType features: Many glyphs - that are part of such features but don't have cmap entries are - now handled properly, for example small caps or superscripts. - Define the configuration macro FT_CONFIG_OPTION_USE_HARFBUZZ to - activate HarfBuzz support. - - You need HarfBuzz version 0.9.19 or newer. - - Note that HarfBuzz depends on FreeType; this currently causes a - chicken-and-egg problem that can be solved as follows in case - HarfBuzz is not yet installed on your system. - - 1. Compile and install FreeType without the configuration - macro FT_CONFIG_OPTION_USE_HARFBUZZ. - - 2. Compile and install HarfBuzz. - - 3. Define macro FT_CONFIG_OPTION_USE_HARFBUZZ, then compile - and install FreeType again. - - With FreeType's `configure' script the procedure boils down to - configure, build, and install FreeType, then configure, compile, - and install HarfBuzz, then configure, compile, and install - FreeType again (after executing `make distclean'). - - - All libraries FreeType depends on are now checked using the - `pkg-config' configuration files first, followed by alternative - methods. - - - The new value `auto' for the various `--with-XXX' library - options (for example `--with-harfbuzz=auto') makes the - `configure' script automatically link to the libraries it finds. - This is now the default. - - - In case FreeType's `configure' script can't find a library, you - can pass environment variables to circumvent pkg-config, and - those variables have been harmonized as a consequence of the - changes mentioned above: - - LIBZ -> removed; use LIBZ_CFLAGS and LIBZ_LIBS - LIBBZ2 -> removed; use BZIP2_CFLAGS and BZIP2_LIBS - LIBPNG_LDFLAGS -> LIBPNG_LIBS - - `./configure --help' shows all available environment variables. - - - The `freetype-config' script now understands option `--static' - to emit static linking information. - - -====================================================================== - -CHANGES BETWEEN 2.5.1 and 2.5.2 - - I. IMPORTANT BUG FIXES - - - Improving the display of some broken TrueType fonts introduced a - bug that made FreeType crash on some popular (but not fully - conformant) fonts like `ahronbd.ttf'. - - - Another round of improvements to correct positioning and hinting - of composite glyphs in TrueType fonts. - - - II. MISCELLANEOUS - - - Version 2.5.1 introduced a bug in handling embedded bitmap - strikes of TrueType fonts, causing garbage display under some - circumstances. - - - The `ftgrid' demo program couldn't be compiled in - non-development builds. - - -====================================================================== - -CHANGES BETWEEN 2.5 and 2.5.1 - - I. IMPORTANT BUG FIXES - - - For some WinFNT files, the last glyph wasn't displayed but - incorrectly marked as invalid. - - - The vertical size of glyphs was incorrectly set after a call to - `FT_GlyphSlot_Embolden', resulting in clipped glyphs. - - - Many fields of the `PCLT' table in SFNT based fonts (if accessed - with `FT_Get_Sfnt_Table') were computed incorrectly. - - - In TrueType fonts, hinting of composite glyphs could sometimes - deliver incorrect positions of components or even distorted - shapes. - - - II. IMPORTANT CHANGES - - - WOFF font format support has been added. - - - The auto-hinter now supports Hebrew. Greek and Cyrillic support - has been improved. - - - Support for the forthcoming `OS/2' SFNT table version 5, as can - be found e.g. in the `Sitka' font family for Windows 8.1. - - - The header file layout has been changed. After installation, - all files are now located in `/include/freetype2'. - - Applications that use (a) `freetype-config' or FreeType's - `pkg-config' file to get the include directory for the compiler, - and (b) the documented way for header inclusion like - - #include - #include FT_FREETYPE_H - ... - - don't need any change to the source code. - - - III. MISCELLANEOUS - - - The stem darkening feature of the new CFF engine can now be - fine-tuned with the new `darkening-parameters' property. - - - `ftgrid' has been updated to toggle various engines with the `H' - key, similar to `ftview' and `ftdiff'. - - - The functionality of `ttdebug' has been greatly enhanced. - - . It now displays twilight, storage, and control value data; key - `T' shows the twilight point table, key `S' the storage data, - and key `C' the control value table. - - . Some keys have been reassigned from lowercase to their - uppercase equivalents; for example `q' to quit the program is - now `Q'. - - . Key `f' finishes the current function. - - . Key `R' restarts the debugger. - - . Keys `b' and `p' set a breakpoint. - - . Key `B' provides a function call backtrace. - - - Better support of ARMv7 and x86_64 processors. - - - Apple's `sbix' color bitmap format is now supported. - - - Improved auto-hinter rendering for many TrueType fonts, - especially in the range 20-40ppem. - - - A new face flag `FT_FACE_FLAG_COLOR' has been added (to be - accessed with the macro `FT_HAS_COLOR'). - - - `FT_Gzip_Uncompress' (modeled after zlib's `uncompress' - function) has been added; this is a by-product of the newly - added WOFF support. - - - Support for a build with `cmake' has been contributed by John - Cary . - - - Support for x64 builds with Visual C++ has been contributed by - Kenneth Miller - - - Manual pages for most demo programs have been added. - - - The GETINFO bytecode instruction for TrueType fonts was buggy if - used to retrieve subpixel hinting information. It was necessary - to set selector bit 6 to get results for selector bits 7-10, - which is wrong. - - - Improved computation of emulated vertical metrics for TrueType - fonts. - - - Fixed horizontal start-up position of vertical phantom points in - TrueType bytecode. - - -====================================================================== - -CHANGES BETWEEN 2.4.12 and 2.5 - - I. IMPORTANT BUG FIXES - - - The cache manager function `FTC_Manager_Reset' didn't flush the - cache. - - - II. IMPORTANT CHANGES - - - Behdad Esfahbod (on behalf of Google) contributed support for - color embedded bitmaps (eg. color emoji). - - A new load flag, FT_LOAD_COLOR, makes FreeType load color - embedded-bitmaps, following this draft specification - - https://color-emoji.googlecode.com/git/specification/v1.html - - which defines two new SFNT tables, `CBDT' and `CBLC' (named and - modeled after `EBDT' and `EBLC', respectively). The color - bitmaps are stored in the new FT_PIXEL_MODE_BGRA format to - represent BGRA pre-multiplied sRGB images. If PNG support is - available, PNG color images as defined in the same proposed - specification are supported also. - - Note that color bitmaps are converted to grayscale if client - didn't ask for color. - - - As announced in the previous release, the old FreeType CFF - engine is now disabled by default. It can be conditionally - compiled by defining the configuration macro - CFF_CONFIG_OPTION_OLD_ENGINE. - - - As announced in the previous release, all code related to macro - FT_CONFIG_OPTION_OLD_INTERNALS has been removed, thus becoming - obsolete. - - - III. MISCELLANEOUS - - - The property API (`FT_Property_Get' and `FT_Property_Set') is - now declared as stable. - - The exception, however, are the experimental auto-hinter - properties `glyph-to-script-map' and `fallback-script' which are - subject to change in a forthcoming release. - - - `ftview' has been updated to support color embedded bitmaps; it - can be toggled on and off with key `c'. The small cache toggle - is now key `K'. - - - It is now possible to control the version of the TrueType - hinting engine using the new `interpreter-version' property of - the `truetype' module: Versions 35 and 38 (the default) are - supported, which roughly corresponds to disable and enable - subpixel hinting support, respectively. - - In both `ftview' and `ftdiff', switching between the two - versions can be done with key `H'. In the `ftbench' demo - program, command line option `-H' has been extended to activate - the non-default interpreter version. - - - The `ttdebug' program has been further improved. In particular, - it accepts a new command line option `-H' to select the hinting - engine. - - - `ftdump's verbose option has been renamed to `-V'. For all demo - programs, `-v' now shows version information. - - - Another round of TrueType subpixel hinting fixes. - - - The `apinames' tool can now create an import file for NetWare. - - - 64bit compilation of the new CFF engine was buggy. - - - Some fixes to improve robustness in memory-tight situations. - - -====================================================================== - -CHANGES BETWEEN 2.4.11 and 2.4.12 - - - We have another CFF parsing and hinting engine! Written by Dave - Arnold , this work has been contributed by - Adobe in collaboration with Google. It is vastly superior to - the old CFF engine, and it will replace it in the next release. - Right now, it is still off by default, and you have to - explicitly select it using the new `hinting-engine' property of - the cff driver: - - ... - #include FT_MODULE_H - #include FT_CFF_DRIVER_H - - FT_Library library; - int engine = FT_CFF_HINTING_ADOBE; - - - ... - FT_Property_Set( library, "cff", "hinting-engine", &engine ); - - The code has a (mature) beta status; we encourage all users to - test it and report any problems. - - In case you want to activate the new CFF engine unconditionally, - apply this patch: - ---- snip --- -diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c -index ebcf189..3f2ce6b 100644 ---- a/src/cff/cffobjs.c -+++ b/src/cff/cffobjs.c -@@ -1056,7 +1056,7 @@ - - - /* set default property values */ -- driver->hinting_engine = FT_CFF_HINTING_FREETYPE; -+ driver->hinting_engine = FT_CFF_HINTING_ADOBE; - driver->no_stem_darkening = FALSE; - - return FT_Err_Ok; ---- snip --- - - - The macro FT_CONFIG_OPTION_OLD_INTERNALS is no longer set by - default. In the next release, we will completely remove the - associated code. Please update your programs in case you are - still using this macro. - - - II. MISCELLANEOUS - - - The (top-level) `configure' script now respects the MAKE - environment variable to specify a `make' binary. For backward - compatibility, GNUMAKE still overrides MAKE, though. - - - The `ftview' and `ftdiff' demo programs have been redesigned, - showing more options permanently on the screen, among other - minor improvements. - - - Using the `H' key, it is now possible to select the CFF engine - in both `ftview' and `ftdiff'. - - - The new command line option `-H' for `ftbench' selects the Adobe - CFF engine. - - - It is now possible to directly select the LCD rendering mode - with the keys `A'-`F' in `ftview'. The key mapping for cycling - through LCD modes has been changed from `K' and `L' to `k' and - `l', and toggling custom LCD filtering is no longer mapped to - key `F' but to key `L'. - - - In `ftdiff', key `x' toggles between layout modes: Either use - the advance width (this is new and now the default) or the - bounding box information to determine line breaks. - - - For all demo tools, the new command line option `-v' shows the - version. - - - For the demo tools with a GUI, the new command line options `-w' - and `-h' select the width and the height of the output window, - respectively. - - - The `ttdebug' program was broken and has been reactivated. Note - that this program is not compiled by default. - - -====================================================================== - -CHANGES BETWEEN 2.4.10 and 2.4.11 - - I. IMPORTANT BUG FIXES - - - Some vulnerabilities in the BDF implementation have been fixed. - Users of this font format should upgrade. - - - II. IMPORTANT CHANGES - - - Subpixel hinting support has been contributed by Infinality, - based on Greg Hitchcock's whitepaper at - - https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx - - Originally, it was a separate patch available from - - https://web.archive.org/web/20150710073951/http://www.infinality.net:80/blog/ - - and which has been integrated. - - Note that ClearType support is not completely implemented! In - particular, full support for the options `compatible_widths', - `symmetrical_smoothing, and `bgr' (via the GETINFO bytecode - instruction) is missing. - - Activation of subpixel hinting support can be controlled with - the `TT_CONFIG_OPTION_SUBPIXEL_HINTING' configuration option; it - is switched off by default. This feature is still experimental; - we welcome test reports! - - - Support for OpenType collections (OTC) has been added. - - - Pure CFF fonts within an SFNT wrapper are now supported. - - - III. MISCELLANEOUS - - - Minor rendering improvements to the auto-hinter. - - - `FT_GlyphSlot_Oblique' now uses a shear angle of 12°. - - - Experimental support to handle `property modules', for example - to control the behaviour of the auto-hinter. The API consists - of two new functions, `FT_Property_Set' and `FT_Property_Get'. - - The code is still subject to change and should not be used for - production. - - - The `ftdiff' demo program now supports UTF-8 encoded input files - for option `-f'. - - - Using keys `r' and `R', you can now adjust the stroker radius in - the `ftview' demo program. - - - Other, minor fixes and improvements. - - -====================================================================== - -CHANGES BETWEEN 2.4.9 and 2.4.10 - - I. IMPORTANT BUG FIXES - - - Incremental glyph loading as needed by ghostscript was broken. - - - II. MISCELLANEOUS - - - A new function `FT_Outline_EmboldenXY', contributed by Alexei - Podtelezhnikov. - - - In the `ftview' demo program, key `e' has been replaced with `x' - and `y' to embolden in the horizontal and vertical direction, - respectively. - - - The glyph spacing computation in `FT_GlyphSlot_Embolden' (and - similar code in `ftview') has been improved. - - - Minor improvements to the TrueType bytecode interpreter and - glyph loader, the auto-hinter, and the B/W rasterizer. - - -====================================================================== - -CHANGES BETWEEN 2.4.8 and 2.4.9 - - I. IMPORTANT BUG FIXES - - - Another round of fixes to better handle invalid fonts. Many of - them are vulnerabilities (see CVE-2012-1126 up to CVE-2012-1144 - and SA48320) so all users should upgrade. - - - II. MISCELLANEOUS - - - The `ENCODING -1 ' format of BDF fonts is now supported. - - - For BDF fonts, support for the whole Unicode encoding range has - been added. - - - Better TTF support for x_ppem != y_ppem. - - - `FT_Get_Advances' sometimes returned bogus values. - - - The demo programs no longer recognize and handle default - suffixes; you now have to always specify the complete font name. - - - Better rendering and LCD mode cycling added to `ftview'. - - -====================================================================== - -CHANGES BETWEEN 2.4.7 and 2.4.8 - - I. IMPORTANT BUG FIXES - - - Some vulnerabilities in handling CID-keyed PostScript fonts have - been fixed; see CVE-2011-3439. - - - II. MISCELLANEOUS - - - Chris Liddell contributed a new API, `FT_Get_PS_Font_Value', to - retrieve most of the dictionary keys in Type 1 fonts. - - -====================================================================== - -CHANGES BETWEEN 2.4.6 and 2.4.7 - - I. IMPORTANT BUG FIXES - - - Some vulnerabilities in handling Type 1 fonts have been fixed; - see CVE-2011-3256. - - - II. MISCELLANEOUS - - - FreeType now properly handles ZapfDingbats glyph names while - constructing a Unicode character map (for fonts which don't have - one). - - -====================================================================== - -CHANGES BETWEEN 2.4.5 and 2.4.6 - - I. IMPORTANT BUG FIXES - - - For TrueType based fonts, the ascender and descender values were - incorrect sometimes (off by a pixel if the ppem value was not a - multiple of 5). Depending on the use you might now experience - a different layout; the change should result in better, more - consistent line spacing. - - - Fix CVE-2011-0226 which causes a vulnerability while handling - Type 1 fonts. - - - BDF fonts containing glyphs with negative values for ENCODING - were incorrectly rejected. This bug has been introduced in - FreeType version 2.2.0. - - - David Bevan contributed a major revision of the FreeType stroker - code: - - . The behaviour of FT_STROKER_LINEJOIN_BEVEL has been corrected. - - . A new line join style, FT_STROKER_LINEJOIN_MITER_FIXED, has - been introduced to support PostScript and PDF miter joins. - - . FT_STROKER_LINEJOIN_MITER_VARIABLE has been introduced as an - alias for FT_STROKER_LINEJOIN_MITER. - - . Various stroking glitches has been fixed. - - - II. MISCELLANEOUS - - - SFNT bitmap fonts which contain an outline glyph for `.notdef' - only no longer set the FT_FACE_FLAG_SCALABLE flag. - - -====================================================================== - -CHANGES BETWEEN 2.4.4 and 2.4.5 - - I. IMPORTANT BUG FIXES - - - A rendering regression for second-order Bézier curves has been - fixed, introduced in 2.4.3. - - - II. IMPORTANT CHANGES - - - If autohinting is not explicitly disabled, FreeType now uses - the autohinter if a TrueType based font doesn't contain native - hints. - - - The load flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH has been made - redundant and is simply ignored; this means that FreeType now - ignores the global advance width value in TrueType fonts. - - - III. MISCELLANEOUS - - - `FT_Sfnt_Table_Info' can now return the number of SFNT tables of - a font. - - - Support for PCF files compressed with bzip2 has been contributed - by Joel Klinghed. To make this work, the OS must provide a - bzip2 library. - - - Bradley Grainger contributed project and solution files in - Visual Studio 2010 format. - - - Again some fixes to better handle broken fonts. - - - Some improvements to the B/W rasterizer. - - - Fixes to the cache module to improve robustness. - - - Just Fill Bugs contributed (experimental) code to compute blue - zones for CJK Ideographs, improving the alignment of horizontal - stems at the top or bottom edges. - - - The `ftgrid' demo program can now display autohinter segments, - to be toggled on and off with key `s'. - - -====================================================================== - -CHANGES BETWEEN 2.4.3 and 2.4.4 - - I. IMPORTANT BUG FIXES - - - UVS support (TrueType/OpenType cmap format 14) support is fixed. - This regression has been introduced in version 2.4.0. - - - II. MISCELLANEOUS - - - Detect tricky fonts (e.g. MingLiU) by the lengths and checksums - of Type42-persistent subtables (`cvt ', `fpgm', and `prep') when - a TrueType font without family name is given. The previous fix, - introduced in 2.4.3, was too rigorous, causing many subsetted - fonts (mainly from PDF files) displayed badly because FreeType - forced rendering with the TrueType bytecode engine instead of - the autohinter. - - - Better support for 64bit platforms. - - - More fixes to improve handling of broken fonts. - - -====================================================================== - -CHANGES BETWEEN 2.4.2 and 2.4.3 - - I. IMPORTANT BUG FIXES - - - Fix rendering of certain cubic, S-shaped arcs. This regression - has been introduced in version 2.4.0. - - - II. MISCELLANEOUS - - - To fix the above mentioned rendering issue, a new spline - flattening algorithm has been introduced which speeds up both - conic and cubic arcs. - - - Handling of broken fonts has been further improved. - - -====================================================================== - -CHANGES BETWEEN 2.4.1 and 2.4.2 - - I. IMPORTANT BUG FIXES - - - A stack overflow in CFF Type2 CharStrings interpreter is fixed. - - - Handling Type 42 font deallocation was broken; additionally, the - library is now more robust against malformed Type 42 fonts. - - - II. MISCELLANEOUS - - - Two new functions, `FT_Reference_Library' (in FT_MODULE_H) and - `FT_Reference_Face' (in FT_FREETYPE_H), have been added to - simplify life-cycle management. A counter gets initialized to 1 - at the time an FT_Library (or FT_Face) structure is created. - The two new functions increment the respective counter. - `FT_Done_Library' and `FT_Done_Face' then only destroy a library - or face if the counter is 1, otherwise they simply decrement the - counter. - - -====================================================================== - -CHANGES BETWEEN 2.4.0 and 2.4.1 - - I. IMPORTANT CHANGES - - - A serious bug in the CFF font module prevented display of many - glyphs in CFF fonts like `MinionPro-Regular.otf'. - - -====================================================================== - -CHANGES BETWEEN 2.3.12 and 2.4.0 - - I. IMPORTANT CHANGES - - - Since May 2010, all patents regarding the TrueType bytecode - interpreter have expired worldwide. Consequently, we now define - TT_CONFIG_OPTION_BYTECODE_INTERPRETER by default (and undefine - TT_CONFIG_OPTION_UNPATENTED_HINTING). - - - A new function `FT_Library_SetLcdFilterWeights' is available to - adjust the filter weights set by `FT_Library_SetLcdFilter'. - - - II. MISCELLANEOUS - - - Thanks to many reports from Robert Święcki, FreeType's stability - in handling broken or damaged fonts is much improved. - - - Support for LCD filter control has been added to the demo - programs `ftdiff' and `ftview'. - - -====================================================================== - -CHANGES BETWEEN 2.3.11 and 2.3.12 - - I. IMPORTANT CHANGES - - - For `FT_Open_Face', new parameters are available to ignore - preferred family names: FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY and - FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY. - - - II. MISCELLANEOUS - - - Support for incremental font loading (controlled with the - FT_CONFIG_OPTION_INCREMENTAL macro) is now active by default. - - - Better support for vertical metrics. - - - Various minor bug fixes. - - -====================================================================== - -CHANGES BETWEEN 2.3.10 and 2.3.11 - - I. IMPORTANT BUG FIXES - - - Version 2.3.10 broke PCF support. - - -====================================================================== - -CHANGES BETWEEN 2.3.10 and 2.3.9 - - I. IMPORTANT BUG FIXES - - - If all ASCII digits in a font have the same (unscaled) width, - the autohinter respects this and won't change it. - - - TrueType fonts are now rasterized correctly if the horizontal - and vertical resolution differ. - - - Type 1 fonts are now handled with increased precision internally - to avoid serious rounding issues if non-integral coordinates are - encountered. - - - Horizontally condensed CFF fonts (using the font matrix) were - rendered incorrectly. This bug has been introduced after - release 2.3.5. - - - II. IMPORTANT CHANGES - - - Support for the SFNT cmap 13 table format (as defined by the new - OpenType 1.6 specification) has been added. - - - B/W rasterization of well-hinted TrueType fonts at small sizes - has been greatly improved. - - - Calculation of vertical metrics in OpenType fonts has been - improved. - - - III. MISCELLANEOUS - - - It is now possible to change the emboldening factor in the - `ftview' demo program with keys `e' and `E'. - - - It is now possible to change the slant value in the `ftview' - demo program with keys `s' and `S'. - - - The 5-levels grayscale mode of the `ftraster' module (which - FreeType doesn't use by default) was broken since version 2.3.0. - - - Compilation of the `ftgrays' and `ftraster' modules was broken - in stand-alone mode. - - - Various fixes for compilation on 64bit and 16bit architectures. - - -====================================================================== - -CHANGES BETWEEN 2.3.9 and 2.3.8 - - I. IMPORTANT BUG FIXES - - - Very unfortunately, FreeType 2.3.8 contained a change that broke - its official ABI. The end result is that programs compiled - against previous versions of the library, but dynamically linked - to 2.3.8 can experience memory corruption if they call the - `FT_Get_PS_Font_Info' function. - - We recommend all users to upgrade to 2.3.9 as soon as possible, - or to downgrade to a previous release of the library if this is - not an option. - - The origin of the bug is that a new field was added to the - publicly defined `PS_FontInfoRec' structure. Unfortunately, - objects of this type can be stack or heap allocated by callers - of `FT_Get_PS_Font_Info', resulting in a memory buffer - overwrite with its implementation in 2.3.8. - - If you want to know whether your code is vulnerable to this - issue, simply search for the substrings `PS_FontInfo' and - `PS_Font_Info' in your source code. If none is found, your code - is safe and is not affected. - - The FreeType team apologizes for the problem. - - - The POSIX support of MacOS resource-fork fonts (Suitcase fonts - and LaserWriter Type1 PostScript fonts) was broken in 2.3.8. If - FreeType2 is built without Carbon framework, these fonts are not - handled correctly. Version 2.3.7 didn't have this bug. - - - `FT_Get_Advance' (and `FT_Get_Advances') returned bad values for - almost all font formats except TrueType fonts. - - - Fix a bug in the SFNT kerning table loader/parser which could - crash the engine if certain malformed tables were encountered. - - - Composite SFNT bitmaps are now handled correctly. - - - II. IMPORTANT CHANGES - - - The new functions `FT_Get_CID_Is_Internally_CID_keyed' and - `FT_Get_CID_From_Glyph_Index' can be used to access CID-keyed - CFF fonts via CID values. This code has been contributed by - Michael Toftdal. - - - III. MISCELLANEOUS - - - `FT_Outline_Get_InsideBorder' returns FT_STROKER_BORDER_RIGHT - for empty outlines. This was incorrectly documented. - - - The `ftview' demo program now supports UTF-8 encoded strings. - - -====================================================================== - -CHANGES BETWEEN 2.3.8 and 2.3.7 - - I. IMPORTANT BUG FIXES - - - CID-keyed fonts in an SFNT wrapper were not handled correctly. - - - The smooth renderer produced truncated images (on the right) for - outline parts with negative horizontal values. Most fonts don't - contain outlines left to the y coordinate axis, but the effect - was very noticeable for outlines processed with FT_Glyph_Stroke, - using thick strokes. - - - `FT_Get_TrueType_Engine_Type' returned a wrong value if both - configuration macros TT_CONFIG_OPTION_BYTECODE_INTERPRETER and - TT_CONFIG_OPTION_UNPATENTED_HINTING were defined. - - - The `face_index' field in the `FT_Face' structure wasn't - initialized properly after calling FT_Open_Face and friends with - a positive face index for CFFs, WinFNTs, and, most importantly, - for TrueType Collections (TTCs). - - - II. IMPORTANT CHANGES - - - Rudimentary support for Type 1 fonts and CID-keyed Type 1 fonts - in an SFNT wrapper has been added -- such fonts are used on the - Mac. The core SFNT tables `TYP1' and `CID ' are passed to the - PS Type 1 and CID-keyed PS font drivers; other tables (`ALMX', - `BBOX', etc.) are not supported yet. - - - A new interface to extract advance values of glyphs without - loading their outlines has been added. The functions are called - `FT_Get_Advance' and `FT_Get_Advances'; they are defined in file - `ftadvanc.h' (to be accessed as FT_ADVANCES_H). - - - A new function `FT_Get_FSType_Flags' (in FT_FREETYPE_H) has been - contributed by David Bevan to access the embedding and - subsetting restriction information of fonts. - - - III. MISCELLANEOUS - - - FT_MulFix is now an inlined function; by default, assembler code - is provided for x86 and ARM. See FT_CONFIG_OPTION_INLINE_MULFIX - and FT_CONFIG_OPTION_NO_ASSEMBLER (in ftoption.h) for more. - - - The handling of `tricky' fonts (this is, fonts which don't work - with the autohinter, needing the font format's hinting engine) - has been generalized and changed slightly: - - . A new face flag FT_FACE_FLAG_TRICKY indicates that the font - format's hinting engine is necessary for correct rendering. - The macro FT_IS_TRICKY can be used to check this flag. - - . FT_LOAD_NO_HINTING is now ignored for tricky fonts. To really - force raw loading of such fonts (without hinting), both - FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT must be used -- - this is something which you probably never want to do. - - . Tricky TrueType fonts always use the bytecode interpreter, - either the patented or unpatented version. - - - The function `FT_GlyphSlot_Own_Bitmap' has been moved from - FT_SYNTHESIS_H to FT_BITMAP_H; it is now part of the `official' - API. (The functions in FT_SYNTHESIS_H are still subject to - change, however.) - - - In the `ftdiff' demo program you can now toggle the use of - FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH with key `a'. - - -====================================================================== - -CHANGES BETWEEN 2.3.7 and 2.3.6 - - I. IMPORTANT BUG FIXES - - - If the library was compiled on an i386 platform using gcc, and - compiler option -O3 was given, `FT_MulFix' sometimes returned - incorrect results which could have caused problems with - `FT_Request_Metrics' and `FT_Select_Metrics', returning an - incorrect descender size. - - - Pure CFFs without subfonts were scaled incorrectly if the font - matrix was non-standard. This bug has been introduced in - version 2.3.6. - - - The `style_name' field in the `FT_FaceRec' structure often - contained a wrong value for Type 1 fonts. This misbehaviour - has been introduced in version 2.3.6 while trying to fix - another problem. [Note, however, that this value is - informative only since the used algorithm to extract it is - very simplistic.] - - - II. IMPORTANT CHANGES - - - Two new macros, FT_OUTLINE_SMART_DROPOUTS and - FT_OUTLINE_EXCLUDE_STUBS, have been introduced. Together with - FT_OUTLINE_IGNORE_DROPOUTS (which was ignored previously) it is - now possible to control the dropout mode of the `raster' module - (for B&W rasterization), using the `flags' field in the - `FT_Outline' structure. - - - The TrueType bytecode interpreter now passes the dropout mode to - the B&W rasterizer. This greatly increases the output for small - ppem values of many fonts like `pala.ttf'. - - -====================================================================== - -CHANGES BETWEEN 2.3.6 and 2.3.5 - - I. IMPORTANT BUG FIXES - - - A bunch of potential security problems have been found. All - users should update. - - - Microsoft Unicode cmaps in TrueType fonts are now always - preferred over Apple cmaps. This is not a bug per se, but there - exist some buggy fonts created for MS which have broken Apple - cmaps. This affects only the automatic selection of FreeType; - it's always possible to manually select an Apple Unicode cmap if - desired. - - - Many bug fixes to the TrueType bytecode interpreter. - - - Improved Mac support. - - - Subsetted CID-keyed CFFs are now supported correctly. - - - CID-keyed CFFs with subfonts which are scaled in a non-standard - way are now handled correctly. - - - A call to FT_Open_Face with `face_index' < 0 crashed FreeType if - the font was a Windows (bitmap) FNT/FON. - - - II. IMPORTANT CHANGES - - - The new function `FT_Get_CID_Registry_Ordering_Supplement' gives - access to those fields in a CID-keyed font. The code has been - contributed by Derek Clegg. - - - George Williams contributed code to validate the new `MATH' - OpenType table (within the `otvalid' module). The `ftvalid' - demo program has been extended accordingly. - - - An API for cmap 14 support (for Unicode Variant Selectors, UVS) - has been contributed by George Williams. - - - A new face flag FT_FACE_FLAG_CID_KEYED has been added, together - with a macro FT_IS_CID_KEYED which evaluates to 1 if the font is - CID-keyed. - - - III. MISCELLANEOUS - - - Build support for symbian has been contributed. - - - Better WGL4 glyph name support, contributed by Sergey Tolstov. - - - Debugging output of the various FT_TRACEX macros is now sent to - stderr. - - - The `ftview' demo program now provides artificial slanting too. - - - The `ftvalid' demo program has a new option `-f' to select the - font index. - - -====================================================================== - -CHANGES BETWEEN 2.3.5 and 2.3.4 - - I. IMPORTANT BUG FIXES - - - Some subglyphs in TrueType fonts were handled incorrectly due to - a missing graphics state reinitialization. - - - Large .Z files (as distributed with some X11 packages) weren't - handled correctly, making FreeType increase the heap stack in an - endless loop. - - - A large number of bugs have been fixed to avoid crashes and - endless loops with invalid fonts. - - - II. IMPORTANT CHANGES - - - The two new cache functions `FTC_ImageCache_LookupScaler' and - `FTC_SBit_Cache_LookupScaler' have been added to allow lookup of - glyphs using an `FTC_Scaler' object; this makes it possible to - use fractional pixel sizes in the cache. The demo programs have - been updated accordingly to use this feature. - - - A new API `FT_Get_CMap_Format' has been added to get the cmap - format of a TrueType font. This is useful in handling PDF - files. The code has been contributed by Derek Clegg. - - - The auto-hinter now produces better output by default for - non-Latin scripts like Indic. This was done by using the CJK - hinting module as the default instead of the Latin one. Thanks - to Rahul Bhalerao for this suggestion. - - - A new API `FT_Face_CheckTrueTypePatents' has been added to find - out whether a given TrueType font uses patented bytecode - instructions. The `ft2demos' bundle contains a new program - called `ftpatchk' which demonstrates its usage. - - - A new API `FT_Face_SetUnpatentedHinting' has been added to - enable or disable the unpatented hinter. - - - Support for Windows FON files in PE format has been contributed - by Dmitry Timoshkov. - - - III. MISCELLANEOUS - - - Vincent Richomme contributed Visual C++ project files for Pocket - PCs. - - -====================================================================== - -CHANGES BETWEEN 2.3.4 and 2.3.3 - - I. IMPORTANT BUG FIXES - - - A serious bug in the handling of bitmap fonts (and bitmap - strikes of outline fonts) has been introduced in 2.3.3. - - -====================================================================== - -CHANGES BETWEEN 2.3.3 and 2.3.2 - - I. IMPORTANT BUG FIXES - - - Remove a serious regression in the TrueType bytecode interpreter - that was introduced in version 2.3.2. Note that this does not - disable the improvements introduced to the interpreter in - version 2.3.2, only some ill cases that occurred with certain - fonts (though a few popular ones). - - - The auto-hinter now ignores single-point contours for computing - blue zones. This bug created `wavy' baselines when rendering - text with various fonts that use these contours to model - mark-attach points (these are points that are never rasterized - and are placed outside of the glyph's real outline). - - - The `rsb_delta' and `lsb_delta' glyph slot fields are now set to - zero for mono-spaced fonts. Otherwise code that uses them would - essentially ruin the fixed-advance property. - - - Fix CVE-2007-1351 which can cause an integer overflow while - parsing BDF fonts, leading to a potentially exploitable heap - overflow condition. - - - II. MISCELLANEOUS - - - Fixed compilation issues on some 64-bit platforms (see ChangeLog - for details). - - - A new demo program `ftdiff' has been added to compare TrueType - hinting, FreeType's auto hinting, and rendering without hinting - in three columns. - - -====================================================================== - -CHANGES BETWEEN 2.3.2 and 2.3.1 - - I. IMPORTANT BUG FIXES - - - FreeType returned incorrect kerning information from TrueType - fonts when the bytecode interpreter was enabled. This happened - due to a typo introduced in version 2.3.0. - - - Negative kerning values from PFM files are now reported - correctly (they were read as 16-bit unsigned values from the - file). - - - Fixed a small memory leak when `FT_Init_FreeType' failed for - some reason. - - - The Postscript hinter placed and sized very thin and ghost stems - incorrectly. - - - The TrueType bytecode interpreter has been fixed to get rid of - most of the rare differences seen in comparison to the Windows - font loader. - - - II. IMPORTANT CHANGES - - - The auto-hinter now better deals with serifs and corner cases - (e.g., glyph '9' in Arial at 9pt, 96dpi). It also improves - spacing adjustments and doesn't change widths for non-spacing - glyphs. - - - Many Mac-specific functions are deprecated (but still - available); modern replacements have been provided for them. - See the documentation in file `ftmac.h'. - - -====================================================================== - -CHANGES BETWEEN 2.3.1 and 2.3.0 - - I. IMPORTANT BUG FIXES - - - The TrueType interpreter sometimes returned incorrect horizontal - metrics due to a bug in the handling of the SHZ instruction. - - - A typo in a security check introduced after version 2.2.1 - prevented FreeType to render some glyphs in CFF fonts. - - -====================================================================== - -CHANGES BETWEEN 2.3.0 and 2.2.1 - - I. IMPORTANT BUG FIXES - - - The PCF font loader is now much more robust while loading - malformed font files. - - - Various memory leaks have been found and fixed. - - - The TrueType name loader now deals properly with some fonts that - encode their names in UTF-16 (the specification was vague, and - the code incorrectly assumed UCS-4). - - - Fixed the TrueType bytecode loader to deal properly with subtle - monochrome/gray issues when scaling the CVT. Some fonts - exhibited bad rendering artifacts otherwise. - - - `FT_GlyphSlot_Embolden' now supports vertical layouts correctly - (it mangled the vertical advance height). - - - Fixed byte endian issues of `ftmac.c' to support Mac OS X on - i386. - - - The PFR font loader no longer erroneously tags font files - without any outlines as FT_FACE_FLAG_SCALABLE. - - - II. NEW API FUNCTIONS - - - `FT_Library_SetLcdFilter' allows you to select a special filter - to be applied to the bitmaps generated by `FT_Render_Glyph' if - one of the FT_RENDER_MODE_LCD and FT_RENDER_MODE_LCD_V modes has - been selected. This filter is used to reduce color fringes; - several settings are available through the FT_LCD_FILTER_XXX - enumeration. - - Its declaration and documentation can be found in file - `include/freetype/ftlcdfil.h' (to be accessed with macro - FT_LCD_FILTER_H). - - *IMPORTANT*: This function returns an error - (FT_Err_Unimplemented_Feature) in default builds of the library - for patent reasons. See below. - - - `FT_Get_Gasp' allows you to query the flags of the TrueType - `gasp' table for a given character pixel size. This is useful - to duplicate the text rendering of MS Windows when the native - bytecode interpreter is enabled (which isn't the default for - other patent reasons). - - Its declaration and documentation can be found in file - `include/freetype/ftgasp.h' (to be accessed with macro - FT_GASP_H). - - - III. IMPORTANT CHANGES - - - The auto-hinter has been tuned a lot to improve its results with - serif fonts, resulting in much better font rendering of many web - pages. - - - The unpatented hinter is now part of the default build of the - library; we have added code to automatically support `tricky' - fonts that need it. - - This means that FreeType should `just work' with certain Asian - fonts, like MingLiU, which cannot properly be loaded without a - bytecode interpreter, but which fortunately do not use any of - the patented bytecode opcodes. We detect these fonts by name, - so please report any font file that doesn't seem to work with - FreeType, and we shall do what we can to support it in a next - release. - - Note that the API hasn't changed, so you can still force - unpatented hinting with a special parameter to `FT_Open_Face' as - well. This might be useful in same cases; for example, a PDF - reader might present a user option to activate it to deal with - certain `tricky' embedded fonts which cannot be clearly - identified. - - If you are a developer for embedded systems, you might want to - *disable* the feature to save code space by undefining - TT_CONFIG_OPTION_UNPATENTED_HINTING in file `ftoption.h'. - - - LCD-optimized rendering is now *disabled* in all default builds - of the library, mainly due to patent issues. For more - information see: - - https://lists.gnu.org/archive/html/freetype/2006-09/msg00064.html - - A new configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING - has been introduced in `ftoption.h'; manually define it in this - file if you want to re-enable the feature. - - The change only affects the implementation, not the FreeType - API. This means that clients don't need to be modified, because - the library still generates LCD decimated bitmaps, but with the - added constraint that R=G=B on each triplet. - - The displayed result should be equal to normal anti-aliased - rendering. - - Additionally, if FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not - defined, the new `FT_Library_SetLcdFilter' function returns the - FT_Err_Unimplemented_Feature error code. - - - Some computation bugs in the TrueType bytecode interpreter were - found, which allow us to get rid of very subtle and rare - differences we had experienced with the Windows renderer. - - - It is now possible to cross-compile the library easily. See the - file `docs/INSTALL.CROSS' for details. - - - The file `src/base/ftmac.c' now contains code for Mac OS X only; - its deprecated function `FT_GetFile_From_Mac_Font_Name' always - returns an error even if the QuickDraw framework is available. - The previous version has been moved to `builds/mac/ftmac.c'. - - Selecting configure option `--with-quickdraw-carbon' makes the - build process use the original `ftmac.c' file instead of the Mac - OS X-only version. - - - IV. MISCELLANEOUS - - - Various performance and memory footprint optimizations have been - performed on the TrueType and CFF font loaders, sometimes with - very drastic benefits (e.g., the TrueType loader is now about - 25% faster; FreeType should use less heap memory under nearly - all conditions). - - - The anti-aliased rasterizer has been optimized and is now 15% to - 25% percent faster than in previous versions, depending on - content. - - - The Type 1 loader has been improved; as an example, it now skips - top-level dictionaries properly. - - - Better support for Mac fonts on POSIX systems, plus compilation - fixes for Mac OS X on ppc64 where `ftmac.c' cannot be built. - - - Configuration without `--with-old-mac-fonts' does not include - `ftmac.c' (this was the behaviour in FreeType version 2.1.10). - - - The TrueTypeGX validator (gxvalid) checks the order of glyph IDs - in the kern table. - - -====================================================================== - -CHANGES BETWEEN 2.2.1 and 2.2 - - I. IMPORTANT BUG FIXES - - - Various integer overflows have been fixed. - - - PFB fonts with MacOS resource fork weren't handled correctly on - non-MacOS platforms. - - -====================================================================== - -CHANGES BETWEEN 2.2 and 2.1.10 - -(not released officially) - - I. IMPORTANT BUG FIXES - - - Vertical metrics for SFNT fonts were incorrect sometimes. - - - The FT_HAS_KERNING macro always returned 0. - - - CFF OpenType fonts didn't return correct vertical metrics for - glyphs with outlines. - - - If FreeType was compiled without hinters, all font formats based - on PS outlines weren't scaled correctly. - - - II. IMPORTANT CHANGES - - - Version 2.2 no longer exposes its internals, this is, the header - files located in the `include/freetype/internal' directory of - the source package are not copied anymore by the `make install' - command. Consequently, a number of rogue clients which directly - access FreeType's internal functions and structures won't - compile without modification. - - We provide patches for most of those rogue clients. See the - following page for more information: - - https://www.freetype.org/freetype2/patches/rogue-patches.html - - Note that, as a convenience to our Unix desktop users, version - 2.2 is *binary* compatible with FreeType 2.1.7, which means that - installing this release on an existing distribution shall not - break any working desktop. - - - FreeType's build mechanism has been redesigned. With GNU make - it is now sufficient in most cases to edit two files: - `modules.cfg', to select the library components, and the - configuration file `include/freetype/config/ftoption.h' (which - can be copied to the objects directory). Removing unused module - directories to prevent its compilation and editing - `include/freetype/config/ftmodule.h' is no longer necessary. - - - The LIGHT hinting algorithm produces more pleasant results. - Also, using the FT_LOAD_TARGET_LIGHT flags within FT_Load_Glyph - always forces auto-hinting, as a special exception. This allows - you to experiment with it even if you have enabled the TrueType - bytecode interpreter in your build. - - - The auto hinter now employs a new algorithm for CJK fonts, based - on Akito Hirai's patch. Note that this only works for fonts - with a Unicode charmap at the moment. - - - The following callback function types have changed slightly (by - adding the `const' keyword where appropriate): - - FT_Outline_MoveToFunc - FT_Outline_LineToFunc - FT_Outline_ConicToFunc - FT_Outline_CubicToFunc - FT_SpanFunc - FT_Raster_RenderFunc - - FT_Glyph_TransformFunc - FT_Renderer_RenderFunc - FT_Renderer_TransformFunc - - Note that this doesn't affect binary backward compatibility. - - - On MacOS, new APIs have been added as replacements for legacy - APIs: `FT_New_Face_From_FSRef' for `FT_New_Face_From_FSSpec', - and `FT_GetFile_From_Mac_ATS_Name' for - `FT_GetFile_From_Mac_Name'. Legacy APIs are still available, if - FreeType is built without disabling them. - - - A new API `FT_Select_Size' has been added to select a bitmap - strike by its index. Code using other functions to select - bitmap strikes should be updated to use this function. - - - A new API `FT_Get_SubGlyph_Info' has been added to retrieve - subglyph data. This can be used by rogue clients which used to - access the internal headers to get the corresponding data. - - - In 2.1.10, the behaviour of `FT_Set_Pixel_Sizes' was changed for - BDF/PCF fonts, and only for them. This causes inconsistency. - In this release, we undo the change. The intent of the change - in 2.1.10 is to allow size selection through real dimensions, - which can now be done through `FT_Request_Size'. - - - Some security issues were discovered and fixed in the CFF and - Type 1 loader, causing crashes of FreeType by malformed font - files. - - - III. MISCELLANEOUS - - - The documentation for FT_LOAD_TARGET_XXX and FT_RENDER_MODE_XXX - values now better reflects its usage and differences: One set is - used to specify the hinting algorithm, the other to specify the - pixel rendering mode. - - - `FT_New_Face' and `FT_New_Face_From_FSSpec' in ftmac.c have been - changed to count supported scalable faces (sfnt, LWFN) only, and - to return the number of available faces via face->num_faces. - Unsupported bitmap faces (fbit, NFNT) are ignored. - - - builds/unix/configure has been improved for MacOS X. It now - automatically checks available functions in Carbon library, and - prepare to use newest functions by default. Options to specify - the dependencies of each Carbon APIs (FSSpec, FSRef, old/new - QuickDraw, ATS) are available too. By manual disabling of all - QuickDraw functionality, FreeType can be built without - `deprecated function' warnings on MacOS 10.4.x, but - FT_GetFile_Mac_Name in ftmac.c then is changed to a dummy - function, and returns an `unimplemented' error. For details see - builds/mac/README. - - - SFNT cmap handling has been improved, mainly to run much faster - with CJK fonts. - - - A new function `FT_Get_TrueType_Engine_Type (declared in - `FT_MODULE_H') is provided to determine the status of the - TrueType bytecode interpreter compiled into the library - (patented, unpatented, unimplemented). - - - Vertical metrics of glyphs are synthesized if the font does not - provide such information. You can tell whether the metrics are - synthesized or not by checking the FT_FACE_FLAG_VERTICAL flag of - the face. - - - The demo programs `ftview' and `ftstring' have been rewritten - for better readability. `ftview' has a new switch `-p' to test - FT_New_Memory_Face (instead of FT_New_Face). - - - FreeType now honours bit 1 in the `head' table of TrueType fonts - (meaning `left sidebearing point at x=0'). This helps with some - buggy fonts. - - - Rudimentary support for Adobe's new `SING Glyphlet' format. See - - https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5148.SING_Tutorial.pdf - - for more information. - - - The `ftdump' program from the `ft2demos' bundle now shows some - information about charmaps. It also supports a new switch `-v' - to increase verbosity. - - - Better AFM support. This includes track kerning support. - - -====================================================================== - -CHANGES BETWEEN 2.1.10 and 2.1.9 - - I. IMPORTANT BUG FIXES - - - The size comparison for BDF and PCF files could fail sometimes. - - - Some CFF files were still not loaded correctly. Patch from - Derek Noonburg. - - - The stroker still had some serious bugs. - - - Boris Letocha fixed a bug in the TrueType interpreter: The - NPUSHW instruction wasn't skipped correctly in IF clauses. Some - fonts like `Helvetica 75 Bold' failed. - - - Another serious bug in handling TrueType hints caused many - distortions. It has been introduced in version 2.1.8, and it is - highly recommended to upgrade. - - - FreeType didn't properly parse empty Type 1 glyphs. - - - An unbound dynamic buffer growth was fixed in the PFR loader. - - - Several bugs have been fixed in the cache sub-system. - - - FreeType behaved incorrectly when resizing two distinct but very - close character pixel sizes through `FT_Set_Char_Size' (Savannah - bug #12263). - - - The auto-hinter didn't work properly for fonts without a Unicode - charmap -- it even refused to load the glyphs. - - - II. IMPORTANT CHANGES - - - Many fixes have been applied to drastically reduce the amount of - heap memory used by FreeType, especially when using - memory-mapped font files (which is the default on Unix systems - which support them). - - - The auto-hinter has been replaced with a new module, called the - `auto-fitter'. It consumes less memory than its predecessor, - and it is prepared to support non-latin scripts better in next - releases. - - - George Williams contributed code to read kerning data from PFM - files. - - - FreeType now uses the TT_NAME_ID_PREFERRED_FAMILY and - TT_NAME_ID_PREFERRED_SUBFAMILY strings (if available) for - setting family and style in SFNT fonts (patch from Kornfeld - Eliyahu Peter). - - - A new API `FT_Sfnt_Table_Info' (in FT_TRUETYPE_TABLES_H) has - been added to retrieve name and size information of SFNT tables. - - - A new API `FT_OpenType_Validate' (in FT_OPENTYPE_VALIDATE_H) has - been added to validate OpenType tables (BASE, GDEF, GPOS, GSUB, - JSTF). After validation it is no longer necessary to check - for errors in those tables while accessing them. - - Note that this module might be moved to another library in the - future to avoid a tight dependency between FreeType and the - OpenType specification. - - - A new API in FT_BITMAP_H (`FT_Bitmap_New', `FT_Bitmap_Convert', - `FT_Bitmap_Copy', `FT_Bitmap_Embolden', `FT_Bitmap_Done') has - been added. Its use is to convert an FT_Bitmap structure in - 1bpp, 2bpp, 4bpp, or 8bpp format into another 8bpp FT_Bitmap, - probably using a different pitch, and to further manipulate it. - - - A new API `FT_Outline_Embolden' (in FT_OUTLINE_H) gives finer - control how outlines are emboldened. - - - `FT_GlyphSlot_Embolden' (in FT_SYNTHESIS_H) now handles bitmaps - also (code contributed by Chia I Wu). Note that this function - is still experimental and may be replaced with a better API. - - - The method how BDF and PCF bitmap fonts are accessed has been - refined. Formerly, FT_Set_Pixel_Sizes and FT_Set_Char_Size - were synonyms in FreeType's BDF and PCF interface. This has - changed now. FT_Set_Pixel_Sizes should be used to select the - actual font dimensions (the `strike', which is the sum of the - `FONT_ASCENT' and `FONT_DESCENT' properties), while - FT_Set_Char_Size selects the `nominal' size (the `PIXELSIZE' - property). In both functions, the width parameter is ignored. - - - III. MISCELLANEOUS - - - The BDF driver no longer converts all returned bitmaps with a - depth of 2bpp or 4bpp to a depth of 8bpp. The documentation has - not mentioned this explicitly, but implementors might have - relied on this after looking into the source files. - - - A new option `--ftversion' has been added to freetype-config to - return the FreeType version. - - - The memory debugger has been updated to dump allocation - statistics on all allocation sources in the library. This is - useful to spot greedy allocations when loading and processing - fonts. - - - We removed a huge array of constant pointers to constant strings - in the `psnames' module. The problem was that compilations in - PIC mode (i.e., when generating a Unix shared object/dll) put - the array into the non-shared writable section of the library - since absolute pointers are not relocatable by nature. - - This reduces the memory consumption by approximately 16KByte per - process linked to FreeType. We now also store the array in a - compressed form (as a trie) which saves about 20KByte of code as - well. - - - Kirill Smelkov provided patches to make src/raster/ftraster.c - compile stand-alone again. - - -====================================================================== - -CHANGES BETWEEN 2.1.9 and 2.1.8 - - I. IMPORTANT BUG FIXES - - - The function `FT_Get_CharMap_Index' was only declared, without - any real code. For consistency, it has been renamed to - `FT_Get_Charmap_Index'. (This function is needed to implement - cmap caches.) - - - `FT_Outline_Get_BBox' sometimes returned incorrect values for - conic outlines (e.g., for TrueType fonts). - - - Handling of `bhed' table has been fixed. - - - The TrueType driver with enabled byte code interpreter sometimes - returned artifacts due to incorrect rounding. This bug has been - introduced after version 2.1.4. - - - The BDF driver dropped the last glyph in the font. - - - The BDF driver now uses the DEFAULT_CHAR property (if available) - to select a glyph shape for the undefined glyph. - - - The stroker failed for closed outlines and single points. - - - II. IMPORTANT CHANGES - - - George Williams contributed code to handle Apple's font - distortion technology found in GX fonts (`avar', `cvar', `fvar', - and `gvar' tables; the Multiple Masters API has been slightly - extended to cope with the new functionality). - - - The `FT_GlyphSlotRec' structure has been extended: The elements - `lsb_delta' and `rsb_delta' give the difference between hinted - and unhinted left and right side bearings if autohinting is - active. Using those values can improve the inter-letter spacing - considerably. See the documentation of `FT_GlyphSlotRec' and - the `ftstring' demo program how to use it. - - - Loading TrueType and Type 1 fonts has been made much faster. - - - The stroker is no longer experimental (but the cache subsystem - still is). - - - III. MISCELLANEOUS - - - A new documentation file `formats.txt' describes various font - formats supported (and not supported) by FreeType. - - -====================================================================== - -CHANGES BETWEEN 2.1.8 and 2.1.7 - - I. IMPORTANT BUG FIXES - - - The native TrueType hinter contained some bugs which prevented - some fonts to be rendered correctly, most notably Legendum.otf. - - - The PostScript hinter now produces improved results. - - - The linear advance width and height values were incorrectly - rounded, making them virtually unusable if not loaded with - FT_LOAD_LINEAR_DESIGN. - - - Indexing CID-keyed CFF fonts is now working: The glyph index is - correctly treated as a CID, similar to FreeType's CID driver - module. Note that CID CMap support is still missing. - - - The FT_FACE_FLAG_GLYPH_NAMES flag is now set correctly for all - font formats. - - - Some subsetted Type 1 fonts weren't parsed correctly. This bug - has been introduced in 2.1.7. In summary, the Type 1 parser has - become more robust. - - - Non-decimal numbers weren't parsed correctly in PS fonts. - - - The WinFNT driver now correctly reports FT_ENCODING_NONE for all - but one encoding. Use the new FT_WinFNT_ID_XXX values together - with `FT_Get_WinFNT_Header' to get the WinFNT charset ID. - - - The descender metrics (face->size->metrics.descender) for WinFNT - bitmap fonts had the wrong sign. - - - The (emulated) `seac' support for CFF fonts was broken. - - - The `flex' operator didn't work for CFF fonts. - - - PS glyphs which use the `hintmask' operator haven't been - rendered correctly in some cases. - - - Metrics for BDF and PCF bitmap font formats have been fixed. - - - Autohinting is now disabled for glyphs which are vertically - distorted or mirrored (using a transformation matrix). This - fixes a bug which produced zero-height glyphs. - - - The `freetype-config' script now handles --prefix and - --exec-prefix correctly; it also returns the proper --rpath (or - -R) value if FreeType has been built as a shared library. - - - II. IMPORTANT CHANGES - - - Both PCF and BDF drivers now handle the SETWIDTH_NAME and - ADD_STYLE_NAME properties. Values are appended to - face->style_name; example: `Bold SemiCondensed'. - - - The PCF driver now handles bitmap fonts compressed with the LZW - algorithm (extension .pcf.Z, compressed with `compress'). - - - A new API function `FT_Get_CMap_Language_ID' (declared in - `tttables.h') is available to get the language ID of a - TrueType/SFNT cmap. - - - The hexadecimal format of data after the `StartData' command in - CID-keyed Type 1 fonts is now supported. While this can't occur - in file-based fonts, it can happen in document-embedded - resources of PostScript documents. - - - Embedded bitmaps in SFNT-based CFF fonts are now supported. - - - A simple API is now available to control FreeType's tracing - mechanism if compiled with FT_DEBUG_LEVEL_TRACE. See the file - `ftdebug.h' for more details. - - - YAMATO Masatake contributed improved handling of MacOS resource - forks on non-MacOS platforms (for example, Linux can mount MacOS - file systems). - - - Support for MacOS has been improved; there is now a new function - `FT_New_Face_From_FSSpec' similar to `FT_New_Face' except that - it accepts an FSSpec instead of a path. - - - The cache sub-system has been rewritten. - - - There is now support for deinstallation of faces. - - - A new API function `FTC_Manager_RemoveFaceID' has been added - to delete all `idle' nodes that correspond to a given - FTC_FaceID. All `locked' nodes (i.e., those with a reference - count > 0), will be modified to prevent them from appearing in - further lookups (they will be cleaned normally when their - reference count reaches 0). - - - There is now support for point scaling (i.e., providing - character sizes in points + dpis, instead of pixels). - - - Three abstract cache classes are now available: - - FTC_GCache: Used to store one glyph item per cache node, - with the ability to group common attributes into - `families'. This replaces the old - FTC_GlyphCache class. - - FTC_ICache: Used to store one FT_Glyph per cache node. This - extends FTC_GCache. Family definition, family - comparison, and glyph loading are however left - to sub-classes. - - FTC_SCache: Used to store up to 16 small bitmaps per cache - node. This extends FTC_GCache. Family - definition, family comparison and glyph loading - are however left to sub-classes. - - - The file `src/cache/ftcbasic.c' implements: - - FTC_ImageCache: Extends FTC_ICache; implements family - definitions and glyph loading similar to the - old API. - - FTC_SBitCache: Extends FTC_SCache, implements family - definitions and glyph loading similar to the - old API - - Client applications should be able to extend FTC_GCache, - FTC_ICache, or FTC_SCache much more easily (i.e., less code to - write, and less callbacks). For example, one could envision - caches that are capable of storing transformed (obliqued), - stroked, emboldened, or colored glyph images. Use - `ftcbasic.c' as an example. - - - All public APIs are now in `include/freetype/ftcache.h', (to - be accessed as `FT_CACHE_H'). The contents of - `include/freetype/cache/' is only needed by applications that - wish to implement their own caches. - - - There were some major performance improvements through the use - of various programming tricks. Cache hits are up to 70% - faster than in the old code. - - - The FTC_CMapCache has been simplified. Charmaps can only be - accessed by index right now. There is also a new API named - `FT_Charmap_GetIndex' for this purpose. - - - The demo programs have been updated to the new code. The - previous versions will not work with the current one. - - - Using an invalid face index in FT_Open_Face and friends now - causes an error even if the font contains a single face only. - - - III. MISCELLANEOUS - - - Wolfgang Domröse contributed support files for building FreeType - on the Atari using the PureC compiler. Note that the Atari is a - 16bit platform. - - - Vitaliy Pasternak contributed project files for VS.NET 2003. - - -====================================================================== - -CHANGES BETWEEN 2.1.7 and 2.1.6 - - I. IMPORTANT BUG FIXES - - - Updated to newest libtool version, fixing build problems on - various platforms. - - - On Unix platforms, `make install' didn't copy the correct - `ftconfig.h' file. - - Note that version 2.1.7 contains the same library C source code as - version 2.1.6. - - -====================================================================== - -CHANGES BETWEEN 2.1.6 and 2.1.5 - - I. IMPORTANT BUG FIXES - - - The PFR font driver didn't load kerning tables correctly, and - the functions in FT_PFR_H didn't work at all. - - - Type 1 font files in binary format (PFB) with an end-of-file - indicator weren't accepted by the FreeType engine. - - - Fonts which contain /PaintType and /StrokeWidth no longer cause - a segfault. This bug has been introduced in version 2.1.5. - - - Fonts loaded with FT_LOAD_RENDER no longer cause strange - results. This bug has been introduced in version 2.1.5. - - - Some Windows (bitmap) FNT/FON files couldn't be handled - correctly. - - - II. IMPORTANT CHANGES - - - The internal module API has been heavily changed in favor of - massive simplifications within the font engine. This also means - that authors of third-party modules must adapt their code to the - new scheme. - - NOTE: THE NEW SCHEME IS NOT COMPLETED YET. PLEASE WAIT UNTIL A - FINAL ANNOUNCEMENT! - - - The PostScript parser has been enhanced to handle comments and - strings correctly. Additionally, more syntax forms are - recognized. - - - Added the optional unpatented hinting system for TrueType. It - allows typefaces which need hinting to produce correct glyph - forms (e.g., Chinese typefaces from Dynalab) to work acceptably - without infringing Apple patents. This system is compiled only - if TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING is defined in - ftoption.h (activated by default). - - - III. MISCELLANEOUS - - - There is now a guard in the public header files to protect - against inclusion of freetype.h from FreeType 1. - - - Direct inclusion of freetype.h and other public header files no - longer works. You have to use the documented scheme - - #include - #include FT_FREETYPE_H - - to load freetype.h with a symbolic name. This protects against - renaming of public header files (which shouldn't happen but - actually has, avoiding two public header files with the same - name). - - -====================================================================== - -CHANGES BETWEEN 2.1.5 and 2.1.4 - - I. IMPORTANT BUG FIXES - - - Parsing the /CIDFontName field now removes the leading slash to - be in sync with other font drivers. - - - gzip support was buggy. Some fonts could not be read. - - - Fonts which have nested subglyphs more than one level deep no - longer cause a segfault. - - - Creation of synthetic cmaps for fonts in CFF format was broken - partially. - - - Numeric font dictionary entries for synthetic fonts are no - longer overwritten. - - - The font matrix wasn't applied to the advance width for Type1, - CID, and CFF fonts. This caused problems when loading certain - synthetic Type 1 fonts like `Helvetica Narrow'. - - - The test for the charset registry in BDF and PCF fonts is now - case-insensitive. - - - FT_Vector_Rotate sometimes returned strange values due to - rounding errors. - - - The PCF driver now returns the correct number of glyphs - (including an artificial `notdef' glyph at index 0). - - - FreeType now supports buggy CMaps which are contained in many - CJK fonts from Dynalab. - - - Opening an invalid font on a Mac caused a segfault due to - double-freeing memory. - - - BDF fonts with more than 32768 glyphs weren't supported - properly. - - - II. IMPORTANT CHANGES - - - Accessing bitmap font formats has been synchronized. To do that - the FT_Bitmap_Size structure has been extended to contain new - fields `size', `x_ppem', and `y_ppem'. - - - The FNT driver now returns multiple faces, not multiple strikes. - - - The `psnames' module has been updated to the Adobe Glyph List - version 2.0. - - - The `psnames' module now understands `uXXXX[X[X]]' glyph names. - - - The algorithm for guessing the font style has been improved. - - - For fonts in SFNT format, root->height is no longer increased if - the line gap is zero. There exist fonts (containing e.g. form - drawing characters) which intentionally have a zero line gap - value. - - - ft_glyph_bbox_xxx flags are now deprecated in favour of - FT_GLYPH_BBOX_XXX. - - - ft_module_xxx flags are now deprecated in favour of - FT_MODULE_XXX. - - - FT_ENCODING_MS_{SJIS,GB2312,BIG5,WANSUNG,JOHAB} are now - deprecated in favour of - FT_ENCODING_{SJIS,GB2312,BIG5,WANSUNG,JOHAB} -- those encodings - are not specific to Microsoft. - - - III. MISCELLANEOUS - - - The autohinter has been further improved; for example, `m' - glyphs now retain its vertical symmetry. - - - Partial support of Mac fonts on non-Mac platforms. - - - `make refdoc' (after first `make') builds the HTML - documentation. You need Python for this. - - - The make build system should now work more reliably on DOS-like - platforms. - - - Support for EMX gcc and Watson C/C++ compilers on MS-DOS has - been added. - - - Better VMS build support. - - - Support for the pkg-config package by providing a `freetype.pc' - file. - - - New configure option --with-old-mac-fonts for Darwin. - - - Some source files have been renamed (mainly to fit into the 8.3 - naming scheme). - - -====================================================================== - -CHANGES BETWEEN 2.1.4 and 2.1.3 - - I. IMPORTANT BUG FIXES - - - Updated to newest libtool version, fixing build problems on - various platforms. - - - A fix in the Gzip stream reader: It couldn't read certain .gz - files properly due to a small typo. In certain cases, FreeType - could also loop endlessly when trying to load tiny gzipped - files. - - - The configure script now tries to use the system-wide zlib when - it finds one (instead of the copy found in src/gzip). And - `freetype-config' has been updated to return relevant flags in - this case when invoked with `--libs' (e.g. `-lzlib'). - - - Certain fonts couldn't be loaded by 2.1.3 because they lacked a - Unicode charmap (e.g. SYMBOL.TTF). FreeType erroneously - rejected them. - - - The CFF loader was modified to accept fonts which only contain a - subset of their reference charset. This prevented the correct - use of PDF-embedded fonts. - - - The logic to detect Unicode charmaps has been modified. This is - required to support fonts which include both 16-bit and 32-bit - charmaps (like very recent asian ones) using the new 10 and 12 - SFNT formats. - - - The TrueType loader now limits the depth of composite glyphs. - This is necessary to prevent broken fonts to break the engine by - blowing the stack with recursive glyph definitions. - - - The CMap cache is now capable of managing UCS-4 character codes - that are mapped through extended charmaps in recent - TrueType/OpenType fonts. - - - The cache sub-system now properly manages out-of-memory - conditions instead of blindly reporting them to the caller. - This means that it will try to empty the cache before restarting - its allocations to see if that can help. - - - The PFR driver didn't return the list of available embedded - bitmaps properly. - - - There was a nasty memory leak when using embedded bitmaps in - certain font formats. - - - II. IMPORTANT CHANGES - - - David Chester contributed some enhancements to the auto-hinter - that significantly increase the quality of its output. The - Postscript hinter was also improved in several ways. - - - The FT_RENDER_MODE_LIGHT render mode was implemented. - - - A new API function called `FT_Get_BDF_Property' has been added - to FT_BDF_H to retrieve BDF properties from BDF _and_ PCF font - files. THIS IS STILL EXPERIMENTAL, since it hasn't been - properly tested yet. - - - A Windows FNT specific API has been added, mostly to access font - headers. This is used by Wine. - - - TrueType tables without an `hmtx' table are now tolerated when - an incremental interface is used. This happens for certain - Type42 fonts passed from Ghostscript to FreeType. - - - The PFR font driver is now capable of returning the font family - and style names when they are available (instead of the sole - `FontID'). This is performed by parsing an *undocumented* - portion of the font file! - - - III. MISCELLANEOUS - - - The path stroker in FT_STROKER_H has entered beta stage. It now - works very well, but its interface might change a bit in the - future. More on this in later releases. - - - The documentation for FT_Size_Metrics didn't appear properly in - the API reference. - - - The file docs/VERSION.DLL has been updated to explain versioning - with FreeType (i.e., comparing release/libtool/so numbers, and - how to use them in autoconf scripts). - - - The installation documentation has been seriously revamped. - Everything is now in the `docs' directory. - - -====================================================================== - -CHANGES BETWEEN 2.1.3 and 2.1.2 - - I. IMPORTANT BUG FIXES - - - FT_Vector_Transform had been incorrectly modified in 2.1.2, - resulting in incorrect transformations being applied (for - example, rotations were processed in opposite angles). - - - The format 8 and 12 TrueType charmap enumeration routines have - been fixed (FT_Get_Next_Char returned invalid values). - - - The PFR font driver returned incorrect advance widths if the - outline and metrics resolution defined in the font file were - different. - - - FT_Glyph_To_Bitmap now returns successfully when called with an - FT_BitmapGlyph argument (it previously returned an error). - - - A bug in the Type 1 loader that prevented valid font bounding - boxes to be loaded from multiple master fonts. - - - The SFNT validation code has been rewritten. FreeType can now - load `broken' fonts that were usable on Windows, but not with - previous versions of the library. - - - The computation of bearings in the BDF driver has been fixed. - - - The Postscript hinter crashed when trying to hint certain glyphs - (more precisely, when trying to apply hints to an empty glyph - outline). - - - The TrueType glyph loader now supports composites in `Apple - format' (they differ slightly from Microsoft/OpenType ones in - the way transformation offsets are computed). - - - FreeType was very slow at opening certain asian CID/CFF fonts, - due to fixed increment in dynamic array re-allocations. This - has been changed to exponential behaviour to get acceptable - performance. - - - - II. IMPORTANT CHANGES - - - The PCF driver now supports gzip-compressed font files natively. - This means that you will be able to use all these bitmap fonts - that come with XFree86 with FreeType (and libXft/libXft2, by - extension). - - - The automatic and postscript hinters have both been updated. - This results in a relatively important increase of rendering - quality since many nasty defaults have been suppressed. Please - visit the web page: - - https://www.freetype.org/hinting/smooth-hinting.html - - for additional details on this topic. - - - The `load_flags' parameter of `FT_Load_Glyph' is now an FT_Int32 - (instead of just being an FT_Int). This breaks source and - binary compatibility for 16bit systems only, while retaining - both of them for 32 and 64 bit ones. - - Some new flags have been added consequently: - - FT_LOAD_NO_AUTOHINT :: Disable the use of the auto-hinter - (but not native format hinters). - - FT_LOAD_TARGET_NORMAL :: Hint and render for normal - anti-aliased displays. - - FT_LOAD_TARGET_MONO :: Hint and render for 1-bit displays. - - FT_LOAD_TARGET_LCD :: Hint and render for horizontal RGB or - BGR subpixel displays (like LCD - screens). THIS IS STILL - EXPERIMENTAL! - - FT_LOAD_TARGET_LCD_V :: Same as FT_LOAD_TARGET_LCD, for - vertical subpixel displays (like - rotated LCD screens). THIS IS STILL - EXPERIMENTAL! - - FT_LOAD_MONOCHROME is still supported, but only affects - rendering, not the hinting. - - Note that the `ftview' demo program available in the `ft2demos' - package has been updated to support LCD-optimized display on - non-paletted displays (under Win32 and X11). - - - The PFR driver now supports embedded bitmaps (all formats - supported), and returns correct kerning metrics for all glyphs. - - - The TrueType charmap loader now supports certain `broken' fonts - that load under Windows without problems. - - - The cache API has been slightly modified (it's still a beta!): - - - The type FTC_ImageDesc has been removed; it is now replaced - by FTC_ImageTypeRec. Note that one of its fields is a - `load_flag' parameter for FT_Load_Glyph. - - - The field `num_grays' of FT_SBitRec has been changed to - `max_grays' in order to fit within a single byte. Its - maximum value is thus 255 (instead of 256 as previously). - - - III. MISCELLANEOUS - - - Added support for the DESTDIR variable during `make install'. - This simplifies packaging of FreeType. - - - Included modified copies of the ZLib sources in `src/gzip' in - order to support gzip-compressed PCF fonts. We do not use the - system-provided zlib for now, though this is a probable - enhancement for future releases. - - - The DocMaker tool used to generate the on-line API reference has - been completely rewritten. It is now located in - `src/tools/docmaker/docmaker.py'. Features: - - - better cross-referenced output - - more polished output - - uses Python regular expressions (though it didn't speed the - program) - - much more modular structure, which allows for different - `backends' in order to generate HTML, XML, or whatever - format. - - One can regenerate the API reference by calling: - - python src/tools/docmaker/docmaker.py \ - --prefix=ft2 \ - --title=FreeType-2.1.3 \ - --output= - include/freetype/*.h \ - include/freetype/config/*.h \ - include/freetype/cache/*.h - - - A new, experimental, support for incremental font loading (i.e., - loading of fonts where the glyphs are not in the font file - itself, but provided by an external component, like a Postscript - interpreter) has been added by Graham Asher. This is still work - in progress, however. - - - A new, EXPERIMENTAL, path stroker has been added. It doesn't - suffer from severe rounding errors and treat bezier arcs - directly. Still work in progress (i.e. not part of the official - API). See the file for some of the - details. - - - The massive re-formatting of sources and internal re-design is - still under-way. Many internal functions, constants, and types - have been renamed. - - -====================================================================== - -CHANGES BETWEEN 2.1.2 and 2.1.1 - - I. IMPORTANT BUG FIXES - - - Many font drivers didn't select a Unicode charmap by default - when a new face was opened (with the FT_CONFIG_OPTION_USE_CMAPS - options enabled), causing many applications to not be able to - display text correctly with the 2.1.x releases. - - - The PFR driver had a bug in its composite loading code that - produces incorrectly placed accents with many fonts. - - - The Type42 driver crashed sometimes due to a nasty bug. - - - The Type 1 custom encoding charmap didn't handle the case where - the first glyph index wasn't 0. - - - A serious typo in the TrueType composite loader produced - incorrectly placed glyphs in fonts like `Wingdings' and a few - others. - - - II. MISCELLANEOUS - - - The Win32 Visual C++ project file has been updated to include - the PFR driver as well. - - - `freetype.m4' is now installed by default by `make install' on - Unix systems. - - - The function FT_Get_PS_Font_Info now works with CID and Type42 - fonts as well. - - -====================================================================== - -CHANGES BETWEEN 2.1.1 and 2.1.0 - - I. IMPORTANT BUG FIXES - - - The `version_info' returned by `freetype-config' in 2.1.0 - returned an invalid value. It now returns 9:1:3 (2.0.9 returned - 9:0:3). - - - Version 2.1.0 couldn't be linked against applications on Win32 - and Amiga systems due to a new debug function that wasn't - properly propagated to the system-specific directory in - `builds'. - - - Various MacOS and Mac OS X specific fixes. - - - Fixed a bug in the TrueType charmap validation routines that - made version 2.1.0 too restrictive -- many popular fonts have - been rejected. - - - There was still a very small difference between the monochrome - glyph bitmaps produced by FreeType 1.x and FreeType 2.x with the - bytecode interpreter enabled. This was caused by an invalid - flag setting in the TrueType glyph loader, making the rasterizer - change its drop-out control mode. Now the results should - _really_ be completely identical. - - - The TrueType name table loader has been improved to support many - popular though buggy Asian fonts. It now ignores empty name - entries, invalid pointer offsets and a few other incorrect - subtleties. Moreover, name strings are now loaded on demand, - which reduces the memory load of many faces (e.g. the ARIAL.TTF - font file contains a 10kByte name table with 70 names). - - - Fixed a bug in the Postscript hinter that prevented family blues - substitution to happen correctly. - - - II. NEW FEATURES - - - Three new font drivers in this release: - - * A BDF font driver, contributed by Franco Zappa Nardelli, - heavily modified by Werner Lemberg. It also supports - anti-aliased bitmaps (using a slightly extended BDF format). - - * A Type42 font driver, contributed by Roberto Alameda. It is - still experimental but seems to work relatively well. - - * A PFR font driver, contributed by David Turner himself. It - doesn't support PFR hinting -- note that BitStream has at - least two patents on this format! - - - III. MISCELLANEOUS - - - The cache sub-system has been optimized in important ways. - Cache hits are now significantly faster. For example, using the - CMap cache is about twice faster than calling FT_Get_Char_Index - on most platforms. Similarly, using an SBit cache is about five - times faster than loading the bitmaps from a bitmap file, and - 300 to 500 times faster than generating them from a scalable - format. - - Note that you should recompile your sources if you designed a - custom cache class for the FT2 Cache subsystem, since the - changes performed are source, but not binary, compatible. - - -====================================================================== - -CHANGES BETWEEN 2.1.0 and 2.0.9 - - I. IMPORTANT BUG FIXES - - - The TrueType bytecode interpreter has been fixed to produce - _exactly_ the same output as FreeType 1.x. Previous differences - were due to slightly distinct fixed-point computation routines - used to perform dot products and vector length measurements. - - It seems that native TrueType hinting is _extremely_ sensitive - to rounding errors. The required vector computation routines - have been optimized and placed within the `ttinterp.c' file. - - - Fixed the parsing of accelerator tables in the PCF font driver. - - - Fixed the Type1 glyph loader routine used to compute the font's - maximum advance width. - - - II. NEW FEATURES - - - The `configure' script used on Unix systems has been modified to - check that GNU Make is being used to build the library. - Otherwise, it will display a message proposing to use the - GNUMAKE environment variable to name it. - - The Unix-specific file README.UNX has been modified accordingly. - - - III. MISCELLANEOUS - - - The FreeType License in `docs/FTL.TXT' has been updated to - include a proposed preferred disclaimer. If you are using - FreeType in your products, you are encouraged (but not mandated) - to use the following text in your documentation: - - """ - Portions of this software are copyright © 1996-2002 The - FreeType Project (www.freetype.org). All rights reserved. - """ - - - The default size of the render pool has been reduced to 16kByte. - This shouldn't result in any noticeable performance penalty, - unless you are using the engine as-is to render very large and - complex glyphs. - - - The FreeType 2 redesign has begun. More information can be - found at this URL: - - https://www.freetype.org/freetype2/redesign.html - - The following internal changes have been performed within the - sources of this release: - - - Many internal types have been renamed to increase - consistency. The following should be true, except for - public types: - - * All structure types have a name ending in `Rec' (short - for `record'). - - * A pointer-to-structure type has the same name as the - structure, _without_ the `Rec' suffix. - - Example: - - typedef struct FooRec_ - { - ... - - } FooRec, *Foo; - - - Many internal macros have been renamed to increase - consistency. The following should be true: - - * All macros have a name beginning with `FT_'. This - required a few changes like - - ALLOC => FT_ALLOC - FREE => FT_FREE - REALLOC => FT_REALLOC - - * All macros are completely UPPERCASE. This required a - few changes like: - - READ_Short => FT_READ_SHORT - NEXT_Short => FT_NEXT_SHORT - GET_ULongLE => FT_GET_ULONG_LE - MEM_Set => FT_MEM_SET - MEM_Copy => FT_MEM_COPY - etc. - - * Whenever possible, all macro names follow the - FT__ pattern. For example - - ACCESS_Frame => FT_FRAME_ENTER - FORGET_Frame => FT_FRAME_EXIT - EXTRACT_Frame => FT_FRAME_EXTRACT - RELEASE_Frame => FT_FRAME_RELEASE - - FILE_Pos => FT_STREAM_POS - FILE_Seek => FT_STREAM_SEEK - FILE_Read => FT_STREAM_READ - FILE_ReadAt => FT_STREAM_READ_AT - READ_Fields => FT_STREAM_READ_FIELDS - - - Many internal functions have been renamed to follow the - FT__ pattern. For example: - - FT_Seek_Stream => FT_Stream_Seek - FT_Read_Stream_At => FT_Stream_ReadAt - FT_Done_Stream => FT_Stream_Close - FT_New_Stream => FT_Stream_Open - FT_New_Memory_Stream => FT_Stream_OpenMemory - FT_Extract_Frame => FT_Stream_ExtractFrame - - Note that method names do not contain `_'. - - - The FT_ALLOC_ARRAY and FT_REALLOC_ARRAY have been replaced - with FT_NEW_ARRAY and FT_RENEW_ARRAY which do not take a - type as the fourth argument. Instead, the array element - type size is computed automatically from the type of the - target pointer used. - - - A new object class, FT_CMap, has been introduced. These - internal objects are used to model character maps. This - eases the support of additional charmap types within the - engine. - - - A new configuration file named `ftstdlib.h' has been added - to `include/freetype/config'. It is used to define aliases - for _every_ routine of the ISO C library that the font - engine uses. Each aliases has a `ft_' prefix - (e.g. `ft_strlen' is an alias for `strlen'). - - This is used to ease the porting of FreeType 2 to exotic - runtime environments where the ISO C Library isn't available - (e.g. XFree86 extension modules). - - More details are available in the `ChangeLog' file. - - -====================================================================== - -CHANGES BETWEEN 2.0.9 and 2.0.8 - - I. IMPORTANT BUG FIXES - - - Certain fonts like `foxjump.ttf' contain broken name tables with - invalid entries and wild offsets. This caused FreeType to crash - when trying to load them. - - The SFNT `name' table loader has been fixed to be able to - support these strange fonts. - - Moreover, the code in charge of processing this table has been - changed to always favour Windows-formatted entries over other - ones. Hence, a font that works on Windows but not on the Mac - will load cleanly in FreeType and report accurate values for - Family & PostScript names. - - - The CID font driver has been fixed. It unfortunately returned a - Postscript Font name with a leading slash, as in - `/MunhwaGothic-Regular'. - - - FreeType 2 should now compile fine on AIX 4.3.3 as a shared - library. - - - A bug in the Postscript hinter has been found and fixed, - removing un-even stem widths at small pixel sizes (like 14-17). - - This improves the quality of a certain number of Postscript - fonts. - - - II. NEW FEATURES - - - A new function named `FT_Library_Version' has been added to - return the current library's major, minor, and patch version - numbers. This is important since the macros FREETYPE_MAJOR, - FREETYPE_MINOR, and FREETYPE_PATCH cannot be used when the - library is dynamically linked by a program. - - - Two new APIs have been added: `FT_Get_First_Char' and - `FT_Get_Next_Char'. - - Together, these can be used to iterate efficiently over the - currently selected charmap of a given face. Read the API - reference for more details. - - - III. MISCELLANEOUS - - - The FreeType sources are under heavy internal re-factoring. As - a consequence, we have created a branch named `STABLE' on the - CVS to hold all future releases/fixes in the 2.0.x family. - - The HEAD branch now contains the re-factored sources and - shouldn't be used for testing or packaging new releases. In - case you would like to access the 2.0.9 sources from our CVS - repository, use the tag `VER-2-0-9'. - - -====================================================================== - -CHANGES BETWEEN 2.0.8 and 2.0.7 - - I. IMPORTANT BUG FIXES - - - There was a small but nasty bug in `freetype-config.in' which - caused the `freetype-config' script to fail on Unix. - - This didn't prevent the installation of the library or even its - execution, but caused problems when trying to compile many Unix - packages that depend on it. - - - Some TrueType or OpenType fonts embedded in PDF documents do not - have a 'cmap', 'post' and 'name' as is required by the - specification. FreeType no longer refuses to load such fonts. - - - Various fixes to the PCF font driver. - - -====================================================================== - -CHANGES BETWEEN 2.0.7 and 2.0.6 - - I. IMPORTANT BUG FIXES - - - Fixed two bugs in the Type 1 font driver. The first one - resulted in a memory leak in subtle cases. The other one caused - FreeType to crash when trying to load `.gsf' files (Ghostscript - so-called Postscript fonts). - - (This made _many_ KDE applications crash on certain systems. - FreeType _is_ becoming a critical system component on Linux :-) - - - Fixed a memory leak in the CFF font driver. - - - Fixed a memory leak in the PCF font driver. - - - Fixed the Visual C++ project file - `builds/win32/visualc/freetype.dsp' since it didn't include the - Postscript hinter component, causing errors at build time. - - - Fixed a small rendering bug in the anti-aliased renderer that - only occurred when trying to draw thin (less than 1 pixel) - strokes. - - - Fixed `builds/unix/freetype2.a4' which is used to generate a - valid `freetype2.m4' for use with autoconf. - - - Fixed the OpenVMS Makefiles. - - - II. MISCELLANEOUS - - - Added `configure' and `install' scripts to the top-level - directory. A GNU-style installation is thus now easily possible - with - - ./configure - make - make install - - -====================================================================== - -CHANGES BETWEEN 2.0.6 and 2.0.5 - - I. IMPORTANT BUG FIXES - - - It wasn't possible to load embedded bitmaps when the auto-hinter - was used. This is now fixed. - - - The TrueType font driver didn't load some composites properly - (the sub-glyphs were slightly shifted, and this was only - noticeable when using monochrome rendering). - - - Various fixes to the auto-hinter. They merely improve the - output of sans-serif fonts. Note that there are still problems - with serifed fonts and composites (accented characters). - - - All scalable font drivers erroneously returned un-fitted glyph - advances when hinting was requested. This created problems for - a number of layout applications. This is a very old bug that - got undetected mainly because most test/demo program perform - rounding explicitly or implicitly (through the cache). - - - `FT_Glyph_To_Bitmap' did erroneously modify the source glyph in - certain cases. - - - `glnames.py' still contained a bug that made FreeType return - invalid names for certain glyphs. - - - The library crashed when loading certain Type 1 fonts like - `sadn.pfb' (`Stalingrad Normal'), which appear to contain - pathetic font info dictionaries. - - - The TrueType glyph loader is now much more paranoid and checks - everything when loading a given glyph image. This was necessary - to avoid problems (crashes and/or memory overwrites) with broken - fonts that came from a really buggy automatic font converter. - - - II. IMPORTANT UPDATES AND NEW FEATURES - - - Important updates to the Mac-specific parts of the library. - - - The caching sub-system has been completely re-designed, and its - API has evolved (the old one is still supported for backward - compatibility). - - The documentation for it is not yet completed, sorry. For now, - you are encouraged to continue using the old API. However, the - ftview demo program in the ft2demos package has already been - updated to use the new caching functions. - - - A new charmap cache is provided too. See `FTC_CMapCache'. This - is useful to perform character code -> glyph index translations - quickly, without the need for an opened FT_Face. - - - A NEW POSTSCRIPT HINTER module has been added to support native - hints in the following formats: PostScript Type 1, PostScript - CID, and CFF/CEF. - - Please test! Note that the auto-hinter produces better results - for a number of badly-hinted fonts (mostly auto-generated ones) - though. - - - A memory debugger is now part of the standard FreeType sources. - To enable it, define FT_DEBUG_MEMORY in - , and recompile the library. - - Additionally, define the _environment_ variable FT_DEBUG_MEMORY - and run any program using FreeType. When the library is exited, - a summary of memory footprints and possible leaks will be - displayed. - - This works transparently with _any_ program that uses FreeType. - However, you will need a lot of memory to use this (allocated - blocks are never released to the heap to detect double deletes - easily). - - - III. MISCELLANEOUS - - - We are aware of subtle differences between the output of - FreeType versions 1 and 2 when it comes to monochrome - TrueType-hinted glyphs. These are most probably due to small - differences in the monochrome rasterizers and will be worked out - in an upcoming release. - - - We have decided to fork the sources in a `stable' branch, and an - `unstable' one, since FreeType is becoming a critical component - of many Unix systems. - - The next bug-fix releases of the library will be named 2.0.7, - 2.0.8, etc., while the `2.1' branch will contain a version of - the sources where we will start major reworking of the library's - internals, in order to produce FreeType 2.2.0 (or even 3.0) in a - more distant future. - - We also hope that this scheme will allow much more frequent - releases than in the past. - - -====================================================================== - -CHANGES BETWEEN 2.0.5 and 2.0.4 - - NOTE THAT 2.0.5 DOES NOT CONTAIN THE POSTSCRIPT HINTER. THIS MODULE - WILL BE PART OF THE NEXT RELEASE (EITHER 2.0.6 or 2.1) - - - Fixed a bug that made certain glyphs, like `Cacute', `cacute' and - `lslash' unavailable from Unicode charmaps of Postscript fonts. - This prevented the correct display of Polish text, for example. - - - The kerning table of Type 1 fonts was loaded by FreeType, when its - AFM file was attached to its face, but the - FT_FACE_FLAG_HAS_KERNING bit flags was not set correctly, - preventing FT_Get_Kerning to return meaningful values. - - - Improved SFNT (TrueType & OpenType) charmap support. Slightly - better performance, as well as support for the new formats defined - by the OpenType 1.3 specification (8, 10, and 12) - - - Fixed a serious typo in `src/base/ftcalc.c' which caused invalid - computations in certain rare cases, producing ugly artefacts. - - - The size of the EM square is computed with a more accurate - algorithm for Postscript fonts. The old one caused slight errors - with embedded fonts found in PDF documents. - - - Fixed a bug in the cache manager that prevented normal LRU - behaviour within the cache manager, causing unnecessary reloads - (for FT_Face and FT_Size objects only). - - - Added a new function named `FT_Get_Name_Index' to retrieve the - glyph index of a given glyph name, when found in a face. - - - Added a new function named `FT_Get_Postscript_Name' to retrieve - the `unique' Postscript font name of a given face. - - - Added a new public header size named FT_SIZES_H (or - ) providing new FT_Size-management functions: - FT_New_Size, FT_Activate_Size, FT_Done_Size. - - - Fixed a reallocation bug that generated a dangling pointer (and - possibly memory leaks) with Postscript fonts (in - src/psaux/psobjs.c). - - - Many fixes for 16-bit correctness. - - - Removed many pedantic compiler warnings from the sources. - - - Added an Amiga build directory in `builds/amiga'. - - -====================================================================== - -CHANGES BETWEEN 2.0.4 and 2.0.3 - - - Fixed a rather annoying bug that was introduced in 2.0.3. Namely, - the font transformation set through FT_Set_Transform was applied - twice to auto-hinted glyphs, resulting in incorrectly rotated text - output. - - - Fixed _many_ compiler warnings. FT2 should now compile cleanly - with Visual C++'s most pedantic warning level (/W4). It already - compiled fine with GCC and a few other compilers. - - - Fixed a bug that prevented the linear advance width of composite - TrueType glyphs to be correctly returned. - - - Fixed the Visual C++ project files located in - `builds/win32/visualc' (previous versions used older names of the - library). - - - Many 32-bit constants have an `L' appended to their value, in - order to improve the 16-bitness of the code. Someone is actually - trying to use FT2 on an Atari ST machine! - - - Updated the `builds/detect.mk' file in order to automatically - build FT2 on AIX systems. AIX uses `/usr/sbin/init' instead of - `/sbin/init' and wasn't previously detected as a Unix platform by - the FreeType build system. - - - Updated the Unix-specific portions of the build system (new - libtool version, etc.). - - - The SFNT kerning loader now ensures that the table is sorted - (since some problem fonts do not meet this requirement). - - -======================================================================= - -CHANGES BETWEEN 2.0.3 and 2.0.2 - - I. CHANGES TO THE MODULES / FONT DRIVERS - - - THE AUTO-HINTER HAS BEEN SLIGHTLY IMPROVED, in order to fix - several annoying artefacts, mainly: - - - Blue zone alignment of horizontal stems wasn't performed - correctly, resulting in artefacts like the `d' being placed - one pixel below the `b' in some fonts like Time New Roman. - - - Overshoot thresholding wasn't performed correctly, creating - unpleasant artefacts at large character pixel sizes. - - - Composite glyph loading has been simplified. This gets rid - of various artefacts where the components of a composite - glyphs were not correctly spaced. - - These are the last changes to the current auto-hinting module. - A new hinting sub-system is currently in the work in order to - support native hints in Type 1 / CFF / OpenType fonts, as well - as globally improve rendering. - - - The PCF driver has been fixed. It reported invalid glyph - dimensions for the fonts available on Solaris. - - - The Type 1, CID and CFF drivers have been modified to fix the - computation of the EM size. - - - The Type 1 driver has been fixed to avoid a dangerous bug that - crashed the library with non-conforming fonts (i.e. ones that do - not place the .notdef glyph at position 0). - - - The TrueType driver had a rather subtle bug (dangling pointer - when loading composite glyphs) that could crash the library in - rare occasions! - - - II. HIGH-LEVEL API CHANGES - - - The error code enumeration values have been changed. An error - value is decomposed in a generic error code, and a module - number. see for details. - - - A new public header file has been introduced, named - FT_TRIGONOMETRY_H (include/freetype/fttrigon.h), providing - trigonometric functions to compute sines, cosines, arctangents, - etc. with 16.16 fixed precision. The implementation is based on - the CORDIC algorithm and is very fast while being sufficiently - accurate. - - - III. INTERNALS - - - Added BeOS-specific files in the old build sub-system. Note - that no changes were required to compile the library with Jam. - - - The configuration is now capable of automatically detecting - 64-bit integers on a set of predefined compilers (GCC, Visual - C++, Borland C++) and will use them by default. This provides a - small performance boost. - - - A small memory leak that happened when opening 0-sized files - (duh!) have been fixed. - - - Fixed bezier stack depth bug in the routines provided by the - FT_BBOX_H header file. Also fixed similar bugs in the - rasterizers. - - - The outline bounding box code has been rewritten to use direct - computations, instead of bezier sub-division, to compute the - exact bounding box of glyphs. This is slightly slower but more - accurate. - - - The build system has been improved and fixed, mainly to support - `make' on Windows 2000 correctly, avoid problems with `make - distclean' on non Unix systems, etc. - - - Hexadecimal constants have been suffixed with `U' to avoid - problems with certain compilers on 64-bit platforms. - - - A new directory named `src/tools' has been created. It contains - Python scripts and simple unit test programs used to develop the - library. - - - The DocMaker tool has been moved from `docs' to `src/tools' and - has been updated with the following: - - - Now accepts the `--title=XXXX' or `-t XXXX' option from the - command line to set the project's name in the generated API - reference. - - - Now accepts the `--output=DIR' or `-o DIR' option from the - command line to set the output directory for all generated - HTML files. - - - Now accepts the `--prefix=XXXX' or `-p XXX' option from the - command line to set the file prefix to use for all - generated HTML files. - - - Now generates the current time/data on each generated page - in order to distinguish between versions. - - DocMaker can be used with other projects now, not only FT2 - (e.g. MLib, FTLayout, etc.). - - -====================================================================== - -CHANGES BETWEEN 2.0.2 and 2.0.1 - - I. CHANGES TO THE MODULES / FONT DRIVERS - - - THE TRUETYPE BYTECODE INTERPRETER IS NOW TURNED OFF, in order to - avoid legal problems with the Apple patents. It seems that we - mistakenly turned this option on in previous releases of the - build. - - Note that if you want to use the bytecode interpreter in order - to get high-quality TrueType rendering, you will need to toggle - by hand the definition of the - TT_CONFIG_OPTION_BYTECODE_INTERPRETER macro in the file - `include/freetype/config/ftoption.h'. - - - The CFF driver has been improved by Tom Kacvinsky and Sander van - der Wal: - - * Support for `seac' emulation. - * Support for `dotsection'. - * Support for retrieving glyph names through - `FT_Get_Glyph_Name'. - - The first two items are necessary to correctly a large number of - Type 1 fonts converted to the CFF formats by Adobe Acrobat. - - - The Type 1 driver was also improved by Tom & others: - - * Better EM size computation. - * Better support for synthetic (transformed) fonts. - * The Type 1 driver returns the charstrings corresponding to - each glyph in the `glyph->control_data' field after a call to - `FT_Load_Glyph' (thanks Ha Shao). - - - Various other bugfixes, including the following: - - * Fixed a nasty memory leak in the Type 1 driver. - * The autohinter and the pcf driver used static writable data - when they shouldn't. - * Many casts were added to make the code more 64-bits safe. It - also now compiles on Windows XP 64-bits without warnings. - * Some incorrect writable statics were removed in the `autohint' - and `pcf' drivers. FreeType 2 now compiles on Epoc again. - - - II. CHANGES TO THE HIGH-LEVEL API - - - The library header files inclusion scheme has been changed. The - old scheme looked like: - - #include - #include - #include - #include - - Now you should use: - - #include - #include FT_FREETYPE_H - #include FT_GLYPH_H - #include FT_CACHE_H - #include FT_CACHE_IMAGE_H - - NOTE THAT THE OLD INCLUSION SCHEME WILL STILL WORK WITH THIS - RELEASE. HOWEVER, WE DO NOT GUARANTEE THAT THIS WILL STILL BE - TRUE IN THE NEXT ONE (A.K.A. FREETYPE 2.1). - - The file is used to define the header filename - macros. The complete and commented list of macros is available - in the API reference under the section name `Header File Macros' - in Chapter I. - - For more information, see section I of the following document: - - https://www.freetype.org/freetype2/docs/tutorial/step1.html - - - Many, many comments have been added to the public source file in - order to automatically generate the API Reference through the - `docmaker.py' Python script. - - The latter has been updated to support the grouping of sections - in chapters and better index sort. See: - - https://www.freetype.org/freetype2/docs/reference/ft2-toc.html - - - III. CHANGES TO THE BUILD PROCESS - - - If you are not building FreeType 2 with its own build system - (but with your own Makefiles or project files), you will need to - be aware that the build process has changed a little bit. - - You don't need to put the `src' directory in the include path - when compiling any FT2 component. Instead, simply put the - component's directory in the current include path. - - So, if you were doing something like: - - cc -c -Iinclude -Isrc src/base/ftbase.c - - change the line to: - - cc -c -Iinclude -Isrc/base src/base/ftbase.c - - If you were doing something like: - - cd src/base - cc -c -I../../include -I.. ftbase.c - - change it to: - - cd src/base - cc -c -I../../include ftbase.c - - -====================================================================== - -CHANGES BETWEEN 2.0.1 and 2.0 - - 2.0.1 introduces a few changes: - - - Fixed many bugs related to the support of CFF / OpenType fonts. - These formats are now much better supported though there is - still work planned to deal with charset tables and PDF-embedded - CFF files that use the old `seac' command. - - - The library could not be compiled in debug mode with a very - small number of C compilers whose pre-processors didn't - implement the `##' directive correctly (i.e. per se the ANSI C - specification!) An elegant fix was found. - - - Added support for the free Borland command-line C++ Builder - compiler. Use `make setup bcc32'. Also fixed a few source - lines that generated new warnings with BCC32. - - - Fixed a bug in FT_Outline_Get_BBox when computing the extrema of - a conic Bezier arc. - - - Updated the INSTALL file to add IDE compilation. - - - Other minor bug fixes, from invalid Type 1 style flags to - correct support of synthetic (obliqued) fonts in the - auto-hinter, better support for embedded bitmaps in a SFNT font. - - - Fixed some problems with `freetype-config'. - - Finally, the `standard' scheme for including FreeType headers is now - gradually changing, but this will be explained in a later release - (probably 2.0.2). - - And very special thanks to Tom Kacvinsky and YAMANO-UCHI Hidetoshi - for their contributions! - - -====================================================================== - -CHANGES BETWEEN beta8 and 2.0 - - - Changed the default installation path for public headers from - `include/freetype' to `include/freetype2'. - - Also added a new `freetype-config' that is automatically generated - and installed on Unix and Cygwin systems. The script itself is - used to retrieve the current install path, C compilation flags as - well as linker flags. - - - Fixed several small bugs: - - * Incorrect max advance width for fixed-pitch Type 1 fonts. - * Incorrect glyph names for certain TrueType fonts. - * The glyph advance was not copied when FT_Glyph_To_Bitmap was - called. - * The linearHoriAdvance and linearVertAdvance fields were not - correctly returned for glyphs processed by the auto-hinter. - * `type1z' renamed back to `type1'; the old `type1' module has - been removed. - - - Revamped the build system to make it a lot more generic. This - will allow us to re-use nearly un-modified in lots of other - projects (including FreeType Layout). - - - Changed `cid' to use `psaux' too. - - - Added the cache sub-system. See as well as - the sources in `src/cache'. Note that it compiles but is still - untested for now. - - - Updated `docs/docmaker.py', a draft API reference is available at - https://web.archive.org/web/20001215173400/http://www.freetype.org:80/ft2api.html. - - - Changed `type1' to use `psaux'. - - - Created a new module named `psaux' to hold the Type 1 & Type 2 - parsing routines. It should be used by `type1', `cid', and `cff' - in the future. - - - Fixed an important bug in `FT_Glyph_Get_CBox'. - - - Fixed some compiler warnings that happened since the TrueType - bytecode decoder was deactivated by default. - - - Fixed two memory leaks: - - * The memory manager (16 bytes) isn't released in - FT_Done_FreeType! - * Using custom input streams, the copy of the original stream was - never released. - - - Fixed the auto-hinter by performing automatic computation of the - `filling direction' of each glyph. This is done through a simple - and fast approximation, and seems to work (problems spotted by - Werner though). The Arphic fonts are a lot nicer though there are - still a lot of things to do to handle Asian fonts correctly. - - -====================================================================== - -BETA-8 (RELEASE CANDIDATE) CHANGES - - - Deactivated the TrueType bytecode interpreter by default. - - - Deactivated the `src/type1' font driver. Now `src/type1z' is used - by default. - - - Updates to the build system. We now compile the library correctly - under Unix system through `configure' which is automatically - called on the first `make' invocation. - - - Added the auto-hinting module! Fixing some bugs here and there. - - - Found some bugs in the composite loader (seac) of the Type1-based - font drivers. - - - Renamed the directory `freetype2/config' to `freetype2/builds' and - updated all relevant files. - - - Found a memory leak in the `type1' driver. - - - Incorporated Tom's patches to support flex operators correctly in - OpenType/CFF fonts. Now all I need is to support pure CFF and CEF - fonts to be done with this driver :-) - - - Added the Windows FNT/FON driver in `src/winfonts'. For now, it - always `simulates' a Unicode charmap, so it shouldn't be - considered completed right now. - - It is there to be more a proof of concept than anything else - anyway. The driver is a single C source file, that compiles to 3 - Kb of code. - - I'm still working on the PCF/BDF drivers, but I'm too lazy to - finish them now. - - - CHANGES TO THE HIGH-LEVEL API - - * FT_Get_Kerning has a new parameter that allows you to select the - coordinates of the kerning vector (font units, scaled, scaled + - grid-fitted). - * The outline functions are now in and not - part of anymore. - * now contains declarations for - FT_New_Library, FT_Done_Library, FT_Add_Default_Modules. - * The so-called convenience functions have moved from `ftoutln.c' - to `ftglyph.c', and are thus available with this optional - component of the library. They are declared in - now. - * Anti-aliased rendering is now the default for FT_Render_Glyph - (i.e. corresponds to render_mode == 0 == ft_render_mode_normal). - To generate a monochrome bitmap, use ft_render_mode_mono, or the - FT_LOAD_MONOCHROME flag in FT_Load_Glyph/FT_Load_Char. - FT_LOAD_ANTI_ALIAS is still defined, but values to 0. - * now include , - solving a few headaches :-) - * The type FT_GlyphSlotRec has now a `library' field. - - - CHANGES TO THE `ftglyph.h' API - - This API has been severely modified in order to make it simpler, - clearer, and more efficient. It certainly now looks like a real - `glyph factory' object, and allows client applications to manage - (i.e. transform, bbox and render) glyph images without ever - knowing their original format. - - - Added support for CID-keyed fonts to the CFF driver. Maybe - support for pure CFF + CEF fonts should come in? - - - Cleaned up source code in order to avoid two functions with the - same name. Also changed the names of the files in `type1z' from - `t1XXXX' to `z1XXXX' in order to avoid any conflicts. - - `make multi' now works well :-) - - Also removed the use of `cidafm' for now, even if the source files - are still there. This functionality will certainly go into a - specific module. - - - ADDED SUPPORT FOR THE AUTO-HINTER - - It works :-) I have a demo program which simply is a copy of - `ftview' that does a `FT_Add_Module(library, - &autohinter_module_class)' after library initialization, and Type - 1 & OpenType/CFF fonts are now hinted. - - CID fonts are not hinted, as they include no charmap and the - auto-hinter doesn't include `generic' global metrics computations - yet. - - Now, I need to release this thing to the FreeType 2 source. - - - CHANGES TO THE RENDERER MODULES - - The monochrome and smooth renderers are now in two distinct - directories, namely `src/raster1' and `src/smooth'. Note that the - old `src/renderer' is now gone. - - I ditched the 5-gray-levels renderers. Basically, it involved a - simple #define toggle in 'src/raster1/ftraster.c'. - - FT_Render_Glyph, FT_Outline_Render & FT_Outline_Get_Bitmap now - select the best renderer available, depending on render mode. If - the current renderer for a given glyph image format isn't capable - of supporting the render mode, another one will be found in the - library's list. This means that client applications do not need - to switch or set the renderers themselves (as in the latest - change), they'll get what they want automatically. At last. - - Changed the demo programs accordingly. - - - MAJOR INTERNAL REDESIGN: - - A lot of internal modifications have been performed lately on the - source in order to provide the following enhancements: - - * More generic module support: - - The FT_Module type is now defined to represent a handle to a - given module. The file contains the - FT_Module_Class definition, as well as the module-loading public - API. - - The FT_Driver type is still defined, and still represents a - pointer to a font driver. Note that FT_Add_Driver is replaced - by FT_Add_Module, FT_Get_Driver by FT_Get_Module, etc. - - * Support for generic glyph image types: - - The FT_Renderer type is a pointer to a module used to perform - various operations on glyph image. - - Each renderer is capable of handling images in a single format - (e.g. ft_glyph_format_outline). Its functions are used to: - - - transform an glyph image - - render a glyph image into a bitmap - - return the control box (dimensions) of a given glyph image - - The scan converters `ftraster.c' and `ftgrays.c' have been moved - to the new directory `src/renderer', and are used to provide two - default renderer modules. - - One corresponds to the `standard' scan-converter, the other to - the `smooth' one. - - he current renderer can be set through the new function - FT_Set_Renderer. - - The old raster-related function FT_Set_Raster, FT_Get_Raster and - FT_Set_Raster_Mode have now disappeared, in favor of the new: - - FT_Get_Renderer - FT_Set_Renderer - - See the file for more details. - - These changes were necessary to properly support different - scalable formats in the future, like bi-color glyphs, etc. - - * Glyph loader object: - - A new internal object, called a 'glyph loader' has been - introduced in the base layer. It is used by all scalable format - font drivers to load glyphs and composites. - - This object has been created to reduce the code size of each - driver, as each one of them basically re-implemented its - functionality. - - See and the FT_GlyphLoader type for - more information. - - * FT_GlyphSlot has new fields: - - In order to support extended features (see below), the - FT_GlyphSlot structure has a few new fields: - - linearHoriAdvance: - - This field gives the linearly scaled (i.e. scaled but - unhinted) advance width for the glyph, expressed as a 16.16 - fixed pixel value. This is useful to perform WYSIWYG text. - - linearVertAdvance: - This field gives the linearly scaled advance height for the - glyph (relevant in vertical glyph layouts only). This is - useful to perform WYSIWYG text. - - Note that the two above field replace the removed `metrics2' - field in the glyph slot. - - advance: - This field is a vector that gives the transformed advance for - the glyph. By default, it corresponds to the advance width, - unless FT_LOAD_VERTICAL_LAYOUT was specified when calling - FT_Load_Glyph or FT_Load_Char. - - bitmap_left: - This field gives the distance in integer pixels from the - current pen position to the left-most pixel of a glyph image - IF IT IS A BITMAP. It is only valid when the `format' field - is set to `ft_glyph_format_bitmap', for example, after calling - the new function FT_Render_Glyph. - - bitmap_top: - This field gives the distance in integer pixels from the - current pen position (located on the baseline) to the top-most - pixel of the glyph image IF IT IS A BITMAP. Positive values - correspond to upwards Y. - - loader: - This is a new private field for the glyph slot. Client - applications should not touch it. - - - * Support for transforms and direct rendering in FT_Load_Glyph: - - Most of the functionality found in has been - moved to the core library. Hence, the following: - - - A transform can be specified for a face through - FT_Set_Transform. this transform is applied by FT_Load_Glyph - to scalable glyph images (i.e. NOT TO BITMAPS) before the - function returns, unless the bit flag FT_LOAD_IGNORE_TRANSFORM - was set in the load flags. - - - Once a glyph image has been loaded, it can be directly - converted to a bitmap by using the new FT_Render_Glyph - function. Note that this function takes the glyph image from - the glyph slot, and converts it to a bitmap whose properties - are returned in `face.glyph.bitmap', `face.glyph.bitmap_left' - and `face.glyph.bitmap_top'. The original native image might - be lost after the conversion. - - - When using the new bit flag FT_LOAD_RENDER, the FT_Load_Glyph - and FT_Load_Char functions will call FT_Render_Glyph - automatically when needed. - - - Reformatted all modules source code in order to get rid of the - basic data types redefinitions (i.e. `TT_Int' instead of `FT_Int', - `T1_Fixed' instead of `FT_Fixed'). Hence the format-specific - prefixes like `TT_', `T1_', `T2_' and `CID_' are only used for - relevant structures. - - -====================================================================== - -OLD CHANGES FOR BETA 7 - - - bug-fixed the OpenType/CFF parser. It now loads and displays my - two fonts nicely, but I'm pretty certain that more testing is - needed :-) - - - fixed the crummy Type 1 hinter, it now handles accented characters - correctly (well, the accent is not always well placed, but that's - another problem..) - - - added the CID-keyed Type 1 driver in `src/cid'. Works pretty well - for only 13 Kb of code ;-) Doesn't read AFM files though, nor the - really useful CMAP files.. - - - fixed two bugs in the smooth renderer (src/base/ftgrays.c). - Thanks to Boris Letocha for spotting them and providing a fix. - - - fixed potential `divide by zero' bugs in ftcalc.c. - - - added source code for the OpenType/CFF driver (still incomplete - though..) - - - modified the SFNT driver slightly to perform more robust header - checks in TT_Load_SFNT_Header. This prevents certain font files - (e.g. some Type 1 Multiple Masters) from being incorrectly - `recognized' as TrueType font files.. - - - moved a lot of stuff from the TrueType driver to the SFNT module, - this allows greater code re-use between font drivers - (e.g. TrueType, OpenType, Compact-TrueType, etc..) - - - added a tiny segment cache to the SFNT Charmap 4 decoder, in order - to minimally speed it up.. - - - added support for Multiple Master fonts in `type1z'. There is - also a new file named which defines functions to - manage them from client applications. - - The new file `src/base/ftmm.c' is also optional to the engine.. - - - various formatting changes (e.g. EXPORT_DEF -> FT_EXPORT_DEF) + - small bug fixes in FT_Load_Glyph, the `type1' driver, etc.. - - - a minor fix to the Type 1 driver to let them apply the font matrix - correctly (used for many oblique fonts..) - - - some fixes for 64-bit systems (mainly changing some FT_TRACE calls - to use %p instead of %lx). Thanks to Karl Robillard. - - - fixed some bugs in the sbit loader (src/base/sfnt/ttsbit.c) + - added a new flag, FT_LOAD_CROP_BITMAP to query that bitmaps be - cropped when loaded from a file (maybe I should move the bitmap - cropper to the base layer ??). - - - changed the default number of gray levels of the smooth renderer - to 256 (instead of the previous 128). Of course, the human eye - can't see any difference ;-) - - - removed TT_MAX_SUBGLYPHS, there is no static limit on the number - of subglyphs in a TrueType font now.. - - -====================================================================== - -OLD CHANGES 16 May 2000 - - - tagged `BETA-6' in the CVS tree. This one is a serious release - candidate even though it doesn't incorporate the auto-hinter yet.. - - - various obsolete files were removed, and copyright header updated - - - finally updated the standard raster to fix the monochrome - rendering bug + re-enable support for 5-gray levels anti-aliasing - (suck, suck..) - - - created new header files, and modified sources accordingly: - - - - simple FreeType types, without the API - - - definition of memory-management macros - - - added the `DSIG' (OpenType Digital Signature) tag to - - - - light update/cleaning of the build system + changes to the sources - in order to get rid of _all_ compiler warnings with three - compilers, i.e: - - gcc with `-ansi -pedantic -Wall -W', Visual C++ with `/W3 /WX' and - LCC - - IMPORTANT NOTE FOR WIN32-LCC USERS: - | - | It seems the C pre-processor that comes with LCC is broken, it - | doesn't recognize the ANSI standard directives # and ## - | correctly when one of the argument is a macro. Also, - | something like: - | - | #define F(x) print##x - | - | F(("hello")) - | - | will get incorrectly translated to: - | - | print "hello") - | - | by its pre-processor. For this reason, you simply cannot build - | FreeType 2 in debug mode with this compiler.. - - - yet another massive grunt work. I've changed the definition of - the EXPORT_DEF, EXPORT_FUNC, BASE_DEF & BASE_FUNC macros. These - now take an argument, which is the function's return value type. - - This is necessary to compile FreeType as a DLL on Windows and - OS/2. Depending on the compiler used, a compiler-specific keyword - like __export or __system must be placed before (VisualC++) or - after (BorlandC++) the type.. - - Of course, this needed a lot of changes throughout the source code - to make it compile again... All cleaned up now, apparently.. - - Note also that there is a new EXPORT_VAR macro defined to allow - the _declaration_ of an exportable public (constant) - variable. This is the case of the raster interfaces (see - ftraster.h and ftgrays.h), as well as each module's interface (see - sfdriver.h, psdriver.h, etc..) - - - new feature: it is now possible to pass extra parameters to font - drivers when creating a new face object. For now, - this capability is unused. It could however prove to - be useful in a near future.. - - the FT_Open_Args structure was changes, as well as the internal - driver interface (the specific `init_face' module function has - now a different signature). - - - updated the tutorial (not finished though). - - - updated the top-level BUILD document - - - fixed a potential memory leak that could occur when loading - embedded bitmaps. - - - added the declaration of FT_New_Memory_Face in - , as it was missing from the public header - (the implementation was already in `ftobjs.c'). - - - the file has been seriously updated in order - to allow the automatic generation of error message tables. See - the comments within it for more information. - - - major directory hierarchy re-organisation. This was done for two - things: - - * first, to ease the `manual' compilation of the library by - requiring at lot less include paths :-) - - * second, to allow external programs to effectively access - internal data fields. For example, this can be extremely - useful if someone wants to write a font producer or a font - manager on top of FreeType. - - Basically, you should now use the 'freetype/' prefix for header - inclusion, as in: - - #include - #include - - Some new include sub-directories are available: - - a. the `freetype/config' directory, contains two files used to - configure the build of the library. Client applications - should not need to look at these normally, but they can if - they want. - - #include - #include - - b. the `freetype/internal' directory, contains header files that - describes library internals. These are the header files that - were previously found in the `src/base' and `src/shared' - directories. - - - As usual, the build system and the demos have been updated to - reflect the change.. - - Here's a layout of the new directory hierarchy: - - TOP_DIR - include/ - freetype/ - freetype.h - ... - config/ - ftoption.h - ftconfig.h - ftmodule.h - - internal/ - ftobjs.h - ftstream.h - ftcalc.h - ... - - src/ - base/ - ... - - sfnt/ - psnames/ - truetype/ - type1/ - type1z/ - - - Compiling a module is now much easier, for example, the following - should work when in the TOP_DIR directory on an ANSI build: - - gcc -c -I./include -I./src/base src/base/ftbase.c - gcc -c -I./include -I./src/sfnt src/sfnt/sfnt.c - etc.. - - (of course, using -Iconfig/ if you provide system-specific - configuration files). - - - updated the structure of FT_Outline_Funcs in order to allow direct - coordinate scaling within the outline decomposition routine (this - is important for virtual `on' points with TrueType outlines) + - updates to the rasters to support this.. - - - updated the OS/2 table loading code in `src/sfnt/ttload.c' in - order to support version 2 of the table (see OpenType 1.2 spec) - - - created `include/tttables.h' and `include/t1tables.h' to allow - client applications to access some of the SFNT and T1 tables of a - face with a procedural interface (see `FT_Get_Sfnt_Table') + - updates to internal source files to reflect the change.. - - - some cleanups in the source code to get rid of warnings when - compiling with the `-Wall -W -ansi -pedantic' options in gcc. - - - debugged and moved the smooth renderer to `src/base/ftgrays.c' and - its header to `include/ftgrays.h' - - - updated TT_MAX_SUBGLYPHS to 96 as some CJK fonts have composites - with up to 80 sub-glyphs !! Thanks to Werner - - -====================================================================== - -OLD CHANGES - 14-apr-2000 - - - fixed a bug in the TrueType glyph loader that prevented the - correct loading of some CJK glyphs in mingli.ttf - - - improved the standard Type 1 hinter in `src/type1' - - - fixed two bugs in the experimental Type 1 driver in `src/type1z' - to handle the new XFree86 4.0 fonts (and a few other ones..) - - - the smooth renderer is now complete and supports sub-banding to - render large glyphs at high speed. However, it is still located - in `demos/src/ftgrays.c' and should move to the library itself in - the next beta. NOTE: The smooth renderer doesn't compile in - stand-alone mode anymore, but this should be fixed RSN.. - - - introduced convenience functions to more easily deal with glyph - images, see `include/ftglyph.h' for more details, as well as the - new demo program named `demos/src/ftstring.c' that demonstrates - its use - - - implemented FT_LOAD_NO_RECURSE in both the TrueType and Type 1 - drivers (this is required by the auto-hinter to improve its - results). - - - changed the raster interface, in order to allow client - applications to provide their own span-drawing callbacks. - However, only the smooth renderer supports this. See - `FT_Raster_Params' in the file `include/ftimage.h'. - - - fixed a small bug in FT_MulFix that caused incorrect transform - computation! - - - Note: The tutorial is out-of-date. - - -====================================================================== - -OLD CHANGES - 12-mar-2000 - - - changed the layout of configuration files : now, all ANSI - configuration files are located in - `freetype2/config'. System-specific over-rides can be placed in - `freetype2/config/'. - - - moved all configuration macros to `config/ftoption.h' - - - improvements in the Type 1 driver with AFM support - - - changed the fields in the FT_Outline structure : the old `flags' - array is re-named `tags', while all ancient flags are encoded into - a single unsigned int named `flags'. - - - introduced new flags in FT_Outline.flags (see - ft_outline_.... enums in `ftimage.h'). - - - changed outline functions to `FT_Outline_' syntax - - - added a smooth anti-alias renderer to the demonstration programs - - - added Mac graphics driver (thanks Just) - - - FT_Open_Face changed in order to received a pointer to a - FT_Open_Args descriptor.. - - - various cleanups, a few more API functions implemented (see - FT_Attach_File) - - - updated some docs - - -====================================================================== - -OLD CHANGES - 22-feb-2000 - - - introduced the `psnames' module. It is used to: - - o convert a Postscript glyph name into the equivalent Unicode - character code (used by the Type 1 driver(s) to synthesize on - the fly a Unicode charmap). - - o provide an interface to retrieve the Postscript names of the - Macintosh, Adobe Standard & Adobe Expert character codes. - (the Macintosh names are used by the SFNT-module postscript - names support routines, while the other two tables are used by - the Type 1 driver(s)). - - - introduced the `type1z' alternate Type 1 driver. This is a (still - experimental) driver for the Type 1 format that will ultimately - replace the one in `src/type1'. It uses pattern matching to load - data from the font, instead of a finite state analyzer. It works - much better than the `old' driver with `broken' fonts. It is also - much smaller (under 15 Kb). - - - the Type 1 drivers (both in `src/type1' and `src/type1z') are - nearly complete. They both provide automatic Unicode charmap - synthesis through the `psnames' module. No re-encoding vector is - needed. (note that they still leak memory due to some code - missing, and I'm getting lazy). - - Trivial AFM support has been added to read kerning information but - wasn't exactly tested as it should ;-) - - - The TrueType glyph loader has been seriously rewritten (see the - file `src/truetype/ttgload.c'. It is now much, much simpler as - well as easier to read, maintain and understand :-) Preliminary - versions introduced a memory leak that has been reported by Jack - Davis, and is now fixed.. - - - introduced the new `ft_glyph_format_plotter', used to represent - stroked outlines like Windows `Vector' fonts, and certain Type 1 - fonts like `Hershey'. The corresponding raster will be written - soon. - - - FT_New_Memory_Face is gone. Likewise, FT_Open_Face has a new - interface that uses a structure to describe the input stream, the - driver (if required), etc.. - - -TODO - - - Write FT_Get_Glyph_Bitmap and FT_Load_Glyph_Bitmap - - - Add a function like FT_Load_Character(face, char_code, load_flags) - that would really embed a call to FT_Get_Char_Index then - FT_Load_Glyph to ease developer's work. - - - Update the tutorial! - - - consider adding support for Multiple Master fonts in the Type 1 - drivers. - - - Test the AFM routines of the Type 1 drivers to check that kerning - information is returned correctly. - - - write a decent auto-gridding component !! We need this to release - FreeType 2.0 gold ! - - -less urgent needs: - - - add a CFF/Type2 driver - - add a BDF driver - - add a FNT/PCF/HBF driver - - add a Speedo driver from the X11 sources - - -====================================================================== - -OLDER CHANGES - 27-jan-2000 - - - updated the `sfnt' module interface to allow several SFNT-based - drivers to co-exist peacefully - - - updated the `T1_Face' type to better separate Postscript font - content from the rest of the FT_Face structure. Might be used - later by the CFF/Type2 driver.. - - - added an experimental replacement Type 1 driver featuring advanced - (and speedy) pattern matching to retrieve the data from postscript - fonts. - - - very minor changes in the implementation of FT_Set_Char_Size and - FT_Set_Pixel_Sizes (they now implement default to lighten the font - driver's code). - - -====================================================================== - -OLD MESSAGE - -This file summarizes the changes that occurred since the last `beta' -of FreeType 2. Because the list is important, it has been divided into -separate sections: - -Table Of Contents: - - I High-Level Interface (easier !) - II Directory Structure - III Glyph Image Formats - IV Build System - V Portability - VI Font Drivers - - ----------------------------------------------------------------------- - -High-Level Interface: - - The high-level API has been considerably simplified. Here is how: - - - resource objects have disappeared. this means that face objects - can now be created with a single function call (see FT_New_Face - and FT_Open_Face) - - - when calling either FT_New_Face & FT_Open_Face, a size object - and a glyph slot object are automatically created for the face, - and can be accessed through `face->glyph' and `face->size' if - one really needs to. In most cases, there's no need to call - FT_New_Size or FT_New_Glyph. - - - similarly, FT_Load_Glyph now only takes a `face' argument - (instead of a glyph slot and a size). Also, its `result' - parameter is gone, as the glyph image type is returned in the - field `face->glyph.format' - - - the list of available charmaps is directly accessible through - `face->charmaps', counting `face->num_charmaps' elements. Each - charmap has an 'encoding' field which specifies which known - encoding it deals with. Valid values are, for example: - - ft_encoding_unicode (for ASCII, Latin-1 and Unicode) - ft_encoding_apple_roman - ft_encoding_sjis - ft_encoding_adobe_standard - ft_encoding_adobe_expert - - other values may be added in the future. Each charmap still - holds its `platform_id' and `encoding_id' values in case the - encoding is too exotic for the current library - - ----------------------------------------------------------------------- - -Directory Structure: - - Should seem obvious to most of you: - - freetype/ - config/ -- configuration sub-makefiles - ansi/ - unix/ -- platform-specific configuration files - win32/ - os2/ - msdos/ - - include/ -- public header files, those to be included - directly by client apps - - src/ -- sources of the library - base/ -- the base layer - sfnt/ -- the sfnt `driver' (see the drivers section - below) - truetype/ -- the truetype driver - type1/ -- the type1 driver - shared/ -- some header files shared between drivers - - demos/ -- demos/tools - - docs/ -- documentation (a bit empty for now) - - ----------------------------------------------------------------------- - -Glyph Image Formats: - - Drivers are now able to register new glyph image formats within the - library. For now, the base layer supports of course bitmaps and - vector outlines, but one could imagine something different like - colored bitmaps, bi-color vectors or whatever else (Metafonts anyone - ??). - - See the file `include/ftimage.h'. Note also that the type - FT_Raster_Map is gone, and is now replaced by FT_Bitmap, which - should encompass all known bitmap types. - - Each new image format must provide at least one `raster', i.e. a - module capable of transforming the glyph image into a bitmap. It's - also possible to change the default raster used for a given glyph - image format. - - The default outline scan-converter now uses 128 levels of grays by - default, which tends to smooth many things. Note that the demo - programs have been updated significantly in order to display these.. - - ----------------------------------------------------------------------- - -Build system: - - You still need GNU Make to build the library. The build system has - been very seriously re-vamped in order to provide things like : - - - automatic host platform detection (reverting to 'config/ansi' if - it is not detected, with pseudo-standard compilation flags) - - - the ability to compile from the Makefiles with very different and - exotic compilers. Note that linking the library can be difficult - for some platforms. - - For example, the file `config/win32/lcclib.bat' is invoked by the - build system to create the `.lib' file with LCC-Win32 because its - librarian has too many flaws to be invoked directly from the - Makefile. - - Here's how it works: - - - the first time you type `make', the build system runs a series of - sub-makefiles in order to detect your host platform. It then - dumps what it found, and creates a file called `config.mk' in the - current directory. This is a sub-Makefile used to define many - important Make variables used to build the library. - - - the second time, the build system detects the `config.mk' then use - it to build the library. All object files go into 'obj' by - default, as well as the library file, but this can easily be - changed. - - Note that you can run `make setup' to force another host platform - detection even if a `config.mk' is present in the current - directory. Another solution is simply to delete the file, then - re-run make. - - Finally, the default compiler for all platforms is gcc (for now, - this will hopefully changed in the future). You can however specify - a different compiler by specifying it after the 'setup' target as - in: - - gnumake setup lcc on Win32 to use the LCC compiler - gnumake setup visualc on Win32 to use Visual C++ - - See the file `config//detect.mk' for a list of supported - compilers for your platforms. - - It should be relatively easy to write new detection rules files and - config.mk.. - - Finally, to build the demo programs, go to `demos' and launch GNU - Make, it will use the `config.mk' in the top directory to build the - test programs.. - - ----------------------------------------------------------------------- - -Portability: - - In the previous beta, a single FT_System object was used to - encompass all low-level operations like thread synchronisation, - memory management and i/o access. This has been greatly simplified: - - - thread synchronisation has been dropped, for the simple reason - that the library is already re-entrant, and that if you really - need two threads accessing the same FT_Library, you should - really synchronize access to it yourself with a simple mutex. - - - memory management is performed through a very simple object - called `FT_Memory', which really is a table containing a table - of pointers to functions like malloc, realloc and free as well - as some user data (closure). - - - resources have disappeared (they created more problems than they - solved), and i/o management have been simplified greatly as a - result. Streams are defined through FT_Stream objects, which - can be either memory-based or disk-based. - - Note that each face has its own stream, which is closed only - when the face object is destroyed. Hence, a function like - TT_Flush_Face in 1.x cannot be directly supported. However, if - you really need something like this, you can easily tailor your - own streams to achieve the same feature at a lower level (and - use FT_Open_Face instead of FT_New_Face to create the face). - - See the file `include/ftsystem.h' for more details, as well as the - implementations found in `config/unix' and `config/ansi'. - - ----------------------------------------------------------------------- - -Font Drivers: - - The Font Driver interface has been modified in order to support - extensions & versioning. - - - The list of the font drivers that are statically linked to the - library at compile time is managed through a new configuration file - called `config//ftmodule.h'. - - This file is autogenerated when invoking `make modules'. This - target will parse all sub-directories of 'src', looking for a - `module.mk' rules file, used to describe the driver to the build - system. - - Hence, one should call `make modules' each time a font driver is - added or removed from the `src' directory. - - Finally, this version provides a `pseudo-driver' in `src/sfnt'. - This driver doesn't support font files directly, but provides - services used by all TrueType-like font drivers. Hence, its code is - shared between the TrueType & OpenType font formats, and possibly - more formats to come if we're lucky.. - - ----------------------------------------------------------------------- - -Extensions support: - - The extensions support is inspired by the one found in 1.x. - - Now, each font driver has its own `extension registry', which lists - which extensions are available for the font faces managed by the - driver. - - Extension ids are now strings, rather than 4-byte tags, as this is - usually more readable. - - Each extension has: - - some data, associated to each face object - - an interface (table of function pointers) - - An extension that is format-specific should simply register itself - to the correct font driver. Here is some example code: - - // Registering an extensions - // - FT_Error FT_Init_XXXX_Extension( FT_Library library ) - { - FT_DriverInterface* tt_driver; - - driver = FT_Get_Driver( library, "truetype" ); - if (!driver) return FT_Err_Unimplemented_Feature; - - return FT_Register_Extension( driver, &extension_class ); - } - - - // Implementing the extensions - // - FT_Error FT_Proceed_Extension_XXX( FT_Face face ) - { - FT_XXX_Extension ext; - FT_XXX_Extension_Interface ext_interface; - - ext = FT_Get_Extension( face, "extensionid", &ext_interface ); - if (!ext) return error; - - return ext_interface->do_it(ext); - } - ------------------------------------------------------------------------- - -Copyright (C) 2000-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute this -file you indicate that you have read the license and understand and -accept it fully. - - -Local Variables: -version-control: never -coding: utf-8 -End: - ---- end of CHANGES --- diff --git a/lib/libesp32_lvgl/freetype/docs/CMAKE b/lib/libesp32_lvgl/freetype/docs/CMAKE deleted file mode 100644 index 31237ae15..000000000 --- a/lib/libesp32_lvgl/freetype/docs/CMAKE +++ /dev/null @@ -1,2 +0,0 @@ -Support for a cmake build has been contributed. See the remarks in the -top-level `CMakeLists.txt' file for more. diff --git a/lib/libesp32_lvgl/freetype/docs/CUSTOMIZE b/lib/libesp32_lvgl/freetype/docs/CUSTOMIZE deleted file mode 100644 index 0f92e7004..000000000 --- a/lib/libesp32_lvgl/freetype/docs/CUSTOMIZE +++ /dev/null @@ -1,152 +0,0 @@ -How to customize the compilation of the library -=============================================== - - FreeType is highly customizable to fit various needs, and this - document describes how it is possible to select options and - components at compilation time. - - -I. Configuration macros - - The file `include/freetype/config/ftoption.h' contains a list of - commented configuration macros that can be toggled by developers to - indicate which features should be active while building the library. - - These options range from debug level to availability of certain - features, like native TrueType hinting through a bytecode - interpreter. - - We invite you to read this file for more information. You can - change the file's content to suit your needs, or override it with - one of the techniques described below. - - -II. Modules list - - If you use GNU make please edit the top-level file `modules.cfg'. - It contains a list of available FreeType modules and extensions to - be compiled. Change it to suit your own preferences. Be aware that - certain modules depend on others, as described in the file. GNU - make uses `modules.cfg' to generate `ftmodule.h' (in the object - directory). - - If you build FreeType in a directory separate from the source files, - put your customized `modules.cfg' in that directory; that way you - can keep the source files `clean'. - - If you don't use GNU make you have to manually edit the file - `include/freetype/config/ftmodule.h' (which is *not* used with if - compiled with GNU make) to add or remove the drivers and components - you want to compile into the library. See `INSTALL.ANY' for more - information. - - -III. System interface - - FreeType's default interface to the system (i.e., the parts that - deal with memory management and i/o streams) is located in - `src/base/ftsystem.c'. - - The current implementation uses standard C library calls to manage - memory and to read font files. It is however possible to write - custom implementations to suit specific systems. - - To tell the GNU Make-based build system to use a custom system - interface, you have to define the environment variable FTSYS_SRC to - point to the relevant implementation: - - on Unix: - - ./configure - export FTSYS_SRC=foo/my_ftsystem.c - make - make install - - on Windows: - - make setup - set FTSYS_SRC=foo/my_ftsystem.c - make - - -IV. Overriding default configuration and module headers - - It is possible to override the default configuration and module - headers without changing the original files. There are three ways - to do that: - - - 1. With GNU make - - [This is actually a combination of method 2 and 3.] - - Just put your custom `ftoption.h' file into the objects directory - (normally `/objs' if you build in the source tree, or the - directory where you invoke configure if you build in a separate - directory), which GNU make prefers over the standard location. No - action is needed for `ftmodule.h' because it is generated - automatically in the objects directory. - - 2. Using the C include path - - Use the C include path to ensure that your own versions of the - files are used at compile time when the lines - - #include FT_CONFIG_OPTIONS_H - #include FT_CONFIG_MODULES_H - - are compiled. Their default values being - and , you - can do something like: - - custom/ - config/ - ftoption.h => custom options header - ftmodule.h => custom modules list - - include/ => normal FreeType 2 include - ... - - then change the C include path to always give the path to `custom' - before the FreeType 2 `include'. - - - 3. Redefining FT_CONFIG_OPTIONS_H and FT_CONFIG_MODULES_H - - Another way to do the same thing is to redefine the macros used to - name the configuration headers. To do so, you need a custom - `ft2build.h' whose content can be as simple as: - - #ifndef FT2_BUILD_MY_PLATFORM_H_ - #define FT2_BUILD_MY_PLATFORM_H_ - - #define FT_CONFIG_OPTIONS_H - #define FT_CONFIG_MODULES_H - - #include - - #endif /* FT2_BUILD_MY_PLATFORM_H_ */ - - Place those files in a separate directory, e.g., - - custom/ - ft2build.h => custom version described above - my-ftoption.h => custom options header - my-ftmodule.h => custom modules list header - - and change the C include path to ensure that `custom' is always - placed before the FT2 `include' during compilation. - ----------------------------------------------------------------------- - -Copyright (C) 2003-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute -this file you indicate that you have read the license and understand -and accept it fully. - - ---- end of CUSTOMIZE --- diff --git a/lib/libesp32_lvgl/freetype/docs/DEBUG b/lib/libesp32_lvgl/freetype/docs/DEBUG deleted file mode 100644 index a96b5e27b..000000000 --- a/lib/libesp32_lvgl/freetype/docs/DEBUG +++ /dev/null @@ -1,216 +0,0 @@ -Debugging within the FreeType sources -===================================== - -I. Configuration macros ------------------------ - -There are several ways to enable debugging features in a FreeType 2 -builds. This is controlled through the definition of special macros -located in the file `ftoption.h'. The macros are: - - - FT_DEBUG_LEVEL_ERROR - - #define this macro if you want to compile the `FT_ERROR' macro - calls to print error messages during program execution. This does - not stop the program. Very useful to spot invalid fonts during - development and to code workarounds for them. - - FT_DEBUG_LEVEL_TRACE - - #define this macro if you want to compile both macros `FT_ERROR' - and `FT_TRACE'. This also includes the variants `FT_TRACE0', - `FT_TRACE1', `FT_TRACE2', ..., `FT_TRACE7'. - - The trace macros are used to send debugging messages when an - appropriate `debug level' is configured at runtime through the - `FT2_DEBUG' environment variable (more on this later). - - FT_DEBUG_MEMORY - - If this macro is #defined, the FreeType engine is linked with a - small but effective debugging memory manager that tracks all - allocations and frees that are performed within the font engine. - - When the `FT2_DEBUG_MEMORY' environment variable is defined at - runtime, a call to `FT_Done_FreeType' dumps memory statistics, - including the list of leaked memory blocks and optionally with the - source locations where these were allocated. It is always a very - good idea to define this in development builds. This works with - _any_ program linked to FreeType, but requires a big deal of - memory (the debugging memory manager never frees the blocks to the - heap in order to detect double frees). - - When `FT2_DEBUG_MEMORY' isn't defined at runtime, the debugging - memory manager is ignored, and performance is unaffected. - - -II. Debugging macros --------------------- - -Several macros can be used within the FreeType sources to help -debugging its code: - - - 1. FT_ERROR(( ... )) - - This macro is used to send debug messages that indicate relatively - serious errors (like broken font files) without stopping the - execution of the running program. Its code is compiled only when - either `FT_DEBUG_LEVEL_ERROR' or `FT_DEBUG_LEVEL_TRACE' are - defined in `ftoption.h'. - - Note that you have to use a printf-like signature, but with double - parentheses, like in - - FT_ERROR(( "your %s is not %s\n", "foo", "bar" )); - - - 2. FT_ASSERT( condition ) - - This macro is used to check strong assertions at runtime. If its - condition isn't TRUE, the program aborts with a panic message. - Its code is compiled when either `FT_DEBUG_LEVEL_ERROR' or - `FT_DEBUG_LEVEL_TRACE' are defined. You don't need double - parentheses here. Example: - - FT_ASSERT( ptr != NULL ); - - - 3. FT_TRACE( level, (message...) ) - - The `FT_TRACE' macro is used to send general-purpose debugging - messages during program execution. This macro uses an *implicit* - macro named `FT_COMPONENT', which names the current FreeType - component being run. - - The developer should always define `FT_COMPONENT' as appropriate, - for example as in - - #undef FT_COMPONENT - #define FT_COMPONENT io - - The value of the `FT_COMPONENT' macro is one of the component - names defined in the internal file `internal/fttrace.h'. If you - modify the FreeType source code and insert a new `FT_COMPONENT' - macro, you must register it in `fttrace.h'. If you insert or - remove many trace macros, you can test for undefined or unused - trace macros with the script `src/tools/chktrcmp.py'. - - Each such component is assigned a `debug level', ranging from - value 0 to 7, through the use of the `FT2_DEBUG' environment - variable (described below) when a program linked with FreeType - starts. - - When `FT_TRACE' is called, its level is compared to the one of the - corresponding component. Messages with trace levels *higher* than - the corresponding component level are filtered out and never - printed. This means that trace messages with level 0 are always - printed, those with level 2 are only printed when the component - level is *at least* 2, etc. - - The second parameter to `FT_TRACE' must contain parentheses and - corresponds to a printf-like call, as in - - FT_TRACE( 2, ( "your %s is not %s\n", "foo", "bar" ) ) - - The shortcut macros `FT_TRACE0', `FT_TRACE1', `FT_TRACE2', ..., - `FT_TRACE7' can be used with constant level indices, and are much - cleaner to use, as in - - FT_TRACE2(( "your %s is not %s\n", "foo", "bar" )); - - -III. Environment variables --------------------------- - -The following environment variables control debugging output and -behaviour of FreeType at runtime. - - - FT2_DEBUG - - This variable is only used when FreeType is built with - `FT_DEBUG_LEVEL_TRACE' defined. It contains a list of component - level definitions, following this format: - - component1:level1 component2:level2 component3:level3 ... - - where `componentX' is the name of a tracing component, as defined - in `fttrace.h'. `levelX' is the corresponding level to use at - runtime. - - `any' is a special component name that is interpreted as `any/all - components'. For example, the following definitions - - set FT2_DEBUG=any:2 memory:5 io:4 (on Windows) - export FT2_DEBUG="any:2 memory:5 io:4" (on Linux with bash) - - both stipulate that all components should have level 2, except for - the memory and io components, which are set to the trace levels 5 - and 4, respectively. - - - FT2_DEBUG_MEMORY - - This environment variable, when defined, tells FreeType to use a - debugging memory manager that tracks leaking memory blocks as well - as other common errors like double frees. It is also capable of - reporting _where_ the leaking blocks were allocated, which - considerably saves time when debugging new additions to the - library. - - This code is only compiled when FreeType is built with the - `FT_DEBUG_MEMORY' macro #defined in `ftoption.h' though, it is - ignored in other builds. - - - FT2_ALLOC_TOTAL_MAX - - This variable is ignored if `FT2_DEBUG_MEMORY' is not defined. It - allows you to specify a maximum heap size for all memory - allocations performed by FreeType. This is very useful to test - the robustness of the font engine and programs that use it in - tight memory conditions. - - If it is undefined, or if its value is not strictly positive, no - allocation bounds are checked at runtime. - - - FT2_ALLOC_COUNT_MAX - - This variable is ignored if `FT2_DEBUG_MEMORY' is not defined. It - allows you to specify a maximum number of memory allocations - performed by FreeType before returning the error - `FT_Err_Out_Of_Memory'. This is useful for debugging and testing - the engine's robustness. - - If it is undefined, or if its value is not strictly positive, no - allocation bounds are checked at runtime. - - - FT2_KEEP_ALIVE - - This variable is ignored if `FT2_DEBUG_MEMORY' is not defined. - `Keep alive' means that freed blocks aren't released to the heap. - This is useful to detect double-frees or weird heap corruption, - reporting the source code location of the original allocation and - deallocation in case of a problem. It uses large amounts of - memory, however. - - If it is undefined, or if its value is not strictly positive, - freed blocks are released at runtime. - ------------------------------------------------------------------------- - -Copyright (C) 2002-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute this -file you indicate that you have read the license and understand and -accept it fully. - - ---- end of DEBUG --- diff --git a/lib/libesp32_lvgl/freetype/docs/DOCGUIDE b/lib/libesp32_lvgl/freetype/docs/DOCGUIDE deleted file mode 100644 index 89617b429..000000000 --- a/lib/libesp32_lvgl/freetype/docs/DOCGUIDE +++ /dev/null @@ -1,298 +0,0 @@ -Introduction ------------- - -Documentation is an extremely important part of any project, and it -helps a lot if it uses consistent syntax and layout. - -The documentation for the FreeType library is maintained in header -files in the `include/` directory in the form of code comments. These -comments are extracted and organized by 'docwriter' (previously -'docmaker'). The generated docs can be viewed in the -`docs/reference/site/` directory after running `make refdoc`. - -Documentation comments follow a specific structure and format as -described below. - - -Documentation Structure ------------------------ - -The documentation is divided into multiple chapters, which contain -sections relevant to it. The chapter details and sections contained -in them are listed in `include/freetype/ftchapters.h`. Any unlisted -section is added to the 'Miscellaneous' chapter. - -Sections may contain sub-sections which consist of properties, -enumerations, and other data types. - - -Comment Blocks --------------- - -Documentation blocks follow a specific format: - - /***************************** (should end on column 77) - * - * (1 asterisk, 1 space, then content) - * - */ (end of block) - -To make 'docwriter' recognize a comment block, there must be at least -two asterisks in the first line. As a consequence, you should change -the second asterisk to something else if you want to prevent a comment -block being handled by 'docwriter' (for example, change `/****/` to -`/*#**/`). - - -Markup Tags ------------ - -Markup tags are used to indicate what comes next. The syntax for a -tag is: - - @foo: - -An `@`, followed by the tag, and then `:`. - - -Reserved Tags -------------- - -There are some keywords that have a special meaning to docwriter. -As a convention, all keywords are written in lowercase. - -* `chapter`: Defines a chapter. Usually the title with underscores. -* `sections`: List of sections in the chapter, in order. -* `section`: Defines the start or continuation of a section. -* `title`: Title for a chapter or section. May contain spaces. -* `abstract`: The abstract for a section, visible in the Table of - Contents (TOC). -* `description`: Detailed description of a tag (except chapters), - shown as synopsis. -* `values`: A list of 'values' for the tag. These values are used for - cross-referencing. - - -Other Tags ----------- - -Except the ones given above, any other tags will be added as a part of -a subsection. All tags are lowercase by convention. - - -Public Header Definitions -------------------------- - -The public headers for FreeType have their names defined in -`include/freetype/config/ftheader.h`. Any new public header file must -be defined in this file, in the following format: - - #define FT_NEWNAME_H - -Where `newname` is the name of the header file. - -This macro is combined with the file location of a sub-section and -printed with the object. - - -Note on code blocks captured after comments -------------------------------------------- - -All non-documentation lines after a documentation comment block are -captured to be displayed as the code for the sub-section. To stop -collection, a line with `/* */` should be added. - - -General Formatting Conventions ------------------------------- - -* Use two spaces after a full stop ending a sentence. -* Use appropriate uppercasing in titles. Refer - - https://english.stackexchange.com/a/34 - - for more information. -* Do not add trailing parentheses when citing a C function. - - -Markdown Usage --------------- - -All tags, except the ones that define the name and title for a block -support markdown in them. Docwriter uses a markdown parser that -follows rules given in John Gruber's markdown guide: - - https://daringfireball.net/projects/markdown/syntax - -with a few exceptions and extensions, detailed below. This may also -be referred to as the **FreeType Flavored Markdown**. - - -Headers -------- - -Markdown headers should not be used directly, because these are added -based on section titles, sub-section names, and tags. However, if a -header needs to be added, note the following correspondence to HTML tags: - -* Section title on top of the page is `H1`. -* Sub-section titles are `H2`. -* Parts of sub-sections are `H4`. -* Any header added will be visible in the Table of Contents (TOC) of - the page. - - -Emphasis --------- - -* Use `_underscores_` for italics. -* Use `**double asterisks**` for bold. - -Although the other notations (double underscore for bold, single -asterisk for italics) are supported, it is recommended to use the -above for consistency. - -Note that there may be cases where having two asterisks or underscores -in a line may lead to text being picked up as italics or bold. -Although unintentional, this is correct markdown behavior. - -For inline code, wrap the sequence with backticks (see below). This -renders symbols correctly without modifications. If a symbol is -absolutely required outside of an inline code block or code sequence, -escape it with a backslash (like `\*` or `\_`). - - -Lists ------ - -Unordered lists can be created with asterisks: - - * Unordered list items can use asterisks. - * Another list item. - -Ordered lists start with numbers: - - 1. This is an ordered list item. - 2. Brackets after numbers won't work. - -To continue a list over multiple paragraphs, indent them with at least -four spaces. For example: - - 1. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. - Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, - viverra nec, fringilla in, laoreet vitae, risus. - - Donec sit amet nisl. Aliquam semper ipsum sit amet velit. - Suspendisse id sem consectetuer libero luctus adipiscing. - - 2. This is the second list item. - - This paragraph is not a part of the list. - -More information on lists in markdown is available at - - https://daringfireball.net/projects/markdown/syntax#list - - -Cross-references ----------------- - -Other sub-sections can be linked with the `@` symbol: - - @description: - While FreeType's CFF driver doesn't expose API functions by - itself, it is possible to control its behaviour with - @FT_Property_Set and @FT_Property_Get. - -If a field in the `values` table of another sub-section is linked, the -link leads to its parent sub-section. - - -Links and Images ----------------- - -All URLs are converted to links in the HTML documentation. - -Markdown syntax for links and images are fully supported. - - -Inline Code ------------ - -To indicate a span of code, wrap it with backtick quotes (`` ` ``): - - Use the `printf()` function. - -Cross-references, markdown, and html styling do not work in inline code -sequences. - - -Code and Syntax Highlighting ----------------------------- - -Blocks of code are fenced by lines with three back-ticks `` ``` `` -followed by the language name, if any (used for syntax highlighting), -as demonstrated in the following example. - - ```c - x = y + z; - if ( zookoo == 2 ) - { - foobar(); - } - ``` - -Note that the indentation of the opening line and the closing line -must be exactly the same. The code sequence itself should have a -larger indentation than the surrounding back-ticks. - -Like inline code, markdown and html styling is *not* supported inside -code blocks. - - -Tables ------- - -Tables are used to list values, input, and other fields. The FreeType -Flavored Markdown adopts a simple approach to tables with two columns, -or field definition tables. - -Field definition names may contain alphanumeric, underscore, and the -`.` characters. This is followed by `::`. The following lines are -the second column of the table. A field definition ends with the -start of another field definition, or a markup tag. - - @Input: - pathname :: - A path to the font file. - - face_index :: - See @FT_Open_Face for a detailed description of this - parameter. - - -Non-breaking Space ------------------- - -A tilde can be used to create a non-breaking space. The example - - The encoding value~0 is reserved. - -is converted to - - The encoding value 0 is reserved. - - ----------------------------------------------------------------------- - -Copyright (C) 2018-2020 by -Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute -this file you indicate that you have read the license and understand -and accept it fully. - - ---- end of DOCGUIDE --- diff --git a/lib/libesp32_lvgl/freetype/docs/FTL.TXT b/lib/libesp32_lvgl/freetype/docs/FTL.TXT deleted file mode 100644 index c406d150f..000000000 --- a/lib/libesp32_lvgl/freetype/docs/FTL.TXT +++ /dev/null @@ -1,169 +0,0 @@ - The FreeType Project LICENSE - ---------------------------- - - 2006-Jan-27 - - Copyright 1996-2002, 2006 by - David Turner, Robert Wilhelm, and Werner Lemberg - - - -Introduction -============ - - The FreeType Project is distributed in several archive packages; - some of them may contain, in addition to the FreeType font engine, - various tools and contributions which rely on, or relate to, the - FreeType Project. - - This license applies to all files found in such packages, and - which do not fall under their own explicit license. The license - affects thus the FreeType font engine, the test programs, - documentation and makefiles, at the very least. - - This license was inspired by the BSD, Artistic, and IJG - (Independent JPEG Group) licenses, which all encourage inclusion - and use of free software in commercial and freeware products - alike. As a consequence, its main points are that: - - o We don't promise that this software works. However, we will be - interested in any kind of bug reports. (`as is' distribution) - - o You can use this software for whatever you want, in parts or - full form, without having to pay us. (`royalty-free' usage) - - o You may not pretend that you wrote this software. If you use - it, or only parts of it, in a program, you must acknowledge - somewhere in your documentation that you have used the - FreeType code. (`credits') - - We specifically permit and encourage the inclusion of this - software, with or without modifications, in commercial products. - We disclaim all warranties covering The FreeType Project and - assume no liability related to The FreeType Project. - - - Finally, many people asked us for a preferred form for a - credit/disclaimer to use in compliance with this license. We thus - encourage you to use the following text: - - """ - Portions of this software are copyright © The FreeType - Project (www.freetype.org). All rights reserved. - """ - - Please replace with the value from the FreeType version you - actually use. - - -Legal Terms -=========== - -0. Definitions --------------- - - Throughout this license, the terms `package', `FreeType Project', - and `FreeType archive' refer to the set of files originally - distributed by the authors (David Turner, Robert Wilhelm, and - Werner Lemberg) as the `FreeType Project', be they named as alpha, - beta or final release. - - `You' refers to the licensee, or person using the project, where - `using' is a generic term including compiling the project's source - code as well as linking it to form a `program' or `executable'. - This program is referred to as `a program using the FreeType - engine'. - - This license applies to all files distributed in the original - FreeType Project, including all source code, binaries and - documentation, unless otherwise stated in the file in its - original, unmodified form as distributed in the original archive. - If you are unsure whether or not a particular file is covered by - this license, you must contact us to verify this. - - The FreeType Project is copyright (C) 1996-2000 by David Turner, - Robert Wilhelm, and Werner Lemberg. All rights reserved except as - specified below. - -1. No Warranty --------------- - - THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO - USE, OF THE FREETYPE PROJECT. - -2. Redistribution ------------------ - - This license grants a worldwide, royalty-free, perpetual and - irrevocable right and license to use, execute, perform, compile, - display, copy, create derivative works of, distribute and - sublicense the FreeType Project (in both source and object code - forms) and derivative works thereof for any purpose; and to - authorize others to exercise some or all of the rights granted - herein, subject to the following conditions: - - o Redistribution of source code must retain this license file - (`FTL.TXT') unaltered; any additions, deletions or changes to - the original files must be clearly indicated in accompanying - documentation. The copyright notices of the unaltered, - original files must be preserved in all copies of source - files. - - o Redistribution in binary form must provide a disclaimer that - states that the software is based in part of the work of the - FreeType Team, in the distribution documentation. We also - encourage you to put an URL to the FreeType web page in your - documentation, though this isn't mandatory. - - These conditions apply to any software derived from or based on - the FreeType Project, not just the unmodified files. If you use - our work, you must acknowledge us. However, no fee need be paid - to us. - -3. Advertising --------------- - - Neither the FreeType authors and contributors nor you shall use - the name of the other for commercial, advertising, or promotional - purposes without specific prior written permission. - - We suggest, but do not require, that you use one or more of the - following phrases to refer to this software in your documentation - or advertising materials: `FreeType Project', `FreeType Engine', - `FreeType library', or `FreeType Distribution'. - - As you have not signed this license, you are not required to - accept it. However, as the FreeType Project is copyrighted - material, only this license, or another one contracted with the - authors, grants you the right to use, distribute, and modify it. - Therefore, by using, distributing, or modifying the FreeType - Project, you indicate that you understand and accept all the terms - of this license. - -4. Contacts ------------ - - There are two mailing lists related to FreeType: - - o freetype@nongnu.org - - Discusses general use and applications of FreeType, as well as - future and wanted additions to the library and distribution. - If you are looking for support, start in this list if you - haven't found anything to help you in the documentation. - - o freetype-devel@nongnu.org - - Discusses bugs, as well as engine internals, design issues, - specific licenses, porting, etc. - - Our home page can be found at - - https://www.freetype.org - - ---- end of FTL.TXT --- diff --git a/lib/libesp32_lvgl/freetype/docs/GPLv2.TXT b/lib/libesp32_lvgl/freetype/docs/GPLv2.TXT deleted file mode 100644 index b2fe7b6af..000000000 --- a/lib/libesp32_lvgl/freetype/docs/GPLv2.TXT +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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 2 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, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/lib/libesp32_lvgl/freetype/docs/INSTALL b/lib/libesp32_lvgl/freetype/docs/INSTALL deleted file mode 100644 index 814fc7bcc..000000000 --- a/lib/libesp32_lvgl/freetype/docs/INSTALL +++ /dev/null @@ -1,90 +0,0 @@ - -There are several ways to build the FreeType library, depending on -your system and the level of customization you need. Here is a short -overview of the documentation available: - - -I. Normal installation and upgrades -=================================== - - 1. Unix Systems (including Mac OS X, Cygwin, and MSys on Windows) - - Please read `INSTALL.UNIX' to install or upgrade FreeType 2 on a - Unix system. Note that you *need* GNU Make for automatic - compilation, since other make tools won't work (this includes BSD - Make). - - GNU Make VERSION 3.81 OR NEWER IS NEEDED! - - [For `cmake' see below.] - - - 2. On VMS with the `mms' build tool - - See `INSTALL.VMS' for installation instructions on this platform. - - - 3. Other systems using GNU Make - - On non-Unix platforms, it is possible to build the library using - GNU Make utility. Note that *NO OTHER MAKE TOOL WILL WORK*[1]! - This methods supports several compilers on Windows, OS/2, and - BeOS, including MinGW, Visual C++, Borland C++, and more. - - Instructions are provided in the file `INSTALL.GNU'. - - - 4. With an IDE Project File (e.g., for Visual Studio or CodeWarrior) - - We provide a small number of `project files' for various IDEs to - automatically build the library as well. Note that these files - are not supported and only sporadically maintained by FreeType - developers, so don't expect them to work in each release. - - To find them, have a look at the content of the `builds/' - directory, where stands for your OS or environment. - - - 5. Using cmake - - See the top-level `CMakeLists.txt' file for more information. - - - 6. From you own IDE, or own Makefiles - - If you want to create your own project file, follow the - instructions given in the `INSTALL.ANY' document of this - directory. - - -II. Custom builds of the library -================================ - - Customizing the compilation of FreeType is easy, and allows you to - select only the components of the font engine that you really need. - For more details read the file `CUSTOMIZE'. - - ----------------------------------------------------------------------- - -[1] make++, a make tool written in Perl, has sufficient support of GNU - make extensions to build FreeType. See - - https://makepp.sourceforge.net - - for more information; you need version 2.0 or newer, and you must - pass option `--norc-substitution'. - ----------------------------------------------------------------------- - -Copyright (C) 2000-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute -this file you indicate that you have read the license and understand -and accept it fully. - - ---- end of INSTALL --- diff --git a/lib/libesp32_lvgl/freetype/docs/INSTALL.ANY b/lib/libesp32_lvgl/freetype/docs/INSTALL.ANY deleted file mode 100644 index 879dddb89..000000000 --- a/lib/libesp32_lvgl/freetype/docs/INSTALL.ANY +++ /dev/null @@ -1,156 +0,0 @@ -Instructions on how to build FreeType with your own build tool -============================================================== - -See the file `CUSTOMIZE' to learn how to customize FreeType to -specific environments. - - -I. Standard procedure ---------------------- - - * If you use macro names for FreeType header files (while mandatory - in earlier versions, this is now optional since FreeType version - 2.10.3) it is necessary to disable pre-compiled headers. This is - very important for Visual C++, because lines like - - #include FT_FREETYPE_H - - are not correctly supported by this compiler while being ISO C - compliant! - - * You need to add the directory `include' to your include path when - compiling the library. - - * FreeType 2 is made of several components; each of them is located - in a subdirectory of `freetype2/src'. For example, - `freetype2/src/truetype/' contains the TrueType font driver. - - * DO NOT COMPILE ALL C FILES! Rather, compile the following ones. - - -- base components (required) - - src/base/ftsystem.c - src/base/ftinit.c - src/base/ftdebug.c - - src/base/ftbase.c - - src/base/ftbbox.c -- recommended, see - src/base/ftglyph.c -- recommended, see - - src/base/ftbdf.c -- optional, see - src/base/ftbitmap.c -- optional, see - src/base/ftcid.c -- optional, see - src/base/ftfstype.c -- optional - src/base/ftgasp.c -- optional, see - src/base/ftgxval.c -- optional, see - src/base/ftmm.c -- optional, see - src/base/ftotval.c -- optional, see - src/base/ftpatent.c -- optional - src/base/ftpfr.c -- optional, see - src/base/ftstroke.c -- optional, see - src/base/ftsynth.c -- optional, see - src/base/fttype1.c -- optional, see - src/base/ftwinfnt.c -- optional, see - - src/base/ftmac.c -- only on the Macintosh - - -- font drivers (optional; at least one is needed) - - src/bdf/bdf.c -- BDF font driver - src/cff/cff.c -- CFF/OpenType font driver - src/cid/type1cid.c -- Type 1 CID-keyed font driver - src/pcf/pcf.c -- PCF font driver - src/pfr/pfr.c -- PFR/TrueDoc font driver - src/sfnt/sfnt.c -- SFNT files support - (TrueType & OpenType) - src/truetype/truetype.c -- TrueType font driver - src/type1/type1.c -- Type 1 font driver - src/type42/type42.c -- Type 42 font driver - src/winfonts/winfnt.c -- Windows FONT / FNT font driver - - -- rasterizers (optional; at least one is needed for vector - formats) - - src/raster/raster.c -- monochrome rasterizer - src/smooth/smooth.c -- anti-aliasing rasterizer - - -- auxiliary modules (optional) - - src/autofit/autofit.c -- auto hinting module - src/cache/ftcache.c -- cache sub-system (in beta) - src/gzip/ftgzip.c -- support for compressed fonts (.gz) - src/lzw/ftlzw.c -- support for compressed fonts (.Z) - src/bzip2/ftbzip2.c -- support for compressed fonts (.bz2) - src/gxvalid/gxvalid.c -- TrueTypeGX/AAT table validation - src/otvalid/otvalid.c -- OpenType table validation - src/psaux/psaux.c -- PostScript Type 1 parsing - src/pshinter/pshinter.c -- PS hinting module - src/psnames/psnames.c -- PostScript glyph names support - - - Notes: - - `ftcache.c' needs `ftglyph.c' - `ftfstype.c' needs `fttype1.c' - `ftglyph.c' needs `ftbitmap.c' - `ftstroke.c' needs `ftglyph.c' - `ftsynth.c' needs `ftbitmap.c' - - `cff.c' needs `sfnt.c', `pshinter.c', and `psnames.c' - `truetype.c' needs `sfnt.c' and `psnames.c' - `type1.c' needs `psaux.c' `pshinter.c', and `psnames.c' - `type1cid.c' needs `psaux.c', `pshinter.c', and `psnames.c' - `type42.c' needs `truetype.c' - - Please consult the central `include/freetype/config/ftoption.h' - configuration file for details on additional libraries necessary - for some optional features. - - - Read the file `CUSTOMIZE' in case you want to compile only a subset - of the drivers, renderers, and optional modules; a detailed - description of the various base extension is given in the top-level - file `modules.cfg'. - - You are done. In case of problems, see the archives of the FreeType - development mailing list. - - -II. Support for flat-directory compilation ------------------------------------------- - - It is possible to put all FreeType 2 source files into a single - directory, with the *exception* of the `include' hierarchy. - - 1. Copy all files in current directory - - cp freetype2/src/base/*.[hc] . - cp freetype2/src/raster1/*.[hc] . - cp freetype2/src/smooth/*.[hc] . - etc. - - 2. Compile sources - - cc -c -Iinclude -DFT2_BUILD_LIBRARY ftsystem.c - cc -c -Iinclude -DFT2_BUILD_LIBRARY ftinit.c - cc -c -Iinclude -DFT2_BUILD_LIBRARY ftdebug.c - cc -c -Iinclude -DFT2_BUILD_LIBRARY ftbase.c - etc. - - You don't need to define the FT_FLAT_COMPILATION macro (as this - was required in previous releases of FreeType 2). - ----------------------------------------------------------------------- - -Copyright (C) 2003-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute -this file you indicate that you have read the license and understand -and accept it fully. - - ---- end of INSTALL.ANY --- diff --git a/lib/libesp32_lvgl/freetype/docs/INSTALL.CROSS b/lib/libesp32_lvgl/freetype/docs/INSTALL.CROSS deleted file mode 100644 index 85118056c..000000000 --- a/lib/libesp32_lvgl/freetype/docs/INSTALL.CROSS +++ /dev/null @@ -1,177 +0,0 @@ -This document contains instructions on how to cross-build the FreeType -library on Unix systems, for example, building binaries for Linux/MIPS -on FreeBSD/i386. Before reading this document, please consult the -file `INSTALL.UNIX' for required tools and the basic self-building -procedure. - - - 1. Required Tools - ----------------- - - For self-building the FreeType library on a Unix system, GNU Make - 3.81 or newer is required. `INSTALL.UNIX' contains hints how to - check the installed `make'. - - The GNU C compiler to cross-build the target system is required. - Currently, using a non-GNU cross compiler is untested. The cross - compiler is expected to be installed with a system prefix. For - example, if your building system is FreeBSD/i386 and the target - system is Linux/MIPS, the cross compiler should be installed with - the name `mips-ip22-linuxelf-gcc'. - - A C compiler for a self-build is required also, to build a tool - (`apinames') that is executed during the build procedure. Non-GNU - self compilers are acceptable, but such a setup is untested. - - - 2. Configuration - ---------------- - - 2.1. Building and target system - - To configure a cross-build, the options `--host=' and - `--build=' must be passed to the `configure' script. - For example, if your build system is FreeBSD/i386 and the target - system is Linux/MIPS, say - - ./configure \ - --build=i386-unknown-freebsd \ - --host=mips-ip22-linuxelf \ - [other options] - - It should be noted that `--host=' specifies the system - where the built binaries will be executed, not the system where - the build actually happens. Older versions of GNU autoconf use - the option pair `--host=' and `--target='. This is broken and - doesn't work. Similarly, an explicit CC specification like - - env CC=mips-ip22-linux-gcc ./configure # BAD - - or - - env CC=/usr/local/mips-ip22-linux/bin/gcc ./configure # BAD - - doesn't work either; such a configuration confuses the - `configure' script while trying to find the cross and native C - compilers. - - - 2.2. The prefix to install FreeType2 - - Setting `--prefix=' properly is important. The prefix - to install FreeType2 is written into the `freetype-config' - script and `freetype2.pc' configuration file. - - If the built FreeType 2 library is used as a part of the - cross-building system, the prefix is expected to be different - from the self-building system. For example, a configuration - with `--prefix=/usr/local' installs binaries into the - system-wide `/usr/local' directory, which then can't be executed - due to the incorrect architecture. This causes confusion in - configuration of all applications that use FreeType2. Instead, - use a prefix to install the cross-build into a separate system - tree, for example, `--prefix=/usr/local/mips-ip22-linux/'. - - On the other hand, if the built FreeType 2 library is used as a - part of the target system, the prefix to install should reflect - the file system structure of the target system. - - - 2.3. Library dependencies - - FreeType normally depends on external libraries like `libpng' or - `libharfbuzz'. The easiest case is to deactivate all such - dependencies using the `--without-XXX' configuration options. - However, if you want to use those libraries, you should ensure - that they are available both on the target system and as - (cross-compiled) libraries on the build system. - - FreeType uses `pkg-config' to find most of the libraries; the - other libraries it links to are expected in the standard system - directories. Since the default pkg-config's meta-information - files (like `harfbuzz.pc') of the build platform don't work, use - one of the two possible solutions below. - - o Use pkg-config's meta-information files that are adjusted to - cross-compile and cross-link with the target platform's - libraries. Make sure those files are found before the build - system's default files. Example: - - ./configure \ - --build=i386-unknown-freebsd \ - --host=mips-ip22-linuxelf \ - PKG_CONFIG_LIBDIR="/usr/local/mips-ip22-linux/lib/pkgconfig" \ - [other options] - - See the manpage of `pkg-config' for more details. - - o Set variables like LIBPNG_LIBS as additional options to the - `configure' script, overriding the values `pkg-config' would - provide. `configure --help' shows the available environment - variables. Example: - - ./configure \ - --build=i386-unknown-freebsd \ - --host=mips-ip22-linuxelf \ - LIBPNG_CFLAGS="-I/usr/local/mips-ip22-linux/include" \ - LIBPNG_LIBS="-L/usr/local/mips-ip22-linux/lib -lpng12" \ - [other options] - - - 3. Building command - ------------------- - - If the configuration finishes successfully, invoking GNU make - builds FreeType2. Just say - - make - - or - - gmake - - depending on the name the GNU make binary actually has. - - - 4. Installation - --------------- - - Saying - - make install - - as usual to install FreeType2 into the directory tree specified by - the argument of the `--prefix' option. - - As noted in section 2.2, FreeType2 is sometimes configured to be - installed into the system directory of the target system, and - should not be installed in the cross-building system. In such - cases, the make variable `DESTDIR' is useful to change the root - directory in the installation. For example, after - - make DESTDIR=/mnt/target_system_root/ install - - the built FreeType2 library files are installed into the directory - `/mnt/target_system_root//lib'. - - - 5. TODO - ------- - - Cross building between Cygwin (or MSys) and Unix must be tested. - - ----------------------------------------------------------------------- - -Copyright (C) 2006-2020 by -suzuki toshiya, David Turner, Robert Wilhelm, and Werner Lemberg. - - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute -this file you indicate that you have read the license and understand -and accept it fully. - - ---- end of INSTALL.CROSS --- diff --git a/lib/libesp32_lvgl/freetype/docs/INSTALL.GNU b/lib/libesp32_lvgl/freetype/docs/INSTALL.GNU deleted file mode 100644 index 8fdbb825e..000000000 --- a/lib/libesp32_lvgl/freetype/docs/INSTALL.GNU +++ /dev/null @@ -1,161 +0,0 @@ -This document contains instructions how to build the FreeType library -on non-Unix systems with the help of GNU Make. Note that if you are -running Cygwin or MinGW/MSYS in Windows, you should follow the -instructions in the file `INSTALL.UNIX' instead. - - - FreeType 2 includes a powerful and flexible build system that allows - you to easily compile it on a great variety of platforms from the - command line. To do so, just follow these simple instructions. - - 1. Install GNU Make - ------------------- - - Because GNU Make is the only Make tool supported to compile - FreeType 2, you should install it on your machine. - - The FreeType 2 build system relies on many features special to GNU - Make. - - NEARLY ALL OTHER MAKE TOOLS FAIL, INCLUDING `BSD MAKE', SO REALLY - INSTALL A RECENT VERSION OF GNU MAKE ON YOUR SYSTEM! - - Note that make++, a make tool written in Perl, supports enough - features of GNU make to compile FreeType. See - - https://makepp.sourceforge.net - - for more information; you need version 2.0 or newer, and you must - pass option `--norc-substitution'. - - Make sure that you are invoking GNU Make from the command line, by - typing something like: - - make -v - - to display its version number. - - VERSION 3.81 OR NEWER IS NEEDED! - - - 2. Invoke `make' - ---------------- - - Go to the root directory of FreeType 2, then simply invoke GNU - Make from the command line. This will launch the FreeType 2 host - platform detection routines. A summary will be displayed, for - example, on Win32. - - - ============================================================== - FreeType build system -- automatic system detection - - The following settings are used: - - platform windows - compiler gcc - configuration directory .\builds\windows - configuration rules .\builds\windows\w32-gcc.mk - - If this does not correspond to your system or settings please - remove the file 'config.mk' from this directory then read the - INSTALL file for help. - - Otherwise, simply type 'make' again to build the library - or 'make refdoc' to build the API reference (the latter needs - Python >= 3.5). - ============================================================= - - - If the detected settings correspond to your platform and compiler, - skip to step 5. Note that if your platform is completely alien to - the build system, the detected platform will be `ansi'. - - - 3. Configure the build system for a different compiler - ------------------------------------------------------ - - If the build system correctly detected your platform, but you want - to use a different compiler than the one specified in the summary - (for most platforms, gcc is the default compiler), invoke GNU Make - with - - make setup - - Examples: - - to use Visual C++ on Win32, type: `make setup visualc' - to use Borland C++ on Win32, type `make setup bcc32' - to use Watcom C++ on Win32, type `make setup watcom' - to use Intel C++ on Win32, type `make setup intelc' - to use LCC-Win32 on Win32, type: `make setup lcc' - to use Watcom C++ on OS/2, type `make setup watcom' - to use VisualAge C++ on OS/2, type `make setup visualage' - - The name to use is platform-dependent. The list of - available compilers for your system is available in the file - `builds//detect.mk'. - - If you are satisfied by the new configuration summary, skip to - step 5. - - - 4. Configure the build system for an unknown platform/compiler - -------------------------------------------------------------- - - The auto-detection/setup phase of the build system copies a file - to the current directory under the name `config.mk'. - - For example, on OS/2+gcc, it would simply copy - `builds/os2/os2-gcc.mk' to `./config.mk'. - - If for some reason your platform isn't correctly detected, copy - manually the configuration sub-makefile to `./config.mk' and go to - step 5. - - Note that this file is a sub-Makefile used to specify Make - variables for compiler and linker invocation during the build. - You can easily create your own version from one of the existing - configuration files, then copy it to the current directory under - the name `./config.mk'. - - - 5. Build the library - -------------------- - - The auto-detection/setup phase should have copied a file in the - current directory, called `./config.mk'. This file contains - definitions of various Make variables used to invoke the compiler - and linker during the build. [It has also generated a file called - `ftmodule.h' in the objects directory (which is normally - `/objs/'); please read the file `docs/CUSTOMIZE' for - customization of FreeType.] - - To launch the build, simply invoke GNU Make again: The top - Makefile will detect the configuration file and run the build with - it. - - - Final note - - The above instructions build a _statically_ linked library of the - font engine in the `objs' directory. On Windows, you can build a - DLL either with MinGW (within an MSYS shell, following the - instructions in `INSTALL.UNIX'), or you use one of the Visual C++ - project files; see the subdirectories of `builds/windows'. For - everything else, you are on your own, and you might follow the - instructions in `INSTALL.ANY' to create your own Makefiles. - ----------------------------------------------------------------------- - -Copyright (C) 2003-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute -this file you indicate that you have read the license and understand -and accept it fully. - - ---- end of INSTALL.GNU --- diff --git a/lib/libesp32_lvgl/freetype/docs/INSTALL.MAC b/lib/libesp32_lvgl/freetype/docs/INSTALL.MAC deleted file mode 100644 index 2587e24a6..000000000 --- a/lib/libesp32_lvgl/freetype/docs/INSTALL.MAC +++ /dev/null @@ -1,32 +0,0 @@ -Please follow the instructions in INSTALL.UNIX to install FreeType on -Mac OS X. - -Currently FreeType2 functions based on some deprecated Carbon APIs -return `FT_Err_Unimplemented_Feature' always, even if FreeType2 is -configured and built on the system that deprecated Carbon APIs are -available. To enable deprecated FreeType2 functions as far as -possible, replace `src/base/ftmac.c' by `builds/mac/ftmac.c'. - -Starting with Mac OS X 10.5, gcc defaults the deployment target to -10.5. In previous versions of Mac OS X, this defaulted to 10.1. If -you want your built binaries to run only on 10.5, this change does not -concern you. If you want them to also run on older versions of Mac -OS X, then you must either set the MACOSX_DEPLOYMENT_TARGET -environment variable or pass `-mmacosx-version-min' to gcc. You -should specify the oldest version of Mac OS you want the code to run -on. For example, if you use Bourne shell: - - export MACOSX_DEPLOYMENT_TARGET=10.2 - -or, if you use C shell: - - setenv MACOSX_DEPLOYMENT_TARGET 10.2 - -Alternatively, you could pass `-mmacosx-version-min=10.2' to gcc. - -Here the number 10.2 is the lowest version that the built binaries can -run on. In the above cases, the built binaries will run on Mac OS X -10.2 and later, but _not_ earlier. If you want to run on earlier, you -have to set lower version, e.g., 10.0. - -For classic Mac OS (Mac OS 7, 8, 9) please refer to builds/mac/README. diff --git a/lib/libesp32_lvgl/freetype/docs/INSTALL.UNIX b/lib/libesp32_lvgl/freetype/docs/INSTALL.UNIX deleted file mode 100644 index f8d220ac2..000000000 --- a/lib/libesp32_lvgl/freetype/docs/INSTALL.UNIX +++ /dev/null @@ -1,118 +0,0 @@ -This document contains instructions on how to build the FreeType -library on Unix systems. This also works for emulations like Cygwin -or MSys on Win32: - - - 1. Ensure that you are using GNU Make - ------------------------------------- - - The FreeType build system _exclusively_ works with GNU Make. You - will not be able to compile the library with the instructions - below using any other alternative (including BSD Make). - - Check that you have GNU make by running the command: - - make -v - - This should dump some text that begins with: - - GNU Make - Copyright (C) Free Software Foundation Inc. - - Note that version 3.81 or higher is *required* or the build will - fail. - - It is also fine to have GNU Make under another name (e.g. 'gmake') - if you use the MAKE variable as described below. - - As a special exception, 'makepp' can also be used to build - FreeType 2. See the file docs/MAKEPP for details. - - For builds with `cmake' please check file `CMakeLists.txt'; this - is a contributed file not directly supported by the FreeType team. - - - 2. Regenerate the configure script if needed - -------------------------------------------- - - This only applies if you are building a git snapshot or checkout, - *not* if you grabbed the sources of an official release. - - You need to invoke the `autogen.sh' script in the top-level - directory in order to create the `configure' script for your - platform. Normally, this simply means typing: - - sh autogen.sh - - In case of problems, you may need to install or upgrade Automake, - Autoconf or Libtool. See README.git in the top-level directory - for more information. - - - 3. Build and install the library - -------------------------------- - - The following should work on all Unix systems where the `make' - command invokes GNU Make: - - ./configure [options] - make - make install (as root) - - The default installation path is `/usr/local'. It can be changed - with the `--prefix=' option. Example: - - ./configure --prefix=/usr - - When using a different command to invoke GNU Make, use the MAKE - variable. For example, if `gmake' is the command to use on your - system, do something like: - - MAKE=gmake ./configure [options] - gmake - gmake install (as root) - - If this still doesn't work, there must be a problem with your - system (e.g., you are using a very old version of GNU Make). - - It is possible to compile FreeType in a different directory. - Assuming the FreeType source files in directory `/src/freetype' a - compilation in directory `foo' works as follows: - - cd foo - /src/freetype/configure [options] - make - make install - - - 3.1 Interdependency with HarfBuzz - ................................. - - Note that there is a chicken-and-egg problem currently since the - HarfBuzz library (used by the auto-hinter to improve support of - OpenType fonts) depends on FreeType, which can be solved as - follows in case HarfBuzz is not yet installed on your system. - - 1. Call FreeType's `configure' script with option - `--without-harfbuzz', then compile and install FreeType. - - 2. Compile and install HarfBuzz. - - 3. Call FreeType's `configure' script without option - `--without-harfbuzz' (after executing `make distclean'), then - compile and install FreeType again. - - ----------------------------------------------------------------------- - -Copyright (C) 2003-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute -this file you indicate that you have read the license and understand -and accept it fully. - - ---- end of INSTALL.UNIX --- diff --git a/lib/libesp32_lvgl/freetype/docs/INSTALL.VMS b/lib/libesp32_lvgl/freetype/docs/INSTALL.VMS deleted file mode 100644 index e1817ec61..000000000 --- a/lib/libesp32_lvgl/freetype/docs/INSTALL.VMS +++ /dev/null @@ -1,62 +0,0 @@ -How to build the FreeType 2 library on VMS ------------------------------------------ - -It is actually very straightforward to install the FreeType 2 library. -Just execute vms_make.com from the toplevel directory to build the -library. This procedure currently accepts the following options: - -DEBUG - Build the library with debug information and without optimization. - -lopts= - Options to pass to the link command e.g. lopts=/traceback - -ccopt= - Options to pass to the C compiler e.g. ccopt=/float=ieee - -In case you did download the demos, place them in a separate directory -sharing the same top level as the directory of FreeType 2 and follow -the same instructions as above for the demos from there. The build -process relies on this to figure out the location of the FreeType 2 -include files. - - -To rebuild the sources it is necessary to have MMS/MMK installed on -the system. - -The library is available in the directory - - [.LIB] - -To compile applications using FreeType 2 you have to define the -logical FREETYPE pointing to the directory - - [.INCLUDE.FREETYPE] - -i.e., if the directory in which this INSTALL.VMS file is located is -$disk:[freetype] then define the logical with - - define freetype $disk:[freetype.include.freetype] - -This version has been tested with Compaq C V6.2-006 on OpenVMS Alpha -V7.2-1. - - - Any problems can be reported to - - Jouk Jansen or - Martin P.J. Zinser - ------------------------------------------------------------------------- - -Copyright (C) 2000-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute this -file you indicate that you have read the license and understand and -accept it fully. - - ---- end of INSTALL.VMS --- diff --git a/lib/libesp32_lvgl/freetype/docs/LICENSE.TXT b/lib/libesp32_lvgl/freetype/docs/LICENSE.TXT deleted file mode 100644 index af5a1c50f..000000000 --- a/lib/libesp32_lvgl/freetype/docs/LICENSE.TXT +++ /dev/null @@ -1,39 +0,0 @@ - -The FreeType 2 font engine is copyrighted work and cannot be used -legally without a software license. In order to make this project -usable to a vast majority of developers, we distribute it under two -mutually exclusive open-source licenses. - -This means that *you* must choose *one* of the two licenses described -below, then obey all its terms and conditions when using FreeType 2 in -any of your projects or products. - - - The FreeType License, found in the file `FTL.TXT', which is similar - to the original BSD license *with* an advertising clause that forces - you to explicitly cite the FreeType project in your product's - documentation. All details are in the license file. This license - is suited to products which don't use the GNU General Public - License. - - Note that this license is compatible to the GNU General Public - License version 3, but not version 2. - - - The GNU General Public License version 2, found in `GPLv2.TXT' (any - later version can be used also), for programs which already use the - GPL. Note that the FTL is incompatible with GPLv2 due to its - advertisement clause. - -The contributed BDF and PCF drivers come with a license similar to that -of the X Window System. It is compatible to the above two licenses (see -file src/bdf/README and src/pcf/README). The same holds for the files -`fthash.c' and `fthash.h'; their code was part of the BDF driver in -earlier FreeType versions. - -The gzip module uses the zlib license (see src/gzip/zlib.h) which too is -compatible to the above two licenses. - -The MD5 checksum support (only used for debugging in development builds) -is in the public domain. - - ---- end of LICENSE.TXT --- diff --git a/lib/libesp32_lvgl/freetype/docs/MAKEPP b/lib/libesp32_lvgl/freetype/docs/MAKEPP deleted file mode 100644 index 4450e4770..000000000 --- a/lib/libesp32_lvgl/freetype/docs/MAKEPP +++ /dev/null @@ -1,5 +0,0 @@ -As a special exception, FreeType can also be built with the 'makepp' -build tool, available from https://makepp.sourceforge.net. - -Note, however, that you will need at least version 2.0 and pass the -option --norc-substitution to have it work correctly. diff --git a/lib/libesp32_lvgl/freetype/docs/PROBLEMS b/lib/libesp32_lvgl/freetype/docs/PROBLEMS deleted file mode 100644 index 40bdc35a6..000000000 --- a/lib/libesp32_lvgl/freetype/docs/PROBLEMS +++ /dev/null @@ -1,90 +0,0 @@ -This file describes various problems that have been encountered in -compiling, installing and running FreeType 2. Suggestions for -additions or other improvements to this file are welcome. - ----------------------------------------------------------------------- - -Running Problems -================ - - -* Some Type 1, Multiple Masters, and CID-keyed PostScript fonts aren't - handled correctly. - ------ - -Of course, there might be bugs in FreeType, but some fonts based on -the PostScript format can't be handled indeed. The reason is that -FreeType doesn't contain a full PostScript interpreter but applies -pattern matching instead. In case a font doesn't follow the standard -structure of the given font format, FreeType fails. A typical example -is Adobe's `Optima' font family which contains extra code to switch -between low and high resolution versions of the glyphs. - -It might be possible to patch FreeType in some situations, though. -Please report failing fonts so that we investigate the problem and set -up a list of such problematic fonts. - - -* Why do identical FreeType versions render differently on different - platforms? - ------ - -Different distributions compile FreeType with different options. The -developer version of a distribution's FreeType package, which is -needed to compile your program against FreeType, includes the file -ftoption.h. Compare each platform's copy of ftoption.h to find the -differences. - - ----------------------------------------------------------------------- - - -Compilation Problems -==================== - - -* I get an `internal compilation error' (ICE) while compiling FreeType - 2.2.1 with Intel C++. - - This has been reported for the following compiler version: - - Intel(R) C++ Compiler for 32-bit applications, - Version 9.0 Build 20050430Z Package ID: W_CC_P_9.0.019 - ------ - -The best solution is to update the compiler to version - - Intel(R) C++ Compiler for 32-bit applications, - Version 9.1 Build 20060323Z Package ID: W_CC_P_9.1.022 - -or newer. If this isn't feasible, apply the following patch. - - ---- src/cache/ftcbasic.c 20 Mar 2006 12:10:24 -0000 1.20 -+++ src/cache/ftcbasic.c.patched 15 May 2006 02:51:02 -0000 -@@ -252,7 +252,7 @@ - */ - - FT_CALLBACK_TABLE_DEF -- const FTC_IFamilyClassRec ftc_basic_image_family_class = -+ FTC_IFamilyClassRec ftc_basic_image_family_class = - { - { - sizeof ( FTC_BasicFamilyRec ), -@@ -266,7 +266,7 @@ - - - FT_CALLBACK_TABLE_DEF -- const FTC_GCacheClassRec ftc_basic_image_cache_class = -+ FTC_GCacheClassRec ftc_basic_image_cache_class = - { - { - ftc_inode_new, - - ----------------------------------------------------------------------- - ---- end of PROBLEMS --- diff --git a/lib/libesp32_lvgl/freetype/docs/README b/lib/libesp32_lvgl/freetype/docs/README deleted file mode 100644 index d71fd379c..000000000 --- a/lib/libesp32_lvgl/freetype/docs/README +++ /dev/null @@ -1,35 +0,0 @@ -After saying `make refdoc' or `make refdoc-venv' the `reference/' directory -contains the FreeType API reference. You need Python >= 3.5 and pip to make -this target. - -There are two ways to generate the documentation: - -1. Using `make refdoc': - - - Ensure `python' and `pip' are available. - - Install pip package `docwriter' with `pip install --user docwriter'. - - Make target with `make refdoc'. - - This target can be run offline once required packages are installed. - -2. Using `make refdoc-venv' (requires internet access): - - - Ensure `python', `pip' and Python package `virtualenv' are available. - - Make target with `make refdoc-venv'. - - This may or may not require internet access every time depending on - pip and system caching. - -This also works with Jam: Just type `jam refdoc' in the main directory. - -Some troubleshooting tips: - -* Regularly run `pip install --upgrade docwriter' to check for updates which -may include bug fixes. - -* `Docwriter' does not support Python 2. Ensure that Python >= 3.5 is -installed and available as `python3'/`python'. - -* Ensure that `docwriter' is installed in the same Python target that -`make refdoc' uses (python3/python). - -* If none of this works, send a mail to `freetype-devel@nongnu.org' or file -an issue at `https://github.com/freetype/docwriter/issues'. diff --git a/lib/libesp32_lvgl/freetype/docs/TODO b/lib/libesp32_lvgl/freetype/docs/TODO deleted file mode 100644 index 8b27e269a..000000000 --- a/lib/libesp32_lvgl/freetype/docs/TODO +++ /dev/null @@ -1,40 +0,0 @@ -Here is a list of items that need to be addressed in FreeType 2 ---------------------------------------------------------------- - -* Implement stem3/counter hints properly in the Postscript hinter. - -* Add CIDCMap support to the CID driver. - -* Add track kerning support to the PFR driver. - -* Add kerning (AFM file) support to the CID driver. - - -Here is a list of bugs which should be handled ----------------------------------------------- - -Other bugs have been registered at the savannah bugzilla of FreeType. - -* CID driver: - Handle the case where a CID font has a top-level font matrix also - (see PLRM, 5.11.3, Type 0 CIDFonts). Since CID_FaceInfoRec lacks - a font_matrix entry we have to directly apply it to all subfont - matrices. - -* CID driver: - Use top-level font matrix entry for setting the upem value, not the - entries in the FDarray. If absent, use 1000. - ------------------------------------------------------------------------- - -Copyright (C) 2001-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute this -file you indicate that you have read the license and understand and -accept it fully. - - ---- end of TODO --- diff --git a/lib/libesp32_lvgl/freetype/docs/VERSIONS.TXT b/lib/libesp32_lvgl/freetype/docs/VERSIONS.TXT deleted file mode 100644 index 4e281a725..000000000 --- a/lib/libesp32_lvgl/freetype/docs/VERSIONS.TXT +++ /dev/null @@ -1,130 +0,0 @@ -Due to our use of `libtool' to generate and install the FreeType 2 -libraries on Unix systems, as well as other historical events, it is -generally very difficult to know precisely which release of the font -engine is installed on a given system. - -This file tries to explain why and to document ways to properly detect -FreeType on Unix. - - -1. Version and Release numbers ------------------------------- - -For each new public release of FreeType 2, there are generally *three* -distinct `version' numbers to consider: - - * The official FreeType 2 release number, like 2.7.0 or 2.10.2. - - * The libtool (and Unix) specific version number, like 23.2.17. - This is what - - pkg-config freetype2 --modversion - - or - - freetype-config --version - - returns. - - * The platform-specific shared object number, used for example when - the library is installed as `/usr/lib/libfreetype.so.6.17.2'. - -The platform-specific number is, unsurprisingly, platform-specific and -varies with the operating system you are using (several variants of -Linux, FreeBSD, Solaris, etc.). You should thus _never_ use it, even -for simple tests. - -The libtool-specific number does not equal the release number but is -tied to it. - -The release number is available at *compile* time through the -following macros defined in `freetype.h': - - - FREETYPE_MAJOR: major release number - - FREETYPE_MINOR: minor release number - - FREETYPE_PATCH: patch release number - -See below for a small autoconf fragment. - -The release number is also available at *runtime* through the -`FT_Library_Version' API. - - -2. History ----------- - -The following table gives, for all releases since 2.5.0, the -corresponding libtool number, as well as the shared object number -found on _most_ systems, but not all of them: - - - release libtool so - ------------------------------- - 2.10.4 23.4.17 6.17.4 - 2.10.3 23.3.17 6.17.3 - 2.10.2 23.2.17 6.17.2 - 2.10.1 23.1.17 6.17.1 - 2.10.0 23.0.17 6.17.0 - 2.9.1 22.1.16 6.16.1 - 2.9.0 22.0.16 6.16.0 - 2.8.1 21.0.15 6.15.0 - 2.8.0 20.0.14 6.14.0 - 2.7.1 19.0.13 6.13.0 - 2.7.0 18.6.12 6.12.6 - 2.6.5 18.5.12 6.12.5 - 2.6.4 18.4.12 6.12.4 - 2.6.3 18.3.12 6.12.3 - 2.6.2 18.2.12 6.12.2 - 2.6.1 18.1.12 6.12.1 - 2.6.0 18.0.12 6.12.0 - 2.5.5 17.4.11 6.11.4 - 2.5.4 17.3.11 6.11.3 - 2.5.3 17.2.11 6.11.2 - 2.5.2 17.1.11 6.11.1 - 2.5.1 17.0.11 6.11.0 - 2.5.0 16.2.10 6.10.2 - - -3. Autoconf Code Fragment -------------------------- - -Lars Clausen contributed the following autoconf fragment to check -which version of FreeType is installed on a system (now updated to use -`pkg-config' instead of `freetype-config'). This one tests for a -version that is at least 2.10.2; you should change it to check against -other release numbers. - - - AC_MSG_CHECKING([whether FreeType version is 2.10.2 or higher]) - old_CPPFLAGS="$CPPFLAGS" - CPPFLAGS=`pkg-config freetype2 --cflags` - AC_TRY_CPP([ - -#include -#include - -#if FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH < 21002 -# error FreeType version too low. -#endif - - ], - [AC_MSG_RESULT(yes) - FREETYPE_LIBS=`pkg-config freetype2 --libs` - AC_SUBST(FREETYPE_LIBS) - AC_DEFINE(HAVE_FREETYPE,1,[Define if you have the FreeType2 library]) - CPPFLAGS="$old_CPPFLAGS"], - [AC_MSG_ERROR([Need FreeType library version 2.10.2 or higher])]) - ----------------------------------------------------------------------- - -Copyright (C) 2002-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute -this file you indicate that you have read the license and understand -and accept it fully. - - ---- end of VERSIONS.TXT --- diff --git a/lib/libesp32_lvgl/freetype/docs/formats.txt b/lib/libesp32_lvgl/freetype/docs/formats.txt deleted file mode 100644 index e640fab25..000000000 --- a/lib/libesp32_lvgl/freetype/docs/formats.txt +++ /dev/null @@ -1,208 +0,0 @@ -This file contains a list of various font formats. It gives the -reference document and whether it is supported in FreeType 2. - -Table fields ------------- - - wrapper format - The format used to represent the font data. In the table below it - is used only if the font format differs. Possible values are - - SFNT binary - PFB binary - PS a text header, followed by binary or text data - LZW compressed with either `gzip' or `compress' - BZ2 compressed with `bzip2'. - - font format - How the font is to be accessed, possibly after converting the file - type and wrapper format into a generic form. Bitmap formats are - `BDF', `PCF', and one form of `WINFNT'; all others are vector - formats. `PS' indicates third-order, `TT' second-order Bézier - curves. - - font type - Sub-formats of the font format. `SBIT' and `MACSBIT' are bitmap - formats, `MM' and `VAR' support optical axes. `CFF2' supports - optical axes also. - - glyph access - If not specified, the glyph access is `standard' to the font - format. Values are `CID' for CID-keyed fonts, `SYNTHETIC' for - fonts that are modified versions of other fonts by means of a - transformation matrix, and `TYPE_0' for PS fonts which are to be - accessed in a tree-like structure. - - FreeType driver - The module in the FreeType library which handles the specific font - format. A missing entry means that FreeType doesn't support the - font format (yet). - - -Notes ------ - - The SFNT container format also provides `collections' (usually - having the file extension `.ttc' or `.otc'). A collection contains - multiple font faces that share some tables to avoid redundancy, thus - reducing the file size. In FreeType, elements of a collection can - be accessed with a proper face index. - - Both the GX and the OpenType 1.8 variation fonts provide `named - instances'. FreeType maps them to face indices (they can also be - accessed with the standard MM interface). - - Other font formats (not using the SFNT wrapper) also provide - multiple faces within one file; they are marked with an asterisk - (`*') in the table below. - - FreeType can be configured to support Mac files (on older Mac OS - versions, a `file' is stored as a data and a resource fork, this is, - within two separate data chunks). If a file can't be opened as a - font, FreeType then checks whether it is a resource fork, trying to - extract the contained font data from either a `POST' or `sfnt' - resource. - - -Please send additions and/or corrections to wl@gnu.org or to the -FreeType developer's list at freetype-devel@nongnu.org (for -subscribers only). If you can provide a font example for a format -which isn't supported yet please send a mail too. - - - wrapper font font glyph FreeType reference - format format type access driver documents - ----------------------------------------------------------------------------- - - --- BDF --- --- bdf 5005.BDF_Spec.pdf, X11 - - - SFNT PS TYPE_1 --- type1 Type 1 GX Font Format - (for the Mac) [3] - SFNT PS TYPE_1 CID cid 5180.sfnt.pdf (for the Mac) - [3] - SFNT PS CFF --- cff OT spec, 5176.CFF.pdf - (`OTTO' format) - SFNT PS CFF CID cff OT spec, 5176.CFF.pdf - SFNT PS CFF SYNTHETIC --- OT spec, 5176.CFF.pdf - SFNT PS CFF2 --- cff OT spec 1.8 - - SFNT TT SBIT --- sfnt XFree86 (bitmaps only; - with `head' table) - SFNT TT MACSBIT --- sfnt OT spec (for the Mac; - bitmaps only; `bhed' table) - SFNT TT --- --- truetype OT spec (`normal' TT font) - SFNT TT VAR --- truetype GX spec (`?var' tables) - SFNT TT VAR --- truetype OT spec 1.8 - (`?var' + `?VAR' tables) - - - --- PS TYPE_1 --- type1 T1_SPEC.pdf - (PFA, Type 1 font resource) - PFB PS TYPE_1 --- type1 T1_SPEC.pdf, - 5040.Download_Fonts.pdf - (`normal' Type 1 font) - --- PS TYPE_1 CID cid PLRM.pdf (CID Font Type 0; - Type 9 font) - --- PS MM --- type1 5015.Type1_Supp.pdf - (Multiple Masters) - --- PS CFF --- cff 5176.CFF.pdf (`pure' CFF) - --- PS* CFF CID cff 5176.CFF.pdf (`pure' CFF) - --- PS CFF SYNTHETIC --- 5176.CFF.pdf (`pure' CFF) - --- PS CFF/MM --- cff old 5167.CFF.pdf (`pure' CFF) - [3] - --- PS* CFF/MM CID cff old 5167.CFF.pdf (`pure' CFF) - [3] - --- PS CFF/MM SYNTHETIC --- old 5167.CFF.pdf (`pure' CFF) - [3] - PS PS CFF --- --- PLRM.pdf (Type 2) [1] - PS PS* CFF CID --- PLRM.pdf (Type 2) [1] - PS PS CFF SYNTHETIC --- PLRM.pdf (Type 2) [1] - PS PS CFF/MM --- --- PLRM.pdf (Type 2) [1] - PS PS* CFF/MM CID --- PLRM.pdf (Type 2) [1] - PS PS CFF/MM SYNTHETIC --- PLRM.pdf (Type 2) [1] - --- PS --- TYPE_0 --- PLRM.pdf - --- PS TYPE_3 --- --- PLRM.pdf (never supported) - --- PS TYPE_3 CID --- PLRM.pdf (CID Font Type 1; - Type 10 font; never supported) - PS PS TYPE_14 --- --- PLRM.pdf (Chameleon font; - Type 14 font; never supported?) - --- PS TYPE_32 CID --- PLRM.pdf (CID Font Type 4; - Type 32 font; never supported?) - PS TT --- --- type42 5012.Type42_Spec.pdf - (Type 42 font) - PS TT --- CID --- PLRM.pdf (CID Font Type 2; - Type 11 font) - - - ? ? CEF ? cff ? - - - --- PCF --- --- pcf X11 [4] - LZW PCF --- --- pcf X11 [4] - BZ2 PCF --- --- pcf X11 [4] - - - --- PFR* PFR0 --- pfr [2] - --- PFR PFR1 --- --- (undocumented, proprietary; - probably never supported) - - - --- WINFNT* --- --- winfonts Windows developer's notes [5] - --- WINFNT VECTOR --- --- Windows developer's notes [5] - - -[1] Support should be rather simple since this is identical to `CFF' - but in a PS wrapper. - -[2] The official PFR specification is no longer available, but - archive.org has archived it: - - https://web.archive.org/web/20091014062300/http://www.bitstream.com/font_rendering/products/truedoc/pfrspec.html - https://web.archive.org/web/20081115152605/http://www.bitstream.com/font_rendering/pdfs/pfrspec1.3.pdf - - The syntax of the auxiliary data is not defined there, but is - partially defined in MHP 1.0.3 (also called ETSI TS 101812 V1.3.1) - section 7.4. - - https://www.etsi.org/ - https://webapp.etsi.org/workprogram/Report_WorkItem.asp?WKI_ID=18799 - -[3] Support is rudimentary currently; some tables or data are not - loaded yet. - -[4] See - - THE X WINDOW SYSTEM SERVER: X VERSION 11, RELEASE 5 - Elias Israel, Erik Fortune, Digital Press, 1992 - ISBN 1-55558-096-3 - - for a specification given in Appendix D on pgs. 436-450. However, - this information might be out of date; unfortunately, there is no - PCF specification available online, and this book is out of print. - George Williams deduced the font format from the X11 sources and - documented it for his FontForge font editor: - - https://fontforge.github.io/pcf-format.html - -[5] This is from MS Windows 3; see Microsoft's Knowledge Base article at - - https://support.microsoft.com/kb/65123 - ------------------------------------------------------------------------- - -Copyright (C) 2004-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute this -file you indicate that you have read the license and understand and -accept it fully. - - ---- end of formats.txt --- - -Local Variables: -coding: utf-8 -End: diff --git a/lib/libesp32_lvgl/freetype/docs/freetype-config.1 b/lib/libesp32_lvgl/freetype/docs/freetype-config.1 deleted file mode 100644 index 7dea66afa..000000000 --- a/lib/libesp32_lvgl/freetype/docs/freetype-config.1 +++ /dev/null @@ -1,146 +0,0 @@ -.TH FREETYPE-CONFIG 1 "October 2020" "FreeType 2.10.4" -. -. -.SH NAME -. -freetype-config \- Get information about a libfreetype installation -. -. -.SH SYNOPSIS -. -.B freetype-config -.RI [ options ] -. -. -.SH DESCRIPTION -. -.B freetype-config -returns information needed for compiling and linking programs with the -FreeType library, such as linker flags and compilation parameters. -. -Alternatively, it can be used to query information about the -FreeType library version installed on the system, such as the -installation (directory path) prefix or the FreeType version number. -. -.PP -If -.BR pkg-config (1) -is found in the path, -.B freetype-config -acts as a wrapper for -.BR pkg-config . -. -.PP -This program is part of the FreeType package. -. -. -.SH OPTIONS -. -There are two types of options: output/display selection options, and -path override options. -. -. -.SS Output selection options -. -Only one of the output selection options should be given at each program -invocation. -. -.TP -.B \-\-prefix -Return the prefix value of the installed FreeType library (the default -prefix will be `/usr' in most cases for distribution-installed -packages). -. -.TP -.B \-\-exec-prefix -Return the executable prefix value of the installed FreeType library -(will often be the same as the prefix value). -. -.TP -.B \-\-ftversion -Return the FreeType version number, directly derived from file -`freetype.h'. -. -.TP -.B \-\-version -Return the `libtool version' of the FreeType library. -. -.TP -.B \-\-libtool -Return the library name for linking with libtool. -. -.TP -.B \-\-libs -Return compiler flags for linking with the installed FreeType library. -. -.TP -.B \-\-cflags -Return compiler flags for compiling against the installed FreeType library. -. -.TP -.B \-\-static -Make command line options display flags for static linking. -. -.TP -.B \-\-help -Show help and exit. -. -. -.SS Path override options -. -These affect any selected output option, except the libtool version -returned by -.BR \-\-version . -. -.TP -.BI \-\-prefix= PREFIX -Override -.B \-\-prefix -value with -.IR PREFIX . -. -This also sets -.BI \-\-exec-prefix= PREFIX -if option -.B \-\-exec-prefix -is not explicitly given. -. -.TP -.BI \-\-exec-prefix= EPREFIX -Override -.B \-\-exec-prefix -value with -.IR EPREFIX . -. -. -.SH BUGS -In case the libraries FreeType links to are located in non-standard -directories, and -.BR pkg-config (1) -is not available, the output from option -.B \-\-libs -might be incomplete. -. -It is thus recommended to use the -.BR pkg-config (1) -interface instead, which is able to correctly resolve all dependencies. -. -.PP -Setting -.B \-\-exec-prefix -(either explicitly or implicitly) might return incorrect results if -combined with option -.BR \-\-static . -. -The same problem can occur if you set the -.B SYSROOT -environment variable. -. -. -.SH AUTHOR -. -This manual page was contributed by Nis Martensen , -with further refinements from the FreeType team. -. -. -.\" eof diff --git a/lib/libesp32_lvgl/freetype/docs/raster.txt b/lib/libesp32_lvgl/freetype/docs/raster.txt deleted file mode 100644 index 1bf4f67d4..000000000 --- a/lib/libesp32_lvgl/freetype/docs/raster.txt +++ /dev/null @@ -1,635 +0,0 @@ - - How FreeType's rasterizer work - - by David Turner - - Revised 2007-Feb-01 - - -This file is an attempt to explain the internals of the FreeType -rasterizer. The rasterizer is of quite general purpose and could -easily be integrated into other programs. - - - I. Introduction - - II. Rendering Technology - 1. Requirements - 2. Profiles and Spans - a. Sweeping the Shape - b. Decomposing Outlines into Profiles - c. The Render Pool - d. Computing Profiles Extents - e. Computing Profiles Coordinates - f. Sweeping and Sorting the Spans - - -I. Introduction -=============== - - A rasterizer is a library in charge of converting a vectorial - representation of a shape into a bitmap. The FreeType rasterizer - has been originally developed to render the glyphs found in - TrueType files, made up of segments and second-order Béziers. - Meanwhile it has been extended to render third-order Bézier curves - also. This document is an explanation of its design and - implementation. - - While these explanations start from the basics, a knowledge of - common rasterization techniques is assumed. - - -II. Rendering Technology -======================== - -1. Requirements ---------------- - - We assume that all scaling, rotating, hinting, etc., has been - already done. The glyph is thus described by a list of points in - the device space. - - - All point coordinates are in the 26.6 fixed float format. The - used orientation is: - - - ^ y - | reference orientation - | - *----> x - 0 - - - `26.6' means that 26 bits are used for the integer part of a - value and 6 bits are used for the fractional part. - Consequently, the `distance' between two neighbouring pixels is - 64 `units' (1 unit = 1/64th of a pixel). - - Note that, for the rasterizer, pixel centers are located at - integer coordinates. The TrueType bytecode interpreter, - however, assumes that the lower left edge of a pixel (which is - taken to be a square with a length of 1 unit) has integer - coordinates. - - - ^ y ^ y - | | - | (1,1) | (0.5,0.5) - +-----------+ +-----+-----+ - | | | | | - | | | | | - | | | o-----+-----> x - | | | (0,0) | - | | | | - o-----------+-----> x +-----------+ - (0,0) (-0.5,-0.5) - - TrueType bytecode interpreter FreeType rasterizer - - - A pixel line in the target bitmap is called a `scanline'. - - - A glyph is usually made of several contours, also called - `outlines'. A contour is simply a closed curve that delimits an - outer or inner region of the glyph. It is described by a series - of successive points of the points table. - - Each point of the glyph has an associated flag that indicates - whether it is `on' or `off' the curve. Two successive `on' - points indicate a line segment joining the two points. - - One `off' point amidst two `on' points indicates a second-degree - (conic) Bézier parametric arc, defined by these three points - (the `off' point being the control point, and the `on' ones the - start and end points). Similarly, a third-degree (cubic) Bézier - curve is described by four points (two `off' control points - between two `on' points). - - Finally, for second-order curves only, two successive `off' - points forces the rasterizer to create, during rendering, an - `on' point amidst them, at their exact middle. This greatly - facilitates the definition of successive Bézier arcs. - - The parametric form of a second-order Bézier curve is: - - P(t) = (1-t)^2*P1 + 2*t*(1-t)*P2 + t^2*P3 - - (P1 and P3 are the end points, P2 the control point.) - - The parametric form of a third-order Bézier curve is: - - P(t) = (1-t)^3*P1 + 3*t*(1-t)^2*P2 + 3*t^2*(1-t)*P3 + t^3*P4 - - (P1 and P4 are the end points, P2 and P3 the control points.) - - For both formulae, t is a real number in the range [0..1]. - - Note that the rasterizer does not use these formulae directly. - They exhibit, however, one very useful property of Bézier arcs: - Each point of the curve is a weighted average of the control - points. - - As all weights are positive and always sum up to 1, whatever the - value of t, each arc point lies within the triangle (polygon) - defined by the arc's three (four) control points. - - In the following, only second-order curves are discussed since - rasterization of third-order curves is completely identical. - - Here some samples for second-order curves. - - - * # on curve - * off curve - __---__ - #-__ _-- -_ - --__ _- - - --__ # \ - --__ # - -# - Two `on' points - Two `on' points and one `off' point - between them - - * - # __ Two `on' points with two `off' - \ - - points between them. The point - \ / \ marked `0' is the middle of the - - 0 \ `off' points, and is a `virtual - -_ _- # on' point where the curve passes. - -- It does not appear in the point - * list. - - -2. Profiles and Spans ---------------------- - - The following is a basic explanation of the _kind_ of computations - made by the rasterizer to build a bitmap from a vector - representation. Note that the actual implementation is slightly - different, due to performance tuning and other factors. - - However, the following ideas remain in the same category, and are - more convenient to understand. - - - a. Sweeping the Shape - - The best way to fill a shape is to decompose it into a number of - simple horizontal segments, then turn them on in the target - bitmap. These segments are called `spans'. - - __---__ - _-- -_ - _- - - - \ - / \ - / \ - | \ - - __---__ Example: filling a shape - _----------_ with spans. - _-------------- - ----------------\ - /-----------------\ This is typically done from the top - / \ to the bottom of the shape, in a - | | \ movement called a `sweep'. - V - - __---__ - _----------_ - _-------------- - ----------------\ - /-----------------\ - /-------------------\ - |---------------------\ - - - In order to draw a span, the rasterizer must compute its - coordinates, which are simply the x coordinates of the shape's - contours, taken on the y scanlines. - - - /---/ |---| Note that there are usually - /---/ |---| several spans per scanline. - | /---/ |---| - | /---/_______|---| When rendering this shape to the - V /----------------| current scanline y, we must - /-----------------| compute the x values of the - a /----| |---| points a, b, c, and d. - - - - * * - - - - * * - - y - - / / b c| |d - - - /---/ |---| - /---/ |---| And then turn on the spans a-b - /---/ |---| and c-d. - /---/_______|---| - /----------------| - /-----------------| - a /----| |---| - - - - ####### - - - - ##### - - y - - / / b c| |d - - - b. Decomposing Outlines into Profiles - - For each scanline during the sweep, we need the following - information: - - o The number of spans on the current scanline, given by the - number of shape points intersecting the scanline (these are - the points a, b, c, and d in the above example). - - o The x coordinates of these points. - - x coordinates are computed before the sweep, in a phase called - `decomposition' which converts the glyph into *profiles*. - - Put it simply, a `profile' is a contour's portion that can only - be either ascending or descending, i.e., it is monotonic in the - vertical direction (we also say y-monotonic). There is no such - thing as a horizontal profile, as we shall see. - - Here are a few examples: - - - this square - 1 2 - ---->---- is made of two - | | | | - | | profiles | | - ^ v ^ + v - | | | | - | | | | - ----<---- - - up down - - - this triangle - - P2 1 2 - - |\ is made of two | \ - ^ | \ \ | \ - | | \ \ profiles | \ | - | | \ v ^ | \ | - | \ | | + \ v - | \ | | \ - P1 ---___ \ ---___ \ - ---_\ ---_ \ - <--__ P3 up down - - - - A more general contour can be made of more than two profiles: - - __ ^ - / | / ___ / | - / | / | / | / | - | | / / => | v / / - | | | | | | ^ | - ^ | |___| | | ^ + | + | + v - | | | v | | - | | | up | - |___________| | down | - - <-- up down - - - Successive profiles are always joined by horizontal segments - that are not part of the profiles themselves. - - For the rasterizer, a profile is simply an *array* that - associates one horizontal *pixel* coordinate to each bitmap - *scanline* crossed by the contour's section containing the - profile. Note that profiles are *oriented* up or down along the - glyph's original flow orientation. - - In other graphics libraries, profiles are also called `edges' or - `edgelists'. - - - c. The Render Pool - - FreeType has been designed to be able to run well on _very_ - light systems, including embedded systems with very few memory. - - A render pool will be allocated once; the rasterizer uses this - pool for all its needs by managing this memory directly in it. - The algorithms that are used for profile computation make it - possible to use the pool as a simple growing heap. This means - that this memory management is actually quite easy and faster - than any kind of malloc()/free() combination. - - Moreover, we'll see later that the rasterizer is able, when - dealing with profiles too large and numerous to lie all at once - in the render pool, to immediately decompose recursively the - rendering process into independent sub-tasks, each taking less - memory to be performed (see `sub-banding' below). - - The render pool doesn't need to be large. A 4KByte pool is - enough for nearly all renditions, though nearly 100% slower than - a more comfortable 16KByte or 32KByte pool (that was tested with - complex glyphs at sizes over 500 pixels). - - - d. Computing Profiles Extents - - Remember that a profile is an array, associating a _scanline_ to - the x pixel coordinate of its intersection with a contour. - - Though it's not exactly how the FreeType rasterizer works, it is - convenient to think that we need a profile's height before - allocating it in the pool and computing its coordinates. - - The profile's height is the number of scanlines crossed by the - y-monotonic section of a contour. We thus need to compute these - sections from the vectorial description. In order to do that, - we are obliged to compute all (local and global) y extrema of - the glyph (minima and maxima). - - - P2 For instance, this triangle has only - two y-extrema, which are simply - |\ - | \ P2.y as a vertical maximum - | \ P3.y as a vertical minimum - | \ - | \ P1.y is not a vertical extremum (though - | \ it is a horizontal minimum, which we - P1 ---___ \ don't need). - ---_\ - P3 - - - Note that the extrema are expressed in pixel units, not in - scanlines. The triangle's height is certainly (P3.y-P2.y+1) - pixel units, but its profiles' heights are computed in - scanlines. The exact conversion is simple: - - - min scanline = FLOOR ( min y ) - - max scanline = CEILING( max y ) - - A problem arises with Bézier Arcs. While a segment is always - necessarily y-monotonic (i.e., flat, ascending, or descending), - which makes extrema computations easy, the ascent of an arc can - vary between its control points. - - - P2 - * - # on curve - * off curve - __-x--_ - _-- -_ - P1 _- - A non y-monotonic Bézier arc. - # \ - - The arc goes from P1 to P3. - \ - \ P3 - # - - - We first need to be able to easily detect non-monotonic arcs, - according to their control points. I will state here, without - proof, that the monotony condition can be expressed as: - - P1.y <= P2.y <= P3.y for an ever-ascending arc - - P1.y >= P2.y >= P3.y for an ever-descending arc - - with the special case of - - P1.y = P2.y = P3.y where the arc is said to be `flat'. - - As you can see, these conditions can be very easily tested. - They are, however, extremely important, as any arc that does not - satisfy them necessarily contains an extremum. - - Note also that a monotonic arc can contain an extremum too, - which is then one of its `on' points: - - - P1 P2 - #---__ * P1P2P3 is ever-descending, but P1 - -_ is an y-extremum. - - - ---_ \ - -> \ - \ P3 - # - - - Let's go back to our previous example: - - - P2 - * - # on curve - * off curve - __-x--_ - _-- -_ - P1 _- - A non-y-monotonic Bézier arc. - # \ - - Here we have - \ P2.y >= P1.y && - \ P3 P2.y >= P3.y (!) - # - - - We need to compute the vertical maximum of this arc to be able - to compute a profile's height (the point marked by an `x'). The - arc's equation indicates that a direct computation is possible, - but we rely on a different technique, which use will become - apparent soon. - - Bézier arcs have the special property of being very easily - decomposed into two sub-arcs, which are themselves Bézier arcs. - Moreover, it is easy to prove that there is at most one vertical - extremum on each Bézier arc (for second-degree curves; similar - conditions can be found for third-order arcs). - - For instance, the following arc P1P2P3 can be decomposed into - two sub-arcs Q1Q2Q3 and R1R2R3: - - - P2 - * - # on curve - * off curve - - - original Bézier arc P1P2P3. - __---__ - _-- --_ - _- -_ - - - - / \ - / \ - # # - P1 P3 - - - - P2 - * - - - - Q3 Decomposed into two subarcs - Q2 R2 Q1Q2Q3 and R1R2R3 - * __-#-__ * - _-- --_ - _- R1 -_ Q1 = P1 R3 = P3 - - - Q2 = (P1+P2)/2 R2 = (P2+P3)/2 - / \ - / \ Q3 = R1 = (Q2+R2)/2 - # # - Q1 R3 Note that Q2, R2, and Q3=R1 - are on a single line which is - tangent to the curve. - - - We have then decomposed a non-y-monotonic Bézier curve into two - smaller sub-arcs. Note that in the above drawing, both sub-arcs - are monotonic, and that the extremum is then Q3=R1. However, in - a more general case, only one sub-arc is guaranteed to be - monotonic. Getting back to our former example: - - - Q2 - * - - __-x--_ R1 - _-- #_ - Q1 _- Q3 - R2 - # \ * - - - \ - \ R3 - # - - - Here, we see that, though Q1Q2Q3 is still non-monotonic, R1R2R3 - is ever descending: We thus know that it doesn't contain the - extremum. We can then re-subdivide Q1Q2Q3 into two sub-arcs and - go on recursively, stopping when we encounter two monotonic - subarcs, or when the subarcs become simply too small. - - We will finally find the vertical extremum. Note that the - iterative process of finding an extremum is called `flattening'. - - - e. Computing Profiles Coordinates - - Once we have the height of each profile, we are able to allocate - it in the render pool. The next task is to compute coordinates - for each scanline. - - In the case of segments, the computation is straightforward, - using the Euclidean algorithm (also known as Bresenham). - However, for Bézier arcs, the job is a little more complicated. - - We assume that all Béziers that are part of a profile are the - result of flattening the curve, which means that they are all - y-monotonic (ascending or descending, and never flat). We now - have to compute the intersections of arcs with the profile's - scanlines. One way is to use a similar scheme to flattening - called `stepping'. - - - Consider this arc, going from P1 to - --------------------- P3. Suppose that we need to - compute its intersections with the - drawn scanlines. As already - --------------------- mentioned this can be done - directly, but the involved - * P2 _---# P3 algorithm is far too slow. - ------------- _-- -- - _- - _/ Instead, it is still possible to - ---------/----------- use the decomposition property in - / the same recursive way, i.e., - | subdivide the arc into subarcs - ------|-------------- until these get too small to cross - | more than one scanline! - | - -----|--------------- This is very easily done using a - | rasterizer-managed stack of - | subarcs. - # P1 - - - f. Sweeping and Sorting the Spans - - Once all our profiles have been computed, we begin the sweep to - build (and fill) the spans. - - As both the TrueType and Type 1 specifications use the winding - fill rule (but with opposite directions), we place, on each - scanline, the present profiles in two separate lists. - - One list, called the `left' one, only contains ascending - profiles, while the other `right' list contains the descending - profiles. - - As each glyph is made of closed curves, a simple geometric - property ensures that the two lists contain the same number of - elements. - - Creating spans is thus straightforward: - - 1. We sort each list in increasing horizontal order. - - 2. We pair each value of the left list with its corresponding - value in the right list. - - - / / | | For example, we have here - / / | | four profiles. Two of - >/ / | | | them are ascending (1 & - 1// / ^ | | | 2 3), while the two others - // // 3| | | v are descending (2 & 4). - / //4 | | | On the given scanline, - a / /< | | the left list is (1,3), - - - - *-----* - - - - *---* - - y - and the right one is - / / b c| |d (4,2) (sorted). - - There are then two spans, joining - 1 to 4 (i.e. a-b) and 3 to 2 - (i.e. c-d)! - - - Sorting doesn't necessarily take much time, as in 99 cases out - of 100, the lists' order is kept from one scanline to the next. - We can thus implement it with two simple singly-linked lists, - sorted by a classic bubble-sort, which takes a minimum amount of - time when the lists are already sorted. - - A previous version of the rasterizer used more elaborate - structures, like arrays to perform `faster' sorting. It turned - out that this old scheme is not faster than the one described - above. - - Once the spans have been `created', we can simply draw them in - the target bitmap. - ------------------------------------------------------------------------- - -Copyright (C) 2003-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute this -file you indicate that you have read the license and understand and -accept it fully. - - ---- end of raster.txt --- - -Local Variables: -coding: utf-8 -End: diff --git a/lib/libesp32_lvgl/freetype/docs/reference/404.html b/lib/libesp32_lvgl/freetype/docs/reference/404.html deleted file mode 100644 index 1fb642171..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/404.html +++ /dev/null @@ -1,1036 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - -
-
- -

404 - Not found

- - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/font-awesome.css b/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/font-awesome.css deleted file mode 100644 index b476b53e3..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/font-awesome.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url("specimen/FontAwesome.woff2") format("woff2"),url("specimen/FontAwesome.woff") format("woff"),url("specimen/FontAwesome.ttf") format("truetype")}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);transform:scale(1,-1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/material-icons.css b/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/material-icons.css deleted file mode 100644 index d23d365ed..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/material-icons.css +++ /dev/null @@ -1,13 +0,0 @@ -/*! - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy - * of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE - * DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - * SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND - * LIMITATIONS UNDER THE LICENSE. - */@font-face{font-family:"Material Icons";font-style:normal;font-weight:400;src:local("Material Icons"),local("MaterialIcons-Regular"),url("specimen/MaterialIcons-Regular.woff2") format("woff2"),url("specimen/MaterialIcons-Regular.woff") format("woff"),url("specimen/MaterialIcons-Regular.ttf") format("truetype")} \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/FontAwesome.ttf b/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/FontAwesome.ttf deleted file mode 100644 index 35acda2fa1196aad98c2adf4378a7611dd713aa3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 165548 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 z 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 d0mRO}xo^G_%I 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 SdSQM28?+M|D(2r_;{O0|uQ74} diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/FontAwesome.woff2 b/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/FontAwesome.woff2 deleted file mode 100644 index 4d13fc60404b91e398a37200c4a77b645cfd9586..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77160 zcmV(81_!itTT%&fM`8Do zgetlXfhX-f>pHa>CezJ5a+CKJB5E?t-D3Q@I zv;Az_{%F*wqQWVk+*x^)@=9sx>ldws&U_`?fwx|)6i0%hGq@6No|Wjj+Lhc2#LbXI zik@&>S#lthOy5xS4viawbfqcF5t#22r#4c;ULsQqOn&iMQrAORQWXh`G=YxhM*4YN zTfgWxZlU6?d>wP(yNq!jqfNVxB}>Ww7cSen4lE1$g!lMN&~*PN_7ITCO&u%|6=U~^ zD`NV@*N5j%{d4(V*d&F9*Lp4o^=-wV4E$&&XJX#);dbqZ^8pUYCyEa?qdKs=!}D|N zZKGn0G1#bWFe1l-8nC}AR*a~P9;0KUBrGsNR8Um3F%kp&^sGD!?K|!B(qItgwkPpO z4nOg8&Z#<)4^Bj%sQjrANfD$Zj098^i(7$$Vl;{o&HR7r?C&hE&b-&}y`y4mHj%mu zNlfW!ecOyC;56fuZ7e6t7R&P^z1O9)e^Pe=qGENxwk%7Q3&sYU;&zJz+X!u6Ex^F$ zTu6(Z`;JIR{;Knn>IcTcKbV%&ZSxB`P>8MADLLm#sD>oQy@;IWvGh3j=*Qa5&VIQ& z#BvplZofSw5gN50lul%1ZW|#duBPzgJG1nxIGMaB*-obI9wC1%7zRoi%C^%k;Mn?+ z?pUuq3@j1^4v?E3B49cgqW>EY2?-#3jqje^;JgycOCcwp0HG~LNR*rji6bO_n_6Fl zxt$OawF6EyR#iAg$gdotjwKXO)cf75+S~gE2n>cpa0mh<1W_5Hw7c36opP+~qRPFS z?z(HcYuX#9GugKj(K=EQB_0sAfiipahu*36k{xIzyD2!y5%vK1@c|DQ3Q0^$kT!Po zBklXM?*0ZWJJ6;!hoDZHGR|mrw+{{o{_lUy{_6}+Pm!l|BNl}Q;&@bv@2Wy(0-c_O zab6Z9oUWgiKYRW)Vv0%P;3X|rT9E6xVx&Q%6AWJDG0oX-H5vJ?>5A8;PEnm%C;H~y z%@URb{E<@x+!!CGA#@@j24G?{>Gvg*2lVeVHM;^7(Pnl#tDV)(Y|gCiIh;CbXJ$WV za+~#V|9GDufDe2U{2(L>iu$ z&FbBmZ9gV+TlVF2nNyNeYL2HloUh~eKdpS)>J9Pm#Xd(4%myqFVno%qUa9n|Ua803 z8#-)?GmgDZL7HHzH4B_FHnRat`EXP62|?edFIDRb!q%9yytA|?Ib5`-)rNGqg%GbH z-}d(Uw;KH$fouQgEh;fvK+gfZPMGsl{cktu>gD1?zL z`z7_05U{qkjReFC1qI#x+jpODe!iG=?eIufIBbyAS`i6yq~pK;J!P{R?B6jf<_85Y z$&N8sKi05v?h+0-IZ#Z-(g8koZ#f{v7%?Dp!%F^s91LTw|BvSLb7Oj@878i9HK*kSp)6{%ZXlv-PQ)RD zE`x4f_xM$H9{@mn{1`uWwLbR;xgELO9FcMuRbkvnQXmT&j}ZE~*Z9?u0F(1c4Md6G z%ZpLJy?$`%3V_^=J3F{;`T31Z7#Ad=bomK731~(`S)uLTR8OErP908ueHZaDB4D$q z{GZri&j-sW%|A#W5to*SAH-ai&E<86{%v3LDwPh%=3Mm7wrS#iOV1$&8oKgshx_jMlowl4ED4$f#L1!t6C1g9p~=ODPt z5-F*yQZ*RmNQ`~4r~k{Ouxs3@+Z>Q5N}1kIzW_;y+Y`2(U+=Sj1(9)2Vkg!}$DaT~ zSw&5w0~|KUc7%a7st`^}4doR9Pl!$j8b%9FcqlQFIssg|->XC5YmQ@}VmJj+^a&GW z;TT&?6ewkE94j()E$+}^)|h0Xjx{@?P9)U!BBDsDj}WU31 zAtcV{=d|bI-bs8=m>_-=CKKcXWW_GX0~^$^=>jcb2lM)283`*Z!V{7?x-M-}_~|s` zV|lNhxg(2J)xt(s?g(|g4crMAX)o}cuastffHd9kY=i3#SX1;l!-O06F-4v5y)!_N z{n~32h};!G7bhd5ytZSkz1eQ+sUW)X74K7DJFF%9?n#Q!!7ID?F7r$p*h2z%vFq+0 z9=`hOhOu`E+Rawmf`Ea#sNtl*!}&#cW`0Ouz3DI?ydh+i=s;0>PiQfT7Zu*A>rw!Z2oWMZdTlLANQLT4}czIhYZic*axDrD;QpTldic#?)QnYZQ#V&@GPdWKu$ce zkR96D(D?F+uOEL7E{&8{@#anN+7VOiE7M#=o-3l-Qlfm(Hnj`lCvjX<;N1eImGc}P zIfq1q23S0QB<*mCfZhipyXl3dlKdo_(zgrVEctLByL0)aRMXBH-Ttp)yZ_WqYe|tF zU*@4;)#eID=!hTcSCgMs|CA-!(RT=~eyOCyMAVSk!pq$%^Rswq@*cQ(TXI^ehX9#d zQzf)Vo7@<4U`9OSg`E*=es@n8G*SbT@I9!qVekl|qYka=BE@A6$s=C?(x-c+DlyNW} z6eaQe@Drh#XmE?Ex(!VKoZcdgD?X0w=CviN3tmmjikMECbJNHMagMY-l@hQIzV7AZ zriQRf5j1k=Eh_KlCFt5{BiAK6a8T){lxWsNJ@?M~+S(158s#PwDXC&%gvLuu_&~q; zp5%18A)_>(Gy@` zHu}fy7?5gdqUqRaZ9G+VYFVjT`f3hBTtJLx%QHo4W^k7Hn4dbj+U@EPSKG&~pSs!K zvyPmU&Tyr~vom3Dulo^!F^FVgi})a%1Gn9)rTvJRN`lw2KOkz(aW}5MO~dBSW@edL zwPwp4)N=wJup1;S7@U)OkZj2gQGo~o4#o=@iYEeNjFZoLvW2r$?(LKzQYnI52$jlzP&K3-Fs?@ z8TYz{a*Ip6o|)y)qHif|*~IjRGj3tOR55>Cr^87ZMJVZQz4x-c--DZz!bJ3J`mBFt zv$MzMB*TT@cUYc?%vG%XC_t5juJ=v#VIpp<4lLvW$%%|VH?JfU3&D=q@FkudiARUh(d2N+ zWLd~2X5t4S?fb`JHk6Khs0b;)4m))>Bf>MuG>~md#IxJ@3UBxJiBI@&t;m6*b~tLF z>Y4m_C`-#PTHIv21B#D$$;E^HZ8uiYUtFhV*G%O%3~-xR^LiE@?1e}-zAdW`mbEM> zF-u5dt!0p?EOIRw9HXESaG^}g@5b$*Gd<>1m;%N!sdSMt*}PbmYdWd4wf_iOfHlC+ za|MYGa1MylQ*%_SxCI*3>pCu7wYNkflt8fcEw)9s%#j8m5R?-^jqs5&y2-XJ@J1PZ zvCEQxGD63Ll8sRsnbjBI1u1mJ!>4@OBQ%73++6qLsDSXuV7F#t5G=NzBh&|HiRm#q z*)7%le!&>OD#^0421Im4)tJOE2i~}o^A-DsEaeX+t0KZ z{sQInfSneVRDtp{f^<>g*rTZi2sAuCI!Z9Zh$ZFSky>G5VCcOA>UPbn{DxunR4-Zq z0{Rr3Vcwm`(344N37c0jkQV&${exerkPtp8!}^!LNFtPq`QzzulIshDd^c?rMzvmA z&&_^jixC$vO7ZGm0Le*_7u+*exgqHorQCbdJY~!;JgCi-!q5HtGLD2^A9dP#_`PVfh~Qf+*{6POoKUi6l2P%*Hl&QKAyfLqkaIKd`D8JY1@={Zhq*1zZjQU5-VVG9EdQhh(N}S^W*!YLJe?QZ~`l?e_yw z5+Rt%0P61dAXbLEnF=K$2o+w?V3$raPx6eS5Bi3KtXuINb~@n7ggV*iUfP^;*T3fx zK(YWg|IErMMW^{br`nI~*hvLG+;Qa(JTE9Xz2mD|`K zWkMsBLSxbz*}wwmYD`=a5~IW|zFKINTi5zYJdLXS5AlQ;aj16QewJ%pn@7XW)l@{k zKU1m8+14)_#x2y>CEb#Vl-cMv42b@BrfGab7RyPY#BuR=W2k^v0h<(f44SbZ&kQd& z1c7+0f=Eva?9UId@{fgyyLhy>XLZ>Hs_gVQ>JLK39^$?US5+# zF8FwgP0>wLKjyriCrA1t{C?ppovgaV>1c~smv@h!4uR$(`2`$DeE7c~B> zpO)wsEU7ZQ#)-uJ6()96NKJ8Y@H7-Z0#aPGy|SvlSYbSo*fbFCmK;D$X{<=pL|?w> z37bU`XR6OqiFvV2n$yv2RQ}kYO5LsvtCo2WW6I7VnMg|XEFd+Y{o1b`B?Ku6B<2+= z&U7;n*3GsPjMqSY02HvKv_gCJS?}VwnX)lP$9Q?8>7cln_TCYaRXg*#;^hb%1uH+IT+qbi5QUIEkAPwUL- zZcK{joDF?6iF-BK80ny(qch>Bj2#sVh;E9olq4i9E2BhC2h@ZuNbOcWnAb?Aj+ol{ zPjg%dw*~)|Ezvu`S2h4n_?1nG-8izHMroCi)H}Y7r8gOC^D?nEB?8ux%nux4T`W2w zjmomxy+te?pWb^_g#G~wZee%3vH68gXQ75Jt@23+IdVE`poA6wl8hR#JV_HpwK4Eu zBw$Qpa>tT{f!Cet&Rr4Zc;X#7JyIEVCMr=i=zs(;dVe1C%lLUbh~NS0gJ4a3_SBi0 zWKV|KrDg~RR0H=-#?#LMUi65trDJ==U20Be7 z%Xwpj z8rGRuVi>6*eIn2 z4sdTqnx|BWhY_zMYaCA7zUpjza))jPvt-vupa&k7+<6n*ist$5`NN|BwO~KBX%LYryjwYCD`L@BOz&Y#&6yLk zrl09#3<5$~a4xgYhziDTTr}+GvxUZ_irgNJWb6?^#5mb!Oz(fO^4&7G%H z5^GS_GXIRAC_Q6#bn~Jjo?A1S$rmQJt!U~*P6dbvJ-70Rj*C#qoAg1nM--Cz!Y317 z=u#u7#!Wgd*X$9WGk^)j?$&fleixkNGkSM;Ai$K^JD4}R=>kur91A#{$yq51$wX5{ z_^yQCFMy;I)XX=RX%FBGjUjh=$~M62v?QPtjW|Ux>QrIgjQe~*2*&>nXZq^b5AiNL zZOI)6wC_3KIl*(?NODXbHzum22a=JFGaEv41mKQ*TW=5nCK7LT+EZuu)vXw=D|?|q zMZe$WYg*z7q#{n@ie%~;HG`r$nwUvewW8XJl|HLR?P9D;g~!gQW+^ITmZnEFJoC&$ zpqK!kl`d!W6#u8;k_s8NrGXb9K``UKExyy)qZX#Ac7FthR3Nwo1`lL3ODL!o z#aVG+vZ|XXb=~EAEWJ7~DkOX|><)vPi!TI8y2~t+U`4!!=-3qTcu*UzvmX| zU;vxoFY7w$fXLF*)+alS*@;#LhY>_6%d`y63v$W)kPx*5f^bYS(x#$=iQiEsSbWTj#TRZs?$7t8|iN~L%c(PyNt zN>cc8olk|i&vOa$9mc_tq1qTUO?Q~7+#U@N=prKaG!!!T;ppICO~e}UM7l3dA&J#? zf-}{*xAKAEE{qjsE0aKYPnTB6aq63DUe`n4s;NtDuJ@l2EaI^^NCY{ITBxi%Cb)05 zg&!!x67sqr4))=f2=^B;|&U9nAtxK%O?JrH(qLN-KLYGA2ys`5Pbca_F5=9yX0 zI@KWOZ;?E|06C&Ni~*hajz+-M`jaFaJ2KXs*J`w}5c=M_?075|63ZIOft^DH#ZttH zbQl)6uo5JL99BwZ9>Hda#W}|*0Iy-0IZ%nKCgAwd#WqiGzSaX5Y^gk*)brv38S)wL zWOF?u0W-yO7LT=1Ezn{_pw#>#jSuWwImbE(F^wt}}lf1z<$?f+@!t&&enhvFSp|oAa+s9!U zHXe30?GjS`pv=ByF^BCWSWJbRy2A=eiD6-y5fj~pEXMQfgpkY{A~P+|N8}+K%cVH8 zxAHg&eBe|%Q{GUMi~=9Hw)OFF98FTLS>9sw=B0b@E4xqqW!sxF_VU+f1*fUgb*|_4 zRz3PvJ}t!oYhpH4pAwRi(5Y}*;!VBKPpDx3vfLzB=tRMJ8;%jV@j>6aqg%i<1&#b+ zk^D-3Kdxp(KRuW4k%?rmuP94I&g0b4>O%zd6?@oyO6liO1^U`$YEO(w~dfSW-)I*JFbc95RKnhH_Ueo)^V z5O<-H?_2BbD+u?V6s?hlkNW{&D{7-4R^P`fkDgL0;{mp{b)#&5Aruay{_1@GD<`i@ zS^hSgHnz=Q2J4n}WYT?K1Ba~KTmN}=+nAMVj->#wyKf}M<5@kRd1_Le5osxl7MTWO zkkpGzVMHjsSp8MXcS#7V+PhkS79{jH0@}OoIU2e8CV!dMG+M*m)+daUL`I+W-4I(& zUB!OpWEez0R`B*0QI%Jr&CRlbeRfkm!A=eXZTHE;D+5#BaqzefNU;B5|N6>RA@|Ob zujYmt7m3)_czpI-ihZS1NN z{mBusZ?O_Oo54A_*Q29z84jB*6Wst#IvTqXn1FOd0WHRQYg4!CYPDfB?VoaEw10XJ zM*G{lAl|>>gn0kjc8K>kTL8Snq(eBCBR95iHQy_>TsDaOw3GMV`td+(amo3Y-6~SVgFExhSbYQt48O)0=vGOBz@93V1J{b z%hnjMkz5Lb^ba^Q<`P+L@G)XOzkbHOO0N0Xg0Ihy$^3ajb3G!GhUm=0X6-0?ONj*> z_f3DrB8?gdNMPm0cL=p(y+ve&>N;XLt~MwFIj|UsJns<6WB+W8-IyLPg}oO15Nn;A zXX*?`q_n+^0gs7HP%P#UtYbBYu|?p@^*>8)y$gH5q(rM|2sDE3?Nr_ z6;wk|U!eBTYxBbDj4oegyx`H4PD;~E0DDx)A+w4$lWIO__?$4^47wxdhTYj)uj=EM znyJ8s%uB-ov3ip%{vp~EGl-_rGMMKEfwnp}WIi3G1!!q)Mb=!*J@7~jy3`z6D|(ulUfoM`T~yvcgH%qlR3L>cQz}3KH_#K=7el_UiNveh$%U8? z_LGuK4xOlJQHD;H94v&y2_rh?&Qj5;yNIP~_>vbFIhO?$;xT|Nf?1iDP{&TfzW|C{ zCb@Y`IIq*W&G(5WFw0|-!FC7~@WzQ;j=+kc@=CQq%FR2Z@=-e+m0g92{YkVJKEF#;crZ%nQcFJ%ER9s%lZuHyt zzJCQXZKOUpq-8^{@!U>*5UtJX?PJ5B=GmY497K(+_9#(mFzjTf_-f`njzVGrbu~ zIo%B~2+9wdNd~?$Ckbz>{gcoZ5?p1VB{W_&eWQl99s=eyg47Eg{UFjXJqPm>4W7YD z$9-*oALJ8xuo5PzsHx8)k^U}Y)`AIEyYYQx=Stt&>pC^1 z<1Ipzi|(09mqxhhS;O1DqBDH|#e6Brh?)T?##hqzUdF1q6jPRD!uP? zbWjmu@AiW4LERk~L~lO?LlBOkXS8(lwDr(C^0>rF%Uwqug_tr@MLb@WZA&whtoIbB zE8!EYJKqhOTZ^g|%QMT``HvY}F|fSBy?KOoxP^}j7bAZUs@!njJZjWwL(^eq=6+n~ z8%LxAL!~qu?!w+=bz*cNLZC~R!u8OxQEj~wJTO)h@b)gBEo@zQDyI4YXo5}-(Ea; zYM(shM=smh)qbs|w%6;$>GU<*xxL%3UDH z0vH0D^OBr9a`sG=$rh?)7@YIo7tGXb<&x^?G`z4x$kihn?Wt54!tl=`j5ks~^J>k@Dr0)P<4=`SHK z9HqZCbCIW(RVN`J;D75Pe20ytLgS&Ts0!l`bX*&cR3jPU^U~6tO^zfhGHzeRUZ*DYv5=CgnUBb27sKfkX_*_QW8g{ZJrxy%`UQ0*MHZ%`jL5C?){`F! z&C1heYOrD0xYm%Mlg`aWz|)=J6XL61(PaYmoZu*Oee#}dZ#fyd`&CdjdPpQ^urvhm z*}68VQ1kadK;l>pC^5~>n9Trx;doyON_o9|l{4Dr69cU$EWU&B<4x-^ZkyN@g+6xh zPwMoB)w72E_{3`d-x8SCuyV~Y<7PBtbGlz8b|q|+<4fOKPHB=WR`~8S-zT@E#MIz^ z=alPCn@!+HKuGW89YXG6E7SeT?x%L$Rz`6^7@OU(bxT^EXsU2P?CnJ`_xORo0LS5ZqJMxCVbRWeo-#hK z{zFi%iIA{N#Sai5nrc7MZU}T|<(}BnT?3{T;ZumX`1pI_wN=xH1(7Hxv$bO9qbFvM z=4UX|gWc*FmBdU?L8VP}WEBU@DdV#;!@A>HA=Y*PjwWDlg|GfH5>Q(U8=Ya^l!UuA z`@jrShkPR|fU*HMN(H2f3L_iHxXfRx)nrwvq&6c~8APszz?(uMOM~~;e4-k-z`+?7 zfGGlRkkAmSbZh-=1DfW@EUpy$Y!T?8>kso)AM7dJxn-C&fjmLF2(TVpFr4e2U+g#7 z+4k*TetXy?4RKO}&ah^a69N0{Pzn%X8X;zvwD}fTRfDp#XjmKaqHNo}UcvD?D4zpu zpg)quKs{n;XPMnk&6ayDlWEX8k|(r56^l4OXTtD$NJe@v5fJxV4@4v5kU@+YF81KM zB`3Ckcdb1#4>KC1$+)+jS|{?MNO*>ms=Mx+CI?BKk~GjUN$;IXX{4>cn`P*Fl-e82 z)6I{U{cqygw40B6gQ97V*DIRULB6*KLPT`CR2Q|GilRB@t|Z3gvZLw#C-?I9 zy!hb|Fjj~seB&a|1(KNJ>wxs3916gZ*He~34@x1F)sNqi(l*9MHd0)QHWXaHyE(K7 z7cKZ-J*L4?vm!Z3S1w#G4ti~Cddo)5wN>F(8-aiB*r&s{6%BN!A zfXYqSk3jA<$0DOjjri6<$##L%7TK|6qVIW0hR0*(fg#o6fLB0H$oz`;1a}}DIS=m zbyp1H(H}*@XgRD90l;D@8c^gVE|w&ON1VYZKqwZG5%G1S)>4fd>}E_8%j0} z>CWmY4@fF`)8Fw6=$}2#(#%l{FRR_s*mX%Ry$HHIkK6B%!5A!-uyP}Uc?5jE0|so# zJYf39QTYezJ;eLe`Rl1hBpc|f(m|4R>6nc&+U%5MHUVSI^MY5$rR0aBG=BCa?{*tv z8T?`Y(3M|9)vn`N-fV}=sLpm8aiki6a}XqLIP~HXQxETrC1SUhA1v?k|2gmVR&_R2s(seFN2Y%r46JqWZi{zMzO@6d9I)pcW^+TATpWS22)!K7 z{@c%I{Tj3rhq(T^vsRbu&Ze%9K%2Jx;;cHVUtnV^eewPNOqD#*TeOfPRjbx2AAHc} zt-4#2+gs(Qnd`dLr*F8*$-Dx&zg#^>Qus?OAzM6)zDVOgj)gmgIpO%m1%Wz|)Je^w zE56KO{+Rh8zqjowkH|kGk|#&d2je}T?ZiXYJha&VyO4V8#=E9bh(Tco8rT zPe-~LXJF3m-dlc?;6F}7;88&8_{fAd=8#U#frP4_L49h#jzVGc!5lN~#ic3g6~oWV zv^sIRNviD2sp=g0o*CI#Z^KCv z#FxvQ-B_rBq7Gjt0mKsW!!`BC6$k3Nbv~=i32Sh;2_&#wx~G` z(eO_m^%*b>b$6$%N#e-yrUExgrg)Xbt1_?iT*?_%W<73Jkye1Kq|hQGIg_l`b~tzn z`?hTr4-{}gX!g?+=y~FiGlIKtQ3(zuiP@z5*mQMqJp{b_?lasFliFvhEL3A?EU$@}>?(xy?0}JwQH8W)@ zgM%@G>PXH-ueM<_`@adULW)`<8U01d5R+zQxRm%!F$xyv|chrOou44}{FQ zu6YqRf~q96u+ODLO0G^H%4Fs2B8k-be>oiK3g$C0AW6*^ms%)ZC=G0PHVrTJK#p08 zLXKYE*x7xsPgH(6W4>d;@{V2knw5LvDa+k`?zu!b?IaU>6Z`Pq6UTXDmMjv=q=0+& zbV0gTGkOq6NxG|T!|+7LG~A?B1pV4nGi0U@Nzx9T^F)#<4HAstN!zTAE&*ige(75b zE&EHBUNV4MV+@np3f(yUgLS?vS?RQ1T-jfytki+QU-&E97h_7L+8iXKTrxUZSLO`W zV$?#Q?RP!b+FLOvP6MA=R(dp(9y_!AD3@k>PN&3w;8lV1W+;Df)|ucTc-JF?m*BR~ zOsPF17R8HHWkv%j8E+8z^ns8d>p9D}&pP2~Dkoz~<@M#QkC?n$ z&e?ks$b<$?W~FX=nO!(W5x+0$ryG2dx-rUj?F|2CK-5Y)v02RT)wWJ`+B%|S>gH%j ztfKJtZwjIKzq@q2O_0W5goIMejlWX#_i4d8d`{b6P$HnB{fI(9u(`CzAZ=h_p7o2O zI!*lxi_iiR31c$L#i%^U6{h{zleCsq2#-&VQv#A)oq+%)VO&84x^U<84CMIggs<|k zy=BH+=Ey;ktf{G+F3hldr`GGNcZSEmemrDYNoc|SQck^RYZ`Xo=5O44Zl=_nqJ53m z?jA^dWvppdl~<{u*c`_{q0Ag3%_vJcw7Cau9bggfCgx23cwR=Xk^w6xrQHLW>mJ6~ zoLc6EiL#W%j~X5^KVItxMGgd}D4^Y)9{5DysmOKYi5BuUui;d}nD6_L6YasFOjC}# zHczo(ZSUG->j%o24td8i_|W>9e3D++Qxe`w@T9$cDvUBrFU6PyDH+cIXb67yo5J#3 zG40794Me%jg^c&;B&HbEF_T9x&XsSefG`7I4C>qZhx=cAaV){D41BBnVE){<2L>v7 z@O+e}#wYA`9CLORgK8)rap0>`tBHC{KGDrK|BkwuzlaI=96JbeGJ_Pwi(vS%g;$GU z{Zx5S_h+a9Wo0lHhxZH-?es7(>U}TAl)Q~QXj^ng`9!-l)?P)w#v|is_sESpWZ=t+AIf!#G5rs&Syz>JIdC**R%{28T7 z3V@q>j&C4r)}lPRp4ColvW%S&W~ir4e=5v=&{fKhhgb93U!Md&2bOjoJ19Yb8HK3L zy4q61UjHC7w>>t}Ha#-tZtH%1W3Rmx2ar!UlUNLfmEdH$tN}_H)_jlNOi-NOoqi9^ zg{k`SIGQU_MC|n7T(8vT(ya@_ty9AnT&F$vRoQmT4Nc^QnjT{!Vf(8~JI_I`92Py) zsKlD7l)2VxfdNW{PJnQm=uIU-Qee^9h&$N%C=>g=hc&|xSDL-sJ+%mnhFKt;XD#Gj z2zE4q&{%)2*@^mvO4vZ|*FE@S$1}z1{Oo{4vd%e)yV|NLF_6$95=Yw_z4vQ4lC3tBMDGfINUylPM{vLdC8$PvGww3M z#7!FCN}^#}-qt^>V~yZ$FrFzti)i5lP8Wc{b)L^3ngy~Q{tIn0A4raVvcVtQ$}w_8 z{3pGv*4Hunp5VvTf00XaophUX0ZP&+jLmekkfXZY#_;M=VNVsAyL*H&%BP~bR*Q}dWg0oT^8Hb z+8?1G&z0BSPn^-$hiXOPI+G&__cnoUIy{k1=Mc@&b;oJ3rj6kk$$N!*-WU(H*D=bT zr0V|Tqw7^x$?|Od3@g!L!cOqQSF7ZW$!NRFDNm;|d2K~(*`%*Q*3~y3q@}A_QE>1T z_6D(LLad5BIEtTzyE_8L9|e!)^p^N1XG>BwZkhJX2IjpB!BjvAu5P?4wikmTJr-d# ze~F%~qM?I`uv&gYSC`RHUPM?eSZ1ec==@HA#jy~*aWwx=5(dFZKo$AuQ_>Rp!25mj zSZFWpKHMx~mgDF1I61Y+^zJP>M|=fW1(A{|-QHr~ANxVa>i9KBlioZk*_GScI>eu& z1|bw(XKH?{PY2&7|BF?JPV1t%IM>@CuK1MYhZAS<3|$8;R~lD;C|B%GHu9HNvEw0;77(X?22w1IM z%aiOB(=+-KA2<0vs~0Nfhj)MhXFr;#l`0{U>G=9ec~qi63stjc&eM9u(Mj>TmCs)n zqy~jI(kAj;bc_&x@JKEnS@BxtC^T6o>twE#!UOw>4wdD*?dko{h9uAd6M2~^-V^XtQB8iDT>SuRV5`lF@KVqR6BpM!C7IOSK==Vpw&g(pxj3)fUkzqW=b~T@qFwtEZ zW+hV>@`(tZVIO~PD)HCr*ovK<9kXxHykgqU{en1fN;#jwg4p7qn!+cTEpyI5hH}vG z>x6~8sZ_AKr9oJMqy|Y0(OfufU3-I1W($>IBOJ=s6IioUUS_%(HTTpfCmY%9#O%-* z7Wh}nGS9alcExi=;#_~8?TAqrbG4o*nahwsLFg1}QWPF4TIl>4u;pQqh|II-98+uo z(Uzi8j9bgxoMgNzDV@owyPUubP~^g*#Jxy#7^83fyfvKkIEl$Fgu-3GXv3c-G_7y!TzN53|0z0QrgQ7caCIUODsHrJxMO^Wb*kGR?`kWpC;A=J&>1(h7!{7l6brcI(kLf%V{TT2<75-6 z8&zYT427ft`=>CKA>vVv&c z>9c-_$@t1_qhpRP6z0#+ww!e6an%ezStolEC*FwaLF8jo@%>hTO&IniscS@-4Xk^{ zrtKJ5&7a4q|Ll#BJS?d+UDhcz~oPM2|KSxUs4*+p8fP(ywu!Bkt8%c6sw78 zWyNMQf4$PiP-wJBw)J zFrI&zxy$w&L>{f?;zPdE1W50pp&X*=#w>q9Fo{|y964+OygHpN!b_)=H+o!D;6hCIj zaWcvUbE@H&Wtj%YJiK-AP$vs@i<*4hd0{uunqN#iOC>hj6>gO$NE&}#blRdD+`i|#RqLfDYEs|E;WZS(Jd4JuKXL$d|7$*@si*w5&^NgZ;jfd9P&&PAfyK0 z@-#u^rMW!<3dHgDRD+nfKzz(tB&HQ<8g4F2+(~@yQiKAa_dwrJf`{u|5QPP|UW&x-B%aYvU?T(iBW85A*9V0nld}B|2ByRyeWvN&^j9@JKZ@!Qbsb8_^ zONlcJ=M0REj)N6&mU~$eu?2^f;T}P5TkRP+t4-So4XIQpAtJu020vP`T?2z@1x3Vd zvJ1qX!amg}mWG+-dq>E0of@wos@EzJey05Ent8dE>tKl|t3mre*_a~%{M0D|w-9f} zC?w+bfEz#g9_ATATsZS!`bnjtFS^eH6s zdY{~Fa>v+oy@j+DD2O^9u(yLph#W_UVr5pQccN(|L%vTj^!N}UkkH#>=UUua>^w(f zJbJADK(RUlt4b}v)x_UlVCbm>IDnyO(zDGhZ+jkL3o0&`h0 z@{No_wWBu{*EDzEFzZK`(=~~~dX2&bK`()oMNe|h|4Dlo1x#xHR(r?t-E^1H#SqLUK8XTlHbx)yx-zJV%;W zKH0>$zqd^jvt0{Zv#3t^*dDNRu~*%VWSum|q z51|7P!|^AB8yP?XE}H1sStdAo3W_XgHx(MPwWI3&GkMs-JB@+sRef+T-$|bg0qg$@ zcvks%*4}As_(r{2#p-68|I7JkSlVNUnAGeZE@BMm>Ov~4d?vr*k9=pVw`DKNYshuG z{&rknNQbtbo??Qa3K@Uo4zmWL7IK@zzE~4tS9XEc*vZt)r;Y|JJv<;-Pq|0 z%OO{|+~4Q~2Y_nK%zLWsoY`7QB;R_zdr#gJaIYRa=XjEGnV2kj4}%4b7WKja_3cjMco6HoZV~yG2pj)qF`7L zVJc{QADVF*X?0cOT;3WMsv=DOy3n*h`BatGSlLolhrUJwXZBrl<;2|=MZwM#05d?$ zzq2)~RxsboSgg_(FUIe6>$S#fx_X73LiM~S2ib$bO1gL%8=}nT-y8|%NqY0{0f5ps z`ihbDjgrz?{)Wz#?J;z;zqWa=h_}v~Uwwh0e6)CN<68v4cmhg&di-qj$o@o|*H)MN zhH~@QV{>G4ak_TpTan|pCJ~N~V4rVQwtu+3Z0kPcpe!WQvt4J6;&li^~|lB(=48NU`r2 z$5ptqRbX95wQEDI>V|^m?Dw++2AZ+`PnhjdQ-wp7;&+p8j}{AOe&HW^M>tULnR|Ok zuD>oM_4^m!6*k2o77=|29Aq>saUVY9U>1M`Y;3hvO+r$Wxlm;ShBD?sjWJS$x#CFt zalGMd2ttrizow=n(pRG;iN|8%w`f9%viT0fnpPY@C_nri9kzc)_XwUrm{EN^M?~~8 z9KsqptPf>CkY>~*A_I*VIO4tc$c;w&m!_F!^Xs=YV7%&ksTIJ23`_L&b#~lbrq5XC zwJVsP@(gweY7>RvwgO%>J>JhSGf$I)DB$V(zS=M?Nr#PQOVRaGpb^N&Z?Kz!PpG`j zY2z{z2Er-Wh6fb0NAky>3RpbR633Wj$86{78f~M+Q_WnU=k|wC%-kU%`fqsdB*QBV z7l{ai1U_VJ?Zx0LjOU$ViklGOPDxDz7Q{@2g^ zTzoYk-lO!p*rq7Q`jeoGlGu3*@oJ@Ulo@R(vh4SO=F>b}N0A8?-ZIw*>G5P#o*45` zoR=`K^ynmrr?zg-4U}@Yt^%@cxh{CkoMm5 zoPXV&&8X3vA}~MBUNYsjSVrfKEPHdn=5k+U5I|P0`W2GF@sfF;XNZy%{u&bu&Q8i- z=V|l^j+gs)0&%@NSlY-OMMQ(3T%oOEF&Z96qmn4Lq!5jYQghe9lB!h2%iZ)m8(i9n zQU3Xn0y1<|34=SAp9^4;)!bVf2iYvJ>OpJ1qf4XeVnl2s<6=0?EM1vtT&$b1{(Ngg ziP`1QcuaAAau(eR)Xs)Je2aR_jJpp)irmA=VV~$?#P>g8-w^PChhYw9GrTaM=nm53 zC<$un+#*J`K`QNg-=oW9v|YuSD_BV8lzPB(|Jl~}3*`%1sRC2!;!GV6;0|>541kSrttz3llsEV32psoEb>y#`{&)#REmCm={YP3 zkS~Izr@rF*wXZJjgaYCHsz`u-g(1b@h09>l*8)ZPyAQk=cp3W?_!Lk1+m;~P8*K!4 z0ZFiI>Zi2PkyUz~diHB7y()Zd<(bL?Dhn<@{q^^L<@~-4$mL_}__@FWXmHolKV{8X zmtDCkNPNtjG0*go`N(BIsa87)*ry2&G7*|kQC5h&l5AHtZ5%aE5u`I4Cj;AF{i3TJ zcoP!fEU41C8?#|4RP34arDaw7u5&RktJ~QYgl2R(7ZZT|fW!VA{8YQHd(t7WicG+# z(LnD{Opce;bjQ6R$qxFtUgJz5bgkxTAoiq|Uby)>LlXGRQts9Xg1wpWOPu`;5H@|AnueaE;&Yr*p!z}53qVrc-7QXPLS&p48sckL6*~l23wsvl+#eZ@qD?{k}E!>@*~j(GCw3uZe+c6>cFUF(NmvF zC7+C~{t{)_o_?MERiAN})$tgb3cTL4+0ux5*#%N=;LyJ;H-rU?%dzP961Dfy#l=2g z7sV9@3e7L;bw(0rhldkSXDLwUl}hx5Tq#%^zXWR_Rz@Q6=mT7I_Se|Ta?%1L^4NDp zU9)or6R3XU9B02{=iu1H`}AmFc}s^F;7ukNi;7i&ih z)Bjxo@;ow7%fz+n`CL9A&@#?$i4;Th0(zq zq4@P%1npcbS*gTbO0&BD8R^ft-;ju`#KWw9ySA545D}A}9Ns}CKAj7;@tFi&)#MX0 zP?>BsaJb-4lf%)F2=;+n%78RaK%c^)5i9`50Me|Ahl4GHEE$u}8Xyn}nlhj}i8BndXM!{V9@ULn(5BO=r$<`sYbb4v3~;t~tLvr= za%ox-M$LVSxQl5z$uH~snh+g~V|q}Z#dTK2Q8`78(k3U&FYF74k#^;r@~!y%rO(}G_EA+zTka?F#8vv(l>5w`m)5p>zc?}JARmg2a;0vX@8X)$ zxrGwVeI2^a3I#e75dbX2(7D|AHX2wrq@S+utY)mi8fBX&1q}yIO&OsTGH`r?G}-iU zHU*Hj0#KEWC4DbARw|3e#iG>jy*FKP&EG4~32 zmoC^Zo2~LJm+tb7QgYY%8DF{mc~wIt63q`c`uX!V5sy>UWxeE81)SF@eNm%^c75VZ*KB>B;`2 z;ddS|3p!af%~7->3c!l$pDPw;A`&Gk9-}fE0qJzh^_pOfN2QS6w51KeW;$q2Gwc>K z#ui=$hJHLy5Ccv6zghsx1S)re`Nq%I(vb2=FrXH2AtGRbP*dgt3ry$(6*dbBHmpzF z)DwFHCb+zC5sVNNXL5^sPFcLNv>-LCj}*in zB%n`#2xa~aM{dQ&bC}^Iii}(a?`ivB<3!fj+0pGkwBNo3JMsYP=y%-A>orw^cxry` zw9KZ~+_i?Pr}WmHpFW3q)2ZL~;3*u^Zz*gl-tLh|@GTvdJNwA=0|P7Be32N^D_f*juK7AWtCz#4>hE>(_0DNNN*N>a1aA&IDhdw9bkWyB#<|~n11hB zccL`+tIBq9mMF%!i3+ z7PVFGOz=o-eeG5ewfKU|_u7UZRra6A9V$XI{cMyD z6jD%T>j}|h1Ft6zzWU8PYR1716h*Dx5hTjS2M1bZcwGy(MXMlwbkF7HBmQnTJ*tKi<85{MeCN8$Q(z-qr#~Oz!UG+tI~i0b9dl{Z0yvB||xj zSfxDrQSI$sY5BX_?~8CORUpWb6c-C0RKtn(ev$1}t}+)WCwF|-FPf`DGZX;A>ao}8 z=Sm1HyL1Zb9^CP)S7%I4B=R6z$X4V04t(CenRdWvFj$>f{tW5tn$OTY+iH$z=lPtr z8Hs8z(9U~uOipdHt>#->Odj?#Q?Vpj2!j##rSZy$6MhZfhoyg#kxQPix~=gT-67Rc zMJU*dnv;ve*-$zrf0y}tug1L7tTc1QlZk~_Ofx}@Hic3R5ovZU6*mP_5IUbsu`{i( zWd@q@?zuf)s*8!Q8KT9eG|RKUGzP*?L*MCAe%z3Zg-%N_D`O-kGnP%U{MPApJUXQ! z6v^u>OgO2=!ar*yf>Yt8mk!+9#p4YSJoDfdZ?`D-Lm?uLxs_J(rRaWjcjl(l~; zK?+iH{>VLBM7RoSIUI4S@8WhIf6qhQZf^tPol8<4GKO~FDaOszF=U)$eMFfuYdkqW zz+DbI#5nz-fBL#YQYm=$%cDC;(`mGQd(AgAp3TY^G|!J)7Q_n--a2QRRtGJ8K)4{? zp&DP;fJ#t$7p1e0`iG5`SUZ;~VMI#JKc$bHToof&lELh9>6+(v@NK@y&Hh32(2g=( zsSVvd5#}~IYKcssUrw z(x6waKfH!3`oiD<_5Zy0<6z!{&xf)jL%o2P%Lo|7Lh768S0_TN!+x`?g3bM7;bIK{ z6Vm?g+BJTCVDQyJ)=e?_>fj3~(wvuFsXmya5;| z*x|VcAa9N&-KDBKX7XU7%%a%*bg{X~pGvPJ-}~dLNFV;?TIB!)5=)iC)QW?#9M5Y5 zz$*|;0d4KA6yD$OQZgQ-<*qUGEUuZslsAo76}LL=}fX=+YRK2vu_!3iu+bq88_~6K6d23g`7+NXELRGw=j@D~xdDR;< zSpN0LOT*?Y4Kwiy?nVFt`{lej7~*hC>vfK=u+_JN3zv-9agadwoS08RcK&%sH1PV6 z%ii8DEN!`?BSa!z%+aHV0XS@=QCjt-G4=C;tI$J~uAk^!t2A#)+^CG`?VgGcm8PJD z9h3cJL^kJWTc*5x8kyHj(HvdXR``B_E{4}Sw&@Ox#uCibFnTHl7##W;6`Dv`*DQd~ zzt1>$l zy`tr!xYPUpkWSf{f5Sj7i_}-tF$F}i2YMV^5W%qGTd++fR^~PAav?M(Rhe?D4Rhk4 zHzj$00OwBGN+>_2Zdq-K9wJl|`a_LPZF2iA1n!vKw0mMxPE?E?>|H7uedv-Kc3`Tc znERrYG3s7Oo#pO}({__iZ|+swhCx#{SD8=QiDe60DB8|K5d-C-&7B^FbZ;?Y&#M($ zNP_3Qd(pu4q<+gzfPGdS%Zu5$0B^FA6+DYRBgg%sZ>sR_zEnm;BJUd|H}5m9tk*8} zC_fdxX19`qisj~A-_rG9A@!WVvHZZlyfGzJ@APp@I_R9IsL!~3k_7ueI4AQLE3Wlc zsJ2%gb=#nVoiKlk3(I{VD^xFu?on>(6QJU35bBa=XfzR!b_H+p_jZ;uafnByQ$ZFzeFCn{3?&FTXjn(nbO86K)<>eWp)YTN2fr4;#I; zuOdnA*$U}^3y!5y|wZ%gt2Spw?1r~Xs#>Bj<$lV% zOegfQxuQPduw&@N;gU{38I`@@s_{4=;TOt_ihJyWm3kCn_5?TuUw8;s;?(fd+}bD} zSR!4{l&r*?O*VJ_ETm@WXJ(YsE6toKRI1fV8&wE&J`FACU3z^38-{PADv@nR2gSA@ zmNAJ_%^i$9yRo{v+qLC~{I@2mg%vs%mzhz6dhtl@;cB|QY#OF&{<%y6?i>x+MlAdP z!SMKxVdz<^A}37CtcJ<7rLtm5aC`Q=mo}}{tLCH*Xp`pAT@$~J5N)ar{YBC}t_#wB zlImumyV?Xsb{vY|>W4+UU`1DHZWeWT;5Z>iR$1piKQ~KW_7y9eTQawn-6dbFZFl6l zbHiG->gi2dKiqcWY@V}|IitB|q=-+-49|NU`Le1kvnM&LFB^Ro01Z@q<;)xF%I7xO z-d5{+!?gc)RT8;d;?ZPO9xPvV>Q>6_qvS=+D?%1Jfq3HKVUJlZOf-#h-B8Oh@*)wf zp>D75YFjB-bJh_xG>!EE+aSp_bLCUYHr>IiqVf!TnJ5J;iECG?hY&ZGs*@ zMqi^@Gv{UkUbjpVm1gT^CmIz%)EFjBH@8MGdxDJTl@dp%im_D4Ld4O|(=V?dX1LXQ zabx&hE=(>-5wdPx9=)X5(pRBtl-4Ni5NH~T-D9L7$ejA?u6*K(CD=bDz|dU%gf`t3 zQO3ZuZYsH%Fu(%jvnLp<87GR3j?-7JXvC@GpFR5k?!}!!NfITQtWVex=oEq$Qbdv_)@$k~&IuRwktnFF{qbwn&9`6Nb>Uc41%a?M zgG${LZ>@pdbjP58^&MamShIiV3+(fVYy{dbgx)RP)TyehuE7}!6jVYZ%RegiAp?{fle zrZ~A&f3U?pW+7v@D4I(fNcW2BgHx@`=twsqOz=~`E=0rvH0O&X{@H$A%i7trVZ2A_ z0-AHLX$VU&kiqv@&@*~q_hy|-?`nyJ1?Y7xt?`{TNyhP**=B8&I%%g8dVJT|pQ!OT)J~x!odB)G@6&^!F&Xx#i;#~kuQXG?@y9`0` z8jmoU@C*%0W|Oo=J$eg_#%Ba)iUY57W}7z`OL!oVThJ2as~-$ZUM^d+rqr!I^IFjX zWBVC5Xt}pViP5L?6Ps)lU5J|-On4|x5|JRH{|v!INPmIG^6cHduk;ZDTpT-w*`2b=}lq&|5&VzP9gpLxa=Pdj-IB)8~jZ0xqAXJQ<(_Q1Ei` z&6%0u5p%gQxx6o&7S&E2IIwkfqP;HDzf-DTa)fHDUASDWrJ7-OUX|n{3@uxM!@ zW_&@H(PqGBU3px^=npz&)a3oneUBfD$JMVB=SHsCO|dRb7o{ys+C!t{MTlnUx~#vf zb?xF@Q79BkjoXBvQfjTMxl;QQ$B)tPFSYPn%>=h~4pdKK4y21jI}=0Lw_^g0MZ1>0 zMaEQ9al_sGXftG#+bw$q{AO5i7R1BwHm9v<4_%_U+g77UVKY3f)!YDfnbb-^Sf=9X zzUTJMO~iU+Qp!wX1*0>fkuR76^az-TxMX^$BA58{Kh%H&A7|P+L|>&H(ZW!uzBj$C z!e7~-%Tr?&eZCc;mcswvsPxK}{4kIt`JFHVrJ!^ByWpEmM2C~*PgS#&h!5i+1eBY&9lSe`3@5A=D2})4dQ=Lbi7ELpiQ@aGf`O>dG~-{rIee z9&s}0(W>Ca(zF2gRl|+DEbGjMZCmj6<=#PJ)7>Vh$6hE6ad&nj>*K!(9`EXsj{E;E(NN#n zqq}mP(>xZHN;%~eYdXK62QEvGuyRNb#S zGVo+VAqX@L`QWZD3X+OWkpnnSEM~p>rxKihGE`|+4RwpLb$8_IQ< zXVLJ&lFU1%8B25DCl6kvrxKufD}x$0RaH-&sQW^h_|UfME3G87B~QCKWo*@@Dv{b_ zK&puaMu`OVV>T3LX9e_4RexXEelcc*rgptnyEP4o5c4fo4V&CB9gi5nAQvfLMDcsQ z^VG9qF&i0{BT;b8BYvnDRc3XEhGa-0g&L$J zwlZr`49qW!tK8Hd13py~UzBx+xJKWsC_4{hGpMNf*5q8{KjbHZJNA z^jbTY%}}r_Ptz%g(^#edwhcZ=ca_8*&Y? zl{cCt)2II&xO<)-uML|M;dle8ZJ`~f2E8$F(2}$CX@l``6R_kU5=z#}+)tXXCsrYe znIg9musw++6$%Z}mo$XJ_)Al|E9#NL$|hRc+nIxrC#2?vrCE*+;Lu*%7Pkduz6Aoz z=6?VG_kH4)EQP{&Cn9sBZ{MzDvB&+fAEV#BeS0nl=WFQ5$W%&MJ7#9;mhXj**J`Ir zR+6|Jyh86Q(e`S^+yNbNO|Dl=uOgcpW%Vze*S5RgyIE$L{fzW@ccMx4@;YnlkxA?5 zaW003$Fc~VWK36SZSMTIvt1ql$(QxQ$NOCkX3yfdDS|@b>U(Um*1NaC9boQ^vC3-J zexu%o-s!J9#DP10tv9j7EqX!0@7UK^!6&TF4s>Fljo2K6S5MV0n9Cm|0Q3e&Q!rA= znpX9Z$)8+E81nn+%5I`6XaO5-DT|>j8V0%P3hEr&E5R&YWX(0Rh&Q}B338(XS`fzLR;O0^i zd>Hn<8c&)sFK*C4k~U4@vH;Ce=+&!2e5nwaToqMrp`;65!)&i}-NFU5JrG-atd}08 zK?AM@KeF)*dP-jqQZ@nvt^QL%gXO>D3BQc`kD#^uZ_*#iOk;S?;n2L=z$7UxKT4FBS~l*jqV5r3fL zc?yV&`?|@ewX^2-Wh-^gXstuOJjO5YEOQBWd8of5@oLxDN$2purs%J=pL_ArjuQT~ z`pGQWzw#ySrGw631ydqhJG9;XUw&X4AwKL~`rM8aD$d$;T{udabsN{W56yK?!3~Mk z4%MMZK8T74XzxsGaW`k;61Y+_7WOR4s*$=FT3yC`ppYc2Lt3S*wviCb!H35qsum>>o?g+x^38-2Cux#N_m_E3sN z0tqF7xNdRLU5MqF$v(gd`g-)XXqjy=ke8ct%L6}x@&+Ke05ej2PWVuP&-WV7*Xz-^YdpaeNVp4 zS347URKFp(y4dzcf?Euw`K@p14Q!Q&zAE|}u&1=ZO9lazgiD9wRd%-AyvB^#t4>)o zn zTIh5Ujl*cs#>u;pQp2VJM{vf&6*oV2Nj_6aiBDkj?Gq;%?$-RYrP1murR10)yKlB$jpRoq* zU7O+1_k{A7X`)3)%S6uynj4a-7SL)p zY{A_GL;yC~rxz{!hK~Zb)WIvKeOgsCpI)x#cu%$6yq%wB#r)V&9!U5b6c7uI!s=B! zB1wDqDUsYUg#?XSz_9olF7?xcD{h2wDDc&ny!|Y+GD2sBK(aaW{CO3T&3Tvuj8CNjN6N2 zc^<8pBeum+YM(Y_a(^QMr^u1Bg5DHL?aMT55*qSP76$I$#wd9XhZgTn_04@GZH^3E znglJ&eDjmkh${UN9h6h?id^^6oQ?kIhlxNE{|n1N3fR(~3Up*`2 zijvce&z>hx^xV344M)^U?$&HBi@N=CsB!yR$aWt@D4j$@85l>8CgVft*s;SQ5ux&v zuRW5-qk1%jf{J!1qa-^6yn6Hp>aAVR%!xZca8VP7<010#C z&pr(kf!0j6UhAS}@7lX}z714Y-k-Mr2U6J$%r9TLNgk@iro>GrLVqrvwAd_Anl0%1 zNXlv{{r)9TfBC(>^h9tn+sIz+UU!XPOV+D_OXveoVLr~j@2jP1&!}hW_$mEMQ~cA} zyb|tYM@Csk%p{W)s+AS^SYU_@HzktNfMc>tk=jufPq`bxkAWgW)u9_gl_#s{wq6h} z>tG`AhC9kff1(D{|A5GBWz>?bPhM<^gF2Z}8KFMxG&N-#7Wf)HTQ?+ny{83(w0{iY zX}{%0@LVcF^bQm!$DPJOmJ9`JZ{7m9kmpTCW4yrK5Wa+krveuUd*Pv0edJrHe_c_J+3K;Y0fGo2K7-^3KpC?_WFK2zB=YrOQX#|1ZRY}N$ zsjg3wbQaq1zOBrX2Esqh)oYCB=NAGx(#X}&Tlw5RR8wig^q~--1elwg97Q}g_Zmel z?@kHWkas)hZA1u-uXWbPdM8_271IRIjYHLUr-uPBp=?(Ras7yfm^#HYOSK& z`wvMb^~2LMmRw~tZiUa+5rruoQg&l_>o4?H(nG{Q-Ana{or#-gdml%+`dImrvbG{( z7p&tb<2KF1iyEl$<3+|T(cr$3H{GD2`gSx^hn7h3?N z-7f#2g>parXHTO6Xp+A#C2Zuc{Zdc36GglYx@H|9PCaBM{&in*V!%HPSi-P^+!JO5 zI@rugFRTlbeLpC5i#EQCqt8&7BKWgRe%EPME#GG`?dVxT9A|p(!G9fnHgQW#ss8N_Q1c&3xd57=V@14Ul( z;Oq|aNiyHKuw+(mm2ptbABVYXT46HV*GPgdjvGBFxMN#vS0!oI8@L~%w_{iUf@6pe z!J}wU#&NgP={AWH8DsoS@;|-{eIIF4Xopg5(CA$r`Op>xj-ym(=xp)QE=7Xv{$V{4qbf+kT65`SQT( z!ZyvE*xJEVow#eKj@8VD4<6E)84uEj`&>;30OfqZbRZDZHBUS=J|IdC=Y78387%)% z9dc1B&9C;GL0lCl^(lD;dekR|9TQ7r*scadjrLb$X}myZdUYo;Torx0UU9+a&q+K6 zK4o6kXer21DjvD?6l{8}e?ow4KMQBv`LY4j_lk?k1Ir+oK{PaH?B{SH*qzj};=~S$xWpk*YrTFKJ~fRkm`kA6J*@ z(N}Xe3Y2Hsg` zd_4%nK)XGK!B0X5uzJQ&ykzsh$u(ATY$O1^q0w5^ggB79gS0qa&ySdKa40%KHcB;6 zSuzO;!>CpsnY9ilN0f=q%y4Dq;hn8qwyJ1qlNKKx4x-X>n%%9B&MK?4XR z6VrUXNWt|*BRA29)zaX!+%fR}Xm1 zh)0bC`jGnm?+!;tk`SQRu6~VKx=N|OR5wj=Uc%_QBZ4r2r{vhfwQ+~O1RC?#%j#l_ zFq%tNZ*=in4T>4nmTeIZUgv8d7i+Y-Eo94Z+TEXj|F2#QO7z`i_A{c#-IYcf6OTsE zROZjR+n1d=Z%+j1JTn zd+6vm8?`#Qp7VM|4Fn(8W8II^OkLUcMnV0%8i zr-c?L`(fwaopm_}=js0UIS}xkC!hfcsZ1Uc`D4(y%EXaKXp!_}&7Sgy>)}~Pk7k*v z0R*+iSy#a$v~R zeX^24%(kxlnZBzNfrHfi>tqOoyp%v43|w(75S}?G)apg?N;OE`O0+b$p?Yc&Fa4;>M((f(+qN5a0fa6{?2lCvuLHUtJ~ zs?$>|(7(8KG&DIi>SSt=D-4F6OKZ8(PI2i%r5OSRluhu66AmjYKYItpG80XMn@&o9 zR`GQZ{5deuBqL;2oG;ZZDUr_&L2EFS#)4iOjE8~wMjVvio6QBl+}v)l0*m+ix|BR6 zq7j@*t-zf3jCOGVB%GV-9-qnRuVe{8>Sv@<-AIjL3V*mP=gMK7dWVl_LqBz>zeAM?E0)b*m z(-tW@b|C-yqZl(%hEkVNw2uUR%ev%$PwfoW32O$$RZzsii+!`7Q&yF){S3^1cz<&M zQOa^}ud$yq9;5$y=a4dqMi8Wo()uUXucO%AZcab&9@l#!UG*^*LMtD{)wQJ!^~{{|qje>0#VA_7t-GV0Vt=7IO_^w2S|1KGCn=&7 zIiMqlKFliD13Y7lJK7x7ntg0O;-~v1`zg0pU=VC&Sr_guH7d{#*$<^ee(Eg@iS`F% zHA>;eTJ<4O1GTx+rl($J0Z@RWFJ@}K3xQP1SdkK<1Xw00W+4cO!<}9e@|b5YYCH+E zFWSfJrGrx^O4gG#;Z|M={+0UQpTC}7#2Ib8d!Ua7GQO-kqNNQmX*UEU0pJe@7AE4U zwf@t!j*X40k61-dQ|KSSc*Zpj9>=l0*@|=`jumLC5r}r@uU|vj7K7zem7BeOK_t37 zhCmC^0leiNW{O-pQ_NwEDVnA>L($P+o!;NhiVSBkC^Ts;Yr+#e1qvfIbcC$AnegCRn?NkwemQ9q{hZ80)DRKKV55>n@+ zrF_6xec$!x3-5M?t7hpcw?AKqOMFRL_1?t$qmqSty(Mj6DiAf?M7yNXV2p=OfuA`f zBa>sjholVH6rcqddf`ip%Fh>sbg|fg9}8rHx@*{h-8b_G>|28~r~`VU8QhR8o~FUQ zVm$X6d{aD^e%QJ#Rz-f)Y+bL?@#<8df815HKiz1(<-p~CrfcD+F|np^Vcxs=+ty|2{Ww#AoH6&% zo#cyzwgikJ)APFGIg@CG*hvi-ht@)l>k0=EIZLZ=Unl@u0cII6x44LJA^Z!4lKC?+ z9iBtCzQH?K4wgx1B&ErK=cc(pgvCHGS8NR*-4R`eCMk0^@ZhL4ck!fIkTYX0{Nqgm zXA54u6v#2s$LYCGvvG4HO>^;rGg?keO=~o~A8voFukYHJ1yE)-pw)>!Y}+;oIY8agmiMNa9*?C0;5E;h zHZt=0bU-%>p5aW6&N2xd_SY96bo}-0C)BUNVo1v5@6@~jh<6gp=2vF&@wdr}H$BYT z{4PCWcnu{5WIqkMf5GmJVYAB1Ad)%YW&d!Hr;EKvkJ70OOUUK-T=0;^+mHL5gr0C3 zEfR5KgQKbmo0CAPN#e)o^I~h<*%Y~*smuj4Wl)?JMmXI8iCS${OeonAC~;6QHNP2d z87I7@!9)1R!d8j3ifO>Ls+-yplcA1kmC*3XzXVu6ap`AXI@6oLTU$`DRye7g8L|tZ zpEjfb+C53hi6{uQV+PGfmYNmYK&cfMz2Hn@A#As71>D9s->gk`+WGpOc2;8bao>Iw z+|m*+q}t6T$4O})h=stm(t^*S)}vJOojv*?LbHPePzF;5I;L%%b*y%a&;$ig1fR%r z&(EdrJEy-Frq5agd~+-oM}-f|I^f1|NcM`aXW8ji6?K547g`8XK4#|3K%L?MWfbCz zu0Te^JT~LavfwTq1(Ui=feqFWFM%nOSdLj|`ofd%rjvvjgu(Vy^JZUHZQ6_h6WNlg9F`pn0bGzs>?3HLw0ZOK&|M5DU zPKimPl{Zeo*d(cX7TUPF^a~>+90YH4G8YBWFps2b{&?jK$gEYWx3(D1 z!<21adU``7ytCf#r&HikiojIc~8C+D%CNYW3!UMh+0Xdsi zJa%p$1_QS`eLF%c*M|;d-cycTNT3ng2n@+=H5Bb2YKy3*W@TT9jMnMqPRxN}#5li# ze0*p1fWUan)K^A~Y4FG;5kt>L0VD19O>3u&F_-A{u@MHIcSe0TnJmI^0V)0=rO?PJ0vAVOUPhak5s4~M34*5kF z25O02RuL8fQ>{_BoGq=8f#?NIsMkGNodk7Ylh7DoD8 zzPfI@YFNx}*sLL!U@enFT-YvoYpfdnBm?&Bf@OHevw%+U zNRBWjHA7s0U^svMzgEe2yb+DSJl{eE#<^>v`hffK8eg-Ib!p$35ZH= z5}7G;Zk%*q^70w$Uk`XiORbbdlm;NByg~_?BxhNeLBCc$A7><$B}~vTOe5~&dmARs zotTzJbPr_fT)?GJloLIi(i>qk;>rz=9}hSpoIKo}ii>mnOkQ42-`w&=W1Po!xvcF- zEnhzAm-46a){EHM_yRk8D~DsL$RUfV1i!Yw-s%fDz8_C7(k|$ygu(YpZpJvgCa5gz z5rLK^>vQvTkX<$?3u_0KNH*~diAHfFDBFo!mU)+qkEVP3!7wP3Uf{|L*1y4G*7)n! zqpZcO4g-UdfaDhx0NmOOot^!(ktSw_&U!;}Nr}%A5Eb1#&YUEYt0*XFT+&5E=|j=< z9|0W|t=$~l^XX$>=y>)o!GlGDE;{5K{rqWO_{J-W&Yzw!e;C)M$@9{JN@+AeU~GqY z5Kiw*B<7HqHp9|Xm#W1QE}fP?(CUxm4>Si|42@W%F=%{!XE;1D$fP_A?m$ZdjhZhO z$MvEw3*)8HHSKT#$bZ+I%5UrFk#v%-aEB0KAZqEQbl_q|krJE>MX7oAwZ0-PRqgo|BCn>&`IF=Y?=7?)5<=Q#D7yDqGNhr5l|ces8J$>Q}~C`goaq;?B(t0HPdZ@otlM-AqfX#@VUglq#y zWsHU;X<;Tgvt)_3&m3ev^ZX7iX$`k*O%m?D+_2dep;STdlq9yCR!B#D=dR@7LJ z85N`5m3X>xbXYH-LD6v6GPDl}URyDKQhVzb^W8M3^|hoU-b4nq-D5+^lon2;PL zp(ocvSOQQmHb;Zou95p}Tj@NO8%~3BV^2n9QToa)l4ofo^B7W2=o7O2Zy7hzS9+Qa zUv#>;B0uVSJW_+F zhC<5xXSd1N+X}5uO%?u&Sz?xr+3NE3!%pTXIOg(K;@F{1e<)9X;eFV@x8p{La*u76dWsCAC0 z;3<~x07XE$zic`7(5?15A?1C^k-R-y@)9btnLDSgvH^s3d$6>z1M4mtq?T|Iz2YM3 zA?o4=EdIQF9Ci+?4{lBwn@bE6?KU%Y0AxOc_BM={1iR09FGv=mecTfslJU`zg93YT zOo1Jo@g$P+4GQO+;4Q?&^kJcoTaNzub94*cZc~hIGLFQb;6R~&lI|MOw~CDqzYY(N zjCe>+aKWO9$K$o$5FXMp@zCQ4CIsQ>3o`==r}2dIkaDmk(QT?&E&SMTv9|S&6XJknCMcy%W2@rdP%wEgdul!cz zeevkyGTT7sO3FwDl~dss9`+PIA%681n@s6mWE&6(nC5c8(lsyV9gs(PP7hc92rczs z1*EYX;^fJiOiBZui#@5-C{m?XGQ-G^>`gnqI*TpO>_G@HJQ>KO2~5KWF-$y0DAG#q zt@IR34uMfZFui753z0sPh|B0G^vM_P~}qobEq zrQ0l5Oo}5#*R0Y-wylJR92l8TH7-l~!I80%rumsuY;$h{jKzA1WRep%|$Mtgz z>Xr+=pZTauYs&7%qXV9JSn}5Q%GN$Inb@Zcg!Jn~;z5y>%z8 z^3vmGU7;TFwL<%I6im0bLCFC%Q-^5POQUw?oOW(4%3o!?IS^&_RtF+&ldlJfLJ~Uf zM+45QzIfJS^;%d8uD;1{8XM`_dH&`30P?~}5KCuNoE&~*P6xuc7wzHzhfi8dI^1I1 zK?i^(IYS9uox^YP70QEYqMHOIy;UmhPlW)g916w1eH_QvJjhlsxs zzRRIMb@u&1a;aLGnikCh(OuI)>sTNZU)6T+O%J?}F;*Owza|+_T<_`~#Wq-@lQQe; zoozSdrLkLV(vK&*9zm(eQ8rS$3sVd2QGM&{l&w>T>}7wI?C(l~^;=Qa)VPBkGn3IpP+HR#54sm{HY` z+mRkD9%1=qq|fB0SeqliDuv(YXIAV~ZgKgK%|}d^D44=pDbsI+P4mHNj^!aETG1E; z%18w+gU}@LiOGOh`t`J+uUxQjskjx;D#*6=jSCkq50sTIXTH*TAUTuoOfr{&8gQp5 z(IZ+dDQS+uxbwB$YU{MpYSgV6Js%ppFk+MQ@*7}oqcGrMU7Tw&lSwJMSnWmIIA)e^ zM6u4dyCpc1LsKr^Z`u`$#G4rQPG{dIe`MWotu39|N|QZdx{AG7JZ#+T$Dj;p*7UX{56pUxSdX5*+lmX{xiD172Y)8r^qOtsfs`JakDoOQx94|Zfum+8Ls zezZtV@&Kz_v2H}f%*thGFWQJGGO015Xk}l@lu>S0J&{A?_VALZ`AGj98-GQO?`Ion zey1g>LZ#y|HU7rnV|vAv3w8~GK4I%wfbk`UB}`S4+3I45lSh*7q z+hO`l8Q2kJcgc&M^(|;weL5bf!FXvPPq_skm5O+LD_)Dkv9d#P0VRZg1LnA0ds|x@ z9@udrnhD%^KuibLb#T>`9o55XyXu1r3*6Q%0o~}MTRq8ti@^1h*ru{v4Dn@&i)wLO z{w41mvtC!Fhm;x_C*nwI(|N*U>hvW_IEolaZFrT!HA2U&7A(LOnqvi2eC;=E(YKM^1`El#k zQ}QEbC`U9$-j_)}w5QbIh2(D4+Jr@t1`hn$ssHzl@?M0Sl7Qxy%a@DVJVYcuZt+M* zTgMhni6_ZJ)FzV0xF>J;a#d{z1%Moi#u59?PRq~TzJGU00Y8ZnP-B1t17 zR+L{Za&t*>4R9ORsqnewx*$Ff1j%AY>`r=>#l14Jah6z<{Y3dmuGV3S_LkZwNdFL4 zgH)oe?3}!rpC6S)$#jo=`r1deGnOa~Z%=e`N^B385_1APJ3fuNIMJ8rg!Roe5xQJDC_U?_s{tY_J-Nuwi)+f zWY`BH3AvFA+bwfZXCvY)F-@=*oP4jXFR69SX!cT+vC}QbE^8!5_)9F^g)w0jJz=Z- zj9E~}LB=d`lqDe%*8d7mP6ZWuc1||eUZutZKJf0wtU>8^+)9T=@YB7`DX_^3FP)i+ z-l}ZOlBq&7M@<==uP0j=kQyv*To%6Pj9eXS-qE8CZ7~IF59R2j!o&fVtm}T)n)zyOF+NOMiR^UwBUR5fNa=fSkCVa9152N(|@>YDi4> zO%JI&l0c6qkRajwR%$ zO>Wq5=AjE(0Ms-6Kt3n-O}y}A4gOiWEJ6fSvzK+T!b$J6YU+fqO93Djd_VvMQB)SN#!#r_D+d_kI&~iIvSZzS(4M_ivYX2bq40%5HH_M* z$^tksg4Srrsj8}+r(w65Ms@aBOk-Q2Zcf*zcyvzRM4MRH#VQd_I0ORy@W$NX!*e$t z0v3rCeE9YlhRre!e~<-Idp>cWJ{Hro9peUl!p4jv$vgDAsPKfCX;7=1yl zVD}F<8`K3jl<0sMOc_Wlt(rF{w;X`k) zw9awDr~6u`W$5Pfn!R+azh&bYS84v0w}D z2dB>*Lf_-4s)9MGaRN8iK=~Q5i-NDXC$tjK?G_&6p5gi(t6M!~9vq3pNGo2^m%7E? z>R~VSM}-qMjC$2P@HQ!V(6)!=L`dX!M$6Ch;}dq}`uZ|%M!hK|!({mL?*qB+E}bdi z2o%QKl~6Wb!?$t?jpGD+s%ZDfJc>-pKeI__E~mGcjsvS!7Y zusJ3)F4{W)=5srbLX5AK{q_nHnrrs;8QkXe^_70lKB#Ib&#-wSRLkR?ylTBoRU3f< z>157=O}yQ)t+ZSJghcUYG!J_kE8*RpAE}H2p%*%;JcBuLsRFkF{z1=w6aoc*p%r%r z2~2&v#X&v7qc#&8uiKzycKF>vbrF;+Rr+85ANEn+GiKgDpXB0|8&bDimk2NgQpNxn ze+{HkULf-<_n7Ne(RYR1SE3so6@q`V?lR(FK?xt_cBx0HJUI&wlgc!1SUaIVy9165W~)bEVdWK?t&E>anro9=REA^l2S{WD}o3I-yMc) zHONyJ~x~)-!6B6-+T3?r`y=Z8V zO!akq*TxVy`3(ue*5q20roz;H@kvO+I>w7{OMSbH3d~_IE!AtI^LSQqFvJ4Fa>~ws zOhb@g;DiViL=ZM;Cg{79Q>AfzaNnr%J(?J}els|}5TWs2c#c!wp<}+N)i_mc5wZ7W zemAhVwjT7ER#jTZI`nqNuM6Z`ZRtLRzY~Bz(+$xG;BXs#^j`+y`4DGI214ERq58vL z3MK1bq-Q<%Noag7-KE5Z^8Qv1UNPj8x-bbMdy|$ohJ$T}bI>`+59*tyv-HtI;PvcI zo|H+!6L5#jX?qG?N~|F25cWDvxT>YndE_OD#dU_~)dm2+`bXvj&Hq-`fuRDm3+B=R zYXWOLZz&qidpsRa@kdJ6rJ;C3PHHnP%c>iy@9_{QpEUqGU2?+IsT<#j` zWPWZHu#qxyaxzb1yEcMbmQ;b((h5=-535UK%USd1ii`NKG-F+nKC~31jRuTxdElq! zfocYDIvNB=U9Vcu=-9|45-b$pGVH3D>%Bu-UOz|o_*Q1(?DprNv9bjF7brsO;7Mik{3{fR zIjt7%It@V#4hzHeobL+%ymqLi)X+54QbM;#AlG{5(X)B%eE)bGzOJ0squW0&_+)V&)k&ZlVcwHls)yDF-7GhRwz{SlA71SeGBHRa#K0Baw`(tc>suBaw4;>+a^8 zyE`uH>D?LzyZSD4ir1++>Pr?$R3{gKHkcZf%5688(jxLY?;7mlzHc#ftUNg=wW9_cFMZljE zbDsz__PRp@cT8%1DH*Z(;yfsZo>_26cjDdiSBqYf{YXrVEem$b+i-;W#F0P&cizO% zpK!&@xt&$|OSqT7p*}I|w}A1)Ov}EhX5s`eaEZ{)j+Yxf)L-k2@t+|J2|508##_3& z!N#qw`E-OWV_Xf@2|(3x@m;c#;6p)5w6Ac@P+@O;9(k#3PTuN~dk;p2^C~m5M$q`n zcuap(cA~Vz<#{E6V7!wZG^fW|(pzO%7JafdOZ-X&%c+Es63hSqUL!oo zoyiE#N#9>D?yfR3EkLnsvow~=`(VoKP~trS=1V3$E-C5F)tp#%Osa^*X0dPC3!RHX zM_t~ojTX`?0`iOI*n&`bxX?+CZmCva=4&l}Q;fxA(Craq{Q}ryRkxQe+Goa>C*2@1 zPKy2YtuRm_^Z*E<&aZ-pNR{oVT}WoI5}prRv|7S=%N^py1zaw|Ad%pJy(^+zUlueI zVwk2+cCQ-$f{KzOyRP=Jh{bjxf^5tLEYx^B>>5N9cu7tIEk+Z9>}4!3iCk@h-qU2X zP+3&RXfPER%PaAAh7A(j2^#CyZFwKZ=7^+l2SZ#n&oRS1XbWI3xcA+g0SYCJwuqw z0lq`Ao}SV699L>VoU*kH+D~c2?VpULl4)!(2N*|mV?75{qY12aHJv=!gz<&?Cryez zBL$AD4emjwM2Hrm!{oMw5TYsQZG$4moADV~ArKBN>X*)(VZKrxm8ycdnP08+k$ovU z%{w*|#qZFcvM7#@Z#veL{Bc8G{rSh0?Wy~%+qLPfK|PLo`5I5}2V%+zg=B<&_{zoG z+xxbS*Y0R~mu@dgewfFq#iV*u=qyTtrb;6+#jV5h5NQkH|5|=uqI+Yzj2>NY2bN+| zI`nor>!afKKV?4&bXr~3xZl;F-)GgTO=}M778E9qdU~I6vmfOp!&O69Tv^`QyJd6r zwuU!pcB145xvW~3WbX(X6cL|PsTNk|tWnHEjvORy1jLMMz-bKKceKX81rj6k=C3;s z&G^iV$q6NS%SRurI6yTzd2uPUsH}YAjI2)G=RN(j#_Yx2Le_!BUR?gEQ~5Yu2LkK$ zs$H5td%U1>SNXN_(p!Hm?71sf4;Z9z*(qK!)%f52$1TXr8%s-|6fkEriA>VG?j}$9 zvQtpJWbNProyDFlZL$@B1;;-3xZU%Bhi>e68_H36S>?2j0Ak@B;)!{tLlRM%2%FBw z`auBC8Ivgpn2$os>qKBYV3LUJnZef>v$3-91?j*3H=fA{k-H^kBBfc07Lyf?`#!dk z+0dv*UEEZC>R@OSr8JmDa98lcwx9A-gh3Sj zPVeG{tq5mo-YMS6?BXV>ie#Ap47xQ7xHPSQA2fbzEiy~0qEPxGWkKaZ_zYE#=I?FR%$ z`X}qka2xh9=8he`O2Zg!>S6}k_RZB{TkkUOvE@H&OK|}lr?Mf8h(Ik~SvfcNDxH>Z zFz|tqX~j*_Y~(%l-@5#^wC$?DrIPl(DCsw6sl2~mtKY|&#{^g9*rTM=E-w3x3XBeL z&D$R6Yov?=pRNn;BM+?e`1rwNT?Rnl`2+5kl8tc#i*K597G11%OOC*4UDHDqD;=6k zHr5L*?Jp-&qRZ%eR;uAfBX9-Argcvy;pJx@^m>V@b@JeJlB#%ROq4E)sCM3S+)ZZh z(Vsvs(E-}a6UbJ? zi)t=*-PZ9{NTKsE!OCsNmDboQGZLu0htOgNbTfdX+Q}&4&m=}8vBXe=XnIucAv-Yc~5wEt#<(A_qRo#V9!r3PQ(T_+p zvDb$fg~Kxb)%*&vb!|;U&7}tCp>S;~S<9`fi_$p`0m5Iqo$}%pN)cPc^YgkcIkeX% z^WiLVfJnG$--9^Gg`n?Y!p+vm-x-%%zfK;QZnOS8jze;IOttTF`ARb4c4HV6{^UM* z%?bRR?$#0HN*;nEb>pN5w>oZFlNOzreHv`^dcxDLwCP@1JD#@Wv3j)Xvlr8etTDh~ zH+qA1FPfNN=bV$U$_{&w&l^1_REHp7O4+=1b4=r+>{F zJz}v137f{^?qY}leL_mwIf;h)#KP2$@ky@pJwsMfjkzVxOw~oop1wSB86Z#E4XT z@RsOP5gsq4QI%Q#rAz&e71cMl|C^R(y%bQy;I z=SraX>8v=nGuK(Qwce=wMqWCe%!=cD?vBcuIAC&p;8EwnXh!KY)$5|VY9g~bYoanc zYopFCEbk`%)_U7iNk+F+dH6k@OPRtu!fW|{B~$mW6rG`^P9mMg|(`OwEA(}UJ(8eEa{%8cMe z%`O7PK5(|??Uy0VT|B4)+wy5mxdFml#Mz~8&TD!I`8A0Vy9 z_LYqv+(tyYkaA?dME-0IVQF zq6on(SOc)SW|R7tuYcQIk^a?H%$GdpFj7aqHr3b^DfUK#a1 z1%xQI+DKBV)IxZTwM^89h-xhu@a^wm+Hf4=b(#WY-J3M zntBML_NYog>eV&+tKxaMLl*~)Q9x2sae`0zr?5OP9ponQ9Z5$f0xfVrUsEr;ZEmLZ zzu3Y9W2TT=H9Pe@c?1a<8hSkmdIs)AmE+0`hl$i@S+5i(+8GNE>~;xS&2k6 z&H+5_A3=)xrPCLtkWR;}m6~bAM3wdqP9%TAHz4izE`}h|E6c!V97&vKp~gD3BR}D| zq)>H7mlts>H9RPj8PD3TEl9gcM4ub4xZqVWCTHxs&b}jAxdIp?eZ+&1i3cr|bE6eJ zNt(*JjbP4uHo}2$*i)qYnsq_zoNa9ui${ZSJP_@f-1>9)PibQ?0?M|6b-x(+1)Y?f zW*)*dZzB(^lAMws+SM-aZ(W6Kt~@AzN$b^?E6^ZY6htkSvC|S{q45O2aUJTNyWuGr z%RE(3ad~f1UNkvN9Gem&2`a(A@g-jV=Jt;wRv&hR94als=IV3Vc`+hRq#?sJ#t86S zRV2}$%8OgA%)m{3f!~o&zJGE8J(=}OEs+NbiN829N#(8n-Yby^$|$iNS!8W!ucpP2 zh@1sXVW7MuRhd+mt_t>)L-!~K4+Os2<%%7S9VZ}2CqF1Ij&~sytX# zm#$Hiq{;({!UaqYDMn3;hhD2bhQhpsaK+vjh3_!~%tE-2YOpH34hR`f@__ApPq7XR z6fA=70*d{S?l8&Uu&>Iw0?@tlh%6j+?umfI=!E>h!V0uVbN&)Fz23yK*~(I-)#@mv zhx7G~E2PjyyG+L)KSpRHeo7bg^1U$+^^}&D0vrpJw4o4iDNiEJElS7|{c#Wtn*zy$ zH^+50mDecSgrdLqtL*>omLX6;f$9i88pDAxlnMZ(CKMSbj&n1u*@uQ$EbBR0gBN_i za~iADLC8Zzc5udg%(^8Mn6m^kxHlhvlwT@%L+j=^&k8)FB8(p!Cn86|wejcDAqU;U zqr?!T=T`OWv#H>7z$QF4L@jNekHMRviw=Qwu5_My=y5gvw<2x#jIX>(>)h;pU;HRu z4!v#dCsv@do11eI-U8dSM)y7v4}B_g)>g?C(}x2VBCw{Q%=c~lx3{eZ@BI9z)fV)r zId5^Oxu?3(`Fp{XZ>*3Z3_K2^e_eM6zd&IQ@FQW2#Ob+N*I9jO!J?GJd?V6w@6ufM z2J(rQNelv%U*DODS1a4gBJGim|J+X8o`Nu!e3$2^Ij1=2*1ZZY#d&6sq__z0ZtVVZ z%b@`1Vwk_qejRWsHAN!<@&$7W%XUuQIX=*1$>iv>QAgDw>wv?W#}9!x{`}C2k$JN= zCaTH|y)81ceo_0D%K(8}^kLz-mYD0%z9}`;ALHZM>0euyk$Uf6X&&!%s^#-yDBrCf z8c(E+J?KL(`pMv&4DAlE8BjDo3=cWxRLd*^?lAzOuhp#56oxs`%_8+?z2M1E?yRO= zQ@i!sAJm+GC?7C(H2ZVUN(XadwV7^Fw|nXA{04o^3?sonr2X>u?#Yj!@t+x(RoTJ& z6TPNhzMN7k7=bS~_a_Pxq?eExi;EG+OK7L}E$!b%_;Z0ZlUV+=-j-PWd00{RGlh;?}k=%CeTjT3gH8S}klO z-cE{TlvhYs2G32%Ul`E}R@0~Cc;<7H^_E#ihG;W_N+Zn02X1Gb;|^{|d`gISN$vPb6iA3F7=ul4nrMeB6Y z*XQm7VkWpe4VXpfU+eMFaM3VIbb24aSPZAFLbS5=tS(aa?fUf!E=9uP#EzhpbuBPY zQ$oYO7;OpS+ttUSoS^aIlk6G?U3Qcf-(;O&w|~pSomd(FQ2*eZ;`*Cg4Ht~+R_;U7 zG*1wbjFGjFzxOaEddCv@3C?)J?>!L=pYD~CkOjz=7SenIVc z)*kS@Lr_avssNX67ObD=zEWqrym-PZ&h#5;d>goL@yeXy@sc>Kw{M&maZ0mb1Dq7= z{6`er;eHH;iOH33AW#bDI1sRT4|Q>Z>!P*U!U)Xz*6@&^wfdQ-jg6m~)r>vHwx1K5 zRNTV1ZZdGK61l%&K^-sQMq3SCD{x-6wMMlUo5U!}^Zmj<$*ePHX94rG_1O*t>`^JS z0mH<^inR_zOl>sxm`6LmKR7YhThXi3RMB&PllwK#Z)ue{h&rb({Q!uxKDj+GFHFA&Z ze4l{Gq>7VX%s=>geYaciqQHSuR|i%1y&m=(u>|Z?eHwv{KTOxa_W2G~&0f2}jLm%* zObOC9Xt+4r4eny%jmM5f+OPs{yf1`J0nyn(g$@MlHp=4b`?ixdO=}c9>CAOGjc+w6 zKXIuEBgQZ>Id!8!F3N3K0v4%h$g1*YXU0)~8k4uWS8wtDXRScS>lk&cJHrXdZxaa*E0_iv+lS{OF)}dP)V5I@OJP>2nDX zo-+~l_juI0*DOc3Ae~K1WW1WNb{8dL?XhpZgMSCsd;;M7t=eohrFscoVM9kddRA<> z4j_DA^}`RQ{cYf{w?(O1QEZ&*yN*Z1H?2wk-`wgXYdgN!d(4dHe{W=Gps5=uM& zs6F0!cNRdrQoq~f{&Bh)TmuqoOE7yfbaw4920bEo4KRPiPTm)k1NFRe4X;G*ZrTQe zN?$c1TWqgUorX6^!WMtQ*YhxV8~87K$A$rMu#mwxJ~l?O zz78iaDhNkh@=@Di*Caawo@j|?6aYm+*ZilMLlU}{gtskV88Cs}0V(j0gL#x&Xv&e1 z_7lIvR_c`sNHU&qLy8%+cu}=b!lm%&IhqnaCVFS#fUS=zl`Ct>yo4vk6u-(>U!;CX z`L&M0P-kEF5JOLUV)5e6%$A9xs$tc)^R`aO$RP00^a`i@enBS=l`jHG+2!qwpKr36 z_39rYrwrQMtQsmXcLJxux%04r>yAqrqfbnDi~EUbF~ChKf6IV++?TO?nIM~O&1Fiu zAuLZP_NZDiPKs>~!Vd=GI;gac+@dN+$6(;}cwKYSwj*XlT$m930rI*Pqr^r@f}Kcr z^X**{tEvE!Nela;kw3UMBNfPkRf#U~HFq`1uFg_FH~ZEXkPoipFdUIOy)&u5ZW94; zCOIbOR&{W&9kirDMstu9n~WP(V>?NGyCGbU7_L=z!W*>ZeW-*1VuHU9nR+_S&CWS_ z9^4@yQrXnl*Ur9^?vvj9smcmYKq-kZ-jI@VOCAy`-Pzor;FIKC~AnIxkg#JEFRE_du zH#B0&q+aZPUhF6-dB+q%QNXQ_XSDMmyplN_Y;5q}yR-|V~XBWrhISFaFAU8k6$!ku*yc^EJSGK*T z=KmJrv-}|W)j{&|Q29k__J?rgrdiT*(u&d(@*R>&7U2?b7&pUyR-wDvz_&Qyw99Xw zKbNE0@4L&_{_7xztJ>$S{4*m;MhQDpY&H;4L4auz-G8eDr11qq-w*6&e^fA8@^>Br z!b$u0v@3qp9<*DRuxmmcu?6CjG|@3k`KVi=D)YuWFKW~JOaVbnFj(b%KK&4}xuml7 zF64CBx^)%E!*m~Njk3gPT8+5sHpJ|qDdP~aq;(PO9%T5M_-^B_`~<+cm8-v=e?OG8 z*~-cl?h1o^ZZvONyYo0m+b^TgXw@OB-2?`GgGoNA*A^e%{NH5$Z)T`L)kW06IxI=<98b%6lU} zd;iB+CHAF5u!l=cJK>D$!T?2$D0_BP5;hA=VVhZf#%kkFlZ?@=RQAxazhDq`AhEds zgq7{P%O6U_+S`NmGG>G^_TNOB>Eo_1pG_M4=u(X_vqNHs79c<)55!(1c}OC*V*}wO z8{dE%PE)z|3zSu&W$!s?u>Xg-9gr~?|U0uB@mjb^C5Ev3=!e?GFI*zjmb|Q4D zyu~u@3=`&LVB1jIu!OhXiT)16P)2N6vDfmM}z$}e0Zi01L{OR))P zfu4}63BO`^8d`|I>r7G-zM8sey-&v|J?^%A((R=D$5wrax+(Cr*S?+LTU!C?AKFm% zThH_E@opW=^W-w@Hdz;)ORAL#zf~Aa6PkSkl2;ipB!Ak2QaYfg45d#1{WD2wx+u<) zA5zwZN{xUE@R2E}ozxcj?YE|}u?71ENSjIfgV}DJQ@1F~XP8Usa0{iV?=qWQpO2;v zZ%*CsfgO2a=)0Qsufd);lqckn+HkfGu_YUS*8xkbMMbG+PZ-5pIx5W9xDWu(4{*Ae z;MPsxlNSsOfn>me1GePI-i?ZjASVHTm#mzJl7?24ui?0DtQoTo zs!1+h#mj{W!Mq+g-|#}8Zy>e5meHZgrj4= z8?!cubAI>-pzZ=nX>G6<7U{7Tqq%Fdj{ zJ6-jjMV`da96|v>(2xaDnTc#7lvUN*e}?e2EZ#%xDgF@TCuW;Nd)!MzhF#ilBPbjN zUh&S~9u>OfdG`);J-nG1Jyp5fYHt>9{t)nNR%I0Sb;+PHh2|qcnGMo#QJl8w2aXxPeRIhTR9(X3!3R|_iCoR%=rf{e*YNuQ9J2MWPNq6ar z4!pI1Hcme~o3T7?Cn}71MA!X4BthWHg7F$S4~b?XA~449yUJQg`8$lGAYb32RT5)I zYp5d03mRD>Vh_R)3Wq#$U)jJeROYo@y{cnAjje|rbW=m_5v zdRhre4peW9JI6TY%}C1-uZa$T%TOO)MRQaN5+_TXK*8h&?#~4G3<`vF_JKn4B}QuG zWJA+`gV)!p1{Mu(u^pqXhCoacn)1(OF^k+Q143^xvVp zbL#KqOr9Ywh(R))QuiPaAe%G_qZz4~f;t^%wO@@YTXY1Mi1bq`U5>vt73?g58&5gA zGXtii)TcZ5eX>j{;)dPC|}Y;umdv*NnW%@a{bJ%bE9HM1yc^v49`?q&f!})o1m8}dVgcOqEpVx4TXOF@ru2`4y|3%+mhgT=W*RK8 z6(O@ep%JM|2AZRqIayLNy6|@Ka`{9v@5Cqi3d8uB4@&O^R@KgztCSwA@*G zejM6|)v@YSADEAE&J1%pcDX={?om(r#j7lDc9prji1zFK94xnCq5@^uO7aSZC05 zUNoyxd;YU#6dH<5$q{+ee{cxV;hLJs1^_YMsC=+b2Myj7GTY!a-XaVP@^r~n;5w-WnAY*kzmT$khfH&2ouL;on2i6_id@}sdR_6ReKn5@%}+F;L77DhvpWU# zR~PA$Lq(#_o)&Wd<$LE~$tH=!EFUNI+jRfk>=llRTR6cNap8$|?)VBVD91|dUAvex z4XE1lnX>E3xizcj@L_rUw+d)z`dP94nYb?R{>wC-2Wlp;wi=T(-|~XCVfGxN_6vh? z%O@zB3xze{mlYEogz~r)a~g_R!$qCdnJxh~9m-+< zUmHO+y#4ztJ!HJx;|xB;xnC|B?y6|d&&cRFbVA{Cxacs%4@gSJABt?8;h}6>RY)}U zb}k9K%06AjC<<$gIWC|eRg^(GEI}<5tiQ&0=7o96u#nP;%kfs=YF1SYoL;_|fqk%i zcYjn!!PA&59|J*g$S^xB^IAkIuG}MgpS-PX%t$xj)nXn}Snn`HfyZRcbwbgi^)=FD zs6EYAuv}CSJnQ6K_r6wz`$U7Gvh4EHB^h>UCRfN0>oF8QmleUAP=ENiR0;ep?5Ol1bMx<)P ztE$4zlNy*+vINO|PA7Ftq~gOIq0xAyhbD?C3aK`Ca&m7+=AbkI7Y(t#-b~w4x4H>u zZj^{xVV|S9z?36&D-|;2K51ql2!9gKrM(;xDaXF~J}@LE+sg!Tq`(lp4;Ai?l>b_^H}p9?N?P7 zRV(TIQAf_v`BC%S#^2;KEadAi;3bMhZ=9n7j^D%HhYl3gyyy<+^p#}IH+p>p4I>>- zw{&}XL?ScctP8us^h=)3WUiI)AbUe~H~o+&(hV9zDQ<)?dmhg;tZSyNkSKf!btpCc zm31j1>wLBpRv`YAS8^1dobY9?6!C7|e{PfB>sVKWPadRukA#v!b(vRHhXx<1k}NVz zA&n@DOMSSa1CaEZr1Qc9y0`qCHF0z6pl^ZoF$ia4Lg4a`fI&`~0(aoLagn+LQRlq|N5^ zAo?@Ty_40YcT(~JErnoFdR*_*r;T>$0D)ulk34{L2mpz=&?+f^;>O=4ZRfvdPTZ#M zx~)lhvVJ4yn>s?eeeZjjL=Y<9{s&aT4?=5{ZP?qoUOTkK1S_$(jNz z*h0Td6Ql>gJg;ZuO-W6E2>{ur0Ok9R5*P^K&cZ-$X5avZT%h=U!L(!^9B-Jyhlz~s zj9V8rTdqPRthzZZx1Lg6)q<1a1_o5keeHD;K_r_i!DZ5-6g0+b0Q$R*b|>%Z>HMFT zUP}nh?9$2{7&Z-IJ2+%5cq_Hl;YtTzhIJKRG7Qe5N3Q_~%5no`Jsq7tz})-WD7O9m z1A&SYcZZZ4FE5lR#{yqqy*2uG&M%%XD>_(xw_5yI*1|4wb;yuWmVlRmS0?QP++|gB zKYxLG@PAH&(tK)a1R7t+O?NXfhvdf*9}gpO7D`)n|5rxvc=^t{UL!E`&pX(Tml8^17>keUn3>qx z_9L=9pXlpN>w0}2baie1xNG~4aEF#*Qx>e4uAb8tATslC7%o9xQ!$=jE_X*CVQ(cj zt}IhkSE-cMl?pfKZDh11MfN=`+faqx>Zx1Ou+!y=nyU5fY>MsY@k@|BGrB%#I&fMy zf7hQMyJvp?-Xrgd)H@t_M6Yz)-%q=y{(RZqbke$g)YT?gIsND76uQQ)aAI{;TV0Te z@t9P)qS(&4Bf{aTRn|ste}4HEdCt|Ps-evg+l9%YLdZI~68eRYJi;uE+=( zy^}oQq7v`}YQUPoHF>1bgKy<2UAm3$u`IoWwkzme$12f8jI200yT!cXn)Vf@plwr% z-BhJX%=S6ry14`6?As!${;kAcOG{^H#qcJ>TwY;4qze*QhNm77#{DRX9CcvsvmK>v zXHOd}i_?jQ0%(1K`;y*ys0JjN1KW}kq$CXAMaKJE)9GT8$L0*PTpikq$arjiTgC9c z0MXNIIk91iyVMQ8uU zLx2A$raTpYXSZbU+t<*ba!q?oSJJLW2WS#E{5i8%_eRN_EOSx@h0EWSdPq0Yde526 zMsj0FOZ@-%8sBdjQ?B9TMqw}+!xpW2vVoOo$3vn|?*Dyxxe6SAQ39 zr}o=50!rC%N7bOy()6@2%<7C^)zpoujsV|rSO3JAl$Z*CT{W0^43YrJ_Mn~?;Q2Aj zd3Dkz=BEy?I7rBkCljCkJEYP;yF5|ucJ(;9gp94ebyloA9_F{nrbSsP7Au+WbZ)t^ ze9qsp)l0SXl?>D$-RZT}Gb)M87O3hX+x)fy_TH-_BOCf2@VMIzlF*J$*=Zt8L!(BR zTETTx2nyZ7gQhq1?GWmDTs`;EhQ85}V+55CSXm@0=3d%KPU~pyaU2D~hiJ(>hp_C2 zqSERdTekq`t%i}cCBccsRay4VLGDNNIGk-8UXIXnAFZ-=7uLeIlanMi33PpWqwGzZGc^&=nRnea|NaiXT#nC$KguRg@; zFjIWnUqNM&XRbUl%s3GJK&>n3u{D$lGy7*ta5~oM@T^4#>P+7MLU#X4uda)UYWq6k zz3wU|dWDqT;HmmB;tp0I3qB5^%}2CY9sWZ~qv}cWPqOz#awYkt zVfMKTxtqb&36J<(y-k6*{Go|<^2nP?XLx;d4Oo1rBJAW;$YLuQ?P3oWpZMX9ftu~R*EY_5 z>qxKAn}=;AoSJlH)-f#}#G4B4{I$Hh2uEFMx!joWsF~ooB)hs%I&KH;M`>RX{u zppQp9s+yUpG8&cB;`Wa`y;aBL<&N%mu$7#ct}8v{IlaZZ5 z=Zq!ATK!0?TvF(_71yry!WnJoSz3fFUExbel3UtEw-Cd>$K)?;JKtu#>kZqP{YrS_#AOR!cJRfQ$C&JWVVDMyly zLYXAKMK@e#{8`quROGJhxW@|h21{q&-^sT-qBk4wAa}2+LTLUe`D=yE%`~!&m;dQp z^Rse1!g_VVt8}YVd}~=Kb&KS0C0xZ>O05*hZ^(wj(LXfpj?Ltv2gj zo8?Ha&UZ5`5o>v?l+mGht-Qj4$}B;K*S85};;G9chJ`QG=>2rtb9JnpBl?`eIEl08 z=F8#vJ7>(744v9t$Nn5!hks;X6vl6}u0eqaY>4|9XCt>DZ~Z{tULNz&c1aGSL$$ev z65-Dm;A_w05pn{E{A-9!a0?dI)PUjhOP!6*ZEg-q_%@``%^}1Idxd&YNmfpta)EM1 z&RUkbaOAbpSEY9-TX`D!9r>%W4Jryw`9t|r#SViZe<6Rv*rQ|A?vR9|{=&j7ajm`3 z9#wZr`#owb!W-}fozU3pz0hm`9__JPUUN*ob?Iu32|rp z;kgF3`_32QV@_zB`;`4u!hd$xDOa20WWvcA?On%R#~mt3*&W9n#uA)vzN8Pqkp@@8H+}ttZw5(A?hRnQ>%D5kf1xQip0-5#VERy0HuB#4XRgf zb-G*_%N++ublNIM#GVdz$~vmkTjRb=*K(NNEugEZdHhGvZ3=6HEjCLRzdeFE0oX)7 zxkqdEzTys>VMG}2Y&qaOYTX-Em=toaod7orjI7}FYP7j3?FLS4rMtiskCPWEIKdHW zkTR6eV&dsj%fKEjVTzk`^Y7?1WFRaVrU76Cf;a{N8y;#fUq(YJxDqy{6sL(Qzgr|< zTp)2LI~YSUY(&;c()klTBjOkFI^I@rEht}`=}2MBxg?|{J$Jt&7HtMYDna2fN{boQ zP`M?VbKqnur#jT(B?*1#y6e$2szFjX?!3eW28EfE_{ z5Z5feEJ4dm=;L*?TbY`i`5n))QA#!1CwiHc51K$u)Sb^-%!#K(M9x5?C{R{pY?G{9 zI8Ny%ES#_@NnN&NtLCIm^Zw7?Sr#}eyUL#GU%Li(pajnQ?EiJ*rHbr0*CYGnEAue| zWbHU}Hi41@^`6J98-3-YuMD5!(ezb$i}Ge;kinU_E6UXSAt{Z>rnBBLo3|CdTj#P) z>#+3d*L^d`u1QC%+jU)z+jxH7UWLk(m^2EVnVWHB>E@UNxLY1Rlq`Gft}!F=UNfri zNks3P>pkmn2PCm2@}SA3!t**oDuLcZX9^2a$-%@x43$EZhDiO6m_Xzq9#n4qn-$u3 zwrt|f%dPMg*kK41v0d)X^U18T!x8iYdNmW93$@Z1@d$f*-xkI3G13H5CV-D@o?KVa zpOpJ&g7BCCl0`|`k#s4C9-;_@IFM4PRB$Q-SxuYTi}&+2B-&RZr>_BEkOW6iu0HSQT6zh@E+HVE_|mVKdIxxk8`>1o!DGj-sSrnCDQ&I zXOi=DGG0uOBRfl;Fg`o7AH&WekdqSmQ&UOR$NU5#A+Oa3NQXY4Q`HpCe7r)w&$Y$1 z9#KxO2rMM47A#8d%Paw{pLz3Pjy^%6@B;TDR0rTw=z~q2&(;o0mcIVc?FS;mN$jhL zoGYn2JEhaS=%ril>EShyttwvSo-rYb-8%qn$t^8EcVb>;nW95!=uZ`UuXQ+NQ_LD#8ldFQlyV_ z8HXb>1RRuE-_{gBurj>nfll`}UR0XDDRo=S6+Sd5ZX@FnDtDj4vPxo}(%t{AB*>(d z)E=s3(*NbiN^unI%{*&L$8QE%m_qn0VNpTH{VTY6%{GUaZg zuKcylw5TpaOh234XZoLP(=yv!^^_y0E?1bU@>yW%9UfOlfx$jY+qzNL&<0zYOH9myL{1h`)?iN&`dd|p}^n! z7iWqFt?}fCgs5W3CA=oLvS`R4-gv;)OrWhPdkYsRW^eYJf9z13NEw#vp2vP{7nYM9 z@z^+`AT4w1v@^RXAqyE^1G zVw`VIzDvSXlD}vkciQLJQ687Z7k>%5uqox8f!!zyy=j=owihOFIgy-@n4H}nMx$i+ zNr1riQ}Ca9vDMU~rRM_Hb#a>)6=&YvwCPqv(OUE-VECHS0RM1( zorRg7`C$_of#;R$EI$ml@aH&?&=3{}=9!!PONO3bm9Moo%xB_11kiGu5mzo%(E(|W*UN~m%89UW)1r-Q6OpSdONsqpjp2Ot(n^TqzQUf6`KywCiL*z>t6&C{%i zl^o^l9z^GW2ADjOt;6+-B{T(sGCl4f9rw~S+mk;$^ z{DUY6{rJd1(1Yq-c<;e!@mgz;u;U~(pzH-z+=z%j16r!JPW}TrHQZXizX1Y6<^?BO z>fEHteIFEep{Lq@NJZn`0j*X}C-YA_sZz!L7^r+oC9Dz@*r6B#%+y0JUf{XM+K%O5 z%i3qnkSH@DwvS;Aj9W0tm<|xay8t7gsAFAfq1ziNn1Nst8}HI`b4nqlDr&X`5))(f z2xedul)Z1uE9MQZ@9iBK85=uoc&NO%c>jSQwHz`$bH)`l)%uP=gGf}ueTlDLjo?s$ z$T}5ud;K1)P$#w5?b-M*wYsf7Jq>*bN=t96o0S<2VG8A`>R3+Zx-H=ZzDv3TI}~_K zKtLVAwuzKs9gFZR1mcOv5vZ!nbzL3Lx~ZL2ELrwDN$p|S%de~@7J19UTnUIAz$3Xb zBA{fs!4ZjJMc%bOP?dhKKW@dKc3pQ`#P7^m*Q^50?~bvs@PM~rDTwCYGo3SZGSKnk z?+^E_RQ~`_rlfhpY%0L9PhA9Y0^}0ZSl-pTiU5kN?3J{ed?992iu_-l6d{b!&^W!t97dh zt7nGy_wxIp0OCNv9gF-c`XYb@lTt1dK~s=an=7sdI8z6JnXxl+3Q#O@-IZ2egk}Z0 z0NvAKnfBV9U1WS~unHP@bWsc3!=yc;6FTAu1aU(z(Z1hH`ZnY_K+X}&rnLV!+k=fM zuj4ibZPja!&x;?05_)@ycKx-r#X}Mc>+MGqt@D(qX?TwE6ZjpAfQr9ybd8y6PZFl%4DfeL*&Dg(7b!f@w@i zj2)gy4>kF`dEl4hKLCM*hk<;r)>UOKhti_VXkzQIEM2{_TZJ zSRGrEJGS)UgfvCVXd%c#L9NT*Y8S5)TFE?oI%csOp`rtcAC`KWJiqwjRGUIa5yKXTRWOv{SP zW~}#b%gqQ$4{p!(NZ1vb%^hjkaaCt$>W$?o(}$)MX&&`08eyybb!p7YG%R6zo*-_% zStPKyoB2rXYf2eo)Xqu>0XRU3bTL7ad5`M*r8uKfQO+qS=MBMea{fHE!s)9gRK)+3 zGEr4UzVlRwsD~847orT*s|ud!(keteAq12X;-#2i@|3Fuxm}VlUf-fCJ;$r{s!4na zUcM4f{b6{cyC;|9iA2y;QxZ}&f_wc(a05#XI2<80k7E^_AxkZi3@j^aVRxL^>^7Ob_S6Y5u&tBC9%x@o1b>UV_z88v6zBou;Epp^(tqoxe1)JWq zLX6^&05_3NIkO?P_-9EVGV6l`X-`5QxvUGiDtpMPA-yKLM%)l{sKHaApYP%5ZFJKr zR>ta)V`zM}lFFitCJ;qEqpd{*mMenOLQ0?}Q6evK!eo)(=gmy#4Aj$-=1%U@W5BBMycfgJo z<+z#TBC6zRsx;upeL|I~S2LO4tnTCPTW>U3X1UBFiyi*b(lapwM1ODEl)b=m!Cgax zs)TUQyg_+vu%c_pH&Y-?uFYz}stxr(**^XGbNVI!@#-+!DRmLGLAoH_IsJ$&UV9oN zc=#`&-lj}j7GUBqFRhj+iQGTJs9DV^hS-~73XFG2d*ZER&16FeF|U=j+1>c<+K}2u z@Qh@I5^9OOJeK2t@fz}^Qm^YU@G50lL$OYCNhp3UmL))Y2Dz9MFs%#?Dv?0Jg6 zV$n;z&Aa&yk);Mi$il9-nupzPd` zE|_1o6$aDR|F39^B74{v`DgM++YxH6-RBhHc@PHS!WFHDJ0Vz%JBr2|gZvgl3P`Au zDrfd`Es*{@GD$nKf$(JG`c#tFSn9+j5?tM87gVhG2bG)0no@J1-);F2$1UzJERG$^ z!aG&4y;ZW?-}$i+#C9!vg{PA}m2OW7If4M4@@s$}5mm11m5`mP?&6aY9t7@-65;LE02$&Il8gBz;kB!3emQ*ocX3=7?L3q^K^<&Wvva# zUN?1o&rq%0|9-~Q#t=VNTzFlgZ$^f1XC|I^HBYD3 zZ|f{GmD{RpOjP}!*2A^j8HP@71^HEAdZ%1e7tT#@_oYT_{jk zoYC=^^mrvQin?FQ<(`=5GG{>kMZlkz$!CV7NNT&wbm>j)`wods5$ZPfMozvB+hbn3 z$_4P*vb^oB@?(+J>#Tn*O5jA)U&jS5EAgRBQEY)vkpl?AWaR*0b(6cNAG|xM;nt>A z{bKECm@DWJeNT{G=H|2U?!oXA4%&&swIR$Ie`08u3B~;4AJYaBj>ma2FZLvTEi?nZ zt&lAOf%g)qqT3vOmf#tDkbYdp&o6E1+KA7wzyu&(gd{Qpp3RivH6z^TzQ9}$flyq6 zYgn_i4vfEaculM+#+4LLYzDw7UielyW-I#?baRbryb;>S%auyJsS~XD3||t4~R3@K@<}WEJcd zjW53+n)c0Z-w?3!@hQ;xFr@qIP$O6}Klwt(hO-f=DT_4=G?taDB ziL0FtwWGmVSeAtY#6csIUoe6elBkN7YK0{o7b8l^^Eh9nyqRV$=kLVG;VsUJUdArq z)+Y*#WOc#*?BavacnB;#a{um}vLlgYv6Hr?f$}OrTFuJcg~bzFQz~l=q4l-I?6iRN z=txez1Q%4YvL*RNorE2g7WsCJL4xMUV~SGWS(G+_;s9jp%)6^u+_C|s02>sC4g&o2 z%I|?6ij7Am2mcvk1Bg81^lzS*kS5}6^LKTOy+2GyT9mVtZk&y)O({e#^HrR2*0MXl z8}__A>JJ4CkL-_(?hL%f_GccAx3dwOxZNoM%F*4Ts-LBd|GBq$4tIQBeq`Tl1Fse) z$-Y42ook7pXevXu7dHH!|z2d*cX8Ip# z{kDk+QwQJGz|@gMRJxTHo|TnN72+7l0D(^>NgMu;YJ1l~a zd+L1`ge=mW+&!(obC2F`jEOzRx=%?v_9TC*?$U7b?ZPK%CTolz+&8Y-`n^Xk?)I?~ z=KYPj58d|7bo2leFzOp}1-0l6CmpT)Vq7_cs&apk+wKi)XKGK}+AVSn-2Rem@dINL z#q5j2H)&&SE7Ktrt3;Pw)%1zZVKF_?q&0DYi);pejt{L4Z139!)uW>&5tWg&8q$&d zYQzag_heKG!Vh)=FQfGN3H690_Uw-zsl86#zSUmA40w~A>_VB_ic2YEP&jVFGdTLc!J;94=7^~+UF+< zNCIV!sC4bz6>ob|mVG2|MHFKDu|Ju^*%g7ytnQ;hp$~Z#vu4}=nz2JK&Yzrn-PW^p zH+tlfj~$O1lh9a4wsxVi)&APsEmuCjxvgJ*nQPCZl*sXqh?JD>zp8fba>$!$f+iua zDk*`p2pw`s_3YAOK;`VJmL*L!(4BLWAx@jU>pj&oXv8I8fgM#d2C|Ni^?6o&433TD zaEK2G(`zg?uGZD9id`#v6ZZ7RMb4L8z!TJ7+0z8d)&qHN+mtRU9Z`CfO;5A))xZDg z5Jc}0?%gNsRF(fzT%s_TS5+r9`;@*qnIqw7&V@l0CCWuwx5}I~Vzttos}wd(F8f|_ z=hf}gw%S2n@nfyOw5crG$6I zp%;9$_}WhPcK~EzdnHly31gpm*wJT^{Zg}@pq#})IePD)ShWX2PM&-<`Pq@P5rmcNLB753es^X2f~1W|_^o1I&Auz<&NSHfmi1H{v*L*{8t1yQ(X;9&T25C| zsAdqu9a^S%sgey+x6K}}eIAnt%=gsI9;-#y+M;z{!1t|v+YOnluowS5*1R+1u|q-Z zY(re*qbEfU&Z#NaE{kF=E&9jzM?(Cx?wr_!^6p4Md|E|^d5p`g(|Peo=iEB~4ErRF zh7%`>ScUd>AIUQ&yLs~hR#8eXxw-$ENnYvG#oGz$Cp22`|5;lZeLnoelWrEDoY?Ec z(XHkg#iMrUtNv7PXIFaLyts14F>4KdP-E~eX8OgQ>Gl%) zOhDwfUV|;&&^PdKYJ_j8vAdjd&7|=9MB=uz3vh5tbn=1119BAlk5zrjBxh|(bdW(% zgS5kTt=-EE9B30N*|O!$n=SXX{aVm=CdFh(t7?2Sw@}6oIiU0VvEDyjU4ME7cN-Yn z?gAhY0DuS@cliIKOq<~k2bjRxdd(nuz=i1^xS-IfA=UUU1uG{kdYoc7`|b#Xrw=OM zt|W`z>W0p0&W0?4wKwWwL*|76731rYZ=NsO_g%q7tY|A9x)Qe|P)@2D$T|%l(#JfX zMB-BrUsE&?I}Xm)Oh+HAu9@BMv+P!1{UJxQsW_L2%A6&z_W~WQXK`JycUZaH!W$S8 zTzU&#h(ecFu=@;$&b!xo{p?gz`F5c6Y}3l{@X8Q{hE}*MBl?Qrp`5C-G8-wq!WLcaLM{2QQ?{dvP@$dI>&A3HC%GgKa ztTc_@6Pv%q*5q>Gt1sfz4Kot5m6GO^s4?rjQ(CK~6i zdwsMs1Mz*Gz4wgQ^`ae?U{VKF1Lt|CtO#jtqE;LlZe@7ico^8PsAKnrVR7J4wd7P6D5A~O2YX{c0+BVIFD-`b~(KTMT)m)-DY;4N7F!3bYEvH=O zw8lx8O++`GPZry{(&MdiRr(Cd6gpAbgPSotJJJa)tC;IL7~y*Bulimk@o|v6LcUr{ zicv)C=*D{m(wCNa$8TjNv?_26*A5mpe6=lfJYL;+*rU*5RQ~NMZVZ*>ea_pNZ_vui zp4TYz-2v~kvV*4t*Vd0agHj&rli=;pMSiD$>gx*yz$ZS@6+m89wm$!o-B&dWfWRd) zBUp(w^adi|w&%FD=xuj@46e86BP{5DEU`oNIO&#!omY;}Pd&uD;)WR9NcS5z>*GDn zw#CdEIxEo);gg;yPUWmT&BAUXT|3#V;Y11w3M+?AeFU{xVAkgs2kg)2)5z)!Pu0FclNz#B-?$EVx zRIcV37GXCe?rjqKeH@89VZ*=wZEG&XG}9j3=QpbHwgb3Jblr=TLi>CC5Z=!p^Pag{ zJ)@C-`z!cKp%?n5;pCV1cl7<~lW$I`F0YVM@gi%kPc>+=ycJ=&y+f5tkT4rhuZsO2 zP^%<_FS~nj%XM4964t<9X6s)fE|7QRc_i#ODI#xJh&waDG+HO*@{^)RCZ4SHZ`tfM z8=&%M$gBxl3p|iOUUic2NB0~0l+0H!Ij%(Fu`Z}fizb5rLM1#qf zAN<)s3GuptNw~=3G(7BVoI@h*V86&V=lrF?-ZvJ|iz@iPDW%5_Z0mX&NDg0$dQFsz0rFIT#po}Z_E^|Zy){2{g*c?4<954(@xJKZV&hT28|^%(^pbnZIM$^O~b&S73B9a06;F7-`6OMF4A)GeU>Yu5D5g*Vf-5?5YJ1dp zePd7h?(6*{Rv@AV`yI@sDV;hD&+cZRo~S6pz4B2W>hK^O^v8hSDyhm_!_~E)lC0r= z#4TWG_`oqKI=_g+1%}d@oEW#lZVx~$$j;q?+9y6^6DYEu@$b(*ET*ZkkyS8`E>WNE zuYc~_FN~yfRVub?qTZ2GF(xKEdz?Kyq#g-T0i_nTkYvM!QWY2_q?H||u~M%Iz@)v! z;-^MHA`*$t_7w<*Gp=CAKV9D zzVQDa3?B2({|te`TO+C0$IRgnyjljg?%FTFgb+DcO-7xl+lPA+;KAHC^8OwI$eEC_ zoZ6}6^v~iOw=0STXoj=H!~b(cW+5Rj*Tvd-#@P#d+_?16J@xKqFg%GB%&8}^@X zR`WtFMQJ$6w>hlP$ud00$Wwk!2}|3l#BkFmhr@!PhX;TvkrmdQ)^}r9M&I^hryi)D zOFzO|K}rzW#=50&H`KSh^I{;;X@~gs%S%ksU|q-SXUUFmBy1^%ar_IpqQSA!jaIQj zAErZ(Dr4_}{7bKCa(aIuku&JphqfHHvwSe)-$t{F4Pf*KTAM-ynNePz_IiCHA=Rl( zkFNM~A`8D;-WgJ|j2iEez)e5x$M6q^xF8d~A2*il3*iZeWK3inNGn*=>GxD{ox8U6 zmmfQwjNiLgwa?GnGmnOAK5F`>S6!f6_XPp^(SnyzRDSpeH#xOMojjXz1(lI$@uwi6p;$ww{h(GIasiWY zPNqh$6O~Kvd^tH$Q0JKT8e(BB{eB806#|h*7H(LOfIm86E^q;6E*~BO3n9X;L*ZtK z0EFL!S`Q@o-0y(;z84DW;nv-rT-b?fwzR8_a(2>Un=$(2z(zC+3ME1y5C|W+LJeyo zy>hZF9VDmpB<#ukT!}YJm8~`2bNBOZU&IW)(JS@!v7;4swY{exitI@gyIAUmMv+dfhbcfG*UTOs)P+I(p#t@!OC)kW`bXDpV+m32 zQe6$9zg=Zq6+<8pcMx9c%DT+}@R6RcS2o_NeM~}p`RLNInW(ciG4q{L3=Oo=aBe-4 zhYTGIVi1%aK0s>*v;G!Dwo=#E#*9J?z&vE@7DUWXOP%N5XL?HOGKFn#1;5>TO>PB6 z=Y2&>N5EH<oBbrabh`Y z3qxPPeo*Rf*7fjVt(nSzz%lTYK4RCYijmXYY1Vdz|C=^58FgO>oXI<8Y90f)FEJ;1 zuo*eGL^zva(I5q_x^62LE?U6y7-n(*xjw;K4$Q;zRFIk$&Y#Y#1od+^r|Rj;8V%R( zAMK!bqgD(btUxLF!RiQs_TYCHF{ly#yR%@@XzvLFrhHm=vXG0ahWAyo|7r8L4<2Ez ze|z{{=d%7Hs+SNo3y4_vAg@jLp+s0_Y{_c^VWW_Ex60Z2C$Kp-5+SFwF}5mTn4YdOpVi8d2WxACwK?(wTJ7cuFiuCig@(&A zgEey5VNpsJ3l760&i#KYjuu+MEUHha>Cb5GPYvig`Wn_)6$d?Fr%%7;Fo?knjuhXE z92|_iS3L4g9n3qx%6nV0z8;+X9Mfem#a_2Z=g7|8tiUaM3_89h9Nd=mR-qOdPaZvV zU54|#wa3x+G{%ohMtw0+tXBb0%6Z}wKu@K9YxnV{Tkk7@xnrLZ3`btN%croh%9}h$fRAg3r~5fEUv2F?ew`DbVpE%N4HtN`|X z@7sX+?i$ArIa94w60cVPfgw-I8luvbr0HO2z`8%1FPJ@_r1J_O@NdWYBKMgZ29G*8 zg7`r;0#-}LBc_p9t{=9DpovLw^l^_%g^umqc`VVmgF0SNL3I#*-`(pn%^z zi(q7tnQSt3*xDWcb`3V2HDc2J3z^5Qt+0Vh)Ax4k{O!>ek8cZzfQqim4V`ZjqnQdx z(U7G$5Q^v!FpB8NO^p2c?FoNVf63Sv5>6lX`~{ZOCQI)--3 zMF?UJO4^h4Fp!i>B9LI@M}JzM(bsOF*+^DaN~^NI7L!8ku06qi~X2%kd{V?eTHWTz%dFj>j}T?yx{aH-F$- z!1EKCceWN;HRa}>-su}K6gHFpzSEe^>d=ybAhaqe1GDJtfb)8{M;7W+JOM67IU?ua zLt)M#dW5c{id(*Z#ZW$)lHIgp1CiKTLjR9q%rtBs5W zfodp9m9*8I8?rixaawOBIU*p86`#rCgU{hKX~5E zfLHS{O)aaXH_{p(*qNT9?nrW0s4@z-krW+C>a^}W```%c;^ru~+~&Cz2JH`=4K;On zcWOd(h0Fit9Et`(k+84Uk8c+bhV@)!8#7tqj{3DsT<*%cYiuKP|8vmGf0Pc(ugn`1 zM-vX{V*f8|=Fr4KS}>OKauv=*xoCw%*cx#;;r>_a^PkdsvqK$>9XKFBtjQAq(?b{P z1vHU_w&I-e6^br5qrz32dtawq(GY--UwtDXe0r29F*3MMhmW1F1iG{Q~9EjEcD;1^ddH6j{7%L#klChR8DOCnXZb_w0aTTWQ>@HiwDn zXiP?u3auGPPhGwKgofVdqYaHs6`kSkBHP?m?b0!yP~g=H4_grO9=VMrfBomA;m43jr2Z+86zdY~WEfX1T?JdSS5b7@3(9@(KUv&Ewa!}^=C z@YNGDZC5VIdon8r*r%-S%XE?#V(@^K#Y&xm1eRmh3j`wSy~_nT3&qaEkycKV6N+Hs-MIds`6X-C(Is)myLbJty^QX0>P7dsg$8M5?956AuVueKNd@&q@_h!q62|?-?G{EKJ8TgR<=lmw&r=_zjry990o;ft^oeJW!XNQp~8D2yN6oL*2$1klFP$Ib8h(%=6y$c^E z9SBn+mem4qOQ6W_fJ7dc+W|!Uqze1UnhX5!>KaXmIYQROG)Lhc^JPHsW{!T|yE_A6 zez#XoYYNvxOabWejv!Qq=aqb*JC@yc=qcimvtdXUlD7<&z`5{xu03pdPWlw0Q(pS( z2H$u`hv}~{7^($k-^O?$Ww-;zxGtJGm8QVrTqp_$|0r&6L1|CjK($AN!?Ap4JMQH@8Aa9@G|DGS zJp4edx_k(Wm^5C1aS43oT;+fJhE^3H;_VxsF>s&{C0oWLQ`GO^BkV@$i~8dC&)6ff zs4b>Lq)GAG% zCM>7Si{DTetjkQUS>fL#IPk!rKK9ZN(LMOWTgTRS+&l&<2}2lu&Ljd{n5CXs$yqo5 zn^z=R;gf%{tX`0uapFcLMTOSc*Fn=1R}->PsT4QLd)4sht&fTkWD3zq%%hh)4} zR8UUkko^dEVzQ6B)SQD|9+UZIf7 zZ%2H-o#7)_Duaqe{pm=d2+@aDcwKEI@7mRmkxNQV&kr<4EvuIpZ&B+*8=b1Q+A`6{ z?Xw2DGjT72RG(eFDe)Z^JT@+BcyGTid_zHArdwk|>N2V0d_f7hdvAZxF|CzLd+`P` zK^0(6t?>*SMmW2|JEzqrAij$^5(E;)fIwnW!(Hx_qsq6@aV%EaZx^3DD)5r}_-wrq zUXg+bjRt zs}9U9vKC{UYi=(3%kOp>mLxwqi|>i1f$!Xx-^IZGV#j;m6U||I1Henb!|L9nWSK{6 zc~;i8yupR1TKTWdr8>9FCt8jbb7z|_0=ofETo*4Z-)Z|UgrzlV%04Kejtf14|32~v z%XS_L+w^xmH(Y}>z8~4(--vnf`hF?c$#EG@O928G0&}Tze)2hgJfheOYYm*>w|is( zhNj=vZ~4QXJD;`3TIh|0umt8o#8Qbgr*?9~txe5=meI2L63T#{my0IyUp}>PJYifW z5ZzK1^IvhFzs+wAKv*JBT~t-xFnPb|zIGYlcC-t3*6RJGbjn@jRn?ak?P=c&hddQS z)8g@Iu6R9TF?KgOiYR9J3hYhlYxCNKI+G{bstUVF>WU1N2KQimdCmwqMD4t$@imfe zj__3uI=VwEFFrX{$3`e4Wl5BLl}jPI+TqZWlWZ`kq%$_L*>1;7N0((PHcn*?FUyP? z?bMFf#j0v*)tcjX`n0X{W%b23a(vN(kl=)r_nW*Tlp6uNXgF)(=TFq0c zLvjk%ltSZ4o3d_nhuYSDwJpsfTH{u`f4kbqcKX&G8%(mSLIE3c`KKZ|#g{dn*uy#C z9)LJj2EOXJc&rC#>R)7D%Q};Mcx_h!D4(}}tKSX!P3n1pE2SwT5+%xlwV5Av{i=nX zf_~nwz83q3(TR&HxAdg9#Y+>Tlvs{~ukSqg&(UYA`!@i5U=V=K+SYm!u*OI*l^nFs zX=_=SJu=4@7UbdY`{iy8U;Ec}|5(5NM^{$TxsHyrfmvNIOFT;MRAg=zow&GJv+d^f zN=-IE;OBDPjhq|vPWxhNzVFjS9XPdoAkD%jgERm(*b+=Y{vkc#Nu?AQb$@#5Z4R2s zkY2spNmV+O5P<2JWdDuB-HZ}p4nJWsXaX;gu*7NZdBr=}*KP(;x{3JbZy?z3kdr8j z{(-f3BUf<-_~!{pVJD6ygusKR@**+z#_9 zUupR8uaaG&#iBsBkip|rei7U`8GFp^9aXe&t^7^>*;pOdkf8-?`ozgo>6@unIy&#s zKvoo!R@uIQMiy^b`(7xJK9Pg5Ifgw}#EUkT$JQsde_T;h7pswSZdX`o zBSt(hd087`3w@5%ml>7RcLn^BBO^zV(9mOrW?HmyHMOy3adL2Lc{&>mzfYG}-gIUR zvQ(uPmV|mCv`7+D_a;#4$`4*Z79Nbok%`0Y9Sy^dOFK>k@$5R(jS-`_ET71?$G^1j z#hG8oLeZ3y!I zIr!2KKxMG`e%y50jm)j5zrxdGk|6RbETSD?hO(x>^k(_Cb8uRYT*DnIqva{A%}LW! z%?zE2exenF<@3*R@AmFSnk+t(IaEI3HZ91nt3`wm?IQ@KIu4F2GPNIFgW1w-^5Tjr zzliSakOP*e2+4~lXJqpP?xT`+QJ^t(OKNuLq7nQ`U_{~f^uX0Vf+JtzdIy!v3*TE2yxCq+3 zmx2?LZ@vO7E!oLXgADFuhj0Py?`ao@9K$>RJRZX#?8>k$SNF?|r3xP5aU*ScE6enB zWo2B_tEVq_xcR+Q;G}N9c<1B3U&`F5BT65Q(LlpRp!gFOz}T3DZOMUSZxE8V`)k*N z1pVct^9@hQl-|Lh@LZ@r5e~>B@eQk=Zv)hL&FJlozmJ^-vaz?bkE?{3W4|B?9Wl#rhXOZA@F^c##c(~_f3A^44sA8$3F=Yvq)2`RJ&I76~~@H!P<-0mJstYKMk^W z-sKgB0TZBoVR*UQdEOeOoXp@X?j7Q1#^VJ=N6~R*JeikR;1#*8w0Kj3_tfuvYGkcg zlALYL&ie#>9tu!z{eYXNOosb&YI;j2*As}Sbr*4<{#7@5yMvCd+RmfXXPZ>?LQ~cW z43IOF(h6MlNq0h_;<>zwepxd2Xo4-M9|&lgk_ExSSZyl2d&6@uXGa3mru04xOC7_2 zeTxNLP5zdtLmE+qnSt>7%*McATI{_ggapmw$ba4 z)47KnvtHpDgRN8Gd6DmD&VU@!V-#;qkolx`T~Nfvh6ST*^iw;4i!0=K2GrR(yB425 zx1z7lCDO16g5L&2!UyWzO^JT`w>I_7nVv$&xDn16db~&w(;2%dxz5GWS!@?W+l%RL z3d>o2*5&Tx_q9OdM5w!~h?hpmOUgYmi z>Vw5{pBc#t(lo#3iIUn=PL(2~eA%106>GSzBJ4=nWSQ33(9U#p+#cGAG;K6Cc${!w zp!zL!oX6YK? zPhI&O*L7gLVKK|yzjQ0m;&LnK;Ar(MF>(?R5;318I+O4Ld6FyC$%e^z+pvXz{l~9jfQxHf$)q$Ogb2+$5*WC2&13Btc zb|lHGdOF1yW+UPX`?*(dB8OU(XM|dJ_Tb4nu{2yl-EaSin=LoZjtvhQzi(aj{?xA2 z*VWyZZK&l1(=@1>ty>FcK=r+|ygG0RWE?!6kGnY(sWxIc3{F3!r2vugB~K?sq}csb z*>s$l@E7}ykdc*@i7ikw)1dHV851~GR7?paz>g7f2uen=i2HLeyl+Me;22Ebi^j89XnvHWgModvFZwFxteCyK_{Pfc`AnRn$l{Z&4W~^yrjq~P04i4Zpid?a^vu2|4`97BKQtU=SAMAT@hYg!+U8x>1a5l(k z(q}(LUBdg{{}lW_cLmPA9Z(({PJO5ffHP+-XyQbV#q3g zT;LT1k;*N|TQC}{og&qHOz}EtP5mBAdbb~5M<8m&Gg_RNN?QpvQB7oRPq!G@8=J>B z8VMwEe~f5`3lqY{!Q7CL**EZwt*40;t%UYAGeSk~8_lQ|*+?I{(Im zM6Iwe%GQCFR)G>y@jLRz)B3 zs#dSsj8h|R7nSjZdgw`zOOz|qmmt4pks!F_i1;7XUbJ0Cz(oD zbOuVKkK|Bnk6Kha)c7r81k~>!B zER=eoTxlpY+10w!Bfp91QnDKHMfQA@lk!iHeX7{aKbI{xi%wg_XiI~7R5UWI*rr`y z^!fLsU!velyQi>BR}f)mg6~7VNUHx5Cl^>S*vrI`Z<0SPWEZ9&R|YV50^yR%glz0C zj^_?F*>#p(F`47~xliY!W(4pzl_dS-b`I^$h8ZYJC?-nae8$odxYcTT=i}WQ7mjw# zgHPv--!4z-8`0NNptNVs+m^UC1z+DSj!*7;(4E`?{$HGn|LQS+j9Ru$Q0Mt>bebJj zeHFCu_jeXCcIaMY8*LR0P}}X-l=Xj{ULfjIKh&6cNM6Gwm|=tRs{v=kVXMiX@6%dx zLr+l#>wYSMIwgGbo6<<=B7&|ga_(B{^Vooo`bkYEnk}vvDj;g377=`jAcR>i8tPZAUT~)gNk>lRbaFvK3 zWD?)4LaDVe;q?lv3x8skl7JoX=$CQQ5$dnY{d+OuLt=6)#YesFT(Z!;@3W#F*j9AdR6S@TTvC6kCu--xuKO z%(~|<I@d0!?Ze^g<`QT~8HQx3YR;=bu2MQm^$aQ*E}bi|yq7K?87K)e zIOR1`-F(r=sugj$^Ap%yeFiYZEoM{$$&hb1?k`=>>__`<5w)(jrLeMxqql7GaA1fgXZW_ zjvEU2!V#?mf)!f|A`)i0DSej9*3%r)yLVD@COY^44&(BZIhx9)@DVSl!MaX4p8KKq z`fH{%V$bXHe%>x*f>;tBe-NyB%F~m+M<(j^NpfhL1uyMtySiU9cTqyg`L1$AnkFsq z6g_0PLKn?PReWp!6$rgew@b@KNcI;?fa7)yDh+sN-vlFNb@|nwtz2Jv3>5G&e8d+0 zMCAq-v8Y+|q9y(P|LB1B`C^m}GWACf5Ja1!6V(gpsp~!%B}ww!q3$(WywZyIjim!W z92<}wiR&_v5hXwOdws{{;_Mwm=RE(ty!y3{ zO7313dtvL9vSs+|`jZOodR1h8n+I1VWOEFnPHv&PBLo z|3{e!zMSRyk!UU&*;xx-4>t=TA8X}|NUNAA>}1A@a7(gcyTggq!|Xi6)&Ako=o5S2 zUXOQo-+_dk%60*Z#ar~Lti@-T#T;J`U16m?8+_%l+iLiq_V+N3ZgWJrYDjU*$!)(2 z<)_E6eG}h?MP0}LQpqIG<`=jx|K^w2m{etqeH&7+1yp3E+52@f>Ge&c|1`!taDLo< z?Ry`q?!;wX3uJcBLmiO8CU-{@6GP)Jkq67jz-m(rI6PuXlqD)Mo#Yn{ChH^3JoTrG zN{>9^GkZ2n9r(P zVNJskC(vRmgm0vq83Mq~zJPen*TUaG+-9HenJyK%_2mtJdY=h$hfPnamJ?W$iA~csmYBI6DmDi%%vn=XSWpGJ$OI5;gcSJwdPv?1Bd?m)mrlW zJ$qNanNc{sn=d;)ub>`RBE8-p5O^f22~?p-NblrO5jkR>OJA>yzx33)aJQXOhx}y% zAT(BNCoiCnwv#i}>79@jCv4(F$c?~cRDW&gndWeF8Ks&EB9o7GLV`kfQjS*W)b-~v zA{NyEK`xZS&V+yB)1>beuI_yWiYqJKXzKy?}t9UZbjUEgSe|1tF`&$~7NYRvxz?25tbyRbAe27dHI>nK= zhFZv@J7UY@v$A8IIK8!;uFzE#&-hkIK)?Oi_omncEP)ih?^`@WT&zmKMw?T?<#o4U z0E8)}taVbxW+J)BL2Gbl_xbFzAvr)iZ3VB&Fx9X_9~Bil+GY$LJS= zu(5Qq>zQjyj)t^d=5&>>cV)U2e>0aOktkZ67U0 zzaM+qMdXXE-m{SRi^~!+B(O4a@kAOIV1Yw%G8S3NUieQ{ z@`=%UqY^ok@;kyO+gKB^0@B;C*l44)wZBY-*1Qa;46fTrGvSyB$(NFN(RSU!j=aC& zs@kBXkRq>@lPtu5@(S57qR9%?Y;QP_pGFKTOPJJ*b$G#`g0o5Lpng(K7L6wc3jJYE zWA0}1YjK`yIlTiswHaa`F{!pLv7c&OHR$c#KB35I#*r8{HOF<>-pm@HUn(9)gb)Xs z#151Dy*9Tqou2zX*1y)bliHDNv75X?7#8Q}CX<=cF^MlxPJYRL z-p&K{r<)xG@b8_zZd9^98(9sDS-EqmV61Mjgy?!Lw?{N4=>gDN{UaJDAK70tZ2{p5 zlnkJmk6~^j0Q_QM{ws;j60EQ7!~I=!pN;eDmxlL9lSupqM)~O5%<^qqBZ}TU5>iqk z^EYF-dmkjr4syM-(x8IJ>>X(~z%px4wL7VW#aO*`n;mmvcfSd%z?`X+%B-wS231>v z(KrLy%EF1C)|2f*5E z35$#~9)VjnVylbnQv7s3OXUi`B}S%VL!(I9^)G_4>bz0 z;Zt4&XL26;b3-Cs&%rH#+VWH+|IFIZt6OJVs}Xt1WQ|SF3I)v=1O12#J3fXC^gMC0 zmpv6?TBJm5Yhi(*-f+Zo2%wfnq>>3@0h^QXZa=F2ow?#!WWk+S@+?L|NjKAE8<$^| zLkfCH^7vpF7x&a36OtmKKNt5TLcQHU-^bSKx7K|$sy1u`od2T$QkJv0L!HFkrb>?h=_O48fmctYHQl!rtQL>13-$W5(BbyiJ}MoRrs*1IF91XV7YsfBa{aVl2s zx57pJzH2CNk3p4**K0Gw{VaQP^R_d?eA^{SWqYY-VH)tjNX6$lns%fag+BmciwTD; z{eVqUm4Mgr3)34~grHgkOhHM1NIlmK)DJ;NPEBY=^bL5fof%EdN2GAc*tSba|5 zd%Da_mCezJ-OR#}B5eCDOYKr|h*?#syewp!p-?V6K2h15S)NpCOho4^p0%JDK5iEh zx5E`Egfd;y$Z2-YWKQw6dL`Uh+8l`BJ0L5q7U=v+RZic}Zm1hu}UNe`mO z=LptzGSdq5EKUf?`+YG^;{mRZ>MEv&WAW2kl}mE-NCVt17>JK7Wgxm{we_u2<8t}k zhE3`2yO=e>c54;}iy6mEDa~O){1F{NO2EspIQ_)1BZPC>#dQK?im_j?!XC+>TvujUx`O zrP>n6kf(ZfC;SY5DVK1NYw{0LRH(j&?q7GP^!vy~O?pd-yJBaRdj5PM2kMk9%57Lq z8{48QQJxx3-?aAE)fi{#%_G-5f|VtP;dT|evh}ysUl}sn2)6>_4#d`5)A05UZPLX1 z02wc&ab>YE*| z00wzTjq#4xcwee33dNraE!<1rf#}rrLC>Ne*Hz+OPOl;ShcE&{W3yKE(nV^p6KB=` zRMYM@Oo1fB_Fum@?w?s^yJuO8^%W-k>^AFHd7i`>XSn}I49ca z=gHReK08-Pi5@6RFtZAuUM|6SAmr9D@_T~cKyi9ccIdqOV(_+7_q`0!Q~}bIJ)p&& zW{@X%7USX^sK)VIDH$%xZw&JAFK)XGZ*H5^hV7)=SIL`3%j>^td5j9#)xL!K>sfi& z?cYH2ZOjQlvHR&piRSs_6lh@}Fy1D3bWyLXRg>DSOkm@f2&XQ#-T~XVg*Xa+Hzzm> z(gA&X*`GJTi-N~5ukS-Mho#wx7!m1QlKQ3LjFDcuw^Q0VZ0*zsb4BrpU(-i{iRjxZ z4wO`zbg%Kr_q%?k8tX1bhjnJ%E;{f`!2~Od6BuwtlWYrt-E_9gK&;Y|FbP3`P{}?M z?*aFreO^3N5_5SLsoPEJFHiDa>%XbLV$8Z*TJ?HoymC7LVZcg7WTsE-x}QtvjkteE z)emmI$xS`a4?+LBe*!!~@gDlt&DDD1dMDe?TRB)09>_d7wn* z>B%%mKS|5ch9vpQtJwXuLJjOM2Z}vQpox06_V}qN{w1Hf;cu>$RMe=8G?PF*FVnZ< zlGv3(nC%)xH(B;wJMqlj{ebX1v|JYhFlX+7n zbOM7NWBYsG`uS@hqD#v^z^BId-Y#pPr(%W@#^g(|t?qMl-|B&F%?8!`c&j(aaz0d{ zGRmQ$2!<3KgmgVe;%z+tR>_L5{q2jsae_f=KcLhRe{PNxD2qyj1QLQAg#pu3`yOas zD@2DAgAQrzZLUC)(Avl_%KNLYno*aAk#w*|2=AMjyPsokxx--ms^V$9V1_pjI3=1Y z#8SZ|$E_JsT`3M5xPrvD%0an8oi56j=9s90h3n8&sNajoTxSRe2822S-r=;hF%2DM ze8e+Kre}(!T_RZ$(U4rL|I%ZzEV~EFNNeM@N8t6~7*%c>!R!d8lVXBl zVJWn=l4EWf;4AzSakR{LSO?S*SHc4=Xh6ACdK~c8lySDg_f`pkFa*>HU#k^?Mk*9{ za)hMXOej0CYjHfP@rr~g=bzpZWd>K)z(RWS24$;J{WoGXRRr;k!7#8hjdn`O-U8}5 zo6@7Qu$vlPAwxkd&&~X!a5-rWMK9dA?DB9=jmEx5D3{D5oiT{fXLI@`D=Ux#grhuG zD^+!nEA~NcC)v7i@}e#|#_(t9O%4YG-k=tCW>)%JiM~ScnO!i>TNad-?#I#}>v((J!f2=gHwtwVc_EHLQC){JFeq7&ps>W$Ag5{AA z5%-n%)m`Uk9s6B0JIB6kaJrH3z;!O?qLioid$n=1i4lrqDOhOBjy_{)&~}-)5yfq~ zDifYQW_zyMSN{T4L=Pc#ME$CI0va)*OlfjUkgHml<^y$ie%U+w2tv?6msX5G3P$2| z#}ZAU`GSWiS?V@OD{M@e!KF@7;%AG)l_V?oK94RRx+$P-W{4>of3`BKkt$%=Cw)rH zdIYbw;3}9c=gIK<(6$4kYGoOTejN0P^d6Erc!4g3XYGDqwO^ERSQsi+-!=}GN!)X>w*ji{P1H>wZ{UH6 zX{an&UKRFSLBQ>AVwy2F&Q`XK_T!efPgBi&dArxpzkCbg)}*sMQ3d!ynYcWix z_|npYGkjM4H_VCfl1lDfoX0C$VNvA=MKO()qiafz$U5Uzd^r!`sw6gjbZ`=$i^_!5*E*mpvGd zg5%DuZ3wIxm4a&5e0xsqmgD* zYGLt_w3+$h0%!yaVq;0um3t$XEA$yK5Pw|pv!C9zSh@wc?lNT5)5EG6KfIzyluy3k zUv3{ba}*4FG$(pmR^nCj0s#eCNQ4~D zqf!&>E;YJNTW#siz8Z?A8ZLGxgC714l~`@O#>4Wd5=#=oawdMM<77yT(2db7k@4Wp zE%_OM$dm`us47x}?QgqM7)?HZM=$E)8)}u-P|8J5me;Vs-QgJLa01hjt`-GZf4WXYs8)21~d#k7r)eGs%T zoTM@mjdY}?b}Wv#jHbE*Kz`zf{tRkAt>Qc*%XqotdNs+gjp4Eba2n*ly|eRwCt$ys zh~nX>+L&#zD&EyQzPT7a-T4FSO1;b<&IKtjfrbAlppEY|+K)W=f(08x4LSchxPcZ; z&=#FTV)*|ywEy4&Mhf@OGx`^f5+SBVpmLE zI=62U*W>|>NHHU*R5SE{tCw-<<`9FC;fkJ1!6_8;hau))x%lmF$sfp7&pD(kD96H)c$SxIVbZT_~A3 zq=}nfv}2Lwr=d1$v7i?b+##9FLkXQFg^h;+o~eoUixID_yyG_rQYZ@APz*{54#pA0 zKa>pR#RSC`{ME;>CYUt;d;KKSEM)0R4s_P8I^L$4pB(rX9NTKK(#8fN{R*CJBK6fj zg$x42U%7H@19J?CBoA$x)b)Wp621#55p_mM7E4!7(moooafA6ECF-Zt^1qol{;FtA zId&y37DAx8Lw|yrU@Kx3nm!Z4dtT`gHi}vb$}j&kSBP&eGZ2SUb=dNsnEsur&WEKT z)j_QnLZ)5KOXZBcM8xs9Gw{W^CwZ=9$>@IzmDQpcEd(2W&^0pw4EE)QCw7R^@bLL; z`;jKBD-xYQQ2yd6a!O3cQ1R6Y?8$v6opn%hlyAYLdyZByBqP$wt`$?@3G?GqjI-WI zFr(&N%W-LTiVx^1Ho9CEPW9Z5AOL?Gi|-iXg08;`9bHFOX<@)jh53F(ufGo7X8;-H z0l)YvMmC@|H(*Hq)5~Lc+wpVu7B-~+C=Jcxyn+Svys26)m~PyI-+W15v=_={`XO5l zHTRU5<6Q%(;GtU{_)M$_Z@txr^r;MoqLKj!*lxsJ-o*}P>e`FX{w*=TWA)e>mkquq zR>aObeoL>tvlW0b{B)@!*Q#MRNDVE1iwYTY0jEF7nOpwz-CzpVB)}t%DHnxnklM&j z{5nE-m_I0{MuyF@X{w^ZXId;$ZzxX3PofMm&=br2L2ZV2EG&HUL-^jmzMYczD$O`Z z?tN3awcrjqUCwXxK5<+SI?>|?PR!D$t||ghxxLKVr-Z6Dw@24}CgX^Pq}kM_7!5qg z%Z*9SS}A#;Gxrf6Yzc??{fJaAfRlxa)hoqd(HC= z7O1`LmWceuZ0Io0(jzpSr>;rS>W?x`vcp>fVVJl1r4thU;2&FV>(dCwX&XK8S-%w< z9R&H4wYnRLSj%_btvh@R$#$Oo0`rfNf}|CtyFYe$!fDRQ{TCn#B2oP}ys`rt2n8pY zPr*hy=n`c2!FY)-Q6avwsaI|ld#8}B@=2^@?xy>AgA!eO(n7ietiyp6B?7 zzEjdImQZsbH{m6+$_l~!C_p?uVA-?$aetr2!i(>2oJ8*9svS$rL?LjaYe}8@!`*TQ zq#ig1wLj@;6j;-piPNt2DLzE!!*!-C3&;{_h7O&)YC#HO4{G<&N_9zob7B%}yt1NC zn%`Mm`%Yl-g?yhDxiV;rXh^>0f5my?!*A)t)TMO`3`(N+D9}1!YxNnLK)>@{8hpI5 zD`Qq^)g>Q(N6@}yx=%cj9sNvX@vp)=nn6ncK;7JEiZgd^P2j%)6VR%zgBZHuTvAw6 z>wG|E*}P>alWtK8B}_gAdu^xWy(?U(@8_IgZ{Dg_YfH_i| zcEU*ZONGosHYDv&Sy(wA_rub(!|ZW;oHgD9RV~OgubHzEy>?~?K2bePVezxt2%>;P z-?ra7<4n?x&FYaE?cEGI)-)$tD$5+muBu}U?sPHFKe+hV5?aCTUXV`J=9AHC=o-*Q zXUuT@-0>M!)m+!o+T(oHaeB!5lJUF^EcXIqSUNsvI7$4;|X#{w!e5pUJ_ zak1J+C*mxrK*L>l)}}XDmB5!T;U_ev;jCB9B2`6t)Wa`7=7pam>YPepUHy>E1}-i| zx=cTq2|P}#Ey5pcy4D8*2oic4dykynV%zxoUkQ#ZS%}$Wd?mL`_nI;G*TmEF^KJp z_vh{DE5H7`9RZOzAku0+?DJ`Ocwh zS7jB5f%YHF1(sTSKSuTtezZh?ey859@nDV}*wx8We3^(^>c;D^k{15Qf0gLJdBw#% zK4AOfnWngIHTLC=dT)#w{3rZBSpE+*HU0+;Htp>`-fzW8*#W`aU5e&a;9&m+kS-Mo diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/MaterialIcons-Regular.ttf b/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/MaterialIcons-Regular.ttf deleted file mode 100644 index 7015564ad166a3e9d88c82f17829f0cc01ebe29a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128180 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 ohyj3!`#ee%L;DTjx@8!5k5~VH0QmdE^#A|> diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/MaterialIcons-Regular.woff b/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/MaterialIcons-Regular.woff deleted file mode 100644 index b648a3eea2d16b6ce783906d6b7d5f251b9eb56c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57620 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

wF7DI|Kx|V1sBQ9FYs>m5C)C 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 BJ$(QG diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/MaterialIcons-Regular.woff2 b/lib/libesp32_lvgl/freetype/docs/reference/assets/fonts/specimen/MaterialIcons-Regular.woff2 deleted file mode 100644 index 9fa211252080046a23b2449dbdced6abc2b0bb34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44300 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 QW8}wPUeo^@jR61v08@RD2LJ#7 diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/images/favicon.png b/lib/libesp32_lvgl/freetype/docs/reference/assets/images/favicon.png deleted file mode 100644 index 76d17f57ad903c3ea2f1b564cafb95bf9af84ee3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 521 zcmV+k0`~ohP)kdg0005dNkl2WptjAn6@db&Pvy?U$ zv>P|<&rCZfZF0jmq0opf8)91(A<*iIVPPJJT((+JiF~>9KAA3%heFdnI;SaK+~|aU zQ~!x`%y{jX1<~SK2RxN7Db8`yWBbf6p7&07{VXfaam*cUs&eu*Zu(xaIL8rP){;a< zS~$}^Td32Rw+W1TqTd|L{#~jJet4!qwKsb5hq%YXiiUV!yH=ltu0>s|FLsT+Iy7K~ z!6*Z0a@vQ;AiZo!=s{{fqR+ct6YQPzbk+j}*qe7vtu39I7 zrOtZqU}=NnLchJxsU9iY+}3TYDl|BvPsX%E@dlyLgdV%q$UP|Y?DfcGb`}K&$;drd z+hL;zy7UTccUYU+h`ONIU|d=%`(0$=KW4%tVWXj~AE \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/images/icons/github.f0b8504a.svg b/lib/libesp32_lvgl/freetype/docs/reference/assets/images/icons/github.f0b8504a.svg deleted file mode 100644 index 3d13b1975..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/images/icons/github.f0b8504a.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/images/icons/gitlab.6dd19c00.svg b/lib/libesp32_lvgl/freetype/docs/reference/assets/images/icons/gitlab.6dd19c00.svg deleted file mode 100644 index 1d9fffa74..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/images/icons/gitlab.6dd19c00.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/application.c33a9706.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/application.c33a9706.js deleted file mode 100644 index 3da6d0caf..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/application.c33a9706.js +++ /dev/null @@ -1,60 +0,0 @@ -!function(e,t){for(var n in t)e[n]=t[n]}(window,function(n){var r={};function i(e){if(r[e])return r[e].exports;var t=r[e]={i:e,l:!1,exports:{}};return n[e].call(t.exports,t,t.exports,i),t.l=!0,t.exports}return i.m=n,i.c=r,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)i.d(n,r,function(e){return t[e]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=13)}([function(e,t,n){"use strict";var r={Listener:function(){function e(e,t,n){var r=this;this.els_=Array.prototype.slice.call("string"==typeof e?document.querySelectorAll(e):[].concat(e)),this.handler_="function"==typeof n?{update:n}:n,this.events_=[].concat(t),this.update_=function(e){return r.handler_.update(e)}}var t=e.prototype;return t.listen=function(){var n=this;this.els_.forEach(function(t){n.events_.forEach(function(e){t.addEventListener(e,n.update_,!1)})}),"function"==typeof this.handler_.setup&&this.handler_.setup()},t.unlisten=function(){var n=this;this.els_.forEach(function(t){n.events_.forEach(function(e){t.removeEventListener(e,n.update_)})}),"function"==typeof this.handler_.reset&&this.handler_.reset()},e}(),MatchMedia:function(e,t){this.handler_=function(e){e.matches?t.listen():t.unlisten()};var n=window.matchMedia(e);n.addListener(this.handler_),this.handler_(n)}},i={Shadow:function(){function e(e,t){var n="string"==typeof e?document.querySelector(e):e;if(!(n instanceof HTMLElement&&n.parentNode instanceof HTMLElement))throw new ReferenceError;if(this.el_=n.parentNode,!((n="string"==typeof t?document.querySelector(t):t)instanceof HTMLElement))throw new ReferenceError;this.header_=n,this.height_=0,this.active_=!1}var t=e.prototype;return t.setup=function(){for(var e=this.el_;e=e.previousElementSibling;){if(!(e instanceof HTMLElement))throw new ReferenceError;this.height_+=e.offsetHeight}this.update()},t.update=function(e){if(!e||"resize"!==e.type&&"orientationchange"!==e.type){var t=window.pageYOffset>=this.height_;t!==this.active_&&(this.header_.dataset.mdState=(this.active_=t)?"shadow":"")}else this.height_=0,this.setup()},t.reset=function(){this.header_.dataset.mdState="",this.height_=0,this.active_=!1},e}(),Title:function(){function e(e,t){var n="string"==typeof e?document.querySelector(e):e;if(!(n instanceof HTMLElement))throw new ReferenceError;if(this.el_=n,!((n="string"==typeof t?document.querySelector(t):t)instanceof HTMLHeadingElement))throw new ReferenceError;this.header_=n,this.active_=!1}var t=e.prototype;return t.setup=function(){var t=this;Array.prototype.forEach.call(this.el_.children,function(e){e.style.width=t.el_.offsetWidth-20+"px"})},t.update=function(e){var t=this,n=window.pageYOffset>=this.header_.offsetTop;n!==this.active_&&(this.el_.dataset.mdState=(this.active_=n)?"active":""),"resize"!==e.type&&"orientationchange"!==e.type||Array.prototype.forEach.call(this.el_.children,function(e){e.style.width=t.el_.offsetWidth-20+"px"})},t.reset=function(){this.el_.dataset.mdState="",this.el_.style.width="",this.active_=!1},e}()},o={Blur:function(){function e(e){this.els_="string"==typeof e?document.querySelectorAll(e):e,this.index_=0,this.offset_=window.pageYOffset,this.dir_=!1,this.anchors_=[].reduce.call(this.els_,function(e,t){var n=decodeURIComponent(t.hash);return e.concat(document.getElementById(n.substring(1))||[])},[])}var t=e.prototype;return t.setup=function(){this.update()},t.update=function(){var e=window.pageYOffset,t=this.offset_-e<0;if(this.dir_!==t&&(this.index_=this.index_=t?0:this.els_.length-1),0!==this.anchors_.length){if(this.offset_<=e)for(var n=this.index_+1;ne)){this.index_=r;break}0=this.offset_?"lock"!==this.el_.dataset.mdState&&(this.el_.dataset.mdState="lock"):"lock"===this.el_.dataset.mdState&&(this.el_.dataset.mdState="")},t.reset=function(){this.el_.dataset.mdState="",this.el_.style.height="",this.height_=0},e}()},c=n(6),l=n.n(c);var u={Adapter:{GitHub:function(o){var e,t;function n(e){var t;t=o.call(this,e)||this;var n=/^.+github\.com\/([^/]+)\/?([^/]+)?.*$/.exec(t.base_);if(n&&3===n.length){var r=n[1],i=n[2];t.base_="https://api.github.com/users/"+r+"/repos",t.name_=i}return t}return t=o,(e=n).prototype=Object.create(t.prototype),(e.prototype.constructor=e).__proto__=t,n.prototype.fetch_=function(){var i=this;return function n(r){return void 0===r&&(r=0),fetch(i.base_+"?per_page=100&sort=updated&page="+r).then(function(e){return e.json()}).then(function(e){if(!(e instanceof Array))return[];if(i.name_){var t=e.find(function(e){return e.name===i.name_});return t||30!==e.length?t?[i.format_(t.stargazers_count)+" Stars",i.format_(t.forks_count)+" Forks"]:[]:n(r+1)}return[e.length+" Repositories"]})}()},n}(function(){function e(e){var t="string"==typeof e?document.querySelector(e):e;if(!(t instanceof HTMLAnchorElement))throw new ReferenceError;this.el_=t,this.base_=this.el_.href,this.salt_=this.hash_(this.base_)}var t=e.prototype;return t.fetch=function(){var n=this;return new Promise(function(t){var e=l.a.getJSON(n.salt_+".cache-source");void 0!==e?t(e):n.fetch_().then(function(e){l.a.set(n.salt_+".cache-source",e,{expires:1/96}),t(e)})})},t.fetch_=function(){throw new Error("fetch_(): Not implemented")},t.format_=function(e){return 1e4=this.el_.children[0].offsetTop+(5-this.height_);e!==this.active_&&(this.el_.dataset.mdState=(this.active_=e)?"hidden":"")},t.reset=function(){this.el_.dataset.mdState="",this.active_=!1},e}()};t.a={Event:r,Header:i,Nav:o,Search:a,Sidebar:s,Source:u,Tabs:f}},function(t,e,n){(function(e){t.exports=e.lunr=n(24)}).call(this,n(4))},function(e,d,h){"use strict";(function(t){var e=h(8),n=setTimeout;function c(e){return Boolean(e&&void 0!==e.length)}function r(){}function o(e){if(!(this instanceof o))throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],f(e,this)}function i(n,r){for(;3===n._state;)n=n._value;0!==n._state?(n._handled=!0,o._immediateFn(function(){var e=1===n._state?r.onFulfilled:r.onRejected;if(null!==e){var t;try{t=e(n._value)}catch(e){return void s(r.promise,e)}a(r.promise,t)}else(1===n._state?a:s)(r.promise,n._value)})):n._deferreds.push(r)}function a(t,e){try{if(e===t)throw new TypeError("A promise cannot be resolved with itself.");if(e&&("object"==typeof e||"function"==typeof e)){var n=e.then;if(e instanceof o)return t._state=3,t._value=e,void l(t);if("function"==typeof n)return void f((r=n,i=e,function(){r.apply(i,arguments)}),t)}t._state=1,t._value=e,l(t)}catch(e){s(t,e)}var r,i}function s(e,t){e._state=2,e._value=t,l(e)}function l(e){2===e._state&&0===e._deferreds.length&&o._immediateFn(function(){e._handled||o._unhandledRejectionFn(e._value)});for(var t=0,n=e._deferreds.length;t"+n+""};this.stack_=[],r.forEach(function(e,t){var n,r=a.docs_.get(t),i=f.createElement("li",{class:"md-search-result__item"},f.createElement("a",{href:r.location,title:r.title,class:"md-search-result__link",tabindex:"-1"},f.createElement("article",{class:"md-search-result__article md-search-result__article--document"},f.createElement("h1",{class:"md-search-result__title"},{__html:r.title.replace(s,c)}),r.text.length?f.createElement("p",{class:"md-search-result__teaser"},{__html:r.text.replace(s,c)}):{}))),o=e.map(function(t){return function(){var e=a.docs_.get(t.ref);i.appendChild(f.createElement("a",{href:e.location,title:e.title,class:"md-search-result__link","data-md-rel":"anchor",tabindex:"-1"},f.createElement("article",{class:"md-search-result__article"},f.createElement("h1",{class:"md-search-result__title"},{__html:e.title.replace(s,c)}),e.text.length?f.createElement("p",{class:"md-search-result__teaser"},{__html:function(e,t){var n=t;if(e.length>n){for(;" "!==e[n]&&0<--n;);return e.substring(0,n)+"..."}return e}(e.text.replace(s,c),400)}):{})))}});(n=a.stack_).push.apply(n,[function(){return a.list_.appendChild(i)}].concat(o))});var o=this.el_.parentNode;if(!(o instanceof HTMLElement))throw new ReferenceError;for(;this.stack_.length&&o.offsetHeight>=o.scrollHeight-16;)this.stack_.shift()();var l=this.list_.querySelectorAll("[data-md-rel=anchor]");switch(Array.prototype.forEach.call(l,function(r){["click","keydown"].forEach(function(n){r.addEventListener(n,function(e){if("keydown"!==n||13===e.keyCode){var t=document.querySelector("[data-md-toggle=search]");if(!(t instanceof HTMLInputElement))throw new ReferenceError;t.checked&&(t.checked=!1,t.dispatchEvent(new CustomEvent("change"))),e.preventDefault(),setTimeout(function(){document.location.href=r.href},100)}})})}),r.size){case 0:this.meta_.textContent=this.message_.none;break;case 1:this.meta_.textContent=this.message_.one;break;default:this.meta_.textContent=this.message_.other.replace("#",r.size)}}}else{var u=function(e){a.docs_=e.reduce(function(e,t){var n,r,i,o=t.location.split("#"),a=o[0],s=o[1];return t.text=(n=t.text,r=document.createTextNode(n),(i=document.createElement("p")).appendChild(r),i.innerHTML),s&&(t.parent=e.get(a),t.parent&&!t.parent.done&&(t.parent.title=t.title,t.parent.text=t.text,t.parent.done=!0)),t.text=t.text.replace(/\n/g," ").replace(/\s+/g," ").replace(/\s+([,.:;!?])/g,function(e,t){return t}),t.parent&&t.parent.title===t.title||e.set(t.location,t),e},new Map);var i=a.docs_,o=a.lang_;a.stack_=[],a.index_=d()(function(){var e,t=this,n={"search.pipeline.trimmer":d.a.trimmer,"search.pipeline.stopwords":d.a.stopWordFilter},r=Object.keys(n).reduce(function(e,t){return h(t).match(/^false$/i)||e.push(n[t]),e},[]);this.pipeline.reset(),r&&(e=this.pipeline).add.apply(e,r),1===o.length&&"en"!==o[0]&&d.a[o[0]]?this.use(d.a[o[0]]):1=t.scrollHeight-16;)a.stack_.splice(0,10).forEach(function(e){return e()})})};setTimeout(function(){return"function"==typeof a.data_?a.data_().then(u):u(a.data_)},250)}},e}()}).call(this,r(3))},function(e,n,r){"use strict";(function(t){r.d(n,"a",function(){return e});var e=function(){function e(e){var t="string"==typeof e?document.querySelector(e):e;if(!(t instanceof HTMLElement))throw new ReferenceError;this.el_=t}return e.prototype.initialize=function(e){e.length&&this.el_.children.length&&this.el_.children[this.el_.children.length-1].appendChild(t.createElement("ul",{class:"md-source__facts"},e.map(function(e){return t.createElement("li",{class:"md-source__fact"},e)}))),this.el_.dataset.mdState="done"},e}()}).call(this,r(3))},,,function(e,n,c){"use strict";c.r(n),function(o){c.d(n,"app",function(){return t});c(14),c(15),c(16),c(17),c(18),c(19),c(20);var r=c(2),e=c(5),a=c.n(e),i=c(0);window.Promise=window.Promise||r.a;var s=function(e){var t=document.getElementsByName("lang:"+e)[0];if(!(t instanceof HTMLMetaElement))throw new ReferenceError;return t.content};var t={initialize:function(t){new i.a.Event.Listener(document,"DOMContentLoaded",function(){if(!(document.body instanceof HTMLElement))throw new ReferenceError;Modernizr.addTest("ios",function(){return!!navigator.userAgent.match(/(iPad|iPhone|iPod)/g)});var e=document.querySelectorAll("table:not([class])");if(Array.prototype.forEach.call(e,function(e){var t=o.createElement("div",{class:"md-typeset__scrollwrap"},o.createElement("div",{class:"md-typeset__table"}));e.nextSibling?e.parentNode.insertBefore(t,e.nextSibling):e.parentNode.appendChild(t),t.children[0].appendChild(e)}),a.a.isSupported()){var t=document.querySelectorAll("pre > code");Array.prototype.forEach.call(t,function(e,t){var n="__code_"+t,r=o.createElement("button",{class:"md-clipboard",title:s("clipboard.copy"),"data-clipboard-target":"#"+n+" pre, #"+n+" code"},o.createElement("span",{class:"md-clipboard__message"})),i=e.parentNode;i.id=n,i.insertBefore(r,e)}),new a.a(".md-clipboard").on("success",function(e){var t=e.trigger.querySelector(".md-clipboard__message");if(!(t instanceof HTMLElement))throw new ReferenceError;e.clearSelection(),t.dataset.mdTimer&&clearTimeout(parseInt(t.dataset.mdTimer,10)),t.classList.add("md-clipboard__message--active"),t.innerHTML=s("clipboard.copied"),t.dataset.mdTimer=setTimeout(function(){t.classList.remove("md-clipboard__message--active"),t.dataset.mdTimer=""},2e3).toString()})}if(!Modernizr.details){var n=document.querySelectorAll("details > summary");Array.prototype.forEach.call(n,function(e){e.addEventListener("click",function(e){var t=e.target.parentNode;t.hasAttribute("open")?t.removeAttribute("open"):t.setAttribute("open","")})})}var r=function(){if(document.location.hash){var e=document.getElementById(document.location.hash.substring(1));if(!e)return;for(var t=e.parentNode;t&&!(t instanceof HTMLDetailsElement);)t=t.parentNode;if(t&&!t.open){t.open=!0;var n=location.hash;location.hash=" ",location.hash=n}}};if(window.addEventListener("hashchange",r),r(),Modernizr.ios){var i=document.querySelectorAll("[data-md-scrollfix]");Array.prototype.forEach.call(i,function(t){t.addEventListener("touchstart",function(){var e=t.scrollTop;0===e?t.scrollTop=1:e+t.offsetHeight===t.scrollHeight&&(t.scrollTop=e-1)})})}}).listen(),new i.a.Event.Listener(window,["scroll","resize","orientationchange"],new i.a.Header.Shadow("[data-md-component=container]","[data-md-component=header]")).listen(),new i.a.Event.Listener(window,["scroll","resize","orientationchange"],new i.a.Header.Title("[data-md-component=title]",".md-typeset h1")).listen(),document.querySelector("[data-md-component=hero]")&&new i.a.Event.Listener(window,["scroll","resize","orientationchange"],new i.a.Tabs.Toggle("[data-md-component=hero]")).listen(),document.querySelector("[data-md-component=tabs]")&&new i.a.Event.Listener(window,["scroll","resize","orientationchange"],new i.a.Tabs.Toggle("[data-md-component=tabs]")).listen(),new i.a.Event.MatchMedia("(min-width: 1220px)",new i.a.Event.Listener(window,["scroll","resize","orientationchange"],new i.a.Sidebar.Position("[data-md-component=navigation]","[data-md-component=header]"))),document.querySelector("[data-md-component=toc]")&&new i.a.Event.MatchMedia("(min-width: 960px)",new i.a.Event.Listener(window,["scroll","resize","orientationchange"],new i.a.Sidebar.Position("[data-md-component=toc]","[data-md-component=header]"))),new i.a.Event.MatchMedia("(min-width: 960px)",new i.a.Event.Listener(window,"scroll",new i.a.Nav.Blur("[data-md-component=toc] .md-nav__link")));var e=document.querySelectorAll("[data-md-component=collapsible]");Array.prototype.forEach.call(e,function(e){new i.a.Event.MatchMedia("(min-width: 1220px)",new i.a.Event.Listener(e.previousElementSibling,"click",new i.a.Nav.Collapse(e)))}),new i.a.Event.MatchMedia("(max-width: 1219px)",new i.a.Event.Listener("[data-md-component=navigation] [data-md-toggle]","change",new i.a.Nav.Scrolling("[data-md-component=navigation] nav"))),document.querySelector("[data-md-component=search]")&&(new i.a.Event.MatchMedia("(max-width: 959px)",new i.a.Event.Listener("[data-md-toggle=search]","change",new i.a.Search.Lock("[data-md-toggle=search]"))),new i.a.Event.Listener("[data-md-component=query]",["focus","keyup","change"],new i.a.Search.Result("[data-md-component=result]",function(){return fetch(t.url.base+"/search/search_index.json",{credentials:"same-origin"}).then(function(e){return e.json()}).then(function(e){return e.docs.map(function(e){return e.location=t.url.base+"/"+e.location,e})})})).listen(),new i.a.Event.Listener("[data-md-component=reset]","click",function(){setTimeout(function(){var e=document.querySelector("[data-md-component=query]");if(!(e instanceof HTMLInputElement))throw new ReferenceError;e.focus()},10)}).listen(),new i.a.Event.Listener("[data-md-toggle=search]","change",function(e){setTimeout(function(e){if(!(e instanceof HTMLInputElement))throw new ReferenceError;if(e.checked){var t=document.querySelector("[data-md-component=query]");if(!(t instanceof HTMLInputElement))throw new ReferenceError;t.focus()}},400,e.target)}).listen(),new i.a.Event.Listener("[data-md-component=query]","focus",function(){var e=document.querySelector("[data-md-toggle=search]");if(!(e instanceof HTMLInputElement))throw new ReferenceError;e.checked||(e.checked=!0,e.dispatchEvent(new CustomEvent("change")))}).listen(),new i.a.Event.Listener(window,"keydown",function(e){var t=document.querySelector("[data-md-toggle=search]");if(!(t instanceof HTMLInputElement))throw new ReferenceError;var n=document.querySelector("[data-md-component=query]");if(!(n instanceof HTMLInputElement))throw new ReferenceError;if(!(document.activeElement instanceof HTMLElement&&document.activeElement.isContentEditable||e.metaKey||e.ctrlKey))if(t.checked){if(13===e.keyCode){if(n===document.activeElement){e.preventDefault();var r=document.querySelector("[data-md-component=search] [href][data-md-state=active]");r instanceof HTMLLinkElement&&(window.location=r.getAttribute("href"),t.checked=!1,t.dispatchEvent(new CustomEvent("change")),n.blur())}}else if(9===e.keyCode||27===e.keyCode)t.checked=!1,t.dispatchEvent(new CustomEvent("change")),n.blur();else if(-1!==[8,37,39].indexOf(e.keyCode))n!==document.activeElement&&n.focus();else if(-1!==[38,40].indexOf(e.keyCode)){var i=e.keyCode,o=Array.prototype.slice.call(document.querySelectorAll("[data-md-component=query], [data-md-component=search] [href]")),a=o.find(function(e){if(!(e instanceof HTMLElement))throw new ReferenceError;return"active"===e.dataset.mdState});a&&(a.dataset.mdState="");var s=Math.max(0,(o.indexOf(a)+o.length+(38===i?-1:1))%o.length);return o[s]&&(o[s].dataset.mdState="active",o[s].focus()),e.preventDefault(),e.stopPropagation(),!1}}else if(document.activeElement&&!document.activeElement.form){if("TEXTAREA"===document.activeElement.tagName||"INPUT"===document.activeElement.tagName)return;70!==e.keyCode&&83!==e.keyCode||(n.focus(),e.preventDefault())}}).listen(),new i.a.Event.Listener(window,"keypress",function(){var e=document.querySelector("[data-md-toggle=search]");if(!(e instanceof HTMLInputElement))throw new ReferenceError;if(e.checked){var t=document.querySelector("[data-md-component=query]");if(!(t instanceof HTMLInputElement))throw new ReferenceError;t!==document.activeElement&&t.focus()}}).listen()),new i.a.Event.Listener(document.body,"keydown",function(e){if(9===e.keyCode){var t=document.querySelectorAll("[data-md-component=navigation] .md-nav__link[for]:not([tabindex])");Array.prototype.forEach.call(t,function(e){e.offsetHeight&&(e.tabIndex=0)})}}).listen(),new i.a.Event.Listener(document.body,"mousedown",function(){var e=document.querySelectorAll("[data-md-component=navigation] .md-nav__link[tabindex]");Array.prototype.forEach.call(e,function(e){e.removeAttribute("tabIndex")})}).listen(),document.body.addEventListener("click",function(){"tabbing"===document.body.dataset.mdState&&(document.body.dataset.mdState="")}),new i.a.Event.MatchMedia("(max-width: 959px)",new i.a.Event.Listener("[data-md-component=navigation] [href^='#']","click",function(){var e=document.querySelector("[data-md-toggle=drawer]");if(!(e instanceof HTMLInputElement))throw new ReferenceError;e.checked&&(e.checked=!1,e.dispatchEvent(new CustomEvent("change")))})),function(){var e=document.querySelector("[data-md-source]");if(!e)return r.a.resolve([]);if(!(e instanceof HTMLAnchorElement))throw new ReferenceError;switch(e.dataset.mdSource){case"github":return new i.a.Source.Adapter.GitHub(e).fetch();default:return r.a.resolve([])}}().then(function(t){var e=document.querySelectorAll("[data-md-source]");Array.prototype.forEach.call(e,function(e){new i.a.Source.Repository(e).initialize(t)})});var n=function(){var e=document.querySelectorAll("details");Array.prototype.forEach.call(e,function(e){e.setAttribute("open","")})};new i.a.Event.MatchMedia("print",{listen:n,unlisten:function(){}}),window.onbeforeprint=n}}}.call(this,c(3))},function(e,t,n){"use strict";n.p},function(e,t,n){"use strict";n.p},function(e,t,n){"use strict";n.p},function(e,t,n){"use strict"},function(e,t,n){"use strict"},function(e,t){!function(){if("undefined"!=typeof window)try{var e=new window.CustomEvent("test",{cancelable:!0});if(e.preventDefault(),!0!==e.defaultPrevented)throw new Error("Could not prevent default")}catch(e){var t=function(e,t){var n,r;return(t=t||{}).bubbles=!!t.bubbles,t.cancelable=!!t.cancelable,(n=document.createEvent("CustomEvent")).initCustomEvent(e,t.bubbles,t.cancelable,t.detail),r=n.preventDefault,n.preventDefault=function(){r.call(this);try{Object.defineProperty(this,"defaultPrevented",{get:function(){return!0}})}catch(e){this.defaultPrevented=!0}},n};t.prototype=window.Event.prototype,window.CustomEvent=t}}()},function(e,t,n){window.fetch||(window.fetch=n(7).default||n(7))},function(e,i,o){(function(e){var t=void 0!==e&&e||"undefined"!=typeof self&&self||window,n=Function.prototype.apply;function r(e,t){this._id=e,this._clearFn=t}i.setTimeout=function(){return new r(n.call(setTimeout,t,arguments),clearTimeout)},i.setInterval=function(){return new r(n.call(setInterval,t,arguments),clearInterval)},i.clearTimeout=i.clearInterval=function(e){e&&e.close()},r.prototype.unref=r.prototype.ref=function(){},r.prototype.close=function(){this._clearFn.call(t,this._id)},i.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},i.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},i._unrefActive=i.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;0<=t&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},o(22),i.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,i.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,o(4))},function(e,t,n){(function(e,p){!function(n,r){"use strict";if(!n.setImmediate){var i,o,t,a,e,s=1,c={},l=!1,u=n.document,f=Object.getPrototypeOf&&Object.getPrototypeOf(n);f=f&&f.setTimeout?f:n,i="[object process]"==={}.toString.call(n.process)?function(e){p.nextTick(function(){h(e)})}:function(){if(n.postMessage&&!n.importScripts){var e=!0,t=n.onmessage;return n.onmessage=function(){e=!1},n.postMessage("","*"),n.onmessage=t,e}}()?(a="setImmediate$"+Math.random()+"$",e=function(e){e.source===n&&"string"==typeof e.data&&0===e.data.indexOf(a)&&h(+e.data.slice(a.length))},n.addEventListener?n.addEventListener("message",e,!1):n.attachEvent("onmessage",e),function(e){n.postMessage(a+e,"*")}):n.MessageChannel?((t=new MessageChannel).port1.onmessage=function(e){h(e.data)},function(e){t.port2.postMessage(e)}):u&&"onreadystatechange"in u.createElement("script")?(o=u.documentElement,function(e){var t=u.createElement("script");t.onreadystatechange=function(){h(e),t.onreadystatechange=null,o.removeChild(t),t=null},o.appendChild(t)}):function(e){setTimeout(h,0,e)},f.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n=this.length)return D.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},D.QueryLexer.prototype.width=function(){return this.pos-this.start},D.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},D.QueryLexer.prototype.backup=function(){this.pos-=1},D.QueryLexer.prototype.acceptDigitRun=function(){for(var e,t;47<(t=(e=this.next()).charCodeAt(0))&&t<58;);e!=D.QueryLexer.EOS&&this.backup()},D.QueryLexer.prototype.more=function(){return this.pos=t&&(e=c.limit_backward,c.limit_backward=t,c.ket=c.cursor,c.find_among_b(o,4)?(c.bra=c.cursor,c.limit_backward=e,c.cursor=c.limit-r,c.cursor>c.limit_backward&&(c.cursor--,c.bra=c.cursor,c.slice_del())):c.limit_backward=e)}this.setCurrent=function(e){c.setCurrent(e)},this.getCurrent=function(){return c.getCurrent()},this.stem=function(){var e,r=c.cursor;return function(){var e,r=c.cursor+3;if(t=c.limit,0<=r&&r<=c.limit){for(i=r;;){if(e=c.cursor,c.in_grouping(d,97,248)){c.cursor=e;break}if((c.cursor=e)>=c.limit)return;c.cursor++}for(;!c.out_grouping(d,97,248);){if(c.cursor>=c.limit)return;c.cursor++}(t=c.cursor)=t&&(r=c.limit_backward,c.limit_backward=t,c.ket=c.cursor,e=c.find_among_b(s,32),c.limit_backward=r,e))switch(c.bra=c.cursor,e){case 1:c.slice_del();break;case 2:c.in_grouping_b(u,97,229)&&c.slice_del()}}(),c.cursor=c.limit,l(),c.cursor=c.limit,function(){var e,r,i,n=c.limit-c.cursor;if(c.ket=c.cursor,c.eq_s_b(2,"st")&&(c.bra=c.cursor,c.eq_s_b(2,"ig")&&c.slice_del()),c.cursor=c.limit-n,c.cursor>=t&&(r=c.limit_backward,c.limit_backward=t,c.ket=c.cursor,e=c.find_among_b(a,5),c.limit_backward=r,e))switch(c.bra=c.cursor,e){case 1:c.slice_del(),i=c.limit-c.cursor,l(),c.cursor=c.limit-i;break;case 2:c.slice_from("løs")}}(),c.cursor=c.limit,c.cursor>=t&&(e=c.limit_backward,c.limit_backward=t,c.ket=c.cursor,c.out_grouping_b(d,97,248)?(c.bra=c.cursor,n=c.slice_to(n),c.limit_backward=e,c.eq_v_b(n)&&c.slice_del()):c.limit_backward=e),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}}); \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.de.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.de.js deleted file mode 100644 index 73e55eb09..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.de.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Lunr languages, `German` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var _,p,r;e.de=function(){this.pipeline.reset(),this.pipeline.add(e.de.trimmer,e.de.stopWordFilter,e.de.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.de.stemmer))},e.de.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.de.trimmer=e.trimmerSupport.generateTrimmer(e.de.wordCharacters),e.Pipeline.registerFunction(e.de.trimmer,"trimmer-de"),e.de.stemmer=(_=e.stemmerSupport.Among,p=e.stemmerSupport.SnowballProgram,r=new function(){var r,n,i,s=[new _("",-1,6),new _("U",0,2),new _("Y",0,1),new _("ä",0,3),new _("ö",0,4),new _("ü",0,5)],o=[new _("e",-1,2),new _("em",-1,1),new _("en",-1,2),new _("ern",-1,1),new _("er",-1,1),new _("s",-1,3),new _("es",5,2)],c=[new _("en",-1,1),new _("er",-1,1),new _("st",-1,2),new _("est",2,1)],u=[new _("ig",-1,1),new _("lich",-1,1)],a=[new _("end",-1,1),new _("ig",-1,2),new _("ung",-1,1),new _("lich",-1,3),new _("isch",-1,2),new _("ik",-1,2),new _("heit",-1,3),new _("keit",-1,4)],t=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32,8],d=[117,30,5],l=[117,30,4],m=new p;function h(e,r,n){return!(!m.eq_s(1,e)||(m.ket=m.cursor,!m.in_grouping(t,97,252)))&&(m.slice_from(r),m.cursor=n,!0)}function w(){for(;!m.in_grouping(t,97,252);){if(m.cursor>=m.limit)return!0;m.cursor++}for(;!m.out_grouping(t,97,252);){if(m.cursor>=m.limit)return!0;m.cursor++}return!1}function f(){return i<=m.cursor}function b(){return n<=m.cursor}this.setCurrent=function(e){m.setCurrent(e)},this.getCurrent=function(){return m.getCurrent()},this.stem=function(){var e=m.cursor;return function(){for(var e,r,n,i,s=m.cursor;;)if(e=m.cursor,m.bra=e,m.eq_s(1,"ß"))m.ket=m.cursor,m.slice_from("ss");else{if(e>=m.limit)break;m.cursor=e+1}for(m.cursor=s;;)for(r=m.cursor;;){if(n=m.cursor,m.in_grouping(t,97,252)){if(i=m.cursor,m.bra=i,h("u","U",n))break;if(m.cursor=i,h("y","Y",n))break}if(n>=m.limit)return m.cursor=r;m.cursor=n+1}}(),m.cursor=e,function(){i=m.limit,n=i;var e=m.cursor+3;0<=e&&e<=m.limit&&(r=e,w()||((i=m.cursor)=m.limit)return;m.cursor++}}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return r.setCurrent(e),r.stem(),r.getCurrent()}):(r.setCurrent(e),r.stem(),r.getCurrent())}),e.Pipeline.registerFunction(e.de.stemmer,"stemmer-de"),e.de.stopWordFilter=e.generateStopWordFilter("aber alle allem allen aller alles als also am an ander andere anderem anderen anderer anderes anderm andern anderr anders auch auf aus bei bin bis bist da damit dann das dasselbe dazu daß dein deine deinem deinen deiner deines dem demselben den denn denselben der derer derselbe derselben des desselben dessen dich die dies diese dieselbe dieselben diesem diesen dieser dieses dir doch dort du durch ein eine einem einen einer eines einig einige einigem einigen einiger einiges einmal er es etwas euch euer eure eurem euren eurer eures für gegen gewesen hab habe haben hat hatte hatten hier hin hinter ich ihm ihn ihnen ihr ihre ihrem ihren ihrer ihres im in indem ins ist jede jedem jeden jeder jedes jene jenem jenen jener jenes jetzt kann kein keine keinem keinen keiner keines können könnte machen man manche manchem manchen mancher manches mein meine meinem meinen meiner meines mich mir mit muss musste nach nicht nichts noch nun nur ob oder ohne sehr sein seine seinem seinen seiner seines selbst sich sie sind so solche solchem solchen solcher solches soll sollte sondern sonst um und uns unse unsem unsen unser unses unter viel vom von vor war waren warst was weg weil weiter welche welchem welchen welcher welches wenn werde werden wie wieder will wir wird wirst wo wollen wollte während würde würden zu zum zur zwar zwischen über".split(" ")),e.Pipeline.registerFunction(e.de.stopWordFilter,"stopWordFilter-de")}}); \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.du.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.du.js deleted file mode 100644 index e9c672998..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.du.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Lunr languages, `Dutch` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var v,q,r;console.warn('[Lunr Languages] Please use the "nl" instead of the "du". The "nl" code is the standard code for Dutch language, and "du" will be removed in the next major versions.'),e.du=function(){this.pipeline.reset(),this.pipeline.add(e.du.trimmer,e.du.stopWordFilter,e.du.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.du.stemmer))},e.du.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.du.trimmer=e.trimmerSupport.generateTrimmer(e.du.wordCharacters),e.Pipeline.registerFunction(e.du.trimmer,"trimmer-du"),e.du.stemmer=(v=e.stemmerSupport.Among,q=e.stemmerSupport.SnowballProgram,r=new function(){var r,i,u,o=[new v("",-1,6),new v("á",0,1),new v("ä",0,1),new v("é",0,2),new v("ë",0,2),new v("í",0,3),new v("ï",0,3),new v("ó",0,4),new v("ö",0,4),new v("ú",0,5),new v("ü",0,5)],n=[new v("",-1,3),new v("I",0,2),new v("Y",0,1)],t=[new v("dd",-1,-1),new v("kk",-1,-1),new v("tt",-1,-1)],c=[new v("ene",-1,2),new v("se",-1,3),new v("en",-1,2),new v("heden",2,1),new v("s",-1,3)],a=[new v("end",-1,1),new v("ig",-1,2),new v("ing",-1,1),new v("lijk",-1,3),new v("baar",-1,4),new v("bar",-1,5)],l=[new v("aa",-1,-1),new v("ee",-1,-1),new v("oo",-1,-1),new v("uu",-1,-1)],m=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],d=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],f=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],_=new q;function s(e){return(_.cursor=e)>=_.limit||(_.cursor++,!1)}function w(){for(;!_.in_grouping(m,97,232);){if(_.cursor>=_.limit)return!0;_.cursor++}for(;!_.out_grouping(m,97,232);){if(_.cursor>=_.limit)return!0;_.cursor++}return!1}function b(){return i<=_.cursor}function p(){return r<=_.cursor}function g(){var e=_.limit-_.cursor;_.find_among_b(t,3)&&(_.cursor=_.limit-e,_.ket=_.cursor,_.cursor>_.limit_backward&&(_.cursor--,_.bra=_.cursor,_.slice_del()))}function h(){var e;u=!1,_.ket=_.cursor,_.eq_s_b(1,"e")&&(_.bra=_.cursor,b()&&(e=_.limit-_.cursor,_.out_grouping_b(m,97,232)&&(_.cursor=_.limit-e,_.slice_del(),u=!0,g())))}function k(){var e;b()&&(e=_.limit-_.cursor,_.out_grouping_b(m,97,232)&&(_.cursor=_.limit-e,_.eq_s_b(3,"gem")||(_.cursor=_.limit-e,_.slice_del(),g())))}this.setCurrent=function(e){_.setCurrent(e)},this.getCurrent=function(){return _.getCurrent()},this.stem=function(){var e=_.cursor;return function(){for(var e,r,i,n=_.cursor;;){if(_.bra=_.cursor,e=_.find_among(o,11))switch(_.ket=_.cursor,e){case 1:_.slice_from("a");continue;case 2:_.slice_from("e");continue;case 3:_.slice_from("i");continue;case 4:_.slice_from("o");continue;case 5:_.slice_from("u");continue;case 6:if(_.cursor>=_.limit)break;_.cursor++;continue}break}for(_.cursor=n,_.bra=n,_.eq_s(1,"y")?(_.ket=_.cursor,_.slice_from("Y")):_.cursor=n;;)if(r=_.cursor,_.in_grouping(m,97,232)){if(i=_.cursor,_.bra=i,_.eq_s(1,"i"))_.ket=_.cursor,_.in_grouping(m,97,232)&&(_.slice_from("I"),_.cursor=r);else if(_.cursor=i,_.eq_s(1,"y"))_.ket=_.cursor,_.slice_from("Y"),_.cursor=r;else if(s(r))break}else if(s(r))break}(),_.cursor=e,i=_.limit,r=i,w()||((i=_.cursor)<3&&(i=3),w()||(r=_.cursor)),_.limit_backward=e,_.cursor=_.limit,function(){var e,r,i,n,o,t,s=_.limit-_.cursor;if(_.ket=_.cursor,e=_.find_among_b(c,5))switch(_.bra=_.cursor,e){case 1:b()&&_.slice_from("heid");break;case 2:k();break;case 3:b()&&_.out_grouping_b(f,97,232)&&_.slice_del()}if(_.cursor=_.limit-s,h(),_.cursor=_.limit-s,_.ket=_.cursor,_.eq_s_b(4,"heid")&&(_.bra=_.cursor,p()&&(r=_.limit-_.cursor,_.eq_s_b(1,"c")||(_.cursor=_.limit-r,_.slice_del(),_.ket=_.cursor,_.eq_s_b(2,"en")&&(_.bra=_.cursor,k())))),_.cursor=_.limit-s,_.ket=_.cursor,e=_.find_among_b(a,6))switch(_.bra=_.cursor,e){case 1:if(p()){if(_.slice_del(),i=_.limit-_.cursor,_.ket=_.cursor,_.eq_s_b(2,"ig")&&(_.bra=_.cursor,p()&&(n=_.limit-_.cursor,!_.eq_s_b(1,"e")))){_.cursor=_.limit-n,_.slice_del();break}_.cursor=_.limit-i,g()}break;case 2:p()&&(o=_.limit-_.cursor,_.eq_s_b(1,"e")||(_.cursor=_.limit-o,_.slice_del()));break;case 3:p()&&(_.slice_del(),h());break;case 4:p()&&_.slice_del();break;case 5:p()&&u&&_.slice_del()}_.cursor=_.limit-s,_.out_grouping_b(d,73,232)&&(t=_.limit-_.cursor,_.find_among_b(l,4)&&_.out_grouping_b(m,97,232)&&(_.cursor=_.limit-t,_.ket=_.cursor,_.cursor>_.limit_backward&&(_.cursor--,_.bra=_.cursor,_.slice_del())))}(),_.cursor=_.limit_backward,function(){for(var e;;)if(_.bra=_.cursor,e=_.find_among(n,3))switch(_.ket=_.cursor,e){case 1:_.slice_from("y");break;case 2:_.slice_from("i");break;case 3:if(_.cursor>=_.limit)return;_.cursor++}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return r.setCurrent(e),r.stem(),r.getCurrent()}):(r.setCurrent(e),r.stem(),r.getCurrent())}),e.Pipeline.registerFunction(e.du.stemmer,"stemmer-du"),e.du.stopWordFilter=e.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),e.Pipeline.registerFunction(e.du.stopWordFilter,"stopWordFilter-du")}}); \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.es.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.es.js deleted file mode 100644 index 2918bd19e..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.es.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Lunr languages, `Spanish` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ -!function(e,s){"function"==typeof define&&define.amd?define(s):"object"==typeof exports?module.exports=s():s()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var C,P,s;e.es=function(){this.pipeline.reset(),this.pipeline.add(e.es.trimmer,e.es.stopWordFilter,e.es.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.es.stemmer))},e.es.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.es.trimmer=e.trimmerSupport.generateTrimmer(e.es.wordCharacters),e.Pipeline.registerFunction(e.es.trimmer,"trimmer-es"),e.es.stemmer=(C=e.stemmerSupport.Among,P=e.stemmerSupport.SnowballProgram,s=new function(){var r,n,i,a=[new C("",-1,6),new C("á",0,1),new C("é",0,2),new C("í",0,3),new C("ó",0,4),new C("ú",0,5)],t=[new C("la",-1,-1),new C("sela",0,-1),new C("le",-1,-1),new C("me",-1,-1),new C("se",-1,-1),new C("lo",-1,-1),new C("selo",5,-1),new C("las",-1,-1),new C("selas",7,-1),new C("les",-1,-1),new C("los",-1,-1),new C("selos",10,-1),new C("nos",-1,-1)],o=[new C("ando",-1,6),new C("iendo",-1,6),new C("yendo",-1,7),new C("ándo",-1,2),new C("iéndo",-1,1),new C("ar",-1,6),new C("er",-1,6),new C("ir",-1,6),new C("ár",-1,3),new C("ér",-1,4),new C("ír",-1,5)],s=[new C("ic",-1,-1),new C("ad",-1,-1),new C("os",-1,-1),new C("iv",-1,1)],u=[new C("able",-1,1),new C("ible",-1,1),new C("ante",-1,1)],w=[new C("ic",-1,1),new C("abil",-1,1),new C("iv",-1,1)],c=[new C("ica",-1,1),new C("ancia",-1,2),new C("encia",-1,5),new C("adora",-1,2),new C("osa",-1,1),new C("ista",-1,1),new C("iva",-1,9),new C("anza",-1,1),new C("logía",-1,3),new C("idad",-1,8),new C("able",-1,1),new C("ible",-1,1),new C("ante",-1,2),new C("mente",-1,7),new C("amente",13,6),new C("ación",-1,2),new C("ución",-1,4),new C("ico",-1,1),new C("ismo",-1,1),new C("oso",-1,1),new C("amiento",-1,1),new C("imiento",-1,1),new C("ivo",-1,9),new C("ador",-1,2),new C("icas",-1,1),new C("ancias",-1,2),new C("encias",-1,5),new C("adoras",-1,2),new C("osas",-1,1),new C("istas",-1,1),new C("ivas",-1,9),new C("anzas",-1,1),new C("logías",-1,3),new C("idades",-1,8),new C("ables",-1,1),new C("ibles",-1,1),new C("aciones",-1,2),new C("uciones",-1,4),new C("adores",-1,2),new C("antes",-1,2),new C("icos",-1,1),new C("ismos",-1,1),new C("osos",-1,1),new C("amientos",-1,1),new C("imientos",-1,1),new C("ivos",-1,9)],m=[new C("ya",-1,1),new C("ye",-1,1),new C("yan",-1,1),new C("yen",-1,1),new C("yeron",-1,1),new C("yendo",-1,1),new C("yo",-1,1),new C("yas",-1,1),new C("yes",-1,1),new C("yais",-1,1),new C("yamos",-1,1),new C("yó",-1,1)],l=[new C("aba",-1,2),new C("ada",-1,2),new C("ida",-1,2),new C("ara",-1,2),new C("iera",-1,2),new C("ía",-1,2),new C("aría",5,2),new C("ería",5,2),new C("iría",5,2),new C("ad",-1,2),new C("ed",-1,2),new C("id",-1,2),new C("ase",-1,2),new C("iese",-1,2),new C("aste",-1,2),new C("iste",-1,2),new C("an",-1,2),new C("aban",16,2),new C("aran",16,2),new C("ieran",16,2),new C("ían",16,2),new C("arían",20,2),new C("erían",20,2),new C("irían",20,2),new C("en",-1,1),new C("asen",24,2),new C("iesen",24,2),new C("aron",-1,2),new C("ieron",-1,2),new C("arán",-1,2),new C("erán",-1,2),new C("irán",-1,2),new C("ado",-1,2),new C("ido",-1,2),new C("ando",-1,2),new C("iendo",-1,2),new C("ar",-1,2),new C("er",-1,2),new C("ir",-1,2),new C("as",-1,2),new C("abas",39,2),new C("adas",39,2),new C("idas",39,2),new C("aras",39,2),new C("ieras",39,2),new C("ías",39,2),new C("arías",45,2),new C("erías",45,2),new C("irías",45,2),new C("es",-1,1),new C("ases",49,2),new C("ieses",49,2),new C("abais",-1,2),new C("arais",-1,2),new C("ierais",-1,2),new C("íais",-1,2),new C("aríais",55,2),new C("eríais",55,2),new C("iríais",55,2),new C("aseis",-1,2),new C("ieseis",-1,2),new C("asteis",-1,2),new C("isteis",-1,2),new C("áis",-1,2),new C("éis",-1,1),new C("aréis",64,2),new C("eréis",64,2),new C("iréis",64,2),new C("ados",-1,2),new C("idos",-1,2),new C("amos",-1,2),new C("ábamos",70,2),new C("áramos",70,2),new C("iéramos",70,2),new C("íamos",70,2),new C("aríamos",74,2),new C("eríamos",74,2),new C("iríamos",74,2),new C("emos",-1,1),new C("aremos",78,2),new C("eremos",78,2),new C("iremos",78,2),new C("ásemos",78,2),new C("iésemos",78,2),new C("imos",-1,2),new C("arás",-1,2),new C("erás",-1,2),new C("irás",-1,2),new C("ís",-1,2),new C("ará",-1,2),new C("erá",-1,2),new C("irá",-1,2),new C("aré",-1,2),new C("eré",-1,2),new C("iré",-1,2),new C("ió",-1,2)],d=[new C("a",-1,1),new C("e",-1,2),new C("o",-1,1),new C("os",-1,1),new C("á",-1,1),new C("é",-1,2),new C("í",-1,1),new C("ó",-1,1)],b=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,4,10],f=new P;function _(){if(f.out_grouping(b,97,252)){for(;!f.in_grouping(b,97,252);){if(f.cursor>=f.limit)return!0;f.cursor++}return!1}return!0}function h(){var e,s=f.cursor;if(function(){if(f.in_grouping(b,97,252)){var e=f.cursor;if(_()){if(f.cursor=e,!f.in_grouping(b,97,252))return!0;for(;!f.out_grouping(b,97,252);){if(f.cursor>=f.limit)return!0;f.cursor++}}return!1}return!0}()){if(f.cursor=s,!f.out_grouping(b,97,252))return;if(e=f.cursor,_()){if(f.cursor=e,!f.in_grouping(b,97,252)||f.cursor>=f.limit)return;f.cursor++}}i=f.cursor}function v(){for(;!f.in_grouping(b,97,252);){if(f.cursor>=f.limit)return!1;f.cursor++}for(;!f.out_grouping(b,97,252);){if(f.cursor>=f.limit)return!1;f.cursor++}return!0}function p(){return i<=f.cursor}function g(){return r<=f.cursor}function k(e,s){if(!g())return!0;f.slice_del(),f.ket=f.cursor;var r=f.find_among_b(e,s);return r&&(f.bra=f.cursor,1==r&&g()&&f.slice_del()),!1}function y(e){return!g()||(f.slice_del(),f.ket=f.cursor,f.eq_s_b(2,e)&&(f.bra=f.cursor,g()&&f.slice_del()),!1)}function q(){var e;if(f.ket=f.cursor,e=f.find_among_b(c,46)){switch(f.bra=f.cursor,e){case 1:if(!g())return!1;f.slice_del();break;case 2:if(y("ic"))return!1;break;case 3:if(!g())return!1;f.slice_from("log");break;case 4:if(!g())return!1;f.slice_from("u");break;case 5:if(!g())return!1;f.slice_from("ente");break;case 6:if(!(n<=f.cursor))return!1;f.slice_del(),f.ket=f.cursor,(e=f.find_among_b(s,4))&&(f.bra=f.cursor,g()&&(f.slice_del(),1==e&&(f.ket=f.cursor,f.eq_s_b(2,"at")&&(f.bra=f.cursor,g()&&f.slice_del()))));break;case 7:if(k(u,3))return!1;break;case 8:if(k(w,3))return!1;break;case 9:if(y("at"))return!1}return!0}return!1}this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var e,s=f.cursor;return e=f.cursor,i=f.limit,r=n=i,h(),f.cursor=e,v()&&(n=f.cursor,v()&&(r=f.cursor)),f.limit_backward=s,f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,f.find_among_b(t,13)&&(f.bra=f.cursor,(e=f.find_among_b(o,11))&&p()))switch(e){case 1:f.bra=f.cursor,f.slice_from("iendo");break;case 2:f.bra=f.cursor,f.slice_from("ando");break;case 3:f.bra=f.cursor,f.slice_from("ar");break;case 4:f.bra=f.cursor,f.slice_from("er");break;case 5:f.bra=f.cursor,f.slice_from("ir");break;case 6:f.slice_del();break;case 7:f.eq_s_b(1,"u")&&f.slice_del()}}(),f.cursor=f.limit,q()||(f.cursor=f.limit,function(){var e,s;if(f.cursor>=i&&(s=f.limit_backward,f.limit_backward=i,f.ket=f.cursor,e=f.find_among_b(m,12),f.limit_backward=s,e)){if(f.bra=f.cursor,1==e){if(!f.eq_s_b(1,"u"))return!1;f.slice_del()}return!0}return!1}()||(f.cursor=f.limit,function(){var e,s,r,n;if(f.cursor>=i&&(s=f.limit_backward,f.limit_backward=i,f.ket=f.cursor,e=f.find_among_b(l,96),f.limit_backward=s,e))switch(f.bra=f.cursor,e){case 1:r=f.limit-f.cursor,f.eq_s_b(1,"u")?(n=f.limit-f.cursor,f.eq_s_b(1,"g")?f.cursor=f.limit-n:f.cursor=f.limit-r):f.cursor=f.limit-r,f.bra=f.cursor;case 2:f.slice_del()}}())),f.cursor=f.limit,function(){var e,s;if(f.ket=f.cursor,e=f.find_among_b(d,8))switch(f.bra=f.cursor,e){case 1:p()&&f.slice_del();break;case 2:p()&&(f.slice_del(),f.ket=f.cursor,f.eq_s_b(1,"u")&&(f.bra=f.cursor,s=f.limit-f.cursor,f.eq_s_b(1,"g")&&(f.cursor=f.limit-s,p()&&f.slice_del())))}}(),f.cursor=f.limit_backward,function(){for(var e;;){if(f.bra=f.cursor,e=f.find_among(a,6))switch(f.ket=f.cursor,e){case 1:f.slice_from("a");continue;case 2:f.slice_from("e");continue;case 3:f.slice_from("i");continue;case 4:f.slice_from("o");continue;case 5:f.slice_from("u");continue;case 6:if(f.cursor>=f.limit)break;f.cursor++;continue}break}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return s.setCurrent(e),s.stem(),s.getCurrent()}):(s.setCurrent(e),s.stem(),s.getCurrent())}),e.Pipeline.registerFunction(e.es.stemmer,"stemmer-es"),e.es.stopWordFilter=e.generateStopWordFilter("a al algo algunas algunos ante antes como con contra cual cuando de del desde donde durante e el ella ellas ellos en entre era erais eran eras eres es esa esas ese eso esos esta estaba estabais estaban estabas estad estada estadas estado estados estamos estando estar estaremos estará estarán estarás estaré estaréis estaría estaríais estaríamos estarían estarías estas este estemos esto estos estoy estuve estuviera estuvierais estuvieran estuvieras estuvieron estuviese estuvieseis estuviesen estuvieses estuvimos estuviste estuvisteis estuviéramos estuviésemos estuvo está estábamos estáis están estás esté estéis estén estés fue fuera fuerais fueran fueras fueron fuese fueseis fuesen fueses fui fuimos fuiste fuisteis fuéramos fuésemos ha habida habidas habido habidos habiendo habremos habrá habrán habrás habré habréis habría habríais habríamos habrían habrías habéis había habíais habíamos habían habías han has hasta hay haya hayamos hayan hayas hayáis he hemos hube hubiera hubierais hubieran hubieras hubieron hubiese hubieseis hubiesen hubieses hubimos hubiste hubisteis hubiéramos hubiésemos hubo la las le les lo los me mi mis mucho muchos muy más mí mía mías mío míos nada ni no nos nosotras nosotros nuestra nuestras nuestro nuestros o os otra otras otro otros para pero poco por porque que quien quienes qué se sea seamos sean seas seremos será serán serás seré seréis sería seríais seríamos serían serías seáis sido siendo sin sobre sois somos son soy su sus suya suyas suyo suyos sí también tanto te tendremos tendrá tendrán tendrás tendré tendréis tendría tendríais tendríamos tendrían tendrías tened tenemos tenga tengamos tengan tengas tengo tengáis tenida tenidas tenido tenidos teniendo tenéis tenía teníais teníamos tenían tenías ti tiene tienen tienes todo todos tu tus tuve tuviera tuvierais tuvieran tuvieras tuvieron tuviese tuvieseis tuviesen tuvieses tuvimos tuviste tuvisteis tuviéramos tuviésemos tuvo tuya tuyas tuyo tuyos tú un una uno unos vosotras vosotros vuestra vuestras vuestro vuestros y ya yo él éramos".split(" ")),e.Pipeline.registerFunction(e.es.stopWordFilter,"stopWordFilter-es")}}); \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.fi.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.fi.js deleted file mode 100644 index f34d10e0d..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.fi.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Lunr languages, `Finnish` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ -!function(i,e){"function"==typeof define&&define.amd?define(e):"object"==typeof exports?module.exports=e():e()(i.lunr)}(this,function(){return function(i){if(void 0===i)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===i.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var v,C,e;i.fi=function(){this.pipeline.reset(),this.pipeline.add(i.fi.trimmer,i.fi.stopWordFilter,i.fi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(i.fi.stemmer))},i.fi.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",i.fi.trimmer=i.trimmerSupport.generateTrimmer(i.fi.wordCharacters),i.Pipeline.registerFunction(i.fi.trimmer,"trimmer-fi"),i.fi.stemmer=(v=i.stemmerSupport.Among,C=i.stemmerSupport.SnowballProgram,e=new function(){var n,t,l,o,r=[new v("pa",-1,1),new v("sti",-1,2),new v("kaan",-1,1),new v("han",-1,1),new v("kin",-1,1),new v("hän",-1,1),new v("kään",-1,1),new v("ko",-1,1),new v("pä",-1,1),new v("kö",-1,1)],s=[new v("lla",-1,-1),new v("na",-1,-1),new v("ssa",-1,-1),new v("ta",-1,-1),new v("lta",3,-1),new v("sta",3,-1)],a=[new v("llä",-1,-1),new v("nä",-1,-1),new v("ssä",-1,-1),new v("tä",-1,-1),new v("ltä",3,-1),new v("stä",3,-1)],u=[new v("lle",-1,-1),new v("ine",-1,-1)],c=[new v("nsa",-1,3),new v("mme",-1,3),new v("nne",-1,3),new v("ni",-1,2),new v("si",-1,1),new v("an",-1,4),new v("en",-1,6),new v("än",-1,5),new v("nsä",-1,3)],i=[new v("aa",-1,-1),new v("ee",-1,-1),new v("ii",-1,-1),new v("oo",-1,-1),new v("uu",-1,-1),new v("ää",-1,-1),new v("öö",-1,-1)],m=[new v("a",-1,8),new v("lla",0,-1),new v("na",0,-1),new v("ssa",0,-1),new v("ta",0,-1),new v("lta",4,-1),new v("sta",4,-1),new v("tta",4,9),new v("lle",-1,-1),new v("ine",-1,-1),new v("ksi",-1,-1),new v("n",-1,7),new v("han",11,1),new v("den",11,-1,q),new v("seen",11,-1,j),new v("hen",11,2),new v("tten",11,-1,q),new v("hin",11,3),new v("siin",11,-1,q),new v("hon",11,4),new v("hän",11,5),new v("hön",11,6),new v("ä",-1,8),new v("llä",22,-1),new v("nä",22,-1),new v("ssä",22,-1),new v("tä",22,-1),new v("ltä",26,-1),new v("stä",26,-1),new v("ttä",26,9)],w=[new v("eja",-1,-1),new v("mma",-1,1),new v("imma",1,-1),new v("mpa",-1,1),new v("impa",3,-1),new v("mmi",-1,1),new v("immi",5,-1),new v("mpi",-1,1),new v("impi",7,-1),new v("ejä",-1,-1),new v("mmä",-1,1),new v("immä",10,-1),new v("mpä",-1,1),new v("impä",12,-1)],_=[new v("i",-1,-1),new v("j",-1,-1)],k=[new v("mma",-1,1),new v("imma",0,-1)],b=[17,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],e=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],f=[17,97,24,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],h=new C;function p(){for(var i;i=h.cursor,!h.in_grouping(d,97,246);){if((h.cursor=i)>=h.limit)return!0;h.cursor++}for(h.cursor=i;!h.out_grouping(d,97,246);){if(h.cursor>=h.limit)return!0;h.cursor++}return!1}function g(){var i,e;if(h.cursor>=o)if(e=h.limit_backward,h.limit_backward=o,h.ket=h.cursor,i=h.find_among_b(r,10)){switch(h.bra=h.cursor,h.limit_backward=e,i){case 1:if(!h.in_grouping_b(f,97,246))return;break;case 2:if(!(l<=h.cursor))return}h.slice_del()}else h.limit_backward=e}function j(){return h.find_among_b(i,7)}function q(){return h.eq_s_b(1,"i")&&h.in_grouping_b(e,97,246)}this.setCurrent=function(i){h.setCurrent(i)},this.getCurrent=function(){return h.getCurrent()},this.stem=function(){var i,e=h.cursor;return o=h.limit,l=o,p()||(o=h.cursor,p()||(l=h.cursor)),n=!1,h.limit_backward=e,h.cursor=h.limit,g(),h.cursor=h.limit,function(){var i,e,r;if(h.cursor>=o)if(e=h.limit_backward,h.limit_backward=o,h.ket=h.cursor,i=h.find_among_b(c,9))switch(h.bra=h.cursor,h.limit_backward=e,i){case 1:r=h.limit-h.cursor,h.eq_s_b(1,"k")||(h.cursor=h.limit-r,h.slice_del());break;case 2:h.slice_del(),h.ket=h.cursor,h.eq_s_b(3,"kse")&&(h.bra=h.cursor,h.slice_from("ksi"));break;case 3:h.slice_del();break;case 4:h.find_among_b(s,6)&&h.slice_del();break;case 5:h.find_among_b(a,6)&&h.slice_del();break;case 6:h.find_among_b(u,2)&&h.slice_del()}else h.limit_backward=e}(),h.cursor=h.limit,function(){var i,e,r;if(h.cursor>=o)if(e=h.limit_backward,h.limit_backward=o,h.ket=h.cursor,i=h.find_among_b(m,30)){switch(h.bra=h.cursor,h.limit_backward=e,i){case 1:if(!h.eq_s_b(1,"a"))return;break;case 2:case 9:if(!h.eq_s_b(1,"e"))return;break;case 3:if(!h.eq_s_b(1,"i"))return;break;case 4:if(!h.eq_s_b(1,"o"))return;break;case 5:if(!h.eq_s_b(1,"ä"))return;break;case 6:if(!h.eq_s_b(1,"ö"))return;break;case 7:if(r=h.limit-h.cursor,!j()&&(h.cursor=h.limit-r,!h.eq_s_b(2,"ie"))){h.cursor=h.limit-r;break}if(h.cursor=h.limit-r,h.cursor<=h.limit_backward){h.cursor=h.limit-r;break}h.cursor--,h.bra=h.cursor;break;case 8:if(!h.in_grouping_b(d,97,246)||!h.out_grouping_b(d,97,246))return}h.slice_del(),n=!0}else h.limit_backward=e}(),h.cursor=h.limit,function(){var i,e,r;if(h.cursor>=l)if(e=h.limit_backward,h.limit_backward=l,h.ket=h.cursor,i=h.find_among_b(w,14)){if(h.bra=h.cursor,h.limit_backward=e,1==i){if(r=h.limit-h.cursor,h.eq_s_b(2,"po"))return;h.cursor=h.limit-r}h.slice_del()}else h.limit_backward=e}(),h.cursor=h.limit,h.cursor=(n?h.cursor>=o&&(i=h.limit_backward,h.limit_backward=o,h.ket=h.cursor,h.find_among_b(_,2)?(h.bra=h.cursor,h.limit_backward=i,h.slice_del()):h.limit_backward=i):(h.cursor=h.limit,function(){var i,e,r,n,t,s;if(h.cursor>=o){if(e=h.limit_backward,h.limit_backward=o,h.ket=h.cursor,h.eq_s_b(1,"t")&&(h.bra=h.cursor,r=h.limit-h.cursor,h.in_grouping_b(d,97,246)&&(h.cursor=h.limit-r,h.slice_del(),h.limit_backward=e,n=h.limit-h.cursor,h.cursor>=l&&(h.cursor=l,t=h.limit_backward,h.limit_backward=h.cursor,h.cursor=h.limit-n,h.ket=h.cursor,i=h.find_among_b(k,2))))){if(h.bra=h.cursor,h.limit_backward=t,1==i){if(s=h.limit-h.cursor,h.eq_s_b(2,"po"))return;h.cursor=h.limit-s}return h.slice_del()}h.limit_backward=e}}()),h.limit),function(){var i,e,r,n;if(h.cursor>=o){for(i=h.limit_backward,h.limit_backward=o,e=h.limit-h.cursor,j()&&(h.cursor=h.limit-e,h.ket=h.cursor,h.cursor>h.limit_backward&&(h.cursor--,h.bra=h.cursor,h.slice_del())),h.cursor=h.limit-e,h.ket=h.cursor,h.in_grouping_b(b,97,228)&&(h.bra=h.cursor,h.out_grouping_b(d,97,246)&&h.slice_del()),h.cursor=h.limit-e,h.ket=h.cursor,h.eq_s_b(1,"j")&&(h.bra=h.cursor,r=h.limit-h.cursor,h.eq_s_b(1,"o")?h.slice_del():(h.cursor=h.limit-r,h.eq_s_b(1,"u")&&h.slice_del())),h.cursor=h.limit-e,h.ket=h.cursor,h.eq_s_b(1,"o")&&(h.bra=h.cursor,h.eq_s_b(1,"j")&&h.slice_del()),h.cursor=h.limit-e,h.limit_backward=i;;){if(n=h.limit-h.cursor,h.out_grouping_b(d,97,246)){h.cursor=h.limit-n;break}if(h.cursor=h.limit-n,h.cursor<=h.limit_backward)return;h.cursor--}h.ket=h.cursor,h.cursor>h.limit_backward&&(h.cursor--,h.bra=h.cursor,t=h.slice_to(),h.eq_v_b(t)&&h.slice_del())}}(),!0}},function(i){return"function"==typeof i.update?i.update(function(i){return e.setCurrent(i),e.stem(),e.getCurrent()}):(e.setCurrent(i),e.stem(),e.getCurrent())}),i.Pipeline.registerFunction(i.fi.stemmer,"stemmer-fi"),i.fi.stopWordFilter=i.generateStopWordFilter("ei eivät emme en et ette että he heidän heidät heihin heille heillä heiltä heissä heistä heitä hän häneen hänelle hänellä häneltä hänen hänessä hänestä hänet häntä itse ja johon joiden joihin joiksi joilla joille joilta joina joissa joista joita joka joksi jolla jolle jolta jona jonka jos jossa josta jota jotka kanssa keiden keihin keiksi keille keillä keiltä keinä keissä keistä keitä keneen keneksi kenelle kenellä keneltä kenen kenenä kenessä kenestä kenet ketkä ketkä ketä koska kuin kuka kun me meidän meidät meihin meille meillä meiltä meissä meistä meitä mihin miksi mikä mille millä miltä minkä minkä minua minulla minulle minulta minun minussa minusta minut minuun minä minä missä mistä mitkä mitä mukaan mutta ne niiden niihin niiksi niille niillä niiltä niin niin niinä niissä niistä niitä noiden noihin noiksi noilla noille noilta noin noina noissa noista noita nuo nyt näiden näihin näiksi näille näillä näiltä näinä näissä näistä näitä nämä ole olemme olen olet olette oli olimme olin olisi olisimme olisin olisit olisitte olisivat olit olitte olivat olla olleet ollut on ovat poikki se sekä sen siihen siinä siitä siksi sille sillä sillä siltä sinua sinulla sinulle sinulta sinun sinussa sinusta sinut sinuun sinä sinä sitä tai te teidän teidät teihin teille teillä teiltä teissä teistä teitä tuo tuohon tuoksi tuolla tuolle tuolta tuon tuona tuossa tuosta tuota tähän täksi tälle tällä tältä tämä tämän tänä tässä tästä tätä vaan vai vaikka yli".split(" ")),i.Pipeline.registerFunction(i.fi.stopWordFilter,"stopWordFilter-fi")}}); \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.fr.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.fr.js deleted file mode 100644 index d043ec654..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.fr.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Lunr languages, `French` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r,y,s;e.fr=function(){this.pipeline.reset(),this.pipeline.add(e.fr.trimmer,e.fr.stopWordFilter,e.fr.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.fr.stemmer))},e.fr.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.fr.trimmer=e.trimmerSupport.generateTrimmer(e.fr.wordCharacters),e.Pipeline.registerFunction(e.fr.trimmer,"trimmer-fr"),e.fr.stemmer=(r=e.stemmerSupport.Among,y=e.stemmerSupport.SnowballProgram,s=new function(){var s,i,t,n=[new r("col",-1,-1),new r("par",-1,-1),new r("tap",-1,-1)],u=[new r("",-1,4),new r("I",0,1),new r("U",0,2),new r("Y",0,3)],o=[new r("iqU",-1,3),new r("abl",-1,3),new r("Ièr",-1,4),new r("ièr",-1,4),new r("eus",-1,2),new r("iv",-1,1)],c=[new r("ic",-1,2),new r("abil",-1,1),new r("iv",-1,3)],a=[new r("iqUe",-1,1),new r("atrice",-1,2),new r("ance",-1,1),new r("ence",-1,5),new r("logie",-1,3),new r("able",-1,1),new r("isme",-1,1),new r("euse",-1,11),new r("iste",-1,1),new r("ive",-1,8),new r("if",-1,8),new r("usion",-1,4),new r("ation",-1,2),new r("ution",-1,4),new r("ateur",-1,2),new r("iqUes",-1,1),new r("atrices",-1,2),new r("ances",-1,1),new r("ences",-1,5),new r("logies",-1,3),new r("ables",-1,1),new r("ismes",-1,1),new r("euses",-1,11),new r("istes",-1,1),new r("ives",-1,8),new r("ifs",-1,8),new r("usions",-1,4),new r("ations",-1,2),new r("utions",-1,4),new r("ateurs",-1,2),new r("ments",-1,15),new r("ements",30,6),new r("issements",31,12),new r("ités",-1,7),new r("ment",-1,15),new r("ement",34,6),new r("issement",35,12),new r("amment",34,13),new r("emment",34,14),new r("aux",-1,10),new r("eaux",39,9),new r("eux",-1,1),new r("ité",-1,7)],l=[new r("ira",-1,1),new r("ie",-1,1),new r("isse",-1,1),new r("issante",-1,1),new r("i",-1,1),new r("irai",4,1),new r("ir",-1,1),new r("iras",-1,1),new r("ies",-1,1),new r("îmes",-1,1),new r("isses",-1,1),new r("issantes",-1,1),new r("îtes",-1,1),new r("is",-1,1),new r("irais",13,1),new r("issais",13,1),new r("irions",-1,1),new r("issions",-1,1),new r("irons",-1,1),new r("issons",-1,1),new r("issants",-1,1),new r("it",-1,1),new r("irait",21,1),new r("issait",21,1),new r("issant",-1,1),new r("iraIent",-1,1),new r("issaIent",-1,1),new r("irent",-1,1),new r("issent",-1,1),new r("iront",-1,1),new r("ît",-1,1),new r("iriez",-1,1),new r("issiez",-1,1),new r("irez",-1,1),new r("issez",-1,1)],w=[new r("a",-1,3),new r("era",0,2),new r("asse",-1,3),new r("ante",-1,3),new r("ée",-1,2),new r("ai",-1,3),new r("erai",5,2),new r("er",-1,2),new r("as",-1,3),new r("eras",8,2),new r("âmes",-1,3),new r("asses",-1,3),new r("antes",-1,3),new r("âtes",-1,3),new r("ées",-1,2),new r("ais",-1,3),new r("erais",15,2),new r("ions",-1,1),new r("erions",17,2),new r("assions",17,3),new r("erons",-1,2),new r("ants",-1,3),new r("és",-1,2),new r("ait",-1,3),new r("erait",23,2),new r("ant",-1,3),new r("aIent",-1,3),new r("eraIent",26,2),new r("èrent",-1,2),new r("assent",-1,3),new r("eront",-1,2),new r("ât",-1,3),new r("ez",-1,2),new r("iez",32,2),new r("eriez",33,2),new r("assiez",33,3),new r("erez",32,2),new r("é",-1,2)],f=[new r("e",-1,3),new r("Ière",0,2),new r("ière",0,2),new r("ion",-1,1),new r("Ier",-1,2),new r("ier",-1,2),new r("ë",-1,4)],m=[new r("ell",-1,-1),new r("eill",-1,-1),new r("enn",-1,-1),new r("onn",-1,-1),new r("ett",-1,-1)],_=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,128,130,103,8,5],b=[1,65,20,0,0,0,0,0,0,0,0,0,0,0,0,0,128],d=new y;function k(e,r,s){return!(!d.eq_s(1,e)||(d.ket=d.cursor,!d.in_grouping(_,97,251)))&&(d.slice_from(r),d.cursor=s,!0)}function p(e,r,s){return!!d.eq_s(1,e)&&(d.ket=d.cursor,d.slice_from(r),d.cursor=s,!0)}function g(){for(;!d.in_grouping(_,97,251);){if(d.cursor>=d.limit)return!0;d.cursor++}for(;!d.out_grouping(_,97,251);){if(d.cursor>=d.limit)return!0;d.cursor++}return!1}function q(){return t<=d.cursor}function v(){return i<=d.cursor}function h(){return s<=d.cursor}function z(){if(!function(){var e,r;if(d.ket=d.cursor,e=d.find_among_b(a,43)){switch(d.bra=d.cursor,e){case 1:if(!h())return!1;d.slice_del();break;case 2:if(!h())return!1;d.slice_del(),d.ket=d.cursor,d.eq_s_b(2,"ic")&&(d.bra=d.cursor,h()?d.slice_del():d.slice_from("iqU"));break;case 3:if(!h())return!1;d.slice_from("log");break;case 4:if(!h())return!1;d.slice_from("u");break;case 5:if(!h())return!1;d.slice_from("ent");break;case 6:if(!q())return!1;if(d.slice_del(),d.ket=d.cursor,e=d.find_among_b(o,6))switch(d.bra=d.cursor,e){case 1:h()&&(d.slice_del(),d.ket=d.cursor,d.eq_s_b(2,"at")&&(d.bra=d.cursor,h()&&d.slice_del()));break;case 2:h()?d.slice_del():v()&&d.slice_from("eux");break;case 3:h()&&d.slice_del();break;case 4:q()&&d.slice_from("i")}break;case 7:if(!h())return!1;if(d.slice_del(),d.ket=d.cursor,e=d.find_among_b(c,3))switch(d.bra=d.cursor,e){case 1:h()?d.slice_del():d.slice_from("abl");break;case 2:h()?d.slice_del():d.slice_from("iqU");break;case 3:h()&&d.slice_del()}break;case 8:if(!h())return!1;if(d.slice_del(),d.ket=d.cursor,d.eq_s_b(2,"at")&&(d.bra=d.cursor,h()&&(d.slice_del(),d.ket=d.cursor,d.eq_s_b(2,"ic")))){d.bra=d.cursor,h()?d.slice_del():d.slice_from("iqU");break}break;case 9:d.slice_from("eau");break;case 10:if(!v())return!1;d.slice_from("al");break;case 11:if(h())d.slice_del();else{if(!v())return!1;d.slice_from("eux")}break;case 12:if(!v()||!d.out_grouping_b(_,97,251))return!1;d.slice_del();break;case 13:return q()&&d.slice_from("ant"),!1;case 14:return q()&&d.slice_from("ent"),!1;case 15:return r=d.limit-d.cursor,d.in_grouping_b(_,97,251)&&q()&&(d.cursor=d.limit-r,d.slice_del()),!1}return!0}return!1}()&&(d.cursor=d.limit,!function(){var e,r;if(d.cursor=t){if(s=d.limit_backward,d.limit_backward=t,d.ket=d.cursor,e=d.find_among_b(f,7))switch(d.bra=d.cursor,e){case 1:if(h()){if(i=d.limit-d.cursor,!d.eq_s_b(1,"s")&&(d.cursor=d.limit-i,!d.eq_s_b(1,"t")))break;d.slice_del()}break;case 2:d.slice_from("i");break;case 3:d.slice_del();break;case 4:d.eq_s_b(2,"gu")&&d.slice_del()}d.limit_backward=s}}();d.cursor=d.limit,d.ket=d.cursor,d.eq_s_b(1,"Y")?(d.bra=d.cursor,d.slice_from("i")):(d.cursor=d.limit,d.eq_s_b(1,"ç")&&(d.bra=d.cursor,d.slice_from("c")))}this.setCurrent=function(e){d.setCurrent(e)},this.getCurrent=function(){return d.getCurrent()},this.stem=function(){var e,r=d.cursor;return function(){for(var e,r;;){if(e=d.cursor,d.in_grouping(_,97,251)){if(d.bra=d.cursor,r=d.cursor,k("u","U",e))continue;if(d.cursor=r,k("i","I",e))continue;if(d.cursor=r,p("y","Y",e))continue}if(d.cursor=e,!k("y","Y",d.bra=e)){if(d.cursor=e,d.eq_s(1,"q")&&(d.bra=d.cursor,p("u","U",e)))continue;if((d.cursor=e)>=d.limit)return;d.cursor++}}}(),d.cursor=r,function(){var e=d.cursor;if(t=d.limit,s=i=t,d.in_grouping(_,97,251)&&d.in_grouping(_,97,251)&&d.cursor=d.limit){d.cursor=t;break}d.cursor++}while(!d.in_grouping(_,97,251))}t=d.cursor,d.cursor=e,g()||(i=d.cursor,g()||(s=d.cursor))}(),d.limit_backward=r,d.cursor=d.limit,z(),d.cursor=d.limit,e=d.limit-d.cursor,d.find_among_b(m,5)&&(d.cursor=d.limit-e,d.ket=d.cursor,d.cursor>d.limit_backward&&(d.cursor--,d.bra=d.cursor,d.slice_del())),d.cursor=d.limit,function(){for(var e,r=1;d.out_grouping_b(_,97,251);)r--;if(r<=0){if(d.ket=d.cursor,e=d.limit-d.cursor,!d.eq_s_b(1,"é")&&(d.cursor=d.limit-e,!d.eq_s_b(1,"è")))return;d.bra=d.cursor,d.slice_from("e")}}(),d.cursor=d.limit_backward,function(){for(var e,r;r=d.cursor,d.bra=r,e=d.find_among(u,4);)switch(d.ket=d.cursor,e){case 1:d.slice_from("i");break;case 2:d.slice_from("u");break;case 3:d.slice_from("y");break;case 4:if(d.cursor>=d.limit)return;d.cursor++}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return s.setCurrent(e),s.stem(),s.getCurrent()}):(s.setCurrent(e),s.stem(),s.getCurrent())}),e.Pipeline.registerFunction(e.fr.stemmer,"stemmer-fr"),e.fr.stopWordFilter=e.generateStopWordFilter("ai aie aient aies ait as au aura aurai auraient aurais aurait auras aurez auriez aurions aurons auront aux avaient avais avait avec avez aviez avions avons ayant ayez ayons c ce ceci celà ces cet cette d dans de des du elle en es est et eu eue eues eurent eus eusse eussent eusses eussiez eussions eut eux eûmes eût eûtes furent fus fusse fussent fusses fussiez fussions fut fûmes fût fûtes ici il ils j je l la le les leur leurs lui m ma mais me mes moi mon même n ne nos notre nous on ont ou par pas pour qu que quel quelle quelles quels qui s sa sans se sera serai seraient serais serait seras serez seriez serions serons seront ses soi soient sois soit sommes son sont soyez soyons suis sur t ta te tes toi ton tu un une vos votre vous y à étaient étais était étant étiez étions été étée étées étés êtes".split(" ")),e.Pipeline.registerFunction(e.fr.stopWordFilter,"stopWordFilter-fr")}}); \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.hu.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.hu.js deleted file mode 100644 index bfc68db84..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.hu.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Lunr languages, `Hungarian` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ -!function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var p,_,n;e.hu=function(){this.pipeline.reset(),this.pipeline.add(e.hu.trimmer,e.hu.stopWordFilter,e.hu.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hu.stemmer))},e.hu.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.hu.trimmer=e.trimmerSupport.generateTrimmer(e.hu.wordCharacters),e.Pipeline.registerFunction(e.hu.trimmer,"trimmer-hu"),e.hu.stemmer=(p=e.stemmerSupport.Among,_=e.stemmerSupport.SnowballProgram,n=new function(){var r,i=[new p("cs",-1,-1),new p("dzs",-1,-1),new p("gy",-1,-1),new p("ly",-1,-1),new p("ny",-1,-1),new p("sz",-1,-1),new p("ty",-1,-1),new p("zs",-1,-1)],n=[new p("á",-1,1),new p("é",-1,2)],a=[new p("bb",-1,-1),new p("cc",-1,-1),new p("dd",-1,-1),new p("ff",-1,-1),new p("gg",-1,-1),new p("jj",-1,-1),new p("kk",-1,-1),new p("ll",-1,-1),new p("mm",-1,-1),new p("nn",-1,-1),new p("pp",-1,-1),new p("rr",-1,-1),new p("ccs",-1,-1),new p("ss",-1,-1),new p("zzs",-1,-1),new p("tt",-1,-1),new p("vv",-1,-1),new p("ggy",-1,-1),new p("lly",-1,-1),new p("nny",-1,-1),new p("tty",-1,-1),new p("ssz",-1,-1),new p("zz",-1,-1)],t=[new p("al",-1,1),new p("el",-1,2)],e=[new p("ba",-1,-1),new p("ra",-1,-1),new p("be",-1,-1),new p("re",-1,-1),new p("ig",-1,-1),new p("nak",-1,-1),new p("nek",-1,-1),new p("val",-1,-1),new p("vel",-1,-1),new p("ul",-1,-1),new p("nál",-1,-1),new p("nél",-1,-1),new p("ból",-1,-1),new p("ról",-1,-1),new p("tól",-1,-1),new p("bõl",-1,-1),new p("rõl",-1,-1),new p("tõl",-1,-1),new p("ül",-1,-1),new p("n",-1,-1),new p("an",19,-1),new p("ban",20,-1),new p("en",19,-1),new p("ben",22,-1),new p("képpen",22,-1),new p("on",19,-1),new p("ön",19,-1),new p("képp",-1,-1),new p("kor",-1,-1),new p("t",-1,-1),new p("at",29,-1),new p("et",29,-1),new p("ként",29,-1),new p("anként",32,-1),new p("enként",32,-1),new p("onként",32,-1),new p("ot",29,-1),new p("ért",29,-1),new p("öt",29,-1),new p("hez",-1,-1),new p("hoz",-1,-1),new p("höz",-1,-1),new p("vá",-1,-1),new p("vé",-1,-1)],s=[new p("án",-1,2),new p("én",-1,1),new p("ánként",-1,3)],c=[new p("stul",-1,2),new p("astul",0,1),new p("ástul",0,3),new p("stül",-1,2),new p("estül",3,1),new p("éstül",3,4)],w=[new p("á",-1,1),new p("é",-1,2)],o=[new p("k",-1,7),new p("ak",0,4),new p("ek",0,6),new p("ok",0,5),new p("ák",0,1),new p("ék",0,2),new p("ök",0,3)],l=[new p("éi",-1,7),new p("áéi",0,6),new p("ééi",0,5),new p("é",-1,9),new p("ké",3,4),new p("aké",4,1),new p("eké",4,1),new p("oké",4,1),new p("áké",4,3),new p("éké",4,2),new p("öké",4,1),new p("éé",3,8)],u=[new p("a",-1,18),new p("ja",0,17),new p("d",-1,16),new p("ad",2,13),new p("ed",2,13),new p("od",2,13),new p("ád",2,14),new p("éd",2,15),new p("öd",2,13),new p("e",-1,18),new p("je",9,17),new p("nk",-1,4),new p("unk",11,1),new p("ánk",11,2),new p("énk",11,3),new p("ünk",11,1),new p("uk",-1,8),new p("juk",16,7),new p("ájuk",17,5),new p("ük",-1,8),new p("jük",19,7),new p("éjük",20,6),new p("m",-1,12),new p("am",22,9),new p("em",22,9),new p("om",22,9),new p("ám",22,10),new p("ém",22,11),new p("o",-1,18),new p("á",-1,19),new p("é",-1,20)],m=[new p("id",-1,10),new p("aid",0,9),new p("jaid",1,6),new p("eid",0,9),new p("jeid",3,6),new p("áid",0,7),new p("éid",0,8),new p("i",-1,15),new p("ai",7,14),new p("jai",8,11),new p("ei",7,14),new p("jei",10,11),new p("ái",7,12),new p("éi",7,13),new p("itek",-1,24),new p("eitek",14,21),new p("jeitek",15,20),new p("éitek",14,23),new p("ik",-1,29),new p("aik",18,26),new p("jaik",19,25),new p("eik",18,26),new p("jeik",21,25),new p("áik",18,27),new p("éik",18,28),new p("ink",-1,20),new p("aink",25,17),new p("jaink",26,16),new p("eink",25,17),new p("jeink",28,16),new p("áink",25,18),new p("éink",25,19),new p("aitok",-1,21),new p("jaitok",32,20),new p("áitok",-1,22),new p("im",-1,5),new p("aim",35,4),new p("jaim",36,1),new p("eim",35,4),new p("jeim",38,1),new p("áim",35,2),new p("éim",35,3)],k=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,52,14],f=new _;function b(){return r<=f.cursor}function d(){var e=f.limit-f.cursor;return!!f.find_among_b(a,23)&&(f.cursor=f.limit-e,!0)}function g(){if(f.cursor>f.limit_backward){f.cursor--,f.ket=f.cursor;var e=f.cursor-1;f.limit_backward<=e&&e<=f.limit&&(f.cursor=e,f.bra=e,f.slice_del())}}function h(){f.ket=f.cursor,f.find_among_b(e,44)&&(f.bra=f.cursor,b()&&(f.slice_del(),function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(n,2))&&(f.bra=f.cursor,b()))switch(e){case 1:f.slice_from("a");break;case 2:f.slice_from("e")}}()))}this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var e=f.cursor;return function(){var e,n=f.cursor;if(r=f.limit,f.in_grouping(k,97,252))for(;;){if(e=f.cursor,f.out_grouping(k,97,252))return f.cursor=e,f.find_among(i,8)||(f.cursor=e)=f.limit)return r=e;f.cursor++}if(f.cursor=n,f.out_grouping(k,97,252)){for(;!f.in_grouping(k,97,252);){if(f.cursor>=f.limit)return;f.cursor++}r=f.cursor}}(),f.limit_backward=e,f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(t,2))&&(f.bra=f.cursor,b())){if((1==e||2==e)&&!d())return;f.slice_del(),g()}}(),f.cursor=f.limit,h(),f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(s,3))&&(f.bra=f.cursor,b()))switch(e){case 1:f.slice_from("e");break;case 2:case 3:f.slice_from("a")}}(),f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(c,6))&&(f.bra=f.cursor,b()))switch(e){case 1:case 2:f.slice_del();break;case 3:f.slice_from("a");break;case 4:f.slice_from("e")}}(),f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(w,2))&&(f.bra=f.cursor,b())){if((1==e||2==e)&&!d())return;f.slice_del(),g()}}(),f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(l,12))&&(f.bra=f.cursor,b()))switch(e){case 1:case 4:case 7:case 9:f.slice_del();break;case 2:case 5:case 8:f.slice_from("e");break;case 3:case 6:f.slice_from("a")}}(),f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(u,31))&&(f.bra=f.cursor,b()))switch(e){case 1:case 4:case 7:case 8:case 9:case 12:case 13:case 16:case 17:case 18:f.slice_del();break;case 2:case 5:case 10:case 14:case 19:f.slice_from("a");break;case 3:case 6:case 11:case 15:case 20:f.slice_from("e")}}(),f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(m,42))&&(f.bra=f.cursor,b()))switch(e){case 1:case 4:case 5:case 6:case 9:case 10:case 11:case 14:case 15:case 16:case 17:case 20:case 21:case 24:case 25:case 26:case 29:f.slice_del();break;case 2:case 7:case 12:case 18:case 22:case 27:f.slice_from("a");break;case 3:case 8:case 13:case 19:case 23:case 28:f.slice_from("e")}}(),f.cursor=f.limit,function(){var e;if(f.ket=f.cursor,(e=f.find_among_b(o,7))&&(f.bra=f.cursor,b()))switch(e){case 1:f.slice_from("a");break;case 2:f.slice_from("e");break;case 3:case 4:case 5:case 6:case 7:f.slice_del()}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}),e.Pipeline.registerFunction(e.hu.stemmer,"stemmer-hu"),e.hu.stopWordFilter=e.generateStopWordFilter("a abban ahhoz ahogy ahol aki akik akkor alatt amely amelyek amelyekben amelyeket amelyet amelynek ami amikor amit amolyan amíg annak arra arról az azok azon azonban azt aztán azután azzal azért be belül benne bár cikk cikkek cikkeket csak de e ebben eddig egy egyes egyetlen egyik egyre egyéb egész ehhez ekkor el ellen elsõ elég elõ elõször elõtt emilyen ennek erre ez ezek ezen ezt ezzel ezért fel felé hanem hiszen hogy hogyan igen ill ill. illetve ilyen ilyenkor ismét ison itt jobban jó jól kell kellett keressünk keresztül ki kívül között közül legalább legyen lehet lehetett lenne lenni lesz lett maga magát majd majd meg mellett mely melyek mert mi mikor milyen minden mindenki mindent mindig mint mintha mit mivel miért most már más másik még míg nagy nagyobb nagyon ne nekem neki nem nincs néha néhány nélkül olyan ott pedig persze rá s saját sem semmi sok sokat sokkal szemben szerint szinte számára talán tehát teljes tovább továbbá több ugyanis utolsó után utána vagy vagyis vagyok valaki valami valamint való van vannak vele vissza viszont volna volt voltak voltam voltunk által általában át én éppen és így õ õk õket össze úgy új újabb újra".split(" ")),e.Pipeline.registerFunction(e.hu.stopWordFilter,"stopWordFilter-hu")}}); \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.it.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.it.js deleted file mode 100644 index 58a46fb6c..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.it.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Lunr languages, `Italian` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var z,P,r;e.it=function(){this.pipeline.reset(),this.pipeline.add(e.it.trimmer,e.it.stopWordFilter,e.it.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.it.stemmer))},e.it.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.it.trimmer=e.trimmerSupport.generateTrimmer(e.it.wordCharacters),e.Pipeline.registerFunction(e.it.trimmer,"trimmer-it"),e.it.stemmer=(z=e.stemmerSupport.Among,P=e.stemmerSupport.SnowballProgram,r=new function(){var o,t,s,a=[new z("",-1,7),new z("qu",0,6),new z("á",0,1),new z("é",0,2),new z("í",0,3),new z("ó",0,4),new z("ú",0,5)],u=[new z("",-1,3),new z("I",0,1),new z("U",0,2)],c=[new z("la",-1,-1),new z("cela",0,-1),new z("gliela",0,-1),new z("mela",0,-1),new z("tela",0,-1),new z("vela",0,-1),new z("le",-1,-1),new z("cele",6,-1),new z("gliele",6,-1),new z("mele",6,-1),new z("tele",6,-1),new z("vele",6,-1),new z("ne",-1,-1),new z("cene",12,-1),new z("gliene",12,-1),new z("mene",12,-1),new z("sene",12,-1),new z("tene",12,-1),new z("vene",12,-1),new z("ci",-1,-1),new z("li",-1,-1),new z("celi",20,-1),new z("glieli",20,-1),new z("meli",20,-1),new z("teli",20,-1),new z("veli",20,-1),new z("gli",20,-1),new z("mi",-1,-1),new z("si",-1,-1),new z("ti",-1,-1),new z("vi",-1,-1),new z("lo",-1,-1),new z("celo",31,-1),new z("glielo",31,-1),new z("melo",31,-1),new z("telo",31,-1),new z("velo",31,-1)],w=[new z("ando",-1,1),new z("endo",-1,1),new z("ar",-1,2),new z("er",-1,2),new z("ir",-1,2)],r=[new z("ic",-1,-1),new z("abil",-1,-1),new z("os",-1,-1),new z("iv",-1,1)],n=[new z("ic",-1,1),new z("abil",-1,1),new z("iv",-1,1)],i=[new z("ica",-1,1),new z("logia",-1,3),new z("osa",-1,1),new z("ista",-1,1),new z("iva",-1,9),new z("anza",-1,1),new z("enza",-1,5),new z("ice",-1,1),new z("atrice",7,1),new z("iche",-1,1),new z("logie",-1,3),new z("abile",-1,1),new z("ibile",-1,1),new z("usione",-1,4),new z("azione",-1,2),new z("uzione",-1,4),new z("atore",-1,2),new z("ose",-1,1),new z("ante",-1,1),new z("mente",-1,1),new z("amente",19,7),new z("iste",-1,1),new z("ive",-1,9),new z("anze",-1,1),new z("enze",-1,5),new z("ici",-1,1),new z("atrici",25,1),new z("ichi",-1,1),new z("abili",-1,1),new z("ibili",-1,1),new z("ismi",-1,1),new z("usioni",-1,4),new z("azioni",-1,2),new z("uzioni",-1,4),new z("atori",-1,2),new z("osi",-1,1),new z("anti",-1,1),new z("amenti",-1,6),new z("imenti",-1,6),new z("isti",-1,1),new z("ivi",-1,9),new z("ico",-1,1),new z("ismo",-1,1),new z("oso",-1,1),new z("amento",-1,6),new z("imento",-1,6),new z("ivo",-1,9),new z("ità",-1,8),new z("istà",-1,1),new z("istè",-1,1),new z("istì",-1,1)],l=[new z("isca",-1,1),new z("enda",-1,1),new z("ata",-1,1),new z("ita",-1,1),new z("uta",-1,1),new z("ava",-1,1),new z("eva",-1,1),new z("iva",-1,1),new z("erebbe",-1,1),new z("irebbe",-1,1),new z("isce",-1,1),new z("ende",-1,1),new z("are",-1,1),new z("ere",-1,1),new z("ire",-1,1),new z("asse",-1,1),new z("ate",-1,1),new z("avate",16,1),new z("evate",16,1),new z("ivate",16,1),new z("ete",-1,1),new z("erete",20,1),new z("irete",20,1),new z("ite",-1,1),new z("ereste",-1,1),new z("ireste",-1,1),new z("ute",-1,1),new z("erai",-1,1),new z("irai",-1,1),new z("isci",-1,1),new z("endi",-1,1),new z("erei",-1,1),new z("irei",-1,1),new z("assi",-1,1),new z("ati",-1,1),new z("iti",-1,1),new z("eresti",-1,1),new z("iresti",-1,1),new z("uti",-1,1),new z("avi",-1,1),new z("evi",-1,1),new z("ivi",-1,1),new z("isco",-1,1),new z("ando",-1,1),new z("endo",-1,1),new z("Yamo",-1,1),new z("iamo",-1,1),new z("avamo",-1,1),new z("evamo",-1,1),new z("ivamo",-1,1),new z("eremo",-1,1),new z("iremo",-1,1),new z("assimo",-1,1),new z("ammo",-1,1),new z("emmo",-1,1),new z("eremmo",54,1),new z("iremmo",54,1),new z("immo",-1,1),new z("ano",-1,1),new z("iscano",58,1),new z("avano",58,1),new z("evano",58,1),new z("ivano",58,1),new z("eranno",-1,1),new z("iranno",-1,1),new z("ono",-1,1),new z("iscono",65,1),new z("arono",65,1),new z("erono",65,1),new z("irono",65,1),new z("erebbero",-1,1),new z("irebbero",-1,1),new z("assero",-1,1),new z("essero",-1,1),new z("issero",-1,1),new z("ato",-1,1),new z("ito",-1,1),new z("uto",-1,1),new z("avo",-1,1),new z("evo",-1,1),new z("ivo",-1,1),new z("ar",-1,1),new z("ir",-1,1),new z("erà",-1,1),new z("irà",-1,1),new z("erò",-1,1),new z("irò",-1,1)],m=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2,1],f=[17,65,0,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2],v=[17],b=new P;function d(e,r,n){return!(!b.eq_s(1,e)||(b.ket=b.cursor,!b.in_grouping(m,97,249)))&&(b.slice_from(r),b.cursor=n,!0)}function _(e){if(b.cursor=e,!b.in_grouping(m,97,249))return!1;for(;!b.out_grouping(m,97,249);){if(b.cursor>=b.limit)return!1;b.cursor++}return!0}function g(){var e,r=b.cursor;if(!function(){if(b.in_grouping(m,97,249)){var e=b.cursor;if(b.out_grouping(m,97,249)){for(;!b.in_grouping(m,97,249);){if(b.cursor>=b.limit)return _(e);b.cursor++}return!0}return _(e)}return!1}()){if(b.cursor=r,!b.out_grouping(m,97,249))return;if(e=b.cursor,b.out_grouping(m,97,249)){for(;!b.in_grouping(m,97,249);){if(b.cursor>=b.limit)return b.cursor=e,void(b.in_grouping(m,97,249)&&b.cursor=b.limit)return;b.cursor++}s=b.cursor}function p(){for(;!b.in_grouping(m,97,249);){if(b.cursor>=b.limit)return!1;b.cursor++}for(;!b.out_grouping(m,97,249);){if(b.cursor>=b.limit)return!1;b.cursor++}return!0}function k(){return s<=b.cursor}function h(){return o<=b.cursor}function q(){var e;if(b.ket=b.cursor,!(e=b.find_among_b(i,51)))return!1;switch(b.bra=b.cursor,e){case 1:if(!h())return!1;b.slice_del();break;case 2:if(!h())return!1;b.slice_del(),b.ket=b.cursor,b.eq_s_b(2,"ic")&&(b.bra=b.cursor,h()&&b.slice_del());break;case 3:if(!h())return!1;b.slice_from("log");break;case 4:if(!h())return!1;b.slice_from("u");break;case 5:if(!h())return!1;b.slice_from("ente");break;case 6:if(!k())return!1;b.slice_del();break;case 7:if(!(t<=b.cursor))return!1;b.slice_del(),b.ket=b.cursor,(e=b.find_among_b(r,4))&&(b.bra=b.cursor,h()&&(b.slice_del(),1==e&&(b.ket=b.cursor,b.eq_s_b(2,"at")&&(b.bra=b.cursor,h()&&b.slice_del()))));break;case 8:if(!h())return!1;b.slice_del(),b.ket=b.cursor,(e=b.find_among_b(n,3))&&(b.bra=b.cursor,1==e&&h()&&b.slice_del());break;case 9:if(!h())return!1;b.slice_del(),b.ket=b.cursor,b.eq_s_b(2,"at")&&(b.bra=b.cursor,h()&&(b.slice_del(),b.ket=b.cursor,b.eq_s_b(2,"ic")&&(b.bra=b.cursor,h()&&b.slice_del())))}return!0}function C(){var e;e=b.limit-b.cursor,b.ket=b.cursor,b.in_grouping_b(f,97,242)&&(b.bra=b.cursor,k()&&(b.slice_del(),b.ket=b.cursor,b.eq_s_b(1,"i")&&(b.bra=b.cursor,k())))?b.slice_del():b.cursor=b.limit-e,b.ket=b.cursor,b.eq_s_b(1,"h")&&(b.bra=b.cursor,b.in_grouping_b(v,99,103)&&k()&&b.slice_del())}this.setCurrent=function(e){b.setCurrent(e)},this.getCurrent=function(){return b.getCurrent()},this.stem=function(){var e,r,n,i=b.cursor;return function(){for(var e,r,n,i,o=b.cursor;;){if(b.bra=b.cursor,e=b.find_among(a,7))switch(b.ket=b.cursor,e){case 1:b.slice_from("à");continue;case 2:b.slice_from("è");continue;case 3:b.slice_from("ì");continue;case 4:b.slice_from("ò");continue;case 5:b.slice_from("ù");continue;case 6:b.slice_from("qU");continue;case 7:if(b.cursor>=b.limit)break;b.cursor++;continue}break}for(b.cursor=o;;)for(r=b.cursor;;){if(n=b.cursor,b.in_grouping(m,97,249)){if(b.bra=b.cursor,i=b.cursor,d("u","U",n))break;if(b.cursor=i,d("i","I",n))break}if(b.cursor=n,b.cursor>=b.limit)return b.cursor=r;b.cursor++}}(),b.cursor=i,e=b.cursor,s=b.limit,o=t=s,g(),b.cursor=e,p()&&(t=b.cursor,p()&&(o=b.cursor)),b.limit_backward=i,b.cursor=b.limit,function(){var e;if(b.ket=b.cursor,b.find_among_b(c,37)&&(b.bra=b.cursor,(e=b.find_among_b(w,5))&&k()))switch(e){case 1:b.slice_del();break;case 2:b.slice_from("e")}}(),b.cursor=b.limit,q()||(b.cursor=b.limit,b.cursor>=s&&(n=b.limit_backward,b.limit_backward=s,b.ket=b.cursor,(r=b.find_among_b(l,87))&&(b.bra=b.cursor,1==r&&b.slice_del()),b.limit_backward=n)),b.cursor=b.limit,C(),b.cursor=b.limit_backward,function(){for(var e;b.bra=b.cursor,e=b.find_among(u,3);)switch(b.ket=b.cursor,e){case 1:b.slice_from("i");break;case 2:b.slice_from("u");break;case 3:if(b.cursor>=b.limit)return;b.cursor++}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return r.setCurrent(e),r.stem(),r.getCurrent()}):(r.setCurrent(e),r.stem(),r.getCurrent())}),e.Pipeline.registerFunction(e.it.stemmer,"stemmer-it"),e.it.stopWordFilter=e.generateStopWordFilter("a abbia abbiamo abbiano abbiate ad agl agli ai al all alla alle allo anche avemmo avendo avesse avessero avessi avessimo aveste avesti avete aveva avevamo avevano avevate avevi avevo avrai avranno avrebbe avrebbero avrei avremmo avremo avreste avresti avrete avrà avrò avuta avute avuti avuto c che chi ci coi col come con contro cui da dagl dagli dai dal dall dalla dalle dallo degl degli dei del dell della delle dello di dov dove e ebbe ebbero ebbi ed era erano eravamo eravate eri ero essendo faccia facciamo facciano facciate faccio facemmo facendo facesse facessero facessi facessimo faceste facesti faceva facevamo facevano facevate facevi facevo fai fanno farai faranno farebbe farebbero farei faremmo faremo fareste faresti farete farà farò fece fecero feci fosse fossero fossi fossimo foste fosti fu fui fummo furono gli ha hai hanno ho i il in io l la le lei li lo loro lui ma mi mia mie miei mio ne negl negli nei nel nell nella nelle nello noi non nostra nostre nostri nostro o per perché più quale quanta quante quanti quanto quella quelle quelli quello questa queste questi questo sarai saranno sarebbe sarebbero sarei saremmo saremo sareste saresti sarete sarà sarò se sei si sia siamo siano siate siete sono sta stai stando stanno starai staranno starebbe starebbero starei staremmo staremo stareste staresti starete starà starò stava stavamo stavano stavate stavi stavo stemmo stesse stessero stessi stessimo steste stesti stette stettero stetti stia stiamo stiano stiate sto su sua sue sugl sugli sui sul sull sulla sulle sullo suo suoi ti tra tu tua tue tuo tuoi tutti tutto un una uno vi voi vostra vostre vostri vostro è".split(" ")),e.Pipeline.registerFunction(e.it.stopWordFilter,"stopWordFilter-it")}}); \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.ja.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.ja.js deleted file mode 100644 index 715b834ad..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.ja.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Lunr languages, `Japanese` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Chad Liu - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(m){if(void 0===m)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===m.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var l="2"==m.version[0];m.ja=function(){this.pipeline.reset(),this.pipeline.add(m.ja.trimmer,m.ja.stopWordFilter,m.ja.stemmer),l?this.tokenizer=m.ja.tokenizer:(m.tokenizer&&(m.tokenizer=m.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=m.ja.tokenizer))};var j=new m.TinySegmenter;m.ja.tokenizer=function(e){var r,t,i,n,o,s,p,a,u;if(!arguments.length||null==e||null==e)return[];if(Array.isArray(e))return e.map(function(e){return l?new m.Token(e.toLowerCase()):e.toLowerCase()});for(r=(t=e.toString().toLowerCase().replace(/^\s+/,"")).length-1;0<=r;r--)if(/\S/.test(t.charAt(r))){t=t.substring(0,r+1);break}for(o=[],i=t.length,p=a=0;a<=i;a++)if(s=a-p,t.charAt(a).match(/\s/)||a==i){if(0=_.limit||(_.cursor++,!1)}function w(){for(;!_.in_grouping(m,97,232);){if(_.cursor>=_.limit)return!0;_.cursor++}for(;!_.out_grouping(m,97,232);){if(_.cursor>=_.limit)return!0;_.cursor++}return!1}function b(){return i<=_.cursor}function p(){return e<=_.cursor}function g(){var r=_.limit-_.cursor;_.find_among_b(t,3)&&(_.cursor=_.limit-r,_.ket=_.cursor,_.cursor>_.limit_backward&&(_.cursor--,_.bra=_.cursor,_.slice_del()))}function h(){var r;u=!1,_.ket=_.cursor,_.eq_s_b(1,"e")&&(_.bra=_.cursor,b()&&(r=_.limit-_.cursor,_.out_grouping_b(m,97,232)&&(_.cursor=_.limit-r,_.slice_del(),u=!0,g())))}function k(){var r;b()&&(r=_.limit-_.cursor,_.out_grouping_b(m,97,232)&&(_.cursor=_.limit-r,_.eq_s_b(3,"gem")||(_.cursor=_.limit-r,_.slice_del(),g())))}this.setCurrent=function(r){_.setCurrent(r)},this.getCurrent=function(){return _.getCurrent()},this.stem=function(){var r=_.cursor;return function(){for(var r,e,i,n=_.cursor;;){if(_.bra=_.cursor,r=_.find_among(o,11))switch(_.ket=_.cursor,r){case 1:_.slice_from("a");continue;case 2:_.slice_from("e");continue;case 3:_.slice_from("i");continue;case 4:_.slice_from("o");continue;case 5:_.slice_from("u");continue;case 6:if(_.cursor>=_.limit)break;_.cursor++;continue}break}for(_.cursor=n,_.bra=n,_.eq_s(1,"y")?(_.ket=_.cursor,_.slice_from("Y")):_.cursor=n;;)if(e=_.cursor,_.in_grouping(m,97,232)){if(i=_.cursor,_.bra=i,_.eq_s(1,"i"))_.ket=_.cursor,_.in_grouping(m,97,232)&&(_.slice_from("I"),_.cursor=e);else if(_.cursor=i,_.eq_s(1,"y"))_.ket=_.cursor,_.slice_from("Y"),_.cursor=e;else if(s(e))break}else if(s(e))break}(),_.cursor=r,i=_.limit,e=i,w()||((i=_.cursor)<3&&(i=3),w()||(e=_.cursor)),_.limit_backward=r,_.cursor=_.limit,function(){var r,e,i,n,o,t,s=_.limit-_.cursor;if(_.ket=_.cursor,r=_.find_among_b(c,5))switch(_.bra=_.cursor,r){case 1:b()&&_.slice_from("heid");break;case 2:k();break;case 3:b()&&_.out_grouping_b(f,97,232)&&_.slice_del()}if(_.cursor=_.limit-s,h(),_.cursor=_.limit-s,_.ket=_.cursor,_.eq_s_b(4,"heid")&&(_.bra=_.cursor,p()&&(e=_.limit-_.cursor,_.eq_s_b(1,"c")||(_.cursor=_.limit-e,_.slice_del(),_.ket=_.cursor,_.eq_s_b(2,"en")&&(_.bra=_.cursor,k())))),_.cursor=_.limit-s,_.ket=_.cursor,r=_.find_among_b(a,6))switch(_.bra=_.cursor,r){case 1:if(p()){if(_.slice_del(),i=_.limit-_.cursor,_.ket=_.cursor,_.eq_s_b(2,"ig")&&(_.bra=_.cursor,p()&&(n=_.limit-_.cursor,!_.eq_s_b(1,"e")))){_.cursor=_.limit-n,_.slice_del();break}_.cursor=_.limit-i,g()}break;case 2:p()&&(o=_.limit-_.cursor,_.eq_s_b(1,"e")||(_.cursor=_.limit-o,_.slice_del()));break;case 3:p()&&(_.slice_del(),h());break;case 4:p()&&_.slice_del();break;case 5:p()&&u&&_.slice_del()}_.cursor=_.limit-s,_.out_grouping_b(d,73,232)&&(t=_.limit-_.cursor,_.find_among_b(l,4)&&_.out_grouping_b(m,97,232)&&(_.cursor=_.limit-t,_.ket=_.cursor,_.cursor>_.limit_backward&&(_.cursor--,_.bra=_.cursor,_.slice_del())))}(),_.cursor=_.limit_backward,function(){for(var r;;)if(_.bra=_.cursor,r=_.find_among(n,3))switch(_.ket=_.cursor,r){case 1:_.slice_from("y");break;case 2:_.slice_from("i");break;case 3:if(_.cursor>=_.limit)return;_.cursor++}}(),!0}},function(r){return"function"==typeof r.update?r.update(function(r){return e.setCurrent(r),e.stem(),e.getCurrent()}):(e.setCurrent(r),e.stem(),e.getCurrent())}),r.Pipeline.registerFunction(r.nl.stemmer,"stemmer-nl"),r.nl.stopWordFilter=r.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),r.Pipeline.registerFunction(r.nl.stopWordFilter,"stopWordFilter-nl")}}); \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.no.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.no.js deleted file mode 100644 index 031e4b206..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.no.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Lunr languages, `Norwegian` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r,n,i;e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=(r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){var o,s,a=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],m=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],u=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],d=[119,125,149,1],c=new n;this.setCurrent=function(e){c.setCurrent(e)},this.getCurrent=function(){return c.getCurrent()},this.stem=function(){var e,r,n,i,t=c.cursor;return function(){var e,r=c.cursor+3;if(s=c.limit,0<=r||r<=c.limit){for(o=r;;){if(e=c.cursor,c.in_grouping(u,97,248)){c.cursor=e;break}if(e>=c.limit)return;c.cursor=e+1}for(;!c.out_grouping(u,97,248);){if(c.cursor>=c.limit)return;c.cursor++}(s=c.cursor)=s&&(r=c.limit_backward,c.limit_backward=s,c.ket=c.cursor,e=c.find_among_b(a,29),c.limit_backward=r,e))switch(c.bra=c.cursor,e){case 1:c.slice_del();break;case 2:n=c.limit-c.cursor,c.in_grouping_b(d,98,122)?c.slice_del():(c.cursor=c.limit-n,c.eq_s_b(1,"k")&&c.out_grouping_b(u,97,248)&&c.slice_del());break;case 3:c.slice_from("er")}}(),c.cursor=c.limit,r=c.limit-c.cursor,c.cursor>=s&&(e=c.limit_backward,c.limit_backward=s,c.ket=c.cursor,c.find_among_b(m,2)?(c.bra=c.cursor,c.limit_backward=e,c.cursor=c.limit-r,c.cursor>c.limit_backward&&(c.cursor--,c.bra=c.cursor,c.slice_del())):c.limit_backward=e),c.cursor=c.limit,c.cursor>=s&&(i=c.limit_backward,c.limit_backward=s,c.ket=c.cursor,(n=c.find_among_b(l,11))?(c.bra=c.cursor,c.limit_backward=i,1==n&&c.slice_del()):c.limit_backward=i),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}}); \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.pt.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.pt.js deleted file mode 100644 index 59e766fe9..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.pt.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Lunr languages, `Portuguese` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var j,C,r;e.pt=function(){this.pipeline.reset(),this.pipeline.add(e.pt.trimmer,e.pt.stopWordFilter,e.pt.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.pt.stemmer))},e.pt.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.pt.trimmer=e.trimmerSupport.generateTrimmer(e.pt.wordCharacters),e.Pipeline.registerFunction(e.pt.trimmer,"trimmer-pt"),e.pt.stemmer=(j=e.stemmerSupport.Among,C=e.stemmerSupport.SnowballProgram,r=new function(){var s,n,i,o=[new j("",-1,3),new j("ã",0,1),new j("õ",0,2)],a=[new j("",-1,3),new j("a~",0,1),new j("o~",0,2)],r=[new j("ic",-1,-1),new j("ad",-1,-1),new j("os",-1,-1),new j("iv",-1,1)],t=[new j("ante",-1,1),new j("avel",-1,1),new j("ível",-1,1)],u=[new j("ic",-1,1),new j("abil",-1,1),new j("iv",-1,1)],w=[new j("ica",-1,1),new j("ância",-1,1),new j("ência",-1,4),new j("ira",-1,9),new j("adora",-1,1),new j("osa",-1,1),new j("ista",-1,1),new j("iva",-1,8),new j("eza",-1,1),new j("logía",-1,2),new j("idade",-1,7),new j("ante",-1,1),new j("mente",-1,6),new j("amente",12,5),new j("ável",-1,1),new j("ível",-1,1),new j("ución",-1,3),new j("ico",-1,1),new j("ismo",-1,1),new j("oso",-1,1),new j("amento",-1,1),new j("imento",-1,1),new j("ivo",-1,8),new j("aça~o",-1,1),new j("ador",-1,1),new j("icas",-1,1),new j("ências",-1,4),new j("iras",-1,9),new j("adoras",-1,1),new j("osas",-1,1),new j("istas",-1,1),new j("ivas",-1,8),new j("ezas",-1,1),new j("logías",-1,2),new j("idades",-1,7),new j("uciones",-1,3),new j("adores",-1,1),new j("antes",-1,1),new j("aço~es",-1,1),new j("icos",-1,1),new j("ismos",-1,1),new j("osos",-1,1),new j("amentos",-1,1),new j("imentos",-1,1),new j("ivos",-1,8)],m=[new j("ada",-1,1),new j("ida",-1,1),new j("ia",-1,1),new j("aria",2,1),new j("eria",2,1),new j("iria",2,1),new j("ara",-1,1),new j("era",-1,1),new j("ira",-1,1),new j("ava",-1,1),new j("asse",-1,1),new j("esse",-1,1),new j("isse",-1,1),new j("aste",-1,1),new j("este",-1,1),new j("iste",-1,1),new j("ei",-1,1),new j("arei",16,1),new j("erei",16,1),new j("irei",16,1),new j("am",-1,1),new j("iam",20,1),new j("ariam",21,1),new j("eriam",21,1),new j("iriam",21,1),new j("aram",20,1),new j("eram",20,1),new j("iram",20,1),new j("avam",20,1),new j("em",-1,1),new j("arem",29,1),new j("erem",29,1),new j("irem",29,1),new j("assem",29,1),new j("essem",29,1),new j("issem",29,1),new j("ado",-1,1),new j("ido",-1,1),new j("ando",-1,1),new j("endo",-1,1),new j("indo",-1,1),new j("ara~o",-1,1),new j("era~o",-1,1),new j("ira~o",-1,1),new j("ar",-1,1),new j("er",-1,1),new j("ir",-1,1),new j("as",-1,1),new j("adas",47,1),new j("idas",47,1),new j("ias",47,1),new j("arias",50,1),new j("erias",50,1),new j("irias",50,1),new j("aras",47,1),new j("eras",47,1),new j("iras",47,1),new j("avas",47,1),new j("es",-1,1),new j("ardes",58,1),new j("erdes",58,1),new j("irdes",58,1),new j("ares",58,1),new j("eres",58,1),new j("ires",58,1),new j("asses",58,1),new j("esses",58,1),new j("isses",58,1),new j("astes",58,1),new j("estes",58,1),new j("istes",58,1),new j("is",-1,1),new j("ais",71,1),new j("eis",71,1),new j("areis",73,1),new j("ereis",73,1),new j("ireis",73,1),new j("áreis",73,1),new j("éreis",73,1),new j("íreis",73,1),new j("ásseis",73,1),new j("ésseis",73,1),new j("ísseis",73,1),new j("áveis",73,1),new j("íeis",73,1),new j("aríeis",84,1),new j("eríeis",84,1),new j("iríeis",84,1),new j("ados",-1,1),new j("idos",-1,1),new j("amos",-1,1),new j("áramos",90,1),new j("éramos",90,1),new j("íramos",90,1),new j("ávamos",90,1),new j("íamos",90,1),new j("aríamos",95,1),new j("eríamos",95,1),new j("iríamos",95,1),new j("emos",-1,1),new j("aremos",99,1),new j("eremos",99,1),new j("iremos",99,1),new j("ássemos",99,1),new j("êssemos",99,1),new j("íssemos",99,1),new j("imos",-1,1),new j("armos",-1,1),new j("ermos",-1,1),new j("irmos",-1,1),new j("ámos",-1,1),new j("arás",-1,1),new j("erás",-1,1),new j("irás",-1,1),new j("eu",-1,1),new j("iu",-1,1),new j("ou",-1,1),new j("ará",-1,1),new j("erá",-1,1),new j("irá",-1,1)],c=[new j("a",-1,1),new j("i",-1,1),new j("o",-1,1),new j("os",-1,1),new j("á",-1,1),new j("í",-1,1),new j("ó",-1,1)],l=[new j("e",-1,1),new j("ç",-1,2),new j("é",-1,1),new j("ê",-1,1)],f=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,3,19,12,2],d=new C;function v(){if(d.out_grouping(f,97,250)){for(;!d.in_grouping(f,97,250);){if(d.cursor>=d.limit)return!0;d.cursor++}return!1}return!0}function p(){var e,r,s=d.cursor;if(d.in_grouping(f,97,250))if(e=d.cursor,v()){if(d.cursor=e,function(){if(d.in_grouping(f,97,250))for(;!d.out_grouping(f,97,250);){if(d.cursor>=d.limit)return!1;d.cursor++}return i=d.cursor,!0}())return}else i=d.cursor;if(d.cursor=s,d.out_grouping(f,97,250)){if(r=d.cursor,v()){if(d.cursor=r,!d.in_grouping(f,97,250)||d.cursor>=d.limit)return;d.cursor++}i=d.cursor}}function _(){for(;!d.in_grouping(f,97,250);){if(d.cursor>=d.limit)return!1;d.cursor++}for(;!d.out_grouping(f,97,250);){if(d.cursor>=d.limit)return!1;d.cursor++}return!0}function h(){return i<=d.cursor}function b(){return s<=d.cursor}function g(){var e;if(d.ket=d.cursor,!(e=d.find_among_b(w,45)))return!1;switch(d.bra=d.cursor,e){case 1:if(!b())return!1;d.slice_del();break;case 2:if(!b())return!1;d.slice_from("log");break;case 3:if(!b())return!1;d.slice_from("u");break;case 4:if(!b())return!1;d.slice_from("ente");break;case 5:if(!(n<=d.cursor))return!1;d.slice_del(),d.ket=d.cursor,(e=d.find_among_b(r,4))&&(d.bra=d.cursor,b()&&(d.slice_del(),1==e&&(d.ket=d.cursor,d.eq_s_b(2,"at")&&(d.bra=d.cursor,b()&&d.slice_del()))));break;case 6:if(!b())return!1;d.slice_del(),d.ket=d.cursor,(e=d.find_among_b(t,3))&&(d.bra=d.cursor,1==e&&b()&&d.slice_del());break;case 7:if(!b())return!1;d.slice_del(),d.ket=d.cursor,(e=d.find_among_b(u,3))&&(d.bra=d.cursor,1==e&&b()&&d.slice_del());break;case 8:if(!b())return!1;d.slice_del(),d.ket=d.cursor,d.eq_s_b(2,"at")&&(d.bra=d.cursor,b()&&d.slice_del());break;case 9:if(!h()||!d.eq_s_b(1,"e"))return!1;d.slice_from("ir")}return!0}function k(e,r){if(d.eq_s_b(1,e)){d.bra=d.cursor;var s=d.limit-d.cursor;if(d.eq_s_b(1,r))return d.cursor=d.limit-s,h()&&d.slice_del(),!1}return!0}function q(){if(!g()&&(d.cursor=d.limit,!function(){var e,r;if(d.cursor>=i){if(r=d.limit_backward,d.limit_backward=i,d.ket=d.cursor,e=d.find_among_b(m,120))return d.bra=d.cursor,1==e&&d.slice_del(),d.limit_backward=r,!0;d.limit_backward=r}return!1}()))return d.cursor=d.limit,d.ket=d.cursor,void((e=d.find_among_b(c,7))&&(d.bra=d.cursor,1==e&&h()&&d.slice_del()));var e;d.cursor=d.limit,d.ket=d.cursor,d.eq_s_b(1,"i")&&(d.bra=d.cursor,d.eq_s_b(1,"c")&&(d.cursor=d.limit,h()&&d.slice_del()))}this.setCurrent=function(e){d.setCurrent(e)},this.getCurrent=function(){return d.getCurrent()},this.stem=function(){var e,r=d.cursor;return function(){for(var e;;){if(d.bra=d.cursor,e=d.find_among(o,3))switch(d.ket=d.cursor,e){case 1:d.slice_from("a~");continue;case 2:d.slice_from("o~");continue;case 3:if(d.cursor>=d.limit)break;d.cursor++;continue}break}}(),d.cursor=r,e=d.cursor,i=d.limit,s=n=i,p(),d.cursor=e,_()&&(n=d.cursor,_()&&(s=d.cursor)),d.limit_backward=r,d.cursor=d.limit,q(),d.cursor=d.limit,function(){var e;if(d.ket=d.cursor,e=d.find_among_b(l,4))switch(d.bra=d.cursor,e){case 1:h()&&(d.slice_del(),d.ket=d.cursor,d.limit,d.cursor,k("u","g")&&k("i","c"));break;case 2:d.slice_from("c")}}(),d.cursor=d.limit_backward,function(){for(var e;;){if(d.bra=d.cursor,e=d.find_among(a,3))switch(d.ket=d.cursor,e){case 1:d.slice_from("ã");continue;case 2:d.slice_from("õ");continue;case 3:if(d.cursor>=d.limit)break;d.cursor++;continue}break}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return r.setCurrent(e),r.stem(),r.getCurrent()}):(r.setCurrent(e),r.stem(),r.getCurrent())}),e.Pipeline.registerFunction(e.pt.stemmer,"stemmer-pt"),e.pt.stopWordFilter=e.generateStopWordFilter("a ao aos aquela aquelas aquele aqueles aquilo as até com como da das de dela delas dele deles depois do dos e ela elas ele eles em entre era eram essa essas esse esses esta estamos estas estava estavam este esteja estejam estejamos estes esteve estive estivemos estiver estivera estiveram estiverem estivermos estivesse estivessem estivéramos estivéssemos estou está estávamos estão eu foi fomos for fora foram forem formos fosse fossem fui fôramos fôssemos haja hajam hajamos havemos hei houve houvemos houver houvera houveram houverei houverem houveremos houveria houveriam houvermos houverá houverão houveríamos houvesse houvessem houvéramos houvéssemos há hão isso isto já lhe lhes mais mas me mesmo meu meus minha minhas muito na nas nem no nos nossa nossas nosso nossos num numa não nós o os ou para pela pelas pelo pelos por qual quando que quem se seja sejam sejamos sem serei seremos seria seriam será serão seríamos seu seus somos sou sua suas são só também te tem temos tenha tenham tenhamos tenho terei teremos teria teriam terá terão teríamos teu teus teve tinha tinham tive tivemos tiver tivera tiveram tiverem tivermos tivesse tivessem tivéramos tivéssemos tu tua tuas tém tínhamos um uma você vocês vos à às éramos".split(" ")),e.Pipeline.registerFunction(e.pt.stopWordFilter,"stopWordFilter-pt")}}); \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.ro.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.ro.js deleted file mode 100644 index c5ecc96c4..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.ro.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Lunr languages, `Romanian` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ -!function(e,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var h,z,i;e.ro=function(){this.pipeline.reset(),this.pipeline.add(e.ro.trimmer,e.ro.stopWordFilter,e.ro.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ro.stemmer))},e.ro.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.ro.trimmer=e.trimmerSupport.generateTrimmer(e.ro.wordCharacters),e.Pipeline.registerFunction(e.ro.trimmer,"trimmer-ro"),e.ro.stemmer=(h=e.stemmerSupport.Among,z=e.stemmerSupport.SnowballProgram,i=new function(){var r,n,t,a,o=[new h("",-1,3),new h("I",0,1),new h("U",0,2)],s=[new h("ea",-1,3),new h("aţia",-1,7),new h("aua",-1,2),new h("iua",-1,4),new h("aţie",-1,7),new h("ele",-1,3),new h("ile",-1,5),new h("iile",6,4),new h("iei",-1,4),new h("atei",-1,6),new h("ii",-1,4),new h("ului",-1,1),new h("ul",-1,1),new h("elor",-1,3),new h("ilor",-1,4),new h("iilor",14,4)],c=[new h("icala",-1,4),new h("iciva",-1,4),new h("ativa",-1,5),new h("itiva",-1,6),new h("icale",-1,4),new h("aţiune",-1,5),new h("iţiune",-1,6),new h("atoare",-1,5),new h("itoare",-1,6),new h("ătoare",-1,5),new h("icitate",-1,4),new h("abilitate",-1,1),new h("ibilitate",-1,2),new h("ivitate",-1,3),new h("icive",-1,4),new h("ative",-1,5),new h("itive",-1,6),new h("icali",-1,4),new h("atori",-1,5),new h("icatori",18,4),new h("itori",-1,6),new h("ători",-1,5),new h("icitati",-1,4),new h("abilitati",-1,1),new h("ivitati",-1,3),new h("icivi",-1,4),new h("ativi",-1,5),new h("itivi",-1,6),new h("icităi",-1,4),new h("abilităi",-1,1),new h("ivităi",-1,3),new h("icităţi",-1,4),new h("abilităţi",-1,1),new h("ivităţi",-1,3),new h("ical",-1,4),new h("ator",-1,5),new h("icator",35,4),new h("itor",-1,6),new h("ător",-1,5),new h("iciv",-1,4),new h("ativ",-1,5),new h("itiv",-1,6),new h("icală",-1,4),new h("icivă",-1,4),new h("ativă",-1,5),new h("itivă",-1,6)],u=[new h("ica",-1,1),new h("abila",-1,1),new h("ibila",-1,1),new h("oasa",-1,1),new h("ata",-1,1),new h("ita",-1,1),new h("anta",-1,1),new h("ista",-1,3),new h("uta",-1,1),new h("iva",-1,1),new h("ic",-1,1),new h("ice",-1,1),new h("abile",-1,1),new h("ibile",-1,1),new h("isme",-1,3),new h("iune",-1,2),new h("oase",-1,1),new h("ate",-1,1),new h("itate",17,1),new h("ite",-1,1),new h("ante",-1,1),new h("iste",-1,3),new h("ute",-1,1),new h("ive",-1,1),new h("ici",-1,1),new h("abili",-1,1),new h("ibili",-1,1),new h("iuni",-1,2),new h("atori",-1,1),new h("osi",-1,1),new h("ati",-1,1),new h("itati",30,1),new h("iti",-1,1),new h("anti",-1,1),new h("isti",-1,3),new h("uti",-1,1),new h("işti",-1,3),new h("ivi",-1,1),new h("ităi",-1,1),new h("oşi",-1,1),new h("ităţi",-1,1),new h("abil",-1,1),new h("ibil",-1,1),new h("ism",-1,3),new h("ator",-1,1),new h("os",-1,1),new h("at",-1,1),new h("it",-1,1),new h("ant",-1,1),new h("ist",-1,3),new h("ut",-1,1),new h("iv",-1,1),new h("ică",-1,1),new h("abilă",-1,1),new h("ibilă",-1,1),new h("oasă",-1,1),new h("ată",-1,1),new h("ită",-1,1),new h("antă",-1,1),new h("istă",-1,3),new h("ută",-1,1),new h("ivă",-1,1)],w=[new h("ea",-1,1),new h("ia",-1,1),new h("esc",-1,1),new h("ăsc",-1,1),new h("ind",-1,1),new h("ând",-1,1),new h("are",-1,1),new h("ere",-1,1),new h("ire",-1,1),new h("âre",-1,1),new h("se",-1,2),new h("ase",10,1),new h("sese",10,2),new h("ise",10,1),new h("use",10,1),new h("âse",10,1),new h("eşte",-1,1),new h("ăşte",-1,1),new h("eze",-1,1),new h("ai",-1,1),new h("eai",19,1),new h("iai",19,1),new h("sei",-1,2),new h("eşti",-1,1),new h("ăşti",-1,1),new h("ui",-1,1),new h("ezi",-1,1),new h("âi",-1,1),new h("aşi",-1,1),new h("seşi",-1,2),new h("aseşi",29,1),new h("seseşi",29,2),new h("iseşi",29,1),new h("useşi",29,1),new h("âseşi",29,1),new h("işi",-1,1),new h("uşi",-1,1),new h("âşi",-1,1),new h("aţi",-1,2),new h("eaţi",38,1),new h("iaţi",38,1),new h("eţi",-1,2),new h("iţi",-1,2),new h("âţi",-1,2),new h("arăţi",-1,1),new h("serăţi",-1,2),new h("aserăţi",45,1),new h("seserăţi",45,2),new h("iserăţi",45,1),new h("userăţi",45,1),new h("âserăţi",45,1),new h("irăţi",-1,1),new h("urăţi",-1,1),new h("ârăţi",-1,1),new h("am",-1,1),new h("eam",54,1),new h("iam",54,1),new h("em",-1,2),new h("asem",57,1),new h("sesem",57,2),new h("isem",57,1),new h("usem",57,1),new h("âsem",57,1),new h("im",-1,2),new h("âm",-1,2),new h("ăm",-1,2),new h("arăm",65,1),new h("serăm",65,2),new h("aserăm",67,1),new h("seserăm",67,2),new h("iserăm",67,1),new h("userăm",67,1),new h("âserăm",67,1),new h("irăm",65,1),new h("urăm",65,1),new h("ârăm",65,1),new h("au",-1,1),new h("eau",76,1),new h("iau",76,1),new h("indu",-1,1),new h("ându",-1,1),new h("ez",-1,1),new h("ească",-1,1),new h("ară",-1,1),new h("seră",-1,2),new h("aseră",84,1),new h("seseră",84,2),new h("iseră",84,1),new h("useră",84,1),new h("âseră",84,1),new h("iră",-1,1),new h("ură",-1,1),new h("âră",-1,1),new h("ează",-1,1)],i=[new h("a",-1,1),new h("e",-1,1),new h("ie",1,1),new h("i",-1,1),new h("ă",-1,1)],m=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,2,32,0,0,4],l=new z;function f(e,i){l.eq_s(1,e)&&(l.ket=l.cursor,l.in_grouping(m,97,259)&&l.slice_from(i))}function p(){if(l.out_grouping(m,97,259)){for(;!l.in_grouping(m,97,259);){if(l.cursor>=l.limit)return!0;l.cursor++}return!1}return!0}function d(){var e,i,r=l.cursor;if(l.in_grouping(m,97,259)){if(e=l.cursor,!p())return void(a=l.cursor);if(l.cursor=e,!function(){if(l.in_grouping(m,97,259))for(;!l.out_grouping(m,97,259);){if(l.cursor>=l.limit)return!0;l.cursor++}return!1}())return void(a=l.cursor)}l.cursor=r,l.out_grouping(m,97,259)&&(i=l.cursor,p()&&(l.cursor=i,l.in_grouping(m,97,259)&&l.cursor=l.limit)return!1;l.cursor++}for(;!l.out_grouping(m,97,259);){if(l.cursor>=l.limit)return!1;l.cursor++}return!0}function v(){return t<=l.cursor}function _(){var e,i=l.limit-l.cursor;if(l.ket=l.cursor,(e=l.find_among_b(c,46))&&(l.bra=l.cursor,v())){switch(e){case 1:l.slice_from("abil");break;case 2:l.slice_from("ibil");break;case 3:l.slice_from("iv");break;case 4:l.slice_from("ic");break;case 5:l.slice_from("at");break;case 6:l.slice_from("it")}return r=!0,l.cursor=l.limit-i,!0}return!1}function g(){var e,i;for(r=!1;;)if(i=l.limit-l.cursor,!_()){l.cursor=l.limit-i;break}if(l.ket=l.cursor,(e=l.find_among_b(u,62))&&(l.bra=l.cursor,n<=l.cursor)){switch(e){case 1:l.slice_del();break;case 2:l.eq_s_b(1,"ţ")&&(l.bra=l.cursor,l.slice_from("t"));break;case 3:l.slice_from("ist")}r=!0}}function k(){var e;l.ket=l.cursor,(e=l.find_among_b(i,5))&&(l.bra=l.cursor,a<=l.cursor&&1==e&&l.slice_del())}this.setCurrent=function(e){l.setCurrent(e)},this.getCurrent=function(){return l.getCurrent()},this.stem=function(){var e,i=l.cursor;return function(){for(var e,i;e=l.cursor,l.in_grouping(m,97,259)&&(i=l.cursor,l.bra=i,f("u","U"),l.cursor=i,f("i","I")),l.cursor=e,!(l.cursor>=l.limit);)l.cursor++}(),l.cursor=i,e=l.cursor,a=l.limit,n=t=a,d(),l.cursor=e,b()&&(t=l.cursor,b()&&(n=l.cursor)),l.limit_backward=i,l.cursor=l.limit,function(){var e,i;if(l.ket=l.cursor,(e=l.find_among_b(s,16))&&(l.bra=l.cursor,v()))switch(e){case 1:l.slice_del();break;case 2:l.slice_from("a");break;case 3:l.slice_from("e");break;case 4:l.slice_from("i");break;case 5:i=l.limit-l.cursor,l.eq_s_b(2,"ab")||(l.cursor=l.limit-i,l.slice_from("i"));break;case 6:l.slice_from("at");break;case 7:l.slice_from("aţi")}}(),l.cursor=l.limit,g(),l.cursor=l.limit,r||(l.cursor=l.limit,function(){var e,i,r;if(l.cursor>=a){if(i=l.limit_backward,l.limit_backward=a,l.ket=l.cursor,e=l.find_among_b(w,94))switch(l.bra=l.cursor,e){case 1:if(r=l.limit-l.cursor,!l.out_grouping_b(m,97,259)&&(l.cursor=l.limit-r,!l.eq_s_b(1,"u")))break;case 2:l.slice_del()}l.limit_backward=i}}(),l.cursor=l.limit),k(),l.cursor=l.limit_backward,function(){for(var e;;){if(l.bra=l.cursor,e=l.find_among(o,3))switch(l.ket=l.cursor,e){case 1:l.slice_from("i");continue;case 2:l.slice_from("u");continue;case 3:if(l.cursor>=l.limit)break;l.cursor++;continue}break}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}),e.Pipeline.registerFunction(e.ro.stemmer,"stemmer-ro"),e.ro.stopWordFilter=e.generateStopWordFilter("acea aceasta această aceea acei aceia acel acela acele acelea acest acesta aceste acestea aceşti aceştia acolo acord acum ai aia aibă aici al ale alea altceva altcineva am ar are asemenea asta astea astăzi asupra au avea avem aveţi azi aş aşadar aţi bine bucur bună ca care caut ce cel ceva chiar cinci cine cineva contra cu cum cumva curând curînd când cât câte câtva câţi cînd cît cîte cîtva cîţi că căci cărei căror cărui către da dacă dar datorită dată dau de deci deja deoarece departe deşi din dinaintea dintr- dintre doi doilea două drept după dă ea ei el ele eram este eu eşti face fata fi fie fiecare fii fim fiu fiţi frumos fără graţie halbă iar ieri la le li lor lui lângă lîngă mai mea mei mele mereu meu mi mie mine mult multă mulţi mulţumesc mâine mîine mă ne nevoie nici nicăieri nimeni nimeri nimic nişte noastre noastră noi noroc nostru nouă noştri nu opt ori oricare orice oricine oricum oricând oricât oricînd oricît oriunde patra patru patrulea pe pentru peste pic poate pot prea prima primul prin puţin puţina puţină până pînă rog sa sale sau se spate spre sub sunt suntem sunteţi sută sînt sîntem sînteţi să săi său ta tale te timp tine toate toată tot totuşi toţi trei treia treilea tu tăi tău un una unde undeva unei uneia unele uneori unii unor unora unu unui unuia unul vi voastre voastră voi vostru vouă voştri vreme vreo vreun vă zece zero zi zice îi îl îmi împotriva în înainte înaintea încotro încât încît între întrucât întrucît îţi ăla ălea ăsta ăstea ăştia şapte şase şi ştiu ţi ţie".split(" ")),e.Pipeline.registerFunction(e.ro.stopWordFilter,"stopWordFilter-ro")}}); \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.ru.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.ru.js deleted file mode 100644 index 104bc6e86..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.ru.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Lunr languages, `Russian` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ -!function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var h,g,n;e.ru=function(){this.pipeline.reset(),this.pipeline.add(e.ru.trimmer,e.ru.stopWordFilter,e.ru.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ru.stemmer))},e.ru.wordCharacters="Ѐ-҄҇-ԯᴫᵸⷠ-ⷿꙀ-ꚟ︮︯",e.ru.trimmer=e.trimmerSupport.generateTrimmer(e.ru.wordCharacters),e.Pipeline.registerFunction(e.ru.trimmer,"trimmer-ru"),e.ru.stemmer=(h=e.stemmerSupport.Among,g=e.stemmerSupport.SnowballProgram,n=new function(){var n,e,r=[new h("в",-1,1),new h("ив",0,2),new h("ыв",0,2),new h("вши",-1,1),new h("ивши",3,2),new h("ывши",3,2),new h("вшись",-1,1),new h("ившись",6,2),new h("ывшись",6,2)],t=[new h("ее",-1,1),new h("ие",-1,1),new h("ое",-1,1),new h("ые",-1,1),new h("ими",-1,1),new h("ыми",-1,1),new h("ей",-1,1),new h("ий",-1,1),new h("ой",-1,1),new h("ый",-1,1),new h("ем",-1,1),new h("им",-1,1),new h("ом",-1,1),new h("ым",-1,1),new h("его",-1,1),new h("ого",-1,1),new h("ему",-1,1),new h("ому",-1,1),new h("их",-1,1),new h("ых",-1,1),new h("ею",-1,1),new h("ою",-1,1),new h("ую",-1,1),new h("юю",-1,1),new h("ая",-1,1),new h("яя",-1,1)],w=[new h("ем",-1,1),new h("нн",-1,1),new h("вш",-1,1),new h("ивш",2,2),new h("ывш",2,2),new h("щ",-1,1),new h("ющ",5,1),new h("ующ",6,2)],i=[new h("сь",-1,1),new h("ся",-1,1)],u=[new h("ла",-1,1),new h("ила",0,2),new h("ыла",0,2),new h("на",-1,1),new h("ена",3,2),new h("ете",-1,1),new h("ите",-1,2),new h("йте",-1,1),new h("ейте",7,2),new h("уйте",7,2),new h("ли",-1,1),new h("или",10,2),new h("ыли",10,2),new h("й",-1,1),new h("ей",13,2),new h("уй",13,2),new h("л",-1,1),new h("ил",16,2),new h("ыл",16,2),new h("ем",-1,1),new h("им",-1,2),new h("ым",-1,2),new h("н",-1,1),new h("ен",22,2),new h("ло",-1,1),new h("ило",24,2),new h("ыло",24,2),new h("но",-1,1),new h("ено",27,2),new h("нно",27,1),new h("ет",-1,1),new h("ует",30,2),new h("ит",-1,2),new h("ыт",-1,2),new h("ют",-1,1),new h("уют",34,2),new h("ят",-1,2),new h("ны",-1,1),new h("ены",37,2),new h("ть",-1,1),new h("ить",39,2),new h("ыть",39,2),new h("ешь",-1,1),new h("ишь",-1,2),new h("ю",-1,2),new h("ую",44,2)],s=[new h("а",-1,1),new h("ев",-1,1),new h("ов",-1,1),new h("е",-1,1),new h("ие",3,1),new h("ье",3,1),new h("и",-1,1),new h("еи",6,1),new h("ии",6,1),new h("ами",6,1),new h("ями",6,1),new h("иями",10,1),new h("й",-1,1),new h("ей",12,1),new h("ией",13,1),new h("ий",12,1),new h("ой",12,1),new h("ам",-1,1),new h("ем",-1,1),new h("ием",18,1),new h("ом",-1,1),new h("ям",-1,1),new h("иям",21,1),new h("о",-1,1),new h("у",-1,1),new h("ах",-1,1),new h("ях",-1,1),new h("иях",26,1),new h("ы",-1,1),new h("ь",-1,1),new h("ю",-1,1),new h("ию",30,1),new h("ью",30,1),new h("я",-1,1),new h("ия",33,1),new h("ья",33,1)],o=[new h("ост",-1,1),new h("ость",-1,1)],c=[new h("ейше",-1,1),new h("н",-1,2),new h("ейш",-1,1),new h("ь",-1,3)],m=[33,65,8,232],l=new g;function f(){for(;!l.in_grouping(m,1072,1103);){if(l.cursor>=l.limit)return!1;l.cursor++}return!0}function a(){for(;!l.out_grouping(m,1072,1103);){if(l.cursor>=l.limit)return!1;l.cursor++}return!0}function p(e,n){var r,t;if(l.ket=l.cursor,r=l.find_among_b(e,n)){switch(l.bra=l.cursor,r){case 1:if(t=l.limit-l.cursor,!l.eq_s_b(1,"а")&&(l.cursor=l.limit-t,!l.eq_s_b(1,"я")))return!1;case 2:l.slice_del()}return!0}return!1}function d(e,n){var r;return l.ket=l.cursor,!!(r=l.find_among_b(e,n))&&(l.bra=l.cursor,1==r&&l.slice_del(),!0)}function _(){return!!d(t,26)&&(p(w,8),!0)}function b(){var e;l.ket=l.cursor,(e=l.find_among_b(o,2))&&(l.bra=l.cursor,n<=l.cursor&&1==e&&l.slice_del())}this.setCurrent=function(e){l.setCurrent(e)},this.getCurrent=function(){return l.getCurrent()},this.stem=function(){return e=l.limit,n=e,f()&&(e=l.cursor,a()&&f()&&a()&&(n=l.cursor)),l.cursor=l.limit,!(l.cursor>3]&1<<(7&s))return this.cursor++,!0}return!1},in_grouping_b:function(r,t,i){if(this.cursor>this.limit_backward){var s=b.charCodeAt(this.cursor-1);if(s<=i&&t<=s&&r[(s-=t)>>3]&1<<(7&s))return this.cursor--,!0}return!1},out_grouping:function(r,t,i){if(this.cursor>3]&1<<(7&s)))return this.cursor++,!0}return!1},out_grouping_b:function(r,t,i){if(this.cursor>this.limit_backward){var s=b.charCodeAt(this.cursor-1);if(i>3]&1<<(7&s)))return this.cursor--,!0}return!1},eq_s:function(r,t){if(this.limit-this.cursor>1),a=0,f=u=(l=r[i]).s_size){if(this.cursor=e+l.s_size,!l.method)return l.result;var m=l.method();if(this.cursor=e+l.s_size,m)return l.result}if((i=l.substring_i)<0)return 0}},find_among_b:function(r,t){for(var i=0,s=t,e=this.cursor,n=this.limit_backward,u=0,o=0,h=!1;;){for(var c=i+(s-i>>1),a=0,f=u=(_=r[i]).s_size){if(this.cursor=e-_.s_size,!_.method)return _.result;var m=_.method();if(this.cursor=e-_.s_size,m)return _.result}if((i=_.substring_i)<0)return 0}},replace_s:function(r,t,i){var s=i.length-(t-r);return b=b.substring(0,r)+i+b.substring(t),this.limit+=s,this.cursor>=t?this.cursor+=s:this.cursor>r&&(this.cursor=r),s},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>b.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),b.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}}); \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.sv.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.sv.js deleted file mode 100644 index a46a4e709..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.sv.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Lunr languages, `Swedish` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r,l,n;e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=(r=e.stemmerSupport.Among,l=e.stemmerSupport.SnowballProgram,n=new function(){var n,t,i=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],s=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],a=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],o=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],u=[119,127,149],m=new l;this.setCurrent=function(e){m.setCurrent(e)},this.getCurrent=function(){return m.getCurrent()},this.stem=function(){var e,r=m.cursor;return function(){var e,r=m.cursor+3;if(t=m.limit,0<=r||r<=m.limit){for(n=r;;){if(e=m.cursor,m.in_grouping(o,97,246)){m.cursor=e;break}if(m.cursor=e,m.cursor>=m.limit)return;m.cursor++}for(;!m.out_grouping(o,97,246);){if(m.cursor>=m.limit)return;m.cursor++}(t=m.cursor)=t&&(m.limit_backward=t,m.cursor=m.limit,m.ket=m.cursor,e=m.find_among_b(i,37),m.limit_backward=r,e))switch(m.bra=m.cursor,e){case 1:m.slice_del();break;case 2:m.in_grouping_b(u,98,121)&&m.slice_del()}}(),m.cursor=m.limit,e=m.limit_backward,m.cursor>=t&&(m.limit_backward=t,m.cursor=m.limit,m.find_among_b(s,7)&&(m.cursor=m.limit,m.ket=m.cursor,m.cursor>m.limit_backward&&(m.bra=--m.cursor,m.slice_del())),m.limit_backward=e),m.cursor=m.limit,function(){var e,r;if(m.cursor>=t){if(r=m.limit_backward,m.limit_backward=t,m.cursor=m.limit,m.ket=m.cursor,e=m.find_among_b(a,5))switch(m.bra=m.cursor,e){case 1:m.slice_del();break;case 2:m.slice_from("lös");break;case 3:m.slice_from("full")}m.limit_backward=r}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}}); \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.th.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.th.js deleted file mode 100644 index 7f9887f7b..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.th.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Lunr languages, `Thai` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2017, Keerati Thiwanruk - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ -!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(t){if(void 0===t)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===t.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var i="2"==t.version[0];t.th=function(){this.pipeline.reset(),this.pipeline.add(t.th.trimmer),i?this.tokenizer=t.th.tokenizer:(t.tokenizer&&(t.tokenizer=t.th.tokenizer),this.tokenizerFn&&(this.tokenizerFn=t.th.tokenizer))},t.th.wordCharacters="[฀-๿]",t.th.trimmer=t.trimmerSupport.generateTrimmer(t.th.wordCharacters),t.Pipeline.registerFunction(t.th.trimmer,"trimmer-th");var n=t.wordcut;n.init(),t.th.tokenizer=function(e){if(!arguments.length||null==e||null==e)return[];if(Array.isArray(e))return e.map(function(e){return i?new t.Token(e):e});var r=e.toString().replace(/^\s+/,"");return n.cut(r).split("|")}}}); \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.tr.js b/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.tr.js deleted file mode 100644 index 64ba95cb1..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/javascripts/lunr/lunr.tr.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Lunr languages, `Turkish` language - * https://github.com/MihaiValentin/lunr-languages - * - * Copyright 2014, Mihai Valentin - * http://www.mozilla.org/MPL/ - */ -/*! - * based on - * Snowball JavaScript Library v0.3 - * http://code.google.com/p/urim/ - * http://snowball.tartarus.org/ - * - * Copyright 2010, Oleg Mazko - * http://www.mozilla.org/MPL/ - */ -!function(r,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(r.lunr)}(this,function(){return function(r){if(void 0===r)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===r.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var mr,dr,i;r.tr=function(){this.pipeline.reset(),this.pipeline.add(r.tr.trimmer,r.tr.stopWordFilter,r.tr.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(r.tr.stemmer))},r.tr.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",r.tr.trimmer=r.trimmerSupport.generateTrimmer(r.tr.wordCharacters),r.Pipeline.registerFunction(r.tr.trimmer,"trimmer-tr"),r.tr.stemmer=(mr=r.stemmerSupport.Among,dr=r.stemmerSupport.SnowballProgram,i=new function(){var t,r=[new mr("m",-1,-1),new mr("n",-1,-1),new mr("miz",-1,-1),new mr("niz",-1,-1),new mr("muz",-1,-1),new mr("nuz",-1,-1),new mr("müz",-1,-1),new mr("nüz",-1,-1),new mr("mız",-1,-1),new mr("nız",-1,-1)],i=[new mr("leri",-1,-1),new mr("ları",-1,-1)],e=[new mr("ni",-1,-1),new mr("nu",-1,-1),new mr("nü",-1,-1),new mr("nı",-1,-1)],n=[new mr("in",-1,-1),new mr("un",-1,-1),new mr("ün",-1,-1),new mr("ın",-1,-1)],u=[new mr("a",-1,-1),new mr("e",-1,-1)],o=[new mr("na",-1,-1),new mr("ne",-1,-1)],s=[new mr("da",-1,-1),new mr("ta",-1,-1),new mr("de",-1,-1),new mr("te",-1,-1)],c=[new mr("nda",-1,-1),new mr("nde",-1,-1)],l=[new mr("dan",-1,-1),new mr("tan",-1,-1),new mr("den",-1,-1),new mr("ten",-1,-1)],a=[new mr("ndan",-1,-1),new mr("nden",-1,-1)],m=[new mr("la",-1,-1),new mr("le",-1,-1)],d=[new mr("ca",-1,-1),new mr("ce",-1,-1)],f=[new mr("im",-1,-1),new mr("um",-1,-1),new mr("üm",-1,-1),new mr("ım",-1,-1)],b=[new mr("sin",-1,-1),new mr("sun",-1,-1),new mr("sün",-1,-1),new mr("sın",-1,-1)],w=[new mr("iz",-1,-1),new mr("uz",-1,-1),new mr("üz",-1,-1),new mr("ız",-1,-1)],_=[new mr("siniz",-1,-1),new mr("sunuz",-1,-1),new mr("sünüz",-1,-1),new mr("sınız",-1,-1)],k=[new mr("lar",-1,-1),new mr("ler",-1,-1)],p=[new mr("niz",-1,-1),new mr("nuz",-1,-1),new mr("nüz",-1,-1),new mr("nız",-1,-1)],g=[new mr("dir",-1,-1),new mr("tir",-1,-1),new mr("dur",-1,-1),new mr("tur",-1,-1),new mr("dür",-1,-1),new mr("tür",-1,-1),new mr("dır",-1,-1),new mr("tır",-1,-1)],y=[new mr("casına",-1,-1),new mr("cesine",-1,-1)],z=[new mr("di",-1,-1),new mr("ti",-1,-1),new mr("dik",-1,-1),new mr("tik",-1,-1),new mr("duk",-1,-1),new mr("tuk",-1,-1),new mr("dük",-1,-1),new mr("tük",-1,-1),new mr("dık",-1,-1),new mr("tık",-1,-1),new mr("dim",-1,-1),new mr("tim",-1,-1),new mr("dum",-1,-1),new mr("tum",-1,-1),new mr("düm",-1,-1),new mr("tüm",-1,-1),new mr("dım",-1,-1),new mr("tım",-1,-1),new mr("din",-1,-1),new mr("tin",-1,-1),new mr("dun",-1,-1),new mr("tun",-1,-1),new mr("dün",-1,-1),new mr("tün",-1,-1),new mr("dın",-1,-1),new mr("tın",-1,-1),new mr("du",-1,-1),new mr("tu",-1,-1),new mr("dü",-1,-1),new mr("tü",-1,-1),new mr("dı",-1,-1),new mr("tı",-1,-1)],h=[new mr("sa",-1,-1),new mr("se",-1,-1),new mr("sak",-1,-1),new mr("sek",-1,-1),new mr("sam",-1,-1),new mr("sem",-1,-1),new mr("san",-1,-1),new mr("sen",-1,-1)],v=[new mr("miş",-1,-1),new mr("muş",-1,-1),new mr("müş",-1,-1),new mr("mış",-1,-1)],q=[new mr("b",-1,1),new mr("c",-1,2),new mr("d",-1,3),new mr("ğ",-1,4)],C=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,8,0,0,0,0,0,0,1],P=[1,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,1],F=[65],S=[65],W=[["a",[1,64,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],97,305],["e",[17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,130],101,252],["ı",[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],97,305],["i",[17],101,105],["o",F,111,117],["ö",S,246,252],["u",F,111,117]],L=new dr;function x(r,i,e){for(;;){var n=L.limit-L.cursor;if(L.in_grouping_b(r,i,e)){L.cursor=L.limit-n;break}if(L.cursor=L.limit-n,L.cursor<=L.limit_backward)return!1;L.cursor--}return!0}function A(){var r,i;r=L.limit-L.cursor,x(C,97,305);for(var e=0;eL.limit_backward&&(L.cursor--,e=L.limit-L.cursor,i()))?(L.cursor=L.limit-e,!0):(L.cursor=L.limit-n,r()?(L.cursor=L.limit-n,!1):(L.cursor=L.limit-n,!(L.cursor<=L.limit_backward)&&(L.cursor--,!!i()&&(L.cursor=L.limit-n,!0))))}function j(r){return E(r,function(){return L.in_grouping_b(C,97,305)})}function T(){return j(function(){return L.eq_s_b(1,"n")})}function Z(){return j(function(){return L.eq_s_b(1,"y")})}function B(){return L.find_among_b(r,10)&&E(function(){return L.in_grouping_b(P,105,305)},function(){return L.out_grouping_b(C,97,305)})}function D(){return A()&&L.in_grouping_b(P,105,305)&&j(function(){return L.eq_s_b(1,"s")})}function G(){return L.find_among_b(i,2)}function H(){return A()&&L.find_among_b(n,4)&&T()}function I(){return A()&&L.find_among_b(s,4)}function J(){return A()&&L.find_among_b(c,2)}function K(){return A()&&L.find_among_b(f,4)&&Z()}function M(){return A()&&L.find_among_b(b,4)}function N(){return A()&&L.find_among_b(w,4)&&Z()}function O(){return L.find_among_b(_,4)}function Q(){return A()&&L.find_among_b(k,2)}function R(){return A()&&L.find_among_b(g,8)}function U(){return A()&&L.find_among_b(z,32)&&Z()}function V(){return L.find_among_b(h,8)&&Z()}function X(){return A()&&L.find_among_b(v,4)&&Z()}function Y(){var r=L.limit-L.cursor;return!(X()||(L.cursor=L.limit-r,U()||(L.cursor=L.limit-r,V()||(L.cursor=L.limit-r,L.eq_s_b(3,"ken")&&Z()))))}function $(){if(L.find_among_b(y,2)){var r=L.limit-L.cursor;if(O()||(L.cursor=L.limit-r,Q()||(L.cursor=L.limit-r,K()||(L.cursor=L.limit-r,M()||(L.cursor=L.limit-r,N()||(L.cursor=L.limit-r))))),X())return!1}return!0}function rr(){if(!A()||!L.find_among_b(p,4))return!0;var r=L.limit-L.cursor;return!U()&&(L.cursor=L.limit-r,!V())}function ir(){var r,i,e,n=L.limit-L.cursor;if(L.ket=L.cursor,t=!0,Y()&&(L.cursor=L.limit-n,$()&&(L.cursor=L.limit-n,function(){if(Q()){L.bra=L.cursor,L.slice_del();var r=L.limit-L.cursor;return L.ket=L.cursor,R()||(L.cursor=L.limit-r,U()||(L.cursor=L.limit-r,V()||(L.cursor=L.limit-r,X()||(L.cursor=L.limit-r)))),t=!1}return!0}()&&(L.cursor=L.limit-n,rr()&&(L.cursor=L.limit-n,e=L.limit-L.cursor,!(O()||(L.cursor=L.limit-e,N()||(L.cursor=L.limit-e,M()||(L.cursor=L.limit-e,K()))))||(L.bra=L.cursor,L.slice_del(),i=L.limit-L.cursor,L.ket=L.cursor,X()||(L.cursor=L.limit-i),0)))))){if(L.cursor=L.limit-n,!R())return;L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,r=L.limit-L.cursor,O()||(L.cursor=L.limit-r,Q()||(L.cursor=L.limit-r,K()||(L.cursor=L.limit-r,M()||(L.cursor=L.limit-r,N()||(L.cursor=L.limit-r))))),X()||(L.cursor=L.limit-r)}L.bra=L.cursor,L.slice_del()}function er(){var r,i,e,n;if(L.ket=L.cursor,L.eq_s_b(2,"ki")){if(r=L.limit-L.cursor,I())return L.bra=L.cursor,L.slice_del(),i=L.limit-L.cursor,L.ket=L.cursor,Q()?(L.bra=L.cursor,L.slice_del(),er()):(L.cursor=L.limit-i,B()&&(L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er()))),!0;if(L.cursor=L.limit-r,H()){if(L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,e=L.limit-L.cursor,G())L.bra=L.cursor,L.slice_del();else{if(L.cursor=L.limit-e,L.ket=L.cursor,!B()&&(L.cursor=L.limit-e,!D()&&(L.cursor=L.limit-e,!er())))return!0;L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er())}return!0}if(L.cursor=L.limit-r,J()){if(n=L.limit-L.cursor,G())L.bra=L.cursor,L.slice_del();else if(L.cursor=L.limit-n,D())L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er());else if(L.cursor=L.limit-n,!er())return!1;return!0}}return!1}function nr(r){if(L.ket=L.cursor,!J()&&(L.cursor=L.limit-r,!A()||!L.find_among_b(o,2)))return!1;var i=L.limit-L.cursor;if(G())L.bra=L.cursor,L.slice_del();else if(L.cursor=L.limit-i,D())L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er());else if(L.cursor=L.limit-i,!er())return!1;return!0}function tr(r){if(L.ket=L.cursor,!(A()&&L.find_among_b(a,2)||(L.cursor=L.limit-r,A()&&L.find_among_b(e,4))))return!1;var i=L.limit-L.cursor;return!(!D()&&(L.cursor=L.limit-i,!G()))&&(L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er()),!0)}function ur(){var r,i=L.limit-L.cursor;return L.ket=L.cursor,!!(H()||(L.cursor=L.limit-i,A()&&L.find_among_b(m,2)&&Z()))&&(L.bra=L.cursor,L.slice_del(),r=L.limit-L.cursor,L.ket=L.cursor,!(!Q()||(L.bra=L.cursor,L.slice_del(),!er()))||(L.cursor=L.limit-r,L.ket=L.cursor,(B()||(L.cursor=L.limit-r,D()||(L.cursor=L.limit-r,er())))&&(L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er())),!0))}function or(){var r,i,e=L.limit-L.cursor;if(L.ket=L.cursor,!(I()||(L.cursor=L.limit-e,A()&&L.in_grouping_b(P,105,305)&&Z()||(L.cursor=L.limit-e,A()&&L.find_among_b(u,2)&&Z()))))return!1;if(L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,r=L.limit-L.cursor,B())L.bra=L.cursor,L.slice_del(),i=L.limit-L.cursor,L.ket=L.cursor,Q()||(L.cursor=L.limit-i);else if(L.cursor=L.limit-r,!Q())return!0;return L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,er(),!0}function sr(){var r,i,e=L.limit-L.cursor;if(L.ket=L.cursor,Q())return L.bra=L.cursor,L.slice_del(),void er();if(L.cursor=L.limit-e,L.ket=L.cursor,A()&&L.find_among_b(d,2)&&T())if(L.bra=L.cursor,L.slice_del(),r=L.limit-L.cursor,L.ket=L.cursor,G())L.bra=L.cursor,L.slice_del();else{if(L.cursor=L.limit-r,L.ket=L.cursor,!B()&&(L.cursor=L.limit-r,!D())){if(L.cursor=L.limit-r,L.ket=L.cursor,!Q())return;if(L.bra=L.cursor,L.slice_del(),!er())return}L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er())}else if(L.cursor=L.limit-e,!nr(e)&&(L.cursor=L.limit-e,!tr(e))){if(L.cursor=L.limit-e,L.ket=L.cursor,A()&&L.find_among_b(l,4))return L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,i=L.limit-L.cursor,void(B()?(L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er())):(L.cursor=L.limit-i,Q()?(L.bra=L.cursor,L.slice_del()):L.cursor=L.limit-i,er()));if(L.cursor=L.limit-e,!ur()){if(L.cursor=L.limit-e,G())return L.bra=L.cursor,void L.slice_del();L.cursor=L.limit-e,er()||(L.cursor=L.limit-e,or()||(L.cursor=L.limit-e,L.ket=L.cursor,(B()||(L.cursor=L.limit-e,D()))&&(L.bra=L.cursor,L.slice_del(),L.ket=L.cursor,Q()&&(L.bra=L.cursor,L.slice_del(),er()))))}}}function cr(r,i,e){if(L.cursor=L.limit-r,function(){for(;;){var r=L.limit-L.cursor;if(L.in_grouping_b(C,97,305)){L.cursor=L.limit-r;break}if(L.cursor=L.limit-r,L.cursor<=L.limit_backward)return!1;L.cursor--}return!0}()){var n=L.limit-L.cursor;if(!L.eq_s_b(1,i)&&(L.cursor=L.limit-n,!L.eq_s_b(1,e)))return!0;L.cursor=L.limit-r;var t=L.cursor;return L.insert(L.cursor,L.cursor,e),L.cursor=t,!1}return!0}function lr(r,i,e){for(;!L.eq_s(i,e);){if(L.cursor>=L.limit)return!0;L.cursor++}return i!=L.limit||(L.cursor=r,!1)}function ar(){var r,i,e=L.cursor;return!(!lr(r=L.cursor,2,"ad")||!lr(L.cursor=r,5,"soyad"))&&(L.limit_backward=e,L.cursor=L.limit,i=L.limit-L.cursor,(L.eq_s_b(1,"d")||(L.cursor=L.limit-i,L.eq_s_b(1,"g")))&&cr(i,"a","ı")&&cr(i,"e","i")&&cr(i,"o","u")&&cr(i,"ö","ü"),L.cursor=L.limit,function(){var r;if(L.ket=L.cursor,r=L.find_among_b(q,4))switch(L.bra=L.cursor,r){case 1:L.slice_from("p");break;case 2:L.slice_from("ç");break;case 3:L.slice_from("t");break;case 4:L.slice_from("k")}}(),!0)}this.setCurrent=function(r){L.setCurrent(r)},this.getCurrent=function(){return L.getCurrent()},this.stem=function(){return!!(function(){for(var r,i=L.cursor,e=2;;){for(r=L.cursor;!L.in_grouping(C,97,305);){if(L.cursor>=L.limit)return L.cursor=r,!(0e&&(this._events[n].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[n].length),"function"==typeof console.trace&&console.trace()));return this},r.prototype.once=function(n,t){if(!a(t))throw TypeError("listener must be a function");var e=!1;function r(){this.removeListener(n,r),e||(e=!0,t.apply(this,arguments))}return r.listener=t,this.on(n,r),this},r.prototype.removeListener=function(n,t){var e,r,i,o;if(!a(t))throw TypeError("listener must be a function");if(!this._events||!this._events[n])return this;if(i=(e=this._events[n]).length,r=-1,e===t||a(e.listener)&&e.listener===t)delete this._events[n],this._events.removeListener&&this.emit("removeListener",n,t);else if(c(e)){for(o=i;0this.maxLength)return i();if(!this.stat&&p(this.cache,o)){var t=this.cache[o];if(Array.isArray(t)&&(t="DIR"),!n||"DIR"===t)return i(null,t);if(n&&"FILE"===t)return i()}var e=this.statCache[o];if(void 0!==e){if(!1===e)return i(null,e);var s=e.isDirectory()?"DIR":"FILE";return n&&"FILE"===s?i():i(null,s,e)}var a=this,c=d("stat\0"+o,function(n,e){{if(e&&e.isSymbolicLink())return u.stat(o,function(n,t){n?a._stat2(r,o,null,e,i):a._stat2(r,o,n,t,i)});a._stat2(r,o,n,e,i)}});c&&u.lstat(o,c)},b.prototype._stat2=function(n,t,e,r,i){if(e)return this.statCache[t]=!1,i();var o="/"===n.slice(-1);if(this.statCache[t]=r,"/"===t.slice(-1)&&!r.isDirectory())return i(null,!1,r);var s=r.isDirectory()?"DIR":"FILE";return this.cache[t]=this.cache[t]||s,o&&"DIR"!==s?i():i(null,s,r)}}).call(this,_("_process"))},{"./common.js":15,"./sync.js":17,_process:24,assert:9,events:14,fs:12,inflight:18,inherits:19,minimatch:20,once:21,path:22,"path-is-absolute":23,util:28}],17:[function(e,r,n){(function(i){(r.exports=n).GlobSync=h;var s=e("fs"),c=e("minimatch"),g=(c.Minimatch,e("./glob.js").Glob,e("util"),e("path")),u=e("assert"),l=e("path-is-absolute"),t=e("./common.js"),o=(t.alphasort,t.alphasorti,t.setopts),a=t.ownProp,f=t.childrenIgnored;function n(n,t){if("function"==typeof t||3===arguments.length)throw new TypeError("callback provided to sync glob\nSee: https://github.com/isaacs/node-glob/issues/167");return new h(n,t).found}function h(n,t){if(!n)throw new Error("must provide pattern");if("function"==typeof t||3===arguments.length)throw new TypeError("callback provided to sync glob\nSee: https://github.com/isaacs/node-glob/issues/167");if(!(this instanceof h))return new h(n,t);if(o(this,n,t),this.noprocess)return this;var e=this.minimatch.set.length;this.matches=new Array(e);for(var r=0;rthis.maxLength)return!1;if(!this.stat&&a(this.cache,t)){var r=this.cache[t];if(Array.isArray(r)&&(r="DIR"),!e||"DIR"===r)return r;if(e&&"FILE"===r)return!1}var i=this.statCache[t];if(!i){var o;try{o=s.lstatSync(t)}catch(n){return!1}if(o.isSymbolicLink())try{i=s.statSync(t)}catch(n){i=o}else i=o}r=(this.statCache[t]=i).isDirectory()?"DIR":"FILE";return this.cache[t]=this.cache[t]||r,(!e||"DIR"===r)&&r},h.prototype._mark=function(n){return t.mark(this,n)},h.prototype._makeAbs=function(n){return t.makeAbs(this,n)}}).call(this,e("_process"))},{"./common.js":15,"./glob.js":16,_process:24,assert:9,fs:12,minimatch:20,path:22,"path-is-absolute":23,util:28}],18:[function(t,r,n){(function(s){var n=t("wrappy"),a=Object.create(null),e=t("once");r.exports=n(function(n,t){return a[n]?(a[n].push(t),null):(a[n]=[t],o=n,e(function n(){var t=a[o],e=t.length,r=function(n){for(var t=n.length,e=[],r=0;re?(t.splice(0,e),s.nextTick(function(){n.apply(null,r)})):delete a[o]}}));var o})}).call(this,t("_process"))},{_process:24,once:21,wrappy:29}],19:[function(n,t,e){"function"==typeof Object.create?t.exports=function(n,t){n.super_=t,n.prototype=Object.create(t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}})}:t.exports=function(n,t){n.super_=t;var e=function(){};e.prototype=t.prototype,n.prototype=new e,n.prototype.constructor=n}},{}],20:[function(n,t,e){(t.exports=s).Minimatch=i;var u={sep:"/"};try{u=n("path")}catch(n){}var M=s.GLOBSTAR=i.GLOBSTAR={},r=n("brace-expansion"),C={"!":{open:"(?:(?!(?:",close:"))[^/]*?)"},"?":{open:"(?:",close:")?"},"+":{open:"(?:",close:")+"},"*":{open:"(?:",close:")*"},"@":{open:"(?:",close:")"}},P="[^/]",z=P+"*?",B="().*{}+?[]^$\\!".split("").reduce(function(n,t){return n[t]=!0,n},{});var l=/\/+/;function o(t,e){t=t||{},e=e||{};var r={};return Object.keys(e).forEach(function(n){r[n]=e[n]}),Object.keys(t).forEach(function(n){r[n]=t[n]}),r}function s(n,t,e){if("string"!=typeof t)throw new TypeError("glob pattern string required");return e||(e={}),!(!e.nocomment&&"#"===t.charAt(0))&&(""===t.trim()?""===n:new i(t,e).match(n))}function i(n,t){if(!(this instanceof i))return new i(n,t);if("string"!=typeof n)throw new TypeError("glob pattern string required");t||(t={}),n=n.trim(),"/"!==u.sep&&(n=n.split(u.sep).join("/")),this.options=t,this.set=[],this.pattern=n,this.regexp=null,this.negate=!1,this.comment=!1,this.empty=!1,this.make()}function a(n,t){if(t||(t=this instanceof i?this.options:{}),void 0===(n=void 0===n?this.pattern:n))throw new TypeError("undefined pattern");return t.nobrace||!n.match(/\{.*\}/)?[n]:r(n)}s.filter=function(r,i){return i=i||{},function(n,t,e){return s(n,r,i)}},s.defaults=function(r){if(!r||!Object.keys(r).length)return s;var i=s,n=function(n,t,e){return i.minimatch(n,t,o(r,e))};return n.Minimatch=function(n,t){return new i.Minimatch(n,o(r,t))},n},i.defaults=function(n){return n&&Object.keys(n).length?s.defaults(n).Minimatch:i},i.prototype.debug=function(){},i.prototype.make=function(){if(this._made)return;var n=this.pattern,t=this.options;if(!t.nocomment&&"#"===n.charAt(0))return void(this.comment=!0);if(!n)return void(this.empty=!0);this.parseNegate();var e=this.globSet=this.braceExpand();t.debug&&(this.debug=console.error);this.debug(this.pattern,e),e=this.globParts=e.map(function(n){return n.split(l)}),this.debug(this.pattern,e),e=e.map(function(n,t,e){return n.map(this.parse,this)},this),this.debug(this.pattern,e),e=e.filter(function(n){return-1===n.indexOf(!1)}),this.debug(this.pattern,e),this.set=e},i.prototype.parseNegate=function(){var n=this.pattern,t=!1,e=this.options,r=0;if(e.nonegate)return;for(var i=0,o=n.length;i>> no match, partial?",n,f,t,h),f!==s))}if("string"==typeof u?(c=r.nocase?l.toLowerCase()===u.toLowerCase():l===u,this.debug("string match",u,l,c)):(c=l.match(u),this.debug("pattern match",u,l,c)),!c)return!1}if(i===s&&o===a)return!0;if(i===s)return e;if(o===a)return i===s-1&&""===n[i];throw new Error("wtf?")}},{"brace-expansion":11,path:22}],21:[function(n,t,e){var r=n("wrappy");function i(n){var t=function(){return t.called?t.value:(t.called=!0,t.value=n.apply(this,arguments))};return t.called=!1,t}function o(n){var t=function(){if(t.called)throw new Error(t.onceError);return t.called=!0,t.value=n.apply(this,arguments)},e=n.name||"Function wrapped with `once`";return t.onceError=e+" shouldn't be called more than once",t.called=!1,t}t.exports=r(i),t.exports.strict=r(o),i.proto=i(function(){Object.defineProperty(Function.prototype,"once",{value:function(){return i(this)},configurable:!0}),Object.defineProperty(Function.prototype,"onceStrict",{value:function(){return o(this)},configurable:!0})})},{wrappy:29}],22:[function(n,t,u){(function(i){function o(n,t){for(var e=0,r=n.length-1;0<=r;r--){var i=n[r];"."===i?n.splice(r,1):".."===i?(n.splice(r,1),e++):e&&(n.splice(r,1),e--)}if(t)for(;e--;e)n.unshift("..");return n}var t=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,s=function(n){return t.exec(n).slice(1)};function a(n,t){if(n.filter)return n.filter(t);for(var e=[],r=0;r":">",'"':""","'":"'","`":"`"},D=d.invert(N),F=function(t){var e=function(n){return t[n]},n="(?:"+d.keys(t).join("|")+")",r=RegExp(n),i=RegExp(n,"g");return function(n){return n=null==n?"":""+n,r.test(n)?n.replace(i,e):n}};d.escape=F(N),d.unescape=F(D),d.result=function(n,t,e){var r=null==n?void 0:n[t];return void 0===r&&(r=e),d.isFunction(r)?r.call(n):r};var M=0;d.uniqueId=function(n){var t=++M+"";return n?n+t:t},d.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var C=/(.)^/,P={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},z=/\\|'|\r|\n|\u2028|\u2029/g,B=function(n){return"\\"+P[n]};d.template=function(o,n,t){!n&&t&&(n=t),n=d.defaults({},n,d.templateSettings);var e=RegExp([(n.escape||C).source,(n.interpolate||C).source,(n.evaluate||C).source].join("|")+"|$","g"),s=0,a="__p+='";o.replace(e,function(n,t,e,r,i){return a+=o.slice(s,i).replace(z,B),s=i+n.length,t?a+="'+\n((__t=("+t+"))==null?'':_.escape(__t))+\n'":e?a+="'+\n((__t=("+e+"))==null?'':__t)+\n'":r&&(a+="';\n"+r+"\n__p+='"),n}),a+="';\n",n.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{var r=new Function(n.variable||"obj","_",a)}catch(n){throw n.source=a,n}var i=function(n){return r.call(this,n,d)},c=n.variable||"obj";return i.source="function("+c+"){\n"+a+"}",i},d.chain=function(n){var t=d(n);return t._chain=!0,t};var U=function(n,t){return n._chain?d(t).chain():t};d.mixin=function(e){d.each(d.functions(e),function(n){var t=d[n]=e[n];d.prototype[n]=function(){var n=[this._wrapped];return i.apply(n,arguments),U(this,t.apply(d,n))}})},d.mixin(d),d.each(["pop","push","reverse","shift","sort","splice","unshift"],function(t){var e=r[t];d.prototype[t]=function(){var n=this._wrapped;return e.apply(n,arguments),"shift"!==t&&"splice"!==t||0!==n.length||delete n[0],U(this,n)}}),d.each(["concat","join","slice"],function(n){var t=r[n];d.prototype[n]=function(){return U(this,t.apply(this._wrapped,arguments))}}),d.prototype.value=function(){return this._wrapped},d.prototype.valueOf=d.prototype.toJSON=d.prototype.value,d.prototype.toString=function(){return""+this._wrapped}}).call(this)},{}],26:[function(n,t,e){arguments[4][19][0].apply(e,arguments)},{dup:19}],27:[function(n,t,e){t.exports=function(n){return n&&"object"==typeof n&&"function"==typeof n.copy&&"function"==typeof n.fill&&"function"==typeof n.readUInt8}},{}],28:[function(h,n,k){(function(r,i){var a=/%[sdj%]/g;k.format=function(n){if(!_(n)){for(var t=[],e=0;e.md-nav__link{color:inherit}button[data-md-color-primary=pink]{background-color:#e91e63}[data-md-color-primary=pink] .md-typeset a{color:#e91e63}[data-md-color-primary=pink] .md-header,[data-md-color-primary=pink] .md-hero{background-color:#e91e63}[data-md-color-primary=pink] .md-nav__link--active,[data-md-color-primary=pink] .md-nav__link:active{color:#e91e63}[data-md-color-primary=pink] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=purple]{background-color:#ab47bc}[data-md-color-primary=purple] .md-typeset a{color:#ab47bc}[data-md-color-primary=purple] .md-header,[data-md-color-primary=purple] .md-hero{background-color:#ab47bc}[data-md-color-primary=purple] .md-nav__link--active,[data-md-color-primary=purple] .md-nav__link:active{color:#ab47bc}[data-md-color-primary=purple] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=deep-purple]{background-color:#7e57c2}[data-md-color-primary=deep-purple] .md-typeset a{color:#7e57c2}[data-md-color-primary=deep-purple] .md-header,[data-md-color-primary=deep-purple] .md-hero{background-color:#7e57c2}[data-md-color-primary=deep-purple] .md-nav__link--active,[data-md-color-primary=deep-purple] .md-nav__link:active{color:#7e57c2}[data-md-color-primary=deep-purple] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=indigo]{background-color:#3f51b5}[data-md-color-primary=indigo] .md-typeset a{color:#3f51b5}[data-md-color-primary=indigo] .md-header,[data-md-color-primary=indigo] .md-hero{background-color:#3f51b5}[data-md-color-primary=indigo] .md-nav__link--active,[data-md-color-primary=indigo] .md-nav__link:active{color:#3f51b5}[data-md-color-primary=indigo] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=blue]{background-color:#2196f3}[data-md-color-primary=blue] .md-typeset a{color:#2196f3}[data-md-color-primary=blue] .md-header,[data-md-color-primary=blue] .md-hero{background-color:#2196f3}[data-md-color-primary=blue] .md-nav__link--active,[data-md-color-primary=blue] .md-nav__link:active{color:#2196f3}[data-md-color-primary=blue] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=light-blue]{background-color:#03a9f4}[data-md-color-primary=light-blue] .md-typeset a{color:#03a9f4}[data-md-color-primary=light-blue] .md-header,[data-md-color-primary=light-blue] .md-hero{background-color:#03a9f4}[data-md-color-primary=light-blue] .md-nav__link--active,[data-md-color-primary=light-blue] .md-nav__link:active{color:#03a9f4}[data-md-color-primary=light-blue] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=cyan]{background-color:#00bcd4}[data-md-color-primary=cyan] .md-typeset a{color:#00bcd4}[data-md-color-primary=cyan] .md-header,[data-md-color-primary=cyan] .md-hero{background-color:#00bcd4}[data-md-color-primary=cyan] .md-nav__link--active,[data-md-color-primary=cyan] .md-nav__link:active{color:#00bcd4}[data-md-color-primary=cyan] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=teal]{background-color:#009688}[data-md-color-primary=teal] .md-typeset a{color:#009688}[data-md-color-primary=teal] .md-header,[data-md-color-primary=teal] .md-hero{background-color:#009688}[data-md-color-primary=teal] .md-nav__link--active,[data-md-color-primary=teal] .md-nav__link:active{color:#009688}[data-md-color-primary=teal] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=green]{background-color:#4caf50}[data-md-color-primary=green] .md-typeset a{color:#4caf50}[data-md-color-primary=green] .md-header,[data-md-color-primary=green] .md-hero{background-color:#4caf50}[data-md-color-primary=green] .md-nav__link--active,[data-md-color-primary=green] .md-nav__link:active{color:#4caf50}[data-md-color-primary=green] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=light-green]{background-color:#7cb342}[data-md-color-primary=light-green] .md-typeset a{color:#7cb342}[data-md-color-primary=light-green] .md-header,[data-md-color-primary=light-green] .md-hero{background-color:#7cb342}[data-md-color-primary=light-green] .md-nav__link--active,[data-md-color-primary=light-green] .md-nav__link:active{color:#7cb342}[data-md-color-primary=light-green] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=lime]{background-color:#c0ca33}[data-md-color-primary=lime] .md-typeset a{color:#c0ca33}[data-md-color-primary=lime] .md-header,[data-md-color-primary=lime] .md-hero{background-color:#c0ca33}[data-md-color-primary=lime] .md-nav__link--active,[data-md-color-primary=lime] .md-nav__link:active{color:#c0ca33}[data-md-color-primary=lime] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=yellow]{background-color:#f9a825}[data-md-color-primary=yellow] .md-typeset a{color:#f9a825}[data-md-color-primary=yellow] .md-header,[data-md-color-primary=yellow] .md-hero{background-color:#f9a825}[data-md-color-primary=yellow] .md-nav__link--active,[data-md-color-primary=yellow] .md-nav__link:active{color:#f9a825}[data-md-color-primary=yellow] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=amber]{background-color:#ffa000}[data-md-color-primary=amber] .md-typeset a{color:#ffa000}[data-md-color-primary=amber] .md-header,[data-md-color-primary=amber] .md-hero{background-color:#ffa000}[data-md-color-primary=amber] .md-nav__link--active,[data-md-color-primary=amber] .md-nav__link:active{color:#ffa000}[data-md-color-primary=amber] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=orange]{background-color:#fb8c00}[data-md-color-primary=orange] .md-typeset a{color:#fb8c00}[data-md-color-primary=orange] .md-header,[data-md-color-primary=orange] .md-hero{background-color:#fb8c00}[data-md-color-primary=orange] .md-nav__link--active,[data-md-color-primary=orange] .md-nav__link:active{color:#fb8c00}[data-md-color-primary=orange] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=deep-orange]{background-color:#ff7043}[data-md-color-primary=deep-orange] .md-typeset a{color:#ff7043}[data-md-color-primary=deep-orange] .md-header,[data-md-color-primary=deep-orange] .md-hero{background-color:#ff7043}[data-md-color-primary=deep-orange] .md-nav__link--active,[data-md-color-primary=deep-orange] .md-nav__link:active{color:#ff7043}[data-md-color-primary=deep-orange] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=brown]{background-color:#795548}[data-md-color-primary=brown] .md-typeset a{color:#795548}[data-md-color-primary=brown] .md-header,[data-md-color-primary=brown] .md-hero{background-color:#795548}[data-md-color-primary=brown] .md-nav__link--active,[data-md-color-primary=brown] .md-nav__link:active{color:#795548}[data-md-color-primary=brown] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=grey]{background-color:#757575}[data-md-color-primary=grey] .md-typeset a{color:#757575}[data-md-color-primary=grey] .md-header,[data-md-color-primary=grey] .md-hero{background-color:#757575}[data-md-color-primary=grey] .md-nav__link--active,[data-md-color-primary=grey] .md-nav__link:active{color:#757575}[data-md-color-primary=grey] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=blue-grey]{background-color:#546e7a}[data-md-color-primary=blue-grey] .md-typeset a{color:#546e7a}[data-md-color-primary=blue-grey] .md-header,[data-md-color-primary=blue-grey] .md-hero{background-color:#546e7a}[data-md-color-primary=blue-grey] .md-nav__link--active,[data-md-color-primary=blue-grey] .md-nav__link:active{color:#546e7a}[data-md-color-primary=blue-grey] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=white]{box-shadow:inset 0 0 .05rem rgba(0,0,0,.54)}[data-md-color-primary=white] .md-header,[data-md-color-primary=white] .md-hero,button[data-md-color-primary=white]{background-color:#fff;color:rgba(0,0,0,.87)}[data-md-color-primary=white] .md-hero--expand{border-bottom:.05rem solid rgba(0,0,0,.07)}[data-md-color-primary=black] .md-header,[data-md-color-primary=black] .md-hero,button[data-md-color-primary=black]{background-color:#000}button[data-md-color-accent=red]{background-color:#ff1744}[data-md-color-accent=red] .md-typeset a:active,[data-md-color-accent=red] .md-typeset a:hover{color:#ff1744}[data-md-color-accent=red] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=red] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#ff1744}[data-md-color-accent=red] .md-nav__link:focus,[data-md-color-accent=red] .md-nav__link:hover,[data-md-color-accent=red] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=red] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=red] .md-typeset .md-clipboard:active:before,[data-md-color-accent=red] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=red] .md-typeset [id] .headerlink:focus,[data-md-color-accent=red] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=red] .md-typeset [id]:target .headerlink{color:#ff1744}[data-md-color-accent=red] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ff1744}[data-md-color-accent=red] .md-search-result__link:hover,[data-md-color-accent=red] .md-search-result__link[data-md-state=active]{background-color:rgba(255,23,68,.1)}[data-md-color-accent=red] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ff1744}[data-md-color-accent=red] .md-source-file:hover:before{background-color:#ff1744}button[data-md-color-accent=pink]{background-color:#f50057}[data-md-color-accent=pink] .md-typeset a:active,[data-md-color-accent=pink] .md-typeset a:hover{color:#f50057}[data-md-color-accent=pink] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=pink] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#f50057}[data-md-color-accent=pink] .md-nav__link:focus,[data-md-color-accent=pink] .md-nav__link:hover,[data-md-color-accent=pink] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=pink] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=pink] .md-typeset .md-clipboard:active:before,[data-md-color-accent=pink] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=pink] .md-typeset [id] .headerlink:focus,[data-md-color-accent=pink] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=pink] .md-typeset [id]:target .headerlink{color:#f50057}[data-md-color-accent=pink] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#f50057}[data-md-color-accent=pink] .md-search-result__link:hover,[data-md-color-accent=pink] .md-search-result__link[data-md-state=active]{background-color:rgba(245,0,87,.1)}[data-md-color-accent=pink] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#f50057}[data-md-color-accent=pink] .md-source-file:hover:before{background-color:#f50057}button[data-md-color-accent=purple]{background-color:#e040fb}[data-md-color-accent=purple] .md-typeset a:active,[data-md-color-accent=purple] .md-typeset a:hover{color:#e040fb}[data-md-color-accent=purple] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=purple] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#e040fb}[data-md-color-accent=purple] .md-nav__link:focus,[data-md-color-accent=purple] .md-nav__link:hover,[data-md-color-accent=purple] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=purple] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=purple] .md-typeset .md-clipboard:active:before,[data-md-color-accent=purple] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=purple] .md-typeset [id] .headerlink:focus,[data-md-color-accent=purple] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=purple] .md-typeset [id]:target .headerlink{color:#e040fb}[data-md-color-accent=purple] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#e040fb}[data-md-color-accent=purple] .md-search-result__link:hover,[data-md-color-accent=purple] .md-search-result__link[data-md-state=active]{background-color:rgba(224,64,251,.1)}[data-md-color-accent=purple] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#e040fb}[data-md-color-accent=purple] .md-source-file:hover:before{background-color:#e040fb}button[data-md-color-accent=deep-purple]{background-color:#7c4dff}[data-md-color-accent=deep-purple] .md-typeset a:active,[data-md-color-accent=deep-purple] .md-typeset a:hover{color:#7c4dff}[data-md-color-accent=deep-purple] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=deep-purple] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#7c4dff}[data-md-color-accent=deep-purple] .md-nav__link:focus,[data-md-color-accent=deep-purple] .md-nav__link:hover,[data-md-color-accent=deep-purple] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=deep-purple] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=deep-purple] .md-typeset .md-clipboard:active:before,[data-md-color-accent=deep-purple] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=deep-purple] .md-typeset [id] .headerlink:focus,[data-md-color-accent=deep-purple] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=deep-purple] .md-typeset [id]:target .headerlink{color:#7c4dff}[data-md-color-accent=deep-purple] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#7c4dff}[data-md-color-accent=deep-purple] .md-search-result__link:hover,[data-md-color-accent=deep-purple] .md-search-result__link[data-md-state=active]{background-color:rgba(124,77,255,.1)}[data-md-color-accent=deep-purple] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#7c4dff}[data-md-color-accent=deep-purple] .md-source-file:hover:before{background-color:#7c4dff}button[data-md-color-accent=indigo]{background-color:#536dfe}[data-md-color-accent=indigo] .md-typeset a:active,[data-md-color-accent=indigo] .md-typeset a:hover{color:#536dfe}[data-md-color-accent=indigo] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=indigo] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#536dfe}[data-md-color-accent=indigo] .md-nav__link:focus,[data-md-color-accent=indigo] .md-nav__link:hover,[data-md-color-accent=indigo] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=indigo] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=indigo] .md-typeset .md-clipboard:active:before,[data-md-color-accent=indigo] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=indigo] .md-typeset [id] .headerlink:focus,[data-md-color-accent=indigo] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=indigo] .md-typeset [id]:target .headerlink{color:#536dfe}[data-md-color-accent=indigo] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#536dfe}[data-md-color-accent=indigo] .md-search-result__link:hover,[data-md-color-accent=indigo] .md-search-result__link[data-md-state=active]{background-color:rgba(83,109,254,.1)}[data-md-color-accent=indigo] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#536dfe}[data-md-color-accent=indigo] .md-source-file:hover:before{background-color:#536dfe}button[data-md-color-accent=blue]{background-color:#448aff}[data-md-color-accent=blue] .md-typeset a:active,[data-md-color-accent=blue] .md-typeset a:hover{color:#448aff}[data-md-color-accent=blue] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=blue] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#448aff}[data-md-color-accent=blue] .md-nav__link:focus,[data-md-color-accent=blue] .md-nav__link:hover,[data-md-color-accent=blue] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=blue] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=blue] .md-typeset .md-clipboard:active:before,[data-md-color-accent=blue] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=blue] .md-typeset [id] .headerlink:focus,[data-md-color-accent=blue] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=blue] .md-typeset [id]:target .headerlink{color:#448aff}[data-md-color-accent=blue] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#448aff}[data-md-color-accent=blue] .md-search-result__link:hover,[data-md-color-accent=blue] .md-search-result__link[data-md-state=active]{background-color:rgba(68,138,255,.1)}[data-md-color-accent=blue] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#448aff}[data-md-color-accent=blue] .md-source-file:hover:before{background-color:#448aff}button[data-md-color-accent=light-blue]{background-color:#0091ea}[data-md-color-accent=light-blue] .md-typeset a:active,[data-md-color-accent=light-blue] .md-typeset a:hover{color:#0091ea}[data-md-color-accent=light-blue] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=light-blue] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#0091ea}[data-md-color-accent=light-blue] .md-nav__link:focus,[data-md-color-accent=light-blue] .md-nav__link:hover,[data-md-color-accent=light-blue] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=light-blue] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=light-blue] .md-typeset .md-clipboard:active:before,[data-md-color-accent=light-blue] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=light-blue] .md-typeset [id] .headerlink:focus,[data-md-color-accent=light-blue] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=light-blue] .md-typeset [id]:target .headerlink{color:#0091ea}[data-md-color-accent=light-blue] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#0091ea}[data-md-color-accent=light-blue] .md-search-result__link:hover,[data-md-color-accent=light-blue] .md-search-result__link[data-md-state=active]{background-color:rgba(0,145,234,.1)}[data-md-color-accent=light-blue] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#0091ea}[data-md-color-accent=light-blue] .md-source-file:hover:before{background-color:#0091ea}button[data-md-color-accent=cyan]{background-color:#00b8d4}[data-md-color-accent=cyan] .md-typeset a:active,[data-md-color-accent=cyan] .md-typeset a:hover{color:#00b8d4}[data-md-color-accent=cyan] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=cyan] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#00b8d4}[data-md-color-accent=cyan] .md-nav__link:focus,[data-md-color-accent=cyan] .md-nav__link:hover,[data-md-color-accent=cyan] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=cyan] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=cyan] .md-typeset .md-clipboard:active:before,[data-md-color-accent=cyan] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=cyan] .md-typeset [id] .headerlink:focus,[data-md-color-accent=cyan] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=cyan] .md-typeset [id]:target .headerlink{color:#00b8d4}[data-md-color-accent=cyan] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#00b8d4}[data-md-color-accent=cyan] .md-search-result__link:hover,[data-md-color-accent=cyan] .md-search-result__link[data-md-state=active]{background-color:rgba(0,184,212,.1)}[data-md-color-accent=cyan] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#00b8d4}[data-md-color-accent=cyan] .md-source-file:hover:before{background-color:#00b8d4}button[data-md-color-accent=teal]{background-color:#00bfa5}[data-md-color-accent=teal] .md-typeset a:active,[data-md-color-accent=teal] .md-typeset a:hover{color:#00bfa5}[data-md-color-accent=teal] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=teal] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#00bfa5}[data-md-color-accent=teal] .md-nav__link:focus,[data-md-color-accent=teal] .md-nav__link:hover,[data-md-color-accent=teal] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=teal] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=teal] .md-typeset .md-clipboard:active:before,[data-md-color-accent=teal] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=teal] .md-typeset [id] .headerlink:focus,[data-md-color-accent=teal] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=teal] .md-typeset [id]:target .headerlink{color:#00bfa5}[data-md-color-accent=teal] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#00bfa5}[data-md-color-accent=teal] .md-search-result__link:hover,[data-md-color-accent=teal] .md-search-result__link[data-md-state=active]{background-color:rgba(0,191,165,.1)}[data-md-color-accent=teal] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#00bfa5}[data-md-color-accent=teal] .md-source-file:hover:before{background-color:#00bfa5}button[data-md-color-accent=green]{background-color:#00c853}[data-md-color-accent=green] .md-typeset a:active,[data-md-color-accent=green] .md-typeset a:hover{color:#00c853}[data-md-color-accent=green] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=green] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#00c853}[data-md-color-accent=green] .md-nav__link:focus,[data-md-color-accent=green] .md-nav__link:hover,[data-md-color-accent=green] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=green] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=green] .md-typeset .md-clipboard:active:before,[data-md-color-accent=green] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=green] .md-typeset [id] .headerlink:focus,[data-md-color-accent=green] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=green] .md-typeset [id]:target .headerlink{color:#00c853}[data-md-color-accent=green] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#00c853}[data-md-color-accent=green] .md-search-result__link:hover,[data-md-color-accent=green] .md-search-result__link[data-md-state=active]{background-color:rgba(0,200,83,.1)}[data-md-color-accent=green] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#00c853}[data-md-color-accent=green] .md-source-file:hover:before{background-color:#00c853}button[data-md-color-accent=light-green]{background-color:#64dd17}[data-md-color-accent=light-green] .md-typeset a:active,[data-md-color-accent=light-green] .md-typeset a:hover{color:#64dd17}[data-md-color-accent=light-green] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=light-green] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#64dd17}[data-md-color-accent=light-green] .md-nav__link:focus,[data-md-color-accent=light-green] .md-nav__link:hover,[data-md-color-accent=light-green] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=light-green] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=light-green] .md-typeset .md-clipboard:active:before,[data-md-color-accent=light-green] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=light-green] .md-typeset [id] .headerlink:focus,[data-md-color-accent=light-green] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=light-green] .md-typeset [id]:target .headerlink{color:#64dd17}[data-md-color-accent=light-green] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#64dd17}[data-md-color-accent=light-green] .md-search-result__link:hover,[data-md-color-accent=light-green] .md-search-result__link[data-md-state=active]{background-color:rgba(100,221,23,.1)}[data-md-color-accent=light-green] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#64dd17}[data-md-color-accent=light-green] .md-source-file:hover:before{background-color:#64dd17}button[data-md-color-accent=lime]{background-color:#aeea00}[data-md-color-accent=lime] .md-typeset a:active,[data-md-color-accent=lime] .md-typeset a:hover{color:#aeea00}[data-md-color-accent=lime] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=lime] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#aeea00}[data-md-color-accent=lime] .md-nav__link:focus,[data-md-color-accent=lime] .md-nav__link:hover,[data-md-color-accent=lime] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=lime] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=lime] .md-typeset .md-clipboard:active:before,[data-md-color-accent=lime] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=lime] .md-typeset [id] .headerlink:focus,[data-md-color-accent=lime] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=lime] .md-typeset [id]:target .headerlink{color:#aeea00}[data-md-color-accent=lime] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#aeea00}[data-md-color-accent=lime] .md-search-result__link:hover,[data-md-color-accent=lime] .md-search-result__link[data-md-state=active]{background-color:rgba(174,234,0,.1)}[data-md-color-accent=lime] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#aeea00}[data-md-color-accent=lime] .md-source-file:hover:before{background-color:#aeea00}button[data-md-color-accent=yellow]{background-color:#ffd600}[data-md-color-accent=yellow] .md-typeset a:active,[data-md-color-accent=yellow] .md-typeset a:hover{color:#ffd600}[data-md-color-accent=yellow] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=yellow] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#ffd600}[data-md-color-accent=yellow] .md-nav__link:focus,[data-md-color-accent=yellow] .md-nav__link:hover,[data-md-color-accent=yellow] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=yellow] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=yellow] .md-typeset .md-clipboard:active:before,[data-md-color-accent=yellow] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=yellow] .md-typeset [id] .headerlink:focus,[data-md-color-accent=yellow] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=yellow] .md-typeset [id]:target .headerlink{color:#ffd600}[data-md-color-accent=yellow] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ffd600}[data-md-color-accent=yellow] .md-search-result__link:hover,[data-md-color-accent=yellow] .md-search-result__link[data-md-state=active]{background-color:rgba(255,214,0,.1)}[data-md-color-accent=yellow] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ffd600}[data-md-color-accent=yellow] .md-source-file:hover:before{background-color:#ffd600}button[data-md-color-accent=amber]{background-color:#ffab00}[data-md-color-accent=amber] .md-typeset a:active,[data-md-color-accent=amber] .md-typeset a:hover{color:#ffab00}[data-md-color-accent=amber] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=amber] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#ffab00}[data-md-color-accent=amber] .md-nav__link:focus,[data-md-color-accent=amber] .md-nav__link:hover,[data-md-color-accent=amber] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=amber] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=amber] .md-typeset .md-clipboard:active:before,[data-md-color-accent=amber] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=amber] .md-typeset [id] .headerlink:focus,[data-md-color-accent=amber] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=amber] .md-typeset [id]:target .headerlink{color:#ffab00}[data-md-color-accent=amber] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ffab00}[data-md-color-accent=amber] .md-search-result__link:hover,[data-md-color-accent=amber] .md-search-result__link[data-md-state=active]{background-color:rgba(255,171,0,.1)}[data-md-color-accent=amber] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ffab00}[data-md-color-accent=amber] .md-source-file:hover:before{background-color:#ffab00}button[data-md-color-accent=orange]{background-color:#ff9100}[data-md-color-accent=orange] .md-typeset a:active,[data-md-color-accent=orange] .md-typeset a:hover{color:#ff9100}[data-md-color-accent=orange] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=orange] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#ff9100}[data-md-color-accent=orange] .md-nav__link:focus,[data-md-color-accent=orange] .md-nav__link:hover,[data-md-color-accent=orange] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=orange] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=orange] .md-typeset .md-clipboard:active:before,[data-md-color-accent=orange] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=orange] .md-typeset [id] .headerlink:focus,[data-md-color-accent=orange] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=orange] .md-typeset [id]:target .headerlink{color:#ff9100}[data-md-color-accent=orange] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ff9100}[data-md-color-accent=orange] .md-search-result__link:hover,[data-md-color-accent=orange] .md-search-result__link[data-md-state=active]{background-color:rgba(255,145,0,.1)}[data-md-color-accent=orange] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ff9100}[data-md-color-accent=orange] .md-source-file:hover:before{background-color:#ff9100}button[data-md-color-accent=deep-orange]{background-color:#ff6e40}[data-md-color-accent=deep-orange] .md-typeset a:active,[data-md-color-accent=deep-orange] .md-typeset a:hover{color:#ff6e40}[data-md-color-accent=deep-orange] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=deep-orange] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#ff6e40}[data-md-color-accent=deep-orange] .md-nav__link:focus,[data-md-color-accent=deep-orange] .md-nav__link:hover,[data-md-color-accent=deep-orange] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=deep-orange] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=deep-orange] .md-typeset .md-clipboard:active:before,[data-md-color-accent=deep-orange] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=deep-orange] .md-typeset [id] .headerlink:focus,[data-md-color-accent=deep-orange] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=deep-orange] .md-typeset [id]:target .headerlink{color:#ff6e40}[data-md-color-accent=deep-orange] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ff6e40}[data-md-color-accent=deep-orange] .md-search-result__link:hover,[data-md-color-accent=deep-orange] .md-search-result__link[data-md-state=active]{background-color:rgba(255,110,64,.1)}[data-md-color-accent=deep-orange] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ff6e40}[data-md-color-accent=deep-orange] .md-source-file:hover:before{background-color:#ff6e40}@media only screen and (max-width:59.9375em){[data-md-color-primary=red] .md-nav__source{background-color:rgba(190,66,64,.9675)}[data-md-color-primary=pink] .md-nav__source{background-color:rgba(185,24,79,.9675)}[data-md-color-primary=purple] .md-nav__source{background-color:rgba(136,57,150,.9675)}[data-md-color-primary=deep-purple] .md-nav__source{background-color:rgba(100,69,154,.9675)}[data-md-color-primary=indigo] .md-nav__source{background-color:rgba(50,64,144,.9675)}[data-md-color-primary=blue] .md-nav__source{background-color:rgba(26,119,193,.9675)}[data-md-color-primary=light-blue] .md-nav__source{background-color:rgba(2,134,194,.9675)}[data-md-color-primary=cyan] .md-nav__source{background-color:rgba(0,150,169,.9675)}[data-md-color-primary=teal] .md-nav__source{background-color:rgba(0,119,108,.9675)}[data-md-color-primary=green] .md-nav__source{background-color:rgba(60,139,64,.9675)}[data-md-color-primary=light-green] .md-nav__source{background-color:rgba(99,142,53,.9675)}[data-md-color-primary=lime] .md-nav__source{background-color:rgba(153,161,41,.9675)}[data-md-color-primary=yellow] .md-nav__source{background-color:rgba(198,134,29,.9675)}[data-md-color-primary=amber] .md-nav__source{background-color:rgba(203,127,0,.9675)}[data-md-color-primary=orange] .md-nav__source{background-color:rgba(200,111,0,.9675)}[data-md-color-primary=deep-orange] .md-nav__source{background-color:rgba(203,89,53,.9675)}[data-md-color-primary=brown] .md-nav__source{background-color:rgba(96,68,57,.9675)}[data-md-color-primary=grey] .md-nav__source{background-color:rgba(93,93,93,.9675)}[data-md-color-primary=blue-grey] .md-nav__source{background-color:rgba(67,88,97,.9675)}[data-md-color-primary=white] .md-nav__source{background-color:rgba(0,0,0,.07);color:rgba(0,0,0,.87)}[data-md-color-primary=black] .md-nav__source{background-color:#404040}}@media only screen and (max-width:76.1875em){html [data-md-color-primary=red] .md-nav--primary .md-nav__title--site{background-color:#ef5350}html [data-md-color-primary=pink] .md-nav--primary .md-nav__title--site{background-color:#e91e63}html [data-md-color-primary=purple] .md-nav--primary .md-nav__title--site{background-color:#ab47bc}html [data-md-color-primary=deep-purple] .md-nav--primary .md-nav__title--site{background-color:#7e57c2}html [data-md-color-primary=indigo] .md-nav--primary .md-nav__title--site{background-color:#3f51b5}html [data-md-color-primary=blue] .md-nav--primary .md-nav__title--site{background-color:#2196f3}html [data-md-color-primary=light-blue] .md-nav--primary .md-nav__title--site{background-color:#03a9f4}html [data-md-color-primary=cyan] .md-nav--primary .md-nav__title--site{background-color:#00bcd4}html [data-md-color-primary=teal] .md-nav--primary .md-nav__title--site{background-color:#009688}html [data-md-color-primary=green] .md-nav--primary .md-nav__title--site{background-color:#4caf50}html [data-md-color-primary=light-green] .md-nav--primary .md-nav__title--site{background-color:#7cb342}html [data-md-color-primary=lime] .md-nav--primary .md-nav__title--site{background-color:#c0ca33}html [data-md-color-primary=yellow] .md-nav--primary .md-nav__title--site{background-color:#f9a825}html [data-md-color-primary=amber] .md-nav--primary .md-nav__title--site{background-color:#ffa000}html [data-md-color-primary=orange] .md-nav--primary .md-nav__title--site{background-color:#fb8c00}html [data-md-color-primary=deep-orange] .md-nav--primary .md-nav__title--site{background-color:#ff7043}html [data-md-color-primary=brown] .md-nav--primary .md-nav__title--site{background-color:#795548}html [data-md-color-primary=grey] .md-nav--primary .md-nav__title--site{background-color:#757575}html [data-md-color-primary=blue-grey] .md-nav--primary .md-nav__title--site{background-color:#546e7a}html [data-md-color-primary=white] .md-nav--primary .md-nav__title--site{background-color:#fff;color:rgba(0,0,0,.87)}[data-md-color-primary=white] .md-hero{border-bottom:.05rem solid rgba(0,0,0,.07)}html [data-md-color-primary=black] .md-nav--primary .md-nav__title--site{background-color:#000}}@media only screen and (min-width:76.25em){[data-md-color-primary=red] .md-tabs{background-color:#ef5350}[data-md-color-primary=pink] .md-tabs{background-color:#e91e63}[data-md-color-primary=purple] .md-tabs{background-color:#ab47bc}[data-md-color-primary=deep-purple] .md-tabs{background-color:#7e57c2}[data-md-color-primary=indigo] .md-tabs{background-color:#3f51b5}[data-md-color-primary=blue] .md-tabs{background-color:#2196f3}[data-md-color-primary=light-blue] .md-tabs{background-color:#03a9f4}[data-md-color-primary=cyan] .md-tabs{background-color:#00bcd4}[data-md-color-primary=teal] .md-tabs{background-color:#009688}[data-md-color-primary=green] .md-tabs{background-color:#4caf50}[data-md-color-primary=light-green] .md-tabs{background-color:#7cb342}[data-md-color-primary=lime] .md-tabs{background-color:#c0ca33}[data-md-color-primary=yellow] .md-tabs{background-color:#f9a825}[data-md-color-primary=amber] .md-tabs{background-color:#ffa000}[data-md-color-primary=orange] .md-tabs{background-color:#fb8c00}[data-md-color-primary=deep-orange] .md-tabs{background-color:#ff7043}[data-md-color-primary=brown] .md-tabs{background-color:#795548}[data-md-color-primary=grey] .md-tabs{background-color:#757575}[data-md-color-primary=blue-grey] .md-tabs{background-color:#546e7a}[data-md-color-primary=white] .md-tabs{border-bottom:.05rem solid rgba(0,0,0,.07);background-color:#fff;color:rgba(0,0,0,.87)}[data-md-color-primary=black] .md-tabs{background-color:#000}}@media only screen and (min-width:60em){[data-md-color-primary=white] .md-search__input{background-color:rgba(0,0,0,.07)}[data-md-color-primary=white] .md-search__input::-webkit-input-placeholder{color:rgba(0,0,0,.54)}[data-md-color-primary=white] .md-search__input::-moz-placeholder{color:rgba(0,0,0,.54)}[data-md-color-primary=white] .md-search__input:-ms-input-placeholder{color:rgba(0,0,0,.54)}[data-md-color-primary=white] .md-search__input::-ms-input-placeholder{color:rgba(0,0,0,.54)}[data-md-color-primary=white] .md-search__input::placeholder{color:rgba(0,0,0,.54)}[data-md-color-primary=black] .md-search__input{background-color:hsla(0,0%,100%,.3)}} \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/assets/stylesheets/application.adb8469c.css b/lib/libesp32_lvgl/freetype/docs/reference/assets/stylesheets/application.adb8469c.css deleted file mode 100644 index 93b3dabad..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/assets/stylesheets/application.adb8469c.css +++ /dev/null @@ -1 +0,0 @@ -html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}html{-webkit-text-size-adjust:none;-moz-text-size-adjust:none;-ms-text-size-adjust:none;text-size-adjust:none}body{margin:0}hr{overflow:visible;box-sizing:content-box}a{-webkit-text-decoration-skip:objects}a,button,input,label{-webkit-tap-highlight-color:transparent}a{color:inherit;text-decoration:none}small,sub,sup{font-size:80%}sub,sup{position:relative;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}table{border-collapse:separate;border-spacing:0}td,th{font-weight:400;vertical-align:top}button{margin:0;padding:0;border:0;outline-style:none;background:transparent;font-size:inherit}input{border:0;outline:0}.md-clipboard:before,.md-icon,.md-nav__button,.md-nav__link:after,.md-nav__title:before,.md-search-result__article--document:before,.md-source-file:before,.md-typeset .admonition>.admonition-title:before,.md-typeset .admonition>summary:before,.md-typeset .critic.comment:before,.md-typeset .footnote-backref,.md-typeset .task-list-control .task-list-indicator:before,.md-typeset details>.admonition-title:before,.md-typeset details>summary:before,.md-typeset summary:after{font-family:Material Icons;font-style:normal;font-variant:normal;font-weight:400;line-height:1;text-transform:none;white-space:nowrap;word-wrap:normal;direction:ltr}.md-content__icon,.md-footer-nav__button,.md-header-nav__button,.md-nav__button,.md-nav__title:before,.md-search-result__article--document:before{display:inline-block;margin:.2rem;padding:.4rem;font-size:1.2rem;cursor:pointer}.md-icon--arrow-back:before{content:""}.md-icon--arrow-forward:before{content:""}.md-icon--menu:before{content:""}.md-icon--search:before{content:""}[dir=rtl] .md-icon--arrow-back:before{content:""}[dir=rtl] .md-icon--arrow-forward:before{content:""}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body,input{color:rgba(0,0,0,.87);font-feature-settings:"kern","liga";font-family:Helvetica Neue,Helvetica,Arial,sans-serif}code,kbd,pre{color:rgba(0,0,0,.87);font-feature-settings:"kern";font-family:Courier New,Courier,monospace}.md-typeset{font-size:.8rem;line-height:1.6;-webkit-print-color-adjust:exact}.md-typeset blockquote,.md-typeset ol,.md-typeset p,.md-typeset ul{margin:1em 0}.md-typeset h1{margin:0 0 2rem;color:rgba(0,0,0,.54);font-size:1.5625rem;line-height:1.3}.md-typeset h1,.md-typeset h2{font-weight:300;letter-spacing:-.01em}.md-typeset h2{margin:2rem 0 .8rem;font-size:1.25rem;line-height:1.4}.md-typeset h3{margin:1.6rem 0 .8rem;font-size:1rem;font-weight:400;letter-spacing:-.01em;line-height:1.5}.md-typeset h2+h3{margin-top:.8rem}.md-typeset h4{font-size:.8rem}.md-typeset h4,.md-typeset h5,.md-typeset h6{margin:.8rem 0;font-weight:700;letter-spacing:-.01em}.md-typeset h5,.md-typeset h6{color:rgba(0,0,0,.54);font-size:.64rem}.md-typeset h5{text-transform:uppercase}.md-typeset hr{margin:1.5em 0;border-bottom:.05rem dotted rgba(0,0,0,.26)}.md-typeset a{color:#3f51b5;word-break:break-word}.md-typeset a,.md-typeset a:before{-webkit-transition:color .125s;transition:color .125s}.md-typeset a:active,.md-typeset a:hover{color:#536dfe}.md-typeset code,.md-typeset pre{background-color:hsla(0,0%,92.5%,.5);color:#37474f;font-size:85%;direction:ltr}.md-typeset code{margin:0 .29412em;padding:.07353em 0;border-radius:.1rem;box-shadow:.29412em 0 0 hsla(0,0%,92.5%,.5),-.29412em 0 0 hsla(0,0%,92.5%,.5);word-break:break-word;-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset h1 code,.md-typeset h2 code,.md-typeset h3 code,.md-typeset h4 code,.md-typeset h5 code,.md-typeset h6 code{margin:0;background-color:transparent;box-shadow:none}.md-typeset a>code{margin:inherit;padding:inherit;border-radius:initial;background-color:inherit;color:inherit;box-shadow:none}.md-typeset pre{position:relative;margin:1em 0;border-radius:.1rem;line-height:1.4;-webkit-overflow-scrolling:touch}.md-typeset pre>code{display:block;margin:0;padding:.525rem .6rem;background-color:transparent;font-size:inherit;box-shadow:none;-webkit-box-decoration-break:slice;box-decoration-break:slice;overflow:auto}.md-typeset pre>code::-webkit-scrollbar{width:.2rem;height:.2rem}.md-typeset pre>code::-webkit-scrollbar-thumb{background-color:rgba(0,0,0,.26)}.md-typeset pre>code::-webkit-scrollbar-thumb:hover{background-color:#536dfe}.md-typeset kbd{padding:0 .29412em;border-radius:.15rem;border:.05rem solid #c9c9c9;border-bottom-color:#bcbcbc;background-color:#fcfcfc;color:#555;font-size:85%;box-shadow:0 .05rem 0 #b0b0b0;word-break:break-word}.md-typeset mark{margin:0 .25em;padding:.0625em 0;border-radius:.1rem;background-color:rgba(255,235,59,.5);box-shadow:.25em 0 0 rgba(255,235,59,.5),-.25em 0 0 rgba(255,235,59,.5);word-break:break-word;-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset abbr{border-bottom:.05rem dotted rgba(0,0,0,.54);text-decoration:none;cursor:help}.md-typeset small{opacity:.75}.md-typeset sub,.md-typeset sup{margin-left:.07812em}[dir=rtl] .md-typeset sub,[dir=rtl] .md-typeset sup{margin-right:.07812em;margin-left:0}.md-typeset blockquote{padding-left:.6rem;border-left:.2rem solid rgba(0,0,0,.26);color:rgba(0,0,0,.54)}[dir=rtl] .md-typeset blockquote{padding-right:.6rem;padding-left:0;border-right:.2rem solid rgba(0,0,0,.26);border-left:initial}.md-typeset ul{list-style-type:disc}.md-typeset ol,.md-typeset ul{margin-left:.625em;padding:0}[dir=rtl] .md-typeset ol,[dir=rtl] .md-typeset ul{margin-right:.625em;margin-left:0}.md-typeset ol ol,.md-typeset ul ol{list-style-type:lower-alpha}.md-typeset ol ol ol,.md-typeset ul ol ol{list-style-type:lower-roman}.md-typeset ol li,.md-typeset ul li{margin-bottom:.5em;margin-left:1.25em}[dir=rtl] .md-typeset ol li,[dir=rtl] .md-typeset ul li{margin-right:1.25em;margin-left:0}.md-typeset ol li blockquote,.md-typeset ol li p,.md-typeset ul li blockquote,.md-typeset ul li p{margin:.5em 0}.md-typeset ol li:last-child,.md-typeset ul li:last-child{margin-bottom:0}.md-typeset ol li ol,.md-typeset ol li ul,.md-typeset ul li ol,.md-typeset ul li ul{margin:.5em 0 .5em .625em}[dir=rtl] .md-typeset ol li ol,[dir=rtl] .md-typeset ol li ul,[dir=rtl] .md-typeset ul li ol,[dir=rtl] .md-typeset ul li ul{margin-right:.625em;margin-left:0}.md-typeset dd{margin:1em 0 1em 1.875em}[dir=rtl] .md-typeset dd{margin-right:1.875em;margin-left:0}.md-typeset iframe,.md-typeset img,.md-typeset svg{max-width:100%}.md-typeset table:not([class]){box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12),0 3px 1px -2px rgba(0,0,0,.2);display:inline-block;max-width:100%;border-radius:.1rem;font-size:.64rem;overflow:auto;-webkit-overflow-scrolling:touch}.md-typeset table:not([class])+*{margin-top:1.5em}.md-typeset table:not([class]) td:not([align]),.md-typeset table:not([class]) th:not([align]){text-align:left}[dir=rtl] .md-typeset table:not([class]) td:not([align]),[dir=rtl] .md-typeset table:not([class]) th:not([align]){text-align:right}.md-typeset table:not([class]) th{min-width:5rem;padding:.6rem .8rem;background-color:rgba(0,0,0,.54);color:#fff;vertical-align:top}.md-typeset table:not([class]) td{padding:.6rem .8rem;border-top:.05rem solid rgba(0,0,0,.07);vertical-align:top}.md-typeset table:not([class]) tr{-webkit-transition:background-color .125s;transition:background-color .125s}.md-typeset table:not([class]) tr:hover{background-color:rgba(0,0,0,.035);box-shadow:inset 0 .05rem 0 #fff}.md-typeset table:not([class]) tr:first-child td{border-top:0}.md-typeset table:not([class]) a{word-break:normal}.md-typeset__scrollwrap{margin:1em -.8rem;overflow-x:auto;-webkit-overflow-scrolling:touch}.md-typeset .md-typeset__table{display:inline-block;margin-bottom:.5em;padding:0 .8rem}.md-typeset .md-typeset__table table{display:table;width:100%;margin:0;overflow:hidden}html{font-size:125%;overflow-x:hidden}body,html{height:100%}body{position:relative;font-size:.5rem}hr{display:block;height:.05rem;padding:0;border:0}.md-svg{display:none}.md-grid{max-width:61rem;margin-right:auto;margin-left:auto}.md-container,.md-main{overflow:auto}.md-container{display:table;width:100%;height:100%;padding-top:2.4rem;table-layout:fixed}.md-main{display:table-row;height:100%}.md-main__inner{height:100%;padding-top:1.5rem;padding-bottom:.05rem}.md-toggle{display:none}.md-overlay{position:fixed;top:0;width:0;height:0;-webkit-transition:width 0s .25s,height 0s .25s,opacity .25s;transition:width 0s .25s,height 0s .25s,opacity .25s;background-color:rgba(0,0,0,.54);opacity:0;z-index:3}.md-flex{display:table}.md-flex__cell{display:table-cell;position:relative;vertical-align:top}.md-flex__cell--shrink{width:0}.md-flex__cell--stretch{display:table;width:100%;table-layout:fixed}.md-flex__ellipsis{display:table-cell;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.md-skip{position:fixed;width:.05rem;height:.05rem;margin:.5rem;padding:.3rem .5rem;-webkit-transform:translateY(.4rem);transform:translateY(.4rem);border-radius:.1rem;background-color:rgba(0,0,0,.87);color:#fff;font-size:.64rem;opacity:0;overflow:hidden}.md-skip:focus{width:auto;height:auto;clip:auto;-webkit-transform:translateX(0);transform:translateX(0);-webkit-transition:opacity .175s 75ms,-webkit-transform .25s cubic-bezier(.4,0,.2,1);transition:opacity .175s 75ms,-webkit-transform .25s cubic-bezier(.4,0,.2,1);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity .175s 75ms;transition:transform .25s cubic-bezier(.4,0,.2,1),opacity .175s 75ms,-webkit-transform .25s cubic-bezier(.4,0,.2,1);opacity:1;z-index:10}@page{margin:25mm}.md-clipboard{position:absolute;top:.3rem;right:.3rem;width:1.4rem;height:1.4rem;border-radius:.1rem;font-size:.8rem;cursor:pointer;z-index:1;-webkit-backface-visibility:hidden;backface-visibility:hidden}.md-clipboard:before{-webkit-transition:color .25s,opacity .25s;transition:color .25s,opacity .25s;color:rgba(0,0,0,.07);content:"\E14D"}.codehilite:hover .md-clipboard:before,.md-typeset .highlight:hover .md-clipboard:before,pre:hover .md-clipboard:before{color:rgba(0,0,0,.54)}.md-clipboard:focus:before,.md-clipboard:hover:before{color:#536dfe}.md-clipboard__message{display:block;position:absolute;top:0;right:1.7rem;padding:.3rem .5rem;-webkit-transform:translateX(.4rem);transform:translateX(.4rem);-webkit-transition:opacity .175s,-webkit-transform .25s cubic-bezier(.9,.1,.9,0);transition:opacity .175s,-webkit-transform .25s cubic-bezier(.9,.1,.9,0);transition:transform .25s cubic-bezier(.9,.1,.9,0),opacity .175s;transition:transform .25s cubic-bezier(.9,.1,.9,0),opacity .175s,-webkit-transform .25s cubic-bezier(.9,.1,.9,0);border-radius:.1rem;background-color:rgba(0,0,0,.54);color:#fff;font-size:.64rem;white-space:nowrap;opacity:0;pointer-events:none}.md-clipboard__message--active{-webkit-transform:translateX(0);transform:translateX(0);-webkit-transition:opacity .175s 75ms,-webkit-transform .25s cubic-bezier(.4,0,.2,1);transition:opacity .175s 75ms,-webkit-transform .25s cubic-bezier(.4,0,.2,1);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity .175s 75ms;transition:transform .25s cubic-bezier(.4,0,.2,1),opacity .175s 75ms,-webkit-transform .25s cubic-bezier(.4,0,.2,1);opacity:1;pointer-events:auto}.md-clipboard__message:before{content:attr(aria-label)}.md-clipboard__message:after{display:block;position:absolute;top:50%;right:-.2rem;width:0;margin-top:-.2rem;border-color:transparent rgba(0,0,0,.54);border-style:solid;border-width:.2rem 0 .2rem .2rem;content:""}.md-content__inner{margin:0 .8rem 1.2rem;padding-top:.6rem}.md-content__inner:before{display:block;height:.4rem;content:""}.md-content__inner>:last-child{margin-bottom:0}.md-content__icon{position:relative;margin:.4rem 0;padding:0;float:right}.md-typeset .md-content__icon{color:rgba(0,0,0,.26)}.md-header{position:fixed;top:0;right:0;left:0;height:2.4rem;-webkit-transition:background-color .25s,color .25s;transition:background-color .25s,color .25s;background-color:#3f51b5;color:#fff;box-shadow:none;z-index:2;-webkit-backface-visibility:hidden;backface-visibility:hidden}.no-js .md-header{-webkit-transition:none;transition:none;box-shadow:none}.md-header[data-md-state=shadow]{-webkit-transition:background-color .25s,color .25s,box-shadow .25s;transition:background-color .25s,color .25s,box-shadow .25s;box-shadow:0 0 .2rem rgba(0,0,0,.1),0 .2rem .4rem rgba(0,0,0,.2)}.md-header-nav{padding:0 .2rem}.md-header-nav__button{position:relative;-webkit-transition:opacity .25s;transition:opacity .25s;z-index:1}.md-header-nav__button:hover{opacity:.7}.md-header-nav__button.md-logo *{display:block}.no-js .md-header-nav__button.md-icon--search{display:none}.md-header-nav__topic{display:block;position:absolute;-webkit-transition:opacity .15s,-webkit-transform .4s cubic-bezier(.1,.7,.1,1);transition:opacity .15s,-webkit-transform .4s cubic-bezier(.1,.7,.1,1);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s,-webkit-transform .4s cubic-bezier(.1,.7,.1,1);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.md-header-nav__topic+.md-header-nav__topic{-webkit-transform:translateX(1.25rem);transform:translateX(1.25rem);-webkit-transition:opacity .15s,-webkit-transform .4s cubic-bezier(1,.7,.1,.1);transition:opacity .15s,-webkit-transform .4s cubic-bezier(1,.7,.1,.1);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s,-webkit-transform .4s cubic-bezier(1,.7,.1,.1);opacity:0;z-index:-1;pointer-events:none}[dir=rtl] .md-header-nav__topic+.md-header-nav__topic{-webkit-transform:translateX(-1.25rem);transform:translateX(-1.25rem)}.no-js .md-header-nav__topic{position:static}.no-js .md-header-nav__topic+.md-header-nav__topic{display:none}.md-header-nav__title{padding:0 1rem;font-size:.9rem;line-height:2.4rem}.md-header-nav__title[data-md-state=active] .md-header-nav__topic{-webkit-transform:translateX(-1.25rem);transform:translateX(-1.25rem);-webkit-transition:opacity .15s,-webkit-transform .4s cubic-bezier(1,.7,.1,.1);transition:opacity .15s,-webkit-transform .4s cubic-bezier(1,.7,.1,.1);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s,-webkit-transform .4s cubic-bezier(1,.7,.1,.1);opacity:0;z-index:-1;pointer-events:none}[dir=rtl] .md-header-nav__title[data-md-state=active] .md-header-nav__topic{-webkit-transform:translateX(1.25rem);transform:translateX(1.25rem)}.md-header-nav__title[data-md-state=active] .md-header-nav__topic+.md-header-nav__topic{-webkit-transform:translateX(0);transform:translateX(0);-webkit-transition:opacity .15s,-webkit-transform .4s cubic-bezier(.1,.7,.1,1);transition:opacity .15s,-webkit-transform .4s cubic-bezier(.1,.7,.1,1);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s,-webkit-transform .4s cubic-bezier(.1,.7,.1,1);opacity:1;z-index:0;pointer-events:auto}.md-header-nav__source{display:none}.md-hero{-webkit-transition:background .25s;transition:background .25s;background-color:#3f51b5;color:#fff;font-size:1rem;overflow:hidden}.md-hero__inner{margin-top:1rem;padding:.8rem .8rem .4rem;-webkit-transition:opacity .25s,-webkit-transform .4s cubic-bezier(.1,.7,.1,1);transition:opacity .25s,-webkit-transform .4s cubic-bezier(.1,.7,.1,1);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .25s;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .25s,-webkit-transform .4s cubic-bezier(.1,.7,.1,1);-webkit-transition-delay:.1s;transition-delay:.1s}[data-md-state=hidden] .md-hero__inner{pointer-events:none;-webkit-transform:translateY(.625rem);transform:translateY(.625rem);-webkit-transition:opacity .1s 0s,-webkit-transform 0s .4s;transition:opacity .1s 0s,-webkit-transform 0s .4s;transition:transform 0s .4s,opacity .1s 0s;transition:transform 0s .4s,opacity .1s 0s,-webkit-transform 0s .4s;opacity:0}.md-hero--expand .md-hero__inner{margin-bottom:1.2rem}.md-footer-nav{background-color:rgba(0,0,0,.87);color:#fff}.md-footer-nav__inner{padding:.2rem;overflow:auto}.md-footer-nav__link{padding-top:1.4rem;padding-bottom:.4rem;-webkit-transition:opacity .25s;transition:opacity .25s}.md-footer-nav__link:hover{opacity:.7}.md-footer-nav__link--prev{width:25%;float:left}[dir=rtl] .md-footer-nav__link--prev{float:right}.md-footer-nav__link--next{width:75%;float:right;text-align:right}[dir=rtl] .md-footer-nav__link--next{float:left;text-align:left}.md-footer-nav__button{-webkit-transition:background .25s;transition:background .25s}.md-footer-nav__title{position:relative;padding:0 1rem;font-size:.9rem;line-height:2.4rem}.md-footer-nav__direction{position:absolute;right:0;left:0;margin-top:-1rem;padding:0 1rem;color:hsla(0,0%,100%,.7);font-size:.75rem}.md-footer-meta{background-color:rgba(0,0,0,.895)}.md-footer-meta__inner{padding:.2rem;overflow:auto}html .md-footer-meta.md-typeset a{color:hsla(0,0%,100%,.7)}html .md-footer-meta.md-typeset a:focus,html .md-footer-meta.md-typeset a:hover{color:#fff}.md-footer-copyright{margin:0 .6rem;padding:.4rem 0;color:hsla(0,0%,100%,.3);font-size:.64rem}.md-footer-copyright__highlight{color:hsla(0,0%,100%,.7)}.md-footer-social{margin:0 .4rem;padding:.2rem 0 .6rem}.md-footer-social__link{display:inline-block;width:1.6rem;height:1.6rem;font-size:.8rem;text-align:center}.md-footer-social__link:before{line-height:1.9}.md-nav{font-size:.7rem;line-height:1.3}.md-nav__title{display:block;padding:0 .6rem;font-weight:700;text-overflow:ellipsis;overflow:hidden}.md-nav__title:before{display:none;content:"\E5C4"}[dir=rtl] .md-nav__title:before{content:"\E5C8"}.md-nav__title .md-nav__button{display:none}.md-nav__list{margin:0;padding:0;list-style:none}.md-nav__item{padding:0 .6rem}.md-nav__item:last-child{padding-bottom:.6rem}.md-nav__item .md-nav__item{padding-right:0}[dir=rtl] .md-nav__item .md-nav__item{padding-right:.6rem;padding-left:0}.md-nav__item .md-nav__item:last-child{padding-bottom:0}.md-nav__button img{width:100%;height:auto}.md-nav__link{display:block;margin-top:.625em;-webkit-transition:color .125s;transition:color .125s;text-overflow:ellipsis;cursor:pointer;overflow:hidden}.md-nav__item--nested>.md-nav__link:after{content:"\E313"}html .md-nav__link[for=__toc],html .md-nav__link[for=__toc]+.md-nav__link:after,html .md-nav__link[for=__toc]~.md-nav{display:none}.md-nav__link[data-md-state=blur]{color:rgba(0,0,0,.54)}.md-nav__link--active,.md-nav__link:active{color:#3f51b5}.md-nav__item--nested>.md-nav__link{color:inherit}.md-nav__link:focus,.md-nav__link:hover{color:#536dfe}.md-nav__source,.no-js .md-search{display:none}.md-search__overlay{opacity:0;z-index:1}.md-search__form{position:relative}.md-search__input{position:relative;padding:0 2.2rem 0 3.6rem;text-overflow:ellipsis;z-index:2}[dir=rtl] .md-search__input{padding:0 3.6rem 0 2.2rem}.md-search__input::-webkit-input-placeholder{-webkit-transition:color .25s cubic-bezier(.1,.7,.1,1);transition:color .25s cubic-bezier(.1,.7,.1,1)}.md-search__input::-moz-placeholder{-moz-transition:color .25s cubic-bezier(.1,.7,.1,1);transition:color .25s cubic-bezier(.1,.7,.1,1)}.md-search__input:-ms-input-placeholder{-ms-transition:color .25s cubic-bezier(.1,.7,.1,1);transition:color .25s cubic-bezier(.1,.7,.1,1)}.md-search__input::-ms-input-placeholder{-ms-transition:color .25s cubic-bezier(.1,.7,.1,1);transition:color .25s cubic-bezier(.1,.7,.1,1)}.md-search__input::placeholder{-webkit-transition:color .25s cubic-bezier(.1,.7,.1,1);transition:color .25s cubic-bezier(.1,.7,.1,1)}.md-search__input::-webkit-input-placeholder{color:rgba(0,0,0,.54)}.md-search__input::-moz-placeholder{color:rgba(0,0,0,.54)}.md-search__input:-ms-input-placeholder{color:rgba(0,0,0,.54)}.md-search__input::-ms-input-placeholder{color:rgba(0,0,0,.54)}.md-search__input::placeholder,.md-search__input~.md-search__icon{color:rgba(0,0,0,.54)}.md-search__input::-ms-clear{display:none}.md-search__icon{position:absolute;-webkit-transition:color .25s cubic-bezier(.1,.7,.1,1),opacity .25s;transition:color .25s cubic-bezier(.1,.7,.1,1),opacity .25s;font-size:1.2rem;cursor:pointer;z-index:2}.md-search__icon:hover{opacity:.7}.md-search__icon[for=__search]{top:.3rem;left:.5rem}[dir=rtl] .md-search__icon[for=__search]{right:.5rem;left:auto}.md-search__icon[for=__search]:before{content:"\E8B6"}.md-search__icon[type=reset]{top:.3rem;right:.5rem;-webkit-transform:scale(.125);transform:scale(.125);-webkit-transition:opacity .15s,-webkit-transform .15s cubic-bezier(.1,.7,.1,1);transition:opacity .15s,-webkit-transform .15s cubic-bezier(.1,.7,.1,1);transition:transform .15s cubic-bezier(.1,.7,.1,1),opacity .15s;transition:transform .15s cubic-bezier(.1,.7,.1,1),opacity .15s,-webkit-transform .15s cubic-bezier(.1,.7,.1,1);opacity:0}[dir=rtl] .md-search__icon[type=reset]{right:auto;left:.5rem}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__icon[type=reset]{-webkit-transform:scale(1);transform:scale(1);opacity:1}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__icon[type=reset]:hover{opacity:.7}.md-search__output{position:absolute;width:100%;border-radius:0 0 .1rem .1rem;overflow:hidden;z-index:1}.md-search__scrollwrap{height:100%;background-color:#fff;box-shadow:inset 0 .05rem 0 rgba(0,0,0,.07);overflow-y:auto;-webkit-overflow-scrolling:touch}.md-search-result{color:rgba(0,0,0,.87);word-break:break-word}.md-search-result__meta{padding:0 .8rem;background-color:rgba(0,0,0,.07);color:rgba(0,0,0,.54);font-size:.64rem;line-height:1.8rem}.md-search-result__list{margin:0;padding:0;border-top:.05rem solid rgba(0,0,0,.07);list-style:none}.md-search-result__item{box-shadow:0 -.05rem 0 rgba(0,0,0,.07)}.md-search-result__link{display:block;-webkit-transition:background .25s;transition:background .25s;outline:0;overflow:hidden}.md-search-result__link:hover,.md-search-result__link[data-md-state=active]{background-color:rgba(83,109,254,.1)}.md-search-result__link:hover .md-search-result__article:before,.md-search-result__link[data-md-state=active] .md-search-result__article:before{opacity:.7}.md-search-result__link:last-child .md-search-result__teaser{margin-bottom:.6rem}.md-search-result__article{position:relative;padding:0 .8rem;overflow:auto}.md-search-result__article--document:before{position:absolute;left:0;margin:.1rem;-webkit-transition:opacity .25s;transition:opacity .25s;color:rgba(0,0,0,.54);content:"\E880"}[dir=rtl] .md-search-result__article--document:before{right:0;left:auto}.md-search-result__article--document .md-search-result__title{margin:.55rem 0;font-size:.8rem;font-weight:400;line-height:1.4}.md-search-result__title{margin:.5em 0;font-size:.64rem;font-weight:700;line-height:1.4}.md-search-result__teaser{display:-webkit-box;max-height:1.65rem;margin:.5em 0;color:rgba(0,0,0,.54);font-size:.64rem;line-height:1.4;text-overflow:ellipsis;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:2}.md-search-result em{font-style:normal;font-weight:700;text-decoration:underline}.md-sidebar{position:absolute;width:12.1rem;padding:1.2rem 0;overflow:hidden}.md-sidebar[data-md-state=lock]{position:fixed;top:2.4rem}.md-sidebar--secondary{display:none}.md-sidebar__scrollwrap{max-height:100%;margin:0 .2rem;overflow-y:auto;-webkit-backface-visibility:hidden;backface-visibility:hidden}.md-sidebar__scrollwrap::-webkit-scrollbar{width:.2rem;height:.2rem}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb{background-color:rgba(0,0,0,.26)}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#536dfe}@-webkit-keyframes md-source__facts--done{0%{height:0}to{height:.65rem}}@keyframes md-source__facts--done{0%{height:0}to{height:.65rem}}@-webkit-keyframes md-source__fact--done{0%{-webkit-transform:translateY(100%);transform:translateY(100%);opacity:0}50%{opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}@keyframes md-source__fact--done{0%{-webkit-transform:translateY(100%);transform:translateY(100%);opacity:0}50%{opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}.md-source{display:block;padding-right:.6rem;-webkit-transition:opacity .25s;transition:opacity .25s;font-size:.65rem;line-height:1.2;white-space:nowrap}[dir=rtl] .md-source{padding-right:0;padding-left:.6rem}.md-source:hover{opacity:.7}.md-source:after,.md-source__icon{display:inline-block;height:2.4rem;content:"";vertical-align:middle}.md-source__icon{width:2.4rem}.md-source__icon svg{width:1.2rem;height:1.2rem;margin-top:.6rem;margin-left:.6rem}[dir=rtl] .md-source__icon svg{margin-right:.6rem;margin-left:0}.md-source__icon+.md-source__repository{margin-left:-2rem;padding-left:2rem}[dir=rtl] .md-source__icon+.md-source__repository{margin-right:-2rem;margin-left:0;padding-right:2rem;padding-left:0}.md-source__repository{display:inline-block;max-width:100%;margin-left:.6rem;font-weight:700;text-overflow:ellipsis;overflow:hidden;vertical-align:middle}.md-source__facts{margin:0;padding:0;font-size:.55rem;font-weight:700;list-style-type:none;opacity:.75;overflow:hidden}[data-md-state=done] .md-source__facts{-webkit-animation:md-source__facts--done .25s ease-in;animation:md-source__facts--done .25s ease-in}.md-source__fact{float:left}[dir=rtl] .md-source__fact{float:right}[data-md-state=done] .md-source__fact{-webkit-animation:md-source__fact--done .4s ease-out;animation:md-source__fact--done .4s ease-out}.md-source__fact:before{margin:0 .1rem;content:"\00B7"}.md-source__fact:first-child:before{display:none}.md-source-file{display:inline-block;margin:1em .5em 1em 0;padding-right:.25rem;border-radius:.1rem;background-color:rgba(0,0,0,.07);font-size:.64rem;list-style-type:none;cursor:pointer;overflow:hidden}.md-source-file:before{display:inline-block;margin-right:.25rem;padding:.25rem;background-color:rgba(0,0,0,.26);color:#fff;font-size:.8rem;content:"\E86F";vertical-align:middle}html .md-source-file{-webkit-transition:background .4s,color .4s,box-shadow .4s cubic-bezier(.4,0,.2,1);transition:background .4s,color .4s,box-shadow .4s cubic-bezier(.4,0,.2,1)}html .md-source-file:before{-webkit-transition:inherit;transition:inherit}html body .md-typeset .md-source-file{color:rgba(0,0,0,.54)}.md-source-file:hover{box-shadow:0 0 8px rgba(0,0,0,.18),0 8px 16px rgba(0,0,0,.36)}.md-source-file:hover:before{background-color:#536dfe}.md-tabs{width:100%;-webkit-transition:background .25s;transition:background .25s;background-color:#3f51b5;color:#fff;overflow:auto}.md-tabs__list{margin:0 0 0 .2rem;padding:0;list-style:none;white-space:nowrap}.md-tabs__item{display:inline-block;height:2.4rem;padding-right:.6rem;padding-left:.6rem}.md-tabs__link{display:block;margin-top:.8rem;-webkit-transition:opacity .25s,-webkit-transform .4s cubic-bezier(.1,.7,.1,1);transition:opacity .25s,-webkit-transform .4s cubic-bezier(.1,.7,.1,1);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .25s;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .25s,-webkit-transform .4s cubic-bezier(.1,.7,.1,1);font-size:.7rem;opacity:.7}.md-tabs__link--active,.md-tabs__link:hover{color:inherit;opacity:1}.md-tabs__item:nth-child(2) .md-tabs__link{-webkit-transition-delay:.02s;transition-delay:.02s}.md-tabs__item:nth-child(3) .md-tabs__link{-webkit-transition-delay:.04s;transition-delay:.04s}.md-tabs__item:nth-child(4) .md-tabs__link{-webkit-transition-delay:.06s;transition-delay:.06s}.md-tabs__item:nth-child(5) .md-tabs__link{-webkit-transition-delay:.08s;transition-delay:.08s}.md-tabs__item:nth-child(6) .md-tabs__link{-webkit-transition-delay:.1s;transition-delay:.1s}.md-tabs__item:nth-child(7) .md-tabs__link{-webkit-transition-delay:.12s;transition-delay:.12s}.md-tabs__item:nth-child(8) .md-tabs__link{-webkit-transition-delay:.14s;transition-delay:.14s}.md-tabs__item:nth-child(9) .md-tabs__link{-webkit-transition-delay:.16s;transition-delay:.16s}.md-tabs__item:nth-child(10) .md-tabs__link{-webkit-transition-delay:.18s;transition-delay:.18s}.md-tabs__item:nth-child(11) .md-tabs__link{-webkit-transition-delay:.2s;transition-delay:.2s}.md-tabs__item:nth-child(12) .md-tabs__link{-webkit-transition-delay:.22s;transition-delay:.22s}.md-tabs__item:nth-child(13) .md-tabs__link{-webkit-transition-delay:.24s;transition-delay:.24s}.md-tabs__item:nth-child(14) .md-tabs__link{-webkit-transition-delay:.26s;transition-delay:.26s}.md-tabs__item:nth-child(15) .md-tabs__link{-webkit-transition-delay:.28s;transition-delay:.28s}.md-tabs__item:nth-child(16) .md-tabs__link{-webkit-transition-delay:.3s;transition-delay:.3s}.md-tabs[data-md-state=hidden]{pointer-events:none}.md-tabs[data-md-state=hidden] .md-tabs__link{-webkit-transform:translateY(50%);transform:translateY(50%);-webkit-transition:color .25s,opacity .1s,-webkit-transform 0s .4s;transition:color .25s,opacity .1s,-webkit-transform 0s .4s;transition:color .25s,transform 0s .4s,opacity .1s;transition:color .25s,transform 0s .4s,opacity .1s,-webkit-transform 0s .4s;opacity:0}.md-typeset .admonition,.md-typeset details{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12),0 3px 1px -2px rgba(0,0,0,.2);position:relative;margin:1.5625em 0;padding:0 .6rem;border-left:.2rem solid #448aff;border-radius:.1rem;font-size:.64rem;overflow:auto}[dir=rtl] .md-typeset .admonition,[dir=rtl] .md-typeset details{border-right:.2rem solid #448aff;border-left:none}html .md-typeset .admonition>:last-child,html .md-typeset details>:last-child{margin-bottom:.6rem}.md-typeset .admonition .admonition,.md-typeset .admonition details,.md-typeset details .admonition,.md-typeset details details{margin:1em 0}.md-typeset .admonition>.admonition-title,.md-typeset .admonition>summary,.md-typeset details>.admonition-title,.md-typeset details>summary{margin:0 -.6rem;padding:.4rem .6rem .4rem 2rem;border-bottom:.05rem solid rgba(68,138,255,.1);background-color:rgba(68,138,255,.1);font-weight:700}[dir=rtl] .md-typeset .admonition>.admonition-title,[dir=rtl] .md-typeset .admonition>summary,[dir=rtl] .md-typeset details>.admonition-title,[dir=rtl] .md-typeset details>summary{padding:.4rem 2rem .4rem .6rem}.md-typeset .admonition>.admonition-title:last-child,.md-typeset .admonition>summary:last-child,.md-typeset details>.admonition-title:last-child,.md-typeset details>summary:last-child{margin-bottom:0}.md-typeset .admonition>.admonition-title:before,.md-typeset .admonition>summary:before,.md-typeset details>.admonition-title:before,.md-typeset details>summary:before{position:absolute;left:.6rem;color:#448aff;font-size:1rem;content:"\E3C9"}[dir=rtl] .md-typeset .admonition>.admonition-title:before,[dir=rtl] .md-typeset .admonition>summary:before,[dir=rtl] .md-typeset details>.admonition-title:before,[dir=rtl] .md-typeset details>summary:before{right:.6rem;left:auto}.md-typeset .admonition.abstract,.md-typeset .admonition.summary,.md-typeset .admonition.tldr,.md-typeset details.abstract,.md-typeset details.summary,.md-typeset details.tldr{border-left-color:#00b0ff}[dir=rtl] .md-typeset .admonition.abstract,[dir=rtl] .md-typeset .admonition.summary,[dir=rtl] .md-typeset .admonition.tldr,[dir=rtl] .md-typeset details.abstract,[dir=rtl] .md-typeset details.summary,[dir=rtl] .md-typeset details.tldr{border-right-color:#00b0ff}.md-typeset .admonition.abstract>.admonition-title,.md-typeset .admonition.abstract>summary,.md-typeset .admonition.summary>.admonition-title,.md-typeset .admonition.summary>summary,.md-typeset .admonition.tldr>.admonition-title,.md-typeset .admonition.tldr>summary,.md-typeset details.abstract>.admonition-title,.md-typeset details.abstract>summary,.md-typeset details.summary>.admonition-title,.md-typeset details.summary>summary,.md-typeset details.tldr>.admonition-title,.md-typeset details.tldr>summary{border-bottom-color:rgba(0,176,255,.1);background-color:rgba(0,176,255,.1)}.md-typeset .admonition.abstract>.admonition-title:before,.md-typeset .admonition.abstract>summary:before,.md-typeset .admonition.summary>.admonition-title:before,.md-typeset .admonition.summary>summary:before,.md-typeset .admonition.tldr>.admonition-title:before,.md-typeset .admonition.tldr>summary:before,.md-typeset details.abstract>.admonition-title:before,.md-typeset details.abstract>summary:before,.md-typeset details.summary>.admonition-title:before,.md-typeset details.summary>summary:before,.md-typeset details.tldr>.admonition-title:before,.md-typeset details.tldr>summary:before{color:#00b0ff;content:""}.md-typeset .admonition.info,.md-typeset .admonition.todo,.md-typeset details.info,.md-typeset details.todo{border-left-color:#00b8d4}[dir=rtl] .md-typeset .admonition.info,[dir=rtl] .md-typeset .admonition.todo,[dir=rtl] .md-typeset details.info,[dir=rtl] .md-typeset details.todo{border-right-color:#00b8d4}.md-typeset .admonition.info>.admonition-title,.md-typeset .admonition.info>summary,.md-typeset .admonition.todo>.admonition-title,.md-typeset .admonition.todo>summary,.md-typeset details.info>.admonition-title,.md-typeset details.info>summary,.md-typeset details.todo>.admonition-title,.md-typeset details.todo>summary{border-bottom-color:rgba(0,184,212,.1);background-color:rgba(0,184,212,.1)}.md-typeset .admonition.info>.admonition-title:before,.md-typeset .admonition.info>summary:before,.md-typeset .admonition.todo>.admonition-title:before,.md-typeset .admonition.todo>summary:before,.md-typeset details.info>.admonition-title:before,.md-typeset details.info>summary:before,.md-typeset details.todo>.admonition-title:before,.md-typeset details.todo>summary:before{color:#00b8d4;content:""}.md-typeset .admonition.hint,.md-typeset .admonition.important,.md-typeset .admonition.tip,.md-typeset details.hint,.md-typeset details.important,.md-typeset details.tip{border-left-color:#00bfa5}[dir=rtl] .md-typeset .admonition.hint,[dir=rtl] .md-typeset .admonition.important,[dir=rtl] .md-typeset .admonition.tip,[dir=rtl] .md-typeset details.hint,[dir=rtl] .md-typeset details.important,[dir=rtl] .md-typeset details.tip{border-right-color:#00bfa5}.md-typeset .admonition.hint>.admonition-title,.md-typeset .admonition.hint>summary,.md-typeset .admonition.important>.admonition-title,.md-typeset .admonition.important>summary,.md-typeset .admonition.tip>.admonition-title,.md-typeset .admonition.tip>summary,.md-typeset details.hint>.admonition-title,.md-typeset details.hint>summary,.md-typeset details.important>.admonition-title,.md-typeset details.important>summary,.md-typeset details.tip>.admonition-title,.md-typeset details.tip>summary{border-bottom-color:rgba(0,191,165,.1);background-color:rgba(0,191,165,.1)}.md-typeset .admonition.hint>.admonition-title:before,.md-typeset .admonition.hint>summary:before,.md-typeset .admonition.important>.admonition-title:before,.md-typeset .admonition.important>summary:before,.md-typeset .admonition.tip>.admonition-title:before,.md-typeset .admonition.tip>summary:before,.md-typeset details.hint>.admonition-title:before,.md-typeset details.hint>summary:before,.md-typeset details.important>.admonition-title:before,.md-typeset details.important>summary:before,.md-typeset details.tip>.admonition-title:before,.md-typeset details.tip>summary:before{color:#00bfa5;content:""}.md-typeset .admonition.check,.md-typeset .admonition.done,.md-typeset .admonition.success,.md-typeset details.check,.md-typeset details.done,.md-typeset details.success{border-left-color:#00c853}[dir=rtl] .md-typeset .admonition.check,[dir=rtl] .md-typeset .admonition.done,[dir=rtl] .md-typeset .admonition.success,[dir=rtl] .md-typeset details.check,[dir=rtl] .md-typeset details.done,[dir=rtl] .md-typeset details.success{border-right-color:#00c853}.md-typeset .admonition.check>.admonition-title,.md-typeset .admonition.check>summary,.md-typeset .admonition.done>.admonition-title,.md-typeset .admonition.done>summary,.md-typeset .admonition.success>.admonition-title,.md-typeset .admonition.success>summary,.md-typeset details.check>.admonition-title,.md-typeset details.check>summary,.md-typeset details.done>.admonition-title,.md-typeset details.done>summary,.md-typeset details.success>.admonition-title,.md-typeset details.success>summary{border-bottom-color:rgba(0,200,83,.1);background-color:rgba(0,200,83,.1)}.md-typeset .admonition.check>.admonition-title:before,.md-typeset .admonition.check>summary:before,.md-typeset .admonition.done>.admonition-title:before,.md-typeset .admonition.done>summary:before,.md-typeset .admonition.success>.admonition-title:before,.md-typeset .admonition.success>summary:before,.md-typeset details.check>.admonition-title:before,.md-typeset details.check>summary:before,.md-typeset details.done>.admonition-title:before,.md-typeset details.done>summary:before,.md-typeset details.success>.admonition-title:before,.md-typeset details.success>summary:before{color:#00c853;content:""}.md-typeset .admonition.faq,.md-typeset .admonition.help,.md-typeset .admonition.question,.md-typeset details.faq,.md-typeset details.help,.md-typeset details.question{border-left-color:#64dd17}[dir=rtl] .md-typeset .admonition.faq,[dir=rtl] .md-typeset .admonition.help,[dir=rtl] .md-typeset .admonition.question,[dir=rtl] .md-typeset details.faq,[dir=rtl] .md-typeset details.help,[dir=rtl] .md-typeset details.question{border-right-color:#64dd17}.md-typeset .admonition.faq>.admonition-title,.md-typeset .admonition.faq>summary,.md-typeset .admonition.help>.admonition-title,.md-typeset .admonition.help>summary,.md-typeset .admonition.question>.admonition-title,.md-typeset .admonition.question>summary,.md-typeset details.faq>.admonition-title,.md-typeset details.faq>summary,.md-typeset details.help>.admonition-title,.md-typeset details.help>summary,.md-typeset details.question>.admonition-title,.md-typeset details.question>summary{border-bottom-color:rgba(100,221,23,.1);background-color:rgba(100,221,23,.1)}.md-typeset .admonition.faq>.admonition-title:before,.md-typeset .admonition.faq>summary:before,.md-typeset .admonition.help>.admonition-title:before,.md-typeset .admonition.help>summary:before,.md-typeset .admonition.question>.admonition-title:before,.md-typeset .admonition.question>summary:before,.md-typeset details.faq>.admonition-title:before,.md-typeset details.faq>summary:before,.md-typeset details.help>.admonition-title:before,.md-typeset details.help>summary:before,.md-typeset details.question>.admonition-title:before,.md-typeset details.question>summary:before{color:#64dd17;content:""}.md-typeset .admonition.attention,.md-typeset .admonition.caution,.md-typeset .admonition.warning,.md-typeset details.attention,.md-typeset details.caution,.md-typeset details.warning{border-left-color:#ff9100}[dir=rtl] .md-typeset .admonition.attention,[dir=rtl] .md-typeset .admonition.caution,[dir=rtl] .md-typeset .admonition.warning,[dir=rtl] .md-typeset details.attention,[dir=rtl] .md-typeset details.caution,[dir=rtl] .md-typeset details.warning{border-right-color:#ff9100}.md-typeset .admonition.attention>.admonition-title,.md-typeset .admonition.attention>summary,.md-typeset .admonition.caution>.admonition-title,.md-typeset .admonition.caution>summary,.md-typeset .admonition.warning>.admonition-title,.md-typeset .admonition.warning>summary,.md-typeset details.attention>.admonition-title,.md-typeset details.attention>summary,.md-typeset details.caution>.admonition-title,.md-typeset details.caution>summary,.md-typeset details.warning>.admonition-title,.md-typeset details.warning>summary{border-bottom-color:rgba(255,145,0,.1);background-color:rgba(255,145,0,.1)}.md-typeset .admonition.attention>.admonition-title:before,.md-typeset .admonition.attention>summary:before,.md-typeset .admonition.caution>.admonition-title:before,.md-typeset .admonition.caution>summary:before,.md-typeset .admonition.warning>.admonition-title:before,.md-typeset .admonition.warning>summary:before,.md-typeset details.attention>.admonition-title:before,.md-typeset details.attention>summary:before,.md-typeset details.caution>.admonition-title:before,.md-typeset details.caution>summary:before,.md-typeset details.warning>.admonition-title:before,.md-typeset details.warning>summary:before{color:#ff9100;content:""}.md-typeset .admonition.fail,.md-typeset .admonition.failure,.md-typeset .admonition.missing,.md-typeset details.fail,.md-typeset details.failure,.md-typeset details.missing{border-left-color:#ff5252}[dir=rtl] .md-typeset .admonition.fail,[dir=rtl] .md-typeset .admonition.failure,[dir=rtl] .md-typeset .admonition.missing,[dir=rtl] .md-typeset details.fail,[dir=rtl] .md-typeset details.failure,[dir=rtl] .md-typeset details.missing{border-right-color:#ff5252}.md-typeset .admonition.fail>.admonition-title,.md-typeset .admonition.fail>summary,.md-typeset .admonition.failure>.admonition-title,.md-typeset .admonition.failure>summary,.md-typeset .admonition.missing>.admonition-title,.md-typeset .admonition.missing>summary,.md-typeset details.fail>.admonition-title,.md-typeset details.fail>summary,.md-typeset details.failure>.admonition-title,.md-typeset details.failure>summary,.md-typeset details.missing>.admonition-title,.md-typeset details.missing>summary{border-bottom-color:rgba(255,82,82,.1);background-color:rgba(255,82,82,.1)}.md-typeset .admonition.fail>.admonition-title:before,.md-typeset .admonition.fail>summary:before,.md-typeset .admonition.failure>.admonition-title:before,.md-typeset .admonition.failure>summary:before,.md-typeset .admonition.missing>.admonition-title:before,.md-typeset .admonition.missing>summary:before,.md-typeset details.fail>.admonition-title:before,.md-typeset details.fail>summary:before,.md-typeset details.failure>.admonition-title:before,.md-typeset details.failure>summary:before,.md-typeset details.missing>.admonition-title:before,.md-typeset details.missing>summary:before{color:#ff5252;content:""}.md-typeset .admonition.danger,.md-typeset .admonition.error,.md-typeset details.danger,.md-typeset details.error{border-left-color:#ff1744}[dir=rtl] .md-typeset .admonition.danger,[dir=rtl] .md-typeset .admonition.error,[dir=rtl] .md-typeset details.danger,[dir=rtl] .md-typeset details.error{border-right-color:#ff1744}.md-typeset .admonition.danger>.admonition-title,.md-typeset .admonition.danger>summary,.md-typeset .admonition.error>.admonition-title,.md-typeset .admonition.error>summary,.md-typeset details.danger>.admonition-title,.md-typeset details.danger>summary,.md-typeset details.error>.admonition-title,.md-typeset details.error>summary{border-bottom-color:rgba(255,23,68,.1);background-color:rgba(255,23,68,.1)}.md-typeset .admonition.danger>.admonition-title:before,.md-typeset .admonition.danger>summary:before,.md-typeset .admonition.error>.admonition-title:before,.md-typeset .admonition.error>summary:before,.md-typeset details.danger>.admonition-title:before,.md-typeset details.danger>summary:before,.md-typeset details.error>.admonition-title:before,.md-typeset details.error>summary:before{color:#ff1744;content:""}.md-typeset .admonition.bug,.md-typeset details.bug{border-left-color:#f50057}[dir=rtl] .md-typeset .admonition.bug,[dir=rtl] .md-typeset details.bug{border-right-color:#f50057}.md-typeset .admonition.bug>.admonition-title,.md-typeset .admonition.bug>summary,.md-typeset details.bug>.admonition-title,.md-typeset details.bug>summary{border-bottom-color:rgba(245,0,87,.1);background-color:rgba(245,0,87,.1)}.md-typeset .admonition.bug>.admonition-title:before,.md-typeset .admonition.bug>summary:before,.md-typeset details.bug>.admonition-title:before,.md-typeset details.bug>summary:before{color:#f50057;content:""}.md-typeset .admonition.example,.md-typeset details.example{border-left-color:#651fff}[dir=rtl] .md-typeset .admonition.example,[dir=rtl] .md-typeset details.example{border-right-color:#651fff}.md-typeset .admonition.example>.admonition-title,.md-typeset .admonition.example>summary,.md-typeset details.example>.admonition-title,.md-typeset details.example>summary{border-bottom-color:rgba(101,31,255,.1);background-color:rgba(101,31,255,.1)}.md-typeset .admonition.example>.admonition-title:before,.md-typeset .admonition.example>summary:before,.md-typeset details.example>.admonition-title:before,.md-typeset details.example>summary:before{color:#651fff;content:""}.md-typeset .admonition.cite,.md-typeset .admonition.quote,.md-typeset details.cite,.md-typeset details.quote{border-left-color:#9e9e9e}[dir=rtl] .md-typeset .admonition.cite,[dir=rtl] .md-typeset .admonition.quote,[dir=rtl] .md-typeset details.cite,[dir=rtl] .md-typeset details.quote{border-right-color:#9e9e9e}.md-typeset .admonition.cite>.admonition-title,.md-typeset .admonition.cite>summary,.md-typeset .admonition.quote>.admonition-title,.md-typeset .admonition.quote>summary,.md-typeset details.cite>.admonition-title,.md-typeset details.cite>summary,.md-typeset details.quote>.admonition-title,.md-typeset details.quote>summary{border-bottom-color:hsla(0,0%,62%,.1);background-color:hsla(0,0%,62%,.1)}.md-typeset .admonition.cite>.admonition-title:before,.md-typeset .admonition.cite>summary:before,.md-typeset .admonition.quote>.admonition-title:before,.md-typeset .admonition.quote>summary:before,.md-typeset details.cite>.admonition-title:before,.md-typeset details.cite>summary:before,.md-typeset details.quote>.admonition-title:before,.md-typeset details.quote>summary:before{color:#9e9e9e;content:""}.codehilite .o,.codehilite .ow,.md-typeset .highlight .o,.md-typeset .highlight .ow{color:inherit}.codehilite .ge,.md-typeset .highlight .ge{color:#000}.codehilite .gr,.md-typeset .highlight .gr{color:#a00}.codehilite .gh,.md-typeset .highlight .gh{color:#999}.codehilite .go,.md-typeset .highlight .go{color:#888}.codehilite .gp,.md-typeset .highlight .gp{color:#555}.codehilite .gs,.md-typeset .highlight .gs{color:inherit}.codehilite .gu,.md-typeset .highlight .gu{color:#aaa}.codehilite .gt,.md-typeset .highlight .gt{color:#a00}.codehilite .gd,.md-typeset .highlight .gd{background-color:#fdd}.codehilite .gi,.md-typeset .highlight .gi{background-color:#dfd}.codehilite .k,.md-typeset .highlight .k{color:#3b78e7}.codehilite .kc,.md-typeset .highlight .kc{color:#a71d5d}.codehilite .kd,.codehilite .kn,.md-typeset .highlight .kd,.md-typeset .highlight .kn{color:#3b78e7}.codehilite .kp,.md-typeset .highlight .kp{color:#a71d5d}.codehilite .kr,.codehilite .kt,.md-typeset .highlight .kr,.md-typeset .highlight .kt{color:#3e61a2}.codehilite .c,.codehilite .cm,.md-typeset .highlight .c,.md-typeset .highlight .cm{color:#999}.codehilite .cp,.md-typeset .highlight .cp{color:#666}.codehilite .c1,.codehilite .ch,.codehilite .cs,.md-typeset .highlight .c1,.md-typeset .highlight .ch,.md-typeset .highlight .cs{color:#999}.codehilite .na,.codehilite .nb,.md-typeset .highlight .na,.md-typeset .highlight .nb{color:#c2185b}.codehilite .bp,.md-typeset .highlight .bp{color:#3e61a2}.codehilite .nc,.md-typeset .highlight .nc{color:#c2185b}.codehilite .no,.md-typeset .highlight .no{color:#3e61a2}.codehilite .nd,.codehilite .ni,.md-typeset .highlight .nd,.md-typeset .highlight .ni{color:#666}.codehilite .ne,.codehilite .nf,.md-typeset .highlight .ne,.md-typeset .highlight .nf{color:#c2185b}.codehilite .nl,.md-typeset .highlight .nl{color:#3b5179}.codehilite .nn,.md-typeset .highlight .nn{color:#ec407a}.codehilite .nt,.md-typeset .highlight .nt{color:#3b78e7}.codehilite .nv,.codehilite .vc,.codehilite .vg,.codehilite .vi,.md-typeset .highlight .nv,.md-typeset .highlight .vc,.md-typeset .highlight .vg,.md-typeset .highlight .vi{color:#3e61a2}.codehilite .nx,.md-typeset .highlight .nx{color:#ec407a}.codehilite .il,.codehilite .m,.codehilite .mf,.codehilite .mh,.codehilite .mi,.codehilite .mo,.md-typeset .highlight .il,.md-typeset .highlight .m,.md-typeset .highlight .mf,.md-typeset .highlight .mh,.md-typeset .highlight .mi,.md-typeset .highlight .mo{color:#e74c3c}.codehilite .s,.codehilite .sb,.codehilite .sc,.md-typeset .highlight .s,.md-typeset .highlight .sb,.md-typeset .highlight .sc{color:#0d904f}.codehilite .sd,.md-typeset .highlight .sd{color:#999}.codehilite .s2,.md-typeset .highlight .s2{color:#0d904f}.codehilite .se,.codehilite .sh,.codehilite .si,.codehilite .sx,.md-typeset .highlight .se,.md-typeset .highlight .sh,.md-typeset .highlight .si,.md-typeset .highlight .sx{color:#183691}.codehilite .sr,.md-typeset .highlight .sr{color:#009926}.codehilite .s1,.codehilite .ss,.md-typeset .highlight .s1,.md-typeset .highlight .ss{color:#0d904f}.codehilite .err,.md-typeset .highlight .err{color:#a61717}.codehilite .w,.md-typeset .highlight .w{color:transparent}.codehilite .hll,.md-typeset .highlight .hll{display:block;margin:0 -.6rem;padding:0 .6rem;background-color:rgba(255,235,59,.5)}.md-typeset .codehilitetable,.md-typeset .highlighttable{display:block;overflow:hidden}.md-typeset .codehilitetable tbody,.md-typeset .codehilitetable td,.md-typeset .highlighttable tbody,.md-typeset .highlighttable td{display:block;padding:0}.md-typeset .codehilitetable tr,.md-typeset .highlighttable tr{display:-webkit-box;display:flex}.md-typeset .codehilitetable .linenodiv,.md-typeset .codehilitetable pre,.md-typeset .highlighttable .linenodiv,.md-typeset .highlighttable pre{margin:0;border-radius:0}.md-typeset .codehilitetable .linenodiv,.md-typeset .highlighttable .linenodiv{padding:.525rem .6rem}.md-typeset .codehilitetable .linenos,.md-typeset .highlighttable .linenos{background-color:rgba(0,0,0,.07);color:rgba(0,0,0,.26);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.md-typeset .codehilitetable .linenos pre,.md-typeset .highlighttable .linenos pre{background-color:transparent;color:inherit;text-align:right}.md-typeset .codehilitetable .code,.md-typeset .highlighttable .code{-webkit-box-flex:1;flex:1;overflow:hidden}.md-typeset>.codehilitetable,.md-typeset>.highlighttable{margin:1em 0;border-radius:.2em}.md-typeset [id^="fnref:"]{display:inline-block}.md-typeset [id^="fnref:"]:target{margin-top:-3.8rem;padding-top:3.8rem;pointer-events:none}.md-typeset [id^="fn:"]:before{display:none;height:0;content:""}.md-typeset [id^="fn:"]:target:before{display:block;margin-top:-3.5rem;padding-top:3.5rem;pointer-events:none}.md-typeset .footnote{color:rgba(0,0,0,.54);font-size:.64rem}.md-typeset .footnote ol{margin-left:0}.md-typeset .footnote li{-webkit-transition:color .25s;transition:color .25s}.md-typeset .footnote li:target{color:rgba(0,0,0,.87)}.md-typeset .footnote li :first-child{margin-top:0}.md-typeset .footnote li:hover .footnote-backref,.md-typeset .footnote li:target .footnote-backref{-webkit-transform:translateX(0);transform:translateX(0);opacity:1}.md-typeset .footnote li:hover .footnote-backref:hover,.md-typeset .footnote li:target .footnote-backref{color:#536dfe}.md-typeset .footnote-ref{display:inline-block;pointer-events:auto}.md-typeset .footnote-ref:before{display:inline;margin:0 .2em;border-left:.05rem solid rgba(0,0,0,.26);font-size:1.25em;content:"";vertical-align:-.25rem}.md-typeset .footnote-backref{display:inline-block;-webkit-transform:translateX(.25rem);transform:translateX(.25rem);-webkit-transition:color .25s,opacity .125s .125s,-webkit-transform .25s .125s;transition:color .25s,opacity .125s .125s,-webkit-transform .25s .125s;transition:transform .25s .125s,color .25s,opacity .125s .125s;transition:transform .25s .125s,color .25s,opacity .125s .125s,-webkit-transform .25s .125s;color:rgba(0,0,0,.26);font-size:0;opacity:0;vertical-align:text-bottom}[dir=rtl] .md-typeset .footnote-backref{-webkit-transform:translateX(-.25rem);transform:translateX(-.25rem)}.md-typeset .footnote-backref:before{display:inline-block;font-size:.8rem;content:"\E31B"}[dir=rtl] .md-typeset .footnote-backref:before{-webkit-transform:scaleX(-1);transform:scaleX(-1)}.md-typeset .headerlink{display:inline-block;margin-left:.5rem;-webkit-transform:translateY(.25rem);transform:translateY(.25rem);-webkit-transition:color .25s,opacity .125s .25s,-webkit-transform .25s .25s;transition:color .25s,opacity .125s .25s,-webkit-transform .25s .25s;transition:transform .25s .25s,color .25s,opacity .125s .25s;transition:transform .25s .25s,color .25s,opacity .125s .25s,-webkit-transform .25s .25s;opacity:0}[dir=rtl] .md-typeset .headerlink{margin-right:.5rem;margin-left:0}html body .md-typeset .headerlink{color:rgba(0,0,0,.26)}.md-typeset h1[id]:before{display:block;margin-top:-9px;padding-top:9px;content:""}.md-typeset h1[id]:target:before{margin-top:-3.45rem;padding-top:3.45rem}.md-typeset h1[id] .headerlink:focus,.md-typeset h1[id]:hover .headerlink,.md-typeset h1[id]:target .headerlink{-webkit-transform:translate(0);transform:translate(0);opacity:1}.md-typeset h1[id] .headerlink:focus,.md-typeset h1[id]:hover .headerlink:hover,.md-typeset h1[id]:target .headerlink{color:#536dfe}.md-typeset h2[id]:before{display:block;margin-top:-8px;padding-top:8px;content:""}.md-typeset h2[id]:target:before{margin-top:-3.4rem;padding-top:3.4rem}.md-typeset h2[id] .headerlink:focus,.md-typeset h2[id]:hover .headerlink,.md-typeset h2[id]:target .headerlink{-webkit-transform:translate(0);transform:translate(0);opacity:1}.md-typeset h2[id] .headerlink:focus,.md-typeset h2[id]:hover .headerlink:hover,.md-typeset h2[id]:target .headerlink{color:#536dfe}.md-typeset h3[id]:before{display:block;margin-top:-9px;padding-top:9px;content:""}.md-typeset h3[id]:target:before{margin-top:-3.45rem;padding-top:3.45rem}.md-typeset h3[id] .headerlink:focus,.md-typeset h3[id]:hover .headerlink,.md-typeset h3[id]:target .headerlink{-webkit-transform:translate(0);transform:translate(0);opacity:1}.md-typeset h3[id] .headerlink:focus,.md-typeset h3[id]:hover .headerlink:hover,.md-typeset h3[id]:target .headerlink{color:#536dfe}.md-typeset h4[id]:before{display:block;margin-top:-9px;padding-top:9px;content:""}.md-typeset h4[id]:target:before{margin-top:-3.45rem;padding-top:3.45rem}.md-typeset h4[id] .headerlink:focus,.md-typeset h4[id]:hover .headerlink,.md-typeset h4[id]:target .headerlink{-webkit-transform:translate(0);transform:translate(0);opacity:1}.md-typeset h4[id] .headerlink:focus,.md-typeset h4[id]:hover .headerlink:hover,.md-typeset h4[id]:target .headerlink{color:#536dfe}.md-typeset h5[id]:before{display:block;margin-top:-11px;padding-top:11px;content:""}.md-typeset h5[id]:target:before{margin-top:-3.55rem;padding-top:3.55rem}.md-typeset h5[id] .headerlink:focus,.md-typeset h5[id]:hover .headerlink,.md-typeset h5[id]:target .headerlink{-webkit-transform:translate(0);transform:translate(0);opacity:1}.md-typeset h5[id] .headerlink:focus,.md-typeset h5[id]:hover .headerlink:hover,.md-typeset h5[id]:target .headerlink{color:#536dfe}.md-typeset h6[id]:before{display:block;margin-top:-11px;padding-top:11px;content:""}.md-typeset h6[id]:target:before{margin-top:-3.55rem;padding-top:3.55rem}.md-typeset h6[id] .headerlink:focus,.md-typeset h6[id]:hover .headerlink,.md-typeset h6[id]:target .headerlink{-webkit-transform:translate(0);transform:translate(0);opacity:1}.md-typeset h6[id] .headerlink:focus,.md-typeset h6[id]:hover .headerlink:hover,.md-typeset h6[id]:target .headerlink{color:#536dfe}.md-typeset .MJXc-display{margin:.75em 0;padding:.75em 0;overflow:auto;-webkit-overflow-scrolling:touch}.md-typeset .MathJax_CHTML{outline:0}.md-typeset .critic.comment,.md-typeset del.critic,.md-typeset ins.critic{margin:0 .25em;padding:.0625em 0;border-radius:.1rem;-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset del.critic{background-color:#fdd;box-shadow:.25em 0 0 #fdd,-.25em 0 0 #fdd}.md-typeset ins.critic{background-color:#dfd;box-shadow:.25em 0 0 #dfd,-.25em 0 0 #dfd}.md-typeset .critic.comment{background-color:hsla(0,0%,92.5%,.5);color:#37474f;box-shadow:.25em 0 0 hsla(0,0%,92.5%,.5),-.25em 0 0 hsla(0,0%,92.5%,.5)}.md-typeset .critic.comment:before{padding-right:.125em;color:rgba(0,0,0,.26);content:"\E0B7";vertical-align:-.125em}.md-typeset .critic.block{display:block;margin:1em 0;padding-right:.8rem;padding-left:.8rem;box-shadow:none}.md-typeset .critic.block :first-child{margin-top:.5em}.md-typeset .critic.block :last-child{margin-bottom:.5em}.md-typeset details{display:block;padding-top:0}.md-typeset details[open]>summary:after{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.md-typeset details:not([open]){padding-bottom:0}.md-typeset details:not([open])>summary{border-bottom:none}.md-typeset details summary{padding-right:2rem}[dir=rtl] .md-typeset details summary{padding-left:2rem}.no-details .md-typeset details:not([open])>*{display:none}.no-details .md-typeset details:not([open]) summary{display:block}.md-typeset summary{display:block;outline:none;cursor:pointer}.md-typeset summary::-webkit-details-marker{display:none}.md-typeset summary:after{position:absolute;top:.4rem;right:.6rem;color:rgba(0,0,0,.26);font-size:1rem;content:"\E313"}[dir=rtl] .md-typeset summary:after{right:auto;left:.6rem}.md-typeset .emojione,.md-typeset .gemoji,.md-typeset .twemoji{width:1rem;vertical-align:text-top}.md-typeset code.codehilite,.md-typeset code.highlight{margin:0 .29412em;padding:.07353em 0}.md-typeset .superfences-content{display:none;-webkit-box-ordinal-group:100;order:99;width:100%;background-color:#fff}.md-typeset .superfences-content pre{margin:0;border-radius:0}.md-typeset .superfences-tabs{display:-webkit-box;display:flex;position:relative;flex-wrap:wrap;margin:1em 0;border:.05rem solid rgba(0,0,0,.07);border-radius:.2em}.md-typeset .superfences-tabs>input{display:none}.md-typeset .superfences-tabs>input:checked+label{font-weight:700}.md-typeset .superfences-tabs>input:checked+label+.superfences-content{display:block}.md-typeset .superfences-tabs>label{width:auto;padding:.6rem;-webkit-transition:color .125s;transition:color .125s;font-size:.64rem;cursor:pointer}html .md-typeset .superfences-tabs>label:hover{color:#536dfe}.md-typeset .task-list-item{position:relative;list-style-type:none}.md-typeset .task-list-item [type=checkbox]{position:absolute;top:.45em;left:-2em}[dir=rtl] .md-typeset .task-list-item [type=checkbox]{right:-2em;left:auto}.md-typeset .task-list-control .task-list-indicator:before{position:absolute;top:.15em;left:-1.25em;color:rgba(0,0,0,.26);font-size:1.25em;content:"\E835";vertical-align:-.25em}[dir=rtl] .md-typeset .task-list-control .task-list-indicator:before{right:-1.25em;left:auto}.md-typeset .task-list-control [type=checkbox]:checked+.task-list-indicator:before{content:"\E834"}.md-typeset .task-list-control [type=checkbox]{opacity:0;z-index:-1}@media print{.md-typeset a:after{color:rgba(0,0,0,.54);content:" [" attr(href) "]"}.md-typeset code,.md-typeset pre{white-space:pre-wrap}.md-typeset code{box-shadow:none;-webkit-box-decoration-break:initial;box-decoration-break:slice}.md-clipboard,.md-content__icon,.md-footer,.md-header,.md-sidebar,.md-tabs,.md-typeset .headerlink{display:none}}@media only screen and (max-width:44.9375em){.md-typeset>pre{margin:1em -.8rem;border-radius:0}.md-typeset>pre>code{padding:.525rem .8rem}.md-footer-nav__link--prev .md-footer-nav__title{display:none}.md-search-result__teaser{max-height:2.5rem;-webkit-line-clamp:3}.codehilite .hll,.md-typeset .highlight .hll{margin:0 -.8rem;padding:0 .8rem}.md-typeset>.codehilite,.md-typeset>.highlight{margin:1em -.8rem}.md-typeset>.codehilite code,.md-typeset>.highlight code{padding:.525rem .8rem}.md-typeset>.codehilitetable,.md-typeset>.highlighttable{margin:1em -.8rem;border-radius:0}.md-typeset>.codehilitetable .linenodiv,.md-typeset>.highlighttable .linenodiv{padding:.5rem .8rem}.md-typeset>p>.MJXc-display{margin:.75em -.8rem;padding:.25em .8rem}.md-typeset>.superfences-tabs{margin:1em -.8rem;border:0;border-top:.05rem solid rgba(0,0,0,.07);border-radius:0}.md-typeset>.superfences-tabs code{padding:.525rem .8rem}.md-typeset>.superfences-tabs input:first-child+label{margin-left:.2rem}}@media only screen and (min-width:100em){html{font-size:137.5%}}@media only screen and (min-width:125em){html{font-size:150%}}@media only screen and (max-width:59.9375em){body[data-md-state=lock]{overflow:hidden}.ios body[data-md-state=lock] .md-container{display:none}html .md-nav__link[for=__toc]{display:block;padding-right:2.4rem}html .md-nav__link[for=__toc]:after{color:inherit;content:"\E8DE"}html .md-nav__link[for=__toc]+.md-nav__link{display:none}html .md-nav__link[for=__toc]~.md-nav{display:-webkit-box;display:flex}html [dir=rtl] .md-nav__link{padding-right:.8rem;padding-left:2.4rem}.md-nav__source{display:block;padding:0 .2rem;background-color:rgba(50,64,144,.9675);color:#fff}.md-search__overlay{position:absolute;top:.2rem;left:.2rem;width:1.8rem;height:1.8rem;-webkit-transform-origin:center;transform-origin:center;-webkit-transition:opacity .2s .2s,-webkit-transform .3s .1s;transition:opacity .2s .2s,-webkit-transform .3s .1s;transition:transform .3s .1s,opacity .2s .2s;transition:transform .3s .1s,opacity .2s .2s,-webkit-transform .3s .1s;border-radius:1rem;background-color:#fff;overflow:hidden;pointer-events:none}[dir=rtl] .md-search__overlay{right:.2rem;left:auto}[data-md-toggle=search]:checked~.md-header .md-search__overlay{-webkit-transition:opacity .1s,-webkit-transform .4s;transition:opacity .1s,-webkit-transform .4s;transition:transform .4s,opacity .1s;transition:transform .4s,opacity .1s,-webkit-transform .4s;opacity:1}.md-search__inner{position:fixed;top:0;left:100%;width:100%;height:100%;-webkit-transform:translateX(5%);transform:translateX(5%);-webkit-transition:right 0s .3s,left 0s .3s,opacity .15s .15s,-webkit-transform .15s cubic-bezier(.4,0,.2,1) .15s;transition:right 0s .3s,left 0s .3s,opacity .15s .15s,-webkit-transform .15s cubic-bezier(.4,0,.2,1) .15s;transition:right 0s .3s,left 0s .3s,transform .15s cubic-bezier(.4,0,.2,1) .15s,opacity .15s .15s;transition:right 0s .3s,left 0s .3s,transform .15s cubic-bezier(.4,0,.2,1) .15s,opacity .15s .15s,-webkit-transform .15s cubic-bezier(.4,0,.2,1) .15s;opacity:0;z-index:2}[data-md-toggle=search]:checked~.md-header .md-search__inner{left:0;-webkit-transform:translateX(0);transform:translateX(0);-webkit-transition:right 0s 0s,left 0s 0s,opacity .15s .15s,-webkit-transform .15s cubic-bezier(.1,.7,.1,1) .15s;transition:right 0s 0s,left 0s 0s,opacity .15s .15s,-webkit-transform .15s cubic-bezier(.1,.7,.1,1) .15s;transition:right 0s 0s,left 0s 0s,transform .15s cubic-bezier(.1,.7,.1,1) .15s,opacity .15s .15s;transition:right 0s 0s,left 0s 0s,transform .15s cubic-bezier(.1,.7,.1,1) .15s,opacity .15s .15s,-webkit-transform .15s cubic-bezier(.1,.7,.1,1) .15s;opacity:1}[dir=rtl] [data-md-toggle=search]:checked~.md-header .md-search__inner{right:0;left:auto}html [dir=rtl] .md-search__inner{right:100%;left:auto;-webkit-transform:translateX(-5%);transform:translateX(-5%)}.md-search__input{width:100%;height:2.4rem;font-size:.9rem}.md-search__icon[for=__search]{top:.6rem;left:.8rem}.md-search__icon[for=__search][for=__search]:before{content:"\E5C4"}[dir=rtl] .md-search__icon[for=__search][for=__search]:before{content:"\E5C8"}.md-search__icon[type=reset]{top:.6rem;right:.8rem}.md-search__output{top:2.4rem;bottom:0}.md-search-result__article--document:before{display:none}}@media only screen and (max-width:76.1875em){[data-md-toggle=drawer]:checked~.md-overlay{width:100%;height:100%;-webkit-transition:width 0s,height 0s,opacity .25s;transition:width 0s,height 0s,opacity .25s;opacity:1}.md-header-nav__button.md-icon--home,.md-header-nav__button.md-logo{display:none}.md-hero__inner{margin-top:2.4rem;margin-bottom:1.2rem}.md-nav{background-color:#fff}.md-nav--primary,.md-nav--primary .md-nav{display:-webkit-box;display:flex;position:absolute;top:0;right:0;left:0;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-direction:column;height:100%;z-index:1}.md-nav--primary .md-nav__item,.md-nav--primary .md-nav__title{font-size:.8rem;line-height:1.5}html .md-nav--primary .md-nav__title{position:relative;height:5.6rem;padding:3rem .8rem .2rem;background-color:rgba(0,0,0,.07);color:rgba(0,0,0,.54);font-weight:400;line-height:2.4rem;white-space:nowrap;cursor:pointer}html .md-nav--primary .md-nav__title:before{display:block;position:absolute;top:.2rem;left:.2rem;width:2rem;height:2rem;color:rgba(0,0,0,.54)}html .md-nav--primary .md-nav__title~.md-nav__list{background-color:#fff;box-shadow:inset 0 .05rem 0 rgba(0,0,0,.07)}html .md-nav--primary .md-nav__title~.md-nav__list>.md-nav__item:first-child{border-top:0}html .md-nav--primary .md-nav__title--site{position:relative;background-color:#3f51b5;color:#fff}html .md-nav--primary .md-nav__title--site .md-nav__button{display:block;position:absolute;top:.2rem;left:.2rem;width:3.2rem;height:3.2rem;font-size:2.4rem}html .md-nav--primary .md-nav__title--site:before{display:none}html [dir=rtl] .md-nav--primary .md-nav__title--site .md-nav__button,html [dir=rtl] .md-nav--primary .md-nav__title:before{right:.2rem;left:auto}.md-nav--primary .md-nav__list{-webkit-box-flex:1;flex:1;overflow-y:auto}.md-nav--primary .md-nav__item{padding:0;border-top:.05rem solid rgba(0,0,0,.07)}[dir=rtl] .md-nav--primary .md-nav__item{padding:0}.md-nav--primary .md-nav__item--nested>.md-nav__link{padding-right:2.4rem}[dir=rtl] .md-nav--primary .md-nav__item--nested>.md-nav__link{padding-right:.8rem;padding-left:2.4rem}.md-nav--primary .md-nav__item--nested>.md-nav__link:after{content:"\E315"}[dir=rtl] .md-nav--primary .md-nav__item--nested>.md-nav__link:after{content:"\E314"}.md-nav--primary .md-nav__link{position:relative;margin-top:0;padding:.6rem .8rem}.md-nav--primary .md-nav__link:after{position:absolute;top:50%;right:.6rem;margin-top:-.6rem;color:inherit;font-size:1.2rem}[dir=rtl] .md-nav--primary .md-nav__link:after{right:auto;left:.6rem}.md-nav--primary .md-nav--secondary .md-nav__link{position:static}.md-nav--primary .md-nav--secondary .md-nav{position:static;background-color:transparent}.md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-left:1.4rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-right:1.4rem;padding-left:0}.md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-left:2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-right:2rem;padding-left:0}.md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-left:2.6rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-right:2.6rem;padding-left:0}.md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-left:3.2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-right:3.2rem;padding-left:0}.md-nav__toggle~.md-nav{display:-webkit-box;display:flex;-webkit-transform:translateX(100%);transform:translateX(100%);-webkit-transition:opacity .125s .05s,-webkit-transform .25s cubic-bezier(.8,0,.6,1);transition:opacity .125s .05s,-webkit-transform .25s cubic-bezier(.8,0,.6,1);transition:transform .25s cubic-bezier(.8,0,.6,1),opacity .125s .05s;transition:transform .25s cubic-bezier(.8,0,.6,1),opacity .125s .05s,-webkit-transform .25s cubic-bezier(.8,0,.6,1);opacity:0}[dir=rtl] .md-nav__toggle~.md-nav{-webkit-transform:translateX(-100%);transform:translateX(-100%)}.no-csstransforms3d .md-nav__toggle~.md-nav{display:none}.md-nav__toggle:checked~.md-nav{-webkit-transform:translateX(0);transform:translateX(0);-webkit-transition:opacity .125s .125s,-webkit-transform .25s cubic-bezier(.4,0,.2,1);transition:opacity .125s .125s,-webkit-transform .25s cubic-bezier(.4,0,.2,1);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity .125s .125s;transition:transform .25s cubic-bezier(.4,0,.2,1),opacity .125s .125s,-webkit-transform .25s cubic-bezier(.4,0,.2,1);opacity:1}.no-csstransforms3d .md-nav__toggle:checked~.md-nav{display:-webkit-box;display:flex}.md-sidebar--primary{position:fixed;top:0;left:-12.1rem;width:12.1rem;height:100%;-webkit-transform:translateX(0);transform:translateX(0);-webkit-transition:box-shadow .25s,-webkit-transform .25s cubic-bezier(.4,0,.2,1);transition:box-shadow .25s,-webkit-transform .25s cubic-bezier(.4,0,.2,1);transition:transform .25s cubic-bezier(.4,0,.2,1),box-shadow .25s;transition:transform .25s cubic-bezier(.4,0,.2,1),box-shadow .25s,-webkit-transform .25s cubic-bezier(.4,0,.2,1);background-color:#fff;z-index:3}[dir=rtl] .md-sidebar--primary{right:-12.1rem;left:auto}.no-csstransforms3d .md-sidebar--primary{display:none}[data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{box-shadow:0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12),0 5px 5px -3px rgba(0,0,0,.4);-webkit-transform:translateX(12.1rem);transform:translateX(12.1rem)}[dir=rtl] [data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{-webkit-transform:translateX(-12.1rem);transform:translateX(-12.1rem)}.no-csstransforms3d [data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{display:block}.md-sidebar--primary .md-sidebar__scrollwrap{overflow:hidden;position:absolute;top:0;right:0;bottom:0;left:0;margin:0}.md-tabs{display:none}}@media only screen and (min-width:60em){.md-content{margin-right:12.1rem}[dir=rtl] .md-content{margin-right:0;margin-left:12.1rem}.md-header-nav__button.md-icon--search{display:none}.md-header-nav__source{display:block;width:11.7rem;max-width:11.7rem;padding-right:.6rem}[dir=rtl] .md-header-nav__source{padding-right:0;padding-left:.6rem}.md-search{padding:.2rem}.md-search__overlay{position:fixed;top:0;left:0;width:0;height:0;-webkit-transition:width 0s .25s,height 0s .25s,opacity .25s;transition:width 0s .25s,height 0s .25s,opacity .25s;background-color:rgba(0,0,0,.54);cursor:pointer}[dir=rtl] .md-search__overlay{right:0;left:auto}[data-md-toggle=search]:checked~.md-header .md-search__overlay{width:100%;height:100%;-webkit-transition:width 0s,height 0s,opacity .25s;transition:width 0s,height 0s,opacity .25s;opacity:1}.md-search__inner{position:relative;width:11.5rem;margin-right:.8rem;padding:.1rem 0;float:right;-webkit-transition:width .25s cubic-bezier(.1,.7,.1,1);transition:width .25s cubic-bezier(.1,.7,.1,1)}[dir=rtl] .md-search__inner{margin-right:0;margin-left:.8rem;float:left}.md-search__form,.md-search__input{border-radius:.1rem}.md-search__input{width:100%;height:1.8rem;padding-left:2.2rem;-webkit-transition:background-color .25s cubic-bezier(.1,.7,.1,1),color .25s cubic-bezier(.1,.7,.1,1);transition:background-color .25s cubic-bezier(.1,.7,.1,1),color .25s cubic-bezier(.1,.7,.1,1);background-color:rgba(0,0,0,.26);color:inherit;font-size:.8rem}[dir=rtl] .md-search__input{padding-right:2.2rem}.md-search__input+.md-search__icon{color:inherit}.md-search__input::-webkit-input-placeholder{color:hsla(0,0%,100%,.7)}.md-search__input::-moz-placeholder{color:hsla(0,0%,100%,.7)}.md-search__input:-ms-input-placeholder{color:hsla(0,0%,100%,.7)}.md-search__input::-ms-input-placeholder{color:hsla(0,0%,100%,.7)}.md-search__input::placeholder{color:hsla(0,0%,100%,.7)}.md-search__input:hover{background-color:hsla(0,0%,100%,.12)}[data-md-toggle=search]:checked~.md-header .md-search__input{border-radius:.1rem .1rem 0 0;background-color:#fff;color:rgba(0,0,0,.87);text-overflow:clip}[data-md-toggle=search]:checked~.md-header .md-search__input::-webkit-input-placeholder{color:rgba(0,0,0,.54)}[data-md-toggle=search]:checked~.md-header .md-search__input::-moz-placeholder{color:rgba(0,0,0,.54)}[data-md-toggle=search]:checked~.md-header .md-search__input:-ms-input-placeholder{color:rgba(0,0,0,.54)}[data-md-toggle=search]:checked~.md-header .md-search__input::-ms-input-placeholder{color:rgba(0,0,0,.54)}[data-md-toggle=search]:checked~.md-header .md-search__input+.md-search__icon,[data-md-toggle=search]:checked~.md-header .md-search__input::placeholder{color:rgba(0,0,0,.54)}.md-search__output{top:1.9rem;-webkit-transition:opacity .4s;transition:opacity .4s;opacity:0}[data-md-toggle=search]:checked~.md-header .md-search__output{box-shadow:0 6px 10px 0 rgba(0,0,0,.14),0 1px 18px 0 rgba(0,0,0,.12),0 3px 5px -1px rgba(0,0,0,.4);opacity:1}.md-search__scrollwrap{max-height:0}[data-md-toggle=search]:checked~.md-header .md-search__scrollwrap{max-height:75vh}.md-search__scrollwrap::-webkit-scrollbar{width:.2rem;height:.2rem}.md-search__scrollwrap::-webkit-scrollbar-thumb{background-color:rgba(0,0,0,.26)}.md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#536dfe}.md-search-result__meta{padding-left:2.2rem}[dir=rtl] .md-search-result__meta{padding-right:2.2rem;padding-left:0}.md-search-result__article{padding-left:2.2rem}[dir=rtl] .md-search-result__article{padding-right:2.2rem;padding-left:.8rem}.md-sidebar--secondary{display:block;margin-left:100%;-webkit-transform:translate(-100%);transform:translate(-100%)}[dir=rtl] .md-sidebar--secondary{margin-right:100%;margin-left:0;-webkit-transform:translate(100%);transform:translate(100%)}}@media only screen and (min-width:76.25em){.md-content{margin-left:12.1rem}[dir=rtl] .md-content{margin-right:12.1rem}.md-content__inner{margin-right:1.2rem;margin-left:1.2rem}.md-header-nav__button.md-icon--menu{display:none}.md-nav[data-md-state=animate]{-webkit-transition:max-height .25s cubic-bezier(.86,0,.07,1);transition:max-height .25s cubic-bezier(.86,0,.07,1)}.md-nav__toggle~.md-nav{max-height:0;overflow:hidden}.no-js .md-nav__toggle~.md-nav{display:none}.md-nav[data-md-state=expand],.md-nav__toggle:checked~.md-nav{max-height:100%}.no-js .md-nav[data-md-state=expand],.no-js .md-nav__toggle:checked~.md-nav{display:block}.md-nav__item--nested>.md-nav>.md-nav__title{display:none}.md-nav__item--nested>.md-nav__link:after{display:inline-block;-webkit-transform-origin:.45em .45em;transform-origin:.45em .45em;-webkit-transform-style:preserve-3d;transform-style:preserve-3d;vertical-align:-.125em}.js .md-nav__item--nested>.md-nav__link:after{-webkit-transition:-webkit-transform .4s;transition:-webkit-transform .4s;transition:transform .4s;transition:transform .4s,-webkit-transform .4s}.md-nav__item--nested .md-nav__toggle:checked~.md-nav__link:after{-webkit-transform:rotateX(180deg);transform:rotateX(180deg)}.md-search__inner{margin-right:1.2rem}[dir=rtl] .md-search__inner{margin-left:1.2rem}.md-search__scrollwrap,[data-md-toggle=search]:checked~.md-header .md-search__inner{width:34.4rem}.md-sidebar--secondary{margin-left:61rem}[dir=rtl] .md-sidebar--secondary{margin-right:61rem;margin-left:0}.md-tabs~.md-main .md-nav--primary>.md-nav__list>.md-nav__item--nested{font-size:0;visibility:hidden}.md-tabs--active~.md-main .md-nav--primary .md-nav__title{display:block;padding:0}.md-tabs--active~.md-main .md-nav--primary .md-nav__title--site{display:none}.no-js .md-tabs--active~.md-main .md-nav--primary .md-nav{display:block}.md-tabs--active~.md-main .md-nav--primary>.md-nav__list>.md-nav__item{font-size:0;visibility:hidden}.md-tabs--active~.md-main .md-nav--primary>.md-nav__list>.md-nav__item--nested{display:none;font-size:.7rem;overflow:auto;visibility:visible}.md-tabs--active~.md-main .md-nav--primary>.md-nav__list>.md-nav__item--nested>.md-nav__link{display:none}.md-tabs--active~.md-main .md-nav--primary>.md-nav__list>.md-nav__item--active{display:block}.md-tabs--active~.md-main .md-nav[data-md-level="1"]{max-height:none;overflow:visible}.md-tabs--active~.md-main .md-nav[data-md-level="1"]>.md-nav__list>.md-nav__item{padding-left:0}.md-tabs--active~.md-main .md-nav[data-md-level="1"] .md-nav .md-nav__title{display:none}}@media only screen and (min-width:45em){.md-footer-nav__link{width:50%}.md-footer-copyright{max-width:75%;float:left}[dir=rtl] .md-footer-copyright{float:right}.md-footer-social{padding:.6rem 0;float:right}[dir=rtl] .md-footer-social{float:left}}@media only screen and (max-width:29.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{-webkit-transform:scale(45);transform:scale(45)}}@media only screen and (min-width:30em) and (max-width:44.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{-webkit-transform:scale(60);transform:scale(60)}}@media only screen and (min-width:45em) and (max-width:59.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{-webkit-transform:scale(75);transform:scale(75)}}@media only screen and (min-width:60em) and (max-width:76.1875em){.md-search__scrollwrap,[data-md-toggle=search]:checked~.md-header .md-search__inner{width:23.4rem}.md-search-result__teaser{max-height:2.5rem;-webkit-line-clamp:3}} \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-auto_hinter.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-auto_hinter.html deleted file mode 100644 index 80ccfd724..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-auto_hinter.html +++ /dev/null @@ -1,1158 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The auto-hinter - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -

- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Controlling FreeType Modules » The auto-hinter

-
-

The auto-hinter

-

Synopsis

-

While FreeType's auto-hinter doesn't expose API functions by itself, it is possible to control its behaviour with FT_Property_Set and FT_Property_Get. The following lists the available properties together with the necessary macros and structures.

-

Note that the auto-hinter's module name is ‘autofitter’ for historical reasons.

-

Available properties are increase-x-height, no-stem-darkening (experimental), darkening-parameters (experimental), warping (experimental), glyph-to-script-map (experimental), fallback-script (experimental), and default-script (experimental), as documented in the ‘Driver properties’ section.

- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-base_interface.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-base_interface.html deleted file mode 100644 index 25f219dbb..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-base_interface.html +++ /dev/null @@ -1,5109 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Base Interface - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Core API » Base Interface

-
-

Base Interface

-

Synopsis

-

This section describes the most important public high-level API functions of FreeType 2.

-

FT_Library

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct FT_LibraryRec_  *FT_Library;
-
- -

A handle to a FreeType library instance. Each ‘library’ is completely independent from the others; it is the ‘root’ of a set of objects like fonts, faces, sizes, etc.

-

It also embeds a memory manager (see FT_Memory), as well as a scan-line converter object (see FT_Raster).

-

[Since 2.5.6] In multi-threaded applications it is easiest to use one FT_Library object per thread. In case this is too cumbersome, a single FT_Library object across threads is possible also, as long as a mutex lock is used around FT_New_Face and FT_Done_Face.

-

note

- -

Library objects are normally created by FT_Init_FreeType, and destroyed with FT_Done_FreeType. If you need reference-counting (cf. FT_Reference_Library), use FT_New_Library and FT_Done_Library.

-
- -

FT_Face

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct FT_FaceRec_*  FT_Face;
-
- -

A handle to a typographic face object. A face object models a given typeface, in a given style.

-

note

- -

A face object also owns a single FT_GlyphSlot object, as well as one or more FT_Size objects.

-

Use FT_New_Face or FT_Open_Face to create a new face object from a given filepath or a custom input stream.

-

Use FT_Done_Face to destroy it (along with its slot and sizes).

-

An FT_Face object can only be safely used from one thread at a time. Similarly, creation and destruction of FT_Face with the same FT_Library object can only be done from one thread at a time. On the other hand, functions like FT_Load_Glyph and its siblings are thread-safe and do not need the lock to be held as long as the same FT_Face object is not used from multiple threads at the same time.

-

also

- -

See FT_FaceRec for the publicly accessible fields of a given face object.

-
- -

FT_Size

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct FT_SizeRec_*  FT_Size;
-
- -

A handle to an object that models a face scaled to a given character size.

-

note

- -

An FT_Face has one active FT_Size object that is used by functions like FT_Load_Glyph to determine the scaling transformation that in turn is used to load and hint glyphs and metrics.

-

You can use FT_Set_Char_Size, FT_Set_Pixel_Sizes, FT_Request_Size or even FT_Select_Size to change the content (i.e., the scaling values) of the active FT_Size.

-

You can use FT_New_Size to create additional size objects for a given FT_Face, but they won't be used by other functions until you activate it through FT_Activate_Size. Only one size can be activated at any given time per face.

-

also

- -

See FT_SizeRec for the publicly accessible fields of a given size object.

-
- -

FT_GlyphSlot

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct FT_GlyphSlotRec_*  FT_GlyphSlot;
-
- -

A handle to a given ‘glyph slot’. A slot is a container that can hold any of the glyphs contained in its parent face.

-

In other words, each time you call FT_Load_Glyph or FT_Load_Char, the slot's content is erased by the new glyph data, i.e., the glyph's metrics, its image (bitmap or outline), and other control information.

-

also

- -

See FT_GlyphSlotRec for the publicly accessible glyph fields.

-
- -

FT_CharMap

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct FT_CharMapRec_*  FT_CharMap;
-
- -

A handle to a character map (usually abbreviated to ‘charmap’). A charmap is used to translate character codes in a given encoding into glyph indexes for its parent's face. Some font formats may provide several charmaps per font.

-

Each face object owns zero or more charmaps, but only one of them can be ‘active’, providing the data used by FT_Get_Char_Index or FT_Load_Char.

-

The list of available charmaps in a face is available through the face->num_charmaps and face->charmaps fields of FT_FaceRec.

-

The currently active charmap is available as face->charmap. You should call FT_Set_Charmap to change it.

-

note

- -

When a new face is created (either through FT_New_Face or FT_Open_Face), the library looks for a Unicode charmap within the list and automatically activates it. If there is no Unicode charmap, FreeType doesn't set an ‘active’ charmap.

-

also

- -

See FT_CharMapRec for the publicly accessible fields of a given character map.

-
- -

FT_Encoding

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef enum  FT_Encoding_
-  {
-    FT_ENC_TAG( FT_ENCODING_NONE, 0, 0, 0, 0 ),
-
-    FT_ENC_TAG( FT_ENCODING_MS_SYMBOL, 's', 'y', 'm', 'b' ),
-    FT_ENC_TAG( FT_ENCODING_UNICODE,   'u', 'n', 'i', 'c' ),
-
-    FT_ENC_TAG( FT_ENCODING_SJIS,    's', 'j', 'i', 's' ),
-    FT_ENC_TAG( FT_ENCODING_PRC,     'g', 'b', ' ', ' ' ),
-    FT_ENC_TAG( FT_ENCODING_BIG5,    'b', 'i', 'g', '5' ),
-    FT_ENC_TAG( FT_ENCODING_WANSUNG, 'w', 'a', 'n', 's' ),
-    FT_ENC_TAG( FT_ENCODING_JOHAB,   'j', 'o', 'h', 'a' ),
-
-    /* for backward compatibility */
-    FT_ENCODING_GB2312     = FT_ENCODING_PRC,
-    FT_ENCODING_MS_SJIS    = FT_ENCODING_SJIS,
-    FT_ENCODING_MS_GB2312  = FT_ENCODING_PRC,
-    FT_ENCODING_MS_BIG5    = FT_ENCODING_BIG5,
-    FT_ENCODING_MS_WANSUNG = FT_ENCODING_WANSUNG,
-    FT_ENCODING_MS_JOHAB   = FT_ENCODING_JOHAB,
-
-    FT_ENC_TAG( FT_ENCODING_ADOBE_STANDARD, 'A', 'D', 'O', 'B' ),
-    FT_ENC_TAG( FT_ENCODING_ADOBE_EXPERT,   'A', 'D', 'B', 'E' ),
-    FT_ENC_TAG( FT_ENCODING_ADOBE_CUSTOM,   'A', 'D', 'B', 'C' ),
-    FT_ENC_TAG( FT_ENCODING_ADOBE_LATIN_1,  'l', 'a', 't', '1' ),
-
-    FT_ENC_TAG( FT_ENCODING_OLD_LATIN_2, 'l', 'a', 't', '2' ),
-
-    FT_ENC_TAG( FT_ENCODING_APPLE_ROMAN, 'a', 'r', 'm', 'n' )
-
-  } FT_Encoding;
-
-
-  /* these constants are deprecated; use the corresponding `FT_Encoding` */
-  /* values instead                                                      */
-#define ft_encoding_none            FT_ENCODING_NONE
-#define ft_encoding_unicode         FT_ENCODING_UNICODE
-#define ft_encoding_symbol          FT_ENCODING_MS_SYMBOL
-#define ft_encoding_latin_1         FT_ENCODING_ADOBE_LATIN_1
-#define ft_encoding_latin_2         FT_ENCODING_OLD_LATIN_2
-#define ft_encoding_sjis            FT_ENCODING_SJIS
-#define ft_encoding_gb2312          FT_ENCODING_PRC
-#define ft_encoding_big5            FT_ENCODING_BIG5
-#define ft_encoding_wansung         FT_ENCODING_WANSUNG
-#define ft_encoding_johab           FT_ENCODING_JOHAB
-
-#define ft_encoding_adobe_standard  FT_ENCODING_ADOBE_STANDARD
-#define ft_encoding_adobe_expert    FT_ENCODING_ADOBE_EXPERT
-#define ft_encoding_adobe_custom    FT_ENCODING_ADOBE_CUSTOM
-#define ft_encoding_apple_roman     FT_ENCODING_APPLE_ROMAN
-
- -

An enumeration to specify character sets supported by charmaps. Used in the FT_Select_Charmap API function.

-

note

- -

Despite the name, this enumeration lists specific character repertories (i.e., charsets), and not text encoding methods (e.g., UTF-8, UTF-16, etc.).

-

Other encodings might be defined in the future.

-

values

- -
- - - - - - - - - - - - - - - - - - - -
FT_ENCODING_NONE -

The encoding value 0 is reserved for all formats except BDF, PCF, and Windows FNT; see below for more information.

-
FT_ENCODING_UNICODE -

The Unicode character set. This value covers all versions of the Unicode repertoire, including ASCII and Latin-1. Most fonts include a Unicode charmap, but not all of them.

-

For example, if you want to access Unicode value U+1F028 (and the font contains it), use value 0x1F028 as the input value for FT_Get_Char_Index.

-
FT_ENCODING_MS_SYMBOL -

Microsoft Symbol encoding, used to encode mathematical symbols and wingdings. For more information, see ‘https://www.microsoft.com/typography/otspec/recom.htm#non-standard-symbol-fonts’, ‘http://www.kostis.net/charsets/symbol.htm’, and ‘http://www.kostis.net/charsets/wingding.htm’.

-

This encoding uses character codes from the PUA (Private Unicode Area) in the range U+F020-U+F0FF.

-
FT_ENCODING_SJIS -

Shift JIS encoding for Japanese. More info at ‘https://en.wikipedia.org/wiki/Shift_JIS’. See note on multi-byte encodings below.

-
FT_ENCODING_PRC -

Corresponds to encoding systems mainly for Simplified Chinese as used in People's Republic of China (PRC). The encoding layout is based on GB 2312 and its supersets GBK and GB 18030.

-
FT_ENCODING_BIG5 -

Corresponds to an encoding system for Traditional Chinese as used in Taiwan and Hong Kong.

-
FT_ENCODING_WANSUNG -

Corresponds to the Korean encoding system known as Extended Wansung (MS Windows code page 949). For more information see ‘https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit949.txt’.

-
FT_ENCODING_JOHAB -

The Korean standard character set (KS C 5601-1992), which corresponds to MS Windows code page 1361. This character set includes all possible Hangul character combinations.

-
FT_ENCODING_ADOBE_LATIN_1 -

Corresponds to a Latin-1 encoding as defined in a Type 1 PostScript font. It is limited to 256 character codes.

-
FT_ENCODING_ADOBE_STANDARD -

Adobe Standard encoding, as found in Type 1, CFF, and OpenType/CFF fonts. It is limited to 256 character codes.

-
FT_ENCODING_ADOBE_EXPERT -

Adobe Expert encoding, as found in Type 1, CFF, and OpenType/CFF fonts. It is limited to 256 character codes.

-
FT_ENCODING_ADOBE_CUSTOM -

Corresponds to a custom encoding, as found in Type 1, CFF, and OpenType/CFF fonts. It is limited to 256 character codes.

-
FT_ENCODING_APPLE_ROMAN -

Apple roman encoding. Many TrueType and OpenType fonts contain a charmap for this 8-bit encoding, since older versions of Mac OS are able to use it.

-
FT_ENCODING_OLD_LATIN_2 -

This value is deprecated and was neither used nor reported by FreeType. Don't use or test for it.

-
FT_ENCODING_MS_SJIS -

Same as FT_ENCODING_SJIS. Deprecated.

-
FT_ENCODING_MS_GB2312 -

Same as FT_ENCODING_PRC. Deprecated.

-
FT_ENCODING_MS_BIG5 -

Same as FT_ENCODING_BIG5. Deprecated.

-
FT_ENCODING_MS_WANSUNG -

Same as FT_ENCODING_WANSUNG. Deprecated.

-
FT_ENCODING_MS_JOHAB -

Same as FT_ENCODING_JOHAB. Deprecated.

-
- -

note

- -

By default, FreeType enables a Unicode charmap and tags it with FT_ENCODING_UNICODE when it is either provided or can be generated from PostScript glyph name dictionaries in the font file. All other encodings are considered legacy and tagged only if explicitly defined in the font file. Otherwise, FT_ENCODING_NONE is used.

-

FT_ENCODING_NONE is set by the BDF and PCF drivers if the charmap is neither Unicode nor ISO-8859-1 (otherwise it is set to FT_ENCODING_UNICODE). Use FT_Get_BDF_Charset_ID to find out which encoding is really present. If, for example, the cs_registry field is ‘KOI8’ and the cs_encoding field is ‘R’, the font is encoded in KOI8-R.

-

FT_ENCODING_NONE is always set (with a single exception) by the winfonts driver. Use FT_Get_WinFNT_Header and examine the charset field of the FT_WinFNT_HeaderRec structure to find out which encoding is really present. For example, FT_WinFNT_ID_CP1251 (204) means Windows code page 1251 (for Russian).

-

FT_ENCODING_NONE is set if platform_id is TT_PLATFORM_MACINTOSH and encoding_id is not TT_MAC_ID_ROMAN (otherwise it is set to FT_ENCODING_APPLE_ROMAN).

-

If platform_id is TT_PLATFORM_MACINTOSH, use the function FT_Get_CMap_Language_ID to query the Mac language ID that may be needed to be able to distinguish Apple encoding variants. See

-

https://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt

-

to get an idea how to do that. Basically, if the language ID is 0, don't use it, otherwise subtract 1 from the language ID. Then examine encoding_id. If, for example, encoding_id is TT_MAC_ID_ROMAN and the language ID (minus 1) is TT_MAC_LANGID_GREEK, it is the Greek encoding, not Roman. TT_MAC_ID_ARABIC with TT_MAC_LANGID_FARSI means the Farsi variant the Arabic encoding.

-
- -

FT_ENC_TAG

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#ifndef FT_ENC_TAG
-#define FT_ENC_TAG( value, a, b, c, d )         \
-          value = ( ( (FT_UInt32)(a) << 24 ) |  \
-                    ( (FT_UInt32)(b) << 16 ) |  \
-                    ( (FT_UInt32)(c) <<  8 ) |  \
-                      (FT_UInt32)(d)         )
-
-#endif /* FT_ENC_TAG */
-
- -

This macro converts four-letter tags into an unsigned long. It is used to define ‘encoding’ identifiers (see FT_Encoding).

-

note

- -

Since many 16-bit compilers don't like 32-bit enumerations, you should redefine this macro in case of problems to something like this: -

  #define FT_ENC_TAG( value, a, b, c, d )  value
-

-

to get a simple enumeration without assigning special numbers.

-
- -

FT_FaceRec

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct  FT_FaceRec_
-  {
-    FT_Long           num_faces;
-    FT_Long           face_index;
-
-    FT_Long           face_flags;
-    FT_Long           style_flags;
-
-    FT_Long           num_glyphs;
-
-    FT_String*        family_name;
-    FT_String*        style_name;
-
-    FT_Int            num_fixed_sizes;
-    FT_Bitmap_Size*   available_sizes;
-
-    FT_Int            num_charmaps;
-    FT_CharMap*       charmaps;
-
-    FT_Generic        generic;
-
-    /*# The following member variables (down to `underline_thickness`) */
-    /*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size    */
-    /*# for bitmap fonts.                                              */
-    FT_BBox           bbox;
-
-    FT_UShort         units_per_EM;
-    FT_Short          ascender;
-    FT_Short          descender;
-    FT_Short          height;
-
-    FT_Short          max_advance_width;
-    FT_Short          max_advance_height;
-
-    FT_Short          underline_position;
-    FT_Short          underline_thickness;
-
-    FT_GlyphSlot      glyph;
-    FT_Size           size;
-    FT_CharMap        charmap;
-
-    /*@private begin */
-
-    FT_Driver         driver;
-    FT_Memory         memory;
-    FT_Stream         stream;
-
-    FT_ListRec        sizes_list;
-
-    FT_Generic        autohint;   /* face-specific auto-hinter data */
-    void*             extensions; /* unused                         */
-
-    FT_Face_Internal  internal;
-
-    /*@private end */
-
-  } FT_FaceRec;
-
- -

FreeType root face class structure. A face object models a typeface in a font file.

-

fields

- - - - - - - - - - - - - - - - - - - - - - - - - - -
num_faces -

The number of faces in the font file. Some font formats can have multiple faces in a single font file.

-
face_index -

This field holds two different values. Bits 0-15 are the index of the face in the font file (starting with value 0). They are set to 0 if there is only one face in the font file.

-

[Since 2.6.1] Bits 16-30 are relevant to GX and OpenType variation fonts only, holding the named instance index for the current face index (starting with value 1; value 0 indicates font access without a named instance). For non-variation fonts, bits 16-30 are ignored. If we have the third named instance of face 4, say, face_index is set to 0x00030004.

-

Bit 31 is always zero (this is, face_index is always a positive value).

-

[Since 2.9] Changing the design coordinates with FT_Set_Var_Design_Coordinates or FT_Set_Var_Blend_Coordinates does not influence the named instance index value (only FT_Set_Named_Instance does that).

-
face_flags -

A set of bit flags that give important information about the face; see FT_FACE_FLAG_XXX for the details.

-
style_flags -

The lower 16 bits contain a set of bit flags indicating the style of the face; see FT_STYLE_FLAG_XXX for the details.

-

[Since 2.6.1] Bits 16-30 hold the number of named instances available for the current face if we have a GX or OpenType variation (sub)font. Bit 31 is always zero (this is, style_flags is always a positive value). Note that a variation font has always at least one named instance, namely the default instance.

-
num_glyphs -

The number of glyphs in the face. If the face is scalable and has sbits (see num_fixed_sizes), it is set to the number of outline glyphs.

-

For CID-keyed fonts (not in an SFNT wrapper) this value gives the highest CID used in the font.

-
family_name -

The face's family name. This is an ASCII string, usually in English, that describes the typeface's family (like ‘Times New Roman’, ‘Bodoni’, ‘Garamond’, etc). This is a least common denominator used to list fonts. Some formats (TrueType & OpenType) provide localized and Unicode versions of this string. Applications should use the format-specific interface to access them. Can be NULL (e.g., in fonts embedded in a PDF file).

-

In case the font doesn't provide a specific family name entry, FreeType tries to synthesize one, deriving it from other name entries.

-
style_name -

The face's style name. This is an ASCII string, usually in English, that describes the typeface's style (like ‘Italic’, ‘Bold’, ‘Condensed’, etc). Not all font formats provide a style name, so this field is optional, and can be set to NULL. As for family_name, some formats provide localized and Unicode versions of this string. Applications should use the format-specific interface to access them.

-
num_fixed_sizes -

The number of bitmap strikes in the face. Even if the face is scalable, there might still be bitmap strikes, which are called ‘sbits’ in that case.

-
available_sizes -

An array of FT_Bitmap_Size for all bitmap strikes in the face. It is set to NULL if there is no bitmap strike.

-

Note that FreeType tries to sanitize the strike data since they are sometimes sloppy or incorrect, but this can easily fail.

-
num_charmaps -

The number of charmaps in the face.

-
charmaps -

An array of the charmaps of the face.

-
generic -

A field reserved for client uses. See the FT_Generic type description.

-
bbox -

The font bounding box. Coordinates are expressed in font units (see units_per_EM). The box is large enough to contain any glyph from the font. Thus, bbox.yMax can be seen as the ‘maximum ascender’, and bbox.yMin as the ‘minimum descender’. Only relevant for scalable formats.

-

Note that the bounding box might be off by (at least) one pixel for hinted fonts. See FT_Size_Metrics for further discussion.

-

Note that the bounding box does not vary in OpenType variable fonts and should only be used in relation to the default instance.

-
units_per_EM -

The number of font units per EM square for this face. This is typically 2048 for TrueType fonts, and 1000 for Type 1 fonts. Only relevant for scalable formats.

-
ascender -

The typographic ascender of the face, expressed in font units. For font formats not having this information, it is set to bbox.yMax. Only relevant for scalable formats.

-
descender -

The typographic descender of the face, expressed in font units. For font formats not having this information, it is set to bbox.yMin. Note that this field is negative for values below the baseline. Only relevant for scalable formats.

-
height -

This value is the vertical distance between two consecutive baselines, expressed in font units. It is always positive. Only relevant for scalable formats.

-

If you want the global glyph height, use ascender - descender.

-
max_advance_width -

The maximum advance width, in font units, for all glyphs in this face. This can be used to make word wrapping computations faster. Only relevant for scalable formats.

-
max_advance_height -

The maximum advance height, in font units, for all glyphs in this face. This is only relevant for vertical layouts, and is set to height for fonts that do not provide vertical metrics. Only relevant for scalable formats.

-
underline_position -

The position, in font units, of the underline line for this face. It is the center of the underlining stem. Only relevant for scalable formats.

-
underline_thickness -

The thickness, in font units, of the underline for this face. Only relevant for scalable formats.

-
glyph -

The face's associated glyph slot(s).

-
size -

The current active size for this face.

-
charmap -

The current active charmap for this face.

-
- -

note

- -

Fields may be changed after a call to FT_Attach_File or FT_Attach_Stream.

-

For an OpenType variation font, the values of the following fields can change after a call to FT_Set_Var_Design_Coordinates (and friends) if the font contains an ‘MVAR’ table: ascender, descender, height, underline_position, and underline_thickness.

-

Especially for TrueType fonts see also the documentation for FT_Size_Metrics.

-
- -

FT_HAS_HORIZONTAL

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_HAS_HORIZONTAL( face ) \
-          ( !!( (face)->face_flags & FT_FACE_FLAG_HORIZONTAL ) )
-
- -

A macro that returns true whenever a face object contains horizontal metrics (this is true for all font formats though).

-

also

- -

FT_HAS_VERTICAL can be used to check for vertical metrics.

-
- -

FT_HAS_VERTICAL

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_HAS_VERTICAL( face ) \
-          ( !!( (face)->face_flags & FT_FACE_FLAG_VERTICAL ) )
-
- -

A macro that returns true whenever a face object contains real vertical metrics (and not only synthesized ones).

-
- -

FT_HAS_KERNING

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_HAS_KERNING( face ) \
-          ( !!( (face)->face_flags & FT_FACE_FLAG_KERNING ) )
-
- -

A macro that returns true whenever a face object contains kerning data that can be accessed with FT_Get_Kerning.

-
- -

FT_HAS_FIXED_SIZES

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_HAS_FIXED_SIZES( face ) \
-          ( !!( (face)->face_flags & FT_FACE_FLAG_FIXED_SIZES ) )
-
- -

A macro that returns true whenever a face object contains some embedded bitmaps. See the available_sizes field of the FT_FaceRec structure.

-
- -

FT_HAS_GLYPH_NAMES

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_HAS_GLYPH_NAMES( face ) \
-          ( !!( (face)->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) )
-
- -

A macro that returns true whenever a face object contains some glyph names that can be accessed through FT_Get_Glyph_Name.

-
- -

FT_HAS_COLOR

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_HAS_COLOR( face ) \
-          ( !!( (face)->face_flags & FT_FACE_FLAG_COLOR ) )
-
- -

A macro that returns true whenever a face object contains tables for color glyphs.

-

since

- -

2.5.1

-
- -

FT_HAS_MULTIPLE_MASTERS

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_HAS_MULTIPLE_MASTERS( face ) \
-          ( !!( (face)->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) )
-
- -

A macro that returns true whenever a face object contains some multiple masters. The functions provided by FT_MULTIPLE_MASTERS_H are then available to choose the exact design you want.

-
- -

FT_IS_SFNT

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_IS_SFNT( face ) \
-          ( !!( (face)->face_flags & FT_FACE_FLAG_SFNT ) )
-
- -

A macro that returns true whenever a face object contains a font whose format is based on the SFNT storage scheme. This usually means: TrueType fonts, OpenType fonts, as well as SFNT-based embedded bitmap fonts.

-

If this macro is true, all functions defined in FT_SFNT_NAMES_H and FT_TRUETYPE_TABLES_H are available.

-
- -

FT_IS_SCALABLE

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_IS_SCALABLE( face ) \
-          ( !!( (face)->face_flags & FT_FACE_FLAG_SCALABLE ) )
-
- -

A macro that returns true whenever a face object contains a scalable font face (true for TrueType, Type 1, Type 42, CID, OpenType/CFF, and PFR font formats).

-
- -

FT_IS_FIXED_WIDTH

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_IS_FIXED_WIDTH( face ) \
-          ( !!( (face)->face_flags & FT_FACE_FLAG_FIXED_WIDTH ) )
-
- -

A macro that returns true whenever a face object contains a font face that contains fixed-width (or ‘monospace’, ‘fixed-pitch’, etc.) glyphs.

-
- -

FT_IS_CID_KEYED

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_IS_CID_KEYED( face ) \
-          ( !!( (face)->face_flags & FT_FACE_FLAG_CID_KEYED ) )
-
- -

A macro that returns true whenever a face object contains a CID-keyed font. See the discussion of FT_FACE_FLAG_CID_KEYED for more details.

-

If this macro is true, all functions defined in FT_CID_H are available.

-
- -

FT_IS_TRICKY

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_IS_TRICKY( face ) \
-          ( !!( (face)->face_flags & FT_FACE_FLAG_TRICKY ) )
-
- -

A macro that returns true whenever a face represents a ‘tricky’ font. See the discussion of FT_FACE_FLAG_TRICKY for more details.

-
- -

FT_IS_NAMED_INSTANCE

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_IS_NAMED_INSTANCE( face ) \
-          ( !!( (face)->face_index & 0x7FFF0000L ) )
-
- -

A macro that returns true whenever a face object is a named instance of a GX or OpenType variation font.

-

[Since 2.9] Changing the design coordinates with FT_Set_Var_Design_Coordinates or FT_Set_Var_Blend_Coordinates does not influence the return value of this macro (only FT_Set_Named_Instance does that).

-

since

- -

2.7

-
- -

FT_IS_VARIATION

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_IS_VARIATION( face ) \
-          ( !!( (face)->face_flags & FT_FACE_FLAG_VARIATION ) )
-
- -

A macro that returns true whenever a face object has been altered by FT_Set_MM_Design_Coordinates, FT_Set_Var_Design_Coordinates, or FT_Set_Var_Blend_Coordinates.

-

since

- -

2.9

-
- -

FT_SizeRec

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct  FT_SizeRec_
-  {
-    FT_Face           face;      /* parent face object              */
-    FT_Generic        generic;   /* generic pointer for client uses */
-    FT_Size_Metrics   metrics;   /* size metrics                    */
-    FT_Size_Internal  internal;
-
-  } FT_SizeRec;
-
- -

FreeType root size class structure. A size object models a face object at a given size.

-

fields

- - - - - -
face -

Handle to the parent face object.

-
generic -

A typeless pointer, unused by the FreeType library or any of its drivers. It can be used by client applications to link their own data to each size object.

-
metrics -

Metrics for this size object. This field is read-only.

-
- -
- -

FT_Size_Metrics

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct  FT_Size_Metrics_
-  {
-    FT_UShort  x_ppem;      /* horizontal pixels per EM               */
-    FT_UShort  y_ppem;      /* vertical pixels per EM                 */
-
-    FT_Fixed   x_scale;     /* scaling values used to convert font    */
-    FT_Fixed   y_scale;     /* units to 26.6 fractional pixels        */
-
-    FT_Pos     ascender;    /* ascender in 26.6 frac. pixels          */
-    FT_Pos     descender;   /* descender in 26.6 frac. pixels         */
-    FT_Pos     height;      /* text height in 26.6 frac. pixels       */
-    FT_Pos     max_advance; /* max horizontal advance, in 26.6 pixels */
-
-  } FT_Size_Metrics;
-
- -

The size metrics structure gives the metrics of a size object.

-

fields

- - - - - - - - - - -
x_ppem -

The width of the scaled EM square in pixels, hence the term ‘ppem’ (pixels per EM). It is also referred to as ‘nominal width’.

-
y_ppem -

The height of the scaled EM square in pixels, hence the term ‘ppem’ (pixels per EM). It is also referred to as ‘nominal height’.

-
x_scale -

A 16.16 fractional scaling value to convert horizontal metrics from font units to 26.6 fractional pixels. Only relevant for scalable font formats.

-
y_scale -

A 16.16 fractional scaling value to convert vertical metrics from font units to 26.6 fractional pixels. Only relevant for scalable font formats.

-
ascender -

The ascender in 26.6 fractional pixels, rounded up to an integer value. See FT_FaceRec for the details.

-
descender -

The descender in 26.6 fractional pixels, rounded down to an integer value. See FT_FaceRec for the details.

-
height -

The height in 26.6 fractional pixels, rounded to an integer value. See FT_FaceRec for the details.

-
max_advance -

The maximum advance width in 26.6 fractional pixels, rounded to an integer value. See FT_FaceRec for the details.

-
- -

note

- -

The scaling values, if relevant, are determined first during a size changing operation. The remaining fields are then set by the driver. For scalable formats, they are usually set to scaled values of the corresponding fields in FT_FaceRec. Some values like ascender or descender are rounded for historical reasons; more precise values (for outline fonts) can be derived by scaling the corresponding FT_FaceRec values manually, with code similar to the following. -

  scaled_ascender = FT_MulFix( face->ascender,
-                               size_metrics->y_scale );
-

-

Note that due to glyph hinting and the selected rendering mode these values are usually not exact; consequently, they must be treated as unreliable with an error margin of at least one pixel!

-

Indeed, the only way to get the exact metrics is to render all glyphs. As this would be a definite performance hit, it is up to client applications to perform such computations.

-

The FT_Size_Metrics structure is valid for bitmap fonts also.

-

TrueType fonts with native bytecode hinting

-

All applications that handle TrueType fonts with native hinting must be aware that TTFs expect different rounding of vertical font dimensions. The application has to cater for this, especially if it wants to rely on a TTF's vertical data (for example, to properly align box characters vertically).

-

Only the application knows in advance that it is going to use native hinting for TTFs! FreeType, on the other hand, selects the hinting mode not at the time of creating an FT_Size object but much later, namely while calling FT_Load_Glyph.

-

Here is some pseudo code that illustrates a possible solution. -

  font_format = FT_Get_Font_Format( face );
-
-  if ( !strcmp( font_format, "TrueType" ) &&
-       do_native_bytecode_hinting         )
-  {
-    ascender  = ROUND( FT_MulFix( face->ascender,
-                                  size_metrics->y_scale ) );
-    descender = ROUND( FT_MulFix( face->descender,
-                                  size_metrics->y_scale ) );
-  }
-  else
-  {
-    ascender  = size_metrics->ascender;
-    descender = size_metrics->descender;
-  }
-
-  height      = size_metrics->height;
-  max_advance = size_metrics->max_advance;
-

-
- -

FT_GlyphSlotRec

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct  FT_GlyphSlotRec_
-  {
-    FT_Library        library;
-    FT_Face           face;
-    FT_GlyphSlot      next;
-    FT_UInt           glyph_index; /* new in 2.10; was reserved previously */
-    FT_Generic        generic;
-
-    FT_Glyph_Metrics  metrics;
-    FT_Fixed          linearHoriAdvance;
-    FT_Fixed          linearVertAdvance;
-    FT_Vector         advance;
-
-    FT_Glyph_Format   format;
-
-    FT_Bitmap         bitmap;
-    FT_Int            bitmap_left;
-    FT_Int            bitmap_top;
-
-    FT_Outline        outline;
-
-    FT_UInt           num_subglyphs;
-    FT_SubGlyph       subglyphs;
-
-    void*             control_data;
-    long              control_len;
-
-    FT_Pos            lsb_delta;
-    FT_Pos            rsb_delta;
-
-    void*             other;
-
-    FT_Slot_Internal  internal;
-
-  } FT_GlyphSlotRec;
-
- -

FreeType root glyph slot class structure. A glyph slot is a container where individual glyphs can be loaded, be they in outline or bitmap format.

-

fields

- - - - - - - - - - - - - - - - - - - - - - - -
library -

A handle to the FreeType library instance this slot belongs to.

-
face -

A handle to the parent face object.

-
next -

In some cases (like some font tools), several glyph slots per face object can be a good thing. As this is rare, the glyph slots are listed through a direct, single-linked list using its next field.

-
glyph_index -

[Since 2.10] The glyph index passed as an argument to FT_Load_Glyph while initializing the glyph slot.

-
generic -

A typeless pointer unused by the FreeType library or any of its drivers. It can be used by client applications to link their own data to each glyph slot object.

-
metrics -

The metrics of the last loaded glyph in the slot. The returned values depend on the last load flags (see the FT_Load_Glyph API function) and can be expressed either in 26.6 fractional pixels or font units.

-

Note that even when the glyph image is transformed, the metrics are not.

-
linearHoriAdvance -

The advance width of the unhinted glyph. Its value is expressed in 16.16 fractional pixels, unless FT_LOAD_LINEAR_DESIGN is set when loading the glyph. This field can be important to perform correct WYSIWYG layout. Only relevant for outline glyphs.

-
linearVertAdvance -

The advance height of the unhinted glyph. Its value is expressed in 16.16 fractional pixels, unless FT_LOAD_LINEAR_DESIGN is set when loading the glyph. This field can be important to perform correct WYSIWYG layout. Only relevant for outline glyphs.

-
advance -

This shorthand is, depending on FT_LOAD_IGNORE_TRANSFORM, the transformed (hinted) advance width for the glyph, in 26.6 fractional pixel format. As specified with FT_LOAD_VERTICAL_LAYOUT, it uses either the horiAdvance or the vertAdvance value of metrics field.

-
format -

This field indicates the format of the image contained in the glyph slot. Typically FT_GLYPH_FORMAT_BITMAP, FT_GLYPH_FORMAT_OUTLINE, or FT_GLYPH_FORMAT_COMPOSITE, but other values are possible.

-
bitmap -

This field is used as a bitmap descriptor. Note that the address and content of the bitmap buffer can change between calls of FT_Load_Glyph and a few other functions.

-
bitmap_left -

The bitmap's left bearing expressed in integer pixels.

-
bitmap_top -

The bitmap's top bearing expressed in integer pixels. This is the distance from the baseline to the top-most glyph scanline, upwards y coordinates being positive.

-
outline -

The outline descriptor for the current glyph image if its format is FT_GLYPH_FORMAT_OUTLINE. Once a glyph is loaded, outline can be transformed, distorted, emboldened, etc. However, it must not be freed.

-

[Since 2.10.1] If FT_LOAD_NO_SCALE is set, outline coordinates of OpenType variation fonts for a selected instance are internally handled as 26.6 fractional font units but returned as (rounded) integers, as expected. To get unrounded font units, don't use FT_LOAD_NO_SCALE but load the glyph with FT_LOAD_NO_HINTING and scale it, using the font's units_per_EM value as the ppem.

-
num_subglyphs -

The number of subglyphs in a composite glyph. This field is only valid for the composite glyph format that should normally only be loaded with the FT_LOAD_NO_RECURSE flag.

-
subglyphs -

An array of subglyph descriptors for composite glyphs. There are num_subglyphs elements in there. Currently internal to FreeType.

-
control_data -

Certain font drivers can also return the control data for a given glyph image (e.g. TrueType bytecode, Type 1 charstrings, etc.). This field is a pointer to such data; it is currently internal to FreeType.

-
control_len -

This is the length in bytes of the control data. Currently internal to FreeType.

-
other -

Reserved.

-
lsb_delta -

The difference between hinted and unhinted left side bearing while auto-hinting is active. Zero otherwise.

-
rsb_delta -

The difference between hinted and unhinted right side bearing while auto-hinting is active. Zero otherwise.

-
- -

note

- -

If FT_Load_Glyph is called with default flags (see FT_LOAD_DEFAULT) the glyph image is loaded in the glyph slot in its native format (e.g., an outline glyph for TrueType and Type 1 formats). [Since 2.9] The prospective bitmap metrics are calculated according to FT_LOAD_TARGET_XXX and other flags even for the outline glyph, even if FT_LOAD_RENDER is not set.

-

This image can later be converted into a bitmap by calling FT_Render_Glyph. This function searches the current renderer for the native image's format, then invokes it.

-

The renderer is in charge of transforming the native image through the slot's face transformation fields, then converting it into a bitmap that is returned in slot->bitmap.

-

Note that slot->bitmap_left and slot->bitmap_top are also used to specify the position of the bitmap relative to the current pen position (e.g., coordinates (0,0) on the baseline). Of course, slot->format is also changed to FT_GLYPH_FORMAT_BITMAP.

-

Here is a small pseudo code fragment that shows how to use lsb_delta and rsb_delta to do fractional positioning of glyphs: -

  FT_GlyphSlot  slot     = face->glyph;
-  FT_Pos        origin_x = 0;
-
-
-  for all glyphs do
-    <load glyph with `FT_Load_Glyph'>
-
-    FT_Outline_Translate( slot->outline, origin_x & 63, 0 );
-
-    <save glyph image, or render glyph, or ...>
-
-    <compute kern between current and next glyph
-     and add it to `origin_x'>
-
-    origin_x += slot->advance.x;
-    origin_x += slot->lsb_delta - slot->rsb_delta;
-  endfor
-

-

Here is another small pseudo code fragment that shows how to use lsb_delta and rsb_delta to improve integer positioning of glyphs: -

  FT_GlyphSlot  slot           = face->glyph;
-  FT_Pos        origin_x       = 0;
-  FT_Pos        prev_rsb_delta = 0;
-
-
-  for all glyphs do
-    <compute kern between current and previous glyph
-     and add it to `origin_x'>
-
-    <load glyph with `FT_Load_Glyph'>
-
-    if ( prev_rsb_delta - slot->lsb_delta >  32 )
-      origin_x -= 64;
-    else if ( prev_rsb_delta - slot->lsb_delta < -31 )
-      origin_x += 64;
-
-    prev_rsb_delta = slot->rsb_delta;
-
-    <save glyph image, or render glyph, or ...>
-
-    origin_x += slot->advance.x;
-  endfor
-

-

If you use strong auto-hinting, you must apply these delta values! Otherwise you will experience far too large inter-glyph spacing at small rendering sizes in most cases. Note that it doesn't harm to use the above code for other hinting modes also, since the delta values are zero then.

-
- -

FT_Glyph_Metrics

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct  FT_Glyph_Metrics_
-  {
-    FT_Pos  width;
-    FT_Pos  height;
-
-    FT_Pos  horiBearingX;
-    FT_Pos  horiBearingY;
-    FT_Pos  horiAdvance;
-
-    FT_Pos  vertBearingX;
-    FT_Pos  vertBearingY;
-    FT_Pos  vertAdvance;
-
-  } FT_Glyph_Metrics;
-
- -

A structure to model the metrics of a single glyph. The values are expressed in 26.6 fractional pixel format; if the flag FT_LOAD_NO_SCALE has been used while loading the glyph, values are expressed in font units instead.

-

fields

- - - - - - - - - - -
width -

The glyph's width.

-
height -

The glyph's height.

-
horiBearingX -

Left side bearing for horizontal layout.

-
horiBearingY -

Top side bearing for horizontal layout.

-
horiAdvance -

Advance width for horizontal layout.

-
vertBearingX -

Left side bearing for vertical layout.

-
vertBearingY -

Top side bearing for vertical layout. Larger positive values mean further below the vertical glyph origin.

-
vertAdvance -

Advance height for vertical layout. Positive values mean the glyph has a positive advance downward.

-
- -

note

- -

If not disabled with FT_LOAD_NO_HINTING, the values represent dimensions of the hinted glyph (in case hinting is applicable).

-

Stroking a glyph with an outside border does not increase horiAdvance or vertAdvance; you have to manually adjust these values to account for the added width and height.

-

FreeType doesn't use the ‘VORG’ table data for CFF fonts because it doesn't have an interface to quickly retrieve the glyph height. The y coordinate of the vertical origin can be simply computed as vertBearingY + height after loading a glyph.

-
- -

FT_SubGlyph

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct FT_SubGlyphRec_*  FT_SubGlyph;
-
- -

The subglyph structure is an internal object used to describe subglyphs (for example, in the case of composites).

-

note

- -

The subglyph implementation is not part of the high-level API, hence the forward structure declaration.

-

You can however retrieve subglyph information with FT_Get_SubGlyph_Info.

-
- -

FT_Bitmap_Size

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct  FT_Bitmap_Size_
-  {
-    FT_Short  height;
-    FT_Short  width;
-
-    FT_Pos    size;
-
-    FT_Pos    x_ppem;
-    FT_Pos    y_ppem;
-
-  } FT_Bitmap_Size;
-
- -

This structure models the metrics of a bitmap strike (i.e., a set of glyphs for a given point size and resolution) in a bitmap font. It is used for the available_sizes field of FT_Face.

-

fields

- - - - - - - -
height -

The vertical distance, in pixels, between two consecutive baselines. It is always positive.

-
width -

The average width, in pixels, of all glyphs in the strike.

-
size -

The nominal size of the strike in 26.6 fractional points. This field is not very useful.

-
x_ppem -

The horizontal ppem (nominal width) in 26.6 fractional pixels.

-
y_ppem -

The vertical ppem (nominal height) in 26.6 fractional pixels.

-
- -

note

- -

Windows FNT: The nominal size given in a FNT font is not reliable. If the driver finds it incorrect, it sets size to some calculated values, and x_ppem and y_ppem to the pixel width and height given in the font, respectively.

-

TrueType embedded bitmaps: size, width, and height values are not contained in the bitmap strike itself. They are computed from the global font parameters.

-
- -

FT_Init_FreeType

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Init_FreeType( FT_Library  *alibrary );
-
- -

Initialize a new FreeType library object. The set of modules that are registered by this function is determined at build time.

-

output

- - - -
alibrary -

A handle to a new library object.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

In case you want to provide your own memory allocating routines, use FT_New_Library instead, followed by a call to FT_Add_Default_Modules (or a series of calls to FT_Add_Module) and FT_Set_Default_Properties.

-

See the documentation of FT_Library and FT_Face for multi-threading issues.

-

If you need reference-counting (cf. FT_Reference_Library), use FT_New_Library and FT_Done_Library.

-

If compilation option FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES is set, this function reads the FREETYPE_PROPERTIES environment variable to control driver properties. See section ‘Driver properties’ for more.

-
- -

FT_Done_FreeType

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Done_FreeType( FT_Library  library );
-
- -

Destroy a given FreeType library object and all of its children, including resources, drivers, faces, sizes, etc.

-

input

- - - -
library -

A handle to the target library object.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FT_New_Face

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_New_Face( FT_Library   library,
-               const char*  filepathname,
-               FT_Long      face_index,
-               FT_Face     *aface );
-
- -

Call FT_Open_Face to open a font by its pathname.

-

inout

- - - -
library -

A handle to the library resource.

-
- -

input

- - - - -
pathname -

A path to the font file.

-
face_index -

See FT_Open_Face for a detailed description of this parameter.

-
- -

output

- - - -
aface -

A handle to a new face object. If face_index is greater than or equal to zero, it must be non-NULL.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

Use FT_Done_Face to destroy the created FT_Face object (along with its slot and sizes).

-
- -

FT_Done_Face

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Done_Face( FT_Face  face );
-
- -

Discard a given face object, as well as all of its child slots and sizes.

-

input

- - - -
face -

A handle to a target face object.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

See the discussion of reference counters in the description of FT_Reference_Face.

-
- -

FT_Reference_Face

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Reference_Face( FT_Face  face );
-
- -

A counter gets initialized to 1 at the time an FT_Face structure is created. This function increments the counter. FT_Done_Face then only destroys a face if the counter is 1, otherwise it simply decrements the counter.

-

This function helps in managing life-cycles of structures that reference FT_Face objects.

-

input

- - - -
face -

A handle to a target face object.

-
- -

return

- -

FreeType error code. 0 means success.

-

since

- -

2.4.2

-
- -

FT_New_Memory_Face

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_New_Memory_Face( FT_Library      library,
-                      const FT_Byte*  file_base,
-                      FT_Long         file_size,
-                      FT_Long         face_index,
-                      FT_Face        *aface );
-
- -

Call FT_Open_Face to open a font that has been loaded into memory.

-

inout

- - - -
library -

A handle to the library resource.

-
- -

input

- - - - - -
file_base -

A pointer to the beginning of the font data.

-
file_size -

The size of the memory chunk used by the font data.

-
face_index -

See FT_Open_Face for a detailed description of this parameter.

-
- -

output

- - - -
aface -

A handle to a new face object. If face_index is greater than or equal to zero, it must be non-NULL.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

You must not deallocate the memory before calling FT_Done_Face.

-
- -

FT_Face_Properties

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Face_Properties( FT_Face        face,
-                      FT_UInt        num_properties,
-                      FT_Parameter*  properties );
-
- -

Set or override certain (library or module-wide) properties on a face-by-face basis. Useful for finer-grained control and avoiding locks on shared structures (threads can modify their own faces as they see fit).

-

Contrary to FT_Property_Set, this function uses FT_Parameter so that you can pass multiple properties to the target face in one call. Note that only a subset of the available properties can be controlled.

- -

Pass NULL as data in FT_Parameter for a given tag to reset the option and use the library or module default again.

-

input

- - - - - -
face -

A handle to the source face object.

-
num_properties -

The number of properties that follow.

-
properties -

A handle to an FT_Parameter array with num_properties elements.

-
- -

return

- -

FreeType error code. 0 means success.

-

example

- -

Here is an example that sets three properties. You must define FT_CONFIG_OPTION_SUBPIXEL_RENDERING to make the LCD filter examples work. -

  FT_Parameter         property1;
-  FT_Bool              darken_stems = 1;
-
-  FT_Parameter         property2;
-  FT_LcdFiveTapFilter  custom_weight =
-                         { 0x11, 0x44, 0x56, 0x44, 0x11 };
-
-  FT_Parameter         property3;
-  FT_Int32             random_seed = 314159265;
-
-  FT_Parameter         properties[3] = { property1,
-                                         property2,
-                                         property3 };
-
-
-  property1.tag  = FT_PARAM_TAG_STEM_DARKENING;
-  property1.data = &darken_stems;
-
-  property2.tag  = FT_PARAM_TAG_LCD_FILTER_WEIGHTS;
-  property2.data = custom_weight;
-
-  property3.tag  = FT_PARAM_TAG_RANDOM_SEED;
-  property3.data = &random_seed;
-
-  FT_Face_Properties( face, 3, properties );
-

-

The next example resets a single property to its default value. -

  FT_Parameter  property;
-
-
-  property.tag  = FT_PARAM_TAG_LCD_FILTER_WEIGHTS;
-  property.data = NULL;
-
-  FT_Face_Properties( face, 1, &property );
-

-

since

- -

2.8

-
- -

FT_Open_Face

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Open_Face( FT_Library           library,
-                const FT_Open_Args*  args,
-                FT_Long              face_index,
-                FT_Face             *aface );
-
- -

Create a face object from a given resource described by FT_Open_Args.

-

inout

- - - -
library -

A handle to the library resource.

-
- -

input

- - - - -
args -

A pointer to an FT_Open_Args structure that must be filled by the caller.

-
face_index -

This field holds two different values. Bits 0-15 are the index of the face in the font file (starting with value 0). Set it to 0 if there is only one face in the font file.

-

[Since 2.6.1] Bits 16-30 are relevant to GX and OpenType variation fonts only, specifying the named instance index for the current face index (starting with value 1; value 0 makes FreeType ignore named instances). For non-variation fonts, bits 16-30 are ignored. Assuming that you want to access the third named instance in face 4, face_index should be set to 0x00030004. If you want to access face 4 without variation handling, simply set face_index to value 4.

-

FT_Open_Face and its siblings can be used to quickly check whether the font format of a given font resource is supported by FreeType. In general, if the face_index argument is negative, the function's return value is 0 if the font format is recognized, or non-zero otherwise. The function allocates a more or less empty face handle in *aface (if aface isn't NULL); the only two useful fields in this special case are face->num_faces and face->style_flags. For any negative value of face_index, face->num_faces gives the number of faces within the font file. For the negative value ‘-(N+1)’ (with ‘N’ a non-negative 16-bit value), bits 16-30 in face->style_flags give the number of named instances in face ‘N’ if we have a variation font (or zero otherwise). After examination, the returned FT_Face structure should be deallocated with a call to FT_Done_Face.

-
- -

output

- - - -
aface -

A handle to a new face object. If face_index is greater than or equal to zero, it must be non-NULL.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

Unlike FreeType 1.x, this function automatically creates a glyph slot for the face object that can be accessed directly through face->glyph.

-

Each new face object created with this function also owns a default FT_Size object, accessible as face->size.

-

One FT_Library instance can have multiple face objects, this is, FT_Open_Face and its siblings can be called multiple times using the same library argument.

-

See the discussion of reference counters in the description of FT_Reference_Face.

-

example

- -

To loop over all faces, use code similar to the following snippet (omitting the error handling). -

  ...
-  FT_Face  face;
-  FT_Long  i, num_faces;
-
-
-  error = FT_Open_Face( library, args, -1, &face );
-  if ( error ) { ... }
-
-  num_faces = face->num_faces;
-  FT_Done_Face( face );
-
-  for ( i = 0; i < num_faces; i++ )
-  {
-    ...
-    error = FT_Open_Face( library, args, i, &face );
-    ...
-    FT_Done_Face( face );
-    ...
-  }
-

-

To loop over all valid values for face_index, use something similar to the following snippet, again without error handling. The code accesses all faces immediately (thus only a single call of FT_Open_Face within the do-loop), with and without named instances. -

  ...
-  FT_Face  face;
-
-  FT_Long  num_faces     = 0;
-  FT_Long  num_instances = 0;
-
-  FT_Long  face_idx     = 0;
-  FT_Long  instance_idx = 0;
-
-
-  do
-  {
-    FT_Long  id = ( instance_idx << 16 ) + face_idx;
-
-
-    error = FT_Open_Face( library, args, id, &face );
-    if ( error ) { ... }
-
-    num_faces     = face->num_faces;
-    num_instances = face->style_flags >> 16;
-
-    ...
-
-    FT_Done_Face( face );
-
-    if ( instance_idx < num_instances )
-      instance_idx++;
-    else
-    {
-      face_idx++;
-      instance_idx = 0;
-    }
-
-  } while ( face_idx < num_faces )
-

-
- -

FT_Open_Args

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct  FT_Open_Args_
-  {
-    FT_UInt         flags;
-    const FT_Byte*  memory_base;
-    FT_Long         memory_size;
-    FT_String*      pathname;
-    FT_Stream       stream;
-    FT_Module       driver;
-    FT_Int          num_params;
-    FT_Parameter*   params;
-
-  } FT_Open_Args;
-
- -

A structure to indicate how to open a new font file or stream. A pointer to such a structure can be used as a parameter for the functions FT_Open_Face and FT_Attach_Stream.

-

fields

- - - - - - - - - - -
flags -

A set of bit flags indicating how to use the structure.

-
memory_base -

The first byte of the file in memory.

-
memory_size -

The size in bytes of the file in memory.

-
pathname -

A pointer to an 8-bit file pathname. The pointer is not owned by FreeType.

-
stream -

A handle to a source stream object.

-
driver -

This field is exclusively used by FT_Open_Face; it simply specifies the font driver to use for opening the face. If set to NULL, FreeType tries to load the face with each one of the drivers in its list.

-
num_params -

The number of extra parameters.

-
params -

Extra parameters passed to the font driver when opening a new face.

-
- -

note

- -

The stream type is determined by the contents of flags that are tested in the following order by FT_Open_Face:

-

If the FT_OPEN_MEMORY bit is set, assume that this is a memory file of memory_size bytes, located at memory_address. The data are not copied, and the client is responsible for releasing and destroying them after the corresponding call to FT_Done_Face.

-

Otherwise, if the FT_OPEN_STREAM bit is set, assume that a custom input stream stream is used.

-

Otherwise, if the FT_OPEN_PATHNAME bit is set, assume that this is a normal file and use pathname to open it.

-

If the FT_OPEN_DRIVER bit is set, FT_Open_Face only tries to open the file with the driver whose handler is in driver.

-

If the FT_OPEN_PARAMS bit is set, the parameters given by num_params and params is used. They are ignored otherwise.

-

Ideally, both the pathname and params fields should be tagged as ‘const’; this is missing for API backward compatibility. In other words, applications should treat them as read-only.

-
- -

FT_Parameter

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct  FT_Parameter_
-  {
-    FT_ULong    tag;
-    FT_Pointer  data;
-
-  } FT_Parameter;
-
- -

A simple structure to pass more or less generic parameters to FT_Open_Face and FT_Face_Properties.

-

fields

- - - - -
tag -

A four-byte identification tag.

-
data -

A pointer to the parameter data.

-
- -

note

- -

The ID and function of parameters are driver-specific. See section ‘Parameter Tags’ for more information.

-
- -

FT_Attach_File

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Attach_File( FT_Face      face,
-                  const char*  filepathname );
-
- -

Call FT_Attach_Stream to attach a file.

-

inout

- - - -
face -

The target face object.

-
- -

input

- - - -
filepathname -

The pathname.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FT_Attach_Stream

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Attach_Stream( FT_Face        face,
-                    FT_Open_Args*  parameters );
-
- -

‘Attach’ data to a face object. Normally, this is used to read additional information for the face object. For example, you can attach an AFM file that comes with a Type 1 font to get the kerning values and other metrics.

-

inout

- - - -
face -

The target face object.

-
- -

input

- - - -
parameters -

A pointer to FT_Open_Args that must be filled by the caller.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The meaning of the ‘attach’ (i.e., what really happens when the new file is read) is not fixed by FreeType itself. It really depends on the font format (and thus the font driver).

-

Client applications are expected to know what they are doing when invoking this function. Most drivers simply do not implement file or stream attachments.

-
- -

FT_Set_Char_Size

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Set_Char_Size( FT_Face     face,
-                    FT_F26Dot6  char_width,
-                    FT_F26Dot6  char_height,
-                    FT_UInt     horz_resolution,
-                    FT_UInt     vert_resolution );
-
- -

Call FT_Request_Size to request the nominal size (in points).

-

inout

- - - -
face -

A handle to a target face object.

-
- -

input

- - - - - - -
char_width -

The nominal width, in 26.6 fractional points.

-
char_height -

The nominal height, in 26.6 fractional points.

-
horz_resolution -

The horizontal resolution in dpi.

-
vert_resolution -

The vertical resolution in dpi.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

While this function allows fractional points as input values, the resulting ppem value for the given resolution is always rounded to the nearest integer.

-

If either the character width or height is zero, it is set equal to the other value.

-

If either the horizontal or vertical resolution is zero, it is set equal to the other value.

-

A character width or height smaller than 1pt is set to 1pt; if both resolution values are zero, they are set to 72dpi.

-

Don't use this function if you are using the FreeType cache API.

-
- -

FT_Set_Pixel_Sizes

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Set_Pixel_Sizes( FT_Face  face,
-                      FT_UInt  pixel_width,
-                      FT_UInt  pixel_height );
-
- -

Call FT_Request_Size to request the nominal size (in pixels).

-

inout

- - - -
face -

A handle to the target face object.

-
- -

input

- - - - -
pixel_width -

The nominal width, in pixels.

-
pixel_height -

The nominal height, in pixels.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

You should not rely on the resulting glyphs matching or being constrained to this pixel size. Refer to FT_Request_Size to understand how requested sizes relate to actual sizes.

-

Don't use this function if you are using the FreeType cache API.

-
- -

FT_Request_Size

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Request_Size( FT_Face          face,
-                   FT_Size_Request  req );
-
- -

Resize the scale of the active FT_Size object in a face.

-

inout

- - - -
face -

A handle to a target face object.

-
- -

input

- - - -
req -

A pointer to a FT_Size_RequestRec.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

Although drivers may select the bitmap strike matching the request, you should not rely on this if you intend to select a particular bitmap strike. Use FT_Select_Size instead in that case.

-

The relation between the requested size and the resulting glyph size is dependent entirely on how the size is defined in the source face. The font designer chooses the final size of each glyph relative to this size. For more information refer to ‘https://www.freetype.org/freetype2/docs/glyphs/glyphs-2.html’.

-

Contrary to FT_Set_Char_Size, this function doesn't have special code to normalize zero-valued widths, heights, or resolutions (which lead to errors in most cases).

-

Don't use this function if you are using the FreeType cache API.

-
- -

FT_Select_Size

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Select_Size( FT_Face  face,
-                  FT_Int   strike_index );
-
- -

Select a bitmap strike. To be more precise, this function sets the scaling factors of the active FT_Size object in a face so that bitmaps from this particular strike are taken by FT_Load_Glyph and friends.

-

inout

- - - -
face -

A handle to a target face object.

-
- -

input

- - - -
strike_index -

The index of the bitmap strike in the available_sizes field of FT_FaceRec structure.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

For bitmaps embedded in outline fonts it is common that only a subset of the available glyphs at a given ppem value is available. FreeType silently uses outlines if there is no bitmap for a given glyph index.

-

For GX and OpenType variation fonts, a bitmap strike makes sense only if the default instance is active (this is, no glyph variation takes place); otherwise, FreeType simply ignores bitmap strikes. The same is true for all named instances that are different from the default instance.

-

Don't use this function if you are using the FreeType cache API.

-
- -

FT_Size_Request_Type

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef enum  FT_Size_Request_Type_
-  {
-    FT_SIZE_REQUEST_TYPE_NOMINAL,
-    FT_SIZE_REQUEST_TYPE_REAL_DIM,
-    FT_SIZE_REQUEST_TYPE_BBOX,
-    FT_SIZE_REQUEST_TYPE_CELL,
-    FT_SIZE_REQUEST_TYPE_SCALES,
-
-    FT_SIZE_REQUEST_TYPE_MAX
-
-  } FT_Size_Request_Type;
-
- -

An enumeration type that lists the supported size request types, i.e., what input size (in font units) maps to the requested output size (in pixels, as computed from the arguments of FT_Size_Request).

-

values

- - - - - - - -
FT_SIZE_REQUEST_TYPE_NOMINAL -

The nominal size. The units_per_EM field of FT_FaceRec is used to determine both scaling values.

-

This is the standard scaling found in most applications. In particular, use this size request type for TrueType fonts if they provide optical scaling or something similar. Note, however, that units_per_EM is a rather abstract value which bears no relation to the actual size of the glyphs in a font.

-
FT_SIZE_REQUEST_TYPE_REAL_DIM -

The real dimension. The sum of the ascender and (minus of) the descender fields of FT_FaceRec is used to determine both scaling values.

-
FT_SIZE_REQUEST_TYPE_BBOX -

The font bounding box. The width and height of the bbox field of FT_FaceRec are used to determine the horizontal and vertical scaling value, respectively.

-
FT_SIZE_REQUEST_TYPE_CELL -

The max_advance_width field of FT_FaceRec is used to determine the horizontal scaling value; the vertical scaling value is determined the same way as FT_SIZE_REQUEST_TYPE_REAL_DIM does. Finally, both scaling values are set to the smaller one. This type is useful if you want to specify the font size for, say, a window of a given dimension and 80x24 cells.

-
FT_SIZE_REQUEST_TYPE_SCALES -

Specify the scaling values directly.

-
- -

note

- -

The above descriptions only apply to scalable formats. For bitmap formats, the behaviour is up to the driver.

-

See the note section of FT_Size_Metrics if you wonder how size requesting relates to scaling values.

-
- -

FT_Size_RequestRec

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct  FT_Size_RequestRec_
-  {
-    FT_Size_Request_Type  type;
-    FT_Long               width;
-    FT_Long               height;
-    FT_UInt               horiResolution;
-    FT_UInt               vertResolution;
-
-  } FT_Size_RequestRec;
-
- -

A structure to model a size request.

-

fields

- - - - - - - -
type -

See FT_Size_Request_Type.

-
width -

The desired width, given as a 26.6 fractional point value (with 72pt = 1in).

-
height -

The desired height, given as a 26.6 fractional point value (with 72pt = 1in).

-
horiResolution -

The horizontal resolution (dpi, i.e., pixels per inch). If set to zero, width is treated as a 26.6 fractional pixel value, which gets internally rounded to an integer.

-
vertResolution -

The vertical resolution (dpi, i.e., pixels per inch). If set to zero, height is treated as a 26.6 fractional pixel value, which gets internally rounded to an integer.

-
- -

note

- -

If width is zero, the horizontal scaling value is set equal to the vertical scaling value, and vice versa.

-

If type is FT_SIZE_REQUEST_TYPE_SCALES, width and height are interpreted directly as 16.16 fractional scaling values, without any further modification, and both horiResolution and vertResolution are ignored.

-
- -

FT_Size_Request

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct FT_Size_RequestRec_  *FT_Size_Request;
-
- -

A handle to a size request structure.

-
- -

FT_Set_Transform

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( void )
-  FT_Set_Transform( FT_Face     face,
-                    FT_Matrix*  matrix,
-                    FT_Vector*  delta );
-
- -

Set the transformation that is applied to glyph images when they are loaded into a glyph slot through FT_Load_Glyph.

-

inout

- - - -
face -

A handle to the source face object.

-
- -

input

- - - - -
matrix -

A pointer to the transformation's 2x2 matrix. Use NULL for the identity matrix.

-
delta -

A pointer to the translation vector. Use NULL for the null vector.

-
- -

note

- -

This function is provided as a convenience, but keep in mind that FT_Matrix coefficients are only 16.16 fixed point values, which can limit the accuracy of the results. Using floating-point computations to perform the transform directly in client code instead will always yield better numbers.

-

The transformation is only applied to scalable image formats after the glyph has been loaded. It means that hinting is unaltered by the transformation and is performed on the character size given in the last call to FT_Set_Char_Size or FT_Set_Pixel_Sizes.

-

Note that this also transforms the face.glyph.advance field, but not the values in face.glyph.metrics.

-
- -

FT_Load_Glyph

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Load_Glyph( FT_Face   face,
-                 FT_UInt   glyph_index,
-                 FT_Int32  load_flags );
-
- -

Load a glyph into the glyph slot of a face object.

-

inout

- - - -
face -

A handle to the target face object where the glyph is loaded.

-
- -

input

- - - - -
glyph_index -

The index of the glyph in the font file. For CID-keyed fonts (either in PS or in CFF format) this argument specifies the CID value.

-
load_flags -

A flag indicating what to load for this glyph. The FT_LOAD_XXX constants can be used to control the glyph loading process (e.g., whether the outline should be scaled, whether to load bitmaps or not, whether to hint the outline, etc).

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The loaded glyph may be transformed. See FT_Set_Transform for the details.

-

For subsetted CID-keyed fonts, FT_Err_Invalid_Argument is returned for invalid CID values (this is, for CID values that don't have a corresponding glyph in the font). See the discussion of the FT_FACE_FLAG_CID_KEYED flag for more details.

-

If you receive FT_Err_Glyph_Too_Big, try getting the glyph outline at EM size, then scale it manually and fill it as a graphics operation.

-
- -

FT_Get_Char_Index

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_UInt )
-  FT_Get_Char_Index( FT_Face   face,
-                     FT_ULong  charcode );
-
- -

Return the glyph index of a given character code. This function uses the currently selected charmap to do the mapping.

-

input

- - - - -
face -

A handle to the source face object.

-
charcode -

The character code.

-
- -

return

- -

The glyph index. 0 means ‘undefined character code’.

-

note

- -

If you use FreeType to manipulate the contents of font files directly, be aware that the glyph index returned by this function doesn't always correspond to the internal indices used within the file. This is done to ensure that value 0 always corresponds to the ‘missing glyph’. If the first glyph is not named ‘.notdef’, then for Type 1 and Type 42 fonts, ‘.notdef’ will be moved into the glyph ID 0 position, and whatever was there will be moved to the position ‘.notdef’ had. For Type 1 fonts, if there is no ‘.notdef’ glyph at all, then one will be created at index 0 and whatever was there will be moved to the last index -- Type 42 fonts are considered invalid under this condition.

-
- -

FT_Get_First_Char

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_ULong )
-  FT_Get_First_Char( FT_Face   face,
-                     FT_UInt  *agindex );
-
- -

Return the first character code in the current charmap of a given face, together with its corresponding glyph index.

-

input

- - - -
face -

A handle to the source face object.

-
- -

output

- - - -
agindex -

Glyph index of first character code. 0 if charmap is empty.

-
- -

return

- -

The charmap's first character code.

-

note

- -

You should use this function together with FT_Get_Next_Char to parse all character codes available in a given charmap. The code should look like this: -

  FT_ULong  charcode;
-  FT_UInt   gindex;
-
-
-  charcode = FT_Get_First_Char( face, &gindex );
-  while ( gindex != 0 )
-  {
-    ... do something with (charcode,gindex) pair ...
-
-    charcode = FT_Get_Next_Char( face, charcode, &gindex );
-  }
-

-

Be aware that character codes can have values up to 0xFFFFFFFF; this might happen for non-Unicode or malformed cmaps. However, even with regular Unicode encoding, so-called ‘last resort fonts’ (using SFNT cmap format 13, see function FT_Get_CMap_Format) normally have entries for all Unicode characters up to 0x1FFFFF, which can cause a lot of iterations.

-

Note that *agindex is set to 0 if the charmap is empty. The result itself can be 0 in two cases: if the charmap is empty or if the value 0 is the first valid character code.

-
- -

FT_Get_Next_Char

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_ULong )
-  FT_Get_Next_Char( FT_Face    face,
-                    FT_ULong   char_code,
-                    FT_UInt   *agindex );
-
- -

Return the next character code in the current charmap of a given face following the value char_code, as well as the corresponding glyph index.

-

input

- - - - -
face -

A handle to the source face object.

-
char_code -

The starting character code.

-
- -

output

- - - -
agindex -

Glyph index of next character code. 0 if charmap is empty.

-
- -

return

- -

The charmap's next character code.

-

note

- -

You should use this function with FT_Get_First_Char to walk over all character codes available in a given charmap. See the note for that function for a simple code example.

-

Note that *agindex is set to 0 when there are no more codes in the charmap.

-
- -

FT_Get_Name_Index

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_UInt )
-  FT_Get_Name_Index( FT_Face           face,
-                     const FT_String*  glyph_name );
-
- -

Return the glyph index of a given glyph name.

-

input

- - - - -
face -

A handle to the source face object.

-
glyph_name -

The glyph name.

-
- -

return

- -

The glyph index. 0 means ‘undefined character code’.

-
- -

FT_Load_Char

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Load_Char( FT_Face   face,
-                FT_ULong  char_code,
-                FT_Int32  load_flags );
-
- -

Load a glyph into the glyph slot of a face object, accessed by its character code.

-

inout

- - - -
face -

A handle to a target face object where the glyph is loaded.

-
- -

input

- - - - -
char_code -

The glyph's character code, according to the current charmap used in the face.

-
load_flags -

A flag indicating what to load for this glyph. The FT_LOAD_XXX constants can be used to control the glyph loading process (e.g., whether the outline should be scaled, whether to load bitmaps or not, whether to hint the outline, etc).

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function simply calls FT_Get_Char_Index and FT_Load_Glyph.

-

Many fonts contain glyphs that can't be loaded by this function since its glyph indices are not listed in any of the font's charmaps.

-

If no active cmap is set up (i.e., face->charmap is zero), the call to FT_Get_Char_Index is omitted, and the function behaves identically to FT_Load_Glyph.

-
- -

FT_LOAD_TARGET_MODE

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_LOAD_TARGET_MODE( x )  ( (FT_Render_Mode)( ( (x) >> 16 ) & 15 ) )
-
- -

Return the FT_Render_Mode corresponding to a given FT_LOAD_TARGET_XXX value.

-
- -

FT_Render_Glyph

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Render_Glyph( FT_GlyphSlot    slot,
-                   FT_Render_Mode  render_mode );
-
- -

Convert a given glyph image to a bitmap. It does so by inspecting the glyph image format, finding the relevant renderer, and invoking it.

-

inout

- - - -
slot -

A handle to the glyph slot containing the image to convert.

-
- -

input

- - - -
render_mode -

The render mode used to render the glyph image into a bitmap. See FT_Render_Mode for a list of possible values.

-

If FT_RENDER_MODE_NORMAL is used, a previous call of FT_Load_Glyph with flag FT_LOAD_COLOR makes FT_Render_Glyph provide a default blending of colored glyph layers associated with the current glyph slot (provided the font contains such layers) instead of rendering the glyph slot's outline. This is an experimental feature; see FT_LOAD_COLOR for more information.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

To get meaningful results, font scaling values must be set with functions like FT_Set_Char_Size before calling FT_Render_Glyph.

-

When FreeType outputs a bitmap of a glyph, it really outputs an alpha coverage map. If a pixel is completely covered by a filled-in outline, the bitmap contains 0xFF at that pixel, meaning that 0xFF/0xFF fraction of that pixel is covered, meaning the pixel is 100% black (or 0% bright). If a pixel is only 50% covered (value 0x80), the pixel is made 50% black (50% bright or a middle shade of grey). 0% covered means 0% black (100% bright or white).

-

On high-DPI screens like on smartphones and tablets, the pixels are so small that their chance of being completely covered and therefore completely black are fairly good. On the low-DPI screens, however, the situation is different. The pixels are too large for most of the details of a glyph and shades of gray are the norm rather than the exception.

-

This is relevant because all our screens have a second problem: they are not linear. 1 + 1 is not 2. Twice the value does not result in twice the brightness. When a pixel is only 50% covered, the coverage map says 50% black, and this translates to a pixel value of 128 when you use 8 bits per channel (0-255). However, this does not translate to 50% brightness for that pixel on our sRGB and gamma 2.2 screens. Due to their non-linearity, they dwell longer in the darks and only a pixel value of about 186 results in 50% brightness -- 128 ends up too dark on both bright and dark backgrounds. The net result is that dark text looks burnt-out, pixely and blotchy on bright background, bright text too frail on dark backgrounds, and colored text on colored background (for example, red on green) seems to have dark halos or ‘dirt’ around it. The situation is especially ugly for diagonal stems like in ‘w’ glyph shapes where the quality of FreeType's anti-aliasing depends on the correct display of grays. On high-DPI screens where smaller, fully black pixels reign supreme, this doesn't matter, but on our low-DPI screens with all the gray shades, it does. 0% and 100% brightness are the same things in linear and non-linear space, just all the shades in-between aren't.

-

The blending function for placing text over a background is -

  dst = alpha * src + (1 - alpha) * dst    ,
-

-

which is known as the OVER operator.

-

To correctly composite an antialiased pixel of a glyph onto a surface,

-
    -
  1. -

    take the foreground and background colors (e.g., in sRGB space) and apply gamma to get them in a linear space,

    -
  2. -
  3. -

    use OVER to blend the two linear colors using the glyph pixel as the alpha value (remember, the glyph bitmap is an alpha coverage bitmap), and

    -
  4. -
  5. -

    apply inverse gamma to the blended pixel and write it back to the image.

    -
  6. -
-

Internal testing at Adobe found that a target inverse gamma of 1.8 for step 3 gives good results across a wide range of displays with an sRGB gamma curve or a similar one.

-

This process can cost performance. There is an approximation that does not need to know about the background color; see https://bel.fi/alankila/lcd/ and https://bel.fi/alankila/lcd/alpcor.html for details.

-

ATTENTION: Linear blending is even more important when dealing with subpixel-rendered glyphs to prevent color-fringing! A subpixel-rendered glyph must first be filtered with a filter that gives equal weight to the three color primaries and does not exceed a sum of 0x100, see section ‘Subpixel Rendering’. Then the only difference to gray linear blending is that subpixel-rendered linear blending is done 3 times per pixel: red foreground subpixel to red background subpixel and so on for green and blue.

-
- -

FT_Render_Mode

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef enum  FT_Render_Mode_
-  {
-    FT_RENDER_MODE_NORMAL = 0,
-    FT_RENDER_MODE_LIGHT,
-    FT_RENDER_MODE_MONO,
-    FT_RENDER_MODE_LCD,
-    FT_RENDER_MODE_LCD_V,
-
-    FT_RENDER_MODE_MAX
-
-  } FT_Render_Mode;
-
-
-  /* these constants are deprecated; use the corresponding */
-  /* `FT_Render_Mode` values instead                       */
-#define ft_render_mode_normal  FT_RENDER_MODE_NORMAL
-#define ft_render_mode_mono    FT_RENDER_MODE_MONO
-
- -

Render modes supported by FreeType 2. Each mode corresponds to a specific type of scanline conversion performed on the outline.

-

For bitmap fonts and embedded bitmaps the bitmap->pixel_mode field in the FT_GlyphSlotRec structure gives the format of the returned bitmap.

-

All modes except FT_RENDER_MODE_MONO use 256 levels of opacity, indicating pixel coverage. Use linear alpha blending and gamma correction to correctly render non-monochrome glyph bitmaps onto a surface; see FT_Render_Glyph.

-

values

- - - - - - - -
FT_RENDER_MODE_NORMAL -

Default render mode; it corresponds to 8-bit anti-aliased bitmaps.

-
FT_RENDER_MODE_LIGHT -

This is equivalent to FT_RENDER_MODE_NORMAL. It is only defined as a separate value because render modes are also used indirectly to define hinting algorithm selectors. See FT_LOAD_TARGET_XXX for details.

-
FT_RENDER_MODE_MONO -

This mode corresponds to 1-bit bitmaps (with 2 levels of opacity).

-
FT_RENDER_MODE_LCD -

This mode corresponds to horizontal RGB and BGR subpixel displays like LCD screens. It produces 8-bit bitmaps that are 3 times the width of the original glyph outline in pixels, and which use the FT_PIXEL_MODE_LCD mode.

-
FT_RENDER_MODE_LCD_V -

This mode corresponds to vertical RGB and BGR subpixel displays (like PDA screens, rotated LCD displays, etc.). It produces 8-bit bitmaps that are 3 times the height of the original glyph outline in pixels and use the FT_PIXEL_MODE_LCD_V mode.

-
- -

note

- -

The selected render mode only affects vector glyphs of a font. Embedded bitmaps often have a different pixel mode like FT_PIXEL_MODE_MONO. You can use FT_Bitmap_Convert to transform them into 8-bit pixmaps.

-
- -

FT_Get_Kerning

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_Kerning( FT_Face     face,
-                  FT_UInt     left_glyph,
-                  FT_UInt     right_glyph,
-                  FT_UInt     kern_mode,
-                  FT_Vector  *akerning );
-
- -

Return the kerning vector between two glyphs of the same face.

-

input

- - - - - - -
face -

A handle to a source face object.

-
left_glyph -

The index of the left glyph in the kern pair.

-
right_glyph -

The index of the right glyph in the kern pair.

-
kern_mode -

See FT_Kerning_Mode for more information. Determines the scale and dimension of the returned kerning vector.

-
- -

output

- - - -
akerning -

The kerning vector. This is either in font units, fractional pixels (26.6 format), or pixels for scalable formats, and in pixels for fixed-sizes formats.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

Only horizontal layouts (left-to-right & right-to-left) are supported by this method. Other layouts, or more sophisticated kernings, are out of the scope of this API function -- they can be implemented through format-specific interfaces.

-

Kerning for OpenType fonts implemented in a ‘GPOS’ table is not supported; use FT_HAS_KERNING to find out whether a font has data that can be extracted with FT_Get_Kerning.

-
- -

FT_Kerning_Mode

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef enum  FT_Kerning_Mode_
-  {
-    FT_KERNING_DEFAULT = 0,
-    FT_KERNING_UNFITTED,
-    FT_KERNING_UNSCALED
-
-  } FT_Kerning_Mode;
-
-
-  /* these constants are deprecated; use the corresponding */
-  /* `FT_Kerning_Mode` values instead                      */
-#define ft_kerning_default   FT_KERNING_DEFAULT
-#define ft_kerning_unfitted  FT_KERNING_UNFITTED
-#define ft_kerning_unscaled  FT_KERNING_UNSCALED
-
- -

An enumeration to specify the format of kerning values returned by FT_Get_Kerning.

-

values

- - - - - -
FT_KERNING_DEFAULT -

Return grid-fitted kerning distances in 26.6 fractional pixels.

-
FT_KERNING_UNFITTED -

Return un-grid-fitted kerning distances in 26.6 fractional pixels.

-
FT_KERNING_UNSCALED -

Return the kerning vector in original font units.

-
- -

note

- -

FT_KERNING_DEFAULT returns full pixel values; it also makes FreeType heuristically scale down kerning distances at small ppem values so that they don't become too big.

-

Both FT_KERNING_DEFAULT and FT_KERNING_UNFITTED use the current horizontal scaling factor (as set e.g. with FT_Set_Char_Size) to convert font units to pixels.

-
- -

FT_Get_Track_Kerning

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_Track_Kerning( FT_Face    face,
-                        FT_Fixed   point_size,
-                        FT_Int     degree,
-                        FT_Fixed*  akerning );
-
- -

Return the track kerning for a given face object at a given size.

-

input

- - - - - -
face -

A handle to a source face object.

-
point_size -

The point size in 16.16 fractional points.

-
degree -

The degree of tightness. Increasingly negative values represent tighter track kerning, while increasingly positive values represent looser track kerning. Value zero means no track kerning.

-
- -

output

- - - -
akerning -

The kerning in 16.16 fractional points, to be uniformly applied between all glyphs.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

Currently, only the Type 1 font driver supports track kerning, using data from AFM files (if attached with FT_Attach_File or FT_Attach_Stream).

-

Only very few AFM files come with track kerning data; please refer to Adobe's AFM specification for more details.

-
- -

FT_Get_Glyph_Name

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_Glyph_Name( FT_Face     face,
-                     FT_UInt     glyph_index,
-                     FT_Pointer  buffer,
-                     FT_UInt     buffer_max );
-
- -

Retrieve the ASCII name of a given glyph in a face. This only works for those faces where FT_HAS_GLYPH_NAMES(face) returns 1.

-

input

- - - - - -
face -

A handle to a source face object.

-
glyph_index -

The glyph index.

-
buffer_max -

The maximum number of bytes available in the buffer.

-
- -

output

- - - -
buffer -

A pointer to a target buffer where the name is copied to.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

An error is returned if the face doesn't provide glyph names or if the glyph index is invalid. In all cases of failure, the first byte of buffer is set to 0 to indicate an empty name.

-

The glyph name is truncated to fit within the buffer if it is too long. The returned string is always zero-terminated.

-

Be aware that FreeType reorders glyph indices internally so that glyph index 0 always corresponds to the ‘missing glyph’ (called ‘.notdef’).

-

This function always returns an error if the config macro FT_CONFIG_OPTION_NO_GLYPH_NAMES is not defined in ftoption.h.

-
- -

FT_Get_Postscript_Name

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( const char* )
-  FT_Get_Postscript_Name( FT_Face  face );
-
- -

Retrieve the ASCII PostScript name of a given face, if available. This only works with PostScript, TrueType, and OpenType fonts.

-

input

- - - -
face -

A handle to the source face object.

-
- -

return

- -

A pointer to the face's PostScript name. NULL if unavailable.

-

note

- -

The returned pointer is owned by the face and is destroyed with it.

-

For variation fonts, this string changes if you select a different instance, and you have to call FT_Get_PostScript_Name again to retrieve it. FreeType follows Adobe TechNote #5902, ‘Generating PostScript Names for Fonts Using OpenType Font Variations’.

-

https://download.macromedia.com/pub/developer/opentype/tech-notes/5902.AdobePSNameGeneration.html

-

[Since 2.9] Special PostScript names for named instances are only returned if the named instance is set with FT_Set_Named_Instance (and the font has corresponding entries in its ‘fvar’ table). If FT_IS_VARIATION returns true, the algorithmically derived PostScript name is provided, not looking up special entries for named instances.

-
- -

FT_CharMapRec

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct  FT_CharMapRec_
-  {
-    FT_Face      face;
-    FT_Encoding  encoding;
-    FT_UShort    platform_id;
-    FT_UShort    encoding_id;
-
-  } FT_CharMapRec;
-
- -

The base charmap structure.

-

fields

- - - - - - -
face -

A handle to the parent face object.

-
encoding -

An FT_Encoding tag identifying the charmap. Use this with FT_Select_Charmap.

-
platform_id -

An ID number describing the platform for the following encoding ID. This comes directly from the TrueType specification and gets emulated for other formats.

-
encoding_id -

A platform-specific encoding number. This also comes from the TrueType specification and gets emulated similarly.

-
- -
- -

FT_Select_Charmap

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Select_Charmap( FT_Face      face,
-                     FT_Encoding  encoding );
-
- -

Select a given charmap by its encoding tag (as listed in freetype.h).

-

inout

- - - -
face -

A handle to the source face object.

-
- -

input

- - - -
encoding -

A handle to the selected encoding.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function returns an error if no charmap in the face corresponds to the encoding queried here.

-

Because many fonts contain more than a single cmap for Unicode encoding, this function has some special code to select the one that covers Unicode best (‘best’ in the sense that a UCS-4 cmap is preferred to a UCS-2 cmap). It is thus preferable to FT_Set_Charmap in this case.

-
- -

FT_Set_Charmap

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Set_Charmap( FT_Face     face,
-                  FT_CharMap  charmap );
-
- -

Select a given charmap for character code to glyph index mapping.

-

inout

- - - -
face -

A handle to the source face object.

-
- -

input

- - - -
charmap -

A handle to the selected charmap.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function returns an error if the charmap is not part of the face (i.e., if it is not listed in the face->charmaps table).

-

It also fails if an OpenType type 14 charmap is selected (which doesn't map character codes to glyph indices at all).

-
- -

FT_Get_Charmap_Index

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Int )
-  FT_Get_Charmap_Index( FT_CharMap  charmap );
-
- -

Retrieve index of a given charmap.

-

input

- - - -
charmap -

A handle to a charmap.

-
- -

return

- -

The index into the array of character maps within the face to which charmap belongs. If an error occurs, -1 is returned.

-
- -

FT_Get_FSType_Flags

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_UShort )
-  FT_Get_FSType_Flags( FT_Face  face );
-
- -

Return the fsType flags for a font.

-

input

- - - -
face -

A handle to the source face object.

-
- -

return

- -

The fsType flags, see FT_FSTYPE_XXX.

-

note

- -

Use this function rather than directly reading the fs_type field in the PS_FontInfoRec structure, which is only guaranteed to return the correct results for Type 1 fonts.

-

since

- -

2.3.8

-
- -

FT_Get_SubGlyph_Info

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_SubGlyph_Info( FT_GlyphSlot  glyph,
-                        FT_UInt       sub_index,
-                        FT_Int       *p_index,
-                        FT_UInt      *p_flags,
-                        FT_Int       *p_arg1,
-                        FT_Int       *p_arg2,
-                        FT_Matrix    *p_transform );
-
- -

Retrieve a description of a given subglyph. Only use it if glyph->format is FT_GLYPH_FORMAT_COMPOSITE; an error is returned otherwise.

-

input

- - - - -
glyph -

The source glyph slot.

-
sub_index -

The index of the subglyph. Must be less than glyph->num_subglyphs.

-
- -

output

- - - - - - - -
p_index -

The glyph index of the subglyph.

-
p_flags -

The subglyph flags, see FT_SUBGLYPH_FLAG_XXX.

-
p_arg1 -

The subglyph's first argument (if any).

-
p_arg2 -

The subglyph's second argument (if any).

-
p_transform -

The subglyph transformation (if any).

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The values of *p_arg1, *p_arg2, and *p_transform must be interpreted depending on the flags returned in *p_flags. See the OpenType specification for details.

-

https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#composite-glyph-description

-
- -

FT_Face_Internal

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct FT_Face_InternalRec_*  FT_Face_Internal;
-
- -

An opaque handle to an FT_Face_InternalRec structure that models the private data of a given FT_Face object.

-

This structure might change between releases of FreeType 2 and is not generally available to client applications.

-
- -

FT_Size_Internal

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct FT_Size_InternalRec_*  FT_Size_Internal;
-
- -

An opaque handle to an FT_Size_InternalRec structure, used to model private data of a given FT_Size object.

-
- -

FT_Slot_Internal

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct FT_Slot_InternalRec_*  FT_Slot_Internal;
-
- -

An opaque handle to an FT_Slot_InternalRec structure, used to model private data of a given FT_GlyphSlot object.

-
- -

FT_FACE_FLAG_XXX

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_FACE_FLAG_SCALABLE          ( 1L <<  0 )
-#define FT_FACE_FLAG_FIXED_SIZES       ( 1L <<  1 )
-#define FT_FACE_FLAG_FIXED_WIDTH       ( 1L <<  2 )
-#define FT_FACE_FLAG_SFNT              ( 1L <<  3 )
-#define FT_FACE_FLAG_HORIZONTAL        ( 1L <<  4 )
-#define FT_FACE_FLAG_VERTICAL          ( 1L <<  5 )
-#define FT_FACE_FLAG_KERNING           ( 1L <<  6 )
-#define FT_FACE_FLAG_FAST_GLYPHS       ( 1L <<  7 )
-#define FT_FACE_FLAG_MULTIPLE_MASTERS  ( 1L <<  8 )
-#define FT_FACE_FLAG_GLYPH_NAMES       ( 1L <<  9 )
-#define FT_FACE_FLAG_EXTERNAL_STREAM   ( 1L << 10 )
-#define FT_FACE_FLAG_HINTER            ( 1L << 11 )
-#define FT_FACE_FLAG_CID_KEYED         ( 1L << 12 )
-#define FT_FACE_FLAG_TRICKY            ( 1L << 13 )
-#define FT_FACE_FLAG_COLOR             ( 1L << 14 )
-#define FT_FACE_FLAG_VARIATION         ( 1L << 15 )
-
- -

A list of bit flags used in the face_flags field of the FT_FaceRec structure. They inform client applications of properties of the corresponding face.

-

values

- - - - - - - - - - - - - - - - - - -
FT_FACE_FLAG_SCALABLE -

The face contains outline glyphs. Note that a face can contain bitmap strikes also, i.e., a face can have both this flag and FT_FACE_FLAG_FIXED_SIZES set.

-
FT_FACE_FLAG_FIXED_SIZES -

The face contains bitmap strikes. See also the num_fixed_sizes and available_sizes fields of FT_FaceRec.

-
FT_FACE_FLAG_FIXED_WIDTH -

The face contains fixed-width characters (like Courier, Lucida, MonoType, etc.).

-
FT_FACE_FLAG_SFNT -

The face uses the SFNT storage scheme. For now, this means TrueType and OpenType.

-
FT_FACE_FLAG_HORIZONTAL -

The face contains horizontal glyph metrics. This should be set for all common formats.

-
FT_FACE_FLAG_VERTICAL -

The face contains vertical glyph metrics. This is only available in some formats, not all of them.

-
FT_FACE_FLAG_KERNING -

The face contains kerning information. If set, the kerning distance can be retrieved using the function FT_Get_Kerning. Otherwise the function always return the vector (0,0). Note that FreeType doesn't handle kerning data from the SFNT ‘GPOS’ table (as present in many OpenType fonts).

-
FT_FACE_FLAG_FAST_GLYPHS -

THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT.

-
FT_FACE_FLAG_MULTIPLE_MASTERS -

The face contains multiple masters and is capable of interpolating between them. Supported formats are Adobe MM, TrueType GX, and OpenType variation fonts.

-

See section ‘Multiple Masters’ for API details.

-
FT_FACE_FLAG_GLYPH_NAMES -

The face contains glyph names, which can be retrieved using FT_Get_Glyph_Name. Note that some TrueType fonts contain broken glyph name tables. Use the function FT_Has_PS_Glyph_Names when needed.

-
FT_FACE_FLAG_EXTERNAL_STREAM -

Used internally by FreeType to indicate that a face's stream was provided by the client application and should not be destroyed when FT_Done_Face is called. Don't read or test this flag.

-
FT_FACE_FLAG_HINTER -

The font driver has a hinting machine of its own. For example, with TrueType fonts, it makes sense to use data from the SFNT ‘gasp’ table only if the native TrueType hinting engine (with the bytecode interpreter) is available and active.

-
FT_FACE_FLAG_CID_KEYED -

The face is CID-keyed. In that case, the face is not accessed by glyph indices but by CID values. For subsetted CID-keyed fonts this has the consequence that not all index values are a valid argument to FT_Load_Glyph. Only the CID values for which corresponding glyphs in the subsetted font exist make FT_Load_Glyph return successfully; in all other cases you get an FT_Err_Invalid_Argument error.

-

Note that CID-keyed fonts that are in an SFNT wrapper (this is, all OpenType/CFF fonts) don't have this flag set since the glyphs are accessed in the normal way (using contiguous indices); the ‘CID-ness’ isn't visible to the application.

-
FT_FACE_FLAG_TRICKY -

The face is ‘tricky’, this is, it always needs the font format's native hinting engine to get a reasonable result. A typical example is the old Chinese font mingli.ttf (but not mingliu.ttc) that uses TrueType bytecode instructions to move and scale all of its subglyphs.

-

It is not possible to auto-hint such fonts using FT_LOAD_FORCE_AUTOHINT; it will also ignore FT_LOAD_NO_HINTING. You have to set both FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT to really disable hinting; however, you probably never want this except for demonstration purposes.

-

Currently, there are about a dozen TrueType fonts in the list of tricky fonts; they are hard-coded in file ttobjs.c.

-
FT_FACE_FLAG_COLOR -

[Since 2.5.1] The face has color glyph tables. See FT_LOAD_COLOR for more information.

-
FT_FACE_FLAG_VARIATION -

[Since 2.9] Set if the current face (or named instance) has been altered with FT_Set_MM_Design_Coordinates, FT_Set_Var_Design_Coordinates, or FT_Set_Var_Blend_Coordinates. This flag is unset by a call to FT_Set_Named_Instance.

-
- -
- -

FT_STYLE_FLAG_XXX

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_STYLE_FLAG_ITALIC  ( 1 << 0 )
-#define FT_STYLE_FLAG_BOLD    ( 1 << 1 )
-
- -

A list of bit flags to indicate the style of a given face. These are used in the style_flags field of FT_FaceRec.

-

values

- - - - -
FT_STYLE_FLAG_ITALIC -

The face style is italic or oblique.

-
FT_STYLE_FLAG_BOLD -

The face is bold.

-
- -

note

- -

The style information as provided by FreeType is very basic. More details are beyond the scope and should be done on a higher level (for example, by analyzing various fields of the ‘OS/2’ table in SFNT based fonts).

-
- -

FT_OPEN_XXX

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_OPEN_MEMORY    0x1
-#define FT_OPEN_STREAM    0x2
-#define FT_OPEN_PATHNAME  0x4
-#define FT_OPEN_DRIVER    0x8
-#define FT_OPEN_PARAMS    0x10
-
-  /* these constants are deprecated; use the corresponding `FT_OPEN_XXX` */
-  /* values instead                                                      */
-#define ft_open_memory    FT_OPEN_MEMORY
-#define ft_open_stream    FT_OPEN_STREAM
-#define ft_open_pathname  FT_OPEN_PATHNAME
-#define ft_open_driver    FT_OPEN_DRIVER
-#define ft_open_params    FT_OPEN_PARAMS
-
- -

A list of bit field constants used within the flags field of the FT_Open_Args structure.

-

values

- - - - - - - -
FT_OPEN_MEMORY -

This is a memory-based stream.

-
FT_OPEN_STREAM -

Copy the stream from the stream field.

-
FT_OPEN_PATHNAME -

Create a new input stream from a C path name.

-
FT_OPEN_DRIVER -

Use the driver field.

-
FT_OPEN_PARAMS -

Use the num_params and params fields.

-
- -

note

- -

The FT_OPEN_MEMORY, FT_OPEN_STREAM, and FT_OPEN_PATHNAME flags are mutually exclusive.

-
- -

FT_LOAD_XXX

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_LOAD_DEFAULT                      0x0
-#define FT_LOAD_NO_SCALE                     ( 1L << 0 )
-#define FT_LOAD_NO_HINTING                   ( 1L << 1 )
-#define FT_LOAD_RENDER                       ( 1L << 2 )
-#define FT_LOAD_NO_BITMAP                    ( 1L << 3 )
-#define FT_LOAD_VERTICAL_LAYOUT              ( 1L << 4 )
-#define FT_LOAD_FORCE_AUTOHINT               ( 1L << 5 )
-#define FT_LOAD_CROP_BITMAP                  ( 1L << 6 )
-#define FT_LOAD_PEDANTIC                     ( 1L << 7 )
-#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH  ( 1L << 9 )
-#define FT_LOAD_NO_RECURSE                   ( 1L << 10 )
-#define FT_LOAD_IGNORE_TRANSFORM             ( 1L << 11 )
-#define FT_LOAD_MONOCHROME                   ( 1L << 12 )
-#define FT_LOAD_LINEAR_DESIGN                ( 1L << 13 )
-#define FT_LOAD_NO_AUTOHINT                  ( 1L << 15 )
-  /* Bits 16-19 are used by `FT_LOAD_TARGET_` */
-#define FT_LOAD_COLOR                        ( 1L << 20 )
-#define FT_LOAD_COMPUTE_METRICS              ( 1L << 21 )
-#define FT_LOAD_BITMAP_METRICS_ONLY          ( 1L << 22 )
-
- -

A list of bit field constants for FT_Load_Glyph to indicate what kind of operations to perform during glyph loading.

-

values

- - - - - - - - - - - - - - - - - - - - -
FT_LOAD_DEFAULT -

Corresponding to 0, this value is used as the default glyph load operation. In this case, the following happens:

-
    -
  1. FreeType looks for a bitmap for the glyph corresponding to the face's current size. If one is found, the function returns. The bitmap data can be accessed from the glyph slot (see note below).

    -
  2. -
  3. If no embedded bitmap is searched for or found, FreeType looks for a scalable outline. If one is found, it is loaded from the font file, scaled to device pixels, then ‘hinted’ to the pixel grid in order to optimize it. The outline data can be accessed from the glyph slot (see note below).

    -
  4. -
-

Note that by default the glyph loader doesn't render outlines into bitmaps. The following flags are used to modify this default behaviour to more specific and useful cases.

-
FT_LOAD_NO_SCALE -

Don't scale the loaded outline glyph but keep it in font units.

-

This flag implies FT_LOAD_NO_HINTING and FT_LOAD_NO_BITMAP, and unsets FT_LOAD_RENDER.

-

If the font is ‘tricky’ (see FT_FACE_FLAG_TRICKY for more), using FT_LOAD_NO_SCALE usually yields meaningless outlines because the subglyphs must be scaled and positioned with hinting instructions. This can be solved by loading the font without FT_LOAD_NO_SCALE and setting the character size to font->units_per_EM.

-
FT_LOAD_NO_HINTING -

Disable hinting. This generally generates ‘blurrier’ bitmap glyphs when the glyph are rendered in any of the anti-aliased modes. See also the note below.

-

This flag is implied by FT_LOAD_NO_SCALE.

-
FT_LOAD_RENDER -

Call FT_Render_Glyph after the glyph is loaded. By default, the glyph is rendered in FT_RENDER_MODE_NORMAL mode. This can be overridden by FT_LOAD_TARGET_XXX or FT_LOAD_MONOCHROME.

-

This flag is unset by FT_LOAD_NO_SCALE.

-
FT_LOAD_NO_BITMAP -

Ignore bitmap strikes when loading. Bitmap-only fonts ignore this flag.

-

FT_LOAD_NO_SCALE always sets this flag.

-
FT_LOAD_VERTICAL_LAYOUT -

Load the glyph for vertical text layout. In particular, the advance value in the FT_GlyphSlotRec structure is set to the vertAdvance value of the metrics field.

-

In case FT_HAS_VERTICAL doesn't return true, you shouldn't use this flag currently. Reason is that in this case vertical metrics get synthesized, and those values are not always consistent across various font formats.

-
FT_LOAD_FORCE_AUTOHINT -

Prefer the auto-hinter over the font's native hinter. See also the note below.

-
FT_LOAD_PEDANTIC -

Make the font driver perform pedantic verifications during glyph loading and hinting. This is mostly used to detect broken glyphs in fonts. By default, FreeType tries to handle broken fonts also.

-

In particular, errors from the TrueType bytecode engine are not passed to the application if this flag is not set; this might result in partially hinted or distorted glyphs in case a glyph's bytecode is buggy.

-
FT_LOAD_NO_RECURSE -

Don't load composite glyphs recursively. Instead, the font driver fills the num_subglyph and subglyphs values of the glyph slot; it also sets glyph->format to FT_GLYPH_FORMAT_COMPOSITE. The description of subglyphs can then be accessed with FT_Get_SubGlyph_Info.

-

Don't use this flag for retrieving metrics information since some font drivers only return rudimentary data.

-

This flag implies FT_LOAD_NO_SCALE and FT_LOAD_IGNORE_TRANSFORM.

-
FT_LOAD_IGNORE_TRANSFORM -

Ignore the transform matrix set by FT_Set_Transform.

-
FT_LOAD_MONOCHROME -

This flag is used with FT_LOAD_RENDER to indicate that you want to render an outline glyph to a 1-bit monochrome bitmap glyph, with 8 pixels packed into each byte of the bitmap data.

-

Note that this has no effect on the hinting algorithm used. You should rather use FT_LOAD_TARGET_MONO so that the monochrome-optimized hinting algorithm is used.

-
FT_LOAD_LINEAR_DESIGN -

Keep linearHoriAdvance and linearVertAdvance fields of FT_GlyphSlotRec in font units. See FT_GlyphSlotRec for details.

-
FT_LOAD_NO_AUTOHINT -

Disable the auto-hinter. See also the note below.

-
FT_LOAD_COLOR -

Load colored glyphs. There are slight differences depending on the font format.

-

[Since 2.5] Load embedded color bitmap images. The resulting color bitmaps, if available, will have the FT_PIXEL_MODE_BGRA format, with pre-multiplied color channels. If the flag is not set and color bitmaps are found, they are converted to 256-level gray bitmaps, using the FT_PIXEL_MODE_GRAY format.

-

[Since 2.10, experimental] If the glyph index contains an entry in the face's ‘COLR’ table with a ‘CPAL’ palette table (as defined in the OpenType specification), make FT_Render_Glyph provide a default blending of the color glyph layers associated with the glyph index, using the same bitmap format as embedded color bitmap images. This is mainly for convenience; for full control of color layers use FT_Get_Color_Glyph_Layer and FreeType's color functions like FT_Palette_Select instead of setting FT_LOAD_COLOR for rendering so that the client application can handle blending by itself.

-
FT_LOAD_COMPUTE_METRICS -

[Since 2.6.1] Compute glyph metrics from the glyph data, without the use of bundled metrics tables (for example, the ‘hdmx’ table in TrueType fonts). This flag is mainly used by font validating or font editing applications, which need to ignore, verify, or edit those tables.

-

Currently, this flag is only implemented for TrueType fonts.

-
FT_LOAD_BITMAP_METRICS_ONLY -

[Since 2.7.1] Request loading of the metrics and bitmap image information of a (possibly embedded) bitmap glyph without allocating or copying the bitmap image data itself. No effect if the target glyph is not a bitmap image.

-

This flag unsets FT_LOAD_RENDER.

-
FT_LOAD_CROP_BITMAP -

Ignored. Deprecated.

-
FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH -

Ignored. Deprecated.

-
- -

note

- -

By default, hinting is enabled and the font's native hinter (see FT_FACE_FLAG_HINTER) is preferred over the auto-hinter. You can disable hinting by setting FT_LOAD_NO_HINTING or change the precedence by setting FT_LOAD_FORCE_AUTOHINT. You can also set FT_LOAD_NO_AUTOHINT in case you don't want the auto-hinter to be used at all.

-

See the description of FT_FACE_FLAG_TRICKY for a special exception (affecting only a handful of Asian fonts).

-

Besides deciding which hinter to use, you can also decide which hinting algorithm to use. See FT_LOAD_TARGET_XXX for details.

-

Note that the auto-hinter needs a valid Unicode cmap (either a native one or synthesized by FreeType) for producing correct results. If a font provides an incorrect mapping (for example, assigning the character code U+005A, LATIN CAPITAL LETTER Z, to a glyph depicting a mathematical integral sign), the auto-hinter might produce useless results.

-
- -

FT_LOAD_TARGET_XXX

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_LOAD_TARGET_( x )   ( (FT_Int32)( (x) & 15 ) << 16 )
-
-#define FT_LOAD_TARGET_NORMAL  FT_LOAD_TARGET_( FT_RENDER_MODE_NORMAL )
-#define FT_LOAD_TARGET_LIGHT   FT_LOAD_TARGET_( FT_RENDER_MODE_LIGHT  )
-#define FT_LOAD_TARGET_MONO    FT_LOAD_TARGET_( FT_RENDER_MODE_MONO   )
-#define FT_LOAD_TARGET_LCD     FT_LOAD_TARGET_( FT_RENDER_MODE_LCD    )
-#define FT_LOAD_TARGET_LCD_V   FT_LOAD_TARGET_( FT_RENDER_MODE_LCD_V  )
-
- -

A list of values to select a specific hinting algorithm for the hinter. You should OR one of these values to your load_flags when calling FT_Load_Glyph.

-

Note that a font's native hinters may ignore the hinting algorithm you have specified (e.g., the TrueType bytecode interpreter). You can set FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used.

-

values

- - - - - - - -
FT_LOAD_TARGET_NORMAL -

The default hinting algorithm, optimized for standard gray-level rendering. For monochrome output, use FT_LOAD_TARGET_MONO instead.

-
FT_LOAD_TARGET_LIGHT -

A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by FreeType's new CFF engine or Microsoft's ClearType font renderer. This preserves inter-glyph spacing in horizontal text. The snapping is done either by the native font driver, if the driver itself and the font support it, or by the auto-hinter.

-

Advance widths are rounded to integer values; however, using the lsb_delta and rsb_delta fields of FT_GlyphSlotRec, it is possible to get fractional advance widths for subpixel positioning (which is recommended to use).

-

If configuration option AF_CONFIG_OPTION_TT_SIZE_METRICS is active, TrueType-like metrics are used to make this mode behave similarly as in unpatched FreeType versions between 2.4.6 and 2.7.1 (inclusive).

-
FT_LOAD_TARGET_MONO -

Strong hinting algorithm that should only be used for monochrome output. The result is probably unpleasant if the glyph is rendered in non-monochrome modes.

-

Note that for outline fonts only the TrueType font driver has proper monochrome hinting support, provided the TTFs contain hints for B/W rendering (which most fonts no longer provide). If these conditions are not met it is very likely that you get ugly results at smaller sizes.

-
FT_LOAD_TARGET_LCD -

A variant of FT_LOAD_TARGET_LIGHT optimized for horizontally decimated LCD displays.

-
FT_LOAD_TARGET_LCD_V -

A variant of FT_LOAD_TARGET_NORMAL optimized for vertically decimated LCD displays.

-
- -

note

- -

You should use only one of the FT_LOAD_TARGET_XXX values in your load_flags. They can't be ORed.

-

If FT_LOAD_RENDER is also set, the glyph is rendered in the corresponding mode (i.e., the mode that matches the used algorithm best). An exception is FT_LOAD_TARGET_MONO since it implies FT_LOAD_MONOCHROME.

-

You can use a hinting algorithm that doesn't correspond to the same rendering mode. As an example, it is possible to use the ‘light’ hinting algorithm and have the results rendered in horizontal LCD pixel mode, with code like -

  FT_Load_Glyph( face, glyph_index,
-                 load_flags | FT_LOAD_TARGET_LIGHT );
-
-  FT_Render_Glyph( face->glyph, FT_RENDER_MODE_LCD );
-

-

In general, you should stick with one rendering mode. For example, switching between FT_LOAD_TARGET_NORMAL and FT_LOAD_TARGET_MONO enforces a lot of recomputation for TrueType fonts, which is slow. Another reason is caching: Selecting a different mode usually causes changes in both the outlines and the rasterized bitmaps; it is thus necessary to empty the cache after a mode switch to avoid false hits.

-
- -

FT_SUBGLYPH_FLAG_XXX

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

- - -

A list of constants describing subglyphs. Please refer to the ‘glyf’ table description in the OpenType specification for the meaning of the various flags (which get synthesized for non-OpenType subglyphs).

-

https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#composite-glyph-description

-

values

- - - - - - - - - -
FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS - -
FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES - -
FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID - -
FT_SUBGLYPH_FLAG_SCALE - -
FT_SUBGLYPH_FLAG_XY_SCALE - -
FT_SUBGLYPH_FLAG_2X2 - -
FT_SUBGLYPH_FLAG_USE_MY_METRICS - -
- -
- -

FT_FSTYPE_XXX

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

- - -

A list of bit flags used in the fsType field of the OS/2 table in a TrueType or OpenType font and the FSType entry in a PostScript font. These bit flags are returned by FT_Get_FSType_Flags; they inform client applications of embedding and subsetting restrictions associated with a font.

-

See https://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/FontPolicies.pdf for more details.

-

values

- - - - - - - - -
FT_FSTYPE_INSTALLABLE_EMBEDDING -

Fonts with no fsType bit set may be embedded and permanently installed on the remote system by an application.

-
FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING -

Fonts that have only this bit set must not be modified, embedded or exchanged in any manner without first obtaining permission of the font software copyright owner.

-
FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING -

The font may be embedded and temporarily loaded on the remote system. Documents containing Preview & Print fonts must be opened ‘read-only’; no edits can be applied to the document.

-
FT_FSTYPE_EDITABLE_EMBEDDING -

The font may be embedded but must only be installed temporarily on other systems. In contrast to Preview & Print fonts, documents containing editable fonts may be opened for reading, editing is permitted, and changes may be saved.

-
FT_FSTYPE_NO_SUBSETTING -

The font may not be subsetted prior to embedding.

-
FT_FSTYPE_BITMAP_EMBEDDING_ONLY -

Only bitmaps contained in the font may be embedded; no outline data may be embedded. If there are no bitmaps available in the font, then the font is unembeddable.

-
- -

note

- -

The flags are ORed together, thus more than a single value can be returned.

-

While the fsType flags can indicate that a font may be embedded, a license with the font vendor may be separately required to use the font in this way.

-
- -

FT_HAS_FAST_GLYPHS

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FT_HAS_FAST_GLYPHS( face )  0
-
- -

Deprecated.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-basic_types.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-basic_types.html deleted file mode 100644 index fe49d583a..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-basic_types.html +++ /dev/null @@ -1,2299 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Basic Data Types - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Core API » Basic Data Types

-
-

Basic Data Types

-

Synopsis

-

This section contains the basic data types defined by FreeType 2, ranging from simple scalar types to bitmap descriptors. More font-specific structures are defined in a different section.

-

FT_Byte

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef unsigned char  FT_Byte;
-
- -

A simple typedef for the unsigned char type.

-
- -

FT_Bytes

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef const FT_Byte*  FT_Bytes;
-
- -

A typedef for constant memory areas.

-
- -

FT_Char

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef signed char  FT_Char;
-
- -

A simple typedef for the signed char type.

-
- -

FT_Int

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef signed int  FT_Int;
-
- -

A typedef for the int type.

-
- -

FT_UInt

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef unsigned int  FT_UInt;
-
- -

A typedef for the unsigned int type.

-
- -

FT_Int16

-
  typedef signed short  FT_Int16;
-
- -

A typedef for a 16bit signed integer type.

-
- -

FT_UInt16

-
  typedef unsigned short  FT_UInt16;
-
- -

A typedef for a 16bit unsigned integer type.

-
- -

FT_Int32

-
  typedef signed XXX  FT_Int32;
-
- -

A typedef for a 32bit signed integer type. The size depends on the configuration.

-
- -

FT_UInt32

-
  typedef unsigned XXX  FT_UInt32;
-
- -
- -

FT_Int64

-
  typedef signed XXX  FT_Int64;
-
- -
- -

FT_UInt64

-
  typedef unsigned XXX  FT_UInt64;
-
- -
- -

FT_Short

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef signed short  FT_Short;
-
- -

A typedef for signed short.

-
- -

FT_UShort

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef unsigned short  FT_UShort;
-
- -

A typedef for unsigned short.

-
- -

FT_Long

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef signed long  FT_Long;
-
- -

A typedef for signed long.

-
- -

FT_ULong

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef unsigned long  FT_ULong;
-
- -

A typedef for unsigned long.

-
- -

FT_Bool

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef unsigned char  FT_Bool;
-
- -

A typedef of unsigned char, used for simple booleans. As usual, values 1 and 0 represent true and false, respectively.

-
- -

FT_Offset

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef size_t  FT_Offset;
-
- -

This is equivalent to the ANSI C size_t type, i.e., the largest unsigned integer type used to express a file size or position, or a memory block size.

-
- -

FT_PtrDist

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef ft_ptrdiff_t  FT_PtrDist;
-
- -

This is equivalent to the ANSI C ptrdiff_t type, i.e., the largest signed integer type used to express the distance between two pointers.

-
- -

FT_String

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef char  FT_String;
-
- -

A simple typedef for the char type, usually used for strings.

-
- -

FT_Tag

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef FT_UInt32  FT_Tag;
-
- -

A typedef for 32-bit tags (as used in the SFNT format).

-
- -

FT_Error

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef int  FT_Error;
-
- -

The FreeType error code type. A value of 0 is always interpreted as a successful operation.

-
- -

FT_Fixed

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef signed long  FT_Fixed;
-
- -

This type is used to store 16.16 fixed-point values, like scaling values or matrix coefficients.

-
- -

FT_Pointer

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef void*  FT_Pointer;
-
- -

A simple typedef for a typeless pointer.

-
- -

FT_Pos

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef signed long  FT_Pos;
-
- -

The type FT_Pos is used to store vectorial coordinates. Depending on the context, these can represent distances in integer font units, or 16.16, or 26.6 fixed-point pixel coordinates.

-
- -

FT_Vector

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef struct  FT_Vector_
-  {
-    FT_Pos  x;
-    FT_Pos  y;
-
-  } FT_Vector;
-
- -

A simple structure used to store a 2D vector; coordinates are of the FT_Pos type.

-

fields

- - - - -
x -

The horizontal coordinate.

-
y -

The vertical coordinate.

-
- -
- -

FT_BBox

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef struct  FT_BBox_
-  {
-    FT_Pos  xMin, yMin;
-    FT_Pos  xMax, yMax;
-
-  } FT_BBox;
-
- -

A structure used to hold an outline's bounding box, i.e., the coordinates of its extrema in the horizontal and vertical directions.

-

fields

- - - - - - -
xMin -

The horizontal minimum (left-most).

-
yMin -

The vertical minimum (bottom-most).

-
xMax -

The horizontal maximum (right-most).

-
yMax -

The vertical maximum (top-most).

-
- -

note

- -

The bounding box is specified with the coordinates of the lower left and the upper right corner. In PostScript, those values are often called (llx,lly) and (urx,ury), respectively.

-

If yMin is negative, this value gives the glyph's descender. Otherwise, the glyph doesn't descend below the baseline. Similarly, if ymax is positive, this value gives the glyph's ascender.

-

xMin gives the horizontal distance from the glyph's origin to the left edge of the glyph's bounding box. If xMin is negative, the glyph extends to the left of the origin.

-
- -

FT_Matrix

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef struct  FT_Matrix_
-  {
-    FT_Fixed  xx, xy;
-    FT_Fixed  yx, yy;
-
-  } FT_Matrix;
-
- -

A simple structure used to store a 2x2 matrix. Coefficients are in 16.16 fixed-point format. The computation performed is: -

  x' = x*xx + y*xy
-  y' = x*yx + y*yy
-

-

fields

- - - - - - -
xx -

Matrix coefficient.

-
xy -

Matrix coefficient.

-
yx -

Matrix coefficient.

-
yy -

Matrix coefficient.

-
- -
- -

FT_FWord

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef signed short  FT_FWord;   /* distance in FUnits */
-
- -

A signed 16-bit integer used to store a distance in original font units.

-
- -

FT_UFWord

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef unsigned short  FT_UFWord;  /* unsigned distance */
-
- -

An unsigned 16-bit integer used to store a distance in original font units.

-
- -

FT_F2Dot14

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef signed short  FT_F2Dot14;
-
- -

A signed 2.14 fixed-point type used for unit vectors.

-
- -

FT_UnitVector

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef struct  FT_UnitVector_
-  {
-    FT_F2Dot14  x;
-    FT_F2Dot14  y;
-
-  } FT_UnitVector;
-
- -

A simple structure used to store a 2D vector unit vector. Uses FT_F2Dot14 types.

-

fields

- - - - -
x -

Horizontal coordinate.

-
y -

Vertical coordinate.

-
- -
- -

FT_F26Dot6

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef signed long  FT_F26Dot6;
-
- -

A signed 26.6 fixed-point type used for vectorial pixel coordinates.

-
- -

FT_Data

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef struct  FT_Data_
-  {
-    const FT_Byte*  pointer;
-    FT_Int          length;
-
-  } FT_Data;
-
- -

Read-only binary data represented as a pointer and a length.

-

fields

- - - - -
pointer -

The data.

-
length -

The length of the data in bytes.

-
- -
- -

FT_MAKE_TAG

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
-          (FT_Tag)                        \
-          ( ( (FT_ULong)_x1 << 24 ) |     \
-            ( (FT_ULong)_x2 << 16 ) |     \
-            ( (FT_ULong)_x3 <<  8 ) |     \
-              (FT_ULong)_x4         )
-
- -

This macro converts four-letter tags that are used to label TrueType tables into an unsigned long, to be used within FreeType.

-

note

- -

The produced values must be 32-bit integers. Don't redefine this macro.

-
- -

FT_Generic

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef struct  FT_Generic_
-  {
-    void*                 data;
-    FT_Generic_Finalizer  finalizer;
-
-  } FT_Generic;
-
- -

Client applications often need to associate their own data to a variety of FreeType core objects. For example, a text layout API might want to associate a glyph cache to a given size object.

-

Some FreeType object contains a generic field, of type FT_Generic, which usage is left to client applications and font servers.

-

It can be used to store a pointer to client-specific data, as well as the address of a ‘finalizer’ function, which will be called by FreeType when the object is destroyed (for example, the previous client example would put the address of the glyph cache destructor in the finalizer field).

-

fields

- - - - -
data -

A typeless pointer to any client-specified data. This field is completely ignored by the FreeType library.

-
finalizer -

A pointer to a ‘generic finalizer’ function, which will be called when the object is destroyed. If this field is set to NULL, no code will be called.

-
- -
- -

FT_Generic_Finalizer

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef void  (*FT_Generic_Finalizer)( void*  object );
-
- -

Describe a function used to destroy the ‘client’ data of any FreeType object. See the description of the FT_Generic type for details of usage.

-

input

- -

The address of the FreeType object that is under finalization. Its client data is accessed through its generic field.

-
- -

FT_Bitmap

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef struct  FT_Bitmap_
-  {
-    unsigned int    rows;
-    unsigned int    width;
-    int             pitch;
-    unsigned char*  buffer;
-    unsigned short  num_grays;
-    unsigned char   pixel_mode;
-    unsigned char   palette_mode;
-    void*           palette;
-
-  } FT_Bitmap;
-
- -

A structure used to describe a bitmap or pixmap to the raster. Note that we now manage pixmaps of various depths through the pixel_mode field.

-

fields

- - - - - - - - - - -
rows -

The number of bitmap rows.

-
width -

The number of pixels in bitmap row.

-
pitch -

The pitch's absolute value is the number of bytes taken by one bitmap row, including padding. However, the pitch is positive when the bitmap has a ‘down’ flow, and negative when it has an ‘up’ flow. In all cases, the pitch is an offset to add to a bitmap pointer in order to go down one row.

-

Note that ‘padding’ means the alignment of a bitmap to a byte border, and FreeType functions normally align to the smallest possible integer value.

-

For the B/W rasterizer, pitch is always an even number.

-

To change the pitch of a bitmap (say, to make it a multiple of 4), use FT_Bitmap_Convert. Alternatively, you might use callback functions to directly render to the application's surface; see the file example2.cpp in the tutorial for a demonstration.

-
buffer -

A typeless pointer to the bitmap buffer. This value should be aligned on 32-bit boundaries in most cases.

-
num_grays -

This field is only used with FT_PIXEL_MODE_GRAY; it gives the number of gray levels used in the bitmap.

-
pixel_mode -

The pixel mode, i.e., how pixel bits are stored. See FT_Pixel_Mode for possible values.

-
palette_mode -

This field is intended for paletted pixel modes; it indicates how the palette is stored. Not used currently.

-
palette -

A typeless pointer to the bitmap palette; this field is intended for paletted pixel modes. Not used currently.

-
- -
- -

FT_Pixel_Mode

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef enum  FT_Pixel_Mode_
-  {
-    FT_PIXEL_MODE_NONE = 0,
-    FT_PIXEL_MODE_MONO,
-    FT_PIXEL_MODE_GRAY,
-    FT_PIXEL_MODE_GRAY2,
-    FT_PIXEL_MODE_GRAY4,
-    FT_PIXEL_MODE_LCD,
-    FT_PIXEL_MODE_LCD_V,
-    FT_PIXEL_MODE_BGRA,
-
-    FT_PIXEL_MODE_MAX      /* do not remove */
-
-  } FT_Pixel_Mode;
-
-
-  /* these constants are deprecated; use the corresponding `FT_Pixel_Mode` */
-  /* values instead.                                                       */
-#define ft_pixel_mode_none   FT_PIXEL_MODE_NONE
-#define ft_pixel_mode_mono   FT_PIXEL_MODE_MONO
-#define ft_pixel_mode_grays  FT_PIXEL_MODE_GRAY
-#define ft_pixel_mode_pal2   FT_PIXEL_MODE_GRAY2
-#define ft_pixel_mode_pal4   FT_PIXEL_MODE_GRAY4
-
- -

An enumeration type used to describe the format of pixels in a given bitmap. Note that additional formats may be added in the future.

-

values

- - - - - - - - - - -
FT_PIXEL_MODE_NONE -

Value 0 is reserved.

-
FT_PIXEL_MODE_MONO -

A monochrome bitmap, using 1 bit per pixel. Note that pixels are stored in most-significant order (MSB), which means that the left-most pixel in a byte has value 128.

-
FT_PIXEL_MODE_GRAY -

An 8-bit bitmap, generally used to represent anti-aliased glyph images. Each pixel is stored in one byte. Note that the number of ‘gray’ levels is stored in the num_grays field of the FT_Bitmap structure (it generally is 256).

-
FT_PIXEL_MODE_GRAY2 -

A 2-bit per pixel bitmap, used to represent embedded anti-aliased bitmaps in font files according to the OpenType specification. We haven't found a single font using this format, however.

-
FT_PIXEL_MODE_GRAY4 -

A 4-bit per pixel bitmap, representing embedded anti-aliased bitmaps in font files according to the OpenType specification. We haven't found a single font using this format, however.

-
FT_PIXEL_MODE_LCD -

An 8-bit bitmap, representing RGB or BGR decimated glyph images used for display on LCD displays; the bitmap is three times wider than the original glyph image. See also FT_RENDER_MODE_LCD.

-
FT_PIXEL_MODE_LCD_V -

An 8-bit bitmap, representing RGB or BGR decimated glyph images used for display on rotated LCD displays; the bitmap is three times taller than the original glyph image. See also FT_RENDER_MODE_LCD_V.

-
FT_PIXEL_MODE_BGRA -

[Since 2.5] An image with four 8-bit channels per pixel, representing a color image (such as emoticons) with alpha channel. For each pixel, the format is BGRA, which means, the blue channel comes first in memory. The color channels are pre-multiplied and in the sRGB colorspace. For example, full red at half-translucent opacity will be represented as ‘00,00,80,80’, not ‘00,00,FF,80’. See also FT_LOAD_COLOR.

-
- -
- -

FT_Glyph_Format

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef enum  FT_Glyph_Format_
-  {
-    FT_IMAGE_TAG( FT_GLYPH_FORMAT_NONE, 0, 0, 0, 0 ),
-
-    FT_IMAGE_TAG( FT_GLYPH_FORMAT_COMPOSITE, 'c', 'o', 'm', 'p' ),
-    FT_IMAGE_TAG( FT_GLYPH_FORMAT_BITMAP,    'b', 'i', 't', 's' ),
-    FT_IMAGE_TAG( FT_GLYPH_FORMAT_OUTLINE,   'o', 'u', 't', 'l' ),
-    FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER,   'p', 'l', 'o', 't' )
-
-  } FT_Glyph_Format;
-
-
-  /* these constants are deprecated; use the corresponding */
-  /* `FT_Glyph_Format` values instead.                     */
-#define ft_glyph_format_none       FT_GLYPH_FORMAT_NONE
-#define ft_glyph_format_composite  FT_GLYPH_FORMAT_COMPOSITE
-#define ft_glyph_format_bitmap     FT_GLYPH_FORMAT_BITMAP
-#define ft_glyph_format_outline    FT_GLYPH_FORMAT_OUTLINE
-#define ft_glyph_format_plotter    FT_GLYPH_FORMAT_PLOTTER
-
- -

An enumeration type used to describe the format of a given glyph image. Note that this version of FreeType only supports two image formats, even though future font drivers will be able to register their own format.

-

values

- - - - - - - -
FT_GLYPH_FORMAT_NONE -

The value 0 is reserved.

-
FT_GLYPH_FORMAT_COMPOSITE -

The glyph image is a composite of several other images. This format is only used with FT_LOAD_NO_RECURSE, and is used to report compound glyphs (like accented characters).

-
FT_GLYPH_FORMAT_BITMAP -

The glyph image is a bitmap, and can be described as an FT_Bitmap. You generally need to access the bitmap field of the FT_GlyphSlotRec structure to read it.

-
FT_GLYPH_FORMAT_OUTLINE -

The glyph image is a vectorial outline made of line segments and Bezier arcs; it can be described as an FT_Outline; you generally want to access the outline field of the FT_GlyphSlotRec structure to read it.

-
FT_GLYPH_FORMAT_PLOTTER -

The glyph image is a vectorial path with no inside and outside contours. Some Type 1 fonts, like those in the Hershey family, contain glyphs in this format. These are described as FT_Outline, but FreeType isn't currently capable of rendering them correctly.

-
- -
- -

FT_IMAGE_TAG

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
#ifndef FT_IMAGE_TAG
-#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 )  \
-          value = ( ( (unsigned long)_x1 << 24 ) | \
-                    ( (unsigned long)_x2 << 16 ) | \
-                    ( (unsigned long)_x3 << 8  ) | \
-                      (unsigned long)_x4         )
-#endif /* FT_IMAGE_TAG */
-
- -

This macro converts four-letter tags to an unsigned long type.

-

note

- -

Since many 16-bit compilers don't like 32-bit enumerations, you should redefine this macro in case of problems to something like this: -

  #define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 )  value
-

-

to get a simple enumeration without assigning special numbers.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-bdf_fonts.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-bdf_fonts.html deleted file mode 100644 index 44318130b..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-bdf_fonts.html +++ /dev/null @@ -1,1375 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BDF and PCF Files - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Format-Specific API » BDF and PCF Files

-
-

BDF and PCF Files

-

Synopsis

-

This section contains the declaration of functions specific to BDF and PCF fonts.

-

BDF_PropertyType

-

Defined in FT_BDF_H (freetype/ftbdf.h).

-
  typedef enum  BDF_PropertyType_
-  {
-    BDF_PROPERTY_TYPE_NONE     = 0,
-    BDF_PROPERTY_TYPE_ATOM     = 1,
-    BDF_PROPERTY_TYPE_INTEGER  = 2,
-    BDF_PROPERTY_TYPE_CARDINAL = 3
-
-  } BDF_PropertyType;
-
- -

A list of BDF property types.

-

values

- - - - - - -
BDF_PROPERTY_TYPE_NONE -

Value 0 is used to indicate a missing property.

-
BDF_PROPERTY_TYPE_ATOM -

Property is a string atom.

-
BDF_PROPERTY_TYPE_INTEGER -

Property is a 32-bit signed integer.

-
BDF_PROPERTY_TYPE_CARDINAL -

Property is a 32-bit unsigned integer.

-
- -
- -

BDF_Property

-

Defined in FT_BDF_H (freetype/ftbdf.h).

-
  typedef struct BDF_PropertyRec_*  BDF_Property;
-
- -

A handle to a BDF_PropertyRec structure to model a given BDF/PCF property.

-
- -

BDF_PropertyRec

-

Defined in FT_BDF_H (freetype/ftbdf.h).

-
  typedef struct  BDF_PropertyRec_
-  {
-    BDF_PropertyType  type;
-    union {
-      const char*     atom;
-      FT_Int32        integer;
-      FT_UInt32       cardinal;
-
-    } u;
-
-  } BDF_PropertyRec;
-
- -

This structure models a given BDF/PCF property.

-

fields

- - - - - - -
type -

The property type.

-
u.atom -

The atom string, if type is BDF_PROPERTY_TYPE_ATOM. May be NULL, indicating an empty string.

-
u.integer -

A signed integer, if type is BDF_PROPERTY_TYPE_INTEGER.

-
u.cardinal -

An unsigned integer, if type is BDF_PROPERTY_TYPE_CARDINAL.

-
- -
- -

FT_Get_BDF_Charset_ID

-

Defined in FT_BDF_H (freetype/ftbdf.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_BDF_Charset_ID( FT_Face       face,
-                         const char*  *acharset_encoding,
-                         const char*  *acharset_registry );
-
- -

Retrieve a BDF font character set identity, according to the BDF specification.

-

input

- - - -
face -

A handle to the input face.

-
- -

output

- - - - -
acharset_encoding -

Charset encoding, as a C string, owned by the face.

-
acharset_registry -

Charset registry, as a C string, owned by the face.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function only works with BDF faces, returning an error otherwise.

-
- -

FT_Get_BDF_Property

-

Defined in FT_BDF_H (freetype/ftbdf.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_BDF_Property( FT_Face           face,
-                       const char*       prop_name,
-                       BDF_PropertyRec  *aproperty );
-
- -

Retrieve a BDF property from a BDF or PCF font file.

-

input

- - - - -
face -

A handle to the input face.

-
name -

The property name.

-
- -

output

- - - -
aproperty -

The property.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function works with BDF and PCF fonts. It returns an error otherwise. It also returns an error if the property is not in the font.

-

A ‘property’ is a either key-value pair within the STARTPROPERTIES ... ENDPROPERTIES block of a BDF font or a key-value pair from the info->props array within a FontRec structure of a PCF font.

-

Integer properties are always stored as ‘signed’ within PCF fonts; consequently, BDF_PROPERTY_TYPE_CARDINAL is a possible return value for BDF fonts only.

-

In case of error, aproperty->type is always set to BDF_PROPERTY_TYPE_NONE.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-bitmap_handling.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-bitmap_handling.html deleted file mode 100644 index 166bc2b57..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-bitmap_handling.html +++ /dev/null @@ -1,1504 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Bitmap Handling - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Support API » Bitmap Handling

-
-

Bitmap Handling

-

Synopsis

-

This section contains functions for handling FT_Bitmap objects, automatically adjusting the target's bitmap buffer size as needed.

-

Note that none of the functions changes the bitmap's ‘flow’ (as indicated by the sign of the pitch field in FT_Bitmap).

-

To set the flow, assign an appropriate positive or negative value to the pitch field of the target FT_Bitmap object after calling FT_Bitmap_Init but before calling any of the other functions described here.

-

FT_Bitmap_Init

-

Defined in FT_BITMAP_H (freetype/ftbitmap.h).

-
  FT_EXPORT( void )
-  FT_Bitmap_Init( FT_Bitmap  *abitmap );
-
-  /* deprecated */
-  FT_EXPORT( void )
-  FT_Bitmap_New( FT_Bitmap  *abitmap );
-
- -

Initialize a pointer to an FT_Bitmap structure.

-

inout

- - - -
abitmap -

A pointer to the bitmap structure.

-
- -

note

- -

A deprecated name for the same function is FT_Bitmap_New.

-
- -

FT_Bitmap_Copy

-

Defined in FT_BITMAP_H (freetype/ftbitmap.h).

-
  FT_EXPORT( FT_Error )
-  FT_Bitmap_Copy( FT_Library        library,
-                  const FT_Bitmap  *source,
-                  FT_Bitmap        *target );
-
- -

Copy a bitmap into another one.

-

input

- - - - -
library -

A handle to a library object.

-
source -

A handle to the source bitmap.

-
- -

output

- - - -
target -

A handle to the target bitmap.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

source->buffer and target->buffer must neither be equal nor overlap.

-
- -

FT_Bitmap_Embolden

-

Defined in FT_BITMAP_H (freetype/ftbitmap.h).

-
  FT_EXPORT( FT_Error )
-  FT_Bitmap_Embolden( FT_Library  library,
-                      FT_Bitmap*  bitmap,
-                      FT_Pos      xStrength,
-                      FT_Pos      yStrength );
-
- -

Embolden a bitmap. The new bitmap will be about xStrength pixels wider and yStrength pixels higher. The left and bottom borders are kept unchanged.

-

input

- - - - - -
library -

A handle to a library object.

-
xStrength -

How strong the glyph is emboldened horizontally. Expressed in 26.6 pixel format.

-
yStrength -

How strong the glyph is emboldened vertically. Expressed in 26.6 pixel format.

-
- -

inout

- - - -
bitmap -

A handle to the target bitmap.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The current implementation restricts xStrength to be less than or equal to 8 if bitmap is of pixel_mode FT_PIXEL_MODE_MONO.

-

If you want to embolden the bitmap owned by a FT_GlyphSlotRec, you should call FT_GlyphSlot_Own_Bitmap on the slot first.

-

Bitmaps in FT_PIXEL_MODE_GRAY2 and FT_PIXEL_MODE_GRAY@ format are converted to FT_PIXEL_MODE_GRAY format (i.e., 8bpp).

-
- -

FT_Bitmap_Convert

-

Defined in FT_BITMAP_H (freetype/ftbitmap.h).

-
  FT_EXPORT( FT_Error )
-  FT_Bitmap_Convert( FT_Library        library,
-                     const FT_Bitmap  *source,
-                     FT_Bitmap        *target,
-                     FT_Int            alignment );
-
- -

Convert a bitmap object with depth 1bpp, 2bpp, 4bpp, 8bpp or 32bpp to a bitmap object with depth 8bpp, making the number of used bytes per line (a.k.a. the ‘pitch’) a multiple of alignment.

-

input

- - - - - -
library -

A handle to a library object.

-
source -

The source bitmap.

-
alignment -

The pitch of the bitmap is a multiple of this argument. Common values are 1, 2, or 4.

-
- -

output

- - - -
target -

The target bitmap.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

It is possible to call FT_Bitmap_Convert multiple times without calling FT_Bitmap_Done (the memory is simply reallocated).

-

Use FT_Bitmap_Done to finally remove the bitmap object.

-

The library argument is taken to have access to FreeType's memory handling functions.

-

source->buffer and target->buffer must neither be equal nor overlap.

-
- -

FT_Bitmap_Blend

-

Defined in FT_BITMAP_H (freetype/ftbitmap.h).

-
  FT_EXPORT( FT_Error )
-  FT_Bitmap_Blend( FT_Library         library,
-                   const FT_Bitmap*   source,
-                   const FT_Vector    source_offset,
-                   FT_Bitmap*         target,
-                   FT_Vector         *atarget_offset,
-                   FT_Color           color );
-
- -

Blend a bitmap onto another bitmap, using a given color.

-

input

- - - - - - -
library -

A handle to a library object.

-
source -

The source bitmap, which can have any FT_Pixel_Mode format.

-
source_offset -

The offset vector to the upper left corner of the source bitmap in 26.6 pixel format. It should represent an integer offset; the function will set the lowest six bits to zero to enforce that.

-
color -

The color used to draw source onto target.

-
- -

inout

- - - - -
target -

A handle to an FT_Bitmap object. It should be either initialized as empty with a call to FT_Bitmap_Init, or it should be of type FT_PIXEL_MODE_BGRA.

-
atarget_offset -

The offset vector to the upper left corner of the target bitmap in 26.6 pixel format. It should represent an integer offset; the function will set the lowest six bits to zero to enforce that.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function doesn't perform clipping.

-

The bitmap in target gets allocated or reallocated as needed; the vector atarget_offset is updated accordingly.

-

In case of allocation or reallocation, the bitmap's pitch is set to 4 * width. Both source and target must have the same bitmap flow (as indicated by the sign of the pitch field).

-

source->buffer and target->buffer must neither be equal nor overlap.

-

since

- -

2.10

-
- -

FT_GlyphSlot_Own_Bitmap

-

Defined in FT_BITMAP_H (freetype/ftbitmap.h).

-
  FT_EXPORT( FT_Error )
-  FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot  slot );
-
- -

Make sure that a glyph slot owns slot->bitmap.

-

input

- - - -
slot -

The glyph slot.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function is to be used in combination with FT_Bitmap_Embolden.

-
- -

FT_Bitmap_Done

-

Defined in FT_BITMAP_H (freetype/ftbitmap.h).

-
  FT_EXPORT( FT_Error )
-  FT_Bitmap_Done( FT_Library  library,
-                  FT_Bitmap  *bitmap );
-
- -

Destroy a bitmap object initialized with FT_Bitmap_Init.

-

input

- - - - -
library -

A handle to a library object.

-
bitmap -

The bitmap object to be freed.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The library argument is taken to have access to FreeType's memory handling functions.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-bzip2.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-bzip2.html deleted file mode 100644 index 5b7d1b262..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-bzip2.html +++ /dev/null @@ -1,1200 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BZIP2 Streams - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Support API » BZIP2 Streams

-
-

BZIP2 Streams

-

Synopsis

-

In certain builds of the library, bzip2 compression recognition is automatically handled when calling FT_New_Face or FT_Open_Face. This means that if no font driver is capable of handling the raw compressed file, the library will try to open a bzip2 compressed stream from it and re-open the face with it.

-

The stream implementation is very basic and resets the decompression process each time seeking backwards is needed within the stream, which significantly undermines the performance.

-

This section contains the declaration of Bzip2-specific functions.

-

FT_Stream_OpenBzip2

-

Defined in FT_BZIP2_H (freetype/ftbzip2.h).

-
  FT_EXPORT( FT_Error )
-  FT_Stream_OpenBzip2( FT_Stream  stream,
-                       FT_Stream  source );
-
- -

Open a new stream to parse bzip2-compressed font files. This is mainly used to support the compressed *.pcf.bz2 fonts that come with XFree86.

-

input

- - - - -
stream -

The target embedding stream.

-
source -

The source stream.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The source stream must be opened before calling this function.

-

Calling the internal function FT_Stream_Close on the new stream will not call FT_Stream_Close on the source stream. None of the stream objects will be released to the heap.

-

This function may return FT_Err_Unimplemented_Feature if your build of FreeType was not compiled with bzip2 support.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-cache_subsystem.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-cache_subsystem.html deleted file mode 100644 index dd55a5d60..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-cache_subsystem.html +++ /dev/null @@ -1,2344 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cache Sub-System - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Cache Sub-System » Cache Sub-System

-
-

Cache Sub-System

-

Synopsis

-

This section describes the FreeType 2 cache sub-system, which is used to limit the number of concurrently opened FT_Face and FT_Size objects, as well as caching information like character maps and glyph images while limiting their maximum memory usage.

-

Note that all types and functions begin with the FTC_ prefix.

-

The cache is highly portable and thus doesn't know anything about the fonts installed on your system, or how to access them. This implies the following scheme:

-

First, available or installed font faces are uniquely identified by FTC_FaceID values, provided to the cache by the client. Note that the cache only stores and compares these values, and doesn't try to interpret them in any way.

-

Second, the cache calls, only when needed, a client-provided function to convert an FTC_FaceID into a new FT_Face object. The latter is then completely managed by the cache, including its termination through FT_Done_Face. To monitor termination of face objects, the finalizer callback in the generic field of the FT_Face object can be used, which might also be used to store the FTC_FaceID of the face.

-

Clients are free to map face IDs to anything else. The most simple usage is to associate them to a (pathname,face_index) pair that is used to call FT_New_Face. However, more complex schemes are also possible.

-

Note that for the cache to work correctly, the face ID values must be persistent, which means that the contents they point to should not change at runtime, or that their value should not become invalid.

-

If this is unavoidable (e.g., when a font is uninstalled at runtime), you should call FTC_Manager_RemoveFaceID as soon as possible, to let the cache get rid of any references to the old FTC_FaceID it may keep internally. Failure to do so will lead to incorrect behaviour or even crashes.

-

To use the cache, start with calling FTC_Manager_New to create a new FTC_Manager object, which models a single cache instance. You can then look up FT_Face and FT_Size objects with FTC_Manager_LookupFace and FTC_Manager_LookupSize, respectively.

-

If you want to use the charmap caching, call FTC_CMapCache_New, then later use FTC_CMapCache_Lookup to perform the equivalent of FT_Get_Char_Index, only much faster.

-

If you want to use the FT_Glyph caching, call FTC_ImageCache, then later use FTC_ImageCache_Lookup to retrieve the corresponding FT_Glyph objects from the cache.

-

If you need lots of small bitmaps, it is much more memory efficient to call FTC_SBitCache_New followed by FTC_SBitCache_Lookup. This returns FTC_SBitRec structures, which are used to store small bitmaps directly. (A small bitmap is one whose metrics and dimensions all fit into 8-bit integers).

-

We hope to also provide a kerning cache in the near future.

-

FTC_Manager

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  typedef struct FTC_ManagerRec_*  FTC_Manager;
-
- -

This object corresponds to one instance of the cache-subsystem. It is used to cache one or more FT_Face objects, along with corresponding FT_Size objects.

-

The manager intentionally limits the total number of opened FT_Face and FT_Size objects to control memory usage. See the max_faces and max_sizes parameters of FTC_Manager_New.

-

The manager is also used to cache ‘nodes’ of various types while limiting their total memory usage.

-

All limitations are enforced by keeping lists of managed objects in most-recently-used order, and flushing old nodes to make room for new ones.

-
- -

FTC_FaceID

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  typedef FT_Pointer  FTC_FaceID;
-
- -

An opaque pointer type that is used to identity face objects. The contents of such objects is application-dependent.

-

These pointers are typically used to point to a user-defined structure containing a font file path, and face index.

-

note

- -

Never use NULL as a valid FTC_FaceID.

-

Face IDs are passed by the client to the cache manager that calls, when needed, the FTC_Face_Requester to translate them into new FT_Face objects.

-

If the content of a given face ID changes at runtime, or if the value becomes invalid (e.g., when uninstalling a font), you should immediately call FTC_Manager_RemoveFaceID before any other cache function.

-

Failure to do so will result in incorrect behaviour or even memory leaks and crashes.

-
- -

FTC_Face_Requester

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  typedef FT_Error
-  (*FTC_Face_Requester)( FTC_FaceID  face_id,
-                         FT_Library  library,
-                         FT_Pointer  req_data,
-                         FT_Face*    aface );
-
- -

A callback function provided by client applications. It is used by the cache manager to translate a given FTC_FaceID into a new valid FT_Face object, on demand.

-

input

- - - - - -
face_id -

The face ID to resolve.

-
library -

A handle to a FreeType library object.

-
req_data -

Application-provided request data (see note below).

-
- -

output

- - - -
aface -

A new FT_Face handle.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The third parameter req_data is the same as the one passed by the client when FTC_Manager_New is called.

-

The face requester should not perform funny things on the returned face object, like creating a new FT_Size for it, or setting a transformation through FT_Set_Transform!

-
- -

FTC_Manager_New

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  FT_EXPORT( FT_Error )
-  FTC_Manager_New( FT_Library          library,
-                   FT_UInt             max_faces,
-                   FT_UInt             max_sizes,
-                   FT_ULong            max_bytes,
-                   FTC_Face_Requester  requester,
-                   FT_Pointer          req_data,
-                   FTC_Manager        *amanager );
-
- -

Create a new cache manager.

-

input

- - - - - - - - -
library -

The parent FreeType library handle to use.

-
max_faces -

Maximum number of opened FT_Face objects managed by this cache instance. Use 0 for defaults.

-
max_sizes -

Maximum number of opened FT_Size objects managed by this cache instance. Use 0 for defaults.

-
max_bytes -

Maximum number of bytes to use for cached data nodes. Use 0 for defaults. Note that this value does not account for managed FT_Face and FT_Size objects.

-
requester -

An application-provided callback used to translate face IDs into real FT_Face objects.

-
req_data -

A generic pointer that is passed to the requester each time it is called (see FTC_Face_Requester).

-
- -

output

- - - -
amanager -

A handle to a new manager object. 0 in case of failure.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FTC_Manager_Reset

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  FT_EXPORT( void )
-  FTC_Manager_Reset( FTC_Manager  manager );
-
- -

Empty a given cache manager. This simply gets rid of all the currently cached FT_Face and FT_Size objects within the manager.

-

inout

- - - -
manager -

A handle to the manager.

-
- -
- -

FTC_Manager_Done

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  FT_EXPORT( void )
-  FTC_Manager_Done( FTC_Manager  manager );
-
- -

Destroy a given manager after emptying it.

-

input

- - - -
manager -

A handle to the target cache manager object.

-
- -
- -

FTC_Manager_LookupFace

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  FT_EXPORT( FT_Error )
-  FTC_Manager_LookupFace( FTC_Manager  manager,
-                          FTC_FaceID   face_id,
-                          FT_Face     *aface );
-
- -

Retrieve the FT_Face object that corresponds to a given face ID through a cache manager.

-

input

- - - - -
manager -

A handle to the cache manager.

-
face_id -

The ID of the face object.

-
- -

output

- - - -
aface -

A handle to the face object.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The returned FT_Face object is always owned by the manager. You should never try to discard it yourself.

-

The FT_Face object doesn't necessarily have a current size object (i.e., face->size can be 0). If you need a specific ‘font size’, use FTC_Manager_LookupSize instead.

-

Never change the face's transformation matrix (i.e., never call the FT_Set_Transform function) on a returned face! If you need to transform glyphs, do it yourself after glyph loading.

-

When you perform a lookup, out-of-memory errors are detected within the lookup and force incremental flushes of the cache until enough memory is released for the lookup to succeed.

-

If a lookup fails with FT_Err_Out_Of_Memory the cache has already been completely flushed, and still no memory was available for the operation.

-
- -

FTC_Manager_LookupSize

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  FT_EXPORT( FT_Error )
-  FTC_Manager_LookupSize( FTC_Manager  manager,
-                          FTC_Scaler   scaler,
-                          FT_Size     *asize );
-
- -

Retrieve the FT_Size object that corresponds to a given FTC_ScalerRec pointer through a cache manager.

-

input

- - - - -
manager -

A handle to the cache manager.

-
scaler -

A scaler handle.

-
- -

output

- - - -
asize -

A handle to the size object.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The returned FT_Size object is always owned by the manager. You should never try to discard it by yourself.

-

You can access the parent FT_Face object simply as size->face if you need it. Note that this object is also owned by the manager.

-

note

- -

When you perform a lookup, out-of-memory errors are detected within the lookup and force incremental flushes of the cache until enough memory is released for the lookup to succeed.

-

If a lookup fails with FT_Err_Out_Of_Memory the cache has already been completely flushed, and still no memory is available for the operation.

-
- -

FTC_Manager_RemoveFaceID

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  FT_EXPORT( void )
-  FTC_Manager_RemoveFaceID( FTC_Manager  manager,
-                            FTC_FaceID   face_id );
-
- -

A special function used to indicate to the cache manager that a given FTC_FaceID is no longer valid, either because its content changed, or because it was deallocated or uninstalled.

-

input

- - - - -
manager -

The cache manager handle.

-
face_id -

The FTC_FaceID to be removed.

-
- -

note

- -

This function flushes all nodes from the cache corresponding to this face_id, with the exception of nodes with a non-null reference count.

-

Such nodes are however modified internally so as to never appear in later lookups with the same face_id value, and to be immediately destroyed when released by all their users.

-
- -

FTC_Node

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  typedef struct FTC_NodeRec_*  FTC_Node;
-
- -

An opaque handle to a cache node object. Each cache node is reference-counted. A node with a count of 0 might be flushed out of a full cache whenever a lookup request is performed.

-

If you look up nodes, you have the ability to ‘acquire’ them, i.e., to increment their reference count. This will prevent the node from being flushed out of the cache until you explicitly ‘release’ it (see FTC_Node_Unref).

-

See also FTC_SBitCache_Lookup and FTC_ImageCache_Lookup.

-
- -

FTC_Node_Unref

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  FT_EXPORT( void )
-  FTC_Node_Unref( FTC_Node     node,
-                  FTC_Manager  manager );
-
- -

Decrement a cache node's internal reference count. When the count reaches 0, it is not destroyed but becomes eligible for subsequent cache flushes.

-

input

- - - - -
node -

The cache node handle.

-
manager -

The cache manager handle.

-
- -
- -

FTC_ImageCache

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  typedef struct FTC_ImageCacheRec_*  FTC_ImageCache;
-
- -

A handle to a glyph image cache object. They are designed to hold many distinct glyph images while not exceeding a certain memory threshold.

-
- -

FTC_ImageCache_New

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  FT_EXPORT( FT_Error )
-  FTC_ImageCache_New( FTC_Manager      manager,
-                      FTC_ImageCache  *acache );
-
- -

Create a new glyph image cache.

-

input

- - - -
manager -

The parent manager for the image cache.

-
- -

output

- - - -
acache -

A handle to the new glyph image cache object.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FTC_ImageCache_Lookup

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  FT_EXPORT( FT_Error )
-  FTC_ImageCache_Lookup( FTC_ImageCache  cache,
-                         FTC_ImageType   type,
-                         FT_UInt         gindex,
-                         FT_Glyph       *aglyph,
-                         FTC_Node       *anode );
-
- -

Retrieve a given glyph image from a glyph image cache.

-

input

- - - - - -
cache -

A handle to the source glyph image cache.

-
type -

A pointer to a glyph image type descriptor.

-
gindex -

The glyph index to retrieve.

-
- -

output

- - - - -
aglyph -

The corresponding FT_Glyph object. 0 in case of failure.

-
anode -

Used to return the address of the corresponding cache node after incrementing its reference count (see note below).

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The returned glyph is owned and managed by the glyph image cache. Never try to transform or discard it manually! You can however create a copy with FT_Glyph_Copy and modify the new one.

-

If anode is not NULL, it receives the address of the cache node containing the glyph image, after increasing its reference count. This ensures that the node (as well as the FT_Glyph) will always be kept in the cache until you call FTC_Node_Unref to ‘release’ it.

-

If anode is NULL, the cache node is left unchanged, which means that the FT_Glyph could be flushed out of the cache on the next call to one of the caching sub-system APIs. Don't assume that it is persistent!

-
- -

FTC_SBit

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  typedef struct FTC_SBitRec_*  FTC_SBit;
-
- -

A handle to a small bitmap descriptor. See the FTC_SBitRec structure for details.

-
- -

FTC_SBitCache

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  typedef struct FTC_SBitCacheRec_*  FTC_SBitCache;
-
- -

A handle to a small bitmap cache. These are special cache objects used to store small glyph bitmaps (and anti-aliased pixmaps) in a much more efficient way than the traditional glyph image cache implemented by FTC_ImageCache.

-
- -

FTC_SBitCache_New

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  FT_EXPORT( FT_Error )
-  FTC_SBitCache_New( FTC_Manager     manager,
-                     FTC_SBitCache  *acache );
-
- -

Create a new cache to store small glyph bitmaps.

-

input

- - - -
manager -

A handle to the source cache manager.

-
- -

output

- - - -
acache -

A handle to the new sbit cache. NULL in case of error.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FTC_SBitCache_Lookup

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  FT_EXPORT( FT_Error )
-  FTC_SBitCache_Lookup( FTC_SBitCache    cache,
-                        FTC_ImageType    type,
-                        FT_UInt          gindex,
-                        FTC_SBit        *sbit,
-                        FTC_Node        *anode );
-
- -

Look up a given small glyph bitmap in a given sbit cache and ‘lock’ it to prevent its flushing from the cache until needed.

-

input

- - - - - -
cache -

A handle to the source sbit cache.

-
type -

A pointer to the glyph image type descriptor.

-
gindex -

The glyph index.

-
- -

output

- - - - -
sbit -

A handle to a small bitmap descriptor.

-
anode -

Used to return the address of the corresponding cache node after incrementing its reference count (see note below).

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The small bitmap descriptor and its bit buffer are owned by the cache and should never be freed by the application. They might as well disappear from memory on the next cache lookup, so don't treat them as persistent data.

-

The descriptor's buffer field is set to 0 to indicate a missing glyph bitmap.

-

If anode is not NULL, it receives the address of the cache node containing the bitmap, after increasing its reference count. This ensures that the node (as well as the image) will always be kept in the cache until you call FTC_Node_Unref to ‘release’ it.

-

If anode is NULL, the cache node is left unchanged, which means that the bitmap could be flushed out of the cache on the next call to one of the caching sub-system APIs. Don't assume that it is persistent!

-
- -

FTC_CMapCache

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  typedef struct FTC_CMapCacheRec_*  FTC_CMapCache;
-
- -

An opaque handle used to model a charmap cache. This cache is to hold character codes -> glyph indices mappings.

-
- -

FTC_CMapCache_New

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  FT_EXPORT( FT_Error )
-  FTC_CMapCache_New( FTC_Manager     manager,
-                     FTC_CMapCache  *acache );
-
- -

Create a new charmap cache.

-

input

- - - -
manager -

A handle to the cache manager.

-
- -

output

- - - -
acache -

A new cache handle. NULL in case of error.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

Like all other caches, this one will be destroyed with the cache manager.

-
- -

FTC_CMapCache_Lookup

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  FT_EXPORT( FT_UInt )
-  FTC_CMapCache_Lookup( FTC_CMapCache  cache,
-                        FTC_FaceID     face_id,
-                        FT_Int         cmap_index,
-                        FT_UInt32      char_code );
-
- -

Translate a character code into a glyph index, using the charmap cache.

-

input

- - - - - - -
cache -

A charmap cache handle.

-
face_id -

The source face ID.

-
cmap_index -

The index of the charmap in the source face. Any negative value means to use the cache FT_Face's default charmap.

-
char_code -

The character code (in the corresponding charmap).

-
- -

return

- -

Glyph index. 0 means ‘no glyph’.

-
- -

FTC_ScalerRec

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  typedef struct  FTC_ScalerRec_
-  {
-    FTC_FaceID  face_id;
-    FT_UInt     width;
-    FT_UInt     height;
-    FT_Int      pixel;
-    FT_UInt     x_res;
-    FT_UInt     y_res;
-
-  } FTC_ScalerRec;
-
- -

A structure used to describe a given character size in either pixels or points to the cache manager. See FTC_Manager_LookupSize.

-

fields

- - - - - - - - -
face_id -

The source face ID.

-
width -

The character width.

-
height -

The character height.

-
pixel -

A Boolean. If 1, the width and height fields are interpreted as integer pixel character sizes. Otherwise, they are expressed as 1/64th of points.

-
x_res -

Only used when pixel is value 0 to indicate the horizontal resolution in dpi.

-
y_res -

Only used when pixel is value 0 to indicate the vertical resolution in dpi.

-
- -

note

- -

This type is mainly used to retrieve FT_Size objects through the cache manager.

-
- -

FTC_Scaler

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  typedef struct FTC_ScalerRec_*  FTC_Scaler;
-
- -

A handle to an FTC_ScalerRec structure.

-
- -

FTC_ImageTypeRec

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  typedef struct  FTC_ImageTypeRec_
-  {
-    FTC_FaceID  face_id;
-    FT_UInt     width;
-    FT_UInt     height;
-    FT_Int32    flags;
-
-  } FTC_ImageTypeRec;
-
- -

A structure used to model the type of images in a glyph cache.

-

fields

- - - - - - -
face_id -

The face ID.

-
width -

The width in pixels.

-
height -

The height in pixels.

-
flags -

The load flags, as in FT_Load_Glyph.

-
- -
- -

FTC_ImageType

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  typedef struct FTC_ImageTypeRec_*  FTC_ImageType;
-
- -

A handle to an FTC_ImageTypeRec structure.

-
- -

FTC_ImageCache_LookupScaler

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  FT_EXPORT( FT_Error )
-  FTC_ImageCache_LookupScaler( FTC_ImageCache  cache,
-                               FTC_Scaler      scaler,
-                               FT_ULong        load_flags,
-                               FT_UInt         gindex,
-                               FT_Glyph       *aglyph,
-                               FTC_Node       *anode );
-
- -

A variant of FTC_ImageCache_Lookup that uses an FTC_ScalerRec to specify the face ID and its size.

-

input

- - - - - - -
cache -

A handle to the source glyph image cache.

-
scaler -

A pointer to a scaler descriptor.

-
load_flags -

The corresponding load flags.

-
gindex -

The glyph index to retrieve.

-
- -

output

- - - - -
aglyph -

The corresponding FT_Glyph object. 0 in case of failure.

-
anode -

Used to return the address of the corresponding cache node after incrementing its reference count (see note below).

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The returned glyph is owned and managed by the glyph image cache. Never try to transform or discard it manually! You can however create a copy with FT_Glyph_Copy and modify the new one.

-

If anode is not NULL, it receives the address of the cache node containing the glyph image, after increasing its reference count. This ensures that the node (as well as the FT_Glyph) will always be kept in the cache until you call FTC_Node_Unref to ‘release’ it.

-

If anode is NULL, the cache node is left unchanged, which means that the FT_Glyph could be flushed out of the cache on the next call to one of the caching sub-system APIs. Don't assume that it is persistent!

-

Calls to FT_Set_Char_Size and friends have no effect on cached glyphs; you should always use the FreeType cache API instead.

-
- -

FTC_SBitRec

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  typedef struct  FTC_SBitRec_
-  {
-    FT_Byte   width;
-    FT_Byte   height;
-    FT_Char   left;
-    FT_Char   top;
-
-    FT_Byte   format;
-    FT_Byte   max_grays;
-    FT_Short  pitch;
-    FT_Char   xadvance;
-    FT_Char   yadvance;
-
-    FT_Byte*  buffer;
-
-  } FTC_SBitRec;
-
- -

A very compact structure used to describe a small glyph bitmap.

-

fields

- - - - - - - - - - - - -
width -

The bitmap width in pixels.

-
height -

The bitmap height in pixels.

-
left -

The horizontal distance from the pen position to the left bitmap border (a.k.a. ‘left side bearing’, or ‘lsb’).

-
top -

The vertical distance from the pen position (on the baseline) to the upper bitmap border (a.k.a. ‘top side bearing’). The distance is positive for upwards y coordinates.

-
format -

The format of the glyph bitmap (monochrome or gray).

-
max_grays -

Maximum gray level value (in the range 1 to 255).

-
pitch -

The number of bytes per bitmap line. May be positive or negative.

-
xadvance -

The horizontal advance width in pixels.

-
yadvance -

The vertical advance height in pixels.

-
buffer -

A pointer to the bitmap pixels.

-
- -
- -

FTC_SBitCache_LookupScaler

-

Defined in FT_CACHE_H (freetype/ftcache.h).

-
  FT_EXPORT( FT_Error )
-  FTC_SBitCache_LookupScaler( FTC_SBitCache  cache,
-                              FTC_Scaler     scaler,
-                              FT_ULong       load_flags,
-                              FT_UInt        gindex,
-                              FTC_SBit      *sbit,
-                              FTC_Node      *anode );
-
- -

A variant of FTC_SBitCache_Lookup that uses an FTC_ScalerRec to specify the face ID and its size.

-

input

- - - - - - -
cache -

A handle to the source sbit cache.

-
scaler -

A pointer to the scaler descriptor.

-
load_flags -

The corresponding load flags.

-
gindex -

The glyph index.

-
- -

output

- - - - -
sbit -

A handle to a small bitmap descriptor.

-
anode -

Used to return the address of the corresponding cache node after incrementing its reference count (see note below).

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The small bitmap descriptor and its bit buffer are owned by the cache and should never be freed by the application. They might as well disappear from memory on the next cache lookup, so don't treat them as persistent data.

-

The descriptor's buffer field is set to 0 to indicate a missing glyph bitmap.

-

If anode is not NULL, it receives the address of the cache node containing the bitmap, after increasing its reference count. This ensures that the node (as well as the image) will always be kept in the cache until you call FTC_Node_Unref to ‘release’ it.

-

If anode is NULL, the cache node is left unchanged, which means that the bitmap could be flushed out of the cache on the next call to one of the caching sub-system APIs. Don't assume that it is persistent!

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-cff_driver.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-cff_driver.html deleted file mode 100644 index 70487fec6..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-cff_driver.html +++ /dev/null @@ -1,1166 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The CFF driver - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Controlling FreeType Modules » The CFF driver

-
-

The CFF driver

-

Synopsis

-

While FreeType's CFF driver doesn't expose API functions by itself, it is possible to control its behaviour with FT_Property_Set and FT_Property_Get.

-

The CFF driver's module name is ‘cff’.

-

Available properties are hinting-engine, no-stem-darkening, darkening-parameters, and random-seed, as documented in the ‘Driver properties’ section.

-

Hinting and antialiasing principles of the new engine

-

The rasterizer is positioning horizontal features (e.g., ascender height & x-height, or crossbars) on the pixel grid and minimizing the amount of antialiasing applied to them, while placing vertical features (vertical stems) on the pixel grid without hinting, thus representing the stem position and weight accurately. Sometimes the vertical stems may be only partially black. In this context, ‘antialiasing’ means that stems are not positioned exactly on pixel borders, causing a fuzzy appearance.

-

There are two principles behind this approach.

-

1) No hinting in the horizontal direction: Unlike ‘superhinted’ TrueType, which changes glyph widths to accommodate regular inter-glyph spacing, Adobe's approach is ‘faithful to the design’ in representing both the glyph width and the inter-glyph spacing designed for the font. This makes the screen display as close as it can be to the result one would get with infinite resolution, while preserving what is considered the key characteristics of each glyph. Note that the distances between unhinted and grid-fitted positions at small sizes are comparable to kerning values and thus would be noticeable (and distracting) while reading if hinting were applied.

-

One of the reasons to not hint horizontally is antialiasing for LCD screens: The pixel geometry of modern displays supplies three vertical subpixels as the eye moves horizontally across each visible pixel. On devices where we can be certain this characteristic is present a rasterizer can take advantage of the subpixels to add increments of weight. In Western writing systems this turns out to be the more critical direction anyway; the weights and spacing of vertical stems (see above) are central to Armenian, Cyrillic, Greek, and Latin type designs. Even when the rasterizer uses greyscale antialiasing instead of color (a necessary compromise when one doesn't know the screen characteristics), the unhinted vertical features preserve the design's weight and spacing much better than aliased type would.

-

2) Alignment in the vertical direction: Weights and spacing along the y axis are less critical; what is much more important is the visual alignment of related features (like cap-height and x-height). The sense of alignment for these is enhanced by the sharpness of grid-fit edges, while the cruder vertical resolution (full pixels instead of ⅓ pixels) is less of a problem.

-

On the technical side, horizontal alignment zones for ascender, x-height, and other important height values (traditionally called ‘blue zones’) as defined in the font are positioned independently, each being rounded to the nearest pixel edge, taking care of overshoot suppression at small sizes, stem darkening, and scaling.

-

Hstems (this is, hint values defined in the font to help align horizontal features) that fall within a blue zone are said to be ‘captured’ and are aligned to that zone. Uncaptured stems are moved in one of four ways, top edge up or down, bottom edge up or down. Unless there are conflicting hstems, the smallest movement is taken to minimize distortion.

- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-cid_fonts.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-cid_fonts.html deleted file mode 100644 index 72a5c4737..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-cid_fonts.html +++ /dev/null @@ -1,1314 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CID Fonts - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Format-Specific API » CID Fonts

-
-

CID Fonts

-

Synopsis

-

This section contains the declaration of CID-keyed font-specific functions.

-

FT_Get_CID_Registry_Ordering_Supplement

-

Defined in FT_CID_H (freetype/ftcid.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_CID_Registry_Ordering_Supplement( FT_Face       face,
-                                           const char*  *registry,
-                                           const char*  *ordering,
-                                           FT_Int       *supplement );
-
- -

Retrieve the Registry/Ordering/Supplement triple (also known as the "R/O/S") from a CID-keyed font.

-

input

- - - -
face -

A handle to the input face.

-
- -

output

- - - - - -
registry -

The registry, as a C string, owned by the face.

-
ordering -

The ordering, as a C string, owned by the face.

-
supplement -

The supplement.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function only works with CID faces, returning an error otherwise.

-

since

- -

2.3.6

-
- -

FT_Get_CID_Is_Internally_CID_Keyed

-

Defined in FT_CID_H (freetype/ftcid.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_CID_Is_Internally_CID_Keyed( FT_Face   face,
-                                      FT_Bool  *is_cid );
-
- -

Retrieve the type of the input face, CID keyed or not. In contrast to the FT_IS_CID_KEYED macro this function returns successfully also for CID-keyed fonts in an SFNT wrapper.

-

input

- - - -
face -

A handle to the input face.

-
- -

output

- - - -
is_cid -

The type of the face as an FT_Bool.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function only works with CID faces and OpenType fonts, returning an error otherwise.

-

since

- -

2.3.9

-
- -

FT_Get_CID_From_Glyph_Index

-

Defined in FT_CID_H (freetype/ftcid.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_CID_From_Glyph_Index( FT_Face   face,
-                               FT_UInt   glyph_index,
-                               FT_UInt  *cid );
-
- -

Retrieve the CID of the input glyph index.

-

input

- - - - -
face -

A handle to the input face.

-
glyph_index -

The input glyph index.

-
- -

output

- - - -
cid -

The CID as an FT_UInt.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function only works with CID faces and OpenType fonts, returning an error otherwise.

-

since

- -

2.3.9

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-color_management.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-color_management.html deleted file mode 100644 index d5ce4c32a..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-color_management.html +++ /dev/null @@ -1,1457 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Glyph Color Management - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Core API » Glyph Color Management

-
-

Glyph Color Management

-

Synopsis

-

The functions described here allow access and manipulation of color palette entries in OpenType's ‘CPAL’ tables.

-

FT_Color

-

Defined in FT_COLOR_H (freetype/ftcolor.h).

-
  typedef struct  FT_Color_
-  {
-    FT_Byte  blue;
-    FT_Byte  green;
-    FT_Byte  red;
-    FT_Byte  alpha;
-
-  } FT_Color;
-
- -

This structure models a BGRA color value of a ‘CPAL’ palette entry.

-

The used color space is sRGB; the colors are not pre-multiplied, and alpha values must be explicitly set.

-

fields

- - - - - - -
blue -

Blue value.

-
green -

Green value.

-
red -

Red value.

-
alpha -

Alpha value, giving the red, green, and blue color's opacity.

-
- -

since

- -

2.10

-
- -

FT_PALETTE_XXX

-

Defined in FT_COLOR_H (freetype/ftcolor.h).

- - -

A list of bit field constants used in the palette_flags array of the FT_Palette_Data structure to indicate for which background a palette with a given index is usable.

-

values

- - - - -
FT_PALETTE_FOR_LIGHT_BACKGROUND -

The palette is appropriate to use when displaying the font on a light background such as white.

-
FT_PALETTE_FOR_DARK_BACKGROUND -

The palette is appropriate to use when displaying the font on a dark background such as black.

-
- -

since

- -

2.10

-
- -

FT_Palette_Data

-

Defined in FT_COLOR_H (freetype/ftcolor.h).

-
  typedef struct  FT_Palette_Data_ {
-    FT_UShort         num_palettes;
-    const FT_UShort*  palette_name_ids;
-    const FT_UShort*  palette_flags;
-
-    FT_UShort         num_palette_entries;
-    const FT_UShort*  palette_entry_name_ids;
-
-  } FT_Palette_Data;
-
- -

This structure holds the data of the ‘CPAL’ table.

-

fields

- - - - - - - -
num_palettes -

The number of palettes.

-
palette_name_ids -

An optional read-only array of palette name IDs with num_palettes elements, corresponding to entries like ‘dark’ or ‘light’ in the font's ‘name’ table.

-

An empty name ID in the ‘CPAL’ table gets represented as value 0xFFFF.

-

NULL if the font's ‘CPAL’ table doesn't contain appropriate data.

-
palette_flags -

An optional read-only array of palette flags with num_palettes elements. Possible values are an ORed combination of FT_PALETTE_FOR_LIGHT_BACKGROUND and FT_PALETTE_FOR_DARK_BACKGROUND.

-

NULL if the font's ‘CPAL’ table doesn't contain appropriate data.

-
num_palette_entries -

The number of entries in a single palette. All palettes have the same size.

-
palette_entry_name_ids -

An optional read-only array of palette entry name IDs with num_palette_entries. In each palette, entries with the same index have the same function. For example, index 0 might correspond to string ‘outline’ in the font's ‘name’ table to indicate that this palette entry is used for outlines, index 1 might correspond to ‘fill’ to indicate the filling color palette entry, etc.

-

An empty entry name ID in the ‘CPAL’ table gets represented as value 0xFFFF.

-

NULL if the font's ‘CPAL’ table doesn't contain appropriate data.

-
- -

note

- -

Use function FT_Get_Sfnt_Name to map name IDs and entry name IDs to name strings.

-

Use function FT_Palette_Select to get the colors associated with a palette entry.

-

since

- -

2.10

-
- -

FT_Palette_Data_Get

-

Defined in FT_COLOR_H (freetype/ftcolor.h).

-
  FT_EXPORT( FT_Error )
-  FT_Palette_Data_Get( FT_Face           face,
-                       FT_Palette_Data  *apalette );
-
- -

Retrieve the face's color palette data.

-

input

- - - -
face -

The source face handle.

-
- -

output

- - - -
apalette -

A pointer to an FT_Palette_Data structure.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

All arrays in the returned FT_Palette_Data structure are read-only.

-

This function always returns an error if the config macro TT_CONFIG_OPTION_COLOR_LAYERS is not defined in ftoption.h.

-

since

- -

2.10

-
- -

FT_Palette_Select

-

Defined in FT_COLOR_H (freetype/ftcolor.h).

-
  FT_EXPORT( FT_Error )
-  FT_Palette_Select( FT_Face     face,
-                     FT_UShort   palette_index,
-                     FT_Color*  *apalette );
-
- -

This function has two purposes.

-

(1) It activates a palette for rendering color glyphs, and

-

(2) it retrieves all (unmodified) color entries of this palette. This function returns a read-write array, which means that a calling application can modify the palette entries on demand.

-

A corollary of (2) is that calling the function, then modifying some values, then calling the function again with the same arguments resets all color entries to the original ‘CPAL’ values; all user modifications are lost.

-

input

- - - - -
face -

The source face handle.

-
palette_index -

The palette index.

-
- -

output

- - - -
apalette -

An array of color entries for a palette with index palette_index, having num_palette_entries elements (as found in the FT_Palette_Data structure). If apalette is set to NULL, no array gets returned (and no color entries can be modified).

-

In case the font doesn't support color palettes, NULL is returned.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The array pointed to by apalette_entries is owned and managed by FreeType.

-

This function always returns an error if the config macro TT_CONFIG_OPTION_COLOR_LAYERS is not defined in ftoption.h.

-

since

- -

2.10

-
- -

FT_Palette_Set_Foreground_Color

-

Defined in FT_COLOR_H (freetype/ftcolor.h).

-
  FT_EXPORT( FT_Error )
-  FT_Palette_Set_Foreground_Color( FT_Face   face,
-                                   FT_Color  foreground_color );
-
- -

‘COLR’ uses palette index 0xFFFF to indicate a ‘text foreground color’. This function sets this value.

-

input

- - - - -
face -

The source face handle.

-
foreground_color -

An FT_Color structure to define the text foreground color.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

If this function isn't called, the text foreground color is set to white opaque (BGRA value 0xFFFFFFFF) if FT_PALETTE_FOR_DARK_BACKGROUND is present for the current palette, and black opaque (BGRA value 0x000000FF) otherwise, including the case that no palette types are available in the ‘CPAL’ table.

-

This function always returns an error if the config macro TT_CONFIG_OPTION_COLOR_LAYERS is not defined in ftoption.h.

-

since

- -

2.10

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-computations.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-computations.html deleted file mode 100644 index fa2c3a7d1..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-computations.html +++ /dev/null @@ -1,2005 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Computations - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Support API » Computations

-
-

Computations

-

Synopsis

-

This section contains various functions used to perform computations on 16.16 fixed-float numbers or 2d vectors.

-

Attention: Most arithmetic functions take FT_Long as arguments. For historical reasons, FreeType was designed under the assumption that FT_Long is a 32-bit integer; results can thus be undefined if the arguments don't fit into 32 bits.

-

FT_MulDiv

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Long )
-  FT_MulDiv( FT_Long  a,
-             FT_Long  b,
-             FT_Long  c );
-
- -

Compute (a*b)/c with maximum accuracy, using a 64-bit intermediate integer whenever necessary.

-

This function isn't necessarily as fast as some processor-specific operations, but is at least completely portable.

-

input

- - - - - -
a -

The first multiplier.

-
b -

The second multiplier.

-
c -

The divisor.

-
- -

return

- -

The result of (a*b)/c. This function never traps when trying to divide by zero; it simply returns ‘MaxInt’ or ‘MinInt’ depending on the signs of a and b.

-
- -

FT_MulFix

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Long )
-  FT_MulFix( FT_Long  a,
-             FT_Long  b );
-
- -

Compute (a*b)/0x10000 with maximum accuracy. Its main use is to multiply a given value by a 16.16 fixed-point factor.

-

input

- - - - -
a -

The first multiplier.

-
b -

The second multiplier. Use a 16.16 factor here whenever possible (see note below).

-
- -

return

- -

The result of (a*b)/0x10000.

-

note

- -

This function has been optimized for the case where the absolute value of a is less than 2048, and b is a 16.16 scaling factor. As this happens mainly when scaling from notional units to fractional pixels in FreeType, it resulted in noticeable speed improvements between versions 2.x and 1.x.

-

As a conclusion, always try to place a 16.16 factor as the second argument of this function; this can make a great difference.

-
- -

FT_DivFix

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Long )
-  FT_DivFix( FT_Long  a,
-             FT_Long  b );
-
- -

Compute (a*0x10000)/b with maximum accuracy. Its main use is to divide a given value by a 16.16 fixed-point factor.

-

input

- - - - -
a -

The numerator.

-
b -

The denominator. Use a 16.16 factor here.

-
- -

return

- -

The result of (a*0x10000)/b.

-
- -

FT_RoundFix

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Fixed )
-  FT_RoundFix( FT_Fixed  a );
-
- -

Round a 16.16 fixed number.

-

input

- - - -
a -

The number to be rounded.

-
- -

return

- -

a rounded to the nearest 16.16 fixed integer, halfway cases away from zero.

-

note

- -

The function uses wrap-around arithmetic.

-
- -

FT_CeilFix

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Fixed )
-  FT_CeilFix( FT_Fixed  a );
-
- -

Compute the smallest following integer of a 16.16 fixed number.

-

input

- - - -
a -

The number for which the ceiling function is to be computed.

-
- -

return

- -

a rounded towards plus infinity.

-

note

- -

The function uses wrap-around arithmetic.

-
- -

FT_FloorFix

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Fixed )
-  FT_FloorFix( FT_Fixed  a );
-
- -

Compute the largest previous integer of a 16.16 fixed number.

-

input

- - - -
a -

The number for which the floor function is to be computed.

-
- -

return

- -

a rounded towards minus infinity.

-
- -

FT_Vector_Transform

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( void )
-  FT_Vector_Transform( FT_Vector*        vector,
-                       const FT_Matrix*  matrix );
-
- -

Transform a single vector through a 2x2 matrix.

-

inout

- - - -
vector -

The target vector to transform.

-
- -

input

- - - -
matrix -

A pointer to the source 2x2 matrix.

-
- -

note

- -

The result is undefined if either vector or matrix is invalid.

-
- -

FT_Matrix_Multiply

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  FT_EXPORT( void )
-  FT_Matrix_Multiply( const FT_Matrix*  a,
-                      FT_Matrix*        b );
-
- -

Perform the matrix operation b = a*b.

-

input

- - - -
a -

A pointer to matrix a.

-
- -

inout

- - - -
b -

A pointer to matrix b.

-
- -

note

- -

The result is undefined if either a or b is zero.

-

Since the function uses wrap-around arithmetic, results become meaningless if the arguments are very large.

-
- -

FT_Matrix_Invert

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  FT_EXPORT( FT_Error )
-  FT_Matrix_Invert( FT_Matrix*  matrix );
-
- -

Invert a 2x2 matrix. Return an error if it can't be inverted.

-

inout

- - - -
matrix -

A pointer to the target matrix. Remains untouched in case of error.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FT_Angle

-

Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h).

-
  typedef FT_Fixed  FT_Angle;
-
- -

This type is used to model angle values in FreeType. Note that the angle is a 16.16 fixed-point value expressed in degrees.

-
- -

FT_ANGLE_PI

-

Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h).

-
#define FT_ANGLE_PI  ( 180L << 16 )
-
- -

The angle pi expressed in FT_Angle units.

-
- -

FT_ANGLE_2PI

-

Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h).

-
#define FT_ANGLE_2PI  ( FT_ANGLE_PI * 2 )
-
- -

The angle 2*pi expressed in FT_Angle units.

-
- -

FT_ANGLE_PI2

-

Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h).

-
#define FT_ANGLE_PI2  ( FT_ANGLE_PI / 2 )
-
- -

The angle pi/2 expressed in FT_Angle units.

-
- -

FT_ANGLE_PI4

-

Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h).

-
#define FT_ANGLE_PI4  ( FT_ANGLE_PI / 4 )
-
- -

The angle pi/4 expressed in FT_Angle units.

-
- -

FT_Sin

-

Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h).

-
  FT_EXPORT( FT_Fixed )
-  FT_Sin( FT_Angle  angle );
-
- -

Return the sinus of a given angle in fixed-point format.

-

input

- - - -
angle -

The input angle.

-
- -

return

- -

The sinus value.

-

note

- -

If you need both the sinus and cosinus for a given angle, use the function FT_Vector_Unit.

-
- -

FT_Cos

-

Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h).

-
  FT_EXPORT( FT_Fixed )
-  FT_Cos( FT_Angle  angle );
-
- -

Return the cosinus of a given angle in fixed-point format.

-

input

- - - -
angle -

The input angle.

-
- -

return

- -

The cosinus value.

-

note

- -

If you need both the sinus and cosinus for a given angle, use the function FT_Vector_Unit.

-
- -

FT_Tan

-

Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h).

-
  FT_EXPORT( FT_Fixed )
-  FT_Tan( FT_Angle  angle );
-
- -

Return the tangent of a given angle in fixed-point format.

-

input

- - - -
angle -

The input angle.

-
- -

return

- -

The tangent value.

-
- -

FT_Atan2

-

Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h).

-
  FT_EXPORT( FT_Angle )
-  FT_Atan2( FT_Fixed  x,
-            FT_Fixed  y );
-
- -

Return the arc-tangent corresponding to a given vector (x,y) in the 2d plane.

-

input

- - - - -
x -

The horizontal vector coordinate.

-
y -

The vertical vector coordinate.

-
- -

return

- -

The arc-tangent value (i.e. angle).

-
- -

FT_Angle_Diff

-

Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h).

-
  FT_EXPORT( FT_Angle )
-  FT_Angle_Diff( FT_Angle  angle1,
-                 FT_Angle  angle2 );
-
- -

Return the difference between two angles. The result is always constrained to the ]-PI..PI] interval.

-

input

- - - - -
angle1 -

First angle.

-
angle2 -

Second angle.

-
- -

return

- -

Constrained value of angle2-angle1.

-
- -

FT_Vector_Unit

-

Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h).

-
  FT_EXPORT( void )
-  FT_Vector_Unit( FT_Vector*  vec,
-                  FT_Angle    angle );
-
- -

Return the unit vector corresponding to a given angle. After the call, the value of vec.x will be cos(angle), and the value of vec.y will be sin(angle).

-

This function is useful to retrieve both the sinus and cosinus of a given angle quickly.

-

output

- - - -
vec -

The address of target vector.

-
- -

input

- - - -
angle -

The input angle.

-
- -
- -

FT_Vector_Rotate

-

Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h).

-
  FT_EXPORT( void )
-  FT_Vector_Rotate( FT_Vector*  vec,
-                    FT_Angle    angle );
-
- -

Rotate a vector by a given angle.

-

inout

- - - -
vec -

The address of target vector.

-
- -

input

- - - -
angle -

The input angle.

-
- -
- -

FT_Vector_Length

-

Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h).

-
  FT_EXPORT( FT_Fixed )
-  FT_Vector_Length( FT_Vector*  vec );
-
- -

Return the length of a given vector.

-

input

- - - -
vec -

The address of target vector.

-
- -

return

- -

The vector length, expressed in the same units that the original vector coordinates.

-
- -

FT_Vector_Polarize

-

Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h).

-
  FT_EXPORT( void )
-  FT_Vector_Polarize( FT_Vector*  vec,
-                      FT_Fixed   *length,
-                      FT_Angle   *angle );
-
- -

Compute both the length and angle of a given vector.

-

input

- - - -
vec -

The address of source vector.

-
- -

output

- - - - -
length -

The vector length.

-
angle -

The vector angle.

-
- -
- -

FT_Vector_From_Polar

-

Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h).

-
  FT_EXPORT( void )
-  FT_Vector_From_Polar( FT_Vector*  vec,
-                        FT_Fixed    length,
-                        FT_Angle    angle );
-
- -

Compute vector coordinates from a length and angle.

-

output

- - - -
vec -

The address of source vector.

-
- -

input

- - - - -
length -

The vector length.

-
angle -

The vector angle.

-
- -
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-error_code_values.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-error_code_values.html deleted file mode 100644 index 1c76c5040..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-error_code_values.html +++ /dev/null @@ -1,1395 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Error Code Values - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Error Codes » Error Code Values

-
-

Error Code Values

-

Synopsis

-

The list below is taken verbatim from the file fterrdef.h (loaded automatically by including FT_FREETYPE_H). The first argument of the FT_ERROR_DEF_ macro is the error label; by default, the prefix FT_Err_ gets added so that you get error names like FT_Err_Cannot_Open_Resource. The second argument is the error code, and the last argument an error string, which is not used by FreeType.

-

Within your application you should only use error names and never its numeric values! The latter might (and actually do) change in forthcoming FreeType versions.

-

Macro FT_NOERRORDEF_ defines FT_Err_Ok, which is always zero. See the ‘Error Enumerations’ subsection how to automatically generate a list of error strings.

-

FT_Err_XXX

-
  /* generic errors */
-
-  FT_NOERRORDEF_( Ok,                                        0x00,
-                  "no error" )
-
-  FT_ERRORDEF_( Cannot_Open_Resource,                        0x01,
-                "cannot open resource" )
-  FT_ERRORDEF_( Unknown_File_Format,                         0x02,
-                "unknown file format" )
-  FT_ERRORDEF_( Invalid_File_Format,                         0x03,
-                "broken file" )
-  FT_ERRORDEF_( Invalid_Version,                             0x04,
-                "invalid FreeType version" )
-  FT_ERRORDEF_( Lower_Module_Version,                        0x05,
-                "module version is too low" )
-  FT_ERRORDEF_( Invalid_Argument,                            0x06,
-                "invalid argument" )
-  FT_ERRORDEF_( Unimplemented_Feature,                       0x07,
-                "unimplemented feature" )
-  FT_ERRORDEF_( Invalid_Table,                               0x08,
-                "broken table" )
-  FT_ERRORDEF_( Invalid_Offset,                              0x09,
-                "broken offset within table" )
-  FT_ERRORDEF_( Array_Too_Large,                             0x0A,
-                "array allocation size too large" )
-  FT_ERRORDEF_( Missing_Module,                              0x0B,
-                "missing module" )
-  FT_ERRORDEF_( Missing_Property,                            0x0C,
-                "missing property" )
-
-  /* glyph/character errors */
-
-  FT_ERRORDEF_( Invalid_Glyph_Index,                         0x10,
-                "invalid glyph index" )
-  FT_ERRORDEF_( Invalid_Character_Code,                      0x11,
-                "invalid character code" )
-  FT_ERRORDEF_( Invalid_Glyph_Format,                        0x12,
-                "unsupported glyph image format" )
-  FT_ERRORDEF_( Cannot_Render_Glyph,                         0x13,
-                "cannot render this glyph format" )
-  FT_ERRORDEF_( Invalid_Outline,                             0x14,
-                "invalid outline" )
-  FT_ERRORDEF_( Invalid_Composite,                           0x15,
-                "invalid composite glyph" )
-  FT_ERRORDEF_( Too_Many_Hints,                              0x16,
-                "too many hints" )
-  FT_ERRORDEF_( Invalid_Pixel_Size,                          0x17,
-                "invalid pixel size" )
-
-  /* handle errors */
-
-  FT_ERRORDEF_( Invalid_Handle,                              0x20,
-                "invalid object handle" )
-  FT_ERRORDEF_( Invalid_Library_Handle,                      0x21,
-                "invalid library handle" )
-  FT_ERRORDEF_( Invalid_Driver_Handle,                       0x22,
-                "invalid module handle" )
-  FT_ERRORDEF_( Invalid_Face_Handle,                         0x23,
-                "invalid face handle" )
-  FT_ERRORDEF_( Invalid_Size_Handle,                         0x24,
-                "invalid size handle" )
-  FT_ERRORDEF_( Invalid_Slot_Handle,                         0x25,
-                "invalid glyph slot handle" )
-  FT_ERRORDEF_( Invalid_CharMap_Handle,                      0x26,
-                "invalid charmap handle" )
-  FT_ERRORDEF_( Invalid_Cache_Handle,                        0x27,
-                "invalid cache manager handle" )
-  FT_ERRORDEF_( Invalid_Stream_Handle,                       0x28,
-                "invalid stream handle" )
-
-  /* driver errors */
-
-  FT_ERRORDEF_( Too_Many_Drivers,                            0x30,
-                "too many modules" )
-  FT_ERRORDEF_( Too_Many_Extensions,                         0x31,
-                "too many extensions" )
-
-  /* memory errors */
-
-  FT_ERRORDEF_( Out_Of_Memory,                               0x40,
-                "out of memory" )
-  FT_ERRORDEF_( Unlisted_Object,                             0x41,
-                "unlisted object" )
-
-  /* stream errors */
-
-  FT_ERRORDEF_( Cannot_Open_Stream,                          0x51,
-                "cannot open stream" )
-  FT_ERRORDEF_( Invalid_Stream_Seek,                         0x52,
-                "invalid stream seek" )
-  FT_ERRORDEF_( Invalid_Stream_Skip,                         0x53,
-                "invalid stream skip" )
-  FT_ERRORDEF_( Invalid_Stream_Read,                         0x54,
-                "invalid stream read" )
-  FT_ERRORDEF_( Invalid_Stream_Operation,                    0x55,
-                "invalid stream operation" )
-  FT_ERRORDEF_( Invalid_Frame_Operation,                     0x56,
-                "invalid frame operation" )
-  FT_ERRORDEF_( Nested_Frame_Access,                         0x57,
-                "nested frame access" )
-  FT_ERRORDEF_( Invalid_Frame_Read,                          0x58,
-                "invalid frame read" )
-
-  /* raster errors */
-
-  FT_ERRORDEF_( Raster_Uninitialized,                        0x60,
-                "raster uninitialized" )
-  FT_ERRORDEF_( Raster_Corrupted,                            0x61,
-                "raster corrupted" )
-  FT_ERRORDEF_( Raster_Overflow,                             0x62,
-                "raster overflow" )
-  FT_ERRORDEF_( Raster_Negative_Height,                      0x63,
-                "negative height while rastering" )
-
-  /* cache errors */
-
-  FT_ERRORDEF_( Too_Many_Caches,                             0x70,
-                "too many registered caches" )
-
-  /* TrueType and SFNT errors */
-
-  FT_ERRORDEF_( Invalid_Opcode,                              0x80,
-                "invalid opcode" )
-  FT_ERRORDEF_( Too_Few_Arguments,                           0x81,
-                "too few arguments" )
-  FT_ERRORDEF_( Stack_Overflow,                              0x82,
-                "stack overflow" )
-  FT_ERRORDEF_( Code_Overflow,                               0x83,
-                "code overflow" )
-  FT_ERRORDEF_( Bad_Argument,                                0x84,
-                "bad argument" )
-  FT_ERRORDEF_( Divide_By_Zero,                              0x85,
-                "division by zero" )
-  FT_ERRORDEF_( Invalid_Reference,                           0x86,
-                "invalid reference" )
-  FT_ERRORDEF_( Debug_OpCode,                                0x87,
-                "found debug opcode" )
-  FT_ERRORDEF_( ENDF_In_Exec_Stream,                         0x88,
-                "found ENDF opcode in execution stream" )
-  FT_ERRORDEF_( Nested_DEFS,                                 0x89,
-                "nested DEFS" )
-  FT_ERRORDEF_( Invalid_CodeRange,                           0x8A,
-                "invalid code range" )
-  FT_ERRORDEF_( Execution_Too_Long,                          0x8B,
-                "execution context too long" )
-  FT_ERRORDEF_( Too_Many_Function_Defs,                      0x8C,
-                "too many function definitions" )
-  FT_ERRORDEF_( Too_Many_Instruction_Defs,                   0x8D,
-                "too many instruction definitions" )
-  FT_ERRORDEF_( Table_Missing,                               0x8E,
-                "SFNT font table missing" )
-  FT_ERRORDEF_( Horiz_Header_Missing,                        0x8F,
-                "horizontal header (hhea) table missing" )
-  FT_ERRORDEF_( Locations_Missing,                           0x90,
-                "locations (loca) table missing" )
-  FT_ERRORDEF_( Name_Table_Missing,                          0x91,
-                "name table missing" )
-  FT_ERRORDEF_( CMap_Table_Missing,                          0x92,
-                "character map (cmap) table missing" )
-  FT_ERRORDEF_( Hmtx_Table_Missing,                          0x93,
-                "horizontal metrics (hmtx) table missing" )
-  FT_ERRORDEF_( Post_Table_Missing,                          0x94,
-                "PostScript (post) table missing" )
-  FT_ERRORDEF_( Invalid_Horiz_Metrics,                       0x95,
-                "invalid horizontal metrics" )
-  FT_ERRORDEF_( Invalid_CharMap_Format,                      0x96,
-                "invalid character map (cmap) format" )
-  FT_ERRORDEF_( Invalid_PPem,                                0x97,
-                "invalid ppem value" )
-  FT_ERRORDEF_( Invalid_Vert_Metrics,                        0x98,
-                "invalid vertical metrics" )
-  FT_ERRORDEF_( Could_Not_Find_Context,                      0x99,
-                "could not find context" )
-  FT_ERRORDEF_( Invalid_Post_Table_Format,                   0x9A,
-                "invalid PostScript (post) table format" )
-  FT_ERRORDEF_( Invalid_Post_Table,                          0x9B,
-                "invalid PostScript (post) table" )
-  FT_ERRORDEF_( DEF_In_Glyf_Bytecode,                        0x9C,
-                "found FDEF or IDEF opcode in glyf bytecode" )
-  FT_ERRORDEF_( Missing_Bitmap,                              0x9D,
-                "missing bitmap in strike" )
-
-  /* CFF, CID, and Type 1 errors */
-
-  FT_ERRORDEF_( Syntax_Error,                                0xA0,
-                "opcode syntax error" )
-  FT_ERRORDEF_( Stack_Underflow,                             0xA1,
-                "argument stack underflow" )
-  FT_ERRORDEF_( Ignore,                                      0xA2,
-                "ignore" )
-  FT_ERRORDEF_( No_Unicode_Glyph_Name,                       0xA3,
-                "no Unicode glyph name found" )
-  FT_ERRORDEF_( Glyph_Too_Big,                               0xA4,
-                "glyph too big for hinting" )
-
-  /* BDF errors */
-
-  FT_ERRORDEF_( Missing_Startfont_Field,                     0xB0,
-                "`STARTFONT' field missing" )
-  FT_ERRORDEF_( Missing_Font_Field,                          0xB1,
-                "`FONT' field missing" )
-  FT_ERRORDEF_( Missing_Size_Field,                          0xB2,
-                "`SIZE' field missing" )
-  FT_ERRORDEF_( Missing_Fontboundingbox_Field,               0xB3,
-                "`FONTBOUNDINGBOX' field missing" )
-  FT_ERRORDEF_( Missing_Chars_Field,                         0xB4,
-                "`CHARS' field missing" )
-  FT_ERRORDEF_( Missing_Startchar_Field,                     0xB5,
-                "`STARTCHAR' field missing" )
-  FT_ERRORDEF_( Missing_Encoding_Field,                      0xB6,
-                "`ENCODING' field missing" )
-  FT_ERRORDEF_( Missing_Bbx_Field,                           0xB7,
-                "`BBX' field missing" )
-  FT_ERRORDEF_( Bbx_Too_Big,                                 0xB8,
-                "`BBX' too big" )
-  FT_ERRORDEF_( Corrupted_Font_Header,                       0xB9,
-                "Font header corrupted or missing fields" )
-  FT_ERRORDEF_( Corrupted_Font_Glyphs,                       0xBA,
-                "Font glyphs corrupted or missing fields" )
-
- -
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-error_enumerations.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-error_enumerations.html deleted file mode 100644 index af273620f..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-error_enumerations.html +++ /dev/null @@ -1,1244 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Error Enumerations - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Error Codes » Error Enumerations

-
-

Error Enumerations

-

Synopsis

-

The header file fterrors.h (which is automatically included by freetype.h defines the handling of FreeType's enumeration constants. It can also be used to generate error message strings with a small macro trick explained below.

-

Error Formats

-

The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be defined in ftoption.h in order to make the higher byte indicate the module where the error has happened (this is not compatible with standard builds of FreeType 2, however). See the file ftmoderr.h for more details.

-

Error Message Strings

-

Error definitions are set up with special macros that allow client applications to build a table of error message strings. The strings are not included in a normal build of FreeType 2 to save space (most client applications do not use them).

-

To do so, you have to define the following macros before including this file. -

  FT_ERROR_START_LIST
-

-

This macro is called before anything else to define the start of the error list. It is followed by several FT_ERROR_DEF calls. -

  FT_ERROR_DEF( e, v, s )
-

-

This macro is called to define one single error. ‘e’ is the error code identifier (e.g., Invalid_Argument), ‘v’ is the error's numerical value, and ‘s’ is the corresponding error string. -

  FT_ERROR_END_LIST
-

-

This macro ends the list.

-

Additionally, you have to undefine FTERRORS_H_ before #including this file.

-

Here is a simple example. -

  #undef FTERRORS_H_
-  #define FT_ERRORDEF( e, v, s )  { e, s },
-  #define FT_ERROR_START_LIST     {
-  #define FT_ERROR_END_LIST       { 0, NULL } };
-
-  const struct
-  {
-    int          err_code;
-    const char*  err_msg;
-  } ft_errors[] =
-
-  #include <freetype/fterrors.h>
-

-

An alternative to using an array is a switch statement. -

  #undef FTERRORS_H_
-  #define FT_ERROR_START_LIST     switch ( error_code ) {
-  #define FT_ERRORDEF( e, v, s )    case v: return s;
-  #define FT_ERROR_END_LIST       }
-

-

If you use FT_CONFIG_OPTION_USE_MODULE_ERRORS, error_code should be replaced with FT_ERROR_BASE(error_code) in the last example.

-

FT_Error_String

-

Defined in FT_ERRORS_H (freetype/fterrors.h).

-
  FT_EXPORT( const char* )
-  FT_Error_String( FT_Error  error_code );
-
-FT_END_HEADER
-
-
-#endif /* FT_ERR_PROTOS_DEFINED */
-
-#endif /* FT_INCLUDE_ERR_PROTOS */
-
-#endif /* !(FTERRORS_H_ && __FTERRORS_H__) */
-
-
-/* END */
-
- -

Retrieve the description of a valid FreeType error code.

-

input

- - - -
error_code -

A valid FreeType error code.

-
- -

return

- -

A C string or NULL, if any error occurred.

-

note

- -

FreeType has to be compiled with FT_CONFIG_OPTION_ERROR_STRINGS or FT_DEBUG_LEVEL_ERROR to get meaningful descriptions. ‘error_string’ will be NULL otherwise.

-

Module identification will be ignored: -

  strcmp( FT_Error_String(  FT_Err_Unknown_File_Format ),
-          FT_Error_String( BDF_Err_Unknown_File_Format ) ) == 0;
-

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-font_formats.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-font_formats.html deleted file mode 100644 index 537e95488..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-font_formats.html +++ /dev/null @@ -1,1197 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Font Formats - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Format-Specific API » Font Formats

-
-

Font Formats

-

Synopsis

-

The single function in this section can be used to get the font format. Note that this information is not needed normally; however, there are special cases (like in PDF devices) where it is important to differentiate, in spite of FreeType's uniform API.

-

FT_Get_Font_Format

-

Defined in FT_FONT_FORMATS_H (freetype/ftfntfmt.h).

-
  FT_EXPORT( const char* )
-  FT_Get_Font_Format( FT_Face  face );
-
-  /* deprecated */
-  FT_EXPORT( const char* )
-  FT_Get_X11_Font_Format( FT_Face  face );
-
- -

Return a string describing the format of a given face. Possible values are ‘TrueType’, ‘Type 1’, ‘BDF’, ‘PCF’, ‘Type 42’, ‘CID Type 1’, ‘CFF’, ‘PFR’, and ‘Windows FNT’.

-

The return value is suitable to be used as an X11 FONT_PROPERTY.

-

input

- - - -
face -

Input face handle.

-
- -

return

- -

Font format string. NULL in case of error.

-

note

- -

A deprecated name for the same function is FT_Get_X11_Font_Format.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-gasp_table.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-gasp_table.html deleted file mode 100644 index 3c2461583..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-gasp_table.html +++ /dev/null @@ -1,1252 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Gasp Table - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Format-Specific API » Gasp Table

-
-

Gasp Table

-

Synopsis

-

The function FT_Get_Gasp can be used to query a TrueType or OpenType font for specific entries in its ‘gasp’ table, if any. This is mainly useful when implementing native TrueType hinting with the bytecode interpreter to duplicate the Windows text rendering results.

-

FT_GASP_XXX

-

Defined in FT_GASP_H (freetype/ftgasp.h).

-
#define FT_GASP_NO_TABLE               -1
-#define FT_GASP_DO_GRIDFIT           0x01
-#define FT_GASP_DO_GRAY              0x02
-#define FT_GASP_SYMMETRIC_GRIDFIT    0x04
-#define FT_GASP_SYMMETRIC_SMOOTHING  0x08
-
- -

A list of values and/or bit-flags returned by the FT_Get_Gasp function.

-

values

- - - - - - - -
FT_GASP_NO_TABLE -

This special value means that there is no GASP table in this face. It is up to the client to decide what to do.

-
FT_GASP_DO_GRIDFIT -

Grid-fitting and hinting should be performed at the specified ppem. This really means TrueType bytecode interpretation. If this bit is not set, no hinting gets applied.

-
FT_GASP_DO_GRAY -

Anti-aliased rendering should be performed at the specified ppem. If not set, do monochrome rendering.

-
FT_GASP_SYMMETRIC_SMOOTHING -

If set, smoothing along multiple axes must be used with ClearType.

-
FT_GASP_SYMMETRIC_GRIDFIT -

Grid-fitting must be used with ClearType's symmetric smoothing.

-
- -

note

- -

The bit-flags FT_GASP_DO_GRIDFIT and FT_GASP_DO_GRAY are to be used for standard font rasterization only. Independently of that, FT_GASP_SYMMETRIC_SMOOTHING and FT_GASP_SYMMETRIC_GRIDFIT are to be used if ClearType is enabled (and FT_GASP_DO_GRIDFIT and FT_GASP_DO_GRAY are consequently ignored).

-

‘ClearType’ is Microsoft's implementation of LCD rendering, partly protected by patents.

-

since

- -

2.3.0

-
- -

FT_Get_Gasp

-

Defined in FT_GASP_H (freetype/ftgasp.h).

-
  FT_EXPORT( FT_Int )
-  FT_Get_Gasp( FT_Face  face,
-               FT_UInt  ppem );
-
- -

For a TrueType or OpenType font file, return the rasterizer behaviour flags from the font's ‘gasp’ table corresponding to a given character pixel size.

-

input

- - - - -
face -

The source face handle.

-
ppem -

The vertical character pixel size.

-
- -

return

- -

Bit flags (see FT_GASP_XXX), or FT_GASP_NO_TABLE if there is no ‘gasp’ table in the face.

-

note

- -

If you want to use the MM functionality of OpenType variation fonts (i.e., using FT_Set_Var_Design_Coordinates and friends), call this function after setting an instance since the return values can change.

-

since

- -

2.3.0

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-glyph_management.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-glyph_management.html deleted file mode 100644 index a0620c4d9..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-glyph_management.html +++ /dev/null @@ -1,1821 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Glyph Management - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Core API » Glyph Management

-
-

Glyph Management

-

Synopsis

-

This section contains definitions used to manage glyph data through generic FT_Glyph objects. Each of them can contain a bitmap, a vector outline, or even images in other formats. These objects are detached from FT_Face, contrary to FT_GlyphSlot.

-

FT_Glyph

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  typedef struct FT_GlyphRec_*  FT_Glyph;
-
- -

Handle to an object used to model generic glyph images. It is a pointer to the FT_GlyphRec structure and can contain a glyph bitmap or pointer.

-

note

- -

Glyph objects are not owned by the library. You must thus release them manually (through FT_Done_Glyph) before calling FT_Done_FreeType.

-
- -

FT_GlyphRec

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  typedef struct  FT_GlyphRec_
-  {
-    FT_Library             library;
-    const FT_Glyph_Class*  clazz;
-    FT_Glyph_Format        format;
-    FT_Vector              advance;
-
-  } FT_GlyphRec;
-
- -

The root glyph structure contains a given glyph image plus its advance width in 16.16 fixed-point format.

-

fields

- - - - - - -
library -

A handle to the FreeType library object.

-
clazz -

A pointer to the glyph's class. Private.

-
format -

The format of the glyph's image.

-
advance -

A 16.16 vector that gives the glyph's advance width.

-
- -
- -

FT_BitmapGlyph

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  typedef struct FT_BitmapGlyphRec_*  FT_BitmapGlyph;
-
- -

A handle to an object used to model a bitmap glyph image. This is a sub-class of FT_Glyph, and a pointer to FT_BitmapGlyphRec.

-
- -

FT_BitmapGlyphRec

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  typedef struct  FT_BitmapGlyphRec_
-  {
-    FT_GlyphRec  root;
-    FT_Int       left;
-    FT_Int       top;
-    FT_Bitmap    bitmap;
-
-  } FT_BitmapGlyphRec;
-
- -

A structure used for bitmap glyph images. This really is a ‘sub-class’ of FT_GlyphRec.

-

fields

- - - - - - -
root -

The root FT_Glyph fields.

-
left -

The left-side bearing, i.e., the horizontal distance from the current pen position to the left border of the glyph bitmap.

-
top -

The top-side bearing, i.e., the vertical distance from the current pen position to the top border of the glyph bitmap. This distance is positive for upwards y!

-
bitmap -

A descriptor for the bitmap.

-
- -

note

- -

You can typecast an FT_Glyph to FT_BitmapGlyph if you have glyph->format == FT_GLYPH_FORMAT_BITMAP. This lets you access the bitmap's contents easily.

-

The corresponding pixel buffer is always owned by FT_BitmapGlyph and is thus created and destroyed with it.

-
- -

FT_OutlineGlyph

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  typedef struct FT_OutlineGlyphRec_*  FT_OutlineGlyph;
-
- -

A handle to an object used to model an outline glyph image. This is a sub-class of FT_Glyph, and a pointer to FT_OutlineGlyphRec.

-
- -

FT_OutlineGlyphRec

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  typedef struct  FT_OutlineGlyphRec_
-  {
-    FT_GlyphRec  root;
-    FT_Outline   outline;
-
-  } FT_OutlineGlyphRec;
-
- -

A structure used for outline (vectorial) glyph images. This really is a ‘sub-class’ of FT_GlyphRec.

-

fields

- - - - -
root -

The root FT_Glyph fields.

-
outline -

A descriptor for the outline.

-
- -

note

- -

You can typecast an FT_Glyph to FT_OutlineGlyph if you have glyph->format == FT_GLYPH_FORMAT_OUTLINE. This lets you access the outline's content easily.

-

As the outline is extracted from a glyph slot, its coordinates are expressed normally in 26.6 pixels, unless the flag FT_LOAD_NO_SCALE was used in FT_Load_Glyph or FT_Load_Char.

-

The outline's tables are always owned by the object and are destroyed with it.

-
- -

FT_New_Glyph

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  FT_EXPORT( FT_Error )
-  FT_New_Glyph( FT_Library       library,
-                FT_Glyph_Format  format,
-                FT_Glyph         *aglyph );
-
- -

A function used to create a new empty glyph image. Note that the created FT_Glyph object must be released with FT_Done_Glyph.

-

input

- - - - -
library -

A handle to the FreeType library object.

-
format -

The format of the glyph's image.

-
- -

output

- - - -
aglyph -

A handle to the glyph object.

-
- -

return

- -

FreeType error code. 0 means success.

-

since

- -

2.10

-
- -

FT_Get_Glyph

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_Glyph( FT_GlyphSlot  slot,
-                FT_Glyph     *aglyph );
-
- -

A function used to extract a glyph image from a slot. Note that the created FT_Glyph object must be released with FT_Done_Glyph.

-

input

- - - -
slot -

A handle to the source glyph slot.

-
- -

output

- - - -
aglyph -

A handle to the glyph object.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

Because *aglyph->advance.x and *aglyph->advance.y are 16.16 fixed-point numbers, slot->advance.x and slot->advance.y (which are in 26.6 fixed-point format) must be in the range ]-32768;32768[.

-
- -

FT_Glyph_Copy

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  FT_EXPORT( FT_Error )
-  FT_Glyph_Copy( FT_Glyph   source,
-                 FT_Glyph  *target );
-
- -

A function used to copy a glyph image. Note that the created FT_Glyph object must be released with FT_Done_Glyph.

-

input

- - - -
source -

A handle to the source glyph object.

-
- -

output

- - - -
target -

A handle to the target glyph object. 0 in case of error.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FT_Glyph_Transform

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  FT_EXPORT( FT_Error )
-  FT_Glyph_Transform( FT_Glyph    glyph,
-                      FT_Matrix*  matrix,
-                      FT_Vector*  delta );
-
- -

Transform a glyph image if its format is scalable.

-

inout

- - - -
glyph -

A handle to the target glyph object.

-
- -

input

- - - - -
matrix -

A pointer to a 2x2 matrix to apply.

-
delta -

A pointer to a 2d vector to apply. Coordinates are expressed in 1/64th of a pixel.

-
- -

return

- -

FreeType error code (if not 0, the glyph format is not scalable).

-

note

- -

The 2x2 transformation matrix is also applied to the glyph's advance vector.

-
- -

FT_Glyph_BBox_Mode

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  typedef enum  FT_Glyph_BBox_Mode_
-  {
-    FT_GLYPH_BBOX_UNSCALED  = 0,
-    FT_GLYPH_BBOX_SUBPIXELS = 0,
-    FT_GLYPH_BBOX_GRIDFIT   = 1,
-    FT_GLYPH_BBOX_TRUNCATE  = 2,
-    FT_GLYPH_BBOX_PIXELS    = 3
-
-  } FT_Glyph_BBox_Mode;
-
-
-  /* these constants are deprecated; use the corresponding */
-  /* `FT_Glyph_BBox_Mode` values instead                   */
-#define ft_glyph_bbox_unscaled   FT_GLYPH_BBOX_UNSCALED
-#define ft_glyph_bbox_subpixels  FT_GLYPH_BBOX_SUBPIXELS
-#define ft_glyph_bbox_gridfit    FT_GLYPH_BBOX_GRIDFIT
-#define ft_glyph_bbox_truncate   FT_GLYPH_BBOX_TRUNCATE
-#define ft_glyph_bbox_pixels     FT_GLYPH_BBOX_PIXELS
-
- -

The mode how the values of FT_Glyph_Get_CBox are returned.

-

values

- - - - - - - -
FT_GLYPH_BBOX_UNSCALED -

Return unscaled font units.

-
FT_GLYPH_BBOX_SUBPIXELS -

Return unfitted 26.6 coordinates.

-
FT_GLYPH_BBOX_GRIDFIT -

Return grid-fitted 26.6 coordinates.

-
FT_GLYPH_BBOX_TRUNCATE -

Return coordinates in integer pixels.

-
FT_GLYPH_BBOX_PIXELS -

Return grid-fitted pixel coordinates.

-
- -
- -

FT_Glyph_Get_CBox

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  FT_EXPORT( void )
-  FT_Glyph_Get_CBox( FT_Glyph  glyph,
-                     FT_UInt   bbox_mode,
-                     FT_BBox  *acbox );
-
- -

Return a glyph's ‘control box’. The control box encloses all the outline's points, including Bezier control points. Though it coincides with the exact bounding box for most glyphs, it can be slightly larger in some situations (like when rotating an outline that contains Bezier outside arcs).

-

Computing the control box is very fast, while getting the bounding box can take much more time as it needs to walk over all segments and arcs in the outline. To get the latter, you can use the ‘ftbbox’ component, which is dedicated to this single task.

-

input

- - - - -
glyph -

A handle to the source glyph object.

-
mode -

The mode that indicates how to interpret the returned bounding box values.

-
- -

output

- - - -
acbox -

The glyph coordinate bounding box. Coordinates are expressed in 1/64th of pixels if it is grid-fitted.

-
- -

note

- -

Coordinates are relative to the glyph origin, using the y upwards convention.

-

If the glyph has been loaded with FT_LOAD_NO_SCALE, bbox_mode must be set to FT_GLYPH_BBOX_UNSCALED to get unscaled font units in 26.6 pixel format. The value FT_GLYPH_BBOX_SUBPIXELS is another name for this constant.

-

If the font is tricky and the glyph has been loaded with FT_LOAD_NO_SCALE, the resulting CBox is meaningless. To get reasonable values for the CBox it is necessary to load the glyph at a large ppem value (so that the hinting instructions can properly shift and scale the subglyphs), then extracting the CBox, which can be eventually converted back to font units.

-

Note that the maximum coordinates are exclusive, which means that one can compute the width and height of the glyph image (be it in integer or 26.6 pixels) as: -

  width  = bbox.xMax - bbox.xMin;
-  height = bbox.yMax - bbox.yMin;
-

-

Note also that for 26.6 coordinates, if bbox_mode is set to FT_GLYPH_BBOX_GRIDFIT, the coordinates will also be grid-fitted, which corresponds to: -

  bbox.xMin = FLOOR(bbox.xMin);
-  bbox.yMin = FLOOR(bbox.yMin);
-  bbox.xMax = CEILING(bbox.xMax);
-  bbox.yMax = CEILING(bbox.yMax);
-

-

To get the bbox in pixel coordinates, set bbox_mode to FT_GLYPH_BBOX_TRUNCATE.

-

To get the bbox in grid-fitted pixel coordinates, set bbox_mode to FT_GLYPH_BBOX_PIXELS.

-
- -

FT_Glyph_To_Bitmap

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  FT_EXPORT( FT_Error )
-  FT_Glyph_To_Bitmap( FT_Glyph*       the_glyph,
-                      FT_Render_Mode  render_mode,
-                      FT_Vector*      origin,
-                      FT_Bool         destroy );
-
- -

Convert a given glyph object to a bitmap glyph object.

-

inout

- - - -
the_glyph -

A pointer to a handle to the target glyph.

-
- -

input

- - - - - -
render_mode -

An enumeration that describes how the data is rendered.

-
origin -

A pointer to a vector used to translate the glyph image before rendering. Can be 0 (if no translation). The origin is expressed in 26.6 pixels.

-
destroy -

A boolean that indicates that the original glyph image should be destroyed by this function. It is never destroyed in case of error.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function does nothing if the glyph format isn't scalable.

-

The glyph image is translated with the origin vector before rendering.

-

The first parameter is a pointer to an FT_Glyph handle, that will be replaced by this function (with newly allocated data). Typically, you would use (omitting error handling): -

  FT_Glyph        glyph;
-  FT_BitmapGlyph  glyph_bitmap;
-
-
-  // load glyph
-  error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAULT );
-
-  // extract glyph image
-  error = FT_Get_Glyph( face->glyph, &glyph );
-
-  // convert to a bitmap (default render mode + destroying old)
-  if ( glyph->format != FT_GLYPH_FORMAT_BITMAP )
-  {
-    error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL,
-                                  0, 1 );
-    if ( error ) // `glyph' unchanged
-      ...
-  }
-
-  // access bitmap content by typecasting
-  glyph_bitmap = (FT_BitmapGlyph)glyph;
-
-  // do funny stuff with it, like blitting/drawing
-  ...
-
-  // discard glyph image (bitmap or not)
-  FT_Done_Glyph( glyph );
-

-

Here is another example, again without error handling: -

  FT_Glyph  glyphs[MAX_GLYPHS]
-
-
-  ...
-
-  for ( idx = 0; i < MAX_GLYPHS; i++ )
-    error = FT_Load_Glyph( face, idx, FT_LOAD_DEFAULT ) ||
-            FT_Get_Glyph ( face->glyph, &glyphs[idx] );
-
-  ...
-
-  for ( idx = 0; i < MAX_GLYPHS; i++ )
-  {
-    FT_Glyph  bitmap = glyphs[idx];
-
-
-    ...
-
-    // after this call, `bitmap' no longer points into
-    // the `glyphs' array (and the old value isn't destroyed)
-    FT_Glyph_To_Bitmap( &bitmap, FT_RENDER_MODE_MONO, 0, 0 );
-
-    ...
-
-    FT_Done_Glyph( bitmap );
-  }
-
-  ...
-
-  for ( idx = 0; i < MAX_GLYPHS; i++ )
-    FT_Done_Glyph( glyphs[idx] );
-

-
- -

FT_Done_Glyph

-

Defined in FT_GLYPH_H (freetype/ftglyph.h).

-
  FT_EXPORT( void )
-  FT_Done_Glyph( FT_Glyph  glyph );
-
- -

Destroy a given glyph.

-

input

- - - -
glyph -

A handle to the target glyph object.

-
- -
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-glyph_stroker.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-glyph_stroker.html deleted file mode 100644 index e797bb9e8..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-glyph_stroker.html +++ /dev/null @@ -1,2092 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Glyph Stroker - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Support API » Glyph Stroker

-
-

Glyph Stroker

-

Synopsis

-

This component generates stroked outlines of a given vectorial glyph. It also allows you to retrieve the ‘outside’ and/or the ‘inside’ borders of the stroke.

-

This can be useful to generate ‘bordered’ glyph, i.e., glyphs displayed with a colored (and anti-aliased) border around their shape.

-

FT_Stroker

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  typedef struct FT_StrokerRec_*  FT_Stroker;
-
- -

Opaque handle to a path stroker object.

-
- -

FT_Stroker_LineJoin

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

- - -

These values determine how two joining lines are rendered in a stroker.

-

values

- - - - - - - -
FT_STROKER_LINEJOIN_ROUND -

Used to render rounded line joins. Circular arcs are used to join two lines smoothly.

-
FT_STROKER_LINEJOIN_BEVEL -

Used to render beveled line joins. The outer corner of the joined lines is filled by enclosing the triangular region of the corner with a straight line between the outer corners of each stroke.

-
FT_STROKER_LINEJOIN_MITER_FIXED -

Used to render mitered line joins, with fixed bevels if the miter limit is exceeded. The outer edges of the strokes for the two segments are extended until they meet at an angle. A bevel join (see above) is used if the segments meet at too sharp an angle and the outer edges meet beyond a distance corresponding to the meter limit. This prevents long spikes being created. FT_STROKER_LINEJOIN_MITER_FIXED generates a miter line join as used in PostScript and PDF.

-
FT_STROKER_LINEJOIN_MITER_VARIABLE - -
FT_STROKER_LINEJOIN_MITER -

Used to render mitered line joins, with variable bevels if the miter limit is exceeded. The intersection of the strokes is clipped perpendicularly to the bisector, at a distance corresponding to the miter limit. This prevents long spikes being created. FT_STROKER_LINEJOIN_MITER_VARIABLE generates a mitered line join as used in XPS. FT_STROKER_LINEJOIN_MITER is an alias for FT_STROKER_LINEJOIN_MITER_VARIABLE, retained for backward compatibility.

-
- -
- -

FT_Stroker_LineCap

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  typedef enum  FT_Stroker_LineCap_
-  {
-    FT_STROKER_LINECAP_BUTT = 0,
-    FT_STROKER_LINECAP_ROUND,
-    FT_STROKER_LINECAP_SQUARE
-
-  } FT_Stroker_LineCap;
-
- -

These values determine how the end of opened sub-paths are rendered in a stroke.

-

values

- - - - - -
FT_STROKER_LINECAP_BUTT -

The end of lines is rendered as a full stop on the last point itself.

-
FT_STROKER_LINECAP_ROUND -

The end of lines is rendered as a half-circle around the last point.

-
FT_STROKER_LINECAP_SQUARE -

The end of lines is rendered as a square around the last point.

-
- -
- -

FT_StrokerBorder

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  typedef enum  FT_StrokerBorder_
-  {
-    FT_STROKER_BORDER_LEFT = 0,
-    FT_STROKER_BORDER_RIGHT
-
-  } FT_StrokerBorder;
-
- -

These values are used to select a given stroke border in FT_Stroker_GetBorderCounts and FT_Stroker_ExportBorder.

-

values

- - - - -
FT_STROKER_BORDER_LEFT -

Select the left border, relative to the drawing direction.

-
FT_STROKER_BORDER_RIGHT -

Select the right border, relative to the drawing direction.

-
- -

note

- -

Applications are generally interested in the ‘inside’ and ‘outside’ borders. However, there is no direct mapping between these and the ‘left’ and ‘right’ ones, since this really depends on the glyph's drawing orientation, which varies between font formats.

-

You can however use FT_Outline_GetInsideBorder and FT_Outline_GetOutsideBorder to get these.

-
- -

FT_Outline_GetInsideBorder

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( FT_StrokerBorder )
-  FT_Outline_GetInsideBorder( FT_Outline*  outline );
-
- -

Retrieve the FT_StrokerBorder value corresponding to the ‘inside’ borders of a given outline.

-

input

- - - -
outline -

The source outline handle.

-
- -

return

- -

The border index. FT_STROKER_BORDER_RIGHT for empty or invalid outlines.

-
- -

FT_Outline_GetOutsideBorder

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( FT_StrokerBorder )
-  FT_Outline_GetOutsideBorder( FT_Outline*  outline );
-
- -

Retrieve the FT_StrokerBorder value corresponding to the ‘outside’ borders of a given outline.

-

input

- - - -
outline -

The source outline handle.

-
- -

return

- -

The border index. FT_STROKER_BORDER_LEFT for empty or invalid outlines.

-
- -

FT_Glyph_Stroke

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( FT_Error )
-  FT_Glyph_Stroke( FT_Glyph    *pglyph,
-                   FT_Stroker   stroker,
-                   FT_Bool      destroy );
-
- -

Stroke a given outline glyph object with a given stroker.

-

inout

- - - -
pglyph -

Source glyph handle on input, new glyph handle on output.

-
- -

input

- - - - -
stroker -

A stroker handle.

-
destroy -

A Boolean. If 1, the source glyph object is destroyed on success.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The source glyph is untouched in case of error.

-

Adding stroke may yield a significantly wider and taller glyph depending on how large of a radius was used to stroke the glyph. You may need to manually adjust horizontal and vertical advance amounts to account for this added size.

-
- -

FT_Glyph_StrokeBorder

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( FT_Error )
-  FT_Glyph_StrokeBorder( FT_Glyph    *pglyph,
-                         FT_Stroker   stroker,
-                         FT_Bool      inside,
-                         FT_Bool      destroy );
-
- -

Stroke a given outline glyph object with a given stroker, but only return either its inside or outside border.

-

inout

- - - -
pglyph -

Source glyph handle on input, new glyph handle on output.

-
- -

input

- - - - - -
stroker -

A stroker handle.

-
inside -

A Boolean. If 1, return the inside border, otherwise the outside border.

-
destroy -

A Boolean. If 1, the source glyph object is destroyed on success.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The source glyph is untouched in case of error.

-

Adding stroke may yield a significantly wider and taller glyph depending on how large of a radius was used to stroke the glyph. You may need to manually adjust horizontal and vertical advance amounts to account for this added size.

-
- -

FT_Stroker_New

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( FT_Error )
-  FT_Stroker_New( FT_Library   library,
-                  FT_Stroker  *astroker );
-
- -

Create a new stroker object.

-

input

- - - -
library -

FreeType library handle.

-
- -

output

- - - -
astroker -

A new stroker object handle. NULL in case of error.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FT_Stroker_Set

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( void )
-  FT_Stroker_Set( FT_Stroker           stroker,
-                  FT_Fixed             radius,
-                  FT_Stroker_LineCap   line_cap,
-                  FT_Stroker_LineJoin  line_join,
-                  FT_Fixed             miter_limit );
-
- -

Reset a stroker object's attributes.

-

input

- - - - - - - -
stroker -

The target stroker handle.

-
radius -

The border radius.

-
line_cap -

The line cap style.

-
line_join -

The line join style.

-
miter_limit -

The maximum reciprocal sine of half-angle at the miter join, expressed as 16.16 fixed point value.

-
- -

note

- -

The radius is expressed in the same units as the outline coordinates.

-

The miter_limit multiplied by the radius gives the maximum size of a miter spike, at which it is clipped for FT_STROKER_LINEJOIN_MITER_VARIABLE or replaced with a bevel join for FT_STROKER_LINEJOIN_MITER_FIXED.

-

This function calls FT_Stroker_Rewind automatically.

-
- -

FT_Stroker_Rewind

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( void )
-  FT_Stroker_Rewind( FT_Stroker  stroker );
-
- -

Reset a stroker object without changing its attributes. You should call this function before beginning a new series of calls to FT_Stroker_BeginSubPath or FT_Stroker_EndSubPath.

-

input

- - - -
stroker -

The target stroker handle.

-
- -
- -

FT_Stroker_ParseOutline

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( FT_Error )
-  FT_Stroker_ParseOutline( FT_Stroker   stroker,
-                           FT_Outline*  outline,
-                           FT_Bool      opened );
-
- -

A convenience function used to parse a whole outline with the stroker. The resulting outline(s) can be retrieved later by functions like FT_Stroker_GetCounts and FT_Stroker_Export.

-

input

- - - - - -
stroker -

The target stroker handle.

-
outline -

The source outline.

-
opened -

A boolean. If 1, the outline is treated as an open path instead of a closed one.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

If opened is 0 (the default), the outline is treated as a closed path, and the stroker generates two distinct ‘border’ outlines.

-

If opened is 1, the outline is processed as an open path, and the stroker generates a single ‘stroke’ outline.

-

This function calls FT_Stroker_Rewind automatically.

-
- -

FT_Stroker_Done

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( void )
-  FT_Stroker_Done( FT_Stroker  stroker );
-
- -

Destroy a stroker object.

-

input

- - - -
stroker -

A stroker handle. Can be NULL.

-
- -
- -

FT_Stroker_BeginSubPath

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( FT_Error )
-  FT_Stroker_BeginSubPath( FT_Stroker  stroker,
-                           FT_Vector*  to,
-                           FT_Bool     open );
-
- -

Start a new sub-path in the stroker.

-

input

- - - - - -
stroker -

The target stroker handle.

-
to -

A pointer to the start vector.

-
open -

A boolean. If 1, the sub-path is treated as an open one.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function is useful when you need to stroke a path that is not stored as an FT_Outline object.

-
- -

FT_Stroker_EndSubPath

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( FT_Error )
-  FT_Stroker_EndSubPath( FT_Stroker  stroker );
-
- -

Close the current sub-path in the stroker.

-

input

- - - -
stroker -

The target stroker handle.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

You should call this function after FT_Stroker_BeginSubPath. If the subpath was not ‘opened’, this function ‘draws’ a single line segment to the start position when needed.

-
- -

FT_Stroker_LineTo

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( FT_Error )
-  FT_Stroker_LineTo( FT_Stroker  stroker,
-                     FT_Vector*  to );
-
- -

‘Draw’ a single line segment in the stroker's current sub-path, from the last position.

-

input

- - - - -
stroker -

The target stroker handle.

-
to -

A pointer to the destination point.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

You should call this function between FT_Stroker_BeginSubPath and FT_Stroker_EndSubPath.

-
- -

FT_Stroker_ConicTo

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( FT_Error )
-  FT_Stroker_ConicTo( FT_Stroker  stroker,
-                      FT_Vector*  control,
-                      FT_Vector*  to );
-
- -

‘Draw’ a single quadratic Bezier in the stroker's current sub-path, from the last position.

-

input

- - - - - -
stroker -

The target stroker handle.

-
control -

A pointer to a Bezier control point.

-
to -

A pointer to the destination point.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

You should call this function between FT_Stroker_BeginSubPath and FT_Stroker_EndSubPath.

-
- -

FT_Stroker_CubicTo

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( FT_Error )
-  FT_Stroker_CubicTo( FT_Stroker  stroker,
-                      FT_Vector*  control1,
-                      FT_Vector*  control2,
-                      FT_Vector*  to );
-
- -

‘Draw’ a single cubic Bezier in the stroker's current sub-path, from the last position.

-

input

- - - - - - -
stroker -

The target stroker handle.

-
control1 -

A pointer to the first Bezier control point.

-
control2 -

A pointer to second Bezier control point.

-
to -

A pointer to the destination point.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

You should call this function between FT_Stroker_BeginSubPath and FT_Stroker_EndSubPath.

-
- -

FT_Stroker_GetBorderCounts

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( FT_Error )
-  FT_Stroker_GetBorderCounts( FT_Stroker        stroker,
-                              FT_StrokerBorder  border,
-                              FT_UInt          *anum_points,
-                              FT_UInt          *anum_contours );
-
- -

Call this function once you have finished parsing your paths with the stroker. It returns the number of points and contours necessary to export one of the ‘border’ or ‘stroke’ outlines generated by the stroker.

-

input

- - - - -
stroker -

The target stroker handle.

-
border -

The border index.

-
- -

output

- - - - -
anum_points -

The number of points.

-
anum_contours -

The number of contours.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

When an outline, or a sub-path, is ‘closed’, the stroker generates two independent ‘border’ outlines, named ‘left’ and ‘right’.

-

When the outline, or a sub-path, is ‘opened’, the stroker merges the ‘border’ outlines with caps. The ‘left’ border receives all points, while the ‘right’ border becomes empty.

-

Use the function FT_Stroker_GetCounts instead if you want to retrieve the counts associated to both borders.

-
- -

FT_Stroker_ExportBorder

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( void )
-  FT_Stroker_ExportBorder( FT_Stroker        stroker,
-                           FT_StrokerBorder  border,
-                           FT_Outline*       outline );
-
- -

Call this function after FT_Stroker_GetBorderCounts to export the corresponding border to your own FT_Outline structure.

-

Note that this function appends the border points and contours to your outline, but does not try to resize its arrays.

-

input

- - - - - -
stroker -

The target stroker handle.

-
border -

The border index.

-
outline -

The target outline handle.

-
- -

note

- -

Always call this function after FT_Stroker_GetBorderCounts to get sure that there is enough room in your FT_Outline object to receive all new data.

-

When an outline, or a sub-path, is ‘closed’, the stroker generates two independent ‘border’ outlines, named ‘left’ and ‘right’.

-

When the outline, or a sub-path, is ‘opened’, the stroker merges the ‘border’ outlines with caps. The ‘left’ border receives all points, while the ‘right’ border becomes empty.

-

Use the function FT_Stroker_Export instead if you want to retrieve all borders at once.

-
- -

FT_Stroker_GetCounts

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( FT_Error )
-  FT_Stroker_GetCounts( FT_Stroker  stroker,
-                        FT_UInt    *anum_points,
-                        FT_UInt    *anum_contours );
-
- -

Call this function once you have finished parsing your paths with the stroker. It returns the number of points and contours necessary to export all points/borders from the stroked outline/path.

-

input

- - - -
stroker -

The target stroker handle.

-
- -

output

- - - - -
anum_points -

The number of points.

-
anum_contours -

The number of contours.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FT_Stroker_Export

-

Defined in FT_STROKER_H (freetype/ftstroke.h).

-
  FT_EXPORT( void )
-  FT_Stroker_Export( FT_Stroker   stroker,
-                     FT_Outline*  outline );
-
- -

Call this function after FT_Stroker_GetBorderCounts to export all borders to your own FT_Outline structure.

-

Note that this function appends the border points and contours to your outline, but does not try to resize its arrays.

-

input

- - - - -
stroker -

The target stroker handle.

-
outline -

The target outline handle.

-
- -
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-glyph_variants.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-glyph_variants.html deleted file mode 100644 index 144fc2f33..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-glyph_variants.html +++ /dev/null @@ -1,1387 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Unicode Variation Sequences - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Core API » Unicode Variation Sequences

-
-

Unicode Variation Sequences

-

Synopsis

-

Many characters, especially for CJK scripts, have variant forms. They are a sort of grey area somewhere between being totally irrelevant and semantically distinct; for this reason, the Unicode consortium decided to introduce Variation Sequences (VS), consisting of a Unicode base character and a variation selector instead of further extending the already huge number of characters.

-

Unicode maintains two different sets, namely ‘Standardized Variation Sequences’ and registered ‘Ideographic Variation Sequences’ (IVS), collected in the ‘Ideographic Variation Database’ (IVD).

-

https://unicode.org/Public/UCD/latest/ucd/StandardizedVariants.txt https://unicode.org/reports/tr37/ https://unicode.org/ivd/

-

To date (January 2017), the character with the most ideographic variations is U+9089, having 32 such IVS.

-

Three Mongolian Variation Selectors have the values U+180B-U+180D; 256 generic Variation Selectors are encoded in the ranges U+FE00-U+FE0F and U+E0100-U+E01EF. IVS currently use Variation Selectors from the range U+E0100-U+E01EF only.

-

A VS consists of the base character value followed by a single Variation Selector. For example, to get the first variation of U+9089, you have to write the character sequence U+9089 U+E0100.

-

Adobe and MS decided to support both standardized and ideographic VS with a new cmap subtable (format 14). It is an odd subtable because it is not a mapping of input code points to glyphs, but contains lists of all variations supported by the font.

-

A variation may be either ‘default’ or ‘non-default’ for a given font. A default variation is the one you will get for that code point if you look it up in the standard Unicode cmap. A non-default variation is a different glyph.

-

FT_Face_GetCharVariantIndex

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_UInt )
-  FT_Face_GetCharVariantIndex( FT_Face   face,
-                               FT_ULong  charcode,
-                               FT_ULong  variantSelector );
-
- -

Return the glyph index of a given character code as modified by the variation selector.

-

input

- - - - - -
face -

A handle to the source face object.

-
charcode -

The character code point in Unicode.

-
variantSelector -

The Unicode code point of the variation selector.

-
- -

return

- -

The glyph index. 0 means either ‘undefined character code’, or ‘undefined selector code’, or ‘no variation selector cmap subtable’, or ‘current CharMap is not Unicode’.

-

note

- -

If you use FreeType to manipulate the contents of font files directly, be aware that the glyph index returned by this function doesn't always correspond to the internal indices used within the file. This is done to ensure that value 0 always corresponds to the ‘missing glyph’.

-

This function is only meaningful if a) the font has a variation selector cmap sub table, and b) the current charmap has a Unicode encoding.

-

since

- -

2.3.6

-
- -

FT_Face_GetCharVariantIsDefault

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Int )
-  FT_Face_GetCharVariantIsDefault( FT_Face   face,
-                                   FT_ULong  charcode,
-                                   FT_ULong  variantSelector );
-
- -

Check whether this variation of this Unicode character is the one to be found in the charmap.

-

input

- - - - - -
face -

A handle to the source face object.

-
charcode -

The character codepoint in Unicode.

-
variantSelector -

The Unicode codepoint of the variation selector.

-
- -

return

- -

1 if found in the standard (Unicode) cmap, 0 if found in the variation selector cmap, or -1 if it is not a variation.

-

note

- -

This function is only meaningful if the font has a variation selector cmap subtable.

-

since

- -

2.3.6

-
- -

FT_Face_GetVariantSelectors

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_UInt32* )
-  FT_Face_GetVariantSelectors( FT_Face  face );
-
- -

Return a zero-terminated list of Unicode variation selectors found in the font.

-

input

- - - -
face -

A handle to the source face object.

-
- -

return

- -

A pointer to an array of selector code points, or NULL if there is no valid variation selector cmap subtable.

-

note

- -

The last item in the array is 0; the array is owned by the FT_Face object but can be overwritten or released on the next call to a FreeType function.

-

since

- -

2.3.6

-
- -

FT_Face_GetVariantsOfChar

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_UInt32* )
-  FT_Face_GetVariantsOfChar( FT_Face   face,
-                             FT_ULong  charcode );
-
- -

Return a zero-terminated list of Unicode variation selectors found for the specified character code.

-

input

- - - - -
face -

A handle to the source face object.

-
charcode -

The character codepoint in Unicode.

-
- -

return

- -

A pointer to an array of variation selector code points that are active for the given character, or NULL if the corresponding list is empty.

-

note

- -

The last item in the array is 0; the array is owned by the FT_Face object but can be overwritten or released on the next call to a FreeType function.

-

since

- -

2.3.6

-
- -

FT_Face_GetCharsOfVariant

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_UInt32* )
-  FT_Face_GetCharsOfVariant( FT_Face   face,
-                             FT_ULong  variantSelector );
-
- -

Return a zero-terminated list of Unicode character codes found for the specified variation selector.

-

input

- - - - -
face -

A handle to the source face object.

-
variantSelector -

The variation selector code point in Unicode.

-
- -

return

- -

A list of all the code points that are specified by this selector (both default and non-default codes are returned) or NULL if there is no valid cmap or the variation selector is invalid.

-

note

- -

The last item in the array is 0; the array is owned by the FT_Face object but can be overwritten or released on the next call to a FreeType function.

-

since

- -

2.3.6

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-gx_validation.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-gx_validation.html deleted file mode 100644 index 37e026f02..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-gx_validation.html +++ /dev/null @@ -1,1478 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TrueTypeGX/AAT Validation - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
- -
-
- - -
-
- - - -

FreeType » Docs » Miscellaneous » TrueTypeGX/AAT Validation

-
-

TrueTypeGX/AAT Validation

-

Synopsis

-

This section contains the declaration of functions to validate some TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd, trak, prop, lcar).

-

FT_TrueTypeGX_Validate

-

Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h).

-
  FT_EXPORT( FT_Error )
-  FT_TrueTypeGX_Validate( FT_Face   face,
-                          FT_UInt   validation_flags,
-                          FT_Bytes  tables[FT_VALIDATE_GX_LENGTH],
-                          FT_UInt   table_length );
-
- -

Validate various TrueTypeGX tables to assure that all offsets and indices are valid. The idea is that a higher-level library that actually does the text layout can access those tables without error checking (which can be quite time consuming).

-

input

- - - - - -
face -

A handle to the input face.

-
validation_flags -

A bit field that specifies the tables to be validated. See FT_VALIDATE_GXXXX for possible values.

-
table_length -

The size of the tables array. Normally, FT_VALIDATE_GX_LENGTH should be passed.

-
- -

output

- - - -
tables -

The array where all validated sfnt tables are stored. The array itself must be allocated by a client.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function only works with TrueTypeGX fonts, returning an error otherwise.

-

After use, the application should deallocate the buffers pointed to by each tables element, by calling FT_TrueTypeGX_Free. A NULL value indicates that the table either doesn't exist in the font, the application hasn't asked for validation, or the validator doesn't have the ability to validate the sfnt table.

-
- -

FT_TrueTypeGX_Free

-

Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h).

-
  FT_EXPORT( void )
-  FT_TrueTypeGX_Free( FT_Face   face,
-                      FT_Bytes  table );
-
- -

Free the buffer allocated by TrueTypeGX validator.

-

input

- - - - -
face -

A handle to the input face.

-
table -

The pointer to the buffer allocated by FT_TrueTypeGX_Validate.

-
- -

note

- -

This function must be used to free the buffer allocated by FT_TrueTypeGX_Validate only.

-
- -

FT_ClassicKern_Validate

-

Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h).

-
  FT_EXPORT( FT_Error )
-  FT_ClassicKern_Validate( FT_Face    face,
-                           FT_UInt    validation_flags,
-                           FT_Bytes  *ckern_table );
-
- -

Validate classic (16-bit format) kern table to assure that the offsets and indices are valid. The idea is that a higher-level library that actually does the text layout can access those tables without error checking (which can be quite time consuming).

-

The ‘kern’ table validator in FT_TrueTypeGX_Validate deals with both the new 32-bit format and the classic 16-bit format, while FT_ClassicKern_Validate only supports the classic 16-bit format.

-

input

- - - - -
face -

A handle to the input face.

-
validation_flags -

A bit field that specifies the dialect to be validated. See FT_VALIDATE_CKERNXXX for possible values.

-
- -

output

- - - -
ckern_table -

A pointer to the kern table.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

After use, the application should deallocate the buffers pointed to by ckern_table, by calling FT_ClassicKern_Free. A NULL value indicates that the table doesn't exist in the font.

-
- -

FT_ClassicKern_Free

-

Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h).

-
  FT_EXPORT( void )
-  FT_ClassicKern_Free( FT_Face   face,
-                       FT_Bytes  table );
-
- -

Free the buffer allocated by classic Kern validator.

-

input

- - - - -
face -

A handle to the input face.

-
table -

The pointer to the buffer that is allocated by FT_ClassicKern_Validate.

-
- -

note

- -

This function must be used to free the buffer allocated by FT_ClassicKern_Validate only.

-
- -

FT_VALIDATE_GX_LENGTH

-

Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h).

-
#define FT_VALIDATE_GX_LENGTH  ( FT_VALIDATE_GX_LAST_INDEX + 1 )
-
- -

The number of tables checked in this module. Use it as a parameter for the table-length argument of function FT_TrueTypeGX_Validate.

-
- -

FT_VALIDATE_GXXXX

-

Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h).

-
#define FT_VALIDATE_feat  FT_VALIDATE_GX_BITFIELD( feat )
-#define FT_VALIDATE_mort  FT_VALIDATE_GX_BITFIELD( mort )
-#define FT_VALIDATE_morx  FT_VALIDATE_GX_BITFIELD( morx )
-#define FT_VALIDATE_bsln  FT_VALIDATE_GX_BITFIELD( bsln )
-#define FT_VALIDATE_just  FT_VALIDATE_GX_BITFIELD( just )
-#define FT_VALIDATE_kern  FT_VALIDATE_GX_BITFIELD( kern )
-#define FT_VALIDATE_opbd  FT_VALIDATE_GX_BITFIELD( opbd )
-#define FT_VALIDATE_trak  FT_VALIDATE_GX_BITFIELD( trak )
-#define FT_VALIDATE_prop  FT_VALIDATE_GX_BITFIELD( prop )
-#define FT_VALIDATE_lcar  FT_VALIDATE_GX_BITFIELD( lcar )
-
-#define FT_VALIDATE_GX  ( FT_VALIDATE_feat | \
-                          FT_VALIDATE_mort | \
-                          FT_VALIDATE_morx | \
-                          FT_VALIDATE_bsln | \
-                          FT_VALIDATE_just | \
-                          FT_VALIDATE_kern | \
-                          FT_VALIDATE_opbd | \
-                          FT_VALIDATE_trak | \
-                          FT_VALIDATE_prop | \
-                          FT_VALIDATE_lcar )
-
- -

A list of bit-field constants used with FT_TrueTypeGX_Validate to indicate which TrueTypeGX/AAT Type tables should be validated.

-

values

- - - - - - - - - - - - - -
FT_VALIDATE_feat -

Validate ‘feat’ table.

-
FT_VALIDATE_mort -

Validate ‘mort’ table.

-
FT_VALIDATE_morx -

Validate ‘morx’ table.

-
FT_VALIDATE_bsln -

Validate ‘bsln’ table.

-
FT_VALIDATE_just -

Validate ‘just’ table.

-
FT_VALIDATE_kern -

Validate ‘kern’ table.

-
FT_VALIDATE_opbd -

Validate ‘opbd’ table.

-
FT_VALIDATE_trak -

Validate ‘trak’ table.

-
FT_VALIDATE_prop -

Validate ‘prop’ table.

-
FT_VALIDATE_lcar -

Validate ‘lcar’ table.

-
FT_VALIDATE_GX -

Validate all TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd, trak, prop and lcar).

-
- -
- -

FT_VALIDATE_CKERNXXX

-

Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h).

-
#define FT_VALIDATE_MS     ( FT_VALIDATE_GX_START << 0 )
-#define FT_VALIDATE_APPLE  ( FT_VALIDATE_GX_START << 1 )
-
-#define FT_VALIDATE_CKERN  ( FT_VALIDATE_MS | FT_VALIDATE_APPLE )
-
- -

A list of bit-field constants used with FT_ClassicKern_Validate to indicate the classic kern dialect or dialects. If the selected type doesn't fit, FT_ClassicKern_Validate regards the table as invalid.

-

values

- - - - - -
FT_VALIDATE_MS -

Handle the ‘kern’ table as a classic Microsoft kern table.

-
FT_VALIDATE_APPLE -

Handle the ‘kern’ table as a classic Apple kern table.

-
FT_VALIDATE_CKERN -

Handle the ‘kern’ as either classic Apple or Microsoft kern table.

-
- -
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-gzip.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-gzip.html deleted file mode 100644 index d6f1f2ce6..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-gzip.html +++ /dev/null @@ -1,1266 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GZIP Streams - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Support API » GZIP Streams

-
-

GZIP Streams

-

Synopsis

-

In certain builds of the library, gzip compression recognition is automatically handled when calling FT_New_Face or FT_Open_Face. This means that if no font driver is capable of handling the raw compressed file, the library will try to open a gzipped stream from it and re-open the face with it.

-

The stream implementation is very basic and resets the decompression process each time seeking backwards is needed within the stream, which significantly undermines the performance.

-

This section contains the declaration of Gzip-specific functions.

-

FT_Stream_OpenGzip

-

Defined in FT_GZIP_H (freetype/ftgzip.h).

-
  FT_EXPORT( FT_Error )
-  FT_Stream_OpenGzip( FT_Stream  stream,
-                      FT_Stream  source );
-
- -

Open a new stream to parse gzip-compressed font files. This is mainly used to support the compressed *.pcf.gz fonts that come with XFree86.

-

input

- - - - -
stream -

The target embedding stream.

-
source -

The source stream.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The source stream must be opened before calling this function.

-

Calling the internal function FT_Stream_Close on the new stream will not call FT_Stream_Close on the source stream. None of the stream objects will be released to the heap.

-

This function may return FT_Err_Unimplemented_Feature if your build of FreeType was not compiled with zlib support.

-
- -

FT_Gzip_Uncompress

-

Defined in FT_GZIP_H (freetype/ftgzip.h).

-
  FT_EXPORT( FT_Error )
-  FT_Gzip_Uncompress( FT_Memory       memory,
-                      FT_Byte*        output,
-                      FT_ULong*       output_len,
-                      const FT_Byte*  input,
-                      FT_ULong        input_len );
-
- -

Decompress a zipped input buffer into an output buffer. This function is modeled after zlib's uncompress function.

-

input

- - - - - -
memory -

A FreeType memory handle.

-
input -

The input buffer.

-
input_len -

The length of the input buffer.

-
- -

output

- - - -
output -

The output buffer.

-
- -

inout

- - - -
output_len -

Before calling the function, this is the total size of the output buffer, which must be large enough to hold the entire uncompressed data (so the size of the uncompressed data must be known in advance). After calling the function, output_len is the size of the used data in output.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function may return FT_Err_Unimplemented_Feature if your build of FreeType was not compiled with zlib support.

-

since

- -

2.5.1

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-header_file_macros.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-header_file_macros.html deleted file mode 100644 index f056cbed8..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-header_file_macros.html +++ /dev/null @@ -1,2215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Header File Macros - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Core API » Header File Macros

-
-

Header File Macros

-

Synopsis

-

In addition to the normal scheme of including header files like -

  #include <freetype/freetype.h>
-  #include <freetype/ftmm.h>
-  #include <freetype/ftglyph.h>
-

-

it is possible to used named macros instead. They can be used directly in #include statements as in -

  #include FT_FREETYPE_H
-  #include FT_MULTIPLE_MASTERS_H
-  #include FT_GLYPH_H
-

-

These macros were introduced to overcome the infamous 8.3 naming rule required by DOS (and FT_MULTIPLE_MASTERS_H is a lot more meaningful than ftmm.h).

-

FT_CONFIG_CONFIG_H

-
#ifndef FT_CONFIG_CONFIG_H
-#define FT_CONFIG_CONFIG_H  <freetype/config/ftconfig.h>
-#endif
-
- -

A macro used in #include statements to name the file containing FreeType 2 configuration data.

-
- -

FT_CONFIG_STANDARD_LIBRARY_H

-
#ifndef FT_CONFIG_STANDARD_LIBRARY_H
-#define FT_CONFIG_STANDARD_LIBRARY_H  <freetype/config/ftstdlib.h>
-#endif
-
- -

A macro used in #include statements to name the file containing FreeType 2 interface to the standard C library functions.

-
- -

FT_CONFIG_OPTIONS_H

-
#ifndef FT_CONFIG_OPTIONS_H
-#define FT_CONFIG_OPTIONS_H  <freetype/config/ftoption.h>
-#endif
-
- -

A macro used in #include statements to name the file containing FreeType 2 project-specific configuration options.

-
- -

FT_CONFIG_MODULES_H

-
#ifndef FT_CONFIG_MODULES_H
-#define FT_CONFIG_MODULES_H  <freetype/config/ftmodule.h>
-#endif
-
- -

A macro used in #include statements to name the file containing the list of FreeType 2 modules that are statically linked to new library instances in FT_Init_FreeType.

-
- -

FT_FREETYPE_H

-
#define FT_FREETYPE_H  <freetype/freetype.h>
-
- -

A macro used in #include statements to name the file containing the base FreeType 2 API.

-
- -

FT_ERRORS_H

-
#define FT_ERRORS_H  <freetype/fterrors.h>
-
- -

A macro used in #include statements to name the file containing the list of FreeType 2 error codes (and messages).

-

It is included by FT_FREETYPE_H.

-
- -

FT_MODULE_ERRORS_H

-
#define FT_MODULE_ERRORS_H  <freetype/ftmoderr.h>
-
- -

A macro used in #include statements to name the file containing the list of FreeType 2 module error offsets (and messages).

-
- -

FT_SYSTEM_H

-
#define FT_SYSTEM_H  <freetype/ftsystem.h>
-
- -

A macro used in #include statements to name the file containing the FreeType 2 interface to low-level operations (i.e., memory management and stream i/o).

-

It is included by FT_FREETYPE_H.

-
- -

FT_IMAGE_H

-
#define FT_IMAGE_H  <freetype/ftimage.h>
-
- -

A macro used in #include statements to name the file containing type definitions related to glyph images (i.e., bitmaps, outlines, scan-converter parameters).

-

It is included by FT_FREETYPE_H.

-
- -

FT_TYPES_H

-
#define FT_TYPES_H  <freetype/fttypes.h>
-
- -

A macro used in #include statements to name the file containing the basic data types defined by FreeType 2.

-

It is included by FT_FREETYPE_H.

-
- -

FT_LIST_H

-
#define FT_LIST_H  <freetype/ftlist.h>
-
- -

A macro used in #include statements to name the file containing the list management API of FreeType 2.

-

(Most applications will never need to include this file.)

-
- -

FT_OUTLINE_H

-
#define FT_OUTLINE_H  <freetype/ftoutln.h>
-
- -

A macro used in #include statements to name the file containing the scalable outline management API of FreeType 2.

-
- -

FT_SIZES_H

-
#define FT_SIZES_H  <freetype/ftsizes.h>
-
- -

A macro used in #include statements to name the file containing the API which manages multiple FT_Size objects per face.

-
- -

FT_MODULE_H

-
#define FT_MODULE_H  <freetype/ftmodapi.h>
-
- -

A macro used in #include statements to name the file containing the module management API of FreeType 2.

-
- -

FT_RENDER_H

-
#define FT_RENDER_H  <freetype/ftrender.h>
-
- -

A macro used in #include statements to name the file containing the renderer module management API of FreeType 2.

-
- -

FT_DRIVER_H

-
#define FT_DRIVER_H  <freetype/ftdriver.h>
-
- -

A macro used in #include statements to name the file containing structures and macros related to the driver modules.

-
- -

FT_AUTOHINTER_H

-
#define FT_AUTOHINTER_H  FT_DRIVER_H
-
- -

A macro used in #include statements to name the file containing structures and macros related to the auto-hinting module.

-

Deprecated since version 2.9; use FT_DRIVER_H instead.

-
- -

FT_CFF_DRIVER_H

-
#define FT_CFF_DRIVER_H  FT_DRIVER_H
-
- -

A macro used in #include statements to name the file containing structures and macros related to the CFF driver module.

-

Deprecated since version 2.9; use FT_DRIVER_H instead.

-
- -

FT_TRUETYPE_DRIVER_H

-
#define FT_TRUETYPE_DRIVER_H  FT_DRIVER_H
-
- -

A macro used in #include statements to name the file containing structures and macros related to the TrueType driver module.

-

Deprecated since version 2.9; use FT_DRIVER_H instead.

-
- -

FT_PCF_DRIVER_H

-
#define FT_PCF_DRIVER_H  FT_DRIVER_H
-
- -

A macro used in #include statements to name the file containing structures and macros related to the PCF driver module.

-

Deprecated since version 2.9; use FT_DRIVER_H instead.

-
- -

FT_TYPE1_TABLES_H

-
#define FT_TYPE1_TABLES_H  <freetype/t1tables.h>
-
- -

A macro used in #include statements to name the file containing the types and API specific to the Type 1 format.

-
- -

FT_TRUETYPE_IDS_H

-
#define FT_TRUETYPE_IDS_H  <freetype/ttnameid.h>
-
- -

A macro used in #include statements to name the file containing the enumeration values which identify name strings, languages, encodings, etc. This file really contains a large set of constant macro definitions, taken from the TrueType and OpenType specifications.

-
- -

FT_TRUETYPE_TABLES_H

-
#define FT_TRUETYPE_TABLES_H  <freetype/tttables.h>
-
- -

A macro used in #include statements to name the file containing the types and API specific to the TrueType (as well as OpenType) format.

-
- -

FT_TRUETYPE_TAGS_H

-
#define FT_TRUETYPE_TAGS_H  <freetype/tttags.h>
-
- -

A macro used in #include statements to name the file containing the definitions of TrueType four-byte ‘tags’ which identify blocks in SFNT-based font formats (i.e., TrueType and OpenType).

-
- -

FT_BDF_H

-
#define FT_BDF_H  <freetype/ftbdf.h>
-
- -

A macro used in #include statements to name the file containing the definitions of an API which accesses BDF-specific strings from a face.

-
- -

FT_CID_H

-
#define FT_CID_H  <freetype/ftcid.h>
-
- -

A macro used in #include statements to name the file containing the definitions of an API which access CID font information from a face.

-
- -

FT_GZIP_H

-
#define FT_GZIP_H  <freetype/ftgzip.h>
-
- -

A macro used in #include statements to name the file containing the definitions of an API which supports gzip-compressed files.

-
- -

FT_LZW_H

-
#define FT_LZW_H  <freetype/ftlzw.h>
-
- -

A macro used in #include statements to name the file containing the definitions of an API which supports LZW-compressed files.

-
- -

FT_BZIP2_H

-
#define FT_BZIP2_H  <freetype/ftbzip2.h>
-
- -

A macro used in #include statements to name the file containing the definitions of an API which supports bzip2-compressed files.

-
- -

FT_WINFONTS_H

-
#define FT_WINFONTS_H   <freetype/ftwinfnt.h>
-
- -

A macro used in #include statements to name the file containing the definitions of an API which supports Windows FNT files.

-
- -

FT_GLYPH_H

-
#define FT_GLYPH_H  <freetype/ftglyph.h>
-
- -

A macro used in #include statements to name the file containing the API of the optional glyph management component.

-
- -

FT_BITMAP_H

-
#define FT_BITMAP_H  <freetype/ftbitmap.h>
-
- -

A macro used in #include statements to name the file containing the API of the optional bitmap conversion component.

-
- -

FT_BBOX_H

-
#define FT_BBOX_H  <freetype/ftbbox.h>
-
- -

A macro used in #include statements to name the file containing the API of the optional exact bounding box computation routines.

-
- -

FT_CACHE_H

-
#define FT_CACHE_H  <freetype/ftcache.h>
-
- -

A macro used in #include statements to name the file containing the API of the optional FreeType 2 cache sub-system.

-
- -

FT_MAC_H

-
#define FT_MAC_H  <freetype/ftmac.h>
-
- -

A macro used in #include statements to name the file containing the Macintosh-specific FreeType 2 API. The latter is used to access fonts embedded in resource forks.

-

This header file must be explicitly included by client applications compiled on the Mac (note that the base API still works though).

-
- -

FT_MULTIPLE_MASTERS_H

-
#define FT_MULTIPLE_MASTERS_H  <freetype/ftmm.h>
-
- -

A macro used in #include statements to name the file containing the optional multiple-masters management API of FreeType 2.

-
- -

FT_SFNT_NAMES_H

-
#define FT_SFNT_NAMES_H  <freetype/ftsnames.h>
-
- -

A macro used in #include statements to name the file containing the optional FreeType 2 API which accesses embedded ‘name’ strings in SFNT-based font formats (i.e., TrueType and OpenType).

-
- -

FT_OPENTYPE_VALIDATE_H

-
#define FT_OPENTYPE_VALIDATE_H  <freetype/ftotval.h>
-
- -

A macro used in #include statements to name the file containing the optional FreeType 2 API which validates OpenType tables (‘BASE’, ‘GDEF’, ‘GPOS’, ‘GSUB’, ‘JSTF’).

-
- -

FT_GX_VALIDATE_H

-
#define FT_GX_VALIDATE_H  <freetype/ftgxval.h>
-
- -

A macro used in #include statements to name the file containing the optional FreeType 2 API which validates TrueTypeGX/AAT tables (‘feat’, ‘mort’, ‘morx’, ‘bsln’, ‘just’, ‘kern’, ‘opbd’, ‘trak’, ‘prop’).

-
- -

FT_PFR_H

-
#define FT_PFR_H  <freetype/ftpfr.h>
-
- -

A macro used in #include statements to name the file containing the FreeType 2 API which accesses PFR-specific data.

-
- -

FT_STROKER_H

-
#define FT_STROKER_H  <freetype/ftstroke.h>
-
- -

A macro used in #include statements to name the file containing the FreeType 2 API which provides functions to stroke outline paths.

-
- -

FT_SYNTHESIS_H

-
#define FT_SYNTHESIS_H  <freetype/ftsynth.h>
-
- -

A macro used in #include statements to name the file containing the FreeType 2 API which performs artificial obliquing and emboldening.

-
- -

FT_FONT_FORMATS_H

-
#define FT_FONT_FORMATS_H  <freetype/ftfntfmt.h>
-
-  /* deprecated */
-#define FT_XFREE86_H  FT_FONT_FORMATS_H
-
- -

A macro used in #include statements to name the file containing the FreeType 2 API which provides functions specific to font formats.

-
- -

FT_TRIGONOMETRY_H

-
#define FT_TRIGONOMETRY_H  <freetype/fttrigon.h>
-
- -

A macro used in #include statements to name the file containing the FreeType 2 API which performs trigonometric computations (e.g., cosines and arc tangents).

-
- -

FT_LCD_FILTER_H

-
#define FT_LCD_FILTER_H  <freetype/ftlcdfil.h>
-
- -

A macro used in #include statements to name the file containing the FreeType 2 API which performs color filtering for subpixel rendering.

-
- -

FT_INCREMENTAL_H

-
#define FT_INCREMENTAL_H  <freetype/ftincrem.h>
-
- -

A macro used in #include statements to name the file containing the FreeType 2 API which performs incremental glyph loading.

-
- -

FT_GASP_H

-
#define FT_GASP_H  <freetype/ftgasp.h>
-
- -

A macro used in #include statements to name the file containing the FreeType 2 API which returns entries from the TrueType GASP table.

-
- -

FT_ADVANCES_H

-
#define FT_ADVANCES_H  <freetype/ftadvanc.h>
-
- -

A macro used in #include statements to name the file containing the FreeType 2 API which returns individual and ranged glyph advances.

-
- -

FT_COLOR_H

-
#define FT_COLOR_H  <freetype/ftcolor.h>
-
- -

A macro used in #include statements to name the file containing the FreeType 2 API which handles the OpenType ‘CPAL’ table.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-header_inclusion.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-header_inclusion.html deleted file mode 100644 index af8ed04a4..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-header_inclusion.html +++ /dev/null @@ -1,1161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FreeType's header inclusion scheme - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » General Remarks » FreeType's header inclusion scheme

-
-

FreeType's header inclusion scheme

-

Synopsis

-

To be as flexible as possible (and for historical reasons), you must load file ft2build.h first before other header files, for example -

  #include <ft2build.h>
-
-  #include <freetype/freetype.h>
-  #include <freetype/ftoutln.h>
-

- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-incremental.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-incremental.html deleted file mode 100644 index c09851bab..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-incremental.html +++ /dev/null @@ -1,1507 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Incremental Loading - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Miscellaneous » Incremental Loading

-
-

Incremental Loading

-

Synopsis

-

This section contains various functions used to perform so-called ‘incremental’ glyph loading. This is a mode where all glyphs loaded from a given FT_Face are provided by the client application.

-

Apart from that, all other tables are loaded normally from the font file. This mode is useful when FreeType is used within another engine, e.g., a PostScript Imaging Processor.

-

To enable this mode, you must use FT_Open_Face, passing an FT_Parameter with the FT_PARAM_TAG_INCREMENTAL tag and an FT_Incremental_Interface value. See the comments for FT_Incremental_InterfaceRec for an example.

-

FT_Incremental

-

Defined in FT_INCREMENTAL_H (freetype/ftincrem.h).

-
  typedef struct FT_IncrementalRec_*  FT_Incremental;
-
- -

An opaque type describing a user-provided object used to implement ‘incremental’ glyph loading within FreeType. This is used to support embedded fonts in certain environments (e.g., PostScript interpreters), where the glyph data isn't in the font file, or must be overridden by different values.

-

note

- -

It is up to client applications to create and implement FT_Incremental objects, as long as they provide implementations for the methods FT_Incremental_GetGlyphDataFunc, FT_Incremental_FreeGlyphDataFunc and FT_Incremental_GetGlyphMetricsFunc.

-

See the description of FT_Incremental_InterfaceRec to understand how to use incremental objects with FreeType.

-
- -

FT_Incremental_MetricsRec

-

Defined in FT_INCREMENTAL_H (freetype/ftincrem.h).

-
  typedef struct  FT_Incremental_MetricsRec_
-  {
-    FT_Long  bearing_x;
-    FT_Long  bearing_y;
-    FT_Long  advance;
-    FT_Long  advance_v;     /* since 2.3.12 */
-
-  } FT_Incremental_MetricsRec;
-
- -

A small structure used to contain the basic glyph metrics returned by the FT_Incremental_GetGlyphMetricsFunc method.

-

fields

- - - - - - -
bearing_x -

Left bearing, in font units.

-
bearing_y -

Top bearing, in font units.

-
advance -

Horizontal component of glyph advance, in font units.

-
advance_v -

Vertical component of glyph advance, in font units.

-
- -

note

- -

These correspond to horizontal or vertical metrics depending on the value of the vertical argument to the function FT_Incremental_GetGlyphMetricsFunc.

-
- -

FT_Incremental_Metrics

-

Defined in FT_INCREMENTAL_H (freetype/ftincrem.h).

-
   typedef struct FT_Incremental_MetricsRec_*  FT_Incremental_Metrics;
-
- -

A handle to an FT_Incremental_MetricsRec structure.

-
- -

FT_Incremental_GetGlyphDataFunc

-

Defined in FT_INCREMENTAL_H (freetype/ftincrem.h).

-
  typedef FT_Error
-  (*FT_Incremental_GetGlyphDataFunc)( FT_Incremental  incremental,
-                                      FT_UInt         glyph_index,
-                                      FT_Data*        adata );
-
- -

A function called by FreeType to access a given glyph's data bytes during FT_Load_Glyph or FT_Load_Char if incremental loading is enabled.

-

Note that the format of the glyph's data bytes depends on the font file format. For TrueType, it must correspond to the raw bytes within the ‘glyf’ table. For PostScript formats, it must correspond to the unencrypted charstring bytes, without any lenIV header. It is undefined for any other format.

-

input

- - - - -
incremental -

Handle to an opaque FT_Incremental handle provided by the client application.

-
glyph_index -

Index of relevant glyph.

-
- -

output

- - - -
adata -

A structure describing the returned glyph data bytes (which will be accessed as a read-only byte block).

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

If this function returns successfully the method FT_Incremental_FreeGlyphDataFunc will be called later to release the data bytes.

-

Nested calls to FT_Incremental_GetGlyphDataFunc can happen for compound glyphs.

-
- -

FT_Incremental_FreeGlyphDataFunc

-

Defined in FT_INCREMENTAL_H (freetype/ftincrem.h).

-
  typedef void
-  (*FT_Incremental_FreeGlyphDataFunc)( FT_Incremental  incremental,
-                                       FT_Data*        data );
-
- -

A function used to release the glyph data bytes returned by a successful call to FT_Incremental_GetGlyphDataFunc.

-

input

- - - - -
incremental -

A handle to an opaque FT_Incremental handle provided by the client application.

-
data -

A structure describing the glyph data bytes (which will be accessed as a read-only byte block).

-
- -
- -

FT_Incremental_GetGlyphMetricsFunc

-

Defined in FT_INCREMENTAL_H (freetype/ftincrem.h).

-
  typedef FT_Error
-  (*FT_Incremental_GetGlyphMetricsFunc)
-                      ( FT_Incremental              incremental,
-                        FT_UInt                     glyph_index,
-                        FT_Bool                     vertical,
-                        FT_Incremental_MetricsRec  *ametrics );
-
- -

A function used to retrieve the basic metrics of a given glyph index before accessing its data. This is necessary because, in certain formats like TrueType, the metrics are stored in a different place from the glyph images proper.

-

input

- - - - - - -
incremental -

A handle to an opaque FT_Incremental handle provided by the client application.

-
glyph_index -

Index of relevant glyph.

-
vertical -

If true, return vertical metrics.

-
ametrics -

This parameter is used for both input and output. The original glyph metrics, if any, in font units. If metrics are not available all the values must be set to zero.

-
- -

output

- - - -
ametrics -

The replacement glyph metrics in font units.

-
- -
- -

FT_Incremental_FuncsRec

-

Defined in FT_INCREMENTAL_H (freetype/ftincrem.h).

-
  typedef struct  FT_Incremental_FuncsRec_
-  {
-    FT_Incremental_GetGlyphDataFunc     get_glyph_data;
-    FT_Incremental_FreeGlyphDataFunc    free_glyph_data;
-    FT_Incremental_GetGlyphMetricsFunc  get_glyph_metrics;
-
-  } FT_Incremental_FuncsRec;
-
- -

A table of functions for accessing fonts that load data incrementally. Used in FT_Incremental_InterfaceRec.

-

fields

- - - - - -
get_glyph_data -

The function to get glyph data. Must not be null.

-
free_glyph_data -

The function to release glyph data. Must not be null.

-
get_glyph_metrics -

The function to get glyph metrics. May be null if the font does not provide overriding glyph metrics.

-
- -
- -

FT_Incremental_InterfaceRec

-

Defined in FT_INCREMENTAL_H (freetype/ftincrem.h).

-
  typedef struct  FT_Incremental_InterfaceRec_
-  {
-    const FT_Incremental_FuncsRec*  funcs;
-    FT_Incremental                  object;
-
-  } FT_Incremental_InterfaceRec;
-
- -

A structure to be used with FT_Open_Face to indicate that the user wants to support incremental glyph loading. You should use it with FT_PARAM_TAG_INCREMENTAL as in the following example: -

  FT_Incremental_InterfaceRec  inc_int;
-  FT_Parameter                 parameter;
-  FT_Open_Args                 open_args;
-
-
-  // set up incremental descriptor
-  inc_int.funcs  = my_funcs;
-  inc_int.object = my_object;
-
-  // set up optional parameter
-  parameter.tag  = FT_PARAM_TAG_INCREMENTAL;
-  parameter.data = &inc_int;
-
-  // set up FT_Open_Args structure
-  open_args.flags      = FT_OPEN_PATHNAME | FT_OPEN_PARAMS;
-  open_args.pathname   = my_font_pathname;
-  open_args.num_params = 1;
-  open_args.params     = &parameter; // we use one optional argument
-
-  // open the font
-  error = FT_Open_Face( library, &open_args, index, &face );
-  ...
-

-
- -

FT_Incremental_Interface

-

Defined in FT_INCREMENTAL_H (freetype/ftincrem.h).

-
  typedef FT_Incremental_InterfaceRec*   FT_Incremental_Interface;
-
- -

A pointer to an FT_Incremental_InterfaceRec structure.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-index.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-index.html deleted file mode 100644 index 347eac1da..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-index.html +++ /dev/null @@ -1,2145 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Index - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Global Index

-
-

FreeType-2.10.4 API Reference

-

B

-

BDF_Property
-BDF_PROPERTY_TYPE_ATOM
-BDF_PROPERTY_TYPE_CARDINAL
-BDF_PROPERTY_TYPE_INTEGER
-BDF_PROPERTY_TYPE_NONE
-BDF_PropertyRec
-BDF_PropertyType

-

C

-

CID_FaceDict
-CID_FaceDictRec
-CID_FaceInfo
-CID_FaceInfoRec
-CID_FontDict
-CID_Info

-

D

-

darkening-parameters
-default-script

-

F

-

fallback-script
-FREETYPE_MAJOR
-FREETYPE_MINOR
-FREETYPE_PATCH
-FREETYPE_XXX
-FT_Activate_Size
-FT_Add_Default_Modules
-FT_Add_Module
-FT_ADVANCE_FLAG_FAST_ONLY
-FT_ADVANCES_H
-FT_Alloc_Func
-FT_Angle
-FT_ANGLE_2PI
-FT_Angle_Diff
-FT_ANGLE_PI
-FT_ANGLE_PI2
-FT_ANGLE_PI4
-FT_Atan2
-FT_Attach_File
-FT_Attach_Stream
-FT_AUTOHINTER_H
-FT_AUTOHINTER_SCRIPT_CJK
-FT_AUTOHINTER_SCRIPT_INDIC
-FT_AUTOHINTER_SCRIPT_LATIN
-FT_AUTOHINTER_SCRIPT_NONE
-FT_AUTOHINTER_SCRIPT_XXX
-FT_BBox
-FT_BBOX_H
-FT_BDF_H
-FT_Bitmap
-FT_Bitmap_Blend
-FT_Bitmap_Convert
-FT_Bitmap_Copy
-FT_Bitmap_Done
-FT_Bitmap_Embolden
-FT_BITMAP_H
-FT_Bitmap_Init
-FT_Bitmap_Size
-FT_BitmapGlyph
-FT_BitmapGlyphRec
-FT_Bool
-FT_Byte
-FT_Bytes
-FT_BZIP2_H
-FT_CACHE_H
-FT_CeilFix
-FT_CFF_DRIVER_H
-FT_Char
-FT_CharMap
-FT_CharMapRec
-FT_CID_H
-FT_ClassicKern_Free
-FT_ClassicKern_Validate
-FT_Color
-FT_COLOR_H
-FT_CONFIG_CONFIG_H
-FT_CONFIG_MODULES_H
-FT_CONFIG_OPTIONS_H
-FT_CONFIG_STANDARD_LIBRARY_H
-FT_Cos
-FT_Data
-FT_DEBUG_HOOK_TRUETYPE
-FT_DEBUG_HOOK_XXX
-FT_DebugHook_Func
-FT_DivFix
-FT_Done_Face
-FT_Done_FreeType
-FT_Done_Glyph
-FT_Done_Library
-FT_Done_MM_Var
-FT_Done_Size
-FT_Driver
-FT_DRIVER_H
-FT_ENC_TAG
-FT_Encoding
-FT_ENCODING_ADOBE_CUSTOM
-FT_ENCODING_ADOBE_EXPERT
-FT_ENCODING_ADOBE_LATIN_1
-FT_ENCODING_ADOBE_STANDARD
-FT_ENCODING_APPLE_ROMAN
-FT_ENCODING_BIG5
-FT_ENCODING_JOHAB
-FT_ENCODING_MS_BIG5
-FT_ENCODING_MS_GB2312
-FT_ENCODING_MS_JOHAB
-FT_ENCODING_MS_SJIS
-FT_ENCODING_MS_SYMBOL
-FT_ENCODING_MS_WANSUNG
-FT_ENCODING_NONE
-FT_ENCODING_OLD_LATIN_2
-FT_ENCODING_PRC
-FT_ENCODING_SJIS
-FT_ENCODING_UNICODE
-FT_ENCODING_WANSUNG
-FT_Err_XXX
-FT_Error
-FT_Error_String
-FT_ERRORS_H
-FT_F26Dot6
-FT_F2Dot14
-FT_Face
-FT_Face_CheckTrueTypePatents
-FT_FACE_FLAG_CID_KEYED
-FT_FACE_FLAG_COLOR
-FT_FACE_FLAG_EXTERNAL_STREAM
-FT_FACE_FLAG_FAST_GLYPHS
-FT_FACE_FLAG_FIXED_SIZES
-FT_FACE_FLAG_FIXED_WIDTH
-FT_FACE_FLAG_GLYPH_NAMES
-FT_FACE_FLAG_HINTER
-FT_FACE_FLAG_HORIZONTAL
-FT_FACE_FLAG_KERNING
-FT_FACE_FLAG_MULTIPLE_MASTERS
-FT_FACE_FLAG_SCALABLE
-FT_FACE_FLAG_SFNT
-FT_FACE_FLAG_TRICKY
-FT_FACE_FLAG_VARIATION
-FT_FACE_FLAG_VERTICAL
-FT_FACE_FLAG_XXX
-FT_Face_GetCharsOfVariant
-FT_Face_GetCharVariantIndex
-FT_Face_GetCharVariantIsDefault
-FT_Face_GetVariantSelectors
-FT_Face_GetVariantsOfChar
-FT_Face_Internal
-FT_Face_Properties
-FT_Face_SetUnpatentedHinting
-FT_FaceRec
-FT_Fixed
-FT_FloorFix
-FT_FONT_FORMATS_H
-FT_Free_Func
-FT_FREETYPE_H
-FT_FSTYPE_BITMAP_EMBEDDING_ONLY
-FT_FSTYPE_EDITABLE_EMBEDDING
-FT_FSTYPE_INSTALLABLE_EMBEDDING
-FT_FSTYPE_NO_SUBSETTING
-FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING
-FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING
-FT_FSTYPE_XXX
-FT_FWord
-FT_GASP_DO_GRAY
-FT_GASP_DO_GRIDFIT
-FT_GASP_H
-FT_GASP_NO_TABLE
-FT_GASP_SYMMETRIC_GRIDFIT
-FT_GASP_SYMMETRIC_SMOOTHING
-FT_GASP_XXX
-FT_Generic
-FT_Generic_Finalizer
-FT_Get_Advance
-FT_Get_Advances
-FT_Get_BDF_Charset_ID
-FT_Get_BDF_Property
-FT_Get_Char_Index
-FT_Get_Charmap_Index
-FT_Get_CID_From_Glyph_Index
-FT_Get_CID_Is_Internally_CID_Keyed
-FT_Get_CID_Registry_Ordering_Supplement
-FT_Get_CMap_Format
-FT_Get_CMap_Language_ID
-FT_Get_Color_Glyph_Layer
-FT_Get_First_Char
-FT_Get_Font_Format
-FT_Get_FSType_Flags
-FT_Get_Gasp
-FT_Get_Glyph
-FT_Get_Glyph_Name
-FT_Get_Kerning
-FT_Get_MM_Blend_Coordinates
-FT_Get_MM_Var
-FT_Get_MM_WeightVector
-FT_Get_Module
-FT_Get_Multi_Master
-FT_Get_Name_Index
-FT_Get_Next_Char
-FT_Get_PFR_Advance
-FT_Get_PFR_Kerning
-FT_Get_PFR_Metrics
-FT_Get_Postscript_Name
-FT_Get_PS_Font_Info
-FT_Get_PS_Font_Private
-FT_Get_PS_Font_Value
-FT_Get_Renderer
-FT_Get_Sfnt_LangTag
-FT_Get_Sfnt_Name
-FT_Get_Sfnt_Name_Count
-FT_Get_Sfnt_Table
-FT_Get_SubGlyph_Info
-FT_Get_Track_Kerning
-FT_Get_TrueType_Engine_Type
-FT_Get_Var_Axis_Flags
-FT_Get_Var_Blend_Coordinates
-FT_Get_Var_Design_Coordinates
-FT_Get_WinFNT_Header
-FT_GetFile_From_Mac_ATS_Name
-FT_GetFile_From_Mac_Name
-FT_GetFilePath_From_Mac_ATS_Name
-FT_Glyph
-FT_GLYPH_BBOX_GRIDFIT
-FT_Glyph_BBox_Mode
-FT_GLYPH_BBOX_PIXELS
-FT_GLYPH_BBOX_SUBPIXELS
-FT_GLYPH_BBOX_TRUNCATE
-FT_GLYPH_BBOX_UNSCALED
-FT_Glyph_Copy
-FT_Glyph_Format
-FT_GLYPH_FORMAT_BITMAP
-FT_GLYPH_FORMAT_COMPOSITE
-FT_GLYPH_FORMAT_NONE
-FT_GLYPH_FORMAT_OUTLINE
-FT_GLYPH_FORMAT_PLOTTER
-FT_Glyph_Get_CBox
-FT_GLYPH_H
-FT_Glyph_Metrics
-FT_Glyph_Stroke
-FT_Glyph_StrokeBorder
-FT_Glyph_To_Bitmap
-FT_Glyph_Transform
-FT_GlyphRec
-FT_GlyphSlot
-FT_GlyphSlot_Own_Bitmap
-FT_GlyphSlotRec
-FT_GX_VALIDATE_H
-FT_GZIP_H
-FT_Gzip_Uncompress
-FT_HAS_COLOR
-FT_HAS_FAST_GLYPHS
-FT_HAS_FIXED_SIZES
-FT_HAS_GLYPH_NAMES
-FT_HAS_HORIZONTAL
-FT_HAS_KERNING
-FT_HAS_MULTIPLE_MASTERS
-FT_Has_PS_Glyph_Names
-FT_HAS_VERTICAL
-FT_HINTING_ADOBE
-FT_HINTING_FREETYPE
-FT_HINTING_XXX
-FT_IMAGE_H
-FT_IMAGE_TAG
-FT_Incremental
-FT_Incremental_FreeGlyphDataFunc
-FT_Incremental_FuncsRec
-FT_Incremental_GetGlyphDataFunc
-FT_Incremental_GetGlyphMetricsFunc
-FT_INCREMENTAL_H
-FT_Incremental_Interface
-FT_Incremental_InterfaceRec
-FT_Incremental_Metrics
-FT_Incremental_MetricsRec
-FT_Init_FreeType
-FT_Int
-FT_Int16
-FT_Int32
-FT_Int64
-FT_IS_CID_KEYED
-FT_IS_FIXED_WIDTH
-FT_IS_NAMED_INSTANCE
-FT_IS_SCALABLE
-FT_IS_SFNT
-FT_IS_TRICKY
-FT_IS_VARIATION
-FT_KERNING_DEFAULT
-FT_Kerning_Mode
-FT_KERNING_UNFITTED
-FT_KERNING_UNSCALED
-FT_LayerIterator
-FT_LCD_FILTER_DEFAULT
-FT_LCD_FILTER_H
-FT_LCD_FILTER_LEGACY
-FT_LCD_FILTER_LEGACY1
-FT_LCD_FILTER_LIGHT
-FT_LCD_FILTER_NONE
-FT_LcdFilter
-FT_LcdFiveTapFilter
-FT_Library
-FT_Library_SetLcdFilter
-FT_Library_SetLcdFilterWeights
-FT_Library_SetLcdGeometry
-FT_Library_Version
-FT_List
-FT_List_Add
-FT_List_Destructor
-FT_List_Finalize
-FT_List_Find
-FT_LIST_H
-FT_List_Insert
-FT_List_Iterate
-FT_List_Iterator
-FT_List_Remove
-FT_List_Up
-FT_ListNode
-FT_ListNodeRec
-FT_ListRec
-FT_LOAD_BITMAP_METRICS_ONLY
-FT_Load_Char
-FT_LOAD_COLOR
-FT_LOAD_COMPUTE_METRICS
-FT_LOAD_CROP_BITMAP
-FT_LOAD_DEFAULT
-FT_LOAD_FORCE_AUTOHINT
-FT_Load_Glyph
-FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
-FT_LOAD_IGNORE_TRANSFORM
-FT_LOAD_LINEAR_DESIGN
-FT_LOAD_MONOCHROME
-FT_LOAD_NO_AUTOHINT
-FT_LOAD_NO_BITMAP
-FT_LOAD_NO_HINTING
-FT_LOAD_NO_RECURSE
-FT_LOAD_NO_SCALE
-FT_LOAD_PEDANTIC
-FT_LOAD_RENDER
-FT_Load_Sfnt_Table
-FT_LOAD_TARGET_LCD
-FT_LOAD_TARGET_LCD_V
-FT_LOAD_TARGET_LIGHT
-FT_LOAD_TARGET_MODE
-FT_LOAD_TARGET_MONO
-FT_LOAD_TARGET_NORMAL
-FT_LOAD_TARGET_XXX
-FT_LOAD_VERTICAL_LAYOUT
-FT_LOAD_XXX
-FT_Long
-FT_LZW_H
-FT_MAC_H
-FT_MAKE_TAG
-FT_Matrix
-FT_Matrix_Invert
-FT_Matrix_Multiply
-FT_Memory
-FT_MemoryRec
-FT_MM_Axis
-FT_MM_Var
-FT_Module
-FT_Module_Class
-FT_Module_Constructor
-FT_Module_Destructor
-FT_MODULE_ERRORS_H
-FT_MODULE_H
-FT_Module_Requester
-FT_MulDiv
-FT_MulFix
-FT_Multi_Master
-FT_MULTIPLE_MASTERS_H
-FT_New_Face
-FT_New_Face_From_FOND
-FT_New_Face_From_FSRef
-FT_New_Face_From_FSSpec
-FT_New_Glyph
-FT_New_Library
-FT_New_Memory_Face
-FT_New_Size
-FT_Offset
-FT_Open_Args
-FT_OPEN_DRIVER
-FT_Open_Face
-FT_OPEN_MEMORY
-FT_OPEN_PARAMS
-FT_OPEN_PATHNAME
-FT_OPEN_STREAM
-FT_OPEN_XXX
-FT_OpenType_Free
-FT_OpenType_Validate
-FT_OPENTYPE_VALIDATE_H
-FT_Orientation
-FT_ORIENTATION_FILL_LEFT
-FT_ORIENTATION_FILL_RIGHT
-FT_ORIENTATION_NONE
-FT_ORIENTATION_POSTSCRIPT
-FT_ORIENTATION_TRUETYPE
-FT_Outline
-FT_Outline_Check
-FT_Outline_ConicToFunc
-FT_Outline_Copy
-FT_Outline_CubicToFunc
-FT_Outline_Decompose
-FT_Outline_Done
-FT_Outline_Embolden
-FT_Outline_EmboldenXY
-FT_OUTLINE_EVEN_ODD_FILL
-FT_Outline_Funcs
-FT_Outline_Get_BBox
-FT_Outline_Get_Bitmap
-FT_Outline_Get_CBox
-FT_Outline_Get_Orientation
-FT_Outline_GetInsideBorder
-FT_Outline_GetOutsideBorder
-FT_OUTLINE_H
-FT_OUTLINE_HIGH_PRECISION
-FT_OUTLINE_IGNORE_DROPOUTS
-FT_OUTLINE_INCLUDE_STUBS
-FT_Outline_LineToFunc
-FT_Outline_MoveToFunc
-FT_Outline_New
-FT_OUTLINE_NONE
-FT_OUTLINE_OVERLAP
-FT_OUTLINE_OWNER
-FT_Outline_Render
-FT_Outline_Reverse
-FT_OUTLINE_REVERSE_FILL
-FT_OUTLINE_SINGLE_PASS
-FT_OUTLINE_SMART_DROPOUTS
-FT_Outline_Transform
-FT_Outline_Translate
-FT_OUTLINE_XXX
-FT_OutlineGlyph
-FT_OutlineGlyphRec
-FT_Palette_Data
-FT_Palette_Data_Get
-FT_PALETTE_FOR_DARK_BACKGROUND
-FT_PALETTE_FOR_LIGHT_BACKGROUND
-FT_Palette_Select
-FT_Palette_Set_Foreground_Color
-FT_PALETTE_XXX
-FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY
-FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY
-FT_PARAM_TAG_INCREMENTAL
-FT_PARAM_TAG_LCD_FILTER_WEIGHTS
-FT_PARAM_TAG_RANDOM_SEED
-FT_PARAM_TAG_STEM_DARKENING
-FT_PARAM_TAG_UNPATENTED_HINTING
-FT_Parameter
-FT_PCF_DRIVER_H
-FT_PFR_H
-FT_Pixel_Mode
-FT_PIXEL_MODE_BGRA
-FT_PIXEL_MODE_GRAY
-FT_PIXEL_MODE_GRAY2
-FT_PIXEL_MODE_GRAY4
-FT_PIXEL_MODE_LCD
-FT_PIXEL_MODE_LCD_V
-FT_PIXEL_MODE_MONO
-FT_PIXEL_MODE_NONE
-FT_Pointer
-FT_Pos
-FT_Prop_GlyphToScriptMap
-FT_Prop_IncreaseXHeight
-FT_Property_Get
-FT_Property_Set
-FT_PtrDist
-FT_Raster
-FT_Raster_BitSet_Func
-FT_Raster_BitTest_Func
-FT_Raster_DoneFunc
-FT_RASTER_FLAG_AA
-FT_RASTER_FLAG_CLIP
-FT_RASTER_FLAG_DEFAULT
-FT_RASTER_FLAG_DIRECT
-FT_RASTER_FLAG_XXX
-FT_Raster_Funcs
-FT_Raster_NewFunc
-FT_Raster_Params
-FT_Raster_RenderFunc
-FT_Raster_ResetFunc
-FT_Raster_SetModeFunc
-FT_Realloc_Func
-FT_Reference_Face
-FT_Reference_Library
-FT_Remove_Module
-FT_Render_Glyph
-FT_RENDER_H
-FT_Render_Mode
-FT_RENDER_MODE_LCD
-FT_RENDER_MODE_LCD_V
-FT_RENDER_MODE_LIGHT
-FT_RENDER_MODE_MONO
-FT_RENDER_MODE_NORMAL
-FT_Renderer
-FT_Renderer_Class
-FT_Request_Size
-FT_RoundFix
-FT_Select_Charmap
-FT_Select_Size
-FT_Set_Char_Size
-FT_Set_Charmap
-FT_Set_Debug_Hook
-FT_Set_Default_Properties
-FT_Set_MM_Blend_Coordinates
-FT_Set_MM_Design_Coordinates
-FT_Set_MM_WeightVector
-FT_Set_Named_Instance
-FT_Set_Pixel_Sizes
-FT_Set_Renderer
-FT_Set_Transform
-FT_Set_Var_Blend_Coordinates
-FT_Set_Var_Design_Coordinates
-FT_SFNT_HEAD
-FT_SFNT_HHEA
-FT_SFNT_MAXP
-FT_SFNT_NAMES_H
-FT_SFNT_OS2
-FT_SFNT_PCLT
-FT_SFNT_POST
-FT_Sfnt_Table_Info
-FT_Sfnt_Tag
-FT_SFNT_VHEA
-FT_SfntLangTag
-FT_SfntName
-FT_Short
-FT_Sin
-FT_Size
-FT_Size_Internal
-FT_Size_Metrics
-FT_Size_Request
-FT_Size_Request_Type
-FT_SIZE_REQUEST_TYPE_BBOX
-FT_SIZE_REQUEST_TYPE_CELL
-FT_SIZE_REQUEST_TYPE_NOMINAL
-FT_SIZE_REQUEST_TYPE_REAL_DIM
-FT_SIZE_REQUEST_TYPE_SCALES
-FT_Size_RequestRec
-FT_SizeRec
-FT_SIZES_H
-FT_Slot_Internal
-FT_Span
-FT_SpanFunc
-FT_Stream
-FT_Stream_CloseFunc
-FT_Stream_IoFunc
-FT_Stream_OpenBzip2
-FT_Stream_OpenGzip
-FT_Stream_OpenLZW
-FT_StreamDesc
-FT_StreamRec
-FT_String
-FT_Stroker
-FT_Stroker_BeginSubPath
-FT_STROKER_BORDER_LEFT
-FT_STROKER_BORDER_RIGHT
-FT_Stroker_ConicTo
-FT_Stroker_CubicTo
-FT_Stroker_Done
-FT_Stroker_EndSubPath
-FT_Stroker_Export
-FT_Stroker_ExportBorder
-FT_Stroker_GetBorderCounts
-FT_Stroker_GetCounts
-FT_STROKER_H
-FT_Stroker_LineCap
-FT_STROKER_LINECAP_BUTT
-FT_STROKER_LINECAP_ROUND
-FT_STROKER_LINECAP_SQUARE
-FT_Stroker_LineJoin
-FT_STROKER_LINEJOIN_BEVEL
-FT_STROKER_LINEJOIN_MITER
-FT_STROKER_LINEJOIN_MITER_FIXED
-FT_STROKER_LINEJOIN_MITER_VARIABLE
-FT_STROKER_LINEJOIN_ROUND
-FT_Stroker_LineTo
-FT_Stroker_New
-FT_Stroker_ParseOutline
-FT_Stroker_Rewind
-FT_Stroker_Set
-FT_StrokerBorder
-FT_STYLE_FLAG_BOLD
-FT_STYLE_FLAG_ITALIC
-FT_STYLE_FLAG_XXX
-FT_SubGlyph
-FT_SUBGLYPH_FLAG_2X2
-FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS
-FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
-FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID
-FT_SUBGLYPH_FLAG_SCALE
-FT_SUBGLYPH_FLAG_USE_MY_METRICS
-FT_SUBGLYPH_FLAG_XXX
-FT_SUBGLYPH_FLAG_XY_SCALE
-FT_SYNTHESIS_H
-FT_SYSTEM_H
-FT_Tag
-FT_Tan
-FT_TRIGONOMETRY_H
-FT_TRUETYPE_DRIVER_H
-FT_TRUETYPE_ENGINE_TYPE_NONE
-FT_TRUETYPE_ENGINE_TYPE_PATENTED
-FT_TRUETYPE_ENGINE_TYPE_UNPATENTED
-FT_TRUETYPE_IDS_H
-FT_TRUETYPE_TABLES_H
-FT_TRUETYPE_TAGS_H
-FT_TrueTypeEngineType
-FT_TrueTypeGX_Free
-FT_TrueTypeGX_Validate
-FT_TYPE1_TABLES_H
-FT_TYPES_H
-FT_UFWord
-FT_UInt
-FT_UInt16
-FT_UInt32
-FT_UInt64
-FT_ULong
-FT_UnitVector
-FT_UShort
-FT_VALIDATE_APPLE
-FT_VALIDATE_BASE
-FT_VALIDATE_bsln
-FT_VALIDATE_CKERN
-FT_VALIDATE_CKERNXXX
-FT_VALIDATE_feat
-FT_VALIDATE_GDEF
-FT_VALIDATE_GPOS
-FT_VALIDATE_GSUB
-FT_VALIDATE_GX
-FT_VALIDATE_GX_LENGTH
-FT_VALIDATE_GXXXX
-FT_VALIDATE_JSTF
-FT_VALIDATE_just
-FT_VALIDATE_kern
-FT_VALIDATE_lcar
-FT_VALIDATE_MATH
-FT_VALIDATE_mort
-FT_VALIDATE_morx
-FT_VALIDATE_MS
-FT_VALIDATE_opbd
-FT_VALIDATE_OT
-FT_VALIDATE_OTXXX
-FT_VALIDATE_prop
-FT_VALIDATE_trak
-FT_Var_Axis
-FT_VAR_AXIS_FLAG_HIDDEN
-FT_VAR_AXIS_FLAG_XXX
-FT_Var_Named_Style
-FT_Vector
-FT_Vector_From_Polar
-FT_Vector_Length
-FT_Vector_Polarize
-FT_Vector_Rotate
-FT_Vector_Transform
-FT_Vector_Unit
-FT_WinFNT_Header
-FT_WinFNT_HeaderRec
-FT_WinFNT_ID_CP1250
-FT_WinFNT_ID_CP1251
-FT_WinFNT_ID_CP1252
-FT_WinFNT_ID_CP1253
-FT_WinFNT_ID_CP1254
-FT_WinFNT_ID_CP1255
-FT_WinFNT_ID_CP1256
-FT_WinFNT_ID_CP1257
-FT_WinFNT_ID_CP1258
-FT_WinFNT_ID_CP1361
-FT_WinFNT_ID_CP874
-FT_WinFNT_ID_CP932
-FT_WinFNT_ID_CP936
-FT_WinFNT_ID_CP949
-FT_WinFNT_ID_CP950
-FT_WinFNT_ID_DEFAULT
-FT_WinFNT_ID_MAC
-FT_WinFNT_ID_OEM
-FT_WinFNT_ID_SYMBOL
-FT_WinFNT_ID_XXX
-FT_WINFONTS_H
-FTC_CMapCache
-FTC_CMapCache_Lookup
-FTC_CMapCache_New
-FTC_Face_Requester
-FTC_FaceID
-FTC_ImageCache
-FTC_ImageCache_Lookup
-FTC_ImageCache_LookupScaler
-FTC_ImageCache_New
-FTC_ImageType
-FTC_ImageTypeRec
-FTC_Manager
-FTC_Manager_Done
-FTC_Manager_LookupFace
-FTC_Manager_LookupSize
-FTC_Manager_New
-FTC_Manager_RemoveFaceID
-FTC_Manager_Reset
-FTC_Node
-FTC_Node_Unref
-FTC_SBit
-FTC_SBitCache
-FTC_SBitCache_Lookup
-FTC_SBitCache_LookupScaler
-FTC_SBitCache_New
-FTC_SBitRec
-FTC_Scaler
-FTC_ScalerRec

-

G

-

glyph-to-script-map

-

H

-

hinting-engine

-

I

-

increase-x-height
-interpreter-version

-

N

-

no-long-family-names
-no-stem-darkening

-

P

-

PS_DICT_BLUE_FUZZ
-PS_DICT_BLUE_SCALE
-PS_DICT_BLUE_SHIFT
-PS_DICT_BLUE_VALUE
-PS_DICT_CHAR_STRING
-PS_DICT_CHAR_STRING_KEY
-PS_DICT_ENCODING_ENTRY
-PS_DICT_ENCODING_TYPE
-PS_DICT_FAMILY_BLUE
-PS_DICT_FAMILY_NAME
-PS_DICT_FAMILY_OTHER_BLUE
-PS_DICT_FONT_BBOX
-PS_DICT_FONT_MATRIX
-PS_DICT_FONT_NAME
-PS_DICT_FONT_TYPE
-PS_DICT_FORCE_BOLD
-PS_DICT_FS_TYPE
-PS_DICT_FULL_NAME
-PS_DICT_IS_FIXED_PITCH
-PS_DICT_ITALIC_ANGLE
-PS_Dict_Keys
-PS_DICT_LANGUAGE_GROUP
-PS_DICT_LEN_IV
-PS_DICT_MIN_FEATURE
-PS_DICT_NOTICE
-PS_DICT_NUM_BLUE_VALUES
-PS_DICT_NUM_CHAR_STRINGS
-PS_DICT_NUM_FAMILY_BLUES
-PS_DICT_NUM_FAMILY_OTHER_BLUES
-PS_DICT_NUM_OTHER_BLUES
-PS_DICT_NUM_STEM_SNAP_H
-PS_DICT_NUM_STEM_SNAP_V
-PS_DICT_NUM_SUBRS
-PS_DICT_OTHER_BLUE
-PS_DICT_PAINT_TYPE
-PS_DICT_PASSWORD
-PS_DICT_RND_STEM_UP
-PS_DICT_STD_HW
-PS_DICT_STD_VW
-PS_DICT_STEM_SNAP_H
-PS_DICT_STEM_SNAP_V
-PS_DICT_SUBR
-PS_DICT_UNDERLINE_POSITION
-PS_DICT_UNDERLINE_THICKNESS
-PS_DICT_UNIQUE_ID
-PS_DICT_VERSION
-PS_DICT_WEIGHT
-PS_FontInfo
-PS_FontInfoRec
-PS_Private
-PS_PrivateRec

-

R

-

random-seed

-

T

-

T1_BLEND_BLUE_SCALE
-T1_BLEND_BLUE_SHIFT
-T1_BLEND_BLUE_VALUES
-T1_BLEND_FAMILY_BLUES
-T1_BLEND_FAMILY_OTHER_BLUES
-T1_Blend_Flags
-T1_BLEND_FORCE_BOLD
-T1_BLEND_ITALIC_ANGLE
-T1_BLEND_OTHER_BLUES
-T1_BLEND_STANDARD_HEIGHT
-T1_BLEND_STANDARD_WIDTH
-T1_BLEND_STEM_SNAP_HEIGHTS
-T1_BLEND_STEM_SNAP_WIDTHS
-T1_BLEND_UNDERLINE_POSITION
-T1_BLEND_UNDERLINE_THICKNESS
-T1_ENCODING_TYPE_ARRAY
-T1_ENCODING_TYPE_EXPERT
-T1_ENCODING_TYPE_ISOLATIN1
-T1_ENCODING_TYPE_NONE
-T1_ENCODING_TYPE_STANDARD
-T1_EncodingType
-T1_FontInfo
-T1_Private
-TT_ADOBE_ID_CUSTOM
-TT_ADOBE_ID_EXPERT
-TT_ADOBE_ID_LATIN_1
-TT_ADOBE_ID_STANDARD
-TT_ADOBE_ID_XXX
-TT_APPLE_ID_DEFAULT
-TT_APPLE_ID_FULL_UNICODE
-TT_APPLE_ID_ISO_10646
-TT_APPLE_ID_UNICODE_1_1
-TT_APPLE_ID_UNICODE_2_0
-TT_APPLE_ID_UNICODE_32
-TT_APPLE_ID_VARIANT_SELECTOR
-TT_APPLE_ID_XXX
-TT_Header
-TT_HoriHeader
-TT_INTERPRETER_VERSION_35
-TT_INTERPRETER_VERSION_38
-TT_INTERPRETER_VERSION_40
-TT_INTERPRETER_VERSION_XXX
-TT_ISO_ID_10646
-TT_ISO_ID_7BIT_ASCII
-TT_ISO_ID_8859_1
-TT_ISO_ID_XXX
-TT_MAC_ID_XXX
-TT_MAC_LANGID_XXX
-TT_MaxProfile
-TT_MS_ID_BIG_5
-TT_MS_ID_JOHAB
-TT_MS_ID_PRC
-TT_MS_ID_SJIS
-TT_MS_ID_SYMBOL_CS
-TT_MS_ID_UCS_4
-TT_MS_ID_UNICODE_CS
-TT_MS_ID_WANSUNG
-TT_MS_ID_XXX
-TT_MS_LANGID_XXX
-TT_NAME_ID_XXX
-TT_OS2
-TT_PCLT
-TT_PLATFORM_ADOBE
-TT_PLATFORM_APPLE_UNICODE
-TT_PLATFORM_CUSTOM
-TT_PLATFORM_ISO
-TT_PLATFORM_MACINTOSH
-TT_PLATFORM_MICROSOFT
-TT_PLATFORM_XXX
-TT_Postscript
-TT_UCR_XXX
-TT_VertHeader

-

W

-

warping

-
-
generated on Tue Oct 20 05:14:52 2020 UTC
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-layer_management.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-layer_management.html deleted file mode 100644 index 99933f4d5..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-layer_management.html +++ /dev/null @@ -1,1310 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Glyph Layer Management - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Core API » Glyph Layer Management

-
-

Glyph Layer Management

-

Synopsis

-

The functions described here allow access of colored glyph layer data in OpenType's ‘COLR’ tables.

-

FT_LayerIterator

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct  FT_LayerIterator_
-  {
-    FT_UInt   num_layers;
-    FT_UInt   layer;
-    FT_Byte*  p;
-
-  } FT_LayerIterator;
-
- -

This iterator object is needed for FT_Get_Color_Glyph_Layer.

-

fields

- - - - - -
num_layers -

The number of glyph layers for the requested glyph index. Will be set by FT_Get_Color_Glyph_Layer.

-
layer -

The current layer. Will be set by FT_Get_Color_Glyph_Layer.

-
p -

An opaque pointer into ‘COLR’ table data. The caller must set this to NULL before the first call of FT_Get_Color_Glyph_Layer.

-
- -
- -

FT_Get_Color_Glyph_Layer

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Bool )
-  FT_Get_Color_Glyph_Layer( FT_Face            face,
-                            FT_UInt            base_glyph,
-                            FT_UInt           *aglyph_index,
-                            FT_UInt           *acolor_index,
-                            FT_LayerIterator*  iterator );
-
- -

This is an interface to the ‘COLR’ table in OpenType fonts to iteratively retrieve the colored glyph layers associated with the current glyph slot.

-

https://docs.microsoft.com/en-us/typography/opentype/spec/colr

-

The glyph layer data for a given glyph index, if present, provides an alternative, multi-color glyph representation: Instead of rendering the outline or bitmap with the given glyph index, glyphs with the indices and colors returned by this function are rendered layer by layer.

-

The returned elements are ordered in the z direction from bottom to top; the 'n'th element should be rendered with the associated palette color and blended on top of the already rendered layers (elements 0, 1, ..., n-1).

-

input

- - - - -
face -

A handle to the parent face object.

-
base_glyph -

The glyph index the colored glyph layers are associated with.

-
- -

inout

- - - -
iterator -

An FT_LayerIterator object. For the first call you should set iterator->p to NULL. For all following calls, simply use the same object again.

-
- -

output

- - - - -
aglyph_index -

The glyph index of the current layer.

-
acolor_index -

The color index into the font face's color palette of the current layer. The value 0xFFFF is special; it doesn't reference a palette entry but indicates that the text foreground color should be used instead (to be set up by the application outside of FreeType).

-

The color palette can be retrieved with FT_Palette_Select.

-
- -

return

- -

Value 1 if everything is OK. If there are no more layers (or if there are no layers at all), value 0 gets returned. In case of an error, value 0 is returned also.

-

note

- -

This function is necessary if you want to handle glyph layers by yourself. In particular, functions that operate with FT_GlyphRec objects (like FT_Get_Glyph or FT_Glyph_To_Bitmap) don't have access to this information.

-

Note that FT_Render_Glyph is able to handle colored glyph layers automatically if the FT_LOAD_COLOR flag is passed to a previous call to FT_Load_Glyph. [This is an experimental feature.]

-

example

- -
  FT_Color*         palette;
-  FT_LayerIterator  iterator;
-
-  FT_Bool  have_layers;
-  FT_UInt  layer_glyph_index;
-  FT_UInt  layer_color_index;
-
-
-  error = FT_Palette_Select( face, palette_index, &palette );
-  if ( error )
-    palette = NULL;
-
-  iterator.p  = NULL;
-  have_layers = FT_Get_Color_Glyph_Layer( face,
-                                          glyph_index,
-                                          &layer_glyph_index,
-                                          &layer_color_index,
-                                          &iterator );
-
-  if ( palette && have_layers )
-  {
-    do
-    {
-      FT_Color  layer_color;
-
-
-      if ( layer_color_index == 0xFFFF )
-        layer_color = text_foreground_color;
-      else
-        layer_color = palette[layer_color_index];
-
-      // Load and render glyph `layer_glyph_index', then
-      // blend resulting pixmap (using color `layer_color')
-      // with previously created pixmaps.
-
-    } while ( FT_Get_Color_Glyph_Layer( face,
-                                        glyph_index,
-                                        &layer_glyph_index,
-                                        &layer_color_index,
-                                        &iterator ) );
-  }
-
- -
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-lcd_rendering.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-lcd_rendering.html deleted file mode 100644 index 480dea914..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-lcd_rendering.html +++ /dev/null @@ -1,1408 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Subpixel Rendering - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Controlling FreeType Modules » Subpixel Rendering

-
-

Subpixel Rendering

-

Synopsis

-

FreeType provides two alternative subpixel rendering technologies. Should you define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your ftoption.h file, this enables ClearType-style rendering. Otherwise, Harmony LCD rendering is enabled. These technologies are controlled differently and API described below, although always available, performs its function when appropriate method is enabled and does nothing otherwise.

-

ClearType-style LCD rendering exploits the color-striped structure of LCD pixels, increasing the available resolution in the direction of the stripe (usually horizontal RGB) by a factor of 3. Using the subpixels coverages unfiltered can create severe color fringes especially when rendering thin features. Indeed, to produce black-on-white text, the nearby color subpixels must be dimmed equally.

-

A good 5-tap FIR filter should be applied to subpixel coverages regardless of pixel boundaries and should have these properties:

-
    -
  1. -

    It should be symmetrical, like { a, b, c, b, a }, to avoid any shifts in appearance.

    -
  2. -
  3. -

    It should be color-balanced, meaning a + b = c, to reduce color fringes by distributing the computed coverage for one subpixel to all subpixels equally.

    -
  4. -
  5. -

    It should be normalized, meaning 2a + 2b + c = 1.0 to maintain overall brightness.

    -
  6. -
-

Boxy 3-tap filter {0, ⅓, ⅓, ⅓, 0} is sharper but is less forgiving of non-ideal gamma curves of a screen (and viewing angles), beveled filters are fuzzier but more tolerant.

-

Use the FT_Library_SetLcdFilter or FT_Library_SetLcdFilterWeights API to specify a low-pass filter, which is then applied to subpixel-rendered bitmaps generated through FT_Render_Glyph.

-

Harmony LCD rendering is suitable to panels with any regular subpixel structure, not just monitors with 3 color striped subpixels, as long as the color subpixels have fixed positions relative to the pixel center. In this case, each color channel is then rendered separately after shifting the outline opposite to the subpixel shift so that the coverage maps are aligned. This method is immune to color fringes because the shifts do not change integral coverage.

-

The subpixel geometry must be specified by xy-coordinates for each subpixel. By convention they may come in the RGB order: {{-⅓, 0}, {0, 0}, {⅓, 0}} for standard RGB striped panel or {{-⅙, ¼}, {-⅙, -¼}, {⅓, 0}} for a certain PenTile panel.

-

Use the FT_Library_SetLcdGeometry API to specify subpixel positions. If one follows the RGB order convention, the same order applies to the resulting FT_PIXEL_MODE_LCD and FT_PIXEL_MODE_LCD_V bitmaps. Note, however, that the coordinate frame for the latter must be rotated clockwise. Harmony with default LCD geometry is equivalent to ClearType with light filter.

-

As a result of ClearType filtering or Harmony rendering, the dimensions of LCD bitmaps can be either wider or taller than the dimensions of the corresponding outline with regard to the pixel grid. For example, for FT_RENDER_MODE_LCD, the filter adds 2 subpixels to the left, and 2 subpixels to the right. The bitmap offset values are adjusted accordingly, so clients shouldn't need to modify their layout and glyph positioning code when enabling the filter.

-

The ClearType and Harmony rendering is applicable to glyph bitmaps rendered through FT_Render_Glyph, FT_Load_Glyph, FT_Load_Char, and FT_Glyph_To_Bitmap, when FT_RENDER_MODE_LCD or FT_RENDER_MODE_LCD_V is specified. This API does not control FT_Outline_Render and FT_Outline_Get_Bitmap.

-

The described algorithms can completely remove color artefacts when combined with gamma-corrected alpha blending in linear space. Each of the 3 alpha values (subpixels) must by independently used to blend one color channel. That is, red alpha blends the red channel of the text color with the red channel of the background pixel.

-

FT_LcdFilter

-

Defined in FT_LCD_FILTER_H (freetype/ftlcdfil.h).

-
  typedef enum  FT_LcdFilter_
-  {
-    FT_LCD_FILTER_NONE    = 0,
-    FT_LCD_FILTER_DEFAULT = 1,
-    FT_LCD_FILTER_LIGHT   = 2,
-    FT_LCD_FILTER_LEGACY1 = 3,
-    FT_LCD_FILTER_LEGACY  = 16,
-
-    FT_LCD_FILTER_MAX   /* do not remove */
-
-  } FT_LcdFilter;
-
- -

A list of values to identify various types of LCD filters.

-

values

- - - - - - - -
FT_LCD_FILTER_NONE -

Do not perform filtering. When used with subpixel rendering, this results in sometimes severe color fringes.

-
FT_LCD_FILTER_DEFAULT -

This is a beveled, normalized, and color-balanced five-tap filter with weights of [0x08 0x4D 0x56 0x4D 0x08] in 1/256th units.

-
FT_LCD_FILTER_LIGHT -

this is a boxy, normalized, and color-balanced three-tap filter with weights of [0x00 0x55 0x56 0x55 0x00] in 1/256th units.

-
FT_LCD_FILTER_LEGACY - -
FT_LCD_FILTER_LEGACY1 -

This filter corresponds to the original libXft color filter. It provides high contrast output but can exhibit really bad color fringes if glyphs are not extremely well hinted to the pixel grid. This filter is only provided for comparison purposes, and might be disabled or stay unsupported in the future. The second value is provided for compatibility with FontConfig, which historically used different enumeration, sometimes incorrectly forwarded to FreeType.

-
- -

since

- -

2.3.0 (FT_LCD_FILTER_LEGACY1 since 2.6.2)

-
- -

FT_Library_SetLcdFilter

-

Defined in FT_LCD_FILTER_H (freetype/ftlcdfil.h).

-
  FT_EXPORT( FT_Error )
-  FT_Library_SetLcdFilter( FT_Library    library,
-                           FT_LcdFilter  filter );
-
- -

This function is used to change filter applied to LCD decimated bitmaps, like the ones used when calling FT_Render_Glyph with FT_RENDER_MODE_LCD or FT_RENDER_MODE_LCD_V.

-

input

- - - - -
library -

A handle to the target library instance.

-
filter -

The filter type.

-

You can use FT_LCD_FILTER_NONE here to disable this feature, or FT_LCD_FILTER_DEFAULT to use a default filter that should work well on most LCD screens.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

Since 2.10.3 the LCD filtering is enabled with FT_LCD_FILTER_DEFAULT. It is no longer necessary to call this function explicitly except to choose a different filter or disable filtering altogether with FT_LCD_FILTER_NONE.

-

This function does nothing but returns FT_Err_Unimplemented_Feature if the configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not defined in your build of the library.

-

since

- -

2.3.0

-
- -

FT_Library_SetLcdFilterWeights

-

Defined in FT_LCD_FILTER_H (freetype/ftlcdfil.h).

-
  FT_EXPORT( FT_Error )
-  FT_Library_SetLcdFilterWeights( FT_Library      library,
-                                  unsigned char  *weights );
-
- -

This function can be used to enable LCD filter with custom weights, instead of using presets in FT_Library_SetLcdFilter.

-

input

- - - - -
library -

A handle to the target library instance.

-
weights -

A pointer to an array; the function copies the first five bytes and uses them to specify the filter weights in 1/256th units.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function does nothing but returns FT_Err_Unimplemented_Feature if the configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not defined in your build of the library.

-

LCD filter weights can also be set per face using FT_Face_Properties with FT_PARAM_TAG_LCD_FILTER_WEIGHTS.

-

since

- -

2.4.0

-
- -

FT_LcdFiveTapFilter

-

Defined in FT_LCD_FILTER_H (freetype/ftlcdfil.h).

-
#define FT_LCD_FILTER_FIVE_TAPS  5
-
-  typedef FT_Byte  FT_LcdFiveTapFilter[FT_LCD_FILTER_FIVE_TAPS];
-
- -

A typedef for passing the five LCD filter weights to FT_Face_Properties within an FT_Parameter structure.

-

since

- -

2.8

-
- -

FT_Library_SetLcdGeometry

-

Defined in FT_LCD_FILTER_H (freetype/ftlcdfil.h).

-
  FT_EXPORT( FT_Error )
-  FT_Library_SetLcdGeometry( FT_Library  library,
-                             FT_Vector   sub[3] );
-
- -

This function can be used to modify default positions of color subpixels, which controls Harmony LCD rendering.

-

input

- - - - -
library -

A handle to the target library instance.

-
sub -

A pointer to an array of 3 vectors in 26.6 fractional pixel format; the function modifies the default values, see the note below.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

Subpixel geometry examples:

-
    -
  • -

    {{-21, 0}, {0, 0}, {21, 0}} is the default, corresponding to 3 color stripes shifted by a third of a pixel. This could be an RGB panel.

    -
  • -
  • -

    {{21, 0}, {0, 0}, {-21, 0}} looks the same as the default but can specify a BGR panel instead, while keeping the bitmap in the same RGB888 format.

    -
  • -
  • -

    {{0, 21}, {0, 0}, {0, -21}} is the vertical RGB, but the bitmap stays RGB888 as a result.

    -
  • -
  • -

    {{-11, 16}, {-11, -16}, {22, 0}} is a certain PenTile arrangement.

    -
  • -
-

This function does nothing and returns FT_Err_Unimplemented_Feature in the context of ClearType-style subpixel rendering when FT_CONFIG_OPTION_SUBPIXEL_RENDERING is defined in your build of the library.

-

since

- -

2.10.0

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-list_processing.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-list_processing.html deleted file mode 100644 index a00dde36f..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-list_processing.html +++ /dev/null @@ -1,1624 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - List Processing - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Support API » List Processing

-
-

List Processing

-

Synopsis

-

This section contains various definitions related to list processing using doubly-linked nodes.

-

FT_List

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef struct FT_ListRec_*  FT_List;
-
- -

A handle to a list record (see FT_ListRec).

-
- -

FT_ListNode

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef struct FT_ListNodeRec_*  FT_ListNode;
-
- -

Many elements and objects in FreeType are listed through an FT_List record (see FT_ListRec). As its name suggests, an FT_ListNode is a handle to a single list element.

-
- -

FT_ListRec

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef struct  FT_ListRec_
-  {
-    FT_ListNode  head;
-    FT_ListNode  tail;
-
-  } FT_ListRec;
-
- -

A structure used to hold a simple doubly-linked list. These are used in many parts of FreeType.

-

fields

- - - - -
-

The head (first element) of doubly-linked list.

-
tail -

The tail (last element) of doubly-linked list.

-
- -
- -

FT_ListNodeRec

-

Defined in FT_TYPES_H (freetype/fttypes.h).

-
  typedef struct  FT_ListNodeRec_
-  {
-    FT_ListNode  prev;
-    FT_ListNode  next;
-    void*        data;
-
-  } FT_ListNodeRec;
-
- -

A structure used to hold a single list element.

-

fields

- - - - - -
prev -

The previous element in the list. NULL if first.

-
next -

The next element in the list. NULL if last.

-
data -

A typeless pointer to the listed object.

-
- -
- -

FT_List_Add

-

Defined in FT_LIST_H (freetype/ftlist.h).

-
  FT_EXPORT( void )
-  FT_List_Add( FT_List      list,
-               FT_ListNode  node );
-
- -

Append an element to the end of a list.

-

inout

- - - - -
list -

A pointer to the parent list.

-
node -

The node to append.

-
- -
- -

FT_List_Insert

-

Defined in FT_LIST_H (freetype/ftlist.h).

-
  FT_EXPORT( void )
-  FT_List_Insert( FT_List      list,
-                  FT_ListNode  node );
-
- -

Insert an element at the head of a list.

-

inout

- - - - -
list -

A pointer to parent list.

-
node -

The node to insert.

-
- -
- -

FT_List_Find

-

Defined in FT_LIST_H (freetype/ftlist.h).

-
  FT_EXPORT( FT_ListNode )
-  FT_List_Find( FT_List  list,
-                void*    data );
-
- -

Find the list node for a given listed object.

-

input

- - - - -
list -

A pointer to the parent list.

-
data -

The address of the listed object.

-
- -

return

- -

List node. NULL if it wasn't found.

-
- -

FT_List_Remove

-

Defined in FT_LIST_H (freetype/ftlist.h).

-
  FT_EXPORT( void )
-  FT_List_Remove( FT_List      list,
-                  FT_ListNode  node );
-
- -

Remove a node from a list. This function doesn't check whether the node is in the list!

-

input

- - - -
node -

The node to remove.

-
- -

inout

- - - -
list -

A pointer to the parent list.

-
- -
- -

FT_List_Up

-

Defined in FT_LIST_H (freetype/ftlist.h).

-
  FT_EXPORT( void )
-  FT_List_Up( FT_List      list,
-              FT_ListNode  node );
-
- -

Move a node to the head/top of a list. Used to maintain LRU lists.

-

inout

- - - - -
list -

A pointer to the parent list.

-
node -

The node to move.

-
- -
- -

FT_List_Iterate

-

Defined in FT_LIST_H (freetype/ftlist.h).

-
  FT_EXPORT( FT_Error )
-  FT_List_Iterate( FT_List           list,
-                   FT_List_Iterator  iterator,
-                   void*             user );
-
- -

Parse a list and calls a given iterator function on each element. Note that parsing is stopped as soon as one of the iterator calls returns a non-zero value.

-

input

- - - - - -
list -

A handle to the list.

-
iterator -

An iterator function, called on each node of the list.

-
user -

A user-supplied field that is passed as the second argument to the iterator.

-
- -

return

- -

The result (a FreeType error code) of the last iterator call.

-
- -

FT_List_Iterator

-

Defined in FT_LIST_H (freetype/ftlist.h).

-
  typedef FT_Error
-  (*FT_List_Iterator)( FT_ListNode  node,
-                       void*        user );
-
- -

An FT_List iterator function that is called during a list parse by FT_List_Iterate.

-

input

- - - - -
node -

The current iteration list node.

-
user -

A typeless pointer passed to FT_List_Iterate. Can be used to point to the iteration's state.

-
- -
- -

FT_List_Finalize

-

Defined in FT_LIST_H (freetype/ftlist.h).

-
  FT_EXPORT( void )
-  FT_List_Finalize( FT_List             list,
-                    FT_List_Destructor  destroy,
-                    FT_Memory           memory,
-                    void*               user );
-
- -

Destroy all elements in the list as well as the list itself.

-

input

- - - - - - -
list -

A handle to the list.

-
destroy -

A list destructor that will be applied to each element of the list. Set this to NULL if not needed.

-
memory -

The current memory object that handles deallocation.

-
user -

A user-supplied field that is passed as the last argument to the destructor.

-
- -

note

- -

This function expects that all nodes added by FT_List_Add or FT_List_Insert have been dynamically allocated.

-
- -

FT_List_Destructor

-

Defined in FT_LIST_H (freetype/ftlist.h).

-
  typedef void
-  (*FT_List_Destructor)( FT_Memory  memory,
-                         void*      data,
-                         void*      user );
-
- -

An FT_List iterator function that is called during a list finalization by FT_List_Finalize to destroy all elements in a given list.

-

input

- - - - - -
system -

The current system object.

-
data -

The current object to destroy.

-
user -

A typeless pointer passed to FT_List_Iterate. It can be used to point to the iteration's state.

-
- -
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-lzw.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-lzw.html deleted file mode 100644 index 03c9e6490..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-lzw.html +++ /dev/null @@ -1,1200 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LZW Streams - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Support API » LZW Streams

-
-

LZW Streams

-

Synopsis

-

In certain builds of the library, LZW compression recognition is automatically handled when calling FT_New_Face or FT_Open_Face. This means that if no font driver is capable of handling the raw compressed file, the library will try to open a LZW stream from it and re-open the face with it.

-

The stream implementation is very basic and resets the decompression process each time seeking backwards is needed within the stream, which significantly undermines the performance.

-

This section contains the declaration of LZW-specific functions.

-

FT_Stream_OpenLZW

-

Defined in FT_LZW_H (freetype/ftlzw.h).

-
  FT_EXPORT( FT_Error )
-  FT_Stream_OpenLZW( FT_Stream  stream,
-                     FT_Stream  source );
-
- -

Open a new stream to parse LZW-compressed font files. This is mainly used to support the compressed *.pcf.Z fonts that come with XFree86.

-

input

- - - - -
stream -

The target embedding stream.

-
source -

The source stream.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The source stream must be opened before calling this function.

-

Calling the internal function FT_Stream_Close on the new stream will not call FT_Stream_Close on the source stream. None of the stream objects will be released to the heap.

-

This function may return FT_Err_Unimplemented_Feature if your build of FreeType was not compiled with LZW support.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-mac_specific.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-mac_specific.html deleted file mode 100644 index 9f7031f6c..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-mac_specific.html +++ /dev/null @@ -1,1486 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Mac Specific Interface - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Core API » Mac Specific Interface

-
-

Mac Specific Interface

-

Synopsis

-

The following definitions are only available if FreeType is compiled on a Macintosh.

-

FT_New_Face_From_FOND

-

Defined in FT_MAC_H (freetype/ftmac.h).

-
  FT_EXPORT( FT_Error )
-  FT_New_Face_From_FOND( FT_Library  library,
-                         Handle      fond,
-                         FT_Long     face_index,
-                         FT_Face    *aface )
-                       FT_DEPRECATED_ATTRIBUTE;
-
- -

Create a new face object from a FOND resource.

-

inout

- - - -
library -

A handle to the library resource.

-
- -

input

- - - - -
fond -

A FOND resource.

-
face_index -

Only supported for the -1 ‘sanity check’ special case.

-
- -

output

- - - -
aface -

A handle to a new face object.

-
- -

return

- -

FreeType error code. 0 means success.

-

example

- -

This function can be used to create FT_Face objects from fonts that are installed in the system as follows. -

  fond  = GetResource( 'FOND', fontName );
-  error = FT_New_Face_From_FOND( library, fond, 0, &face );
-

-
- -

FT_GetFile_From_Mac_Name

-

Defined in FT_MAC_H (freetype/ftmac.h).

-
  FT_EXPORT( FT_Error )
-  FT_GetFile_From_Mac_Name( const char*  fontName,
-                            FSSpec*      pathSpec,
-                            FT_Long*     face_index )
-                          FT_DEPRECATED_ATTRIBUTE;
-
- -

Return an FSSpec for the disk file containing the named font.

-

input

- - - -
fontName -

Mac OS name of the font (e.g., Times New Roman Bold).

-
- -

output

- - - - -
pathSpec -

FSSpec to the file. For passing to FT_New_Face_From_FSSpec.

-
face_index -

Index of the face. For passing to FT_New_Face_From_FSSpec.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FT_GetFile_From_Mac_ATS_Name

-

Defined in FT_MAC_H (freetype/ftmac.h).

-
  FT_EXPORT( FT_Error )
-  FT_GetFile_From_Mac_ATS_Name( const char*  fontName,
-                                FSSpec*      pathSpec,
-                                FT_Long*     face_index )
-                              FT_DEPRECATED_ATTRIBUTE;
-
- -

Return an FSSpec for the disk file containing the named font.

-

input

- - - -
fontName -

Mac OS name of the font in ATS framework.

-
- -

output

- - - - -
pathSpec -

FSSpec to the file. For passing to FT_New_Face_From_FSSpec.

-
face_index -

Index of the face. For passing to FT_New_Face_From_FSSpec.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FT_GetFilePath_From_Mac_ATS_Name

-

Defined in FT_MAC_H (freetype/ftmac.h).

-
  FT_EXPORT( FT_Error )
-  FT_GetFilePath_From_Mac_ATS_Name( const char*  fontName,
-                                    UInt8*       path,
-                                    UInt32       maxPathSize,
-                                    FT_Long*     face_index )
-                                  FT_DEPRECATED_ATTRIBUTE;
-
- -

Return a pathname of the disk file and face index for given font name that is handled by ATS framework.

-

input

- - - -
fontName -

Mac OS name of the font in ATS framework.

-
- -

output

- - - - - -
path -

Buffer to store pathname of the file. For passing to FT_New_Face. The client must allocate this buffer before calling this function.

-
maxPathSize -

Lengths of the buffer path that client allocated.

-
face_index -

Index of the face. For passing to FT_New_Face.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FT_New_Face_From_FSSpec

-

Defined in FT_MAC_H (freetype/ftmac.h).

-
  FT_EXPORT( FT_Error )
-  FT_New_Face_From_FSSpec( FT_Library     library,
-                           const FSSpec  *spec,
-                           FT_Long        face_index,
-                           FT_Face       *aface )
-                         FT_DEPRECATED_ATTRIBUTE;
-
- -

Create a new face object from a given resource and typeface index using an FSSpec to the font file.

-

inout

- - - -
library -

A handle to the library resource.

-
- -

input

- - - - -
spec -

FSSpec to the font file.

-
face_index -

The index of the face within the resource. The first face has index 0.

-
- -

output

- - - -
aface -

A handle to a new face object.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

FT_New_Face_From_FSSpec is identical to FT_New_Face except it accepts an FSSpec instead of a path.

-
- -

FT_New_Face_From_FSRef

-

Defined in FT_MAC_H (freetype/ftmac.h).

-
  FT_EXPORT( FT_Error )
-  FT_New_Face_From_FSRef( FT_Library    library,
-                          const FSRef  *ref,
-                          FT_Long       face_index,
-                          FT_Face      *aface )
-                        FT_DEPRECATED_ATTRIBUTE;
-
- -

Create a new face object from a given resource and typeface index using an FSRef to the font file.

-

inout

- - - -
library -

A handle to the library resource.

-
- -

input

- - - - -
spec -

FSRef to the font file.

-
face_index -

The index of the face within the resource. The first face has index 0.

-
- -

output

- - - -
aface -

A handle to a new face object.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

FT_New_Face_From_FSRef is identical to FT_New_Face except it accepts an FSRef instead of a path.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-module_management.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-module_management.html deleted file mode 100644 index 8dd7322ca..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-module_management.html +++ /dev/null @@ -1,2159 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Module Management - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Support API » Module Management

-
-

Module Management

-

Synopsis

-

The definitions below are used to manage modules within FreeType. Modules can be added, upgraded, and removed at runtime. Additionally, some module properties can be controlled also.

-

Here is a list of possible values of the module_name field in the FT_Module_Class structure. -

  autofitter
-  bdf
-  cff
-  gxvalid
-  otvalid
-  pcf
-  pfr
-  psaux
-  pshinter
-  psnames
-  raster1
-  sfnt
-  smooth
-  truetype
-  type1
-  type42
-  t1cid
-  winfonts
-

-

Note that the FreeType Cache sub-system is not a FreeType module.

-

FT_Module

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct FT_ModuleRec_*  FT_Module;
-
- -

A handle to a given FreeType module object. A module can be a font driver, a renderer, or anything else that provides services to the former.

-
- -

FT_Module_Constructor

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  typedef FT_Error
-  (*FT_Module_Constructor)( FT_Module  module );
-
- -

A function used to initialize (not create) a new module object.

-

input

- - - -
module -

The module to initialize.

-
- -
- -

FT_Module_Destructor

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  typedef void
-  (*FT_Module_Destructor)( FT_Module  module );
-
- -

A function used to finalize (not destroy) a given module object.

-

input

- - - -
module -

The module to finalize.

-
- -
- -

FT_Module_Requester

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  typedef FT_Module_Interface
-  (*FT_Module_Requester)( FT_Module    module,
-                          const char*  name );
-
- -

A function used to query a given module for a specific interface.

-

input

- - - - -
module -

The module to be searched.

-
name -

The name of the interface in the module.

-
- -
- -

FT_Module_Class

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  typedef struct  FT_Module_Class_
-  {
-    FT_ULong               module_flags;
-    FT_Long                module_size;
-    const FT_String*       module_name;
-    FT_Fixed               module_version;
-    FT_Fixed               module_requires;
-
-    const void*            module_interface;
-
-    FT_Module_Constructor  module_init;
-    FT_Module_Destructor   module_done;
-    FT_Module_Requester    get_interface;
-
-  } FT_Module_Class;
-
- -

The module class descriptor. While being a public structure necessary for FreeType's module bookkeeping, most of the fields are essentially internal, not to be used directly by an application.

-

fields

- - - - - - - - - - - -
module_flags -

Bit flags describing the module.

-
module_size -

The size of one module object/instance in bytes.

-
module_name -

The name of the module.

-
module_version -

The version, as a 16.16 fixed number (major.minor).

-
module_requires -

The version of FreeType this module requires, as a 16.16 fixed number (major.minor). Starts at version 2.0, i.e., 0x20000.

-
module_interface -

A typeless pointer to a structure (which varies between different modules) that holds the module's interface functions. This is essentially what get_interface returns.

-
module_init -

The initializing function.

-
module_done -

The finalizing function.

-
get_interface -

The interface requesting function.

-
- -
- -

FT_Add_Module

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  FT_EXPORT( FT_Error )
-  FT_Add_Module( FT_Library              library,
-                 const FT_Module_Class*  clazz );
-
- -

Add a new module to a given library instance.

-

inout

- - - -
library -

A handle to the library object.

-
- -

input

- - - -
clazz -

A pointer to class descriptor for the module.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

An error will be returned if a module already exists by that name, or if the module requires a version of FreeType that is too great.

-
- -

FT_Get_Module

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  FT_EXPORT( FT_Module )
-  FT_Get_Module( FT_Library   library,
-                 const char*  module_name );
-
- -

Find a module by its name.

-

input

- - - - -
library -

A handle to the library object.

-
module_name -

The module's name (as an ASCII string).

-
- -

return

- -

A module handle. 0 if none was found.

-

note

- -

FreeType's internal modules aren't documented very well, and you should look up the source code for details.

-
- -

FT_Remove_Module

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  FT_EXPORT( FT_Error )
-  FT_Remove_Module( FT_Library  library,
-                    FT_Module   module );
-
- -

Remove a given module from a library instance.

-

inout

- - - -
library -

A handle to a library object.

-
- -

input

- - - -
module -

A handle to a module object.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The module object is destroyed by the function in case of success.

-
- -

FT_Add_Default_Modules

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  FT_EXPORT( void )
-  FT_Add_Default_Modules( FT_Library  library );
-
- -

Add the set of default drivers to a given library object. This is only useful when you create a library object with FT_New_Library (usually to plug a custom memory manager).

-

inout

- - - -
library -

A handle to a new library object.

-
- -
- -

FT_Property_Set

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  FT_EXPORT( FT_Error )
-  FT_Property_Set( FT_Library        library,
-                   const FT_String*  module_name,
-                   const FT_String*  property_name,
-                   const void*       value );
-
- -

Set a property for a given module.

-

input

- - - - - - -
library -

A handle to the library the module is part of.

-
module_name -

The module name.

-
property_name -

The property name. Properties are described in section ‘Driver properties’.

-

Note that only a few modules have properties.

-
value -

A generic pointer to a variable or structure that gives the new value of the property. The exact definition of value is dependent on the property; see section ‘Driver properties’.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

If module_name isn't a valid module name, or property_name doesn't specify a valid property, or if value doesn't represent a valid value for the given property, an error is returned.

-

The following example sets property ‘bar’ (a simple integer) in module ‘foo’ to value 1. -

  FT_UInt  bar;
-
-
-  bar = 1;
-  FT_Property_Set( library, "foo", "bar", &bar );
-

-

Note that the FreeType Cache sub-system doesn't recognize module property changes. To avoid glyph lookup confusion within the cache you should call FTC_Manager_Reset to completely flush the cache if a module property gets changed after FTC_Manager_New has been called.

-

It is not possible to set properties of the FreeType Cache sub-system itself with FT_Property_Set; use ?FTC_Property_Set? instead.

-

since

- -

2.4.11

-
- -

FT_Property_Get

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  FT_EXPORT( FT_Error )
-  FT_Property_Get( FT_Library        library,
-                   const FT_String*  module_name,
-                   const FT_String*  property_name,
-                   void*             value );
-
- -

Get a module's property value.

-

input

- - - - - -
library -

A handle to the library the module is part of.

-
module_name -

The module name.

-
property_name -

The property name. Properties are described in section ‘Driver properties’.

-
- -

inout

- - - -
value -

A generic pointer to a variable or structure that gives the value of the property. The exact definition of value is dependent on the property; see section ‘Driver properties’.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

If module_name isn't a valid module name, or property_name doesn't specify a valid property, or if value doesn't represent a valid value for the given property, an error is returned.

-

The following example gets property ‘baz’ (a range) in module ‘foo’. -

  typedef  range_
-  {
-    FT_Int32  min;
-    FT_Int32  max;
-
-  } range;
-
-  range  baz;
-
-
-  FT_Property_Get( library, "foo", "baz", &baz );
-

-

It is not possible to retrieve properties of the FreeType Cache sub-system with FT_Property_Get; use ?FTC_Property_Get? instead.

-

since

- -

2.4.11

-
- -

FT_Set_Default_Properties

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  FT_EXPORT( void )
-  FT_Set_Default_Properties( FT_Library  library );
-
- -

If compilation option FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES is set, this function reads the FREETYPE_PROPERTIES environment variable to control driver properties. See section ‘Driver properties’ for more.

-

If the compilation option is not set, this function does nothing.

-

FREETYPE_PROPERTIES has the following syntax form (broken here into multiple lines for better readability). -

  <optional whitespace>
-  <module-name1> ':'
-  <property-name1> '=' <property-value1>
-  <whitespace>
-  <module-name2> ':'
-  <property-name2> '=' <property-value2>
-  ...
-

-

Example: -

  FREETYPE_PROPERTIES=truetype:interpreter-version=35 \
-                      cff:no-stem-darkening=0 \
-                      autofitter:warping=1
-

-

inout

- - - -
library -

A handle to a new library object.

-
- -

since

- -

2.8

-
- -

FT_New_Library

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  FT_EXPORT( FT_Error )
-  FT_New_Library( FT_Memory    memory,
-                  FT_Library  *alibrary );
-
- -

This function is used to create a new FreeType library instance from a given memory object. It is thus possible to use libraries with distinct memory allocators within the same program. Note, however, that the used FT_Memory structure is expected to remain valid for the life of the FT_Library object.

-

Normally, you would call this function (followed by a call to FT_Add_Default_Modules or a series of calls to FT_Add_Module, and a call to FT_Set_Default_Properties) instead of FT_Init_FreeType to initialize the FreeType library.

-

Don't use FT_Done_FreeType but FT_Done_Library to destroy a library instance.

-

input

- - - -
memory -

A handle to the original memory object.

-
- -

output

- - - -
alibrary -

A pointer to handle of a new library object.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

See the discussion of reference counters in the description of FT_Reference_Library.

-
- -

FT_Done_Library

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  FT_EXPORT( FT_Error )
-  FT_Done_Library( FT_Library  library );
-
- -

Discard a given library object. This closes all drivers and discards all resource objects.

-

input

- - - -
library -

A handle to the target library.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

See the discussion of reference counters in the description of FT_Reference_Library.

-
- -

FT_Reference_Library

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  FT_EXPORT( FT_Error )
-  FT_Reference_Library( FT_Library  library );
-
- -

A counter gets initialized to 1 at the time an FT_Library structure is created. This function increments the counter. FT_Done_Library then only destroys a library if the counter is 1, otherwise it simply decrements the counter.

-

This function helps in managing life-cycles of structures that reference FT_Library objects.

-

input

- - - -
library -

A handle to a target library object.

-
- -

return

- -

FreeType error code. 0 means success.

-

since

- -

2.4.2

-
- -

FT_Renderer

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct FT_RendererRec_*  FT_Renderer;
-
- -

A handle to a given FreeType renderer. A renderer is a module in charge of converting a glyph's outline image to a bitmap. It supports a single glyph image format, and one or more target surface depths.

-
- -

FT_Renderer_Class

-

Defined in FT_RENDER_H (freetype/ftrender.h).

-
  typedef struct  FT_Renderer_Class_
-  {
-    FT_Module_Class            root;
-
-    FT_Glyph_Format            glyph_format;
-
-    FT_Renderer_RenderFunc     render_glyph;
-    FT_Renderer_TransformFunc  transform_glyph;
-    FT_Renderer_GetCBoxFunc    get_glyph_cbox;
-    FT_Renderer_SetModeFunc    set_mode;
-
-    FT_Raster_Funcs*           raster_class;
-
-  } FT_Renderer_Class;
-
- -

The renderer module class descriptor.

-

fields

- - - - - - - - - -
root -

The root FT_Module_Class fields.

-
glyph_format -

The glyph image format this renderer handles.

-
render_glyph -

A method used to render the image that is in a given glyph slot into a bitmap.

-
transform_glyph -

A method used to transform the image that is in a given glyph slot.

-
get_glyph_cbox -

A method used to access the glyph's cbox.

-
set_mode -

A method used to pass additional parameters.

-
raster_class -

For FT_GLYPH_FORMAT_OUTLINE renderers only. This is a pointer to its raster's class.

-
- -
- -

FT_Get_Renderer

-

Defined in FT_RENDER_H (freetype/ftrender.h).

-
  FT_EXPORT( FT_Renderer )
-  FT_Get_Renderer( FT_Library       library,
-                   FT_Glyph_Format  format );
-
- -

Retrieve the current renderer for a given glyph format.

-

input

- - - - -
library -

A handle to the library object.

-
format -

The glyph format.

-
- -

return

- -

A renderer handle. 0 if none found.

-

note

- -

An error will be returned if a module already exists by that name, or if the module requires a version of FreeType that is too great.

-

To add a new renderer, simply use FT_Add_Module. To retrieve a renderer by its name, use FT_Get_Module.

-
- -

FT_Set_Renderer

-

Defined in FT_RENDER_H (freetype/ftrender.h).

-
  FT_EXPORT( FT_Error )
-  FT_Set_Renderer( FT_Library     library,
-                   FT_Renderer    renderer,
-                   FT_UInt        num_params,
-                   FT_Parameter*  parameters );
-
- -

Set the current renderer to use, and set additional mode.

-

inout

- - - -
library -

A handle to the library object.

-
- -

input

- - - - - -
renderer -

A handle to the renderer object.

-
num_params -

The number of additional parameters.

-
parameters -

Additional parameters.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

In case of success, the renderer will be used to convert glyph images in the renderer's known format into bitmaps.

-

This doesn't change the current renderer for other formats.

-

Currently, no FreeType renderer module uses parameters; you should thus always pass NULL as the value.

-
- -

FT_Set_Debug_Hook

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  FT_EXPORT( void )
-  FT_Set_Debug_Hook( FT_Library         library,
-                     FT_UInt            hook_index,
-                     FT_DebugHook_Func  debug_hook );
-
- -

Set a debug hook function for debugging the interpreter of a font format.

-

While this is a public API function, an application needs access to FreeType's internal header files to do something useful.

-

Have a look at the source code of the ttdebug FreeType demo program for an example of its usage.

-

inout

- - - -
library -

A handle to the library object.

-
- -

input

- - - - -
hook_index -

The index of the debug hook. You should use defined enumeration macros like FT_DEBUG_HOOK_TRUETYPE.

-
debug_hook -

The function used to debug the interpreter.

-
- -

note

- -

Currently, four debug hook slots are available, but only one (for the TrueType interpreter) is defined.

-
- -

FT_Driver

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  typedef struct FT_DriverRec_*  FT_Driver;
-
- -

A handle to a given FreeType font driver object. A font driver is a module capable of creating faces from font files.

-
- -

FT_DebugHook_Func

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  typedef FT_Error
-  (*FT_DebugHook_Func)( void*  arg );
-
- -

A drop-in replacement (or rather a wrapper) for the bytecode or charstring interpreter's main loop function.

-

Its job is essentially

-
    -
  • -

    to activate debug mode to enforce single-stepping,

    -
  • -
  • -

    to call the main loop function to interpret the next opcode, and

    -
  • -
  • -

    to show the changed context to the user.

    -
  • -
-

An example for such a main loop function is TT_RunIns (declared in FreeType's internal header file src/truetype/ttinterp.h).

-

Have a look at the source code of the ttdebug FreeType demo program for an example of a drop-in replacement.

-

inout

- - - -
arg -

A typeless pointer, to be cast to the main loop function's data structure (which depends on the font module). For TrueType fonts it is bytecode interpreter's execution context, TT_ExecContext, which is declared in FreeType's internal header file tttypes.h.

-
- -
- -

FT_DEBUG_HOOK_XXX

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

- - -

A list of named debug hook indices.

-

values

- - - -
FT_DEBUG_HOOK_TRUETYPE -

This hook index identifies the TrueType bytecode debugger.

-
- -
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-multiple_masters.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-multiple_masters.html deleted file mode 100644 index f89cb09f5..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-multiple_masters.html +++ /dev/null @@ -1,2069 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Multiple Masters - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Format-Specific API » Multiple Masters

-
-

Multiple Masters

-

Synopsis

-

The following types and functions are used to manage Multiple Master fonts, i.e., the selection of specific design instances by setting design axis coordinates.

-

Besides Adobe MM fonts, the interface supports Apple's TrueType GX and OpenType variation fonts. Some of the routines only work with Adobe MM fonts, others will work with all three types. They are similar enough that a consistent interface makes sense.

-

FT_MM_Axis

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  typedef struct  FT_MM_Axis_
-  {
-    FT_String*  name;
-    FT_Long     minimum;
-    FT_Long     maximum;
-
-  } FT_MM_Axis;
-
- -

A structure to model a given axis in design space for Multiple Masters fonts.

-

This structure can't be used for TrueType GX or OpenType variation fonts.

-

fields

- - - - - -
name -

The axis's name.

-
minimum -

The axis's minimum design coordinate.

-
maximum -

The axis's maximum design coordinate.

-
- -
- -

FT_Multi_Master

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  typedef struct  FT_Multi_Master_
-  {
-    FT_UInt     num_axis;
-    FT_UInt     num_designs;
-    FT_MM_Axis  axis[T1_MAX_MM_AXIS];
-
-  } FT_Multi_Master;
-
- -

A structure to model the axes and space of a Multiple Masters font.

-

This structure can't be used for TrueType GX or OpenType variation fonts.

-

fields

- - - - - -
num_axis -

Number of axes. Cannot exceed 4.

-
num_designs -

Number of designs; should be normally 2^num_axis even though the Type 1 specification strangely allows for intermediate designs to be present. This number cannot exceed 16.

-
axis -

A table of axis descriptors.

-
- -
- -

FT_Var_Axis

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  typedef struct  FT_Var_Axis_
-  {
-    FT_String*  name;
-
-    FT_Fixed    minimum;
-    FT_Fixed    def;
-    FT_Fixed    maximum;
-
-    FT_ULong    tag;
-    FT_UInt     strid;
-
-  } FT_Var_Axis;
-
- -

A structure to model a given axis in design space for Multiple Masters, TrueType GX, and OpenType variation fonts.

-

fields

- - - - - - - - -
name -

The axis's name. Not always meaningful for TrueType GX or OpenType variation fonts.

-
minimum -

The axis's minimum design coordinate.

-
def -

The axis's default design coordinate. FreeType computes meaningful default values for Adobe MM fonts.

-
maximum -

The axis's maximum design coordinate.

-
tag -

The axis's tag (the equivalent to ‘name’ for TrueType GX and OpenType variation fonts). FreeType provides default values for Adobe MM fonts if possible.

-
strid -

The axis name entry in the font's ‘name’ table. This is another (and often better) version of the ‘name’ field for TrueType GX or OpenType variation fonts. Not meaningful for Adobe MM fonts.

-
- -

note

- -

The fields minimum, def, and maximum are 16.16 fractional values for TrueType GX and OpenType variation fonts. For Adobe MM fonts, the values are integers.

-
- -

FT_Var_Named_Style

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  typedef struct  FT_Var_Named_Style_
-  {
-    FT_Fixed*  coords;
-    FT_UInt    strid;
-    FT_UInt    psid;   /* since 2.7.1 */
-
-  } FT_Var_Named_Style;
-
- -

A structure to model a named instance in a TrueType GX or OpenType variation font.

-

This structure can't be used for Adobe MM fonts.

-

fields

- - - - - -
coords -

The design coordinates for this instance. This is an array with one entry for each axis.

-
strid -

The entry in ‘name’ table identifying this instance.

-
psid -

The entry in ‘name’ table identifying a PostScript name for this instance. Value 0xFFFF indicates a missing entry.

-
- -
- -

FT_MM_Var

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  typedef struct  FT_MM_Var_
-  {
-    FT_UInt              num_axis;
-    FT_UInt              num_designs;
-    FT_UInt              num_namedstyles;
-    FT_Var_Axis*         axis;
-    FT_Var_Named_Style*  namedstyle;
-
-  } FT_MM_Var;
-
- -

A structure to model the axes and space of an Adobe MM, TrueType GX, or OpenType variation font.

-

Some fields are specific to one format and not to the others.

-

fields

- - - - - - - -
num_axis -

The number of axes. The maximum value is 4 for Adobe MM fonts; no limit in TrueType GX or OpenType variation fonts.

-
num_designs -

The number of designs; should be normally 2^num_axis for Adobe MM fonts. Not meaningful for TrueType GX or OpenType variation fonts (where every glyph could have a different number of designs).

-
num_namedstyles -

The number of named styles; a ‘named style’ is a tuple of design coordinates that has a string ID (in the ‘name’ table) associated with it. The font can tell the user that, for example, [Weight=1.5,Width=1.1] is ‘Bold’. Another name for ‘named style’ is ‘named instance’.

-

For Adobe Multiple Masters fonts, this value is always zero because the format does not support named styles.

-
axis -

An axis descriptor table. TrueType GX and OpenType variation fonts contain slightly more data than Adobe MM fonts. Memory management of this pointer is done internally by FreeType.

-
namedstyle -

A named style (instance) table. Only meaningful for TrueType GX and OpenType variation fonts. Memory management of this pointer is done internally by FreeType.

-
- -
- -

FT_Get_Multi_Master

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_Multi_Master( FT_Face           face,
-                       FT_Multi_Master  *amaster );
-
- -

Retrieve a variation descriptor of a given Adobe MM font.

-

This function can't be used with TrueType GX or OpenType variation fonts.

-

input

- - - -
face -

A handle to the source face.

-
- -

output

- - - -
amaster -

The Multiple Masters descriptor.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FT_Get_MM_Var

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_MM_Var( FT_Face      face,
-                 FT_MM_Var*  *amaster );
-
- -

Retrieve a variation descriptor for a given font.

-

This function works with all supported variation formats.

-

input

- - - -
face -

A handle to the source face.

-
- -

output

- - - -
amaster -

The variation descriptor. Allocates a data structure, which the user must deallocate with a call to FT_Done_MM_Var after use.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FT_Done_MM_Var

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  FT_EXPORT( FT_Error )
-  FT_Done_MM_Var( FT_Library   library,
-                  FT_MM_Var   *amaster );
-
- -

Free the memory allocated by FT_Get_MM_Var.

-

input

- - - -
library -

A handle of the face's parent library object that was used in the call to FT_Get_MM_Var to create amaster.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FT_Set_MM_Design_Coordinates

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  FT_EXPORT( FT_Error )
-  FT_Set_MM_Design_Coordinates( FT_Face   face,
-                                FT_UInt   num_coords,
-                                FT_Long*  coords );
-
- -

For Adobe MM fonts, choose an interpolated font design through design coordinates.

-

This function can't be used with TrueType GX or OpenType variation fonts.

-

inout

- - - -
face -

A handle to the source face.

-
- -

input

- - - - -
num_coords -

The number of available design coordinates. If it is larger than the number of axes, ignore the excess values. If it is smaller than the number of axes, use default values for the remaining axes.

-
coords -

An array of design coordinates.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

[Since 2.8.1] To reset all axes to the default values, call the function with num_coords set to zero and coords set to NULL.

-

[Since 2.9] If num_coords is larger than zero, this function sets the FT_FACE_FLAG_VARIATION bit in FT_Face's face_flags field (i.e., FT_IS_VARIATION will return true). If num_coords is zero, this bit flag gets unset.

-
- -

FT_Set_Var_Design_Coordinates

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  FT_EXPORT( FT_Error )
-  FT_Set_Var_Design_Coordinates( FT_Face    face,
-                                 FT_UInt    num_coords,
-                                 FT_Fixed*  coords );
-
- -

Choose an interpolated font design through design coordinates.

-

This function works with all supported variation formats.

-

inout

- - - -
face -

A handle to the source face.

-
- -

input

- - - - -
num_coords -

The number of available design coordinates. If it is larger than the number of axes, ignore the excess values. If it is smaller than the number of axes, use default values for the remaining axes.

-
coords -

An array of design coordinates.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

[Since 2.8.1] To reset all axes to the default values, call the function with num_coords set to zero and coords set to NULL. [Since 2.9] ‘Default values’ means the currently selected named instance (or the base font if no named instance is selected).

-

[Since 2.9] If num_coords is larger than zero, this function sets the FT_FACE_FLAG_VARIATION bit in FT_Face's face_flags field (i.e., FT_IS_VARIATION will return true). If num_coords is zero, this bit flag gets unset.

-
- -

FT_Get_Var_Design_Coordinates

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_Var_Design_Coordinates( FT_Face    face,
-                                 FT_UInt    num_coords,
-                                 FT_Fixed*  coords );
-
- -

Get the design coordinates of the currently selected interpolated font.

-

This function works with all supported variation formats.

-

input

- - - - -
face -

A handle to the source face.

-
num_coords -

The number of design coordinates to retrieve. If it is larger than the number of axes, set the excess values to 0.

-
- -

output

- - - -
coords -

The design coordinates array.

-
- -

return

- -

FreeType error code. 0 means success.

-

since

- -

2.7.1

-
- -

FT_Set_MM_Blend_Coordinates

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  FT_EXPORT( FT_Error )
-  FT_Set_MM_Blend_Coordinates( FT_Face    face,
-                               FT_UInt    num_coords,
-                               FT_Fixed*  coords );
-
- -

Choose an interpolated font design through normalized blend coordinates.

-

This function works with all supported variation formats.

-

inout

- - - -
face -

A handle to the source face.

-
- -

input

- - - - -
num_coords -

The number of available design coordinates. If it is larger than the number of axes, ignore the excess values. If it is smaller than the number of axes, use default values for the remaining axes.

-
coords -

The design coordinates array (each element must be between 0 and 1.0 for Adobe MM fonts, and between -1.0 and 1.0 for TrueType GX and OpenType variation fonts).

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

[Since 2.8.1] To reset all axes to the default values, call the function with num_coords set to zero and coords set to NULL. [Since 2.9] ‘Default values’ means the currently selected named instance (or the base font if no named instance is selected).

-

[Since 2.9] If num_coords is larger than zero, this function sets the FT_FACE_FLAG_VARIATION bit in FT_Face's face_flags field (i.e., FT_IS_VARIATION will return true). If num_coords is zero, this bit flag gets unset.

-
- -

FT_Get_MM_Blend_Coordinates

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_MM_Blend_Coordinates( FT_Face    face,
-                               FT_UInt    num_coords,
-                               FT_Fixed*  coords );
-
- -

Get the normalized blend coordinates of the currently selected interpolated font.

-

This function works with all supported variation formats.

-

input

- - - - -
face -

A handle to the source face.

-
num_coords -

The number of normalized blend coordinates to retrieve. If it is larger than the number of axes, set the excess values to 0.5 for Adobe MM fonts, and to 0 for TrueType GX and OpenType variation fonts.

-
- -

output

- - - -
coords -

The normalized blend coordinates array.

-
- -

return

- -

FreeType error code. 0 means success.

-

since

- -

2.7.1

-
- -

FT_Set_Var_Blend_Coordinates

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  FT_EXPORT( FT_Error )
-  FT_Set_Var_Blend_Coordinates( FT_Face    face,
-                                FT_UInt    num_coords,
-                                FT_Fixed*  coords );
-
- -

This is another name of FT_Set_MM_Blend_Coordinates.

-
- -

FT_Get_Var_Blend_Coordinates

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_Var_Blend_Coordinates( FT_Face    face,
-                                FT_UInt    num_coords,
-                                FT_Fixed*  coords );
-
- -

This is another name of FT_Get_MM_Blend_Coordinates.

-

since

- -

2.7.1

-
- -

FT_Set_MM_WeightVector

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  FT_EXPORT( FT_Error )
-  FT_Set_MM_WeightVector( FT_Face    face,
-                          FT_UInt    len,
-                          FT_Fixed*  weightvector );
-
- -

For Adobe MM fonts, choose an interpolated font design by directly setting the weight vector.

-

This function can't be used with TrueType GX or OpenType variation fonts.

-

inout

- - - -
face -

A handle to the source face.

-
- -

input

- - - - -
len -

The length of the weight vector array. If it is larger than the number of designs, the extra values are ignored. If it is less than the number of designs, the remaining values are set to zero.

-
weightvector -

An array representing the weight vector.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

Adobe Multiple Master fonts limit the number of designs, and thus the length of the weight vector to 16.

-

If len is zero and weightvector is NULL, the weight vector array is reset to the default values.

-

The Adobe documentation also states that the values in the WeightVector array must total 1.0 ± 0.001. In practice this does not seem to be enforced, so is not enforced here, either.

-

since

- -

2.10

-
- -

FT_Get_MM_WeightVector

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_MM_WeightVector( FT_Face    face,
-                          FT_UInt*   len,
-                          FT_Fixed*  weightvector );
-
- -

For Adobe MM fonts, retrieve the current weight vector of the font.

-

This function can't be used with TrueType GX or OpenType variation fonts.

-

inout

- - - - -
face -

A handle to the source face.

-
len -

A pointer to the size of the array to be filled. If the size of the array is less than the number of designs, FT_Err_Invalid_Argument is returned, and len is set to the required size (the number of designs). If the size of the array is greater than the number of designs, the remaining entries are set to 0. On successful completion, len is set to the number of designs (i.e., the number of values written to the array).

-
- -

output

- - - -
weightvector -

An array to be filled.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

Adobe Multiple Master fonts limit the number of designs, and thus the length of the WeightVector to 16.

-

since

- -

2.10

-
- -

FT_VAR_AXIS_FLAG_XXX

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

- - -

A list of bit flags used in the return value of FT_Get_Var_Axis_Flags.

-

values

- - - -
FT_VAR_AXIS_FLAG_HIDDEN -

The variation axis should not be exposed to user interfaces.

-
- -

since

- -

2.8.1

-
- -

FT_Get_Var_Axis_Flags

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_Var_Axis_Flags( FT_MM_Var*  master,
-                         FT_UInt     axis_index,
-                         FT_UInt*    flags );
-
- -

Get the ‘flags’ field of an OpenType Variation Axis Record.

-

Not meaningful for Adobe MM fonts (*flags is always zero).

-

input

- - - - -
master -

The variation descriptor.

-
axis_index -

The index of the requested variation axis.

-
- -

output

- - - -
flags -

The ‘flags’ field. See FT_VAR_AXIS_FLAG_XXX for possible values.

-
- -

return

- -

FreeType error code. 0 means success.

-

since

- -

2.8.1

-
- -

FT_Set_Named_Instance

-

Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h).

-
  FT_EXPORT( FT_Error )
-  FT_Set_Named_Instance( FT_Face  face,
-                         FT_UInt  instance_index );
-
- -

Set or change the current named instance.

-

input

- - - - -
face -

A handle to the source face.

-
instance_index -

The index of the requested instance, starting with value 1. If set to value 0, FreeType switches to font access without a named instance.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The function uses the value of instance_index to set bits 16-30 of the face's face_index field. It also resets any variation applied to the font, and the FT_FACE_FLAG_VARIATION bit of the face's face_flags field gets reset to zero (i.e., FT_IS_VARIATION will return false).

-

For Adobe MM fonts (which don't have named instances) this function simply resets the current face to the default instance.

-

since

- -

2.9

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-ot_validation.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-ot_validation.html deleted file mode 100644 index a3dca8fe0..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-ot_validation.html +++ /dev/null @@ -1,1306 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OpenType Validation - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Miscellaneous » OpenType Validation

-
-

OpenType Validation

-

Synopsis

-

This section contains the declaration of functions to validate some OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH).

-

FT_OpenType_Validate

-

Defined in FT_OPENTYPE_VALIDATE_H (freetype/ftotval.h).

-
  FT_EXPORT( FT_Error )
-  FT_OpenType_Validate( FT_Face    face,
-                        FT_UInt    validation_flags,
-                        FT_Bytes  *BASE_table,
-                        FT_Bytes  *GDEF_table,
-                        FT_Bytes  *GPOS_table,
-                        FT_Bytes  *GSUB_table,
-                        FT_Bytes  *JSTF_table );
-
- -

Validate various OpenType tables to assure that all offsets and indices are valid. The idea is that a higher-level library that actually does the text layout can access those tables without error checking (which can be quite time consuming).

-

input

- - - - -
face -

A handle to the input face.

-
validation_flags -

A bit field that specifies the tables to be validated. See FT_VALIDATE_OTXXX for possible values.

-
- -

output

- - - - - - - -
BASE_table -

A pointer to the BASE table.

-
GDEF_table -

A pointer to the GDEF table.

-
GPOS_table -

A pointer to the GPOS table.

-
GSUB_table -

A pointer to the GSUB table.

-
JSTF_table -

A pointer to the JSTF table.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function only works with OpenType fonts, returning an error otherwise.

-

After use, the application should deallocate the five tables with FT_OpenType_Free. A NULL value indicates that the table either doesn't exist in the font, or the application hasn't asked for validation.

-
- -

FT_OpenType_Free

-

Defined in FT_OPENTYPE_VALIDATE_H (freetype/ftotval.h).

-
  FT_EXPORT( void )
-  FT_OpenType_Free( FT_Face   face,
-                    FT_Bytes  table );
-
- -

Free the buffer allocated by OpenType validator.

-

input

- - - - -
face -

A handle to the input face.

-
table -

The pointer to the buffer that is allocated by FT_OpenType_Validate.

-
- -

note

- -

This function must be used to free the buffer allocated by FT_OpenType_Validate only.

-
- -

FT_VALIDATE_OTXXX

-

Defined in FT_OPENTYPE_VALIDATE_H (freetype/ftotval.h).

-
#define FT_VALIDATE_BASE  0x0100
-#define FT_VALIDATE_GDEF  0x0200
-#define FT_VALIDATE_GPOS  0x0400
-#define FT_VALIDATE_GSUB  0x0800
-#define FT_VALIDATE_JSTF  0x1000
-#define FT_VALIDATE_MATH  0x2000
-
-#define FT_VALIDATE_OT  ( FT_VALIDATE_BASE | \
-                          FT_VALIDATE_GDEF | \
-                          FT_VALIDATE_GPOS | \
-                          FT_VALIDATE_GSUB | \
-                          FT_VALIDATE_JSTF | \
-                          FT_VALIDATE_MATH )
-
- -

A list of bit-field constants used with FT_OpenType_Validate to indicate which OpenType tables should be validated.

-

values

- - - - - - - - - -
FT_VALIDATE_BASE -

Validate BASE table.

-
FT_VALIDATE_GDEF -

Validate GDEF table.

-
FT_VALIDATE_GPOS -

Validate GPOS table.

-
FT_VALIDATE_GSUB -

Validate GSUB table.

-
FT_VALIDATE_JSTF -

Validate JSTF table.

-
FT_VALIDATE_MATH -

Validate MATH table.

-
FT_VALIDATE_OT -

Validate all OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH).

-
- -
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-outline_processing.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-outline_processing.html deleted file mode 100644 index c48861b35..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-outline_processing.html +++ /dev/null @@ -1,2250 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Outline Processing - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Support API » Outline Processing

-
-

Outline Processing

-

Synopsis

-

This section contains routines used to create and destroy scalable glyph images known as ‘outlines’. These can also be measured, transformed, and converted into bitmaps and pixmaps.

-

FT_Outline

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef struct  FT_Outline_
-  {
-    short       n_contours;      /* number of contours in glyph        */
-    short       n_points;        /* number of points in the glyph      */
-
-    FT_Vector*  points;          /* the outline's points               */
-    char*       tags;            /* the points flags                   */
-    short*      contours;        /* the contour end points             */
-
-    int         flags;           /* outline masks                      */
-
-  } FT_Outline;
-
- -

This structure is used to describe an outline to the scan-line converter.

-

fields

- - - - - - - - -
n_contours -

The number of contours in the outline.

-
n_points -

The number of points in the outline.

-
points -

A pointer to an array of n_points FT_Vector elements, giving the outline's point coordinates.

-
tags -

A pointer to an array of n_points chars, giving each outline point's type.

-

If bit 0 is unset, the point is ‘off’ the curve, i.e., a Bezier control point, while it is ‘on’ if set.

-

Bit 1 is meaningful for ‘off’ points only. If set, it indicates a third-order Bezier arc control point; and a second-order control point if unset.

-

If bit 2 is set, bits 5-7 contain the drop-out mode (as defined in the OpenType specification; the value is the same as the argument to the ‘SCANMODE’ instruction).

-

Bits 3 and 4 are reserved for internal purposes.

-
contours -

An array of n_contours shorts, giving the end point of each contour within the outline. For example, the first contour is defined by the points ‘0’ to contours[0], the second one is defined by the points contours[0]+1 to contours[1], etc.

-
flags -

A set of bit flags used to characterize the outline and give hints to the scan-converter and hinter on how to convert/grid-fit it. See FT_OUTLINE_XXX.

-
- -

note

- -

The B/W rasterizer only checks bit 2 in the tags array for the first point of each contour. The drop-out mode as given with FT_OUTLINE_IGNORE_DROPOUTS, FT_OUTLINE_SMART_DROPOUTS, and FT_OUTLINE_INCLUDE_STUBS in flags is then overridden.

-
- -

FT_Outline_New

-

Defined in FT_OUTLINE_H (freetype/ftoutln.h).

-
  FT_EXPORT( FT_Error )
-  FT_Outline_New( FT_Library   library,
-                  FT_UInt      numPoints,
-                  FT_Int       numContours,
-                  FT_Outline  *anoutline );
-
- -

Create a new outline of a given size.

-

input

- - - - - -
library -

A handle to the library object from where the outline is allocated. Note however that the new outline will not necessarily be freed, when destroying the library, by FT_Done_FreeType.

-
numPoints -

The maximum number of points within the outline. Must be smaller than or equal to 0xFFFF (65535).

-
numContours -

The maximum number of contours within the outline. This value must be in the range 0 to numPoints.

-
- -

output

- - - -
anoutline -

A handle to the new outline.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The reason why this function takes a library parameter is simply to use the library's memory allocator.

-
- -

FT_Outline_Done

-

Defined in FT_OUTLINE_H (freetype/ftoutln.h).

-
  FT_EXPORT( FT_Error )
-  FT_Outline_Done( FT_Library   library,
-                   FT_Outline*  outline );
-
- -

Destroy an outline created with FT_Outline_New.

-

input

- - - - -
library -

A handle of the library object used to allocate the outline.

-
outline -

A pointer to the outline object to be discarded.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

If the outline's ‘owner’ field is not set, only the outline descriptor will be released.

-
- -

FT_Outline_Copy

-

Defined in FT_OUTLINE_H (freetype/ftoutln.h).

-
  FT_EXPORT( FT_Error )
-  FT_Outline_Copy( const FT_Outline*  source,
-                   FT_Outline        *target );
-
- -

Copy an outline into another one. Both objects must have the same sizes (number of points & number of contours) when this function is called.

-

input

- - - -
source -

A handle to the source outline.

-
- -

output

- - - -
target -

A handle to the target outline.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FT_Outline_Translate

-

Defined in FT_OUTLINE_H (freetype/ftoutln.h).

-
  FT_EXPORT( void )
-  FT_Outline_Translate( const FT_Outline*  outline,
-                        FT_Pos             xOffset,
-                        FT_Pos             yOffset );
-
- -

Apply a simple translation to the points of an outline.

-

inout

- - - -
outline -

A pointer to the target outline descriptor.

-
- -

input

- - - - -
xOffset -

The horizontal offset.

-
yOffset -

The vertical offset.

-
- -
- -

FT_Outline_Transform

-

Defined in FT_OUTLINE_H (freetype/ftoutln.h).

-
  FT_EXPORT( void )
-  FT_Outline_Transform( const FT_Outline*  outline,
-                        const FT_Matrix*   matrix );
-
- -

Apply a simple 2x2 matrix to all of an outline's points. Useful for applying rotations, slanting, flipping, etc.

-

inout

- - - -
outline -

A pointer to the target outline descriptor.

-
- -

input

- - - -
matrix -

A pointer to the transformation matrix.

-
- -

note

- -

You can use FT_Outline_Translate if you need to translate the outline's points.

-
- -

FT_Outline_Embolden

-

Defined in FT_OUTLINE_H (freetype/ftoutln.h).

-
  FT_EXPORT( FT_Error )
-  FT_Outline_Embolden( FT_Outline*  outline,
-                       FT_Pos       strength );
-
- -

Embolden an outline. The new outline will be at most 4 times strength pixels wider and higher. You may think of the left and bottom borders as unchanged.

-

Negative strength values to reduce the outline thickness are possible also.

-

inout

- - - -
outline -

A handle to the target outline.

-
- -

input

- - - -
strength -

How strong the glyph is emboldened. Expressed in 26.6 pixel format.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The used algorithm to increase or decrease the thickness of the glyph doesn't change the number of points; this means that certain situations like acute angles or intersections are sometimes handled incorrectly.

-

If you need ‘better’ metrics values you should call FT_Outline_Get_CBox or FT_Outline_Get_BBox.

-

To get meaningful results, font scaling values must be set with functions like FT_Set_Char_Size before calling FT_Render_Glyph.

-

example

- -
  FT_Load_Glyph( face, index, FT_LOAD_DEFAULT );
-
-  if ( face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
-    FT_Outline_Embolden( &face->glyph->outline, strength );
-
- -
- -

FT_Outline_EmboldenXY

-

Defined in FT_OUTLINE_H (freetype/ftoutln.h).

-
  FT_EXPORT( FT_Error )
-  FT_Outline_EmboldenXY( FT_Outline*  outline,
-                         FT_Pos       xstrength,
-                         FT_Pos       ystrength );
-
- -

Embolden an outline. The new outline will be xstrength pixels wider and ystrength pixels higher. Otherwise, it is similar to FT_Outline_Embolden, which uses the same strength in both directions.

-

since

- -

2.4.10

-
- -

FT_Outline_Reverse

-

Defined in FT_OUTLINE_H (freetype/ftoutln.h).

-
  FT_EXPORT( void )
-  FT_Outline_Reverse( FT_Outline*  outline );
-
- -

Reverse the drawing direction of an outline. This is used to ensure consistent fill conventions for mirrored glyphs.

-

inout

- - - -
outline -

A pointer to the target outline descriptor.

-
- -

note

- -

This function toggles the bit flag FT_OUTLINE_REVERSE_FILL in the outline's flags field.

-

It shouldn't be used by a normal client application, unless it knows what it is doing.

-
- -

FT_Outline_Check

-

Defined in FT_OUTLINE_H (freetype/ftoutln.h).

-
  FT_EXPORT( FT_Error )
-  FT_Outline_Check( FT_Outline*  outline );
-
- -

Check the contents of an outline descriptor.

-

input

- - - -
outline -

A handle to a source outline.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

An empty outline, or an outline with a single point only is also valid.

-
- -

FT_Outline_Get_CBox

-

Defined in FT_OUTLINE_H (freetype/ftoutln.h).

-
  FT_EXPORT( void )
-  FT_Outline_Get_CBox( const FT_Outline*  outline,
-                       FT_BBox           *acbox );
-
- -

Return an outline's ‘control box’. The control box encloses all the outline's points, including Bezier control points. Though it coincides with the exact bounding box for most glyphs, it can be slightly larger in some situations (like when rotating an outline that contains Bezier outside arcs).

-

Computing the control box is very fast, while getting the bounding box can take much more time as it needs to walk over all segments and arcs in the outline. To get the latter, you can use the ‘ftbbox’ component, which is dedicated to this single task.

-

input

- - - -
outline -

A pointer to the source outline descriptor.

-
- -

output

- - - -
acbox -

The outline's control box.

-
- -

note

- -

See FT_Glyph_Get_CBox for a discussion of tricky fonts.

-
- -

FT_Outline_Get_BBox

-

Defined in FT_BBOX_H (freetype/ftbbox.h).

-
  FT_EXPORT( FT_Error )
-  FT_Outline_Get_BBox( FT_Outline*  outline,
-                       FT_BBox     *abbox );
-
- -

Compute the exact bounding box of an outline. This is slower than computing the control box. However, it uses an advanced algorithm that returns very quickly when the two boxes coincide. Otherwise, the outline Bezier arcs are traversed to extract their extrema.

-

input

- - - -
outline -

A pointer to the source outline.

-
- -

output

- - - -
abbox -

The outline's exact bounding box.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

If the font is tricky and the glyph has been loaded with FT_LOAD_NO_SCALE, the resulting BBox is meaningless. To get reasonable values for the BBox it is necessary to load the glyph at a large ppem value (so that the hinting instructions can properly shift and scale the subglyphs), then extracting the BBox, which can be eventually converted back to font units.

-
- -

FT_Outline_Get_Bitmap

-

Defined in FT_OUTLINE_H (freetype/ftoutln.h).

-
  FT_EXPORT( FT_Error )
-  FT_Outline_Get_Bitmap( FT_Library        library,
-                         FT_Outline*       outline,
-                         const FT_Bitmap  *abitmap );
-
- -

Render an outline within a bitmap. The outline's image is simply OR-ed to the target bitmap.

-

input

- - - - -
library -

A handle to a FreeType library object.

-
outline -

A pointer to the source outline descriptor.

-
- -

inout

- - - -
abitmap -

A pointer to the target bitmap descriptor.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function does not create the bitmap, it only renders an outline image within the one you pass to it! Consequently, the various fields in abitmap should be set accordingly.

-

It will use the raster corresponding to the default glyph format.

-

The value of the num_grays field in abitmap is ignored. If you select the gray-level rasterizer, and you want less than 256 gray levels, you have to use FT_Outline_Render directly.

-
- -

FT_Outline_Render

-

Defined in FT_OUTLINE_H (freetype/ftoutln.h).

-
  FT_EXPORT( FT_Error )
-  FT_Outline_Render( FT_Library         library,
-                     FT_Outline*        outline,
-                     FT_Raster_Params*  params );
-
- -

Render an outline within a bitmap using the current scan-convert.

-

input

- - - - -
library -

A handle to a FreeType library object.

-
outline -

A pointer to the source outline descriptor.

-
- -

inout

- - - -
params -

A pointer to an FT_Raster_Params structure used to describe the rendering operation.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This advanced function uses FT_Raster_Params as an argument. The field params.source will be set to outline before the scan converter is called, which means that the value you give to it is actually ignored. Either params.target must point to preallocated bitmap, or FT_RASTER_FLAG_DIRECT must be set in params.flags allowing FreeType rasterizer to be used for direct composition, translucency, etc. See FT_Raster_Params for more details.

-
- -

FT_Outline_Decompose

-

Defined in FT_OUTLINE_H (freetype/ftoutln.h).

-
  FT_EXPORT( FT_Error )
-  FT_Outline_Decompose( FT_Outline*              outline,
-                        const FT_Outline_Funcs*  func_interface,
-                        void*                    user );
-
- -

Walk over an outline's structure to decompose it into individual segments and Bezier arcs. This function also emits ‘move to’ operations to indicate the start of new contours in the outline.

-

input

- - - - -
outline -

A pointer to the source target.

-
func_interface -

A table of ‘emitters’, i.e., function pointers called during decomposition to indicate path operations.

-
- -

inout

- - - -
user -

A typeless pointer that is passed to each emitter during the decomposition. It can be used to store the state during the decomposition.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

A contour that contains a single point only is represented by a ‘move to’ operation followed by ‘line to’ to the same point. In most cases, it is best to filter this out before using the outline for stroking purposes (otherwise it would result in a visible dot when round caps are used).

-

Similarly, the function returns success for an empty outline also (doing nothing, this is, not calling any emitter); if necessary, you should filter this out, too.

-
- -

FT_Outline_Funcs

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef struct  FT_Outline_Funcs_
-  {
-    FT_Outline_MoveToFunc   move_to;
-    FT_Outline_LineToFunc   line_to;
-    FT_Outline_ConicToFunc  conic_to;
-    FT_Outline_CubicToFunc  cubic_to;
-
-    int                     shift;
-    FT_Pos                  delta;
-
-  } FT_Outline_Funcs;
-
- -

A structure to hold various function pointers used during outline decomposition in order to emit segments, conic, and cubic Beziers.

-

fields

- - - - - - - - -
move_to -

The ‘move to’ emitter.

-
line_to -

The segment emitter.

-
conic_to -

The second-order Bezier arc emitter.

-
cubic_to -

The third-order Bezier arc emitter.

-
shift -

The shift that is applied to coordinates before they are sent to the emitter.

-
delta -

The delta that is applied to coordinates before they are sent to the emitter, but after the shift.

-
- -

note

- -

The point coordinates sent to the emitters are the transformed version of the original coordinates (this is important for high accuracy during scan-conversion). The transformation is simple: -

  x' = (x << shift) - delta
-  y' = (y << shift) - delta
-

-

Set the values of shift and delta to 0 to get the original point coordinates.

-
- -

FT_Outline_MoveToFunc

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef int
-  (*FT_Outline_MoveToFunc)( const FT_Vector*  to,
-                            void*             user );
-
-#define FT_Outline_MoveTo_Func  FT_Outline_MoveToFunc
-
- -

A function pointer type used to describe the signature of a ‘move to’ function during outline walking/decomposition.

-

A ‘move to’ is emitted to start a new contour in an outline.

-

input

- - - - -
to -

A pointer to the target point of the ‘move to’.

-
user -

A typeless pointer, which is passed from the caller of the decomposition function.

-
- -

return

- -

Error code. 0 means success.

-
- -

FT_Outline_LineToFunc

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef int
-  (*FT_Outline_LineToFunc)( const FT_Vector*  to,
-                            void*             user );
-
-#define FT_Outline_LineTo_Func  FT_Outline_LineToFunc
-
- -

A function pointer type used to describe the signature of a ‘line to’ function during outline walking/decomposition.

-

A ‘line to’ is emitted to indicate a segment in the outline.

-

input

- - - - -
to -

A pointer to the target point of the ‘line to’.

-
user -

A typeless pointer, which is passed from the caller of the decomposition function.

-
- -

return

- -

Error code. 0 means success.

-
- -

FT_Outline_ConicToFunc

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef int
-  (*FT_Outline_ConicToFunc)( const FT_Vector*  control,
-                             const FT_Vector*  to,
-                             void*             user );
-
-#define FT_Outline_ConicTo_Func  FT_Outline_ConicToFunc
-
- -

A function pointer type used to describe the signature of a ‘conic to’ function during outline walking or decomposition.

-

A ‘conic to’ is emitted to indicate a second-order Bezier arc in the outline.

-

input

- - - - - -
control -

An intermediate control point between the last position and the new target in to.

-
to -

A pointer to the target end point of the conic arc.

-
user -

A typeless pointer, which is passed from the caller of the decomposition function.

-
- -

return

- -

Error code. 0 means success.

-
- -

FT_Outline_CubicToFunc

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef int
-  (*FT_Outline_CubicToFunc)( const FT_Vector*  control1,
-                             const FT_Vector*  control2,
-                             const FT_Vector*  to,
-                             void*             user );
-
-#define FT_Outline_CubicTo_Func  FT_Outline_CubicToFunc
-
- -

A function pointer type used to describe the signature of a ‘cubic to’ function during outline walking or decomposition.

-

A ‘cubic to’ is emitted to indicate a third-order Bezier arc.

-

input

- - - - - - -
control1 -

A pointer to the first Bezier control point.

-
control2 -

A pointer to the second Bezier control point.

-
to -

A pointer to the target end point.

-
user -

A typeless pointer, which is passed from the caller of the decomposition function.

-
- -

return

- -

Error code. 0 means success.

-
- -

FT_Orientation

-

Defined in FT_OUTLINE_H (freetype/ftoutln.h).

- - -

A list of values used to describe an outline's contour orientation.

-

The TrueType and PostScript specifications use different conventions to determine whether outline contours should be filled or unfilled.

-

values

- - - - - - - -
FT_ORIENTATION_TRUETYPE -

According to the TrueType specification, clockwise contours must be filled, and counter-clockwise ones must be unfilled.

-
FT_ORIENTATION_POSTSCRIPT -

According to the PostScript specification, counter-clockwise contours must be filled, and clockwise ones must be unfilled.

-
FT_ORIENTATION_FILL_RIGHT -

This is identical to FT_ORIENTATION_TRUETYPE, but is used to remember that in TrueType, everything that is to the right of the drawing direction of a contour must be filled.

-
FT_ORIENTATION_FILL_LEFT -

This is identical to FT_ORIENTATION_POSTSCRIPT, but is used to remember that in PostScript, everything that is to the left of the drawing direction of a contour must be filled.

-
FT_ORIENTATION_NONE -

The orientation cannot be determined. That is, different parts of the glyph have different orientation.

-
- -
- -

FT_Outline_Get_Orientation

-

Defined in FT_OUTLINE_H (freetype/ftoutln.h).

-
  FT_EXPORT( FT_Orientation )
-  FT_Outline_Get_Orientation( FT_Outline*  outline );
-
- -

This function analyzes a glyph outline and tries to compute its fill orientation (see FT_Orientation). This is done by integrating the total area covered by the outline. The positive integral corresponds to the clockwise orientation and FT_ORIENTATION_POSTSCRIPT is returned. The negative integral corresponds to the counter-clockwise orientation and FT_ORIENTATION_TRUETYPE is returned.

-

Note that this will return FT_ORIENTATION_TRUETYPE for empty outlines.

-

input

- - - -
outline -

A handle to the source outline.

-
- -

return

- -

The orientation.

-
- -

FT_OUTLINE_XXX

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
#define FT_OUTLINE_NONE             0x0
-#define FT_OUTLINE_OWNER            0x1
-#define FT_OUTLINE_EVEN_ODD_FILL    0x2
-#define FT_OUTLINE_REVERSE_FILL     0x4
-#define FT_OUTLINE_IGNORE_DROPOUTS  0x8
-#define FT_OUTLINE_SMART_DROPOUTS   0x10
-#define FT_OUTLINE_INCLUDE_STUBS    0x20
-#define FT_OUTLINE_OVERLAP          0x40
-
-#define FT_OUTLINE_HIGH_PRECISION   0x100
-#define FT_OUTLINE_SINGLE_PASS      0x200
-
-
-  /* these constants are deprecated; use the corresponding */
-  /* `FT_OUTLINE_XXX` values instead                       */
-#define ft_outline_none             FT_OUTLINE_NONE
-#define ft_outline_owner            FT_OUTLINE_OWNER
-#define ft_outline_even_odd_fill    FT_OUTLINE_EVEN_ODD_FILL
-#define ft_outline_reverse_fill     FT_OUTLINE_REVERSE_FILL
-#define ft_outline_ignore_dropouts  FT_OUTLINE_IGNORE_DROPOUTS
-#define ft_outline_high_precision   FT_OUTLINE_HIGH_PRECISION
-#define ft_outline_single_pass      FT_OUTLINE_SINGLE_PASS
-
- -

A list of bit-field constants used for the flags in an outline's flags field.

-

values

- - - - - - - - - - - - -
FT_OUTLINE_NONE -

Value 0 is reserved.

-
FT_OUTLINE_OWNER -

If set, this flag indicates that the outline's field arrays (i.e., points, flags, and contours) are ‘owned’ by the outline object, and should thus be freed when it is destroyed.

-
FT_OUTLINE_EVEN_ODD_FILL -

By default, outlines are filled using the non-zero winding rule. If set to 1, the outline will be filled using the even-odd fill rule (only works with the smooth rasterizer).

-
FT_OUTLINE_REVERSE_FILL -

By default, outside contours of an outline are oriented in clock-wise direction, as defined in the TrueType specification. This flag is set if the outline uses the opposite direction (typically for Type 1 fonts). This flag is ignored by the scan converter.

-
FT_OUTLINE_IGNORE_DROPOUTS -

By default, the scan converter will try to detect drop-outs in an outline and correct the glyph bitmap to ensure consistent shape continuity. If set, this flag hints the scan-line converter to ignore such cases. See below for more information.

-
FT_OUTLINE_SMART_DROPOUTS -

Select smart dropout control. If unset, use simple dropout control. Ignored if FT_OUTLINE_IGNORE_DROPOUTS is set. See below for more information.

-
FT_OUTLINE_INCLUDE_STUBS -

If set, turn pixels on for ‘stubs’, otherwise exclude them. Ignored if FT_OUTLINE_IGNORE_DROPOUTS is set. See below for more information.

-
FT_OUTLINE_OVERLAP -

This flag indicates that this outline contains overlapping contrours and the anti-aliased renderer should perform oversampling to mitigate possible artifacts. This flag should not be set for well designed glyphs without overlaps because it quadruples the rendering time.

-
FT_OUTLINE_HIGH_PRECISION -

This flag indicates that the scan-line converter should try to convert this outline to bitmaps with the highest possible quality. It is typically set for small character sizes. Note that this is only a hint that might be completely ignored by a given scan-converter.

-
FT_OUTLINE_SINGLE_PASS -

This flag is set to force a given scan-converter to only use a single pass over the outline to render a bitmap glyph image. Normally, it is set for very large character sizes. It is only a hint that might be completely ignored by a given scan-converter.

-
- -

note

- -

The flags FT_OUTLINE_IGNORE_DROPOUTS, FT_OUTLINE_SMART_DROPOUTS, and FT_OUTLINE_INCLUDE_STUBS are ignored by the smooth rasterizer.

-

There exists a second mechanism to pass the drop-out mode to the B/W rasterizer; see the tags field in FT_Outline.

-

Please refer to the description of the ‘SCANTYPE’ instruction in the OpenType specification (in file ttinst1.doc) how simple drop-outs, smart drop-outs, and stubs are defined.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-parameter_tags.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-parameter_tags.html deleted file mode 100644 index a7d050b59..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-parameter_tags.html +++ /dev/null @@ -1,1334 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Parameter Tags - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Controlling FreeType Modules » Parameter Tags

-
-

Parameter Tags

-

Synopsis

-

This section contains macros for the FT_Parameter structure that are used with various functions to activate some special functionality or different behaviour of various components of FreeType.

-

FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY

-
#define FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY \
-          FT_MAKE_TAG( 'i', 'g', 'p', 'f' )
-
-  /* this constant is deprecated */
-#define FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY \
-          FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY
-
- -

A tag for FT_Parameter to make FT_Open_Face ignore typographic family names in the ‘name’ table (introduced in OpenType version 1.4). Use this for backward compatibility with legacy systems that have a four-faces-per-family restriction.

-

since

- -

2.8

-
- -

FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY

-
#define FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY \
-          FT_MAKE_TAG( 'i', 'g', 'p', 's' )
-
-  /* this constant is deprecated */
-#define FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY \
-          FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY
-
- -

A tag for FT_Parameter to make FT_Open_Face ignore typographic subfamily names in the ‘name’ table (introduced in OpenType version 1.4). Use this for backward compatibility with legacy systems that have a four-faces-per-family restriction.

-

since

- -

2.8

-
- -

FT_PARAM_TAG_INCREMENTAL

-
#define FT_PARAM_TAG_INCREMENTAL \
-          FT_MAKE_TAG( 'i', 'n', 'c', 'r' )
-
- -

An FT_Parameter tag to be used with FT_Open_Face to indicate incremental glyph loading.

-
- -

FT_PARAM_TAG_LCD_FILTER_WEIGHTS

-
#define FT_PARAM_TAG_LCD_FILTER_WEIGHTS \
-          FT_MAKE_TAG( 'l', 'c', 'd', 'f' )
-
- -

An FT_Parameter tag to be used with FT_Face_Properties. The corresponding argument specifies the five LCD filter weights for a given face (if using FT_LOAD_TARGET_LCD, for example), overriding the global default values or the values set up with FT_Library_SetLcdFilterWeights.

-

since

- -

2.8

-
- -

FT_PARAM_TAG_RANDOM_SEED

-
#define FT_PARAM_TAG_RANDOM_SEED \
-          FT_MAKE_TAG( 's', 'e', 'e', 'd' )
-
- -

An FT_Parameter tag to be used with FT_Face_Properties. The corresponding 32bit signed integer argument overrides the font driver's random seed value with a face-specific one; see random-seed.

-

since

- -

2.8

-
- -

FT_PARAM_TAG_STEM_DARKENING

-
#define FT_PARAM_TAG_STEM_DARKENING \
-          FT_MAKE_TAG( 'd', 'a', 'r', 'k' )
-
- -

An FT_Parameter tag to be used with FT_Face_Properties. The corresponding Boolean argument specifies whether to apply stem darkening, overriding the global default values or the values set up with FT_Property_Set (see no-stem-darkening).

-

This is a passive setting that only takes effect if the font driver or autohinter honors it, which the CFF, Type 1, and CID drivers always do, but the autohinter only in ‘light’ hinting mode (as of version 2.9).

-

since

- -

2.8

-
- -

FT_PARAM_TAG_UNPATENTED_HINTING

-
#define FT_PARAM_TAG_UNPATENTED_HINTING \
-          FT_MAKE_TAG( 'u', 'n', 'p', 'a' )
-
- -

Deprecated, no effect.

-

Previously: A constant used as the tag of an FT_Parameter structure to indicate that unpatented methods only should be used by the TrueType bytecode interpreter for a typeface opened by FT_Open_Face.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-pcf_driver.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-pcf_driver.html deleted file mode 100644 index dc6d71cb6..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-pcf_driver.html +++ /dev/null @@ -1,1157 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The PCF driver - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
- -
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-pfr_fonts.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-pfr_fonts.html deleted file mode 100644 index bd9d14c6c..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-pfr_fonts.html +++ /dev/null @@ -1,1318 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PFR Fonts - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Format-Specific API » PFR Fonts

-
-

PFR Fonts

-

Synopsis

-

This section contains the declaration of PFR-specific functions.

-

FT_Get_PFR_Metrics

-

Defined in FT_PFR_H (freetype/ftpfr.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_PFR_Metrics( FT_Face    face,
-                      FT_UInt   *aoutline_resolution,
-                      FT_UInt   *ametrics_resolution,
-                      FT_Fixed  *ametrics_x_scale,
-                      FT_Fixed  *ametrics_y_scale );
-
- -

Return the outline and metrics resolutions of a given PFR face.

-

input

- - - -
face -

Handle to the input face. It can be a non-PFR face.

-
- -

output

- - - - - - -
aoutline_resolution -

Outline resolution. This is equivalent to face->units_per_EM for non-PFR fonts. Optional (parameter can be NULL).

-
ametrics_resolution -

Metrics resolution. This is equivalent to outline_resolution for non-PFR fonts. Optional (parameter can be NULL).

-
ametrics_x_scale -

A 16.16 fixed-point number used to scale distance expressed in metrics units to device subpixels. This is equivalent to face->size->x_scale, but for metrics only. Optional (parameter can be NULL).

-
ametrics_y_scale -

Same as ametrics_x_scale but for the vertical direction. optional (parameter can be NULL).

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

If the input face is not a PFR, this function will return an error. However, in all cases, it will return valid values.

-
- -

FT_Get_PFR_Kerning

-

Defined in FT_PFR_H (freetype/ftpfr.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_PFR_Kerning( FT_Face     face,
-                      FT_UInt     left,
-                      FT_UInt     right,
-                      FT_Vector  *avector );
-
- -

Return the kerning pair corresponding to two glyphs in a PFR face. The distance is expressed in metrics units, unlike the result of FT_Get_Kerning.

-

input

- - - - - -
face -

A handle to the input face.

-
left -

Index of the left glyph.

-
-

Index of the right glyph.

-
- -

output

- - - -
avector -

A kerning vector.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function always return distances in original PFR metrics units. This is unlike FT_Get_Kerning with the FT_KERNING_UNSCALED mode, which always returns distances converted to outline units.

-

You can use the value of the x_scale and y_scale parameters returned by FT_Get_PFR_Metrics to scale these to device subpixels.

-
- -

FT_Get_PFR_Advance

-

Defined in FT_PFR_H (freetype/ftpfr.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_PFR_Advance( FT_Face   face,
-                      FT_UInt   gindex,
-                      FT_Pos   *aadvance );
-
- -

Return a given glyph advance, expressed in original metrics units, from a PFR font.

-

input

- - - - -
face -

A handle to the input face.

-
gindex -

The glyph index.

-
- -

output

- - - -
aadvance -

The glyph advance in metrics units.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

You can use the x_scale or y_scale results of FT_Get_PFR_Metrics to convert the advance to device subpixels (i.e., 1/64th of pixels).

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-properties.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-properties.html deleted file mode 100644 index 99449520e..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-properties.html +++ /dev/null @@ -1,1906 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Driver properties - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Controlling FreeType Modules » Driver properties

-
-

Driver properties

-

Synopsis

-

Driver modules can be controlled by setting and unsetting properties, using the functions FT_Property_Set and FT_Property_Get. This section documents the available properties, together with auxiliary macros and structures.

-

FT_HINTING_XXX

-

Defined in FT_DRIVER_H (freetype/ftdriver.h).

-
#define FT_HINTING_FREETYPE  0
-#define FT_HINTING_ADOBE     1
-
-  /* these constants (introduced in 2.4.12) are deprecated */
-#define FT_CFF_HINTING_FREETYPE  FT_HINTING_FREETYPE
-#define FT_CFF_HINTING_ADOBE     FT_HINTING_ADOBE
-
- -

A list of constants used for the hinting-engine property to select the hinting engine for CFF, Type 1, and CID fonts.

-

values

- - - - -
FT_HINTING_FREETYPE -

Use the old FreeType hinting engine.

-
FT_HINTING_ADOBE -

Use the hinting engine contributed by Adobe.

-
- -

since

- -

2.9

-
- -

hinting-engine

-

Thanks to Adobe, which contributed a new hinting (and parsing) engine, an application can select between ‘freetype’ and ‘adobe’ if compiled with CFF_CONFIG_OPTION_OLD_ENGINE. If this configuration macro isn't defined, ‘hinting-engine’ does nothing.

-

The same holds for the Type 1 and CID modules if compiled with T1_CONFIG_OPTION_OLD_ENGINE.

-

For the ‘cff’ module, the default engine is ‘freetype’ if CFF_CONFIG_OPTION_OLD_ENGINE is defined, and ‘adobe’ otherwise.

-

For both the ‘type1’ and ‘t1cid’ modules, the default engine is ‘freetype’ if T1_CONFIG_OPTION_OLD_ENGINE is defined, and ‘adobe’ otherwise.

-

note

- -

This property can be used with FT_Property_Get also.

-

This property can be set via the FREETYPE_PROPERTIES environment variable (using values ‘adobe’ or ‘freetype’).

-

example

- -

The following example code demonstrates how to select Adobe's hinting engine for the ‘cff’ module (omitting the error handling). -

  FT_Library  library;
-  FT_UInt     hinting_engine = FT_HINTING_ADOBE;
-
-
-  FT_Init_FreeType( &library );
-
-  FT_Property_Set( library, "cff",
-                            "hinting-engine", &hinting_engine );
-

-

since

- -

2.4.12 (for ‘cff’ module)

-

2.9 (for ‘type1’ and ‘t1cid’ modules)

-
- -

no-stem-darkening

-

All glyphs that pass through the auto-hinter will be emboldened unless this property is set to TRUE. The same is true for the CFF, Type 1, and CID font modules if the ‘Adobe’ engine is selected (which is the default).

-

Stem darkening emboldens glyphs at smaller sizes to make them more readable on common low-DPI screens when using linear alpha blending and gamma correction, see FT_Render_Glyph. When not using linear alpha blending and gamma correction, glyphs will appear heavy and fuzzy!

-

Gamma correction essentially lightens fonts since shades of grey are shifted to higher pixel values (= higher brightness) to match the original intention to the reality of our screens. The side-effect is that glyphs ‘thin out’. Mac OS X and Adobe's proprietary font rendering library implement a counter-measure: stem darkening at smaller sizes where shades of gray dominate. By emboldening a glyph slightly in relation to its pixel size, individual pixels get higher coverage of filled-in outlines and are therefore ‘blacker’. This counteracts the ‘thinning out’ of glyphs, making text remain readable at smaller sizes.

-

For the auto-hinter, stem-darkening is experimental currently and thus switched off by default (this is, no-stem-darkening is set to TRUE by default). Total consistency with the CFF driver is not achieved right now because the emboldening method differs and glyphs must be scaled down on the Y-axis to keep outline points inside their precomputed blue zones. The smaller the size (especially 9ppem and down), the higher the loss of emboldening versus the CFF driver.

-

Note that stem darkening is never applied if FT_LOAD_NO_SCALE is set.

-

note

- -

This property can be used with FT_Property_Get also.

-

This property can be set via the FREETYPE_PROPERTIES environment variable (using values 1 and 0 for ‘on’ and ‘off’, respectively). It can also be set per face using FT_Face_Properties with FT_PARAM_TAG_STEM_DARKENING.

-

example

- -
  FT_Library  library;
-  FT_Bool     no_stem_darkening = TRUE;
-
-
-  FT_Init_FreeType( &library );
-
-  FT_Property_Set( library, "cff",
-                            "no-stem-darkening", &no_stem_darkening );
-
- -

since

- -

2.4.12 (for ‘cff’ module)

-

2.6.2 (for ‘autofitter’ module)

-

2.9 (for ‘type1’ and ‘t1cid’ modules)

-
- -

darkening-parameters

-

By default, the Adobe hinting engine, as used by the CFF, Type 1, and CID font drivers, darkens stems as follows (if the no-stem-darkening property isn't set): -

  stem width <= 0.5px:   darkening amount = 0.4px
-  stem width  = 1px:     darkening amount = 0.275px
-  stem width  = 1.667px: darkening amount = 0.275px
-  stem width >= 2.333px: darkening amount = 0px
-

-

and piecewise linear in-between. At configuration time, these four control points can be set with the macro CFF_CONFIG_OPTION_DARKENING_PARAMETERS; the CFF, Type 1, and CID drivers share these values. At runtime, the control points can be changed using the darkening-parameters property (see the example below that demonstrates this for the Type 1 driver).

-

The x values give the stem width, and the y values the darkening amount. The unit is 1000th of pixels. All coordinate values must be positive; the x values must be monotonically increasing; the y values must be monotonically decreasing and smaller than or equal to 500 (corresponding to half a pixel); the slope of each linear piece must be shallower than -1 (e.g., -.4).

-

The auto-hinter provides this property, too, as an experimental feature. See no-stem-darkening for more.

-

note

- -

This property can be used with FT_Property_Get also.

-

This property can be set via the FREETYPE_PROPERTIES environment variable, using eight comma-separated integers without spaces. Here the above example, using \ to break the line for readability. -

  FREETYPE_PROPERTIES=\
-  type1:darkening-parameters=500,300,1000,200,1500,100,2000,0
-

-

example

- -
  FT_Library  library;
-  FT_Int      darken_params[8] = {  500, 300,   // x1, y1
-                                   1000, 200,   // x2, y2
-                                   1500, 100,   // x3, y3
-                                   2000,   0 }; // x4, y4
-
-
-  FT_Init_FreeType( &library );
-
-  FT_Property_Set( library, "type1",
-                            "darkening-parameters", darken_params );
-
- -

since

- -

2.5.1 (for ‘cff’ module)

-

2.6.2 (for ‘autofitter’ module)

-

2.9 (for ‘type1’ and ‘t1cid’ modules)

-
- -

random-seed

-

By default, the seed value for the CFF ‘random’ operator and the similar ‘0 28 callothersubr pop’ command for the Type 1 and CID drivers is set to a random value. However, mainly for debugging purposes, it is often necessary to use a known value as a seed so that the pseudo-random number sequences generated by ‘random’ are repeatable.

-

The random-seed property does that. Its argument is a signed 32bit integer; if the value is zero or negative, the seed given by the intitialRandomSeed private DICT operator in a CFF file gets used (or a default value if there is no such operator). If the value is positive, use it instead of initialRandomSeed, which is consequently ignored.

-

note

- -

This property can be set via the FREETYPE_PROPERTIES environment variable. It can also be set per face using FT_Face_Properties with FT_PARAM_TAG_RANDOM_SEED.

-

since

- -

2.8 (for ‘cff’ module)

-

2.9 (for ‘type1’ and ‘t1cid’ modules)

-
- -

no-long-family-names

-

If PCF_CONFIG_OPTION_LONG_FAMILY_NAMES is active while compiling FreeType, the PCF driver constructs long family names.

-

There are many PCF fonts just called ‘Fixed’ which look completely different, and which have nothing to do with each other. When selecting ‘Fixed’ in KDE or Gnome one gets results that appear rather random, the style changes often if one changes the size and one cannot select some fonts at all. The improve this situation, the PCF module prepends the foundry name (plus a space) to the family name. It also checks whether there are ‘wide’ characters; all put together, family names like ‘Sony Fixed’ or ‘Misc Fixed Wide’ are constructed.

-

If no-long-family-names is set, this feature gets switched off.

-

note

- -

This property can be used with FT_Property_Get also.

-

This property can be set via the FREETYPE_PROPERTIES environment variable (using values 1 and 0 for ‘on’ and ‘off’, respectively).

-

example

- -
  FT_Library  library;
-  FT_Bool     no_long_family_names = TRUE;
-
-
-  FT_Init_FreeType( &library );
-
-  FT_Property_Set( library, "pcf",
-                            "no-long-family-names",
-                            &no_long_family_names );
-
- -

since

- -

2.8

-
- -

TT_INTERPRETER_VERSION_XXX

-

Defined in FT_DRIVER_H (freetype/ftdriver.h).

- - -

A list of constants used for the interpreter-version property to select the hinting engine for Truetype fonts.

-

The numeric value in the constant names represents the version number as returned by the ‘GETINFO’ bytecode instruction.

-

values

- - - - - -
TT_INTERPRETER_VERSION_35 -

Version 35 corresponds to MS rasterizer v.1.7 as used e.g. in Windows 98; only grayscale and B/W rasterizing is supported.

-
TT_INTERPRETER_VERSION_38 -

Version 38 corresponds to MS rasterizer v.1.9; it is roughly equivalent to the hinting provided by DirectWrite ClearType (as can be found, for example, in the Internet Explorer 9 running on Windows 7). It is used in FreeType to select the ‘Infinality’ subpixel hinting code. The code may be removed in a future version.

-
TT_INTERPRETER_VERSION_40 -

Version 40 corresponds to MS rasterizer v.2.1; it is roughly equivalent to the hinting provided by DirectWrite ClearType (as can be found, for example, in Microsoft's Edge Browser on Windows 10). It is used in FreeType to select the ‘minimal’ subpixel hinting code, a stripped-down and higher performance version of the ‘Infinality’ code.

-
- -

note

- -

This property controls the behaviour of the bytecode interpreter and thus how outlines get hinted. It does not control how glyph get rasterized! In particular, it does not control subpixel color filtering.

-

If FreeType has not been compiled with the configuration option TT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version 38 or 40 causes an FT_Err_Unimplemented_Feature error.

-

Depending on the graphics framework, Microsoft uses different bytecode and rendering engines. As a consequence, the version numbers returned by a call to the ‘GETINFO’ bytecode instruction are more convoluted than desired.

-

Here are two tables that try to shed some light on the possible values for the MS rasterizer engine, together with the additional features introduced by it. -

  GETINFO framework               version feature
-  -------------------------------------------------------------------
-      3   GDI (Win 3.1),            v1.0  16-bit, first version
-          TrueImage
-     33   GDI (Win NT 3.1),         v1.5  32-bit
-          HP Laserjet
-     34   GDI (Win 95)              v1.6  font smoothing,
-                                          new SCANTYPE opcode
-     35   GDI (Win 98/2000)         v1.7  (UN)SCALED_COMPONENT_OFFSET
-                                            bits in composite glyphs
-     36   MGDI (Win CE 2)           v1.6+ classic ClearType
-     37   GDI (XP and later),       v1.8  ClearType
-          GDI+ old (before Vista)
-     38   GDI+ old (Vista, Win 7),  v1.9  subpixel ClearType,
-          WPF                             Y-direction ClearType,
-                                          additional error checking
-     39   DWrite (before Win 8)     v2.0  subpixel ClearType flags
-                                            in GETINFO opcode,
-                                          bug fixes
-     40   GDI+ (after Win 7),       v2.1  Y-direction ClearType flag
-          DWrite (Win 8)                    in GETINFO opcode,
-                                          Gray ClearType
-

-

The ‘version’ field gives a rough orientation only, since some applications provided certain features much earlier (as an example, Microsoft Reader used subpixel and Y-direction ClearType already in Windows 2000). Similarly, updates to a given framework might include improved hinting support. -

   version   sampling          rendering        comment
-            x        y       x           y
-  --------------------------------------------------------------
-    v1.0   normal  normal  B/W           B/W    bi-level
-    v1.6   high    high    gray          gray   grayscale
-    v1.8   high    normal  color-filter  B/W    (GDI) ClearType
-    v1.9   high    high    color-filter  gray   Color ClearType
-    v2.1   high    normal  gray          B/W    Gray ClearType
-    v2.1   high    high    gray          gray   Gray ClearType
-

-

Color and Gray ClearType are the two available variants of ‘Y-direction ClearType’, meaning grayscale rasterization along the Y-direction; the name used in the TrueType specification for this feature is ‘symmetric smoothing’. ‘Classic ClearType’ is the original algorithm used before introducing a modified version in Win XP. Another name for v1.6's grayscale rendering is ‘font smoothing’, and ‘Color ClearType’ is sometimes also called ‘DWrite ClearType’. To differentiate between today's Color ClearType and the earlier ClearType variant with B/W rendering along the vertical axis, the latter is sometimes called ‘GDI ClearType’.

-

‘Normal’ and ‘high’ sampling describe the (virtual) resolution to access the rasterized outline after the hinting process. ‘Normal’ means 1 sample per grid line (i.e., B/W). In the current Microsoft implementation, ‘high’ means an extra virtual resolution of 16x16 (or 16x1) grid lines per pixel for bytecode instructions like ‘MIRP’. After hinting, these 16 grid lines are mapped to 6x5 (or 6x1) grid lines for color filtering if Color ClearType is activated.

-

Note that ‘Gray ClearType’ is essentially the same as v1.6's grayscale rendering. However, the GETINFO instruction handles it differently: v1.6 returns bit 12 (hinting for grayscale), while v2.1 returns bits 13 (hinting for ClearType), 18 (symmetrical smoothing), and 19 (Gray ClearType). Also, this mode respects bits 2 and 3 for the version 1 gasp table exclusively (like Color ClearType), while v1.6 only respects the values of version 0 (bits 0 and 1).

-

Keep in mind that the features of the above interpreter versions might not map exactly to FreeType features or behavior because it is a fundamentally different library with different internals.

-
- -

interpreter-version

-

Currently, three versions are available, two representing the bytecode interpreter with subpixel hinting support (old ‘Infinality’ code and new stripped-down and higher performance ‘minimal’ code) and one without, respectively. The default is subpixel support if TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined, and no subpixel support otherwise (since it isn't available then).

-

If subpixel hinting is on, many TrueType bytecode instructions behave differently compared to B/W or grayscale rendering (except if ‘native ClearType’ is selected by the font). Microsoft's main idea is to render at a much increased horizontal resolution, then sampling down the created output to subpixel precision. However, many older fonts are not suited to this and must be specially taken care of by applying (hardcoded) tweaks in Microsoft's interpreter.

-

Details on subpixel hinting and some of the necessary tweaks can be found in Greg Hitchcock's whitepaper at ‘https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx’. Note that FreeType currently doesn't really ‘subpixel hint’ (6x1, 6x2, or 6x5 supersampling) like discussed in the paper. Depending on the chosen interpreter, it simply ignores instructions on vertical stems to arrive at very similar results.

-

note

- -

This property can be used with FT_Property_Get also.

-

This property can be set via the FREETYPE_PROPERTIES environment variable (using values ‘35’, ‘38’, or ‘40’).

-

example

- -

The following example code demonstrates how to deactivate subpixel hinting (omitting the error handling). -

  FT_Library  library;
-  FT_Face     face;
-  FT_UInt     interpreter_version = TT_INTERPRETER_VERSION_35;
-
-
-  FT_Init_FreeType( &library );
-
-  FT_Property_Set( library, "truetype",
-                            "interpreter-version",
-                            &interpreter_version );
-

-

since

- -

2.5

-
- -

glyph-to-script-map

-

Experimental only

-

The auto-hinter provides various script modules to hint glyphs. Examples of supported scripts are Latin or CJK. Before a glyph is auto-hinted, the Unicode character map of the font gets examined, and the script is then determined based on Unicode character ranges, see below.

-

OpenType fonts, however, often provide much more glyphs than character codes (small caps, superscripts, ligatures, swashes, etc.), to be controlled by so-called ‘features’. Handling OpenType features can be quite complicated and thus needs a separate library on top of FreeType.

-

The mapping between glyph indices and scripts (in the auto-hinter sense, see the FT_AUTOHINTER_SCRIPT_XXX values) is stored as an array with num_glyphs elements, as found in the font's FT_Face structure. The glyph-to-script-map property returns a pointer to this array, which can be modified as needed. Note that the modification should happen before the first glyph gets processed by the auto-hinter so that the global analysis of the font shapes actually uses the modified mapping.

-

example

- -

The following example code demonstrates how to access it (omitting the error handling). -

  FT_Library                library;
-  FT_Face                   face;
-  FT_Prop_GlyphToScriptMap  prop;
-
-
-  FT_Init_FreeType( &library );
-  FT_New_Face( library, "foo.ttf", 0, &face );
-
-  prop.face = face;
-
-  FT_Property_Get( library, "autofitter",
-                            "glyph-to-script-map", &prop );
-
-  // adjust `prop.map' as needed right here
-
-  FT_Load_Glyph( face, ..., FT_LOAD_FORCE_AUTOHINT );
-

-

since

- -

2.4.11

-
- -

FT_AUTOHINTER_SCRIPT_XXX

-

Defined in FT_DRIVER_H (freetype/ftdriver.h).

- - -

Experimental only

-

A list of constants used for the glyph-to-script-map property to specify the script submodule the auto-hinter should use for hinting a particular glyph.

-

values

- - - - - - -
FT_AUTOHINTER_SCRIPT_NONE -

Don't auto-hint this glyph.

-
FT_AUTOHINTER_SCRIPT_LATIN -

Apply the latin auto-hinter. For the auto-hinter, ‘latin’ is a very broad term, including Cyrillic and Greek also since characters from those scripts share the same design constraints.

-

By default, characters from the following Unicode ranges are assigned to this submodule.

-
  U+0020 - U+007F  // Basic Latin (no control characters)
-  U+00A0 - U+00FF  // Latin-1 Supplement (no control characters)
-  U+0100 - U+017F  // Latin Extended-A
-  U+0180 - U+024F  // Latin Extended-B
-  U+0250 - U+02AF  // IPA Extensions
-  U+02B0 - U+02FF  // Spacing Modifier Letters
-  U+0300 - U+036F  // Combining Diacritical Marks
-  U+0370 - U+03FF  // Greek and Coptic
-  U+0400 - U+04FF  // Cyrillic
-  U+0500 - U+052F  // Cyrillic Supplement
-  U+1D00 - U+1D7F  // Phonetic Extensions
-  U+1D80 - U+1DBF  // Phonetic Extensions Supplement
-  U+1DC0 - U+1DFF  // Combining Diacritical Marks Supplement
-  U+1E00 - U+1EFF  // Latin Extended Additional
-  U+1F00 - U+1FFF  // Greek Extended
-  U+2000 - U+206F  // General Punctuation
-  U+2070 - U+209F  // Superscripts and Subscripts
-  U+20A0 - U+20CF  // Currency Symbols
-  U+2150 - U+218F  // Number Forms
-  U+2460 - U+24FF  // Enclosed Alphanumerics
-  U+2C60 - U+2C7F  // Latin Extended-C
-  U+2DE0 - U+2DFF  // Cyrillic Extended-A
-  U+2E00 - U+2E7F  // Supplemental Punctuation
-  U+A640 - U+A69F  // Cyrillic Extended-B
-  U+A720 - U+A7FF  // Latin Extended-D
-  U+FB00 - U+FB06  // Alphab. Present. Forms (Latin Ligatures)
- U+1D400 - U+1D7FF // Mathematical Alphanumeric Symbols
- U+1F100 - U+1F1FF // Enclosed Alphanumeric Supplement
-
-
FT_AUTOHINTER_SCRIPT_CJK -

Apply the CJK auto-hinter, covering Chinese, Japanese, Korean, old Vietnamese, and some other scripts.

-

By default, characters from the following Unicode ranges are assigned to this submodule.

-
  U+1100 - U+11FF  // Hangul Jamo
-  U+2E80 - U+2EFF  // CJK Radicals Supplement
-  U+2F00 - U+2FDF  // Kangxi Radicals
-  U+2FF0 - U+2FFF  // Ideographic Description Characters
-  U+3000 - U+303F  // CJK Symbols and Punctuation
-  U+3040 - U+309F  // Hiragana
-  U+30A0 - U+30FF  // Katakana
-  U+3100 - U+312F  // Bopomofo
-  U+3130 - U+318F  // Hangul Compatibility Jamo
-  U+3190 - U+319F  // Kanbun
-  U+31A0 - U+31BF  // Bopomofo Extended
-  U+31C0 - U+31EF  // CJK Strokes
-  U+31F0 - U+31FF  // Katakana Phonetic Extensions
-  U+3200 - U+32FF  // Enclosed CJK Letters and Months
-  U+3300 - U+33FF  // CJK Compatibility
-  U+3400 - U+4DBF  // CJK Unified Ideographs Extension A
-  U+4DC0 - U+4DFF  // Yijing Hexagram Symbols
-  U+4E00 - U+9FFF  // CJK Unified Ideographs
-  U+A960 - U+A97F  // Hangul Jamo Extended-A
-  U+AC00 - U+D7AF  // Hangul Syllables
-  U+D7B0 - U+D7FF  // Hangul Jamo Extended-B
-  U+F900 - U+FAFF  // CJK Compatibility Ideographs
-  U+FE10 - U+FE1F  // Vertical forms
-  U+FE30 - U+FE4F  // CJK Compatibility Forms
-  U+FF00 - U+FFEF  // Halfwidth and Fullwidth Forms
- U+1B000 - U+1B0FF // Kana Supplement
- U+1D300 - U+1D35F // Tai Xuan Hing Symbols
- U+1F200 - U+1F2FF // Enclosed Ideographic Supplement
- U+20000 - U+2A6DF // CJK Unified Ideographs Extension B
- U+2A700 - U+2B73F // CJK Unified Ideographs Extension C
- U+2B740 - U+2B81F // CJK Unified Ideographs Extension D
- U+2F800 - U+2FA1F // CJK Compatibility Ideographs Supplement
-
-
FT_AUTOHINTER_SCRIPT_INDIC -

Apply the indic auto-hinter, covering all major scripts from the Indian sub-continent and some other related scripts like Thai, Lao, or Tibetan.

-

By default, characters from the following Unicode ranges are assigned to this submodule.

-
  U+0900 - U+0DFF  // Indic Range
-  U+0F00 - U+0FFF  // Tibetan
-  U+1900 - U+194F  // Limbu
-  U+1B80 - U+1BBF  // Sundanese
-  U+A800 - U+A82F  // Syloti Nagri
-  U+ABC0 - U+ABFF  // Meetei Mayek
- U+11800 - U+118DF // Sharada
-
-

Note that currently Indic support is rudimentary only, missing blue zone support.

-
- -

since

- -

2.4.11

-
- -

FT_Prop_GlyphToScriptMap

-

Defined in FT_DRIVER_H (freetype/ftdriver.h).

-
  typedef struct  FT_Prop_GlyphToScriptMap_
-  {
-    FT_Face     face;
-    FT_UShort*  map;
-
-  } FT_Prop_GlyphToScriptMap;
-
- -

Experimental only

-

The data exchange structure for the glyph-to-script-map property.

-

since

- -

2.4.11

-
- -

fallback-script

-

Experimental only

-

If no auto-hinter script module can be assigned to a glyph, a fallback script gets assigned to it (see also the glyph-to-script-map property). By default, this is FT_AUTOHINTER_SCRIPT_CJK. Using the fallback-script property, this fallback value can be changed.

-

note

- -

This property can be used with FT_Property_Get also.

-

It's important to use the right timing for changing this value: The creation of the glyph-to-script map that eventually uses the fallback script value gets triggered either by setting or reading a face-specific property like glyph-to-script-map, or by auto-hinting any glyph from that face. In particular, if you have already created an FT_Face structure but not loaded any glyph (using the auto-hinter), a change of the fallback script will affect this face.

-

example

- -
  FT_Library  library;
-  FT_UInt     fallback_script = FT_AUTOHINTER_SCRIPT_NONE;
-
-
-  FT_Init_FreeType( &library );
-
-  FT_Property_Set( library, "autofitter",
-                            "fallback-script", &fallback_script );
-
- -

since

- -

2.4.11

-
- -

default-script

-

Experimental only

-

If FreeType gets compiled with FT_CONFIG_OPTION_USE_HARFBUZZ to make the HarfBuzz library access OpenType features for getting better glyph coverages, this property sets the (auto-fitter) script to be used for the default (OpenType) script data of a font's GSUB table. Features for the default script are intended for all scripts not explicitly handled in GSUB; an example is a ‘dlig’ feature, containing the combination of the characters ‘T’, ‘E’, and ‘L’ to form a ‘TEL’ ligature.

-

By default, this is FT_AUTOHINTER_SCRIPT_LATIN. Using the default-script property, this default value can be changed.

-

note

- -

This property can be used with FT_Property_Get also.

-

It's important to use the right timing for changing this value: The creation of the glyph-to-script map that eventually uses the default script value gets triggered either by setting or reading a face-specific property like glyph-to-script-map, or by auto-hinting any glyph from that face. In particular, if you have already created an FT_Face structure but not loaded any glyph (using the auto-hinter), a change of the default script will affect this face.

-

example

- -
  FT_Library  library;
-  FT_UInt     default_script = FT_AUTOHINTER_SCRIPT_NONE;
-
-
-  FT_Init_FreeType( &library );
-
-  FT_Property_Set( library, "autofitter",
-                            "default-script", &default_script );
-
- -

since

- -

2.5.3

-
- -

increase-x-height

-

For ppem values in the range 6 <= ppem <= increase-x-height, round up the font's x height much more often than normally. If the value is set to 0, which is the default, this feature is switched off. Use this property to improve the legibility of small font sizes if necessary.

-

note

- -

This property can be used with FT_Property_Get also.

-

Set this value right after calling FT_Set_Char_Size, but before loading any glyph (using the auto-hinter).

-

example

- -
  FT_Library               library;
-  FT_Face                  face;
-  FT_Prop_IncreaseXHeight  prop;
-
-
-  FT_Init_FreeType( &library );
-  FT_New_Face( library, "foo.ttf", 0, &face );
-  FT_Set_Char_Size( face, 10 * 64, 0, 72, 0 );
-
-  prop.face  = face;
-  prop.limit = 14;
-
-  FT_Property_Set( library, "autofitter",
-                            "increase-x-height", &prop );
-
- -

since

- -

2.4.11

-
- -

FT_Prop_IncreaseXHeight

-

Defined in FT_DRIVER_H (freetype/ftdriver.h).

-
  typedef struct  FT_Prop_IncreaseXHeight_
-  {
-    FT_Face  face;
-    FT_UInt  limit;
-
-  } FT_Prop_IncreaseXHeight;
-
- -

The data exchange structure for the increase-x-height property.

-
- -

warping

-

Experimental only

-

If FreeType gets compiled with option AF_CONFIG_OPTION_USE_WARPER to activate the warp hinting code in the auto-hinter, this property switches warping on and off.

-

Warping only works in ‘normal’ auto-hinting mode replacing it. The idea of the code is to slightly scale and shift a glyph along the non-hinted dimension (which is usually the horizontal axis) so that as much of its segments are aligned (more or less) to the grid. To find out a glyph's optimal scaling and shifting value, various parameter combinations are tried and scored.

-

By default, warping is off.

-

note

- -

This property can be used with FT_Property_Get also.

-

This property can be set via the FREETYPE_PROPERTIES environment variable (using values 1 and 0 for ‘on’ and ‘off’, respectively).

-

The warping code can also change advance widths. Have a look at the lsb_delta and rsb_delta fields in the FT_GlyphSlotRec structure for details on improving inter-glyph distances while rendering.

-

Since warping is a global property of the auto-hinter it is best to change its value before rendering any face. Otherwise, you should reload all faces that get auto-hinted in ‘normal’ hinting mode.

-

example

- -

This example shows how to switch on warping (omitting the error handling). -

  FT_Library  library;
-  FT_Bool     warping = 1;
-
-
-  FT_Init_FreeType( &library );
-
-  FT_Property_Set( library, "autofitter", "warping", &warping );
-

-

since

- -

2.6

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-quick_advance.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-quick_advance.html deleted file mode 100644 index 3fb8a56fa..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-quick_advance.html +++ /dev/null @@ -1,1297 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Quick retrieval of advance values - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Support API » Quick retrieval of advance values

-
-

Quick retrieval of advance values

-

Synopsis

-

This section contains functions to quickly extract advance values without handling glyph outlines, if possible.

-

FT_Get_Advance

-

Defined in FT_ADVANCES_H (freetype/ftadvanc.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_Advance( FT_Face    face,
-                  FT_UInt    gindex,
-                  FT_Int32   load_flags,
-                  FT_Fixed  *padvance );
-
- -

Retrieve the advance value of a given glyph outline in an FT_Face.

-

input

- - - - - -
face -

The source FT_Face handle.

-
gindex -

The glyph index.

-
load_flags -

A set of bit flags similar to those used when calling FT_Load_Glyph, used to determine what kind of advances you need.

-
- -

output

- - - -
padvance -

The advance value. If scaling is performed (based on the value of load_flags), the advance value is in 16.16 format. Otherwise, it is in font units.

-

If FT_LOAD_VERTICAL_LAYOUT is set, this is the vertical advance corresponding to a vertical layout. Otherwise, it is the horizontal advance in a horizontal layout.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function may fail if you use FT_ADVANCE_FLAG_FAST_ONLY and if the corresponding font backend doesn't have a quick way to retrieve the advances.

-

A scaled advance is returned in 16.16 format but isn't transformed by the affine transformation specified by FT_Set_Transform.

-
- -

FT_Get_Advances

-

Defined in FT_ADVANCES_H (freetype/ftadvanc.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_Advances( FT_Face    face,
-                   FT_UInt    start,
-                   FT_UInt    count,
-                   FT_Int32   load_flags,
-                   FT_Fixed  *padvances );
-
- -

Retrieve the advance values of several glyph outlines in an FT_Face.

-

input

- - - - - - -
face -

The source FT_Face handle.

-
start -

The first glyph index.

-
count -

The number of advance values you want to retrieve.

-
load_flags -

A set of bit flags similar to those used when calling FT_Load_Glyph.

-
- -

output

- - - -
padvance -

The advance values. This array, to be provided by the caller, must contain at least count elements.

-

If scaling is performed (based on the value of load_flags), the advance values are in 16.16 format. Otherwise, they are in font units.

-

If FT_LOAD_VERTICAL_LAYOUT is set, these are the vertical advances corresponding to a vertical layout. Otherwise, they are the horizontal advances in a horizontal layout.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function may fail if you use FT_ADVANCE_FLAG_FAST_ONLY and if the corresponding font backend doesn't have a quick way to retrieve the advances.

-

Scaled advances are returned in 16.16 format but aren't transformed by the affine transformation specified by FT_Set_Transform.

-
- -

FT_ADVANCE_FLAG_FAST_ONLY

-

Defined in FT_ADVANCES_H (freetype/ftadvanc.h).

-
#define FT_ADVANCE_FLAG_FAST_ONLY  0x20000000L
-
- -

A bit-flag to be OR-ed with the flags parameter of the FT_Get_Advance and FT_Get_Advances functions.

-

If set, it indicates that you want these functions to fail if the corresponding hinting mode or font driver doesn't allow for very quick advance computation.

-

Typically, glyphs that are either unscaled, unhinted, bitmapped, or light-hinted can have their advance width computed very quickly.

-

Normal and bytecode hinted modes that require loading, scaling, and hinting of the glyph outline, are extremely slow by comparison.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-raster.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-raster.html deleted file mode 100644 index c9bf6a6d6..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-raster.html +++ /dev/null @@ -1,1706 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Scanline Converter - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Support API » Scanline Converter

-
-

Scanline Converter

-

Synopsis

-

This section contains technical definitions.

-

FT_Raster

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef struct FT_RasterRec_*  FT_Raster;
-
- -

An opaque handle (pointer) to a raster object. Each object can be used independently to convert an outline into a bitmap or pixmap.

-
- -

FT_Span

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef struct  FT_Span_
-  {
-    short           x;
-    unsigned short  len;
-    unsigned char   coverage;
-
-  } FT_Span;
-
- -

A structure used to model a single span of gray pixels when rendering an anti-aliased bitmap.

-

fields

- - - - - -
x -

The span's horizontal start position.

-
len -

The span's length in pixels.

-
coverage -

The span color/coverage, ranging from 0 (background) to 255 (foreground).

-
- -

note

- -

This structure is used by the span drawing callback type named FT_SpanFunc that takes the y coordinate of the span as a parameter.

-

The coverage value is always between 0 and 255. If you want less gray values, the callback function has to reduce them.

-
- -

FT_SpanFunc

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef void
-  (*FT_SpanFunc)( int             y,
-                  int             count,
-                  const FT_Span*  spans,
-                  void*           user );
-
-#define FT_Raster_Span_Func  FT_SpanFunc
-
- -

A function used as a call-back by the anti-aliased renderer in order to let client applications draw themselves the gray pixel spans on each scan line.

-

input

- - - - - - -
y -

The scanline's upward y coordinate.

-
count -

The number of spans to draw on this scanline.

-
spans -

A table of count spans to draw on the scanline.

-
user -

User-supplied data that is passed to the callback.

-
- -

note

- -

This callback allows client applications to directly render the gray spans of the anti-aliased bitmap to any kind of surfaces.

-

This can be used to write anti-aliased outlines directly to a given background bitmap, and even perform translucency.

-
- -

FT_Raster_Params

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef struct  FT_Raster_Params_
-  {
-    const FT_Bitmap*        target;
-    const void*             source;
-    int                     flags;
-    FT_SpanFunc             gray_spans;
-    FT_SpanFunc             black_spans;  /* unused */
-    FT_Raster_BitTest_Func  bit_test;     /* unused */
-    FT_Raster_BitSet_Func   bit_set;      /* unused */
-    void*                   user;
-    FT_BBox                 clip_box;
-
-  } FT_Raster_Params;
-
- -

A structure to hold the parameters used by a raster's render function, passed as an argument to FT_Outline_Render.

-

fields

- - - - - - - - - - - -
target -

The target bitmap.

-
source -

A pointer to the source glyph image (e.g., an FT_Outline).

-
flags -

The rendering flags.

-
gray_spans -

The gray span drawing callback.

-
black_spans -

Unused.

-
bit_test -

Unused.

-
bit_set -

Unused.

-
user -

User-supplied data that is passed to each drawing callback.

-
clip_box -

An optional span clipping box expressed in integer pixels (not in 26.6 fixed-point units).

-
- -

note

- -

The FT_RASTER_FLAG_AA bit flag must be set in the flags to generate an anti-aliased glyph bitmap, otherwise a monochrome bitmap is generated. The target should have appropriate pixel mode and its dimensions define the clipping region.

-

If both FT_RASTER_FLAG_AA and FT_RASTER_FLAG_DIRECT bit flags are set in flags, the raster calls an FT_SpanFunc callback gray_spans with user data as an argument ignoring target. This allows direct composition over a pre-existing user surface to perform the span drawing and composition. To optionally clip the spans, set the FT_RASTER_FLAG_CLIP flag and clip_box. The monochrome raster does not support the direct mode.

-

The gray-level rasterizer always uses 256 gray levels. If you want fewer gray levels, you have to use FT_RASTER_FLAG_DIRECT and reduce the levels in the callback function.

-
- -

FT_RASTER_FLAG_XXX

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
#define FT_RASTER_FLAG_DEFAULT  0x0
-#define FT_RASTER_FLAG_AA       0x1
-#define FT_RASTER_FLAG_DIRECT   0x2
-#define FT_RASTER_FLAG_CLIP     0x4
-
-  /* these constants are deprecated; use the corresponding */
-  /* `FT_RASTER_FLAG_XXX` values instead                   */
-#define ft_raster_flag_default  FT_RASTER_FLAG_DEFAULT
-#define ft_raster_flag_aa       FT_RASTER_FLAG_AA
-#define ft_raster_flag_direct   FT_RASTER_FLAG_DIRECT
-#define ft_raster_flag_clip     FT_RASTER_FLAG_CLIP
-
- -

A list of bit flag constants as used in the flags field of a FT_Raster_Params structure.

-

values

- - - - - - -
FT_RASTER_FLAG_DEFAULT -

This value is 0.

-
FT_RASTER_FLAG_AA -

This flag is set to indicate that an anti-aliased glyph image should be generated. Otherwise, it will be monochrome (1-bit).

-
FT_RASTER_FLAG_DIRECT -

This flag is set to indicate direct rendering. In this mode, client applications must provide their own span callback. This lets them directly draw or compose over an existing bitmap. If this bit is not set, the target pixmap's buffer must be zeroed before rendering and the output will be clipped to its size.

-

Direct rendering is only possible with anti-aliased glyphs.

-
FT_RASTER_FLAG_CLIP -

This flag is only used in direct rendering mode. If set, the output will be clipped to a box specified in the clip_box field of the FT_Raster_Params structure. Otherwise, the clip_box is effectively set to the bounding box and all spans are generated.

-
- -
- -

FT_Raster_NewFunc

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef int
-  (*FT_Raster_NewFunc)( void*       memory,
-                        FT_Raster*  raster );
-
-#define FT_Raster_New_Func  FT_Raster_NewFunc
-
- -

A function used to create a new raster object.

-

input

- - - -
memory -

A handle to the memory allocator.

-
- -

output

- - - -
raster -

A handle to the new raster object.

-
- -

return

- -

Error code. 0 means success.

-

note

- -

The memory parameter is a typeless pointer in order to avoid un-wanted dependencies on the rest of the FreeType code. In practice, it is an FT_Memory object, i.e., a handle to the standard FreeType memory allocator. However, this field can be completely ignored by a given raster implementation.

-
- -

FT_Raster_DoneFunc

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef void
-  (*FT_Raster_DoneFunc)( FT_Raster  raster );
-
-#define FT_Raster_Done_Func  FT_Raster_DoneFunc
-
- -

A function used to destroy a given raster object.

-

input

- - - -
raster -

A handle to the raster object.

-
- -
- -

FT_Raster_ResetFunc

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef void
-  (*FT_Raster_ResetFunc)( FT_Raster       raster,
-                          unsigned char*  pool_base,
-                          unsigned long   pool_size );
-
-#define FT_Raster_Reset_Func  FT_Raster_ResetFunc
-
- -

FreeType used to provide an area of memory called the ‘render pool’ available to all registered rasterizers. This was not thread safe, however, and now FreeType never allocates this pool.

-

This function is called after a new raster object is created.

-

input

- - - - - -
raster -

A handle to the new raster object.

-
pool_base -

Previously, the address in memory of the render pool. Set this to NULL.

-
pool_size -

Previously, the size in bytes of the render pool. Set this to 0.

-
- -

note

- -

Rasterizers should rely on dynamic or stack allocation if they want to (a handle to the memory allocator is passed to the rasterizer constructor).

-
- -

FT_Raster_SetModeFunc

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef int
-  (*FT_Raster_SetModeFunc)( FT_Raster      raster,
-                            unsigned long  mode,
-                            void*          args );
-
-#define FT_Raster_Set_Mode_Func  FT_Raster_SetModeFunc
-
- -

This function is a generic facility to change modes or attributes in a given raster. This can be used for debugging purposes, or simply to allow implementation-specific ‘features’ in a given raster module.

-

input

- - - - - -
raster -

A handle to the new raster object.

-
mode -

A 4-byte tag used to name the mode or property.

-
args -

A pointer to the new mode/property to use.

-
- -
- -

FT_Raster_RenderFunc

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef int
-  (*FT_Raster_RenderFunc)( FT_Raster                raster,
-                           const FT_Raster_Params*  params );
-
-#define FT_Raster_Render_Func  FT_Raster_RenderFunc
-
- -

Invoke a given raster to scan-convert a given glyph image into a target bitmap.

-

input

- - - - -
raster -

A handle to the raster object.

-
params -

A pointer to an FT_Raster_Params structure used to store the rendering parameters.

-
- -

return

- -

Error code. 0 means success.

-

note

- -

The exact format of the source image depends on the raster's glyph format defined in its FT_Raster_Funcs structure. It can be an FT_Outline or anything else in order to support a large array of glyph formats.

-

Note also that the render function can fail and return a FT_Err_Unimplemented_Feature error code if the raster used does not support direct composition.

-
- -

FT_Raster_Funcs

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef struct  FT_Raster_Funcs_
-  {
-    FT_Glyph_Format        glyph_format;
-
-    FT_Raster_NewFunc      raster_new;
-    FT_Raster_ResetFunc    raster_reset;
-    FT_Raster_SetModeFunc  raster_set_mode;
-    FT_Raster_RenderFunc   raster_render;
-    FT_Raster_DoneFunc     raster_done;
-
-  } FT_Raster_Funcs;
-
- -

A structure used to describe a given raster class to the library.

-

fields

- - - - - - - -
glyph_format -

The supported glyph format for this raster.

-
raster_new -

The raster constructor.

-
raster_reset -

Used to reset the render pool within the raster.

-
raster_render -

A function to render a glyph into a given bitmap.

-
raster_done -

The raster destructor.

-
- -
- -

FT_Raster_BitTest_Func

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef int
-  (*FT_Raster_BitTest_Func)( int    y,
-                             int    x,
-                             void*  user );
-
- -

Deprecated, unimplemented.

-
- -

FT_Raster_BitSet_Func

-

Defined in FT_IMAGE_H (freetype/ftimage.h).

-
  typedef void
-  (*FT_Raster_BitSet_Func)( int    y,
-                            int    x,
-                            void*  user );
-
- -

Deprecated, unimplemented.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-sfnt_names.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-sfnt_names.html deleted file mode 100644 index a87ca65cd..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-sfnt_names.html +++ /dev/null @@ -1,1405 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SFNT Names - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Format-Specific API » SFNT Names

-
-

SFNT Names

-

Synopsis

-

The TrueType and OpenType specifications allow the inclusion of a special names table (‘name’) in font files. This table contains textual (and internationalized) information regarding the font, like family name, copyright, version, etc.

-

The definitions below are used to access them if available.

-

Note that this has nothing to do with glyph names!

-

FT_SfntName

-

Defined in FT_SFNT_NAMES_H (freetype/ftsnames.h).

-
  typedef struct  FT_SfntName_
-  {
-    FT_UShort  platform_id;
-    FT_UShort  encoding_id;
-    FT_UShort  language_id;
-    FT_UShort  name_id;
-
-    FT_Byte*   string;      /* this string is *not* null-terminated! */
-    FT_UInt    string_len;  /* in bytes                              */
-
-  } FT_SfntName;
-
- -

A structure used to model an SFNT ‘name’ table entry.

-

fields

- - - - - - - - -
platform_id -

The platform ID for string. See TT_PLATFORM_XXX for possible values.

-
encoding_id -

The encoding ID for string. See TT_APPLE_ID_XXX, TT_MAC_ID_XXX, TT_ISO_ID_XXX, TT_MS_ID_XXX, and TT_ADOBE_ID_XXX for possible values.

-
language_id -

The language ID for string. See TT_MAC_LANGID_XXX and TT_MS_LANGID_XXX for possible values.

-

Registered OpenType values for language_id are always smaller than 0x8000; values equal or larger than 0x8000 usually indicate a language tag string (introduced in OpenType version 1.6). Use function FT_Get_Sfnt_LangTag with language_id as its argument to retrieve the associated language tag.

-
name_id -

An identifier for string. See TT_NAME_ID_XXX for possible values.

-
string -

The ‘name’ string. Note that its format differs depending on the (platform,encoding) pair, being either a string of bytes (without a terminating NULL byte) or containing UTF-16BE entities.

-
string_len -

The length of string in bytes.

-
- -

note

- -

Please refer to the TrueType or OpenType specification for more details.

-
- -

FT_Get_Sfnt_Name_Count

-

Defined in FT_SFNT_NAMES_H (freetype/ftsnames.h).

-
  FT_EXPORT( FT_UInt )
-  FT_Get_Sfnt_Name_Count( FT_Face  face );
-
- -

Retrieve the number of name strings in the SFNT ‘name’ table.

-

input

- - - -
face -

A handle to the source face.

-
- -

return

- -

The number of strings in the ‘name’ table.

-

note

- -

This function always returns an error if the config macro TT_CONFIG_OPTION_SFNT_NAMES is not defined in ftoption.h.

-
- -

FT_Get_Sfnt_Name

-

Defined in FT_SFNT_NAMES_H (freetype/ftsnames.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_Sfnt_Name( FT_Face       face,
-                    FT_UInt       idx,
-                    FT_SfntName  *aname );
-
- -

Retrieve a string of the SFNT ‘name’ table for a given index.

-

input

- - - - -
face -

A handle to the source face.

-
idx -

The index of the ‘name’ string.

-
- -

output

- - - -
aname -

The indexed FT_SfntName structure.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The string array returned in the aname structure is not null-terminated. Note that you don't have to deallocate string by yourself; FreeType takes care of it if you call FT_Done_Face.

-

Use FT_Get_Sfnt_Name_Count to get the total number of available ‘name’ table entries, then do a loop until you get the right platform, encoding, and name ID.

-

‘name’ table format 1 entries can use language tags also, see FT_Get_Sfnt_LangTag.

-

This function always returns an error if the config macro TT_CONFIG_OPTION_SFNT_NAMES is not defined in ftoption.h.

-
- -

FT_SfntLangTag

-

Defined in FT_SFNT_NAMES_H (freetype/ftsnames.h).

-
  typedef struct  FT_SfntLangTag_
-  {
-    FT_Byte*  string;      /* this string is *not* null-terminated! */
-    FT_UInt   string_len;  /* in bytes                              */
-
-  } FT_SfntLangTag;
-
- -

A structure to model a language tag entry from an SFNT ‘name’ table.

-

fields

- - - - -
string -

The language tag string, encoded in UTF-16BE (without trailing NULL bytes).

-
string_len -

The length of string in bytes.

-
- -

note

- -

Please refer to the TrueType or OpenType specification for more details.

-

since

- -

2.8

-
- -

FT_Get_Sfnt_LangTag

-

Defined in FT_SFNT_NAMES_H (freetype/ftsnames.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_Sfnt_LangTag( FT_Face          face,
-                       FT_UInt          langID,
-                       FT_SfntLangTag  *alangTag );
-
- -

Retrieve the language tag associated with a language ID of an SFNT ‘name’ table entry.

-

input

- - - - -
face -

A handle to the source face.

-
langID -

The language ID, as returned by FT_Get_Sfnt_Name. This is always a value larger than 0x8000.

-
- -

output

- - - -
alangTag -

The language tag associated with the ‘name’ table entry's language ID.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The string array returned in the alangTag structure is not null-terminated. Note that you don't have to deallocate string by yourself; FreeType takes care of it if you call FT_Done_Face.

-

Only ‘name’ table format 1 supports language tags. For format 0 tables, this function always returns FT_Err_Invalid_Table. For invalid format 1 language ID values, FT_Err_Invalid_Argument is returned.

-

This function always returns an error if the config macro TT_CONFIG_OPTION_SFNT_NAMES is not defined in ftoption.h.

-

since

- -

2.8

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-sizes_management.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-sizes_management.html deleted file mode 100644 index 515e020b8..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-sizes_management.html +++ /dev/null @@ -1,1276 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Size Management - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Core API » Size Management

-
-

Size Management

-

Synopsis

-

When creating a new face object (e.g., with FT_New_Face), an FT_Size object is automatically created and used to store all pixel-size dependent information, available in the face->size field.

-

It is however possible to create more sizes for a given face, mostly in order to manage several character pixel sizes of the same font family and style. See FT_New_Size and FT_Done_Size.

-

Note that FT_Set_Pixel_Sizes and FT_Set_Char_Size only modify the contents of the current ‘active’ size; you thus need to use FT_Activate_Size to change it.

-

99% of applications won't need the functions provided here, especially if they use the caching sub-system, so be cautious when using these.

-

FT_New_Size

-

Defined in FT_SIZES_H (freetype/ftsizes.h).

-
  FT_EXPORT( FT_Error )
-  FT_New_Size( FT_Face   face,
-               FT_Size*  size );
-
- -

Create a new size object from a given face object.

-

input

- - - -
face -

A handle to a parent face object.

-
- -

output

- - - -
asize -

A handle to a new size object.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

You need to call FT_Activate_Size in order to select the new size for upcoming calls to FT_Set_Pixel_Sizes, FT_Set_Char_Size, FT_Load_Glyph, FT_Load_Char, etc.

-
- -

FT_Done_Size

-

Defined in FT_SIZES_H (freetype/ftsizes.h).

-
  FT_EXPORT( FT_Error )
-  FT_Done_Size( FT_Size  size );
-
- -

Discard a given size object. Note that FT_Done_Face automatically discards all size objects allocated with FT_New_Size.

-

input

- - - -
size -

A handle to a target size object.

-
- -

return

- -

FreeType error code. 0 means success.

-
- -

FT_Activate_Size

-

Defined in FT_SIZES_H (freetype/ftsizes.h).

-
  FT_EXPORT( FT_Error )
-  FT_Activate_Size( FT_Size  size );
-
- -

Even though it is possible to create several size objects for a given face (see FT_New_Size for details), functions like FT_Load_Glyph or FT_Load_Char only use the one that has been activated last to determine the ‘current character pixel size’.

-

This function can be used to ‘activate’ a previously created size object.

-

input

- - - -
size -

A handle to a target size object.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

If face is the size's parent face object, this function changes the value of face->size to the input size handle.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-system_interface.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-system_interface.html deleted file mode 100644 index 27a4a0f3b..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-system_interface.html +++ /dev/null @@ -1,1549 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - System Interface - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Support API » System Interface

-
-

System Interface

-

Synopsis

-

This section contains various definitions related to memory management and i/o access. You need to understand this information if you want to use a custom memory manager or you own i/o streams.

-

FT_Memory

-

Defined in FT_SYSTEM_H (freetype/ftsystem.h).

-
  typedef struct FT_MemoryRec_*  FT_Memory;
-
- -

A handle to a given memory manager object, defined with an FT_MemoryRec structure.

-
- -

FT_Alloc_Func

-

Defined in FT_SYSTEM_H (freetype/ftsystem.h).

-
  typedef void*
-  (*FT_Alloc_Func)( FT_Memory  memory,
-                    long       size );
-
- -

A function used to allocate size bytes from memory.

-

input

- - - - -
memory -

A handle to the source memory manager.

-
size -

The size in bytes to allocate.

-
- -

return

- -

Address of new memory block. 0 in case of failure.

-
- -

FT_Free_Func

-

Defined in FT_SYSTEM_H (freetype/ftsystem.h).

-
  typedef void
-  (*FT_Free_Func)( FT_Memory  memory,
-                   void*      block );
-
- -

A function used to release a given block of memory.

-

input

- - - - -
memory -

A handle to the source memory manager.

-
block -

The address of the target memory block.

-
- -
- -

FT_Realloc_Func

-

Defined in FT_SYSTEM_H (freetype/ftsystem.h).

-
  typedef void*
-  (*FT_Realloc_Func)( FT_Memory  memory,
-                      long       cur_size,
-                      long       new_size,
-                      void*      block );
-
- -

A function used to re-allocate a given block of memory.

-

input

- - - - - - -
memory -

A handle to the source memory manager.

-
cur_size -

The block's current size in bytes.

-
new_size -

The block's requested new size.

-
block -

The block's current address.

-
- -

return

- -

New block address. 0 in case of memory shortage.

-

note

- -

In case of error, the old block must still be available.

-
- -

FT_MemoryRec

-

Defined in FT_SYSTEM_H (freetype/ftsystem.h).

-
  struct  FT_MemoryRec_
-  {
-    void*            user;
-    FT_Alloc_Func    alloc;
-    FT_Free_Func     free;
-    FT_Realloc_Func  realloc;
-  };
-
- -

A structure used to describe a given memory manager to FreeType 2.

-

fields

- - - - - - -
user -

A generic typeless pointer for user data.

-
alloc -

A pointer type to an allocation function.

-
free -

A pointer type to an memory freeing function.

-
realloc -

A pointer type to a reallocation function.

-
- -
- -

FT_Stream

-

Defined in FT_SYSTEM_H (freetype/ftsystem.h).

-
  typedef struct FT_StreamRec_*  FT_Stream;
-
- -

A handle to an input stream.

-

also

- -

See FT_StreamRec for the publicly accessible fields of a given stream object.

-
- -

FT_StreamDesc

-

Defined in FT_SYSTEM_H (freetype/ftsystem.h).

-
  typedef union  FT_StreamDesc_
-  {
-    long   value;
-    void*  pointer;
-
-  } FT_StreamDesc;
-
- -

A union type used to store either a long or a pointer. This is used to store a file descriptor or a FILE* in an input stream.

-
- -

FT_Stream_IoFunc

-

Defined in FT_SYSTEM_H (freetype/ftsystem.h).

-
  typedef unsigned long
-  (*FT_Stream_IoFunc)( FT_Stream       stream,
-                       unsigned long   offset,
-                       unsigned char*  buffer,
-                       unsigned long   count );
-
- -

A function used to seek and read data from a given input stream.

-

input

- - - - - - -
stream -

A handle to the source stream.

-
offset -

The offset of read in stream (always from start).

-
buffer -

The address of the read buffer.

-
count -

The number of bytes to read from the stream.

-
- -

return

- -

The number of bytes effectively read by the stream.

-

note

- -

This function might be called to perform a seek or skip operation with a count of 0. A non-zero return value then indicates an error.

-
- -

FT_Stream_CloseFunc

-

Defined in FT_SYSTEM_H (freetype/ftsystem.h).

-
  typedef void
-  (*FT_Stream_CloseFunc)( FT_Stream  stream );
-
- -

A function used to close a given input stream.

-

input

- - - -
stream -

A handle to the target stream.

-
- -
- -

FT_StreamRec

-

Defined in FT_SYSTEM_H (freetype/ftsystem.h).

-
  typedef struct  FT_StreamRec_
-  {
-    unsigned char*       base;
-    unsigned long        size;
-    unsigned long        pos;
-
-    FT_StreamDesc        descriptor;
-    FT_StreamDesc        pathname;
-    FT_Stream_IoFunc     read;
-    FT_Stream_CloseFunc  close;
-
-    FT_Memory            memory;
-    unsigned char*       cursor;
-    unsigned char*       limit;
-
-  } FT_StreamRec;
-
- -

A structure used to describe an input stream.

-

input

- - - - - - - - - - - - -
base -

For memory-based streams, this is the address of the first stream byte in memory. This field should always be set to NULL for disk-based streams.

-
size -

The stream size in bytes.

-

In case of compressed streams where the size is unknown before actually doing the decompression, the value is set to 0x7FFFFFFF. (Note that this size value can occur for normal streams also; it is thus just a hint.)

-
pos -

The current position within the stream.

-
descriptor -

This field is a union that can hold an integer or a pointer. It is used by stream implementations to store file descriptors or FILE* pointers.

-
pathname -

This field is completely ignored by FreeType. However, it is often useful during debugging to use it to store the stream's filename (where available).

-
read -

The stream's input function.

-
close -

The stream's close function.

-
memory -

The memory manager to use to preload frames. This is set internally by FreeType and shouldn't be touched by stream implementations.

-
cursor -

This field is set and used internally by FreeType when parsing frames. In particular, the FT_GET_XXX macros use this instead of the pos field.

-
limit -

This field is set and used internally by FreeType when parsing frames.

-
- -
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-t1_cid_driver.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-t1_cid_driver.html deleted file mode 100644 index 37f2cf576..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-t1_cid_driver.html +++ /dev/null @@ -1,1160 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The Type 1 and CID drivers - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Controlling FreeType Modules » The Type 1 and CID drivers

-
-

The Type 1 and CID drivers

-

Synopsis

-

It is possible to control the behaviour of FreeType's Type 1 and Type 1 CID drivers with FT_Property_Set and FT_Property_Get.

-

Behind the scenes, both drivers use the Adobe CFF engine for hinting; however, the used properties must be specified separately.

-

The Type 1 driver's module name is ‘type1’; the CID driver's module name is ‘t1cid’.

-

Available properties are hinting-engine, no-stem-darkening, darkening-parameters, and random-seed, as documented in the ‘Driver properties’ section.

-

Please see the ‘The CFF driver’ section for more details on the new hinting engine.

- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-truetype_engine.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-truetype_engine.html deleted file mode 100644 index e673e477b..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-truetype_engine.html +++ /dev/null @@ -1,1237 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The TrueType Engine - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Miscellaneous » The TrueType Engine

-
-

The TrueType Engine

-

Synopsis

-

This section contains a function used to query the level of TrueType bytecode support compiled in this version of the library.

-

FT_TrueTypeEngineType

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  typedef enum  FT_TrueTypeEngineType_
-  {
-    FT_TRUETYPE_ENGINE_TYPE_NONE = 0,
-    FT_TRUETYPE_ENGINE_TYPE_UNPATENTED,
-    FT_TRUETYPE_ENGINE_TYPE_PATENTED
-
-  } FT_TrueTypeEngineType;
-
- -

A list of values describing which kind of TrueType bytecode engine is implemented in a given FT_Library instance. It is used by the FT_Get_TrueType_Engine_Type function.

-

values

- - - - - -
FT_TRUETYPE_ENGINE_TYPE_NONE -

The library doesn't implement any kind of bytecode interpreter.

-
FT_TRUETYPE_ENGINE_TYPE_UNPATENTED -

Deprecated and removed.

-
FT_TRUETYPE_ENGINE_TYPE_PATENTED -

The library implements a bytecode interpreter that covers the full instruction set of the TrueType virtual machine (this was governed by patents until May 2010, hence the name).

-
- -

since

- -

2.2

-
- -

FT_Get_TrueType_Engine_Type

-

Defined in FT_MODULE_H (freetype/ftmodapi.h).

-
  FT_EXPORT( FT_TrueTypeEngineType )
-  FT_Get_TrueType_Engine_Type( FT_Library  library );
-
- -

Return an FT_TrueTypeEngineType value to indicate which level of the TrueType virtual machine a given library instance supports.

-

input

- - - -
library -

A library instance.

-
- -

return

- -

A value indicating which level is supported.

-

since

- -

2.2

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-truetype_tables.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-truetype_tables.html deleted file mode 100644 index b6ee1d04c..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-truetype_tables.html +++ /dev/null @@ -1,3158 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TrueType Tables - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Format-Specific API » TrueType Tables

-
-

TrueType Tables

-

Synopsis

-

This section contains definitions of some basic tables specific to TrueType and OpenType as well as some routines used to access and process them.

-

TT_Header

-

Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h).

-
  typedef struct  TT_Header_
-  {
-    FT_Fixed   Table_Version;
-    FT_Fixed   Font_Revision;
-
-    FT_Long    CheckSum_Adjust;
-    FT_Long    Magic_Number;
-
-    FT_UShort  Flags;
-    FT_UShort  Units_Per_EM;
-
-    FT_ULong   Created [2];
-    FT_ULong   Modified[2];
-
-    FT_Short   xMin;
-    FT_Short   yMin;
-    FT_Short   xMax;
-    FT_Short   yMax;
-
-    FT_UShort  Mac_Style;
-    FT_UShort  Lowest_Rec_PPEM;
-
-    FT_Short   Font_Direction;
-    FT_Short   Index_To_Loc_Format;
-    FT_Short   Glyph_Data_Format;
-
-  } TT_Header;
-
- -

A structure to model a TrueType font header table. All fields follow the OpenType specification. The 64-bit timestamps are stored in two-element arrays Created and Modified, first the upper then the lower 32 bits.

-
- -

TT_HoriHeader

-

Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h).

-
  typedef struct  TT_HoriHeader_
-  {
-    FT_Fixed   Version;
-    FT_Short   Ascender;
-    FT_Short   Descender;
-    FT_Short   Line_Gap;
-
-    FT_UShort  advance_Width_Max;      /* advance width maximum */
-
-    FT_Short   min_Left_Side_Bearing;  /* minimum left-sb       */
-    FT_Short   min_Right_Side_Bearing; /* minimum right-sb      */
-    FT_Short   xMax_Extent;            /* xmax extents          */
-    FT_Short   caret_Slope_Rise;
-    FT_Short   caret_Slope_Run;
-    FT_Short   caret_Offset;
-
-    FT_Short   Reserved[4];
-
-    FT_Short   metric_Data_Format;
-    FT_UShort  number_Of_HMetrics;
-
-    /* The following fields are not defined by the OpenType specification */
-    /* but they are used to connect the metrics header to the relevant    */
-    /* 'hmtx' table.                                                      */
-
-    void*      long_metrics;
-    void*      short_metrics;
-
-  } TT_HoriHeader;
-
- -

A structure to model a TrueType horizontal header, the ‘hhea’ table, as well as the corresponding horizontal metrics table, ‘hmtx’.

-

fields

- - - - - - - - - - - - - - - - - - -
Version -

The table version.

-
Ascender -

The font's ascender, i.e., the distance from the baseline to the top-most of all glyph points found in the font.

-

This value is invalid in many fonts, as it is usually set by the font designer, and often reflects only a portion of the glyphs found in the font (maybe ASCII).

-

You should use the sTypoAscender field of the ‘OS/2’ table instead if you want the correct one.

-
Descender -

The font's descender, i.e., the distance from the baseline to the bottom-most of all glyph points found in the font. It is negative.

-

This value is invalid in many fonts, as it is usually set by the font designer, and often reflects only a portion of the glyphs found in the font (maybe ASCII).

-

You should use the sTypoDescender field of the ‘OS/2’ table instead if you want the correct one.

-
Line_Gap -

The font's line gap, i.e., the distance to add to the ascender and descender to get the BTB, i.e., the baseline-to-baseline distance for the font.

-
advance_Width_Max -

This field is the maximum of all advance widths found in the font. It can be used to compute the maximum width of an arbitrary string of text.

-
min_Left_Side_Bearing -

The minimum left side bearing of all glyphs within the font.

-
min_Right_Side_Bearing -

The minimum right side bearing of all glyphs within the font.

-
xMax_Extent -

The maximum horizontal extent (i.e., the ‘width’ of a glyph's bounding box) for all glyphs in the font.

-
caret_Slope_Rise -

The rise coefficient of the cursor's slope of the cursor (slope=rise/run).

-
caret_Slope_Run -

The run coefficient of the cursor's slope.

-
caret_Offset -

The cursor's offset for slanted fonts.

-
Reserved -

8 reserved bytes.

-
metric_Data_Format -

Always 0.

-
number_Of_HMetrics -

Number of HMetrics entries in the ‘hmtx’ table -- this value can be smaller than the total number of glyphs in the font.

-
long_metrics -

A pointer into the ‘hmtx’ table.

-
short_metrics -

A pointer into the ‘hmtx’ table.

-
- -

note

- -

For an OpenType variation font, the values of the following fields can change after a call to FT_Set_Var_Design_Coordinates (and friends) if the font contains an ‘MVAR’ table: caret_Slope_Rise, caret_Slope_Run, and caret_Offset.

-
- -

TT_VertHeader

-

Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h).

-
  typedef struct  TT_VertHeader_
-  {
-    FT_Fixed   Version;
-    FT_Short   Ascender;
-    FT_Short   Descender;
-    FT_Short   Line_Gap;
-
-    FT_UShort  advance_Height_Max;      /* advance height maximum */
-
-    FT_Short   min_Top_Side_Bearing;    /* minimum top-sb          */
-    FT_Short   min_Bottom_Side_Bearing; /* minimum bottom-sb       */
-    FT_Short   yMax_Extent;             /* ymax extents            */
-    FT_Short   caret_Slope_Rise;
-    FT_Short   caret_Slope_Run;
-    FT_Short   caret_Offset;
-
-    FT_Short   Reserved[4];
-
-    FT_Short   metric_Data_Format;
-    FT_UShort  number_Of_VMetrics;
-
-    /* The following fields are not defined by the OpenType specification */
-    /* but they are used to connect the metrics header to the relevant    */
-    /* 'vmtx' table.                                                      */
-
-    void*      long_metrics;
-    void*      short_metrics;
-
-  } TT_VertHeader;
-
- -

A structure used to model a TrueType vertical header, the ‘vhea’ table, as well as the corresponding vertical metrics table, ‘vmtx’.

-

fields

- - - - - - - - - - - - - - - - - - -
Version -

The table version.

-
Ascender -

The font's ascender, i.e., the distance from the baseline to the top-most of all glyph points found in the font.

-

This value is invalid in many fonts, as it is usually set by the font designer, and often reflects only a portion of the glyphs found in the font (maybe ASCII).

-

You should use the sTypoAscender field of the ‘OS/2’ table instead if you want the correct one.

-
Descender -

The font's descender, i.e., the distance from the baseline to the bottom-most of all glyph points found in the font. It is negative.

-

This value is invalid in many fonts, as it is usually set by the font designer, and often reflects only a portion of the glyphs found in the font (maybe ASCII).

-

You should use the sTypoDescender field of the ‘OS/2’ table instead if you want the correct one.

-
Line_Gap -

The font's line gap, i.e., the distance to add to the ascender and descender to get the BTB, i.e., the baseline-to-baseline distance for the font.

-
advance_Height_Max -

This field is the maximum of all advance heights found in the font. It can be used to compute the maximum height of an arbitrary string of text.

-
min_Top_Side_Bearing -

The minimum top side bearing of all glyphs within the font.

-
min_Bottom_Side_Bearing -

The minimum bottom side bearing of all glyphs within the font.

-
yMax_Extent -

The maximum vertical extent (i.e., the ‘height’ of a glyph's bounding box) for all glyphs in the font.

-
caret_Slope_Rise -

The rise coefficient of the cursor's slope of the cursor (slope=rise/run).

-
caret_Slope_Run -

The run coefficient of the cursor's slope.

-
caret_Offset -

The cursor's offset for slanted fonts.

-
Reserved -

8 reserved bytes.

-
metric_Data_Format -

Always 0.

-
number_Of_VMetrics -

Number of VMetrics entries in the ‘vmtx’ table -- this value can be smaller than the total number of glyphs in the font.

-
long_metrics -

A pointer into the ‘vmtx’ table.

-
short_metrics -

A pointer into the ‘vmtx’ table.

-
- -

note

- -

For an OpenType variation font, the values of the following fields can change after a call to FT_Set_Var_Design_Coordinates (and friends) if the font contains an ‘MVAR’ table: Ascender, Descender, Line_Gap, caret_Slope_Rise, caret_Slope_Run, and caret_Offset.

-
- -

TT_OS2

-

Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h).

-
  typedef struct  TT_OS2_
-  {
-    FT_UShort  version;                /* 0x0001 - more or 0xFFFF */
-    FT_Short   xAvgCharWidth;
-    FT_UShort  usWeightClass;
-    FT_UShort  usWidthClass;
-    FT_UShort  fsType;
-    FT_Short   ySubscriptXSize;
-    FT_Short   ySubscriptYSize;
-    FT_Short   ySubscriptXOffset;
-    FT_Short   ySubscriptYOffset;
-    FT_Short   ySuperscriptXSize;
-    FT_Short   ySuperscriptYSize;
-    FT_Short   ySuperscriptXOffset;
-    FT_Short   ySuperscriptYOffset;
-    FT_Short   yStrikeoutSize;
-    FT_Short   yStrikeoutPosition;
-    FT_Short   sFamilyClass;
-
-    FT_Byte    panose[10];
-
-    FT_ULong   ulUnicodeRange1;        /* Bits 0-31   */
-    FT_ULong   ulUnicodeRange2;        /* Bits 32-63  */
-    FT_ULong   ulUnicodeRange3;        /* Bits 64-95  */
-    FT_ULong   ulUnicodeRange4;        /* Bits 96-127 */
-
-    FT_Char    achVendID[4];
-
-    FT_UShort  fsSelection;
-    FT_UShort  usFirstCharIndex;
-    FT_UShort  usLastCharIndex;
-    FT_Short   sTypoAscender;
-    FT_Short   sTypoDescender;
-    FT_Short   sTypoLineGap;
-    FT_UShort  usWinAscent;
-    FT_UShort  usWinDescent;
-
-    /* only version 1 and higher: */
-
-    FT_ULong   ulCodePageRange1;       /* Bits 0-31   */
-    FT_ULong   ulCodePageRange2;       /* Bits 32-63  */
-
-    /* only version 2 and higher: */
-
-    FT_Short   sxHeight;
-    FT_Short   sCapHeight;
-    FT_UShort  usDefaultChar;
-    FT_UShort  usBreakChar;
-    FT_UShort  usMaxContext;
-
-    /* only version 5 and higher: */
-
-    FT_UShort  usLowerOpticalPointSize;       /* in twips (1/20th points) */
-    FT_UShort  usUpperOpticalPointSize;       /* in twips (1/20th points) */
-
-  } TT_OS2;
-
- -

A structure to model a TrueType ‘OS/2’ table. All fields comply to the OpenType specification.

-

Note that we now support old Mac fonts that do not include an ‘OS/2’ table. In this case, the version field is always set to 0xFFFF.

-

note

- -

For an OpenType variation font, the values of the following fields can change after a call to FT_Set_Var_Design_Coordinates (and friends) if the font contains an ‘MVAR’ table: sCapHeight, sTypoAscender, sTypoDescender, sTypoLineGap, sxHeight, usWinAscent, usWinDescent, yStrikeoutPosition, yStrikeoutSize, ySubscriptXOffset, ySubScriptXSize, ySubscriptYOffset, ySubscriptYSize, ySuperscriptXOffset, ySuperscriptXSize, ySuperscriptYOffset, and ySuperscriptYSize.

-

Possible values for bits in the ulUnicodeRangeX fields are given by the TT_UCR_XXX macros.

-
- -

TT_Postscript

-

Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h).

-
  typedef struct  TT_Postscript_
-  {
-    FT_Fixed  FormatType;
-    FT_Fixed  italicAngle;
-    FT_Short  underlinePosition;
-    FT_Short  underlineThickness;
-    FT_ULong  isFixedPitch;
-    FT_ULong  minMemType42;
-    FT_ULong  maxMemType42;
-    FT_ULong  minMemType1;
-    FT_ULong  maxMemType1;
-
-    /* Glyph names follow in the 'post' table, but we don't */
-    /* load them by default.                                */
-
-  } TT_Postscript;
-
- -

A structure to model a TrueType ‘post’ table. All fields comply to the OpenType specification. This structure does not reference a font's PostScript glyph names; use FT_Get_Glyph_Name to retrieve them.

-

note

- -

For an OpenType variation font, the values of the following fields can change after a call to FT_Set_Var_Design_Coordinates (and friends) if the font contains an ‘MVAR’ table: underlinePosition and underlineThickness.

-
- -

TT_PCLT

-

Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h).

-
  typedef struct  TT_PCLT_
-  {
-    FT_Fixed   Version;
-    FT_ULong   FontNumber;
-    FT_UShort  Pitch;
-    FT_UShort  xHeight;
-    FT_UShort  Style;
-    FT_UShort  TypeFamily;
-    FT_UShort  CapHeight;
-    FT_UShort  SymbolSet;
-    FT_Char    TypeFace[16];
-    FT_Char    CharacterComplement[8];
-    FT_Char    FileName[6];
-    FT_Char    StrokeWeight;
-    FT_Char    WidthType;
-    FT_Byte    SerifStyle;
-    FT_Byte    Reserved;
-
-  } TT_PCLT;
-
- -

A structure to model a TrueType ‘PCLT’ table. All fields comply to the OpenType specification.

-
- -

TT_MaxProfile

-

Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h).

-
  typedef struct  TT_MaxProfile_
-  {
-    FT_Fixed   version;
-    FT_UShort  numGlyphs;
-    FT_UShort  maxPoints;
-    FT_UShort  maxContours;
-    FT_UShort  maxCompositePoints;
-    FT_UShort  maxCompositeContours;
-    FT_UShort  maxZones;
-    FT_UShort  maxTwilightPoints;
-    FT_UShort  maxStorage;
-    FT_UShort  maxFunctionDefs;
-    FT_UShort  maxInstructionDefs;
-    FT_UShort  maxStackElements;
-    FT_UShort  maxSizeOfInstructions;
-    FT_UShort  maxComponentElements;
-    FT_UShort  maxComponentDepth;
-
-  } TT_MaxProfile;
-
- -

The maximum profile (‘maxp’) table contains many max values, which can be used to pre-allocate arrays for speeding up glyph loading and hinting.

-

fields

- - - - - - - - - - - - - - - - - -
version -

The version number.

-
numGlyphs -

The number of glyphs in this TrueType font.

-
maxPoints -

The maximum number of points in a non-composite TrueType glyph. See also maxCompositePoints.

-
maxContours -

The maximum number of contours in a non-composite TrueType glyph. See also maxCompositeContours.

-
maxCompositePoints -

The maximum number of points in a composite TrueType glyph. See also maxPoints.

-
maxCompositeContours -

The maximum number of contours in a composite TrueType glyph. See also maxContours.

-
maxZones -

The maximum number of zones used for glyph hinting.

-
maxTwilightPoints -

The maximum number of points in the twilight zone used for glyph hinting.

-
maxStorage -

The maximum number of elements in the storage area used for glyph hinting.

-
maxFunctionDefs -

The maximum number of function definitions in the TrueType bytecode for this font.

-
maxInstructionDefs -

The maximum number of instruction definitions in the TrueType bytecode for this font.

-
maxStackElements -

The maximum number of stack elements used during bytecode interpretation.

-
maxSizeOfInstructions -

The maximum number of TrueType opcodes used for glyph hinting.

-
maxComponentElements -

The maximum number of simple (i.e., non-composite) glyphs in a composite glyph.

-
maxComponentDepth -

The maximum nesting depth of composite glyphs.

-
- -

note

- -

This structure is only used during font loading.

-
- -

FT_Sfnt_Tag

-

Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h).

-
  typedef enum  FT_Sfnt_Tag_
-  {
-    FT_SFNT_HEAD,
-    FT_SFNT_MAXP,
-    FT_SFNT_OS2,
-    FT_SFNT_HHEA,
-    FT_SFNT_VHEA,
-    FT_SFNT_POST,
-    FT_SFNT_PCLT,
-
-    FT_SFNT_MAX
-
-  } FT_Sfnt_Tag;
-
-  /* these constants are deprecated; use the corresponding `FT_Sfnt_Tag` */
-  /* values instead                                                      */
-#define ft_sfnt_head  FT_SFNT_HEAD
-#define ft_sfnt_maxp  FT_SFNT_MAXP
-#define ft_sfnt_os2   FT_SFNT_OS2
-#define ft_sfnt_hhea  FT_SFNT_HHEA
-#define ft_sfnt_vhea  FT_SFNT_VHEA
-#define ft_sfnt_post  FT_SFNT_POST
-#define ft_sfnt_pclt  FT_SFNT_PCLT
-
- -

An enumeration to specify indices of SFNT tables loaded and parsed by FreeType during initialization of an SFNT font. Used in the FT_Get_Sfnt_Table API function.

-

values

- - - - - - - - - -
FT_SFNT_HEAD -

To access the font's TT_Header structure.

-
FT_SFNT_MAXP -

To access the font's TT_MaxProfile structure.

-
FT_SFNT_OS2 -

To access the font's TT_OS2 structure.

-
FT_SFNT_HHEA -

To access the font's TT_HoriHeader structure.

-
FT_SFNT_VHEA -

To access the font's TT_VertHeader structure.

-
FT_SFNT_POST -

To access the font's TT_Postscript structure.

-
FT_SFNT_PCLT -

To access the font's TT_PCLT structure.

-
- -
- -

FT_Get_Sfnt_Table

-

Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h).

-
  FT_EXPORT( void* )
-  FT_Get_Sfnt_Table( FT_Face      face,
-                     FT_Sfnt_Tag  tag );
-
- -

Return a pointer to a given SFNT table stored within a face.

-

input

- - - - -
face -

A handle to the source.

-
tag -

The index of the SFNT table.

-
- -

return

- -

A type-less pointer to the table. This will be NULL in case of error, or if the corresponding table was not found OR loaded from the file.

-

Use a typecast according to tag to access the structure elements.

-

note

- -

The table is owned by the face object and disappears with it.

-

This function is only useful to access SFNT tables that are loaded by the sfnt, truetype, and opentype drivers. See FT_Sfnt_Tag for a list.

-

example

- -

Here is an example demonstrating access to the ‘vhea’ table. -

  TT_VertHeader*  vert_header;
-
-
-  vert_header =
-    (TT_VertHeader*)FT_Get_Sfnt_Table( face, FT_SFNT_VHEA );
-

-
- -

FT_Load_Sfnt_Table

-

Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h).

-
  FT_EXPORT( FT_Error )
-  FT_Load_Sfnt_Table( FT_Face    face,
-                      FT_ULong   tag,
-                      FT_Long    offset,
-                      FT_Byte*   buffer,
-                      FT_ULong*  length );
-
- -

Load any SFNT font table into client memory.

-

input

- - - - - -
face -

A handle to the source face.

-
tag -

The four-byte tag of the table to load. Use value 0 if you want to access the whole font file. Otherwise, you can use one of the definitions found in the FT_TRUETYPE_TAGS_H file, or forge a new one with FT_MAKE_TAG.

-
offset -

The starting offset in the table (or file if tag == 0).

-
- -

output

- - - -
buffer -

The target buffer address. The client must ensure that the memory array is big enough to hold the data.

-
- -

inout

- - - -
length -

If the length parameter is NULL, try to load the whole table. Return an error code if it fails.

-

Else, if *length is 0, exit immediately while returning the table's (or file) full size in it.

-

Else the number of bytes to read from the table or file, from the starting offset.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

If you need to determine the table's length you should first call this function with *length set to 0, as in the following example: -

  FT_ULong  length = 0;
-
-
-  error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length );
-  if ( error ) { ... table does not exist ... }
-
-  buffer = malloc( length );
-  if ( buffer == NULL ) { ... not enough memory ... }
-
-  error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length );
-  if ( error ) { ... could not load table ... }
-

-

Note that structures like TT_Header or TT_OS2 can't be used with this function; they are limited to FT_Get_Sfnt_Table. Reason is that those structures depend on the processor architecture, with varying size (e.g. 32bit vs. 64bit) or order (big endian vs. little endian).

-
- -

FT_Sfnt_Table_Info

-

Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h).

-
  FT_EXPORT( FT_Error )
-  FT_Sfnt_Table_Info( FT_Face    face,
-                      FT_UInt    table_index,
-                      FT_ULong  *tag,
-                      FT_ULong  *length );
-
- -

Return information on an SFNT table.

-

input

- - - - -
face -

A handle to the source face.

-
table_index -

The index of an SFNT table. The function returns FT_Err_Table_Missing for an invalid value.

-
- -

inout

- - - -
tag -

The name tag of the SFNT table. If the value is NULL, table_index is ignored, and length returns the number of SFNT tables in the font.

-
- -

output

- - - -
length -

The length of the SFNT table (or the number of SFNT tables, depending on tag).

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

While parsing fonts, FreeType handles SFNT tables with length zero as missing.

-
- -

FT_Get_CMap_Language_ID

-

Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h).

-
  FT_EXPORT( FT_ULong )
-  FT_Get_CMap_Language_ID( FT_CharMap  charmap );
-
- -

Return cmap language ID as specified in the OpenType standard. Definitions of language ID values are in file FT_TRUETYPE_IDS_H.

-

input

- - - -
charmap -

The target charmap.

-
- -

return

- -

The language ID of charmap. If charmap doesn't belong to an SFNT face, just return 0 as the default value.

-

For a format 14 cmap (to access Unicode IVS), the return value is 0xFFFFFFFF.

-
- -

FT_Get_CMap_Format

-

Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h).

-
  FT_EXPORT( FT_Long )
-  FT_Get_CMap_Format( FT_CharMap  charmap );
-
- -

Return the format of an SFNT ‘cmap’ table.

-

input

- - - -
charmap -

The target charmap.

-
- -

return

- -

The format of charmap. If charmap doesn't belong to an SFNT face, return -1.

-
- -

FT_PARAM_TAG_UNPATENTED_HINTING

-
#define FT_PARAM_TAG_UNPATENTED_HINTING \
-          FT_MAKE_TAG( 'u', 'n', 'p', 'a' )
-
- -

Deprecated, no effect.

-

Previously: A constant used as the tag of an FT_Parameter structure to indicate that unpatented methods only should be used by the TrueType bytecode interpreter for a typeface opened by FT_Open_Face.

-
- -

TT_PLATFORM_XXX

-

Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h).

-
#define TT_PLATFORM_APPLE_UNICODE  0
-#define TT_PLATFORM_MACINTOSH      1
-#define TT_PLATFORM_ISO            2 /* deprecated */
-#define TT_PLATFORM_MICROSOFT      3
-#define TT_PLATFORM_CUSTOM         4
-#define TT_PLATFORM_ADOBE          7 /* artificial */
-
- -

A list of valid values for the platform_id identifier code in FT_CharMapRec and FT_SfntName structures.

-

values

- - - - - - - - -
TT_PLATFORM_APPLE_UNICODE -

Used by Apple to indicate a Unicode character map and/or name entry. See TT_APPLE_ID_XXX for corresponding encoding_id values. Note that name entries in this format are coded as big-endian UCS-2 character codes only.

-
TT_PLATFORM_MACINTOSH -

Used by Apple to indicate a MacOS-specific charmap and/or name entry. See TT_MAC_ID_XXX for corresponding encoding_id values. Note that most TrueType fonts contain an Apple roman charmap to be usable on MacOS systems (even if they contain a Microsoft charmap as well).

-
TT_PLATFORM_ISO -

This value was used to specify ISO/IEC 10646 charmaps. It is however now deprecated. See TT_ISO_ID_XXX for a list of corresponding encoding_id values.

-
TT_PLATFORM_MICROSOFT -

Used by Microsoft to indicate Windows-specific charmaps. See TT_MS_ID_XXX for a list of corresponding encoding_id values. Note that most fonts contain a Unicode charmap using (TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS).

-
TT_PLATFORM_CUSTOM -

Used to indicate application-specific charmaps.

-
TT_PLATFORM_ADOBE -

This value isn't part of any font format specification, but is used by FreeType to report Adobe-specific charmaps in an FT_CharMapRec structure. See TT_ADOBE_ID_XXX.

-
- -
- -

TT_APPLE_ID_XXX

-

Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h).

-
#define TT_APPLE_ID_DEFAULT           0 /* Unicode 1.0                   */
-#define TT_APPLE_ID_UNICODE_1_1       1 /* specify Hangul at U+34xx      */
-#define TT_APPLE_ID_ISO_10646         2 /* deprecated                    */
-#define TT_APPLE_ID_UNICODE_2_0       3 /* or later                      */
-#define TT_APPLE_ID_UNICODE_32        4 /* 2.0 or later, full repertoire */
-#define TT_APPLE_ID_VARIANT_SELECTOR  5 /* variation selector data       */
-#define TT_APPLE_ID_FULL_UNICODE      6 /* used with type 13 cmaps       */
-
- -

A list of valid values for the encoding_id for TT_PLATFORM_APPLE_UNICODE charmaps and name entries.

-

values

- - - - - - - - - -
TT_APPLE_ID_DEFAULT -

Unicode version 1.0.

-
TT_APPLE_ID_UNICODE_1_1 -

Unicode 1.1; specifies Hangul characters starting at U+34xx.

-
TT_APPLE_ID_ISO_10646 -

Deprecated (identical to preceding).

-
TT_APPLE_ID_UNICODE_2_0 -

Unicode 2.0 and beyond (UTF-16 BMP only).

-
TT_APPLE_ID_UNICODE_32 -

Unicode 3.1 and beyond, using UTF-32.

-
TT_APPLE_ID_VARIANT_SELECTOR -

From Adobe, not Apple. Not a normal cmap. Specifies variations on a real cmap.

-
TT_APPLE_ID_FULL_UNICODE -

Used for fallback fonts that provide complete Unicode coverage with a type 13 cmap.

-
- -
- -

TT_MAC_ID_XXX

-

Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h).

-
#define TT_MAC_ID_ROMAN                 0
-#define TT_MAC_ID_JAPANESE              1
-#define TT_MAC_ID_TRADITIONAL_CHINESE   2
-#define TT_MAC_ID_KOREAN                3
-#define TT_MAC_ID_ARABIC                4
-#define TT_MAC_ID_HEBREW                5
-#define TT_MAC_ID_GREEK                 6
-#define TT_MAC_ID_RUSSIAN               7
-#define TT_MAC_ID_RSYMBOL               8
-#define TT_MAC_ID_DEVANAGARI            9
-#define TT_MAC_ID_GURMUKHI             10
-#define TT_MAC_ID_GUJARATI             11
-#define TT_MAC_ID_ORIYA                12
-#define TT_MAC_ID_BENGALI              13
-#define TT_MAC_ID_TAMIL                14
-#define TT_MAC_ID_TELUGU               15
-#define TT_MAC_ID_KANNADA              16
-#define TT_MAC_ID_MALAYALAM            17
-#define TT_MAC_ID_SINHALESE            18
-#define TT_MAC_ID_BURMESE              19
-#define TT_MAC_ID_KHMER                20
-#define TT_MAC_ID_THAI                 21
-#define TT_MAC_ID_LAOTIAN              22
-#define TT_MAC_ID_GEORGIAN             23
-#define TT_MAC_ID_ARMENIAN             24
-#define TT_MAC_ID_MALDIVIAN            25
-#define TT_MAC_ID_SIMPLIFIED_CHINESE   25
-#define TT_MAC_ID_TIBETAN              26
-#define TT_MAC_ID_MONGOLIAN            27
-#define TT_MAC_ID_GEEZ                 28
-#define TT_MAC_ID_SLAVIC               29
-#define TT_MAC_ID_VIETNAMESE           30
-#define TT_MAC_ID_SINDHI               31
-#define TT_MAC_ID_UNINTERP             32
-
- -

A list of valid values for the encoding_id for TT_PLATFORM_MACINTOSH charmaps and name entries.

-
- -

TT_ISO_ID_XXX

-

Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h).

-
#define TT_ISO_ID_7BIT_ASCII  0
-#define TT_ISO_ID_10646       1
-#define TT_ISO_ID_8859_1      2
-
- -

A list of valid values for the encoding_id for TT_PLATFORM_ISO charmaps and name entries.

-

Their use is now deprecated.

-

values

- - - - - -
TT_ISO_ID_7BIT_ASCII -

ASCII.

-
TT_ISO_ID_10646 -

ISO/10646.

-
TT_ISO_ID_8859_1 -

Also known as Latin-1.

-
- -
- -

TT_MS_ID_XXX

-

Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h).

-
#define TT_MS_ID_SYMBOL_CS    0
-#define TT_MS_ID_UNICODE_CS   1
-#define TT_MS_ID_SJIS         2
-#define TT_MS_ID_PRC          3
-#define TT_MS_ID_BIG_5        4
-#define TT_MS_ID_WANSUNG      5
-#define TT_MS_ID_JOHAB        6
-#define TT_MS_ID_UCS_4       10
-
-  /* this value is deprecated */
-#define TT_MS_ID_GB2312  TT_MS_ID_PRC
-
- -

A list of valid values for the encoding_id for TT_PLATFORM_MICROSOFT charmaps and name entries.

-

values

- - - - - - - - - - -
TT_MS_ID_SYMBOL_CS -

Microsoft symbol encoding. See FT_ENCODING_MS_SYMBOL.

-
TT_MS_ID_UNICODE_CS -

Microsoft WGL4 charmap, matching Unicode. See FT_ENCODING_UNICODE.

-
TT_MS_ID_SJIS -

Shift JIS Japanese encoding. See FT_ENCODING_SJIS.

-
TT_MS_ID_PRC -

Chinese encodings as used in the People's Republic of China (PRC). This means the encodings GB 2312 and its supersets GBK and GB 18030. See FT_ENCODING_PRC.

-
TT_MS_ID_BIG_5 -

Traditional Chinese as used in Taiwan and Hong Kong. See FT_ENCODING_BIG5.

-
TT_MS_ID_WANSUNG -

Korean Extended Wansung encoding. See FT_ENCODING_WANSUNG.

-
TT_MS_ID_JOHAB -

Korean Johab encoding. See FT_ENCODING_JOHAB.

-
TT_MS_ID_UCS_4 -

UCS-4 or UTF-32 charmaps. This has been added to the OpenType specification version 1.4 (mid-2001).

-
- -
- -

TT_ADOBE_ID_XXX

-

Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h).

- - -

A list of valid values for the encoding_id for TT_PLATFORM_ADOBE charmaps. This is a FreeType-specific extension!

-

values

- - - - - - -
TT_ADOBE_ID_STANDARD -

Adobe standard encoding.

-
TT_ADOBE_ID_EXPERT -

Adobe expert encoding.

-
TT_ADOBE_ID_CUSTOM -

Adobe custom encoding.

-
TT_ADOBE_ID_LATIN_1 -

Adobe Latin 1 encoding.

-
- -
- -

TT_MAC_LANGID_XXX

-

Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h).

-
#define TT_MAC_LANGID_ENGLISH                       0
-#define TT_MAC_LANGID_FRENCH                        1
-#define TT_MAC_LANGID_GERMAN                        2
-#define TT_MAC_LANGID_ITALIAN                       3
-#define TT_MAC_LANGID_DUTCH                         4
-#define TT_MAC_LANGID_SWEDISH                       5
-#define TT_MAC_LANGID_SPANISH                       6
-#define TT_MAC_LANGID_DANISH                        7
-#define TT_MAC_LANGID_PORTUGUESE                    8
-#define TT_MAC_LANGID_NORWEGIAN                     9
-#define TT_MAC_LANGID_HEBREW                       10
-#define TT_MAC_LANGID_JAPANESE                     11
-#define TT_MAC_LANGID_ARABIC                       12
-#define TT_MAC_LANGID_FINNISH                      13
-#define TT_MAC_LANGID_GREEK                        14
-#define TT_MAC_LANGID_ICELANDIC                    15
-#define TT_MAC_LANGID_MALTESE                      16
-#define TT_MAC_LANGID_TURKISH                      17
-#define TT_MAC_LANGID_CROATIAN                     18
-#define TT_MAC_LANGID_CHINESE_TRADITIONAL          19
-#define TT_MAC_LANGID_URDU                         20
-#define TT_MAC_LANGID_HINDI                        21
-#define TT_MAC_LANGID_THAI                         22
-#define TT_MAC_LANGID_KOREAN                       23
-#define TT_MAC_LANGID_LITHUANIAN                   24
-#define TT_MAC_LANGID_POLISH                       25
-#define TT_MAC_LANGID_HUNGARIAN                    26
-#define TT_MAC_LANGID_ESTONIAN                     27
-#define TT_MAC_LANGID_LETTISH                      28
-#define TT_MAC_LANGID_SAAMISK                      29
-#define TT_MAC_LANGID_FAEROESE                     30
-#define TT_MAC_LANGID_FARSI                        31
-#define TT_MAC_LANGID_RUSSIAN                      32
-#define TT_MAC_LANGID_CHINESE_SIMPLIFIED           33
-#define TT_MAC_LANGID_FLEMISH                      34
-#define TT_MAC_LANGID_IRISH                        35
-#define TT_MAC_LANGID_ALBANIAN                     36
-#define TT_MAC_LANGID_ROMANIAN                     37
-#define TT_MAC_LANGID_CZECH                        38
-#define TT_MAC_LANGID_SLOVAK                       39
-#define TT_MAC_LANGID_SLOVENIAN                    40
-#define TT_MAC_LANGID_YIDDISH                      41
-#define TT_MAC_LANGID_SERBIAN                      42
-#define TT_MAC_LANGID_MACEDONIAN                   43
-#define TT_MAC_LANGID_BULGARIAN                    44
-#define TT_MAC_LANGID_UKRAINIAN                    45
-#define TT_MAC_LANGID_BYELORUSSIAN                 46
-#define TT_MAC_LANGID_UZBEK                        47
-#define TT_MAC_LANGID_KAZAKH                       48
-#define TT_MAC_LANGID_AZERBAIJANI                  49
-#define TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT  49
-#define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT    50
-#define TT_MAC_LANGID_ARMENIAN                     51
-#define TT_MAC_LANGID_GEORGIAN                     52
-#define TT_MAC_LANGID_MOLDAVIAN                    53
-#define TT_MAC_LANGID_KIRGHIZ                      54
-#define TT_MAC_LANGID_TAJIKI                       55
-#define TT_MAC_LANGID_TURKMEN                      56
-#define TT_MAC_LANGID_MONGOLIAN                    57
-#define TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT   57
-#define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT    58
-#define TT_MAC_LANGID_PASHTO                       59
-#define TT_MAC_LANGID_KURDISH                      60
-#define TT_MAC_LANGID_KASHMIRI                     61
-#define TT_MAC_LANGID_SINDHI                       62
-#define TT_MAC_LANGID_TIBETAN                      63
-#define TT_MAC_LANGID_NEPALI                       64
-#define TT_MAC_LANGID_SANSKRIT                     65
-#define TT_MAC_LANGID_MARATHI                      66
-#define TT_MAC_LANGID_BENGALI                      67
-#define TT_MAC_LANGID_ASSAMESE                     68
-#define TT_MAC_LANGID_GUJARATI                     69
-#define TT_MAC_LANGID_PUNJABI                      70
-#define TT_MAC_LANGID_ORIYA                        71
-#define TT_MAC_LANGID_MALAYALAM                    72
-#define TT_MAC_LANGID_KANNADA                      73
-#define TT_MAC_LANGID_TAMIL                        74
-#define TT_MAC_LANGID_TELUGU                       75
-#define TT_MAC_LANGID_SINHALESE                    76
-#define TT_MAC_LANGID_BURMESE                      77
-#define TT_MAC_LANGID_KHMER                        78
-#define TT_MAC_LANGID_LAO                          79
-#define TT_MAC_LANGID_VIETNAMESE                   80
-#define TT_MAC_LANGID_INDONESIAN                   81
-#define TT_MAC_LANGID_TAGALOG                      82
-#define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT           83
-#define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT          84
-#define TT_MAC_LANGID_AMHARIC                      85
-#define TT_MAC_LANGID_TIGRINYA                     86
-#define TT_MAC_LANGID_GALLA                        87
-#define TT_MAC_LANGID_SOMALI                       88
-#define TT_MAC_LANGID_SWAHILI                      89
-#define TT_MAC_LANGID_RUANDA                       90
-#define TT_MAC_LANGID_RUNDI                        91
-#define TT_MAC_LANGID_CHEWA                        92
-#define TT_MAC_LANGID_MALAGASY                     93
-#define TT_MAC_LANGID_ESPERANTO                    94
-#define TT_MAC_LANGID_WELSH                       128
-#define TT_MAC_LANGID_BASQUE                      129
-#define TT_MAC_LANGID_CATALAN                     130
-#define TT_MAC_LANGID_LATIN                       131
-#define TT_MAC_LANGID_QUECHUA                     132
-#define TT_MAC_LANGID_GUARANI                     133
-#define TT_MAC_LANGID_AYMARA                      134
-#define TT_MAC_LANGID_TATAR                       135
-#define TT_MAC_LANGID_UIGHUR                      136
-#define TT_MAC_LANGID_DZONGKHA                    137
-#define TT_MAC_LANGID_JAVANESE                    138
-#define TT_MAC_LANGID_SUNDANESE                   139
-
-  /* The following codes are new as of 2000-03-10 */
-#define TT_MAC_LANGID_GALICIAN                    140
-#define TT_MAC_LANGID_AFRIKAANS                   141
-#define TT_MAC_LANGID_BRETON                      142
-#define TT_MAC_LANGID_INUKTITUT                   143
-#define TT_MAC_LANGID_SCOTTISH_GAELIC             144
-#define TT_MAC_LANGID_MANX_GAELIC                 145
-#define TT_MAC_LANGID_IRISH_GAELIC                146
-#define TT_MAC_LANGID_TONGAN                      147
-#define TT_MAC_LANGID_GREEK_POLYTONIC             148
-#define TT_MAC_LANGID_GREELANDIC                  149
-#define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT    150
-
- -

Possible values of the language identifier field in the name records of the SFNT ‘name’ table if the ‘platform’ identifier code is TT_PLATFORM_MACINTOSH. These values are also used as return values for function FT_Get_CMap_Language_ID.

-

The canonical source for Apple's IDs is

-

https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html

-
- -

TT_MS_LANGID_XXX

-

Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h).

-
#define TT_MS_LANGID_ARABIC_SAUDI_ARABIA               0x0401
-#define TT_MS_LANGID_ARABIC_IRAQ                       0x0801
-#define TT_MS_LANGID_ARABIC_EGYPT                      0x0C01
-#define TT_MS_LANGID_ARABIC_LIBYA                      0x1001
-#define TT_MS_LANGID_ARABIC_ALGERIA                    0x1401
-#define TT_MS_LANGID_ARABIC_MOROCCO                    0x1801
-#define TT_MS_LANGID_ARABIC_TUNISIA                    0x1C01
-#define TT_MS_LANGID_ARABIC_OMAN                       0x2001
-#define TT_MS_LANGID_ARABIC_YEMEN                      0x2401
-#define TT_MS_LANGID_ARABIC_SYRIA                      0x2801
-#define TT_MS_LANGID_ARABIC_JORDAN                     0x2C01
-#define TT_MS_LANGID_ARABIC_LEBANON                    0x3001
-#define TT_MS_LANGID_ARABIC_KUWAIT                     0x3401
-#define TT_MS_LANGID_ARABIC_UAE                        0x3801
-#define TT_MS_LANGID_ARABIC_BAHRAIN                    0x3C01
-#define TT_MS_LANGID_ARABIC_QATAR                      0x4001
-#define TT_MS_LANGID_BULGARIAN_BULGARIA                0x0402
-#define TT_MS_LANGID_CATALAN_CATALAN                   0x0403
-#define TT_MS_LANGID_CHINESE_TAIWAN                    0x0404
-#define TT_MS_LANGID_CHINESE_PRC                       0x0804
-#define TT_MS_LANGID_CHINESE_HONG_KONG                 0x0C04
-#define TT_MS_LANGID_CHINESE_SINGAPORE                 0x1004
-#define TT_MS_LANGID_CHINESE_MACAO                     0x1404
-#define TT_MS_LANGID_CZECH_CZECH_REPUBLIC              0x0405
-#define TT_MS_LANGID_DANISH_DENMARK                    0x0406
-#define TT_MS_LANGID_GERMAN_GERMANY                    0x0407
-#define TT_MS_LANGID_GERMAN_SWITZERLAND                0x0807
-#define TT_MS_LANGID_GERMAN_AUSTRIA                    0x0C07
-#define TT_MS_LANGID_GERMAN_LUXEMBOURG                 0x1007
-#define TT_MS_LANGID_GERMAN_LIECHTENSTEIN              0x1407
-#define TT_MS_LANGID_GREEK_GREECE                      0x0408
-#define TT_MS_LANGID_ENGLISH_UNITED_STATES             0x0409
-#define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM            0x0809
-#define TT_MS_LANGID_ENGLISH_AUSTRALIA                 0x0C09
-#define TT_MS_LANGID_ENGLISH_CANADA                    0x1009
-#define TT_MS_LANGID_ENGLISH_NEW_ZEALAND               0x1409
-#define TT_MS_LANGID_ENGLISH_IRELAND                   0x1809
-#define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA              0x1C09
-#define TT_MS_LANGID_ENGLISH_JAMAICA                   0x2009
-#define TT_MS_LANGID_ENGLISH_CARIBBEAN                 0x2409
-#define TT_MS_LANGID_ENGLISH_BELIZE                    0x2809
-#define TT_MS_LANGID_ENGLISH_TRINIDAD                  0x2C09
-#define TT_MS_LANGID_ENGLISH_ZIMBABWE                  0x3009
-#define TT_MS_LANGID_ENGLISH_PHILIPPINES               0x3409
-#define TT_MS_LANGID_ENGLISH_INDIA                     0x4009
-#define TT_MS_LANGID_ENGLISH_MALAYSIA                  0x4409
-#define TT_MS_LANGID_ENGLISH_SINGAPORE                 0x4809
-#define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT    0x040A
-#define TT_MS_LANGID_SPANISH_MEXICO                    0x080A
-#define TT_MS_LANGID_SPANISH_SPAIN_MODERN_SORT         0x0C0A
-#define TT_MS_LANGID_SPANISH_GUATEMALA                 0x100A
-#define TT_MS_LANGID_SPANISH_COSTA_RICA                0x140A
-#define TT_MS_LANGID_SPANISH_PANAMA                    0x180A
-#define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC        0x1C0A
-#define TT_MS_LANGID_SPANISH_VENEZUELA                 0x200A
-#define TT_MS_LANGID_SPANISH_COLOMBIA                  0x240A
-#define TT_MS_LANGID_SPANISH_PERU                      0x280A
-#define TT_MS_LANGID_SPANISH_ARGENTINA                 0x2C0A
-#define TT_MS_LANGID_SPANISH_ECUADOR                   0x300A
-#define TT_MS_LANGID_SPANISH_CHILE                     0x340A
-#define TT_MS_LANGID_SPANISH_URUGUAY                   0x380A
-#define TT_MS_LANGID_SPANISH_PARAGUAY                  0x3C0A
-#define TT_MS_LANGID_SPANISH_BOLIVIA                   0x400A
-#define TT_MS_LANGID_SPANISH_EL_SALVADOR               0x440A
-#define TT_MS_LANGID_SPANISH_HONDURAS                  0x480A
-#define TT_MS_LANGID_SPANISH_NICARAGUA                 0x4C0A
-#define TT_MS_LANGID_SPANISH_PUERTO_RICO               0x500A
-#define TT_MS_LANGID_SPANISH_UNITED_STATES             0x540A
-#define TT_MS_LANGID_FINNISH_FINLAND                   0x040B
-#define TT_MS_LANGID_FRENCH_FRANCE                     0x040C
-#define TT_MS_LANGID_FRENCH_BELGIUM                    0x080C
-#define TT_MS_LANGID_FRENCH_CANADA                     0x0C0C
-#define TT_MS_LANGID_FRENCH_SWITZERLAND                0x100C
-#define TT_MS_LANGID_FRENCH_LUXEMBOURG                 0x140C
-#define TT_MS_LANGID_FRENCH_MONACO                     0x180C
-#define TT_MS_LANGID_HEBREW_ISRAEL                     0x040D
-#define TT_MS_LANGID_HUNGARIAN_HUNGARY                 0x040E
-#define TT_MS_LANGID_ICELANDIC_ICELAND                 0x040F
-#define TT_MS_LANGID_ITALIAN_ITALY                     0x0410
-#define TT_MS_LANGID_ITALIAN_SWITZERLAND               0x0810
-#define TT_MS_LANGID_JAPANESE_JAPAN                    0x0411
-#define TT_MS_LANGID_KOREAN_KOREA                      0x0412
-#define TT_MS_LANGID_DUTCH_NETHERLANDS                 0x0413
-#define TT_MS_LANGID_DUTCH_BELGIUM                     0x0813
-#define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL           0x0414
-#define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK          0x0814
-#define TT_MS_LANGID_POLISH_POLAND                     0x0415
-#define TT_MS_LANGID_PORTUGUESE_BRAZIL                 0x0416
-#define TT_MS_LANGID_PORTUGUESE_PORTUGAL               0x0816
-#define TT_MS_LANGID_ROMANSH_SWITZERLAND               0x0417
-#define TT_MS_LANGID_ROMANIAN_ROMANIA                  0x0418
-#define TT_MS_LANGID_RUSSIAN_RUSSIA                    0x0419
-#define TT_MS_LANGID_CROATIAN_CROATIA                  0x041A
-#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN              0x081A
-#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC           0x0C1A
-#define TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA       0x101A
-#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA        0x141A
-#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN         0x181A
-#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC      0x1C1A
-#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZ_CYRILLIC      0x201A
-#define TT_MS_LANGID_SLOVAK_SLOVAKIA                   0x041B
-#define TT_MS_LANGID_ALBANIAN_ALBANIA                  0x041C
-#define TT_MS_LANGID_SWEDISH_SWEDEN                    0x041D
-#define TT_MS_LANGID_SWEDISH_FINLAND                   0x081D
-#define TT_MS_LANGID_THAI_THAILAND                     0x041E
-#define TT_MS_LANGID_TURKISH_TURKEY                    0x041F
-#define TT_MS_LANGID_URDU_PAKISTAN                     0x0420
-#define TT_MS_LANGID_INDONESIAN_INDONESIA              0x0421
-#define TT_MS_LANGID_UKRAINIAN_UKRAINE                 0x0422
-#define TT_MS_LANGID_BELARUSIAN_BELARUS                0x0423
-#define TT_MS_LANGID_SLOVENIAN_SLOVENIA                0x0424
-#define TT_MS_LANGID_ESTONIAN_ESTONIA                  0x0425
-#define TT_MS_LANGID_LATVIAN_LATVIA                    0x0426
-#define TT_MS_LANGID_LITHUANIAN_LITHUANIA              0x0427
-#define TT_MS_LANGID_TAJIK_TAJIKISTAN                  0x0428
-#define TT_MS_LANGID_VIETNAMESE_VIET_NAM               0x042A
-#define TT_MS_LANGID_ARMENIAN_ARMENIA                  0x042B
-#define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN            0x042C
-#define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC         0x082C
-#define TT_MS_LANGID_BASQUE_BASQUE                     0x042D
-#define TT_MS_LANGID_UPPER_SORBIAN_GERMANY             0x042E
-#define TT_MS_LANGID_LOWER_SORBIAN_GERMANY             0x082E
-#define TT_MS_LANGID_MACEDONIAN_MACEDONIA              0x042F
-#define TT_MS_LANGID_SETSWANA_SOUTH_AFRICA             0x0432
-#define TT_MS_LANGID_ISIXHOSA_SOUTH_AFRICA             0x0434
-#define TT_MS_LANGID_ISIZULU_SOUTH_AFRICA              0x0435
-#define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA            0x0436
-#define TT_MS_LANGID_GEORGIAN_GEORGIA                  0x0437
-#define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS           0x0438
-#define TT_MS_LANGID_HINDI_INDIA                       0x0439
-#define TT_MS_LANGID_MALTESE_MALTA                     0x043A
-#define TT_MS_LANGID_SAMI_NORTHERN_NORWAY              0x043B
-#define TT_MS_LANGID_SAMI_NORTHERN_SWEDEN              0x083B
-#define TT_MS_LANGID_SAMI_NORTHERN_FINLAND             0x0C3B
-#define TT_MS_LANGID_SAMI_LULE_NORWAY                  0x103B
-#define TT_MS_LANGID_SAMI_LULE_SWEDEN                  0x143B
-#define TT_MS_LANGID_SAMI_SOUTHERN_NORWAY              0x183B
-#define TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN              0x1C3B
-#define TT_MS_LANGID_SAMI_SKOLT_FINLAND                0x203B
-#define TT_MS_LANGID_SAMI_INARI_FINLAND                0x243B
-#define TT_MS_LANGID_IRISH_IRELAND                     0x083C
-#define TT_MS_LANGID_MALAY_MALAYSIA                    0x043E
-#define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM           0x083E
-#define TT_MS_LANGID_KAZAKH_KAZAKHSTAN                 0x043F
-#define TT_MS_LANGID_KYRGYZ_KYRGYZSTAN /* Cyrillic*/   0x0440
-#define TT_MS_LANGID_KISWAHILI_KENYA                   0x0441
-#define TT_MS_LANGID_TURKMEN_TURKMENISTAN              0x0442
-#define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN            0x0443
-#define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC         0x0843
-#define TT_MS_LANGID_TATAR_RUSSIA                      0x0444
-#define TT_MS_LANGID_BENGALI_INDIA                     0x0445
-#define TT_MS_LANGID_BENGALI_BANGLADESH                0x0845
-#define TT_MS_LANGID_PUNJABI_INDIA                     0x0446
-#define TT_MS_LANGID_GUJARATI_INDIA                    0x0447
-#define TT_MS_LANGID_ODIA_INDIA                        0x0448
-#define TT_MS_LANGID_TAMIL_INDIA                       0x0449
-#define TT_MS_LANGID_TELUGU_INDIA                      0x044A
-#define TT_MS_LANGID_KANNADA_INDIA                     0x044B
-#define TT_MS_LANGID_MALAYALAM_INDIA                   0x044C
-#define TT_MS_LANGID_ASSAMESE_INDIA                    0x044D
-#define TT_MS_LANGID_MARATHI_INDIA                     0x044E
-#define TT_MS_LANGID_SANSKRIT_INDIA                    0x044F
-#define TT_MS_LANGID_MONGOLIAN_MONGOLIA /* Cyrillic */ 0x0450
-#define TT_MS_LANGID_MONGOLIAN_PRC                     0x0850
-#define TT_MS_LANGID_TIBETAN_PRC                       0x0451
-#define TT_MS_LANGID_WELSH_UNITED_KINGDOM              0x0452
-#define TT_MS_LANGID_KHMER_CAMBODIA                    0x0453
-#define TT_MS_LANGID_LAO_LAOS                          0x0454
-#define TT_MS_LANGID_GALICIAN_GALICIAN                 0x0456
-#define TT_MS_LANGID_KONKANI_INDIA                     0x0457
-#define TT_MS_LANGID_SYRIAC_SYRIA                      0x045A
-#define TT_MS_LANGID_SINHALA_SRI_LANKA                 0x045B
-#define TT_MS_LANGID_INUKTITUT_CANADA                  0x045D
-#define TT_MS_LANGID_INUKTITUT_CANADA_LATIN            0x085D
-#define TT_MS_LANGID_AMHARIC_ETHIOPIA                  0x045E
-#define TT_MS_LANGID_TAMAZIGHT_ALGERIA                 0x085F
-#define TT_MS_LANGID_NEPALI_NEPAL                      0x0461
-#define TT_MS_LANGID_FRISIAN_NETHERLANDS               0x0462
-#define TT_MS_LANGID_PASHTO_AFGHANISTAN                0x0463
-#define TT_MS_LANGID_FILIPINO_PHILIPPINES              0x0464
-#define TT_MS_LANGID_DHIVEHI_MALDIVES                  0x0465
-#define TT_MS_LANGID_HAUSA_NIGERIA                     0x0468
-#define TT_MS_LANGID_YORUBA_NIGERIA                    0x046A
-#define TT_MS_LANGID_QUECHUA_BOLIVIA                   0x046B
-#define TT_MS_LANGID_QUECHUA_ECUADOR                   0x086B
-#define TT_MS_LANGID_QUECHUA_PERU                      0x0C6B
-#define TT_MS_LANGID_SESOTHO_SA_LEBOA_SOUTH_AFRICA     0x046C
-#define TT_MS_LANGID_BASHKIR_RUSSIA                    0x046D
-#define TT_MS_LANGID_LUXEMBOURGISH_LUXEMBOURG          0x046E
-#define TT_MS_LANGID_GREENLANDIC_GREENLAND             0x046F
-#define TT_MS_LANGID_IGBO_NIGERIA                      0x0470
-#define TT_MS_LANGID_YI_PRC                            0x0478
-#define TT_MS_LANGID_MAPUDUNGUN_CHILE                  0x047A
-#define TT_MS_LANGID_MOHAWK_MOHAWK                     0x047C
-#define TT_MS_LANGID_BRETON_FRANCE                     0x047E
-#define TT_MS_LANGID_UIGHUR_PRC                        0x0480
-#define TT_MS_LANGID_MAORI_NEW_ZEALAND                 0x0481
-#define TT_MS_LANGID_OCCITAN_FRANCE                    0x0482
-#define TT_MS_LANGID_CORSICAN_FRANCE                   0x0483
-#define TT_MS_LANGID_ALSATIAN_FRANCE                   0x0484
-#define TT_MS_LANGID_YAKUT_RUSSIA                      0x0485
-#define TT_MS_LANGID_KICHE_GUATEMALA                   0x0486
-#define TT_MS_LANGID_KINYARWANDA_RWANDA                0x0487
-#define TT_MS_LANGID_WOLOF_SENEGAL                     0x0488
-#define TT_MS_LANGID_DARI_AFGHANISTAN                  0x048C
-
- -

Possible values of the language identifier field in the name records of the SFNT ‘name’ table if the ‘platform’ identifier code is TT_PLATFORM_MICROSOFT. These values are also used as return values for function FT_Get_CMap_Language_ID.

-

The canonical source for Microsoft's IDs is

-

https://docs.microsoft.com/en-us/windows/desktop/Intl/language-identifier-constants-and-strings ,

-

however, we only provide macros for language identifiers present in the OpenType specification: Microsoft has abandoned the concept of LCIDs (language code identifiers), and format 1 of the ‘name’ table provides a better mechanism for languages not covered here.

-

More legacy values not listed in the reference can be found in the FT_TRUETYPE_IDS_H header file.

-
- -

TT_NAME_ID_XXX

-

Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h).

-
#define TT_NAME_ID_COPYRIGHT              0
-#define TT_NAME_ID_FONT_FAMILY            1
-#define TT_NAME_ID_FONT_SUBFAMILY         2
-#define TT_NAME_ID_UNIQUE_ID              3
-#define TT_NAME_ID_FULL_NAME              4
-#define TT_NAME_ID_VERSION_STRING         5
-#define TT_NAME_ID_PS_NAME                6
-#define TT_NAME_ID_TRADEMARK              7
-
-  /* the following values are from the OpenType spec */
-#define TT_NAME_ID_MANUFACTURER           8
-#define TT_NAME_ID_DESIGNER               9
-#define TT_NAME_ID_DESCRIPTION            10
-#define TT_NAME_ID_VENDOR_URL             11
-#define TT_NAME_ID_DESIGNER_URL           12
-#define TT_NAME_ID_LICENSE                13
-#define TT_NAME_ID_LICENSE_URL            14
-  /* number 15 is reserved */
-#define TT_NAME_ID_TYPOGRAPHIC_FAMILY     16
-#define TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY  17
-#define TT_NAME_ID_MAC_FULL_NAME          18
-
-  /* The following code is new as of 2000-01-21 */
-#define TT_NAME_ID_SAMPLE_TEXT            19
-
-  /* This is new in OpenType 1.3 */
-#define TT_NAME_ID_CID_FINDFONT_NAME      20
-
-  /* This is new in OpenType 1.5 */
-#define TT_NAME_ID_WWS_FAMILY             21
-#define TT_NAME_ID_WWS_SUBFAMILY          22
-
-  /* This is new in OpenType 1.7 */
-#define TT_NAME_ID_LIGHT_BACKGROUND       23
-#define TT_NAME_ID_DARK_BACKGROUND        24
-
-  /* This is new in OpenType 1.8 */
-#define TT_NAME_ID_VARIATIONS_PREFIX      25
-
-  /* these two values are deprecated */
-#define TT_NAME_ID_PREFERRED_FAMILY     TT_NAME_ID_TYPOGRAPHIC_FAMILY
-#define TT_NAME_ID_PREFERRED_SUBFAMILY  TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY
-
- -

Possible values of the ‘name’ identifier field in the name records of an SFNT ‘name’ table. These values are platform independent.

-
- -

TT_UCR_XXX

-

Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h).

-
  /* ulUnicodeRange1 */
-  /* --------------- */
-
-  /* Bit  0   Basic Latin */
-#define TT_UCR_BASIC_LATIN                     (1L <<  0) /* U+0020-U+007E */
-  /* Bit  1   C1 Controls and Latin-1 Supplement */
-#define TT_UCR_LATIN1_SUPPLEMENT               (1L <<  1) /* U+0080-U+00FF */
-  /* Bit  2   Latin Extended-A */
-#define TT_UCR_LATIN_EXTENDED_A                (1L <<  2) /* U+0100-U+017F */
-  /* Bit  3   Latin Extended-B */
-#define TT_UCR_LATIN_EXTENDED_B                (1L <<  3) /* U+0180-U+024F */
-  /* Bit  4   IPA Extensions                 */
-  /*          Phonetic Extensions            */
-  /*          Phonetic Extensions Supplement */
-#define TT_UCR_IPA_EXTENSIONS                  (1L <<  4) /* U+0250-U+02AF */
-                                                          /* U+1D00-U+1D7F */
-                                                          /* U+1D80-U+1DBF */
-  /* Bit  5   Spacing Modifier Letters */
-  /*          Modifier Tone Letters    */
-#define TT_UCR_SPACING_MODIFIER                (1L <<  5) /* U+02B0-U+02FF */
-                                                          /* U+A700-U+A71F */
-  /* Bit  6   Combining Diacritical Marks            */
-  /*          Combining Diacritical Marks Supplement */
-#define TT_UCR_COMBINING_DIACRITICAL_MARKS     (1L <<  6) /* U+0300-U+036F */
-                                                          /* U+1DC0-U+1DFF */
-  /* Bit  7   Greek and Coptic */
-#define TT_UCR_GREEK                           (1L <<  7) /* U+0370-U+03FF */
-  /* Bit  8   Coptic */
-#define TT_UCR_COPTIC                          (1L <<  8) /* U+2C80-U+2CFF */
-  /* Bit  9   Cyrillic            */
-  /*          Cyrillic Supplement */
-  /*          Cyrillic Extended-A */
-  /*          Cyrillic Extended-B */
-#define TT_UCR_CYRILLIC                        (1L <<  9) /* U+0400-U+04FF */
-                                                          /* U+0500-U+052F */
-                                                          /* U+2DE0-U+2DFF */
-                                                          /* U+A640-U+A69F */
-  /* Bit 10   Armenian */
-#define TT_UCR_ARMENIAN                        (1L << 10) /* U+0530-U+058F */
-  /* Bit 11   Hebrew */
-#define TT_UCR_HEBREW                          (1L << 11) /* U+0590-U+05FF */
-  /* Bit 12   Vai */
-#define TT_UCR_VAI                             (1L << 12) /* U+A500-U+A63F */
-  /* Bit 13   Arabic            */
-  /*          Arabic Supplement */
-#define TT_UCR_ARABIC                          (1L << 13) /* U+0600-U+06FF */
-                                                          /* U+0750-U+077F */
-  /* Bit 14   NKo */
-#define TT_UCR_NKO                             (1L << 14) /* U+07C0-U+07FF */
-  /* Bit 15   Devanagari */
-#define TT_UCR_DEVANAGARI                      (1L << 15) /* U+0900-U+097F */
-  /* Bit 16   Bengali */
-#define TT_UCR_BENGALI                         (1L << 16) /* U+0980-U+09FF */
-  /* Bit 17   Gurmukhi */
-#define TT_UCR_GURMUKHI                        (1L << 17) /* U+0A00-U+0A7F */
-  /* Bit 18   Gujarati */
-#define TT_UCR_GUJARATI                        (1L << 18) /* U+0A80-U+0AFF */
-  /* Bit 19   Oriya */
-#define TT_UCR_ORIYA                           (1L << 19) /* U+0B00-U+0B7F */
-  /* Bit 20   Tamil */
-#define TT_UCR_TAMIL                           (1L << 20) /* U+0B80-U+0BFF */
-  /* Bit 21   Telugu */
-#define TT_UCR_TELUGU                          (1L << 21) /* U+0C00-U+0C7F */
-  /* Bit 22   Kannada */
-#define TT_UCR_KANNADA                         (1L << 22) /* U+0C80-U+0CFF */
-  /* Bit 23   Malayalam */
-#define TT_UCR_MALAYALAM                       (1L << 23) /* U+0D00-U+0D7F */
-  /* Bit 24   Thai */
-#define TT_UCR_THAI                            (1L << 24) /* U+0E00-U+0E7F */
-  /* Bit 25   Lao */
-#define TT_UCR_LAO                             (1L << 25) /* U+0E80-U+0EFF */
-  /* Bit 26   Georgian            */
-  /*          Georgian Supplement */
-#define TT_UCR_GEORGIAN                        (1L << 26) /* U+10A0-U+10FF */
-                                                          /* U+2D00-U+2D2F */
-  /* Bit 27   Balinese */
-#define TT_UCR_BALINESE                        (1L << 27) /* U+1B00-U+1B7F */
-  /* Bit 28   Hangul Jamo */
-#define TT_UCR_HANGUL_JAMO                     (1L << 28) /* U+1100-U+11FF */
-  /* Bit 29   Latin Extended Additional */
-  /*          Latin Extended-C          */
-  /*          Latin Extended-D          */
-#define TT_UCR_LATIN_EXTENDED_ADDITIONAL       (1L << 29) /* U+1E00-U+1EFF */
-                                                          /* U+2C60-U+2C7F */
-                                                          /* U+A720-U+A7FF */
-  /* Bit 30   Greek Extended */
-#define TT_UCR_GREEK_EXTENDED                  (1L << 30) /* U+1F00-U+1FFF */
-  /* Bit 31   General Punctuation      */
-  /*          Supplemental Punctuation */
-#define TT_UCR_GENERAL_PUNCTUATION             (1L << 31) /* U+2000-U+206F */
-                                                          /* U+2E00-U+2E7F */
-
-  /* ulUnicodeRange2 */
-  /* --------------- */
-
-  /* Bit 32   Superscripts And Subscripts */
-#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS         (1L <<  0) /* U+2070-U+209F */
-  /* Bit 33   Currency Symbols */
-#define TT_UCR_CURRENCY_SYMBOLS                (1L <<  1) /* U+20A0-U+20CF */
-  /* Bit 34   Combining Diacritical Marks For Symbols */
-#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \
-                                               (1L <<  2) /* U+20D0-U+20FF */
-  /* Bit 35   Letterlike Symbols */
-#define TT_UCR_LETTERLIKE_SYMBOLS              (1L <<  3) /* U+2100-U+214F */
-  /* Bit 36   Number Forms */
-#define TT_UCR_NUMBER_FORMS                    (1L <<  4) /* U+2150-U+218F */
-  /* Bit 37   Arrows                           */
-  /*          Supplemental Arrows-A            */
-  /*          Supplemental Arrows-B            */
-  /*          Miscellaneous Symbols and Arrows */
-#define TT_UCR_ARROWS                          (1L <<  5) /* U+2190-U+21FF */
-                                                          /* U+27F0-U+27FF */
-                                                          /* U+2900-U+297F */
-                                                          /* U+2B00-U+2BFF */
-  /* Bit 38   Mathematical Operators               */
-  /*          Supplemental Mathematical Operators  */
-  /*          Miscellaneous Mathematical Symbols-A */
-  /*          Miscellaneous Mathematical Symbols-B */
-#define TT_UCR_MATHEMATICAL_OPERATORS          (1L <<  6) /* U+2200-U+22FF */
-                                                          /* U+2A00-U+2AFF */
-                                                          /* U+27C0-U+27EF */
-                                                          /* U+2980-U+29FF */
-  /* Bit 39 Miscellaneous Technical */
-#define TT_UCR_MISCELLANEOUS_TECHNICAL         (1L <<  7) /* U+2300-U+23FF */
-  /* Bit 40   Control Pictures */
-#define TT_UCR_CONTROL_PICTURES                (1L <<  8) /* U+2400-U+243F */
-  /* Bit 41   Optical Character Recognition */
-#define TT_UCR_OCR                             (1L <<  9) /* U+2440-U+245F */
-  /* Bit 42   Enclosed Alphanumerics */
-#define TT_UCR_ENCLOSED_ALPHANUMERICS          (1L << 10) /* U+2460-U+24FF */
-  /* Bit 43   Box Drawing */
-#define TT_UCR_BOX_DRAWING                     (1L << 11) /* U+2500-U+257F */
-  /* Bit 44   Block Elements */
-#define TT_UCR_BLOCK_ELEMENTS                  (1L << 12) /* U+2580-U+259F */
-  /* Bit 45   Geometric Shapes */
-#define TT_UCR_GEOMETRIC_SHAPES                (1L << 13) /* U+25A0-U+25FF */
-  /* Bit 46   Miscellaneous Symbols */
-#define TT_UCR_MISCELLANEOUS_SYMBOLS           (1L << 14) /* U+2600-U+26FF */
-  /* Bit 47   Dingbats */
-#define TT_UCR_DINGBATS                        (1L << 15) /* U+2700-U+27BF */
-  /* Bit 48   CJK Symbols and Punctuation */
-#define TT_UCR_CJK_SYMBOLS                     (1L << 16) /* U+3000-U+303F */
-  /* Bit 49   Hiragana */
-#define TT_UCR_HIRAGANA                        (1L << 17) /* U+3040-U+309F */
-  /* Bit 50   Katakana                     */
-  /*          Katakana Phonetic Extensions */
-#define TT_UCR_KATAKANA                        (1L << 18) /* U+30A0-U+30FF */
-                                                          /* U+31F0-U+31FF */
-  /* Bit 51   Bopomofo          */
-  /*          Bopomofo Extended */
-#define TT_UCR_BOPOMOFO                        (1L << 19) /* U+3100-U+312F */
-                                                          /* U+31A0-U+31BF */
-  /* Bit 52   Hangul Compatibility Jamo */
-#define TT_UCR_HANGUL_COMPATIBILITY_JAMO       (1L << 20) /* U+3130-U+318F */
-  /* Bit 53   Phags-Pa */
-#define TT_UCR_CJK_MISC                        (1L << 21) /* U+A840-U+A87F */
-#define TT_UCR_KANBUN  TT_UCR_CJK_MISC /* deprecated */
-#define TT_UCR_PHAGSPA
-  /* Bit 54   Enclosed CJK Letters and Months */
-#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS     (1L << 22) /* U+3200-U+32FF */
-  /* Bit 55   CJK Compatibility */
-#define TT_UCR_CJK_COMPATIBILITY               (1L << 23) /* U+3300-U+33FF */
-  /* Bit 56   Hangul Syllables */
-#define TT_UCR_HANGUL                          (1L << 24) /* U+AC00-U+D7A3 */
-  /* Bit 57   High Surrogates              */
-  /*          High Private Use Surrogates  */
-  /*          Low Surrogates               */
-
-  /* According to OpenType specs v.1.3+,   */
-  /* setting bit 57 implies that there is  */
-  /* at least one codepoint beyond the     */
-  /* Basic Multilingual Plane that is      */
-  /* supported by this font.  So it really */
-  /* means >= U+10000.                     */
-#define TT_UCR_SURROGATES                      (1L << 25) /* U+D800-U+DB7F */
-                                                          /* U+DB80-U+DBFF */
-                                                          /* U+DC00-U+DFFF */
-#define TT_UCR_NON_PLANE_0  TT_UCR_SURROGATES
-  /* Bit 58  Phoenician */
-#define TT_UCR_PHOENICIAN                      (1L << 26) /*U+10900-U+1091F*/
-  /* Bit 59   CJK Unified Ideographs             */
-  /*          CJK Radicals Supplement            */
-  /*          Kangxi Radicals                    */
-  /*          Ideographic Description Characters */
-  /*          CJK Unified Ideographs Extension A */
-  /*          CJK Unified Ideographs Extension B */
-  /*          Kanbun                             */
-#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS          (1L << 27) /* U+4E00-U+9FFF */
-                                                          /* U+2E80-U+2EFF */
-                                                          /* U+2F00-U+2FDF */
-                                                          /* U+2FF0-U+2FFF */
-                                                          /* U+3400-U+4DB5 */
-                                                          /*U+20000-U+2A6DF*/
-                                                          /* U+3190-U+319F */
-  /* Bit 60   Private Use */
-#define TT_UCR_PRIVATE_USE                     (1L << 28) /* U+E000-U+F8FF */
-  /* Bit 61   CJK Strokes                             */
-  /*          CJK Compatibility Ideographs            */
-  /*          CJK Compatibility Ideographs Supplement */
-#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS    (1L << 29) /* U+31C0-U+31EF */
-                                                          /* U+F900-U+FAFF */
-                                                          /*U+2F800-U+2FA1F*/
-  /* Bit 62   Alphabetic Presentation Forms */
-#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS   (1L << 30) /* U+FB00-U+FB4F */
-  /* Bit 63   Arabic Presentation Forms-A */
-#define TT_UCR_ARABIC_PRESENTATION_FORMS_A     (1L << 31) /* U+FB50-U+FDFF */
-
-  /* ulUnicodeRange3 */
-  /* --------------- */
-
-  /* Bit 64   Combining Half Marks */
-#define TT_UCR_COMBINING_HALF_MARKS            (1L <<  0) /* U+FE20-U+FE2F */
-  /* Bit 65   Vertical forms          */
-  /*          CJK Compatibility Forms */
-#define TT_UCR_CJK_COMPATIBILITY_FORMS         (1L <<  1) /* U+FE10-U+FE1F */
-                                                          /* U+FE30-U+FE4F */
-  /* Bit 66   Small Form Variants */
-#define TT_UCR_SMALL_FORM_VARIANTS             (1L <<  2) /* U+FE50-U+FE6F */
-  /* Bit 67   Arabic Presentation Forms-B */
-#define TT_UCR_ARABIC_PRESENTATION_FORMS_B     (1L <<  3) /* U+FE70-U+FEFE */
-  /* Bit 68   Halfwidth and Fullwidth Forms */
-#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS       (1L <<  4) /* U+FF00-U+FFEF */
-  /* Bit 69   Specials */
-#define TT_UCR_SPECIALS                        (1L <<  5) /* U+FFF0-U+FFFD */
-  /* Bit 70   Tibetan */
-#define TT_UCR_TIBETAN                         (1L <<  6) /* U+0F00-U+0FFF */
-  /* Bit 71   Syriac */
-#define TT_UCR_SYRIAC                          (1L <<  7) /* U+0700-U+074F */
-  /* Bit 72   Thaana */
-#define TT_UCR_THAANA                          (1L <<  8) /* U+0780-U+07BF */
-  /* Bit 73   Sinhala */
-#define TT_UCR_SINHALA                         (1L <<  9) /* U+0D80-U+0DFF */
-  /* Bit 74   Myanmar */
-#define TT_UCR_MYANMAR                         (1L << 10) /* U+1000-U+109F */
-  /* Bit 75   Ethiopic            */
-  /*          Ethiopic Supplement */
-  /*          Ethiopic Extended   */
-#define TT_UCR_ETHIOPIC                        (1L << 11) /* U+1200-U+137F */
-                                                          /* U+1380-U+139F */
-                                                          /* U+2D80-U+2DDF */
-  /* Bit 76   Cherokee */
-#define TT_UCR_CHEROKEE                        (1L << 12) /* U+13A0-U+13FF */
-  /* Bit 77   Unified Canadian Aboriginal Syllabics */
-#define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS   (1L << 13) /* U+1400-U+167F */
-  /* Bit 78   Ogham */
-#define TT_UCR_OGHAM                           (1L << 14) /* U+1680-U+169F */
-  /* Bit 79   Runic */
-#define TT_UCR_RUNIC                           (1L << 15) /* U+16A0-U+16FF */
-  /* Bit 80   Khmer         */
-  /*          Khmer Symbols */
-#define TT_UCR_KHMER                           (1L << 16) /* U+1780-U+17FF */
-                                                          /* U+19E0-U+19FF */
-  /* Bit 81   Mongolian */
-#define TT_UCR_MONGOLIAN                       (1L << 17) /* U+1800-U+18AF */
-  /* Bit 82   Braille Patterns */
-#define TT_UCR_BRAILLE                         (1L << 18) /* U+2800-U+28FF */
-  /* Bit 83   Yi Syllables */
-  /*          Yi Radicals  */
-#define TT_UCR_YI                              (1L << 19) /* U+A000-U+A48F */
-                                                          /* U+A490-U+A4CF */
-  /* Bit 84   Tagalog  */
-  /*          Hanunoo  */
-  /*          Buhid    */
-  /*          Tagbanwa */
-#define TT_UCR_PHILIPPINE                      (1L << 20) /* U+1700-U+171F */
-                                                          /* U+1720-U+173F */
-                                                          /* U+1740-U+175F */
-                                                          /* U+1760-U+177F */
-  /* Bit 85   Old Italic */
-#define TT_UCR_OLD_ITALIC                      (1L << 21) /*U+10300-U+1032F*/
-  /* Bit 86   Gothic */
-#define TT_UCR_GOTHIC                          (1L << 22) /*U+10330-U+1034F*/
-  /* Bit 87   Deseret */
-#define TT_UCR_DESERET                         (1L << 23) /*U+10400-U+1044F*/
-  /* Bit 88   Byzantine Musical Symbols      */
-  /*          Musical Symbols                */
-  /*          Ancient Greek Musical Notation */
-#define TT_UCR_MUSICAL_SYMBOLS                 (1L << 24) /*U+1D000-U+1D0FF*/
-                                                          /*U+1D100-U+1D1FF*/
-                                                          /*U+1D200-U+1D24F*/
-  /* Bit 89   Mathematical Alphanumeric Symbols */
-#define TT_UCR_MATH_ALPHANUMERIC_SYMBOLS       (1L << 25) /*U+1D400-U+1D7FF*/
-  /* Bit 90   Private Use (plane 15) */
-  /*          Private Use (plane 16) */
-#define TT_UCR_PRIVATE_USE_SUPPLEMENTARY       (1L << 26) /*U+F0000-U+FFFFD*/
-                                                        /*U+100000-U+10FFFD*/
-  /* Bit 91   Variation Selectors            */
-  /*          Variation Selectors Supplement */
-#define TT_UCR_VARIATION_SELECTORS             (1L << 27) /* U+FE00-U+FE0F */
-                                                          /*U+E0100-U+E01EF*/
-  /* Bit 92   Tags */
-#define TT_UCR_TAGS                            (1L << 28) /*U+E0000-U+E007F*/
-  /* Bit 93   Limbu */
-#define TT_UCR_LIMBU                           (1L << 29) /* U+1900-U+194F */
-  /* Bit 94   Tai Le */
-#define TT_UCR_TAI_LE                          (1L << 30) /* U+1950-U+197F */
-  /* Bit 95   New Tai Lue */
-#define TT_UCR_NEW_TAI_LUE                     (1L << 31) /* U+1980-U+19DF */
-
-  /* ulUnicodeRange4 */
-  /* --------------- */
-
-  /* Bit 96   Buginese */
-#define TT_UCR_BUGINESE                        (1L <<  0) /* U+1A00-U+1A1F */
-  /* Bit 97   Glagolitic */
-#define TT_UCR_GLAGOLITIC                      (1L <<  1) /* U+2C00-U+2C5F */
-  /* Bit 98   Tifinagh */
-#define TT_UCR_TIFINAGH                        (1L <<  2) /* U+2D30-U+2D7F */
-  /* Bit 99   Yijing Hexagram Symbols */
-#define TT_UCR_YIJING                          (1L <<  3) /* U+4DC0-U+4DFF */
-  /* Bit 100  Syloti Nagri */
-#define TT_UCR_SYLOTI_NAGRI                    (1L <<  4) /* U+A800-U+A82F */
-  /* Bit 101  Linear B Syllabary */
-  /*          Linear B Ideograms */
-  /*          Aegean Numbers     */
-#define TT_UCR_LINEAR_B                        (1L <<  5) /*U+10000-U+1007F*/
-                                                          /*U+10080-U+100FF*/
-                                                          /*U+10100-U+1013F*/
-  /* Bit 102  Ancient Greek Numbers */
-#define TT_UCR_ANCIENT_GREEK_NUMBERS           (1L <<  6) /*U+10140-U+1018F*/
-  /* Bit 103  Ugaritic */
-#define TT_UCR_UGARITIC                        (1L <<  7) /*U+10380-U+1039F*/
-  /* Bit 104  Old Persian */
-#define TT_UCR_OLD_PERSIAN                     (1L <<  8) /*U+103A0-U+103DF*/
-  /* Bit 105  Shavian */
-#define TT_UCR_SHAVIAN                         (1L <<  9) /*U+10450-U+1047F*/
-  /* Bit 106  Osmanya */
-#define TT_UCR_OSMANYA                         (1L << 10) /*U+10480-U+104AF*/
-  /* Bit 107  Cypriot Syllabary */
-#define TT_UCR_CYPRIOT_SYLLABARY               (1L << 11) /*U+10800-U+1083F*/
-  /* Bit 108  Kharoshthi */
-#define TT_UCR_KHAROSHTHI                      (1L << 12) /*U+10A00-U+10A5F*/
-  /* Bit 109  Tai Xuan Jing Symbols */
-#define TT_UCR_TAI_XUAN_JING                   (1L << 13) /*U+1D300-U+1D35F*/
-  /* Bit 110  Cuneiform                         */
-  /*          Cuneiform Numbers and Punctuation */
-#define TT_UCR_CUNEIFORM                       (1L << 14) /*U+12000-U+123FF*/
-                                                          /*U+12400-U+1247F*/
-  /* Bit 111  Counting Rod Numerals */
-#define TT_UCR_COUNTING_ROD_NUMERALS           (1L << 15) /*U+1D360-U+1D37F*/
-  /* Bit 112  Sundanese */
-#define TT_UCR_SUNDANESE                       (1L << 16) /* U+1B80-U+1BBF */
-  /* Bit 113  Lepcha */
-#define TT_UCR_LEPCHA                          (1L << 17) /* U+1C00-U+1C4F */
-  /* Bit 114  Ol Chiki */
-#define TT_UCR_OL_CHIKI                        (1L << 18) /* U+1C50-U+1C7F */
-  /* Bit 115  Saurashtra */
-#define TT_UCR_SAURASHTRA                      (1L << 19) /* U+A880-U+A8DF */
-  /* Bit 116  Kayah Li */
-#define TT_UCR_KAYAH_LI                        (1L << 20) /* U+A900-U+A92F */
-  /* Bit 117  Rejang */
-#define TT_UCR_REJANG                          (1L << 21) /* U+A930-U+A95F */
-  /* Bit 118  Cham */
-#define TT_UCR_CHAM                            (1L << 22) /* U+AA00-U+AA5F */
-  /* Bit 119  Ancient Symbols */
-#define TT_UCR_ANCIENT_SYMBOLS                 (1L << 23) /*U+10190-U+101CF*/
-  /* Bit 120  Phaistos Disc */
-#define TT_UCR_PHAISTOS_DISC                   (1L << 24) /*U+101D0-U+101FF*/
-  /* Bit 121  Carian */
-  /*          Lycian */
-  /*          Lydian */
-#define TT_UCR_OLD_ANATOLIAN                   (1L << 25) /*U+102A0-U+102DF*/
-                                                          /*U+10280-U+1029F*/
-                                                          /*U+10920-U+1093F*/
-  /* Bit 122  Domino Tiles  */
-  /*          Mahjong Tiles */
-#define TT_UCR_GAME_TILES                      (1L << 26) /*U+1F030-U+1F09F*/
-                                                          /*U+1F000-U+1F02F*/
-  /* Bit 123-127 Reserved for process-internal usage */
-
- -

Possible bit mask values for the ulUnicodeRangeX fields in an SFNT ‘OS/2’ table.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-tt_driver.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-tt_driver.html deleted file mode 100644 index a5fe98a28..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-tt_driver.html +++ /dev/null @@ -1,1173 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The TrueType driver - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Controlling FreeType Modules » The TrueType driver

-
-

The TrueType driver

-

Synopsis

-

While FreeType's TrueType driver doesn't expose API functions by itself, it is possible to control its behaviour with FT_Property_Set and FT_Property_Get. The following lists the available properties together with the necessary macros and structures.

-

The TrueType driver's module name is ‘truetype’.

-

A single property interpreter-version is available, as documented in the ‘Driver properties’ section.

-

We start with a list of definitions, kindly provided by Greg Hitchcock.

-

Bi-Level Rendering

-

Monochromatic rendering, exclusively used in the early days of TrueType by both Apple and Microsoft. Microsoft's GDI interface supported hinting of the right-side bearing point, such that the advance width could be non-linear. Most often this was done to achieve some level of glyph symmetry. To enable reasonable performance (e.g., not having to run hinting on all glyphs just to get the widths) there was a bit in the head table indicating if the side bearing was hinted, and additional tables, ‘hdmx’ and ‘LTSH’, to cache hinting widths across multiple sizes and device aspect ratios.

-

Font Smoothing

-

Microsoft's GDI implementation of anti-aliasing. Not traditional anti-aliasing as the outlines were hinted before the sampling. The widths matched the bi-level rendering.

-

ClearType Rendering

-

Technique that uses physical subpixels to improve rendering on LCD (and other) displays. Because of the higher resolution, many methods of improving symmetry in glyphs through hinting the right-side bearing were no longer necessary. This lead to what GDI calls ‘natural widths’ ClearType, see http://rastertragedy.com/RTRCh4.htm#Sec21. Since hinting has extra resolution, most non-linearity went away, but it is still possible for hints to change the advance widths in this mode.

-

ClearType Compatible Widths

-

One of the earliest challenges with ClearType was allowing the implementation in GDI to be selected without requiring all UI and documents to reflow. To address this, a compatible method of rendering ClearType was added where the font hints are executed once to determine the width in bi-level rendering, and then re-run in ClearType, with the difference in widths being absorbed in the font hints for ClearType (mostly in the white space of hints); see http://rastertragedy.com/RTRCh4.htm#Sec20. Somewhat by definition, compatible width ClearType allows for non-linear widths, but only when the bi-level version has non-linear widths.

-

ClearType Subpixel Positioning

-

One of the nice benefits of ClearType is the ability to more crisply display fractional widths; unfortunately, the GDI model of integer bitmaps did not support this. However, the WPF and Direct Write frameworks do support fractional widths. DWrite calls this ‘natural mode’, not to be confused with GDI's ‘natural widths’. Subpixel positioning, in the current implementation of Direct Write, unfortunately does not support hinted advance widths, see http://rastertragedy.com/RTRCh4.htm#Sec22. Note that the TrueType interpreter fully allows the advance width to be adjusted in this mode, just the DWrite client will ignore those changes.

-

ClearType Backward Compatibility

-

This is a set of exceptions made in the TrueType interpreter to minimize hinting techniques that were problematic with the extra resolution of ClearType; see http://rastertragedy.com/RTRCh4.htm#Sec1 and https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx. This technique is not to be confused with ClearType compatible widths. ClearType backward compatibility has no direct impact on changing advance widths, but there might be an indirect impact on disabling some deltas. This could be worked around in backward compatibility mode.

-

Native ClearType Mode

-

(Not to be confused with ‘natural widths’.) This mode removes all the exceptions in the TrueType interpreter when running with ClearType. Any issues on widths would still apply, though.

- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-type1_tables.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-type1_tables.html deleted file mode 100644 index 675266f7c..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-type1_tables.html +++ /dev/null @@ -1,2101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Type 1 Tables - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - - - - -
-
- - - -

FreeType » Docs » Format-Specific API » Type 1 Tables

-
-

Type 1 Tables

-

Synopsis

-

This section contains the definition of Type 1-specific tables, including structures related to other PostScript font formats.

-

PS_FontInfoRec

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  typedef struct  PS_FontInfoRec_
-  {
-    FT_String*  version;
-    FT_String*  notice;
-    FT_String*  full_name;
-    FT_String*  family_name;
-    FT_String*  weight;
-    FT_Long     italic_angle;
-    FT_Bool     is_fixed_pitch;
-    FT_Short    underline_position;
-    FT_UShort   underline_thickness;
-
-  } PS_FontInfoRec;
-
- -

A structure used to model a Type 1 or Type 2 FontInfo dictionary. Note that for Multiple Master fonts, each instance has its own FontInfo dictionary.

-
- -

PS_FontInfo

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  typedef struct PS_FontInfoRec_*  PS_FontInfo;
-
- -

A handle to a PS_FontInfoRec structure.

-
- -

PS_PrivateRec

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  typedef struct  PS_PrivateRec_
-  {
-    FT_Int     unique_id;
-    FT_Int     lenIV;
-
-    FT_Byte    num_blue_values;
-    FT_Byte    num_other_blues;
-    FT_Byte    num_family_blues;
-    FT_Byte    num_family_other_blues;
-
-    FT_Short   blue_values[14];
-    FT_Short   other_blues[10];
-
-    FT_Short   family_blues      [14];
-    FT_Short   family_other_blues[10];
-
-    FT_Fixed   blue_scale;
-    FT_Int     blue_shift;
-    FT_Int     blue_fuzz;
-
-    FT_UShort  standard_width[1];
-    FT_UShort  standard_height[1];
-
-    FT_Byte    num_snap_widths;
-    FT_Byte    num_snap_heights;
-    FT_Bool    force_bold;
-    FT_Bool    round_stem_up;
-
-    FT_Short   snap_widths [13];  /* including std width  */
-    FT_Short   snap_heights[13];  /* including std height */
-
-    FT_Fixed   expansion_factor;
-
-    FT_Long    language_group;
-    FT_Long    password;
-
-    FT_Short   min_feature[2];
-
-  } PS_PrivateRec;
-
- -

A structure used to model a Type 1 or Type 2 private dictionary. Note that for Multiple Master fonts, each instance has its own Private dictionary.

-
- -

PS_Private

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  typedef struct PS_PrivateRec_*  PS_Private;
-
- -

A handle to a PS_PrivateRec structure.

-
- -

CID_FaceDictRec

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  typedef struct  CID_FaceDictRec_
-  {
-    PS_PrivateRec  private_dict;
-
-    FT_UInt        len_buildchar;
-    FT_Fixed       forcebold_threshold;
-    FT_Pos         stroke_width;
-    FT_Fixed       expansion_factor;   /* this is a duplicate of           */
-                                       /* `private_dict->expansion_factor' */
-    FT_Byte        paint_type;
-    FT_Byte        font_type;
-    FT_Matrix      font_matrix;
-    FT_Vector      font_offset;
-
-    FT_UInt        num_subrs;
-    FT_ULong       subrmap_offset;
-    FT_Int         sd_bytes;
-
-  } CID_FaceDictRec;
-
- -

A structure used to represent data in a CID top-level dictionary. In most cases, they are part of the font's ‘/FDArray’ array. Within a CID font file, such (internal) subfont dictionaries are enclosed by ‘%ADOBeginFontDict’ and ‘%ADOEndFontDict’ comments.

-

Note that CID_FaceDictRec misses a field for the ‘/FontName’ keyword, specifying the subfont's name (the top-level font name is given by the ‘/CIDFontName’ keyword). This is an oversight, but it doesn't limit the ‘cid’ font module's functionality because FreeType neither needs this entry nor gives access to CID subfonts.

-
- -

CID_FaceDict

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  typedef struct CID_FaceDictRec_*  CID_FaceDict;
-
- -

A handle to a CID_FaceDictRec structure.

-
- -

CID_FaceInfoRec

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  typedef struct  CID_FaceInfoRec_
-  {
-    FT_String*      cid_font_name;
-    FT_Fixed        cid_version;
-    FT_Int          cid_font_type;
-
-    FT_String*      registry;
-    FT_String*      ordering;
-    FT_Int          supplement;
-
-    PS_FontInfoRec  font_info;
-    FT_BBox         font_bbox;
-    FT_ULong        uid_base;
-
-    FT_Int          num_xuid;
-    FT_ULong        xuid[16];
-
-    FT_ULong        cidmap_offset;
-    FT_Int          fd_bytes;
-    FT_Int          gd_bytes;
-    FT_ULong        cid_count;
-
-    FT_Int          num_dicts;
-    CID_FaceDict    font_dicts;
-
-    FT_ULong        data_offset;
-
-  } CID_FaceInfoRec;
-
- -

A structure used to represent CID Face information.

-
- -

CID_FaceInfo

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  typedef struct CID_FaceInfoRec_*  CID_FaceInfo;
-
- -

A handle to a CID_FaceInfoRec structure.

-
- -

FT_Has_PS_Glyph_Names

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  FT_EXPORT( FT_Int )
-  FT_Has_PS_Glyph_Names( FT_Face  face );
-
- -

Return true if a given face provides reliable PostScript glyph names. This is similar to using the FT_HAS_GLYPH_NAMES macro, except that certain fonts (mostly TrueType) contain incorrect glyph name tables.

-

When this function returns true, the caller is sure that the glyph names returned by FT_Get_Glyph_Name are reliable.

-

input

- - - -
face -

face handle

-
- -

return

- -

Boolean. True if glyph names are reliable.

-
- -

FT_Get_PS_Font_Info

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_PS_Font_Info( FT_Face      face,
-                       PS_FontInfo  afont_info );
-
- -

Retrieve the PS_FontInfoRec structure corresponding to a given PostScript font.

-

input

- - - -
face -

PostScript face handle.

-
- -

output

- - - -
afont_info -

Output font info structure pointer.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

String pointers within the PS_FontInfoRec structure are owned by the face and don't need to be freed by the caller. Missing entries in the font's FontInfo dictionary are represented by NULL pointers.

-

If the font's format is not PostScript-based, this function will return the FT_Err_Invalid_Argument error code.

-
- -

FT_Get_PS_Font_Private

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_PS_Font_Private( FT_Face     face,
-                          PS_Private  afont_private );
-
- -

Retrieve the PS_PrivateRec structure corresponding to a given PostScript font.

-

input

- - - -
face -

PostScript face handle.

-
- -

output

- - - -
afont_private -

Output private dictionary structure pointer.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

The string pointers within the PS_PrivateRec structure are owned by the face and don't need to be freed by the caller.

-

If the font's format is not PostScript-based, this function returns the FT_Err_Invalid_Argument error code.

-
- -

FT_Get_PS_Font_Value

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  FT_EXPORT( FT_Long )
-  FT_Get_PS_Font_Value( FT_Face       face,
-                        PS_Dict_Keys  key,
-                        FT_UInt       idx,
-                        void         *value,
-                        FT_Long       value_len );
-
- -

Retrieve the value for the supplied key from a PostScript font.

-

input

- - - - - - - -
face -

PostScript face handle.

-
key -

An enumeration value representing the dictionary key to retrieve.

-
idx -

For array values, this specifies the index to be returned.

-
value -

A pointer to memory into which to write the value.

-
valen_len -

The size, in bytes, of the memory supplied for the value.

-
- -

output

- - - -
value -

The value matching the above key, if it exists.

-
- -

return

- -

The amount of memory (in bytes) required to hold the requested value (if it exists, -1 otherwise).

-

note

- -

The values returned are not pointers into the internal structures of the face, but are ‘fresh’ copies, so that the memory containing them belongs to the calling application. This also enforces the ‘read-only’ nature of these values, i.e., this function cannot be used to manipulate the face.

-

value is a void pointer because the values returned can be of various types.

-

If either value is NULL or value_len is too small, just the required memory size for the requested entry is returned.

-

The idx parameter is used, not only to retrieve elements of, for example, the FontMatrix or FontBBox, but also to retrieve name keys from the CharStrings dictionary, and the charstrings themselves. It is ignored for atomic values.

-

PS_DICT_BLUE_SCALE returns a value that is scaled up by 1000. To get the value as in the font stream, you need to divide by 65536000.0 (to remove the FT_Fixed scale, and the x1000 scale).

-

IMPORTANT: Only key/value pairs read by the FreeType interpreter can be retrieved. So, for example, PostScript procedures such as NP, ND, and RD are not available. Arbitrary keys are, obviously, not be available either.

-

If the font's format is not PostScript-based, this function returns the FT_Err_Invalid_Argument error code.

-

since

- -

2.4.8

-
- -

T1_Blend_Flags

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  typedef enum  T1_Blend_Flags_
-  {
-    /* required fields in a FontInfo blend dictionary */
-    T1_BLEND_UNDERLINE_POSITION = 0,
-    T1_BLEND_UNDERLINE_THICKNESS,
-    T1_BLEND_ITALIC_ANGLE,
-
-    /* required fields in a Private blend dictionary */
-    T1_BLEND_BLUE_VALUES,
-    T1_BLEND_OTHER_BLUES,
-    T1_BLEND_STANDARD_WIDTH,
-    T1_BLEND_STANDARD_HEIGHT,
-    T1_BLEND_STEM_SNAP_WIDTHS,
-    T1_BLEND_STEM_SNAP_HEIGHTS,
-    T1_BLEND_BLUE_SCALE,
-    T1_BLEND_BLUE_SHIFT,
-    T1_BLEND_FAMILY_BLUES,
-    T1_BLEND_FAMILY_OTHER_BLUES,
-    T1_BLEND_FORCE_BOLD,
-
-    T1_BLEND_MAX    /* do not remove */
-
-  } T1_Blend_Flags;
-
-
-  /* these constants are deprecated; use the corresponding */
-  /* `T1_Blend_Flags` values instead                       */
-#define t1_blend_underline_position   T1_BLEND_UNDERLINE_POSITION
-#define t1_blend_underline_thickness  T1_BLEND_UNDERLINE_THICKNESS
-#define t1_blend_italic_angle         T1_BLEND_ITALIC_ANGLE
-#define t1_blend_blue_values          T1_BLEND_BLUE_VALUES
-#define t1_blend_other_blues          T1_BLEND_OTHER_BLUES
-#define t1_blend_standard_widths      T1_BLEND_STANDARD_WIDTH
-#define t1_blend_standard_height      T1_BLEND_STANDARD_HEIGHT
-#define t1_blend_stem_snap_widths     T1_BLEND_STEM_SNAP_WIDTHS
-#define t1_blend_stem_snap_heights    T1_BLEND_STEM_SNAP_HEIGHTS
-#define t1_blend_blue_scale           T1_BLEND_BLUE_SCALE
-#define t1_blend_blue_shift           T1_BLEND_BLUE_SHIFT
-#define t1_blend_family_blues         T1_BLEND_FAMILY_BLUES
-#define t1_blend_family_other_blues   T1_BLEND_FAMILY_OTHER_BLUES
-#define t1_blend_force_bold           T1_BLEND_FORCE_BOLD
-#define t1_blend_max                  T1_BLEND_MAX
-
- -

A set of flags used to indicate which fields are present in a given blend dictionary (font info or private). Used to support Multiple Masters fonts.

-

values

- - - - - - - - - - - - - - - - -
T1_BLEND_UNDERLINE_POSITION - -
T1_BLEND_UNDERLINE_THICKNESS - -
T1_BLEND_ITALIC_ANGLE - -
T1_BLEND_BLUE_VALUES - -
T1_BLEND_OTHER_BLUES - -
T1_BLEND_STANDARD_WIDTH - -
T1_BLEND_STANDARD_HEIGHT - -
T1_BLEND_STEM_SNAP_WIDTHS - -
T1_BLEND_STEM_SNAP_HEIGHTS - -
T1_BLEND_BLUE_SCALE - -
T1_BLEND_BLUE_SHIFT - -
T1_BLEND_FAMILY_BLUES - -
T1_BLEND_FAMILY_OTHER_BLUES - -
T1_BLEND_FORCE_BOLD - -
- -
- -

T1_EncodingType

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  typedef enum  T1_EncodingType_
-  {
-    T1_ENCODING_TYPE_NONE = 0,
-    T1_ENCODING_TYPE_ARRAY,
-    T1_ENCODING_TYPE_STANDARD,
-    T1_ENCODING_TYPE_ISOLATIN1,
-    T1_ENCODING_TYPE_EXPERT
-
-  } T1_EncodingType;
-
- -

An enumeration describing the ‘Encoding’ entry in a Type 1 dictionary.

-

values

- - - - - - - -
T1_ENCODING_TYPE_NONE - -
T1_ENCODING_TYPE_ARRAY - -
T1_ENCODING_TYPE_STANDARD - -
T1_ENCODING_TYPE_ISOLATIN1 - -
T1_ENCODING_TYPE_EXPERT - -
- -

since

- -

2.4.8

-
- -

PS_Dict_Keys

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  typedef enum  PS_Dict_Keys_
-  {
-    /* conventionally in the font dictionary */
-    PS_DICT_FONT_TYPE,              /* FT_Byte         */
-    PS_DICT_FONT_MATRIX,            /* FT_Fixed        */
-    PS_DICT_FONT_BBOX,              /* FT_Fixed        */
-    PS_DICT_PAINT_TYPE,             /* FT_Byte         */
-    PS_DICT_FONT_NAME,              /* FT_String*      */
-    PS_DICT_UNIQUE_ID,              /* FT_Int          */
-    PS_DICT_NUM_CHAR_STRINGS,       /* FT_Int          */
-    PS_DICT_CHAR_STRING_KEY,        /* FT_String*      */
-    PS_DICT_CHAR_STRING,            /* FT_String*      */
-    PS_DICT_ENCODING_TYPE,          /* T1_EncodingType */
-    PS_DICT_ENCODING_ENTRY,         /* FT_String*      */
-
-    /* conventionally in the font Private dictionary */
-    PS_DICT_NUM_SUBRS,              /* FT_Int     */
-    PS_DICT_SUBR,                   /* FT_String* */
-    PS_DICT_STD_HW,                 /* FT_UShort  */
-    PS_DICT_STD_VW,                 /* FT_UShort  */
-    PS_DICT_NUM_BLUE_VALUES,        /* FT_Byte    */
-    PS_DICT_BLUE_VALUE,             /* FT_Short   */
-    PS_DICT_BLUE_FUZZ,              /* FT_Int     */
-    PS_DICT_NUM_OTHER_BLUES,        /* FT_Byte    */
-    PS_DICT_OTHER_BLUE,             /* FT_Short   */
-    PS_DICT_NUM_FAMILY_BLUES,       /* FT_Byte    */
-    PS_DICT_FAMILY_BLUE,            /* FT_Short   */
-    PS_DICT_NUM_FAMILY_OTHER_BLUES, /* FT_Byte    */
-    PS_DICT_FAMILY_OTHER_BLUE,      /* FT_Short   */
-    PS_DICT_BLUE_SCALE,             /* FT_Fixed   */
-    PS_DICT_BLUE_SHIFT,             /* FT_Int     */
-    PS_DICT_NUM_STEM_SNAP_H,        /* FT_Byte    */
-    PS_DICT_STEM_SNAP_H,            /* FT_Short   */
-    PS_DICT_NUM_STEM_SNAP_V,        /* FT_Byte    */
-    PS_DICT_STEM_SNAP_V,            /* FT_Short   */
-    PS_DICT_FORCE_BOLD,             /* FT_Bool    */
-    PS_DICT_RND_STEM_UP,            /* FT_Bool    */
-    PS_DICT_MIN_FEATURE,            /* FT_Short   */
-    PS_DICT_LEN_IV,                 /* FT_Int     */
-    PS_DICT_PASSWORD,               /* FT_Long    */
-    PS_DICT_LANGUAGE_GROUP,         /* FT_Long    */
-
-    /* conventionally in the font FontInfo dictionary */
-    PS_DICT_VERSION,                /* FT_String* */
-    PS_DICT_NOTICE,                 /* FT_String* */
-    PS_DICT_FULL_NAME,              /* FT_String* */
-    PS_DICT_FAMILY_NAME,            /* FT_String* */
-    PS_DICT_WEIGHT,                 /* FT_String* */
-    PS_DICT_IS_FIXED_PITCH,         /* FT_Bool    */
-    PS_DICT_UNDERLINE_POSITION,     /* FT_Short   */
-    PS_DICT_UNDERLINE_THICKNESS,    /* FT_UShort  */
-    PS_DICT_FS_TYPE,                /* FT_UShort  */
-    PS_DICT_ITALIC_ANGLE,           /* FT_Long    */
-
-    PS_DICT_MAX = PS_DICT_ITALIC_ANGLE
-
-  } PS_Dict_Keys;
-
- -

An enumeration used in calls to FT_Get_PS_Font_Value to identify the Type 1 dictionary entry to retrieve.

-

values

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PS_DICT_FONT_TYPE - -
PS_DICT_FONT_MATRIX - -
PS_DICT_FONT_BBOX - -
PS_DICT_PAINT_TYPE - -
PS_DICT_FONT_NAME - -
PS_DICT_UNIQUE_ID - -
PS_DICT_NUM_CHAR_STRINGS - -
PS_DICT_CHAR_STRING_KEY - -
PS_DICT_CHAR_STRING - -
PS_DICT_ENCODING_TYPE - -
PS_DICT_ENCODING_ENTRY - -
PS_DICT_NUM_SUBRS - -
PS_DICT_SUBR - -
PS_DICT_STD_HW - -
PS_DICT_STD_VW - -
PS_DICT_NUM_BLUE_VALUES - -
PS_DICT_BLUE_VALUE - -
PS_DICT_BLUE_FUZZ - -
PS_DICT_NUM_OTHER_BLUES - -
PS_DICT_OTHER_BLUE - -
PS_DICT_NUM_FAMILY_BLUES - -
PS_DICT_FAMILY_BLUE - -
PS_DICT_NUM_FAMILY_OTHER_BLUES - -
PS_DICT_FAMILY_OTHER_BLUE - -
PS_DICT_BLUE_SCALE - -
PS_DICT_BLUE_SHIFT - -
PS_DICT_NUM_STEM_SNAP_H - -
PS_DICT_STEM_SNAP_H - -
PS_DICT_NUM_STEM_SNAP_V - -
PS_DICT_STEM_SNAP_V - -
PS_DICT_FORCE_BOLD - -
PS_DICT_RND_STEM_UP - -
PS_DICT_MIN_FEATURE - -
PS_DICT_LEN_IV - -
PS_DICT_PASSWORD - -
PS_DICT_LANGUAGE_GROUP - -
PS_DICT_VERSION - -
PS_DICT_NOTICE - -
PS_DICT_FULL_NAME - -
PS_DICT_FAMILY_NAME - -
PS_DICT_WEIGHT - -
PS_DICT_IS_FIXED_PITCH - -
PS_DICT_UNDERLINE_POSITION - -
PS_DICT_UNDERLINE_THICKNESS - -
PS_DICT_FS_TYPE - -
PS_DICT_ITALIC_ANGLE - -
- -

since

- -

2.4.8

-
- -

T1_FontInfo

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  typedef PS_FontInfoRec  T1_FontInfo;
-
- -

This type is equivalent to PS_FontInfoRec. It is deprecated but kept to maintain source compatibility between various versions of FreeType.

-
- -

T1_Private

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  typedef PS_PrivateRec  T1_Private;
-
- -

This type is equivalent to PS_PrivateRec. It is deprecated but kept to maintain source compatibility between various versions of FreeType.

-
- -

CID_FontDict

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  typedef CID_FaceDictRec  CID_FontDict;
-
- -

This type is equivalent to CID_FaceDictRec. It is deprecated but kept to maintain source compatibility between various versions of FreeType.

-
- -

CID_Info

-

Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h).

-
  typedef CID_FaceInfoRec  CID_Info;
-
- -

This type is equivalent to CID_FaceInfoRec. It is deprecated but kept to maintain source compatibility between various versions of FreeType.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-user_allocation.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-user_allocation.html deleted file mode 100644 index 96427a4ae..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-user_allocation.html +++ /dev/null @@ -1,1156 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - User allocation - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » General Remarks » User allocation

-
-

User allocation

-

Synopsis

-

FreeType assumes that structures allocated by the user and passed as arguments are zeroed out except for the actual data. In other words, it is recommended to use calloc (or variants of it) instead of malloc for allocation.

- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-version.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-version.html deleted file mode 100644 index b0f3f5cd7..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-version.html +++ /dev/null @@ -1,1332 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FreeType Version - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Core API » FreeType Version

-
-

FreeType Version

-

Synopsis

-

Note that those functions and macros are of limited use because even a new release of FreeType with only documentation changes increases the version number.

-

FT_Library_Version

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( void )
-  FT_Library_Version( FT_Library   library,
-                      FT_Int      *amajor,
-                      FT_Int      *aminor,
-                      FT_Int      *apatch );
-
- -

Return the version of the FreeType library being used. This is useful when dynamically linking to the library, since one cannot use the macros FREETYPE_MAJOR, FREETYPE_MINOR, and FREETYPE_PATCH.

-

input

- - - -
library -

A source library handle.

-
- -

output

- - - - - -
amajor -

The major version number.

-
aminor -

The minor version number.

-
apatch -

The patch version number.

-
- -

note

- -

The reason why this function takes a library argument is because certain programs implement library initialization in a custom way that doesn't use FT_Init_FreeType.

-

In such cases, the library version might not be available before the library object has been created.

-
- -

FT_Face_CheckTrueTypePatents

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Bool )
-  FT_Face_CheckTrueTypePatents( FT_Face  face );
-
- -

Deprecated, does nothing.

-

input

- - - -
face -

A face handle.

-
- -

return

- -

Always returns false.

-

note

- -

Since May 2010, TrueType hinting is no longer patented.

-

since

- -

2.3.5

-
- -

FT_Face_SetUnpatentedHinting

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
  FT_EXPORT( FT_Bool )
-  FT_Face_SetUnpatentedHinting( FT_Face  face,
-                                FT_Bool  value );
-
- -

Deprecated, does nothing.

-

input

- - - - -
face -

A face handle.

-
value -

New boolean setting.

-
- -

return

- -

Always returns false.

-

note

- -

Since May 2010, TrueType hinting is no longer patented.

-

since

- -

2.3.5

-
- -

FREETYPE_XXX

-

Defined in FT_FREETYPE_H (freetype/freetype.h).

-
#define FREETYPE_MAJOR  2
-#define FREETYPE_MINOR  10
-#define FREETYPE_PATCH  4
-
- -

These three macros identify the FreeType source code version. Use FT_Library_Version to access them at runtime.

-

values

- - - - - -
FREETYPE_MAJOR -

The major version number.

-
FREETYPE_MINOR -

The minor version number.

-
FREETYPE_PATCH -

The patch level.

-
- -

note

- -

The version number of FreeType if built as a dynamic link library with the ‘libtool’ package is not controlled by these three macros.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/ft2-winfnt_fonts.html b/lib/libesp32_lvgl/freetype/docs/reference/ft2-winfnt_fonts.html deleted file mode 100644 index 31a060da4..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/ft2-winfnt_fonts.html +++ /dev/null @@ -1,1392 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Window FNT Files - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Format-Specific API » Window FNT Files

-
-

Window FNT Files

-

Synopsis

-

This section contains the declaration of Windows FNT-specific functions.

-

FT_WinFNT_ID_XXX

-

Defined in FT_WINFONTS_H (freetype/ftwinfnt.h).

-
#define FT_WinFNT_ID_CP1252    0
-#define FT_WinFNT_ID_DEFAULT   1
-#define FT_WinFNT_ID_SYMBOL    2
-#define FT_WinFNT_ID_MAC      77
-#define FT_WinFNT_ID_CP932   128
-#define FT_WinFNT_ID_CP949   129
-#define FT_WinFNT_ID_CP1361  130
-#define FT_WinFNT_ID_CP936   134
-#define FT_WinFNT_ID_CP950   136
-#define FT_WinFNT_ID_CP1253  161
-#define FT_WinFNT_ID_CP1254  162
-#define FT_WinFNT_ID_CP1258  163
-#define FT_WinFNT_ID_CP1255  177
-#define FT_WinFNT_ID_CP1256  178
-#define FT_WinFNT_ID_CP1257  186
-#define FT_WinFNT_ID_CP1251  204
-#define FT_WinFNT_ID_CP874   222
-#define FT_WinFNT_ID_CP1250  238
-#define FT_WinFNT_ID_OEM     255
-
- -

A list of valid values for the charset byte in FT_WinFNT_HeaderRec. Exact mapping tables for the various ‘cpXXXX’ encodings (except for ‘cp1361’) can be found at ‘ftp://ftp.unicode.org/Public/’ in the MAPPINGS/VENDORS/MICSFT/WINDOWS subdirectory. ‘cp1361’ is roughly a superset of MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT.

-

values

- - - - - - - - - - - - - - - - - - - - - -
FT_WinFNT_ID_DEFAULT -

This is used for font enumeration and font creation as a ‘don't care’ value. Valid font files don't contain this value. When querying for information about the character set of the font that is currently selected into a specified device context, this return value (of the related Windows API) simply denotes failure.

-
FT_WinFNT_ID_SYMBOL -

There is no known mapping table available.

-
FT_WinFNT_ID_MAC -

Mac Roman encoding.

-
FT_WinFNT_ID_OEM -

From Michael Poettgen <michael@poettgen.de>:

-

The ‘Windows Font Mapping’ article says that FT_WinFNT_ID_OEM is used for the charset of vector fonts, like modern.fon, roman.fon, and script.fon on Windows.

-

The ‘CreateFont’ documentation says: The FT_WinFNT_ID_OEM value specifies a character set that is operating-system dependent.

-

The ‘IFIMETRICS’ documentation from the ‘Windows Driver Development Kit’ says: This font supports an OEM-specific character set. The OEM character set is system dependent.

-

In general OEM, as opposed to ANSI (i.e., ‘cp1252’), denotes the second default codepage that most international versions of Windows have. It is one of the OEM codepages from

-

https://docs.microsoft.com/en-us/windows/desktop/intl/code-page-identifiers ,

-

and is used for the ‘DOS boxes’, to support legacy applications. A German Windows version for example usually uses ANSI codepage 1252 and OEM codepage 850.

-
FT_WinFNT_ID_CP874 -

A superset of Thai TIS 620 and ISO 8859-11.

-
FT_WinFNT_ID_CP932 -

A superset of Japanese Shift-JIS (with minor deviations).

-
FT_WinFNT_ID_CP936 -

A superset of simplified Chinese GB 2312-1980 (with different ordering and minor deviations).

-
FT_WinFNT_ID_CP949 -

A superset of Korean Hangul KS C 5601-1987 (with different ordering and minor deviations).

-
FT_WinFNT_ID_CP950 -

A superset of traditional Chinese Big 5 ETen (with different ordering and minor deviations).

-
FT_WinFNT_ID_CP1250 -

A superset of East European ISO 8859-2 (with slightly different ordering).

-
FT_WinFNT_ID_CP1251 -

A superset of Russian ISO 8859-5 (with different ordering).

-
FT_WinFNT_ID_CP1252 -

ANSI encoding. A superset of ISO 8859-1.

-
FT_WinFNT_ID_CP1253 -

A superset of Greek ISO 8859-7 (with minor modifications).

-
FT_WinFNT_ID_CP1254 -

A superset of Turkish ISO 8859-9.

-
FT_WinFNT_ID_CP1255 -

A superset of Hebrew ISO 8859-8 (with some modifications).

-
FT_WinFNT_ID_CP1256 -

A superset of Arabic ISO 8859-6 (with different ordering).

-
FT_WinFNT_ID_CP1257 -

A superset of Baltic ISO 8859-13 (with some deviations).

-
FT_WinFNT_ID_CP1258 -

For Vietnamese. This encoding doesn't cover all necessary characters.

-
FT_WinFNT_ID_CP1361 -

Korean (Johab).

-
- -
- -

FT_WinFNT_HeaderRec

-

Defined in FT_WINFONTS_H (freetype/ftwinfnt.h).

-
  typedef struct  FT_WinFNT_HeaderRec_
-  {
-    FT_UShort  version;
-    FT_ULong   file_size;
-    FT_Byte    copyright[60];
-    FT_UShort  file_type;
-    FT_UShort  nominal_point_size;
-    FT_UShort  vertical_resolution;
-    FT_UShort  horizontal_resolution;
-    FT_UShort  ascent;
-    FT_UShort  internal_leading;
-    FT_UShort  external_leading;
-    FT_Byte    italic;
-    FT_Byte    underline;
-    FT_Byte    strike_out;
-    FT_UShort  weight;
-    FT_Byte    charset;
-    FT_UShort  pixel_width;
-    FT_UShort  pixel_height;
-    FT_Byte    pitch_and_family;
-    FT_UShort  avg_width;
-    FT_UShort  max_width;
-    FT_Byte    first_char;
-    FT_Byte    last_char;
-    FT_Byte    default_char;
-    FT_Byte    break_char;
-    FT_UShort  bytes_per_row;
-    FT_ULong   device_offset;
-    FT_ULong   face_name_offset;
-    FT_ULong   bits_pointer;
-    FT_ULong   bits_offset;
-    FT_Byte    reserved;
-    FT_ULong   flags;
-    FT_UShort  A_space;
-    FT_UShort  B_space;
-    FT_UShort  C_space;
-    FT_UShort  color_table_offset;
-    FT_ULong   reserved1[4];
-
-  } FT_WinFNT_HeaderRec;
-
- -

Windows FNT Header info.

-
- -

FT_WinFNT_Header

-

Defined in FT_WINFONTS_H (freetype/ftwinfnt.h).

-
  typedef struct FT_WinFNT_HeaderRec_*  FT_WinFNT_Header;
-
- -

A handle to an FT_WinFNT_HeaderRec structure.

-
- -

FT_Get_WinFNT_Header

-

Defined in FT_WINFONTS_H (freetype/ftwinfnt.h).

-
  FT_EXPORT( FT_Error )
-  FT_Get_WinFNT_Header( FT_Face               face,
-                        FT_WinFNT_HeaderRec  *aheader );
-
- -

Retrieve a Windows FNT font info header.

-

input

- - - -
face -

A handle to the input face.

-
- -

output

- - - -
aheader -

The WinFNT header.

-
- -

return

- -

FreeType error code. 0 means success.

-

note

- -

This function only works with Windows FNT faces, returning an error otherwise.

-
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/images/favico.ico b/lib/libesp32_lvgl/freetype/docs/reference/images/favico.ico deleted file mode 100644 index a1a22ed43bd4a8f885c727c8061f5559517b5a0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1150 zcmdT^-7AAp7(X&LEj3e{LS{3z`3MP{Bt;~jGZfzUrDQ|%wJ=hwk&lHdqZO`Xxpv|2 za^b?w&pFS_TBLBdPS1JHd4A9DoagzS-j}f~J`4uNXA28x7&9@(9Nc(_N7OiXjB(7U zSB>_3vPwC~WRuRi@%r|XvVp^Dv~HT<**3$yWrinQgz=-c6fSZ{V-0YJ)tvHa4OZgQ zg!dg=V4u~J9u+gWjV-4yM29~AT-I - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TOC - FreeType-2.10.4 API Reference - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - -
- -
- -
- - - - -
-
- - -
-
-
- -
-
-
- - -
-
-
- - -
-
-
- - -
-
- - - -

FreeType » Docs » Table of Contents

-
-

FreeType-2.10.4 API Reference

-

Table of Contents

-

General Remarks

- - - -
-

How client applications should include FreeType header files.

-
-

How client applications should allocate FreeType data structures.

-
- -

Core API

- - - - - - - - - - - -
-

Functions and macros related to FreeType versions.

-
-

The basic data types defined by the library.

-
-

The FreeType 2 base font interface.

-
-

The FreeType 2 interface to Unicode Variation Sequences (UVS), using the SFNT cmap format 14.

-
-

Retrieving and manipulating OpenType's ‘CPAL’ table data.

-
-

Retrieving and manipulating OpenType's ‘COLR’ table data.

-
-

Generic interface to manage individual glyph data.

-
-

Only available on the Macintosh.

-
-

Managing multiple sizes per face.

-
-

Macro definitions used to #include specific header files.

-
- -

Format-Specific API

- - - - - - - - - - - -
-

How to manage Multiple Masters fonts.

-
-

TrueType-specific table types and functions.

-
-

Type 1-specific font tables.

-
-

Access the names embedded in TrueType and OpenType files.

-
-

BDF and PCF specific API.

-
-

CID-keyed font-specific API.

-
-

PFR/TrueDoc-specific API.

-
-

Windows FNT-specific API.

-
-

Getting the font format.

-
-

Retrieving TrueType ‘gasp’ table entries.

-
- -

Controlling FreeType Modules

- - - - - - - - - -
-

Controlling the auto-hinting module.

-
-

Controlling the CFF driver module.

-
-

Controlling the Type 1 and CID driver modules.

-
-

Controlling the TrueType driver module.

-
-

Controlling the PCF driver module.

-
-

Controlling driver modules.

-
-

Macros for driver property and font loading parameter tags.

-
-

API to control subpixel rendering.

-
- -

Cache Sub-System

- - -
-

How to cache face, size, and glyph data with FreeType 2.

-
- -

Support API

- - - - - - - - - - - - - -
-

Crunching fixed numbers and vectors.

-
-

Simple management of lists.

-
-

Functions to create, transform, and render vectorial glyph images.

-
-

Retrieve horizontal and vertical advance values without processing glyph outlines, if possible.

-
-

Handling FT_Bitmap objects.

-
-

How vectorial outlines are converted into bitmaps and pixmaps.

-
-

Generating bordered and stroked glyphs.

-
-

How FreeType manages memory and i/o.

-
-

How to add, upgrade, remove, and control modules from FreeType.

-
-

Using gzip-compressed font files.

-
-

Using LZW-compressed font files.

-
-

Using bzip2-compressed font files.

-
- -

Error Codes

- - - -
-

How to handle errors and error strings.

-
-

All possible error codes returned by FreeType functions.

-
- -

Miscellaneous

- - - - - -
-

An API to validate TrueTypeGX/AAT tables.

-
-

Custom Glyph Loading.

-
-

TrueType bytecode support.

-
-

An API to validate OpenType tables.

-
- -

Global Index

-
-
generated on Tue Oct 20 05:14:52 2020 UTC
- - - - - - - - - - -
-
-
-
- - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/javascripts/extra.js b/lib/libesp32_lvgl/freetype/docs/reference/javascripts/extra.js deleted file mode 100644 index 00f167089..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/javascripts/extra.js +++ /dev/null @@ -1,54 +0,0 @@ -/* -Internal link topbar offest adjust Javascript -Code provided by @makshh on GitHub - -Bug report on material-mkdocs - https://github.com/squidfunk/mkdocs-material/issues/791 -*/ - -// Offset top helper -function offsetY(elem) { - if(!elem) elem = this; - var y = elem.offsetTop; - while (elem = elem.offsetParent) { - y += elem.offsetTop; - } - return y; -} - -// If a link on the same page is clicked, calculate the -// correct offset and scroll to that part of the page. -// -var links = document.getElementsByTagName('a'); -for(var i = 0; i < links.length; i++) { - links[i].onclick = function (event) { - if (this.pathname == window.location.pathname && - this.protocol == window.location.protocol && - this.host == window.location.host) { - event.preventDefault(); - if(this.hash.substr(1)){ - var o = document.getElementById(this.hash.substr(1)); - var sT = offsetY(o) - document.getElementsByClassName('md-header')[0].clientHeight; - window.location.hash = this.hash; - window.scrollTo(0, sT); - } - } - } -} - -// Slugify supplied text -function slugify(text){ - text = text.toLowerCase(); - text = text.replace(" ", "-"); - return text; -} - -// If there is a hash in the url, slugify it -// and replace -if(window.location.hash) { - // Fragment exists - slug = slugify(window.location.hash); - history.replaceState(undefined, undefined, slug) - //window.location.hash = slug; - document.location.replace(window.location.href); -} diff --git a/lib/libesp32_lvgl/freetype/docs/reference/search/search_index.json b/lib/libesp32_lvgl/freetype/docs/reference/search/search_index.json deleted file mode 100644 index 60c8c8576..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/search/search_index.json +++ /dev/null @@ -1 +0,0 @@ -{"config":{"lang":["en"],"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"index.html","text":"FreeType \u00bb Docs \u00bb Table of Contents FreeType-2.10.4 API Reference \u00b6 Table of Contents \u00b6 General Remarks \u00b6 FreeType's header inclusion scheme How client applications should include FreeType header files. User allocation How client applications should allocate FreeType data structures. Core API \u00b6 FreeType Version Functions and macros related to FreeType versions. Basic Data Types The basic data types defined by the library. Base Interface The FreeType 2 base font interface. Unicode Variation Sequences The FreeType 2 interface to Unicode Variation Sequences (UVS), using the SFNT cmap format 14. Glyph Color Management Retrieving and manipulating OpenType's \u2018CPAL\u2019 table data. Glyph Layer Management Retrieving and manipulating OpenType's \u2018COLR\u2019 table data. Glyph Management Generic interface to manage individual glyph data. Mac Specific Interface Only available on the Macintosh. Size Management Managing multiple sizes per face. Header File Macros Macro definitions used to #include specific header files. Format-Specific API \u00b6 Multiple Masters How to manage Multiple Masters fonts. TrueType Tables TrueType-specific table types and functions. Type 1 Tables Type 1-specific font tables. SFNT Names Access the names embedded in TrueType and OpenType files. BDF and PCF Files BDF and PCF specific API. CID Fonts CID-keyed font-specific API. PFR Fonts PFR/TrueDoc-specific API. Window FNT Files Windows FNT-specific API. Font Formats Getting the font format. Gasp Table Retrieving TrueType \u2018gasp\u2019 table entries. Controlling FreeType Modules \u00b6 The auto-hinter Controlling the auto-hinting module. The CFF driver Controlling the CFF driver module. The Type 1 and CID drivers Controlling the Type 1 and CID driver modules. The TrueType driver Controlling the TrueType driver module. The PCF driver Controlling the PCF driver module. Driver properties Controlling driver modules. Parameter Tags Macros for driver property and font loading parameter tags. Subpixel Rendering API to control subpixel rendering. Cache Sub-System \u00b6 Cache Sub-System How to cache face, size, and glyph data with FreeType 2. Support API \u00b6 Computations Crunching fixed numbers and vectors. List Processing Simple management of lists. Outline Processing Functions to create, transform, and render vectorial glyph images. Quick retrieval of advance values Retrieve horizontal and vertical advance values without processing glyph outlines, if possible. Bitmap Handling Handling FT_Bitmap objects. Scanline Converter How vectorial outlines are converted into bitmaps and pixmaps. Glyph Stroker Generating bordered and stroked glyphs. System Interface How FreeType manages memory and i/o. Module Management How to add, upgrade, remove, and control modules from FreeType. GZIP Streams Using gzip-compressed font files. LZW Streams Using LZW-compressed font files. BZIP2 Streams Using bzip2-compressed font files. Error Codes \u00b6 Error Enumerations How to handle errors and error strings. Error Code Values All possible error codes returned by FreeType functions. Miscellaneous \u00b6 TrueTypeGX/AAT Validation An API to validate TrueTypeGX/AAT tables. Incremental Loading Custom Glyph Loading. The TrueType Engine TrueType bytecode support. OpenType Validation An API to validate OpenType tables. Global Index \u00b6 generated on Tue Oct 20 05:14:52 2020 UTC","title":"TOC"},{"location":"index.html#freetype-2104-api-reference","text":"","title":"FreeType-2.10.4 API Reference"},{"location":"index.html#table-of-contents","text":"","title":"Table of Contents"},{"location":"index.html#general-remarks","text":"FreeType's header inclusion scheme How client applications should include FreeType header files. User allocation How client applications should allocate FreeType data structures.","title":"General Remarks"},{"location":"index.html#core-api","text":"FreeType Version Functions and macros related to FreeType versions. Basic Data Types The basic data types defined by the library. Base Interface The FreeType 2 base font interface. Unicode Variation Sequences The FreeType 2 interface to Unicode Variation Sequences (UVS), using the SFNT cmap format 14. Glyph Color Management Retrieving and manipulating OpenType's \u2018CPAL\u2019 table data. Glyph Layer Management Retrieving and manipulating OpenType's \u2018COLR\u2019 table data. Glyph Management Generic interface to manage individual glyph data. Mac Specific Interface Only available on the Macintosh. Size Management Managing multiple sizes per face. Header File Macros Macro definitions used to #include specific header files.","title":"Core API"},{"location":"index.html#format-specific-api","text":"Multiple Masters How to manage Multiple Masters fonts. TrueType Tables TrueType-specific table types and functions. Type 1 Tables Type 1-specific font tables. SFNT Names Access the names embedded in TrueType and OpenType files. BDF and PCF Files BDF and PCF specific API. CID Fonts CID-keyed font-specific API. PFR Fonts PFR/TrueDoc-specific API. Window FNT Files Windows FNT-specific API. Font Formats Getting the font format. Gasp Table Retrieving TrueType \u2018gasp\u2019 table entries.","title":"Format-Specific API"},{"location":"index.html#controlling-freetype-modules","text":"The auto-hinter Controlling the auto-hinting module. The CFF driver Controlling the CFF driver module. The Type 1 and CID drivers Controlling the Type 1 and CID driver modules. The TrueType driver Controlling the TrueType driver module. The PCF driver Controlling the PCF driver module. Driver properties Controlling driver modules. Parameter Tags Macros for driver property and font loading parameter tags. Subpixel Rendering API to control subpixel rendering.","title":"Controlling FreeType Modules"},{"location":"index.html#cache-sub-system","text":"Cache Sub-System How to cache face, size, and glyph data with FreeType 2.","title":"Cache Sub-System"},{"location":"index.html#support-api","text":"Computations Crunching fixed numbers and vectors. List Processing Simple management of lists. Outline Processing Functions to create, transform, and render vectorial glyph images. Quick retrieval of advance values Retrieve horizontal and vertical advance values without processing glyph outlines, if possible. Bitmap Handling Handling FT_Bitmap objects. Scanline Converter How vectorial outlines are converted into bitmaps and pixmaps. Glyph Stroker Generating bordered and stroked glyphs. System Interface How FreeType manages memory and i/o. Module Management How to add, upgrade, remove, and control modules from FreeType. GZIP Streams Using gzip-compressed font files. LZW Streams Using LZW-compressed font files. BZIP2 Streams Using bzip2-compressed font files.","title":"Support API"},{"location":"index.html#error-codes","text":"Error Enumerations How to handle errors and error strings. Error Code Values All possible error codes returned by FreeType functions.","title":"Error Codes"},{"location":"index.html#miscellaneous","text":"TrueTypeGX/AAT Validation An API to validate TrueTypeGX/AAT tables. Incremental Loading Custom Glyph Loading. The TrueType Engine TrueType bytecode support. OpenType Validation An API to validate OpenType tables.","title":"Miscellaneous"},{"location":"index.html#global-index","text":"generated on Tue Oct 20 05:14:52 2020 UTC","title":"Global Index"},{"location":"ft2-auto_hinter.html","text":"FreeType \u00bb Docs \u00bb Controlling FreeType Modules \u00bb The auto-hinter The auto-hinter \u00b6 Synopsis \u00b6 While FreeType's auto-hinter doesn't expose API functions by itself, it is possible to control its behaviour with FT_Property_Set and FT_Property_Get . The following lists the available properties together with the necessary macros and structures. Note that the auto-hinter's module name is \u2018autofitter\u2019 for historical reasons. Available properties are increase-x-height , no-stem-darkening (experimental), darkening-parameters (experimental), warping (experimental), glyph-to-script-map (experimental), fallback-script (experimental), and default-script (experimental), as documented in the \u2018 Driver properties \u2019 section.","title":"The auto-hinter"},{"location":"ft2-auto_hinter.html#the-auto-hinter","text":"","title":"The auto-hinter"},{"location":"ft2-auto_hinter.html#synopsis","text":"While FreeType's auto-hinter doesn't expose API functions by itself, it is possible to control its behaviour with FT_Property_Set and FT_Property_Get . The following lists the available properties together with the necessary macros and structures. Note that the auto-hinter's module name is \u2018autofitter\u2019 for historical reasons. Available properties are increase-x-height , no-stem-darkening (experimental), darkening-parameters (experimental), warping (experimental), glyph-to-script-map (experimental), fallback-script (experimental), and default-script (experimental), as documented in the \u2018 Driver properties \u2019 section.","title":"Synopsis"},{"location":"ft2-base_interface.html","text":"FreeType \u00bb Docs \u00bb Core API \u00bb Base Interface Base Interface \u00b6 Synopsis \u00b6 This section describes the most important public high-level API functions of FreeType 2. FT_Library \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_LibraryRec_ * FT_Library ; A handle to a FreeType library instance. Each \u2018library\u2019 is completely independent from the others; it is the \u2018root\u2019 of a set of objects like fonts, faces, sizes, etc. It also embeds a memory manager (see FT_Memory ), as well as a scan-line converter object (see FT_Raster ). [Since 2.5.6] In multi-threaded applications it is easiest to use one FT_Library object per thread. In case this is too cumbersome, a single FT_Library object across threads is possible also, as long as a mutex lock is used around FT_New_Face and FT_Done_Face . note Library objects are normally created by FT_Init_FreeType , and destroyed with FT_Done_FreeType . If you need reference-counting (cf. FT_Reference_Library ), use FT_New_Library and FT_Done_Library . FT_Face \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_FaceRec_* FT_Face ; A handle to a typographic face object. A face object models a given typeface, in a given style. note A face object also owns a single FT_GlyphSlot object, as well as one or more FT_Size objects. Use FT_New_Face or FT_Open_Face to create a new face object from a given filepath or a custom input stream. Use FT_Done_Face to destroy it (along with its slot and sizes). An FT_Face object can only be safely used from one thread at a time. Similarly, creation and destruction of FT_Face with the same FT_Library object can only be done from one thread at a time. On the other hand, functions like FT_Load_Glyph and its siblings are thread-safe and do not need the lock to be held as long as the same FT_Face object is not used from multiple threads at the same time. also See FT_FaceRec for the publicly accessible fields of a given face object. FT_Size \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_SizeRec_* FT_Size ; A handle to an object that models a face scaled to a given character size. note An FT_Face has one active FT_Size object that is used by functions like FT_Load_Glyph to determine the scaling transformation that in turn is used to load and hint glyphs and metrics. You can use FT_Set_Char_Size , FT_Set_Pixel_Sizes , FT_Request_Size or even FT_Select_Size to change the content (i.e., the scaling values) of the active FT_Size . You can use FT_New_Size to create additional size objects for a given FT_Face , but they won't be used by other functions until you activate it through FT_Activate_Size . Only one size can be activated at any given time per face. also See FT_SizeRec for the publicly accessible fields of a given size object. FT_GlyphSlot \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_GlyphSlotRec_* FT_GlyphSlot ; A handle to a given \u2018glyph slot\u2019. A slot is a container that can hold any of the glyphs contained in its parent face. In other words, each time you call FT_Load_Glyph or FT_Load_Char , the slot's content is erased by the new glyph data, i.e., the glyph's metrics, its image (bitmap or outline), and other control information. also See FT_GlyphSlotRec for the publicly accessible glyph fields. FT_CharMap \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_CharMapRec_* FT_CharMap ; A handle to a character map (usually abbreviated to \u2018charmap\u2019). A charmap is used to translate character codes in a given encoding into glyph indexes for its parent's face. Some font formats may provide several charmaps per font. Each face object owns zero or more charmaps, but only one of them can be \u2018active\u2019, providing the data used by FT_Get_Char_Index or FT_Load_Char . The list of available charmaps in a face is available through the face->num_charmaps and face->charmaps fields of FT_FaceRec . The currently active charmap is available as face->charmap . You should call FT_Set_Charmap to change it. note When a new face is created (either through FT_New_Face or FT_Open_Face ), the library looks for a Unicode charmap within the list and automatically activates it. If there is no Unicode charmap, FreeType doesn't set an \u2018active\u2019 charmap. also See FT_CharMapRec for the publicly accessible fields of a given character map. FT_Encoding \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef enum FT_Encoding_ { FT_ENC_TAG ( FT_ENCODING_NONE , 0, 0, 0, 0 ), FT_ENC_TAG ( FT_ENCODING_MS_SYMBOL , 's', 'y', 'm', 'b' ), FT_ENC_TAG ( FT_ENCODING_UNICODE , 'u', 'n', 'i', 'c' ), FT_ENC_TAG ( FT_ENCODING_SJIS , 's', 'j', 'i', 's' ), FT_ENC_TAG ( FT_ENCODING_PRC , 'g', 'b', ' ', ' ' ), FT_ENC_TAG ( FT_ENCODING_BIG5 , 'b', 'i', 'g', '5' ), FT_ENC_TAG ( FT_ENCODING_WANSUNG , 'w', 'a', 'n', 's' ), FT_ENC_TAG ( FT_ENCODING_JOHAB , 'j', 'o', 'h', 'a' ), /* for backward compatibility */ FT_ENCODING_GB2312 = FT_ENCODING_PRC , FT_ENCODING_MS_SJIS = FT_ENCODING_SJIS , FT_ENCODING_MS_GB2312 = FT_ENCODING_PRC , FT_ENCODING_MS_BIG5 = FT_ENCODING_BIG5 , FT_ENCODING_MS_WANSUNG = FT_ENCODING_WANSUNG , FT_ENCODING_MS_JOHAB = FT_ENCODING_JOHAB , FT_ENC_TAG ( FT_ENCODING_ADOBE_STANDARD , 'A', 'D', 'O', 'B' ), FT_ENC_TAG ( FT_ENCODING_ADOBE_EXPERT , 'A', 'D', 'B', 'E' ), FT_ENC_TAG ( FT_ENCODING_ADOBE_CUSTOM , 'A', 'D', 'B', 'C' ), FT_ENC_TAG ( FT_ENCODING_ADOBE_LATIN_1 , 'l', 'a', 't', '1' ), FT_ENC_TAG ( FT_ENCODING_OLD_LATIN_2 , 'l', 'a', 't', '2' ), FT_ENC_TAG ( FT_ENCODING_APPLE_ROMAN , 'a', 'r', 'm', 'n' ) } FT_Encoding ; /* these constants are deprecated; use the corresponding ` FT_Encoding ` */ /* values instead */ # define ft_encoding_none FT_ENCODING_NONE # define ft_encoding_unicode FT_ENCODING_UNICODE # define ft_encoding_symbol FT_ENCODING_MS_SYMBOL # define ft_encoding_latin_1 FT_ENCODING_ADOBE_LATIN_1 # define ft_encoding_latin_2 FT_ENCODING_OLD_LATIN_2 # define ft_encoding_sjis FT_ENCODING_SJIS # define ft_encoding_gb2312 FT_ENCODING_PRC # define ft_encoding_big5 FT_ENCODING_BIG5 # define ft_encoding_wansung FT_ENCODING_WANSUNG # define ft_encoding_johab FT_ENCODING_JOHAB # define ft_encoding_adobe_standard FT_ENCODING_ADOBE_STANDARD # define ft_encoding_adobe_expert FT_ENCODING_ADOBE_EXPERT # define ft_encoding_adobe_custom FT_ENCODING_ADOBE_CUSTOM # define ft_encoding_apple_roman FT_ENCODING_APPLE_ROMAN An enumeration to specify character sets supported by charmaps. Used in the FT_Select_Charmap API function. note Despite the name, this enumeration lists specific character repertories (i.e., charsets), and not text encoding methods (e.g., UTF-8, UTF-16, etc.). Other encodings might be defined in the future. values FT_ENCODING_NONE The encoding value 0 is reserved for all formats except BDF, PCF, and Windows FNT; see below for more information. FT_ENCODING_UNICODE The Unicode character set. This value covers all versions of the Unicode repertoire, including ASCII and Latin-1. Most fonts include a Unicode charmap, but not all of them. For example, if you want to access Unicode value U+1F028 (and the font contains it), use value 0x1F028 as the input value for FT_Get_Char_Index . FT_ENCODING_MS_SYMBOL Microsoft Symbol encoding, used to encode mathematical symbols and wingdings. For more information, see \u2018 https://www.microsoft.com/typography/otspec/recom.htm#non-standard-symbol-fonts \u2019, \u2018 http://www.kostis.net/charsets/symbol.htm \u2019, and \u2018 http://www.kostis.net/charsets/wingding.htm \u2019. This encoding uses character codes from the PUA (Private Unicode Area) in the range U+F020-U+F0FF. FT_ENCODING_SJIS Shift JIS encoding for Japanese. More info at \u2018 https://en.wikipedia.org/wiki/Shift_JIS \u2019. See note on multi-byte encodings below. FT_ENCODING_PRC Corresponds to encoding systems mainly for Simplified Chinese as used in People's Republic of China (PRC). The encoding layout is based on GB 2312 and its supersets GBK and GB 18030. FT_ENCODING_BIG5 Corresponds to an encoding system for Traditional Chinese as used in Taiwan and Hong Kong. FT_ENCODING_WANSUNG Corresponds to the Korean encoding system known as Extended Wansung (MS Windows code page 949). For more information see \u2018 https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit949.txt \u2019. FT_ENCODING_JOHAB The Korean standard character set (KS C 5601-1992), which corresponds to MS Windows code page 1361. This character set includes all possible Hangul character combinations. FT_ENCODING_ADOBE_LATIN_1 Corresponds to a Latin-1 encoding as defined in a Type 1 PostScript font. It is limited to 256 character codes. FT_ENCODING_ADOBE_STANDARD Adobe Standard encoding, as found in Type 1, CFF, and OpenType/CFF fonts. It is limited to 256 character codes. FT_ENCODING_ADOBE_EXPERT Adobe Expert encoding, as found in Type 1, CFF, and OpenType/CFF fonts. It is limited to 256 character codes. FT_ENCODING_ADOBE_CUSTOM Corresponds to a custom encoding, as found in Type 1, CFF, and OpenType/CFF fonts. It is limited to 256 character codes. FT_ENCODING_APPLE_ROMAN Apple roman encoding. Many TrueType and OpenType fonts contain a charmap for this 8-bit encoding, since older versions of Mac OS are able to use it. FT_ENCODING_OLD_LATIN_2 This value is deprecated and was neither used nor reported by FreeType. Don't use or test for it. FT_ENCODING_MS_SJIS Same as FT_ENCODING_SJIS. Deprecated. FT_ENCODING_MS_GB2312 Same as FT_ENCODING_PRC. Deprecated. FT_ENCODING_MS_BIG5 Same as FT_ENCODING_BIG5. Deprecated. FT_ENCODING_MS_WANSUNG Same as FT_ENCODING_WANSUNG. Deprecated. FT_ENCODING_MS_JOHAB Same as FT_ENCODING_JOHAB. Deprecated. note By default, FreeType enables a Unicode charmap and tags it with FT_ENCODING_UNICODE when it is either provided or can be generated from PostScript glyph name dictionaries in the font file. All other encodings are considered legacy and tagged only if explicitly defined in the font file. Otherwise, FT_ENCODING_NONE is used. FT_ENCODING_NONE is set by the BDF and PCF drivers if the charmap is neither Unicode nor ISO-8859-1 (otherwise it is set to FT_ENCODING_UNICODE ). Use FT_Get_BDF_Charset_ID to find out which encoding is really present. If, for example, the cs_registry field is \u2018KOI8\u2019 and the cs_encoding field is \u2018R\u2019, the font is encoded in KOI8-R. FT_ENCODING_NONE is always set (with a single exception) by the winfonts driver. Use FT_Get_WinFNT_Header and examine the charset field of the FT_WinFNT_HeaderRec structure to find out which encoding is really present. For example, FT_WinFNT_ID_CP1251 (204) means Windows code page 1251 (for Russian). FT_ENCODING_NONE is set if platform_id is TT_PLATFORM_MACINTOSH and encoding_id is not TT_MAC_ID_ROMAN (otherwise it is set to FT_ENCODING_APPLE_ROMAN ). If platform_id is TT_PLATFORM_MACINTOSH , use the function FT_Get_CMap_Language_ID to query the Mac language ID that may be needed to be able to distinguish Apple encoding variants. See https://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt to get an idea how to do that. Basically, if the language ID is 0, don't use it, otherwise subtract 1 from the language ID. Then examine encoding_id . If, for example, encoding_id is TT_MAC_ID_ROMAN and the language ID (minus 1) is TT_MAC_LANGID_GREEK , it is the Greek encoding, not Roman. TT_MAC_ID_ARABIC with TT_MAC_LANGID_FARSI means the Farsi variant the Arabic encoding. FT_ENC_TAG \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # ifndef FT_ENC_TAG # define FT_ENC_TAG ( value, a, b, c, d ) \\ value = ( ( ( FT_UInt32 )(a) << 24 ) | \\ ( ( FT_UInt32 )(b) << 16 ) | \\ ( ( FT_UInt32 )(c) << 8 ) | \\ ( FT_UInt32 )(d) ) # endif /* FT_ENC_TAG */ This macro converts four-letter tags into an unsigned long. It is used to define \u2018encoding\u2019 identifiers (see FT_Encoding ). note Since many 16-bit compilers don't like 32-bit enumerations, you should redefine this macro in case of problems to something like this: #define FT_ENC_TAG( value, a, b, c, d ) value to get a simple enumeration without assigning special numbers. FT_FaceRec \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_FaceRec_ { FT_Long num_faces; FT_Long face_index; FT_Long face_flags; FT_Long style_flags; FT_Long num_glyphs; FT_String * family_name; FT_String * style_name; FT_Int num_fixed_sizes; FT_Bitmap_Size * available_sizes; FT_Int num_charmaps; FT_CharMap * charmaps; FT_Generic generic; /*# The following member variables (down to `underline_thickness`) */ /*# are only relevant to scalable outlines; cf. @ FT_Bitmap_Size */ /*# for bitmap fonts. */ FT_BBox bbox; FT_UShort units_per_EM; FT_Short ascender; FT_Short descender; FT_Short height; FT_Short max_advance_width; FT_Short max_advance_height; FT_Short underline_position; FT_Short underline_thickness; FT_GlyphSlot glyph; FT_Size size; FT_CharMap charmap; /*@private begin */ FT_Driver driver; FT_Memory memory; FT_Stream stream; FT_ListRec sizes_list; FT_Generic autohint; /* face-specific auto-hinter data */ void * extensions; /* unused */ FT_Face_Internal internal; /*@private end */ } FT_FaceRec ; FreeType root face class structure. A face object models a typeface in a font file. fields num_faces The number of faces in the font file. Some font formats can have multiple faces in a single font file. face_index This field holds two different values. Bits 0-15 are the index of the face in the font file (starting with value 0). They are set to 0 if there is only one face in the font file. [Since 2.6.1] Bits 16-30 are relevant to GX and OpenType variation fonts only, holding the named instance index for the current face index (starting with value 1; value 0 indicates font access without a named instance). For non-variation fonts, bits 16-30 are ignored. If we have the third named instance of face 4, say, face_index is set to 0x00030004. Bit 31 is always zero (this is, face_index is always a positive value). [Since 2.9] Changing the design coordinates with FT_Set_Var_Design_Coordinates or FT_Set_Var_Blend_Coordinates does not influence the named instance index value (only FT_Set_Named_Instance does that). face_flags A set of bit flags that give important information about the face; see FT_FACE_FLAG_XXX for the details. style_flags The lower 16 bits contain a set of bit flags indicating the style of the face; see FT_STYLE_FLAG_XXX for the details. [Since 2.6.1] Bits 16-30 hold the number of named instances available for the current face if we have a GX or OpenType variation (sub)font. Bit 31 is always zero (this is, style_flags is always a positive value). Note that a variation font has always at least one named instance, namely the default instance. num_glyphs The number of glyphs in the face. If the face is scalable and has sbits (see num_fixed_sizes ), it is set to the number of outline glyphs. For CID-keyed fonts (not in an SFNT wrapper) this value gives the highest CID used in the font. family_name The face's family name. This is an ASCII string, usually in English, that describes the typeface's family (like \u2018Times New Roman\u2019, \u2018Bodoni\u2019, \u2018Garamond\u2019, etc). This is a least common denominator used to list fonts. Some formats (TrueType & OpenType) provide localized and Unicode versions of this string. Applications should use the format-specific interface to access them. Can be NULL (e.g., in fonts embedded in a PDF file). In case the font doesn't provide a specific family name entry, FreeType tries to synthesize one, deriving it from other name entries. style_name The face's style name. This is an ASCII string, usually in English, that describes the typeface's style (like \u2018Italic\u2019, \u2018Bold\u2019, \u2018Condensed\u2019, etc). Not all font formats provide a style name, so this field is optional, and can be set to NULL . As for family_name , some formats provide localized and Unicode versions of this string. Applications should use the format-specific interface to access them. num_fixed_sizes The number of bitmap strikes in the face. Even if the face is scalable, there might still be bitmap strikes, which are called \u2018sbits\u2019 in that case. available_sizes An array of FT_Bitmap_Size for all bitmap strikes in the face. It is set to NULL if there is no bitmap strike. Note that FreeType tries to sanitize the strike data since they are sometimes sloppy or incorrect, but this can easily fail. num_charmaps The number of charmaps in the face. charmaps An array of the charmaps of the face. generic A field reserved for client uses. See the FT_Generic type description. bbox The font bounding box. Coordinates are expressed in font units (see units_per_EM ). The box is large enough to contain any glyph from the font. Thus, bbox.yMax can be seen as the \u2018maximum ascender\u2019, and bbox.yMin as the \u2018minimum descender\u2019. Only relevant for scalable formats. Note that the bounding box might be off by (at least) one pixel for hinted fonts. See FT_Size_Metrics for further discussion. Note that the bounding box does not vary in OpenType variable fonts and should only be used in relation to the default instance. units_per_EM The number of font units per EM square for this face. This is typically 2048 for TrueType fonts, and 1000 for Type 1 fonts. Only relevant for scalable formats. ascender The typographic ascender of the face, expressed in font units. For font formats not having this information, it is set to bbox.yMax . Only relevant for scalable formats. descender The typographic descender of the face, expressed in font units. For font formats not having this information, it is set to bbox.yMin . Note that this field is negative for values below the baseline. Only relevant for scalable formats. height This value is the vertical distance between two consecutive baselines, expressed in font units. It is always positive. Only relevant for scalable formats. If you want the global glyph height, use ascender - descender . max_advance_width The maximum advance width, in font units, for all glyphs in this face. This can be used to make word wrapping computations faster. Only relevant for scalable formats. max_advance_height The maximum advance height, in font units, for all glyphs in this face. This is only relevant for vertical layouts, and is set to height for fonts that do not provide vertical metrics. Only relevant for scalable formats. underline_position The position, in font units, of the underline line for this face. It is the center of the underlining stem. Only relevant for scalable formats. underline_thickness The thickness, in font units, of the underline for this face. Only relevant for scalable formats. glyph The face's associated glyph slot(s). size The current active size for this face. charmap The current active charmap for this face. note Fields may be changed after a call to FT_Attach_File or FT_Attach_Stream . For an OpenType variation font, the values of the following fields can change after a call to FT_Set_Var_Design_Coordinates (and friends) if the font contains an \u2018MVAR\u2019 table: ascender , descender , height , underline_position , and underline_thickness . Especially for TrueType fonts see also the documentation for FT_Size_Metrics . FT_HAS_HORIZONTAL \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_HORIZONTAL ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_HORIZONTAL ) ) A macro that returns true whenever a face object contains horizontal metrics (this is true for all font formats though). also FT_HAS_VERTICAL can be used to check for vertical metrics. FT_HAS_VERTICAL \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_VERTICAL ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_VERTICAL ) ) A macro that returns true whenever a face object contains real vertical metrics (and not only synthesized ones). FT_HAS_KERNING \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_KERNING ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_KERNING ) ) A macro that returns true whenever a face object contains kerning data that can be accessed with FT_Get_Kerning . FT_HAS_FIXED_SIZES \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_FIXED_SIZES ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_FIXED_SIZES ) ) A macro that returns true whenever a face object contains some embedded bitmaps. See the available_sizes field of the FT_FaceRec structure. FT_HAS_GLYPH_NAMES \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_GLYPH_NAMES ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) ) A macro that returns true whenever a face object contains some glyph names that can be accessed through FT_Get_Glyph_Name . FT_HAS_COLOR \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_COLOR ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_COLOR ) ) A macro that returns true whenever a face object contains tables for color glyphs. since 2.5.1 FT_HAS_MULTIPLE_MASTERS \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_MULTIPLE_MASTERS ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) ) A macro that returns true whenever a face object contains some multiple masters. The functions provided by FT_MULTIPLE_MASTERS_H are then available to choose the exact design you want. FT_IS_SFNT \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_IS_SFNT ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_SFNT ) ) A macro that returns true whenever a face object contains a font whose format is based on the SFNT storage scheme. This usually means: TrueType fonts, OpenType fonts, as well as SFNT-based embedded bitmap fonts. If this macro is true, all functions defined in FT_SFNT_NAMES_H and FT_TRUETYPE_TABLES_H are available. FT_IS_SCALABLE \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_IS_SCALABLE ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_SCALABLE ) ) A macro that returns true whenever a face object contains a scalable font face (true for TrueType, Type 1, Type 42, CID, OpenType/CFF, and PFR font formats). FT_IS_FIXED_WIDTH \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_IS_FIXED_WIDTH ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_FIXED_WIDTH ) ) A macro that returns true whenever a face object contains a font face that contains fixed-width (or \u2018monospace\u2019, \u2018fixed-pitch\u2019, etc.) glyphs. FT_IS_CID_KEYED \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_IS_CID_KEYED ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_CID_KEYED ) ) A macro that returns true whenever a face object contains a CID-keyed font. See the discussion of FT_FACE_FLAG_CID_KEYED for more details. If this macro is true, all functions defined in FT_CID_H are available. FT_IS_TRICKY \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_IS_TRICKY ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_TRICKY ) ) A macro that returns true whenever a face represents a \u2018tricky\u2019 font. See the discussion of FT_FACE_FLAG_TRICKY for more details. FT_IS_NAMED_INSTANCE \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_IS_NAMED_INSTANCE ( face ) \\ ( !!( (face)->face_index & 0x7FFF0000L ) ) A macro that returns true whenever a face object is a named instance of a GX or OpenType variation font. [Since 2.9] Changing the design coordinates with FT_Set_Var_Design_Coordinates or FT_Set_Var_Blend_Coordinates does not influence the return value of this macro (only FT_Set_Named_Instance does that). since 2.7 FT_IS_VARIATION \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_IS_VARIATION ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_VARIATION ) ) A macro that returns true whenever a face object has been altered by FT_Set_MM_Design_Coordinates , FT_Set_Var_Design_Coordinates , or FT_Set_Var_Blend_Coordinates . since 2.9 FT_SizeRec \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_SizeRec_ { FT_Face face; /* parent face object */ FT_Generic generic; /* generic pointer for client uses */ FT_Size_Metrics metrics; /* size metrics */ FT_Size_Internal internal; } FT_SizeRec ; FreeType root size class structure. A size object models a face object at a given size. fields face Handle to the parent face object. generic A typeless pointer, unused by the FreeType library or any of its drivers. It can be used by client applications to link their own data to each size object. metrics Metrics for this size object. This field is read-only. FT_Size_Metrics \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Size_Metrics_ { FT_UShort x_ppem; /* horizontal pixels per EM */ FT_UShort y_ppem; /* vertical pixels per EM */ FT_Fixed x_scale; /* scaling values used to convert font */ FT_Fixed y_scale; /* units to 26.6 fractional pixels */ FT_Pos ascender; /* ascender in 26.6 frac. pixels */ FT_Pos descender; /* descender in 26.6 frac. pixels */ FT_Pos height; /* text height in 26.6 frac. pixels */ FT_Pos max_advance; /* max horizontal advance, in 26.6 pixels */ } FT_Size_Metrics ; The size metrics structure gives the metrics of a size object. fields x_ppem The width of the scaled EM square in pixels, hence the term \u2018ppem\u2019 (pixels per EM). It is also referred to as \u2018nominal width\u2019. y_ppem The height of the scaled EM square in pixels, hence the term \u2018ppem\u2019 (pixels per EM). It is also referred to as \u2018nominal height\u2019. x_scale A 16.16 fractional scaling value to convert horizontal metrics from font units to 26.6 fractional pixels. Only relevant for scalable font formats. y_scale A 16.16 fractional scaling value to convert vertical metrics from font units to 26.6 fractional pixels. Only relevant for scalable font formats. ascender The ascender in 26.6 fractional pixels, rounded up to an integer value. See FT_FaceRec for the details. descender The descender in 26.6 fractional pixels, rounded down to an integer value. See FT_FaceRec for the details. height The height in 26.6 fractional pixels, rounded to an integer value. See FT_FaceRec for the details. max_advance The maximum advance width in 26.6 fractional pixels, rounded to an integer value. See FT_FaceRec for the details. note The scaling values, if relevant, are determined first during a size changing operation. The remaining fields are then set by the driver. For scalable formats, they are usually set to scaled values of the corresponding fields in FT_FaceRec . Some values like ascender or descender are rounded for historical reasons; more precise values (for outline fonts) can be derived by scaling the corresponding FT_FaceRec values manually, with code similar to the following. scaled_ascender = FT_MulFix( face->ascender, size_metrics->y_scale ); Note that due to glyph hinting and the selected rendering mode these values are usually not exact; consequently, they must be treated as unreliable with an error margin of at least one pixel! Indeed, the only way to get the exact metrics is to render all glyphs. As this would be a definite performance hit, it is up to client applications to perform such computations. The FT_Size_Metrics structure is valid for bitmap fonts also. TrueType fonts with native bytecode hinting All applications that handle TrueType fonts with native hinting must be aware that TTFs expect different rounding of vertical font dimensions. The application has to cater for this, especially if it wants to rely on a TTF's vertical data (for example, to properly align box characters vertically). Only the application knows in advance that it is going to use native hinting for TTFs! FreeType, on the other hand, selects the hinting mode not at the time of creating an FT_Size object but much later, namely while calling FT_Load_Glyph . Here is some pseudo code that illustrates a possible solution. font_format = FT_Get_Font_Format( face ); if ( !strcmp( font_format, \"TrueType\" ) && do_native_bytecode_hinting ) { ascender = ROUND( FT_MulFix( face->ascender, size_metrics->y_scale ) ); descender = ROUND( FT_MulFix( face->descender, size_metrics->y_scale ) ); } else { ascender = size_metrics->ascender; descender = size_metrics->descender; } height = size_metrics->height; max_advance = size_metrics->max_advance; FT_GlyphSlotRec \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_GlyphSlotRec_ { FT_Library library; FT_Face face; FT_GlyphSlot next; FT_UInt glyph_index; /* new in 2.10; was reserved previously */ FT_Generic generic; FT_Glyph_Metrics metrics; FT_Fixed linearHoriAdvance; FT_Fixed linearVertAdvance; FT_Vector advance; FT_Glyph_Format format; FT_Bitmap bitmap; FT_Int bitmap_left; FT_Int bitmap_top; FT_Outline outline; FT_UInt num_subglyphs; FT_SubGlyph subglyphs; void * control_data; long control_len; FT_Pos lsb_delta; FT_Pos rsb_delta; void * other; FT_Slot_Internal internal; } FT_GlyphSlotRec ; FreeType root glyph slot class structure. A glyph slot is a container where individual glyphs can be loaded, be they in outline or bitmap format. fields library A handle to the FreeType library instance this slot belongs to. face A handle to the parent face object. next In some cases (like some font tools), several glyph slots per face object can be a good thing. As this is rare, the glyph slots are listed through a direct, single-linked list using its next field. glyph_index [Since 2.10] The glyph index passed as an argument to FT_Load_Glyph while initializing the glyph slot. generic A typeless pointer unused by the FreeType library or any of its drivers. It can be used by client applications to link their own data to each glyph slot object. metrics The metrics of the last loaded glyph in the slot. The returned values depend on the last load flags (see the FT_Load_Glyph API function) and can be expressed either in 26.6 fractional pixels or font units. Note that even when the glyph image is transformed, the metrics are not. linearHoriAdvance The advance width of the unhinted glyph. Its value is expressed in 16.16 fractional pixels, unless FT_LOAD_LINEAR_DESIGN is set when loading the glyph. This field can be important to perform correct WYSIWYG layout. Only relevant for outline glyphs. linearVertAdvance The advance height of the unhinted glyph. Its value is expressed in 16.16 fractional pixels, unless FT_LOAD_LINEAR_DESIGN is set when loading the glyph. This field can be important to perform correct WYSIWYG layout. Only relevant for outline glyphs. advance This shorthand is, depending on FT_LOAD_IGNORE_TRANSFORM , the transformed (hinted) advance width for the glyph, in 26.6 fractional pixel format. As specified with FT_LOAD_VERTICAL_LAYOUT , it uses either the horiAdvance or the vertAdvance value of metrics field. format This field indicates the format of the image contained in the glyph slot. Typically FT_GLYPH_FORMAT_BITMAP , FT_GLYPH_FORMAT_OUTLINE , or FT_GLYPH_FORMAT_COMPOSITE , but other values are possible. bitmap This field is used as a bitmap descriptor. Note that the address and content of the bitmap buffer can change between calls of FT_Load_Glyph and a few other functions. bitmap_left The bitmap's left bearing expressed in integer pixels. bitmap_top The bitmap's top bearing expressed in integer pixels. This is the distance from the baseline to the top-most glyph scanline, upwards y coordinates being positive . outline The outline descriptor for the current glyph image if its format is FT_GLYPH_FORMAT_OUTLINE . Once a glyph is loaded, outline can be transformed, distorted, emboldened, etc. However, it must not be freed. [Since 2.10.1] If FT_LOAD_NO_SCALE is set, outline coordinates of OpenType variation fonts for a selected instance are internally handled as 26.6 fractional font units but returned as (rounded) integers, as expected. To get unrounded font units, don't use FT_LOAD_NO_SCALE but load the glyph with FT_LOAD_NO_HINTING and scale it, using the font's units_per_EM value as the ppem. num_subglyphs The number of subglyphs in a composite glyph. This field is only valid for the composite glyph format that should normally only be loaded with the FT_LOAD_NO_RECURSE flag. subglyphs An array of subglyph descriptors for composite glyphs. There are num_subglyphs elements in there. Currently internal to FreeType. control_data Certain font drivers can also return the control data for a given glyph image (e.g. TrueType bytecode, Type 1 charstrings, etc.). This field is a pointer to such data; it is currently internal to FreeType. control_len This is the length in bytes of the control data. Currently internal to FreeType. other Reserved. lsb_delta The difference between hinted and unhinted left side bearing while auto-hinting is active. Zero otherwise. rsb_delta The difference between hinted and unhinted right side bearing while auto-hinting is active. Zero otherwise. note If FT_Load_Glyph is called with default flags (see FT_LOAD_DEFAULT ) the glyph image is loaded in the glyph slot in its native format (e.g., an outline glyph for TrueType and Type 1 formats). [Since 2.9] The prospective bitmap metrics are calculated according to FT_LOAD_TARGET_XXX and other flags even for the outline glyph, even if FT_LOAD_RENDER is not set. This image can later be converted into a bitmap by calling FT_Render_Glyph . This function searches the current renderer for the native image's format, then invokes it. The renderer is in charge of transforming the native image through the slot's face transformation fields, then converting it into a bitmap that is returned in slot->bitmap . Note that slot->bitmap_left and slot->bitmap_top are also used to specify the position of the bitmap relative to the current pen position (e.g., coordinates (0,0) on the baseline). Of course, slot->format is also changed to FT_GLYPH_FORMAT_BITMAP . Here is a small pseudo code fragment that shows how to use lsb_delta and rsb_delta to do fractional positioning of glyphs: FT_GlyphSlot slot = face->glyph; FT_Pos origin_x = 0; for all glyphs do FT_Outline_Translate( slot->outline, origin_x & 63, 0 ); origin_x += slot->advance.x; origin_x += slot->lsb_delta - slot->rsb_delta; endfor Here is another small pseudo code fragment that shows how to use lsb_delta and rsb_delta to improve integer positioning of glyphs: FT_GlyphSlot slot = face->glyph; FT_Pos origin_x = 0; FT_Pos prev_rsb_delta = 0; for all glyphs do if ( prev_rsb_delta - slot->lsb_delta > 32 ) origin_x -= 64; else if ( prev_rsb_delta - slot->lsb_delta < -31 ) origin_x += 64; prev_rsb_delta = slot->rsb_delta; origin_x += slot->advance.x; endfor If you use strong auto-hinting, you must apply these delta values! Otherwise you will experience far too large inter-glyph spacing at small rendering sizes in most cases. Note that it doesn't harm to use the above code for other hinting modes also, since the delta values are zero then. FT_Glyph_Metrics \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Glyph_Metrics_ { FT_Pos width; FT_Pos height; FT_Pos horiBearingX; FT_Pos horiBearingY; FT_Pos horiAdvance; FT_Pos vertBearingX; FT_Pos vertBearingY; FT_Pos vertAdvance; } FT_Glyph_Metrics ; A structure to model the metrics of a single glyph. The values are expressed in 26.6 fractional pixel format; if the flag FT_LOAD_NO_SCALE has been used while loading the glyph, values are expressed in font units instead. fields width The glyph's width. height The glyph's height. horiBearingX Left side bearing for horizontal layout. horiBearingY Top side bearing for horizontal layout. horiAdvance Advance width for horizontal layout. vertBearingX Left side bearing for vertical layout. vertBearingY Top side bearing for vertical layout. Larger positive values mean further below the vertical glyph origin. vertAdvance Advance height for vertical layout. Positive values mean the glyph has a positive advance downward. note If not disabled with FT_LOAD_NO_HINTING , the values represent dimensions of the hinted glyph (in case hinting is applicable). Stroking a glyph with an outside border does not increase horiAdvance or vertAdvance ; you have to manually adjust these values to account for the added width and height. FreeType doesn't use the \u2018VORG\u2019 table data for CFF fonts because it doesn't have an interface to quickly retrieve the glyph height. The y coordinate of the vertical origin can be simply computed as vertBearingY + height after loading a glyph. FT_SubGlyph \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_SubGlyphRec_* FT_SubGlyph ; The subglyph structure is an internal object used to describe subglyphs (for example, in the case of composites). note The subglyph implementation is not part of the high-level API, hence the forward structure declaration. You can however retrieve subglyph information with FT_Get_SubGlyph_Info . FT_Bitmap_Size \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Bitmap_Size_ { FT_Short height; FT_Short width; FT_Pos size; FT_Pos x_ppem; FT_Pos y_ppem; } FT_Bitmap_Size ; This structure models the metrics of a bitmap strike (i.e., a set of glyphs for a given point size and resolution) in a bitmap font. It is used for the available_sizes field of FT_Face . fields height The vertical distance, in pixels, between two consecutive baselines. It is always positive. width The average width, in pixels, of all glyphs in the strike. size The nominal size of the strike in 26.6 fractional points. This field is not very useful. x_ppem The horizontal ppem (nominal width) in 26.6 fractional pixels. y_ppem The vertical ppem (nominal height) in 26.6 fractional pixels. note Windows FNT: The nominal size given in a FNT font is not reliable. If the driver finds it incorrect, it sets size to some calculated values, and x_ppem and y_ppem to the pixel width and height given in the font, respectively. TrueType embedded bitmaps: size , width , and height values are not contained in the bitmap strike itself. They are computed from the global font parameters. FT_Init_FreeType \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Init_FreeType ( FT_Library *alibrary ); Initialize a new FreeType library object. The set of modules that are registered by this function is determined at build time. output alibrary A handle to a new library object. return FreeType error code. 0 means success. note In case you want to provide your own memory allocating routines, use FT_New_Library instead, followed by a call to FT_Add_Default_Modules (or a series of calls to FT_Add_Module ) and FT_Set_Default_Properties . See the documentation of FT_Library and FT_Face for multi-threading issues. If you need reference-counting (cf. FT_Reference_Library ), use FT_New_Library and FT_Done_Library . If compilation option FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES is set, this function reads the FREETYPE_PROPERTIES environment variable to control driver properties. See section \u2018 Driver properties \u2019 for more. FT_Done_FreeType \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Done_FreeType ( FT_Library library ); Destroy a given FreeType library object and all of its children, including resources, drivers, faces, sizes, etc. input library A handle to the target library object. return FreeType error code. 0 means success. FT_New_Face \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_New_Face ( FT_Library library, const char * filepathname, FT_Long face_index, FT_Face *aface ); Call FT_Open_Face to open a font by its pathname. inout library A handle to the library resource. input pathname A path to the font file. face_index See FT_Open_Face for a detailed description of this parameter. output aface A handle to a new face object. If face_index is greater than or equal to zero, it must be non- NULL . return FreeType error code. 0 means success. note Use FT_Done_Face to destroy the created FT_Face object (along with its slot and sizes). FT_Done_Face \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Done_Face ( FT_Face face ); Discard a given face object, as well as all of its child slots and sizes. input face A handle to a target face object. return FreeType error code. 0 means success. note See the discussion of reference counters in the description of FT_Reference_Face . FT_Reference_Face \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Reference_Face ( FT_Face face ); A counter gets initialized to 1 at the time an FT_Face structure is created. This function increments the counter. FT_Done_Face then only destroys a face if the counter is 1, otherwise it simply decrements the counter. This function helps in managing life-cycles of structures that reference FT_Face objects. input face A handle to a target face object. return FreeType error code. 0 means success. since 2.4.2 FT_New_Memory_Face \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_New_Memory_Face ( FT_Library library, const FT_Byte * file_base, FT_Long file_size, FT_Long face_index, FT_Face *aface ); Call FT_Open_Face to open a font that has been loaded into memory. inout library A handle to the library resource. input file_base A pointer to the beginning of the font data. file_size The size of the memory chunk used by the font data. face_index See FT_Open_Face for a detailed description of this parameter. output aface A handle to a new face object. If face_index is greater than or equal to zero, it must be non- NULL . return FreeType error code. 0 means success. note You must not deallocate the memory before calling FT_Done_Face . FT_Face_Properties \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Face_Properties ( FT_Face face, FT_UInt num_properties, FT_Parameter * properties ); Set or override certain (library or module-wide) properties on a face-by-face basis. Useful for finer-grained control and avoiding locks on shared structures (threads can modify their own faces as they see fit). Contrary to FT_Property_Set , this function uses FT_Parameter so that you can pass multiple properties to the target face in one call. Note that only a subset of the available properties can be controlled. FT_PARAM_TAG_STEM_DARKENING (stem darkening, corresponding to the property no-stem-darkening provided by the \u2018autofit\u2019, \u2018cff\u2019, \u2018type1\u2019, and \u2018t1cid\u2019 modules; see no-stem-darkening ). FT_PARAM_TAG_LCD_FILTER_WEIGHTS (LCD filter weights, corresponding to function FT_Library_SetLcdFilterWeights ). FT_PARAM_TAG_RANDOM_SEED (seed value for the CFF, Type 1, and CID \u2018random\u2019 operator, corresponding to the random-seed property provided by the \u2018cff\u2019, \u2018type1\u2019, and \u2018t1cid\u2019 modules; see random-seed ). Pass NULL as data in FT_Parameter for a given tag to reset the option and use the library or module default again. input face A handle to the source face object. num_properties The number of properties that follow. properties A handle to an FT_Parameter array with num_properties elements. return FreeType error code. 0 means success. example Here is an example that sets three properties. You must define FT_CONFIG_OPTION_SUBPIXEL_RENDERING to make the LCD filter examples work. FT_Parameter property1; FT_Bool darken_stems = 1; FT_Parameter property2; FT_LcdFiveTapFilter custom_weight = { 0x11, 0x44, 0x56, 0x44, 0x11 }; FT_Parameter property3; FT_Int32 random_seed = 314159265; FT_Parameter properties[3] = { property1, property2, property3 }; property1.tag = FT_PARAM_TAG_STEM_DARKENING; property1.data = &darken_stems; property2.tag = FT_PARAM_TAG_LCD_FILTER_WEIGHTS; property2.data = custom_weight; property3.tag = FT_PARAM_TAG_RANDOM_SEED; property3.data = &random_seed; FT_Face_Properties( face, 3, properties ); The next example resets a single property to its default value. FT_Parameter property; property.tag = FT_PARAM_TAG_LCD_FILTER_WEIGHTS; property.data = NULL; FT_Face_Properties( face, 1, &property ); since 2.8 FT_Open_Face \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Open_Face ( FT_Library library, const FT_Open_Args * args, FT_Long face_index, FT_Face *aface ); Create a face object from a given resource described by FT_Open_Args . inout library A handle to the library resource. input args A pointer to an FT_Open_Args structure that must be filled by the caller. face_index This field holds two different values. Bits 0-15 are the index of the face in the font file (starting with value 0). Set it to 0 if there is only one face in the font file. [Since 2.6.1] Bits 16-30 are relevant to GX and OpenType variation fonts only, specifying the named instance index for the current face index (starting with value 1; value 0 makes FreeType ignore named instances). For non-variation fonts, bits 16-30 are ignored. Assuming that you want to access the third named instance in face 4, face_index should be set to 0x00030004. If you want to access face 4 without variation handling, simply set face_index to value 4. FT_Open_Face and its siblings can be used to quickly check whether the font format of a given font resource is supported by FreeType. In general, if the face_index argument is negative, the function's return value is 0 if the font format is recognized, or non-zero otherwise. The function allocates a more or less empty face handle in *aface (if aface isn't NULL ); the only two useful fields in this special case are face->num_faces and face->style_flags . For any negative value of face_index , face->num_faces gives the number of faces within the font file. For the negative value \u2018-(N+1)\u2019 (with \u2018N\u2019 a non-negative 16-bit value), bits 16-30 in face->style_flags give the number of named instances in face \u2018N\u2019 if we have a variation font (or zero otherwise). After examination, the returned FT_Face structure should be deallocated with a call to FT_Done_Face . output aface A handle to a new face object. If face_index is greater than or equal to zero, it must be non- NULL . return FreeType error code. 0 means success. note Unlike FreeType 1.x, this function automatically creates a glyph slot for the face object that can be accessed directly through face->glyph . Each new face object created with this function also owns a default FT_Size object, accessible as face->size . One FT_Library instance can have multiple face objects, this is, FT_Open_Face and its siblings can be called multiple times using the same library argument. See the discussion of reference counters in the description of FT_Reference_Face . example To loop over all faces, use code similar to the following snippet (omitting the error handling). ... FT_Face face; FT_Long i, num_faces; error = FT_Open_Face( library, args, -1, &face ); if ( error ) { ... } num_faces = face->num_faces; FT_Done_Face( face ); for ( i = 0; i < num_faces; i++ ) { ... error = FT_Open_Face( library, args, i, &face ); ... FT_Done_Face( face ); ... } To loop over all valid values for face_index , use something similar to the following snippet, again without error handling. The code accesses all faces immediately (thus only a single call of FT_Open_Face within the do-loop), with and without named instances. ... FT_Face face; FT_Long num_faces = 0; FT_Long num_instances = 0; FT_Long face_idx = 0; FT_Long instance_idx = 0; do { FT_Long id = ( instance_idx << 16 ) + face_idx; error = FT_Open_Face( library, args, id, &face ); if ( error ) { ... } num_faces = face->num_faces; num_instances = face->style_flags >> 16; ... FT_Done_Face( face ); if ( instance_idx < num_instances ) instance_idx++; else { face_idx++; instance_idx = 0; } } while ( face_idx < num_faces ) FT_Open_Args \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Open_Args_ { FT_UInt flags; const FT_Byte * memory_base; FT_Long memory_size; FT_String * pathname; FT_Stream stream; FT_Module driver; FT_Int num_params; FT_Parameter * params; } FT_Open_Args ; A structure to indicate how to open a new font file or stream. A pointer to such a structure can be used as a parameter for the functions FT_Open_Face and FT_Attach_Stream . fields flags A set of bit flags indicating how to use the structure. memory_base The first byte of the file in memory. memory_size The size in bytes of the file in memory. pathname A pointer to an 8-bit file pathname. The pointer is not owned by FreeType. stream A handle to a source stream object. driver This field is exclusively used by FT_Open_Face ; it simply specifies the font driver to use for opening the face. If set to NULL , FreeType tries to load the face with each one of the drivers in its list. num_params The number of extra parameters. params Extra parameters passed to the font driver when opening a new face. note The stream type is determined by the contents of flags that are tested in the following order by FT_Open_Face : If the FT_OPEN_MEMORY bit is set, assume that this is a memory file of memory_size bytes, located at memory_address . The data are not copied, and the client is responsible for releasing and destroying them after the corresponding call to FT_Done_Face . Otherwise, if the FT_OPEN_STREAM bit is set, assume that a custom input stream stream is used. Otherwise, if the FT_OPEN_PATHNAME bit is set, assume that this is a normal file and use pathname to open it. If the FT_OPEN_DRIVER bit is set, FT_Open_Face only tries to open the file with the driver whose handler is in driver . If the FT_OPEN_PARAMS bit is set, the parameters given by num_params and params is used. They are ignored otherwise. Ideally, both the pathname and params fields should be tagged as \u2018const\u2019; this is missing for API backward compatibility. In other words, applications should treat them as read-only. FT_Parameter \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Parameter_ { FT_ULong tag; FT_Pointer data; } FT_Parameter ; A simple structure to pass more or less generic parameters to FT_Open_Face and FT_Face_Properties . fields tag A four-byte identification tag. data A pointer to the parameter data. note The ID and function of parameters are driver-specific. See section \u2018 Parameter Tags \u2019 for more information. FT_Attach_File \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Attach_File ( FT_Face face, const char * filepathname ); Call FT_Attach_Stream to attach a file. inout face The target face object. input filepathname The pathname. return FreeType error code. 0 means success. FT_Attach_Stream \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Attach_Stream ( FT_Face face, FT_Open_Args * parameters ); \u2018Attach\u2019 data to a face object. Normally, this is used to read additional information for the face object. For example, you can attach an AFM file that comes with a Type 1 font to get the kerning values and other metrics. inout face The target face object. input parameters A pointer to FT_Open_Args that must be filled by the caller. return FreeType error code. 0 means success. note The meaning of the \u2018attach\u2019 (i.e., what really happens when the new file is read) is not fixed by FreeType itself. It really depends on the font format (and thus the font driver). Client applications are expected to know what they are doing when invoking this function. Most drivers simply do not implement file or stream attachments. FT_Set_Char_Size \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Set_Char_Size ( FT_Face face, FT_F26Dot6 char_width, FT_F26Dot6 char_height, FT_UInt horz_resolution, FT_UInt vert_resolution ); Call FT_Request_Size to request the nominal size (in points). inout face A handle to a target face object. input char_width The nominal width, in 26.6 fractional points. char_height The nominal height, in 26.6 fractional points. horz_resolution The horizontal resolution in dpi. vert_resolution The vertical resolution in dpi. return FreeType error code. 0 means success. note While this function allows fractional points as input values, the resulting ppem value for the given resolution is always rounded to the nearest integer. If either the character width or height is zero, it is set equal to the other value. If either the horizontal or vertical resolution is zero, it is set equal to the other value. A character width or height smaller than 1pt is set to 1pt; if both resolution values are zero, they are set to 72dpi. Don't use this function if you are using the FreeType cache API. FT_Set_Pixel_Sizes \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Set_Pixel_Sizes ( FT_Face face, FT_UInt pixel_width, FT_UInt pixel_height ); Call FT_Request_Size to request the nominal size (in pixels). inout face A handle to the target face object. input pixel_width The nominal width, in pixels. pixel_height The nominal height, in pixels. return FreeType error code. 0 means success. note You should not rely on the resulting glyphs matching or being constrained to this pixel size. Refer to FT_Request_Size to understand how requested sizes relate to actual sizes. Don't use this function if you are using the FreeType cache API. FT_Request_Size \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Request_Size ( FT_Face face, FT_Size_Request req ); Resize the scale of the active FT_Size object in a face. inout face A handle to a target face object. input req A pointer to a FT_Size_RequestRec . return FreeType error code. 0 means success. note Although drivers may select the bitmap strike matching the request, you should not rely on this if you intend to select a particular bitmap strike. Use FT_Select_Size instead in that case. The relation between the requested size and the resulting glyph size is dependent entirely on how the size is defined in the source face. The font designer chooses the final size of each glyph relative to this size. For more information refer to \u2018 https://www.freetype.org/freetype2/docs/glyphs/glyphs-2.html \u2019. Contrary to FT_Set_Char_Size , this function doesn't have special code to normalize zero-valued widths, heights, or resolutions (which lead to errors in most cases). Don't use this function if you are using the FreeType cache API. FT_Select_Size \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Select_Size ( FT_Face face, FT_Int strike_index ); Select a bitmap strike. To be more precise, this function sets the scaling factors of the active FT_Size object in a face so that bitmaps from this particular strike are taken by FT_Load_Glyph and friends. inout face A handle to a target face object. input strike_index The index of the bitmap strike in the available_sizes field of FT_FaceRec structure. return FreeType error code. 0 means success. note For bitmaps embedded in outline fonts it is common that only a subset of the available glyphs at a given ppem value is available. FreeType silently uses outlines if there is no bitmap for a given glyph index. For GX and OpenType variation fonts, a bitmap strike makes sense only if the default instance is active (this is, no glyph variation takes place); otherwise, FreeType simply ignores bitmap strikes. The same is true for all named instances that are different from the default instance. Don't use this function if you are using the FreeType cache API. FT_Size_Request_Type \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef enum FT_Size_Request_Type_ { FT_SIZE_REQUEST_TYPE_NOMINAL , FT_SIZE_REQUEST_TYPE_REAL_DIM , FT_SIZE_REQUEST_TYPE_BBOX , FT_SIZE_REQUEST_TYPE_CELL , FT_SIZE_REQUEST_TYPE_SCALES , FT_SIZE_REQUEST_TYPE_MAX } FT_Size_Request_Type ; An enumeration type that lists the supported size request types, i.e., what input size (in font units) maps to the requested output size (in pixels, as computed from the arguments of FT_Size_Request ). values FT_SIZE_REQUEST_TYPE_NOMINAL The nominal size. The units_per_EM field of FT_FaceRec is used to determine both scaling values. This is the standard scaling found in most applications. In particular, use this size request type for TrueType fonts if they provide optical scaling or something similar. Note, however, that units_per_EM is a rather abstract value which bears no relation to the actual size of the glyphs in a font. FT_SIZE_REQUEST_TYPE_REAL_DIM The real dimension. The sum of the ascender and (minus of) the descender fields of FT_FaceRec is used to determine both scaling values. FT_SIZE_REQUEST_TYPE_BBOX The font bounding box. The width and height of the bbox field of FT_FaceRec are used to determine the horizontal and vertical scaling value, respectively. FT_SIZE_REQUEST_TYPE_CELL The max_advance_width field of FT_FaceRec is used to determine the horizontal scaling value; the vertical scaling value is determined the same way as FT_SIZE_REQUEST_TYPE_REAL_DIM does. Finally, both scaling values are set to the smaller one. This type is useful if you want to specify the font size for, say, a window of a given dimension and 80x24 cells. FT_SIZE_REQUEST_TYPE_SCALES Specify the scaling values directly. note The above descriptions only apply to scalable formats. For bitmap formats, the behaviour is up to the driver. See the note section of FT_Size_Metrics if you wonder how size requesting relates to scaling values. FT_Size_RequestRec \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Size_RequestRec_ { FT_Size_Request_Type type; FT_Long width; FT_Long height; FT_UInt horiResolution; FT_UInt vertResolution; } FT_Size_RequestRec ; A structure to model a size request. fields type See FT_Size_Request_Type . width The desired width, given as a 26.6 fractional point value (with 72pt = 1in). height The desired height, given as a 26.6 fractional point value (with 72pt = 1in). horiResolution The horizontal resolution (dpi, i.e., pixels per inch). If set to zero, width is treated as a 26.6 fractional pixel value, which gets internally rounded to an integer. vertResolution The vertical resolution (dpi, i.e., pixels per inch). If set to zero, height is treated as a 26.6 fractional pixel value, which gets internally rounded to an integer. note If width is zero, the horizontal scaling value is set equal to the vertical scaling value, and vice versa. If type is FT_SIZE_REQUEST_TYPE_SCALES , width and height are interpreted directly as 16.16 fractional scaling values, without any further modification, and both horiResolution and vertResolution are ignored. FT_Size_Request \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Size_RequestRec_ * FT_Size_Request ; A handle to a size request structure. FT_Set_Transform \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( void ) FT_Set_Transform ( FT_Face face, FT_Matrix * matrix, FT_Vector * delta ); Set the transformation that is applied to glyph images when they are loaded into a glyph slot through FT_Load_Glyph . inout face A handle to the source face object. input matrix A pointer to the transformation's 2x2 matrix. Use NULL for the identity matrix. delta A pointer to the translation vector. Use NULL for the null vector. note This function is provided as a convenience, but keep in mind that FT_Matrix coefficients are only 16.16 fixed point values, which can limit the accuracy of the results. Using floating-point computations to perform the transform directly in client code instead will always yield better numbers. The transformation is only applied to scalable image formats after the glyph has been loaded. It means that hinting is unaltered by the transformation and is performed on the character size given in the last call to FT_Set_Char_Size or FT_Set_Pixel_Sizes . Note that this also transforms the face.glyph.advance field, but not the values in face.glyph.metrics . FT_Load_Glyph \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Load_Glyph ( FT_Face face, FT_UInt glyph_index, FT_Int32 load_flags ); Load a glyph into the glyph slot of a face object. inout face A handle to the target face object where the glyph is loaded. input glyph_index The index of the glyph in the font file. For CID-keyed fonts (either in PS or in CFF format) this argument specifies the CID value. load_flags A flag indicating what to load for this glyph. The FT_LOAD_XXX constants can be used to control the glyph loading process (e.g., whether the outline should be scaled, whether to load bitmaps or not, whether to hint the outline, etc). return FreeType error code. 0 means success. note The loaded glyph may be transformed. See FT_Set_Transform for the details. For subsetted CID-keyed fonts, FT_Err_Invalid_Argument is returned for invalid CID values (this is, for CID values that don't have a corresponding glyph in the font). See the discussion of the FT_FACE_FLAG_CID_KEYED flag for more details. If you receive FT_Err_Glyph_Too_Big , try getting the glyph outline at EM size, then scale it manually and fill it as a graphics operation. FT_Get_Char_Index \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_UInt ) FT_Get_Char_Index ( FT_Face face, FT_ULong charcode ); Return the glyph index of a given character code. This function uses the currently selected charmap to do the mapping. input face A handle to the source face object. charcode The character code. return The glyph index. 0 means \u2018undefined character code\u2019. note If you use FreeType to manipulate the contents of font files directly, be aware that the glyph index returned by this function doesn't always correspond to the internal indices used within the file. This is done to ensure that value 0 always corresponds to the \u2018missing glyph\u2019. If the first glyph is not named \u2018.notdef\u2019, then for Type 1 and Type 42 fonts, \u2018.notdef\u2019 will be moved into the glyph ID 0 position, and whatever was there will be moved to the position \u2018.notdef\u2019 had. For Type 1 fonts, if there is no \u2018.notdef\u2019 glyph at all, then one will be created at index 0 and whatever was there will be moved to the last index -- Type 42 fonts are considered invalid under this condition. FT_Get_First_Char \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_ULong ) FT_Get_First_Char ( FT_Face face, FT_UInt *agindex ); Return the first character code in the current charmap of a given face, together with its corresponding glyph index. input face A handle to the source face object. output agindex Glyph index of first character code. 0 if charmap is empty. return The charmap's first character code. note You should use this function together with FT_Get_Next_Char to parse all character codes available in a given charmap. The code should look like this: FT_ULong charcode; FT_UInt gindex; charcode = FT_Get_First_Char( face, &gindex ); while ( gindex != 0 ) { ... do something with (charcode,gindex) pair ... charcode = FT_Get_Next_Char( face, charcode, &gindex ); } Be aware that character codes can have values up to 0xFFFFFFFF; this might happen for non-Unicode or malformed cmaps. However, even with regular Unicode encoding, so-called \u2018last resort fonts\u2019 (using SFNT cmap format 13, see function FT_Get_CMap_Format ) normally have entries for all Unicode characters up to 0x1FFFFF, which can cause a lot of iterations. Note that *agindex is set to 0 if the charmap is empty. The result itself can be 0 in two cases: if the charmap is empty or if the value 0 is the first valid character code. FT_Get_Next_Char \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_ULong ) FT_Get_Next_Char ( FT_Face face, FT_ULong char_code, FT_UInt *agindex ); Return the next character code in the current charmap of a given face following the value char_code , as well as the corresponding glyph index. input face A handle to the source face object. char_code The starting character code. output agindex Glyph index of next character code. 0 if charmap is empty. return The charmap's next character code. note You should use this function with FT_Get_First_Char to walk over all character codes available in a given charmap. See the note for that function for a simple code example. Note that *agindex is set to 0 when there are no more codes in the charmap. FT_Get_Name_Index \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_UInt ) FT_Get_Name_Index ( FT_Face face, const FT_String * glyph_name ); Return the glyph index of a given glyph name. input face A handle to the source face object. glyph_name The glyph name. return The glyph index. 0 means \u2018undefined character code\u2019. FT_Load_Char \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Load_Char ( FT_Face face, FT_ULong char_code, FT_Int32 load_flags ); Load a glyph into the glyph slot of a face object, accessed by its character code. inout face A handle to a target face object where the glyph is loaded. input char_code The glyph's character code, according to the current charmap used in the face. load_flags A flag indicating what to load for this glyph. The FT_LOAD_XXX constants can be used to control the glyph loading process (e.g., whether the outline should be scaled, whether to load bitmaps or not, whether to hint the outline, etc). return FreeType error code. 0 means success. note This function simply calls FT_Get_Char_Index and FT_Load_Glyph . Many fonts contain glyphs that can't be loaded by this function since its glyph indices are not listed in any of the font's charmaps. If no active cmap is set up (i.e., face->charmap is zero), the call to FT_Get_Char_Index is omitted, and the function behaves identically to FT_Load_Glyph . FT_LOAD_TARGET_MODE \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_LOAD_TARGET_MODE ( x ) ( ( FT_Render_Mode )( ( (x) >> 16 ) & 15 ) ) Return the FT_Render_Mode corresponding to a given FT_LOAD_TARGET_XXX value. FT_Render_Glyph \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Render_Glyph ( FT_GlyphSlot slot, FT_Render_Mode render_mode ); Convert a given glyph image to a bitmap. It does so by inspecting the glyph image format, finding the relevant renderer, and invoking it. inout slot A handle to the glyph slot containing the image to convert. input render_mode The render mode used to render the glyph image into a bitmap. See FT_Render_Mode for a list of possible values. If FT_RENDER_MODE_NORMAL is used, a previous call of FT_Load_Glyph with flag FT_LOAD_COLOR makes FT_Render_Glyph provide a default blending of colored glyph layers associated with the current glyph slot (provided the font contains such layers) instead of rendering the glyph slot's outline. This is an experimental feature; see FT_LOAD_COLOR for more information. return FreeType error code. 0 means success. note To get meaningful results, font scaling values must be set with functions like FT_Set_Char_Size before calling FT_Render_Glyph . When FreeType outputs a bitmap of a glyph, it really outputs an alpha coverage map. If a pixel is completely covered by a filled-in outline, the bitmap contains 0xFF at that pixel, meaning that 0xFF/0xFF fraction of that pixel is covered, meaning the pixel is 100% black (or 0% bright). If a pixel is only 50% covered (value 0x80), the pixel is made 50% black (50% bright or a middle shade of grey). 0% covered means 0% black (100% bright or white). On high-DPI screens like on smartphones and tablets, the pixels are so small that their chance of being completely covered and therefore completely black are fairly good. On the low-DPI screens, however, the situation is different. The pixels are too large for most of the details of a glyph and shades of gray are the norm rather than the exception. This is relevant because all our screens have a second problem: they are not linear. 1 + 1 is not 2. Twice the value does not result in twice the brightness. When a pixel is only 50% covered, the coverage map says 50% black, and this translates to a pixel value of 128 when you use 8 bits per channel (0-255). However, this does not translate to 50% brightness for that pixel on our sRGB and gamma 2.2 screens. Due to their non-linearity, they dwell longer in the darks and only a pixel value of about 186 results in 50% brightness -- 128 ends up too dark on both bright and dark backgrounds. The net result is that dark text looks burnt-out, pixely and blotchy on bright background, bright text too frail on dark backgrounds, and colored text on colored background (for example, red on green) seems to have dark halos or \u2018dirt\u2019 around it. The situation is especially ugly for diagonal stems like in \u2018w\u2019 glyph shapes where the quality of FreeType's anti-aliasing depends on the correct display of grays. On high-DPI screens where smaller, fully black pixels reign supreme, this doesn't matter, but on our low-DPI screens with all the gray shades, it does. 0% and 100% brightness are the same things in linear and non-linear space, just all the shades in-between aren't. The blending function for placing text over a background is dst = alpha * src + (1 - alpha) * dst , which is known as the OVER operator. To correctly composite an antialiased pixel of a glyph onto a surface, take the foreground and background colors (e.g., in sRGB space) and apply gamma to get them in a linear space, use OVER to blend the two linear colors using the glyph pixel as the alpha value (remember, the glyph bitmap is an alpha coverage bitmap), and apply inverse gamma to the blended pixel and write it back to the image. Internal testing at Adobe found that a target inverse gamma of 1.8 for step 3 gives good results across a wide range of displays with an sRGB gamma curve or a similar one. This process can cost performance. There is an approximation that does not need to know about the background color; see https://bel.fi/alankila/lcd/ and https://bel.fi/alankila/lcd/alpcor.html for details. ATTENTION : Linear blending is even more important when dealing with subpixel-rendered glyphs to prevent color-fringing! A subpixel-rendered glyph must first be filtered with a filter that gives equal weight to the three color primaries and does not exceed a sum of 0x100, see section \u2018 Subpixel Rendering \u2019. Then the only difference to gray linear blending is that subpixel-rendered linear blending is done 3 times per pixel: red foreground subpixel to red background subpixel and so on for green and blue. FT_Render_Mode \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef enum FT_Render_Mode_ { FT_RENDER_MODE_NORMAL = 0, FT_RENDER_MODE_LIGHT , FT_RENDER_MODE_MONO , FT_RENDER_MODE_LCD , FT_RENDER_MODE_LCD_V , FT_RENDER_MODE_MAX } FT_Render_Mode ; /* these constants are deprecated; use the corresponding */ /* ` FT_Render_Mode ` values instead */ # define ft_render_mode_normal FT_RENDER_MODE_NORMAL # define ft_render_mode_mono FT_RENDER_MODE_MONO Render modes supported by FreeType 2. Each mode corresponds to a specific type of scanline conversion performed on the outline. For bitmap fonts and embedded bitmaps the bitmap->pixel_mode field in the FT_GlyphSlotRec structure gives the format of the returned bitmap. All modes except FT_RENDER_MODE_MONO use 256 levels of opacity, indicating pixel coverage. Use linear alpha blending and gamma correction to correctly render non-monochrome glyph bitmaps onto a surface; see FT_Render_Glyph . values FT_RENDER_MODE_NORMAL Default render mode; it corresponds to 8-bit anti-aliased bitmaps. FT_RENDER_MODE_LIGHT This is equivalent to FT_RENDER_MODE_NORMAL . It is only defined as a separate value because render modes are also used indirectly to define hinting algorithm selectors. See FT_LOAD_TARGET_XXX for details. FT_RENDER_MODE_MONO This mode corresponds to 1-bit bitmaps (with 2 levels of opacity). FT_RENDER_MODE_LCD This mode corresponds to horizontal RGB and BGR subpixel displays like LCD screens. It produces 8-bit bitmaps that are 3 times the width of the original glyph outline in pixels, and which use the FT_PIXEL_MODE_LCD mode. FT_RENDER_MODE_LCD_V This mode corresponds to vertical RGB and BGR subpixel displays (like PDA screens, rotated LCD displays, etc.). It produces 8-bit bitmaps that are 3 times the height of the original glyph outline in pixels and use the FT_PIXEL_MODE_LCD_V mode. note The selected render mode only affects vector glyphs of a font. Embedded bitmaps often have a different pixel mode like FT_PIXEL_MODE_MONO . You can use FT_Bitmap_Convert to transform them into 8-bit pixmaps. FT_Get_Kerning \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Get_Kerning ( FT_Face face, FT_UInt left_glyph, FT_UInt right_glyph, FT_UInt kern_mode, FT_Vector *akerning ); Return the kerning vector between two glyphs of the same face. input face A handle to a source face object. left_glyph The index of the left glyph in the kern pair. right_glyph The index of the right glyph in the kern pair. kern_mode See FT_Kerning_Mode for more information. Determines the scale and dimension of the returned kerning vector. output akerning The kerning vector. This is either in font units, fractional pixels (26.6 format), or pixels for scalable formats, and in pixels for fixed-sizes formats. return FreeType error code. 0 means success. note Only horizontal layouts (left-to-right & right-to-left) are supported by this method. Other layouts, or more sophisticated kernings, are out of the scope of this API function -- they can be implemented through format-specific interfaces. Kerning for OpenType fonts implemented in a \u2018GPOS\u2019 table is not supported; use FT_HAS_KERNING to find out whether a font has data that can be extracted with FT_Get_Kerning . FT_Kerning_Mode \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef enum FT_Kerning_Mode_ { FT_KERNING_DEFAULT = 0, FT_KERNING_UNFITTED , FT_KERNING_UNSCALED } FT_Kerning_Mode ; /* these constants are deprecated; use the corresponding */ /* ` FT_Kerning_Mode ` values instead */ # define ft_kerning_default FT_KERNING_DEFAULT # define ft_kerning_unfitted FT_KERNING_UNFITTED # define ft_kerning_unscaled FT_KERNING_UNSCALED An enumeration to specify the format of kerning values returned by FT_Get_Kerning . values FT_KERNING_DEFAULT Return grid-fitted kerning distances in 26.6 fractional pixels. FT_KERNING_UNFITTED Return un-grid-fitted kerning distances in 26.6 fractional pixels. FT_KERNING_UNSCALED Return the kerning vector in original font units. note FT_KERNING_DEFAULT returns full pixel values; it also makes FreeType heuristically scale down kerning distances at small ppem values so that they don't become too big. Both FT_KERNING_DEFAULT and FT_KERNING_UNFITTED use the current horizontal scaling factor (as set e.g. with FT_Set_Char_Size ) to convert font units to pixels. FT_Get_Track_Kerning \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Get_Track_Kerning ( FT_Face face, FT_Fixed point_size, FT_Int degree, FT_Fixed * akerning ); Return the track kerning for a given face object at a given size. input face A handle to a source face object. point_size The point size in 16.16 fractional points. degree The degree of tightness. Increasingly negative values represent tighter track kerning, while increasingly positive values represent looser track kerning. Value zero means no track kerning. output akerning The kerning in 16.16 fractional points, to be uniformly applied between all glyphs. return FreeType error code. 0 means success. note Currently, only the Type 1 font driver supports track kerning, using data from AFM files (if attached with FT_Attach_File or FT_Attach_Stream ). Only very few AFM files come with track kerning data; please refer to Adobe's AFM specification for more details. FT_Get_Glyph_Name \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Get_Glyph_Name ( FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max ); Retrieve the ASCII name of a given glyph in a face. This only works for those faces where FT_HAS_GLYPH_NAMES (face) returns 1. input face A handle to a source face object. glyph_index The glyph index. buffer_max The maximum number of bytes available in the buffer. output buffer A pointer to a target buffer where the name is copied to. return FreeType error code. 0 means success. note An error is returned if the face doesn't provide glyph names or if the glyph index is invalid. In all cases of failure, the first byte of buffer is set to 0 to indicate an empty name. The glyph name is truncated to fit within the buffer if it is too long. The returned string is always zero-terminated. Be aware that FreeType reorders glyph indices internally so that glyph index 0 always corresponds to the \u2018missing glyph\u2019 (called \u2018.notdef\u2019). This function always returns an error if the config macro FT_CONFIG_OPTION_NO_GLYPH_NAMES is not defined in ftoption.h . FT_Get_Postscript_Name \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( const char * ) FT_Get_Postscript_Name ( FT_Face face ); Retrieve the ASCII PostScript name of a given face, if available. This only works with PostScript, TrueType, and OpenType fonts. input face A handle to the source face object. return A pointer to the face's PostScript name. NULL if unavailable. note The returned pointer is owned by the face and is destroyed with it. For variation fonts, this string changes if you select a different instance, and you have to call FT_Get_PostScript_Name again to retrieve it. FreeType follows Adobe TechNote #5902, \u2018Generating PostScript Names for Fonts Using OpenType Font Variations\u2019. https://download.macromedia.com/pub/developer/opentype/tech-notes/5902.AdobePSNameGeneration.html [Since 2.9] Special PostScript names for named instances are only returned if the named instance is set with FT_Set_Named_Instance (and the font has corresponding entries in its \u2018fvar\u2019 table). If FT_IS_VARIATION returns true, the algorithmically derived PostScript name is provided, not looking up special entries for named instances. FT_CharMapRec \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_CharMapRec_ { FT_Face face; FT_Encoding encoding; FT_UShort platform_id; FT_UShort encoding_id; } FT_CharMapRec ; The base charmap structure. fields face A handle to the parent face object. encoding An FT_Encoding tag identifying the charmap. Use this with FT_Select_Charmap . platform_id An ID number describing the platform for the following encoding ID. This comes directly from the TrueType specification and gets emulated for other formats. encoding_id A platform-specific encoding number. This also comes from the TrueType specification and gets emulated similarly. FT_Select_Charmap \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Select_Charmap ( FT_Face face, FT_Encoding encoding ); Select a given charmap by its encoding tag (as listed in freetype.h ). inout face A handle to the source face object. input encoding A handle to the selected encoding. return FreeType error code. 0 means success. note This function returns an error if no charmap in the face corresponds to the encoding queried here. Because many fonts contain more than a single cmap for Unicode encoding, this function has some special code to select the one that covers Unicode best (\u2018best\u2019 in the sense that a UCS-4 cmap is preferred to a UCS-2 cmap). It is thus preferable to FT_Set_Charmap in this case. FT_Set_Charmap \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Set_Charmap ( FT_Face face, FT_CharMap charmap ); Select a given charmap for character code to glyph index mapping. inout face A handle to the source face object. input charmap A handle to the selected charmap. return FreeType error code. 0 means success. note This function returns an error if the charmap is not part of the face (i.e., if it is not listed in the face->charmaps table). It also fails if an OpenType type 14 charmap is selected (which doesn't map character codes to glyph indices at all). FT_Get_Charmap_Index \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Int ) FT_Get_Charmap_Index ( FT_CharMap charmap ); Retrieve index of a given charmap. input charmap A handle to a charmap. return The index into the array of character maps within the face to which charmap belongs. If an error occurs, -1 is returned. FT_Get_FSType_Flags \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_UShort ) FT_Get_FSType_Flags ( FT_Face face ); Return the fsType flags for a font. input face A handle to the source face object. return The fsType flags, see FT_FSTYPE_XXX . note Use this function rather than directly reading the fs_type field in the PS_FontInfoRec structure, which is only guaranteed to return the correct results for Type 1 fonts. since 2.3.8 FT_Get_SubGlyph_Info \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Get_SubGlyph_Info ( FT_GlyphSlot glyph, FT_UInt sub_index, FT_Int *p_index, FT_UInt *p_flags, FT_Int *p_arg1, FT_Int *p_arg2, FT_Matrix *p_transform ); Retrieve a description of a given subglyph. Only use it if glyph->format is FT_GLYPH_FORMAT_COMPOSITE ; an error is returned otherwise. input glyph The source glyph slot. sub_index The index of the subglyph. Must be less than glyph->num_subglyphs . output p_index The glyph index of the subglyph. p_flags The subglyph flags, see FT_SUBGLYPH_FLAG_XXX . p_arg1 The subglyph's first argument (if any). p_arg2 The subglyph's second argument (if any). p_transform The subglyph transformation (if any). return FreeType error code. 0 means success. note The values of *p_arg1 , *p_arg2 , and *p_transform must be interpreted depending on the flags returned in *p_flags . See the OpenType specification for details. https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#composite-glyph-description FT_Face_Internal \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Face_InternalRec_* FT_Face_Internal ; An opaque handle to an FT_Face_InternalRec structure that models the private data of a given FT_Face object. This structure might change between releases of FreeType 2 and is not generally available to client applications. FT_Size_Internal \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Size_InternalRec_* FT_Size_Internal ; An opaque handle to an FT_Size_InternalRec structure, used to model private data of a given FT_Size object. FT_Slot_Internal \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Slot_InternalRec_* FT_Slot_Internal ; An opaque handle to an FT_Slot_InternalRec structure, used to model private data of a given FT_GlyphSlot object. FT_FACE_FLAG_XXX \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_FACE_FLAG_SCALABLE ( 1L << 0 ) # define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 ) # define FT_FACE_FLAG_FIXED_WIDTH ( 1L << 2 ) # define FT_FACE_FLAG_SFNT ( 1L << 3 ) # define FT_FACE_FLAG_HORIZONTAL ( 1L << 4 ) # define FT_FACE_FLAG_VERTICAL ( 1L << 5 ) # define FT_FACE_FLAG_KERNING ( 1L << 6 ) # define FT_FACE_FLAG_FAST_GLYPHS ( 1L << 7 ) # define FT_FACE_FLAG_MULTIPLE_MASTERS ( 1L << 8 ) # define FT_FACE_FLAG_GLYPH_NAMES ( 1L << 9 ) # define FT_FACE_FLAG_EXTERNAL_STREAM ( 1L << 10 ) # define FT_FACE_FLAG_HINTER ( 1L << 11 ) # define FT_FACE_FLAG_CID_KEYED ( 1L << 12 ) # define FT_FACE_FLAG_TRICKY ( 1L << 13 ) # define FT_FACE_FLAG_COLOR ( 1L << 14 ) # define FT_FACE_FLAG_VARIATION ( 1L << 15 ) A list of bit flags used in the face_flags field of the FT_FaceRec structure. They inform client applications of properties of the corresponding face. values FT_FACE_FLAG_SCALABLE The face contains outline glyphs. Note that a face can contain bitmap strikes also, i.e., a face can have both this flag and FT_FACE_FLAG_FIXED_SIZES set. FT_FACE_FLAG_FIXED_SIZES The face contains bitmap strikes. See also the num_fixed_sizes and available_sizes fields of FT_FaceRec . FT_FACE_FLAG_FIXED_WIDTH The face contains fixed-width characters (like Courier, Lucida, MonoType, etc.). FT_FACE_FLAG_SFNT The face uses the SFNT storage scheme. For now, this means TrueType and OpenType. FT_FACE_FLAG_HORIZONTAL The face contains horizontal glyph metrics. This should be set for all common formats. FT_FACE_FLAG_VERTICAL The face contains vertical glyph metrics. This is only available in some formats, not all of them. FT_FACE_FLAG_KERNING The face contains kerning information. If set, the kerning distance can be retrieved using the function FT_Get_Kerning . Otherwise the function always return the vector (0,0). Note that FreeType doesn't handle kerning data from the SFNT \u2018GPOS\u2019 table (as present in many OpenType fonts). FT_FACE_FLAG_FAST_GLYPHS THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT. FT_FACE_FLAG_MULTIPLE_MASTERS The face contains multiple masters and is capable of interpolating between them. Supported formats are Adobe MM, TrueType GX, and OpenType variation fonts. See section \u2018 Multiple Masters \u2019 for API details. FT_FACE_FLAG_GLYPH_NAMES The face contains glyph names, which can be retrieved using FT_Get_Glyph_Name . Note that some TrueType fonts contain broken glyph name tables. Use the function FT_Has_PS_Glyph_Names when needed. FT_FACE_FLAG_EXTERNAL_STREAM Used internally by FreeType to indicate that a face's stream was provided by the client application and should not be destroyed when FT_Done_Face is called. Don't read or test this flag. FT_FACE_FLAG_HINTER The font driver has a hinting machine of its own. For example, with TrueType fonts, it makes sense to use data from the SFNT \u2018gasp\u2019 table only if the native TrueType hinting engine (with the bytecode interpreter) is available and active. FT_FACE_FLAG_CID_KEYED The face is CID-keyed. In that case, the face is not accessed by glyph indices but by CID values. For subsetted CID-keyed fonts this has the consequence that not all index values are a valid argument to FT_Load_Glyph . Only the CID values for which corresponding glyphs in the subsetted font exist make FT_Load_Glyph return successfully; in all other cases you get an FT_Err_Invalid_Argument error. Note that CID-keyed fonts that are in an SFNT wrapper (this is, all OpenType/CFF fonts) don't have this flag set since the glyphs are accessed in the normal way (using contiguous indices); the \u2018CID-ness\u2019 isn't visible to the application. FT_FACE_FLAG_TRICKY The face is \u2018tricky\u2019, this is, it always needs the font format's native hinting engine to get a reasonable result. A typical example is the old Chinese font mingli.ttf (but not mingliu.ttc ) that uses TrueType bytecode instructions to move and scale all of its subglyphs. It is not possible to auto-hint such fonts using FT_LOAD_FORCE_AUTOHINT ; it will also ignore FT_LOAD_NO_HINTING . You have to set both FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT to really disable hinting; however, you probably never want this except for demonstration purposes. Currently, there are about a dozen TrueType fonts in the list of tricky fonts; they are hard-coded in file ttobjs.c . FT_FACE_FLAG_COLOR [Since 2.5.1] The face has color glyph tables. See FT_LOAD_COLOR for more information. FT_FACE_FLAG_VARIATION [Since 2.9] Set if the current face (or named instance) has been altered with FT_Set_MM_Design_Coordinates , FT_Set_Var_Design_Coordinates , or FT_Set_Var_Blend_Coordinates . This flag is unset by a call to FT_Set_Named_Instance . FT_STYLE_FLAG_XXX \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_STYLE_FLAG_ITALIC ( 1 << 0 ) # define FT_STYLE_FLAG_BOLD ( 1 << 1 ) A list of bit flags to indicate the style of a given face. These are used in the style_flags field of FT_FaceRec . values FT_STYLE_FLAG_ITALIC The face style is italic or oblique. FT_STYLE_FLAG_BOLD The face is bold. note The style information as provided by FreeType is very basic. More details are beyond the scope and should be done on a higher level (for example, by analyzing various fields of the \u2018OS/2\u2019 table in SFNT based fonts). FT_OPEN_XXX \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_OPEN_MEMORY 0x1 # define FT_OPEN_STREAM 0x2 # define FT_OPEN_PATHNAME 0x4 # define FT_OPEN_DRIVER 0x8 # define FT_OPEN_PARAMS 0x10 /* these constants are deprecated; use the corresponding ` FT_OPEN_XXX ` */ /* values instead */ # define ft_open_memory FT_OPEN_MEMORY # define ft_open_stream FT_OPEN_STREAM # define ft_open_pathname FT_OPEN_PATHNAME # define ft_open_driver FT_OPEN_DRIVER # define ft_open_params FT_OPEN_PARAMS A list of bit field constants used within the flags field of the FT_Open_Args structure. values FT_OPEN_MEMORY This is a memory-based stream. FT_OPEN_STREAM Copy the stream from the stream field. FT_OPEN_PATHNAME Create a new input stream from a C path name. FT_OPEN_DRIVER Use the driver field. FT_OPEN_PARAMS Use the num_params and params fields. note The FT_OPEN_MEMORY , FT_OPEN_STREAM , and FT_OPEN_PATHNAME flags are mutually exclusive. FT_LOAD_XXX \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_LOAD_DEFAULT 0x0 # define FT_LOAD_NO_SCALE ( 1L << 0 ) # define FT_LOAD_NO_HINTING ( 1L << 1 ) # define FT_LOAD_RENDER ( 1L << 2 ) # define FT_LOAD_NO_BITMAP ( 1L << 3 ) # define FT_LOAD_VERTICAL_LAYOUT ( 1L << 4 ) # define FT_LOAD_FORCE_AUTOHINT ( 1L << 5 ) # define FT_LOAD_CROP_BITMAP ( 1L << 6 ) # define FT_LOAD_PEDANTIC ( 1L << 7 ) # define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ( 1L << 9 ) # define FT_LOAD_NO_RECURSE ( 1L << 10 ) # define FT_LOAD_IGNORE_TRANSFORM ( 1L << 11 ) # define FT_LOAD_MONOCHROME ( 1L << 12 ) # define FT_LOAD_LINEAR_DESIGN ( 1L << 13 ) # define FT_LOAD_NO_AUTOHINT ( 1L << 15 ) /* Bits 16-19 are used by `FT_LOAD_TARGET_` */ # define FT_LOAD_COLOR ( 1L << 20 ) # define FT_LOAD_COMPUTE_METRICS ( 1L << 21 ) # define FT_LOAD_BITMAP_METRICS_ONLY ( 1L << 22 ) A list of bit field constants for FT_Load_Glyph to indicate what kind of operations to perform during glyph loading. values FT_LOAD_DEFAULT Corresponding to 0, this value is used as the default glyph load operation. In this case, the following happens: FreeType looks for a bitmap for the glyph corresponding to the face's current size. If one is found, the function returns. The bitmap data can be accessed from the glyph slot (see note below). If no embedded bitmap is searched for or found, FreeType looks for a scalable outline. If one is found, it is loaded from the font file, scaled to device pixels, then \u2018hinted\u2019 to the pixel grid in order to optimize it. The outline data can be accessed from the glyph slot (see note below). Note that by default the glyph loader doesn't render outlines into bitmaps. The following flags are used to modify this default behaviour to more specific and useful cases. FT_LOAD_NO_SCALE Don't scale the loaded outline glyph but keep it in font units. This flag implies FT_LOAD_NO_HINTING and FT_LOAD_NO_BITMAP , and unsets FT_LOAD_RENDER . If the font is \u2018tricky\u2019 (see FT_FACE_FLAG_TRICKY for more), using FT_LOAD_NO_SCALE usually yields meaningless outlines because the subglyphs must be scaled and positioned with hinting instructions. This can be solved by loading the font without FT_LOAD_NO_SCALE and setting the character size to font->units_per_EM . FT_LOAD_NO_HINTING Disable hinting. This generally generates \u2018blurrier\u2019 bitmap glyphs when the glyph are rendered in any of the anti-aliased modes. See also the note below. This flag is implied by FT_LOAD_NO_SCALE . FT_LOAD_RENDER Call FT_Render_Glyph after the glyph is loaded. By default, the glyph is rendered in FT_RENDER_MODE_NORMAL mode. This can be overridden by FT_LOAD_TARGET_XXX or FT_LOAD_MONOCHROME . This flag is unset by FT_LOAD_NO_SCALE . FT_LOAD_NO_BITMAP Ignore bitmap strikes when loading. Bitmap-only fonts ignore this flag. FT_LOAD_NO_SCALE always sets this flag. FT_LOAD_VERTICAL_LAYOUT Load the glyph for vertical text layout. In particular, the advance value in the FT_GlyphSlotRec structure is set to the vertAdvance value of the metrics field. In case FT_HAS_VERTICAL doesn't return true, you shouldn't use this flag currently. Reason is that in this case vertical metrics get synthesized, and those values are not always consistent across various font formats. FT_LOAD_FORCE_AUTOHINT Prefer the auto-hinter over the font's native hinter. See also the note below. FT_LOAD_PEDANTIC Make the font driver perform pedantic verifications during glyph loading and hinting. This is mostly used to detect broken glyphs in fonts. By default, FreeType tries to handle broken fonts also. In particular, errors from the TrueType bytecode engine are not passed to the application if this flag is not set; this might result in partially hinted or distorted glyphs in case a glyph's bytecode is buggy. FT_LOAD_NO_RECURSE Don't load composite glyphs recursively. Instead, the font driver fills the num_subglyph and subglyphs values of the glyph slot; it also sets glyph->format to FT_GLYPH_FORMAT_COMPOSITE . The description of subglyphs can then be accessed with FT_Get_SubGlyph_Info . Don't use this flag for retrieving metrics information since some font drivers only return rudimentary data. This flag implies FT_LOAD_NO_SCALE and FT_LOAD_IGNORE_TRANSFORM . FT_LOAD_IGNORE_TRANSFORM Ignore the transform matrix set by FT_Set_Transform . FT_LOAD_MONOCHROME This flag is used with FT_LOAD_RENDER to indicate that you want to render an outline glyph to a 1-bit monochrome bitmap glyph, with 8 pixels packed into each byte of the bitmap data. Note that this has no effect on the hinting algorithm used. You should rather use FT_LOAD_TARGET_MONO so that the monochrome-optimized hinting algorithm is used. FT_LOAD_LINEAR_DESIGN Keep linearHoriAdvance and linearVertAdvance fields of FT_GlyphSlotRec in font units. See FT_GlyphSlotRec for details. FT_LOAD_NO_AUTOHINT Disable the auto-hinter. See also the note below. FT_LOAD_COLOR Load colored glyphs. There are slight differences depending on the font format. [Since 2.5] Load embedded color bitmap images. The resulting color bitmaps, if available, will have the FT_PIXEL_MODE_BGRA format, with pre-multiplied color channels. If the flag is not set and color bitmaps are found, they are converted to 256-level gray bitmaps, using the FT_PIXEL_MODE_GRAY format. [Since 2.10, experimental] If the glyph index contains an entry in the face's \u2018COLR\u2019 table with a \u2018CPAL\u2019 palette table (as defined in the OpenType specification), make FT_Render_Glyph provide a default blending of the color glyph layers associated with the glyph index, using the same bitmap format as embedded color bitmap images. This is mainly for convenience; for full control of color layers use FT_Get_Color_Glyph_Layer and FreeType's color functions like FT_Palette_Select instead of setting FT_LOAD_COLOR for rendering so that the client application can handle blending by itself. FT_LOAD_COMPUTE_METRICS [Since 2.6.1] Compute glyph metrics from the glyph data, without the use of bundled metrics tables (for example, the \u2018hdmx\u2019 table in TrueType fonts). This flag is mainly used by font validating or font editing applications, which need to ignore, verify, or edit those tables. Currently, this flag is only implemented for TrueType fonts. FT_LOAD_BITMAP_METRICS_ONLY [Since 2.7.1] Request loading of the metrics and bitmap image information of a (possibly embedded) bitmap glyph without allocating or copying the bitmap image data itself. No effect if the target glyph is not a bitmap image. This flag unsets FT_LOAD_RENDER . FT_LOAD_CROP_BITMAP Ignored. Deprecated. FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH Ignored. Deprecated. note By default, hinting is enabled and the font's native hinter (see FT_FACE_FLAG_HINTER ) is preferred over the auto-hinter. You can disable hinting by setting FT_LOAD_NO_HINTING or change the precedence by setting FT_LOAD_FORCE_AUTOHINT . You can also set FT_LOAD_NO_AUTOHINT in case you don't want the auto-hinter to be used at all. See the description of FT_FACE_FLAG_TRICKY for a special exception (affecting only a handful of Asian fonts). Besides deciding which hinter to use, you can also decide which hinting algorithm to use. See FT_LOAD_TARGET_XXX for details. Note that the auto-hinter needs a valid Unicode cmap (either a native one or synthesized by FreeType) for producing correct results. If a font provides an incorrect mapping (for example, assigning the character code U+005A, LATIN CAPITAL LETTER Z, to a glyph depicting a mathematical integral sign), the auto-hinter might produce useless results. FT_LOAD_TARGET_XXX \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_LOAD_TARGET_( x ) ( ( FT_Int32 )( (x) & 15 ) << 16 ) # define FT_LOAD_TARGET_NORMAL FT_LOAD_TARGET_( FT_RENDER_MODE_NORMAL ) # define FT_LOAD_TARGET_LIGHT FT_LOAD_TARGET_( FT_RENDER_MODE_LIGHT ) # define FT_LOAD_TARGET_MONO FT_LOAD_TARGET_( FT_RENDER_MODE_MONO ) # define FT_LOAD_TARGET_LCD FT_LOAD_TARGET_( FT_RENDER_MODE_LCD ) # define FT_LOAD_TARGET_LCD_V FT_LOAD_TARGET_( FT_RENDER_MODE_LCD_V ) A list of values to select a specific hinting algorithm for the hinter. You should OR one of these values to your load_flags when calling FT_Load_Glyph . Note that a font's native hinters may ignore the hinting algorithm you have specified (e.g., the TrueType bytecode interpreter). You can set FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used. values FT_LOAD_TARGET_NORMAL The default hinting algorithm, optimized for standard gray-level rendering. For monochrome output, use FT_LOAD_TARGET_MONO instead. FT_LOAD_TARGET_LIGHT A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by FreeType's new CFF engine or Microsoft's ClearType font renderer. This preserves inter-glyph spacing in horizontal text. The snapping is done either by the native font driver, if the driver itself and the font support it, or by the auto-hinter. Advance widths are rounded to integer values; however, using the lsb_delta and rsb_delta fields of FT_GlyphSlotRec , it is possible to get fractional advance widths for subpixel positioning (which is recommended to use). If configuration option AF_CONFIG_OPTION_TT_SIZE_METRICS is active, TrueType-like metrics are used to make this mode behave similarly as in unpatched FreeType versions between 2.4.6 and 2.7.1 (inclusive). FT_LOAD_TARGET_MONO Strong hinting algorithm that should only be used for monochrome output. The result is probably unpleasant if the glyph is rendered in non-monochrome modes. Note that for outline fonts only the TrueType font driver has proper monochrome hinting support, provided the TTFs contain hints for B/W rendering (which most fonts no longer provide). If these conditions are not met it is very likely that you get ugly results at smaller sizes. FT_LOAD_TARGET_LCD A variant of FT_LOAD_TARGET_LIGHT optimized for horizontally decimated LCD displays. FT_LOAD_TARGET_LCD_V A variant of FT_LOAD_TARGET_NORMAL optimized for vertically decimated LCD displays. note You should use only one of the FT_LOAD_TARGET_XXX values in your load_flags . They can't be ORed. If FT_LOAD_RENDER is also set, the glyph is rendered in the corresponding mode (i.e., the mode that matches the used algorithm best). An exception is FT_LOAD_TARGET_MONO since it implies FT_LOAD_MONOCHROME . You can use a hinting algorithm that doesn't correspond to the same rendering mode. As an example, it is possible to use the \u2018light\u2019 hinting algorithm and have the results rendered in horizontal LCD pixel mode, with code like FT_Load_Glyph( face, glyph_index, load_flags | FT_LOAD_TARGET_LIGHT ); FT_Render_Glyph( face->glyph, FT_RENDER_MODE_LCD ); In general, you should stick with one rendering mode. For example, switching between FT_LOAD_TARGET_NORMAL and FT_LOAD_TARGET_MONO enforces a lot of recomputation for TrueType fonts, which is slow. Another reason is caching: Selecting a different mode usually causes changes in both the outlines and the rasterized bitmaps; it is thus necessary to empty the cache after a mode switch to avoid false hits. FT_SUBGLYPH_FLAG_XXX \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1 # define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2 # define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4 # define FT_SUBGLYPH_FLAG_SCALE 8 # define FT_SUBGLYPH_FLAG_XY_SCALE 0x40 # define FT_SUBGLYPH_FLAG_2X2 0x80 # define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200 A list of constants describing subglyphs. Please refer to the \u2018glyf\u2019 table description in the OpenType specification for the meaning of the various flags (which get synthesized for non-OpenType subglyphs). https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#composite-glyph-description values FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID FT_SUBGLYPH_FLAG_SCALE FT_SUBGLYPH_FLAG_XY_SCALE FT_SUBGLYPH_FLAG_2X2 FT_SUBGLYPH_FLAG_USE_MY_METRICS FT_FSTYPE_XXX \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_FSTYPE_INSTALLABLE_EMBEDDING 0x0000 # define FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING 0x0002 # define FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING 0x0004 # define FT_FSTYPE_EDITABLE_EMBEDDING 0x0008 # define FT_FSTYPE_NO_SUBSETTING 0x0100 # define FT_FSTYPE_BITMAP_EMBEDDING_ONLY 0x0200 A list of bit flags used in the fsType field of the OS/2 table in a TrueType or OpenType font and the FSType entry in a PostScript font. These bit flags are returned by FT_Get_FSType_Flags ; they inform client applications of embedding and subsetting restrictions associated with a font. See https://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/FontPolicies.pdf for more details. values FT_FSTYPE_INSTALLABLE_EMBEDDING Fonts with no fsType bit set may be embedded and permanently installed on the remote system by an application. FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING Fonts that have only this bit set must not be modified, embedded or exchanged in any manner without first obtaining permission of the font software copyright owner. FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING The font may be embedded and temporarily loaded on the remote system. Documents containing Preview & Print fonts must be opened \u2018read-only\u2019; no edits can be applied to the document. FT_FSTYPE_EDITABLE_EMBEDDING The font may be embedded but must only be installed temporarily on other systems. In contrast to Preview & Print fonts, documents containing editable fonts may be opened for reading, editing is permitted, and changes may be saved. FT_FSTYPE_NO_SUBSETTING The font may not be subsetted prior to embedding. FT_FSTYPE_BITMAP_EMBEDDING_ONLY Only bitmaps contained in the font may be embedded; no outline data may be embedded. If there are no bitmaps available in the font, then the font is unembeddable. note The flags are ORed together, thus more than a single value can be returned. While the fsType flags can indicate that a font may be embedded, a license with the font vendor may be separately required to use the font in this way. FT_HAS_FAST_GLYPHS \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_FAST_GLYPHS ( face ) 0 Deprecated.","title":"Base Interface"},{"location":"ft2-base_interface.html#base-interface","text":"","title":"Base Interface"},{"location":"ft2-base_interface.html#synopsis","text":"This section describes the most important public high-level API functions of FreeType 2.","title":"Synopsis"},{"location":"ft2-base_interface.html#ft_library","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_LibraryRec_ * FT_Library ; A handle to a FreeType library instance. Each \u2018library\u2019 is completely independent from the others; it is the \u2018root\u2019 of a set of objects like fonts, faces, sizes, etc. It also embeds a memory manager (see FT_Memory ), as well as a scan-line converter object (see FT_Raster ). [Since 2.5.6] In multi-threaded applications it is easiest to use one FT_Library object per thread. In case this is too cumbersome, a single FT_Library object across threads is possible also, as long as a mutex lock is used around FT_New_Face and FT_Done_Face .","title":"FT_Library"},{"location":"ft2-base_interface.html#ft_face","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_FaceRec_* FT_Face ; A handle to a typographic face object. A face object models a given typeface, in a given style.","title":"FT_Face"},{"location":"ft2-base_interface.html#ft_size","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_SizeRec_* FT_Size ; A handle to an object that models a face scaled to a given character size.","title":"FT_Size"},{"location":"ft2-base_interface.html#ft_glyphslot","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_GlyphSlotRec_* FT_GlyphSlot ; A handle to a given \u2018glyph slot\u2019. A slot is a container that can hold any of the glyphs contained in its parent face. In other words, each time you call FT_Load_Glyph or FT_Load_Char , the slot's content is erased by the new glyph data, i.e., the glyph's metrics, its image (bitmap or outline), and other control information.","title":"FT_GlyphSlot"},{"location":"ft2-base_interface.html#ft_charmap","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_CharMapRec_* FT_CharMap ; A handle to a character map (usually abbreviated to \u2018charmap\u2019). A charmap is used to translate character codes in a given encoding into glyph indexes for its parent's face. Some font formats may provide several charmaps per font. Each face object owns zero or more charmaps, but only one of them can be \u2018active\u2019, providing the data used by FT_Get_Char_Index or FT_Load_Char . The list of available charmaps in a face is available through the face->num_charmaps and face->charmaps fields of FT_FaceRec . The currently active charmap is available as face->charmap . You should call FT_Set_Charmap to change it.","title":"FT_CharMap"},{"location":"ft2-base_interface.html#ft_encoding","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef enum FT_Encoding_ { FT_ENC_TAG ( FT_ENCODING_NONE , 0, 0, 0, 0 ), FT_ENC_TAG ( FT_ENCODING_MS_SYMBOL , 's', 'y', 'm', 'b' ), FT_ENC_TAG ( FT_ENCODING_UNICODE , 'u', 'n', 'i', 'c' ), FT_ENC_TAG ( FT_ENCODING_SJIS , 's', 'j', 'i', 's' ), FT_ENC_TAG ( FT_ENCODING_PRC , 'g', 'b', ' ', ' ' ), FT_ENC_TAG ( FT_ENCODING_BIG5 , 'b', 'i', 'g', '5' ), FT_ENC_TAG ( FT_ENCODING_WANSUNG , 'w', 'a', 'n', 's' ), FT_ENC_TAG ( FT_ENCODING_JOHAB , 'j', 'o', 'h', 'a' ), /* for backward compatibility */ FT_ENCODING_GB2312 = FT_ENCODING_PRC , FT_ENCODING_MS_SJIS = FT_ENCODING_SJIS , FT_ENCODING_MS_GB2312 = FT_ENCODING_PRC , FT_ENCODING_MS_BIG5 = FT_ENCODING_BIG5 , FT_ENCODING_MS_WANSUNG = FT_ENCODING_WANSUNG , FT_ENCODING_MS_JOHAB = FT_ENCODING_JOHAB , FT_ENC_TAG ( FT_ENCODING_ADOBE_STANDARD , 'A', 'D', 'O', 'B' ), FT_ENC_TAG ( FT_ENCODING_ADOBE_EXPERT , 'A', 'D', 'B', 'E' ), FT_ENC_TAG ( FT_ENCODING_ADOBE_CUSTOM , 'A', 'D', 'B', 'C' ), FT_ENC_TAG ( FT_ENCODING_ADOBE_LATIN_1 , 'l', 'a', 't', '1' ), FT_ENC_TAG ( FT_ENCODING_OLD_LATIN_2 , 'l', 'a', 't', '2' ), FT_ENC_TAG ( FT_ENCODING_APPLE_ROMAN , 'a', 'r', 'm', 'n' ) } FT_Encoding ; /* these constants are deprecated; use the corresponding ` FT_Encoding ` */ /* values instead */ # define ft_encoding_none FT_ENCODING_NONE # define ft_encoding_unicode FT_ENCODING_UNICODE # define ft_encoding_symbol FT_ENCODING_MS_SYMBOL # define ft_encoding_latin_1 FT_ENCODING_ADOBE_LATIN_1 # define ft_encoding_latin_2 FT_ENCODING_OLD_LATIN_2 # define ft_encoding_sjis FT_ENCODING_SJIS # define ft_encoding_gb2312 FT_ENCODING_PRC # define ft_encoding_big5 FT_ENCODING_BIG5 # define ft_encoding_wansung FT_ENCODING_WANSUNG # define ft_encoding_johab FT_ENCODING_JOHAB # define ft_encoding_adobe_standard FT_ENCODING_ADOBE_STANDARD # define ft_encoding_adobe_expert FT_ENCODING_ADOBE_EXPERT # define ft_encoding_adobe_custom FT_ENCODING_ADOBE_CUSTOM # define ft_encoding_apple_roman FT_ENCODING_APPLE_ROMAN An enumeration to specify character sets supported by charmaps. Used in the FT_Select_Charmap API function.","title":"FT_Encoding"},{"location":"ft2-base_interface.html#ft_enc_tag","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # ifndef FT_ENC_TAG # define FT_ENC_TAG ( value, a, b, c, d ) \\ value = ( ( ( FT_UInt32 )(a) << 24 ) | \\ ( ( FT_UInt32 )(b) << 16 ) | \\ ( ( FT_UInt32 )(c) << 8 ) | \\ ( FT_UInt32 )(d) ) # endif /* FT_ENC_TAG */ This macro converts four-letter tags into an unsigned long. It is used to define \u2018encoding\u2019 identifiers (see FT_Encoding ).","title":"FT_ENC_TAG"},{"location":"ft2-base_interface.html#ft_facerec","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_FaceRec_ { FT_Long num_faces; FT_Long face_index; FT_Long face_flags; FT_Long style_flags; FT_Long num_glyphs; FT_String * family_name; FT_String * style_name; FT_Int num_fixed_sizes; FT_Bitmap_Size * available_sizes; FT_Int num_charmaps; FT_CharMap * charmaps; FT_Generic generic; /*# The following member variables (down to `underline_thickness`) */ /*# are only relevant to scalable outlines; cf. @ FT_Bitmap_Size */ /*# for bitmap fonts. */ FT_BBox bbox; FT_UShort units_per_EM; FT_Short ascender; FT_Short descender; FT_Short height; FT_Short max_advance_width; FT_Short max_advance_height; FT_Short underline_position; FT_Short underline_thickness; FT_GlyphSlot glyph; FT_Size size; FT_CharMap charmap; /*@private begin */ FT_Driver driver; FT_Memory memory; FT_Stream stream; FT_ListRec sizes_list; FT_Generic autohint; /* face-specific auto-hinter data */ void * extensions; /* unused */ FT_Face_Internal internal; /*@private end */ } FT_FaceRec ; FreeType root face class structure. A face object models a typeface in a font file.","title":"FT_FaceRec"},{"location":"ft2-base_interface.html#ft_has_horizontal","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_HORIZONTAL ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_HORIZONTAL ) ) A macro that returns true whenever a face object contains horizontal metrics (this is true for all font formats though).","title":"FT_HAS_HORIZONTAL"},{"location":"ft2-base_interface.html#ft_has_vertical","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_VERTICAL ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_VERTICAL ) ) A macro that returns true whenever a face object contains real vertical metrics (and not only synthesized ones).","title":"FT_HAS_VERTICAL"},{"location":"ft2-base_interface.html#ft_has_kerning","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_KERNING ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_KERNING ) ) A macro that returns true whenever a face object contains kerning data that can be accessed with FT_Get_Kerning .","title":"FT_HAS_KERNING"},{"location":"ft2-base_interface.html#ft_has_fixed_sizes","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_FIXED_SIZES ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_FIXED_SIZES ) ) A macro that returns true whenever a face object contains some embedded bitmaps. See the available_sizes field of the FT_FaceRec structure.","title":"FT_HAS_FIXED_SIZES"},{"location":"ft2-base_interface.html#ft_has_glyph_names","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_GLYPH_NAMES ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) ) A macro that returns true whenever a face object contains some glyph names that can be accessed through FT_Get_Glyph_Name .","title":"FT_HAS_GLYPH_NAMES"},{"location":"ft2-base_interface.html#ft_has_color","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_COLOR ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_COLOR ) ) A macro that returns true whenever a face object contains tables for color glyphs.","title":"FT_HAS_COLOR"},{"location":"ft2-base_interface.html#ft_has_multiple_masters","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_MULTIPLE_MASTERS ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) ) A macro that returns true whenever a face object contains some multiple masters. The functions provided by FT_MULTIPLE_MASTERS_H are then available to choose the exact design you want.","title":"FT_HAS_MULTIPLE_MASTERS"},{"location":"ft2-base_interface.html#ft_is_sfnt","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_IS_SFNT ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_SFNT ) ) A macro that returns true whenever a face object contains a font whose format is based on the SFNT storage scheme. This usually means: TrueType fonts, OpenType fonts, as well as SFNT-based embedded bitmap fonts. If this macro is true, all functions defined in FT_SFNT_NAMES_H and FT_TRUETYPE_TABLES_H are available.","title":"FT_IS_SFNT"},{"location":"ft2-base_interface.html#ft_is_scalable","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_IS_SCALABLE ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_SCALABLE ) ) A macro that returns true whenever a face object contains a scalable font face (true for TrueType, Type 1, Type 42, CID, OpenType/CFF, and PFR font formats).","title":"FT_IS_SCALABLE"},{"location":"ft2-base_interface.html#ft_is_fixed_width","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_IS_FIXED_WIDTH ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_FIXED_WIDTH ) ) A macro that returns true whenever a face object contains a font face that contains fixed-width (or \u2018monospace\u2019, \u2018fixed-pitch\u2019, etc.) glyphs.","title":"FT_IS_FIXED_WIDTH"},{"location":"ft2-base_interface.html#ft_is_cid_keyed","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_IS_CID_KEYED ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_CID_KEYED ) ) A macro that returns true whenever a face object contains a CID-keyed font. See the discussion of FT_FACE_FLAG_CID_KEYED for more details. If this macro is true, all functions defined in FT_CID_H are available.","title":"FT_IS_CID_KEYED"},{"location":"ft2-base_interface.html#ft_is_tricky","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_IS_TRICKY ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_TRICKY ) ) A macro that returns true whenever a face represents a \u2018tricky\u2019 font. See the discussion of FT_FACE_FLAG_TRICKY for more details.","title":"FT_IS_TRICKY"},{"location":"ft2-base_interface.html#ft_is_named_instance","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_IS_NAMED_INSTANCE ( face ) \\ ( !!( (face)->face_index & 0x7FFF0000L ) ) A macro that returns true whenever a face object is a named instance of a GX or OpenType variation font. [Since 2.9] Changing the design coordinates with FT_Set_Var_Design_Coordinates or FT_Set_Var_Blend_Coordinates does not influence the return value of this macro (only FT_Set_Named_Instance does that).","title":"FT_IS_NAMED_INSTANCE"},{"location":"ft2-base_interface.html#ft_is_variation","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_IS_VARIATION ( face ) \\ ( !!( (face)->face_flags & FT_FACE_FLAG_VARIATION ) ) A macro that returns true whenever a face object has been altered by FT_Set_MM_Design_Coordinates , FT_Set_Var_Design_Coordinates , or FT_Set_Var_Blend_Coordinates .","title":"FT_IS_VARIATION"},{"location":"ft2-base_interface.html#ft_sizerec","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_SizeRec_ { FT_Face face; /* parent face object */ FT_Generic generic; /* generic pointer for client uses */ FT_Size_Metrics metrics; /* size metrics */ FT_Size_Internal internal; } FT_SizeRec ; FreeType root size class structure. A size object models a face object at a given size.","title":"FT_SizeRec"},{"location":"ft2-base_interface.html#ft_size_metrics","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Size_Metrics_ { FT_UShort x_ppem; /* horizontal pixels per EM */ FT_UShort y_ppem; /* vertical pixels per EM */ FT_Fixed x_scale; /* scaling values used to convert font */ FT_Fixed y_scale; /* units to 26.6 fractional pixels */ FT_Pos ascender; /* ascender in 26.6 frac. pixels */ FT_Pos descender; /* descender in 26.6 frac. pixels */ FT_Pos height; /* text height in 26.6 frac. pixels */ FT_Pos max_advance; /* max horizontal advance, in 26.6 pixels */ } FT_Size_Metrics ; The size metrics structure gives the metrics of a size object.","title":"FT_Size_Metrics"},{"location":"ft2-base_interface.html#ft_glyphslotrec","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_GlyphSlotRec_ { FT_Library library; FT_Face face; FT_GlyphSlot next; FT_UInt glyph_index; /* new in 2.10; was reserved previously */ FT_Generic generic; FT_Glyph_Metrics metrics; FT_Fixed linearHoriAdvance; FT_Fixed linearVertAdvance; FT_Vector advance; FT_Glyph_Format format; FT_Bitmap bitmap; FT_Int bitmap_left; FT_Int bitmap_top; FT_Outline outline; FT_UInt num_subglyphs; FT_SubGlyph subglyphs; void * control_data; long control_len; FT_Pos lsb_delta; FT_Pos rsb_delta; void * other; FT_Slot_Internal internal; } FT_GlyphSlotRec ; FreeType root glyph slot class structure. A glyph slot is a container where individual glyphs can be loaded, be they in outline or bitmap format.","title":"FT_GlyphSlotRec"},{"location":"ft2-base_interface.html#ft_glyph_metrics","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Glyph_Metrics_ { FT_Pos width; FT_Pos height; FT_Pos horiBearingX; FT_Pos horiBearingY; FT_Pos horiAdvance; FT_Pos vertBearingX; FT_Pos vertBearingY; FT_Pos vertAdvance; } FT_Glyph_Metrics ; A structure to model the metrics of a single glyph. The values are expressed in 26.6 fractional pixel format; if the flag FT_LOAD_NO_SCALE has been used while loading the glyph, values are expressed in font units instead.","title":"FT_Glyph_Metrics"},{"location":"ft2-base_interface.html#ft_subglyph","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_SubGlyphRec_* FT_SubGlyph ; The subglyph structure is an internal object used to describe subglyphs (for example, in the case of composites).","title":"FT_SubGlyph"},{"location":"ft2-base_interface.html#ft_bitmap_size","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Bitmap_Size_ { FT_Short height; FT_Short width; FT_Pos size; FT_Pos x_ppem; FT_Pos y_ppem; } FT_Bitmap_Size ; This structure models the metrics of a bitmap strike (i.e., a set of glyphs for a given point size and resolution) in a bitmap font. It is used for the available_sizes field of FT_Face .","title":"FT_Bitmap_Size"},{"location":"ft2-base_interface.html#ft_init_freetype","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Init_FreeType ( FT_Library *alibrary ); Initialize a new FreeType library object. The set of modules that are registered by this function is determined at build time.","title":"FT_Init_FreeType"},{"location":"ft2-base_interface.html#ft_done_freetype","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Done_FreeType ( FT_Library library ); Destroy a given FreeType library object and all of its children, including resources, drivers, faces, sizes, etc.","title":"FT_Done_FreeType"},{"location":"ft2-base_interface.html#ft_new_face","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_New_Face ( FT_Library library, const char * filepathname, FT_Long face_index, FT_Face *aface ); Call FT_Open_Face to open a font by its pathname.","title":"FT_New_Face"},{"location":"ft2-base_interface.html#ft_done_face","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Done_Face ( FT_Face face ); Discard a given face object, as well as all of its child slots and sizes.","title":"FT_Done_Face"},{"location":"ft2-base_interface.html#ft_reference_face","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Reference_Face ( FT_Face face ); A counter gets initialized to 1 at the time an FT_Face structure is created. This function increments the counter. FT_Done_Face then only destroys a face if the counter is 1, otherwise it simply decrements the counter. This function helps in managing life-cycles of structures that reference FT_Face objects.","title":"FT_Reference_Face"},{"location":"ft2-base_interface.html#ft_new_memory_face","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_New_Memory_Face ( FT_Library library, const FT_Byte * file_base, FT_Long file_size, FT_Long face_index, FT_Face *aface ); Call FT_Open_Face to open a font that has been loaded into memory.","title":"FT_New_Memory_Face"},{"location":"ft2-base_interface.html#ft_face_properties","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Face_Properties ( FT_Face face, FT_UInt num_properties, FT_Parameter * properties ); Set or override certain (library or module-wide) properties on a face-by-face basis. Useful for finer-grained control and avoiding locks on shared structures (threads can modify their own faces as they see fit). Contrary to FT_Property_Set , this function uses FT_Parameter so that you can pass multiple properties to the target face in one call. Note that only a subset of the available properties can be controlled. FT_PARAM_TAG_STEM_DARKENING (stem darkening, corresponding to the property no-stem-darkening provided by the \u2018autofit\u2019, \u2018cff\u2019, \u2018type1\u2019, and \u2018t1cid\u2019 modules; see no-stem-darkening ). FT_PARAM_TAG_LCD_FILTER_WEIGHTS (LCD filter weights, corresponding to function FT_Library_SetLcdFilterWeights ). FT_PARAM_TAG_RANDOM_SEED (seed value for the CFF, Type 1, and CID \u2018random\u2019 operator, corresponding to the random-seed property provided by the \u2018cff\u2019, \u2018type1\u2019, and \u2018t1cid\u2019 modules; see random-seed ). Pass NULL as data in FT_Parameter for a given tag to reset the option and use the library or module default again.","title":"FT_Face_Properties"},{"location":"ft2-base_interface.html#ft_open_face","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Open_Face ( FT_Library library, const FT_Open_Args * args, FT_Long face_index, FT_Face *aface ); Create a face object from a given resource described by FT_Open_Args .","title":"FT_Open_Face"},{"location":"ft2-base_interface.html#ft_open_args","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Open_Args_ { FT_UInt flags; const FT_Byte * memory_base; FT_Long memory_size; FT_String * pathname; FT_Stream stream; FT_Module driver; FT_Int num_params; FT_Parameter * params; } FT_Open_Args ; A structure to indicate how to open a new font file or stream. A pointer to such a structure can be used as a parameter for the functions FT_Open_Face and FT_Attach_Stream .","title":"FT_Open_Args"},{"location":"ft2-base_interface.html#ft_parameter","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Parameter_ { FT_ULong tag; FT_Pointer data; } FT_Parameter ; A simple structure to pass more or less generic parameters to FT_Open_Face and FT_Face_Properties .","title":"FT_Parameter"},{"location":"ft2-base_interface.html#ft_attach_file","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Attach_File ( FT_Face face, const char * filepathname ); Call FT_Attach_Stream to attach a file.","title":"FT_Attach_File"},{"location":"ft2-base_interface.html#ft_attach_stream","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Attach_Stream ( FT_Face face, FT_Open_Args * parameters ); \u2018Attach\u2019 data to a face object. Normally, this is used to read additional information for the face object. For example, you can attach an AFM file that comes with a Type 1 font to get the kerning values and other metrics.","title":"FT_Attach_Stream"},{"location":"ft2-base_interface.html#ft_set_char_size","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Set_Char_Size ( FT_Face face, FT_F26Dot6 char_width, FT_F26Dot6 char_height, FT_UInt horz_resolution, FT_UInt vert_resolution ); Call FT_Request_Size to request the nominal size (in points).","title":"FT_Set_Char_Size"},{"location":"ft2-base_interface.html#ft_set_pixel_sizes","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Set_Pixel_Sizes ( FT_Face face, FT_UInt pixel_width, FT_UInt pixel_height ); Call FT_Request_Size to request the nominal size (in pixels).","title":"FT_Set_Pixel_Sizes"},{"location":"ft2-base_interface.html#ft_request_size","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Request_Size ( FT_Face face, FT_Size_Request req ); Resize the scale of the active FT_Size object in a face.","title":"FT_Request_Size"},{"location":"ft2-base_interface.html#ft_select_size","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Select_Size ( FT_Face face, FT_Int strike_index ); Select a bitmap strike. To be more precise, this function sets the scaling factors of the active FT_Size object in a face so that bitmaps from this particular strike are taken by FT_Load_Glyph and friends.","title":"FT_Select_Size"},{"location":"ft2-base_interface.html#ft_size_request_type","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef enum FT_Size_Request_Type_ { FT_SIZE_REQUEST_TYPE_NOMINAL , FT_SIZE_REQUEST_TYPE_REAL_DIM , FT_SIZE_REQUEST_TYPE_BBOX , FT_SIZE_REQUEST_TYPE_CELL , FT_SIZE_REQUEST_TYPE_SCALES , FT_SIZE_REQUEST_TYPE_MAX } FT_Size_Request_Type ; An enumeration type that lists the supported size request types, i.e., what input size (in font units) maps to the requested output size (in pixels, as computed from the arguments of FT_Size_Request ).","title":"FT_Size_Request_Type"},{"location":"ft2-base_interface.html#ft_size_requestrec","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Size_RequestRec_ { FT_Size_Request_Type type; FT_Long width; FT_Long height; FT_UInt horiResolution; FT_UInt vertResolution; } FT_Size_RequestRec ; A structure to model a size request.","title":"FT_Size_RequestRec"},{"location":"ft2-base_interface.html#ft_size_request","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Size_RequestRec_ * FT_Size_Request ; A handle to a size request structure.","title":"FT_Size_Request"},{"location":"ft2-base_interface.html#ft_set_transform","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( void ) FT_Set_Transform ( FT_Face face, FT_Matrix * matrix, FT_Vector * delta ); Set the transformation that is applied to glyph images when they are loaded into a glyph slot through FT_Load_Glyph .","title":"FT_Set_Transform"},{"location":"ft2-base_interface.html#ft_load_glyph","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Load_Glyph ( FT_Face face, FT_UInt glyph_index, FT_Int32 load_flags ); Load a glyph into the glyph slot of a face object.","title":"FT_Load_Glyph"},{"location":"ft2-base_interface.html#ft_get_char_index","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_UInt ) FT_Get_Char_Index ( FT_Face face, FT_ULong charcode ); Return the glyph index of a given character code. This function uses the currently selected charmap to do the mapping.","title":"FT_Get_Char_Index"},{"location":"ft2-base_interface.html#ft_get_first_char","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_ULong ) FT_Get_First_Char ( FT_Face face, FT_UInt *agindex ); Return the first character code in the current charmap of a given face, together with its corresponding glyph index.","title":"FT_Get_First_Char"},{"location":"ft2-base_interface.html#ft_get_next_char","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_ULong ) FT_Get_Next_Char ( FT_Face face, FT_ULong char_code, FT_UInt *agindex ); Return the next character code in the current charmap of a given face following the value char_code , as well as the corresponding glyph index.","title":"FT_Get_Next_Char"},{"location":"ft2-base_interface.html#ft_get_name_index","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_UInt ) FT_Get_Name_Index ( FT_Face face, const FT_String * glyph_name ); Return the glyph index of a given glyph name.","title":"FT_Get_Name_Index"},{"location":"ft2-base_interface.html#ft_load_char","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Load_Char ( FT_Face face, FT_ULong char_code, FT_Int32 load_flags ); Load a glyph into the glyph slot of a face object, accessed by its character code.","title":"FT_Load_Char"},{"location":"ft2-base_interface.html#ft_load_target_mode","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_LOAD_TARGET_MODE ( x ) ( ( FT_Render_Mode )( ( (x) >> 16 ) & 15 ) ) Return the FT_Render_Mode corresponding to a given FT_LOAD_TARGET_XXX value.","title":"FT_LOAD_TARGET_MODE"},{"location":"ft2-base_interface.html#ft_render_glyph","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Render_Glyph ( FT_GlyphSlot slot, FT_Render_Mode render_mode ); Convert a given glyph image to a bitmap. It does so by inspecting the glyph image format, finding the relevant renderer, and invoking it.","title":"FT_Render_Glyph"},{"location":"ft2-base_interface.html#ft_render_mode","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef enum FT_Render_Mode_ { FT_RENDER_MODE_NORMAL = 0, FT_RENDER_MODE_LIGHT , FT_RENDER_MODE_MONO , FT_RENDER_MODE_LCD , FT_RENDER_MODE_LCD_V , FT_RENDER_MODE_MAX } FT_Render_Mode ; /* these constants are deprecated; use the corresponding */ /* ` FT_Render_Mode ` values instead */ # define ft_render_mode_normal FT_RENDER_MODE_NORMAL # define ft_render_mode_mono FT_RENDER_MODE_MONO Render modes supported by FreeType 2. Each mode corresponds to a specific type of scanline conversion performed on the outline. For bitmap fonts and embedded bitmaps the bitmap->pixel_mode field in the FT_GlyphSlotRec structure gives the format of the returned bitmap. All modes except FT_RENDER_MODE_MONO use 256 levels of opacity, indicating pixel coverage. Use linear alpha blending and gamma correction to correctly render non-monochrome glyph bitmaps onto a surface; see FT_Render_Glyph .","title":"FT_Render_Mode"},{"location":"ft2-base_interface.html#ft_get_kerning","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Get_Kerning ( FT_Face face, FT_UInt left_glyph, FT_UInt right_glyph, FT_UInt kern_mode, FT_Vector *akerning ); Return the kerning vector between two glyphs of the same face.","title":"FT_Get_Kerning"},{"location":"ft2-base_interface.html#ft_kerning_mode","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef enum FT_Kerning_Mode_ { FT_KERNING_DEFAULT = 0, FT_KERNING_UNFITTED , FT_KERNING_UNSCALED } FT_Kerning_Mode ; /* these constants are deprecated; use the corresponding */ /* ` FT_Kerning_Mode ` values instead */ # define ft_kerning_default FT_KERNING_DEFAULT # define ft_kerning_unfitted FT_KERNING_UNFITTED # define ft_kerning_unscaled FT_KERNING_UNSCALED An enumeration to specify the format of kerning values returned by FT_Get_Kerning .","title":"FT_Kerning_Mode"},{"location":"ft2-base_interface.html#ft_get_track_kerning","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Get_Track_Kerning ( FT_Face face, FT_Fixed point_size, FT_Int degree, FT_Fixed * akerning ); Return the track kerning for a given face object at a given size.","title":"FT_Get_Track_Kerning"},{"location":"ft2-base_interface.html#ft_get_glyph_name","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Get_Glyph_Name ( FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max ); Retrieve the ASCII name of a given glyph in a face. This only works for those faces where FT_HAS_GLYPH_NAMES (face) returns 1.","title":"FT_Get_Glyph_Name"},{"location":"ft2-base_interface.html#ft_get_postscript_name","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( const char * ) FT_Get_Postscript_Name ( FT_Face face ); Retrieve the ASCII PostScript name of a given face, if available. This only works with PostScript, TrueType, and OpenType fonts.","title":"FT_Get_Postscript_Name"},{"location":"ft2-base_interface.html#ft_charmaprec","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_CharMapRec_ { FT_Face face; FT_Encoding encoding; FT_UShort platform_id; FT_UShort encoding_id; } FT_CharMapRec ; The base charmap structure.","title":"FT_CharMapRec"},{"location":"ft2-base_interface.html#ft_select_charmap","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Select_Charmap ( FT_Face face, FT_Encoding encoding ); Select a given charmap by its encoding tag (as listed in freetype.h ).","title":"FT_Select_Charmap"},{"location":"ft2-base_interface.html#ft_set_charmap","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Set_Charmap ( FT_Face face, FT_CharMap charmap ); Select a given charmap for character code to glyph index mapping.","title":"FT_Set_Charmap"},{"location":"ft2-base_interface.html#ft_get_charmap_index","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Int ) FT_Get_Charmap_Index ( FT_CharMap charmap ); Retrieve index of a given charmap.","title":"FT_Get_Charmap_Index"},{"location":"ft2-base_interface.html#ft_get_fstype_flags","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_UShort ) FT_Get_FSType_Flags ( FT_Face face ); Return the fsType flags for a font.","title":"FT_Get_FSType_Flags"},{"location":"ft2-base_interface.html#ft_get_subglyph_info","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Error ) FT_Get_SubGlyph_Info ( FT_GlyphSlot glyph, FT_UInt sub_index, FT_Int *p_index, FT_UInt *p_flags, FT_Int *p_arg1, FT_Int *p_arg2, FT_Matrix *p_transform ); Retrieve a description of a given subglyph. Only use it if glyph->format is FT_GLYPH_FORMAT_COMPOSITE ; an error is returned otherwise.","title":"FT_Get_SubGlyph_Info"},{"location":"ft2-base_interface.html#ft_face_internal","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Face_InternalRec_* FT_Face_Internal ; An opaque handle to an FT_Face_InternalRec structure that models the private data of a given FT_Face object. This structure might change between releases of FreeType 2 and is not generally available to client applications.","title":"FT_Face_Internal"},{"location":"ft2-base_interface.html#ft_size_internal","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Size_InternalRec_* FT_Size_Internal ; An opaque handle to an FT_Size_InternalRec structure, used to model private data of a given FT_Size object.","title":"FT_Size_Internal"},{"location":"ft2-base_interface.html#ft_slot_internal","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_Slot_InternalRec_* FT_Slot_Internal ; An opaque handle to an FT_Slot_InternalRec structure, used to model private data of a given FT_GlyphSlot object.","title":"FT_Slot_Internal"},{"location":"ft2-base_interface.html#ft_face_flag_xxx","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_FACE_FLAG_SCALABLE ( 1L << 0 ) # define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 ) # define FT_FACE_FLAG_FIXED_WIDTH ( 1L << 2 ) # define FT_FACE_FLAG_SFNT ( 1L << 3 ) # define FT_FACE_FLAG_HORIZONTAL ( 1L << 4 ) # define FT_FACE_FLAG_VERTICAL ( 1L << 5 ) # define FT_FACE_FLAG_KERNING ( 1L << 6 ) # define FT_FACE_FLAG_FAST_GLYPHS ( 1L << 7 ) # define FT_FACE_FLAG_MULTIPLE_MASTERS ( 1L << 8 ) # define FT_FACE_FLAG_GLYPH_NAMES ( 1L << 9 ) # define FT_FACE_FLAG_EXTERNAL_STREAM ( 1L << 10 ) # define FT_FACE_FLAG_HINTER ( 1L << 11 ) # define FT_FACE_FLAG_CID_KEYED ( 1L << 12 ) # define FT_FACE_FLAG_TRICKY ( 1L << 13 ) # define FT_FACE_FLAG_COLOR ( 1L << 14 ) # define FT_FACE_FLAG_VARIATION ( 1L << 15 ) A list of bit flags used in the face_flags field of the FT_FaceRec structure. They inform client applications of properties of the corresponding face.","title":"FT_FACE_FLAG_XXX"},{"location":"ft2-base_interface.html#ft_style_flag_xxx","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_STYLE_FLAG_ITALIC ( 1 << 0 ) # define FT_STYLE_FLAG_BOLD ( 1 << 1 ) A list of bit flags to indicate the style of a given face. These are used in the style_flags field of FT_FaceRec .","title":"FT_STYLE_FLAG_XXX"},{"location":"ft2-base_interface.html#ft_open_xxx","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_OPEN_MEMORY 0x1 # define FT_OPEN_STREAM 0x2 # define FT_OPEN_PATHNAME 0x4 # define FT_OPEN_DRIVER 0x8 # define FT_OPEN_PARAMS 0x10 /* these constants are deprecated; use the corresponding ` FT_OPEN_XXX ` */ /* values instead */ # define ft_open_memory FT_OPEN_MEMORY # define ft_open_stream FT_OPEN_STREAM # define ft_open_pathname FT_OPEN_PATHNAME # define ft_open_driver FT_OPEN_DRIVER # define ft_open_params FT_OPEN_PARAMS A list of bit field constants used within the flags field of the FT_Open_Args structure.","title":"FT_OPEN_XXX"},{"location":"ft2-base_interface.html#ft_load_xxx","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_LOAD_DEFAULT 0x0 # define FT_LOAD_NO_SCALE ( 1L << 0 ) # define FT_LOAD_NO_HINTING ( 1L << 1 ) # define FT_LOAD_RENDER ( 1L << 2 ) # define FT_LOAD_NO_BITMAP ( 1L << 3 ) # define FT_LOAD_VERTICAL_LAYOUT ( 1L << 4 ) # define FT_LOAD_FORCE_AUTOHINT ( 1L << 5 ) # define FT_LOAD_CROP_BITMAP ( 1L << 6 ) # define FT_LOAD_PEDANTIC ( 1L << 7 ) # define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ( 1L << 9 ) # define FT_LOAD_NO_RECURSE ( 1L << 10 ) # define FT_LOAD_IGNORE_TRANSFORM ( 1L << 11 ) # define FT_LOAD_MONOCHROME ( 1L << 12 ) # define FT_LOAD_LINEAR_DESIGN ( 1L << 13 ) # define FT_LOAD_NO_AUTOHINT ( 1L << 15 ) /* Bits 16-19 are used by `FT_LOAD_TARGET_` */ # define FT_LOAD_COLOR ( 1L << 20 ) # define FT_LOAD_COMPUTE_METRICS ( 1L << 21 ) # define FT_LOAD_BITMAP_METRICS_ONLY ( 1L << 22 ) A list of bit field constants for FT_Load_Glyph to indicate what kind of operations to perform during glyph loading.","title":"FT_LOAD_XXX"},{"location":"ft2-base_interface.html#ft_load_target_xxx","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_LOAD_TARGET_( x ) ( ( FT_Int32 )( (x) & 15 ) << 16 ) # define FT_LOAD_TARGET_NORMAL FT_LOAD_TARGET_( FT_RENDER_MODE_NORMAL ) # define FT_LOAD_TARGET_LIGHT FT_LOAD_TARGET_( FT_RENDER_MODE_LIGHT ) # define FT_LOAD_TARGET_MONO FT_LOAD_TARGET_( FT_RENDER_MODE_MONO ) # define FT_LOAD_TARGET_LCD FT_LOAD_TARGET_( FT_RENDER_MODE_LCD ) # define FT_LOAD_TARGET_LCD_V FT_LOAD_TARGET_( FT_RENDER_MODE_LCD_V ) A list of values to select a specific hinting algorithm for the hinter. You should OR one of these values to your load_flags when calling FT_Load_Glyph . Note that a font's native hinters may ignore the hinting algorithm you have specified (e.g., the TrueType bytecode interpreter). You can set FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used.","title":"FT_LOAD_TARGET_XXX"},{"location":"ft2-base_interface.html#ft_subglyph_flag_xxx","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1 # define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2 # define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4 # define FT_SUBGLYPH_FLAG_SCALE 8 # define FT_SUBGLYPH_FLAG_XY_SCALE 0x40 # define FT_SUBGLYPH_FLAG_2X2 0x80 # define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200 A list of constants describing subglyphs. Please refer to the \u2018glyf\u2019 table description in the OpenType specification for the meaning of the various flags (which get synthesized for non-OpenType subglyphs). https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#composite-glyph-description","title":"FT_SUBGLYPH_FLAG_XXX"},{"location":"ft2-base_interface.html#ft_fstype_xxx","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_FSTYPE_INSTALLABLE_EMBEDDING 0x0000 # define FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING 0x0002 # define FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING 0x0004 # define FT_FSTYPE_EDITABLE_EMBEDDING 0x0008 # define FT_FSTYPE_NO_SUBSETTING 0x0100 # define FT_FSTYPE_BITMAP_EMBEDDING_ONLY 0x0200 A list of bit flags used in the fsType field of the OS/2 table in a TrueType or OpenType font and the FSType entry in a PostScript font. These bit flags are returned by FT_Get_FSType_Flags ; they inform client applications of embedding and subsetting restrictions associated with a font. See https://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/FontPolicies.pdf for more details.","title":"FT_FSTYPE_XXX"},{"location":"ft2-base_interface.html#ft_has_fast_glyphs","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FT_HAS_FAST_GLYPHS ( face ) 0 Deprecated.","title":"FT_HAS_FAST_GLYPHS"},{"location":"ft2-basic_types.html","text":"FreeType \u00bb Docs \u00bb Core API \u00bb Basic Data Types Basic Data Types \u00b6 Synopsis \u00b6 This section contains the basic data types defined by FreeType 2, ranging from simple scalar types to bitmap descriptors. More font-specific structures are defined in a different section. FT_Byte \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef unsigned char FT_Byte ; A simple typedef for the unsigned char type. FT_Bytes \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef const FT_Byte * FT_Bytes ; A typedef for constant memory areas. FT_Char \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed char FT_Char ; A simple typedef for the signed char type. FT_Int \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed int FT_Int ; A typedef for the int type. FT_UInt \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef unsigned int FT_UInt ; A typedef for the unsigned int type. FT_Int16 \u00b6 typedef signed short FT_Int16 ; A typedef for a 16bit signed integer type. FT_UInt16 \u00b6 typedef unsigned short FT_UInt16 ; A typedef for a 16bit unsigned integer type. FT_Int32 \u00b6 typedef signed XXX FT_Int32 ; A typedef for a 32bit signed integer type. The size depends on the configuration. FT_UInt32 \u00b6 typedef unsigned XXX FT_UInt32 ; FT_Int64 \u00b6 typedef signed XXX FT_Int64 ; FT_UInt64 \u00b6 typedef unsigned XXX FT_UInt64 ; FT_Short \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed short FT_Short ; A typedef for signed short. FT_UShort \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef unsigned short FT_UShort ; A typedef for unsigned short. FT_Long \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed long FT_Long ; A typedef for signed long. FT_ULong \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef unsigned long FT_ULong ; A typedef for unsigned long. FT_Bool \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef unsigned char FT_Bool ; A typedef of unsigned char, used for simple booleans. As usual, values 1 and 0 represent true and false, respectively. FT_Offset \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef size_t FT_Offset ; This is equivalent to the ANSI C size_t type, i.e., the largest unsigned integer type used to express a file size or position, or a memory block size. FT_PtrDist \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef ft_ptrdiff_t FT_PtrDist ; This is equivalent to the ANSI C ptrdiff_t type, i.e., the largest signed integer type used to express the distance between two pointers. FT_String \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef char FT_String ; A simple typedef for the char type, usually used for strings. FT_Tag \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef FT_UInt32 FT_Tag ; A typedef for 32-bit tags (as used in the SFNT format). FT_Error \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef int FT_Error ; The FreeType error code type. A value of 0 is always interpreted as a successful operation. FT_Fixed \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed long FT_Fixed ; This type is used to store 16.16 fixed-point values, like scaling values or matrix coefficients. FT_Pointer \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef void * FT_Pointer ; A simple typedef for a typeless pointer. FT_Pos \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef signed long FT_Pos ; The type FT_Pos is used to store vectorial coordinates. Depending on the context, these can represent distances in integer font units, or 16.16, or 26.6 fixed-point pixel coordinates. FT_Vector \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_Vector_ { FT_Pos x; FT_Pos y; } FT_Vector ; A simple structure used to store a 2D vector; coordinates are of the FT_Pos type. fields x The horizontal coordinate. y The vertical coordinate. FT_BBox \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_BBox_ { FT_Pos xMin, yMin; FT_Pos xMax, yMax; } FT_BBox ; A structure used to hold an outline's bounding box, i.e., the coordinates of its extrema in the horizontal and vertical directions. fields xMin The horizontal minimum (left-most). yMin The vertical minimum (bottom-most). xMax The horizontal maximum (right-most). yMax The vertical maximum (top-most). note The bounding box is specified with the coordinates of the lower left and the upper right corner. In PostScript, those values are often called (llx,lly) and (urx,ury), respectively. If yMin is negative, this value gives the glyph's descender. Otherwise, the glyph doesn't descend below the baseline. Similarly, if ymax is positive, this value gives the glyph's ascender. xMin gives the horizontal distance from the glyph's origin to the left edge of the glyph's bounding box. If xMin is negative, the glyph extends to the left of the origin. FT_Matrix \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_Matrix_ { FT_Fixed xx, xy; FT_Fixed yx, yy; } FT_Matrix ; A simple structure used to store a 2x2 matrix. Coefficients are in 16.16 fixed-point format. The computation performed is: x' = x*xx + y*xy y' = x*yx + y*yy fields xx Matrix coefficient. xy Matrix coefficient. yx Matrix coefficient. yy Matrix coefficient. FT_FWord \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed short FT_FWord ; /* distance in FUnits */ A signed 16-bit integer used to store a distance in original font units. FT_UFWord \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef unsigned short FT_UFWord ; /* unsigned distance */ An unsigned 16-bit integer used to store a distance in original font units. FT_F2Dot14 \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed short FT_F2Dot14 ; A signed 2.14 fixed-point type used for unit vectors. FT_UnitVector \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_UnitVector_ { FT_F2Dot14 x; FT_F2Dot14 y; } FT_UnitVector ; A simple structure used to store a 2D vector unit vector. Uses FT_F2Dot14 types. fields x Horizontal coordinate. y Vertical coordinate. FT_F26Dot6 \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed long FT_F26Dot6 ; A signed 26.6 fixed-point type used for vectorial pixel coordinates. FT_Data \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_Data_ { const FT_Byte * pointer; FT_Int length; } FT_Data ; Read-only binary data represented as a pointer and a length. fields pointer The data. length The length of the data in bytes. FT_MAKE_TAG \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). # define FT_MAKE_TAG ( _x1, _x2, _x3, _x4 ) \\ ( FT_Tag ) \\ ( ( ( FT_ULong )_x1 << 24 ) | \\ ( ( FT_ULong )_x2 << 16 ) | \\ ( ( FT_ULong )_x3 << 8 ) | \\ ( FT_ULong )_x4 ) This macro converts four-letter tags that are used to label TrueType tables into an unsigned long, to be used within FreeType. note The produced values must be 32-bit integers. Don't redefine this macro. FT_Generic \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_Generic_ { void * data; FT_Generic_Finalizer finalizer; } FT_Generic ; Client applications often need to associate their own data to a variety of FreeType core objects. For example, a text layout API might want to associate a glyph cache to a given size object. Some FreeType object contains a generic field, of type FT_Generic , which usage is left to client applications and font servers. It can be used to store a pointer to client-specific data, as well as the address of a \u2018finalizer\u2019 function, which will be called by FreeType when the object is destroyed (for example, the previous client example would put the address of the glyph cache destructor in the finalizer field). fields data A typeless pointer to any client-specified data. This field is completely ignored by the FreeType library. finalizer A pointer to a \u2018generic finalizer\u2019 function, which will be called when the object is destroyed. If this field is set to NULL , no code will be called. FT_Generic_Finalizer \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef void (* FT_Generic_Finalizer )( void * object ); Describe a function used to destroy the \u2018client\u2019 data of any FreeType object. See the description of the FT_Generic type for details of usage. input The address of the FreeType object that is under finalization. Its client data is accessed through its generic field. FT_Bitmap \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_Bitmap_ { unsigned int rows; unsigned int width; int pitch; unsigned char * buffer; unsigned short num_grays; unsigned char pixel_mode; unsigned char palette_mode; void * palette; } FT_Bitmap ; A structure used to describe a bitmap or pixmap to the raster. Note that we now manage pixmaps of various depths through the pixel_mode field. fields rows The number of bitmap rows. width The number of pixels in bitmap row. pitch The pitch's absolute value is the number of bytes taken by one bitmap row, including padding. However, the pitch is positive when the bitmap has a \u2018down\u2019 flow, and negative when it has an \u2018up\u2019 flow. In all cases, the pitch is an offset to add to a bitmap pointer in order to go down one row. Note that \u2018padding\u2019 means the alignment of a bitmap to a byte border, and FreeType functions normally align to the smallest possible integer value. For the B/W rasterizer, pitch is always an even number. To change the pitch of a bitmap (say, to make it a multiple of 4), use FT_Bitmap_Convert . Alternatively, you might use callback functions to directly render to the application's surface; see the file example2.cpp in the tutorial for a demonstration. buffer A typeless pointer to the bitmap buffer. This value should be aligned on 32-bit boundaries in most cases. num_grays This field is only used with FT_PIXEL_MODE_GRAY ; it gives the number of gray levels used in the bitmap. pixel_mode The pixel mode, i.e., how pixel bits are stored. See FT_Pixel_Mode for possible values. palette_mode This field is intended for paletted pixel modes; it indicates how the palette is stored. Not used currently. palette A typeless pointer to the bitmap palette; this field is intended for paletted pixel modes. Not used currently. FT_Pixel_Mode \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef enum FT_Pixel_Mode_ { FT_PIXEL_MODE_NONE = 0, FT_PIXEL_MODE_MONO , FT_PIXEL_MODE_GRAY , FT_PIXEL_MODE_GRAY2 , FT_PIXEL_MODE_GRAY4 , FT_PIXEL_MODE_LCD , FT_PIXEL_MODE_LCD_V , FT_PIXEL_MODE_BGRA , FT_PIXEL_MODE_MAX /* do not remove */ } FT_Pixel_Mode ; /* these constants are deprecated; use the corresponding ` FT_Pixel_Mode ` */ /* values instead. */ # define ft_pixel_mode_none FT_PIXEL_MODE_NONE # define ft_pixel_mode_mono FT_PIXEL_MODE_MONO # define ft_pixel_mode_grays FT_PIXEL_MODE_GRAY # define ft_pixel_mode_pal2 FT_PIXEL_MODE_GRAY2 # define ft_pixel_mode_pal4 FT_PIXEL_MODE_GRAY4 An enumeration type used to describe the format of pixels in a given bitmap. Note that additional formats may be added in the future. values FT_PIXEL_MODE_NONE Value 0 is reserved. FT_PIXEL_MODE_MONO A monochrome bitmap, using 1 bit per pixel. Note that pixels are stored in most-significant order (MSB), which means that the left-most pixel in a byte has value 128. FT_PIXEL_MODE_GRAY An 8-bit bitmap, generally used to represent anti-aliased glyph images. Each pixel is stored in one byte. Note that the number of \u2018gray\u2019 levels is stored in the num_grays field of the FT_Bitmap structure (it generally is 256). FT_PIXEL_MODE_GRAY2 A 2-bit per pixel bitmap, used to represent embedded anti-aliased bitmaps in font files according to the OpenType specification. We haven't found a single font using this format, however. FT_PIXEL_MODE_GRAY4 A 4-bit per pixel bitmap, representing embedded anti-aliased bitmaps in font files according to the OpenType specification. We haven't found a single font using this format, however. FT_PIXEL_MODE_LCD An 8-bit bitmap, representing RGB or BGR decimated glyph images used for display on LCD displays; the bitmap is three times wider than the original glyph image. See also FT_RENDER_MODE_LCD . FT_PIXEL_MODE_LCD_V An 8-bit bitmap, representing RGB or BGR decimated glyph images used for display on rotated LCD displays; the bitmap is three times taller than the original glyph image. See also FT_RENDER_MODE_LCD_V . FT_PIXEL_MODE_BGRA [Since 2.5] An image with four 8-bit channels per pixel, representing a color image (such as emoticons) with alpha channel. For each pixel, the format is BGRA, which means, the blue channel comes first in memory. The color channels are pre-multiplied and in the sRGB colorspace. For example, full red at half-translucent opacity will be represented as \u201800,00,80,80\u2019, not \u201800,00,FF,80\u2019. See also FT_LOAD_COLOR . FT_Glyph_Format \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef enum FT_Glyph_Format_ { FT_IMAGE_TAG ( FT_GLYPH_FORMAT_NONE , 0, 0, 0, 0 ), FT_IMAGE_TAG ( FT_GLYPH_FORMAT_COMPOSITE , 'c', 'o', 'm', 'p' ), FT_IMAGE_TAG ( FT_GLYPH_FORMAT_BITMAP , 'b', 'i', 't', 's' ), FT_IMAGE_TAG ( FT_GLYPH_FORMAT_OUTLINE , 'o', 'u', 't', 'l' ), FT_IMAGE_TAG ( FT_GLYPH_FORMAT_PLOTTER , 'p', 'l', 'o', 't' ) } FT_Glyph_Format ; /* these constants are deprecated; use the corresponding */ /* ` FT_Glyph_Format ` values instead. */ # define ft_glyph_format_none FT_GLYPH_FORMAT_NONE # define ft_glyph_format_composite FT_GLYPH_FORMAT_COMPOSITE # define ft_glyph_format_bitmap FT_GLYPH_FORMAT_BITMAP # define ft_glyph_format_outline FT_GLYPH_FORMAT_OUTLINE # define ft_glyph_format_plotter FT_GLYPH_FORMAT_PLOTTER An enumeration type used to describe the format of a given glyph image. Note that this version of FreeType only supports two image formats, even though future font drivers will be able to register their own format. values FT_GLYPH_FORMAT_NONE The value 0 is reserved. FT_GLYPH_FORMAT_COMPOSITE The glyph image is a composite of several other images. This format is only used with FT_LOAD_NO_RECURSE , and is used to report compound glyphs (like accented characters). FT_GLYPH_FORMAT_BITMAP The glyph image is a bitmap, and can be described as an FT_Bitmap . You generally need to access the bitmap field of the FT_GlyphSlotRec structure to read it. FT_GLYPH_FORMAT_OUTLINE The glyph image is a vectorial outline made of line segments and Bezier arcs; it can be described as an FT_Outline ; you generally want to access the outline field of the FT_GlyphSlotRec structure to read it. FT_GLYPH_FORMAT_PLOTTER The glyph image is a vectorial path with no inside and outside contours. Some Type 1 fonts, like those in the Hershey family, contain glyphs in this format. These are described as FT_Outline , but FreeType isn't currently capable of rendering them correctly. FT_IMAGE_TAG \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). # ifndef FT_IMAGE_TAG # define FT_IMAGE_TAG ( value, _x1, _x2, _x3, _x4 ) \\ value = ( ( ( unsigned long )_x1 << 24 ) | \\ ( ( unsigned long )_x2 << 16 ) | \\ ( ( unsigned long )_x3 << 8 ) | \\ ( unsigned long )_x4 ) # endif /* FT_IMAGE_TAG */ This macro converts four-letter tags to an unsigned long type. note Since many 16-bit compilers don't like 32-bit enumerations, you should redefine this macro in case of problems to something like this: #define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) value to get a simple enumeration without assigning special numbers.","title":"Basic Data Types"},{"location":"ft2-basic_types.html#basic-data-types","text":"","title":"Basic Data Types"},{"location":"ft2-basic_types.html#synopsis","text":"This section contains the basic data types defined by FreeType 2, ranging from simple scalar types to bitmap descriptors. More font-specific structures are defined in a different section.","title":"Synopsis"},{"location":"ft2-basic_types.html#ft_byte","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef unsigned char FT_Byte ; A simple typedef for the unsigned char type.","title":"FT_Byte"},{"location":"ft2-basic_types.html#ft_bytes","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef const FT_Byte * FT_Bytes ; A typedef for constant memory areas.","title":"FT_Bytes"},{"location":"ft2-basic_types.html#ft_char","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed char FT_Char ; A simple typedef for the signed char type.","title":"FT_Char"},{"location":"ft2-basic_types.html#ft_int","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed int FT_Int ; A typedef for the int type.","title":"FT_Int"},{"location":"ft2-basic_types.html#ft_uint","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef unsigned int FT_UInt ; A typedef for the unsigned int type.","title":"FT_UInt"},{"location":"ft2-basic_types.html#ft_int16","text":"typedef signed short FT_Int16 ; A typedef for a 16bit signed integer type.","title":"FT_Int16"},{"location":"ft2-basic_types.html#ft_uint16","text":"typedef unsigned short FT_UInt16 ; A typedef for a 16bit unsigned integer type.","title":"FT_UInt16"},{"location":"ft2-basic_types.html#ft_int32","text":"typedef signed XXX FT_Int32 ; A typedef for a 32bit signed integer type. The size depends on the configuration.","title":"FT_Int32"},{"location":"ft2-basic_types.html#ft_uint32","text":"typedef unsigned XXX FT_UInt32 ;","title":"FT_UInt32"},{"location":"ft2-basic_types.html#ft_int64","text":"typedef signed XXX FT_Int64 ;","title":"FT_Int64"},{"location":"ft2-basic_types.html#ft_uint64","text":"typedef unsigned XXX FT_UInt64 ;","title":"FT_UInt64"},{"location":"ft2-basic_types.html#ft_short","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed short FT_Short ; A typedef for signed short.","title":"FT_Short"},{"location":"ft2-basic_types.html#ft_ushort","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef unsigned short FT_UShort ; A typedef for unsigned short.","title":"FT_UShort"},{"location":"ft2-basic_types.html#ft_long","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed long FT_Long ; A typedef for signed long.","title":"FT_Long"},{"location":"ft2-basic_types.html#ft_ulong","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef unsigned long FT_ULong ; A typedef for unsigned long.","title":"FT_ULong"},{"location":"ft2-basic_types.html#ft_bool","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef unsigned char FT_Bool ; A typedef of unsigned char, used for simple booleans. As usual, values 1 and 0 represent true and false, respectively.","title":"FT_Bool"},{"location":"ft2-basic_types.html#ft_offset","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef size_t FT_Offset ; This is equivalent to the ANSI C size_t type, i.e., the largest unsigned integer type used to express a file size or position, or a memory block size.","title":"FT_Offset"},{"location":"ft2-basic_types.html#ft_ptrdist","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef ft_ptrdiff_t FT_PtrDist ; This is equivalent to the ANSI C ptrdiff_t type, i.e., the largest signed integer type used to express the distance between two pointers.","title":"FT_PtrDist"},{"location":"ft2-basic_types.html#ft_string","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef char FT_String ; A simple typedef for the char type, usually used for strings.","title":"FT_String"},{"location":"ft2-basic_types.html#ft_tag","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef FT_UInt32 FT_Tag ; A typedef for 32-bit tags (as used in the SFNT format).","title":"FT_Tag"},{"location":"ft2-basic_types.html#ft_error","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef int FT_Error ; The FreeType error code type. A value of 0 is always interpreted as a successful operation.","title":"FT_Error"},{"location":"ft2-basic_types.html#ft_fixed","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed long FT_Fixed ; This type is used to store 16.16 fixed-point values, like scaling values or matrix coefficients.","title":"FT_Fixed"},{"location":"ft2-basic_types.html#ft_pointer","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef void * FT_Pointer ; A simple typedef for a typeless pointer.","title":"FT_Pointer"},{"location":"ft2-basic_types.html#ft_pos","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef signed long FT_Pos ; The type FT_Pos is used to store vectorial coordinates. Depending on the context, these can represent distances in integer font units, or 16.16, or 26.6 fixed-point pixel coordinates.","title":"FT_Pos"},{"location":"ft2-basic_types.html#ft_vector","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_Vector_ { FT_Pos x; FT_Pos y; } FT_Vector ; A simple structure used to store a 2D vector; coordinates are of the FT_Pos type.","title":"FT_Vector"},{"location":"ft2-basic_types.html#ft_bbox","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_BBox_ { FT_Pos xMin, yMin; FT_Pos xMax, yMax; } FT_BBox ; A structure used to hold an outline's bounding box, i.e., the coordinates of its extrema in the horizontal and vertical directions.","title":"FT_BBox"},{"location":"ft2-basic_types.html#ft_matrix","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_Matrix_ { FT_Fixed xx, xy; FT_Fixed yx, yy; } FT_Matrix ; A simple structure used to store a 2x2 matrix. Coefficients are in 16.16 fixed-point format. The computation performed is: x' = x*xx + y*xy y' = x*yx + y*yy","title":"FT_Matrix"},{"location":"ft2-basic_types.html#ft_fword","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed short FT_FWord ; /* distance in FUnits */ A signed 16-bit integer used to store a distance in original font units.","title":"FT_FWord"},{"location":"ft2-basic_types.html#ft_ufword","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef unsigned short FT_UFWord ; /* unsigned distance */ An unsigned 16-bit integer used to store a distance in original font units.","title":"FT_UFWord"},{"location":"ft2-basic_types.html#ft_f2dot14","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed short FT_F2Dot14 ; A signed 2.14 fixed-point type used for unit vectors.","title":"FT_F2Dot14"},{"location":"ft2-basic_types.html#ft_unitvector","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_UnitVector_ { FT_F2Dot14 x; FT_F2Dot14 y; } FT_UnitVector ; A simple structure used to store a 2D vector unit vector. Uses FT_F2Dot14 types.","title":"FT_UnitVector"},{"location":"ft2-basic_types.html#ft_f26dot6","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef signed long FT_F26Dot6 ; A signed 26.6 fixed-point type used for vectorial pixel coordinates.","title":"FT_F26Dot6"},{"location":"ft2-basic_types.html#ft_data","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_Data_ { const FT_Byte * pointer; FT_Int length; } FT_Data ; Read-only binary data represented as a pointer and a length.","title":"FT_Data"},{"location":"ft2-basic_types.html#ft_make_tag","text":"Defined in FT_TYPES_H (freetype/fttypes.h). # define FT_MAKE_TAG ( _x1, _x2, _x3, _x4 ) \\ ( FT_Tag ) \\ ( ( ( FT_ULong )_x1 << 24 ) | \\ ( ( FT_ULong )_x2 << 16 ) | \\ ( ( FT_ULong )_x3 << 8 ) | \\ ( FT_ULong )_x4 ) This macro converts four-letter tags that are used to label TrueType tables into an unsigned long, to be used within FreeType.","title":"FT_MAKE_TAG"},{"location":"ft2-basic_types.html#ft_generic","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_Generic_ { void * data; FT_Generic_Finalizer finalizer; } FT_Generic ; Client applications often need to associate their own data to a variety of FreeType core objects. For example, a text layout API might want to associate a glyph cache to a given size object. Some FreeType object contains a generic field, of type FT_Generic , which usage is left to client applications and font servers. It can be used to store a pointer to client-specific data, as well as the address of a \u2018finalizer\u2019 function, which will be called by FreeType when the object is destroyed (for example, the previous client example would put the address of the glyph cache destructor in the finalizer field).","title":"FT_Generic"},{"location":"ft2-basic_types.html#ft_generic_finalizer","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef void (* FT_Generic_Finalizer )( void * object ); Describe a function used to destroy the \u2018client\u2019 data of any FreeType object. See the description of the FT_Generic type for details of usage.","title":"FT_Generic_Finalizer"},{"location":"ft2-basic_types.html#ft_bitmap","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_Bitmap_ { unsigned int rows; unsigned int width; int pitch; unsigned char * buffer; unsigned short num_grays; unsigned char pixel_mode; unsigned char palette_mode; void * palette; } FT_Bitmap ; A structure used to describe a bitmap or pixmap to the raster. Note that we now manage pixmaps of various depths through the pixel_mode field.","title":"FT_Bitmap"},{"location":"ft2-basic_types.html#ft_pixel_mode","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef enum FT_Pixel_Mode_ { FT_PIXEL_MODE_NONE = 0, FT_PIXEL_MODE_MONO , FT_PIXEL_MODE_GRAY , FT_PIXEL_MODE_GRAY2 , FT_PIXEL_MODE_GRAY4 , FT_PIXEL_MODE_LCD , FT_PIXEL_MODE_LCD_V , FT_PIXEL_MODE_BGRA , FT_PIXEL_MODE_MAX /* do not remove */ } FT_Pixel_Mode ; /* these constants are deprecated; use the corresponding ` FT_Pixel_Mode ` */ /* values instead. */ # define ft_pixel_mode_none FT_PIXEL_MODE_NONE # define ft_pixel_mode_mono FT_PIXEL_MODE_MONO # define ft_pixel_mode_grays FT_PIXEL_MODE_GRAY # define ft_pixel_mode_pal2 FT_PIXEL_MODE_GRAY2 # define ft_pixel_mode_pal4 FT_PIXEL_MODE_GRAY4 An enumeration type used to describe the format of pixels in a given bitmap. Note that additional formats may be added in the future.","title":"FT_Pixel_Mode"},{"location":"ft2-basic_types.html#ft_glyph_format","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef enum FT_Glyph_Format_ { FT_IMAGE_TAG ( FT_GLYPH_FORMAT_NONE , 0, 0, 0, 0 ), FT_IMAGE_TAG ( FT_GLYPH_FORMAT_COMPOSITE , 'c', 'o', 'm', 'p' ), FT_IMAGE_TAG ( FT_GLYPH_FORMAT_BITMAP , 'b', 'i', 't', 's' ), FT_IMAGE_TAG ( FT_GLYPH_FORMAT_OUTLINE , 'o', 'u', 't', 'l' ), FT_IMAGE_TAG ( FT_GLYPH_FORMAT_PLOTTER , 'p', 'l', 'o', 't' ) } FT_Glyph_Format ; /* these constants are deprecated; use the corresponding */ /* ` FT_Glyph_Format ` values instead. */ # define ft_glyph_format_none FT_GLYPH_FORMAT_NONE # define ft_glyph_format_composite FT_GLYPH_FORMAT_COMPOSITE # define ft_glyph_format_bitmap FT_GLYPH_FORMAT_BITMAP # define ft_glyph_format_outline FT_GLYPH_FORMAT_OUTLINE # define ft_glyph_format_plotter FT_GLYPH_FORMAT_PLOTTER An enumeration type used to describe the format of a given glyph image. Note that this version of FreeType only supports two image formats, even though future font drivers will be able to register their own format.","title":"FT_Glyph_Format"},{"location":"ft2-basic_types.html#ft_image_tag","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). # ifndef FT_IMAGE_TAG # define FT_IMAGE_TAG ( value, _x1, _x2, _x3, _x4 ) \\ value = ( ( ( unsigned long )_x1 << 24 ) | \\ ( ( unsigned long )_x2 << 16 ) | \\ ( ( unsigned long )_x3 << 8 ) | \\ ( unsigned long )_x4 ) # endif /* FT_IMAGE_TAG */ This macro converts four-letter tags to an unsigned long type.","title":"FT_IMAGE_TAG"},{"location":"ft2-bdf_fonts.html","text":"FreeType \u00bb Docs \u00bb Format-Specific API \u00bb BDF and PCF Files BDF and PCF Files \u00b6 Synopsis \u00b6 This section contains the declaration of functions specific to BDF and PCF fonts. BDF_PropertyType \u00b6 Defined in FT_BDF_H (freetype/ftbdf.h). typedef enum BDF_PropertyType_ { BDF_PROPERTY_TYPE_NONE = 0, BDF_PROPERTY_TYPE_ATOM = 1, BDF_PROPERTY_TYPE_INTEGER = 2, BDF_PROPERTY_TYPE_CARDINAL = 3 } BDF_PropertyType ; A list of BDF property types. values BDF_PROPERTY_TYPE_NONE Value 0 is used to indicate a missing property. BDF_PROPERTY_TYPE_ATOM Property is a string atom. BDF_PROPERTY_TYPE_INTEGER Property is a 32-bit signed integer. BDF_PROPERTY_TYPE_CARDINAL Property is a 32-bit unsigned integer. BDF_Property \u00b6 Defined in FT_BDF_H (freetype/ftbdf.h). typedef struct BDF_PropertyRec_* BDF_Property ; A handle to a BDF_PropertyRec structure to model a given BDF/PCF property. BDF_PropertyRec \u00b6 Defined in FT_BDF_H (freetype/ftbdf.h). typedef struct BDF_PropertyRec_ { BDF_PropertyType type; union { const char * atom; FT_Int32 integer; FT_UInt32 cardinal; } u; } BDF_PropertyRec ; This structure models a given BDF/PCF property. fields type The property type. u.atom The atom string, if type is BDF_PROPERTY_TYPE_ATOM . May be NULL , indicating an empty string. u.integer A signed integer, if type is BDF_PROPERTY_TYPE_INTEGER . u.cardinal An unsigned integer, if type is BDF_PROPERTY_TYPE_CARDINAL . FT_Get_BDF_Charset_ID \u00b6 Defined in FT_BDF_H (freetype/ftbdf.h). FT_EXPORT( FT_Error ) FT_Get_BDF_Charset_ID ( FT_Face face, const char * *acharset_encoding, const char * *acharset_registry ); Retrieve a BDF font character set identity, according to the BDF specification. input face A handle to the input face. output acharset_encoding Charset encoding, as a C string, owned by the face. acharset_registry Charset registry, as a C string, owned by the face. return FreeType error code. 0 means success. note This function only works with BDF faces, returning an error otherwise. FT_Get_BDF_Property \u00b6 Defined in FT_BDF_H (freetype/ftbdf.h). FT_EXPORT( FT_Error ) FT_Get_BDF_Property ( FT_Face face, const char * prop_name, BDF_PropertyRec *aproperty ); Retrieve a BDF property from a BDF or PCF font file. input face A handle to the input face. name The property name. output aproperty The property. return FreeType error code. 0 means success. note This function works with BDF and PCF fonts. It returns an error otherwise. It also returns an error if the property is not in the font. A \u2018property\u2019 is a either key-value pair within the STARTPROPERTIES ... ENDPROPERTIES block of a BDF font or a key-value pair from the info->props array within a FontRec structure of a PCF font. Integer properties are always stored as \u2018signed\u2019 within PCF fonts; consequently, BDF_PROPERTY_TYPE_CARDINAL is a possible return value for BDF fonts only. In case of error, aproperty->type is always set to BDF_PROPERTY_TYPE_NONE .","title":"BDF and PCF Files"},{"location":"ft2-bdf_fonts.html#bdf-and-pcf-files","text":"","title":"BDF and PCF Files"},{"location":"ft2-bdf_fonts.html#synopsis","text":"This section contains the declaration of functions specific to BDF and PCF fonts.","title":"Synopsis"},{"location":"ft2-bdf_fonts.html#bdf_propertytype","text":"Defined in FT_BDF_H (freetype/ftbdf.h). typedef enum BDF_PropertyType_ { BDF_PROPERTY_TYPE_NONE = 0, BDF_PROPERTY_TYPE_ATOM = 1, BDF_PROPERTY_TYPE_INTEGER = 2, BDF_PROPERTY_TYPE_CARDINAL = 3 } BDF_PropertyType ; A list of BDF property types.","title":"BDF_PropertyType"},{"location":"ft2-bdf_fonts.html#bdf_property","text":"Defined in FT_BDF_H (freetype/ftbdf.h). typedef struct BDF_PropertyRec_* BDF_Property ; A handle to a BDF_PropertyRec structure to model a given BDF/PCF property.","title":"BDF_Property"},{"location":"ft2-bdf_fonts.html#bdf_propertyrec","text":"Defined in FT_BDF_H (freetype/ftbdf.h). typedef struct BDF_PropertyRec_ { BDF_PropertyType type; union { const char * atom; FT_Int32 integer; FT_UInt32 cardinal; } u; } BDF_PropertyRec ; This structure models a given BDF/PCF property.","title":"BDF_PropertyRec"},{"location":"ft2-bdf_fonts.html#ft_get_bdf_charset_id","text":"Defined in FT_BDF_H (freetype/ftbdf.h). FT_EXPORT( FT_Error ) FT_Get_BDF_Charset_ID ( FT_Face face, const char * *acharset_encoding, const char * *acharset_registry ); Retrieve a BDF font character set identity, according to the BDF specification.","title":"FT_Get_BDF_Charset_ID"},{"location":"ft2-bdf_fonts.html#ft_get_bdf_property","text":"Defined in FT_BDF_H (freetype/ftbdf.h). FT_EXPORT( FT_Error ) FT_Get_BDF_Property ( FT_Face face, const char * prop_name, BDF_PropertyRec *aproperty ); Retrieve a BDF property from a BDF or PCF font file.","title":"FT_Get_BDF_Property"},{"location":"ft2-bitmap_handling.html","text":"FreeType \u00bb Docs \u00bb Support API \u00bb Bitmap Handling Bitmap Handling \u00b6 Synopsis \u00b6 This section contains functions for handling FT_Bitmap objects, automatically adjusting the target's bitmap buffer size as needed. Note that none of the functions changes the bitmap's \u2018flow\u2019 (as indicated by the sign of the pitch field in FT_Bitmap ). To set the flow, assign an appropriate positive or negative value to the pitch field of the target FT_Bitmap object after calling FT_Bitmap_Init but before calling any of the other functions described here. FT_Bitmap_Init \u00b6 Defined in FT_BITMAP_H (freetype/ftbitmap.h). FT_EXPORT( void ) FT_Bitmap_Init ( FT_Bitmap *abitmap ); /* deprecated */ FT_EXPORT( void ) FT_Bitmap_New( FT_Bitmap *abitmap ); Initialize a pointer to an FT_Bitmap structure. inout abitmap A pointer to the bitmap structure. note A deprecated name for the same function is FT_Bitmap_New . FT_Bitmap_Copy \u00b6 Defined in FT_BITMAP_H (freetype/ftbitmap.h). FT_EXPORT( FT_Error ) FT_Bitmap_Copy ( FT_Library library, const FT_Bitmap *source, FT_Bitmap *target ); Copy a bitmap into another one. input library A handle to a library object. source A handle to the source bitmap. output target A handle to the target bitmap. return FreeType error code. 0 means success. note source->buffer and target->buffer must neither be equal nor overlap. FT_Bitmap_Embolden \u00b6 Defined in FT_BITMAP_H (freetype/ftbitmap.h). FT_EXPORT( FT_Error ) FT_Bitmap_Embolden ( FT_Library library, FT_Bitmap * bitmap, FT_Pos xStrength, FT_Pos yStrength ); Embolden a bitmap. The new bitmap will be about xStrength pixels wider and yStrength pixels higher. The left and bottom borders are kept unchanged. input library A handle to a library object. xStrength How strong the glyph is emboldened horizontally. Expressed in 26.6 pixel format. yStrength How strong the glyph is emboldened vertically. Expressed in 26.6 pixel format. inout bitmap A handle to the target bitmap. return FreeType error code. 0 means success. note The current implementation restricts xStrength to be less than or equal to 8 if bitmap is of pixel_mode FT_PIXEL_MODE_MONO . If you want to embolden the bitmap owned by a FT_GlyphSlotRec , you should call FT_GlyphSlot_Own_Bitmap on the slot first. Bitmaps in FT_PIXEL_MODE_GRAY2 and FT_PIXEL_MODE_GRAY @ format are converted to FT_PIXEL_MODE_GRAY format (i.e., 8bpp). FT_Bitmap_Convert \u00b6 Defined in FT_BITMAP_H (freetype/ftbitmap.h). FT_EXPORT( FT_Error ) FT_Bitmap_Convert ( FT_Library library, const FT_Bitmap *source, FT_Bitmap *target, FT_Int alignment ); Convert a bitmap object with depth 1bpp, 2bpp, 4bpp, 8bpp or 32bpp to a bitmap object with depth 8bpp, making the number of used bytes per line (a.k.a. the \u2018pitch\u2019) a multiple of alignment . input library A handle to a library object. source The source bitmap. alignment The pitch of the bitmap is a multiple of this argument. Common values are 1, 2, or 4. output target The target bitmap. return FreeType error code. 0 means success. note It is possible to call FT_Bitmap_Convert multiple times without calling FT_Bitmap_Done (the memory is simply reallocated). Use FT_Bitmap_Done to finally remove the bitmap object. The library argument is taken to have access to FreeType's memory handling functions. source->buffer and target->buffer must neither be equal nor overlap. FT_Bitmap_Blend \u00b6 Defined in FT_BITMAP_H (freetype/ftbitmap.h). FT_EXPORT( FT_Error ) FT_Bitmap_Blend ( FT_Library library, const FT_Bitmap * source, const FT_Vector source_offset, FT_Bitmap * target, FT_Vector *atarget_offset, FT_Color color ); Blend a bitmap onto another bitmap, using a given color. input library A handle to a library object. source The source bitmap, which can have any FT_Pixel_Mode format. source_offset The offset vector to the upper left corner of the source bitmap in 26.6 pixel format. It should represent an integer offset; the function will set the lowest six bits to zero to enforce that. color The color used to draw source onto target . inout target A handle to an FT_Bitmap object. It should be either initialized as empty with a call to FT_Bitmap_Init , or it should be of type FT_PIXEL_MODE_BGRA . atarget_offset The offset vector to the upper left corner of the target bitmap in 26.6 pixel format. It should represent an integer offset; the function will set the lowest six bits to zero to enforce that. return FreeType error code. 0 means success. note This function doesn't perform clipping. The bitmap in target gets allocated or reallocated as needed; the vector atarget_offset is updated accordingly. In case of allocation or reallocation, the bitmap's pitch is set to 4 * width . Both source and target must have the same bitmap flow (as indicated by the sign of the pitch field). source->buffer and target->buffer must neither be equal nor overlap. since 2.10 FT_GlyphSlot_Own_Bitmap \u00b6 Defined in FT_BITMAP_H (freetype/ftbitmap.h). FT_EXPORT( FT_Error ) FT_GlyphSlot_Own_Bitmap ( FT_GlyphSlot slot ); Make sure that a glyph slot owns slot->bitmap . input slot The glyph slot. return FreeType error code. 0 means success. note This function is to be used in combination with FT_Bitmap_Embolden . FT_Bitmap_Done \u00b6 Defined in FT_BITMAP_H (freetype/ftbitmap.h). FT_EXPORT( FT_Error ) FT_Bitmap_Done ( FT_Library library, FT_Bitmap *bitmap ); Destroy a bitmap object initialized with FT_Bitmap_Init . input library A handle to a library object. bitmap The bitmap object to be freed. return FreeType error code. 0 means success. note The library argument is taken to have access to FreeType's memory handling functions.","title":"Bitmap Handling"},{"location":"ft2-bitmap_handling.html#bitmap-handling","text":"","title":"Bitmap Handling"},{"location":"ft2-bitmap_handling.html#synopsis","text":"This section contains functions for handling FT_Bitmap objects, automatically adjusting the target's bitmap buffer size as needed. Note that none of the functions changes the bitmap's \u2018flow\u2019 (as indicated by the sign of the pitch field in FT_Bitmap ). To set the flow, assign an appropriate positive or negative value to the pitch field of the target FT_Bitmap object after calling FT_Bitmap_Init but before calling any of the other functions described here.","title":"Synopsis"},{"location":"ft2-bitmap_handling.html#ft_bitmap_init","text":"Defined in FT_BITMAP_H (freetype/ftbitmap.h). FT_EXPORT( void ) FT_Bitmap_Init ( FT_Bitmap *abitmap ); /* deprecated */ FT_EXPORT( void ) FT_Bitmap_New( FT_Bitmap *abitmap ); Initialize a pointer to an FT_Bitmap structure.","title":"FT_Bitmap_Init"},{"location":"ft2-bitmap_handling.html#ft_bitmap_copy","text":"Defined in FT_BITMAP_H (freetype/ftbitmap.h). FT_EXPORT( FT_Error ) FT_Bitmap_Copy ( FT_Library library, const FT_Bitmap *source, FT_Bitmap *target ); Copy a bitmap into another one.","title":"FT_Bitmap_Copy"},{"location":"ft2-bitmap_handling.html#ft_bitmap_embolden","text":"Defined in FT_BITMAP_H (freetype/ftbitmap.h). FT_EXPORT( FT_Error ) FT_Bitmap_Embolden ( FT_Library library, FT_Bitmap * bitmap, FT_Pos xStrength, FT_Pos yStrength ); Embolden a bitmap. The new bitmap will be about xStrength pixels wider and yStrength pixels higher. The left and bottom borders are kept unchanged.","title":"FT_Bitmap_Embolden"},{"location":"ft2-bitmap_handling.html#ft_bitmap_convert","text":"Defined in FT_BITMAP_H (freetype/ftbitmap.h). FT_EXPORT( FT_Error ) FT_Bitmap_Convert ( FT_Library library, const FT_Bitmap *source, FT_Bitmap *target, FT_Int alignment ); Convert a bitmap object with depth 1bpp, 2bpp, 4bpp, 8bpp or 32bpp to a bitmap object with depth 8bpp, making the number of used bytes per line (a.k.a. the \u2018pitch\u2019) a multiple of alignment .","title":"FT_Bitmap_Convert"},{"location":"ft2-bitmap_handling.html#ft_bitmap_blend","text":"Defined in FT_BITMAP_H (freetype/ftbitmap.h). FT_EXPORT( FT_Error ) FT_Bitmap_Blend ( FT_Library library, const FT_Bitmap * source, const FT_Vector source_offset, FT_Bitmap * target, FT_Vector *atarget_offset, FT_Color color ); Blend a bitmap onto another bitmap, using a given color.","title":"FT_Bitmap_Blend"},{"location":"ft2-bitmap_handling.html#ft_glyphslot_own_bitmap","text":"Defined in FT_BITMAP_H (freetype/ftbitmap.h). FT_EXPORT( FT_Error ) FT_GlyphSlot_Own_Bitmap ( FT_GlyphSlot slot ); Make sure that a glyph slot owns slot->bitmap .","title":"FT_GlyphSlot_Own_Bitmap"},{"location":"ft2-bitmap_handling.html#ft_bitmap_done","text":"Defined in FT_BITMAP_H (freetype/ftbitmap.h). FT_EXPORT( FT_Error ) FT_Bitmap_Done ( FT_Library library, FT_Bitmap *bitmap ); Destroy a bitmap object initialized with FT_Bitmap_Init .","title":"FT_Bitmap_Done"},{"location":"ft2-bzip2.html","text":"FreeType \u00bb Docs \u00bb Support API \u00bb BZIP2 Streams BZIP2 Streams \u00b6 Synopsis \u00b6 In certain builds of the library, bzip2 compression recognition is automatically handled when calling FT_New_Face or FT_Open_Face . This means that if no font driver is capable of handling the raw compressed file, the library will try to open a bzip2 compressed stream from it and re-open the face with it. The stream implementation is very basic and resets the decompression process each time seeking backwards is needed within the stream, which significantly undermines the performance. This section contains the declaration of Bzip2-specific functions. FT_Stream_OpenBzip2 \u00b6 Defined in FT_BZIP2_H (freetype/ftbzip2.h). FT_EXPORT( FT_Error ) FT_Stream_OpenBzip2 ( FT_Stream stream, FT_Stream source ); Open a new stream to parse bzip2-compressed font files. This is mainly used to support the compressed *.pcf.bz2 fonts that come with XFree86. input stream The target embedding stream. source The source stream. return FreeType error code. 0 means success. note The source stream must be opened before calling this function. Calling the internal function FT_Stream_Close on the new stream will not call FT_Stream_Close on the source stream. None of the stream objects will be released to the heap. This function may return FT_Err_Unimplemented_Feature if your build of FreeType was not compiled with bzip2 support.","title":"BZIP2 Streams"},{"location":"ft2-bzip2.html#bzip2-streams","text":"","title":"BZIP2 Streams"},{"location":"ft2-bzip2.html#synopsis","text":"In certain builds of the library, bzip2 compression recognition is automatically handled when calling FT_New_Face or FT_Open_Face . This means that if no font driver is capable of handling the raw compressed file, the library will try to open a bzip2 compressed stream from it and re-open the face with it. The stream implementation is very basic and resets the decompression process each time seeking backwards is needed within the stream, which significantly undermines the performance. This section contains the declaration of Bzip2-specific functions.","title":"Synopsis"},{"location":"ft2-bzip2.html#ft_stream_openbzip2","text":"Defined in FT_BZIP2_H (freetype/ftbzip2.h). FT_EXPORT( FT_Error ) FT_Stream_OpenBzip2 ( FT_Stream stream, FT_Stream source ); Open a new stream to parse bzip2-compressed font files. This is mainly used to support the compressed *.pcf.bz2 fonts that come with XFree86.","title":"FT_Stream_OpenBzip2"},{"location":"ft2-cache_subsystem.html","text":"FreeType \u00bb Docs \u00bb Cache Sub-System \u00bb Cache Sub-System Cache Sub-System \u00b6 Synopsis \u00b6 This section describes the FreeType 2 cache sub-system, which is used to limit the number of concurrently opened FT_Face and FT_Size objects, as well as caching information like character maps and glyph images while limiting their maximum memory usage. Note that all types and functions begin with the FTC_ prefix. The cache is highly portable and thus doesn't know anything about the fonts installed on your system, or how to access them. This implies the following scheme: First, available or installed font faces are uniquely identified by FTC_FaceID values, provided to the cache by the client. Note that the cache only stores and compares these values, and doesn't try to interpret them in any way. Second, the cache calls, only when needed, a client-provided function to convert an FTC_FaceID into a new FT_Face object. The latter is then completely managed by the cache, including its termination through FT_Done_Face . To monitor termination of face objects, the finalizer callback in the generic field of the FT_Face object can be used, which might also be used to store the FTC_FaceID of the face. Clients are free to map face IDs to anything else. The most simple usage is to associate them to a (pathname,face_index) pair that is used to call FT_New_Face . However, more complex schemes are also possible. Note that for the cache to work correctly, the face ID values must be persistent , which means that the contents they point to should not change at runtime, or that their value should not become invalid. If this is unavoidable (e.g., when a font is uninstalled at runtime), you should call FTC_Manager_RemoveFaceID as soon as possible, to let the cache get rid of any references to the old FTC_FaceID it may keep internally. Failure to do so will lead to incorrect behaviour or even crashes. To use the cache, start with calling FTC_Manager_New to create a new FTC_Manager object, which models a single cache instance. You can then look up FT_Face and FT_Size objects with FTC_Manager_LookupFace and FTC_Manager_LookupSize , respectively. If you want to use the charmap caching, call FTC_CMapCache_New , then later use FTC_CMapCache_Lookup to perform the equivalent of FT_Get_Char_Index , only much faster. If you want to use the FT_Glyph caching, call FTC_ImageCache , then later use FTC_ImageCache_Lookup to retrieve the corresponding FT_Glyph objects from the cache. If you need lots of small bitmaps, it is much more memory efficient to call FTC_SBitCache_New followed by FTC_SBitCache_Lookup . This returns FTC_SBitRec structures, which are used to store small bitmaps directly. (A small bitmap is one whose metrics and dimensions all fit into 8-bit integers). We hope to also provide a kerning cache in the near future. FTC_Manager \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_ManagerRec_* FTC_Manager ; This object corresponds to one instance of the cache-subsystem. It is used to cache one or more FT_Face objects, along with corresponding FT_Size objects. The manager intentionally limits the total number of opened FT_Face and FT_Size objects to control memory usage. See the max_faces and max_sizes parameters of FTC_Manager_New . The manager is also used to cache \u2018nodes\u2019 of various types while limiting their total memory usage. All limitations are enforced by keeping lists of managed objects in most-recently-used order, and flushing old nodes to make room for new ones. FTC_FaceID \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). typedef FT_Pointer FTC_FaceID ; An opaque pointer type that is used to identity face objects. The contents of such objects is application-dependent. These pointers are typically used to point to a user-defined structure containing a font file path, and face index. note Never use NULL as a valid FTC_FaceID . Face IDs are passed by the client to the cache manager that calls, when needed, the FTC_Face_Requester to translate them into new FT_Face objects. If the content of a given face ID changes at runtime, or if the value becomes invalid (e.g., when uninstalling a font), you should immediately call FTC_Manager_RemoveFaceID before any other cache function. Failure to do so will result in incorrect behaviour or even memory leaks and crashes. FTC_Face_Requester \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). typedef FT_Error (* FTC_Face_Requester )( FTC_FaceID face_id, FT_Library library, FT_Pointer req_data, FT_Face * aface ); A callback function provided by client applications. It is used by the cache manager to translate a given FTC_FaceID into a new valid FT_Face object, on demand. input face_id The face ID to resolve. library A handle to a FreeType library object. req_data Application-provided request data (see note below). output aface A new FT_Face handle. return FreeType error code. 0 means success. note The third parameter req_data is the same as the one passed by the client when FTC_Manager_New is called. The face requester should not perform funny things on the returned face object, like creating a new FT_Size for it, or setting a transformation through FT_Set_Transform ! FTC_Manager_New \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_Manager_New ( FT_Library library, FT_UInt max_faces, FT_UInt max_sizes, FT_ULong max_bytes, FTC_Face_Requester requester, FT_Pointer req_data, FTC_Manager *amanager ); Create a new cache manager. input library The parent FreeType library handle to use. max_faces Maximum number of opened FT_Face objects managed by this cache instance. Use 0 for defaults. max_sizes Maximum number of opened FT_Size objects managed by this cache instance. Use 0 for defaults. max_bytes Maximum number of bytes to use for cached data nodes. Use 0 for defaults. Note that this value does not account for managed FT_Face and FT_Size objects. requester An application-provided callback used to translate face IDs into real FT_Face objects. req_data A generic pointer that is passed to the requester each time it is called (see FTC_Face_Requester ). output amanager A handle to a new manager object. 0 in case of failure. return FreeType error code. 0 means success. FTC_Manager_Reset \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( void ) FTC_Manager_Reset ( FTC_Manager manager ); Empty a given cache manager. This simply gets rid of all the currently cached FT_Face and FT_Size objects within the manager. inout manager A handle to the manager. FTC_Manager_Done \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( void ) FTC_Manager_Done ( FTC_Manager manager ); Destroy a given manager after emptying it. input manager A handle to the target cache manager object. FTC_Manager_LookupFace \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_Manager_LookupFace ( FTC_Manager manager, FTC_FaceID face_id, FT_Face *aface ); Retrieve the FT_Face object that corresponds to a given face ID through a cache manager. input manager A handle to the cache manager. face_id The ID of the face object. output aface A handle to the face object. return FreeType error code. 0 means success. note The returned FT_Face object is always owned by the manager. You should never try to discard it yourself. The FT_Face object doesn't necessarily have a current size object (i.e., face->size can be 0). If you need a specific \u2018font size\u2019, use FTC_Manager_LookupSize instead. Never change the face's transformation matrix (i.e., never call the FT_Set_Transform function) on a returned face! If you need to transform glyphs, do it yourself after glyph loading. When you perform a lookup, out-of-memory errors are detected within the lookup and force incremental flushes of the cache until enough memory is released for the lookup to succeed. If a lookup fails with FT_Err_Out_Of_Memory the cache has already been completely flushed, and still no memory was available for the operation. FTC_Manager_LookupSize \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_Manager_LookupSize ( FTC_Manager manager, FTC_Scaler scaler, FT_Size *asize ); Retrieve the FT_Size object that corresponds to a given FTC_ScalerRec pointer through a cache manager. input manager A handle to the cache manager. scaler A scaler handle. output asize A handle to the size object. return FreeType error code. 0 means success. note The returned FT_Size object is always owned by the manager. You should never try to discard it by yourself. You can access the parent FT_Face object simply as size->face if you need it. Note that this object is also owned by the manager. note When you perform a lookup, out-of-memory errors are detected within the lookup and force incremental flushes of the cache until enough memory is released for the lookup to succeed. If a lookup fails with FT_Err_Out_Of_Memory the cache has already been completely flushed, and still no memory is available for the operation. FTC_Manager_RemoveFaceID \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( void ) FTC_Manager_RemoveFaceID ( FTC_Manager manager, FTC_FaceID face_id ); A special function used to indicate to the cache manager that a given FTC_FaceID is no longer valid, either because its content changed, or because it was deallocated or uninstalled. input manager The cache manager handle. face_id The FTC_FaceID to be removed. note This function flushes all nodes from the cache corresponding to this face_id , with the exception of nodes with a non-null reference count. Such nodes are however modified internally so as to never appear in later lookups with the same face_id value, and to be immediately destroyed when released by all their users. FTC_Node \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_NodeRec_* FTC_Node ; An opaque handle to a cache node object. Each cache node is reference-counted. A node with a count of 0 might be flushed out of a full cache whenever a lookup request is performed. If you look up nodes, you have the ability to \u2018acquire\u2019 them, i.e., to increment their reference count. This will prevent the node from being flushed out of the cache until you explicitly \u2018release\u2019 it (see FTC_Node_Unref ). See also FTC_SBitCache_Lookup and FTC_ImageCache_Lookup . FTC_Node_Unref \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( void ) FTC_Node_Unref ( FTC_Node node, FTC_Manager manager ); Decrement a cache node's internal reference count. When the count reaches 0, it is not destroyed but becomes eligible for subsequent cache flushes. input node The cache node handle. manager The cache manager handle. FTC_ImageCache \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_ImageCacheRec_* FTC_ImageCache ; A handle to a glyph image cache object. They are designed to hold many distinct glyph images while not exceeding a certain memory threshold. FTC_ImageCache_New \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_ImageCache_New ( FTC_Manager manager, FTC_ImageCache *acache ); Create a new glyph image cache. input manager The parent manager for the image cache. output acache A handle to the new glyph image cache object. return FreeType error code. 0 means success. FTC_ImageCache_Lookup \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_ImageCache_Lookup ( FTC_ImageCache cache, FTC_ImageType type, FT_UInt gindex, FT_Glyph *aglyph, FTC_Node *anode ); Retrieve a given glyph image from a glyph image cache. input cache A handle to the source glyph image cache. type A pointer to a glyph image type descriptor. gindex The glyph index to retrieve. output aglyph The corresponding FT_Glyph object. 0 in case of failure. anode Used to return the address of the corresponding cache node after incrementing its reference count (see note below). return FreeType error code. 0 means success. note The returned glyph is owned and managed by the glyph image cache. Never try to transform or discard it manually! You can however create a copy with FT_Glyph_Copy and modify the new one. If anode is not NULL , it receives the address of the cache node containing the glyph image, after increasing its reference count. This ensures that the node (as well as the FT_Glyph ) will always be kept in the cache until you call FTC_Node_Unref to \u2018release\u2019 it. If anode is NULL , the cache node is left unchanged, which means that the FT_Glyph could be flushed out of the cache on the next call to one of the caching sub-system APIs. Don't assume that it is persistent! FTC_SBit \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_SBitRec_* FTC_SBit ; A handle to a small bitmap descriptor. See the FTC_SBitRec structure for details. FTC_SBitCache \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_SBitCacheRec_* FTC_SBitCache ; A handle to a small bitmap cache. These are special cache objects used to store small glyph bitmaps (and anti-aliased pixmaps) in a much more efficient way than the traditional glyph image cache implemented by FTC_ImageCache . FTC_SBitCache_New \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_SBitCache_New ( FTC_Manager manager, FTC_SBitCache *acache ); Create a new cache to store small glyph bitmaps. input manager A handle to the source cache manager. output acache A handle to the new sbit cache. NULL in case of error. return FreeType error code. 0 means success. FTC_SBitCache_Lookup \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_SBitCache_Lookup ( FTC_SBitCache cache, FTC_ImageType type, FT_UInt gindex, FTC_SBit *sbit, FTC_Node *anode ); Look up a given small glyph bitmap in a given sbit cache and \u2018lock\u2019 it to prevent its flushing from the cache until needed. input cache A handle to the source sbit cache. type A pointer to the glyph image type descriptor. gindex The glyph index. output sbit A handle to a small bitmap descriptor. anode Used to return the address of the corresponding cache node after incrementing its reference count (see note below). return FreeType error code. 0 means success. note The small bitmap descriptor and its bit buffer are owned by the cache and should never be freed by the application. They might as well disappear from memory on the next cache lookup, so don't treat them as persistent data. The descriptor's buffer field is set to 0 to indicate a missing glyph bitmap. If anode is not NULL , it receives the address of the cache node containing the bitmap, after increasing its reference count. This ensures that the node (as well as the image) will always be kept in the cache until you call FTC_Node_Unref to \u2018release\u2019 it. If anode is NULL , the cache node is left unchanged, which means that the bitmap could be flushed out of the cache on the next call to one of the caching sub-system APIs. Don't assume that it is persistent! FTC_CMapCache \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_CMapCacheRec_* FTC_CMapCache ; An opaque handle used to model a charmap cache. This cache is to hold character codes -> glyph indices mappings. FTC_CMapCache_New \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_CMapCache_New ( FTC_Manager manager, FTC_CMapCache *acache ); Create a new charmap cache. input manager A handle to the cache manager. output acache A new cache handle. NULL in case of error. return FreeType error code. 0 means success. note Like all other caches, this one will be destroyed with the cache manager. FTC_CMapCache_Lookup \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_UInt ) FTC_CMapCache_Lookup ( FTC_CMapCache cache, FTC_FaceID face_id, FT_Int cmap_index, FT_UInt32 char_code ); Translate a character code into a glyph index, using the charmap cache. input cache A charmap cache handle. face_id The source face ID. cmap_index The index of the charmap in the source face. Any negative value means to use the cache FT_Face 's default charmap. char_code The character code (in the corresponding charmap). return Glyph index. 0 means \u2018no glyph\u2019. FTC_ScalerRec \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_ScalerRec_ { FTC_FaceID face_id; FT_UInt width; FT_UInt height; FT_Int pixel; FT_UInt x_res; FT_UInt y_res; } FTC_ScalerRec ; A structure used to describe a given character size in either pixels or points to the cache manager. See FTC_Manager_LookupSize . fields face_id The source face ID. width The character width. height The character height. pixel A Boolean. If 1, the width and height fields are interpreted as integer pixel character sizes. Otherwise, they are expressed as 1/64th of points. x_res Only used when pixel is value 0 to indicate the horizontal resolution in dpi. y_res Only used when pixel is value 0 to indicate the vertical resolution in dpi. note This type is mainly used to retrieve FT_Size objects through the cache manager. FTC_Scaler \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_ScalerRec_* FTC_Scaler ; A handle to an FTC_ScalerRec structure. FTC_ImageTypeRec \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_ImageTypeRec_ { FTC_FaceID face_id; FT_UInt width; FT_UInt height; FT_Int32 flags; } FTC_ImageTypeRec ; A structure used to model the type of images in a glyph cache. fields face_id The face ID. width The width in pixels. height The height in pixels. flags The load flags, as in FT_Load_Glyph . FTC_ImageType \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_ImageTypeRec_* FTC_ImageType ; A handle to an FTC_ImageTypeRec structure. FTC_ImageCache_LookupScaler \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_ImageCache_LookupScaler ( FTC_ImageCache cache, FTC_Scaler scaler, FT_ULong load_flags, FT_UInt gindex, FT_Glyph *aglyph, FTC_Node *anode ); A variant of FTC_ImageCache_Lookup that uses an FTC_ScalerRec to specify the face ID and its size. input cache A handle to the source glyph image cache. scaler A pointer to a scaler descriptor. load_flags The corresponding load flags. gindex The glyph index to retrieve. output aglyph The corresponding FT_Glyph object. 0 in case of failure. anode Used to return the address of the corresponding cache node after incrementing its reference count (see note below). return FreeType error code. 0 means success. note The returned glyph is owned and managed by the glyph image cache. Never try to transform or discard it manually! You can however create a copy with FT_Glyph_Copy and modify the new one. If anode is not NULL , it receives the address of the cache node containing the glyph image, after increasing its reference count. This ensures that the node (as well as the FT_Glyph ) will always be kept in the cache until you call FTC_Node_Unref to \u2018release\u2019 it. If anode is NULL , the cache node is left unchanged, which means that the FT_Glyph could be flushed out of the cache on the next call to one of the caching sub-system APIs. Don't assume that it is persistent! Calls to FT_Set_Char_Size and friends have no effect on cached glyphs; you should always use the FreeType cache API instead. FTC_SBitRec \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_SBitRec_ { FT_Byte width; FT_Byte height; FT_Char left; FT_Char top; FT_Byte format; FT_Byte max_grays; FT_Short pitch; FT_Char xadvance; FT_Char yadvance; FT_Byte * buffer; } FTC_SBitRec ; A very compact structure used to describe a small glyph bitmap. fields width The bitmap width in pixels. height The bitmap height in pixels. left The horizontal distance from the pen position to the left bitmap border (a.k.a. \u2018left side bearing\u2019, or \u2018lsb\u2019). top The vertical distance from the pen position (on the baseline) to the upper bitmap border (a.k.a. \u2018top side bearing\u2019). The distance is positive for upwards y coordinates. format The format of the glyph bitmap (monochrome or gray). max_grays Maximum gray level value (in the range 1 to 255). pitch The number of bytes per bitmap line. May be positive or negative. xadvance The horizontal advance width in pixels. yadvance The vertical advance height in pixels. buffer A pointer to the bitmap pixels. FTC_SBitCache_LookupScaler \u00b6 Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_SBitCache_LookupScaler ( FTC_SBitCache cache, FTC_Scaler scaler, FT_ULong load_flags, FT_UInt gindex, FTC_SBit *sbit, FTC_Node *anode ); A variant of FTC_SBitCache_Lookup that uses an FTC_ScalerRec to specify the face ID and its size. input cache A handle to the source sbit cache. scaler A pointer to the scaler descriptor. load_flags The corresponding load flags. gindex The glyph index. output sbit A handle to a small bitmap descriptor. anode Used to return the address of the corresponding cache node after incrementing its reference count (see note below). return FreeType error code. 0 means success. note The small bitmap descriptor and its bit buffer are owned by the cache and should never be freed by the application. They might as well disappear from memory on the next cache lookup, so don't treat them as persistent data. The descriptor's buffer field is set to 0 to indicate a missing glyph bitmap. If anode is not NULL , it receives the address of the cache node containing the bitmap, after increasing its reference count. This ensures that the node (as well as the image) will always be kept in the cache until you call FTC_Node_Unref to \u2018release\u2019 it. If anode is NULL , the cache node is left unchanged, which means that the bitmap could be flushed out of the cache on the next call to one of the caching sub-system APIs. Don't assume that it is persistent!","title":"Cache Sub-System"},{"location":"ft2-cache_subsystem.html#cache-sub-system","text":"","title":"Cache Sub-System"},{"location":"ft2-cache_subsystem.html#synopsis","text":"This section describes the FreeType 2 cache sub-system, which is used to limit the number of concurrently opened FT_Face and FT_Size objects, as well as caching information like character maps and glyph images while limiting their maximum memory usage. Note that all types and functions begin with the FTC_ prefix. The cache is highly portable and thus doesn't know anything about the fonts installed on your system, or how to access them. This implies the following scheme: First, available or installed font faces are uniquely identified by FTC_FaceID values, provided to the cache by the client. Note that the cache only stores and compares these values, and doesn't try to interpret them in any way. Second, the cache calls, only when needed, a client-provided function to convert an FTC_FaceID into a new FT_Face object. The latter is then completely managed by the cache, including its termination through FT_Done_Face . To monitor termination of face objects, the finalizer callback in the generic field of the FT_Face object can be used, which might also be used to store the FTC_FaceID of the face. Clients are free to map face IDs to anything else. The most simple usage is to associate them to a (pathname,face_index) pair that is used to call FT_New_Face . However, more complex schemes are also possible. Note that for the cache to work correctly, the face ID values must be persistent , which means that the contents they point to should not change at runtime, or that their value should not become invalid. If this is unavoidable (e.g., when a font is uninstalled at runtime), you should call FTC_Manager_RemoveFaceID as soon as possible, to let the cache get rid of any references to the old FTC_FaceID it may keep internally. Failure to do so will lead to incorrect behaviour or even crashes. To use the cache, start with calling FTC_Manager_New to create a new FTC_Manager object, which models a single cache instance. You can then look up FT_Face and FT_Size objects with FTC_Manager_LookupFace and FTC_Manager_LookupSize , respectively. If you want to use the charmap caching, call FTC_CMapCache_New , then later use FTC_CMapCache_Lookup to perform the equivalent of FT_Get_Char_Index , only much faster. If you want to use the FT_Glyph caching, call FTC_ImageCache , then later use FTC_ImageCache_Lookup to retrieve the corresponding FT_Glyph objects from the cache. If you need lots of small bitmaps, it is much more memory efficient to call FTC_SBitCache_New followed by FTC_SBitCache_Lookup . This returns FTC_SBitRec structures, which are used to store small bitmaps directly. (A small bitmap is one whose metrics and dimensions all fit into 8-bit integers). We hope to also provide a kerning cache in the near future.","title":"Synopsis"},{"location":"ft2-cache_subsystem.html#ftc_manager","text":"Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_ManagerRec_* FTC_Manager ; This object corresponds to one instance of the cache-subsystem. It is used to cache one or more FT_Face objects, along with corresponding FT_Size objects. The manager intentionally limits the total number of opened FT_Face and FT_Size objects to control memory usage. See the max_faces and max_sizes parameters of FTC_Manager_New . The manager is also used to cache \u2018nodes\u2019 of various types while limiting their total memory usage. All limitations are enforced by keeping lists of managed objects in most-recently-used order, and flushing old nodes to make room for new ones.","title":"FTC_Manager"},{"location":"ft2-cache_subsystem.html#ftc_faceid","text":"Defined in FT_CACHE_H (freetype/ftcache.h). typedef FT_Pointer FTC_FaceID ; An opaque pointer type that is used to identity face objects. The contents of such objects is application-dependent. These pointers are typically used to point to a user-defined structure containing a font file path, and face index.","title":"FTC_FaceID"},{"location":"ft2-cache_subsystem.html#ftc_face_requester","text":"Defined in FT_CACHE_H (freetype/ftcache.h). typedef FT_Error (* FTC_Face_Requester )( FTC_FaceID face_id, FT_Library library, FT_Pointer req_data, FT_Face * aface ); A callback function provided by client applications. It is used by the cache manager to translate a given FTC_FaceID into a new valid FT_Face object, on demand.","title":"FTC_Face_Requester"},{"location":"ft2-cache_subsystem.html#ftc_manager_new","text":"Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_Manager_New ( FT_Library library, FT_UInt max_faces, FT_UInt max_sizes, FT_ULong max_bytes, FTC_Face_Requester requester, FT_Pointer req_data, FTC_Manager *amanager ); Create a new cache manager.","title":"FTC_Manager_New"},{"location":"ft2-cache_subsystem.html#ftc_manager_reset","text":"Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( void ) FTC_Manager_Reset ( FTC_Manager manager ); Empty a given cache manager. This simply gets rid of all the currently cached FT_Face and FT_Size objects within the manager.","title":"FTC_Manager_Reset"},{"location":"ft2-cache_subsystem.html#ftc_manager_done","text":"Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( void ) FTC_Manager_Done ( FTC_Manager manager ); Destroy a given manager after emptying it.","title":"FTC_Manager_Done"},{"location":"ft2-cache_subsystem.html#ftc_manager_lookupface","text":"Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_Manager_LookupFace ( FTC_Manager manager, FTC_FaceID face_id, FT_Face *aface ); Retrieve the FT_Face object that corresponds to a given face ID through a cache manager.","title":"FTC_Manager_LookupFace"},{"location":"ft2-cache_subsystem.html#ftc_manager_lookupsize","text":"Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_Manager_LookupSize ( FTC_Manager manager, FTC_Scaler scaler, FT_Size *asize ); Retrieve the FT_Size object that corresponds to a given FTC_ScalerRec pointer through a cache manager.","title":"FTC_Manager_LookupSize"},{"location":"ft2-cache_subsystem.html#ftc_manager_removefaceid","text":"Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( void ) FTC_Manager_RemoveFaceID ( FTC_Manager manager, FTC_FaceID face_id ); A special function used to indicate to the cache manager that a given FTC_FaceID is no longer valid, either because its content changed, or because it was deallocated or uninstalled.","title":"FTC_Manager_RemoveFaceID"},{"location":"ft2-cache_subsystem.html#ftc_node","text":"Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_NodeRec_* FTC_Node ; An opaque handle to a cache node object. Each cache node is reference-counted. A node with a count of 0 might be flushed out of a full cache whenever a lookup request is performed. If you look up nodes, you have the ability to \u2018acquire\u2019 them, i.e., to increment their reference count. This will prevent the node from being flushed out of the cache until you explicitly \u2018release\u2019 it (see FTC_Node_Unref ). See also FTC_SBitCache_Lookup and FTC_ImageCache_Lookup .","title":"FTC_Node"},{"location":"ft2-cache_subsystem.html#ftc_node_unref","text":"Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( void ) FTC_Node_Unref ( FTC_Node node, FTC_Manager manager ); Decrement a cache node's internal reference count. When the count reaches 0, it is not destroyed but becomes eligible for subsequent cache flushes.","title":"FTC_Node_Unref"},{"location":"ft2-cache_subsystem.html#ftc_imagecache","text":"Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_ImageCacheRec_* FTC_ImageCache ; A handle to a glyph image cache object. They are designed to hold many distinct glyph images while not exceeding a certain memory threshold.","title":"FTC_ImageCache"},{"location":"ft2-cache_subsystem.html#ftc_imagecache_new","text":"Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_ImageCache_New ( FTC_Manager manager, FTC_ImageCache *acache ); Create a new glyph image cache.","title":"FTC_ImageCache_New"},{"location":"ft2-cache_subsystem.html#ftc_imagecache_lookup","text":"Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_ImageCache_Lookup ( FTC_ImageCache cache, FTC_ImageType type, FT_UInt gindex, FT_Glyph *aglyph, FTC_Node *anode ); Retrieve a given glyph image from a glyph image cache.","title":"FTC_ImageCache_Lookup"},{"location":"ft2-cache_subsystem.html#ftc_sbit","text":"Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_SBitRec_* FTC_SBit ; A handle to a small bitmap descriptor. See the FTC_SBitRec structure for details.","title":"FTC_SBit"},{"location":"ft2-cache_subsystem.html#ftc_sbitcache","text":"Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_SBitCacheRec_* FTC_SBitCache ; A handle to a small bitmap cache. These are special cache objects used to store small glyph bitmaps (and anti-aliased pixmaps) in a much more efficient way than the traditional glyph image cache implemented by FTC_ImageCache .","title":"FTC_SBitCache"},{"location":"ft2-cache_subsystem.html#ftc_sbitcache_new","text":"Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_SBitCache_New ( FTC_Manager manager, FTC_SBitCache *acache ); Create a new cache to store small glyph bitmaps.","title":"FTC_SBitCache_New"},{"location":"ft2-cache_subsystem.html#ftc_sbitcache_lookup","text":"Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_SBitCache_Lookup ( FTC_SBitCache cache, FTC_ImageType type, FT_UInt gindex, FTC_SBit *sbit, FTC_Node *anode ); Look up a given small glyph bitmap in a given sbit cache and \u2018lock\u2019 it to prevent its flushing from the cache until needed.","title":"FTC_SBitCache_Lookup"},{"location":"ft2-cache_subsystem.html#ftc_cmapcache","text":"Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_CMapCacheRec_* FTC_CMapCache ; An opaque handle used to model a charmap cache. This cache is to hold character codes -> glyph indices mappings.","title":"FTC_CMapCache"},{"location":"ft2-cache_subsystem.html#ftc_cmapcache_new","text":"Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_CMapCache_New ( FTC_Manager manager, FTC_CMapCache *acache ); Create a new charmap cache.","title":"FTC_CMapCache_New"},{"location":"ft2-cache_subsystem.html#ftc_cmapcache_lookup","text":"Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_UInt ) FTC_CMapCache_Lookup ( FTC_CMapCache cache, FTC_FaceID face_id, FT_Int cmap_index, FT_UInt32 char_code ); Translate a character code into a glyph index, using the charmap cache.","title":"FTC_CMapCache_Lookup"},{"location":"ft2-cache_subsystem.html#ftc_scalerrec","text":"Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_ScalerRec_ { FTC_FaceID face_id; FT_UInt width; FT_UInt height; FT_Int pixel; FT_UInt x_res; FT_UInt y_res; } FTC_ScalerRec ; A structure used to describe a given character size in either pixels or points to the cache manager. See FTC_Manager_LookupSize .","title":"FTC_ScalerRec"},{"location":"ft2-cache_subsystem.html#ftc_scaler","text":"Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_ScalerRec_* FTC_Scaler ; A handle to an FTC_ScalerRec structure.","title":"FTC_Scaler"},{"location":"ft2-cache_subsystem.html#ftc_imagetyperec","text":"Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_ImageTypeRec_ { FTC_FaceID face_id; FT_UInt width; FT_UInt height; FT_Int32 flags; } FTC_ImageTypeRec ; A structure used to model the type of images in a glyph cache.","title":"FTC_ImageTypeRec"},{"location":"ft2-cache_subsystem.html#ftc_imagetype","text":"Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_ImageTypeRec_* FTC_ImageType ; A handle to an FTC_ImageTypeRec structure.","title":"FTC_ImageType"},{"location":"ft2-cache_subsystem.html#ftc_imagecache_lookupscaler","text":"Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_ImageCache_LookupScaler ( FTC_ImageCache cache, FTC_Scaler scaler, FT_ULong load_flags, FT_UInt gindex, FT_Glyph *aglyph, FTC_Node *anode ); A variant of FTC_ImageCache_Lookup that uses an FTC_ScalerRec to specify the face ID and its size.","title":"FTC_ImageCache_LookupScaler"},{"location":"ft2-cache_subsystem.html#ftc_sbitrec","text":"Defined in FT_CACHE_H (freetype/ftcache.h). typedef struct FTC_SBitRec_ { FT_Byte width; FT_Byte height; FT_Char left; FT_Char top; FT_Byte format; FT_Byte max_grays; FT_Short pitch; FT_Char xadvance; FT_Char yadvance; FT_Byte * buffer; } FTC_SBitRec ; A very compact structure used to describe a small glyph bitmap.","title":"FTC_SBitRec"},{"location":"ft2-cache_subsystem.html#ftc_sbitcache_lookupscaler","text":"Defined in FT_CACHE_H (freetype/ftcache.h). FT_EXPORT( FT_Error ) FTC_SBitCache_LookupScaler ( FTC_SBitCache cache, FTC_Scaler scaler, FT_ULong load_flags, FT_UInt gindex, FTC_SBit *sbit, FTC_Node *anode ); A variant of FTC_SBitCache_Lookup that uses an FTC_ScalerRec to specify the face ID and its size.","title":"FTC_SBitCache_LookupScaler"},{"location":"ft2-cff_driver.html","text":"FreeType \u00bb Docs \u00bb Controlling FreeType Modules \u00bb The CFF driver The CFF driver \u00b6 Synopsis \u00b6 While FreeType's CFF driver doesn't expose API functions by itself, it is possible to control its behaviour with FT_Property_Set and FT_Property_Get . The CFF driver's module name is \u2018cff\u2019. Available properties are hinting-engine , no-stem-darkening , darkening-parameters , and random-seed , as documented in the \u2018 Driver properties \u2019 section. Hinting and antialiasing principles of the new engine The rasterizer is positioning horizontal features (e.g., ascender height & x-height, or crossbars) on the pixel grid and minimizing the amount of antialiasing applied to them, while placing vertical features (vertical stems) on the pixel grid without hinting, thus representing the stem position and weight accurately. Sometimes the vertical stems may be only partially black. In this context, \u2018antialiasing\u2019 means that stems are not positioned exactly on pixel borders, causing a fuzzy appearance. There are two principles behind this approach. 1) No hinting in the horizontal direction: Unlike \u2018superhinted\u2019 TrueType, which changes glyph widths to accommodate regular inter-glyph spacing, Adobe's approach is \u2018faithful to the design\u2019 in representing both the glyph width and the inter-glyph spacing designed for the font. This makes the screen display as close as it can be to the result one would get with infinite resolution, while preserving what is considered the key characteristics of each glyph. Note that the distances between unhinted and grid-fitted positions at small sizes are comparable to kerning values and thus would be noticeable (and distracting) while reading if hinting were applied. One of the reasons to not hint horizontally is antialiasing for LCD screens: The pixel geometry of modern displays supplies three vertical subpixels as the eye moves horizontally across each visible pixel. On devices where we can be certain this characteristic is present a rasterizer can take advantage of the subpixels to add increments of weight. In Western writing systems this turns out to be the more critical direction anyway; the weights and spacing of vertical stems (see above) are central to Armenian, Cyrillic, Greek, and Latin type designs. Even when the rasterizer uses greyscale antialiasing instead of color (a necessary compromise when one doesn't know the screen characteristics), the unhinted vertical features preserve the design's weight and spacing much better than aliased type would. 2) Alignment in the vertical direction: Weights and spacing along the y axis are less critical; what is much more important is the visual alignment of related features (like cap-height and x-height). The sense of alignment for these is enhanced by the sharpness of grid-fit edges, while the cruder vertical resolution (full pixels instead of \u2153 pixels) is less of a problem. On the technical side, horizontal alignment zones for ascender, x-height, and other important height values (traditionally called \u2018blue zones\u2019) as defined in the font are positioned independently, each being rounded to the nearest pixel edge, taking care of overshoot suppression at small sizes, stem darkening, and scaling. Hstems (this is, hint values defined in the font to help align horizontal features) that fall within a blue zone are said to be \u2018captured\u2019 and are aligned to that zone. Uncaptured stems are moved in one of four ways, top edge up or down, bottom edge up or down. Unless there are conflicting hstems, the smallest movement is taken to minimize distortion.","title":"The CFF driver"},{"location":"ft2-cff_driver.html#the-cff-driver","text":"","title":"The CFF driver"},{"location":"ft2-cff_driver.html#synopsis","text":"While FreeType's CFF driver doesn't expose API functions by itself, it is possible to control its behaviour with FT_Property_Set and FT_Property_Get . The CFF driver's module name is \u2018cff\u2019. Available properties are hinting-engine , no-stem-darkening , darkening-parameters , and random-seed , as documented in the \u2018 Driver properties \u2019 section. Hinting and antialiasing principles of the new engine The rasterizer is positioning horizontal features (e.g., ascender height & x-height, or crossbars) on the pixel grid and minimizing the amount of antialiasing applied to them, while placing vertical features (vertical stems) on the pixel grid without hinting, thus representing the stem position and weight accurately. Sometimes the vertical stems may be only partially black. In this context, \u2018antialiasing\u2019 means that stems are not positioned exactly on pixel borders, causing a fuzzy appearance. There are two principles behind this approach. 1) No hinting in the horizontal direction: Unlike \u2018superhinted\u2019 TrueType, which changes glyph widths to accommodate regular inter-glyph spacing, Adobe's approach is \u2018faithful to the design\u2019 in representing both the glyph width and the inter-glyph spacing designed for the font. This makes the screen display as close as it can be to the result one would get with infinite resolution, while preserving what is considered the key characteristics of each glyph. Note that the distances between unhinted and grid-fitted positions at small sizes are comparable to kerning values and thus would be noticeable (and distracting) while reading if hinting were applied. One of the reasons to not hint horizontally is antialiasing for LCD screens: The pixel geometry of modern displays supplies three vertical subpixels as the eye moves horizontally across each visible pixel. On devices where we can be certain this characteristic is present a rasterizer can take advantage of the subpixels to add increments of weight. In Western writing systems this turns out to be the more critical direction anyway; the weights and spacing of vertical stems (see above) are central to Armenian, Cyrillic, Greek, and Latin type designs. Even when the rasterizer uses greyscale antialiasing instead of color (a necessary compromise when one doesn't know the screen characteristics), the unhinted vertical features preserve the design's weight and spacing much better than aliased type would. 2) Alignment in the vertical direction: Weights and spacing along the y axis are less critical; what is much more important is the visual alignment of related features (like cap-height and x-height). The sense of alignment for these is enhanced by the sharpness of grid-fit edges, while the cruder vertical resolution (full pixels instead of \u2153 pixels) is less of a problem. On the technical side, horizontal alignment zones for ascender, x-height, and other important height values (traditionally called \u2018blue zones\u2019) as defined in the font are positioned independently, each being rounded to the nearest pixel edge, taking care of overshoot suppression at small sizes, stem darkening, and scaling. Hstems (this is, hint values defined in the font to help align horizontal features) that fall within a blue zone are said to be \u2018captured\u2019 and are aligned to that zone. Uncaptured stems are moved in one of four ways, top edge up or down, bottom edge up or down. Unless there are conflicting hstems, the smallest movement is taken to minimize distortion.","title":"Synopsis"},{"location":"ft2-cid_fonts.html","text":"FreeType \u00bb Docs \u00bb Format-Specific API \u00bb CID Fonts CID Fonts \u00b6 Synopsis \u00b6 This section contains the declaration of CID-keyed font-specific functions. FT_Get_CID_Registry_Ordering_Supplement \u00b6 Defined in FT_CID_H (freetype/ftcid.h). FT_EXPORT( FT_Error ) FT_Get_CID_Registry_Ordering_Supplement ( FT_Face face, const char * *registry, const char * *ordering, FT_Int *supplement ); Retrieve the Registry/Ordering/Supplement triple (also known as the \"R/O/S\") from a CID-keyed font. input face A handle to the input face. output registry The registry, as a C string, owned by the face. ordering The ordering, as a C string, owned by the face. supplement The supplement. return FreeType error code. 0 means success. note This function only works with CID faces, returning an error otherwise. since 2.3.6 FT_Get_CID_Is_Internally_CID_Keyed \u00b6 Defined in FT_CID_H (freetype/ftcid.h). FT_EXPORT( FT_Error ) FT_Get_CID_Is_Internally_CID_Keyed ( FT_Face face, FT_Bool *is_cid ); Retrieve the type of the input face, CID keyed or not. In contrast to the FT_IS_CID_KEYED macro this function returns successfully also for CID-keyed fonts in an SFNT wrapper. input face A handle to the input face. output is_cid The type of the face as an FT_Bool . return FreeType error code. 0 means success. note This function only works with CID faces and OpenType fonts, returning an error otherwise. since 2.3.9 FT_Get_CID_From_Glyph_Index \u00b6 Defined in FT_CID_H (freetype/ftcid.h). FT_EXPORT( FT_Error ) FT_Get_CID_From_Glyph_Index ( FT_Face face, FT_UInt glyph_index, FT_UInt *cid ); Retrieve the CID of the input glyph index. input face A handle to the input face. glyph_index The input glyph index. output cid The CID as an FT_UInt . return FreeType error code. 0 means success. note This function only works with CID faces and OpenType fonts, returning an error otherwise. since 2.3.9","title":"CID Fonts"},{"location":"ft2-cid_fonts.html#cid-fonts","text":"","title":"CID Fonts"},{"location":"ft2-cid_fonts.html#synopsis","text":"This section contains the declaration of CID-keyed font-specific functions.","title":"Synopsis"},{"location":"ft2-cid_fonts.html#ft_get_cid_registry_ordering_supplement","text":"Defined in FT_CID_H (freetype/ftcid.h). FT_EXPORT( FT_Error ) FT_Get_CID_Registry_Ordering_Supplement ( FT_Face face, const char * *registry, const char * *ordering, FT_Int *supplement ); Retrieve the Registry/Ordering/Supplement triple (also known as the \"R/O/S\") from a CID-keyed font.","title":"FT_Get_CID_Registry_Ordering_Supplement"},{"location":"ft2-cid_fonts.html#ft_get_cid_is_internally_cid_keyed","text":"Defined in FT_CID_H (freetype/ftcid.h). FT_EXPORT( FT_Error ) FT_Get_CID_Is_Internally_CID_Keyed ( FT_Face face, FT_Bool *is_cid ); Retrieve the type of the input face, CID keyed or not. In contrast to the FT_IS_CID_KEYED macro this function returns successfully also for CID-keyed fonts in an SFNT wrapper.","title":"FT_Get_CID_Is_Internally_CID_Keyed"},{"location":"ft2-cid_fonts.html#ft_get_cid_from_glyph_index","text":"Defined in FT_CID_H (freetype/ftcid.h). FT_EXPORT( FT_Error ) FT_Get_CID_From_Glyph_Index ( FT_Face face, FT_UInt glyph_index, FT_UInt *cid ); Retrieve the CID of the input glyph index.","title":"FT_Get_CID_From_Glyph_Index"},{"location":"ft2-color_management.html","text":"FreeType \u00bb Docs \u00bb Core API \u00bb Glyph Color Management Glyph Color Management \u00b6 Synopsis \u00b6 The functions described here allow access and manipulation of color palette entries in OpenType's \u2018CPAL\u2019 tables. FT_Color \u00b6 Defined in FT_COLOR_H (freetype/ftcolor.h). typedef struct FT_Color_ { FT_Byte blue; FT_Byte green; FT_Byte red; FT_Byte alpha; } FT_Color ; This structure models a BGRA color value of a \u2018CPAL\u2019 palette entry. The used color space is sRGB; the colors are not pre-multiplied, and alpha values must be explicitly set. fields blue Blue value. green Green value. red Red value. alpha Alpha value, giving the red, green, and blue color's opacity. since 2.10 FT_PALETTE_XXX \u00b6 Defined in FT_COLOR_H (freetype/ftcolor.h). # define FT_PALETTE_FOR_LIGHT_BACKGROUND 0x01 # define FT_PALETTE_FOR_DARK_BACKGROUND 0x02 A list of bit field constants used in the palette_flags array of the FT_Palette_Data structure to indicate for which background a palette with a given index is usable. values FT_PALETTE_FOR_LIGHT_BACKGROUND The palette is appropriate to use when displaying the font on a light background such as white. FT_PALETTE_FOR_DARK_BACKGROUND The palette is appropriate to use when displaying the font on a dark background such as black. since 2.10 FT_Palette_Data \u00b6 Defined in FT_COLOR_H (freetype/ftcolor.h). typedef struct FT_Palette_Data_ { FT_UShort num_palettes; const FT_UShort * palette_name_ids; const FT_UShort * palette_flags; FT_UShort num_palette_entries; const FT_UShort * palette_entry_name_ids; } FT_Palette_Data ; This structure holds the data of the \u2018CPAL\u2019 table. fields num_palettes The number of palettes. palette_name_ids An optional read-only array of palette name IDs with num_palettes elements, corresponding to entries like \u2018dark\u2019 or \u2018light\u2019 in the font's \u2018name\u2019 table. An empty name ID in the \u2018CPAL\u2019 table gets represented as value 0xFFFF. NULL if the font's \u2018CPAL\u2019 table doesn't contain appropriate data. palette_flags An optional read-only array of palette flags with num_palettes elements. Possible values are an ORed combination of FT_PALETTE_FOR_LIGHT_BACKGROUND and FT_PALETTE_FOR_DARK_BACKGROUND . NULL if the font's \u2018CPAL\u2019 table doesn't contain appropriate data. num_palette_entries The number of entries in a single palette. All palettes have the same size. palette_entry_name_ids An optional read-only array of palette entry name IDs with num_palette_entries . In each palette, entries with the same index have the same function. For example, index 0 might correspond to string \u2018outline\u2019 in the font's \u2018name\u2019 table to indicate that this palette entry is used for outlines, index 1 might correspond to \u2018fill\u2019 to indicate the filling color palette entry, etc. An empty entry name ID in the \u2018CPAL\u2019 table gets represented as value 0xFFFF. NULL if the font's \u2018CPAL\u2019 table doesn't contain appropriate data. note Use function FT_Get_Sfnt_Name to map name IDs and entry name IDs to name strings. Use function FT_Palette_Select to get the colors associated with a palette entry. since 2.10 FT_Palette_Data_Get \u00b6 Defined in FT_COLOR_H (freetype/ftcolor.h). FT_EXPORT( FT_Error ) FT_Palette_Data_Get ( FT_Face face, FT_Palette_Data *apalette ); Retrieve the face's color palette data. input face The source face handle. output apalette A pointer to an FT_Palette_Data structure. return FreeType error code. 0 means success. note All arrays in the returned FT_Palette_Data structure are read-only. This function always returns an error if the config macro TT_CONFIG_OPTION_COLOR_LAYERS is not defined in ftoption.h . since 2.10 FT_Palette_Select \u00b6 Defined in FT_COLOR_H (freetype/ftcolor.h). FT_EXPORT( FT_Error ) FT_Palette_Select ( FT_Face face, FT_UShort palette_index, FT_Color * *apalette ); This function has two purposes. (1) It activates a palette for rendering color glyphs, and (2) it retrieves all (unmodified) color entries of this palette. This function returns a read-write array, which means that a calling application can modify the palette entries on demand. A corollary of (2) is that calling the function, then modifying some values, then calling the function again with the same arguments resets all color entries to the original \u2018CPAL\u2019 values; all user modifications are lost. input face The source face handle. palette_index The palette index. output apalette An array of color entries for a palette with index palette_index , having num_palette_entries elements (as found in the FT_Palette_Data structure). If apalette is set to NULL , no array gets returned (and no color entries can be modified). In case the font doesn't support color palettes, NULL is returned. return FreeType error code. 0 means success. note The array pointed to by apalette_entries is owned and managed by FreeType. This function always returns an error if the config macro TT_CONFIG_OPTION_COLOR_LAYERS is not defined in ftoption.h . since 2.10 FT_Palette_Set_Foreground_Color \u00b6 Defined in FT_COLOR_H (freetype/ftcolor.h). FT_EXPORT( FT_Error ) FT_Palette_Set_Foreground_Color ( FT_Face face, FT_Color foreground_color ); \u2018COLR\u2019 uses palette index 0xFFFF to indicate a \u2018text foreground color\u2019. This function sets this value. input face The source face handle. foreground_color An FT_Color structure to define the text foreground color. return FreeType error code. 0 means success. note If this function isn't called, the text foreground color is set to white opaque (BGRA value 0xFFFFFFFF) if FT_PALETTE_FOR_DARK_BACKGROUND is present for the current palette, and black opaque (BGRA value 0x000000FF) otherwise, including the case that no palette types are available in the \u2018CPAL\u2019 table. This function always returns an error if the config macro TT_CONFIG_OPTION_COLOR_LAYERS is not defined in ftoption.h . since 2.10","title":"Glyph Color Management"},{"location":"ft2-color_management.html#glyph-color-management","text":"","title":"Glyph Color Management"},{"location":"ft2-color_management.html#synopsis","text":"The functions described here allow access and manipulation of color palette entries in OpenType's \u2018CPAL\u2019 tables.","title":"Synopsis"},{"location":"ft2-color_management.html#ft_color","text":"Defined in FT_COLOR_H (freetype/ftcolor.h). typedef struct FT_Color_ { FT_Byte blue; FT_Byte green; FT_Byte red; FT_Byte alpha; } FT_Color ; This structure models a BGRA color value of a \u2018CPAL\u2019 palette entry. The used color space is sRGB; the colors are not pre-multiplied, and alpha values must be explicitly set.","title":"FT_Color"},{"location":"ft2-color_management.html#ft_palette_xxx","text":"Defined in FT_COLOR_H (freetype/ftcolor.h). # define FT_PALETTE_FOR_LIGHT_BACKGROUND 0x01 # define FT_PALETTE_FOR_DARK_BACKGROUND 0x02 A list of bit field constants used in the palette_flags array of the FT_Palette_Data structure to indicate for which background a palette with a given index is usable.","title":"FT_PALETTE_XXX"},{"location":"ft2-color_management.html#ft_palette_data","text":"Defined in FT_COLOR_H (freetype/ftcolor.h). typedef struct FT_Palette_Data_ { FT_UShort num_palettes; const FT_UShort * palette_name_ids; const FT_UShort * palette_flags; FT_UShort num_palette_entries; const FT_UShort * palette_entry_name_ids; } FT_Palette_Data ; This structure holds the data of the \u2018CPAL\u2019 table.","title":"FT_Palette_Data"},{"location":"ft2-color_management.html#ft_palette_data_get","text":"Defined in FT_COLOR_H (freetype/ftcolor.h). FT_EXPORT( FT_Error ) FT_Palette_Data_Get ( FT_Face face, FT_Palette_Data *apalette ); Retrieve the face's color palette data.","title":"FT_Palette_Data_Get"},{"location":"ft2-color_management.html#ft_palette_select","text":"Defined in FT_COLOR_H (freetype/ftcolor.h). FT_EXPORT( FT_Error ) FT_Palette_Select ( FT_Face face, FT_UShort palette_index, FT_Color * *apalette ); This function has two purposes. (1) It activates a palette for rendering color glyphs, and (2) it retrieves all (unmodified) color entries of this palette. This function returns a read-write array, which means that a calling application can modify the palette entries on demand. A corollary of (2) is that calling the function, then modifying some values, then calling the function again with the same arguments resets all color entries to the original \u2018CPAL\u2019 values; all user modifications are lost.","title":"FT_Palette_Select"},{"location":"ft2-color_management.html#ft_palette_set_foreground_color","text":"Defined in FT_COLOR_H (freetype/ftcolor.h). FT_EXPORT( FT_Error ) FT_Palette_Set_Foreground_Color ( FT_Face face, FT_Color foreground_color ); \u2018COLR\u2019 uses palette index 0xFFFF to indicate a \u2018text foreground color\u2019. This function sets this value.","title":"FT_Palette_Set_Foreground_Color"},{"location":"ft2-computations.html","text":"FreeType \u00bb Docs \u00bb Support API \u00bb Computations Computations \u00b6 Synopsis \u00b6 This section contains various functions used to perform computations on 16.16 fixed-float numbers or 2d vectors. Attention : Most arithmetic functions take FT_Long as arguments. For historical reasons, FreeType was designed under the assumption that FT_Long is a 32-bit integer; results can thus be undefined if the arguments don't fit into 32 bits. FT_MulDiv \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Long ) FT_MulDiv ( FT_Long a, FT_Long b, FT_Long c ); Compute (a*b)/c with maximum accuracy, using a 64-bit intermediate integer whenever necessary. This function isn't necessarily as fast as some processor-specific operations, but is at least completely portable. input a The first multiplier. b The second multiplier. c The divisor. return The result of (a*b)/c . This function never traps when trying to divide by zero; it simply returns \u2018MaxInt\u2019 or \u2018MinInt\u2019 depending on the signs of a and b . FT_MulFix \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Long ) FT_MulFix ( FT_Long a, FT_Long b ); Compute (a*b)/0x10000 with maximum accuracy. Its main use is to multiply a given value by a 16.16 fixed-point factor. input a The first multiplier. b The second multiplier. Use a 16.16 factor here whenever possible (see note below). return The result of (a*b)/0x10000 . note This function has been optimized for the case where the absolute value of a is less than 2048, and b is a 16.16 scaling factor. As this happens mainly when scaling from notional units to fractional pixels in FreeType, it resulted in noticeable speed improvements between versions 2.x and 1.x. As a conclusion, always try to place a 16.16 factor as the second argument of this function; this can make a great difference. FT_DivFix \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Long ) FT_DivFix ( FT_Long a, FT_Long b ); Compute (a*0x10000)/b with maximum accuracy. Its main use is to divide a given value by a 16.16 fixed-point factor. input a The numerator. b The denominator. Use a 16.16 factor here. return The result of (a*0x10000)/b . FT_RoundFix \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Fixed ) FT_RoundFix ( FT_Fixed a ); Round a 16.16 fixed number. input a The number to be rounded. return a rounded to the nearest 16.16 fixed integer, halfway cases away from zero. note The function uses wrap-around arithmetic. FT_CeilFix \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Fixed ) FT_CeilFix ( FT_Fixed a ); Compute the smallest following integer of a 16.16 fixed number. input a The number for which the ceiling function is to be computed. return a rounded towards plus infinity. note The function uses wrap-around arithmetic. FT_FloorFix \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Fixed ) FT_FloorFix ( FT_Fixed a ); Compute the largest previous integer of a 16.16 fixed number. input a The number for which the floor function is to be computed. return a rounded towards minus infinity. FT_Vector_Transform \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( void ) FT_Vector_Transform ( FT_Vector * vector, const FT_Matrix * matrix ); Transform a single vector through a 2x2 matrix. inout vector The target vector to transform. input matrix A pointer to the source 2x2 matrix. note The result is undefined if either vector or matrix is invalid. FT_Matrix_Multiply \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( void ) FT_Matrix_Multiply ( const FT_Matrix * a, FT_Matrix * b ); Perform the matrix operation b = a*b . input a A pointer to matrix a . inout b A pointer to matrix b . note The result is undefined if either a or b is zero. Since the function uses wrap-around arithmetic, results become meaningless if the arguments are very large. FT_Matrix_Invert \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( FT_Error ) FT_Matrix_Invert ( FT_Matrix * matrix ); Invert a 2x2 matrix. Return an error if it can't be inverted. inout matrix A pointer to the target matrix. Remains untouched in case of error. return FreeType error code. 0 means success. FT_Angle \u00b6 Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). typedef FT_Fixed FT_Angle ; This type is used to model angle values in FreeType. Note that the angle is a 16.16 fixed-point value expressed in degrees. FT_ANGLE_PI \u00b6 Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). # define FT_ANGLE_PI ( 180L << 16 ) The angle pi expressed in FT_Angle units. FT_ANGLE_2PI \u00b6 Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). # define FT_ANGLE_2PI ( FT_ANGLE_PI * 2 ) The angle 2*pi expressed in FT_Angle units. FT_ANGLE_PI2 \u00b6 Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). # define FT_ANGLE_PI2 ( FT_ANGLE_PI / 2 ) The angle pi/2 expressed in FT_Angle units. FT_ANGLE_PI4 \u00b6 Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). # define FT_ANGLE_PI4 ( FT_ANGLE_PI / 4 ) The angle pi/4 expressed in FT_Angle units. FT_Sin \u00b6 Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( FT_Fixed ) FT_Sin ( FT_Angle angle ); Return the sinus of a given angle in fixed-point format. input angle The input angle. return The sinus value. note If you need both the sinus and cosinus for a given angle, use the function FT_Vector_Unit . FT_Cos \u00b6 Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( FT_Fixed ) FT_Cos ( FT_Angle angle ); Return the cosinus of a given angle in fixed-point format. input angle The input angle. return The cosinus value. note If you need both the sinus and cosinus for a given angle, use the function FT_Vector_Unit . FT_Tan \u00b6 Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( FT_Fixed ) FT_Tan ( FT_Angle angle ); Return the tangent of a given angle in fixed-point format. input angle The input angle. return The tangent value. FT_Atan2 \u00b6 Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( FT_Angle ) FT_Atan2 ( FT_Fixed x, FT_Fixed y ); Return the arc-tangent corresponding to a given vector (x,y) in the 2d plane. input x The horizontal vector coordinate. y The vertical vector coordinate. return The arc-tangent value (i.e. angle). FT_Angle_Diff \u00b6 Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( FT_Angle ) FT_Angle_Diff ( FT_Angle angle1, FT_Angle angle2 ); Return the difference between two angles. The result is always constrained to the ]-PI..PI] interval. input angle1 First angle. angle2 Second angle. return Constrained value of angle2-angle1 . FT_Vector_Unit \u00b6 Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( void ) FT_Vector_Unit ( FT_Vector * vec, FT_Angle angle ); Return the unit vector corresponding to a given angle. After the call, the value of vec.x will be cos(angle) , and the value of vec.y will be sin(angle) . This function is useful to retrieve both the sinus and cosinus of a given angle quickly. output vec The address of target vector. input angle The input angle. FT_Vector_Rotate \u00b6 Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( void ) FT_Vector_Rotate ( FT_Vector * vec, FT_Angle angle ); Rotate a vector by a given angle. inout vec The address of target vector. input angle The input angle. FT_Vector_Length \u00b6 Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( FT_Fixed ) FT_Vector_Length ( FT_Vector * vec ); Return the length of a given vector. input vec The address of target vector. return The vector length, expressed in the same units that the original vector coordinates. FT_Vector_Polarize \u00b6 Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( void ) FT_Vector_Polarize ( FT_Vector * vec, FT_Fixed *length, FT_Angle *angle ); Compute both the length and angle of a given vector. input vec The address of source vector. output length The vector length. angle The vector angle. FT_Vector_From_Polar \u00b6 Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( void ) FT_Vector_From_Polar ( FT_Vector * vec, FT_Fixed length, FT_Angle angle ); Compute vector coordinates from a length and angle. output vec The address of source vector. input length The vector length. angle The vector angle.","title":"Computations"},{"location":"ft2-computations.html#computations","text":"","title":"Computations"},{"location":"ft2-computations.html#synopsis","text":"This section contains various functions used to perform computations on 16.16 fixed-float numbers or 2d vectors. Attention : Most arithmetic functions take FT_Long as arguments. For historical reasons, FreeType was designed under the assumption that FT_Long is a 32-bit integer; results can thus be undefined if the arguments don't fit into 32 bits.","title":"Synopsis"},{"location":"ft2-computations.html#ft_muldiv","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Long ) FT_MulDiv ( FT_Long a, FT_Long b, FT_Long c ); Compute (a*b)/c with maximum accuracy, using a 64-bit intermediate integer whenever necessary. This function isn't necessarily as fast as some processor-specific operations, but is at least completely portable.","title":"FT_MulDiv"},{"location":"ft2-computations.html#ft_mulfix","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Long ) FT_MulFix ( FT_Long a, FT_Long b ); Compute (a*b)/0x10000 with maximum accuracy. Its main use is to multiply a given value by a 16.16 fixed-point factor.","title":"FT_MulFix"},{"location":"ft2-computations.html#ft_divfix","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Long ) FT_DivFix ( FT_Long a, FT_Long b ); Compute (a*0x10000)/b with maximum accuracy. Its main use is to divide a given value by a 16.16 fixed-point factor.","title":"FT_DivFix"},{"location":"ft2-computations.html#ft_roundfix","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Fixed ) FT_RoundFix ( FT_Fixed a ); Round a 16.16 fixed number.","title":"FT_RoundFix"},{"location":"ft2-computations.html#ft_ceilfix","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Fixed ) FT_CeilFix ( FT_Fixed a ); Compute the smallest following integer of a 16.16 fixed number.","title":"FT_CeilFix"},{"location":"ft2-computations.html#ft_floorfix","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Fixed ) FT_FloorFix ( FT_Fixed a ); Compute the largest previous integer of a 16.16 fixed number.","title":"FT_FloorFix"},{"location":"ft2-computations.html#ft_vector_transform","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( void ) FT_Vector_Transform ( FT_Vector * vector, const FT_Matrix * matrix ); Transform a single vector through a 2x2 matrix.","title":"FT_Vector_Transform"},{"location":"ft2-computations.html#ft_matrix_multiply","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( void ) FT_Matrix_Multiply ( const FT_Matrix * a, FT_Matrix * b ); Perform the matrix operation b = a*b .","title":"FT_Matrix_Multiply"},{"location":"ft2-computations.html#ft_matrix_invert","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( FT_Error ) FT_Matrix_Invert ( FT_Matrix * matrix ); Invert a 2x2 matrix. Return an error if it can't be inverted.","title":"FT_Matrix_Invert"},{"location":"ft2-computations.html#ft_angle","text":"Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). typedef FT_Fixed FT_Angle ; This type is used to model angle values in FreeType. Note that the angle is a 16.16 fixed-point value expressed in degrees.","title":"FT_Angle"},{"location":"ft2-computations.html#ft_angle_pi","text":"Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). # define FT_ANGLE_PI ( 180L << 16 ) The angle pi expressed in FT_Angle units.","title":"FT_ANGLE_PI"},{"location":"ft2-computations.html#ft_angle_2pi","text":"Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). # define FT_ANGLE_2PI ( FT_ANGLE_PI * 2 ) The angle 2*pi expressed in FT_Angle units.","title":"FT_ANGLE_2PI"},{"location":"ft2-computations.html#ft_angle_pi2","text":"Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). # define FT_ANGLE_PI2 ( FT_ANGLE_PI / 2 ) The angle pi/2 expressed in FT_Angle units.","title":"FT_ANGLE_PI2"},{"location":"ft2-computations.html#ft_angle_pi4","text":"Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). # define FT_ANGLE_PI4 ( FT_ANGLE_PI / 4 ) The angle pi/4 expressed in FT_Angle units.","title":"FT_ANGLE_PI4"},{"location":"ft2-computations.html#ft_sin","text":"Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( FT_Fixed ) FT_Sin ( FT_Angle angle ); Return the sinus of a given angle in fixed-point format.","title":"FT_Sin"},{"location":"ft2-computations.html#ft_cos","text":"Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( FT_Fixed ) FT_Cos ( FT_Angle angle ); Return the cosinus of a given angle in fixed-point format.","title":"FT_Cos"},{"location":"ft2-computations.html#ft_tan","text":"Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( FT_Fixed ) FT_Tan ( FT_Angle angle ); Return the tangent of a given angle in fixed-point format.","title":"FT_Tan"},{"location":"ft2-computations.html#ft_atan2","text":"Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( FT_Angle ) FT_Atan2 ( FT_Fixed x, FT_Fixed y ); Return the arc-tangent corresponding to a given vector (x,y) in the 2d plane.","title":"FT_Atan2"},{"location":"ft2-computations.html#ft_angle_diff","text":"Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( FT_Angle ) FT_Angle_Diff ( FT_Angle angle1, FT_Angle angle2 ); Return the difference between two angles. The result is always constrained to the ]-PI..PI] interval.","title":"FT_Angle_Diff"},{"location":"ft2-computations.html#ft_vector_unit","text":"Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( void ) FT_Vector_Unit ( FT_Vector * vec, FT_Angle angle ); Return the unit vector corresponding to a given angle. After the call, the value of vec.x will be cos(angle) , and the value of vec.y will be sin(angle) . This function is useful to retrieve both the sinus and cosinus of a given angle quickly.","title":"FT_Vector_Unit"},{"location":"ft2-computations.html#ft_vector_rotate","text":"Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( void ) FT_Vector_Rotate ( FT_Vector * vec, FT_Angle angle ); Rotate a vector by a given angle.","title":"FT_Vector_Rotate"},{"location":"ft2-computations.html#ft_vector_length","text":"Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( FT_Fixed ) FT_Vector_Length ( FT_Vector * vec ); Return the length of a given vector.","title":"FT_Vector_Length"},{"location":"ft2-computations.html#ft_vector_polarize","text":"Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( void ) FT_Vector_Polarize ( FT_Vector * vec, FT_Fixed *length, FT_Angle *angle ); Compute both the length and angle of a given vector.","title":"FT_Vector_Polarize"},{"location":"ft2-computations.html#ft_vector_from_polar","text":"Defined in FT_TRIGONOMETRY_H (freetype/fttrigon.h). FT_EXPORT( void ) FT_Vector_From_Polar ( FT_Vector * vec, FT_Fixed length, FT_Angle angle ); Compute vector coordinates from a length and angle.","title":"FT_Vector_From_Polar"},{"location":"ft2-error_code_values.html","text":"FreeType \u00bb Docs \u00bb Error Codes \u00bb Error Code Values Error Code Values \u00b6 Synopsis \u00b6 The list below is taken verbatim from the file fterrdef.h (loaded automatically by including FT_FREETYPE_H ). The first argument of the FT_ERROR_DEF_ macro is the error label; by default, the prefix FT_Err_ gets added so that you get error names like FT_Err_Cannot_Open_Resource . The second argument is the error code, and the last argument an error string, which is not used by FreeType. Within your application you should only use error names and never its numeric values! The latter might (and actually do) change in forthcoming FreeType versions. Macro FT_NOERRORDEF_ defines FT_Err_Ok , which is always zero. See the \u2018Error Enumerations\u2019 subsection how to automatically generate a list of error strings. FT_Err_XXX \u00b6 /* generic errors */ FT_NOERRORDEF_( Ok, 0x00, \"no error\" ) FT_ERRORDEF_( Cannot_Open_Resource, 0x01, \"cannot open resource\" ) FT_ERRORDEF_( Unknown_File_Format, 0x02, \"unknown file format\" ) FT_ERRORDEF_( Invalid_File_Format, 0x03, \"broken file\" ) FT_ERRORDEF_( Invalid_Version, 0x04, \"invalid FreeType version\" ) FT_ERRORDEF_( Lower_Module_Version, 0x05, \"module version is too low\" ) FT_ERRORDEF_( Invalid_Argument, 0x06, \"invalid argument\" ) FT_ERRORDEF_( Unimplemented_Feature, 0x07, \"unimplemented feature\" ) FT_ERRORDEF_( Invalid_Table, 0x08, \"broken table\" ) FT_ERRORDEF_( Invalid_Offset, 0x09, \"broken offset within table\" ) FT_ERRORDEF_( Array_Too_Large, 0x0A, \"array allocation size too large\" ) FT_ERRORDEF_( Missing_Module, 0x0B, \"missing module\" ) FT_ERRORDEF_( Missing_Property, 0x0C, \"missing property\" ) /* glyph/character errors */ FT_ERRORDEF_( Invalid_Glyph_Index, 0x10, \"invalid glyph index\" ) FT_ERRORDEF_( Invalid_Character_Code, 0x11, \"invalid character code\" ) FT_ERRORDEF_( Invalid_Glyph_Format, 0x12, \"unsupported glyph image format\" ) FT_ERRORDEF_( Cannot_Render_Glyph, 0x13, \"cannot render this glyph format\" ) FT_ERRORDEF_( Invalid_Outline, 0x14, \"invalid outline\" ) FT_ERRORDEF_( Invalid_Composite, 0x15, \"invalid composite glyph\" ) FT_ERRORDEF_( Too_Many_Hints, 0x16, \"too many hints\" ) FT_ERRORDEF_( Invalid_Pixel_Size, 0x17, \"invalid pixel size\" ) /* handle errors */ FT_ERRORDEF_( Invalid_Handle, 0x20, \"invalid object handle\" ) FT_ERRORDEF_( Invalid_Library_Handle, 0x21, \"invalid library handle\" ) FT_ERRORDEF_( Invalid_Driver_Handle, 0x22, \"invalid module handle\" ) FT_ERRORDEF_( Invalid_Face_Handle, 0x23, \"invalid face handle\" ) FT_ERRORDEF_( Invalid_Size_Handle, 0x24, \"invalid size handle\" ) FT_ERRORDEF_( Invalid_Slot_Handle, 0x25, \"invalid glyph slot handle\" ) FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26, \"invalid charmap handle\" ) FT_ERRORDEF_( Invalid_Cache_Handle, 0x27, \"invalid cache manager handle\" ) FT_ERRORDEF_( Invalid_Stream_Handle, 0x28, \"invalid stream handle\" ) /* driver errors */ FT_ERRORDEF_( Too_Many_Drivers, 0x30, \"too many modules\" ) FT_ERRORDEF_( Too_Many_Extensions, 0x31, \"too many extensions\" ) /* memory errors */ FT_ERRORDEF_( Out_Of_Memory, 0x40, \"out of memory\" ) FT_ERRORDEF_( Unlisted_Object, 0x41, \"unlisted object\" ) /* stream errors */ FT_ERRORDEF_( Cannot_Open_Stream, 0x51, \"cannot open stream\" ) FT_ERRORDEF_( Invalid_Stream_Seek, 0x52, \"invalid stream seek\" ) FT_ERRORDEF_( Invalid_Stream_Skip, 0x53, \"invalid stream skip\" ) FT_ERRORDEF_( Invalid_Stream_Read, 0x54, \"invalid stream read\" ) FT_ERRORDEF_( Invalid_Stream_Operation, 0x55, \"invalid stream operation\" ) FT_ERRORDEF_( Invalid_Frame_Operation, 0x56, \"invalid frame operation\" ) FT_ERRORDEF_( Nested_Frame_Access, 0x57, \"nested frame access\" ) FT_ERRORDEF_( Invalid_Frame_Read, 0x58, \"invalid frame read\" ) /* raster errors */ FT_ERRORDEF_( Raster_Uninitialized, 0x60, \"raster uninitialized\" ) FT_ERRORDEF_( Raster_Corrupted, 0x61, \"raster corrupted\" ) FT_ERRORDEF_( Raster_Overflow, 0x62, \"raster overflow\" ) FT_ERRORDEF_( Raster_Negative_Height, 0x63, \"negative height while rastering\" ) /* cache errors */ FT_ERRORDEF_( Too_Many_Caches, 0x70, \"too many registered caches\" ) /* TrueType and SFNT errors */ FT_ERRORDEF_( Invalid_Opcode, 0x80, \"invalid opcode\" ) FT_ERRORDEF_( Too_Few_Arguments, 0x81, \"too few arguments\" ) FT_ERRORDEF_( Stack_Overflow, 0x82, \"stack overflow\" ) FT_ERRORDEF_( Code_Overflow, 0x83, \"code overflow\" ) FT_ERRORDEF_( Bad_Argument, 0x84, \"bad argument\" ) FT_ERRORDEF_( Divide_By_Zero, 0x85, \"division by zero\" ) FT_ERRORDEF_( Invalid_Reference, 0x86, \"invalid reference\" ) FT_ERRORDEF_( Debug_OpCode, 0x87, \"found debug opcode\" ) FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88, \"found ENDF opcode in execution stream\" ) FT_ERRORDEF_( Nested_DEFS, 0x89, \"nested DEFS\" ) FT_ERRORDEF_( Invalid_CodeRange, 0x8A, \"invalid code range\" ) FT_ERRORDEF_( Execution_Too_Long, 0x8B, \"execution context too long \" ) FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C, \"too many function definitions\" ) FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D, \"too many instruction definitions\" ) FT_ERRORDEF_( Table_Missing, 0x8E, \"SFNT font table missing\" ) FT_ERRORDEF_( Horiz_Header_Missing, 0x8F, \"horizontal header (hhea) table missing\" ) FT_ERRORDEF_( Locations_Missing, 0x90, \"locations (loca) table missing\" ) FT_ERRORDEF_( Name_Table_Missing, 0x91, \"name table missing\" ) FT_ERRORDEF_( CMap_Table_Missing, 0x92, \"character map (cmap) table missing\" ) FT_ERRORDEF_( Hmtx_Table_Missing, 0x93, \"horizontal metrics (hmtx) table missing\" ) FT_ERRORDEF_( Post_Table_Missing, 0x94, \"PostScript (post) table missing\" ) FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95, \"invalid horizontal metrics\" ) FT_ERRORDEF_( Invalid_CharMap_Format, 0x96, \"invalid character map (cmap) format\" ) FT_ERRORDEF_( Invalid_PPem, 0x97, \"invalid ppem value\" ) FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98, \"invalid vertical metrics\" ) FT_ERRORDEF_( Could_Not_Find_Context, 0x99, \"could not find context\" ) FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A, \"invalid PostScript (post) table format\" ) FT_ERRORDEF_( Invalid_Post_Table, 0x9B, \"invalid PostScript (post) table\" ) FT_ERRORDEF_( DEF_In_Glyf_Bytecode, 0x9C, \"found FDEF or IDEF opcode in glyf bytecode\" ) FT_ERRORDEF_( Missing_Bitmap, 0x9D, \"missing bitmap in strike\" ) /* CFF, CID, and Type 1 errors */ FT_ERRORDEF_( Syntax_Error, 0xA0, \"opcode syntax error\" ) FT_ERRORDEF_( Stack_Underflow, 0xA1, \"argument stack underflow\" ) FT_ERRORDEF_( Ignore, 0xA2, \"ignore\" ) FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3, \"no Unicode glyph name found\" ) FT_ERRORDEF_( Glyph_Too_Big, 0xA4, \"glyph too big for hinting\" ) /* BDF errors */ FT_ERRORDEF_( Missing_Startfont_Field, 0xB0, \"`STARTFONT' field missing\" ) FT_ERRORDEF_( Missing_Font_Field, 0xB1, \"`FONT' field missing\" ) FT_ERRORDEF_( Missing_Size_Field, 0xB2, \"`SIZE' field missing\" ) FT_ERRORDEF_( Missing_Fontboundingbox_Field, 0xB3, \"`FONTBOUNDINGBOX' field missing\" ) FT_ERRORDEF_( Missing_Chars_Field, 0xB4, \"`CHARS' field missing\" ) FT_ERRORDEF_( Missing_Startchar_Field, 0xB5, \"`STARTCHAR' field missing\" ) FT_ERRORDEF_( Missing_Encoding_Field, 0xB6, \"`ENCODING' field missing\" ) FT_ERRORDEF_( Missing_Bbx_Field, 0xB7, \"`BBX' field missing\" ) FT_ERRORDEF_( Bbx_Too_Big, 0xB8, \"`BBX' too big\" ) FT_ERRORDEF_( Corrupted_Font_Header, 0xB9, \"Font header corrupted or missing fields\" ) FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xBA, \"Font glyphs corrupted or missing fields\" )","title":"Error Code Values"},{"location":"ft2-error_code_values.html#error-code-values","text":"","title":"Error Code Values"},{"location":"ft2-error_code_values.html#synopsis","text":"The list below is taken verbatim from the file fterrdef.h (loaded automatically by including FT_FREETYPE_H ). The first argument of the FT_ERROR_DEF_ macro is the error label; by default, the prefix FT_Err_ gets added so that you get error names like FT_Err_Cannot_Open_Resource . The second argument is the error code, and the last argument an error string, which is not used by FreeType. Within your application you should only use error names and never its numeric values! The latter might (and actually do) change in forthcoming FreeType versions. Macro FT_NOERRORDEF_ defines FT_Err_Ok , which is always zero. See the \u2018Error Enumerations\u2019 subsection how to automatically generate a list of error strings.","title":"Synopsis"},{"location":"ft2-error_code_values.html#ft_err_xxx","text":"/* generic errors */ FT_NOERRORDEF_( Ok, 0x00, \"no error\" ) FT_ERRORDEF_( Cannot_Open_Resource, 0x01, \"cannot open resource\" ) FT_ERRORDEF_( Unknown_File_Format, 0x02, \"unknown file format\" ) FT_ERRORDEF_( Invalid_File_Format, 0x03, \"broken file\" ) FT_ERRORDEF_( Invalid_Version, 0x04, \"invalid FreeType version\" ) FT_ERRORDEF_( Lower_Module_Version, 0x05, \"module version is too low\" ) FT_ERRORDEF_( Invalid_Argument, 0x06, \"invalid argument\" ) FT_ERRORDEF_( Unimplemented_Feature, 0x07, \"unimplemented feature\" ) FT_ERRORDEF_( Invalid_Table, 0x08, \"broken table\" ) FT_ERRORDEF_( Invalid_Offset, 0x09, \"broken offset within table\" ) FT_ERRORDEF_( Array_Too_Large, 0x0A, \"array allocation size too large\" ) FT_ERRORDEF_( Missing_Module, 0x0B, \"missing module\" ) FT_ERRORDEF_( Missing_Property, 0x0C, \"missing property\" ) /* glyph/character errors */ FT_ERRORDEF_( Invalid_Glyph_Index, 0x10, \"invalid glyph index\" ) FT_ERRORDEF_( Invalid_Character_Code, 0x11, \"invalid character code\" ) FT_ERRORDEF_( Invalid_Glyph_Format, 0x12, \"unsupported glyph image format\" ) FT_ERRORDEF_( Cannot_Render_Glyph, 0x13, \"cannot render this glyph format\" ) FT_ERRORDEF_( Invalid_Outline, 0x14, \"invalid outline\" ) FT_ERRORDEF_( Invalid_Composite, 0x15, \"invalid composite glyph\" ) FT_ERRORDEF_( Too_Many_Hints, 0x16, \"too many hints\" ) FT_ERRORDEF_( Invalid_Pixel_Size, 0x17, \"invalid pixel size\" ) /* handle errors */ FT_ERRORDEF_( Invalid_Handle, 0x20, \"invalid object handle\" ) FT_ERRORDEF_( Invalid_Library_Handle, 0x21, \"invalid library handle\" ) FT_ERRORDEF_( Invalid_Driver_Handle, 0x22, \"invalid module handle\" ) FT_ERRORDEF_( Invalid_Face_Handle, 0x23, \"invalid face handle\" ) FT_ERRORDEF_( Invalid_Size_Handle, 0x24, \"invalid size handle\" ) FT_ERRORDEF_( Invalid_Slot_Handle, 0x25, \"invalid glyph slot handle\" ) FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26, \"invalid charmap handle\" ) FT_ERRORDEF_( Invalid_Cache_Handle, 0x27, \"invalid cache manager handle\" ) FT_ERRORDEF_( Invalid_Stream_Handle, 0x28, \"invalid stream handle\" ) /* driver errors */ FT_ERRORDEF_( Too_Many_Drivers, 0x30, \"too many modules\" ) FT_ERRORDEF_( Too_Many_Extensions, 0x31, \"too many extensions\" ) /* memory errors */ FT_ERRORDEF_( Out_Of_Memory, 0x40, \"out of memory\" ) FT_ERRORDEF_( Unlisted_Object, 0x41, \"unlisted object\" ) /* stream errors */ FT_ERRORDEF_( Cannot_Open_Stream, 0x51, \"cannot open stream\" ) FT_ERRORDEF_( Invalid_Stream_Seek, 0x52, \"invalid stream seek\" ) FT_ERRORDEF_( Invalid_Stream_Skip, 0x53, \"invalid stream skip\" ) FT_ERRORDEF_( Invalid_Stream_Read, 0x54, \"invalid stream read\" ) FT_ERRORDEF_( Invalid_Stream_Operation, 0x55, \"invalid stream operation\" ) FT_ERRORDEF_( Invalid_Frame_Operation, 0x56, \"invalid frame operation\" ) FT_ERRORDEF_( Nested_Frame_Access, 0x57, \"nested frame access\" ) FT_ERRORDEF_( Invalid_Frame_Read, 0x58, \"invalid frame read\" ) /* raster errors */ FT_ERRORDEF_( Raster_Uninitialized, 0x60, \"raster uninitialized\" ) FT_ERRORDEF_( Raster_Corrupted, 0x61, \"raster corrupted\" ) FT_ERRORDEF_( Raster_Overflow, 0x62, \"raster overflow\" ) FT_ERRORDEF_( Raster_Negative_Height, 0x63, \"negative height while rastering\" ) /* cache errors */ FT_ERRORDEF_( Too_Many_Caches, 0x70, \"too many registered caches\" ) /* TrueType and SFNT errors */ FT_ERRORDEF_( Invalid_Opcode, 0x80, \"invalid opcode\" ) FT_ERRORDEF_( Too_Few_Arguments, 0x81, \"too few arguments\" ) FT_ERRORDEF_( Stack_Overflow, 0x82, \"stack overflow\" ) FT_ERRORDEF_( Code_Overflow, 0x83, \"code overflow\" ) FT_ERRORDEF_( Bad_Argument, 0x84, \"bad argument\" ) FT_ERRORDEF_( Divide_By_Zero, 0x85, \"division by zero\" ) FT_ERRORDEF_( Invalid_Reference, 0x86, \"invalid reference\" ) FT_ERRORDEF_( Debug_OpCode, 0x87, \"found debug opcode\" ) FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88, \"found ENDF opcode in execution stream\" ) FT_ERRORDEF_( Nested_DEFS, 0x89, \"nested DEFS\" ) FT_ERRORDEF_( Invalid_CodeRange, 0x8A, \"invalid code range\" ) FT_ERRORDEF_( Execution_Too_Long, 0x8B, \"execution context too long \" ) FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C, \"too many function definitions\" ) FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D, \"too many instruction definitions\" ) FT_ERRORDEF_( Table_Missing, 0x8E, \"SFNT font table missing\" ) FT_ERRORDEF_( Horiz_Header_Missing, 0x8F, \"horizontal header (hhea) table missing\" ) FT_ERRORDEF_( Locations_Missing, 0x90, \"locations (loca) table missing\" ) FT_ERRORDEF_( Name_Table_Missing, 0x91, \"name table missing\" ) FT_ERRORDEF_( CMap_Table_Missing, 0x92, \"character map (cmap) table missing\" ) FT_ERRORDEF_( Hmtx_Table_Missing, 0x93, \"horizontal metrics (hmtx) table missing\" ) FT_ERRORDEF_( Post_Table_Missing, 0x94, \"PostScript (post) table missing\" ) FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95, \"invalid horizontal metrics\" ) FT_ERRORDEF_( Invalid_CharMap_Format, 0x96, \"invalid character map (cmap) format\" ) FT_ERRORDEF_( Invalid_PPem, 0x97, \"invalid ppem value\" ) FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98, \"invalid vertical metrics\" ) FT_ERRORDEF_( Could_Not_Find_Context, 0x99, \"could not find context\" ) FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A, \"invalid PostScript (post) table format\" ) FT_ERRORDEF_( Invalid_Post_Table, 0x9B, \"invalid PostScript (post) table\" ) FT_ERRORDEF_( DEF_In_Glyf_Bytecode, 0x9C, \"found FDEF or IDEF opcode in glyf bytecode\" ) FT_ERRORDEF_( Missing_Bitmap, 0x9D, \"missing bitmap in strike\" ) /* CFF, CID, and Type 1 errors */ FT_ERRORDEF_( Syntax_Error, 0xA0, \"opcode syntax error\" ) FT_ERRORDEF_( Stack_Underflow, 0xA1, \"argument stack underflow\" ) FT_ERRORDEF_( Ignore, 0xA2, \"ignore\" ) FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3, \"no Unicode glyph name found\" ) FT_ERRORDEF_( Glyph_Too_Big, 0xA4, \"glyph too big for hinting\" ) /* BDF errors */ FT_ERRORDEF_( Missing_Startfont_Field, 0xB0, \"`STARTFONT' field missing\" ) FT_ERRORDEF_( Missing_Font_Field, 0xB1, \"`FONT' field missing\" ) FT_ERRORDEF_( Missing_Size_Field, 0xB2, \"`SIZE' field missing\" ) FT_ERRORDEF_( Missing_Fontboundingbox_Field, 0xB3, \"`FONTBOUNDINGBOX' field missing\" ) FT_ERRORDEF_( Missing_Chars_Field, 0xB4, \"`CHARS' field missing\" ) FT_ERRORDEF_( Missing_Startchar_Field, 0xB5, \"`STARTCHAR' field missing\" ) FT_ERRORDEF_( Missing_Encoding_Field, 0xB6, \"`ENCODING' field missing\" ) FT_ERRORDEF_( Missing_Bbx_Field, 0xB7, \"`BBX' field missing\" ) FT_ERRORDEF_( Bbx_Too_Big, 0xB8, \"`BBX' too big\" ) FT_ERRORDEF_( Corrupted_Font_Header, 0xB9, \"Font header corrupted or missing fields\" ) FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xBA, \"Font glyphs corrupted or missing fields\" )","title":"FT_Err_XXX"},{"location":"ft2-error_enumerations.html","text":"FreeType \u00bb Docs \u00bb Error Codes \u00bb Error Enumerations Error Enumerations \u00b6 Synopsis \u00b6 The header file fterrors.h (which is automatically included by freetype.h defines the handling of FreeType's enumeration constants. It can also be used to generate error message strings with a small macro trick explained below. Error Formats The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be defined in ftoption.h in order to make the higher byte indicate the module where the error has happened (this is not compatible with standard builds of FreeType 2, however). See the file ftmoderr.h for more details. Error Message Strings Error definitions are set up with special macros that allow client applications to build a table of error message strings. The strings are not included in a normal build of FreeType 2 to save space (most client applications do not use them). To do so, you have to define the following macros before including this file. FT_ERROR_START_LIST This macro is called before anything else to define the start of the error list. It is followed by several FT_ERROR_DEF calls. FT_ERROR_DEF( e, v, s ) This macro is called to define one single error. \u2018e\u2019 is the error code identifier (e.g., Invalid_Argument ), \u2018v\u2019 is the error's numerical value, and \u2018s\u2019 is the corresponding error string. FT_ERROR_END_LIST This macro ends the list. Additionally, you have to undefine FTERRORS_H_ before #including this file. Here is a simple example. #undef FTERRORS_H_ #define FT_ERRORDEF( e, v, s ) { e, s }, #define FT_ERROR_START_LIST { #define FT_ERROR_END_LIST { 0, NULL } }; const struct { int err_code; const char* err_msg; } ft_errors[] = #include An alternative to using an array is a switch statement. #undef FTERRORS_H_ #define FT_ERROR_START_LIST switch ( error_code ) { #define FT_ERRORDEF( e, v, s ) case v: return s; #define FT_ERROR_END_LIST } If you use FT_CONFIG_OPTION_USE_MODULE_ERRORS , error_code should be replaced with FT_ERROR_BASE(error_code) in the last example. FT_Error_String \u00b6 Defined in FT_ERRORS_H (freetype/fterrors.h). FT_EXPORT( const char * ) FT_Error_String ( FT_Error error_code ); FT_END_HEADER # endif /* FT_ERR_PROTOS_DEFINED */ # endif /* FT_INCLUDE_ERR_PROTOS */ # endif /* !(FTERRORS_H_ && __FTERRORS_H__) */ /* END */ Retrieve the description of a valid FreeType error code. input error_code A valid FreeType error code. return A C string or NULL , if any error occurred. note FreeType has to be compiled with FT_CONFIG_OPTION_ERROR_STRINGS or FT_DEBUG_LEVEL_ERROR to get meaningful descriptions. \u2018error_string\u2019 will be NULL otherwise. Module identification will be ignored: strcmp ( FT_Error_String ( FT_Err_Unknown_File_Format ), FT_Error_String ( BDF_Err_Unknown_File_Format ) ) == 0 ;","title":"Error Enumerations"},{"location":"ft2-error_enumerations.html#error-enumerations","text":"","title":"Error Enumerations"},{"location":"ft2-error_enumerations.html#synopsis","text":"The header file fterrors.h (which is automatically included by freetype.h defines the handling of FreeType's enumeration constants. It can also be used to generate error message strings with a small macro trick explained below. Error Formats The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be defined in ftoption.h in order to make the higher byte indicate the module where the error has happened (this is not compatible with standard builds of FreeType 2, however). See the file ftmoderr.h for more details. Error Message Strings Error definitions are set up with special macros that allow client applications to build a table of error message strings. The strings are not included in a normal build of FreeType 2 to save space (most client applications do not use them). To do so, you have to define the following macros before including this file. FT_ERROR_START_LIST This macro is called before anything else to define the start of the error list. It is followed by several FT_ERROR_DEF calls. FT_ERROR_DEF( e, v, s ) This macro is called to define one single error. \u2018e\u2019 is the error code identifier (e.g., Invalid_Argument ), \u2018v\u2019 is the error's numerical value, and \u2018s\u2019 is the corresponding error string. FT_ERROR_END_LIST This macro ends the list. Additionally, you have to undefine FTERRORS_H_ before #including this file. Here is a simple example. #undef FTERRORS_H_ #define FT_ERRORDEF( e, v, s ) { e, s }, #define FT_ERROR_START_LIST { #define FT_ERROR_END_LIST { 0, NULL } }; const struct { int err_code; const char* err_msg; } ft_errors[] = #include An alternative to using an array is a switch statement. #undef FTERRORS_H_ #define FT_ERROR_START_LIST switch ( error_code ) { #define FT_ERRORDEF( e, v, s ) case v: return s; #define FT_ERROR_END_LIST } If you use FT_CONFIG_OPTION_USE_MODULE_ERRORS , error_code should be replaced with FT_ERROR_BASE(error_code) in the last example.","title":"Synopsis"},{"location":"ft2-error_enumerations.html#ft_error_string","text":"Defined in FT_ERRORS_H (freetype/fterrors.h). FT_EXPORT( const char * ) FT_Error_String ( FT_Error error_code ); FT_END_HEADER # endif /* FT_ERR_PROTOS_DEFINED */ # endif /* FT_INCLUDE_ERR_PROTOS */ # endif /* !(FTERRORS_H_ && __FTERRORS_H__) */ /* END */ Retrieve the description of a valid FreeType error code.","title":"FT_Error_String"},{"location":"ft2-font_formats.html","text":"FreeType \u00bb Docs \u00bb Format-Specific API \u00bb Font Formats Font Formats \u00b6 Synopsis \u00b6 The single function in this section can be used to get the font format. Note that this information is not needed normally; however, there are special cases (like in PDF devices) where it is important to differentiate, in spite of FreeType's uniform API. FT_Get_Font_Format \u00b6 Defined in FT_FONT_FORMATS_H (freetype/ftfntfmt.h). FT_EXPORT( const char * ) FT_Get_Font_Format ( FT_Face face ); /* deprecated */ FT_EXPORT( const char * ) FT_Get_X11_Font_Format( FT_Face face ); Return a string describing the format of a given face. Possible values are \u2018TrueType\u2019, \u2018Type 1\u2019, \u2018BDF\u2019, \u2018PCF\u2019, \u2018Type 42\u2019, \u2018CID Type 1\u2019, \u2018CFF\u2019, \u2018PFR\u2019, and \u2018Windows FNT\u2019. The return value is suitable to be used as an X11 FONT_PROPERTY. input face Input face handle. return Font format string. NULL in case of error. note A deprecated name for the same function is FT_Get_X11_Font_Format .","title":"Font Formats"},{"location":"ft2-font_formats.html#font-formats","text":"","title":"Font Formats"},{"location":"ft2-font_formats.html#synopsis","text":"The single function in this section can be used to get the font format. Note that this information is not needed normally; however, there are special cases (like in PDF devices) where it is important to differentiate, in spite of FreeType's uniform API.","title":"Synopsis"},{"location":"ft2-font_formats.html#ft_get_font_format","text":"Defined in FT_FONT_FORMATS_H (freetype/ftfntfmt.h). FT_EXPORT( const char * ) FT_Get_Font_Format ( FT_Face face ); /* deprecated */ FT_EXPORT( const char * ) FT_Get_X11_Font_Format( FT_Face face ); Return a string describing the format of a given face. Possible values are \u2018TrueType\u2019, \u2018Type 1\u2019, \u2018BDF\u2019, \u2018PCF\u2019, \u2018Type 42\u2019, \u2018CID Type 1\u2019, \u2018CFF\u2019, \u2018PFR\u2019, and \u2018Windows FNT\u2019. The return value is suitable to be used as an X11 FONT_PROPERTY.","title":"FT_Get_Font_Format"},{"location":"ft2-gasp_table.html","text":"FreeType \u00bb Docs \u00bb Format-Specific API \u00bb Gasp Table Gasp Table \u00b6 Synopsis \u00b6 The function FT_Get_Gasp can be used to query a TrueType or OpenType font for specific entries in its \u2018gasp\u2019 table, if any. This is mainly useful when implementing native TrueType hinting with the bytecode interpreter to duplicate the Windows text rendering results. FT_GASP_XXX \u00b6 Defined in FT_GASP_H (freetype/ftgasp.h). # define FT_GASP_NO_TABLE -1 # define FT_GASP_DO_GRIDFIT 0x01 # define FT_GASP_DO_GRAY 0x02 # define FT_GASP_SYMMETRIC_GRIDFIT 0x04 # define FT_GASP_SYMMETRIC_SMOOTHING 0x08 A list of values and/or bit-flags returned by the FT_Get_Gasp function. values FT_GASP_NO_TABLE This special value means that there is no GASP table in this face. It is up to the client to decide what to do. FT_GASP_DO_GRIDFIT Grid-fitting and hinting should be performed at the specified ppem. This really means TrueType bytecode interpretation. If this bit is not set, no hinting gets applied. FT_GASP_DO_GRAY Anti-aliased rendering should be performed at the specified ppem. If not set, do monochrome rendering. FT_GASP_SYMMETRIC_SMOOTHING If set, smoothing along multiple axes must be used with ClearType. FT_GASP_SYMMETRIC_GRIDFIT Grid-fitting must be used with ClearType's symmetric smoothing. note The bit-flags FT_GASP_DO_GRIDFIT and FT_GASP_DO_GRAY are to be used for standard font rasterization only. Independently of that, FT_GASP_SYMMETRIC_SMOOTHING and FT_GASP_SYMMETRIC_GRIDFIT are to be used if ClearType is enabled (and FT_GASP_DO_GRIDFIT and FT_GASP_DO_GRAY are consequently ignored). \u2018ClearType\u2019 is Microsoft's implementation of LCD rendering, partly protected by patents. since 2.3.0 FT_Get_Gasp \u00b6 Defined in FT_GASP_H (freetype/ftgasp.h). FT_EXPORT( FT_Int ) FT_Get_Gasp ( FT_Face face, FT_UInt ppem ); For a TrueType or OpenType font file, return the rasterizer behaviour flags from the font's \u2018gasp\u2019 table corresponding to a given character pixel size. input face The source face handle. ppem The vertical character pixel size. return Bit flags (see FT_GASP_XXX ), or FT_GASP_NO_TABLE if there is no \u2018gasp\u2019 table in the face. note If you want to use the MM functionality of OpenType variation fonts (i.e., using FT_Set_Var_Design_Coordinates and friends), call this function after setting an instance since the return values can change. since 2.3.0","title":"Gasp Table"},{"location":"ft2-gasp_table.html#gasp-table","text":"","title":"Gasp Table"},{"location":"ft2-gasp_table.html#synopsis","text":"The function FT_Get_Gasp can be used to query a TrueType or OpenType font for specific entries in its \u2018gasp\u2019 table, if any. This is mainly useful when implementing native TrueType hinting with the bytecode interpreter to duplicate the Windows text rendering results.","title":"Synopsis"},{"location":"ft2-gasp_table.html#ft_gasp_xxx","text":"Defined in FT_GASP_H (freetype/ftgasp.h). # define FT_GASP_NO_TABLE -1 # define FT_GASP_DO_GRIDFIT 0x01 # define FT_GASP_DO_GRAY 0x02 # define FT_GASP_SYMMETRIC_GRIDFIT 0x04 # define FT_GASP_SYMMETRIC_SMOOTHING 0x08 A list of values and/or bit-flags returned by the FT_Get_Gasp function.","title":"FT_GASP_XXX"},{"location":"ft2-gasp_table.html#ft_get_gasp","text":"Defined in FT_GASP_H (freetype/ftgasp.h). FT_EXPORT( FT_Int ) FT_Get_Gasp ( FT_Face face, FT_UInt ppem ); For a TrueType or OpenType font file, return the rasterizer behaviour flags from the font's \u2018gasp\u2019 table corresponding to a given character pixel size.","title":"FT_Get_Gasp"},{"location":"ft2-glyph_management.html","text":"FreeType \u00bb Docs \u00bb Core API \u00bb Glyph Management Glyph Management \u00b6 Synopsis \u00b6 This section contains definitions used to manage glyph data through generic FT_Glyph objects. Each of them can contain a bitmap, a vector outline, or even images in other formats. These objects are detached from FT_Face , contrary to FT_GlyphSlot . FT_Glyph \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). typedef struct FT_GlyphRec_* FT_Glyph ; Handle to an object used to model generic glyph images. It is a pointer to the FT_GlyphRec structure and can contain a glyph bitmap or pointer. note Glyph objects are not owned by the library. You must thus release them manually (through FT_Done_Glyph ) before calling FT_Done_FreeType . FT_GlyphRec \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). typedef struct FT_GlyphRec_ { FT_Library library; const FT_Glyph_Class* clazz; FT_Glyph_Format format; FT_Vector advance; } FT_GlyphRec ; The root glyph structure contains a given glyph image plus its advance width in 16.16 fixed-point format. fields library A handle to the FreeType library object. clazz A pointer to the glyph's class. Private. format The format of the glyph's image. advance A 16.16 vector that gives the glyph's advance width. FT_BitmapGlyph \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). typedef struct FT_BitmapGlyphRec_* FT_BitmapGlyph ; A handle to an object used to model a bitmap glyph image. This is a sub-class of FT_Glyph , and a pointer to FT_BitmapGlyphRec . FT_BitmapGlyphRec \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). typedef struct FT_BitmapGlyphRec_ { FT_GlyphRec root; FT_Int left; FT_Int top; FT_Bitmap bitmap; } FT_BitmapGlyphRec ; A structure used for bitmap glyph images. This really is a \u2018sub-class\u2019 of FT_GlyphRec . fields root The root FT_Glyph fields. left The left-side bearing, i.e., the horizontal distance from the current pen position to the left border of the glyph bitmap. top The top-side bearing, i.e., the vertical distance from the current pen position to the top border of the glyph bitmap. This distance is positive for upwards y! bitmap A descriptor for the bitmap. note You can typecast an FT_Glyph to FT_BitmapGlyph if you have glyph->format == FT_GLYPH_FORMAT_BITMAP . This lets you access the bitmap's contents easily. The corresponding pixel buffer is always owned by FT_BitmapGlyph and is thus created and destroyed with it. FT_OutlineGlyph \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). typedef struct FT_OutlineGlyphRec_* FT_OutlineGlyph ; A handle to an object used to model an outline glyph image. This is a sub-class of FT_Glyph , and a pointer to FT_OutlineGlyphRec . FT_OutlineGlyphRec \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). typedef struct FT_OutlineGlyphRec_ { FT_GlyphRec root; FT_Outline outline; } FT_OutlineGlyphRec ; A structure used for outline (vectorial) glyph images. This really is a \u2018sub-class\u2019 of FT_GlyphRec . fields root The root FT_Glyph fields. outline A descriptor for the outline. note You can typecast an FT_Glyph to FT_OutlineGlyph if you have glyph->format == FT_GLYPH_FORMAT_OUTLINE . This lets you access the outline's content easily. As the outline is extracted from a glyph slot, its coordinates are expressed normally in 26.6 pixels, unless the flag FT_LOAD_NO_SCALE was used in FT_Load_Glyph or FT_Load_Char . The outline's tables are always owned by the object and are destroyed with it. FT_New_Glyph \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( FT_Error ) FT_New_Glyph ( FT_Library library, FT_Glyph_Format format, FT_Glyph *aglyph ); A function used to create a new empty glyph image. Note that the created FT_Glyph object must be released with FT_Done_Glyph . input library A handle to the FreeType library object. format The format of the glyph's image. output aglyph A handle to the glyph object. return FreeType error code. 0 means success. since 2.10 FT_Get_Glyph \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( FT_Error ) FT_Get_Glyph ( FT_GlyphSlot slot, FT_Glyph *aglyph ); A function used to extract a glyph image from a slot. Note that the created FT_Glyph object must be released with FT_Done_Glyph . input slot A handle to the source glyph slot. output aglyph A handle to the glyph object. return FreeType error code. 0 means success. note Because *aglyph->advance.x and *aglyph->advance.y are 16.16 fixed-point numbers, slot->advance.x and slot->advance.y (which are in 26.6 fixed-point format) must be in the range ]-32768;32768[. FT_Glyph_Copy \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( FT_Error ) FT_Glyph_Copy ( FT_Glyph source, FT_Glyph *target ); A function used to copy a glyph image. Note that the created FT_Glyph object must be released with FT_Done_Glyph . input source A handle to the source glyph object. output target A handle to the target glyph object. 0 in case of error. return FreeType error code. 0 means success. FT_Glyph_Transform \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( FT_Error ) FT_Glyph_Transform ( FT_Glyph glyph, FT_Matrix * matrix, FT_Vector * delta ); Transform a glyph image if its format is scalable. inout glyph A handle to the target glyph object. input matrix A pointer to a 2x2 matrix to apply. delta A pointer to a 2d vector to apply. Coordinates are expressed in 1/64th of a pixel. return FreeType error code (if not 0, the glyph format is not scalable). note The 2x2 transformation matrix is also applied to the glyph's advance vector. FT_Glyph_BBox_Mode \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). typedef enum FT_Glyph_BBox_Mode_ { FT_GLYPH_BBOX_UNSCALED = 0, FT_GLYPH_BBOX_SUBPIXELS = 0, FT_GLYPH_BBOX_GRIDFIT = 1, FT_GLYPH_BBOX_TRUNCATE = 2, FT_GLYPH_BBOX_PIXELS = 3 } FT_Glyph_BBox_Mode ; /* these constants are deprecated; use the corresponding */ /* ` FT_Glyph_BBox_Mode ` values instead */ # define ft_glyph_bbox_unscaled FT_GLYPH_BBOX_UNSCALED # define ft_glyph_bbox_subpixels FT_GLYPH_BBOX_SUBPIXELS # define ft_glyph_bbox_gridfit FT_GLYPH_BBOX_GRIDFIT # define ft_glyph_bbox_truncate FT_GLYPH_BBOX_TRUNCATE # define ft_glyph_bbox_pixels FT_GLYPH_BBOX_PIXELS The mode how the values of FT_Glyph_Get_CBox are returned. values FT_GLYPH_BBOX_UNSCALED Return unscaled font units. FT_GLYPH_BBOX_SUBPIXELS Return unfitted 26.6 coordinates. FT_GLYPH_BBOX_GRIDFIT Return grid-fitted 26.6 coordinates. FT_GLYPH_BBOX_TRUNCATE Return coordinates in integer pixels. FT_GLYPH_BBOX_PIXELS Return grid-fitted pixel coordinates. FT_Glyph_Get_CBox \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( void ) FT_Glyph_Get_CBox ( FT_Glyph glyph, FT_UInt bbox_mode, FT_BBox *acbox ); Return a glyph's \u2018control box\u2019. The control box encloses all the outline's points, including Bezier control points. Though it coincides with the exact bounding box for most glyphs, it can be slightly larger in some situations (like when rotating an outline that contains Bezier outside arcs). Computing the control box is very fast, while getting the bounding box can take much more time as it needs to walk over all segments and arcs in the outline. To get the latter, you can use the \u2018ftbbox\u2019 component, which is dedicated to this single task. input glyph A handle to the source glyph object. mode The mode that indicates how to interpret the returned bounding box values. output acbox The glyph coordinate bounding box. Coordinates are expressed in 1/64th of pixels if it is grid-fitted. note Coordinates are relative to the glyph origin, using the y upwards convention. If the glyph has been loaded with FT_LOAD_NO_SCALE , bbox_mode must be set to FT_GLYPH_BBOX_UNSCALED to get unscaled font units in 26.6 pixel format. The value FT_GLYPH_BBOX_SUBPIXELS is another name for this constant. If the font is tricky and the glyph has been loaded with FT_LOAD_NO_SCALE , the resulting CBox is meaningless. To get reasonable values for the CBox it is necessary to load the glyph at a large ppem value (so that the hinting instructions can properly shift and scale the subglyphs), then extracting the CBox, which can be eventually converted back to font units. Note that the maximum coordinates are exclusive, which means that one can compute the width and height of the glyph image (be it in integer or 26.6 pixels) as: width = bbox.xMax - bbox.xMin; height = bbox.yMax - bbox.yMin; Note also that for 26.6 coordinates, if bbox_mode is set to FT_GLYPH_BBOX_GRIDFIT , the coordinates will also be grid-fitted, which corresponds to: bbox.xMin = FLOOR(bbox.xMin); bbox.yMin = FLOOR(bbox.yMin); bbox.xMax = CEILING(bbox.xMax); bbox.yMax = CEILING(bbox.yMax); To get the bbox in pixel coordinates, set bbox_mode to FT_GLYPH_BBOX_TRUNCATE . To get the bbox in grid-fitted pixel coordinates, set bbox_mode to FT_GLYPH_BBOX_PIXELS . FT_Glyph_To_Bitmap \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( FT_Error ) FT_Glyph_To_Bitmap ( FT_Glyph * the_glyph, FT_Render_Mode render_mode, FT_Vector * origin, FT_Bool destroy ); Convert a given glyph object to a bitmap glyph object. inout the_glyph A pointer to a handle to the target glyph. input render_mode An enumeration that describes how the data is rendered. origin A pointer to a vector used to translate the glyph image before rendering. Can be 0 (if no translation). The origin is expressed in 26.6 pixels. destroy A boolean that indicates that the original glyph image should be destroyed by this function. It is never destroyed in case of error. return FreeType error code. 0 means success. note This function does nothing if the glyph format isn't scalable. The glyph image is translated with the origin vector before rendering. The first parameter is a pointer to an FT_Glyph handle, that will be replaced by this function (with newly allocated data). Typically, you would use (omitting error handling): FT_Glyph glyph; FT_BitmapGlyph glyph_bitmap; // load glyph error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAULT ); // extract glyph image error = FT_Get_Glyph( face->glyph, &glyph ); // convert to a bitmap (default render mode + destroying old) if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) { error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, 0, 1 ); if ( error ) // `glyph' unchanged ... } // access bitmap content by typecasting glyph_bitmap = (FT_BitmapGlyph)glyph; // do funny stuff with it, like blitting/drawing ... // discard glyph image (bitmap or not) FT_Done_Glyph( glyph ); Here is another example, again without error handling: FT_Glyph glyphs[MAX_GLYPHS] ... for ( idx = 0; i < MAX_GLYPHS; i++ ) error = FT_Load_Glyph( face, idx, FT_LOAD_DEFAULT ) || FT_Get_Glyph ( face->glyph, &glyphs[idx] ); ... for ( idx = 0; i < MAX_GLYPHS; i++ ) { FT_Glyph bitmap = glyphs[idx]; ... // after this call, `bitmap' no longer points into // the `glyphs' array (and the old value isn't destroyed) FT_Glyph_To_Bitmap( &bitmap, FT_RENDER_MODE_MONO, 0, 0 ); ... FT_Done_Glyph( bitmap ); } ... for ( idx = 0; i < MAX_GLYPHS; i++ ) FT_Done_Glyph( glyphs[idx] ); FT_Done_Glyph \u00b6 Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( void ) FT_Done_Glyph ( FT_Glyph glyph ); Destroy a given glyph. input glyph A handle to the target glyph object.","title":"Glyph Management"},{"location":"ft2-glyph_management.html#glyph-management","text":"","title":"Glyph Management"},{"location":"ft2-glyph_management.html#synopsis","text":"This section contains definitions used to manage glyph data through generic FT_Glyph objects. Each of them can contain a bitmap, a vector outline, or even images in other formats. These objects are detached from FT_Face , contrary to FT_GlyphSlot .","title":"Synopsis"},{"location":"ft2-glyph_management.html#ft_glyph","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). typedef struct FT_GlyphRec_* FT_Glyph ; Handle to an object used to model generic glyph images. It is a pointer to the FT_GlyphRec structure and can contain a glyph bitmap or pointer.","title":"FT_Glyph"},{"location":"ft2-glyph_management.html#ft_glyphrec","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). typedef struct FT_GlyphRec_ { FT_Library library; const FT_Glyph_Class* clazz; FT_Glyph_Format format; FT_Vector advance; } FT_GlyphRec ; The root glyph structure contains a given glyph image plus its advance width in 16.16 fixed-point format.","title":"FT_GlyphRec"},{"location":"ft2-glyph_management.html#ft_bitmapglyph","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). typedef struct FT_BitmapGlyphRec_* FT_BitmapGlyph ; A handle to an object used to model a bitmap glyph image. This is a sub-class of FT_Glyph , and a pointer to FT_BitmapGlyphRec .","title":"FT_BitmapGlyph"},{"location":"ft2-glyph_management.html#ft_bitmapglyphrec","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). typedef struct FT_BitmapGlyphRec_ { FT_GlyphRec root; FT_Int left; FT_Int top; FT_Bitmap bitmap; } FT_BitmapGlyphRec ; A structure used for bitmap glyph images. This really is a \u2018sub-class\u2019 of FT_GlyphRec .","title":"FT_BitmapGlyphRec"},{"location":"ft2-glyph_management.html#ft_outlineglyph","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). typedef struct FT_OutlineGlyphRec_* FT_OutlineGlyph ; A handle to an object used to model an outline glyph image. This is a sub-class of FT_Glyph , and a pointer to FT_OutlineGlyphRec .","title":"FT_OutlineGlyph"},{"location":"ft2-glyph_management.html#ft_outlineglyphrec","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). typedef struct FT_OutlineGlyphRec_ { FT_GlyphRec root; FT_Outline outline; } FT_OutlineGlyphRec ; A structure used for outline (vectorial) glyph images. This really is a \u2018sub-class\u2019 of FT_GlyphRec .","title":"FT_OutlineGlyphRec"},{"location":"ft2-glyph_management.html#ft_new_glyph","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( FT_Error ) FT_New_Glyph ( FT_Library library, FT_Glyph_Format format, FT_Glyph *aglyph ); A function used to create a new empty glyph image. Note that the created FT_Glyph object must be released with FT_Done_Glyph .","title":"FT_New_Glyph"},{"location":"ft2-glyph_management.html#ft_get_glyph","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( FT_Error ) FT_Get_Glyph ( FT_GlyphSlot slot, FT_Glyph *aglyph ); A function used to extract a glyph image from a slot. Note that the created FT_Glyph object must be released with FT_Done_Glyph .","title":"FT_Get_Glyph"},{"location":"ft2-glyph_management.html#ft_glyph_copy","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( FT_Error ) FT_Glyph_Copy ( FT_Glyph source, FT_Glyph *target ); A function used to copy a glyph image. Note that the created FT_Glyph object must be released with FT_Done_Glyph .","title":"FT_Glyph_Copy"},{"location":"ft2-glyph_management.html#ft_glyph_transform","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( FT_Error ) FT_Glyph_Transform ( FT_Glyph glyph, FT_Matrix * matrix, FT_Vector * delta ); Transform a glyph image if its format is scalable.","title":"FT_Glyph_Transform"},{"location":"ft2-glyph_management.html#ft_glyph_bbox_mode","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). typedef enum FT_Glyph_BBox_Mode_ { FT_GLYPH_BBOX_UNSCALED = 0, FT_GLYPH_BBOX_SUBPIXELS = 0, FT_GLYPH_BBOX_GRIDFIT = 1, FT_GLYPH_BBOX_TRUNCATE = 2, FT_GLYPH_BBOX_PIXELS = 3 } FT_Glyph_BBox_Mode ; /* these constants are deprecated; use the corresponding */ /* ` FT_Glyph_BBox_Mode ` values instead */ # define ft_glyph_bbox_unscaled FT_GLYPH_BBOX_UNSCALED # define ft_glyph_bbox_subpixels FT_GLYPH_BBOX_SUBPIXELS # define ft_glyph_bbox_gridfit FT_GLYPH_BBOX_GRIDFIT # define ft_glyph_bbox_truncate FT_GLYPH_BBOX_TRUNCATE # define ft_glyph_bbox_pixels FT_GLYPH_BBOX_PIXELS The mode how the values of FT_Glyph_Get_CBox are returned.","title":"FT_Glyph_BBox_Mode"},{"location":"ft2-glyph_management.html#ft_glyph_get_cbox","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( void ) FT_Glyph_Get_CBox ( FT_Glyph glyph, FT_UInt bbox_mode, FT_BBox *acbox ); Return a glyph's \u2018control box\u2019. The control box encloses all the outline's points, including Bezier control points. Though it coincides with the exact bounding box for most glyphs, it can be slightly larger in some situations (like when rotating an outline that contains Bezier outside arcs). Computing the control box is very fast, while getting the bounding box can take much more time as it needs to walk over all segments and arcs in the outline. To get the latter, you can use the \u2018ftbbox\u2019 component, which is dedicated to this single task.","title":"FT_Glyph_Get_CBox"},{"location":"ft2-glyph_management.html#ft_glyph_to_bitmap","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( FT_Error ) FT_Glyph_To_Bitmap ( FT_Glyph * the_glyph, FT_Render_Mode render_mode, FT_Vector * origin, FT_Bool destroy ); Convert a given glyph object to a bitmap glyph object.","title":"FT_Glyph_To_Bitmap"},{"location":"ft2-glyph_management.html#ft_done_glyph","text":"Defined in FT_GLYPH_H (freetype/ftglyph.h). FT_EXPORT( void ) FT_Done_Glyph ( FT_Glyph glyph ); Destroy a given glyph.","title":"FT_Done_Glyph"},{"location":"ft2-glyph_stroker.html","text":"FreeType \u00bb Docs \u00bb Support API \u00bb Glyph Stroker Glyph Stroker \u00b6 Synopsis \u00b6 This component generates stroked outlines of a given vectorial glyph. It also allows you to retrieve the \u2018outside\u2019 and/or the \u2018inside\u2019 borders of the stroke. This can be useful to generate \u2018bordered\u2019 glyph, i.e., glyphs displayed with a colored (and anti-aliased) border around their shape. FT_Stroker \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). typedef struct FT_StrokerRec_* FT_Stroker ; Opaque handle to a path stroker object. FT_Stroker_LineJoin \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). typedef enum FT_Stroker_LineJoin_ { FT_STROKER_LINEJOIN_ROUND = 0, FT_STROKER_LINEJOIN_BEVEL = 1, FT_STROKER_LINEJOIN_MITER_VARIABLE = 2, FT_STROKER_LINEJOIN_MITER = FT_STROKER_LINEJOIN_MITER_VARIABLE , FT_STROKER_LINEJOIN_MITER_FIXED = 3 } FT_Stroker_LineJoin ; These values determine how two joining lines are rendered in a stroker. values FT_STROKER_LINEJOIN_ROUND Used to render rounded line joins. Circular arcs are used to join two lines smoothly. FT_STROKER_LINEJOIN_BEVEL Used to render beveled line joins. The outer corner of the joined lines is filled by enclosing the triangular region of the corner with a straight line between the outer corners of each stroke. FT_STROKER_LINEJOIN_MITER_FIXED Used to render mitered line joins, with fixed bevels if the miter limit is exceeded. The outer edges of the strokes for the two segments are extended until they meet at an angle. A bevel join (see above) is used if the segments meet at too sharp an angle and the outer edges meet beyond a distance corresponding to the meter limit. This prevents long spikes being created. FT_STROKER_LINEJOIN_MITER_FIXED generates a miter line join as used in PostScript and PDF. FT_STROKER_LINEJOIN_MITER_VARIABLE FT_STROKER_LINEJOIN_MITER Used to render mitered line joins, with variable bevels if the miter limit is exceeded. The intersection of the strokes is clipped perpendicularly to the bisector, at a distance corresponding to the miter limit. This prevents long spikes being created. FT_STROKER_LINEJOIN_MITER_VARIABLE generates a mitered line join as used in XPS. FT_STROKER_LINEJOIN_MITER is an alias for FT_STROKER_LINEJOIN_MITER_VARIABLE , retained for backward compatibility. FT_Stroker_LineCap \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). typedef enum FT_Stroker_LineCap_ { FT_STROKER_LINECAP_BUTT = 0, FT_STROKER_LINECAP_ROUND , FT_STROKER_LINECAP_SQUARE } FT_Stroker_LineCap ; These values determine how the end of opened sub-paths are rendered in a stroke. values FT_STROKER_LINECAP_BUTT The end of lines is rendered as a full stop on the last point itself. FT_STROKER_LINECAP_ROUND The end of lines is rendered as a half-circle around the last point. FT_STROKER_LINECAP_SQUARE The end of lines is rendered as a square around the last point. FT_StrokerBorder \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). typedef enum FT_StrokerBorder_ { FT_STROKER_BORDER_LEFT = 0, FT_STROKER_BORDER_RIGHT } FT_StrokerBorder ; These values are used to select a given stroke border in FT_Stroker_GetBorderCounts and FT_Stroker_ExportBorder . values FT_STROKER_BORDER_LEFT Select the left border, relative to the drawing direction. FT_STROKER_BORDER_RIGHT Select the right border, relative to the drawing direction. note Applications are generally interested in the \u2018inside\u2019 and \u2018outside\u2019 borders. However, there is no direct mapping between these and the \u2018left\u2019 and \u2018right\u2019 ones, since this really depends on the glyph's drawing orientation, which varies between font formats. You can however use FT_Outline_GetInsideBorder and FT_Outline_GetOutsideBorder to get these. FT_Outline_GetInsideBorder \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_StrokerBorder ) FT_Outline_GetInsideBorder ( FT_Outline * outline ); Retrieve the FT_StrokerBorder value corresponding to the \u2018inside\u2019 borders of a given outline. input outline The source outline handle. return The border index. FT_STROKER_BORDER_RIGHT for empty or invalid outlines. FT_Outline_GetOutsideBorder \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_StrokerBorder ) FT_Outline_GetOutsideBorder ( FT_Outline * outline ); Retrieve the FT_StrokerBorder value corresponding to the \u2018outside\u2019 borders of a given outline. input outline The source outline handle. return The border index. FT_STROKER_BORDER_LEFT for empty or invalid outlines. FT_Glyph_Stroke \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Glyph_Stroke ( FT_Glyph *pglyph, FT_Stroker stroker, FT_Bool destroy ); Stroke a given outline glyph object with a given stroker. inout pglyph Source glyph handle on input, new glyph handle on output. input stroker A stroker handle. destroy A Boolean. If 1, the source glyph object is destroyed on success. return FreeType error code. 0 means success. note The source glyph is untouched in case of error. Adding stroke may yield a significantly wider and taller glyph depending on how large of a radius was used to stroke the glyph. You may need to manually adjust horizontal and vertical advance amounts to account for this added size. FT_Glyph_StrokeBorder \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Glyph_StrokeBorder ( FT_Glyph *pglyph, FT_Stroker stroker, FT_Bool inside, FT_Bool destroy ); Stroke a given outline glyph object with a given stroker, but only return either its inside or outside border. inout pglyph Source glyph handle on input, new glyph handle on output. input stroker A stroker handle. inside A Boolean. If 1, return the inside border, otherwise the outside border. destroy A Boolean. If 1, the source glyph object is destroyed on success. return FreeType error code. 0 means success. note The source glyph is untouched in case of error. Adding stroke may yield a significantly wider and taller glyph depending on how large of a radius was used to stroke the glyph. You may need to manually adjust horizontal and vertical advance amounts to account for this added size. FT_Stroker_New \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_New ( FT_Library library, FT_Stroker *astroker ); Create a new stroker object. input library FreeType library handle. output astroker A new stroker object handle. NULL in case of error. return FreeType error code. 0 means success. FT_Stroker_Set \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( void ) FT_Stroker_Set ( FT_Stroker stroker, FT_Fixed radius, FT_Stroker_LineCap line_cap, FT_Stroker_LineJoin line_join, FT_Fixed miter_limit ); Reset a stroker object's attributes. input stroker The target stroker handle. radius The border radius. line_cap The line cap style. line_join The line join style. miter_limit The maximum reciprocal sine of half-angle at the miter join, expressed as 16.16 fixed point value. note The radius is expressed in the same units as the outline coordinates. The miter_limit multiplied by the radius gives the maximum size of a miter spike, at which it is clipped for FT_STROKER_LINEJOIN_MITER_VARIABLE or replaced with a bevel join for FT_STROKER_LINEJOIN_MITER_FIXED . This function calls FT_Stroker_Rewind automatically. FT_Stroker_Rewind \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( void ) FT_Stroker_Rewind ( FT_Stroker stroker ); Reset a stroker object without changing its attributes. You should call this function before beginning a new series of calls to FT_Stroker_BeginSubPath or FT_Stroker_EndSubPath . input stroker The target stroker handle. FT_Stroker_ParseOutline \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_ParseOutline ( FT_Stroker stroker, FT_Outline * outline, FT_Bool opened ); A convenience function used to parse a whole outline with the stroker. The resulting outline(s) can be retrieved later by functions like FT_Stroker_GetCounts and FT_Stroker_Export . input stroker The target stroker handle. outline The source outline. opened A boolean. If 1, the outline is treated as an open path instead of a closed one. return FreeType error code. 0 means success. note If opened is 0 (the default), the outline is treated as a closed path, and the stroker generates two distinct \u2018border\u2019 outlines. If opened is 1, the outline is processed as an open path, and the stroker generates a single \u2018stroke\u2019 outline. This function calls FT_Stroker_Rewind automatically. FT_Stroker_Done \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( void ) FT_Stroker_Done ( FT_Stroker stroker ); Destroy a stroker object. input stroker A stroker handle. Can be NULL . FT_Stroker_BeginSubPath \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_BeginSubPath ( FT_Stroker stroker, FT_Vector * to, FT_Bool open ); Start a new sub-path in the stroker. input stroker The target stroker handle. to A pointer to the start vector. open A boolean. If 1, the sub-path is treated as an open one. return FreeType error code. 0 means success. note This function is useful when you need to stroke a path that is not stored as an FT_Outline object. FT_Stroker_EndSubPath \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_EndSubPath ( FT_Stroker stroker ); Close the current sub-path in the stroker. input stroker The target stroker handle. return FreeType error code. 0 means success. note You should call this function after FT_Stroker_BeginSubPath . If the subpath was not \u2018opened\u2019, this function \u2018draws\u2019 a single line segment to the start position when needed. FT_Stroker_LineTo \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_LineTo ( FT_Stroker stroker, FT_Vector * to ); \u2018Draw\u2019 a single line segment in the stroker's current sub-path, from the last position. input stroker The target stroker handle. to A pointer to the destination point. return FreeType error code. 0 means success. note You should call this function between FT_Stroker_BeginSubPath and FT_Stroker_EndSubPath . FT_Stroker_ConicTo \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_ConicTo ( FT_Stroker stroker, FT_Vector * control, FT_Vector * to ); \u2018Draw\u2019 a single quadratic Bezier in the stroker's current sub-path, from the last position. input stroker The target stroker handle. control A pointer to a Bezier control point. to A pointer to the destination point. return FreeType error code. 0 means success. note You should call this function between FT_Stroker_BeginSubPath and FT_Stroker_EndSubPath . FT_Stroker_CubicTo \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_CubicTo ( FT_Stroker stroker, FT_Vector * control1, FT_Vector * control2, FT_Vector * to ); \u2018Draw\u2019 a single cubic Bezier in the stroker's current sub-path, from the last position. input stroker The target stroker handle. control1 A pointer to the first Bezier control point. control2 A pointer to second Bezier control point. to A pointer to the destination point. return FreeType error code. 0 means success. note You should call this function between FT_Stroker_BeginSubPath and FT_Stroker_EndSubPath . FT_Stroker_GetBorderCounts \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_GetBorderCounts ( FT_Stroker stroker, FT_StrokerBorder border, FT_UInt *anum_points, FT_UInt *anum_contours ); Call this function once you have finished parsing your paths with the stroker. It returns the number of points and contours necessary to export one of the \u2018border\u2019 or \u2018stroke\u2019 outlines generated by the stroker. input stroker The target stroker handle. border The border index. output anum_points The number of points. anum_contours The number of contours. return FreeType error code. 0 means success. note When an outline, or a sub-path, is \u2018closed\u2019, the stroker generates two independent \u2018border\u2019 outlines, named \u2018left\u2019 and \u2018right\u2019. When the outline, or a sub-path, is \u2018opened\u2019, the stroker merges the \u2018border\u2019 outlines with caps. The \u2018left\u2019 border receives all points, while the \u2018right\u2019 border becomes empty. Use the function FT_Stroker_GetCounts instead if you want to retrieve the counts associated to both borders. FT_Stroker_ExportBorder \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( void ) FT_Stroker_ExportBorder ( FT_Stroker stroker, FT_StrokerBorder border, FT_Outline * outline ); Call this function after FT_Stroker_GetBorderCounts to export the corresponding border to your own FT_Outline structure. Note that this function appends the border points and contours to your outline, but does not try to resize its arrays. input stroker The target stroker handle. border The border index. outline The target outline handle. note Always call this function after FT_Stroker_GetBorderCounts to get sure that there is enough room in your FT_Outline object to receive all new data. When an outline, or a sub-path, is \u2018closed\u2019, the stroker generates two independent \u2018border\u2019 outlines, named \u2018left\u2019 and \u2018right\u2019. When the outline, or a sub-path, is \u2018opened\u2019, the stroker merges the \u2018border\u2019 outlines with caps. The \u2018left\u2019 border receives all points, while the \u2018right\u2019 border becomes empty. Use the function FT_Stroker_Export instead if you want to retrieve all borders at once. FT_Stroker_GetCounts \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_GetCounts ( FT_Stroker stroker, FT_UInt *anum_points, FT_UInt *anum_contours ); Call this function once you have finished parsing your paths with the stroker. It returns the number of points and contours necessary to export all points/borders from the stroked outline/path. input stroker The target stroker handle. output anum_points The number of points. anum_contours The number of contours. return FreeType error code. 0 means success. FT_Stroker_Export \u00b6 Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( void ) FT_Stroker_Export ( FT_Stroker stroker, FT_Outline * outline ); Call this function after FT_Stroker_GetBorderCounts to export all borders to your own FT_Outline structure. Note that this function appends the border points and contours to your outline, but does not try to resize its arrays. input stroker The target stroker handle. outline The target outline handle.","title":"Glyph Stroker"},{"location":"ft2-glyph_stroker.html#glyph-stroker","text":"","title":"Glyph Stroker"},{"location":"ft2-glyph_stroker.html#synopsis","text":"This component generates stroked outlines of a given vectorial glyph. It also allows you to retrieve the \u2018outside\u2019 and/or the \u2018inside\u2019 borders of the stroke. This can be useful to generate \u2018bordered\u2019 glyph, i.e., glyphs displayed with a colored (and anti-aliased) border around their shape.","title":"Synopsis"},{"location":"ft2-glyph_stroker.html#ft_stroker","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). typedef struct FT_StrokerRec_* FT_Stroker ; Opaque handle to a path stroker object.","title":"FT_Stroker"},{"location":"ft2-glyph_stroker.html#ft_stroker_linejoin","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). typedef enum FT_Stroker_LineJoin_ { FT_STROKER_LINEJOIN_ROUND = 0, FT_STROKER_LINEJOIN_BEVEL = 1, FT_STROKER_LINEJOIN_MITER_VARIABLE = 2, FT_STROKER_LINEJOIN_MITER = FT_STROKER_LINEJOIN_MITER_VARIABLE , FT_STROKER_LINEJOIN_MITER_FIXED = 3 } FT_Stroker_LineJoin ; These values determine how two joining lines are rendered in a stroker.","title":"FT_Stroker_LineJoin"},{"location":"ft2-glyph_stroker.html#ft_stroker_linecap","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). typedef enum FT_Stroker_LineCap_ { FT_STROKER_LINECAP_BUTT = 0, FT_STROKER_LINECAP_ROUND , FT_STROKER_LINECAP_SQUARE } FT_Stroker_LineCap ; These values determine how the end of opened sub-paths are rendered in a stroke.","title":"FT_Stroker_LineCap"},{"location":"ft2-glyph_stroker.html#ft_strokerborder","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). typedef enum FT_StrokerBorder_ { FT_STROKER_BORDER_LEFT = 0, FT_STROKER_BORDER_RIGHT } FT_StrokerBorder ; These values are used to select a given stroke border in FT_Stroker_GetBorderCounts and FT_Stroker_ExportBorder .","title":"FT_StrokerBorder"},{"location":"ft2-glyph_stroker.html#ft_outline_getinsideborder","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_StrokerBorder ) FT_Outline_GetInsideBorder ( FT_Outline * outline ); Retrieve the FT_StrokerBorder value corresponding to the \u2018inside\u2019 borders of a given outline.","title":"FT_Outline_GetInsideBorder"},{"location":"ft2-glyph_stroker.html#ft_outline_getoutsideborder","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_StrokerBorder ) FT_Outline_GetOutsideBorder ( FT_Outline * outline ); Retrieve the FT_StrokerBorder value corresponding to the \u2018outside\u2019 borders of a given outline.","title":"FT_Outline_GetOutsideBorder"},{"location":"ft2-glyph_stroker.html#ft_glyph_stroke","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Glyph_Stroke ( FT_Glyph *pglyph, FT_Stroker stroker, FT_Bool destroy ); Stroke a given outline glyph object with a given stroker.","title":"FT_Glyph_Stroke"},{"location":"ft2-glyph_stroker.html#ft_glyph_strokeborder","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Glyph_StrokeBorder ( FT_Glyph *pglyph, FT_Stroker stroker, FT_Bool inside, FT_Bool destroy ); Stroke a given outline glyph object with a given stroker, but only return either its inside or outside border.","title":"FT_Glyph_StrokeBorder"},{"location":"ft2-glyph_stroker.html#ft_stroker_new","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_New ( FT_Library library, FT_Stroker *astroker ); Create a new stroker object.","title":"FT_Stroker_New"},{"location":"ft2-glyph_stroker.html#ft_stroker_set","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( void ) FT_Stroker_Set ( FT_Stroker stroker, FT_Fixed radius, FT_Stroker_LineCap line_cap, FT_Stroker_LineJoin line_join, FT_Fixed miter_limit ); Reset a stroker object's attributes.","title":"FT_Stroker_Set"},{"location":"ft2-glyph_stroker.html#ft_stroker_rewind","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( void ) FT_Stroker_Rewind ( FT_Stroker stroker ); Reset a stroker object without changing its attributes. You should call this function before beginning a new series of calls to FT_Stroker_BeginSubPath or FT_Stroker_EndSubPath .","title":"FT_Stroker_Rewind"},{"location":"ft2-glyph_stroker.html#ft_stroker_parseoutline","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_ParseOutline ( FT_Stroker stroker, FT_Outline * outline, FT_Bool opened ); A convenience function used to parse a whole outline with the stroker. The resulting outline(s) can be retrieved later by functions like FT_Stroker_GetCounts and FT_Stroker_Export .","title":"FT_Stroker_ParseOutline"},{"location":"ft2-glyph_stroker.html#ft_stroker_done","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( void ) FT_Stroker_Done ( FT_Stroker stroker ); Destroy a stroker object.","title":"FT_Stroker_Done"},{"location":"ft2-glyph_stroker.html#ft_stroker_beginsubpath","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_BeginSubPath ( FT_Stroker stroker, FT_Vector * to, FT_Bool open ); Start a new sub-path in the stroker.","title":"FT_Stroker_BeginSubPath"},{"location":"ft2-glyph_stroker.html#ft_stroker_endsubpath","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_EndSubPath ( FT_Stroker stroker ); Close the current sub-path in the stroker.","title":"FT_Stroker_EndSubPath"},{"location":"ft2-glyph_stroker.html#ft_stroker_lineto","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_LineTo ( FT_Stroker stroker, FT_Vector * to ); \u2018Draw\u2019 a single line segment in the stroker's current sub-path, from the last position.","title":"FT_Stroker_LineTo"},{"location":"ft2-glyph_stroker.html#ft_stroker_conicto","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_ConicTo ( FT_Stroker stroker, FT_Vector * control, FT_Vector * to ); \u2018Draw\u2019 a single quadratic Bezier in the stroker's current sub-path, from the last position.","title":"FT_Stroker_ConicTo"},{"location":"ft2-glyph_stroker.html#ft_stroker_cubicto","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_CubicTo ( FT_Stroker stroker, FT_Vector * control1, FT_Vector * control2, FT_Vector * to ); \u2018Draw\u2019 a single cubic Bezier in the stroker's current sub-path, from the last position.","title":"FT_Stroker_CubicTo"},{"location":"ft2-glyph_stroker.html#ft_stroker_getbordercounts","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_GetBorderCounts ( FT_Stroker stroker, FT_StrokerBorder border, FT_UInt *anum_points, FT_UInt *anum_contours ); Call this function once you have finished parsing your paths with the stroker. It returns the number of points and contours necessary to export one of the \u2018border\u2019 or \u2018stroke\u2019 outlines generated by the stroker.","title":"FT_Stroker_GetBorderCounts"},{"location":"ft2-glyph_stroker.html#ft_stroker_exportborder","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( void ) FT_Stroker_ExportBorder ( FT_Stroker stroker, FT_StrokerBorder border, FT_Outline * outline ); Call this function after FT_Stroker_GetBorderCounts to export the corresponding border to your own FT_Outline structure. Note that this function appends the border points and contours to your outline, but does not try to resize its arrays.","title":"FT_Stroker_ExportBorder"},{"location":"ft2-glyph_stroker.html#ft_stroker_getcounts","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( FT_Error ) FT_Stroker_GetCounts ( FT_Stroker stroker, FT_UInt *anum_points, FT_UInt *anum_contours ); Call this function once you have finished parsing your paths with the stroker. It returns the number of points and contours necessary to export all points/borders from the stroked outline/path.","title":"FT_Stroker_GetCounts"},{"location":"ft2-glyph_stroker.html#ft_stroker_export","text":"Defined in FT_STROKER_H (freetype/ftstroke.h). FT_EXPORT( void ) FT_Stroker_Export ( FT_Stroker stroker, FT_Outline * outline ); Call this function after FT_Stroker_GetBorderCounts to export all borders to your own FT_Outline structure. Note that this function appends the border points and contours to your outline, but does not try to resize its arrays.","title":"FT_Stroker_Export"},{"location":"ft2-glyph_variants.html","text":"FreeType \u00bb Docs \u00bb Core API \u00bb Unicode Variation Sequences Unicode Variation Sequences \u00b6 Synopsis \u00b6 Many characters, especially for CJK scripts, have variant forms. They are a sort of grey area somewhere between being totally irrelevant and semantically distinct; for this reason, the Unicode consortium decided to introduce Variation Sequences (VS), consisting of a Unicode base character and a variation selector instead of further extending the already huge number of characters. Unicode maintains two different sets, namely \u2018Standardized Variation Sequences\u2019 and registered \u2018Ideographic Variation Sequences\u2019 (IVS), collected in the \u2018Ideographic Variation Database\u2019 (IVD). https://unicode.org/Public/UCD/latest/ucd/StandardizedVariants.txt https://unicode.org/reports/tr37/ https://unicode.org/ivd/ To date (January 2017), the character with the most ideographic variations is U+9089, having 32 such IVS. Three Mongolian Variation Selectors have the values U+180B-U+180D; 256 generic Variation Selectors are encoded in the ranges U+FE00-U+FE0F and U+E0100-U+E01EF. IVS currently use Variation Selectors from the range U+E0100-U+E01EF only. A VS consists of the base character value followed by a single Variation Selector. For example, to get the first variation of U+9089, you have to write the character sequence U+9089 U+E0100 . Adobe and MS decided to support both standardized and ideographic VS with a new cmap subtable (format 14). It is an odd subtable because it is not a mapping of input code points to glyphs, but contains lists of all variations supported by the font. A variation may be either \u2018default\u2019 or \u2018non-default\u2019 for a given font. A default variation is the one you will get for that code point if you look it up in the standard Unicode cmap. A non-default variation is a different glyph. FT_Face_GetCharVariantIndex \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_UInt ) FT_Face_GetCharVariantIndex ( FT_Face face, FT_ULong charcode, FT_ULong variantSelector ); Return the glyph index of a given character code as modified by the variation selector. input face A handle to the source face object. charcode The character code point in Unicode. variantSelector The Unicode code point of the variation selector. return The glyph index. 0 means either \u2018undefined character code\u2019, or \u2018undefined selector code\u2019, or \u2018no variation selector cmap subtable\u2019, or \u2018current CharMap is not Unicode\u2019. note If you use FreeType to manipulate the contents of font files directly, be aware that the glyph index returned by this function doesn't always correspond to the internal indices used within the file. This is done to ensure that value 0 always corresponds to the \u2018missing glyph\u2019. This function is only meaningful if a) the font has a variation selector cmap sub table, and b) the current charmap has a Unicode encoding. since 2.3.6 FT_Face_GetCharVariantIsDefault \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Int ) FT_Face_GetCharVariantIsDefault ( FT_Face face, FT_ULong charcode, FT_ULong variantSelector ); Check whether this variation of this Unicode character is the one to be found in the charmap. input face A handle to the source face object. charcode The character codepoint in Unicode. variantSelector The Unicode codepoint of the variation selector. return 1 if found in the standard (Unicode) cmap, 0 if found in the variation selector cmap, or -1 if it is not a variation. note This function is only meaningful if the font has a variation selector cmap subtable. since 2.3.6 FT_Face_GetVariantSelectors \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_UInt32 * ) FT_Face_GetVariantSelectors ( FT_Face face ); Return a zero-terminated list of Unicode variation selectors found in the font. input face A handle to the source face object. return A pointer to an array of selector code points, or NULL if there is no valid variation selector cmap subtable. note The last item in the array is 0; the array is owned by the FT_Face object but can be overwritten or released on the next call to a FreeType function. since 2.3.6 FT_Face_GetVariantsOfChar \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_UInt32 * ) FT_Face_GetVariantsOfChar ( FT_Face face, FT_ULong charcode ); Return a zero-terminated list of Unicode variation selectors found for the specified character code. input face A handle to the source face object. charcode The character codepoint in Unicode. return A pointer to an array of variation selector code points that are active for the given character, or NULL if the corresponding list is empty. note The last item in the array is 0; the array is owned by the FT_Face object but can be overwritten or released on the next call to a FreeType function. since 2.3.6 FT_Face_GetCharsOfVariant \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_UInt32 * ) FT_Face_GetCharsOfVariant ( FT_Face face, FT_ULong variantSelector ); Return a zero-terminated list of Unicode character codes found for the specified variation selector. input face A handle to the source face object. variantSelector The variation selector code point in Unicode. return A list of all the code points that are specified by this selector (both default and non-default codes are returned) or NULL if there is no valid cmap or the variation selector is invalid. note The last item in the array is 0; the array is owned by the FT_Face object but can be overwritten or released on the next call to a FreeType function. since 2.3.6","title":"Unicode Variation Sequences"},{"location":"ft2-glyph_variants.html#unicode-variation-sequences","text":"","title":"Unicode Variation Sequences"},{"location":"ft2-glyph_variants.html#synopsis","text":"Many characters, especially for CJK scripts, have variant forms. They are a sort of grey area somewhere between being totally irrelevant and semantically distinct; for this reason, the Unicode consortium decided to introduce Variation Sequences (VS), consisting of a Unicode base character and a variation selector instead of further extending the already huge number of characters. Unicode maintains two different sets, namely \u2018Standardized Variation Sequences\u2019 and registered \u2018Ideographic Variation Sequences\u2019 (IVS), collected in the \u2018Ideographic Variation Database\u2019 (IVD). https://unicode.org/Public/UCD/latest/ucd/StandardizedVariants.txt https://unicode.org/reports/tr37/ https://unicode.org/ivd/ To date (January 2017), the character with the most ideographic variations is U+9089, having 32 such IVS. Three Mongolian Variation Selectors have the values U+180B-U+180D; 256 generic Variation Selectors are encoded in the ranges U+FE00-U+FE0F and U+E0100-U+E01EF. IVS currently use Variation Selectors from the range U+E0100-U+E01EF only. A VS consists of the base character value followed by a single Variation Selector. For example, to get the first variation of U+9089, you have to write the character sequence U+9089 U+E0100 . Adobe and MS decided to support both standardized and ideographic VS with a new cmap subtable (format 14). It is an odd subtable because it is not a mapping of input code points to glyphs, but contains lists of all variations supported by the font. A variation may be either \u2018default\u2019 or \u2018non-default\u2019 for a given font. A default variation is the one you will get for that code point if you look it up in the standard Unicode cmap. A non-default variation is a different glyph.","title":"Synopsis"},{"location":"ft2-glyph_variants.html#ft_face_getcharvariantindex","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_UInt ) FT_Face_GetCharVariantIndex ( FT_Face face, FT_ULong charcode, FT_ULong variantSelector ); Return the glyph index of a given character code as modified by the variation selector.","title":"FT_Face_GetCharVariantIndex"},{"location":"ft2-glyph_variants.html#ft_face_getcharvariantisdefault","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Int ) FT_Face_GetCharVariantIsDefault ( FT_Face face, FT_ULong charcode, FT_ULong variantSelector ); Check whether this variation of this Unicode character is the one to be found in the charmap.","title":"FT_Face_GetCharVariantIsDefault"},{"location":"ft2-glyph_variants.html#ft_face_getvariantselectors","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_UInt32 * ) FT_Face_GetVariantSelectors ( FT_Face face ); Return a zero-terminated list of Unicode variation selectors found in the font.","title":"FT_Face_GetVariantSelectors"},{"location":"ft2-glyph_variants.html#ft_face_getvariantsofchar","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_UInt32 * ) FT_Face_GetVariantsOfChar ( FT_Face face, FT_ULong charcode ); Return a zero-terminated list of Unicode variation selectors found for the specified character code.","title":"FT_Face_GetVariantsOfChar"},{"location":"ft2-glyph_variants.html#ft_face_getcharsofvariant","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_UInt32 * ) FT_Face_GetCharsOfVariant ( FT_Face face, FT_ULong variantSelector ); Return a zero-terminated list of Unicode character codes found for the specified variation selector.","title":"FT_Face_GetCharsOfVariant"},{"location":"ft2-gx_validation.html","text":"FreeType \u00bb Docs \u00bb Miscellaneous \u00bb TrueTypeGX/AAT Validation TrueTypeGX/AAT Validation \u00b6 Synopsis \u00b6 This section contains the declaration of functions to validate some TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd, trak, prop, lcar). FT_TrueTypeGX_Validate \u00b6 Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h). FT_EXPORT( FT_Error ) FT_TrueTypeGX_Validate ( FT_Face face, FT_UInt validation_flags, FT_Bytes tables[ FT_VALIDATE_GX_LENGTH ], FT_UInt table_length ); Validate various TrueTypeGX tables to assure that all offsets and indices are valid. The idea is that a higher-level library that actually does the text layout can access those tables without error checking (which can be quite time consuming). input face A handle to the input face. validation_flags A bit field that specifies the tables to be validated. See FT_VALIDATE_GXXXX for possible values. table_length The size of the tables array. Normally, FT_VALIDATE_GX_LENGTH should be passed. output tables The array where all validated sfnt tables are stored. The array itself must be allocated by a client. return FreeType error code. 0 means success. note This function only works with TrueTypeGX fonts, returning an error otherwise. After use, the application should deallocate the buffers pointed to by each tables element, by calling FT_TrueTypeGX_Free . A NULL value indicates that the table either doesn't exist in the font, the application hasn't asked for validation, or the validator doesn't have the ability to validate the sfnt table. FT_TrueTypeGX_Free \u00b6 Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h). FT_EXPORT( void ) FT_TrueTypeGX_Free ( FT_Face face, FT_Bytes table ); Free the buffer allocated by TrueTypeGX validator. input face A handle to the input face. table The pointer to the buffer allocated by FT_TrueTypeGX_Validate . note This function must be used to free the buffer allocated by FT_TrueTypeGX_Validate only. FT_ClassicKern_Validate \u00b6 Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h). FT_EXPORT( FT_Error ) FT_ClassicKern_Validate ( FT_Face face, FT_UInt validation_flags, FT_Bytes *ckern_table ); Validate classic (16-bit format) kern table to assure that the offsets and indices are valid. The idea is that a higher-level library that actually does the text layout can access those tables without error checking (which can be quite time consuming). The \u2018kern\u2019 table validator in FT_TrueTypeGX_Validate deals with both the new 32-bit format and the classic 16-bit format, while FT_ClassicKern_Validate only supports the classic 16-bit format. input face A handle to the input face. validation_flags A bit field that specifies the dialect to be validated. See FT_VALIDATE_CKERNXXX for possible values. output ckern_table A pointer to the kern table. return FreeType error code. 0 means success. note After use, the application should deallocate the buffers pointed to by ckern_table , by calling FT_ClassicKern_Free . A NULL value indicates that the table doesn't exist in the font. FT_ClassicKern_Free \u00b6 Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h). FT_EXPORT( void ) FT_ClassicKern_Free ( FT_Face face, FT_Bytes table ); Free the buffer allocated by classic Kern validator. input face A handle to the input face. table The pointer to the buffer that is allocated by FT_ClassicKern_Validate . note This function must be used to free the buffer allocated by FT_ClassicKern_Validate only. FT_VALIDATE_GX_LENGTH \u00b6 Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h). # define FT_VALIDATE_GX_LENGTH ( FT_VALIDATE_GX_LAST_INDEX + 1 ) The number of tables checked in this module. Use it as a parameter for the table-length argument of function FT_TrueTypeGX_Validate . FT_VALIDATE_GXXXX \u00b6 Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h). # define FT_VALIDATE_feat FT_VALIDATE_GX_BITFIELD( feat ) # define FT_VALIDATE_mort FT_VALIDATE_GX_BITFIELD( mort ) # define FT_VALIDATE_morx FT_VALIDATE_GX_BITFIELD( morx ) # define FT_VALIDATE_bsln FT_VALIDATE_GX_BITFIELD( bsln ) # define FT_VALIDATE_just FT_VALIDATE_GX_BITFIELD( just ) # define FT_VALIDATE_kern FT_VALIDATE_GX_BITFIELD( kern ) # define FT_VALIDATE_opbd FT_VALIDATE_GX_BITFIELD( opbd ) # define FT_VALIDATE_trak FT_VALIDATE_GX_BITFIELD( trak ) # define FT_VALIDATE_prop FT_VALIDATE_GX_BITFIELD( prop ) # define FT_VALIDATE_lcar FT_VALIDATE_GX_BITFIELD( lcar ) # define FT_VALIDATE_GX ( FT_VALIDATE_feat | \\ FT_VALIDATE_mort | \\ FT_VALIDATE_morx | \\ FT_VALIDATE_bsln | \\ FT_VALIDATE_just | \\ FT_VALIDATE_kern | \\ FT_VALIDATE_opbd | \\ FT_VALIDATE_trak | \\ FT_VALIDATE_prop | \\ FT_VALIDATE_lcar ) A list of bit-field constants used with FT_TrueTypeGX_Validate to indicate which TrueTypeGX/AAT Type tables should be validated. values FT_VALIDATE_feat Validate \u2018feat\u2019 table. FT_VALIDATE_mort Validate \u2018mort\u2019 table. FT_VALIDATE_morx Validate \u2018morx\u2019 table. FT_VALIDATE_bsln Validate \u2018bsln\u2019 table. FT_VALIDATE_just Validate \u2018just\u2019 table. FT_VALIDATE_kern Validate \u2018kern\u2019 table. FT_VALIDATE_opbd Validate \u2018opbd\u2019 table. FT_VALIDATE_trak Validate \u2018trak\u2019 table. FT_VALIDATE_prop Validate \u2018prop\u2019 table. FT_VALIDATE_lcar Validate \u2018lcar\u2019 table. FT_VALIDATE_GX Validate all TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd, trak, prop and lcar). FT_VALIDATE_CKERNXXX \u00b6 Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h). # define FT_VALIDATE_MS ( FT_VALIDATE_GX_START << 0 ) # define FT_VALIDATE_APPLE ( FT_VALIDATE_GX_START << 1 ) # define FT_VALIDATE_CKERN ( FT_VALIDATE_MS | FT_VALIDATE_APPLE ) A list of bit-field constants used with FT_ClassicKern_Validate to indicate the classic kern dialect or dialects. If the selected type doesn't fit, FT_ClassicKern_Validate regards the table as invalid. values FT_VALIDATE_MS Handle the \u2018kern\u2019 table as a classic Microsoft kern table. FT_VALIDATE_APPLE Handle the \u2018kern\u2019 table as a classic Apple kern table. FT_VALIDATE_CKERN Handle the \u2018kern\u2019 as either classic Apple or Microsoft kern table.","title":"TrueTypeGX/AAT Validation"},{"location":"ft2-gx_validation.html#truetypegxaat-validation","text":"","title":"TrueTypeGX/AAT Validation"},{"location":"ft2-gx_validation.html#synopsis","text":"This section contains the declaration of functions to validate some TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd, trak, prop, lcar).","title":"Synopsis"},{"location":"ft2-gx_validation.html#ft_truetypegx_validate","text":"Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h). FT_EXPORT( FT_Error ) FT_TrueTypeGX_Validate ( FT_Face face, FT_UInt validation_flags, FT_Bytes tables[ FT_VALIDATE_GX_LENGTH ], FT_UInt table_length ); Validate various TrueTypeGX tables to assure that all offsets and indices are valid. The idea is that a higher-level library that actually does the text layout can access those tables without error checking (which can be quite time consuming).","title":"FT_TrueTypeGX_Validate"},{"location":"ft2-gx_validation.html#ft_truetypegx_free","text":"Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h). FT_EXPORT( void ) FT_TrueTypeGX_Free ( FT_Face face, FT_Bytes table ); Free the buffer allocated by TrueTypeGX validator.","title":"FT_TrueTypeGX_Free"},{"location":"ft2-gx_validation.html#ft_classickern_validate","text":"Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h). FT_EXPORT( FT_Error ) FT_ClassicKern_Validate ( FT_Face face, FT_UInt validation_flags, FT_Bytes *ckern_table ); Validate classic (16-bit format) kern table to assure that the offsets and indices are valid. The idea is that a higher-level library that actually does the text layout can access those tables without error checking (which can be quite time consuming). The \u2018kern\u2019 table validator in FT_TrueTypeGX_Validate deals with both the new 32-bit format and the classic 16-bit format, while FT_ClassicKern_Validate only supports the classic 16-bit format.","title":"FT_ClassicKern_Validate"},{"location":"ft2-gx_validation.html#ft_classickern_free","text":"Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h). FT_EXPORT( void ) FT_ClassicKern_Free ( FT_Face face, FT_Bytes table ); Free the buffer allocated by classic Kern validator.","title":"FT_ClassicKern_Free"},{"location":"ft2-gx_validation.html#ft_validate_gx_length","text":"Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h). # define FT_VALIDATE_GX_LENGTH ( FT_VALIDATE_GX_LAST_INDEX + 1 ) The number of tables checked in this module. Use it as a parameter for the table-length argument of function FT_TrueTypeGX_Validate .","title":"FT_VALIDATE_GX_LENGTH"},{"location":"ft2-gx_validation.html#ft_validate_gxxxx","text":"Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h). # define FT_VALIDATE_feat FT_VALIDATE_GX_BITFIELD( feat ) # define FT_VALIDATE_mort FT_VALIDATE_GX_BITFIELD( mort ) # define FT_VALIDATE_morx FT_VALIDATE_GX_BITFIELD( morx ) # define FT_VALIDATE_bsln FT_VALIDATE_GX_BITFIELD( bsln ) # define FT_VALIDATE_just FT_VALIDATE_GX_BITFIELD( just ) # define FT_VALIDATE_kern FT_VALIDATE_GX_BITFIELD( kern ) # define FT_VALIDATE_opbd FT_VALIDATE_GX_BITFIELD( opbd ) # define FT_VALIDATE_trak FT_VALIDATE_GX_BITFIELD( trak ) # define FT_VALIDATE_prop FT_VALIDATE_GX_BITFIELD( prop ) # define FT_VALIDATE_lcar FT_VALIDATE_GX_BITFIELD( lcar ) # define FT_VALIDATE_GX ( FT_VALIDATE_feat | \\ FT_VALIDATE_mort | \\ FT_VALIDATE_morx | \\ FT_VALIDATE_bsln | \\ FT_VALIDATE_just | \\ FT_VALIDATE_kern | \\ FT_VALIDATE_opbd | \\ FT_VALIDATE_trak | \\ FT_VALIDATE_prop | \\ FT_VALIDATE_lcar ) A list of bit-field constants used with FT_TrueTypeGX_Validate to indicate which TrueTypeGX/AAT Type tables should be validated.","title":"FT_VALIDATE_GXXXX"},{"location":"ft2-gx_validation.html#ft_validate_ckernxxx","text":"Defined in FT_GX_VALIDATE_H (freetype/ftgxval.h). # define FT_VALIDATE_MS ( FT_VALIDATE_GX_START << 0 ) # define FT_VALIDATE_APPLE ( FT_VALIDATE_GX_START << 1 ) # define FT_VALIDATE_CKERN ( FT_VALIDATE_MS | FT_VALIDATE_APPLE ) A list of bit-field constants used with FT_ClassicKern_Validate to indicate the classic kern dialect or dialects. If the selected type doesn't fit, FT_ClassicKern_Validate regards the table as invalid.","title":"FT_VALIDATE_CKERNXXX"},{"location":"ft2-gzip.html","text":"FreeType \u00bb Docs \u00bb Support API \u00bb GZIP Streams GZIP Streams \u00b6 Synopsis \u00b6 In certain builds of the library, gzip compression recognition is automatically handled when calling FT_New_Face or FT_Open_Face . This means that if no font driver is capable of handling the raw compressed file, the library will try to open a gzipped stream from it and re-open the face with it. The stream implementation is very basic and resets the decompression process each time seeking backwards is needed within the stream, which significantly undermines the performance. This section contains the declaration of Gzip-specific functions. FT_Stream_OpenGzip \u00b6 Defined in FT_GZIP_H (freetype/ftgzip.h). FT_EXPORT( FT_Error ) FT_Stream_OpenGzip ( FT_Stream stream, FT_Stream source ); Open a new stream to parse gzip-compressed font files. This is mainly used to support the compressed *.pcf.gz fonts that come with XFree86. input stream The target embedding stream. source The source stream. return FreeType error code. 0 means success. note The source stream must be opened before calling this function. Calling the internal function FT_Stream_Close on the new stream will not call FT_Stream_Close on the source stream. None of the stream objects will be released to the heap. This function may return FT_Err_Unimplemented_Feature if your build of FreeType was not compiled with zlib support. FT_Gzip_Uncompress \u00b6 Defined in FT_GZIP_H (freetype/ftgzip.h). FT_EXPORT( FT_Error ) FT_Gzip_Uncompress ( FT_Memory memory, FT_Byte * output, FT_ULong * output_len, const FT_Byte * input, FT_ULong input_len ); Decompress a zipped input buffer into an output buffer. This function is modeled after zlib's uncompress function. input memory A FreeType memory handle. input The input buffer. input_len The length of the input buffer. output output The output buffer. inout output_len Before calling the function, this is the total size of the output buffer, which must be large enough to hold the entire uncompressed data (so the size of the uncompressed data must be known in advance). After calling the function, output_len is the size of the used data in output . return FreeType error code. 0 means success. note This function may return FT_Err_Unimplemented_Feature if your build of FreeType was not compiled with zlib support. since 2.5.1","title":"GZIP Streams"},{"location":"ft2-gzip.html#gzip-streams","text":"","title":"GZIP Streams"},{"location":"ft2-gzip.html#synopsis","text":"In certain builds of the library, gzip compression recognition is automatically handled when calling FT_New_Face or FT_Open_Face . This means that if no font driver is capable of handling the raw compressed file, the library will try to open a gzipped stream from it and re-open the face with it. The stream implementation is very basic and resets the decompression process each time seeking backwards is needed within the stream, which significantly undermines the performance. This section contains the declaration of Gzip-specific functions.","title":"Synopsis"},{"location":"ft2-gzip.html#ft_stream_opengzip","text":"Defined in FT_GZIP_H (freetype/ftgzip.h). FT_EXPORT( FT_Error ) FT_Stream_OpenGzip ( FT_Stream stream, FT_Stream source ); Open a new stream to parse gzip-compressed font files. This is mainly used to support the compressed *.pcf.gz fonts that come with XFree86.","title":"FT_Stream_OpenGzip"},{"location":"ft2-gzip.html#ft_gzip_uncompress","text":"Defined in FT_GZIP_H (freetype/ftgzip.h). FT_EXPORT( FT_Error ) FT_Gzip_Uncompress ( FT_Memory memory, FT_Byte * output, FT_ULong * output_len, const FT_Byte * input, FT_ULong input_len ); Decompress a zipped input buffer into an output buffer. This function is modeled after zlib's uncompress function.","title":"FT_Gzip_Uncompress"},{"location":"ft2-header_file_macros.html","text":"FreeType \u00bb Docs \u00bb Core API \u00bb Header File Macros Header File Macros \u00b6 Synopsis \u00b6 In addition to the normal scheme of including header files like #include #include #include it is possible to used named macros instead. They can be used directly in #include statements as in #include FT_FREETYPE_H #include FT_MULTIPLE_MASTERS_H #include FT_GLYPH_H These macros were introduced to overcome the infamous 8.3 naming rule required by DOS (and FT_MULTIPLE_MASTERS_H is a lot more meaningful than ftmm.h ). FT_CONFIG_CONFIG_H \u00b6 # ifndef FT_CONFIG_CONFIG_H # define FT_CONFIG_CONFIG_H # endif A macro used in #include statements to name the file containing FreeType 2 configuration data. FT_CONFIG_STANDARD_LIBRARY_H \u00b6 # ifndef FT_CONFIG_STANDARD_LIBRARY_H # define FT_CONFIG_STANDARD_LIBRARY_H # endif A macro used in #include statements to name the file containing FreeType 2 interface to the standard C library functions. FT_CONFIG_OPTIONS_H \u00b6 # ifndef FT_CONFIG_OPTIONS_H # define FT_CONFIG_OPTIONS_H # endif A macro used in #include statements to name the file containing FreeType 2 project-specific configuration options. FT_CONFIG_MODULES_H \u00b6 # ifndef FT_CONFIG_MODULES_H # define FT_CONFIG_MODULES_H # endif A macro used in #include statements to name the file containing the list of FreeType 2 modules that are statically linked to new library instances in FT_Init_FreeType . FT_FREETYPE_H \u00b6 # define FT_FREETYPE_H A macro used in #include statements to name the file containing the base FreeType 2 API. FT_ERRORS_H \u00b6 # define FT_ERRORS_H A macro used in #include statements to name the file containing the list of FreeType 2 error codes (and messages). It is included by FT_FREETYPE_H . FT_MODULE_ERRORS_H \u00b6 # define FT_MODULE_ERRORS_H A macro used in #include statements to name the file containing the list of FreeType 2 module error offsets (and messages). FT_SYSTEM_H \u00b6 # define FT_SYSTEM_H A macro used in #include statements to name the file containing the FreeType 2 interface to low-level operations (i.e., memory management and stream i/o). It is included by FT_FREETYPE_H . FT_IMAGE_H \u00b6 # define FT_IMAGE_H A macro used in #include statements to name the file containing type definitions related to glyph images (i.e., bitmaps, outlines, scan-converter parameters). It is included by FT_FREETYPE_H . FT_TYPES_H \u00b6 # define FT_TYPES_H A macro used in #include statements to name the file containing the basic data types defined by FreeType 2. It is included by FT_FREETYPE_H . FT_LIST_H \u00b6 # define FT_LIST_H A macro used in #include statements to name the file containing the list management API of FreeType 2. (Most applications will never need to include this file.) FT_OUTLINE_H \u00b6 # define FT_OUTLINE_H A macro used in #include statements to name the file containing the scalable outline management API of FreeType 2. FT_SIZES_H \u00b6 # define FT_SIZES_H A macro used in #include statements to name the file containing the API which manages multiple FT_Size objects per face. FT_MODULE_H \u00b6 # define FT_MODULE_H A macro used in #include statements to name the file containing the module management API of FreeType 2. FT_RENDER_H \u00b6 # define FT_RENDER_H A macro used in #include statements to name the file containing the renderer module management API of FreeType 2. FT_DRIVER_H \u00b6 # define FT_DRIVER_H A macro used in #include statements to name the file containing structures and macros related to the driver modules. FT_AUTOHINTER_H \u00b6 # define FT_AUTOHINTER_H FT_DRIVER_H A macro used in #include statements to name the file containing structures and macros related to the auto-hinting module. Deprecated since version 2.9; use FT_DRIVER_H instead. FT_CFF_DRIVER_H \u00b6 # define FT_CFF_DRIVER_H FT_DRIVER_H A macro used in #include statements to name the file containing structures and macros related to the CFF driver module. Deprecated since version 2.9; use FT_DRIVER_H instead. FT_TRUETYPE_DRIVER_H \u00b6 # define FT_TRUETYPE_DRIVER_H FT_DRIVER_H A macro used in #include statements to name the file containing structures and macros related to the TrueType driver module. Deprecated since version 2.9; use FT_DRIVER_H instead. FT_PCF_DRIVER_H \u00b6 # define FT_PCF_DRIVER_H FT_DRIVER_H A macro used in #include statements to name the file containing structures and macros related to the PCF driver module. Deprecated since version 2.9; use FT_DRIVER_H instead. FT_TYPE1_TABLES_H \u00b6 # define FT_TYPE1_TABLES_H A macro used in #include statements to name the file containing the types and API specific to the Type 1 format. FT_TRUETYPE_IDS_H \u00b6 # define FT_TRUETYPE_IDS_H A macro used in #include statements to name the file containing the enumeration values which identify name strings, languages, encodings, etc. This file really contains a large set of constant macro definitions, taken from the TrueType and OpenType specifications. FT_TRUETYPE_TABLES_H \u00b6 # define FT_TRUETYPE_TABLES_H A macro used in #include statements to name the file containing the types and API specific to the TrueType (as well as OpenType) format. FT_TRUETYPE_TAGS_H \u00b6 # define FT_TRUETYPE_TAGS_H A macro used in #include statements to name the file containing the definitions of TrueType four-byte \u2018tags\u2019 which identify blocks in SFNT-based font formats (i.e., TrueType and OpenType). FT_BDF_H \u00b6 # define FT_BDF_H A macro used in #include statements to name the file containing the definitions of an API which accesses BDF-specific strings from a face. FT_CID_H \u00b6 # define FT_CID_H A macro used in #include statements to name the file containing the definitions of an API which access CID font information from a face. FT_GZIP_H \u00b6 # define FT_GZIP_H A macro used in #include statements to name the file containing the definitions of an API which supports gzip-compressed files. FT_LZW_H \u00b6 # define FT_LZW_H A macro used in #include statements to name the file containing the definitions of an API which supports LZW-compressed files. FT_BZIP2_H \u00b6 # define FT_BZIP2_H A macro used in #include statements to name the file containing the definitions of an API which supports bzip2-compressed files. FT_WINFONTS_H \u00b6 # define FT_WINFONTS_H A macro used in #include statements to name the file containing the definitions of an API which supports Windows FNT files. FT_GLYPH_H \u00b6 # define FT_GLYPH_H A macro used in #include statements to name the file containing the API of the optional glyph management component. FT_BITMAP_H \u00b6 # define FT_BITMAP_H A macro used in #include statements to name the file containing the API of the optional bitmap conversion component. FT_BBOX_H \u00b6 # define FT_BBOX_H A macro used in #include statements to name the file containing the API of the optional exact bounding box computation routines. FT_CACHE_H \u00b6 # define FT_CACHE_H A macro used in #include statements to name the file containing the API of the optional FreeType 2 cache sub-system. FT_MAC_H \u00b6 # define FT_MAC_H A macro used in #include statements to name the file containing the Macintosh-specific FreeType 2 API. The latter is used to access fonts embedded in resource forks. This header file must be explicitly included by client applications compiled on the Mac (note that the base API still works though). FT_MULTIPLE_MASTERS_H \u00b6 # define FT_MULTIPLE_MASTERS_H A macro used in #include statements to name the file containing the optional multiple-masters management API of FreeType 2. FT_SFNT_NAMES_H \u00b6 # define FT_SFNT_NAMES_H A macro used in #include statements to name the file containing the optional FreeType 2 API which accesses embedded \u2018name\u2019 strings in SFNT-based font formats (i.e., TrueType and OpenType). FT_OPENTYPE_VALIDATE_H \u00b6 # define FT_OPENTYPE_VALIDATE_H A macro used in #include statements to name the file containing the optional FreeType 2 API which validates OpenType tables (\u2018BASE\u2019, \u2018GDEF\u2019, \u2018GPOS\u2019, \u2018GSUB\u2019, \u2018JSTF\u2019). FT_GX_VALIDATE_H \u00b6 # define FT_GX_VALIDATE_H A macro used in #include statements to name the file containing the optional FreeType 2 API which validates TrueTypeGX/AAT tables (\u2018feat\u2019, \u2018mort\u2019, \u2018morx\u2019, \u2018bsln\u2019, \u2018just\u2019, \u2018kern\u2019, \u2018opbd\u2019, \u2018trak\u2019, \u2018prop\u2019). FT_PFR_H \u00b6 # define FT_PFR_H A macro used in #include statements to name the file containing the FreeType 2 API which accesses PFR-specific data. FT_STROKER_H \u00b6 # define FT_STROKER_H A macro used in #include statements to name the file containing the FreeType 2 API which provides functions to stroke outline paths. FT_SYNTHESIS_H \u00b6 # define FT_SYNTHESIS_H A macro used in #include statements to name the file containing the FreeType 2 API which performs artificial obliquing and emboldening. FT_FONT_FORMATS_H \u00b6 # define FT_FONT_FORMATS_H /* deprecated */ # define FT_XFREE86_H FT_FONT_FORMATS_H A macro used in #include statements to name the file containing the FreeType 2 API which provides functions specific to font formats. FT_TRIGONOMETRY_H \u00b6 # define FT_TRIGONOMETRY_H A macro used in #include statements to name the file containing the FreeType 2 API which performs trigonometric computations (e.g., cosines and arc tangents). FT_LCD_FILTER_H \u00b6 # define FT_LCD_FILTER_H A macro used in #include statements to name the file containing the FreeType 2 API which performs color filtering for subpixel rendering. FT_INCREMENTAL_H \u00b6 # define FT_INCREMENTAL_H A macro used in #include statements to name the file containing the FreeType 2 API which performs incremental glyph loading. FT_GASP_H \u00b6 # define FT_GASP_H A macro used in #include statements to name the file containing the FreeType 2 API which returns entries from the TrueType GASP table. FT_ADVANCES_H \u00b6 # define FT_ADVANCES_H A macro used in #include statements to name the file containing the FreeType 2 API which returns individual and ranged glyph advances. FT_COLOR_H \u00b6 # define FT_COLOR_H A macro used in #include statements to name the file containing the FreeType 2 API which handles the OpenType \u2018CPAL\u2019 table.","title":"Header File Macros"},{"location":"ft2-header_file_macros.html#header-file-macros","text":"","title":"Header File Macros"},{"location":"ft2-header_file_macros.html#synopsis","text":"In addition to the normal scheme of including header files like #include #include #include it is possible to used named macros instead. They can be used directly in #include statements as in #include FT_FREETYPE_H #include FT_MULTIPLE_MASTERS_H #include FT_GLYPH_H These macros were introduced to overcome the infamous 8.3 naming rule required by DOS (and FT_MULTIPLE_MASTERS_H is a lot more meaningful than ftmm.h ).","title":"Synopsis"},{"location":"ft2-header_file_macros.html#ft_config_config_h","text":"# ifndef FT_CONFIG_CONFIG_H # define FT_CONFIG_CONFIG_H # endif A macro used in #include statements to name the file containing FreeType 2 configuration data.","title":"FT_CONFIG_CONFIG_H"},{"location":"ft2-header_file_macros.html#ft_config_standard_library_h","text":"# ifndef FT_CONFIG_STANDARD_LIBRARY_H # define FT_CONFIG_STANDARD_LIBRARY_H # endif A macro used in #include statements to name the file containing FreeType 2 interface to the standard C library functions.","title":"FT_CONFIG_STANDARD_LIBRARY_H"},{"location":"ft2-header_file_macros.html#ft_config_options_h","text":"# ifndef FT_CONFIG_OPTIONS_H # define FT_CONFIG_OPTIONS_H # endif A macro used in #include statements to name the file containing FreeType 2 project-specific configuration options.","title":"FT_CONFIG_OPTIONS_H"},{"location":"ft2-header_file_macros.html#ft_config_modules_h","text":"# ifndef FT_CONFIG_MODULES_H # define FT_CONFIG_MODULES_H # endif A macro used in #include statements to name the file containing the list of FreeType 2 modules that are statically linked to new library instances in FT_Init_FreeType .","title":"FT_CONFIG_MODULES_H"},{"location":"ft2-header_file_macros.html#ft_freetype_h","text":"# define FT_FREETYPE_H A macro used in #include statements to name the file containing the base FreeType 2 API.","title":"FT_FREETYPE_H"},{"location":"ft2-header_file_macros.html#ft_errors_h","text":"# define FT_ERRORS_H A macro used in #include statements to name the file containing the list of FreeType 2 error codes (and messages). It is included by FT_FREETYPE_H .","title":"FT_ERRORS_H"},{"location":"ft2-header_file_macros.html#ft_module_errors_h","text":"# define FT_MODULE_ERRORS_H A macro used in #include statements to name the file containing the list of FreeType 2 module error offsets (and messages).","title":"FT_MODULE_ERRORS_H"},{"location":"ft2-header_file_macros.html#ft_system_h","text":"# define FT_SYSTEM_H A macro used in #include statements to name the file containing the FreeType 2 interface to low-level operations (i.e., memory management and stream i/o). It is included by FT_FREETYPE_H .","title":"FT_SYSTEM_H"},{"location":"ft2-header_file_macros.html#ft_image_h","text":"# define FT_IMAGE_H A macro used in #include statements to name the file containing type definitions related to glyph images (i.e., bitmaps, outlines, scan-converter parameters). It is included by FT_FREETYPE_H .","title":"FT_IMAGE_H"},{"location":"ft2-header_file_macros.html#ft_types_h","text":"# define FT_TYPES_H A macro used in #include statements to name the file containing the basic data types defined by FreeType 2. It is included by FT_FREETYPE_H .","title":"FT_TYPES_H"},{"location":"ft2-header_file_macros.html#ft_list_h","text":"# define FT_LIST_H A macro used in #include statements to name the file containing the list management API of FreeType 2. (Most applications will never need to include this file.)","title":"FT_LIST_H"},{"location":"ft2-header_file_macros.html#ft_outline_h","text":"# define FT_OUTLINE_H A macro used in #include statements to name the file containing the scalable outline management API of FreeType 2.","title":"FT_OUTLINE_H"},{"location":"ft2-header_file_macros.html#ft_sizes_h","text":"# define FT_SIZES_H A macro used in #include statements to name the file containing the API which manages multiple FT_Size objects per face.","title":"FT_SIZES_H"},{"location":"ft2-header_file_macros.html#ft_module_h","text":"# define FT_MODULE_H A macro used in #include statements to name the file containing the module management API of FreeType 2.","title":"FT_MODULE_H"},{"location":"ft2-header_file_macros.html#ft_render_h","text":"# define FT_RENDER_H A macro used in #include statements to name the file containing the renderer module management API of FreeType 2.","title":"FT_RENDER_H"},{"location":"ft2-header_file_macros.html#ft_driver_h","text":"# define FT_DRIVER_H A macro used in #include statements to name the file containing structures and macros related to the driver modules.","title":"FT_DRIVER_H"},{"location":"ft2-header_file_macros.html#ft_autohinter_h","text":"# define FT_AUTOHINTER_H FT_DRIVER_H A macro used in #include statements to name the file containing structures and macros related to the auto-hinting module. Deprecated since version 2.9; use FT_DRIVER_H instead.","title":"FT_AUTOHINTER_H"},{"location":"ft2-header_file_macros.html#ft_cff_driver_h","text":"# define FT_CFF_DRIVER_H FT_DRIVER_H A macro used in #include statements to name the file containing structures and macros related to the CFF driver module. Deprecated since version 2.9; use FT_DRIVER_H instead.","title":"FT_CFF_DRIVER_H"},{"location":"ft2-header_file_macros.html#ft_truetype_driver_h","text":"# define FT_TRUETYPE_DRIVER_H FT_DRIVER_H A macro used in #include statements to name the file containing structures and macros related to the TrueType driver module. Deprecated since version 2.9; use FT_DRIVER_H instead.","title":"FT_TRUETYPE_DRIVER_H"},{"location":"ft2-header_file_macros.html#ft_pcf_driver_h","text":"# define FT_PCF_DRIVER_H FT_DRIVER_H A macro used in #include statements to name the file containing structures and macros related to the PCF driver module. Deprecated since version 2.9; use FT_DRIVER_H instead.","title":"FT_PCF_DRIVER_H"},{"location":"ft2-header_file_macros.html#ft_type1_tables_h","text":"# define FT_TYPE1_TABLES_H A macro used in #include statements to name the file containing the types and API specific to the Type 1 format.","title":"FT_TYPE1_TABLES_H"},{"location":"ft2-header_file_macros.html#ft_truetype_ids_h","text":"# define FT_TRUETYPE_IDS_H A macro used in #include statements to name the file containing the enumeration values which identify name strings, languages, encodings, etc. This file really contains a large set of constant macro definitions, taken from the TrueType and OpenType specifications.","title":"FT_TRUETYPE_IDS_H"},{"location":"ft2-header_file_macros.html#ft_truetype_tables_h","text":"# define FT_TRUETYPE_TABLES_H A macro used in #include statements to name the file containing the types and API specific to the TrueType (as well as OpenType) format.","title":"FT_TRUETYPE_TABLES_H"},{"location":"ft2-header_file_macros.html#ft_truetype_tags_h","text":"# define FT_TRUETYPE_TAGS_H A macro used in #include statements to name the file containing the definitions of TrueType four-byte \u2018tags\u2019 which identify blocks in SFNT-based font formats (i.e., TrueType and OpenType).","title":"FT_TRUETYPE_TAGS_H"},{"location":"ft2-header_file_macros.html#ft_bdf_h","text":"# define FT_BDF_H A macro used in #include statements to name the file containing the definitions of an API which accesses BDF-specific strings from a face.","title":"FT_BDF_H"},{"location":"ft2-header_file_macros.html#ft_cid_h","text":"# define FT_CID_H A macro used in #include statements to name the file containing the definitions of an API which access CID font information from a face.","title":"FT_CID_H"},{"location":"ft2-header_file_macros.html#ft_gzip_h","text":"# define FT_GZIP_H A macro used in #include statements to name the file containing the definitions of an API which supports gzip-compressed files.","title":"FT_GZIP_H"},{"location":"ft2-header_file_macros.html#ft_lzw_h","text":"# define FT_LZW_H A macro used in #include statements to name the file containing the definitions of an API which supports LZW-compressed files.","title":"FT_LZW_H"},{"location":"ft2-header_file_macros.html#ft_bzip2_h","text":"# define FT_BZIP2_H A macro used in #include statements to name the file containing the definitions of an API which supports bzip2-compressed files.","title":"FT_BZIP2_H"},{"location":"ft2-header_file_macros.html#ft_winfonts_h","text":"# define FT_WINFONTS_H A macro used in #include statements to name the file containing the definitions of an API which supports Windows FNT files.","title":"FT_WINFONTS_H"},{"location":"ft2-header_file_macros.html#ft_glyph_h","text":"# define FT_GLYPH_H A macro used in #include statements to name the file containing the API of the optional glyph management component.","title":"FT_GLYPH_H"},{"location":"ft2-header_file_macros.html#ft_bitmap_h","text":"# define FT_BITMAP_H A macro used in #include statements to name the file containing the API of the optional bitmap conversion component.","title":"FT_BITMAP_H"},{"location":"ft2-header_file_macros.html#ft_bbox_h","text":"# define FT_BBOX_H A macro used in #include statements to name the file containing the API of the optional exact bounding box computation routines.","title":"FT_BBOX_H"},{"location":"ft2-header_file_macros.html#ft_cache_h","text":"# define FT_CACHE_H A macro used in #include statements to name the file containing the API of the optional FreeType 2 cache sub-system.","title":"FT_CACHE_H"},{"location":"ft2-header_file_macros.html#ft_mac_h","text":"# define FT_MAC_H A macro used in #include statements to name the file containing the Macintosh-specific FreeType 2 API. The latter is used to access fonts embedded in resource forks. This header file must be explicitly included by client applications compiled on the Mac (note that the base API still works though).","title":"FT_MAC_H"},{"location":"ft2-header_file_macros.html#ft_multiple_masters_h","text":"# define FT_MULTIPLE_MASTERS_H A macro used in #include statements to name the file containing the optional multiple-masters management API of FreeType 2.","title":"FT_MULTIPLE_MASTERS_H"},{"location":"ft2-header_file_macros.html#ft_sfnt_names_h","text":"# define FT_SFNT_NAMES_H A macro used in #include statements to name the file containing the optional FreeType 2 API which accesses embedded \u2018name\u2019 strings in SFNT-based font formats (i.e., TrueType and OpenType).","title":"FT_SFNT_NAMES_H"},{"location":"ft2-header_file_macros.html#ft_opentype_validate_h","text":"# define FT_OPENTYPE_VALIDATE_H A macro used in #include statements to name the file containing the optional FreeType 2 API which validates OpenType tables (\u2018BASE\u2019, \u2018GDEF\u2019, \u2018GPOS\u2019, \u2018GSUB\u2019, \u2018JSTF\u2019).","title":"FT_OPENTYPE_VALIDATE_H"},{"location":"ft2-header_file_macros.html#ft_gx_validate_h","text":"# define FT_GX_VALIDATE_H A macro used in #include statements to name the file containing the optional FreeType 2 API which validates TrueTypeGX/AAT tables (\u2018feat\u2019, \u2018mort\u2019, \u2018morx\u2019, \u2018bsln\u2019, \u2018just\u2019, \u2018kern\u2019, \u2018opbd\u2019, \u2018trak\u2019, \u2018prop\u2019).","title":"FT_GX_VALIDATE_H"},{"location":"ft2-header_file_macros.html#ft_pfr_h","text":"# define FT_PFR_H A macro used in #include statements to name the file containing the FreeType 2 API which accesses PFR-specific data.","title":"FT_PFR_H"},{"location":"ft2-header_file_macros.html#ft_stroker_h","text":"# define FT_STROKER_H A macro used in #include statements to name the file containing the FreeType 2 API which provides functions to stroke outline paths.","title":"FT_STROKER_H"},{"location":"ft2-header_file_macros.html#ft_synthesis_h","text":"# define FT_SYNTHESIS_H A macro used in #include statements to name the file containing the FreeType 2 API which performs artificial obliquing and emboldening.","title":"FT_SYNTHESIS_H"},{"location":"ft2-header_file_macros.html#ft_font_formats_h","text":"# define FT_FONT_FORMATS_H /* deprecated */ # define FT_XFREE86_H FT_FONT_FORMATS_H A macro used in #include statements to name the file containing the FreeType 2 API which provides functions specific to font formats.","title":"FT_FONT_FORMATS_H"},{"location":"ft2-header_file_macros.html#ft_trigonometry_h","text":"# define FT_TRIGONOMETRY_H A macro used in #include statements to name the file containing the FreeType 2 API which performs trigonometric computations (e.g., cosines and arc tangents).","title":"FT_TRIGONOMETRY_H"},{"location":"ft2-header_file_macros.html#ft_lcd_filter_h","text":"# define FT_LCD_FILTER_H A macro used in #include statements to name the file containing the FreeType 2 API which performs color filtering for subpixel rendering.","title":"FT_LCD_FILTER_H"},{"location":"ft2-header_file_macros.html#ft_incremental_h","text":"# define FT_INCREMENTAL_H A macro used in #include statements to name the file containing the FreeType 2 API which performs incremental glyph loading.","title":"FT_INCREMENTAL_H"},{"location":"ft2-header_file_macros.html#ft_gasp_h","text":"# define FT_GASP_H A macro used in #include statements to name the file containing the FreeType 2 API which returns entries from the TrueType GASP table.","title":"FT_GASP_H"},{"location":"ft2-header_file_macros.html#ft_advances_h","text":"# define FT_ADVANCES_H A macro used in #include statements to name the file containing the FreeType 2 API which returns individual and ranged glyph advances.","title":"FT_ADVANCES_H"},{"location":"ft2-header_file_macros.html#ft_color_h","text":"# define FT_COLOR_H A macro used in #include statements to name the file containing the FreeType 2 API which handles the OpenType \u2018CPAL\u2019 table.","title":"FT_COLOR_H"},{"location":"ft2-header_inclusion.html","text":"FreeType \u00bb Docs \u00bb General Remarks \u00bb FreeType's header inclusion scheme FreeType's header inclusion scheme \u00b6 Synopsis \u00b6 To be as flexible as possible (and for historical reasons), you must load file ft2build.h first before other header files, for example #include #include #include ","title":"FreeType's header inclusion scheme"},{"location":"ft2-header_inclusion.html#freetypes-header-inclusion-scheme","text":"","title":"FreeType's header inclusion scheme"},{"location":"ft2-header_inclusion.html#synopsis","text":"To be as flexible as possible (and for historical reasons), you must load file ft2build.h first before other header files, for example #include #include #include ","title":"Synopsis"},{"location":"ft2-incremental.html","text":"FreeType \u00bb Docs \u00bb Miscellaneous \u00bb Incremental Loading Incremental Loading \u00b6 Synopsis \u00b6 This section contains various functions used to perform so-called \u2018incremental\u2019 glyph loading. This is a mode where all glyphs loaded from a given FT_Face are provided by the client application. Apart from that, all other tables are loaded normally from the font file. This mode is useful when FreeType is used within another engine, e.g., a PostScript Imaging Processor. To enable this mode, you must use FT_Open_Face , passing an FT_Parameter with the FT_PARAM_TAG_INCREMENTAL tag and an FT_Incremental_Interface value. See the comments for FT_Incremental_InterfaceRec for an example. FT_Incremental \u00b6 Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef struct FT_IncrementalRec_* FT_Incremental ; An opaque type describing a user-provided object used to implement \u2018incremental\u2019 glyph loading within FreeType. This is used to support embedded fonts in certain environments (e.g., PostScript interpreters), where the glyph data isn't in the font file, or must be overridden by different values. note It is up to client applications to create and implement FT_Incremental objects, as long as they provide implementations for the methods FT_Incremental_GetGlyphDataFunc , FT_Incremental_FreeGlyphDataFunc and FT_Incremental_GetGlyphMetricsFunc . See the description of FT_Incremental_InterfaceRec to understand how to use incremental objects with FreeType. FT_Incremental_MetricsRec \u00b6 Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef struct FT_Incremental_MetricsRec_ { FT_Long bearing_x; FT_Long bearing_y; FT_Long advance; FT_Long advance_v; /* since 2.3.12 */ } FT_Incremental_MetricsRec ; A small structure used to contain the basic glyph metrics returned by the FT_Incremental_GetGlyphMetricsFunc method. fields bearing_x Left bearing, in font units. bearing_y Top bearing, in font units. advance Horizontal component of glyph advance, in font units. advance_v Vertical component of glyph advance, in font units. note These correspond to horizontal or vertical metrics depending on the value of the vertical argument to the function FT_Incremental_GetGlyphMetricsFunc . FT_Incremental_Metrics \u00b6 Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef struct FT_Incremental_MetricsRec_* FT_Incremental_Metrics ; A handle to an FT_Incremental_MetricsRec structure. FT_Incremental_GetGlyphDataFunc \u00b6 Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef FT_Error (* FT_Incremental_GetGlyphDataFunc )( FT_Incremental incremental, FT_UInt glyph_index, FT_Data * adata ); A function called by FreeType to access a given glyph's data bytes during FT_Load_Glyph or FT_Load_Char if incremental loading is enabled. Note that the format of the glyph's data bytes depends on the font file format. For TrueType, it must correspond to the raw bytes within the \u2018glyf\u2019 table. For PostScript formats, it must correspond to the unencrypted charstring bytes, without any lenIV header. It is undefined for any other format. input incremental Handle to an opaque FT_Incremental handle provided by the client application. glyph_index Index of relevant glyph. output adata A structure describing the returned glyph data bytes (which will be accessed as a read-only byte block). return FreeType error code. 0 means success. note If this function returns successfully the method FT_Incremental_FreeGlyphDataFunc will be called later to release the data bytes. Nested calls to FT_Incremental_GetGlyphDataFunc can happen for compound glyphs. FT_Incremental_FreeGlyphDataFunc \u00b6 Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef void (* FT_Incremental_FreeGlyphDataFunc )( FT_Incremental incremental, FT_Data * data ); A function used to release the glyph data bytes returned by a successful call to FT_Incremental_GetGlyphDataFunc . input incremental A handle to an opaque FT_Incremental handle provided by the client application. data A structure describing the glyph data bytes (which will be accessed as a read-only byte block). FT_Incremental_GetGlyphMetricsFunc \u00b6 Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef FT_Error (* FT_Incremental_GetGlyphMetricsFunc ) ( FT_Incremental incremental, FT_UInt glyph_index, FT_Bool vertical, FT_Incremental_MetricsRec *ametrics ); A function used to retrieve the basic metrics of a given glyph index before accessing its data. This is necessary because, in certain formats like TrueType, the metrics are stored in a different place from the glyph images proper. input incremental A handle to an opaque FT_Incremental handle provided by the client application. glyph_index Index of relevant glyph. vertical If true, return vertical metrics. ametrics This parameter is used for both input and output. The original glyph metrics, if any, in font units. If metrics are not available all the values must be set to zero. output ametrics The replacement glyph metrics in font units. FT_Incremental_FuncsRec \u00b6 Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef struct FT_Incremental_FuncsRec_ { FT_Incremental_GetGlyphDataFunc get_glyph_data; FT_Incremental_FreeGlyphDataFunc free_glyph_data; FT_Incremental_GetGlyphMetricsFunc get_glyph_metrics; } FT_Incremental_FuncsRec ; A table of functions for accessing fonts that load data incrementally. Used in FT_Incremental_InterfaceRec . fields get_glyph_data The function to get glyph data. Must not be null. free_glyph_data The function to release glyph data. Must not be null. get_glyph_metrics The function to get glyph metrics. May be null if the font does not provide overriding glyph metrics. FT_Incremental_InterfaceRec \u00b6 Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef struct FT_Incremental_InterfaceRec_ { const FT_Incremental_FuncsRec * funcs; FT_Incremental object; } FT_Incremental_InterfaceRec ; A structure to be used with FT_Open_Face to indicate that the user wants to support incremental glyph loading. You should use it with FT_PARAM_TAG_INCREMENTAL as in the following example: FT_Incremental_InterfaceRec inc_int; FT_Parameter parameter; FT_Open_Args open_args; // set up incremental descriptor inc_int.funcs = my_funcs; inc_int.object = my_object; // set up optional parameter parameter.tag = FT_PARAM_TAG_INCREMENTAL; parameter.data = &inc_int; // set up FT_Open_Args structure open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS; open_args.pathname = my_font_pathname; open_args.num_params = 1; open_args.params = ¶meter; // we use one optional argument // open the font error = FT_Open_Face( library, &open_args, index, &face ); ... FT_Incremental_Interface \u00b6 Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef FT_Incremental_InterfaceRec * FT_Incremental_Interface ; A pointer to an FT_Incremental_InterfaceRec structure.","title":"Incremental Loading"},{"location":"ft2-incremental.html#incremental-loading","text":"","title":"Incremental Loading"},{"location":"ft2-incremental.html#synopsis","text":"This section contains various functions used to perform so-called \u2018incremental\u2019 glyph loading. This is a mode where all glyphs loaded from a given FT_Face are provided by the client application. Apart from that, all other tables are loaded normally from the font file. This mode is useful when FreeType is used within another engine, e.g., a PostScript Imaging Processor. To enable this mode, you must use FT_Open_Face , passing an FT_Parameter with the FT_PARAM_TAG_INCREMENTAL tag and an FT_Incremental_Interface value. See the comments for FT_Incremental_InterfaceRec for an example.","title":"Synopsis"},{"location":"ft2-incremental.html#ft_incremental","text":"Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef struct FT_IncrementalRec_* FT_Incremental ; An opaque type describing a user-provided object used to implement \u2018incremental\u2019 glyph loading within FreeType. This is used to support embedded fonts in certain environments (e.g., PostScript interpreters), where the glyph data isn't in the font file, or must be overridden by different values.","title":"FT_Incremental"},{"location":"ft2-incremental.html#ft_incremental_metricsrec","text":"Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef struct FT_Incremental_MetricsRec_ { FT_Long bearing_x; FT_Long bearing_y; FT_Long advance; FT_Long advance_v; /* since 2.3.12 */ } FT_Incremental_MetricsRec ; A small structure used to contain the basic glyph metrics returned by the FT_Incremental_GetGlyphMetricsFunc method.","title":"FT_Incremental_MetricsRec"},{"location":"ft2-incremental.html#ft_incremental_metrics","text":"Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef struct FT_Incremental_MetricsRec_* FT_Incremental_Metrics ; A handle to an FT_Incremental_MetricsRec structure.","title":"FT_Incremental_Metrics"},{"location":"ft2-incremental.html#ft_incremental_getglyphdatafunc","text":"Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef FT_Error (* FT_Incremental_GetGlyphDataFunc )( FT_Incremental incremental, FT_UInt glyph_index, FT_Data * adata ); A function called by FreeType to access a given glyph's data bytes during FT_Load_Glyph or FT_Load_Char if incremental loading is enabled. Note that the format of the glyph's data bytes depends on the font file format. For TrueType, it must correspond to the raw bytes within the \u2018glyf\u2019 table. For PostScript formats, it must correspond to the unencrypted charstring bytes, without any lenIV header. It is undefined for any other format.","title":"FT_Incremental_GetGlyphDataFunc"},{"location":"ft2-incremental.html#ft_incremental_freeglyphdatafunc","text":"Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef void (* FT_Incremental_FreeGlyphDataFunc )( FT_Incremental incremental, FT_Data * data ); A function used to release the glyph data bytes returned by a successful call to FT_Incremental_GetGlyphDataFunc .","title":"FT_Incremental_FreeGlyphDataFunc"},{"location":"ft2-incremental.html#ft_incremental_getglyphmetricsfunc","text":"Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef FT_Error (* FT_Incremental_GetGlyphMetricsFunc ) ( FT_Incremental incremental, FT_UInt glyph_index, FT_Bool vertical, FT_Incremental_MetricsRec *ametrics ); A function used to retrieve the basic metrics of a given glyph index before accessing its data. This is necessary because, in certain formats like TrueType, the metrics are stored in a different place from the glyph images proper.","title":"FT_Incremental_GetGlyphMetricsFunc"},{"location":"ft2-incremental.html#ft_incremental_funcsrec","text":"Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef struct FT_Incremental_FuncsRec_ { FT_Incremental_GetGlyphDataFunc get_glyph_data; FT_Incremental_FreeGlyphDataFunc free_glyph_data; FT_Incremental_GetGlyphMetricsFunc get_glyph_metrics; } FT_Incremental_FuncsRec ; A table of functions for accessing fonts that load data incrementally. Used in FT_Incremental_InterfaceRec .","title":"FT_Incremental_FuncsRec"},{"location":"ft2-incremental.html#ft_incremental_interfacerec","text":"Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef struct FT_Incremental_InterfaceRec_ { const FT_Incremental_FuncsRec * funcs; FT_Incremental object; } FT_Incremental_InterfaceRec ; A structure to be used with FT_Open_Face to indicate that the user wants to support incremental glyph loading. You should use it with FT_PARAM_TAG_INCREMENTAL as in the following example: FT_Incremental_InterfaceRec inc_int; FT_Parameter parameter; FT_Open_Args open_args; // set up incremental descriptor inc_int.funcs = my_funcs; inc_int.object = my_object; // set up optional parameter parameter.tag = FT_PARAM_TAG_INCREMENTAL; parameter.data = &inc_int; // set up FT_Open_Args structure open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS; open_args.pathname = my_font_pathname; open_args.num_params = 1; open_args.params = ¶meter; // we use one optional argument // open the font error = FT_Open_Face( library, &open_args, index, &face ); ...","title":"FT_Incremental_InterfaceRec"},{"location":"ft2-incremental.html#ft_incremental_interface","text":"Defined in FT_INCREMENTAL_H (freetype/ftincrem.h). typedef FT_Incremental_InterfaceRec * FT_Incremental_Interface ; A pointer to an FT_Incremental_InterfaceRec structure.","title":"FT_Incremental_Interface"},{"location":"ft2-index.html","text":"FreeType \u00bb Docs \u00bb Global Index FreeType-2.10.4 API Reference \u00b6 B \u00b6 BDF_Property BDF_PROPERTY_TYPE_ATOM BDF_PROPERTY_TYPE_CARDINAL BDF_PROPERTY_TYPE_INTEGER BDF_PROPERTY_TYPE_NONE BDF_PropertyRec BDF_PropertyType C \u00b6 CID_FaceDict CID_FaceDictRec CID_FaceInfo CID_FaceInfoRec CID_FontDict CID_Info D \u00b6 darkening-parameters default-script F \u00b6 fallback-script FREETYPE_MAJOR FREETYPE_MINOR FREETYPE_PATCH FREETYPE_XXX FT_Activate_Size FT_Add_Default_Modules FT_Add_Module FT_ADVANCE_FLAG_FAST_ONLY FT_ADVANCES_H FT_Alloc_Func FT_Angle FT_ANGLE_2PI FT_Angle_Diff FT_ANGLE_PI FT_ANGLE_PI2 FT_ANGLE_PI4 FT_Atan2 FT_Attach_File FT_Attach_Stream FT_AUTOHINTER_H FT_AUTOHINTER_SCRIPT_CJK FT_AUTOHINTER_SCRIPT_INDIC FT_AUTOHINTER_SCRIPT_LATIN FT_AUTOHINTER_SCRIPT_NONE FT_AUTOHINTER_SCRIPT_XXX FT_BBox FT_BBOX_H FT_BDF_H FT_Bitmap FT_Bitmap_Blend FT_Bitmap_Convert FT_Bitmap_Copy FT_Bitmap_Done FT_Bitmap_Embolden FT_BITMAP_H FT_Bitmap_Init FT_Bitmap_Size FT_BitmapGlyph FT_BitmapGlyphRec FT_Bool FT_Byte FT_Bytes FT_BZIP2_H FT_CACHE_H FT_CeilFix FT_CFF_DRIVER_H FT_Char FT_CharMap FT_CharMapRec FT_CID_H FT_ClassicKern_Free FT_ClassicKern_Validate FT_Color FT_COLOR_H FT_CONFIG_CONFIG_H FT_CONFIG_MODULES_H FT_CONFIG_OPTIONS_H FT_CONFIG_STANDARD_LIBRARY_H FT_Cos FT_Data FT_DEBUG_HOOK_TRUETYPE FT_DEBUG_HOOK_XXX FT_DebugHook_Func FT_DivFix FT_Done_Face FT_Done_FreeType FT_Done_Glyph FT_Done_Library FT_Done_MM_Var FT_Done_Size FT_Driver FT_DRIVER_H FT_ENC_TAG FT_Encoding FT_ENCODING_ADOBE_CUSTOM FT_ENCODING_ADOBE_EXPERT FT_ENCODING_ADOBE_LATIN_1 FT_ENCODING_ADOBE_STANDARD FT_ENCODING_APPLE_ROMAN FT_ENCODING_BIG5 FT_ENCODING_JOHAB FT_ENCODING_MS_BIG5 FT_ENCODING_MS_GB2312 FT_ENCODING_MS_JOHAB FT_ENCODING_MS_SJIS FT_ENCODING_MS_SYMBOL FT_ENCODING_MS_WANSUNG FT_ENCODING_NONE FT_ENCODING_OLD_LATIN_2 FT_ENCODING_PRC FT_ENCODING_SJIS FT_ENCODING_UNICODE FT_ENCODING_WANSUNG FT_Err_XXX FT_Error FT_Error_String FT_ERRORS_H FT_F26Dot6 FT_F2Dot14 FT_Face FT_Face_CheckTrueTypePatents FT_FACE_FLAG_CID_KEYED FT_FACE_FLAG_COLOR FT_FACE_FLAG_EXTERNAL_STREAM FT_FACE_FLAG_FAST_GLYPHS FT_FACE_FLAG_FIXED_SIZES FT_FACE_FLAG_FIXED_WIDTH FT_FACE_FLAG_GLYPH_NAMES FT_FACE_FLAG_HINTER FT_FACE_FLAG_HORIZONTAL FT_FACE_FLAG_KERNING FT_FACE_FLAG_MULTIPLE_MASTERS FT_FACE_FLAG_SCALABLE FT_FACE_FLAG_SFNT FT_FACE_FLAG_TRICKY FT_FACE_FLAG_VARIATION FT_FACE_FLAG_VERTICAL FT_FACE_FLAG_XXX FT_Face_GetCharsOfVariant FT_Face_GetCharVariantIndex FT_Face_GetCharVariantIsDefault FT_Face_GetVariantSelectors FT_Face_GetVariantsOfChar FT_Face_Internal FT_Face_Properties FT_Face_SetUnpatentedHinting FT_FaceRec FT_Fixed FT_FloorFix FT_FONT_FORMATS_H FT_Free_Func FT_FREETYPE_H FT_FSTYPE_BITMAP_EMBEDDING_ONLY FT_FSTYPE_EDITABLE_EMBEDDING FT_FSTYPE_INSTALLABLE_EMBEDDING FT_FSTYPE_NO_SUBSETTING FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING FT_FSTYPE_XXX FT_FWord FT_GASP_DO_GRAY FT_GASP_DO_GRIDFIT FT_GASP_H FT_GASP_NO_TABLE FT_GASP_SYMMETRIC_GRIDFIT FT_GASP_SYMMETRIC_SMOOTHING FT_GASP_XXX FT_Generic FT_Generic_Finalizer FT_Get_Advance FT_Get_Advances FT_Get_BDF_Charset_ID FT_Get_BDF_Property FT_Get_Char_Index FT_Get_Charmap_Index FT_Get_CID_From_Glyph_Index FT_Get_CID_Is_Internally_CID_Keyed FT_Get_CID_Registry_Ordering_Supplement FT_Get_CMap_Format FT_Get_CMap_Language_ID FT_Get_Color_Glyph_Layer FT_Get_First_Char FT_Get_Font_Format FT_Get_FSType_Flags FT_Get_Gasp FT_Get_Glyph FT_Get_Glyph_Name FT_Get_Kerning FT_Get_MM_Blend_Coordinates FT_Get_MM_Var FT_Get_MM_WeightVector FT_Get_Module FT_Get_Multi_Master FT_Get_Name_Index FT_Get_Next_Char FT_Get_PFR_Advance FT_Get_PFR_Kerning FT_Get_PFR_Metrics FT_Get_Postscript_Name FT_Get_PS_Font_Info FT_Get_PS_Font_Private FT_Get_PS_Font_Value FT_Get_Renderer FT_Get_Sfnt_LangTag FT_Get_Sfnt_Name FT_Get_Sfnt_Name_Count FT_Get_Sfnt_Table FT_Get_SubGlyph_Info FT_Get_Track_Kerning FT_Get_TrueType_Engine_Type FT_Get_Var_Axis_Flags FT_Get_Var_Blend_Coordinates FT_Get_Var_Design_Coordinates FT_Get_WinFNT_Header FT_GetFile_From_Mac_ATS_Name FT_GetFile_From_Mac_Name FT_GetFilePath_From_Mac_ATS_Name FT_Glyph FT_GLYPH_BBOX_GRIDFIT FT_Glyph_BBox_Mode FT_GLYPH_BBOX_PIXELS FT_GLYPH_BBOX_SUBPIXELS FT_GLYPH_BBOX_TRUNCATE FT_GLYPH_BBOX_UNSCALED FT_Glyph_Copy FT_Glyph_Format FT_GLYPH_FORMAT_BITMAP FT_GLYPH_FORMAT_COMPOSITE FT_GLYPH_FORMAT_NONE FT_GLYPH_FORMAT_OUTLINE FT_GLYPH_FORMAT_PLOTTER FT_Glyph_Get_CBox FT_GLYPH_H FT_Glyph_Metrics FT_Glyph_Stroke FT_Glyph_StrokeBorder FT_Glyph_To_Bitmap FT_Glyph_Transform FT_GlyphRec FT_GlyphSlot FT_GlyphSlot_Own_Bitmap FT_GlyphSlotRec FT_GX_VALIDATE_H FT_GZIP_H FT_Gzip_Uncompress FT_HAS_COLOR FT_HAS_FAST_GLYPHS FT_HAS_FIXED_SIZES FT_HAS_GLYPH_NAMES FT_HAS_HORIZONTAL FT_HAS_KERNING FT_HAS_MULTIPLE_MASTERS FT_Has_PS_Glyph_Names FT_HAS_VERTICAL FT_HINTING_ADOBE FT_HINTING_FREETYPE FT_HINTING_XXX FT_IMAGE_H FT_IMAGE_TAG FT_Incremental FT_Incremental_FreeGlyphDataFunc FT_Incremental_FuncsRec FT_Incremental_GetGlyphDataFunc FT_Incremental_GetGlyphMetricsFunc FT_INCREMENTAL_H FT_Incremental_Interface FT_Incremental_InterfaceRec FT_Incremental_Metrics FT_Incremental_MetricsRec FT_Init_FreeType FT_Int FT_Int16 FT_Int32 FT_Int64 FT_IS_CID_KEYED FT_IS_FIXED_WIDTH FT_IS_NAMED_INSTANCE FT_IS_SCALABLE FT_IS_SFNT FT_IS_TRICKY FT_IS_VARIATION FT_KERNING_DEFAULT FT_Kerning_Mode FT_KERNING_UNFITTED FT_KERNING_UNSCALED FT_LayerIterator FT_LCD_FILTER_DEFAULT FT_LCD_FILTER_H FT_LCD_FILTER_LEGACY FT_LCD_FILTER_LEGACY1 FT_LCD_FILTER_LIGHT FT_LCD_FILTER_NONE FT_LcdFilter FT_LcdFiveTapFilter FT_Library FT_Library_SetLcdFilter FT_Library_SetLcdFilterWeights FT_Library_SetLcdGeometry FT_Library_Version FT_List FT_List_Add FT_List_Destructor FT_List_Finalize FT_List_Find FT_LIST_H FT_List_Insert FT_List_Iterate FT_List_Iterator FT_List_Remove FT_List_Up FT_ListNode FT_ListNodeRec FT_ListRec FT_LOAD_BITMAP_METRICS_ONLY FT_Load_Char FT_LOAD_COLOR FT_LOAD_COMPUTE_METRICS FT_LOAD_CROP_BITMAP FT_LOAD_DEFAULT FT_LOAD_FORCE_AUTOHINT FT_Load_Glyph FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH FT_LOAD_IGNORE_TRANSFORM FT_LOAD_LINEAR_DESIGN FT_LOAD_MONOCHROME FT_LOAD_NO_AUTOHINT FT_LOAD_NO_BITMAP FT_LOAD_NO_HINTING FT_LOAD_NO_RECURSE FT_LOAD_NO_SCALE FT_LOAD_PEDANTIC FT_LOAD_RENDER FT_Load_Sfnt_Table FT_LOAD_TARGET_LCD FT_LOAD_TARGET_LCD_V FT_LOAD_TARGET_LIGHT FT_LOAD_TARGET_MODE FT_LOAD_TARGET_MONO FT_LOAD_TARGET_NORMAL FT_LOAD_TARGET_XXX FT_LOAD_VERTICAL_LAYOUT FT_LOAD_XXX FT_Long FT_LZW_H FT_MAC_H FT_MAKE_TAG FT_Matrix FT_Matrix_Invert FT_Matrix_Multiply FT_Memory FT_MemoryRec FT_MM_Axis FT_MM_Var FT_Module FT_Module_Class FT_Module_Constructor FT_Module_Destructor FT_MODULE_ERRORS_H FT_MODULE_H FT_Module_Requester FT_MulDiv FT_MulFix FT_Multi_Master FT_MULTIPLE_MASTERS_H FT_New_Face FT_New_Face_From_FOND FT_New_Face_From_FSRef FT_New_Face_From_FSSpec FT_New_Glyph FT_New_Library FT_New_Memory_Face FT_New_Size FT_Offset FT_Open_Args FT_OPEN_DRIVER FT_Open_Face FT_OPEN_MEMORY FT_OPEN_PARAMS FT_OPEN_PATHNAME FT_OPEN_STREAM FT_OPEN_XXX FT_OpenType_Free FT_OpenType_Validate FT_OPENTYPE_VALIDATE_H FT_Orientation FT_ORIENTATION_FILL_LEFT FT_ORIENTATION_FILL_RIGHT FT_ORIENTATION_NONE FT_ORIENTATION_POSTSCRIPT FT_ORIENTATION_TRUETYPE FT_Outline FT_Outline_Check FT_Outline_ConicToFunc FT_Outline_Copy FT_Outline_CubicToFunc FT_Outline_Decompose FT_Outline_Done FT_Outline_Embolden FT_Outline_EmboldenXY FT_OUTLINE_EVEN_ODD_FILL FT_Outline_Funcs FT_Outline_Get_BBox FT_Outline_Get_Bitmap FT_Outline_Get_CBox FT_Outline_Get_Orientation FT_Outline_GetInsideBorder FT_Outline_GetOutsideBorder FT_OUTLINE_H FT_OUTLINE_HIGH_PRECISION FT_OUTLINE_IGNORE_DROPOUTS FT_OUTLINE_INCLUDE_STUBS FT_Outline_LineToFunc FT_Outline_MoveToFunc FT_Outline_New FT_OUTLINE_NONE FT_OUTLINE_OVERLAP FT_OUTLINE_OWNER FT_Outline_Render FT_Outline_Reverse FT_OUTLINE_REVERSE_FILL FT_OUTLINE_SINGLE_PASS FT_OUTLINE_SMART_DROPOUTS FT_Outline_Transform FT_Outline_Translate FT_OUTLINE_XXX FT_OutlineGlyph FT_OutlineGlyphRec FT_Palette_Data FT_Palette_Data_Get FT_PALETTE_FOR_DARK_BACKGROUND FT_PALETTE_FOR_LIGHT_BACKGROUND FT_Palette_Select FT_Palette_Set_Foreground_Color FT_PALETTE_XXX FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY FT_PARAM_TAG_INCREMENTAL FT_PARAM_TAG_LCD_FILTER_WEIGHTS FT_PARAM_TAG_RANDOM_SEED FT_PARAM_TAG_STEM_DARKENING FT_PARAM_TAG_UNPATENTED_HINTING FT_Parameter FT_PCF_DRIVER_H FT_PFR_H FT_Pixel_Mode FT_PIXEL_MODE_BGRA FT_PIXEL_MODE_GRAY FT_PIXEL_MODE_GRAY2 FT_PIXEL_MODE_GRAY4 FT_PIXEL_MODE_LCD FT_PIXEL_MODE_LCD_V FT_PIXEL_MODE_MONO FT_PIXEL_MODE_NONE FT_Pointer FT_Pos FT_Prop_GlyphToScriptMap FT_Prop_IncreaseXHeight FT_Property_Get FT_Property_Set FT_PtrDist FT_Raster FT_Raster_BitSet_Func FT_Raster_BitTest_Func FT_Raster_DoneFunc FT_RASTER_FLAG_AA FT_RASTER_FLAG_CLIP FT_RASTER_FLAG_DEFAULT FT_RASTER_FLAG_DIRECT FT_RASTER_FLAG_XXX FT_Raster_Funcs FT_Raster_NewFunc FT_Raster_Params FT_Raster_RenderFunc FT_Raster_ResetFunc FT_Raster_SetModeFunc FT_Realloc_Func FT_Reference_Face FT_Reference_Library FT_Remove_Module FT_Render_Glyph FT_RENDER_H FT_Render_Mode FT_RENDER_MODE_LCD FT_RENDER_MODE_LCD_V FT_RENDER_MODE_LIGHT FT_RENDER_MODE_MONO FT_RENDER_MODE_NORMAL FT_Renderer FT_Renderer_Class FT_Request_Size FT_RoundFix FT_Select_Charmap FT_Select_Size FT_Set_Char_Size FT_Set_Charmap FT_Set_Debug_Hook FT_Set_Default_Properties FT_Set_MM_Blend_Coordinates FT_Set_MM_Design_Coordinates FT_Set_MM_WeightVector FT_Set_Named_Instance FT_Set_Pixel_Sizes FT_Set_Renderer FT_Set_Transform FT_Set_Var_Blend_Coordinates FT_Set_Var_Design_Coordinates FT_SFNT_HEAD FT_SFNT_HHEA FT_SFNT_MAXP FT_SFNT_NAMES_H FT_SFNT_OS2 FT_SFNT_PCLT FT_SFNT_POST FT_Sfnt_Table_Info FT_Sfnt_Tag FT_SFNT_VHEA FT_SfntLangTag FT_SfntName FT_Short FT_Sin FT_Size FT_Size_Internal FT_Size_Metrics FT_Size_Request FT_Size_Request_Type FT_SIZE_REQUEST_TYPE_BBOX FT_SIZE_REQUEST_TYPE_CELL FT_SIZE_REQUEST_TYPE_NOMINAL FT_SIZE_REQUEST_TYPE_REAL_DIM FT_SIZE_REQUEST_TYPE_SCALES FT_Size_RequestRec FT_SizeRec FT_SIZES_H FT_Slot_Internal FT_Span FT_SpanFunc FT_Stream FT_Stream_CloseFunc FT_Stream_IoFunc FT_Stream_OpenBzip2 FT_Stream_OpenGzip FT_Stream_OpenLZW FT_StreamDesc FT_StreamRec FT_String FT_Stroker FT_Stroker_BeginSubPath FT_STROKER_BORDER_LEFT FT_STROKER_BORDER_RIGHT FT_Stroker_ConicTo FT_Stroker_CubicTo FT_Stroker_Done FT_Stroker_EndSubPath FT_Stroker_Export FT_Stroker_ExportBorder FT_Stroker_GetBorderCounts FT_Stroker_GetCounts FT_STROKER_H FT_Stroker_LineCap FT_STROKER_LINECAP_BUTT FT_STROKER_LINECAP_ROUND FT_STROKER_LINECAP_SQUARE FT_Stroker_LineJoin FT_STROKER_LINEJOIN_BEVEL FT_STROKER_LINEJOIN_MITER FT_STROKER_LINEJOIN_MITER_FIXED FT_STROKER_LINEJOIN_MITER_VARIABLE FT_STROKER_LINEJOIN_ROUND FT_Stroker_LineTo FT_Stroker_New FT_Stroker_ParseOutline FT_Stroker_Rewind FT_Stroker_Set FT_StrokerBorder FT_STYLE_FLAG_BOLD FT_STYLE_FLAG_ITALIC FT_STYLE_FLAG_XXX FT_SubGlyph FT_SUBGLYPH_FLAG_2X2 FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID FT_SUBGLYPH_FLAG_SCALE FT_SUBGLYPH_FLAG_USE_MY_METRICS FT_SUBGLYPH_FLAG_XXX FT_SUBGLYPH_FLAG_XY_SCALE FT_SYNTHESIS_H FT_SYSTEM_H FT_Tag FT_Tan FT_TRIGONOMETRY_H FT_TRUETYPE_DRIVER_H FT_TRUETYPE_ENGINE_TYPE_NONE FT_TRUETYPE_ENGINE_TYPE_PATENTED FT_TRUETYPE_ENGINE_TYPE_UNPATENTED FT_TRUETYPE_IDS_H FT_TRUETYPE_TABLES_H FT_TRUETYPE_TAGS_H FT_TrueTypeEngineType FT_TrueTypeGX_Free FT_TrueTypeGX_Validate FT_TYPE1_TABLES_H FT_TYPES_H FT_UFWord FT_UInt FT_UInt16 FT_UInt32 FT_UInt64 FT_ULong FT_UnitVector FT_UShort FT_VALIDATE_APPLE FT_VALIDATE_BASE FT_VALIDATE_bsln FT_VALIDATE_CKERN FT_VALIDATE_CKERNXXX FT_VALIDATE_feat FT_VALIDATE_GDEF FT_VALIDATE_GPOS FT_VALIDATE_GSUB FT_VALIDATE_GX FT_VALIDATE_GX_LENGTH FT_VALIDATE_GXXXX FT_VALIDATE_JSTF FT_VALIDATE_just FT_VALIDATE_kern FT_VALIDATE_lcar FT_VALIDATE_MATH FT_VALIDATE_mort FT_VALIDATE_morx FT_VALIDATE_MS FT_VALIDATE_opbd FT_VALIDATE_OT FT_VALIDATE_OTXXX FT_VALIDATE_prop FT_VALIDATE_trak FT_Var_Axis FT_VAR_AXIS_FLAG_HIDDEN FT_VAR_AXIS_FLAG_XXX FT_Var_Named_Style FT_Vector FT_Vector_From_Polar FT_Vector_Length FT_Vector_Polarize FT_Vector_Rotate FT_Vector_Transform FT_Vector_Unit FT_WinFNT_Header FT_WinFNT_HeaderRec FT_WinFNT_ID_CP1250 FT_WinFNT_ID_CP1251 FT_WinFNT_ID_CP1252 FT_WinFNT_ID_CP1253 FT_WinFNT_ID_CP1254 FT_WinFNT_ID_CP1255 FT_WinFNT_ID_CP1256 FT_WinFNT_ID_CP1257 FT_WinFNT_ID_CP1258 FT_WinFNT_ID_CP1361 FT_WinFNT_ID_CP874 FT_WinFNT_ID_CP932 FT_WinFNT_ID_CP936 FT_WinFNT_ID_CP949 FT_WinFNT_ID_CP950 FT_WinFNT_ID_DEFAULT FT_WinFNT_ID_MAC FT_WinFNT_ID_OEM FT_WinFNT_ID_SYMBOL FT_WinFNT_ID_XXX FT_WINFONTS_H FTC_CMapCache FTC_CMapCache_Lookup FTC_CMapCache_New FTC_Face_Requester FTC_FaceID FTC_ImageCache FTC_ImageCache_Lookup FTC_ImageCache_LookupScaler FTC_ImageCache_New FTC_ImageType FTC_ImageTypeRec FTC_Manager FTC_Manager_Done FTC_Manager_LookupFace FTC_Manager_LookupSize FTC_Manager_New FTC_Manager_RemoveFaceID FTC_Manager_Reset FTC_Node FTC_Node_Unref FTC_SBit FTC_SBitCache FTC_SBitCache_Lookup FTC_SBitCache_LookupScaler FTC_SBitCache_New FTC_SBitRec FTC_Scaler FTC_ScalerRec G \u00b6 glyph-to-script-map H \u00b6 hinting-engine I \u00b6 increase-x-height interpreter-version N \u00b6 no-long-family-names no-stem-darkening P \u00b6 PS_DICT_BLUE_FUZZ PS_DICT_BLUE_SCALE PS_DICT_BLUE_SHIFT PS_DICT_BLUE_VALUE PS_DICT_CHAR_STRING PS_DICT_CHAR_STRING_KEY PS_DICT_ENCODING_ENTRY PS_DICT_ENCODING_TYPE PS_DICT_FAMILY_BLUE PS_DICT_FAMILY_NAME PS_DICT_FAMILY_OTHER_BLUE PS_DICT_FONT_BBOX PS_DICT_FONT_MATRIX PS_DICT_FONT_NAME PS_DICT_FONT_TYPE PS_DICT_FORCE_BOLD PS_DICT_FS_TYPE PS_DICT_FULL_NAME PS_DICT_IS_FIXED_PITCH PS_DICT_ITALIC_ANGLE PS_Dict_Keys PS_DICT_LANGUAGE_GROUP PS_DICT_LEN_IV PS_DICT_MIN_FEATURE PS_DICT_NOTICE PS_DICT_NUM_BLUE_VALUES PS_DICT_NUM_CHAR_STRINGS PS_DICT_NUM_FAMILY_BLUES PS_DICT_NUM_FAMILY_OTHER_BLUES PS_DICT_NUM_OTHER_BLUES PS_DICT_NUM_STEM_SNAP_H PS_DICT_NUM_STEM_SNAP_V PS_DICT_NUM_SUBRS PS_DICT_OTHER_BLUE PS_DICT_PAINT_TYPE PS_DICT_PASSWORD PS_DICT_RND_STEM_UP PS_DICT_STD_HW PS_DICT_STD_VW PS_DICT_STEM_SNAP_H PS_DICT_STEM_SNAP_V PS_DICT_SUBR PS_DICT_UNDERLINE_POSITION PS_DICT_UNDERLINE_THICKNESS PS_DICT_UNIQUE_ID PS_DICT_VERSION PS_DICT_WEIGHT PS_FontInfo PS_FontInfoRec PS_Private PS_PrivateRec R \u00b6 random-seed T \u00b6 T1_BLEND_BLUE_SCALE T1_BLEND_BLUE_SHIFT T1_BLEND_BLUE_VALUES T1_BLEND_FAMILY_BLUES T1_BLEND_FAMILY_OTHER_BLUES T1_Blend_Flags T1_BLEND_FORCE_BOLD T1_BLEND_ITALIC_ANGLE T1_BLEND_OTHER_BLUES T1_BLEND_STANDARD_HEIGHT T1_BLEND_STANDARD_WIDTH T1_BLEND_STEM_SNAP_HEIGHTS T1_BLEND_STEM_SNAP_WIDTHS T1_BLEND_UNDERLINE_POSITION T1_BLEND_UNDERLINE_THICKNESS T1_ENCODING_TYPE_ARRAY T1_ENCODING_TYPE_EXPERT T1_ENCODING_TYPE_ISOLATIN1 T1_ENCODING_TYPE_NONE T1_ENCODING_TYPE_STANDARD T1_EncodingType T1_FontInfo T1_Private TT_ADOBE_ID_CUSTOM TT_ADOBE_ID_EXPERT TT_ADOBE_ID_LATIN_1 TT_ADOBE_ID_STANDARD TT_ADOBE_ID_XXX TT_APPLE_ID_DEFAULT TT_APPLE_ID_FULL_UNICODE TT_APPLE_ID_ISO_10646 TT_APPLE_ID_UNICODE_1_1 TT_APPLE_ID_UNICODE_2_0 TT_APPLE_ID_UNICODE_32 TT_APPLE_ID_VARIANT_SELECTOR TT_APPLE_ID_XXX TT_Header TT_HoriHeader TT_INTERPRETER_VERSION_35 TT_INTERPRETER_VERSION_38 TT_INTERPRETER_VERSION_40 TT_INTERPRETER_VERSION_XXX TT_ISO_ID_10646 TT_ISO_ID_7BIT_ASCII TT_ISO_ID_8859_1 TT_ISO_ID_XXX TT_MAC_ID_XXX TT_MAC_LANGID_XXX TT_MaxProfile TT_MS_ID_BIG_5 TT_MS_ID_JOHAB TT_MS_ID_PRC TT_MS_ID_SJIS TT_MS_ID_SYMBOL_CS TT_MS_ID_UCS_4 TT_MS_ID_UNICODE_CS TT_MS_ID_WANSUNG TT_MS_ID_XXX TT_MS_LANGID_XXX TT_NAME_ID_XXX TT_OS2 TT_PCLT TT_PLATFORM_ADOBE TT_PLATFORM_APPLE_UNICODE TT_PLATFORM_CUSTOM TT_PLATFORM_ISO TT_PLATFORM_MACINTOSH TT_PLATFORM_MICROSOFT TT_PLATFORM_XXX TT_Postscript TT_UCR_XXX TT_VertHeader W \u00b6 warping generated on Tue Oct 20 05:14:52 2020 UTC","title":"Index"},{"location":"ft2-index.html#freetype-2104-api-reference","text":"","title":"FreeType-2.10.4 API Reference"},{"location":"ft2-index.html#b","text":"BDF_Property BDF_PROPERTY_TYPE_ATOM BDF_PROPERTY_TYPE_CARDINAL BDF_PROPERTY_TYPE_INTEGER BDF_PROPERTY_TYPE_NONE BDF_PropertyRec BDF_PropertyType","title":"B"},{"location":"ft2-index.html#c","text":"CID_FaceDict CID_FaceDictRec CID_FaceInfo CID_FaceInfoRec CID_FontDict CID_Info","title":"C"},{"location":"ft2-index.html#d","text":"darkening-parameters default-script","title":"D"},{"location":"ft2-index.html#f","text":"fallback-script FREETYPE_MAJOR FREETYPE_MINOR FREETYPE_PATCH FREETYPE_XXX FT_Activate_Size FT_Add_Default_Modules FT_Add_Module FT_ADVANCE_FLAG_FAST_ONLY FT_ADVANCES_H FT_Alloc_Func FT_Angle FT_ANGLE_2PI FT_Angle_Diff FT_ANGLE_PI FT_ANGLE_PI2 FT_ANGLE_PI4 FT_Atan2 FT_Attach_File FT_Attach_Stream FT_AUTOHINTER_H FT_AUTOHINTER_SCRIPT_CJK FT_AUTOHINTER_SCRIPT_INDIC FT_AUTOHINTER_SCRIPT_LATIN FT_AUTOHINTER_SCRIPT_NONE FT_AUTOHINTER_SCRIPT_XXX FT_BBox FT_BBOX_H FT_BDF_H FT_Bitmap FT_Bitmap_Blend FT_Bitmap_Convert FT_Bitmap_Copy FT_Bitmap_Done FT_Bitmap_Embolden FT_BITMAP_H FT_Bitmap_Init FT_Bitmap_Size FT_BitmapGlyph FT_BitmapGlyphRec FT_Bool FT_Byte FT_Bytes FT_BZIP2_H FT_CACHE_H FT_CeilFix FT_CFF_DRIVER_H FT_Char FT_CharMap FT_CharMapRec FT_CID_H FT_ClassicKern_Free FT_ClassicKern_Validate FT_Color FT_COLOR_H FT_CONFIG_CONFIG_H FT_CONFIG_MODULES_H FT_CONFIG_OPTIONS_H FT_CONFIG_STANDARD_LIBRARY_H FT_Cos FT_Data FT_DEBUG_HOOK_TRUETYPE FT_DEBUG_HOOK_XXX FT_DebugHook_Func FT_DivFix FT_Done_Face FT_Done_FreeType FT_Done_Glyph FT_Done_Library FT_Done_MM_Var FT_Done_Size FT_Driver FT_DRIVER_H FT_ENC_TAG FT_Encoding FT_ENCODING_ADOBE_CUSTOM FT_ENCODING_ADOBE_EXPERT FT_ENCODING_ADOBE_LATIN_1 FT_ENCODING_ADOBE_STANDARD FT_ENCODING_APPLE_ROMAN FT_ENCODING_BIG5 FT_ENCODING_JOHAB FT_ENCODING_MS_BIG5 FT_ENCODING_MS_GB2312 FT_ENCODING_MS_JOHAB FT_ENCODING_MS_SJIS FT_ENCODING_MS_SYMBOL FT_ENCODING_MS_WANSUNG FT_ENCODING_NONE FT_ENCODING_OLD_LATIN_2 FT_ENCODING_PRC FT_ENCODING_SJIS FT_ENCODING_UNICODE FT_ENCODING_WANSUNG FT_Err_XXX FT_Error FT_Error_String FT_ERRORS_H FT_F26Dot6 FT_F2Dot14 FT_Face FT_Face_CheckTrueTypePatents FT_FACE_FLAG_CID_KEYED FT_FACE_FLAG_COLOR FT_FACE_FLAG_EXTERNAL_STREAM FT_FACE_FLAG_FAST_GLYPHS FT_FACE_FLAG_FIXED_SIZES FT_FACE_FLAG_FIXED_WIDTH FT_FACE_FLAG_GLYPH_NAMES FT_FACE_FLAG_HINTER FT_FACE_FLAG_HORIZONTAL FT_FACE_FLAG_KERNING FT_FACE_FLAG_MULTIPLE_MASTERS FT_FACE_FLAG_SCALABLE FT_FACE_FLAG_SFNT FT_FACE_FLAG_TRICKY FT_FACE_FLAG_VARIATION FT_FACE_FLAG_VERTICAL FT_FACE_FLAG_XXX FT_Face_GetCharsOfVariant FT_Face_GetCharVariantIndex FT_Face_GetCharVariantIsDefault FT_Face_GetVariantSelectors FT_Face_GetVariantsOfChar FT_Face_Internal FT_Face_Properties FT_Face_SetUnpatentedHinting FT_FaceRec FT_Fixed FT_FloorFix FT_FONT_FORMATS_H FT_Free_Func FT_FREETYPE_H FT_FSTYPE_BITMAP_EMBEDDING_ONLY FT_FSTYPE_EDITABLE_EMBEDDING FT_FSTYPE_INSTALLABLE_EMBEDDING FT_FSTYPE_NO_SUBSETTING FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING FT_FSTYPE_XXX FT_FWord FT_GASP_DO_GRAY FT_GASP_DO_GRIDFIT FT_GASP_H FT_GASP_NO_TABLE FT_GASP_SYMMETRIC_GRIDFIT FT_GASP_SYMMETRIC_SMOOTHING FT_GASP_XXX FT_Generic FT_Generic_Finalizer FT_Get_Advance FT_Get_Advances FT_Get_BDF_Charset_ID FT_Get_BDF_Property FT_Get_Char_Index FT_Get_Charmap_Index FT_Get_CID_From_Glyph_Index FT_Get_CID_Is_Internally_CID_Keyed FT_Get_CID_Registry_Ordering_Supplement FT_Get_CMap_Format FT_Get_CMap_Language_ID FT_Get_Color_Glyph_Layer FT_Get_First_Char FT_Get_Font_Format FT_Get_FSType_Flags FT_Get_Gasp FT_Get_Glyph FT_Get_Glyph_Name FT_Get_Kerning FT_Get_MM_Blend_Coordinates FT_Get_MM_Var FT_Get_MM_WeightVector FT_Get_Module FT_Get_Multi_Master FT_Get_Name_Index FT_Get_Next_Char FT_Get_PFR_Advance FT_Get_PFR_Kerning FT_Get_PFR_Metrics FT_Get_Postscript_Name FT_Get_PS_Font_Info FT_Get_PS_Font_Private FT_Get_PS_Font_Value FT_Get_Renderer FT_Get_Sfnt_LangTag FT_Get_Sfnt_Name FT_Get_Sfnt_Name_Count FT_Get_Sfnt_Table FT_Get_SubGlyph_Info FT_Get_Track_Kerning FT_Get_TrueType_Engine_Type FT_Get_Var_Axis_Flags FT_Get_Var_Blend_Coordinates FT_Get_Var_Design_Coordinates FT_Get_WinFNT_Header FT_GetFile_From_Mac_ATS_Name FT_GetFile_From_Mac_Name FT_GetFilePath_From_Mac_ATS_Name FT_Glyph FT_GLYPH_BBOX_GRIDFIT FT_Glyph_BBox_Mode FT_GLYPH_BBOX_PIXELS FT_GLYPH_BBOX_SUBPIXELS FT_GLYPH_BBOX_TRUNCATE FT_GLYPH_BBOX_UNSCALED FT_Glyph_Copy FT_Glyph_Format FT_GLYPH_FORMAT_BITMAP FT_GLYPH_FORMAT_COMPOSITE FT_GLYPH_FORMAT_NONE FT_GLYPH_FORMAT_OUTLINE FT_GLYPH_FORMAT_PLOTTER FT_Glyph_Get_CBox FT_GLYPH_H FT_Glyph_Metrics FT_Glyph_Stroke FT_Glyph_StrokeBorder FT_Glyph_To_Bitmap FT_Glyph_Transform FT_GlyphRec FT_GlyphSlot FT_GlyphSlot_Own_Bitmap FT_GlyphSlotRec FT_GX_VALIDATE_H FT_GZIP_H FT_Gzip_Uncompress FT_HAS_COLOR FT_HAS_FAST_GLYPHS FT_HAS_FIXED_SIZES FT_HAS_GLYPH_NAMES FT_HAS_HORIZONTAL FT_HAS_KERNING FT_HAS_MULTIPLE_MASTERS FT_Has_PS_Glyph_Names FT_HAS_VERTICAL FT_HINTING_ADOBE FT_HINTING_FREETYPE FT_HINTING_XXX FT_IMAGE_H FT_IMAGE_TAG FT_Incremental FT_Incremental_FreeGlyphDataFunc FT_Incremental_FuncsRec FT_Incremental_GetGlyphDataFunc FT_Incremental_GetGlyphMetricsFunc FT_INCREMENTAL_H FT_Incremental_Interface FT_Incremental_InterfaceRec FT_Incremental_Metrics FT_Incremental_MetricsRec FT_Init_FreeType FT_Int FT_Int16 FT_Int32 FT_Int64 FT_IS_CID_KEYED FT_IS_FIXED_WIDTH FT_IS_NAMED_INSTANCE FT_IS_SCALABLE FT_IS_SFNT FT_IS_TRICKY FT_IS_VARIATION FT_KERNING_DEFAULT FT_Kerning_Mode FT_KERNING_UNFITTED FT_KERNING_UNSCALED FT_LayerIterator FT_LCD_FILTER_DEFAULT FT_LCD_FILTER_H FT_LCD_FILTER_LEGACY FT_LCD_FILTER_LEGACY1 FT_LCD_FILTER_LIGHT FT_LCD_FILTER_NONE FT_LcdFilter FT_LcdFiveTapFilter FT_Library FT_Library_SetLcdFilter FT_Library_SetLcdFilterWeights FT_Library_SetLcdGeometry FT_Library_Version FT_List FT_List_Add FT_List_Destructor FT_List_Finalize FT_List_Find FT_LIST_H FT_List_Insert FT_List_Iterate FT_List_Iterator FT_List_Remove FT_List_Up FT_ListNode FT_ListNodeRec FT_ListRec FT_LOAD_BITMAP_METRICS_ONLY FT_Load_Char FT_LOAD_COLOR FT_LOAD_COMPUTE_METRICS FT_LOAD_CROP_BITMAP FT_LOAD_DEFAULT FT_LOAD_FORCE_AUTOHINT FT_Load_Glyph FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH FT_LOAD_IGNORE_TRANSFORM FT_LOAD_LINEAR_DESIGN FT_LOAD_MONOCHROME FT_LOAD_NO_AUTOHINT FT_LOAD_NO_BITMAP FT_LOAD_NO_HINTING FT_LOAD_NO_RECURSE FT_LOAD_NO_SCALE FT_LOAD_PEDANTIC FT_LOAD_RENDER FT_Load_Sfnt_Table FT_LOAD_TARGET_LCD FT_LOAD_TARGET_LCD_V FT_LOAD_TARGET_LIGHT FT_LOAD_TARGET_MODE FT_LOAD_TARGET_MONO FT_LOAD_TARGET_NORMAL FT_LOAD_TARGET_XXX FT_LOAD_VERTICAL_LAYOUT FT_LOAD_XXX FT_Long FT_LZW_H FT_MAC_H FT_MAKE_TAG FT_Matrix FT_Matrix_Invert FT_Matrix_Multiply FT_Memory FT_MemoryRec FT_MM_Axis FT_MM_Var FT_Module FT_Module_Class FT_Module_Constructor FT_Module_Destructor FT_MODULE_ERRORS_H FT_MODULE_H FT_Module_Requester FT_MulDiv FT_MulFix FT_Multi_Master FT_MULTIPLE_MASTERS_H FT_New_Face FT_New_Face_From_FOND FT_New_Face_From_FSRef FT_New_Face_From_FSSpec FT_New_Glyph FT_New_Library FT_New_Memory_Face FT_New_Size FT_Offset FT_Open_Args FT_OPEN_DRIVER FT_Open_Face FT_OPEN_MEMORY FT_OPEN_PARAMS FT_OPEN_PATHNAME FT_OPEN_STREAM FT_OPEN_XXX FT_OpenType_Free FT_OpenType_Validate FT_OPENTYPE_VALIDATE_H FT_Orientation FT_ORIENTATION_FILL_LEFT FT_ORIENTATION_FILL_RIGHT FT_ORIENTATION_NONE FT_ORIENTATION_POSTSCRIPT FT_ORIENTATION_TRUETYPE FT_Outline FT_Outline_Check FT_Outline_ConicToFunc FT_Outline_Copy FT_Outline_CubicToFunc FT_Outline_Decompose FT_Outline_Done FT_Outline_Embolden FT_Outline_EmboldenXY FT_OUTLINE_EVEN_ODD_FILL FT_Outline_Funcs FT_Outline_Get_BBox FT_Outline_Get_Bitmap FT_Outline_Get_CBox FT_Outline_Get_Orientation FT_Outline_GetInsideBorder FT_Outline_GetOutsideBorder FT_OUTLINE_H FT_OUTLINE_HIGH_PRECISION FT_OUTLINE_IGNORE_DROPOUTS FT_OUTLINE_INCLUDE_STUBS FT_Outline_LineToFunc FT_Outline_MoveToFunc FT_Outline_New FT_OUTLINE_NONE FT_OUTLINE_OVERLAP FT_OUTLINE_OWNER FT_Outline_Render FT_Outline_Reverse FT_OUTLINE_REVERSE_FILL FT_OUTLINE_SINGLE_PASS FT_OUTLINE_SMART_DROPOUTS FT_Outline_Transform FT_Outline_Translate FT_OUTLINE_XXX FT_OutlineGlyph FT_OutlineGlyphRec FT_Palette_Data FT_Palette_Data_Get FT_PALETTE_FOR_DARK_BACKGROUND FT_PALETTE_FOR_LIGHT_BACKGROUND FT_Palette_Select FT_Palette_Set_Foreground_Color FT_PALETTE_XXX FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY FT_PARAM_TAG_INCREMENTAL FT_PARAM_TAG_LCD_FILTER_WEIGHTS FT_PARAM_TAG_RANDOM_SEED FT_PARAM_TAG_STEM_DARKENING FT_PARAM_TAG_UNPATENTED_HINTING FT_Parameter FT_PCF_DRIVER_H FT_PFR_H FT_Pixel_Mode FT_PIXEL_MODE_BGRA FT_PIXEL_MODE_GRAY FT_PIXEL_MODE_GRAY2 FT_PIXEL_MODE_GRAY4 FT_PIXEL_MODE_LCD FT_PIXEL_MODE_LCD_V FT_PIXEL_MODE_MONO FT_PIXEL_MODE_NONE FT_Pointer FT_Pos FT_Prop_GlyphToScriptMap FT_Prop_IncreaseXHeight FT_Property_Get FT_Property_Set FT_PtrDist FT_Raster FT_Raster_BitSet_Func FT_Raster_BitTest_Func FT_Raster_DoneFunc FT_RASTER_FLAG_AA FT_RASTER_FLAG_CLIP FT_RASTER_FLAG_DEFAULT FT_RASTER_FLAG_DIRECT FT_RASTER_FLAG_XXX FT_Raster_Funcs FT_Raster_NewFunc FT_Raster_Params FT_Raster_RenderFunc FT_Raster_ResetFunc FT_Raster_SetModeFunc FT_Realloc_Func FT_Reference_Face FT_Reference_Library FT_Remove_Module FT_Render_Glyph FT_RENDER_H FT_Render_Mode FT_RENDER_MODE_LCD FT_RENDER_MODE_LCD_V FT_RENDER_MODE_LIGHT FT_RENDER_MODE_MONO FT_RENDER_MODE_NORMAL FT_Renderer FT_Renderer_Class FT_Request_Size FT_RoundFix FT_Select_Charmap FT_Select_Size FT_Set_Char_Size FT_Set_Charmap FT_Set_Debug_Hook FT_Set_Default_Properties FT_Set_MM_Blend_Coordinates FT_Set_MM_Design_Coordinates FT_Set_MM_WeightVector FT_Set_Named_Instance FT_Set_Pixel_Sizes FT_Set_Renderer FT_Set_Transform FT_Set_Var_Blend_Coordinates FT_Set_Var_Design_Coordinates FT_SFNT_HEAD FT_SFNT_HHEA FT_SFNT_MAXP FT_SFNT_NAMES_H FT_SFNT_OS2 FT_SFNT_PCLT FT_SFNT_POST FT_Sfnt_Table_Info FT_Sfnt_Tag FT_SFNT_VHEA FT_SfntLangTag FT_SfntName FT_Short FT_Sin FT_Size FT_Size_Internal FT_Size_Metrics FT_Size_Request FT_Size_Request_Type FT_SIZE_REQUEST_TYPE_BBOX FT_SIZE_REQUEST_TYPE_CELL FT_SIZE_REQUEST_TYPE_NOMINAL FT_SIZE_REQUEST_TYPE_REAL_DIM FT_SIZE_REQUEST_TYPE_SCALES FT_Size_RequestRec FT_SizeRec FT_SIZES_H FT_Slot_Internal FT_Span FT_SpanFunc FT_Stream FT_Stream_CloseFunc FT_Stream_IoFunc FT_Stream_OpenBzip2 FT_Stream_OpenGzip FT_Stream_OpenLZW FT_StreamDesc FT_StreamRec FT_String FT_Stroker FT_Stroker_BeginSubPath FT_STROKER_BORDER_LEFT FT_STROKER_BORDER_RIGHT FT_Stroker_ConicTo FT_Stroker_CubicTo FT_Stroker_Done FT_Stroker_EndSubPath FT_Stroker_Export FT_Stroker_ExportBorder FT_Stroker_GetBorderCounts FT_Stroker_GetCounts FT_STROKER_H FT_Stroker_LineCap FT_STROKER_LINECAP_BUTT FT_STROKER_LINECAP_ROUND FT_STROKER_LINECAP_SQUARE FT_Stroker_LineJoin FT_STROKER_LINEJOIN_BEVEL FT_STROKER_LINEJOIN_MITER FT_STROKER_LINEJOIN_MITER_FIXED FT_STROKER_LINEJOIN_MITER_VARIABLE FT_STROKER_LINEJOIN_ROUND FT_Stroker_LineTo FT_Stroker_New FT_Stroker_ParseOutline FT_Stroker_Rewind FT_Stroker_Set FT_StrokerBorder FT_STYLE_FLAG_BOLD FT_STYLE_FLAG_ITALIC FT_STYLE_FLAG_XXX FT_SubGlyph FT_SUBGLYPH_FLAG_2X2 FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID FT_SUBGLYPH_FLAG_SCALE FT_SUBGLYPH_FLAG_USE_MY_METRICS FT_SUBGLYPH_FLAG_XXX FT_SUBGLYPH_FLAG_XY_SCALE FT_SYNTHESIS_H FT_SYSTEM_H FT_Tag FT_Tan FT_TRIGONOMETRY_H FT_TRUETYPE_DRIVER_H FT_TRUETYPE_ENGINE_TYPE_NONE FT_TRUETYPE_ENGINE_TYPE_PATENTED FT_TRUETYPE_ENGINE_TYPE_UNPATENTED FT_TRUETYPE_IDS_H FT_TRUETYPE_TABLES_H FT_TRUETYPE_TAGS_H FT_TrueTypeEngineType FT_TrueTypeGX_Free FT_TrueTypeGX_Validate FT_TYPE1_TABLES_H FT_TYPES_H FT_UFWord FT_UInt FT_UInt16 FT_UInt32 FT_UInt64 FT_ULong FT_UnitVector FT_UShort FT_VALIDATE_APPLE FT_VALIDATE_BASE FT_VALIDATE_bsln FT_VALIDATE_CKERN FT_VALIDATE_CKERNXXX FT_VALIDATE_feat FT_VALIDATE_GDEF FT_VALIDATE_GPOS FT_VALIDATE_GSUB FT_VALIDATE_GX FT_VALIDATE_GX_LENGTH FT_VALIDATE_GXXXX FT_VALIDATE_JSTF FT_VALIDATE_just FT_VALIDATE_kern FT_VALIDATE_lcar FT_VALIDATE_MATH FT_VALIDATE_mort FT_VALIDATE_morx FT_VALIDATE_MS FT_VALIDATE_opbd FT_VALIDATE_OT FT_VALIDATE_OTXXX FT_VALIDATE_prop FT_VALIDATE_trak FT_Var_Axis FT_VAR_AXIS_FLAG_HIDDEN FT_VAR_AXIS_FLAG_XXX FT_Var_Named_Style FT_Vector FT_Vector_From_Polar FT_Vector_Length FT_Vector_Polarize FT_Vector_Rotate FT_Vector_Transform FT_Vector_Unit FT_WinFNT_Header FT_WinFNT_HeaderRec FT_WinFNT_ID_CP1250 FT_WinFNT_ID_CP1251 FT_WinFNT_ID_CP1252 FT_WinFNT_ID_CP1253 FT_WinFNT_ID_CP1254 FT_WinFNT_ID_CP1255 FT_WinFNT_ID_CP1256 FT_WinFNT_ID_CP1257 FT_WinFNT_ID_CP1258 FT_WinFNT_ID_CP1361 FT_WinFNT_ID_CP874 FT_WinFNT_ID_CP932 FT_WinFNT_ID_CP936 FT_WinFNT_ID_CP949 FT_WinFNT_ID_CP950 FT_WinFNT_ID_DEFAULT FT_WinFNT_ID_MAC FT_WinFNT_ID_OEM FT_WinFNT_ID_SYMBOL FT_WinFNT_ID_XXX FT_WINFONTS_H FTC_CMapCache FTC_CMapCache_Lookup FTC_CMapCache_New FTC_Face_Requester FTC_FaceID FTC_ImageCache FTC_ImageCache_Lookup FTC_ImageCache_LookupScaler FTC_ImageCache_New FTC_ImageType FTC_ImageTypeRec FTC_Manager FTC_Manager_Done FTC_Manager_LookupFace FTC_Manager_LookupSize FTC_Manager_New FTC_Manager_RemoveFaceID FTC_Manager_Reset FTC_Node FTC_Node_Unref FTC_SBit FTC_SBitCache FTC_SBitCache_Lookup FTC_SBitCache_LookupScaler FTC_SBitCache_New FTC_SBitRec FTC_Scaler FTC_ScalerRec","title":"F"},{"location":"ft2-index.html#g","text":"glyph-to-script-map","title":"G"},{"location":"ft2-index.html#h","text":"hinting-engine","title":"H"},{"location":"ft2-index.html#i","text":"increase-x-height interpreter-version","title":"I"},{"location":"ft2-index.html#n","text":"no-long-family-names no-stem-darkening","title":"N"},{"location":"ft2-index.html#p","text":"PS_DICT_BLUE_FUZZ PS_DICT_BLUE_SCALE PS_DICT_BLUE_SHIFT PS_DICT_BLUE_VALUE PS_DICT_CHAR_STRING PS_DICT_CHAR_STRING_KEY PS_DICT_ENCODING_ENTRY PS_DICT_ENCODING_TYPE PS_DICT_FAMILY_BLUE PS_DICT_FAMILY_NAME PS_DICT_FAMILY_OTHER_BLUE PS_DICT_FONT_BBOX PS_DICT_FONT_MATRIX PS_DICT_FONT_NAME PS_DICT_FONT_TYPE PS_DICT_FORCE_BOLD PS_DICT_FS_TYPE PS_DICT_FULL_NAME PS_DICT_IS_FIXED_PITCH PS_DICT_ITALIC_ANGLE PS_Dict_Keys PS_DICT_LANGUAGE_GROUP PS_DICT_LEN_IV PS_DICT_MIN_FEATURE PS_DICT_NOTICE PS_DICT_NUM_BLUE_VALUES PS_DICT_NUM_CHAR_STRINGS PS_DICT_NUM_FAMILY_BLUES PS_DICT_NUM_FAMILY_OTHER_BLUES PS_DICT_NUM_OTHER_BLUES PS_DICT_NUM_STEM_SNAP_H PS_DICT_NUM_STEM_SNAP_V PS_DICT_NUM_SUBRS PS_DICT_OTHER_BLUE PS_DICT_PAINT_TYPE PS_DICT_PASSWORD PS_DICT_RND_STEM_UP PS_DICT_STD_HW PS_DICT_STD_VW PS_DICT_STEM_SNAP_H PS_DICT_STEM_SNAP_V PS_DICT_SUBR PS_DICT_UNDERLINE_POSITION PS_DICT_UNDERLINE_THICKNESS PS_DICT_UNIQUE_ID PS_DICT_VERSION PS_DICT_WEIGHT PS_FontInfo PS_FontInfoRec PS_Private PS_PrivateRec","title":"P"},{"location":"ft2-index.html#r","text":"random-seed","title":"R"},{"location":"ft2-index.html#t","text":"T1_BLEND_BLUE_SCALE T1_BLEND_BLUE_SHIFT T1_BLEND_BLUE_VALUES T1_BLEND_FAMILY_BLUES T1_BLEND_FAMILY_OTHER_BLUES T1_Blend_Flags T1_BLEND_FORCE_BOLD T1_BLEND_ITALIC_ANGLE T1_BLEND_OTHER_BLUES T1_BLEND_STANDARD_HEIGHT T1_BLEND_STANDARD_WIDTH T1_BLEND_STEM_SNAP_HEIGHTS T1_BLEND_STEM_SNAP_WIDTHS T1_BLEND_UNDERLINE_POSITION T1_BLEND_UNDERLINE_THICKNESS T1_ENCODING_TYPE_ARRAY T1_ENCODING_TYPE_EXPERT T1_ENCODING_TYPE_ISOLATIN1 T1_ENCODING_TYPE_NONE T1_ENCODING_TYPE_STANDARD T1_EncodingType T1_FontInfo T1_Private TT_ADOBE_ID_CUSTOM TT_ADOBE_ID_EXPERT TT_ADOBE_ID_LATIN_1 TT_ADOBE_ID_STANDARD TT_ADOBE_ID_XXX TT_APPLE_ID_DEFAULT TT_APPLE_ID_FULL_UNICODE TT_APPLE_ID_ISO_10646 TT_APPLE_ID_UNICODE_1_1 TT_APPLE_ID_UNICODE_2_0 TT_APPLE_ID_UNICODE_32 TT_APPLE_ID_VARIANT_SELECTOR TT_APPLE_ID_XXX TT_Header TT_HoriHeader TT_INTERPRETER_VERSION_35 TT_INTERPRETER_VERSION_38 TT_INTERPRETER_VERSION_40 TT_INTERPRETER_VERSION_XXX TT_ISO_ID_10646 TT_ISO_ID_7BIT_ASCII TT_ISO_ID_8859_1 TT_ISO_ID_XXX TT_MAC_ID_XXX TT_MAC_LANGID_XXX TT_MaxProfile TT_MS_ID_BIG_5 TT_MS_ID_JOHAB TT_MS_ID_PRC TT_MS_ID_SJIS TT_MS_ID_SYMBOL_CS TT_MS_ID_UCS_4 TT_MS_ID_UNICODE_CS TT_MS_ID_WANSUNG TT_MS_ID_XXX TT_MS_LANGID_XXX TT_NAME_ID_XXX TT_OS2 TT_PCLT TT_PLATFORM_ADOBE TT_PLATFORM_APPLE_UNICODE TT_PLATFORM_CUSTOM TT_PLATFORM_ISO TT_PLATFORM_MACINTOSH TT_PLATFORM_MICROSOFT TT_PLATFORM_XXX TT_Postscript TT_UCR_XXX TT_VertHeader","title":"T"},{"location":"ft2-index.html#w","text":"warping generated on Tue Oct 20 05:14:52 2020 UTC","title":"W"},{"location":"ft2-layer_management.html","text":"FreeType \u00bb Docs \u00bb Core API \u00bb Glyph Layer Management Glyph Layer Management \u00b6 Synopsis \u00b6 The functions described here allow access of colored glyph layer data in OpenType's \u2018COLR\u2019 tables. FT_LayerIterator \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_LayerIterator_ { FT_UInt num_layers; FT_UInt layer; FT_Byte * p; } FT_LayerIterator ; This iterator object is needed for FT_Get_Color_Glyph_Layer . fields num_layers The number of glyph layers for the requested glyph index. Will be set by FT_Get_Color_Glyph_Layer . layer The current layer. Will be set by FT_Get_Color_Glyph_Layer . p An opaque pointer into \u2018COLR\u2019 table data. The caller must set this to NULL before the first call of FT_Get_Color_Glyph_Layer . FT_Get_Color_Glyph_Layer \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Bool ) FT_Get_Color_Glyph_Layer ( FT_Face face, FT_UInt base_glyph, FT_UInt *aglyph_index, FT_UInt *acolor_index, FT_LayerIterator * iterator ); This is an interface to the \u2018COLR\u2019 table in OpenType fonts to iteratively retrieve the colored glyph layers associated with the current glyph slot. https://docs.microsoft.com/en-us/typography/opentype/spec/colr The glyph layer data for a given glyph index, if present, provides an alternative, multi-color glyph representation: Instead of rendering the outline or bitmap with the given glyph index, glyphs with the indices and colors returned by this function are rendered layer by layer. The returned elements are ordered in the z direction from bottom to top; the 'n'th element should be rendered with the associated palette color and blended on top of the already rendered layers (elements 0, 1, ..., n-1). input face A handle to the parent face object. base_glyph The glyph index the colored glyph layers are associated with. inout iterator An FT_LayerIterator object. For the first call you should set iterator->p to NULL . For all following calls, simply use the same object again. output aglyph_index The glyph index of the current layer. acolor_index The color index into the font face's color palette of the current layer. The value 0xFFFF is special; it doesn't reference a palette entry but indicates that the text foreground color should be used instead (to be set up by the application outside of FreeType). The color palette can be retrieved with FT_Palette_Select . return Value 1 if everything is OK. If there are no more layers (or if there are no layers at all), value 0 gets returned. In case of an error, value 0 is returned also. note This function is necessary if you want to handle glyph layers by yourself. In particular, functions that operate with FT_GlyphRec objects (like FT_Get_Glyph or FT_Glyph_To_Bitmap ) don't have access to this information. Note that FT_Render_Glyph is able to handle colored glyph layers automatically if the FT_LOAD_COLOR flag is passed to a previous call to FT_Load_Glyph . [This is an experimental feature.] example FT_Color* palette; FT_LayerIterator iterator; FT_Bool have_layers; FT_UInt layer_glyph_index; FT_UInt layer_color_index; error = FT_Palette_Select( face, palette_index, &palette ); if ( error ) palette = NULL; iterator.p = NULL; have_layers = FT_Get_Color_Glyph_Layer( face, glyph_index, &layer_glyph_index, &layer_color_index, &iterator ); if ( palette && have_layers ) { do { FT_Color layer_color; if ( layer_color_index == 0xFFFF ) layer_color = text_foreground_color; else layer_color = palette[layer_color_index]; // Load and render glyph `layer_glyph_index', then // blend resulting pixmap (using color `layer_color') // with previously created pixmaps. } while ( FT_Get_Color_Glyph_Layer( face, glyph_index, &layer_glyph_index, &layer_color_index, &iterator ) ); }","title":"Glyph Layer Management"},{"location":"ft2-layer_management.html#glyph-layer-management","text":"","title":"Glyph Layer Management"},{"location":"ft2-layer_management.html#synopsis","text":"The functions described here allow access of colored glyph layer data in OpenType's \u2018COLR\u2019 tables.","title":"Synopsis"},{"location":"ft2-layer_management.html#ft_layeriterator","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_LayerIterator_ { FT_UInt num_layers; FT_UInt layer; FT_Byte * p; } FT_LayerIterator ; This iterator object is needed for FT_Get_Color_Glyph_Layer .","title":"FT_LayerIterator"},{"location":"ft2-layer_management.html#ft_get_color_glyph_layer","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Bool ) FT_Get_Color_Glyph_Layer ( FT_Face face, FT_UInt base_glyph, FT_UInt *aglyph_index, FT_UInt *acolor_index, FT_LayerIterator * iterator ); This is an interface to the \u2018COLR\u2019 table in OpenType fonts to iteratively retrieve the colored glyph layers associated with the current glyph slot. https://docs.microsoft.com/en-us/typography/opentype/spec/colr The glyph layer data for a given glyph index, if present, provides an alternative, multi-color glyph representation: Instead of rendering the outline or bitmap with the given glyph index, glyphs with the indices and colors returned by this function are rendered layer by layer. The returned elements are ordered in the z direction from bottom to top; the 'n'th element should be rendered with the associated palette color and blended on top of the already rendered layers (elements 0, 1, ..., n-1).","title":"FT_Get_Color_Glyph_Layer"},{"location":"ft2-lcd_rendering.html","text":"FreeType \u00bb Docs \u00bb Controlling FreeType Modules \u00bb Subpixel Rendering Subpixel Rendering \u00b6 Synopsis \u00b6 FreeType provides two alternative subpixel rendering technologies. Should you define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your ftoption.h file, this enables ClearType-style rendering. Otherwise, Harmony LCD rendering is enabled. These technologies are controlled differently and API described below, although always available, performs its function when appropriate method is enabled and does nothing otherwise. ClearType-style LCD rendering exploits the color-striped structure of LCD pixels, increasing the available resolution in the direction of the stripe (usually horizontal RGB) by a factor of 3. Using the subpixels coverages unfiltered can create severe color fringes especially when rendering thin features. Indeed, to produce black-on-white text, the nearby color subpixels must be dimmed equally. A good 5-tap FIR filter should be applied to subpixel coverages regardless of pixel boundaries and should have these properties: It should be symmetrical, like { a, b, c, b, a }, to avoid any shifts in appearance. It should be color-balanced, meaning a + b = c, to reduce color fringes by distributing the computed coverage for one subpixel to all subpixels equally. It should be normalized, meaning 2a + 2b + c = 1.0 to maintain overall brightness. Boxy 3-tap filter {0, \u2153, \u2153, \u2153, 0} is sharper but is less forgiving of non-ideal gamma curves of a screen (and viewing angles), beveled filters are fuzzier but more tolerant. Use the FT_Library_SetLcdFilter or FT_Library_SetLcdFilterWeights API to specify a low-pass filter, which is then applied to subpixel-rendered bitmaps generated through FT_Render_Glyph . Harmony LCD rendering is suitable to panels with any regular subpixel structure, not just monitors with 3 color striped subpixels, as long as the color subpixels have fixed positions relative to the pixel center. In this case, each color channel is then rendered separately after shifting the outline opposite to the subpixel shift so that the coverage maps are aligned. This method is immune to color fringes because the shifts do not change integral coverage. The subpixel geometry must be specified by xy-coordinates for each subpixel. By convention they may come in the RGB order: {{-\u2153, 0}, {0, 0}, {\u2153, 0}} for standard RGB striped panel or {{-\u2159, \u00bc}, {-\u2159, -\u00bc}, {\u2153, 0}} for a certain PenTile panel. Use the FT_Library_SetLcdGeometry API to specify subpixel positions. If one follows the RGB order convention, the same order applies to the resulting FT_PIXEL_MODE_LCD and FT_PIXEL_MODE_LCD_V bitmaps. Note, however, that the coordinate frame for the latter must be rotated clockwise. Harmony with default LCD geometry is equivalent to ClearType with light filter. As a result of ClearType filtering or Harmony rendering, the dimensions of LCD bitmaps can be either wider or taller than the dimensions of the corresponding outline with regard to the pixel grid. For example, for FT_RENDER_MODE_LCD , the filter adds 2 subpixels to the left, and 2 subpixels to the right. The bitmap offset values are adjusted accordingly, so clients shouldn't need to modify their layout and glyph positioning code when enabling the filter. The ClearType and Harmony rendering is applicable to glyph bitmaps rendered through FT_Render_Glyph , FT_Load_Glyph , FT_Load_Char , and FT_Glyph_To_Bitmap , when FT_RENDER_MODE_LCD or FT_RENDER_MODE_LCD_V is specified. This API does not control FT_Outline_Render and FT_Outline_Get_Bitmap . The described algorithms can completely remove color artefacts when combined with gamma-corrected alpha blending in linear space. Each of the 3 alpha values (subpixels) must by independently used to blend one color channel. That is, red alpha blends the red channel of the text color with the red channel of the background pixel. FT_LcdFilter \u00b6 Defined in FT_LCD_FILTER_H (freetype/ftlcdfil.h). typedef enum FT_LcdFilter_ { FT_LCD_FILTER_NONE = 0, FT_LCD_FILTER_DEFAULT = 1, FT_LCD_FILTER_LIGHT = 2, FT_LCD_FILTER_LEGACY1 = 3, FT_LCD_FILTER_LEGACY = 16, FT_LCD_FILTER_MAX /* do not remove */ } FT_LcdFilter ; A list of values to identify various types of LCD filters. values FT_LCD_FILTER_NONE Do not perform filtering. When used with subpixel rendering, this results in sometimes severe color fringes. FT_LCD_FILTER_DEFAULT This is a beveled, normalized, and color-balanced five-tap filter with weights of [0x08 0x4D 0x56 0x4D 0x08] in 1/256th units. FT_LCD_FILTER_LIGHT this is a boxy, normalized, and color-balanced three-tap filter with weights of [0x00 0x55 0x56 0x55 0x00] in 1/256th units. FT_LCD_FILTER_LEGACY FT_LCD_FILTER_LEGACY1 This filter corresponds to the original libXft color filter. It provides high contrast output but can exhibit really bad color fringes if glyphs are not extremely well hinted to the pixel grid. This filter is only provided for comparison purposes, and might be disabled or stay unsupported in the future. The second value is provided for compatibility with FontConfig, which historically used different enumeration, sometimes incorrectly forwarded to FreeType. since 2.3.0 ( FT_LCD_FILTER_LEGACY1 since 2.6.2) FT_Library_SetLcdFilter \u00b6 Defined in FT_LCD_FILTER_H (freetype/ftlcdfil.h). FT_EXPORT( FT_Error ) FT_Library_SetLcdFilter ( FT_Library library, FT_LcdFilter filter ); This function is used to change filter applied to LCD decimated bitmaps, like the ones used when calling FT_Render_Glyph with FT_RENDER_MODE_LCD or FT_RENDER_MODE_LCD_V . input library A handle to the target library instance. filter The filter type. You can use FT_LCD_FILTER_NONE here to disable this feature, or FT_LCD_FILTER_DEFAULT to use a default filter that should work well on most LCD screens. return FreeType error code. 0 means success. note Since 2.10.3 the LCD filtering is enabled with FT_LCD_FILTER_DEFAULT . It is no longer necessary to call this function explicitly except to choose a different filter or disable filtering altogether with FT_LCD_FILTER_NONE . This function does nothing but returns FT_Err_Unimplemented_Feature if the configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not defined in your build of the library. since 2.3.0 FT_Library_SetLcdFilterWeights \u00b6 Defined in FT_LCD_FILTER_H (freetype/ftlcdfil.h). FT_EXPORT( FT_Error ) FT_Library_SetLcdFilterWeights ( FT_Library library, unsigned char *weights ); This function can be used to enable LCD filter with custom weights, instead of using presets in FT_Library_SetLcdFilter . input library A handle to the target library instance. weights A pointer to an array; the function copies the first five bytes and uses them to specify the filter weights in 1/256th units. return FreeType error code. 0 means success. note This function does nothing but returns FT_Err_Unimplemented_Feature if the configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not defined in your build of the library. LCD filter weights can also be set per face using FT_Face_Properties with FT_PARAM_TAG_LCD_FILTER_WEIGHTS . since 2.4.0 FT_LcdFiveTapFilter \u00b6 Defined in FT_LCD_FILTER_H (freetype/ftlcdfil.h). # define FT_LCD_FILTER_FIVE_TAPS 5 typedef FT_Byte FT_LcdFiveTapFilter [FT_LCD_FILTER_FIVE_TAPS]; A typedef for passing the five LCD filter weights to FT_Face_Properties within an FT_Parameter structure. since 2.8 FT_Library_SetLcdGeometry \u00b6 Defined in FT_LCD_FILTER_H (freetype/ftlcdfil.h). FT_EXPORT( FT_Error ) FT_Library_SetLcdGeometry ( FT_Library library, FT_Vector sub[3] ); This function can be used to modify default positions of color subpixels, which controls Harmony LCD rendering. input library A handle to the target library instance. sub A pointer to an array of 3 vectors in 26.6 fractional pixel format; the function modifies the default values, see the note below. return FreeType error code. 0 means success. note Subpixel geometry examples: {{-21, 0}, {0, 0}, {21, 0}} is the default, corresponding to 3 color stripes shifted by a third of a pixel. This could be an RGB panel. {{21, 0}, {0, 0}, {-21, 0}} looks the same as the default but can specify a BGR panel instead, while keeping the bitmap in the same RGB888 format. {{0, 21}, {0, 0}, {0, -21}} is the vertical RGB, but the bitmap stays RGB888 as a result. {{-11, 16}, {-11, -16}, {22, 0}} is a certain PenTile arrangement. This function does nothing and returns FT_Err_Unimplemented_Feature in the context of ClearType-style subpixel rendering when FT_CONFIG_OPTION_SUBPIXEL_RENDERING is defined in your build of the library. since 2.10.0","title":"Subpixel Rendering"},{"location":"ft2-lcd_rendering.html#subpixel-rendering","text":"","title":"Subpixel Rendering"},{"location":"ft2-lcd_rendering.html#synopsis","text":"FreeType provides two alternative subpixel rendering technologies. Should you define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your ftoption.h file, this enables ClearType-style rendering. Otherwise, Harmony LCD rendering is enabled. These technologies are controlled differently and API described below, although always available, performs its function when appropriate method is enabled and does nothing otherwise. ClearType-style LCD rendering exploits the color-striped structure of LCD pixels, increasing the available resolution in the direction of the stripe (usually horizontal RGB) by a factor of 3. Using the subpixels coverages unfiltered can create severe color fringes especially when rendering thin features. Indeed, to produce black-on-white text, the nearby color subpixels must be dimmed equally. A good 5-tap FIR filter should be applied to subpixel coverages regardless of pixel boundaries and should have these properties: It should be symmetrical, like { a, b, c, b, a }, to avoid any shifts in appearance. It should be color-balanced, meaning a + b = c, to reduce color fringes by distributing the computed coverage for one subpixel to all subpixels equally. It should be normalized, meaning 2a + 2b + c = 1.0 to maintain overall brightness. Boxy 3-tap filter {0, \u2153, \u2153, \u2153, 0} is sharper but is less forgiving of non-ideal gamma curves of a screen (and viewing angles), beveled filters are fuzzier but more tolerant. Use the FT_Library_SetLcdFilter or FT_Library_SetLcdFilterWeights API to specify a low-pass filter, which is then applied to subpixel-rendered bitmaps generated through FT_Render_Glyph . Harmony LCD rendering is suitable to panels with any regular subpixel structure, not just monitors with 3 color striped subpixels, as long as the color subpixels have fixed positions relative to the pixel center. In this case, each color channel is then rendered separately after shifting the outline opposite to the subpixel shift so that the coverage maps are aligned. This method is immune to color fringes because the shifts do not change integral coverage. The subpixel geometry must be specified by xy-coordinates for each subpixel. By convention they may come in the RGB order: {{-\u2153, 0}, {0, 0}, {\u2153, 0}} for standard RGB striped panel or {{-\u2159, \u00bc}, {-\u2159, -\u00bc}, {\u2153, 0}} for a certain PenTile panel. Use the FT_Library_SetLcdGeometry API to specify subpixel positions. If one follows the RGB order convention, the same order applies to the resulting FT_PIXEL_MODE_LCD and FT_PIXEL_MODE_LCD_V bitmaps. Note, however, that the coordinate frame for the latter must be rotated clockwise. Harmony with default LCD geometry is equivalent to ClearType with light filter. As a result of ClearType filtering or Harmony rendering, the dimensions of LCD bitmaps can be either wider or taller than the dimensions of the corresponding outline with regard to the pixel grid. For example, for FT_RENDER_MODE_LCD , the filter adds 2 subpixels to the left, and 2 subpixels to the right. The bitmap offset values are adjusted accordingly, so clients shouldn't need to modify their layout and glyph positioning code when enabling the filter. The ClearType and Harmony rendering is applicable to glyph bitmaps rendered through FT_Render_Glyph , FT_Load_Glyph , FT_Load_Char , and FT_Glyph_To_Bitmap , when FT_RENDER_MODE_LCD or FT_RENDER_MODE_LCD_V is specified. This API does not control FT_Outline_Render and FT_Outline_Get_Bitmap . The described algorithms can completely remove color artefacts when combined with gamma-corrected alpha blending in linear space. Each of the 3 alpha values (subpixels) must by independently used to blend one color channel. That is, red alpha blends the red channel of the text color with the red channel of the background pixel.","title":"Synopsis"},{"location":"ft2-lcd_rendering.html#ft_lcdfilter","text":"Defined in FT_LCD_FILTER_H (freetype/ftlcdfil.h). typedef enum FT_LcdFilter_ { FT_LCD_FILTER_NONE = 0, FT_LCD_FILTER_DEFAULT = 1, FT_LCD_FILTER_LIGHT = 2, FT_LCD_FILTER_LEGACY1 = 3, FT_LCD_FILTER_LEGACY = 16, FT_LCD_FILTER_MAX /* do not remove */ } FT_LcdFilter ; A list of values to identify various types of LCD filters.","title":"FT_LcdFilter"},{"location":"ft2-lcd_rendering.html#ft_library_setlcdfilter","text":"Defined in FT_LCD_FILTER_H (freetype/ftlcdfil.h). FT_EXPORT( FT_Error ) FT_Library_SetLcdFilter ( FT_Library library, FT_LcdFilter filter ); This function is used to change filter applied to LCD decimated bitmaps, like the ones used when calling FT_Render_Glyph with FT_RENDER_MODE_LCD or FT_RENDER_MODE_LCD_V .","title":"FT_Library_SetLcdFilter"},{"location":"ft2-lcd_rendering.html#ft_library_setlcdfilterweights","text":"Defined in FT_LCD_FILTER_H (freetype/ftlcdfil.h). FT_EXPORT( FT_Error ) FT_Library_SetLcdFilterWeights ( FT_Library library, unsigned char *weights ); This function can be used to enable LCD filter with custom weights, instead of using presets in FT_Library_SetLcdFilter .","title":"FT_Library_SetLcdFilterWeights"},{"location":"ft2-lcd_rendering.html#ft_lcdfivetapfilter","text":"Defined in FT_LCD_FILTER_H (freetype/ftlcdfil.h). # define FT_LCD_FILTER_FIVE_TAPS 5 typedef FT_Byte FT_LcdFiveTapFilter [FT_LCD_FILTER_FIVE_TAPS]; A typedef for passing the five LCD filter weights to FT_Face_Properties within an FT_Parameter structure.","title":"FT_LcdFiveTapFilter"},{"location":"ft2-lcd_rendering.html#ft_library_setlcdgeometry","text":"Defined in FT_LCD_FILTER_H (freetype/ftlcdfil.h). FT_EXPORT( FT_Error ) FT_Library_SetLcdGeometry ( FT_Library library, FT_Vector sub[3] ); This function can be used to modify default positions of color subpixels, which controls Harmony LCD rendering.","title":"FT_Library_SetLcdGeometry"},{"location":"ft2-list_processing.html","text":"FreeType \u00bb Docs \u00bb Support API \u00bb List Processing List Processing \u00b6 Synopsis \u00b6 This section contains various definitions related to list processing using doubly-linked nodes. FT_List \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_ListRec_* FT_List ; A handle to a list record (see FT_ListRec ). FT_ListNode \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_ListNodeRec_* FT_ListNode ; Many elements and objects in FreeType are listed through an FT_List record (see FT_ListRec ). As its name suggests, an FT_ListNode is a handle to a single list element. FT_ListRec \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_ListRec_ { FT_ListNode head; FT_ListNode tail; } FT_ListRec ; A structure used to hold a simple doubly-linked list. These are used in many parts of FreeType. fields head The head (first element) of doubly-linked list. tail The tail (last element) of doubly-linked list. FT_ListNodeRec \u00b6 Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_ListNodeRec_ { FT_ListNode prev; FT_ListNode next; void * data; } FT_ListNodeRec ; A structure used to hold a single list element. fields prev The previous element in the list. NULL if first. next The next element in the list. NULL if last. data A typeless pointer to the listed object. FT_List_Add \u00b6 Defined in FT_LIST_H (freetype/ftlist.h). FT_EXPORT( void ) FT_List_Add ( FT_List list, FT_ListNode node ); Append an element to the end of a list. inout list A pointer to the parent list. node The node to append. FT_List_Insert \u00b6 Defined in FT_LIST_H (freetype/ftlist.h). FT_EXPORT( void ) FT_List_Insert ( FT_List list, FT_ListNode node ); Insert an element at the head of a list. inout list A pointer to parent list. node The node to insert. FT_List_Find \u00b6 Defined in FT_LIST_H (freetype/ftlist.h). FT_EXPORT( FT_ListNode ) FT_List_Find ( FT_List list, void * data ); Find the list node for a given listed object. input list A pointer to the parent list. data The address of the listed object. return List node. NULL if it wasn't found. FT_List_Remove \u00b6 Defined in FT_LIST_H (freetype/ftlist.h). FT_EXPORT( void ) FT_List_Remove ( FT_List list, FT_ListNode node ); Remove a node from a list. This function doesn't check whether the node is in the list! input node The node to remove. inout list A pointer to the parent list. FT_List_Up \u00b6 Defined in FT_LIST_H (freetype/ftlist.h). FT_EXPORT( void ) FT_List_Up ( FT_List list, FT_ListNode node ); Move a node to the head/top of a list. Used to maintain LRU lists. inout list A pointer to the parent list. node The node to move. FT_List_Iterate \u00b6 Defined in FT_LIST_H (freetype/ftlist.h). FT_EXPORT( FT_Error ) FT_List_Iterate ( FT_List list, FT_List_Iterator iterator, void * user ); Parse a list and calls a given iterator function on each element. Note that parsing is stopped as soon as one of the iterator calls returns a non-zero value. input list A handle to the list. iterator An iterator function, called on each node of the list. user A user-supplied field that is passed as the second argument to the iterator. return The result (a FreeType error code) of the last iterator call. FT_List_Iterator \u00b6 Defined in FT_LIST_H (freetype/ftlist.h). typedef FT_Error (* FT_List_Iterator )( FT_ListNode node, void * user ); An FT_List iterator function that is called during a list parse by FT_List_Iterate . input node The current iteration list node. user A typeless pointer passed to FT_List_Iterate . Can be used to point to the iteration's state. FT_List_Finalize \u00b6 Defined in FT_LIST_H (freetype/ftlist.h). FT_EXPORT( void ) FT_List_Finalize ( FT_List list, FT_List_Destructor destroy, FT_Memory memory, void * user ); Destroy all elements in the list as well as the list itself. input list A handle to the list. destroy A list destructor that will be applied to each element of the list. Set this to NULL if not needed. memory The current memory object that handles deallocation. user A user-supplied field that is passed as the last argument to the destructor. note This function expects that all nodes added by FT_List_Add or FT_List_Insert have been dynamically allocated. FT_List_Destructor \u00b6 Defined in FT_LIST_H (freetype/ftlist.h). typedef void (* FT_List_Destructor )( FT_Memory memory, void * data, void * user ); An FT_List iterator function that is called during a list finalization by FT_List_Finalize to destroy all elements in a given list. input system The current system object. data The current object to destroy. user A typeless pointer passed to FT_List_Iterate . It can be used to point to the iteration's state.","title":"List Processing"},{"location":"ft2-list_processing.html#list-processing","text":"","title":"List Processing"},{"location":"ft2-list_processing.html#synopsis","text":"This section contains various definitions related to list processing using doubly-linked nodes.","title":"Synopsis"},{"location":"ft2-list_processing.html#ft_list","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_ListRec_* FT_List ; A handle to a list record (see FT_ListRec ).","title":"FT_List"},{"location":"ft2-list_processing.html#ft_listnode","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_ListNodeRec_* FT_ListNode ; Many elements and objects in FreeType are listed through an FT_List record (see FT_ListRec ). As its name suggests, an FT_ListNode is a handle to a single list element.","title":"FT_ListNode"},{"location":"ft2-list_processing.html#ft_listrec","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_ListRec_ { FT_ListNode head; FT_ListNode tail; } FT_ListRec ; A structure used to hold a simple doubly-linked list. These are used in many parts of FreeType.","title":"FT_ListRec"},{"location":"ft2-list_processing.html#ft_listnoderec","text":"Defined in FT_TYPES_H (freetype/fttypes.h). typedef struct FT_ListNodeRec_ { FT_ListNode prev; FT_ListNode next; void * data; } FT_ListNodeRec ; A structure used to hold a single list element.","title":"FT_ListNodeRec"},{"location":"ft2-list_processing.html#ft_list_add","text":"Defined in FT_LIST_H (freetype/ftlist.h). FT_EXPORT( void ) FT_List_Add ( FT_List list, FT_ListNode node ); Append an element to the end of a list.","title":"FT_List_Add"},{"location":"ft2-list_processing.html#ft_list_insert","text":"Defined in FT_LIST_H (freetype/ftlist.h). FT_EXPORT( void ) FT_List_Insert ( FT_List list, FT_ListNode node ); Insert an element at the head of a list.","title":"FT_List_Insert"},{"location":"ft2-list_processing.html#ft_list_find","text":"Defined in FT_LIST_H (freetype/ftlist.h). FT_EXPORT( FT_ListNode ) FT_List_Find ( FT_List list, void * data ); Find the list node for a given listed object.","title":"FT_List_Find"},{"location":"ft2-list_processing.html#ft_list_remove","text":"Defined in FT_LIST_H (freetype/ftlist.h). FT_EXPORT( void ) FT_List_Remove ( FT_List list, FT_ListNode node ); Remove a node from a list. This function doesn't check whether the node is in the list!","title":"FT_List_Remove"},{"location":"ft2-list_processing.html#ft_list_up","text":"Defined in FT_LIST_H (freetype/ftlist.h). FT_EXPORT( void ) FT_List_Up ( FT_List list, FT_ListNode node ); Move a node to the head/top of a list. Used to maintain LRU lists.","title":"FT_List_Up"},{"location":"ft2-list_processing.html#ft_list_iterate","text":"Defined in FT_LIST_H (freetype/ftlist.h). FT_EXPORT( FT_Error ) FT_List_Iterate ( FT_List list, FT_List_Iterator iterator, void * user ); Parse a list and calls a given iterator function on each element. Note that parsing is stopped as soon as one of the iterator calls returns a non-zero value.","title":"FT_List_Iterate"},{"location":"ft2-list_processing.html#ft_list_iterator","text":"Defined in FT_LIST_H (freetype/ftlist.h). typedef FT_Error (* FT_List_Iterator )( FT_ListNode node, void * user ); An FT_List iterator function that is called during a list parse by FT_List_Iterate .","title":"FT_List_Iterator"},{"location":"ft2-list_processing.html#ft_list_finalize","text":"Defined in FT_LIST_H (freetype/ftlist.h). FT_EXPORT( void ) FT_List_Finalize ( FT_List list, FT_List_Destructor destroy, FT_Memory memory, void * user ); Destroy all elements in the list as well as the list itself.","title":"FT_List_Finalize"},{"location":"ft2-list_processing.html#ft_list_destructor","text":"Defined in FT_LIST_H (freetype/ftlist.h). typedef void (* FT_List_Destructor )( FT_Memory memory, void * data, void * user ); An FT_List iterator function that is called during a list finalization by FT_List_Finalize to destroy all elements in a given list.","title":"FT_List_Destructor"},{"location":"ft2-lzw.html","text":"FreeType \u00bb Docs \u00bb Support API \u00bb LZW Streams LZW Streams \u00b6 Synopsis \u00b6 In certain builds of the library, LZW compression recognition is automatically handled when calling FT_New_Face or FT_Open_Face . This means that if no font driver is capable of handling the raw compressed file, the library will try to open a LZW stream from it and re-open the face with it. The stream implementation is very basic and resets the decompression process each time seeking backwards is needed within the stream, which significantly undermines the performance. This section contains the declaration of LZW-specific functions. FT_Stream_OpenLZW \u00b6 Defined in FT_LZW_H (freetype/ftlzw.h). FT_EXPORT( FT_Error ) FT_Stream_OpenLZW ( FT_Stream stream, FT_Stream source ); Open a new stream to parse LZW-compressed font files. This is mainly used to support the compressed *.pcf.Z fonts that come with XFree86. input stream The target embedding stream. source The source stream. return FreeType error code. 0 means success. note The source stream must be opened before calling this function. Calling the internal function FT_Stream_Close on the new stream will not call FT_Stream_Close on the source stream. None of the stream objects will be released to the heap. This function may return FT_Err_Unimplemented_Feature if your build of FreeType was not compiled with LZW support.","title":"LZW Streams"},{"location":"ft2-lzw.html#lzw-streams","text":"","title":"LZW Streams"},{"location":"ft2-lzw.html#synopsis","text":"In certain builds of the library, LZW compression recognition is automatically handled when calling FT_New_Face or FT_Open_Face . This means that if no font driver is capable of handling the raw compressed file, the library will try to open a LZW stream from it and re-open the face with it. The stream implementation is very basic and resets the decompression process each time seeking backwards is needed within the stream, which significantly undermines the performance. This section contains the declaration of LZW-specific functions.","title":"Synopsis"},{"location":"ft2-lzw.html#ft_stream_openlzw","text":"Defined in FT_LZW_H (freetype/ftlzw.h). FT_EXPORT( FT_Error ) FT_Stream_OpenLZW ( FT_Stream stream, FT_Stream source ); Open a new stream to parse LZW-compressed font files. This is mainly used to support the compressed *.pcf.Z fonts that come with XFree86.","title":"FT_Stream_OpenLZW"},{"location":"ft2-mac_specific.html","text":"FreeType \u00bb Docs \u00bb Core API \u00bb Mac Specific Interface Mac Specific Interface \u00b6 Synopsis \u00b6 The following definitions are only available if FreeType is compiled on a Macintosh. FT_New_Face_From_FOND \u00b6 Defined in FT_MAC_H (freetype/ftmac.h). FT_EXPORT( FT_Error ) FT_New_Face_From_FOND ( FT_Library library, Handle fond, FT_Long face_index, FT_Face *aface ) FT_DEPRECATED_ATTRIBUTE; Create a new face object from a FOND resource. inout library A handle to the library resource. input fond A FOND resource. face_index Only supported for the -1 \u2018sanity check\u2019 special case. output aface A handle to a new face object. return FreeType error code. 0 means success. example This function can be used to create FT_Face objects from fonts that are installed in the system as follows. fond = GetResource( 'FOND', fontName ); error = FT_New_Face_From_FOND( library, fond, 0, &face ); FT_GetFile_From_Mac_Name \u00b6 Defined in FT_MAC_H (freetype/ftmac.h). FT_EXPORT( FT_Error ) FT_GetFile_From_Mac_Name ( const char * fontName, FSSpec* pathSpec, FT_Long * face_index ) FT_DEPRECATED_ATTRIBUTE; Return an FSSpec for the disk file containing the named font. input fontName Mac OS name of the font (e.g., Times New Roman Bold). output pathSpec FSSpec to the file. For passing to FT_New_Face_From_FSSpec . face_index Index of the face. For passing to FT_New_Face_From_FSSpec . return FreeType error code. 0 means success. FT_GetFile_From_Mac_ATS_Name \u00b6 Defined in FT_MAC_H (freetype/ftmac.h). FT_EXPORT( FT_Error ) FT_GetFile_From_Mac_ATS_Name ( const char * fontName, FSSpec* pathSpec, FT_Long * face_index ) FT_DEPRECATED_ATTRIBUTE; Return an FSSpec for the disk file containing the named font. input fontName Mac OS name of the font in ATS framework. output pathSpec FSSpec to the file. For passing to FT_New_Face_From_FSSpec . face_index Index of the face. For passing to FT_New_Face_From_FSSpec . return FreeType error code. 0 means success. FT_GetFilePath_From_Mac_ATS_Name \u00b6 Defined in FT_MAC_H (freetype/ftmac.h). FT_EXPORT( FT_Error ) FT_GetFilePath_From_Mac_ATS_Name ( const char * fontName, UInt8* path, UInt32 maxPathSize, FT_Long * face_index ) FT_DEPRECATED_ATTRIBUTE; Return a pathname of the disk file and face index for given font name that is handled by ATS framework. input fontName Mac OS name of the font in ATS framework. output path Buffer to store pathname of the file. For passing to FT_New_Face . The client must allocate this buffer before calling this function. maxPathSize Lengths of the buffer path that client allocated. face_index Index of the face. For passing to FT_New_Face . return FreeType error code. 0 means success. FT_New_Face_From_FSSpec \u00b6 Defined in FT_MAC_H (freetype/ftmac.h). FT_EXPORT( FT_Error ) FT_New_Face_From_FSSpec ( FT_Library library, const FSSpec *spec, FT_Long face_index, FT_Face *aface ) FT_DEPRECATED_ATTRIBUTE; Create a new face object from a given resource and typeface index using an FSSpec to the font file. inout library A handle to the library resource. input spec FSSpec to the font file. face_index The index of the face within the resource. The first face has index 0. output aface A handle to a new face object. return FreeType error code. 0 means success. note FT_New_Face_From_FSSpec is identical to FT_New_Face except it accepts an FSSpec instead of a path. FT_New_Face_From_FSRef \u00b6 Defined in FT_MAC_H (freetype/ftmac.h). FT_EXPORT( FT_Error ) FT_New_Face_From_FSRef ( FT_Library library, const FSRef *ref, FT_Long face_index, FT_Face *aface ) FT_DEPRECATED_ATTRIBUTE; Create a new face object from a given resource and typeface index using an FSRef to the font file. inout library A handle to the library resource. input spec FSRef to the font file. face_index The index of the face within the resource. The first face has index 0. output aface A handle to a new face object. return FreeType error code. 0 means success. note FT_New_Face_From_FSRef is identical to FT_New_Face except it accepts an FSRef instead of a path.","title":"Mac Specific Interface"},{"location":"ft2-mac_specific.html#mac-specific-interface","text":"","title":"Mac Specific Interface"},{"location":"ft2-mac_specific.html#synopsis","text":"The following definitions are only available if FreeType is compiled on a Macintosh.","title":"Synopsis"},{"location":"ft2-mac_specific.html#ft_new_face_from_fond","text":"Defined in FT_MAC_H (freetype/ftmac.h). FT_EXPORT( FT_Error ) FT_New_Face_From_FOND ( FT_Library library, Handle fond, FT_Long face_index, FT_Face *aface ) FT_DEPRECATED_ATTRIBUTE; Create a new face object from a FOND resource.","title":"FT_New_Face_From_FOND"},{"location":"ft2-mac_specific.html#ft_getfile_from_mac_name","text":"Defined in FT_MAC_H (freetype/ftmac.h). FT_EXPORT( FT_Error ) FT_GetFile_From_Mac_Name ( const char * fontName, FSSpec* pathSpec, FT_Long * face_index ) FT_DEPRECATED_ATTRIBUTE; Return an FSSpec for the disk file containing the named font.","title":"FT_GetFile_From_Mac_Name"},{"location":"ft2-mac_specific.html#ft_getfile_from_mac_ats_name","text":"Defined in FT_MAC_H (freetype/ftmac.h). FT_EXPORT( FT_Error ) FT_GetFile_From_Mac_ATS_Name ( const char * fontName, FSSpec* pathSpec, FT_Long * face_index ) FT_DEPRECATED_ATTRIBUTE; Return an FSSpec for the disk file containing the named font.","title":"FT_GetFile_From_Mac_ATS_Name"},{"location":"ft2-mac_specific.html#ft_getfilepath_from_mac_ats_name","text":"Defined in FT_MAC_H (freetype/ftmac.h). FT_EXPORT( FT_Error ) FT_GetFilePath_From_Mac_ATS_Name ( const char * fontName, UInt8* path, UInt32 maxPathSize, FT_Long * face_index ) FT_DEPRECATED_ATTRIBUTE; Return a pathname of the disk file and face index for given font name that is handled by ATS framework.","title":"FT_GetFilePath_From_Mac_ATS_Name"},{"location":"ft2-mac_specific.html#ft_new_face_from_fsspec","text":"Defined in FT_MAC_H (freetype/ftmac.h). FT_EXPORT( FT_Error ) FT_New_Face_From_FSSpec ( FT_Library library, const FSSpec *spec, FT_Long face_index, FT_Face *aface ) FT_DEPRECATED_ATTRIBUTE; Create a new face object from a given resource and typeface index using an FSSpec to the font file.","title":"FT_New_Face_From_FSSpec"},{"location":"ft2-mac_specific.html#ft_new_face_from_fsref","text":"Defined in FT_MAC_H (freetype/ftmac.h). FT_EXPORT( FT_Error ) FT_New_Face_From_FSRef ( FT_Library library, const FSRef *ref, FT_Long face_index, FT_Face *aface ) FT_DEPRECATED_ATTRIBUTE; Create a new face object from a given resource and typeface index using an FSRef to the font file.","title":"FT_New_Face_From_FSRef"},{"location":"ft2-module_management.html","text":"FreeType \u00bb Docs \u00bb Support API \u00bb Module Management Module Management \u00b6 Synopsis \u00b6 The definitions below are used to manage modules within FreeType. Modules can be added, upgraded, and removed at runtime. Additionally, some module properties can be controlled also. Here is a list of possible values of the module_name field in the FT_Module_Class structure. autofitter bdf cff gxvalid otvalid pcf pfr psaux pshinter psnames raster1 sfnt smooth truetype type1 type42 t1cid winfonts Note that the FreeType Cache sub-system is not a FreeType module. FT_Module \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_ModuleRec_* FT_Module ; A handle to a given FreeType module object. A module can be a font driver, a renderer, or anything else that provides services to the former. FT_Module_Constructor \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). typedef FT_Error (* FT_Module_Constructor )( FT_Module module ); A function used to initialize (not create) a new module object. input module The module to initialize. FT_Module_Destructor \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). typedef void (* FT_Module_Destructor )( FT_Module module ); A function used to finalize (not destroy) a given module object. input module The module to finalize. FT_Module_Requester \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). typedef FT_Module_Interface (* FT_Module_Requester )( FT_Module module, const char * name ); A function used to query a given module for a specific interface. input module The module to be searched. name The name of the interface in the module. FT_Module_Class \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). typedef struct FT_Module_Class_ { FT_ULong module_flags; FT_Long module_size; const FT_String * module_name; FT_Fixed module_version; FT_Fixed module_requires; const void * module_interface; FT_Module_Constructor module_init; FT_Module_Destructor module_done; FT_Module_Requester get_interface; } FT_Module_Class ; The module class descriptor. While being a public structure necessary for FreeType's module bookkeeping, most of the fields are essentially internal, not to be used directly by an application. fields module_flags Bit flags describing the module. module_size The size of one module object/instance in bytes. module_name The name of the module. module_version The version, as a 16.16 fixed number (major.minor). module_requires The version of FreeType this module requires, as a 16.16 fixed number (major.minor). Starts at version 2.0, i.e., 0x20000. module_interface A typeless pointer to a structure (which varies between different modules) that holds the module's interface functions. This is essentially what get_interface returns. module_init The initializing function. module_done The finalizing function. get_interface The interface requesting function. FT_Add_Module \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Error ) FT_Add_Module ( FT_Library library, const FT_Module_Class * clazz ); Add a new module to a given library instance. inout library A handle to the library object. input clazz A pointer to class descriptor for the module. return FreeType error code. 0 means success. note An error will be returned if a module already exists by that name, or if the module requires a version of FreeType that is too great. FT_Get_Module \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Module ) FT_Get_Module ( FT_Library library, const char * module_name ); Find a module by its name. input library A handle to the library object. module_name The module's name (as an ASCII string). return A module handle. 0 if none was found. note FreeType's internal modules aren't documented very well, and you should look up the source code for details. FT_Remove_Module \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Error ) FT_Remove_Module ( FT_Library library, FT_Module module ); Remove a given module from a library instance. inout library A handle to a library object. input module A handle to a module object. return FreeType error code. 0 means success. note The module object is destroyed by the function in case of success. FT_Add_Default_Modules \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( void ) FT_Add_Default_Modules ( FT_Library library ); Add the set of default drivers to a given library object. This is only useful when you create a library object with FT_New_Library (usually to plug a custom memory manager). inout library A handle to a new library object. FT_Property_Set \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Error ) FT_Property_Set ( FT_Library library, const FT_String * module_name, const FT_String * property_name, const void * value ); Set a property for a given module. input library A handle to the library the module is part of. module_name The module name. property_name The property name. Properties are described in section \u2018 Driver properties \u2019. Note that only a few modules have properties. value A generic pointer to a variable or structure that gives the new value of the property. The exact definition of value is dependent on the property; see section \u2018 Driver properties \u2019. return FreeType error code. 0 means success. note If module_name isn't a valid module name, or property_name doesn't specify a valid property, or if value doesn't represent a valid value for the given property, an error is returned. The following example sets property \u2018bar\u2019 (a simple integer) in module \u2018foo\u2019 to value 1. FT_UInt bar; bar = 1; FT_Property_Set( library, \"foo\", \"bar\", &bar ); Note that the FreeType Cache sub-system doesn't recognize module property changes. To avoid glyph lookup confusion within the cache you should call FTC_Manager_Reset to completely flush the cache if a module property gets changed after FTC_Manager_New has been called. It is not possible to set properties of the FreeType Cache sub-system itself with FT_Property_Set; use ?FTC_Property_Set? instead. since 2.4.11 FT_Property_Get \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Error ) FT_Property_Get ( FT_Library library, const FT_String * module_name, const FT_String * property_name, void * value ); Get a module's property value. input library A handle to the library the module is part of. module_name The module name. property_name The property name. Properties are described in section \u2018 Driver properties \u2019. inout value A generic pointer to a variable or structure that gives the value of the property. The exact definition of value is dependent on the property; see section \u2018 Driver properties \u2019. return FreeType error code. 0 means success. note If module_name isn't a valid module name, or property_name doesn't specify a valid property, or if value doesn't represent a valid value for the given property, an error is returned. The following example gets property \u2018baz\u2019 (a range) in module \u2018foo\u2019. typedef range_ { FT_Int32 min; FT_Int32 max; } range; range baz; FT_Property_Get( library, \"foo\", \"baz\", &baz ); It is not possible to retrieve properties of the FreeType Cache sub-system with FT_Property_Get; use ?FTC_Property_Get? instead. since 2.4.11 FT_Set_Default_Properties \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( void ) FT_Set_Default_Properties ( FT_Library library ); If compilation option FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES is set, this function reads the FREETYPE_PROPERTIES environment variable to control driver properties. See section \u2018 Driver properties \u2019 for more. If the compilation option is not set, this function does nothing. FREETYPE_PROPERTIES has the following syntax form (broken here into multiple lines for better readability). ':' '=' ':' '=' ... Example: FREETYPE_PROPERTIES=truetype:interpreter-version=35 \\ cff:no-stem-darkening=0 \\ autofitter:warping=1 inout library A handle to a new library object. since 2.8 FT_New_Library \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Error ) FT_New_Library ( FT_Memory memory, FT_Library *alibrary ); This function is used to create a new FreeType library instance from a given memory object. It is thus possible to use libraries with distinct memory allocators within the same program. Note, however, that the used FT_Memory structure is expected to remain valid for the life of the FT_Library object. Normally, you would call this function (followed by a call to FT_Add_Default_Modules or a series of calls to FT_Add_Module , and a call to FT_Set_Default_Properties ) instead of FT_Init_FreeType to initialize the FreeType library. Don't use FT_Done_FreeType but FT_Done_Library to destroy a library instance. input memory A handle to the original memory object. output alibrary A pointer to handle of a new library object. return FreeType error code. 0 means success. note See the discussion of reference counters in the description of FT_Reference_Library . FT_Done_Library \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Error ) FT_Done_Library ( FT_Library library ); Discard a given library object. This closes all drivers and discards all resource objects. input library A handle to the target library. return FreeType error code. 0 means success. note See the discussion of reference counters in the description of FT_Reference_Library . FT_Reference_Library \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Error ) FT_Reference_Library ( FT_Library library ); A counter gets initialized to 1 at the time an FT_Library structure is created. This function increments the counter. FT_Done_Library then only destroys a library if the counter is 1, otherwise it simply decrements the counter. This function helps in managing life-cycles of structures that reference FT_Library objects. input library A handle to a target library object. return FreeType error code. 0 means success. since 2.4.2 FT_Renderer \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_RendererRec_* FT_Renderer ; A handle to a given FreeType renderer. A renderer is a module in charge of converting a glyph's outline image to a bitmap. It supports a single glyph image format, and one or more target surface depths. FT_Renderer_Class \u00b6 Defined in FT_RENDER_H (freetype/ftrender.h). typedef struct FT_Renderer_Class_ { FT_Module_Class root; FT_Glyph_Format glyph_format; FT_Renderer_RenderFunc render_glyph; FT_Renderer_TransformFunc transform_glyph; FT_Renderer_GetCBoxFunc get_glyph_cbox; FT_Renderer_SetModeFunc set_mode; FT_Raster_Funcs * raster_class; } FT_Renderer_Class ; The renderer module class descriptor. fields root The root FT_Module_Class fields. glyph_format The glyph image format this renderer handles. render_glyph A method used to render the image that is in a given glyph slot into a bitmap. transform_glyph A method used to transform the image that is in a given glyph slot. get_glyph_cbox A method used to access the glyph's cbox. set_mode A method used to pass additional parameters. raster_class For FT_GLYPH_FORMAT_OUTLINE renderers only. This is a pointer to its raster's class. FT_Get_Renderer \u00b6 Defined in FT_RENDER_H (freetype/ftrender.h). FT_EXPORT( FT_Renderer ) FT_Get_Renderer ( FT_Library library, FT_Glyph_Format format ); Retrieve the current renderer for a given glyph format. input library A handle to the library object. format The glyph format. return A renderer handle. 0 if none found. note An error will be returned if a module already exists by that name, or if the module requires a version of FreeType that is too great. To add a new renderer, simply use FT_Add_Module . To retrieve a renderer by its name, use FT_Get_Module . FT_Set_Renderer \u00b6 Defined in FT_RENDER_H (freetype/ftrender.h). FT_EXPORT( FT_Error ) FT_Set_Renderer ( FT_Library library, FT_Renderer renderer, FT_UInt num_params, FT_Parameter * parameters ); Set the current renderer to use, and set additional mode. inout library A handle to the library object. input renderer A handle to the renderer object. num_params The number of additional parameters. parameters Additional parameters. return FreeType error code. 0 means success. note In case of success, the renderer will be used to convert glyph images in the renderer's known format into bitmaps. This doesn't change the current renderer for other formats. Currently, no FreeType renderer module uses parameters ; you should thus always pass NULL as the value. FT_Set_Debug_Hook \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( void ) FT_Set_Debug_Hook ( FT_Library library, FT_UInt hook_index, FT_DebugHook_Func debug_hook ); Set a debug hook function for debugging the interpreter of a font format. While this is a public API function, an application needs access to FreeType's internal header files to do something useful. Have a look at the source code of the ttdebug FreeType demo program for an example of its usage. inout library A handle to the library object. input hook_index The index of the debug hook. You should use defined enumeration macros like FT_DEBUG_HOOK_TRUETYPE . debug_hook The function used to debug the interpreter. note Currently, four debug hook slots are available, but only one (for the TrueType interpreter) is defined. FT_Driver \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_DriverRec_* FT_Driver ; A handle to a given FreeType font driver object. A font driver is a module capable of creating faces from font files. FT_DebugHook_Func \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). typedef FT_Error (* FT_DebugHook_Func )( void * arg ); A drop-in replacement (or rather a wrapper) for the bytecode or charstring interpreter's main loop function. Its job is essentially to activate debug mode to enforce single-stepping, to call the main loop function to interpret the next opcode, and to show the changed context to the user. An example for such a main loop function is TT_RunIns (declared in FreeType's internal header file src/truetype/ttinterp.h ). Have a look at the source code of the ttdebug FreeType demo program for an example of a drop-in replacement. inout arg A typeless pointer, to be cast to the main loop function's data structure (which depends on the font module). For TrueType fonts it is bytecode interpreter's execution context, TT_ExecContext , which is declared in FreeType's internal header file tttypes.h . FT_DEBUG_HOOK_XXX \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). # define FT_DEBUG_HOOK_TRUETYPE 0 A list of named debug hook indices. values FT_DEBUG_HOOK_TRUETYPE This hook index identifies the TrueType bytecode debugger.","title":"Module Management"},{"location":"ft2-module_management.html#module-management","text":"","title":"Module Management"},{"location":"ft2-module_management.html#synopsis","text":"The definitions below are used to manage modules within FreeType. Modules can be added, upgraded, and removed at runtime. Additionally, some module properties can be controlled also. Here is a list of possible values of the module_name field in the FT_Module_Class structure. autofitter bdf cff gxvalid otvalid pcf pfr psaux pshinter psnames raster1 sfnt smooth truetype type1 type42 t1cid winfonts Note that the FreeType Cache sub-system is not a FreeType module.","title":"Synopsis"},{"location":"ft2-module_management.html#ft_module","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_ModuleRec_* FT_Module ; A handle to a given FreeType module object. A module can be a font driver, a renderer, or anything else that provides services to the former.","title":"FT_Module"},{"location":"ft2-module_management.html#ft_module_constructor","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). typedef FT_Error (* FT_Module_Constructor )( FT_Module module ); A function used to initialize (not create) a new module object.","title":"FT_Module_Constructor"},{"location":"ft2-module_management.html#ft_module_destructor","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). typedef void (* FT_Module_Destructor )( FT_Module module ); A function used to finalize (not destroy) a given module object.","title":"FT_Module_Destructor"},{"location":"ft2-module_management.html#ft_module_requester","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). typedef FT_Module_Interface (* FT_Module_Requester )( FT_Module module, const char * name ); A function used to query a given module for a specific interface.","title":"FT_Module_Requester"},{"location":"ft2-module_management.html#ft_module_class","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). typedef struct FT_Module_Class_ { FT_ULong module_flags; FT_Long module_size; const FT_String * module_name; FT_Fixed module_version; FT_Fixed module_requires; const void * module_interface; FT_Module_Constructor module_init; FT_Module_Destructor module_done; FT_Module_Requester get_interface; } FT_Module_Class ; The module class descriptor. While being a public structure necessary for FreeType's module bookkeeping, most of the fields are essentially internal, not to be used directly by an application.","title":"FT_Module_Class"},{"location":"ft2-module_management.html#ft_add_module","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Error ) FT_Add_Module ( FT_Library library, const FT_Module_Class * clazz ); Add a new module to a given library instance.","title":"FT_Add_Module"},{"location":"ft2-module_management.html#ft_get_module","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Module ) FT_Get_Module ( FT_Library library, const char * module_name ); Find a module by its name.","title":"FT_Get_Module"},{"location":"ft2-module_management.html#ft_remove_module","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Error ) FT_Remove_Module ( FT_Library library, FT_Module module ); Remove a given module from a library instance.","title":"FT_Remove_Module"},{"location":"ft2-module_management.html#ft_add_default_modules","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( void ) FT_Add_Default_Modules ( FT_Library library ); Add the set of default drivers to a given library object. This is only useful when you create a library object with FT_New_Library (usually to plug a custom memory manager).","title":"FT_Add_Default_Modules"},{"location":"ft2-module_management.html#ft_property_set","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Error ) FT_Property_Set ( FT_Library library, const FT_String * module_name, const FT_String * property_name, const void * value ); Set a property for a given module.","title":"FT_Property_Set"},{"location":"ft2-module_management.html#ft_property_get","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Error ) FT_Property_Get ( FT_Library library, const FT_String * module_name, const FT_String * property_name, void * value ); Get a module's property value.","title":"FT_Property_Get"},{"location":"ft2-module_management.html#ft_set_default_properties","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( void ) FT_Set_Default_Properties ( FT_Library library ); If compilation option FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES is set, this function reads the FREETYPE_PROPERTIES environment variable to control driver properties. See section \u2018 Driver properties \u2019 for more. If the compilation option is not set, this function does nothing. FREETYPE_PROPERTIES has the following syntax form (broken here into multiple lines for better readability). ':' '=' ':' '=' ... Example: FREETYPE_PROPERTIES=truetype:interpreter-version=35 \\ cff:no-stem-darkening=0 \\ autofitter:warping=1","title":"FT_Set_Default_Properties"},{"location":"ft2-module_management.html#ft_new_library","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Error ) FT_New_Library ( FT_Memory memory, FT_Library *alibrary ); This function is used to create a new FreeType library instance from a given memory object. It is thus possible to use libraries with distinct memory allocators within the same program. Note, however, that the used FT_Memory structure is expected to remain valid for the life of the FT_Library object. Normally, you would call this function (followed by a call to FT_Add_Default_Modules or a series of calls to FT_Add_Module , and a call to FT_Set_Default_Properties ) instead of FT_Init_FreeType to initialize the FreeType library. Don't use FT_Done_FreeType but FT_Done_Library to destroy a library instance.","title":"FT_New_Library"},{"location":"ft2-module_management.html#ft_done_library","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Error ) FT_Done_Library ( FT_Library library ); Discard a given library object. This closes all drivers and discards all resource objects.","title":"FT_Done_Library"},{"location":"ft2-module_management.html#ft_reference_library","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_Error ) FT_Reference_Library ( FT_Library library ); A counter gets initialized to 1 at the time an FT_Library structure is created. This function increments the counter. FT_Done_Library then only destroys a library if the counter is 1, otherwise it simply decrements the counter. This function helps in managing life-cycles of structures that reference FT_Library objects.","title":"FT_Reference_Library"},{"location":"ft2-module_management.html#ft_renderer","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_RendererRec_* FT_Renderer ; A handle to a given FreeType renderer. A renderer is a module in charge of converting a glyph's outline image to a bitmap. It supports a single glyph image format, and one or more target surface depths.","title":"FT_Renderer"},{"location":"ft2-module_management.html#ft_renderer_class","text":"Defined in FT_RENDER_H (freetype/ftrender.h). typedef struct FT_Renderer_Class_ { FT_Module_Class root; FT_Glyph_Format glyph_format; FT_Renderer_RenderFunc render_glyph; FT_Renderer_TransformFunc transform_glyph; FT_Renderer_GetCBoxFunc get_glyph_cbox; FT_Renderer_SetModeFunc set_mode; FT_Raster_Funcs * raster_class; } FT_Renderer_Class ; The renderer module class descriptor.","title":"FT_Renderer_Class"},{"location":"ft2-module_management.html#ft_get_renderer","text":"Defined in FT_RENDER_H (freetype/ftrender.h). FT_EXPORT( FT_Renderer ) FT_Get_Renderer ( FT_Library library, FT_Glyph_Format format ); Retrieve the current renderer for a given glyph format.","title":"FT_Get_Renderer"},{"location":"ft2-module_management.html#ft_set_renderer","text":"Defined in FT_RENDER_H (freetype/ftrender.h). FT_EXPORT( FT_Error ) FT_Set_Renderer ( FT_Library library, FT_Renderer renderer, FT_UInt num_params, FT_Parameter * parameters ); Set the current renderer to use, and set additional mode.","title":"FT_Set_Renderer"},{"location":"ft2-module_management.html#ft_set_debug_hook","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( void ) FT_Set_Debug_Hook ( FT_Library library, FT_UInt hook_index, FT_DebugHook_Func debug_hook ); Set a debug hook function for debugging the interpreter of a font format. While this is a public API function, an application needs access to FreeType's internal header files to do something useful. Have a look at the source code of the ttdebug FreeType demo program for an example of its usage.","title":"FT_Set_Debug_Hook"},{"location":"ft2-module_management.html#ft_driver","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). typedef struct FT_DriverRec_* FT_Driver ; A handle to a given FreeType font driver object. A font driver is a module capable of creating faces from font files.","title":"FT_Driver"},{"location":"ft2-module_management.html#ft_debughook_func","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). typedef FT_Error (* FT_DebugHook_Func )( void * arg ); A drop-in replacement (or rather a wrapper) for the bytecode or charstring interpreter's main loop function. Its job is essentially to activate debug mode to enforce single-stepping, to call the main loop function to interpret the next opcode, and to show the changed context to the user. An example for such a main loop function is TT_RunIns (declared in FreeType's internal header file src/truetype/ttinterp.h ). Have a look at the source code of the ttdebug FreeType demo program for an example of a drop-in replacement.","title":"FT_DebugHook_Func"},{"location":"ft2-module_management.html#ft_debug_hook_xxx","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). # define FT_DEBUG_HOOK_TRUETYPE 0 A list of named debug hook indices.","title":"FT_DEBUG_HOOK_XXX"},{"location":"ft2-multiple_masters.html","text":"FreeType \u00bb Docs \u00bb Format-Specific API \u00bb Multiple Masters Multiple Masters \u00b6 Synopsis \u00b6 The following types and functions are used to manage Multiple Master fonts, i.e., the selection of specific design instances by setting design axis coordinates. Besides Adobe MM fonts, the interface supports Apple's TrueType GX and OpenType variation fonts. Some of the routines only work with Adobe MM fonts, others will work with all three types. They are similar enough that a consistent interface makes sense. FT_MM_Axis \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). typedef struct FT_MM_Axis_ { FT_String * name; FT_Long minimum; FT_Long maximum; } FT_MM_Axis ; A structure to model a given axis in design space for Multiple Masters fonts. This structure can't be used for TrueType GX or OpenType variation fonts. fields name The axis's name. minimum The axis's minimum design coordinate. maximum The axis's maximum design coordinate. FT_Multi_Master \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). typedef struct FT_Multi_Master_ { FT_UInt num_axis; FT_UInt num_designs; FT_MM_Axis axis[T1_MAX_MM_AXIS]; } FT_Multi_Master ; A structure to model the axes and space of a Multiple Masters font. This structure can't be used for TrueType GX or OpenType variation fonts. fields num_axis Number of axes. Cannot exceed 4. num_designs Number of designs; should be normally 2^num_axis even though the Type 1 specification strangely allows for intermediate designs to be present. This number cannot exceed 16. axis A table of axis descriptors. FT_Var_Axis \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). typedef struct FT_Var_Axis_ { FT_String * name; FT_Fixed minimum; FT_Fixed def; FT_Fixed maximum; FT_ULong tag; FT_UInt strid; } FT_Var_Axis ; A structure to model a given axis in design space for Multiple Masters, TrueType GX, and OpenType variation fonts. fields name The axis's name. Not always meaningful for TrueType GX or OpenType variation fonts. minimum The axis's minimum design coordinate. def The axis's default design coordinate. FreeType computes meaningful default values for Adobe MM fonts. maximum The axis's maximum design coordinate. tag The axis's tag (the equivalent to \u2018name\u2019 for TrueType GX and OpenType variation fonts). FreeType provides default values for Adobe MM fonts if possible. strid The axis name entry in the font's \u2018name\u2019 table. This is another (and often better) version of the \u2018name\u2019 field for TrueType GX or OpenType variation fonts. Not meaningful for Adobe MM fonts. note The fields minimum , def , and maximum are 16.16 fractional values for TrueType GX and OpenType variation fonts. For Adobe MM fonts, the values are integers. FT_Var_Named_Style \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). typedef struct FT_Var_Named_Style_ { FT_Fixed * coords; FT_UInt strid; FT_UInt psid; /* since 2.7.1 */ } FT_Var_Named_Style ; A structure to model a named instance in a TrueType GX or OpenType variation font. This structure can't be used for Adobe MM fonts. fields coords The design coordinates for this instance. This is an array with one entry for each axis. strid The entry in \u2018name\u2019 table identifying this instance. psid The entry in \u2018name\u2019 table identifying a PostScript name for this instance. Value 0xFFFF indicates a missing entry. FT_MM_Var \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). typedef struct FT_MM_Var_ { FT_UInt num_axis; FT_UInt num_designs; FT_UInt num_namedstyles; FT_Var_Axis * axis; FT_Var_Named_Style * namedstyle; } FT_MM_Var ; A structure to model the axes and space of an Adobe MM, TrueType GX, or OpenType variation font. Some fields are specific to one format and not to the others. fields num_axis The number of axes. The maximum value is 4 for Adobe MM fonts; no limit in TrueType GX or OpenType variation fonts. num_designs The number of designs; should be normally 2^num_axis for Adobe MM fonts. Not meaningful for TrueType GX or OpenType variation fonts (where every glyph could have a different number of designs). num_namedstyles The number of named styles; a \u2018named style\u2019 is a tuple of design coordinates that has a string ID (in the \u2018name\u2019 table) associated with it. The font can tell the user that, for example, [Weight=1.5,Width=1.1] is \u2018Bold\u2019. Another name for \u2018named style\u2019 is \u2018named instance\u2019. For Adobe Multiple Masters fonts, this value is always zero because the format does not support named styles. axis An axis descriptor table. TrueType GX and OpenType variation fonts contain slightly more data than Adobe MM fonts. Memory management of this pointer is done internally by FreeType. namedstyle A named style (instance) table. Only meaningful for TrueType GX and OpenType variation fonts. Memory management of this pointer is done internally by FreeType. FT_Get_Multi_Master \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Get_Multi_Master ( FT_Face face, FT_Multi_Master *amaster ); Retrieve a variation descriptor of a given Adobe MM font. This function can't be used with TrueType GX or OpenType variation fonts. input face A handle to the source face. output amaster The Multiple Masters descriptor. return FreeType error code. 0 means success. FT_Get_MM_Var \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Get_MM_Var ( FT_Face face, FT_MM_Var * *amaster ); Retrieve a variation descriptor for a given font. This function works with all supported variation formats. input face A handle to the source face. output amaster The variation descriptor. Allocates a data structure, which the user must deallocate with a call to FT_Done_MM_Var after use. return FreeType error code. 0 means success. FT_Done_MM_Var \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Done_MM_Var ( FT_Library library, FT_MM_Var *amaster ); Free the memory allocated by FT_Get_MM_Var . input library A handle of the face's parent library object that was used in the call to FT_Get_MM_Var to create amaster . return FreeType error code. 0 means success. FT_Set_MM_Design_Coordinates \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Set_MM_Design_Coordinates ( FT_Face face, FT_UInt num_coords, FT_Long * coords ); For Adobe MM fonts, choose an interpolated font design through design coordinates. This function can't be used with TrueType GX or OpenType variation fonts. inout face A handle to the source face. input num_coords The number of available design coordinates. If it is larger than the number of axes, ignore the excess values. If it is smaller than the number of axes, use default values for the remaining axes. coords An array of design coordinates. return FreeType error code. 0 means success. note [Since 2.8.1] To reset all axes to the default values, call the function with num_coords set to zero and coords set to NULL . [Since 2.9] If num_coords is larger than zero, this function sets the FT_FACE_FLAG_VARIATION bit in FT_Face 's face_flags field (i.e., FT_IS_VARIATION will return true). If num_coords is zero, this bit flag gets unset. FT_Set_Var_Design_Coordinates \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Set_Var_Design_Coordinates ( FT_Face face, FT_UInt num_coords, FT_Fixed * coords ); Choose an interpolated font design through design coordinates. This function works with all supported variation formats. inout face A handle to the source face. input num_coords The number of available design coordinates. If it is larger than the number of axes, ignore the excess values. If it is smaller than the number of axes, use default values for the remaining axes. coords An array of design coordinates. return FreeType error code. 0 means success. note [Since 2.8.1] To reset all axes to the default values, call the function with num_coords set to zero and coords set to NULL . [Since 2.9] \u2018Default values\u2019 means the currently selected named instance (or the base font if no named instance is selected). [Since 2.9] If num_coords is larger than zero, this function sets the FT_FACE_FLAG_VARIATION bit in FT_Face 's face_flags field (i.e., FT_IS_VARIATION will return true). If num_coords is zero, this bit flag gets unset. FT_Get_Var_Design_Coordinates \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Get_Var_Design_Coordinates ( FT_Face face, FT_UInt num_coords, FT_Fixed * coords ); Get the design coordinates of the currently selected interpolated font. This function works with all supported variation formats. input face A handle to the source face. num_coords The number of design coordinates to retrieve. If it is larger than the number of axes, set the excess values to 0. output coords The design coordinates array. return FreeType error code. 0 means success. since 2.7.1 FT_Set_MM_Blend_Coordinates \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Set_MM_Blend_Coordinates ( FT_Face face, FT_UInt num_coords, FT_Fixed * coords ); Choose an interpolated font design through normalized blend coordinates. This function works with all supported variation formats. inout face A handle to the source face. input num_coords The number of available design coordinates. If it is larger than the number of axes, ignore the excess values. If it is smaller than the number of axes, use default values for the remaining axes. coords The design coordinates array (each element must be between 0 and 1.0 for Adobe MM fonts, and between -1.0 and 1.0 for TrueType GX and OpenType variation fonts). return FreeType error code. 0 means success. note [Since 2.8.1] To reset all axes to the default values, call the function with num_coords set to zero and coords set to NULL . [Since 2.9] \u2018Default values\u2019 means the currently selected named instance (or the base font if no named instance is selected). [Since 2.9] If num_coords is larger than zero, this function sets the FT_FACE_FLAG_VARIATION bit in FT_Face 's face_flags field (i.e., FT_IS_VARIATION will return true). If num_coords is zero, this bit flag gets unset. FT_Get_MM_Blend_Coordinates \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Get_MM_Blend_Coordinates ( FT_Face face, FT_UInt num_coords, FT_Fixed * coords ); Get the normalized blend coordinates of the currently selected interpolated font. This function works with all supported variation formats. input face A handle to the source face. num_coords The number of normalized blend coordinates to retrieve. If it is larger than the number of axes, set the excess values to 0.5 for Adobe MM fonts, and to 0 for TrueType GX and OpenType variation fonts. output coords The normalized blend coordinates array. return FreeType error code. 0 means success. since 2.7.1 FT_Set_Var_Blend_Coordinates \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Set_Var_Blend_Coordinates ( FT_Face face, FT_UInt num_coords, FT_Fixed * coords ); This is another name of FT_Set_MM_Blend_Coordinates . FT_Get_Var_Blend_Coordinates \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Get_Var_Blend_Coordinates ( FT_Face face, FT_UInt num_coords, FT_Fixed * coords ); This is another name of FT_Get_MM_Blend_Coordinates . since 2.7.1 FT_Set_MM_WeightVector \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Set_MM_WeightVector ( FT_Face face, FT_UInt len, FT_Fixed * weightvector ); For Adobe MM fonts, choose an interpolated font design by directly setting the weight vector. This function can't be used with TrueType GX or OpenType variation fonts. inout face A handle to the source face. input len The length of the weight vector array. If it is larger than the number of designs, the extra values are ignored. If it is less than the number of designs, the remaining values are set to zero. weightvector An array representing the weight vector. return FreeType error code. 0 means success. note Adobe Multiple Master fonts limit the number of designs, and thus the length of the weight vector to 16. If len is zero and weightvector is NULL , the weight vector array is reset to the default values. The Adobe documentation also states that the values in the WeightVector array must total 1.0 \u00b1 0.001. In practice this does not seem to be enforced, so is not enforced here, either. since 2.10 FT_Get_MM_WeightVector \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Get_MM_WeightVector ( FT_Face face, FT_UInt * len, FT_Fixed * weightvector ); For Adobe MM fonts, retrieve the current weight vector of the font. This function can't be used with TrueType GX or OpenType variation fonts. inout face A handle to the source face. len A pointer to the size of the array to be filled. If the size of the array is less than the number of designs, FT_Err_Invalid_Argument is returned, and len is set to the required size (the number of designs). If the size of the array is greater than the number of designs, the remaining entries are set to 0. On successful completion, len is set to the number of designs (i.e., the number of values written to the array). output weightvector An array to be filled. return FreeType error code. 0 means success. note Adobe Multiple Master fonts limit the number of designs, and thus the length of the WeightVector to 16. since 2.10 FT_VAR_AXIS_FLAG_XXX \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). # define FT_VAR_AXIS_FLAG_HIDDEN 1 A list of bit flags used in the return value of FT_Get_Var_Axis_Flags . values FT_VAR_AXIS_FLAG_HIDDEN The variation axis should not be exposed to user interfaces. since 2.8.1 FT_Get_Var_Axis_Flags \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Get_Var_Axis_Flags ( FT_MM_Var * master, FT_UInt axis_index, FT_UInt * flags ); Get the \u2018flags\u2019 field of an OpenType Variation Axis Record. Not meaningful for Adobe MM fonts ( *flags is always zero). input master The variation descriptor. axis_index The index of the requested variation axis. output flags The \u2018flags\u2019 field. See FT_VAR_AXIS_FLAG_XXX for possible values. return FreeType error code. 0 means success. since 2.8.1 FT_Set_Named_Instance \u00b6 Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Set_Named_Instance ( FT_Face face, FT_UInt instance_index ); Set or change the current named instance. input face A handle to the source face. instance_index The index of the requested instance, starting with value 1. If set to value 0, FreeType switches to font access without a named instance. return FreeType error code. 0 means success. note The function uses the value of instance_index to set bits 16-30 of the face's face_index field. It also resets any variation applied to the font, and the FT_FACE_FLAG_VARIATION bit of the face's face_flags field gets reset to zero (i.e., FT_IS_VARIATION will return false). For Adobe MM fonts (which don't have named instances) this function simply resets the current face to the default instance. since 2.9","title":"Multiple Masters"},{"location":"ft2-multiple_masters.html#multiple-masters","text":"","title":"Multiple Masters"},{"location":"ft2-multiple_masters.html#synopsis","text":"The following types and functions are used to manage Multiple Master fonts, i.e., the selection of specific design instances by setting design axis coordinates. Besides Adobe MM fonts, the interface supports Apple's TrueType GX and OpenType variation fonts. Some of the routines only work with Adobe MM fonts, others will work with all three types. They are similar enough that a consistent interface makes sense.","title":"Synopsis"},{"location":"ft2-multiple_masters.html#ft_mm_axis","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). typedef struct FT_MM_Axis_ { FT_String * name; FT_Long minimum; FT_Long maximum; } FT_MM_Axis ; A structure to model a given axis in design space for Multiple Masters fonts. This structure can't be used for TrueType GX or OpenType variation fonts.","title":"FT_MM_Axis"},{"location":"ft2-multiple_masters.html#ft_multi_master","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). typedef struct FT_Multi_Master_ { FT_UInt num_axis; FT_UInt num_designs; FT_MM_Axis axis[T1_MAX_MM_AXIS]; } FT_Multi_Master ; A structure to model the axes and space of a Multiple Masters font. This structure can't be used for TrueType GX or OpenType variation fonts.","title":"FT_Multi_Master"},{"location":"ft2-multiple_masters.html#ft_var_axis","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). typedef struct FT_Var_Axis_ { FT_String * name; FT_Fixed minimum; FT_Fixed def; FT_Fixed maximum; FT_ULong tag; FT_UInt strid; } FT_Var_Axis ; A structure to model a given axis in design space for Multiple Masters, TrueType GX, and OpenType variation fonts.","title":"FT_Var_Axis"},{"location":"ft2-multiple_masters.html#ft_var_named_style","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). typedef struct FT_Var_Named_Style_ { FT_Fixed * coords; FT_UInt strid; FT_UInt psid; /* since 2.7.1 */ } FT_Var_Named_Style ; A structure to model a named instance in a TrueType GX or OpenType variation font. This structure can't be used for Adobe MM fonts.","title":"FT_Var_Named_Style"},{"location":"ft2-multiple_masters.html#ft_mm_var","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). typedef struct FT_MM_Var_ { FT_UInt num_axis; FT_UInt num_designs; FT_UInt num_namedstyles; FT_Var_Axis * axis; FT_Var_Named_Style * namedstyle; } FT_MM_Var ; A structure to model the axes and space of an Adobe MM, TrueType GX, or OpenType variation font. Some fields are specific to one format and not to the others.","title":"FT_MM_Var"},{"location":"ft2-multiple_masters.html#ft_get_multi_master","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Get_Multi_Master ( FT_Face face, FT_Multi_Master *amaster ); Retrieve a variation descriptor of a given Adobe MM font. This function can't be used with TrueType GX or OpenType variation fonts.","title":"FT_Get_Multi_Master"},{"location":"ft2-multiple_masters.html#ft_get_mm_var","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Get_MM_Var ( FT_Face face, FT_MM_Var * *amaster ); Retrieve a variation descriptor for a given font. This function works with all supported variation formats.","title":"FT_Get_MM_Var"},{"location":"ft2-multiple_masters.html#ft_done_mm_var","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Done_MM_Var ( FT_Library library, FT_MM_Var *amaster ); Free the memory allocated by FT_Get_MM_Var .","title":"FT_Done_MM_Var"},{"location":"ft2-multiple_masters.html#ft_set_mm_design_coordinates","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Set_MM_Design_Coordinates ( FT_Face face, FT_UInt num_coords, FT_Long * coords ); For Adobe MM fonts, choose an interpolated font design through design coordinates. This function can't be used with TrueType GX or OpenType variation fonts.","title":"FT_Set_MM_Design_Coordinates"},{"location":"ft2-multiple_masters.html#ft_set_var_design_coordinates","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Set_Var_Design_Coordinates ( FT_Face face, FT_UInt num_coords, FT_Fixed * coords ); Choose an interpolated font design through design coordinates. This function works with all supported variation formats.","title":"FT_Set_Var_Design_Coordinates"},{"location":"ft2-multiple_masters.html#ft_get_var_design_coordinates","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Get_Var_Design_Coordinates ( FT_Face face, FT_UInt num_coords, FT_Fixed * coords ); Get the design coordinates of the currently selected interpolated font. This function works with all supported variation formats.","title":"FT_Get_Var_Design_Coordinates"},{"location":"ft2-multiple_masters.html#ft_set_mm_blend_coordinates","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Set_MM_Blend_Coordinates ( FT_Face face, FT_UInt num_coords, FT_Fixed * coords ); Choose an interpolated font design through normalized blend coordinates. This function works with all supported variation formats.","title":"FT_Set_MM_Blend_Coordinates"},{"location":"ft2-multiple_masters.html#ft_get_mm_blend_coordinates","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Get_MM_Blend_Coordinates ( FT_Face face, FT_UInt num_coords, FT_Fixed * coords ); Get the normalized blend coordinates of the currently selected interpolated font. This function works with all supported variation formats.","title":"FT_Get_MM_Blend_Coordinates"},{"location":"ft2-multiple_masters.html#ft_set_var_blend_coordinates","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Set_Var_Blend_Coordinates ( FT_Face face, FT_UInt num_coords, FT_Fixed * coords ); This is another name of FT_Set_MM_Blend_Coordinates .","title":"FT_Set_Var_Blend_Coordinates"},{"location":"ft2-multiple_masters.html#ft_get_var_blend_coordinates","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Get_Var_Blend_Coordinates ( FT_Face face, FT_UInt num_coords, FT_Fixed * coords ); This is another name of FT_Get_MM_Blend_Coordinates .","title":"FT_Get_Var_Blend_Coordinates"},{"location":"ft2-multiple_masters.html#ft_set_mm_weightvector","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Set_MM_WeightVector ( FT_Face face, FT_UInt len, FT_Fixed * weightvector ); For Adobe MM fonts, choose an interpolated font design by directly setting the weight vector. This function can't be used with TrueType GX or OpenType variation fonts.","title":"FT_Set_MM_WeightVector"},{"location":"ft2-multiple_masters.html#ft_get_mm_weightvector","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Get_MM_WeightVector ( FT_Face face, FT_UInt * len, FT_Fixed * weightvector ); For Adobe MM fonts, retrieve the current weight vector of the font. This function can't be used with TrueType GX or OpenType variation fonts.","title":"FT_Get_MM_WeightVector"},{"location":"ft2-multiple_masters.html#ft_var_axis_flag_xxx","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). # define FT_VAR_AXIS_FLAG_HIDDEN 1 A list of bit flags used in the return value of FT_Get_Var_Axis_Flags .","title":"FT_VAR_AXIS_FLAG_XXX"},{"location":"ft2-multiple_masters.html#ft_get_var_axis_flags","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Get_Var_Axis_Flags ( FT_MM_Var * master, FT_UInt axis_index, FT_UInt * flags ); Get the \u2018flags\u2019 field of an OpenType Variation Axis Record. Not meaningful for Adobe MM fonts ( *flags is always zero).","title":"FT_Get_Var_Axis_Flags"},{"location":"ft2-multiple_masters.html#ft_set_named_instance","text":"Defined in FT_MULTIPLE_MASTERS_H (freetype/ftmm.h). FT_EXPORT( FT_Error ) FT_Set_Named_Instance ( FT_Face face, FT_UInt instance_index ); Set or change the current named instance.","title":"FT_Set_Named_Instance"},{"location":"ft2-ot_validation.html","text":"FreeType \u00bb Docs \u00bb Miscellaneous \u00bb OpenType Validation OpenType Validation \u00b6 Synopsis \u00b6 This section contains the declaration of functions to validate some OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH). FT_OpenType_Validate \u00b6 Defined in FT_OPENTYPE_VALIDATE_H (freetype/ftotval.h). FT_EXPORT( FT_Error ) FT_OpenType_Validate ( FT_Face face, FT_UInt validation_flags, FT_Bytes *BASE_table, FT_Bytes *GDEF_table, FT_Bytes *GPOS_table, FT_Bytes *GSUB_table, FT_Bytes *JSTF_table ); Validate various OpenType tables to assure that all offsets and indices are valid. The idea is that a higher-level library that actually does the text layout can access those tables without error checking (which can be quite time consuming). input face A handle to the input face. validation_flags A bit field that specifies the tables to be validated. See FT_VALIDATE_OTXXX for possible values. output BASE_table A pointer to the BASE table. GDEF_table A pointer to the GDEF table. GPOS_table A pointer to the GPOS table. GSUB_table A pointer to the GSUB table. JSTF_table A pointer to the JSTF table. return FreeType error code. 0 means success. note This function only works with OpenType fonts, returning an error otherwise. After use, the application should deallocate the five tables with FT_OpenType_Free . A NULL value indicates that the table either doesn't exist in the font, or the application hasn't asked for validation. FT_OpenType_Free \u00b6 Defined in FT_OPENTYPE_VALIDATE_H (freetype/ftotval.h). FT_EXPORT( void ) FT_OpenType_Free ( FT_Face face, FT_Bytes table ); Free the buffer allocated by OpenType validator. input face A handle to the input face. table The pointer to the buffer that is allocated by FT_OpenType_Validate . note This function must be used to free the buffer allocated by FT_OpenType_Validate only. FT_VALIDATE_OTXXX \u00b6 Defined in FT_OPENTYPE_VALIDATE_H (freetype/ftotval.h). # define FT_VALIDATE_BASE 0x0100 # define FT_VALIDATE_GDEF 0x0200 # define FT_VALIDATE_GPOS 0x0400 # define FT_VALIDATE_GSUB 0x0800 # define FT_VALIDATE_JSTF 0x1000 # define FT_VALIDATE_MATH 0x2000 # define FT_VALIDATE_OT ( FT_VALIDATE_BASE | \\ FT_VALIDATE_GDEF | \\ FT_VALIDATE_GPOS | \\ FT_VALIDATE_GSUB | \\ FT_VALIDATE_JSTF | \\ FT_VALIDATE_MATH ) A list of bit-field constants used with FT_OpenType_Validate to indicate which OpenType tables should be validated. values FT_VALIDATE_BASE Validate BASE table. FT_VALIDATE_GDEF Validate GDEF table. FT_VALIDATE_GPOS Validate GPOS table. FT_VALIDATE_GSUB Validate GSUB table. FT_VALIDATE_JSTF Validate JSTF table. FT_VALIDATE_MATH Validate MATH table. FT_VALIDATE_OT Validate all OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH).","title":"OpenType Validation"},{"location":"ft2-ot_validation.html#opentype-validation","text":"","title":"OpenType Validation"},{"location":"ft2-ot_validation.html#synopsis","text":"This section contains the declaration of functions to validate some OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH).","title":"Synopsis"},{"location":"ft2-ot_validation.html#ft_opentype_validate","text":"Defined in FT_OPENTYPE_VALIDATE_H (freetype/ftotval.h). FT_EXPORT( FT_Error ) FT_OpenType_Validate ( FT_Face face, FT_UInt validation_flags, FT_Bytes *BASE_table, FT_Bytes *GDEF_table, FT_Bytes *GPOS_table, FT_Bytes *GSUB_table, FT_Bytes *JSTF_table ); Validate various OpenType tables to assure that all offsets and indices are valid. The idea is that a higher-level library that actually does the text layout can access those tables without error checking (which can be quite time consuming).","title":"FT_OpenType_Validate"},{"location":"ft2-ot_validation.html#ft_opentype_free","text":"Defined in FT_OPENTYPE_VALIDATE_H (freetype/ftotval.h). FT_EXPORT( void ) FT_OpenType_Free ( FT_Face face, FT_Bytes table ); Free the buffer allocated by OpenType validator.","title":"FT_OpenType_Free"},{"location":"ft2-ot_validation.html#ft_validate_otxxx","text":"Defined in FT_OPENTYPE_VALIDATE_H (freetype/ftotval.h). # define FT_VALIDATE_BASE 0x0100 # define FT_VALIDATE_GDEF 0x0200 # define FT_VALIDATE_GPOS 0x0400 # define FT_VALIDATE_GSUB 0x0800 # define FT_VALIDATE_JSTF 0x1000 # define FT_VALIDATE_MATH 0x2000 # define FT_VALIDATE_OT ( FT_VALIDATE_BASE | \\ FT_VALIDATE_GDEF | \\ FT_VALIDATE_GPOS | \\ FT_VALIDATE_GSUB | \\ FT_VALIDATE_JSTF | \\ FT_VALIDATE_MATH ) A list of bit-field constants used with FT_OpenType_Validate to indicate which OpenType tables should be validated.","title":"FT_VALIDATE_OTXXX"},{"location":"ft2-outline_processing.html","text":"FreeType \u00bb Docs \u00bb Support API \u00bb Outline Processing Outline Processing \u00b6 Synopsis \u00b6 This section contains routines used to create and destroy scalable glyph images known as \u2018outlines\u2019. These can also be measured, transformed, and converted into bitmaps and pixmaps. FT_Outline \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_Outline_ { short n_contours; /* number of contours in glyph */ short n_points; /* number of points in the glyph */ FT_Vector * points; /* the outline's points */ char * tags; /* the points flags */ short * contours; /* the contour end points */ int flags; /* outline masks */ } FT_Outline ; This structure is used to describe an outline to the scan-line converter. fields n_contours The number of contours in the outline. n_points The number of points in the outline. points A pointer to an array of n_points FT_Vector elements, giving the outline's point coordinates. tags A pointer to an array of n_points chars, giving each outline point's type. If bit 0 is unset, the point is \u2018off\u2019 the curve, i.e., a Bezier control point, while it is \u2018on\u2019 if set. Bit 1 is meaningful for \u2018off\u2019 points only. If set, it indicates a third-order Bezier arc control point; and a second-order control point if unset. If bit 2 is set, bits 5-7 contain the drop-out mode (as defined in the OpenType specification; the value is the same as the argument to the \u2018SCANMODE\u2019 instruction). Bits 3 and 4 are reserved for internal purposes. contours An array of n_contours shorts, giving the end point of each contour within the outline. For example, the first contour is defined by the points \u20180\u2019 to contours[0] , the second one is defined by the points contours[0]+1 to contours[1] , etc. flags A set of bit flags used to characterize the outline and give hints to the scan-converter and hinter on how to convert/grid-fit it. See FT_OUTLINE_XXX . note The B/W rasterizer only checks bit 2 in the tags array for the first point of each contour. The drop-out mode as given with FT_OUTLINE_IGNORE_DROPOUTS , FT_OUTLINE_SMART_DROPOUTS , and FT_OUTLINE_INCLUDE_STUBS in flags is then overridden. FT_Outline_New \u00b6 Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_New ( FT_Library library, FT_UInt numPoints, FT_Int numContours, FT_Outline *anoutline ); Create a new outline of a given size. input library A handle to the library object from where the outline is allocated. Note however that the new outline will not necessarily be freed , when destroying the library, by FT_Done_FreeType . numPoints The maximum number of points within the outline. Must be smaller than or equal to 0xFFFF (65535). numContours The maximum number of contours within the outline. This value must be in the range 0 to numPoints . output anoutline A handle to the new outline. return FreeType error code. 0 means success. note The reason why this function takes a library parameter is simply to use the library's memory allocator. FT_Outline_Done \u00b6 Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_Done ( FT_Library library, FT_Outline * outline ); Destroy an outline created with FT_Outline_New . input library A handle of the library object used to allocate the outline. outline A pointer to the outline object to be discarded. return FreeType error code. 0 means success. note If the outline's \u2018owner\u2019 field is not set, only the outline descriptor will be released. FT_Outline_Copy \u00b6 Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_Copy ( const FT_Outline * source, FT_Outline *target ); Copy an outline into another one. Both objects must have the same sizes (number of points & number of contours) when this function is called. input source A handle to the source outline. output target A handle to the target outline. return FreeType error code. 0 means success. FT_Outline_Translate \u00b6 Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( void ) FT_Outline_Translate ( const FT_Outline * outline, FT_Pos xOffset, FT_Pos yOffset ); Apply a simple translation to the points of an outline. inout outline A pointer to the target outline descriptor. input xOffset The horizontal offset. yOffset The vertical offset. FT_Outline_Transform \u00b6 Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( void ) FT_Outline_Transform ( const FT_Outline * outline, const FT_Matrix * matrix ); Apply a simple 2x2 matrix to all of an outline's points. Useful for applying rotations, slanting, flipping, etc. inout outline A pointer to the target outline descriptor. input matrix A pointer to the transformation matrix. note You can use FT_Outline_Translate if you need to translate the outline's points. FT_Outline_Embolden \u00b6 Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_Embolden ( FT_Outline * outline, FT_Pos strength ); Embolden an outline. The new outline will be at most 4 times strength pixels wider and higher. You may think of the left and bottom borders as unchanged. Negative strength values to reduce the outline thickness are possible also. inout outline A handle to the target outline. input strength How strong the glyph is emboldened. Expressed in 26.6 pixel format. return FreeType error code. 0 means success. note The used algorithm to increase or decrease the thickness of the glyph doesn't change the number of points; this means that certain situations like acute angles or intersections are sometimes handled incorrectly. If you need \u2018better\u2019 metrics values you should call FT_Outline_Get_CBox or FT_Outline_Get_BBox . To get meaningful results, font scaling values must be set with functions like FT_Set_Char_Size before calling FT_Render_Glyph. example FT_Load_Glyph( face, index, FT_LOAD_DEFAULT ); if ( face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ) FT_Outline_Embolden( &face->glyph->outline, strength ); FT_Outline_EmboldenXY \u00b6 Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_EmboldenXY ( FT_Outline * outline, FT_Pos xstrength, FT_Pos ystrength ); Embolden an outline. The new outline will be xstrength pixels wider and ystrength pixels higher. Otherwise, it is similar to FT_Outline_Embolden , which uses the same strength in both directions. since 2.4.10 FT_Outline_Reverse \u00b6 Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( void ) FT_Outline_Reverse ( FT_Outline * outline ); Reverse the drawing direction of an outline. This is used to ensure consistent fill conventions for mirrored glyphs. inout outline A pointer to the target outline descriptor. note This function toggles the bit flag FT_OUTLINE_REVERSE_FILL in the outline's flags field. It shouldn't be used by a normal client application, unless it knows what it is doing. FT_Outline_Check \u00b6 Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_Check ( FT_Outline * outline ); Check the contents of an outline descriptor. input outline A handle to a source outline. return FreeType error code. 0 means success. note An empty outline, or an outline with a single point only is also valid. FT_Outline_Get_CBox \u00b6 Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( void ) FT_Outline_Get_CBox ( const FT_Outline * outline, FT_BBox *acbox ); Return an outline's \u2018control box\u2019. The control box encloses all the outline's points, including Bezier control points. Though it coincides with the exact bounding box for most glyphs, it can be slightly larger in some situations (like when rotating an outline that contains Bezier outside arcs). Computing the control box is very fast, while getting the bounding box can take much more time as it needs to walk over all segments and arcs in the outline. To get the latter, you can use the \u2018ftbbox\u2019 component, which is dedicated to this single task. input outline A pointer to the source outline descriptor. output acbox The outline's control box. note See FT_Glyph_Get_CBox for a discussion of tricky fonts. FT_Outline_Get_BBox \u00b6 Defined in FT_BBOX_H (freetype/ftbbox.h). FT_EXPORT( FT_Error ) FT_Outline_Get_BBox ( FT_Outline * outline, FT_BBox *abbox ); Compute the exact bounding box of an outline. This is slower than computing the control box. However, it uses an advanced algorithm that returns very quickly when the two boxes coincide. Otherwise, the outline Bezier arcs are traversed to extract their extrema. input outline A pointer to the source outline. output abbox The outline's exact bounding box. return FreeType error code. 0 means success. note If the font is tricky and the glyph has been loaded with FT_LOAD_NO_SCALE , the resulting BBox is meaningless. To get reasonable values for the BBox it is necessary to load the glyph at a large ppem value (so that the hinting instructions can properly shift and scale the subglyphs), then extracting the BBox, which can be eventually converted back to font units. FT_Outline_Get_Bitmap \u00b6 Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_Get_Bitmap ( FT_Library library, FT_Outline * outline, const FT_Bitmap *abitmap ); Render an outline within a bitmap. The outline's image is simply OR-ed to the target bitmap. input library A handle to a FreeType library object. outline A pointer to the source outline descriptor. inout abitmap A pointer to the target bitmap descriptor. return FreeType error code. 0 means success. note This function does not create the bitmap, it only renders an outline image within the one you pass to it! Consequently, the various fields in abitmap should be set accordingly. It will use the raster corresponding to the default glyph format. The value of the num_grays field in abitmap is ignored. If you select the gray-level rasterizer, and you want less than 256 gray levels, you have to use FT_Outline_Render directly. FT_Outline_Render \u00b6 Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_Render ( FT_Library library, FT_Outline * outline, FT_Raster_Params * params ); Render an outline within a bitmap using the current scan-convert. input library A handle to a FreeType library object. outline A pointer to the source outline descriptor. inout params A pointer to an FT_Raster_Params structure used to describe the rendering operation. return FreeType error code. 0 means success. note This advanced function uses FT_Raster_Params as an argument. The field params.source will be set to outline before the scan converter is called, which means that the value you give to it is actually ignored. Either params.target must point to preallocated bitmap, or FT_RASTER_FLAG_DIRECT must be set in params.flags allowing FreeType rasterizer to be used for direct composition, translucency, etc. See FT_Raster_Params for more details. FT_Outline_Decompose \u00b6 Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_Decompose ( FT_Outline * outline, const FT_Outline_Funcs * func_interface, void * user ); Walk over an outline's structure to decompose it into individual segments and Bezier arcs. This function also emits \u2018move to\u2019 operations to indicate the start of new contours in the outline. input outline A pointer to the source target. func_interface A table of \u2018emitters\u2019, i.e., function pointers called during decomposition to indicate path operations. inout user A typeless pointer that is passed to each emitter during the decomposition. It can be used to store the state during the decomposition. return FreeType error code. 0 means success. note A contour that contains a single point only is represented by a \u2018move to\u2019 operation followed by \u2018line to\u2019 to the same point. In most cases, it is best to filter this out before using the outline for stroking purposes (otherwise it would result in a visible dot when round caps are used). Similarly, the function returns success for an empty outline also (doing nothing, this is, not calling any emitter); if necessary, you should filter this out, too. FT_Outline_Funcs \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_Outline_Funcs_ { FT_Outline_MoveToFunc move_to; FT_Outline_LineToFunc line_to; FT_Outline_ConicToFunc conic_to; FT_Outline_CubicToFunc cubic_to; int shift; FT_Pos delta; } FT_Outline_Funcs ; A structure to hold various function pointers used during outline decomposition in order to emit segments, conic, and cubic Beziers. fields move_to The \u2018move to\u2019 emitter. line_to The segment emitter. conic_to The second-order Bezier arc emitter. cubic_to The third-order Bezier arc emitter. shift The shift that is applied to coordinates before they are sent to the emitter. delta The delta that is applied to coordinates before they are sent to the emitter, but after the shift. note The point coordinates sent to the emitters are the transformed version of the original coordinates (this is important for high accuracy during scan-conversion). The transformation is simple: x' = (x << shift) - delta y' = (y << shift) - delta Set the values of shift and delta to 0 to get the original point coordinates. FT_Outline_MoveToFunc \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Outline_MoveToFunc )( const FT_Vector * to, void * user ); # define FT_Outline_MoveTo_Func FT_Outline_MoveToFunc A function pointer type used to describe the signature of a \u2018move to\u2019 function during outline walking/decomposition. A \u2018move to\u2019 is emitted to start a new contour in an outline. input to A pointer to the target point of the \u2018move to\u2019. user A typeless pointer, which is passed from the caller of the decomposition function. return Error code. 0 means success. FT_Outline_LineToFunc \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Outline_LineToFunc )( const FT_Vector * to, void * user ); # define FT_Outline_LineTo_Func FT_Outline_LineToFunc A function pointer type used to describe the signature of a \u2018line to\u2019 function during outline walking/decomposition. A \u2018line to\u2019 is emitted to indicate a segment in the outline. input to A pointer to the target point of the \u2018line to\u2019. user A typeless pointer, which is passed from the caller of the decomposition function. return Error code. 0 means success. FT_Outline_ConicToFunc \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Outline_ConicToFunc )( const FT_Vector * control, const FT_Vector * to, void * user ); # define FT_Outline_ConicTo_Func FT_Outline_ConicToFunc A function pointer type used to describe the signature of a \u2018conic to\u2019 function during outline walking or decomposition. A \u2018conic to\u2019 is emitted to indicate a second-order Bezier arc in the outline. input control An intermediate control point between the last position and the new target in to . to A pointer to the target end point of the conic arc. user A typeless pointer, which is passed from the caller of the decomposition function. return Error code. 0 means success. FT_Outline_CubicToFunc \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Outline_CubicToFunc )( const FT_Vector * control1, const FT_Vector * control2, const FT_Vector * to, void * user ); # define FT_Outline_CubicTo_Func FT_Outline_CubicToFunc A function pointer type used to describe the signature of a \u2018cubic to\u2019 function during outline walking or decomposition. A \u2018cubic to\u2019 is emitted to indicate a third-order Bezier arc. input control1 A pointer to the first Bezier control point. control2 A pointer to the second Bezier control point. to A pointer to the target end point. user A typeless pointer, which is passed from the caller of the decomposition function. return Error code. 0 means success. FT_Orientation \u00b6 Defined in FT_OUTLINE_H (freetype/ftoutln.h). typedef enum FT_Orientation_ { FT_ORIENTATION_TRUETYPE = 0, FT_ORIENTATION_POSTSCRIPT = 1, FT_ORIENTATION_FILL_RIGHT = FT_ORIENTATION_TRUETYPE , FT_ORIENTATION_FILL_LEFT = FT_ORIENTATION_POSTSCRIPT , FT_ORIENTATION_NONE } FT_Orientation ; A list of values used to describe an outline's contour orientation. The TrueType and PostScript specifications use different conventions to determine whether outline contours should be filled or unfilled. values FT_ORIENTATION_TRUETYPE According to the TrueType specification, clockwise contours must be filled, and counter-clockwise ones must be unfilled. FT_ORIENTATION_POSTSCRIPT According to the PostScript specification, counter-clockwise contours must be filled, and clockwise ones must be unfilled. FT_ORIENTATION_FILL_RIGHT This is identical to FT_ORIENTATION_TRUETYPE , but is used to remember that in TrueType, everything that is to the right of the drawing direction of a contour must be filled. FT_ORIENTATION_FILL_LEFT This is identical to FT_ORIENTATION_POSTSCRIPT , but is used to remember that in PostScript, everything that is to the left of the drawing direction of a contour must be filled. FT_ORIENTATION_NONE The orientation cannot be determined. That is, different parts of the glyph have different orientation. FT_Outline_Get_Orientation \u00b6 Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Orientation ) FT_Outline_Get_Orientation ( FT_Outline * outline ); This function analyzes a glyph outline and tries to compute its fill orientation (see FT_Orientation ). This is done by integrating the total area covered by the outline. The positive integral corresponds to the clockwise orientation and FT_ORIENTATION_POSTSCRIPT is returned. The negative integral corresponds to the counter-clockwise orientation and FT_ORIENTATION_TRUETYPE is returned. Note that this will return FT_ORIENTATION_TRUETYPE for empty outlines. input outline A handle to the source outline. return The orientation. FT_OUTLINE_XXX \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). # define FT_OUTLINE_NONE 0x0 # define FT_OUTLINE_OWNER 0x1 # define FT_OUTLINE_EVEN_ODD_FILL 0x2 # define FT_OUTLINE_REVERSE_FILL 0x4 # define FT_OUTLINE_IGNORE_DROPOUTS 0x8 # define FT_OUTLINE_SMART_DROPOUTS 0x10 # define FT_OUTLINE_INCLUDE_STUBS 0x20 # define FT_OUTLINE_OVERLAP 0x40 # define FT_OUTLINE_HIGH_PRECISION 0x100 # define FT_OUTLINE_SINGLE_PASS 0x200 /* these constants are deprecated; use the corresponding */ /* ` FT_OUTLINE_XXX ` values instead */ # define ft_outline_none FT_OUTLINE_NONE # define ft_outline_owner FT_OUTLINE_OWNER # define ft_outline_even_odd_fill FT_OUTLINE_EVEN_ODD_FILL # define ft_outline_reverse_fill FT_OUTLINE_REVERSE_FILL # define ft_outline_ignore_dropouts FT_OUTLINE_IGNORE_DROPOUTS # define ft_outline_high_precision FT_OUTLINE_HIGH_PRECISION # define ft_outline_single_pass FT_OUTLINE_SINGLE_PASS A list of bit-field constants used for the flags in an outline's flags field. values FT_OUTLINE_NONE Value 0 is reserved. FT_OUTLINE_OWNER If set, this flag indicates that the outline's field arrays (i.e., points , flags , and contours ) are \u2018owned\u2019 by the outline object, and should thus be freed when it is destroyed. FT_OUTLINE_EVEN_ODD_FILL By default, outlines are filled using the non-zero winding rule. If set to 1, the outline will be filled using the even-odd fill rule (only works with the smooth rasterizer). FT_OUTLINE_REVERSE_FILL By default, outside contours of an outline are oriented in clock-wise direction, as defined in the TrueType specification. This flag is set if the outline uses the opposite direction (typically for Type 1 fonts). This flag is ignored by the scan converter. FT_OUTLINE_IGNORE_DROPOUTS By default, the scan converter will try to detect drop-outs in an outline and correct the glyph bitmap to ensure consistent shape continuity. If set, this flag hints the scan-line converter to ignore such cases. See below for more information. FT_OUTLINE_SMART_DROPOUTS Select smart dropout control. If unset, use simple dropout control. Ignored if FT_OUTLINE_IGNORE_DROPOUTS is set. See below for more information. FT_OUTLINE_INCLUDE_STUBS If set, turn pixels on for \u2018stubs\u2019, otherwise exclude them. Ignored if FT_OUTLINE_IGNORE_DROPOUTS is set. See below for more information. FT_OUTLINE_OVERLAP This flag indicates that this outline contains overlapping contrours and the anti-aliased renderer should perform oversampling to mitigate possible artifacts. This flag should not be set for well designed glyphs without overlaps because it quadruples the rendering time. FT_OUTLINE_HIGH_PRECISION This flag indicates that the scan-line converter should try to convert this outline to bitmaps with the highest possible quality. It is typically set for small character sizes. Note that this is only a hint that might be completely ignored by a given scan-converter. FT_OUTLINE_SINGLE_PASS This flag is set to force a given scan-converter to only use a single pass over the outline to render a bitmap glyph image. Normally, it is set for very large character sizes. It is only a hint that might be completely ignored by a given scan-converter. note The flags FT_OUTLINE_IGNORE_DROPOUTS , FT_OUTLINE_SMART_DROPOUTS , and FT_OUTLINE_INCLUDE_STUBS are ignored by the smooth rasterizer. There exists a second mechanism to pass the drop-out mode to the B/W rasterizer; see the tags field in FT_Outline . Please refer to the description of the \u2018SCANTYPE\u2019 instruction in the OpenType specification (in file ttinst1.doc ) how simple drop-outs, smart drop-outs, and stubs are defined.","title":"Outline Processing"},{"location":"ft2-outline_processing.html#outline-processing","text":"","title":"Outline Processing"},{"location":"ft2-outline_processing.html#synopsis","text":"This section contains routines used to create and destroy scalable glyph images known as \u2018outlines\u2019. These can also be measured, transformed, and converted into bitmaps and pixmaps.","title":"Synopsis"},{"location":"ft2-outline_processing.html#ft_outline","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_Outline_ { short n_contours; /* number of contours in glyph */ short n_points; /* number of points in the glyph */ FT_Vector * points; /* the outline's points */ char * tags; /* the points flags */ short * contours; /* the contour end points */ int flags; /* outline masks */ } FT_Outline ; This structure is used to describe an outline to the scan-line converter.","title":"FT_Outline"},{"location":"ft2-outline_processing.html#ft_outline_new","text":"Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_New ( FT_Library library, FT_UInt numPoints, FT_Int numContours, FT_Outline *anoutline ); Create a new outline of a given size.","title":"FT_Outline_New"},{"location":"ft2-outline_processing.html#ft_outline_done","text":"Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_Done ( FT_Library library, FT_Outline * outline ); Destroy an outline created with FT_Outline_New .","title":"FT_Outline_Done"},{"location":"ft2-outline_processing.html#ft_outline_copy","text":"Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_Copy ( const FT_Outline * source, FT_Outline *target ); Copy an outline into another one. Both objects must have the same sizes (number of points & number of contours) when this function is called.","title":"FT_Outline_Copy"},{"location":"ft2-outline_processing.html#ft_outline_translate","text":"Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( void ) FT_Outline_Translate ( const FT_Outline * outline, FT_Pos xOffset, FT_Pos yOffset ); Apply a simple translation to the points of an outline.","title":"FT_Outline_Translate"},{"location":"ft2-outline_processing.html#ft_outline_transform","text":"Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( void ) FT_Outline_Transform ( const FT_Outline * outline, const FT_Matrix * matrix ); Apply a simple 2x2 matrix to all of an outline's points. Useful for applying rotations, slanting, flipping, etc.","title":"FT_Outline_Transform"},{"location":"ft2-outline_processing.html#ft_outline_embolden","text":"Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_Embolden ( FT_Outline * outline, FT_Pos strength ); Embolden an outline. The new outline will be at most 4 times strength pixels wider and higher. You may think of the left and bottom borders as unchanged. Negative strength values to reduce the outline thickness are possible also.","title":"FT_Outline_Embolden"},{"location":"ft2-outline_processing.html#ft_outline_emboldenxy","text":"Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_EmboldenXY ( FT_Outline * outline, FT_Pos xstrength, FT_Pos ystrength ); Embolden an outline. The new outline will be xstrength pixels wider and ystrength pixels higher. Otherwise, it is similar to FT_Outline_Embolden , which uses the same strength in both directions.","title":"FT_Outline_EmboldenXY"},{"location":"ft2-outline_processing.html#ft_outline_reverse","text":"Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( void ) FT_Outline_Reverse ( FT_Outline * outline ); Reverse the drawing direction of an outline. This is used to ensure consistent fill conventions for mirrored glyphs.","title":"FT_Outline_Reverse"},{"location":"ft2-outline_processing.html#ft_outline_check","text":"Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_Check ( FT_Outline * outline ); Check the contents of an outline descriptor.","title":"FT_Outline_Check"},{"location":"ft2-outline_processing.html#ft_outline_get_cbox","text":"Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( void ) FT_Outline_Get_CBox ( const FT_Outline * outline, FT_BBox *acbox ); Return an outline's \u2018control box\u2019. The control box encloses all the outline's points, including Bezier control points. Though it coincides with the exact bounding box for most glyphs, it can be slightly larger in some situations (like when rotating an outline that contains Bezier outside arcs). Computing the control box is very fast, while getting the bounding box can take much more time as it needs to walk over all segments and arcs in the outline. To get the latter, you can use the \u2018ftbbox\u2019 component, which is dedicated to this single task.","title":"FT_Outline_Get_CBox"},{"location":"ft2-outline_processing.html#ft_outline_get_bbox","text":"Defined in FT_BBOX_H (freetype/ftbbox.h). FT_EXPORT( FT_Error ) FT_Outline_Get_BBox ( FT_Outline * outline, FT_BBox *abbox ); Compute the exact bounding box of an outline. This is slower than computing the control box. However, it uses an advanced algorithm that returns very quickly when the two boxes coincide. Otherwise, the outline Bezier arcs are traversed to extract their extrema.","title":"FT_Outline_Get_BBox"},{"location":"ft2-outline_processing.html#ft_outline_get_bitmap","text":"Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_Get_Bitmap ( FT_Library library, FT_Outline * outline, const FT_Bitmap *abitmap ); Render an outline within a bitmap. The outline's image is simply OR-ed to the target bitmap.","title":"FT_Outline_Get_Bitmap"},{"location":"ft2-outline_processing.html#ft_outline_render","text":"Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_Render ( FT_Library library, FT_Outline * outline, FT_Raster_Params * params ); Render an outline within a bitmap using the current scan-convert.","title":"FT_Outline_Render"},{"location":"ft2-outline_processing.html#ft_outline_decompose","text":"Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Error ) FT_Outline_Decompose ( FT_Outline * outline, const FT_Outline_Funcs * func_interface, void * user ); Walk over an outline's structure to decompose it into individual segments and Bezier arcs. This function also emits \u2018move to\u2019 operations to indicate the start of new contours in the outline.","title":"FT_Outline_Decompose"},{"location":"ft2-outline_processing.html#ft_outline_funcs","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_Outline_Funcs_ { FT_Outline_MoveToFunc move_to; FT_Outline_LineToFunc line_to; FT_Outline_ConicToFunc conic_to; FT_Outline_CubicToFunc cubic_to; int shift; FT_Pos delta; } FT_Outline_Funcs ; A structure to hold various function pointers used during outline decomposition in order to emit segments, conic, and cubic Beziers.","title":"FT_Outline_Funcs"},{"location":"ft2-outline_processing.html#ft_outline_movetofunc","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Outline_MoveToFunc )( const FT_Vector * to, void * user ); # define FT_Outline_MoveTo_Func FT_Outline_MoveToFunc A function pointer type used to describe the signature of a \u2018move to\u2019 function during outline walking/decomposition. A \u2018move to\u2019 is emitted to start a new contour in an outline.","title":"FT_Outline_MoveToFunc"},{"location":"ft2-outline_processing.html#ft_outline_linetofunc","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Outline_LineToFunc )( const FT_Vector * to, void * user ); # define FT_Outline_LineTo_Func FT_Outline_LineToFunc A function pointer type used to describe the signature of a \u2018line to\u2019 function during outline walking/decomposition. A \u2018line to\u2019 is emitted to indicate a segment in the outline.","title":"FT_Outline_LineToFunc"},{"location":"ft2-outline_processing.html#ft_outline_conictofunc","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Outline_ConicToFunc )( const FT_Vector * control, const FT_Vector * to, void * user ); # define FT_Outline_ConicTo_Func FT_Outline_ConicToFunc A function pointer type used to describe the signature of a \u2018conic to\u2019 function during outline walking or decomposition. A \u2018conic to\u2019 is emitted to indicate a second-order Bezier arc in the outline.","title":"FT_Outline_ConicToFunc"},{"location":"ft2-outline_processing.html#ft_outline_cubictofunc","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Outline_CubicToFunc )( const FT_Vector * control1, const FT_Vector * control2, const FT_Vector * to, void * user ); # define FT_Outline_CubicTo_Func FT_Outline_CubicToFunc A function pointer type used to describe the signature of a \u2018cubic to\u2019 function during outline walking or decomposition. A \u2018cubic to\u2019 is emitted to indicate a third-order Bezier arc.","title":"FT_Outline_CubicToFunc"},{"location":"ft2-outline_processing.html#ft_orientation","text":"Defined in FT_OUTLINE_H (freetype/ftoutln.h). typedef enum FT_Orientation_ { FT_ORIENTATION_TRUETYPE = 0, FT_ORIENTATION_POSTSCRIPT = 1, FT_ORIENTATION_FILL_RIGHT = FT_ORIENTATION_TRUETYPE , FT_ORIENTATION_FILL_LEFT = FT_ORIENTATION_POSTSCRIPT , FT_ORIENTATION_NONE } FT_Orientation ; A list of values used to describe an outline's contour orientation. The TrueType and PostScript specifications use different conventions to determine whether outline contours should be filled or unfilled.","title":"FT_Orientation"},{"location":"ft2-outline_processing.html#ft_outline_get_orientation","text":"Defined in FT_OUTLINE_H (freetype/ftoutln.h). FT_EXPORT( FT_Orientation ) FT_Outline_Get_Orientation ( FT_Outline * outline ); This function analyzes a glyph outline and tries to compute its fill orientation (see FT_Orientation ). This is done by integrating the total area covered by the outline. The positive integral corresponds to the clockwise orientation and FT_ORIENTATION_POSTSCRIPT is returned. The negative integral corresponds to the counter-clockwise orientation and FT_ORIENTATION_TRUETYPE is returned. Note that this will return FT_ORIENTATION_TRUETYPE for empty outlines.","title":"FT_Outline_Get_Orientation"},{"location":"ft2-outline_processing.html#ft_outline_xxx","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). # define FT_OUTLINE_NONE 0x0 # define FT_OUTLINE_OWNER 0x1 # define FT_OUTLINE_EVEN_ODD_FILL 0x2 # define FT_OUTLINE_REVERSE_FILL 0x4 # define FT_OUTLINE_IGNORE_DROPOUTS 0x8 # define FT_OUTLINE_SMART_DROPOUTS 0x10 # define FT_OUTLINE_INCLUDE_STUBS 0x20 # define FT_OUTLINE_OVERLAP 0x40 # define FT_OUTLINE_HIGH_PRECISION 0x100 # define FT_OUTLINE_SINGLE_PASS 0x200 /* these constants are deprecated; use the corresponding */ /* ` FT_OUTLINE_XXX ` values instead */ # define ft_outline_none FT_OUTLINE_NONE # define ft_outline_owner FT_OUTLINE_OWNER # define ft_outline_even_odd_fill FT_OUTLINE_EVEN_ODD_FILL # define ft_outline_reverse_fill FT_OUTLINE_REVERSE_FILL # define ft_outline_ignore_dropouts FT_OUTLINE_IGNORE_DROPOUTS # define ft_outline_high_precision FT_OUTLINE_HIGH_PRECISION # define ft_outline_single_pass FT_OUTLINE_SINGLE_PASS A list of bit-field constants used for the flags in an outline's flags field.","title":"FT_OUTLINE_XXX"},{"location":"ft2-parameter_tags.html","text":"FreeType \u00bb Docs \u00bb Controlling FreeType Modules \u00bb Parameter Tags Parameter Tags \u00b6 Synopsis \u00b6 This section contains macros for the FT_Parameter structure that are used with various functions to activate some special functionality or different behaviour of various components of FreeType. FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY \u00b6 # define FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY \\ FT_MAKE_TAG ( 'i', 'g', 'p', 'f' ) /* this constant is deprecated */ # define FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY \\ FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY A tag for FT_Parameter to make FT_Open_Face ignore typographic family names in the \u2018name\u2019 table (introduced in OpenType version 1.4). Use this for backward compatibility with legacy systems that have a four-faces-per-family restriction. since 2.8 FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY \u00b6 # define FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY \\ FT_MAKE_TAG ( 'i', 'g', 'p', 's' ) /* this constant is deprecated */ # define FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY \\ FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY A tag for FT_Parameter to make FT_Open_Face ignore typographic subfamily names in the \u2018name\u2019 table (introduced in OpenType version 1.4). Use this for backward compatibility with legacy systems that have a four-faces-per-family restriction. since 2.8 FT_PARAM_TAG_INCREMENTAL \u00b6 # define FT_PARAM_TAG_INCREMENTAL \\ FT_MAKE_TAG ( 'i', 'n', 'c', 'r' ) An FT_Parameter tag to be used with FT_Open_Face to indicate incremental glyph loading. FT_PARAM_TAG_LCD_FILTER_WEIGHTS \u00b6 # define FT_PARAM_TAG_LCD_FILTER_WEIGHTS \\ FT_MAKE_TAG ( 'l', 'c', 'd', 'f' ) An FT_Parameter tag to be used with FT_Face_Properties . The corresponding argument specifies the five LCD filter weights for a given face (if using FT_LOAD_TARGET_LCD , for example), overriding the global default values or the values set up with FT_Library_SetLcdFilterWeights . since 2.8 FT_PARAM_TAG_RANDOM_SEED \u00b6 # define FT_PARAM_TAG_RANDOM_SEED \\ FT_MAKE_TAG ( 's', 'e', 'e', 'd' ) An FT_Parameter tag to be used with FT_Face_Properties . The corresponding 32bit signed integer argument overrides the font driver's random seed value with a face-specific one; see random-seed . since 2.8 FT_PARAM_TAG_STEM_DARKENING \u00b6 # define FT_PARAM_TAG_STEM_DARKENING \\ FT_MAKE_TAG ( 'd', 'a', 'r', 'k' ) An FT_Parameter tag to be used with FT_Face_Properties . The corresponding Boolean argument specifies whether to apply stem darkening, overriding the global default values or the values set up with FT_Property_Set (see no-stem-darkening ). This is a passive setting that only takes effect if the font driver or autohinter honors it, which the CFF, Type 1, and CID drivers always do, but the autohinter only in \u2018light\u2019 hinting mode (as of version 2.9). since 2.8 FT_PARAM_TAG_UNPATENTED_HINTING \u00b6 # define FT_PARAM_TAG_UNPATENTED_HINTING \\ FT_MAKE_TAG ( 'u', 'n', 'p', 'a' ) Deprecated, no effect. Previously: A constant used as the tag of an FT_Parameter structure to indicate that unpatented methods only should be used by the TrueType bytecode interpreter for a typeface opened by FT_Open_Face .","title":"Parameter Tags"},{"location":"ft2-parameter_tags.html#parameter-tags","text":"","title":"Parameter Tags"},{"location":"ft2-parameter_tags.html#synopsis","text":"This section contains macros for the FT_Parameter structure that are used with various functions to activate some special functionality or different behaviour of various components of FreeType.","title":"Synopsis"},{"location":"ft2-parameter_tags.html#ft_param_tag_ignore_typographic_family","text":"# define FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY \\ FT_MAKE_TAG ( 'i', 'g', 'p', 'f' ) /* this constant is deprecated */ # define FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY \\ FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY A tag for FT_Parameter to make FT_Open_Face ignore typographic family names in the \u2018name\u2019 table (introduced in OpenType version 1.4). Use this for backward compatibility with legacy systems that have a four-faces-per-family restriction.","title":"FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY"},{"location":"ft2-parameter_tags.html#ft_param_tag_ignore_typographic_subfamily","text":"# define FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY \\ FT_MAKE_TAG ( 'i', 'g', 'p', 's' ) /* this constant is deprecated */ # define FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY \\ FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY A tag for FT_Parameter to make FT_Open_Face ignore typographic subfamily names in the \u2018name\u2019 table (introduced in OpenType version 1.4). Use this for backward compatibility with legacy systems that have a four-faces-per-family restriction.","title":"FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY"},{"location":"ft2-parameter_tags.html#ft_param_tag_incremental","text":"# define FT_PARAM_TAG_INCREMENTAL \\ FT_MAKE_TAG ( 'i', 'n', 'c', 'r' ) An FT_Parameter tag to be used with FT_Open_Face to indicate incremental glyph loading.","title":"FT_PARAM_TAG_INCREMENTAL"},{"location":"ft2-parameter_tags.html#ft_param_tag_lcd_filter_weights","text":"# define FT_PARAM_TAG_LCD_FILTER_WEIGHTS \\ FT_MAKE_TAG ( 'l', 'c', 'd', 'f' ) An FT_Parameter tag to be used with FT_Face_Properties . The corresponding argument specifies the five LCD filter weights for a given face (if using FT_LOAD_TARGET_LCD , for example), overriding the global default values or the values set up with FT_Library_SetLcdFilterWeights .","title":"FT_PARAM_TAG_LCD_FILTER_WEIGHTS"},{"location":"ft2-parameter_tags.html#ft_param_tag_random_seed","text":"# define FT_PARAM_TAG_RANDOM_SEED \\ FT_MAKE_TAG ( 's', 'e', 'e', 'd' ) An FT_Parameter tag to be used with FT_Face_Properties . The corresponding 32bit signed integer argument overrides the font driver's random seed value with a face-specific one; see random-seed .","title":"FT_PARAM_TAG_RANDOM_SEED"},{"location":"ft2-parameter_tags.html#ft_param_tag_stem_darkening","text":"# define FT_PARAM_TAG_STEM_DARKENING \\ FT_MAKE_TAG ( 'd', 'a', 'r', 'k' ) An FT_Parameter tag to be used with FT_Face_Properties . The corresponding Boolean argument specifies whether to apply stem darkening, overriding the global default values or the values set up with FT_Property_Set (see no-stem-darkening ). This is a passive setting that only takes effect if the font driver or autohinter honors it, which the CFF, Type 1, and CID drivers always do, but the autohinter only in \u2018light\u2019 hinting mode (as of version 2.9).","title":"FT_PARAM_TAG_STEM_DARKENING"},{"location":"ft2-parameter_tags.html#ft_param_tag_unpatented_hinting","text":"# define FT_PARAM_TAG_UNPATENTED_HINTING \\ FT_MAKE_TAG ( 'u', 'n', 'p', 'a' ) Deprecated, no effect. Previously: A constant used as the tag of an FT_Parameter structure to indicate that unpatented methods only should be used by the TrueType bytecode interpreter for a typeface opened by FT_Open_Face .","title":"FT_PARAM_TAG_UNPATENTED_HINTING"},{"location":"ft2-pcf_driver.html","text":"FreeType \u00bb Docs \u00bb Controlling FreeType Modules \u00bb The PCF driver The PCF driver \u00b6 Synopsis \u00b6 While FreeType's PCF driver doesn't expose API functions by itself, it is possible to control its behaviour with FT_Property_Set and FT_Property_Get . Right now, there is a single property no-long-family-names available if FreeType is compiled with PCF_CONFIG_OPTION_LONG_FAMILY_NAMES. The PCF driver's module name is \u2018pcf\u2019.","title":"The PCF driver"},{"location":"ft2-pcf_driver.html#the-pcf-driver","text":"","title":"The PCF driver"},{"location":"ft2-pcf_driver.html#synopsis","text":"While FreeType's PCF driver doesn't expose API functions by itself, it is possible to control its behaviour with FT_Property_Set and FT_Property_Get . Right now, there is a single property no-long-family-names available if FreeType is compiled with PCF_CONFIG_OPTION_LONG_FAMILY_NAMES. The PCF driver's module name is \u2018pcf\u2019.","title":"Synopsis"},{"location":"ft2-pfr_fonts.html","text":"FreeType \u00bb Docs \u00bb Format-Specific API \u00bb PFR Fonts PFR Fonts \u00b6 Synopsis \u00b6 This section contains the declaration of PFR-specific functions. FT_Get_PFR_Metrics \u00b6 Defined in FT_PFR_H (freetype/ftpfr.h). FT_EXPORT( FT_Error ) FT_Get_PFR_Metrics ( FT_Face face, FT_UInt *aoutline_resolution, FT_UInt *ametrics_resolution, FT_Fixed *ametrics_x_scale, FT_Fixed *ametrics_y_scale ); Return the outline and metrics resolutions of a given PFR face. input face Handle to the input face. It can be a non-PFR face. output aoutline_resolution Outline resolution. This is equivalent to face->units_per_EM for non-PFR fonts. Optional (parameter can be NULL ). ametrics_resolution Metrics resolution. This is equivalent to outline_resolution for non-PFR fonts. Optional (parameter can be NULL ). ametrics_x_scale A 16.16 fixed-point number used to scale distance expressed in metrics units to device subpixels. This is equivalent to face->size->x_scale , but for metrics only. Optional (parameter can be NULL ). ametrics_y_scale Same as ametrics_x_scale but for the vertical direction. optional (parameter can be NULL ). return FreeType error code. 0 means success. note If the input face is not a PFR, this function will return an error. However, in all cases, it will return valid values. FT_Get_PFR_Kerning \u00b6 Defined in FT_PFR_H (freetype/ftpfr.h). FT_EXPORT( FT_Error ) FT_Get_PFR_Kerning ( FT_Face face, FT_UInt left, FT_UInt right, FT_Vector *avector ); Return the kerning pair corresponding to two glyphs in a PFR face. The distance is expressed in metrics units, unlike the result of FT_Get_Kerning . input face A handle to the input face. left Index of the left glyph. right Index of the right glyph. output avector A kerning vector. return FreeType error code. 0 means success. note This function always return distances in original PFR metrics units. This is unlike FT_Get_Kerning with the FT_KERNING_UNSCALED mode, which always returns distances converted to outline units. You can use the value of the x_scale and y_scale parameters returned by FT_Get_PFR_Metrics to scale these to device subpixels. FT_Get_PFR_Advance \u00b6 Defined in FT_PFR_H (freetype/ftpfr.h). FT_EXPORT( FT_Error ) FT_Get_PFR_Advance ( FT_Face face, FT_UInt gindex, FT_Pos *aadvance ); Return a given glyph advance, expressed in original metrics units, from a PFR font. input face A handle to the input face. gindex The glyph index. output aadvance The glyph advance in metrics units. return FreeType error code. 0 means success. note You can use the x_scale or y_scale results of FT_Get_PFR_Metrics to convert the advance to device subpixels (i.e., 1/64 th of pixels).","title":"PFR Fonts"},{"location":"ft2-pfr_fonts.html#pfr-fonts","text":"","title":"PFR Fonts"},{"location":"ft2-pfr_fonts.html#synopsis","text":"This section contains the declaration of PFR-specific functions.","title":"Synopsis"},{"location":"ft2-pfr_fonts.html#ft_get_pfr_metrics","text":"Defined in FT_PFR_H (freetype/ftpfr.h). FT_EXPORT( FT_Error ) FT_Get_PFR_Metrics ( FT_Face face, FT_UInt *aoutline_resolution, FT_UInt *ametrics_resolution, FT_Fixed *ametrics_x_scale, FT_Fixed *ametrics_y_scale ); Return the outline and metrics resolutions of a given PFR face.","title":"FT_Get_PFR_Metrics"},{"location":"ft2-pfr_fonts.html#ft_get_pfr_kerning","text":"Defined in FT_PFR_H (freetype/ftpfr.h). FT_EXPORT( FT_Error ) FT_Get_PFR_Kerning ( FT_Face face, FT_UInt left, FT_UInt right, FT_Vector *avector ); Return the kerning pair corresponding to two glyphs in a PFR face. The distance is expressed in metrics units, unlike the result of FT_Get_Kerning .","title":"FT_Get_PFR_Kerning"},{"location":"ft2-pfr_fonts.html#ft_get_pfr_advance","text":"Defined in FT_PFR_H (freetype/ftpfr.h). FT_EXPORT( FT_Error ) FT_Get_PFR_Advance ( FT_Face face, FT_UInt gindex, FT_Pos *aadvance ); Return a given glyph advance, expressed in original metrics units, from a PFR font.","title":"FT_Get_PFR_Advance"},{"location":"ft2-properties.html","text":"FreeType \u00bb Docs \u00bb Controlling FreeType Modules \u00bb Driver properties Driver properties \u00b6 Synopsis \u00b6 Driver modules can be controlled by setting and unsetting properties, using the functions FT_Property_Set and FT_Property_Get . This section documents the available properties, together with auxiliary macros and structures. FT_HINTING_XXX \u00b6 Defined in FT_DRIVER_H (freetype/ftdriver.h). # define FT_HINTING_FREETYPE 0 # define FT_HINTING_ADOBE 1 /* these constants (introduced in 2.4.12) are deprecated */ # define FT_CFF_HINTING_FREETYPE FT_HINTING_FREETYPE # define FT_CFF_HINTING_ADOBE FT_HINTING_ADOBE A list of constants used for the hinting-engine property to select the hinting engine for CFF, Type 1, and CID fonts. values FT_HINTING_FREETYPE Use the old FreeType hinting engine. FT_HINTING_ADOBE Use the hinting engine contributed by Adobe. since 2.9 hinting-engine \u00b6 Thanks to Adobe, which contributed a new hinting (and parsing) engine, an application can select between \u2018freetype\u2019 and \u2018adobe\u2019 if compiled with CFF_CONFIG_OPTION_OLD_ENGINE . If this configuration macro isn't defined, \u2018hinting-engine\u2019 does nothing. The same holds for the Type 1 and CID modules if compiled with T1_CONFIG_OPTION_OLD_ENGINE . For the \u2018cff\u2019 module, the default engine is \u2018freetype\u2019 if CFF_CONFIG_OPTION_OLD_ENGINE is defined, and \u2018adobe\u2019 otherwise. For both the \u2018type1\u2019 and \u2018t1cid\u2019 modules, the default engine is \u2018freetype\u2019 if T1_CONFIG_OPTION_OLD_ENGINE is defined, and \u2018adobe\u2019 otherwise. note This property can be used with FT_Property_Get also. This property can be set via the FREETYPE_PROPERTIES environment variable (using values \u2018adobe\u2019 or \u2018freetype\u2019). example The following example code demonstrates how to select Adobe's hinting engine for the \u2018cff\u2019 module (omitting the error handling). FT_Library library; FT_UInt hinting_engine = FT_HINTING_ADOBE; FT_Init_FreeType( &library ); FT_Property_Set( library, \"cff\", \"hinting-engine\", &hinting_engine ); since 2.4.12 (for \u2018cff\u2019 module) 2.9 (for \u2018type1\u2019 and \u2018t1cid\u2019 modules) no-stem-darkening \u00b6 All glyphs that pass through the auto-hinter will be emboldened unless this property is set to TRUE. The same is true for the CFF, Type 1, and CID font modules if the \u2018Adobe\u2019 engine is selected (which is the default). Stem darkening emboldens glyphs at smaller sizes to make them more readable on common low-DPI screens when using linear alpha blending and gamma correction, see FT_Render_Glyph . When not using linear alpha blending and gamma correction, glyphs will appear heavy and fuzzy! Gamma correction essentially lightens fonts since shades of grey are shifted to higher pixel values (= higher brightness) to match the original intention to the reality of our screens. The side-effect is that glyphs \u2018thin out\u2019. Mac OS X and Adobe's proprietary font rendering library implement a counter-measure: stem darkening at smaller sizes where shades of gray dominate. By emboldening a glyph slightly in relation to its pixel size, individual pixels get higher coverage of filled-in outlines and are therefore \u2018blacker\u2019. This counteracts the \u2018thinning out\u2019 of glyphs, making text remain readable at smaller sizes. For the auto-hinter, stem-darkening is experimental currently and thus switched off by default (this is, no-stem-darkening is set to TRUE by default). Total consistency with the CFF driver is not achieved right now because the emboldening method differs and glyphs must be scaled down on the Y-axis to keep outline points inside their precomputed blue zones. The smaller the size (especially 9ppem and down), the higher the loss of emboldening versus the CFF driver. Note that stem darkening is never applied if FT_LOAD_NO_SCALE is set. note This property can be used with FT_Property_Get also. This property can be set via the FREETYPE_PROPERTIES environment variable (using values 1 and 0 for \u2018on\u2019 and \u2018off\u2019, respectively). It can also be set per face using FT_Face_Properties with FT_PARAM_TAG_STEM_DARKENING . example FT_Library library; FT_Bool no_stem_darkening = TRUE; FT_Init_FreeType( &library ); FT_Property_Set( library, \"cff\", \"no-stem-darkening\", &no_stem_darkening ); since 2.4.12 (for \u2018cff\u2019 module) 2.6.2 (for \u2018autofitter\u2019 module) 2.9 (for \u2018type1\u2019 and \u2018t1cid\u2019 modules) darkening-parameters \u00b6 By default, the Adobe hinting engine, as used by the CFF, Type 1, and CID font drivers, darkens stems as follows (if the no-stem-darkening property isn't set): stem width <= 0.5px: darkening amount = 0.4px stem width = 1px: darkening amount = 0.275px stem width = 1.667px: darkening amount = 0.275px stem width >= 2.333px: darkening amount = 0px and piecewise linear in-between. At configuration time, these four control points can be set with the macro CFF_CONFIG_OPTION_DARKENING_PARAMETERS ; the CFF, Type 1, and CID drivers share these values. At runtime, the control points can be changed using the darkening-parameters property (see the example below that demonstrates this for the Type 1 driver). The x values give the stem width, and the y values the darkening amount. The unit is 1000 th of pixels. All coordinate values must be positive; the x values must be monotonically increasing; the y values must be monotonically decreasing and smaller than or equal to 500 (corresponding to half a pixel); the slope of each linear piece must be shallower than -1 (e.g., -.4). The auto-hinter provides this property, too, as an experimental feature. See no-stem-darkening for more. note This property can be used with FT_Property_Get also. This property can be set via the FREETYPE_PROPERTIES environment variable, using eight comma-separated integers without spaces. Here the above example, using \\ to break the line for readability. FREETYPE_PROPERTIES=\\ type1:darkening-parameters=500,300,1000,200,1500,100,2000,0 example FT_Library library; FT_Int darken_params[8] = { 500, 300, // x1, y1 1000, 200, // x2, y2 1500, 100, // x3, y3 2000, 0 }; // x4, y4 FT_Init_FreeType( &library ); FT_Property_Set( library, \"type1\", \"darkening-parameters\", darken_params ); since 2.5.1 (for \u2018cff\u2019 module) 2.6.2 (for \u2018autofitter\u2019 module) 2.9 (for \u2018type1\u2019 and \u2018t1cid\u2019 modules) random-seed \u00b6 By default, the seed value for the CFF \u2018random\u2019 operator and the similar \u20180 28 callothersubr pop\u2019 command for the Type 1 and CID drivers is set to a random value. However, mainly for debugging purposes, it is often necessary to use a known value as a seed so that the pseudo-random number sequences generated by \u2018random\u2019 are repeatable. The random-seed property does that. Its argument is a signed 32bit integer; if the value is zero or negative, the seed given by the intitialRandomSeed private DICT operator in a CFF file gets used (or a default value if there is no such operator). If the value is positive, use it instead of initialRandomSeed , which is consequently ignored. note This property can be set via the FREETYPE_PROPERTIES environment variable. It can also be set per face using FT_Face_Properties with FT_PARAM_TAG_RANDOM_SEED . since 2.8 (for \u2018cff\u2019 module) 2.9 (for \u2018type1\u2019 and \u2018t1cid\u2019 modules) no-long-family-names \u00b6 If PCF_CONFIG_OPTION_LONG_FAMILY_NAMES is active while compiling FreeType, the PCF driver constructs long family names. There are many PCF fonts just called \u2018Fixed\u2019 which look completely different, and which have nothing to do with each other. When selecting \u2018Fixed\u2019 in KDE or Gnome one gets results that appear rather random, the style changes often if one changes the size and one cannot select some fonts at all. The improve this situation, the PCF module prepends the foundry name (plus a space) to the family name. It also checks whether there are \u2018wide\u2019 characters; all put together, family names like \u2018Sony Fixed\u2019 or \u2018Misc Fixed Wide\u2019 are constructed. If no-long-family-names is set, this feature gets switched off. note This property can be used with FT_Property_Get also. This property can be set via the FREETYPE_PROPERTIES environment variable (using values 1 and 0 for \u2018on\u2019 and \u2018off\u2019, respectively). example FT_Library library; FT_Bool no_long_family_names = TRUE; FT_Init_FreeType( &library ); FT_Property_Set( library, \"pcf\", \"no-long-family-names\", &no_long_family_names ); since 2.8 TT_INTERPRETER_VERSION_XXX \u00b6 Defined in FT_DRIVER_H (freetype/ftdriver.h). # define TT_INTERPRETER_VERSION_35 35 # define TT_INTERPRETER_VERSION_38 38 # define TT_INTERPRETER_VERSION_40 40 A list of constants used for the interpreter-version property to select the hinting engine for Truetype fonts. The numeric value in the constant names represents the version number as returned by the \u2018GETINFO\u2019 bytecode instruction. values TT_INTERPRETER_VERSION_35 Version 35 corresponds to MS rasterizer v.1.7 as used e.g. in Windows 98; only grayscale and B/W rasterizing is supported. TT_INTERPRETER_VERSION_38 Version 38 corresponds to MS rasterizer v.1.9; it is roughly equivalent to the hinting provided by DirectWrite ClearType (as can be found, for example, in the Internet Explorer 9 running on Windows 7). It is used in FreeType to select the \u2018Infinality\u2019 subpixel hinting code. The code may be removed in a future version. TT_INTERPRETER_VERSION_40 Version 40 corresponds to MS rasterizer v.2.1; it is roughly equivalent to the hinting provided by DirectWrite ClearType (as can be found, for example, in Microsoft's Edge Browser on Windows 10). It is used in FreeType to select the \u2018minimal\u2019 subpixel hinting code, a stripped-down and higher performance version of the \u2018Infinality\u2019 code. note This property controls the behaviour of the bytecode interpreter and thus how outlines get hinted. It does not control how glyph get rasterized! In particular, it does not control subpixel color filtering. If FreeType has not been compiled with the configuration option TT_CONFIG_OPTION_SUBPIXEL_HINTING , selecting version 38 or 40 causes an FT_Err_Unimplemented_Feature error. Depending on the graphics framework, Microsoft uses different bytecode and rendering engines. As a consequence, the version numbers returned by a call to the \u2018GETINFO\u2019 bytecode instruction are more convoluted than desired. Here are two tables that try to shed some light on the possible values for the MS rasterizer engine, together with the additional features introduced by it. GETINFO framework version feature ------------------------------------------------------------------- 3 GDI (Win 3.1), v1.0 16-bit, first version TrueImage 33 GDI (Win NT 3.1), v1.5 32-bit HP Laserjet 34 GDI (Win 95) v1.6 font smoothing, new SCANTYPE opcode 35 GDI (Win 98/2000) v1.7 (UN)SCALED_COMPONENT_OFFSET bits in composite glyphs 36 MGDI (Win CE 2) v1.6+ classic ClearType 37 GDI (XP and later), v1.8 ClearType GDI+ old (before Vista) 38 GDI+ old (Vista, Win 7), v1.9 subpixel ClearType, WPF Y-direction ClearType, additional error checking 39 DWrite (before Win 8) v2.0 subpixel ClearType flags in GETINFO opcode, bug fixes 40 GDI+ (after Win 7), v2.1 Y-direction ClearType flag DWrite (Win 8) in GETINFO opcode, Gray ClearType The \u2018version\u2019 field gives a rough orientation only, since some applications provided certain features much earlier (as an example, Microsoft Reader used subpixel and Y-direction ClearType already in Windows 2000). Similarly, updates to a given framework might include improved hinting support. version sampling rendering comment x y x y -------------------------------------------------------------- v1.0 normal normal B/W B/W bi-level v1.6 high high gray gray grayscale v1.8 high normal color-filter B/W (GDI) ClearType v1.9 high high color-filter gray Color ClearType v2.1 high normal gray B/W Gray ClearType v2.1 high high gray gray Gray ClearType Color and Gray ClearType are the two available variants of \u2018Y-direction ClearType\u2019, meaning grayscale rasterization along the Y-direction; the name used in the TrueType specification for this feature is \u2018symmetric smoothing\u2019. \u2018Classic ClearType\u2019 is the original algorithm used before introducing a modified version in Win XP. Another name for v1.6's grayscale rendering is \u2018font smoothing\u2019, and \u2018Color ClearType\u2019 is sometimes also called \u2018DWrite ClearType\u2019. To differentiate between today's Color ClearType and the earlier ClearType variant with B/W rendering along the vertical axis, the latter is sometimes called \u2018GDI ClearType\u2019. \u2018Normal\u2019 and \u2018high\u2019 sampling describe the (virtual) resolution to access the rasterized outline after the hinting process. \u2018Normal\u2019 means 1 sample per grid line (i.e., B/W). In the current Microsoft implementation, \u2018high\u2019 means an extra virtual resolution of 16x16 (or 16x1) grid lines per pixel for bytecode instructions like \u2018MIRP\u2019. After hinting, these 16 grid lines are mapped to 6x5 (or 6x1) grid lines for color filtering if Color ClearType is activated. Note that \u2018Gray ClearType\u2019 is essentially the same as v1.6's grayscale rendering. However, the GETINFO instruction handles it differently: v1.6 returns bit 12 (hinting for grayscale), while v2.1 returns bits 13 (hinting for ClearType), 18 (symmetrical smoothing), and 19 (Gray ClearType). Also, this mode respects bits 2 and 3 for the version 1 gasp table exclusively (like Color ClearType), while v1.6 only respects the values of version 0 (bits 0 and 1). Keep in mind that the features of the above interpreter versions might not map exactly to FreeType features or behavior because it is a fundamentally different library with different internals. interpreter-version \u00b6 Currently, three versions are available, two representing the bytecode interpreter with subpixel hinting support (old \u2018Infinality\u2019 code and new stripped-down and higher performance \u2018minimal\u2019 code) and one without, respectively. The default is subpixel support if TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined, and no subpixel support otherwise (since it isn't available then). If subpixel hinting is on, many TrueType bytecode instructions behave differently compared to B/W or grayscale rendering (except if \u2018native ClearType\u2019 is selected by the font). Microsoft's main idea is to render at a much increased horizontal resolution, then sampling down the created output to subpixel precision. However, many older fonts are not suited to this and must be specially taken care of by applying (hardcoded) tweaks in Microsoft's interpreter. Details on subpixel hinting and some of the necessary tweaks can be found in Greg Hitchcock's whitepaper at \u2018 https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx \u2019. Note that FreeType currently doesn't really \u2018subpixel hint\u2019 (6x1, 6x2, or 6x5 supersampling) like discussed in the paper. Depending on the chosen interpreter, it simply ignores instructions on vertical stems to arrive at very similar results. note This property can be used with FT_Property_Get also. This property can be set via the FREETYPE_PROPERTIES environment variable (using values \u201835\u2019, \u201838\u2019, or \u201840\u2019). example The following example code demonstrates how to deactivate subpixel hinting (omitting the error handling). FT_Library library; FT_Face face; FT_UInt interpreter_version = TT_INTERPRETER_VERSION_35; FT_Init_FreeType( &library ); FT_Property_Set( library, \"truetype\", \"interpreter-version\", &interpreter_version ); since 2.5 glyph-to-script-map \u00b6 Experimental only The auto-hinter provides various script modules to hint glyphs. Examples of supported scripts are Latin or CJK. Before a glyph is auto-hinted, the Unicode character map of the font gets examined, and the script is then determined based on Unicode character ranges, see below. OpenType fonts, however, often provide much more glyphs than character codes (small caps, superscripts, ligatures, swashes, etc.), to be controlled by so-called \u2018features\u2019. Handling OpenType features can be quite complicated and thus needs a separate library on top of FreeType. The mapping between glyph indices and scripts (in the auto-hinter sense, see the FT_AUTOHINTER_SCRIPT_XXX values) is stored as an array with num_glyphs elements, as found in the font's FT_Face structure. The glyph-to-script-map property returns a pointer to this array, which can be modified as needed. Note that the modification should happen before the first glyph gets processed by the auto-hinter so that the global analysis of the font shapes actually uses the modified mapping. example The following example code demonstrates how to access it (omitting the error handling). FT_Library library; FT_Face face; FT_Prop_GlyphToScriptMap prop; FT_Init_FreeType( &library ); FT_New_Face( library, \"foo.ttf\", 0, &face ); prop.face = face; FT_Property_Get( library, \"autofitter\", \"glyph-to-script-map\", &prop ); // adjust `prop.map' as needed right here FT_Load_Glyph( face, ..., FT_LOAD_FORCE_AUTOHINT ); since 2.4.11 FT_AUTOHINTER_SCRIPT_XXX \u00b6 Defined in FT_DRIVER_H (freetype/ftdriver.h). # define FT_AUTOHINTER_SCRIPT_NONE 0 # define FT_AUTOHINTER_SCRIPT_LATIN 1 # define FT_AUTOHINTER_SCRIPT_CJK 2 # define FT_AUTOHINTER_SCRIPT_INDIC 3 Experimental only A list of constants used for the glyph-to-script-map property to specify the script submodule the auto-hinter should use for hinting a particular glyph. values FT_AUTOHINTER_SCRIPT_NONE Don't auto-hint this glyph. FT_AUTOHINTER_SCRIPT_LATIN Apply the latin auto-hinter. For the auto-hinter, \u2018latin\u2019 is a very broad term, including Cyrillic and Greek also since characters from those scripts share the same design constraints. By default, characters from the following Unicode ranges are assigned to this submodule. U+0020 - U+007F // Basic Latin (no control characters) U+00A0 - U+00FF // Latin-1 Supplement (no control characters) U+0100 - U+017F // Latin Extended-A U+0180 - U+024F // Latin Extended-B U+0250 - U+02AF // IPA Extensions U+02B0 - U+02FF // Spacing Modifier Letters U+0300 - U+036F // Combining Diacritical Marks U+0370 - U+03FF // Greek and Coptic U+0400 - U+04FF // Cyrillic U+0500 - U+052F // Cyrillic Supplement U+1D00 - U+1D7F // Phonetic Extensions U+1D80 - U+1DBF // Phonetic Extensions Supplement U+1DC0 - U+1DFF // Combining Diacritical Marks Supplement U+1E00 - U+1EFF // Latin Extended Additional U+1F00 - U+1FFF // Greek Extended U+2000 - U+206F // General Punctuation U+2070 - U+209F // Superscripts and Subscripts U+20A0 - U+20CF // Currency Symbols U+2150 - U+218F // Number Forms U+2460 - U+24FF // Enclosed Alphanumerics U+2C60 - U+2C7F // Latin Extended-C U+2DE0 - U+2DFF // Cyrillic Extended-A U+2E00 - U+2E7F // Supplemental Punctuation U+A640 - U+A69F // Cyrillic Extended-B U+A720 - U+A7FF // Latin Extended-D U+FB00 - U+FB06 // Alphab. Present. Forms (Latin Ligatures) U+1D400 - U+1D7FF // Mathematical Alphanumeric Symbols U+1F100 - U+1F1FF // Enclosed Alphanumeric Supplement FT_AUTOHINTER_SCRIPT_CJK Apply the CJK auto-hinter, covering Chinese, Japanese, Korean, old Vietnamese, and some other scripts. By default, characters from the following Unicode ranges are assigned to this submodule. U+1100 - U+11FF // Hangul Jamo U+2E80 - U+2EFF // CJK Radicals Supplement U+2F00 - U+2FDF // Kangxi Radicals U+2FF0 - U+2FFF // Ideographic Description Characters U+3000 - U+303F // CJK Symbols and Punctuation U+3040 - U+309F // Hiragana U+30A0 - U+30FF // Katakana U+3100 - U+312F // Bopomofo U+3130 - U+318F // Hangul Compatibility Jamo U+3190 - U+319F // Kanbun U+31A0 - U+31BF // Bopomofo Extended U+31C0 - U+31EF // CJK Strokes U+31F0 - U+31FF // Katakana Phonetic Extensions U+3200 - U+32FF // Enclosed CJK Letters and Months U+3300 - U+33FF // CJK Compatibility U+3400 - U+4DBF // CJK Unified Ideographs Extension A U+4DC0 - U+4DFF // Yijing Hexagram Symbols U+4E00 - U+9FFF // CJK Unified Ideographs U+A960 - U+A97F // Hangul Jamo Extended-A U+AC00 - U+D7AF // Hangul Syllables U+D7B0 - U+D7FF // Hangul Jamo Extended-B U+F900 - U+FAFF // CJK Compatibility Ideographs U+FE10 - U+FE1F // Vertical forms U+FE30 - U+FE4F // CJK Compatibility Forms U+FF00 - U+FFEF // Halfwidth and Fullwidth Forms U+1B000 - U+1B0FF // Kana Supplement U+1D300 - U+1D35F // Tai Xuan Hing Symbols U+1F200 - U+1F2FF // Enclosed Ideographic Supplement U+20000 - U+2A6DF // CJK Unified Ideographs Extension B U+2A700 - U+2B73F // CJK Unified Ideographs Extension C U+2B740 - U+2B81F // CJK Unified Ideographs Extension D U+2F800 - U+2FA1F // CJK Compatibility Ideographs Supplement FT_AUTOHINTER_SCRIPT_INDIC Apply the indic auto-hinter, covering all major scripts from the Indian sub-continent and some other related scripts like Thai, Lao, or Tibetan. By default, characters from the following Unicode ranges are assigned to this submodule. U+0900 - U+0DFF // Indic Range U+0F00 - U+0FFF // Tibetan U+1900 - U+194F // Limbu U+1B80 - U+1BBF // Sundanese U+A800 - U+A82F // Syloti Nagri U+ABC0 - U+ABFF // Meetei Mayek U+11800 - U+118DF // Sharada Note that currently Indic support is rudimentary only, missing blue zone support. since 2.4.11 FT_Prop_GlyphToScriptMap \u00b6 Defined in FT_DRIVER_H (freetype/ftdriver.h). typedef struct FT_Prop_GlyphToScriptMap_ { FT_Face face; FT_UShort * map; } FT_Prop_GlyphToScriptMap ; Experimental only The data exchange structure for the glyph-to-script-map property. since 2.4.11 fallback-script \u00b6 Experimental only If no auto-hinter script module can be assigned to a glyph, a fallback script gets assigned to it (see also the glyph-to-script-map property). By default, this is FT_AUTOHINTER_SCRIPT_CJK . Using the fallback-script property, this fallback value can be changed. note This property can be used with FT_Property_Get also. It's important to use the right timing for changing this value: The creation of the glyph-to-script map that eventually uses the fallback script value gets triggered either by setting or reading a face-specific property like glyph-to-script-map , or by auto-hinting any glyph from that face. In particular, if you have already created an FT_Face structure but not loaded any glyph (using the auto-hinter), a change of the fallback script will affect this face. example FT_Library library; FT_UInt fallback_script = FT_AUTOHINTER_SCRIPT_NONE; FT_Init_FreeType( &library ); FT_Property_Set( library, \"autofitter\", \"fallback-script\", &fallback_script ); since 2.4.11 default-script \u00b6 Experimental only If FreeType gets compiled with FT_CONFIG_OPTION_USE_HARFBUZZ to make the HarfBuzz library access OpenType features for getting better glyph coverages, this property sets the (auto-fitter) script to be used for the default (OpenType) script data of a font's GSUB table. Features for the default script are intended for all scripts not explicitly handled in GSUB; an example is a \u2018dlig\u2019 feature, containing the combination of the characters \u2018T\u2019, \u2018E\u2019, and \u2018L\u2019 to form a \u2018TEL\u2019 ligature. By default, this is FT_AUTOHINTER_SCRIPT_LATIN . Using the default-script property, this default value can be changed. note This property can be used with FT_Property_Get also. It's important to use the right timing for changing this value: The creation of the glyph-to-script map that eventually uses the default script value gets triggered either by setting or reading a face-specific property like glyph-to-script-map , or by auto-hinting any glyph from that face. In particular, if you have already created an FT_Face structure but not loaded any glyph (using the auto-hinter), a change of the default script will affect this face. example FT_Library library; FT_UInt default_script = FT_AUTOHINTER_SCRIPT_NONE; FT_Init_FreeType( &library ); FT_Property_Set( library, \"autofitter\", \"default-script\", &default_script ); since 2.5.3 increase-x-height \u00b6 For ppem values in the range 6 <= ppem <= increase-x-height , round up the font's x height much more often than normally. If the value is set to 0, which is the default, this feature is switched off. Use this property to improve the legibility of small font sizes if necessary. note This property can be used with FT_Property_Get also. Set this value right after calling FT_Set_Char_Size , but before loading any glyph (using the auto-hinter). example FT_Library library; FT_Face face; FT_Prop_IncreaseXHeight prop; FT_Init_FreeType( &library ); FT_New_Face( library, \"foo.ttf\", 0, &face ); FT_Set_Char_Size( face, 10 * 64, 0, 72, 0 ); prop.face = face; prop.limit = 14; FT_Property_Set( library, \"autofitter\", \"increase-x-height\", &prop ); since 2.4.11 FT_Prop_IncreaseXHeight \u00b6 Defined in FT_DRIVER_H (freetype/ftdriver.h). typedef struct FT_Prop_IncreaseXHeight_ { FT_Face face; FT_UInt limit; } FT_Prop_IncreaseXHeight ; The data exchange structure for the increase-x-height property. warping \u00b6 Experimental only If FreeType gets compiled with option AF_CONFIG_OPTION_USE_WARPER to activate the warp hinting code in the auto-hinter, this property switches warping on and off. Warping only works in \u2018normal\u2019 auto-hinting mode replacing it. The idea of the code is to slightly scale and shift a glyph along the non-hinted dimension (which is usually the horizontal axis) so that as much of its segments are aligned (more or less) to the grid. To find out a glyph's optimal scaling and shifting value, various parameter combinations are tried and scored. By default, warping is off. note This property can be used with FT_Property_Get also. This property can be set via the FREETYPE_PROPERTIES environment variable (using values 1 and 0 for \u2018on\u2019 and \u2018off\u2019, respectively). The warping code can also change advance widths. Have a look at the lsb_delta and rsb_delta fields in the FT_GlyphSlotRec structure for details on improving inter-glyph distances while rendering. Since warping is a global property of the auto-hinter it is best to change its value before rendering any face. Otherwise, you should reload all faces that get auto-hinted in \u2018normal\u2019 hinting mode. example This example shows how to switch on warping (omitting the error handling). FT_Library library; FT_Bool warping = 1; FT_Init_FreeType( &library ); FT_Property_Set( library, \"autofitter\", \"warping\", &warping ); since 2.6","title":"Driver properties"},{"location":"ft2-properties.html#driver-properties","text":"","title":"Driver properties"},{"location":"ft2-properties.html#synopsis","text":"Driver modules can be controlled by setting and unsetting properties, using the functions FT_Property_Set and FT_Property_Get . This section documents the available properties, together with auxiliary macros and structures.","title":"Synopsis"},{"location":"ft2-properties.html#ft_hinting_xxx","text":"Defined in FT_DRIVER_H (freetype/ftdriver.h). # define FT_HINTING_FREETYPE 0 # define FT_HINTING_ADOBE 1 /* these constants (introduced in 2.4.12) are deprecated */ # define FT_CFF_HINTING_FREETYPE FT_HINTING_FREETYPE # define FT_CFF_HINTING_ADOBE FT_HINTING_ADOBE A list of constants used for the hinting-engine property to select the hinting engine for CFF, Type 1, and CID fonts.","title":"FT_HINTING_XXX"},{"location":"ft2-properties.html#hinting-engine","text":"Thanks to Adobe, which contributed a new hinting (and parsing) engine, an application can select between \u2018freetype\u2019 and \u2018adobe\u2019 if compiled with CFF_CONFIG_OPTION_OLD_ENGINE . If this configuration macro isn't defined, \u2018hinting-engine\u2019 does nothing. The same holds for the Type 1 and CID modules if compiled with T1_CONFIG_OPTION_OLD_ENGINE . For the \u2018cff\u2019 module, the default engine is \u2018freetype\u2019 if CFF_CONFIG_OPTION_OLD_ENGINE is defined, and \u2018adobe\u2019 otherwise. For both the \u2018type1\u2019 and \u2018t1cid\u2019 modules, the default engine is \u2018freetype\u2019 if T1_CONFIG_OPTION_OLD_ENGINE is defined, and \u2018adobe\u2019 otherwise.","title":"hinting-engine"},{"location":"ft2-properties.html#no-stem-darkening","text":"All glyphs that pass through the auto-hinter will be emboldened unless this property is set to TRUE. The same is true for the CFF, Type 1, and CID font modules if the \u2018Adobe\u2019 engine is selected (which is the default). Stem darkening emboldens glyphs at smaller sizes to make them more readable on common low-DPI screens when using linear alpha blending and gamma correction, see FT_Render_Glyph . When not using linear alpha blending and gamma correction, glyphs will appear heavy and fuzzy! Gamma correction essentially lightens fonts since shades of grey are shifted to higher pixel values (= higher brightness) to match the original intention to the reality of our screens. The side-effect is that glyphs \u2018thin out\u2019. Mac OS X and Adobe's proprietary font rendering library implement a counter-measure: stem darkening at smaller sizes where shades of gray dominate. By emboldening a glyph slightly in relation to its pixel size, individual pixels get higher coverage of filled-in outlines and are therefore \u2018blacker\u2019. This counteracts the \u2018thinning out\u2019 of glyphs, making text remain readable at smaller sizes. For the auto-hinter, stem-darkening is experimental currently and thus switched off by default (this is, no-stem-darkening is set to TRUE by default). Total consistency with the CFF driver is not achieved right now because the emboldening method differs and glyphs must be scaled down on the Y-axis to keep outline points inside their precomputed blue zones. The smaller the size (especially 9ppem and down), the higher the loss of emboldening versus the CFF driver. Note that stem darkening is never applied if FT_LOAD_NO_SCALE is set.","title":"no-stem-darkening"},{"location":"ft2-properties.html#darkening-parameters","text":"By default, the Adobe hinting engine, as used by the CFF, Type 1, and CID font drivers, darkens stems as follows (if the no-stem-darkening property isn't set): stem width <= 0.5px: darkening amount = 0.4px stem width = 1px: darkening amount = 0.275px stem width = 1.667px: darkening amount = 0.275px stem width >= 2.333px: darkening amount = 0px and piecewise linear in-between. At configuration time, these four control points can be set with the macro CFF_CONFIG_OPTION_DARKENING_PARAMETERS ; the CFF, Type 1, and CID drivers share these values. At runtime, the control points can be changed using the darkening-parameters property (see the example below that demonstrates this for the Type 1 driver). The x values give the stem width, and the y values the darkening amount. The unit is 1000 th of pixels. All coordinate values must be positive; the x values must be monotonically increasing; the y values must be monotonically decreasing and smaller than or equal to 500 (corresponding to half a pixel); the slope of each linear piece must be shallower than -1 (e.g., -.4). The auto-hinter provides this property, too, as an experimental feature. See no-stem-darkening for more.","title":"darkening-parameters"},{"location":"ft2-properties.html#random-seed","text":"By default, the seed value for the CFF \u2018random\u2019 operator and the similar \u20180 28 callothersubr pop\u2019 command for the Type 1 and CID drivers is set to a random value. However, mainly for debugging purposes, it is often necessary to use a known value as a seed so that the pseudo-random number sequences generated by \u2018random\u2019 are repeatable. The random-seed property does that. Its argument is a signed 32bit integer; if the value is zero or negative, the seed given by the intitialRandomSeed private DICT operator in a CFF file gets used (or a default value if there is no such operator). If the value is positive, use it instead of initialRandomSeed , which is consequently ignored.","title":"random-seed"},{"location":"ft2-properties.html#no-long-family-names","text":"If PCF_CONFIG_OPTION_LONG_FAMILY_NAMES is active while compiling FreeType, the PCF driver constructs long family names. There are many PCF fonts just called \u2018Fixed\u2019 which look completely different, and which have nothing to do with each other. When selecting \u2018Fixed\u2019 in KDE or Gnome one gets results that appear rather random, the style changes often if one changes the size and one cannot select some fonts at all. The improve this situation, the PCF module prepends the foundry name (plus a space) to the family name. It also checks whether there are \u2018wide\u2019 characters; all put together, family names like \u2018Sony Fixed\u2019 or \u2018Misc Fixed Wide\u2019 are constructed. If no-long-family-names is set, this feature gets switched off.","title":"no-long-family-names"},{"location":"ft2-properties.html#tt_interpreter_version_xxx","text":"Defined in FT_DRIVER_H (freetype/ftdriver.h). # define TT_INTERPRETER_VERSION_35 35 # define TT_INTERPRETER_VERSION_38 38 # define TT_INTERPRETER_VERSION_40 40 A list of constants used for the interpreter-version property to select the hinting engine for Truetype fonts. The numeric value in the constant names represents the version number as returned by the \u2018GETINFO\u2019 bytecode instruction.","title":"TT_INTERPRETER_VERSION_XXX"},{"location":"ft2-properties.html#interpreter-version","text":"Currently, three versions are available, two representing the bytecode interpreter with subpixel hinting support (old \u2018Infinality\u2019 code and new stripped-down and higher performance \u2018minimal\u2019 code) and one without, respectively. The default is subpixel support if TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined, and no subpixel support otherwise (since it isn't available then). If subpixel hinting is on, many TrueType bytecode instructions behave differently compared to B/W or grayscale rendering (except if \u2018native ClearType\u2019 is selected by the font). Microsoft's main idea is to render at a much increased horizontal resolution, then sampling down the created output to subpixel precision. However, many older fonts are not suited to this and must be specially taken care of by applying (hardcoded) tweaks in Microsoft's interpreter. Details on subpixel hinting and some of the necessary tweaks can be found in Greg Hitchcock's whitepaper at \u2018 https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx \u2019. Note that FreeType currently doesn't really \u2018subpixel hint\u2019 (6x1, 6x2, or 6x5 supersampling) like discussed in the paper. Depending on the chosen interpreter, it simply ignores instructions on vertical stems to arrive at very similar results.","title":"interpreter-version"},{"location":"ft2-properties.html#glyph-to-script-map","text":"Experimental only The auto-hinter provides various script modules to hint glyphs. Examples of supported scripts are Latin or CJK. Before a glyph is auto-hinted, the Unicode character map of the font gets examined, and the script is then determined based on Unicode character ranges, see below. OpenType fonts, however, often provide much more glyphs than character codes (small caps, superscripts, ligatures, swashes, etc.), to be controlled by so-called \u2018features\u2019. Handling OpenType features can be quite complicated and thus needs a separate library on top of FreeType. The mapping between glyph indices and scripts (in the auto-hinter sense, see the FT_AUTOHINTER_SCRIPT_XXX values) is stored as an array with num_glyphs elements, as found in the font's FT_Face structure. The glyph-to-script-map property returns a pointer to this array, which can be modified as needed. Note that the modification should happen before the first glyph gets processed by the auto-hinter so that the global analysis of the font shapes actually uses the modified mapping.","title":"glyph-to-script-map"},{"location":"ft2-properties.html#ft_autohinter_script_xxx","text":"Defined in FT_DRIVER_H (freetype/ftdriver.h). # define FT_AUTOHINTER_SCRIPT_NONE 0 # define FT_AUTOHINTER_SCRIPT_LATIN 1 # define FT_AUTOHINTER_SCRIPT_CJK 2 # define FT_AUTOHINTER_SCRIPT_INDIC 3 Experimental only A list of constants used for the glyph-to-script-map property to specify the script submodule the auto-hinter should use for hinting a particular glyph.","title":"FT_AUTOHINTER_SCRIPT_XXX"},{"location":"ft2-properties.html#ft_prop_glyphtoscriptmap","text":"Defined in FT_DRIVER_H (freetype/ftdriver.h). typedef struct FT_Prop_GlyphToScriptMap_ { FT_Face face; FT_UShort * map; } FT_Prop_GlyphToScriptMap ; Experimental only The data exchange structure for the glyph-to-script-map property.","title":"FT_Prop_GlyphToScriptMap"},{"location":"ft2-properties.html#fallback-script","text":"Experimental only If no auto-hinter script module can be assigned to a glyph, a fallback script gets assigned to it (see also the glyph-to-script-map property). By default, this is FT_AUTOHINTER_SCRIPT_CJK . Using the fallback-script property, this fallback value can be changed.","title":"fallback-script"},{"location":"ft2-properties.html#default-script","text":"Experimental only If FreeType gets compiled with FT_CONFIG_OPTION_USE_HARFBUZZ to make the HarfBuzz library access OpenType features for getting better glyph coverages, this property sets the (auto-fitter) script to be used for the default (OpenType) script data of a font's GSUB table. Features for the default script are intended for all scripts not explicitly handled in GSUB; an example is a \u2018dlig\u2019 feature, containing the combination of the characters \u2018T\u2019, \u2018E\u2019, and \u2018L\u2019 to form a \u2018TEL\u2019 ligature. By default, this is FT_AUTOHINTER_SCRIPT_LATIN . Using the default-script property, this default value can be changed.","title":"default-script"},{"location":"ft2-properties.html#increase-x-height","text":"For ppem values in the range 6 <= ppem <= increase-x-height , round up the font's x height much more often than normally. If the value is set to 0, which is the default, this feature is switched off. Use this property to improve the legibility of small font sizes if necessary.","title":"increase-x-height"},{"location":"ft2-properties.html#ft_prop_increasexheight","text":"Defined in FT_DRIVER_H (freetype/ftdriver.h). typedef struct FT_Prop_IncreaseXHeight_ { FT_Face face; FT_UInt limit; } FT_Prop_IncreaseXHeight ; The data exchange structure for the increase-x-height property.","title":"FT_Prop_IncreaseXHeight"},{"location":"ft2-properties.html#warping","text":"Experimental only If FreeType gets compiled with option AF_CONFIG_OPTION_USE_WARPER to activate the warp hinting code in the auto-hinter, this property switches warping on and off. Warping only works in \u2018normal\u2019 auto-hinting mode replacing it. The idea of the code is to slightly scale and shift a glyph along the non-hinted dimension (which is usually the horizontal axis) so that as much of its segments are aligned (more or less) to the grid. To find out a glyph's optimal scaling and shifting value, various parameter combinations are tried and scored. By default, warping is off.","title":"warping"},{"location":"ft2-quick_advance.html","text":"FreeType \u00bb Docs \u00bb Support API \u00bb Quick retrieval of advance values Quick retrieval of advance values \u00b6 Synopsis \u00b6 This section contains functions to quickly extract advance values without handling glyph outlines, if possible. FT_Get_Advance \u00b6 Defined in FT_ADVANCES_H (freetype/ftadvanc.h). FT_EXPORT( FT_Error ) FT_Get_Advance ( FT_Face face, FT_UInt gindex, FT_Int32 load_flags, FT_Fixed *padvance ); Retrieve the advance value of a given glyph outline in an FT_Face . input face The source FT_Face handle. gindex The glyph index. load_flags A set of bit flags similar to those used when calling FT_Load_Glyph , used to determine what kind of advances you need. output padvance The advance value. If scaling is performed (based on the value of load_flags ), the advance value is in 16.16 format. Otherwise, it is in font units. If FT_LOAD_VERTICAL_LAYOUT is set, this is the vertical advance corresponding to a vertical layout. Otherwise, it is the horizontal advance in a horizontal layout. return FreeType error code. 0 means success. note This function may fail if you use FT_ADVANCE_FLAG_FAST_ONLY and if the corresponding font backend doesn't have a quick way to retrieve the advances. A scaled advance is returned in 16.16 format but isn't transformed by the affine transformation specified by FT_Set_Transform . FT_Get_Advances \u00b6 Defined in FT_ADVANCES_H (freetype/ftadvanc.h). FT_EXPORT( FT_Error ) FT_Get_Advances ( FT_Face face, FT_UInt start, FT_UInt count, FT_Int32 load_flags, FT_Fixed *padvances ); Retrieve the advance values of several glyph outlines in an FT_Face . input face The source FT_Face handle. start The first glyph index. count The number of advance values you want to retrieve. load_flags A set of bit flags similar to those used when calling FT_Load_Glyph . output padvance The advance values. This array, to be provided by the caller, must contain at least count elements. If scaling is performed (based on the value of load_flags ), the advance values are in 16.16 format. Otherwise, they are in font units. If FT_LOAD_VERTICAL_LAYOUT is set, these are the vertical advances corresponding to a vertical layout. Otherwise, they are the horizontal advances in a horizontal layout. return FreeType error code. 0 means success. note This function may fail if you use FT_ADVANCE_FLAG_FAST_ONLY and if the corresponding font backend doesn't have a quick way to retrieve the advances. Scaled advances are returned in 16.16 format but aren't transformed by the affine transformation specified by FT_Set_Transform . FT_ADVANCE_FLAG_FAST_ONLY \u00b6 Defined in FT_ADVANCES_H (freetype/ftadvanc.h). # define FT_ADVANCE_FLAG_FAST_ONLY 0x20000000L A bit-flag to be OR-ed with the flags parameter of the FT_Get_Advance and FT_Get_Advances functions. If set, it indicates that you want these functions to fail if the corresponding hinting mode or font driver doesn't allow for very quick advance computation. Typically, glyphs that are either unscaled, unhinted, bitmapped, or light-hinted can have their advance width computed very quickly. Normal and bytecode hinted modes that require loading, scaling, and hinting of the glyph outline, are extremely slow by comparison.","title":"Quick retrieval of advance values"},{"location":"ft2-quick_advance.html#quick-retrieval-of-advance-values","text":"","title":"Quick retrieval of advance values"},{"location":"ft2-quick_advance.html#synopsis","text":"This section contains functions to quickly extract advance values without handling glyph outlines, if possible.","title":"Synopsis"},{"location":"ft2-quick_advance.html#ft_get_advance","text":"Defined in FT_ADVANCES_H (freetype/ftadvanc.h). FT_EXPORT( FT_Error ) FT_Get_Advance ( FT_Face face, FT_UInt gindex, FT_Int32 load_flags, FT_Fixed *padvance ); Retrieve the advance value of a given glyph outline in an FT_Face .","title":"FT_Get_Advance"},{"location":"ft2-quick_advance.html#ft_get_advances","text":"Defined in FT_ADVANCES_H (freetype/ftadvanc.h). FT_EXPORT( FT_Error ) FT_Get_Advances ( FT_Face face, FT_UInt start, FT_UInt count, FT_Int32 load_flags, FT_Fixed *padvances ); Retrieve the advance values of several glyph outlines in an FT_Face .","title":"FT_Get_Advances"},{"location":"ft2-quick_advance.html#ft_advance_flag_fast_only","text":"Defined in FT_ADVANCES_H (freetype/ftadvanc.h). # define FT_ADVANCE_FLAG_FAST_ONLY 0x20000000L A bit-flag to be OR-ed with the flags parameter of the FT_Get_Advance and FT_Get_Advances functions. If set, it indicates that you want these functions to fail if the corresponding hinting mode or font driver doesn't allow for very quick advance computation. Typically, glyphs that are either unscaled, unhinted, bitmapped, or light-hinted can have their advance width computed very quickly. Normal and bytecode hinted modes that require loading, scaling, and hinting of the glyph outline, are extremely slow by comparison.","title":"FT_ADVANCE_FLAG_FAST_ONLY"},{"location":"ft2-raster.html","text":"FreeType \u00bb Docs \u00bb Support API \u00bb Scanline Converter Scanline Converter \u00b6 Synopsis \u00b6 This section contains technical definitions. FT_Raster \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_RasterRec_* FT_Raster ; An opaque handle (pointer) to a raster object. Each object can be used independently to convert an outline into a bitmap or pixmap. FT_Span \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_Span_ { short x; unsigned short len; unsigned char coverage; } FT_Span ; A structure used to model a single span of gray pixels when rendering an anti-aliased bitmap. fields x The span's horizontal start position. len The span's length in pixels. coverage The span color/coverage, ranging from 0 (background) to 255 (foreground). note This structure is used by the span drawing callback type named FT_SpanFunc that takes the y coordinate of the span as a parameter. The coverage value is always between 0 and 255. If you want less gray values, the callback function has to reduce them. FT_SpanFunc \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef void (* FT_SpanFunc )( int y, int count, const FT_Span * spans, void * user ); # define FT_Raster_Span_Func FT_SpanFunc A function used as a call-back by the anti-aliased renderer in order to let client applications draw themselves the gray pixel spans on each scan line. input y The scanline's upward y coordinate. count The number of spans to draw on this scanline. spans A table of count spans to draw on the scanline. user User-supplied data that is passed to the callback. note This callback allows client applications to directly render the gray spans of the anti-aliased bitmap to any kind of surfaces. This can be used to write anti-aliased outlines directly to a given background bitmap, and even perform translucency. FT_Raster_Params \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_Raster_Params_ { const FT_Bitmap * target; const void * source; int flags; FT_SpanFunc gray_spans; FT_SpanFunc black_spans; /* unused */ FT_Raster_BitTest_Func bit_test; /* unused */ FT_Raster_BitSet_Func bit_set; /* unused */ void * user; FT_BBox clip_box; } FT_Raster_Params ; A structure to hold the parameters used by a raster's render function, passed as an argument to FT_Outline_Render . fields target The target bitmap. source A pointer to the source glyph image (e.g., an FT_Outline ). flags The rendering flags. gray_spans The gray span drawing callback. black_spans Unused. bit_test Unused. bit_set Unused. user User-supplied data that is passed to each drawing callback. clip_box An optional span clipping box expressed in integer pixels (not in 26.6 fixed-point units). note The FT_RASTER_FLAG_AA bit flag must be set in the flags to generate an anti-aliased glyph bitmap, otherwise a monochrome bitmap is generated. The target should have appropriate pixel mode and its dimensions define the clipping region. If both FT_RASTER_FLAG_AA and FT_RASTER_FLAG_DIRECT bit flags are set in flags , the raster calls an FT_SpanFunc callback gray_spans with user data as an argument ignoring target . This allows direct composition over a pre-existing user surface to perform the span drawing and composition. To optionally clip the spans, set the FT_RASTER_FLAG_CLIP flag and clip_box . The monochrome raster does not support the direct mode. The gray-level rasterizer always uses 256 gray levels. If you want fewer gray levels, you have to use FT_RASTER_FLAG_DIRECT and reduce the levels in the callback function. FT_RASTER_FLAG_XXX \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). # define FT_RASTER_FLAG_DEFAULT 0x0 # define FT_RASTER_FLAG_AA 0x1 # define FT_RASTER_FLAG_DIRECT 0x2 # define FT_RASTER_FLAG_CLIP 0x4 /* these constants are deprecated; use the corresponding */ /* ` FT_RASTER_FLAG_XXX ` values instead */ # define ft_raster_flag_default FT_RASTER_FLAG_DEFAULT # define ft_raster_flag_aa FT_RASTER_FLAG_AA # define ft_raster_flag_direct FT_RASTER_FLAG_DIRECT # define ft_raster_flag_clip FT_RASTER_FLAG_CLIP A list of bit flag constants as used in the flags field of a FT_Raster_Params structure. values FT_RASTER_FLAG_DEFAULT This value is 0. FT_RASTER_FLAG_AA This flag is set to indicate that an anti-aliased glyph image should be generated. Otherwise, it will be monochrome (1-bit). FT_RASTER_FLAG_DIRECT This flag is set to indicate direct rendering. In this mode, client applications must provide their own span callback. This lets them directly draw or compose over an existing bitmap. If this bit is not set, the target pixmap's buffer must be zeroed before rendering and the output will be clipped to its size. Direct rendering is only possible with anti-aliased glyphs. FT_RASTER_FLAG_CLIP This flag is only used in direct rendering mode. If set, the output will be clipped to a box specified in the clip_box field of the FT_Raster_Params structure. Otherwise, the clip_box is effectively set to the bounding box and all spans are generated. FT_Raster_NewFunc \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Raster_NewFunc )( void * memory, FT_Raster * raster ); # define FT_Raster_New_Func FT_Raster_NewFunc A function used to create a new raster object. input memory A handle to the memory allocator. output raster A handle to the new raster object. return Error code. 0 means success. note The memory parameter is a typeless pointer in order to avoid un-wanted dependencies on the rest of the FreeType code. In practice, it is an FT_Memory object, i.e., a handle to the standard FreeType memory allocator. However, this field can be completely ignored by a given raster implementation. FT_Raster_DoneFunc \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef void (* FT_Raster_DoneFunc )( FT_Raster raster ); # define FT_Raster_Done_Func FT_Raster_DoneFunc A function used to destroy a given raster object. input raster A handle to the raster object. FT_Raster_ResetFunc \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef void (* FT_Raster_ResetFunc )( FT_Raster raster, unsigned char * pool_base, unsigned long pool_size ); # define FT_Raster_Reset_Func FT_Raster_ResetFunc FreeType used to provide an area of memory called the \u2018render pool\u2019 available to all registered rasterizers. This was not thread safe, however, and now FreeType never allocates this pool. This function is called after a new raster object is created. input raster A handle to the new raster object. pool_base Previously, the address in memory of the render pool. Set this to NULL . pool_size Previously, the size in bytes of the render pool. Set this to 0. note Rasterizers should rely on dynamic or stack allocation if they want to (a handle to the memory allocator is passed to the rasterizer constructor). FT_Raster_SetModeFunc \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Raster_SetModeFunc )( FT_Raster raster, unsigned long mode, void * args ); # define FT_Raster_Set_Mode_Func FT_Raster_SetModeFunc This function is a generic facility to change modes or attributes in a given raster. This can be used for debugging purposes, or simply to allow implementation-specific \u2018features\u2019 in a given raster module. input raster A handle to the new raster object. mode A 4-byte tag used to name the mode or property. args A pointer to the new mode/property to use. FT_Raster_RenderFunc \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Raster_RenderFunc )( FT_Raster raster, const FT_Raster_Params * params ); # define FT_Raster_Render_Func FT_Raster_RenderFunc Invoke a given raster to scan-convert a given glyph image into a target bitmap. input raster A handle to the raster object. params A pointer to an FT_Raster_Params structure used to store the rendering parameters. return Error code. 0 means success. note The exact format of the source image depends on the raster's glyph format defined in its FT_Raster_Funcs structure. It can be an FT_Outline or anything else in order to support a large array of glyph formats. Note also that the render function can fail and return a FT_Err_Unimplemented_Feature error code if the raster used does not support direct composition. FT_Raster_Funcs \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_Raster_Funcs_ { FT_Glyph_Format glyph_format; FT_Raster_NewFunc raster_new; FT_Raster_ResetFunc raster_reset; FT_Raster_SetModeFunc raster_set_mode; FT_Raster_RenderFunc raster_render; FT_Raster_DoneFunc raster_done; } FT_Raster_Funcs ; A structure used to describe a given raster class to the library. fields glyph_format The supported glyph format for this raster. raster_new The raster constructor. raster_reset Used to reset the render pool within the raster. raster_render A function to render a glyph into a given bitmap. raster_done The raster destructor. FT_Raster_BitTest_Func \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Raster_BitTest_Func )( int y, int x, void * user ); Deprecated, unimplemented. FT_Raster_BitSet_Func \u00b6 Defined in FT_IMAGE_H (freetype/ftimage.h). typedef void (* FT_Raster_BitSet_Func )( int y, int x, void * user ); Deprecated, unimplemented.","title":"Scanline Converter"},{"location":"ft2-raster.html#scanline-converter","text":"","title":"Scanline Converter"},{"location":"ft2-raster.html#synopsis","text":"This section contains technical definitions.","title":"Synopsis"},{"location":"ft2-raster.html#ft_raster","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_RasterRec_* FT_Raster ; An opaque handle (pointer) to a raster object. Each object can be used independently to convert an outline into a bitmap or pixmap.","title":"FT_Raster"},{"location":"ft2-raster.html#ft_span","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_Span_ { short x; unsigned short len; unsigned char coverage; } FT_Span ; A structure used to model a single span of gray pixels when rendering an anti-aliased bitmap.","title":"FT_Span"},{"location":"ft2-raster.html#ft_spanfunc","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef void (* FT_SpanFunc )( int y, int count, const FT_Span * spans, void * user ); # define FT_Raster_Span_Func FT_SpanFunc A function used as a call-back by the anti-aliased renderer in order to let client applications draw themselves the gray pixel spans on each scan line.","title":"FT_SpanFunc"},{"location":"ft2-raster.html#ft_raster_params","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_Raster_Params_ { const FT_Bitmap * target; const void * source; int flags; FT_SpanFunc gray_spans; FT_SpanFunc black_spans; /* unused */ FT_Raster_BitTest_Func bit_test; /* unused */ FT_Raster_BitSet_Func bit_set; /* unused */ void * user; FT_BBox clip_box; } FT_Raster_Params ; A structure to hold the parameters used by a raster's render function, passed as an argument to FT_Outline_Render .","title":"FT_Raster_Params"},{"location":"ft2-raster.html#ft_raster_flag_xxx","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). # define FT_RASTER_FLAG_DEFAULT 0x0 # define FT_RASTER_FLAG_AA 0x1 # define FT_RASTER_FLAG_DIRECT 0x2 # define FT_RASTER_FLAG_CLIP 0x4 /* these constants are deprecated; use the corresponding */ /* ` FT_RASTER_FLAG_XXX ` values instead */ # define ft_raster_flag_default FT_RASTER_FLAG_DEFAULT # define ft_raster_flag_aa FT_RASTER_FLAG_AA # define ft_raster_flag_direct FT_RASTER_FLAG_DIRECT # define ft_raster_flag_clip FT_RASTER_FLAG_CLIP A list of bit flag constants as used in the flags field of a FT_Raster_Params structure.","title":"FT_RASTER_FLAG_XXX"},{"location":"ft2-raster.html#ft_raster_newfunc","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Raster_NewFunc )( void * memory, FT_Raster * raster ); # define FT_Raster_New_Func FT_Raster_NewFunc A function used to create a new raster object.","title":"FT_Raster_NewFunc"},{"location":"ft2-raster.html#ft_raster_donefunc","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef void (* FT_Raster_DoneFunc )( FT_Raster raster ); # define FT_Raster_Done_Func FT_Raster_DoneFunc A function used to destroy a given raster object.","title":"FT_Raster_DoneFunc"},{"location":"ft2-raster.html#ft_raster_resetfunc","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef void (* FT_Raster_ResetFunc )( FT_Raster raster, unsigned char * pool_base, unsigned long pool_size ); # define FT_Raster_Reset_Func FT_Raster_ResetFunc FreeType used to provide an area of memory called the \u2018render pool\u2019 available to all registered rasterizers. This was not thread safe, however, and now FreeType never allocates this pool. This function is called after a new raster object is created.","title":"FT_Raster_ResetFunc"},{"location":"ft2-raster.html#ft_raster_setmodefunc","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Raster_SetModeFunc )( FT_Raster raster, unsigned long mode, void * args ); # define FT_Raster_Set_Mode_Func FT_Raster_SetModeFunc This function is a generic facility to change modes or attributes in a given raster. This can be used for debugging purposes, or simply to allow implementation-specific \u2018features\u2019 in a given raster module.","title":"FT_Raster_SetModeFunc"},{"location":"ft2-raster.html#ft_raster_renderfunc","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Raster_RenderFunc )( FT_Raster raster, const FT_Raster_Params * params ); # define FT_Raster_Render_Func FT_Raster_RenderFunc Invoke a given raster to scan-convert a given glyph image into a target bitmap.","title":"FT_Raster_RenderFunc"},{"location":"ft2-raster.html#ft_raster_funcs","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef struct FT_Raster_Funcs_ { FT_Glyph_Format glyph_format; FT_Raster_NewFunc raster_new; FT_Raster_ResetFunc raster_reset; FT_Raster_SetModeFunc raster_set_mode; FT_Raster_RenderFunc raster_render; FT_Raster_DoneFunc raster_done; } FT_Raster_Funcs ; A structure used to describe a given raster class to the library.","title":"FT_Raster_Funcs"},{"location":"ft2-raster.html#ft_raster_bittest_func","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef int (* FT_Raster_BitTest_Func )( int y, int x, void * user ); Deprecated, unimplemented.","title":"FT_Raster_BitTest_Func"},{"location":"ft2-raster.html#ft_raster_bitset_func","text":"Defined in FT_IMAGE_H (freetype/ftimage.h). typedef void (* FT_Raster_BitSet_Func )( int y, int x, void * user ); Deprecated, unimplemented.","title":"FT_Raster_BitSet_Func"},{"location":"ft2-sfnt_names.html","text":"FreeType \u00bb Docs \u00bb Format-Specific API \u00bb SFNT Names SFNT Names \u00b6 Synopsis \u00b6 The TrueType and OpenType specifications allow the inclusion of a special names table (\u2018name\u2019) in font files. This table contains textual (and internationalized) information regarding the font, like family name, copyright, version, etc. The definitions below are used to access them if available. Note that this has nothing to do with glyph names! FT_SfntName \u00b6 Defined in FT_SFNT_NAMES_H (freetype/ftsnames.h). typedef struct FT_SfntName_ { FT_UShort platform_id; FT_UShort encoding_id; FT_UShort language_id; FT_UShort name_id; FT_Byte * string; /* this string is *not* null-terminated! */ FT_UInt string_len; /* in bytes */ } FT_SfntName ; A structure used to model an SFNT \u2018name\u2019 table entry. fields platform_id The platform ID for string . See TT_PLATFORM_XXX for possible values. encoding_id The encoding ID for string . See TT_APPLE_ID_XXX , TT_MAC_ID_XXX , TT_ISO_ID_XXX , TT_MS_ID_XXX , and TT_ADOBE_ID_XXX for possible values. language_id The language ID for string . See TT_MAC_LANGID_XXX and TT_MS_LANGID_XXX for possible values. Registered OpenType values for language_id are always smaller than 0x8000; values equal or larger than 0x8000 usually indicate a language tag string (introduced in OpenType version 1.6). Use function FT_Get_Sfnt_LangTag with language_id as its argument to retrieve the associated language tag. name_id An identifier for string . See TT_NAME_ID_XXX for possible values. string The \u2018name\u2019 string. Note that its format differs depending on the (platform,encoding) pair, being either a string of bytes (without a terminating NULL byte) or containing UTF-16BE entities. string_len The length of string in bytes. note Please refer to the TrueType or OpenType specification for more details. FT_Get_Sfnt_Name_Count \u00b6 Defined in FT_SFNT_NAMES_H (freetype/ftsnames.h). FT_EXPORT( FT_UInt ) FT_Get_Sfnt_Name_Count ( FT_Face face ); Retrieve the number of name strings in the SFNT \u2018name\u2019 table. input face A handle to the source face. return The number of strings in the \u2018name\u2019 table. note This function always returns an error if the config macro TT_CONFIG_OPTION_SFNT_NAMES is not defined in ftoption.h . FT_Get_Sfnt_Name \u00b6 Defined in FT_SFNT_NAMES_H (freetype/ftsnames.h). FT_EXPORT( FT_Error ) FT_Get_Sfnt_Name ( FT_Face face, FT_UInt idx, FT_SfntName *aname ); Retrieve a string of the SFNT \u2018name\u2019 table for a given index. input face A handle to the source face. idx The index of the \u2018name\u2019 string. output aname The indexed FT_SfntName structure. return FreeType error code. 0 means success. note The string array returned in the aname structure is not null-terminated. Note that you don't have to deallocate string by yourself; FreeType takes care of it if you call FT_Done_Face . Use FT_Get_Sfnt_Name_Count to get the total number of available \u2018name\u2019 table entries, then do a loop until you get the right platform, encoding, and name ID. \u2018name\u2019 table format 1 entries can use language tags also, see FT_Get_Sfnt_LangTag . This function always returns an error if the config macro TT_CONFIG_OPTION_SFNT_NAMES is not defined in ftoption.h . FT_SfntLangTag \u00b6 Defined in FT_SFNT_NAMES_H (freetype/ftsnames.h). typedef struct FT_SfntLangTag_ { FT_Byte * string; /* this string is *not* null-terminated! */ FT_UInt string_len; /* in bytes */ } FT_SfntLangTag ; A structure to model a language tag entry from an SFNT \u2018name\u2019 table. fields string The language tag string, encoded in UTF-16BE (without trailing NULL bytes). string_len The length of string in bytes . note Please refer to the TrueType or OpenType specification for more details. since 2.8 FT_Get_Sfnt_LangTag \u00b6 Defined in FT_SFNT_NAMES_H (freetype/ftsnames.h). FT_EXPORT( FT_Error ) FT_Get_Sfnt_LangTag ( FT_Face face, FT_UInt langID, FT_SfntLangTag *alangTag ); Retrieve the language tag associated with a language ID of an SFNT \u2018name\u2019 table entry. input face A handle to the source face. langID The language ID, as returned by FT_Get_Sfnt_Name . This is always a value larger than 0x8000. output alangTag The language tag associated with the \u2018name\u2019 table entry's language ID. return FreeType error code. 0 means success. note The string array returned in the alangTag structure is not null-terminated. Note that you don't have to deallocate string by yourself; FreeType takes care of it if you call FT_Done_Face . Only \u2018name\u2019 table format 1 supports language tags. For format 0 tables, this function always returns FT_Err_Invalid_Table. For invalid format 1 language ID values, FT_Err_Invalid_Argument is returned. This function always returns an error if the config macro TT_CONFIG_OPTION_SFNT_NAMES is not defined in ftoption.h . since 2.8","title":"SFNT Names"},{"location":"ft2-sfnt_names.html#sfnt-names","text":"","title":"SFNT Names"},{"location":"ft2-sfnt_names.html#synopsis","text":"The TrueType and OpenType specifications allow the inclusion of a special names table (\u2018name\u2019) in font files. This table contains textual (and internationalized) information regarding the font, like family name, copyright, version, etc. The definitions below are used to access them if available. Note that this has nothing to do with glyph names!","title":"Synopsis"},{"location":"ft2-sfnt_names.html#ft_sfntname","text":"Defined in FT_SFNT_NAMES_H (freetype/ftsnames.h). typedef struct FT_SfntName_ { FT_UShort platform_id; FT_UShort encoding_id; FT_UShort language_id; FT_UShort name_id; FT_Byte * string; /* this string is *not* null-terminated! */ FT_UInt string_len; /* in bytes */ } FT_SfntName ; A structure used to model an SFNT \u2018name\u2019 table entry.","title":"FT_SfntName"},{"location":"ft2-sfnt_names.html#ft_get_sfnt_name_count","text":"Defined in FT_SFNT_NAMES_H (freetype/ftsnames.h). FT_EXPORT( FT_UInt ) FT_Get_Sfnt_Name_Count ( FT_Face face ); Retrieve the number of name strings in the SFNT \u2018name\u2019 table.","title":"FT_Get_Sfnt_Name_Count"},{"location":"ft2-sfnt_names.html#ft_get_sfnt_name","text":"Defined in FT_SFNT_NAMES_H (freetype/ftsnames.h). FT_EXPORT( FT_Error ) FT_Get_Sfnt_Name ( FT_Face face, FT_UInt idx, FT_SfntName *aname ); Retrieve a string of the SFNT \u2018name\u2019 table for a given index.","title":"FT_Get_Sfnt_Name"},{"location":"ft2-sfnt_names.html#ft_sfntlangtag","text":"Defined in FT_SFNT_NAMES_H (freetype/ftsnames.h). typedef struct FT_SfntLangTag_ { FT_Byte * string; /* this string is *not* null-terminated! */ FT_UInt string_len; /* in bytes */ } FT_SfntLangTag ; A structure to model a language tag entry from an SFNT \u2018name\u2019 table.","title":"FT_SfntLangTag"},{"location":"ft2-sfnt_names.html#ft_get_sfnt_langtag","text":"Defined in FT_SFNT_NAMES_H (freetype/ftsnames.h). FT_EXPORT( FT_Error ) FT_Get_Sfnt_LangTag ( FT_Face face, FT_UInt langID, FT_SfntLangTag *alangTag ); Retrieve the language tag associated with a language ID of an SFNT \u2018name\u2019 table entry.","title":"FT_Get_Sfnt_LangTag"},{"location":"ft2-sizes_management.html","text":"FreeType \u00bb Docs \u00bb Core API \u00bb Size Management Size Management \u00b6 Synopsis \u00b6 When creating a new face object (e.g., with FT_New_Face ), an FT_Size object is automatically created and used to store all pixel-size dependent information, available in the face->size field. It is however possible to create more sizes for a given face, mostly in order to manage several character pixel sizes of the same font family and style. See FT_New_Size and FT_Done_Size . Note that FT_Set_Pixel_Sizes and FT_Set_Char_Size only modify the contents of the current \u2018active\u2019 size; you thus need to use FT_Activate_Size to change it. 99% of applications won't need the functions provided here, especially if they use the caching sub-system, so be cautious when using these. FT_New_Size \u00b6 Defined in FT_SIZES_H (freetype/ftsizes.h). FT_EXPORT( FT_Error ) FT_New_Size ( FT_Face face, FT_Size * size ); Create a new size object from a given face object. input face A handle to a parent face object. output asize A handle to a new size object. return FreeType error code. 0 means success. note You need to call FT_Activate_Size in order to select the new size for upcoming calls to FT_Set_Pixel_Sizes , FT_Set_Char_Size , FT_Load_Glyph , FT_Load_Char , etc. FT_Done_Size \u00b6 Defined in FT_SIZES_H (freetype/ftsizes.h). FT_EXPORT( FT_Error ) FT_Done_Size ( FT_Size size ); Discard a given size object. Note that FT_Done_Face automatically discards all size objects allocated with FT_New_Size . input size A handle to a target size object. return FreeType error code. 0 means success. FT_Activate_Size \u00b6 Defined in FT_SIZES_H (freetype/ftsizes.h). FT_EXPORT( FT_Error ) FT_Activate_Size ( FT_Size size ); Even though it is possible to create several size objects for a given face (see FT_New_Size for details), functions like FT_Load_Glyph or FT_Load_Char only use the one that has been activated last to determine the \u2018current character pixel size\u2019. This function can be used to \u2018activate\u2019 a previously created size object. input size A handle to a target size object. return FreeType error code. 0 means success. note If face is the size's parent face object, this function changes the value of face->size to the input size handle.","title":"Size Management"},{"location":"ft2-sizes_management.html#size-management","text":"","title":"Size Management"},{"location":"ft2-sizes_management.html#synopsis","text":"When creating a new face object (e.g., with FT_New_Face ), an FT_Size object is automatically created and used to store all pixel-size dependent information, available in the face->size field. It is however possible to create more sizes for a given face, mostly in order to manage several character pixel sizes of the same font family and style. See FT_New_Size and FT_Done_Size . Note that FT_Set_Pixel_Sizes and FT_Set_Char_Size only modify the contents of the current \u2018active\u2019 size; you thus need to use FT_Activate_Size to change it. 99% of applications won't need the functions provided here, especially if they use the caching sub-system, so be cautious when using these.","title":"Synopsis"},{"location":"ft2-sizes_management.html#ft_new_size","text":"Defined in FT_SIZES_H (freetype/ftsizes.h). FT_EXPORT( FT_Error ) FT_New_Size ( FT_Face face, FT_Size * size ); Create a new size object from a given face object.","title":"FT_New_Size"},{"location":"ft2-sizes_management.html#ft_done_size","text":"Defined in FT_SIZES_H (freetype/ftsizes.h). FT_EXPORT( FT_Error ) FT_Done_Size ( FT_Size size ); Discard a given size object. Note that FT_Done_Face automatically discards all size objects allocated with FT_New_Size .","title":"FT_Done_Size"},{"location":"ft2-sizes_management.html#ft_activate_size","text":"Defined in FT_SIZES_H (freetype/ftsizes.h). FT_EXPORT( FT_Error ) FT_Activate_Size ( FT_Size size ); Even though it is possible to create several size objects for a given face (see FT_New_Size for details), functions like FT_Load_Glyph or FT_Load_Char only use the one that has been activated last to determine the \u2018current character pixel size\u2019. This function can be used to \u2018activate\u2019 a previously created size object.","title":"FT_Activate_Size"},{"location":"ft2-system_interface.html","text":"FreeType \u00bb Docs \u00bb Support API \u00bb System Interface System Interface \u00b6 Synopsis \u00b6 This section contains various definitions related to memory management and i/o access. You need to understand this information if you want to use a custom memory manager or you own i/o streams. FT_Memory \u00b6 Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef struct FT_MemoryRec_* FT_Memory ; A handle to a given memory manager object, defined with an FT_MemoryRec structure. FT_Alloc_Func \u00b6 Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef void * (* FT_Alloc_Func )( FT_Memory memory, long size ); A function used to allocate size bytes from memory . input memory A handle to the source memory manager. size The size in bytes to allocate. return Address of new memory block. 0 in case of failure. FT_Free_Func \u00b6 Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef void (* FT_Free_Func )( FT_Memory memory, void * block ); A function used to release a given block of memory. input memory A handle to the source memory manager. block The address of the target memory block. FT_Realloc_Func \u00b6 Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef void * (* FT_Realloc_Func )( FT_Memory memory, long cur_size, long new_size, void * block ); A function used to re-allocate a given block of memory. input memory A handle to the source memory manager. cur_size The block's current size in bytes. new_size The block's requested new size. block The block's current address. return New block address. 0 in case of memory shortage. note In case of error, the old block must still be available. FT_MemoryRec \u00b6 Defined in FT_SYSTEM_H (freetype/ftsystem.h). struct FT_MemoryRec_ { void * user; FT_Alloc_Func alloc; FT_Free_Func free; FT_Realloc_Func realloc; }; A structure used to describe a given memory manager to FreeType 2. fields user A generic typeless pointer for user data. alloc A pointer type to an allocation function. free A pointer type to an memory freeing function. realloc A pointer type to a reallocation function. FT_Stream \u00b6 Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef struct FT_StreamRec_* FT_Stream ; A handle to an input stream. also See FT_StreamRec for the publicly accessible fields of a given stream object. FT_StreamDesc \u00b6 Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef union FT_StreamDesc_ { long value; void * pointer; } FT_StreamDesc ; A union type used to store either a long or a pointer. This is used to store a file descriptor or a FILE* in an input stream. FT_Stream_IoFunc \u00b6 Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef unsigned long (* FT_Stream_IoFunc )( FT_Stream stream, unsigned long offset, unsigned char * buffer, unsigned long count ); A function used to seek and read data from a given input stream. input stream A handle to the source stream. offset The offset of read in stream (always from start). buffer The address of the read buffer. count The number of bytes to read from the stream. return The number of bytes effectively read by the stream. note This function might be called to perform a seek or skip operation with a count of 0. A non-zero return value then indicates an error. FT_Stream_CloseFunc \u00b6 Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef void (* FT_Stream_CloseFunc )( FT_Stream stream ); A function used to close a given input stream. input stream A handle to the target stream. FT_StreamRec \u00b6 Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef struct FT_StreamRec_ { unsigned char * base; unsigned long size; unsigned long pos; FT_StreamDesc descriptor; FT_StreamDesc pathname; FT_Stream_IoFunc read; FT_Stream_CloseFunc close; FT_Memory memory; unsigned char * cursor; unsigned char * limit; } FT_StreamRec ; A structure used to describe an input stream. input base For memory-based streams, this is the address of the first stream byte in memory. This field should always be set to NULL for disk-based streams. size The stream size in bytes. In case of compressed streams where the size is unknown before actually doing the decompression, the value is set to 0x7FFFFFFF. (Note that this size value can occur for normal streams also; it is thus just a hint.) pos The current position within the stream. descriptor This field is a union that can hold an integer or a pointer. It is used by stream implementations to store file descriptors or FILE* pointers. pathname This field is completely ignored by FreeType. However, it is often useful during debugging to use it to store the stream's filename (where available). read The stream's input function. close The stream's close function. memory The memory manager to use to preload frames. This is set internally by FreeType and shouldn't be touched by stream implementations. cursor This field is set and used internally by FreeType when parsing frames. In particular, the FT_GET_XXX macros use this instead of the pos field. limit This field is set and used internally by FreeType when parsing frames.","title":"System Interface"},{"location":"ft2-system_interface.html#system-interface","text":"","title":"System Interface"},{"location":"ft2-system_interface.html#synopsis","text":"This section contains various definitions related to memory management and i/o access. You need to understand this information if you want to use a custom memory manager or you own i/o streams.","title":"Synopsis"},{"location":"ft2-system_interface.html#ft_memory","text":"Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef struct FT_MemoryRec_* FT_Memory ; A handle to a given memory manager object, defined with an FT_MemoryRec structure.","title":"FT_Memory"},{"location":"ft2-system_interface.html#ft_alloc_func","text":"Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef void * (* FT_Alloc_Func )( FT_Memory memory, long size ); A function used to allocate size bytes from memory .","title":"FT_Alloc_Func"},{"location":"ft2-system_interface.html#ft_free_func","text":"Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef void (* FT_Free_Func )( FT_Memory memory, void * block ); A function used to release a given block of memory.","title":"FT_Free_Func"},{"location":"ft2-system_interface.html#ft_realloc_func","text":"Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef void * (* FT_Realloc_Func )( FT_Memory memory, long cur_size, long new_size, void * block ); A function used to re-allocate a given block of memory.","title":"FT_Realloc_Func"},{"location":"ft2-system_interface.html#ft_memoryrec","text":"Defined in FT_SYSTEM_H (freetype/ftsystem.h). struct FT_MemoryRec_ { void * user; FT_Alloc_Func alloc; FT_Free_Func free; FT_Realloc_Func realloc; }; A structure used to describe a given memory manager to FreeType 2.","title":"FT_MemoryRec"},{"location":"ft2-system_interface.html#ft_stream","text":"Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef struct FT_StreamRec_* FT_Stream ; A handle to an input stream.","title":"FT_Stream"},{"location":"ft2-system_interface.html#ft_streamdesc","text":"Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef union FT_StreamDesc_ { long value; void * pointer; } FT_StreamDesc ; A union type used to store either a long or a pointer. This is used to store a file descriptor or a FILE* in an input stream.","title":"FT_StreamDesc"},{"location":"ft2-system_interface.html#ft_stream_iofunc","text":"Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef unsigned long (* FT_Stream_IoFunc )( FT_Stream stream, unsigned long offset, unsigned char * buffer, unsigned long count ); A function used to seek and read data from a given input stream.","title":"FT_Stream_IoFunc"},{"location":"ft2-system_interface.html#ft_stream_closefunc","text":"Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef void (* FT_Stream_CloseFunc )( FT_Stream stream ); A function used to close a given input stream.","title":"FT_Stream_CloseFunc"},{"location":"ft2-system_interface.html#ft_streamrec","text":"Defined in FT_SYSTEM_H (freetype/ftsystem.h). typedef struct FT_StreamRec_ { unsigned char * base; unsigned long size; unsigned long pos; FT_StreamDesc descriptor; FT_StreamDesc pathname; FT_Stream_IoFunc read; FT_Stream_CloseFunc close; FT_Memory memory; unsigned char * cursor; unsigned char * limit; } FT_StreamRec ; A structure used to describe an input stream.","title":"FT_StreamRec"},{"location":"ft2-t1_cid_driver.html","text":"FreeType \u00bb Docs \u00bb Controlling FreeType Modules \u00bb The Type 1 and CID drivers The Type 1 and CID drivers \u00b6 Synopsis \u00b6 It is possible to control the behaviour of FreeType's Type 1 and Type 1 CID drivers with FT_Property_Set and FT_Property_Get . Behind the scenes, both drivers use the Adobe CFF engine for hinting; however, the used properties must be specified separately. The Type 1 driver's module name is \u2018type1\u2019; the CID driver's module name is \u2018t1cid\u2019. Available properties are hinting-engine , no-stem-darkening , darkening-parameters , and random-seed , as documented in the \u2018 Driver properties \u2019 section. Please see the \u2018 The CFF driver \u2019 section for more details on the new hinting engine.","title":"The Type 1 and CID drivers"},{"location":"ft2-t1_cid_driver.html#the-type-1-and-cid-drivers","text":"","title":"The Type 1 and CID drivers"},{"location":"ft2-t1_cid_driver.html#synopsis","text":"It is possible to control the behaviour of FreeType's Type 1 and Type 1 CID drivers with FT_Property_Set and FT_Property_Get . Behind the scenes, both drivers use the Adobe CFF engine for hinting; however, the used properties must be specified separately. The Type 1 driver's module name is \u2018type1\u2019; the CID driver's module name is \u2018t1cid\u2019. Available properties are hinting-engine , no-stem-darkening , darkening-parameters , and random-seed , as documented in the \u2018 Driver properties \u2019 section. Please see the \u2018 The CFF driver \u2019 section for more details on the new hinting engine.","title":"Synopsis"},{"location":"ft2-truetype_engine.html","text":"FreeType \u00bb Docs \u00bb Miscellaneous \u00bb The TrueType Engine The TrueType Engine \u00b6 Synopsis \u00b6 This section contains a function used to query the level of TrueType bytecode support compiled in this version of the library. FT_TrueTypeEngineType \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). typedef enum FT_TrueTypeEngineType_ { FT_TRUETYPE_ENGINE_TYPE_NONE = 0, FT_TRUETYPE_ENGINE_TYPE_UNPATENTED , FT_TRUETYPE_ENGINE_TYPE_PATENTED } FT_TrueTypeEngineType ; A list of values describing which kind of TrueType bytecode engine is implemented in a given FT_Library instance. It is used by the FT_Get_TrueType_Engine_Type function. values FT_TRUETYPE_ENGINE_TYPE_NONE The library doesn't implement any kind of bytecode interpreter. FT_TRUETYPE_ENGINE_TYPE_UNPATENTED Deprecated and removed. FT_TRUETYPE_ENGINE_TYPE_PATENTED The library implements a bytecode interpreter that covers the full instruction set of the TrueType virtual machine (this was governed by patents until May 2010, hence the name). since 2.2 FT_Get_TrueType_Engine_Type \u00b6 Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_TrueTypeEngineType ) FT_Get_TrueType_Engine_Type ( FT_Library library ); Return an FT_TrueTypeEngineType value to indicate which level of the TrueType virtual machine a given library instance supports. input library A library instance. return A value indicating which level is supported. since 2.2","title":"The TrueType Engine"},{"location":"ft2-truetype_engine.html#the-truetype-engine","text":"","title":"The TrueType Engine"},{"location":"ft2-truetype_engine.html#synopsis","text":"This section contains a function used to query the level of TrueType bytecode support compiled in this version of the library.","title":"Synopsis"},{"location":"ft2-truetype_engine.html#ft_truetypeenginetype","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). typedef enum FT_TrueTypeEngineType_ { FT_TRUETYPE_ENGINE_TYPE_NONE = 0, FT_TRUETYPE_ENGINE_TYPE_UNPATENTED , FT_TRUETYPE_ENGINE_TYPE_PATENTED } FT_TrueTypeEngineType ; A list of values describing which kind of TrueType bytecode engine is implemented in a given FT_Library instance. It is used by the FT_Get_TrueType_Engine_Type function.","title":"FT_TrueTypeEngineType"},{"location":"ft2-truetype_engine.html#ft_get_truetype_engine_type","text":"Defined in FT_MODULE_H (freetype/ftmodapi.h). FT_EXPORT( FT_TrueTypeEngineType ) FT_Get_TrueType_Engine_Type ( FT_Library library ); Return an FT_TrueTypeEngineType value to indicate which level of the TrueType virtual machine a given library instance supports.","title":"FT_Get_TrueType_Engine_Type"},{"location":"ft2-truetype_tables.html","text":"FreeType \u00bb Docs \u00bb Format-Specific API \u00bb TrueType Tables TrueType Tables \u00b6 Synopsis \u00b6 This section contains definitions of some basic tables specific to TrueType and OpenType as well as some routines used to access and process them. TT_Header \u00b6 Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef struct TT_Header_ { FT_Fixed Table_Version; FT_Fixed Font_Revision; FT_Long CheckSum_Adjust; FT_Long Magic_Number; FT_UShort Flags; FT_UShort Units_Per_EM; FT_ULong Created [2]; FT_ULong Modified[2]; FT_Short xMin; FT_Short yMin; FT_Short xMax; FT_Short yMax; FT_UShort Mac_Style; FT_UShort Lowest_Rec_PPEM; FT_Short Font_Direction; FT_Short Index_To_Loc_Format; FT_Short Glyph_Data_Format; } TT_Header ; A structure to model a TrueType font header table. All fields follow the OpenType specification. The 64-bit timestamps are stored in two-element arrays Created and Modified , first the upper then the lower 32 bits. TT_HoriHeader \u00b6 Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef struct TT_HoriHeader_ { FT_Fixed Version; FT_Short Ascender; FT_Short Descender; FT_Short Line_Gap; FT_UShort advance_Width_Max; /* advance width maximum */ FT_Short min_Left_Side_Bearing; /* minimum left-sb */ FT_Short min_Right_Side_Bearing; /* minimum right-sb */ FT_Short xMax_Extent; /* xmax extents */ FT_Short caret_Slope_Rise; FT_Short caret_Slope_Run; FT_Short caret_Offset; FT_Short Reserved[4]; FT_Short metric_Data_Format; FT_UShort number_Of_HMetrics; /* The following fields are not defined by the OpenType specification */ /* but they are used to connect the metrics header to the relevant */ /* 'hmtx' table. */ void * long_metrics; void * short_metrics; } TT_HoriHeader ; A structure to model a TrueType horizontal header, the \u2018hhea\u2019 table, as well as the corresponding horizontal metrics table, \u2018hmtx\u2019. fields Version The table version. Ascender The font's ascender, i.e., the distance from the baseline to the top-most of all glyph points found in the font. This value is invalid in many fonts, as it is usually set by the font designer, and often reflects only a portion of the glyphs found in the font (maybe ASCII). You should use the sTypoAscender field of the \u2018OS/2\u2019 table instead if you want the correct one. Descender The font's descender, i.e., the distance from the baseline to the bottom-most of all glyph points found in the font. It is negative. This value is invalid in many fonts, as it is usually set by the font designer, and often reflects only a portion of the glyphs found in the font (maybe ASCII). You should use the sTypoDescender field of the \u2018OS/2\u2019 table instead if you want the correct one. Line_Gap The font's line gap, i.e., the distance to add to the ascender and descender to get the BTB, i.e., the baseline-to-baseline distance for the font. advance_Width_Max This field is the maximum of all advance widths found in the font. It can be used to compute the maximum width of an arbitrary string of text. min_Left_Side_Bearing The minimum left side bearing of all glyphs within the font. min_Right_Side_Bearing The minimum right side bearing of all glyphs within the font. xMax_Extent The maximum horizontal extent (i.e., the \u2018width\u2019 of a glyph's bounding box) for all glyphs in the font. caret_Slope_Rise The rise coefficient of the cursor's slope of the cursor (slope=rise/run). caret_Slope_Run The run coefficient of the cursor's slope. caret_Offset The cursor's offset for slanted fonts. Reserved 8 reserved bytes. metric_Data_Format Always 0. number_Of_HMetrics Number of HMetrics entries in the \u2018hmtx\u2019 table -- this value can be smaller than the total number of glyphs in the font. long_metrics A pointer into the \u2018hmtx\u2019 table. short_metrics A pointer into the \u2018hmtx\u2019 table. note For an OpenType variation font, the values of the following fields can change after a call to FT_Set_Var_Design_Coordinates (and friends) if the font contains an \u2018MVAR\u2019 table: caret_Slope_Rise , caret_Slope_Run , and caret_Offset . TT_VertHeader \u00b6 Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef struct TT_VertHeader_ { FT_Fixed Version; FT_Short Ascender; FT_Short Descender; FT_Short Line_Gap; FT_UShort advance_Height_Max; /* advance height maximum */ FT_Short min_Top_Side_Bearing; /* minimum top-sb */ FT_Short min_Bottom_Side_Bearing; /* minimum bottom-sb */ FT_Short yMax_Extent; /* ymax extents */ FT_Short caret_Slope_Rise; FT_Short caret_Slope_Run; FT_Short caret_Offset; FT_Short Reserved[4]; FT_Short metric_Data_Format; FT_UShort number_Of_VMetrics; /* The following fields are not defined by the OpenType specification */ /* but they are used to connect the metrics header to the relevant */ /* 'vmtx' table. */ void * long_metrics; void * short_metrics; } TT_VertHeader ; A structure used to model a TrueType vertical header, the \u2018vhea\u2019 table, as well as the corresponding vertical metrics table, \u2018vmtx\u2019. fields Version The table version. Ascender The font's ascender, i.e., the distance from the baseline to the top-most of all glyph points found in the font. This value is invalid in many fonts, as it is usually set by the font designer, and often reflects only a portion of the glyphs found in the font (maybe ASCII). You should use the sTypoAscender field of the \u2018OS/2\u2019 table instead if you want the correct one. Descender The font's descender, i.e., the distance from the baseline to the bottom-most of all glyph points found in the font. It is negative. This value is invalid in many fonts, as it is usually set by the font designer, and often reflects only a portion of the glyphs found in the font (maybe ASCII). You should use the sTypoDescender field of the \u2018OS/2\u2019 table instead if you want the correct one. Line_Gap The font's line gap, i.e., the distance to add to the ascender and descender to get the BTB, i.e., the baseline-to-baseline distance for the font. advance_Height_Max This field is the maximum of all advance heights found in the font. It can be used to compute the maximum height of an arbitrary string of text. min_Top_Side_Bearing The minimum top side bearing of all glyphs within the font. min_Bottom_Side_Bearing The minimum bottom side bearing of all glyphs within the font. yMax_Extent The maximum vertical extent (i.e., the \u2018height\u2019 of a glyph's bounding box) for all glyphs in the font. caret_Slope_Rise The rise coefficient of the cursor's slope of the cursor (slope=rise/run). caret_Slope_Run The run coefficient of the cursor's slope. caret_Offset The cursor's offset for slanted fonts. Reserved 8 reserved bytes. metric_Data_Format Always 0. number_Of_VMetrics Number of VMetrics entries in the \u2018vmtx\u2019 table -- this value can be smaller than the total number of glyphs in the font. long_metrics A pointer into the \u2018vmtx\u2019 table. short_metrics A pointer into the \u2018vmtx\u2019 table. note For an OpenType variation font, the values of the following fields can change after a call to FT_Set_Var_Design_Coordinates (and friends) if the font contains an \u2018MVAR\u2019 table: Ascender , Descender , Line_Gap , caret_Slope_Rise , caret_Slope_Run , and caret_Offset . TT_OS2 \u00b6 Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef struct TT_OS2_ { FT_UShort version; /* 0x0001 - more or 0xFFFF */ FT_Short xAvgCharWidth; FT_UShort usWeightClass; FT_UShort usWidthClass; FT_UShort fsType; FT_Short ySubscriptXSize; FT_Short ySubscriptYSize; FT_Short ySubscriptXOffset; FT_Short ySubscriptYOffset; FT_Short ySuperscriptXSize; FT_Short ySuperscriptYSize; FT_Short ySuperscriptXOffset; FT_Short ySuperscriptYOffset; FT_Short yStrikeoutSize; FT_Short yStrikeoutPosition; FT_Short sFamilyClass; FT_Byte panose[10]; FT_ULong ulUnicodeRange1; /* Bits 0-31 */ FT_ULong ulUnicodeRange2; /* Bits 32-63 */ FT_ULong ulUnicodeRange3; /* Bits 64-95 */ FT_ULong ulUnicodeRange4; /* Bits 96-127 */ FT_Char achVendID[4]; FT_UShort fsSelection; FT_UShort usFirstCharIndex; FT_UShort usLastCharIndex; FT_Short sTypoAscender; FT_Short sTypoDescender; FT_Short sTypoLineGap; FT_UShort usWinAscent; FT_UShort usWinDescent; /* only version 1 and higher: */ FT_ULong ulCodePageRange1; /* Bits 0-31 */ FT_ULong ulCodePageRange2; /* Bits 32-63 */ /* only version 2 and higher: */ FT_Short sxHeight; FT_Short sCapHeight; FT_UShort usDefaultChar; FT_UShort usBreakChar; FT_UShort usMaxContext; /* only version 5 and higher: */ FT_UShort usLowerOpticalPointSize; /* in twips (1/20th points) */ FT_UShort usUpperOpticalPointSize; /* in twips (1/20th points) */ } TT_OS2 ; A structure to model a TrueType \u2018OS/2\u2019 table. All fields comply to the OpenType specification. Note that we now support old Mac fonts that do not include an \u2018OS/2\u2019 table. In this case, the version field is always set to 0xFFFF. note For an OpenType variation font, the values of the following fields can change after a call to FT_Set_Var_Design_Coordinates (and friends) if the font contains an \u2018MVAR\u2019 table: sCapHeight , sTypoAscender , sTypoDescender , sTypoLineGap , sxHeight , usWinAscent , usWinDescent , yStrikeoutPosition , yStrikeoutSize , ySubscriptXOffset , ySubScriptXSize , ySubscriptYOffset , ySubscriptYSize , ySuperscriptXOffset , ySuperscriptXSize , ySuperscriptYOffset , and ySuperscriptYSize . Possible values for bits in the ulUnicodeRangeX fields are given by the TT_UCR_XXX macros. TT_Postscript \u00b6 Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef struct TT_Postscript_ { FT_Fixed FormatType; FT_Fixed italicAngle; FT_Short underlinePosition; FT_Short underlineThickness; FT_ULong isFixedPitch; FT_ULong minMemType42; FT_ULong maxMemType42; FT_ULong minMemType1; FT_ULong maxMemType1; /* Glyph names follow in the 'post' table, but we don't */ /* load them by default. */ } TT_Postscript ; A structure to model a TrueType \u2018post\u2019 table. All fields comply to the OpenType specification. This structure does not reference a font's PostScript glyph names; use FT_Get_Glyph_Name to retrieve them. note For an OpenType variation font, the values of the following fields can change after a call to FT_Set_Var_Design_Coordinates (and friends) if the font contains an \u2018MVAR\u2019 table: underlinePosition and underlineThickness . TT_PCLT \u00b6 Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef struct TT_PCLT_ { FT_Fixed Version; FT_ULong FontNumber; FT_UShort Pitch; FT_UShort xHeight; FT_UShort Style; FT_UShort TypeFamily; FT_UShort CapHeight; FT_UShort SymbolSet; FT_Char TypeFace[16]; FT_Char CharacterComplement[8]; FT_Char FileName[6]; FT_Char StrokeWeight; FT_Char WidthType; FT_Byte SerifStyle; FT_Byte Reserved; } TT_PCLT ; A structure to model a TrueType \u2018PCLT\u2019 table. All fields comply to the OpenType specification. TT_MaxProfile \u00b6 Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef struct TT_MaxProfile_ { FT_Fixed version; FT_UShort numGlyphs; FT_UShort maxPoints; FT_UShort maxContours; FT_UShort maxCompositePoints; FT_UShort maxCompositeContours; FT_UShort maxZones; FT_UShort maxTwilightPoints; FT_UShort maxStorage; FT_UShort maxFunctionDefs; FT_UShort maxInstructionDefs; FT_UShort maxStackElements; FT_UShort maxSizeOfInstructions; FT_UShort maxComponentElements; FT_UShort maxComponentDepth; } TT_MaxProfile ; The maximum profile (\u2018maxp\u2019) table contains many max values, which can be used to pre-allocate arrays for speeding up glyph loading and hinting. fields version The version number. numGlyphs The number of glyphs in this TrueType font. maxPoints The maximum number of points in a non-composite TrueType glyph. See also maxCompositePoints . maxContours The maximum number of contours in a non-composite TrueType glyph. See also maxCompositeContours . maxCompositePoints The maximum number of points in a composite TrueType glyph. See also maxPoints . maxCompositeContours The maximum number of contours in a composite TrueType glyph. See also maxContours . maxZones The maximum number of zones used for glyph hinting. maxTwilightPoints The maximum number of points in the twilight zone used for glyph hinting. maxStorage The maximum number of elements in the storage area used for glyph hinting. maxFunctionDefs The maximum number of function definitions in the TrueType bytecode for this font. maxInstructionDefs The maximum number of instruction definitions in the TrueType bytecode for this font. maxStackElements The maximum number of stack elements used during bytecode interpretation. maxSizeOfInstructions The maximum number of TrueType opcodes used for glyph hinting. maxComponentElements The maximum number of simple (i.e., non-composite) glyphs in a composite glyph. maxComponentDepth The maximum nesting depth of composite glyphs. note This structure is only used during font loading. FT_Sfnt_Tag \u00b6 Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef enum FT_Sfnt_Tag_ { FT_SFNT_HEAD , FT_SFNT_MAXP , FT_SFNT_OS2 , FT_SFNT_HHEA , FT_SFNT_VHEA , FT_SFNT_POST , FT_SFNT_PCLT , FT_SFNT_MAX } FT_Sfnt_Tag ; /* these constants are deprecated; use the corresponding ` FT_Sfnt_Tag ` */ /* values instead */ # define ft_sfnt_head FT_SFNT_HEAD # define ft_sfnt_maxp FT_SFNT_MAXP # define ft_sfnt_os2 FT_SFNT_OS2 # define ft_sfnt_hhea FT_SFNT_HHEA # define ft_sfnt_vhea FT_SFNT_VHEA # define ft_sfnt_post FT_SFNT_POST # define ft_sfnt_pclt FT_SFNT_PCLT An enumeration to specify indices of SFNT tables loaded and parsed by FreeType during initialization of an SFNT font. Used in the FT_Get_Sfnt_Table API function. values FT_SFNT_HEAD To access the font's TT_Header structure. FT_SFNT_MAXP To access the font's TT_MaxProfile structure. FT_SFNT_OS2 To access the font's TT_OS2 structure. FT_SFNT_HHEA To access the font's TT_HoriHeader structure. FT_SFNT_VHEA To access the font's TT_VertHeader structure. FT_SFNT_POST To access the font's TT_Postscript structure. FT_SFNT_PCLT To access the font's TT_PCLT structure. FT_Get_Sfnt_Table \u00b6 Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). FT_EXPORT( void * ) FT_Get_Sfnt_Table ( FT_Face face, FT_Sfnt_Tag tag ); Return a pointer to a given SFNT table stored within a face. input face A handle to the source. tag The index of the SFNT table. return A type-less pointer to the table. This will be NULL in case of error, or if the corresponding table was not found OR loaded from the file. Use a typecast according to tag to access the structure elements. note The table is owned by the face object and disappears with it. This function is only useful to access SFNT tables that are loaded by the sfnt, truetype, and opentype drivers. See FT_Sfnt_Tag for a list. example Here is an example demonstrating access to the \u2018vhea\u2019 table. TT_VertHeader* vert_header; vert_header = (TT_VertHeader*)FT_Get_Sfnt_Table( face, FT_SFNT_VHEA ); FT_Load_Sfnt_Table \u00b6 Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). FT_EXPORT( FT_Error ) FT_Load_Sfnt_Table ( FT_Face face, FT_ULong tag, FT_Long offset, FT_Byte * buffer, FT_ULong * length ); Load any SFNT font table into client memory. input face A handle to the source face. tag The four-byte tag of the table to load. Use value 0 if you want to access the whole font file. Otherwise, you can use one of the definitions found in the FT_TRUETYPE_TAGS_H file, or forge a new one with FT_MAKE_TAG . offset The starting offset in the table (or file if tag == 0). output buffer The target buffer address. The client must ensure that the memory array is big enough to hold the data. inout length If the length parameter is NULL , try to load the whole table. Return an error code if it fails. Else, if *length is 0, exit immediately while returning the table's (or file) full size in it. Else the number of bytes to read from the table or file, from the starting offset. return FreeType error code. 0 means success. note If you need to determine the table's length you should first call this function with *length set to 0, as in the following example: FT_ULong length = 0; error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length ); if ( error ) { ... table does not exist ... } buffer = malloc( length ); if ( buffer == NULL ) { ... not enough memory ... } error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length ); if ( error ) { ... could not load table ... } Note that structures like TT_Header or TT_OS2 can't be used with this function; they are limited to FT_Get_Sfnt_Table . Reason is that those structures depend on the processor architecture, with varying size (e.g. 32bit vs. 64bit) or order (big endian vs. little endian). FT_Sfnt_Table_Info \u00b6 Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). FT_EXPORT( FT_Error ) FT_Sfnt_Table_Info ( FT_Face face, FT_UInt table_index, FT_ULong *tag, FT_ULong *length ); Return information on an SFNT table. input face A handle to the source face. table_index The index of an SFNT table. The function returns FT_Err_Table_Missing for an invalid value. inout tag The name tag of the SFNT table. If the value is NULL , table_index is ignored, and length returns the number of SFNT tables in the font. output length The length of the SFNT table (or the number of SFNT tables, depending on tag ). return FreeType error code. 0 means success. note While parsing fonts, FreeType handles SFNT tables with length zero as missing. FT_Get_CMap_Language_ID \u00b6 Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). FT_EXPORT( FT_ULong ) FT_Get_CMap_Language_ID ( FT_CharMap charmap ); Return cmap language ID as specified in the OpenType standard. Definitions of language ID values are in file FT_TRUETYPE_IDS_H . input charmap The target charmap. return The language ID of charmap . If charmap doesn't belong to an SFNT face, just return 0 as the default value. For a format 14 cmap (to access Unicode IVS), the return value is 0xFFFFFFFF. FT_Get_CMap_Format \u00b6 Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). FT_EXPORT( FT_Long ) FT_Get_CMap_Format ( FT_CharMap charmap ); Return the format of an SFNT \u2018cmap\u2019 table. input charmap The target charmap. return The format of charmap . If charmap doesn't belong to an SFNT face, return -1. FT_PARAM_TAG_UNPATENTED_HINTING \u00b6 # define FT_PARAM_TAG_UNPATENTED_HINTING \\ FT_MAKE_TAG ( 'u', 'n', 'p', 'a' ) Deprecated, no effect. Previously: A constant used as the tag of an FT_Parameter structure to indicate that unpatented methods only should be used by the TrueType bytecode interpreter for a typeface opened by FT_Open_Face . TT_PLATFORM_XXX \u00b6 Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_PLATFORM_APPLE_UNICODE 0 # define TT_PLATFORM_MACINTOSH 1 # define TT_PLATFORM_ISO 2 /* deprecated */ # define TT_PLATFORM_MICROSOFT 3 # define TT_PLATFORM_CUSTOM 4 # define TT_PLATFORM_ADOBE 7 /* artificial */ A list of valid values for the platform_id identifier code in FT_CharMapRec and FT_SfntName structures. values TT_PLATFORM_APPLE_UNICODE Used by Apple to indicate a Unicode character map and/or name entry. See TT_APPLE_ID_XXX for corresponding encoding_id values. Note that name entries in this format are coded as big-endian UCS-2 character codes only . TT_PLATFORM_MACINTOSH Used by Apple to indicate a MacOS-specific charmap and/or name entry. See TT_MAC_ID_XXX for corresponding encoding_id values. Note that most TrueType fonts contain an Apple roman charmap to be usable on MacOS systems (even if they contain a Microsoft charmap as well). TT_PLATFORM_ISO This value was used to specify ISO/IEC 10646 charmaps. It is however now deprecated. See TT_ISO_ID_XXX for a list of corresponding encoding_id values. TT_PLATFORM_MICROSOFT Used by Microsoft to indicate Windows-specific charmaps. See TT_MS_ID_XXX for a list of corresponding encoding_id values. Note that most fonts contain a Unicode charmap using ( TT_PLATFORM_MICROSOFT , TT_MS_ID_UNICODE_CS ). TT_PLATFORM_CUSTOM Used to indicate application-specific charmaps. TT_PLATFORM_ADOBE This value isn't part of any font format specification, but is used by FreeType to report Adobe-specific charmaps in an FT_CharMapRec structure. See TT_ADOBE_ID_XXX . TT_APPLE_ID_XXX \u00b6 Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_APPLE_ID_DEFAULT 0 /* Unicode 1.0 */ # define TT_APPLE_ID_UNICODE_1_1 1 /* specify Hangul at U+34xx */ # define TT_APPLE_ID_ISO_10646 2 /* deprecated */ # define TT_APPLE_ID_UNICODE_2_0 3 /* or later */ # define TT_APPLE_ID_UNICODE_32 4 /* 2.0 or later, full repertoire */ # define TT_APPLE_ID_VARIANT_SELECTOR 5 /* variation selector data */ # define TT_APPLE_ID_FULL_UNICODE 6 /* used with type 13 cmaps */ A list of valid values for the encoding_id for TT_PLATFORM_APPLE_UNICODE charmaps and name entries. values TT_APPLE_ID_DEFAULT Unicode version 1.0. TT_APPLE_ID_UNICODE_1_1 Unicode 1.1; specifies Hangul characters starting at U+34xx. TT_APPLE_ID_ISO_10646 Deprecated (identical to preceding). TT_APPLE_ID_UNICODE_2_0 Unicode 2.0 and beyond (UTF-16 BMP only). TT_APPLE_ID_UNICODE_32 Unicode 3.1 and beyond, using UTF-32. TT_APPLE_ID_VARIANT_SELECTOR From Adobe, not Apple. Not a normal cmap. Specifies variations on a real cmap. TT_APPLE_ID_FULL_UNICODE Used for fallback fonts that provide complete Unicode coverage with a type 13 cmap. TT_MAC_ID_XXX \u00b6 Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_MAC_ID_ROMAN 0 # define TT_MAC_ID_JAPANESE 1 # define TT_MAC_ID_TRADITIONAL_CHINESE 2 # define TT_MAC_ID_KOREAN 3 # define TT_MAC_ID_ARABIC 4 # define TT_MAC_ID_HEBREW 5 # define TT_MAC_ID_GREEK 6 # define TT_MAC_ID_RUSSIAN 7 # define TT_MAC_ID_RSYMBOL 8 # define TT_MAC_ID_DEVANAGARI 9 # define TT_MAC_ID_GURMUKHI 10 # define TT_MAC_ID_GUJARATI 11 # define TT_MAC_ID_ORIYA 12 # define TT_MAC_ID_BENGALI 13 # define TT_MAC_ID_TAMIL 14 # define TT_MAC_ID_TELUGU 15 # define TT_MAC_ID_KANNADA 16 # define TT_MAC_ID_MALAYALAM 17 # define TT_MAC_ID_SINHALESE 18 # define TT_MAC_ID_BURMESE 19 # define TT_MAC_ID_KHMER 20 # define TT_MAC_ID_THAI 21 # define TT_MAC_ID_LAOTIAN 22 # define TT_MAC_ID_GEORGIAN 23 # define TT_MAC_ID_ARMENIAN 24 # define TT_MAC_ID_MALDIVIAN 25 # define TT_MAC_ID_SIMPLIFIED_CHINESE 25 # define TT_MAC_ID_TIBETAN 26 # define TT_MAC_ID_MONGOLIAN 27 # define TT_MAC_ID_GEEZ 28 # define TT_MAC_ID_SLAVIC 29 # define TT_MAC_ID_VIETNAMESE 30 # define TT_MAC_ID_SINDHI 31 # define TT_MAC_ID_UNINTERP 32 A list of valid values for the encoding_id for TT_PLATFORM_MACINTOSH charmaps and name entries. TT_ISO_ID_XXX \u00b6 Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_ISO_ID_7BIT_ASCII 0 # define TT_ISO_ID_10646 1 # define TT_ISO_ID_8859_1 2 A list of valid values for the encoding_id for TT_PLATFORM_ISO charmaps and name entries. Their use is now deprecated. values TT_ISO_ID_7BIT_ASCII ASCII. TT_ISO_ID_10646 ISO/10646. TT_ISO_ID_8859_1 Also known as Latin-1. TT_MS_ID_XXX \u00b6 Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_MS_ID_SYMBOL_CS 0 # define TT_MS_ID_UNICODE_CS 1 # define TT_MS_ID_SJIS 2 # define TT_MS_ID_PRC 3 # define TT_MS_ID_BIG_5 4 # define TT_MS_ID_WANSUNG 5 # define TT_MS_ID_JOHAB 6 # define TT_MS_ID_UCS_4 10 /* this value is deprecated */ # define TT_MS_ID_GB2312 TT_MS_ID_PRC A list of valid values for the encoding_id for TT_PLATFORM_MICROSOFT charmaps and name entries. values TT_MS_ID_SYMBOL_CS Microsoft symbol encoding. See FT_ENCODING_MS_SYMBOL . TT_MS_ID_UNICODE_CS Microsoft WGL4 charmap, matching Unicode. See FT_ENCODING_UNICODE . TT_MS_ID_SJIS Shift JIS Japanese encoding. See FT_ENCODING_SJIS . TT_MS_ID_PRC Chinese encodings as used in the People's Republic of China (PRC). This means the encodings GB 2312 and its supersets GBK and GB 18030. See FT_ENCODING_PRC . TT_MS_ID_BIG_5 Traditional Chinese as used in Taiwan and Hong Kong. See FT_ENCODING_BIG5 . TT_MS_ID_WANSUNG Korean Extended Wansung encoding. See FT_ENCODING_WANSUNG . TT_MS_ID_JOHAB Korean Johab encoding. See FT_ENCODING_JOHAB . TT_MS_ID_UCS_4 UCS-4 or UTF-32 charmaps. This has been added to the OpenType specification version 1.4 (mid-2001). TT_ADOBE_ID_XXX \u00b6 Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_ADOBE_ID_STANDARD 0 # define TT_ADOBE_ID_EXPERT 1 # define TT_ADOBE_ID_CUSTOM 2 # define TT_ADOBE_ID_LATIN_1 3 A list of valid values for the encoding_id for TT_PLATFORM_ADOBE charmaps. This is a FreeType-specific extension! values TT_ADOBE_ID_STANDARD Adobe standard encoding. TT_ADOBE_ID_EXPERT Adobe expert encoding. TT_ADOBE_ID_CUSTOM Adobe custom encoding. TT_ADOBE_ID_LATIN_1 Adobe Latin 1 encoding. TT_MAC_LANGID_XXX \u00b6 Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_MAC_LANGID_ENGLISH 0 # define TT_MAC_LANGID_FRENCH 1 # define TT_MAC_LANGID_GERMAN 2 # define TT_MAC_LANGID_ITALIAN 3 # define TT_MAC_LANGID_DUTCH 4 # define TT_MAC_LANGID_SWEDISH 5 # define TT_MAC_LANGID_SPANISH 6 # define TT_MAC_LANGID_DANISH 7 # define TT_MAC_LANGID_PORTUGUESE 8 # define TT_MAC_LANGID_NORWEGIAN 9 # define TT_MAC_LANGID_HEBREW 10 # define TT_MAC_LANGID_JAPANESE 11 # define TT_MAC_LANGID_ARABIC 12 # define TT_MAC_LANGID_FINNISH 13 # define TT_MAC_LANGID_GREEK 14 # define TT_MAC_LANGID_ICELANDIC 15 # define TT_MAC_LANGID_MALTESE 16 # define TT_MAC_LANGID_TURKISH 17 # define TT_MAC_LANGID_CROATIAN 18 # define TT_MAC_LANGID_CHINESE_TRADITIONAL 19 # define TT_MAC_LANGID_URDU 20 # define TT_MAC_LANGID_HINDI 21 # define TT_MAC_LANGID_THAI 22 # define TT_MAC_LANGID_KOREAN 23 # define TT_MAC_LANGID_LITHUANIAN 24 # define TT_MAC_LANGID_POLISH 25 # define TT_MAC_LANGID_HUNGARIAN 26 # define TT_MAC_LANGID_ESTONIAN 27 # define TT_MAC_LANGID_LETTISH 28 # define TT_MAC_LANGID_SAAMISK 29 # define TT_MAC_LANGID_FAEROESE 30 # define TT_MAC_LANGID_FARSI 31 # define TT_MAC_LANGID_RUSSIAN 32 # define TT_MAC_LANGID_CHINESE_SIMPLIFIED 33 # define TT_MAC_LANGID_FLEMISH 34 # define TT_MAC_LANGID_IRISH 35 # define TT_MAC_LANGID_ALBANIAN 36 # define TT_MAC_LANGID_ROMANIAN 37 # define TT_MAC_LANGID_CZECH 38 # define TT_MAC_LANGID_SLOVAK 39 # define TT_MAC_LANGID_SLOVENIAN 40 # define TT_MAC_LANGID_YIDDISH 41 # define TT_MAC_LANGID_SERBIAN 42 # define TT_MAC_LANGID_MACEDONIAN 43 # define TT_MAC_LANGID_BULGARIAN 44 # define TT_MAC_LANGID_UKRAINIAN 45 # define TT_MAC_LANGID_BYELORUSSIAN 46 # define TT_MAC_LANGID_UZBEK 47 # define TT_MAC_LANGID_KAZAKH 48 # define TT_MAC_LANGID_AZERBAIJANI 49 # define TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT 49 # define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT 50 # define TT_MAC_LANGID_ARMENIAN 51 # define TT_MAC_LANGID_GEORGIAN 52 # define TT_MAC_LANGID_MOLDAVIAN 53 # define TT_MAC_LANGID_KIRGHIZ 54 # define TT_MAC_LANGID_TAJIKI 55 # define TT_MAC_LANGID_TURKMEN 56 # define TT_MAC_LANGID_MONGOLIAN 57 # define TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT 57 # define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT 58 # define TT_MAC_LANGID_PASHTO 59 # define TT_MAC_LANGID_KURDISH 60 # define TT_MAC_LANGID_KASHMIRI 61 # define TT_MAC_LANGID_SINDHI 62 # define TT_MAC_LANGID_TIBETAN 63 # define TT_MAC_LANGID_NEPALI 64 # define TT_MAC_LANGID_SANSKRIT 65 # define TT_MAC_LANGID_MARATHI 66 # define TT_MAC_LANGID_BENGALI 67 # define TT_MAC_LANGID_ASSAMESE 68 # define TT_MAC_LANGID_GUJARATI 69 # define TT_MAC_LANGID_PUNJABI 70 # define TT_MAC_LANGID_ORIYA 71 # define TT_MAC_LANGID_MALAYALAM 72 # define TT_MAC_LANGID_KANNADA 73 # define TT_MAC_LANGID_TAMIL 74 # define TT_MAC_LANGID_TELUGU 75 # define TT_MAC_LANGID_SINHALESE 76 # define TT_MAC_LANGID_BURMESE 77 # define TT_MAC_LANGID_KHMER 78 # define TT_MAC_LANGID_LAO 79 # define TT_MAC_LANGID_VIETNAMESE 80 # define TT_MAC_LANGID_INDONESIAN 81 # define TT_MAC_LANGID_TAGALOG 82 # define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT 83 # define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT 84 # define TT_MAC_LANGID_AMHARIC 85 # define TT_MAC_LANGID_TIGRINYA 86 # define TT_MAC_LANGID_GALLA 87 # define TT_MAC_LANGID_SOMALI 88 # define TT_MAC_LANGID_SWAHILI 89 # define TT_MAC_LANGID_RUANDA 90 # define TT_MAC_LANGID_RUNDI 91 # define TT_MAC_LANGID_CHEWA 92 # define TT_MAC_LANGID_MALAGASY 93 # define TT_MAC_LANGID_ESPERANTO 94 # define TT_MAC_LANGID_WELSH 128 # define TT_MAC_LANGID_BASQUE 129 # define TT_MAC_LANGID_CATALAN 130 # define TT_MAC_LANGID_LATIN 131 # define TT_MAC_LANGID_QUECHUA 132 # define TT_MAC_LANGID_GUARANI 133 # define TT_MAC_LANGID_AYMARA 134 # define TT_MAC_LANGID_TATAR 135 # define TT_MAC_LANGID_UIGHUR 136 # define TT_MAC_LANGID_DZONGKHA 137 # define TT_MAC_LANGID_JAVANESE 138 # define TT_MAC_LANGID_SUNDANESE 139 /* The following codes are new as of 2000-03-10 */ # define TT_MAC_LANGID_GALICIAN 140 # define TT_MAC_LANGID_AFRIKAANS 141 # define TT_MAC_LANGID_BRETON 142 # define TT_MAC_LANGID_INUKTITUT 143 # define TT_MAC_LANGID_SCOTTISH_GAELIC 144 # define TT_MAC_LANGID_MANX_GAELIC 145 # define TT_MAC_LANGID_IRISH_GAELIC 146 # define TT_MAC_LANGID_TONGAN 147 # define TT_MAC_LANGID_GREEK_POLYTONIC 148 # define TT_MAC_LANGID_GREELANDIC 149 # define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT 150 Possible values of the language identifier field in the name records of the SFNT \u2018name\u2019 table if the \u2018platform\u2019 identifier code is TT_PLATFORM_MACINTOSH . These values are also used as return values for function FT_Get_CMap_Language_ID . The canonical source for Apple's IDs is https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html TT_MS_LANGID_XXX \u00b6 Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_MS_LANGID_ARABIC_SAUDI_ARABIA 0x0401 # define TT_MS_LANGID_ARABIC_IRAQ 0x0801 # define TT_MS_LANGID_ARABIC_EGYPT 0x0C01 # define TT_MS_LANGID_ARABIC_LIBYA 0x1001 # define TT_MS_LANGID_ARABIC_ALGERIA 0x1401 # define TT_MS_LANGID_ARABIC_MOROCCO 0x1801 # define TT_MS_LANGID_ARABIC_TUNISIA 0x1C01 # define TT_MS_LANGID_ARABIC_OMAN 0x2001 # define TT_MS_LANGID_ARABIC_YEMEN 0x2401 # define TT_MS_LANGID_ARABIC_SYRIA 0x2801 # define TT_MS_LANGID_ARABIC_JORDAN 0x2C01 # define TT_MS_LANGID_ARABIC_LEBANON 0x3001 # define TT_MS_LANGID_ARABIC_KUWAIT 0x3401 # define TT_MS_LANGID_ARABIC_UAE 0x3801 # define TT_MS_LANGID_ARABIC_BAHRAIN 0x3C01 # define TT_MS_LANGID_ARABIC_QATAR 0x4001 # define TT_MS_LANGID_BULGARIAN_BULGARIA 0x0402 # define TT_MS_LANGID_CATALAN_CATALAN 0x0403 # define TT_MS_LANGID_CHINESE_TAIWAN 0x0404 # define TT_MS_LANGID_CHINESE_PRC 0x0804 # define TT_MS_LANGID_CHINESE_HONG_KONG 0x0C04 # define TT_MS_LANGID_CHINESE_SINGAPORE 0x1004 # define TT_MS_LANGID_CHINESE_MACAO 0x1404 # define TT_MS_LANGID_CZECH_CZECH_REPUBLIC 0x0405 # define TT_MS_LANGID_DANISH_DENMARK 0x0406 # define TT_MS_LANGID_GERMAN_GERMANY 0x0407 # define TT_MS_LANGID_GERMAN_SWITZERLAND 0x0807 # define TT_MS_LANGID_GERMAN_AUSTRIA 0x0C07 # define TT_MS_LANGID_GERMAN_LUXEMBOURG 0x1007 # define TT_MS_LANGID_GERMAN_LIECHTENSTEIN 0x1407 # define TT_MS_LANGID_GREEK_GREECE 0x0408 # define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409 # define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM 0x0809 # define TT_MS_LANGID_ENGLISH_AUSTRALIA 0x0C09 # define TT_MS_LANGID_ENGLISH_CANADA 0x1009 # define TT_MS_LANGID_ENGLISH_NEW_ZEALAND 0x1409 # define TT_MS_LANGID_ENGLISH_IRELAND 0x1809 # define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA 0x1C09 # define TT_MS_LANGID_ENGLISH_JAMAICA 0x2009 # define TT_MS_LANGID_ENGLISH_CARIBBEAN 0x2409 # define TT_MS_LANGID_ENGLISH_BELIZE 0x2809 # define TT_MS_LANGID_ENGLISH_TRINIDAD 0x2C09 # define TT_MS_LANGID_ENGLISH_ZIMBABWE 0x3009 # define TT_MS_LANGID_ENGLISH_PHILIPPINES 0x3409 # define TT_MS_LANGID_ENGLISH_INDIA 0x4009 # define TT_MS_LANGID_ENGLISH_MALAYSIA 0x4409 # define TT_MS_LANGID_ENGLISH_SINGAPORE 0x4809 # define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT 0x040A # define TT_MS_LANGID_SPANISH_MEXICO 0x080A # define TT_MS_LANGID_SPANISH_SPAIN_MODERN_SORT 0x0C0A # define TT_MS_LANGID_SPANISH_GUATEMALA 0x100A # define TT_MS_LANGID_SPANISH_COSTA_RICA 0x140A # define TT_MS_LANGID_SPANISH_PANAMA 0x180A # define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC 0x1C0A # define TT_MS_LANGID_SPANISH_VENEZUELA 0x200A # define TT_MS_LANGID_SPANISH_COLOMBIA 0x240A # define TT_MS_LANGID_SPANISH_PERU 0x280A # define TT_MS_LANGID_SPANISH_ARGENTINA 0x2C0A # define TT_MS_LANGID_SPANISH_ECUADOR 0x300A # define TT_MS_LANGID_SPANISH_CHILE 0x340A # define TT_MS_LANGID_SPANISH_URUGUAY 0x380A # define TT_MS_LANGID_SPANISH_PARAGUAY 0x3C0A # define TT_MS_LANGID_SPANISH_BOLIVIA 0x400A # define TT_MS_LANGID_SPANISH_EL_SALVADOR 0x440A # define TT_MS_LANGID_SPANISH_HONDURAS 0x480A # define TT_MS_LANGID_SPANISH_NICARAGUA 0x4C0A # define TT_MS_LANGID_SPANISH_PUERTO_RICO 0x500A # define TT_MS_LANGID_SPANISH_UNITED_STATES 0x540A # define TT_MS_LANGID_FINNISH_FINLAND 0x040B # define TT_MS_LANGID_FRENCH_FRANCE 0x040C # define TT_MS_LANGID_FRENCH_BELGIUM 0x080C # define TT_MS_LANGID_FRENCH_CANADA 0x0C0C # define TT_MS_LANGID_FRENCH_SWITZERLAND 0x100C # define TT_MS_LANGID_FRENCH_LUXEMBOURG 0x140C # define TT_MS_LANGID_FRENCH_MONACO 0x180C # define TT_MS_LANGID_HEBREW_ISRAEL 0x040D # define TT_MS_LANGID_HUNGARIAN_HUNGARY 0x040E # define TT_MS_LANGID_ICELANDIC_ICELAND 0x040F # define TT_MS_LANGID_ITALIAN_ITALY 0x0410 # define TT_MS_LANGID_ITALIAN_SWITZERLAND 0x0810 # define TT_MS_LANGID_JAPANESE_JAPAN 0x0411 # define TT_MS_LANGID_KOREAN_KOREA 0x0412 # define TT_MS_LANGID_DUTCH_NETHERLANDS 0x0413 # define TT_MS_LANGID_DUTCH_BELGIUM 0x0813 # define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL 0x0414 # define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK 0x0814 # define TT_MS_LANGID_POLISH_POLAND 0x0415 # define TT_MS_LANGID_PORTUGUESE_BRAZIL 0x0416 # define TT_MS_LANGID_PORTUGUESE_PORTUGAL 0x0816 # define TT_MS_LANGID_ROMANSH_SWITZERLAND 0x0417 # define TT_MS_LANGID_ROMANIAN_ROMANIA 0x0418 # define TT_MS_LANGID_RUSSIAN_RUSSIA 0x0419 # define TT_MS_LANGID_CROATIAN_CROATIA 0x041A # define TT_MS_LANGID_SERBIAN_SERBIA_LATIN 0x081A # define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 0x0C1A # define TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA 0x101A # define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x141A # define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN 0x181A # define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC 0x1C1A # define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZ_CYRILLIC 0x201A # define TT_MS_LANGID_SLOVAK_SLOVAKIA 0x041B # define TT_MS_LANGID_ALBANIAN_ALBANIA 0x041C # define TT_MS_LANGID_SWEDISH_SWEDEN 0x041D # define TT_MS_LANGID_SWEDISH_FINLAND 0x081D # define TT_MS_LANGID_THAI_THAILAND 0x041E # define TT_MS_LANGID_TURKISH_TURKEY 0x041F # define TT_MS_LANGID_URDU_PAKISTAN 0x0420 # define TT_MS_LANGID_INDONESIAN_INDONESIA 0x0421 # define TT_MS_LANGID_UKRAINIAN_UKRAINE 0x0422 # define TT_MS_LANGID_BELARUSIAN_BELARUS 0x0423 # define TT_MS_LANGID_SLOVENIAN_SLOVENIA 0x0424 # define TT_MS_LANGID_ESTONIAN_ESTONIA 0x0425 # define TT_MS_LANGID_LATVIAN_LATVIA 0x0426 # define TT_MS_LANGID_LITHUANIAN_LITHUANIA 0x0427 # define TT_MS_LANGID_TAJIK_TAJIKISTAN 0x0428 # define TT_MS_LANGID_VIETNAMESE_VIET_NAM 0x042A # define TT_MS_LANGID_ARMENIAN_ARMENIA 0x042B # define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN 0x042C # define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC 0x082C # define TT_MS_LANGID_BASQUE_BASQUE 0x042D # define TT_MS_LANGID_UPPER_SORBIAN_GERMANY 0x042E # define TT_MS_LANGID_LOWER_SORBIAN_GERMANY 0x082E # define TT_MS_LANGID_MACEDONIAN_MACEDONIA 0x042F # define TT_MS_LANGID_SETSWANA_SOUTH_AFRICA 0x0432 # define TT_MS_LANGID_ISIXHOSA_SOUTH_AFRICA 0x0434 # define TT_MS_LANGID_ISIZULU_SOUTH_AFRICA 0x0435 # define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA 0x0436 # define TT_MS_LANGID_GEORGIAN_GEORGIA 0x0437 # define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 0x0438 # define TT_MS_LANGID_HINDI_INDIA 0x0439 # define TT_MS_LANGID_MALTESE_MALTA 0x043A # define TT_MS_LANGID_SAMI_NORTHERN_NORWAY 0x043B # define TT_MS_LANGID_SAMI_NORTHERN_SWEDEN 0x083B # define TT_MS_LANGID_SAMI_NORTHERN_FINLAND 0x0C3B # define TT_MS_LANGID_SAMI_LULE_NORWAY 0x103B # define TT_MS_LANGID_SAMI_LULE_SWEDEN 0x143B # define TT_MS_LANGID_SAMI_SOUTHERN_NORWAY 0x183B # define TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN 0x1C3B # define TT_MS_LANGID_SAMI_SKOLT_FINLAND 0x203B # define TT_MS_LANGID_SAMI_INARI_FINLAND 0x243B # define TT_MS_LANGID_IRISH_IRELAND 0x083C # define TT_MS_LANGID_MALAY_MALAYSIA 0x043E # define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 0x083E # define TT_MS_LANGID_KAZAKH_KAZAKHSTAN 0x043F # define TT_MS_LANGID_KYRGYZ_KYRGYZSTAN /* Cyrillic*/ 0x0440 # define TT_MS_LANGID_KISWAHILI_KENYA 0x0441 # define TT_MS_LANGID_TURKMEN_TURKMENISTAN 0x0442 # define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 0x0443 # define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC 0x0843 # define TT_MS_LANGID_TATAR_RUSSIA 0x0444 # define TT_MS_LANGID_BENGALI_INDIA 0x0445 # define TT_MS_LANGID_BENGALI_BANGLADESH 0x0845 # define TT_MS_LANGID_PUNJABI_INDIA 0x0446 # define TT_MS_LANGID_GUJARATI_INDIA 0x0447 # define TT_MS_LANGID_ODIA_INDIA 0x0448 # define TT_MS_LANGID_TAMIL_INDIA 0x0449 # define TT_MS_LANGID_TELUGU_INDIA 0x044A # define TT_MS_LANGID_KANNADA_INDIA 0x044B # define TT_MS_LANGID_MALAYALAM_INDIA 0x044C # define TT_MS_LANGID_ASSAMESE_INDIA 0x044D # define TT_MS_LANGID_MARATHI_INDIA 0x044E # define TT_MS_LANGID_SANSKRIT_INDIA 0x044F # define TT_MS_LANGID_MONGOLIAN_MONGOLIA /* Cyrillic */ 0x0450 # define TT_MS_LANGID_MONGOLIAN_PRC 0x0850 # define TT_MS_LANGID_TIBETAN_PRC 0x0451 # define TT_MS_LANGID_WELSH_UNITED_KINGDOM 0x0452 # define TT_MS_LANGID_KHMER_CAMBODIA 0x0453 # define TT_MS_LANGID_LAO_LAOS 0x0454 # define TT_MS_LANGID_GALICIAN_GALICIAN 0x0456 # define TT_MS_LANGID_KONKANI_INDIA 0x0457 # define TT_MS_LANGID_SYRIAC_SYRIA 0x045A # define TT_MS_LANGID_SINHALA_SRI_LANKA 0x045B # define TT_MS_LANGID_INUKTITUT_CANADA 0x045D # define TT_MS_LANGID_INUKTITUT_CANADA_LATIN 0x085D # define TT_MS_LANGID_AMHARIC_ETHIOPIA 0x045E # define TT_MS_LANGID_TAMAZIGHT_ALGERIA 0x085F # define TT_MS_LANGID_NEPALI_NEPAL 0x0461 # define TT_MS_LANGID_FRISIAN_NETHERLANDS 0x0462 # define TT_MS_LANGID_PASHTO_AFGHANISTAN 0x0463 # define TT_MS_LANGID_FILIPINO_PHILIPPINES 0x0464 # define TT_MS_LANGID_DHIVEHI_MALDIVES 0x0465 # define TT_MS_LANGID_HAUSA_NIGERIA 0x0468 # define TT_MS_LANGID_YORUBA_NIGERIA 0x046A # define TT_MS_LANGID_QUECHUA_BOLIVIA 0x046B # define TT_MS_LANGID_QUECHUA_ECUADOR 0x086B # define TT_MS_LANGID_QUECHUA_PERU 0x0C6B # define TT_MS_LANGID_SESOTHO_SA_LEBOA_SOUTH_AFRICA 0x046C # define TT_MS_LANGID_BASHKIR_RUSSIA 0x046D # define TT_MS_LANGID_LUXEMBOURGISH_LUXEMBOURG 0x046E # define TT_MS_LANGID_GREENLANDIC_GREENLAND 0x046F # define TT_MS_LANGID_IGBO_NIGERIA 0x0470 # define TT_MS_LANGID_YI_PRC 0x0478 # define TT_MS_LANGID_MAPUDUNGUN_CHILE 0x047A # define TT_MS_LANGID_MOHAWK_MOHAWK 0x047C # define TT_MS_LANGID_BRETON_FRANCE 0x047E # define TT_MS_LANGID_UIGHUR_PRC 0x0480 # define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0481 # define TT_MS_LANGID_OCCITAN_FRANCE 0x0482 # define TT_MS_LANGID_CORSICAN_FRANCE 0x0483 # define TT_MS_LANGID_ALSATIAN_FRANCE 0x0484 # define TT_MS_LANGID_YAKUT_RUSSIA 0x0485 # define TT_MS_LANGID_KICHE_GUATEMALA 0x0486 # define TT_MS_LANGID_KINYARWANDA_RWANDA 0x0487 # define TT_MS_LANGID_WOLOF_SENEGAL 0x0488 # define TT_MS_LANGID_DARI_AFGHANISTAN 0x048C Possible values of the language identifier field in the name records of the SFNT \u2018name\u2019 table if the \u2018platform\u2019 identifier code is TT_PLATFORM_MICROSOFT . These values are also used as return values for function FT_Get_CMap_Language_ID . The canonical source for Microsoft's IDs is https://docs.microsoft.com/en-us/windows/desktop/Intl/language-identifier-constants-and-strings , however, we only provide macros for language identifiers present in the OpenType specification: Microsoft has abandoned the concept of LCIDs (language code identifiers), and format 1 of the \u2018name\u2019 table provides a better mechanism for languages not covered here. More legacy values not listed in the reference can be found in the FT_TRUETYPE_IDS_H header file. TT_NAME_ID_XXX \u00b6 Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_NAME_ID_COPYRIGHT 0 # define TT_NAME_ID_FONT_FAMILY 1 # define TT_NAME_ID_FONT_SUBFAMILY 2 # define TT_NAME_ID_UNIQUE_ID 3 # define TT_NAME_ID_FULL_NAME 4 # define TT_NAME_ID_VERSION_STRING 5 # define TT_NAME_ID_PS_NAME 6 # define TT_NAME_ID_TRADEMARK 7 /* the following values are from the OpenType spec */ # define TT_NAME_ID_MANUFACTURER 8 # define TT_NAME_ID_DESIGNER 9 # define TT_NAME_ID_DESCRIPTION 10 # define TT_NAME_ID_VENDOR_URL 11 # define TT_NAME_ID_DESIGNER_URL 12 # define TT_NAME_ID_LICENSE 13 # define TT_NAME_ID_LICENSE_URL 14 /* number 15 is reserved */ # define TT_NAME_ID_TYPOGRAPHIC_FAMILY 16 # define TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY 17 # define TT_NAME_ID_MAC_FULL_NAME 18 /* The following code is new as of 2000-01-21 */ # define TT_NAME_ID_SAMPLE_TEXT 19 /* This is new in OpenType 1.3 */ # define TT_NAME_ID_CID_FINDFONT_NAME 20 /* This is new in OpenType 1.5 */ # define TT_NAME_ID_WWS_FAMILY 21 # define TT_NAME_ID_WWS_SUBFAMILY 22 /* This is new in OpenType 1.7 */ # define TT_NAME_ID_LIGHT_BACKGROUND 23 # define TT_NAME_ID_DARK_BACKGROUND 24 /* This is new in OpenType 1.8 */ # define TT_NAME_ID_VARIATIONS_PREFIX 25 /* these two values are deprecated */ # define TT_NAME_ID_PREFERRED_FAMILY TT_NAME_ID_TYPOGRAPHIC_FAMILY # define TT_NAME_ID_PREFERRED_SUBFAMILY TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY Possible values of the \u2018name\u2019 identifier field in the name records of an SFNT \u2018name\u2019 table. These values are platform independent. TT_UCR_XXX \u00b6 Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). /* ulUnicodeRange1 */ /* --------------- */ /* Bit 0 Basic Latin */ # define TT_UCR_BASIC_LATIN (1L << 0) /* U+0020-U+007E */ /* Bit 1 C1 Controls and Latin-1 Supplement */ # define TT_UCR_LATIN1_SUPPLEMENT (1L << 1) /* U+0080-U+00FF */ /* Bit 2 Latin Extended-A */ # define TT_UCR_LATIN_EXTENDED_A (1L << 2) /* U+0100-U+017F */ /* Bit 3 Latin Extended-B */ # define TT_UCR_LATIN_EXTENDED_B (1L << 3) /* U+0180-U+024F */ /* Bit 4 IPA Extensions */ /* Phonetic Extensions */ /* Phonetic Extensions Supplement */ # define TT_UCR_IPA_EXTENSIONS (1L << 4) /* U+0250-U+02AF */ /* U+1D00-U+1D7F */ /* U+1D80-U+1DBF */ /* Bit 5 Spacing Modifier Letters */ /* Modifier Tone Letters */ # define TT_UCR_SPACING_MODIFIER (1L << 5) /* U+02B0-U+02FF */ /* U+A700-U+A71F */ /* Bit 6 Combining Diacritical Marks */ /* Combining Diacritical Marks Supplement */ # define TT_UCR_COMBINING_DIACRITICAL_MARKS (1L << 6) /* U+0300-U+036F */ /* U+1DC0-U+1DFF */ /* Bit 7 Greek and Coptic */ # define TT_UCR_GREEK (1L << 7) /* U+0370-U+03FF */ /* Bit 8 Coptic */ # define TT_UCR_COPTIC (1L << 8) /* U+2C80-U+2CFF */ /* Bit 9 Cyrillic */ /* Cyrillic Supplement */ /* Cyrillic Extended-A */ /* Cyrillic Extended-B */ # define TT_UCR_CYRILLIC (1L << 9) /* U+0400-U+04FF */ /* U+0500-U+052F */ /* U+2DE0-U+2DFF */ /* U+A640-U+A69F */ /* Bit 10 Armenian */ # define TT_UCR_ARMENIAN (1L << 10) /* U+0530-U+058F */ /* Bit 11 Hebrew */ # define TT_UCR_HEBREW (1L << 11) /* U+0590-U+05FF */ /* Bit 12 Vai */ # define TT_UCR_VAI (1L << 12) /* U+A500-U+A63F */ /* Bit 13 Arabic */ /* Arabic Supplement */ # define TT_UCR_ARABIC (1L << 13) /* U+0600-U+06FF */ /* U+0750-U+077F */ /* Bit 14 NKo */ # define TT_UCR_NKO (1L << 14) /* U+07C0-U+07FF */ /* Bit 15 Devanagari */ # define TT_UCR_DEVANAGARI (1L << 15) /* U+0900-U+097F */ /* Bit 16 Bengali */ # define TT_UCR_BENGALI (1L << 16) /* U+0980-U+09FF */ /* Bit 17 Gurmukhi */ # define TT_UCR_GURMUKHI (1L << 17) /* U+0A00-U+0A7F */ /* Bit 18 Gujarati */ # define TT_UCR_GUJARATI (1L << 18) /* U+0A80-U+0AFF */ /* Bit 19 Oriya */ # define TT_UCR_ORIYA (1L << 19) /* U+0B00-U+0B7F */ /* Bit 20 Tamil */ # define TT_UCR_TAMIL (1L << 20) /* U+0B80-U+0BFF */ /* Bit 21 Telugu */ # define TT_UCR_TELUGU (1L << 21) /* U+0C00-U+0C7F */ /* Bit 22 Kannada */ # define TT_UCR_KANNADA (1L << 22) /* U+0C80-U+0CFF */ /* Bit 23 Malayalam */ # define TT_UCR_MALAYALAM (1L << 23) /* U+0D00-U+0D7F */ /* Bit 24 Thai */ # define TT_UCR_THAI (1L << 24) /* U+0E00-U+0E7F */ /* Bit 25 Lao */ # define TT_UCR_LAO (1L << 25) /* U+0E80-U+0EFF */ /* Bit 26 Georgian */ /* Georgian Supplement */ # define TT_UCR_GEORGIAN (1L << 26) /* U+10A0-U+10FF */ /* U+2D00-U+2D2F */ /* Bit 27 Balinese */ # define TT_UCR_BALINESE (1L << 27) /* U+1B00-U+1B7F */ /* Bit 28 Hangul Jamo */ # define TT_UCR_HANGUL_JAMO (1L << 28) /* U+1100-U+11FF */ /* Bit 29 Latin Extended Additional */ /* Latin Extended-C */ /* Latin Extended-D */ # define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1L << 29) /* U+1E00-U+1EFF */ /* U+2C60-U+2C7F */ /* U+A720-U+A7FF */ /* Bit 30 Greek Extended */ # define TT_UCR_GREEK_EXTENDED (1L << 30) /* U+1F00-U+1FFF */ /* Bit 31 General Punctuation */ /* Supplemental Punctuation */ # define TT_UCR_GENERAL_PUNCTUATION (1L << 31) /* U+2000-U+206F */ /* U+2E00-U+2E7F */ /* ulUnicodeRange2 */ /* --------------- */ /* Bit 32 Superscripts And Subscripts */ # define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1L << 0) /* U+2070-U+209F */ /* Bit 33 Currency Symbols */ # define TT_UCR_CURRENCY_SYMBOLS (1L << 1) /* U+20A0-U+20CF */ /* Bit 34 Combining Diacritical Marks For Symbols */ # define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \\ (1L << 2) /* U+20D0-U+20FF */ /* Bit 35 Letterlike Symbols */ # define TT_UCR_LETTERLIKE_SYMBOLS (1L << 3) /* U+2100-U+214F */ /* Bit 36 Number Forms */ # define TT_UCR_NUMBER_FORMS (1L << 4) /* U+2150-U+218F */ /* Bit 37 Arrows */ /* Supplemental Arrows-A */ /* Supplemental Arrows-B */ /* Miscellaneous Symbols and Arrows */ # define TT_UCR_ARROWS (1L << 5) /* U+2190-U+21FF */ /* U+27F0-U+27FF */ /* U+2900-U+297F */ /* U+2B00-U+2BFF */ /* Bit 38 Mathematical Operators */ /* Supplemental Mathematical Operators */ /* Miscellaneous Mathematical Symbols-A */ /* Miscellaneous Mathematical Symbols-B */ # define TT_UCR_MATHEMATICAL_OPERATORS (1L << 6) /* U+2200-U+22FF */ /* U+2A00-U+2AFF */ /* U+27C0-U+27EF */ /* U+2980-U+29FF */ /* Bit 39 Miscellaneous Technical */ # define TT_UCR_MISCELLANEOUS_TECHNICAL (1L << 7) /* U+2300-U+23FF */ /* Bit 40 Control Pictures */ # define TT_UCR_CONTROL_PICTURES (1L << 8) /* U+2400-U+243F */ /* Bit 41 Optical Character Recognition */ # define TT_UCR_OCR (1L << 9) /* U+2440-U+245F */ /* Bit 42 Enclosed Alphanumerics */ # define TT_UCR_ENCLOSED_ALPHANUMERICS (1L << 10) /* U+2460-U+24FF */ /* Bit 43 Box Drawing */ # define TT_UCR_BOX_DRAWING (1L << 11) /* U+2500-U+257F */ /* Bit 44 Block Elements */ # define TT_UCR_BLOCK_ELEMENTS (1L << 12) /* U+2580-U+259F */ /* Bit 45 Geometric Shapes */ # define TT_UCR_GEOMETRIC_SHAPES (1L << 13) /* U+25A0-U+25FF */ /* Bit 46 Miscellaneous Symbols */ # define TT_UCR_MISCELLANEOUS_SYMBOLS (1L << 14) /* U+2600-U+26FF */ /* Bit 47 Dingbats */ # define TT_UCR_DINGBATS (1L << 15) /* U+2700-U+27BF */ /* Bit 48 CJK Symbols and Punctuation */ # define TT_UCR_CJK_SYMBOLS (1L << 16) /* U+3000-U+303F */ /* Bit 49 Hiragana */ # define TT_UCR_HIRAGANA (1L << 17) /* U+3040-U+309F */ /* Bit 50 Katakana */ /* Katakana Phonetic Extensions */ # define TT_UCR_KATAKANA (1L << 18) /* U+30A0-U+30FF */ /* U+31F0-U+31FF */ /* Bit 51 Bopomofo */ /* Bopomofo Extended */ # define TT_UCR_BOPOMOFO (1L << 19) /* U+3100-U+312F */ /* U+31A0-U+31BF */ /* Bit 52 Hangul Compatibility Jamo */ # define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1L << 20) /* U+3130-U+318F */ /* Bit 53 Phags-Pa */ # define TT_UCR_CJK_MISC (1L << 21) /* U+A840-U+A87F */ # define TT_UCR_KANBUN TT_UCR_CJK_MISC /* deprecated */ # define TT_UCR_PHAGSPA /* Bit 54 Enclosed CJK Letters and Months */ # define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1L << 22) /* U+3200-U+32FF */ /* Bit 55 CJK Compatibility */ # define TT_UCR_CJK_COMPATIBILITY (1L << 23) /* U+3300-U+33FF */ /* Bit 56 Hangul Syllables */ # define TT_UCR_HANGUL (1L << 24) /* U+AC00-U+D7A3 */ /* Bit 57 High Surrogates */ /* High Private Use Surrogates */ /* Low Surrogates */ /* According to OpenType specs v.1.3+, */ /* setting bit 57 implies that there is */ /* at least one codepoint beyond the */ /* Basic Multilingual Plane that is */ /* supported by this font. So it really */ /* means >= U+10000. */ # define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DB7F */ /* U+DB80-U+DBFF */ /* U+DC00-U+DFFF */ # define TT_UCR_NON_PLANE_0 TT_UCR_SURROGATES /* Bit 58 Phoenician */ # define TT_UCR_PHOENICIAN (1L << 26) /*U+10900-U+1091F*/ /* Bit 59 CJK Unified Ideographs */ /* CJK Radicals Supplement */ /* Kangxi Radicals */ /* Ideographic Description Characters */ /* CJK Unified Ideographs Extension A */ /* CJK Unified Ideographs Extension B */ /* Kanbun */ # define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1L << 27) /* U+4E00-U+9FFF */ /* U+2E80-U+2EFF */ /* U+2F00-U+2FDF */ /* U+2FF0-U+2FFF */ /* U+3400-U+4DB5 */ /*U+20000-U+2A6DF*/ /* U+3190-U+319F */ /* Bit 60 Private Use */ # define TT_UCR_PRIVATE_USE (1L << 28) /* U+E000-U+F8FF */ /* Bit 61 CJK Strokes */ /* CJK Compatibility Ideographs */ /* CJK Compatibility Ideographs Supplement */ # define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1L << 29) /* U+31C0-U+31EF */ /* U+F900-U+FAFF */ /*U+2F800-U+2FA1F*/ /* Bit 62 Alphabetic Presentation Forms */ # define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1L << 30) /* U+FB00-U+FB4F */ /* Bit 63 Arabic Presentation Forms-A */ # define TT_UCR_ARABIC_PRESENTATION_FORMS_A (1L << 31) /* U+FB50-U+FDFF */ /* ulUnicodeRange3 */ /* --------------- */ /* Bit 64 Combining Half Marks */ # define TT_UCR_COMBINING_HALF_MARKS (1L << 0) /* U+FE20-U+FE2F */ /* Bit 65 Vertical forms */ /* CJK Compatibility Forms */ # define TT_UCR_CJK_COMPATIBILITY_FORMS (1L << 1) /* U+FE10-U+FE1F */ /* U+FE30-U+FE4F */ /* Bit 66 Small Form Variants */ # define TT_UCR_SMALL_FORM_VARIANTS (1L << 2) /* U+FE50-U+FE6F */ /* Bit 67 Arabic Presentation Forms-B */ # define TT_UCR_ARABIC_PRESENTATION_FORMS_B (1L << 3) /* U+FE70-U+FEFE */ /* Bit 68 Halfwidth and Fullwidth Forms */ # define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1L << 4) /* U+FF00-U+FFEF */ /* Bit 69 Specials */ # define TT_UCR_SPECIALS (1L << 5) /* U+FFF0-U+FFFD */ /* Bit 70 Tibetan */ # define TT_UCR_TIBETAN (1L << 6) /* U+0F00-U+0FFF */ /* Bit 71 Syriac */ # define TT_UCR_SYRIAC (1L << 7) /* U+0700-U+074F */ /* Bit 72 Thaana */ # define TT_UCR_THAANA (1L << 8) /* U+0780-U+07BF */ /* Bit 73 Sinhala */ # define TT_UCR_SINHALA (1L << 9) /* U+0D80-U+0DFF */ /* Bit 74 Myanmar */ # define TT_UCR_MYANMAR (1L << 10) /* U+1000-U+109F */ /* Bit 75 Ethiopic */ /* Ethiopic Supplement */ /* Ethiopic Extended */ # define TT_UCR_ETHIOPIC (1L << 11) /* U+1200-U+137F */ /* U+1380-U+139F */ /* U+2D80-U+2DDF */ /* Bit 76 Cherokee */ # define TT_UCR_CHEROKEE (1L << 12) /* U+13A0-U+13FF */ /* Bit 77 Unified Canadian Aboriginal Syllabics */ # define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS (1L << 13) /* U+1400-U+167F */ /* Bit 78 Ogham */ # define TT_UCR_OGHAM (1L << 14) /* U+1680-U+169F */ /* Bit 79 Runic */ # define TT_UCR_RUNIC (1L << 15) /* U+16A0-U+16FF */ /* Bit 80 Khmer */ /* Khmer Symbols */ # define TT_UCR_KHMER (1L << 16) /* U+1780-U+17FF */ /* U+19E0-U+19FF */ /* Bit 81 Mongolian */ # define TT_UCR_MONGOLIAN (1L << 17) /* U+1800-U+18AF */ /* Bit 82 Braille Patterns */ # define TT_UCR_BRAILLE (1L << 18) /* U+2800-U+28FF */ /* Bit 83 Yi Syllables */ /* Yi Radicals */ # define TT_UCR_YI (1L << 19) /* U+A000-U+A48F */ /* U+A490-U+A4CF */ /* Bit 84 Tagalog */ /* Hanunoo */ /* Buhid */ /* Tagbanwa */ # define TT_UCR_PHILIPPINE (1L << 20) /* U+1700-U+171F */ /* U+1720-U+173F */ /* U+1740-U+175F */ /* U+1760-U+177F */ /* Bit 85 Old Italic */ # define TT_UCR_OLD_ITALIC (1L << 21) /*U+10300-U+1032F*/ /* Bit 86 Gothic */ # define TT_UCR_GOTHIC (1L << 22) /*U+10330-U+1034F*/ /* Bit 87 Deseret */ # define TT_UCR_DESERET (1L << 23) /*U+10400-U+1044F*/ /* Bit 88 Byzantine Musical Symbols */ /* Musical Symbols */ /* Ancient Greek Musical Notation */ # define TT_UCR_MUSICAL_SYMBOLS (1L << 24) /*U+1D000-U+1D0FF*/ /*U+1D100-U+1D1FF*/ /*U+1D200-U+1D24F*/ /* Bit 89 Mathematical Alphanumeric Symbols */ # define TT_UCR_MATH_ALPHANUMERIC_SYMBOLS (1L << 25) /*U+1D400-U+1D7FF*/ /* Bit 90 Private Use (plane 15) */ /* Private Use (plane 16) */ # define TT_UCR_PRIVATE_USE_SUPPLEMENTARY (1L << 26) /*U+F0000-U+FFFFD*/ /*U+100000-U+10FFFD*/ /* Bit 91 Variation Selectors */ /* Variation Selectors Supplement */ # define TT_UCR_VARIATION_SELECTORS (1L << 27) /* U+FE00-U+FE0F */ /*U+E0100-U+E01EF*/ /* Bit 92 Tags */ # define TT_UCR_TAGS (1L << 28) /*U+E0000-U+E007F*/ /* Bit 93 Limbu */ # define TT_UCR_LIMBU (1L << 29) /* U+1900-U+194F */ /* Bit 94 Tai Le */ # define TT_UCR_TAI_LE (1L << 30) /* U+1950-U+197F */ /* Bit 95 New Tai Lue */ # define TT_UCR_NEW_TAI_LUE (1L << 31) /* U+1980-U+19DF */ /* ulUnicodeRange4 */ /* --------------- */ /* Bit 96 Buginese */ # define TT_UCR_BUGINESE (1L << 0) /* U+1A00-U+1A1F */ /* Bit 97 Glagolitic */ # define TT_UCR_GLAGOLITIC (1L << 1) /* U+2C00-U+2C5F */ /* Bit 98 Tifinagh */ # define TT_UCR_TIFINAGH (1L << 2) /* U+2D30-U+2D7F */ /* Bit 99 Yijing Hexagram Symbols */ # define TT_UCR_YIJING (1L << 3) /* U+4DC0-U+4DFF */ /* Bit 100 Syloti Nagri */ # define TT_UCR_SYLOTI_NAGRI (1L << 4) /* U+A800-U+A82F */ /* Bit 101 Linear B Syllabary */ /* Linear B Ideograms */ /* Aegean Numbers */ # define TT_UCR_LINEAR_B (1L << 5) /*U+10000-U+1007F*/ /*U+10080-U+100FF*/ /*U+10100-U+1013F*/ /* Bit 102 Ancient Greek Numbers */ # define TT_UCR_ANCIENT_GREEK_NUMBERS (1L << 6) /*U+10140-U+1018F*/ /* Bit 103 Ugaritic */ # define TT_UCR_UGARITIC (1L << 7) /*U+10380-U+1039F*/ /* Bit 104 Old Persian */ # define TT_UCR_OLD_PERSIAN (1L << 8) /*U+103A0-U+103DF*/ /* Bit 105 Shavian */ # define TT_UCR_SHAVIAN (1L << 9) /*U+10450-U+1047F*/ /* Bit 106 Osmanya */ # define TT_UCR_OSMANYA (1L << 10) /*U+10480-U+104AF*/ /* Bit 107 Cypriot Syllabary */ # define TT_UCR_CYPRIOT_SYLLABARY (1L << 11) /*U+10800-U+1083F*/ /* Bit 108 Kharoshthi */ # define TT_UCR_KHAROSHTHI (1L << 12) /*U+10A00-U+10A5F*/ /* Bit 109 Tai Xuan Jing Symbols */ # define TT_UCR_TAI_XUAN_JING (1L << 13) /*U+1D300-U+1D35F*/ /* Bit 110 Cuneiform */ /* Cuneiform Numbers and Punctuation */ # define TT_UCR_CUNEIFORM (1L << 14) /*U+12000-U+123FF*/ /*U+12400-U+1247F*/ /* Bit 111 Counting Rod Numerals */ # define TT_UCR_COUNTING_ROD_NUMERALS (1L << 15) /*U+1D360-U+1D37F*/ /* Bit 112 Sundanese */ # define TT_UCR_SUNDANESE (1L << 16) /* U+1B80-U+1BBF */ /* Bit 113 Lepcha */ # define TT_UCR_LEPCHA (1L << 17) /* U+1C00-U+1C4F */ /* Bit 114 Ol Chiki */ # define TT_UCR_OL_CHIKI (1L << 18) /* U+1C50-U+1C7F */ /* Bit 115 Saurashtra */ # define TT_UCR_SAURASHTRA (1L << 19) /* U+A880-U+A8DF */ /* Bit 116 Kayah Li */ # define TT_UCR_KAYAH_LI (1L << 20) /* U+A900-U+A92F */ /* Bit 117 Rejang */ # define TT_UCR_REJANG (1L << 21) /* U+A930-U+A95F */ /* Bit 118 Cham */ # define TT_UCR_CHAM (1L << 22) /* U+AA00-U+AA5F */ /* Bit 119 Ancient Symbols */ # define TT_UCR_ANCIENT_SYMBOLS (1L << 23) /*U+10190-U+101CF*/ /* Bit 120 Phaistos Disc */ # define TT_UCR_PHAISTOS_DISC (1L << 24) /*U+101D0-U+101FF*/ /* Bit 121 Carian */ /* Lycian */ /* Lydian */ # define TT_UCR_OLD_ANATOLIAN (1L << 25) /*U+102A0-U+102DF*/ /*U+10280-U+1029F*/ /*U+10920-U+1093F*/ /* Bit 122 Domino Tiles */ /* Mahjong Tiles */ # define TT_UCR_GAME_TILES (1L << 26) /*U+1F030-U+1F09F*/ /*U+1F000-U+1F02F*/ /* Bit 123-127 Reserved for process-internal usage */ Possible bit mask values for the ulUnicodeRangeX fields in an SFNT \u2018OS/2\u2019 table.","title":"TrueType Tables"},{"location":"ft2-truetype_tables.html#truetype-tables","text":"","title":"TrueType Tables"},{"location":"ft2-truetype_tables.html#synopsis","text":"This section contains definitions of some basic tables specific to TrueType and OpenType as well as some routines used to access and process them.","title":"Synopsis"},{"location":"ft2-truetype_tables.html#tt_header","text":"Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef struct TT_Header_ { FT_Fixed Table_Version; FT_Fixed Font_Revision; FT_Long CheckSum_Adjust; FT_Long Magic_Number; FT_UShort Flags; FT_UShort Units_Per_EM; FT_ULong Created [2]; FT_ULong Modified[2]; FT_Short xMin; FT_Short yMin; FT_Short xMax; FT_Short yMax; FT_UShort Mac_Style; FT_UShort Lowest_Rec_PPEM; FT_Short Font_Direction; FT_Short Index_To_Loc_Format; FT_Short Glyph_Data_Format; } TT_Header ; A structure to model a TrueType font header table. All fields follow the OpenType specification. The 64-bit timestamps are stored in two-element arrays Created and Modified , first the upper then the lower 32 bits.","title":"TT_Header"},{"location":"ft2-truetype_tables.html#tt_horiheader","text":"Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef struct TT_HoriHeader_ { FT_Fixed Version; FT_Short Ascender; FT_Short Descender; FT_Short Line_Gap; FT_UShort advance_Width_Max; /* advance width maximum */ FT_Short min_Left_Side_Bearing; /* minimum left-sb */ FT_Short min_Right_Side_Bearing; /* minimum right-sb */ FT_Short xMax_Extent; /* xmax extents */ FT_Short caret_Slope_Rise; FT_Short caret_Slope_Run; FT_Short caret_Offset; FT_Short Reserved[4]; FT_Short metric_Data_Format; FT_UShort number_Of_HMetrics; /* The following fields are not defined by the OpenType specification */ /* but they are used to connect the metrics header to the relevant */ /* 'hmtx' table. */ void * long_metrics; void * short_metrics; } TT_HoriHeader ; A structure to model a TrueType horizontal header, the \u2018hhea\u2019 table, as well as the corresponding horizontal metrics table, \u2018hmtx\u2019.","title":"TT_HoriHeader"},{"location":"ft2-truetype_tables.html#tt_vertheader","text":"Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef struct TT_VertHeader_ { FT_Fixed Version; FT_Short Ascender; FT_Short Descender; FT_Short Line_Gap; FT_UShort advance_Height_Max; /* advance height maximum */ FT_Short min_Top_Side_Bearing; /* minimum top-sb */ FT_Short min_Bottom_Side_Bearing; /* minimum bottom-sb */ FT_Short yMax_Extent; /* ymax extents */ FT_Short caret_Slope_Rise; FT_Short caret_Slope_Run; FT_Short caret_Offset; FT_Short Reserved[4]; FT_Short metric_Data_Format; FT_UShort number_Of_VMetrics; /* The following fields are not defined by the OpenType specification */ /* but they are used to connect the metrics header to the relevant */ /* 'vmtx' table. */ void * long_metrics; void * short_metrics; } TT_VertHeader ; A structure used to model a TrueType vertical header, the \u2018vhea\u2019 table, as well as the corresponding vertical metrics table, \u2018vmtx\u2019.","title":"TT_VertHeader"},{"location":"ft2-truetype_tables.html#tt_os2","text":"Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef struct TT_OS2_ { FT_UShort version; /* 0x0001 - more or 0xFFFF */ FT_Short xAvgCharWidth; FT_UShort usWeightClass; FT_UShort usWidthClass; FT_UShort fsType; FT_Short ySubscriptXSize; FT_Short ySubscriptYSize; FT_Short ySubscriptXOffset; FT_Short ySubscriptYOffset; FT_Short ySuperscriptXSize; FT_Short ySuperscriptYSize; FT_Short ySuperscriptXOffset; FT_Short ySuperscriptYOffset; FT_Short yStrikeoutSize; FT_Short yStrikeoutPosition; FT_Short sFamilyClass; FT_Byte panose[10]; FT_ULong ulUnicodeRange1; /* Bits 0-31 */ FT_ULong ulUnicodeRange2; /* Bits 32-63 */ FT_ULong ulUnicodeRange3; /* Bits 64-95 */ FT_ULong ulUnicodeRange4; /* Bits 96-127 */ FT_Char achVendID[4]; FT_UShort fsSelection; FT_UShort usFirstCharIndex; FT_UShort usLastCharIndex; FT_Short sTypoAscender; FT_Short sTypoDescender; FT_Short sTypoLineGap; FT_UShort usWinAscent; FT_UShort usWinDescent; /* only version 1 and higher: */ FT_ULong ulCodePageRange1; /* Bits 0-31 */ FT_ULong ulCodePageRange2; /* Bits 32-63 */ /* only version 2 and higher: */ FT_Short sxHeight; FT_Short sCapHeight; FT_UShort usDefaultChar; FT_UShort usBreakChar; FT_UShort usMaxContext; /* only version 5 and higher: */ FT_UShort usLowerOpticalPointSize; /* in twips (1/20th points) */ FT_UShort usUpperOpticalPointSize; /* in twips (1/20th points) */ } TT_OS2 ; A structure to model a TrueType \u2018OS/2\u2019 table. All fields comply to the OpenType specification. Note that we now support old Mac fonts that do not include an \u2018OS/2\u2019 table. In this case, the version field is always set to 0xFFFF.","title":"TT_OS2"},{"location":"ft2-truetype_tables.html#tt_postscript","text":"Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef struct TT_Postscript_ { FT_Fixed FormatType; FT_Fixed italicAngle; FT_Short underlinePosition; FT_Short underlineThickness; FT_ULong isFixedPitch; FT_ULong minMemType42; FT_ULong maxMemType42; FT_ULong minMemType1; FT_ULong maxMemType1; /* Glyph names follow in the 'post' table, but we don't */ /* load them by default. */ } TT_Postscript ; A structure to model a TrueType \u2018post\u2019 table. All fields comply to the OpenType specification. This structure does not reference a font's PostScript glyph names; use FT_Get_Glyph_Name to retrieve them.","title":"TT_Postscript"},{"location":"ft2-truetype_tables.html#tt_pclt","text":"Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef struct TT_PCLT_ { FT_Fixed Version; FT_ULong FontNumber; FT_UShort Pitch; FT_UShort xHeight; FT_UShort Style; FT_UShort TypeFamily; FT_UShort CapHeight; FT_UShort SymbolSet; FT_Char TypeFace[16]; FT_Char CharacterComplement[8]; FT_Char FileName[6]; FT_Char StrokeWeight; FT_Char WidthType; FT_Byte SerifStyle; FT_Byte Reserved; } TT_PCLT ; A structure to model a TrueType \u2018PCLT\u2019 table. All fields comply to the OpenType specification.","title":"TT_PCLT"},{"location":"ft2-truetype_tables.html#tt_maxprofile","text":"Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef struct TT_MaxProfile_ { FT_Fixed version; FT_UShort numGlyphs; FT_UShort maxPoints; FT_UShort maxContours; FT_UShort maxCompositePoints; FT_UShort maxCompositeContours; FT_UShort maxZones; FT_UShort maxTwilightPoints; FT_UShort maxStorage; FT_UShort maxFunctionDefs; FT_UShort maxInstructionDefs; FT_UShort maxStackElements; FT_UShort maxSizeOfInstructions; FT_UShort maxComponentElements; FT_UShort maxComponentDepth; } TT_MaxProfile ; The maximum profile (\u2018maxp\u2019) table contains many max values, which can be used to pre-allocate arrays for speeding up glyph loading and hinting.","title":"TT_MaxProfile"},{"location":"ft2-truetype_tables.html#ft_sfnt_tag","text":"Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). typedef enum FT_Sfnt_Tag_ { FT_SFNT_HEAD , FT_SFNT_MAXP , FT_SFNT_OS2 , FT_SFNT_HHEA , FT_SFNT_VHEA , FT_SFNT_POST , FT_SFNT_PCLT , FT_SFNT_MAX } FT_Sfnt_Tag ; /* these constants are deprecated; use the corresponding ` FT_Sfnt_Tag ` */ /* values instead */ # define ft_sfnt_head FT_SFNT_HEAD # define ft_sfnt_maxp FT_SFNT_MAXP # define ft_sfnt_os2 FT_SFNT_OS2 # define ft_sfnt_hhea FT_SFNT_HHEA # define ft_sfnt_vhea FT_SFNT_VHEA # define ft_sfnt_post FT_SFNT_POST # define ft_sfnt_pclt FT_SFNT_PCLT An enumeration to specify indices of SFNT tables loaded and parsed by FreeType during initialization of an SFNT font. Used in the FT_Get_Sfnt_Table API function.","title":"FT_Sfnt_Tag"},{"location":"ft2-truetype_tables.html#ft_get_sfnt_table","text":"Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). FT_EXPORT( void * ) FT_Get_Sfnt_Table ( FT_Face face, FT_Sfnt_Tag tag ); Return a pointer to a given SFNT table stored within a face.","title":"FT_Get_Sfnt_Table"},{"location":"ft2-truetype_tables.html#ft_load_sfnt_table","text":"Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). FT_EXPORT( FT_Error ) FT_Load_Sfnt_Table ( FT_Face face, FT_ULong tag, FT_Long offset, FT_Byte * buffer, FT_ULong * length ); Load any SFNT font table into client memory.","title":"FT_Load_Sfnt_Table"},{"location":"ft2-truetype_tables.html#ft_sfnt_table_info","text":"Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). FT_EXPORT( FT_Error ) FT_Sfnt_Table_Info ( FT_Face face, FT_UInt table_index, FT_ULong *tag, FT_ULong *length ); Return information on an SFNT table.","title":"FT_Sfnt_Table_Info"},{"location":"ft2-truetype_tables.html#ft_get_cmap_language_id","text":"Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). FT_EXPORT( FT_ULong ) FT_Get_CMap_Language_ID ( FT_CharMap charmap ); Return cmap language ID as specified in the OpenType standard. Definitions of language ID values are in file FT_TRUETYPE_IDS_H .","title":"FT_Get_CMap_Language_ID"},{"location":"ft2-truetype_tables.html#ft_get_cmap_format","text":"Defined in FT_TRUETYPE_TABLES_H (freetype/tttables.h). FT_EXPORT( FT_Long ) FT_Get_CMap_Format ( FT_CharMap charmap ); Return the format of an SFNT \u2018cmap\u2019 table.","title":"FT_Get_CMap_Format"},{"location":"ft2-truetype_tables.html#ft_param_tag_unpatented_hinting","text":"# define FT_PARAM_TAG_UNPATENTED_HINTING \\ FT_MAKE_TAG ( 'u', 'n', 'p', 'a' ) Deprecated, no effect. Previously: A constant used as the tag of an FT_Parameter structure to indicate that unpatented methods only should be used by the TrueType bytecode interpreter for a typeface opened by FT_Open_Face .","title":"FT_PARAM_TAG_UNPATENTED_HINTING"},{"location":"ft2-truetype_tables.html#tt_platform_xxx","text":"Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_PLATFORM_APPLE_UNICODE 0 # define TT_PLATFORM_MACINTOSH 1 # define TT_PLATFORM_ISO 2 /* deprecated */ # define TT_PLATFORM_MICROSOFT 3 # define TT_PLATFORM_CUSTOM 4 # define TT_PLATFORM_ADOBE 7 /* artificial */ A list of valid values for the platform_id identifier code in FT_CharMapRec and FT_SfntName structures.","title":"TT_PLATFORM_XXX"},{"location":"ft2-truetype_tables.html#tt_apple_id_xxx","text":"Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_APPLE_ID_DEFAULT 0 /* Unicode 1.0 */ # define TT_APPLE_ID_UNICODE_1_1 1 /* specify Hangul at U+34xx */ # define TT_APPLE_ID_ISO_10646 2 /* deprecated */ # define TT_APPLE_ID_UNICODE_2_0 3 /* or later */ # define TT_APPLE_ID_UNICODE_32 4 /* 2.0 or later, full repertoire */ # define TT_APPLE_ID_VARIANT_SELECTOR 5 /* variation selector data */ # define TT_APPLE_ID_FULL_UNICODE 6 /* used with type 13 cmaps */ A list of valid values for the encoding_id for TT_PLATFORM_APPLE_UNICODE charmaps and name entries.","title":"TT_APPLE_ID_XXX"},{"location":"ft2-truetype_tables.html#tt_mac_id_xxx","text":"Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_MAC_ID_ROMAN 0 # define TT_MAC_ID_JAPANESE 1 # define TT_MAC_ID_TRADITIONAL_CHINESE 2 # define TT_MAC_ID_KOREAN 3 # define TT_MAC_ID_ARABIC 4 # define TT_MAC_ID_HEBREW 5 # define TT_MAC_ID_GREEK 6 # define TT_MAC_ID_RUSSIAN 7 # define TT_MAC_ID_RSYMBOL 8 # define TT_MAC_ID_DEVANAGARI 9 # define TT_MAC_ID_GURMUKHI 10 # define TT_MAC_ID_GUJARATI 11 # define TT_MAC_ID_ORIYA 12 # define TT_MAC_ID_BENGALI 13 # define TT_MAC_ID_TAMIL 14 # define TT_MAC_ID_TELUGU 15 # define TT_MAC_ID_KANNADA 16 # define TT_MAC_ID_MALAYALAM 17 # define TT_MAC_ID_SINHALESE 18 # define TT_MAC_ID_BURMESE 19 # define TT_MAC_ID_KHMER 20 # define TT_MAC_ID_THAI 21 # define TT_MAC_ID_LAOTIAN 22 # define TT_MAC_ID_GEORGIAN 23 # define TT_MAC_ID_ARMENIAN 24 # define TT_MAC_ID_MALDIVIAN 25 # define TT_MAC_ID_SIMPLIFIED_CHINESE 25 # define TT_MAC_ID_TIBETAN 26 # define TT_MAC_ID_MONGOLIAN 27 # define TT_MAC_ID_GEEZ 28 # define TT_MAC_ID_SLAVIC 29 # define TT_MAC_ID_VIETNAMESE 30 # define TT_MAC_ID_SINDHI 31 # define TT_MAC_ID_UNINTERP 32 A list of valid values for the encoding_id for TT_PLATFORM_MACINTOSH charmaps and name entries.","title":"TT_MAC_ID_XXX"},{"location":"ft2-truetype_tables.html#tt_iso_id_xxx","text":"Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_ISO_ID_7BIT_ASCII 0 # define TT_ISO_ID_10646 1 # define TT_ISO_ID_8859_1 2 A list of valid values for the encoding_id for TT_PLATFORM_ISO charmaps and name entries. Their use is now deprecated.","title":"TT_ISO_ID_XXX"},{"location":"ft2-truetype_tables.html#tt_ms_id_xxx","text":"Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_MS_ID_SYMBOL_CS 0 # define TT_MS_ID_UNICODE_CS 1 # define TT_MS_ID_SJIS 2 # define TT_MS_ID_PRC 3 # define TT_MS_ID_BIG_5 4 # define TT_MS_ID_WANSUNG 5 # define TT_MS_ID_JOHAB 6 # define TT_MS_ID_UCS_4 10 /* this value is deprecated */ # define TT_MS_ID_GB2312 TT_MS_ID_PRC A list of valid values for the encoding_id for TT_PLATFORM_MICROSOFT charmaps and name entries.","title":"TT_MS_ID_XXX"},{"location":"ft2-truetype_tables.html#tt_adobe_id_xxx","text":"Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_ADOBE_ID_STANDARD 0 # define TT_ADOBE_ID_EXPERT 1 # define TT_ADOBE_ID_CUSTOM 2 # define TT_ADOBE_ID_LATIN_1 3 A list of valid values for the encoding_id for TT_PLATFORM_ADOBE charmaps. This is a FreeType-specific extension!","title":"TT_ADOBE_ID_XXX"},{"location":"ft2-truetype_tables.html#tt_mac_langid_xxx","text":"Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_MAC_LANGID_ENGLISH 0 # define TT_MAC_LANGID_FRENCH 1 # define TT_MAC_LANGID_GERMAN 2 # define TT_MAC_LANGID_ITALIAN 3 # define TT_MAC_LANGID_DUTCH 4 # define TT_MAC_LANGID_SWEDISH 5 # define TT_MAC_LANGID_SPANISH 6 # define TT_MAC_LANGID_DANISH 7 # define TT_MAC_LANGID_PORTUGUESE 8 # define TT_MAC_LANGID_NORWEGIAN 9 # define TT_MAC_LANGID_HEBREW 10 # define TT_MAC_LANGID_JAPANESE 11 # define TT_MAC_LANGID_ARABIC 12 # define TT_MAC_LANGID_FINNISH 13 # define TT_MAC_LANGID_GREEK 14 # define TT_MAC_LANGID_ICELANDIC 15 # define TT_MAC_LANGID_MALTESE 16 # define TT_MAC_LANGID_TURKISH 17 # define TT_MAC_LANGID_CROATIAN 18 # define TT_MAC_LANGID_CHINESE_TRADITIONAL 19 # define TT_MAC_LANGID_URDU 20 # define TT_MAC_LANGID_HINDI 21 # define TT_MAC_LANGID_THAI 22 # define TT_MAC_LANGID_KOREAN 23 # define TT_MAC_LANGID_LITHUANIAN 24 # define TT_MAC_LANGID_POLISH 25 # define TT_MAC_LANGID_HUNGARIAN 26 # define TT_MAC_LANGID_ESTONIAN 27 # define TT_MAC_LANGID_LETTISH 28 # define TT_MAC_LANGID_SAAMISK 29 # define TT_MAC_LANGID_FAEROESE 30 # define TT_MAC_LANGID_FARSI 31 # define TT_MAC_LANGID_RUSSIAN 32 # define TT_MAC_LANGID_CHINESE_SIMPLIFIED 33 # define TT_MAC_LANGID_FLEMISH 34 # define TT_MAC_LANGID_IRISH 35 # define TT_MAC_LANGID_ALBANIAN 36 # define TT_MAC_LANGID_ROMANIAN 37 # define TT_MAC_LANGID_CZECH 38 # define TT_MAC_LANGID_SLOVAK 39 # define TT_MAC_LANGID_SLOVENIAN 40 # define TT_MAC_LANGID_YIDDISH 41 # define TT_MAC_LANGID_SERBIAN 42 # define TT_MAC_LANGID_MACEDONIAN 43 # define TT_MAC_LANGID_BULGARIAN 44 # define TT_MAC_LANGID_UKRAINIAN 45 # define TT_MAC_LANGID_BYELORUSSIAN 46 # define TT_MAC_LANGID_UZBEK 47 # define TT_MAC_LANGID_KAZAKH 48 # define TT_MAC_LANGID_AZERBAIJANI 49 # define TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT 49 # define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT 50 # define TT_MAC_LANGID_ARMENIAN 51 # define TT_MAC_LANGID_GEORGIAN 52 # define TT_MAC_LANGID_MOLDAVIAN 53 # define TT_MAC_LANGID_KIRGHIZ 54 # define TT_MAC_LANGID_TAJIKI 55 # define TT_MAC_LANGID_TURKMEN 56 # define TT_MAC_LANGID_MONGOLIAN 57 # define TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT 57 # define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT 58 # define TT_MAC_LANGID_PASHTO 59 # define TT_MAC_LANGID_KURDISH 60 # define TT_MAC_LANGID_KASHMIRI 61 # define TT_MAC_LANGID_SINDHI 62 # define TT_MAC_LANGID_TIBETAN 63 # define TT_MAC_LANGID_NEPALI 64 # define TT_MAC_LANGID_SANSKRIT 65 # define TT_MAC_LANGID_MARATHI 66 # define TT_MAC_LANGID_BENGALI 67 # define TT_MAC_LANGID_ASSAMESE 68 # define TT_MAC_LANGID_GUJARATI 69 # define TT_MAC_LANGID_PUNJABI 70 # define TT_MAC_LANGID_ORIYA 71 # define TT_MAC_LANGID_MALAYALAM 72 # define TT_MAC_LANGID_KANNADA 73 # define TT_MAC_LANGID_TAMIL 74 # define TT_MAC_LANGID_TELUGU 75 # define TT_MAC_LANGID_SINHALESE 76 # define TT_MAC_LANGID_BURMESE 77 # define TT_MAC_LANGID_KHMER 78 # define TT_MAC_LANGID_LAO 79 # define TT_MAC_LANGID_VIETNAMESE 80 # define TT_MAC_LANGID_INDONESIAN 81 # define TT_MAC_LANGID_TAGALOG 82 # define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT 83 # define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT 84 # define TT_MAC_LANGID_AMHARIC 85 # define TT_MAC_LANGID_TIGRINYA 86 # define TT_MAC_LANGID_GALLA 87 # define TT_MAC_LANGID_SOMALI 88 # define TT_MAC_LANGID_SWAHILI 89 # define TT_MAC_LANGID_RUANDA 90 # define TT_MAC_LANGID_RUNDI 91 # define TT_MAC_LANGID_CHEWA 92 # define TT_MAC_LANGID_MALAGASY 93 # define TT_MAC_LANGID_ESPERANTO 94 # define TT_MAC_LANGID_WELSH 128 # define TT_MAC_LANGID_BASQUE 129 # define TT_MAC_LANGID_CATALAN 130 # define TT_MAC_LANGID_LATIN 131 # define TT_MAC_LANGID_QUECHUA 132 # define TT_MAC_LANGID_GUARANI 133 # define TT_MAC_LANGID_AYMARA 134 # define TT_MAC_LANGID_TATAR 135 # define TT_MAC_LANGID_UIGHUR 136 # define TT_MAC_LANGID_DZONGKHA 137 # define TT_MAC_LANGID_JAVANESE 138 # define TT_MAC_LANGID_SUNDANESE 139 /* The following codes are new as of 2000-03-10 */ # define TT_MAC_LANGID_GALICIAN 140 # define TT_MAC_LANGID_AFRIKAANS 141 # define TT_MAC_LANGID_BRETON 142 # define TT_MAC_LANGID_INUKTITUT 143 # define TT_MAC_LANGID_SCOTTISH_GAELIC 144 # define TT_MAC_LANGID_MANX_GAELIC 145 # define TT_MAC_LANGID_IRISH_GAELIC 146 # define TT_MAC_LANGID_TONGAN 147 # define TT_MAC_LANGID_GREEK_POLYTONIC 148 # define TT_MAC_LANGID_GREELANDIC 149 # define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT 150 Possible values of the language identifier field in the name records of the SFNT \u2018name\u2019 table if the \u2018platform\u2019 identifier code is TT_PLATFORM_MACINTOSH . These values are also used as return values for function FT_Get_CMap_Language_ID . The canonical source for Apple's IDs is https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html","title":"TT_MAC_LANGID_XXX"},{"location":"ft2-truetype_tables.html#tt_ms_langid_xxx","text":"Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_MS_LANGID_ARABIC_SAUDI_ARABIA 0x0401 # define TT_MS_LANGID_ARABIC_IRAQ 0x0801 # define TT_MS_LANGID_ARABIC_EGYPT 0x0C01 # define TT_MS_LANGID_ARABIC_LIBYA 0x1001 # define TT_MS_LANGID_ARABIC_ALGERIA 0x1401 # define TT_MS_LANGID_ARABIC_MOROCCO 0x1801 # define TT_MS_LANGID_ARABIC_TUNISIA 0x1C01 # define TT_MS_LANGID_ARABIC_OMAN 0x2001 # define TT_MS_LANGID_ARABIC_YEMEN 0x2401 # define TT_MS_LANGID_ARABIC_SYRIA 0x2801 # define TT_MS_LANGID_ARABIC_JORDAN 0x2C01 # define TT_MS_LANGID_ARABIC_LEBANON 0x3001 # define TT_MS_LANGID_ARABIC_KUWAIT 0x3401 # define TT_MS_LANGID_ARABIC_UAE 0x3801 # define TT_MS_LANGID_ARABIC_BAHRAIN 0x3C01 # define TT_MS_LANGID_ARABIC_QATAR 0x4001 # define TT_MS_LANGID_BULGARIAN_BULGARIA 0x0402 # define TT_MS_LANGID_CATALAN_CATALAN 0x0403 # define TT_MS_LANGID_CHINESE_TAIWAN 0x0404 # define TT_MS_LANGID_CHINESE_PRC 0x0804 # define TT_MS_LANGID_CHINESE_HONG_KONG 0x0C04 # define TT_MS_LANGID_CHINESE_SINGAPORE 0x1004 # define TT_MS_LANGID_CHINESE_MACAO 0x1404 # define TT_MS_LANGID_CZECH_CZECH_REPUBLIC 0x0405 # define TT_MS_LANGID_DANISH_DENMARK 0x0406 # define TT_MS_LANGID_GERMAN_GERMANY 0x0407 # define TT_MS_LANGID_GERMAN_SWITZERLAND 0x0807 # define TT_MS_LANGID_GERMAN_AUSTRIA 0x0C07 # define TT_MS_LANGID_GERMAN_LUXEMBOURG 0x1007 # define TT_MS_LANGID_GERMAN_LIECHTENSTEIN 0x1407 # define TT_MS_LANGID_GREEK_GREECE 0x0408 # define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409 # define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM 0x0809 # define TT_MS_LANGID_ENGLISH_AUSTRALIA 0x0C09 # define TT_MS_LANGID_ENGLISH_CANADA 0x1009 # define TT_MS_LANGID_ENGLISH_NEW_ZEALAND 0x1409 # define TT_MS_LANGID_ENGLISH_IRELAND 0x1809 # define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA 0x1C09 # define TT_MS_LANGID_ENGLISH_JAMAICA 0x2009 # define TT_MS_LANGID_ENGLISH_CARIBBEAN 0x2409 # define TT_MS_LANGID_ENGLISH_BELIZE 0x2809 # define TT_MS_LANGID_ENGLISH_TRINIDAD 0x2C09 # define TT_MS_LANGID_ENGLISH_ZIMBABWE 0x3009 # define TT_MS_LANGID_ENGLISH_PHILIPPINES 0x3409 # define TT_MS_LANGID_ENGLISH_INDIA 0x4009 # define TT_MS_LANGID_ENGLISH_MALAYSIA 0x4409 # define TT_MS_LANGID_ENGLISH_SINGAPORE 0x4809 # define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT 0x040A # define TT_MS_LANGID_SPANISH_MEXICO 0x080A # define TT_MS_LANGID_SPANISH_SPAIN_MODERN_SORT 0x0C0A # define TT_MS_LANGID_SPANISH_GUATEMALA 0x100A # define TT_MS_LANGID_SPANISH_COSTA_RICA 0x140A # define TT_MS_LANGID_SPANISH_PANAMA 0x180A # define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC 0x1C0A # define TT_MS_LANGID_SPANISH_VENEZUELA 0x200A # define TT_MS_LANGID_SPANISH_COLOMBIA 0x240A # define TT_MS_LANGID_SPANISH_PERU 0x280A # define TT_MS_LANGID_SPANISH_ARGENTINA 0x2C0A # define TT_MS_LANGID_SPANISH_ECUADOR 0x300A # define TT_MS_LANGID_SPANISH_CHILE 0x340A # define TT_MS_LANGID_SPANISH_URUGUAY 0x380A # define TT_MS_LANGID_SPANISH_PARAGUAY 0x3C0A # define TT_MS_LANGID_SPANISH_BOLIVIA 0x400A # define TT_MS_LANGID_SPANISH_EL_SALVADOR 0x440A # define TT_MS_LANGID_SPANISH_HONDURAS 0x480A # define TT_MS_LANGID_SPANISH_NICARAGUA 0x4C0A # define TT_MS_LANGID_SPANISH_PUERTO_RICO 0x500A # define TT_MS_LANGID_SPANISH_UNITED_STATES 0x540A # define TT_MS_LANGID_FINNISH_FINLAND 0x040B # define TT_MS_LANGID_FRENCH_FRANCE 0x040C # define TT_MS_LANGID_FRENCH_BELGIUM 0x080C # define TT_MS_LANGID_FRENCH_CANADA 0x0C0C # define TT_MS_LANGID_FRENCH_SWITZERLAND 0x100C # define TT_MS_LANGID_FRENCH_LUXEMBOURG 0x140C # define TT_MS_LANGID_FRENCH_MONACO 0x180C # define TT_MS_LANGID_HEBREW_ISRAEL 0x040D # define TT_MS_LANGID_HUNGARIAN_HUNGARY 0x040E # define TT_MS_LANGID_ICELANDIC_ICELAND 0x040F # define TT_MS_LANGID_ITALIAN_ITALY 0x0410 # define TT_MS_LANGID_ITALIAN_SWITZERLAND 0x0810 # define TT_MS_LANGID_JAPANESE_JAPAN 0x0411 # define TT_MS_LANGID_KOREAN_KOREA 0x0412 # define TT_MS_LANGID_DUTCH_NETHERLANDS 0x0413 # define TT_MS_LANGID_DUTCH_BELGIUM 0x0813 # define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL 0x0414 # define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK 0x0814 # define TT_MS_LANGID_POLISH_POLAND 0x0415 # define TT_MS_LANGID_PORTUGUESE_BRAZIL 0x0416 # define TT_MS_LANGID_PORTUGUESE_PORTUGAL 0x0816 # define TT_MS_LANGID_ROMANSH_SWITZERLAND 0x0417 # define TT_MS_LANGID_ROMANIAN_ROMANIA 0x0418 # define TT_MS_LANGID_RUSSIAN_RUSSIA 0x0419 # define TT_MS_LANGID_CROATIAN_CROATIA 0x041A # define TT_MS_LANGID_SERBIAN_SERBIA_LATIN 0x081A # define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 0x0C1A # define TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA 0x101A # define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x141A # define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN 0x181A # define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC 0x1C1A # define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZ_CYRILLIC 0x201A # define TT_MS_LANGID_SLOVAK_SLOVAKIA 0x041B # define TT_MS_LANGID_ALBANIAN_ALBANIA 0x041C # define TT_MS_LANGID_SWEDISH_SWEDEN 0x041D # define TT_MS_LANGID_SWEDISH_FINLAND 0x081D # define TT_MS_LANGID_THAI_THAILAND 0x041E # define TT_MS_LANGID_TURKISH_TURKEY 0x041F # define TT_MS_LANGID_URDU_PAKISTAN 0x0420 # define TT_MS_LANGID_INDONESIAN_INDONESIA 0x0421 # define TT_MS_LANGID_UKRAINIAN_UKRAINE 0x0422 # define TT_MS_LANGID_BELARUSIAN_BELARUS 0x0423 # define TT_MS_LANGID_SLOVENIAN_SLOVENIA 0x0424 # define TT_MS_LANGID_ESTONIAN_ESTONIA 0x0425 # define TT_MS_LANGID_LATVIAN_LATVIA 0x0426 # define TT_MS_LANGID_LITHUANIAN_LITHUANIA 0x0427 # define TT_MS_LANGID_TAJIK_TAJIKISTAN 0x0428 # define TT_MS_LANGID_VIETNAMESE_VIET_NAM 0x042A # define TT_MS_LANGID_ARMENIAN_ARMENIA 0x042B # define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN 0x042C # define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC 0x082C # define TT_MS_LANGID_BASQUE_BASQUE 0x042D # define TT_MS_LANGID_UPPER_SORBIAN_GERMANY 0x042E # define TT_MS_LANGID_LOWER_SORBIAN_GERMANY 0x082E # define TT_MS_LANGID_MACEDONIAN_MACEDONIA 0x042F # define TT_MS_LANGID_SETSWANA_SOUTH_AFRICA 0x0432 # define TT_MS_LANGID_ISIXHOSA_SOUTH_AFRICA 0x0434 # define TT_MS_LANGID_ISIZULU_SOUTH_AFRICA 0x0435 # define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA 0x0436 # define TT_MS_LANGID_GEORGIAN_GEORGIA 0x0437 # define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 0x0438 # define TT_MS_LANGID_HINDI_INDIA 0x0439 # define TT_MS_LANGID_MALTESE_MALTA 0x043A # define TT_MS_LANGID_SAMI_NORTHERN_NORWAY 0x043B # define TT_MS_LANGID_SAMI_NORTHERN_SWEDEN 0x083B # define TT_MS_LANGID_SAMI_NORTHERN_FINLAND 0x0C3B # define TT_MS_LANGID_SAMI_LULE_NORWAY 0x103B # define TT_MS_LANGID_SAMI_LULE_SWEDEN 0x143B # define TT_MS_LANGID_SAMI_SOUTHERN_NORWAY 0x183B # define TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN 0x1C3B # define TT_MS_LANGID_SAMI_SKOLT_FINLAND 0x203B # define TT_MS_LANGID_SAMI_INARI_FINLAND 0x243B # define TT_MS_LANGID_IRISH_IRELAND 0x083C # define TT_MS_LANGID_MALAY_MALAYSIA 0x043E # define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 0x083E # define TT_MS_LANGID_KAZAKH_KAZAKHSTAN 0x043F # define TT_MS_LANGID_KYRGYZ_KYRGYZSTAN /* Cyrillic*/ 0x0440 # define TT_MS_LANGID_KISWAHILI_KENYA 0x0441 # define TT_MS_LANGID_TURKMEN_TURKMENISTAN 0x0442 # define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 0x0443 # define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC 0x0843 # define TT_MS_LANGID_TATAR_RUSSIA 0x0444 # define TT_MS_LANGID_BENGALI_INDIA 0x0445 # define TT_MS_LANGID_BENGALI_BANGLADESH 0x0845 # define TT_MS_LANGID_PUNJABI_INDIA 0x0446 # define TT_MS_LANGID_GUJARATI_INDIA 0x0447 # define TT_MS_LANGID_ODIA_INDIA 0x0448 # define TT_MS_LANGID_TAMIL_INDIA 0x0449 # define TT_MS_LANGID_TELUGU_INDIA 0x044A # define TT_MS_LANGID_KANNADA_INDIA 0x044B # define TT_MS_LANGID_MALAYALAM_INDIA 0x044C # define TT_MS_LANGID_ASSAMESE_INDIA 0x044D # define TT_MS_LANGID_MARATHI_INDIA 0x044E # define TT_MS_LANGID_SANSKRIT_INDIA 0x044F # define TT_MS_LANGID_MONGOLIAN_MONGOLIA /* Cyrillic */ 0x0450 # define TT_MS_LANGID_MONGOLIAN_PRC 0x0850 # define TT_MS_LANGID_TIBETAN_PRC 0x0451 # define TT_MS_LANGID_WELSH_UNITED_KINGDOM 0x0452 # define TT_MS_LANGID_KHMER_CAMBODIA 0x0453 # define TT_MS_LANGID_LAO_LAOS 0x0454 # define TT_MS_LANGID_GALICIAN_GALICIAN 0x0456 # define TT_MS_LANGID_KONKANI_INDIA 0x0457 # define TT_MS_LANGID_SYRIAC_SYRIA 0x045A # define TT_MS_LANGID_SINHALA_SRI_LANKA 0x045B # define TT_MS_LANGID_INUKTITUT_CANADA 0x045D # define TT_MS_LANGID_INUKTITUT_CANADA_LATIN 0x085D # define TT_MS_LANGID_AMHARIC_ETHIOPIA 0x045E # define TT_MS_LANGID_TAMAZIGHT_ALGERIA 0x085F # define TT_MS_LANGID_NEPALI_NEPAL 0x0461 # define TT_MS_LANGID_FRISIAN_NETHERLANDS 0x0462 # define TT_MS_LANGID_PASHTO_AFGHANISTAN 0x0463 # define TT_MS_LANGID_FILIPINO_PHILIPPINES 0x0464 # define TT_MS_LANGID_DHIVEHI_MALDIVES 0x0465 # define TT_MS_LANGID_HAUSA_NIGERIA 0x0468 # define TT_MS_LANGID_YORUBA_NIGERIA 0x046A # define TT_MS_LANGID_QUECHUA_BOLIVIA 0x046B # define TT_MS_LANGID_QUECHUA_ECUADOR 0x086B # define TT_MS_LANGID_QUECHUA_PERU 0x0C6B # define TT_MS_LANGID_SESOTHO_SA_LEBOA_SOUTH_AFRICA 0x046C # define TT_MS_LANGID_BASHKIR_RUSSIA 0x046D # define TT_MS_LANGID_LUXEMBOURGISH_LUXEMBOURG 0x046E # define TT_MS_LANGID_GREENLANDIC_GREENLAND 0x046F # define TT_MS_LANGID_IGBO_NIGERIA 0x0470 # define TT_MS_LANGID_YI_PRC 0x0478 # define TT_MS_LANGID_MAPUDUNGUN_CHILE 0x047A # define TT_MS_LANGID_MOHAWK_MOHAWK 0x047C # define TT_MS_LANGID_BRETON_FRANCE 0x047E # define TT_MS_LANGID_UIGHUR_PRC 0x0480 # define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0481 # define TT_MS_LANGID_OCCITAN_FRANCE 0x0482 # define TT_MS_LANGID_CORSICAN_FRANCE 0x0483 # define TT_MS_LANGID_ALSATIAN_FRANCE 0x0484 # define TT_MS_LANGID_YAKUT_RUSSIA 0x0485 # define TT_MS_LANGID_KICHE_GUATEMALA 0x0486 # define TT_MS_LANGID_KINYARWANDA_RWANDA 0x0487 # define TT_MS_LANGID_WOLOF_SENEGAL 0x0488 # define TT_MS_LANGID_DARI_AFGHANISTAN 0x048C Possible values of the language identifier field in the name records of the SFNT \u2018name\u2019 table if the \u2018platform\u2019 identifier code is TT_PLATFORM_MICROSOFT . These values are also used as return values for function FT_Get_CMap_Language_ID . The canonical source for Microsoft's IDs is https://docs.microsoft.com/en-us/windows/desktop/Intl/language-identifier-constants-and-strings , however, we only provide macros for language identifiers present in the OpenType specification: Microsoft has abandoned the concept of LCIDs (language code identifiers), and format 1 of the \u2018name\u2019 table provides a better mechanism for languages not covered here. More legacy values not listed in the reference can be found in the FT_TRUETYPE_IDS_H header file.","title":"TT_MS_LANGID_XXX"},{"location":"ft2-truetype_tables.html#tt_name_id_xxx","text":"Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). # define TT_NAME_ID_COPYRIGHT 0 # define TT_NAME_ID_FONT_FAMILY 1 # define TT_NAME_ID_FONT_SUBFAMILY 2 # define TT_NAME_ID_UNIQUE_ID 3 # define TT_NAME_ID_FULL_NAME 4 # define TT_NAME_ID_VERSION_STRING 5 # define TT_NAME_ID_PS_NAME 6 # define TT_NAME_ID_TRADEMARK 7 /* the following values are from the OpenType spec */ # define TT_NAME_ID_MANUFACTURER 8 # define TT_NAME_ID_DESIGNER 9 # define TT_NAME_ID_DESCRIPTION 10 # define TT_NAME_ID_VENDOR_URL 11 # define TT_NAME_ID_DESIGNER_URL 12 # define TT_NAME_ID_LICENSE 13 # define TT_NAME_ID_LICENSE_URL 14 /* number 15 is reserved */ # define TT_NAME_ID_TYPOGRAPHIC_FAMILY 16 # define TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY 17 # define TT_NAME_ID_MAC_FULL_NAME 18 /* The following code is new as of 2000-01-21 */ # define TT_NAME_ID_SAMPLE_TEXT 19 /* This is new in OpenType 1.3 */ # define TT_NAME_ID_CID_FINDFONT_NAME 20 /* This is new in OpenType 1.5 */ # define TT_NAME_ID_WWS_FAMILY 21 # define TT_NAME_ID_WWS_SUBFAMILY 22 /* This is new in OpenType 1.7 */ # define TT_NAME_ID_LIGHT_BACKGROUND 23 # define TT_NAME_ID_DARK_BACKGROUND 24 /* This is new in OpenType 1.8 */ # define TT_NAME_ID_VARIATIONS_PREFIX 25 /* these two values are deprecated */ # define TT_NAME_ID_PREFERRED_FAMILY TT_NAME_ID_TYPOGRAPHIC_FAMILY # define TT_NAME_ID_PREFERRED_SUBFAMILY TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY Possible values of the \u2018name\u2019 identifier field in the name records of an SFNT \u2018name\u2019 table. These values are platform independent.","title":"TT_NAME_ID_XXX"},{"location":"ft2-truetype_tables.html#tt_ucr_xxx","text":"Defined in FT_TRUETYPE_IDS_H (freetype/ttnameid.h). /* ulUnicodeRange1 */ /* --------------- */ /* Bit 0 Basic Latin */ # define TT_UCR_BASIC_LATIN (1L << 0) /* U+0020-U+007E */ /* Bit 1 C1 Controls and Latin-1 Supplement */ # define TT_UCR_LATIN1_SUPPLEMENT (1L << 1) /* U+0080-U+00FF */ /* Bit 2 Latin Extended-A */ # define TT_UCR_LATIN_EXTENDED_A (1L << 2) /* U+0100-U+017F */ /* Bit 3 Latin Extended-B */ # define TT_UCR_LATIN_EXTENDED_B (1L << 3) /* U+0180-U+024F */ /* Bit 4 IPA Extensions */ /* Phonetic Extensions */ /* Phonetic Extensions Supplement */ # define TT_UCR_IPA_EXTENSIONS (1L << 4) /* U+0250-U+02AF */ /* U+1D00-U+1D7F */ /* U+1D80-U+1DBF */ /* Bit 5 Spacing Modifier Letters */ /* Modifier Tone Letters */ # define TT_UCR_SPACING_MODIFIER (1L << 5) /* U+02B0-U+02FF */ /* U+A700-U+A71F */ /* Bit 6 Combining Diacritical Marks */ /* Combining Diacritical Marks Supplement */ # define TT_UCR_COMBINING_DIACRITICAL_MARKS (1L << 6) /* U+0300-U+036F */ /* U+1DC0-U+1DFF */ /* Bit 7 Greek and Coptic */ # define TT_UCR_GREEK (1L << 7) /* U+0370-U+03FF */ /* Bit 8 Coptic */ # define TT_UCR_COPTIC (1L << 8) /* U+2C80-U+2CFF */ /* Bit 9 Cyrillic */ /* Cyrillic Supplement */ /* Cyrillic Extended-A */ /* Cyrillic Extended-B */ # define TT_UCR_CYRILLIC (1L << 9) /* U+0400-U+04FF */ /* U+0500-U+052F */ /* U+2DE0-U+2DFF */ /* U+A640-U+A69F */ /* Bit 10 Armenian */ # define TT_UCR_ARMENIAN (1L << 10) /* U+0530-U+058F */ /* Bit 11 Hebrew */ # define TT_UCR_HEBREW (1L << 11) /* U+0590-U+05FF */ /* Bit 12 Vai */ # define TT_UCR_VAI (1L << 12) /* U+A500-U+A63F */ /* Bit 13 Arabic */ /* Arabic Supplement */ # define TT_UCR_ARABIC (1L << 13) /* U+0600-U+06FF */ /* U+0750-U+077F */ /* Bit 14 NKo */ # define TT_UCR_NKO (1L << 14) /* U+07C0-U+07FF */ /* Bit 15 Devanagari */ # define TT_UCR_DEVANAGARI (1L << 15) /* U+0900-U+097F */ /* Bit 16 Bengali */ # define TT_UCR_BENGALI (1L << 16) /* U+0980-U+09FF */ /* Bit 17 Gurmukhi */ # define TT_UCR_GURMUKHI (1L << 17) /* U+0A00-U+0A7F */ /* Bit 18 Gujarati */ # define TT_UCR_GUJARATI (1L << 18) /* U+0A80-U+0AFF */ /* Bit 19 Oriya */ # define TT_UCR_ORIYA (1L << 19) /* U+0B00-U+0B7F */ /* Bit 20 Tamil */ # define TT_UCR_TAMIL (1L << 20) /* U+0B80-U+0BFF */ /* Bit 21 Telugu */ # define TT_UCR_TELUGU (1L << 21) /* U+0C00-U+0C7F */ /* Bit 22 Kannada */ # define TT_UCR_KANNADA (1L << 22) /* U+0C80-U+0CFF */ /* Bit 23 Malayalam */ # define TT_UCR_MALAYALAM (1L << 23) /* U+0D00-U+0D7F */ /* Bit 24 Thai */ # define TT_UCR_THAI (1L << 24) /* U+0E00-U+0E7F */ /* Bit 25 Lao */ # define TT_UCR_LAO (1L << 25) /* U+0E80-U+0EFF */ /* Bit 26 Georgian */ /* Georgian Supplement */ # define TT_UCR_GEORGIAN (1L << 26) /* U+10A0-U+10FF */ /* U+2D00-U+2D2F */ /* Bit 27 Balinese */ # define TT_UCR_BALINESE (1L << 27) /* U+1B00-U+1B7F */ /* Bit 28 Hangul Jamo */ # define TT_UCR_HANGUL_JAMO (1L << 28) /* U+1100-U+11FF */ /* Bit 29 Latin Extended Additional */ /* Latin Extended-C */ /* Latin Extended-D */ # define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1L << 29) /* U+1E00-U+1EFF */ /* U+2C60-U+2C7F */ /* U+A720-U+A7FF */ /* Bit 30 Greek Extended */ # define TT_UCR_GREEK_EXTENDED (1L << 30) /* U+1F00-U+1FFF */ /* Bit 31 General Punctuation */ /* Supplemental Punctuation */ # define TT_UCR_GENERAL_PUNCTUATION (1L << 31) /* U+2000-U+206F */ /* U+2E00-U+2E7F */ /* ulUnicodeRange2 */ /* --------------- */ /* Bit 32 Superscripts And Subscripts */ # define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1L << 0) /* U+2070-U+209F */ /* Bit 33 Currency Symbols */ # define TT_UCR_CURRENCY_SYMBOLS (1L << 1) /* U+20A0-U+20CF */ /* Bit 34 Combining Diacritical Marks For Symbols */ # define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \\ (1L << 2) /* U+20D0-U+20FF */ /* Bit 35 Letterlike Symbols */ # define TT_UCR_LETTERLIKE_SYMBOLS (1L << 3) /* U+2100-U+214F */ /* Bit 36 Number Forms */ # define TT_UCR_NUMBER_FORMS (1L << 4) /* U+2150-U+218F */ /* Bit 37 Arrows */ /* Supplemental Arrows-A */ /* Supplemental Arrows-B */ /* Miscellaneous Symbols and Arrows */ # define TT_UCR_ARROWS (1L << 5) /* U+2190-U+21FF */ /* U+27F0-U+27FF */ /* U+2900-U+297F */ /* U+2B00-U+2BFF */ /* Bit 38 Mathematical Operators */ /* Supplemental Mathematical Operators */ /* Miscellaneous Mathematical Symbols-A */ /* Miscellaneous Mathematical Symbols-B */ # define TT_UCR_MATHEMATICAL_OPERATORS (1L << 6) /* U+2200-U+22FF */ /* U+2A00-U+2AFF */ /* U+27C0-U+27EF */ /* U+2980-U+29FF */ /* Bit 39 Miscellaneous Technical */ # define TT_UCR_MISCELLANEOUS_TECHNICAL (1L << 7) /* U+2300-U+23FF */ /* Bit 40 Control Pictures */ # define TT_UCR_CONTROL_PICTURES (1L << 8) /* U+2400-U+243F */ /* Bit 41 Optical Character Recognition */ # define TT_UCR_OCR (1L << 9) /* U+2440-U+245F */ /* Bit 42 Enclosed Alphanumerics */ # define TT_UCR_ENCLOSED_ALPHANUMERICS (1L << 10) /* U+2460-U+24FF */ /* Bit 43 Box Drawing */ # define TT_UCR_BOX_DRAWING (1L << 11) /* U+2500-U+257F */ /* Bit 44 Block Elements */ # define TT_UCR_BLOCK_ELEMENTS (1L << 12) /* U+2580-U+259F */ /* Bit 45 Geometric Shapes */ # define TT_UCR_GEOMETRIC_SHAPES (1L << 13) /* U+25A0-U+25FF */ /* Bit 46 Miscellaneous Symbols */ # define TT_UCR_MISCELLANEOUS_SYMBOLS (1L << 14) /* U+2600-U+26FF */ /* Bit 47 Dingbats */ # define TT_UCR_DINGBATS (1L << 15) /* U+2700-U+27BF */ /* Bit 48 CJK Symbols and Punctuation */ # define TT_UCR_CJK_SYMBOLS (1L << 16) /* U+3000-U+303F */ /* Bit 49 Hiragana */ # define TT_UCR_HIRAGANA (1L << 17) /* U+3040-U+309F */ /* Bit 50 Katakana */ /* Katakana Phonetic Extensions */ # define TT_UCR_KATAKANA (1L << 18) /* U+30A0-U+30FF */ /* U+31F0-U+31FF */ /* Bit 51 Bopomofo */ /* Bopomofo Extended */ # define TT_UCR_BOPOMOFO (1L << 19) /* U+3100-U+312F */ /* U+31A0-U+31BF */ /* Bit 52 Hangul Compatibility Jamo */ # define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1L << 20) /* U+3130-U+318F */ /* Bit 53 Phags-Pa */ # define TT_UCR_CJK_MISC (1L << 21) /* U+A840-U+A87F */ # define TT_UCR_KANBUN TT_UCR_CJK_MISC /* deprecated */ # define TT_UCR_PHAGSPA /* Bit 54 Enclosed CJK Letters and Months */ # define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1L << 22) /* U+3200-U+32FF */ /* Bit 55 CJK Compatibility */ # define TT_UCR_CJK_COMPATIBILITY (1L << 23) /* U+3300-U+33FF */ /* Bit 56 Hangul Syllables */ # define TT_UCR_HANGUL (1L << 24) /* U+AC00-U+D7A3 */ /* Bit 57 High Surrogates */ /* High Private Use Surrogates */ /* Low Surrogates */ /* According to OpenType specs v.1.3+, */ /* setting bit 57 implies that there is */ /* at least one codepoint beyond the */ /* Basic Multilingual Plane that is */ /* supported by this font. So it really */ /* means >= U+10000. */ # define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DB7F */ /* U+DB80-U+DBFF */ /* U+DC00-U+DFFF */ # define TT_UCR_NON_PLANE_0 TT_UCR_SURROGATES /* Bit 58 Phoenician */ # define TT_UCR_PHOENICIAN (1L << 26) /*U+10900-U+1091F*/ /* Bit 59 CJK Unified Ideographs */ /* CJK Radicals Supplement */ /* Kangxi Radicals */ /* Ideographic Description Characters */ /* CJK Unified Ideographs Extension A */ /* CJK Unified Ideographs Extension B */ /* Kanbun */ # define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1L << 27) /* U+4E00-U+9FFF */ /* U+2E80-U+2EFF */ /* U+2F00-U+2FDF */ /* U+2FF0-U+2FFF */ /* U+3400-U+4DB5 */ /*U+20000-U+2A6DF*/ /* U+3190-U+319F */ /* Bit 60 Private Use */ # define TT_UCR_PRIVATE_USE (1L << 28) /* U+E000-U+F8FF */ /* Bit 61 CJK Strokes */ /* CJK Compatibility Ideographs */ /* CJK Compatibility Ideographs Supplement */ # define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1L << 29) /* U+31C0-U+31EF */ /* U+F900-U+FAFF */ /*U+2F800-U+2FA1F*/ /* Bit 62 Alphabetic Presentation Forms */ # define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1L << 30) /* U+FB00-U+FB4F */ /* Bit 63 Arabic Presentation Forms-A */ # define TT_UCR_ARABIC_PRESENTATION_FORMS_A (1L << 31) /* U+FB50-U+FDFF */ /* ulUnicodeRange3 */ /* --------------- */ /* Bit 64 Combining Half Marks */ # define TT_UCR_COMBINING_HALF_MARKS (1L << 0) /* U+FE20-U+FE2F */ /* Bit 65 Vertical forms */ /* CJK Compatibility Forms */ # define TT_UCR_CJK_COMPATIBILITY_FORMS (1L << 1) /* U+FE10-U+FE1F */ /* U+FE30-U+FE4F */ /* Bit 66 Small Form Variants */ # define TT_UCR_SMALL_FORM_VARIANTS (1L << 2) /* U+FE50-U+FE6F */ /* Bit 67 Arabic Presentation Forms-B */ # define TT_UCR_ARABIC_PRESENTATION_FORMS_B (1L << 3) /* U+FE70-U+FEFE */ /* Bit 68 Halfwidth and Fullwidth Forms */ # define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1L << 4) /* U+FF00-U+FFEF */ /* Bit 69 Specials */ # define TT_UCR_SPECIALS (1L << 5) /* U+FFF0-U+FFFD */ /* Bit 70 Tibetan */ # define TT_UCR_TIBETAN (1L << 6) /* U+0F00-U+0FFF */ /* Bit 71 Syriac */ # define TT_UCR_SYRIAC (1L << 7) /* U+0700-U+074F */ /* Bit 72 Thaana */ # define TT_UCR_THAANA (1L << 8) /* U+0780-U+07BF */ /* Bit 73 Sinhala */ # define TT_UCR_SINHALA (1L << 9) /* U+0D80-U+0DFF */ /* Bit 74 Myanmar */ # define TT_UCR_MYANMAR (1L << 10) /* U+1000-U+109F */ /* Bit 75 Ethiopic */ /* Ethiopic Supplement */ /* Ethiopic Extended */ # define TT_UCR_ETHIOPIC (1L << 11) /* U+1200-U+137F */ /* U+1380-U+139F */ /* U+2D80-U+2DDF */ /* Bit 76 Cherokee */ # define TT_UCR_CHEROKEE (1L << 12) /* U+13A0-U+13FF */ /* Bit 77 Unified Canadian Aboriginal Syllabics */ # define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS (1L << 13) /* U+1400-U+167F */ /* Bit 78 Ogham */ # define TT_UCR_OGHAM (1L << 14) /* U+1680-U+169F */ /* Bit 79 Runic */ # define TT_UCR_RUNIC (1L << 15) /* U+16A0-U+16FF */ /* Bit 80 Khmer */ /* Khmer Symbols */ # define TT_UCR_KHMER (1L << 16) /* U+1780-U+17FF */ /* U+19E0-U+19FF */ /* Bit 81 Mongolian */ # define TT_UCR_MONGOLIAN (1L << 17) /* U+1800-U+18AF */ /* Bit 82 Braille Patterns */ # define TT_UCR_BRAILLE (1L << 18) /* U+2800-U+28FF */ /* Bit 83 Yi Syllables */ /* Yi Radicals */ # define TT_UCR_YI (1L << 19) /* U+A000-U+A48F */ /* U+A490-U+A4CF */ /* Bit 84 Tagalog */ /* Hanunoo */ /* Buhid */ /* Tagbanwa */ # define TT_UCR_PHILIPPINE (1L << 20) /* U+1700-U+171F */ /* U+1720-U+173F */ /* U+1740-U+175F */ /* U+1760-U+177F */ /* Bit 85 Old Italic */ # define TT_UCR_OLD_ITALIC (1L << 21) /*U+10300-U+1032F*/ /* Bit 86 Gothic */ # define TT_UCR_GOTHIC (1L << 22) /*U+10330-U+1034F*/ /* Bit 87 Deseret */ # define TT_UCR_DESERET (1L << 23) /*U+10400-U+1044F*/ /* Bit 88 Byzantine Musical Symbols */ /* Musical Symbols */ /* Ancient Greek Musical Notation */ # define TT_UCR_MUSICAL_SYMBOLS (1L << 24) /*U+1D000-U+1D0FF*/ /*U+1D100-U+1D1FF*/ /*U+1D200-U+1D24F*/ /* Bit 89 Mathematical Alphanumeric Symbols */ # define TT_UCR_MATH_ALPHANUMERIC_SYMBOLS (1L << 25) /*U+1D400-U+1D7FF*/ /* Bit 90 Private Use (plane 15) */ /* Private Use (plane 16) */ # define TT_UCR_PRIVATE_USE_SUPPLEMENTARY (1L << 26) /*U+F0000-U+FFFFD*/ /*U+100000-U+10FFFD*/ /* Bit 91 Variation Selectors */ /* Variation Selectors Supplement */ # define TT_UCR_VARIATION_SELECTORS (1L << 27) /* U+FE00-U+FE0F */ /*U+E0100-U+E01EF*/ /* Bit 92 Tags */ # define TT_UCR_TAGS (1L << 28) /*U+E0000-U+E007F*/ /* Bit 93 Limbu */ # define TT_UCR_LIMBU (1L << 29) /* U+1900-U+194F */ /* Bit 94 Tai Le */ # define TT_UCR_TAI_LE (1L << 30) /* U+1950-U+197F */ /* Bit 95 New Tai Lue */ # define TT_UCR_NEW_TAI_LUE (1L << 31) /* U+1980-U+19DF */ /* ulUnicodeRange4 */ /* --------------- */ /* Bit 96 Buginese */ # define TT_UCR_BUGINESE (1L << 0) /* U+1A00-U+1A1F */ /* Bit 97 Glagolitic */ # define TT_UCR_GLAGOLITIC (1L << 1) /* U+2C00-U+2C5F */ /* Bit 98 Tifinagh */ # define TT_UCR_TIFINAGH (1L << 2) /* U+2D30-U+2D7F */ /* Bit 99 Yijing Hexagram Symbols */ # define TT_UCR_YIJING (1L << 3) /* U+4DC0-U+4DFF */ /* Bit 100 Syloti Nagri */ # define TT_UCR_SYLOTI_NAGRI (1L << 4) /* U+A800-U+A82F */ /* Bit 101 Linear B Syllabary */ /* Linear B Ideograms */ /* Aegean Numbers */ # define TT_UCR_LINEAR_B (1L << 5) /*U+10000-U+1007F*/ /*U+10080-U+100FF*/ /*U+10100-U+1013F*/ /* Bit 102 Ancient Greek Numbers */ # define TT_UCR_ANCIENT_GREEK_NUMBERS (1L << 6) /*U+10140-U+1018F*/ /* Bit 103 Ugaritic */ # define TT_UCR_UGARITIC (1L << 7) /*U+10380-U+1039F*/ /* Bit 104 Old Persian */ # define TT_UCR_OLD_PERSIAN (1L << 8) /*U+103A0-U+103DF*/ /* Bit 105 Shavian */ # define TT_UCR_SHAVIAN (1L << 9) /*U+10450-U+1047F*/ /* Bit 106 Osmanya */ # define TT_UCR_OSMANYA (1L << 10) /*U+10480-U+104AF*/ /* Bit 107 Cypriot Syllabary */ # define TT_UCR_CYPRIOT_SYLLABARY (1L << 11) /*U+10800-U+1083F*/ /* Bit 108 Kharoshthi */ # define TT_UCR_KHAROSHTHI (1L << 12) /*U+10A00-U+10A5F*/ /* Bit 109 Tai Xuan Jing Symbols */ # define TT_UCR_TAI_XUAN_JING (1L << 13) /*U+1D300-U+1D35F*/ /* Bit 110 Cuneiform */ /* Cuneiform Numbers and Punctuation */ # define TT_UCR_CUNEIFORM (1L << 14) /*U+12000-U+123FF*/ /*U+12400-U+1247F*/ /* Bit 111 Counting Rod Numerals */ # define TT_UCR_COUNTING_ROD_NUMERALS (1L << 15) /*U+1D360-U+1D37F*/ /* Bit 112 Sundanese */ # define TT_UCR_SUNDANESE (1L << 16) /* U+1B80-U+1BBF */ /* Bit 113 Lepcha */ # define TT_UCR_LEPCHA (1L << 17) /* U+1C00-U+1C4F */ /* Bit 114 Ol Chiki */ # define TT_UCR_OL_CHIKI (1L << 18) /* U+1C50-U+1C7F */ /* Bit 115 Saurashtra */ # define TT_UCR_SAURASHTRA (1L << 19) /* U+A880-U+A8DF */ /* Bit 116 Kayah Li */ # define TT_UCR_KAYAH_LI (1L << 20) /* U+A900-U+A92F */ /* Bit 117 Rejang */ # define TT_UCR_REJANG (1L << 21) /* U+A930-U+A95F */ /* Bit 118 Cham */ # define TT_UCR_CHAM (1L << 22) /* U+AA00-U+AA5F */ /* Bit 119 Ancient Symbols */ # define TT_UCR_ANCIENT_SYMBOLS (1L << 23) /*U+10190-U+101CF*/ /* Bit 120 Phaistos Disc */ # define TT_UCR_PHAISTOS_DISC (1L << 24) /*U+101D0-U+101FF*/ /* Bit 121 Carian */ /* Lycian */ /* Lydian */ # define TT_UCR_OLD_ANATOLIAN (1L << 25) /*U+102A0-U+102DF*/ /*U+10280-U+1029F*/ /*U+10920-U+1093F*/ /* Bit 122 Domino Tiles */ /* Mahjong Tiles */ # define TT_UCR_GAME_TILES (1L << 26) /*U+1F030-U+1F09F*/ /*U+1F000-U+1F02F*/ /* Bit 123-127 Reserved for process-internal usage */ Possible bit mask values for the ulUnicodeRangeX fields in an SFNT \u2018OS/2\u2019 table.","title":"TT_UCR_XXX"},{"location":"ft2-tt_driver.html","text":"FreeType \u00bb Docs \u00bb Controlling FreeType Modules \u00bb The TrueType driver The TrueType driver \u00b6 Synopsis \u00b6 While FreeType's TrueType driver doesn't expose API functions by itself, it is possible to control its behaviour with FT_Property_Set and FT_Property_Get . The following lists the available properties together with the necessary macros and structures. The TrueType driver's module name is \u2018truetype\u2019. A single property interpreter-version is available, as documented in the \u2018 Driver properties \u2019 section. We start with a list of definitions, kindly provided by Greg Hitchcock. Bi-Level Rendering Monochromatic rendering, exclusively used in the early days of TrueType by both Apple and Microsoft. Microsoft's GDI interface supported hinting of the right-side bearing point, such that the advance width could be non-linear. Most often this was done to achieve some level of glyph symmetry. To enable reasonable performance (e.g., not having to run hinting on all glyphs just to get the widths) there was a bit in the head table indicating if the side bearing was hinted, and additional tables, \u2018hdmx\u2019 and \u2018LTSH\u2019, to cache hinting widths across multiple sizes and device aspect ratios. Font Smoothing Microsoft's GDI implementation of anti-aliasing. Not traditional anti-aliasing as the outlines were hinted before the sampling. The widths matched the bi-level rendering. ClearType Rendering Technique that uses physical subpixels to improve rendering on LCD (and other) displays. Because of the higher resolution, many methods of improving symmetry in glyphs through hinting the right-side bearing were no longer necessary. This lead to what GDI calls \u2018natural widths\u2019 ClearType, see http://rastertragedy.com/RTRCh4.htm#Sec21 . Since hinting has extra resolution, most non-linearity went away, but it is still possible for hints to change the advance widths in this mode. ClearType Compatible Widths One of the earliest challenges with ClearType was allowing the implementation in GDI to be selected without requiring all UI and documents to reflow. To address this, a compatible method of rendering ClearType was added where the font hints are executed once to determine the width in bi-level rendering, and then re-run in ClearType, with the difference in widths being absorbed in the font hints for ClearType (mostly in the white space of hints); see http://rastertragedy.com/RTRCh4.htm#Sec20 . Somewhat by definition, compatible width ClearType allows for non-linear widths, but only when the bi-level version has non-linear widths. ClearType Subpixel Positioning One of the nice benefits of ClearType is the ability to more crisply display fractional widths; unfortunately, the GDI model of integer bitmaps did not support this. However, the WPF and Direct Write frameworks do support fractional widths. DWrite calls this \u2018natural mode\u2019, not to be confused with GDI's \u2018natural widths\u2019. Subpixel positioning, in the current implementation of Direct Write, unfortunately does not support hinted advance widths, see http://rastertragedy.com/RTRCh4.htm#Sec22 . Note that the TrueType interpreter fully allows the advance width to be adjusted in this mode, just the DWrite client will ignore those changes. ClearType Backward Compatibility This is a set of exceptions made in the TrueType interpreter to minimize hinting techniques that were problematic with the extra resolution of ClearType; see http://rastertragedy.com/RTRCh4.htm#Sec1 and https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx . This technique is not to be confused with ClearType compatible widths. ClearType backward compatibility has no direct impact on changing advance widths, but there might be an indirect impact on disabling some deltas. This could be worked around in backward compatibility mode. Native ClearType Mode (Not to be confused with \u2018natural widths\u2019.) This mode removes all the exceptions in the TrueType interpreter when running with ClearType. Any issues on widths would still apply, though.","title":"The TrueType driver"},{"location":"ft2-tt_driver.html#the-truetype-driver","text":"","title":"The TrueType driver"},{"location":"ft2-tt_driver.html#synopsis","text":"While FreeType's TrueType driver doesn't expose API functions by itself, it is possible to control its behaviour with FT_Property_Set and FT_Property_Get . The following lists the available properties together with the necessary macros and structures. The TrueType driver's module name is \u2018truetype\u2019. A single property interpreter-version is available, as documented in the \u2018 Driver properties \u2019 section. We start with a list of definitions, kindly provided by Greg Hitchcock. Bi-Level Rendering Monochromatic rendering, exclusively used in the early days of TrueType by both Apple and Microsoft. Microsoft's GDI interface supported hinting of the right-side bearing point, such that the advance width could be non-linear. Most often this was done to achieve some level of glyph symmetry. To enable reasonable performance (e.g., not having to run hinting on all glyphs just to get the widths) there was a bit in the head table indicating if the side bearing was hinted, and additional tables, \u2018hdmx\u2019 and \u2018LTSH\u2019, to cache hinting widths across multiple sizes and device aspect ratios. Font Smoothing Microsoft's GDI implementation of anti-aliasing. Not traditional anti-aliasing as the outlines were hinted before the sampling. The widths matched the bi-level rendering. ClearType Rendering Technique that uses physical subpixels to improve rendering on LCD (and other) displays. Because of the higher resolution, many methods of improving symmetry in glyphs through hinting the right-side bearing were no longer necessary. This lead to what GDI calls \u2018natural widths\u2019 ClearType, see http://rastertragedy.com/RTRCh4.htm#Sec21 . Since hinting has extra resolution, most non-linearity went away, but it is still possible for hints to change the advance widths in this mode. ClearType Compatible Widths One of the earliest challenges with ClearType was allowing the implementation in GDI to be selected without requiring all UI and documents to reflow. To address this, a compatible method of rendering ClearType was added where the font hints are executed once to determine the width in bi-level rendering, and then re-run in ClearType, with the difference in widths being absorbed in the font hints for ClearType (mostly in the white space of hints); see http://rastertragedy.com/RTRCh4.htm#Sec20 . Somewhat by definition, compatible width ClearType allows for non-linear widths, but only when the bi-level version has non-linear widths. ClearType Subpixel Positioning One of the nice benefits of ClearType is the ability to more crisply display fractional widths; unfortunately, the GDI model of integer bitmaps did not support this. However, the WPF and Direct Write frameworks do support fractional widths. DWrite calls this \u2018natural mode\u2019, not to be confused with GDI's \u2018natural widths\u2019. Subpixel positioning, in the current implementation of Direct Write, unfortunately does not support hinted advance widths, see http://rastertragedy.com/RTRCh4.htm#Sec22 . Note that the TrueType interpreter fully allows the advance width to be adjusted in this mode, just the DWrite client will ignore those changes. ClearType Backward Compatibility This is a set of exceptions made in the TrueType interpreter to minimize hinting techniques that were problematic with the extra resolution of ClearType; see http://rastertragedy.com/RTRCh4.htm#Sec1 and https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx . This technique is not to be confused with ClearType compatible widths. ClearType backward compatibility has no direct impact on changing advance widths, but there might be an indirect impact on disabling some deltas. This could be worked around in backward compatibility mode. Native ClearType Mode (Not to be confused with \u2018natural widths\u2019.) This mode removes all the exceptions in the TrueType interpreter when running with ClearType. Any issues on widths would still apply, though.","title":"Synopsis"},{"location":"ft2-type1_tables.html","text":"FreeType \u00bb Docs \u00bb Format-Specific API \u00bb Type 1 Tables Type 1 Tables \u00b6 Synopsis \u00b6 This section contains the definition of Type 1-specific tables, including structures related to other PostScript font formats. PS_FontInfoRec \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct PS_FontInfoRec_ { FT_String * version; FT_String * notice; FT_String * full_name; FT_String * family_name; FT_String * weight; FT_Long italic_angle; FT_Bool is_fixed_pitch; FT_Short underline_position; FT_UShort underline_thickness; } PS_FontInfoRec ; A structure used to model a Type 1 or Type 2 FontInfo dictionary. Note that for Multiple Master fonts, each instance has its own FontInfo dictionary. PS_FontInfo \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct PS_FontInfoRec_* PS_FontInfo ; A handle to a PS_FontInfoRec structure. PS_PrivateRec \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct PS_PrivateRec_ { FT_Int unique_id; FT_Int lenIV; FT_Byte num_blue_values; FT_Byte num_other_blues; FT_Byte num_family_blues; FT_Byte num_family_other_blues; FT_Short blue_values[14]; FT_Short other_blues[10]; FT_Short family_blues [14]; FT_Short family_other_blues[10]; FT_Fixed blue_scale; FT_Int blue_shift; FT_Int blue_fuzz; FT_UShort standard_width[1]; FT_UShort standard_height[1]; FT_Byte num_snap_widths; FT_Byte num_snap_heights; FT_Bool force_bold; FT_Bool round_stem_up; FT_Short snap_widths [13]; /* including std width */ FT_Short snap_heights[13]; /* including std height */ FT_Fixed expansion_factor; FT_Long language_group; FT_Long password; FT_Short min_feature[2]; } PS_PrivateRec ; A structure used to model a Type 1 or Type 2 private dictionary. Note that for Multiple Master fonts, each instance has its own Private dictionary. PS_Private \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct PS_PrivateRec_* PS_Private ; A handle to a PS_PrivateRec structure. CID_FaceDictRec \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct CID_FaceDictRec_ { PS_PrivateRec private_dict; FT_UInt len_buildchar; FT_Fixed forcebold_threshold; FT_Pos stroke_width; FT_Fixed expansion_factor; /* this is a duplicate of */ /* `private_dict->expansion_factor' */ FT_Byte paint_type; FT_Byte font_type; FT_Matrix font_matrix; FT_Vector font_offset; FT_UInt num_subrs; FT_ULong subrmap_offset; FT_Int sd_bytes; } CID_FaceDictRec ; A structure used to represent data in a CID top-level dictionary. In most cases, they are part of the font's \u2018/FDArray\u2019 array. Within a CID font file, such (internal) subfont dictionaries are enclosed by \u2018%ADOBeginFontDict\u2019 and \u2018%ADOEndFontDict\u2019 comments. Note that CID_FaceDictRec misses a field for the \u2018/FontName\u2019 keyword, specifying the subfont's name (the top-level font name is given by the \u2018/CIDFontName\u2019 keyword). This is an oversight, but it doesn't limit the \u2018cid\u2019 font module's functionality because FreeType neither needs this entry nor gives access to CID subfonts. CID_FaceDict \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct CID_FaceDictRec_* CID_FaceDict ; A handle to a CID_FaceDictRec structure. CID_FaceInfoRec \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct CID_FaceInfoRec_ { FT_String * cid_font_name; FT_Fixed cid_version; FT_Int cid_font_type; FT_String * registry; FT_String * ordering; FT_Int supplement; PS_FontInfoRec font_info; FT_BBox font_bbox; FT_ULong uid_base; FT_Int num_xuid; FT_ULong xuid[16]; FT_ULong cidmap_offset; FT_Int fd_bytes; FT_Int gd_bytes; FT_ULong cid_count; FT_Int num_dicts; CID_FaceDict font_dicts; FT_ULong data_offset; } CID_FaceInfoRec ; A structure used to represent CID Face information. CID_FaceInfo \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct CID_FaceInfoRec_* CID_FaceInfo ; A handle to a CID_FaceInfoRec structure. FT_Has_PS_Glyph_Names \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). FT_EXPORT( FT_Int ) FT_Has_PS_Glyph_Names ( FT_Face face ); Return true if a given face provides reliable PostScript glyph names. This is similar to using the FT_HAS_GLYPH_NAMES macro, except that certain fonts (mostly TrueType) contain incorrect glyph name tables. When this function returns true, the caller is sure that the glyph names returned by FT_Get_Glyph_Name are reliable. input face face handle return Boolean. True if glyph names are reliable. FT_Get_PS_Font_Info \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). FT_EXPORT( FT_Error ) FT_Get_PS_Font_Info ( FT_Face face, PS_FontInfo afont_info ); Retrieve the PS_FontInfoRec structure corresponding to a given PostScript font. input face PostScript face handle. output afont_info Output font info structure pointer. return FreeType error code. 0 means success. note String pointers within the PS_FontInfoRec structure are owned by the face and don't need to be freed by the caller. Missing entries in the font's FontInfo dictionary are represented by NULL pointers. If the font's format is not PostScript-based, this function will return the FT_Err_Invalid_Argument error code. FT_Get_PS_Font_Private \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). FT_EXPORT( FT_Error ) FT_Get_PS_Font_Private ( FT_Face face, PS_Private afont_private ); Retrieve the PS_PrivateRec structure corresponding to a given PostScript font. input face PostScript face handle. output afont_private Output private dictionary structure pointer. return FreeType error code. 0 means success. note The string pointers within the PS_PrivateRec structure are owned by the face and don't need to be freed by the caller. If the font's format is not PostScript-based, this function returns the FT_Err_Invalid_Argument error code. FT_Get_PS_Font_Value \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). FT_EXPORT( FT_Long ) FT_Get_PS_Font_Value ( FT_Face face, PS_Dict_Keys key, FT_UInt idx, void *value, FT_Long value_len ); Retrieve the value for the supplied key from a PostScript font. input face PostScript face handle. key An enumeration value representing the dictionary key to retrieve. idx For array values, this specifies the index to be returned. value A pointer to memory into which to write the value. valen_len The size, in bytes, of the memory supplied for the value. output value The value matching the above key, if it exists. return The amount of memory (in bytes) required to hold the requested value (if it exists, -1 otherwise). note The values returned are not pointers into the internal structures of the face, but are \u2018fresh\u2019 copies, so that the memory containing them belongs to the calling application. This also enforces the \u2018read-only\u2019 nature of these values, i.e., this function cannot be used to manipulate the face. value is a void pointer because the values returned can be of various types. If either value is NULL or value_len is too small, just the required memory size for the requested entry is returned. The idx parameter is used, not only to retrieve elements of, for example, the FontMatrix or FontBBox, but also to retrieve name keys from the CharStrings dictionary, and the charstrings themselves. It is ignored for atomic values. PS_DICT_BLUE_SCALE returns a value that is scaled up by 1000. To get the value as in the font stream, you need to divide by 65536000.0 (to remove the FT_Fixed scale, and the x1000 scale). IMPORTANT: Only key/value pairs read by the FreeType interpreter can be retrieved. So, for example, PostScript procedures such as NP, ND, and RD are not available. Arbitrary keys are, obviously, not be available either. If the font's format is not PostScript-based, this function returns the FT_Err_Invalid_Argument error code. since 2.4.8 T1_Blend_Flags \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef enum T1_Blend_Flags_ { /* required fields in a FontInfo blend dictionary */ T1_BLEND_UNDERLINE_POSITION = 0, T1_BLEND_UNDERLINE_THICKNESS , T1_BLEND_ITALIC_ANGLE , /* required fields in a Private blend dictionary */ T1_BLEND_BLUE_VALUES , T1_BLEND_OTHER_BLUES , T1_BLEND_STANDARD_WIDTH , T1_BLEND_STANDARD_HEIGHT , T1_BLEND_STEM_SNAP_WIDTHS , T1_BLEND_STEM_SNAP_HEIGHTS , T1_BLEND_BLUE_SCALE , T1_BLEND_BLUE_SHIFT , T1_BLEND_FAMILY_BLUES , T1_BLEND_FAMILY_OTHER_BLUES , T1_BLEND_FORCE_BOLD , T1_BLEND_MAX /* do not remove */ } T1_Blend_Flags ; /* these constants are deprecated; use the corresponding */ /* ` T1_Blend_Flags ` values instead */ # define t1_blend_underline_position T1_BLEND_UNDERLINE_POSITION # define t1_blend_underline_thickness T1_BLEND_UNDERLINE_THICKNESS # define t1_blend_italic_angle T1_BLEND_ITALIC_ANGLE # define t1_blend_blue_values T1_BLEND_BLUE_VALUES # define t1_blend_other_blues T1_BLEND_OTHER_BLUES # define t1_blend_standard_widths T1_BLEND_STANDARD_WIDTH # define t1_blend_standard_height T1_BLEND_STANDARD_HEIGHT # define t1_blend_stem_snap_widths T1_BLEND_STEM_SNAP_WIDTHS # define t1_blend_stem_snap_heights T1_BLEND_STEM_SNAP_HEIGHTS # define t1_blend_blue_scale T1_BLEND_BLUE_SCALE # define t1_blend_blue_shift T1_BLEND_BLUE_SHIFT # define t1_blend_family_blues T1_BLEND_FAMILY_BLUES # define t1_blend_family_other_blues T1_BLEND_FAMILY_OTHER_BLUES # define t1_blend_force_bold T1_BLEND_FORCE_BOLD # define t1_blend_max T1_BLEND_MAX A set of flags used to indicate which fields are present in a given blend dictionary (font info or private). Used to support Multiple Masters fonts. values T1_BLEND_UNDERLINE_POSITION T1_BLEND_UNDERLINE_THICKNESS T1_BLEND_ITALIC_ANGLE T1_BLEND_BLUE_VALUES T1_BLEND_OTHER_BLUES T1_BLEND_STANDARD_WIDTH T1_BLEND_STANDARD_HEIGHT T1_BLEND_STEM_SNAP_WIDTHS T1_BLEND_STEM_SNAP_HEIGHTS T1_BLEND_BLUE_SCALE T1_BLEND_BLUE_SHIFT T1_BLEND_FAMILY_BLUES T1_BLEND_FAMILY_OTHER_BLUES T1_BLEND_FORCE_BOLD T1_EncodingType \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef enum T1_EncodingType_ { T1_ENCODING_TYPE_NONE = 0, T1_ENCODING_TYPE_ARRAY , T1_ENCODING_TYPE_STANDARD , T1_ENCODING_TYPE_ISOLATIN1 , T1_ENCODING_TYPE_EXPERT } T1_EncodingType ; An enumeration describing the \u2018Encoding\u2019 entry in a Type 1 dictionary. values T1_ENCODING_TYPE_NONE T1_ENCODING_TYPE_ARRAY T1_ENCODING_TYPE_STANDARD T1_ENCODING_TYPE_ISOLATIN1 T1_ENCODING_TYPE_EXPERT since 2.4.8 PS_Dict_Keys \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef enum PS_Dict_Keys_ { /* conventionally in the font dictionary */ PS_DICT_FONT_TYPE , /* FT_Byte */ PS_DICT_FONT_MATRIX , /* FT_Fixed */ PS_DICT_FONT_BBOX , /* FT_Fixed */ PS_DICT_PAINT_TYPE , /* FT_Byte */ PS_DICT_FONT_NAME , /* FT_String * */ PS_DICT_UNIQUE_ID , /* FT_Int */ PS_DICT_NUM_CHAR_STRINGS , /* FT_Int */ PS_DICT_CHAR_STRING_KEY , /* FT_String * */ PS_DICT_CHAR_STRING , /* FT_String * */ PS_DICT_ENCODING_TYPE , /* T1_EncodingType */ PS_DICT_ENCODING_ENTRY , /* FT_String * */ /* conventionally in the font Private dictionary */ PS_DICT_NUM_SUBRS , /* FT_Int */ PS_DICT_SUBR , /* FT_String * */ PS_DICT_STD_HW , /* FT_UShort */ PS_DICT_STD_VW , /* FT_UShort */ PS_DICT_NUM_BLUE_VALUES , /* FT_Byte */ PS_DICT_BLUE_VALUE , /* FT_Short */ PS_DICT_BLUE_FUZZ , /* FT_Int */ PS_DICT_NUM_OTHER_BLUES , /* FT_Byte */ PS_DICT_OTHER_BLUE , /* FT_Short */ PS_DICT_NUM_FAMILY_BLUES , /* FT_Byte */ PS_DICT_FAMILY_BLUE , /* FT_Short */ PS_DICT_NUM_FAMILY_OTHER_BLUES , /* FT_Byte */ PS_DICT_FAMILY_OTHER_BLUE , /* FT_Short */ PS_DICT_BLUE_SCALE , /* FT_Fixed */ PS_DICT_BLUE_SHIFT , /* FT_Int */ PS_DICT_NUM_STEM_SNAP_H , /* FT_Byte */ PS_DICT_STEM_SNAP_H , /* FT_Short */ PS_DICT_NUM_STEM_SNAP_V , /* FT_Byte */ PS_DICT_STEM_SNAP_V , /* FT_Short */ PS_DICT_FORCE_BOLD , /* FT_Bool */ PS_DICT_RND_STEM_UP , /* FT_Bool */ PS_DICT_MIN_FEATURE , /* FT_Short */ PS_DICT_LEN_IV , /* FT_Int */ PS_DICT_PASSWORD , /* FT_Long */ PS_DICT_LANGUAGE_GROUP , /* FT_Long */ /* conventionally in the font FontInfo dictionary */ PS_DICT_VERSION , /* FT_String * */ PS_DICT_NOTICE , /* FT_String * */ PS_DICT_FULL_NAME , /* FT_String * */ PS_DICT_FAMILY_NAME , /* FT_String * */ PS_DICT_WEIGHT , /* FT_String * */ PS_DICT_IS_FIXED_PITCH , /* FT_Bool */ PS_DICT_UNDERLINE_POSITION , /* FT_Short */ PS_DICT_UNDERLINE_THICKNESS , /* FT_UShort */ PS_DICT_FS_TYPE , /* FT_UShort */ PS_DICT_ITALIC_ANGLE , /* FT_Long */ PS_DICT_MAX = PS_DICT_ITALIC_ANGLE } PS_Dict_Keys ; An enumeration used in calls to FT_Get_PS_Font_Value to identify the Type 1 dictionary entry to retrieve. values PS_DICT_FONT_TYPE PS_DICT_FONT_MATRIX PS_DICT_FONT_BBOX PS_DICT_PAINT_TYPE PS_DICT_FONT_NAME PS_DICT_UNIQUE_ID PS_DICT_NUM_CHAR_STRINGS PS_DICT_CHAR_STRING_KEY PS_DICT_CHAR_STRING PS_DICT_ENCODING_TYPE PS_DICT_ENCODING_ENTRY PS_DICT_NUM_SUBRS PS_DICT_SUBR PS_DICT_STD_HW PS_DICT_STD_VW PS_DICT_NUM_BLUE_VALUES PS_DICT_BLUE_VALUE PS_DICT_BLUE_FUZZ PS_DICT_NUM_OTHER_BLUES PS_DICT_OTHER_BLUE PS_DICT_NUM_FAMILY_BLUES PS_DICT_FAMILY_BLUE PS_DICT_NUM_FAMILY_OTHER_BLUES PS_DICT_FAMILY_OTHER_BLUE PS_DICT_BLUE_SCALE PS_DICT_BLUE_SHIFT PS_DICT_NUM_STEM_SNAP_H PS_DICT_STEM_SNAP_H PS_DICT_NUM_STEM_SNAP_V PS_DICT_STEM_SNAP_V PS_DICT_FORCE_BOLD PS_DICT_RND_STEM_UP PS_DICT_MIN_FEATURE PS_DICT_LEN_IV PS_DICT_PASSWORD PS_DICT_LANGUAGE_GROUP PS_DICT_VERSION PS_DICT_NOTICE PS_DICT_FULL_NAME PS_DICT_FAMILY_NAME PS_DICT_WEIGHT PS_DICT_IS_FIXED_PITCH PS_DICT_UNDERLINE_POSITION PS_DICT_UNDERLINE_THICKNESS PS_DICT_FS_TYPE PS_DICT_ITALIC_ANGLE since 2.4.8 T1_FontInfo \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef PS_FontInfoRec T1_FontInfo ; This type is equivalent to PS_FontInfoRec . It is deprecated but kept to maintain source compatibility between various versions of FreeType. T1_Private \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef PS_PrivateRec T1_Private ; This type is equivalent to PS_PrivateRec . It is deprecated but kept to maintain source compatibility between various versions of FreeType. CID_FontDict \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef CID_FaceDictRec CID_FontDict ; This type is equivalent to CID_FaceDictRec . It is deprecated but kept to maintain source compatibility between various versions of FreeType. CID_Info \u00b6 Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef CID_FaceInfoRec CID_Info ; This type is equivalent to CID_FaceInfoRec . It is deprecated but kept to maintain source compatibility between various versions of FreeType.","title":"Type 1 Tables"},{"location":"ft2-type1_tables.html#type-1-tables","text":"","title":"Type 1 Tables"},{"location":"ft2-type1_tables.html#synopsis","text":"This section contains the definition of Type 1-specific tables, including structures related to other PostScript font formats.","title":"Synopsis"},{"location":"ft2-type1_tables.html#ps_fontinforec","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct PS_FontInfoRec_ { FT_String * version; FT_String * notice; FT_String * full_name; FT_String * family_name; FT_String * weight; FT_Long italic_angle; FT_Bool is_fixed_pitch; FT_Short underline_position; FT_UShort underline_thickness; } PS_FontInfoRec ; A structure used to model a Type 1 or Type 2 FontInfo dictionary. Note that for Multiple Master fonts, each instance has its own FontInfo dictionary.","title":"PS_FontInfoRec"},{"location":"ft2-type1_tables.html#ps_fontinfo","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct PS_FontInfoRec_* PS_FontInfo ; A handle to a PS_FontInfoRec structure.","title":"PS_FontInfo"},{"location":"ft2-type1_tables.html#ps_privaterec","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct PS_PrivateRec_ { FT_Int unique_id; FT_Int lenIV; FT_Byte num_blue_values; FT_Byte num_other_blues; FT_Byte num_family_blues; FT_Byte num_family_other_blues; FT_Short blue_values[14]; FT_Short other_blues[10]; FT_Short family_blues [14]; FT_Short family_other_blues[10]; FT_Fixed blue_scale; FT_Int blue_shift; FT_Int blue_fuzz; FT_UShort standard_width[1]; FT_UShort standard_height[1]; FT_Byte num_snap_widths; FT_Byte num_snap_heights; FT_Bool force_bold; FT_Bool round_stem_up; FT_Short snap_widths [13]; /* including std width */ FT_Short snap_heights[13]; /* including std height */ FT_Fixed expansion_factor; FT_Long language_group; FT_Long password; FT_Short min_feature[2]; } PS_PrivateRec ; A structure used to model a Type 1 or Type 2 private dictionary. Note that for Multiple Master fonts, each instance has its own Private dictionary.","title":"PS_PrivateRec"},{"location":"ft2-type1_tables.html#ps_private","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct PS_PrivateRec_* PS_Private ; A handle to a PS_PrivateRec structure.","title":"PS_Private"},{"location":"ft2-type1_tables.html#cid_facedictrec","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct CID_FaceDictRec_ { PS_PrivateRec private_dict; FT_UInt len_buildchar; FT_Fixed forcebold_threshold; FT_Pos stroke_width; FT_Fixed expansion_factor; /* this is a duplicate of */ /* `private_dict->expansion_factor' */ FT_Byte paint_type; FT_Byte font_type; FT_Matrix font_matrix; FT_Vector font_offset; FT_UInt num_subrs; FT_ULong subrmap_offset; FT_Int sd_bytes; } CID_FaceDictRec ; A structure used to represent data in a CID top-level dictionary. In most cases, they are part of the font's \u2018/FDArray\u2019 array. Within a CID font file, such (internal) subfont dictionaries are enclosed by \u2018%ADOBeginFontDict\u2019 and \u2018%ADOEndFontDict\u2019 comments. Note that CID_FaceDictRec misses a field for the \u2018/FontName\u2019 keyword, specifying the subfont's name (the top-level font name is given by the \u2018/CIDFontName\u2019 keyword). This is an oversight, but it doesn't limit the \u2018cid\u2019 font module's functionality because FreeType neither needs this entry nor gives access to CID subfonts.","title":"CID_FaceDictRec"},{"location":"ft2-type1_tables.html#cid_facedict","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct CID_FaceDictRec_* CID_FaceDict ; A handle to a CID_FaceDictRec structure.","title":"CID_FaceDict"},{"location":"ft2-type1_tables.html#cid_faceinforec","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct CID_FaceInfoRec_ { FT_String * cid_font_name; FT_Fixed cid_version; FT_Int cid_font_type; FT_String * registry; FT_String * ordering; FT_Int supplement; PS_FontInfoRec font_info; FT_BBox font_bbox; FT_ULong uid_base; FT_Int num_xuid; FT_ULong xuid[16]; FT_ULong cidmap_offset; FT_Int fd_bytes; FT_Int gd_bytes; FT_ULong cid_count; FT_Int num_dicts; CID_FaceDict font_dicts; FT_ULong data_offset; } CID_FaceInfoRec ; A structure used to represent CID Face information.","title":"CID_FaceInfoRec"},{"location":"ft2-type1_tables.html#cid_faceinfo","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef struct CID_FaceInfoRec_* CID_FaceInfo ; A handle to a CID_FaceInfoRec structure.","title":"CID_FaceInfo"},{"location":"ft2-type1_tables.html#ft_has_ps_glyph_names","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). FT_EXPORT( FT_Int ) FT_Has_PS_Glyph_Names ( FT_Face face ); Return true if a given face provides reliable PostScript glyph names. This is similar to using the FT_HAS_GLYPH_NAMES macro, except that certain fonts (mostly TrueType) contain incorrect glyph name tables. When this function returns true, the caller is sure that the glyph names returned by FT_Get_Glyph_Name are reliable.","title":"FT_Has_PS_Glyph_Names"},{"location":"ft2-type1_tables.html#ft_get_ps_font_info","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). FT_EXPORT( FT_Error ) FT_Get_PS_Font_Info ( FT_Face face, PS_FontInfo afont_info ); Retrieve the PS_FontInfoRec structure corresponding to a given PostScript font.","title":"FT_Get_PS_Font_Info"},{"location":"ft2-type1_tables.html#ft_get_ps_font_private","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). FT_EXPORT( FT_Error ) FT_Get_PS_Font_Private ( FT_Face face, PS_Private afont_private ); Retrieve the PS_PrivateRec structure corresponding to a given PostScript font.","title":"FT_Get_PS_Font_Private"},{"location":"ft2-type1_tables.html#ft_get_ps_font_value","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). FT_EXPORT( FT_Long ) FT_Get_PS_Font_Value ( FT_Face face, PS_Dict_Keys key, FT_UInt idx, void *value, FT_Long value_len ); Retrieve the value for the supplied key from a PostScript font.","title":"FT_Get_PS_Font_Value"},{"location":"ft2-type1_tables.html#t1_blend_flags","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef enum T1_Blend_Flags_ { /* required fields in a FontInfo blend dictionary */ T1_BLEND_UNDERLINE_POSITION = 0, T1_BLEND_UNDERLINE_THICKNESS , T1_BLEND_ITALIC_ANGLE , /* required fields in a Private blend dictionary */ T1_BLEND_BLUE_VALUES , T1_BLEND_OTHER_BLUES , T1_BLEND_STANDARD_WIDTH , T1_BLEND_STANDARD_HEIGHT , T1_BLEND_STEM_SNAP_WIDTHS , T1_BLEND_STEM_SNAP_HEIGHTS , T1_BLEND_BLUE_SCALE , T1_BLEND_BLUE_SHIFT , T1_BLEND_FAMILY_BLUES , T1_BLEND_FAMILY_OTHER_BLUES , T1_BLEND_FORCE_BOLD , T1_BLEND_MAX /* do not remove */ } T1_Blend_Flags ; /* these constants are deprecated; use the corresponding */ /* ` T1_Blend_Flags ` values instead */ # define t1_blend_underline_position T1_BLEND_UNDERLINE_POSITION # define t1_blend_underline_thickness T1_BLEND_UNDERLINE_THICKNESS # define t1_blend_italic_angle T1_BLEND_ITALIC_ANGLE # define t1_blend_blue_values T1_BLEND_BLUE_VALUES # define t1_blend_other_blues T1_BLEND_OTHER_BLUES # define t1_blend_standard_widths T1_BLEND_STANDARD_WIDTH # define t1_blend_standard_height T1_BLEND_STANDARD_HEIGHT # define t1_blend_stem_snap_widths T1_BLEND_STEM_SNAP_WIDTHS # define t1_blend_stem_snap_heights T1_BLEND_STEM_SNAP_HEIGHTS # define t1_blend_blue_scale T1_BLEND_BLUE_SCALE # define t1_blend_blue_shift T1_BLEND_BLUE_SHIFT # define t1_blend_family_blues T1_BLEND_FAMILY_BLUES # define t1_blend_family_other_blues T1_BLEND_FAMILY_OTHER_BLUES # define t1_blend_force_bold T1_BLEND_FORCE_BOLD # define t1_blend_max T1_BLEND_MAX A set of flags used to indicate which fields are present in a given blend dictionary (font info or private). Used to support Multiple Masters fonts.","title":"T1_Blend_Flags"},{"location":"ft2-type1_tables.html#t1_encodingtype","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef enum T1_EncodingType_ { T1_ENCODING_TYPE_NONE = 0, T1_ENCODING_TYPE_ARRAY , T1_ENCODING_TYPE_STANDARD , T1_ENCODING_TYPE_ISOLATIN1 , T1_ENCODING_TYPE_EXPERT } T1_EncodingType ; An enumeration describing the \u2018Encoding\u2019 entry in a Type 1 dictionary.","title":"T1_EncodingType"},{"location":"ft2-type1_tables.html#ps_dict_keys","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef enum PS_Dict_Keys_ { /* conventionally in the font dictionary */ PS_DICT_FONT_TYPE , /* FT_Byte */ PS_DICT_FONT_MATRIX , /* FT_Fixed */ PS_DICT_FONT_BBOX , /* FT_Fixed */ PS_DICT_PAINT_TYPE , /* FT_Byte */ PS_DICT_FONT_NAME , /* FT_String * */ PS_DICT_UNIQUE_ID , /* FT_Int */ PS_DICT_NUM_CHAR_STRINGS , /* FT_Int */ PS_DICT_CHAR_STRING_KEY , /* FT_String * */ PS_DICT_CHAR_STRING , /* FT_String * */ PS_DICT_ENCODING_TYPE , /* T1_EncodingType */ PS_DICT_ENCODING_ENTRY , /* FT_String * */ /* conventionally in the font Private dictionary */ PS_DICT_NUM_SUBRS , /* FT_Int */ PS_DICT_SUBR , /* FT_String * */ PS_DICT_STD_HW , /* FT_UShort */ PS_DICT_STD_VW , /* FT_UShort */ PS_DICT_NUM_BLUE_VALUES , /* FT_Byte */ PS_DICT_BLUE_VALUE , /* FT_Short */ PS_DICT_BLUE_FUZZ , /* FT_Int */ PS_DICT_NUM_OTHER_BLUES , /* FT_Byte */ PS_DICT_OTHER_BLUE , /* FT_Short */ PS_DICT_NUM_FAMILY_BLUES , /* FT_Byte */ PS_DICT_FAMILY_BLUE , /* FT_Short */ PS_DICT_NUM_FAMILY_OTHER_BLUES , /* FT_Byte */ PS_DICT_FAMILY_OTHER_BLUE , /* FT_Short */ PS_DICT_BLUE_SCALE , /* FT_Fixed */ PS_DICT_BLUE_SHIFT , /* FT_Int */ PS_DICT_NUM_STEM_SNAP_H , /* FT_Byte */ PS_DICT_STEM_SNAP_H , /* FT_Short */ PS_DICT_NUM_STEM_SNAP_V , /* FT_Byte */ PS_DICT_STEM_SNAP_V , /* FT_Short */ PS_DICT_FORCE_BOLD , /* FT_Bool */ PS_DICT_RND_STEM_UP , /* FT_Bool */ PS_DICT_MIN_FEATURE , /* FT_Short */ PS_DICT_LEN_IV , /* FT_Int */ PS_DICT_PASSWORD , /* FT_Long */ PS_DICT_LANGUAGE_GROUP , /* FT_Long */ /* conventionally in the font FontInfo dictionary */ PS_DICT_VERSION , /* FT_String * */ PS_DICT_NOTICE , /* FT_String * */ PS_DICT_FULL_NAME , /* FT_String * */ PS_DICT_FAMILY_NAME , /* FT_String * */ PS_DICT_WEIGHT , /* FT_String * */ PS_DICT_IS_FIXED_PITCH , /* FT_Bool */ PS_DICT_UNDERLINE_POSITION , /* FT_Short */ PS_DICT_UNDERLINE_THICKNESS , /* FT_UShort */ PS_DICT_FS_TYPE , /* FT_UShort */ PS_DICT_ITALIC_ANGLE , /* FT_Long */ PS_DICT_MAX = PS_DICT_ITALIC_ANGLE } PS_Dict_Keys ; An enumeration used in calls to FT_Get_PS_Font_Value to identify the Type 1 dictionary entry to retrieve.","title":"PS_Dict_Keys"},{"location":"ft2-type1_tables.html#t1_fontinfo","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef PS_FontInfoRec T1_FontInfo ; This type is equivalent to PS_FontInfoRec . It is deprecated but kept to maintain source compatibility between various versions of FreeType.","title":"T1_FontInfo"},{"location":"ft2-type1_tables.html#t1_private","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef PS_PrivateRec T1_Private ; This type is equivalent to PS_PrivateRec . It is deprecated but kept to maintain source compatibility between various versions of FreeType.","title":"T1_Private"},{"location":"ft2-type1_tables.html#cid_fontdict","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef CID_FaceDictRec CID_FontDict ; This type is equivalent to CID_FaceDictRec . It is deprecated but kept to maintain source compatibility between various versions of FreeType.","title":"CID_FontDict"},{"location":"ft2-type1_tables.html#cid_info","text":"Defined in FT_TYPE1_TABLES_H (freetype/t1tables.h). typedef CID_FaceInfoRec CID_Info ; This type is equivalent to CID_FaceInfoRec . It is deprecated but kept to maintain source compatibility between various versions of FreeType.","title":"CID_Info"},{"location":"ft2-user_allocation.html","text":"FreeType \u00bb Docs \u00bb General Remarks \u00bb User allocation User allocation \u00b6 Synopsis \u00b6 FreeType assumes that structures allocated by the user and passed as arguments are zeroed out except for the actual data. In other words, it is recommended to use calloc (or variants of it) instead of malloc for allocation.","title":"User allocation"},{"location":"ft2-user_allocation.html#user-allocation","text":"","title":"User allocation"},{"location":"ft2-user_allocation.html#synopsis","text":"FreeType assumes that structures allocated by the user and passed as arguments are zeroed out except for the actual data. In other words, it is recommended to use calloc (or variants of it) instead of malloc for allocation.","title":"Synopsis"},{"location":"ft2-version.html","text":"FreeType \u00bb Docs \u00bb Core API \u00bb FreeType Version FreeType Version \u00b6 Synopsis \u00b6 Note that those functions and macros are of limited use because even a new release of FreeType with only documentation changes increases the version number. FT_Library_Version \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( void ) FT_Library_Version ( FT_Library library, FT_Int *amajor, FT_Int *aminor, FT_Int *apatch ); Return the version of the FreeType library being used. This is useful when dynamically linking to the library, since one cannot use the macros FREETYPE_MAJOR , FREETYPE_MINOR , and FREETYPE_PATCH . input library A source library handle. output amajor The major version number. aminor The minor version number. apatch The patch version number. note The reason why this function takes a library argument is because certain programs implement library initialization in a custom way that doesn't use FT_Init_FreeType . In such cases, the library version might not be available before the library object has been created. FT_Face_CheckTrueTypePatents \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Bool ) FT_Face_CheckTrueTypePatents ( FT_Face face ); Deprecated, does nothing. input face A face handle. return Always returns false. note Since May 2010, TrueType hinting is no longer patented. since 2.3.5 FT_Face_SetUnpatentedHinting \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Bool ) FT_Face_SetUnpatentedHinting ( FT_Face face, FT_Bool value ); Deprecated, does nothing. input face A face handle. value New boolean setting. return Always returns false. note Since May 2010, TrueType hinting is no longer patented. since 2.3.5 FREETYPE_XXX \u00b6 Defined in FT_FREETYPE_H (freetype/freetype.h). # define FREETYPE_MAJOR 2 # define FREETYPE_MINOR 10 # define FREETYPE_PATCH 4 These three macros identify the FreeType source code version. Use FT_Library_Version to access them at runtime. values FREETYPE_MAJOR The major version number. FREETYPE_MINOR The minor version number. FREETYPE_PATCH The patch level. note The version number of FreeType if built as a dynamic link library with the \u2018libtool\u2019 package is not controlled by these three macros.","title":"FreeType Version"},{"location":"ft2-version.html#freetype-version","text":"","title":"FreeType Version"},{"location":"ft2-version.html#synopsis","text":"Note that those functions and macros are of limited use because even a new release of FreeType with only documentation changes increases the version number.","title":"Synopsis"},{"location":"ft2-version.html#ft_library_version","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( void ) FT_Library_Version ( FT_Library library, FT_Int *amajor, FT_Int *aminor, FT_Int *apatch ); Return the version of the FreeType library being used. This is useful when dynamically linking to the library, since one cannot use the macros FREETYPE_MAJOR , FREETYPE_MINOR , and FREETYPE_PATCH .","title":"FT_Library_Version"},{"location":"ft2-version.html#ft_face_checktruetypepatents","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Bool ) FT_Face_CheckTrueTypePatents ( FT_Face face ); Deprecated, does nothing.","title":"FT_Face_CheckTrueTypePatents"},{"location":"ft2-version.html#ft_face_setunpatentedhinting","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). FT_EXPORT( FT_Bool ) FT_Face_SetUnpatentedHinting ( FT_Face face, FT_Bool value ); Deprecated, does nothing.","title":"FT_Face_SetUnpatentedHinting"},{"location":"ft2-version.html#freetype_xxx","text":"Defined in FT_FREETYPE_H (freetype/freetype.h). # define FREETYPE_MAJOR 2 # define FREETYPE_MINOR 10 # define FREETYPE_PATCH 4 These three macros identify the FreeType source code version. Use FT_Library_Version to access them at runtime.","title":"FREETYPE_XXX"},{"location":"ft2-winfnt_fonts.html","text":"FreeType \u00bb Docs \u00bb Format-Specific API \u00bb Window FNT Files Window FNT Files \u00b6 Synopsis \u00b6 This section contains the declaration of Windows FNT-specific functions. FT_WinFNT_ID_XXX \u00b6 Defined in FT_WINFONTS_H (freetype/ftwinfnt.h). # define FT_WinFNT_ID_CP1252 0 # define FT_WinFNT_ID_DEFAULT 1 # define FT_WinFNT_ID_SYMBOL 2 # define FT_WinFNT_ID_MAC 77 # define FT_WinFNT_ID_CP932 128 # define FT_WinFNT_ID_CP949 129 # define FT_WinFNT_ID_CP1361 130 # define FT_WinFNT_ID_CP936 134 # define FT_WinFNT_ID_CP950 136 # define FT_WinFNT_ID_CP1253 161 # define FT_WinFNT_ID_CP1254 162 # define FT_WinFNT_ID_CP1258 163 # define FT_WinFNT_ID_CP1255 177 # define FT_WinFNT_ID_CP1256 178 # define FT_WinFNT_ID_CP1257 186 # define FT_WinFNT_ID_CP1251 204 # define FT_WinFNT_ID_CP874 222 # define FT_WinFNT_ID_CP1250 238 # define FT_WinFNT_ID_OEM 255 A list of valid values for the charset byte in FT_WinFNT_HeaderRec . Exact mapping tables for the various \u2018cpXXXX\u2019 encodings (except for \u2018cp1361\u2019) can be found at \u2018 ftp://ftp.unicode.org/Public/ \u2019 in the MAPPINGS/VENDORS/MICSFT/WINDOWS subdirectory. \u2018cp1361\u2019 is roughly a superset of MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT . values FT_WinFNT_ID_DEFAULT This is used for font enumeration and font creation as a \u2018don't care\u2019 value. Valid font files don't contain this value. When querying for information about the character set of the font that is currently selected into a specified device context, this return value (of the related Windows API) simply denotes failure. FT_WinFNT_ID_SYMBOL There is no known mapping table available. FT_WinFNT_ID_MAC Mac Roman encoding. FT_WinFNT_ID_OEM From Michael Poettgen : The \u2018Windows Font Mapping\u2019 article says that FT_WinFNT_ID_OEM is used for the charset of vector fonts, like modern.fon , roman.fon , and script.fon on Windows. The \u2018CreateFont\u2019 documentation says: The FT_WinFNT_ID_OEM value specifies a character set that is operating-system dependent. The \u2018IFIMETRICS\u2019 documentation from the \u2018Windows Driver Development Kit\u2019 says: This font supports an OEM-specific character set. The OEM character set is system dependent. In general OEM, as opposed to ANSI (i.e., \u2018cp1252\u2019), denotes the second default codepage that most international versions of Windows have. It is one of the OEM codepages from https://docs.microsoft.com/en-us/windows/desktop/intl/code-page-identifiers , and is used for the \u2018DOS boxes\u2019, to support legacy applications. A German Windows version for example usually uses ANSI codepage 1252 and OEM codepage 850. FT_WinFNT_ID_CP874 A superset of Thai TIS 620 and ISO 8859-11. FT_WinFNT_ID_CP932 A superset of Japanese Shift-JIS (with minor deviations). FT_WinFNT_ID_CP936 A superset of simplified Chinese GB 2312-1980 (with different ordering and minor deviations). FT_WinFNT_ID_CP949 A superset of Korean Hangul KS C 5601-1987 (with different ordering and minor deviations). FT_WinFNT_ID_CP950 A superset of traditional Chinese Big 5 ETen (with different ordering and minor deviations). FT_WinFNT_ID_CP1250 A superset of East European ISO 8859-2 (with slightly different ordering). FT_WinFNT_ID_CP1251 A superset of Russian ISO 8859-5 (with different ordering). FT_WinFNT_ID_CP1252 ANSI encoding. A superset of ISO 8859-1. FT_WinFNT_ID_CP1253 A superset of Greek ISO 8859-7 (with minor modifications). FT_WinFNT_ID_CP1254 A superset of Turkish ISO 8859-9. FT_WinFNT_ID_CP1255 A superset of Hebrew ISO 8859-8 (with some modifications). FT_WinFNT_ID_CP1256 A superset of Arabic ISO 8859-6 (with different ordering). FT_WinFNT_ID_CP1257 A superset of Baltic ISO 8859-13 (with some deviations). FT_WinFNT_ID_CP1258 For Vietnamese. This encoding doesn't cover all necessary characters. FT_WinFNT_ID_CP1361 Korean (Johab). FT_WinFNT_HeaderRec \u00b6 Defined in FT_WINFONTS_H (freetype/ftwinfnt.h). typedef struct FT_WinFNT_HeaderRec_ { FT_UShort version; FT_ULong file_size; FT_Byte copyright[60]; FT_UShort file_type; FT_UShort nominal_point_size; FT_UShort vertical_resolution; FT_UShort horizontal_resolution; FT_UShort ascent; FT_UShort internal_leading; FT_UShort external_leading; FT_Byte italic; FT_Byte underline; FT_Byte strike_out; FT_UShort weight; FT_Byte charset; FT_UShort pixel_width; FT_UShort pixel_height; FT_Byte pitch_and_family; FT_UShort avg_width; FT_UShort max_width; FT_Byte first_char; FT_Byte last_char; FT_Byte default_char; FT_Byte break_char; FT_UShort bytes_per_row; FT_ULong device_offset; FT_ULong face_name_offset; FT_ULong bits_pointer; FT_ULong bits_offset; FT_Byte reserved; FT_ULong flags; FT_UShort A_space; FT_UShort B_space; FT_UShort C_space; FT_UShort color_table_offset; FT_ULong reserved1[4]; } FT_WinFNT_HeaderRec ; Windows FNT Header info. FT_WinFNT_Header \u00b6 Defined in FT_WINFONTS_H (freetype/ftwinfnt.h). typedef struct FT_WinFNT_HeaderRec_* FT_WinFNT_Header ; A handle to an FT_WinFNT_HeaderRec structure. FT_Get_WinFNT_Header \u00b6 Defined in FT_WINFONTS_H (freetype/ftwinfnt.h). FT_EXPORT( FT_Error ) FT_Get_WinFNT_Header ( FT_Face face, FT_WinFNT_HeaderRec *aheader ); Retrieve a Windows FNT font info header. input face A handle to the input face. output aheader The WinFNT header. return FreeType error code. 0 means success. note This function only works with Windows FNT faces, returning an error otherwise.","title":"Window FNT Files"},{"location":"ft2-winfnt_fonts.html#window-fnt-files","text":"","title":"Window FNT Files"},{"location":"ft2-winfnt_fonts.html#synopsis","text":"This section contains the declaration of Windows FNT-specific functions.","title":"Synopsis"},{"location":"ft2-winfnt_fonts.html#ft_winfnt_id_xxx","text":"Defined in FT_WINFONTS_H (freetype/ftwinfnt.h). # define FT_WinFNT_ID_CP1252 0 # define FT_WinFNT_ID_DEFAULT 1 # define FT_WinFNT_ID_SYMBOL 2 # define FT_WinFNT_ID_MAC 77 # define FT_WinFNT_ID_CP932 128 # define FT_WinFNT_ID_CP949 129 # define FT_WinFNT_ID_CP1361 130 # define FT_WinFNT_ID_CP936 134 # define FT_WinFNT_ID_CP950 136 # define FT_WinFNT_ID_CP1253 161 # define FT_WinFNT_ID_CP1254 162 # define FT_WinFNT_ID_CP1258 163 # define FT_WinFNT_ID_CP1255 177 # define FT_WinFNT_ID_CP1256 178 # define FT_WinFNT_ID_CP1257 186 # define FT_WinFNT_ID_CP1251 204 # define FT_WinFNT_ID_CP874 222 # define FT_WinFNT_ID_CP1250 238 # define FT_WinFNT_ID_OEM 255 A list of valid values for the charset byte in FT_WinFNT_HeaderRec . Exact mapping tables for the various \u2018cpXXXX\u2019 encodings (except for \u2018cp1361\u2019) can be found at \u2018 ftp://ftp.unicode.org/Public/ \u2019 in the MAPPINGS/VENDORS/MICSFT/WINDOWS subdirectory. \u2018cp1361\u2019 is roughly a superset of MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT .","title":"FT_WinFNT_ID_XXX"},{"location":"ft2-winfnt_fonts.html#ft_winfnt_headerrec","text":"Defined in FT_WINFONTS_H (freetype/ftwinfnt.h). typedef struct FT_WinFNT_HeaderRec_ { FT_UShort version; FT_ULong file_size; FT_Byte copyright[60]; FT_UShort file_type; FT_UShort nominal_point_size; FT_UShort vertical_resolution; FT_UShort horizontal_resolution; FT_UShort ascent; FT_UShort internal_leading; FT_UShort external_leading; FT_Byte italic; FT_Byte underline; FT_Byte strike_out; FT_UShort weight; FT_Byte charset; FT_UShort pixel_width; FT_UShort pixel_height; FT_Byte pitch_and_family; FT_UShort avg_width; FT_UShort max_width; FT_Byte first_char; FT_Byte last_char; FT_Byte default_char; FT_Byte break_char; FT_UShort bytes_per_row; FT_ULong device_offset; FT_ULong face_name_offset; FT_ULong bits_pointer; FT_ULong bits_offset; FT_Byte reserved; FT_ULong flags; FT_UShort A_space; FT_UShort B_space; FT_UShort C_space; FT_UShort color_table_offset; FT_ULong reserved1[4]; } FT_WinFNT_HeaderRec ; Windows FNT Header info.","title":"FT_WinFNT_HeaderRec"},{"location":"ft2-winfnt_fonts.html#ft_winfnt_header","text":"Defined in FT_WINFONTS_H (freetype/ftwinfnt.h). typedef struct FT_WinFNT_HeaderRec_* FT_WinFNT_Header ; A handle to an FT_WinFNT_HeaderRec structure.","title":"FT_WinFNT_Header"},{"location":"ft2-winfnt_fonts.html#ft_get_winfnt_header","text":"Defined in FT_WINFONTS_H (freetype/ftwinfnt.h). FT_EXPORT( FT_Error ) FT_Get_WinFNT_Header ( FT_Face face, FT_WinFNT_HeaderRec *aheader ); Retrieve a Windows FNT font info header.","title":"FT_Get_WinFNT_Header"}]} \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/sitemap.xml b/lib/libesp32_lvgl/freetype/docs/reference/sitemap.xml deleted file mode 100644 index 11fea0b54..000000000 --- a/lib/libesp32_lvgl/freetype/docs/reference/sitemap.xml +++ /dev/null @@ -1,207 +0,0 @@ - - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - None - 2020-10-20 - daily - - \ No newline at end of file diff --git a/lib/libesp32_lvgl/freetype/docs/reference/sitemap.xml.gz b/lib/libesp32_lvgl/freetype/docs/reference/sitemap.xml.gz deleted file mode 100644 index 8e781570ed967749c456973cae96b28c1e6f2959..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 219 zcmb2|=HLh{>WgRkUz}NznwwalSCN~;@b;`DUz33V>jm583U@Dyg=Kl&+*z`eU12E` z=aw5Q7i|~kQM-5WzVB`O`cENWW!k?aGJm}{Rp z_)Oolcv7jMAG_kS%4b*Ht*;3e%11dai?&nQ7T~cjz3T2&&s}n+6^s4vMXFxAZoWpd zZ{NjMos?;(*GxEFae7code { - font-family: monospace; - background-color: #D6E8FF; - padding: 2ex 0 2ex 1%; - overflow-x:auto; -} -span.keyword { - font-family: monospace; - text-align: left; - white-space: pre; - color: #d73a49; -} -.md-typeset pre>code { - white-space: pre; -} -/* H4 Heading */ -h4 { - background-color: #EEEEFF; - font-size: medium; - font-style: oblique; - font-weight: bold; - padding: 0.3em 0 0.3em 1%; -} - -/* Fields table */ -table.fields { - width: 90%; - margin: 1.5ex 0 1.5ex 10%; -} -table.fields td.val { - font-weight: bold; - text-align: right; - width: 30%; - vertical-align: baseline; - padding: 1em 1em 0 0; -} -table.fields td.desc { - vertical-align: baseline; - padding: 1ex 0 0 1em; -} -table.fields td.desc p:first-child { - margin: 0; -} - -table.fields td.desc p { - margin: 1.5ex 0 0 0; -} - -/* Define 'long' tables */ -table.long { - display: block; - width: 93%; -} -table.long thead, -table.long tbody, -table.long th, -table.long td, -table.long tr { - display: block; -} -/* Hide table headers (but not display: none; -, for accessibility) */ -table.long thead tr { - position: absolute; - top: -9999px; - left: -9999px; -} -table.long tr { - border: 0; -} -table.long { - margin: 1.5ex 3% 1.5ex 3%; -} -table.long td.val { - text-align: left; -} -table.long td { - /* Behave like a "row" */ - border: none; - border-bottom: 0; - position: relative; - padding-left: 50%; -} -table.long td:before { - /* Now like a table header */ - position: absolute; - /* Top/left values mimic padding */ - top: 6px; - left: 6px; - width: 45%; - padding-right: 10px; - white-space: nowrap; -} -/* End 'long' table definition */ - -/* toc table */ -table.toc { - width: 95%; - margin: 1.5ex 0 1.5ex 5%; -} -table.toc td.link { - width: 30%; - text-align: right; - vertical-align: baseline; - padding: 1ex 1em 1ex 0; -} -table.toc td.desc { - vertical-align: baseline; - padding: 1ex 0 1ex 1em; - text-align: left; -} -table.toc td.desc p:first-child { - margin: 0; - text-align: left; -} -table.toc td.desc p { - margin: 1.5ex 0 0 0; - text-align: left; -} -div.timestamp { - font-size: small; -} - -/* Change table layout for smaller screens. This query will take effect for any screen smaller than - 760px and also iPads specifically. */ -@media only screen and (max-width: 760px), (min-device-width: 768px) and (max-device-width: 1024px) { - /* Force table to not be like tables anymore */ - table, thead, tbody, th, td, tr { - display: block; - } - /* Hide table headers (but not display: none; - , for accessibility) */ - thead tr { - position: absolute; - top: -9999px; - left: -9999px; - } - tr { - border: 0; - } - table.fields { - width: 93%; - margin: 1.5ex 3% 1.5ex 3%; - } - table.fields td.val { - text-align: left; - } - td { - /* Behave like a "row" */ - border: none; - border-bottom: 0; - position: relative; - padding-left: 50%; - } - td:before { - /* Now like a table header */ - position: absolute; - /* Top/left values mimic padding */ - top: 6px; - left: 6px; - width: 45%; - padding-right: 10px; - white-space: nowrap; - } -} diff --git a/lib/libesp32_lvgl/freetype/docs/release b/lib/libesp32_lvgl/freetype/docs/release deleted file mode 100644 index 628dded2c..000000000 --- a/lib/libesp32_lvgl/freetype/docs/release +++ /dev/null @@ -1,202 +0,0 @@ -How to prepare a new release ----------------------------- - -. include/freetype/freetype.h: Update FREETYPE_MAJOR, FREETYPE_MINOR, - and FREETYPE_PATCH. - -. Update version numbers in all files where necessary (for example, do - a grep for both `2.3.1' and `231' for release 2.3.1). - -. builds/unix/configure.raw: Update `version_info'. - -. docs/CHANGES: Document differences to last release. - -. README: Update. - -. docs/VERSIONS.TXT: Document changed `version_info'. - -. ChangeLog: Announce new release (both in the freetype2 and - freetype2-demos modules). - -. Clone the git archive to another directory with - - git clone -l -s . ../freetype2.test - - or something like this and run - - make distclean; make devel; make - make distclean; make devel; make multi - make distclean; make devel CC=g++; make CC=g++ - make distclean; make devel CC=g++; make multi CC=g++ - - sh autogen.sh - make distclean; ./configure; make - make distclean; ./configure CC=g++; make - - in the cloned repository to test compilation with both gcc and g++. - -. Test C++ compilation for freetype2-demos too (using `git clone' as - above). - -. Run src/tools/chktrcmp.py and check that there are no undefined - trace_XXXX macros. - -. After pushing the new release, tag the git repositories (freetype2, - freetype2-demos) with - - git tag VER- -m "" -u - - and push the tags with - - git push --tags - -. Check with - - git clean -ndx - - that the git directory is really clean (and remove extraneous files - if necessary). - -. Say `make dist' in both the freetype2 and freetype2-demos modules - to generate the .tar.gz, .tar.xz, and .zip files. - -. Create the doc bundles (freetype-doc-.tar.gz, - freetype-doc-.tar.xz, ftdoc.zip). This is - everything in - - /freetype2/docs - - except the `reference' subdirectory. Do *not* use option `-l' from - zip! - -. Run the following script (with updated `$VERSION', `$SAVANNAH_USER', - and $SOURCEFORGE_USER variables) to sign and upload the bundles to - both Savannah and SourceForge. The signing code has been taken from - the `gnupload' script (part of the automake bundle). - - #!/bin/sh - - VERSION=2.5.1 - SAVANNAH_USER=wl - SOURCEFORGE_USER=wlemb - - ##################################################################### - - GPG='/usr/bin/gpg --batch --no-tty' - - version=`echo $VERSION | sed "s/\\.//g"` - - FREETYPE_PACKAGES="freetype-$VERSION.tar.gz \ - freetype-$VERSION.tar.xz \ - ft$version.zip" - FT2DEMOS_PACKAGES="ft2demos-$VERSION.tar.gz \ - ft2demos-$VERSION.tar.xz \ - ftdmo$version.zip" - FTDOC_PACKAGES="freetype-doc-$VERSION.tar.gz \ - freetype-doc-$VERSION.tar.xz \ - ftdoc$version.zip" - - PACKAGE_LIST="$FREETYPE_PACKAGES \ - $FT2DEMOS_PACKAGES \ - $FTDOC_PACKAGES" - - set -e - unset passphrase - - PATH=/empty echo -n "Enter GPG passphrase: " - stty -echo - read -r passphrase - stty echo - echo - - for f in $PACKAGE_LIST; do - if test ! -f $f; then - echo "$0: Cannot find \`$f'" 1>&2 - exit 1 - else - : - fi - done - - for f in $PACKAGE_LIST; do - echo "Signing $f..." - rm -f $f.sig - echo $passphrase | $GPG --passphrase-fd 0 -ba -o $f.sig $f - done - - FREETYPE_SIGNATURES= - for i in $FREETYPE_PACKAGES; do - FREETYPE_SIGNATURES="$FREETYPE_SIGNATURES $i.sig" - done - - FT2DEMOS_SIGNATURES= - for i in $FT2DEMOS_PACKAGES; do - FT2DEMOS_SIGNATURES="$FT2DEMOS_SIGNATURES $i.sig" - done - - FTDOC_SIGNATURES= - for i in $FTDOC_PACKAGES; do - FTDOC_SIGNATURES="$FTDOC_SIGNATURES $i.sig" - done - - SIGNATURE_LIST="$FREETYPE_SIGNATURES \ - $FT2DEMOS_SIGNATURES \ - $FTDOC_SIGNATURES" - - scp $PACKAGE_LIST $SIGNATURE_LIST \ - $SAVANNAH_USER@dl.sv.nongnu.org:/releases/freetype/ - - rsync -avP -e ssh $FREETYPE_PACKAGES $FREETYPE_SIGNATURES \ - $SOURCEFORGE_USER,freetype@frs.sf.net:/home/frs/project/f/fr/freetype/freetype2/$VERSION/ - rsync -avP -e ssh $FT2DEMOS_PACKAGES $FT2DEMOS_SIGNATURES \ - $SOURCEFORGE_USER,freetype@frs.sf.net:/home/frs/project/f/fr/freetype/freetype-demos/$VERSION/ - rsync -avP -e ssh $FTDOC_PACKAGES $FTDOC_SIGNATURES \ - $SOURCEFORGE_USER,freetype@frs.sf.net:/home/frs/project/f/fr/freetype/freetype-docs/$VERSION/ - - # EOF - -. Prepare a README for SourceForge and upload it with the following - script (with updated `$VERSION' and $SOURCEFORGE_USER variables). - - #!/bin/sh - - VERSION=2.5.1 - SOURCEFORGE_USER=wlemb - - ##################################################################### - - rsync -avP -e ssh README \ - $SOURCEFORGE_USER,freetype@frs.sf.net:/home/frs/project/f/fr/freetype/freetype2/$VERSION/ - - # EOF - -. On SourceForge, tag the just uploaded `ftXXX.zip' and - `freetype-XXX.tar.xz' files as the default files to download for - `Windows' and `Others', respectively. - -. Copy the reference files (generated by `make dist') to - - /freetype2/docs/reference - -. Update the `freetype-web' repository. `git push' then automatically - triggers an update of the public web pages within ten minutes, due - to a cron script (on wl@freedesktop.org) that rsyncs with - - freedesktop.org://srv/freetype.freedesktop.org/www - -. Announce new release on freetype-announce@nongnu.org and to relevant - newsgroups. - ----------------------------------------------------------------------- - -Copyright (C) 2003-2020 by -David Turner, Robert Wilhelm, and Werner Lemberg. - -This file is part of the FreeType project, and may only be used, -modified, and distributed under the terms of the FreeType project -license, LICENSE.TXT. By continuing to use, modify, or distribute -this file you indicate that you have read the license and understand -and accept it fully. - - ---- end of release --- diff --git a/lib/libesp32_lvgl/freetype/include/dlg/dlg.h b/lib/libesp32_lvgl/freetype/include/dlg/dlg.h new file mode 100644 index 000000000..fa10730e8 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/include/dlg/dlg.h @@ -0,0 +1,290 @@ +// Copyright (c) 2019 nyorain +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt + +#ifndef INC_DLG_DLG_H_ +#define INC_DLG_DLG_H_ + +#include +#include +#include +#include +#include + +// Hosted at https://github.com/nyorain/dlg. +// There are examples and documentation. +// Issue reports and contributions appreciated. + +// - CONFIG - +// Define this macro to make all dlg macros have no effect at all +// #define DLG_DISABLE + +// the log/assertion levels below which logs/assertions are ignored +// defaulted depending on the NDEBUG macro +#ifndef DLG_LOG_LEVEL + #ifdef NDEBUG + #define DLG_LOG_LEVEL dlg_level_warn + #else + #define DLG_LOG_LEVEL dlg_level_trace + #endif +#endif + +#ifndef DLG_ASSERT_LEVEL + #ifdef NDEBUG + #define DLG_ASSERT_LEVEL dlg_level_warn + #else + #define DLG_ASSERT_LEVEL dlg_level_trace + #endif +#endif + +// the assert level of dlg_assert +#ifndef DLG_DEFAULT_ASSERT + #define DLG_DEFAULT_ASSERT dlg_level_error +#endif + +// evaluated to the 'file' member in dlg_origin +#ifndef DLG_FILE + #define DLG_FILE dlg__strip_root_path(__FILE__, DLG_BASE_PATH) + + // the base path stripped from __FILE__. If you don't override DLG_FILE set this to + // the project root to make 'main.c' from '/some/bullshit/main.c' + #ifndef DLG_BASE_PATH + #define DLG_BASE_PATH "" + #endif +#endif + +// Default tags applied to all logs/assertions (in the defining file). +// Must be in format ```#define DLG_DEFAULT_TAGS "tag1", "tag2"``` +// or just nothing (as defaulted here) +#ifndef DLG_DEFAULT_TAGS + #define DLG_DEFAULT_TAGS_TERM NULL +#else + #define DLG_DEFAULT_TAGS_TERM DLG_DEFAULT_TAGS, NULL +#endif + +// The function used for formatting. Can have any signature, but must be callable with +// the arguments the log/assertions macros are called with. Must return a const char* +// that will not be freed by dlg, the formatting function must keep track of it. +// The formatting function might use dlg_thread_buffer or a custom owned buffer. +// The returned const char* has to be valid until the dlg log/assertion ends. +// Usually a c function with ... (i.e. using va_list) or a variadic c++ template do +// allow formatting. +#ifndef DLG_FMT_FUNC + #define DLG_FMT_FUNC dlg__printf_format +#endif + +// Only overwrite (i.e. predefine) this if you know what you are doing. +// On windows this is used to add the dllimport specified. +// If you are using the static version of dlg (on windows) define +// DLG_STATIC before including dlg.h +#ifndef DLG_API + #if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(DLG_STATIC) + #define DLG_API __declspec(dllimport) + #else + #define DLG_API + #endif +#endif + +// This macro is used when an assertion fails. It gets the source expression +// and can return an alternative (that must stay alive). +// Mainly useful to execute something on failed assertion. +#ifndef DLG_FAILED_ASSERTION_TEXT + #define DLG_FAILED_ASSERTION_TEXT(x) x +#endif + +// - utility - +// two methods needed since cplusplus does not support compound literals +// and c does not support uniform initialization/initializer lists +#ifdef __cplusplus + #include + #define DLG_CREATE_TAGS(...) std::initializer_list \ + {DLG_DEFAULT_TAGS_TERM, __VA_ARGS__, NULL}.begin() +#else + #define DLG_CREATE_TAGS(...) (const char* const[]) {DLG_DEFAULT_TAGS_TERM, __VA_ARGS__, NULL} +#endif + +#ifdef __GNUC__ + #define DLG_PRINTF_ATTRIB(a, b) __attribute__ ((format (printf, a, b))) +#else + #define DLG_PRINTF_ATTRIB(a, b) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +// Represents the importance of a log/assertion call. +enum dlg_level { + dlg_level_trace = 0, // temporary used debug, e.g. to check if control reaches function + dlg_level_debug, // general debugging, prints e.g. all major events + dlg_level_info, // general useful information + dlg_level_warn, // warning, something went wrong but might have no (really bad) side effect + dlg_level_error, // something really went wrong; expect serious issues + dlg_level_fatal // critical error; application is likely to crash/exit +}; + +// Holds various information associated with a log/assertion call. +// Forwarded to the output handler. +struct dlg_origin { + const char* file; + unsigned int line; + const char* func; + enum dlg_level level; + const char** tags; // null-terminated + const char* expr; // assertion expression, otherwise null +}; + +// Type of the output handler, see dlg_set_handler. +typedef void(*dlg_handler)(const struct dlg_origin* origin, const char* string, void* data); + +#ifndef DLG_DISABLE + // Tagged/Untagged logging with variable level + // Tags must always be in the format `("tag1", "tag2")` (including brackets) + // Example usages: + // dlg_log(dlg_level_warning, "test 1") + // dlg_logt(("tag1, "tag2"), dlg_level_debug, "test %d", 2) + #define dlg_log(level, ...) if(level >= DLG_LOG_LEVEL) \ + dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__, \ + DLG_FMT_FUNC(__VA_ARGS__), NULL) + #define dlg_logt(level, tags, ...) if(level >= DLG_LOG_LEVEL) \ + dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__, __func__, \ + DLG_FMT_FUNC(__VA_ARGS__), NULL) + + // Dynamic level assert macros in various versions for additional arguments + // Example usages: + // dlg_assertl(dlg_level_warning, data != nullptr); + // dlg_assertlt(("tag1, "tag2"), dlg_level_trace, data != nullptr); + // dlg_asserttlm(("tag1), dlg_level_warning, data != nullptr, "Data must not be null"); + // dlg_assertlm(dlg_level_error, data != nullptr, "Data must not be null"); + #define dlg_assertl(level, expr) if(level >= DLG_ASSERT_LEVEL && !(expr)) \ + dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__, NULL, \ + DLG_FAILED_ASSERTION_TEXT(#expr)) + #define dlg_assertlt(level, tags, expr) if(level >= DLG_ASSERT_LEVEL && !(expr)) \ + dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__, __func__, NULL, \ + DLG_FAILED_ASSERTION_TEXT(#expr)) + #define dlg_assertlm(level, expr, ...) if(level >= DLG_ASSERT_LEVEL && !(expr)) \ + dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__, \ + DLG_FMT_FUNC(__VA_ARGS__), DLG_FAILED_ASSERTION_TEXT(#expr)) + #define dlg_assertltm(level, tags, expr, ...) if(level >= DLG_ASSERT_LEVEL && !(expr)) \ + dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__, \ + __func__, DLG_FMT_FUNC(__VA_ARGS__), DLG_FAILED_ASSERTION_TEXT(#expr)) + + #define dlg__assert_or(level, tags, expr, code, msg) if(!(expr)) {\ + if(level >= DLG_ASSERT_LEVEL) \ + dlg__do_log(level, tags, DLG_FILE, __LINE__, __func__, msg, \ + DLG_FAILED_ASSERTION_TEXT(#expr)); \ + code; \ + } (void) NULL + + // - Private interface: not part of the abi/api but needed in macros - + // Formats the given format string and arguments as printf would, uses the thread buffer. + DLG_API const char* dlg__printf_format(const char* format, ...) DLG_PRINTF_ATTRIB(1, 2); + DLG_API void dlg__do_log(enum dlg_level lvl, const char* const*, const char*, int, + const char*, const char*, const char*); + DLG_API const char* dlg__strip_root_path(const char* file, const char* base); + +#else // DLG_DISABLE + + #define dlg_log(level, ...) + #define dlg_logt(level, tags, ...) + + #define dlg_assertl(level, expr) // assert without tags/message + #define dlg_assertlt(level, tags, expr) // assert with tags + #define dlg_assertlm(level, expr, ...) // assert with message + #define dlg_assertltm(level, tags, expr, ...) // assert with tags & message + + #define dlg__assert_or(level, tags, expr, code, msg) if(!(expr)) { code; } (void) NULL +#endif // DLG_DISABLE + +// The API below is independent from DLG_DISABLE + +// Sets the handler that is responsible for formatting and outputting log calls. +// This function is not thread safe and the handler is set globally. +// The handler itself must not change dlg tags or call a dlg macro (if it +// does so, the provided string or tags array in 'origin' might get invalid). +// The handler can also be used for various other things such as dealing +// with failed assertions or filtering calls based on the passed tags. +// The default handler is dlg_default_output (see its doc for more info). +// If using c++ make sure the registered handler cannot throw e.g. by +// wrapping everything into a try-catch blog. +DLG_API void dlg_set_handler(dlg_handler handler, void* data); + +// The default output handler. +// Only use this to reset the output handler, prefer to use +// dlg_generic_output (from output.h) which this function simply calls. +// It also flushes the stream used and correctly outputs even from multiple threads. +DLG_API void dlg_default_output(const struct dlg_origin*, const char* string, void*); + +// Returns the currently active dlg handler and sets `data` to +// its user data pointer. `data` must not be NULL. +// Useful to create handler chains. +// This function is not threadsafe, i.e. retrieving the handler while +// changing it from another thread is unsafe. +// See `dlg_set_handler`. +DLG_API dlg_handler dlg_get_handler(void** data); + +// Adds the given tag associated with the given function to the thread specific list. +// If func is not NULL the tag will only applied to calls from the same function. +// Remove the tag again calling dlg_remove_tag (with exactly the same pointers!). +// Does not check if the tag is already present. +DLG_API void dlg_add_tag(const char* tag, const char* func); + +// Removes a tag added with dlg_add_tag (has no effect for tags no present). +// The pointers must be exactly the same pointers that were supplied to dlg_add_tag, +// this function will not check using strcmp. When the same tag/func combination +// is added multiple times, this function remove exactly one candidate, it is +// undefined which. Returns whether a tag was found (and removed). +DLG_API bool dlg_remove_tag(const char* tag, const char* func); + +// Returns the thread-specific buffer and its size for dlg. +// The buffer should only be used by formatting functions. +// The buffer can be reallocated and the size changed, just make sure +// to update both values correctly. +DLG_API char** dlg_thread_buffer(size_t** size); + +// Untagged leveled logging +#define dlg_trace(...) dlg_log(dlg_level_trace, __VA_ARGS__) +#define dlg_debug(...) dlg_log(dlg_level_debug, __VA_ARGS__) +#define dlg_info(...) dlg_log(dlg_level_info, __VA_ARGS__) +#define dlg_warn(...) dlg_log(dlg_level_warn, __VA_ARGS__) +#define dlg_error(...) dlg_log(dlg_level_error, __VA_ARGS__) +#define dlg_fatal(...) dlg_log(dlg_level_fatal, __VA_ARGS__) + +// Tagged leveled logging +#define dlg_tracet(tags, ...) dlg_logt(dlg_level_trace, tags, __VA_ARGS__) +#define dlg_debugt(tags, ...) dlg_logt(dlg_level_debug, tags, __VA_ARGS__) +#define dlg_infot(tags, ...) dlg_logt(dlg_level_info, tags, __VA_ARGS__) +#define dlg_warnt(tags, ...) dlg_logt(dlg_level_warn, tags, __VA_ARGS__) +#define dlg_errort(tags, ...) dlg_logt(dlg_level_error, tags, __VA_ARGS__) +#define dlg_fatalt(tags, ...) dlg_logt(dlg_level_fatal, tags, __VA_ARGS__) + +// Assert macros useing DLG_DEFAULT_ASSERT as level +#define dlg_assert(expr) dlg_assertl(DLG_DEFAULT_ASSERT, expr) +#define dlg_assertt(tags, expr) dlg_assertlt(DLG_DEFAULT_ASSERT, tags, expr) +#define dlg_assertm(expr, ...) dlg_assertlm(DLG_DEFAULT_ASSERT, expr, __VA_ARGS__) +#define dlg_asserttm(tags, expr, ...) dlg_assertltm(DLG_DEFAULT_ASSERT, tags, expr, __VA_ARGS__) + +// If (expr) does not evaluate to true, always executes 'code' (no matter what +// DLG_ASSERT_LEVEL is or if dlg is disabled or not). +// When dlg is enabled and the level is greater or equal to DLG_ASSERT_LEVEL, +// logs the failed assertion. +// Example usages: +// dlg_assertl_or(dlg_level_warn, data != nullptr, return); +// dlg_assertlm_or(dlg_level_fatal, data != nullptr, return, "Data must not be null"); +// dlg_assert_or(data != nullptr, logError(); return false); +#define dlg_assertltm_or(level, tags, expr, code, ...) dlg__assert_or(level, \ + DLG_CREATE_TAGS tags, expr, code, DLG_FMT_FUNC(__VA_ARGS__)) +#define dlg_assertlm_or(level, expr, code, ...) dlg__assert_or(level, \ + DLG_CREATE_TAGS(NULL), expr, code, DLG_FMT_FUNC(__VA_ARGS__)) +#define dlg_assertl_or(level, expr, code) dlg__assert_or(level, \ + DLG_CREATE_TAGS(NULL), expr, code, NULL) + +#define dlg_assert_or(expr, code) dlg_assertl_or(DLG_DEFAULT_ASSERT, expr, code) +#define dlg_assertm_or(expr, code, ...) dlg_assertlm_or(DLG_DEFAULT_ASSERT, expr, code, __VA_ARGS__) + +#ifdef __cplusplus +} +#endif + +#endif // header guard diff --git a/lib/libesp32_lvgl/freetype/include/dlg/output.h b/lib/libesp32_lvgl/freetype/include/dlg/output.h new file mode 100644 index 000000000..453e4a561 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/include/dlg/output.h @@ -0,0 +1,172 @@ +// Copyright (c) 2019 nyorain +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt + +#ifndef INC_DLG_OUTPUT_H_ +#define INC_DLG_OUTPUT_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Text style +enum dlg_text_style { + dlg_text_style_reset = 0, + dlg_text_style_bold = 1, + dlg_text_style_dim = 2, + dlg_text_style_italic = 3, + dlg_text_style_underline = 4, + dlg_text_style_blink = 5, + dlg_text_style_rblink = 6, + dlg_text_style_reversed = 7, + dlg_text_style_conceal = 8, + dlg_text_style_crossed = 9, + dlg_text_style_none, +}; + +// Text color +enum dlg_color { + dlg_color_black = 0, + dlg_color_red, + dlg_color_green, + dlg_color_yellow, + dlg_color_blue, + dlg_color_magenta, + dlg_color_cyan, + dlg_color_gray, + dlg_color_reset = 9, + + dlg_color_black2 = 60, + dlg_color_red2, + dlg_color_green2, + dlg_color_yellow2, + dlg_color_blue2, + dlg_color_magenta2, + dlg_color_cyan2, + dlg_color_gray2, + + dlg_color_none = 69, +}; + +struct dlg_style { + enum dlg_text_style style; + enum dlg_color fg; + enum dlg_color bg; +}; + +// Like fprintf but fixes utf-8 output to console on windows. +// On non-windows sytems just uses the corresponding standard library +// functions. On windows, if dlg was compiled with the win_console option, +// will first try to output it in a way that allows the default console +// to display utf-8. If that fails, will fall back to the standard +// library functions. +DLG_API int dlg_fprintf(FILE* stream, const char* format, ...) DLG_PRINTF_ATTRIB(2, 3); +DLG_API int dlg_vfprintf(FILE* stream, const char* format, va_list list); + +// Like dlg_printf, but also applies the given style to this output. +// The style will always be applied (using escape sequences), independent of the given stream. +// On windows escape sequences don't work out of the box, see dlg_win_init_ansi(). +DLG_API int dlg_styled_fprintf(FILE* stream, struct dlg_style style, + const char* format, ...) DLG_PRINTF_ATTRIB(3, 4); + +// Features to output from the generic output handler. +// Some features might have only an effect in the specializations. +enum dlg_output_feature { + dlg_output_tags = 1, // output tags list + dlg_output_time = 2, // output time of log call (hour:minute:second) + dlg_output_style = 4, // whether to use the supplied styles + dlg_output_func = 8, // output function + dlg_output_file_line = 16, // output file:line, + dlg_output_newline = 32, // output a newline at the end + dlg_output_threadsafe = 64, // locks stream before printing + dlg_output_time_msecs = 128 // output micro seconds (ms on windows) +}; + +// The default level-dependent output styles. The array values represent the styles +// to be used for the associated level (i.e. [0] for trace level). +DLG_API extern const struct dlg_style dlg_default_output_styles[6]; + +// Generic output function. Used by the default output handler and might be useful +// for custom output handlers (that don't want to manually format the output). +// Will call the given output func with the given data (and format + args to print) +// for everything it has to print in printf format. +// See also the *_stream and *_buf specializations for common usage. +// The given output function must not be NULL. +typedef void(*dlg_generic_output_handler)(void* data, const char* format, ...); +DLG_API void dlg_generic_output(dlg_generic_output_handler output, void* data, + unsigned int features, const struct dlg_origin* origin, const char* string, + const struct dlg_style styles[6]); + +// Generic output function, using a format string instead of feature flags. +// Use following conversion characters: +// %h - output the time in H:M:S format +// %m - output the time in milliseconds +// %t - output the full list of tags, comma separated +// %f - output the function name noted in the origin +// %o - output the file:line of the origin +// %s - print the appropriate style escape sequence. +// %r - print the escape sequence to reset the style. +// %c - The content of the log/assert +// %% - print the '%' character +// Only the above specified conversion characters are valid, the rest are +// written as it is. +DLG_API void dlg_generic_outputf(dlg_generic_output_handler output, void* data, + const char* format_string, const struct dlg_origin* origin, + const char* string, const struct dlg_style styles[6]); + +// Generic output function. Used by the default output handler and might be useful +// for custom output handlers (that don't want to manually format the output). +// If stream is NULL uses stdout. +// Automatically uses dlg_fprintf to assure correct utf-8 even on windows consoles. +// Locks the stream (i.e. assures threadsafe access) when the associated feature +// is passed (note that stdout/stderr might still mix from multiple threads). +DLG_API void dlg_generic_output_stream(FILE* stream, unsigned int features, + const struct dlg_origin* origin, const char* string, + const struct dlg_style styles[6]); +DLG_API void dlg_generic_outputf_stream(FILE* stream, const char* format_string, + const struct dlg_origin* origin, const char* string, + const struct dlg_style styles[6], bool lock_stream); + +// Generic output function (see dlg_generic_output) that uses a buffer instead of +// a stream. buf must at least point to *size bytes. Will set *size to the number +// of bytes written (capped to the given size), if buf == NULL will set *size +// to the needed size. The size parameter must not be NULL. +DLG_API void dlg_generic_output_buf(char* buf, size_t* size, unsigned int features, + const struct dlg_origin* origin, const char* string, + const struct dlg_style styles[6]); +DLG_API void dlg_generic_outputf_buf(char* buf, size_t* size, const char* format_string, + const struct dlg_origin* origin, const char* string, + const struct dlg_style styles[6]); + +// Returns if the given stream is a tty. Useful for custom output handlers +// e.g. to determine whether to use color. +// NOTE: Due to windows limitations currently returns false for wsl ttys. +DLG_API bool dlg_is_tty(FILE* stream); + +// Returns the null-terminated escape sequence for the given style into buf. +// Undefined behvaiour if any member of style has a value outside its enum range (will +// probably result in a buffer overflow or garbage being printed). +// If all member of style are 'none' will simply nullterminate the first buf char. +DLG_API void dlg_escape_sequence(struct dlg_style style, char buf[12]); + +// The reset style escape sequence. +DLG_API extern const char* const dlg_reset_sequence; + +// Just returns true without other effect on non-windows systems or if dlg +// was compiled without the win_console option. +// On windows tries to set the console mode to ansi to make escape sequences work. +// This works only on newer windows 10 versions. Returns false on error. +// Only the first call to it will have an effect, following calls just return the result. +// The function is threadsafe. Automatically called by the default output handler. +// This will only be able to set the mode for the stdout and stderr consoles, so +// other streams to consoles will still not work. +DLG_API bool dlg_win_init_ansi(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // header guard diff --git a/lib/libesp32_lvgl/freetype/include/freetype/config/ftconfig.h b/lib/libesp32_lvgl/freetype/include/freetype/config/ftconfig.h index b464e0b78..a85151699 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/config/ftconfig.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/config/ftconfig.h @@ -4,7 +4,7 @@ * * ANSI-specific configuration file (specification only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/config/ftheader.h b/lib/libesp32_lvgl/freetype/include/freetype/config/ftheader.h index 28b5cc60c..e607bce15 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/config/ftheader.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/config/ftheader.h @@ -4,7 +4,7 @@ * * Build macros of the FreeType 2 library. * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -777,6 +777,18 @@ #define FT_COLOR_H + /************************************************************************** + * + * @macro: + * FT_OTSVG_H + * + * @description: + * A macro used in `#include` statements to name the file containing the + * FreeType~2 API which handles the OpenType 'SVG~' glyphs. + */ +#define FT_OTSVG_H + + /* */ /* These header files don't need to be included by the user. */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/config/ftmodule.h b/lib/libesp32_lvgl/freetype/include/freetype/config/ftmodule.h index b5c4b1ee5..2fa130f3e 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/config/ftmodule.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/config/ftmodule.h @@ -10,19 +10,19 @@ * */ -FT_USE_MODULE( FT_Module_Class, autofit_module_class ) +// FT_USE_MODULE( FT_Module_Class, autofit_module_class ) FT_USE_MODULE( FT_Driver_ClassRec, tt_driver_class ) -FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class ) -FT_USE_MODULE( FT_Driver_ClassRec, cff_driver_class ) -FT_USE_MODULE( FT_Driver_ClassRec, t1cid_driver_class ) -FT_USE_MODULE( FT_Driver_ClassRec, pfr_driver_class ) -FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class ) -FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class ) -FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class ) -FT_USE_MODULE( FT_Module_Class, psaux_module_class ) -FT_USE_MODULE( FT_Module_Class, psnames_module_class ) -FT_USE_MODULE( FT_Module_Class, pshinter_module_class ) -FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class ) +// FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class ) +// FT_USE_MODULE( FT_Driver_ClassRec, cff_driver_class ) +// FT_USE_MODULE( FT_Driver_ClassRec, t1cid_driver_class ) +// FT_USE_MODULE( FT_Driver_ClassRec, pfr_driver_class ) +// FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class ) +// FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class ) +// FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class ) +// FT_USE_MODULE( FT_Module_Class, psaux_module_class ) +// FT_USE_MODULE( FT_Module_Class, psnames_module_class ) +// FT_USE_MODULE( FT_Module_Class, pshinter_module_class ) +// FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class ) FT_USE_MODULE( FT_Module_Class, sfnt_module_class ) FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class ) FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class ) diff --git a/lib/libesp32_lvgl/freetype/include/freetype/config/ftoption.h b/lib/libesp32_lvgl/freetype/include/freetype/config/ftoption.h index 097f19b8a..1976b33af 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/config/ftoption.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/config/ftoption.h @@ -4,7 +4,7 @@ * * User-selectable configuration macros (specification only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -105,8 +105,7 @@ FT_BEGIN_HEADER * * ``` * FREETYPE_PROPERTIES=truetype:interpreter-version=35 \ - * cff:no-stem-darkening=1 \ - * autofitter:warping=1 + * cff:no-stem-darkening=1 * ``` * */ @@ -220,6 +219,10 @@ FT_BEGIN_HEADER * If you use a build system like cmake or the `configure` script, * options set by those programs have precedence, overwriting the value * here with the configured one. + * + * If you use the GNU make build system directly (that is, without the + * `configure` script) and you define this macro, you also have to pass + * `SYSTEM_ZLIB=yes` as an argument to make. */ /* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */ @@ -431,6 +434,23 @@ FT_BEGIN_HEADER /* #define FT_DEBUG_LEVEL_TRACE */ + /************************************************************************** + * + * Logging + * + * Compiling FreeType in debug or trace mode makes FreeType write error + * and trace log messages to `stderr`. Enabling this macro + * automatically forces the `FT_DEBUG_LEVEL_ERROR` and + * `FT_DEBUG_LEVEL_TRACE` macros and allows FreeType to write error and + * trace log messages to a file instead of `stderr`. For writing logs + * to a file, FreeType uses an the external `dlg` library (the source + * code is in `src/dlg`). + * + * This option needs a C99 compiler. + */ +/* #define FT_DEBUG_LOGGING */ + + /************************************************************************** * * Autofitter debugging @@ -441,9 +461,9 @@ FT_BEGIN_HEADER * while compiling in 'release' mode): * * ``` - * _af_debug_disable_horz_hints - * _af_debug_disable_vert_hints - * _af_debug_disable_blue_hints + * af_debug_disable_horz_hints_ + * af_debug_disable_vert_hints_ + * af_debug_disable_blue_hints_ * ``` * * Additionally, the following functions provide dumps of various @@ -460,7 +480,7 @@ FT_BEGIN_HEADER * As an argument, they use another global variable: * * ``` - * _af_debug_hints + * af_debug_hints_ * ``` * * Please have a look at the `ftgrid` demo program to see how those @@ -507,6 +527,20 @@ FT_BEGIN_HEADER #undef FT_CONFIG_OPTION_USE_MODULE_ERRORS + /************************************************************************** + * + * OpenType SVG Glyph Support + * + * Setting this macro enables support for OpenType SVG glyphs. By + * default, FreeType can only fetch SVG documents. However, it can also + * render them if external rendering hook functions are plugged in at + * runtime. + * + * More details on the hooks can be found in file `otsvg.h`. + */ +#define FT_CONFIG_OPTION_SVG + + /************************************************************************** * * Error Strings @@ -550,12 +584,12 @@ FT_BEGIN_HEADER /************************************************************************** * * Define `TT_CONFIG_OPTION_POSTSCRIPT_NAMES` if you want to be able to - * load and enumerate the glyph Postscript names in a TrueType or OpenType + * load and enumerate Postscript names of glyphs in a TrueType or OpenType * file. * - * Note that when you do not compile the 'psnames' module by undefining the - * above `FT_CONFIG_OPTION_POSTSCRIPT_NAMES`, the 'sfnt' module will - * contain additional code used to read the PS Names table from a font. + * Note that if you do not compile the 'psnames' module by undefining the + * above `FT_CONFIG_OPTION_POSTSCRIPT_NAMES` macro, the 'sfnt' module will + * contain additional code to read the PostScript name table from a font. * * (By default, the module uses 'psnames' to extract glyph names.) */ @@ -627,36 +661,12 @@ FT_BEGIN_HEADER * not) instructions in a certain way so that all TrueType fonts look like * they do in a Windows ClearType (DirectWrite) environment. See [1] for a * technical overview on what this means. See `ttinterp.h` for more - * details on the LEAN option. + * details on this option. * - * There are three possible values. - * - * Value 1: - * This value is associated with the 'Infinality' moniker, contributed by - * an individual nicknamed Infinality with the goal of making TrueType - * fonts render better than on Windows. A high amount of configurability - * and flexibility, down to rules for single glyphs in fonts, but also - * very slow. Its experimental and slow nature and the original - * developer losing interest meant that this option was never enabled in - * default builds. - * - * The corresponding interpreter version is v38. - * - * Value 2: - * The new default mode for the TrueType driver. The Infinality code - * base was stripped to the bare minimum and all configurability removed - * in the name of speed and simplicity. The configurability was mainly - * aimed at legacy fonts like 'Arial', 'Times New Roman', or 'Courier'. - * Legacy fonts are fonts that modify vertical stems to achieve clean - * black-and-white bitmaps. The new mode focuses on applying a minimal - * set of rules to all fonts indiscriminately so that modern and web - * fonts render well while legacy fonts render okay. - * - * The corresponding interpreter version is v40. - * - * Value 3: - * Compile both, making both v38 and v40 available (the latter is the - * default). + * The new default mode focuses on applying a minimal set of rules to all + * fonts indiscriminately so that modern and web fonts render well while + * legacy fonts render okay. The corresponding interpreter version is v40. + * The so-called Infinality mode (v38) is no longer available in FreeType. * * By undefining these, you get rendering behavior like on Windows without * ClearType, i.e., Windows XP without ClearType enabled and Win9x @@ -671,9 +681,7 @@ FT_BEGIN_HEADER * [1] * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */ -/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */ -#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2 -/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING ( 1 | 2 ) */ +#define TT_CONFIG_OPTION_SUBPIXEL_HINTING /************************************************************************** @@ -705,6 +713,24 @@ FT_BEGIN_HEADER #define TT_CONFIG_OPTION_GX_VAR_SUPPORT + /************************************************************************** + * + * Define `TT_CONFIG_OPTION_NO_BORING_EXPANSION` if you want to exclude + * support for 'boring' OpenType specification expansions. + * + * https://github.com/harfbuzz/boring-expansion-spec + * + * Right now, the following features are covered: + * + * - 'avar' version 2.0 + * + * Most likely, this is a temporary configuration option to be removed in + * the near future, since it is assumed that eventually those features are + * added to the OpenType standard. + */ +/* #define TT_CONFIG_OPTION_NO_BORING_EXPANSION */ + + /************************************************************************** * * Define `TT_CONFIG_OPTION_BDF` if you want to include support for an @@ -892,24 +918,6 @@ FT_BEGIN_HEADER #endif - /************************************************************************** - * - * Compile 'autofit' module with warp hinting. The idea of the warping - * code is to slightly scale and shift a glyph within a single dimension so - * that as much of its segments are aligned (more or less) on the grid. To - * find out the optimal scaling and shifting value, various parameter - * combinations are tried and scored. - * - * You can switch warping on and off with the `warping` property of the - * auto-hinter (see file `ftdriver.h` for more information; by default it - * is switched off). - * - * This experimental option is not active if the rendering mode is - * `FT_RENDER_MODE_LIGHT`. - */ -#define AF_CONFIG_OPTION_USE_WARPER - - /************************************************************************** * * Use TrueType-like size metrics for 'light' auto-hinting. @@ -943,21 +951,29 @@ FT_BEGIN_HEADER /* - * The next three macros are defined if native TrueType hinting is + * The next two macros are defined if native TrueType hinting is * requested by the definitions above. Don't change this. */ #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER #define TT_USE_BYTECODE_INTERPRETER - #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING -#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 1 -#define TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY -#endif - -#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 2 #define TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL #endif #endif + + + /* + * The TT_SUPPORT_COLRV1 macro is defined to indicate to clients that this + * version of FreeType has support for 'COLR' v1 API. This definition is + * useful to FreeType clients that want to build in support for 'COLR' v1 + * depending on a tip-of-tree checkout before it is officially released in + * FreeType, and while the feature cannot yet be tested against using + * version macros. Don't change this macro. This may be removed once the + * feature is in a FreeType release version and version macros can be used + * to test for availability. + */ +#ifdef TT_CONFIG_OPTION_COLOR_LAYERS +#define TT_SUPPORT_COLRV1 #endif @@ -989,8 +1005,8 @@ FT_BEGIN_HEADER #error "Invalid CFF darkening parameters!" #endif -FT_END_HEADER +FT_END_HEADER #endif /* FTOPTION_H_ */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/config/ftstdlib.h b/lib/libesp32_lvgl/freetype/include/freetype/config/ftstdlib.h index d6091f8b3..f65148a90 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/config/ftstdlib.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/config/ftstdlib.h @@ -5,7 +5,7 @@ * ANSI-specific library and header configuration file (specification * only). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -43,7 +43,8 @@ * * `UINT_MAX` and `ULONG_MAX` are used to automatically compute the size of * `int` and `long` in bytes at compile-time. So far, this works for all - * platforms the library has been tested on. + * platforms the library has been tested on. We also check `ULLONG_MAX` + * to see whether we can use 64-bit `long long` later on. * * Note that on the extremely rare platforms that do not provide integer * types that are _exactly_ 16 and 32~bits wide (e.g., some old Crays where @@ -66,6 +67,15 @@ #define FT_LONG_MIN LONG_MIN #define FT_LONG_MAX LONG_MAX #define FT_ULONG_MAX ULONG_MAX +#ifdef LLONG_MAX +#define FT_LLONG_MAX LLONG_MAX +#endif +#ifdef LLONG_MIN +#define FT_LLONG_MIN LLONG_MIN +#endif +#ifdef ULLONG_MAX +#define FT_ULLONG_MAX ULLONG_MAX +#endif /************************************************************************** @@ -101,13 +111,13 @@ #include -#define FT_FILE FILE -#define ft_fclose fclose -#define ft_fopen fopen -#define ft_fread fread -#define ft_fseek fseek -#define ft_ftell ftell -#define ft_sprintf sprintf +#define FT_FILE FILE +#define ft_fclose fclose +#define ft_fopen fopen +#define ft_fread fread +#define ft_fseek fseek +#define ft_ftell ftell +#define ft_snprintf snprintf /************************************************************************** diff --git a/lib/libesp32_lvgl/freetype/include/freetype/config/integer-types.h b/lib/libesp32_lvgl/freetype/include/freetype/config/integer-types.h index a0ca0c95e..7258b5085 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/config/integer-types.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/config/integer-types.h @@ -4,7 +4,7 @@ * * FreeType integer types definitions. * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -60,6 +60,18 @@ #endif /* !defined(FT_SIZEOF_LONG) */ +#ifndef FT_SIZEOF_LONG_LONG + + /* The size of a `long long` type if available */ +#if defined( FT_ULLONG_MAX ) && FT_ULLONG_MAX >= 0xFFFFFFFFFFFFFFFFULL +#define FT_SIZEOF_LONG_LONG ( 64 / FT_CHAR_BIT ) +#else +#define FT_SIZEOF_LONG_LONG 0 +#endif + +#endif /* !defined(FT_SIZEOF_LONG_LONG) */ + + /************************************************************************** * * @section: @@ -174,15 +186,17 @@ #endif - /* determine whether we have a 64-bit `int` type for platforms without */ - /* Autoconf */ + /* determine whether we have a 64-bit integer type */ #if FT_SIZEOF_LONG == ( 64 / FT_CHAR_BIT ) - /* `FT_LONG64` must be defined if a 64-bit type is available */ -#define FT_LONG64 #define FT_INT64 long #define FT_UINT64 unsigned long +#elif FT_SIZEOF_LONG_LONG >= ( 64 / FT_CHAR_BIT ) + +#define FT_INT64 long long int +#define FT_UINT64 unsigned long long int + /************************************************************************** * * A 64-bit data type may create compilation problems if you compile in @@ -192,16 +206,9 @@ */ #elif !defined( __STDC__ ) || defined( FT_CONFIG_OPTION_FORCE_INT64 ) -#if defined( __STDC_VERSION__ ) && __STDC_VERSION__ >= 199901L - -#define FT_LONG64 -#define FT_INT64 long long int -#define FT_UINT64 unsigned long long int - -#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */ +#if defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */ /* this compiler provides the `__int64` type */ -#define FT_LONG64 #define FT_INT64 __int64 #define FT_UINT64 unsigned __int64 @@ -211,32 +218,30 @@ /* to test the compiler version. */ /* this compiler provides the `__int64` type */ -#define FT_LONG64 #define FT_INT64 __int64 #define FT_UINT64 unsigned __int64 -#elif defined( __WATCOMC__ ) /* Watcom C++ */ +#elif defined( __WATCOMC__ ) && __WATCOMC__ >= 1100 /* Watcom C++ */ - /* Watcom doesn't provide 64-bit data types */ +#define FT_INT64 long long int +#define FT_UINT64 unsigned long long int #elif defined( __MWERKS__ ) /* Metrowerks CodeWarrior */ -#define FT_LONG64 #define FT_INT64 long long int #define FT_UINT64 unsigned long long int #elif defined( __GNUC__ ) /* GCC provides the `long long` type */ -#define FT_LONG64 #define FT_INT64 long long int #define FT_UINT64 unsigned long long int -#endif /* __STDC_VERSION__ >= 199901L */ +#endif /* !__STDC__ */ #endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */ -#ifdef FT_LONG64 +#ifdef FT_INT64 typedef FT_INT64 FT_Int64; typedef FT_UINT64 FT_UInt64; #endif diff --git a/lib/libesp32_lvgl/freetype/include/freetype/config/mac-support.h b/lib/libesp32_lvgl/freetype/include/freetype/config/mac-support.h index 94867088e..b77b96d5d 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/config/mac-support.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/config/mac-support.h @@ -4,7 +4,7 @@ * * Mac/OS X support configuration header. * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/config/public-macros.h b/lib/libesp32_lvgl/freetype/include/freetype/config/public-macros.h index 6aa673e80..23d0fa6a3 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/config/public-macros.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/config/public-macros.h @@ -4,7 +4,7 @@ * * Define a set of compiler macros used in public FreeType headers. * - * Copyright (C) 2020 by + * Copyright (C) 2020-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -103,6 +103,7 @@ FT_BEGIN_HEADER */ #define FT_EXPORT( x ) FT_PUBLIC_FUNCTION_ATTRIBUTE extern x + /* * `FT_UNUSED` indicates that a given parameter is not used -- this is * only used to get rid of unpleasant compiler warnings. @@ -115,6 +116,23 @@ FT_BEGIN_HEADER #endif + /* + * Support for casts in both C and C++. + */ +#ifdef __cplusplus +#define FT_STATIC_CAST( type, var ) static_cast(var) +#define FT_REINTERPRET_CAST( type, var ) reinterpret_cast(var) + +#define FT_STATIC_BYTE_CAST( type, var ) \ + static_cast( static_cast( var ) ) +#else +#define FT_STATIC_CAST( type, var ) (type)(var) +#define FT_REINTERPRET_CAST( type, var ) (type)(var) + +#define FT_STATIC_BYTE_CAST( type, var ) (type)(unsigned char)(var) +#endif + + FT_END_HEADER #endif /* FREETYPE_CONFIG_PUBLIC_MACROS_H_ */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/freetype.h b/lib/libesp32_lvgl/freetype/include/freetype/freetype.h index be191f5aa..92acf3794 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/freetype.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/freetype.h @@ -4,7 +4,7 @@ * * FreeType high-level API and common types (specification only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -30,6 +30,34 @@ FT_BEGIN_HEADER + /************************************************************************** + * + * @section: + * preamble + * + * @title: + * Preamble + * + * @abstract: + * What FreeType is and isn't + * + * @description: + * FreeType is a library that provides access to glyphs in font files. It + * scales the glyph images and their metrics to a requested size, and it + * rasterizes the glyph images to produce pixel or subpixel alpha coverage + * bitmaps. + * + * Note that FreeType is _not_ a text layout engine. You have to use + * higher-level libraries like HarfBuzz, Pango, or ICU for that. + * + * Note also that FreeType does _not_ perform alpha blending or + * compositing the resulting bitmaps or pixmaps by itself. Use your + * favourite graphics library (for example, Cairo or Skia) to further + * process FreeType's output. + * + */ + + /************************************************************************** * * @section: @@ -74,6 +102,277 @@ FT_BEGIN_HEADER */ + /************************************************************************** + * + * @section: + * font_testing_macros + * + * @title: + * Font Testing Macros + * + * @abstract: + * Macros to test various properties of fonts. + * + * @description: + * Macros to test the most important font properties. + * + * It is recommended to use these high-level macros instead of directly + * testing the corresponding flags, which are scattered over various + * structures. + * + * @order: + * FT_HAS_HORIZONTAL + * FT_HAS_VERTICAL + * FT_HAS_KERNING + * FT_HAS_FIXED_SIZES + * FT_HAS_GLYPH_NAMES + * FT_HAS_COLOR + * FT_HAS_MULTIPLE_MASTERS + * FT_HAS_SVG + * FT_HAS_SBIX + * FT_HAS_SBIX_OVERLAY + * + * FT_IS_SFNT + * FT_IS_SCALABLE + * FT_IS_FIXED_WIDTH + * FT_IS_CID_KEYED + * FT_IS_TRICKY + * FT_IS_NAMED_INSTANCE + * FT_IS_VARIATION + * + */ + + + /************************************************************************** + * + * @section: + * library_setup + * + * @title: + * Library Setup + * + * @abstract: + * Functions to start and end the usage of the FreeType library. + * + * @description: + * Functions to start and end the usage of the FreeType library. + * + * Note that @FT_Library_Version and @FREETYPE_XXX are of limited use + * because even a new release of FreeType with only documentation + * changes increases the version number. + * + * @order: + * FT_Library + * FT_Init_FreeType + * FT_Done_FreeType + * + * FT_Library_Version + * FREETYPE_XXX + * + */ + + + /************************************************************************** + * + * @section: + * face_creation + * + * @title: + * Face Creation + * + * @abstract: + * Functions to manage fonts. + * + * @description: + * The functions and structures collected in this section operate on + * fonts globally. + * + * @order: + * FT_Face + * FT_FaceRec + * FT_FACE_FLAG_XXX + * FT_STYLE_FLAG_XXX + * + * FT_New_Face + * FT_Done_Face + * FT_Reference_Face + * FT_New_Memory_Face + * FT_Face_Properties + * FT_Open_Face + * FT_Open_Args + * FT_OPEN_XXX + * FT_Parameter + * FT_Attach_File + * FT_Attach_Stream + * + */ + + + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + * @title: + * Sizing and Scaling + * + * @abstract: + * Functions to manage font sizes. + * + * @description: + * The functions and structures collected in this section are related to + * selecting and manipulating the size of a font globally. + * + * @order: + * FT_Size + * FT_SizeRec + * FT_Size_Metrics + * + * FT_Bitmap_Size + * + * FT_Set_Char_Size + * FT_Set_Pixel_Sizes + * FT_Request_Size + * FT_Select_Size + * FT_Size_Request_Type + * FT_Size_RequestRec + * FT_Size_Request + * + * FT_Set_Transform + * FT_Get_Transform + * + */ + + + /************************************************************************** + * + * @section: + * glyph_retrieval + * + * @title: + * Glyph Retrieval + * + * @abstract: + * Functions to manage glyphs. + * + * @description: + * The functions and structures collected in this section operate on + * single glyphs, of which @FT_Load_Glyph is most important. + * + * @order: + * FT_GlyphSlot + * FT_GlyphSlotRec + * FT_Glyph_Metrics + * + * FT_Load_Glyph + * FT_LOAD_XXX + * FT_LOAD_TARGET_MODE + * FT_LOAD_TARGET_XXX + * + * FT_Render_Glyph + * FT_Render_Mode + * FT_Get_Kerning + * FT_Kerning_Mode + * FT_Get_Track_Kerning + * + */ + + + /************************************************************************** + * + * @section: + * character_mapping + * + * @title: + * Character Mapping + * + * @abstract: + * Functions to manage character-to-glyph maps. + * + * @description: + * This section holds functions and structures that are related to + * mapping character input codes to glyph indices. + * + * Note that for many scripts the simplistic approach used by FreeType + * of mapping a single character to a single glyph is not valid or + * possible! In general, a higher-level library like HarfBuzz or ICU + * should be used for handling text strings. + * + * @order: + * FT_CharMap + * FT_CharMapRec + * FT_Encoding + * FT_ENC_TAG + * + * FT_Select_Charmap + * FT_Set_Charmap + * FT_Get_Charmap_Index + * + * FT_Get_Char_Index + * FT_Get_First_Char + * FT_Get_Next_Char + * FT_Load_Char + * + */ + + + /************************************************************************** + * + * @section: + * information_retrieval + * + * @title: + * Information Retrieval + * + * @abstract: + * Functions to retrieve font and glyph information. + * + * @description: + * Functions to retrieve font and glyph information. Only some very + * basic data is covered; see also the chapter on the format-specific + * API for more. + * + * + * @order: + * FT_Get_Name_Index + * FT_Get_Glyph_Name + * FT_Get_Postscript_Name + * FT_Get_FSType_Flags + * FT_FSTYPE_XXX + * FT_Get_SubGlyph_Info + * FT_SUBGLYPH_FLAG_XXX + * + */ + + + /************************************************************************** + * + * @section: + * other_api_data + * + * @title: + * Other API Data + * + * @abstract: + * Other structures, enumerations, and macros. + * + * @description: + * Other structures, enumerations, and macros. Deprecated functions are + * also listed here. + * + * @order: + * FT_Face_Internal + * FT_Size_Internal + * FT_Slot_Internal + * + * FT_SubGlyph + * + * FT_HAS_FAST_GLYPHS + * FT_Face_CheckTrueTypePatents + * FT_Face_SetUnpatentedHinting + * + */ + /*************************************************************************/ /*************************************************************************/ @@ -87,165 +386,10 @@ FT_BEGIN_HEADER /************************************************************************** * * @section: - * base_interface - * - * @title: - * Base Interface - * - * @abstract: - * The FreeType~2 base font interface. - * - * @description: - * This section describes the most important public high-level API - * functions of FreeType~2. - * - * @order: - * FT_Library - * FT_Face - * FT_Size - * FT_GlyphSlot - * FT_CharMap - * FT_Encoding - * FT_ENC_TAG - * - * FT_FaceRec - * - * FT_FACE_FLAG_SCALABLE - * FT_FACE_FLAG_FIXED_SIZES - * FT_FACE_FLAG_FIXED_WIDTH - * FT_FACE_FLAG_HORIZONTAL - * FT_FACE_FLAG_VERTICAL - * FT_FACE_FLAG_COLOR - * FT_FACE_FLAG_SFNT - * FT_FACE_FLAG_CID_KEYED - * FT_FACE_FLAG_TRICKY - * FT_FACE_FLAG_KERNING - * FT_FACE_FLAG_MULTIPLE_MASTERS - * FT_FACE_FLAG_VARIATION - * FT_FACE_FLAG_GLYPH_NAMES - * FT_FACE_FLAG_EXTERNAL_STREAM - * FT_FACE_FLAG_HINTER - * - * FT_HAS_HORIZONTAL - * FT_HAS_VERTICAL - * FT_HAS_KERNING - * FT_HAS_FIXED_SIZES - * FT_HAS_GLYPH_NAMES - * FT_HAS_COLOR - * FT_HAS_MULTIPLE_MASTERS - * - * FT_IS_SFNT - * FT_IS_SCALABLE - * FT_IS_FIXED_WIDTH - * FT_IS_CID_KEYED - * FT_IS_TRICKY - * FT_IS_NAMED_INSTANCE - * FT_IS_VARIATION - * - * FT_STYLE_FLAG_BOLD - * FT_STYLE_FLAG_ITALIC - * - * FT_SizeRec - * FT_Size_Metrics - * - * FT_GlyphSlotRec - * FT_Glyph_Metrics - * FT_SubGlyph - * - * FT_Bitmap_Size - * - * FT_Init_FreeType - * FT_Done_FreeType - * - * FT_New_Face - * FT_Done_Face - * FT_Reference_Face - * FT_New_Memory_Face - * FT_Face_Properties - * FT_Open_Face - * FT_Open_Args - * FT_Parameter - * FT_Attach_File - * FT_Attach_Stream - * - * FT_Set_Char_Size - * FT_Set_Pixel_Sizes - * FT_Request_Size - * FT_Select_Size - * FT_Size_Request_Type - * FT_Size_RequestRec - * FT_Size_Request - * FT_Set_Transform - * FT_Load_Glyph - * FT_Get_Char_Index - * FT_Get_First_Char - * FT_Get_Next_Char - * FT_Get_Name_Index - * FT_Load_Char - * - * FT_OPEN_MEMORY - * FT_OPEN_STREAM - * FT_OPEN_PATHNAME - * FT_OPEN_DRIVER - * FT_OPEN_PARAMS - * - * FT_LOAD_DEFAULT - * FT_LOAD_RENDER - * FT_LOAD_MONOCHROME - * FT_LOAD_LINEAR_DESIGN - * FT_LOAD_NO_SCALE - * FT_LOAD_NO_HINTING - * FT_LOAD_NO_BITMAP - * FT_LOAD_NO_AUTOHINT - * FT_LOAD_COLOR - * - * FT_LOAD_VERTICAL_LAYOUT - * FT_LOAD_IGNORE_TRANSFORM - * FT_LOAD_FORCE_AUTOHINT - * FT_LOAD_NO_RECURSE - * FT_LOAD_PEDANTIC - * - * FT_LOAD_TARGET_NORMAL - * FT_LOAD_TARGET_LIGHT - * FT_LOAD_TARGET_MONO - * FT_LOAD_TARGET_LCD - * FT_LOAD_TARGET_LCD_V - * - * FT_LOAD_TARGET_MODE - * - * FT_Render_Glyph - * FT_Render_Mode - * FT_Get_Kerning - * FT_Kerning_Mode - * FT_Get_Track_Kerning - * FT_Get_Glyph_Name - * FT_Get_Postscript_Name - * - * FT_CharMapRec - * FT_Select_Charmap - * FT_Set_Charmap - * FT_Get_Charmap_Index - * - * FT_Get_FSType_Flags - * FT_Get_SubGlyph_Info - * - * FT_Face_Internal - * FT_Size_Internal - * FT_Slot_Internal - * - * FT_FACE_FLAG_XXX - * FT_STYLE_FLAG_XXX - * FT_OPEN_XXX - * FT_LOAD_XXX - * FT_LOAD_TARGET_XXX - * FT_SUBGLYPH_FLAG_XXX - * FT_FSTYPE_XXX - * - * FT_HAS_FAST_GLYPHS + * glyph_retrieval * */ - /************************************************************************** * * @struct: @@ -313,6 +457,13 @@ FT_BEGIN_HEADER } FT_Glyph_Metrics; + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + */ + /************************************************************************** * * @struct: @@ -373,6 +524,13 @@ FT_BEGIN_HEADER /*************************************************************************/ /*************************************************************************/ + /************************************************************************** + * + * @section: + * library_setup + * + */ + /************************************************************************** * * @type: @@ -447,7 +605,7 @@ FT_BEGIN_HEADER /************************************************************************** * * @section: - * base_interface + * face_creation * */ @@ -483,6 +641,13 @@ FT_BEGIN_HEADER typedef struct FT_FaceRec_* FT_Face; + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + */ + /************************************************************************** * * @type: @@ -493,13 +658,15 @@ FT_BEGIN_HEADER * size. * * @note: - * An @FT_Face has one _active_ @FT_Size object that is used by functions - * like @FT_Load_Glyph to determine the scaling transformation that in - * turn is used to load and hint glyphs and metrics. + * An @FT_Face has one _active_ `FT_Size` object that is used by + * functions like @FT_Load_Glyph to determine the scaling transformation + * that in turn is used to load and hint glyphs and metrics. * - * You can use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes, @FT_Request_Size + * A newly created `FT_Size` object contains only meaningless zero values. + * You must use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes, @FT_Request_Size * or even @FT_Select_Size to change the content (i.e., the scaling - * values) of the active @FT_Size. + * values) of the active `FT_Size`. Otherwise, the scaling and hinting + * will not be performed. * * You can use @FT_New_Size to create additional size objects for a given * @FT_Face, but they won't be used by other functions until you activate @@ -513,6 +680,13 @@ FT_BEGIN_HEADER typedef struct FT_SizeRec_* FT_Size; + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @type: @@ -532,6 +706,13 @@ FT_BEGIN_HEADER typedef struct FT_GlyphSlotRec_* FT_GlyphSlot; + /************************************************************************** + * + * @section: + * character_mapping + * + */ + /************************************************************************** * * @type: @@ -587,11 +768,12 @@ FT_BEGIN_HEADER */ #ifndef FT_ENC_TAG -#define FT_ENC_TAG( value, a, b, c, d ) \ - value = ( ( (FT_UInt32)(a) << 24 ) | \ - ( (FT_UInt32)(b) << 16 ) | \ - ( (FT_UInt32)(c) << 8 ) | \ - (FT_UInt32)(d) ) + +#define FT_ENC_TAG( value, a, b, c, d ) \ + value = ( ( FT_STATIC_BYTE_CAST( FT_UInt32, a ) << 24 ) | \ + ( FT_STATIC_BYTE_CAST( FT_UInt32, b ) << 16 ) | \ + ( FT_STATIC_BYTE_CAST( FT_UInt32, c ) << 8 ) | \ + FT_STATIC_BYTE_CAST( FT_UInt32, d ) ) #endif /* FT_ENC_TAG */ @@ -607,7 +789,7 @@ FT_BEGIN_HEADER * * @note: * Despite the name, this enumeration lists specific character - * repertories (i.e., charsets), and not text encoding methods (e.g., + * repertoires (i.e., charsets), and not text encoding methods (e.g., * UTF-8, UTF-16, etc.). * * Other encodings might be defined in the future. @@ -701,11 +883,16 @@ FT_BEGIN_HEADER * Same as FT_ENCODING_JOHAB. Deprecated. * * @note: - * By default, FreeType enables a Unicode charmap and tags it with - * `FT_ENCODING_UNICODE` when it is either provided or can be generated - * from PostScript glyph name dictionaries in the font file. All other - * encodings are considered legacy and tagged only if explicitly defined - * in the font file. Otherwise, `FT_ENCODING_NONE` is used. + * When loading a font, FreeType makes a Unicode charmap active if + * possible (either if the font provides such a charmap, or if FreeType + * can synthesize one from PostScript glyph name dictionaries; in either + * case, the charmap is tagged with `FT_ENCODING_UNICODE`). If such a + * charmap is synthesized, it is placed at the first position of the + * charmap array. + * + * All other encodings are considered legacy and tagged only if + * explicitly defined in the font file. Otherwise, `FT_ENCODING_NONE` is + * used. * * `FT_ENCODING_NONE` is set by the BDF and PCF drivers if the charmap is * neither Unicode nor ISO-8859-1 (otherwise it is set to @@ -735,7 +922,7 @@ FT_BEGIN_HEADER * `encoding_id`. If, for example, `encoding_id` is `TT_MAC_ID_ROMAN` * and the language ID (minus~1) is `TT_MAC_LANGID_GREEK`, it is the * Greek encoding, not Roman. `TT_MAC_ID_ARABIC` with - * `TT_MAC_LANGID_FARSI` means the Farsi variant the Arabic encoding. + * `TT_MAC_LANGID_FARSI` means the Farsi variant of the Arabic encoding. */ typedef enum FT_Encoding_ { @@ -833,6 +1020,13 @@ FT_BEGIN_HEADER /*************************************************************************/ + /************************************************************************** + * + * @section: + * other_api_data + * + */ + /************************************************************************** * * @type: @@ -848,6 +1042,13 @@ FT_BEGIN_HEADER typedef struct FT_Face_InternalRec_* FT_Face_Internal; + /************************************************************************** + * + * @section: + * face_creation + * + */ + /************************************************************************** * * @struct: @@ -874,7 +1075,7 @@ FT_BEGIN_HEADER * If we have the third named instance of face~4, say, `face_index` is * set to 0x00030004. * - * Bit 31 is always zero (this is, `face_index` is always a positive + * Bit 31 is always zero (that is, `face_index` is always a positive * value). * * [Since 2.9] Changing the design coordinates with @@ -892,7 +1093,7 @@ FT_BEGIN_HEADER * * [Since 2.6.1] Bits 16-30 hold the number of named instances * available for the current face if we have a GX or OpenType variation - * (sub)font. Bit 31 is always zero (this is, `style_flags` is always + * (sub)font. Bit 31 is always zero (that is, `style_flags` is always * a positive value). Note that a variation font has always at least * one named instance, namely the default instance. * @@ -958,7 +1159,7 @@ FT_BEGIN_HEADER * Note that the bounding box might be off by (at least) one pixel for * hinted fonts. See @FT_Size_Metrics for further discussion. * - * Note that the bounding box does not vary in OpenType variable fonts + * Note that the bounding box does not vary in OpenType variation fonts * and should only be used in relation to the default instance. * * units_per_EM :: @@ -1046,9 +1247,9 @@ FT_BEGIN_HEADER FT_Generic generic; - /*# The following member variables (down to `underline_thickness`) */ - /*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */ - /*# for bitmap fonts. */ + /* The following member variables (down to `underline_thickness`) */ + /* are only relevant to scalable outlines; cf. @FT_Bitmap_Size */ + /* for bitmap fonts. */ FT_BBox bbox; FT_UShort units_per_EM; @@ -1066,7 +1267,7 @@ FT_BEGIN_HEADER FT_Size size; FT_CharMap charmap; - /*@private begin */ + /* private fields, internal to FreeType */ FT_Driver driver; FT_Memory memory; @@ -1079,8 +1280,6 @@ FT_BEGIN_HEADER FT_Face_Internal internal; - /*@private end */ - } FT_FaceRec; @@ -1123,9 +1322,9 @@ FT_BEGIN_HEADER * FT_FACE_FLAG_KERNING :: * The face contains kerning information. If set, the kerning distance * can be retrieved using the function @FT_Get_Kerning. Otherwise the - * function always return the vector (0,0). Note that FreeType doesn't - * handle kerning data from the SFNT 'GPOS' table (as present in many - * OpenType fonts). + * function always returns the vector (0,0). Note that FreeType + * doesn't handle kerning data from the SFNT 'GPOS' table (as present + * in many OpenType fonts). * * FT_FACE_FLAG_FAST_GLYPHS :: * THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT. @@ -1163,13 +1362,13 @@ FT_BEGIN_HEADER * successfully; in all other cases you get an * `FT_Err_Invalid_Argument` error. * - * Note that CID-keyed fonts that are in an SFNT wrapper (this is, all + * Note that CID-keyed fonts that are in an SFNT wrapper (that is, all * OpenType/CFF fonts) don't have this flag set since the glyphs are * accessed in the normal way (using contiguous indices); the * 'CID-ness' isn't visible to the application. * * FT_FACE_FLAG_TRICKY :: - * The face is 'tricky', this is, it always needs the font format's + * The face is 'tricky', that is, it always needs the font format's * native hinting engine to get a reasonable result. A typical example * is the old Chinese font `mingli.ttf` (but not `mingliu.ttc`) that * uses TrueType bytecode instructions to move and scale all of its @@ -1191,8 +1390,21 @@ FT_BEGIN_HEADER * FT_FACE_FLAG_VARIATION :: * [Since 2.9] Set if the current face (or named instance) has been * altered with @FT_Set_MM_Design_Coordinates, - * @FT_Set_Var_Design_Coordinates, or @FT_Set_Var_Blend_Coordinates. - * This flag is unset by a call to @FT_Set_Named_Instance. + * @FT_Set_Var_Design_Coordinates, @FT_Set_Var_Blend_Coordinates, or + * @FT_Set_MM_WeightVector to select a non-default instance. + * + * FT_FACE_FLAG_SVG :: + * [Since 2.12] The face has an 'SVG~' OpenType table. + * + * FT_FACE_FLAG_SBIX :: + * [Since 2.12] The face has an 'sbix' OpenType table *and* outlines. + * For such fonts, @FT_FACE_FLAG_SCALABLE is not set by default to + * retain backward compatibility. + * + * FT_FACE_FLAG_SBIX_OVERLAY :: + * [Since 2.12] The face has an 'sbix' OpenType table where outlines + * should be drawn on top of bitmap strikes. + * */ #define FT_FACE_FLAG_SCALABLE ( 1L << 0 ) #define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 ) @@ -1210,8 +1422,18 @@ FT_BEGIN_HEADER #define FT_FACE_FLAG_TRICKY ( 1L << 13 ) #define FT_FACE_FLAG_COLOR ( 1L << 14 ) #define FT_FACE_FLAG_VARIATION ( 1L << 15 ) +#define FT_FACE_FLAG_SVG ( 1L << 16 ) +#define FT_FACE_FLAG_SBIX ( 1L << 17 ) +#define FT_FACE_FLAG_SBIX_OVERLAY ( 1L << 18 ) + /************************************************************************** + * + * @section: + * font_testing_macros + * + */ + /************************************************************************** * * @macro: @@ -1321,6 +1543,13 @@ FT_BEGIN_HEADER ( !!( (face)->face_flags & FT_FACE_FLAG_FIXED_SIZES ) ) + /************************************************************************** + * + * @section: + * other_api_data + * + */ + /************************************************************************** * * @macro: @@ -1333,6 +1562,13 @@ FT_BEGIN_HEADER #define FT_HAS_FAST_GLYPHS( face ) 0 + /************************************************************************** + * + * @section: + * font_testing_macros + * + */ + /************************************************************************** * * @macro: @@ -1391,8 +1627,8 @@ FT_BEGIN_HEADER * * @description: * A macro that returns true whenever a face object has been altered by - * @FT_Set_MM_Design_Coordinates, @FT_Set_Var_Design_Coordinates, or - * @FT_Set_Var_Blend_Coordinates. + * @FT_Set_MM_Design_Coordinates, @FT_Set_Var_Design_Coordinates, + * @FT_Set_Var_Blend_Coordinates, or @FT_Set_MM_WeightVector. * * @since: * 2.9 @@ -1450,6 +1686,131 @@ FT_BEGIN_HEADER ( !!( (face)->face_flags & FT_FACE_FLAG_COLOR ) ) + /************************************************************************** + * + * @macro: + * FT_HAS_SVG + * + * @description: + * A macro that returns true whenever a face object contains an 'SVG~' + * OpenType table. + * + * @since: + * 2.12 + */ +#define FT_HAS_SVG( face ) \ + ( !!( (face)->face_flags & FT_FACE_FLAG_SVG ) ) + + + /************************************************************************** + * + * @macro: + * FT_HAS_SBIX + * + * @description: + * A macro that returns true whenever a face object contains an 'sbix' + * OpenType table *and* outline glyphs. + * + * Currently, FreeType only supports bitmap glyphs in PNG format for this + * table (i.e., JPEG and TIFF formats are unsupported, as are + * Apple-specific formats not part of the OpenType specification). + * + * @note: + * For backward compatibility, a font with an 'sbix' table is treated as + * a bitmap-only face. Using @FT_Open_Face with + * @FT_PARAM_TAG_IGNORE_SBIX, an application can switch off 'sbix' + * handling so that the face is treated as an ordinary outline font with + * scalable outlines. + * + * Here is some pseudo code that roughly illustrates how to implement + * 'sbix' handling according to the OpenType specification. + * + * ``` + * if ( FT_HAS_SBIX( face ) ) + * { + * // open font as a scalable one without sbix handling + * FT_Face face2; + * FT_Parameter param = { FT_PARAM_TAG_IGNORE_SBIX, NULL }; + * FT_Open_Args args = { FT_OPEN_PARAMS | ..., + * ..., + * 1, ¶m }; + * + * + * FT_Open_Face( library, &args, 0, &face2 ); + * + * available_size` as necessary into + * `preferred_sizes`[*]> + * + * for ( i = 0; i < face->num_fixed_sizes; i++ ) + * { + * size = preferred_sizes[i].size; + * + * error = FT_Set_Pixel_Sizes( face, size, size ); + * + * + * // check whether we have a glyph in a bitmap strike + * error = FT_Load_Glyph( face, + * glyph_index, + * FT_LOAD_SBITS_ONLY | + * FT_LOAD_BITMAP_METRICS_ONLY ); + * if ( error == FT_Err_Invalid_Argument ) + * continue; + * else if ( error ) + * + * else + * break; + * } + * + * if ( i != face->num_fixed_sizes ) + * + * + * if ( i == face->num_fixed_sizes || + * FT_HAS_SBIX_OVERLAY( face ) ) + * + * } + * ``` + * + * [*] Assuming a target value of 400dpi and available strike sizes 100, + * 200, 300, and 400dpi, a possible order might be [400, 200, 300, 100]: + * scaling 200dpi to 400dpi usually gives better results than scaling + * 300dpi to 400dpi; it is also much faster. However, scaling 100dpi to + * 400dpi can yield a too pixelated result, thus the preference might be + * 300dpi over 100dpi. + * + * @since: + * 2.12 + */ +#define FT_HAS_SBIX( face ) \ + ( !!( (face)->face_flags & FT_FACE_FLAG_SBIX ) ) + + + /************************************************************************** + * + * @macro: + * FT_HAS_SBIX_OVERLAY + * + * @description: + * A macro that returns true whenever a face object contains an 'sbix' + * OpenType table with bit~1 in its `flags` field set, instructing the + * application to overlay the bitmap strike with the corresponding + * outline glyph. See @FT_HAS_SBIX for pseudo code how to use it. + * + * @since: + * 2.12 + */ +#define FT_HAS_SBIX_OVERLAY( face ) \ + ( !!( (face)->face_flags & FT_FACE_FLAG_SBIX_OVERLAY ) ) + + + /************************************************************************** + * + * @section: + * face_creation + * + */ + /************************************************************************** * * @enum: @@ -1476,6 +1837,13 @@ FT_BEGIN_HEADER #define FT_STYLE_FLAG_BOLD ( 1 << 1 ) + /************************************************************************** + * + * @section: + * other_api_data + * + */ + /************************************************************************** * * @type: @@ -1488,6 +1856,13 @@ FT_BEGIN_HEADER typedef struct FT_Size_InternalRec_* FT_Size_Internal; + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + */ + /************************************************************************** * * @struct: @@ -1639,6 +2014,13 @@ FT_BEGIN_HEADER } FT_SizeRec; + /************************************************************************** + * + * @section: + * other_api_data + * + */ + /************************************************************************** * * @struct: @@ -1670,6 +2052,13 @@ FT_BEGIN_HEADER typedef struct FT_Slot_InternalRec_* FT_Slot_Internal; + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @struct: @@ -1714,13 +2103,13 @@ FT_BEGIN_HEADER * The advance width of the unhinted glyph. Its value is expressed in * 16.16 fractional pixels, unless @FT_LOAD_LINEAR_DESIGN is set when * loading the glyph. This field can be important to perform correct - * WYSIWYG layout. Only relevant for outline glyphs. + * WYSIWYG layout. Only relevant for scalable glyphs. * * linearVertAdvance :: * The advance height of the unhinted glyph. Its value is expressed in * 16.16 fractional pixels, unless @FT_LOAD_LINEAR_DESIGN is set when * loading the glyph. This field can be important to perform correct - * WYSIWYG layout. Only relevant for outline glyphs. + * WYSIWYG layout. Only relevant for scalable glyphs. * * advance :: * This shorthand is, depending on @FT_LOAD_IGNORE_TRANSFORM, the @@ -1914,6 +2303,13 @@ FT_BEGIN_HEADER /*************************************************************************/ + /************************************************************************** + * + * @section: + * library_setup + * + */ + /************************************************************************** * * @function: @@ -1971,6 +2367,13 @@ FT_BEGIN_HEADER FT_Done_FreeType( FT_Library library ); + /************************************************************************** + * + * @section: + * face_creation + * + */ + /************************************************************************** * * @enum: @@ -2065,7 +2468,8 @@ FT_BEGIN_HEADER * The size in bytes of the file in memory. * * pathname :: - * A pointer to an 8-bit file pathname. The pointer is not owned by + * A pointer to an 8-bit file pathname, which must be a C~string (i.e., + * no null bytes except at the very end). The pointer is not owned by * FreeType. * * stream :: @@ -2084,8 +2488,7 @@ FT_BEGIN_HEADER * Extra parameters passed to the font driver when opening a new face. * * @note: - * The stream type is determined by the contents of `flags` that are - * tested in the following order by @FT_Open_Face: + * The stream type is determined by the contents of `flags`: * * If the @FT_OPEN_MEMORY bit is set, assume that this is a memory file * of `memory_size` bytes, located at `memory_address`. The data are not @@ -2098,6 +2501,9 @@ FT_BEGIN_HEADER * Otherwise, if the @FT_OPEN_PATHNAME bit is set, assume that this is a * normal file and use `pathname` to open it. * + * If none of the above bits are set or if multiple are set at the same + * time, the flags are invalid and @FT_Open_Face fails. + * * If the @FT_OPEN_DRIVER bit is set, @FT_Open_Face only tries to open * the file with the driver whose handler is in `driver`. * @@ -2150,6 +2556,13 @@ FT_BEGIN_HEADER * FreeType error code. 0~means success. * * @note: + * The `pathname` string should be recognizable as such by a standard + * `fopen` call on your system; in particular, this means that `pathname` + * must not contain null bytes. If that is not sufficient to address all + * file name possibilities (for example, to handle wide character file + * names on Windows in UTF-16 encoding) you might use @FT_Open_Face to + * pass a memory array or a stream object instead. + * * Use @FT_Done_Face to destroy the created @FT_Face object (along with * its slot and sizes). */ @@ -2263,13 +2676,17 @@ FT_BEGIN_HEADER * Each new face object created with this function also owns a default * @FT_Size object, accessible as `face->size`. * - * One @FT_Library instance can have multiple face objects, this is, + * One @FT_Library instance can have multiple face objects, that is, * @FT_Open_Face and its siblings can be called multiple times using the * same `library` argument. * * See the discussion of reference counters in the description of * @FT_Reference_Face. * + * If `FT_OPEN_STREAM` is set in `args->flags`, the stream in + * `args->stream` is automatically closed before this function returns + * any error (including `FT_Err_Invalid_Argument`). + * * @example: * To loop over all faces, use code similar to the following snippet * (omitting the error handling). @@ -2401,8 +2818,8 @@ FT_BEGIN_HEADER * stream attachments. */ FT_EXPORT( FT_Error ) - FT_Attach_Stream( FT_Face face, - FT_Open_Args* parameters ); + FT_Attach_Stream( FT_Face face, + const FT_Open_Args* parameters ); /************************************************************************** @@ -2428,6 +2845,7 @@ FT_BEGIN_HEADER * * @since: * 2.4.2 + * */ FT_EXPORT( FT_Error ) FT_Reference_Face( FT_Face face ); @@ -2457,6 +2875,13 @@ FT_BEGIN_HEADER FT_Done_Face( FT_Face face ); + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + */ + /************************************************************************** * * @function: @@ -2486,7 +2911,7 @@ FT_BEGIN_HEADER * silently uses outlines if there is no bitmap for a given glyph index. * * For GX and OpenType variation fonts, a bitmap strike makes sense only - * if the default instance is active (this is, no glyph variation takes + * if the default instance is active (that is, no glyph variation takes * place); otherwise, FreeType simply ignores bitmap strikes. The same * is true for all named instances that are different from the default * instance. @@ -2652,8 +3077,8 @@ FT_BEGIN_HEADER * 'https://www.freetype.org/freetype2/docs/glyphs/glyphs-2.html'. * * Contrary to @FT_Set_Char_Size, this function doesn't have special code - * to normalize zero-valued widths, heights, or resolutions (which lead - * to errors in most cases). + * to normalize zero-valued widths, heights, or resolutions, which are + * treated as @FT_LOAD_NO_SCALE. * * Don't use this function if you are using the FreeType cache API. */ @@ -2749,6 +3174,13 @@ FT_BEGIN_HEADER FT_UInt pixel_height ); + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @function: @@ -2769,7 +3201,7 @@ FT_BEGIN_HEADER * * load_flags :: * A flag indicating what to load for this glyph. The @FT_LOAD_XXX - * constants can be used to control the glyph loading process (e.g., + * flags can be used to control the glyph loading process (e.g., * whether the outline should be scaled, whether to load bitmaps or * not, whether to hint the outline, etc). * @@ -2777,11 +3209,13 @@ FT_BEGIN_HEADER * FreeType error code. 0~means success. * * @note: - * The loaded glyph may be transformed. See @FT_Set_Transform for the - * details. + * For proper scaling and hinting, the active @FT_Size object owned by + * the face has to be meaningfully initialized by calling + * @FT_Set_Char_Size before this function, for example. The loaded + * glyph may be transformed. See @FT_Set_Transform for the details. * * For subsetted CID-keyed fonts, `FT_Err_Invalid_Argument` is returned - * for invalid CID values (this is, for CID values that don't have a + * for invalid CID values (that is, for CID values that don't have a * corresponding glyph in the font). See the discussion of the * @FT_FACE_FLAG_CID_KEYED flag for more details. * @@ -2795,6 +3229,13 @@ FT_BEGIN_HEADER FT_Int32 load_flags ); + /************************************************************************** + * + * @section: + * character_mapping + * + */ + /************************************************************************** * * @function: @@ -2838,6 +3279,13 @@ FT_BEGIN_HEADER FT_Int32 load_flags ); + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @enum: @@ -2868,19 +3316,21 @@ FT_BEGIN_HEADER * * FT_LOAD_NO_SCALE :: * Don't scale the loaded outline glyph but keep it in font units. + * This flag is also assumed if @FT_Size owned by the face was not + * properly initialized. * * This flag implies @FT_LOAD_NO_HINTING and @FT_LOAD_NO_BITMAP, and * unsets @FT_LOAD_RENDER. * * If the font is 'tricky' (see @FT_FACE_FLAG_TRICKY for more), using * `FT_LOAD_NO_SCALE` usually yields meaningless outlines because the - * subglyphs must be scaled and positioned with hinting instructions. + * subglyphs must be scaled and positioned with hinting instructions. * This can be solved by loading the font without `FT_LOAD_NO_SCALE` * and setting the character size to `font->units_per_EM`. * * FT_LOAD_NO_HINTING :: * Disable hinting. This generally generates 'blurrier' bitmap glyphs - * when the glyph are rendered in any of the anti-aliased modes. See + * when the glyphs are rendered in any of the anti-aliased modes. See * also the note below. * * This flag is implied by @FT_LOAD_NO_SCALE. @@ -2898,6 +3348,15 @@ FT_BEGIN_HEADER * * @FT_LOAD_NO_SCALE always sets this flag. * + * FT_LOAD_SBITS_ONLY :: + * [Since 2.12] This is the opposite of @FT_LOAD_NO_BITMAP, more or + * less: @FT_Load_Glyph returns `FT_Err_Invalid_Argument` if the face + * contains a bitmap strike for the given size (or the strike selected + * by @FT_Select_Size) but there is no glyph in the strike. + * + * Note that this load flag was part of FreeType since version 2.0.6 + * but previously tagged as internal. + * * FT_LOAD_VERTICAL_LAYOUT :: * Load the glyph for vertical text layout. In particular, the * `advance` value in the @FT_GlyphSlotRec structure is set to the @@ -2954,25 +3413,39 @@ FT_BEGIN_HEADER * Disable the auto-hinter. See also the note below. * * FT_LOAD_COLOR :: - * Load colored glyphs. There are slight differences depending on the - * font format. + * Load colored glyphs. FreeType searches in the following order; + * there are slight differences depending on the font format. * - * [Since 2.5] Load embedded color bitmap images. The resulting color - * bitmaps, if available, will have the @FT_PIXEL_MODE_BGRA format, - * with pre-multiplied color channels. If the flag is not set and - * color bitmaps are found, they are converted to 256-level gray - * bitmaps, using the @FT_PIXEL_MODE_GRAY format. + * [Since 2.5] Load embedded color bitmap images (provided + * @FT_LOAD_NO_BITMAP is not set). The resulting color bitmaps, if + * available, have the @FT_PIXEL_MODE_BGRA format, with pre-multiplied + * color channels. If the flag is not set and color bitmaps are found, + * they are converted to 256-level gray bitmaps, using the + * @FT_PIXEL_MODE_GRAY format. * - * [Since 2.10, experimental] If the glyph index contains an entry in + * [Since 2.12] If the glyph index maps to an entry in the face's + * 'SVG~' table, load the associated SVG document from this table and + * set the `format` field of @FT_GlyphSlotRec to @FT_GLYPH_FORMAT_SVG + * ([since 2.13.1] provided @FT_LOAD_NO_SVG is not set). Note that + * FreeType itself can't render SVG documents; however, the library + * provides hooks to seamlessly integrate an external renderer. See + * sections @ot_svg_driver and @svg_fonts for more. + * + * [Since 2.10, experimental] If the glyph index maps to an entry in * the face's 'COLR' table with a 'CPAL' palette table (as defined in * the OpenType specification), make @FT_Render_Glyph provide a default * blending of the color glyph layers associated with the glyph index, * using the same bitmap format as embedded color bitmap images. This - * is mainly for convenience; for full control of color layers use + * is mainly for convenience and works only for glyphs in 'COLR' v0 + * tables (or glyphs in 'COLR' v1 tables that exclusively use v0 + * features). For full control of color layers use * @FT_Get_Color_Glyph_Layer and FreeType's color functions like * @FT_Palette_Select instead of setting @FT_LOAD_COLOR for rendering * so that the client application can handle blending by itself. * + * FT_LOAD_NO_SVG :: + * [Since 2.13.1] Ignore SVG glyph data when loading. + * * FT_LOAD_COMPUTE_METRICS :: * [Since 2.6.1] Compute glyph metrics from the glyph data, without the * use of bundled metrics tables (for example, the 'hdmx' table in @@ -3019,30 +3492,32 @@ FT_BEGIN_HEADER * */ #define FT_LOAD_DEFAULT 0x0 -#define FT_LOAD_NO_SCALE ( 1L << 0 ) -#define FT_LOAD_NO_HINTING ( 1L << 1 ) -#define FT_LOAD_RENDER ( 1L << 2 ) -#define FT_LOAD_NO_BITMAP ( 1L << 3 ) -#define FT_LOAD_VERTICAL_LAYOUT ( 1L << 4 ) -#define FT_LOAD_FORCE_AUTOHINT ( 1L << 5 ) -#define FT_LOAD_CROP_BITMAP ( 1L << 6 ) -#define FT_LOAD_PEDANTIC ( 1L << 7 ) -#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ( 1L << 9 ) +#define FT_LOAD_NO_SCALE ( 1L << 0 ) +#define FT_LOAD_NO_HINTING ( 1L << 1 ) +#define FT_LOAD_RENDER ( 1L << 2 ) +#define FT_LOAD_NO_BITMAP ( 1L << 3 ) +#define FT_LOAD_VERTICAL_LAYOUT ( 1L << 4 ) +#define FT_LOAD_FORCE_AUTOHINT ( 1L << 5 ) +#define FT_LOAD_CROP_BITMAP ( 1L << 6 ) +#define FT_LOAD_PEDANTIC ( 1L << 7 ) +#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ( 1L << 9 ) #define FT_LOAD_NO_RECURSE ( 1L << 10 ) #define FT_LOAD_IGNORE_TRANSFORM ( 1L << 11 ) #define FT_LOAD_MONOCHROME ( 1L << 12 ) #define FT_LOAD_LINEAR_DESIGN ( 1L << 13 ) +#define FT_LOAD_SBITS_ONLY ( 1L << 14 ) #define FT_LOAD_NO_AUTOHINT ( 1L << 15 ) /* Bits 16-19 are used by `FT_LOAD_TARGET_` */ #define FT_LOAD_COLOR ( 1L << 20 ) #define FT_LOAD_COMPUTE_METRICS ( 1L << 21 ) #define FT_LOAD_BITMAP_METRICS_ONLY ( 1L << 22 ) +#define FT_LOAD_NO_SVG ( 1L << 24 ) /* */ /* used internally only by certain font drivers */ -#define FT_LOAD_ADVANCE_ONLY ( 1L << 8 ) -#define FT_LOAD_SBITS_ONLY ( 1L << 14 ) +#define FT_LOAD_ADVANCE_ONLY ( 1L << 8 ) +#define FT_LOAD_SVG_ONLY ( 1L << 23 ) /************************************************************************** @@ -3132,7 +3607,7 @@ FT_BEGIN_HEADER * necessary to empty the cache after a mode switch to avoid false hits. * */ -#define FT_LOAD_TARGET_( x ) ( (FT_Int32)( (x) & 15 ) << 16 ) +#define FT_LOAD_TARGET_( x ) ( FT_STATIC_CAST( FT_Int32, (x) & 15 ) << 16 ) #define FT_LOAD_TARGET_NORMAL FT_LOAD_TARGET_( FT_RENDER_MODE_NORMAL ) #define FT_LOAD_TARGET_LIGHT FT_LOAD_TARGET_( FT_RENDER_MODE_LIGHT ) @@ -3151,9 +3626,17 @@ FT_BEGIN_HEADER * @FT_LOAD_TARGET_XXX value. * */ -#define FT_LOAD_TARGET_MODE( x ) ( (FT_Render_Mode)( ( (x) >> 16 ) & 15 ) ) +#define FT_LOAD_TARGET_MODE( x ) \ + FT_STATIC_CAST( FT_Render_Mode, ( (x) >> 16 ) & 15 ) + /************************************************************************** + * + * @section: + * sizing_and_scaling + * + */ + /************************************************************************** * * @function: @@ -3172,11 +3655,12 @@ FT_BEGIN_HEADER * A pointer to the transformation's 2x2 matrix. Use `NULL` for the * identity matrix. * delta :: - * A pointer to the translation vector. Use `NULL` for the null vector. + * A pointer to the translation vector. Use `NULL` for the null + * vector. * * @note: * This function is provided as a convenience, but keep in mind that - * @FT_Matrix coefficients are only 16.16 fixed point values, which can + * @FT_Matrix coefficients are only 16.16 fixed-point values, which can * limit the accuracy of the results. Using floating-point computations * to perform the transform directly in client code instead will always * yield better numbers. @@ -3195,6 +3679,46 @@ FT_BEGIN_HEADER FT_Vector* delta ); + /************************************************************************** + * + * @function: + * FT_Get_Transform + * + * @description: + * Return the transformation that is applied to glyph images when they + * are loaded into a glyph slot through @FT_Load_Glyph. See + * @FT_Set_Transform for more details. + * + * @input: + * face :: + * A handle to the source face object. + * + * @output: + * matrix :: + * A pointer to a transformation's 2x2 matrix. Set this to NULL if you + * are not interested in the value. + * + * delta :: + * A pointer to a translation vector. Set this to NULL if you are not + * interested in the value. + * + * @since: + * 2.11 + * + */ + FT_EXPORT( void ) + FT_Get_Transform( FT_Face face, + FT_Matrix* matrix, + FT_Vector* delta ); + + + /************************************************************************** + * + * @section: + * glyph_retrieval + * + */ + /************************************************************************** * * @enum: @@ -3213,6 +3737,10 @@ FT_BEGIN_HEADER * correction to correctly render non-monochrome glyph bitmaps onto a * surface; see @FT_Render_Glyph. * + * The @FT_RENDER_MODE_SDF is a special render mode that uses up to 256 + * distance values, indicating the signed distance from the grid position + * to the nearest outline. + * * @values: * FT_RENDER_MODE_NORMAL :: * Default render mode; it corresponds to 8-bit anti-aliased bitmaps. @@ -3238,11 +3766,88 @@ FT_BEGIN_HEADER * bitmaps that are 3~times the height of the original glyph outline in * pixels and use the @FT_PIXEL_MODE_LCD_V mode. * + * FT_RENDER_MODE_SDF :: + * This mode corresponds to 8-bit, single-channel signed distance field + * (SDF) bitmaps. Each pixel in the SDF grid is the value from the + * pixel's position to the nearest glyph's outline. The distances are + * calculated from the center of the pixel and are positive if they are + * filled by the outline (i.e., inside the outline) and negative + * otherwise. Check the note below on how to convert the output values + * to usable data. + * * @note: * The selected render mode only affects vector glyphs of a font. * Embedded bitmaps often have a different pixel mode like * @FT_PIXEL_MODE_MONO. You can use @FT_Bitmap_Convert to transform them * into 8-bit pixmaps. + * + * For @FT_RENDER_MODE_SDF the output bitmap buffer contains normalized + * distances that are packed into unsigned 8-bit values. To get pixel + * values in floating point representation use the following pseudo-C + * code for the conversion. + * + * ``` + * // Load glyph and render using FT_RENDER_MODE_SDF, + * // then use the output buffer as follows. + * + * ... + * FT_Byte buffer = glyph->bitmap->buffer; + * + * + * for pixel in buffer + * { + * // `sd` is the signed distance and `spread` is the current spread; + * // the default spread is 2 and can be changed. + * + * float sd = (float)pixel - 128.0f; + * + * + * // Convert to pixel values. + * sd = ( sd / 128.0f ) * spread; + * + * // Store `sd` in a buffer or use as required. + * } + * + * ``` + * + * FreeType has two rasterizers for generating SDF, namely: + * + * 1. `sdf` for generating SDF directly from glyph's outline, and + * + * 2. `bsdf` for generating SDF from rasterized bitmaps. + * + * Depending on the glyph type (i.e., outline or bitmap), one of the two + * rasterizers is chosen at runtime and used for generating SDFs. To + * force the use of `bsdf` you should render the glyph with any of the + * FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and + * then re-render with `FT_RENDER_MODE_SDF`. + * + * There are some issues with stability and possible failures of the SDF + * renderers (specifically `sdf`). + * + * 1. The `sdf` rasterizer is sensitive to really small features (e.g., + * sharp turns that are less than 1~pixel) and imperfections in the + * glyph's outline, causing artifacts in the final output. + * + * 2. The `sdf` rasterizer has limited support for handling intersecting + * contours and *cannot* handle self-intersecting contours whatsoever. + * Self-intersection happens when a single connected contour + * intersects itself at some point; having these in your font + * definitely poses a problem to the rasterizer and cause artifacts, + * too. + * + * 3. Generating SDF for really small glyphs may result in undesirable + * output; the pixel grid (which stores distance information) becomes + * too coarse. + * + * 4. Since the output buffer is normalized, precision at smaller spreads + * is greater than precision at larger spread values because the + * output range of [0..255] gets mapped to a smaller SDF range. A + * spread of~2 should be sufficient in most cases. + * + * Points (1) and (2) can be avoided by using the `bsdf` rasterizer, + * which is more stable than the `sdf` rasterizer in general. + * */ typedef enum FT_Render_Mode_ { @@ -3251,6 +3856,7 @@ FT_BEGIN_HEADER FT_RENDER_MODE_MONO, FT_RENDER_MODE_LCD, FT_RENDER_MODE_LCD_V, + FT_RENDER_MODE_SDF, FT_RENDER_MODE_MAX @@ -3282,7 +3888,7 @@ FT_BEGIN_HEADER * @FT_Render_Mode for a list of possible values. * * If @FT_RENDER_MODE_NORMAL is used, a previous call of @FT_Load_Glyph - * with flag @FT_LOAD_COLOR makes FT_Render_Glyph provide a default + * with flag @FT_LOAD_COLOR makes `FT_Render_Glyph` provide a default * blending of colored glyph layers associated with the current glyph * slot (provided the font contains such layers) instead of rendering * the glyph slot's outline. This is an experimental feature; see @@ -3292,9 +3898,6 @@ FT_BEGIN_HEADER * FreeType error code. 0~means success. * * @note: - * To get meaningful results, font scaling values must be set with - * functions like @FT_Set_Char_Size before calling `FT_Render_Glyph`. - * * When FreeType outputs a bitmap of a glyph, it really outputs an alpha * coverage map. If a pixel is completely covered by a filled-in * outline, the bitmap contains 0xFF at that pixel, meaning that @@ -3338,7 +3941,8 @@ FT_BEGIN_HEADER * * which is known as the OVER operator. * - * To correctly composite an antialiased pixel of a glyph onto a surface, + * To correctly composite an anti-aliased pixel of a glyph onto a + * surface, * * 1. take the foreground and background colors (e.g., in sRGB space) * and apply gamma to get them in a linear space, @@ -3511,86 +4115,10 @@ FT_BEGIN_HEADER /************************************************************************** * - * @function: - * FT_Get_Glyph_Name + * @section: + * character_mapping * - * @description: - * Retrieve the ASCII name of a given glyph in a face. This only works - * for those faces where @FT_HAS_GLYPH_NAMES(face) returns~1. - * - * @input: - * face :: - * A handle to a source face object. - * - * glyph_index :: - * The glyph index. - * - * buffer_max :: - * The maximum number of bytes available in the buffer. - * - * @output: - * buffer :: - * A pointer to a target buffer where the name is copied to. - * - * @return: - * FreeType error code. 0~means success. - * - * @note: - * An error is returned if the face doesn't provide glyph names or if the - * glyph index is invalid. In all cases of failure, the first byte of - * `buffer` is set to~0 to indicate an empty name. - * - * The glyph name is truncated to fit within the buffer if it is too - * long. The returned string is always zero-terminated. - * - * Be aware that FreeType reorders glyph indices internally so that glyph - * index~0 always corresponds to the 'missing glyph' (called '.notdef'). - * - * This function always returns an error if the config macro - * `FT_CONFIG_OPTION_NO_GLYPH_NAMES` is not defined in `ftoption.h`. */ - FT_EXPORT( FT_Error ) - FT_Get_Glyph_Name( FT_Face face, - FT_UInt glyph_index, - FT_Pointer buffer, - FT_UInt buffer_max ); - - - /************************************************************************** - * - * @function: - * FT_Get_Postscript_Name - * - * @description: - * Retrieve the ASCII PostScript name of a given face, if available. - * This only works with PostScript, TrueType, and OpenType fonts. - * - * @input: - * face :: - * A handle to the source face object. - * - * @return: - * A pointer to the face's PostScript name. `NULL` if unavailable. - * - * @note: - * The returned pointer is owned by the face and is destroyed with it. - * - * For variation fonts, this string changes if you select a different - * instance, and you have to call `FT_Get_PostScript_Name` again to - * retrieve it. FreeType follows Adobe TechNote #5902, 'Generating - * PostScript Names for Fonts Using OpenType Font Variations'. - * - * https://download.macromedia.com/pub/developer/opentype/tech-notes/5902.AdobePSNameGeneration.html - * - * [Since 2.9] Special PostScript names for named instances are only - * returned if the named instance is set with @FT_Set_Named_Instance (and - * the font has corresponding entries in its 'fvar' table). If - * @FT_IS_VARIATION returns true, the algorithmically derived PostScript - * name is provided, not looking up special entries for named instances. - */ - FT_EXPORT( const char* ) - FT_Get_Postscript_Name( FT_Face face ); - /************************************************************************** * @@ -3808,6 +4336,13 @@ FT_BEGIN_HEADER FT_UInt *agindex ); + /************************************************************************** + * + * @section: + * face_creation + * + */ + /************************************************************************** * * @function: @@ -3906,13 +4441,21 @@ FT_BEGIN_HEADER FT_Parameter* properties ); + /************************************************************************** + * + * @section: + * information_retrieval + * + */ + /************************************************************************** * * @function: * FT_Get_Name_Index * * @description: - * Return the glyph index of a given glyph name. + * Return the glyph index of a given glyph name. This only works + * for those faces where @FT_HAS_GLYPH_NAMES returns true. * * @input: * face :: @@ -3923,12 +4466,108 @@ FT_BEGIN_HEADER * * @return: * The glyph index. 0~means 'undefined character code'. + * + * @note: + * Acceptable glyph names might come from the [Adobe Glyph + * List](https://github.com/adobe-type-tools/agl-aglfn). See + * @FT_Get_Glyph_Name for the inverse functionality. + * + * This function has limited capabilities if the config macro + * `FT_CONFIG_OPTION_POSTSCRIPT_NAMES` is not defined in `ftoption.h`: + * It then works only for fonts that actually embed glyph names (which + * many recent OpenType fonts do not). */ FT_EXPORT( FT_UInt ) FT_Get_Name_Index( FT_Face face, const FT_String* glyph_name ); + /************************************************************************** + * + * @function: + * FT_Get_Glyph_Name + * + * @description: + * Retrieve the ASCII name of a given glyph in a face. This only works + * for those faces where @FT_HAS_GLYPH_NAMES returns true. + * + * @input: + * face :: + * A handle to a source face object. + * + * glyph_index :: + * The glyph index. + * + * buffer_max :: + * The maximum number of bytes available in the buffer. + * + * @output: + * buffer :: + * A pointer to a target buffer where the name is copied to. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * An error is returned if the face doesn't provide glyph names or if the + * glyph index is invalid. In all cases of failure, the first byte of + * `buffer` is set to~0 to indicate an empty name. + * + * The glyph name is truncated to fit within the buffer if it is too + * long. The returned string is always zero-terminated. + * + * Be aware that FreeType reorders glyph indices internally so that glyph + * index~0 always corresponds to the 'missing glyph' (called '.notdef'). + * + * This function has limited capabilities if the config macro + * `FT_CONFIG_OPTION_POSTSCRIPT_NAMES` is not defined in `ftoption.h`: + * It then works only for fonts that actually embed glyph names (which + * many recent OpenType fonts do not). + */ + FT_EXPORT( FT_Error ) + FT_Get_Glyph_Name( FT_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ); + + + /************************************************************************** + * + * @function: + * FT_Get_Postscript_Name + * + * @description: + * Retrieve the ASCII PostScript name of a given face, if available. + * This only works with PostScript, TrueType, and OpenType fonts. + * + * @input: + * face :: + * A handle to the source face object. + * + * @return: + * A pointer to the face's PostScript name. `NULL` if unavailable. + * + * @note: + * The returned pointer is owned by the face and is destroyed with it. + * + * For variation fonts, this string changes if you select a different + * instance, and you have to call `FT_Get_PostScript_Name` again to + * retrieve it. FreeType follows Adobe TechNote #5902, 'Generating + * PostScript Names for Fonts Using OpenType Font Variations'. + * + * https://download.macromedia.com/pub/developer/opentype/tech-notes/5902.AdobePSNameGeneration.html + * + * [Since 2.9] Special PostScript names for named instances are only + * returned if the named instance is set with @FT_Set_Named_Instance (and + * the font has corresponding entries in its 'fvar' table or is the + * default named instance). If @FT_IS_VARIATION returns true, the + * algorithmically derived PostScript name is provided, not looking up + * special entries for named instances. + */ + FT_EXPORT( const char* ) + FT_Get_Postscript_Name( FT_Face face ); + + /************************************************************************** * * @enum: @@ -4015,175 +4654,6 @@ FT_BEGIN_HEADER FT_Matrix *p_transform ); - /************************************************************************** - * - * @section: - * layer_management - * - * @title: - * Glyph Layer Management - * - * @abstract: - * Retrieving and manipulating OpenType's 'COLR' table data. - * - * @description: - * The functions described here allow access of colored glyph layer data - * in OpenType's 'COLR' tables. - */ - - - /************************************************************************** - * - * @struct: - * FT_LayerIterator - * - * @description: - * This iterator object is needed for @FT_Get_Color_Glyph_Layer. - * - * @fields: - * num_layers :: - * The number of glyph layers for the requested glyph index. Will be - * set by @FT_Get_Color_Glyph_Layer. - * - * layer :: - * The current layer. Will be set by @FT_Get_Color_Glyph_Layer. - * - * p :: - * An opaque pointer into 'COLR' table data. The caller must set this - * to `NULL` before the first call of @FT_Get_Color_Glyph_Layer. - */ - typedef struct FT_LayerIterator_ - { - FT_UInt num_layers; - FT_UInt layer; - FT_Byte* p; - - } FT_LayerIterator; - - - /************************************************************************** - * - * @function: - * FT_Get_Color_Glyph_Layer - * - * @description: - * This is an interface to the 'COLR' table in OpenType fonts to - * iteratively retrieve the colored glyph layers associated with the - * current glyph slot. - * - * https://docs.microsoft.com/en-us/typography/opentype/spec/colr - * - * The glyph layer data for a given glyph index, if present, provides an - * alternative, multi-color glyph representation: Instead of rendering - * the outline or bitmap with the given glyph index, glyphs with the - * indices and colors returned by this function are rendered layer by - * layer. - * - * The returned elements are ordered in the z~direction from bottom to - * top; the 'n'th element should be rendered with the associated palette - * color and blended on top of the already rendered layers (elements 0, - * 1, ..., n-1). - * - * @input: - * face :: - * A handle to the parent face object. - * - * base_glyph :: - * The glyph index the colored glyph layers are associated with. - * - * @inout: - * iterator :: - * An @FT_LayerIterator object. For the first call you should set - * `iterator->p` to `NULL`. For all following calls, simply use the - * same object again. - * - * @output: - * aglyph_index :: - * The glyph index of the current layer. - * - * acolor_index :: - * The color index into the font face's color palette of the current - * layer. The value 0xFFFF is special; it doesn't reference a palette - * entry but indicates that the text foreground color should be used - * instead (to be set up by the application outside of FreeType). - * - * The color palette can be retrieved with @FT_Palette_Select. - * - * @return: - * Value~1 if everything is OK. If there are no more layers (or if there - * are no layers at all), value~0 gets returned. In case of an error, - * value~0 is returned also. - * - * @note: - * This function is necessary if you want to handle glyph layers by - * yourself. In particular, functions that operate with @FT_GlyphRec - * objects (like @FT_Get_Glyph or @FT_Glyph_To_Bitmap) don't have access - * to this information. - * - * Note that @FT_Render_Glyph is able to handle colored glyph layers - * automatically if the @FT_LOAD_COLOR flag is passed to a previous call - * to @FT_Load_Glyph. [This is an experimental feature.] - * - * @example: - * ``` - * FT_Color* palette; - * FT_LayerIterator iterator; - * - * FT_Bool have_layers; - * FT_UInt layer_glyph_index; - * FT_UInt layer_color_index; - * - * - * error = FT_Palette_Select( face, palette_index, &palette ); - * if ( error ) - * palette = NULL; - * - * iterator.p = NULL; - * have_layers = FT_Get_Color_Glyph_Layer( face, - * glyph_index, - * &layer_glyph_index, - * &layer_color_index, - * &iterator ); - * - * if ( palette && have_layers ) - * { - * do - * { - * FT_Color layer_color; - * - * - * if ( layer_color_index == 0xFFFF ) - * layer_color = text_foreground_color; - * else - * layer_color = palette[layer_color_index]; - * - * // Load and render glyph `layer_glyph_index', then - * // blend resulting pixmap (using color `layer_color') - * // with previously created pixmaps. - * - * } while ( FT_Get_Color_Glyph_Layer( face, - * glyph_index, - * &layer_glyph_index, - * &layer_color_index, - * &iterator ) ); - * } - * ``` - */ - FT_EXPORT( FT_Bool ) - FT_Get_Color_Glyph_Layer( FT_Face face, - FT_UInt base_glyph, - FT_UInt *aglyph_index, - FT_UInt *acolor_index, - FT_LayerIterator* iterator ); - - - /************************************************************************** - * - * @section: - * base_interface - * - */ - /************************************************************************** * * @enum: @@ -4267,6 +4737,7 @@ FT_BEGIN_HEADER * * @since: * 2.3.8 + * */ FT_EXPORT( FT_UShort ) FT_Get_FSType_Flags( FT_Face face ); @@ -4360,6 +4831,7 @@ FT_BEGIN_HEADER * * @since: * 2.3.6 + * */ FT_EXPORT( FT_UInt ) FT_Face_GetCharVariantIndex( FT_Face face, @@ -4396,6 +4868,7 @@ FT_BEGIN_HEADER * * @since: * 2.3.6 + * */ FT_EXPORT( FT_Int ) FT_Face_GetCharVariantIsDefault( FT_Face face, @@ -4427,6 +4900,7 @@ FT_BEGIN_HEADER * * @since: * 2.3.6 + * */ FT_EXPORT( FT_UInt32* ) FT_Face_GetVariantSelectors( FT_Face face ); @@ -4460,6 +4934,7 @@ FT_BEGIN_HEADER * * @since: * 2.3.6 + * */ FT_EXPORT( FT_UInt32* ) FT_Face_GetVariantsOfChar( FT_Face face, @@ -4494,6 +4969,7 @@ FT_BEGIN_HEADER * * @since: * 2.3.6 + * */ FT_EXPORT( FT_UInt32* ) FT_Face_GetCharsOfVariant( FT_Face face, @@ -4513,7 +4989,8 @@ FT_BEGIN_HEADER * * @description: * This section contains various functions used to perform computations - * on 16.16 fixed-float numbers or 2d vectors. + * on 16.16 fixed-point numbers or 2D vectors. FreeType does not use + * floating-point data types. * * **Attention**: Most arithmetic functions take `FT_Long` as arguments. * For historical reasons, FreeType was designed under the assumption @@ -4717,32 +5194,10 @@ FT_BEGIN_HEADER /************************************************************************** * * @section: - * version - * - * @title: - * FreeType Version - * - * @abstract: - * Functions and macros related to FreeType versions. - * - * @description: - * Note that those functions and macros are of limited use because even a - * new release of FreeType with only documentation changes increases the - * version number. - * - * @order: - * FT_Library_Version - * - * FREETYPE_MAJOR - * FREETYPE_MINOR - * FREETYPE_PATCH - * - * FT_Face_CheckTrueTypePatents - * FT_Face_SetUnpatentedHinting + * library_setup * */ - /************************************************************************** * * @enum: @@ -4766,8 +5221,8 @@ FT_BEGIN_HEADER * */ #define FREETYPE_MAJOR 2 -#define FREETYPE_MINOR 10 -#define FREETYPE_PATCH 4 +#define FREETYPE_MINOR 13 +#define FREETYPE_PATCH 2 /************************************************************************** @@ -4809,6 +5264,13 @@ FT_BEGIN_HEADER FT_Int *apatch ); + /************************************************************************** + * + * @section: + * other_api_data + * + */ + /************************************************************************** * * @function: @@ -4829,6 +5291,7 @@ FT_BEGIN_HEADER * * @since: * 2.3.5 + * */ FT_EXPORT( FT_Bool ) FT_Face_CheckTrueTypePatents( FT_Face face ); @@ -4857,6 +5320,7 @@ FT_BEGIN_HEADER * * @since: * 2.3.5 + * */ FT_EXPORT( FT_Bool ) FT_Face_SetUnpatentedHinting( FT_Face face, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftadvanc.h b/lib/libesp32_lvgl/freetype/include/freetype/ftadvanc.h index f166bc6f9..4560ded6d 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftadvanc.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftadvanc.h @@ -4,7 +4,7 @@ * * Quick computation of advance widths (specification only). * - * Copyright (C) 2008-2020 by + * Copyright (C) 2008-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftbbox.h b/lib/libesp32_lvgl/freetype/include/freetype/ftbbox.h index fda1ad94a..fc21740fc 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftbbox.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftbbox.h @@ -4,7 +4,7 @@ * * FreeType exact bbox computation (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftbdf.h b/lib/libesp32_lvgl/freetype/include/freetype/ftbdf.h index 2e1daeeaa..e8ce64312 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftbdf.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftbdf.h @@ -4,7 +4,7 @@ * * FreeType API for accessing BDF-specific strings (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftbitmap.h b/lib/libesp32_lvgl/freetype/include/freetype/ftbitmap.h index 282c22e1c..eb6b4b1ee 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftbitmap.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftbitmap.h @@ -4,7 +4,7 @@ * * FreeType utility functions for bitmaps (specification). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftbzip2.h b/lib/libesp32_lvgl/freetype/include/freetype/ftbzip2.h index eb6a5a55d..7d29f4682 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftbzip2.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftbzip2.h @@ -4,7 +4,7 @@ * * Bzip2-compressed stream support. * - * Copyright (C) 2010-2020 by + * Copyright (C) 2010-2023 by * Joel Klinghed. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftcache.h b/lib/libesp32_lvgl/freetype/include/freetype/ftcache.h index 604727520..a2072e26b 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftcache.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftcache.h @@ -4,7 +4,7 @@ * * FreeType Cache subsystem (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -43,61 +43,61 @@ FT_BEGIN_HEADER * objects, as well as caching information like character maps and glyph * images while limiting their maximum memory usage. * - * Note that all types and functions begin with the `FTC_` prefix. + * Note that all types and functions begin with the `FTC_` prefix rather + * than the usual `FT_` prefix in the rest of FreeType. * - * The cache is highly portable and thus doesn't know anything about the - * fonts installed on your system, or how to access them. This implies - * the following scheme: + * The cache is highly portable and, thus, doesn't know anything about + * the fonts installed on your system, or how to access them. Therefore, + * it requires the following. * - * First, available or installed font faces are uniquely identified by - * @FTC_FaceID values, provided to the cache by the client. Note that - * the cache only stores and compares these values, and doesn't try to - * interpret them in any way. + * * @FTC_FaceID, an arbitrary non-zero value that uniquely identifies + * available or installed font faces, has to be provided to the + * cache by the client. Note that the cache only stores and compares + * these values and doesn't try to interpret them in any way, but they + * have to be persistent on the client side. * - * Second, the cache calls, only when needed, a client-provided function - * to convert an @FTC_FaceID into a new @FT_Face object. The latter is - * then completely managed by the cache, including its termination - * through @FT_Done_Face. To monitor termination of face objects, the - * finalizer callback in the `generic` field of the @FT_Face object can - * be used, which might also be used to store the @FTC_FaceID of the - * face. + * * @FTC_Face_Requester, a method to convert an @FTC_FaceID into a new + * @FT_Face object when necessary, has to be provided to the cache by + * the client. The @FT_Face object is completely managed by the cache, + * including its termination through @FT_Done_Face. To monitor + * termination of face objects, the finalizer callback in the `generic` + * field of the @FT_Face object can be used, which might also be used + * to store the @FTC_FaceID of the face. * - * Clients are free to map face IDs to anything else. The most simple - * usage is to associate them to a (pathname,face_index) pair that is - * used to call @FT_New_Face. However, more complex schemes are also - * possible. + * Clients are free to map face IDs to anything useful. The most simple + * usage is, for example, to associate them to a `{pathname,face_index}` + * pair that is then used by @FTC_Face_Requester to call @FT_New_Face. + * However, more complex schemes are also possible. * * Note that for the cache to work correctly, the face ID values must be * **persistent**, which means that the contents they point to should not * change at runtime, or that their value should not become invalid. - * * If this is unavoidable (e.g., when a font is uninstalled at runtime), - * you should call @FTC_Manager_RemoveFaceID as soon as possible, to let + * you should call @FTC_Manager_RemoveFaceID as soon as possible to let * the cache get rid of any references to the old @FTC_FaceID it may keep * internally. Failure to do so will lead to incorrect behaviour or even - * crashes. + * crashes in @FTC_Face_Requester. * * To use the cache, start with calling @FTC_Manager_New to create a new * @FTC_Manager object, which models a single cache instance. You can * then look up @FT_Face and @FT_Size objects with - * @FTC_Manager_LookupFace and @FTC_Manager_LookupSize, respectively. + * @FTC_Manager_LookupFace and @FTC_Manager_LookupSize, respectively, and + * use them in any FreeType work stream. You can also cache other + * FreeType objects as follows. * - * If you want to use the charmap caching, call @FTC_CMapCache_New, then - * later use @FTC_CMapCache_Lookup to perform the equivalent of - * @FT_Get_Char_Index, only much faster. + * * If you want to use the charmap caching, call @FTC_CMapCache_New, + * then later use @FTC_CMapCache_Lookup to perform the equivalent of + * @FT_Get_Char_Index, only much faster. * - * If you want to use the @FT_Glyph caching, call @FTC_ImageCache, then - * later use @FTC_ImageCache_Lookup to retrieve the corresponding - * @FT_Glyph objects from the cache. - * - * If you need lots of small bitmaps, it is much more memory efficient to - * call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This - * returns @FTC_SBitRec structures, which are used to store small bitmaps - * directly. (A small bitmap is one whose metrics and dimensions all fit - * into 8-bit integers). - * - * We hope to also provide a kerning cache in the near future. + * * If you want to use the @FT_Glyph caching, call @FTC_ImageCache_New, + * then later use @FTC_ImageCache_Lookup to retrieve the corresponding + * @FT_Glyph objects from the cache. * + * * If you need lots of small bitmaps, it is much more memory-efficient + * to call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This + * returns @FTC_SBitRec structures, which are used to store small + * bitmaps directly. (A small bitmap is one whose metrics and + * dimensions all fit into 8-bit integers). * * @order: * FTC_Manager @@ -424,7 +424,7 @@ FT_BEGIN_HEADER * pixel :: * A Boolean. If 1, the `width` and `height` fields are interpreted as * integer pixel character sizes. Otherwise, they are expressed as - * 1/64th of points. + * 1/64 of points. * * x_res :: * Only used when `pixel` is value~0 to indicate the horizontal diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftchapters.h b/lib/libesp32_lvgl/freetype/include/freetype/ftchapters.h index 2ee26973e..7566fbd10 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftchapters.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftchapters.h @@ -15,6 +15,7 @@ * General Remarks * * @sections: + * preamble * header_inclusion * user_allocation * @@ -30,9 +31,28 @@ * Core API * * @sections: - * version * basic_types - * base_interface + * library_setup + * face_creation + * font_testing_macros + * sizing_and_scaling + * glyph_retrieval + * character_mapping + * information_retrieval + * other_api_data + * + */ + + + /************************************************************************** + * + * @chapter: + * extended_api + * + * @title: + * Extended API + * + * @sections: * glyph_variants * color_management * layer_management @@ -61,6 +81,7 @@ * cid_fonts * pfr_fonts * winfnt_fonts + * svg_fonts * font_formats * gasp_table * @@ -81,6 +102,7 @@ * t1_cid_driver * tt_driver * pcf_driver + * ot_svg_driver * properties * parameter_tags * lcd_rendering @@ -123,6 +145,7 @@ * gzip * lzw * bzip2 + * debugging_apis * */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftcid.h b/lib/libesp32_lvgl/freetype/include/freetype/ftcid.h index a29fb3330..ef2293902 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftcid.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftcid.h @@ -4,7 +4,7 @@ * * FreeType API for accessing CID font information (specification). * - * Copyright (C) 2007-2020 by + * Copyright (C) 2007-2023 by * Dereg Clegg and Michael Toftdal. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftcolor.h b/lib/libesp32_lvgl/freetype/include/freetype/ftcolor.h index ecc6485e5..eae200fdf 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftcolor.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftcolor.h @@ -4,7 +4,7 @@ * * FreeType's glyph color management (specification). * - * Copyright (C) 2018-2020 by + * Copyright (C) 2018-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -302,6 +302,1360 @@ FT_BEGIN_HEADER FT_Palette_Set_Foreground_Color( FT_Face face, FT_Color foreground_color ); + + /************************************************************************** + * + * @section: + * layer_management + * + * @title: + * Glyph Layer Management + * + * @abstract: + * Retrieving and manipulating OpenType's 'COLR' table data. + * + * @description: + * The functions described here allow access of colored glyph layer data + * in OpenType's 'COLR' tables. + */ + + + /************************************************************************** + * + * @struct: + * FT_LayerIterator + * + * @description: + * This iterator object is needed for @FT_Get_Color_Glyph_Layer. + * + * @fields: + * num_layers :: + * The number of glyph layers for the requested glyph index. Will be + * set by @FT_Get_Color_Glyph_Layer. + * + * layer :: + * The current layer. Will be set by @FT_Get_Color_Glyph_Layer. + * + * p :: + * An opaque pointer into 'COLR' table data. The caller must set this + * to `NULL` before the first call of @FT_Get_Color_Glyph_Layer. + */ + typedef struct FT_LayerIterator_ + { + FT_UInt num_layers; + FT_UInt layer; + FT_Byte* p; + + } FT_LayerIterator; + + + /************************************************************************** + * + * @function: + * FT_Get_Color_Glyph_Layer + * + * @description: + * This is an interface to the 'COLR' table in OpenType fonts to + * iteratively retrieve the colored glyph layers associated with the + * current glyph slot. + * + * https://docs.microsoft.com/en-us/typography/opentype/spec/colr + * + * The glyph layer data for a given glyph index, if present, provides an + * alternative, multi-color glyph representation: Instead of rendering + * the outline or bitmap with the given glyph index, glyphs with the + * indices and colors returned by this function are rendered layer by + * layer. + * + * The returned elements are ordered in the z~direction from bottom to + * top; the 'n'th element should be rendered with the associated palette + * color and blended on top of the already rendered layers (elements 0, + * 1, ..., n-1). + * + * @input: + * face :: + * A handle to the parent face object. + * + * base_glyph :: + * The glyph index the colored glyph layers are associated with. + * + * @inout: + * iterator :: + * An @FT_LayerIterator object. For the first call you should set + * `iterator->p` to `NULL`. For all following calls, simply use the + * same object again. + * + * @output: + * aglyph_index :: + * The glyph index of the current layer. + * + * acolor_index :: + * The color index into the font face's color palette of the current + * layer. The value 0xFFFF is special; it doesn't reference a palette + * entry but indicates that the text foreground color should be used + * instead (to be set up by the application outside of FreeType). + * + * The color palette can be retrieved with @FT_Palette_Select. + * + * @return: + * Value~1 if everything is OK. If there are no more layers (or if there + * are no layers at all), value~0 gets returned. In case of an error, + * value~0 is returned also. + * + * @note: + * This function is necessary if you want to handle glyph layers by + * yourself. In particular, functions that operate with @FT_GlyphRec + * objects (like @FT_Get_Glyph or @FT_Glyph_To_Bitmap) don't have access + * to this information. + * + * Note that @FT_Render_Glyph is able to handle colored glyph layers + * automatically if the @FT_LOAD_COLOR flag is passed to a previous call + * to @FT_Load_Glyph. [This is an experimental feature.] + * + * @example: + * ``` + * FT_Color* palette; + * FT_LayerIterator iterator; + * + * FT_Bool have_layers; + * FT_UInt layer_glyph_index; + * FT_UInt layer_color_index; + * + * + * error = FT_Palette_Select( face, palette_index, &palette ); + * if ( error ) + * palette = NULL; + * + * iterator.p = NULL; + * have_layers = FT_Get_Color_Glyph_Layer( face, + * glyph_index, + * &layer_glyph_index, + * &layer_color_index, + * &iterator ); + * + * if ( palette && have_layers ) + * { + * do + * { + * FT_Color layer_color; + * + * + * if ( layer_color_index == 0xFFFF ) + * layer_color = text_foreground_color; + * else + * layer_color = palette[layer_color_index]; + * + * // Load and render glyph `layer_glyph_index', then + * // blend resulting pixmap (using color `layer_color') + * // with previously created pixmaps. + * + * } while ( FT_Get_Color_Glyph_Layer( face, + * glyph_index, + * &layer_glyph_index, + * &layer_color_index, + * &iterator ) ); + * } + * ``` + * + * @since: + * 2.10 + */ + FT_EXPORT( FT_Bool ) + FT_Get_Color_Glyph_Layer( FT_Face face, + FT_UInt base_glyph, + FT_UInt *aglyph_index, + FT_UInt *acolor_index, + FT_LayerIterator* iterator ); + + + /************************************************************************** + * + * @enum: + * FT_PaintFormat + * + * @description: + * Enumeration describing the different paint format types of the v1 + * extensions to the 'COLR' table, see + * 'https://github.com/googlefonts/colr-gradients-spec'. + * + * The enumeration values loosely correspond with the format numbers of + * the specification: FreeType always returns a fully specified 'Paint' + * structure for the 'Transform', 'Translate', 'Scale', 'Rotate', and + * 'Skew' table types even though the specification has different formats + * depending on whether or not a center is specified, whether the scale + * is uniform in x and y~direction or not, etc. Also, only non-variable + * format identifiers are listed in this enumeration; as soon as support + * for variable 'COLR' v1 fonts is implemented, interpolation is + * performed dependent on axis coordinates, which are configured on the + * @FT_Face through @FT_Set_Var_Design_Coordinates. This implies that + * always static, readily interpolated values are returned in the 'Paint' + * structures. + * + * @since: + * 2.13 + */ + typedef enum FT_PaintFormat_ + { + FT_COLR_PAINTFORMAT_COLR_LAYERS = 1, + FT_COLR_PAINTFORMAT_SOLID = 2, + FT_COLR_PAINTFORMAT_LINEAR_GRADIENT = 4, + FT_COLR_PAINTFORMAT_RADIAL_GRADIENT = 6, + FT_COLR_PAINTFORMAT_SWEEP_GRADIENT = 8, + FT_COLR_PAINTFORMAT_GLYPH = 10, + FT_COLR_PAINTFORMAT_COLR_GLYPH = 11, + FT_COLR_PAINTFORMAT_TRANSFORM = 12, + FT_COLR_PAINTFORMAT_TRANSLATE = 14, + FT_COLR_PAINTFORMAT_SCALE = 16, + FT_COLR_PAINTFORMAT_ROTATE = 24, + FT_COLR_PAINTFORMAT_SKEW = 28, + FT_COLR_PAINTFORMAT_COMPOSITE = 32, + FT_COLR_PAINT_FORMAT_MAX = 33, + FT_COLR_PAINTFORMAT_UNSUPPORTED = 255 + + } FT_PaintFormat; + + + /************************************************************************** + * + * @struct: + * FT_ColorStopIterator + * + * @description: + * This iterator object is needed for @FT_Get_Colorline_Stops. It keeps + * state while iterating over the stops of an @FT_ColorLine, representing + * the `ColorLine` struct of the v1 extensions to 'COLR', see + * 'https://github.com/googlefonts/colr-gradients-spec'. Do not manually + * modify fields of this iterator. + * + * @fields: + * num_color_stops :: + * The number of color stops for the requested glyph index. Set by + * @FT_Get_Paint. + * + * current_color_stop :: + * The current color stop. Set by @FT_Get_Colorline_Stops. + * + * p :: + * An opaque pointer into 'COLR' table data. Set by @FT_Get_Paint. + * Updated by @FT_Get_Colorline_Stops. + * + * read_variable :: + * A boolean keeping track of whether variable color lines are to be + * read. Set by @FT_Get_Paint. + * + * @since: + * 2.13 + */ + typedef struct FT_ColorStopIterator_ + { + FT_UInt num_color_stops; + FT_UInt current_color_stop; + + FT_Byte* p; + + FT_Bool read_variable; + + } FT_ColorStopIterator; + + + /************************************************************************** + * + * @struct: + * FT_ColorIndex + * + * @description: + * A structure representing a `ColorIndex` value of the 'COLR' v1 + * extensions, see 'https://github.com/googlefonts/colr-gradients-spec'. + * + * @fields: + * palette_index :: + * The palette index into a 'CPAL' palette. + * + * alpha :: + * Alpha transparency value multiplied with the value from 'CPAL'. + * + * @since: + * 2.13 + */ + typedef struct FT_ColorIndex_ + { + FT_UInt16 palette_index; + FT_F2Dot14 alpha; + + } FT_ColorIndex; + + + /************************************************************************** + * + * @struct: + * FT_ColorStop + * + * @description: + * A structure representing a `ColorStop` value of the 'COLR' v1 + * extensions, see 'https://github.com/googlefonts/colr-gradients-spec'. + * + * @fields: + * stop_offset :: + * The stop offset along the gradient, expressed as a 16.16 fixed-point + * coordinate. + * + * color :: + * The color information for this stop, see @FT_ColorIndex. + * + * @since: + * 2.13 + */ + typedef struct FT_ColorStop_ + { + FT_Fixed stop_offset; + FT_ColorIndex color; + + } FT_ColorStop; + + + /************************************************************************** + * + * @enum: + * FT_PaintExtend + * + * @description: + * An enumeration representing the 'Extend' mode of the 'COLR' v1 + * extensions, see 'https://github.com/googlefonts/colr-gradients-spec'. + * It describes how the gradient fill continues at the other boundaries. + * + * @since: + * 2.13 + */ + typedef enum FT_PaintExtend_ + { + FT_COLR_PAINT_EXTEND_PAD = 0, + FT_COLR_PAINT_EXTEND_REPEAT = 1, + FT_COLR_PAINT_EXTEND_REFLECT = 2 + + } FT_PaintExtend; + + + /************************************************************************** + * + * @struct: + * FT_ColorLine + * + * @description: + * A structure representing a `ColorLine` value of the 'COLR' v1 + * extensions, see 'https://github.com/googlefonts/colr-gradients-spec'. + * It describes a list of color stops along the defined gradient. + * + * @fields: + * extend :: + * The extend mode at the outer boundaries, see @FT_PaintExtend. + * + * color_stop_iterator :: + * The @FT_ColorStopIterator used to enumerate and retrieve the + * actual @FT_ColorStop's. + * + * @since: + * 2.13 + */ + typedef struct FT_ColorLine_ + { + FT_PaintExtend extend; + FT_ColorStopIterator color_stop_iterator; + + } FT_ColorLine; + + + /************************************************************************** + * + * @struct: + * FT_Affine23 + * + * @description: + * A structure used to store a 2x3 matrix. Coefficients are in + * 16.16 fixed-point format. The computation performed is + * + * ``` + * x' = x*xx + y*xy + dx + * y' = x*yx + y*yy + dy + * ``` + * + * @fields: + * xx :: + * Matrix coefficient. + * + * xy :: + * Matrix coefficient. + * + * dx :: + * x translation. + * + * yx :: + * Matrix coefficient. + * + * yy :: + * Matrix coefficient. + * + * dy :: + * y translation. + * + * @since: + * 2.13 + */ + typedef struct FT_Affine_23_ + { + FT_Fixed xx, xy, dx; + FT_Fixed yx, yy, dy; + + } FT_Affine23; + + + /************************************************************************** + * + * @enum: + * FT_Composite_Mode + * + * @description: + * An enumeration listing the 'COLR' v1 composite modes used in + * @FT_PaintComposite. For more details on each paint mode, see + * 'https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators'. + * + * @since: + * 2.13 + */ + typedef enum FT_Composite_Mode_ + { + FT_COLR_COMPOSITE_CLEAR = 0, + FT_COLR_COMPOSITE_SRC = 1, + FT_COLR_COMPOSITE_DEST = 2, + FT_COLR_COMPOSITE_SRC_OVER = 3, + FT_COLR_COMPOSITE_DEST_OVER = 4, + FT_COLR_COMPOSITE_SRC_IN = 5, + FT_COLR_COMPOSITE_DEST_IN = 6, + FT_COLR_COMPOSITE_SRC_OUT = 7, + FT_COLR_COMPOSITE_DEST_OUT = 8, + FT_COLR_COMPOSITE_SRC_ATOP = 9, + FT_COLR_COMPOSITE_DEST_ATOP = 10, + FT_COLR_COMPOSITE_XOR = 11, + FT_COLR_COMPOSITE_PLUS = 12, + FT_COLR_COMPOSITE_SCREEN = 13, + FT_COLR_COMPOSITE_OVERLAY = 14, + FT_COLR_COMPOSITE_DARKEN = 15, + FT_COLR_COMPOSITE_LIGHTEN = 16, + FT_COLR_COMPOSITE_COLOR_DODGE = 17, + FT_COLR_COMPOSITE_COLOR_BURN = 18, + FT_COLR_COMPOSITE_HARD_LIGHT = 19, + FT_COLR_COMPOSITE_SOFT_LIGHT = 20, + FT_COLR_COMPOSITE_DIFFERENCE = 21, + FT_COLR_COMPOSITE_EXCLUSION = 22, + FT_COLR_COMPOSITE_MULTIPLY = 23, + FT_COLR_COMPOSITE_HSL_HUE = 24, + FT_COLR_COMPOSITE_HSL_SATURATION = 25, + FT_COLR_COMPOSITE_HSL_COLOR = 26, + FT_COLR_COMPOSITE_HSL_LUMINOSITY = 27, + FT_COLR_COMPOSITE_MAX = 28 + + } FT_Composite_Mode; + + + /************************************************************************** + * + * @struct: + * FT_OpaquePaint + * + * @description: + * A structure representing an offset to a `Paint` value stored in any + * of the paint tables of a 'COLR' v1 font. Compare Offset<24> there. + * When 'COLR' v1 paint tables represented by FreeType objects such as + * @FT_PaintColrLayers, @FT_PaintComposite, or @FT_PaintTransform + * reference downstream nested paint tables, we do not immediately + * retrieve them but encapsulate their location in this type. Use + * @FT_Get_Paint to retrieve the actual @FT_COLR_Paint object that + * describes the details of the respective paint table. + * + * @fields: + * p :: + * An internal offset to a Paint table, needs to be set to NULL before + * passing this struct as an argument to @FT_Get_Paint. + * + * insert_root_transform :: + * An internal boolean to track whether an initial root transform is + * to be provided. Do not set this value. + * + * @since: + * 2.13 + */ + typedef struct FT_Opaque_Paint_ + { + FT_Byte* p; + FT_Bool insert_root_transform; + } FT_OpaquePaint; + + + /************************************************************************** + * + * @struct: + * FT_PaintColrLayers + * + * @description: + * A structure representing a `PaintColrLayers` table of a 'COLR' v1 + * font. This table describes a set of layers that are to be composited + * with composite mode `FT_COLR_COMPOSITE_SRC_OVER`. The return value + * of this function is an @FT_LayerIterator initialized so that it can + * be used with @FT_Get_Paint_Layers to retrieve the @FT_OpaquePaint + * objects as references to each layer. + * + * @fields: + * layer_iterator :: + * The layer iterator that describes the layers of this paint. + * + * @since: + * 2.13 + */ + typedef struct FT_PaintColrLayers_ + { + FT_LayerIterator layer_iterator; + + } FT_PaintColrLayers; + + + /************************************************************************** + * + * @struct: + * FT_PaintSolid + * + * @description: + * A structure representing a `PaintSolid` value of the 'COLR' v1 + * extensions, see 'https://github.com/googlefonts/colr-gradients-spec'. + * Using a `PaintSolid` value means that the glyph layer filled with + * this paint is solid-colored and does not contain a gradient. + * + * @fields: + * color :: + * The color information for this solid paint, see @FT_ColorIndex. + * + * @since: + * 2.13 + */ + typedef struct FT_PaintSolid_ + { + FT_ColorIndex color; + + } FT_PaintSolid; + + + /************************************************************************** + * + * @struct: + * FT_PaintLinearGradient + * + * @description: + * A structure representing a `PaintLinearGradient` value of the 'COLR' + * v1 extensions, see + * 'https://github.com/googlefonts/colr-gradients-spec'. The glyph + * layer filled with this paint is drawn filled with a linear gradient. + * + * @fields: + * colorline :: + * The @FT_ColorLine information for this paint, i.e., the list of + * color stops along the gradient. + * + * p0 :: + * The starting point of the gradient definition in font units + * represented as a 16.16 fixed-point `FT_Vector`. + * + * p1 :: + * The end point of the gradient definition in font units + * represented as a 16.16 fixed-point `FT_Vector`. + * + * p2 :: + * Optional point~p2 to rotate the gradient in font units + * represented as a 16.16 fixed-point `FT_Vector`. + * Otherwise equal to~p0. + * + * @since: + * 2.13 + */ + typedef struct FT_PaintLinearGradient_ + { + FT_ColorLine colorline; + + /* TODO: Potentially expose those as x0, y0 etc. */ + FT_Vector p0; + FT_Vector p1; + FT_Vector p2; + + } FT_PaintLinearGradient; + + + /************************************************************************** + * + * @struct: + * FT_PaintRadialGradient + * + * @description: + * A structure representing a `PaintRadialGradient` value of the 'COLR' + * v1 extensions, see + * 'https://github.com/googlefonts/colr-gradients-spec'. The glyph + * layer filled with this paint is drawn filled with a radial gradient. + * + * @fields: + * colorline :: + * The @FT_ColorLine information for this paint, i.e., the list of + * color stops along the gradient. + * + * c0 :: + * The center of the starting point of the radial gradient in font + * units represented as a 16.16 fixed-point `FT_Vector`. + * + * r0 :: + * The radius of the starting circle of the radial gradient in font + * units represented as a 16.16 fixed-point value. + * + * c1 :: + * The center of the end point of the radial gradient in font units + * represented as a 16.16 fixed-point `FT_Vector`. + * + * r1 :: + * The radius of the end circle of the radial gradient in font + * units represented as a 16.16 fixed-point value. + * + * @since: + * 2.13 + */ + typedef struct FT_PaintRadialGradient_ + { + FT_ColorLine colorline; + + FT_Vector c0; + FT_Pos r0; + FT_Vector c1; + FT_Pos r1; + + } FT_PaintRadialGradient; + + + /************************************************************************** + * + * @struct: + * FT_PaintSweepGradient + * + * @description: + * A structure representing a `PaintSweepGradient` value of the 'COLR' + * v1 extensions, see + * 'https://github.com/googlefonts/colr-gradients-spec'. The glyph + * layer filled with this paint is drawn filled with a sweep gradient + * from `start_angle` to `end_angle`. + * + * @fields: + * colorline :: + * The @FT_ColorLine information for this paint, i.e., the list of + * color stops along the gradient. + * + * center :: + * The center of the sweep gradient in font units represented as a + * vector of 16.16 fixed-point values. + * + * start_angle :: + * The start angle of the sweep gradient in 16.16 fixed-point + * format specifying degrees divided by 180.0 (as in the + * spec). Multiply by 180.0f to receive degrees value. Values are + * given counter-clockwise, starting from the (positive) y~axis. + * + * end_angle :: + * The end angle of the sweep gradient in 16.16 fixed-point + * format specifying degrees divided by 180.0 (as in the + * spec). Multiply by 180.0f to receive degrees value. Values are + * given counter-clockwise, starting from the (positive) y~axis. + * + * @since: + * 2.13 + */ + typedef struct FT_PaintSweepGradient_ + { + FT_ColorLine colorline; + + FT_Vector center; + FT_Fixed start_angle; + FT_Fixed end_angle; + + } FT_PaintSweepGradient; + + + /************************************************************************** + * + * @struct: + * FT_PaintGlyph + * + * @description: + * A structure representing a 'COLR' v1 `PaintGlyph` paint table. + * + * @fields: + * paint :: + * An opaque paint object pointing to a `Paint` table that serves as + * the fill for the glyph ID. + * + * glyphID :: + * The glyph ID from the 'glyf' table, which serves as the contour + * information that is filled with paint. + * + * @since: + * 2.13 + */ + typedef struct FT_PaintGlyph_ + { + FT_OpaquePaint paint; + FT_UInt glyphID; + + } FT_PaintGlyph; + + + /************************************************************************** + * + * @struct: + * FT_PaintColrGlyph + * + * @description: + * A structure representing a 'COLR' v1 `PaintColorGlyph` paint table. + * + * @fields: + * glyphID :: + * The glyph ID from the `BaseGlyphV1List` table that is drawn for + * this paint. + * + * @since: + * 2.13 + */ + typedef struct FT_PaintColrGlyph_ + { + FT_UInt glyphID; + + } FT_PaintColrGlyph; + + + /************************************************************************** + * + * @struct: + * FT_PaintTransform + * + * @description: + * A structure representing a 'COLR' v1 `PaintTransform` paint table. + * + * @fields: + * paint :: + * An opaque paint that is subject to being transformed. + * + * affine :: + * A 2x3 transformation matrix in @FT_Affine23 format containing + * 16.16 fixed-point values. + * + * @since: + * 2.13 + */ + typedef struct FT_PaintTransform_ + { + FT_OpaquePaint paint; + FT_Affine23 affine; + + } FT_PaintTransform; + + + /************************************************************************** + * + * @struct: + * FT_PaintTranslate + * + * @description: + * A structure representing a 'COLR' v1 `PaintTranslate` paint table. + * Used for translating downstream paints by a given x and y~delta. + * + * @fields: + * paint :: + * An @FT_OpaquePaint object referencing the paint that is to be + * rotated. + * + * dx :: + * Translation in x~direction in font units represented as a + * 16.16 fixed-point value. + * + * dy :: + * Translation in y~direction in font units represented as a + * 16.16 fixed-point value. + * + * @since: + * 2.13 + */ + typedef struct FT_PaintTranslate_ + { + FT_OpaquePaint paint; + + FT_Fixed dx; + FT_Fixed dy; + + } FT_PaintTranslate; + + + /************************************************************************** + * + * @struct: + * FT_PaintScale + * + * @description: + * A structure representing all of the 'COLR' v1 'PaintScale*' paint + * tables. Used for scaling downstream paints by a given x and y~scale, + * with a given center. This structure is used for all 'PaintScale*' + * types that are part of specification; fields of this structure are + * filled accordingly. If there is a center, the center values are set, + * otherwise they are set to the zero coordinate. If the source font + * file has 'PaintScaleUniform*' set, the scale values are set + * accordingly to the same value. + * + * @fields: + * paint :: + * An @FT_OpaquePaint object referencing the paint that is to be + * scaled. + * + * scale_x :: + * Scale factor in x~direction represented as a + * 16.16 fixed-point value. + * + * scale_y :: + * Scale factor in y~direction represented as a + * 16.16 fixed-point value. + * + * center_x :: + * x~coordinate of center point to scale from represented as a + * 16.16 fixed-point value. + * + * center_y :: + * y~coordinate of center point to scale from represented as a + * 16.16 fixed-point value. + * + * @since: + * 2.13 + */ + typedef struct FT_PaintScale_ + { + FT_OpaquePaint paint; + + FT_Fixed scale_x; + FT_Fixed scale_y; + + FT_Fixed center_x; + FT_Fixed center_y; + + } FT_PaintScale; + + + /************************************************************************** + * + * @struct: + * FT_PaintRotate + * + * @description: + * A structure representing a 'COLR' v1 `PaintRotate` paint table. Used + * for rotating downstream paints with a given center and angle. + * + * @fields: + * paint :: + * An @FT_OpaquePaint object referencing the paint that is to be + * rotated. + * + * angle :: + * The rotation angle that is to be applied in degrees divided by + * 180.0 (as in the spec) represented as a 16.16 fixed-point + * value. Multiply by 180.0f to receive degrees value. + * + * center_x :: + * The x~coordinate of the pivot point of the rotation in font + * units represented as a 16.16 fixed-point value. + * + * center_y :: + * The y~coordinate of the pivot point of the rotation in font + * units represented as a 16.16 fixed-point value. + * + * @since: + * 2.13 + */ + + typedef struct FT_PaintRotate_ + { + FT_OpaquePaint paint; + + FT_Fixed angle; + + FT_Fixed center_x; + FT_Fixed center_y; + + } FT_PaintRotate; + + + /************************************************************************** + * + * @struct: + * FT_PaintSkew + * + * @description: + * A structure representing a 'COLR' v1 `PaintSkew` paint table. Used + * for skewing or shearing downstream paints by a given center and + * angle. + * + * @fields: + * paint :: + * An @FT_OpaquePaint object referencing the paint that is to be + * skewed. + * + * x_skew_angle :: + * The skewing angle in x~direction in degrees divided by 180.0 + * (as in the spec) represented as a 16.16 fixed-point + * value. Multiply by 180.0f to receive degrees. + * + * y_skew_angle :: + * The skewing angle in y~direction in degrees divided by 180.0 + * (as in the spec) represented as a 16.16 fixed-point + * value. Multiply by 180.0f to receive degrees. + * + * center_x :: + * The x~coordinate of the pivot point of the skew in font units + * represented as a 16.16 fixed-point value. + * + * center_y :: + * The y~coordinate of the pivot point of the skew in font units + * represented as a 16.16 fixed-point value. + * + * @since: + * 2.13 + */ + typedef struct FT_PaintSkew_ + { + FT_OpaquePaint paint; + + FT_Fixed x_skew_angle; + FT_Fixed y_skew_angle; + + FT_Fixed center_x; + FT_Fixed center_y; + + } FT_PaintSkew; + + + /************************************************************************** + * + * @struct: + * FT_PaintComposite + * + * @description: + * A structure representing a 'COLR' v1 `PaintComposite` paint table. + * Used for compositing two paints in a 'COLR' v1 directed acyclic graph. + * + * @fields: + * source_paint :: + * An @FT_OpaquePaint object referencing the source that is to be + * composited. + * + * composite_mode :: + * An @FT_Composite_Mode enum value determining the composition + * operation. + * + * backdrop_paint :: + * An @FT_OpaquePaint object referencing the backdrop paint that + * `source_paint` is composited onto. + * + * @since: + * 2.13 + */ + typedef struct FT_PaintComposite_ + { + FT_OpaquePaint source_paint; + FT_Composite_Mode composite_mode; + FT_OpaquePaint backdrop_paint; + + } FT_PaintComposite; + + + /************************************************************************** + * + * @union: + * FT_COLR_Paint + * + * @description: + * A union object representing format and details of a paint table of a + * 'COLR' v1 font, see + * 'https://github.com/googlefonts/colr-gradients-spec'. Use + * @FT_Get_Paint to retrieve a @FT_COLR_Paint for an @FT_OpaquePaint + * object. + * + * @fields: + * format :: + * The gradient format for this Paint structure. + * + * u :: + * Union of all paint table types: + * + * * @FT_PaintColrLayers + * * @FT_PaintGlyph + * * @FT_PaintSolid + * * @FT_PaintLinearGradient + * * @FT_PaintRadialGradient + * * @FT_PaintSweepGradient + * * @FT_PaintTransform + * * @FT_PaintTranslate + * * @FT_PaintRotate + * * @FT_PaintSkew + * * @FT_PaintComposite + * * @FT_PaintColrGlyph + * + * @since: + * 2.13 + */ + typedef struct FT_COLR_Paint_ + { + FT_PaintFormat format; + + union + { + FT_PaintColrLayers colr_layers; + FT_PaintGlyph glyph; + FT_PaintSolid solid; + FT_PaintLinearGradient linear_gradient; + FT_PaintRadialGradient radial_gradient; + FT_PaintSweepGradient sweep_gradient; + FT_PaintTransform transform; + FT_PaintTranslate translate; + FT_PaintScale scale; + FT_PaintRotate rotate; + FT_PaintSkew skew; + FT_PaintComposite composite; + FT_PaintColrGlyph colr_glyph; + + } u; + + } FT_COLR_Paint; + + + /************************************************************************** + * + * @enum: + * FT_Color_Root_Transform + * + * @description: + * An enumeration to specify whether @FT_Get_Color_Glyph_Paint is to + * return a root transform to configure the client's graphics context + * matrix. + * + * @values: + * FT_COLOR_INCLUDE_ROOT_TRANSFORM :: + * Do include the root transform as the initial @FT_COLR_Paint object. + * + * FT_COLOR_NO_ROOT_TRANSFORM :: + * Do not output an initial root transform. + * + * @since: + * 2.13 + */ + typedef enum FT_Color_Root_Transform_ + { + FT_COLOR_INCLUDE_ROOT_TRANSFORM, + FT_COLOR_NO_ROOT_TRANSFORM, + + FT_COLOR_ROOT_TRANSFORM_MAX + + } FT_Color_Root_Transform; + + + /************************************************************************** + * + * @struct: + * FT_ClipBox + * + * @description: + * A structure representing a 'COLR' v1 'ClipBox' table. 'COLR' v1 + * glyphs may optionally define a clip box for aiding allocation or + * defining a maximum drawable region. Use @FT_Get_Color_Glyph_ClipBox + * to retrieve it. + * + * @fields: + * bottom_left :: + * The bottom left corner of the clip box as an @FT_Vector with + * fixed-point coordinates in 26.6 format. + * + * top_left :: + * The top left corner of the clip box as an @FT_Vector with + * fixed-point coordinates in 26.6 format. + * + * top_right :: + * The top right corner of the clip box as an @FT_Vector with + * fixed-point coordinates in 26.6 format. + * + * bottom_right :: + * The bottom right corner of the clip box as an @FT_Vector with + * fixed-point coordinates in 26.6 format. + * + * @since: + * 2.13 + */ + typedef struct FT_ClipBox_ + { + FT_Vector bottom_left; + FT_Vector top_left; + FT_Vector top_right; + FT_Vector bottom_right; + + } FT_ClipBox; + + + /************************************************************************** + * + * @function: + * FT_Get_Color_Glyph_Paint + * + * @description: + * This is the starting point and interface to color gradient + * information in a 'COLR' v1 table in OpenType fonts to recursively + * retrieve the paint tables for the directed acyclic graph of a colored + * glyph, given a glyph ID. + * + * https://github.com/googlefonts/colr-gradients-spec + * + * In a 'COLR' v1 font, each color glyph defines a directed acyclic + * graph of nested paint tables, such as `PaintGlyph`, `PaintSolid`, + * `PaintLinearGradient`, `PaintRadialGradient`, and so on. Using this + * function and specifying a glyph ID, one retrieves the root paint + * table for this glyph ID. + * + * This function allows control whether an initial root transform is + * returned to configure scaling, transform, and translation correctly + * on the client's graphics context. The initial root transform is + * computed and returned according to the values configured for @FT_Size + * and @FT_Set_Transform on the @FT_Face object, see below for details + * of the `root_transform` parameter. This has implications for a + * client 'COLR' v1 implementation: When this function returns an + * initially computed root transform, at the time of executing the + * @FT_PaintGlyph operation, the contours should be retrieved using + * @FT_Load_Glyph at unscaled, untransformed size. This is because the + * root transform applied to the graphics context will take care of + * correct scaling. + * + * Alternatively, to allow hinting of contours, at the time of executing + * @FT_Load_Glyph, the current graphics context transformation matrix + * can be decomposed into a scaling matrix and a remainder, and + * @FT_Load_Glyph can be used to retrieve the contours at scaled size. + * Care must then be taken to blit or clip to the graphics context with + * taking this remainder transformation into account. + * + * @input: + * face :: + * A handle to the parent face object. + * + * base_glyph :: + * The glyph index for which to retrieve the root paint table. + * + * root_transform :: + * Specifies whether an initially computed root is returned by the + * @FT_PaintTransform operation to account for the activated size + * (see @FT_Activate_Size) and the configured transform and translate + * (see @FT_Set_Transform). + * + * This root transform is returned before nodes of the glyph graph of + * the font are returned. Subsequent @FT_COLR_Paint structures + * contain unscaled and untransformed values. The inserted root + * transform enables the client application to apply an initial + * transform to its graphics context. When executing subsequent + * FT_COLR_Paint operations, values from @FT_COLR_Paint operations + * will ultimately be correctly scaled because of the root transform + * applied to the graphics context. Use + * @FT_COLOR_INCLUDE_ROOT_TRANSFORM to include the root transform, use + * @FT_COLOR_NO_ROOT_TRANSFORM to not include it. The latter may be + * useful when traversing the 'COLR' v1 glyph graph and reaching a + * @FT_PaintColrGlyph. When recursing into @FT_PaintColrGlyph and + * painting that inline, no additional root transform is needed as it + * has already been applied to the graphics context at the beginning + * of drawing this glyph. + * + * @output: + * paint :: + * The @FT_OpaquePaint object that references the actual paint table. + * + * The respective actual @FT_COLR_Paint object is retrieved via + * @FT_Get_Paint. + * + * @return: + * Value~1 if everything is OK. If no color glyph is found, or the root + * paint could not be retrieved, value~0 gets returned. In case of an + * error, value~0 is returned also. + * + * @since: + * 2.13 + */ + FT_EXPORT( FT_Bool ) + FT_Get_Color_Glyph_Paint( FT_Face face, + FT_UInt base_glyph, + FT_Color_Root_Transform root_transform, + FT_OpaquePaint* paint ); + + + /************************************************************************** + * + * @function: + * FT_Get_Color_Glyph_ClipBox + * + * @description: + * Search for a 'COLR' v1 clip box for the specified `base_glyph` and + * fill the `clip_box` parameter with the 'COLR' v1 'ClipBox' information + * if one is found. + * + * @input: + * face :: + * A handle to the parent face object. + * + * base_glyph :: + * The glyph index for which to retrieve the clip box. + * + * @output: + * clip_box :: + * The clip box for the requested `base_glyph` if one is found. The + * clip box is computed taking scale and transformations configured on + * the @FT_Face into account. @FT_ClipBox contains @FT_Vector values + * in 26.6 format. + * + * @return: + * Value~1 if a clip box is found. If no clip box is found or an error + * occured, value~0 is returned. + * + * @note: + * To retrieve the clip box in font units, reset scale to units-per-em + * and remove transforms configured using @FT_Set_Transform. + * + * @since: + * 2.13 + */ + FT_EXPORT( FT_Bool ) + FT_Get_Color_Glyph_ClipBox( FT_Face face, + FT_UInt base_glyph, + FT_ClipBox* clip_box ); + + + /************************************************************************** + * + * @function: + * FT_Get_Paint_Layers + * + * @description: + * Access the layers of a `PaintColrLayers` table. + * + * If the root paint of a color glyph, or a nested paint of a 'COLR' + * glyph is a `PaintColrLayers` table, this function retrieves the + * layers of the `PaintColrLayers` table. + * + * The @FT_PaintColrLayers object contains an @FT_LayerIterator, which + * is used here to iterate over the layers. Each layer is returned as + * an @FT_OpaquePaint object, which then can be used with @FT_Get_Paint + * to retrieve the actual paint object. + * + * @input: + * face :: + * A handle to the parent face object. + * + * @inout: + * iterator :: + * The @FT_LayerIterator from an @FT_PaintColrLayers object, for which + * the layers are to be retrieved. The internal state of the iterator + * is incremented after one call to this function for retrieving one + * layer. + * + * @output: + * paint :: + * The @FT_OpaquePaint object that references the actual paint table. + * The respective actual @FT_COLR_Paint object is retrieved via + * @FT_Get_Paint. + * + * @return: + * Value~1 if everything is OK. Value~0 gets returned when the paint + * object can not be retrieved or any other error occurs. + * + * @since: + * 2.13 + */ + FT_EXPORT( FT_Bool ) + FT_Get_Paint_Layers( FT_Face face, + FT_LayerIterator* iterator, + FT_OpaquePaint* paint ); + + + /************************************************************************** + * + * @function: + * FT_Get_Colorline_Stops + * + * @description: + * This is an interface to color gradient information in a 'COLR' v1 + * table in OpenType fonts to iteratively retrieve the gradient and + * solid fill information for colored glyph layers for a specified glyph + * ID. + * + * https://github.com/googlefonts/colr-gradients-spec + * + * @input: + * face :: + * A handle to the parent face object. + * + * @inout: + * iterator :: + * The retrieved @FT_ColorStopIterator, configured on an @FT_ColorLine, + * which in turn got retrieved via paint information in + * @FT_PaintLinearGradient or @FT_PaintRadialGradient. + * + * @output: + * color_stop :: + * Color index and alpha value for the retrieved color stop. + * + * @return: + * Value~1 if everything is OK. If there are no more color stops, + * value~0 gets returned. In case of an error, value~0 is returned + * also. + * + * @since: + * 2.13 + */ + FT_EXPORT( FT_Bool ) + FT_Get_Colorline_Stops( FT_Face face, + FT_ColorStop* color_stop, + FT_ColorStopIterator* iterator ); + + + /************************************************************************** + * + * @function: + * FT_Get_Paint + * + * @description: + * Access the details of a paint using an @FT_OpaquePaint opaque paint + * object, which internally stores the offset to the respective `Paint` + * object in the 'COLR' table. + * + * @input: + * face :: + * A handle to the parent face object. + * + * opaque_paint :: + * The opaque paint object for which the underlying @FT_COLR_Paint + * data is to be retrieved. + * + * @output: + * paint :: + * The specific @FT_COLR_Paint object containing information coming + * from one of the font's `Paint*` tables. + * + * @return: + * Value~1 if everything is OK. Value~0 if no details can be found for + * this paint or any other error occured. + * + * @since: + * 2.13 + */ + FT_EXPORT( FT_Bool ) + FT_Get_Paint( FT_Face face, + FT_OpaquePaint opaque_paint, + FT_COLR_Paint* paint ); + /* */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftdriver.h b/lib/libesp32_lvgl/freetype/include/freetype/ftdriver.h index 804ec34a3..7af7465bc 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftdriver.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftdriver.h @@ -4,7 +4,7 @@ * * FreeType API for controlling driver modules (specification only). * - * Copyright (C) 2017-2020 by + * Copyright (C) 2017-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -53,10 +53,10 @@ FT_BEGIN_HEADER * reasons. * * Available properties are @increase-x-height, @no-stem-darkening - * (experimental), @darkening-parameters (experimental), @warping - * (experimental), @glyph-to-script-map (experimental), @fallback-script - * (experimental), and @default-script (experimental), as documented in - * the @properties section. + * (experimental), @darkening-parameters (experimental), + * @glyph-to-script-map (experimental), @fallback-script (experimental), + * and @default-script (experimental), as documented in the @properties + * section. * */ @@ -84,15 +84,15 @@ FT_BEGIN_HEADER * @properties section. * * - * **Hinting and antialiasing principles of the new engine** + * **Hinting and anti-aliasing principles of the new engine** * * The rasterizer is positioning horizontal features (e.g., ascender * height & x-height, or crossbars) on the pixel grid and minimizing the - * amount of antialiasing applied to them, while placing vertical + * amount of anti-aliasing applied to them, while placing vertical * features (vertical stems) on the pixel grid without hinting, thus * representing the stem position and weight accurately. Sometimes the * vertical stems may be only partially black. In this context, - * 'antialiasing' means that stems are not positioned exactly on pixel + * 'anti-aliasing' means that stems are not positioned exactly on pixel * borders, causing a fuzzy appearance. * * There are two principles behind this approach. @@ -108,7 +108,7 @@ FT_BEGIN_HEADER * sizes are comparable to kerning values and thus would be noticeable * (and distracting) while reading if hinting were applied. * - * One of the reasons to not hint horizontally is antialiasing for LCD + * One of the reasons to not hint horizontally is anti-aliasing for LCD * screens: The pixel geometry of modern displays supplies three vertical * subpixels as the eye moves horizontally across each visible pixel. On * devices where we can be certain this characteristic is present a @@ -116,7 +116,7 @@ FT_BEGIN_HEADER * weight. In Western writing systems this turns out to be the more * critical direction anyway; the weights and spacing of vertical stems * (see above) are central to Armenian, Cyrillic, Greek, and Latin type - * designs. Even when the rasterizer uses greyscale antialiasing instead + * designs. Even when the rasterizer uses greyscale anti-aliasing instead * of color (a necessary compromise when one doesn't know the screen * characteristics), the unhinted vertical features preserve the design's * weight and spacing much better than aliased type would. @@ -134,7 +134,7 @@ FT_BEGIN_HEADER * each being rounded to the nearest pixel edge, taking care of overshoot * suppression at small sizes, stem darkening, and scaling. * - * Hstems (this is, hint values defined in the font to help align + * Hstems (that is, hint values defined in the font to help align * horizontal features) that fall within a blue zone are said to be * 'captured' and are aligned to that zone. Uncaptured stems are moved * in one of four ways, top edge up or down, bottom edge up or down. @@ -212,16 +212,14 @@ FT_BEGIN_HEADER * @description: * While FreeType's TrueType driver doesn't expose API functions by * itself, it is possible to control its behaviour with @FT_Property_Set - * and @FT_Property_Get. The following lists the available properties - * together with the necessary macros and structures. + * and @FT_Property_Get. * - * The TrueType driver's module name is 'truetype'. + * The TrueType driver's module name is 'truetype'; a single property + * @interpreter-version is available, as documented in the @properties + * section. * - * A single property @interpreter-version is available, as documented in - * the @properties section. - * - * We start with a list of definitions, kindly provided by Greg - * Hitchcock. + * To help understand the differences between interpreter versions, we + * introduce a list of definitions, kindly provided by Greg Hitchcock. * * _Bi-Level Rendering_ * @@ -300,6 +298,31 @@ FT_BEGIN_HEADER */ + /************************************************************************** + * + * @section: + * ot_svg_driver + * + * @title: + * The SVG driver + * + * @abstract: + * Controlling the external rendering of OT-SVG glyphs. + * + * @description: + * By default, FreeType can only load the 'SVG~' table of OpenType fonts + * if configuration macro `FT_CONFIG_OPTION_SVG` is defined. To make it + * render SVG glyphs, an external SVG rendering library is needed. All + * details on the interface between FreeType and the external library + * via function hooks can be found in section @svg_fonts. + * + * The OT-SVG driver's module name is 'ot-svg'; it supports a single + * property called @svg-hooks, documented below in the @properties + * section. + * + */ + + /************************************************************************** * * @section: @@ -362,12 +385,8 @@ FT_BEGIN_HEADER * The same holds for the Type~1 and CID modules if compiled with * `T1_CONFIG_OPTION_OLD_ENGINE`. * - * For the 'cff' module, the default engine is 'freetype' if - * `CFF_CONFIG_OPTION_OLD_ENGINE` is defined, and 'adobe' otherwise. - * - * For both the 'type1' and 't1cid' modules, the default engine is - * 'freetype' if `T1_CONFIG_OPTION_OLD_ENGINE` is defined, and 'adobe' - * otherwise. + * For the 'cff' module, the default engine is 'adobe'. For both the + * 'type1' and 't1cid' modules, the default engine is 'adobe', too. * * @note: * This property can be used with @FT_Property_Get also. @@ -427,7 +446,7 @@ FT_BEGIN_HEADER * at smaller sizes. * * For the auto-hinter, stem-darkening is experimental currently and thus - * switched off by default (this is, `no-stem-darkening` is set to TRUE + * switched off by default (that is, `no-stem-darkening` is set to TRUE * by default). Total consistency with the CFF driver is not achieved * right now because the emboldening method differs and glyphs must be * scaled down on the Y-axis to keep outline points inside their @@ -632,11 +651,8 @@ FT_BEGIN_HEADER * Windows~98; only grayscale and B/W rasterizing is supported. * * TT_INTERPRETER_VERSION_38 :: - * Version~38 corresponds to MS rasterizer v.1.9; it is roughly - * equivalent to the hinting provided by DirectWrite ClearType (as can - * be found, for example, in the Internet Explorer~9 running on - * Windows~7). It is used in FreeType to select the 'Infinality' - * subpixel hinting code. The code may be removed in a future version. + * Version~38 is the same Version~40. The original 'Infinality' code is + * no longer available. * * TT_INTERPRETER_VERSION_40 :: * Version~40 corresponds to MS rasterizer v.2.1; it is roughly @@ -801,6 +817,39 @@ FT_BEGIN_HEADER * 2.5 */ + /************************************************************************** + * + * @property: + * svg-hooks + * + * @description: + * Set up the interface between FreeType and an extern SVG rendering + * library like 'librsvg'. All details on the function hooks can be + * found in section @svg_fonts. + * + * @example: + * The following example code expects that the four hook functions + * `svg_*` are defined elsewhere. Error handling is omitted, too. + * + * ``` + * FT_Library library; + * SVG_RendererHooks hooks = { + * (SVG_Lib_Init_Func)svg_init, + * (SVG_Lib_Free_Func)svg_free, + * (SVG_Lib_Render_Func)svg_render, + * (SVG_Lib_Preset_Slot_Func)svg_preset_slot }; + * + * + * FT_Init_FreeType( &library ); + * + * FT_Property_Set( library, "ot-svg", + * "svg-hooks", &hooks ); + * ``` + * + * @since: + * 2.12 + */ + /************************************************************************** * @@ -1166,48 +1215,18 @@ FT_BEGIN_HEADER * warping * * @description: - * **Experimental only** + * **Obsolete** * - * If FreeType gets compiled with option `AF_CONFIG_OPTION_USE_WARPER` to - * activate the warp hinting code in the auto-hinter, this property - * switches warping on and off. + * This property was always experimental and probably never worked + * correctly. It was entirely removed from the FreeType~2 sources. This + * entry is only here for historical reference. * - * Warping only works in 'normal' auto-hinting mode replacing it. The - * idea of the code is to slightly scale and shift a glyph along the + * Warping only worked in 'normal' auto-hinting mode replacing it. The + * idea of the code was to slightly scale and shift a glyph along the * non-hinted dimension (which is usually the horizontal axis) so that as - * much of its segments are aligned (more or less) to the grid. To find + * much of its segments were aligned (more or less) to the grid. To find * out a glyph's optimal scaling and shifting value, various parameter - * combinations are tried and scored. - * - * By default, warping is off. - * - * @note: - * This property can be used with @FT_Property_Get also. - * - * This property can be set via the `FREETYPE_PROPERTIES` environment - * variable (using values 1 and 0 for 'on' and 'off', respectively). - * - * The warping code can also change advance widths. Have a look at the - * `lsb_delta` and `rsb_delta` fields in the @FT_GlyphSlotRec structure - * for details on improving inter-glyph distances while rendering. - * - * Since warping is a global property of the auto-hinter it is best to - * change its value before rendering any face. Otherwise, you should - * reload all faces that get auto-hinted in 'normal' hinting mode. - * - * @example: - * This example shows how to switch on warping (omitting the error - * handling). - * - * ``` - * FT_Library library; - * FT_Bool warping = 1; - * - * - * FT_Init_FreeType( &library ); - * - * FT_Property_Set( library, "autofitter", "warping", &warping ); - * ``` + * combinations were tried and scored. * * @since: * 2.6 diff --git a/lib/libesp32_lvgl/freetype/include/freetype/fterrdef.h b/lib/libesp32_lvgl/freetype/include/freetype/fterrdef.h index 895d2d4dc..d59b3cc2d 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/fterrdef.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/fterrdef.h @@ -4,7 +4,7 @@ * * FreeType error codes (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -101,6 +101,8 @@ "too many hints" ) FT_ERRORDEF_( Invalid_Pixel_Size, 0x17, "invalid pixel size" ) + FT_ERRORDEF_( Invalid_SVG_Document, 0x18, + "invalid SVG document" ) /* handle errors */ @@ -234,6 +236,8 @@ "found FDEF or IDEF opcode in glyf bytecode" ) FT_ERRORDEF_( Missing_Bitmap, 0x9D, "missing bitmap in strike" ) + FT_ERRORDEF_( Missing_SVG_Hooks, 0x9E, + "SVG hooks have not been set" ) /* CFF, CID, and Type 1 errors */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/fterrors.h b/lib/libesp32_lvgl/freetype/include/freetype/fterrors.h index 60a637c77..15ef3f76b 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/fterrors.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/fterrors.h @@ -4,7 +4,7 @@ * * FreeType error code handling (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -29,7 +29,7 @@ * * @description: * The header file `fterrors.h` (which is automatically included by - * `freetype.h` defines the handling of FreeType's enumeration + * `freetype.h`) defines the handling of FreeType's enumeration * constants. It can also be used to generate error message strings * with a small macro trick explained below. * @@ -281,6 +281,8 @@ FT_BEGIN_HEADER FT_EXPORT( const char* ) FT_Error_String( FT_Error error_code ); + /* */ + FT_END_HEADER diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftfntfmt.h b/lib/libesp32_lvgl/freetype/include/freetype/ftfntfmt.h index f803349cd..c0018fc83 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftfntfmt.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftfntfmt.h @@ -4,7 +4,7 @@ * * Support functions for font formats. * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftgasp.h b/lib/libesp32_lvgl/freetype/include/freetype/ftgasp.h index 6b76882c7..d5f19add8 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftgasp.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftgasp.h @@ -4,7 +4,7 @@ * * Access of TrueType's 'gasp' table (specification). * - * Copyright (C) 2007-2020 by + * Copyright (C) 2007-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftglyph.h b/lib/libesp32_lvgl/freetype/include/freetype/ftglyph.h index 704619e3d..4658895f7 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftglyph.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftglyph.h @@ -4,7 +4,7 @@ * * FreeType convenience functions to handle glyphs (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -126,7 +126,7 @@ FT_BEGIN_HEADER * * @description: * A handle to an object used to model a bitmap glyph image. This is a - * sub-class of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec. + * 'sub-class' of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec. */ typedef struct FT_BitmapGlyphRec_* FT_BitmapGlyph; @@ -142,7 +142,7 @@ FT_BEGIN_HEADER * * @fields: * root :: - * The root @FT_Glyph fields. + * The root fields of @FT_Glyph. * * left :: * The left-side bearing, i.e., the horizontal distance from the @@ -181,7 +181,7 @@ FT_BEGIN_HEADER * * @description: * A handle to an object used to model an outline glyph image. This is a - * sub-class of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec. + * 'sub-class' of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec. */ typedef struct FT_OutlineGlyphRec_* FT_OutlineGlyph; @@ -222,6 +222,92 @@ FT_BEGIN_HEADER } FT_OutlineGlyphRec; + /************************************************************************** + * + * @type: + * FT_SvgGlyph + * + * @description: + * A handle to an object used to model an SVG glyph. This is a + * 'sub-class' of @FT_Glyph, and a pointer to @FT_SvgGlyphRec. + * + * @since: + * 2.12 + */ + typedef struct FT_SvgGlyphRec_* FT_SvgGlyph; + + + /************************************************************************** + * + * @struct: + * FT_SvgGlyphRec + * + * @description: + * A structure used for OT-SVG glyphs. This is a 'sub-class' of + * @FT_GlyphRec. + * + * @fields: + * root :: + * The root @FT_GlyphRec fields. + * + * svg_document :: + * A pointer to the SVG document. + * + * svg_document_length :: + * The length of `svg_document`. + * + * glyph_index :: + * The index of the glyph to be rendered. + * + * metrics :: + * A metrics object storing the size information. + * + * units_per_EM :: + * The size of the EM square. + * + * start_glyph_id :: + * The first glyph ID in the glyph range covered by this document. + * + * end_glyph_id :: + * The last glyph ID in the glyph range covered by this document. + * + * transform :: + * A 2x2 transformation matrix to apply to the glyph while rendering + * it. + * + * delta :: + * Translation to apply to the glyph while rendering. + * + * @note: + * The Glyph Management API requires @FT_Glyph or its 'sub-class' to have + * all the information needed to completely define the glyph's rendering. + * Outline-based glyphs can directly apply transformations to the outline + * but this is not possible for an SVG document that hasn't been parsed. + * Therefore, the transformation is stored along with the document. In + * the absence of a 'ViewBox' or 'Width'/'Height' attribute, the size of + * the ViewPort should be assumed to be 'units_per_EM'. + */ + typedef struct FT_SvgGlyphRec_ + { + FT_GlyphRec root; + + FT_Byte* svg_document; + FT_ULong svg_document_length; + + FT_UInt glyph_index; + + FT_Size_Metrics metrics; + FT_UShort units_per_EM; + + FT_UShort start_glyph_id; + FT_UShort end_glyph_id; + + FT_Matrix transform; + FT_Vector delta; + + } FT_SvgGlyphRec; + + /************************************************************************** * * @function: @@ -269,7 +355,7 @@ FT_BEGIN_HEADER * * @output: * aglyph :: - * A handle to the glyph object. + * A handle to the glyph object. `NULL` in case of error. * * @return: * FreeType error code. 0~means success. @@ -299,7 +385,7 @@ FT_BEGIN_HEADER * * @output: * target :: - * A handle to the target glyph object. 0~in case of error. + * A handle to the target glyph object. `NULL` in case of error. * * @return: * FreeType error code. 0~means success. @@ -327,7 +413,7 @@ FT_BEGIN_HEADER * * delta :: * A pointer to a 2d vector to apply. Coordinates are expressed in - * 1/64th of a pixel. + * 1/64 of a pixel. * * @return: * FreeType error code (if not 0, the glyph format is not scalable). @@ -337,9 +423,9 @@ FT_BEGIN_HEADER * vector. */ FT_EXPORT( FT_Error ) - FT_Glyph_Transform( FT_Glyph glyph, - FT_Matrix* matrix, - FT_Vector* delta ); + FT_Glyph_Transform( FT_Glyph glyph, + const FT_Matrix* matrix, + const FT_Vector* delta ); /************************************************************************** @@ -414,7 +500,7 @@ FT_BEGIN_HEADER * @output: * acbox :: * The glyph coordinate bounding box. Coordinates are expressed in - * 1/64th of pixels if it is grid-fitted. + * 1/64 of pixels if it is grid-fitted. * * @note: * Coordinates are relative to the glyph origin, using the y~upwards @@ -498,9 +584,9 @@ FT_BEGIN_HEADER * The glyph image is translated with the `origin` vector before * rendering. * - * The first parameter is a pointer to an @FT_Glyph handle, that will be + * The first parameter is a pointer to an @FT_Glyph handle that will be * _replaced_ by this function (with newly allocated data). Typically, - * you would use (omitting error handling): + * you would do something like the following (omitting error handling). * * ``` * FT_Glyph glyph; @@ -517,7 +603,7 @@ FT_BEGIN_HEADER * if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) * { * error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, - * 0, 1 ); + * 0, 1 ); * if ( error ) // `glyph' unchanged * ... * } @@ -532,7 +618,7 @@ FT_BEGIN_HEADER * FT_Done_Glyph( glyph ); * ``` * - * Here is another example, again without error handling: + * Here is another example, again without error handling. * * ``` * FT_Glyph glyphs[MAX_GLYPHS] @@ -569,10 +655,10 @@ FT_BEGIN_HEADER * ``` */ FT_EXPORT( FT_Error ) - FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, - FT_Render_Mode render_mode, - FT_Vector* origin, - FT_Bool destroy ); + FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, + FT_Render_Mode render_mode, + const FT_Vector* origin, + FT_Bool destroy ); /************************************************************************** @@ -585,7 +671,7 @@ FT_BEGIN_HEADER * * @input: * glyph :: - * A handle to the target glyph object. + * A handle to the target glyph object. Can be `NULL`. */ FT_EXPORT( void ) FT_Done_Glyph( FT_Glyph glyph ); diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftgxval.h b/lib/libesp32_lvgl/freetype/include/freetype/ftgxval.h index 354460a9a..e8de9a6ed 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftgxval.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftgxval.h @@ -4,7 +4,7 @@ * * FreeType API for validating TrueTypeGX/AAT tables (specification). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * Masatake YAMATO, Redhat K.K, * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftgzip.h b/lib/libesp32_lvgl/freetype/include/freetype/ftgzip.h index ec5939a19..443ec29db 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftgzip.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftgzip.h @@ -4,7 +4,7 @@ * * Gzip-compressed stream support. * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftimage.h b/lib/libesp32_lvgl/freetype/include/freetype/ftimage.h index 74911620d..6baa81256 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftimage.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftimage.h @@ -5,7 +5,7 @@ * FreeType glyph image formats and default raster interface * (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -19,7 +19,7 @@ /************************************************************************** * * Note: A 'raster' is simply a scan-line converter, used to render - * FT_Outlines into FT_Bitmaps. + * `FT_Outline`s into `FT_Bitmap`s. * */ @@ -28,11 +28,6 @@ #define FTIMAGE_H_ - /* STANDALONE_ is from ftgrays.c */ -#ifndef STANDALONE_ -#endif - - FT_BEGIN_HEADER @@ -201,6 +196,11 @@ FT_BEGIN_HEADER #define ft_pixel_mode_pal2 FT_PIXEL_MODE_GRAY2 #define ft_pixel_mode_pal4 FT_PIXEL_MODE_GRAY4 + /* */ + + /* For debugging, the @FT_Pixel_Mode enumeration must stay in sync */ + /* with the `pixel_modes` array in file `ftobjs.c`. */ + /************************************************************************** * @@ -256,6 +256,12 @@ FT_BEGIN_HEADER * palette :: * A typeless pointer to the bitmap palette; this field is intended for * paletted pixel modes. Not used currently. + * + * @note: + * `width` and `rows` refer to the *physical* size of the bitmap, not the + * *logical* one. For example, if @FT_Pixel_Mode is set to + * `FT_PIXEL_MODE_LCD`, the logical width is a just a third of the + * physical one. */ typedef struct FT_Bitmap_ { @@ -401,11 +407,11 @@ FT_BEGIN_HEADER * information. * * FT_OUTLINE_OVERLAP :: - * This flag indicates that this outline contains overlapping contrours - * and the anti-aliased renderer should perform oversampling to - * mitigate possible artifacts. This flag should _not_ be set for - * well designed glyphs without overlaps because it quadruples the - * rendering time. + * [Since 2.10.3] This flag indicates that this outline contains + * overlapping contours and the anti-aliased renderer should perform + * oversampling to mitigate possible artifacts. This flag should _not_ + * be set for well designed glyphs without overlaps because it quadruples + * the rendering time. * * FT_OUTLINE_HIGH_PRECISION :: * This flag indicates that the scan-line converter should try to @@ -695,11 +701,13 @@ FT_BEGIN_HEADER * to get a simple enumeration without assigning special numbers. */ #ifndef FT_IMAGE_TAG -#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) \ - value = ( ( (unsigned long)_x1 << 24 ) | \ - ( (unsigned long)_x2 << 16 ) | \ - ( (unsigned long)_x3 << 8 ) | \ - (unsigned long)_x4 ) + +#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) \ + value = ( ( FT_STATIC_BYTE_CAST( unsigned long, _x1 ) << 24 ) | \ + ( FT_STATIC_BYTE_CAST( unsigned long, _x2 ) << 16 ) | \ + ( FT_STATIC_BYTE_CAST( unsigned long, _x3 ) << 8 ) | \ + FT_STATIC_BYTE_CAST( unsigned long, _x4 ) ) + #endif /* FT_IMAGE_TAG */ @@ -739,6 +747,10 @@ FT_BEGIN_HEADER * contours. Some Type~1 fonts, like those in the Hershey family, * contain glyphs in this format. These are described as @FT_Outline, * but FreeType isn't currently capable of rendering them correctly. + * + * FT_GLYPH_FORMAT_SVG :: + * [Since 2.12] The glyph is represented by an SVG document in the + * 'SVG~' table. */ typedef enum FT_Glyph_Format_ { @@ -747,7 +759,8 @@ FT_BEGIN_HEADER FT_IMAGE_TAG( FT_GLYPH_FORMAT_COMPOSITE, 'c', 'o', 'm', 'p' ), FT_IMAGE_TAG( FT_GLYPH_FORMAT_BITMAP, 'b', 'i', 't', 's' ), FT_IMAGE_TAG( FT_GLYPH_FORMAT_OUTLINE, 'o', 'u', 't', 'l' ), - FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER, 'p', 'l', 'o', 't' ) + FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER, 'p', 'l', 'o', 't' ), + FT_IMAGE_TAG( FT_GLYPH_FORMAT_SVG, 'S', 'V', 'G', ' ' ) } FT_Glyph_Format; @@ -772,17 +785,6 @@ FT_BEGIN_HEADER /*************************************************************************/ - /************************************************************************** - * - * A raster is a scan converter, in charge of rendering an outline into a - * bitmap. This section contains the public API for rasters. - * - * Note that in FreeType 2, all rasters are now encapsulated within - * specific modules called 'renderers'. See `ftrender.h` for more details - * on renderers. - * - */ - /************************************************************************** * @@ -796,16 +798,35 @@ FT_BEGIN_HEADER * How vectorial outlines are converted into bitmaps and pixmaps. * * @description: - * This section contains technical definitions. + * A raster or a rasterizer is a scan converter in charge of producing a + * pixel coverage bitmap that can be used as an alpha channel when + * compositing a glyph with a background. FreeType comes with two + * rasterizers: bilevel `raster1` and anti-aliased `smooth` are two + * separate modules. They are usually called from the high-level + * @FT_Load_Glyph or @FT_Render_Glyph functions and produce the entire + * coverage bitmap at once, while staying largely invisible to users. + * + * Instead of working with complete coverage bitmaps, it is also possible + * to intercept consecutive pixel runs on the same scanline with the same + * coverage, called _spans_, and process them individually. Only the + * `smooth` rasterizer permits this when calling @FT_Outline_Render with + * @FT_Raster_Params as described below. + * + * Working with either complete bitmaps or spans it is important to think + * of them as colorless coverage objects suitable as alpha channels to + * blend arbitrary colors with a background. For best results, it is + * recommended to use gamma correction, too. + * + * This section also describes the public API needed to set up alternative + * @FT_Renderer modules. * * @order: - * FT_Raster * FT_Span * FT_SpanFunc - * * FT_Raster_Params * FT_RASTER_FLAG_XXX * + * FT_Raster * FT_Raster_NewFunc * FT_Raster_DoneFunc * FT_Raster_ResetFunc @@ -816,26 +837,14 @@ FT_BEGIN_HEADER */ - /************************************************************************** - * - * @type: - * FT_Raster - * - * @description: - * An opaque handle (pointer) to a raster object. Each object can be - * used independently to convert an outline into a bitmap or pixmap. - */ - typedef struct FT_RasterRec_* FT_Raster; - - /************************************************************************** * * @struct: * FT_Span * * @description: - * A structure used to model a single span of gray pixels when rendering - * an anti-aliased bitmap. + * A structure to model a single span of consecutive pixels when + * rendering an anti-aliased bitmap. * * @fields: * x :: @@ -852,8 +861,8 @@ FT_BEGIN_HEADER * This structure is used by the span drawing callback type named * @FT_SpanFunc that takes the y~coordinate of the span as a parameter. * - * The coverage value is always between 0 and 255. If you want less gray - * values, the callback function has to reduce them. + * The anti-aliased rasterizer produces coverage values from 0 to 255, + * that is, from completely transparent to completely opaque. */ typedef struct FT_Span_ { @@ -871,8 +880,8 @@ FT_BEGIN_HEADER * * @description: * A function used as a call-back by the anti-aliased renderer in order - * to let client applications draw themselves the gray pixel spans on - * each scan line. + * to let client applications draw themselves the pixel spans on each + * scan line. * * @input: * y :: @@ -888,11 +897,12 @@ FT_BEGIN_HEADER * User-supplied data that is passed to the callback. * * @note: - * This callback allows client applications to directly render the gray - * spans of the anti-aliased bitmap to any kind of surfaces. + * This callback allows client applications to directly render the spans + * of the anti-aliased bitmap to any kind of surfaces. * * This can be used to write anti-aliased outlines directly to a given - * background bitmap, and even perform translucency. + * background bitmap using alpha compositing. It can also be used for + * oversampling and averaging. */ typedef void (*FT_SpanFunc)( int y, @@ -962,11 +972,17 @@ FT_BEGIN_HEADER * will be clipped to a box specified in the `clip_box` field of the * @FT_Raster_Params structure. Otherwise, the `clip_box` is * effectively set to the bounding box and all spans are generated. + * + * FT_RASTER_FLAG_SDF :: + * This flag is set to indicate that a signed distance field glyph + * image should be generated. This is only used while rendering with + * the @FT_RENDER_MODE_SDF render mode. */ #define FT_RASTER_FLAG_DEFAULT 0x0 #define FT_RASTER_FLAG_AA 0x1 #define FT_RASTER_FLAG_DIRECT 0x2 #define FT_RASTER_FLAG_CLIP 0x4 +#define FT_RASTER_FLAG_SDF 0x8 /* these constants are deprecated; use the corresponding */ /* `FT_RASTER_FLAG_XXX` values instead */ @@ -1047,6 +1063,23 @@ FT_BEGIN_HEADER } FT_Raster_Params; + /************************************************************************** + * + * @type: + * FT_Raster + * + * @description: + * An opaque handle (pointer) to a raster object. Each object can be + * used independently to convert an outline into a bitmap or pixmap. + * + * @note: + * In FreeType 2, all rasters are now encapsulated within specific + * @FT_Renderer modules and only used in their context. + * + */ + typedef struct FT_RasterRec_* FT_Raster; + + /************************************************************************** * * @functype: diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftincrem.h b/lib/libesp32_lvgl/freetype/include/freetype/ftincrem.h index f67655eda..2d4f5def2 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftincrem.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftincrem.h @@ -4,7 +4,7 @@ * * FreeType incremental loading (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -213,9 +213,14 @@ FT_BEGIN_HEADER * * @description: * A function used to retrieve the basic metrics of a given glyph index - * before accessing its data. This is necessary because, in certain - * formats like TrueType, the metrics are stored in a different place - * from the glyph images proper. + * before accessing its data. This allows for handling font types such + * as PCL~XL Format~1, Class~2 downloaded TrueType fonts, where the glyph + * metrics (`hmtx` and `vmtx` tables) are permitted to be omitted from + * the font, and the relevant metrics included in the header of the glyph + * outline data. Importantly, this is not intended to allow custom glyph + * metrics (for example, Postscript Metrics dictionaries), because that + * conflicts with the requirements of outline hinting. Such custom + * metrics must be handled separately, by the calling application. * * @input: * incremental :: @@ -235,7 +240,7 @@ FT_BEGIN_HEADER * * @output: * ametrics :: - * The replacement glyph metrics in font units. + * The glyph metrics in font units. * */ typedef FT_Error @@ -264,7 +269,7 @@ FT_BEGIN_HEADER * * get_glyph_metrics :: * The function to get glyph metrics. May be null if the font does not - * provide overriding glyph metrics. + * require it. * */ typedef struct FT_Incremental_FuncsRec_ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftlcdfil.h b/lib/libesp32_lvgl/freetype/include/freetype/ftlcdfil.h index c6995f2ff..d3723e16f 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftlcdfil.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftlcdfil.h @@ -5,7 +5,7 @@ * FreeType API for color filtering of subpixel bitmap glyphs * (specification). * - * Copyright (C) 2006-2020 by + * Copyright (C) 2006-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -44,7 +44,7 @@ FT_BEGIN_HEADER * API to control subpixel rendering. * * @description: - * FreeType provides two alternative subpixel rendering technologies. + * FreeType provides two alternative subpixel rendering technologies. * Should you define `FT_CONFIG_OPTION_SUBPIXEL_RENDERING` in your * `ftoption.h` file, this enables ClearType-style rendering. * Otherwise, Harmony LCD rendering is enabled. These technologies are @@ -55,13 +55,12 @@ FT_BEGIN_HEADER * ClearType-style LCD rendering exploits the color-striped structure of * LCD pixels, increasing the available resolution in the direction of * the stripe (usually horizontal RGB) by a factor of~3. Using the - * subpixels coverages unfiltered can create severe color fringes + * subpixel coverages unfiltered can create severe color fringes * especially when rendering thin features. Indeed, to produce * black-on-white text, the nearby color subpixels must be dimmed - * equally. - * - * A good 5-tap FIR filter should be applied to subpixel coverages - * regardless of pixel boundaries and should have these properties: + * evenly. Therefore, an equalizing 5-tap FIR filter should be applied + * to subpixel coverages regardless of pixel boundaries and should have + * these properties: * * 1. It should be symmetrical, like {~a, b, c, b, a~}, to avoid * any shifts in appearance. @@ -84,7 +83,7 @@ FT_BEGIN_HEADER * Harmony LCD rendering is suitable to panels with any regular subpixel * structure, not just monitors with 3 color striped subpixels, as long * as the color subpixels have fixed positions relative to the pixel - * center. In this case, each color channel is then rendered separately + * center. In this case, each color channel can be rendered separately * after shifting the outline opposite to the subpixel shift so that the * coverage maps are aligned. This method is immune to color fringes * because the shifts do not change integral coverage. @@ -101,9 +100,9 @@ FT_BEGIN_HEADER * clockwise. Harmony with default LCD geometry is equivalent to * ClearType with light filter. * - * As a result of ClearType filtering or Harmony rendering, the - * dimensions of LCD bitmaps can be either wider or taller than the - * dimensions of the corresponding outline with regard to the pixel grid. + * As a result of ClearType filtering or Harmony shifts, the resulting + * dimensions of LCD bitmaps can be slightly wider or taller than the + * dimensions the original outline with regard to the pixel grid. * For example, for @FT_RENDER_MODE_LCD, the filter adds 2~subpixels to * the left, and 2~subpixels to the right. The bitmap offset values are * adjusted accordingly, so clients shouldn't need to modify their layout @@ -138,11 +137,11 @@ FT_BEGIN_HEADER * * FT_LCD_FILTER_DEFAULT :: * This is a beveled, normalized, and color-balanced five-tap filter - * with weights of [0x08 0x4D 0x56 0x4D 0x08] in 1/256th units. + * with weights of [0x08 0x4D 0x56 0x4D 0x08] in 1/256 units. * * FT_LCD_FILTER_LIGHT :: * this is a boxy, normalized, and color-balanced three-tap filter with - * weights of [0x00 0x55 0x56 0x55 0x00] in 1/256th units. + * weights of [0x00 0x55 0x56 0x55 0x00] in 1/256 units. * * FT_LCD_FILTER_LEGACY :: * FT_LCD_FILTER_LEGACY1 :: @@ -227,7 +226,7 @@ FT_BEGIN_HEADER * * weights :: * A pointer to an array; the function copies the first five bytes and - * uses them to specify the filter weights in 1/256th units. + * uses them to specify the filter weights in 1/256 units. * * @return: * FreeType error code. 0~means success. diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftlist.h b/lib/libesp32_lvgl/freetype/include/freetype/ftlist.h index 458892270..b55313133 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftlist.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftlist.h @@ -4,7 +4,7 @@ * * Generic list support for FreeType (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftlogging.h b/lib/libesp32_lvgl/freetype/include/freetype/ftlogging.h new file mode 100644 index 000000000..53b8b8964 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftlogging.h @@ -0,0 +1,184 @@ +/**************************************************************************** + * + * ftlogging.h + * + * Additional debugging APIs. + * + * Copyright (C) 2020-2023 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#ifndef FTLOGGING_H_ +#define FTLOGGING_H_ + + +#include +#include FT_CONFIG_CONFIG_H + + +FT_BEGIN_HEADER + + + /************************************************************************** + * + * @section: + * debugging_apis + * + * @title: + * External Debugging APIs + * + * @abstract: + * Public APIs to control the `FT_DEBUG_LOGGING` macro. + * + * @description: + * This section contains the declarations of public functions that + * enables fine control of what the `FT_DEBUG_LOGGING` macro outputs. + * + */ + + + /************************************************************************** + * + * @function: + * FT_Trace_Set_Level + * + * @description: + * Change the levels of tracing components of FreeType at run time. + * + * @input: + * tracing_level :: + * New tracing value. + * + * @example: + * The following call makes FreeType trace everything but the 'memory' + * component. + * + * ``` + * FT_Trace_Set_Level( "any:7 memory:0" ); + * ``` + * + * @note: + * This function does nothing if compilation option `FT_DEBUG_LOGGING` + * isn't set. + * + * @since: + * 2.11 + * + */ + FT_EXPORT( void ) + FT_Trace_Set_Level( const char* tracing_level ); + + + /************************************************************************** + * + * @function: + * FT_Trace_Set_Default_Level + * + * @description: + * Reset tracing value of FreeType's components to the default value + * (i.e., to the value of the `FT2_DEBUG` environment value or to NULL + * if `FT2_DEBUG` is not set). + * + * @note: + * This function does nothing if compilation option `FT_DEBUG_LOGGING` + * isn't set. + * + * @since: + * 2.11 + * + */ + FT_EXPORT( void ) + FT_Trace_Set_Default_Level( void ); + + + /************************************************************************** + * + * @functype: + * FT_Custom_Log_Handler + * + * @description: + * A function typedef that is used to handle the logging of tracing and + * debug messages on a file system. + * + * @input: + * ft_component :: + * The name of `FT_COMPONENT` from which the current debug or error + * message is produced. + * + * fmt :: + * Actual debug or tracing message. + * + * args:: + * Arguments of debug or tracing messages. + * + * @since: + * 2.11 + * + */ + typedef void + (*FT_Custom_Log_Handler)( const char* ft_component, + const char* fmt, + va_list args ); + + + /************************************************************************** + * + * @function: + * FT_Set_Log_Handler + * + * @description: + * A function to set a custom log handler. + * + * @input: + * handler :: + * New logging function. + * + * @note: + * This function does nothing if compilation option `FT_DEBUG_LOGGING` + * isn't set. + * + * @since: + * 2.11 + * + */ + FT_EXPORT( void ) + FT_Set_Log_Handler( FT_Custom_Log_Handler handler ); + + + /************************************************************************** + * + * @function: + * FT_Set_Default_Log_Handler + * + * @description: + * A function to undo the effect of @FT_Set_Log_Handler, resetting the + * log handler to FreeType's built-in version. + * + * @note: + * This function does nothing if compilation option `FT_DEBUG_LOGGING` + * isn't set. + * + * @since: + * 2.11 + * + */ + FT_EXPORT( void ) + FT_Set_Default_Log_Handler( void ); + + /* */ + + +FT_END_HEADER + +#endif /* FTLOGGING_H_ */ + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftlzw.h b/lib/libesp32_lvgl/freetype/include/freetype/ftlzw.h index ae46ad602..adfd17247 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftlzw.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftlzw.h @@ -4,7 +4,7 @@ * * LZW-compressed stream support. * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftmac.h b/lib/libesp32_lvgl/freetype/include/freetype/ftmac.h index c9de98184..a91e38f9e 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftmac.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftmac.h @@ -4,7 +4,7 @@ * * Additional Mac-specific API. * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftmm.h b/lib/libesp32_lvgl/freetype/include/freetype/ftmm.h index d8781a829..d145128a9 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftmm.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftmm.h @@ -4,7 +4,7 @@ * * FreeType Multiple Master font interface (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -47,6 +47,9 @@ FT_BEGIN_HEADER * MM fonts, others will work with all three types. They are similar * enough that a consistent interface makes sense. * + * For Adobe MM fonts, macro @FT_IS_SFNT returns false. For GX and + * OpenType variation fonts, it returns true. + * */ @@ -150,7 +153,7 @@ FT_BEGIN_HEADER * @note: * The fields `minimum`, `def`, and `maximum` are 16.16 fractional values * for TrueType GX and OpenType variation fonts. For Adobe MM fonts, the - * values are integers. + * values are whole numbers (i.e., the fractional part is zero). */ typedef struct FT_Var_Axis_ { @@ -395,6 +398,10 @@ FT_BEGIN_HEADER * FreeType error code. 0~means success. * * @note: + * The design coordinates are 16.16 fractional values for TrueType GX and + * OpenType variation fonts. For Adobe MM fonts, the values are supposed + * to be whole numbers (i.e., the fractional part is zero). + * * [Since 2.8.1] To reset all axes to the default values, call the * function with `num_coords` set to zero and `coords` set to `NULL`. * [Since 2.9] 'Default values' means the currently selected named @@ -437,6 +444,11 @@ FT_BEGIN_HEADER * @return: * FreeType error code. 0~means success. * + * @note: + * The design coordinates are 16.16 fractional values for TrueType GX and + * OpenType variation fonts. For Adobe MM fonts, the values are whole + * numbers (i.e., the fractional part is zero). + * * @since: * 2.7.1 */ @@ -468,9 +480,9 @@ FT_BEGIN_HEADER * the number of axes, use default values for the remaining axes. * * coords :: - * The design coordinates array (each element must be between 0 and 1.0 - * for Adobe MM fonts, and between -1.0 and 1.0 for TrueType GX and - * OpenType variation fonts). + * The design coordinates array. Each element is a 16.16 fractional + * value and must be between 0 and 1.0 for Adobe MM fonts, and between + * -1.0 and 1.0 for TrueType GX and OpenType variation fonts. * * @return: * FreeType error code. 0~means success. @@ -515,7 +527,7 @@ FT_BEGIN_HEADER * * @output: * coords :: - * The normalized blend coordinates array. + * The normalized blend coordinates array (as 16.16 fractional values). * * @return: * FreeType error code. 0~means success. @@ -590,10 +602,12 @@ FT_BEGIN_HEADER * * @note: * Adobe Multiple Master fonts limit the number of designs, and thus the - * length of the weight vector to~16. + * length of the weight vector to 16~elements. * - * If `len` is zero and `weightvector` is `NULL`, the weight vector array - * is reset to the default values. + * If `len` is larger than zero, this function sets the + * @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags` field (i.e., + * @FT_IS_VARIATION will return true). If `len` is zero, this bit flag + * is unset and the weight vector array is reset to the default values. * * The Adobe documentation also states that the values in the * WeightVector array must total 1.0 +/-~0.001. In practice this does @@ -741,6 +755,45 @@ FT_BEGIN_HEADER FT_Set_Named_Instance( FT_Face face, FT_UInt instance_index ); + + /************************************************************************** + * + * @function: + * FT_Get_Default_Named_Instance + * + * @description: + * Retrieve the index of the default named instance, to be used with + * @FT_Set_Named_Instance. + * + * The default instance of a variation font is that instance for which + * the nth axis coordinate is equal to `axis[n].def` (as specified in the + * @FT_MM_Var structure), with~n covering all axes. + * + * FreeType synthesizes a named instance for the default instance if the + * font does not contain such an entry. + * + * @input: + * face :: + * A handle to the source face. + * + * @output: + * instance_index :: + * The index of the default named instance. + * + * @return: + * FreeType error code. 0~means success. + * + * @note: + * For Adobe MM fonts (which don't have named instances) this function + * always returns zero for `instance_index`. + * + * @since: + * 2.13.1 + */ + FT_EXPORT( FT_Error ) + FT_Get_Default_Named_Instance( FT_Face face, + FT_UInt *instance_index ); + /* */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftmodapi.h b/lib/libesp32_lvgl/freetype/include/freetype/ftmodapi.h index 3f7ae82ba..c8f0c2c2a 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftmodapi.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftmodapi.h @@ -4,7 +4,7 @@ * * FreeType modules public interface (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -45,10 +45,12 @@ FT_BEGIN_HEADER * * @description: * The definitions below are used to manage modules within FreeType. - * Modules can be added, upgraded, and removed at runtime. Additionally, - * some module properties can be controlled also. + * Internal and external modules can be added, upgraded, and removed at + * runtime. For example, an alternative renderer or proprietary font + * driver can be registered and prioritized. Additionally, some module + * properties can also be controlled. * - * Here is a list of possible values of the `module_name` field in the + * Here is a list of existing values of the `module_name` field in the * @FT_Module_Class structure. * * ``` @@ -86,6 +88,7 @@ FT_BEGIN_HEADER * FT_Remove_Module * FT_Add_Default_Modules * + * FT_FACE_DRIVER_NAME * FT_Property_Set * FT_Property_Get * FT_Set_Default_Properties @@ -328,6 +331,27 @@ FT_BEGIN_HEADER FT_Module module ); + /************************************************************************** + * + * @macro: + * FT_FACE_DRIVER_NAME + * + * @description: + * A macro that retrieves the name of a font driver from a face object. + * + * @note: + * The font driver name is a valid `module_name` for @FT_Property_Set + * and @FT_Property_Get. This is not the same as @FT_Get_Font_Format. + * + * @since: + * 2.11 + * + */ +#define FT_FACE_DRIVER_NAME( face ) \ + ( ( *FT_REINTERPRET_CAST( FT_Module_Class**, \ + ( face )->driver ) )->module_name ) + + /************************************************************************** * * @function: @@ -485,8 +509,7 @@ FT_BEGIN_HEADER * * ``` * FREETYPE_PROPERTIES=truetype:interpreter-version=35 \ - * cff:no-stem-darkening=0 \ - * autofitter:warping=1 + * cff:no-stem-darkening=0 * ``` * * @inout: diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftmoderr.h b/lib/libesp32_lvgl/freetype/include/freetype/ftmoderr.h index f05fc53aa..c8c892dcc 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftmoderr.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftmoderr.h @@ -4,7 +4,7 @@ * * FreeType module error offsets (specification). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -171,6 +171,7 @@ FT_MODERRDEF( Type42, 0x1400, "Type 42 module" ) FT_MODERRDEF( Winfonts, 0x1500, "Windows FON/FNT module" ) FT_MODERRDEF( GXvalid, 0x1600, "GX validation module" ) + FT_MODERRDEF( Sdf, 0x1700, "Signed distance field raster module" ) #ifdef FT_MODERR_END_LIST diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftotval.h b/lib/libesp32_lvgl/freetype/include/freetype/ftotval.h index 9c00ad30b..011bdfc83 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftotval.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftotval.h @@ -4,7 +4,7 @@ * * FreeType API for validating OpenType tables (specification). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftoutln.h b/lib/libesp32_lvgl/freetype/include/freetype/ftoutln.h index 84e9b144c..f9329ca40 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftoutln.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftoutln.h @@ -5,7 +5,7 @@ * Support for the FT_Outline type used to store glyph shapes of * most scalable font formats (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -109,14 +109,16 @@ FT_BEGIN_HEADER * FreeType error code. 0~means success. * * @note: - * A contour that contains a single point only is represented by a 'move - * to' operation followed by 'line to' to the same point. In most cases, - * it is best to filter this out before using the outline for stroking - * purposes (otherwise it would result in a visible dot when round caps - * are used). + * Degenerate contours, segments, and Bezier arcs may be reported. In + * most cases, it is best to filter these out before using the outline + * for stroking or other path modification purposes (which may cause + * degenerate segments to become non-degenrate and visible, like when + * stroke caps are used or the path is otherwise outset). Some glyph + * outlines may contain deliberate degenerate single points for mark + * attachement. * * Similarly, the function returns success for an empty outline also - * (doing nothing, this is, not calling any emitter); if necessary, you + * (doing nothing, that is, not calling any emitter); if necessary, you * should filter this out, too. */ FT_EXPORT( FT_Error ) diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftparams.h b/lib/libesp32_lvgl/freetype/include/freetype/ftparams.h index 55ea2a387..6a9f243bc 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftparams.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftparams.h @@ -4,7 +4,7 @@ * * FreeType API for possible FT_Parameter tags (specification only). * - * Copyright (C) 2017-2020 by + * Copyright (C) 2017-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -112,6 +112,21 @@ FT_BEGIN_HEADER FT_MAKE_TAG( 'i', 'n', 'c', 'r' ) + /************************************************************************** + * + * @enum: + * FT_PARAM_TAG_IGNORE_SBIX + * + * @description: + * A tag for @FT_Parameter to make @FT_Open_Face ignore an 'sbix' table + * while loading a font. Use this if @FT_FACE_FLAG_SBIX is set and you + * want to access the outline glyphs in the font. + * + */ +#define FT_PARAM_TAG_IGNORE_SBIX \ + FT_MAKE_TAG( 'i', 's', 'b', 'x' ) + + /************************************************************************** * * @enum: diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftpfr.h b/lib/libesp32_lvgl/freetype/include/freetype/ftpfr.h index 9a5383f91..7111d40a0 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftpfr.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftpfr.h @@ -4,7 +4,7 @@ * * FreeType API for accessing PFR-specific data (specification only). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -161,7 +161,7 @@ FT_BEGIN_HEADER * * @note: * You can use the `x_scale` or `y_scale` results of @FT_Get_PFR_Metrics - * to convert the advance to device subpixels (i.e., 1/64th of pixels). + * to convert the advance to device subpixels (i.e., 1/64 of pixels). */ FT_EXPORT( FT_Error ) FT_Get_PFR_Advance( FT_Face face, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftrender.h b/lib/libesp32_lvgl/freetype/include/freetype/ftrender.h index 8007951b3..0b6fad32e 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftrender.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftrender.h @@ -4,7 +4,7 @@ * * FreeType renderer modules public interface (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -158,7 +158,7 @@ FT_BEGIN_HEADER FT_Renderer_GetCBoxFunc get_glyph_cbox; FT_Renderer_SetModeFunc set_mode; - FT_Raster_Funcs* raster_class; + const FT_Raster_Funcs* raster_class; } FT_Renderer_Class; diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftsizes.h b/lib/libesp32_lvgl/freetype/include/freetype/ftsizes.h index a8682a30f..7bfb1aed4 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftsizes.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftsizes.h @@ -4,7 +4,7 @@ * * FreeType size objects management (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftsnames.h b/lib/libesp32_lvgl/freetype/include/freetype/ftsnames.h index 729e6ab06..9d5d22bb2 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftsnames.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftsnames.h @@ -7,7 +7,7 @@ * * This is _not_ used to retrieve glyph names! * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftstroke.h b/lib/libesp32_lvgl/freetype/include/freetype/ftstroke.h index a759c94dd..b3d90802a 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftstroke.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftstroke.h @@ -4,7 +4,7 @@ * * FreeType path stroker (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -293,7 +293,7 @@ FT_BEGIN_HEADER * * miter_limit :: * The maximum reciprocal sine of half-angle at the miter join, - * expressed as 16.16 fixed point value. + * expressed as 16.16 fixed-point value. * * @note: * The `radius` is expressed in the same units as the outline diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftsynth.h b/lib/libesp32_lvgl/freetype/include/freetype/ftsynth.h index bdb4c5753..af90967dd 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftsynth.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftsynth.h @@ -5,7 +5,7 @@ * FreeType synthesizing code for emboldening and slanting * (specification). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -68,10 +68,31 @@ FT_BEGIN_HEADER FT_EXPORT( void ) FT_GlyphSlot_Embolden( FT_GlyphSlot slot ); - /* Slant an outline glyph to the right by about 12 degrees. */ + /* Precisely adjust the glyph weight either horizontally or vertically. */ + /* The `xdelta` and `ydelta` values are fractions of the face Em size */ + /* (in fixed-point format). Considering that a regular face would have */ + /* stem widths on the order of 0.1 Em, a delta of 0.05 (0x0CCC) should */ + /* be very noticeable. To increase or decrease the weight, use positive */ + /* or negative values, respectively. */ + FT_EXPORT( void ) + FT_GlyphSlot_AdjustWeight( FT_GlyphSlot slot, + FT_Fixed xdelta, + FT_Fixed ydelta ); + + + /* Slant an outline glyph to the right by about 12 degrees. */ FT_EXPORT( void ) FT_GlyphSlot_Oblique( FT_GlyphSlot slot ); + /* Slant an outline glyph by a given sine of an angle. You can apply */ + /* slant along either x- or y-axis by choosing a corresponding non-zero */ + /* argument. If both slants are non-zero, some affine transformation */ + /* will result. */ + FT_EXPORT( void ) + FT_GlyphSlot_Slant( FT_GlyphSlot slot, + FT_Fixed xslant, + FT_Fixed yslant ); + /* */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftsystem.h b/lib/libesp32_lvgl/freetype/include/freetype/ftsystem.h index 22aead714..3a08f4912 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftsystem.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftsystem.h @@ -4,7 +4,7 @@ * * FreeType low-level system interface definition (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -229,7 +229,7 @@ FT_BEGIN_HEADER * A handle to the source stream. * * offset :: - * The offset of read in stream (always from start). + * The offset from the start of the stream to seek to. * * buffer :: * The address of the read buffer. @@ -238,11 +238,9 @@ FT_BEGIN_HEADER * The number of bytes to read from the stream. * * @return: - * The number of bytes effectively read by the stream. - * - * @note: - * This function might be called to perform a seek or skip operation with - * a `count` of~0. A non-zero return value then indicates an error. + * If count >~0, return the number of bytes effectively read by the + * stream (after seeking to `offset`). If count ==~0, return the status + * of the seek operation (non-zero indicates an error). * */ typedef unsigned long diff --git a/lib/libesp32_lvgl/freetype/include/freetype/fttrigon.h b/lib/libesp32_lvgl/freetype/include/freetype/fttrigon.h index 2ce6b324c..294981a6f 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/fttrigon.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/fttrigon.h @@ -4,7 +4,7 @@ * * FreeType trigonometric functions (specification). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/fttypes.h b/lib/libesp32_lvgl/freetype/include/freetype/fttypes.h index aaeb9e878..5b109f0c7 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/fttypes.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/fttypes.h @@ -4,7 +4,7 @@ * * FreeType simple types definitions (specification only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -45,7 +45,10 @@ FT_BEGIN_HEADER * @description: * This section contains the basic data types defined by FreeType~2, * ranging from simple scalar types to bitmap descriptors. More - * font-specific structures are defined in a different section. + * font-specific structures are defined in a different section. Note + * that FreeType does not use floating-point data types. Fractional + * values are represented by fixed-point integers, with lower bits + * storing the fractional part. * * @order: * FT_Byte @@ -413,7 +416,7 @@ FT_BEGIN_HEADER typedef struct FT_Data_ { const FT_Byte* pointer; - FT_Int length; + FT_UInt length; } FT_Data; @@ -479,18 +482,17 @@ FT_BEGIN_HEADER * * @description: * This macro converts four-letter tags that are used to label TrueType - * tables into an unsigned long, to be used within FreeType. + * tables into an `FT_Tag` type, to be used within FreeType. * * @note: * The produced values **must** be 32-bit integers. Don't redefine this * macro. */ -#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ - (FT_Tag) \ - ( ( (FT_ULong)_x1 << 24 ) | \ - ( (FT_ULong)_x2 << 16 ) | \ - ( (FT_ULong)_x3 << 8 ) | \ - (FT_ULong)_x4 ) +#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ + ( ( FT_STATIC_BYTE_CAST( FT_Tag, _x1 ) << 24 ) | \ + ( FT_STATIC_BYTE_CAST( FT_Tag, _x2 ) << 16 ) | \ + ( FT_STATIC_BYTE_CAST( FT_Tag, _x3 ) << 8 ) | \ + FT_STATIC_BYTE_CAST( FT_Tag, _x4 ) ) /*************************************************************************/ @@ -588,7 +590,7 @@ FT_BEGIN_HEADER #define FT_IS_EMPTY( list ) ( (list).head == 0 ) -#define FT_BOOL( x ) ( (FT_Bool)( (x) != 0 ) ) +#define FT_BOOL( x ) FT_STATIC_CAST( FT_Bool, (x) != 0 ) /* concatenate C tokens */ #define FT_ERR_XCAT( x, y ) x ## y diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ftwinfnt.h b/lib/libesp32_lvgl/freetype/include/freetype/ftwinfnt.h index 786528c6e..7b701ea59 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ftwinfnt.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ftwinfnt.h @@ -4,7 +4,7 @@ * * FreeType API for accessing Windows fnt-specific data. * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -55,7 +55,7 @@ FT_BEGIN_HEADER * FT_WinFNT_ID_XXX * * @description: - * A list of valid values for the `charset` byte in @FT_WinFNT_HeaderRec. + * A list of valid values for the `charset` byte in @FT_WinFNT_HeaderRec. * Exact mapping tables for the various 'cpXXXX' encodings (except for * 'cp1361') can be found at 'ftp://ftp.unicode.org/Public/' in the * `MAPPINGS/VENDORS/MICSFT/WINDOWS` subdirectory. 'cp1361' is roughly a diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/autohint.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/autohint.h index 2a472e20b..bf9c8b7cf 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/autohint.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/autohint.h @@ -4,7 +4,7 @@ * * High-level 'autohint' module-specific interface (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/cffotypes.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/cffotypes.h index a316fd1f3..50d535384 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/cffotypes.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/cffotypes.h @@ -4,7 +4,7 @@ * * Basic OpenType/CFF object type definitions (specification). * - * Copyright (C) 2017-2020 by + * Copyright (C) 2017-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/cfftypes.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/cfftypes.h index f21167b1e..c2521764c 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/cfftypes.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/cfftypes.h @@ -5,7 +5,7 @@ * Basic OpenType/CFF type definitions and interface (specification * only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -315,7 +315,7 @@ FT_BEGIN_HEADER /* The normal stack then points to these values instead of the DICT */ /* because all other operators in Private DICT clear the stack. */ /* `blend_stack' could be cleared at each operator other than blend. */ - /* Blended values are stored as 5-byte fixed point values. */ + /* Blended values are stored as 5-byte fixed-point values. */ FT_Byte* blend_stack; /* base of stack allocation */ FT_Byte* blend_top; /* first empty slot */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/compiler-macros.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/compiler-macros.h index 97c18d3a2..6f6765097 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/compiler-macros.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/compiler-macros.h @@ -4,7 +4,7 @@ * * Compiler-specific macro definitions used internally by FreeType. * - * Copyright (C) 2020 by + * Copyright (C) 2020-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -34,6 +34,22 @@ FT_BEGIN_HEADER # if defined( _COMPILER_VERSION ) && ( _COMPILER_VERSION >= 730 ) # pragma set woff 3505 # endif +#endif + + /* Newer compilers warn for fall-through case statements. */ +#ifndef FALL_THROUGH +# if ( defined( __STDC_VERSION__ ) && __STDC_VERSION__ > 201710L ) || \ + ( defined( __cplusplus ) && __cplusplus > 201402L ) +# define FALL_THROUGH [[__fallthrough__]] +# elif ( defined( __GNUC__ ) && __GNUC__ >= 7 ) || \ + ( defined( __clang__ ) && \ + ( defined( __apple_build_version__ ) \ + ? __apple_build_version__ >= 12000000 \ + : __clang_major__ >= 10 ) ) +# define FALL_THROUGH __attribute__(( __fallthrough__ )) +# else +# define FALL_THROUGH ( (void)0 ) +# endif #endif /* @@ -71,12 +87,18 @@ FT_BEGIN_HEADER */ #define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT -#ifdef _WIN64 +#ifdef __UINTPTR_TYPE__ + /* + * GCC and Clang both provide a `__UINTPTR_TYPE__` that can be used to + * avoid a dependency on `stdint.h`. + */ +# define FT_UINT_TO_POINTER( x ) (void *)(__UINTPTR_TYPE__)(x) +#elif defined( _WIN64 ) /* only 64bit Windows uses the LLP64 data model, i.e., */ /* 32-bit integers, 64-bit pointers. */ -#define FT_UINT_TO_POINTER( x ) (void *)(unsigned __int64)(x) +# define FT_UINT_TO_POINTER( x ) (void *)(unsigned __int64)(x) #else -#define FT_UINT_TO_POINTER( x ) (void *)(unsigned long)(x) +# define FT_UINT_TO_POINTER( x ) (void *)(unsigned long)(x) #endif /* @@ -216,79 +238,93 @@ FT_BEGIN_HEADER #define FT_EXPORT_VAR( x ) FT_FUNCTION_DECLARATION( x ) #endif - /* When compiling FreeType as a DLL or DSO with hidden visibility, */ - /* some systems/compilers need a special attribute in front OR after */ - /* the return type of function declarations. */ - /* */ - /* Two macros are used within the FreeType source code to define */ - /* exported library functions: `FT_EXPORT` and `FT_EXPORT_DEF`. */ - /* */ - /* - `FT_EXPORT( return_type )` */ - /* */ - /* is used in a function declaration, as in */ - /* */ - /* ``` */ - /* FT_EXPORT( FT_Error ) */ - /* FT_Init_FreeType( FT_Library* alibrary ); */ - /* ``` */ - /* */ - /* - `FT_EXPORT_DEF( return_type )` */ - /* */ - /* is used in a function definition, as in */ - /* */ - /* ``` */ - /* FT_EXPORT_DEF( FT_Error ) */ - /* FT_Init_FreeType( FT_Library* alibrary ) */ - /* { */ - /* ... some code ... */ - /* return FT_Err_Ok; */ - /* } */ - /* ``` */ - /* */ - /* You can provide your own implementation of `FT_EXPORT` and */ - /* `FT_EXPORT_DEF` here if you want. */ - /* */ - /* To export a variable, use `FT_EXPORT_VAR`. */ - /* */ + /* + * When compiling FreeType as a DLL or DSO with hidden visibility, + * some systems/compilers need a special attribute in front OR after + * the return type of function declarations. + * + * Two macros are used within the FreeType source code to define + * exported library functions: `FT_EXPORT` and `FT_EXPORT_DEF`. + * + * - `FT_EXPORT( return_type )` + * + * is used in a function declaration, as in + * + * ``` + * FT_EXPORT( FT_Error ) + * FT_Init_FreeType( FT_Library* alibrary ); + * ``` + * + * - `FT_EXPORT_DEF( return_type )` + * + * is used in a function definition, as in + * + * ``` + * FT_EXPORT_DEF( FT_Error ) + * FT_Init_FreeType( FT_Library* alibrary ) + * { + * ... some code ... + * return FT_Err_Ok; + * } + * ``` + * + * You can provide your own implementation of `FT_EXPORT` and + * `FT_EXPORT_DEF` here if you want. + * + * To export a variable, use `FT_EXPORT_VAR`. + */ - /* See `freetype/config/compiler_macros.h` for the `FT_EXPORT` definition */ + /* See `freetype/config/public-macros.h` for the `FT_EXPORT` definition */ #define FT_EXPORT_DEF( x ) FT_FUNCTION_DEFINITION( x ) - /* The following macros are needed to compile the library with a */ - /* C++ compiler and with 16bit compilers. */ - /* */ + /* + * The following macros are needed to compile the library with a + * C++ compiler and with 16bit compilers. + */ - /* This is special. Within C++, you must specify `extern "C"` for */ - /* functions which are used via function pointers, and you also */ - /* must do that for structures which contain function pointers to */ - /* assure C linkage -- it's not possible to have (local) anonymous */ - /* functions which are accessed by (global) function pointers. */ - /* */ - /* */ - /* FT_CALLBACK_DEF is used to _define_ a callback function, */ - /* located in the same source code file as the structure that uses */ - /* it. */ - /* */ - /* FT_BASE_CALLBACK and FT_BASE_CALLBACK_DEF are used to declare */ - /* and define a callback function, respectively, in a similar way */ - /* as FT_BASE and FT_BASE_DEF work. */ - /* */ - /* FT_CALLBACK_TABLE is used to _declare_ a constant variable that */ - /* contains pointers to callback functions. */ - /* */ - /* FT_CALLBACK_TABLE_DEF is used to _define_ a constant variable */ - /* that contains pointers to callback functions. */ - /* */ - /* */ - /* Some 16bit compilers have to redefine these macros to insert */ - /* the infamous `_cdecl` or `__fastcall` declarations. */ - /* */ + /* + * This is special. Within C++, you must specify `extern "C"` for + * functions which are used via function pointers, and you also + * must do that for structures which contain function pointers to + * assure C linkage -- it's not possible to have (local) anonymous + * functions which are accessed by (global) function pointers. + * + * + * FT_CALLBACK_DEF is used to _define_ a callback function, + * located in the same source code file as the structure that uses + * it. FT_COMPARE_DEF, in addition, ensures the `cdecl` calling + * convention on x86, required by the C library function `qsort`. + * + * FT_BASE_CALLBACK and FT_BASE_CALLBACK_DEF are used to declare + * and define a callback function, respectively, in a similar way + * as FT_BASE and FT_BASE_DEF work. + * + * FT_CALLBACK_TABLE is used to _declare_ a constant variable that + * contains pointers to callback functions. + * + * FT_CALLBACK_TABLE_DEF is used to _define_ a constant variable + * that contains pointers to callback functions. + * + * + * Some 16bit compilers have to redefine these macros to insert + * the infamous `_cdecl` or `__fastcall` declarations. + */ #ifdef __cplusplus #define FT_CALLBACK_DEF( x ) extern "C" x #else #define FT_CALLBACK_DEF( x ) static x #endif +#if defined( __GNUC__ ) && defined( __i386__ ) +#define FT_COMPARE_DEF( x ) FT_CALLBACK_DEF( x ) __attribute__(( cdecl )) +#elif defined( _MSC_VER ) && defined( _M_IX86 ) +#define FT_COMPARE_DEF( x ) FT_CALLBACK_DEF( x ) __cdecl +#elif defined( __WATCOMC__ ) && __WATCOMC__ >= 1240 +#define FT_COMPARE_DEF( x ) FT_CALLBACK_DEF( x ) __watcall +#else +#define FT_COMPARE_DEF( x ) FT_CALLBACK_DEF( x ) +#endif + #define FT_BASE_CALLBACK( x ) FT_FUNCTION_DECLARATION( x ) #define FT_BASE_CALLBACK_DEF( x ) FT_FUNCTION_DEFINITION( x ) diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftcalc.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftcalc.h index c65307472..d9aea2360 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftcalc.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftcalc.h @@ -4,7 +4,7 @@ * * Arithmetic computations (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -278,6 +278,40 @@ FT_BEGIN_HEADER FT_Long c ); + /************************************************************************** + * + * @function: + * FT_MulAddFix + * + * @description: + * Compute `(s[0] * f[0] + s[1] * f[1] + ...) / 0x10000`, where `s[n]` is + * usually a 16.16 scalar. + * + * @input: + * s :: + * The array of scalars. + * f :: + * The array of factors. + * count :: + * The number of entries in the array. + * + * @return: + * The result of `(s[0] * f[0] + s[1] * f[1] + ...) / 0x10000`. + * + * @note: + * This function is currently used for the scaled delta computation of + * variation stores. It internally uses 64-bit data types when + * available, otherwise it emulates 64-bit math by using 32-bit + * operations, which produce a correct result but most likely at a slower + * performance in comparison to the implementation base on `int64_t`. + * + */ + FT_BASE( FT_Int32 ) + FT_MulAddFix( FT_Fixed* s, + FT_Int32* f, + FT_UInt count ); + + /* * A variant of FT_Matrix_Multiply which scales its result afterwards. The * idea is that both `a' and `b' are scaled by factors of 10 so that the @@ -298,9 +332,9 @@ FT_BEGIN_HEADER * Based on geometric considerations we use the following inequality to * identify a degenerate matrix. * - * 50 * abs(xx*yy - xy*yx) < xx^2 + xy^2 + yx^2 + yy^2 + * 32 * abs(xx*yy - xy*yx) < xx^2 + xy^2 + yx^2 + yy^2 * - * Value 50 is heuristic. + * Value 32 is heuristic. */ FT_BASE( FT_Bool ) FT_Matrix_Check( const FT_Matrix* matrix ); @@ -359,8 +393,8 @@ FT_BEGIN_HEADER #ifndef FT_CONFIG_OPTION_NO_ASSEMBLER -#if defined( __GNUC__ ) && \ - ( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4 ) ) +#if defined( __clang__ ) || ( defined( __GNUC__ ) && \ + ( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4 ) ) ) #if FT_SIZEOF_INT == 4 @@ -370,12 +404,25 @@ FT_BEGIN_HEADER #define FT_MSB( x ) ( 31 - __builtin_clzl( x ) ) -#endif /* __GNUC__ */ +#endif +#elif defined( _MSC_VER ) && _MSC_VER >= 1400 -#elif defined( _MSC_VER ) && ( _MSC_VER >= 1400 ) +#if defined( _WIN32_WCE ) -#if FT_SIZEOF_INT == 4 +#include +#pragma intrinsic( _CountLeadingZeros ) + +#define FT_MSB( x ) ( 31 - _CountLeadingZeros( x ) ) + +#elif defined( _M_ARM64 ) || defined( _M_ARM ) + +#include +#pragma intrinsic( _CountLeadingZeros ) + +#define FT_MSB( x ) ( 31 - _CountLeadingZeros( x ) ) + +#elif defined( _M_IX86 ) || defined( _M_AMD64 ) || defined( _M_IA64 ) #include #pragma intrinsic( _BitScanReverse ) @@ -391,15 +438,40 @@ FT_BEGIN_HEADER return (FT_Int32)where; } -#define FT_MSB( x ) ( FT_MSB_i386( x ) ) +#define FT_MSB( x ) FT_MSB_i386( x ) #endif -#endif /* _MSC_VER */ +#elif defined( __WATCOMC__ ) && defined( __386__ ) + extern __inline FT_Int32 + FT_MSB_i386( FT_UInt32 x ); + +#pragma aux FT_MSB_i386 = \ + "bsr eax, eax" \ + __parm [__eax] __nomemory \ + __value [__eax] \ + __modify __exact [__eax] __nomemory; + +#define FT_MSB( x ) FT_MSB_i386( x ) + +#elif defined( __DECC ) || defined( __DECCXX ) + +#include + +#define FT_MSB( x ) (FT_Int)( 63 - _leadz( x ) ) + +#elif defined( _CRAYC ) + +#include + +#define FT_MSB( x ) (FT_Int)( 31 - _leadz32( x ) ) + +#endif /* FT_MSB macro definitions */ #endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ + #ifndef FT_MSB FT_BASE( FT_Int ) @@ -487,7 +559,7 @@ FT_BEGIN_HEADER #define NEG_INT32( a ) \ (FT_Int32)( (FT_UInt32)0 - (FT_UInt32)(a) ) -#ifdef FT_LONG64 +#ifdef FT_INT64 #define ADD_INT64( a, b ) \ (FT_Int64)( (FT_UInt64)(a) + (FT_UInt64)(b) ) @@ -498,7 +570,7 @@ FT_BEGIN_HEADER #define NEG_INT64( a ) \ (FT_Int64)( (FT_UInt64)0 - (FT_UInt64)(a) ) -#endif /* FT_LONG64 */ +#endif /* FT_INT64 */ FT_END_HEADER diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftdebug.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftdebug.h index df5357ad5..4e013ba1e 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftdebug.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftdebug.h @@ -4,7 +4,7 @@ * * Debugging and logging component (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -31,9 +31,24 @@ #include "compiler-macros.h" +#ifdef FT_DEBUG_LOGGING +#define DLG_STATIC +#include +#include + +#include +#endif /* FT_DEBUG_LOGGING */ + FT_BEGIN_HEADER + /* force the definition of FT_DEBUG_LEVEL_TRACE if FT_DEBUG_LOGGING is */ + /* already defined. */ + /* */ +#ifdef FT_DEBUG_LOGGING +#undef FT_DEBUG_LEVEL_TRACE +#define FT_DEBUG_LEVEL_TRACE +#endif /* force the definition of FT_DEBUG_LEVEL_ERROR if FT_DEBUG_LEVEL_TRACE */ /* is already defined; this simplifies the following #ifdefs */ @@ -82,20 +97,66 @@ FT_BEGIN_HEADER * Each component must define the macro FT_COMPONENT to a valid FT_Trace * value before using any TRACE macro. * + * To get consistent logging output, there should be no newline character + * (i.e., '\n') or a single trailing one in the message string of + * `FT_TRACEx` and `FT_ERROR`. */ + + /************************************************************************* + * + * If FT_DEBUG_LOGGING is enabled, tracing messages are sent to dlg's API. + * If FT_DEBUG_LOGGING is disabled, tracing messages are sent to + * `FT_Message` (defined in ftdebug.c). + */ +#ifdef FT_DEBUG_LOGGING + + /* we need two macros to convert the names of `FT_COMPONENT` to a string */ +#define FT_LOGGING_TAG( x ) FT_LOGGING_TAG_( x ) +#define FT_LOGGING_TAG_( x ) #x + + /* we need two macros to convert the component and the trace level */ + /* to a string that combines them */ +#define FT_LOGGING_TAGX( x, y ) FT_LOGGING_TAGX_( x, y ) +#define FT_LOGGING_TAGX_( x, y ) #x ":" #y + + +#define FT_LOG( level, varformat ) \ + do \ + { \ + const char* dlg_tag = FT_LOGGING_TAGX( FT_COMPONENT, level ); \ + \ + \ + ft_add_tag( dlg_tag ); \ + if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] >= level ) \ + { \ + if ( custom_output_handler != NULL ) \ + FT_Logging_Callback varformat; \ + else \ + dlg_trace varformat; \ + } \ + ft_remove_tag( dlg_tag ); \ + } while( 0 ) + +#else /* !FT_DEBUG_LOGGING */ + +#define FT_LOG( level, varformat ) \ + do \ + { \ + if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] >= level ) \ + FT_Message varformat; \ + } while ( 0 ) + +#endif /* !FT_DEBUG_LOGGING */ + + #ifdef FT_DEBUG_LEVEL_TRACE /* we need two macros here to make cpp expand `FT_COMPONENT' */ #define FT_TRACE_COMP( x ) FT_TRACE_COMP_( x ) #define FT_TRACE_COMP_( x ) trace_ ## x -#define FT_TRACE( level, varformat ) \ - do \ - { \ - if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] >= level ) \ - FT_Message varformat; \ - } while ( 0 ) +#define FT_TRACE( level, varformat ) FT_LOG( level, varformat ) #else /* !FT_DEBUG_LEVEL_TRACE */ @@ -204,7 +265,32 @@ FT_BEGIN_HEADER #ifdef FT_DEBUG_LEVEL_ERROR -#define FT_ERROR( varformat ) FT_Message varformat + /************************************************************************** + * + * If FT_DEBUG_LOGGING is enabled, error messages are sent to dlg's API. + * If FT_DEBUG_LOGGING is disabled, error messages are sent to `FT_Message` + * (defined in ftdebug.c). + * + */ +#ifdef FT_DEBUG_LOGGING + +#define FT_ERROR( varformat ) \ + do \ + { \ + const char* dlg_tag = FT_LOGGING_TAG( FT_COMPONENT ); \ + \ + \ + ft_add_tag( dlg_tag ); \ + dlg_trace varformat; \ + ft_remove_tag( dlg_tag ); \ + } while ( 0 ) + +#else /* !FT_DEBUG_LOGGING */ + +#define FT_ERROR( varformat ) FT_Message varformat + +#endif /* !FT_DEBUG_LOGGING */ + #else /* !FT_DEBUG_LEVEL_ERROR */ @@ -277,6 +363,77 @@ FT_BEGIN_HEADER FT_BASE( void ) ft_debug_init( void ); + +#ifdef FT_DEBUG_LOGGING + + /************************************************************************** + * + * 'dlg' uses output handlers to control how and where log messages are + * printed. Therefore we need to define a default output handler for + * FreeType. + */ + FT_BASE( void ) + ft_log_handler( const struct dlg_origin* origin, + const char* string, + void* data ); + + + /************************************************************************** + * + * 1. `ft_default_log_handler` stores the function pointer that is used + * internally by FreeType to print logs to a file. + * + * 2. `custom_output_handler` stores the function pointer to the callback + * function provided by the user. + * + * It is defined in `ftdebug.c`. + */ + extern dlg_handler ft_default_log_handler; + extern FT_Custom_Log_Handler custom_output_handler; + + + /************************************************************************** + * + * If FT_DEBUG_LOGGING macro is enabled, FreeType needs to initialize and + * un-initialize `FILE*`. + * + * These functions are defined in `ftdebug.c`. + */ + FT_BASE( void ) + ft_logging_init( void ); + + FT_BASE( void ) + ft_logging_deinit( void ); + + + /************************************************************************** + * + * For printing the name of `FT_COMPONENT` along with the actual log we + * need to add a tag with the name of `FT_COMPONENT`. + * + * These functions are defined in `ftdebug.c`. + */ + FT_BASE( void ) + ft_add_tag( const char* tag ); + + FT_BASE( void ) + ft_remove_tag( const char* tag ); + + + /************************************************************************** + * + * A function to print log data using a custom callback logging function + * (which is set using `FT_Set_Log_Handler`). + * + * This function is defined in `ftdebug.c`. + */ + FT_BASE( void ) + FT_Logging_Callback( const char* fmt, + ... ); + +#endif /* FT_DEBUG_LOGGING */ + + FT_END_HEADER #endif /* FTDEBUG_H_ */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftdrv.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftdrv.h index 7f22710ea..9001c07ad 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftdrv.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftdrv.h @@ -4,7 +4,7 @@ * * FreeType internal font driver interface (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -157,6 +157,7 @@ FT_BEGIN_HEADER * A handle to a function used to select a new fixed size. It is used * only if @FT_FACE_FLAG_FIXED_SIZES is set. Can be set to 0 if the * scaling done in the base layer suffices. + * * @note: * Most function pointers, with the exception of `load_glyph`, can be set * to 0 to indicate a default behaviour. diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftgloadr.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftgloadr.h index 27b8659f7..36e5509f9 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftgloadr.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftgloadr.h @@ -4,7 +4,7 @@ * * The FreeType glyph loader (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg * * This file is part of the FreeType project, and may only be used, @@ -22,6 +22,7 @@ #include +#include "compiler-macros.h" FT_BEGIN_HEADER diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftmemory.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftmemory.h index ddb18b051..5eb1d21ff 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftmemory.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftmemory.h @@ -4,7 +4,7 @@ * * The FreeType memory management macros (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg * * This file is part of the FreeType project, and may only be used, @@ -96,15 +96,15 @@ extern "C++" #ifdef FT_DEBUG_MEMORY - FT_BASE( const char* ) _ft_debug_file; - FT_BASE( long ) _ft_debug_lineno; + FT_BASE( const char* ) ft_debug_file_; + FT_BASE( long ) ft_debug_lineno_; -#define FT_DEBUG_INNER( exp ) ( _ft_debug_file = __FILE__, \ - _ft_debug_lineno = __LINE__, \ +#define FT_DEBUG_INNER( exp ) ( ft_debug_file_ = __FILE__, \ + ft_debug_lineno_ = __LINE__, \ (exp) ) -#define FT_ASSIGNP_INNER( p, exp ) ( _ft_debug_file = __FILE__, \ - _ft_debug_lineno = __LINE__, \ +#define FT_ASSIGNP_INNER( p, exp ) ( ft_debug_file_ = __FILE__, \ + ft_debug_lineno_ = __LINE__, \ FT_ASSIGNP( p, exp ) ) #else /* !FT_DEBUG_MEMORY */ @@ -344,14 +344,13 @@ extern "C++" #define FT_RENEW_ARRAY( ptr, curcnt, newcnt ) \ FT_MEM_SET_ERROR( FT_MEM_RENEW_ARRAY( ptr, curcnt, newcnt ) ) -#define FT_QNEW( ptr ) \ - FT_MEM_SET_ERROR( FT_MEM_QNEW( ptr ) ) +#define FT_QNEW( ptr ) FT_MEM_SET_ERROR( FT_MEM_QNEW( ptr ) ) -#define FT_QNEW_ARRAY( ptr, count ) \ - FT_MEM_SET_ERROR( FT_MEM_NEW_ARRAY( ptr, count ) ) +#define FT_QNEW_ARRAY( ptr, count ) \ + FT_MEM_SET_ERROR( FT_MEM_QNEW_ARRAY( ptr, count ) ) -#define FT_QRENEW_ARRAY( ptr, curcnt, newcnt ) \ - FT_MEM_SET_ERROR( FT_MEM_RENEW_ARRAY( ptr, curcnt, newcnt ) ) +#define FT_QRENEW_ARRAY( ptr, curcnt, newcnt ) \ + FT_MEM_SET_ERROR( FT_MEM_QRENEW_ARRAY( ptr, curcnt, newcnt ) ) FT_BASE( FT_Pointer ) diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftmmtypes.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftmmtypes.h new file mode 100644 index 000000000..c4b21d614 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftmmtypes.h @@ -0,0 +1,91 @@ +/**************************************************************************** + * + * ftmmtypes.h + * + * OpenType Variations type definitions for internal use + * with the multi-masters service (specification). + * + * Copyright (C) 2022-2023 by + * David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and + * Dominik Röttsches. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#ifndef FTMMTYPES_H_ +#define FTMMTYPES_H_ + +FT_BEGIN_HEADER + + + typedef FT_Int32 FT_ItemVarDelta; + + typedef struct GX_ItemVarDataRec_ + { + FT_UInt itemCount; /* Number of delta sets per item. */ + FT_UInt regionIdxCount; /* Number of region indices. */ + FT_UInt* regionIndices; /* Array of `regionCount` indices; */ + /* these index `varRegionList`. */ + FT_Byte* deltaSet; /* Array of `itemCount` deltas; */ + /* use `innerIndex` for this array. */ + FT_UShort wordDeltaCount; /* Number of the first 32-bit ints */ + /* or 16-bit ints of `deltaSet` */ + /* depending on `longWords`. */ + FT_Bool longWords; /* If true, `deltaSet` is a 32-bit */ + /* array followed by a 16-bit */ + /* array, otherwise a 16-bit array */ + /* followed by an 8-bit array. */ + } GX_ItemVarDataRec, *GX_ItemVarData; + + + /* contribution of one axis to a region */ + typedef struct GX_AxisCoordsRec_ + { + FT_Fixed startCoord; + FT_Fixed peakCoord; /* zero means no effect (factor = 1) */ + FT_Fixed endCoord; + + } GX_AxisCoordsRec, *GX_AxisCoords; + + + typedef struct GX_VarRegionRec_ + { + GX_AxisCoords axisList; /* array of axisCount records */ + + } GX_VarRegionRec, *GX_VarRegion; + + + /* item variation store */ + typedef struct GX_ItemVarStoreRec_ + { + FT_UInt dataCount; + GX_ItemVarData varData; /* array of dataCount records; */ + /* use `outerIndex' for this array */ + FT_UShort axisCount; + FT_UInt regionCount; /* total number of regions defined */ + GX_VarRegion varRegionList; + + } GX_ItemVarStoreRec, *GX_ItemVarStore; + + + typedef struct GX_DeltaSetIdxMapRec_ + { + FT_ULong mapCount; + FT_UInt* outerIndex; /* indices to item var data */ + FT_UInt* innerIndex; /* indices to delta set */ + + } GX_DeltaSetIdxMapRec, *GX_DeltaSetIdxMap; + + +FT_END_HEADER + +#endif /* FTMMTYPES_H_ */ + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftobjs.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftobjs.h index 25db2c494..28bc9b65f 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftobjs.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftobjs.h @@ -4,7 +4,7 @@ * * The FreeType private base classes (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -418,7 +418,8 @@ FT_BEGIN_HEADER * initializing the glyph slot. */ -#define FT_GLYPH_OWN_BITMAP 0x1U +#define FT_GLYPH_OWN_BITMAP 0x1U +#define FT_GLYPH_OWN_GZIP_SVG 0x2U typedef struct FT_Slot_InternalRec_ { @@ -673,7 +674,7 @@ FT_BEGIN_HEADER /* Set the metrics according to a size request. */ - FT_BASE( void ) + FT_BASE( FT_Error ) FT_Request_Metrics( FT_Face face, FT_Size_Request req ); diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftpsprop.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftpsprop.h index 81ec29151..1d5b287ad 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftpsprop.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftpsprop.h @@ -4,7 +4,7 @@ * * Get and set properties of PostScript drivers (specification). * - * Copyright (C) 2017-2020 by + * Copyright (C) 2017-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftrfork.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftrfork.h index 1b7b25acb..e96459921 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftrfork.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftrfork.h @@ -4,7 +4,7 @@ * * Embedded resource forks accessor (specification). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * Masatake YAMATO and Redhat K.K. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftserv.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftserv.h index 6e1a9472d..1e85d6d38 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftserv.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftserv.h @@ -4,7 +4,7 @@ * * The FreeType services (specification only). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftstream.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftstream.h index e7d922260..88e19287c 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftstream.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftstream.h @@ -4,7 +4,7 @@ * * Stream handling (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -196,9 +196,9 @@ FT_BEGIN_HEADER FT_BYTE_U32( p, 2, 8 ) | \ FT_BYTE_U32( p, 3, 0 ) ) -#define FT_PEEK_OFF3( p ) FT_INT32( FT_BYTE_U32( p, 0, 16 ) | \ - FT_BYTE_U32( p, 1, 8 ) | \ - FT_BYTE_U32( p, 2, 0 ) ) +#define FT_PEEK_OFF3( p ) ( FT_INT32( FT_BYTE_U32( p, 0, 24 ) | \ + FT_BYTE_U32( p, 1, 16 ) | \ + FT_BYTE_U32( p, 2, 8 ) ) >> 8 ) #define FT_PEEK_UOFF3( p ) FT_UINT32( FT_BYTE_U32( p, 0, 16 ) | \ FT_BYTE_U32( p, 1, 8 ) | \ @@ -220,9 +220,9 @@ FT_BEGIN_HEADER FT_BYTE_U32( p, 1, 8 ) | \ FT_BYTE_U32( p, 0, 0 ) ) -#define FT_PEEK_OFF3_LE( p ) FT_INT32( FT_BYTE_U32( p, 2, 16 ) | \ - FT_BYTE_U32( p, 1, 8 ) | \ - FT_BYTE_U32( p, 0, 0 ) ) +#define FT_PEEK_OFF3_LE( p ) ( FT_INT32( FT_BYTE_U32( p, 2, 24 ) | \ + FT_BYTE_U32( p, 1, 16 ) | \ + FT_BYTE_U32( p, 0, 8 ) ) >> 8 ) #define FT_PEEK_UOFF3_LE( p ) FT_UINT32( FT_BYTE_U32( p, 2, 16 ) | \ FT_BYTE_U32( p, 1, 8 ) | \ @@ -238,42 +238,42 @@ FT_BEGIN_HEADER #define FT_NEXT_BYTE( buffer ) \ ( (unsigned char)*buffer++ ) -#define FT_NEXT_SHORT( buffer ) \ - ( (short)( buffer += 2, FT_PEEK_SHORT( buffer - 2 ) ) ) +#define FT_NEXT_SHORT( buffer ) \ + ( buffer += 2, FT_PEEK_SHORT( buffer - 2 ) ) -#define FT_NEXT_USHORT( buffer ) \ - ( (unsigned short)( buffer += 2, FT_PEEK_USHORT( buffer - 2 ) ) ) +#define FT_NEXT_USHORT( buffer ) \ + ( buffer += 2, FT_PEEK_USHORT( buffer - 2 ) ) -#define FT_NEXT_OFF3( buffer ) \ - ( (long)( buffer += 3, FT_PEEK_OFF3( buffer - 3 ) ) ) +#define FT_NEXT_OFF3( buffer ) \ + ( buffer += 3, FT_PEEK_OFF3( buffer - 3 ) ) -#define FT_NEXT_UOFF3( buffer ) \ - ( (unsigned long)( buffer += 3, FT_PEEK_UOFF3( buffer - 3 ) ) ) +#define FT_NEXT_UOFF3( buffer ) \ + ( buffer += 3, FT_PEEK_UOFF3( buffer - 3 ) ) -#define FT_NEXT_LONG( buffer ) \ - ( (long)( buffer += 4, FT_PEEK_LONG( buffer - 4 ) ) ) +#define FT_NEXT_LONG( buffer ) \ + ( buffer += 4, FT_PEEK_LONG( buffer - 4 ) ) -#define FT_NEXT_ULONG( buffer ) \ - ( (unsigned long)( buffer += 4, FT_PEEK_ULONG( buffer - 4 ) ) ) +#define FT_NEXT_ULONG( buffer ) \ + ( buffer += 4, FT_PEEK_ULONG( buffer - 4 ) ) -#define FT_NEXT_SHORT_LE( buffer ) \ - ( (short)( buffer += 2, FT_PEEK_SHORT_LE( buffer - 2 ) ) ) +#define FT_NEXT_SHORT_LE( buffer ) \ + ( buffer += 2, FT_PEEK_SHORT_LE( buffer - 2 ) ) -#define FT_NEXT_USHORT_LE( buffer ) \ - ( (unsigned short)( buffer += 2, FT_PEEK_USHORT_LE( buffer - 2 ) ) ) +#define FT_NEXT_USHORT_LE( buffer ) \ + ( buffer += 2, FT_PEEK_USHORT_LE( buffer - 2 ) ) -#define FT_NEXT_OFF3_LE( buffer ) \ - ( (long)( buffer += 3, FT_PEEK_OFF3_LE( buffer - 3 ) ) ) +#define FT_NEXT_OFF3_LE( buffer ) \ + ( buffer += 3, FT_PEEK_OFF3_LE( buffer - 3 ) ) -#define FT_NEXT_UOFF3_LE( buffer ) \ - ( (unsigned long)( buffer += 3, FT_PEEK_UOFF3_LE( buffer - 3 ) ) ) +#define FT_NEXT_UOFF3_LE( buffer ) \ + ( buffer += 3, FT_PEEK_UOFF3_LE( buffer - 3 ) ) -#define FT_NEXT_LONG_LE( buffer ) \ - ( (long)( buffer += 4, FT_PEEK_LONG_LE( buffer - 4 ) ) ) +#define FT_NEXT_LONG_LE( buffer ) \ + ( buffer += 4, FT_PEEK_LONG_LE( buffer - 4 ) ) -#define FT_NEXT_ULONG_LE( buffer ) \ - ( (unsigned long)( buffer += 4, FT_PEEK_ULONG_LE( buffer - 4 ) ) ) +#define FT_NEXT_ULONG_LE( buffer ) \ + ( buffer += 4, FT_PEEK_ULONG_LE( buffer - 4 ) ) /************************************************************************** @@ -305,20 +305,19 @@ FT_BEGIN_HEADER #else #define FT_GET_MACRO( func, type ) ( (type)func( stream ) ) -#define FT_GET_CHAR() FT_GET_MACRO( FT_Stream_GetChar, FT_Char ) -#define FT_GET_BYTE() FT_GET_MACRO( FT_Stream_GetChar, FT_Byte ) -#define FT_GET_SHORT() FT_GET_MACRO( FT_Stream_GetUShort, FT_Short ) -#define FT_GET_USHORT() FT_GET_MACRO( FT_Stream_GetUShort, FT_UShort ) -#define FT_GET_OFF3() FT_GET_MACRO( FT_Stream_GetUOffset, FT_Long ) -#define FT_GET_UOFF3() FT_GET_MACRO( FT_Stream_GetUOffset, FT_ULong ) -#define FT_GET_LONG() FT_GET_MACRO( FT_Stream_GetULong, FT_Long ) -#define FT_GET_ULONG() FT_GET_MACRO( FT_Stream_GetULong, FT_ULong ) -#define FT_GET_TAG4() FT_GET_MACRO( FT_Stream_GetULong, FT_ULong ) +#define FT_GET_CHAR() FT_GET_MACRO( FT_Stream_GetByte, FT_Char ) +#define FT_GET_BYTE() FT_GET_MACRO( FT_Stream_GetByte, FT_Byte ) +#define FT_GET_SHORT() FT_GET_MACRO( FT_Stream_GetUShort, FT_Int16 ) +#define FT_GET_USHORT() FT_GET_MACRO( FT_Stream_GetUShort, FT_UInt16 ) +#define FT_GET_UOFF3() FT_GET_MACRO( FT_Stream_GetUOffset, FT_UInt32 ) +#define FT_GET_LONG() FT_GET_MACRO( FT_Stream_GetULong, FT_Int32 ) +#define FT_GET_ULONG() FT_GET_MACRO( FT_Stream_GetULong, FT_UInt32 ) +#define FT_GET_TAG4() FT_GET_MACRO( FT_Stream_GetULong, FT_UInt32 ) -#define FT_GET_SHORT_LE() FT_GET_MACRO( FT_Stream_GetUShortLE, FT_Short ) -#define FT_GET_USHORT_LE() FT_GET_MACRO( FT_Stream_GetUShortLE, FT_UShort ) -#define FT_GET_LONG_LE() FT_GET_MACRO( FT_Stream_GetULongLE, FT_Long ) -#define FT_GET_ULONG_LE() FT_GET_MACRO( FT_Stream_GetULongLE, FT_ULong ) +#define FT_GET_SHORT_LE() FT_GET_MACRO( FT_Stream_GetUShortLE, FT_Int16 ) +#define FT_GET_USHORT_LE() FT_GET_MACRO( FT_Stream_GetUShortLE, FT_UInt16 ) +#define FT_GET_LONG_LE() FT_GET_MACRO( FT_Stream_GetULongLE, FT_Int32 ) +#define FT_GET_ULONG_LE() FT_GET_MACRO( FT_Stream_GetULongLE, FT_UInt32 ) #endif @@ -333,19 +332,18 @@ FT_BEGIN_HEADER * `FT_STREAM_POS'. They use the full machinery to check whether a read is * valid. */ -#define FT_READ_BYTE( var ) FT_READ_MACRO( FT_Stream_ReadChar, FT_Byte, var ) -#define FT_READ_CHAR( var ) FT_READ_MACRO( FT_Stream_ReadChar, FT_Char, var ) -#define FT_READ_SHORT( var ) FT_READ_MACRO( FT_Stream_ReadUShort, FT_Short, var ) -#define FT_READ_USHORT( var ) FT_READ_MACRO( FT_Stream_ReadUShort, FT_UShort, var ) -#define FT_READ_OFF3( var ) FT_READ_MACRO( FT_Stream_ReadUOffset, FT_Long, var ) -#define FT_READ_UOFF3( var ) FT_READ_MACRO( FT_Stream_ReadUOffset, FT_ULong, var ) -#define FT_READ_LONG( var ) FT_READ_MACRO( FT_Stream_ReadULong, FT_Long, var ) -#define FT_READ_ULONG( var ) FT_READ_MACRO( FT_Stream_ReadULong, FT_ULong, var ) +#define FT_READ_BYTE( var ) FT_READ_MACRO( FT_Stream_ReadByte, FT_Byte, var ) +#define FT_READ_CHAR( var ) FT_READ_MACRO( FT_Stream_ReadByte, FT_Char, var ) +#define FT_READ_SHORT( var ) FT_READ_MACRO( FT_Stream_ReadUShort, FT_Int16, var ) +#define FT_READ_USHORT( var ) FT_READ_MACRO( FT_Stream_ReadUShort, FT_UInt16, var ) +#define FT_READ_UOFF3( var ) FT_READ_MACRO( FT_Stream_ReadUOffset, FT_UInt32, var ) +#define FT_READ_LONG( var ) FT_READ_MACRO( FT_Stream_ReadULong, FT_Int32, var ) +#define FT_READ_ULONG( var ) FT_READ_MACRO( FT_Stream_ReadULong, FT_UInt32, var ) -#define FT_READ_SHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadUShortLE, FT_Short, var ) -#define FT_READ_USHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadUShortLE, FT_UShort, var ) -#define FT_READ_LONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadULongLE, FT_Long, var ) -#define FT_READ_ULONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadULongLE, FT_ULong, var ) +#define FT_READ_SHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadUShortLE, FT_Int16, var ) +#define FT_READ_USHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadUShortLE, FT_UInt16, var ) +#define FT_READ_LONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadULongLE, FT_Int32, var ) +#define FT_READ_ULONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadULongLE, FT_UInt32, var ) #ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM @@ -457,37 +455,37 @@ FT_BEGIN_HEADER /* read a byte from an entered frame */ - FT_BASE( FT_Char ) - FT_Stream_GetChar( FT_Stream stream ); + FT_BASE( FT_Byte ) + FT_Stream_GetByte( FT_Stream stream ); /* read a 16-bit big-endian unsigned integer from an entered frame */ - FT_BASE( FT_UShort ) + FT_BASE( FT_UInt16 ) FT_Stream_GetUShort( FT_Stream stream ); /* read a 24-bit big-endian unsigned integer from an entered frame */ - FT_BASE( FT_ULong ) + FT_BASE( FT_UInt32 ) FT_Stream_GetUOffset( FT_Stream stream ); /* read a 32-bit big-endian unsigned integer from an entered frame */ - FT_BASE( FT_ULong ) + FT_BASE( FT_UInt32 ) FT_Stream_GetULong( FT_Stream stream ); /* read a 16-bit little-endian unsigned integer from an entered frame */ - FT_BASE( FT_UShort ) + FT_BASE( FT_UInt16 ) FT_Stream_GetUShortLE( FT_Stream stream ); /* read a 32-bit little-endian unsigned integer from an entered frame */ - FT_BASE( FT_ULong ) + FT_BASE( FT_UInt32 ) FT_Stream_GetULongLE( FT_Stream stream ); /* read a byte from a stream */ - FT_BASE( FT_Char ) - FT_Stream_ReadChar( FT_Stream stream, + FT_BASE( FT_Byte ) + FT_Stream_ReadByte( FT_Stream stream, FT_Error* error ); /* read a 16-bit big-endian unsigned integer from a stream */ - FT_BASE( FT_UShort ) + FT_BASE( FT_UInt16 ) FT_Stream_ReadUShort( FT_Stream stream, FT_Error* error ); @@ -497,17 +495,17 @@ FT_BEGIN_HEADER FT_Error* error ); /* read a 32-bit big-endian integer from a stream */ - FT_BASE( FT_ULong ) + FT_BASE( FT_UInt32 ) FT_Stream_ReadULong( FT_Stream stream, FT_Error* error ); /* read a 16-bit little-endian unsigned integer from a stream */ - FT_BASE( FT_UShort ) + FT_BASE( FT_UInt16 ) FT_Stream_ReadUShortLE( FT_Stream stream, FT_Error* error ); /* read a 32-bit little-endian unsigned integer from a stream */ - FT_BASE( FT_ULong ) + FT_BASE( FT_UInt32 ) FT_Stream_ReadULongLE( FT_Stream stream, FT_Error* error ); diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/fttrace.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/fttrace.h index 58bd77413..319fe56fd 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/fttrace.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/fttrace.h @@ -4,7 +4,7 @@ * * Tracing handling (specification only). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -18,6 +18,11 @@ /* definitions of trace levels for FreeType 2 */ + /* the maximum string length (if the argument to `FT_TRACE_DEF` */ + /* gets used as a string) plus one charachter for ':' plus */ + /* another one for the trace level */ +#define FT_MAX_TRACE_LEVEL_LENGTH (9 + 1 + 1) + /* the first level must always be `trace_any' */ FT_TRACE_DEF( any ) @@ -38,12 +43,17 @@ FT_TRACE_DEF( checksum ) /* bitmap checksum (ftobjs.c) */ FT_TRACE_DEF( mm ) /* MM interface (ftmm.c) */ FT_TRACE_DEF( psprops ) /* PS driver properties (ftpsprop.c) */ FT_TRACE_DEF( raccess ) /* resource fork accessor (ftrfork.c) */ -FT_TRACE_DEF( raster ) /* monochrome rasterizer (ftraster.c) */ -FT_TRACE_DEF( smooth ) /* anti-aliasing raster (ftgrays.c) */ FT_TRACE_DEF( synth ) /* bold/slant synthesizer (ftsynth.c) */ - /* Cache sub-system */ -FT_TRACE_DEF( cache ) /* cache sub-system (ftcache.c, etc.) */ + /* rasterizers */ +FT_TRACE_DEF( raster ) /* monochrome rasterizer (ftraster.c) */ +FT_TRACE_DEF( smooth ) /* anti-aliasing raster (ftgrays.c) */ + + /* ot-svg module */ +FT_TRACE_DEF( otsvg ) /* OT-SVG renderer (ftsvg.c) */ + + /* cache sub-system */ +FT_TRACE_DEF( cache ) /* cache sub-system (ftcache.c, etc.) */ /* SFNT driver components */ FT_TRACE_DEF( sfdriver ) /* SFNT font driver (sfdriver.c) */ @@ -54,6 +64,7 @@ FT_TRACE_DEF( ttbdf ) /* TrueType embedded BDF (ttbdf.c) */ FT_TRACE_DEF( ttcmap ) /* charmap handler (ttcmap.c) */ FT_TRACE_DEF( ttcolr ) /* glyph layer table (ttcolr.c) */ FT_TRACE_DEF( ttcpal ) /* color palette table (ttcpal.c) */ +FT_TRACE_DEF( ttsvg ) /* OpenType SVG table (ttsvg.c) */ FT_TRACE_DEF( ttkern ) /* kerning handler (ttkern.c) */ FT_TRACE_DEF( ttload ) /* basic TrueType tables (ttload.c) */ FT_TRACE_DEF( ttmtx ) /* metrics-related tables (ttmtx.c) */ @@ -77,6 +88,7 @@ FT_TRACE_DEF( t1objs ) FT_TRACE_DEF( t1parse ) /* PostScript helper module `psaux' */ +FT_TRACE_DEF( afmparse ) FT_TRACE_DEF( cffdecode ) FT_TRACE_DEF( psconv ) FT_TRACE_DEF( psobjs ) @@ -151,8 +163,10 @@ FT_TRACE_DEF( afglobal ) FT_TRACE_DEF( afhints ) FT_TRACE_DEF( afmodule ) FT_TRACE_DEF( aflatin ) -FT_TRACE_DEF( aflatin2 ) FT_TRACE_DEF( afshaper ) -FT_TRACE_DEF( afwarp ) + + /* SDF components */ +FT_TRACE_DEF( sdf ) /* signed distance raster for outlines (ftsdf.c) */ +FT_TRACE_DEF( bsdf ) /* signed distance raster for bitmaps (ftbsdf.c) */ /* END */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftvalid.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftvalid.h index a5bc6c9b5..e98ee4e47 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/ftvalid.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/ftvalid.h @@ -4,7 +4,7 @@ * * FreeType validation support (specification). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/psaux.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/psaux.h index 8e0a262fd..dfb1987f8 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/psaux.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/psaux.h @@ -5,7 +5,7 @@ * Auxiliary functions and data structures related to PostScript fonts * (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -132,9 +132,6 @@ FT_BEGIN_HEADER * max_elems :: * The maximum number of elements in table. * - * num_elems :: - * The current number of elements in table. - * * elements :: * A table of element addresses within the block. * @@ -155,7 +152,6 @@ FT_BEGIN_HEADER FT_ULong init; FT_Int max_elems; - FT_Int num_elems; FT_Byte** elements; /* addresses of table elements */ FT_UInt* lengths; /* lengths of table elements */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/pshints.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/pshints.h index 663e9d348..ededc4c72 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/pshints.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/pshints.h @@ -6,7 +6,7 @@ * recorders (specification only). These are used to support native * T1/T2 hints in the 'type1', 'cid', and 'cff' font drivers. * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -294,7 +294,7 @@ FT_BEGIN_HEADER * * @note: * On input, all points within the outline are in font coordinates. On - * output, they are in 1/64th of pixels. + * output, they are in 1/64 of pixels. * * The scaling transformation is taken from the 'globals' object which * must correspond to the same font as the glyph. @@ -607,7 +607,7 @@ FT_BEGIN_HEADER * * @note: * On input, all points within the outline are in font coordinates. On - * output, they are in 1/64th of pixels. + * output, they are in 1/64 of pixels. * * The scaling transformation is taken from the 'globals' object which * must correspond to the same font than the glyph. diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svbdf.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svbdf.h index 81f5a06b6..bf0c1dcc7 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svbdf.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svbdf.h @@ -4,7 +4,7 @@ * * The FreeType BDF services (specification). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svcfftl.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svcfftl.h index 1d2dbb6a8..4a20498ee 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svcfftl.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svcfftl.h @@ -4,7 +4,7 @@ * * The FreeType CFF tables loader service (specification). * - * Copyright (C) 2017-2020 by + * Copyright (C) 2017-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svcid.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svcid.h index bd49f3270..06d0cb8fd 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svcid.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svcid.h @@ -4,7 +4,7 @@ * * The FreeType CID font services (specification). * - * Copyright (C) 2007-2020 by + * Copyright (C) 2007-2023 by * Derek Clegg and Michael Toftdal. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svfntfmt.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svfntfmt.h index 6114d638a..bc45e8056 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svfntfmt.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svfntfmt.h @@ -4,7 +4,7 @@ * * The FreeType font format service (specification only). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svgldict.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svgldict.h index f9443e40d..6437abfbf 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svgldict.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svgldict.h @@ -4,7 +4,7 @@ * * The FreeType glyph dictionary services (specification). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svgxval.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svgxval.h index 83c2f26ce..31016afe0 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svgxval.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svgxval.h @@ -4,7 +4,7 @@ * * FreeType API for validating TrueTypeGX/AAT tables (specification). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svkern.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svkern.h index 13cfb3272..bcabbc3e6 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svkern.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svkern.h @@ -4,7 +4,7 @@ * * The FreeType Kerning service (specification). * - * Copyright (C) 2006-2020 by + * Copyright (C) 2006-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svmetric.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svmetric.h index 2b30edaab..167617ebb 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svmetric.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svmetric.h @@ -4,7 +4,7 @@ * * The FreeType services for metrics variations (specification). * - * Copyright (C) 2016-2020 by + * Copyright (C) 2016-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -77,6 +77,9 @@ FT_BEGIN_HEADER typedef void (*FT_Metrics_Adjust_Func)( FT_Face face ); + typedef FT_Error + (*FT_Size_Reset_Func)( FT_Size size ); + FT_DEFINE_SERVICE( MetricsVariations ) { @@ -90,6 +93,7 @@ FT_BEGIN_HEADER FT_VOrg_Adjust_Func vorg_adjust; FT_Metrics_Adjust_Func metrics_adjust; + FT_Size_Reset_Func size_reset; }; @@ -101,7 +105,8 @@ FT_BEGIN_HEADER tsb_adjust_, \ bsb_adjust_, \ vorg_adjust_, \ - metrics_adjust_ ) \ + metrics_adjust_, \ + size_reset_ ) \ static const FT_Service_MetricsVariationsRec class_ = \ { \ hadvance_adjust_, \ @@ -111,7 +116,8 @@ FT_BEGIN_HEADER tsb_adjust_, \ bsb_adjust_, \ vorg_adjust_, \ - metrics_adjust_ \ + metrics_adjust_, \ + size_reset_ \ }; /* */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svmm.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svmm.h index 5a807636a..7e76ab832 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svmm.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svmm.h @@ -4,8 +4,8 @@ * * The FreeType Multiple Masters and GX var services (specification). * - * Copyright (C) 2003-2020 by - * David Turner, Robert Wilhelm, and Werner Lemberg. + * Copyright (C) 2003-2023 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. * * This file is part of the FreeType project, and may only be used, * modified, and distributed under the terms of the FreeType project @@ -19,7 +19,9 @@ #ifndef SVMM_H_ #define SVMM_H_ +#include #include +#include FT_BEGIN_HEADER @@ -58,9 +60,9 @@ FT_BEGIN_HEADER /* use return value -1 to indicate that the new coordinates */ /* are equal to the current ones; no changes are thus needed */ typedef FT_Error - (*FT_Set_MM_Blend_Func)( FT_Face face, - FT_UInt num_coords, - FT_Long* coords ); + (*FT_Set_MM_Blend_Func)( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); typedef FT_Error (*FT_Get_Var_Design_Func)( FT_Face face, @@ -68,13 +70,17 @@ FT_BEGIN_HEADER FT_Fixed* coords ); typedef FT_Error - (*FT_Set_Instance_Func)( FT_Face face, - FT_UInt instance_index ); + (*FT_Set_Named_Instance_Func)( FT_Face face, + FT_UInt instance_index ); typedef FT_Error - (*FT_Get_MM_Blend_Func)( FT_Face face, - FT_UInt num_coords, - FT_Long* coords ); + (*FT_Get_Default_Named_Instance_Func)( FT_Face face, + FT_UInt *instance_index ); + + typedef FT_Error + (*FT_Get_MM_Blend_Func)( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); typedef FT_Error (*FT_Get_Var_Blend_Func)( FT_Face face, @@ -84,7 +90,7 @@ FT_BEGIN_HEADER FT_MM_Var* *mm_var ); typedef void - (*FT_Done_Blend_Func)( FT_Face ); + (*FT_Done_Blend_Func)( FT_Face face ); typedef FT_Error (*FT_Set_MM_WeightVector_Func)( FT_Face face, @@ -96,53 +102,105 @@ FT_BEGIN_HEADER FT_UInt* len, FT_Fixed* weight_vector ); + typedef void + (*FT_Construct_PS_Name_Func)( FT_Face face ); + + typedef FT_Error + (*FT_Var_Load_Delta_Set_Idx_Map_Func)( FT_Face face, + FT_ULong offset, + GX_DeltaSetIdxMap map, + GX_ItemVarStore itemStore, + FT_ULong table_len ); + + typedef FT_Error + (*FT_Var_Load_Item_Var_Store_Func)( FT_Face face, + FT_ULong offset, + GX_ItemVarStore itemStore ); + + typedef FT_ItemVarDelta + (*FT_Var_Get_Item_Delta_Func)( FT_Face face, + GX_ItemVarStore itemStore, + FT_UInt outerIndex, + FT_UInt innerIndex ); + + typedef void + (*FT_Var_Done_Item_Var_Store_Func)( FT_Face face, + GX_ItemVarStore itemStore ); + + typedef void + (*FT_Var_Done_Delta_Set_Idx_Map_Func)( FT_Face face, + GX_DeltaSetIdxMap deltaSetIdxMap ); + FT_DEFINE_SERVICE( MultiMasters ) { - FT_Get_MM_Func get_mm; - FT_Set_MM_Design_Func set_mm_design; - FT_Set_MM_Blend_Func set_mm_blend; - FT_Get_MM_Blend_Func get_mm_blend; - FT_Get_MM_Var_Func get_mm_var; - FT_Set_Var_Design_Func set_var_design; - FT_Get_Var_Design_Func get_var_design; - FT_Set_Instance_Func set_instance; - FT_Set_MM_WeightVector_Func set_mm_weightvector; - FT_Get_MM_WeightVector_Func get_mm_weightvector; + FT_Get_MM_Func get_mm; + FT_Set_MM_Design_Func set_mm_design; + FT_Set_MM_Blend_Func set_mm_blend; + FT_Get_MM_Blend_Func get_mm_blend; + FT_Get_MM_Var_Func get_mm_var; + FT_Set_Var_Design_Func set_var_design; + FT_Get_Var_Design_Func get_var_design; + FT_Set_Named_Instance_Func set_named_instance; + FT_Get_Default_Named_Instance_Func get_default_named_instance; + FT_Set_MM_WeightVector_Func set_mm_weightvector; + FT_Get_MM_WeightVector_Func get_mm_weightvector; /* for internal use; only needed for code sharing between modules */ - FT_Get_Var_Blend_Func get_var_blend; - FT_Done_Blend_Func done_blend; + FT_Construct_PS_Name_Func construct_ps_name; + FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map; + FT_Var_Load_Item_Var_Store_Func load_item_var_store; + FT_Var_Get_Item_Delta_Func get_item_delta; + FT_Var_Done_Item_Var_Store_Func done_item_var_store; + FT_Var_Done_Delta_Set_Idx_Map_Func done_delta_set_idx_map; + FT_Get_Var_Blend_Func get_var_blend; + FT_Done_Blend_Func done_blend; }; -#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_, \ - get_mm_, \ - set_mm_design_, \ - set_mm_blend_, \ - get_mm_blend_, \ - get_mm_var_, \ - set_var_design_, \ - get_var_design_, \ - set_instance_, \ - set_weightvector_, \ - get_weightvector_, \ - get_var_blend_, \ - done_blend_ ) \ - static const FT_Service_MultiMastersRec class_ = \ - { \ - get_mm_, \ - set_mm_design_, \ - set_mm_blend_, \ - get_mm_blend_, \ - get_mm_var_, \ - set_var_design_, \ - get_var_design_, \ - set_instance_, \ - set_weightvector_, \ - get_weightvector_, \ - get_var_blend_, \ - done_blend_ \ +#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_, \ + get_mm_, \ + set_mm_design_, \ + set_mm_blend_, \ + get_mm_blend_, \ + get_mm_var_, \ + set_var_design_, \ + get_var_design_, \ + set_named_instance_, \ + get_default_named_instance_, \ + set_mm_weightvector_, \ + get_mm_weightvector_, \ + \ + construct_ps_name_, \ + load_delta_set_idx_map_, \ + load_item_var_store_, \ + get_item_delta_, \ + done_item_var_store_, \ + done_delta_set_idx_map_, \ + get_var_blend_, \ + done_blend_ ) \ + static const FT_Service_MultiMastersRec class_ = \ + { \ + get_mm_, \ + set_mm_design_, \ + set_mm_blend_, \ + get_mm_blend_, \ + get_mm_var_, \ + set_var_design_, \ + get_var_design_, \ + set_named_instance_, \ + get_default_named_instance_, \ + set_mm_weightvector_, \ + get_mm_weightvector_, \ + \ + construct_ps_name_, \ + load_delta_set_idx_map_, \ + load_item_var_store_, \ + get_item_delta_, \ + done_item_var_store_, \ + done_delta_set_idx_map_, \ + get_var_blend_, \ + done_blend_ \ }; /* */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svotval.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svotval.h index 763fb2efb..a4683cd5f 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svotval.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svotval.h @@ -4,7 +4,7 @@ * * The FreeType OpenType validation service (specification). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpfr.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpfr.h index bdeba0785..fd189c7de 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpfr.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpfr.h @@ -4,7 +4,7 @@ * * Internal PFR service functions (specification). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpostnm.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpostnm.h index 8ef62c5f9..2b8f6dfec 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpostnm.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpostnm.h @@ -4,7 +4,7 @@ * * The FreeType PostScript name services (specification). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svprop.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svprop.h index 8f755436a..932ce32e0 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svprop.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svprop.h @@ -4,7 +4,7 @@ * * The FreeType property service (specification). * - * Copyright (C) 2012-2020 by + * Copyright (C) 2012-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpscmap.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpscmap.h index b4dcd8075..6e599f3aa 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpscmap.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpscmap.h @@ -4,7 +4,7 @@ * * The FreeType PostScript charmap service (specification). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -97,7 +97,7 @@ FT_BEGIN_HEADER (*PS_Unicodes_CharIndexFunc)( PS_Unicodes unicodes, FT_UInt32 unicode ); - typedef FT_UInt32 + typedef FT_UInt (*PS_Unicodes_CharNextFunc)( PS_Unicodes unicodes, FT_UInt32 *unicode ); diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpsinfo.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpsinfo.h index 1e7276ff4..09c4cdccc 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpsinfo.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svpsinfo.h @@ -4,7 +4,7 @@ * * The FreeType PostScript info service (specification). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svsfnt.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svsfnt.h index 39c8b5e19..f98df2ef5 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svsfnt.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svsfnt.h @@ -4,7 +4,7 @@ * * The FreeType SFNT table loading service (specification). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svttcmap.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svttcmap.h index c18bb2336..5f9eb02d6 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svttcmap.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svttcmap.h @@ -4,7 +4,7 @@ * * The FreeType TrueType/sfnt cmap extra information service. * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * Masatake YAMATO, Redhat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svtteng.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svtteng.h index 7a17e4a75..ad577cb29 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svtteng.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svtteng.h @@ -4,7 +4,7 @@ * * The FreeType TrueType engine query service (specification). * - * Copyright (C) 2006-2020 by + * Copyright (C) 2006-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svttglyf.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svttglyf.h index 90a81dd40..ca6fff744 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svttglyf.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svttglyf.h @@ -4,7 +4,7 @@ * * The FreeType TrueType glyph service. * - * Copyright (C) 2007-2020 by + * Copyright (C) 2007-2023 by * David Turner. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svwinfnt.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svwinfnt.h index 8c915f525..002923f8c 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svwinfnt.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/services/svwinfnt.h @@ -4,7 +4,7 @@ * * The FreeType Windows FNT/FONT service (specification). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/sfnt.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/sfnt.h index b4c12dbb2..a2d4e15ba 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/sfnt.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/sfnt.h @@ -4,7 +4,7 @@ * * High-level 'sfnt' driver interface (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -311,6 +311,33 @@ FT_BEGIN_HEADER TT_SBit_MetricsRec *ametrics ); + /************************************************************************** + * + * @functype: + * TT_Load_Svg_Doc_Func + * + * @description: + * Scan the SVG document list to find the document containing the glyph + * that has the ID 'glyph*XXX*', where *XXX* is the value of + * `glyph_index` as a decimal integer. + * + * @inout: + * glyph :: + * The glyph slot from which pointers to the SVG document list is to be + * grabbed. The results are stored back in the slot. + * + * @input: + * glyph_index :: + * The index of the glyph that is to be looked up. + * + * @return: + * FreeType error code. 0 means success. + */ + typedef FT_Error + (*TT_Load_Svg_Doc_Func)( FT_GlyphSlot glyph, + FT_UInt glyph_index ); + + /************************************************************************** * * @functype: @@ -524,6 +551,170 @@ FT_BEGIN_HEADER FT_LayerIterator* iterator ); + /************************************************************************** + * + * @functype: + * TT_Get_Color_Glyph_Paint_Func + * + * @description: + * Find the root @FT_OpaquePaint object for a given glyph ID. + * + * @input: + * face :: + * The target face object. + * + * base_glyph :: + * The glyph index the colored glyph layers are associated with. + * + * @output: + * paint :: + * The root @FT_OpaquePaint object. + * + * @return: + * Value~1 if everything is OK. If no color glyph is found, or the root + * paint could not be retrieved, value~0 gets returned. In case of an + * error, value~0 is returned also. + */ + typedef FT_Bool + ( *TT_Get_Color_Glyph_Paint_Func )( TT_Face face, + FT_UInt base_glyph, + FT_Color_Root_Transform root_transform, + FT_OpaquePaint *paint ); + + + /************************************************************************** + * + * @functype: + * TT_Get_Color_Glyph_ClipBox_Func + * + * @description: + * Search for a 'COLR' v1 clip box for the specified `base_glyph` and + * fill the `clip_box` parameter with the 'COLR' v1 'ClipBox' information + * if one is found. + * + * @input: + * face :: + * A handle to the parent face object. + * + * base_glyph :: + * The glyph index for which to retrieve the clip box. + * + * @output: + * clip_box :: + * The clip box for the requested `base_glyph` if one is found. The + * clip box is computed taking scale and transformations configured on + * the @FT_Face into account. @FT_ClipBox contains @FT_Vector values + * in 26.6 format. + * + * @note: + * To retrieve the clip box in font units, reset scale to units-per-em + * and remove transforms configured using @FT_Set_Transform. + * + * @return: + * Value~1 if a ClipBox is found. If no clip box is found or an + * error occured, value~0 is returned. + */ + typedef FT_Bool + ( *TT_Get_Color_Glyph_ClipBox_Func )( TT_Face face, + FT_UInt base_glyph, + FT_ClipBox* clip_box ); + + + /************************************************************************** + * + * @functype: + * TT_Get_Paint_Layers_Func + * + * @description: + * Access the layers of a `PaintColrLayers` table. + * + * @input: + * face :: + * The target face object. + * + * @inout: + * iterator :: + * The @FT_LayerIterator from an @FT_PaintColrLayers object, for which + * the layers are to be retrieved. The internal state of the iterator + * is incremented after one call to this function for retrieving one + * layer. + * + * @output: + * paint :: + * The root @FT_OpaquePaint object referencing the actual paint table. + * + * @return: + * Value~1 if everything is OK. Value~0 gets returned when the paint + * object can not be retrieved or any other error occurs. + */ + typedef FT_Bool + ( *TT_Get_Paint_Layers_Func )( TT_Face face, + FT_LayerIterator* iterator, + FT_OpaquePaint *paint ); + + + /************************************************************************** + * + * @functype: + * TT_Get_Colorline_Stops_Func + * + * @description: + * Get the gradient and solid fill information for a given glyph. + * + * @input: + * face :: + * The target face object. + * + * @inout: + * iterator :: + * An @FT_ColorStopIterator object. For the first call you should set + * `iterator->p` to `NULL`. For all following calls, simply use the + * same object again. + * + * @output: + * color_stop :: + * Color index and alpha value for the retrieved color stop. + * + * @return: + * Value~1 if everything is OK. If there are no more color stops, + * value~0 gets returned. In case of an error, value~0 is returned + * also. + */ + typedef FT_Bool + ( *TT_Get_Colorline_Stops_Func )( TT_Face face, + FT_ColorStop *color_stop, + FT_ColorStopIterator* iterator ); + + + /************************************************************************** + * + * @functype: + * TT_Get_Paint_Func + * + * @description: + * Get the paint details for a given @FT_OpaquePaint object. + * + * @input: + * face :: + * The target face object. + * + * opaque_paint :: + * The @FT_OpaquePaint object. + * + * @output: + * paint :: + * An @FT_COLR_Paint object holding the details on `opaque_paint`. + * + * @return: + * Value~1 if everything is OK. Value~0 if no details can be found for + * this paint or any other error occured. + */ + typedef FT_Bool + ( *TT_Get_Paint_Func )( TT_Face face, + FT_OpaquePaint opaque_paint, + FT_COLR_Paint *paint ); + + /************************************************************************** * * @functype: @@ -709,73 +900,83 @@ FT_BEGIN_HEADER */ typedef struct SFNT_Interface_ { - TT_Loader_GotoTableFunc goto_table; + TT_Loader_GotoTableFunc goto_table; - TT_Init_Face_Func init_face; - TT_Load_Face_Func load_face; - TT_Done_Face_Func done_face; - FT_Module_Requester get_interface; + TT_Init_Face_Func init_face; + TT_Load_Face_Func load_face; + TT_Done_Face_Func done_face; + FT_Module_Requester get_interface; - TT_Load_Any_Func load_any; + TT_Load_Any_Func load_any; /* these functions are called by `load_face' but they can also */ /* be called from external modules, if there is a need to do so */ - TT_Load_Table_Func load_head; - TT_Load_Metrics_Func load_hhea; - TT_Load_Table_Func load_cmap; - TT_Load_Table_Func load_maxp; - TT_Load_Table_Func load_os2; - TT_Load_Table_Func load_post; + TT_Load_Table_Func load_head; + TT_Load_Metrics_Func load_hhea; + TT_Load_Table_Func load_cmap; + TT_Load_Table_Func load_maxp; + TT_Load_Table_Func load_os2; + TT_Load_Table_Func load_post; - TT_Load_Table_Func load_name; - TT_Free_Table_Func free_name; + TT_Load_Table_Func load_name; + TT_Free_Table_Func free_name; /* this field was called `load_kerning' up to version 2.1.10 */ - TT_Load_Table_Func load_kern; + TT_Load_Table_Func load_kern; - TT_Load_Table_Func load_gasp; - TT_Load_Table_Func load_pclt; + TT_Load_Table_Func load_gasp; + TT_Load_Table_Func load_pclt; /* see `ttload.h'; this field was called `load_bitmap_header' up to */ /* version 2.1.10 */ - TT_Load_Table_Func load_bhed; + TT_Load_Table_Func load_bhed; - TT_Load_SBit_Image_Func load_sbit_image; + TT_Load_SBit_Image_Func load_sbit_image; /* see `ttpost.h' */ - TT_Get_PS_Name_Func get_psname; - TT_Free_Table_Func free_psnames; + TT_Get_PS_Name_Func get_psname; + TT_Free_Table_Func free_psnames; /* starting here, the structure differs from version 2.1.7 */ /* this field was introduced in version 2.1.8, named `get_psname' */ - TT_Face_GetKerningFunc get_kerning; + TT_Face_GetKerningFunc get_kerning; /* new elements introduced after version 2.1.10 */ /* load the font directory, i.e., the offset table and */ /* the table directory */ - TT_Load_Table_Func load_font_dir; - TT_Load_Metrics_Func load_hmtx; + TT_Load_Table_Func load_font_dir; + TT_Load_Metrics_Func load_hmtx; - TT_Load_Table_Func load_eblc; - TT_Free_Table_Func free_eblc; + TT_Load_Table_Func load_eblc; + TT_Free_Table_Func free_eblc; TT_Set_SBit_Strike_Func set_sbit_strike; TT_Load_Strike_Metrics_Func load_strike_metrics; - TT_Load_Table_Func load_cpal; - TT_Load_Table_Func load_colr; - TT_Free_Table_Func free_cpal; - TT_Free_Table_Func free_colr; - TT_Set_Palette_Func set_palette; - TT_Get_Colr_Layer_Func get_colr_layer; - TT_Blend_Colr_Func colr_blend; + TT_Load_Table_Func load_cpal; + TT_Load_Table_Func load_colr; + TT_Free_Table_Func free_cpal; + TT_Free_Table_Func free_colr; + TT_Set_Palette_Func set_palette; + TT_Get_Colr_Layer_Func get_colr_layer; + TT_Get_Color_Glyph_Paint_Func get_colr_glyph_paint; + TT_Get_Color_Glyph_ClipBox_Func get_color_glyph_clipbox; + TT_Get_Paint_Layers_Func get_paint_layers; + TT_Get_Colorline_Stops_Func get_colorline_stops; + TT_Get_Paint_Func get_paint; + TT_Blend_Colr_Func colr_blend; - TT_Get_Metrics_Func get_metrics; + TT_Get_Metrics_Func get_metrics; - TT_Get_Name_Func get_name; - TT_Get_Name_ID_Func get_name_id; + TT_Get_Name_Func get_name; + TT_Get_Name_ID_Func get_name_id; + + /* OpenType SVG Support */ + TT_Load_Table_Func load_svg; + TT_Free_Table_Func free_svg; + TT_Load_Svg_Doc_Func load_svg_doc; } SFNT_Interface; @@ -820,10 +1021,18 @@ FT_BEGIN_HEADER free_colr_, \ set_palette_, \ get_colr_layer_, \ + get_colr_glyph_paint_, \ + get_color_glyph_clipbox, \ + get_paint_layers_, \ + get_colorline_stops_, \ + get_paint_, \ colr_blend_, \ get_metrics_, \ get_name_, \ - get_name_id_ ) \ + get_name_id_, \ + load_svg_, \ + free_svg_, \ + load_svg_doc_ ) \ static const SFNT_Interface class_ = \ { \ goto_table_, \ @@ -860,10 +1069,18 @@ FT_BEGIN_HEADER free_colr_, \ set_palette_, \ get_colr_layer_, \ + get_colr_glyph_paint_, \ + get_color_glyph_clipbox, \ + get_paint_layers_, \ + get_colorline_stops_, \ + get_paint_, \ colr_blend_, \ get_metrics_, \ get_name_, \ - get_name_id_ \ + get_name_id_, \ + load_svg_, \ + free_svg_, \ + load_svg_doc_ \ }; diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/svginterface.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/svginterface.h new file mode 100644 index 000000000..f464b2c05 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/svginterface.h @@ -0,0 +1,46 @@ +/**************************************************************************** + * + * svginterface.h + * + * Interface of ot-svg module (specification only). + * + * Copyright (C) 2022-2023 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#ifndef SVGINTERFACE_H_ +#define SVGINTERFACE_H_ + +#include +#include + + +FT_BEGIN_HEADER + + typedef FT_Error + (*Preset_Bitmap_Func)( FT_Module module, + FT_GlyphSlot slot, + FT_Bool cache ); + + typedef struct SVG_Interface_ + { + Preset_Bitmap_Func preset_slot; + + } SVG_Interface; + + typedef SVG_Interface* SVG_Service; + +FT_END_HEADER + +#endif /* SVGINTERFACE_H_ */ + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/t1types.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/t1types.h index 6a0fe5e97..b9c94398f 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/t1types.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/t1types.h @@ -5,7 +5,7 @@ * Basic Type1/Type2 type definitions and interface (specification * only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -172,8 +172,8 @@ FT_BEGIN_HEADER { FT_Bool IsCIDFont; FT_BBox FontBBox; - FT_Fixed Ascender; - FT_Fixed Descender; + FT_Fixed Ascender; /* optional, mind the zero */ + FT_Fixed Descender; /* optional, mind the zero */ AFM_TrackKern TrackKerns; /* free if non-NULL */ FT_UInt NumTrackKern; AFM_KernPair KernPairs; /* free if non-NULL */ @@ -201,30 +201,30 @@ FT_BEGIN_HEADER typedef struct T1_FaceRec_ { - FT_FaceRec root; - T1_FontRec type1; - const void* psnames; - const void* psaux; - const void* afm_data; - FT_CharMapRec charmaprecs[2]; - FT_CharMap charmaps[2]; + FT_FaceRec root; + T1_FontRec type1; + const void* psnames; + const void* psaux; + const void* afm_data; + FT_CharMapRec charmaprecs[2]; + FT_CharMap charmaps[2]; /* support for Multiple Masters fonts */ - PS_Blend blend; + PS_Blend blend; /* undocumented, optional: indices of subroutines that express */ /* the NormalizeDesignVector and the ConvertDesignVector procedure, */ /* respectively, as Type 2 charstrings; -1 if keywords not present */ - FT_Int ndv_idx; - FT_Int cdv_idx; + FT_Int ndv_idx; + FT_Int cdv_idx; /* undocumented, optional: has the same meaning as len_buildchar */ /* for Type 2 fonts; manipulated by othersubrs 19, 24, and 25 */ - FT_UInt len_buildchar; - FT_Long* buildchar; + FT_UInt len_buildchar; + FT_Long* buildchar; /* since version 2.1 - interface to PostScript hinter */ - const void* pshinter; + const void* pshinter; } T1_FaceRec; diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/tttypes.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/tttypes.h index c36342c93..b9788c783 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/tttypes.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/tttypes.h @@ -5,7 +5,7 @@ * Basic SFNT/TrueType type definitions and interface (specification * only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -779,13 +779,15 @@ FT_BEGIN_HEADER /************************************************************************** * * @struct: - * TT_Post_20Rec + * TT_Post_NamesRec * * @description: - * Postscript names sub-table, format 2.0. Stores the PS name of each - * glyph in the font face. + * Postscript names table, either format 2.0 or 2.5. * * @fields: + * loaded :: + * A flag to indicate whether the PS names are loaded. + * * num_glyphs :: * The number of named glyphs in the table. * @@ -798,68 +800,13 @@ FT_BEGIN_HEADER * glyph_names :: * The PS names not in Mac Encoding. */ - typedef struct TT_Post_20Rec_ + typedef struct TT_Post_NamesRec_ { + FT_Bool loaded; FT_UShort num_glyphs; FT_UShort num_names; FT_UShort* glyph_indices; - FT_Char** glyph_names; - - } TT_Post_20Rec, *TT_Post_20; - - - /************************************************************************** - * - * @struct: - * TT_Post_25Rec - * - * @description: - * Postscript names sub-table, format 2.5. Stores the PS name of each - * glyph in the font face. - * - * @fields: - * num_glyphs :: - * The number of glyphs in the table. - * - * offsets :: - * An array of signed offsets in a normal Mac Postscript name encoding. - */ - typedef struct TT_Post_25_ - { - FT_UShort num_glyphs; - FT_Char* offsets; - - } TT_Post_25Rec, *TT_Post_25; - - - /************************************************************************** - * - * @struct: - * TT_Post_NamesRec - * - * @description: - * Postscript names table, either format 2.0 or 2.5. - * - * @fields: - * loaded :: - * A flag to indicate whether the PS names are loaded. - * - * format_20 :: - * The sub-table used for format 2.0. - * - * format_25 :: - * The sub-table used for format 2.5. - */ - typedef struct TT_Post_NamesRec_ - { - FT_Bool loaded; - - union - { - TT_Post_20Rec format_20; - TT_Post_25Rec format_25; - - } names; + FT_Byte** glyph_names; } TT_Post_NamesRec, *TT_Post_Names; @@ -1253,12 +1200,16 @@ FT_BEGIN_HEADER * mm :: * A pointer to the Multiple Masters service. * - * var :: - * A pointer to the Metrics Variations service. + * tt_var :: + * A pointer to the Metrics Variations service for the "truetype" + * driver. * - * hdmx :: - * The face's horizontal device metrics ('hdmx' table). This table is - * optional in TrueType/OpenType fonts. + * face_var :: + * A pointer to the Metrics Variations service for this `TT_Face`'s + * driver. + * + * psaux :: + * A pointer to the PostScript Auxiliary service. * * gasp :: * The grid-fitting and scaling properties table ('gasp'). This table @@ -1364,6 +1315,12 @@ FT_BEGIN_HEADER * var_postscript_prefix_len :: * The length of the `var_postscript_prefix` string. * + * var_default_named_instance :: + * The index of the default named instance. + * + * non_var_style_name :: + * The non-variation style name, used as a backup. + * * horz_metrics_size :: * The size of the 'hmtx' table. * @@ -1372,7 +1329,7 @@ FT_BEGIN_HEADER * * num_locations :: * The number of glyph locations in this TrueType file. This should be - * identical to the number of glyphs. Ignored for Type 2 fonts. + * one more than the number of glyphs. Ignored for Type 2 fonts. * * glyph_locations :: * An array of longs. These are offsets to glyph data within the @@ -1390,8 +1347,8 @@ FT_BEGIN_HEADER * hdmx_record_size :: * The size of a single hdmx record. * - * hdmx_record_sizes :: - * An array holding the ppem sizes available in the 'hdmx' table. + * hdmx_records :: + * A array of pointers to the 'hdmx' table records sorted by ppem. * * sbit_table :: * A pointer to the font's embedded bitmap location table. @@ -1410,14 +1367,6 @@ FT_BEGIN_HEADER * A mapping between the strike indices exposed by the API and the * indices used in the font's sbit table. * - * cpal :: - * A pointer to data related to the 'CPAL' table. `NULL` if the table - * is not available. - * - * colr :: - * A pointer to data related to the 'COLR' table. `NULL` if the table - * is not available. - * * kern_table :: * A pointer to the 'kern' table. * @@ -1445,19 +1394,23 @@ FT_BEGIN_HEADER * vert_metrics_offset :: * The file offset of the 'vmtx' table. * - * sph_found_func_flags :: - * Flags identifying special bytecode functions (used by the v38 - * implementation of the bytecode interpreter). - * - * sph_compatibility_mode :: - * This flag is set if we are in ClearType backward compatibility mode - * (used by the v38 implementation of the bytecode interpreter). - * * ebdt_start :: * The file offset of the sbit data table (CBDT, bdat, etc.). * * ebdt_size :: * The size of the sbit data table. + * + * cpal :: + * A pointer to data related to the 'CPAL' table. `NULL` if the table + * is not available. + * + * colr :: + * A pointer to data related to the 'COLR' table. `NULL` if the table + * is not available. + * + * svg :: + * A pointer to data related to the 'SVG' table. `NULL` if the table + * is not available. */ typedef struct TT_FaceRec_ { @@ -1508,8 +1461,14 @@ FT_BEGIN_HEADER void* mm; /* a typeless pointer to the FT_Service_MetricsVariationsRec table */ - /* used to handle the HVAR, VVAR, and MVAR OpenType tables */ - void* var; + /* used to handle the HVAR, VVAR, and MVAR OpenType tables by the */ + /* "truetype" driver */ + void* tt_var; + + /* a typeless pointer to the FT_Service_MetricsVariationsRec table */ + /* used to handle the HVAR, VVAR, and MVAR OpenType tables by this */ + /* TT_Face's driver */ + void* face_var; /* since 2.13.1 */ #endif /* a typeless pointer to the PostScript Aux service */ @@ -1591,6 +1550,9 @@ FT_BEGIN_HEADER const char* var_postscript_prefix; /* since 2.7.2 */ FT_UInt var_postscript_prefix_len; /* since 2.7.2 */ + FT_UInt var_default_named_instance; /* since 2.13.1 */ + + const char* non_var_style_name; /* since 2.13.1 */ #endif /* since version 2.2 */ @@ -1598,14 +1560,14 @@ FT_BEGIN_HEADER FT_ULong horz_metrics_size; FT_ULong vert_metrics_size; - FT_ULong num_locations; /* in broken TTF, gid > 0xFFFF */ + FT_ULong num_locations; /* up to 0xFFFF + 1 */ FT_Byte* glyph_locations; FT_Byte* hdmx_table; FT_ULong hdmx_table_size; FT_UInt hdmx_record_count; FT_ULong hdmx_record_size; - FT_Byte* hdmx_record_sizes; + FT_Byte** hdmx_records; FT_Byte* sbit_table; FT_ULong sbit_table_size; @@ -1627,13 +1589,6 @@ FT_BEGIN_HEADER FT_ULong horz_metrics_offset; FT_ULong vert_metrics_offset; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* since 2.4.12 */ - FT_ULong sph_found_func_flags; /* special functions found */ - /* for this face */ - FT_Bool sph_compatibility_mode; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS /* since 2.7 */ FT_ULong ebdt_start; /* either `CBDT', `EBDT', or `bdat' */ @@ -1644,6 +1599,9 @@ FT_BEGIN_HEADER void* cpal; void* colr; + /* since 2.12 */ + void* svg; + } TT_FaceRec; @@ -1734,7 +1692,7 @@ FT_BEGIN_HEADER FT_UInt glyph_index; FT_Stream stream; - FT_Int byte_len; + FT_UInt byte_len; FT_Short n_contours; FT_BBox bbox; @@ -1769,6 +1727,9 @@ FT_BEGIN_HEADER /* since version 2.6.2 */ FT_ListRec composites; + /* since version 2.11.2 */ + FT_Byte* widthp; + } TT_LoaderRec; diff --git a/lib/libesp32_lvgl/freetype/include/freetype/internal/wofftypes.h b/lib/libesp32_lvgl/freetype/include/freetype/internal/wofftypes.h index 1874a138a..0c1d8eeaf 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/internal/wofftypes.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/internal/wofftypes.h @@ -5,7 +5,7 @@ * Basic WOFF/WOFF2 type definitions and interface (specification * only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -92,7 +92,7 @@ FT_BEGIN_HEADER */ typedef struct WOFF_TableRec_ { - FT_ULong Tag; /* table ID */ + FT_Tag Tag; /* table ID */ FT_ULong Offset; /* table file offset */ FT_ULong CompLength; /* compressed table length */ FT_ULong OrigLength; /* uncompressed table length */ @@ -191,7 +191,7 @@ FT_BEGIN_HEADER typedef struct WOFF2_TableRec_ { FT_Byte FlagByte; /* table type and flags */ - FT_ULong Tag; /* table file offset */ + FT_Tag Tag; /* table file offset */ FT_ULong dst_length; /* uncompressed table length */ FT_ULong TransformLength; /* transformed length */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/otsvg.h b/lib/libesp32_lvgl/freetype/include/freetype/otsvg.h new file mode 100644 index 000000000..bfe9a6ab7 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/include/freetype/otsvg.h @@ -0,0 +1,336 @@ +/**************************************************************************** + * + * otsvg.h + * + * Interface for OT-SVG support related things (specification). + * + * Copyright (C) 2022-2023 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#ifndef OTSVG_H_ +#define OTSVG_H_ + +#include + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /************************************************************************** + * + * @section: + * svg_fonts + * + * @title: + * OpenType SVG Fonts + * + * @abstract: + * OT-SVG API between FreeType and an external SVG rendering library. + * + * @description: + * This section describes the four hooks necessary to render SVG + * 'documents' that are contained in an OpenType font's 'SVG~' table. + * + * For more information on the implementation, see our standard hooks + * based on 'librsvg' in the [FreeType Demo + * Programs](https://gitlab.freedesktop.org/freetype/freetype-demos) + * repository. + * + */ + + + /************************************************************************** + * + * @functype: + * SVG_Lib_Init_Func + * + * @description: + * A callback that is called when the first OT-SVG glyph is rendered in + * the lifetime of an @FT_Library object. In a typical implementation, + * one would want to allocate a structure and point the `data_pointer` + * to it and perform any library initializations that might be needed. + * + * @inout: + * data_pointer :: + * The SVG rendering module stores a pointer variable that can be used + * by clients to store any data that needs to be shared across + * different hooks. `data_pointer` is essentially a pointer to that + * pointer such that it can be written to as well as read from. + * + * @return: + * FreeType error code. 0 means success. + * + * @since: + * 2.12 + */ + typedef FT_Error + (*SVG_Lib_Init_Func)( FT_Pointer *data_pointer ); + + + /************************************************************************** + * + * @functype: + * SVG_Lib_Free_Func + * + * @description: + * A callback that is called when the `ot-svg` module is being freed. + * It is only called if the init hook was called earlier. This means + * that neither the init nor the free hook is called if no OT-SVG glyph + * is rendered. + * + * In a typical implementation, one would want to free any state + * structure that was allocated in the init hook and perform any + * library-related closure that might be needed. + * + * @inout: + * data_pointer :: + * The SVG rendering module stores a pointer variable that can be used + * by clients to store any data that needs to be shared across + * different hooks. `data_pointer` is essentially a pointer to that + * pointer such that it can be written to as well as read from. + * + * @since: + * 2.12 + */ + typedef void + (*SVG_Lib_Free_Func)( FT_Pointer *data_pointer ); + + + /************************************************************************** + * + * @functype: + * SVG_Lib_Render_Func + * + * @description: + * A callback that is called to render an OT-SVG glyph. This callback + * hook is called right after the preset hook @SVG_Lib_Preset_Slot_Func + * has been called with `cache` set to `TRUE`. The data necessary to + * render is available through the handle @FT_SVG_Document, which is set + * in the `other` field of @FT_GlyphSlotRec. + * + * The render hook is expected to render the SVG glyph to the bitmap + * buffer that is allocated already at `slot->bitmap.buffer`. It also + * sets the `num_grays` value as well as `slot->format`. + * + * @input: + * slot :: + * The slot to render. + * + * @inout: + * data_pointer :: + * The SVG rendering module stores a pointer variable that can be used + * by clients to store any data that needs to be shared across + * different hooks. `data_pointer` is essentially a pointer to that + * pointer such that it can be written to as well as read from. + * + * @return: + * FreeType error code. 0 means success. + * + * @since: + * 2.12 + */ + typedef FT_Error + (*SVG_Lib_Render_Func)( FT_GlyphSlot slot, + FT_Pointer *data_pointer ); + + + /************************************************************************** + * + * @functype: + * SVG_Lib_Preset_Slot_Func + * + * @description: + * A callback that is called to preset the glyph slot. It is called from + * two places. + * + * 1. When `FT_Load_Glyph` needs to preset the glyph slot. + * + * 2. Right before the `svg` module calls the render callback hook. + * + * When it is the former, the argument `cache` is set to `FALSE`. When + * it is the latter, the argument `cache` is set to `TRUE`. This + * distinction has been made because many calculations that are necessary + * for presetting a glyph slot are the same needed later for the render + * callback hook. Thus, if `cache` is `TRUE`, the hook can _cache_ those + * calculations in a memory block referenced by the state pointer. + * + * This hook is expected to preset the slot by setting parameters such as + * `bitmap_left`, `bitmap_top`, `width`, `rows`, `pitch`, and + * `pixel_mode`. It is also expected to set all the metrics for the slot + * including the vertical advance if it is not already set. Typically, + * fonts have horizontal advances but not vertical ones. If those are + * available, they had already been set, otherwise they have to be + * estimated and set manually. The hook must take into account the + * transformations that have been set, and translate the transformation + * matrices into the SVG coordinate system, as the original matrix is + * intended for the TTF/CFF coordinate system. + * + * @input: + * slot :: + * The glyph slot that has the SVG document loaded. + * + * cache :: + * See description. + * + * @inout: + * data_pointer :: + * The SVG rendering module stores a pointer variable that can be used + * by clients to store any data that needs to be shared across + * different hooks. `data_pointer` is essentially a pointer to that + * pointer such that it can be written to as well as read from. + * + * @return: + * FreeType error code. 0 means success. + * + * @since: + * 2.12 + */ + typedef FT_Error + (*SVG_Lib_Preset_Slot_Func)( FT_GlyphSlot slot, + FT_Bool cache, + FT_Pointer *state ); + + + /************************************************************************** + * + * @struct: + * SVG_RendererHooks + * + * @description: + * A structure that stores the four hooks needed to render OT-SVG glyphs + * properly. The structure is publicly used to set the hooks via the + * @svg-hooks driver property. + * + * The behavior of each hook is described in its documentation. One + * thing to note is that the preset hook and the render hook often need + * to do the same operations; therefore, it's better to cache the + * intermediate data in a state structure to avoid calculating it twice. + * For example, in the preset hook one can draw the glyph on a recorder + * surface and later create a bitmap surface from it in the render hook. + * + * All four hooks must be non-NULL. + * + * @fields: + * init_svg :: + * The initialization hook. + * + * free_svg :: + * The cleanup hook. + * + * render_hook :: + * The render hook. + * + * preset_slot :: + * The preset hook. + * + * @since: + * 2.12 + */ + typedef struct SVG_RendererHooks_ + { + SVG_Lib_Init_Func init_svg; + SVG_Lib_Free_Func free_svg; + SVG_Lib_Render_Func render_svg; + + SVG_Lib_Preset_Slot_Func preset_slot; + + } SVG_RendererHooks; + + + /************************************************************************** + * + * @struct: + * FT_SVG_DocumentRec + * + * @description: + * A structure that models one SVG document. + * + * @fields: + * svg_document :: + * A pointer to the SVG document. + * + * svg_document_length :: + * The length of `svg_document`. + * + * metrics :: + * A metrics object storing the size information. + * + * units_per_EM :: + * The size of the EM square. + * + * start_glyph_id :: + * The first glyph ID in the glyph range covered by this document. + * + * end_glyph_id :: + * The last glyph ID in the glyph range covered by this document. + * + * transform :: + * A 2x2 transformation matrix to apply to the glyph while rendering + * it. + * + * delta :: + * The translation to apply to the glyph while rendering. + * + * @note: + * When an @FT_GlyphSlot object `slot` is passed down to a renderer, the + * renderer can only access the `metrics` and `units_per_EM` fields via + * `slot->face`. However, when @FT_Glyph_To_Bitmap sets up a dummy + * object, it has no way to set a `face` object. Thus, metrics + * information and `units_per_EM` (which is necessary for OT-SVG) has to + * be stored separately. + * + * @since: + * 2.12 + */ + typedef struct FT_SVG_DocumentRec_ + { + FT_Byte* svg_document; + FT_ULong svg_document_length; + + FT_Size_Metrics metrics; + FT_UShort units_per_EM; + + FT_UShort start_glyph_id; + FT_UShort end_glyph_id; + + FT_Matrix transform; + FT_Vector delta; + + } FT_SVG_DocumentRec; + + + /************************************************************************** + * + * @type: + * FT_SVG_Document + * + * @description: + * A handle to an @FT_SVG_DocumentRec object. + * + * @since: + * 2.12 + */ + typedef struct FT_SVG_DocumentRec_* FT_SVG_Document; + + +FT_END_HEADER + +#endif /* OTSVG_H_ */ + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/include/freetype/t1tables.h b/lib/libesp32_lvgl/freetype/include/freetype/t1tables.h index 426e14024..1aecfbbd9 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/t1tables.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/t1tables.h @@ -5,7 +5,7 @@ * Basic Type 1/Type 2 tables definitions and interface (specification * only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -360,7 +360,7 @@ FT_BEGIN_HEADER FT_UInt num_subrs; FT_ULong subrmap_offset; - FT_Int sd_bytes; + FT_UInt sd_bytes; } CID_FaceDictRec; @@ -415,11 +415,11 @@ FT_BEGIN_HEADER FT_ULong xuid[16]; FT_ULong cidmap_offset; - FT_Int fd_bytes; - FT_Int gd_bytes; + FT_UInt fd_bytes; + FT_UInt gd_bytes; FT_ULong cid_count; - FT_Int num_dicts; + FT_UInt num_dicts; CID_FaceDict font_dicts; FT_ULong data_offset; @@ -453,22 +453,22 @@ FT_BEGIN_HEADER /************************************************************************** * * @function: - * FT_Has_PS_Glyph_Names + * FT_Has_PS_Glyph_Names * * @description: - * Return true if a given face provides reliable PostScript glyph names. - * This is similar to using the @FT_HAS_GLYPH_NAMES macro, except that - * certain fonts (mostly TrueType) contain incorrect glyph name tables. + * Return true if a given face provides reliable PostScript glyph names. + * This is similar to using the @FT_HAS_GLYPH_NAMES macro, except that + * certain fonts (mostly TrueType) contain incorrect glyph name tables. * - * When this function returns true, the caller is sure that the glyph - * names returned by @FT_Get_Glyph_Name are reliable. + * When this function returns true, the caller is sure that the glyph + * names returned by @FT_Get_Glyph_Name are reliable. * * @input: - * face :: - * face handle + * face :: + * face handle * * @return: - * Boolean. True if glyph names are reliable. + * Boolean. True if glyph names are reliable. * */ FT_EXPORT( FT_Int ) @@ -478,30 +478,40 @@ FT_BEGIN_HEADER /************************************************************************** * * @function: - * FT_Get_PS_Font_Info + * FT_Get_PS_Font_Info * * @description: - * Retrieve the @PS_FontInfoRec structure corresponding to a given - * PostScript font. + * Retrieve the @PS_FontInfoRec structure corresponding to a given + * PostScript font. * * @input: - * face :: - * PostScript face handle. + * face :: + * PostScript face handle. * * @output: - * afont_info :: - * Output font info structure pointer. + * afont_info :: + * A pointer to a @PS_FontInfoRec object. * * @return: - * FreeType error code. 0~means success. + * FreeType error code. 0~means success. * * @note: - * String pointers within the @PS_FontInfoRec structure are owned by the - * face and don't need to be freed by the caller. Missing entries in - * the font's FontInfo dictionary are represented by `NULL` pointers. + * String pointers within the @PS_FontInfoRec structure are owned by the + * face and don't need to be freed by the caller. Missing entries in the + * font's FontInfo dictionary are represented by `NULL` pointers. * - * If the font's format is not PostScript-based, this function will - * return the `FT_Err_Invalid_Argument` error code. + * The following font formats support this feature: 'Type~1', 'Type~42', + * 'CFF', 'CID~Type~1'. For other font formats this function returns the + * `FT_Err_Invalid_Argument` error code. + * + * @example: + * ``` + * PS_FontInfoRec font_info; + * + * + * error = FT_Get_PS_Font_Info( face, &font_info ); + * ... + * ``` * */ FT_EXPORT( FT_Error ) @@ -512,29 +522,39 @@ FT_BEGIN_HEADER /************************************************************************** * * @function: - * FT_Get_PS_Font_Private + * FT_Get_PS_Font_Private * * @description: - * Retrieve the @PS_PrivateRec structure corresponding to a given - * PostScript font. + * Retrieve the @PS_PrivateRec structure corresponding to a given + * PostScript font. * * @input: - * face :: - * PostScript face handle. + * face :: + * PostScript face handle. * * @output: - * afont_private :: - * Output private dictionary structure pointer. + * afont_private :: + * A pointer to a @PS_PrivateRec object. * * @return: - * FreeType error code. 0~means success. + * FreeType error code. 0~means success. * * @note: - * The string pointers within the @PS_PrivateRec structure are owned by - * the face and don't need to be freed by the caller. + * The string pointers within the @PS_PrivateRec structure are owned by + * the face and don't need to be freed by the caller. * - * If the font's format is not PostScript-based, this function returns - * the `FT_Err_Invalid_Argument` error code. + * Only the 'Type~1' font format supports this feature. For other font + * formats this function returns the `FT_Err_Invalid_Argument` error + * code. + * + * @example: + * ``` + * PS_PrivateRec font_private; + * + * + * error = FT_Get_PS_Font_Private( face, &font_private ); + * ... + * ``` * */ FT_EXPORT( FT_Error ) @@ -693,67 +713,67 @@ FT_BEGIN_HEADER /************************************************************************** * * @function: - * FT_Get_PS_Font_Value + * FT_Get_PS_Font_Value * * @description: - * Retrieve the value for the supplied key from a PostScript font. + * Retrieve the value for the supplied key from a PostScript font. * * @input: - * face :: - * PostScript face handle. + * face :: + * PostScript face handle. * - * key :: - * An enumeration value representing the dictionary key to retrieve. + * key :: + * An enumeration value representing the dictionary key to retrieve. * - * idx :: - * For array values, this specifies the index to be returned. + * idx :: + * For array values, this specifies the index to be returned. * - * value :: - * A pointer to memory into which to write the value. + * value :: + * A pointer to memory into which to write the value. * - * valen_len :: - * The size, in bytes, of the memory supplied for the value. + * valen_len :: + * The size, in bytes, of the memory supplied for the value. * * @output: - * value :: - * The value matching the above key, if it exists. + * value :: + * The value matching the above key, if it exists. * * @return: - * The amount of memory (in bytes) required to hold the requested value - * (if it exists, -1 otherwise). + * The amount of memory (in bytes) required to hold the requested value + * (if it exists, -1 otherwise). * * @note: - * The values returned are not pointers into the internal structures of - * the face, but are 'fresh' copies, so that the memory containing them - * belongs to the calling application. This also enforces the - * 'read-only' nature of these values, i.e., this function cannot be - * used to manipulate the face. + * The values returned are not pointers into the internal structures of + * the face, but are 'fresh' copies, so that the memory containing them + * belongs to the calling application. This also enforces the + * 'read-only' nature of these values, i.e., this function cannot be + * used to manipulate the face. * - * `value` is a void pointer because the values returned can be of - * various types. + * `value` is a void pointer because the values returned can be of + * various types. * - * If either `value` is `NULL` or `value_len` is too small, just the - * required memory size for the requested entry is returned. + * If either `value` is `NULL` or `value_len` is too small, just the + * required memory size for the requested entry is returned. * - * The `idx` parameter is used, not only to retrieve elements of, for - * example, the FontMatrix or FontBBox, but also to retrieve name keys - * from the CharStrings dictionary, and the charstrings themselves. It - * is ignored for atomic values. + * The `idx` parameter is used, not only to retrieve elements of, for + * example, the FontMatrix or FontBBox, but also to retrieve name keys + * from the CharStrings dictionary, and the charstrings themselves. It + * is ignored for atomic values. * - * `PS_DICT_BLUE_SCALE` returns a value that is scaled up by 1000. To - * get the value as in the font stream, you need to divide by 65536000.0 - * (to remove the FT_Fixed scale, and the x1000 scale). + * `PS_DICT_BLUE_SCALE` returns a value that is scaled up by 1000. To + * get the value as in the font stream, you need to divide by 65536000.0 + * (to remove the FT_Fixed scale, and the x1000 scale). * - * IMPORTANT: Only key/value pairs read by the FreeType interpreter can - * be retrieved. So, for example, PostScript procedures such as NP, ND, - * and RD are not available. Arbitrary keys are, obviously, not be - * available either. + * IMPORTANT: Only key/value pairs read by the FreeType interpreter can + * be retrieved. So, for example, PostScript procedures such as NP, ND, + * and RD are not available. Arbitrary keys are, obviously, not be + * available either. * - * If the font's format is not PostScript-based, this function returns - * the `FT_Err_Invalid_Argument` error code. + * If the font's format is not PostScript-based, this function returns + * the `FT_Err_Invalid_Argument` error code. * * @since: - * 2.4.8 + * 2.4.8 * */ FT_EXPORT( FT_Long ) diff --git a/lib/libesp32_lvgl/freetype/include/freetype/ttnameid.h b/lib/libesp32_lvgl/freetype/include/freetype/ttnameid.h index 2b2ed4c61..e31c68b9b 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/ttnameid.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/ttnameid.h @@ -4,7 +4,7 @@ * * TrueType name ID definitions (specification only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -591,7 +591,7 @@ FT_BEGIN_HEADER #define TT_MS_LANGID_MALAY_MALAYSIA 0x043E #define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 0x083E #define TT_MS_LANGID_KAZAKH_KAZAKHSTAN 0x043F -#define TT_MS_LANGID_KYRGYZ_KYRGYZSTAN /* Cyrillic*/ 0x0440 +#define TT_MS_LANGID_KYRGYZ_KYRGYZSTAN /* Cyrillic */ 0x0440 #define TT_MS_LANGID_KISWAHILI_KENYA 0x0441 #define TT_MS_LANGID_TURKMEN_TURKMENISTAN 0x0442 #define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 0x0443 diff --git a/lib/libesp32_lvgl/freetype/include/freetype/tttables.h b/lib/libesp32_lvgl/freetype/include/freetype/tttables.h index c8fa35ef8..a9f60e762 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/tttables.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/tttables.h @@ -5,7 +5,7 @@ * Basic SFNT/TrueType tables definitions and interface * (specification only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -424,8 +424,8 @@ FT_BEGIN_HEADER /* only version 5 and higher: */ - FT_UShort usLowerOpticalPointSize; /* in twips (1/20th points) */ - FT_UShort usUpperOpticalPointSize; /* in twips (1/20th points) */ + FT_UShort usLowerOpticalPointSize; /* in twips (1/20 points) */ + FT_UShort usUpperOpticalPointSize; /* in twips (1/20 points) */ } TT_OS2; diff --git a/lib/libesp32_lvgl/freetype/include/freetype/tttags.h b/lib/libesp32_lvgl/freetype/include/freetype/tttags.h index 3c9fbd59d..9bf4fca23 100644 --- a/lib/libesp32_lvgl/freetype/include/freetype/tttags.h +++ b/lib/libesp32_lvgl/freetype/include/freetype/tttags.h @@ -4,7 +4,7 @@ * * Tags for TrueType and OpenType tables (specification only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -95,6 +95,7 @@ FT_BEGIN_HEADER #define TTAG_sbix FT_MAKE_TAG( 's', 'b', 'i', 'x' ) #define TTAG_sfnt FT_MAKE_TAG( 's', 'f', 'n', 't' ) #define TTAG_SING FT_MAKE_TAG( 'S', 'I', 'N', 'G' ) +#define TTAG_SVG FT_MAKE_TAG( 'S', 'V', 'G', ' ' ) #define TTAG_trak FT_MAKE_TAG( 't', 'r', 'a', 'k' ) #define TTAG_true FT_MAKE_TAG( 't', 'r', 'u', 'e' ) #define TTAG_ttc FT_MAKE_TAG( 't', 't', 'c', ' ' ) diff --git a/lib/libesp32_lvgl/freetype/include/ft2build.h b/lib/libesp32_lvgl/freetype/include/ft2build.h index b4fd1f8c3..58491ceea 100644 --- a/lib/libesp32_lvgl/freetype/include/ft2build.h +++ b/lib/libesp32_lvgl/freetype/include/ft2build.h @@ -4,7 +4,7 @@ * * FreeType 2 build and setup macros. * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/library.json b/lib/libesp32_lvgl/freetype/library.json index dd7932a53..93d86e7b1 100644 --- a/lib/libesp32_lvgl/freetype/library.json +++ b/lib/libesp32_lvgl/freetype/library.json @@ -1,6 +1,6 @@ { "name":"freetype", - "version": "2.10.4", + "version": "2.13.2", "description":"Software library to render fonts", "keywords":"freetype", "license": "FreeType License", diff --git a/lib/libesp32_lvgl/freetype/meson.build b/lib/libesp32_lvgl/freetype/meson.build deleted file mode 100644 index fb297c65c..000000000 --- a/lib/libesp32_lvgl/freetype/meson.build +++ /dev/null @@ -1,395 +0,0 @@ -# -# Meson project file for FreeType 2 -# - -# Copyright (C) 2020-2021 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - - -project('freetype2', 'c', - meson_version: '>= 0.55.0', - default_options: ['default_library=both'], - version: run_command('builds/meson/extract_freetype_version.py', - 'include/freetype/freetype.h').stdout().strip(), -) - -# -# Rules to compile the FreeType 2 library itself -# - - -# Apparently meson doesn't provide a read_file() function, so instead -# running an external command is required. - -python = import('python') -python_exe = python.find_installation(required: true) - -ft2_so_version = run_command(python_exe, - files('builds/meson/extract_libtool_version.py'), - '--soversion', - files('builds/unix/configure.raw')).stdout().strip() - -ft2_pkgconfig_version = run_command(python_exe, - files('builds/meson/extract_libtool_version.py'), - files('builds/unix/configure.raw')).stdout().strip() - -ft2_includes = include_directories('include') - - -# Generate a custom `ftmodule.h` version based on the content of -# `modules.cfg`. - -ftmodule_h = custom_target('ftmodule.h', - output: 'ftmodule.h', - input: 'modules.cfg', - command: [python_exe, files('builds/meson/parse_modules_cfg.py'), - '--format=ftmodule.h', '@INPUT@', '--output', '@OUTPUT@'], - install: true, - install_dir: 'include/freetype2/freetype/config', -) -ft2_sources = [ftmodule_h] - - -# FreeType 2 modules. - -ft_main_modules = run_command(python_exe, - files('builds/meson/parse_modules_cfg.py'), - '--format=main-modules', - files('modules.cfg')).stdout().strip().split() - -ft2_sources += files([ - 'src/base/ftbase.c', - 'src/base/ftinit.c', -]) - -foreach mod: ft_main_modules - source = mod - if mod == 'winfonts' - source = 'winfnt' - elif mod == 'cid' - source = 'type1cid' - endif - ft2_sources += 'src/@0@/@1@.c'.format(mod, source) -endforeach - -# NOTE: The `gzip` and `bzip2` aux modules are handled through options. -ft_aux_modules = run_command(python_exe, - files('builds/meson/parse_modules_cfg.py'), - '--format=aux-modules', - files('modules.cfg')).stdout().strip().split() - -foreach auxmod: ft_aux_modules - source = auxmod - # Most sources are named `src//.c`, but there are a few - # exceptions handled here. - if auxmod == 'cache' - source = 'ftcache' - elif auxmod == 'lzw' - source = 'ftlzw' - elif auxmod == 'gzip' or auxmod == 'bzip2' - # Handled through options instead, see below. - continue - endif - ft2_sources += 'src/@0@/@1@.c'.format(auxmod, source) -endforeach - - -# FreeType 2 base extensions. -# Normally configured through `modules.cfg`. - -base_extensions = run_command(python_exe, - files('builds/meson/parse_modules_cfg.py'), - '--format=base-extensions-list', - files('modules.cfg')).stdout().split() - -foreach ext: base_extensions - ft2_sources += files('src/base/' + ext) -endforeach - - -# Header files. - -ft2_public_headers = files([ - 'include/freetype/freetype.h', - 'include/freetype/ftadvanc.h', - 'include/freetype/ftbbox.h', - 'include/freetype/ftbdf.h', - 'include/freetype/ftbitmap.h', - 'include/freetype/ftbzip2.h', - 'include/freetype/ftcache.h', - 'include/freetype/ftchapters.h', - 'include/freetype/ftcolor.h', - 'include/freetype/ftdriver.h', - 'include/freetype/fterrdef.h', - 'include/freetype/fterrors.h', - 'include/freetype/ftfntfmt.h', - 'include/freetype/ftgasp.h', - 'include/freetype/ftglyph.h', - 'include/freetype/ftgxval.h', - 'include/freetype/ftgzip.h', - 'include/freetype/ftimage.h', - 'include/freetype/ftincrem.h', - 'include/freetype/ftlcdfil.h', - 'include/freetype/ftlist.h', - 'include/freetype/ftlzw.h', - 'include/freetype/ftmac.h', - 'include/freetype/ftmm.h', - 'include/freetype/ftmodapi.h', - 'include/freetype/ftmoderr.h', - 'include/freetype/ftotval.h', - 'include/freetype/ftoutln.h', - 'include/freetype/ftparams.h', - 'include/freetype/ftpfr.h', - 'include/freetype/ftrender.h', - 'include/freetype/ftsizes.h', - 'include/freetype/ftsnames.h', - 'include/freetype/ftstroke.h', - 'include/freetype/ftsynth.h', - 'include/freetype/ftsystem.h', - 'include/freetype/fttrigon.h', - 'include/freetype/fttypes.h', - 'include/freetype/ftwinfnt.h', - 'include/freetype/t1tables.h', - 'include/freetype/ttnameid.h', - 'include/freetype/tttables.h', - 'include/freetype/tttags.h', -]) - -ft2_config_headers = files([ - 'include/freetype/config/ftconfig.h', - 'include/freetype/config/ftheader.h', - 'include/freetype/config/ftstdlib.h', - 'include/freetype/config/integer-types.h', - 'include/freetype/config/mac-support.h', - 'include/freetype/config/public-macros.h', -]) - -ft2_defines = ['-DFT2_BUILD_LIBRARY=1'] - - -# System support file. - -cc = meson.get_compiler('c') - -# NOTE: msys2 on Windows has `unistd.h` and `fcntl.h` but not `sys/mman.h`! -has_unistd_h = cc.has_header('unistd.h') -has_fcntl_h = cc.has_header('fcntl.h') -has_sys_mman_h = cc.has_header('sys/mman.h') - -mmap_option = get_option('mmap') - -if mmap_option.disabled() - ft2_sources += files(['src/base/ftsystem.c',]) -elif host_machine.system() == 'windows' - ft2_sources += files(['builds/windows/ftsystem.c',]) -else - if has_unistd_h and has_fcntl_h and has_sys_mman_h - # This version of ftsystem.c uses mmap() to read input font files. - ft2_sources += files(['builds/unix/ftsystem.c',]) - elif mmap_option.enabled() - error('mmap was enabled via options but is not available,' - + ' required headers were not found!') - else - ft2_sources += files(['src/base/ftsystem.c',]) - endif -endif - - -# Debug support file -# -# NOTE: Some specialized versions exist for other platforms not supported by -# Meson. Most implementation differences are extremely minor, i.e., in the -# implementation of FT_Message() and FT_Panic(), and getting the `FT2_DEBUG` -# value from the environment, when this is supported. A smaller refactor -# might make these platform-specific files much smaller, and could be moved -# into `ftsystem.c` as well. -# -if host_machine.system() == 'windows' - winmod = import('windows') - ft2_sources += [ - 'builds/windows/ftdebug.c', - winmod.compile_resources('src/base/ftver.rc'), - ] -else - ft2_sources += 'src/base/ftdebug.c' -endif - -ft2_deps = [] - - -# Generate `ftoption.h` based on available dependencies. - -process_header_command = [python_exe, - files('builds/meson/process_ftoption_h.py'), - '@INPUT@', '--output=@OUTPUT@'] -ftoption_command = process_header_command - - -# GZip support -zlib_dep = dependency('zlib', - required: get_option('zlib'), - fallback: 'zlib') - -if zlib_dep.found() - ftoption_command += [ - '--enable=FT_CONFIG_OPTION_USE_ZLIB', - '--enable=FT_CONFIG_OPTION_SYSTEM_ZLIB', - ] - ft2_sources += files(['src/gzip/ftgzip.c',]) - ft2_deps += [zlib_dep] -else - ftoption_command += ['--disable=FT_CONFIG_OPTION_USE_ZLIB'] -endif - -# BZip2 support -bzip2_dep = cc.find_library('bz2', - required: get_option('bzip2')) - -if bzip2_dep.found() - ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_BZIP2'] - ft2_sources += files(['src/bzip2/ftbzip2.c',]) - ft2_deps += [bzip2_dep] -endif - -# PNG support -libpng_dep = dependency('libpng', - required: get_option('png'), - fallback: 'libpng') - -if libpng_dep.found() - ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_PNG'] - ft2_deps += [libpng_dep] -endif - -# Harfbuzz support -harfbuzz_dep = dependency('harfbuzz', - version: '>= 2.0.0', - required: get_option('harfbuzz')) - -if harfbuzz_dep.found() - ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_HARFBUZZ'] - ft2_deps += [harfbuzz_dep] -endif - -# Brotli decompression support -brotli_dep = dependency('libbrotlidec', - required: get_option('brotli')) - -if brotli_dep.found() - ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_BROTLI'] - ft2_deps += [brotli_dep] -endif - -# We can now generate `ftoption.h`. -ftoption_h = custom_target('ftoption.h', - input: 'include/freetype/config/ftoption.h', - output: 'ftoption.h', - command: ftoption_command, - install: true, - install_dir: 'include/freetype2/freetype/config', -) -ft2_sources += ftoption_h -ft2_defines += ['-DFT_CONFIG_OPTIONS_H='] - -if host_machine.system() == 'windows' - ft2_defines += ['-DDLL_EXPORT=1'] -endif - - -# Generate `ftconfig.h` - -ftconfig_command = process_header_command -if has_unistd_h - ftconfig_command += '--enable=HAVE_UNISTD_H' -endif -if has_fcntl_h - ftconfig_command += '--enable=HAVE_FCNTL_H' -endif - -if host_machine.system() in ['linux', 'darwin', 'cygwin'] - ftconfig_h_in = files('builds/unix/ftconfig.h.in') - ftconfig_h = custom_target('ftconfig.h', - input: ftconfig_h_in, - output: 'ftconfig.h', - command: ftconfig_command, - install: true, - install_dir: 'include/freetype2/freetype/config', - ) - ft2_sources += ftconfig_h - ft2_defines += ['-DFT_CONFIG_CONFIG_H='] -endif - - -ft2_lib = library('freetype', - sources: ft2_sources + [ftmodule_h], - c_args: ft2_defines, - gnu_symbol_visibility: 'hidden', - include_directories: ft2_includes, - dependencies: ft2_deps, - install: true, - version: ft2_so_version, -) - - -# To be used by other projects including this one through subproject(). -freetype_dep = declare_dependency( - include_directories: ft2_includes, - link_with: ft2_lib, - version: ft2_pkgconfig_version) - -meson.override_dependency('freetype2', freetype_dep) - - -# NOTE: Using both `install_dir` and `subdir` doesn't seem to work below, -# i.e., the subdir value seems to be ignored, contrary to examples in the -# Meson documentation. -install_headers('include/ft2build.h', - install_dir: 'include/freetype2') -install_headers(ft2_public_headers, - install_dir: 'include/freetype2/freetype') -install_headers(ft2_config_headers, - install_dir: 'include/freetype2/freetype/config') - - -pkgconfig = import('pkgconfig') - -pkgconfig.generate(ft2_lib, - filebase: 'freetype2', - name: 'FreeType 2', - description: 'A free, high-quality, and portable font engine.', - url: 'https://freetype.org', - subdirs: 'freetype2', - version: ft2_pkgconfig_version, -) - - -# NOTE: Unlike the old `make refdoc` command, this generates the -# documentation under `$BUILD/docs/` since Meson doesn't support modifying -# the source root directory (which is a good thing). -gen_docs = custom_target('freetype2 reference documentation', - output: 'docs', - input: ft2_public_headers + ft2_config_headers, - command: [python_exe, - files('builds/meson/generate_reference_docs.py'), - '--version=' + meson.project_version(), - '--input-dir=' + meson.source_root(), - '--output-dir=@OUTPUT@' - ], -) - - -summary({'OS': host_machine.system(), - 'Zlib': zlib_dep.found() ? 'yes' : 'no', - 'Bzip2': bzip2_dep.found() ? 'yes' : 'no', - 'Png': libpng_dep.found() ? 'yes' : 'no', - 'Harfbuzz': harfbuzz_dep.found() ? 'yes' : 'no', - 'Brotli': brotli_dep.found() ? 'yes' : 'no', - }, section: 'Configuration Options Summary:') - -# EOF diff --git a/lib/libesp32_lvgl/freetype/meson_options.txt b/lib/libesp32_lvgl/freetype/meson_options.txt deleted file mode 100644 index f0fc50a38..000000000 --- a/lib/libesp32_lvgl/freetype/meson_options.txt +++ /dev/null @@ -1,46 +0,0 @@ -# -# meson_options.txt -# - -# Copyright (C) 2020-2021 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. - - -option('zlib', - type: 'feature', - value: 'auto', - description: 'Support reading gzip-compressed font files.') - -option('bzip2', - type: 'feature', - value: 'auto', - description: 'Support reading bzip2-compressed font files.') - -option('png', - type: 'feature', - value: 'auto', - description: 'Support color bitmap glyph formats in the PNG format.' - + 'Requires libpng.') - -option('harfbuzz', - type: 'feature', - value: 'auto', - description: 'Use Harfbuzz library to improve auto-hinting.' - + ' If available, many glyphs not directly addressable' - + ' by a font\'s character map will be hinted also.') - -option('brotli', - type: 'feature', - value: 'auto', - description: 'Use Brotli library to support decompressing WOFF2 fonts.') - -option('mmap', - type: 'feature', - value: 'auto', - description: 'Use mmap() to open font files for faster parsing.') diff --git a/lib/libesp32_lvgl/freetype/modules.cfg b/lib/libesp32_lvgl/freetype/modules.cfg deleted file mode 100644 index de66ee53a..000000000 --- a/lib/libesp32_lvgl/freetype/modules.cfg +++ /dev/null @@ -1,250 +0,0 @@ -# modules.cfg -# -# Copyright (C) 2005-2021 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. -# -# -# In case you compile the FreeType library with GNU make or makepp, this -# file controls which components are built into the library. Otherwise, -# please read this file for information on the various modules and its -# dependencies, then follow the instructions in the file `docs/INSTALL.ANY'. -# -# To deactivate a module, simply comment out the corresponding line. To -# activate a module, remove the comment character. -# -# Note that many modules and components are further controlled with macros -# in the file `include/freetype/config/ftoption.h'. - - -#### -#### font modules -- at least one is required -#### -#### The order given here (from top to down) is the order used for testing -#### font formats in the compiled library. -#### - -# TrueType font driver. -# -# This driver needs the `sfnt' module. -FONT_MODULES += truetype - -# PostScript Type 1 font driver. -# -# This driver needs the `psaux', `pshinter', and `psnames' modules. -FONT_MODULES += type1 - -# CFF/OpenType font driver. -# -# This driver needs the `sfnt', `psaux', `pshinter', and `psnames' modules. -FONT_MODULES += cff - -# Type 1 CID-keyed font driver. -# -# This driver needs the `psaux', `pshinter', and `psnames' modules. -FONT_MODULES += cid - -# PFR/TrueDoc font driver. See optional extension ftpfr.c below also. -FONT_MODULES += pfr - -# PostScript Type 42 font driver. -# -# This driver needs the `truetype' and `psaux' modules. -FONT_MODULES += type42 - -# Windows FONT/FNT font driver. See optional extension ftwinfnt.c below -# also. -FONT_MODULES += winfonts - -# PCF font driver. If debugging and tracing is enabled, needs `ftbitmap.c'. -FONT_MODULES += pcf - -# BDF font driver. See optional extension ftbdf.c below also. -FONT_MODULES += bdf - -# SFNT files support. If used without `truetype' or `cff', it supports -# bitmap-only fonts within an SFNT wrapper. -# -# This driver needs the `psnames' module. -FONT_MODULES += sfnt - - -#### -#### hinting modules -#### - -# FreeType's auto hinter. -HINTING_MODULES += autofit - -# PostScript hinter. -HINTING_MODULES += pshinter - -# The TrueType hinting engine doesn't have a module of its own but is -# controlled in file include/freetype/config/ftoption.h -# (TT_CONFIG_OPTION_BYTECODE_INTERPRETER and friends). - - -#### -#### raster modules -- at least one is required for vector font formats -#### - -# Monochrome rasterizer. -RASTER_MODULES += raster - -# Anti-aliasing rasterizer. -RASTER_MODULES += smooth - -# Signed distance field rasterizer. -RASTER_MODULES += sdf - - -#### -#### auxiliary modules -#### - -# FreeType's cache sub-system (quite stable but still in beta -- this means -# that its public API is subject to change if necessary). See -# include/freetype/ftcache.h. Needs `ftglyph.c'. -AUX_MODULES += cache - -# TrueType GX/AAT table validation. Needs `ftgxval.c' below. -# -# AUX_MODULES += gxvalid - -# Support for streams compressed with gzip (files with suffix .gz). -# -# See include/freetype/ftgzip.h for the API. -AUX_MODULES += gzip - -# Support for streams compressed with LZW (files with suffix .Z). -# -# See include/freetype/ftlzw.h for the API. -AUX_MODULES += lzw - -# Support for streams compressed with bzip2 (files with suffix .bz2). -# -# See include/freetype/ftbzip2.h for the API. -AUX_MODULES += bzip2 - -# OpenType table validation. Needs `ftotval.c' below. -# -# AUX_MODULES += otvalid - -# Auxiliary PostScript driver component to share common code. -# -# This module depends on `psnames'. -AUX_MODULES += psaux - -# Support for PostScript glyph names. -# -# This module can be controlled in ftconfig.h -# (FT_CONFIG_OPTION_POSTSCRIPT_NAMES). -AUX_MODULES += psnames - - -#### -#### base module extensions -#### - -# Exact bounding box calculation. -# -# See include/freetype/ftbbox.h for the API. -BASE_EXTENSIONS += ftbbox.c - -# Access BDF-specific strings. Needs BDF font driver. -# -# See include/freetype/ftbdf.h for the API. -BASE_EXTENSIONS += ftbdf.c - -# Utility functions for converting 1bpp, 2bpp, 4bpp, and 8bpp bitmaps into -# 8bpp format, and for emboldening of bitmap glyphs. -# -# See include/freetype/ftbitmap.h for the API. -BASE_EXTENSIONS += ftbitmap.c - -# Access CID font information. -# -# See include/freetype/ftcid.h for the API. -BASE_EXTENSIONS += ftcid.c - -# Access FSType information. Needs `fttype1.c'. -# -# See include/freetype/freetype.h for the API. -BASE_EXTENSIONS += ftfstype.c - -# Support for GASP table queries. -# -# See include/freetype/ftgasp.h for the API. -BASE_EXTENSIONS += ftgasp.c - -# Convenience functions to handle glyphs. Needs `ftbitmap.c'. -# -# See include/freetype/ftglyph.h for the API. -BASE_EXTENSIONS += ftglyph.c - -# Interface for gxvalid module. -# -# See include/freetype/ftgxval.h for the API. -BASE_EXTENSIONS += ftgxval.c - -# Multiple Master font interface. -# -# See include/freetype/ftmm.h for the API. -BASE_EXTENSIONS += ftmm.c - -# Interface for otvalid module. -# -# See include/freetype/ftotval.h for the API. -BASE_EXTENSIONS += ftotval.c - -# Support for FT_Face_CheckTrueTypePatents. -# -# See include/freetype/freetype.h for the API. -BASE_EXTENSIONS += ftpatent.c - -# Interface for accessing PFR-specific data. Needs PFR font driver. -# -# See include/freetype/ftpfr.h for the API. -BASE_EXTENSIONS += ftpfr.c - -# Path stroker. Needs `ftglyph.c'. -# -# See include/freetype/ftstroke.h for the API. -BASE_EXTENSIONS += ftstroke.c - -# Support for synthetic emboldening and slanting of fonts. Needs -# `ftbitmap.c'. -# -# See include/freetype/ftsynth.h for the API. -BASE_EXTENSIONS += ftsynth.c - -# Interface to access data specific to PostScript Type 1 and Type 2 (CFF) -# fonts. -# -# See include/freetype/t1tables.h for the API. -BASE_EXTENSIONS += fttype1.c - -# Interface for accessing data specific to Windows FNT files. Needs winfnt -# driver. -# -# See include/freetype/ftwinfnt.h for the API. -BASE_EXTENSIONS += ftwinfnt.c - -#### -#### The components `ftsystem.c' (for memory allocation and stream I/O -#### management) and `ftdebug.c' (for emitting debug messages to the user) -#### are controlled with the following variables. -#### -#### ftsystem.c: $(FTSYS_SRC) -#### ftdebug.c: $(FTDEBUG_SRC) -#### -#### Please refer to docs/CUSTOMIZE for details. -#### - - -# EOF diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afangles.c b/lib/libesp32_lvgl/freetype/src/autofit/afangles.c deleted file mode 100644 index a2d45eb72..000000000 --- a/lib/libesp32_lvgl/freetype/src/autofit/afangles.c +++ /dev/null @@ -1,285 +0,0 @@ -/**************************************************************************** - * - * afangles.c - * - * Routines used to compute vector angles with limited accuracy - * and very high speed. It also contains sorting routines (body). - * - * Copyright (C) 2003-2020 by - * David Turner, Robert Wilhelm, and Werner Lemberg. - * - * This file is part of the FreeType project, and may only be used, - * modified, and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - */ - - -#include "aftypes.h" - - - /* - * We are not using `af_angle_atan' anymore, but we keep the source - * code below just in case... - */ - - -#if 0 - - - /* - * The trick here is to realize that we don't need a very accurate angle - * approximation. We are going to use the result of `af_angle_atan' to - * only compare the sign of angle differences, or check whether its - * magnitude is very small. - * - * The approximation - * - * dy * PI / (|dx|+|dy|) - * - * should be enough, and much faster to compute. - */ - FT_LOCAL_DEF( AF_Angle ) - af_angle_atan( FT_Fixed dx, - FT_Fixed dy ) - { - AF_Angle angle; - FT_Fixed ax = dx; - FT_Fixed ay = dy; - - - if ( ax < 0 ) - ax = -ax; - if ( ay < 0 ) - ay = -ay; - - ax += ay; - - if ( ax == 0 ) - angle = 0; - else - { - angle = ( AF_ANGLE_PI2 * dy ) / ( ax + ay ); - if ( dx < 0 ) - { - if ( angle >= 0 ) - angle = AF_ANGLE_PI - angle; - else - angle = -AF_ANGLE_PI - angle; - } - } - - return angle; - } - - -#elif 0 - - - /* the following table has been automatically generated with */ - /* the `mather.py' Python script */ - -#define AF_ATAN_BITS 8 - - static const FT_Byte af_arctan[1L << AF_ATAN_BITS] = - { - 0, 0, 1, 1, 1, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 5, - 5, 5, 6, 6, 6, 7, 7, 7, - 8, 8, 8, 9, 9, 9, 10, 10, - 10, 10, 11, 11, 11, 12, 12, 12, - 13, 13, 13, 14, 14, 14, 14, 15, - 15, 15, 16, 16, 16, 17, 17, 17, - 18, 18, 18, 18, 19, 19, 19, 20, - 20, 20, 21, 21, 21, 21, 22, 22, - 22, 23, 23, 23, 24, 24, 24, 24, - 25, 25, 25, 26, 26, 26, 26, 27, - 27, 27, 28, 28, 28, 28, 29, 29, - 29, 30, 30, 30, 30, 31, 31, 31, - 31, 32, 32, 32, 33, 33, 33, 33, - 34, 34, 34, 34, 35, 35, 35, 35, - 36, 36, 36, 36, 37, 37, 37, 38, - 38, 38, 38, 39, 39, 39, 39, 40, - 40, 40, 40, 41, 41, 41, 41, 42, - 42, 42, 42, 42, 43, 43, 43, 43, - 44, 44, 44, 44, 45, 45, 45, 45, - 46, 46, 46, 46, 46, 47, 47, 47, - 47, 48, 48, 48, 48, 48, 49, 49, - 49, 49, 50, 50, 50, 50, 50, 51, - 51, 51, 51, 51, 52, 52, 52, 52, - 52, 53, 53, 53, 53, 53, 54, 54, - 54, 54, 54, 55, 55, 55, 55, 55, - 56, 56, 56, 56, 56, 57, 57, 57, - 57, 57, 57, 58, 58, 58, 58, 58, - 59, 59, 59, 59, 59, 59, 60, 60, - 60, 60, 60, 61, 61, 61, 61, 61, - 61, 62, 62, 62, 62, 62, 62, 63, - 63, 63, 63, 63, 63, 64, 64, 64 - }; - - - FT_LOCAL_DEF( AF_Angle ) - af_angle_atan( FT_Fixed dx, - FT_Fixed dy ) - { - AF_Angle angle; - - - /* check trivial cases */ - if ( dy == 0 ) - { - angle = 0; - if ( dx < 0 ) - angle = AF_ANGLE_PI; - return angle; - } - else if ( dx == 0 ) - { - angle = AF_ANGLE_PI2; - if ( dy < 0 ) - angle = -AF_ANGLE_PI2; - return angle; - } - - angle = 0; - if ( dx < 0 ) - { - dx = -dx; - dy = -dy; - angle = AF_ANGLE_PI; - } - - if ( dy < 0 ) - { - FT_Pos tmp; - - - tmp = dx; - dx = -dy; - dy = tmp; - angle -= AF_ANGLE_PI2; - } - - if ( dx == 0 && dy == 0 ) - return 0; - - if ( dx == dy ) - angle += AF_ANGLE_PI4; - else if ( dx > dy ) - angle += af_arctan[FT_DivFix( dy, dx ) >> ( 16 - AF_ATAN_BITS )]; - else - angle += AF_ANGLE_PI2 - - af_arctan[FT_DivFix( dx, dy ) >> ( 16 - AF_ATAN_BITS )]; - - if ( angle > AF_ANGLE_PI ) - angle -= AF_ANGLE_2PI; - - return angle; - } - - -#endif /* 0 */ - - - FT_LOCAL_DEF( void ) - af_sort_pos( FT_UInt count, - FT_Pos* table ) - { - FT_UInt i, j; - FT_Pos swap; - - - for ( i = 1; i < count; i++ ) - { - for ( j = i; j > 0; j-- ) - { - if ( table[j] >= table[j - 1] ) - break; - - swap = table[j]; - table[j] = table[j - 1]; - table[j - 1] = swap; - } - } - } - - - FT_LOCAL_DEF( void ) - af_sort_and_quantize_widths( FT_UInt* count, - AF_Width table, - FT_Pos threshold ) - { - FT_UInt i, j; - FT_UInt cur_idx; - FT_Pos cur_val; - FT_Pos sum; - AF_WidthRec swap; - - - if ( *count == 1 ) - return; - - /* sort */ - for ( i = 1; i < *count; i++ ) - { - for ( j = i; j > 0; j-- ) - { - if ( table[j].org >= table[j - 1].org ) - break; - - swap = table[j]; - table[j] = table[j - 1]; - table[j - 1] = swap; - } - } - - cur_idx = 0; - cur_val = table[cur_idx].org; - - /* compute and use mean values for clusters not larger than */ - /* `threshold'; this is very primitive and might not yield */ - /* the best result, but normally, using reference character */ - /* `o', `*count' is 2, so the code below is fully sufficient */ - for ( i = 1; i < *count; i++ ) - { - if ( table[i].org - cur_val > threshold || - i == *count - 1 ) - { - sum = 0; - - /* fix loop for end of array */ - if ( table[i].org - cur_val <= threshold && - i == *count - 1 ) - i++; - - for ( j = cur_idx; j < i; j++ ) - { - sum += table[j].org; - table[j].org = 0; - } - table[cur_idx].org = sum / (FT_Pos)j; - - if ( i < *count - 1 ) - { - cur_idx = i + 1; - cur_val = table[cur_idx].org; - } - } - } - - cur_idx = 1; - - /* compress array to remove zero values */ - for ( i = 1; i < *count; i++ ) - { - if ( table[i].org ) - table[cur_idx++] = table[i]; - } - - *count = cur_idx; - } - - -/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afangles.h b/lib/libesp32_lvgl/freetype/src/autofit/afangles.h deleted file mode 100644 index 18d7dae3a..000000000 --- a/lib/libesp32_lvgl/freetype/src/autofit/afangles.h +++ /dev/null @@ -1,7 +0,0 @@ -/* - * afangles.h - * - * This is a dummy file, used to please the build system. It is never - * included by the auto-fitter sources. - * - */ diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afblue.c b/lib/libesp32_lvgl/freetype/src/autofit/afblue.c index 9ebffdd09..d7655b9b9 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afblue.c +++ b/lib/libesp32_lvgl/freetype/src/autofit/afblue.c @@ -7,7 +7,7 @@ * * Auto-fitter data for blue strings (body). * - * Copyright (C) 2013-2020 by + * Copyright (C) 2013-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afblue.cin b/lib/libesp32_lvgl/freetype/src/autofit/afblue.cin index c6a697fee..d561c5093 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afblue.cin +++ b/lib/libesp32_lvgl/freetype/src/autofit/afblue.cin @@ -4,7 +4,7 @@ * * Auto-fitter data for blue strings (body). * - * Copyright (C) 2013-2020 by + * Copyright (C) 2013-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afblue.dat b/lib/libesp32_lvgl/freetype/src/autofit/afblue.dat index b19b8df0f..8299baa25 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afblue.dat +++ b/lib/libesp32_lvgl/freetype/src/autofit/afblue.dat @@ -2,7 +2,7 @@ // // Auto-fitter data for blue strings. // -// Copyright (C) 2013-2020 by +// Copyright (C) 2013-2023 by // David Turner, Robert Wilhelm, and Werner Lemberg. // // This file is part of the FreeType project, and may only be used, @@ -89,7 +89,7 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: "ت ث ط ظ ك" // We don't necessarily have access to medial forms via Unicode in case // Arabic presentational forms are missing. The only character that is - // guaranteed to have the same vertical position with joining (this is, + // guaranteed to have the same vertical position with joining (that is, // non-isolated) forms is U+0640, ARABIC TATWEEL, which must join both // round and flat curves. AF_BLUE_STRING_ARABIC_JOIN diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afblue.h b/lib/libesp32_lvgl/freetype/src/autofit/afblue.h index 486d663b6..76f2f47cb 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afblue.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/afblue.h @@ -7,7 +7,7 @@ * * Auto-fitter data for blue strings (specification). * - * Copyright (C) 2013-2020 by + * Copyright (C) 2013-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afblue.hin b/lib/libesp32_lvgl/freetype/src/autofit/afblue.hin index 395702709..6a31298e6 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afblue.hin +++ b/lib/libesp32_lvgl/freetype/src/autofit/afblue.hin @@ -4,7 +4,7 @@ * * Auto-fitter data for blue strings (specification). * - * Copyright (C) 2013-2020 by + * Copyright (C) 2013-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afcjk.c b/lib/libesp32_lvgl/freetype/src/autofit/afcjk.c index 3b340cd5e..f414289ad 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afcjk.c +++ b/lib/libesp32_lvgl/freetype/src/autofit/afcjk.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for CJK writing system (body). * - * Copyright (C) 2006-2020 by + * Copyright (C) 2006-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -37,11 +37,6 @@ #include "aferrors.h" -#ifdef AF_CONFIG_OPTION_USE_WARPER -#include "afwarp.h" -#endif - - /************************************************************************** * * The macro FT_COMPONENT is used in trace mode. It is an implicit @@ -72,11 +67,11 @@ AF_GlyphHintsRec hints[1]; - FT_TRACE5(( "\n" - "cjk standard widths computation (style `%s')\n" - "===================================================\n" - "\n", + FT_TRACE5(( "\n" )); + FT_TRACE5(( "cjk standard widths computation (style `%s')\n", af_style_names[metrics->root.style_class->style] )); + FT_TRACE5(( "===================================================\n" )); + FT_TRACE5(( "\n" )); af_glyph_hints_init( hints, face->memory ); @@ -314,9 +309,9 @@ /* style's entry in the `af_blue_stringset' array, computing its */ /* extremum points (depending on the string properties) */ - FT_TRACE5(( "cjk blue zones computation\n" - "==========================\n" - "\n" )); + FT_TRACE5(( "cjk blue zones computation\n" )); + FT_TRACE5(( "==========================\n" )); + FT_TRACE5(( "\n" )); #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ shaper_buf = af_shaper_buf_create( face ); @@ -422,16 +417,14 @@ { FT_Int nn; - FT_Int first = 0; - FT_Int last = -1; + FT_Int pp, first, last; - for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ ) + last = -1; + for ( nn = 0; nn < outline.n_contours; nn++ ) { - FT_Int pp; - - - last = outline.contours[nn]; + first = last + 1; + last = outline.contours[nn]; /* Avoid single-point contours since they are never rasterized. */ /* In some fonts, they correspond to mark attachment points */ @@ -555,9 +548,8 @@ if ( AF_CJK_IS_TOP_BLUE( bs ) ) blue->flags |= AF_CJK_BLUE_TOP; - FT_TRACE5(( " -> reference = %ld\n" - " overshoot = %ld\n", - *blue_ref, *blue_shoot )); + FT_TRACE5(( " -> reference = %ld\n", *blue_ref )); + FT_TRACE5(( " overshoot = %ld\n", *blue_shoot )); } /* end for loop */ @@ -575,8 +567,8 @@ af_cjk_metrics_check_digits( AF_CJKMetrics metrics, FT_Face face ) { - FT_Bool started = 0, same_width = 1; - FT_Fixed advance = 0, old_advance = 0; + FT_Bool started = 0, same_width = 1; + FT_Long advance = 0, old_advance = 0; /* If HarfBuzz is not available, we need a pointer to a single */ /* unsigned long value. */ @@ -641,10 +633,11 @@ /* Initialize global metrics. */ FT_LOCAL_DEF( FT_Error ) - af_cjk_metrics_init( AF_CJKMetrics metrics, - FT_Face face ) + af_cjk_metrics_init( AF_StyleMetrics metrics_, /* AF_CJKMetrics */ + FT_Face face ) { - FT_CharMap oldmap = face->charmap; + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + FT_CharMap oldmap = face->charmap; metrics->units_per_em = face->units_per_EM; @@ -656,7 +649,7 @@ af_cjk_metrics_check_digits( metrics, face ); } - FT_Set_Charmap( face, oldmap ); + face->charmap = oldmap; return FT_Err_Ok; } @@ -743,13 +736,15 @@ blue->shoot.fit = blue->ref.fit - delta2; - FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]:\n" - " ref: cur=%.2f fit=%.2f\n" - " shoot: cur=%.2f fit=%.2f\n", + FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]:\n", ( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V', - nn, blue->ref.org, blue->shoot.org, - blue->ref.cur / 64.0, blue->ref.fit / 64.0, - blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 )); + nn, blue->ref.org, blue->shoot.org )); + FT_TRACE5(( " ref: cur=%.2f fit=%.2f\n", + (double)blue->ref.cur / 64, + (double)blue->ref.fit / 64 )); + FT_TRACE5(( " shoot: cur=%.2f fit=%.2f\n", + (double)blue->shoot.cur / 64, + (double)blue->shoot.fit / 64 )); blue->flags |= AF_CJK_BLUE_ACTIVE; } @@ -760,9 +755,12 @@ /* Scale global values in both directions. */ FT_LOCAL_DEF( void ) - af_cjk_metrics_scale( AF_CJKMetrics metrics, - AF_Scaler scaler ) + af_cjk_metrics_scale( AF_StyleMetrics metrics_, /* AF_CJKMetrics */ + AF_Scaler scaler ) { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + + /* we copy the whole structure since the x and y scaling values */ /* are not modified, contrary to e.g. the `latin' auto-hinter */ metrics->root.scaler = *scaler; @@ -775,11 +773,14 @@ /* Extract standard_width from writing system/script specific */ /* metrics class. */ - FT_LOCAL_DEF( void ) - af_cjk_get_standard_widths( AF_CJKMetrics metrics, - FT_Pos* stdHW, - FT_Pos* stdVW ) + FT_CALLBACK_DEF( void ) + af_cjk_get_standard_widths( AF_StyleMetrics metrics_, /* AF_CJKMetrics */ + FT_Pos* stdHW, + FT_Pos* stdVW ) { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + + if ( stdHW ) *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width; @@ -849,7 +850,7 @@ { AF_AxisHints axis = &hints->axis[dim]; AF_Segment segments = axis->segments; - AF_Segment segment_limit = segments + axis->num_segments; + AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments ); AF_Direction major_dir = axis->major_dir; AF_Segment seg1, seg2; FT_Pos len_threshold; @@ -1011,7 +1012,7 @@ AF_CJKAxis laxis = &((AF_CJKMetrics)hints->metrics)->axis[dim]; AF_Segment segments = axis->segments; - AF_Segment segment_limit = segments + axis->num_segments; + AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments ); AF_Segment seg; FT_Fixed scale; @@ -1050,7 +1051,7 @@ { AF_Edge found = NULL; FT_Pos best = 0xFFFFU; - FT_Int ee; + FT_UInt ee; /* look for an edge corresponding to the segment */ @@ -1159,7 +1160,7 @@ */ { AF_Edge edges = axis->edges; - AF_Edge edge_limit = edges + axis->num_edges; + AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges ); AF_Edge edge; @@ -1297,7 +1298,7 @@ { AF_AxisHints axis = &hints->axis[dim]; AF_Edge edge = axis->edges; - AF_Edge edge_limit = edge + axis->num_edges; + AF_Edge edge_limit = FT_OFFSET( edge, axis->num_edges ); AF_CJKAxis cjk = &metrics->axis[dim]; FT_Fixed scale = cjk->scale; FT_Pos best_dist0; /* initial threshold */ @@ -1380,9 +1381,10 @@ /* Initalize hinting engine. */ FT_LOCAL_DEF( FT_Error ) - af_cjk_hints_init( AF_GlyphHints hints, - AF_CJKMetrics metrics ) + af_cjk_hints_init( AF_GlyphHints hints, + AF_StyleMetrics metrics_ ) /* AF_CJKMetrics */ { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; FT_Render_Mode mode; FT_UInt32 scaler_flags, other_flags; @@ -1401,11 +1403,6 @@ /* compute flags depending on render mode, etc. */ mode = metrics->root.scaler.render_mode; -#if 0 /* AF_CONFIG_OPTION_USE_WARPER */ - if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V ) - metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL; -#endif - scaler_flags = hints->scaler_flags; other_flags = 0; @@ -1434,12 +1431,6 @@ scaler_flags |= AF_SCALER_FLAG_NO_ADVANCE; -#ifdef AF_CONFIG_OPTION_USE_WARPER - /* get (global) warper flag */ - if ( !metrics->root.globals->module->warping ) - scaler_flags |= AF_SCALER_FLAG_NO_WARPER; -#endif - hints->scaler_flags = scaler_flags; hints->other_flags = other_flags; @@ -1643,11 +1634,13 @@ stem_edge->pos = base_edge->pos + fitted_width; - FT_TRACE5(( " CJKLINK: edge %ld @%d (opos=%.2f) linked to %.2f," + FT_TRACE5(( " CJKLINK: edge %td @%d (opos=%.2f) linked to %.2f," " dist was %.2f, now %.2f\n", stem_edge - hints->axis[dim].edges, stem_edge->fpos, - stem_edge->opos / 64.0, stem_edge->pos / 64.0, - dist / 64.0, fitted_width / 64.0 )); + (double)stem_edge->opos / 64, + (double)stem_edge->pos / 64, + (double)dist / 64, + (double)fitted_width / 64 )); } @@ -1815,7 +1808,7 @@ { AF_AxisHints axis = &hints->axis[dim]; AF_Edge edges = axis->edges; - AF_Edge edge_limit = edges + axis->num_edges; + AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges ); FT_PtrDist n_edges; AF_Edge edge; AF_Edge anchor = NULL; @@ -1865,10 +1858,10 @@ continue; #ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE5(( " CJKBLUE: edge %ld @%d (opos=%.2f) snapped to %.2f," + FT_TRACE5(( " CJKBLUE: edge %td @%d (opos=%.2f) snapped to %.2f," " was %.2f\n", - edge1 - edges, edge1->fpos, edge1->opos / 64.0, - blue->fit / 64.0, edge1->pos / 64.0 )); + edge1 - edges, edge1->fpos, (double)edge1->opos / 64, + (double)blue->fit / 64, (double)edge1->pos / 64 )); num_actions++; #endif @@ -1929,7 +1922,7 @@ /* this should not happen, but it's better to be safe */ if ( edge2->blue_edge ) { - FT_TRACE5(( "ASSERTION FAILED for edge %ld\n", edge2-edges )); + FT_TRACE5(( "ASSERTION FAILED for edge %td\n", edge2 - edges )); af_cjk_align_linked_edge( hints, dim, edge2, edge ); edge->flags |= AF_EDGE_DONE; @@ -2041,8 +2034,8 @@ #if 0 printf( "stem (%d,%d) adjusted (%.1f,%.1f)\n", edge - edges, edge2 - edges, - ( edge->pos - edge->opos ) / 64.0, - ( edge2->pos - edge2->opos ) / 64.0 ); + (double)( edge->pos - edge->opos ) / 64, + (double)( edge2->pos - edge2->opos ) / 64 ); #endif anchor = edge; @@ -2194,7 +2187,7 @@ { AF_AxisHints axis = & hints->axis[dim]; AF_Edge edges = axis->edges; - AF_Edge edge_limit = edges + axis->num_edges; + AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges ); AF_Edge edge; FT_Bool snapping; @@ -2281,11 +2274,13 @@ /* Apply the complete hinting algorithm to a CJK glyph. */ FT_LOCAL_DEF( FT_Error ) - af_cjk_hints_apply( FT_UInt glyph_index, - AF_GlyphHints hints, - FT_Outline* outline, - AF_CJKMetrics metrics ) + af_cjk_hints_apply( FT_UInt glyph_index, + AF_GlyphHints hints, + FT_Outline* outline, + AF_StyleMetrics metrics_ ) /* AF_CJKMetrics */ { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + FT_Error error; int dim; @@ -2322,25 +2317,6 @@ if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) || ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) ) { - -#ifdef AF_CONFIG_OPTION_USE_WARPER - if ( dim == AF_DIMENSION_HORZ && - metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL && - AF_HINTS_DO_WARP( hints ) ) - { - AF_WarperRec warper; - FT_Fixed scale; - FT_Pos delta; - - - af_warper_compute( &warper, hints, (AF_Dimension)dim, - &scale, &delta ); - af_glyph_hints_scale_dim( hints, (AF_Dimension)dim, - scale, delta ); - continue; - } -#endif /* AF_CONFIG_OPTION_USE_WARPER */ - af_cjk_hint_edges( hints, (AF_Dimension)dim ); af_cjk_align_edge_points( hints, (AF_Dimension)dim ); af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim ); diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afcjk.h b/lib/libesp32_lvgl/freetype/src/autofit/afcjk.h index fd0f451aa..f380ef6e0 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afcjk.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/afcjk.h @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for CJK writing system (specification). * - * Copyright (C) 2006-2020 by + * Copyright (C) 2006-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -103,22 +103,22 @@ FT_BEGIN_HEADER #ifdef AF_CONFIG_OPTION_CJK FT_LOCAL( FT_Error ) - af_cjk_metrics_init( AF_CJKMetrics metrics, - FT_Face face ); + af_cjk_metrics_init( AF_StyleMetrics metrics, + FT_Face face ); FT_LOCAL( void ) - af_cjk_metrics_scale( AF_CJKMetrics metrics, - AF_Scaler scaler ); + af_cjk_metrics_scale( AF_StyleMetrics metrics, + AF_Scaler scaler ); FT_LOCAL( FT_Error ) - af_cjk_hints_init( AF_GlyphHints hints, - AF_CJKMetrics metrics ); + af_cjk_hints_init( AF_GlyphHints hints, + AF_StyleMetrics metrics ); FT_LOCAL( FT_Error ) - af_cjk_hints_apply( FT_UInt glyph_index, - AF_GlyphHints hints, - FT_Outline* outline, - AF_CJKMetrics metrics ); + af_cjk_hints_apply( FT_UInt glyph_index, + AF_GlyphHints hints, + FT_Outline* outline, + AF_StyleMetrics metrics ); /* shared; called from afindic.c */ FT_LOCAL( void ) diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afcover.h b/lib/libesp32_lvgl/freetype/src/autofit/afcover.h index 03085ad07..102ed4278 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afcover.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/afcover.h @@ -4,7 +4,7 @@ * * Auto-fitter coverages (specification only). * - * Copyright (C) 2013-2020 by + * Copyright (C) 2013-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afdummy.c b/lib/libesp32_lvgl/freetype/src/autofit/afdummy.c index 77d31df97..a4629b528 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afdummy.c +++ b/lib/libesp32_lvgl/freetype/src/autofit/afdummy.c @@ -5,7 +5,7 @@ * Auto-fitter dummy routines to be used if no hinting should be * performed (body). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afdummy.h b/lib/libesp32_lvgl/freetype/src/autofit/afdummy.h index efd799e84..a7af3f62c 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afdummy.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/afdummy.h @@ -5,7 +5,7 @@ * Auto-fitter dummy routines to be used if no hinting should be * performed (specification). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/autofit/aferrors.h b/lib/libesp32_lvgl/freetype/src/autofit/aferrors.h index f90899944..88faf05c9 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/aferrors.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/aferrors.h @@ -4,7 +4,7 @@ * * Autofitter error codes (specification only). * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afglobal.c b/lib/libesp32_lvgl/freetype/src/autofit/afglobal.c index d5129423d..b1957570f 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afglobal.c +++ b/lib/libesp32_lvgl/freetype/src/autofit/afglobal.c @@ -4,7 +4,7 @@ * * Auto-fitter routines to compute global hinting values (body). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -19,6 +19,7 @@ #include "afglobal.h" #include "afranges.h" #include "afshaper.h" +#include "afws-decl.h" #include @@ -32,11 +33,6 @@ #define FT_COMPONENT afglobal - /* get writing system specific header files */ -#undef WRITING_SYSTEM -#define WRITING_SYSTEM( ws, WS ) /* empty */ -#include "afwrtsys.h" - #include "aferrors.h" @@ -74,7 +70,7 @@ af_writing_system_classes[] = { -#include "afwrtsys.h" +#include "afws-iter.h" NULL /* do not remove */ }; @@ -133,13 +129,13 @@ FT_Face face = globals->face; FT_CharMap old_charmap = face->charmap; FT_UShort* gstyles = globals->glyph_styles; - FT_UInt ss; + FT_UShort ss; + FT_UShort dflt = 0xFFFFU; /* a non-valid value */ FT_UInt i; - FT_UInt dflt = ~0U; /* a non-valid value */ /* the value AF_STYLE_UNASSIGNED means `uncovered glyph' */ - for ( i = 0; i < (FT_UInt)globals->glyph_count; i++ ) + for ( i = 0; i < globals->glyph_count; i++ ) gstyles[i] = AF_STYLE_UNASSIGNED; error = FT_Select_Charmap( face, FT_ENCODING_UNICODE ); @@ -172,8 +168,7 @@ */ if ( style_class->coverage == AF_COVERAGE_DEFAULT ) { - if ( (FT_UInt)style_class->script == - globals->module->default_script ) + if ( style_class->script == globals->module->default_script ) dflt = ss; for ( range = script_class->script_uni_ranges; @@ -187,9 +182,9 @@ gindex = FT_Get_Char_Index( face, charcode ); if ( gindex != 0 && - gindex < (FT_ULong)globals->glyph_count && + gindex < globals->glyph_count && ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED ) - gstyles[gindex] = (FT_UShort)ss; + gstyles[gindex] = ss; for (;;) { @@ -198,9 +193,9 @@ if ( gindex == 0 || charcode > range->last ) break; - if ( gindex < (FT_ULong)globals->glyph_count && + if ( gindex < globals->glyph_count && ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED ) - gstyles[gindex] = (FT_UShort)ss; + gstyles[gindex] = ss; } } @@ -215,9 +210,9 @@ gindex = FT_Get_Char_Index( face, charcode ); - if ( gindex != 0 && - gindex < (FT_ULong)globals->glyph_count && - ( gstyles[gindex] & AF_STYLE_MASK ) == (FT_UShort)ss ) + if ( gindex != 0 && + gindex < globals->glyph_count && + ( gstyles[gindex] & AF_STYLE_MASK ) == ss ) gstyles[gindex] |= AF_NONBASE; for (;;) @@ -227,8 +222,8 @@ if ( gindex == 0 || charcode > range->last ) break; - if ( gindex < (FT_ULong)globals->glyph_count && - ( gstyles[gindex] & AF_STYLE_MASK ) == (FT_UShort)ss ) + if ( gindex < globals->glyph_count && + ( gstyles[gindex] & AF_STYLE_MASK ) == ss ) gstyles[gindex] |= AF_NONBASE; } } @@ -259,7 +254,7 @@ FT_UInt gindex = FT_Get_Char_Index( face, i ); - if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count ) + if ( gindex != 0 && gindex < globals->glyph_count ) gstyles[gindex] |= AF_DIGIT; } @@ -270,7 +265,7 @@ */ if ( globals->module->fallback_style != AF_STYLE_UNASSIGNED ) { - FT_Long nn; + FT_UInt nn; for ( nn = 0; nn < globals->glyph_count; nn++ ) @@ -285,16 +280,16 @@ #ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE4(( "\n" - "style coverage\n" - "==============\n" - "\n" )); + FT_TRACE4(( "\n" )); + FT_TRACE4(( "style coverage\n" )); + FT_TRACE4(( "==============\n" )); + FT_TRACE4(( "\n" )); for ( ss = 0; af_style_classes[ss]; ss++ ) { AF_StyleClass style_class = af_style_classes[ss]; FT_UInt count = 0; - FT_Long idx; + FT_UInt idx; FT_TRACE4(( "%s:\n", af_style_names[style_class->style] )); @@ -306,7 +301,7 @@ if ( !( count % 10 ) ) FT_TRACE4(( " " )); - FT_TRACE4(( " %ld", idx )); + FT_TRACE4(( " %d", idx )); count++; if ( !( count % 10 ) ) @@ -322,7 +317,7 @@ #endif /* FT_DEBUG_LEVEL_TRACE */ - FT_Set_Charmap( face, old_charmap ); + face->charmap = old_charmap; return error; } @@ -341,13 +336,15 @@ /* we allocate an AF_FaceGlobals structure together */ /* with the glyph_styles array */ - if ( FT_ALLOC( globals, - sizeof ( *globals ) + - (FT_ULong)face->num_glyphs * sizeof ( FT_UShort ) ) ) + if ( FT_QALLOC( globals, + sizeof ( *globals ) + + (FT_ULong)face->num_glyphs * sizeof ( FT_UShort ) ) ) goto Exit; + FT_ZERO( &globals->metrics ); + globals->face = face; - globals->glyph_count = face->num_glyphs; + globals->glyph_count = (FT_UInt)face->num_glyphs; /* right after the globals structure come the glyph styles */ globals->glyph_styles = (FT_UShort*)( globals + 1 ); globals->module = module; @@ -359,7 +356,7 @@ globals->scale_down_factor = 0; #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - globals->hb_font = hb_ft_font_create( face, NULL ); + globals->hb_font = hb_ft_font_create_( face, NULL ); globals->hb_buf = hb_buffer_create(); #endif @@ -379,8 +376,11 @@ FT_LOCAL_DEF( void ) - af_face_globals_free( AF_FaceGlobals globals ) + af_face_globals_free( void* globals_ ) { + AF_FaceGlobals globals = (AF_FaceGlobals)globals_; + + if ( globals ) { FT_Memory memory = globals->face->memory; @@ -431,7 +431,7 @@ FT_Error error = FT_Err_Ok; - if ( gindex >= (FT_ULong)globals->glyph_count ) + if ( gindex >= globals->glyph_count ) { error = FT_THROW( Invalid_Argument ); goto Exit; @@ -478,6 +478,10 @@ { style = (AF_Style)( globals->glyph_styles[gindex] & AF_STYLE_UNASSIGNED ); + /* IMPORTANT: Clear the error code, see + * https://gitlab.freedesktop.org/freetype/freetype/-/issues/1063 + */ + error = FT_Err_Ok; goto Again; } @@ -499,7 +503,7 @@ af_face_globals_is_digit( AF_FaceGlobals globals, FT_UInt gindex ) { - if ( gindex < (FT_ULong)globals->glyph_count ) + if ( gindex < globals->glyph_count ) return FT_BOOL( globals->glyph_styles[gindex] & AF_DIGIT ); return FT_BOOL( 0 ); diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afglobal.h b/lib/libesp32_lvgl/freetype/src/autofit/afglobal.h index fecf7af97..66170e419 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afglobal.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/afglobal.h @@ -5,7 +5,7 @@ * Auto-fitter routines to compute global hinting values * (specification). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -105,7 +105,7 @@ FT_BEGIN_HEADER typedef struct AF_FaceGlobalsRec_ { FT_Face face; - FT_Long glyph_count; /* same as face->num_glyphs */ + FT_UInt glyph_count; /* unsigned face->num_glyphs */ FT_UShort* glyph_styles; #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ @@ -156,9 +156,9 @@ FT_BEGIN_HEADER AF_StyleMetrics *ametrics ); FT_LOCAL( void ) - af_face_globals_free( AF_FaceGlobals globals ); + af_face_globals_free( void* globals ); - FT_LOCAL_DEF( FT_Bool ) + FT_LOCAL( FT_Bool ) af_face_globals_is_digit( AF_FaceGlobals globals, FT_UInt gindex ); diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afhints.c b/lib/libesp32_lvgl/freetype/src/autofit/afhints.c index a8e00890e..e4a378fbf 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afhints.c +++ b/lib/libesp32_lvgl/freetype/src/autofit/afhints.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines (body). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -32,6 +32,104 @@ #define FT_COMPONENT afhints + FT_LOCAL_DEF( void ) + af_sort_pos( FT_UInt count, + FT_Pos* table ) + { + FT_UInt i, j; + FT_Pos swap; + + + for ( i = 1; i < count; i++ ) + { + for ( j = i; j > 0; j-- ) + { + if ( table[j] >= table[j - 1] ) + break; + + swap = table[j]; + table[j] = table[j - 1]; + table[j - 1] = swap; + } + } + } + + + FT_LOCAL_DEF( void ) + af_sort_and_quantize_widths( FT_UInt* count, + AF_Width table, + FT_Pos threshold ) + { + FT_UInt i, j; + FT_UInt cur_idx; + FT_Pos cur_val; + FT_Pos sum; + AF_WidthRec swap; + + + if ( *count == 1 ) + return; + + /* sort */ + for ( i = 1; i < *count; i++ ) + { + for ( j = i; j > 0; j-- ) + { + if ( table[j].org >= table[j - 1].org ) + break; + + swap = table[j]; + table[j] = table[j - 1]; + table[j - 1] = swap; + } + } + + cur_idx = 0; + cur_val = table[cur_idx].org; + + /* compute and use mean values for clusters not larger than */ + /* `threshold'; this is very primitive and might not yield */ + /* the best result, but normally, using reference character */ + /* `o', `*count' is 2, so the code below is fully sufficient */ + for ( i = 1; i < *count; i++ ) + { + if ( table[i].org - cur_val > threshold || + i == *count - 1 ) + { + sum = 0; + + /* fix loop for end of array */ + if ( table[i].org - cur_val <= threshold && + i == *count - 1 ) + i++; + + for ( j = cur_idx; j < i; j++ ) + { + sum += table[j].org; + table[j].org = 0; + } + table[cur_idx].org = sum / (FT_Pos)j; + + if ( i < *count - 1 ) + { + cur_idx = i + 1; + cur_val = table[cur_idx].org; + } + } + } + + cur_idx = 1; + + /* compress array to remove zero values */ + for ( i = 1; i < *count; i++ ) + { + if ( table[i].org ) + table[cur_idx++] = table[i]; + } + + *count = cur_idx; + } + /* Get new segment for given axis. */ FT_LOCAL_DEF( FT_Error ) @@ -53,9 +151,9 @@ } else if ( axis->num_segments >= axis->max_segments ) { - FT_Int old_max = axis->max_segments; - FT_Int new_max = old_max; - FT_Int big_max = (FT_Int)( FT_INT_MAX / sizeof ( *segment ) ); + FT_UInt old_max = axis->max_segments; + FT_UInt new_max = old_max; + FT_UInt big_max = FT_INT_MAX / sizeof ( *segment ); if ( old_max >= big_max ) @@ -95,7 +193,7 @@ /* Get new edge for given axis, direction, and position, */ /* without initializing the edge itself. */ - FT_LOCAL( FT_Error ) + FT_LOCAL_DEF( FT_Error ) af_axis_hints_new_edge( AF_AxisHints axis, FT_Int fpos, AF_Direction dir, @@ -118,9 +216,9 @@ } else if ( axis->num_edges >= axis->max_edges ) { - FT_Int old_max = axis->max_edges; - FT_Int new_max = old_max; - FT_Int big_max = (FT_Int)( FT_INT_MAX / sizeof ( *edge ) ); + FT_UInt old_max = axis->max_edges; + FT_UInt new_max = old_max; + FT_UInt big_max = FT_INT_MAX / sizeof ( *edge ); if ( old_max >= big_max ) @@ -222,8 +320,9 @@ static char* - af_print_idx( char* p, - int idx ) + af_print_idx( char* p, + size_t n, + int idx ) { if ( idx == -1 ) { @@ -232,7 +331,7 @@ p[2] = '\0'; } else - ft_sprintf( p, "%d", idx ); + ft_snprintf( p, n, "%d", idx ); return p; } @@ -359,12 +458,12 @@ " %5d %5d %7.2f %7.2f %7.2f %7.2f" " %5s %5s %5s %5s\n", point_idx, - af_print_idx( buf1, + af_print_idx( buf1, 16, af_get_edge_index( hints, segment_idx_1, 1 ) ), - af_print_idx( buf2, segment_idx_1 ), - af_print_idx( buf3, + af_print_idx( buf2, 16, segment_idx_1 ), + af_print_idx( buf3, 16, af_get_edge_index( hints, segment_idx_0, 0 ) ), - af_print_idx( buf4, segment_idx_0 ), + af_print_idx( buf4, 16, segment_idx_0 ), ( point->flags & AF_FLAG_NEAR ) ? " near " : ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) @@ -373,23 +472,27 @@ point->fx, point->fy, - point->ox / 64.0, - point->oy / 64.0, - point->x / 64.0, - point->y / 64.0, + (double)point->ox / 64, + (double)point->oy / 64, + (double)point->x / 64, + (double)point->y / 64, - af_print_idx( buf5, af_get_strong_edge_index( hints, - point->before, - 1 ) ), - af_print_idx( buf6, af_get_strong_edge_index( hints, - point->after, - 1 ) ), - af_print_idx( buf7, af_get_strong_edge_index( hints, - point->before, - 0 ) ), - af_print_idx( buf8, af_get_strong_edge_index( hints, - point->after, - 0 ) ) )); + af_print_idx( buf5, 16, + af_get_strong_edge_index( hints, + point->before, + 1 ) ), + af_print_idx( buf6, 16, + af_get_strong_edge_index( hints, + point->after, + 1 ) ), + af_print_idx( buf7, 16, + af_get_strong_edge_index( hints, + point->before, + 0 ) ), + af_print_idx( buf8, 16, + af_get_strong_edge_index( hints, + point->after, + 0 ) ) )); } AF_DUMP(( "\n" )); } @@ -476,9 +579,12 @@ AF_INDEX_NUM( seg->first, points ), AF_INDEX_NUM( seg->last, points ), - af_print_idx( buf1, AF_INDEX_NUM( seg->link, segments ) ), - af_print_idx( buf2, AF_INDEX_NUM( seg->serif, segments ) ), - af_print_idx( buf3, AF_INDEX_NUM( seg->edge, edges ) ), + af_print_idx( buf1, 16, + AF_INDEX_NUM( seg->link, segments ) ), + af_print_idx( buf2, 16, + AF_INDEX_NUM( seg->serif, segments ) ), + af_print_idx( buf3, 16, + AF_INDEX_NUM( seg->edge, edges ) ), seg->height, seg->height - ( seg->max_coord - seg->min_coord ), @@ -499,7 +605,7 @@ FT_Error af_glyph_hints_get_num_segments( AF_GlyphHints hints, FT_Int dimension, - FT_Int* num_segments ) + FT_UInt* num_segments ) { AF_Dimension dim; AF_AxisHints axis; @@ -525,7 +631,7 @@ FT_Error af_glyph_hints_get_segment_offset( AF_GlyphHints hints, FT_Int dimension, - FT_Int idx, + FT_UInt idx, FT_Pos *offset, FT_Bool *is_blue, FT_Pos *blue_offset ) @@ -542,7 +648,7 @@ axis = &hints->axis[dim]; - if ( idx < 0 || idx >= axis->num_segments ) + if ( idx >= axis->num_segments ) return FT_THROW( Invalid_Argument ); seg = &axis->segments[idx]; @@ -594,13 +700,13 @@ if ( dimension == AF_DIMENSION_HORZ ) AF_DUMP(( "Table of %s edges (1px=%.2fu, 10u=%.2fpx):\n", "vertical", - 65536.0 * 64.0 / hints->x_scale, - 10.0 * hints->x_scale / 65536.0 / 64.0 )); + 65536 * 64 / (double)hints->x_scale, + 10 * (double)hints->x_scale / 65536 / 64 )); else AF_DUMP(( "Table of %s edges (1px=%.2fu, 10u=%.2fpx):\n", "horizontal", - 65536.0 * 64.0 / hints->y_scale, - 10.0 * hints->y_scale / 65536.0 / 64.0 )); + 65536 * 64 / (double)hints->y_scale, + 10 * (double)hints->y_scale / 65536 / 64 )); if ( axis->num_edges ) { @@ -616,14 +722,16 @@ AF_DUMP(( " %5d %7.2f %5s %4s %5s" " %c %7.2f %7.2f %11s\n", AF_INDEX_NUM( edge, edges ), - (int)edge->opos / 64.0, + (double)(int)edge->opos / 64, af_dir_str( (AF_Direction)edge->dir ), - af_print_idx( buf1, AF_INDEX_NUM( edge->link, edges ) ), - af_print_idx( buf2, AF_INDEX_NUM( edge->serif, edges ) ), + af_print_idx( buf1, 16, + AF_INDEX_NUM( edge->link, edges ) ), + af_print_idx( buf2, 16, + AF_INDEX_NUM( edge->serif, edges ) ), edge->blue_edge ? 'y' : 'n', - edge->opos / 64.0, - edge->pos / 64.0, + (double)edge->opos / 64, + (double)edge->pos / 64, af_edge_flags_to_string( edge->flags ) )); AF_DUMP(( "\n" )); } @@ -764,7 +872,7 @@ { FT_Error error = FT_Err_Ok; AF_Point points; - FT_UInt old_max, new_max; + FT_Int old_max, new_max; FT_Fixed x_scale = hints->x_scale; FT_Fixed y_scale = hints->y_scale; FT_Pos x_delta = hints->x_delta; @@ -781,8 +889,8 @@ hints->axis[1].num_edges = 0; /* first of all, reallocate the contours array if necessary */ - new_max = (FT_UInt)outline->n_contours; - old_max = (FT_UInt)hints->max_contours; + new_max = outline->n_contours; + old_max = hints->max_contours; if ( new_max <= AF_CONTOURS_EMBEDDED ) { @@ -797,12 +905,12 @@ if ( hints->contours == hints->embedded.contours ) hints->contours = NULL; - new_max = ( new_max + 3 ) & ~3U; /* round up to a multiple of 4 */ + new_max = ( new_max + 3 ) & ~3; /* round up to a multiple of 4 */ if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) ) goto Exit; - hints->max_contours = (FT_Int)new_max; + hints->max_contours = new_max; } /* @@ -810,8 +918,8 @@ * note that we reserve two additional point positions, used to * hint metrics appropriately */ - new_max = (FT_UInt)( outline->n_points + 2 ); - old_max = (FT_UInt)hints->max_points; + new_max = outline->n_points + 2; + old_max = hints->max_points; if ( new_max <= AF_POINTS_EMBEDDED ) { @@ -826,12 +934,12 @@ if ( hints->points == hints->embedded.points ) hints->points = NULL; - new_max = ( new_max + 2 + 7 ) & ~7U; /* round up to a multiple of 8 */ + new_max = ( new_max + 2 + 7 ) & ~7; /* round up to a multiple of 8 */ if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) ) goto Exit; - hints->max_points = (FT_Int)new_max; + hints->max_points = new_max; } hints->num_points = outline->n_points; @@ -855,9 +963,6 @@ hints->x_delta = x_delta; hints->y_delta = y_delta; - hints->xmin_delta = 0; - hints->xmax_delta = 0; - points = hints->points; if ( hints->num_points == 0 ) goto Exit; @@ -1221,7 +1326,7 @@ { AF_AxisHints axis = & hints->axis[dim]; AF_Segment segments = axis->segments; - AF_Segment segment_limit = segments + axis->num_segments; + AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments ); AF_Segment seg; @@ -1298,7 +1403,7 @@ AF_Point point_limit = points + hints->num_points; AF_AxisHints axis = &hints->axis[dim]; AF_Edge edges = axis->edges; - AF_Edge edge_limit = edges + axis->num_edges; + AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges ); FT_UInt touch_flag; @@ -1688,33 +1793,4 @@ } -#ifdef AF_CONFIG_OPTION_USE_WARPER - - /* Apply (small) warp scale and warp delta for given dimension. */ - - FT_LOCAL_DEF( void ) - af_glyph_hints_scale_dim( AF_GlyphHints hints, - AF_Dimension dim, - FT_Fixed scale, - FT_Pos delta ) - { - AF_Point points = hints->points; - AF_Point points_limit = points + hints->num_points; - AF_Point point; - - - if ( dim == AF_DIMENSION_HORZ ) - { - for ( point = points; point < points_limit; point++ ) - point->x = FT_MulFix( point->fx, scale ) + delta; - } - else - { - for ( point = points; point < points_limit; point++ ) - point->y = FT_MulFix( point->fy, scale ) + delta; - } - } - -#endif /* AF_CONFIG_OPTION_USE_WARPER */ - /* END */ diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afhints.h b/lib/libesp32_lvgl/freetype/src/autofit/afhints.h index 6397f098f..d1cf9529b 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afhints.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/afhints.h @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines (specification). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -21,8 +21,6 @@ #include "aftypes.h" -#define xxAF_SORT_SEGMENTS - FT_BEGIN_HEADER /* @@ -310,15 +308,12 @@ FT_BEGIN_HEADER typedef struct AF_AxisHintsRec_ { - FT_Int num_segments; /* number of used segments */ - FT_Int max_segments; /* number of allocated segments */ + FT_UInt num_segments; /* number of used segments */ + FT_UInt max_segments; /* number of allocated segments */ AF_Segment segments; /* segments array */ -#ifdef AF_SORT_SEGMENTS - FT_Int mid_segments; -#endif - FT_Int num_edges; /* number of used edges */ - FT_Int max_edges; /* number of allocated edges */ + FT_UInt num_edges; /* number of used edges */ + FT_UInt max_edges; /* number of allocated edges */ AF_Edge edges; /* edges array */ AF_Direction major_dir; /* either vertical or horizontal */ @@ -362,9 +357,6 @@ FT_BEGIN_HEADER /* implementations */ AF_StyleMetrics metrics; - FT_Pos xmin_delta; /* used for warping */ - FT_Pos xmax_delta; - /* Two arrays to avoid allocation penalty. */ /* The `embedded' structure must be the last element! */ struct @@ -383,14 +375,14 @@ FT_BEGIN_HEADER #ifdef FT_DEBUG_AUTOFIT #define AF_HINTS_DO_HORIZONTAL( h ) \ - ( !_af_debug_disable_horz_hints && \ + ( !af_debug_disable_horz_hints_ && \ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_HORIZONTAL ) ) #define AF_HINTS_DO_VERTICAL( h ) \ - ( !_af_debug_disable_vert_hints && \ + ( !af_debug_disable_vert_hints_ && \ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL ) ) -#define AF_HINTS_DO_BLUES( h ) ( !_af_debug_disable_blue_hints ) +#define AF_HINTS_DO_BLUES( h ) ( !af_debug_disable_blue_hints_ ) #else /* !FT_DEBUG_AUTOFIT */ @@ -408,10 +400,6 @@ FT_BEGIN_HEADER #define AF_HINTS_DO_ADVANCE( h ) \ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE ) -#define AF_HINTS_DO_WARP( h ) \ - !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_WARPER ) - - FT_LOCAL( AF_Direction ) af_direction_compute( FT_Pos dx, @@ -459,14 +447,6 @@ FT_BEGIN_HEADER af_glyph_hints_align_weak_points( AF_GlyphHints hints, AF_Dimension dim ); -#ifdef AF_CONFIG_OPTION_USE_WARPER - FT_LOCAL( void ) - af_glyph_hints_scale_dim( AF_GlyphHints hints, - AF_Dimension dim, - FT_Fixed scale, - FT_Pos delta ); -#endif - FT_LOCAL( void ) af_glyph_hints_done( AF_GlyphHints hints ); diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afindic.c b/lib/libesp32_lvgl/freetype/src/autofit/afindic.c index bc2837a26..7fb12c63d 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afindic.c +++ b/lib/libesp32_lvgl/freetype/src/autofit/afindic.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for Indic writing system (body). * - * Copyright (C) 2007-2020 by + * Copyright (C) 2007-2023 by * Rahul Bhalerao , . * * This file is part of the FreeType project, and may only be used, @@ -27,15 +27,13 @@ #include "aferrors.h" -#ifdef AF_CONFIG_OPTION_USE_WARPER -#include "afwarp.h" -#endif - - static FT_Error - af_indic_metrics_init( AF_CJKMetrics metrics, - FT_Face face ) + af_indic_metrics_init( AF_StyleMetrics metrics_, /* AF_CJKMetrics */ + FT_Face face ) { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + + /* skip blue zone init in CJK routines */ FT_CharMap oldmap = face->charmap; @@ -54,15 +52,14 @@ af_cjk_metrics_check_digits( metrics, face ); } - FT_Set_Charmap( face, oldmap ); - + face->charmap = oldmap; return FT_Err_Ok; } static void - af_indic_metrics_scale( AF_CJKMetrics metrics, - AF_Scaler scaler ) + af_indic_metrics_scale( AF_StyleMetrics metrics, + AF_Scaler scaler ) { /* use CJK routines */ af_cjk_metrics_scale( metrics, scaler ); @@ -70,8 +67,8 @@ static FT_Error - af_indic_hints_init( AF_GlyphHints hints, - AF_CJKMetrics metrics ) + af_indic_hints_init( AF_GlyphHints hints, + AF_StyleMetrics metrics ) { /* use CJK routines */ return af_cjk_hints_init( hints, metrics ); @@ -79,10 +76,10 @@ static FT_Error - af_indic_hints_apply( FT_UInt glyph_index, - AF_GlyphHints hints, - FT_Outline* outline, - AF_CJKMetrics metrics ) + af_indic_hints_apply( FT_UInt glyph_index, + AF_GlyphHints hints, + FT_Outline* outline, + AF_StyleMetrics metrics ) { /* use CJK routines */ return af_cjk_hints_apply( glyph_index, hints, outline, metrics ); @@ -93,10 +90,13 @@ /* metrics class. */ static void - af_indic_get_standard_widths( AF_CJKMetrics metrics, - FT_Pos* stdHW, - FT_Pos* stdVW ) + af_indic_get_standard_widths( AF_StyleMetrics metrics_, /* AF_CJKMetrics */ + FT_Pos* stdHW, + FT_Pos* stdVW ) { + AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_; + + if ( stdHW ) *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width; diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afindic.h b/lib/libesp32_lvgl/freetype/src/autofit/afindic.h index 088b88b19..3eb67f63b 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afindic.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/afindic.h @@ -5,7 +5,7 @@ * Auto-fitter hinting routines for Indic writing system * (specification). * - * Copyright (C) 2007-2020 by + * Copyright (C) 2007-2023 by * Rahul Bhalerao , . * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/autofit/aflatin.c b/lib/libesp32_lvgl/freetype/src/autofit/aflatin.c index 21ec02ebd..b86367aa9 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/aflatin.c +++ b/lib/libesp32_lvgl/freetype/src/autofit/aflatin.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for latin writing system (body). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -24,11 +24,6 @@ #include "aferrors.h" -#ifdef AF_CONFIG_OPTION_USE_WARPER -#include "afwarp.h" -#endif - - /************************************************************************** * * The macro FT_COMPONENT is used in trace mode. It is an implicit @@ -63,11 +58,11 @@ AF_GlyphHintsRec hints[1]; - FT_TRACE5(( "\n" - "latin standard widths computation (style `%s')\n" - "=====================================================\n" - "\n", + FT_TRACE5(( "\n" )); + FT_TRACE5(( "latin standard widths computation (style `%s')\n", af_style_names[metrics->root.style_class->style] )); + FT_TRACE5(( "=====================================================\n" )); + FT_TRACE5(( "\n" )); af_glyph_hints_init( hints, face->memory ); @@ -205,7 +200,7 @@ (AF_Dimension)dim ); seg = axhints->segments; - limit = seg + axhints->num_segments; + limit = FT_OFFSET( seg, axhints->num_segments ); for ( ; seg < limit; seg++ ) { @@ -350,9 +345,9 @@ /* we walk over the blue character strings as specified in the */ /* style's entry in the `af_blue_stringset' array */ - FT_TRACE5(( "latin blue zones computation\n" - "============================\n" - "\n" )); + FT_TRACE5(( "latin blue zones computation\n" )); + FT_TRACE5(( "============================\n" )); + FT_TRACE5(( "\n" )); #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ shaper_buf = af_shaper_buf_create( face ); @@ -501,23 +496,20 @@ /* now compute min or max point indices and coordinates */ points = outline.points; best_point = -1; + best_contour_first = -1; + best_contour_last = -1; best_y = 0; /* make compiler happy */ - best_contour_first = 0; /* ditto */ - best_contour_last = 0; /* ditto */ { FT_Int nn; - FT_Int first = 0; - FT_Int last = -1; + FT_Int pp, first, last; - for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ ) + last = -1; + for ( nn = 0; nn < outline.n_contours; nn++ ) { - FT_Int old_best_point = best_point; - FT_Int pp; - - - last = outline.contours[nn]; + first = last + 1; + last = outline.contours[nn]; /* Avoid single-point contours since they are never */ /* rasterized. In some fonts, they correspond to mark */ @@ -556,7 +548,7 @@ } } - if ( best_point != old_best_point ) + if ( best_point > best_contour_last ) { best_contour_first = first; best_contour_last = last; @@ -976,9 +968,8 @@ if ( AF_LATIN_IS_X_HEIGHT_BLUE( bs ) ) blue->flags |= AF_LATIN_BLUE_ADJUSTMENT; - FT_TRACE5(( " -> reference = %ld\n" - " overshoot = %ld\n", - *blue_ref, *blue_shoot )); + FT_TRACE5(( " -> reference = %ld\n", *blue_ref )); + FT_TRACE5(( " overshoot = %ld\n", *blue_shoot )); } /* end for loop */ @@ -1031,7 +1022,7 @@ { *a = *b; FT_TRACE5(( "blue zone overlap:" - " adjusting %s %ld to %ld\n", + " adjusting %s %td to %ld\n", a_is_top ? "overshoot" : "reference", blue_sorted[i] - axis->blues, *a )); @@ -1049,7 +1040,7 @@ AF_FaceGlobals globals = metrics->root.globals; FT_UShort* gstyles = globals->glyph_styles; - FT_Long i; + FT_UInt i; FT_TRACE5(( "no blue zones found:" @@ -1074,8 +1065,8 @@ af_latin_metrics_check_digits( AF_LatinMetrics metrics, FT_Face face ) { - FT_Bool started = 0, same_width = 1; - FT_Fixed advance = 0, old_advance = 0; + FT_Bool started = 0, same_width = 1; + FT_Long advance = 0, old_advance = 0; /* If HarfBuzz is not available, we need a pointer to a single */ /* unsigned long value. */ @@ -1140,9 +1131,11 @@ /* Initialize global metrics. */ FT_LOCAL_DEF( FT_Error ) - af_latin_metrics_init( AF_LatinMetrics metrics, + af_latin_metrics_init( AF_StyleMetrics metrics_, /* AF_LatinMetrics */ FT_Face face ) { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + FT_Error error = FT_Err_Ok; FT_CharMap oldmap = face->charmap; @@ -1163,7 +1156,7 @@ } Exit: - FT_Set_Charmap( face, oldmap ); + face->charmap = oldmap; return error; } @@ -1275,29 +1268,28 @@ if ( dist == 0 ) { - FT_TRACE5(( - "af_latin_metrics_scale_dim:" - " x height alignment (style `%s'):\n" - " " - " vertical scaling changed from %.5f to %.5f (by %ld%%)\n" - "\n", - af_style_names[metrics->root.style_class->style], - scale / 65536.0, - new_scale / 65536.0, - ( fitted - scaled ) * 100 / scaled )); + FT_TRACE5(( "af_latin_metrics_scale_dim:" + " x height alignment (style `%s'):\n", + af_style_names[metrics->root.style_class->style] )); + FT_TRACE5(( " " + " vertical scaling changed" + " from %.5f to %.5f (by %ld%%)\n", + (double)scale / 65536, + (double)new_scale / 65536, + ( fitted - scaled ) * 100 / scaled )); + FT_TRACE5(( "\n" )); scale = new_scale; } #ifdef FT_DEBUG_LEVEL_TRACE else { - FT_TRACE5(( - "af_latin_metrics_scale_dim:" - " x height alignment (style `%s'):\n" - " " - " excessive vertical scaling abandoned\n" - "\n", - af_style_names[metrics->root.style_class->style] )); + FT_TRACE5(( "af_latin_metrics_scale_dim:" + " x height alignment (style `%s'):\n", + af_style_names[metrics->root.style_class->style] )); + FT_TRACE5(( " " + " excessive vertical scaling abandoned\n" )); + FT_TRACE5(( "\n" )); } #endif } @@ -1334,7 +1326,7 @@ FT_TRACE5(( " %ld scaled to %.2f\n", width->org, - width->cur / 64.0 )); + (double)width->cur / 64 )); } FT_TRACE5(( "\n" )); @@ -1346,9 +1338,11 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( axis->extra_light ) - FT_TRACE5(( "`%s' style is extra light (at current resolution)\n" - "\n", + { + FT_TRACE5(( "`%s' style is extra light (at current resolution)\n", af_style_names[metrics->root.style_class->style] )); + FT_TRACE5(( "\n" )); + } #endif if ( dim == AF_DIMENSION_VERT ) @@ -1473,16 +1467,16 @@ AF_LatinBlue blue = &axis->blues[nn]; - FT_TRACE5(( " reference %d: %ld scaled to %.2f%s\n" - " overshoot %d: %ld scaled to %.2f%s\n", + FT_TRACE5(( " reference %d: %ld scaled to %.2f%s\n", nn, blue->ref.org, - blue->ref.fit / 64.0, + (double)blue->ref.fit / 64, ( blue->flags & AF_LATIN_BLUE_ACTIVE ) ? "" - : " (inactive)", + : " (inactive)" )); + FT_TRACE5(( " overshoot %d: %ld scaled to %.2f%s\n", nn, blue->shoot.org, - blue->shoot.fit / 64.0, + (double)blue->shoot.fit / 64, ( blue->flags & AF_LATIN_BLUE_ACTIVE ) ? "" : " (inactive)" )); } @@ -1494,9 +1488,12 @@ /* Scale global values in both directions. */ FT_LOCAL_DEF( void ) - af_latin_metrics_scale( AF_LatinMetrics metrics, + af_latin_metrics_scale( AF_StyleMetrics metrics_, /* AF_LatinMetrics */ AF_Scaler scaler ) { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + + metrics->root.scaler.render_mode = scaler->render_mode; metrics->root.scaler.face = scaler->face; metrics->root.scaler.flags = scaler->flags; @@ -1509,11 +1506,14 @@ /* Extract standard_width from writing system/script specific */ /* metrics class. */ - FT_LOCAL_DEF( void ) - af_latin_get_standard_widths( AF_LatinMetrics metrics, + FT_CALLBACK_DEF( void ) + af_latin_get_standard_widths( AF_StyleMetrics metrics_, /* AF_LatinMetrics */ FT_Pos* stdHW, FT_Pos* stdVW ) { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + + if ( stdHW ) *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width; @@ -1847,6 +1847,31 @@ ( FT_ABS( point->out_dir ) == major_dir || point == point->prev ) ) { + /* + * For efficiency, we restrict the number of segments to 1000, + * which is a heuristic value: it is very unlikely that a glyph + * with so many segments can be hinted in a sensible way. + * Reasons: + * + * - The glyph has really 1000 segments; this implies that it has + * at least 2000 outline points. Assuming 'normal' fonts that + * have superfluous points optimized away, viewing such a glyph + * only makes sense at large magnifications where hinting + * isn't applied anyway. + * + * - We have a broken glyph. Hinting doesn't make sense in this + * case either. + */ + if ( axis->num_segments > 1000 ) + { + FT_TRACE0(( "af_latin_hints_compute_segments:" + " more than 1000 segments in this glyph;\n" )); + FT_TRACE0(( " " + " hinting is suppressed\n" )); + axis->num_segments = 0; + return FT_Err_Ok; + } + /* this is the start of a new segment! */ segment_dir = (AF_Direction)point->out_dir; @@ -1969,7 +1994,7 @@ { AF_AxisHints axis = &hints->axis[dim]; AF_Segment segments = axis->segments; - AF_Segment segment_limit = segments + axis->num_segments; + AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments ); FT_Pos len_threshold, len_score, dist_score, max_width; AF_Segment seg1, seg2; @@ -2021,7 +2046,7 @@ max = seg2->max_coord; /* compute maximum coordinate difference of the two segments */ - /* (this is, how much they overlap) */ + /* (that is, how much they overlap) */ len = max - min; if ( len >= len_threshold ) { @@ -2089,7 +2114,7 @@ { if ( seg2->link != seg1 ) { - seg1->link = 0; + seg1->link = NULL; seg1->serif = seg2->link; } } @@ -2114,7 +2139,7 @@ FT_Bool top_to_bottom_hinting = 0; AF_Segment segments = axis->segments; - AF_Segment segment_limit = segments + axis->num_segments; + AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments ); AF_Segment seg; #if 0 @@ -2183,7 +2208,7 @@ for ( seg = segments; seg < segment_limit; seg++ ) { AF_Edge found = NULL; - FT_Int ee; + FT_UInt ee; /* ignore too short segments, too wide ones, and, in this loop, */ @@ -2257,7 +2282,7 @@ for ( seg = segments; seg < segment_limit; seg++ ) { AF_Edge found = NULL; - FT_Int ee; + FT_UInt ee; if ( seg->dir != AF_DIR_NONE ) @@ -2480,7 +2505,7 @@ { AF_AxisHints axis = &hints->axis[AF_DIMENSION_VERT]; AF_Edge edge = axis->edges; - AF_Edge edge_limit = edge + axis->num_edges; + AF_Edge edge_limit = FT_OFFSET( edge, axis->num_edges ); AF_LatinAxis latin = &metrics->axis[AF_DIMENSION_VERT]; FT_Fixed scale = latin->scale; @@ -2590,8 +2615,10 @@ static FT_Error af_latin_hints_init( AF_GlyphHints hints, - AF_LatinMetrics metrics ) + AF_StyleMetrics metrics_ ) /* AF_LatinMetrics */ { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + FT_Render_Mode mode; FT_UInt32 scaler_flags, other_flags; FT_Face face = metrics->root.scaler.face; @@ -2611,11 +2638,6 @@ /* compute flags depending on render mode, etc. */ mode = metrics->root.scaler.render_mode; -#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */ - if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V ) - metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL; -#endif - scaler_flags = hints->scaler_flags; other_flags = 0; @@ -2653,12 +2675,6 @@ ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 ) scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL; -#ifdef AF_CONFIG_OPTION_USE_WARPER - /* get (global) warper flag */ - if ( !metrics->root.globals->module->warping ) - scaler_flags |= AF_SCALER_FLAG_NO_WARPER; -#endif - hints->scaler_flags = scaler_flags; hints->other_flags = other_flags; @@ -2944,10 +2960,11 @@ stem_edge->pos = base_edge->pos + fitted_width; - FT_TRACE5(( " LINK: edge %ld (opos=%.2f) linked to %.2f," + FT_TRACE5(( " LINK: edge %td (opos=%.2f) linked to %.2f," " dist was %.2f, now %.2f\n", - stem_edge - hints->axis[dim].edges, stem_edge->opos / 64.0, - stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 )); + stem_edge - hints->axis[dim].edges, + (double)stem_edge->opos / 64, (double)stem_edge->pos / 64, + (double)dist / 64, (double)fitted_width / 64 )); } @@ -2984,7 +3001,7 @@ { AF_AxisHints axis = &hints->axis[dim]; AF_Edge edges = axis->edges; - AF_Edge edge_limit = edges + axis->num_edges; + AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges ); FT_PtrDist n_edges; AF_Edge edge; AF_Edge anchor = NULL; @@ -3068,15 +3085,17 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( !anchor ) - FT_TRACE5(( " BLUE_ANCHOR: edge %ld (opos=%.2f) snapped to %.2f," - " was %.2f (anchor=edge %ld)\n", - edge1 - edges, edge1->opos / 64.0, blue->fit / 64.0, - edge1->pos / 64.0, edge - edges )); + FT_TRACE5(( " BLUE_ANCHOR: edge %td (opos=%.2f) snapped to %.2f," + " was %.2f (anchor=edge %td)\n", + edge1 - edges, + (double)edge1->opos / 64, (double)blue->fit / 64, + (double)edge1->pos / 64, edge - edges )); else - FT_TRACE5(( " BLUE: edge %ld (opos=%.2f) snapped to %.2f," + FT_TRACE5(( " BLUE: edge %td (opos=%.2f) snapped to %.2f," " was %.2f\n", - edge1 - edges, edge1->opos / 64.0, blue->fit / 64.0, - edge1->pos / 64.0 )); + edge1 - edges, + (double)edge1->opos / 64, (double)blue->fit / 64, + (double)edge1->pos / 64 )); num_actions++; #endif @@ -3122,7 +3141,7 @@ /* this should not happen, but it's better to be safe */ if ( edge2->blue_edge ) { - FT_TRACE5(( " ASSERTION FAILED for edge %ld\n", edge2 - edges )); + FT_TRACE5(( " ASSERTION FAILED for edge %td\n", edge2 - edges )); af_latin_align_linked_edge( hints, dim, edge2, edge ); edge->flags |= AF_EDGE_DONE; @@ -3190,11 +3209,11 @@ anchor = edge; edge->flags |= AF_EDGE_DONE; - FT_TRACE5(( " ANCHOR: edge %ld (opos=%.2f) and %ld (opos=%.2f)" + FT_TRACE5(( " ANCHOR: edge %td (opos=%.2f) and %td (opos=%.2f)" " snapped to %.2f and %.2f\n", - edge - edges, edge->opos / 64.0, - edge2 - edges, edge2->opos / 64.0, - edge->pos / 64.0, edge2->pos / 64.0 )); + edge - edges, (double)edge->opos / 64, + edge2 - edges, (double)edge2->opos / 64, + (double)edge->pos / 64, (double)edge2->pos / 64 )); af_latin_align_linked_edge( hints, dim, edge, edge2 ); @@ -3219,9 +3238,9 @@ if ( edge2->flags & AF_EDGE_DONE ) { - FT_TRACE5(( " ADJUST: edge %ld (pos=%.2f) moved to %.2f\n", - edge - edges, edge->pos / 64.0, - ( edge2->pos - cur_len ) / 64.0 )); + FT_TRACE5(( " ADJUST: edge %td (pos=%.2f) moved to %.2f\n", + edge - edges, (double)edge->pos / 64, + (double)( edge2->pos - cur_len ) / 64 )); edge->pos = edge2->pos - cur_len; } @@ -3260,11 +3279,11 @@ edge->pos = cur_pos1 - cur_len / 2; edge2->pos = cur_pos1 + cur_len / 2; - FT_TRACE5(( " STEM: edge %ld (opos=%.2f) linked to %ld (opos=%.2f)" + FT_TRACE5(( " STEM: edge %td (opos=%.2f) linked to %td (opos=%.2f)" " snapped to %.2f and %.2f\n", - edge - edges, edge->opos / 64.0, - edge2 - edges, edge2->opos / 64.0, - edge->pos / 64.0, edge2->pos / 64.0 )); + edge - edges, (double)edge->opos / 64, + edge2 - edges, (double)edge2->opos / 64, + (double)edge->pos / 64, (double)edge2->pos / 64 )); } else @@ -3291,11 +3310,11 @@ edge->pos = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2; edge2->pos = edge->pos + cur_len; - FT_TRACE5(( " STEM: edge %ld (opos=%.2f) linked to %ld (opos=%.2f)" + FT_TRACE5(( " STEM: edge %td (opos=%.2f) linked to %td (opos=%.2f)" " snapped to %.2f and %.2f\n", - edge - edges, edge->opos / 64.0, - edge2 - edges, edge2->opos / 64.0, - edge->pos / 64.0, edge2->pos / 64.0 )); + edge - edges, (double)edge->opos / 64, + edge2 - edges, (double)edge2->opos / 64, + (double)edge->pos / 64, (double)edge2->pos / 64 )); } #ifdef FT_DEBUG_LEVEL_TRACE @@ -3314,10 +3333,10 @@ if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 ) { #ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE5(( " BOUND: edge %ld (pos=%.2f) moved to %.2f\n", + FT_TRACE5(( " BOUND: edge %td (pos=%.2f) moved to %.2f\n", edge - edges, - edge->pos / 64.0, - edge[-1].pos / 64.0 )); + (double)edge->pos / 64, + (double)edge[-1].pos / 64 )); num_actions++; #endif @@ -3416,19 +3435,20 @@ if ( delta < 64 + 16 ) { af_latin_align_serif_edge( hints, edge->serif, edge ); - FT_TRACE5(( " SERIF: edge %ld (opos=%.2f) serif to %ld (opos=%.2f)" + FT_TRACE5(( " SERIF: edge %td (opos=%.2f) serif to %td (opos=%.2f)" " aligned to %.2f\n", - edge - edges, edge->opos / 64.0, - edge->serif - edges, edge->serif->opos / 64.0, - edge->pos / 64.0 )); + edge - edges, (double)edge->opos / 64, + edge->serif - edges, (double)edge->serif->opos / 64, + (double)edge->pos / 64 )); } else if ( !anchor ) { edge->pos = FT_PIX_ROUND( edge->opos ); anchor = edge; - FT_TRACE5(( " SERIF_ANCHOR: edge %ld (opos=%.2f)" + FT_TRACE5(( " SERIF_ANCHOR: edge %td (opos=%.2f)" " snapped to %.2f\n", - edge-edges, edge->opos / 64.0, edge->pos / 64.0 )); + edge - edges, + (double)edge->opos / 64, (double)edge->pos / 64 )); } else { @@ -3454,19 +3474,20 @@ after->pos - before->pos, after->opos - before->opos ); - FT_TRACE5(( " SERIF_LINK1: edge %ld (opos=%.2f) snapped to %.2f" - " from %ld (opos=%.2f)\n", - edge - edges, edge->opos / 64.0, - edge->pos / 64.0, - before - edges, before->opos / 64.0 )); + FT_TRACE5(( " SERIF_LINK1: edge %td (opos=%.2f) snapped to %.2f" + " from %td (opos=%.2f)\n", + edge - edges, (double)edge->opos / 64, + (double)edge->pos / 64, + before - edges, (double)before->opos / 64 )); } else { edge->pos = anchor->pos + ( ( edge->opos - anchor->opos + 16 ) & ~31 ); - FT_TRACE5(( " SERIF_LINK2: edge %ld (opos=%.2f)" + FT_TRACE5(( " SERIF_LINK2: edge %td (opos=%.2f)" " snapped to %.2f\n", - edge - edges, edge->opos / 64.0, edge->pos / 64.0 )); + edge - edges, + (double)edge->opos / 64, (double)edge->pos / 64 )); } } @@ -3484,10 +3505,10 @@ if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 ) { #ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE5(( " BOUND: edge %ld (pos=%.2f) moved to %.2f\n", + FT_TRACE5(( " BOUND: edge %td (pos=%.2f) moved to %.2f\n", edge - edges, - edge->pos / 64.0, - edge[-1].pos / 64.0 )); + (double)edge->pos / 64, + (double)edge[-1].pos / 64 )); num_actions++; #endif @@ -3505,10 +3526,10 @@ if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 ) { #ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE5(( " BOUND: edge %ld (pos=%.2f) moved to %.2f\n", + FT_TRACE5(( " BOUND: edge %td (pos=%.2f) moved to %.2f\n", edge - edges, - edge->pos / 64.0, - edge[1].pos / 64.0 )); + (double)edge->pos / 64, + (double)edge[1].pos / 64 )); num_actions++; #endif @@ -3533,8 +3554,10 @@ af_latin_hints_apply( FT_UInt glyph_index, AF_GlyphHints hints, FT_Outline* outline, - AF_LatinMetrics metrics ) + AF_StyleMetrics metrics_ ) /* AF_LatinMetrics */ { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + FT_Error error; int dim; @@ -3575,24 +3598,6 @@ /* grid-fit the outline */ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) { -#ifdef AF_CONFIG_OPTION_USE_WARPER - if ( dim == AF_DIMENSION_HORZ && - metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL && - AF_HINTS_DO_WARP( hints ) ) - { - AF_WarperRec warper; - FT_Fixed scale; - FT_Pos delta; - - - af_warper_compute( &warper, hints, (AF_Dimension)dim, - &scale, &delta ); - af_glyph_hints_scale_dim( hints, (AF_Dimension)dim, - scale, delta ); - continue; - } -#endif /* AF_CONFIG_OPTION_USE_WARPER */ - if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) || ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) ) { diff --git a/lib/libesp32_lvgl/freetype/src/autofit/aflatin.h b/lib/libesp32_lvgl/freetype/src/autofit/aflatin.h index 62bc4c8d4..31aa91d3b 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/aflatin.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/aflatin.h @@ -5,7 +5,7 @@ * Auto-fitter hinting routines for latin writing system * (specification). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -116,11 +116,11 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - af_latin_metrics_init( AF_LatinMetrics metrics, + af_latin_metrics_init( AF_StyleMetrics metrics, FT_Face face ); FT_LOCAL( void ) - af_latin_metrics_scale( AF_LatinMetrics metrics, + af_latin_metrics_scale( AF_StyleMetrics metrics, AF_Scaler scaler ); FT_LOCAL( void ) diff --git a/lib/libesp32_lvgl/freetype/src/autofit/aflatin2.c b/lib/libesp32_lvgl/freetype/src/autofit/aflatin2.c deleted file mode 100644 index 902f3982e..000000000 --- a/lib/libesp32_lvgl/freetype/src/autofit/aflatin2.c +++ /dev/null @@ -1,2428 +0,0 @@ -/* ATTENTION: This file doesn't compile. It is only here as a reference */ -/* of an alternative latin hinting algorithm that was always */ -/* marked as experimental. */ - - -/**************************************************************************** - * - * aflatin2.c - * - * Auto-fitter hinting routines for latin writing system (body). - * - * Copyright (C) 2003-2020 by - * David Turner, Robert Wilhelm, and Werner Lemberg. - * - * This file is part of the FreeType project, and may only be used, - * modified, and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - */ - - -#include - - -#ifdef FT_OPTION_AUTOFIT2 - -#include "afglobal.h" -#include "aflatin.h" -#include "aflatin2.h" -#include "aferrors.h" - - -#ifdef AF_CONFIG_OPTION_USE_WARPER -#include "afwarp.h" -#endif - - - /************************************************************************** - * - * The macro FT_COMPONENT is used in trace mode. It is an implicit - * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log - * messages during execution. - */ -#undef FT_COMPONENT -#define FT_COMPONENT aflatin2 - - - FT_LOCAL_DEF( FT_Error ) - af_latin2_hints_compute_segments( AF_GlyphHints hints, - AF_Dimension dim ); - - FT_LOCAL_DEF( void ) - af_latin2_hints_link_segments( AF_GlyphHints hints, - AF_Dimension dim ); - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** L A T I N G L O B A L M E T R I C S *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - FT_LOCAL_DEF( void ) - af_latin2_metrics_init_widths( AF_LatinMetrics metrics, - FT_Face face ) - { - /* scan the array of segments in each direction */ - AF_GlyphHintsRec hints[1]; - - - af_glyph_hints_init( hints, face->memory ); - - metrics->axis[AF_DIMENSION_HORZ].width_count = 0; - metrics->axis[AF_DIMENSION_VERT].width_count = 0; - - { - FT_Error error; - FT_UInt glyph_index; - int dim; - AF_LatinMetricsRec dummy[1]; - AF_Scaler scaler = &dummy->root.scaler; - - - glyph_index = FT_Get_Char_Index( - face, - metrics->root.style_class->standard_char ); - if ( glyph_index == 0 ) - goto Exit; - - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); - if ( error || face->glyph->outline.n_points <= 0 ) - goto Exit; - - FT_ZERO( dummy ); - - dummy->units_per_em = metrics->units_per_em; - scaler->x_scale = scaler->y_scale = 0x10000L; - scaler->x_delta = scaler->y_delta = 0; - scaler->face = face; - scaler->render_mode = FT_RENDER_MODE_NORMAL; - scaler->flags = 0; - - af_glyph_hints_rescale( hints, (AF_StyleMetrics)dummy ); - - error = af_glyph_hints_reload( hints, &face->glyph->outline ); - if ( error ) - goto Exit; - - for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) - { - AF_LatinAxis axis = &metrics->axis[dim]; - AF_AxisHints axhints = &hints->axis[dim]; - AF_Segment seg, limit, link; - FT_UInt num_widths = 0; - - - error = af_latin2_hints_compute_segments( hints, - (AF_Dimension)dim ); - if ( error ) - goto Exit; - - af_latin2_hints_link_segments( hints, - (AF_Dimension)dim ); - - seg = axhints->segments; - limit = seg + axhints->num_segments; - - for ( ; seg < limit; seg++ ) - { - link = seg->link; - - /* we only consider stem segments there! */ - if ( link && link->link == seg && link > seg ) - { - FT_Pos dist; - - - dist = seg->pos - link->pos; - if ( dist < 0 ) - dist = -dist; - - if ( num_widths < AF_LATIN_MAX_WIDTHS ) - axis->widths[num_widths++].org = dist; - } - } - - af_sort_widths( num_widths, axis->widths ); - axis->width_count = num_widths; - } - - Exit: - for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) - { - AF_LatinAxis axis = &metrics->axis[dim]; - FT_Pos stdw; - - - stdw = ( axis->width_count > 0 ) - ? axis->widths[0].org - : AF_LATIN_CONSTANT( metrics, 50 ); - - /* let's try 20% of the smallest width */ - axis->edge_distance_threshold = stdw / 5; - axis->standard_width = stdw; - axis->extra_light = 0; - } - } - - af_glyph_hints_done( hints ); - } - - - -#define AF_LATIN_MAX_TEST_CHARACTERS 12 - - - static const char af_latin2_blue_chars[AF_LATIN_MAX_BLUES] - [AF_LATIN_MAX_TEST_CHARACTERS+1] = - { - "THEZOCQS", - "HEZLOCUS", - "fijkdbh", - "xzroesc", - "xzroesc", - "pqgjy" - }; - - - static void - af_latin2_metrics_init_blues( AF_LatinMetrics metrics, - FT_Face face ) - { - FT_Pos flats [AF_LATIN_MAX_TEST_CHARACTERS]; - FT_Pos rounds[AF_LATIN_MAX_TEST_CHARACTERS]; - FT_Int num_flats; - FT_Int num_rounds; - FT_Int bb; - AF_LatinBlue blue; - FT_Error error; - AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT]; - FT_GlyphSlot glyph = face->glyph; - - - /* we compute the blues simply by loading each character from the */ - /* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */ - /* bottom-most points (depending on `AF_IS_TOP_BLUE') */ - - FT_TRACE5(( "blue zones computation\n" - "======================\n\n" )); - - for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ ) - { - const char* p = af_latin2_blue_chars[bb]; - const char* limit = p + AF_LATIN_MAX_TEST_CHARACTERS; - FT_Pos* blue_ref; - FT_Pos* blue_shoot; - - - FT_TRACE5(( "blue zone %d:\n", bb )); - - num_flats = 0; - num_rounds = 0; - - for ( ; p < limit && *p; p++ ) - { - FT_UInt glyph_index; - FT_Int best_point, best_y, best_first, best_last; - FT_Vector* points; - FT_Bool round; - - - /* load the character in the face -- skip unknown or empty ones */ - glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p ); - if ( glyph_index == 0 ) - continue; - - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); - if ( error || glyph->outline.n_points <= 0 ) - continue; - - /* now compute min or max point indices and coordinates */ - points = glyph->outline.points; - best_point = -1; - best_y = 0; /* make compiler happy */ - best_first = 0; /* ditto */ - best_last = 0; /* ditto */ - - { - FT_Int nn; - FT_Int first = 0; - FT_Int last = -1; - - - for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ ) - { - FT_Int old_best_point = best_point; - FT_Int pp; - - - last = glyph->outline.contours[nn]; - - /* Avoid single-point contours since they are never rasterized. */ - /* In some fonts, they correspond to mark attachment points */ - /* which are way outside of the glyph's real outline. */ - if ( last <= first ) - continue; - - if ( AF_LATIN_IS_TOP_BLUE( bb ) ) - { - for ( pp = first; pp <= last; pp++ ) - if ( best_point < 0 || points[pp].y > best_y ) - { - best_point = pp; - best_y = points[pp].y; - } - } - else - { - for ( pp = first; pp <= last; pp++ ) - if ( best_point < 0 || points[pp].y < best_y ) - { - best_point = pp; - best_y = points[pp].y; - } - } - - if ( best_point != old_best_point ) - { - best_first = first; - best_last = last; - } - } - FT_TRACE5(( " %c %d", *p, best_y )); - } - - /* now check whether the point belongs to a straight or round */ - /* segment; we first need to find in which contour the extremum */ - /* lies, then inspect its previous and next points */ - if ( best_point >= 0 ) - { - FT_Pos best_x = points[best_point].x; - FT_Int start, end, prev, next; - FT_Pos dist; - - - /* now look for the previous and next points that are not on the */ - /* same Y coordinate. Threshold the `closeness'... */ - start = end = best_point; - - do - { - prev = start - 1; - if ( prev < best_first ) - prev = best_last; - - dist = FT_ABS( points[prev].y - best_y ); - /* accept a small distance or a small angle (both values are */ - /* heuristic; value 20 corresponds to approx. 2.9 degrees) */ - if ( dist > 5 ) - if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist ) - break; - - start = prev; - - } while ( start != best_point ); - - do - { - next = end + 1; - if ( next > best_last ) - next = best_first; - - dist = FT_ABS( points[next].y - best_y ); - if ( dist > 5 ) - if ( FT_ABS( points[next].x - best_x ) <= 20 * dist ) - break; - - end = next; - - } while ( end != best_point ); - - /* now, set the `round' flag depending on the segment's kind */ - round = FT_BOOL( - FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON || - FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON ); - - FT_TRACE5(( " (%s)\n", round ? "round" : "flat" )); - } - - if ( round ) - rounds[num_rounds++] = best_y; - else - flats[num_flats++] = best_y; - } - - if ( num_flats == 0 && num_rounds == 0 ) - { - /* - * we couldn't find a single glyph to compute this blue zone, - * we will simply ignore it then - */ - FT_TRACE5(( " empty\n" )); - continue; - } - - /* we have computed the contents of the `rounds' and `flats' tables, */ - /* now determine the reference and overshoot position of the blue -- */ - /* we simply take the median value after a simple sort */ - af_sort_pos( num_rounds, rounds ); - af_sort_pos( num_flats, flats ); - - blue = & axis->blues[axis->blue_count]; - blue_ref = & blue->ref.org; - blue_shoot = & blue->shoot.org; - - axis->blue_count++; - - if ( num_flats == 0 ) - { - *blue_ref = - *blue_shoot = rounds[num_rounds / 2]; - } - else if ( num_rounds == 0 ) - { - *blue_ref = - *blue_shoot = flats[num_flats / 2]; - } - else - { - *blue_ref = flats[num_flats / 2]; - *blue_shoot = rounds[num_rounds / 2]; - } - - /* there are sometimes problems: if the overshoot position of top */ - /* zones is under its reference position, or the opposite for bottom */ - /* zones. We must thus check everything there and correct the errors */ - if ( *blue_shoot != *blue_ref ) - { - FT_Pos ref = *blue_ref; - FT_Pos shoot = *blue_shoot; - FT_Bool over_ref = FT_BOOL( shoot > ref ); - - - if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref ) - { - *blue_ref = - *blue_shoot = ( shoot + ref ) / 2; - - FT_TRACE5(( " [overshoot smaller than reference," - " taking mean value]\n" )); - } - } - - blue->flags = 0; - if ( AF_LATIN_IS_TOP_BLUE( bb ) ) - blue->flags |= AF_LATIN_BLUE_TOP; - - /* - * The following flag is used later to adjust the y and x scales - * in order to optimize the pixel grid alignment of the top of small - * letters. - */ - if ( AF_LATIN_IS_X_HEIGHT_BLUE( bb ) ) - blue->flags |= AF_LATIN_BLUE_ADJUSTMENT; - - FT_TRACE5(( " -> reference = %ld\n" - " overshoot = %ld\n", - *blue_ref, *blue_shoot )); - } - - return; - } - - - FT_LOCAL_DEF( void ) - af_latin2_metrics_check_digits( AF_LatinMetrics metrics, - FT_Face face ) - { - FT_UInt i; - FT_Bool started = 0, same_width = 1; - FT_Fixed advance, old_advance = 0; - - - /* check whether all ASCII digits have the same advance width; */ - /* digit `0' is 0x30 in all supported charmaps */ - for ( i = 0x30; i <= 0x39; i++ ) - { - FT_UInt glyph_index; - - - glyph_index = FT_Get_Char_Index( face, i ); - if ( glyph_index == 0 ) - continue; - - if ( FT_Get_Advance( face, glyph_index, - FT_LOAD_NO_SCALE | - FT_LOAD_NO_HINTING | - FT_LOAD_IGNORE_TRANSFORM, - &advance ) ) - continue; - - if ( started ) - { - if ( advance != old_advance ) - { - same_width = 0; - break; - } - } - else - { - old_advance = advance; - started = 1; - } - } - - metrics->root.digits_have_same_width = same_width; - } - - - FT_LOCAL_DEF( FT_Error ) - af_latin2_metrics_init( AF_LatinMetrics metrics, - FT_Face face ) - { - FT_Error error = FT_Err_Ok; - FT_CharMap oldmap = face->charmap; - FT_UInt ee; - - static const FT_Encoding latin_encodings[] = - { - FT_ENCODING_UNICODE, - FT_ENCODING_APPLE_ROMAN, - FT_ENCODING_ADOBE_STANDARD, - FT_ENCODING_ADOBE_LATIN_1, - FT_ENCODING_NONE /* end of list */ - }; - - - metrics->units_per_em = face->units_per_EM; - - /* do we have a latin charmap in there? */ - for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ ) - { - error = FT_Select_Charmap( face, latin_encodings[ee] ); - if ( !error ) - break; - } - - if ( !error ) - { - af_latin2_metrics_init_widths( metrics, face ); - af_latin2_metrics_init_blues( metrics, face ); - af_latin2_metrics_check_digits( metrics, face ); - } - - FT_Set_Charmap( face, oldmap ); - return FT_Err_Ok; - } - - - static void - af_latin2_metrics_scale_dim( AF_LatinMetrics metrics, - AF_Scaler scaler, - AF_Dimension dim ) - { - FT_Fixed scale; - FT_Pos delta; - AF_LatinAxis axis; - FT_UInt nn; - - - if ( dim == AF_DIMENSION_HORZ ) - { - scale = scaler->x_scale; - delta = scaler->x_delta; - } - else - { - scale = scaler->y_scale; - delta = scaler->y_delta; - } - - axis = &metrics->axis[dim]; - - if ( axis->org_scale == scale && axis->org_delta == delta ) - return; - - axis->org_scale = scale; - axis->org_delta = delta; - - /* - * correct Y scale to optimize the alignment of the top of small - * letters to the pixel grid - */ - if ( dim == AF_DIMENSION_VERT ) - { - AF_LatinAxis vaxis = &metrics->axis[AF_DIMENSION_VERT]; - AF_LatinBlue blue = NULL; - - - for ( nn = 0; nn < vaxis->blue_count; nn++ ) - { - if ( vaxis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT ) - { - blue = &vaxis->blues[nn]; - break; - } - } - - if ( blue ) - { - FT_Pos scaled; - FT_Pos threshold; - FT_Pos fitted; - FT_UInt limit; - FT_UInt ppem; - - - scaled = FT_MulFix( blue->shoot.org, scaler->y_scale ); - ppem = metrics->root.scaler.face->size->metrics.x_ppem; - limit = metrics->root.globals->increase_x_height; - threshold = 40; - - /* if the `increase-x-height' property is active, */ - /* we round up much more often */ - if ( limit && - ppem <= limit && - ppem >= AF_PROP_INCREASE_X_HEIGHT_MIN ) - threshold = 52; - - fitted = ( scaled + threshold ) & ~63; - -#if 1 - if ( scaled != fitted ) - { - scale = FT_MulDiv( scale, fitted, scaled ); - FT_TRACE5(( "== scaled x-top = %.2g" - " fitted = %.2g, scaling = %.4g\n", - scaled / 64.0, fitted / 64.0, - ( fitted * 1.0 ) / scaled )); - } -#endif - } - } - - axis->scale = scale; - axis->delta = delta; - - if ( dim == AF_DIMENSION_HORZ ) - { - metrics->root.scaler.x_scale = scale; - metrics->root.scaler.x_delta = delta; - } - else - { - metrics->root.scaler.y_scale = scale; - metrics->root.scaler.y_delta = delta; - } - - /* scale the standard widths */ - for ( nn = 0; nn < axis->width_count; nn++ ) - { - AF_Width width = axis->widths + nn; - - - width->cur = FT_MulFix( width->org, scale ); - width->fit = width->cur; - } - - /* an extra-light axis corresponds to a standard width that is */ - /* smaller than 5/8 pixels */ - axis->extra_light = - FT_BOOL( FT_MulFix( axis->standard_width, scale ) < 32 + 8 ); - - if ( dim == AF_DIMENSION_VERT ) - { - /* scale the blue zones */ - for ( nn = 0; nn < axis->blue_count; nn++ ) - { - AF_LatinBlue blue = &axis->blues[nn]; - FT_Pos dist; - - - blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta; - blue->ref.fit = blue->ref.cur; - blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta; - blue->shoot.fit = blue->shoot.cur; - blue->flags &= ~AF_LATIN_BLUE_ACTIVE; - - /* a blue zone is only active if it is less than 3/4 pixels tall */ - dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale ); - if ( dist <= 48 && dist >= -48 ) - { - FT_Pos delta1, delta2; - - delta1 = blue->shoot.org - blue->ref.org; - delta2 = delta1; - if ( delta1 < 0 ) - delta2 = -delta2; - - delta2 = FT_MulFix( delta2, scale ); - - if ( delta2 < 32 ) - delta2 = 0; - else if ( delta2 < 64 ) - delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 ); - else - delta2 = FT_PIX_ROUND( delta2 ); - - if ( delta1 < 0 ) - delta2 = -delta2; - - blue->ref.fit = FT_PIX_ROUND( blue->ref.cur ); - blue->shoot.fit = blue->ref.fit + delta2; - - FT_TRACE5(( ">> activating blue zone %d:" - " ref.cur=%.2g ref.fit=%.2g" - " shoot.cur=%.2g shoot.fit=%.2g\n", - nn, blue->ref.cur / 64.0, blue->ref.fit / 64.0, - blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 )); - - blue->flags |= AF_LATIN_BLUE_ACTIVE; - } - } - } - } - - - FT_LOCAL_DEF( void ) - af_latin2_metrics_scale( AF_LatinMetrics metrics, - AF_Scaler scaler ) - { - metrics->root.scaler.render_mode = scaler->render_mode; - metrics->root.scaler.face = scaler->face; - metrics->root.scaler.flags = scaler->flags; - - af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ ); - af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT ); - } - - - /* Extract standard_width from writing system/script specific */ - /* metrics class. */ - - FT_LOCAL_DEF( void ) - af_latin2_get_standard_widths( AF_LatinMetrics metrics, - FT_Pos* stdHW, - FT_Pos* stdVW ) - { - if ( stdHW ) - *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width; - - if ( stdVW ) - *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width; - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** L A T I N G L Y P H A N A L Y S I S *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - -#define SORT_SEGMENTS - - FT_LOCAL_DEF( FT_Error ) - af_latin2_hints_compute_segments( AF_GlyphHints hints, - AF_Dimension dim ) - { - AF_AxisHints axis = &hints->axis[dim]; - FT_Memory memory = hints->memory; - FT_Error error = FT_Err_Ok; - AF_Segment segment = NULL; - AF_SegmentRec seg0; - AF_Point* contour = hints->contours; - AF_Point* contour_limit = contour + hints->num_contours; - AF_Direction major_dir, segment_dir; - - - FT_ZERO( &seg0 ); - seg0.score = 32000; - seg0.flags = AF_EDGE_NORMAL; - - major_dir = (AF_Direction)FT_ABS( axis->major_dir ); - segment_dir = major_dir; - - axis->num_segments = 0; - - /* set up (u,v) in each point */ - if ( dim == AF_DIMENSION_HORZ ) - { - AF_Point point = hints->points; - AF_Point limit = point + hints->num_points; - - - for ( ; point < limit; point++ ) - { - point->u = point->fx; - point->v = point->fy; - } - } - else - { - AF_Point point = hints->points; - AF_Point limit = point + hints->num_points; - - - for ( ; point < limit; point++ ) - { - point->u = point->fy; - point->v = point->fx; - } - } - - /* do each contour separately */ - for ( ; contour < contour_limit; contour++ ) - { - AF_Point point = contour[0]; - AF_Point start = point; - AF_Point last = point->prev; - - - if ( point == last ) /* skip singletons -- just in case */ - continue; - - /* already on an edge ?, backtrack to find its start */ - if ( FT_ABS( point->in_dir ) == major_dir ) - { - point = point->prev; - - while ( point->in_dir == start->in_dir ) - point = point->prev; - } - else /* otherwise, find first segment start, if any */ - { - while ( FT_ABS( point->out_dir ) != major_dir ) - { - point = point->next; - - if ( point == start ) - goto NextContour; - } - } - - start = point; - - for (;;) - { - AF_Point first; - FT_Pos min_u, min_v, max_u, max_v; - - /* we're at the start of a new segment */ - FT_ASSERT( FT_ABS( point->out_dir ) == major_dir && - point->in_dir != point->out_dir ); - first = point; - - min_u = max_u = point->u; - min_v = max_v = point->v; - - point = point->next; - - while ( point->out_dir == first->out_dir ) - { - point = point->next; - - if ( point->u < min_u ) - min_u = point->u; - - if ( point->u > max_u ) - max_u = point->u; - } - - if ( point->v < min_v ) - min_v = point->v; - - if ( point->v > max_v ) - max_v = point->v; - - /* record new segment */ - error = af_axis_hints_new_segment( axis, memory, &segment ); - if ( error ) - goto Exit; - - segment[0] = seg0; - segment->dir = first->out_dir; - segment->first = first; - segment->last = point; - segment->pos = (FT_Short)( ( min_u + max_u ) >> 1 ); - segment->min_coord = (FT_Short) min_v; - segment->max_coord = (FT_Short) max_v; - segment->height = (FT_Short)( max_v - min_v ); - - /* a segment is round if it doesn't have successive */ - /* on-curve points. */ - { - AF_Point pt = first; - AF_Point last = point; - FT_UInt f0 = pt->flags & AF_FLAG_CONTROL; - FT_UInt f1; - - - segment->flags &= ~AF_EDGE_ROUND; - - for ( ; pt != last; f0 = f1 ) - { - pt = pt->next; - f1 = pt->flags & AF_FLAG_CONTROL; - - if ( !f0 && !f1 ) - break; - - if ( pt == last ) - segment->flags |= AF_EDGE_ROUND; - } - } - - /* this can happen in the case of a degenerate contour - * e.g. a 2-point vertical contour - */ - if ( point == start ) - break; - - /* jump to the start of the next segment, if any */ - while ( FT_ABS( point->out_dir ) != major_dir ) - { - point = point->next; - - if ( point == start ) - goto NextContour; - } - } - - NextContour: - ; - } /* contours */ - - /* now slightly increase the height of segments when this makes */ - /* sense -- this is used to better detect and ignore serifs */ - { - AF_Segment segments = axis->segments; - AF_Segment segments_end = segments + axis->num_segments; - - - for ( segment = segments; segment < segments_end; segment++ ) - { - AF_Point first = segment->first; - AF_Point last = segment->last; - AF_Point p; - FT_Pos first_v = first->v; - FT_Pos last_v = last->v; - - - if ( first_v < last_v ) - { - p = first->prev; - if ( p->v < first_v ) - segment->height = (FT_Short)( segment->height + - ( ( first_v - p->v ) >> 1 ) ); - - p = last->next; - if ( p->v > last_v ) - segment->height = (FT_Short)( segment->height + - ( ( p->v - last_v ) >> 1 ) ); - } - else - { - p = first->prev; - if ( p->v > first_v ) - segment->height = (FT_Short)( segment->height + - ( ( p->v - first_v ) >> 1 ) ); - - p = last->next; - if ( p->v < last_v ) - segment->height = (FT_Short)( segment->height + - ( ( last_v - p->v ) >> 1 ) ); - } - } - } - -#ifdef AF_SORT_SEGMENTS - /* place all segments with a negative direction to the start - * of the array, used to speed up segment linking later... - */ - { - AF_Segment segments = axis->segments; - FT_UInt count = axis->num_segments; - FT_UInt ii, jj; - - for ( ii = 0; ii < count; ii++ ) - { - if ( segments[ii].dir > 0 ) - { - for ( jj = ii + 1; jj < count; jj++ ) - { - if ( segments[jj].dir < 0 ) - { - AF_SegmentRec tmp; - - - tmp = segments[ii]; - segments[ii] = segments[jj]; - segments[jj] = tmp; - - break; - } - } - - if ( jj == count ) - break; - } - } - axis->mid_segments = ii; - } -#endif - - Exit: - return error; - } - - - FT_LOCAL_DEF( void ) - af_latin2_hints_link_segments( AF_GlyphHints hints, - AF_Dimension dim ) - { - AF_AxisHints axis = &hints->axis[dim]; - AF_Segment segments = axis->segments; - AF_Segment segment_limit = segments + axis->num_segments; -#ifdef AF_SORT_SEGMENTS - AF_Segment segment_mid = segments + axis->mid_segments; -#endif - FT_Pos len_threshold, len_score; - AF_Segment seg1, seg2; - - - len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 ); - if ( len_threshold == 0 ) - len_threshold = 1; - - len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 ); - -#ifdef AF_SORT_SEGMENTS - for ( seg1 = segments; seg1 < segment_mid; seg1++ ) - { - if ( seg1->dir != axis->major_dir ) - continue; - - for ( seg2 = segment_mid; seg2 < segment_limit; seg2++ ) -#else - /* now compare each segment to the others */ - for ( seg1 = segments; seg1 < segment_limit; seg1++ ) - { - if ( seg1->dir != axis->major_dir ) - continue; - - for ( seg2 = segments; seg2 < segment_limit; seg2++ ) - if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos ) -#endif - { - FT_Pos pos1 = seg1->pos; - FT_Pos pos2 = seg2->pos; - FT_Pos dist = pos2 - pos1; - - - if ( dist < 0 ) - continue; - - { - FT_Pos min = seg1->min_coord; - FT_Pos max = seg1->max_coord; - FT_Pos len, score; - - - if ( min < seg2->min_coord ) - min = seg2->min_coord; - - if ( max > seg2->max_coord ) - max = seg2->max_coord; - - len = max - min; - if ( len >= len_threshold ) - { - score = dist + len_score / len; - if ( score < seg1->score ) - { - seg1->score = score; - seg1->link = seg2; - } - - if ( score < seg2->score ) - { - seg2->score = score; - seg2->link = seg1; - } - } - } - } - } -#if 0 - } -#endif - - /* now, compute the `serif' segments */ - for ( seg1 = segments; seg1 < segment_limit; seg1++ ) - { - seg2 = seg1->link; - - if ( seg2 ) - { - if ( seg2->link != seg1 ) - { - seg1->link = NULL; - seg1->serif = seg2->link; - } - } - } - } - - - FT_LOCAL_DEF( FT_Error ) - af_latin2_hints_compute_edges( AF_GlyphHints hints, - AF_Dimension dim ) - { - AF_AxisHints axis = &hints->axis[dim]; - FT_Error error = FT_Err_Ok; - FT_Memory memory = hints->memory; - AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim]; - - AF_Segment segments = axis->segments; - AF_Segment segment_limit = segments + axis->num_segments; - AF_Segment seg; - - AF_Direction up_dir; - FT_Fixed scale; - FT_Pos edge_distance_threshold; - FT_Pos segment_length_threshold; - - - axis->num_edges = 0; - - scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale - : hints->y_scale; - - up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP - : AF_DIR_RIGHT; - - /* - * We want to ignore very small (mostly serif) segments, we do that - * by ignoring those that whose length is less than a given fraction - * of the standard width. If there is no standard width, we ignore - * those that are less than a given size in pixels - * - * also, unlink serif segments that are linked to segments farther - * than 50% of the standard width - */ - if ( dim == AF_DIMENSION_HORZ ) - { - if ( laxis->width_count > 0 ) - segment_length_threshold = ( laxis->standard_width * 10 ) >> 4; - else - segment_length_threshold = FT_DivFix( 64, hints->y_scale ); - } - else - segment_length_threshold = 0; - - /********************************************************************** - * - * We will begin by generating a sorted table of edges for the - * current direction. To do so, we simply scan each segment and try - * to find an edge in our table that corresponds to its position. - * - * If no edge is found, we create and insert a new edge in the - * sorted table. Otherwise, we simply add the segment to the edge's - * list which will be processed in the second step to compute the - * edge's properties. - * - * Note that the edges table is sorted along the segment/edge - * position. - * - */ - - edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold, - scale ); - if ( edge_distance_threshold > 64 / 4 ) - edge_distance_threshold = 64 / 4; - - edge_distance_threshold = FT_DivFix( edge_distance_threshold, - scale ); - - for ( seg = segments; seg < segment_limit; seg++ ) - { - AF_Edge found = NULL; - FT_Int ee; - - - if ( seg->height < segment_length_threshold ) - continue; - - /* A special case for serif edges: If they are smaller than */ - /* 1.5 pixels we ignore them. */ - if ( seg->serif ) - { - FT_Pos dist = seg->serif->pos - seg->pos; - - - if ( dist < 0 ) - dist = -dist; - - if ( dist >= laxis->standard_width >> 1 ) - { - /* unlink this serif, it is too distant from its reference stem */ - seg->serif = NULL; - } - else if ( 2*seg->height < 3 * segment_length_threshold ) - continue; - } - - /* look for an edge corresponding to the segment */ - for ( ee = 0; ee < axis->num_edges; ee++ ) - { - AF_Edge edge = axis->edges + ee; - FT_Pos dist; - - - dist = seg->pos - edge->fpos; - if ( dist < 0 ) - dist = -dist; - - if ( dist < edge_distance_threshold && edge->dir == seg->dir ) - { - found = edge; - break; - } - } - - if ( !found ) - { - AF_Edge edge; - - - /* insert a new edge in the list and */ - /* sort according to the position */ - error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, 0, - memory, &edge ); - if ( error ) - goto Exit; - - /* add the segment to the new edge's list */ - FT_ZERO( edge ); - - edge->first = seg; - edge->last = seg; - edge->dir = seg->dir; - edge->fpos = seg->pos; - edge->opos = FT_MulFix( seg->pos, scale ); - edge->pos = edge->opos; - seg->edge_next = seg; - } - else - { - /* if an edge was found, simply add the segment to the edge's */ - /* list */ - seg->edge_next = found->first; - found->last->edge_next = seg; - found->last = seg; - } - } - - - /********************************************************************** - * - * Good, we will now compute each edge's properties according to - * segments found on its position. Basically, these are: - * - * - edge's main direction - * - stem edge, serif edge or both (which defaults to stem then) - * - rounded edge, straight or both (which defaults to straight) - * - link for edge - * - */ - - /* first of all, set the `edge' field in each segment -- this is */ - /* required in order to compute edge links */ - - /* - * Note that removing this loop and setting the `edge' field of each - * segment directly in the code above slows down execution speed for - * some reasons on platforms like the Sun. - */ - { - AF_Edge edges = axis->edges; - AF_Edge edge_limit = edges + axis->num_edges; - AF_Edge edge; - - - for ( edge = edges; edge < edge_limit; edge++ ) - { - seg = edge->first; - if ( seg ) - do - { - seg->edge = edge; - seg = seg->edge_next; - - } while ( seg != edge->first ); - } - - /* now, compute each edge properties */ - for ( edge = edges; edge < edge_limit; edge++ ) - { - FT_Int is_round = 0; /* does it contain round segments? */ - FT_Int is_straight = 0; /* does it contain straight segments? */ -#if 0 - FT_Pos ups = 0; /* number of upwards segments */ - FT_Pos downs = 0; /* number of downwards segments */ -#endif - - - seg = edge->first; - - do - { - FT_Bool is_serif; - - - /* check for roundness of segment */ - if ( seg->flags & AF_EDGE_ROUND ) - is_round++; - else - is_straight++; - -#if 0 - /* check for segment direction */ - if ( seg->dir == up_dir ) - ups += seg->max_coord-seg->min_coord; - else - downs += seg->max_coord-seg->min_coord; -#endif - - /* check for links -- if seg->serif is set, then seg->link must */ - /* be ignored */ - is_serif = FT_BOOL( seg->serif && - seg->serif->edge && - seg->serif->edge != edge ); - - if ( ( seg->link && seg->link->edge ) || is_serif ) - { - AF_Edge edge2; - AF_Segment seg2; - - - edge2 = edge->link; - seg2 = seg->link; - - if ( is_serif ) - { - seg2 = seg->serif; - edge2 = edge->serif; - } - - if ( edge2 ) - { - FT_Pos edge_delta; - FT_Pos seg_delta; - - - edge_delta = edge->fpos - edge2->fpos; - if ( edge_delta < 0 ) - edge_delta = -edge_delta; - - seg_delta = seg->pos - seg2->pos; - if ( seg_delta < 0 ) - seg_delta = -seg_delta; - - if ( seg_delta < edge_delta ) - edge2 = seg2->edge; - } - else - edge2 = seg2->edge; - - if ( is_serif ) - { - edge->serif = edge2; - edge2->flags |= AF_EDGE_SERIF; - } - else - edge->link = edge2; - } - - seg = seg->edge_next; - - } while ( seg != edge->first ); - - /* set the round/straight flags */ - edge->flags = AF_EDGE_NORMAL; - - if ( is_round > 0 && is_round >= is_straight ) - edge->flags |= AF_EDGE_ROUND; - -#if 0 - /* set the edge's main direction */ - edge->dir = AF_DIR_NONE; - - if ( ups > downs ) - edge->dir = (FT_Char)up_dir; - - else if ( ups < downs ) - edge->dir = (FT_Char)-up_dir; - - else if ( ups == downs ) - edge->dir = 0; /* both up and down! */ -#endif - - /* gets rid of serifs if link is set */ - /* XXX: This gets rid of many unpleasant artefacts! */ - /* Example: the `c' in cour.pfa at size 13 */ - - if ( edge->serif && edge->link ) - edge->serif = NULL; - } - } - - Exit: - return error; - } - - - FT_LOCAL_DEF( FT_Error ) - af_latin2_hints_detect_features( AF_GlyphHints hints, - AF_Dimension dim ) - { - FT_Error error; - - - error = af_latin2_hints_compute_segments( hints, dim ); - if ( !error ) - { - af_latin2_hints_link_segments( hints, dim ); - - error = af_latin2_hints_compute_edges( hints, dim ); - } - return error; - } - - - static void - af_latin2_hints_compute_blue_edges( AF_GlyphHints hints, - AF_LatinMetrics metrics ) - { - AF_AxisHints axis = &hints->axis[AF_DIMENSION_VERT]; - AF_Edge edge = axis->edges; - AF_Edge edge_limit = edge + axis->num_edges; - AF_LatinAxis latin = &metrics->axis[AF_DIMENSION_VERT]; - FT_Fixed scale = latin->scale; - FT_Pos best_dist0; /* initial threshold */ - - - /* compute the initial threshold as a fraction of the EM size */ - best_dist0 = FT_MulFix( metrics->units_per_em / 40, scale ); - - if ( best_dist0 > 64 / 2 ) - best_dist0 = 64 / 2; - - /* compute which blue zones are active, i.e. have their scaled */ - /* size < 3/4 pixels */ - - /* for each horizontal edge search the blue zone which is closest */ - for ( ; edge < edge_limit; edge++ ) - { - FT_Int bb; - AF_Width best_blue = NULL; - FT_Pos best_dist = best_dist0; - - for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ ) - { - AF_LatinBlue blue = latin->blues + bb; - FT_Bool is_top_blue, is_major_dir; - - - /* skip inactive blue zones (i.e., those that are too small) */ - if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) ) - continue; - - /* if it is a top zone, check for right edges -- if it is a bottom */ - /* zone, check for left edges */ - /* */ - /* of course, that's for TrueType */ - is_top_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 ); - is_major_dir = FT_BOOL( edge->dir == axis->major_dir ); - - /* if it is a top zone, the edge must be against the major */ - /* direction; if it is a bottom zone, it must be in the major */ - /* direction */ - if ( is_top_blue ^ is_major_dir ) - { - FT_Pos dist; - AF_Width compare; - - - /* if it's a rounded edge, compare it to the overshoot position */ - /* if it's a flat edge, compare it to the reference position */ - if ( edge->flags & AF_EDGE_ROUND ) - compare = &blue->shoot; - else - compare = &blue->ref; - - dist = edge->fpos - compare->org; - if ( dist < 0 ) - dist = -dist; - - dist = FT_MulFix( dist, scale ); - if ( dist < best_dist ) - { - best_dist = dist; - best_blue = compare; - } - -#if 0 - /* now, compare it to the overshoot position if the edge is */ - /* rounded, and if the edge is over the reference position of a */ - /* top zone, or under the reference position of a bottom zone */ - if ( edge->flags & AF_EDGE_ROUND && dist != 0 ) - { - FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org ); - - - if ( is_top_blue ^ is_under_ref ) - { - blue = latin->blues + bb; - dist = edge->fpos - blue->shoot.org; - if ( dist < 0 ) - dist = -dist; - - dist = FT_MulFix( dist, scale ); - if ( dist < best_dist ) - { - best_dist = dist; - best_blue = & blue->shoot; - } - } - } -#endif - } - } - - if ( best_blue ) - edge->blue_edge = best_blue; - } - } - - - static FT_Error - af_latin2_hints_init( AF_GlyphHints hints, - AF_LatinMetrics metrics ) - { - FT_Render_Mode mode; - FT_UInt32 scaler_flags, other_flags; - FT_Face face = metrics->root.scaler.face; - - - af_glyph_hints_rescale( hints, (AF_StyleMetrics)metrics ); - - /* - * correct x_scale and y_scale if needed, since they may have - * been modified `af_latin2_metrics_scale_dim' above - */ - hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale; - hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta; - hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale; - hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta; - - /* compute flags depending on render mode, etc. */ - mode = metrics->root.scaler.render_mode; - -#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */ - if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V ) - metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL; -#endif - - scaler_flags = hints->scaler_flags; - other_flags = 0; - - /* - * We snap the width of vertical stems for the monochrome and - * horizontal LCD rendering targets only. - */ - if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD ) - other_flags |= AF_LATIN_HINTS_HORZ_SNAP; - - /* - * We snap the width of horizontal stems for the monochrome and - * vertical LCD rendering targets only. - */ - if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V ) - other_flags |= AF_LATIN_HINTS_VERT_SNAP; - - /* - * We adjust stems to full pixels unless in `light' or `lcd' mode. - */ - if ( mode != FT_RENDER_MODE_LIGHT && mode != FT_RENDER_MODE_LCD ) - other_flags |= AF_LATIN_HINTS_STEM_ADJUST; - - if ( mode == FT_RENDER_MODE_MONO ) - other_flags |= AF_LATIN_HINTS_MONO; - - /* - * In `light' or `lcd' mode we disable horizontal hinting completely. - * We also do it if the face is italic. - */ - if ( mode == FT_RENDER_MODE_LIGHT || mode == FT_RENDER_MODE_LCD || - ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 ) - scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL; - -#ifdef AF_CONFIG_OPTION_USE_WARPER - /* get (global) warper flag */ - if ( !metrics->root.globals->module->warping ) - scaler_flags |= AF_SCALER_FLAG_NO_WARPER; -#endif - - hints->scaler_flags = scaler_flags; - hints->other_flags = other_flags; - - return 0; - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** L A T I N G L Y P H G R I D - F I T T I N G *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /* snap a given width in scaled coordinates to one of the */ - /* current standard widths */ - - static FT_Pos - af_latin2_snap_width( AF_Width widths, - FT_UInt count, - FT_Pos width ) - { - FT_UInt n; - FT_Pos best = 64 + 32 + 2; - FT_Pos reference = width; - FT_Pos scaled; - - - for ( n = 0; n < count; n++ ) - { - FT_Pos w; - FT_Pos dist; - - - w = widths[n].cur; - dist = width - w; - if ( dist < 0 ) - dist = -dist; - if ( dist < best ) - { - best = dist; - reference = w; - } - } - - scaled = FT_PIX_ROUND( reference ); - - if ( width >= reference ) - { - if ( width < scaled + 48 ) - width = reference; - } - else - { - if ( width > scaled - 48 ) - width = reference; - } - - return width; - } - - - /* compute the snapped width of a given stem */ - - static FT_Pos - af_latin2_compute_stem_width( AF_GlyphHints hints, - AF_Dimension dim, - FT_Pos width, - FT_UInt base_flags, - FT_UInt stem_flags ) - { - AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics; - AF_LatinAxis axis = & metrics->axis[dim]; - FT_Pos dist = width; - FT_Int sign = 0; - FT_Int vertical = ( dim == AF_DIMENSION_VERT ); - - FT_UNUSED( base_flags ); - - - if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) || - axis->extra_light ) - return width; - - if ( dist < 0 ) - { - dist = -width; - sign = 1; - } - - if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) || - ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) - { - /* smooth hinting process: very lightly quantize the stem width */ - - /* leave the widths of serifs alone */ - - if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) ) - goto Done_Width; - -#if 0 - else if ( ( base_flags & AF_EDGE_ROUND ) ) - { - if ( dist < 80 ) - dist = 64; - } - else if ( dist < 56 ) - dist = 56; -#endif - if ( axis->width_count > 0 ) - { - FT_Pos delta; - - - /* compare to standard width */ - if ( axis->width_count > 0 ) - { - delta = dist - axis->widths[0].cur; - - if ( delta < 0 ) - delta = -delta; - - if ( delta < 40 ) - { - dist = axis->widths[0].cur; - if ( dist < 48 ) - dist = 48; - - goto Done_Width; - } - } - - if ( dist < 3 * 64 ) - { - delta = dist & 63; - dist &= -64; - - if ( delta < 10 ) - dist += delta; - - else if ( delta < 32 ) - dist += 10; - - else if ( delta < 54 ) - dist += 54; - - else - dist += delta; - } - else - dist = ( dist + 32 ) & ~63; - } - } - else - { - /* strong hinting process: snap the stem width to integer pixels */ - FT_Pos org_dist = dist; - - - dist = af_latin2_snap_width( axis->widths, axis->width_count, dist ); - - if ( vertical ) - { - /* in the case of vertical hinting, always round */ - /* the stem heights to integer pixels */ - - if ( dist >= 64 ) - dist = ( dist + 16 ) & ~63; - else - dist = 64; - } - else - { - if ( AF_LATIN_HINTS_DO_MONO( hints ) ) - { - /* monochrome horizontal hinting: snap widths to integer pixels */ - /* with a different threshold */ - - if ( dist < 64 ) - dist = 64; - else - dist = ( dist + 32 ) & ~63; - } - else - { - /* for horizontal anti-aliased hinting, we adopt a more subtle */ - /* approach: we strengthen small stems, round stems whose size */ - /* is between 1 and 2 pixels to an integer, otherwise nothing */ - - if ( dist < 48 ) - dist = ( dist + 64 ) >> 1; - - else if ( dist < 128 ) - { - /* We only round to an integer width if the corresponding */ - /* distortion is less than 1/4 pixel. Otherwise this */ - /* makes everything worse since the diagonals, which are */ - /* not hinted, appear a lot bolder or thinner than the */ - /* vertical stems. */ - - FT_Int delta; - - - dist = ( dist + 22 ) & ~63; - delta = dist - org_dist; - if ( delta < 0 ) - delta = -delta; - - if ( delta >= 16 ) - { - dist = org_dist; - if ( dist < 48 ) - dist = ( dist + 64 ) >> 1; - } - } - else - /* round otherwise to prevent color fringes in LCD mode */ - dist = ( dist + 32 ) & ~63; - } - } - } - - Done_Width: - if ( sign ) - dist = -dist; - - return dist; - } - - - /* align one stem edge relative to the previous stem edge */ - - static void - af_latin2_align_linked_edge( AF_GlyphHints hints, - AF_Dimension dim, - AF_Edge base_edge, - AF_Edge stem_edge ) - { - FT_Pos dist = stem_edge->opos - base_edge->opos; - - FT_Pos fitted_width = af_latin2_compute_stem_width( hints, dim, dist, - base_edge->flags, - stem_edge->flags ); - - - stem_edge->pos = base_edge->pos + fitted_width; - - FT_TRACE5(( "LINK: edge %d (opos=%.2f) linked to (%.2f), " - "dist was %.2f, now %.2f\n", - stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0, - stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 )); - } - - - static void - af_latin2_align_serif_edge( AF_GlyphHints hints, - AF_Edge base, - AF_Edge serif ) - { - FT_UNUSED( hints ); - - serif->pos = base->pos + ( serif->opos - base->opos ); - } - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /**** ****/ - /**** E D G E H I N T I N G ****/ - /**** ****/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - static void - af_latin2_hint_edges( AF_GlyphHints hints, - AF_Dimension dim ) - { - AF_AxisHints axis = &hints->axis[dim]; - AF_Edge edges = axis->edges; - AF_Edge edge_limit = edges + axis->num_edges; - AF_Edge edge; - AF_Edge anchor = NULL; - FT_Int has_serifs = 0; - FT_Pos anchor_drift = 0; - - - - FT_TRACE5(( "==== hinting %s edges =====\n", - dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" )); - - /* we begin by aligning all stems relative to the blue zone */ - /* if needed -- that's only for horizontal edges */ - - if ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_BLUES( hints ) ) - { - for ( edge = edges; edge < edge_limit; edge++ ) - { - AF_Width blue; - AF_Edge edge1, edge2; - - - if ( edge->flags & AF_EDGE_DONE ) - continue; - - blue = edge->blue_edge; - edge1 = NULL; - edge2 = edge->link; - - if ( blue ) - { - edge1 = edge; - } - else if ( edge2 && edge2->blue_edge ) - { - blue = edge2->blue_edge; - edge1 = edge2; - edge2 = edge; - } - - if ( !edge1 ) - continue; - - FT_TRACE5(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), " - "was (%.2f)\n", - edge1-edges, edge1->opos / 64.0, blue->fit / 64.0, - edge1->pos / 64.0 )); - - edge1->pos = blue->fit; - edge1->flags |= AF_EDGE_DONE; - - if ( edge2 && !edge2->blue_edge ) - { - af_latin2_align_linked_edge( hints, dim, edge1, edge2 ); - edge2->flags |= AF_EDGE_DONE; - } - - if ( !anchor ) - { - anchor = edge; - - anchor_drift = ( anchor->pos - anchor->opos ); - if ( edge2 ) - anchor_drift = ( anchor_drift + - ( edge2->pos - edge2->opos ) ) >> 1; - } - } - } - - /* now we will align all stem edges, trying to maintain the */ - /* relative order of stems in the glyph */ - for ( edge = edges; edge < edge_limit; edge++ ) - { - AF_Edge edge2; - - - if ( edge->flags & AF_EDGE_DONE ) - continue; - - /* skip all non-stem edges */ - edge2 = edge->link; - if ( !edge2 ) - { - has_serifs++; - continue; - } - - /* now align the stem */ - - /* this should not happen, but it's better to be safe */ - if ( edge2->blue_edge ) - { - FT_TRACE5(( "ASSERTION FAILED for edge %d\n", edge2-edges )); - - af_latin2_align_linked_edge( hints, dim, edge2, edge ); - edge->flags |= AF_EDGE_DONE; - continue; - } - - if ( !anchor ) - { - FT_Pos org_len, org_center, cur_len; - FT_Pos cur_pos1, error1, error2, u_off, d_off; - - - org_len = edge2->opos - edge->opos; - cur_len = af_latin2_compute_stem_width( hints, dim, org_len, - edge->flags, - edge2->flags ); - if ( cur_len <= 64 ) - u_off = d_off = 32; - else - { - u_off = 38; - d_off = 26; - } - - if ( cur_len < 96 ) - { - org_center = edge->opos + ( org_len >> 1 ); - - cur_pos1 = FT_PIX_ROUND( org_center ); - - error1 = org_center - ( cur_pos1 - u_off ); - if ( error1 < 0 ) - error1 = -error1; - - error2 = org_center - ( cur_pos1 + d_off ); - if ( error2 < 0 ) - error2 = -error2; - - if ( error1 < error2 ) - cur_pos1 -= u_off; - else - cur_pos1 += d_off; - - edge->pos = cur_pos1 - cur_len / 2; - edge2->pos = edge->pos + cur_len; - } - else - edge->pos = FT_PIX_ROUND( edge->opos ); - - FT_TRACE5(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)" - " snapped to (%.2f) (%.2f)\n", - edge-edges, edge->opos / 64.0, - edge2-edges, edge2->opos / 64.0, - edge->pos / 64.0, edge2->pos / 64.0 )); - anchor = edge; - - edge->flags |= AF_EDGE_DONE; - - af_latin2_align_linked_edge( hints, dim, edge, edge2 ); - - edge2->flags |= AF_EDGE_DONE; - - anchor_drift = ( ( anchor->pos - anchor->opos ) + - ( edge2->pos - edge2->opos ) ) >> 1; - - FT_TRACE5(( "DRIFT: %.2f\n", anchor_drift/64.0 )); - } - else - { - FT_Pos org_pos, org_len, org_center, cur_center, cur_len; - FT_Pos org_left, org_right; - - - org_pos = edge->opos + anchor_drift; - org_len = edge2->opos - edge->opos; - org_center = org_pos + ( org_len >> 1 ); - - cur_len = af_latin2_compute_stem_width( hints, dim, org_len, - edge->flags, - edge2->flags ); - - org_left = org_pos + ( ( org_len - cur_len ) >> 1 ); - org_right = org_pos + ( ( org_len + cur_len ) >> 1 ); - - FT_TRACE5(( "ALIGN: left=%.2f right=%.2f ", - org_left / 64.0, org_right / 64.0 )); - cur_center = org_center; - - if ( edge2->flags & AF_EDGE_DONE ) - { - FT_TRACE5(( "\n" )); - edge->pos = edge2->pos - cur_len; - } - else - { - /* we want to compare several displacement, and choose - * the one that increases fitness while minimizing - * distortion as well - */ - FT_Pos displacements[6], scores[6], org, fit, delta; - FT_UInt count = 0; - - /* note: don't even try to fit tiny stems */ - if ( cur_len < 32 ) - { - FT_TRACE5(( "tiny stem\n" )); - goto AlignStem; - } - - /* if the span is within a single pixel, don't touch it */ - if ( FT_PIX_FLOOR( org_left ) == FT_PIX_CEIL( org_right ) ) - { - FT_TRACE5(( "single pixel stem\n" )); - goto AlignStem; - } - - if ( cur_len <= 96 ) - { - /* we want to avoid the absolute worst case which is - * when the left and right edges of the span each represent - * about 50% of the gray. we'd better want to change this - * to 25/75%, since this is much more pleasant to the eye with - * very acceptable distortion - */ - FT_Pos frac_left = org_left & 63; - FT_Pos frac_right = org_right & 63; - - if ( frac_left >= 22 && frac_left <= 42 && - frac_right >= 22 && frac_right <= 42 ) - { - org = frac_left; - fit = ( org <= 32 ) ? 16 : 48; - delta = FT_ABS( fit - org ); - displacements[count] = fit - org; - scores[count++] = delta; - FT_TRACE5(( "dispA=%.2f (%d) ", ( fit - org ) / 64.0, delta )); - - org = frac_right; - fit = ( org <= 32 ) ? 16 : 48; - delta = FT_ABS( fit - org ); - displacements[count] = fit - org; - scores[count++] = delta; - FT_TRACE5(( "dispB=%.2f (%d) ", ( fit - org ) / 64.0, delta )); - } - } - - /* snapping the left edge to the grid */ - org = org_left; - fit = FT_PIX_ROUND( org ); - delta = FT_ABS( fit - org ); - displacements[count] = fit - org; - scores[count++] = delta; - FT_TRACE5(( "dispC=%.2f (%d) ", ( fit - org ) / 64.0, delta )); - - /* snapping the right edge to the grid */ - org = org_right; - fit = FT_PIX_ROUND( org ); - delta = FT_ABS( fit - org ); - displacements[count] = fit - org; - scores[count++] = delta; - FT_TRACE5(( "dispD=%.2f (%d) ", ( fit - org ) / 64.0, delta )); - - /* now find the best displacement */ - { - FT_Pos best_score = scores[0]; - FT_Pos best_disp = displacements[0]; - FT_UInt nn; - - for ( nn = 1; nn < count; nn++ ) - { - if ( scores[nn] < best_score ) - { - best_score = scores[nn]; - best_disp = displacements[nn]; - } - } - - cur_center = org_center + best_disp; - } - FT_TRACE5(( "\n" )); - } - - AlignStem: - edge->pos = cur_center - ( cur_len >> 1 ); - edge2->pos = edge->pos + cur_len; - - FT_TRACE5(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f)" - " snapped to (%.2f) and (%.2f)," - " org_len=%.2f cur_len=%.2f\n", - edge-edges, edge->opos / 64.0, - edge2-edges, edge2->opos / 64.0, - edge->pos / 64.0, edge2->pos / 64.0, - org_len / 64.0, cur_len / 64.0 )); - - edge->flags |= AF_EDGE_DONE; - edge2->flags |= AF_EDGE_DONE; - - if ( edge > edges && edge->pos < edge[-1].pos ) - { - FT_TRACE5(( "BOUND: %d (pos=%.2f) to (%.2f)\n", - edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 )); - edge->pos = edge[-1].pos; - } - } - } - - /* make sure that lowercase m's maintain their symmetry */ - - /* In general, lowercase m's have six vertical edges if they are sans */ - /* serif, or twelve if they are with serifs. This implementation is */ - /* based on that assumption, and seems to work very well with most */ - /* faces. However, if for a certain face this assumption is not */ - /* true, the m is just rendered like before. In addition, any stem */ - /* correction will only be applied to symmetrical glyphs (even if the */ - /* glyph is not an m), so the potential for unwanted distortion is */ - /* relatively low. */ - - /* We don't handle horizontal edges since we can't easily assure that */ - /* the third (lowest) stem aligns with the base line; it might end up */ - /* one pixel higher or lower. */ - -#if 0 - { - FT_Int n_edges = edge_limit - edges; - - - if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) ) - { - AF_Edge edge1, edge2, edge3; - FT_Pos dist1, dist2, span, delta; - - - if ( n_edges == 6 ) - { - edge1 = edges; - edge2 = edges + 2; - edge3 = edges + 4; - } - else - { - edge1 = edges + 1; - edge2 = edges + 5; - edge3 = edges + 9; - } - - dist1 = edge2->opos - edge1->opos; - dist2 = edge3->opos - edge2->opos; - - span = dist1 - dist2; - if ( span < 0 ) - span = -span; - - if ( span < 8 ) - { - delta = edge3->pos - ( 2 * edge2->pos - edge1->pos ); - edge3->pos -= delta; - if ( edge3->link ) - edge3->link->pos -= delta; - - /* move the serifs along with the stem */ - if ( n_edges == 12 ) - { - ( edges + 8 )->pos -= delta; - ( edges + 11 )->pos -= delta; - } - - edge3->flags |= AF_EDGE_DONE; - if ( edge3->link ) - edge3->link->flags |= AF_EDGE_DONE; - } - } - } -#endif - - if ( has_serifs || !anchor ) - { - /* - * now hint the remaining edges (serifs and single) in order - * to complete our processing - */ - for ( edge = edges; edge < edge_limit; edge++ ) - { - FT_Pos delta; - - - if ( edge->flags & AF_EDGE_DONE ) - continue; - - delta = 1000; - - if ( edge->serif ) - { - delta = edge->serif->opos - edge->opos; - if ( delta < 0 ) - delta = -delta; - } - - if ( delta < 64 + 16 ) - { - af_latin2_align_serif_edge( hints, edge->serif, edge ); - FT_TRACE5(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)" - " aligned to (%.2f)\n", - edge-edges, edge->opos / 64.0, - edge->serif - edges, edge->serif->opos / 64.0, - edge->pos / 64.0 )); - } - else if ( !anchor ) - { - FT_TRACE5(( "SERIF_ANCHOR: edge %d (opos=%.2f)" - " snapped to (%.2f)\n", - edge-edges, edge->opos / 64.0, edge->pos / 64.0 )); - edge->pos = FT_PIX_ROUND( edge->opos ); - anchor = edge; - } - else - { - AF_Edge before, after; - - - for ( before = edge - 1; before >= edges; before-- ) - if ( before->flags & AF_EDGE_DONE ) - break; - - for ( after = edge + 1; after < edge_limit; after++ ) - if ( after->flags & AF_EDGE_DONE ) - break; - - if ( before >= edges && before < edge && - after < edge_limit && after > edge ) - { - if ( after->opos == before->opos ) - edge->pos = before->pos; - else - edge->pos = before->pos + - FT_MulDiv( edge->opos - before->opos, - after->pos - before->pos, - after->opos - before->opos ); - FT_TRACE5(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)" - " from %d (opos=%.2f)\n", - edge-edges, edge->opos / 64.0, edge->pos / 64.0, - before - edges, before->opos / 64.0 )); - } - else - { - edge->pos = anchor->pos + - ( ( edge->opos - anchor->opos + 16 ) & ~31 ); - - FT_TRACE5(( "SERIF_LINK2: edge %d (opos=%.2f)" - " snapped to (%.2f)\n", - edge-edges, edge->opos / 64.0, edge->pos / 64.0 )); - } - } - - edge->flags |= AF_EDGE_DONE; - - if ( edge > edges && edge->pos < edge[-1].pos ) - edge->pos = edge[-1].pos; - - if ( edge + 1 < edge_limit && - edge[1].flags & AF_EDGE_DONE && - edge->pos > edge[1].pos ) - edge->pos = edge[1].pos; - } - } - } - - - static FT_Error - af_latin2_hints_apply( FT_UInt glyph_index, - AF_GlyphHints hints, - FT_Outline* outline, - AF_LatinMetrics metrics ) - { - FT_Error error; - int dim; - - FT_UNUSED( glyph_index ); - - - error = af_glyph_hints_reload( hints, outline ); - if ( error ) - goto Exit; - - /* analyze glyph outline */ - if ( AF_HINTS_DO_HORIZONTAL( hints ) ) - { - error = af_latin2_hints_detect_features( hints, AF_DIMENSION_HORZ ); - if ( error ) - goto Exit; - } - - if ( AF_HINTS_DO_VERTICAL( hints ) ) - { - error = af_latin2_hints_detect_features( hints, AF_DIMENSION_VERT ); - if ( error ) - goto Exit; - - af_latin2_hints_compute_blue_edges( hints, metrics ); - } - - /* grid-fit the outline */ - for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) - { -#ifdef AF_CONFIG_OPTION_USE_WARPER - if ( dim == AF_DIMENSION_HORZ && - metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL && - AF_HINTS_DO_WARP( hints ) ) - { - AF_WarperRec warper; - FT_Fixed scale; - FT_Pos delta; - - - af_warper_compute( &warper, hints, dim, &scale, &delta ); - af_glyph_hints_scale_dim( hints, dim, scale, delta ); - continue; - } -#endif /* AF_CONFIG_OPTION_USE_WARPER */ - - if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) || - ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) ) - { - af_latin2_hint_edges( hints, (AF_Dimension)dim ); - af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim ); - af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim ); - af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim ); - } - } - af_glyph_hints_save( hints, outline ); - - Exit: - return error; - } - - - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** L A T I N S C R I P T C L A S S *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - - AF_DEFINE_WRITING_SYSTEM_CLASS( - af_latin2_writing_system_class, - - AF_WRITING_SYSTEM_LATIN2, - - sizeof ( AF_LatinMetricsRec ), - - (AF_WritingSystem_InitMetricsFunc) af_latin2_metrics_init, /* style_metrics_init */ - (AF_WritingSystem_ScaleMetricsFunc)af_latin2_metrics_scale, /* style_metrics_scale */ - (AF_WritingSystem_DoneMetricsFunc) NULL, /* style_metrics_done */ - (AF_WritingSystem_GetStdWidthsFunc)af_latin2_get_standard_widths, /* style_metrics_getstdw */ - - (AF_WritingSystem_InitHintsFunc) af_latin2_hints_init, /* style_hints_init */ - (AF_WritingSystem_ApplyHintsFunc) af_latin2_hints_apply /* style_hints_apply */ - ) - -#else /* !FT_OPTION_AUTOFIT2 */ - - /* ANSI C doesn't like empty source files */ - typedef int _af_latin2_dummy; - -#endif /* !FT_OPTION_AUTOFIT2 */ - - -/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/autofit/aflatin2.h b/lib/libesp32_lvgl/freetype/src/autofit/aflatin2.h deleted file mode 100644 index c2aebc49a..000000000 --- a/lib/libesp32_lvgl/freetype/src/autofit/aflatin2.h +++ /dev/null @@ -1,46 +0,0 @@ -/* ATTENTION: This file doesn't compile. It is only here as a reference */ -/* of an alternative latin hinting algorithm that was always */ -/* marked as experimental. */ - - -/**************************************************************************** - * - * aflatin2.h - * - * Auto-fitter hinting routines for latin writing system - * (specification). - * - * Copyright (C) 2003-2020 by - * David Turner, Robert Wilhelm, and Werner Lemberg. - * - * This file is part of the FreeType project, and may only be used, - * modified, and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - */ - - -#ifndef AFLATIN2_H_ -#define AFLATIN2_H_ - -#include "afhints.h" - - -FT_BEGIN_HEADER - - - /* the `latin' writing system */ - - AF_DECLARE_WRITING_SYSTEM_CLASS( af_latin2_writing_system_class ) - - -/* */ - -FT_END_HEADER - -#endif /* AFLATIN_H_ */ - - -/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afloader.c b/lib/libesp32_lvgl/freetype/src/autofit/afloader.c index c35d85c4c..7c47d562a 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afloader.c +++ b/lib/libesp32_lvgl/freetype/src/autofit/afloader.c @@ -4,7 +4,7 @@ * * Auto-fitter glyph loading routines (body). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -55,10 +55,8 @@ error = af_face_globals_new( face, &loader->globals, module ); if ( !error ) { - face->autohint.data = - (FT_Pointer)loader->globals; - face->autohint.finalizer = - (FT_Generic_Finalizer)af_face_globals_free; + face->autohint.data = (FT_Pointer)loader->globals; + face->autohint.finalizer = af_face_globals_free; } } @@ -105,7 +103,6 @@ globals->stem_darkening_for_ppem; FT_Fixed em_size = af_intToFixed( face->units_per_EM ); - FT_Fixed em_ratio = FT_DivFix( af_intToFixed( 1000 ), em_size ); FT_Matrix scale_down_matrix = { 0x10000L, 0, 0, 0x10000L }; @@ -142,12 +139,11 @@ darken_by_font_units_x = - af_intToFixed( af_loader_compute_darkening( loader, - face, - stdVW ) ); - darken_x = FT_DivFix( FT_MulFix( darken_by_font_units_x, - size_metrics->x_scale ), - em_ratio ); + af_loader_compute_darkening( loader, + face, + stdVW ) ; + darken_x = FT_MulFix( darken_by_font_units_x, + size_metrics->x_scale ); globals->standard_vertical_width = stdVW; globals->stem_darkening_for_ppem = size_metrics->x_ppem; @@ -161,12 +157,11 @@ darken_by_font_units_y = - af_intToFixed( af_loader_compute_darkening( loader, - face, - stdHW ) ); - darken_y = FT_DivFix( FT_MulFix( darken_by_font_units_y, - size_metrics->y_scale ), - em_ratio ); + af_loader_compute_darkening( loader, + face, + stdHW ) ; + darken_y = FT_MulFix( darken_by_font_units_y, + size_metrics->y_scale ); globals->standard_horizontal_width = stdHW; globals->stem_darkening_for_ppem = size_metrics->x_ppem; @@ -232,9 +227,6 @@ AF_WritingSystemClass writing_system_class; - if ( !size ) - return FT_THROW( Invalid_Size_Handle ); - FT_ZERO( &scaler ); if ( !size_internal->autohint_metrics.x_scale || @@ -300,12 +292,6 @@ if ( error ) goto Exit; -#ifdef FT_OPTION_AUTOFIT2 - /* XXX: undocumented hook to activate the latin2 writing system. */ - if ( load_flags & ( 1UL << 20 ) ) - style_options = AF_STYLE_LTN2_DFLT; -#endif - /* * Glyphs (really code points) are assigned to scripts. Script * analysis is done lazily: For each glyph that passes through here, @@ -482,8 +468,8 @@ FT_Pos pp2x = loader->pp2.x; - loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta ); - loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta ); + loader->pp1.x = FT_PIX_ROUND( pp1x ); + loader->pp2.x = FT_PIX_ROUND( pp2x ); slot->lsb_delta = loader->pp1.x - pp1x; slot->rsb_delta = loader->pp2.x - pp2x; @@ -594,7 +580,7 @@ * * XXX: Currently a crude adaption of the original algorithm. Do better? */ - FT_LOCAL_DEF( FT_Int32 ) + FT_LOCAL_DEF( FT_Fixed ) af_loader_compute_darkening( AF_Loader loader, FT_Face face, FT_Pos standard_width ) @@ -713,7 +699,7 @@ } /* Convert darken_amount from per 1000 em to true character space. */ - return af_fixedToInt( FT_DivFix( darken_amount, em_ratio ) ); + return FT_DivFix( darken_amount, em_ratio ); } diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afloader.h b/lib/libesp32_lvgl/freetype/src/autofit/afloader.h index 97282371c..e4e197e37 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afloader.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/afloader.h @@ -4,7 +4,7 @@ * * Auto-fitter glyph loading routines (specification). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -75,7 +75,7 @@ FT_BEGIN_HEADER FT_UInt gindex, FT_Int32 load_flags ); - FT_LOCAL_DEF( FT_Int32 ) + FT_LOCAL( FT_Fixed ) af_loader_compute_darkening( AF_Loader loader, FT_Face face, FT_Pos standard_width ); diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afmodule.c b/lib/libesp32_lvgl/freetype/src/autofit/afmodule.c index e16494460..20a6b96bc 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afmodule.c +++ b/lib/libesp32_lvgl/freetype/src/autofit/afmodule.c @@ -4,7 +4,7 @@ * * Auto-fitter module implementation (body). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -43,14 +43,14 @@ #endif - int _af_debug_disable_horz_hints; - int _af_debug_disable_vert_hints; - int _af_debug_disable_blue_hints; + int af_debug_disable_horz_hints_; + int af_debug_disable_vert_hints_; + int af_debug_disable_blue_hints_; /* we use a global object instead of a local one for debugging */ - AF_GlyphHintsRec _af_debug_hints_rec[1]; + static AF_GlyphHintsRec af_debug_hints_rec_[1]; - void* _af_debug_hints = _af_debug_hints_rec; + void* af_debug_hints_ = af_debug_hints_rec_; #endif #include @@ -89,10 +89,8 @@ error = af_face_globals_new( face, &globals, module ); if ( !error ) { - face->autohint.data = - (FT_Pointer)globals; - face->autohint.finalizer = - (FT_Generic_Finalizer)af_face_globals_free; + face->autohint.data = (FT_Pointer)globals; + face->autohint.finalizer = af_face_globals_free; } } @@ -119,8 +117,8 @@ if ( !ft_strcmp( property_name, "fallback-script" ) ) { - FT_UInt* fallback_script; - FT_UInt ss; + AF_Script* fallback_script; + FT_UInt ss; #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES @@ -128,7 +126,7 @@ return FT_THROW( Invalid_Argument ); #endif - fallback_script = (FT_UInt*)value; + fallback_script = (AF_Script*)value; /* We translate the fallback script to a fallback style that uses */ /* `fallback-script' as its script and `AF_COVERAGE_NONE' as its */ @@ -138,8 +136,8 @@ AF_StyleClass style_class = af_style_classes[ss]; - if ( (FT_UInt)style_class->script == *fallback_script && - style_class->coverage == AF_COVERAGE_DEFAULT ) + if ( style_class->script == *fallback_script && + style_class->coverage == AF_COVERAGE_DEFAULT ) { module->fallback_style = ss; break; @@ -148,7 +146,7 @@ if ( !af_style_classes[ss] ) { - FT_TRACE0(( "af_property_set: Invalid value %d for property `%s'\n", + FT_TRACE2(( "af_property_set: Invalid value %d for property `%s'\n", *fallback_script, property_name )); return FT_THROW( Invalid_Argument ); } @@ -157,7 +155,7 @@ } else if ( !ft_strcmp( property_name, "default-script" ) ) { - FT_UInt* default_script; + AF_Script* default_script; #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES @@ -165,7 +163,7 @@ return FT_THROW( Invalid_Argument ); #endif - default_script = (FT_UInt*)value; + default_script = (AF_Script*)value; module->default_script = *default_script; @@ -190,35 +188,6 @@ return error; } -#ifdef AF_CONFIG_OPTION_USE_WARPER - else if ( !ft_strcmp( property_name, "warping" ) ) - { -#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES - if ( value_is_string ) - { - const char* s = (const char*)value; - long w = ft_strtol( s, NULL, 10 ); - - - if ( w == 0 ) - module->warping = 0; - else if ( w == 1 ) - module->warping = 1; - else - return FT_THROW( Invalid_Argument ); - } - else -#endif - { - FT_Bool* warping = (FT_Bool*)value; - - - module->warping = *warping; - } - - return error; - } -#endif /* AF_CONFIG_OPTION_USE_WARPER */ else if ( !ft_strcmp( property_name, "darkening-parameters" ) ) { FT_Int* darken_params; @@ -307,7 +276,7 @@ return error; } - FT_TRACE0(( "af_property_set: missing property `%s'\n", + FT_TRACE2(( "af_property_set: missing property `%s'\n", property_name )); return FT_THROW( Missing_Property ); } @@ -320,11 +289,6 @@ { FT_Error error = FT_Err_Ok; AF_Module module = (AF_Module)ft_module; - FT_UInt fallback_style = module->fallback_style; - FT_UInt default_script = module->default_script; -#ifdef AF_CONFIG_OPTION_USE_WARPER - FT_Bool warping = module->warping; -#endif if ( !ft_strcmp( property_name, "glyph-to-script-map" ) ) @@ -341,9 +305,9 @@ } else if ( !ft_strcmp( property_name, "fallback-script" ) ) { - FT_UInt* val = (FT_UInt*)value; + AF_Script* val = (AF_Script*)value; - AF_StyleClass style_class = af_style_classes[fallback_style]; + AF_StyleClass style_class = af_style_classes[module->fallback_style]; *val = style_class->script; @@ -352,10 +316,10 @@ } else if ( !ft_strcmp( property_name, "default-script" ) ) { - FT_UInt* val = (FT_UInt*)value; + AF_Script* val = (AF_Script*)value; - *val = default_script; + *val = module->default_script; return error; } @@ -371,17 +335,6 @@ return error; } -#ifdef AF_CONFIG_OPTION_USE_WARPER - else if ( !ft_strcmp( property_name, "warping" ) ) - { - FT_Bool* val = (FT_Bool*)value; - - - *val = warping; - - return error; - } -#endif /* AF_CONFIG_OPTION_USE_WARPER */ else if ( !ft_strcmp( property_name, "darkening-parameters" ) ) { FT_Int* darken_params = module->darken_params; @@ -410,7 +363,7 @@ return error; } - FT_TRACE0(( "af_property_get: missing property `%s'\n", + FT_TRACE2(( "af_property_get: missing property `%s'\n", property_name )); return FT_THROW( Missing_Property ); } @@ -419,8 +372,9 @@ FT_DEFINE_SERVICE_PROPERTIESREC( af_service_properties, - (FT_Properties_SetFunc)af_property_set, /* set_property */ - (FT_Properties_GetFunc)af_property_get ) /* get_property */ + af_property_set, /* FT_Properties_SetFunc set_property */ + af_property_get /* FT_Properties_GetFunc get_property */ + ) FT_DEFINE_SERVICEDESCREC1( @@ -447,9 +401,6 @@ module->fallback_style = AF_STYLE_FALLBACK; module->default_script = AF_SCRIPT_DEFAULT; -#ifdef AF_CONFIG_OPTION_USE_WARPER - module->warping = 0; -#endif module->no_stem_darkening = TRUE; module->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1; @@ -471,19 +422,21 @@ FT_UNUSED( ft_module ); #ifdef FT_DEBUG_AUTOFIT - if ( _af_debug_hints_rec->memory ) - af_glyph_hints_done( _af_debug_hints_rec ); + if ( af_debug_hints_rec_->memory ) + af_glyph_hints_done( af_debug_hints_rec_ ); #endif } FT_CALLBACK_DEF( FT_Error ) - af_autofitter_load_glyph( AF_Module module, - FT_GlyphSlot slot, - FT_Size size, - FT_UInt glyph_index, - FT_Int32 load_flags ) + af_autofitter_load_glyph( FT_AutoHinter module_, + FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ) { + AF_Module module = (AF_Module)module_; + FT_Error error = FT_Err_Ok; FT_Memory memory = module->root.library->memory; @@ -491,7 +444,7 @@ /* in debug mode, we use a global object that survives this routine */ - AF_GlyphHints hints = _af_debug_hints_rec; + AF_GlyphHints hints = af_debug_hints_rec_; AF_LoaderRec loader[1]; FT_UNUSED( size ); @@ -547,10 +500,10 @@ FT_DEFINE_AUTOHINTER_INTERFACE( af_autofitter_interface, - NULL, /* reset_face */ - NULL, /* get_global_hints */ - NULL, /* done_global_hints */ - (FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph /* load_glyph */ + NULL, /* FT_AutoHinter_GlobalResetFunc reset_face */ + NULL, /* FT_AutoHinter_GlobalGetFunc get_global_hints */ + NULL, /* FT_AutoHinter_GlobalDoneFunc done_global_hints */ + af_autofitter_load_glyph /* FT_AutoHinter_GlyphLoadFunc load_glyph */ ) FT_DEFINE_MODULE( @@ -565,9 +518,9 @@ (const void*)&af_autofitter_interface, - (FT_Module_Constructor)af_autofitter_init, /* module_init */ - (FT_Module_Destructor) af_autofitter_done, /* module_done */ - (FT_Module_Requester) af_get_interface /* get_interface */ + af_autofitter_init, /* FT_Module_Constructor module_init */ + af_autofitter_done, /* FT_Module_Destructor module_done */ + af_get_interface /* FT_Module_Requester get_interface */ ) diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afmodule.h b/lib/libesp32_lvgl/freetype/src/autofit/afmodule.h index e8fe4a93a..4b8b4562c 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afmodule.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/afmodule.h @@ -4,7 +4,7 @@ * * Auto-fitter module implementation (specification). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -36,10 +36,7 @@ FT_BEGIN_HEADER FT_ModuleRec root; FT_UInt fallback_style; - FT_UInt default_script; -#ifdef AF_CONFIG_OPTION_USE_WARPER - FT_Bool warping; -#endif + AF_Script default_script; FT_Bool no_stem_darkening; FT_Int darken_params[8]; diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afranges.c b/lib/libesp32_lvgl/freetype/src/autofit/afranges.c index c8ebf5e78..cfcaf340a 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afranges.c +++ b/lib/libesp32_lvgl/freetype/src/autofit/afranges.c @@ -4,7 +4,7 @@ * * Auto-fitter Unicode script ranges (body). * - * Copyright (C) 2013-2020 by + * Copyright (C) 2013-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afranges.h b/lib/libesp32_lvgl/freetype/src/autofit/afranges.h index c2ffda4b0..5775738bc 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afranges.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/afranges.h @@ -4,7 +4,7 @@ * * Auto-fitter Unicode script ranges (specification). * - * Copyright (C) 2013-2020 by + * Copyright (C) 2013-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afscript.h b/lib/libesp32_lvgl/freetype/src/autofit/afscript.h index 4cf9cc19f..3a101937d 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afscript.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/afscript.h @@ -4,7 +4,7 @@ * * Auto-fitter scripts (specification only). * - * Copyright (C) 2013-2020 by + * Copyright (C) 2013-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afshaper.c b/lib/libesp32_lvgl/freetype/src/autofit/afshaper.c index bbf7b6b1f..abc6f1d29 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afshaper.c +++ b/lib/libesp32_lvgl/freetype/src/autofit/afshaper.c @@ -4,7 +4,7 @@ * * HarfBuzz interface for accessing OpenType features (body). * - * Copyright (C) 2013-2020 by + * Copyright (C) 2013-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -132,13 +132,24 @@ /* Convert a HarfBuzz script tag into the corresponding OpenType */ /* tag or tags -- some Indic scripts like Devanagari have an old */ /* and a new set of features. */ - hb_ot_tags_from_script( script, - &script_tags[0], - &script_tags[1] ); + { + unsigned int tags_count = 3; + hb_tag_t tags[3]; - /* `hb_ot_tags_from_script' usually returns HB_OT_TAG_DEFAULT_SCRIPT */ - /* as the second tag. We change that to HB_TAG_NONE except for the */ - /* default script. */ + + hb_ot_tags_from_script_and_language( script, + HB_LANGUAGE_INVALID, + &tags_count, + tags, + NULL, + NULL ); + script_tags[0] = tags_count > 0 ? tags[0] : HB_TAG_NONE; + script_tags[1] = tags_count > 1 ? tags[1] : HB_TAG_NONE; + script_tags[2] = tags_count > 2 ? tags[2] : HB_TAG_NONE; + } + + /* If the second tag is HB_OT_TAG_DEFAULT_SCRIPT, change that to */ + /* HB_TAG_NONE except for the default script. */ if ( default_script ) { if ( script_tags[0] == HB_TAG_NONE ) @@ -157,9 +168,6 @@ /* HarfBuzz maps them to `DFLT', which we don't want to handle here */ if ( script_tags[0] == HB_OT_TAG_DEFAULT_SCRIPT ) goto Exit; - - if ( script_tags[1] == HB_OT_TAG_DEFAULT_SCRIPT ) - script_tags[1] = HB_TAG_NONE; } gsub_lookups = hb_set_create(); @@ -173,9 +181,9 @@ if ( hb_set_is_empty( gsub_lookups ) ) goto Exit; /* nothing to do */ - FT_TRACE4(( "GSUB lookups (style `%s'):\n" - " ", + FT_TRACE4(( "GSUB lookups (style `%s'):\n", af_style_names[style_class->style] )); + FT_TRACE4(( " " )); #ifdef FT_DEBUG_LEVEL_TRACE count = 0; @@ -202,12 +210,13 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( !count ) FT_TRACE4(( " (none)" )); - FT_TRACE4(( "\n\n" )); + FT_TRACE4(( "\n" )); + FT_TRACE4(( "\n" )); #endif - FT_TRACE4(( "GPOS lookups (style `%s'):\n" - " ", + FT_TRACE4(( "GPOS lookups (style `%s'):\n", af_style_names[style_class->style] )); + FT_TRACE4(( " " )); gpos_lookups = hb_set_create(); hb_ot_layout_collect_lookups( face, @@ -242,13 +251,14 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( !count ) FT_TRACE4(( " (none)" )); - FT_TRACE4(( "\n\n" )); + FT_TRACE4(( "\n" )); + FT_TRACE4(( "\n" )); #endif /* * We now check whether we can construct blue zones, using glyphs * covered by the feature only. In case there is not a single zone - * (this is, not a single character is covered), we skip this coverage. + * (that is, not a single character is covered), we skip this coverage. * */ if ( style_class->coverage != AF_COVERAGE_DEFAULT ) @@ -303,9 +313,9 @@ * hinted and usually rendered glyph. * * Consider the superscript feature of font `pala.ttf': Some of the - * glyphs are `real', this is, they have a zero vertical offset, but + * glyphs are `real', that is, they have a zero vertical offset, but * most of them are small caps glyphs shifted up to the superscript - * position (this is, the `sups' feature is present in both the GSUB and + * position (that is, the `sups' feature is present in both the GSUB and * GPOS tables). The code for blue zones computation actually uses a * feature's y offset so that the `real' glyphs get correct hints. But * later on it is impossible to decide whether a glyph index belongs to, @@ -353,8 +363,10 @@ { #ifdef FT_DEBUG_LEVEL_TRACE if ( !( count % 10 ) ) - FT_TRACE4(( "\n" - " " )); + { + FT_TRACE4(( "\n" )); + FT_TRACE4(( " " )); + } FT_TRACE4(( " %d", idx )); count++; @@ -376,9 +388,12 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( !count ) - FT_TRACE4(( "\n" - " (none)" )); - FT_TRACE4(( "\n\n" )); + { + FT_TRACE4(( "\n" )); + FT_TRACE4(( " (none)" )); + } + FT_TRACE4(( "\n" )); + FT_TRACE4(( "\n" )); #endif Exit: diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afshaper.h b/lib/libesp32_lvgl/freetype/src/autofit/afshaper.h index 138c27b32..054a18ffb 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afshaper.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/afshaper.h @@ -4,7 +4,7 @@ * * HarfBuzz interface for accessing OpenType features (specification). * - * Copyright (C) 2013-2020 by + * Copyright (C) 2013-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -27,7 +27,7 @@ #include #include -#include +#include "ft-hb.h" #endif diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afstyles.h b/lib/libesp32_lvgl/freetype/src/autofit/afstyles.h index 9113ec451..73ebef017 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/afstyles.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/afstyles.h @@ -4,7 +4,7 @@ * * Auto-fitter styles (specification only). * - * Copyright (C) 2013-2020 by + * Copyright (C) 2013-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -299,15 +299,6 @@ AF_BLUE_STRINGSET_LATP, AF_COVERAGE_DEFAULT ) -#ifdef FT_OPTION_AUTOFIT2 - STYLE( ltn2_dflt, LTN2_DFLT, - "Latin 2 default style", - AF_WRITING_SYSTEM_LATIN2, - AF_SCRIPT_LATN, - AF_BLUE_STRINGSET_LATN, - AF_COVERAGE_DEFAULT ) -#endif - STYLE( lisu_dflt, LISU_DFLT, "Lisu default style", AF_WRITING_SYSTEM_LATIN, diff --git a/lib/libesp32_lvgl/freetype/src/autofit/aftypes.h b/lib/libesp32_lvgl/freetype/src/autofit/aftypes.h index 5f040c6b4..661519449 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/aftypes.h +++ b/lib/libesp32_lvgl/freetype/src/autofit/aftypes.h @@ -4,7 +4,7 @@ * * Auto-fitter types (specification only). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -57,10 +57,10 @@ FT_BEGIN_HEADER #ifdef FT_DEBUG_AUTOFIT -extern int _af_debug_disable_horz_hints; -extern int _af_debug_disable_vert_hints; -extern int _af_debug_disable_blue_hints; -extern void* _af_debug_hints; +extern int af_debug_disable_horz_hints_; +extern int af_debug_disable_vert_hints_; +extern int af_debug_disable_blue_hints_; +extern void* af_debug_hints_; #endif /* FT_DEBUG_AUTOFIT */ @@ -92,63 +92,6 @@ extern void* _af_debug_hints; FT_Pos threshold ); - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** A N G L E T Y P E S *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /* - * The auto-fitter doesn't need a very high angular accuracy; - * this allows us to speed up some computations considerably with a - * light Cordic algorithm (see afangles.c). - */ - - typedef FT_Int AF_Angle; - - -#define AF_ANGLE_PI 256 -#define AF_ANGLE_2PI ( AF_ANGLE_PI * 2 ) -#define AF_ANGLE_PI2 ( AF_ANGLE_PI / 2 ) -#define AF_ANGLE_PI4 ( AF_ANGLE_PI / 4 ) - - -#if 0 - /* - * compute the angle of a given 2-D vector - */ - FT_LOCAL( AF_Angle ) - af_angle_atan( FT_Pos dx, - FT_Pos dy ); - - - /* - * compute `angle2 - angle1'; the result is always within - * the range [-AF_ANGLE_PI .. AF_ANGLE_PI - 1] - */ - FT_LOCAL( AF_Angle ) - af_angle_diff( AF_Angle angle1, - AF_Angle angle2 ); -#endif /* 0 */ - - -#define AF_ANGLE_DIFF( result, angle1, angle2 ) \ - FT_BEGIN_STMNT \ - AF_Angle _delta = (angle2) - (angle1); \ - \ - \ - while ( _delta <= -AF_ANGLE_PI ) \ - _delta += AF_ANGLE_2PI; \ - \ - while ( _delta > AF_ANGLE_PI ) \ - _delta -= AF_ANGLE_2PI; \ - \ - result = _delta; \ - FT_END_STMNT - - /* * opaque handle to glyph-specific hints -- see `afhints.h' for more * details @@ -172,18 +115,17 @@ extern void* _af_debug_hints; #define AF_SCALER_FLAG_NO_HORIZONTAL 1U /* disable horizontal hinting */ #define AF_SCALER_FLAG_NO_VERTICAL 2U /* disable vertical hinting */ #define AF_SCALER_FLAG_NO_ADVANCE 4U /* disable advance hinting */ -#define AF_SCALER_FLAG_NO_WARPER 8U /* disable warper */ typedef struct AF_ScalerRec_ { - FT_Face face; /* source font face */ - FT_Fixed x_scale; /* from font units to 1/64th device pixels */ - FT_Fixed y_scale; /* from font units to 1/64th device pixels */ - FT_Pos x_delta; /* in 1/64th device pixels */ - FT_Pos y_delta; /* in 1/64th device pixels */ - FT_Render_Mode render_mode; /* monochrome, anti-aliased, LCD, etc. */ - FT_UInt32 flags; /* additional control flags, see above */ + FT_Face face; /* source font face */ + FT_Fixed x_scale; /* from font units to 1/64 device pixels */ + FT_Fixed y_scale; /* from font units to 1/64 device pixels */ + FT_Pos x_delta; /* in 1/64 device pixels */ + FT_Pos y_delta; /* in 1/64 device pixels */ + FT_Render_Mode render_mode; /* monochrome, anti-aliased, LCD, etc. */ + FT_UInt32 flags; /* additional control flags, see above */ } AF_ScalerRec, *AF_Scaler; @@ -256,7 +198,6 @@ extern void* _af_debug_hints; * outline according to the results of the glyph analyzer. */ -#define AFWRTSYS_H_ /* don't load header files */ #undef WRITING_SYSTEM #define WRITING_SYSTEM( ws, WS ) \ AF_WRITING_SYSTEM_ ## WS, @@ -265,14 +206,12 @@ extern void* _af_debug_hints; typedef enum AF_WritingSystem_ { -#include "afwrtsys.h" +#include "afws-iter.h" AF_WRITING_SYSTEM_MAX /* do not remove */ } AF_WritingSystem; -#undef AFWRTSYS_H_ - typedef struct AF_WritingSystemClassRec_ { diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afwarp.c b/lib/libesp32_lvgl/freetype/src/autofit/afwarp.c deleted file mode 100644 index 808280df5..000000000 --- a/lib/libesp32_lvgl/freetype/src/autofit/afwarp.c +++ /dev/null @@ -1,373 +0,0 @@ -/**************************************************************************** - * - * afwarp.c - * - * Auto-fitter warping algorithm (body). - * - * Copyright (C) 2006-2020 by - * David Turner, Robert Wilhelm, and Werner Lemberg. - * - * This file is part of the FreeType project, and may only be used, - * modified, and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - */ - - - /* - * The idea of the warping code is to slightly scale and shift a glyph - * within a single dimension so that as much of its segments are aligned - * (more or less) on the grid. To find out the optimal scaling and - * shifting value, various parameter combinations are tried and scored. - */ - -#include "afwarp.h" - -#ifdef AF_CONFIG_OPTION_USE_WARPER - - /************************************************************************** - * - * The macro FT_COMPONENT is used in trace mode. It is an implicit - * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log - * messages during execution. - */ -#undef FT_COMPONENT -#define FT_COMPONENT afwarp - - - /* The weights cover the range 0/64 - 63/64 of a pixel. Obviously, */ - /* values around a half pixel (which means exactly between two grid */ - /* lines) gets the worst weight. */ -#if 1 - static const AF_WarpScore - af_warper_weights[64] = - { - 35, 32, 30, 25, 20, 15, 12, 10, 5, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, -2, -5, -8,-10,-10,-20,-20,-30,-30, - - -30,-30,-20,-20,-10,-10, -8, -5, -2, -1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 5, 10, 12, 15, 20, 25, 30, 32, - }; -#else - static const AF_WarpScore - af_warper_weights[64] = - { - 30, 20, 10, 5, 4, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -1, -2, -2, -5, -5,-10,-10,-15,-20, - - -20,-15,-15,-10,-10, -5, -5, -2, -2, -1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4, 5, 10, 20, - }; -#endif - - - /* Score segments for a given `scale' and `delta' in the range */ - /* `xx1' to `xx2', and store the best result in `warper'. If */ - /* the new best score is equal to the old one, prefer the */ - /* value with a smaller distortion (around `base_distort'). */ - - static void - af_warper_compute_line_best( AF_Warper warper, - FT_Fixed scale, - FT_Pos delta, - FT_Pos xx1, - FT_Pos xx2, - AF_WarpScore base_distort, - AF_Segment segments, - FT_Int num_segments ) - { - FT_Int idx_min, idx_max, idx0; - FT_Int nn; - AF_WarpScore scores[65]; - - - for ( nn = 0; nn < 65; nn++ ) - scores[nn] = 0; - - idx0 = xx1 - warper->t1; - - /* compute minimum and maximum indices */ - { - FT_Pos xx1min = warper->x1min; - FT_Pos xx1max = warper->x1max; - FT_Pos w = xx2 - xx1; - - - if ( xx1min + w < warper->x2min ) - xx1min = warper->x2min - w; - - if ( xx1max + w > warper->x2max ) - xx1max = warper->x2max - w; - - idx_min = xx1min - warper->t1; - idx_max = xx1max - warper->t1; - - if ( idx_min < 0 || idx_min > idx_max || idx_max > 64 ) - { - FT_TRACE5(( "invalid indices:\n" - " min=%d max=%d, xx1=%ld xx2=%ld,\n" - " x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n", - idx_min, idx_max, xx1, xx2, - warper->x1min, warper->x1max, - warper->x2min, warper->x2max )); - return; - } - } - - for ( nn = 0; nn < num_segments; nn++ ) - { - FT_Pos len = segments[nn].max_coord - segments[nn].min_coord; - FT_Pos y0 = FT_MulFix( segments[nn].pos, scale ) + delta; - FT_Pos y = y0 + ( idx_min - idx0 ); - FT_Int idx; - - - /* score the length of the segments for the given range */ - for ( idx = idx_min; idx <= idx_max; idx++, y++ ) - scores[idx] += af_warper_weights[y & 63] * len; - } - - /* find best score */ - { - FT_Int idx; - - - for ( idx = idx_min; idx <= idx_max; idx++ ) - { - AF_WarpScore score = scores[idx]; - AF_WarpScore distort = base_distort + ( idx - idx0 ); - - - if ( score > warper->best_score || - ( score == warper->best_score && - distort < warper->best_distort ) ) - { - warper->best_score = score; - warper->best_distort = distort; - warper->best_scale = scale; - warper->best_delta = delta + ( idx - idx0 ); - } - } - } - } - - - /* Compute optimal scaling and delta values for a given glyph and */ - /* dimension. */ - - FT_LOCAL_DEF( void ) - af_warper_compute( AF_Warper warper, - AF_GlyphHints hints, - AF_Dimension dim, - FT_Fixed *a_scale, - FT_Pos *a_delta ) - { - AF_AxisHints axis; - AF_Point points; - - FT_Fixed org_scale; - FT_Pos org_delta; - - FT_Int nn, num_points, num_segments; - FT_Int X1, X2; - FT_Int w; - - AF_WarpScore base_distort; - AF_Segment segments; - - - /* get original scaling transformation */ - if ( dim == AF_DIMENSION_VERT ) - { - org_scale = hints->y_scale; - org_delta = hints->y_delta; - } - else - { - org_scale = hints->x_scale; - org_delta = hints->x_delta; - } - - warper->best_scale = org_scale; - warper->best_delta = org_delta; - warper->best_score = FT_INT_MIN; - warper->best_distort = 0; - - axis = &hints->axis[dim]; - segments = axis->segments; - num_segments = axis->num_segments; - points = hints->points; - num_points = hints->num_points; - - *a_scale = org_scale; - *a_delta = org_delta; - - /* get X1 and X2, minimum and maximum in original coordinates */ - if ( num_segments < 1 ) - return; - -#if 1 - X1 = X2 = points[0].fx; - for ( nn = 1; nn < num_points; nn++ ) - { - FT_Int X = points[nn].fx; - - - if ( X < X1 ) - X1 = X; - if ( X > X2 ) - X2 = X; - } -#else - X1 = X2 = segments[0].pos; - for ( nn = 1; nn < num_segments; nn++ ) - { - FT_Int X = segments[nn].pos; - - - if ( X < X1 ) - X1 = X; - if ( X > X2 ) - X2 = X; - } -#endif - - if ( X1 >= X2 ) - return; - - warper->x1 = FT_MulFix( X1, org_scale ) + org_delta; - warper->x2 = FT_MulFix( X2, org_scale ) + org_delta; - - warper->t1 = AF_WARPER_FLOOR( warper->x1 ); - warper->t2 = AF_WARPER_CEIL( warper->x2 ); - - /* examine a half pixel wide range around the maximum coordinates */ - warper->x1min = warper->x1 & ~31; - warper->x1max = warper->x1min + 32; - warper->x2min = warper->x2 & ~31; - warper->x2max = warper->x2min + 32; - - if ( warper->x1max > warper->x2 ) - warper->x1max = warper->x2; - - if ( warper->x2min < warper->x1 ) - warper->x2min = warper->x1; - - warper->w0 = warper->x2 - warper->x1; - - if ( warper->w0 <= 64 ) - { - warper->x1max = warper->x1; - warper->x2min = warper->x2; - } - - /* examine (at most) a pixel wide range around the natural width */ - warper->wmin = warper->x2min - warper->x1max; - warper->wmax = warper->x2max - warper->x1min; - -#if 1 - /* some heuristics to reduce the number of widths to be examined */ - { - int margin = 16; - - - if ( warper->w0 <= 128 ) - { - margin = 8; - if ( warper->w0 <= 96 ) - margin = 4; - } - - if ( warper->wmin < warper->w0 - margin ) - warper->wmin = warper->w0 - margin; - - if ( warper->wmax > warper->w0 + margin ) - warper->wmax = warper->w0 + margin; - } - - if ( warper->wmin < warper->w0 * 3 / 4 ) - warper->wmin = warper->w0 * 3 / 4; - - if ( warper->wmax > warper->w0 * 5 / 4 ) - warper->wmax = warper->w0 * 5 / 4; -#else - /* no scaling, just translation */ - warper->wmin = warper->wmax = warper->w0; -#endif - - for ( w = warper->wmin; w <= warper->wmax; w++ ) - { - FT_Fixed new_scale; - FT_Pos new_delta; - FT_Pos xx1, xx2; - - - /* compute min and max positions for given width, */ - /* assuring that they stay within the coordinate ranges */ - xx1 = warper->x1; - xx2 = warper->x2; - if ( w >= warper->w0 ) - { - xx1 -= w - warper->w0; - if ( xx1 < warper->x1min ) - { - xx2 += warper->x1min - xx1; - xx1 = warper->x1min; - } - } - else - { - xx1 -= w - warper->w0; - if ( xx1 > warper->x1max ) - { - xx2 -= xx1 - warper->x1max; - xx1 = warper->x1max; - } - } - - if ( xx1 < warper->x1 ) - base_distort = warper->x1 - xx1; - else - base_distort = xx1 - warper->x1; - - if ( xx2 < warper->x2 ) - base_distort += warper->x2 - xx2; - else - base_distort += xx2 - warper->x2; - - /* give base distortion a greater weight while scoring */ - base_distort *= 10; - - new_scale = org_scale + FT_DivFix( w - warper->w0, X2 - X1 ); - new_delta = xx1 - FT_MulFix( X1, new_scale ); - - af_warper_compute_line_best( warper, new_scale, new_delta, xx1, xx2, - base_distort, - segments, num_segments ); - } - - { - FT_Fixed best_scale = warper->best_scale; - FT_Pos best_delta = warper->best_delta; - - - hints->xmin_delta = FT_MulFix( X1, best_scale - org_scale ) - + best_delta; - hints->xmax_delta = FT_MulFix( X2, best_scale - org_scale ) - + best_delta; - - *a_scale = best_scale; - *a_delta = best_delta; - } - } - -#else /* !AF_CONFIG_OPTION_USE_WARPER */ - - /* ANSI C doesn't like empty source files */ - typedef int _af_warp_dummy; - -#endif /* !AF_CONFIG_OPTION_USE_WARPER */ - -/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afwarp.h b/lib/libesp32_lvgl/freetype/src/autofit/afwarp.h deleted file mode 100644 index cdea23e7d..000000000 --- a/lib/libesp32_lvgl/freetype/src/autofit/afwarp.h +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** - * - * afwarp.h - * - * Auto-fitter warping algorithm (specification). - * - * Copyright (C) 2006-2020 by - * David Turner, Robert Wilhelm, and Werner Lemberg. - * - * This file is part of the FreeType project, and may only be used, - * modified, and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - */ - - -#ifndef AFWARP_H_ -#define AFWARP_H_ - -#include "afhints.h" - -FT_BEGIN_HEADER - -#define AF_WARPER_SCALE - -#define AF_WARPER_FLOOR( x ) ( (x) & ~FT_TYPEOF( x )63 ) -#define AF_WARPER_CEIL( x ) AF_WARPER_FLOOR( (x) + 63 ) - - - typedef FT_Int32 AF_WarpScore; - - typedef struct AF_WarperRec_ - { - FT_Pos x1, x2; - FT_Pos t1, t2; - FT_Pos x1min, x1max; - FT_Pos x2min, x2max; - FT_Pos w0, wmin, wmax; - - FT_Fixed best_scale; - FT_Pos best_delta; - AF_WarpScore best_score; - AF_WarpScore best_distort; - - } AF_WarperRec, *AF_Warper; - - -#ifdef AF_CONFIG_OPTION_USE_WARPER - FT_LOCAL( void ) - af_warper_compute( AF_Warper warper, - AF_GlyphHints hints, - AF_Dimension dim, - FT_Fixed *a_scale, - FT_Pos *a_delta ); -#endif - - -FT_END_HEADER - - -#endif /* AFWARP_H_ */ - - -/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afwrtsys.h b/lib/libesp32_lvgl/freetype/src/autofit/afwrtsys.h deleted file mode 100644 index 3990633d2..000000000 --- a/lib/libesp32_lvgl/freetype/src/autofit/afwrtsys.h +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** - * - * afwrtsys.h - * - * Auto-fitter writing systems (specification only). - * - * Copyright (C) 2013-2020 by - * David Turner, Robert Wilhelm, and Werner Lemberg. - * - * This file is part of the FreeType project, and may only be used, - * modified, and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - */ - - -#ifndef AFWRTSYS_H_ -#define AFWRTSYS_H_ - - /* Since preprocessor directives can't create other preprocessor */ - /* directives, we have to include the header files manually. */ - -#include "afdummy.h" -#include "aflatin.h" -#include "afcjk.h" -#include "afindic.h" -#ifdef FT_OPTION_AUTOFIT2 -#include "aflatin2.h" -#endif - -#endif /* AFWRTSYS_H_ */ - - - /* The following part can be included multiple times. */ - /* Define `WRITING_SYSTEM' as needed. */ - - - /* Add new writing systems here. The arguments are the writing system */ - /* name in lowercase and uppercase, respectively. */ - - WRITING_SYSTEM( dummy, DUMMY ) - WRITING_SYSTEM( latin, LATIN ) - WRITING_SYSTEM( cjk, CJK ) - WRITING_SYSTEM( indic, INDIC ) -#ifdef FT_OPTION_AUTOFIT2 - WRITING_SYSTEM( latin2, LATIN2 ) -#endif - - -/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afws-decl.h b/lib/libesp32_lvgl/freetype/src/autofit/afws-decl.h new file mode 100644 index 000000000..48c888afe --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/autofit/afws-decl.h @@ -0,0 +1,33 @@ +/**************************************************************************** + * + * afws-decl.h + * + * Auto-fitter writing system declarations (specification only). + * + * Copyright (C) 2013-2023 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#ifndef AFWS_DECL_H_ +#define AFWS_DECL_H_ + + /* Since preprocessor directives can't create other preprocessor */ + /* directives, we have to include the header files manually. */ + +#include "afdummy.h" +#include "aflatin.h" +#include "afcjk.h" +#include "afindic.h" + +#endif /* AFWS_DECL_H_ */ + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/autofit/afws-iter.h b/lib/libesp32_lvgl/freetype/src/autofit/afws-iter.h new file mode 100644 index 000000000..a0a686f8c --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/autofit/afws-iter.h @@ -0,0 +1,31 @@ +/**************************************************************************** + * + * afws-iter.h + * + * Auto-fitter writing systems iterator (specification only). + * + * Copyright (C) 2013-2023 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + /* This header may be included multiple times. */ + /* Define `WRITING_SYSTEM' as needed. */ + + + /* Add new writing systems here. The arguments are the writing system */ + /* name in lowercase and uppercase, respectively. */ + + WRITING_SYSTEM( dummy, DUMMY ) + WRITING_SYSTEM( latin, LATIN ) + WRITING_SYSTEM( cjk, CJK ) + WRITING_SYSTEM( indic, INDIC ) + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/autofit/autofit.c b/lib/libesp32_lvgl/freetype/src/autofit/autofit.c index ef5e7f145..8bd609b5e 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/autofit.c +++ b/lib/libesp32_lvgl/freetype/src/autofit/autofit.c @@ -4,7 +4,7 @@ * * Auto-fitter module (body). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -18,7 +18,7 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT -#include "afangles.c" +#include "ft-hb.c" #include "afblue.c" #include "afcjk.c" #include "afdummy.c" @@ -26,12 +26,10 @@ #include "afhints.c" #include "afindic.c" #include "aflatin.c" -#include "aflatin2.c" #include "afloader.c" #include "afmodule.c" #include "afranges.c" #include "afshaper.c" -#include "afwarp.c" /* END */ diff --git a/lib/libesp32_lvgl/freetype/src/autofit/ft-hb.c b/lib/libesp32_lvgl/freetype/src/autofit/ft-hb.c new file mode 100644 index 000000000..71aee0455 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/autofit/ft-hb.c @@ -0,0 +1,115 @@ +/* + * Copyright © 2009, 2023 Red Hat, Inc. + * Copyright © 2015 Google, Inc. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod, Matthias Clasen + * Google Author(s): Behdad Esfahbod + */ + +#include +#include + +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ + +#include "ft-hb.h" + +/* The following three functions are a more or less verbatim + * copy of corresponding HarfBuzz code from hb-ft.cc + */ + +static hb_blob_t * +hb_ft_reference_table_ (hb_face_t *face, hb_tag_t tag, void *user_data) +{ + FT_Face ft_face = (FT_Face) user_data; + FT_Byte *buffer; + FT_ULong length = 0; + FT_Error error; + + FT_UNUSED (face); + + /* Note: FreeType like HarfBuzz uses the NONE tag for fetching the entire blob */ + + error = FT_Load_Sfnt_Table (ft_face, tag, 0, NULL, &length); + if (error) + return NULL; + + buffer = (FT_Byte *) ft_smalloc (length); + if (!buffer) + return NULL; + + error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length); + if (error) + { + free (buffer); + return NULL; + } + + return hb_blob_create ((const char *) buffer, length, + HB_MEMORY_MODE_WRITABLE, + buffer, ft_sfree); +} + +static hb_face_t * +hb_ft_face_create_ (FT_Face ft_face, + hb_destroy_func_t destroy) +{ + hb_face_t *face; + + if (!ft_face->stream->read) { + hb_blob_t *blob; + + blob = hb_blob_create ((const char *) ft_face->stream->base, + (unsigned int) ft_face->stream->size, + HB_MEMORY_MODE_READONLY, + ft_face, destroy); + face = hb_face_create (blob, ft_face->face_index); + hb_blob_destroy (blob); + } else { + face = hb_face_create_for_tables (hb_ft_reference_table_, ft_face, destroy); + } + + hb_face_set_index (face, ft_face->face_index); + hb_face_set_upem (face, ft_face->units_per_EM); + + return face; +} + +FT_LOCAL_DEF(hb_font_t *) +hb_ft_font_create_ (FT_Face ft_face, + hb_destroy_func_t destroy) +{ + hb_font_t *font; + hb_face_t *face; + + face = hb_ft_face_create_ (ft_face, destroy); + font = hb_font_create (face); + hb_face_destroy (face); + return font; +} + +#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */ + +/* ANSI C doesn't like empty source files */ +typedef int ft_hb_dummy_; + +#endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ */ + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/autofit/ft-hb.h b/lib/libesp32_lvgl/freetype/src/autofit/ft-hb.h new file mode 100644 index 000000000..92a5774bc --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/autofit/ft-hb.h @@ -0,0 +1,48 @@ +/* + * Copyright © 2009, 2023 Red Hat, Inc. + * Copyright © 2015 Google, Inc. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod, Matthias Clasen + * Google Author(s): Behdad Esfahbod + */ + +#ifndef FT_HB_H +#define FT_HB_H + +#include + +#include +#include + + +FT_BEGIN_HEADER + +FT_LOCAL(hb_font_t *) +hb_ft_font_create_ (FT_Face ft_face, + hb_destroy_func_t destroy); + + +FT_END_HEADER + +#endif /* FT_HB_H */ + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/autofit/module.mk b/lib/libesp32_lvgl/freetype/src/autofit/module.mk index c32781f47..95cb20ad2 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/module.mk +++ b/lib/libesp32_lvgl/freetype/src/autofit/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 2003-2020 by +# Copyright (C) 2003-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/autofit/rules.mk b/lib/libesp32_lvgl/freetype/src/autofit/rules.mk index 553ddce6b..a46ba3f0f 100644 --- a/lib/libesp32_lvgl/freetype/src/autofit/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/autofit/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 2003-2020 by +# Copyright (C) 2003-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, @@ -28,8 +28,7 @@ AUTOF_COMPILE := $(CC) $(ANSIFLAGS) \ # AUTOF driver sources (i.e., C files) # -AUTOF_DRV_SRC := $(AUTOF_DIR)/afangles.c \ - $(AUTOF_DIR)/afblue.c \ +AUTOF_DRV_SRC := $(AUTOF_DIR)/afblue.c \ $(AUTOF_DIR)/afcjk.c \ $(AUTOF_DIR)/afdummy.c \ $(AUTOF_DIR)/afglobal.c \ @@ -40,17 +39,18 @@ AUTOF_DRV_SRC := $(AUTOF_DIR)/afangles.c \ $(AUTOF_DIR)/afmodule.c \ $(AUTOF_DIR)/afranges.c \ $(AUTOF_DIR)/afshaper.c \ - $(AUTOF_DIR)/afwarp.c + $(AUTOF_DIR)/ft-hb.c # AUTOF driver headers # -AUTOF_DRV_H := $(AUTOF_DRV_SRC:%c=%h) \ - $(AUTOF_DIR)/afcover.h \ - $(AUTOF_DIR)/aferrors.h \ - $(AUTOF_DIR)/afscript.h \ - $(AUTOF_DIR)/afstyles.h \ - $(AUTOF_DIR)/aftypes.h \ - $(AUTOF_DIR)/afwrtsys.h +AUTOF_DRV_H := $(AUTOF_DRV_SRC:%c=%h) \ + $(AUTOF_DIR)/afcover.h \ + $(AUTOF_DIR)/aferrors.h \ + $(AUTOF_DIR)/afscript.h \ + $(AUTOF_DIR)/afstyles.h \ + $(AUTOF_DIR)/aftypes.h \ + $(AUTOF_DIR)/afws-decl.h \ + $(AUTOF_DIR)/afws-iter.h # AUTOF driver object(s) diff --git a/lib/libesp32_lvgl/freetype/src/base/ftadvanc.c b/lib/libesp32_lvgl/freetype/src/base/ftadvanc.c index c689e6a15..de25476fe 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftadvanc.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftadvanc.c @@ -4,7 +4,7 @@ * * Quick computation of advance widths (body). * - * Copyright (C) 2008-2020 by + * Copyright (C) 2008-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -23,7 +23,7 @@ static FT_Error - _ft_face_scale_advances( FT_Face face, + ft_face_scale_advances_( FT_Face face, FT_Fixed* advances, FT_UInt count, FT_Int32 flags ) @@ -96,7 +96,7 @@ error = func( face, gindex, 1, flags, padvance ); if ( !error ) - return _ft_face_scale_advances( face, padvance, 1, flags ); + return ft_face_scale_advances_( face, padvance, 1, flags ); if ( FT_ERR_NEQ( error, Unimplemented_Feature ) ) return error; @@ -142,7 +142,7 @@ { error = func( face, start, count, flags, padvances ); if ( !error ) - return _ft_face_scale_advances( face, padvances, count, flags ); + return ft_face_scale_advances_( face, padvances, count, flags ); if ( FT_ERR_NEQ( error, Unimplemented_Feature ) ) return error; diff --git a/lib/libesp32_lvgl/freetype/src/base/ftbase.c b/lib/libesp32_lvgl/freetype/src/base/ftbase.c index bfbaffd64..156510f00 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftbase.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftbase.c @@ -4,7 +4,7 @@ * * Single object library component (body only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/base/ftbase.h b/lib/libesp32_lvgl/freetype/src/base/ftbase.h index 25afa9bc3..00790d3b2 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftbase.h +++ b/lib/libesp32_lvgl/freetype/src/base/ftbase.h @@ -4,7 +4,7 @@ * * Private functions used in the `base' module (specification). * - * Copyright (C) 2008-2020 by + * Copyright (C) 2008-2023 by * David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. * * This file is part of the FreeType project, and may only be used, @@ -28,6 +28,7 @@ FT_BEGIN_HEADER FT_DECLARE_GLYPH( ft_bitmap_glyph_class ) FT_DECLARE_GLYPH( ft_outline_glyph_class ) + FT_DECLARE_GLYPH( ft_svg_glyph_class ) #ifdef FT_CONFIG_OPTION_MAC_FONTS diff --git a/lib/libesp32_lvgl/freetype/src/base/ftbbox.c b/lib/libesp32_lvgl/freetype/src/base/ftbbox.c index 30a4eba0b..385fea404 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftbbox.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftbbox.c @@ -4,7 +4,7 @@ * * FreeType bbox computation (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used @@ -82,10 +82,13 @@ * @Return: * Always 0. Needed for the interface only. */ - static int - BBox_Move_To( FT_Vector* to, - TBBox_Rec* user ) + FT_CALLBACK_DEF( int ) + BBox_Move_To( const FT_Vector* to, + void* user_ ) { + TBBox_Rec* user = (TBBox_Rec*)user_; + + FT_UPDATE_BBOX( to, user->bbox ); user->last = *to; @@ -116,10 +119,13 @@ * @Return: * Always 0. Needed for the interface only. */ - static int - BBox_Line_To( FT_Vector* to, - TBBox_Rec* user ) + FT_CALLBACK_DEF( int ) + BBox_Line_To( const FT_Vector* to, + void* user_ ) { + TBBox_Rec* user = (TBBox_Rec*)user_; + + user->last = *to; return 0; @@ -205,11 +211,14 @@ * In the case of a non-monotonous arc, we compute directly the * extremum coordinates, as it is sufficiently fast. */ - static int - BBox_Conic_To( FT_Vector* control, - FT_Vector* to, - TBBox_Rec* user ) + FT_CALLBACK_DEF( int ) + BBox_Conic_To( const FT_Vector* control, + const FT_Vector* to, + void* user_ ) { + TBBox_Rec* user = (TBBox_Rec*)user_; + + /* in case `to' is implicit and not included in bbox yet */ FT_UPDATE_BBOX( to, user->bbox ); @@ -410,12 +419,15 @@ * In the case of a non-monotonous arc, we don't compute directly * extremum coordinates, we subdivide instead. */ - static int - BBox_Cubic_To( FT_Vector* control1, - FT_Vector* control2, - FT_Vector* to, - TBBox_Rec* user ) + FT_CALLBACK_DEF( int ) + BBox_Cubic_To( const FT_Vector* control1, + const FT_Vector* control2, + const FT_Vector* to, + void* user_ ) { + TBBox_Rec* user = (TBBox_Rec*)user_; + + /* We don't need to check `to' since it is always an on-point, */ /* thus within the bbox. Only segments with an off-point outside */ /* the bbox can possibly reach new extreme values. */ diff --git a/lib/libesp32_lvgl/freetype/src/base/ftbdf.c b/lib/libesp32_lvgl/freetype/src/base/ftbdf.c index fc374c667..f697c00fe 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftbdf.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftbdf.c @@ -4,7 +4,7 @@ * * FreeType API for accessing BDF-specific strings (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/base/ftbitmap.c b/lib/libesp32_lvgl/freetype/src/base/ftbitmap.c index 584213ddc..1c93648dc 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftbitmap.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftbitmap.c @@ -4,7 +4,7 @@ * * FreeType utility functions for bitmaps (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -66,11 +66,8 @@ { FT_Memory memory; FT_Error error = FT_Err_Ok; - - FT_Int pitch; - FT_ULong size; - - FT_Int source_pitch_sign, target_pitch_sign; + FT_Int pitch; + FT_Int flip; if ( !library ) @@ -82,53 +79,29 @@ if ( source == target ) return FT_Err_Ok; - source_pitch_sign = source->pitch < 0 ? -1 : 1; - target_pitch_sign = target->pitch < 0 ? -1 : 1; - - if ( !source->buffer ) - { - *target = *source; - if ( source_pitch_sign != target_pitch_sign ) - target->pitch = -target->pitch; - - return FT_Err_Ok; - } + flip = ( source->pitch < 0 && target->pitch > 0 ) || + ( source->pitch > 0 && target->pitch < 0 ); memory = library->memory; - pitch = source->pitch; + FT_FREE( target->buffer ); + *target = *source; + + if ( flip ) + target->pitch = -target->pitch; + + if ( !source->buffer ) + return FT_Err_Ok; + + pitch = source->pitch; if ( pitch < 0 ) pitch = -pitch; - size = (FT_ULong)pitch * source->rows; - if ( target->buffer ) - { - FT_Int target_pitch = target->pitch; - FT_ULong target_size; - - - if ( target_pitch < 0 ) - target_pitch = -target_pitch; - target_size = (FT_ULong)target_pitch * target->rows; - - if ( target_size != size ) - (void)FT_QREALLOC( target->buffer, target_size, size ); - } - else - (void)FT_QALLOC( target->buffer, size ); + FT_MEM_QALLOC_MULT( target->buffer, target->rows, pitch ); if ( !error ) { - unsigned char *p; - - - p = target->buffer; - *target = *source; - target->buffer = p; - - if ( source_pitch_sign == target_pitch_sign ) - FT_MEM_COPY( target->buffer, source->buffer, size ); - else + if ( flip ) { /* take care of bitmap flow */ FT_UInt i; @@ -146,6 +119,9 @@ t -= pitch; } } + else + FT_MEM_COPY( target->buffer, source->buffer, + (FT_Long)source->rows * pitch ); } return error; @@ -480,7 +456,7 @@ * A gamma of 2.2 is fair to assume. And then, we need to * undo the premultiplication too. * - * https://accessibility.kde.org/hsl-adjusted.php + * http://www.brucelindbloom.com/index.html?WorkingSpaceInfo.html#SideNotes * * We do the computation with integers only, applying a gamma of 2.0. * We guarantee 32-bit arithmetic to avoid overflow but the resulting @@ -488,9 +464,9 @@ * */ - l = ( 4732UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] + - 46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] + - 13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2] ) >> 16; + l = ( 4731UL /* 0.072186 * 65536 */ * bgra[0] * bgra[0] + + 46868UL /* 0.715158 * 65536 */ * bgra[1] * bgra[1] + + 13937UL /* 0.212656 * 65536 */ * bgra[2] * bgra[2] ) >> 16; /* * Final transparency can be determined as follows. @@ -542,39 +518,31 @@ case FT_PIXEL_MODE_LCD_V: case FT_PIXEL_MODE_BGRA: { - FT_Int pad, old_target_pitch, target_pitch; - FT_ULong old_size; + FT_Int width = (FT_Int)source->width; + FT_Int neg = ( target->pitch == 0 && source->pitch < 0 ) || + target->pitch < 0; - old_target_pitch = target->pitch; - if ( old_target_pitch < 0 ) - old_target_pitch = -old_target_pitch; - - old_size = target->rows * (FT_UInt)old_target_pitch; + FT_Bitmap_Done( library, target ); target->pixel_mode = FT_PIXEL_MODE_GRAY; target->rows = source->rows; target->width = source->width; - pad = 0; - if ( alignment > 0 ) + if ( alignment ) { - pad = (FT_Int)source->width % alignment; - if ( pad != 0 ) - pad = alignment - pad; + FT_Int rem = width % alignment; + + + if ( rem ) + width = alignment > 0 ? width - rem + alignment + : width - rem - alignment; } - target_pitch = (FT_Int)source->width + pad; - - if ( target_pitch > 0 && - (FT_ULong)target->rows > FT_ULONG_MAX / (FT_ULong)target_pitch ) - return FT_THROW( Invalid_Argument ); - - if ( FT_QREALLOC( target->buffer, - old_size, target->rows * (FT_UInt)target_pitch ) ) + if ( FT_QALLOC_MULT( target->buffer, target->rows, width ) ) return error; - target->pitch = target->pitch < 0 ? -target_pitch : target_pitch; + target->pitch = neg ? -width : width; } break; @@ -907,8 +875,8 @@ final_rows = ( final_ury - final_lly ) >> 6; #ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE5(( "FT_Bitmap_Blend:\n" - " source bitmap: (%ld, %ld) -- (%ld, %ld); %d x %d\n", + FT_TRACE5(( "FT_Bitmap_Blend:\n" )); + FT_TRACE5(( " source bitmap: (%ld, %ld) -- (%ld, %ld); %d x %d\n", source_llx / 64, source_lly / 64, source_urx / 64, source_ury / 64, source_->width, source_->rows )); diff --git a/lib/libesp32_lvgl/freetype/src/base/ftcalc.c b/lib/libesp32_lvgl/freetype/src/base/ftcalc.c index b5258c85a..c5bc7e3b1 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftcalc.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftcalc.c @@ -4,7 +4,7 @@ * * Arithmetic computations (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -45,7 +45,7 @@ /* we need to emulate a 64-bit data type if a real one isn't available */ -#ifndef FT_LONG64 +#ifndef FT_INT64 typedef struct FT_Int64_ { @@ -54,7 +54,7 @@ } FT_Int64; -#endif /* !FT_LONG64 */ +#endif /* !FT_INT64 */ /************************************************************************** @@ -79,7 +79,7 @@ FT_END_STMNT /* The following three functions are available regardless of whether */ - /* FT_LONG64 is defined. */ + /* FT_INT64 is defined. */ /* documentation is in freetype.h */ @@ -109,7 +109,7 @@ #ifndef FT_MSB - FT_BASE_DEF ( FT_Int ) + FT_BASE_DEF( FT_Int ) FT_MSB( FT_UInt32 z ) { FT_Int shift = 0; @@ -164,7 +164,7 @@ } -#ifdef FT_LONG64 +#ifdef FT_INT64 /* documentation is in freetype.h */ @@ -272,7 +272,7 @@ } -#else /* !FT_LONG64 */ +#else /* !FT_INT64 */ static void @@ -651,7 +651,7 @@ } -#endif /* !FT_LONG64 */ +#endif /* !FT_INT64 */ /* documentation is in ftglyph.h */ @@ -749,65 +749,43 @@ FT_BASE_DEF( FT_Bool ) FT_Matrix_Check( const FT_Matrix* matrix ) { - FT_Matrix m; - FT_Fixed val[4]; - FT_Fixed nonzero_minval, maxval; - FT_Fixed temp1, temp2; - FT_UInt i; + FT_Fixed xx, xy, yx, yy; + FT_Fixed val; + FT_Int shift; + FT_ULong temp1, temp2; if ( !matrix ) return 0; - val[0] = FT_ABS( matrix->xx ); - val[1] = FT_ABS( matrix->xy ); - val[2] = FT_ABS( matrix->yx ); - val[3] = FT_ABS( matrix->yy ); + xx = matrix->xx; + xy = matrix->xy; + yx = matrix->yx; + yy = matrix->yy; + val = FT_ABS( xx ) | FT_ABS( xy ) | FT_ABS( yx ) | FT_ABS( yy ); - /* - * To avoid overflow, we ensure that each value is not larger than - * - * int(sqrt(2^31 / 4)) = 23170 ; - * - * we also check that no value becomes zero if we have to scale. - */ - - maxval = 0; - nonzero_minval = FT_LONG_MAX; - - for ( i = 0; i < 4; i++ ) - { - if ( val[i] > maxval ) - maxval = val[i]; - if ( val[i] && val[i] < nonzero_minval ) - nonzero_minval = val[i]; - } - - /* we only handle 32bit values */ - if ( maxval > 0x7FFFFFFFL ) + /* we only handle non-zero 32-bit values */ + if ( !val || val > 0x7FFFFFFFL ) return 0; - if ( maxval > 23170 ) + /* Scale matrix to avoid the temp1 overflow, which is */ + /* more stringent than avoiding the temp2 overflow. */ + + shift = FT_MSB( val ) - 12; + + if ( shift > 0 ) { - FT_Fixed scale = FT_DivFix( maxval, 23170 ); - - - if ( !FT_DivFix( nonzero_minval, scale ) ) - return 0; /* value range too large */ - - m.xx = FT_DivFix( matrix->xx, scale ); - m.xy = FT_DivFix( matrix->xy, scale ); - m.yx = FT_DivFix( matrix->yx, scale ); - m.yy = FT_DivFix( matrix->yy, scale ); + xx >>= shift; + xy >>= shift; + yx >>= shift; + yy >>= shift; } - else - m = *matrix; - temp1 = FT_ABS( m.xx * m.yy - m.xy * m.yx ); - temp2 = m.xx * m.xx + m.xy * m.xy + m.yx * m.yx + m.yy * m.yy; + temp1 = 32U * (FT_ULong)FT_ABS( xx * yy - xy * yx ); + temp2 = (FT_ULong)( xx * xx ) + (FT_ULong)( xy * xy ) + + (FT_ULong)( yx * yx ) + (FT_ULong)( yy * yy ); - if ( temp1 == 0 || - temp2 / temp1 > 50 ) + if ( temp1 <= temp2 ) return 0; return 1; @@ -985,7 +963,7 @@ /* we silently ignore overflow errors since such large values */ /* lead to even more (harmless) rendering errors later on */ -#ifdef FT_LONG64 +#ifdef FT_INT64 FT_Int64 delta = SUB_INT64( MUL_INT64( in_x, out_y ), MUL_INT64( in_y, out_x ) ); @@ -1061,7 +1039,7 @@ /* */ /* This approach has the advantage that the angle between */ /* `in' and `out' is not checked. In case one of the two */ - /* vectors is `dominant', this is, much larger than the */ + /* vectors is `dominant', that is, much larger than the */ /* other vector, we thus always have a flat corner. */ /* */ /* hypotenuse */ @@ -1085,4 +1063,65 @@ } + FT_BASE_DEF( FT_Int32 ) + FT_MulAddFix( FT_Fixed* s, + FT_Int32* f, + FT_UInt count ) + { + FT_UInt i; + FT_Int64 temp; + + +#ifdef FT_INT64 + temp = 0; + + for ( i = 0; i < count; ++i ) + temp += (FT_Int64)s[i] * f[i]; + + return (FT_Int32)( ( temp + 0x8000 ) >> 16 ); +#else + temp.hi = 0; + temp.lo = 0; + + for ( i = 0; i < count; ++i ) + { + FT_Int64 multResult; + + FT_Int sign = 1; + FT_UInt32 carry = 0; + + FT_UInt32 scalar; + FT_UInt32 factor; + + + scalar = (FT_UInt32)s[i]; + factor = (FT_UInt32)f[i]; + + FT_MOVE_SIGN( s[i], scalar, sign ); + FT_MOVE_SIGN( f[i], factor, sign ); + + ft_multo64( scalar, factor, &multResult ); + + if ( sign < 0 ) + { + /* Emulated `FT_Int64` negation. */ + carry = ( multResult.lo == 0 ); + + multResult.lo = ~multResult.lo + 1; + multResult.hi = ~multResult.hi + carry; + } + + FT_Add64( &temp, &multResult, &temp ); + } + + /* Shift and round value. */ + return (FT_Int32)( ( ( temp.hi << 16 ) | ( temp.lo >> 16 ) ) + + ( 1 & ( temp.lo >> 15 ) ) ); + + +#endif /* !FT_INT64 */ + + } + + /* END */ diff --git a/lib/libesp32_lvgl/freetype/src/base/ftcid.c b/lib/libesp32_lvgl/freetype/src/base/ftcid.c index ce8a876ad..866cd23e9 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftcid.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftcid.c @@ -4,7 +4,7 @@ * * FreeType API for accessing CID font information. * - * Copyright (C) 2007-2020 by + * Copyright (C) 2007-2023 by * Derek Clegg and Michael Toftdal. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/base/ftcolor.c b/lib/libesp32_lvgl/freetype/src/base/ftcolor.c index a50d68009..bcd6e893d 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftcolor.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftcolor.c @@ -4,7 +4,7 @@ * * FreeType's glyph color management (body). * - * Copyright (C) 2018-2020 by + * Copyright (C) 2018-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/base/ftdbgmem.c b/lib/libesp32_lvgl/freetype/src/base/ftdbgmem.c index eb0d65160..8fab50dd0 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftdbgmem.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftdbgmem.c @@ -4,7 +4,7 @@ * * Memory debugger (body). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -35,8 +35,8 @@ #include FT_CONFIG_STANDARD_LIBRARY_H - FT_BASE_DEF( const char* ) _ft_debug_file = NULL; - FT_BASE_DEF( long ) _ft_debug_lineno = 0; + FT_BASE_DEF( const char* ) ft_debug_file_ = NULL; + FT_BASE_DEF( long ) ft_debug_lineno_ = 0; extern void FT_DumpMemory( FT_Memory memory ); @@ -302,46 +302,6 @@ } - static FT_MemTable - ft_mem_table_new( FT_Memory memory ) - { - FT_MemTable table; - - - table = (FT_MemTable)memory->alloc( memory, sizeof ( *table ) ); - if ( !table ) - goto Exit; - - FT_ZERO( table ); - - table->size = FT_MEM_SIZE_MIN; - table->nodes = 0; - - table->memory = memory; - - table->memory_user = memory->user; - - table->alloc = memory->alloc; - table->realloc = memory->realloc; - table->free = memory->free; - - table->buckets = (FT_MemNode *) - memory->alloc( - memory, - table->size * (FT_Long)sizeof ( FT_MemNode ) ); - if ( table->buckets ) - FT_ARRAY_ZERO( table->buckets, table->size ); - else - { - memory->free( memory, table ); - table = NULL; - } - - Exit: - return table; - } - - static void ft_mem_table_destroy( FT_MemTable table ) { @@ -350,8 +310,6 @@ FT_Long leaks = 0; - FT_DumpMemory( table->memory ); - /* remove all blocks from the table, revealing leaked ones */ for ( i = 0; i < table->size; i++ ) { @@ -413,8 +371,6 @@ printf( "FreeType: maximum memory footprint = %ld\n", table->alloc_max ); - ft_mem_table_free( table, table ); - if ( leak_count > 0 ) ft_mem_debug_panic( "FreeType: %ld bytes of memory leaked in %ld blocks\n", @@ -459,8 +415,8 @@ /* cast to FT_PtrDist first since void* can be larger */ /* than FT_UInt32 and GCC 4.1.1 emits a warning */ - hash = (FT_UInt32)(FT_PtrDist)(void*)_ft_debug_file + - (FT_UInt32)( 5 * _ft_debug_lineno ); + hash = (FT_UInt32)(FT_PtrDist)(void*)ft_debug_file_ + + (FT_UInt32)( 5 * ft_debug_lineno_ ); pnode = &table->sources[hash % FT_MEM_SOURCE_BUCKETS]; for (;;) @@ -469,8 +425,8 @@ if ( !node ) break; - if ( node->file_name == _ft_debug_file && - node->line_no == _ft_debug_lineno ) + if ( node->file_name == ft_debug_file_ && + node->line_no == ft_debug_lineno_ ) goto Exit; pnode = &node->link; @@ -481,8 +437,8 @@ ft_mem_debug_panic( "not enough memory to perform memory debugging\n" ); - node->file_name = _ft_debug_file; - node->line_no = _ft_debug_lineno; + node->file_name = ft_debug_file_; + node->line_no = ft_debug_lineno_; node->cur_blocks = 0; node->max_blocks = 0; @@ -539,7 +495,7 @@ "org=%s:%d new=%s:%d\n", node->address, node->size, FT_FILENAME( node->source->file_name ), node->source->line_no, - FT_FILENAME( _ft_debug_file ), _ft_debug_lineno ); + FT_FILENAME( ft_debug_file_ ), ft_debug_lineno_ ); } } @@ -626,7 +582,7 @@ " Block was allocated at (%s:%ld)\n" " and released at (%s:%ld).", address, - FT_FILENAME( _ft_debug_file ), _ft_debug_lineno, + FT_FILENAME( ft_debug_file_ ), ft_debug_lineno_, FT_FILENAME( node->source->file_name ), node->source->line_no, FT_FILENAME( node->free_file_name ), node->free_line_no ); @@ -648,8 +604,8 @@ /* we simply invert the node's size to indicate that the node */ /* was freed. */ node->size = -node->size; - node->free_file_name = _ft_debug_file; - node->free_line_no = _ft_debug_lineno; + node->free_file_name = ft_debug_file_; + node->free_line_no = ft_debug_lineno_; } else { @@ -671,7 +627,7 @@ ft_mem_debug_panic( "trying to free unknown block at %p in (%s:%ld)\n", address, - FT_FILENAME( _ft_debug_file ), _ft_debug_lineno ); + FT_FILENAME( ft_debug_file_ ), ft_debug_lineno_ ); } } @@ -705,8 +661,8 @@ table->alloc_count++; } - _ft_debug_file = ""; - _ft_debug_lineno = 0; + ft_debug_file_ = ""; + ft_debug_lineno_ = 0; return (FT_Pointer)block; } @@ -721,8 +677,8 @@ if ( !block ) ft_mem_debug_panic( "trying to free NULL in (%s:%ld)", - FT_FILENAME( _ft_debug_file ), - _ft_debug_lineno ); + FT_FILENAME( ft_debug_file_ ), + ft_debug_lineno_ ); ft_mem_table_remove( table, (FT_Byte*)block, 0 ); @@ -731,8 +687,8 @@ table->alloc_count--; - _ft_debug_file = ""; - _ft_debug_lineno = 0; + ft_debug_file_ = ""; + ft_debug_lineno_ = 0; } @@ -747,8 +703,8 @@ FT_Pointer new_block; FT_Long delta; - const char* file_name = FT_FILENAME( _ft_debug_file ); - FT_Long line_no = _ft_debug_lineno; + const char* file_name = FT_FILENAME( ft_debug_file_ ); + FT_Long line_no = ft_debug_lineno_; /* unlikely, but possible */ @@ -811,8 +767,8 @@ ft_mem_table_remove( table, (FT_Byte*)block, delta ); - _ft_debug_file = ""; - _ft_debug_lineno = 0; + ft_debug_file_ = ""; + ft_debug_lineno_ = 0; if ( !table->keep_alive ) ft_mem_table_free( table, block ); @@ -821,17 +777,30 @@ } - extern FT_Int + extern void ft_mem_debug_init( FT_Memory memory ) { FT_MemTable table; - FT_Int result = 0; - if ( ft_getenv( "FT2_DEBUG_MEMORY" ) ) + if ( !ft_getenv( "FT2_DEBUG_MEMORY" ) ) + return; + + table = (FT_MemTable)memory->alloc( memory, sizeof ( *table ) ); + + if ( table ) { - table = ft_mem_table_new( memory ); - if ( table ) + FT_ZERO( table ); + + table->memory = memory; + table->memory_user = memory->user; + table->alloc = memory->alloc; + table->realloc = memory->realloc; + table->free = memory->free; + + ft_mem_table_resize( table ); + + if ( table->size ) { const char* p; @@ -876,33 +845,36 @@ if ( keep_alive > 0 ) table->keep_alive = 1; } - - result = 1; } + else + memory->free( memory, table ); } - return result; } extern void ft_mem_debug_done( FT_Memory memory ) { - FT_MemTable table = (FT_MemTable)memory->user; - - - if ( table ) + if ( memory->free == ft_mem_debug_free ) { + FT_MemTable table = (FT_MemTable)memory->user; + + + FT_DumpMemory( memory ); + + ft_mem_table_destroy( table ); + memory->free = table->free; memory->realloc = table->realloc; memory->alloc = table->alloc; + memory->user = table->memory_user; - ft_mem_table_destroy( table ); - memory->user = NULL; + memory->free( memory, table ); } } - static int + FT_COMPARE_DEF( int ) ft_mem_source_compare( const void* p1, const void* p2 ) { @@ -922,11 +894,9 @@ extern void FT_DumpMemory( FT_Memory memory ) { - FT_MemTable table = (FT_MemTable)memory->user; - - - if ( table ) + if ( memory->free == ft_mem_debug_free ) { + FT_MemTable table = (FT_MemTable)memory->user; FT_MemSource* bucket = table->sources; FT_MemSource* limit = bucket + FT_MEM_SOURCE_BUCKETS; FT_MemSource* sources; @@ -993,7 +963,7 @@ #else /* !FT_DEBUG_MEMORY */ /* ANSI C doesn't like empty source files */ - typedef int _debug_mem_dummy; + typedef int debug_mem_dummy_; #endif /* !FT_DEBUG_MEMORY */ diff --git a/lib/libesp32_lvgl/freetype/src/base/ftdebug.c b/lib/libesp32_lvgl/freetype/src/base/ftdebug.c index 62cf680b0..61c4563b0 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftdebug.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftdebug.c @@ -4,7 +4,7 @@ * * Debugging and logging component (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -42,7 +42,53 @@ #include +#include #include +#include + + +#ifdef FT_DEBUG_LOGGING + + /************************************************************************** + * + * Variables used to control logging. + * + * 1. `ft_default_trace_level` stores the value of trace levels, which are + * provided to FreeType using the `FT2_DEBUG` environment variable. + * + * 2. `ft_fileptr` stores the `FILE*` handle. + * + * 3. `ft_component` is a string that holds the name of `FT_COMPONENT`. + * + * 4. The flag `ft_component_flag` prints the name of `FT_COMPONENT` along + * with the actual log message if set to true. + * + * 5. The flag `ft_timestamp_flag` prints time along with the actual log + * message if set to ture. + * + * 6. `ft_have_newline_char` is used to differentiate between a log + * message with and without a trailing newline character. + * + * 7. `ft_custom_trace_level` stores the custom trace level value, which + * is provided by the user at run-time. + * + * We use `static` to avoid 'unused variable' warnings. + * + */ + static const char* ft_default_trace_level = NULL; + static FILE* ft_fileptr = NULL; + static const char* ft_component = NULL; + static FT_Bool ft_component_flag = FALSE; + static FT_Bool ft_timestamp_flag = FALSE; + static FT_Bool ft_have_newline_char = TRUE; + static const char* ft_custom_trace_level = NULL; + + /* declared in ftdebug.h */ + + dlg_handler ft_default_log_handler = NULL; + FT_Custom_Log_Handler custom_output_handler = NULL; + +#endif /* FT_DEBUG_LOGGING */ #ifdef FT_DEBUG_LEVEL_ERROR @@ -106,7 +152,6 @@ #endif /* FT_DEBUG_LEVEL_ERROR */ - #ifdef FT_DEBUG_LEVEL_TRACE /* array of trace levels, initialized to 0; */ @@ -195,9 +240,18 @@ FT_BASE_DEF( void ) ft_debug_init( void ) { - const char* ft2_debug = ft_getenv( "FT2_DEBUG" ); + const char* ft2_debug = NULL; +#ifdef FT_DEBUG_LOGGING + if ( ft_custom_trace_level != NULL ) + ft2_debug = ft_custom_trace_level; + else + ft2_debug = ft_default_trace_level; +#else + ft2_debug = ft_getenv( "FT2_DEBUG" ); +#endif + if ( ft2_debug ) { const char* p = ft2_debug; @@ -210,6 +264,49 @@ if ( *p == ' ' || *p == '\t' || *p == ',' || *p == ';' || *p == '=' ) continue; +#ifdef FT_DEBUG_LOGGING + + /* check extra arguments for logging */ + if ( *p == '-' ) + { + const char* r = ++p; + + + if ( *r == 'v' ) + { + const char* s = ++r; + + + ft_component_flag = TRUE; + + if ( *s == 't' ) + { + ft_timestamp_flag = TRUE; + p++; + } + + p++; + } + + else if ( *r == 't' ) + { + const char* s = ++r; + + + ft_timestamp_flag = TRUE; + + if ( *s == 'v' ) + { + ft_component_flag = TRUE; + p++; + } + + p++; + } + } + +#endif /* FT_DEBUG_LOGGING */ + /* read toggle name, followed by ':' */ q = p; while ( *p && *p != ':' ) @@ -311,8 +408,237 @@ /* nothing */ } - #endif /* !FT_DEBUG_LEVEL_TRACE */ +#ifdef FT_DEBUG_LOGGING + + /************************************************************************** + * + * Initialize and de-initialize 'dlg' library. + * + */ + + FT_BASE_DEF( void ) + ft_logging_init( void ) + { + ft_default_log_handler = ft_log_handler; + ft_default_trace_level = ft_getenv( "FT2_DEBUG" ); + + if ( ft_getenv( "FT_LOGGING_FILE" ) ) + ft_fileptr = ft_fopen( ft_getenv( "FT_LOGGING_FILE" ), "w" ); + else + ft_fileptr = stderr; + + ft_debug_init(); + + /* Set the default output handler for 'dlg'. */ + dlg_set_handler( ft_default_log_handler, NULL ); + } + + + FT_BASE_DEF( void ) + ft_logging_deinit( void ) + { + if ( ft_fileptr != stderr ) + ft_fclose( ft_fileptr ); + } + + + /************************************************************************** + * + * An output log handler for FreeType. + * + */ + FT_BASE_DEF( void ) + ft_log_handler( const struct dlg_origin* origin, + const char* string, + void* data ) + { + char features_buf[128]; + char* bufp = features_buf; + + FT_UNUSED( data ); + + + if ( ft_have_newline_char ) + { + const char* features = NULL; + size_t features_length = 0; + + +#define FEATURES_TIMESTAMP "[%h:%m] " +#define FEATURES_COMPONENT "[%t] " +#define FEATURES_TIMESTAMP_COMPONENT "[%h:%m %t] " + + if ( ft_timestamp_flag && ft_component_flag ) + { + features = FEATURES_TIMESTAMP_COMPONENT; + features_length = sizeof ( FEATURES_TIMESTAMP_COMPONENT ); + } + else if ( ft_timestamp_flag ) + { + features = FEATURES_TIMESTAMP; + features_length = sizeof ( FEATURES_TIMESTAMP ); + } + else if ( ft_component_flag ) + { + features = FEATURES_COMPONENT; + features_length = sizeof ( FEATURES_COMPONENT ); + } + + if ( ft_component_flag || ft_timestamp_flag ) + { + ft_strncpy( features_buf, features, features_length ); + bufp += features_length - 1; + } + + if ( ft_component_flag ) + { + size_t tag_length = ft_strlen( *origin->tags ); + size_t i; + + + /* To vertically align tracing messages we compensate the */ + /* different FT_COMPONENT string lengths by inserting an */ + /* appropriate amount of space characters. */ + for ( i = 0; + i < FT_MAX_TRACE_LEVEL_LENGTH - tag_length; + i++ ) + *bufp++ = ' '; + } + } + + /* Finally add the format string for the tracing message. */ + *bufp++ = '%'; + *bufp++ = 'c'; + *bufp = '\0'; + + dlg_generic_outputf_stream( ft_fileptr, + (const char*)features_buf, + origin, + string, + dlg_default_output_styles, + true ); + + if ( ft_strrchr( string, '\n' ) ) + ft_have_newline_char = TRUE; + else + ft_have_newline_char = FALSE; + } + + + /* documentation is in ftdebug.h */ + FT_BASE_DEF( void ) + ft_add_tag( const char* tag ) + { + ft_component = tag; + + dlg_add_tag( tag, NULL ); + } + + + /* documentation is in ftdebug.h */ + FT_BASE_DEF( void ) + ft_remove_tag( const char* tag ) + { + dlg_remove_tag( tag, NULL ); + } + + + /* documentation is in ftlogging.h */ + + FT_EXPORT_DEF( void ) + FT_Trace_Set_Level( const char* level ) + { + ft_component_flag = FALSE; + ft_timestamp_flag = FALSE; + ft_custom_trace_level = level; + + ft_debug_init(); + } + + + /* documentation is in ftlogging.h */ + + FT_EXPORT_DEF( void ) + FT_Trace_Set_Default_Level( void ) + { + ft_component_flag = FALSE; + ft_timestamp_flag = FALSE; + ft_custom_trace_level = NULL; + + ft_debug_init(); + } + + + /************************************************************************** + * + * Functions to handle a custom log handler. + * + */ + + /* documentation is in ftlogging.h */ + + FT_EXPORT_DEF( void ) + FT_Set_Log_Handler( FT_Custom_Log_Handler handler ) + { + custom_output_handler = handler; + } + + + /* documentation is in ftlogging.h */ + + FT_EXPORT_DEF( void ) + FT_Set_Default_Log_Handler( void ) + { + custom_output_handler = NULL; + } + + + /* documentation is in ftdebug.h */ + FT_BASE_DEF( void ) + FT_Logging_Callback( const char* fmt, + ... ) + { + va_list ap; + + + va_start( ap, fmt ); + custom_output_handler( ft_component, fmt, ap ); + va_end( ap ); + } + +#else /* !FT_DEBUG_LOGGING */ + + FT_EXPORT_DEF( void ) + FT_Trace_Set_Level( const char* level ) + { + FT_UNUSED( level ); + } + + + FT_EXPORT_DEF( void ) + FT_Trace_Set_Default_Level( void ) + { + /* nothing */ + } + + + FT_EXPORT_DEF( void ) + FT_Set_Log_Handler( FT_Custom_Log_Handler handler ) + { + FT_UNUSED( handler ); + } + + + FT_EXPORT_DEF( void ) + FT_Set_Default_Log_Handler( void ) + { + /* nothing */ + } + +#endif /* !FT_DEBUG_LOGGING */ + + /* END */ diff --git a/lib/libesp32_lvgl/freetype/src/base/fterrors.c b/lib/libesp32_lvgl/freetype/src/base/fterrors.c index eba9e7656..5ad9709c8 100644 --- a/lib/libesp32_lvgl/freetype/src/base/fterrors.c +++ b/lib/libesp32_lvgl/freetype/src/base/fterrors.c @@ -4,7 +4,7 @@ * * FreeType API for error code handling. * - * Copyright (C) 2018-2020 by + * Copyright (C) 2018-2023 by * Armin Hasitzka, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/base/ftfntfmt.c b/lib/libesp32_lvgl/freetype/src/base/ftfntfmt.c index a45317e79..0b41f7cc8 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftfntfmt.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftfntfmt.c @@ -4,7 +4,7 @@ * * FreeType utility file for font formats (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/base/ftfstype.c b/lib/libesp32_lvgl/freetype/src/base/ftfstype.c index bca548fc5..ea24e64c6 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftfstype.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftfstype.c @@ -4,7 +4,7 @@ * * FreeType utility file to access FSType data (body). * - * Copyright (C) 2008-2020 by + * Copyright (C) 2008-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/base/ftgasp.c b/lib/libesp32_lvgl/freetype/src/base/ftgasp.c index eed05a326..29b7b08b7 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftgasp.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftgasp.c @@ -4,7 +4,7 @@ * * Access of TrueType's `gasp' table (body). * - * Copyright (C) 2007-2020 by + * Copyright (C) 2007-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/base/ftgloadr.c b/lib/libesp32_lvgl/freetype/src/base/ftgloadr.c index 05fc7692b..9823d09e4 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftgloadr.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftgloadr.c @@ -4,7 +4,7 @@ * * The FreeType glyph loader (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg * * This file is part of the FreeType project, and may only be used, @@ -212,12 +212,12 @@ FT_Outline* current = &loader->current.outline; FT_Bool adjust = 0; - FT_UInt new_max, old_max; + FT_UInt new_max, old_max, min_new_max; error = FT_GlyphLoader_CreateExtra( loader ); if ( error ) - return error; + goto Exit; /* check points & tags */ new_max = (FT_UInt)base->n_points + (FT_UInt)current->n_points + @@ -226,10 +226,18 @@ if ( new_max > old_max ) { - new_max = FT_PAD_CEIL( new_max, 8 ); - if ( new_max > FT_OUTLINE_POINTS_MAX ) - return FT_THROW( Array_Too_Large ); + { + error = FT_THROW( Array_Too_Large ); + goto Exit; + } + + min_new_max = old_max + ( old_max >> 1 ); + if ( new_max < min_new_max ) + new_max = min_new_max; + new_max = FT_PAD_CEIL( new_max, 8 ); + if ( new_max > FT_OUTLINE_POINTS_MAX ) + new_max = FT_OUTLINE_POINTS_MAX; if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) || FT_RENEW_ARRAY( base->tags, old_max, new_max ) ) @@ -254,7 +262,7 @@ error = FT_GlyphLoader_CreateExtra( loader ); if ( error ) - return error; + goto Exit; /* check contours */ old_max = loader->max_contours; @@ -262,10 +270,18 @@ n_contours; if ( new_max > old_max ) { - new_max = FT_PAD_CEIL( new_max, 4 ); - if ( new_max > FT_OUTLINE_CONTOURS_MAX ) - return FT_THROW( Array_Too_Large ); + { + error = FT_THROW( Array_Too_Large ); + goto Exit; + } + + min_new_max = old_max + ( old_max >> 1 ); + if ( new_max < min_new_max ) + new_max = min_new_max; + new_max = FT_PAD_CEIL( new_max, 4 ); + if ( new_max > FT_OUTLINE_CONTOURS_MAX ) + new_max = FT_OUTLINE_CONTOURS_MAX; if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) ) goto Exit; diff --git a/lib/libesp32_lvgl/freetype/src/base/ftglyph.c b/lib/libesp32_lvgl/freetype/src/base/ftglyph.c index 825eba2c4..393d4949f 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftglyph.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftglyph.c @@ -4,7 +4,7 @@ * * FreeType convenience functions to handle glyphs (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -34,6 +34,7 @@ #include #include #include +#include #include "ftbase.h" @@ -277,6 +278,240 @@ ) +#ifdef FT_CONFIG_OPTION_SVG + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** FT_SvgGlyph support ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_CALLBACK_DEF( FT_Error ) + ft_svg_glyph_init( FT_Glyph svg_glyph, + FT_GlyphSlot slot ) + { + FT_ULong doc_length; + FT_SVG_Document document; + FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph; + + FT_Error error = FT_Err_Ok; + FT_Memory memory = FT_GLYPH( glyph )->library->memory; + + + if ( slot->format != FT_GLYPH_FORMAT_SVG ) + { + error = FT_THROW( Invalid_Glyph_Format ); + goto Exit; + } + + if ( slot->other == NULL ) + { + error = FT_THROW( Invalid_Slot_Handle ); + goto Exit; + } + + document = (FT_SVG_Document)slot->other; + + if ( document->svg_document_length == 0 ) + { + error = FT_THROW( Invalid_Slot_Handle ); + goto Exit; + } + + /* allocate a new document */ + doc_length = document->svg_document_length; + if ( FT_QALLOC( glyph->svg_document, doc_length ) ) + goto Exit; + glyph->svg_document_length = doc_length; + + glyph->glyph_index = slot->glyph_index; + + glyph->metrics = document->metrics; + glyph->units_per_EM = document->units_per_EM; + + glyph->start_glyph_id = document->start_glyph_id; + glyph->end_glyph_id = document->end_glyph_id; + + glyph->transform = document->transform; + glyph->delta = document->delta; + + /* copy the document into glyph */ + FT_MEM_COPY( glyph->svg_document, document->svg_document, doc_length ); + + Exit: + return error; + } + + + FT_CALLBACK_DEF( void ) + ft_svg_glyph_done( FT_Glyph svg_glyph ) + { + FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph; + FT_Memory memory = svg_glyph->library->memory; + + + /* just free the memory */ + FT_FREE( glyph->svg_document ); + } + + + FT_CALLBACK_DEF( FT_Error ) + ft_svg_glyph_copy( FT_Glyph svg_source, + FT_Glyph svg_target ) + { + FT_SvgGlyph source = (FT_SvgGlyph)svg_source; + FT_SvgGlyph target = (FT_SvgGlyph)svg_target; + + FT_Error error = FT_Err_Ok; + FT_Memory memory = FT_GLYPH( source )->library->memory; + + + if ( svg_source->format != FT_GLYPH_FORMAT_SVG ) + { + error = FT_THROW( Invalid_Glyph_Format ); + goto Exit; + } + + if ( source->svg_document_length == 0 ) + { + error = FT_THROW( Invalid_Slot_Handle ); + goto Exit; + } + + target->glyph_index = source->glyph_index; + + target->svg_document_length = source->svg_document_length; + + target->metrics = source->metrics; + target->units_per_EM = source->units_per_EM; + + target->start_glyph_id = source->start_glyph_id; + target->end_glyph_id = source->end_glyph_id; + + target->transform = source->transform; + target->delta = source->delta; + + /* allocate space for the SVG document */ + if ( FT_QALLOC( target->svg_document, target->svg_document_length ) ) + goto Exit; + + /* copy the document */ + FT_MEM_COPY( target->svg_document, + source->svg_document, + target->svg_document_length ); + + Exit: + return error; + } + + + FT_CALLBACK_DEF( void ) + ft_svg_glyph_transform( FT_Glyph svg_glyph, + const FT_Matrix* _matrix, + const FT_Vector* _delta ) + { + FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph; + FT_Matrix* matrix = (FT_Matrix*)_matrix; + FT_Vector* delta = (FT_Vector*)_delta; + + FT_Matrix tmp_matrix; + FT_Vector tmp_delta; + + FT_Matrix a, b; + FT_Pos x, y; + + + if ( !matrix ) + { + tmp_matrix.xx = 0x10000; + tmp_matrix.xy = 0; + tmp_matrix.yx = 0; + tmp_matrix.yy = 0x10000; + + matrix = &tmp_matrix; + } + + if ( !delta ) + { + tmp_delta.x = 0; + tmp_delta.y = 0; + + delta = &tmp_delta; + } + + a = glyph->transform; + b = *matrix; + FT_Matrix_Multiply( &b, &a ); + + x = ADD_LONG( ADD_LONG( FT_MulFix( matrix->xx, glyph->delta.x ), + FT_MulFix( matrix->xy, glyph->delta.y ) ), + delta->x ); + y = ADD_LONG( ADD_LONG( FT_MulFix( matrix->yx, glyph->delta.x ), + FT_MulFix( matrix->yy, glyph->delta.y ) ), + delta->y ); + + glyph->delta.x = x; + glyph->delta.y = y; + + glyph->transform = a; + } + + + FT_CALLBACK_DEF( FT_Error ) + ft_svg_glyph_prepare( FT_Glyph svg_glyph, + FT_GlyphSlot slot ) + { + FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph; + + FT_Error error = FT_Err_Ok; + FT_Memory memory = svg_glyph->library->memory; + + FT_SVG_Document document = NULL; + + + if ( FT_NEW( document ) ) + return error; + + document->svg_document = glyph->svg_document; + document->svg_document_length = glyph->svg_document_length; + + document->metrics = glyph->metrics; + document->units_per_EM = glyph->units_per_EM; + + document->start_glyph_id = glyph->start_glyph_id; + document->end_glyph_id = glyph->end_glyph_id; + + document->transform = glyph->transform; + document->delta = glyph->delta; + + slot->format = FT_GLYPH_FORMAT_SVG; + slot->glyph_index = glyph->glyph_index; + slot->other = document; + + return error; + } + + + FT_DEFINE_GLYPH( + ft_svg_glyph_class, + + sizeof ( FT_SvgGlyphRec ), + FT_GLYPH_FORMAT_SVG, + + ft_svg_glyph_init, /* FT_Glyph_InitFunc glyph_init */ + ft_svg_glyph_done, /* FT_Glyph_DoneFunc glyph_done */ + ft_svg_glyph_copy, /* FT_Glyph_CopyFunc glyph_copy */ + ft_svg_glyph_transform, /* FT_Glyph_TransformFunc glyph_transform */ + NULL, /* FT_Glyph_GetBBoxFunc glyph_bbox */ + ft_svg_glyph_prepare /* FT_Glyph_PrepareFunc glyph_prepare */ + ) + +#endif /* FT_CONFIG_OPTION_SVG */ + + /*************************************************************************/ /*************************************************************************/ /**** ****/ @@ -377,6 +612,12 @@ else if ( format == FT_GLYPH_FORMAT_OUTLINE ) clazz = &ft_outline_glyph_class; +#ifdef FT_CONFIG_OPTION_SVG + /* if it is an SVG glyph */ + else if ( format == FT_GLYPH_FORMAT_SVG ) + clazz = &ft_svg_glyph_class; +#endif + else { /* try to find a renderer that supports the glyph image format */ @@ -441,7 +682,10 @@ Exit2: /* if an error occurred, destroy the glyph */ if ( error ) + { FT_Done_Glyph( glyph ); + *aglyph = NULL; + } else *aglyph = glyph; @@ -453,9 +697,9 @@ /* documentation is in ftglyph.h */ FT_EXPORT_DEF( FT_Error ) - FT_Glyph_Transform( FT_Glyph glyph, - FT_Matrix* matrix, - FT_Vector* delta ) + FT_Glyph_Transform( FT_Glyph glyph, + const FT_Matrix* matrix, + const FT_Vector* delta ) { FT_Error error = FT_Err_Ok; @@ -533,10 +777,10 @@ /* documentation is in ftglyph.h */ FT_EXPORT_DEF( FT_Error ) - FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, - FT_Render_Mode render_mode, - FT_Vector* origin, - FT_Bool destroy ) + FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, + FT_Render_Mode render_mode, + const FT_Vector* origin, + FT_Bool destroy ) { FT_GlyphSlotRec dummy; FT_GlyphSlot_InternalRec dummy_internal; @@ -585,7 +829,7 @@ #if 1 /* if `origin' is set, translate the glyph image */ if ( origin ) - FT_Glyph_Transform( glyph, 0, origin ); + FT_Glyph_Transform( glyph, NULL, origin ); #else FT_UNUSED( origin ); #endif @@ -595,6 +839,16 @@ if ( !error ) error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode ); +#ifdef FT_CONFIG_OPTION_SVG + if ( clazz == &ft_svg_glyph_class ) + { + FT_Memory memory = library->memory; + + + FT_FREE( dummy.other ); + } +#endif + #if 1 if ( !destroy && origin ) { @@ -603,7 +857,7 @@ v.x = -origin->x; v.y = -origin->y; - FT_Glyph_Transform( glyph, 0, &v ); + FT_Glyph_Transform( glyph, NULL, &v ); } #endif diff --git a/lib/libesp32_lvgl/freetype/src/base/ftgxval.c b/lib/libesp32_lvgl/freetype/src/base/ftgxval.c index f04df1452..6b3c5d248 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftgxval.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftgxval.c @@ -4,7 +4,7 @@ * * FreeType API for validating TrueTypeGX/AAT tables (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * Masatake YAMATO, Redhat K.K, * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/base/fthash.c b/lib/libesp32_lvgl/freetype/src/base/fthash.c index 449b03a5c..313bbbb4b 100644 --- a/lib/libesp32_lvgl/freetype/src/base/fthash.c +++ b/lib/libesp32_lvgl/freetype/src/base/fthash.c @@ -243,7 +243,7 @@ nn = *bp; if ( !nn ) { - if ( FT_NEW( nn ) ) + if ( FT_QNEW( nn ) ) goto Exit; *bp = nn; diff --git a/lib/libesp32_lvgl/freetype/src/base/ftinit.c b/lib/libesp32_lvgl/freetype/src/base/ftinit.c index 0acc75e46..c9c71d24b 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftinit.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftinit.c @@ -4,7 +4,7 @@ * * FreeType initialization layer (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -202,6 +202,10 @@ FT_Memory memory; +#ifdef FT_DEBUG_LOGGING + ft_logging_init(); +#endif + /* check of `alibrary' delayed to `FT_New_Library' */ /* First of all, allocate a new system object -- this function is part */ @@ -248,6 +252,10 @@ /* discard memory manager */ FT_Done_Memory( memory ); +#ifdef FT_DEBUG_LOGGING + ft_logging_deinit(); +#endif + return FT_Err_Ok; } diff --git a/lib/libesp32_lvgl/freetype/src/base/ftlcdfil.c b/lib/libesp32_lvgl/freetype/src/base/ftlcdfil.c index 1e84dbc89..6c3fd66e0 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftlcdfil.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftlcdfil.c @@ -4,7 +4,7 @@ * * FreeType API for color filtering of subpixel bitmap glyphs (body). * - * Copyright (C) 2006-2020 by + * Copyright (C) 2006-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -32,7 +32,7 @@ /* add padding according to filter weights */ - FT_BASE_DEF (void) + FT_BASE_DEF( void ) ft_lcd_padding( FT_BBox* cbox, FT_GlyphSlot slot, FT_Render_Mode mode ) @@ -357,7 +357,7 @@ FT_EXPORT_DEF( FT_Error ) FT_Library_SetLcdGeometry( FT_Library library, - FT_Vector* sub ) + FT_Vector sub[3] ) { FT_UNUSED( library ); FT_UNUSED( sub ); @@ -368,7 +368,7 @@ #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ /* add padding to accommodate outline shifts */ - FT_BASE_DEF (void) + FT_BASE_DEF( void ) ft_lcd_padding( FT_BBox* cbox, FT_GlyphSlot slot, FT_Render_Mode mode ) @@ -428,7 +428,7 @@ ft_memcpy( library->lcd_geometry, sub, 3 * sizeof( FT_Vector ) ); - return FT_THROW( Unimplemented_Feature ); + return FT_Err_Ok; } #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ diff --git a/lib/libesp32_lvgl/freetype/src/base/ftmac.c b/lib/libesp32_lvgl/freetype/src/base/ftmac.c index 55a631fd7..492d05538 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftmac.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftmac.c @@ -8,7 +8,7 @@ * This file is for Mac OS X only; see builds/mac/ftoldmac.c for * classic platforms built by MPW. * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -67,6 +67,7 @@ #include #include +#include #include #include "ftbase.h" @@ -105,7 +106,7 @@ /* Don't want warnings about our own use of deprecated functions. */ #define FT_DEPRECATED_ATTRIBUTE -#include FT_MAC_H +#include #ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */ #define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault @@ -314,7 +315,7 @@ NULL, NULL, NULL ) ) return ( OSType ) 0; - return ((FInfo *)(info.finderInfo))->fdType; + return ( (FInfo *)( info.finderInfo ) )->fdType; } @@ -462,7 +463,7 @@ if ( ps_name_len != 0 ) { - ft_memcpy(ps_name, names[0] + 1, ps_name_len); + ft_memcpy( ps_name, names[0] + 1, ps_name_len ); ps_name[ps_name_len] = 0; } if ( style->indexes[face_index] > 1 && @@ -560,7 +561,7 @@ if ( lwfn_file_name[0] ) { err = lookup_lwfn_by_fond( pathname, lwfn_file_name, - buff, sizeof ( buff ) ); + buff, sizeof ( buff ) ); if ( !err ) have_lwfn = 1; } @@ -631,7 +632,7 @@ old_total_size = total_size; } - if ( FT_ALLOC( buffer, (FT_Long)total_size ) ) + if ( FT_QALLOC( buffer, (FT_Long)total_size ) ) goto Error; /* Second pass: append all POST data to the buffer, add PFB fields. */ @@ -752,7 +753,7 @@ if ( FT_MAC_RFORK_MAX_LEN < sfnt_size ) return FT_THROW( Array_Too_Large ); - if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) ) + if ( FT_QALLOC( sfnt_data, (FT_Long)sfnt_size ) ) { ReleaseResource( sfnt ); return error; @@ -1081,7 +1082,7 @@ #else /* !FT_MACINTOSH */ /* ANSI C doesn't like empty source files */ - typedef int _ft_mac_dummy; + typedef int ft_mac_dummy_; #endif /* !FT_MACINTOSH */ diff --git a/lib/libesp32_lvgl/freetype/src/base/ftmm.c b/lib/libesp32_lvgl/freetype/src/base/ftmm.c index 9a702b993..9e2dd7ee7 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftmm.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftmm.c @@ -4,7 +4,7 @@ * * Multiple Master font support (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -185,6 +185,14 @@ error = FT_ERR( Invalid_Argument ); if ( service->set_mm_design ) error = service->set_mm_design( face, num_coords, coords ); + + if ( !error ) + { + if ( num_coords ) + face->face_flags |= FT_FACE_FLAG_VARIATION; + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + } } /* enforce recomputation of auto-hinting data */ @@ -220,6 +228,14 @@ error = FT_ERR( Invalid_Argument ); if ( service->set_mm_weightvector ) error = service->set_mm_weightvector( face, len, weightvector ); + + if ( !error ) + { + if ( len ) + face->face_flags |= FT_FACE_FLAG_VARIATION; + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + } } /* enforce recomputation of auto-hinting data */ @@ -283,6 +299,30 @@ if ( service_mm->set_var_design ) error = service_mm->set_var_design( face, num_coords, coords ); + if ( !error || error == -1 ) + { + FT_Bool is_variation_old = FT_IS_VARIATION( face ); + + + if ( num_coords ) + face->face_flags |= FT_FACE_FLAG_VARIATION; + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + + if ( service_mm->construct_ps_name ) + { + if ( error == -1 ) + { + /* The PS name of a named instance and a non-named instance */ + /* usually differs, even if the axis values are identical. */ + if ( is_variation_old != FT_IS_VARIATION( face ) ) + service_mm->construct_ps_name( face ); + } + else + service_mm->construct_ps_name( face ); + } + } + /* internal error code -1 means `no change'; we can exit immediately */ if ( error == -1 ) return FT_Err_Ok; @@ -359,6 +399,30 @@ if ( service_mm->set_mm_blend ) error = service_mm->set_mm_blend( face, num_coords, coords ); + if ( !error || error == -1 ) + { + FT_Bool is_variation_old = FT_IS_VARIATION( face ); + + + if ( num_coords ) + face->face_flags |= FT_FACE_FLAG_VARIATION; + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + + if ( service_mm->construct_ps_name ) + { + if ( error == -1 ) + { + /* The PS name of a named instance and a non-named instance */ + /* usually differs, even if the axis values are identical. */ + if ( is_variation_old != FT_IS_VARIATION( face ) ) + service_mm->construct_ps_name( face ); + } + else + service_mm->construct_ps_name( face ); + } + } + /* internal error code -1 means `no change'; we can exit immediately */ if ( error == -1 ) return FT_Err_Ok; @@ -410,6 +474,30 @@ if ( service_mm->set_mm_blend ) error = service_mm->set_mm_blend( face, num_coords, coords ); + if ( !error || error == -1 ) + { + FT_Bool is_variation_old = FT_IS_VARIATION( face ); + + + if ( num_coords ) + face->face_flags |= FT_FACE_FLAG_VARIATION; + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + + if ( service_mm->construct_ps_name ) + { + if ( error == -1 ) + { + /* The PS name of a named instance and a non-named instance */ + /* usually differs, even if the axis values are identical. */ + if ( is_variation_old != FT_IS_VARIATION( face ) ) + service_mm->construct_ps_name( face ); + } + else + service_mm->construct_ps_name( face ); + } + } + /* internal error code -1 means `no change'; we can exit immediately */ if ( error == -1 ) return FT_Err_Ok; @@ -535,8 +623,35 @@ if ( !error ) { error = FT_ERR( Invalid_Argument ); - if ( service_mm->set_instance ) - error = service_mm->set_instance( face, instance_index ); + if ( service_mm->set_named_instance ) + error = service_mm->set_named_instance( face, instance_index ); + + if ( !error || error == -1 ) + { + FT_Bool is_variation_old = FT_IS_VARIATION( face ); + + + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + face->face_index = ( instance_index << 16 ) | + ( face->face_index & 0xFFFFL ); + + if ( service_mm->construct_ps_name ) + { + if ( error == -1 ) + { + /* The PS name of a named instance and a non-named instance */ + /* usually differs, even if the axis values are identical. */ + if ( is_variation_old != FT_IS_VARIATION( face ) ) + service_mm->construct_ps_name( face ); + } + else + service_mm->construct_ps_name( face ); + } + } + + /* internal error code -1 means `no change'; we can exit immediately */ + if ( error == -1 ) + return FT_Err_Ok; } if ( !error ) @@ -554,11 +669,32 @@ face->autohint.data = NULL; } + return error; + } + + + /* documentation is in ftmm.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Get_Default_Named_Instance( FT_Face face, + FT_UInt *instance_index ) + { + FT_Error error; + + FT_Service_MultiMasters service_mm = NULL; + + + /* check of `face' delayed to `ft_face_get_mm_service' */ + + error = ft_face_get_mm_service( face, &service_mm ); if ( !error ) { - face->face_index = ( instance_index << 16 ) | - ( face->face_index & 0xFFFFL ); - face->face_flags &= ~FT_FACE_FLAG_VARIATION; + /* no error if `get_default_named_instance` is not available */ + if ( service_mm->get_default_named_instance ) + error = service_mm->get_default_named_instance( face, + instance_index ); + else + error = FT_Err_Ok; } return error; diff --git a/lib/libesp32_lvgl/freetype/src/base/ftobjs.c b/lib/libesp32_lvgl/freetype/src/base/ftobjs.c index c060bbbc8..89a25bc73 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftobjs.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftobjs.c @@ -4,7 +4,7 @@ * * The FreeType private base classes (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,7 @@ #include #include /* for SFNT_Load_Table_Func */ #include /* for PS_Driver */ +#include #include #include @@ -78,6 +80,9 @@ #pragma warning( pop ) #endif + /* This array must stay in sync with the @FT_Pixel_Mode enumeration */ + /* (in file `ftimage.h`). */ + static const char* const pixel_modes[] = { "none", @@ -87,7 +92,8 @@ "gray 4-bit bitmap", "LCD 8-bit bitmap", "vertical LCD 8-bit bitmap", - "BGRA 32-bit color image bitmap" + "BGRA 32-bit color image bitmap", + "SDF 8-bit bitmap" }; #endif /* FT_DEBUG_LEVEL_TRACE */ @@ -193,6 +199,7 @@ FT_Error error; FT_Memory memory; FT_Stream stream = NULL; + FT_UInt mode; *astream = NULL; @@ -204,49 +211,56 @@ return FT_THROW( Invalid_Argument ); memory = library->memory; + mode = args->flags & + ( FT_OPEN_MEMORY | FT_OPEN_STREAM | FT_OPEN_PATHNAME ); - if ( FT_NEW( stream ) ) - goto Exit; - - stream->memory = memory; - - if ( args->flags & FT_OPEN_MEMORY ) + if ( mode == FT_OPEN_MEMORY ) { /* create a memory-based stream */ + if ( FT_NEW( stream ) ) + goto Exit; + FT_Stream_OpenMemory( stream, (const FT_Byte*)args->memory_base, (FT_ULong)args->memory_size ); + stream->memory = memory; } #ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT - else if ( args->flags & FT_OPEN_PATHNAME ) + else if ( mode == FT_OPEN_PATHNAME ) { /* create a normal system stream */ + if ( FT_NEW( stream ) ) + goto Exit; + + stream->memory = memory; error = FT_Stream_Open( stream, args->pathname ); - stream->pathname.pointer = args->pathname; + if ( error ) + FT_FREE( stream ); } - else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream ) + else if ( ( mode == FT_OPEN_STREAM ) && args->stream ) { /* use an existing, user-provided stream */ /* in this case, we do not need to allocate a new stream object */ /* since the caller is responsible for closing it himself */ - FT_FREE( stream ); - stream = args->stream; + stream = args->stream; + stream->memory = memory; + error = FT_Err_Ok; } #endif else + { error = FT_THROW( Invalid_Argument ); + if ( ( args->flags & FT_OPEN_STREAM ) && args->stream ) + FT_Stream_Close( args->stream ); + } - if ( error ) - FT_FREE( stream ); - else - stream->memory = memory; /* just to be certain */ - - *astream = stream; + if ( !error ) + *astream = stream; Exit: return error; @@ -316,6 +330,19 @@ if ( !error && clazz->init_slot ) error = clazz->init_slot( slot ); +#ifdef FT_CONFIG_OPTION_SVG + /* if SVG table exists, allocate the space in `slot->other` */ + if ( slot->face->face_flags & FT_FACE_FLAG_SVG ) + { + FT_SVG_Document document = NULL; + + + if ( FT_NEW( document ) ) + goto Exit; + slot->other = document; + } +#endif + Exit: return error; } @@ -360,7 +387,18 @@ FT_Pos width, height, pitch; - if ( slot->format != FT_GLYPH_FORMAT_OUTLINE ) + if ( slot->format == FT_GLYPH_FORMAT_SVG ) + { + FT_Module module; + SVG_Service svg_service; + + + module = FT_Get_Module( slot->library, "ot-svg" ); + svg_service = (SVG_Service)module->clazz->module_interface; + + return (FT_Bool)svg_service->preset_slot( module, slot, FALSE ); + } + else if ( slot->format != FT_GLYPH_FORMAT_OUTLINE ) return 1; if ( origin ) @@ -470,7 +508,7 @@ case FT_PIXEL_MODE_LCD_V: height *= 3; - /* fall through */ + FALL_THROUGH; case FT_PIXEL_MODE_GRAY: default: @@ -523,7 +561,7 @@ else slot->internal->flags |= FT_GLYPH_OWN_BITMAP; - (void)FT_ALLOC( slot->bitmap.buffer, size ); + FT_MEM_ALLOC( slot->bitmap.buffer, size ); return error; } @@ -535,6 +573,8 @@ ft_glyphslot_free_bitmap( slot ); /* clear all public fields in the glyph slot */ + slot->glyph_index = 0; + FT_ZERO( &slot->metrics ); FT_ZERO( &slot->outline ); @@ -550,11 +590,32 @@ slot->subglyphs = NULL; slot->control_data = NULL; slot->control_len = 0; - slot->other = NULL; - slot->format = FT_GLYPH_FORMAT_NONE; + +#ifndef FT_CONFIG_OPTION_SVG + slot->other = NULL; +#else + if ( !( slot->face->face_flags & FT_FACE_FLAG_SVG ) ) + slot->other = NULL; + else + { + if ( slot->internal->flags & FT_GLYPH_OWN_GZIP_SVG ) + { + FT_Memory memory = slot->face->memory; + FT_SVG_Document doc = (FT_SVG_Document)slot->other; + + + FT_FREE( doc->svg_document ); + slot->internal->flags &= ~FT_GLYPH_OWN_GZIP_SVG; + } + } +#endif + + slot->format = FT_GLYPH_FORMAT_NONE; slot->linearHoriAdvance = 0; slot->linearVertAdvance = 0; + slot->advance.x = 0; + slot->advance.y = 0; slot->lsb_delta = 0; slot->rsb_delta = 0; } @@ -567,6 +628,24 @@ FT_Driver_Class clazz = driver->clazz; FT_Memory memory = driver->root.memory; +#ifdef FT_CONFIG_OPTION_SVG + if ( slot->face->face_flags & FT_FACE_FLAG_SVG ) + { + /* Free memory in case SVG was there. */ + /* `slot->internal` might be NULL in out-of-memory situations. */ + if ( slot->internal && slot->internal->flags & FT_GLYPH_OWN_GZIP_SVG ) + { + FT_SVG_Document doc = (FT_SVG_Document)slot->other; + + + FT_FREE( doc->svg_document ); + + slot->internal->flags &= ~FT_GLYPH_OWN_GZIP_SVG; + } + + FT_FREE( slot->other ); + } +#endif if ( clazz->done_slot ) clazz->done_slot( slot ); @@ -734,6 +813,29 @@ } + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( void ) + FT_Get_Transform( FT_Face face, + FT_Matrix* matrix, + FT_Vector* delta ) + { + FT_Face_Internal internal; + + + if ( !face ) + return; + + internal = face->internal; + + if ( matrix ) + *matrix = internal->transform_matrix; + + if ( delta ) + *delta = internal->transform_delta; + } + + static FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot ); @@ -819,6 +921,11 @@ library = driver->root.library; hinter = library->auto_hinter; + /* undefined scale means no scale */ + if ( face->size->metrics.x_ppem == 0 || + face->size->metrics.y_ppem == 0 ) + load_flags |= FT_LOAD_NO_SCALE; + /* resolve load flags dependencies */ if ( load_flags & FT_LOAD_NO_RECURSE ) @@ -908,11 +1015,22 @@ FT_AutoHinter_Interface hinting; - /* try to load embedded bitmaps first if available */ - /* */ - /* XXX: This is really a temporary hack that should disappear */ - /* promptly with FreeType 2.1! */ - /* */ + /* XXX: The use of the `FT_LOAD_XXX_ONLY` flags is not very */ + /* elegant. */ + + /* try to load SVG documents if available */ + if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 && + FT_HAS_SVG( face ) ) + { + error = driver->clazz->load_glyph( slot, face->size, + glyph_index, + load_flags | FT_LOAD_SVG_ONLY ); + + if ( !error && slot->format == FT_GLYPH_FORMAT_SVG ) + goto Load_Ok; + } + + /* try to load embedded bitmaps if available */ if ( FT_HAS_FIXED_SIZES( face ) && ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) { @@ -1056,35 +1174,46 @@ #ifdef FT_DEBUG_LEVEL_TRACE FT_TRACE5(( "FT_Load_Glyph: index %d, flags 0x%x\n", glyph_index, load_flags )); - FT_TRACE5(( " x advance: %f\n", slot->advance.x / 64.0 )); - FT_TRACE5(( " y advance: %f\n", slot->advance.y / 64.0 )); - FT_TRACE5(( " linear x advance: %f\n", - slot->linearHoriAdvance / 65536.0 )); - FT_TRACE5(( " linear y advance: %f\n", - slot->linearVertAdvance / 65536.0 )); - FT_TRACE5(( "\n" )); - FT_TRACE5(( " bitmap %dx%d, %s (mode %d)\n", + FT_TRACE5(( " bitmap %dx%d %s, %s (mode %d)\n", slot->bitmap.width, slot->bitmap.rows, + slot->outline.points ? + slot->bitmap.buffer ? "rendered" + : "preset" + : + slot->internal->flags & FT_GLYPH_OWN_BITMAP ? "owned" + : "unowned", pixel_modes[slot->bitmap.pixel_mode], slot->bitmap.pixel_mode )); FT_TRACE5(( "\n" )); + FT_TRACE5(( " x advance: %f\n", (double)slot->advance.x / 64 )); + FT_TRACE5(( " y advance: %f\n", (double)slot->advance.y / 64 )); + FT_TRACE5(( " linear x advance: %f\n", + (double)slot->linearHoriAdvance / 65536 )); + FT_TRACE5(( " linear y advance: %f\n", + (double)slot->linearVertAdvance / 65536 )); { FT_Glyph_Metrics* metrics = &slot->metrics; FT_TRACE5(( " metrics:\n" )); - FT_TRACE5(( " width: %f\n", metrics->width / 64.0 )); - FT_TRACE5(( " height: %f\n", metrics->height / 64.0 )); + FT_TRACE5(( " width: %f\n", (double)metrics->width / 64 )); + FT_TRACE5(( " height: %f\n", (double)metrics->height / 64 )); FT_TRACE5(( "\n" )); - FT_TRACE5(( " horiBearingX: %f\n", metrics->horiBearingX / 64.0 )); - FT_TRACE5(( " horiBearingY: %f\n", metrics->horiBearingY / 64.0 )); - FT_TRACE5(( " horiAdvance: %f\n", metrics->horiAdvance / 64.0 )); + FT_TRACE5(( " horiBearingX: %f\n", + (double)metrics->horiBearingX / 64 )); + FT_TRACE5(( " horiBearingY: %f\n", + (double)metrics->horiBearingY / 64 )); + FT_TRACE5(( " horiAdvance: %f\n", + (double)metrics->horiAdvance / 64 )); FT_TRACE5(( "\n" )); - FT_TRACE5(( " vertBearingX: %f\n", metrics->vertBearingX / 64.0 )); - FT_TRACE5(( " vertBearingY: %f\n", metrics->vertBearingY / 64.0 )); - FT_TRACE5(( " vertAdvance: %f\n", metrics->vertAdvance / 64.0 )); + FT_TRACE5(( " vertBearingX: %f\n", + (double)metrics->vertBearingX / 64 )); + FT_TRACE5(( " vertBearingY: %f\n", + (double)metrics->vertBearingY / 64 )); + FT_TRACE5(( " vertAdvance: %f\n", + (double)metrics->vertAdvance / 64 )); } #endif @@ -1117,9 +1246,13 @@ /* destructor for sizes list */ static void destroy_size( FT_Memory memory, - FT_Size size, - FT_Driver driver ) + void* size_, + void* driver_ ) { + FT_Size size = (FT_Size)size_; + FT_Driver driver = (FT_Driver)driver_; + + /* finalize client-specific data */ if ( size->generic.finalizer ) size->generic.finalizer( size ); @@ -1165,10 +1298,12 @@ /* destructor for faces list */ static void destroy_face( FT_Memory memory, - FT_Face face, - FT_Driver driver ) + void* face_, + void* driver_ ) { - FT_Driver_Class clazz = driver->clazz; + FT_Face face = (FT_Face)face_; + FT_Driver driver = (FT_Driver)driver_; + FT_Driver_Class clazz = driver->clazz; /* discard auto-hinting data */ @@ -1182,7 +1317,7 @@ /* discard all sizes for this face */ FT_List_Finalize( &face->sizes_list, - (FT_List_Destructor)destroy_size, + destroy_size, memory, driver ); face->size = NULL; @@ -1218,7 +1353,7 @@ Destroy_Driver( FT_Driver driver ) { FT_List_Finalize( &driver->faces_list, - (FT_List_Destructor)destroy_face, + destroy_face, driver->root.memory, driver ); } @@ -1367,7 +1502,7 @@ static FT_Error open_face( FT_Driver driver, FT_Stream *astream, - FT_Bool external_stream, + FT_Bool *anexternal_stream, FT_Long face_index, FT_Int num_params, FT_Parameter* params, @@ -1393,7 +1528,7 @@ face->stream = *astream; /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */ - if ( external_stream ) + if ( *anexternal_stream ) face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM; if ( FT_NEW( internal ) ) @@ -1423,7 +1558,10 @@ (FT_Int)face_index, num_params, params ); - *astream = face->stream; /* Stream may have been changed. */ + /* Stream may have been changed. */ + *astream = face->stream; + *anexternal_stream = + ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0; if ( error ) goto Fail; @@ -1547,14 +1685,13 @@ static void memory_stream_close( FT_Stream stream ) { - FT_Memory memory = stream->memory; + FT_Memory memory = (FT_Memory)stream->descriptor.pointer; FT_FREE( stream->base ); - stream->size = 0; - stream->base = NULL; stream->close = NULL; + FT_FREE( stream ); } @@ -1585,7 +1722,8 @@ FT_Stream_OpenMemory( stream, base, size ); - stream->close = close; + stream->descriptor.pointer = memory; + stream->close = close; *astream = stream; @@ -1606,28 +1744,37 @@ { FT_Open_Args args; FT_Error error; - FT_Stream stream = NULL; FT_Memory memory = library->memory; + args.driver = NULL; + args.flags = 0; + + if ( driver_name ) + { + args.driver = FT_Get_Module( library, driver_name ); + if ( !args.driver ) + { + FT_FREE( base ); + return FT_THROW( Missing_Module ); + } + + args.flags = args.flags | FT_OPEN_DRIVER; + } + + /* `memory_stream_close` also frees the stream object. */ error = new_memory_stream( library, base, size, memory_stream_close, - &stream ); + &args.stream ); if ( error ) { FT_FREE( base ); return error; } - args.flags = FT_OPEN_STREAM; - args.stream = stream; - if ( driver_name ) - { - args.flags = args.flags | FT_OPEN_DRIVER; - args.driver = FT_Get_Module( library, driver_name ); - } + args.flags |= FT_OPEN_STREAM; #ifdef FT_MACINTOSH /* At this point, the face index has served its purpose; */ @@ -1639,21 +1786,7 @@ face_index &= 0x7FFF0000L; /* retain GX data */ #endif - error = ft_open_face_internal( library, &args, face_index, aface, 0 ); - - if ( !error ) - (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; - else -#ifdef FT_MACINTOSH - FT_Stream_Free( stream, 0 ); -#else - { - FT_Stream_Close( stream ); - FT_FREE( stream ); - } -#endif - - return error; + return ft_open_face_internal( library, &args, face_index, aface, 0 ); } @@ -1782,7 +1915,7 @@ if ( error ) goto Exit; - if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) ) + if ( FT_QALLOC( sfnt_ps, (FT_Long)length ) ) goto Exit; error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length ); @@ -1796,7 +1929,7 @@ sfnt_ps, length, FT_MIN( face_index, 0 ), - is_sfnt_cid ? "cid" : "type1", + is_sfnt_cid ? "t1cid" : "type1", aface ); Exit: { @@ -1892,7 +2025,7 @@ goto Exit; } - if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) ) + if ( FT_QALLOC( pfb_data, (FT_Long)pfb_len + 2 ) ) goto Exit; pfb_data[0] = 0x80; @@ -1956,7 +2089,7 @@ { FT_TRACE3(( " Write POST fragment #%d header (4-byte) to buffer" " %p + 0x%08lx\n", - i, pfb_data, pfb_lenpos )); + i, (void*)pfb_data, pfb_lenpos )); if ( pfb_lenpos + 3 > pfb_len + 2 ) goto Exit2; @@ -1971,7 +2104,7 @@ FT_TRACE3(( " Write POST fragment #%d header (6-byte) to buffer" " %p + 0x%08lx\n", - i, pfb_data, pfb_pos )); + i, (void*)pfb_data, pfb_pos )); if ( pfb_pos + 6 > pfb_len + 2 ) goto Exit2; @@ -1994,7 +2127,7 @@ FT_TRACE3(( " Load POST fragment #%d (%ld byte) to buffer" " %p + 0x%08lx\n", - i, rlen, pfb_data, pfb_pos )); + i, rlen, (void*)pfb_data, pfb_pos )); error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen ); if ( error ) @@ -2057,7 +2190,7 @@ FT_Byte* sfnt_data = NULL; FT_Error error; FT_ULong flag_offset; - FT_Long rlen; + FT_ULong rlen; int is_cff; FT_Long face_index_in_resource = 0; @@ -2072,11 +2205,11 @@ if ( error ) goto Exit; - if ( FT_READ_LONG( rlen ) ) + if ( FT_READ_ULONG( rlen ) ) goto Exit; - if ( rlen < 1 ) + if ( !rlen ) return FT_THROW( Cannot_Open_Resource ); - if ( (FT_ULong)rlen > FT_MAC_RFORK_MAX_LEN ) + if ( rlen > FT_MAC_RFORK_MAX_LEN ) return FT_THROW( Invalid_Offset ); error = open_face_PS_from_sfnt_stream( library, @@ -2092,10 +2225,11 @@ if ( error ) goto Exit; - if ( FT_ALLOC( sfnt_data, rlen ) ) + if ( FT_QALLOC( sfnt_data, rlen ) ) return error; - error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, (FT_ULong)rlen ); - if ( error ) { + error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen ); + if ( error ) + { FT_FREE( sfnt_data ); goto Exit; } @@ -2103,7 +2237,7 @@ is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 ); error = open_face_from_buffer( library, sfnt_data, - (FT_ULong)rlen, + rlen, face_index_in_resource, is_cff ? "cff" : "truetype", aface ); @@ -2407,6 +2541,16 @@ #endif + /* only use lower 31 bits together with sign bit */ + if ( face_index > 0 ) + face_index &= 0x7FFFFFFFL; + else + { + face_index = -face_index; + face_index &= 0x7FFFFFFFL; + face_index = -face_index; + } + #ifdef FT_DEBUG_LEVEL_TRACE FT_TRACE3(( "FT_Open_Face: " )); if ( face_index < 0 ) @@ -2422,7 +2566,7 @@ /* test for valid `library' delayed to `FT_Stream_New' */ - if ( ( !aface && face_index >= 0 ) || !args ) + if ( !args ) return FT_THROW( Invalid_Argument ); external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) && @@ -2433,6 +2577,14 @@ if ( error ) goto Fail3; + /* Do this error check after `FT_Stream_New` to ensure that the */ + /* 'close' callback is called. */ + if ( !aface && face_index >= 0 ) + { + error = FT_THROW( Invalid_Argument ); + goto Fail3; + } + memory = library->memory; /* If the font driver is specified in the `args' structure, use */ @@ -2454,7 +2606,7 @@ params = args->params; } - error = open_face( driver, &stream, external_stream, face_index, + error = open_face( driver, &stream, &external_stream, face_index, num_params, params, &face ); if ( !error ) goto Success; @@ -2490,7 +2642,7 @@ params = args->params; } - error = open_face( driver, &stream, external_stream, face_index, + error = open_face( driver, &stream, &external_stream, face_index, num_params, params, &face ); if ( !error ) goto Success; @@ -2566,7 +2718,7 @@ FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" )); /* add the face object to its driver's list */ - if ( FT_NEW( node ) ) + if ( FT_QNEW( node ) ) goto Fail; node->data = face; @@ -2681,10 +2833,10 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( !error && face_index < 0 ) { - FT_TRACE3(( "FT_Open_Face: The font has %ld face%s\n" - " and %ld named instance%s for face %ld\n", + FT_TRACE3(( "FT_Open_Face: The font has %ld face%s\n", face->num_faces, - face->num_faces == 1 ? "" : "s", + face->num_faces == 1 ? "" : "s" )); + FT_TRACE3(( " and %ld named instance%s for face %ld\n", face->style_flags >> 16, ( face->style_flags >> 16 ) == 1 ? "" : "s", -face_index - 1 )); @@ -2722,8 +2874,8 @@ /* documentation is in freetype.h */ FT_EXPORT_DEF( FT_Error ) - FT_Attach_Stream( FT_Face face, - FT_Open_Args* parameters ) + FT_Attach_Stream( FT_Face face, + const FT_Open_Args* parameters ) { FT_Stream stream; FT_Error error; @@ -2851,7 +3003,7 @@ memory = face->memory; /* Allocate new size object and perform basic initialisation */ - if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) ) + if ( FT_ALLOC( size, clazz->size_object_size ) || FT_QNEW( node ) ) goto Exit; size->face = face; @@ -3088,10 +3240,12 @@ } - FT_BASE_DEF( void ) + FT_BASE_DEF( FT_Error ) FT_Request_Metrics( FT_Face face, FT_Size_Request req ) { + FT_Error error = FT_Err_Ok; + FT_Size_Metrics* metrics; @@ -3146,34 +3300,49 @@ scaled_h = FT_REQUEST_HEIGHT( req ); /* determine scales */ + if ( req->height || !req->width ) + { + if ( h == 0 ) + { + FT_ERROR(( "FT_Request_Metrics: Divide by zero\n" )); + error = FT_ERR( Divide_By_Zero ); + goto Exit; + } + + metrics->y_scale = FT_DivFix( scaled_h, h ); + } + if ( req->width ) { + if ( w == 0 ) + { + FT_ERROR(( "FT_Request_Metrics: Divide by zero\n" )); + error = FT_ERR( Divide_By_Zero ); + goto Exit; + } + metrics->x_scale = FT_DivFix( scaled_w, w ); - - if ( req->height ) - { - metrics->y_scale = FT_DivFix( scaled_h, h ); - - if ( req->type == FT_SIZE_REQUEST_TYPE_CELL ) - { - if ( metrics->y_scale > metrics->x_scale ) - metrics->y_scale = metrics->x_scale; - else - metrics->x_scale = metrics->y_scale; - } - } - else - { - metrics->y_scale = metrics->x_scale; - scaled_h = FT_MulDiv( scaled_w, h, w ); - } } else { - metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h ); + metrics->x_scale = metrics->y_scale; scaled_w = FT_MulDiv( scaled_h, w, h ); } + if ( !req->height ) + { + metrics->y_scale = metrics->x_scale; + scaled_h = FT_MulDiv( scaled_w, h, w ); + } + + if ( req->type == FT_SIZE_REQUEST_TYPE_CELL ) + { + if ( metrics->y_scale > metrics->x_scale ) + metrics->y_scale = metrics->x_scale; + else + metrics->x_scale = metrics->y_scale; + } + Calculate_Ppem: /* calculate the ppems */ if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL ) @@ -3182,8 +3351,18 @@ scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale ); } - metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 ); - metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 ); + scaled_w = ( scaled_w + 32 ) >> 6; + scaled_h = ( scaled_h + 32 ) >> 6; + if ( scaled_w > (FT_Long)FT_USHORT_MAX || + scaled_h > (FT_Long)FT_USHORT_MAX ) + { + FT_ERROR(( "FT_Request_Metrics: Resulting ppem size too large\n" )); + error = FT_ERR( Invalid_Pixel_Size ); + goto Exit; + } + + metrics->x_ppem = (FT_UShort)scaled_w; + metrics->y_ppem = (FT_UShort)scaled_h; ft_recompute_scaled_metrics( face, metrics ); } @@ -3193,6 +3372,9 @@ metrics->x_scale = 1L << 16; metrics->y_scale = 1L << 16; } + + Exit: + return error; } @@ -3234,15 +3416,19 @@ FT_TRACE5(( " x scale: %ld (%f)\n", - metrics->x_scale, metrics->x_scale / 65536.0 )); + metrics->x_scale, (double)metrics->x_scale / 65536 )); FT_TRACE5(( " y scale: %ld (%f)\n", - metrics->y_scale, metrics->y_scale / 65536.0 )); - FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 )); - FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 )); - FT_TRACE5(( " height: %f\n", metrics->height / 64.0 )); - FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 )); - FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem )); - FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem )); + metrics->y_scale, (double)metrics->y_scale / 65536 )); + FT_TRACE5(( " ascender: %f\n", + (double)metrics->ascender / 64 )); + FT_TRACE5(( " descender: %f\n", + (double)metrics->descender / 64 )); + FT_TRACE5(( " height: %f\n", + (double)metrics->height / 64 )); + FT_TRACE5(( " max advance: %f\n", + (double)metrics->max_advance / 64 )); + FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem )); + FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem )); } #endif @@ -3256,7 +3442,7 @@ FT_Request_Size( FT_Face face, FT_Size_Request req ) { - FT_Error error = FT_Err_Ok; + FT_Error error; FT_Driver_Class clazz; FT_ULong strike_index; @@ -3264,6 +3450,9 @@ if ( !face ) return FT_THROW( Invalid_Face_Handle ); + if ( !face->size ) + return FT_THROW( Invalid_Size_Handle ); + if ( !req || req->width < 0 || req->height < 0 || req->type >= FT_SIZE_REQUEST_TYPE_MAX ) return FT_THROW( Invalid_Argument ); @@ -3292,13 +3481,15 @@ */ error = FT_Match_Size( face, req, 0, &strike_index ); if ( error ) - return error; + goto Exit; return FT_Select_Size( face, (FT_Int)strike_index ); } else { - FT_Request_Metrics( face, req ); + error = FT_Request_Metrics( face, req ); + if ( error ) + goto Exit; FT_TRACE5(( "FT_Request_Size:\n" )); } @@ -3309,18 +3500,23 @@ FT_TRACE5(( " x scale: %ld (%f)\n", - metrics->x_scale, metrics->x_scale / 65536.0 )); + metrics->x_scale, (double)metrics->x_scale / 65536 )); FT_TRACE5(( " y scale: %ld (%f)\n", - metrics->y_scale, metrics->y_scale / 65536.0 )); - FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 )); - FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 )); - FT_TRACE5(( " height: %f\n", metrics->height / 64.0 )); - FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 )); - FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem )); - FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem )); + metrics->y_scale, (double)metrics->y_scale / 65536 )); + FT_TRACE5(( " ascender: %f\n", + (double)metrics->ascender / 64 )); + FT_TRACE5(( " descender: %f\n", + (double)metrics->descender / 64 )); + FT_TRACE5(( " height: %f\n", + (double)metrics->height / 64 )); + FT_TRACE5(( " max advance: %f\n", + (double)metrics->max_advance / 64 )); + FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem )); + FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem )); } #endif + Exit: return error; } @@ -3645,9 +3841,9 @@ FT_CharMap last_charmap = face->charmaps[face->num_charmaps - 1]; - if ( FT_RENEW_ARRAY( face->charmaps, - face->num_charmaps, - face->num_charmaps - 1 ) ) + if ( FT_QRENEW_ARRAY( face->charmaps, + face->num_charmaps, + face->num_charmaps - 1 ) ) return; /* remove it from our list of charmaps */ @@ -3679,7 +3875,7 @@ FT_CharMap charmap, FT_CMap *acmap ) { - FT_Error error = FT_Err_Ok; + FT_Error error; FT_Face face; FT_Memory memory; FT_CMap cmap = NULL; @@ -3704,9 +3900,9 @@ } /* add it to our list of charmaps */ - if ( FT_RENEW_ARRAY( face->charmaps, - face->num_charmaps, - face->num_charmaps + 1 ) ) + if ( FT_QRENEW_ARRAY( face->charmaps, + face->num_charmaps, + face->num_charmaps + 1 ) ) goto Fail; face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap; @@ -4400,7 +4596,7 @@ FT_ListNode node = NULL; - if ( FT_NEW( node ) ) + if ( FT_QNEW( node ) ) goto Exit; { @@ -4412,8 +4608,7 @@ render->glyph_format = clazz->glyph_format; /* allocate raster object if needed */ - if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && - clazz->raster_class->raster_new ) + if ( clazz->raster_class && clazz->raster_class->raster_new ) { error = clazz->raster_class->raster_new( memory, &render->raster ); if ( error ) @@ -4423,6 +4618,11 @@ render->render = clazz->render_glyph; } +#ifdef FT_CONFIG_OPTION_SVG + if ( clazz->glyph_format == FT_GLYPH_FORMAT_SVG ) + render->render = clazz->render_glyph; +#endif + /* add to list */ node->data = module; FT_List_Add( &library->renderers, node ); @@ -4460,8 +4660,7 @@ /* release raster object, if any */ - if ( render->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && - render->raster ) + if ( render->raster ) render->clazz->raster_class->raster_done( render->raster ); /* remove from list */ @@ -4556,9 +4755,6 @@ switch ( slot->format ) { - case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */ - break; - default: if ( slot->internal->load_flags & FT_LOAD_COLOR ) { @@ -4646,7 +4842,7 @@ else renderer = FT_Lookup_Renderer( library, slot->format, &node ); - error = FT_ERR( Unimplemented_Feature ); + error = FT_ERR( Cannot_Render_Glyph ); while ( renderer ) { error = renderer->render( renderer, slot, render_mode, NULL ); @@ -4662,6 +4858,11 @@ /* format. */ renderer = FT_Lookup_Renderer( library, slot->format, &node ); } + + /* it is not an error if we cannot render a bitmap glyph */ + if ( FT_ERR_EQ( error, Cannot_Render_Glyph ) && + slot->format == FT_GLYPH_FORMAT_BITMAP ) + error = FT_Err_Ok; } } @@ -4734,11 +4935,11 @@ /* we use FT_TRACE7 in this block */ if ( !error && - ft_trace_levels[trace_checksum] >= 7 ) + ft_trace_levels[trace_checksum] >= 7 && + slot->bitmap.buffer ) { if ( slot->bitmap.rows < 128U && - slot->bitmap.width < 128U && - slot->bitmap.buffer ) + slot->bitmap.width < 128U ) { int rows = (int)slot->bitmap.rows; int width = (int)slot->bitmap.width; @@ -5149,16 +5350,16 @@ if ( cur == limit ) { - FT_ERROR(( "%s: can't find module `%s'\n", - func_name, module_name )); + FT_TRACE2(( "%s: can't find module `%s'\n", + func_name, module_name )); return FT_THROW( Missing_Module ); } /* check whether we have a service interface */ if ( !cur[0]->clazz->get_interface ) { - FT_ERROR(( "%s: module `%s' doesn't support properties\n", - func_name, module_name )); + FT_TRACE2(( "%s: module `%s' doesn't support properties\n", + func_name, module_name )); return FT_THROW( Unimplemented_Feature ); } @@ -5167,8 +5368,8 @@ FT_SERVICE_ID_PROPERTIES ); if ( !interface ) { - FT_ERROR(( "%s: module `%s' doesn't support properties\n", - func_name, module_name )); + FT_TRACE2(( "%s: module `%s' doesn't support properties\n", + func_name, module_name )); return FT_THROW( Unimplemented_Feature ); } @@ -5181,8 +5382,8 @@ if ( missing_func ) { - FT_ERROR(( "%s: property service of module `%s' is broken\n", - func_name, module_name )); + FT_TRACE2(( "%s: property service of module `%s' is broken\n", + func_name, module_name )); return FT_THROW( Unimplemented_Feature ); } @@ -5292,10 +5493,12 @@ if ( !memory || !alibrary ) return FT_THROW( Invalid_Argument ); +#ifndef FT_DEBUG_LOGGING #ifdef FT_DEBUG_LEVEL_ERROR /* init debugging support */ ft_debug_init(); -#endif +#endif /* FT_DEBUG_LEVEL_ERROR */ +#endif /* !FT_DEBUG_LOGGING */ /* first of all, allocate the library object */ if ( FT_NEW( library ) ) @@ -5567,4 +5770,145 @@ } + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Bool ) + FT_Get_Color_Glyph_Paint( FT_Face face, + FT_UInt base_glyph, + FT_Color_Root_Transform root_transform, + FT_OpaquePaint* paint ) + { + TT_Face ttface; + SFNT_Service sfnt; + + + if ( !face || !paint ) + return 0; + + if ( !FT_IS_SFNT( face ) ) + return 0; + + ttface = (TT_Face)face; + sfnt = (SFNT_Service)ttface->sfnt; + + if ( sfnt->get_colr_layer ) + return sfnt->get_colr_glyph_paint( ttface, + base_glyph, + root_transform, + paint ); + else + return 0; + } + + + /* documentation is in ftcolor.h */ + + FT_EXPORT_DEF( FT_Bool ) + FT_Get_Color_Glyph_ClipBox( FT_Face face, + FT_UInt base_glyph, + FT_ClipBox* clip_box ) + { + TT_Face ttface; + SFNT_Service sfnt; + + + if ( !face || !clip_box ) + return 0; + + if ( !FT_IS_SFNT( face ) ) + return 0; + + ttface = (TT_Face)face; + sfnt = (SFNT_Service)ttface->sfnt; + + if ( sfnt->get_color_glyph_clipbox ) + return sfnt->get_color_glyph_clipbox( ttface, + base_glyph, + clip_box ); + else + return 0; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Bool ) + FT_Get_Paint_Layers( FT_Face face, + FT_LayerIterator* layer_iterator, + FT_OpaquePaint* paint ) + { + TT_Face ttface; + SFNT_Service sfnt; + + + if ( !face || !paint || !layer_iterator ) + return 0; + + if ( !FT_IS_SFNT( face ) ) + return 0; + + ttface = (TT_Face)face; + sfnt = (SFNT_Service)ttface->sfnt; + + if ( sfnt->get_paint_layers ) + return sfnt->get_paint_layers( ttface, layer_iterator, paint ); + else + return 0; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Bool ) + FT_Get_Paint( FT_Face face, + FT_OpaquePaint opaque_paint, + FT_COLR_Paint* paint ) + { + TT_Face ttface; + SFNT_Service sfnt; + + + if ( !face || !paint ) + return 0; + + if ( !FT_IS_SFNT( face ) ) + return 0; + + ttface = (TT_Face)face; + sfnt = (SFNT_Service)ttface->sfnt; + + if ( sfnt->get_paint ) + return sfnt->get_paint( ttface, opaque_paint, paint ); + else + return 0; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Bool ) + FT_Get_Colorline_Stops ( FT_Face face, + FT_ColorStop * color_stop, + FT_ColorStopIterator *iterator ) + { + TT_Face ttface; + SFNT_Service sfnt; + + + if ( !face || !color_stop || !iterator ) + return 0; + + if ( !FT_IS_SFNT( face ) ) + return 0; + + ttface = (TT_Face)face; + sfnt = (SFNT_Service)ttface->sfnt; + + if ( sfnt->get_colorline_stops ) + return sfnt->get_colorline_stops ( ttface, color_stop, iterator ); + else + return 0; + } + + /* END */ diff --git a/lib/libesp32_lvgl/freetype/src/base/ftotval.c b/lib/libesp32_lvgl/freetype/src/base/ftotval.c index 90a5dd617..192e12a71 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftotval.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftotval.c @@ -4,7 +4,7 @@ * * FreeType API for validating OpenType tables (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/base/ftoutln.c b/lib/libesp32_lvgl/freetype/src/base/ftoutln.c index 311f098e3..134f39d2b 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftoutln.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftoutln.c @@ -4,7 +4,7 @@ * * FreeType outline management (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -58,7 +58,9 @@ FT_Error error; FT_Int n; /* index of contour in outline */ - FT_UInt first; /* index of first point in contour */ + FT_Int first; /* index of first point in contour */ + FT_Int last; /* index of last point in contour */ + FT_Int tag; /* current point's state */ FT_Int shift; @@ -73,18 +75,17 @@ shift = func_interface->shift; delta = func_interface->delta; - first = 0; + last = -1; for ( n = 0; n < outline->n_contours; n++ ) { - FT_Int last; /* index of last point in contour */ + FT_TRACE5(( "FT_Outline_Decompose: Contour %d\n", n )); - - FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n )); - - last = outline->contours[n]; - if ( last < 0 ) + first = last + 1; + last = outline->contours[n]; + if ( last < first ) goto Invalid_Outline; + limit = outline->points + last; v_start = outline->points[first]; @@ -130,7 +131,7 @@ } FT_TRACE5(( " move to (%.2f, %.2f)\n", - v_start.x / 64.0, v_start.y / 64.0 )); + (double)v_start.x / 64, (double)v_start.y / 64 )); error = func_interface->move_to( &v_start, user ); if ( error ) goto Exit; @@ -152,7 +153,7 @@ vec.y = SCALED( point->y ); FT_TRACE5(( " line to (%.2f, %.2f)\n", - vec.x / 64.0, vec.y / 64.0 )); + (double)vec.x / 64, (double)vec.y / 64 )); error = func_interface->line_to( &vec, user ); if ( error ) goto Exit; @@ -181,8 +182,10 @@ { FT_TRACE5(( " conic to (%.2f, %.2f)" " with control (%.2f, %.2f)\n", - vec.x / 64.0, vec.y / 64.0, - v_control.x / 64.0, v_control.y / 64.0 )); + (double)vec.x / 64, + (double)vec.y / 64, + (double)v_control.x / 64, + (double)v_control.y / 64 )); error = func_interface->conic_to( &v_control, &vec, user ); if ( error ) goto Exit; @@ -197,8 +200,10 @@ FT_TRACE5(( " conic to (%.2f, %.2f)" " with control (%.2f, %.2f)\n", - v_middle.x / 64.0, v_middle.y / 64.0, - v_control.x / 64.0, v_control.y / 64.0 )); + (double)v_middle.x / 64, + (double)v_middle.y / 64, + (double)v_control.x / 64, + (double)v_control.y / 64 )); error = func_interface->conic_to( &v_control, &v_middle, user ); if ( error ) goto Exit; @@ -209,8 +214,10 @@ FT_TRACE5(( " conic to (%.2f, %.2f)" " with control (%.2f, %.2f)\n", - v_start.x / 64.0, v_start.y / 64.0, - v_control.x / 64.0, v_control.y / 64.0 )); + (double)v_start.x / 64, + (double)v_start.y / 64, + (double)v_control.x / 64, + (double)v_control.y / 64 )); error = func_interface->conic_to( &v_control, &v_start, user ); goto Close; @@ -242,9 +249,12 @@ FT_TRACE5(( " cubic to (%.2f, %.2f)" " with controls (%.2f, %.2f) and (%.2f, %.2f)\n", - vec.x / 64.0, vec.y / 64.0, - vec1.x / 64.0, vec1.y / 64.0, - vec2.x / 64.0, vec2.y / 64.0 )); + (double)vec.x / 64, + (double)vec.y / 64, + (double)vec1.x / 64, + (double)vec1.y / 64, + (double)vec2.x / 64, + (double)vec2.y / 64 )); error = func_interface->cubic_to( &vec1, &vec2, &vec, user ); if ( error ) goto Exit; @@ -253,9 +263,12 @@ FT_TRACE5(( " cubic to (%.2f, %.2f)" " with controls (%.2f, %.2f) and (%.2f, %.2f)\n", - v_start.x / 64.0, v_start.y / 64.0, - vec1.x / 64.0, vec1.y / 64.0, - vec2.x / 64.0, vec2.y / 64.0 )); + (double)v_start.x / 64, + (double)v_start.y / 64, + (double)vec1.x / 64, + (double)vec1.y / 64, + (double)vec2.x / 64, + (double)vec2.y / 64 )); error = func_interface->cubic_to( &vec1, &vec2, &v_start, user ); goto Close; } @@ -264,14 +277,12 @@ /* close the contour with a line segment */ FT_TRACE5(( " line to (%.2f, %.2f)\n", - v_start.x / 64.0, v_start.y / 64.0 )); + (double)v_start.x / 64, (double)v_start.y / 64 )); error = func_interface->line_to( &v_start, user ); Close: if ( error ) goto Exit; - - first = (FT_UInt)last + 1; } FT_TRACE5(( "FT_Outline_Decompose: Done\n" )); @@ -356,7 +367,7 @@ if ( n_points <= 0 || n_contours <= 0 ) goto Bad; - end0 = end = -1; + end0 = -1; for ( n = 0; n < n_contours; n++ ) { end = outline->contours[n]; @@ -368,7 +379,7 @@ end0 = end; } - if ( end != n_points - 1 ) + if ( end0 != n_points - 1 ) goto Bad; /* XXX: check the tags array */ @@ -376,7 +387,7 @@ } Bad: - return FT_THROW( Invalid_Argument ); + return FT_THROW( Invalid_Outline ); } @@ -538,10 +549,12 @@ if ( !outline ) return; - first = 0; - + last = -1; for ( n = 0; n < outline->n_contours; n++ ) { + /* keep the first contour point as is and swap points around it */ + /* to guarantee that the cubic arches stay valid after reverse */ + first = last + 2; last = outline->contours[n]; /* reverse point table */ @@ -579,8 +592,6 @@ q--; } } - - first = last + 1; } outline->flags ^= FT_OUTLINE_REVERSE_FILL; @@ -929,7 +940,7 @@ points = outline->points; - first = 0; + last = -1; for ( c = 0; c < outline->n_contours; c++ ) { FT_Vector in, out, anchor, shift; @@ -937,8 +948,9 @@ FT_Int i, j, k; - l_in = 0; - last = outline->contours[c]; + first = last + 1; + last = outline->contours[c]; + l_in = 0; /* pacify compiler */ in.x = in.y = anchor.x = anchor.y = 0; @@ -1025,8 +1037,6 @@ in = out; l_in = l_out; } - - first = last + 1; } return FT_Err_Ok; @@ -1042,7 +1052,7 @@ FT_Int xshift, yshift; FT_Vector* points; FT_Vector v_prev, v_cur; - FT_Int c, n, first; + FT_Int c, n, first, last; FT_Pos area = 0; @@ -1074,11 +1084,11 @@ points = outline->points; - first = 0; + last = -1; for ( c = 0; c < outline->n_contours; c++ ) { - FT_Int last = outline->contours[c]; - + first = last + 1; + last = outline->contours[c]; v_prev.x = points[last].x >> xshift; v_prev.y = points[last].y >> yshift; @@ -1094,8 +1104,6 @@ v_prev = v_cur; } - - first = last + 1; } if ( area > 0 ) diff --git a/lib/libesp32_lvgl/freetype/src/base/ftpatent.c b/lib/libesp32_lvgl/freetype/src/base/ftpatent.c index a02c636a6..cb5efadff 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftpatent.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftpatent.c @@ -5,7 +5,7 @@ * FreeType API for checking patented TrueType bytecode instructions * (body). Obsolete, retained for backward compatibility. * - * Copyright (C) 2007-2020 by + * Copyright (C) 2007-2023 by * David Turner. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/base/ftpfr.c b/lib/libesp32_lvgl/freetype/src/base/ftpfr.c index c656fcd9b..378385a59 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftpfr.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftpfr.c @@ -4,7 +4,7 @@ * * FreeType API for accessing PFR-specific data (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/base/ftpsprop.c b/lib/libesp32_lvgl/freetype/src/base/ftpsprop.c index 8c29f50f6..cefdf489d 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftpsprop.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftpsprop.c @@ -5,7 +5,7 @@ * Get and set properties of PostScript drivers (body). * See `ftdriver.h' for available properties. * - * Copyright (C) 2017-2020 by + * Copyright (C) 2017-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -220,7 +220,7 @@ return error; } - FT_TRACE0(( "ps_property_set: missing property `%s'\n", + FT_TRACE2(( "ps_property_set: missing property `%s'\n", property_name )); return FT_THROW( Missing_Property ); } @@ -275,7 +275,7 @@ return error; } - FT_TRACE0(( "ps_property_get: missing property `%s'\n", + FT_TRACE2(( "ps_property_get: missing property `%s'\n", property_name )); return FT_THROW( Missing_Property ); } diff --git a/lib/libesp32_lvgl/freetype/src/base/ftrfork.c b/lib/libesp32_lvgl/freetype/src/base/ftrfork.c index f989be47f..2ab430195 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftrfork.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftrfork.c @@ -4,7 +4,7 @@ * * Embedded resource forks accessor (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * Masatake YAMATO and Redhat K.K. * * FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are @@ -167,16 +167,11 @@ } - static int - ft_raccess_sort_ref_by_id( FT_RFork_Ref* a, - FT_RFork_Ref* b ) + FT_COMPARE_DEF( int ) + ft_raccess_sort_ref_by_id( const void* a, + const void* b ) { - if ( a->res_id < b->res_id ) - return -1; - else if ( a->res_id > b->res_id ) - return 1; - else - return 0; + return ( (FT_RFork_Ref*)a )->res_id - ( (FT_RFork_Ref*)b )->res_id; } @@ -256,7 +251,7 @@ if ( error ) return error; - if ( FT_NEW_ARRAY( ref, *count ) ) + if ( FT_QNEW_ARRAY( ref, *count ) ) return error; for ( j = 0; j < *count; j++ ) @@ -294,8 +289,7 @@ ft_qsort( ref, (size_t)*count, sizeof ( FT_RFork_Ref ), - ( int(*)(const void*, - const void*) )ft_raccess_sort_ref_by_id ); + ft_raccess_sort_ref_by_id ); FT_TRACE3(( " -- sort resources by their ids --\n" )); @@ -305,7 +299,7 @@ j, ref[j].res_id, ref[j].offset )); } - if ( FT_NEW_ARRAY( offsets_internal, *count ) ) + if ( FT_QNEW_ARRAY( offsets_internal, *count ) ) goto Exit; /* XXX: duplicated reference ID, @@ -408,17 +402,17 @@ FT_Long *result_offset ); - CONST_FT_RFORK_RULE_ARRAY_BEGIN(ft_raccess_guess_table, - ft_raccess_guess_rec) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_double, apple_double) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_single, apple_single) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_ufs_export, darwin_ufs_export) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_newvfs, darwin_newvfs) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_hfsplus, darwin_hfsplus) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(vfat, vfat) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_cap, linux_cap) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_double, linux_double) - CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_netatalk, linux_netatalk) + CONST_FT_RFORK_RULE_ARRAY_BEGIN( ft_raccess_guess_table, + ft_raccess_guess_rec ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( apple_double, apple_double ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( apple_single, apple_single ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_ufs_export, darwin_ufs_export ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_newvfs, darwin_newvfs ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_hfsplus, darwin_hfsplus ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( vfat, vfat ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_cap, linux_cap ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_double, linux_double ) + CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_netatalk, linux_netatalk ) CONST_FT_RFORK_RULE_ARRAY_END @@ -608,7 +602,7 @@ if ( base_file_len + 6 > FT_INT_MAX ) return FT_THROW( Array_Too_Large ); - if ( FT_ALLOC( newpath, base_file_len + 6 ) ) + if ( FT_QALLOC( newpath, base_file_len + 6 ) ) return error; FT_MEM_COPY( newpath, base_file_name, base_file_len ); @@ -644,7 +638,7 @@ if ( base_file_len + 18 > FT_INT_MAX ) return FT_THROW( Array_Too_Large ); - if ( FT_ALLOC( newpath, base_file_len + 18 ) ) + if ( FT_QALLOC( newpath, base_file_len + 18 ) ) return error; FT_MEM_COPY( newpath, base_file_name, base_file_len ); @@ -874,13 +868,11 @@ const char* tmp; const char* slash; size_t new_length; - FT_Error error = FT_Err_Ok; - - FT_UNUSED( error ); + FT_Error error; new_length = ft_strlen( original_name ) + ft_strlen( insertion ); - if ( FT_ALLOC( new_name, new_length + 1 ) ) + if ( FT_QALLOC( new_name, new_length + 1 ) ) return NULL; tmp = ft_strrchr( original_name, '/' ); diff --git a/lib/libesp32_lvgl/freetype/src/base/ftsnames.c b/lib/libesp32_lvgl/freetype/src/base/ftsnames.c index 8507f28d3..1917a3f1d 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftsnames.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftsnames.c @@ -7,7 +7,7 @@ * * This is _not_ used to retrieve glyph names! * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -65,7 +65,7 @@ FT_Stream stream = face->stream; - if ( FT_NEW_ARRAY ( entry->string, entry->stringLength ) || + if ( FT_QNEW_ARRAY ( entry->string, entry->stringLength ) || FT_STREAM_SEEK( entry->stringOffset ) || FT_STREAM_READ( entry->string, entry->stringLength ) ) { @@ -121,7 +121,7 @@ FT_Stream stream = face->stream; - if ( FT_NEW_ARRAY ( entry->string, entry->stringLength ) || + if ( FT_QNEW_ARRAY ( entry->string, entry->stringLength ) || FT_STREAM_SEEK( entry->stringOffset ) || FT_STREAM_READ( entry->string, entry->stringLength ) ) { diff --git a/lib/libesp32_lvgl/freetype/src/base/ftstream.c b/lib/libesp32_lvgl/freetype/src/base/ftstream.c index d940254d8..64826aceb 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftstream.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftstream.c @@ -4,7 +4,7 @@ * * I/O stream support (body). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -61,7 +61,7 @@ if ( stream->read ) { - if ( stream->read( stream, pos, 0, 0 ) ) + if ( stream->read( stream, pos, NULL, 0 ) ) { FT_ERROR(( "FT_Stream_Seek:" " invalid i/o; pos = 0x%lx, size = 0x%lx\n", @@ -141,7 +141,9 @@ if ( read_bytes > count ) read_bytes = count; - FT_MEM_COPY( buffer, stream->base + pos, read_bytes ); + /* Allow "reading" zero bytes without UB even if buffer is NULL */ + if ( count ) + FT_MEM_COPY( buffer, stream->base + pos, read_bytes ); } stream->pos = pos + read_bytes; @@ -178,7 +180,9 @@ if ( read_bytes > count ) read_bytes = count; - FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes ); + /* Allow "reading" zero bytes without UB even if buffer is NULL */ + if ( count ) + FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes ); } stream->pos += read_bytes; @@ -261,7 +265,7 @@ } #ifdef FT_DEBUG_MEMORY - /* assume _ft_debug_file and _ft_debug_lineno are already set */ + /* assume `ft_debug_file_` and `ft_debug_lineno_` are already set */ stream->base = (unsigned char*)ft_mem_qalloc( memory, (FT_Long)count, &error ); @@ -347,27 +351,27 @@ } - FT_BASE_DEF( FT_Char ) - FT_Stream_GetChar( FT_Stream stream ) + FT_BASE_DEF( FT_Byte ) + FT_Stream_GetByte( FT_Stream stream ) { - FT_Char result; + FT_Byte result; FT_ASSERT( stream && stream->cursor ); result = 0; if ( stream->cursor < stream->limit ) - result = (FT_Char)*stream->cursor++; + result = *stream->cursor++; return result; } - FT_BASE_DEF( FT_UShort ) + FT_BASE_DEF( FT_UInt16 ) FT_Stream_GetUShort( FT_Stream stream ) { FT_Byte* p; - FT_UShort result; + FT_UInt16 result; FT_ASSERT( stream && stream->cursor ); @@ -382,11 +386,11 @@ } - FT_BASE_DEF( FT_UShort ) + FT_BASE_DEF( FT_UInt16 ) FT_Stream_GetUShortLE( FT_Stream stream ) { FT_Byte* p; - FT_UShort result; + FT_UInt16 result; FT_ASSERT( stream && stream->cursor ); @@ -401,11 +405,11 @@ } - FT_BASE_DEF( FT_ULong ) + FT_BASE_DEF( FT_UInt32 ) FT_Stream_GetUOffset( FT_Stream stream ) { FT_Byte* p; - FT_ULong result; + FT_UInt32 result; FT_ASSERT( stream && stream->cursor ); @@ -419,11 +423,11 @@ } - FT_BASE_DEF( FT_ULong ) + FT_BASE_DEF( FT_UInt32 ) FT_Stream_GetULong( FT_Stream stream ) { FT_Byte* p; - FT_ULong result; + FT_UInt32 result; FT_ASSERT( stream && stream->cursor ); @@ -437,11 +441,11 @@ } - FT_BASE_DEF( FT_ULong ) + FT_BASE_DEF( FT_UInt32 ) FT_Stream_GetULongLE( FT_Stream stream ) { FT_Byte* p; - FT_ULong result; + FT_UInt32 result; FT_ASSERT( stream && stream->cursor ); @@ -455,8 +459,8 @@ } - FT_BASE_DEF( FT_Char ) - FT_Stream_ReadChar( FT_Stream stream, + FT_BASE_DEF( FT_Byte ) + FT_Stream_ReadByte( FT_Stream stream, FT_Error* error ) { FT_Byte result = 0; @@ -464,47 +468,46 @@ FT_ASSERT( stream ); - *error = FT_Err_Ok; - - if ( stream->read ) + if ( stream->pos < stream->size ) { - if ( stream->read( stream, stream->pos, &result, 1L ) != 1L ) - goto Fail; + if ( stream->read ) + { + if ( stream->read( stream, stream->pos, &result, 1L ) != 1L ) + goto Fail; + } + else + result = stream->base[stream->pos]; } else - { - if ( stream->pos < stream->size ) - result = stream->base[stream->pos]; - else - goto Fail; - } + goto Fail; + stream->pos++; - return (FT_Char)result; + *error = FT_Err_Ok; + + return result; Fail: *error = FT_THROW( Invalid_Stream_Operation ); - FT_ERROR(( "FT_Stream_ReadChar:" + FT_ERROR(( "FT_Stream_ReadByte:" " invalid i/o; pos = 0x%lx, size = 0x%lx\n", stream->pos, stream->size )); - return 0; + return result; } - FT_BASE_DEF( FT_UShort ) + FT_BASE_DEF( FT_UInt16 ) FT_Stream_ReadUShort( FT_Stream stream, FT_Error* error ) { FT_Byte reads[2]; - FT_Byte* p = 0; - FT_UShort result = 0; + FT_Byte* p; + FT_UInt16 result = 0; FT_ASSERT( stream ); - *error = FT_Err_Ok; - if ( stream->pos + 1 < stream->size ) { if ( stream->read ) @@ -525,6 +528,8 @@ stream->pos += 2; + *error = FT_Err_Ok; + return result; Fail: @@ -533,23 +538,21 @@ " invalid i/o; pos = 0x%lx, size = 0x%lx\n", stream->pos, stream->size )); - return 0; + return result; } - FT_BASE_DEF( FT_UShort ) + FT_BASE_DEF( FT_UInt16 ) FT_Stream_ReadUShortLE( FT_Stream stream, FT_Error* error ) { FT_Byte reads[2]; - FT_Byte* p = 0; - FT_UShort result = 0; + FT_Byte* p; + FT_UInt16 result = 0; FT_ASSERT( stream ); - *error = FT_Err_Ok; - if ( stream->pos + 1 < stream->size ) { if ( stream->read ) @@ -570,6 +573,8 @@ stream->pos += 2; + *error = FT_Err_Ok; + return result; Fail: @@ -578,7 +583,7 @@ " invalid i/o; pos = 0x%lx, size = 0x%lx\n", stream->pos, stream->size )); - return 0; + return result; } @@ -587,14 +592,12 @@ FT_Error* error ) { FT_Byte reads[3]; - FT_Byte* p = 0; + FT_Byte* p; FT_ULong result = 0; FT_ASSERT( stream ); - *error = FT_Err_Ok; - if ( stream->pos + 2 < stream->size ) { if ( stream->read ) @@ -615,6 +618,8 @@ stream->pos += 3; + *error = FT_Err_Ok; + return result; Fail: @@ -623,23 +628,21 @@ " invalid i/o; pos = 0x%lx, size = 0x%lx\n", stream->pos, stream->size )); - return 0; + return result; } - FT_BASE_DEF( FT_ULong ) + FT_BASE_DEF( FT_UInt32 ) FT_Stream_ReadULong( FT_Stream stream, FT_Error* error ) { FT_Byte reads[4]; - FT_Byte* p = 0; - FT_ULong result = 0; + FT_Byte* p; + FT_UInt32 result = 0; FT_ASSERT( stream ); - *error = FT_Err_Ok; - if ( stream->pos + 3 < stream->size ) { if ( stream->read ) @@ -660,6 +663,8 @@ stream->pos += 4; + *error = FT_Err_Ok; + return result; Fail: @@ -668,23 +673,21 @@ " invalid i/o; pos = 0x%lx, size = 0x%lx\n", stream->pos, stream->size )); - return 0; + return result; } - FT_BASE_DEF( FT_ULong ) + FT_BASE_DEF( FT_UInt32 ) FT_Stream_ReadULongLE( FT_Stream stream, FT_Error* error ) { FT_Byte reads[4]; - FT_Byte* p = 0; - FT_ULong result = 0; + FT_Byte* p; + FT_UInt32 result = 0; FT_ASSERT( stream ); - *error = FT_Err_Ok; - if ( stream->pos + 3 < stream->size ) { if ( stream->read ) @@ -705,6 +708,8 @@ stream->pos += 4; + *error = FT_Err_Ok; + return result; Fail: @@ -713,7 +718,7 @@ " invalid i/o; pos = 0x%lx, size = 0x%lx\n", stream->pos, stream->size )); - return 0; + return result; } diff --git a/lib/libesp32_lvgl/freetype/src/base/ftstroke.c b/lib/libesp32_lvgl/freetype/src/base/ftstroke.c index 56f98e1d9..92f1e4308 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftstroke.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftstroke.c @@ -4,7 +4,7 @@ * * FreeType path stroker (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -974,7 +974,8 @@ FT_StrokeBorder border = stroker->borders + side; FT_Angle phi, theta, rotate; FT_Fixed length; - FT_Vector sigma, delta; + FT_Vector sigma = { 0, 0 }; + FT_Vector delta; FT_Error error = FT_Err_Ok; FT_Bool intersect; /* use intersection of lines? */ @@ -1048,7 +1049,7 @@ { /* this is a mitered (pointed) or beveled (truncated) corner */ FT_Fixed radius = stroker->radius; - FT_Vector sigma; + FT_Vector sigma = { 0, 0 }; FT_Angle theta = 0, phi = 0; FT_Bool bevel, fixed_bevel; @@ -1528,7 +1529,8 @@ stroker->angle_in = angle_out; } - stroker->center = *to; + stroker->center = *to; + stroker->line_length = 0; Exit: return error; @@ -1744,7 +1746,8 @@ stroker->angle_in = angle_out; } - stroker->center = *to; + stroker->center = *to; + stroker->line_length = 0; Exit: return error; @@ -1897,13 +1900,9 @@ } else { - FT_Angle turn; - FT_Int inside_side; - - /* close the path if needed */ - if ( stroker->center.x != stroker->subpath_start.x || - stroker->center.y != stroker->subpath_start.y ) + if ( !FT_IS_SMALL( stroker->center.x - stroker->subpath_start.x ) || + !FT_IS_SMALL( stroker->center.y - stroker->subpath_start.y ) ) { error = FT_Stroker_LineTo( stroker, &stroker->subpath_start ); if ( error ) @@ -1912,29 +1911,11 @@ /* process the corner */ stroker->angle_out = stroker->subpath_angle; - turn = FT_Angle_Diff( stroker->angle_in, - stroker->angle_out ); - /* no specific corner processing is required if the turn is 0 */ - if ( turn != 0 ) - { - /* when we turn to the right, the inside side is 0 */ - /* otherwise, the inside side is 1 */ - inside_side = ( turn < 0 ); - - error = ft_stroker_inside( stroker, - inside_side, - stroker->subpath_line_length ); - if ( error ) - goto Exit; - - /* process the outside side */ - error = ft_stroker_outside( stroker, - !inside_side, - stroker->subpath_line_length ); - if ( error ) - goto Exit; - } + error = ft_stroker_process_corner( stroker, + stroker->subpath_line_length ); + if ( error ) + goto Exit; /* then end our two subpaths */ ft_stroke_border_close( stroker->borders + 0, FALSE ); @@ -2074,7 +2055,9 @@ FT_Error error; FT_Int n; /* index of contour in outline */ - FT_UInt first; /* index of first point in contour */ + FT_Int first; /* index of first point in contour */ + FT_Int last; /* index of last point in contour */ + FT_Int tag; /* current point's state */ @@ -2086,22 +2069,17 @@ FT_Stroker_Rewind( stroker ); - first = 0; - + last = -1; for ( n = 0; n < outline->n_contours; n++ ) { - FT_UInt last; /* index of last point in contour */ - - - last = (FT_UInt)outline->contours[n]; - limit = outline->points + last; + first = last + 1; + last = outline->contours[n]; /* skip empty points; we don't stroke these */ if ( last <= first ) - { - first = last + 1; continue; - } + + limit = outline->points + last; v_start = outline->points[first]; v_last = outline->points[last]; @@ -2250,8 +2228,6 @@ if ( error ) goto Exit; } - - first = last + 1; } return FT_Err_Ok; diff --git a/lib/libesp32_lvgl/freetype/src/base/ftsynth.c b/lib/libesp32_lvgl/freetype/src/base/ftsynth.c index a9119e2b2..f32edd338 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftsynth.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftsynth.c @@ -4,7 +4,7 @@ * * FreeType synthesizing code for emboldening and slanting (body). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -45,6 +45,18 @@ FT_EXPORT_DEF( void ) FT_GlyphSlot_Oblique( FT_GlyphSlot slot ) + { + /* Value '0x0366A' corresponds to a shear angle of about 12 degrees. */ + FT_GlyphSlot_Slant( slot, 0x0366A, 0 ); + } + + + /* documentation is in ftsynth.h */ + + FT_EXPORT_DEF( void ) + FT_GlyphSlot_Slant( FT_GlyphSlot slot, + FT_Fixed xslant, + FT_Fixed yslant ) { FT_Matrix transform; FT_Outline* outline; @@ -61,13 +73,11 @@ /* we don't touch the advance width */ - /* For italic, simply apply a shear transform, with an angle */ - /* of about 12 degrees. */ - + /* For italic, simply apply a shear transform */ transform.xx = 0x10000L; - transform.yx = 0x00000L; + transform.yx = -yslant; - transform.xy = 0x0366AL; + transform.xy = xslant; transform.yy = 0x10000L; FT_Outline_Transform( outline, &transform ); @@ -87,9 +97,18 @@ FT_EXPORT_DEF( void ) FT_GlyphSlot_Embolden( FT_GlyphSlot slot ) + { + FT_GlyphSlot_AdjustWeight( slot, 0x0AAA, 0x0AAA ); + } + + + FT_EXPORT_DEF( void ) + FT_GlyphSlot_AdjustWeight( FT_GlyphSlot slot, + FT_Fixed xdelta, + FT_Fixed ydelta ) { FT_Library library; - FT_Face face; + FT_Size size; FT_Error error; FT_Pos xstr, ystr; @@ -98,16 +117,15 @@ return; library = slot->library; - face = slot->face; + size = slot->face->size; if ( slot->format != FT_GLYPH_FORMAT_OUTLINE && slot->format != FT_GLYPH_FORMAT_BITMAP ) return; - /* some reasonable strength */ - xstr = FT_MulFix( face->units_per_EM, - face->size->metrics.y_scale ) / 24; - ystr = xstr; + /* express deltas in pixels in 26.6 format */ + xstr = (FT_Pos)size->metrics.x_ppem * xdelta / 1024; + ystr = (FT_Pos)size->metrics.y_ppem * ydelta / 1024; if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) FT_Outline_EmboldenXY( &slot->outline, xstr, ystr ); diff --git a/lib/libesp32_lvgl/freetype/src/base/ftsystem.c b/lib/libesp32_lvgl/freetype/src/base/ftsystem.c index 3013cbda9..61c99e363 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftsystem.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftsystem.c @@ -4,7 +4,7 @@ * * ANSI-specific FreeType low-level system interface (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -206,7 +206,7 @@ * The number of bytes to read from the stream. * * @Return: - * The number of bytes actually read. If `count' is zero (this is, + * The number of bytes actually read. If `count' is zero (that is, * the function is used for seeking), a non-zero return value * indicates an error. */ @@ -219,7 +219,7 @@ FT_FILE* file; - if ( !count && offset > stream->size ) + if ( offset > stream->size && !count ) return 1; file = STREAM_FILE( stream ); @@ -227,6 +227,11 @@ if ( stream->pos != offset ) ft_fseek( file, (long)offset, SEEK_SET ); + /* Avoid calling `fread` with `buffer=NULL` and `count=0`, */ + /* which is undefined behaviour. */ + if ( !count ) + return 0; + return (unsigned long)ft_fread( buffer, 1, count, file ); } @@ -275,7 +280,7 @@ stream->close = ft_ansi_stream_close; FT_TRACE1(( "FT_Stream_Open:" )); - FT_TRACE1(( " opened `%s' (%d bytes) successfully\n", + FT_TRACE1(( " opened `%s' (%ld bytes) successfully\n", filepathname, stream->size )); return FT_Err_Ok; diff --git a/lib/libesp32_lvgl/freetype/src/base/fttrigon.c b/lib/libesp32_lvgl/freetype/src/base/fttrigon.c index c6f027cf6..2dd2c3459 100644 --- a/lib/libesp32_lvgl/freetype/src/base/fttrigon.c +++ b/lib/libesp32_lvgl/freetype/src/base/fttrigon.c @@ -4,7 +4,7 @@ * * FreeType trigonometric functions (body). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -53,7 +53,7 @@ }; -#ifdef FT_LONG64 +#ifdef FT_INT64 /* multiply a given value by the CORDIC shrink factor */ static FT_Fixed @@ -76,7 +76,7 @@ return s < 0 ? -val : val; } -#else /* !FT_LONG64 */ +#else /* !FT_INT64 */ /* multiply a given value by the CORDIC shrink factor */ static FT_Fixed @@ -125,7 +125,7 @@ return s < 0 ? -val : val; } -#endif /* !FT_LONG64 */ +#endif /* !FT_INT64 */ /* undefined and never called for zero vector */ diff --git a/lib/libesp32_lvgl/freetype/src/base/fttype1.c b/lib/libesp32_lvgl/freetype/src/base/fttype1.c index be60ed6ec..637c5cf77 100644 --- a/lib/libesp32_lvgl/freetype/src/base/fttype1.c +++ b/lib/libesp32_lvgl/freetype/src/base/fttype1.c @@ -4,7 +4,7 @@ * * FreeType utility file for PS names support (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/base/ftutil.c b/lib/libesp32_lvgl/freetype/src/base/ftutil.c index d90cfbcd2..6120846d2 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftutil.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftutil.c @@ -4,7 +4,7 @@ * * FreeType utility file for memory and list management (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/base/ftver.rc b/lib/libesp32_lvgl/freetype/src/base/ftver.rc index 0b92e9b89..137a6334b 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftver.rc +++ b/lib/libesp32_lvgl/freetype/src/base/ftver.rc @@ -4,7 +4,7 @@ /* */ /* FreeType VERSIONINFO resource for Windows DLLs. */ /* */ -/* Copyright (C) 2018-2020 by */ +/* Copyright (C) 2018-2023 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -18,8 +18,8 @@ #include -#define FT_VERSION 2,10,4,0 -#define FT_VERSION_STR "2.10.4" +#define FT_VERSION 2,13,2,0 +#define FT_VERSION_STR "2.13.2" VS_VERSION_INFO VERSIONINFO FILEVERSION FT_VERSION @@ -38,14 +38,14 @@ FILETYPE VFT_STATIC_LIB BEGIN BLOCK "StringFileInfo" BEGIN - BLOCK "040904E4" + BLOCK "040904B0" BEGIN VALUE "CompanyName", "The FreeType Project" VALUE "FileDescription", "Font Rendering Library" VALUE "FileVersion", FT_VERSION_STR VALUE "ProductName", "FreeType" VALUE "ProductVersion", FT_VERSION_STR - VALUE "LegalCopyright", "\251 2000-2020 The FreeType Project www.freetype.org. All rights reserved." + VALUE "LegalCopyright", L"\x00A9 2000-2023 The FreeType Project www.freetype.org. All rights reserved." VALUE "InternalName", "freetype" VALUE "OriginalFilename", FT_FILENAME END @@ -56,6 +56,6 @@ BEGIN /* The following line should only be modified for localized versions. */ /* It consists of any number of WORD,WORD pairs, with each pair */ /* describing a "language,codepage" combination supported by the file. */ - VALUE "Translation", 0x409, 1252 + VALUE "Translation", 0x409, 1200 END END diff --git a/lib/libesp32_lvgl/freetype/src/base/ftwinfnt.c b/lib/libesp32_lvgl/freetype/src/base/ftwinfnt.c index 699dc3d70..03b023e07 100644 --- a/lib/libesp32_lvgl/freetype/src/base/ftwinfnt.c +++ b/lib/libesp32_lvgl/freetype/src/base/ftwinfnt.c @@ -4,7 +4,7 @@ * * FreeType API for accessing Windows FNT specific info (body). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/base/rules.mk b/lib/libesp32_lvgl/freetype/src/base/rules.mk index 411c4c821..b7de9b5ca 100644 --- a/lib/libesp32_lvgl/freetype/src/base/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/base/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/bdf/README b/lib/libesp32_lvgl/freetype/src/bdf/README index 996ac2d2a..d7cb8c14e 100644 --- a/lib/libesp32_lvgl/freetype/src/bdf/README +++ b/lib/libesp32_lvgl/freetype/src/bdf/README @@ -13,7 +13,7 @@ This code implements a BDF driver for the FreeType library, following the Adobe Specification V 2.2. The specification of the BDF font format is available from Adobe's web site: - https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5005.BDF_Spec.pdf + https://adobe-type-tools.github.io/font-tech-notes/pdfs/5005.BDF_Spec.pdf Many good bitmap fonts in bdf format come with XFree86 (www.XFree86.org). They do not define vertical metrics, because the X Consortium BDF @@ -23,6 +23,10 @@ specification has removed them. Encodings ********* +[This section is out of date, retained for historical reasons. BDF + properties can be retrieved with `FT_Get_BDF_Property`, character set ID + values with `FT_Get_BDF_Charset_ID`.] + The variety of encodings that accompanies bdf fonts appears to encompass the small set defined in freetype.h. On the other hand, two properties that specify encoding and registry are usually defined in bdf fonts. diff --git a/lib/libesp32_lvgl/freetype/src/bdf/bdf.h b/lib/libesp32_lvgl/freetype/src/bdf/bdf.h index 5acbd5f2f..e2cb52c10 100644 --- a/lib/libesp32_lvgl/freetype/src/bdf/bdf.h +++ b/lib/libesp32_lvgl/freetype/src/bdf/bdf.h @@ -239,10 +239,6 @@ FT_BEGIN_HEADER FT_LOCAL( void ) bdf_free_font( bdf_font_t* font ); - FT_LOCAL( bdf_property_t * ) - bdf_get_property( char* name, - bdf_font_t* font ); - FT_LOCAL( bdf_property_t * ) bdf_get_font_property( bdf_font_t* font, const char* name ); diff --git a/lib/libesp32_lvgl/freetype/src/bdf/bdfdrivr.c b/lib/libesp32_lvgl/freetype/src/bdf/bdfdrivr.c index d29188b97..e02a16093 100644 --- a/lib/libesp32_lvgl/freetype/src/bdf/bdfdrivr.c +++ b/lib/libesp32_lvgl/freetype/src/bdf/bdfdrivr.c @@ -92,24 +92,18 @@ THE SOFTWARE. { BDF_CMap cmap = (BDF_CMap)bdfcmap; BDF_encoding_el* encodings = cmap->encodings; - FT_ULong min, max, mid; /* num_encodings */ FT_UShort result = 0; /* encodings->glyph */ + FT_ULong min = 0; + FT_ULong max = cmap->num_encodings; + FT_ULong mid = ( min + max ) >> 1; - min = 0; - max = cmap->num_encodings; - mid = ( min + max ) >> 1; while ( min < max ) { - FT_ULong code; + FT_ULong code = encodings[mid].enc; - if ( mid >= max || mid < min ) - mid = ( min + max ) >> 1; - - code = encodings[mid].enc; - if ( charcode == code ) { /* increase glyph index by 1 -- */ @@ -123,8 +117,10 @@ THE SOFTWARE. else min = mid + 1; - /* prediction in a continuous block */ + /* reasonable prediction in a continuous block */ mid += charcode - code; + if ( mid >= max || mid < min ) + mid = ( min + max ) >> 1; } return result; @@ -137,25 +133,19 @@ THE SOFTWARE. { BDF_CMap cmap = (BDF_CMap)bdfcmap; BDF_encoding_el* encodings = cmap->encodings; - FT_ULong min, max, mid; /* num_encodings */ FT_UShort result = 0; /* encodings->glyph */ FT_ULong charcode = *acharcode + 1; + FT_ULong min = 0; + FT_ULong max = cmap->num_encodings; + FT_ULong mid = ( min + max ) >> 1; - min = 0; - max = cmap->num_encodings; - mid = ( min + max ) >> 1; while ( min < max ) { - FT_ULong code; /* same as BDF_encoding_el.enc */ + FT_ULong code = encodings[mid].enc; - if ( mid >= max || mid < min ) - mid = ( min + max ) >> 1; - - code = encodings[mid].enc; - if ( charcode == code ) { /* increase glyph index by 1 -- */ @@ -171,6 +161,8 @@ THE SOFTWARE. /* prediction in a continuous block */ mid += charcode - code; + if ( mid >= max || mid < min ) + mid = ( min + max ) >> 1; } charcode = 0; @@ -276,7 +268,7 @@ THE SOFTWARE. char* s; - if ( FT_ALLOC( face->style_name, len ) ) + if ( FT_QALLOC( face->style_name, len ) ) return error; s = face->style_name; @@ -319,9 +311,9 @@ THE SOFTWARE. FT_CALLBACK_DEF( void ) - BDF_Face_Done( FT_Face bdfface ) /* BDF_Face */ + BDF_Face_Done( FT_Face face ) /* BDF_Face */ { - BDF_Face face = (BDF_Face)bdfface; + BDF_Face bdfface = (BDF_Face)face; FT_Memory memory; @@ -330,31 +322,31 @@ THE SOFTWARE. memory = FT_FACE_MEMORY( face ); - bdf_free_font( face->bdffont ); + bdf_free_font( bdfface->bdffont ); - FT_FREE( face->en_table ); + FT_FREE( bdfface->en_table ); - FT_FREE( face->charset_encoding ); - FT_FREE( face->charset_registry ); - FT_FREE( bdfface->family_name ); - FT_FREE( bdfface->style_name ); + FT_FREE( bdfface->charset_encoding ); + FT_FREE( bdfface->charset_registry ); + FT_FREE( face->family_name ); + FT_FREE( face->style_name ); - FT_FREE( bdfface->available_sizes ); + FT_FREE( face->available_sizes ); - FT_FREE( face->bdffont ); + FT_FREE( bdfface->bdffont ); } FT_CALLBACK_DEF( FT_Error ) BDF_Face_Init( FT_Stream stream, - FT_Face bdfface, /* BDF_Face */ + FT_Face face, /* BDF_Face */ FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { - FT_Error error = FT_Err_Ok; - BDF_Face face = (BDF_Face)bdfface; - FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Error error = FT_Err_Ok; + BDF_Face bdfface = (BDF_Face)face; + FT_Memory memory = FT_FACE_MEMORY( face ); bdf_font_t* font = NULL; bdf_options_t options; @@ -383,7 +375,7 @@ THE SOFTWARE. goto Exit; /* we have a bdf font: let's construct the face object */ - face->bdffont = font; + bdfface->bdffont = font; /* BDF cannot have multiple faces in a single font file. * XXX: non-zero face_index is already invalid argument, but @@ -394,7 +386,7 @@ THE SOFTWARE. if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 ) { FT_ERROR(( "BDF_Face_Init: invalid face index\n" )); - BDF_Face_Done( bdfface ); + BDF_Face_Done( face ); return FT_THROW( Invalid_Argument ); } @@ -409,18 +401,18 @@ THE SOFTWARE. font->unencoded_size, font->unencoded_used )); - bdfface->num_faces = 1; - bdfface->face_index = 0; + face->num_faces = 1; + face->face_index = 0; - bdfface->face_flags |= FT_FACE_FLAG_FIXED_SIZES | - FT_FACE_FLAG_HORIZONTAL; + face->face_flags |= FT_FACE_FLAG_FIXED_SIZES | + FT_FACE_FLAG_HORIZONTAL; prop = bdf_get_font_property( font, "SPACING" ); if ( prop && prop->format == BDF_ATOM && prop->value.atom && ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' || *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) ) - bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + face->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */ /* FZ XXX: I need a font to implement this */ @@ -428,31 +420,30 @@ THE SOFTWARE. prop = bdf_get_font_property( font, "FAMILY_NAME" ); if ( prop && prop->value.atom ) { - if ( FT_STRDUP( bdfface->family_name, prop->value.atom ) ) + if ( FT_STRDUP( face->family_name, prop->value.atom ) ) goto Exit; } else - bdfface->family_name = NULL; + face->family_name = NULL; - if ( FT_SET_ERROR( bdf_interpret_style( face ) ) ) + if ( FT_SET_ERROR( bdf_interpret_style( bdfface ) ) ) goto Exit; /* the number of glyphs (with one slot for the undefined glyph */ /* at position 0 and all unencoded glyphs) */ - bdfface->num_glyphs = (FT_Long)( font->glyphs_size + 1 ); + face->num_glyphs = (FT_Long)( font->glyphs_size + 1 ); - bdfface->num_fixed_sizes = 1; - if ( FT_NEW_ARRAY( bdfface->available_sizes, 1 ) ) + face->num_fixed_sizes = 1; + if ( FT_NEW( face->available_sizes ) ) goto Exit; { - FT_Bitmap_Size* bsize = bdfface->available_sizes; - FT_Short resolution_x = 0, resolution_y = 0; + FT_Bitmap_Size* bsize = face->available_sizes; + FT_Short resolution_x = 0; + FT_Short resolution_y = 0; long value; - FT_ZERO( bsize ); - /* sanity checks */ if ( font->font_ascent > 0x7FFF || font->font_ascent < -0x7FFF ) { @@ -489,7 +480,7 @@ THE SOFTWARE. else { /* this is a heuristical value */ - bsize->width = (FT_Short)FT_MulDiv( bsize->height, 2, 3 ); + bsize->width = ( bsize->height * 2 + 1 ) / 3; } prop = bdf_get_font_property( font, "POINT_SIZE" ); @@ -608,20 +599,20 @@ THE SOFTWARE. unsigned long n; - if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) ) + if ( FT_QNEW_ARRAY( bdfface->en_table, font->glyphs_size ) ) goto Exit; - face->default_glyph = 0; + bdfface->default_glyph = 0; for ( n = 0; n < font->glyphs_size; n++ ) { - (face->en_table[n]).enc = cur[n].encoding; + (bdfface->en_table[n]).enc = cur[n].encoding; FT_TRACE4(( " idx %ld, val 0x%lX\n", n, cur[n].encoding )); - (face->en_table[n]).glyph = (FT_UShort)n; + (bdfface->en_table[n]).glyph = (FT_UShort)n; if ( cur[n].encoding == font->default_char ) { if ( n < FT_UINT_MAX ) - face->default_glyph = (FT_UInt)n; + bdfface->default_glyph = (FT_UInt)n; else FT_TRACE1(( "BDF_Face_Init:" " idx %ld is too large for this system\n", n )); @@ -649,27 +640,27 @@ THE SOFTWARE. const char* s; - if ( FT_STRDUP( face->charset_encoding, + if ( FT_STRDUP( bdfface->charset_encoding, charset_encoding->value.atom ) || - FT_STRDUP( face->charset_registry, + FT_STRDUP( bdfface->charset_registry, charset_registry->value.atom ) ) goto Exit; /* Uh, oh, compare first letters manually to avoid dependency */ /* on locales. */ - s = face->charset_registry; + s = bdfface->charset_registry; if ( ( s[0] == 'i' || s[0] == 'I' ) && ( s[1] == 's' || s[1] == 'S' ) && ( s[2] == 'o' || s[2] == 'O' ) ) { s += 3; - if ( !ft_strcmp( s, "10646" ) || - ( !ft_strcmp( s, "8859" ) && - !ft_strcmp( face->charset_encoding, "1" ) ) ) + if ( !ft_strcmp( s, "10646" ) || + ( !ft_strcmp( s, "8859" ) && + !ft_strcmp( bdfface->charset_encoding, "1" ) ) ) unicode_charmap = 1; /* another name for ASCII */ - else if ( !ft_strcmp( s, "646.1991" ) && - !ft_strcmp( face->charset_encoding, "IRV" ) ) + else if ( !ft_strcmp( s, "646.1991" ) && + !ft_strcmp( bdfface->charset_encoding, "IRV" ) ) unicode_charmap = 1; } @@ -677,7 +668,7 @@ THE SOFTWARE. FT_CharMapRec charmap; - charmap.face = FT_FACE( face ); + charmap.face = face; charmap.encoding = FT_ENCODING_NONE; /* initial platform/encoding should indicate unset status? */ charmap.platform_id = TT_PLATFORM_APPLE_UNICODE; @@ -703,7 +694,7 @@ THE SOFTWARE. FT_CharMapRec charmap; - charmap.face = FT_FACE( face ); + charmap.face = face; charmap.encoding = FT_ENCODING_ADOBE_STANDARD; charmap.platform_id = TT_PLATFORM_ADOBE; charmap.encoding_id = TT_ADOBE_ID_STANDARD; @@ -711,8 +702,8 @@ THE SOFTWARE. error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL ); /* Select default charmap */ - if ( bdfface->num_charmaps ) - bdfface->charmap = bdfface->charmaps[0]; + if ( face->num_charmaps ) + face->charmap = face->charmaps[0]; } } } @@ -721,7 +712,7 @@ THE SOFTWARE. return error; Fail: - BDF_Face_Done( bdfface ); + BDF_Face_Done( face ); return FT_THROW( Unknown_File_Format ); } @@ -878,17 +869,18 @@ THE SOFTWARE. * */ - static FT_Error - bdf_get_bdf_property( BDF_Face face, + FT_CALLBACK_DEF( FT_Error ) + bdf_get_bdf_property( FT_Face face, /* BDF_Face */ const char* prop_name, BDF_PropertyRec *aproperty ) { + BDF_Face bdfface = (BDF_Face)face; bdf_property_t* prop; - FT_ASSERT( face && face->bdffont ); + FT_ASSERT( bdfface && bdfface->bdffont ); - prop = bdf_get_font_property( face->bdffont, prop_name ); + prop = bdf_get_font_property( bdfface->bdffont, prop_name ); if ( prop ) { switch ( prop->format ) @@ -931,13 +923,16 @@ THE SOFTWARE. } - static FT_Error - bdf_get_charset_id( BDF_Face face, + FT_CALLBACK_DEF( FT_Error ) + bdf_get_charset_id( FT_Face face, /* BDF_Face */ const char* *acharset_encoding, const char* *acharset_registry ) { - *acharset_encoding = face->charset_encoding; - *acharset_registry = face->charset_registry; + BDF_Face bdfface = (BDF_Face)face; + + + *acharset_encoding = bdfface->charset_encoding; + *acharset_registry = bdfface->charset_registry; return 0; } @@ -974,7 +969,6 @@ THE SOFTWARE. } - FT_CALLBACK_TABLE_DEF const FT_Driver_ClassRec bdf_driver_class = { diff --git a/lib/libesp32_lvgl/freetype/src/bdf/bdflib.c b/lib/libesp32_lvgl/freetype/src/bdf/bdflib.c index a4ddb9a1d..0fa7e0a8c 100644 --- a/lib/libesp32_lvgl/freetype/src/bdf/bdflib.c +++ b/lib/libesp32_lvgl/freetype/src/bdf/bdflib.c @@ -51,6 +51,9 @@ #define FT_COMPONENT bdflib +#define BUFSIZE 128 + + /************************************************************************** * * Default BDF font options. @@ -58,7 +61,7 @@ */ - static const bdf_options_t _bdf_opts = + static const bdf_options_t bdf_opts_ = { 1, /* Correct metrics. */ 1, /* Preserve unencoded glyphs. */ @@ -76,7 +79,7 @@ /* List of most properties that might appear in a font. Doesn't include */ /* the RAW_* and AXIS_* properties in X11R6 polymorphic fonts. */ - static const bdf_property_t _bdf_properties[] = + static const bdf_property_t bdf_properties_[] = { { "ADD_STYLE_NAME", BDF_ATOM, 1, { 0 } }, { "AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } }, @@ -164,13 +167,13 @@ }; static const unsigned long - _num_bdf_properties = sizeof ( _bdf_properties ) / - sizeof ( _bdf_properties[0] ); + num_bdf_properties_ = sizeof ( bdf_properties_ ) / + sizeof ( bdf_properties_[0] ); /* An auxiliary macro to parse properties, to be used in conditionals. */ /* It behaves like `strncmp' but also tests the following character */ - /* whether it is a whitespace or NULL. */ + /* whether it is a whitespace or null. */ /* `property' is a constant string of length `n' to compare with. */ #define _bdf_strncmp( name, property, n ) \ ( ft_strncmp( name, property, n ) || \ @@ -185,12 +188,12 @@ "Added `FONT_ASCENT %hd'.\n" #define ACMSG2 "FONT_DESCENT property missing. " \ "Added `FONT_DESCENT %hd'.\n" -#define ACMSG3 "Font width != actual width. Old: %hd New: %hd.\n" +#define ACMSG3 "Font width != actual width. Old: %d New: %d.\n" #define ACMSG4 "Font left bearing != actual left bearing. " \ "Old: %hd New: %hd.\n" #define ACMSG5 "Font ascent != actual ascent. Old: %hd New: %hd.\n" -#define ACMSG6 "Font descent != actual descent. Old: %hd New: %hd.\n" -#define ACMSG7 "Font height != actual height. Old: %hd New: %hd.\n" +#define ACMSG6 "Font descent != actual descent. Old: %d New: %d.\n" +#define ACMSG7 "Font height != actual height. Old: %d New: %d.\n" #define ACMSG8 "Glyph scalable width (SWIDTH) adjustments made.\n" #define ACMSG9 "SWIDTH field missing at line %ld. Set automatically.\n" #define ACMSG10 "DWIDTH field missing at line %ld. Set to glyph width.\n" @@ -227,7 +230,7 @@ /* Function type for parsing lines of a BDF font. */ typedef FT_Error - (*_bdf_line_func_t)( char* line, + (*bdf_line_func_t_)( char* line, unsigned long linelen, unsigned long lineno, void* call_data, @@ -236,19 +239,19 @@ /* List structure for splitting lines into fields. */ - typedef struct _bdf_list_t_ + typedef struct bdf_list_t__ { char** field; unsigned long size; unsigned long used; FT_Memory memory; - } _bdf_list_t; + } bdf_list_t_; /* Structure used while loading BDF fonts. */ - typedef struct _bdf_parse_t_ + typedef struct bdf_parse_t__ { unsigned long flags; unsigned long cnt; @@ -268,12 +271,12 @@ bdf_font_t* font; bdf_options_t* opts; - _bdf_list_t list; + bdf_list_t_ list; FT_Memory memory; unsigned long size; /* the stream size */ - } _bdf_parse_t; + } bdf_parse_t_; #define setsbit( m, cc ) \ @@ -283,7 +286,7 @@ static void - _bdf_list_init( _bdf_list_t* list, + bdf_list_init_( bdf_list_t_* list, FT_Memory memory ) { FT_ZERO( list ); @@ -292,7 +295,7 @@ static void - _bdf_list_done( _bdf_list_t* list ) + bdf_list_done_( bdf_list_t_* list ) { FT_Memory memory = list->memory; @@ -306,15 +309,15 @@ static FT_Error - _bdf_list_ensure( _bdf_list_t* list, - unsigned long num_items ) /* same as _bdf_list_t.used */ + bdf_list_ensure_( bdf_list_t_* list, + unsigned long num_items ) /* same as bdf_list_t_.used */ { FT_Error error = FT_Err_Ok; if ( num_items > list->size ) { - unsigned long oldsize = list->size; /* same as _bdf_list_t.size */ + unsigned long oldsize = list->size; /* same as bdf_list_t_.size */ unsigned long newsize = oldsize + ( oldsize >> 1 ) + 5; unsigned long bigsize = (unsigned long)( FT_INT_MAX / sizeof ( char* ) ); FT_Memory memory = list->memory; @@ -328,7 +331,7 @@ else if ( newsize < oldsize || newsize > bigsize ) newsize = bigsize; - if ( FT_RENEW_ARRAY( list->field, oldsize, newsize ) ) + if ( FT_QRENEW_ARRAY( list->field, oldsize, newsize ) ) goto Exit; list->size = newsize; @@ -340,13 +343,13 @@ static void - _bdf_list_shift( _bdf_list_t* list, + bdf_list_shift_( bdf_list_t_* list, unsigned long n ) { unsigned long i, u; - if ( list == 0 || list->used == 0 || n == 0 ) + if ( list == NULL || list->used == 0 || n == 0 ) return; if ( n >= list->used ) @@ -367,7 +370,7 @@ static char * - _bdf_list_join( _bdf_list_t* list, + bdf_list_join_( bdf_list_t_* list, int c, unsigned long *alen ) { @@ -377,8 +380,8 @@ *alen = 0; - if ( list == 0 || list->used == 0 ) - return 0; + if ( list == NULL || list->used == 0 ) + return NULL; dp = list->field[0]; for ( i = j = 0; i < list->used; i++ ) @@ -405,7 +408,7 @@ /* don't have to check the number of fields in most cases. */ static FT_Error - _bdf_list_split( _bdf_list_t* list, + bdf_list_split_( bdf_list_t_* list, const char* separators, char* line, unsigned long linelen ) @@ -436,7 +439,7 @@ /* In the original code, if the `separators' parameter is NULL or */ /* empty, the list is split into individual bytes. We don't need */ /* this, so an error is signaled. */ - if ( separators == 0 || *separators == 0 ) + if ( separators == NULL || *separators == 0 ) { error = FT_THROW( Invalid_Argument ); goto Exit; @@ -467,7 +470,7 @@ /* Resize the list if necessary. */ if ( list->used == list->size ) { - error = _bdf_list_ensure( list, list->used + 1 ); + error = bdf_list_ensure_( list, list->used + 1 ); if ( error ) goto Exit; } @@ -496,7 +499,7 @@ /* Finally, NULL-terminate the list. */ if ( list->used + final_empty >= list->size ) { - error = _bdf_list_ensure( list, list->used + final_empty + 1 ); + error = bdf_list_ensure_( list, list->used + final_empty + 1 ); if ( error ) goto Exit; } @@ -504,7 +507,7 @@ if ( final_empty ) list->field[list->used++] = (char*)empty; - list->field[list->used] = 0; + list->field[list->used] = NULL; Exit: return error; @@ -515,12 +518,12 @@ static FT_Error - _bdf_readstream( FT_Stream stream, - _bdf_line_func_t callback, + bdf_readstream_( FT_Stream stream, + bdf_line_func_t_ callback, void* client_data, unsigned long *lno ) { - _bdf_line_func_t cb; + bdf_line_func_t_ cb; unsigned long lineno, buf_size; int refill, hold, to_skip; ptrdiff_t bytes, start, end, cursor, avail; @@ -529,7 +532,7 @@ FT_Error error = FT_Err_Ok; - if ( callback == 0 ) + if ( callback == NULL ) { error = FT_THROW( Invalid_Argument ); goto Exit; @@ -538,7 +541,7 @@ /* initial size and allocation of the input buffer */ buf_size = 1024; - if ( FT_NEW_ARRAY( buf, buf_size ) ) + if ( FT_QALLOC( buf, buf_size ) ) goto Exit; cb = callback; @@ -581,8 +584,14 @@ /* or even resizing it */ if ( end >= avail ) { - if ( bytes == 0 ) /* last line in file doesn't end in \r or \n */ - break; /* ignore it then exit */ + if ( bytes == 0 ) + { + /* last line in file doesn't end in \r or \n; */ + /* ignore it then exit */ + if ( lineno == 1 ) + error = FT_THROW( Missing_Startfont_Field ); + break; + } if ( start == 0 ) { @@ -593,16 +602,21 @@ if ( buf_size >= 65536UL ) /* limit ourselves to 64KByte */ { - FT_ERROR(( "_bdf_readstream: " ERRMSG6, lineno )); - error = FT_THROW( Invalid_Argument ); + if ( lineno == 1 ) + error = FT_THROW( Missing_Startfont_Field ); + else + { + FT_ERROR(( "bdf_readstream_: " ERRMSG6, lineno )); + error = FT_THROW( Invalid_Argument ); + } goto Exit; } new_size = buf_size * 2; - if ( FT_RENEW_ARRAY( buf, buf_size, new_size ) ) + if ( FT_QREALLOC( buf, buf_size, new_size ) ) goto Exit; - cursor = (ptrdiff_t)buf_size; + cursor = avail; buf_size = new_size; } else @@ -612,7 +626,6 @@ FT_MEM_MOVE( buf, buf + start, bytes ); cursor = bytes; - avail -= bytes; start = 0; } refill = 1; @@ -692,12 +705,12 @@ /* Routine to convert a decimal ASCII string to an unsigned long integer. */ static unsigned long - _bdf_atoul( const char* s ) + bdf_atoul_( const char* s ) { unsigned long v; - if ( s == 0 || *s == 0 ) + if ( s == NULL || *s == 0 ) return 0; for ( v = 0; sbitset( ddigits, *s ); s++ ) @@ -717,12 +730,12 @@ /* Routine to convert a decimal ASCII string to a signed long integer. */ static long - _bdf_atol( const char* s ) + bdf_atol_( const char* s ) { long v, neg; - if ( s == 0 || *s == 0 ) + if ( s == NULL || *s == 0 ) return 0; /* Check for a minus sign. */ @@ -750,12 +763,12 @@ /* Routine to convert a decimal ASCII string to an unsigned short integer. */ static unsigned short - _bdf_atous( const char* s ) + bdf_atous_( const char* s ) { unsigned short v; - if ( s == 0 || *s == 0 ) + if ( s == NULL || *s == 0 ) return 0; for ( v = 0; sbitset( ddigits, *s ); s++ ) @@ -775,12 +788,12 @@ /* Routine to convert a decimal ASCII string to a signed short integer. */ static short - _bdf_atos( const char* s ) + bdf_atos_( const char* s ) { short v, neg; - if ( s == 0 || *s == 0 ) + if ( s == NULL || *s == 0 ) return 0; /* Check for a minus. */ @@ -807,7 +820,7 @@ /* Routine to compare two glyphs by encoding so they can be sorted. */ - static int + FT_COMPARE_DEF( int ) by_encoding( const void* a, const void* b ) { @@ -844,27 +857,27 @@ if ( ft_hash_str_lookup( name, &(font->proptbl) ) ) goto Exit; - if ( FT_RENEW_ARRAY( font->user_props, - font->nuser_props, - font->nuser_props + 1 ) ) + if ( FT_QRENEW_ARRAY( font->user_props, + font->nuser_props, + font->nuser_props + 1 ) ) goto Exit; p = font->user_props + font->nuser_props; - FT_ZERO( p ); n = ft_strlen( name ) + 1; - if ( n > FT_ULONG_MAX ) + if ( n > FT_LONG_MAX ) return FT_THROW( Invalid_Argument ); - if ( FT_NEW_ARRAY( p->name, n ) ) + if ( FT_QALLOC( p->name, n ) ) goto Exit; FT_MEM_COPY( (char *)p->name, name, n ); - p->format = format; - p->builtin = 0; + p->format = format; + p->builtin = 0; + p->value.atom = NULL; /* nothing is ever stored here */ - n = _num_bdf_properties + font->nuser_props; + n = num_bdf_properties_ + font->nuser_props; error = ft_hash_str_insert( p->name, n, &(font->proptbl), memory ); if ( error ) @@ -877,23 +890,23 @@ } - FT_LOCAL_DEF( bdf_property_t* ) - bdf_get_property( char* name, + static bdf_property_t* + bdf_get_property( const char* name, bdf_font_t* font ) { size_t* propid; - if ( name == 0 || *name == 0 ) - return 0; + if ( name == NULL || *name == 0 ) + return NULL; if ( ( propid = ft_hash_str_lookup( name, &(font->proptbl) ) ) == NULL ) - return 0; + return NULL; - if ( *propid >= _num_bdf_properties ) - return font->user_props + ( *propid - _num_bdf_properties ); + if ( *propid >= num_bdf_properties_ ) + return font->user_props + ( *propid - num_bdf_properties_ ); - return (bdf_property_t*)_bdf_properties + *propid; + return (bdf_property_t*)bdf_properties_ + *propid; } @@ -933,8 +946,8 @@ static FT_Error - _bdf_add_comment( bdf_font_t* font, - char* comment, + bdf_add_comment_( bdf_font_t* font, + const char* comment, unsigned long len ) { char* cp; @@ -942,15 +955,15 @@ FT_Error error = FT_Err_Ok; - if ( FT_RENEW_ARRAY( font->comments, - font->comments_len, - font->comments_len + len + 1 ) ) + if ( FT_QRENEW_ARRAY( font->comments, + font->comments_len, + font->comments_len + len + 1 ) ) goto Exit; cp = font->comments + font->comments_len; FT_MEM_COPY( cp, comment, len ); - cp[len] = '\n'; + cp[len] = '\0'; font->comments_len += len + 1; @@ -962,20 +975,20 @@ /* Set the spacing from the font name if it exists, or set it to the */ /* default specified in the options. */ static FT_Error - _bdf_set_default_spacing( bdf_font_t* font, + bdf_set_default_spacing_( bdf_font_t* font, bdf_options_t* opts, unsigned long lineno ) { size_t len; char name[256]; - _bdf_list_t list; + bdf_list_t_ list; FT_Memory memory; FT_Error error = FT_Err_Ok; FT_UNUSED( lineno ); /* only used in debug mode */ - if ( font == 0 || font->name == 0 || font->name[0] == 0 ) + if ( font == NULL || font->name == NULL || font->name[0] == 0 ) { error = FT_THROW( Invalid_Argument ); goto Exit; @@ -983,7 +996,7 @@ memory = font->memory; - _bdf_list_init( &list, memory ); + bdf_list_init_( &list, memory ); font->spacing = opts->font_spacing; @@ -991,14 +1004,14 @@ /* Limit ourselves to 256 characters in the font name. */ if ( len >= 256 ) { - FT_ERROR(( "_bdf_set_default_spacing: " ERRMSG7, lineno )); + FT_ERROR(( "bdf_set_default_spacing_: " ERRMSG7, lineno )); error = FT_THROW( Invalid_Argument ); goto Exit; } FT_MEM_COPY( name, font->name, len ); - error = _bdf_list_split( &list, "-", name, (unsigned long)len ); + error = bdf_list_split_( &list, "-", name, (unsigned long)len ); if ( error ) goto Fail; @@ -1022,7 +1035,7 @@ } Fail: - _bdf_list_done( &list ); + bdf_list_done_( &list ); Exit: return error; @@ -1032,7 +1045,7 @@ /* Determine whether the property is an atom or not. If it is, then */ /* clean it up so the double quotes are removed if they exist. */ static int - _bdf_is_atom( char* line, + bdf_is_atom_( char* line, unsigned long linelen, char** name, char** value, @@ -1043,27 +1056,24 @@ bdf_property_t* p; - *name = sp = ep = line; + sp = ep = line; while ( *ep && *ep != ' ' && *ep != '\t' ) ep++; - hold = -1; - if ( *ep ) - { - hold = *ep; - *ep = 0; - } + hold = *ep; + *ep = '\0'; p = bdf_get_property( sp, font ); - /* Restore the character that was saved before any return can happen. */ - if ( hold != -1 ) - *ep = (char)hold; - /* If the property exists and is not an atom, just return here. */ if ( p && p->format != BDF_ATOM ) + { + *ep = (char)hold; /* Undo NUL-termination. */ return 0; + } + + *name = sp; /* The property is an atom. Trim all leading and trailing whitespace */ /* and double quotes for the atom value. */ @@ -1071,32 +1081,33 @@ ep = line + linelen; /* Trim the leading whitespace if it exists. */ - if ( *sp ) - *sp++ = 0; - while ( *sp && - ( *sp == ' ' || *sp == '\t' ) ) - sp++; + if ( sp < ep ) + do + sp++; + while ( *sp == ' ' || *sp == '\t' ); /* Trim the leading double quote if it exists. */ if ( *sp == '"' ) sp++; + *value = sp; /* Trim the trailing whitespace if it exists. */ - while ( ep > sp && - ( *( ep - 1 ) == ' ' || *( ep - 1 ) == '\t' ) ) - *--ep = 0; + if ( sp < ep ) + do + *ep-- = '\0'; + while ( *ep == ' ' || *ep == '\t' ); /* Trim the trailing double quote if it exists. */ - if ( ep > sp && *( ep - 1 ) == '"' ) - *--ep = 0; + if ( *ep == '"' ) + *ep = '\0'; return 1; } static FT_Error - _bdf_add_property( bdf_font_t* font, + bdf_add_property_( bdf_font_t* font, const char* name, char* value, unsigned long lineno ) @@ -1131,11 +1142,11 @@ break; case BDF_INTEGER: - fp->value.l = _bdf_atol( value ); + fp->value.l = bdf_atol_( value ); break; case BDF_CARDINAL: - fp->value.ul = _bdf_atoul( value ); + fp->value.ul = bdf_atoul_( value ); break; default: @@ -1159,28 +1170,18 @@ /* Allocate another property if this is overflowing. */ if ( font->props_used == font->props_size ) { - if ( font->props_size == 0 ) - { - if ( FT_NEW_ARRAY( font->props, 1 ) ) - goto Exit; - } - else - { - if ( FT_RENEW_ARRAY( font->props, - font->props_size, - font->props_size + 1 ) ) - goto Exit; - } + if ( FT_QRENEW_ARRAY( font->props, + font->props_size, + font->props_size + 1 ) ) + goto Exit; - fp = font->props + font->props_size; - FT_ZERO( fp ); font->props_size++; } - if ( *propid >= _num_bdf_properties ) - prop = font->user_props + ( *propid - _num_bdf_properties ); + if ( *propid >= num_bdf_properties_ ) + prop = font->user_props + ( *propid - num_bdf_properties_ ); else - prop = (bdf_property_t*)_bdf_properties + *propid; + prop = (bdf_property_t*)bdf_properties_ + *propid; fp = font->props + font->props_used; @@ -1191,8 +1192,8 @@ switch ( prop->format ) { case BDF_ATOM: - fp->value.atom = 0; - if ( value != 0 && value[0] ) + fp->value.atom = NULL; + if ( value && value[0] ) { if ( FT_STRDUP( fp->value.atom, value ) ) goto Exit; @@ -1200,11 +1201,11 @@ break; case BDF_INTEGER: - fp->value.l = _bdf_atol( value ); + fp->value.l = bdf_atol_( value ); break; case BDF_CARDINAL: - fp->value.ul = _bdf_atoul( value ); + fp->value.ul = bdf_atoul_( value ); break; } @@ -1238,7 +1239,7 @@ { if ( !fp->value.atom ) { - FT_ERROR(( "_bdf_add_property: " ERRMSG8, lineno, "SPACING" )); + FT_ERROR(( "bdf_add_property_: " ERRMSG8, lineno, "SPACING" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } @@ -1263,7 +1264,7 @@ static FT_Error - _bdf_parse_end( char* line, + bdf_parse_end_( char* line, unsigned long linelen, unsigned long lineno, void* call_data, @@ -1283,7 +1284,7 @@ /* Actually parse the glyph info and bitmaps. */ static FT_Error - _bdf_parse_glyphs( char* line, + bdf_parse_glyphs_( char* line, unsigned long linelen, unsigned long lineno, void* call_data, @@ -1294,8 +1295,8 @@ unsigned char* bp; unsigned long i, slen, nibbles; - _bdf_line_func_t* next; - _bdf_parse_t* p; + bdf_line_func_t_* next; + bdf_parse_t_* p; bdf_glyph_t* glyph; bdf_font_t* font; @@ -1305,8 +1306,8 @@ FT_UNUSED( lineno ); /* only used in debug mode */ - next = (_bdf_line_func_t *)call_data; - p = (_bdf_parse_t *) client_data; + next = (bdf_line_func_t_ *)call_data; + p = (bdf_parse_t_ *) client_data; font = p->font; memory = font->memory; @@ -1314,15 +1315,18 @@ /* Check for a comment. */ if ( _bdf_strncmp( line, "COMMENT", 7 ) == 0 ) { - linelen -= 7; - - s = line + 7; - if ( *s != 0 ) + if ( p->opts->keep_comments ) { - s++; - linelen--; + linelen -= 7; + + s = line + 7; + if ( *s != 0 ) + { + s++; + linelen--; + } + error = bdf_add_comment_( p->font, s, linelen ); } - error = _bdf_add_comment( p->font, s, linelen ); goto Exit; } @@ -1331,21 +1335,21 @@ { if ( _bdf_strncmp( line, "CHARS", 5 ) != 0 ) { - FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "CHARS" )); + FT_ERROR(( "bdf_parse_glyphs_: " ERRMSG1, lineno, "CHARS" )); error = FT_THROW( Missing_Chars_Field ); goto Exit; } - error = _bdf_list_split( &p->list, " +", line, linelen ); + error = bdf_list_split_( &p->list, " +", line, linelen ); if ( error ) goto Exit; - p->cnt = font->glyphs_size = _bdf_atoul( p->list.field[1] ); + p->cnt = font->glyphs_size = bdf_atoul_( p->list.field[1] ); /* We need at least 20 bytes per glyph. */ if ( p->cnt > p->size / 20 ) { p->cnt = font->glyphs_size = p->size / 20; - FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG17, p->cnt )); + FT_TRACE2(( "bdf_parse_glyphs_: " ACMSG17, p->cnt )); } /* Make sure the number of glyphs is non-zero. */ @@ -1356,7 +1360,7 @@ /* number of code points available in Unicode). */ if ( p->cnt >= 0x110000UL ) { - FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG5, lineno, "CHARS" )); + FT_ERROR(( "bdf_parse_glyphs_: " ERRMSG5, lineno, "CHARS" )); error = FT_THROW( Invalid_Argument ); goto Exit; } @@ -1375,7 +1379,7 @@ if ( p->flags & BDF_GLYPH_BITS_ ) { /* Missing ENDCHAR field. */ - FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "ENDCHAR" )); + FT_ERROR(( "bdf_parse_glyphs_: " ERRMSG1, lineno, "ENDCHAR" )); error = FT_THROW( Corrupted_Font_Glyphs ); goto Exit; } @@ -1387,7 +1391,7 @@ by_encoding ); p->flags &= ~BDF_START_; - *next = _bdf_parse_end; + *next = bdf_parse_end_; goto Exit; } @@ -1414,7 +1418,7 @@ if ( p->flags & BDF_GLYPH_BITS_ ) { /* Missing ENDCHAR field. */ - FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "ENDCHAR" )); + FT_ERROR(( "bdf_parse_glyphs_: " ERRMSG1, lineno, "ENDCHAR" )); error = FT_THROW( Missing_Startchar_Field ); goto Exit; } @@ -1423,22 +1427,22 @@ /* encoding can be checked for an unencoded character. */ FT_FREE( p->glyph_name ); - error = _bdf_list_split( &p->list, " +", line, linelen ); + error = bdf_list_split_( &p->list, " +", line, linelen ); if ( error ) goto Exit; - _bdf_list_shift( &p->list, 1 ); + bdf_list_shift_( &p->list, 1 ); - s = _bdf_list_join( &p->list, ' ', &slen ); + s = bdf_list_join_( &p->list, ' ', &slen ); if ( !s ) { - FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG8, lineno, "STARTCHAR" )); + FT_ERROR(( "bdf_parse_glyphs_: " ERRMSG8, lineno, "STARTCHAR" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } - if ( FT_NEW_ARRAY( p->glyph_name, slen + 1 ) ) + if ( FT_QALLOC( p->glyph_name, slen + 1 ) ) goto Exit; FT_MEM_COPY( p->glyph_name, s, slen + 1 ); @@ -1456,16 +1460,16 @@ if ( !( p->flags & BDF_GLYPH_ ) ) { /* Missing STARTCHAR field. */ - FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "STARTCHAR" )); + FT_ERROR(( "bdf_parse_glyphs_: " ERRMSG1, lineno, "STARTCHAR" )); error = FT_THROW( Missing_Startchar_Field ); goto Exit; } - error = _bdf_list_split( &p->list, " +", line, linelen ); + error = bdf_list_split_( &p->list, " +", line, linelen ); if ( error ) goto Exit; - p->glyph_enc = _bdf_atol( p->list.field[1] ); + p->glyph_enc = bdf_atol_( p->list.field[1] ); /* Normalize negative encoding values. The specification only */ /* allows -1, but we can be more generous here. */ @@ -1474,7 +1478,7 @@ /* Check for alternative encoding format. */ if ( p->glyph_enc == -1 && p->list.used > 2 ) - p->glyph_enc = _bdf_atol( p->list.field[2] ); + p->glyph_enc = bdf_atol_( p->list.field[2] ); if ( p->glyph_enc < -1 || p->glyph_enc >= 0x110000L ) p->glyph_enc = -1; @@ -1506,7 +1510,7 @@ { /* Unencoded glyph. Check whether it should */ /* be added or not. */ - if ( p->opts->keep_unencoded != 0 ) + if ( p->opts->keep_unencoded ) { /* Allocate the next unencoded glyph. */ if ( font->unencoded_used == font->unencoded_size ) @@ -1532,8 +1536,6 @@ /* kept. */ FT_FREE( p->glyph_name ); } - - p->glyph_name = NULL; } /* Clear the flags that might be added when width and height are */ @@ -1563,7 +1565,7 @@ { if ( !( p->flags & BDF_GLYPH_HEIGHT_CHECK_ ) ) { - FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG13, glyph->encoding )); + FT_TRACE2(( "bdf_parse_glyphs_: " ACMSG13, glyph->encoding )); p->flags |= BDF_GLYPH_HEIGHT_CHECK_; } @@ -1590,7 +1592,7 @@ if ( i < nibbles && !( p->flags & BDF_GLYPH_WIDTH_CHECK_ ) ) { - FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG16, glyph->encoding )); + FT_TRACE2(( "bdf_parse_glyphs_: " ACMSG16, glyph->encoding )); p->flags |= BDF_GLYPH_WIDTH_CHECK_; } @@ -1604,7 +1606,7 @@ sbitset( hdigits, line[nibbles] ) && !( p->flags & BDF_GLYPH_WIDTH_CHECK_ ) ) { - FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG14, glyph->encoding )); + FT_TRACE2(( "bdf_parse_glyphs_: " ACMSG14, glyph->encoding )); p->flags |= BDF_GLYPH_WIDTH_CHECK_; } @@ -1615,30 +1617,30 @@ /* Expect the SWIDTH (scalable width) field next. */ if ( _bdf_strncmp( line, "SWIDTH", 6 ) == 0 ) { - error = _bdf_list_split( &p->list, " +", line, linelen ); + error = bdf_list_split_( &p->list, " +", line, linelen ); if ( error ) goto Exit; - glyph->swidth = (unsigned short)_bdf_atoul( p->list.field[1] ); + glyph->swidth = bdf_atous_( p->list.field[1] ); p->flags |= BDF_SWIDTH_; goto Exit; } - /* Expect the DWIDTH (scalable width) field next. */ + /* Expect the DWIDTH (device width) field next. */ if ( _bdf_strncmp( line, "DWIDTH", 6 ) == 0 ) { - error = _bdf_list_split( &p->list, " +", line, linelen ); + error = bdf_list_split_( &p->list, " +", line, linelen ); if ( error ) goto Exit; - glyph->dwidth = (unsigned short)_bdf_atoul( p->list.field[1] ); + glyph->dwidth = bdf_atous_( p->list.field[1] ); if ( !( p->flags & BDF_SWIDTH_ ) ) { /* Missing SWIDTH field. Emit an auto correction message and set */ /* the scalable width from the device width. */ - FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG9, lineno )); + FT_TRACE2(( "bdf_parse_glyphs_: " ACMSG9, lineno )); glyph->swidth = (unsigned short)FT_MulDiv( glyph->dwidth, 72000L, @@ -1653,14 +1655,14 @@ /* Expect the BBX field next. */ if ( _bdf_strncmp( line, "BBX", 3 ) == 0 ) { - error = _bdf_list_split( &p->list, " +", line, linelen ); + error = bdf_list_split_( &p->list, " +", line, linelen ); if ( error ) goto Exit; - glyph->bbx.width = _bdf_atous( p->list.field[1] ); - glyph->bbx.height = _bdf_atous( p->list.field[2] ); - glyph->bbx.x_offset = _bdf_atos( p->list.field[3] ); - glyph->bbx.y_offset = _bdf_atos( p->list.field[4] ); + glyph->bbx.width = bdf_atous_( p->list.field[1] ); + glyph->bbx.height = bdf_atous_( p->list.field[2] ); + glyph->bbx.x_offset = bdf_atos_( p->list.field[3] ); + glyph->bbx.y_offset = bdf_atos_( p->list.field[4] ); /* Generate the ascent and descent of the character. */ glyph->bbx.ascent = (short)( glyph->bbx.height + glyph->bbx.y_offset ); @@ -1681,13 +1683,13 @@ { /* Missing DWIDTH field. Emit an auto correction message and set */ /* the device width to the glyph width. */ - FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG10, lineno )); + FT_TRACE2(( "bdf_parse_glyphs_: " ACMSG10, lineno )); glyph->dwidth = glyph->bbx.width; } /* If the BDF_CORRECT_METRICS flag is set, then adjust the SWIDTH */ /* value if necessary. */ - if ( p->opts->correct_metrics != 0 ) + if ( p->opts->correct_metrics ) { /* Determine the point size of the glyph. */ unsigned short sw = (unsigned short)FT_MulDiv( @@ -1717,7 +1719,7 @@ if ( !( p->flags & BDF_BBX_ ) ) { /* Missing BBX field. */ - FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "BBX" )); + FT_ERROR(( "bdf_parse_glyphs_: " ERRMSG1, lineno, "BBX" )); error = FT_THROW( Missing_Bbx_Field ); goto Exit; } @@ -1728,14 +1730,14 @@ bitmap_size = glyph->bpr * glyph->bbx.height; if ( glyph->bpr > 0xFFFFU || bitmap_size > 0xFFFFU ) { - FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG4, lineno )); + FT_ERROR(( "bdf_parse_glyphs_: " ERRMSG4, lineno )); error = FT_THROW( Bbx_Too_Big ); goto Exit; } else glyph->bytes = (unsigned short)bitmap_size; - if ( FT_NEW_ARRAY( glyph->bitmap, glyph->bytes ) ) + if ( FT_ALLOC( glyph->bitmap, glyph->bytes ) ) goto Exit; p->row = 0; @@ -1744,13 +1746,13 @@ goto Exit; } - FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG9, lineno )); + FT_ERROR(( "bdf_parse_glyphs_: " ERRMSG9, lineno )); error = FT_THROW( Invalid_File_Format ); goto Exit; Missing_Encoding: /* Missing ENCODING field. */ - FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "ENCODING" )); + FT_ERROR(( "bdf_parse_glyphs_: " ERRMSG1, lineno, "ENCODING" )); error = FT_THROW( Missing_Encoding_Field ); Exit: @@ -1763,25 +1765,25 @@ /* Load the font properties. */ static FT_Error - _bdf_parse_properties( char* line, + bdf_parse_properties_( char* line, unsigned long linelen, unsigned long lineno, void* call_data, void* client_data ) { unsigned long vlen; - _bdf_line_func_t* next; - _bdf_parse_t* p; + bdf_line_func_t_* next; + bdf_parse_t_* p; char* name; char* value; - char nbuf[128]; + char nbuf[BUFSIZE]; FT_Error error = FT_Err_Ok; FT_UNUSED( lineno ); - next = (_bdf_line_func_t *)call_data; - p = (_bdf_parse_t *) client_data; + next = (bdf_line_func_t_ *)call_data; + p = (bdf_parse_t_ *) client_data; /* Check for the end of the properties. */ if ( _bdf_strncmp( line, "ENDPROPERTIES", 13 ) == 0 ) @@ -1795,29 +1797,29 @@ if ( bdf_get_font_property( p->font, "FONT_ASCENT" ) == 0 ) { p->font->font_ascent = p->font->bbx.ascent; - ft_sprintf( nbuf, "%hd", p->font->bbx.ascent ); - error = _bdf_add_property( p->font, "FONT_ASCENT", + ft_snprintf( nbuf, BUFSIZE, "%hd", p->font->bbx.ascent ); + error = bdf_add_property_( p->font, "FONT_ASCENT", nbuf, lineno ); if ( error ) goto Exit; - FT_TRACE2(( "_bdf_parse_properties: " ACMSG1, p->font->bbx.ascent )); + FT_TRACE2(( "bdf_parse_properties_: " ACMSG1, p->font->bbx.ascent )); } if ( bdf_get_font_property( p->font, "FONT_DESCENT" ) == 0 ) { p->font->font_descent = p->font->bbx.descent; - ft_sprintf( nbuf, "%hd", p->font->bbx.descent ); - error = _bdf_add_property( p->font, "FONT_DESCENT", + ft_snprintf( nbuf, BUFSIZE, "%hd", p->font->bbx.descent ); + error = bdf_add_property_( p->font, "FONT_DESCENT", nbuf, lineno ); if ( error ) goto Exit; - FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent )); + FT_TRACE2(( "bdf_parse_properties_: " ACMSG2, p->font->bbx.descent )); } p->flags &= ~BDF_PROPS_; - *next = _bdf_parse_glyphs; + *next = bdf_parse_glyphs_; goto Exit; } @@ -1834,27 +1836,27 @@ value += 7; if ( *value ) *value++ = 0; - error = _bdf_add_property( p->font, name, value, lineno ); + error = bdf_add_property_( p->font, name, value, lineno ); if ( error ) goto Exit; } - else if ( _bdf_is_atom( line, linelen, &name, &value, p->font ) ) + else if ( bdf_is_atom_( line, linelen, &name, &value, p->font ) ) { - error = _bdf_add_property( p->font, name, value, lineno ); + error = bdf_add_property_( p->font, name, value, lineno ); if ( error ) goto Exit; } else { - error = _bdf_list_split( &p->list, " +", line, linelen ); + error = bdf_list_split_( &p->list, " +", line, linelen ); if ( error ) goto Exit; name = p->list.field[0]; - _bdf_list_shift( &p->list, 1 ); - value = _bdf_list_join( &p->list, ' ', &vlen ); + bdf_list_shift_( &p->list, 1 ); + value = bdf_list_join_( &p->list, ' ', &vlen ); - error = _bdf_add_property( p->font, name, value, lineno ); + error = bdf_add_property_( p->font, name, value, lineno ); if ( error ) goto Exit; } @@ -1866,15 +1868,15 @@ /* Load the font header. */ static FT_Error - _bdf_parse_start( char* line, + bdf_parse_start_( char* line, unsigned long linelen, unsigned long lineno, void* call_data, void* client_data ) { unsigned long slen; - _bdf_line_func_t* next; - _bdf_parse_t* p; + bdf_line_func_t_* next; + bdf_parse_t_* p; bdf_font_t* font; char *s; @@ -1884,8 +1886,8 @@ FT_UNUSED( lineno ); /* only used in debug mode */ - next = (_bdf_line_func_t *)call_data; - p = (_bdf_parse_t *) client_data; + next = (bdf_line_func_t_ *)call_data; + p = (bdf_parse_t_ *) client_data; if ( p->font ) memory = p->font->memory; @@ -1894,7 +1896,7 @@ /* comments before the STARTFONT line for some reason. */ if ( _bdf_strncmp( line, "COMMENT", 7 ) == 0 ) { - if ( p->opts->keep_comments != 0 && p->font != 0 ) + if ( p->opts->keep_comments && p->font ) { linelen -= 7; @@ -1904,13 +1906,8 @@ s++; linelen--; } - - error = _bdf_add_comment( p->font, s, linelen ); - if ( error ) - goto Exit; - /* here font is not defined! */ + error = bdf_add_comment_( p->font, s, linelen ); } - goto Exit; } @@ -1927,14 +1924,13 @@ } p->flags = BDF_START_; - font = p->font = 0; + font = p->font = NULL; if ( FT_NEW( font ) ) goto Exit; p->font = font; font->memory = p->memory; - p->memory = 0; { /* setup */ size_t i; @@ -1944,8 +1940,8 @@ error = ft_hash_str_init( &(font->proptbl), memory ); if ( error ) goto Exit; - for ( i = 0, prop = (bdf_property_t*)_bdf_properties; - i < _num_bdf_properties; i++, prop++ ) + for ( i = 0, prop = (bdf_property_t*)bdf_properties_; + i < num_bdf_properties_; i++, prop++ ) { error = ft_hash_str_insert( prop->name, i, &(font->proptbl), memory ); @@ -1954,7 +1950,7 @@ } } - if ( FT_ALLOC( p->font->internal, sizeof ( FT_HashRec ) ) ) + if ( FT_QALLOC( p->font->internal, sizeof ( FT_HashRec ) ) ) goto Exit; error = ft_hash_str_init( (FT_Hash)p->font->internal, memory ); if ( error ) @@ -1971,23 +1967,23 @@ if ( !( p->flags & BDF_FONT_BBX_ ) ) { /* Missing the FONTBOUNDINGBOX field. */ - FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONTBOUNDINGBOX" )); + FT_ERROR(( "bdf_parse_start_: " ERRMSG1, lineno, "FONTBOUNDINGBOX" )); error = FT_THROW( Missing_Fontboundingbox_Field ); goto Exit; } - error = _bdf_list_split( &p->list, " +", line, linelen ); + error = bdf_list_split_( &p->list, " +", line, linelen ); if ( error ) goto Exit; /* at this point, `p->font' can't be NULL */ - p->cnt = p->font->props_size = _bdf_atoul( p->list.field[1] ); + p->cnt = p->font->props_size = bdf_atoul_( p->list.field[1] ); /* We need at least 4 bytes per property. */ if ( p->cnt > p->size / 4 ) { p->font->props_size = 0; - FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG5, lineno, "STARTPROPERTIES" )); + FT_ERROR(( "bdf_parse_glyphs_: " ERRMSG5, lineno, "STARTPROPERTIES" )); error = FT_THROW( Invalid_Argument ); goto Exit; } @@ -1999,7 +1995,7 @@ } p->flags |= BDF_PROPS_; - *next = _bdf_parse_properties; + *next = bdf_parse_properties_; goto Exit; } @@ -2010,20 +2006,20 @@ if ( !( p->flags & BDF_SIZE_ ) ) { /* Missing the SIZE field. */ - FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "SIZE" )); + FT_ERROR(( "bdf_parse_start_: " ERRMSG1, lineno, "SIZE" )); error = FT_THROW( Missing_Size_Field ); goto Exit; } - error = _bdf_list_split( &p->list, " +", line, linelen ); + error = bdf_list_split_( &p->list, " +", line, linelen ); if ( error ) goto Exit; - p->font->bbx.width = _bdf_atous( p->list.field[1] ); - p->font->bbx.height = _bdf_atous( p->list.field[2] ); + p->font->bbx.width = bdf_atous_( p->list.field[1] ); + p->font->bbx.height = bdf_atous_( p->list.field[2] ); - p->font->bbx.x_offset = _bdf_atos( p->list.field[3] ); - p->font->bbx.y_offset = _bdf_atos( p->list.field[4] ); + p->font->bbx.x_offset = bdf_atos_( p->list.field[3] ); + p->font->bbx.y_offset = bdf_atos_( p->list.field[4] ); p->font->bbx.ascent = (short)( p->font->bbx.height + p->font->bbx.y_offset ); @@ -2038,16 +2034,16 @@ /* The next thing to check for is the FONT field. */ if ( _bdf_strncmp( line, "FONT", 4 ) == 0 ) { - error = _bdf_list_split( &p->list, " +", line, linelen ); + error = bdf_list_split_( &p->list, " +", line, linelen ); if ( error ) goto Exit; - _bdf_list_shift( &p->list, 1 ); + bdf_list_shift_( &p->list, 1 ); - s = _bdf_list_join( &p->list, ' ', &slen ); + s = bdf_list_join_( &p->list, ' ', &slen ); if ( !s ) { - FT_ERROR(( "_bdf_parse_start: " ERRMSG8, lineno, "FONT" )); + FT_ERROR(( "bdf_parse_start_: " ERRMSG8, lineno, "FONT" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } @@ -2055,13 +2051,13 @@ /* Allowing multiple `FONT' lines (which is invalid) doesn't hurt... */ FT_FREE( p->font->name ); - if ( FT_NEW_ARRAY( p->font->name, slen + 1 ) ) + if ( FT_QALLOC( p->font->name, slen + 1 ) ) goto Exit; FT_MEM_COPY( p->font->name, s, slen + 1 ); /* If the font name is an XLFD name, set the spacing to the one in */ /* the font name. If there is no spacing fall back on the default. */ - error = _bdf_set_default_spacing( p->font, p->opts, lineno ); + error = bdf_set_default_spacing_( p->font, p->opts, lineno ); if ( error ) goto Exit; @@ -2076,18 +2072,18 @@ if ( !( p->flags & BDF_FONT_NAME_ ) ) { /* Missing the FONT field. */ - FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONT" )); + FT_ERROR(( "bdf_parse_start_: " ERRMSG1, lineno, "FONT" )); error = FT_THROW( Missing_Font_Field ); goto Exit; } - error = _bdf_list_split( &p->list, " +", line, linelen ); + error = bdf_list_split_( &p->list, " +", line, linelen ); if ( error ) goto Exit; - p->font->point_size = _bdf_atoul( p->list.field[1] ); - p->font->resolution_x = _bdf_atoul( p->list.field[2] ); - p->font->resolution_y = _bdf_atoul( p->list.field[3] ); + p->font->point_size = bdf_atoul_( p->list.field[1] ); + p->font->resolution_x = bdf_atoul_( p->list.field[2] ); + p->font->resolution_y = bdf_atoul_( p->list.field[3] ); /* Check for the bits per pixel field. */ if ( p->list.used == 5 ) @@ -2095,7 +2091,7 @@ unsigned short bpp; - bpp = (unsigned short)_bdf_atos( p->list.field[4] ); + bpp = bdf_atous_( p->list.field[4] ); /* Only values 1, 2, 4, 8 are allowed for greymap fonts. */ if ( bpp > 4 ) @@ -2108,7 +2104,7 @@ p->font->bpp = 1; if ( p->font->bpp != bpp ) - FT_TRACE2(( "_bdf_parse_start: " ACMSG11, p->font->bpp )); + FT_TRACE2(( "bdf_parse_start_: " ACMSG11, p->font->bpp )); } else p->font->bpp = 1; @@ -2121,13 +2117,13 @@ /* Check for the CHARS field -- font properties are optional */ if ( _bdf_strncmp( line, "CHARS", 5 ) == 0 ) { - char nbuf[128]; + char nbuf[BUFSIZE]; if ( !( p->flags & BDF_FONT_BBX_ ) ) { /* Missing the FONTBOUNDINGBOX field. */ - FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONTBOUNDINGBOX" )); + FT_ERROR(( "bdf_parse_start_: " ERRMSG1, lineno, "FONTBOUNDINGBOX" )); error = FT_THROW( Missing_Fontboundingbox_Field ); goto Exit; } @@ -2135,29 +2131,29 @@ /* Add the two standard X11 properties which are required */ /* for compiling fonts. */ p->font->font_ascent = p->font->bbx.ascent; - ft_sprintf( nbuf, "%hd", p->font->bbx.ascent ); - error = _bdf_add_property( p->font, "FONT_ASCENT", + ft_snprintf( nbuf, BUFSIZE, "%hd", p->font->bbx.ascent ); + error = bdf_add_property_( p->font, "FONT_ASCENT", nbuf, lineno ); if ( error ) goto Exit; - FT_TRACE2(( "_bdf_parse_properties: " ACMSG1, p->font->bbx.ascent )); + FT_TRACE2(( "bdf_parse_properties_: " ACMSG1, p->font->bbx.ascent )); p->font->font_descent = p->font->bbx.descent; - ft_sprintf( nbuf, "%hd", p->font->bbx.descent ); - error = _bdf_add_property( p->font, "FONT_DESCENT", + ft_snprintf( nbuf, BUFSIZE, "%hd", p->font->bbx.descent ); + error = bdf_add_property_( p->font, "FONT_DESCENT", nbuf, lineno ); if ( error ) goto Exit; - FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent )); + FT_TRACE2(( "bdf_parse_properties_: " ACMSG2, p->font->bbx.descent )); - *next = _bdf_parse_glyphs; + *next = bdf_parse_glyphs_; /* A special return value. */ error = -1; goto Exit; } - FT_ERROR(( "_bdf_parse_start: " ERRMSG9, lineno )); + FT_ERROR(( "bdf_parse_start_: " ERRMSG9, lineno )); error = FT_THROW( Invalid_File_Format ); Exit: @@ -2174,34 +2170,32 @@ FT_LOCAL_DEF( FT_Error ) bdf_load_font( FT_Stream stream, - FT_Memory extmemory, + FT_Memory memory, bdf_options_t* opts, bdf_font_t* *font ) { unsigned long lineno = 0; /* make compiler happy */ - _bdf_parse_t *p = NULL; + bdf_parse_t_ *p = NULL; - FT_Memory memory = extmemory; /* needed for FT_NEW */ - FT_Error error = FT_Err_Ok; + FT_Error error = FT_Err_Ok; if ( FT_NEW( p ) ) goto Exit; - memory = NULL; - p->opts = (bdf_options_t*)( ( opts != 0 ) ? opts : &_bdf_opts ); + p->opts = (bdf_options_t*)( opts ? opts : &bdf_opts_ ); p->minlb = 32767; p->size = stream->size; - p->memory = extmemory; /* only during font creation */ + p->memory = memory; /* only during font creation */ - _bdf_list_init( &p->list, extmemory ); + bdf_list_init_( &p->list, memory ); - error = _bdf_readstream( stream, _bdf_parse_start, + error = bdf_readstream_( stream, bdf_parse_start_, (void *)p, &lineno ); if ( error ) goto Fail; - if ( p->font != 0 ) + if ( p->font ) { /* If the font is not proportional, set the font's monowidth */ /* field to the width of the font bounding box. */ @@ -2282,22 +2276,7 @@ } } - if ( p->font != 0 ) - { - /* Make sure the comments are NULL terminated if they exist. */ - memory = p->font->memory; - - if ( p->font->comments_len > 0 ) - { - if ( FT_RENEW_ARRAY( p->font->comments, - p->font->comments_len, - p->font->comments_len + 1 ) ) - goto Fail; - - p->font->comments[p->font->comments_len] = 0; - } - } - else if ( !error ) + if ( !p->font && !error ) error = FT_THROW( Invalid_File_Format ); *font = p->font; @@ -2305,9 +2284,7 @@ Exit: if ( p ) { - _bdf_list_done( &p->list ); - - memory = extmemory; + bdf_list_done_( &p->list ); FT_FREE( p->glyph_name ); FT_FREE( p ); @@ -2318,8 +2295,6 @@ Fail: bdf_free_font( p->font ); - memory = extmemory; - FT_FREE( p->font ); goto Exit; @@ -2335,7 +2310,7 @@ FT_Memory memory; - if ( font == 0 ) + if ( font == NULL ) return; memory = font->memory; @@ -2385,11 +2360,7 @@ /* Free up the user defined properties. */ for ( prop = font->user_props, i = 0; i < font->nuser_props; i++, prop++ ) - { FT_FREE( prop->name ); - if ( prop->format == BDF_ATOM ) - FT_FREE( prop->value.atom ); - } FT_FREE( font->user_props ); @@ -2404,7 +2375,7 @@ size_t* propid; - if ( font == 0 || font->props_size == 0 || name == 0 || *name == 0 ) + if ( font == NULL || font->props_size == 0 || name == NULL || *name == 0 ) return 0; propid = ft_hash_str_lookup( name, (FT_Hash)font->internal ); diff --git a/lib/libesp32_lvgl/freetype/src/bzip2/ftbzip2.c b/lib/libesp32_lvgl/freetype/src/bzip2/ftbzip2.c index 411c5d263..ad342bd01 100644 --- a/lib/libesp32_lvgl/freetype/src/bzip2/ftbzip2.c +++ b/lib/libesp32_lvgl/freetype/src/bzip2/ftbzip2.c @@ -8,7 +8,7 @@ * parse compressed PCF fonts, as found with many X11 server * distributions. * - * Copyright (C) 2010-2020 by + * Copyright (C) 2010-2023 by * Joel Klinghed. * * based on `src/gzip/ftgzip.c' @@ -57,28 +57,34 @@ /* it is better to use FreeType memory routines instead of raw 'malloc/free' */ - typedef void *(* alloc_func)(void*, int, int); - typedef void (* free_func)(void*, void*); + typedef void* (*alloc_func)( void*, int, int ); + typedef void (*free_func) ( void*, void* ); + static void* - ft_bzip2_alloc( FT_Memory memory, - int items, - int size ) + ft_bzip2_alloc( void* memory_, /* FT_Memory */ + int items, + int size ) { + FT_Memory memory = (FT_Memory)memory_; + FT_ULong sz = (FT_ULong)size * (FT_ULong)items; FT_Error error; FT_Pointer p = NULL; - (void)FT_ALLOC( p, sz ); + FT_MEM_QALLOC( p, sz ); return p; } static void - ft_bzip2_free( FT_Memory memory, - void* address ) + ft_bzip2_free( void* memory_, /* FT_Memory */ + void* address ) { + FT_Memory memory = (FT_Memory)memory_; + + FT_MEM_FREE( address ); } @@ -102,10 +108,11 @@ FT_Byte input[FT_BZIP2_BUFFER_SIZE]; /* input read buffer */ - FT_Byte buffer[FT_BZIP2_BUFFER_SIZE]; /* output buffer */ - FT_ULong pos; /* position in output */ + FT_Byte buffer[FT_BZIP2_BUFFER_SIZE]; /* output buffer */ + FT_ULong pos; /* position in output */ FT_Byte* cursor; FT_Byte* limit; + FT_Bool reset; /* reset before next read */ } FT_BZip2FileRec, *FT_BZip2File; @@ -153,6 +160,7 @@ zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE; zip->cursor = zip->limit; zip->pos = 0; + zip->reset = 0; /* check .bz2 header */ { @@ -167,8 +175,8 @@ } /* initialize bzlib */ - bzstream->bzalloc = (alloc_func)ft_bzip2_alloc; - bzstream->bzfree = (free_func) ft_bzip2_free; + bzstream->bzalloc = ft_bzip2_alloc; + bzstream->bzfree = ft_bzip2_free; bzstream->opaque = zip->memory; bzstream->avail_in = 0; @@ -228,6 +236,7 @@ zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE; zip->cursor = zip->limit; zip->pos = 0; + zip->reset = 0; BZ2_bzDecompressInit( bzstream, 0, 0 ); } @@ -302,18 +311,23 @@ err = BZ2_bzDecompress( bzstream ); - if ( err == BZ_STREAM_END ) + if ( err != BZ_OK ) { - zip->limit = (FT_Byte*)bzstream->next_out; - if ( zip->limit == zip->cursor ) - error = FT_THROW( Invalid_Stream_Operation ); - break; - } - else if ( err != BZ_OK ) - { - zip->limit = zip->cursor; - error = FT_THROW( Invalid_Stream_Operation ); - break; + zip->reset = 1; + + if ( err == BZ_STREAM_END ) + { + zip->limit = (FT_Byte*)bzstream->next_out; + if ( zip->limit == zip->cursor ) + error = FT_THROW( Invalid_Stream_Operation ); + break; + } + else + { + zip->limit = zip->cursor; + error = FT_THROW( Invalid_Stream_Operation ); + break; + } } } @@ -327,12 +341,13 @@ FT_ULong count ) { FT_Error error = FT_Err_Ok; - FT_ULong delta; for (;;) { - delta = (FT_ULong)( zip->limit - zip->cursor ); + FT_ULong delta = (FT_ULong)( zip->limit - zip->cursor ); + + if ( delta >= count ) delta = count; @@ -362,9 +377,9 @@ FT_Error error; - /* Reset inflate stream if we're seeking backwards. */ - /* Yes, that is not too efficient, but it saves memory :-) */ - if ( pos < zip->pos ) + /* Reset inflate stream if seeking backwards or bzip reported an error. */ + /* Yes, that is not too efficient, but it saves memory :-) */ + if ( pos < zip->pos || zip->reset ) { error = ft_bzip2_file_reset( zip ); if ( error ) @@ -494,7 +509,7 @@ stream->size = 0x7FFFFFFFL; /* don't know the real size! */ stream->pos = 0; - stream->base = 0; + stream->base = NULL; stream->read = ft_bzip2_stream_io; stream->close = ft_bzip2_stream_close; diff --git a/lib/libesp32_lvgl/freetype/src/bzip2/rules.mk b/lib/libesp32_lvgl/freetype/src/bzip2/rules.mk index eed0f4baa..f4d3733eb 100644 --- a/lib/libesp32_lvgl/freetype/src/bzip2/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/bzip2/rules.mk @@ -2,7 +2,7 @@ # FreeType 2 BZIP2 support configuration rules # -# Copyright (C) 2010-2020 by +# Copyright (C) 2010-2023 by # Joel Klinghed. # # based on `src/lzw/rules.mk' diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftcache.c b/lib/libesp32_lvgl/freetype/src/cache/ftcache.c index e90f4639c..1af2e6772 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftcache.c +++ b/lib/libesp32_lvgl/freetype/src/cache/ftcache.c @@ -4,7 +4,7 @@ * * The FreeType Caching sub-system (body only). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftcbasic.c b/lib/libesp32_lvgl/freetype/src/cache/ftcbasic.c index 43ea314d4..24a56c8d2 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftcbasic.c +++ b/lib/libesp32_lvgl/freetype/src/cache/ftcbasic.c @@ -4,7 +4,7 @@ * * The FreeType basic cache interface (body). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -26,6 +26,7 @@ #include "ftccback.h" #include "ftcerror.h" +#undef FT_COMPONENT #define FT_COMPONENT cache @@ -108,15 +109,18 @@ if ( error || !face ) return result; +#ifdef FT_DEBUG_LEVEL_TRACE if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs ) + { FT_TRACE1(( "ftc_basic_family_get_count:" - " the number of glyphs in this face is %ld,\n" - " " - " which is too much and thus truncated\n", + " the number of glyphs in this face is %ld,\n", face->num_glyphs )); + FT_TRACE1(( " " + " which is too much and thus truncated\n" )); + } +#endif - if ( !error ) - result = (FT_UInt)face->num_glyphs; + result = (FT_UInt)face->num_glyphs; return result; } @@ -178,7 +182,8 @@ if ( !error ) { if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP || - face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ) + face->glyph->format == FT_GLYPH_FORMAT_OUTLINE || + face->glyph->format == FT_GLYPH_FORMAT_SVG ) { /* ok, copy it */ FT_Glyph glyph; @@ -314,7 +319,7 @@ #if 0xFFFFFFFFUL > FT_UINT_MAX if ( (type->flags & (FT_ULong)FT_UINT_MAX) ) FT_TRACE1(( "FTC_ImageCache_Lookup:" - " higher bits in load_flags 0x%x are dropped\n", + " higher bits in load_flags 0x%lx are dropped\n", (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) )); #endif @@ -332,7 +337,7 @@ #if 1 /* inlining is about 50% faster! */ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, - FTC_GNode_Compare, + ftc_gnode_compare, hash, gindex, &query, node, @@ -406,7 +411,7 @@ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, - FTC_GNode_Compare, + ftc_gnode_compare, hash, gindex, &query, node, @@ -512,7 +517,7 @@ #if 0xFFFFFFFFUL > FT_UINT_MAX if ( (type->flags & (FT_ULong)FT_UINT_MAX) ) FT_TRACE1(( "FTC_ImageCache_Lookup:" - " higher bits in load_flags 0x%x are dropped\n", + " higher bits in load_flags 0x%lx are dropped\n", (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) )); #endif @@ -532,7 +537,7 @@ #if 1 /* inlining is about 50% faster! */ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, - FTC_SNode_Compare, + ftc_snode_compare, hash, gindex, &query, node, @@ -608,7 +613,7 @@ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, - FTC_SNode_Compare, + ftc_snode_compare, hash, gindex, &query, node, diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftccache.c b/lib/libesp32_lvgl/freetype/src/cache/ftccache.c index 1c8e0f322..e0698557b 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftccache.c +++ b/lib/libesp32_lvgl/freetype/src/cache/ftccache.c @@ -4,7 +4,7 @@ * * The FreeType internal cache interface (body). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -90,15 +90,14 @@ ftc_get_top_node_for_hash( FTC_Cache cache, FT_Offset hash ) { - FTC_Node* pnode; FT_Offset idx; idx = hash & cache->mask; - if ( idx < cache->p ) - idx = hash & ( 2 * cache->mask + 1 ); - pnode = cache->buckets + idx; - return pnode; + if ( idx >= cache->p ) + idx = hash & ( cache->mask >> 1 ); + + return cache->buckets + idx; } #endif /* !FTC_INLINE */ @@ -114,12 +113,12 @@ for (;;) { FTC_Node node, *pnode; - FT_UFast p = cache->p; - FT_UFast mask = cache->mask; - FT_UFast count = mask + p + 1; /* number of buckets */ + FT_UFast p = cache->p; + FT_UFast size = cache->mask + 1; /* available size */ + FT_UFast half = size >> 1; - /* do we need to shrink the buckets array? */ + /* do we need to expand the buckets array? */ if ( cache->slack < 0 ) { FTC_Node new_list = NULL; @@ -128,20 +127,22 @@ /* try to expand the buckets array _before_ splitting * the bucket lists */ - if ( p >= mask ) + if ( p == size ) { FT_Memory memory = cache->memory; FT_Error error; /* if we can't expand the array, leave immediately */ - if ( FT_RENEW_ARRAY( cache->buckets, - ( mask + 1 ) * 2, ( mask + 1 ) * 4 ) ) + if ( FT_QRENEW_ARRAY( cache->buckets, size, size * 2 ) ) break; + + cache->mask = 2 * size - 1; + half = size; } - /* split a single bucket */ - pnode = cache->buckets + p; + /* the bucket to split */ + pnode = cache->buckets + p - half; for (;;) { @@ -149,7 +150,7 @@ if ( !node ) break; - if ( node->hash & ( mask + 1 ) ) + if ( node->hash & half ) { *pnode = node->link; node->link = new_list; @@ -159,56 +160,50 @@ pnode = &node->link; } - cache->buckets[p + mask + 1] = new_list; + cache->buckets[p] = new_list; cache->slack += FTC_HASH_MAX_LOAD; + cache->p = p + 1; - if ( p >= mask ) - { - cache->mask = 2 * mask + 1; - cache->p = 0; - } - else - cache->p = p + 1; + FT_TRACE2(( "ftc_cache_resize: cache %u increased to %u hashes\n", + cache->index, cache->p )); } - /* do we need to expand the buckets array? */ - else if ( cache->slack > (FT_Long)count * FTC_HASH_SUB_LOAD ) + /* do we need to shrink the buckets array? */ + else if ( cache->slack > (FT_Long)p * FTC_HASH_SUB_LOAD ) { - FT_UFast old_index = p + mask; - FTC_Node* pold; + FTC_Node old_list = cache->buckets[--p]; - if ( old_index + 1 <= FTC_HASH_INITIAL_SIZE ) + if ( p < FTC_HASH_INITIAL_SIZE ) break; - if ( p == 0 ) + if ( p == half ) { FT_Memory memory = cache->memory; FT_Error error; /* if we can't shrink the array, leave immediately */ - if ( FT_RENEW_ARRAY( cache->buckets, - ( mask + 1 ) * 2, mask + 1 ) ) + if ( FT_QRENEW_ARRAY( cache->buckets, size, half ) ) break; - cache->mask >>= 1; - p = cache->mask; + cache->mask = half - 1; } - else - p--; - pnode = cache->buckets + p; + /* the bucket to merge */ + pnode = cache->buckets + p - half; + while ( *pnode ) pnode = &(*pnode)->link; - pold = cache->buckets + old_index; - *pnode = *pold; - *pold = NULL; + *pnode = old_list; cache->slack -= FTC_HASH_MAX_LOAD; cache->p = p; + + FT_TRACE2(( "ftc_cache_resize: cache %u decreased to %u hashes\n", + cache->index, cache->p )); } /* otherwise, the hash table is balanced */ @@ -240,7 +235,7 @@ if ( node == node0 ) break; - pnode = &(*pnode)->link; + pnode = &node->link; } *pnode = node0->link; @@ -308,7 +303,7 @@ #if 0 /* check, just in case of general corruption :-) */ if ( manager->num_nodes == 0 ) - FT_TRACE0(( "ftc_node_destroy: invalid cache node count (%d)\n", + FT_TRACE0(( "ftc_node_destroy: invalid cache node count (%u)\n", manager->num_nodes )); #endif } @@ -323,13 +318,6 @@ /*************************************************************************/ - FT_LOCAL_DEF( FT_Error ) - FTC_Cache_Init( FTC_Cache cache ) - { - return ftc_cache_init( cache ); - } - - FT_LOCAL_DEF( FT_Error ) ftc_cache_init( FTC_Cache cache ) { @@ -337,30 +325,38 @@ FT_Error error; - cache->p = 0; + cache->p = FTC_HASH_INITIAL_SIZE; cache->mask = FTC_HASH_INITIAL_SIZE - 1; cache->slack = FTC_HASH_INITIAL_SIZE * FTC_HASH_MAX_LOAD; - (void)FT_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE * 2 ); + FT_MEM_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE ); return error; } - static void - FTC_Cache_Clear( FTC_Cache cache ) + FT_LOCAL_DEF( FT_Error ) + FTC_Cache_Init( FTC_Cache cache ) { - if ( cache && cache->buckets ) + return ftc_cache_init( cache ); + } + + + FT_LOCAL_DEF( void ) + ftc_cache_done( FTC_Cache cache ) + { + FT_Memory memory = cache->memory; + + + if ( cache->buckets ) { FTC_Manager manager = cache->manager; + FT_UFast count = cache->p; FT_UFast i; - FT_UFast count; - count = cache->p + cache->mask + 1; - for ( i = 0; i < count; i++ ) { - FTC_Node *pnode = cache->buckets + i, next, node = *pnode; + FTC_Node node = cache->buckets[i], next; while ( node ) @@ -377,30 +373,14 @@ cache->clazz.node_free( node, cache ); node = next; } - cache->buckets[i] = NULL; } - ftc_cache_resize( cache ); } - } + FT_FREE( cache->buckets ); - FT_LOCAL_DEF( void ) - ftc_cache_done( FTC_Cache cache ) - { - if ( cache->memory ) - { - FT_Memory memory = cache->memory; - - - FTC_Cache_Clear( cache ); - - FT_FREE( cache->buckets ); - cache->mask = 0; - cache->p = 0; - cache->slack = 0; - - cache->memory = NULL; - } + cache->p = 0; + cache->mask = 0; + cache->slack = 0; } @@ -417,7 +397,7 @@ FTC_Node node ) { node->hash = hash; - node->cache_index = (FT_UInt16)cache->index; + node->cache_index = (FT_UShort)cache->index; node->ref_count = 0; ftc_node_hash_link( node, cache ); @@ -459,7 +439,7 @@ { error = cache->clazz.node_new( &node, query, cache ); } - FTC_CACHE_TRYLOOP_END( NULL ); + FTC_CACHE_TRYLOOP_END( NULL ) if ( error ) node = NULL; @@ -528,7 +508,7 @@ goto NewNode; } else - pnode = &((*pnode)->link); + pnode = &(*pnode)->link; } } @@ -563,16 +543,15 @@ FTC_Cache_RemoveFaceID( FTC_Cache cache, FTC_FaceID face_id ) { - FT_UFast i, count; FTC_Manager manager = cache->manager; FTC_Node frees = NULL; + FT_UFast count = cache->p; + FT_UFast i; - count = cache->p + cache->mask + 1; for ( i = 0; i < count; i++ ) { - FTC_Node* bucket = cache->buckets + i; - FTC_Node* pnode = bucket; + FTC_Node* pnode = cache->buckets + i; for (;;) diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftccache.h b/lib/libesp32_lvgl/freetype/src/cache/ftccache.h index 11698bb0e..850d2554b 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftccache.h +++ b/lib/libesp32_lvgl/freetype/src/cache/ftccache.h @@ -4,7 +4,7 @@ * * FreeType internal cache interface (specification). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -72,11 +72,12 @@ FT_BEGIN_HEADER #define FTC_NODE_NEXT( x ) FTC_NODE( (x)->mru.next ) #define FTC_NODE_PREV( x ) FTC_NODE( (x)->mru.prev ) + /* address the hash table entries */ #ifdef FTC_INLINE -#define FTC_NODE_TOP_FOR_HASH( cache, hash ) \ - ( ( cache )->buckets + \ - ( ( ( ( hash ) & ( cache )->mask ) < ( cache )->p ) \ - ? ( ( hash ) & ( ( cache )->mask * 2 + 1 ) ) \ +#define FTC_NODE_TOP_FOR_HASH( cache, hash ) \ + ( ( cache )->buckets + \ + ( ( ( ( hash ) & ( cache )->mask ) >= ( cache )->p ) \ + ? ( ( hash ) & ( ( cache )->mask >> 1 ) ) \ : ( ( hash ) & ( cache )->mask ) ) ) #else FT_LOCAL( FTC_Node* ) @@ -139,11 +140,13 @@ FT_BEGIN_HEADER } FTC_CacheClassRec; - /* each cache really implements a dynamic hash table to manage its nodes */ + /* each cache really implements a hash table to manage its nodes */ + /* the number of the table entries (buckets) can change dynamically */ + /* each bucket contains a linked lists of nodes for a given hash */ typedef struct FTC_CacheRec_ { - FT_UFast p; - FT_UFast mask; + FT_UFast p; /* hash table counter */ + FT_UFast mask; /* hash table index range */ FT_Long slack; FTC_Node* buckets; @@ -210,7 +213,7 @@ FT_BEGIN_HEADER #define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \ FT_BEGIN_STMNT \ FTC_Node *_bucket, *_pnode, _node; \ - FTC_Cache _cache = FTC_CACHE(cache); \ + FTC_Cache _cache = FTC_CACHE( cache ); \ FT_Offset _hash = (FT_Offset)(hash); \ FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \ FT_Bool _list_changed = FALSE; \ @@ -251,7 +254,7 @@ FT_BEGIN_HEADER goto NewNode_; \ } \ else \ - _pnode = &((*_pnode)->link); \ + _pnode = &(*_pnode)->link; \ } \ } \ \ diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftccback.h b/lib/libesp32_lvgl/freetype/src/cache/ftccback.h index 542acb156..5f9db213a 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftccback.h +++ b/lib/libesp32_lvgl/freetype/src/cache/ftccback.h @@ -4,7 +4,7 @@ * * Callback functions of the caching sub-system (specification only). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftccmap.c b/lib/libesp32_lvgl/freetype/src/cache/ftccmap.c index 468c008cf..84f22a667 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftccmap.c +++ b/lib/libesp32_lvgl/freetype/src/cache/ftccmap.c @@ -4,7 +4,7 @@ * * FreeType CharMap cache (body) * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -116,7 +116,7 @@ FT_UInt nn; - if ( !FT_NEW( node ) ) + if ( !FT_QNEW( node ) ) { node->face_id = query->face_id; node->cmap_index = query->cmap_index; @@ -273,12 +273,11 @@ if ( error ) goto Exit; - FT_ASSERT( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first ) < - FTC_CMAP_INDICES_MAX ); + FT_ASSERT( char_code - FTC_CMAP_NODE( node )->first < + FTC_CMAP_INDICES_MAX ); /* something rotten can happen with rogue clients */ - if ( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first >= - FTC_CMAP_INDICES_MAX ) ) + if ( char_code - FTC_CMAP_NODE( node )->first >= FTC_CMAP_INDICES_MAX ) return 0; /* XXX: should return appropriate error */ gindex = FTC_CMAP_NODE( node )->indices[char_code - @@ -296,21 +295,19 @@ if ( error ) goto Exit; - if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps ) + if ( cmap_index < face->num_charmaps ) { - FT_CharMap old, cmap = NULL; + FT_CharMap old = face->charmap; + FT_CharMap cmap = face->charmaps[cmap_index]; - old = face->charmap; - cmap = face->charmaps[cmap_index]; - - if ( old != cmap && !no_cmap_change ) - FT_Set_Charmap( face, cmap ); + if ( !no_cmap_change ) + face->charmap = cmap; gindex = FT_Get_Char_Index( face, char_code ); - if ( old != cmap && !no_cmap_change ) - FT_Set_Charmap( face, old ); + if ( !no_cmap_change ) + face->charmap = old; } FTC_CMAP_NODE( node )->indices[char_code - diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftcerror.h b/lib/libesp32_lvgl/freetype/src/cache/ftcerror.h index bedfd2837..dc1a62013 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftcerror.h +++ b/lib/libesp32_lvgl/freetype/src/cache/ftcerror.h @@ -4,7 +4,7 @@ * * Caching sub-system error codes (specification only). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftcglyph.c b/lib/libesp32_lvgl/freetype/src/cache/ftcglyph.c index 7f5438aad..d344733f3 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftcglyph.c +++ b/lib/libesp32_lvgl/freetype/src/cache/ftcglyph.c @@ -4,7 +4,7 @@ * * FreeType Glyph Image (FT_Glyph) cache (body). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -79,20 +79,6 @@ } -#ifdef FTC_INLINE - - FT_LOCAL_DEF( FT_Bool ) - FTC_GNode_Compare( FTC_GNode gnode, - FTC_GQuery gquery, - FTC_Cache cache, - FT_Bool* list_changed ) - { - return ftc_gnode_compare( FTC_NODE( gnode ), gquery, - cache, list_changed ); - } - -#endif - /*************************************************************************/ /*************************************************************************/ /***** *****/ @@ -115,22 +101,22 @@ FT_LOCAL_DEF( FT_Error ) - ftc_gcache_init( FTC_Cache ftccache ) + ftc_gcache_init( FTC_Cache cache ) { - FTC_GCache cache = (FTC_GCache)ftccache; + FTC_GCache gcache = (FTC_GCache)cache; FT_Error error; - error = FTC_Cache_Init( FTC_CACHE( cache ) ); + error = FTC_Cache_Init( cache ); if ( !error ) { - FTC_GCacheClass clazz = (FTC_GCacheClass)FTC_CACHE( cache )->org_class; + FTC_GCacheClass clazz = (FTC_GCacheClass)cache->org_class; - FTC_MruList_Init( &cache->families, + FTC_MruList_Init( &gcache->families, clazz->family_class, 0, /* no maximum here! */ cache, - FTC_CACHE( cache )->memory ); + cache->memory ); } return error; @@ -140,31 +126,31 @@ #if 0 FT_LOCAL_DEF( FT_Error ) - FTC_GCache_Init( FTC_GCache cache ) + FTC_GCache_Init( FTC_GCache gcache ) { - return ftc_gcache_init( FTC_CACHE( cache ) ); + return ftc_gcache_init( FTC_CACHE( gcache ) ); } #endif /* 0 */ FT_LOCAL_DEF( void ) - ftc_gcache_done( FTC_Cache ftccache ) + ftc_gcache_done( FTC_Cache cache ) { - FTC_GCache cache = (FTC_GCache)ftccache; + FTC_GCache gcache = (FTC_GCache)cache; - FTC_Cache_Done( (FTC_Cache)cache ); - FTC_MruList_Done( &cache->families ); + FTC_Cache_Done( cache ); + FTC_MruList_Done( &gcache->families ); } #if 0 FT_LOCAL_DEF( void ) - FTC_GCache_Done( FTC_GCache cache ) + FTC_GCache_Done( FTC_GCache gcache ) { - ftc_gcache_done( FTC_CACHE( cache ) ); + ftc_gcache_done( FTC_CACHE( gcache ) ); } #endif /* 0 */ @@ -183,7 +169,7 @@ #ifndef FTC_INLINE FT_LOCAL_DEF( FT_Error ) - FTC_GCache_Lookup( FTC_GCache cache, + FTC_GCache_Lookup( FTC_GCache gcache, FT_Offset hash, FT_UInt gindex, FTC_GQuery query, @@ -204,7 +190,7 @@ /* out-of-memory condition occurs during glyph node initialization. */ family->num_nodes++; - error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, anode ); + error = FTC_Cache_Lookup( FTC_CACHE( gcache ), hash, query, anode ); if ( --family->num_nodes == 0 ) FTC_FAMILY_FREE( family, cache ); diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftcglyph.h b/lib/libesp32_lvgl/freetype/src/cache/ftcglyph.h index 5629545f3..0181e9816 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftcglyph.h +++ b/lib/libesp32_lvgl/freetype/src/cache/ftcglyph.h @@ -4,7 +4,7 @@ * * FreeType abstract glyph cache (specification). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -58,7 +58,7 @@ * - FTC_GNode sub-class, e.g. MyNode, with relevant methods: * my_node_new (must call FTC_GNode_Init) * my_node_free (must call FTC_GNode_Done) - * my_node_compare (must call FTC_GNode_Compare) + * my_node_compare (must call ftc_gnode_compare) * my_node_remove_faceid (must call ftc_gnode_unselect in case * of match) * @@ -140,8 +140,8 @@ FT_BEGIN_HEADER } FTC_FamilyRec, *FTC_Family; -#define FTC_FAMILY(x) ( (FTC_Family)(x) ) -#define FTC_FAMILY_P(x) ( (FTC_Family*)(x) ) +#define FTC_FAMILY( x ) ( (FTC_Family)(x) ) +#define FTC_FAMILY_P( x ) ( (FTC_Family*)(x) ) typedef struct FTC_GNodeRec_ @@ -179,19 +179,6 @@ FT_BEGIN_HEADER FT_UInt gindex, /* glyph index for node */ FTC_Family family ); -#ifdef FTC_INLINE - - /* returns TRUE iff the query's glyph index correspond to the node; */ - /* this assumes that the `family' and `hash' fields of the query are */ - /* already correctly set */ - FT_LOCAL( FT_Bool ) - FTC_GNode_Compare( FTC_GNode gnode, - FTC_GQuery gquery, - FTC_Cache cache, - FT_Bool* list_changed ); - -#endif - /* call this function to clear a node's family -- this is necessary */ /* to implement the `node_remove_faceid' cache method correctly */ FT_LOCAL( void ) @@ -245,7 +232,7 @@ FT_BEGIN_HEADER #define FTC_GCACHE_CLASS( x ) ((FTC_GCacheClass)(x)) #define FTC_CACHE_GCACHE_CLASS( x ) \ - FTC_GCACHE_CLASS( FTC_CACHE(x)->org_class ) + FTC_GCACHE_CLASS( FTC_CACHE( x )->org_class ) #define FTC_CACHE_FAMILY_CLASS( x ) \ ( (FTC_MruListClass)FTC_CACHE_GCACHE_CLASS( x )->family_class ) diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftcimage.c b/lib/libesp32_lvgl/freetype/src/cache/ftcimage.c index 58ebad8c9..428e5e1a7 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftcimage.c +++ b/lib/libesp32_lvgl/freetype/src/cache/ftcimage.c @@ -4,7 +4,7 @@ * * FreeType Image cache (body). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -64,7 +64,7 @@ FTC_INode inode = NULL; - if ( !FT_NEW( inode ) ) + if ( !FT_QNEW( inode ) ) { FTC_GNode gnode = FTC_GNODE( inode ); FTC_Family family = gquery->family; @@ -74,6 +74,7 @@ /* initialize its inner fields */ FTC_GNode_Init( gnode, gindex, family ); + inode->glyph = NULL; /* we will now load the glyph image */ error = clazz->family_load_glyph( family, gindex, cache, diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftcimage.h b/lib/libesp32_lvgl/freetype/src/cache/ftcimage.h index a400788b3..d2a807f15 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftcimage.h +++ b/lib/libesp32_lvgl/freetype/src/cache/ftcimage.h @@ -4,7 +4,7 @@ * * FreeType Generic Image cache (specification) * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -51,8 +51,8 @@ FT_BEGIN_HEADER } FTC_INodeRec, *FTC_INode; #define FTC_INODE( x ) ( (FTC_INode)( x ) ) -#define FTC_INODE_GINDEX( x ) FTC_GNODE(x)->gindex -#define FTC_INODE_FAMILY( x ) FTC_GNODE(x)->family +#define FTC_INODE_GINDEX( x ) FTC_GNODE( x )->gindex +#define FTC_INODE_FAMILY( x ) FTC_GNODE( x )->family typedef FT_Error (*FTC_IFamily_LoadGlyphFunc)( FTC_Family family, @@ -72,7 +72,7 @@ FT_BEGIN_HEADER #define FTC_IFAMILY_CLASS( x ) ((FTC_IFamilyClass)(x)) #define FTC_CACHE_IFAMILY_CLASS( x ) \ - FTC_IFAMILY_CLASS( FTC_CACHE_GCACHE_CLASS(x)->family_class ) + FTC_IFAMILY_CLASS( FTC_CACHE_GCACHE_CLASS( x )->family_class ) /* can be used as a @FTC_Node_FreeFunc */ diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftcmanag.c b/lib/libesp32_lvgl/freetype/src/cache/ftcmanag.c index 436d41f37..94f8469c9 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftcmanag.c +++ b/lib/libesp32_lvgl/freetype/src/cache/ftcmanag.c @@ -4,7 +4,7 @@ * * FreeType Cache Manager (body). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -357,7 +357,7 @@ { FT_Error error; FT_Memory memory; - FTC_Manager manager = 0; + FTC_Manager manager = NULL; if ( !library ) @@ -368,7 +368,7 @@ memory = library->memory; - if ( FT_NEW( manager ) ) + if ( FT_QNEW( manager ) ) goto Exit; if ( max_faces == 0 ) @@ -383,6 +383,7 @@ manager->library = library; manager->memory = memory; manager->max_weight = max_bytes; + manager->cur_weight = 0; manager->request_face = requester; manager->request_data = req_data; @@ -399,6 +400,10 @@ manager, memory ); + manager->nodes_list = NULL; + manager->num_nodes = 0; + manager->num_caches = 0; + *amanager = manager; Exit: @@ -421,7 +426,7 @@ memory = manager->memory; /* now discard all caches */ - for (idx = manager->num_caches; idx-- > 0; ) + for ( idx = manager->num_caches; idx-- > 0; ) { FTC_Cache cache = manager->caches[idx]; @@ -484,8 +489,8 @@ FTC_Cache cache = manager->caches[node->cache_index]; - if ( (FT_UInt)node->cache_index >= manager->num_caches ) - FT_TRACE0(( "FTC_Manager_Check: invalid node (cache index = %ld\n", + if ( node->cache_index >= manager->num_caches ) + FT_TRACE0(( "FTC_Manager_Check: invalid node (cache index = %hu\n", node->cache_index )); else weight += cache->clazz.node_weight( node, cache ); @@ -515,7 +520,7 @@ if ( count != manager->num_nodes ) FT_TRACE0(( "FTC_Manager_Check:" - " invalid cache node count %d instead of %d\n", + " invalid cache node count %u instead of %u\n", manager->num_nodes, count )); } } @@ -532,7 +537,7 @@ FT_LOCAL_DEF( void ) FTC_Manager_Compress( FTC_Manager manager ) { - FTC_Node node, first; + FTC_Node node, prev, first; if ( !manager ) @@ -543,7 +548,7 @@ #ifdef FT_DEBUG_ERROR FTC_Manager_Check( manager ); - FT_TRACE0(( "compressing, weight = %ld, max = %ld, nodes = %d\n", + FT_TRACE0(( "compressing, weight = %ld, max = %ld, nodes = %u\n", manager->cur_weight, manager->max_weight, manager->num_nodes )); #endif @@ -552,20 +557,16 @@ return; /* go to last node -- it's a circular list */ - node = FTC_NODE_PREV( first ); + prev = FTC_NODE_PREV( first ); do { - FTC_Node prev; - - - prev = ( node == first ) ? NULL : FTC_NODE_PREV( node ); + node = prev; + prev = FTC_NODE_PREV( node ); if ( node->ref_count <= 0 ) ftc_node_destroy( node, manager ); - node = prev; - - } while ( node && manager->cur_weight > manager->max_weight ); + } while ( node != first && manager->cur_weight > manager->max_weight ); } @@ -593,7 +594,7 @@ goto Exit; } - if ( !FT_ALLOC( cache, clazz->cache_size ) ) + if ( !FT_QALLOC( cache, clazz->cache_size ) ) { cache->manager = manager; cache->memory = memory; @@ -628,20 +629,20 @@ FT_UInt count ) { FTC_Node first = manager->nodes_list; - FTC_Node node; - FT_UInt result; + FTC_Node prev, node; + FT_UInt result = 0; /* try to remove `count' nodes from the list */ - if ( !first ) /* empty list! */ - return 0; + if ( !first || !count ) + return result; - /* go to last node - it's a circular list */ - node = FTC_NODE_PREV(first); - for ( result = 0; result < count; ) + /* go to last node -- it's a circular list */ + prev = FTC_NODE_PREV( first ); + do { - FTC_Node prev = FTC_NODE_PREV( node ); - + node = prev; + prev = FTC_NODE_PREV( node ); /* don't touch locked nodes */ if ( node->ref_count <= 0 ) @@ -649,13 +650,9 @@ ftc_node_destroy( node, manager ); result++; } + } while ( node != first && result < count ); - if ( node == first ) - break; - - node = prev; - } - return result; + return result; } @@ -689,9 +686,9 @@ FTC_Node_Unref( FTC_Node node, FTC_Manager manager ) { - if ( node && - manager && - (FT_UInt)node->cache_index < manager->num_caches ) + if ( node && + manager && + node->cache_index < manager->num_caches ) node->ref_count--; } diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftcmanag.h b/lib/libesp32_lvgl/freetype/src/cache/ftcmanag.h index 6c6ec6854..5b30929c9 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftcmanag.h +++ b/lib/libesp32_lvgl/freetype/src/cache/ftcmanag.h @@ -4,7 +4,7 @@ * * FreeType Cache Manager (specification). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftcmru.c b/lib/libesp32_lvgl/freetype/src/cache/ftcmru.c index 8feed45f6..ad10a06bc 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftcmru.c +++ b/lib/libesp32_lvgl/freetype/src/cache/ftcmru.c @@ -4,7 +4,7 @@ * * FreeType MRU support (body). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -262,6 +262,8 @@ if ( list->clazz.node_done ) list->clazz.node_done( node, list->data ); } + + /* zero new node in case of node_init failure */ else if ( FT_ALLOC( node, list->clazz.node_size ) ) goto Exit; @@ -327,29 +329,23 @@ FTC_MruNode_CompareFunc selection, FT_Pointer key ) { - FTC_MruNode first, node, next; + FTC_MruNode first = list->nodes; + FTC_MruNode prev, node; - first = list->nodes; - while ( first && ( !selection || selection( first, key ) ) ) + if ( !first || !selection ) + return; + + prev = first->prev; + do { - FTC_MruList_Remove( list, first ); - first = list->nodes; - } + node = prev; + prev = node->prev; - if ( first ) - { - node = first->next; - while ( node != first ) - { - next = node->next; + if ( selection( node, key ) ) + FTC_MruList_Remove( list, node ); - if ( selection( node, key ) ) - FTC_MruList_Remove( list, node ); - - node = next; - } - } + } while ( node != first ); } diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftcmru.h b/lib/libesp32_lvgl/freetype/src/cache/ftcmru.h index ac4f9b126..45e5249ca 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftcmru.h +++ b/lib/libesp32_lvgl/freetype/src/cache/ftcmru.h @@ -4,7 +4,7 @@ * * Simple MRU list-cache (specification). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftcsbits.c b/lib/libesp32_lvgl/freetype/src/cache/ftcsbits.c index e0db930af..9929a0bcc 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftcsbits.c +++ b/lib/libesp32_lvgl/freetype/src/cache/ftcsbits.c @@ -4,7 +4,7 @@ * * FreeType sbits manager (body). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -52,10 +52,8 @@ pitch = -pitch; size = (FT_ULong)pitch * bitmap->rows; - if ( !size ) - return FT_Err_Ok; - if ( !FT_ALLOC( sbit->buffer, size ) ) + if ( !FT_QALLOC( sbit->buffer, size ) ) FT_MEM_COPY( sbit->buffer, bitmap->buffer, size ); return error; @@ -108,13 +106,12 @@ FT_Error error; FTC_GNode gnode = FTC_GNODE( snode ); FTC_Family family = gnode->family; - FT_Memory memory = manager->memory; FT_Face face; FTC_SBit sbit; FTC_SFamilyClass clazz; - if ( (FT_UInt)(gindex - gnode->gindex) >= snode->count ) + if ( gindex - gnode->gindex >= snode->count ) { FT_ERROR(( "ftc_snode_load: invalid glyph index" )); return FT_THROW( Invalid_Argument ); @@ -123,8 +120,6 @@ sbit = snode->sbits + ( gindex - gnode->gindex ); clazz = (FTC_SFamilyClass)family->clazz; - sbit->buffer = 0; - error = clazz->family_load_glyph( family, gindex, manager, &face ); if ( error ) goto BadGlyph; @@ -143,12 +138,13 @@ goto BadGlyph; } - /* Check whether our values fit into 8-bit containers! */ + /* Check whether our values fit into 8/16-bit containers! */ /* If this is not the case, our bitmap is too large */ /* and we will leave it as `missing' with sbit.buffer = 0 */ #define CHECK_CHAR( d ) ( temp = (FT_Char)d, (FT_Int) temp == (FT_Int) d ) #define CHECK_BYTE( d ) ( temp = (FT_Byte)d, (FT_UInt)temp == (FT_UInt)d ) +#define CHECK_SHRT( d ) ( temp = (FT_Short)d, (FT_Int)temp == (FT_Int) d ) /* horizontal advance in pixels */ xadvance = ( slot->advance.x + 32 ) >> 6; @@ -156,7 +152,7 @@ if ( !CHECK_BYTE( bitmap->rows ) || !CHECK_BYTE( bitmap->width ) || - !CHECK_CHAR( bitmap->pitch ) || + !CHECK_SHRT( bitmap->pitch ) || !CHECK_CHAR( slot->bitmap_left ) || !CHECK_CHAR( slot->bitmap_top ) || !CHECK_CHAR( xadvance ) || @@ -169,16 +165,25 @@ sbit->width = (FT_Byte)bitmap->width; sbit->height = (FT_Byte)bitmap->rows; - sbit->pitch = (FT_Char)bitmap->pitch; + sbit->pitch = (FT_Short)bitmap->pitch; sbit->left = (FT_Char)slot->bitmap_left; sbit->top = (FT_Char)slot->bitmap_top; sbit->xadvance = (FT_Char)xadvance; sbit->yadvance = (FT_Char)yadvance; sbit->format = (FT_Byte)bitmap->pixel_mode; - sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1); + sbit->max_grays = (FT_Byte)( bitmap->num_grays - 1 ); - /* copy the bitmap into a new buffer -- ignore error */ - error = ftc_sbit_copy_bitmap( sbit, bitmap, memory ); + if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) + { + /* take the bitmap ownership */ + sbit->buffer = bitmap->buffer; + slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; + } + else + { + /* copy the bitmap into a new buffer -- ignore error */ + error = ftc_sbit_copy_bitmap( sbit, bitmap, manager->memory ); + } /* now, compute size */ if ( asize ) @@ -228,7 +233,7 @@ goto Exit; } - if ( !FT_NEW( snode ) ) + if ( !FT_QNEW( snode ) ) { FT_UInt count, start; @@ -243,7 +248,9 @@ snode->count = count; for ( node_count = 0; node_count < count; node_count++ ) { - snode->sbits[node_count].width = 255; + snode->sbits[node_count].width = 255; + snode->sbits[node_count].height = 0; + snode->sbits[node_count].buffer = NULL; } error = ftc_snode_load( snode, @@ -335,10 +342,10 @@ FT_Bool result; - if (list_changed) + if ( list_changed ) *list_changed = FALSE; - result = FT_BOOL( gnode->family == gquery->family && - (FT_UInt)( gindex - gnode->gindex ) < snode->count ); + result = FT_BOOL( gnode->family == gquery->family && + gindex - gnode->gindex < snode->count ); if ( result ) { /* check if we need to load the glyph bitmap now */ @@ -390,7 +397,7 @@ { error = ftc_snode_load( snode, cache->manager, gindex, &size ); } - FTC_CACHE_TRYLOOP_END( list_changed ); + FTC_CACHE_TRYLOOP_END( list_changed ) ftcsnode->ref_count--; /* unlock the node */ @@ -404,19 +411,4 @@ return result; } - -#ifdef FTC_INLINE - - FT_LOCAL_DEF( FT_Bool ) - FTC_SNode_Compare( FTC_SNode snode, - FTC_GQuery gquery, - FTC_Cache cache, - FT_Bool* list_changed ) - { - return ftc_snode_compare( FTC_NODE( snode ), gquery, - cache, list_changed ); - } - -#endif - /* END */ diff --git a/lib/libesp32_lvgl/freetype/src/cache/ftcsbits.h b/lib/libesp32_lvgl/freetype/src/cache/ftcsbits.h index 46f797e72..e833cb5c3 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/ftcsbits.h +++ b/lib/libesp32_lvgl/freetype/src/cache/ftcsbits.h @@ -4,7 +4,7 @@ * * A small-bitmap cache (specification). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -61,7 +61,7 @@ FT_BEGIN_HEADER typedef const FTC_SFamilyClassRec* FTC_SFamilyClass; -#define FTC_SFAMILY_CLASS( x ) ((FTC_SFamilyClass)(x)) +#define FTC_SFAMILY_CLASS( x ) ( (FTC_SFamilyClass)(x) ) #define FTC_CACHE_SFAMILY_CLASS( x ) \ FTC_SFAMILY_CLASS( FTC_CACHE_GCACHE_CLASS( x )->family_class ) @@ -81,17 +81,6 @@ FT_BEGIN_HEADER FTC_SNode_Weight( FTC_SNode inode ); #endif - -#ifdef FTC_INLINE - - FT_LOCAL( FT_Bool ) - FTC_SNode_Compare( FTC_SNode snode, - FTC_GQuery gquery, - FTC_Cache cache, - FT_Bool* list_changed); - -#endif - /* */ FT_END_HEADER diff --git a/lib/libesp32_lvgl/freetype/src/cache/rules.mk b/lib/libesp32_lvgl/freetype/src/cache/rules.mk index 4738b5153..82b39aa33 100644 --- a/lib/libesp32_lvgl/freetype/src/cache/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/cache/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 2000-2020 by +# Copyright (C) 2000-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/cff/cff.c b/lib/libesp32_lvgl/freetype/src/cff/cff.c index 0fa6c8787..b486c389e 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/cff.c +++ b/lib/libesp32_lvgl/freetype/src/cff/cff.c @@ -4,7 +4,7 @@ * * FreeType OpenType driver component (body only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cff/cffcmap.c b/lib/libesp32_lvgl/freetype/src/cff/cffcmap.c index 6d16ed422..10d287bc8 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/cffcmap.c +++ b/lib/libesp32_lvgl/freetype/src/cff/cffcmap.c @@ -4,7 +4,7 @@ * * CFF character mapping table (cmap) support (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -32,9 +32,10 @@ /*************************************************************************/ FT_CALLBACK_DEF( FT_Error ) - cff_cmap_encoding_init( CFF_CMapStd cmap, - FT_Pointer pointer ) + cff_cmap_encoding_init( FT_CMap cmap, + FT_Pointer pointer ) { + CFF_CMapStd cffcmap = (CFF_CMapStd)cmap; TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); CFF_Font cff = (CFF_Font)face->extra.data; CFF_Encoding encoding = &cff->encoding; @@ -42,63 +43,56 @@ FT_UNUSED( pointer ); - cmap->gids = encoding->codes; + cffcmap->gids = encoding->codes; return 0; } FT_CALLBACK_DEF( void ) - cff_cmap_encoding_done( CFF_CMapStd cmap ) + cff_cmap_encoding_done( FT_CMap cmap ) { - cmap->gids = NULL; + CFF_CMapStd cffcmap = (CFF_CMapStd)cmap; + + + cffcmap->gids = NULL; } FT_CALLBACK_DEF( FT_UInt ) - cff_cmap_encoding_char_index( CFF_CMapStd cmap, - FT_UInt32 char_code ) + cff_cmap_encoding_char_index( FT_CMap cmap, + FT_UInt32 char_code ) { - FT_UInt result = 0; + CFF_CMapStd cffcmap = (CFF_CMapStd)cmap; + FT_UInt result = 0; if ( char_code < 256 ) - result = cmap->gids[char_code]; + result = cffcmap->gids[char_code]; return result; } - FT_CALLBACK_DEF( FT_UInt32 ) - cff_cmap_encoding_char_next( CFF_CMapStd cmap, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + cff_cmap_encoding_char_next( FT_CMap cmap, + FT_UInt32 *pchar_code ) { - FT_UInt result = 0; - FT_UInt32 char_code = *pchar_code; + CFF_CMapStd cffcmap = (CFF_CMapStd)cmap; + FT_UInt result = 0; + FT_UInt32 char_code = *pchar_code; - *pchar_code = 0; - - if ( char_code < 255 ) + while ( char_code < 255 ) { - FT_UInt code = (FT_UInt)(char_code + 1); - - - for (;;) + result = cffcmap->gids[++char_code]; + if ( result ) { - if ( code >= 256 ) - break; - - result = cmap->gids[code]; - if ( result != 0 ) - { - *pchar_code = code; - break; - } - - code++; + *pchar_code = char_code; + break; } } + return result; } @@ -130,9 +124,10 @@ /*************************************************************************/ FT_CALLBACK_DEF( const char* ) - cff_sid_to_glyph_name( TT_Face face, + cff_sid_to_glyph_name( void* face_, /* TT_Face */ FT_UInt idx ) { + TT_Face face = (TT_Face)face_; CFF_Font cff = (CFF_Font)face->extra.data; CFF_Charset charset = &cff->charset; FT_UInt sid = charset->sids[idx]; @@ -143,14 +138,15 @@ FT_CALLBACK_DEF( FT_Error ) - cff_cmap_unicode_init( PS_Unicodes unicodes, + cff_cmap_unicode_init( FT_CMap cmap, /* PS_Unicodes */ FT_Pointer pointer ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); - CFF_Font cff = (CFF_Font)face->extra.data; - CFF_Charset charset = &cff->charset; - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); + CFF_Font cff = (CFF_Font)face->extra.data; + CFF_Charset charset = &cff->charset; + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; FT_UNUSED( pointer ); @@ -166,17 +162,18 @@ return psnames->unicodes_init( memory, unicodes, cff->num_glyphs, - (PS_GetGlyphNameFunc)&cff_sid_to_glyph_name, + &cff_sid_to_glyph_name, (PS_FreeGlyphNameFunc)NULL, (FT_Pointer)face ); } FT_CALLBACK_DEF( void ) - cff_cmap_unicode_done( PS_Unicodes unicodes ) + cff_cmap_unicode_done( FT_CMap cmap ) /* PS_Unicodes */ { - FT_Face face = FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); + PS_Unicodes unicodes = (PS_Unicodes)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); FT_FREE( unicodes->maps ); @@ -185,25 +182,27 @@ FT_CALLBACK_DEF( FT_UInt ) - cff_cmap_unicode_char_index( PS_Unicodes unicodes, - FT_UInt32 char_code ) + cff_cmap_unicode_char_index( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 char_code ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - CFF_Font cff = (CFF_Font)face->extra.data; - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + CFF_Font cff = (CFF_Font)face->extra.data; + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; return psnames->unicodes_char_index( unicodes, char_code ); } - FT_CALLBACK_DEF( FT_UInt32 ) - cff_cmap_unicode_char_next( PS_Unicodes unicodes, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + cff_cmap_unicode_char_next( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 *pchar_code ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - CFF_Font cff = (CFF_Font)face->extra.data; - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + CFF_Font cff = (CFF_Font)face->extra.data; + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; return psnames->unicodes_char_next( unicodes, pchar_code ); diff --git a/lib/libesp32_lvgl/freetype/src/cff/cffcmap.h b/lib/libesp32_lvgl/freetype/src/cff/cffcmap.h index 69fab8dc6..b2afc2fab 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/cffcmap.h +++ b/lib/libesp32_lvgl/freetype/src/cff/cffcmap.h @@ -4,7 +4,7 @@ * * CFF character mapping table (cmap) support (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cff/cffdrivr.c b/lib/libesp32_lvgl/freetype/src/cff/cffdrivr.c index 486ab2423..9898d625c 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/cffdrivr.c +++ b/lib/libesp32_lvgl/freetype/src/cff/cffdrivr.c @@ -4,8 +4,8 @@ * * OpenType font driver implementation (body). * - * Copyright (C) 1996-2020 by - * David Turner, Robert Wilhelm, and Werner Lemberg. + * Copyright (C) 1996-2023 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. * * This file is part of the FreeType project, and may only be used, * modified, and distributed under the terms of the FreeType project @@ -108,20 +108,20 @@ * They can be implemented by format-specific interfaces. */ FT_CALLBACK_DEF( FT_Error ) - cff_get_kerning( FT_Face ttface, /* TT_Face */ + cff_get_kerning( FT_Face face, /* CFF_Face */ FT_UInt left_glyph, FT_UInt right_glyph, FT_Vector* kerning ) { - TT_Face face = (TT_Face)ttface; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + CFF_Face cffface = (CFF_Face)face; + SFNT_Service sfnt = (SFNT_Service)cffface->sfnt; kerning->x = 0; kerning->y = 0; if ( sfnt ) - kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph ); + kerning->x = sfnt->get_kerning( cffface, left_glyph, right_glyph ); return FT_Err_Ok; } @@ -158,23 +158,23 @@ * FreeType error code. 0 means success. */ FT_CALLBACK_DEF( FT_Error ) - cff_glyph_load( FT_GlyphSlot cffslot, /* CFF_GlyphSlot */ - FT_Size cffsize, /* CFF_Size */ + cff_glyph_load( FT_GlyphSlot slot, /* CFF_GlyphSlot */ + FT_Size size, /* CFF_Size */ FT_UInt glyph_index, FT_Int32 load_flags ) { FT_Error error; - CFF_GlyphSlot slot = (CFF_GlyphSlot)cffslot; - CFF_Size size = (CFF_Size)cffsize; + CFF_GlyphSlot cffslot = (CFF_GlyphSlot)slot; + CFF_Size cffsize = (CFF_Size)size; - if ( !slot ) + if ( !cffslot ) return FT_THROW( Invalid_Slot_Handle ); FT_TRACE1(( "cff_glyph_load: glyph index %d\n", glyph_index )); /* check whether we want a scaled outline or bitmap */ - if ( !size ) + if ( !cffsize ) load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; /* reset the size object if necessary */ @@ -184,12 +184,12 @@ if ( size ) { /* these two objects must have the same parent */ - if ( cffsize->face != cffslot->face ) + if ( size->face != slot->face ) return FT_THROW( Invalid_Face_Handle ); } /* now load the glyph outline if necessary */ - error = cff_slot_load( slot, size, glyph_index, load_flags ); + error = cff_slot_load( cffslot, cffsize, glyph_index, load_flags ); /* force drop-out mode to 2 - irrelevant now */ /* slot->outline.dropout_mode = 2; */ @@ -216,7 +216,7 @@ /* it is no longer necessary that those values are identical to */ /* the values in the `CFF' table */ - TT_Face ttface = (TT_Face)face; + CFF_Face cffface = (CFF_Face)face; FT_Short dummy; @@ -225,7 +225,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without VVAR table */ if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && - !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) + !( cffface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif @@ -233,7 +233,7 @@ /* otherwise we extract the info from the CFF glyphstrings */ /* (instead of synthesizing a global value using the `OS/2' */ /* table) */ - if ( !ttface->vertical_info ) + if ( !cffface->vertical_info ) goto Missing_Table; for ( nn = 0; nn < count; nn++ ) @@ -241,11 +241,11 @@ FT_UShort ah; - ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface, - 1, - start + nn, - &dummy, - &ah ); + ( (SFNT_Service)cffface->sfnt )->get_metrics( cffface, + 1, + start + nn, + &dummy, + &ah ); FT_TRACE5(( " idx %d: advance height %d font unit%s\n", start + nn, @@ -259,12 +259,12 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without HVAR table */ if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && - !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) + !( cffface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif /* check whether we have data from the `hmtx' table at all */ - if ( !ttface->horizontal.number_Of_HMetrics ) + if ( !cffface->horizontal.number_Of_HMetrics ) goto Missing_Table; for ( nn = 0; nn < count; nn++ ) @@ -272,11 +272,11 @@ FT_UShort aw; - ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface, - 0, - start + nn, - &dummy, - &aw ); + ( (SFNT_Service)cffface->sfnt )->get_metrics( cffface, + 0, + start + nn, + &dummy, + &aw ); FT_TRACE5(( " idx %d: advance width %d font unit%s\n", start + nn, @@ -312,13 +312,14 @@ * */ - static FT_Error - cff_get_glyph_name( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_glyph_name( FT_Face face, /* CFF_Face */ FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max ) { - CFF_Font font = (CFF_Font)face->extra.data; + CFF_Face cffface = (CFF_Face)face; + CFF_Font font = (CFF_Font)cffface->extra.data; FT_String* gname; FT_UShort sid; FT_Error error; @@ -338,15 +339,12 @@ if ( service && service->get_name ) - return service->get_name( FT_FACE( face ), - glyph_index, - buffer, - buffer_max ); + return service->get_name( face, glyph_index, buffer, buffer_max ); else { FT_ERROR(( "cff_get_glyph_name:" - " cannot get glyph name from a CFF2 font\n" - " " + " cannot get glyph name from a CFF2 font\n" )); + FT_ERROR(( " " " without the `psnames' module\n" )); error = FT_THROW( Missing_Module ); goto Exit; @@ -356,8 +354,8 @@ if ( !font->psnames ) { FT_ERROR(( "cff_get_glyph_name:" - " cannot get glyph name from CFF & CEF fonts\n" - " " + " cannot get glyph name from CFF & CEF fonts\n" )); + FT_ERROR(( " " " without the `psnames' module\n" )); error = FT_THROW( Missing_Module ); goto Exit; @@ -366,7 +364,7 @@ /* first, locate the sid in the charset table */ sid = font->charset.sids[glyph_index]; - /* now, lookup the name itself */ + /* now, look up the name itself */ gname = cff_index_get_sid_string( font, sid ); if ( gname ) @@ -379,21 +377,19 @@ } - static FT_UInt - cff_get_name_index( CFF_Face face, + FT_CALLBACK_DEF( FT_UInt ) + cff_get_name_index( FT_Face face, /* CFF_Face */ const FT_String* glyph_name ) { - CFF_Font cff; - CFF_Charset charset; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; + CFF_Charset charset = &cff->charset; FT_Service_PsCMaps psnames; FT_String* name; FT_UShort sid; FT_UInt i; - cff = (CFF_FontRec *)face->extra.data; - charset = &cff->charset; - /* CFF2 table does not have glyph names; */ /* we need to use `post' table method */ if ( cff->version_major == 2 ) @@ -408,12 +404,12 @@ if ( service && service->name_index ) - return service->name_index( FT_FACE( face ), glyph_name ); + return service->name_index( face, glyph_name ); else { FT_ERROR(( "cff_get_name_index:" - " cannot get glyph index from a CFF2 font\n" - " " + " cannot get glyph index from a CFF2 font\n" )); + FT_ERROR(( " " " without the `psnames' module\n" )); return 0; } @@ -446,8 +442,8 @@ FT_DEFINE_SERVICE_GLYPHDICTREC( cff_service_glyph_dict, - (FT_GlyphDict_GetNameFunc) cff_get_glyph_name, /* get_name */ - (FT_GlyphDict_NameIndexFunc)cff_get_name_index /* name_index */ + cff_get_glyph_name, /* FT_GlyphDict_GetNameFunc get_name */ + cff_get_name_index /* FT_GlyphDict_NameIndexFunc name_index */ ) @@ -456,29 +452,36 @@ * */ - static FT_Int + FT_CALLBACK_DEF( FT_Int ) cff_ps_has_glyph_names( FT_Face face ) { return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0; } - static FT_Error - cff_ps_get_font_info( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_ps_get_font_info( FT_Face face, /* CFF_Face */ PS_FontInfoRec* afont_info ) { - CFF_Font cff = (CFF_Font)face->extra.data; - FT_Error error = FT_Err_Ok; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; + FT_Error error = FT_Err_Ok; + if ( cffface->is_cff2 ) + { + error = FT_THROW( Invalid_Argument ); + goto Fail; + } + if ( cff && !cff->font_info ) { CFF_FontRecDict dict = &cff->top_font.font_dict; - PS_FontInfoRec *font_info = NULL; - FT_Memory memory = face->root.memory; + FT_Memory memory = FT_FACE_MEMORY( face ); + PS_FontInfoRec* font_info = NULL; - if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) ) + if ( FT_QNEW( font_info ) ) goto Fail; font_info->version = cff_index_get_sid_string( cff, @@ -507,23 +510,24 @@ } - static FT_Error - cff_ps_get_font_extra( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_ps_get_font_extra( FT_Face face, /* CFF_Face */ PS_FontExtraRec* afont_extra ) { - CFF_Font cff = (CFF_Font)face->extra.data; - FT_Error error = FT_Err_Ok; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; + FT_Error error = FT_Err_Ok; - if ( cff && cff->font_extra == NULL ) + if ( cff && !cff->font_extra ) { CFF_FontRecDict dict = &cff->top_font.font_dict; + FT_Memory memory = FT_FACE_MEMORY( face ); PS_FontExtraRec* font_extra = NULL; - FT_Memory memory = face->root.memory; FT_String* embedded_postscript; - if ( FT_ALLOC( font_extra, sizeof ( *font_extra ) ) ) + if ( FT_QNEW( font_extra ) ) goto Fail; font_extra->fs_type = 0U; @@ -588,13 +592,13 @@ FT_DEFINE_SERVICE_PSINFOREC( cff_service_ps_info, - (PS_GetFontInfoFunc) cff_ps_get_font_info, /* ps_get_font_info */ - (PS_GetFontExtraFunc) cff_ps_get_font_extra, /* ps_get_font_extra */ - (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names, /* ps_has_glyph_names */ + cff_ps_get_font_info, /* PS_GetFontInfoFunc ps_get_font_info */ + cff_ps_get_font_extra, /* PS_GetFontExtraFunc ps_get_font_extra */ + cff_ps_has_glyph_names, /* PS_HasGlyphNamesFunc ps_has_glyph_names */ /* unsupported with CFF fonts */ - (PS_GetFontPrivateFunc)NULL, /* ps_get_font_private */ + NULL, /* PS_GetFontPrivateFunc ps_get_font_private */ /* not implemented */ - (PS_GetFontValueFunc) NULL /* ps_get_font_value */ + NULL /* PS_GetFontValueFunc ps_get_font_value */ ) @@ -603,17 +607,18 @@ * */ - static const char* - cff_get_ps_name( CFF_Face face ) + FT_CALLBACK_DEF( const char* ) + cff_get_ps_name( FT_Face face ) /* CFF_Face */ { - CFF_Font cff = (CFF_Font)face->extra.data; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; + SFNT_Service sfnt = (SFNT_Service)cffface->sfnt; /* following the OpenType specification 1.7, we return the name stored */ /* in the `name' table for a CFF wrapped into an SFNT container */ - if ( FT_IS_SFNT( FT_FACE( face ) ) && sfnt ) + if ( FT_IS_SFNT( face ) && sfnt ) { FT_Library library = FT_FACE_LIBRARY( face ); FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); @@ -625,17 +630,17 @@ if ( service && service->get_ps_font_name ) - return service->get_ps_font_name( FT_FACE( face ) ); + return service->get_ps_font_name( face ); } - return (const char*)cff->font_name; + return cff ? (const char*)cff->font_name : NULL; } FT_DEFINE_SERVICE_PSFONTNAMEREC( cff_service_ps_name, - (FT_PsName_GetFunc)cff_get_ps_name /* get_ps_font_name */ + cff_get_ps_name /* FT_PsName_GetFunc get_ps_font_name */ ) @@ -649,7 +654,7 @@ * Otherwise call the service function in the sfnt module. * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) cff_get_cmap_info( FT_CharMap charmap, TT_CMapInfo *cmap_info ) { @@ -683,7 +688,7 @@ FT_DEFINE_SERVICE_TTCMAPSREC( cff_service_get_cmap_info, - (TT_CMap_Info_GetFunc)cff_get_cmap_info /* get_cmap_info */ + cff_get_cmap_info /* TT_CMap_Info_GetFunc get_cmap_info */ ) @@ -691,14 +696,15 @@ * CID INFO SERVICE * */ - static FT_Error - cff_get_ros( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_ros( FT_Face face, /* FT_Face */ const char* *registry, const char* *ordering, FT_Int *supplement ) { - FT_Error error = FT_Err_Ok; - CFF_Font cff = (CFF_Font)face->extra.data; + FT_Error error = FT_Err_Ok; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; if ( cff ) @@ -748,12 +754,13 @@ } - static FT_Error - cff_get_is_cid( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_is_cid( FT_Face face, /* CFF_Face */ FT_Bool *is_cid ) { - FT_Error error = FT_Err_Ok; - CFF_Font cff = (CFF_Font)face->extra.data; + FT_Error error = FT_Err_Ok; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; *is_cid = 0; @@ -771,17 +778,16 @@ } - static FT_Error - cff_get_cid_from_glyph_index( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_cid_from_glyph_index( FT_Face face, /* CFF_Face */ FT_UInt glyph_index, FT_UInt *cid ) { - FT_Error error = FT_Err_Ok; - CFF_Font cff; + FT_Error error = FT_Err_Ok; + CFF_Face cffface = (CFF_Face)face; + CFF_Font cff = (CFF_Font)cffface->extra.data; - cff = (CFF_Font)face->extra.data; - if ( cff ) { FT_UInt c; @@ -814,12 +820,12 @@ FT_DEFINE_SERVICE_CIDREC( cff_service_cid_info, - (FT_CID_GetRegistryOrderingSupplementFunc) - cff_get_ros, /* get_ros */ - (FT_CID_GetIsInternallyCIDKeyedFunc) - cff_get_is_cid, /* get_is_cid */ - (FT_CID_GetCIDFromGlyphIndexFunc) - cff_get_cid_from_glyph_index /* get_cid_from_glyph_index */ + cff_get_ros, + /* FT_CID_GetRegistryOrderingSupplementFunc get_ros */ + cff_get_is_cid, + /* FT_CID_GetIsInternallyCIDKeyedFunc get_is_cid */ + cff_get_cid_from_glyph_index + /* FT_CID_GetCIDFromGlyphIndexFunc get_cid_from_glyph_index */ ) @@ -831,9 +837,9 @@ FT_DEFINE_SERVICE_PROPERTIESREC( cff_service_properties, - (FT_Properties_SetFunc)ps_property_set, /* set_property */ - (FT_Properties_GetFunc)ps_property_get ) /* get_property */ - + ps_property_set, /* FT_Properties_SetFunc set_property */ + ps_property_get /* FT_Properties_GetFunc get_property */ + ) #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT @@ -842,116 +848,231 @@ * */ - static FT_Error - cff_set_mm_blend( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_set_mm_blend( FT_Face face, /* CFF_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->set_mm_blend( FT_FACE( face ), num_coords, coords ); + return mm->set_mm_blend( face, num_coords, coords ); } - static FT_Error - cff_get_mm_blend( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_mm_blend( FT_Face face, /* CFF_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_mm_blend( FT_FACE( face ), num_coords, coords ); + return mm->get_mm_blend( face, num_coords, coords ); } - static FT_Error - cff_set_mm_weightvector( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_set_mm_weightvector( FT_Face face, /* CFF_Face */ FT_UInt len, FT_Fixed* weightvector ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->set_mm_weightvector( FT_FACE( face ), len, weightvector ); + return mm->set_mm_weightvector( face, len, weightvector ); } - static FT_Error - cff_get_mm_weightvector( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_mm_weightvector( FT_Face face, /* CFF_Face */ FT_UInt* len, FT_Fixed* weightvector ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_mm_weightvector( FT_FACE( face ), len, weightvector ); + return mm->get_mm_weightvector( face, len, weightvector ); } - static FT_Error - cff_get_mm_var( CFF_Face face, + FT_CALLBACK_DEF( void ) + cff_construct_ps_name( FT_Face face ) /* CFF_Face */ + { + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; + + + mm->construct_ps_name( face ); + } + + + FT_CALLBACK_DEF( FT_Error ) + cff_get_mm_var( FT_Face face, /* CFF_Face */ FT_MM_Var* *master ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_mm_var( FT_FACE( face ), master ); + return mm->get_mm_var( face, master ); } - static FT_Error - cff_set_var_design( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_set_var_design( FT_Face face, /* CFF_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->set_var_design( FT_FACE( face ), num_coords, coords ); + return mm->set_var_design( face, num_coords, coords ); } - static FT_Error - cff_get_var_design( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_get_var_design( FT_Face face, /* CFF_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_var_design( FT_FACE( face ), num_coords, coords ); + return mm->get_var_design( face, num_coords, coords ); } - static FT_Error - cff_set_instance( CFF_Face face, - FT_UInt instance_index ) + FT_CALLBACK_DEF( FT_Error ) + cff_set_named_instance( FT_Face face, /* CFF_Face */ + FT_UInt instance_index ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->set_instance( FT_FACE( face ), instance_index ); + return mm->set_named_instance( face, instance_index ); } + FT_CALLBACK_DEF( FT_Error ) + cff_get_default_named_instance( FT_Face face, /* CFF_Face */ + FT_UInt *instance_index ) + { + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; + + + return mm->get_default_named_instance( face, instance_index ); + } + + + FT_CALLBACK_DEF( FT_Error ) + cff_load_item_variation_store( FT_Face face, /* CFF_Face */ + FT_ULong offset, + GX_ItemVarStore itemStore ) + { + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; + + + return mm->load_item_var_store( face, offset, itemStore ); + } + + + FT_CALLBACK_DEF( FT_Error ) + cff_load_delta_set_index_mapping( FT_Face face, /* CFF_Face */ + FT_ULong offset, + GX_DeltaSetIdxMap map, + GX_ItemVarStore itemStore, + FT_ULong table_len ) + { + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; + + + return mm->load_delta_set_idx_map( face, offset, map, + itemStore, table_len ); + } + + + FT_CALLBACK_DEF( FT_Int ) + cff_get_item_delta( FT_Face face, /* CFF_Face */ + GX_ItemVarStore itemStore, + FT_UInt outerIndex, + FT_UInt innerIndex ) + { + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; + + + return mm->get_item_delta( face, itemStore, outerIndex, innerIndex ); + } + + + FT_CALLBACK_DEF( void ) + cff_done_item_variation_store( FT_Face face, /* CFF_Face */ + GX_ItemVarStore itemStore ) + { + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; + + + mm->done_item_var_store( face, itemStore ); + } + + + FT_CALLBACK_DEF( void ) + cff_done_delta_set_index_map( FT_Face face, /* CFF_Face */ + GX_DeltaSetIdxMap deltaSetIdxMap ) + { + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; + + + mm->done_delta_set_idx_map( face, deltaSetIdxMap ); + } + + + FT_DEFINE_SERVICE_MULTIMASTERSREC( cff_service_multi_masters, - (FT_Get_MM_Func) NULL, /* get_mm */ - (FT_Set_MM_Design_Func) NULL, /* set_mm_design */ - (FT_Set_MM_Blend_Func) cff_set_mm_blend, /* set_mm_blend */ - (FT_Get_MM_Blend_Func) cff_get_mm_blend, /* get_mm_blend */ - (FT_Get_MM_Var_Func) cff_get_mm_var, /* get_mm_var */ - (FT_Set_Var_Design_Func) cff_set_var_design, /* set_var_design */ - (FT_Get_Var_Design_Func) cff_get_var_design, /* get_var_design */ - (FT_Set_Instance_Func) cff_set_instance, /* set_instance */ - (FT_Set_MM_WeightVector_Func)cff_set_mm_weightvector, /* set_mm_weightvector */ - (FT_Get_MM_WeightVector_Func)cff_get_mm_weightvector, /* get_mm_weightvector */ - - (FT_Get_Var_Blend_Func) cff_get_var_blend, /* get_var_blend */ - (FT_Done_Blend_Func) cff_done_blend /* done_blend */ + NULL, /* FT_Get_MM_Func get_mm */ + NULL, /* FT_Set_MM_Design_Func set_mm_design */ + cff_set_mm_blend, /* FT_Set_MM_Blend_Func set_mm_blend */ + cff_get_mm_blend, /* FT_Get_MM_Blend_Func get_mm_blend */ + cff_get_mm_var, /* FT_Get_MM_Var_Func get_mm_var */ + cff_set_var_design, /* FT_Set_Var_Design_Func set_var_design */ + cff_get_var_design, /* FT_Get_Var_Design_Func get_var_design */ + cff_set_named_instance, + /* FT_Set_Named_Instance_Func set_named_instance */ + cff_get_default_named_instance, + /* FT_Get_Default_Named_Instance_Func get_default_named_instance */ + cff_set_mm_weightvector, + /* FT_Set_MM_WeightVector_Func set_mm_weightvector */ + cff_get_mm_weightvector, + /* FT_Get_MM_WeightVector_Func get_mm_weightvector */ + cff_construct_ps_name, + /* FT_Construct_PS_Name_Func construct_ps_name */ + cff_load_delta_set_index_mapping, + /* FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map */ + cff_load_item_variation_store, + /* FT_Var_Load_Item_Var_Store_Func load_item_variation_store */ + cff_get_item_delta, + /* FT_Var_Get_Item_Delta_Func get_item_delta */ + cff_done_item_variation_store, + /* FT_Var_Done_Item_Var_Store_Func done_item_variation_store */ + cff_done_delta_set_index_map, + /* FT_Var_Done_Delta_Set_Idx_Map_Func done_delta_set_index_map */ + cff_get_var_blend, /* FT_Get_Var_Blend_Func get_var_blend */ + cff_done_blend /* FT_Done_Blend_Func done_blend */ ) @@ -960,41 +1081,46 @@ * */ - static FT_Error - cff_hadvance_adjust( CFF_Face face, + FT_CALLBACK_DEF( FT_Error ) + cff_hadvance_adjust( FT_Face face, /* CFF_Face */ FT_UInt gindex, FT_Int *avalue ) { - FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MetricsVariations + var = (FT_Service_MetricsVariations)cffface->tt_var; - return var->hadvance_adjust( FT_FACE( face ), gindex, avalue ); + return var->hadvance_adjust( face, gindex, avalue ); } - static void - cff_metrics_adjust( CFF_Face face ) + FT_CALLBACK_DEF( void ) + cff_metrics_adjust( FT_Face face ) /* CFF_Face */ { - FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MetricsVariations + var = (FT_Service_MetricsVariations)cffface->tt_var; - var->metrics_adjust( FT_FACE( face ) ); + var->metrics_adjust( face ); } FT_DEFINE_SERVICE_METRICSVARIATIONSREC( cff_service_metrics_variations, - (FT_HAdvance_Adjust_Func)cff_hadvance_adjust, /* hadvance_adjust */ - (FT_LSB_Adjust_Func) NULL, /* lsb_adjust */ - (FT_RSB_Adjust_Func) NULL, /* rsb_adjust */ + cff_hadvance_adjust, /* FT_HAdvance_Adjust_Func hadvance_adjust */ + NULL, /* FT_LSB_Adjust_Func lsb_adjust */ + NULL, /* FT_RSB_Adjust_Func rsb_adjust */ - (FT_VAdvance_Adjust_Func)NULL, /* vadvance_adjust */ - (FT_TSB_Adjust_Func) NULL, /* tsb_adjust */ - (FT_BSB_Adjust_Func) NULL, /* bsb_adjust */ - (FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */ + NULL, /* FT_VAdvance_Adjust_Func vadvance_adjust */ + NULL, /* FT_TSB_Adjust_Func tsb_adjust */ + NULL, /* FT_BSB_Adjust_Func bsb_adjust */ + NULL, /* FT_VOrg_Adjust_Func vorg_adjust */ - (FT_Metrics_Adjust_Func) cff_metrics_adjust /* metrics_adjust */ + cff_metrics_adjust, /* FT_Metrics_Adjust_Func metrics_adjust */ + NULL /* FT_Size_Reset_Func size_reset */ ) #endif @@ -1007,11 +1133,11 @@ FT_DEFINE_SERVICE_CFFLOADREC( cff_service_cff_load, - (FT_Get_Standard_Encoding_Func)cff_get_standard_encoding, - (FT_Load_Private_Dict_Func) cff_load_private_dict, - (FT_FD_Select_Get_Func) cff_fd_select_get, - (FT_Blend_Check_Vector_Func) cff_blend_check_vector, - (FT_Blend_Build_Vector_Func) cff_blend_build_vector + cff_get_standard_encoding, /* FT_Get_Standard_Encoding_Func get_standard_encoding */ + cff_load_private_dict, /* FT_Load_Private_Dict_Func load_private_dict */ + cff_fd_select_get, /* FT_FD_Select_Get_Func fd_select_get */ + cff_blend_check_vector, /* FT_Blend_Check_Vector_Func blend_check_vector */ + cff_blend_build_vector /* FT_Blend_Build_Vector_Func blend_build_vector */ ) @@ -1027,8 +1153,7 @@ /*************************************************************************/ /*************************************************************************/ -#if !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES && \ - defined TT_CONFIG_OPTION_GX_VAR_SUPPORT +#if defined TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_DEFINE_SERVICEDESCREC10( cff_services, @@ -1043,7 +1168,7 @@ FT_SERVICE_ID_PROPERTIES, &cff_service_properties, FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load ) -#elif !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES +#else FT_DEFINE_SERVICEDESCREC8( cff_services, @@ -1056,32 +1181,6 @@ FT_SERVICE_ID_PROPERTIES, &cff_service_properties, FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load ) -#elif defined TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_DEFINE_SERVICEDESCREC9( - cff_services, - - FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, - FT_SERVICE_ID_MULTI_MASTERS, &cff_service_multi_masters, - FT_SERVICE_ID_METRICS_VARIATIONS, &cff_service_metrics_var, - FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info, - FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name, - FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info, - FT_SERVICE_ID_CID, &cff_service_cid_info, - FT_SERVICE_ID_PROPERTIES, &cff_service_properties, - FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load - ) -#else - FT_DEFINE_SERVICEDESCREC7( - cff_services, - - FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, - FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info, - FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name, - FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info, - FT_SERVICE_ID_CID, &cff_service_cid_info, - FT_SERVICE_ID_PROPERTIES, &cff_service_properties, - FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load - ) #endif diff --git a/lib/libesp32_lvgl/freetype/src/cff/cffdrivr.h b/lib/libesp32_lvgl/freetype/src/cff/cffdrivr.h index d198dd35c..ab1f147bb 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/cffdrivr.h +++ b/lib/libesp32_lvgl/freetype/src/cff/cffdrivr.h @@ -4,7 +4,7 @@ * * High-level OpenType driver interface (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cff/cfferrs.h b/lib/libesp32_lvgl/freetype/src/cff/cfferrs.h index 5b00a3f0a..bc9a3043f 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/cfferrs.h +++ b/lib/libesp32_lvgl/freetype/src/cff/cfferrs.h @@ -4,7 +4,7 @@ * * CFF error codes (specification only). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cff/cffgload.c b/lib/libesp32_lvgl/freetype/src/cff/cffgload.c index feee38a41..c483d1d1a 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/cffgload.c +++ b/lib/libesp32_lvgl/freetype/src/cff/cffgload.c @@ -4,7 +4,7 @@ * * OpenType Glyph Loader (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -29,6 +29,14 @@ #include "cfferrs.h" +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#define IS_DEFAULT_INSTANCE( _face ) \ + ( !( FT_IS_NAMED_INSTANCE( _face ) || \ + FT_IS_VARIATION( _face ) ) ) +#else +#define IS_DEFAULT_INSTANCE( _face ) 1 +#endif + /************************************************************************** * @@ -59,7 +67,7 @@ *pointer = (FT_Byte*)data.pointer; - *length = (FT_ULong)data.length; + *length = data.length; return error; } @@ -67,7 +75,7 @@ #endif /* FT_CONFIG_OPTION_INCREMENTAL */ { - CFF_Font cff = (CFF_Font)(face->extra.data); + CFF_Font cff = (CFF_Font)( face->extra.data ); return cff_index_access_element( &cff->charstrings_index, glyph_index, @@ -94,7 +102,7 @@ data.pointer = *pointer; - data.length = (FT_Int)length; + data.length = (FT_UInt)length; face->root.internal->incremental_interface->funcs->free_glyph_data( face->root.internal->incremental_interface->object, &data ); @@ -103,7 +111,7 @@ #endif /* FT_CONFIG_OPTION_INCREMENTAL */ { - CFF_Font cff = (CFF_Font)(face->extra.data); + CFF_Font cff = (CFF_Font)( face->extra.data ); cff_index_forget_element( &cff->charstrings_index, pointer ); @@ -255,8 +263,8 @@ if ( size->strike_index != 0xFFFFFFFFUL && - sfnt->load_eblc && - ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) + ( load_flags & FT_LOAD_NO_BITMAP ) == 0 && + IS_DEFAULT_INSTANCE( size->root.face ) ) { TT_SBit_MetricsRec metrics; @@ -346,6 +354,75 @@ if ( load_flags & FT_LOAD_SBITS_ONLY ) return FT_THROW( Invalid_Argument ); +#ifdef FT_CONFIG_OPTION_SVG + /* check for OT-SVG */ + if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 && + ( load_flags & FT_LOAD_COLOR ) && + face->svg ) + { + /* + * We load the SVG document and try to grab the advances from the + * table. For the bearings we rely on the presetting hook to do that. + */ + + SFNT_Service sfnt = (SFNT_Service)face->sfnt; + + + if ( size && (size->root.metrics.x_ppem < 1 || + size->root.metrics.y_ppem < 1 ) ) + { + error = FT_THROW( Invalid_Size_Handle ); + return error; + } + + FT_TRACE3(( "Trying to load SVG glyph\n" )); + + error = sfnt->load_svg_doc( (FT_GlyphSlot)glyph, glyph_index ); + if ( !error ) + { + FT_Fixed x_scale = size->root.metrics.x_scale; + FT_Fixed y_scale = size->root.metrics.y_scale; + + FT_Short dummy; + FT_UShort advanceX; + FT_UShort advanceY; + + + FT_TRACE3(( "Successfully loaded SVG glyph\n" )); + + glyph->root.format = FT_GLYPH_FORMAT_SVG; + + /* + * If horizontal or vertical advances are not present in the table, + * this is a problem with the font since the standard requires them. + * However, we are graceful and calculate the values by ourselves + * for the vertical case. + */ + sfnt->get_metrics( face, + FALSE, + glyph_index, + &dummy, + &advanceX ); + sfnt->get_metrics( face, + TRUE, + glyph_index, + &dummy, + &advanceY ); + + glyph->root.linearHoriAdvance = advanceX; + glyph->root.linearVertAdvance = advanceY; + + glyph->root.metrics.horiAdvance = FT_MulFix( advanceX, x_scale ); + glyph->root.metrics.vertAdvance = FT_MulFix( advanceY, y_scale ); + + return error; + } + + FT_TRACE3(( "Failed to load SVG glyph\n" )); + } + +#endif /* FT_CONFIG_OPTION_SVG */ + /* if we have a CID subfont, use its matrix (which has already */ /* been multiplied with the root matrix) */ @@ -413,13 +490,14 @@ decoder.builder.no_recurse = FT_BOOL( load_flags & FT_LOAD_NO_RECURSE ); - /* now load the unscaled outline */ - error = cff_get_glyph_data( face, glyph_index, - &charstring, &charstring_len ); + /* this function also checks for a valid subfont index */ + error = decoder_funcs->prepare( &decoder, size, glyph_index ); if ( error ) goto Glyph_Build_Finished; - error = decoder_funcs->prepare( &decoder, size, glyph_index ); + /* now load the unscaled outline */ + error = cff_get_glyph_data( face, glyph_index, + &charstring, &charstring_len ); if ( error ) goto Glyph_Build_Finished; diff --git a/lib/libesp32_lvgl/freetype/src/cff/cffgload.h b/lib/libesp32_lvgl/freetype/src/cff/cffgload.h index 3b312f452..3b8cf236d 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/cffgload.h +++ b/lib/libesp32_lvgl/freetype/src/cff/cffgload.h @@ -4,7 +4,7 @@ * * OpenType Glyph Loader (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cff/cffload.c b/lib/libesp32_lvgl/freetype/src/cff/cffload.c index 73d3eecd3..af79082e9 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/cffload.c +++ b/lib/libesp32_lvgl/freetype/src/cff/cffload.c @@ -4,7 +4,7 @@ * * OpenType and CFF data/program tables loader (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -356,9 +356,9 @@ data_size = (FT_ULong)( idx->count + 1 ) * offsize; - if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) || - FT_STREAM_SEEK( idx->start + idx->hdr_size ) || - FT_FRAME_ENTER( data_size ) ) + if ( FT_QNEW_ARRAY( idx->offsets, idx->count + 1 ) || + FT_STREAM_SEEK( idx->start + idx->hdr_size ) || + FT_FRAME_ENTER( data_size ) ) goto Exit; poff = idx->offsets; @@ -400,7 +400,7 @@ /* Allocate a table containing pointers to an index's elements. */ /* The `pool' argument makes this function convert the index */ - /* entries to C-style strings (this is, NULL-terminated). */ + /* entries to C-style strings (that is, null-terminated). */ static FT_Error cff_index_get_pointers( CFF_Index idx, FT_Byte*** table, @@ -427,7 +427,7 @@ new_size = idx->data_size + idx->count; if ( idx->count > 0 && - !FT_NEW_ARRAY( tbl, idx->count + 1 ) && + !FT_QNEW_ARRAY( tbl, idx->count + 1 ) && ( !pool || !FT_ALLOC( new_bytes, new_size ) ) ) { FT_ULong n, cur_offset; @@ -622,7 +622,7 @@ FT_Byte* bytes; FT_ULong byte_len; FT_Error error; - FT_String* name = 0; + FT_String* name = NULL; if ( !idx->stream ) /* CFF2 does not include a name index */ @@ -634,10 +634,9 @@ if ( error ) goto Exit; - if ( !FT_ALLOC( name, byte_len + 1 ) ) + if ( !FT_QALLOC( name, byte_len + 1 ) ) { - if ( byte_len ) - FT_MEM_COPY( name, bytes, byte_len ); + FT_MEM_COPY( name, bytes, byte_len ); name[byte_len] = 0; } cff_index_forget_element( idx, &bytes ); @@ -772,8 +771,7 @@ case 3: /* first, compare to the cache */ - if ( (FT_UInt)( glyph_index - fdselect->cache_first ) < - fdselect->cache_count ) + if ( glyph_index - fdselect->cache_first < fdselect->cache_count ) { fd = fdselect->cache_fd; break; @@ -836,7 +834,6 @@ { FT_Error error = FT_Err_Ok; FT_UInt i; - FT_Long j; FT_UShort max_cid = 0; @@ -854,9 +851,10 @@ /* When multiple GIDs map to the same CID, we choose the lowest */ /* GID. This is not described in any spec, but it matches the */ - /* behaviour of recent Acroread versions. */ - for ( j = (FT_Long)num_glyphs - 1; j >= 0; j-- ) - charset->cids[charset->sids[j]] = (FT_UShort)j; + /* behaviour of recent Acroread versions. The loop stops when */ + /* the unsigned index wraps around after reaching zero. */ + for ( i = num_glyphs - 1; i < num_glyphs; i-- ) + charset->cids[charset->sids[i]] = (FT_UShort)i; charset->max_cid = max_cid; charset->num_glyphs = num_glyphs; @@ -932,7 +930,7 @@ goto Exit; /* Allocate memory for sids. */ - if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) + if ( FT_QNEW_ARRAY( charset->sids, num_glyphs ) ) goto Exit; /* assign the .notdef glyph */ @@ -1018,14 +1016,14 @@ case 0: if ( num_glyphs > 229 ) { - FT_ERROR(( "cff_charset_load: implicit charset larger than\n" - "predefined charset (Adobe ISO-Latin)\n" )); + FT_ERROR(( "cff_charset_load: implicit charset larger than\n" )); + FT_ERROR(( "predefined charset (Adobe ISO-Latin)\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } /* Allocate memory for sids. */ - if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) + if ( FT_QNEW_ARRAY( charset->sids, num_glyphs ) ) goto Exit; /* Copy the predefined charset into the allocated memory. */ @@ -1036,14 +1034,14 @@ case 1: if ( num_glyphs > 166 ) { - FT_ERROR(( "cff_charset_load: implicit charset larger than\n" - "predefined charset (Adobe Expert)\n" )); + FT_ERROR(( "cff_charset_load: implicit charset larger than\n" )); + FT_ERROR(( "predefined charset (Adobe Expert)\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } /* Allocate memory for sids. */ - if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) + if ( FT_QNEW_ARRAY( charset->sids, num_glyphs ) ) goto Exit; /* Copy the predefined charset into the allocated memory. */ @@ -1054,14 +1052,14 @@ case 2: if ( num_glyphs > 87 ) { - FT_ERROR(( "cff_charset_load: implicit charset larger than\n" - "predefined charset (Adobe Expert Subset)\n" )); + FT_ERROR(( "cff_charset_load: implicit charset larger than\n" )); + FT_ERROR(( "predefined charset (Adobe Expert Subset)\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } /* Allocate memory for sids. */ - if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) + if ( FT_QNEW_ARRAY( charset->sids, num_glyphs ) ) goto Exit; /* Copy the predefined charset into the allocated memory. */ @@ -1087,7 +1085,6 @@ FT_FREE( charset->cids ); charset->format = 0; charset->offset = 0; - charset->sids = 0; } return error; @@ -1141,6 +1138,8 @@ { FT_UInt vsOffset; FT_UInt format; + FT_UInt dataCount; + FT_UInt regionCount; FT_ULong regionListOffset; @@ -1163,16 +1162,16 @@ } /* read top level fields */ - if ( FT_READ_ULONG( regionListOffset ) || - FT_READ_USHORT( vstore->dataCount ) ) + if ( FT_READ_ULONG( regionListOffset ) || + FT_READ_USHORT( dataCount ) ) goto Exit; /* make temporary copy of item variation data offsets; */ /* we'll parse region list first, then come back */ - if ( FT_NEW_ARRAY( dataOffsetArray, vstore->dataCount ) ) + if ( FT_QNEW_ARRAY( dataOffsetArray, dataCount ) ) goto Exit; - for ( i = 0; i < vstore->dataCount; i++ ) + for ( i = 0; i < dataCount; i++ ) { if ( FT_READ_ULONG( dataOffsetArray[i] ) ) goto Exit; @@ -1181,20 +1180,24 @@ /* parse regionList and axisLists */ if ( FT_STREAM_SEEK( vsOffset + regionListOffset ) || FT_READ_USHORT( vstore->axisCount ) || - FT_READ_USHORT( vstore->regionCount ) ) + FT_READ_USHORT( regionCount ) ) goto Exit; - if ( FT_NEW_ARRAY( vstore->varRegionList, vstore->regionCount ) ) + vstore->regionCount = 0; + if ( FT_QNEW_ARRAY( vstore->varRegionList, regionCount ) ) goto Exit; - for ( i = 0; i < vstore->regionCount; i++ ) + for ( i = 0; i < regionCount; i++ ) { CFF_VarRegion* region = &vstore->varRegionList[i]; - if ( FT_NEW_ARRAY( region->axisList, vstore->axisCount ) ) + if ( FT_QNEW_ARRAY( region->axisList, vstore->axisCount ) ) goto Exit; + /* keep track of how many axisList to deallocate on error */ + vstore->regionCount++; + for ( j = 0; j < vstore->axisCount; j++ ) { CFF_AxisCoords* axis = ®ion->axisList[j]; @@ -1214,10 +1217,11 @@ } /* use dataOffsetArray now to parse varData items */ - if ( FT_NEW_ARRAY( vstore->varData, vstore->dataCount ) ) + vstore->dataCount = 0; + if ( FT_QNEW_ARRAY( vstore->varData, dataCount ) ) goto Exit; - for ( i = 0; i < vstore->dataCount; i++ ) + for ( i = 0; i < dataCount; i++ ) { CFF_VarData* data = &vstore->varData[i]; @@ -1236,9 +1240,12 @@ if ( FT_READ_USHORT( data->regionIdxCount ) ) goto Exit; - if ( FT_NEW_ARRAY( data->regionIndices, data->regionIdxCount ) ) + if ( FT_QNEW_ARRAY( data->regionIndices, data->regionIdxCount ) ) goto Exit; + /* keep track of how many regionIndices to deallocate on error */ + vstore->dataCount++; + for ( j = 0; j < data->regionIdxCount; j++ ) { if ( FT_READ_USHORT( data->regionIndices[j] ) ) @@ -1281,7 +1288,7 @@ /* Blended values are written to a different buffer, */ /* using reserved operator 255. */ /* */ - /* Blend calculation is done in 16.16 fixed point. */ + /* Blend calculation is done in 16.16 fixed-point. */ FT_LOCAL_DEF( FT_Error ) cff_blend_doBlend( CFF_SubFont subFont, CFF_Parser parser, @@ -1322,9 +1329,9 @@ /* increase or allocate `blend_stack' and reset `blend_top'; */ /* prepare to append `numBlends' values to the buffer */ - if ( FT_REALLOC( subFont->blend_stack, - subFont->blend_alloc, - subFont->blend_alloc + size ) ) + if ( FT_QREALLOC( subFont->blend_stack, + subFont->blend_alloc, + subFont->blend_alloc + size ) ) goto Exit; subFont->blend_top = subFont->blend_stack + subFont->blend_used; @@ -1354,19 +1361,20 @@ for ( i = 0; i < numBlends; i++ ) { const FT_Int32* weight = &blend->BV[1]; - FT_UInt32 sum; + FT_Fixed sum; /* convert inputs to 16.16 fixed point */ - sum = cff_parse_num( parser, &parser->stack[i + base] ) * 0x10000; + sum = cff_parse_fixed( parser, &parser->stack[i + base] ); for ( j = 1; j < blend->lenBV; j++ ) - sum += cff_parse_num( parser, &parser->stack[delta++] ) * *weight++; + sum += FT_MulFix( cff_parse_fixed( parser, &parser->stack[delta++] ), + *weight++ ); /* point parser stack to new value on blend_stack */ parser->stack[i + base] = subFont->blend_top; - /* Push blended result as Type 2 5-byte fixed point number. This */ + /* Push blended result as Type 2 5-byte fixed-point number. This */ /* will not conflict with actual DICTs because 255 is a reserved */ /* opcode in both CFF and CFF2 DICTs. See `cff_parse_num' for */ /* decode of this, which rounds to an integer. */ @@ -1437,9 +1445,7 @@ /* prepare buffer for the blend vector */ len = varData->regionIdxCount + 1; /* add 1 for default component */ - if ( FT_REALLOC( blend->BV, - blend->lenBV * sizeof( *blend->BV ), - len * sizeof( *blend->BV ) ) ) + if ( FT_QRENEW_ARRAY( blend->BV, blend->lenBV, len ) ) goto Exit; blend->lenBV = len; @@ -1456,10 +1462,8 @@ if ( master == 0 ) { blend->BV[master] = FT_FIXED_ONE; - FT_TRACE4(( " build blend vector len %d\n" - " [ %f ", - len, - blend->BV[master] / 65536.0 )); + FT_TRACE4(( " build blend vector len %d\n", len )); + FT_TRACE4(( " [ %f ", blend->BV[master] / 65536.0 )); continue; } @@ -1543,9 +1547,7 @@ if ( lenNDV != 0 ) { /* user has set a normalized vector */ - if ( FT_REALLOC( blend->lastNDV, - blend->lenNDV * sizeof ( *NDV ), - lenNDV * sizeof ( *NDV ) ) ) + if ( FT_QRENEW_ARRAY( blend->lastNDV, blend->lenNDV, lenNDV ) ) goto Exit; FT_MEM_COPY( blend->lastNDV, @@ -1588,16 +1590,17 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_LOCAL_DEF( FT_Error ) - cff_get_var_blend( CFF_Face face, + cff_get_var_blend( FT_Face face, /* CFF_Face */ FT_UInt *num_coords, FT_Fixed* *coords, FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ) { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - return mm->get_var_blend( FT_FACE( face ), + return mm->get_var_blend( face, num_coords, coords, normalizedcoords, @@ -1606,13 +1609,14 @@ FT_LOCAL_DEF( void ) - cff_done_blend( CFF_Face face ) + cff_done_blend( FT_Face face ) /* CFF_Face */ { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + CFF_Face cffface = (CFF_Face)face; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; - if (mm) - mm->done_blend( FT_FACE( face ) ); + if ( mm ) + mm->done_blend( face ); } #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ @@ -1649,13 +1653,6 @@ goto Exit; } - /* Zero out the code to gid/sid mappings. */ - for ( j = 0; j < 256; j++ ) - { - encoding->sids [j] = 0; - encoding->codes[j] = 0; - } - /* Note: The encoding table in a CFF font is indexed by glyph index; */ /* the first encoded glyph index is 1. Hence, we read the character */ /* code (`glyph_code') at index j and make the assignment: */ @@ -1670,6 +1667,10 @@ if ( offset > 1 ) { + /* Zero out the code to gid/sid mappings. */ + FT_ARRAY_ZERO( encoding->sids, 256 ); + FT_ARRAY_ZERO( encoding->codes, 256 ); + encoding->offset = base_offset + offset; /* we need to parse the table to determine its size */ @@ -1827,7 +1828,8 @@ /* Construct code to GID mapping from code to SID mapping */ /* and charset. */ - encoding->count = 0; + encoding->offset = offset; /* used in cff_face_init */ + encoding->count = 0; error = cff_charset_compute_cids( charset, num_glyphs, stream->memory ); @@ -2010,7 +2012,7 @@ /* Top and Font DICTs are not allowed to have blend operators. */ error = cff_parser_init( &parser, code, - &subfont->font_dict, + top, font->library, stackSize, 0, @@ -2363,8 +2365,8 @@ if ( font->name_index.count > 1 ) { FT_ERROR(( "cff_font_load:" - " invalid CFF font with multiple subfonts\n" - " " + " invalid CFF font with multiple subfonts\n" )); + FT_ERROR(( " " " in SFNT wrapper\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; diff --git a/lib/libesp32_lvgl/freetype/src/cff/cffload.h b/lib/libesp32_lvgl/freetype/src/cff/cffload.h index fc998db2d..b5286b0c8 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/cffload.h +++ b/lib/libesp32_lvgl/freetype/src/cff/cffload.h @@ -4,7 +4,7 @@ * * OpenType & CFF data/program tables loader (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -105,14 +105,14 @@ FT_BEGIN_HEADER #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_LOCAL( FT_Error ) - cff_get_var_blend( CFF_Face face, + cff_get_var_blend( FT_Face face, FT_UInt *num_coords, FT_Fixed* *coords, FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ); FT_LOCAL( void ) - cff_done_blend( CFF_Face face ); + cff_done_blend( FT_Face face ); #endif diff --git a/lib/libesp32_lvgl/freetype/src/cff/cffobjs.c b/lib/libesp32_lvgl/freetype/src/cff/cffobjs.c index d555d5235..6d08620c4 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/cffobjs.c +++ b/lib/libesp32_lvgl/freetype/src/cff/cffobjs.c @@ -4,7 +4,7 @@ * * OpenType objects manager (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -69,8 +69,8 @@ FT_Module module; - module = FT_Get_Module( size->root.face->driver->root.library, - "pshinter" ); + module = FT_Get_Module( font->library, "pshinter" ); + return ( module && pshinter && pshinter->get_globals_funcs ) ? pshinter->get_globals_funcs( module ) : 0; @@ -182,8 +182,7 @@ goto Exit; cff_make_private_dict( &font->top_font, &priv ); - error = funcs->create( cffsize->face->memory, &priv, - &internal->topfont ); + error = funcs->create( memory, &priv, &internal->topfont ); if ( error ) goto Exit; @@ -193,8 +192,7 @@ cff_make_private_dict( sub, &priv ); - error = funcs->create( cffsize->face->memory, &priv, - &internal->subfonts[i - 1] ); + error = funcs->create( memory, &priv, &internal->subfonts[i - 1] ); if ( error ) goto Exit; } @@ -283,6 +281,8 @@ cff_size_request( FT_Size size, FT_Size_Request req ) { + FT_Error error; + CFF_Size cffsize = (CFF_Size)size; PSH_Globals_Funcs funcs; @@ -304,7 +304,9 @@ #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - FT_Request_Metrics( size->face, req ); + error = FT_Request_Metrics( size->face, req ); + if ( error ) + goto Exit; funcs = cff_size_get_globals_funcs( cffsize ); @@ -345,7 +347,8 @@ } } - return FT_Err_Ok; + Exit: + return error; } @@ -376,8 +379,7 @@ FT_Module module; - module = FT_Get_Module( slot->face->driver->root.library, - "pshinter" ); + module = FT_Get_Module( slot->library, "pshinter" ); if ( module ) { T2_Hints_Funcs funcs; @@ -406,9 +408,7 @@ FT_String* result; - (void)FT_STRDUP( result, source ); - - FT_UNUSED( error ); + FT_MEM_STRDUP( result, source ); return result; } @@ -659,8 +659,8 @@ if ( dict->cid_registry == 0xFFFFU && !psnames ) { FT_ERROR(( "cff_face_init:" - " cannot open CFF & CEF fonts\n" - " " + " cannot open CFF & CEF fonts\n" )); + FT_ERROR(( " " " without the `psnames' module\n" )); error = FT_THROW( Missing_Module ); goto Exit; @@ -684,13 +684,13 @@ /* In Multiple Master CFFs, two SIDs hold the Normalize Design */ /* Vector (NDV) and Convert Design Vector (CDV) charstrings, */ - /* which may contain NULL bytes in the middle of the data, too. */ + /* which may contain null bytes in the middle of the data, too. */ /* We thus access `cff->strings' directly. */ for ( idx = 1; idx < cff->num_strings; idx++ ) { FT_Byte* s1 = cff->strings[idx - 1]; FT_Byte* s2 = cff->strings[idx]; - FT_PtrDist s1len = s2 - s1 - 1; /* without the final NULL byte */ + FT_PtrDist s1len = s2 - s1 - 1; /* without the final null byte */ FT_PtrDist l; @@ -719,22 +719,15 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; - FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; - FT_UInt instance_index = (FT_UInt)face_index >> 16; if ( FT_HAS_MULTIPLE_MASTERS( cffface ) && - mm && instance_index > 0 ) { - error = mm->set_instance( cffface, instance_index ); + error = FT_Set_Named_Instance( cffface, instance_index ); if ( error ) goto Exit; - - if ( var ) - var->metrics_adjust( cffface ); } } #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ @@ -1028,12 +1021,10 @@ cffface->style_flags = flags; } -#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES /* CID-keyed CFF or CFF2 fonts don't have glyph names -- the SFNT */ /* loader has unset this flag because of the 3.0 `post' table. */ if ( dict->cid_registry == 0xFFFFU && !cff2 ) cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; -#endif if ( dict->cid_registry != 0xFFFFU && pure_cff ) cffface->face_flags |= FT_FACE_FLAG_CID_KEYED; @@ -1049,11 +1040,11 @@ { FT_CharMapRec cmaprec; FT_CharMap cmap; - FT_UInt nn; + FT_Int nn; CFF_Encoding encoding = &cff->encoding; - for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ ) + for ( nn = 0; nn < cffface->num_charmaps; nn++ ) { cmap = cffface->charmaps[nn]; @@ -1078,7 +1069,7 @@ cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; cmaprec.encoding = FT_ENCODING_UNICODE; - nn = (FT_UInt)cffface->num_charmaps; + nn = cffface->num_charmaps; error = FT_CMap_New( &cff_cmap_unicode_class_rec, NULL, &cmaprec, NULL ); @@ -1089,7 +1080,7 @@ error = FT_Err_Ok; /* if no Unicode charmap was previously selected, select this one */ - if ( !cffface->charmap && nn != (FT_UInt)cffface->num_charmaps ) + if ( !cffface->charmap && nn != cffface->num_charmaps ) cffface->charmap = cffface->charmaps[nn]; Skip_Unicode: @@ -1159,7 +1150,7 @@ } #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - cff_done_blend( face ); + cff_done_blend( cffface ); face->blend = NULL; #endif } @@ -1174,11 +1165,7 @@ /* set default property values, cf. `ftcffdrv.h' */ -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - driver->hinting_engine = FT_HINTING_FREETYPE; -#else driver->hinting_engine = FT_HINTING_ADOBE; -#endif driver->no_stem_darkening = TRUE; diff --git a/lib/libesp32_lvgl/freetype/src/cff/cffobjs.h b/lib/libesp32_lvgl/freetype/src/cff/cffobjs.h index 845bd9094..8f05f6132 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/cffobjs.h +++ b/lib/libesp32_lvgl/freetype/src/cff/cffobjs.h @@ -4,7 +4,7 @@ * * OpenType objects manager (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cff/cffparse.c b/lib/libesp32_lvgl/freetype/src/cff/cffparse.c index 69bcd5d95..3b076704c 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/cffparse.c +++ b/lib/libesp32_lvgl/freetype/src/cff/cffparse.c @@ -4,7 +4,7 @@ * * CFF token stream parser (body) * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -62,11 +62,8 @@ parser->num_axes = num_axes; /* allocate the stack buffer */ - if ( FT_NEW_ARRAY( parser->stack, stackSize ) ) - { - FT_FREE( parser->stack ); + if ( FT_QNEW_ARRAY( parser->stack, stackSize ) ) goto Exit; - } parser->stackSize = stackSize; parser->top = parser->stack; /* empty stack */ @@ -76,23 +73,6 @@ } -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - static void - finalize_t2_strings( FT_Memory memory, - void* data, - void* user ) - { - CFF_T2_String t2 = (CFF_T2_String)data; - - - FT_UNUSED( user ); - - memory->free( memory, t2->start ); - memory->free( memory, data ); - } -#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ - - FT_LOCAL_DEF( void ) cff_parser_done( CFF_Parser parser ) { @@ -102,63 +82,19 @@ FT_FREE( parser->stack ); #ifdef CFF_CONFIG_OPTION_OLD_ENGINE - FT_List_Finalize( &parser->t2_strings, - finalize_t2_strings, - memory, - NULL ); + FT_List_Finalize( &parser->t2_strings, NULL, memory, NULL ); #endif } - /* Assuming `first >= last'. */ - - static FT_Error - cff_parser_within_limits( CFF_Parser parser, - FT_Byte* first, - FT_Byte* last ) - { -#ifndef CFF_CONFIG_OPTION_OLD_ENGINE - - /* Fast path for regular FreeType builds with the "new" engine; */ - /* `first >= parser->start' can be assumed. */ - - FT_UNUSED( first ); - - return last < parser->limit ? FT_Err_Ok : FT_THROW( Invalid_Argument ); - -#else /* CFF_CONFIG_OPTION_OLD_ENGINE */ - - FT_ListNode node; - - - if ( first >= parser->start && - last < parser->limit ) - return FT_Err_Ok; - - node = parser->t2_strings.head; - - while ( node ) - { - CFF_T2_String t2 = (CFF_T2_String)node->data; - - - if ( first >= t2->start && - last < t2->limit ) - return FT_Err_Ok; - - node = node->next; - } - - return FT_THROW( Invalid_Argument ); - -#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ - } - + /* The parser limit checks in the next two functions are supposed */ + /* to detect the immediate crossing of the stream boundary. They */ + /* shall not be triggered from the distant t2_strings buffers. */ /* read an integer */ static FT_Long - cff_parse_integer( CFF_Parser parser, - FT_Byte* start ) + cff_parse_integer( FT_Byte* start, + FT_Byte* limit ) { FT_Byte* p = start; FT_Int v = *p++; @@ -167,14 +103,14 @@ if ( v == 28 ) { - if ( cff_parser_within_limits( parser, p, p + 1 ) ) + if ( p + 2 > limit && limit >= p ) goto Bad; val = (FT_Short)( ( (FT_UShort)p[0] << 8 ) | p[1] ); } else if ( v == 29 ) { - if ( cff_parser_within_limits( parser, p, p + 3 ) ) + if ( p + 4 > limit && limit >= p ) goto Bad; val = (FT_Long)( ( (FT_ULong)p[0] << 24 ) | @@ -188,14 +124,14 @@ } else if ( v < 251 ) { - if ( cff_parser_within_limits( parser, p, p ) ) + if ( p + 1 > limit && limit >= p ) goto Bad; val = ( v - 247 ) * 256 + p[0] + 108; } else { - if ( cff_parser_within_limits( parser, p, p ) ) + if ( p + 1 > limit && limit >= p ) goto Bad; val = -( v - 251 ) * 256 - p[0] - 108; @@ -244,10 +180,10 @@ /* read a real */ static FT_Fixed - cff_parse_real( CFF_Parser parser, - FT_Byte* start, - FT_Long power_ten, - FT_Long* scaling ) + cff_parse_real( FT_Byte* start, + FT_Byte* limit, + FT_Long power_ten, + FT_Long* scaling ) { FT_Byte* p = start; FT_Int nib; @@ -282,7 +218,7 @@ p++; /* Make sure we don't read past the end. */ - if ( cff_parser_within_limits( parser, p, p ) ) + if ( p + 1 > limit && limit >= p ) goto Bad; } @@ -319,7 +255,7 @@ p++; /* Make sure we don't read past the end. */ - if ( cff_parser_within_limits( parser, p, p ) ) + if ( p + 1 > limit && limit >= p ) goto Bad; } @@ -358,7 +294,7 @@ p++; /* Make sure we don't read past the end. */ - if ( cff_parser_within_limits( parser, p, p ) ) + if ( p + 1 > limit && limit >= p ) goto Bad; } @@ -525,12 +461,12 @@ if ( **d == 30 ) { /* binary-coded decimal is truncated to integer */ - return cff_parse_real( parser, *d, 0, NULL ) >> 16; + return cff_parse_real( *d, parser->limit, 0, NULL ) >> 16; } else if ( **d == 255 ) { - /* 16.16 fixed point is used internally for CFF2 blend results. */ + /* 16.16 fixed-point is used internally for CFF2 blend results. */ /* Since these are trusted values, a limit check is not needed. */ /* After the 255, 4 bytes give the number. */ @@ -551,7 +487,7 @@ } else - return cff_parse_integer( parser, *d ); + return cff_parse_integer( *d, parser->limit ); } @@ -562,15 +498,33 @@ FT_Long scaling ) { if ( **d == 30 ) - return cff_parse_real( parser, *d, scaling, NULL ); - else + return cff_parse_real( *d, parser->limit, scaling, NULL ); + else if ( **d == 255 ) { - FT_Long val = cff_parse_integer( parser, *d ); - + FT_Fixed val = ( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) | + ( (FT_UInt32)*( d[0] + 2 ) << 16 ) | + ( (FT_UInt32)*( d[0] + 3 ) << 8 ) | + (FT_UInt32)*( d[0] + 4 ) ) ); if ( scaling ) { if ( FT_ABS( val ) > power_ten_limits[scaling] ) + { + FT_TRACE4(( "!!!OVERFLOW:!!!" )); + return val > 0 ? 0x7FFFFFFFL : -0x7FFFFFFFL; + } + val *= power_tens[scaling]; + } + return val; + } + else + { + FT_Long val = cff_parse_integer( *d, parser->limit ); + + + if ( scaling ) + { + if ( ( FT_ABS( val ) << 16 ) > power_ten_limits[scaling] ) { val = val > 0 ? 0x7FFFFFFFL : -0x7FFFFFFFL; goto Overflow; @@ -600,7 +554,7 @@ /* read a floating point number, either integer or real */ - static FT_Fixed + FT_LOCAL_DEF( FT_Fixed ) cff_parse_fixed( CFF_Parser parser, FT_Byte** d ) { @@ -630,14 +584,14 @@ FT_ASSERT( scaling ); if ( **d == 30 ) - return cff_parse_real( parser, *d, 0, scaling ); + return cff_parse_real( *d, parser->limit, 0, scaling ); else { FT_Long number; FT_Int integer_length; - number = cff_parse_integer( parser, d[0] ); + number = cff_parse_integer( *d, parser->limit ); if ( number > 0x7FFFL ) { @@ -686,7 +640,7 @@ dict->has_font_matrix = TRUE; - /* We expect a well-formed font matrix, this is, the matrix elements */ + /* We expect a well-formed font matrix, that is, the matrix elements */ /* `xx' and `yy' are of approximately the same magnitude. To avoid */ /* loss of precision, we use the magnitude of the largest matrix */ /* element to scale all other elements. The scaling factor is then */ @@ -713,9 +667,10 @@ ( max_scaling - min_scaling ) > 9 ) { FT_TRACE1(( "cff_parse_font_matrix:" - " strange scaling values (minimum %ld, maximum %ld),\n" - " " - " using default matrix\n", min_scaling, max_scaling )); + " strange scaling values (minimum %ld, maximum %ld),\n", + min_scaling, max_scaling )); + FT_TRACE1(( " " + " using default matrix\n" )); goto Unlikely; } @@ -757,12 +712,12 @@ *upm = (FT_ULong)power_tens[-max_scaling]; FT_TRACE4(( " [%f %f %f %f %f %f]\n", - (double)matrix->xx / *upm / 65536, - (double)matrix->xy / *upm / 65536, - (double)matrix->yx / *upm / 65536, - (double)matrix->yy / *upm / 65536, - (double)offset->x / *upm / 65536, - (double)offset->y / *upm / 65536 )); + (double)matrix->xx / (double)*upm / 65536, + (double)matrix->xy / (double)*upm / 65536, + (double)matrix->yx / (double)*upm / 65536, + (double)matrix->yy / (double)*upm / 65536, + (double)offset->x / (double)*upm / 65536, + (double)offset->y / (double)*upm / 65536 )); if ( !FT_Matrix_Check( matrix ) ) { @@ -1263,11 +1218,8 @@ FT_Byte* charstring_base; FT_ULong charstring_len; - FT_Fixed* stack; - FT_ListNode node; - CFF_T2_String t2; - FT_Fixed t2_size; - FT_Byte* q; + FT_Fixed* stack; + FT_Byte* q = NULL; charstring_base = ++p; @@ -1308,39 +1260,18 @@ /* Now copy the stack data in the temporary decoder object, */ /* converting it back to charstring number representations */ /* (this is ugly, I know). */ + /* The maximum required size is 5 bytes per stack element. */ + if ( FT_QALLOC( q, (FT_Long)( 2 * sizeof ( FT_ListNode ) ) + + 5 * ( decoder.top - decoder.stack ) ) ) + goto Exit; - node = (FT_ListNode)memory->alloc( memory, - sizeof ( FT_ListNodeRec ) ); - if ( !node ) - goto Out_Of_Memory_Error; + FT_List_Add( &parser->t2_strings, (FT_ListNode)q ); - FT_List_Add( &parser->t2_strings, node ); + q += 2 * sizeof ( FT_ListNode ); - t2 = (CFF_T2_String)memory->alloc( memory, - sizeof ( CFF_T2_StringRec ) ); - if ( !t2 ) - goto Out_Of_Memory_Error; - - node->data = t2; - - /* `5' is the conservative upper bound of required bytes per stack */ - /* element. */ - - t2_size = 5 * ( decoder.top - decoder.stack ); - - q = (FT_Byte*)memory->alloc( memory, t2_size ); - if ( !q ) - goto Out_Of_Memory_Error; - - t2->start = q; - t2->limit = q + t2_size; - - stack = decoder.stack; - - while ( stack < decoder.top ) + for ( stack = decoder.stack; stack < decoder.top; stack++ ) { - FT_ULong num; - FT_Bool neg; + FT_Long num = *stack; if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize ) @@ -1348,69 +1279,37 @@ *parser->top++ = q; - if ( *stack < 0 ) - { - num = (FT_ULong)NEG_LONG( *stack ); - neg = 1; - } - else - { - num = (FT_ULong)*stack; - neg = 0; - } - if ( num & 0xFFFFU ) { - if ( neg ) - num = (FT_ULong)-num; - *q++ = 255; - *q++ = ( num & 0xFF000000U ) >> 24; - *q++ = ( num & 0x00FF0000U ) >> 16; - *q++ = ( num & 0x0000FF00U ) >> 8; - *q++ = num & 0x000000FFU; + *q++ = (FT_Byte)( ( num >> 24 ) & 0xFF ); + *q++ = (FT_Byte)( ( num >> 16 ) & 0xFF ); + *q++ = (FT_Byte)( ( num >> 8 ) & 0xFF ); + *q++ = (FT_Byte)( ( num ) & 0xFF ); } else { num >>= 16; - if ( neg ) + if ( -107 <= num && num <= 107 ) + *q++ = (FT_Byte)( num + 139 ); + else if ( 108 <= num && num <= 1131 ) { - if ( num <= 107 ) - *q++ = (FT_Byte)( 139 - num ); - else if ( num <= 1131 ) - { - *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 251 ); - *q++ = (FT_Byte)( ( num - 108 ) & 0xFF ); - } - else - { - num = (FT_ULong)-num; - - *q++ = 28; - *q++ = (FT_Byte)( num >> 8 ); - *q++ = (FT_Byte)( num & 0xFF ); - } + *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 247 ); + *q++ = (FT_Byte)( ( num - 108 ) & 0xFF ); + } + else if ( -1131 <= num && num <= -108 ) + { + *q++ = (FT_Byte)( ( ( -num - 108 ) >> 8 ) + 251 ); + *q++ = (FT_Byte)( ( -num - 108) & 0xFF ); } else { - if ( num <= 107 ) - *q++ = (FT_Byte)( num + 139 ); - else if ( num <= 1131 ) - { - *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 247 ); - *q++ = (FT_Byte)( ( num - 108 ) & 0xFF ); - } - else - { - *q++ = 28; - *q++ = (FT_Byte)( num >> 8 ); - *q++ = (FT_Byte)( num & 0xFF ); - } + *q++ = 28; + *q++ = (FT_Byte)( num >> 8 ); + *q++ = (FT_Byte)( num & 0xFF ); } } - - stack++; } } #endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ @@ -1515,6 +1414,7 @@ case cff_kind_fixed_thousand: FT_TRACE4(( " %f\n", (double)val / 65536 / 1000 )); + break; default: ; /* never reached */ @@ -1596,12 +1496,6 @@ Exit: return error; -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - Out_Of_Memory_Error: - error = FT_THROW( Out_Of_Memory ); - goto Exit; -#endif - Stack_Overflow: error = FT_THROW( Invalid_Argument ); goto Exit; diff --git a/lib/libesp32_lvgl/freetype/src/cff/cffparse.h b/lib/libesp32_lvgl/freetype/src/cff/cffparse.h index 6f3fbb37d..418caacc6 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/cffparse.h +++ b/lib/libesp32_lvgl/freetype/src/cff/cffparse.h @@ -4,7 +4,7 @@ * * CFF token stream parser (specification) * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -76,6 +76,10 @@ FT_BEGIN_HEADER cff_parse_num( CFF_Parser parser, FT_Byte** d ); + FT_LOCAL( FT_Fixed ) + cff_parse_fixed( CFF_Parser parser, + FT_Byte** d ); + FT_LOCAL( FT_Error ) cff_parser_init( CFF_Parser parser, FT_UInt code, @@ -133,15 +137,6 @@ FT_BEGIN_HEADER FT_END_HEADER -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - typedef struct CFF_T2_String_ - { - FT_Byte* start; - FT_Byte* limit; - - } CFF_T2_StringRec, *CFF_T2_String; -#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ - #endif /* CFFPARSE_H_ */ diff --git a/lib/libesp32_lvgl/freetype/src/cff/cfftoken.h b/lib/libesp32_lvgl/freetype/src/cff/cfftoken.h index 4c6a53eec..b61cb0e66 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/cfftoken.h +++ b/lib/libesp32_lvgl/freetype/src/cff/cfftoken.h @@ -4,7 +4,7 @@ * * CFF token definitions (specification only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cff/module.mk b/lib/libesp32_lvgl/freetype/src/cff/module.mk index bd728c6a3..b881d049f 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/module.mk +++ b/lib/libesp32_lvgl/freetype/src/cff/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/cff/rules.mk b/lib/libesp32_lvgl/freetype/src/cff/rules.mk index 70bb92d50..629424adf 100644 --- a/lib/libesp32_lvgl/freetype/src/cff/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/cff/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/cid/ciderrs.h b/lib/libesp32_lvgl/freetype/src/cid/ciderrs.h index f698bb229..40a1097d0 100644 --- a/lib/libesp32_lvgl/freetype/src/cid/ciderrs.h +++ b/lib/libesp32_lvgl/freetype/src/cid/ciderrs.h @@ -4,7 +4,7 @@ * * CID error codes (specification only). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cid/cidgload.c b/lib/libesp32_lvgl/freetype/src/cid/cidgload.c index 54aa62f81..eaca765ad 100644 --- a/lib/libesp32_lvgl/freetype/src/cid/cidgload.c +++ b/lib/libesp32_lvgl/freetype/src/cid/cidgload.c @@ -4,7 +4,7 @@ * * CID-keyed Type1 Glyph Loader (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -40,6 +40,117 @@ #define FT_COMPONENT cidgload + /* + * A helper function to compute FD number (`fd_select`), the offset to the + * head of the glyph data (`off1`), and the offset to the and of the glyph + * data (`off2`). + * + * The number how many times `cid_get_offset` is invoked can be controlled + * by the number of non-NULL arguments. If `fd_select` is non-NULL but + * `off1` and `off2` are NULL, `cid_get_offset` is invoked only for + * `fd_select`; `off1` and `off2` are not validated. + * + */ + FT_LOCAL_DEF( FT_Error ) + cid_compute_fd_and_offsets( CID_Face face, + FT_UInt glyph_index, + FT_ULong* fd_select_p, + FT_ULong* off1_p, + FT_ULong* off2_p ) + { + FT_Error error = FT_Err_Ok; + + CID_FaceInfo cid = &face->cid; + FT_Stream stream = face->cid_stream; + FT_UInt entry_len = cid->fd_bytes + cid->gd_bytes; + + FT_Byte* p; + FT_Bool need_frame_exit = 0; + FT_ULong fd_select, off1, off2; + + + /* For ordinary fonts, read the CID font dictionary index */ + /* and charstring offset from the CIDMap. */ + + if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset + + glyph_index * entry_len ) || + FT_FRAME_ENTER( 2 * entry_len ) ) + goto Exit; + + need_frame_exit = 1; + + p = (FT_Byte*)stream->cursor; + fd_select = cid_get_offset( &p, cid->fd_bytes ); + off1 = cid_get_offset( &p, cid->gd_bytes ); + + p += cid->fd_bytes; + off2 = cid_get_offset( &p, cid->gd_bytes ); + + if ( fd_select_p ) + *fd_select_p = fd_select; + if ( off1_p ) + *off1_p = off1; + if ( off2_p ) + *off2_p = off2; + + if ( fd_select >= cid->num_dicts ) + { + /* + * fd_select == 0xFF is often used to indicate that the CID + * has no charstring to be rendered, similar to GID = 0xFFFF + * in TrueType fonts. + */ + if ( ( cid->fd_bytes == 1 && fd_select == 0xFFU ) || + ( cid->fd_bytes == 2 && fd_select == 0xFFFFU ) ) + { + FT_TRACE1(( "cid_load_glyph: fail for glyph index %d:\n", + glyph_index )); + FT_TRACE1(( " FD number %ld is the maximum\n", + fd_select )); + FT_TRACE1(( " integer fitting into %d byte%s\n", + cid->fd_bytes, cid->fd_bytes == 1 ? "" : "s" )); + } + else + { + FT_TRACE0(( "cid_load_glyph: fail for glyph index %d:\n", + glyph_index )); + FT_TRACE0(( " FD number %ld is larger\n", + fd_select )); + FT_TRACE0(( " than number of dictionaries (%d)\n", + cid->num_dicts )); + } + + error = FT_THROW( Invalid_Offset ); + goto Exit; + } + else if ( off2 > stream->size ) + { + FT_TRACE0(( "cid_load_glyph: fail for glyph index %d:\n", + glyph_index )); + FT_TRACE0(( " end of the glyph data\n" )); + FT_TRACE0(( " is beyond the data stream\n" )); + + error = FT_THROW( Invalid_Offset ); + goto Exit; + } + else if ( off1 > off2 ) + { + FT_TRACE0(( "cid_load_glyph: fail for glyph index %d:\n", + glyph_index )); + FT_TRACE0(( " the end position of glyph data\n" )); + FT_TRACE0(( " is set before the start position\n" )); + + error = FT_THROW( Invalid_Offset ); + } + + Exit: + if ( need_frame_exit ) + FT_FRAME_EXIT(); + + return error; + } + + FT_CALLBACK_DEF( FT_Error ) cid_load_glyph( T1_Decoder decoder, FT_UInt glyph_index ) @@ -63,7 +174,7 @@ #endif - FT_TRACE1(( "cid_load_glyph: glyph index %d\n", glyph_index )); + FT_TRACE1(( "cid_load_glyph: glyph index %u\n", glyph_index )); #ifdef FT_CONFIG_OPTION_INCREMENTAL @@ -76,20 +187,17 @@ error = inc->funcs->get_glyph_data( inc->object, glyph_index, &glyph_data ); - if ( error ) + if ( error || glyph_data.length < cid->fd_bytes ) goto Exit; p = (FT_Byte*)glyph_data.pointer; - fd_select = cid_get_offset( &p, (FT_Byte)cid->fd_bytes ); + fd_select = cid_get_offset( &p, cid->fd_bytes ); - if ( glyph_data.length != 0 ) - { - glyph_length = (FT_ULong)( glyph_data.length - cid->fd_bytes ); - (void)FT_ALLOC( charstring, glyph_length ); - if ( !error ) - ft_memcpy( charstring, glyph_data.pointer + cid->fd_bytes, + glyph_length = glyph_data.length - cid->fd_bytes; + + if ( !FT_QALLOC( charstring, glyph_length ) ) + FT_MEM_COPY( charstring, glyph_data.pointer + cid->fd_bytes, glyph_length ); - } inc->funcs->free_glyph_data( inc->object, &glyph_data ); @@ -100,41 +208,20 @@ else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ - - /* For ordinary fonts read the CID font dictionary index */ - /* and charstring offset from the CIDMap. */ { - FT_UInt entry_len = (FT_UInt)( cid->fd_bytes + cid->gd_bytes ); FT_ULong off1, off2; - if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset + - glyph_index * entry_len ) || - FT_FRAME_ENTER( 2 * entry_len ) ) + error = cid_compute_fd_and_offsets( face, glyph_index, + &fd_select, &off1, &off2 ); + if ( error ) goto Exit; - p = (FT_Byte*)stream->cursor; - fd_select = cid_get_offset( &p, (FT_Byte)cid->fd_bytes ); - off1 = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ); - p += cid->fd_bytes; - off2 = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ); - FT_FRAME_EXIT(); - - if ( fd_select >= (FT_ULong)cid->num_dicts || - off2 > stream->size || - off1 > off2 ) - { - FT_TRACE0(( "cid_load_glyph: invalid glyph stream offsets\n" )); - error = FT_THROW( Invalid_Offset ); - goto Exit; - } - glyph_length = off2 - off1; - if ( glyph_length == 0 ) - goto Exit; - if ( FT_ALLOC( charstring, glyph_length ) ) - goto Exit; - if ( FT_STREAM_READ_AT( cid->data_offset + off1, + + if ( glyph_length == 0 || + FT_QALLOC( charstring, glyph_length ) || + FT_STREAM_READ_AT( cid->data_offset + off1, charstring, glyph_length ) ) goto Exit; } @@ -165,7 +252,9 @@ cs_offset = decoder->lenIV >= 0 ? (FT_UInt)decoder->lenIV : 0; if ( cs_offset > glyph_length ) { - FT_TRACE0(( "cid_load_glyph: invalid glyph stream offsets\n" )); + FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, " + "offset to the charstring is beyond glyph length\n", + glyph_index )); error = FT_THROW( Invalid_Offset ); goto Exit; } diff --git a/lib/libesp32_lvgl/freetype/src/cid/cidgload.h b/lib/libesp32_lvgl/freetype/src/cid/cidgload.h index da36e37e0..edd622923 100644 --- a/lib/libesp32_lvgl/freetype/src/cid/cidgload.h +++ b/lib/libesp32_lvgl/freetype/src/cid/cidgload.h @@ -4,7 +4,7 @@ * * OpenType Glyph Loader (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -42,6 +42,14 @@ FT_BEGIN_HEADER FT_Int32 load_flags ); + FT_LOCAL( FT_Error ) + cid_compute_fd_and_offsets( CID_Face face, + FT_UInt glyph_index, + FT_ULong* fd_select_p, + FT_ULong* off1_p, + FT_ULong* off2_p ); + + FT_END_HEADER #endif /* CIDGLOAD_H_ */ diff --git a/lib/libesp32_lvgl/freetype/src/cid/cidload.c b/lib/libesp32_lvgl/freetype/src/cid/cidload.c index bb9136a3d..a7da8ea39 100644 --- a/lib/libesp32_lvgl/freetype/src/cid/cidload.c +++ b/lib/libesp32_lvgl/freetype/src/cid/cidload.c @@ -4,7 +4,7 @@ * * CID-keyed Type1 font loader (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -41,7 +41,7 @@ /* read a single offset */ FT_LOCAL_DEF( FT_ULong ) cid_get_offset( FT_Byte* *start, - FT_Byte offsize ) + FT_UInt offsize ) { FT_ULong result; FT_Byte* p = *start; @@ -113,7 +113,7 @@ CID_FaceDict dict; - if ( parser->num_dict < 0 || parser->num_dict >= cid->num_dicts ) + if ( parser->num_dict >= cid->num_dicts ) { FT_ERROR(( "cid_load_keyword: invalid use of `%s'\n", keyword->ident )); @@ -155,23 +155,24 @@ FT_CALLBACK_DEF( void ) - cid_parse_font_matrix( CID_Face face, - CID_Parser* parser ) + cid_parse_font_matrix( FT_Face face, /* CID_Face */ + void* parser_ ) { + CID_Face cidface = (CID_Face)face; + CID_Parser* parser = (CID_Parser*)parser_; CID_FaceDict dict; - FT_Face root = (FT_Face)&face->root; FT_Fixed temp[6]; FT_Fixed temp_scale; - if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts ) + if ( parser->num_dict < cidface->cid.num_dicts ) { FT_Matrix* matrix; FT_Vector* offset; FT_Int result; - dict = face->cid.font_dicts + parser->num_dict; + dict = cidface->cid.font_dicts + parser->num_dict; matrix = &dict->font_matrix; offset = &dict->font_offset; @@ -204,7 +205,7 @@ if ( temp_scale != 0x10000L ) { /* set units per EM based on FontMatrix values */ - root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); + face->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); temp[0] = FT_DivFix( temp[0], temp_scale ); temp[1] = FT_DivFix( temp[1], temp_scale ); @@ -237,18 +238,20 @@ FT_CALLBACK_DEF( void ) - parse_fd_array( CID_Face face, - CID_Parser* parser ) + parse_fd_array( FT_Face face, /* CID_Face */ + void* parser_ ) { - CID_FaceInfo cid = &face->cid; - FT_Memory memory = face->root.memory; - FT_Stream stream = parser->stream; - FT_Error error = FT_Err_Ok; - FT_Long num_dicts; + CID_Face cidface = (CID_Face)face; + CID_Parser* parser = (CID_Parser*)parser_; + CID_FaceInfo cid = &cidface->cid; + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Stream stream = parser->stream; + FT_Error error = FT_Err_Ok; + FT_Long num_dicts, max_dicts; num_dicts = cid_parser_to_int( parser ); - if ( num_dicts < 0 ) + if ( num_dicts < 0 || num_dicts > FT_INT_MAX ) { FT_ERROR(( "parse_fd_array: invalid number of dictionaries\n" )); goto Exit; @@ -272,18 +275,18 @@ * need a `dup X' at the very beginning and a `put' at the end, so a * rough guess using 100 bytes as the minimum is justified. */ - if ( (FT_ULong)num_dicts > stream->size / 100 ) + max_dicts = (FT_Long)( stream->size / 100 ); + if ( num_dicts > max_dicts ) { FT_TRACE0(( "parse_fd_array: adjusting FDArray size" " (from %ld to %ld)\n", - num_dicts, - stream->size / 100 )); - num_dicts = (FT_Long)( stream->size / 100 ); + num_dicts, max_dicts )); + num_dicts = max_dicts; } if ( !cid->font_dicts ) { - FT_Int n; + FT_UInt n; if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) ) @@ -313,18 +316,20 @@ /* By mistake, `expansion_factor' appears both in PS_PrivateRec */ /* and CID_FaceDictRec (both are public header files and can't */ - /* changed). We simply copy the value. */ + /* be thus changed). We simply copy the value. */ FT_CALLBACK_DEF( void ) - parse_expansion_factor( CID_Face face, - CID_Parser* parser ) + parse_expansion_factor( FT_Face face, /* CID_Face */ + void* parser_ ) { + CID_Face cidface = (CID_Face)face; + CID_Parser* parser = (CID_Parser*)parser_; CID_FaceDict dict; - if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts ) + if ( parser->num_dict < cidface->cid.num_dicts ) { - dict = face->cid.font_dicts + parser->num_dict; + dict = cidface->cid.font_dicts + parser->num_dict; dict->expansion_factor = cid_parser_to_fixed( parser, 0 ); dict->private_dict.expansion_factor = dict->expansion_factor; @@ -341,11 +346,15 @@ /* to catch it for producing better trace output. */ FT_CALLBACK_DEF( void ) - parse_font_name( CID_Face face, - CID_Parser* parser ) + parse_font_name( FT_Face face, /* CID_Face */ + void* parser_ ) { #ifdef FT_DEBUG_LEVEL_TRACE - if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts ) + CID_Face cidface = (CID_Face)face; + CID_Parser* parser = (CID_Parser*)parser_; + + + if ( parser->num_dict < cidface->cid.num_dicts ) { T1_TokenRec token; FT_UInt len; @@ -361,7 +370,7 @@ } #else FT_UNUSED( face ); - FT_UNUSED( parser ); + FT_UNUSED( parser_ ); #endif return; @@ -427,7 +436,7 @@ parser->num_dict++; #ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE4(( " FontDict %d", parser->num_dict )); + FT_TRACE4(( " FontDict %u", parser->num_dict )); if ( parser->num_dict > face->cid.num_dicts ) FT_TRACE4(( " (ignored)" )); FT_TRACE4(( "\n" )); @@ -517,7 +526,7 @@ FT_Memory memory = face->root.memory; FT_Stream stream = face->cid_stream; FT_Error error; - FT_Int n; + FT_UInt n; CID_Subrs subr; FT_UInt max_offsets = 0; FT_ULong* offsets = NULL; @@ -552,20 +561,20 @@ goto Fail; } - if ( FT_RENEW_ARRAY( offsets, max_offsets, new_max ) ) + if ( FT_QRENEW_ARRAY( offsets, max_offsets, new_max ) ) goto Fail; max_offsets = new_max; } /* read the subrmap's offsets */ - if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) || - FT_FRAME_ENTER( ( num_subrs + 1 ) * (FT_UInt)dict->sd_bytes ) ) + if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) || + FT_FRAME_ENTER( ( num_subrs + 1 ) * dict->sd_bytes ) ) goto Fail; p = (FT_Byte*)stream->cursor; for ( count = 0; count <= num_subrs; count++ ) - offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes ); + offsets[count] = cid_get_offset( &p, dict->sd_bytes ); FT_FRAME_EXIT(); @@ -589,12 +598,12 @@ /* allocate, and read them */ data_len = offsets[num_subrs] - offsets[0]; - if ( FT_NEW_ARRAY( subr->code, num_subrs + 1 ) || - FT_ALLOC( subr->code[0], data_len ) ) + if ( FT_QNEW_ARRAY( subr->code, num_subrs + 1 ) || + FT_QALLOC( subr->code[0], data_len ) ) goto Fail; if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) || - FT_STREAM_READ( subr->code[0], data_len ) ) + FT_STREAM_READ( subr->code[0], data_len ) ) goto Fail; /* set up pointers */ @@ -665,17 +674,18 @@ static FT_Error - cid_hex_to_binary( FT_Byte* data, - FT_ULong data_len, - FT_ULong offset, - CID_Face face ) + cid_hex_to_binary( FT_Byte* data, + FT_ULong data_len, + FT_ULong offset, + CID_Face face, + FT_ULong* data_written ) { FT_Stream stream = face->root.stream; FT_Error error; FT_Byte buffer[256]; FT_Byte *p, *plimit; - FT_Byte *d, *dlimit; + FT_Byte *d = data, *dlimit; FT_Byte val; FT_Bool upper_nibble, done; @@ -684,7 +694,6 @@ if ( FT_STREAM_SEEK( offset ) ) goto Exit; - d = data; dlimit = d + data_len; p = buffer; plimit = p; @@ -758,6 +767,7 @@ error = FT_Err_Ok; Exit: + *data_written = (FT_ULong)( d - data ); return error; } @@ -770,12 +780,11 @@ CID_Parser* parser; FT_Memory memory = face->root.memory; FT_Error error; - FT_Int n; + FT_UInt n; CID_FaceInfo cid = &face->cid; FT_ULong binary_length; - FT_ULong entry_len; cid_init_loader( &loader, face ); @@ -803,8 +812,8 @@ if ( parser->binary_length > face->root.stream->size - parser->data_offset ) { - FT_TRACE0(( "cid_face_open: adjusting length of binary data\n" - " (from %ld to %ld bytes)\n", + FT_TRACE0(( "cid_face_open: adjusting length of binary data\n" )); + FT_TRACE0(( " (from %lu to %lu bytes)\n", parser->binary_length, face->root.stream->size - parser->data_offset )); parser->binary_length = face->root.stream->size - @@ -812,15 +821,16 @@ } /* we must convert the data section from hexadecimal to binary */ - if ( FT_ALLOC( face->binary_data, parser->binary_length ) || + if ( FT_QALLOC( face->binary_data, parser->binary_length ) || FT_SET_ERROR( cid_hex_to_binary( face->binary_data, parser->binary_length, parser->data_offset, - face ) ) ) + face, + &binary_length ) ) ) goto Exit; FT_Stream_OpenMemory( face->cid_stream, - face->binary_data, parser->binary_length ); + face->binary_data, binary_length ); cid->data_offset = 0; } else @@ -831,10 +841,10 @@ /* sanity tests */ - if ( cid->fd_bytes < 0 || cid->gd_bytes < 1 ) + if ( cid->gd_bytes == 0 ) { FT_ERROR(( "cid_face_open:" - " Invalid `FDBytes' or `GDBytes' value\n" )); + " Invalid `GDBytes' value\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } @@ -843,15 +853,32 @@ if ( cid->fd_bytes > 4 || cid->gd_bytes > 4 ) { FT_ERROR(( "cid_face_open:" - " Values of `FDBytes' or `GDBytes' larger than 4\n" - " " + " Values of `FDBytes' or `GDBytes' larger than 4\n" )); + FT_ERROR(( " " " are not supported\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } binary_length = face->cid_stream->size - cid->data_offset; - entry_len = (FT_ULong)( cid->fd_bytes + cid->gd_bytes ); + + if ( cid->cidmap_offset > binary_length ) + { + FT_ERROR(( "cid_face_open: Invalid `CIDMapOffset' value\n" )); + error = FT_THROW( Invalid_File_Format ); + goto Exit; + } + + /* the initial pre-check prevents the multiplication overflow */ + if ( cid->cid_count > FT_ULONG_MAX / 8 || + cid->cid_count * ( cid->fd_bytes + cid->gd_bytes ) > + binary_length - cid->cidmap_offset ) + { + FT_ERROR(( "cid_face_open: Invalid `CIDCount' value\n" )); + error = FT_THROW( Invalid_File_Format ); + goto Exit; + } + for ( n = 0; n < cid->num_dicts; n++ ) { @@ -877,8 +904,7 @@ dict->private_dict.blue_fuzz = 1; } - if ( dict->sd_bytes < 0 || - ( dict->num_subrs && dict->sd_bytes < 1 ) ) + if ( dict->num_subrs && dict->sd_bytes == 0 ) { FT_ERROR(( "cid_face_open: Invalid `SDBytes' value\n" )); error = FT_THROW( Invalid_File_Format ); @@ -901,11 +927,10 @@ goto Exit; } - /* `num_subrs' is scanned as a signed integer */ - if ( (FT_Int)dict->num_subrs < 0 || - ( dict->sd_bytes && - dict->num_subrs > ( binary_length - dict->subrmap_offset ) / - (FT_UInt)dict->sd_bytes ) ) + /* the initial pre-check prevents the multiplication overflow */ + if ( dict->num_subrs > FT_UINT_MAX / 4 || + dict->num_subrs * dict->sd_bytes > + binary_length - dict->subrmap_offset ) { FT_ERROR(( "cid_face_open: Invalid `SubrCount' value\n" )); error = FT_THROW( Invalid_File_Format ); @@ -913,22 +938,6 @@ } } - if ( cid->cidmap_offset > binary_length ) - { - FT_ERROR(( "cid_face_open: Invalid `CIDMapOffset' value\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - if ( entry_len && - cid->cid_count > - ( binary_length - cid->cidmap_offset ) / entry_len ) - { - FT_ERROR(( "cid_face_open: Invalid `CIDCount' value\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - /* we can now safely proceed */ error = cid_read_subrs( face ); diff --git a/lib/libesp32_lvgl/freetype/src/cid/cidload.h b/lib/libesp32_lvgl/freetype/src/cid/cidload.h index 06fb9ef47..d12d2962a 100644 --- a/lib/libesp32_lvgl/freetype/src/cid/cidload.h +++ b/lib/libesp32_lvgl/freetype/src/cid/cidload.h @@ -4,7 +4,7 @@ * * CID-keyed Type1 font loader (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -37,7 +37,7 @@ FT_BEGIN_HEADER FT_LOCAL( FT_ULong ) cid_get_offset( FT_Byte** start, - FT_Byte offsize ); + FT_UInt offsize ); FT_LOCAL( FT_Error ) cid_face_open( CID_Face face, diff --git a/lib/libesp32_lvgl/freetype/src/cid/cidobjs.c b/lib/libesp32_lvgl/freetype/src/cid/cidobjs.c index 04b295eb8..f698a4192 100644 --- a/lib/libesp32_lvgl/freetype/src/cid/cidobjs.c +++ b/lib/libesp32_lvgl/freetype/src/cid/cidobjs.c @@ -4,7 +4,7 @@ * * CID objects manager (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -69,8 +69,7 @@ FT_Module module; - module = FT_Get_Module( slot->face->driver->root.library, - "pshinter" ); + module = FT_Get_Module( slot->library, "pshinter" ); if ( module ) { T1_Hints_Funcs funcs; @@ -153,14 +152,18 @@ } - FT_LOCAL( FT_Error ) + FT_LOCAL_DEF( FT_Error ) cid_size_request( FT_Size size, FT_Size_Request req ) { + FT_Error error; + PSH_Globals_Funcs funcs; - FT_Request_Metrics( size->face, req ); + error = FT_Request_Metrics( size->face, req ); + if ( error ) + goto Exit; funcs = cid_size_get_globals_funcs( (CID_Size)size ); @@ -170,7 +173,8 @@ size->metrics.y_scale, 0, 0 ); - return FT_Err_Ok; + Exit: + return error; } @@ -211,7 +215,7 @@ /* release subrs */ if ( face->subrs ) { - FT_Int n; + FT_UInt n; for ( n = 0; n < cid->num_dicts; n++ ) @@ -263,7 +267,8 @@ * * @Input: * stream :: - * The source font stream. + * Dummy argument for compatibility with the `FT_Face_InitFunc` API. + * Ignored. The stream should be passed through `face->root.stream`. * * face_index :: * The index of the font face in the resource. @@ -370,6 +375,14 @@ if ( info->is_fixed_pitch ) cidface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + /* + * For the sfnt-wrapped CID fonts for MacOS, currently, + * its `cmap' tables are ignored, and the content in + * its `CID ' table is treated the same as naked CID-keyed + * font. See ft_lookup_PS_in_sfnt_stream(). + */ + cidface->face_flags |= FT_FACE_FLAG_CID_KEYED; + /* XXX: TODO: add kerning with .afm support */ /* get style name -- be careful, some broken fonts only */ @@ -479,11 +492,7 @@ /* set default property values, cf. `ftt1drv.h' */ -#ifdef T1_CONFIG_OPTION_OLD_ENGINE - driver->hinting_engine = FT_HINTING_FREETYPE; -#else driver->hinting_engine = FT_HINTING_ADOBE; -#endif driver->no_stem_darkening = TRUE; diff --git a/lib/libesp32_lvgl/freetype/src/cid/cidobjs.h b/lib/libesp32_lvgl/freetype/src/cid/cidobjs.h index 6ae306137..83c0c61c3 100644 --- a/lib/libesp32_lvgl/freetype/src/cid/cidobjs.h +++ b/lib/libesp32_lvgl/freetype/src/cid/cidobjs.h @@ -4,7 +4,7 @@ * * CID objects manager (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cid/cidparse.c b/lib/libesp32_lvgl/freetype/src/cid/cidparse.c index 1fc098b44..171a88621 100644 --- a/lib/libesp32_lvgl/freetype/src/cid/cidparse.c +++ b/lib/libesp32_lvgl/freetype/src/cid/cidparse.c @@ -4,7 +4,7 @@ * * CID-keyed Type1 parser (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -73,7 +73,11 @@ /* first of all, check the font format in the header */ if ( FT_FRAME_ENTER( 31 ) ) + { + FT_TRACE2(( " not a CID-keyed font\n" )); + error = FT_THROW( Unknown_File_Format ); goto Exit; + } if ( ft_strncmp( (char *)stream->cursor, "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) ) @@ -181,7 +185,7 @@ parser->root.base = parser->postscript; parser->root.cursor = parser->postscript; parser->root.limit = parser->root.cursor + ps_len; - parser->num_dict = -1; + parser->num_dict = FT_UINT_MAX; /* Finally, we check whether `StartData' or `/sfnts' was real -- */ /* it could be in a comment or string. We also get the arguments */ @@ -210,18 +214,24 @@ cur <= limit - STARTDATA_LEN && ft_strncmp( (char*)cur, STARTDATA, STARTDATA_LEN ) == 0 ) { - if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 ) + T1_TokenRec type_token; + FT_Long binary_length; + + + parser->root.cursor = arg1; + cid_parser_to_token( parser, &type_token ); + if ( type_token.limit - type_token.start == 5 && + ft_memcmp( (char*)type_token.start, "(Hex)", 5 ) == 0 ) { - FT_Long tmp = ft_strtol( (const char *)arg2, NULL, 10 ); - - - if ( tmp < 0 ) + parser->root.cursor = arg2; + binary_length = cid_parser_to_int( parser ); + if ( binary_length < 0 ) { FT_ERROR(( "cid_parser_new: invalid length of hex data\n" )); error = FT_THROW( Invalid_File_Format ); } else - parser->binary_length = (FT_ULong)tmp; + parser->binary_length = (FT_ULong)binary_length; } goto Exit; diff --git a/lib/libesp32_lvgl/freetype/src/cid/cidparse.h b/lib/libesp32_lvgl/freetype/src/cid/cidparse.h index 0b49bebf4..2fd4e7a93 100644 --- a/lib/libesp32_lvgl/freetype/src/cid/cidparse.h +++ b/lib/libesp32_lvgl/freetype/src/cid/cidparse.h @@ -4,7 +4,7 @@ * * CID-keyed Type1 parser (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -78,7 +78,7 @@ FT_BEGIN_HEADER FT_ULong binary_length; CID_FaceInfo cid; - FT_Int num_dict; + FT_UInt num_dict; } CID_Parser; diff --git a/lib/libesp32_lvgl/freetype/src/cid/cidriver.c b/lib/libesp32_lvgl/freetype/src/cid/cidriver.c index d08cea1d7..99e7b1183 100644 --- a/lib/libesp32_lvgl/freetype/src/cid/cidriver.c +++ b/lib/libesp32_lvgl/freetype/src/cid/cidriver.c @@ -4,7 +4,7 @@ * * CID driver interface (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -48,10 +48,11 @@ * */ - static const char* - cid_get_postscript_name( CID_Face face ) + FT_CALLBACK_DEF( const char* ) + cid_get_postscript_name( FT_Face face ) /* CID_Face */ { - const char* result = face->cid.cid_font_name; + CID_Face cidface = (CID_Face)face; + const char* result = cidface->cid.cid_font_name; if ( result && result[0] == '/' ) @@ -72,34 +73,36 @@ * */ - static FT_Error - cid_ps_get_font_info( FT_Face face, + FT_CALLBACK_DEF( FT_Error ) + cid_ps_get_font_info( FT_Face face, /* CID_Face */ PS_FontInfoRec* afont_info ) { - *afont_info = ((CID_Face)face)->cid.font_info; + *afont_info = ( (CID_Face)face )->cid.font_info; return FT_Err_Ok; } - static FT_Error - cid_ps_get_font_extra( FT_Face face, - PS_FontExtraRec* afont_extra ) + + FT_CALLBACK_DEF( FT_Error ) + cid_ps_get_font_extra( FT_Face face, /* CID_Face */ + PS_FontExtraRec* afont_extra ) { - *afont_extra = ((CID_Face)face)->font_extra; + *afont_extra = ( (CID_Face)face )->font_extra; return FT_Err_Ok; } + static const FT_Service_PsInfoRec cid_service_ps_info = { - (PS_GetFontInfoFunc) cid_ps_get_font_info, /* ps_get_font_info */ - (PS_GetFontExtraFunc) cid_ps_get_font_extra, /* ps_get_font_extra */ + cid_ps_get_font_info, /* PS_GetFontInfoFunc ps_get_font_info */ + cid_ps_get_font_extra, /* PS_GetFontExtraFunc ps_get_font_extra */ /* unsupported with CID fonts */ - (PS_HasGlyphNamesFunc) NULL, /* ps_has_glyph_names */ + NULL, /* PS_HasGlyphNamesFunc ps_has_glyph_names */ /* unsupported */ - (PS_GetFontPrivateFunc)NULL, /* ps_get_font_private */ + NULL, /* PS_GetFontPrivateFunc ps_get_font_private */ /* not implemented */ - (PS_GetFontValueFunc) NULL /* ps_get_font_value */ + NULL /* PS_GetFontValueFunc ps_get_font_value */ }; @@ -107,13 +110,14 @@ * CID INFO SERVICE * */ - static FT_Error - cid_get_ros( CID_Face face, + FT_CALLBACK_DEF( FT_Error ) + cid_get_ros( FT_Face face, /* CID_Face */ const char* *registry, const char* *ordering, FT_Int *supplement ) { - CID_FaceInfo cid = &face->cid; + CID_Face cidface = (CID_Face)face; + CID_FaceInfo cid = &cidface->cid; if ( registry ) @@ -129,32 +133,48 @@ } - static FT_Error - cid_get_is_cid( CID_Face face, + FT_CALLBACK_DEF( FT_Error ) + cid_get_is_cid( FT_Face face, /* CID_Face */ FT_Bool *is_cid ) { FT_Error error = FT_Err_Ok; FT_UNUSED( face ); + /* + * XXX: If the ROS is Adobe-Identity-H or -V, + * the font has no reliable information about + * its glyph collection. Should we not set + * *is_cid in such cases? + */ if ( is_cid ) - *is_cid = 1; /* cid driver is only used for CID keyed fonts */ + *is_cid = 1; return error; } - static FT_Error - cid_get_cid_from_glyph_index( CID_Face face, + FT_CALLBACK_DEF( FT_Error ) + cid_get_cid_from_glyph_index( FT_Face face, /* CID_Face */ FT_UInt glyph_index, FT_UInt *cid ) { - FT_Error error = FT_Err_Ok; - FT_UNUSED( face ); + FT_Error error = FT_Err_Ok; + CID_Face cidface = (CID_Face)face; - if ( cid ) - *cid = glyph_index; /* identity mapping */ + /* + * Currently, FreeType does not support incrementally-defined, CID-keyed + * fonts that store the glyph description data in a `/GlyphDirectory` + * array or dictionary. Fonts loaded by the incremental loading feature + * are thus not handled here. + */ + error = cid_compute_fd_and_offsets( cidface, glyph_index, + NULL, NULL, NULL ); + if ( error ) + *cid = 0; + else + *cid = glyph_index; return error; } @@ -162,12 +182,12 @@ static const FT_Service_CIDRec cid_service_cid_info = { - (FT_CID_GetRegistryOrderingSupplementFunc) - cid_get_ros, /* get_ros */ - (FT_CID_GetIsInternallyCIDKeyedFunc) - cid_get_is_cid, /* get_is_cid */ - (FT_CID_GetCIDFromGlyphIndexFunc) - cid_get_cid_from_glyph_index /* get_cid_from_glyph_index */ + cid_get_ros, + /* FT_CID_GetRegistryOrderingSupplementFunc get_ros */ + cid_get_is_cid, + /* FT_CID_GetIsInternallyCIDKeyedFunc get_is_cid */ + cid_get_cid_from_glyph_index + /* FT_CID_GetCIDFromGlyphIndexFunc get_cid_from_glyph_index */ }; @@ -179,9 +199,9 @@ FT_DEFINE_SERVICE_PROPERTIESREC( cid_service_properties, - (FT_Properties_SetFunc)ps_property_set, /* set_property */ - (FT_Properties_GetFunc)ps_property_get ) /* get_property */ - + ps_property_set, /* FT_Properties_SetFunc set_property */ + ps_property_get /* FT_Properties_GetFunc get_property */ + ) /* * SERVICE LIST @@ -209,7 +229,6 @@ } - FT_CALLBACK_TABLE_DEF const FT_Driver_ClassRec t1cid_driver_class = { diff --git a/lib/libesp32_lvgl/freetype/src/cid/cidriver.h b/lib/libesp32_lvgl/freetype/src/cid/cidriver.h index 0fc8ed37b..a6249385c 100644 --- a/lib/libesp32_lvgl/freetype/src/cid/cidriver.h +++ b/lib/libesp32_lvgl/freetype/src/cid/cidriver.h @@ -4,7 +4,7 @@ * * High-level CID driver interface (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cid/cidtoken.h b/lib/libesp32_lvgl/freetype/src/cid/cidtoken.h index e9f068bb5..925951acd 100644 --- a/lib/libesp32_lvgl/freetype/src/cid/cidtoken.h +++ b/lib/libesp32_lvgl/freetype/src/cid/cidtoken.h @@ -4,7 +4,7 @@ * * CID token definitions (specification only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/cid/module.mk b/lib/libesp32_lvgl/freetype/src/cid/module.mk index 9fb02235e..563cb3489 100644 --- a/lib/libesp32_lvgl/freetype/src/cid/module.mk +++ b/lib/libesp32_lvgl/freetype/src/cid/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/cid/rules.mk b/lib/libesp32_lvgl/freetype/src/cid/rules.mk index 94f663c80..c526ad38d 100644 --- a/lib/libesp32_lvgl/freetype/src/cid/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/cid/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/cid/type1cid.c b/lib/libesp32_lvgl/freetype/src/cid/type1cid.c index 082e8bfe5..905c896a3 100644 --- a/lib/libesp32_lvgl/freetype/src/cid/type1cid.c +++ b/lib/libesp32_lvgl/freetype/src/cid/type1cid.c @@ -4,7 +4,7 @@ * * FreeType OpenType driver component (body only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/dlg/dlg.c b/lib/libesp32_lvgl/freetype/src/dlg/dlg.c new file mode 100644 index 000000000..0e6bc74b6 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/dlg/dlg.c @@ -0,0 +1,803 @@ +// Copyright (c) 2019 nyorain +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt + +#define _XOPEN_SOURCE 600 +#define _POSIX_C_SOURCE 200809L +#define _WIN32_WINNT 0x0600 + +// Needed on windows so that we can use sprintf without warning. +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include +#include +#include +#include + +const char* const dlg_reset_sequence = "\033[0m"; +const struct dlg_style dlg_default_output_styles[] = { + {dlg_text_style_italic, dlg_color_green, dlg_color_none}, + {dlg_text_style_dim, dlg_color_gray, dlg_color_none}, + {dlg_text_style_none, dlg_color_cyan, dlg_color_none}, + {dlg_text_style_none, dlg_color_yellow, dlg_color_none}, + {dlg_text_style_none, dlg_color_red, dlg_color_none}, + {dlg_text_style_bold, dlg_color_red, dlg_color_none} +}; + +static void* xalloc(size_t size) { + void* ret = calloc(size, 1); + if(!ret) fprintf(stderr, "dlg: calloc returned NULL, probably crashing (size: %zu)\n", size); + return ret; +} + +static void* xrealloc(void* ptr, size_t size) { + void* ret = realloc(ptr, size); + if(!ret) fprintf(stderr, "dlg: realloc returned NULL, probably crashing (size: %zu)\n", size); + return ret; +} + +struct dlg_tag_func_pair { + const char* tag; + const char* func; +}; + +struct dlg_data { + const char** tags; // vec + struct dlg_tag_func_pair* pairs; // vec + char* buffer; + size_t buffer_size; +}; + +static dlg_handler g_handler = dlg_default_output; +static void* g_data = NULL; + +static void dlg_free_data(void* data); +static struct dlg_data* dlg_create_data(void); + +// platform-specific +#if defined(__unix__) || defined(__unix) || defined(__linux__) || defined(__APPLE__) || defined(__MACH__) + #define DLG_OS_UNIX + #include + #include + #include + + static pthread_key_t dlg_data_key; + + static void dlg_main_cleanup(void) { + void* data = pthread_getspecific(dlg_data_key); + if(data) { + dlg_free_data(data); + pthread_setspecific(dlg_data_key, NULL); + } + } + + static void init_data_key(void) { + pthread_key_create(&dlg_data_key, dlg_free_data); + atexit(dlg_main_cleanup); + } + + static struct dlg_data* dlg_data(void) { + static pthread_once_t key_once = PTHREAD_ONCE_INIT; + pthread_once(&key_once, init_data_key); + + void* data = pthread_getspecific(dlg_data_key); + if(!data) { + data = dlg_create_data(); + pthread_setspecific(dlg_data_key, data); + } + + return (struct dlg_data*) data; + } + + static void lock_file(FILE* file) { + flockfile(file); + } + + static void unlock_file(FILE* file) { + funlockfile(file); + } + + bool dlg_is_tty(FILE* stream) { + return isatty(fileno(stream)); + } + + static unsigned get_msecs(void) { + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_usec; + } + +// platform switch -- end unix +#elif defined(WIN32) || defined(_WIN32) || defined(_WIN64) + #define DLG_OS_WIN + #define WIN32_LEAN_AND_MEAN + #define DEFINE_CONSOLEV2_PROPERTIES + #include + #include + + // thanks for nothing, microsoft + #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING + #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 + #endif + + // the max buffer size we will convert on the stack + #define DLG_MAX_STACK_BUF_SIZE 1024 + + static void WINAPI dlg_fls_destructor(void* data) { + dlg_free_data(data); + } + + // TODO: error handling + static BOOL CALLBACK dlg_init_fls(PINIT_ONCE io, void* param, void** lpContext) { + (void) io; + (void) param; + **((DWORD**) lpContext) = FlsAlloc(dlg_fls_destructor); + return true; + } + + static struct dlg_data* dlg_data(void) { + static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT; + static DWORD fls = 0; + void* flsp = (void*) &fls; + InitOnceExecuteOnce(&init_once, dlg_init_fls, NULL, &flsp); + void* data = FlsGetValue(fls); + if(!data) { + data = dlg_create_data(); + FlsSetValue(fls, data); + } + + return (struct dlg_data*) data; + } + + static void lock_file(FILE* file) { + _lock_file(file); + } + + static void unlock_file(FILE* file) { + _unlock_file(file); + } + + bool dlg_is_tty(FILE* stream) { + return _isatty(_fileno(stream)); + } + +#ifdef DLG_WIN_CONSOLE + static bool init_ansi_console(void) { + HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); + HANDLE err = GetStdHandle(STD_ERROR_HANDLE); + if(out == INVALID_HANDLE_VALUE || err == INVALID_HANDLE_VALUE) + return false; + + DWORD outMode, errMode; + if(!GetConsoleMode(out, &outMode) || !GetConsoleMode(err, &errMode)) + return false; + + outMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + errMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + if(!SetConsoleMode(out, outMode) || !SetConsoleMode(out, errMode)) + return false; + + return true; + } + + static bool win_write_heap(void* handle, int needed, const char* format, va_list args) { + char* buf1 = xalloc(3 * needed + 3 + (needed % 2)); + wchar_t* buf2 = (wchar_t*) (buf1 + needed + 1 + (needed % 2)); + vsnprintf(buf1, needed + 1, format, args); + needed = MultiByteToWideChar(CP_UTF8, 0, buf1, needed, buf2, needed + 1); + bool ret = (needed != 0 && WriteConsoleW(handle, buf2, needed, NULL, NULL) != 0); + free(buf1); + return ret; + } + + static bool win_write_stack(void* handle, int needed, const char* format, va_list args) { + char buf1[DLG_MAX_STACK_BUF_SIZE]; + wchar_t buf2[DLG_MAX_STACK_BUF_SIZE]; + vsnprintf(buf1, needed + 1, format, args); + needed = MultiByteToWideChar(CP_UTF8, 0, buf1, needed, buf2, needed + 1); + return (needed != 0 && WriteConsoleW(handle, buf2, needed, NULL, NULL) != 0); + } +#endif // DLG_WIN_CONSOLE + + static unsigned get_msecs() { + SYSTEMTIME st; + GetSystemTime(&st); + return st.wMilliseconds; + } + +#else // platform switch -- end windows + #error Cannot determine platform (needed for color and utf-8 and stuff) +#endif + +// general +void dlg_escape_sequence(struct dlg_style style, char buf[12]) { + int nums[3]; + unsigned int count = 0; + + if(style.fg != dlg_color_none) { + nums[count++] = style.fg + 30; + } + + if(style.bg != dlg_color_none) { + nums[count++] = style.fg + 40; + } + + if(style.style != dlg_text_style_none) { + nums[count++] = style.style; + } + + switch(count) { + case 1: snprintf(buf, 12, "\033[%dm", nums[0]); break; + case 2: snprintf(buf, 12, "\033[%d;%dm", nums[0], nums[1]); break; + case 3: snprintf(buf, 12, "\033[%d;%d;%dm", nums[0], nums[1], nums[2]); break; + default: buf[0] = '\0'; break; + } +} + +int dlg_vfprintf(FILE* stream, const char* format, va_list args) { +#if defined(DLG_OS_WIN) && defined(DLG_WIN_CONSOLE) + void* handle = NULL; + if(stream == stdout) { + handle = GetStdHandle(STD_OUTPUT_HANDLE); + } else if(stream == stderr) { + handle = GetStdHandle(STD_ERROR_HANDLE); + } + + if(handle) { + va_list args_copy; + va_copy(args_copy, args); + int needed = vsnprintf(NULL, 0, format, args_copy); + va_end(args_copy); + + if(needed < 0) { + return needed; + } + + // We don't allocate too much on the stack + // but we also don't want to call alloc every logging call + // or use another cached buffer + if(needed >= DLG_MAX_STACK_BUF_SIZE) { + if(win_write_heap(handle, needed, format, args)) { + return needed; + } + } else { + if(win_write_stack(handle, needed, format, args)) { + return needed; + } + } + } +#endif + + return vfprintf(stream, format, args); +} + +int dlg_fprintf(FILE* stream, const char* format, ...) { + va_list args; + va_start(args, format); + int ret = dlg_vfprintf(stream, format, args); + va_end(args); + return ret; +} + +int dlg_styled_fprintf(FILE* stream, struct dlg_style style, const char* format, ...) { + char buf[12]; + dlg_escape_sequence(style, buf); + + fprintf(stream, "%s", buf); + va_list args; + va_start(args, format); + int ret = dlg_vfprintf(stream, format, args); + va_end(args); + fprintf(stream, "%s", dlg_reset_sequence); + return ret; +} + +void dlg_generic_output(dlg_generic_output_handler output, void* data, + unsigned int features, const struct dlg_origin* origin, const char* string, + const struct dlg_style styles[6]) { + // We never print any dynamic content below so we can be sure at compile + // time that a buffer of size 64 is large enough. + char format_buf[64]; + char* format = format_buf; + + if(features & dlg_output_style) { + format += sprintf(format, "%%s"); + } + + if(features & (dlg_output_time | dlg_output_file_line | dlg_output_tags | dlg_output_func)) { + format += sprintf(format, "["); + } + + bool first_meta = true; + if(features & dlg_output_time) { + format += sprintf(format, "%%h"); + first_meta = false; + } + + if(features & dlg_output_time_msecs) { + if(!first_meta) { + format += sprintf(format, ":"); + } + + format += sprintf(format, "%%m"); + first_meta = false; + } + + if(features & dlg_output_file_line) { + if(!first_meta) { + format += sprintf(format, " "); + } + + format += sprintf(format, "%%o"); + first_meta = false; + } + + if(features & dlg_output_func) { + if(!first_meta) { + format += sprintf(format, " "); + } + + format += sprintf(format, "%%f"); + first_meta = false; + } + + if(features & dlg_output_tags) { + if(!first_meta) { + format += sprintf(format, " "); + } + + format += sprintf(format, "{%%t}"); + first_meta = false; + } + + if(features & (dlg_output_time | dlg_output_file_line | dlg_output_tags | dlg_output_func)) { + format += sprintf(format, "] "); + } + + format += sprintf(format, "%%c"); + + if(features & dlg_output_newline) { + format += sprintf(format, "\n"); + } + + *format = '\0'; + dlg_generic_outputf(output, data, format_buf, origin, string, styles); +} + +void dlg_generic_outputf(dlg_generic_output_handler output, void* data, + const char* format_string, const struct dlg_origin* origin, const char* string, + const struct dlg_style styles[6]) { + bool reset_style = false; + for(const char* it = format_string; *it; it++) { + if(*it != '%') { + output(data, "%c", *it); + continue; + } + + char next = *(it + 1); // must be valid since *it is not '\0' + if(next == 'h') { + time_t t = time(NULL); + struct tm tm_info; + + #ifdef DLG_OS_WIN + if(localtime_s(&tm_info, &t)) { + #else + if(!localtime_r(&t, &tm_info)) { + #endif + output(data, ""); + } else { + char timebuf[32]; + strftime(timebuf, sizeof(timebuf), "%H:%M:%S", &tm_info); + output(data, "%s", timebuf); + } + it++; + } else if(next == 'm') { + output(data, "%06d", get_msecs()); + it++; + } else if(next == 't') { + bool first_tag = true; + for(const char** tags = origin->tags; *tags; ++tags) { + if(!first_tag) { + output(data, ", "); + } + + output(data, "%s", *tags); + first_tag = false; + } + ++it; + } else if(next == 'f') { + output(data, "%s", origin->func); + ++it; + } else if(next == 'o') { + output(data, "%s:%u", origin->file, origin->line); + ++it; + } else if(next == 's') { + char buf[12]; + dlg_escape_sequence(styles[origin->level], buf); + output(data, "%s", buf); + reset_style = true; + ++it; + } else if(next == 'r') { + output(data, "%s", dlg_reset_sequence); + reset_style = false; + ++it; + } else if(next == 'c') { + if(origin->expr && string) { + output(data, "assertion '%s' failed: '%s'", origin->expr, string); + } else if(origin->expr) { + output(data, "assertion '%s' failed", origin->expr); + } else if(string) { + output(data, "%s", string); + } + ++it; + } else if(next == '%') { + output(data, "%s", "%"); + ++it; + } else { + // in this case it's a '%' without known format specifier following + output(data, "%s", "%"); + } + } + + if(reset_style) { + output(data, "%s", dlg_reset_sequence); + } +} + +struct buf { + char* buf; + size_t* size; +}; + +static void print_size(void* size, const char* format, ...) { + va_list args; + va_start(args, format); + + int ret = vsnprintf(NULL, 0, format, args); + va_end(args); + + if(ret > 0) { + *((size_t*) size) += ret; + } +} + +static void print_buf(void* dbuf, const char* format, ...) { + struct buf* buf = (struct buf*) dbuf; + va_list args; + va_start(args, format); + + int printed = vsnprintf(buf->buf, *buf->size, format, args); + va_end(args); + + if(printed > 0) { + *buf->size -= printed; + buf->buf += printed; + } +} + +void dlg_generic_output_buf(char* buf, size_t* size, unsigned int features, + const struct dlg_origin* origin, const char* string, + const struct dlg_style styles[6]) { + if(buf) { + struct buf mbuf; + mbuf.buf = buf; + mbuf.size = size; + dlg_generic_output(print_buf, &mbuf, features, origin, string, styles); + } else { + *size = 0; + dlg_generic_output(print_size, size, features, origin, string, styles); + } +} + +void dlg_generic_outputf_buf(char* buf, size_t* size, const char* format_string, + const struct dlg_origin* origin, const char* string, + const struct dlg_style styles[6]) { + if(buf) { + struct buf mbuf; + mbuf.buf = buf; + mbuf.size = size; + dlg_generic_outputf(print_buf, &mbuf, format_string, origin, string, styles); + } else { + *size = 0; + dlg_generic_outputf(print_size, size, format_string, origin, string, styles); + } +} + +static void print_stream(void* stream, const char* format, ...) { + va_list args; + va_start(args, format); + dlg_vfprintf((FILE*) stream, format, args); + va_end(args); +} + +void dlg_generic_output_stream(FILE* stream, unsigned int features, + const struct dlg_origin* origin, const char* string, + const struct dlg_style styles[6]) { + stream = stream ? stream : stdout; + if(features & dlg_output_threadsafe) { + lock_file(stream); + } + + dlg_generic_output(print_stream, stream, features, origin, string, styles); + if(features & dlg_output_threadsafe) { + unlock_file(stream); + } +} + +void dlg_generic_outputf_stream(FILE* stream, const char* format_string, + const struct dlg_origin* origin, const char* string, + const struct dlg_style styles[6], bool lock_stream) { + stream = stream ? stream : stdout; + if(lock_stream) { + lock_file(stream); + } + + dlg_generic_outputf(print_stream, stream, format_string, origin, string, styles); + if(lock_stream) { + unlock_file(stream); + } +} + +void dlg_default_output(const struct dlg_origin* origin, const char* string, void* data) { + FILE* stream = data ? (FILE*) data : stdout; + unsigned int features = dlg_output_file_line | + dlg_output_newline | + dlg_output_threadsafe; + +#ifdef DLG_DEFAULT_OUTPUT_ALWAYS_COLOR + dlg_win_init_ansi(); + features |= dlg_output_style; +#else + if(dlg_is_tty(stream) && dlg_win_init_ansi()) { + features |= dlg_output_style; + } +#endif + + dlg_generic_output_stream(stream, features, origin, string, dlg_default_output_styles); + fflush(stream); +} + +bool dlg_win_init_ansi(void) { +#if defined(DLG_OS_WIN) && defined(DLG_WIN_CONSOLE) + // TODO: use init once + static volatile LONG status = 0; + LONG res = InterlockedCompareExchange(&status, 1, 0); + if(res == 0) { // not initialized + InterlockedExchange(&status, 3 + init_ansi_console()); + } + + while(status == 1); // currently initialized in another thread, spinlock + return (status == 4); +#else + return true; +#endif +} + +// small dynamic vec/array implementation +// Since the macros vec_init and vec_add[c]/vec_push might +// change the pointers value it must not be referenced somewhere else. +#define vec__raw(vec) (((unsigned int*) vec) - 2) + +static void* vec_do_create(unsigned int typesize, unsigned int cap, unsigned int size) { + unsigned long a = (size > cap) ? size : cap; + void* ptr = xalloc(2 * sizeof(unsigned int) + a * typesize); + unsigned int* begin = (unsigned int*) ptr; + begin[0] = size * typesize; + begin[1] = a * typesize; + return begin + 2; +} + +// NOTE: can be more efficient if we are allowed to reorder vector +static void vec_do_erase(void* vec, unsigned int pos, unsigned int size) { + unsigned int* begin = vec__raw(vec); + begin[0] -= size; + char* buf = (char*) vec; + memcpy(buf + pos, buf + pos + size, size); +} + +static void* vec_do_add(void** vec, unsigned int size) { + unsigned int* begin = vec__raw(*vec); + unsigned int needed = begin[0] + size; + if(needed >= begin[1]) { + void* ptr = xrealloc(begin, sizeof(unsigned int) * 2 + needed * 2); + begin = (unsigned int*) ptr; + begin[1] = needed * 2; + (*vec) = begin + 2; + } + + void* ptr = ((char*) (*vec)) + begin[0]; + begin[0] += size; + return ptr; +} + +#define vec_create(type, size) (type*) vec_do_create(sizeof(type), size * 2, size) +#define vec_create_reserve(type, size, capacity) (type*) vec_do_create(sizeof(type), capcity, size) +#define vec_init(array, size) array = vec_do_create(sizeof(*array), size * 2, size) +#define vec_init_reserve(array, size, capacity) *((void**) &array) = vec_do_create(sizeof(*array), capacity, size) +#define vec_free(vec) (free((vec) ? vec__raw(vec) : NULL), vec = NULL) +#define vec_erase_range(vec, pos, count) vec_do_erase(vec, pos * sizeof(*vec), count * sizeof(*vec)) +#define vec_erase(vec, pos) vec_do_erase(vec, pos * sizeof(*vec), sizeof(*vec)) +#define vec_size(vec) (vec__raw(vec)[0] / sizeof(*vec)) +#define vec_capacity(vec) (vec_raw(vec)[1] / sizeof(*vec)) +#define vec_add(vec) vec_do_add((void**) &vec, sizeof(*vec)) +#define vec_addc(vec, count) (vec_do_add((void**) &vec, sizeof(*vec) * count)) +#define vec_push(vec, value) (vec_do_add((void**) &vec, sizeof(*vec)), vec_last(vec) = (value)) +#define vec_pop(vec) (vec__raw(vec)[0] -= sizeof(*vec)) +#define vec_popc(vec, count) (vec__raw(vec)[0] -= sizeof(*vec) * count) +#define vec_clear(vec) (vec__raw(vec)[0] = 0) +#define vec_last(vec) (vec[vec_size(vec) - 1]) + +static struct dlg_data* dlg_create_data(void) { + struct dlg_data* data = (struct dlg_data*) xalloc(sizeof(struct dlg_data)); + vec_init_reserve(data->tags, 0, 20); + vec_init_reserve(data->pairs, 0, 20); + data->buffer_size = 100; + data->buffer = (char*) xalloc(data->buffer_size); + return data; +} + +static void dlg_free_data(void* ddata) { + struct dlg_data* data = (struct dlg_data*) ddata; + if(data) { + vec_free(data->pairs); + vec_free(data->tags); + free(data->buffer); + free(data); + } +} + +void dlg_add_tag(const char* tag, const char* func) { + struct dlg_data* data = dlg_data(); + struct dlg_tag_func_pair* pair = + (struct dlg_tag_func_pair*) vec_add(data->pairs); + pair->tag = tag; + pair->func = func; +} + +bool dlg_remove_tag(const char* tag, const char* func) { + struct dlg_data* data = dlg_data(); + for(unsigned int i = 0; i < vec_size(data->pairs); ++i) { + if(data->pairs[i].func == func && data->pairs[i].tag == tag) { + vec_erase(data->pairs, i); + return true; + } + } + + return false; +} + +char** dlg_thread_buffer(size_t** size) { + struct dlg_data* data = dlg_data(); + if(size) { + *size = &data->buffer_size; + } + return &data->buffer; +} + +void dlg_set_handler(dlg_handler handler, void* data) { + g_handler = handler; + g_data = data; +} + +dlg_handler dlg_get_handler(void** data) { + *data = g_data; + return g_handler; +} + +const char* dlg__printf_format(const char* str, ...) { + va_list vlist; + va_start(vlist, str); + + va_list vlistcopy; + va_copy(vlistcopy, vlist); + int needed = vsnprintf(NULL, 0, str, vlist); + if(needed < 0) { + printf("dlg__printf_format: invalid format given\n"); + va_end(vlist); + va_end(vlistcopy); + return NULL; + } + + va_end(vlist); + + size_t* buf_size; + char** buf = dlg_thread_buffer(&buf_size); + if(*buf_size <= (unsigned int) needed) { + *buf_size = (needed + 1) * 2; + *buf = (char*) xrealloc(*buf, *buf_size); + } + + vsnprintf(*buf, *buf_size, str, vlistcopy); + va_end(vlistcopy); + + return *buf; +} + +void dlg__do_log(enum dlg_level lvl, const char* const* tags, const char* file, int line, + const char* func, const char* string, const char* expr) { + struct dlg_data* data = dlg_data(); + unsigned int tag_count = 0; + + // push default tags + while(tags[tag_count]) { + vec_push(data->tags, tags[tag_count++]); + } + + // push current global tags + for(size_t i = 0; i < vec_size(data->pairs); ++i) { + const struct dlg_tag_func_pair pair = data->pairs[i]; + if(pair.func == NULL || !strcmp(pair.func, func)) { + vec_push(data->tags, pair.tag); + } + } + + // push call-specific tags, skip first terminating NULL + ++tag_count; + while(tags[tag_count]) { + vec_push(data->tags, tags[tag_count++]); + } + + vec_push(data->tags, NULL); // terminating NULL + struct dlg_origin origin; + origin.level = lvl; + origin.file = file; + origin.line = line; + origin.func = func; + origin.expr = expr; + origin.tags = data->tags; + + g_handler(&origin, string, g_data); + vec_clear(data->tags); +} + +#ifdef _MSC_VER +// shitty msvc compatbility +// meson gives us sane paths (separated by '/') while on MSVC, +// __FILE__ contains a '\\' separator. +static bool path_same(char a, char b) { + return (a == b) || + (a == '/' && b == '\\') || + (a == '\\' && b == '/'); +} +#else + +static inline bool path_same(char a, char b) { + return a == b; +} + +#endif + +const char* dlg__strip_root_path(const char* file, const char* base) { + if(!file) { + return NULL; + } + + const char* saved = file; + if(*file == '.') { // relative path detected + while(*(++file) == '.' || *file == '/' || *file == '\\'); + if(*file == '\0') { // weird case: purely relative path without file + return saved; + } + + return file; + } + + // strip base from file if it is given + if(base) { + char fn = *file; + char bn = *base; + while(bn != '\0' && path_same(fn, bn)) { + fn = *(++file); + bn = *(++base); + } + + if(fn == '\0' || bn != '\0') { // weird case: base isn't prefix of file + return saved; + } + } + + return file; +} diff --git a/lib/libesp32_lvgl/freetype/src/dlg/dlgwrap.c b/lib/libesp32_lvgl/freetype/src/dlg/dlgwrap.c new file mode 100644 index 000000000..e9dc3410a --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/dlg/dlgwrap.c @@ -0,0 +1,32 @@ +/**************************************************************************** + * + * dlgwrap.c + * + * Wrapper file for the 'dlg' library (body only) + * + * Copyright (C) 2020-2023 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#include +#include FT_CONFIG_OPTIONS_H + + +#ifdef FT_DEBUG_LOGGING +#define DLG_STATIC +#include "dlg.c" +#else + /* ANSI C doesn't like empty source files */ + typedef int dlg_dummy_; +#endif + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/dlg/rules.mk b/lib/libesp32_lvgl/freetype/src/dlg/rules.mk new file mode 100644 index 000000000..7f506fd35 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/dlg/rules.mk @@ -0,0 +1,70 @@ +# +# FreeType 2 dlg logging library configuration rules +# + + +# Copyright (C) 2020-2023 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# dlg logging library directory +# +DLG_DIR := $(SRC_DIR)/dlg + + +# compilation flags for the library +# +DLG_COMPILE := $(CC) $(ANSIFLAGS) \ + $I$(subst /,$(COMPILER_SEP),$(DLG_DIR)) \ + $(INCLUDE_FLAGS) \ + $(FT_CFLAGS) + + +# dlg logging library sources (i.e., C files) +# +DLG_SRC := $(DLG_DIR)/dlgwrap.c + +# dlg logging library headers +# +DLG_H := $(TOP_DIR)/include/dlg/dlg.h \ + $(TOP_DIR)/include/dlg/output.h + + +# dlg logging library object(s) +# +# DLG_OBJ_M is used during `multi' builds +# DLG_OBJ_S is used during `single' builds +# +DLG_OBJ_M := $(DLG_SRC:$(DLG_DIR)/%.c=$(OBJ_DIR)/%.$O) +DLG_OBJ_S := $(OBJ_DIR)/dlg.$O + +# dlg logging library source file for single build +# +DLG_SRC_S := $(DLG_DIR)/dlgwrap.c + + +# dlg logging library - single object +# +$(DLG_OBJ_S): $(DLG_SRC_S) $(DLG_SRC) $(FREETYPE_H) $(DLG_H) + $(DLG_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(DLG_SRC_S)) + + +# dlg logging library - multiple objects +# +$(OBJ_DIR)/%.$O: $(DLG_DIR)/%.c $(FREETYPE_H) $(DLG_H) + $(DLG_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) + + +# update main object lists +# +DLG_OBJS_S += $(DLG_OBJ_S) +DLG_OBJS_M += $(DLG_OBJ_M) + + +# EOF diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/README b/lib/libesp32_lvgl/freetype/src/gxvalid/README index 2a32bab20..0e3db322e 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/README +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/README @@ -518,7 +518,7 @@ gxvalid: TrueType GX validator ------------------------------------------------------------------------ -Copyright (C) 2004-2020 by +Copyright (C) 2004-2023 by suzuki toshiya, Masatake YAMATO, Red hat K.K., David Turner, Robert Wilhelm, and Werner Lemberg. diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvalid.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvalid.c index 683b8a697..e0359f4df 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvalid.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvalid.c @@ -4,7 +4,7 @@ * * FreeType validator for TrueTypeGX/AAT tables (body only). * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvalid.h b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvalid.h index ff2812da2..a83408b41 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvalid.h +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvalid.h @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT table validation (specification only). * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvbsln.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvbsln.c index ac58d4615..030a64ee4 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvbsln.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvbsln.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT bsln table validation (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvcommn.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvcommn.c index ead0f24cd..7f908742a 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvcommn.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvcommn.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT common tables validation (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * @@ -46,16 +46,11 @@ /*************************************************************************/ /*************************************************************************/ - static int - gxv_compare_ushort_offset( FT_UShort* a, - FT_UShort* b ) + FT_COMPARE_DEF( int ) + gxv_compare_ushort_offset( const void* a, + const void* b ) { - if ( *a < *b ) - return -1; - else if ( *a > *b ) - return 1; - else - return 0; + return *(FT_UShort*)a - *(FT_UShort*)b; } @@ -78,7 +73,7 @@ buff[nmemb] = limit; ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_UShort ), - ( int(*)(const void*, const void*) )gxv_compare_ushort_offset ); + gxv_compare_ushort_offset ); if ( buff[nmemb] > limit ) FT_INVALID_OFFSET; @@ -111,13 +106,17 @@ /*************************************************************************/ /*************************************************************************/ - static int - gxv_compare_ulong_offset( FT_ULong* a, - FT_ULong* b ) + FT_COMPARE_DEF( int ) + gxv_compare_ulong_offset( const void* a, + const void* b ) { - if ( *a < *b ) + FT_ULong a_ = *(FT_ULong*)a; + FT_ULong b_ = *(FT_ULong*)b; + + + if ( a_ < b_ ) return -1; - else if ( *a > *b ) + else if ( a_ > b_ ) return 1; else return 0; @@ -143,7 +142,7 @@ buff[nmemb] = limit; ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_ULong ), - ( int(*)(const void*, const void*) )gxv_compare_ulong_offset ); + gxv_compare_ulong_offset ); if ( buff[nmemb] > limit ) FT_INVALID_OFFSET; @@ -439,7 +438,7 @@ GXV_LIMIT_CHECK( 2 ); if ( p + 2 >= limit ) /* some fonts have too-short fmt0 array */ { - GXV_TRACE(( "too short, glyphs %d - %d are missing\n", + GXV_TRACE(( "too short, glyphs %d - %ld are missing\n", i, gxvalid->face->num_glyphs )); GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID ); break; @@ -534,7 +533,7 @@ if ( lastGlyph < firstGlyph ) { - GXV_TRACE(( "reverse ordered range specification at unit %d:", + GXV_TRACE(( "reverse ordered range specification at unit %d:" " lastGlyph %d < firstGlyph %d ", unit, lastGlyph, firstGlyph )); GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID ); @@ -605,7 +604,7 @@ if ( lastGlyph < firstGlyph ) { - GXV_TRACE(( "reverse ordered range specification at unit %d:", + GXV_TRACE(( "reverse ordered range specification at unit %d:" " lastGlyph %d < firstGlyph %d ", unit, lastGlyph, firstGlyph )); GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID ); @@ -825,7 +824,7 @@ face = gxvalid->face; if ( face->num_glyphs < gid ) { - GXV_TRACE(( " gxv_glyphid_check() gid overflow: num_glyphs %d < %d\n", + GXV_TRACE(( " gxv_glyphid_check() gid overflow: num_glyphs %ld < %d\n", face->num_glyphs, gid )); GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID ); } @@ -1034,7 +1033,7 @@ GXV_NAME_ENTER( "StateArray" ); GXV_TRACE(( "parse %d bytes by stateSize=%d maxClassID=%d\n", - (int)(*length_p), stateSize, (int)(maxClassID) )); + (int)( *length_p ), stateSize, (int)maxClassID )); /* * 2 states are predefined and must be described in StateArray: @@ -1419,7 +1418,7 @@ GXV_NAME_ENTER( "XStateArray" ); GXV_TRACE(( "parse % 3d bytes by stateSize=% 3d maxClassID=% 3d\n", - (int)(*length_p), stateSize, (int)(maxClassID) )); + (int)( *length_p ), (int)stateSize, (int)maxClassID )); /* * 2 states are predefined and must be described: @@ -1493,9 +1492,11 @@ state = (FT_UShort)( newState_idx / ( 1 + maxClassID ) ); if ( 0 != ( newState_idx % ( 1 + maxClassID ) ) ) { - FT_TRACE4(( "-> new state = %d (supposed)\n" - "but newState index 0x%04x is not aligned to %d-classes\n", - state, newState_idx, 1 + maxClassID )); + FT_TRACE4(( "-> new state = %d (supposed)\n", + state )); + FT_TRACE4(( "but newState index 0x%04x" + " is not aligned to %d-classes\n", + newState_idx, 1 + maxClassID )); GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET ); } @@ -1581,10 +1582,10 @@ stateArray = FT_NEXT_ULONG( p ); entryTable = FT_NEXT_ULONG( p ); - GXV_TRACE(( "nClasses =0x%08x\n", gxvalid->xstatetable.nClasses )); - GXV_TRACE(( "offset to classTable=0x%08x\n", classTable )); - GXV_TRACE(( "offset to stateArray=0x%08x\n", stateArray )); - GXV_TRACE(( "offset to entryTable=0x%08x\n", entryTable )); + GXV_TRACE(( "nClasses =0x%08lx\n", gxvalid->xstatetable.nClasses )); + GXV_TRACE(( "offset to classTable=0x%08lx\n", classTable )); + GXV_TRACE(( "offset to stateArray=0x%08lx\n", stateArray )); + GXV_TRACE(( "offset to entryTable=0x%08lx\n", entryTable )); if ( gxvalid->xstatetable.nClasses > 0xFFFFU ) FT_INVALID_DATA; diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvcommn.h b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvcommn.h index 59d149215..f88d23a41 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvcommn.h +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvcommn.h @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT common tables validation (specification). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * @@ -61,8 +61,11 @@ FT_BEGIN_HEADER #undef GXV_LOAD_UNUSED_VARS /* debug purpose */ -#define IS_PARANOID_VALIDATION ( gxvalid->root->level >= FT_VALIDATE_PARANOID ) -#define GXV_SET_ERR_IF_PARANOID( err ) { if ( IS_PARANOID_VALIDATION ) ( err ); } +#define IS_PARANOID_VALIDATION \ + ( gxvalid->root->level >= FT_VALIDATE_PARANOID ) +#define GXV_SET_ERR_IF_PARANOID( err ) \ + do { if ( IS_PARANOID_VALIDATION ) ( err ); } while ( 0 ) + /*************************************************************************/ /*************************************************************************/ @@ -261,17 +264,17 @@ FT_BEGIN_HEADER } GXV_ValidatorRec; -#define GXV_TABLE_DATA( tag, field ) \ +#define GXV_TABLE_DATA( tag, field ) \ ( ( (GXV_ ## tag ## _Data)gxvalid->table_data )->field ) #undef FT_INVALID_ -#define FT_INVALID_( _error ) \ +#define FT_INVALID_( _error ) \ ft_validator_error( gxvalid->root, FT_THROW( _error ) ) -#define GXV_LIMIT_CHECK( _count ) \ - FT_BEGIN_STMNT \ +#define GXV_LIMIT_CHECK( _count ) \ + FT_BEGIN_STMNT \ if ( p + _count > ( limit? limit : gxvalid->root->limit ) ) \ - FT_INVALID_TOO_SHORT; \ + FT_INVALID_TOO_SHORT; \ FT_END_STMNT @@ -279,19 +282,19 @@ FT_BEGIN_HEADER #define GXV_INIT gxvalid->debug_indent = 0 -#define GXV_NAME_ENTER( name ) \ - FT_BEGIN_STMNT \ - gxvalid->debug_indent += 2; \ - FT_TRACE4(( "%*.s", gxvalid->debug_indent, 0 )); \ - FT_TRACE4(( "%s table\n", name )); \ +#define GXV_NAME_ENTER( name ) \ + FT_BEGIN_STMNT \ + gxvalid->debug_indent += 2; \ + FT_TRACE4(( "%*.s", gxvalid->debug_indent, "" )); \ + FT_TRACE4(( "%s table\n", name )); \ FT_END_STMNT #define GXV_EXIT gxvalid->debug_indent -= 2 -#define GXV_TRACE( s ) \ - FT_BEGIN_STMNT \ - FT_TRACE4(( "%*.s", gxvalid->debug_indent, 0 )); \ - FT_TRACE4( s ); \ +#define GXV_TRACE( s ) \ + FT_BEGIN_STMNT \ + FT_TRACE4(( "%*.s", gxvalid->debug_indent, "" )); \ + FT_TRACE4( s ); \ FT_END_STMNT #else /* !FT_DEBUG_LEVEL_TRACE */ diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxverror.h b/lib/libesp32_lvgl/freetype/src/gxvalid/gxverror.h index 5d8f0b680..09311ed3c 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxverror.h +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxverror.h @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT validation module error codes (specification only). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvfeat.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvfeat.c index 400ec8a3f..6cf18212a 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvfeat.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvfeat.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT feat table validation (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * @@ -90,7 +90,7 @@ if ( feature >= gxv_feat_registry_length ) { - GXV_TRACE(( "feature number %d is out of range %d\n", + GXV_TRACE(( "feature number %d is out of range %lu\n", feature, gxv_feat_registry_length )); GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA ); goto Exit; diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvfeat.h b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvfeat.h index 435dcefb0..b33c1bc68 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvfeat.h +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvfeat.h @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT feat table validation (specification). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvfgen.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvfgen.c index fe05a6f3a..cf98bb36c 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvfgen.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvfgen.c @@ -5,7 +5,7 @@ * Generate feature registry data for gxv `feat' validator. * This program is derived from gxfeatreg.c in gxlayout. * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * Masatake YAMATO and Redhat K.K. * * This file may only be used, @@ -97,7 +97,8 @@ #define EMPTYFEAT {0, 0, {NULL}} - static GX_Feature_RegistryRec featreg_table[] = { + static GX_Feature_RegistryRec featreg_table[] = + { { /* 0 */ "All Typographic Features", 0, diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvjust.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvjust.c index 3c7f1f953..5cca94d8f 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvjust.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvjust.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT just table validation (body). * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * @@ -78,7 +78,7 @@ return; GXV_TRACE(( "just table includes too large %s" - " GID=%d > %d (in maxp)\n", + " GID=%d > %ld (in maxp)\n", msg_tag, gid, gxvalid->face->num_glyphs )); GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID ); } @@ -140,7 +140,7 @@ count = FT_NEXT_ULONG( p ); for ( i = 0; i < count; i++ ) { - GXV_TRACE(( "validating wdc pair %d/%d\n", i + 1, count )); + GXV_TRACE(( "validating wdc pair %lu/%lu\n", i + 1, count )); gxv_just_wdp_entry_validate( p, limit, gxvalid ); p += gxvalid->subtable_length; } @@ -156,7 +156,6 @@ { FT_Bytes p = table; FT_Bytes wdc_end = table + GXV_JUST_DATA( wdc_offset_max ); - FT_UInt i; GXV_NAME_ENTER( "just justDeltaClusters" ); @@ -164,7 +163,7 @@ if ( limit <= wdc_end ) FT_INVALID_OFFSET; - for ( i = 0; p <= wdc_end; i++ ) + while ( p <= wdc_end ) { gxv_just_wdc_entry_validate( p, limit, gxvalid ); p += gxvalid->subtable_length; @@ -206,7 +205,8 @@ if ( lowerLimit >= upperLimit ) { GXV_TRACE(( "just table includes invalid range spec:" - " lowerLimit(%d) > upperLimit(%d)\n" )); + " lowerLimit(%ld) > upperLimit(%ld)\n", + lowerLimit, upperLimit )); GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA ); } @@ -294,14 +294,14 @@ gxvalid->subtable_length = (FT_ULong)( p - table ); if ( variantsAxis != 0x64756374L ) /* 'duct' */ - GXV_TRACE(( "variantsAxis 0x%08x is non default value", + GXV_TRACE(( "variantsAxis 0x%08lx is non default value", variantsAxis )); if ( minimumLimit > noStretchValue ) - GXV_TRACE(( "type4:minimumLimit 0x%08x > noStretchValue 0x%08x\n", + GXV_TRACE(( "type4:minimumLimit 0x%08lx > noStretchValue 0x%08lx\n", minimumLimit, noStretchValue )); else if ( noStretchValue > maximumLimit ) - GXV_TRACE(( "type4:noStretchValue 0x%08x > maximumLimit 0x%08x\n", + GXV_TRACE(( "type4:noStretchValue 0x%08lx > maximumLimit 0x%08lx\n", noStretchValue, maximumLimit )); else if ( !IS_PARANOID_VALIDATION ) return; @@ -389,7 +389,7 @@ GXV_LIMIT_CHECK( 4 ); actionCount = FT_NEXT_ULONG( p ); - GXV_TRACE(( "actionCount = %d\n", actionCount )); + GXV_TRACE(( "actionCount = %lu\n", actionCount )); for ( i = 0; i < actionCount; i++ ) { @@ -514,14 +514,14 @@ coverage = FT_NEXT_USHORT( p ); subFeatureFlags = FT_NEXT_ULONG( p ); - GXV_TRACE(( " justClassTable: coverage = 0x%04x (%s) ", coverage )); + GXV_TRACE(( " justClassTable: coverage = 0x%04x ", coverage )); if ( ( coverage & 0x4000 ) == 0 ) GXV_TRACE(( "ascending\n" )); else GXV_TRACE(( "descending\n" )); if ( subFeatureFlags ) - GXV_TRACE(( " justClassTable: nonzero value (0x%08x)" + GXV_TRACE(( " justClassTable: nonzero value (0x%08lx)" " in unused subFeatureFlags\n", subFeatureFlags )); gxvalid->statetable.optdata = NULL; @@ -684,7 +684,7 @@ /* Version 1.0 (always:2000) */ - GXV_TRACE(( " (version = 0x%08x)\n", version )); + GXV_TRACE(( " (version = 0x%08lx)\n", version )); if ( version != 0x00010000UL ) FT_INVALID_FORMAT; diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvkern.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvkern.c index cc0b3dfcb..21fc24596 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvkern.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvkern.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT kern table validation (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * @@ -487,7 +487,7 @@ if ( gxvalid->face->num_glyphs != glyphCount ) { - GXV_TRACE(( "maxGID=%d, but glyphCount=%d\n", + GXV_TRACE(( "maxGID=%ld, but glyphCount=%d\n", gxvalid->face->num_glyphs, glyphCount )); GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID ); } @@ -745,7 +745,7 @@ #ifdef GXV_LOAD_TRACE_VARS FT_UShort version = 0; /* MS only: subtable version, unused */ #endif - FT_ULong length; /* MS: 16bit, Apple: 32bit*/ + FT_ULong length; /* MS: 16bit, Apple: 32bit */ FT_UShort coverage; #ifdef GXV_LOAD_TRACE_VARS FT_UShort tupleIndex = 0; /* Apple only */ @@ -772,7 +772,7 @@ tupleIndex = 0; #endif GXV_TRACE(( "Subtable version = %d\n", version )); - GXV_TRACE(( "Subtable length = %d\n", length )); + GXV_TRACE(( "Subtable length = %lu\n", length )); break; case KERN_DIALECT_APPLE: @@ -783,7 +783,7 @@ #ifdef GXV_LOAD_TRACE_VARS tupleIndex = 0; #endif - GXV_TRACE(( "Subtable length = %d\n", length )); + GXV_TRACE(( "Subtable length = %lu\n", length )); if ( KERN_IS_NEW( gxvalid ) ) { @@ -800,7 +800,7 @@ default: length = u16[1]; GXV_TRACE(( "cannot detect subtable dialect, " - "just skip %d byte\n", length )); + "just skip %lu byte\n", length )); goto Exit; } @@ -884,7 +884,7 @@ for ( i = 0; i < nTables; i++ ) { - GXV_TRACE(( "validating subtable %d/%d\n", i, nTables )); + GXV_TRACE(( "validating subtable %d/%lu\n", i, nTables )); /* p should be 32bit-aligned? */ gxv_kern_subtable_validate( p, 0, gxvalid ); p += gxvalid->subtable_length; diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvlcar.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvlcar.c index 82ac1907a..5f3bf8907 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvlcar.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvlcar.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT lcar table validation (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmod.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmod.c index a467e8713..0b4115bbc 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmod.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmod.c @@ -4,7 +4,7 @@ * * FreeType's TrueTypeGX/AAT validation module implementation (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * @@ -62,7 +62,7 @@ if ( error ) goto Exit; - if ( FT_ALLOC( *table, *table_len ) ) + if ( FT_QALLOC( *table, *table_len ) ) goto Exit; error = FT_Load_Sfnt_Table( face, tag, 0, *table, table_len ); @@ -76,27 +76,31 @@ FT_Byte* volatile _sfnt = NULL; \ FT_ULong len_ ## _sfnt = 0 -#define GXV_TABLE_LOAD( _sfnt ) \ - if ( ( FT_VALIDATE_ ## _sfnt ## _INDEX < table_count ) && \ - ( gx_flags & FT_VALIDATE_ ## _sfnt ) ) \ - { \ - error = gxv_load_table( face, TTAG_ ## _sfnt, \ - &_sfnt, &len_ ## _sfnt ); \ - if ( error ) \ - goto Exit; \ - } +#define GXV_TABLE_LOAD( _sfnt ) \ + FT_BEGIN_STMNT \ + if ( ( FT_VALIDATE_ ## _sfnt ## _INDEX < table_count ) && \ + ( gx_flags & FT_VALIDATE_ ## _sfnt ) ) \ + { \ + error = gxv_load_table( face, TTAG_ ## _sfnt, \ + &_sfnt, &len_ ## _sfnt ); \ + if ( error ) \ + goto Exit; \ + } \ + FT_END_STMNT -#define GXV_TABLE_VALIDATE( _sfnt ) \ - if ( _sfnt ) \ - { \ - ft_validator_init( &valid, _sfnt, _sfnt + len_ ## _sfnt, \ - FT_VALIDATE_DEFAULT ); \ - if ( ft_setjmp( valid.jump_buffer ) == 0 ) \ - gxv_ ## _sfnt ## _validate( _sfnt, face, &valid ); \ - error = valid.error; \ - if ( error ) \ - goto Exit; \ - } +#define GXV_TABLE_VALIDATE( _sfnt ) \ + FT_BEGIN_STMNT \ + if ( _sfnt ) \ + { \ + ft_validator_init( &valid, _sfnt, _sfnt + len_ ## _sfnt, \ + FT_VALIDATE_DEFAULT ); \ + if ( ft_setjmp( valid.jump_buffer ) == 0 ) \ + gxv_ ## _sfnt ## _validate( _sfnt, face, &valid ); \ + error = valid.error; \ + if ( error ) \ + goto Exit; \ + } \ + FT_END_STMNT #define GXV_TABLE_SET( _sfnt ) \ if ( FT_VALIDATE_ ## _sfnt ## _INDEX < table_count ) \ diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmod.h b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmod.h index f2982c96c..db3d1d9f5 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmod.h +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmod.h @@ -5,7 +5,7 @@ * FreeType's TrueTypeGX/AAT validation module implementation * (specification). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort.c index aae7f01a8..7032d6349 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT mort table validation (body). * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * @@ -288,7 +288,7 @@ for ( i = 0; i < nChains; i++ ) { - GXV_TRACE(( "validating chain %d/%d\n", i + 1, nChains )); + GXV_TRACE(( "validating chain %lu/%lu\n", i + 1, nChains )); GXV_32BIT_ALIGNMENT_VALIDATE( p - table ); gxv_mort_chain_validate( p, limit, gxvalid ); p += gxvalid->subtable_length; diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort.h b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort.h index 7237c5825..5c819bdbc 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort.h +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort.h @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT common definition for mort table (specification). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort0.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort0.c index d452c1cca..24e70a0da 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort0.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort0.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT mort table validation * body for type0 (Indic Script Rearrangement) subtable. * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort1.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort1.c index d743f89f6..ea5591f98 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort1.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort1.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT mort table validation * body for type1 (Contextual Substitution) subtable. * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort2.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort2.c index 9e69e1269..50644f06a 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort2.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort2.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT mort table validation * body for type2 (Ligature Substitution) subtable. * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * @@ -152,7 +152,7 @@ GXV_32BIT_ALIGNMENT_VALIDATE( ligActionOffset ); if ( p < lat_base ) { - GXV_TRACE(( "too short offset 0x%04x: p < lat_base (%d byte rewind)\n", + GXV_TRACE(( "too short offset 0x%04x: p < lat_base (%ld byte rewind)\n", ligActionOffset, lat_base - p )); /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */ @@ -160,7 +160,7 @@ } else if ( lat_limit < p ) { - GXV_TRACE(( "too large offset 0x%04x: lat_limit < p (%d byte overrun)\n", + GXV_TRACE(( "too large offset 0x%04x: lat_limit < p (%ld byte overrun)\n", ligActionOffset, p - lat_limit )); /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */ @@ -187,17 +187,17 @@ offset = lig_action & 0x3FFFFFFFUL; if ( offset * 2 < optdata->ligatureTable ) { - GXV_TRACE(( "too short offset 0x%08x:" - " 2 x offset < ligatureTable (%d byte rewind)\n", + GXV_TRACE(( "too short offset 0x%08lx:" + " 2 x offset < ligatureTable (%lu byte rewind)\n", offset, optdata->ligatureTable - offset * 2 )); GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET ); } else if ( offset * 2 > optdata->ligatureTable + optdata->ligatureTable_length ) { - GXV_TRACE(( "too long offset 0x%08x:" + GXV_TRACE(( "too long offset 0x%08lx:" " 2 x offset > ligatureTable + ligatureTable_length" - " (%d byte overrun)\n", + " (%lu byte overrun)\n", offset, optdata->ligatureTable + optdata->ligatureTable_length - offset * 2 )); diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort4.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort4.c index 4584d204c..0641b1133 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort4.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort4.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT mort table validation * body for type4 (Non-Contextual Glyph Substitution) subtable. * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort5.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort5.c index a15a24fe6..9225bb0c6 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort5.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmort5.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT mort table validation * body for type5 (Contextual Glyph Insertion) subtable. * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * @@ -63,7 +63,7 @@ *GXV_mort_subtable_type5_StateOptRecData; - FT_LOCAL_DEF( void ) + static void gxv_mort_subtable_type5_subtable_setup( FT_UShort table_size, FT_UShort classTable, FT_UShort stateArray, diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx.c index 754d9f8bf..931bf006b 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT morx table validation (body). * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * @@ -84,7 +84,7 @@ p += 4; #endif - GXV_TRACE(( "validating chain subtable %d/%d (%d bytes)\n", + GXV_TRACE(( "validating chain subtable %d/%d (%lu bytes)\n", i + 1, nSubtables, length )); type = coverage & 0x0007; @@ -99,7 +99,7 @@ func = fmt_funcs_table[type]; if ( !func ) - GXV_TRACE(( "morx type %d is reserved\n", type )); + GXV_TRACE(( "morx type %lu is reserved\n", type )); func( p, p + rest, gxvalid ); @@ -186,7 +186,7 @@ for ( i = 0; i < nChains; i++ ) { - GXV_TRACE(( "validating chain %d/%d\n", i + 1, nChains )); + GXV_TRACE(( "validating chain %lu/%lu\n", i + 1, nChains )); GXV_32BIT_ALIGNMENT_VALIDATE( p - table ); gxv_morx_chain_validate( p, limit, gxvalid ); p += gxvalid->subtable_length; diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx.h b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx.h index f747b1d63..27572553d 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx.h +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx.h @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT common definition for morx table (specification). * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx0.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx0.c index 5a42e552e..73523f363 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx0.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx0.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT morx table validation * body for type0 (Indic Script Rearrangement) subtable. * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx1.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx1.c index 9f8b69067..71a201880 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx1.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx1.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT morx table validation * body for type1 (Contextual Substitution) subtable. * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx2.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx2.c index 98b5c49c2..858c81143 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx2.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx2.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT morx table validation * body for type2 (Ligature Substitution) subtable. * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * @@ -72,11 +72,11 @@ optdata->componentTable = FT_NEXT_ULONG( p ); optdata->ligatureTable = FT_NEXT_ULONG( p ); - GXV_TRACE(( "offset to ligActionTable=0x%08x\n", + GXV_TRACE(( "offset to ligActionTable=0x%08lx\n", optdata->ligActionTable )); - GXV_TRACE(( "offset to componentTable=0x%08x\n", + GXV_TRACE(( "offset to componentTable=0x%08lx\n", optdata->componentTable )); - GXV_TRACE(( "offset to ligatureTable=0x%08x\n", + GXV_TRACE(( "offset to ligatureTable=0x%08lx\n", optdata->ligatureTable )); } @@ -116,19 +116,19 @@ gxv_set_length_by_ulong_offset( o, l, buff, 6, table_size, gxvalid ); - GXV_TRACE(( "classTable: offset=0x%08x length=0x%08x\n", + GXV_TRACE(( "classTable: offset=0x%08lx length=0x%08lx\n", classTable, *classTable_length_p )); - GXV_TRACE(( "stateArray: offset=0x%08x length=0x%08x\n", + GXV_TRACE(( "stateArray: offset=0x%08lx length=0x%08lx\n", stateArray, *stateArray_length_p )); - GXV_TRACE(( "entryTable: offset=0x%08x length=0x%08x\n", + GXV_TRACE(( "entryTable: offset=0x%08lx length=0x%08lx\n", entryTable, *entryTable_length_p )); - GXV_TRACE(( "ligActionTable: offset=0x%08x length=0x%08x\n", + GXV_TRACE(( "ligActionTable: offset=0x%08lx length=0x%08lx\n", optdata->ligActionTable, optdata->ligActionTable_length )); - GXV_TRACE(( "componentTable: offset=0x%08x length=0x%08x\n", + GXV_TRACE(( "componentTable: offset=0x%08lx length=0x%08lx\n", optdata->componentTable, optdata->componentTable_length )); - GXV_TRACE(( "ligatureTable: offset=0x%08x length=0x%08x\n", + GXV_TRACE(( "ligatureTable: offset=0x%08lx length=0x%08lx\n", optdata->ligatureTable, optdata->ligatureTable_length )); @@ -157,12 +157,12 @@ if ( p < lat_base ) { - GXV_TRACE(( "p < lat_base (%d byte rewind)\n", lat_base - p )); + GXV_TRACE(( "p < lat_base (%ld byte rewind)\n", lat_base - p )); FT_INVALID_OFFSET; } else if ( lat_limit < p ) { - GXV_TRACE(( "lat_limit < p (%d byte overrun)\n", p - lat_limit )); + GXV_TRACE(( "lat_limit < p (%ld byte overrun)\n", p - lat_limit )); FT_INVALID_OFFSET; } @@ -196,7 +196,7 @@ GXV_TRACE(( "ligature action table includes" " too negative offset moving all GID" - " below defined range: 0x%04x\n", + " below defined range: 0x%04lx\n", offset & 0xFFFFU )); GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET ); } @@ -207,14 +207,14 @@ GXV_TRACE(( "ligature action table includes" " too large offset moving all GID" - " over defined range: 0x%04x\n", + " over defined range: 0x%04lx\n", offset & 0xFFFFU )); GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET ); } GXV_TRACE(( "ligature action table includes" " invalid offset to add to 16-bit GID:" - " 0x%08x\n", offset )); + " 0x%08lx\n", offset )); GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET ); } } diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx4.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx4.c index 857e4d4eb..c9ad19906 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx4.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx4.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT morx table validation * body for "morx" type4 (Non-Contextual Glyph Substitution) subtable. * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx5.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx5.c index 7ceba077a..95fa4e288 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx5.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvmorx5.c @@ -5,7 +5,7 @@ * TrueTypeGX/AAT morx table validation * body for type5 (Contextual Glyph Insertion) subtable. * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvopbd.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvopbd.c index a398fe097..5e9a9665e 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvopbd.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvopbd.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT opbd table validation (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * @@ -188,7 +188,7 @@ /* only 0x00010000 is defined (1996) */ - GXV_TRACE(( "(version=0x%08x)\n", version )); + GXV_TRACE(( "(version=0x%08lx)\n", version )); if ( 0x00010000UL != version ) FT_INVALID_FORMAT; diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvprop.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvprop.c index bee8bab97..63a052a8e 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvprop.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvprop.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT prop table validation (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * @@ -283,7 +283,7 @@ format = FT_NEXT_USHORT( p ); defaultProp = FT_NEXT_USHORT( p ); - GXV_TRACE(( " version 0x%08x\n", version )); + GXV_TRACE(( " version 0x%08lx\n", version )); GXV_TRACE(( " format 0x%04x\n", format )); GXV_TRACE(( " defaultProp 0x%04x\n", defaultProp )); @@ -309,7 +309,7 @@ if ( format == 0 ) { FT_TRACE3(( "(format 0, no per-glyph properties, " - "remaining %d bytes are skipped)", limit - p )); + "remaining %ld bytes are skipped)", limit - p )); goto Exit; } diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvtrak.c b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvtrak.c index 58a631c9e..f3fb51c8a 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/gxvtrak.c +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/gxvtrak.c @@ -4,7 +4,7 @@ * * TrueTypeGX/AAT trak table validation (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * suzuki toshiya, Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * @@ -130,7 +130,7 @@ p = table + j * ( 4 + 2 + 2 ); t = FT_NEXT_LONG( p ); if ( t == track ) - GXV_TRACE(( "duplicated entries found for track value 0x%x\n", + GXV_TRACE(( "duplicated entries found for track value 0x%lx\n", track )); } } @@ -243,7 +243,7 @@ vertOffset = FT_NEXT_USHORT( p ); reserved = FT_NEXT_USHORT( p ); - GXV_TRACE(( " (version = 0x%08x)\n", version )); + GXV_TRACE(( " (version = 0x%08lx)\n", version )); GXV_TRACE(( " (format = 0x%04x)\n", format )); GXV_TRACE(( " (horizOffset = 0x%04x)\n", horizOffset )); GXV_TRACE(( " (vertOffset = 0x%04x)\n", vertOffset )); diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/module.mk b/lib/libesp32_lvgl/freetype/src/gxvalid/module.mk index e7d408df9..49491348a 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/module.mk +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/module.mk @@ -2,7 +2,7 @@ # FreeType 2 gxvalid module definition # -# Copyright (C) 2004-2020 by +# Copyright (C) 2004-2023 by # suzuki toshiya, Masatake YAMATO, Red Hat K.K., # David Turner, Robert Wilhelm, and Werner Lemberg. # diff --git a/lib/libesp32_lvgl/freetype/src/gxvalid/rules.mk b/lib/libesp32_lvgl/freetype/src/gxvalid/rules.mk index d55a4935e..95ae6334e 100644 --- a/lib/libesp32_lvgl/freetype/src/gxvalid/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/gxvalid/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 2004-2020 by +# Copyright (C) 2004-2023 by # suzuki toshiya, Masatake YAMATO, Red Hat K.K., # David Turner, Robert Wilhelm, and Werner Lemberg. # diff --git a/lib/libesp32_lvgl/freetype/src/gzip/README.freetype b/lib/libesp32_lvgl/freetype/src/gzip/README.freetype new file mode 100644 index 000000000..76298b06b --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/gzip/README.freetype @@ -0,0 +1,23 @@ +Name: zlib +Short Name: zlib +URL: http://zlib.net/ +Version: 1.2.13 +License: see `zlib.h` + +Description: +"A massively spiffy yet delicately unobtrusive compression library." + +'zlib' is a free, general-purpose, legally unencumbered lossless +data-compression library. 'zlib' implements the "deflate" compression +algorithm described by RFC 1951, which combines the LZ77 (Lempel-Ziv) +algorithm with Huffman coding. zlib also implements the zlib (RFC 1950) and +gzip (RFC 1952) wrapper formats. + +Local Modifications: +The files in this directory have been prepared as follows. + + - Take the unmodified source code files from the zlib distribution that are + included by `ftgzip.c`. + - Copy `zconf.h` to `ftzconf.h` (which stays unmodified otherwise). + - Run zlib's `zlib2ansi` script on all `.c` files. + - Apply the diff file(s) in the `patches` folder. diff --git a/lib/libesp32_lvgl/freetype/src/gzip/adler32.c b/lib/libesp32_lvgl/freetype/src/gzip/adler32.c index c53f9dd12..aa032e1dd 100644 --- a/lib/libesp32_lvgl/freetype/src/gzip/adler32.c +++ b/lib/libesp32_lvgl/freetype/src/gzip/adler32.c @@ -1,48 +1,192 @@ /* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2002 Mark Adler + * Copyright (C) 1995-2011, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ -#include "zlib.h" +#include "zutil.h" -#define BASE 65521L /* largest prime smaller than 65536 */ +#ifndef Z_FREETYPE +local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); +#endif + +#define BASE 65521U /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ -#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); +/* use NO_DIVIDE if your processor does not do division in hardware -- + try it both ways to see which is faster */ +#ifdef NO_DIVIDE +/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 + (thank you to John Reiser for pointing this out) */ +# define CHOP(a) \ + do { \ + unsigned long tmp = a >> 16; \ + a &= 0xffffUL; \ + a += (tmp << 4) - tmp; \ + } while (0) +# define MOD28(a) \ + do { \ + CHOP(a); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD(a) \ + do { \ + CHOP(a); \ + MOD28(a); \ + } while (0) +# define MOD63(a) \ + do { /* this assumes a is not negative */ \ + z_off64_t tmp = a >> 32; \ + a &= 0xffffffffL; \ + a += (tmp << 8) - (tmp << 5) + tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD28(a) a %= BASE +# define MOD63(a) a %= BASE +#endif + /* ========================================================================= */ -ZEXPORT(uLong) adler32( /* adler, buf, len) */ +uLong ZEXPORT adler32_z( uLong adler, const Bytef *buf, - uInt len ) + z_size_t len) { - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int k; + unsigned long sum2; + unsigned n; - if (buf == Z_NULL) return 1L; + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; - while (len > 0) { - k = len < NMAX ? len : NMAX; - len -= k; - while (k >= 16) { + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD28(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; DO16(buf); buf += 16; - k -= 16; } - if (k != 0) do { - s1 += *buf++; - s2 += s1; - } while (--k); - s1 %= BASE; - s2 %= BASE; + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); } - return (s2 << 16) | s1; + + /* return recombined sums */ + return adler | (sum2 << 16); } + +/* ========================================================================= */ +uLong ZEXPORT adler32( + uLong adler, + const Bytef *buf, + uInt len) +{ + return adler32_z(adler, buf, len); +} + +#ifndef Z_FREETYPE + +/* ========================================================================= */ +local uLong adler32_combine_( + uLong adler1, + uLong adler2, + z_off64_t len2) +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* for negative len, return invalid adler32 as a clue for debugging */ + if (len2 < 0) + return 0xffffffffUL; + + /* the derivation of this formula is left as an exercise for the reader */ + MOD63(len2); /* assumes len2 >= 0 */ + rem = (unsigned)len2; + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine( + uLong adler1, + uLong adler2, + z_off_t len2) +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64( + uLong adler1, + uLong adler2, + z_off64_t len2) +{ + return adler32_combine_(adler1, adler2, len2); +} + +#endif /* !Z_FREETYPE */ diff --git a/lib/libesp32_lvgl/freetype/src/gzip/crc32.c b/lib/libesp32_lvgl/freetype/src/gzip/crc32.c new file mode 100644 index 000000000..6cd1b09d5 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/gzip/crc32.c @@ -0,0 +1,1135 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2022 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * This interleaved implementation of a CRC makes use of pipelined multiple + * arithmetic-logic units, commonly found in modern CPU cores. It is due to + * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + + MAKECRCH can be #defined to write out crc32.h. A main() routine is also + produced, so that this one source file can be compiled to an executable. + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */ + + /* + A CRC of a message is computed on N braids of words in the message, where + each word consists of W bytes (4 or 8). If N is 3, for example, then three + running sparse CRCs are calculated respectively on each braid, at these + indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ... + This is done starting at a word boundary, and continues until as many blocks + of N * W bytes as are available have been processed. The results are combined + into a single CRC at the end. For this code, N must be in the range 1..6 and + W must be 4 or 8. The upper limit on N can be increased if desired by adding + more #if blocks, extending the patterns apparent in the code. In addition, + crc32.h would need to be regenerated, if the maximum N value is increased. + + N and W are chosen empirically by benchmarking the execution time on a given + processor. The choices for N and W below were based on testing on Intel Kaby + Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64 + Octeon II processors. The Intel, AMD, and ARM processors were all fastest + with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4. + They were all tested with either gcc or clang, all using the -O3 optimization + level. Your mileage may vary. + */ + +/* Define N */ +#ifdef Z_TESTN +# define N Z_TESTN +#else +# define N 5 +#endif +#if N < 1 || N > 6 +# error N must be in 1..6 +#endif + +/* + z_crc_t must be at least 32 bits. z_word_t must be at least as long as + z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and + that bytes are eight bits. + */ + +/* + Define W and the associated z_word_t type. If W is not defined, then a + braided calculation is not used, and the associated tables and code are not + compiled. + */ +#ifdef Z_TESTW +# if Z_TESTW-1 != -1 +# define W Z_TESTW +# endif +#else +# ifdef MAKECRCH +# define W 8 /* required for MAKECRCH */ +# else +# if defined(__x86_64__) || defined(__aarch64__) +# define W 8 +# else +# define W 4 +# endif +# endif +#endif +#ifdef W +# if W == 8 && defined(Z_U8) + typedef Z_U8 z_word_t; +# elif defined(Z_U4) +# undef W +# define W 4 + typedef Z_U4 z_word_t; +# else +# undef W +# endif +#endif + +/* If available, use the ARM processor CRC32 instruction. */ +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8 +# define ARMCRC32 +#endif + +#ifndef Z_FREETYPE +/* Local functions. */ +local z_crc_t multmodp OF((z_crc_t a, z_crc_t b)); +local z_crc_t x2nmodp OF((z_off64_t n, unsigned k)); +#endif /* Z_FREETYPE */ + +#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) + local z_word_t byte_swap OF((z_word_t word)); +#endif + +#if defined(W) && !defined(ARMCRC32) + local z_crc_t crc_word OF((z_word_t data)); + local z_word_t crc_word_big OF((z_word_t data)); +#endif + +#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) +/* + Swap the bytes in a z_word_t to convert between little and big endian. Any + self-respecting compiler will optimize this to a single machine byte-swap + instruction, if one is available. This assumes that word_t is either 32 bits + or 64 bits. + */ +local z_word_t byte_swap( + z_word_t word) +{ +# if W == 8 + return + (word & 0xff00000000000000) >> 56 | + (word & 0xff000000000000) >> 40 | + (word & 0xff0000000000) >> 24 | + (word & 0xff00000000) >> 8 | + (word & 0xff000000) << 8 | + (word & 0xff0000) << 24 | + (word & 0xff00) << 40 | + (word & 0xff) << 56; +# else /* W == 4 */ + return + (word & 0xff000000) >> 24 | + (word & 0xff0000) >> 8 | + (word & 0xff00) << 8 | + (word & 0xff) << 24; +# endif +} +#endif + +/* CRC polynomial. */ +#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ + +#ifdef DYNAMIC_CRC_TABLE + +local z_crc_t FAR crc_table[256]; +local z_crc_t FAR x2n_table[32]; +local void make_crc_table OF((void)); +#ifdef W + local z_word_t FAR crc_big_table[256]; + local z_crc_t FAR crc_braid_table[W][256]; + local z_word_t FAR crc_braid_big_table[W][256]; + local void braid OF((z_crc_t [][256], z_word_t [][256], int, int)); +#endif +#ifdef MAKECRCH + local void write_table OF((FILE *, const z_crc_t FAR *, int)); + local void write_table32hi OF((FILE *, const z_word_t FAR *, int)); + local void write_table64 OF((FILE *, const z_word_t FAR *, int)); +#endif /* MAKECRCH */ + +/* + Define a once() function depending on the availability of atomics. If this is + compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in + multiple threads, and if atomics are not available, then get_crc_table() must + be called to initialize the tables and must return before any threads are + allowed to compute or combine CRCs. + */ + +/* Definition of once functionality. */ +typedef struct once_s once_t; +local void once OF((once_t *, void (*)(void))); + +/* Check for the availability of atomics. */ +#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \ + !defined(__STDC_NO_ATOMICS__) + +#include + +/* Structure for once(), which must be initialized with ONCE_INIT. */ +struct once_s { + atomic_flag begun; + atomic_int done; +}; +#define ONCE_INIT {ATOMIC_FLAG_INIT, 0} + +/* + Run the provided init() function exactly once, even if multiple threads + invoke once() at the same time. The state must be a once_t initialized with + ONCE_INIT. + */ +local void once(state, init) + once_t *state; + void (*init)(void); +{ + if (!atomic_load(&state->done)) { + if (atomic_flag_test_and_set(&state->begun)) + while (!atomic_load(&state->done)) + ; + else { + init(); + atomic_store(&state->done, 1); + } + } +} + +#else /* no atomics */ + +/* Structure for once(), which must be initialized with ONCE_INIT. */ +struct once_s { + volatile int begun; + volatile int done; +}; +#define ONCE_INIT {0, 0} + +/* Test and set. Alas, not atomic, but tries to minimize the period of + vulnerability. */ +local int test_and_set OF((int volatile *)); +local int test_and_set( + int volatile *flag) +{ + int was; + + was = *flag; + *flag = 1; + return was; +} + +/* Run the provided init() function once. This is not thread-safe. */ +local void once(state, init) + once_t *state; + void (*init)(void); +{ + if (!state->done) { + if (test_and_set(&state->begun)) + while (!state->done) + ; + else { + init(); + state->done = 1; + } + } +} + +#endif + +/* State for once(). */ +local once_t made = ONCE_INIT; + +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x + (which is shifting right by one and adding x^32 mod p if the bit shifted out + is a one). We start with the highest power (least significant bit) of q and + repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all the + information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. + */ + +local void make_crc_table() +{ + unsigned i, j, n; + z_crc_t p; + + /* initialize the CRC of bytes tables */ + for (i = 0; i < 256; i++) { + p = i; + for (j = 0; j < 8; j++) + p = p & 1 ? (p >> 1) ^ POLY : p >> 1; + crc_table[i] = p; +#ifdef W + crc_big_table[i] = byte_swap(p); +#endif + } + + /* initialize the x^2^n mod p(x) table */ + p = (z_crc_t)1 << 30; /* x^1 */ + x2n_table[0] = p; + for (n = 1; n < 32; n++) + x2n_table[n] = p = multmodp(p, p); + +#ifdef W + /* initialize the braiding tables -- needs x2n_table[] */ + braid(crc_braid_table, crc_braid_big_table, N, W); +#endif + +#ifdef MAKECRCH + { + /* + The crc32.h header file contains tables for both 32-bit and 64-bit + z_word_t's, and so requires a 64-bit type be available. In that case, + z_word_t must be defined to be 64-bits. This code then also generates + and writes out the tables for the case that z_word_t is 32 bits. + */ +#if !defined(W) || W != 8 +# error Need a 64-bit integer type in order to generate crc32.h. +#endif + FILE *out; + int k, n; + z_crc_t ltl[8][256]; + z_word_t big[8][256]; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + + /* write out little-endian CRC table to crc32.h */ + fprintf(out, + "/* crc32.h -- tables for rapid CRC calculation\n" + " * Generated automatically by crc32.c\n */\n" + "\n" + "local const z_crc_t FAR crc_table[] = {\n" + " "); + write_table(out, crc_table, 256); + fprintf(out, + "};\n"); + + /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#ifdef W\n" + "\n" + "#if W == 8\n" + "\n" + "local const z_word_t FAR crc_big_table[] = {\n" + " "); + write_table64(out, crc_big_table, 256); + fprintf(out, + "};\n"); + + /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#else /* W == 4 */\n" + "\n" + "local const z_word_t FAR crc_big_table[] = {\n" + " "); + write_table32hi(out, crc_big_table, 256); + fprintf(out, + "};\n" + "\n" + "#endif\n"); + + /* write out braid tables for each value of N */ + for (n = 1; n <= 6; n++) { + fprintf(out, + "\n" + "#if N == %d\n", n); + + /* compute braid tables for this N and 64-bit word_t */ + braid(ltl, big, n, 8); + + /* write out braid tables for 64-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#if W == 8\n" + "\n" + "local const z_crc_t FAR crc_braid_table[][256] = {\n"); + for (k = 0; k < 8; k++) { + fprintf(out, " {"); + write_table(out, ltl[k], 256); + fprintf(out, "}%s", k < 7 ? ",\n" : ""); + } + fprintf(out, + "};\n" + "\n" + "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); + for (k = 0; k < 8; k++) { + fprintf(out, " {"); + write_table64(out, big[k], 256); + fprintf(out, "}%s", k < 7 ? ",\n" : ""); + } + fprintf(out, + "};\n"); + + /* compute braid tables for this N and 32-bit word_t */ + braid(ltl, big, n, 4); + + /* write out braid tables for 32-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#else /* W == 4 */\n" + "\n" + "local const z_crc_t FAR crc_braid_table[][256] = {\n"); + for (k = 0; k < 4; k++) { + fprintf(out, " {"); + write_table(out, ltl[k], 256); + fprintf(out, "}%s", k < 3 ? ",\n" : ""); + } + fprintf(out, + "};\n" + "\n" + "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); + for (k = 0; k < 4; k++) { + fprintf(out, " {"); + write_table32hi(out, big[k], 256); + fprintf(out, "}%s", k < 3 ? ",\n" : ""); + } + fprintf(out, + "};\n" + "\n" + "#endif\n" + "\n" + "#endif\n"); + } + fprintf(out, + "\n" + "#endif\n"); + + /* write out zeros operator table to crc32.h */ + fprintf(out, + "\n" + "local const z_crc_t FAR x2n_table[] = {\n" + " "); + write_table(out, x2n_table, 32); + fprintf(out, + "};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH + +/* + Write the 32-bit values in table[0..k-1] to out, five per line in + hexadecimal separated by commas. + */ +local void write_table( + FILE *out, + const z_crc_t FAR *table, + int k) +{ + int n; + + for (n = 0; n < k; n++) + fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", + (unsigned long)(table[n]), + n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); +} + +/* + Write the high 32-bits of each value in table[0..k-1] to out, five per line + in hexadecimal separated by commas. + */ +local void write_table32hi( + FILE *out, + const z_word_t FAR *table, + int k) +{ + int n; + + for (n = 0; n < k; n++) + fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", + (unsigned long)(table[n] >> 32), + n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); +} + +/* + Write the 64-bit values in table[0..k-1] to out, three per line in + hexadecimal separated by commas. This assumes that if there is a 64-bit + type, then there is also a long long integer type, and it is at least 64 + bits. If not, then the type cast and format string can be adjusted + accordingly. + */ +local void write_table64( + FILE *out, + const z_word_t FAR *table, + int k) +{ + int n; + + for (n = 0; n < k; n++) + fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ", + (unsigned long long)(table[n]), + n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", ")); +} + +/* Actually do the deed. */ +int main() +{ + make_crc_table(); + return 0; +} + +#endif /* MAKECRCH */ + +#ifdef W +/* + Generate the little and big-endian braid tables for the given n and z_word_t + size w. Each array must have room for w blocks of 256 elements. + */ +local void braid(ltl, big, n, w) + z_crc_t ltl[][256]; + z_word_t big[][256]; + int n; + int w; +{ + int k; + z_crc_t i, p, q; + for (k = 0; k < w; k++) { + p = x2nmodp((n * w + 3 - k) << 3, 0); + ltl[k][0] = 0; + big[w - 1 - k][0] = 0; + for (i = 1; i < 256; i++) { + ltl[k][i] = q = multmodp(i << 24, p); + big[w - 1 - k][i] = byte_swap(q); + } + } +} +#endif + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables for byte-wise and braided CRC-32 calculations, and a table of powers + * of x for combining CRC-32s, all made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ======================================================================== + * Routines used for CRC calculation. Some are also required for the table + * generation above. + */ + +#ifndef Z_FREETYPE + +/* + Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial, + reflected. For speed, this requires that a not be zero. + */ +local z_crc_t multmodp( + z_crc_t a, + z_crc_t b) +{ + z_crc_t m, p; + + m = (z_crc_t)1 << 31; + p = 0; + for (;;) { + if (a & m) { + p ^= b; + if ((a & (m - 1)) == 0) + break; + } + m >>= 1; + b = b & 1 ? (b >> 1) ^ POLY : b >> 1; + } + return p; +} + +/* + Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been + initialized. + */ +local z_crc_t x2nmodp( + z_off64_t n, + unsigned k) +{ + z_crc_t p; + + p = (z_crc_t)1 << 31; /* x^0 == 1 */ + while (n) { + if (n & 1) + p = multmodp(x2n_table[k & 31], p); + n >>= 1; + k++; + } + return p; +} + +/* ========================================================================= + * This function can be used by asm versions of crc32(), and to force the + * generation of the CRC tables in a threaded application. + */ +const z_crc_t FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + once(&made, make_crc_table); +#endif /* DYNAMIC_CRC_TABLE */ + return (const z_crc_t FAR *)crc_table; +} + +#endif /* Z_FREETYPE */ + +/* ========================================================================= + * Use ARM machine instructions if available. This will compute the CRC about + * ten times faster than the braided calculation. This code does not check for + * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will + * only be defined if the compilation specifies an ARM processor architecture + * that has the instructions. For example, compiling with -march=armv8.1-a or + * -march=armv8-a+crc, or -march=native if the compile machine has the crc32 + * instructions. + */ +#ifdef ARMCRC32 + +/* + Constants empirically determined to maximize speed. These values are from + measurements on a Cortex-A57. Your mileage may vary. + */ +#define Z_BATCH 3990 /* number of words in a batch */ +#define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */ +#define Z_BATCH_MIN 800 /* fewest words in a final batch */ + +unsigned long ZEXPORT crc32_z( + unsigned long crc, + const unsigned char FAR *buf, + z_size_t len) +{ + z_crc_t val; + z_word_t crc1, crc2; + const z_word_t *word; + z_word_t val0, val1, val2; + z_size_t last, last2, i; + z_size_t num; + + /* Return initial CRC, if requested. */ + if (buf == Z_NULL) return 0; + +#ifdef DYNAMIC_CRC_TABLE + once(&made, make_crc_table); +#endif /* DYNAMIC_CRC_TABLE */ + + /* Pre-condition the CRC */ + crc = (~crc) & 0xffffffff; + + /* Compute the CRC up to a word boundary. */ + while (len && ((z_size_t)buf & 7) != 0) { + len--; + val = *buf++; + __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val)); + } + + /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */ + word = (z_word_t const *)buf; + num = len >> 3; + len &= 7; + + /* Do three interleaved CRCs to realize the throughput of one crc32x + instruction per cycle. Each CRC is calculated on Z_BATCH words. The + three CRCs are combined into a single CRC after each set of batches. */ + while (num >= 3 * Z_BATCH) { + crc1 = 0; + crc2 = 0; + for (i = 0; i < Z_BATCH; i++) { + val0 = word[i]; + val1 = word[i + Z_BATCH]; + val2 = word[i + 2 * Z_BATCH]; + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1)); + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2)); + } + word += 3 * Z_BATCH; + num -= 3 * Z_BATCH; + crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1; + crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2; + } + + /* Do one last smaller batch with the remaining words, if there are enough + to pay for the combination of CRCs. */ + last = num / 3; + if (last >= Z_BATCH_MIN) { + last2 = last << 1; + crc1 = 0; + crc2 = 0; + for (i = 0; i < last; i++) { + val0 = word[i]; + val1 = word[i + last]; + val2 = word[i + last2]; + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1)); + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2)); + } + word += 3 * last; + num -= 3 * last; + val = x2nmodp(last, 6); + crc = multmodp(val, crc) ^ crc1; + crc = multmodp(val, crc) ^ crc2; + } + + /* Compute the CRC on any remaining words. */ + for (i = 0; i < num; i++) { + val0 = word[i]; + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); + } + word += num; + + /* Complete the CRC on any remaining bytes. */ + buf = (const unsigned char FAR *)word; + while (len) { + len--; + val = *buf++; + __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val)); + } + + /* Return the CRC, post-conditioned. */ + return crc ^ 0xffffffff; +} + +#else + +#ifdef W + +/* + Return the CRC of the W bytes in the word_t data, taking the + least-significant byte of the word as the first byte of data, without any pre + or post conditioning. This is used to combine the CRCs of each braid. + */ +local z_crc_t crc_word( + z_word_t data) +{ + int k; + for (k = 0; k < W; k++) + data = (data >> 8) ^ crc_table[data & 0xff]; + return (z_crc_t)data; +} + +local z_word_t crc_word_big( + z_word_t data) +{ + int k; + for (k = 0; k < W; k++) + data = (data << 8) ^ + crc_big_table[(data >> ((W - 1) << 3)) & 0xff]; + return data; +} + +#endif + +/* ========================================================================= */ +unsigned long ZEXPORT crc32_z( + unsigned long crc, + const unsigned char FAR *buf, + z_size_t len) +{ + /* Return initial CRC, if requested. */ + if (buf == Z_NULL) return 0; + +#ifdef DYNAMIC_CRC_TABLE + once(&made, make_crc_table); +#endif /* DYNAMIC_CRC_TABLE */ + + /* Pre-condition the CRC */ + crc = (~crc) & 0xffffffff; + +#ifdef W + + /* If provided enough bytes, do a braided CRC calculation. */ + if (len >= N * W + W - 1) { + z_size_t blks; + z_word_t const *words; + unsigned endian; + int k; + + /* Compute the CRC up to a z_word_t boundary. */ + while (len && ((z_size_t)buf & (W - 1)) != 0) { + len--; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + } + + /* Compute the CRC on as many N z_word_t blocks as are available. */ + blks = len / (N * W); + len -= blks * N * W; + words = (z_word_t const *)buf; + + /* Do endian check at execution time instead of compile time, since ARM + processors can change the endianess at execution time. If the + compiler knows what the endianess will be, it can optimize out the + check and the unused branch. */ + endian = 1; + if (*(unsigned char *)&endian) { + /* Little endian. */ + + z_crc_t crc0; + z_word_t word0; +#if N > 1 + z_crc_t crc1; + z_word_t word1; +#if N > 2 + z_crc_t crc2; + z_word_t word2; +#if N > 3 + z_crc_t crc3; + z_word_t word3; +#if N > 4 + z_crc_t crc4; + z_word_t word4; +#if N > 5 + z_crc_t crc5; + z_word_t word5; +#endif +#endif +#endif +#endif +#endif + + /* Initialize the CRC for each braid. */ + crc0 = crc; +#if N > 1 + crc1 = 0; +#if N > 2 + crc2 = 0; +#if N > 3 + crc3 = 0; +#if N > 4 + crc4 = 0; +#if N > 5 + crc5 = 0; +#endif +#endif +#endif +#endif +#endif + + /* + Process the first blks-1 blocks, computing the CRCs on each braid + independently. + */ + while (--blks) { + /* Load the word for each braid into registers. */ + word0 = crc0 ^ words[0]; +#if N > 1 + word1 = crc1 ^ words[1]; +#if N > 2 + word2 = crc2 ^ words[2]; +#if N > 3 + word3 = crc3 ^ words[3]; +#if N > 4 + word4 = crc4 ^ words[4]; +#if N > 5 + word5 = crc5 ^ words[5]; +#endif +#endif +#endif +#endif +#endif + words += N; + + /* Compute and update the CRC for each word. The loop should + get unrolled. */ + crc0 = crc_braid_table[0][word0 & 0xff]; +#if N > 1 + crc1 = crc_braid_table[0][word1 & 0xff]; +#if N > 2 + crc2 = crc_braid_table[0][word2 & 0xff]; +#if N > 3 + crc3 = crc_braid_table[0][word3 & 0xff]; +#if N > 4 + crc4 = crc_braid_table[0][word4 & 0xff]; +#if N > 5 + crc5 = crc_braid_table[0][word5 & 0xff]; +#endif +#endif +#endif +#endif +#endif + for (k = 1; k < W; k++) { + crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff]; +#if N > 1 + crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff]; +#if N > 2 + crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff]; +#if N > 3 + crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff]; +#if N > 4 + crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff]; +#if N > 5 + crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff]; +#endif +#endif +#endif +#endif +#endif + } + } + + /* + Process the last block, combining the CRCs of the N braids at the + same time. + */ + crc = crc_word(crc0 ^ words[0]); +#if N > 1 + crc = crc_word(crc1 ^ words[1] ^ crc); +#if N > 2 + crc = crc_word(crc2 ^ words[2] ^ crc); +#if N > 3 + crc = crc_word(crc3 ^ words[3] ^ crc); +#if N > 4 + crc = crc_word(crc4 ^ words[4] ^ crc); +#if N > 5 + crc = crc_word(crc5 ^ words[5] ^ crc); +#endif +#endif +#endif +#endif +#endif + words += N; + } + else { + /* Big endian. */ + + z_word_t crc0, word0, comb; +#if N > 1 + z_word_t crc1, word1; +#if N > 2 + z_word_t crc2, word2; +#if N > 3 + z_word_t crc3, word3; +#if N > 4 + z_word_t crc4, word4; +#if N > 5 + z_word_t crc5, word5; +#endif +#endif +#endif +#endif +#endif + + /* Initialize the CRC for each braid. */ + crc0 = byte_swap(crc); +#if N > 1 + crc1 = 0; +#if N > 2 + crc2 = 0; +#if N > 3 + crc3 = 0; +#if N > 4 + crc4 = 0; +#if N > 5 + crc5 = 0; +#endif +#endif +#endif +#endif +#endif + + /* + Process the first blks-1 blocks, computing the CRCs on each braid + independently. + */ + while (--blks) { + /* Load the word for each braid into registers. */ + word0 = crc0 ^ words[0]; +#if N > 1 + word1 = crc1 ^ words[1]; +#if N > 2 + word2 = crc2 ^ words[2]; +#if N > 3 + word3 = crc3 ^ words[3]; +#if N > 4 + word4 = crc4 ^ words[4]; +#if N > 5 + word5 = crc5 ^ words[5]; +#endif +#endif +#endif +#endif +#endif + words += N; + + /* Compute and update the CRC for each word. The loop should + get unrolled. */ + crc0 = crc_braid_big_table[0][word0 & 0xff]; +#if N > 1 + crc1 = crc_braid_big_table[0][word1 & 0xff]; +#if N > 2 + crc2 = crc_braid_big_table[0][word2 & 0xff]; +#if N > 3 + crc3 = crc_braid_big_table[0][word3 & 0xff]; +#if N > 4 + crc4 = crc_braid_big_table[0][word4 & 0xff]; +#if N > 5 + crc5 = crc_braid_big_table[0][word5 & 0xff]; +#endif +#endif +#endif +#endif +#endif + for (k = 1; k < W; k++) { + crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff]; +#if N > 1 + crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff]; +#if N > 2 + crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff]; +#if N > 3 + crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff]; +#if N > 4 + crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff]; +#if N > 5 + crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff]; +#endif +#endif +#endif +#endif +#endif + } + } + + /* + Process the last block, combining the CRCs of the N braids at the + same time. + */ + comb = crc_word_big(crc0 ^ words[0]); +#if N > 1 + comb = crc_word_big(crc1 ^ words[1] ^ comb); +#if N > 2 + comb = crc_word_big(crc2 ^ words[2] ^ comb); +#if N > 3 + comb = crc_word_big(crc3 ^ words[3] ^ comb); +#if N > 4 + comb = crc_word_big(crc4 ^ words[4] ^ comb); +#if N > 5 + comb = crc_word_big(crc5 ^ words[5] ^ comb); +#endif +#endif +#endif +#endif +#endif + words += N; + crc = byte_swap(comb); + } + + /* + Update the pointer to the remaining bytes to process. + */ + buf = (unsigned char const *)words; + } + +#endif /* W */ + + /* Complete the computation of the CRC on any remaining bytes. */ + while (len >= 8) { + len -= 8; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + } + while (len) { + len--; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + } + + /* Return the CRC, post-conditioned. */ + return crc ^ 0xffffffff; +} + +#endif + +/* ========================================================================= */ +unsigned long ZEXPORT crc32( + unsigned long crc, + const unsigned char FAR *buf, + uInt len) +{ + return crc32_z(crc, buf, len); +} + +#ifndef Z_FREETYPE + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine64( + uLong crc1, + uLong crc2, + z_off64_t len2) +{ +#ifdef DYNAMIC_CRC_TABLE + once(&made, make_crc_table); +#endif /* DYNAMIC_CRC_TABLE */ + return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine( + uLong crc1, + uLong crc2, + z_off_t len2) +{ + return crc32_combine64(crc1, crc2, (z_off64_t)len2); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine_gen64( + z_off64_t len2) +{ +#ifdef DYNAMIC_CRC_TABLE + once(&made, make_crc_table); +#endif /* DYNAMIC_CRC_TABLE */ + return x2nmodp(len2, 3); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine_gen( + z_off_t len2) +{ + return crc32_combine_gen64((z_off64_t)len2); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine_op( + uLong crc1, + uLong crc2, + uLong op) +{ + return multmodp(op, crc1) ^ (crc2 & 0xffffffff); +} + +#endif /* Z_FREETYPE */ diff --git a/lib/libesp32_lvgl/freetype/src/gzip/crc32.h b/lib/libesp32_lvgl/freetype/src/gzip/crc32.h new file mode 100644 index 000000000..137df68d6 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/gzip/crc32.h @@ -0,0 +1,9446 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const z_crc_t FAR crc_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}; + +#ifdef W + +#if W == 8 + +local const z_word_t FAR crc_big_table[] = { + 0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000, + 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000, + 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000, + 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000, + 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000, + 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000, + 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000, + 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000, + 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000, + 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000, + 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000, + 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000, + 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000, + 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000, + 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000, + 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000, + 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000, + 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000, + 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000, + 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000, + 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000, + 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000, + 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000, + 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000, + 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000, + 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000, + 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000, + 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000, + 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000, + 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000, + 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000, + 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000, + 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000, + 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000, + 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000, + 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000, + 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000, + 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000, + 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000, + 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000, + 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000, + 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000, + 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000, + 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000, + 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000, + 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000, + 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000, + 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000, + 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000, + 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000, + 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000, + 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000, + 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000, + 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000, + 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000, + 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000, + 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000, + 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000, + 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000, + 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000, + 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000, + 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000, + 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000, + 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000, + 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000, + 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000, + 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000, + 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000, + 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000, + 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000, + 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000, + 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000, + 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000, + 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000, + 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000, + 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000, + 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000, + 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000, + 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000, + 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000, + 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000, + 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000, + 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000, + 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000, + 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000, + 0x8def022d00000000}; + +#else /* W == 4 */ + +local const z_word_t FAR crc_big_table[] = { + 0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, + 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, + 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, + 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, + 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, + 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, + 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, + 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, + 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, + 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, + 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, + 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, + 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, + 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, + 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, + 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, + 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, + 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, + 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, + 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, + 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, + 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, + 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, + 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, + 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, + 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, + 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, + 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, + 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, + 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, + 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, + 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, + 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, + 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, + 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, + 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, + 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, + 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, + 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, + 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, + 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, + 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, + 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, + 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, + 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, + 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, + 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, + 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, + 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, + 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, + 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, + 0x8def022d}; + +#endif + +#if N == 1 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, + 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b, + 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, + 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, + 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e, + 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, + 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, + 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, + 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719, + 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3, + 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa, + 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, + 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed, + 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, + 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25, + 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041, + 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, + 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, + 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, + 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758, + 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e, + 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, + 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed, + 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, + 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, + 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544, + 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, + 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c, + 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1, + 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, + 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, + 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, + 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976, + 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7, + 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, + 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, + 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12, + 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, + 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a, + 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e, + 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278, + 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682, + 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, + 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a, + 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561, + 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05, + 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9, + 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, + 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, + 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, + 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, + 0x264b06e6}, + {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, + 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3, + 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, + 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, + 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9, + 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, + 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, + 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712, + 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8, + 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6, + 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, + 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, + 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579, + 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, + 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37, + 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590, + 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, + 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, + 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, + 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678, + 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282, + 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, + 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, + 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, + 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, + 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146, + 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, + 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, + 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c, + 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, + 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, + 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, + 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d, + 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd, + 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, + 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, + 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7, + 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, + 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, + 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105, + 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff, + 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1, + 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, + 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, + 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617, + 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, + 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959, + 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, + 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, + 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a, + 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184, + 0x92364a30}, + {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, + 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8, + 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, + 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, + 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6, + 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, + 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d, + 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, + 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d, + 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408, + 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, + 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, + 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c, + 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, + 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a, + 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9, + 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, + 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, + 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, + 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4, + 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37, + 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, + 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca, + 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, + 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, + 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, + 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, + 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, + 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643, + 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, + 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, + 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, + 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8, + 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026, + 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, + 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, + 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118, + 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, + 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, + 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c, + 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf, + 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, + 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, + 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec, + 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82, + 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, + 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, + 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, + 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, + 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1, + 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869, + 0xe4c4abcc}, + {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, + 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271, + 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, + 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, + 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43, + 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, + 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, + 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314, + 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205, + 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136, + 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, + 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, + 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849, + 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, + 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8, + 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98, + 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, + 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba, + 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, + 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d, + 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c, + 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, + 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, + 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, + 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, + 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922, + 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532, + 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, + 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710, + 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, + 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, + 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, + 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956, + 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7, + 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, + 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, + 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5, + 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, + 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb, + 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb, + 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da, + 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, + 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, + 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48, + 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df, + 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, + 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, + 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, + 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, + 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c, + 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, + 0xca64c78c}, + {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, + 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, + 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, + 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, + 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, + 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, + 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, + 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, + 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, + 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, + 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, + 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, + 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, + 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, + 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, + 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, + 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, + 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, + 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, + 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, + 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, + 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, + 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, + 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, + 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, + 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, + 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, + 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, + 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, + 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, + 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, + 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, + 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, + 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, + 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, + 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, + 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, + 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, + 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, + 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, + 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, + 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, + 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, + 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, + 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, + 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, + 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, + 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, + 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, + 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, + 0xde0506f1}, + {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, + 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, + 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, + 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, + 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, + 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, + 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, + 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, + 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, + 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, + 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, + 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, + 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, + 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, + 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, + 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, + 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, + 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, + 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, + 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, + 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, + 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, + 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, + 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, + 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, + 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, + 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, + 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, + 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, + 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, + 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, + 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, + 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, + 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, + 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, + 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, + 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, + 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, + 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, + 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, + 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, + 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, + 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, + 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, + 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, + 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, + 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, + 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, + 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, + 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, + 0xbe9834ed}, + {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, + 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, + 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, + 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, + 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, + 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, + 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, + 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, + 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, + 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, + 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, + 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, + 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, + 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, + 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, + 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, + 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, + 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, + 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, + 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, + 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, + 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, + 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, + 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, + 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, + 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, + 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, + 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, + 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, + 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, + 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, + 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, + 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, + 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, + 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, + 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, + 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, + 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, + 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, + 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, + 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, + 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, + 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, + 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, + 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, + 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, + 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, + 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, + 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, + 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, + 0x9324fd72}, + {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000, + 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000, + 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000, + 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000, + 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000, + 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000, + 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000, + 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000, + 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000, + 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000, + 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000, + 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000, + 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000, + 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000, + 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000, + 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000, + 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000, + 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000, + 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000, + 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000, + 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000, + 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000, + 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000, + 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000, + 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000, + 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000, + 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000, + 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000, + 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000, + 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000, + 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000, + 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000, + 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000, + 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000, + 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000, + 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000, + 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000, + 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000, + 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000, + 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000, + 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000, + 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000, + 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000, + 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000, + 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000, + 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000, + 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000, + 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000, + 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000, + 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000, + 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000, + 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000, + 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000, + 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000, + 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000, + 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000, + 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000, + 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000, + 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000, + 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000, + 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000, + 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000, + 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000, + 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000, + 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000, + 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000, + 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000, + 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000, + 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000, + 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000, + 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000, + 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000, + 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000, + 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000, + 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000, + 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000, + 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000, + 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000, + 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000, + 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000, + 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000, + 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000, + 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000, + 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000, + 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000, + 0x8def022d00000000}, + {0x0000000000000000, 0x41311b1900000000, 0x8262363200000000, + 0xc3532d2b00000000, 0x04c56c6400000000, 0x45f4777d00000000, + 0x86a75a5600000000, 0xc796414f00000000, 0x088ad9c800000000, + 0x49bbc2d100000000, 0x8ae8effa00000000, 0xcbd9f4e300000000, + 0x0c4fb5ac00000000, 0x4d7eaeb500000000, 0x8e2d839e00000000, + 0xcf1c988700000000, 0x5112c24a00000000, 0x1023d95300000000, + 0xd370f47800000000, 0x9241ef6100000000, 0x55d7ae2e00000000, + 0x14e6b53700000000, 0xd7b5981c00000000, 0x9684830500000000, + 0x59981b8200000000, 0x18a9009b00000000, 0xdbfa2db000000000, + 0x9acb36a900000000, 0x5d5d77e600000000, 0x1c6c6cff00000000, + 0xdf3f41d400000000, 0x9e0e5acd00000000, 0xa224849500000000, + 0xe3159f8c00000000, 0x2046b2a700000000, 0x6177a9be00000000, + 0xa6e1e8f100000000, 0xe7d0f3e800000000, 0x2483dec300000000, + 0x65b2c5da00000000, 0xaaae5d5d00000000, 0xeb9f464400000000, + 0x28cc6b6f00000000, 0x69fd707600000000, 0xae6b313900000000, + 0xef5a2a2000000000, 0x2c09070b00000000, 0x6d381c1200000000, + 0xf33646df00000000, 0xb2075dc600000000, 0x715470ed00000000, + 0x30656bf400000000, 0xf7f32abb00000000, 0xb6c231a200000000, + 0x75911c8900000000, 0x34a0079000000000, 0xfbbc9f1700000000, + 0xba8d840e00000000, 0x79dea92500000000, 0x38efb23c00000000, + 0xff79f37300000000, 0xbe48e86a00000000, 0x7d1bc54100000000, + 0x3c2ade5800000000, 0x054f79f000000000, 0x447e62e900000000, + 0x872d4fc200000000, 0xc61c54db00000000, 0x018a159400000000, + 0x40bb0e8d00000000, 0x83e823a600000000, 0xc2d938bf00000000, + 0x0dc5a03800000000, 0x4cf4bb2100000000, 0x8fa7960a00000000, + 0xce968d1300000000, 0x0900cc5c00000000, 0x4831d74500000000, + 0x8b62fa6e00000000, 0xca53e17700000000, 0x545dbbba00000000, + 0x156ca0a300000000, 0xd63f8d8800000000, 0x970e969100000000, + 0x5098d7de00000000, 0x11a9ccc700000000, 0xd2fae1ec00000000, + 0x93cbfaf500000000, 0x5cd7627200000000, 0x1de6796b00000000, + 0xdeb5544000000000, 0x9f844f5900000000, 0x58120e1600000000, + 0x1923150f00000000, 0xda70382400000000, 0x9b41233d00000000, + 0xa76bfd6500000000, 0xe65ae67c00000000, 0x2509cb5700000000, + 0x6438d04e00000000, 0xa3ae910100000000, 0xe29f8a1800000000, + 0x21cca73300000000, 0x60fdbc2a00000000, 0xafe124ad00000000, + 0xeed03fb400000000, 0x2d83129f00000000, 0x6cb2098600000000, + 0xab2448c900000000, 0xea1553d000000000, 0x29467efb00000000, + 0x687765e200000000, 0xf6793f2f00000000, 0xb748243600000000, + 0x741b091d00000000, 0x352a120400000000, 0xf2bc534b00000000, + 0xb38d485200000000, 0x70de657900000000, 0x31ef7e6000000000, + 0xfef3e6e700000000, 0xbfc2fdfe00000000, 0x7c91d0d500000000, + 0x3da0cbcc00000000, 0xfa368a8300000000, 0xbb07919a00000000, + 0x7854bcb100000000, 0x3965a7a800000000, 0x4b98833b00000000, + 0x0aa9982200000000, 0xc9fab50900000000, 0x88cbae1000000000, + 0x4f5def5f00000000, 0x0e6cf44600000000, 0xcd3fd96d00000000, + 0x8c0ec27400000000, 0x43125af300000000, 0x022341ea00000000, + 0xc1706cc100000000, 0x804177d800000000, 0x47d7369700000000, + 0x06e62d8e00000000, 0xc5b500a500000000, 0x84841bbc00000000, + 0x1a8a417100000000, 0x5bbb5a6800000000, 0x98e8774300000000, + 0xd9d96c5a00000000, 0x1e4f2d1500000000, 0x5f7e360c00000000, + 0x9c2d1b2700000000, 0xdd1c003e00000000, 0x120098b900000000, + 0x533183a000000000, 0x9062ae8b00000000, 0xd153b59200000000, + 0x16c5f4dd00000000, 0x57f4efc400000000, 0x94a7c2ef00000000, + 0xd596d9f600000000, 0xe9bc07ae00000000, 0xa88d1cb700000000, + 0x6bde319c00000000, 0x2aef2a8500000000, 0xed796bca00000000, + 0xac4870d300000000, 0x6f1b5df800000000, 0x2e2a46e100000000, + 0xe136de6600000000, 0xa007c57f00000000, 0x6354e85400000000, + 0x2265f34d00000000, 0xe5f3b20200000000, 0xa4c2a91b00000000, + 0x6791843000000000, 0x26a09f2900000000, 0xb8aec5e400000000, + 0xf99fdefd00000000, 0x3accf3d600000000, 0x7bfde8cf00000000, + 0xbc6ba98000000000, 0xfd5ab29900000000, 0x3e099fb200000000, + 0x7f3884ab00000000, 0xb0241c2c00000000, 0xf115073500000000, + 0x32462a1e00000000, 0x7377310700000000, 0xb4e1704800000000, + 0xf5d06b5100000000, 0x3683467a00000000, 0x77b25d6300000000, + 0x4ed7facb00000000, 0x0fe6e1d200000000, 0xccb5ccf900000000, + 0x8d84d7e000000000, 0x4a1296af00000000, 0x0b238db600000000, + 0xc870a09d00000000, 0x8941bb8400000000, 0x465d230300000000, + 0x076c381a00000000, 0xc43f153100000000, 0x850e0e2800000000, + 0x42984f6700000000, 0x03a9547e00000000, 0xc0fa795500000000, + 0x81cb624c00000000, 0x1fc5388100000000, 0x5ef4239800000000, + 0x9da70eb300000000, 0xdc9615aa00000000, 0x1b0054e500000000, + 0x5a314ffc00000000, 0x996262d700000000, 0xd85379ce00000000, + 0x174fe14900000000, 0x567efa5000000000, 0x952dd77b00000000, + 0xd41ccc6200000000, 0x138a8d2d00000000, 0x52bb963400000000, + 0x91e8bb1f00000000, 0xd0d9a00600000000, 0xecf37e5e00000000, + 0xadc2654700000000, 0x6e91486c00000000, 0x2fa0537500000000, + 0xe836123a00000000, 0xa907092300000000, 0x6a54240800000000, + 0x2b653f1100000000, 0xe479a79600000000, 0xa548bc8f00000000, + 0x661b91a400000000, 0x272a8abd00000000, 0xe0bccbf200000000, + 0xa18dd0eb00000000, 0x62defdc000000000, 0x23efe6d900000000, + 0xbde1bc1400000000, 0xfcd0a70d00000000, 0x3f838a2600000000, + 0x7eb2913f00000000, 0xb924d07000000000, 0xf815cb6900000000, + 0x3b46e64200000000, 0x7a77fd5b00000000, 0xb56b65dc00000000, + 0xf45a7ec500000000, 0x370953ee00000000, 0x763848f700000000, + 0xb1ae09b800000000, 0xf09f12a100000000, 0x33cc3f8a00000000, + 0x72fd249300000000}, + {0x0000000000000000, 0x376ac20100000000, 0x6ed4840300000000, + 0x59be460200000000, 0xdca8090700000000, 0xebc2cb0600000000, + 0xb27c8d0400000000, 0x85164f0500000000, 0xb851130e00000000, + 0x8f3bd10f00000000, 0xd685970d00000000, 0xe1ef550c00000000, + 0x64f91a0900000000, 0x5393d80800000000, 0x0a2d9e0a00000000, + 0x3d475c0b00000000, 0x70a3261c00000000, 0x47c9e41d00000000, + 0x1e77a21f00000000, 0x291d601e00000000, 0xac0b2f1b00000000, + 0x9b61ed1a00000000, 0xc2dfab1800000000, 0xf5b5691900000000, + 0xc8f2351200000000, 0xff98f71300000000, 0xa626b11100000000, + 0x914c731000000000, 0x145a3c1500000000, 0x2330fe1400000000, + 0x7a8eb81600000000, 0x4de47a1700000000, 0xe0464d3800000000, + 0xd72c8f3900000000, 0x8e92c93b00000000, 0xb9f80b3a00000000, + 0x3cee443f00000000, 0x0b84863e00000000, 0x523ac03c00000000, + 0x6550023d00000000, 0x58175e3600000000, 0x6f7d9c3700000000, + 0x36c3da3500000000, 0x01a9183400000000, 0x84bf573100000000, + 0xb3d5953000000000, 0xea6bd33200000000, 0xdd01113300000000, + 0x90e56b2400000000, 0xa78fa92500000000, 0xfe31ef2700000000, + 0xc95b2d2600000000, 0x4c4d622300000000, 0x7b27a02200000000, + 0x2299e62000000000, 0x15f3242100000000, 0x28b4782a00000000, + 0x1fdeba2b00000000, 0x4660fc2900000000, 0x710a3e2800000000, + 0xf41c712d00000000, 0xc376b32c00000000, 0x9ac8f52e00000000, + 0xada2372f00000000, 0xc08d9a7000000000, 0xf7e7587100000000, + 0xae591e7300000000, 0x9933dc7200000000, 0x1c25937700000000, + 0x2b4f517600000000, 0x72f1177400000000, 0x459bd57500000000, + 0x78dc897e00000000, 0x4fb64b7f00000000, 0x16080d7d00000000, + 0x2162cf7c00000000, 0xa474807900000000, 0x931e427800000000, + 0xcaa0047a00000000, 0xfdcac67b00000000, 0xb02ebc6c00000000, + 0x87447e6d00000000, 0xdefa386f00000000, 0xe990fa6e00000000, + 0x6c86b56b00000000, 0x5bec776a00000000, 0x0252316800000000, + 0x3538f36900000000, 0x087faf6200000000, 0x3f156d6300000000, + 0x66ab2b6100000000, 0x51c1e96000000000, 0xd4d7a66500000000, + 0xe3bd646400000000, 0xba03226600000000, 0x8d69e06700000000, + 0x20cbd74800000000, 0x17a1154900000000, 0x4e1f534b00000000, + 0x7975914a00000000, 0xfc63de4f00000000, 0xcb091c4e00000000, + 0x92b75a4c00000000, 0xa5dd984d00000000, 0x989ac44600000000, + 0xaff0064700000000, 0xf64e404500000000, 0xc124824400000000, + 0x4432cd4100000000, 0x73580f4000000000, 0x2ae6494200000000, + 0x1d8c8b4300000000, 0x5068f15400000000, 0x6702335500000000, + 0x3ebc755700000000, 0x09d6b75600000000, 0x8cc0f85300000000, + 0xbbaa3a5200000000, 0xe2147c5000000000, 0xd57ebe5100000000, + 0xe839e25a00000000, 0xdf53205b00000000, 0x86ed665900000000, + 0xb187a45800000000, 0x3491eb5d00000000, 0x03fb295c00000000, + 0x5a456f5e00000000, 0x6d2fad5f00000000, 0x801b35e100000000, + 0xb771f7e000000000, 0xeecfb1e200000000, 0xd9a573e300000000, + 0x5cb33ce600000000, 0x6bd9fee700000000, 0x3267b8e500000000, + 0x050d7ae400000000, 0x384a26ef00000000, 0x0f20e4ee00000000, + 0x569ea2ec00000000, 0x61f460ed00000000, 0xe4e22fe800000000, + 0xd388ede900000000, 0x8a36abeb00000000, 0xbd5c69ea00000000, + 0xf0b813fd00000000, 0xc7d2d1fc00000000, 0x9e6c97fe00000000, + 0xa90655ff00000000, 0x2c101afa00000000, 0x1b7ad8fb00000000, + 0x42c49ef900000000, 0x75ae5cf800000000, 0x48e900f300000000, + 0x7f83c2f200000000, 0x263d84f000000000, 0x115746f100000000, + 0x944109f400000000, 0xa32bcbf500000000, 0xfa958df700000000, + 0xcdff4ff600000000, 0x605d78d900000000, 0x5737bad800000000, + 0x0e89fcda00000000, 0x39e33edb00000000, 0xbcf571de00000000, + 0x8b9fb3df00000000, 0xd221f5dd00000000, 0xe54b37dc00000000, + 0xd80c6bd700000000, 0xef66a9d600000000, 0xb6d8efd400000000, + 0x81b22dd500000000, 0x04a462d000000000, 0x33cea0d100000000, + 0x6a70e6d300000000, 0x5d1a24d200000000, 0x10fe5ec500000000, + 0x27949cc400000000, 0x7e2adac600000000, 0x494018c700000000, + 0xcc5657c200000000, 0xfb3c95c300000000, 0xa282d3c100000000, + 0x95e811c000000000, 0xa8af4dcb00000000, 0x9fc58fca00000000, + 0xc67bc9c800000000, 0xf1110bc900000000, 0x740744cc00000000, + 0x436d86cd00000000, 0x1ad3c0cf00000000, 0x2db902ce00000000, + 0x4096af9100000000, 0x77fc6d9000000000, 0x2e422b9200000000, + 0x1928e99300000000, 0x9c3ea69600000000, 0xab54649700000000, + 0xf2ea229500000000, 0xc580e09400000000, 0xf8c7bc9f00000000, + 0xcfad7e9e00000000, 0x9613389c00000000, 0xa179fa9d00000000, + 0x246fb59800000000, 0x1305779900000000, 0x4abb319b00000000, + 0x7dd1f39a00000000, 0x3035898d00000000, 0x075f4b8c00000000, + 0x5ee10d8e00000000, 0x698bcf8f00000000, 0xec9d808a00000000, + 0xdbf7428b00000000, 0x8249048900000000, 0xb523c68800000000, + 0x88649a8300000000, 0xbf0e588200000000, 0xe6b01e8000000000, + 0xd1dadc8100000000, 0x54cc938400000000, 0x63a6518500000000, + 0x3a18178700000000, 0x0d72d58600000000, 0xa0d0e2a900000000, + 0x97ba20a800000000, 0xce0466aa00000000, 0xf96ea4ab00000000, + 0x7c78ebae00000000, 0x4b1229af00000000, 0x12ac6fad00000000, + 0x25c6adac00000000, 0x1881f1a700000000, 0x2feb33a600000000, + 0x765575a400000000, 0x413fb7a500000000, 0xc429f8a000000000, + 0xf3433aa100000000, 0xaafd7ca300000000, 0x9d97bea200000000, + 0xd073c4b500000000, 0xe71906b400000000, 0xbea740b600000000, + 0x89cd82b700000000, 0x0cdbcdb200000000, 0x3bb10fb300000000, + 0x620f49b100000000, 0x55658bb000000000, 0x6822d7bb00000000, + 0x5f4815ba00000000, 0x06f653b800000000, 0x319c91b900000000, + 0xb48adebc00000000, 0x83e01cbd00000000, 0xda5e5abf00000000, + 0xed3498be00000000}, + {0x0000000000000000, 0x6567bcb800000000, 0x8bc809aa00000000, + 0xeeafb51200000000, 0x5797628f00000000, 0x32f0de3700000000, + 0xdc5f6b2500000000, 0xb938d79d00000000, 0xef28b4c500000000, + 0x8a4f087d00000000, 0x64e0bd6f00000000, 0x018701d700000000, + 0xb8bfd64a00000000, 0xddd86af200000000, 0x3377dfe000000000, + 0x5610635800000000, 0x9f57195000000000, 0xfa30a5e800000000, + 0x149f10fa00000000, 0x71f8ac4200000000, 0xc8c07bdf00000000, + 0xada7c76700000000, 0x4308727500000000, 0x266fcecd00000000, + 0x707fad9500000000, 0x1518112d00000000, 0xfbb7a43f00000000, + 0x9ed0188700000000, 0x27e8cf1a00000000, 0x428f73a200000000, + 0xac20c6b000000000, 0xc9477a0800000000, 0x3eaf32a000000000, + 0x5bc88e1800000000, 0xb5673b0a00000000, 0xd00087b200000000, + 0x6938502f00000000, 0x0c5fec9700000000, 0xe2f0598500000000, + 0x8797e53d00000000, 0xd187866500000000, 0xb4e03add00000000, + 0x5a4f8fcf00000000, 0x3f28337700000000, 0x8610e4ea00000000, + 0xe377585200000000, 0x0dd8ed4000000000, 0x68bf51f800000000, + 0xa1f82bf000000000, 0xc49f974800000000, 0x2a30225a00000000, + 0x4f579ee200000000, 0xf66f497f00000000, 0x9308f5c700000000, + 0x7da740d500000000, 0x18c0fc6d00000000, 0x4ed09f3500000000, + 0x2bb7238d00000000, 0xc518969f00000000, 0xa07f2a2700000000, + 0x1947fdba00000000, 0x7c20410200000000, 0x928ff41000000000, + 0xf7e848a800000000, 0x3d58149b00000000, 0x583fa82300000000, + 0xb6901d3100000000, 0xd3f7a18900000000, 0x6acf761400000000, + 0x0fa8caac00000000, 0xe1077fbe00000000, 0x8460c30600000000, + 0xd270a05e00000000, 0xb7171ce600000000, 0x59b8a9f400000000, + 0x3cdf154c00000000, 0x85e7c2d100000000, 0xe0807e6900000000, + 0x0e2fcb7b00000000, 0x6b4877c300000000, 0xa20f0dcb00000000, + 0xc768b17300000000, 0x29c7046100000000, 0x4ca0b8d900000000, + 0xf5986f4400000000, 0x90ffd3fc00000000, 0x7e5066ee00000000, + 0x1b37da5600000000, 0x4d27b90e00000000, 0x284005b600000000, + 0xc6efb0a400000000, 0xa3880c1c00000000, 0x1ab0db8100000000, + 0x7fd7673900000000, 0x9178d22b00000000, 0xf41f6e9300000000, + 0x03f7263b00000000, 0x66909a8300000000, 0x883f2f9100000000, + 0xed58932900000000, 0x546044b400000000, 0x3107f80c00000000, + 0xdfa84d1e00000000, 0xbacff1a600000000, 0xecdf92fe00000000, + 0x89b82e4600000000, 0x67179b5400000000, 0x027027ec00000000, + 0xbb48f07100000000, 0xde2f4cc900000000, 0x3080f9db00000000, + 0x55e7456300000000, 0x9ca03f6b00000000, 0xf9c783d300000000, + 0x176836c100000000, 0x720f8a7900000000, 0xcb375de400000000, + 0xae50e15c00000000, 0x40ff544e00000000, 0x2598e8f600000000, + 0x73888bae00000000, 0x16ef371600000000, 0xf840820400000000, + 0x9d273ebc00000000, 0x241fe92100000000, 0x4178559900000000, + 0xafd7e08b00000000, 0xcab05c3300000000, 0x3bb659ed00000000, + 0x5ed1e55500000000, 0xb07e504700000000, 0xd519ecff00000000, + 0x6c213b6200000000, 0x094687da00000000, 0xe7e932c800000000, + 0x828e8e7000000000, 0xd49eed2800000000, 0xb1f9519000000000, + 0x5f56e48200000000, 0x3a31583a00000000, 0x83098fa700000000, + 0xe66e331f00000000, 0x08c1860d00000000, 0x6da63ab500000000, + 0xa4e140bd00000000, 0xc186fc0500000000, 0x2f29491700000000, + 0x4a4ef5af00000000, 0xf376223200000000, 0x96119e8a00000000, + 0x78be2b9800000000, 0x1dd9972000000000, 0x4bc9f47800000000, + 0x2eae48c000000000, 0xc001fdd200000000, 0xa566416a00000000, + 0x1c5e96f700000000, 0x79392a4f00000000, 0x97969f5d00000000, + 0xf2f123e500000000, 0x05196b4d00000000, 0x607ed7f500000000, + 0x8ed162e700000000, 0xebb6de5f00000000, 0x528e09c200000000, + 0x37e9b57a00000000, 0xd946006800000000, 0xbc21bcd000000000, + 0xea31df8800000000, 0x8f56633000000000, 0x61f9d62200000000, + 0x049e6a9a00000000, 0xbda6bd0700000000, 0xd8c101bf00000000, + 0x366eb4ad00000000, 0x5309081500000000, 0x9a4e721d00000000, + 0xff29cea500000000, 0x11867bb700000000, 0x74e1c70f00000000, + 0xcdd9109200000000, 0xa8beac2a00000000, 0x4611193800000000, + 0x2376a58000000000, 0x7566c6d800000000, 0x10017a6000000000, + 0xfeaecf7200000000, 0x9bc973ca00000000, 0x22f1a45700000000, + 0x479618ef00000000, 0xa939adfd00000000, 0xcc5e114500000000, + 0x06ee4d7600000000, 0x6389f1ce00000000, 0x8d2644dc00000000, + 0xe841f86400000000, 0x51792ff900000000, 0x341e934100000000, + 0xdab1265300000000, 0xbfd69aeb00000000, 0xe9c6f9b300000000, + 0x8ca1450b00000000, 0x620ef01900000000, 0x07694ca100000000, + 0xbe519b3c00000000, 0xdb36278400000000, 0x3599929600000000, + 0x50fe2e2e00000000, 0x99b9542600000000, 0xfcdee89e00000000, + 0x12715d8c00000000, 0x7716e13400000000, 0xce2e36a900000000, + 0xab498a1100000000, 0x45e63f0300000000, 0x208183bb00000000, + 0x7691e0e300000000, 0x13f65c5b00000000, 0xfd59e94900000000, + 0x983e55f100000000, 0x2106826c00000000, 0x44613ed400000000, + 0xaace8bc600000000, 0xcfa9377e00000000, 0x38417fd600000000, + 0x5d26c36e00000000, 0xb389767c00000000, 0xd6eecac400000000, + 0x6fd61d5900000000, 0x0ab1a1e100000000, 0xe41e14f300000000, + 0x8179a84b00000000, 0xd769cb1300000000, 0xb20e77ab00000000, + 0x5ca1c2b900000000, 0x39c67e0100000000, 0x80fea99c00000000, + 0xe599152400000000, 0x0b36a03600000000, 0x6e511c8e00000000, + 0xa716668600000000, 0xc271da3e00000000, 0x2cde6f2c00000000, + 0x49b9d39400000000, 0xf081040900000000, 0x95e6b8b100000000, + 0x7b490da300000000, 0x1e2eb11b00000000, 0x483ed24300000000, + 0x2d596efb00000000, 0xc3f6dbe900000000, 0xa691675100000000, + 0x1fa9b0cc00000000, 0x7ace0c7400000000, 0x9461b96600000000, + 0xf10605de00000000}, + {0x0000000000000000, 0xb029603d00000000, 0x6053c07a00000000, + 0xd07aa04700000000, 0xc0a680f500000000, 0x708fe0c800000000, + 0xa0f5408f00000000, 0x10dc20b200000000, 0xc14b703000000000, + 0x7162100d00000000, 0xa118b04a00000000, 0x1131d07700000000, + 0x01edf0c500000000, 0xb1c490f800000000, 0x61be30bf00000000, + 0xd197508200000000, 0x8297e06000000000, 0x32be805d00000000, + 0xe2c4201a00000000, 0x52ed402700000000, 0x4231609500000000, + 0xf21800a800000000, 0x2262a0ef00000000, 0x924bc0d200000000, + 0x43dc905000000000, 0xf3f5f06d00000000, 0x238f502a00000000, + 0x93a6301700000000, 0x837a10a500000000, 0x3353709800000000, + 0xe329d0df00000000, 0x5300b0e200000000, 0x042fc1c100000000, + 0xb406a1fc00000000, 0x647c01bb00000000, 0xd455618600000000, + 0xc489413400000000, 0x74a0210900000000, 0xa4da814e00000000, + 0x14f3e17300000000, 0xc564b1f100000000, 0x754dd1cc00000000, + 0xa537718b00000000, 0x151e11b600000000, 0x05c2310400000000, + 0xb5eb513900000000, 0x6591f17e00000000, 0xd5b8914300000000, + 0x86b821a100000000, 0x3691419c00000000, 0xe6ebe1db00000000, + 0x56c281e600000000, 0x461ea15400000000, 0xf637c16900000000, + 0x264d612e00000000, 0x9664011300000000, 0x47f3519100000000, + 0xf7da31ac00000000, 0x27a091eb00000000, 0x9789f1d600000000, + 0x8755d16400000000, 0x377cb15900000000, 0xe706111e00000000, + 0x572f712300000000, 0x4958f35800000000, 0xf971936500000000, + 0x290b332200000000, 0x9922531f00000000, 0x89fe73ad00000000, + 0x39d7139000000000, 0xe9adb3d700000000, 0x5984d3ea00000000, + 0x8813836800000000, 0x383ae35500000000, 0xe840431200000000, + 0x5869232f00000000, 0x48b5039d00000000, 0xf89c63a000000000, + 0x28e6c3e700000000, 0x98cfa3da00000000, 0xcbcf133800000000, + 0x7be6730500000000, 0xab9cd34200000000, 0x1bb5b37f00000000, + 0x0b6993cd00000000, 0xbb40f3f000000000, 0x6b3a53b700000000, + 0xdb13338a00000000, 0x0a84630800000000, 0xbaad033500000000, + 0x6ad7a37200000000, 0xdafec34f00000000, 0xca22e3fd00000000, + 0x7a0b83c000000000, 0xaa71238700000000, 0x1a5843ba00000000, + 0x4d77329900000000, 0xfd5e52a400000000, 0x2d24f2e300000000, + 0x9d0d92de00000000, 0x8dd1b26c00000000, 0x3df8d25100000000, + 0xed82721600000000, 0x5dab122b00000000, 0x8c3c42a900000000, + 0x3c15229400000000, 0xec6f82d300000000, 0x5c46e2ee00000000, + 0x4c9ac25c00000000, 0xfcb3a26100000000, 0x2cc9022600000000, + 0x9ce0621b00000000, 0xcfe0d2f900000000, 0x7fc9b2c400000000, + 0xafb3128300000000, 0x1f9a72be00000000, 0x0f46520c00000000, + 0xbf6f323100000000, 0x6f15927600000000, 0xdf3cf24b00000000, + 0x0eaba2c900000000, 0xbe82c2f400000000, 0x6ef862b300000000, + 0xded1028e00000000, 0xce0d223c00000000, 0x7e24420100000000, + 0xae5ee24600000000, 0x1e77827b00000000, 0x92b0e6b100000000, + 0x2299868c00000000, 0xf2e326cb00000000, 0x42ca46f600000000, + 0x5216664400000000, 0xe23f067900000000, 0x3245a63e00000000, + 0x826cc60300000000, 0x53fb968100000000, 0xe3d2f6bc00000000, + 0x33a856fb00000000, 0x838136c600000000, 0x935d167400000000, + 0x2374764900000000, 0xf30ed60e00000000, 0x4327b63300000000, + 0x102706d100000000, 0xa00e66ec00000000, 0x7074c6ab00000000, + 0xc05da69600000000, 0xd081862400000000, 0x60a8e61900000000, + 0xb0d2465e00000000, 0x00fb266300000000, 0xd16c76e100000000, + 0x614516dc00000000, 0xb13fb69b00000000, 0x0116d6a600000000, + 0x11caf61400000000, 0xa1e3962900000000, 0x7199366e00000000, + 0xc1b0565300000000, 0x969f277000000000, 0x26b6474d00000000, + 0xf6cce70a00000000, 0x46e5873700000000, 0x5639a78500000000, + 0xe610c7b800000000, 0x366a67ff00000000, 0x864307c200000000, + 0x57d4574000000000, 0xe7fd377d00000000, 0x3787973a00000000, + 0x87aef70700000000, 0x9772d7b500000000, 0x275bb78800000000, + 0xf72117cf00000000, 0x470877f200000000, 0x1408c71000000000, + 0xa421a72d00000000, 0x745b076a00000000, 0xc472675700000000, + 0xd4ae47e500000000, 0x648727d800000000, 0xb4fd879f00000000, + 0x04d4e7a200000000, 0xd543b72000000000, 0x656ad71d00000000, + 0xb510775a00000000, 0x0539176700000000, 0x15e537d500000000, + 0xa5cc57e800000000, 0x75b6f7af00000000, 0xc59f979200000000, + 0xdbe815e900000000, 0x6bc175d400000000, 0xbbbbd59300000000, + 0x0b92b5ae00000000, 0x1b4e951c00000000, 0xab67f52100000000, + 0x7b1d556600000000, 0xcb34355b00000000, 0x1aa365d900000000, + 0xaa8a05e400000000, 0x7af0a5a300000000, 0xcad9c59e00000000, + 0xda05e52c00000000, 0x6a2c851100000000, 0xba56255600000000, + 0x0a7f456b00000000, 0x597ff58900000000, 0xe95695b400000000, + 0x392c35f300000000, 0x890555ce00000000, 0x99d9757c00000000, + 0x29f0154100000000, 0xf98ab50600000000, 0x49a3d53b00000000, + 0x983485b900000000, 0x281de58400000000, 0xf86745c300000000, + 0x484e25fe00000000, 0x5892054c00000000, 0xe8bb657100000000, + 0x38c1c53600000000, 0x88e8a50b00000000, 0xdfc7d42800000000, + 0x6feeb41500000000, 0xbf94145200000000, 0x0fbd746f00000000, + 0x1f6154dd00000000, 0xaf4834e000000000, 0x7f3294a700000000, + 0xcf1bf49a00000000, 0x1e8ca41800000000, 0xaea5c42500000000, + 0x7edf646200000000, 0xcef6045f00000000, 0xde2a24ed00000000, + 0x6e0344d000000000, 0xbe79e49700000000, 0x0e5084aa00000000, + 0x5d50344800000000, 0xed79547500000000, 0x3d03f43200000000, + 0x8d2a940f00000000, 0x9df6b4bd00000000, 0x2ddfd48000000000, + 0xfda574c700000000, 0x4d8c14fa00000000, 0x9c1b447800000000, + 0x2c32244500000000, 0xfc48840200000000, 0x4c61e43f00000000, + 0x5cbdc48d00000000, 0xec94a4b000000000, 0x3cee04f700000000, + 0x8cc764ca00000000}, + {0x0000000000000000, 0xa5d35ccb00000000, 0x0ba1c84d00000000, + 0xae72948600000000, 0x1642919b00000000, 0xb391cd5000000000, + 0x1de359d600000000, 0xb830051d00000000, 0x6d8253ec00000000, + 0xc8510f2700000000, 0x66239ba100000000, 0xc3f0c76a00000000, + 0x7bc0c27700000000, 0xde139ebc00000000, 0x70610a3a00000000, + 0xd5b256f100000000, 0x9b02d60300000000, 0x3ed18ac800000000, + 0x90a31e4e00000000, 0x3570428500000000, 0x8d40479800000000, + 0x28931b5300000000, 0x86e18fd500000000, 0x2332d31e00000000, + 0xf68085ef00000000, 0x5353d92400000000, 0xfd214da200000000, + 0x58f2116900000000, 0xe0c2147400000000, 0x451148bf00000000, + 0xeb63dc3900000000, 0x4eb080f200000000, 0x3605ac0700000000, + 0x93d6f0cc00000000, 0x3da4644a00000000, 0x9877388100000000, + 0x20473d9c00000000, 0x8594615700000000, 0x2be6f5d100000000, + 0x8e35a91a00000000, 0x5b87ffeb00000000, 0xfe54a32000000000, + 0x502637a600000000, 0xf5f56b6d00000000, 0x4dc56e7000000000, + 0xe81632bb00000000, 0x4664a63d00000000, 0xe3b7faf600000000, + 0xad077a0400000000, 0x08d426cf00000000, 0xa6a6b24900000000, + 0x0375ee8200000000, 0xbb45eb9f00000000, 0x1e96b75400000000, + 0xb0e423d200000000, 0x15377f1900000000, 0xc08529e800000000, + 0x6556752300000000, 0xcb24e1a500000000, 0x6ef7bd6e00000000, + 0xd6c7b87300000000, 0x7314e4b800000000, 0xdd66703e00000000, + 0x78b52cf500000000, 0x6c0a580f00000000, 0xc9d904c400000000, + 0x67ab904200000000, 0xc278cc8900000000, 0x7a48c99400000000, + 0xdf9b955f00000000, 0x71e901d900000000, 0xd43a5d1200000000, + 0x01880be300000000, 0xa45b572800000000, 0x0a29c3ae00000000, + 0xaffa9f6500000000, 0x17ca9a7800000000, 0xb219c6b300000000, + 0x1c6b523500000000, 0xb9b80efe00000000, 0xf7088e0c00000000, + 0x52dbd2c700000000, 0xfca9464100000000, 0x597a1a8a00000000, + 0xe14a1f9700000000, 0x4499435c00000000, 0xeaebd7da00000000, + 0x4f388b1100000000, 0x9a8adde000000000, 0x3f59812b00000000, + 0x912b15ad00000000, 0x34f8496600000000, 0x8cc84c7b00000000, + 0x291b10b000000000, 0x8769843600000000, 0x22bad8fd00000000, + 0x5a0ff40800000000, 0xffdca8c300000000, 0x51ae3c4500000000, + 0xf47d608e00000000, 0x4c4d659300000000, 0xe99e395800000000, + 0x47ecadde00000000, 0xe23ff11500000000, 0x378da7e400000000, + 0x925efb2f00000000, 0x3c2c6fa900000000, 0x99ff336200000000, + 0x21cf367f00000000, 0x841c6ab400000000, 0x2a6efe3200000000, + 0x8fbda2f900000000, 0xc10d220b00000000, 0x64de7ec000000000, + 0xcaacea4600000000, 0x6f7fb68d00000000, 0xd74fb39000000000, + 0x729cef5b00000000, 0xdcee7bdd00000000, 0x793d271600000000, + 0xac8f71e700000000, 0x095c2d2c00000000, 0xa72eb9aa00000000, + 0x02fde56100000000, 0xbacde07c00000000, 0x1f1ebcb700000000, + 0xb16c283100000000, 0x14bf74fa00000000, 0xd814b01e00000000, + 0x7dc7ecd500000000, 0xd3b5785300000000, 0x7666249800000000, + 0xce56218500000000, 0x6b857d4e00000000, 0xc5f7e9c800000000, + 0x6024b50300000000, 0xb596e3f200000000, 0x1045bf3900000000, + 0xbe372bbf00000000, 0x1be4777400000000, 0xa3d4726900000000, + 0x06072ea200000000, 0xa875ba2400000000, 0x0da6e6ef00000000, + 0x4316661d00000000, 0xe6c53ad600000000, 0x48b7ae5000000000, + 0xed64f29b00000000, 0x5554f78600000000, 0xf087ab4d00000000, + 0x5ef53fcb00000000, 0xfb26630000000000, 0x2e9435f100000000, + 0x8b47693a00000000, 0x2535fdbc00000000, 0x80e6a17700000000, + 0x38d6a46a00000000, 0x9d05f8a100000000, 0x33776c2700000000, + 0x96a430ec00000000, 0xee111c1900000000, 0x4bc240d200000000, + 0xe5b0d45400000000, 0x4063889f00000000, 0xf8538d8200000000, + 0x5d80d14900000000, 0xf3f245cf00000000, 0x5621190400000000, + 0x83934ff500000000, 0x2640133e00000000, 0x883287b800000000, + 0x2de1db7300000000, 0x95d1de6e00000000, 0x300282a500000000, + 0x9e70162300000000, 0x3ba34ae800000000, 0x7513ca1a00000000, + 0xd0c096d100000000, 0x7eb2025700000000, 0xdb615e9c00000000, + 0x63515b8100000000, 0xc682074a00000000, 0x68f093cc00000000, + 0xcd23cf0700000000, 0x189199f600000000, 0xbd42c53d00000000, + 0x133051bb00000000, 0xb6e30d7000000000, 0x0ed3086d00000000, + 0xab0054a600000000, 0x0572c02000000000, 0xa0a19ceb00000000, + 0xb41ee81100000000, 0x11cdb4da00000000, 0xbfbf205c00000000, + 0x1a6c7c9700000000, 0xa25c798a00000000, 0x078f254100000000, + 0xa9fdb1c700000000, 0x0c2eed0c00000000, 0xd99cbbfd00000000, + 0x7c4fe73600000000, 0xd23d73b000000000, 0x77ee2f7b00000000, + 0xcfde2a6600000000, 0x6a0d76ad00000000, 0xc47fe22b00000000, + 0x61acbee000000000, 0x2f1c3e1200000000, 0x8acf62d900000000, + 0x24bdf65f00000000, 0x816eaa9400000000, 0x395eaf8900000000, + 0x9c8df34200000000, 0x32ff67c400000000, 0x972c3b0f00000000, + 0x429e6dfe00000000, 0xe74d313500000000, 0x493fa5b300000000, + 0xececf97800000000, 0x54dcfc6500000000, 0xf10fa0ae00000000, + 0x5f7d342800000000, 0xfaae68e300000000, 0x821b441600000000, + 0x27c818dd00000000, 0x89ba8c5b00000000, 0x2c69d09000000000, + 0x9459d58d00000000, 0x318a894600000000, 0x9ff81dc000000000, + 0x3a2b410b00000000, 0xef9917fa00000000, 0x4a4a4b3100000000, + 0xe438dfb700000000, 0x41eb837c00000000, 0xf9db866100000000, + 0x5c08daaa00000000, 0xf27a4e2c00000000, 0x57a912e700000000, + 0x1919921500000000, 0xbccacede00000000, 0x12b85a5800000000, + 0xb76b069300000000, 0x0f5b038e00000000, 0xaa885f4500000000, + 0x04facbc300000000, 0xa129970800000000, 0x749bc1f900000000, + 0xd1489d3200000000, 0x7f3a09b400000000, 0xdae9557f00000000, + 0x62d9506200000000, 0xc70a0ca900000000, 0x6978982f00000000, + 0xccabc4e400000000}, + {0x0000000000000000, 0xb40b77a600000000, 0x29119f9700000000, + 0x9d1ae83100000000, 0x13244ff400000000, 0xa72f385200000000, + 0x3a35d06300000000, 0x8e3ea7c500000000, 0x674eef3300000000, + 0xd345989500000000, 0x4e5f70a400000000, 0xfa54070200000000, + 0x746aa0c700000000, 0xc061d76100000000, 0x5d7b3f5000000000, + 0xe97048f600000000, 0xce9cde6700000000, 0x7a97a9c100000000, + 0xe78d41f000000000, 0x5386365600000000, 0xddb8919300000000, + 0x69b3e63500000000, 0xf4a90e0400000000, 0x40a279a200000000, + 0xa9d2315400000000, 0x1dd946f200000000, 0x80c3aec300000000, + 0x34c8d96500000000, 0xbaf67ea000000000, 0x0efd090600000000, + 0x93e7e13700000000, 0x27ec969100000000, 0x9c39bdcf00000000, + 0x2832ca6900000000, 0xb528225800000000, 0x012355fe00000000, + 0x8f1df23b00000000, 0x3b16859d00000000, 0xa60c6dac00000000, + 0x12071a0a00000000, 0xfb7752fc00000000, 0x4f7c255a00000000, + 0xd266cd6b00000000, 0x666dbacd00000000, 0xe8531d0800000000, + 0x5c586aae00000000, 0xc142829f00000000, 0x7549f53900000000, + 0x52a563a800000000, 0xe6ae140e00000000, 0x7bb4fc3f00000000, + 0xcfbf8b9900000000, 0x41812c5c00000000, 0xf58a5bfa00000000, + 0x6890b3cb00000000, 0xdc9bc46d00000000, 0x35eb8c9b00000000, + 0x81e0fb3d00000000, 0x1cfa130c00000000, 0xa8f164aa00000000, + 0x26cfc36f00000000, 0x92c4b4c900000000, 0x0fde5cf800000000, + 0xbbd52b5e00000000, 0x79750b4400000000, 0xcd7e7ce200000000, + 0x506494d300000000, 0xe46fe37500000000, 0x6a5144b000000000, + 0xde5a331600000000, 0x4340db2700000000, 0xf74bac8100000000, + 0x1e3be47700000000, 0xaa3093d100000000, 0x372a7be000000000, + 0x83210c4600000000, 0x0d1fab8300000000, 0xb914dc2500000000, + 0x240e341400000000, 0x900543b200000000, 0xb7e9d52300000000, + 0x03e2a28500000000, 0x9ef84ab400000000, 0x2af33d1200000000, + 0xa4cd9ad700000000, 0x10c6ed7100000000, 0x8ddc054000000000, + 0x39d772e600000000, 0xd0a73a1000000000, 0x64ac4db600000000, + 0xf9b6a58700000000, 0x4dbdd22100000000, 0xc38375e400000000, + 0x7788024200000000, 0xea92ea7300000000, 0x5e999dd500000000, + 0xe54cb68b00000000, 0x5147c12d00000000, 0xcc5d291c00000000, + 0x78565eba00000000, 0xf668f97f00000000, 0x42638ed900000000, + 0xdf7966e800000000, 0x6b72114e00000000, 0x820259b800000000, + 0x36092e1e00000000, 0xab13c62f00000000, 0x1f18b18900000000, + 0x9126164c00000000, 0x252d61ea00000000, 0xb83789db00000000, + 0x0c3cfe7d00000000, 0x2bd068ec00000000, 0x9fdb1f4a00000000, + 0x02c1f77b00000000, 0xb6ca80dd00000000, 0x38f4271800000000, + 0x8cff50be00000000, 0x11e5b88f00000000, 0xa5eecf2900000000, + 0x4c9e87df00000000, 0xf895f07900000000, 0x658f184800000000, + 0xd1846fee00000000, 0x5fbac82b00000000, 0xebb1bf8d00000000, + 0x76ab57bc00000000, 0xc2a0201a00000000, 0xf2ea168800000000, + 0x46e1612e00000000, 0xdbfb891f00000000, 0x6ff0feb900000000, + 0xe1ce597c00000000, 0x55c52eda00000000, 0xc8dfc6eb00000000, + 0x7cd4b14d00000000, 0x95a4f9bb00000000, 0x21af8e1d00000000, + 0xbcb5662c00000000, 0x08be118a00000000, 0x8680b64f00000000, + 0x328bc1e900000000, 0xaf9129d800000000, 0x1b9a5e7e00000000, + 0x3c76c8ef00000000, 0x887dbf4900000000, 0x1567577800000000, + 0xa16c20de00000000, 0x2f52871b00000000, 0x9b59f0bd00000000, + 0x0643188c00000000, 0xb2486f2a00000000, 0x5b3827dc00000000, + 0xef33507a00000000, 0x7229b84b00000000, 0xc622cfed00000000, + 0x481c682800000000, 0xfc171f8e00000000, 0x610df7bf00000000, + 0xd506801900000000, 0x6ed3ab4700000000, 0xdad8dce100000000, + 0x47c234d000000000, 0xf3c9437600000000, 0x7df7e4b300000000, + 0xc9fc931500000000, 0x54e67b2400000000, 0xe0ed0c8200000000, + 0x099d447400000000, 0xbd9633d200000000, 0x208cdbe300000000, + 0x9487ac4500000000, 0x1ab90b8000000000, 0xaeb27c2600000000, + 0x33a8941700000000, 0x87a3e3b100000000, 0xa04f752000000000, + 0x1444028600000000, 0x895eeab700000000, 0x3d559d1100000000, + 0xb36b3ad400000000, 0x07604d7200000000, 0x9a7aa54300000000, + 0x2e71d2e500000000, 0xc7019a1300000000, 0x730aedb500000000, + 0xee10058400000000, 0x5a1b722200000000, 0xd425d5e700000000, + 0x602ea24100000000, 0xfd344a7000000000, 0x493f3dd600000000, + 0x8b9f1dcc00000000, 0x3f946a6a00000000, 0xa28e825b00000000, + 0x1685f5fd00000000, 0x98bb523800000000, 0x2cb0259e00000000, + 0xb1aacdaf00000000, 0x05a1ba0900000000, 0xecd1f2ff00000000, + 0x58da855900000000, 0xc5c06d6800000000, 0x71cb1ace00000000, + 0xfff5bd0b00000000, 0x4bfecaad00000000, 0xd6e4229c00000000, + 0x62ef553a00000000, 0x4503c3ab00000000, 0xf108b40d00000000, + 0x6c125c3c00000000, 0xd8192b9a00000000, 0x56278c5f00000000, + 0xe22cfbf900000000, 0x7f3613c800000000, 0xcb3d646e00000000, + 0x224d2c9800000000, 0x96465b3e00000000, 0x0b5cb30f00000000, + 0xbf57c4a900000000, 0x3169636c00000000, 0x856214ca00000000, + 0x1878fcfb00000000, 0xac738b5d00000000, 0x17a6a00300000000, + 0xa3add7a500000000, 0x3eb73f9400000000, 0x8abc483200000000, + 0x0482eff700000000, 0xb089985100000000, 0x2d93706000000000, + 0x999807c600000000, 0x70e84f3000000000, 0xc4e3389600000000, + 0x59f9d0a700000000, 0xedf2a70100000000, 0x63cc00c400000000, + 0xd7c7776200000000, 0x4add9f5300000000, 0xfed6e8f500000000, + 0xd93a7e6400000000, 0x6d3109c200000000, 0xf02be1f300000000, + 0x4420965500000000, 0xca1e319000000000, 0x7e15463600000000, + 0xe30fae0700000000, 0x5704d9a100000000, 0xbe74915700000000, + 0x0a7fe6f100000000, 0x97650ec000000000, 0x236e796600000000, + 0xad50dea300000000, 0x195ba90500000000, 0x8441413400000000, + 0x304a369200000000}, + {0x0000000000000000, 0x9e00aacc00000000, 0x7d07254200000000, + 0xe3078f8e00000000, 0xfa0e4a8400000000, 0x640ee04800000000, + 0x87096fc600000000, 0x1909c50a00000000, 0xb51be5d300000000, + 0x2b1b4f1f00000000, 0xc81cc09100000000, 0x561c6a5d00000000, + 0x4f15af5700000000, 0xd115059b00000000, 0x32128a1500000000, + 0xac1220d900000000, 0x2b31bb7c00000000, 0xb53111b000000000, + 0x56369e3e00000000, 0xc83634f200000000, 0xd13ff1f800000000, + 0x4f3f5b3400000000, 0xac38d4ba00000000, 0x32387e7600000000, + 0x9e2a5eaf00000000, 0x002af46300000000, 0xe32d7bed00000000, + 0x7d2dd12100000000, 0x6424142b00000000, 0xfa24bee700000000, + 0x1923316900000000, 0x87239ba500000000, 0x566276f900000000, + 0xc862dc3500000000, 0x2b6553bb00000000, 0xb565f97700000000, + 0xac6c3c7d00000000, 0x326c96b100000000, 0xd16b193f00000000, + 0x4f6bb3f300000000, 0xe379932a00000000, 0x7d7939e600000000, + 0x9e7eb66800000000, 0x007e1ca400000000, 0x1977d9ae00000000, + 0x8777736200000000, 0x6470fcec00000000, 0xfa70562000000000, + 0x7d53cd8500000000, 0xe353674900000000, 0x0054e8c700000000, + 0x9e54420b00000000, 0x875d870100000000, 0x195d2dcd00000000, + 0xfa5aa24300000000, 0x645a088f00000000, 0xc848285600000000, + 0x5648829a00000000, 0xb54f0d1400000000, 0x2b4fa7d800000000, + 0x324662d200000000, 0xac46c81e00000000, 0x4f41479000000000, + 0xd141ed5c00000000, 0xedc29d2900000000, 0x73c237e500000000, + 0x90c5b86b00000000, 0x0ec512a700000000, 0x17ccd7ad00000000, + 0x89cc7d6100000000, 0x6acbf2ef00000000, 0xf4cb582300000000, + 0x58d978fa00000000, 0xc6d9d23600000000, 0x25de5db800000000, + 0xbbdef77400000000, 0xa2d7327e00000000, 0x3cd798b200000000, + 0xdfd0173c00000000, 0x41d0bdf000000000, 0xc6f3265500000000, + 0x58f38c9900000000, 0xbbf4031700000000, 0x25f4a9db00000000, + 0x3cfd6cd100000000, 0xa2fdc61d00000000, 0x41fa499300000000, + 0xdffae35f00000000, 0x73e8c38600000000, 0xede8694a00000000, + 0x0eefe6c400000000, 0x90ef4c0800000000, 0x89e6890200000000, + 0x17e623ce00000000, 0xf4e1ac4000000000, 0x6ae1068c00000000, + 0xbba0ebd000000000, 0x25a0411c00000000, 0xc6a7ce9200000000, + 0x58a7645e00000000, 0x41aea15400000000, 0xdfae0b9800000000, + 0x3ca9841600000000, 0xa2a92eda00000000, 0x0ebb0e0300000000, + 0x90bba4cf00000000, 0x73bc2b4100000000, 0xedbc818d00000000, + 0xf4b5448700000000, 0x6ab5ee4b00000000, 0x89b261c500000000, + 0x17b2cb0900000000, 0x909150ac00000000, 0x0e91fa6000000000, + 0xed9675ee00000000, 0x7396df2200000000, 0x6a9f1a2800000000, + 0xf49fb0e400000000, 0x17983f6a00000000, 0x899895a600000000, + 0x258ab57f00000000, 0xbb8a1fb300000000, 0x588d903d00000000, + 0xc68d3af100000000, 0xdf84fffb00000000, 0x4184553700000000, + 0xa283dab900000000, 0x3c83707500000000, 0xda853b5300000000, + 0x4485919f00000000, 0xa7821e1100000000, 0x3982b4dd00000000, + 0x208b71d700000000, 0xbe8bdb1b00000000, 0x5d8c549500000000, + 0xc38cfe5900000000, 0x6f9ede8000000000, 0xf19e744c00000000, + 0x1299fbc200000000, 0x8c99510e00000000, 0x9590940400000000, + 0x0b903ec800000000, 0xe897b14600000000, 0x76971b8a00000000, + 0xf1b4802f00000000, 0x6fb42ae300000000, 0x8cb3a56d00000000, + 0x12b30fa100000000, 0x0bbacaab00000000, 0x95ba606700000000, + 0x76bdefe900000000, 0xe8bd452500000000, 0x44af65fc00000000, + 0xdaafcf3000000000, 0x39a840be00000000, 0xa7a8ea7200000000, + 0xbea12f7800000000, 0x20a185b400000000, 0xc3a60a3a00000000, + 0x5da6a0f600000000, 0x8ce74daa00000000, 0x12e7e76600000000, + 0xf1e068e800000000, 0x6fe0c22400000000, 0x76e9072e00000000, + 0xe8e9ade200000000, 0x0bee226c00000000, 0x95ee88a000000000, + 0x39fca87900000000, 0xa7fc02b500000000, 0x44fb8d3b00000000, + 0xdafb27f700000000, 0xc3f2e2fd00000000, 0x5df2483100000000, + 0xbef5c7bf00000000, 0x20f56d7300000000, 0xa7d6f6d600000000, + 0x39d65c1a00000000, 0xdad1d39400000000, 0x44d1795800000000, + 0x5dd8bc5200000000, 0xc3d8169e00000000, 0x20df991000000000, + 0xbedf33dc00000000, 0x12cd130500000000, 0x8ccdb9c900000000, + 0x6fca364700000000, 0xf1ca9c8b00000000, 0xe8c3598100000000, + 0x76c3f34d00000000, 0x95c47cc300000000, 0x0bc4d60f00000000, + 0x3747a67a00000000, 0xa9470cb600000000, 0x4a40833800000000, + 0xd44029f400000000, 0xcd49ecfe00000000, 0x5349463200000000, + 0xb04ec9bc00000000, 0x2e4e637000000000, 0x825c43a900000000, + 0x1c5ce96500000000, 0xff5b66eb00000000, 0x615bcc2700000000, + 0x7852092d00000000, 0xe652a3e100000000, 0x05552c6f00000000, + 0x9b5586a300000000, 0x1c761d0600000000, 0x8276b7ca00000000, + 0x6171384400000000, 0xff71928800000000, 0xe678578200000000, + 0x7878fd4e00000000, 0x9b7f72c000000000, 0x057fd80c00000000, + 0xa96df8d500000000, 0x376d521900000000, 0xd46add9700000000, + 0x4a6a775b00000000, 0x5363b25100000000, 0xcd63189d00000000, + 0x2e64971300000000, 0xb0643ddf00000000, 0x6125d08300000000, + 0xff257a4f00000000, 0x1c22f5c100000000, 0x82225f0d00000000, + 0x9b2b9a0700000000, 0x052b30cb00000000, 0xe62cbf4500000000, + 0x782c158900000000, 0xd43e355000000000, 0x4a3e9f9c00000000, + 0xa939101200000000, 0x3739bade00000000, 0x2e307fd400000000, + 0xb030d51800000000, 0x53375a9600000000, 0xcd37f05a00000000, + 0x4a146bff00000000, 0xd414c13300000000, 0x37134ebd00000000, + 0xa913e47100000000, 0xb01a217b00000000, 0x2e1a8bb700000000, + 0xcd1d043900000000, 0x531daef500000000, 0xff0f8e2c00000000, + 0x610f24e000000000, 0x8208ab6e00000000, 0x1c0801a200000000, + 0x0501c4a800000000, 0x9b016e6400000000, 0x7806e1ea00000000, + 0xe6064b2600000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, + 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, + 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, + 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, + 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, + 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, + 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, + 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, + 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, + 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, + 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, + 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, + 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, + 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, + 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, + 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, + 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, + 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, + 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, + 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, + 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, + 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, + 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, + 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, + 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, + 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, + 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, + 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, + 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, + 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, + 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, + 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, + 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, + 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, + 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, + 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, + 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, + 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, + 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, + 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, + 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, + 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, + 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, + 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, + 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, + 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, + 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, + 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, + 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, + 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, + 0xde0506f1}, + {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, + 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, + 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, + 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, + 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, + 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, + 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, + 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, + 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, + 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, + 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, + 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, + 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, + 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, + 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, + 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, + 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, + 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, + 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, + 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, + 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, + 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, + 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, + 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, + 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, + 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, + 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, + 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, + 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, + 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, + 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, + 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, + 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, + 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, + 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, + 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, + 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, + 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, + 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, + 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, + 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, + 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, + 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, + 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, + 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, + 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, + 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, + 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, + 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, + 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, + 0xbe9834ed}, + {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, + 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, + 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, + 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, + 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, + 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, + 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, + 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, + 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, + 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, + 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, + 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, + 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, + 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, + 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, + 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, + 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, + 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, + 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, + 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, + 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, + 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, + 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, + 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, + 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, + 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, + 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, + 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, + 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, + 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, + 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, + 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, + 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, + 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, + 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, + 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, + 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, + 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, + 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, + 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, + 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, + 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, + 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, + 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, + 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, + 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, + 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, + 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, + 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, + 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, + 0x9324fd72}, + {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, + 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, + 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, + 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, + 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, + 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, + 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, + 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, + 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, + 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, + 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, + 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, + 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, + 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, + 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, + 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, + 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, + 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, + 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, + 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, + 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, + 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, + 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, + 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, + 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, + 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, + 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, + 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, + 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, + 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, + 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, + 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, + 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, + 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, + 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, + 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, + 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, + 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, + 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, + 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, + 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, + 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, + 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, + 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, + 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, + 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, + 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, + 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, + 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, + 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, + 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, + 0x8def022d}, + {0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64, + 0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1, + 0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e, + 0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61, + 0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82, + 0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff, + 0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7, + 0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da, + 0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139, + 0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6, + 0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89, + 0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c, + 0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0, + 0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d, + 0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a, + 0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177, + 0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de, + 0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b, + 0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824, + 0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e, + 0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad, + 0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0, + 0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d, + 0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60, + 0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83, + 0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822, + 0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d, + 0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8, + 0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171, + 0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c, + 0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b, + 0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6, + 0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca, + 0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f, + 0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430, + 0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf, + 0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c, + 0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51, + 0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9, + 0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84, + 0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67, + 0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398, + 0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7, + 0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62, + 0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e, + 0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923, + 0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4, + 0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9, + 0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070, + 0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5, + 0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a, + 0x72fd2493}, + {0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907, + 0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f, + 0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a, + 0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e, + 0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512, + 0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14, + 0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b, + 0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d, + 0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731, + 0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925, + 0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620, + 0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28, + 0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70, + 0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176, + 0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d, + 0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b, + 0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b, + 0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63, + 0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266, + 0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a, + 0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446, + 0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40, + 0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557, + 0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51, + 0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d, + 0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0, + 0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5, + 0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed, + 0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd, + 0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb, + 0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0, + 0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6, + 0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de, + 0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6, + 0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3, + 0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7, + 0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb, + 0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd, + 0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92, + 0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094, + 0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598, + 0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c, + 0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489, + 0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81, + 0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9, + 0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af, + 0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4, + 0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2, + 0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2, + 0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba, + 0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf, + 0xed3498be}, + {0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f, + 0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d, + 0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0, + 0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42, + 0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95, + 0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2, + 0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a, + 0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d, + 0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea, + 0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748, + 0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5, + 0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27, + 0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b, + 0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac, + 0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4, + 0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3, + 0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44, + 0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6, + 0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b, + 0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329, + 0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe, + 0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9, + 0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1, + 0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6, + 0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921, + 0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555, + 0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8, + 0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a, + 0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd, + 0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a, + 0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2, + 0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5, + 0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2, + 0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330, + 0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad, + 0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f, + 0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8, + 0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef, + 0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc, + 0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb, + 0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c, + 0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e, + 0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03, + 0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1, + 0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6, + 0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1, + 0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9, + 0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e, + 0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409, + 0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb, + 0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966, + 0xf10605de}}; + +#endif + +#endif + +#if N == 2 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87, + 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede, + 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab, + 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c, + 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1, + 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7, + 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e, + 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308, + 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5, + 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472, + 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07, + 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e, + 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa, + 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec, + 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6, + 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0, + 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3, + 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba, + 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf, + 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975, + 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8, + 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde, + 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a, + 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c, + 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1, + 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65, + 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410, + 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649, + 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a, + 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c, + 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946, + 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450, + 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e, + 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857, + 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022, + 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5, + 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758, + 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e, + 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d, + 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b, + 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6, + 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401, + 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74, + 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d, + 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073, + 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65, + 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f, + 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749, + 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a, + 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033, + 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846, + 0x0d7139d7}, + {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563, + 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f, + 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875, + 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536, + 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8, + 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43, + 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f, + 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184, + 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a, + 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39, + 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523, + 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f, + 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d, + 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6, + 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b, + 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0, + 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151, + 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d, + 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47, + 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a, + 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964, + 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef, + 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d, + 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6, + 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348, + 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53, + 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449, + 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645, + 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4, + 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f, + 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2, + 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69, + 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46, + 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a, + 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650, + 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13, + 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded, + 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366, + 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57, + 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc, + 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222, + 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61, + 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b, + 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277, + 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558, + 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3, + 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e, + 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5, + 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74, + 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78, + 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262, + 0x1c53e98a}, + {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b, + 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40, + 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580, + 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7, + 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a, + 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37, + 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75, + 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218, + 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5, + 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2, + 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02, + 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59, + 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1, + 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c, + 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a, + 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307, + 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486, + 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd, + 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d, + 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2, + 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f, + 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72, + 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8, + 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985, + 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268, + 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94, + 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454, + 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f, + 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e, + 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3, + 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915, + 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778, + 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821, + 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a, + 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba, + 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d, + 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560, + 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d, + 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe, + 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3, + 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e, + 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509, + 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9, + 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92, + 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb, + 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6, + 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50, + 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d, + 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc, + 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7, + 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927, + 0x3f88e851}, + {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96, + 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8, + 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0, + 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14, + 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7, + 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4, + 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe, + 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad, + 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e, + 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa, + 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2, + 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c, + 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab, + 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8, + 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d, + 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e, + 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7, + 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99, + 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1, + 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690, + 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933, + 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20, + 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf, + 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc, + 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f, + 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92, + 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca, + 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4, + 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd, + 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de, + 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb, + 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8, + 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474, + 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a, + 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252, + 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6, + 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55, + 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846, + 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7, + 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4, + 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47, + 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3, + 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb, + 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5, + 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49, + 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a, + 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f, + 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c, + 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305, + 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b, + 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523, + 0x3dee8ca6}, + {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f, + 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91, + 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e, + 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c, + 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02, + 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12, + 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567, + 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277, + 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679, + 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b, + 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4, + 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a, + 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0, + 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0, + 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91, + 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881, + 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173, + 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d, + 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912, + 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8, + 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6, + 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6, + 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b, + 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b, + 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75, + 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f, + 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00, + 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee, + 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c, + 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c, + 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d, + 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d, + 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67, + 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89, + 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706, + 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14, + 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a, + 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a, + 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f, + 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f, + 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591, + 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983, + 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c, + 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2, + 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8, + 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8, + 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89, + 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99, + 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b, + 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485, + 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a, + 0x36197165}, + {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382, + 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85, + 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06, + 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca, + 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e, + 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc, + 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616, + 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54, + 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10, + 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc, + 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f, + 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58, + 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef, + 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad, + 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b, + 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29, + 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6, + 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1, + 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622, + 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039, + 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d, + 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f, + 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32, + 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770, + 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034, + 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f, + 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc, + 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db, + 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154, + 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16, + 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0, + 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592, + 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca, + 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd, + 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e, + 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882, + 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6, + 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384, + 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1, + 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3, + 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7, + 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b, + 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8, + 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff, + 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7, + 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5, + 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23, + 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761, + 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee, + 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9, + 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a, + 0x1a3b93aa}, + {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a, + 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca, + 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3, + 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb, + 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c, + 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58, + 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed, + 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9, + 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e, + 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906, + 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f, + 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf, + 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0, + 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4, + 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769, + 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d, + 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632, + 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82, + 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb, + 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73, + 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484, + 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0, + 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5, + 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1, + 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516, + 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f, + 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946, + 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6, + 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9, + 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad, + 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820, + 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364, + 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab, + 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b, + 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62, + 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a, + 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd, + 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089, + 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c, + 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8, + 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f, + 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477, + 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e, + 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be, + 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71, + 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635, + 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8, + 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc, + 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3, + 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753, + 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a, + 0xe147d714}, + {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c, + 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b, + 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92, + 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4, + 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069, + 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526, + 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25, + 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a, + 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7, + 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491, + 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958, + 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f, + 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307, + 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648, + 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999, + 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6, + 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a, + 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d, + 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4, + 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61, + 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc, + 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3, + 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53, + 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c, + 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1, + 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c, + 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5, + 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92, + 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e, + 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771, + 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0, + 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def, + 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0, + 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7, + 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e, + 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58, + 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285, + 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca, + 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce, + 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81, + 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c, + 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a, + 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3, + 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4, + 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb, + 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4, + 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75, + 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a, + 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296, + 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1, + 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808, + 0x494f0c4b}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0x43147b1700000000, 0x8628f62e00000000, + 0xc53c8d3900000000, 0x0c51ec5d00000000, 0x4f45974a00000000, + 0x8a791a7300000000, 0xc96d616400000000, 0x18a2d8bb00000000, + 0x5bb6a3ac00000000, 0x9e8a2e9500000000, 0xdd9e558200000000, + 0x14f334e600000000, 0x57e74ff100000000, 0x92dbc2c800000000, + 0xd1cfb9df00000000, 0x7142c0ac00000000, 0x3256bbbb00000000, + 0xf76a368200000000, 0xb47e4d9500000000, 0x7d132cf100000000, + 0x3e0757e600000000, 0xfb3bdadf00000000, 0xb82fa1c800000000, + 0x69e0181700000000, 0x2af4630000000000, 0xefc8ee3900000000, + 0xacdc952e00000000, 0x65b1f44a00000000, 0x26a58f5d00000000, + 0xe399026400000000, 0xa08d797300000000, 0xa382f18200000000, + 0xe0968a9500000000, 0x25aa07ac00000000, 0x66be7cbb00000000, + 0xafd31ddf00000000, 0xecc766c800000000, 0x29fbebf100000000, + 0x6aef90e600000000, 0xbb20293900000000, 0xf834522e00000000, + 0x3d08df1700000000, 0x7e1ca40000000000, 0xb771c56400000000, + 0xf465be7300000000, 0x3159334a00000000, 0x724d485d00000000, + 0xd2c0312e00000000, 0x91d44a3900000000, 0x54e8c70000000000, + 0x17fcbc1700000000, 0xde91dd7300000000, 0x9d85a66400000000, + 0x58b92b5d00000000, 0x1bad504a00000000, 0xca62e99500000000, + 0x8976928200000000, 0x4c4a1fbb00000000, 0x0f5e64ac00000000, + 0xc63305c800000000, 0x85277edf00000000, 0x401bf3e600000000, + 0x030f88f100000000, 0x070392de00000000, 0x4417e9c900000000, + 0x812b64f000000000, 0xc23f1fe700000000, 0x0b527e8300000000, + 0x4846059400000000, 0x8d7a88ad00000000, 0xce6ef3ba00000000, + 0x1fa14a6500000000, 0x5cb5317200000000, 0x9989bc4b00000000, + 0xda9dc75c00000000, 0x13f0a63800000000, 0x50e4dd2f00000000, + 0x95d8501600000000, 0xd6cc2b0100000000, 0x7641527200000000, + 0x3555296500000000, 0xf069a45c00000000, 0xb37ddf4b00000000, + 0x7a10be2f00000000, 0x3904c53800000000, 0xfc38480100000000, + 0xbf2c331600000000, 0x6ee38ac900000000, 0x2df7f1de00000000, + 0xe8cb7ce700000000, 0xabdf07f000000000, 0x62b2669400000000, + 0x21a61d8300000000, 0xe49a90ba00000000, 0xa78eebad00000000, + 0xa481635c00000000, 0xe795184b00000000, 0x22a9957200000000, + 0x61bdee6500000000, 0xa8d08f0100000000, 0xebc4f41600000000, + 0x2ef8792f00000000, 0x6dec023800000000, 0xbc23bbe700000000, + 0xff37c0f000000000, 0x3a0b4dc900000000, 0x791f36de00000000, + 0xb07257ba00000000, 0xf3662cad00000000, 0x365aa19400000000, + 0x754eda8300000000, 0xd5c3a3f000000000, 0x96d7d8e700000000, + 0x53eb55de00000000, 0x10ff2ec900000000, 0xd9924fad00000000, + 0x9a8634ba00000000, 0x5fbab98300000000, 0x1caec29400000000, + 0xcd617b4b00000000, 0x8e75005c00000000, 0x4b498d6500000000, + 0x085df67200000000, 0xc130971600000000, 0x8224ec0100000000, + 0x4718613800000000, 0x040c1a2f00000000, 0x4f00556600000000, + 0x0c142e7100000000, 0xc928a34800000000, 0x8a3cd85f00000000, + 0x4351b93b00000000, 0x0045c22c00000000, 0xc5794f1500000000, + 0x866d340200000000, 0x57a28ddd00000000, 0x14b6f6ca00000000, + 0xd18a7bf300000000, 0x929e00e400000000, 0x5bf3618000000000, + 0x18e71a9700000000, 0xdddb97ae00000000, 0x9ecfecb900000000, + 0x3e4295ca00000000, 0x7d56eedd00000000, 0xb86a63e400000000, + 0xfb7e18f300000000, 0x3213799700000000, 0x7107028000000000, + 0xb43b8fb900000000, 0xf72ff4ae00000000, 0x26e04d7100000000, + 0x65f4366600000000, 0xa0c8bb5f00000000, 0xe3dcc04800000000, + 0x2ab1a12c00000000, 0x69a5da3b00000000, 0xac99570200000000, + 0xef8d2c1500000000, 0xec82a4e400000000, 0xaf96dff300000000, + 0x6aaa52ca00000000, 0x29be29dd00000000, 0xe0d348b900000000, + 0xa3c733ae00000000, 0x66fbbe9700000000, 0x25efc58000000000, + 0xf4207c5f00000000, 0xb734074800000000, 0x72088a7100000000, + 0x311cf16600000000, 0xf871900200000000, 0xbb65eb1500000000, + 0x7e59662c00000000, 0x3d4d1d3b00000000, 0x9dc0644800000000, + 0xded41f5f00000000, 0x1be8926600000000, 0x58fce97100000000, + 0x9191881500000000, 0xd285f30200000000, 0x17b97e3b00000000, + 0x54ad052c00000000, 0x8562bcf300000000, 0xc676c7e400000000, + 0x034a4add00000000, 0x405e31ca00000000, 0x893350ae00000000, + 0xca272bb900000000, 0x0f1ba68000000000, 0x4c0fdd9700000000, + 0x4803c7b800000000, 0x0b17bcaf00000000, 0xce2b319600000000, + 0x8d3f4a8100000000, 0x44522be500000000, 0x074650f200000000, + 0xc27addcb00000000, 0x816ea6dc00000000, 0x50a11f0300000000, + 0x13b5641400000000, 0xd689e92d00000000, 0x959d923a00000000, + 0x5cf0f35e00000000, 0x1fe4884900000000, 0xdad8057000000000, + 0x99cc7e6700000000, 0x3941071400000000, 0x7a557c0300000000, + 0xbf69f13a00000000, 0xfc7d8a2d00000000, 0x3510eb4900000000, + 0x7604905e00000000, 0xb3381d6700000000, 0xf02c667000000000, + 0x21e3dfaf00000000, 0x62f7a4b800000000, 0xa7cb298100000000, + 0xe4df529600000000, 0x2db233f200000000, 0x6ea648e500000000, + 0xab9ac5dc00000000, 0xe88ebecb00000000, 0xeb81363a00000000, + 0xa8954d2d00000000, 0x6da9c01400000000, 0x2ebdbb0300000000, + 0xe7d0da6700000000, 0xa4c4a17000000000, 0x61f82c4900000000, + 0x22ec575e00000000, 0xf323ee8100000000, 0xb037959600000000, + 0x750b18af00000000, 0x361f63b800000000, 0xff7202dc00000000, + 0xbc6679cb00000000, 0x795af4f200000000, 0x3a4e8fe500000000, + 0x9ac3f69600000000, 0xd9d78d8100000000, 0x1ceb00b800000000, + 0x5fff7baf00000000, 0x96921acb00000000, 0xd58661dc00000000, + 0x10baece500000000, 0x53ae97f200000000, 0x82612e2d00000000, + 0xc175553a00000000, 0x0449d80300000000, 0x475da31400000000, + 0x8e30c27000000000, 0xcd24b96700000000, 0x0818345e00000000, + 0x4b0c4f4900000000}, + {0x0000000000000000, 0x3e6bc2ef00000000, 0x3dd0f50400000000, + 0x03bb37eb00000000, 0x7aa0eb0900000000, 0x44cb29e600000000, + 0x47701e0d00000000, 0x791bdce200000000, 0xf440d71300000000, + 0xca2b15fc00000000, 0xc990221700000000, 0xf7fbe0f800000000, + 0x8ee03c1a00000000, 0xb08bfef500000000, 0xb330c91e00000000, + 0x8d5b0bf100000000, 0xe881ae2700000000, 0xd6ea6cc800000000, + 0xd5515b2300000000, 0xeb3a99cc00000000, 0x9221452e00000000, + 0xac4a87c100000000, 0xaff1b02a00000000, 0x919a72c500000000, + 0x1cc1793400000000, 0x22aabbdb00000000, 0x21118c3000000000, + 0x1f7a4edf00000000, 0x6661923d00000000, 0x580a50d200000000, + 0x5bb1673900000000, 0x65daa5d600000000, 0xd0035d4f00000000, + 0xee689fa000000000, 0xedd3a84b00000000, 0xd3b86aa400000000, + 0xaaa3b64600000000, 0x94c874a900000000, 0x9773434200000000, + 0xa91881ad00000000, 0x24438a5c00000000, 0x1a2848b300000000, + 0x19937f5800000000, 0x27f8bdb700000000, 0x5ee3615500000000, + 0x6088a3ba00000000, 0x6333945100000000, 0x5d5856be00000000, + 0x3882f36800000000, 0x06e9318700000000, 0x0552066c00000000, + 0x3b39c48300000000, 0x4222186100000000, 0x7c49da8e00000000, + 0x7ff2ed6500000000, 0x41992f8a00000000, 0xccc2247b00000000, + 0xf2a9e69400000000, 0xf112d17f00000000, 0xcf79139000000000, + 0xb662cf7200000000, 0x88090d9d00000000, 0x8bb23a7600000000, + 0xb5d9f89900000000, 0xa007ba9e00000000, 0x9e6c787100000000, + 0x9dd74f9a00000000, 0xa3bc8d7500000000, 0xdaa7519700000000, + 0xe4cc937800000000, 0xe777a49300000000, 0xd91c667c00000000, + 0x54476d8d00000000, 0x6a2caf6200000000, 0x6997988900000000, + 0x57fc5a6600000000, 0x2ee7868400000000, 0x108c446b00000000, + 0x1337738000000000, 0x2d5cb16f00000000, 0x488614b900000000, + 0x76edd65600000000, 0x7556e1bd00000000, 0x4b3d235200000000, + 0x3226ffb000000000, 0x0c4d3d5f00000000, 0x0ff60ab400000000, + 0x319dc85b00000000, 0xbcc6c3aa00000000, 0x82ad014500000000, + 0x811636ae00000000, 0xbf7df44100000000, 0xc66628a300000000, + 0xf80dea4c00000000, 0xfbb6dda700000000, 0xc5dd1f4800000000, + 0x7004e7d100000000, 0x4e6f253e00000000, 0x4dd412d500000000, + 0x73bfd03a00000000, 0x0aa40cd800000000, 0x34cfce3700000000, + 0x3774f9dc00000000, 0x091f3b3300000000, 0x844430c200000000, + 0xba2ff22d00000000, 0xb994c5c600000000, 0x87ff072900000000, + 0xfee4dbcb00000000, 0xc08f192400000000, 0xc3342ecf00000000, + 0xfd5fec2000000000, 0x988549f600000000, 0xa6ee8b1900000000, + 0xa555bcf200000000, 0x9b3e7e1d00000000, 0xe225a2ff00000000, + 0xdc4e601000000000, 0xdff557fb00000000, 0xe19e951400000000, + 0x6cc59ee500000000, 0x52ae5c0a00000000, 0x51156be100000000, + 0x6f7ea90e00000000, 0x166575ec00000000, 0x280eb70300000000, + 0x2bb580e800000000, 0x15de420700000000, 0x010905e600000000, + 0x3f62c70900000000, 0x3cd9f0e200000000, 0x02b2320d00000000, + 0x7ba9eeef00000000, 0x45c22c0000000000, 0x46791beb00000000, + 0x7812d90400000000, 0xf549d2f500000000, 0xcb22101a00000000, + 0xc89927f100000000, 0xf6f2e51e00000000, 0x8fe939fc00000000, + 0xb182fb1300000000, 0xb239ccf800000000, 0x8c520e1700000000, + 0xe988abc100000000, 0xd7e3692e00000000, 0xd4585ec500000000, + 0xea339c2a00000000, 0x932840c800000000, 0xad43822700000000, + 0xaef8b5cc00000000, 0x9093772300000000, 0x1dc87cd200000000, + 0x23a3be3d00000000, 0x201889d600000000, 0x1e734b3900000000, + 0x676897db00000000, 0x5903553400000000, 0x5ab862df00000000, + 0x64d3a03000000000, 0xd10a58a900000000, 0xef619a4600000000, + 0xecdaadad00000000, 0xd2b16f4200000000, 0xabaab3a000000000, + 0x95c1714f00000000, 0x967a46a400000000, 0xa811844b00000000, + 0x254a8fba00000000, 0x1b214d5500000000, 0x189a7abe00000000, + 0x26f1b85100000000, 0x5fea64b300000000, 0x6181a65c00000000, + 0x623a91b700000000, 0x5c51535800000000, 0x398bf68e00000000, + 0x07e0346100000000, 0x045b038a00000000, 0x3a30c16500000000, + 0x432b1d8700000000, 0x7d40df6800000000, 0x7efbe88300000000, + 0x40902a6c00000000, 0xcdcb219d00000000, 0xf3a0e37200000000, + 0xf01bd49900000000, 0xce70167600000000, 0xb76bca9400000000, + 0x8900087b00000000, 0x8abb3f9000000000, 0xb4d0fd7f00000000, + 0xa10ebf7800000000, 0x9f657d9700000000, 0x9cde4a7c00000000, + 0xa2b5889300000000, 0xdbae547100000000, 0xe5c5969e00000000, + 0xe67ea17500000000, 0xd815639a00000000, 0x554e686b00000000, + 0x6b25aa8400000000, 0x689e9d6f00000000, 0x56f55f8000000000, + 0x2fee836200000000, 0x1185418d00000000, 0x123e766600000000, + 0x2c55b48900000000, 0x498f115f00000000, 0x77e4d3b000000000, + 0x745fe45b00000000, 0x4a3426b400000000, 0x332ffa5600000000, + 0x0d4438b900000000, 0x0eff0f5200000000, 0x3094cdbd00000000, + 0xbdcfc64c00000000, 0x83a404a300000000, 0x801f334800000000, + 0xbe74f1a700000000, 0xc76f2d4500000000, 0xf904efaa00000000, + 0xfabfd84100000000, 0xc4d41aae00000000, 0x710de23700000000, + 0x4f6620d800000000, 0x4cdd173300000000, 0x72b6d5dc00000000, + 0x0bad093e00000000, 0x35c6cbd100000000, 0x367dfc3a00000000, + 0x08163ed500000000, 0x854d352400000000, 0xbb26f7cb00000000, + 0xb89dc02000000000, 0x86f602cf00000000, 0xffedde2d00000000, + 0xc1861cc200000000, 0xc23d2b2900000000, 0xfc56e9c600000000, + 0x998c4c1000000000, 0xa7e78eff00000000, 0xa45cb91400000000, + 0x9a377bfb00000000, 0xe32ca71900000000, 0xdd4765f600000000, + 0xdefc521d00000000, 0xe09790f200000000, 0x6dcc9b0300000000, + 0x53a759ec00000000, 0x501c6e0700000000, 0x6e77ace800000000, + 0x176c700a00000000, 0x2907b2e500000000, 0x2abc850e00000000, + 0x14d747e100000000}, + {0x0000000000000000, 0xc0df8ec100000000, 0xc1b96c5800000000, + 0x0166e29900000000, 0x8273d9b000000000, 0x42ac577100000000, + 0x43cab5e800000000, 0x83153b2900000000, 0x45e1c3ba00000000, + 0x853e4d7b00000000, 0x8458afe200000000, 0x4487212300000000, + 0xc7921a0a00000000, 0x074d94cb00000000, 0x062b765200000000, + 0xc6f4f89300000000, 0xcbc4f6ae00000000, 0x0b1b786f00000000, + 0x0a7d9af600000000, 0xcaa2143700000000, 0x49b72f1e00000000, + 0x8968a1df00000000, 0x880e434600000000, 0x48d1cd8700000000, + 0x8e25351400000000, 0x4efabbd500000000, 0x4f9c594c00000000, + 0x8f43d78d00000000, 0x0c56eca400000000, 0xcc89626500000000, + 0xcdef80fc00000000, 0x0d300e3d00000000, 0xd78f9c8600000000, + 0x1750124700000000, 0x1636f0de00000000, 0xd6e97e1f00000000, + 0x55fc453600000000, 0x9523cbf700000000, 0x9445296e00000000, + 0x549aa7af00000000, 0x926e5f3c00000000, 0x52b1d1fd00000000, + 0x53d7336400000000, 0x9308bda500000000, 0x101d868c00000000, + 0xd0c2084d00000000, 0xd1a4ead400000000, 0x117b641500000000, + 0x1c4b6a2800000000, 0xdc94e4e900000000, 0xddf2067000000000, + 0x1d2d88b100000000, 0x9e38b39800000000, 0x5ee73d5900000000, + 0x5f81dfc000000000, 0x9f5e510100000000, 0x59aaa99200000000, + 0x9975275300000000, 0x9813c5ca00000000, 0x58cc4b0b00000000, + 0xdbd9702200000000, 0x1b06fee300000000, 0x1a601c7a00000000, + 0xdabf92bb00000000, 0xef1948d600000000, 0x2fc6c61700000000, + 0x2ea0248e00000000, 0xee7faa4f00000000, 0x6d6a916600000000, + 0xadb51fa700000000, 0xacd3fd3e00000000, 0x6c0c73ff00000000, + 0xaaf88b6c00000000, 0x6a2705ad00000000, 0x6b41e73400000000, + 0xab9e69f500000000, 0x288b52dc00000000, 0xe854dc1d00000000, + 0xe9323e8400000000, 0x29edb04500000000, 0x24ddbe7800000000, + 0xe40230b900000000, 0xe564d22000000000, 0x25bb5ce100000000, + 0xa6ae67c800000000, 0x6671e90900000000, 0x67170b9000000000, + 0xa7c8855100000000, 0x613c7dc200000000, 0xa1e3f30300000000, + 0xa085119a00000000, 0x605a9f5b00000000, 0xe34fa47200000000, + 0x23902ab300000000, 0x22f6c82a00000000, 0xe22946eb00000000, + 0x3896d45000000000, 0xf8495a9100000000, 0xf92fb80800000000, + 0x39f036c900000000, 0xbae50de000000000, 0x7a3a832100000000, + 0x7b5c61b800000000, 0xbb83ef7900000000, 0x7d7717ea00000000, + 0xbda8992b00000000, 0xbcce7bb200000000, 0x7c11f57300000000, + 0xff04ce5a00000000, 0x3fdb409b00000000, 0x3ebda20200000000, + 0xfe622cc300000000, 0xf35222fe00000000, 0x338dac3f00000000, + 0x32eb4ea600000000, 0xf234c06700000000, 0x7121fb4e00000000, + 0xb1fe758f00000000, 0xb098971600000000, 0x704719d700000000, + 0xb6b3e14400000000, 0x766c6f8500000000, 0x770a8d1c00000000, + 0xb7d503dd00000000, 0x34c038f400000000, 0xf41fb63500000000, + 0xf57954ac00000000, 0x35a6da6d00000000, 0x9f35e17700000000, + 0x5fea6fb600000000, 0x5e8c8d2f00000000, 0x9e5303ee00000000, + 0x1d4638c700000000, 0xdd99b60600000000, 0xdcff549f00000000, + 0x1c20da5e00000000, 0xdad422cd00000000, 0x1a0bac0c00000000, + 0x1b6d4e9500000000, 0xdbb2c05400000000, 0x58a7fb7d00000000, + 0x987875bc00000000, 0x991e972500000000, 0x59c119e400000000, + 0x54f117d900000000, 0x942e991800000000, 0x95487b8100000000, + 0x5597f54000000000, 0xd682ce6900000000, 0x165d40a800000000, + 0x173ba23100000000, 0xd7e42cf000000000, 0x1110d46300000000, + 0xd1cf5aa200000000, 0xd0a9b83b00000000, 0x107636fa00000000, + 0x93630dd300000000, 0x53bc831200000000, 0x52da618b00000000, + 0x9205ef4a00000000, 0x48ba7df100000000, 0x8865f33000000000, + 0x890311a900000000, 0x49dc9f6800000000, 0xcac9a44100000000, + 0x0a162a8000000000, 0x0b70c81900000000, 0xcbaf46d800000000, + 0x0d5bbe4b00000000, 0xcd84308a00000000, 0xcce2d21300000000, + 0x0c3d5cd200000000, 0x8f2867fb00000000, 0x4ff7e93a00000000, + 0x4e910ba300000000, 0x8e4e856200000000, 0x837e8b5f00000000, + 0x43a1059e00000000, 0x42c7e70700000000, 0x821869c600000000, + 0x010d52ef00000000, 0xc1d2dc2e00000000, 0xc0b43eb700000000, + 0x006bb07600000000, 0xc69f48e500000000, 0x0640c62400000000, + 0x072624bd00000000, 0xc7f9aa7c00000000, 0x44ec915500000000, + 0x84331f9400000000, 0x8555fd0d00000000, 0x458a73cc00000000, + 0x702ca9a100000000, 0xb0f3276000000000, 0xb195c5f900000000, + 0x714a4b3800000000, 0xf25f701100000000, 0x3280fed000000000, + 0x33e61c4900000000, 0xf339928800000000, 0x35cd6a1b00000000, + 0xf512e4da00000000, 0xf474064300000000, 0x34ab888200000000, + 0xb7beb3ab00000000, 0x77613d6a00000000, 0x7607dff300000000, + 0xb6d8513200000000, 0xbbe85f0f00000000, 0x7b37d1ce00000000, + 0x7a51335700000000, 0xba8ebd9600000000, 0x399b86bf00000000, + 0xf944087e00000000, 0xf822eae700000000, 0x38fd642600000000, + 0xfe099cb500000000, 0x3ed6127400000000, 0x3fb0f0ed00000000, + 0xff6f7e2c00000000, 0x7c7a450500000000, 0xbca5cbc400000000, + 0xbdc3295d00000000, 0x7d1ca79c00000000, 0xa7a3352700000000, + 0x677cbbe600000000, 0x661a597f00000000, 0xa6c5d7be00000000, + 0x25d0ec9700000000, 0xe50f625600000000, 0xe46980cf00000000, + 0x24b60e0e00000000, 0xe242f69d00000000, 0x229d785c00000000, + 0x23fb9ac500000000, 0xe324140400000000, 0x60312f2d00000000, + 0xa0eea1ec00000000, 0xa188437500000000, 0x6157cdb400000000, + 0x6c67c38900000000, 0xacb84d4800000000, 0xaddeafd100000000, + 0x6d01211000000000, 0xee141a3900000000, 0x2ecb94f800000000, + 0x2fad766100000000, 0xef72f8a000000000, 0x2986003300000000, + 0xe9598ef200000000, 0xe83f6c6b00000000, 0x28e0e2aa00000000, + 0xabf5d98300000000, 0x6b2a574200000000, 0x6a4cb5db00000000, + 0xaa933b1a00000000}, + {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000, + 0xf0d29e7700000000, 0x7f3b060300000000, 0x1077a39800000000, + 0xe0a53def00000000, 0x8fe9987400000000, 0xfe760c0600000000, + 0x913aa99d00000000, 0x61e837ea00000000, 0x0ea4927100000000, + 0x814d0a0500000000, 0xee01af9e00000000, 0x1ed331e900000000, + 0x719f947200000000, 0xfced180c00000000, 0x93a1bd9700000000, + 0x637323e000000000, 0x0c3f867b00000000, 0x83d61e0f00000000, + 0xec9abb9400000000, 0x1c4825e300000000, 0x7304807800000000, + 0x029b140a00000000, 0x6dd7b19100000000, 0x9d052fe600000000, + 0xf2498a7d00000000, 0x7da0120900000000, 0x12ecb79200000000, + 0xe23e29e500000000, 0x8d728c7e00000000, 0xf8db311800000000, + 0x9797948300000000, 0x67450af400000000, 0x0809af6f00000000, + 0x87e0371b00000000, 0xe8ac928000000000, 0x187e0cf700000000, + 0x7732a96c00000000, 0x06ad3d1e00000000, 0x69e1988500000000, + 0x993306f200000000, 0xf67fa36900000000, 0x79963b1d00000000, + 0x16da9e8600000000, 0xe60800f100000000, 0x8944a56a00000000, + 0x0436291400000000, 0x6b7a8c8f00000000, 0x9ba812f800000000, + 0xf4e4b76300000000, 0x7b0d2f1700000000, 0x14418a8c00000000, + 0xe49314fb00000000, 0x8bdfb16000000000, 0xfa40251200000000, + 0x950c808900000000, 0x65de1efe00000000, 0x0a92bb6500000000, + 0x857b231100000000, 0xea37868a00000000, 0x1ae518fd00000000, + 0x75a9bd6600000000, 0xf0b7633000000000, 0x9ffbc6ab00000000, + 0x6f2958dc00000000, 0x0065fd4700000000, 0x8f8c653300000000, + 0xe0c0c0a800000000, 0x10125edf00000000, 0x7f5efb4400000000, + 0x0ec16f3600000000, 0x618dcaad00000000, 0x915f54da00000000, + 0xfe13f14100000000, 0x71fa693500000000, 0x1eb6ccae00000000, + 0xee6452d900000000, 0x8128f74200000000, 0x0c5a7b3c00000000, + 0x6316dea700000000, 0x93c440d000000000, 0xfc88e54b00000000, + 0x73617d3f00000000, 0x1c2dd8a400000000, 0xecff46d300000000, + 0x83b3e34800000000, 0xf22c773a00000000, 0x9d60d2a100000000, + 0x6db24cd600000000, 0x02fee94d00000000, 0x8d17713900000000, + 0xe25bd4a200000000, 0x12894ad500000000, 0x7dc5ef4e00000000, + 0x086c522800000000, 0x6720f7b300000000, 0x97f269c400000000, + 0xf8becc5f00000000, 0x7757542b00000000, 0x181bf1b000000000, + 0xe8c96fc700000000, 0x8785ca5c00000000, 0xf61a5e2e00000000, + 0x9956fbb500000000, 0x698465c200000000, 0x06c8c05900000000, + 0x8921582d00000000, 0xe66dfdb600000000, 0x16bf63c100000000, + 0x79f3c65a00000000, 0xf4814a2400000000, 0x9bcdefbf00000000, + 0x6b1f71c800000000, 0x0453d45300000000, 0x8bba4c2700000000, + 0xe4f6e9bc00000000, 0x142477cb00000000, 0x7b68d25000000000, + 0x0af7462200000000, 0x65bbe3b900000000, 0x95697dce00000000, + 0xfa25d85500000000, 0x75cc402100000000, 0x1a80e5ba00000000, + 0xea527bcd00000000, 0x851ede5600000000, 0xe06fc76000000000, + 0x8f2362fb00000000, 0x7ff1fc8c00000000, 0x10bd591700000000, + 0x9f54c16300000000, 0xf01864f800000000, 0x00cafa8f00000000, + 0x6f865f1400000000, 0x1e19cb6600000000, 0x71556efd00000000, + 0x8187f08a00000000, 0xeecb551100000000, 0x6122cd6500000000, + 0x0e6e68fe00000000, 0xfebcf68900000000, 0x91f0531200000000, + 0x1c82df6c00000000, 0x73ce7af700000000, 0x831ce48000000000, + 0xec50411b00000000, 0x63b9d96f00000000, 0x0cf57cf400000000, + 0xfc27e28300000000, 0x936b471800000000, 0xe2f4d36a00000000, + 0x8db876f100000000, 0x7d6ae88600000000, 0x12264d1d00000000, + 0x9dcfd56900000000, 0xf28370f200000000, 0x0251ee8500000000, + 0x6d1d4b1e00000000, 0x18b4f67800000000, 0x77f853e300000000, + 0x872acd9400000000, 0xe866680f00000000, 0x678ff07b00000000, + 0x08c355e000000000, 0xf811cb9700000000, 0x975d6e0c00000000, + 0xe6c2fa7e00000000, 0x898e5fe500000000, 0x795cc19200000000, + 0x1610640900000000, 0x99f9fc7d00000000, 0xf6b559e600000000, + 0x0667c79100000000, 0x692b620a00000000, 0xe459ee7400000000, + 0x8b154bef00000000, 0x7bc7d59800000000, 0x148b700300000000, + 0x9b62e87700000000, 0xf42e4dec00000000, 0x04fcd39b00000000, + 0x6bb0760000000000, 0x1a2fe27200000000, 0x756347e900000000, + 0x85b1d99e00000000, 0xeafd7c0500000000, 0x6514e47100000000, + 0x0a5841ea00000000, 0xfa8adf9d00000000, 0x95c67a0600000000, + 0x10d8a45000000000, 0x7f9401cb00000000, 0x8f469fbc00000000, + 0xe00a3a2700000000, 0x6fe3a25300000000, 0x00af07c800000000, + 0xf07d99bf00000000, 0x9f313c2400000000, 0xeeaea85600000000, + 0x81e20dcd00000000, 0x713093ba00000000, 0x1e7c362100000000, + 0x9195ae5500000000, 0xfed90bce00000000, 0x0e0b95b900000000, + 0x6147302200000000, 0xec35bc5c00000000, 0x837919c700000000, + 0x73ab87b000000000, 0x1ce7222b00000000, 0x930eba5f00000000, + 0xfc421fc400000000, 0x0c9081b300000000, 0x63dc242800000000, + 0x1243b05a00000000, 0x7d0f15c100000000, 0x8ddd8bb600000000, + 0xe2912e2d00000000, 0x6d78b65900000000, 0x023413c200000000, + 0xf2e68db500000000, 0x9daa282e00000000, 0xe803954800000000, + 0x874f30d300000000, 0x779daea400000000, 0x18d10b3f00000000, + 0x9738934b00000000, 0xf87436d000000000, 0x08a6a8a700000000, + 0x67ea0d3c00000000, 0x1675994e00000000, 0x79393cd500000000, + 0x89eba2a200000000, 0xe6a7073900000000, 0x694e9f4d00000000, + 0x06023ad600000000, 0xf6d0a4a100000000, 0x999c013a00000000, + 0x14ee8d4400000000, 0x7ba228df00000000, 0x8b70b6a800000000, + 0xe43c133300000000, 0x6bd58b4700000000, 0x04992edc00000000, + 0xf44bb0ab00000000, 0x9b07153000000000, 0xea98814200000000, + 0x85d424d900000000, 0x7506baae00000000, 0x1a4a1f3500000000, + 0x95a3874100000000, 0xfaef22da00000000, 0x0a3dbcad00000000, + 0x6571193600000000}, + {0x0000000000000000, 0x85d996dd00000000, 0x4bb55c6000000000, + 0xce6ccabd00000000, 0x966ab9c000000000, 0x13b32f1d00000000, + 0xdddfe5a000000000, 0x5806737d00000000, 0x6dd3035a00000000, + 0xe80a958700000000, 0x26665f3a00000000, 0xa3bfc9e700000000, + 0xfbb9ba9a00000000, 0x7e602c4700000000, 0xb00ce6fa00000000, + 0x35d5702700000000, 0xdaa607b400000000, 0x5f7f916900000000, + 0x91135bd400000000, 0x14cacd0900000000, 0x4cccbe7400000000, + 0xc91528a900000000, 0x0779e21400000000, 0x82a074c900000000, + 0xb77504ee00000000, 0x32ac923300000000, 0xfcc0588e00000000, + 0x7919ce5300000000, 0x211fbd2e00000000, 0xa4c62bf300000000, + 0x6aaae14e00000000, 0xef73779300000000, 0xf54b7eb300000000, + 0x7092e86e00000000, 0xbefe22d300000000, 0x3b27b40e00000000, + 0x6321c77300000000, 0xe6f851ae00000000, 0x28949b1300000000, + 0xad4d0dce00000000, 0x98987de900000000, 0x1d41eb3400000000, + 0xd32d218900000000, 0x56f4b75400000000, 0x0ef2c42900000000, + 0x8b2b52f400000000, 0x4547984900000000, 0xc09e0e9400000000, + 0x2fed790700000000, 0xaa34efda00000000, 0x6458256700000000, + 0xe181b3ba00000000, 0xb987c0c700000000, 0x3c5e561a00000000, + 0xf2329ca700000000, 0x77eb0a7a00000000, 0x423e7a5d00000000, + 0xc7e7ec8000000000, 0x098b263d00000000, 0x8c52b0e000000000, + 0xd454c39d00000000, 0x518d554000000000, 0x9fe19ffd00000000, + 0x1a38092000000000, 0xab918dbd00000000, 0x2e481b6000000000, + 0xe024d1dd00000000, 0x65fd470000000000, 0x3dfb347d00000000, + 0xb822a2a000000000, 0x764e681d00000000, 0xf397fec000000000, + 0xc6428ee700000000, 0x439b183a00000000, 0x8df7d28700000000, + 0x082e445a00000000, 0x5028372700000000, 0xd5f1a1fa00000000, + 0x1b9d6b4700000000, 0x9e44fd9a00000000, 0x71378a0900000000, + 0xf4ee1cd400000000, 0x3a82d66900000000, 0xbf5b40b400000000, + 0xe75d33c900000000, 0x6284a51400000000, 0xace86fa900000000, + 0x2931f97400000000, 0x1ce4895300000000, 0x993d1f8e00000000, + 0x5751d53300000000, 0xd28843ee00000000, 0x8a8e309300000000, + 0x0f57a64e00000000, 0xc13b6cf300000000, 0x44e2fa2e00000000, + 0x5edaf30e00000000, 0xdb0365d300000000, 0x156faf6e00000000, + 0x90b639b300000000, 0xc8b04ace00000000, 0x4d69dc1300000000, + 0x830516ae00000000, 0x06dc807300000000, 0x3309f05400000000, + 0xb6d0668900000000, 0x78bcac3400000000, 0xfd653ae900000000, + 0xa563499400000000, 0x20badf4900000000, 0xeed615f400000000, + 0x6b0f832900000000, 0x847cf4ba00000000, 0x01a5626700000000, + 0xcfc9a8da00000000, 0x4a103e0700000000, 0x12164d7a00000000, + 0x97cfdba700000000, 0x59a3111a00000000, 0xdc7a87c700000000, + 0xe9aff7e000000000, 0x6c76613d00000000, 0xa21aab8000000000, + 0x27c33d5d00000000, 0x7fc54e2000000000, 0xfa1cd8fd00000000, + 0x3470124000000000, 0xb1a9849d00000000, 0x17256aa000000000, + 0x92fcfc7d00000000, 0x5c9036c000000000, 0xd949a01d00000000, + 0x814fd36000000000, 0x049645bd00000000, 0xcafa8f0000000000, + 0x4f2319dd00000000, 0x7af669fa00000000, 0xff2fff2700000000, + 0x3143359a00000000, 0xb49aa34700000000, 0xec9cd03a00000000, + 0x694546e700000000, 0xa7298c5a00000000, 0x22f01a8700000000, + 0xcd836d1400000000, 0x485afbc900000000, 0x8636317400000000, + 0x03efa7a900000000, 0x5be9d4d400000000, 0xde30420900000000, + 0x105c88b400000000, 0x95851e6900000000, 0xa0506e4e00000000, + 0x2589f89300000000, 0xebe5322e00000000, 0x6e3ca4f300000000, + 0x363ad78e00000000, 0xb3e3415300000000, 0x7d8f8bee00000000, + 0xf8561d3300000000, 0xe26e141300000000, 0x67b782ce00000000, + 0xa9db487300000000, 0x2c02deae00000000, 0x7404add300000000, + 0xf1dd3b0e00000000, 0x3fb1f1b300000000, 0xba68676e00000000, + 0x8fbd174900000000, 0x0a64819400000000, 0xc4084b2900000000, + 0x41d1ddf400000000, 0x19d7ae8900000000, 0x9c0e385400000000, + 0x5262f2e900000000, 0xd7bb643400000000, 0x38c813a700000000, + 0xbd11857a00000000, 0x737d4fc700000000, 0xf6a4d91a00000000, + 0xaea2aa6700000000, 0x2b7b3cba00000000, 0xe517f60700000000, + 0x60ce60da00000000, 0x551b10fd00000000, 0xd0c2862000000000, + 0x1eae4c9d00000000, 0x9b77da4000000000, 0xc371a93d00000000, + 0x46a83fe000000000, 0x88c4f55d00000000, 0x0d1d638000000000, + 0xbcb4e71d00000000, 0x396d71c000000000, 0xf701bb7d00000000, + 0x72d82da000000000, 0x2ade5edd00000000, 0xaf07c80000000000, + 0x616b02bd00000000, 0xe4b2946000000000, 0xd167e44700000000, + 0x54be729a00000000, 0x9ad2b82700000000, 0x1f0b2efa00000000, + 0x470d5d8700000000, 0xc2d4cb5a00000000, 0x0cb801e700000000, + 0x8961973a00000000, 0x6612e0a900000000, 0xe3cb767400000000, + 0x2da7bcc900000000, 0xa87e2a1400000000, 0xf078596900000000, + 0x75a1cfb400000000, 0xbbcd050900000000, 0x3e1493d400000000, + 0x0bc1e3f300000000, 0x8e18752e00000000, 0x4074bf9300000000, + 0xc5ad294e00000000, 0x9dab5a3300000000, 0x1872ccee00000000, + 0xd61e065300000000, 0x53c7908e00000000, 0x49ff99ae00000000, + 0xcc260f7300000000, 0x024ac5ce00000000, 0x8793531300000000, + 0xdf95206e00000000, 0x5a4cb6b300000000, 0x94207c0e00000000, + 0x11f9ead300000000, 0x242c9af400000000, 0xa1f50c2900000000, + 0x6f99c69400000000, 0xea40504900000000, 0xb246233400000000, + 0x379fb5e900000000, 0xf9f37f5400000000, 0x7c2ae98900000000, + 0x93599e1a00000000, 0x168008c700000000, 0xd8ecc27a00000000, + 0x5d3554a700000000, 0x053327da00000000, 0x80eab10700000000, + 0x4e867bba00000000, 0xcb5fed6700000000, 0xfe8a9d4000000000, + 0x7b530b9d00000000, 0xb53fc12000000000, 0x30e657fd00000000, + 0x68e0248000000000, 0xed39b25d00000000, 0x235578e000000000, + 0xa68cee3d00000000}, + {0x0000000000000000, 0x76e10f9d00000000, 0xadc46ee100000000, + 0xdb25617c00000000, 0x1b8fac1900000000, 0x6d6ea38400000000, + 0xb64bc2f800000000, 0xc0aacd6500000000, 0x361e593300000000, + 0x40ff56ae00000000, 0x9bda37d200000000, 0xed3b384f00000000, + 0x2d91f52a00000000, 0x5b70fab700000000, 0x80559bcb00000000, + 0xf6b4945600000000, 0x6c3cb26600000000, 0x1addbdfb00000000, + 0xc1f8dc8700000000, 0xb719d31a00000000, 0x77b31e7f00000000, + 0x015211e200000000, 0xda77709e00000000, 0xac967f0300000000, + 0x5a22eb5500000000, 0x2cc3e4c800000000, 0xf7e685b400000000, + 0x81078a2900000000, 0x41ad474c00000000, 0x374c48d100000000, + 0xec6929ad00000000, 0x9a88263000000000, 0xd87864cd00000000, + 0xae996b5000000000, 0x75bc0a2c00000000, 0x035d05b100000000, + 0xc3f7c8d400000000, 0xb516c74900000000, 0x6e33a63500000000, + 0x18d2a9a800000000, 0xee663dfe00000000, 0x9887326300000000, + 0x43a2531f00000000, 0x35435c8200000000, 0xf5e991e700000000, + 0x83089e7a00000000, 0x582dff0600000000, 0x2eccf09b00000000, + 0xb444d6ab00000000, 0xc2a5d93600000000, 0x1980b84a00000000, + 0x6f61b7d700000000, 0xafcb7ab200000000, 0xd92a752f00000000, + 0x020f145300000000, 0x74ee1bce00000000, 0x825a8f9800000000, + 0xf4bb800500000000, 0x2f9ee17900000000, 0x597feee400000000, + 0x99d5238100000000, 0xef342c1c00000000, 0x34114d6000000000, + 0x42f042fd00000000, 0xf1f7b94100000000, 0x8716b6dc00000000, + 0x5c33d7a000000000, 0x2ad2d83d00000000, 0xea78155800000000, + 0x9c991ac500000000, 0x47bc7bb900000000, 0x315d742400000000, + 0xc7e9e07200000000, 0xb108efef00000000, 0x6a2d8e9300000000, + 0x1ccc810e00000000, 0xdc664c6b00000000, 0xaa8743f600000000, + 0x71a2228a00000000, 0x07432d1700000000, 0x9dcb0b2700000000, + 0xeb2a04ba00000000, 0x300f65c600000000, 0x46ee6a5b00000000, + 0x8644a73e00000000, 0xf0a5a8a300000000, 0x2b80c9df00000000, + 0x5d61c64200000000, 0xabd5521400000000, 0xdd345d8900000000, + 0x06113cf500000000, 0x70f0336800000000, 0xb05afe0d00000000, + 0xc6bbf19000000000, 0x1d9e90ec00000000, 0x6b7f9f7100000000, + 0x298fdd8c00000000, 0x5f6ed21100000000, 0x844bb36d00000000, + 0xf2aabcf000000000, 0x3200719500000000, 0x44e17e0800000000, + 0x9fc41f7400000000, 0xe92510e900000000, 0x1f9184bf00000000, + 0x69708b2200000000, 0xb255ea5e00000000, 0xc4b4e5c300000000, + 0x041e28a600000000, 0x72ff273b00000000, 0xa9da464700000000, + 0xdf3b49da00000000, 0x45b36fea00000000, 0x3352607700000000, + 0xe877010b00000000, 0x9e960e9600000000, 0x5e3cc3f300000000, + 0x28ddcc6e00000000, 0xf3f8ad1200000000, 0x8519a28f00000000, + 0x73ad36d900000000, 0x054c394400000000, 0xde69583800000000, + 0xa88857a500000000, 0x68229ac000000000, 0x1ec3955d00000000, + 0xc5e6f42100000000, 0xb307fbbc00000000, 0xe2ef738300000000, + 0x940e7c1e00000000, 0x4f2b1d6200000000, 0x39ca12ff00000000, + 0xf960df9a00000000, 0x8f81d00700000000, 0x54a4b17b00000000, + 0x2245bee600000000, 0xd4f12ab000000000, 0xa210252d00000000, + 0x7935445100000000, 0x0fd44bcc00000000, 0xcf7e86a900000000, + 0xb99f893400000000, 0x62bae84800000000, 0x145be7d500000000, + 0x8ed3c1e500000000, 0xf832ce7800000000, 0x2317af0400000000, + 0x55f6a09900000000, 0x955c6dfc00000000, 0xe3bd626100000000, + 0x3898031d00000000, 0x4e790c8000000000, 0xb8cd98d600000000, + 0xce2c974b00000000, 0x1509f63700000000, 0x63e8f9aa00000000, + 0xa34234cf00000000, 0xd5a33b5200000000, 0x0e865a2e00000000, + 0x786755b300000000, 0x3a97174e00000000, 0x4c7618d300000000, + 0x975379af00000000, 0xe1b2763200000000, 0x2118bb5700000000, + 0x57f9b4ca00000000, 0x8cdcd5b600000000, 0xfa3dda2b00000000, + 0x0c894e7d00000000, 0x7a6841e000000000, 0xa14d209c00000000, + 0xd7ac2f0100000000, 0x1706e26400000000, 0x61e7edf900000000, + 0xbac28c8500000000, 0xcc23831800000000, 0x56aba52800000000, + 0x204aaab500000000, 0xfb6fcbc900000000, 0x8d8ec45400000000, + 0x4d24093100000000, 0x3bc506ac00000000, 0xe0e067d000000000, + 0x9601684d00000000, 0x60b5fc1b00000000, 0x1654f38600000000, + 0xcd7192fa00000000, 0xbb909d6700000000, 0x7b3a500200000000, + 0x0ddb5f9f00000000, 0xd6fe3ee300000000, 0xa01f317e00000000, + 0x1318cac200000000, 0x65f9c55f00000000, 0xbedca42300000000, + 0xc83dabbe00000000, 0x089766db00000000, 0x7e76694600000000, + 0xa553083a00000000, 0xd3b207a700000000, 0x250693f100000000, + 0x53e79c6c00000000, 0x88c2fd1000000000, 0xfe23f28d00000000, + 0x3e893fe800000000, 0x4868307500000000, 0x934d510900000000, + 0xe5ac5e9400000000, 0x7f2478a400000000, 0x09c5773900000000, + 0xd2e0164500000000, 0xa40119d800000000, 0x64abd4bd00000000, + 0x124adb2000000000, 0xc96fba5c00000000, 0xbf8eb5c100000000, + 0x493a219700000000, 0x3fdb2e0a00000000, 0xe4fe4f7600000000, + 0x921f40eb00000000, 0x52b58d8e00000000, 0x2454821300000000, + 0xff71e36f00000000, 0x8990ecf200000000, 0xcb60ae0f00000000, + 0xbd81a19200000000, 0x66a4c0ee00000000, 0x1045cf7300000000, + 0xd0ef021600000000, 0xa60e0d8b00000000, 0x7d2b6cf700000000, + 0x0bca636a00000000, 0xfd7ef73c00000000, 0x8b9ff8a100000000, + 0x50ba99dd00000000, 0x265b964000000000, 0xe6f15b2500000000, + 0x901054b800000000, 0x4b3535c400000000, 0x3dd43a5900000000, + 0xa75c1c6900000000, 0xd1bd13f400000000, 0x0a98728800000000, + 0x7c797d1500000000, 0xbcd3b07000000000, 0xca32bfed00000000, + 0x1117de9100000000, 0x67f6d10c00000000, 0x9142455a00000000, + 0xe7a34ac700000000, 0x3c862bbb00000000, 0x4a67242600000000, + 0x8acde94300000000, 0xfc2ce6de00000000, 0x270987a200000000, + 0x51e8883f00000000}, + {0x0000000000000000, 0xe8dbfbb900000000, 0x91b186a800000000, + 0x796a7d1100000000, 0x63657c8a00000000, 0x8bbe873300000000, + 0xf2d4fa2200000000, 0x1a0f019b00000000, 0x87cc89cf00000000, + 0x6f17727600000000, 0x167d0f6700000000, 0xfea6f4de00000000, + 0xe4a9f54500000000, 0x0c720efc00000000, 0x751873ed00000000, + 0x9dc3885400000000, 0x4f9f624400000000, 0xa74499fd00000000, + 0xde2ee4ec00000000, 0x36f51f5500000000, 0x2cfa1ece00000000, + 0xc421e57700000000, 0xbd4b986600000000, 0x559063df00000000, + 0xc853eb8b00000000, 0x2088103200000000, 0x59e26d2300000000, + 0xb139969a00000000, 0xab36970100000000, 0x43ed6cb800000000, + 0x3a8711a900000000, 0xd25cea1000000000, 0x9e3ec58800000000, + 0x76e53e3100000000, 0x0f8f432000000000, 0xe754b89900000000, + 0xfd5bb90200000000, 0x158042bb00000000, 0x6cea3faa00000000, + 0x8431c41300000000, 0x19f24c4700000000, 0xf129b7fe00000000, + 0x8843caef00000000, 0x6098315600000000, 0x7a9730cd00000000, + 0x924ccb7400000000, 0xeb26b66500000000, 0x03fd4ddc00000000, + 0xd1a1a7cc00000000, 0x397a5c7500000000, 0x4010216400000000, + 0xa8cbdadd00000000, 0xb2c4db4600000000, 0x5a1f20ff00000000, + 0x23755dee00000000, 0xcbaea65700000000, 0x566d2e0300000000, + 0xbeb6d5ba00000000, 0xc7dca8ab00000000, 0x2f07531200000000, + 0x3508528900000000, 0xddd3a93000000000, 0xa4b9d42100000000, + 0x4c622f9800000000, 0x7d7bfbca00000000, 0x95a0007300000000, + 0xecca7d6200000000, 0x041186db00000000, 0x1e1e874000000000, + 0xf6c57cf900000000, 0x8faf01e800000000, 0x6774fa5100000000, + 0xfab7720500000000, 0x126c89bc00000000, 0x6b06f4ad00000000, + 0x83dd0f1400000000, 0x99d20e8f00000000, 0x7109f53600000000, + 0x0863882700000000, 0xe0b8739e00000000, 0x32e4998e00000000, + 0xda3f623700000000, 0xa3551f2600000000, 0x4b8ee49f00000000, + 0x5181e50400000000, 0xb95a1ebd00000000, 0xc03063ac00000000, + 0x28eb981500000000, 0xb528104100000000, 0x5df3ebf800000000, + 0x249996e900000000, 0xcc426d5000000000, 0xd64d6ccb00000000, + 0x3e96977200000000, 0x47fcea6300000000, 0xaf2711da00000000, + 0xe3453e4200000000, 0x0b9ec5fb00000000, 0x72f4b8ea00000000, + 0x9a2f435300000000, 0x802042c800000000, 0x68fbb97100000000, + 0x1191c46000000000, 0xf94a3fd900000000, 0x6489b78d00000000, + 0x8c524c3400000000, 0xf538312500000000, 0x1de3ca9c00000000, + 0x07eccb0700000000, 0xef3730be00000000, 0x965d4daf00000000, + 0x7e86b61600000000, 0xacda5c0600000000, 0x4401a7bf00000000, + 0x3d6bdaae00000000, 0xd5b0211700000000, 0xcfbf208c00000000, + 0x2764db3500000000, 0x5e0ea62400000000, 0xb6d55d9d00000000, + 0x2b16d5c900000000, 0xc3cd2e7000000000, 0xbaa7536100000000, + 0x527ca8d800000000, 0x4873a94300000000, 0xa0a852fa00000000, + 0xd9c22feb00000000, 0x3119d45200000000, 0xbbf0874e00000000, + 0x532b7cf700000000, 0x2a4101e600000000, 0xc29afa5f00000000, + 0xd895fbc400000000, 0x304e007d00000000, 0x49247d6c00000000, + 0xa1ff86d500000000, 0x3c3c0e8100000000, 0xd4e7f53800000000, + 0xad8d882900000000, 0x4556739000000000, 0x5f59720b00000000, + 0xb78289b200000000, 0xcee8f4a300000000, 0x26330f1a00000000, + 0xf46fe50a00000000, 0x1cb41eb300000000, 0x65de63a200000000, + 0x8d05981b00000000, 0x970a998000000000, 0x7fd1623900000000, + 0x06bb1f2800000000, 0xee60e49100000000, 0x73a36cc500000000, + 0x9b78977c00000000, 0xe212ea6d00000000, 0x0ac911d400000000, + 0x10c6104f00000000, 0xf81debf600000000, 0x817796e700000000, + 0x69ac6d5e00000000, 0x25ce42c600000000, 0xcd15b97f00000000, + 0xb47fc46e00000000, 0x5ca43fd700000000, 0x46ab3e4c00000000, + 0xae70c5f500000000, 0xd71ab8e400000000, 0x3fc1435d00000000, + 0xa202cb0900000000, 0x4ad930b000000000, 0x33b34da100000000, + 0xdb68b61800000000, 0xc167b78300000000, 0x29bc4c3a00000000, + 0x50d6312b00000000, 0xb80dca9200000000, 0x6a51208200000000, + 0x828adb3b00000000, 0xfbe0a62a00000000, 0x133b5d9300000000, + 0x09345c0800000000, 0xe1efa7b100000000, 0x9885daa000000000, + 0x705e211900000000, 0xed9da94d00000000, 0x054652f400000000, + 0x7c2c2fe500000000, 0x94f7d45c00000000, 0x8ef8d5c700000000, + 0x66232e7e00000000, 0x1f49536f00000000, 0xf792a8d600000000, + 0xc68b7c8400000000, 0x2e50873d00000000, 0x573afa2c00000000, + 0xbfe1019500000000, 0xa5ee000e00000000, 0x4d35fbb700000000, + 0x345f86a600000000, 0xdc847d1f00000000, 0x4147f54b00000000, + 0xa99c0ef200000000, 0xd0f673e300000000, 0x382d885a00000000, + 0x222289c100000000, 0xcaf9727800000000, 0xb3930f6900000000, + 0x5b48f4d000000000, 0x89141ec000000000, 0x61cfe57900000000, + 0x18a5986800000000, 0xf07e63d100000000, 0xea71624a00000000, + 0x02aa99f300000000, 0x7bc0e4e200000000, 0x931b1f5b00000000, + 0x0ed8970f00000000, 0xe6036cb600000000, 0x9f6911a700000000, + 0x77b2ea1e00000000, 0x6dbdeb8500000000, 0x8566103c00000000, + 0xfc0c6d2d00000000, 0x14d7969400000000, 0x58b5b90c00000000, + 0xb06e42b500000000, 0xc9043fa400000000, 0x21dfc41d00000000, + 0x3bd0c58600000000, 0xd30b3e3f00000000, 0xaa61432e00000000, + 0x42bab89700000000, 0xdf7930c300000000, 0x37a2cb7a00000000, + 0x4ec8b66b00000000, 0xa6134dd200000000, 0xbc1c4c4900000000, + 0x54c7b7f000000000, 0x2dadcae100000000, 0xc576315800000000, + 0x172adb4800000000, 0xfff120f100000000, 0x869b5de000000000, + 0x6e40a65900000000, 0x744fa7c200000000, 0x9c945c7b00000000, + 0xe5fe216a00000000, 0x0d25dad300000000, 0x90e6528700000000, + 0x783da93e00000000, 0x0157d42f00000000, 0xe98c2f9600000000, + 0xf3832e0d00000000, 0x1b58d5b400000000, 0x6232a8a500000000, + 0x8ae9531c00000000}, + {0x0000000000000000, 0x919168ae00000000, 0x6325a08700000000, + 0xf2b4c82900000000, 0x874c31d400000000, 0x16dd597a00000000, + 0xe469915300000000, 0x75f8f9fd00000000, 0x4f9f137300000000, + 0xde0e7bdd00000000, 0x2cbab3f400000000, 0xbd2bdb5a00000000, + 0xc8d322a700000000, 0x59424a0900000000, 0xabf6822000000000, + 0x3a67ea8e00000000, 0x9e3e27e600000000, 0x0faf4f4800000000, + 0xfd1b876100000000, 0x6c8aefcf00000000, 0x1972163200000000, + 0x88e37e9c00000000, 0x7a57b6b500000000, 0xebc6de1b00000000, + 0xd1a1349500000000, 0x40305c3b00000000, 0xb284941200000000, + 0x2315fcbc00000000, 0x56ed054100000000, 0xc77c6def00000000, + 0x35c8a5c600000000, 0xa459cd6800000000, 0x7d7b3f1700000000, + 0xecea57b900000000, 0x1e5e9f9000000000, 0x8fcff73e00000000, + 0xfa370ec300000000, 0x6ba6666d00000000, 0x9912ae4400000000, + 0x0883c6ea00000000, 0x32e42c6400000000, 0xa37544ca00000000, + 0x51c18ce300000000, 0xc050e44d00000000, 0xb5a81db000000000, + 0x2439751e00000000, 0xd68dbd3700000000, 0x471cd59900000000, + 0xe34518f100000000, 0x72d4705f00000000, 0x8060b87600000000, + 0x11f1d0d800000000, 0x6409292500000000, 0xf598418b00000000, + 0x072c89a200000000, 0x96bde10c00000000, 0xacda0b8200000000, + 0x3d4b632c00000000, 0xcfffab0500000000, 0x5e6ec3ab00000000, + 0x2b963a5600000000, 0xba0752f800000000, 0x48b39ad100000000, + 0xd922f27f00000000, 0xfaf67e2e00000000, 0x6b67168000000000, + 0x99d3dea900000000, 0x0842b60700000000, 0x7dba4ffa00000000, + 0xec2b275400000000, 0x1e9fef7d00000000, 0x8f0e87d300000000, + 0xb5696d5d00000000, 0x24f805f300000000, 0xd64ccdda00000000, + 0x47dda57400000000, 0x32255c8900000000, 0xa3b4342700000000, + 0x5100fc0e00000000, 0xc09194a000000000, 0x64c859c800000000, + 0xf559316600000000, 0x07edf94f00000000, 0x967c91e100000000, + 0xe384681c00000000, 0x721500b200000000, 0x80a1c89b00000000, + 0x1130a03500000000, 0x2b574abb00000000, 0xbac6221500000000, + 0x4872ea3c00000000, 0xd9e3829200000000, 0xac1b7b6f00000000, + 0x3d8a13c100000000, 0xcf3edbe800000000, 0x5eafb34600000000, + 0x878d413900000000, 0x161c299700000000, 0xe4a8e1be00000000, + 0x7539891000000000, 0x00c170ed00000000, 0x9150184300000000, + 0x63e4d06a00000000, 0xf275b8c400000000, 0xc812524a00000000, + 0x59833ae400000000, 0xab37f2cd00000000, 0x3aa69a6300000000, + 0x4f5e639e00000000, 0xdecf0b3000000000, 0x2c7bc31900000000, + 0xbdeaabb700000000, 0x19b366df00000000, 0x88220e7100000000, + 0x7a96c65800000000, 0xeb07aef600000000, 0x9eff570b00000000, + 0x0f6e3fa500000000, 0xfddaf78c00000000, 0x6c4b9f2200000000, + 0x562c75ac00000000, 0xc7bd1d0200000000, 0x3509d52b00000000, + 0xa498bd8500000000, 0xd160447800000000, 0x40f12cd600000000, + 0xb245e4ff00000000, 0x23d48c5100000000, 0xf4edfd5c00000000, + 0x657c95f200000000, 0x97c85ddb00000000, 0x0659357500000000, + 0x73a1cc8800000000, 0xe230a42600000000, 0x10846c0f00000000, + 0x811504a100000000, 0xbb72ee2f00000000, 0x2ae3868100000000, + 0xd8574ea800000000, 0x49c6260600000000, 0x3c3edffb00000000, + 0xadafb75500000000, 0x5f1b7f7c00000000, 0xce8a17d200000000, + 0x6ad3daba00000000, 0xfb42b21400000000, 0x09f67a3d00000000, + 0x9867129300000000, 0xed9feb6e00000000, 0x7c0e83c000000000, + 0x8eba4be900000000, 0x1f2b234700000000, 0x254cc9c900000000, + 0xb4dda16700000000, 0x4669694e00000000, 0xd7f801e000000000, + 0xa200f81d00000000, 0x339190b300000000, 0xc125589a00000000, + 0x50b4303400000000, 0x8996c24b00000000, 0x1807aae500000000, + 0xeab362cc00000000, 0x7b220a6200000000, 0x0edaf39f00000000, + 0x9f4b9b3100000000, 0x6dff531800000000, 0xfc6e3bb600000000, + 0xc609d13800000000, 0x5798b99600000000, 0xa52c71bf00000000, + 0x34bd191100000000, 0x4145e0ec00000000, 0xd0d4884200000000, + 0x2260406b00000000, 0xb3f128c500000000, 0x17a8e5ad00000000, + 0x86398d0300000000, 0x748d452a00000000, 0xe51c2d8400000000, + 0x90e4d47900000000, 0x0175bcd700000000, 0xf3c174fe00000000, + 0x62501c5000000000, 0x5837f6de00000000, 0xc9a69e7000000000, + 0x3b12565900000000, 0xaa833ef700000000, 0xdf7bc70a00000000, + 0x4eeaafa400000000, 0xbc5e678d00000000, 0x2dcf0f2300000000, + 0x0e1b837200000000, 0x9f8aebdc00000000, 0x6d3e23f500000000, + 0xfcaf4b5b00000000, 0x8957b2a600000000, 0x18c6da0800000000, + 0xea72122100000000, 0x7be37a8f00000000, 0x4184900100000000, + 0xd015f8af00000000, 0x22a1308600000000, 0xb330582800000000, + 0xc6c8a1d500000000, 0x5759c97b00000000, 0xa5ed015200000000, + 0x347c69fc00000000, 0x9025a49400000000, 0x01b4cc3a00000000, + 0xf300041300000000, 0x62916cbd00000000, 0x1769954000000000, + 0x86f8fdee00000000, 0x744c35c700000000, 0xe5dd5d6900000000, + 0xdfbab7e700000000, 0x4e2bdf4900000000, 0xbc9f176000000000, + 0x2d0e7fce00000000, 0x58f6863300000000, 0xc967ee9d00000000, + 0x3bd326b400000000, 0xaa424e1a00000000, 0x7360bc6500000000, + 0xe2f1d4cb00000000, 0x10451ce200000000, 0x81d4744c00000000, + 0xf42c8db100000000, 0x65bde51f00000000, 0x97092d3600000000, + 0x0698459800000000, 0x3cffaf1600000000, 0xad6ec7b800000000, + 0x5fda0f9100000000, 0xce4b673f00000000, 0xbbb39ec200000000, + 0x2a22f66c00000000, 0xd8963e4500000000, 0x490756eb00000000, + 0xed5e9b8300000000, 0x7ccff32d00000000, 0x8e7b3b0400000000, + 0x1fea53aa00000000, 0x6a12aa5700000000, 0xfb83c2f900000000, + 0x09370ad000000000, 0x98a6627e00000000, 0xa2c188f000000000, + 0x3350e05e00000000, 0xc1e4287700000000, 0x507540d900000000, + 0x258db92400000000, 0xb41cd18a00000000, 0x46a819a300000000, + 0xd739710d00000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, + 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b, + 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, + 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, + 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e, + 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, + 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, + 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, + 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719, + 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3, + 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa, + 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, + 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed, + 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, + 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25, + 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041, + 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, + 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, + 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, + 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758, + 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e, + 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, + 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed, + 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, + 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, + 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544, + 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, + 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c, + 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1, + 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, + 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, + 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, + 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976, + 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7, + 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, + 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, + 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12, + 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, + 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a, + 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e, + 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278, + 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682, + 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, + 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a, + 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561, + 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05, + 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9, + 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, + 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, + 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, + 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, + 0x264b06e6}, + {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, + 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3, + 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, + 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, + 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9, + 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, + 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, + 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712, + 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8, + 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6, + 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, + 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, + 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579, + 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, + 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37, + 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590, + 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, + 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, + 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, + 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678, + 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282, + 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, + 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, + 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, + 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, + 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146, + 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, + 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, + 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c, + 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, + 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, + 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, + 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d, + 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd, + 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, + 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, + 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7, + 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, + 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, + 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105, + 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff, + 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1, + 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, + 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, + 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617, + 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, + 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959, + 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, + 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, + 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a, + 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184, + 0x92364a30}, + {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, + 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8, + 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, + 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, + 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6, + 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, + 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d, + 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, + 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d, + 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408, + 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, + 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, + 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c, + 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, + 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a, + 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9, + 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, + 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, + 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, + 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4, + 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37, + 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, + 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca, + 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, + 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, + 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, + 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, + 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, + 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643, + 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, + 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, + 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, + 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8, + 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026, + 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, + 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, + 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118, + 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, + 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, + 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c, + 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf, + 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, + 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, + 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec, + 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82, + 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, + 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, + 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, + 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, + 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1, + 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869, + 0xe4c4abcc}, + {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, + 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271, + 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, + 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, + 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43, + 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, + 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, + 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314, + 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205, + 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136, + 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, + 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, + 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849, + 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, + 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8, + 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98, + 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, + 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba, + 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, + 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d, + 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c, + 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, + 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, + 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, + 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, + 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922, + 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532, + 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, + 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710, + 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, + 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, + 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, + 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956, + 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7, + 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, + 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, + 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5, + 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, + 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb, + 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb, + 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da, + 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, + 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, + 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48, + 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df, + 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, + 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, + 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, + 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, + 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c, + 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, + 0xca64c78c}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0xb029603d, 0x6053c07a, 0xd07aa047, 0xc0a680f5, + 0x708fe0c8, 0xa0f5408f, 0x10dc20b2, 0xc14b7030, 0x7162100d, + 0xa118b04a, 0x1131d077, 0x01edf0c5, 0xb1c490f8, 0x61be30bf, + 0xd1975082, 0x8297e060, 0x32be805d, 0xe2c4201a, 0x52ed4027, + 0x42316095, 0xf21800a8, 0x2262a0ef, 0x924bc0d2, 0x43dc9050, + 0xf3f5f06d, 0x238f502a, 0x93a63017, 0x837a10a5, 0x33537098, + 0xe329d0df, 0x5300b0e2, 0x042fc1c1, 0xb406a1fc, 0x647c01bb, + 0xd4556186, 0xc4894134, 0x74a02109, 0xa4da814e, 0x14f3e173, + 0xc564b1f1, 0x754dd1cc, 0xa537718b, 0x151e11b6, 0x05c23104, + 0xb5eb5139, 0x6591f17e, 0xd5b89143, 0x86b821a1, 0x3691419c, + 0xe6ebe1db, 0x56c281e6, 0x461ea154, 0xf637c169, 0x264d612e, + 0x96640113, 0x47f35191, 0xf7da31ac, 0x27a091eb, 0x9789f1d6, + 0x8755d164, 0x377cb159, 0xe706111e, 0x572f7123, 0x4958f358, + 0xf9719365, 0x290b3322, 0x9922531f, 0x89fe73ad, 0x39d71390, + 0xe9adb3d7, 0x5984d3ea, 0x88138368, 0x383ae355, 0xe8404312, + 0x5869232f, 0x48b5039d, 0xf89c63a0, 0x28e6c3e7, 0x98cfa3da, + 0xcbcf1338, 0x7be67305, 0xab9cd342, 0x1bb5b37f, 0x0b6993cd, + 0xbb40f3f0, 0x6b3a53b7, 0xdb13338a, 0x0a846308, 0xbaad0335, + 0x6ad7a372, 0xdafec34f, 0xca22e3fd, 0x7a0b83c0, 0xaa712387, + 0x1a5843ba, 0x4d773299, 0xfd5e52a4, 0x2d24f2e3, 0x9d0d92de, + 0x8dd1b26c, 0x3df8d251, 0xed827216, 0x5dab122b, 0x8c3c42a9, + 0x3c152294, 0xec6f82d3, 0x5c46e2ee, 0x4c9ac25c, 0xfcb3a261, + 0x2cc90226, 0x9ce0621b, 0xcfe0d2f9, 0x7fc9b2c4, 0xafb31283, + 0x1f9a72be, 0x0f46520c, 0xbf6f3231, 0x6f159276, 0xdf3cf24b, + 0x0eaba2c9, 0xbe82c2f4, 0x6ef862b3, 0xded1028e, 0xce0d223c, + 0x7e244201, 0xae5ee246, 0x1e77827b, 0x92b0e6b1, 0x2299868c, + 0xf2e326cb, 0x42ca46f6, 0x52166644, 0xe23f0679, 0x3245a63e, + 0x826cc603, 0x53fb9681, 0xe3d2f6bc, 0x33a856fb, 0x838136c6, + 0x935d1674, 0x23747649, 0xf30ed60e, 0x4327b633, 0x102706d1, + 0xa00e66ec, 0x7074c6ab, 0xc05da696, 0xd0818624, 0x60a8e619, + 0xb0d2465e, 0x00fb2663, 0xd16c76e1, 0x614516dc, 0xb13fb69b, + 0x0116d6a6, 0x11caf614, 0xa1e39629, 0x7199366e, 0xc1b05653, + 0x969f2770, 0x26b6474d, 0xf6cce70a, 0x46e58737, 0x5639a785, + 0xe610c7b8, 0x366a67ff, 0x864307c2, 0x57d45740, 0xe7fd377d, + 0x3787973a, 0x87aef707, 0x9772d7b5, 0x275bb788, 0xf72117cf, + 0x470877f2, 0x1408c710, 0xa421a72d, 0x745b076a, 0xc4726757, + 0xd4ae47e5, 0x648727d8, 0xb4fd879f, 0x04d4e7a2, 0xd543b720, + 0x656ad71d, 0xb510775a, 0x05391767, 0x15e537d5, 0xa5cc57e8, + 0x75b6f7af, 0xc59f9792, 0xdbe815e9, 0x6bc175d4, 0xbbbbd593, + 0x0b92b5ae, 0x1b4e951c, 0xab67f521, 0x7b1d5566, 0xcb34355b, + 0x1aa365d9, 0xaa8a05e4, 0x7af0a5a3, 0xcad9c59e, 0xda05e52c, + 0x6a2c8511, 0xba562556, 0x0a7f456b, 0x597ff589, 0xe95695b4, + 0x392c35f3, 0x890555ce, 0x99d9757c, 0x29f01541, 0xf98ab506, + 0x49a3d53b, 0x983485b9, 0x281de584, 0xf86745c3, 0x484e25fe, + 0x5892054c, 0xe8bb6571, 0x38c1c536, 0x88e8a50b, 0xdfc7d428, + 0x6feeb415, 0xbf941452, 0x0fbd746f, 0x1f6154dd, 0xaf4834e0, + 0x7f3294a7, 0xcf1bf49a, 0x1e8ca418, 0xaea5c425, 0x7edf6462, + 0xcef6045f, 0xde2a24ed, 0x6e0344d0, 0xbe79e497, 0x0e5084aa, + 0x5d503448, 0xed795475, 0x3d03f432, 0x8d2a940f, 0x9df6b4bd, + 0x2ddfd480, 0xfda574c7, 0x4d8c14fa, 0x9c1b4478, 0x2c322445, + 0xfc488402, 0x4c61e43f, 0x5cbdc48d, 0xec94a4b0, 0x3cee04f7, + 0x8cc764ca}, + {0x00000000, 0xa5d35ccb, 0x0ba1c84d, 0xae729486, 0x1642919b, + 0xb391cd50, 0x1de359d6, 0xb830051d, 0x6d8253ec, 0xc8510f27, + 0x66239ba1, 0xc3f0c76a, 0x7bc0c277, 0xde139ebc, 0x70610a3a, + 0xd5b256f1, 0x9b02d603, 0x3ed18ac8, 0x90a31e4e, 0x35704285, + 0x8d404798, 0x28931b53, 0x86e18fd5, 0x2332d31e, 0xf68085ef, + 0x5353d924, 0xfd214da2, 0x58f21169, 0xe0c21474, 0x451148bf, + 0xeb63dc39, 0x4eb080f2, 0x3605ac07, 0x93d6f0cc, 0x3da4644a, + 0x98773881, 0x20473d9c, 0x85946157, 0x2be6f5d1, 0x8e35a91a, + 0x5b87ffeb, 0xfe54a320, 0x502637a6, 0xf5f56b6d, 0x4dc56e70, + 0xe81632bb, 0x4664a63d, 0xe3b7faf6, 0xad077a04, 0x08d426cf, + 0xa6a6b249, 0x0375ee82, 0xbb45eb9f, 0x1e96b754, 0xb0e423d2, + 0x15377f19, 0xc08529e8, 0x65567523, 0xcb24e1a5, 0x6ef7bd6e, + 0xd6c7b873, 0x7314e4b8, 0xdd66703e, 0x78b52cf5, 0x6c0a580f, + 0xc9d904c4, 0x67ab9042, 0xc278cc89, 0x7a48c994, 0xdf9b955f, + 0x71e901d9, 0xd43a5d12, 0x01880be3, 0xa45b5728, 0x0a29c3ae, + 0xaffa9f65, 0x17ca9a78, 0xb219c6b3, 0x1c6b5235, 0xb9b80efe, + 0xf7088e0c, 0x52dbd2c7, 0xfca94641, 0x597a1a8a, 0xe14a1f97, + 0x4499435c, 0xeaebd7da, 0x4f388b11, 0x9a8adde0, 0x3f59812b, + 0x912b15ad, 0x34f84966, 0x8cc84c7b, 0x291b10b0, 0x87698436, + 0x22bad8fd, 0x5a0ff408, 0xffdca8c3, 0x51ae3c45, 0xf47d608e, + 0x4c4d6593, 0xe99e3958, 0x47ecadde, 0xe23ff115, 0x378da7e4, + 0x925efb2f, 0x3c2c6fa9, 0x99ff3362, 0x21cf367f, 0x841c6ab4, + 0x2a6efe32, 0x8fbda2f9, 0xc10d220b, 0x64de7ec0, 0xcaacea46, + 0x6f7fb68d, 0xd74fb390, 0x729cef5b, 0xdcee7bdd, 0x793d2716, + 0xac8f71e7, 0x095c2d2c, 0xa72eb9aa, 0x02fde561, 0xbacde07c, + 0x1f1ebcb7, 0xb16c2831, 0x14bf74fa, 0xd814b01e, 0x7dc7ecd5, + 0xd3b57853, 0x76662498, 0xce562185, 0x6b857d4e, 0xc5f7e9c8, + 0x6024b503, 0xb596e3f2, 0x1045bf39, 0xbe372bbf, 0x1be47774, + 0xa3d47269, 0x06072ea2, 0xa875ba24, 0x0da6e6ef, 0x4316661d, + 0xe6c53ad6, 0x48b7ae50, 0xed64f29b, 0x5554f786, 0xf087ab4d, + 0x5ef53fcb, 0xfb266300, 0x2e9435f1, 0x8b47693a, 0x2535fdbc, + 0x80e6a177, 0x38d6a46a, 0x9d05f8a1, 0x33776c27, 0x96a430ec, + 0xee111c19, 0x4bc240d2, 0xe5b0d454, 0x4063889f, 0xf8538d82, + 0x5d80d149, 0xf3f245cf, 0x56211904, 0x83934ff5, 0x2640133e, + 0x883287b8, 0x2de1db73, 0x95d1de6e, 0x300282a5, 0x9e701623, + 0x3ba34ae8, 0x7513ca1a, 0xd0c096d1, 0x7eb20257, 0xdb615e9c, + 0x63515b81, 0xc682074a, 0x68f093cc, 0xcd23cf07, 0x189199f6, + 0xbd42c53d, 0x133051bb, 0xb6e30d70, 0x0ed3086d, 0xab0054a6, + 0x0572c020, 0xa0a19ceb, 0xb41ee811, 0x11cdb4da, 0xbfbf205c, + 0x1a6c7c97, 0xa25c798a, 0x078f2541, 0xa9fdb1c7, 0x0c2eed0c, + 0xd99cbbfd, 0x7c4fe736, 0xd23d73b0, 0x77ee2f7b, 0xcfde2a66, + 0x6a0d76ad, 0xc47fe22b, 0x61acbee0, 0x2f1c3e12, 0x8acf62d9, + 0x24bdf65f, 0x816eaa94, 0x395eaf89, 0x9c8df342, 0x32ff67c4, + 0x972c3b0f, 0x429e6dfe, 0xe74d3135, 0x493fa5b3, 0xececf978, + 0x54dcfc65, 0xf10fa0ae, 0x5f7d3428, 0xfaae68e3, 0x821b4416, + 0x27c818dd, 0x89ba8c5b, 0x2c69d090, 0x9459d58d, 0x318a8946, + 0x9ff81dc0, 0x3a2b410b, 0xef9917fa, 0x4a4a4b31, 0xe438dfb7, + 0x41eb837c, 0xf9db8661, 0x5c08daaa, 0xf27a4e2c, 0x57a912e7, + 0x19199215, 0xbccacede, 0x12b85a58, 0xb76b0693, 0x0f5b038e, + 0xaa885f45, 0x04facbc3, 0xa1299708, 0x749bc1f9, 0xd1489d32, + 0x7f3a09b4, 0xdae9557f, 0x62d95062, 0xc70a0ca9, 0x6978982f, + 0xccabc4e4}, + {0x00000000, 0xb40b77a6, 0x29119f97, 0x9d1ae831, 0x13244ff4, + 0xa72f3852, 0x3a35d063, 0x8e3ea7c5, 0x674eef33, 0xd3459895, + 0x4e5f70a4, 0xfa540702, 0x746aa0c7, 0xc061d761, 0x5d7b3f50, + 0xe97048f6, 0xce9cde67, 0x7a97a9c1, 0xe78d41f0, 0x53863656, + 0xddb89193, 0x69b3e635, 0xf4a90e04, 0x40a279a2, 0xa9d23154, + 0x1dd946f2, 0x80c3aec3, 0x34c8d965, 0xbaf67ea0, 0x0efd0906, + 0x93e7e137, 0x27ec9691, 0x9c39bdcf, 0x2832ca69, 0xb5282258, + 0x012355fe, 0x8f1df23b, 0x3b16859d, 0xa60c6dac, 0x12071a0a, + 0xfb7752fc, 0x4f7c255a, 0xd266cd6b, 0x666dbacd, 0xe8531d08, + 0x5c586aae, 0xc142829f, 0x7549f539, 0x52a563a8, 0xe6ae140e, + 0x7bb4fc3f, 0xcfbf8b99, 0x41812c5c, 0xf58a5bfa, 0x6890b3cb, + 0xdc9bc46d, 0x35eb8c9b, 0x81e0fb3d, 0x1cfa130c, 0xa8f164aa, + 0x26cfc36f, 0x92c4b4c9, 0x0fde5cf8, 0xbbd52b5e, 0x79750b44, + 0xcd7e7ce2, 0x506494d3, 0xe46fe375, 0x6a5144b0, 0xde5a3316, + 0x4340db27, 0xf74bac81, 0x1e3be477, 0xaa3093d1, 0x372a7be0, + 0x83210c46, 0x0d1fab83, 0xb914dc25, 0x240e3414, 0x900543b2, + 0xb7e9d523, 0x03e2a285, 0x9ef84ab4, 0x2af33d12, 0xa4cd9ad7, + 0x10c6ed71, 0x8ddc0540, 0x39d772e6, 0xd0a73a10, 0x64ac4db6, + 0xf9b6a587, 0x4dbdd221, 0xc38375e4, 0x77880242, 0xea92ea73, + 0x5e999dd5, 0xe54cb68b, 0x5147c12d, 0xcc5d291c, 0x78565eba, + 0xf668f97f, 0x42638ed9, 0xdf7966e8, 0x6b72114e, 0x820259b8, + 0x36092e1e, 0xab13c62f, 0x1f18b189, 0x9126164c, 0x252d61ea, + 0xb83789db, 0x0c3cfe7d, 0x2bd068ec, 0x9fdb1f4a, 0x02c1f77b, + 0xb6ca80dd, 0x38f42718, 0x8cff50be, 0x11e5b88f, 0xa5eecf29, + 0x4c9e87df, 0xf895f079, 0x658f1848, 0xd1846fee, 0x5fbac82b, + 0xebb1bf8d, 0x76ab57bc, 0xc2a0201a, 0xf2ea1688, 0x46e1612e, + 0xdbfb891f, 0x6ff0feb9, 0xe1ce597c, 0x55c52eda, 0xc8dfc6eb, + 0x7cd4b14d, 0x95a4f9bb, 0x21af8e1d, 0xbcb5662c, 0x08be118a, + 0x8680b64f, 0x328bc1e9, 0xaf9129d8, 0x1b9a5e7e, 0x3c76c8ef, + 0x887dbf49, 0x15675778, 0xa16c20de, 0x2f52871b, 0x9b59f0bd, + 0x0643188c, 0xb2486f2a, 0x5b3827dc, 0xef33507a, 0x7229b84b, + 0xc622cfed, 0x481c6828, 0xfc171f8e, 0x610df7bf, 0xd5068019, + 0x6ed3ab47, 0xdad8dce1, 0x47c234d0, 0xf3c94376, 0x7df7e4b3, + 0xc9fc9315, 0x54e67b24, 0xe0ed0c82, 0x099d4474, 0xbd9633d2, + 0x208cdbe3, 0x9487ac45, 0x1ab90b80, 0xaeb27c26, 0x33a89417, + 0x87a3e3b1, 0xa04f7520, 0x14440286, 0x895eeab7, 0x3d559d11, + 0xb36b3ad4, 0x07604d72, 0x9a7aa543, 0x2e71d2e5, 0xc7019a13, + 0x730aedb5, 0xee100584, 0x5a1b7222, 0xd425d5e7, 0x602ea241, + 0xfd344a70, 0x493f3dd6, 0x8b9f1dcc, 0x3f946a6a, 0xa28e825b, + 0x1685f5fd, 0x98bb5238, 0x2cb0259e, 0xb1aacdaf, 0x05a1ba09, + 0xecd1f2ff, 0x58da8559, 0xc5c06d68, 0x71cb1ace, 0xfff5bd0b, + 0x4bfecaad, 0xd6e4229c, 0x62ef553a, 0x4503c3ab, 0xf108b40d, + 0x6c125c3c, 0xd8192b9a, 0x56278c5f, 0xe22cfbf9, 0x7f3613c8, + 0xcb3d646e, 0x224d2c98, 0x96465b3e, 0x0b5cb30f, 0xbf57c4a9, + 0x3169636c, 0x856214ca, 0x1878fcfb, 0xac738b5d, 0x17a6a003, + 0xa3add7a5, 0x3eb73f94, 0x8abc4832, 0x0482eff7, 0xb0899851, + 0x2d937060, 0x999807c6, 0x70e84f30, 0xc4e33896, 0x59f9d0a7, + 0xedf2a701, 0x63cc00c4, 0xd7c77762, 0x4add9f53, 0xfed6e8f5, + 0xd93a7e64, 0x6d3109c2, 0xf02be1f3, 0x44209655, 0xca1e3190, + 0x7e154636, 0xe30fae07, 0x5704d9a1, 0xbe749157, 0x0a7fe6f1, + 0x97650ec0, 0x236e7966, 0xad50dea3, 0x195ba905, 0x84414134, + 0x304a3692}, + {0x00000000, 0x9e00aacc, 0x7d072542, 0xe3078f8e, 0xfa0e4a84, + 0x640ee048, 0x87096fc6, 0x1909c50a, 0xb51be5d3, 0x2b1b4f1f, + 0xc81cc091, 0x561c6a5d, 0x4f15af57, 0xd115059b, 0x32128a15, + 0xac1220d9, 0x2b31bb7c, 0xb53111b0, 0x56369e3e, 0xc83634f2, + 0xd13ff1f8, 0x4f3f5b34, 0xac38d4ba, 0x32387e76, 0x9e2a5eaf, + 0x002af463, 0xe32d7bed, 0x7d2dd121, 0x6424142b, 0xfa24bee7, + 0x19233169, 0x87239ba5, 0x566276f9, 0xc862dc35, 0x2b6553bb, + 0xb565f977, 0xac6c3c7d, 0x326c96b1, 0xd16b193f, 0x4f6bb3f3, + 0xe379932a, 0x7d7939e6, 0x9e7eb668, 0x007e1ca4, 0x1977d9ae, + 0x87777362, 0x6470fcec, 0xfa705620, 0x7d53cd85, 0xe3536749, + 0x0054e8c7, 0x9e54420b, 0x875d8701, 0x195d2dcd, 0xfa5aa243, + 0x645a088f, 0xc8482856, 0x5648829a, 0xb54f0d14, 0x2b4fa7d8, + 0x324662d2, 0xac46c81e, 0x4f414790, 0xd141ed5c, 0xedc29d29, + 0x73c237e5, 0x90c5b86b, 0x0ec512a7, 0x17ccd7ad, 0x89cc7d61, + 0x6acbf2ef, 0xf4cb5823, 0x58d978fa, 0xc6d9d236, 0x25de5db8, + 0xbbdef774, 0xa2d7327e, 0x3cd798b2, 0xdfd0173c, 0x41d0bdf0, + 0xc6f32655, 0x58f38c99, 0xbbf40317, 0x25f4a9db, 0x3cfd6cd1, + 0xa2fdc61d, 0x41fa4993, 0xdffae35f, 0x73e8c386, 0xede8694a, + 0x0eefe6c4, 0x90ef4c08, 0x89e68902, 0x17e623ce, 0xf4e1ac40, + 0x6ae1068c, 0xbba0ebd0, 0x25a0411c, 0xc6a7ce92, 0x58a7645e, + 0x41aea154, 0xdfae0b98, 0x3ca98416, 0xa2a92eda, 0x0ebb0e03, + 0x90bba4cf, 0x73bc2b41, 0xedbc818d, 0xf4b54487, 0x6ab5ee4b, + 0x89b261c5, 0x17b2cb09, 0x909150ac, 0x0e91fa60, 0xed9675ee, + 0x7396df22, 0x6a9f1a28, 0xf49fb0e4, 0x17983f6a, 0x899895a6, + 0x258ab57f, 0xbb8a1fb3, 0x588d903d, 0xc68d3af1, 0xdf84fffb, + 0x41845537, 0xa283dab9, 0x3c837075, 0xda853b53, 0x4485919f, + 0xa7821e11, 0x3982b4dd, 0x208b71d7, 0xbe8bdb1b, 0x5d8c5495, + 0xc38cfe59, 0x6f9ede80, 0xf19e744c, 0x1299fbc2, 0x8c99510e, + 0x95909404, 0x0b903ec8, 0xe897b146, 0x76971b8a, 0xf1b4802f, + 0x6fb42ae3, 0x8cb3a56d, 0x12b30fa1, 0x0bbacaab, 0x95ba6067, + 0x76bdefe9, 0xe8bd4525, 0x44af65fc, 0xdaafcf30, 0x39a840be, + 0xa7a8ea72, 0xbea12f78, 0x20a185b4, 0xc3a60a3a, 0x5da6a0f6, + 0x8ce74daa, 0x12e7e766, 0xf1e068e8, 0x6fe0c224, 0x76e9072e, + 0xe8e9ade2, 0x0bee226c, 0x95ee88a0, 0x39fca879, 0xa7fc02b5, + 0x44fb8d3b, 0xdafb27f7, 0xc3f2e2fd, 0x5df24831, 0xbef5c7bf, + 0x20f56d73, 0xa7d6f6d6, 0x39d65c1a, 0xdad1d394, 0x44d17958, + 0x5dd8bc52, 0xc3d8169e, 0x20df9910, 0xbedf33dc, 0x12cd1305, + 0x8ccdb9c9, 0x6fca3647, 0xf1ca9c8b, 0xe8c35981, 0x76c3f34d, + 0x95c47cc3, 0x0bc4d60f, 0x3747a67a, 0xa9470cb6, 0x4a408338, + 0xd44029f4, 0xcd49ecfe, 0x53494632, 0xb04ec9bc, 0x2e4e6370, + 0x825c43a9, 0x1c5ce965, 0xff5b66eb, 0x615bcc27, 0x7852092d, + 0xe652a3e1, 0x05552c6f, 0x9b5586a3, 0x1c761d06, 0x8276b7ca, + 0x61713844, 0xff719288, 0xe6785782, 0x7878fd4e, 0x9b7f72c0, + 0x057fd80c, 0xa96df8d5, 0x376d5219, 0xd46add97, 0x4a6a775b, + 0x5363b251, 0xcd63189d, 0x2e649713, 0xb0643ddf, 0x6125d083, + 0xff257a4f, 0x1c22f5c1, 0x82225f0d, 0x9b2b9a07, 0x052b30cb, + 0xe62cbf45, 0x782c1589, 0xd43e3550, 0x4a3e9f9c, 0xa9391012, + 0x3739bade, 0x2e307fd4, 0xb030d518, 0x53375a96, 0xcd37f05a, + 0x4a146bff, 0xd414c133, 0x37134ebd, 0xa913e471, 0xb01a217b, + 0x2e1a8bb7, 0xcd1d0439, 0x531daef5, 0xff0f8e2c, 0x610f24e0, + 0x8208ab6e, 0x1c0801a2, 0x0501c4a8, 0x9b016e64, 0x7806e1ea, + 0xe6064b26}}; + +#endif + +#endif + +#if N == 3 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f, + 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999, + 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee, + 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615, + 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383, + 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb, + 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275, + 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d, + 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b, + 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460, + 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317, + 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1, + 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5, + 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd, + 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04, + 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c, + 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7, + 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11, + 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66, + 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7, + 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871, + 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309, + 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd, + 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85, + 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913, + 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d, + 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a, + 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc, + 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57, + 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f, + 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6, + 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e, + 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f, + 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289, + 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe, + 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05, + 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893, + 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb, + 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0, + 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8, + 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e, + 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5, + 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2, + 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574, + 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5, + 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add, + 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114, + 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c, + 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7, + 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701, + 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076, + 0x09cd8551}, + {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193, + 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2, + 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c, + 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71, + 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a, + 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d, + 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71, + 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436, + 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d, + 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000, + 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae, + 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf, + 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930, + 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277, + 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff, + 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8, + 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef, + 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e, + 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20, + 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95, + 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e, + 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9, + 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d, + 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a, + 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151, + 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4, + 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a, + 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b, + 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c, + 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b, + 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3, + 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4, + 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b, + 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a, + 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4, + 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189, + 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92, + 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5, + 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9, + 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe, + 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5, + 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8, + 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66, + 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707, + 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8, + 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f, + 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707, + 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40, + 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017, + 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876, + 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8, + 0x7bc97a0c}, + {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300, + 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0, + 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80, + 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701, + 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41, + 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81, + 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43, + 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83, + 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3, + 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42, + 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202, + 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2, + 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7, + 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407, + 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47, + 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87, + 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86, + 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46, + 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506, + 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44, + 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704, + 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4, + 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5, + 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505, + 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45, + 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f, + 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f, + 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f, + 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e, + 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e, + 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e, + 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce, + 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c, + 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc, + 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c, + 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d, + 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d, + 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d, + 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88, + 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48, + 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708, + 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89, + 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9, + 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309, + 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb, + 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b, + 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b, + 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b, + 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a, + 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a, + 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a, + 0x7851a2ca}, + {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb, + 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8, + 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0, + 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f, + 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a, + 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf, + 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5, + 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380, + 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815, + 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa, + 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2, + 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1, + 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1, + 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4, + 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa, + 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df, + 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6, + 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5, + 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad, + 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca, + 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f, + 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a, + 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8, + 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d, + 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708, + 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d, + 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865, + 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636, + 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f, + 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a, + 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744, + 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061, + 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0, + 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293, + 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb, + 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874, + 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1, + 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4, + 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f, + 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a, + 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f, + 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120, + 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778, + 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b, + 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a, + 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af, + 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81, + 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4, + 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd, + 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e, + 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6, + 0x566b6848}, + {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59, + 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4, + 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67, + 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef, + 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97, + 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88, + 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687, + 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698, + 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0, + 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068, + 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb, + 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056, + 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016, + 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009, + 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028, + 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037, + 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a, + 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7, + 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054, + 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7, + 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af, + 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0, + 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4, + 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab, + 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3, + 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a, + 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9, + 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54, + 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09, + 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16, + 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37, + 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28, + 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e, + 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3, + 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40, + 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8, + 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0, + 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf, + 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6, + 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9, + 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1, + 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059, + 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca, + 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067, + 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031, + 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e, + 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f, + 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010, + 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d, + 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0, + 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073, + 0xd8ac6b35}, + {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2, + 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd, + 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696, + 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3, + 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f, + 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35, + 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5, + 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f, + 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673, + 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46, + 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d, + 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632, + 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28, + 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192, + 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c, + 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6, + 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0, + 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff, + 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4, + 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95, + 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9, + 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03, + 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7, + 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d, + 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151, + 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808, + 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343, + 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c, + 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a, + 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0, + 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e, + 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594, + 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6, + 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399, + 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2, + 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7, + 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb, + 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571, + 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289, + 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33, + 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f, + 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a, + 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461, + 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e, + 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c, + 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6, + 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918, + 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2, + 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484, + 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb, + 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0, + 0xa140efa8}, + {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706, + 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed, + 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289, + 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a, + 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214, + 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3, + 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3, + 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254, + 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a, + 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9, + 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad, + 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746, + 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060, + 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187, + 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef, + 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408, + 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e, + 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495, + 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1, + 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532, + 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c, + 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb, + 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb, + 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c, + 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42, + 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060, + 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04, + 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef, + 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99, + 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e, + 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16, + 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1, + 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7, + 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c, + 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38, + 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb, + 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5, + 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42, + 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62, + 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85, + 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb, + 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18, + 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c, + 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997, + 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1, + 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36, + 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e, + 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9, + 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf, + 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24, + 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040, + 0x917cd6a1}, + {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf, + 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd, + 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896, + 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9, + 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3, + 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f, + 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d, + 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1, + 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab, + 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4, + 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f, + 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d, + 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4, + 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978, + 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad, + 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621, + 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46, + 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854, + 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f, + 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a, + 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890, + 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c, + 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4, + 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238, + 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622, + 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab, + 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0, + 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2, + 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295, + 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19, + 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc, + 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140, + 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd, + 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf, + 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184, + 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb, + 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1, + 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d, + 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb, + 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257, + 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d, + 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22, + 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069, + 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b, + 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6, + 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a, + 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf, + 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33, + 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254, + 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146, + 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d, + 0x18ba364e}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0x43cba68700000000, 0xc7903cd400000000, + 0x845b9a5300000000, 0xcf27087300000000, 0x8cecaef400000000, + 0x08b734a700000000, 0x4b7c922000000000, 0x9e4f10e600000000, + 0xdd84b66100000000, 0x59df2c3200000000, 0x1a148ab500000000, + 0x5168189500000000, 0x12a3be1200000000, 0x96f8244100000000, + 0xd53382c600000000, 0x7d99511700000000, 0x3e52f79000000000, + 0xba096dc300000000, 0xf9c2cb4400000000, 0xb2be596400000000, + 0xf175ffe300000000, 0x752e65b000000000, 0x36e5c33700000000, + 0xe3d641f100000000, 0xa01de77600000000, 0x24467d2500000000, + 0x678ddba200000000, 0x2cf1498200000000, 0x6f3aef0500000000, + 0xeb61755600000000, 0xa8aad3d100000000, 0xfa32a32e00000000, + 0xb9f905a900000000, 0x3da29ffa00000000, 0x7e69397d00000000, + 0x3515ab5d00000000, 0x76de0dda00000000, 0xf285978900000000, + 0xb14e310e00000000, 0x647db3c800000000, 0x27b6154f00000000, + 0xa3ed8f1c00000000, 0xe026299b00000000, 0xab5abbbb00000000, + 0xe8911d3c00000000, 0x6cca876f00000000, 0x2f0121e800000000, + 0x87abf23900000000, 0xc46054be00000000, 0x403bceed00000000, + 0x03f0686a00000000, 0x488cfa4a00000000, 0x0b475ccd00000000, + 0x8f1cc69e00000000, 0xccd7601900000000, 0x19e4e2df00000000, + 0x5a2f445800000000, 0xde74de0b00000000, 0x9dbf788c00000000, + 0xd6c3eaac00000000, 0x95084c2b00000000, 0x1153d67800000000, + 0x529870ff00000000, 0xf465465d00000000, 0xb7aee0da00000000, + 0x33f57a8900000000, 0x703edc0e00000000, 0x3b424e2e00000000, + 0x7889e8a900000000, 0xfcd272fa00000000, 0xbf19d47d00000000, + 0x6a2a56bb00000000, 0x29e1f03c00000000, 0xadba6a6f00000000, + 0xee71cce800000000, 0xa50d5ec800000000, 0xe6c6f84f00000000, + 0x629d621c00000000, 0x2156c49b00000000, 0x89fc174a00000000, + 0xca37b1cd00000000, 0x4e6c2b9e00000000, 0x0da78d1900000000, + 0x46db1f3900000000, 0x0510b9be00000000, 0x814b23ed00000000, + 0xc280856a00000000, 0x17b307ac00000000, 0x5478a12b00000000, + 0xd0233b7800000000, 0x93e89dff00000000, 0xd8940fdf00000000, + 0x9b5fa95800000000, 0x1f04330b00000000, 0x5ccf958c00000000, + 0x0e57e57300000000, 0x4d9c43f400000000, 0xc9c7d9a700000000, + 0x8a0c7f2000000000, 0xc170ed0000000000, 0x82bb4b8700000000, + 0x06e0d1d400000000, 0x452b775300000000, 0x9018f59500000000, + 0xd3d3531200000000, 0x5788c94100000000, 0x14436fc600000000, + 0x5f3ffde600000000, 0x1cf45b6100000000, 0x98afc13200000000, + 0xdb6467b500000000, 0x73ceb46400000000, 0x300512e300000000, + 0xb45e88b000000000, 0xf7952e3700000000, 0xbce9bc1700000000, + 0xff221a9000000000, 0x7b7980c300000000, 0x38b2264400000000, + 0xed81a48200000000, 0xae4a020500000000, 0x2a11985600000000, + 0x69da3ed100000000, 0x22a6acf100000000, 0x616d0a7600000000, + 0xe536902500000000, 0xa6fd36a200000000, 0xe8cb8cba00000000, + 0xab002a3d00000000, 0x2f5bb06e00000000, 0x6c9016e900000000, + 0x27ec84c900000000, 0x6427224e00000000, 0xe07cb81d00000000, + 0xa3b71e9a00000000, 0x76849c5c00000000, 0x354f3adb00000000, + 0xb114a08800000000, 0xf2df060f00000000, 0xb9a3942f00000000, + 0xfa6832a800000000, 0x7e33a8fb00000000, 0x3df80e7c00000000, + 0x9552ddad00000000, 0xd6997b2a00000000, 0x52c2e17900000000, + 0x110947fe00000000, 0x5a75d5de00000000, 0x19be735900000000, + 0x9de5e90a00000000, 0xde2e4f8d00000000, 0x0b1dcd4b00000000, + 0x48d66bcc00000000, 0xcc8df19f00000000, 0x8f46571800000000, + 0xc43ac53800000000, 0x87f163bf00000000, 0x03aaf9ec00000000, + 0x40615f6b00000000, 0x12f92f9400000000, 0x5132891300000000, + 0xd569134000000000, 0x96a2b5c700000000, 0xddde27e700000000, + 0x9e15816000000000, 0x1a4e1b3300000000, 0x5985bdb400000000, + 0x8cb63f7200000000, 0xcf7d99f500000000, 0x4b2603a600000000, + 0x08eda52100000000, 0x4391370100000000, 0x005a918600000000, + 0x84010bd500000000, 0xc7caad5200000000, 0x6f607e8300000000, + 0x2cabd80400000000, 0xa8f0425700000000, 0xeb3be4d000000000, + 0xa04776f000000000, 0xe38cd07700000000, 0x67d74a2400000000, + 0x241ceca300000000, 0xf12f6e6500000000, 0xb2e4c8e200000000, + 0x36bf52b100000000, 0x7574f43600000000, 0x3e08661600000000, + 0x7dc3c09100000000, 0xf9985ac200000000, 0xba53fc4500000000, + 0x1caecae700000000, 0x5f656c6000000000, 0xdb3ef63300000000, + 0x98f550b400000000, 0xd389c29400000000, 0x9042641300000000, + 0x1419fe4000000000, 0x57d258c700000000, 0x82e1da0100000000, + 0xc12a7c8600000000, 0x4571e6d500000000, 0x06ba405200000000, + 0x4dc6d27200000000, 0x0e0d74f500000000, 0x8a56eea600000000, + 0xc99d482100000000, 0x61379bf000000000, 0x22fc3d7700000000, + 0xa6a7a72400000000, 0xe56c01a300000000, 0xae10938300000000, + 0xeddb350400000000, 0x6980af5700000000, 0x2a4b09d000000000, + 0xff788b1600000000, 0xbcb32d9100000000, 0x38e8b7c200000000, + 0x7b23114500000000, 0x305f836500000000, 0x739425e200000000, + 0xf7cfbfb100000000, 0xb404193600000000, 0xe69c69c900000000, + 0xa557cf4e00000000, 0x210c551d00000000, 0x62c7f39a00000000, + 0x29bb61ba00000000, 0x6a70c73d00000000, 0xee2b5d6e00000000, + 0xade0fbe900000000, 0x78d3792f00000000, 0x3b18dfa800000000, + 0xbf4345fb00000000, 0xfc88e37c00000000, 0xb7f4715c00000000, + 0xf43fd7db00000000, 0x70644d8800000000, 0x33afeb0f00000000, + 0x9b0538de00000000, 0xd8ce9e5900000000, 0x5c95040a00000000, + 0x1f5ea28d00000000, 0x542230ad00000000, 0x17e9962a00000000, + 0x93b20c7900000000, 0xd079aafe00000000, 0x054a283800000000, + 0x46818ebf00000000, 0xc2da14ec00000000, 0x8111b26b00000000, + 0xca6d204b00000000, 0x89a686cc00000000, 0x0dfd1c9f00000000, + 0x4e36ba1800000000}, + {0x0000000000000000, 0xe1b652ef00000000, 0x836bd40500000000, + 0x62dd86ea00000000, 0x06d7a80b00000000, 0xe761fae400000000, + 0x85bc7c0e00000000, 0x640a2ee100000000, 0x0cae511700000000, + 0xed1803f800000000, 0x8fc5851200000000, 0x6e73d7fd00000000, + 0x0a79f91c00000000, 0xebcfabf300000000, 0x89122d1900000000, + 0x68a47ff600000000, 0x185ca32e00000000, 0xf9eaf1c100000000, + 0x9b37772b00000000, 0x7a8125c400000000, 0x1e8b0b2500000000, + 0xff3d59ca00000000, 0x9de0df2000000000, 0x7c568dcf00000000, + 0x14f2f23900000000, 0xf544a0d600000000, 0x9799263c00000000, + 0x762f74d300000000, 0x12255a3200000000, 0xf39308dd00000000, + 0x914e8e3700000000, 0x70f8dcd800000000, 0x30b8465d00000000, + 0xd10e14b200000000, 0xb3d3925800000000, 0x5265c0b700000000, + 0x366fee5600000000, 0xd7d9bcb900000000, 0xb5043a5300000000, + 0x54b268bc00000000, 0x3c16174a00000000, 0xdda045a500000000, + 0xbf7dc34f00000000, 0x5ecb91a000000000, 0x3ac1bf4100000000, + 0xdb77edae00000000, 0xb9aa6b4400000000, 0x581c39ab00000000, + 0x28e4e57300000000, 0xc952b79c00000000, 0xab8f317600000000, + 0x4a39639900000000, 0x2e334d7800000000, 0xcf851f9700000000, + 0xad58997d00000000, 0x4ceecb9200000000, 0x244ab46400000000, + 0xc5fce68b00000000, 0xa721606100000000, 0x4697328e00000000, + 0x229d1c6f00000000, 0xc32b4e8000000000, 0xa1f6c86a00000000, + 0x40409a8500000000, 0x60708dba00000000, 0x81c6df5500000000, + 0xe31b59bf00000000, 0x02ad0b5000000000, 0x66a725b100000000, + 0x8711775e00000000, 0xe5ccf1b400000000, 0x047aa35b00000000, + 0x6cdedcad00000000, 0x8d688e4200000000, 0xefb508a800000000, + 0x0e035a4700000000, 0x6a0974a600000000, 0x8bbf264900000000, + 0xe962a0a300000000, 0x08d4f24c00000000, 0x782c2e9400000000, + 0x999a7c7b00000000, 0xfb47fa9100000000, 0x1af1a87e00000000, + 0x7efb869f00000000, 0x9f4dd47000000000, 0xfd90529a00000000, + 0x1c26007500000000, 0x74827f8300000000, 0x95342d6c00000000, + 0xf7e9ab8600000000, 0x165ff96900000000, 0x7255d78800000000, + 0x93e3856700000000, 0xf13e038d00000000, 0x1088516200000000, + 0x50c8cbe700000000, 0xb17e990800000000, 0xd3a31fe200000000, + 0x32154d0d00000000, 0x561f63ec00000000, 0xb7a9310300000000, + 0xd574b7e900000000, 0x34c2e50600000000, 0x5c669af000000000, + 0xbdd0c81f00000000, 0xdf0d4ef500000000, 0x3ebb1c1a00000000, + 0x5ab132fb00000000, 0xbb07601400000000, 0xd9dae6fe00000000, + 0x386cb41100000000, 0x489468c900000000, 0xa9223a2600000000, + 0xcbffbccc00000000, 0x2a49ee2300000000, 0x4e43c0c200000000, + 0xaff5922d00000000, 0xcd2814c700000000, 0x2c9e462800000000, + 0x443a39de00000000, 0xa58c6b3100000000, 0xc751eddb00000000, + 0x26e7bf3400000000, 0x42ed91d500000000, 0xa35bc33a00000000, + 0xc18645d000000000, 0x2030173f00000000, 0x81e66bae00000000, + 0x6050394100000000, 0x028dbfab00000000, 0xe33bed4400000000, + 0x8731c3a500000000, 0x6687914a00000000, 0x045a17a000000000, + 0xe5ec454f00000000, 0x8d483ab900000000, 0x6cfe685600000000, + 0x0e23eebc00000000, 0xef95bc5300000000, 0x8b9f92b200000000, + 0x6a29c05d00000000, 0x08f446b700000000, 0xe942145800000000, + 0x99bac88000000000, 0x780c9a6f00000000, 0x1ad11c8500000000, + 0xfb674e6a00000000, 0x9f6d608b00000000, 0x7edb326400000000, + 0x1c06b48e00000000, 0xfdb0e66100000000, 0x9514999700000000, + 0x74a2cb7800000000, 0x167f4d9200000000, 0xf7c91f7d00000000, + 0x93c3319c00000000, 0x7275637300000000, 0x10a8e59900000000, + 0xf11eb77600000000, 0xb15e2df300000000, 0x50e87f1c00000000, + 0x3235f9f600000000, 0xd383ab1900000000, 0xb78985f800000000, + 0x563fd71700000000, 0x34e251fd00000000, 0xd554031200000000, + 0xbdf07ce400000000, 0x5c462e0b00000000, 0x3e9ba8e100000000, + 0xdf2dfa0e00000000, 0xbb27d4ef00000000, 0x5a91860000000000, + 0x384c00ea00000000, 0xd9fa520500000000, 0xa9028edd00000000, + 0x48b4dc3200000000, 0x2a695ad800000000, 0xcbdf083700000000, + 0xafd526d600000000, 0x4e63743900000000, 0x2cbef2d300000000, + 0xcd08a03c00000000, 0xa5acdfca00000000, 0x441a8d2500000000, + 0x26c70bcf00000000, 0xc771592000000000, 0xa37b77c100000000, + 0x42cd252e00000000, 0x2010a3c400000000, 0xc1a6f12b00000000, + 0xe196e61400000000, 0x0020b4fb00000000, 0x62fd321100000000, + 0x834b60fe00000000, 0xe7414e1f00000000, 0x06f71cf000000000, + 0x642a9a1a00000000, 0x859cc8f500000000, 0xed38b70300000000, + 0x0c8ee5ec00000000, 0x6e53630600000000, 0x8fe531e900000000, + 0xebef1f0800000000, 0x0a594de700000000, 0x6884cb0d00000000, + 0x893299e200000000, 0xf9ca453a00000000, 0x187c17d500000000, + 0x7aa1913f00000000, 0x9b17c3d000000000, 0xff1ded3100000000, + 0x1eabbfde00000000, 0x7c76393400000000, 0x9dc06bdb00000000, + 0xf564142d00000000, 0x14d246c200000000, 0x760fc02800000000, + 0x97b992c700000000, 0xf3b3bc2600000000, 0x1205eec900000000, + 0x70d8682300000000, 0x916e3acc00000000, 0xd12ea04900000000, + 0x3098f2a600000000, 0x5245744c00000000, 0xb3f326a300000000, + 0xd7f9084200000000, 0x364f5aad00000000, 0x5492dc4700000000, + 0xb5248ea800000000, 0xdd80f15e00000000, 0x3c36a3b100000000, + 0x5eeb255b00000000, 0xbf5d77b400000000, 0xdb57595500000000, + 0x3ae10bba00000000, 0x583c8d5000000000, 0xb98adfbf00000000, + 0xc972036700000000, 0x28c4518800000000, 0x4a19d76200000000, + 0xabaf858d00000000, 0xcfa5ab6c00000000, 0x2e13f98300000000, + 0x4cce7f6900000000, 0xad782d8600000000, 0xc5dc527000000000, + 0x246a009f00000000, 0x46b7867500000000, 0xa701d49a00000000, + 0xc30bfa7b00000000, 0x22bda89400000000, 0x40602e7e00000000, + 0xa1d67c9100000000}, + {0x0000000000000000, 0x5880e2d700000000, 0xf106b47400000000, + 0xa98656a300000000, 0xe20d68e900000000, 0xba8d8a3e00000000, + 0x130bdc9d00000000, 0x4b8b3e4a00000000, 0x851da10900000000, + 0xdd9d43de00000000, 0x741b157d00000000, 0x2c9bf7aa00000000, + 0x6710c9e000000000, 0x3f902b3700000000, 0x96167d9400000000, + 0xce969f4300000000, 0x0a3b421300000000, 0x52bba0c400000000, + 0xfb3df66700000000, 0xa3bd14b000000000, 0xe8362afa00000000, + 0xb0b6c82d00000000, 0x19309e8e00000000, 0x41b07c5900000000, + 0x8f26e31a00000000, 0xd7a601cd00000000, 0x7e20576e00000000, + 0x26a0b5b900000000, 0x6d2b8bf300000000, 0x35ab692400000000, + 0x9c2d3f8700000000, 0xc4addd5000000000, 0x1476842600000000, + 0x4cf666f100000000, 0xe570305200000000, 0xbdf0d28500000000, + 0xf67beccf00000000, 0xaefb0e1800000000, 0x077d58bb00000000, + 0x5ffdba6c00000000, 0x916b252f00000000, 0xc9ebc7f800000000, + 0x606d915b00000000, 0x38ed738c00000000, 0x73664dc600000000, + 0x2be6af1100000000, 0x8260f9b200000000, 0xdae01b6500000000, + 0x1e4dc63500000000, 0x46cd24e200000000, 0xef4b724100000000, + 0xb7cb909600000000, 0xfc40aedc00000000, 0xa4c04c0b00000000, + 0x0d461aa800000000, 0x55c6f87f00000000, 0x9b50673c00000000, + 0xc3d085eb00000000, 0x6a56d34800000000, 0x32d6319f00000000, + 0x795d0fd500000000, 0x21dded0200000000, 0x885bbba100000000, + 0xd0db597600000000, 0x28ec084d00000000, 0x706cea9a00000000, + 0xd9eabc3900000000, 0x816a5eee00000000, 0xcae160a400000000, + 0x9261827300000000, 0x3be7d4d000000000, 0x6367360700000000, + 0xadf1a94400000000, 0xf5714b9300000000, 0x5cf71d3000000000, + 0x0477ffe700000000, 0x4ffcc1ad00000000, 0x177c237a00000000, + 0xbefa75d900000000, 0xe67a970e00000000, 0x22d74a5e00000000, + 0x7a57a88900000000, 0xd3d1fe2a00000000, 0x8b511cfd00000000, + 0xc0da22b700000000, 0x985ac06000000000, 0x31dc96c300000000, + 0x695c741400000000, 0xa7caeb5700000000, 0xff4a098000000000, + 0x56cc5f2300000000, 0x0e4cbdf400000000, 0x45c783be00000000, + 0x1d47616900000000, 0xb4c137ca00000000, 0xec41d51d00000000, + 0x3c9a8c6b00000000, 0x641a6ebc00000000, 0xcd9c381f00000000, + 0x951cdac800000000, 0xde97e48200000000, 0x8617065500000000, + 0x2f9150f600000000, 0x7711b22100000000, 0xb9872d6200000000, + 0xe107cfb500000000, 0x4881991600000000, 0x10017bc100000000, + 0x5b8a458b00000000, 0x030aa75c00000000, 0xaa8cf1ff00000000, + 0xf20c132800000000, 0x36a1ce7800000000, 0x6e212caf00000000, + 0xc7a77a0c00000000, 0x9f2798db00000000, 0xd4aca69100000000, + 0x8c2c444600000000, 0x25aa12e500000000, 0x7d2af03200000000, + 0xb3bc6f7100000000, 0xeb3c8da600000000, 0x42badb0500000000, + 0x1a3a39d200000000, 0x51b1079800000000, 0x0931e54f00000000, + 0xa0b7b3ec00000000, 0xf837513b00000000, 0x50d8119a00000000, + 0x0858f34d00000000, 0xa1dea5ee00000000, 0xf95e473900000000, + 0xb2d5797300000000, 0xea559ba400000000, 0x43d3cd0700000000, + 0x1b532fd000000000, 0xd5c5b09300000000, 0x8d45524400000000, + 0x24c304e700000000, 0x7c43e63000000000, 0x37c8d87a00000000, + 0x6f483aad00000000, 0xc6ce6c0e00000000, 0x9e4e8ed900000000, + 0x5ae3538900000000, 0x0263b15e00000000, 0xabe5e7fd00000000, + 0xf365052a00000000, 0xb8ee3b6000000000, 0xe06ed9b700000000, + 0x49e88f1400000000, 0x11686dc300000000, 0xdffef28000000000, + 0x877e105700000000, 0x2ef846f400000000, 0x7678a42300000000, + 0x3df39a6900000000, 0x657378be00000000, 0xccf52e1d00000000, + 0x9475ccca00000000, 0x44ae95bc00000000, 0x1c2e776b00000000, + 0xb5a821c800000000, 0xed28c31f00000000, 0xa6a3fd5500000000, + 0xfe231f8200000000, 0x57a5492100000000, 0x0f25abf600000000, + 0xc1b334b500000000, 0x9933d66200000000, 0x30b580c100000000, + 0x6835621600000000, 0x23be5c5c00000000, 0x7b3ebe8b00000000, + 0xd2b8e82800000000, 0x8a380aff00000000, 0x4e95d7af00000000, + 0x1615357800000000, 0xbf9363db00000000, 0xe713810c00000000, + 0xac98bf4600000000, 0xf4185d9100000000, 0x5d9e0b3200000000, + 0x051ee9e500000000, 0xcb8876a600000000, 0x9308947100000000, + 0x3a8ec2d200000000, 0x620e200500000000, 0x29851e4f00000000, + 0x7105fc9800000000, 0xd883aa3b00000000, 0x800348ec00000000, + 0x783419d700000000, 0x20b4fb0000000000, 0x8932ada300000000, + 0xd1b24f7400000000, 0x9a39713e00000000, 0xc2b993e900000000, + 0x6b3fc54a00000000, 0x33bf279d00000000, 0xfd29b8de00000000, + 0xa5a95a0900000000, 0x0c2f0caa00000000, 0x54afee7d00000000, + 0x1f24d03700000000, 0x47a432e000000000, 0xee22644300000000, + 0xb6a2869400000000, 0x720f5bc400000000, 0x2a8fb91300000000, + 0x8309efb000000000, 0xdb890d6700000000, 0x9002332d00000000, + 0xc882d1fa00000000, 0x6104875900000000, 0x3984658e00000000, + 0xf712facd00000000, 0xaf92181a00000000, 0x06144eb900000000, + 0x5e94ac6e00000000, 0x151f922400000000, 0x4d9f70f300000000, + 0xe419265000000000, 0xbc99c48700000000, 0x6c429df100000000, + 0x34c27f2600000000, 0x9d44298500000000, 0xc5c4cb5200000000, + 0x8e4ff51800000000, 0xd6cf17cf00000000, 0x7f49416c00000000, + 0x27c9a3bb00000000, 0xe95f3cf800000000, 0xb1dfde2f00000000, + 0x1859888c00000000, 0x40d96a5b00000000, 0x0b52541100000000, + 0x53d2b6c600000000, 0xfa54e06500000000, 0xa2d402b200000000, + 0x6679dfe200000000, 0x3ef93d3500000000, 0x977f6b9600000000, + 0xcfff894100000000, 0x8474b70b00000000, 0xdcf455dc00000000, + 0x7572037f00000000, 0x2df2e1a800000000, 0xe3647eeb00000000, + 0xbbe49c3c00000000, 0x1262ca9f00000000, 0x4ae2284800000000, + 0x0169160200000000, 0x59e9f4d500000000, 0xf06fa27600000000, + 0xa8ef40a100000000}, + {0x0000000000000000, 0x463b676500000000, 0x8c76ceca00000000, + 0xca4da9af00000000, 0x59ebed4e00000000, 0x1fd08a2b00000000, + 0xd59d238400000000, 0x93a644e100000000, 0xb2d6db9d00000000, + 0xf4edbcf800000000, 0x3ea0155700000000, 0x789b723200000000, + 0xeb3d36d300000000, 0xad0651b600000000, 0x674bf81900000000, + 0x21709f7c00000000, 0x25abc6e000000000, 0x6390a18500000000, + 0xa9dd082a00000000, 0xefe66f4f00000000, 0x7c402bae00000000, + 0x3a7b4ccb00000000, 0xf036e56400000000, 0xb60d820100000000, + 0x977d1d7d00000000, 0xd1467a1800000000, 0x1b0bd3b700000000, + 0x5d30b4d200000000, 0xce96f03300000000, 0x88ad975600000000, + 0x42e03ef900000000, 0x04db599c00000000, 0x0b50fc1a00000000, + 0x4d6b9b7f00000000, 0x872632d000000000, 0xc11d55b500000000, + 0x52bb115400000000, 0x1480763100000000, 0xdecddf9e00000000, + 0x98f6b8fb00000000, 0xb986278700000000, 0xffbd40e200000000, + 0x35f0e94d00000000, 0x73cb8e2800000000, 0xe06dcac900000000, + 0xa656adac00000000, 0x6c1b040300000000, 0x2a20636600000000, + 0x2efb3afa00000000, 0x68c05d9f00000000, 0xa28df43000000000, + 0xe4b6935500000000, 0x7710d7b400000000, 0x312bb0d100000000, + 0xfb66197e00000000, 0xbd5d7e1b00000000, 0x9c2de16700000000, + 0xda16860200000000, 0x105b2fad00000000, 0x566048c800000000, + 0xc5c60c2900000000, 0x83fd6b4c00000000, 0x49b0c2e300000000, + 0x0f8ba58600000000, 0x16a0f83500000000, 0x509b9f5000000000, + 0x9ad636ff00000000, 0xdced519a00000000, 0x4f4b157b00000000, + 0x0970721e00000000, 0xc33ddbb100000000, 0x8506bcd400000000, + 0xa47623a800000000, 0xe24d44cd00000000, 0x2800ed6200000000, + 0x6e3b8a0700000000, 0xfd9dcee600000000, 0xbba6a98300000000, + 0x71eb002c00000000, 0x37d0674900000000, 0x330b3ed500000000, + 0x753059b000000000, 0xbf7df01f00000000, 0xf946977a00000000, + 0x6ae0d39b00000000, 0x2cdbb4fe00000000, 0xe6961d5100000000, + 0xa0ad7a3400000000, 0x81dde54800000000, 0xc7e6822d00000000, + 0x0dab2b8200000000, 0x4b904ce700000000, 0xd836080600000000, + 0x9e0d6f6300000000, 0x5440c6cc00000000, 0x127ba1a900000000, + 0x1df0042f00000000, 0x5bcb634a00000000, 0x9186cae500000000, + 0xd7bdad8000000000, 0x441be96100000000, 0x02208e0400000000, + 0xc86d27ab00000000, 0x8e5640ce00000000, 0xaf26dfb200000000, + 0xe91db8d700000000, 0x2350117800000000, 0x656b761d00000000, + 0xf6cd32fc00000000, 0xb0f6559900000000, 0x7abbfc3600000000, + 0x3c809b5300000000, 0x385bc2cf00000000, 0x7e60a5aa00000000, + 0xb42d0c0500000000, 0xf2166b6000000000, 0x61b02f8100000000, + 0x278b48e400000000, 0xedc6e14b00000000, 0xabfd862e00000000, + 0x8a8d195200000000, 0xccb67e3700000000, 0x06fbd79800000000, + 0x40c0b0fd00000000, 0xd366f41c00000000, 0x955d937900000000, + 0x5f103ad600000000, 0x192b5db300000000, 0x2c40f16b00000000, + 0x6a7b960e00000000, 0xa0363fa100000000, 0xe60d58c400000000, + 0x75ab1c2500000000, 0x33907b4000000000, 0xf9ddd2ef00000000, + 0xbfe6b58a00000000, 0x9e962af600000000, 0xd8ad4d9300000000, + 0x12e0e43c00000000, 0x54db835900000000, 0xc77dc7b800000000, + 0x8146a0dd00000000, 0x4b0b097200000000, 0x0d306e1700000000, + 0x09eb378b00000000, 0x4fd050ee00000000, 0x859df94100000000, + 0xc3a69e2400000000, 0x5000dac500000000, 0x163bbda000000000, + 0xdc76140f00000000, 0x9a4d736a00000000, 0xbb3dec1600000000, + 0xfd068b7300000000, 0x374b22dc00000000, 0x717045b900000000, + 0xe2d6015800000000, 0xa4ed663d00000000, 0x6ea0cf9200000000, + 0x289ba8f700000000, 0x27100d7100000000, 0x612b6a1400000000, + 0xab66c3bb00000000, 0xed5da4de00000000, 0x7efbe03f00000000, + 0x38c0875a00000000, 0xf28d2ef500000000, 0xb4b6499000000000, + 0x95c6d6ec00000000, 0xd3fdb18900000000, 0x19b0182600000000, + 0x5f8b7f4300000000, 0xcc2d3ba200000000, 0x8a165cc700000000, + 0x405bf56800000000, 0x0660920d00000000, 0x02bbcb9100000000, + 0x4480acf400000000, 0x8ecd055b00000000, 0xc8f6623e00000000, + 0x5b5026df00000000, 0x1d6b41ba00000000, 0xd726e81500000000, + 0x911d8f7000000000, 0xb06d100c00000000, 0xf656776900000000, + 0x3c1bdec600000000, 0x7a20b9a300000000, 0xe986fd4200000000, + 0xafbd9a2700000000, 0x65f0338800000000, 0x23cb54ed00000000, + 0x3ae0095e00000000, 0x7cdb6e3b00000000, 0xb696c79400000000, + 0xf0ada0f100000000, 0x630be41000000000, 0x2530837500000000, + 0xef7d2ada00000000, 0xa9464dbf00000000, 0x8836d2c300000000, + 0xce0db5a600000000, 0x04401c0900000000, 0x427b7b6c00000000, + 0xd1dd3f8d00000000, 0x97e658e800000000, 0x5dabf14700000000, + 0x1b90962200000000, 0x1f4bcfbe00000000, 0x5970a8db00000000, + 0x933d017400000000, 0xd506661100000000, 0x46a022f000000000, + 0x009b459500000000, 0xcad6ec3a00000000, 0x8ced8b5f00000000, + 0xad9d142300000000, 0xeba6734600000000, 0x21ebdae900000000, + 0x67d0bd8c00000000, 0xf476f96d00000000, 0xb24d9e0800000000, + 0x780037a700000000, 0x3e3b50c200000000, 0x31b0f54400000000, + 0x778b922100000000, 0xbdc63b8e00000000, 0xfbfd5ceb00000000, + 0x685b180a00000000, 0x2e607f6f00000000, 0xe42dd6c000000000, + 0xa216b1a500000000, 0x83662ed900000000, 0xc55d49bc00000000, + 0x0f10e01300000000, 0x492b877600000000, 0xda8dc39700000000, + 0x9cb6a4f200000000, 0x56fb0d5d00000000, 0x10c06a3800000000, + 0x141b33a400000000, 0x522054c100000000, 0x986dfd6e00000000, + 0xde569a0b00000000, 0x4df0deea00000000, 0x0bcbb98f00000000, + 0xc186102000000000, 0x87bd774500000000, 0xa6cde83900000000, + 0xe0f68f5c00000000, 0x2abb26f300000000, 0x6c80419600000000, + 0xff26057700000000, 0xb91d621200000000, 0x7350cbbd00000000, + 0x356bacd800000000}, + {0x0000000000000000, 0x9e83da9f00000000, 0x7d01c4e400000000, + 0xe3821e7b00000000, 0xbb04f91200000000, 0x2587238d00000000, + 0xc6053df600000000, 0x5886e76900000000, 0x7609f22500000000, + 0xe88a28ba00000000, 0x0b0836c100000000, 0x958bec5e00000000, + 0xcd0d0b3700000000, 0x538ed1a800000000, 0xb00ccfd300000000, + 0x2e8f154c00000000, 0xec12e44b00000000, 0x72913ed400000000, + 0x911320af00000000, 0x0f90fa3000000000, 0x57161d5900000000, + 0xc995c7c600000000, 0x2a17d9bd00000000, 0xb494032200000000, + 0x9a1b166e00000000, 0x0498ccf100000000, 0xe71ad28a00000000, + 0x7999081500000000, 0x211fef7c00000000, 0xbf9c35e300000000, + 0x5c1e2b9800000000, 0xc29df10700000000, 0xd825c89700000000, + 0x46a6120800000000, 0xa5240c7300000000, 0x3ba7d6ec00000000, + 0x6321318500000000, 0xfda2eb1a00000000, 0x1e20f56100000000, + 0x80a32ffe00000000, 0xae2c3ab200000000, 0x30afe02d00000000, + 0xd32dfe5600000000, 0x4dae24c900000000, 0x1528c3a000000000, + 0x8bab193f00000000, 0x6829074400000000, 0xf6aadddb00000000, + 0x34372cdc00000000, 0xaab4f64300000000, 0x4936e83800000000, + 0xd7b532a700000000, 0x8f33d5ce00000000, 0x11b00f5100000000, + 0xf232112a00000000, 0x6cb1cbb500000000, 0x423edef900000000, + 0xdcbd046600000000, 0x3f3f1a1d00000000, 0xa1bcc08200000000, + 0xf93a27eb00000000, 0x67b9fd7400000000, 0x843be30f00000000, + 0x1ab8399000000000, 0xf14de1f400000000, 0x6fce3b6b00000000, + 0x8c4c251000000000, 0x12cfff8f00000000, 0x4a4918e600000000, + 0xd4cac27900000000, 0x3748dc0200000000, 0xa9cb069d00000000, + 0x874413d100000000, 0x19c7c94e00000000, 0xfa45d73500000000, + 0x64c60daa00000000, 0x3c40eac300000000, 0xa2c3305c00000000, + 0x41412e2700000000, 0xdfc2f4b800000000, 0x1d5f05bf00000000, + 0x83dcdf2000000000, 0x605ec15b00000000, 0xfedd1bc400000000, + 0xa65bfcad00000000, 0x38d8263200000000, 0xdb5a384900000000, + 0x45d9e2d600000000, 0x6b56f79a00000000, 0xf5d52d0500000000, + 0x1657337e00000000, 0x88d4e9e100000000, 0xd0520e8800000000, + 0x4ed1d41700000000, 0xad53ca6c00000000, 0x33d010f300000000, + 0x2968296300000000, 0xb7ebf3fc00000000, 0x5469ed8700000000, + 0xcaea371800000000, 0x926cd07100000000, 0x0cef0aee00000000, + 0xef6d149500000000, 0x71eece0a00000000, 0x5f61db4600000000, + 0xc1e201d900000000, 0x22601fa200000000, 0xbce3c53d00000000, + 0xe465225400000000, 0x7ae6f8cb00000000, 0x9964e6b000000000, + 0x07e73c2f00000000, 0xc57acd2800000000, 0x5bf917b700000000, + 0xb87b09cc00000000, 0x26f8d35300000000, 0x7e7e343a00000000, + 0xe0fdeea500000000, 0x037ff0de00000000, 0x9dfc2a4100000000, + 0xb3733f0d00000000, 0x2df0e59200000000, 0xce72fbe900000000, + 0x50f1217600000000, 0x0877c61f00000000, 0x96f41c8000000000, + 0x757602fb00000000, 0xebf5d86400000000, 0xa39db33200000000, + 0x3d1e69ad00000000, 0xde9c77d600000000, 0x401fad4900000000, + 0x18994a2000000000, 0x861a90bf00000000, 0x65988ec400000000, + 0xfb1b545b00000000, 0xd594411700000000, 0x4b179b8800000000, + 0xa89585f300000000, 0x36165f6c00000000, 0x6e90b80500000000, + 0xf013629a00000000, 0x13917ce100000000, 0x8d12a67e00000000, + 0x4f8f577900000000, 0xd10c8de600000000, 0x328e939d00000000, + 0xac0d490200000000, 0xf48bae6b00000000, 0x6a0874f400000000, + 0x898a6a8f00000000, 0x1709b01000000000, 0x3986a55c00000000, + 0xa7057fc300000000, 0x448761b800000000, 0xda04bb2700000000, + 0x82825c4e00000000, 0x1c0186d100000000, 0xff8398aa00000000, + 0x6100423500000000, 0x7bb87ba500000000, 0xe53ba13a00000000, + 0x06b9bf4100000000, 0x983a65de00000000, 0xc0bc82b700000000, + 0x5e3f582800000000, 0xbdbd465300000000, 0x233e9ccc00000000, + 0x0db1898000000000, 0x9332531f00000000, 0x70b04d6400000000, + 0xee3397fb00000000, 0xb6b5709200000000, 0x2836aa0d00000000, + 0xcbb4b47600000000, 0x55376ee900000000, 0x97aa9fee00000000, + 0x0929457100000000, 0xeaab5b0a00000000, 0x7428819500000000, + 0x2cae66fc00000000, 0xb22dbc6300000000, 0x51afa21800000000, + 0xcf2c788700000000, 0xe1a36dcb00000000, 0x7f20b75400000000, + 0x9ca2a92f00000000, 0x022173b000000000, 0x5aa794d900000000, + 0xc4244e4600000000, 0x27a6503d00000000, 0xb9258aa200000000, + 0x52d052c600000000, 0xcc53885900000000, 0x2fd1962200000000, + 0xb1524cbd00000000, 0xe9d4abd400000000, 0x7757714b00000000, + 0x94d56f3000000000, 0x0a56b5af00000000, 0x24d9a0e300000000, + 0xba5a7a7c00000000, 0x59d8640700000000, 0xc75bbe9800000000, + 0x9fdd59f100000000, 0x015e836e00000000, 0xe2dc9d1500000000, + 0x7c5f478a00000000, 0xbec2b68d00000000, 0x20416c1200000000, + 0xc3c3726900000000, 0x5d40a8f600000000, 0x05c64f9f00000000, + 0x9b45950000000000, 0x78c78b7b00000000, 0xe64451e400000000, + 0xc8cb44a800000000, 0x56489e3700000000, 0xb5ca804c00000000, + 0x2b495ad300000000, 0x73cfbdba00000000, 0xed4c672500000000, + 0x0ece795e00000000, 0x904da3c100000000, 0x8af59a5100000000, + 0x147640ce00000000, 0xf7f45eb500000000, 0x6977842a00000000, + 0x31f1634300000000, 0xaf72b9dc00000000, 0x4cf0a7a700000000, + 0xd2737d3800000000, 0xfcfc687400000000, 0x627fb2eb00000000, + 0x81fdac9000000000, 0x1f7e760f00000000, 0x47f8916600000000, + 0xd97b4bf900000000, 0x3af9558200000000, 0xa47a8f1d00000000, + 0x66e77e1a00000000, 0xf864a48500000000, 0x1be6bafe00000000, + 0x8565606100000000, 0xdde3870800000000, 0x43605d9700000000, + 0xa0e243ec00000000, 0x3e61997300000000, 0x10ee8c3f00000000, + 0x8e6d56a000000000, 0x6def48db00000000, 0xf36c924400000000, + 0xabea752d00000000, 0x3569afb200000000, 0xd6ebb1c900000000, + 0x48686b5600000000}, + {0x0000000000000000, 0xc064281700000000, 0x80c9502e00000000, + 0x40ad783900000000, 0x0093a15c00000000, 0xc0f7894b00000000, + 0x805af17200000000, 0x403ed96500000000, 0x002643b900000000, + 0xc0426bae00000000, 0x80ef139700000000, 0x408b3b8000000000, + 0x00b5e2e500000000, 0xc0d1caf200000000, 0x807cb2cb00000000, + 0x40189adc00000000, 0x414af7a900000000, 0x812edfbe00000000, + 0xc183a78700000000, 0x01e78f9000000000, 0x41d956f500000000, + 0x81bd7ee200000000, 0xc11006db00000000, 0x01742ecc00000000, + 0x416cb41000000000, 0x81089c0700000000, 0xc1a5e43e00000000, + 0x01c1cc2900000000, 0x41ff154c00000000, 0x819b3d5b00000000, + 0xc136456200000000, 0x01526d7500000000, 0xc3929f8800000000, + 0x03f6b79f00000000, 0x435bcfa600000000, 0x833fe7b100000000, + 0xc3013ed400000000, 0x036516c300000000, 0x43c86efa00000000, + 0x83ac46ed00000000, 0xc3b4dc3100000000, 0x03d0f42600000000, + 0x437d8c1f00000000, 0x8319a40800000000, 0xc3277d6d00000000, + 0x0343557a00000000, 0x43ee2d4300000000, 0x838a055400000000, + 0x82d8682100000000, 0x42bc403600000000, 0x0211380f00000000, + 0xc275101800000000, 0x824bc97d00000000, 0x422fe16a00000000, + 0x0282995300000000, 0xc2e6b14400000000, 0x82fe2b9800000000, + 0x429a038f00000000, 0x02377bb600000000, 0xc25353a100000000, + 0x826d8ac400000000, 0x4209a2d300000000, 0x02a4daea00000000, + 0xc2c0f2fd00000000, 0xc7234eca00000000, 0x074766dd00000000, + 0x47ea1ee400000000, 0x878e36f300000000, 0xc7b0ef9600000000, + 0x07d4c78100000000, 0x4779bfb800000000, 0x871d97af00000000, + 0xc7050d7300000000, 0x0761256400000000, 0x47cc5d5d00000000, + 0x87a8754a00000000, 0xc796ac2f00000000, 0x07f2843800000000, + 0x475ffc0100000000, 0x873bd41600000000, 0x8669b96300000000, + 0x460d917400000000, 0x06a0e94d00000000, 0xc6c4c15a00000000, + 0x86fa183f00000000, 0x469e302800000000, 0x0633481100000000, + 0xc657600600000000, 0x864ffada00000000, 0x462bd2cd00000000, + 0x0686aaf400000000, 0xc6e282e300000000, 0x86dc5b8600000000, + 0x46b8739100000000, 0x06150ba800000000, 0xc67123bf00000000, + 0x04b1d14200000000, 0xc4d5f95500000000, 0x8478816c00000000, + 0x441ca97b00000000, 0x0422701e00000000, 0xc446580900000000, + 0x84eb203000000000, 0x448f082700000000, 0x049792fb00000000, + 0xc4f3baec00000000, 0x845ec2d500000000, 0x443aeac200000000, + 0x040433a700000000, 0xc4601bb000000000, 0x84cd638900000000, + 0x44a94b9e00000000, 0x45fb26eb00000000, 0x859f0efc00000000, + 0xc53276c500000000, 0x05565ed200000000, 0x456887b700000000, + 0x850cafa000000000, 0xc5a1d79900000000, 0x05c5ff8e00000000, + 0x45dd655200000000, 0x85b94d4500000000, 0xc514357c00000000, + 0x05701d6b00000000, 0x454ec40e00000000, 0x852aec1900000000, + 0xc587942000000000, 0x05e3bc3700000000, 0xcf41ed4f00000000, + 0x0f25c55800000000, 0x4f88bd6100000000, 0x8fec957600000000, + 0xcfd24c1300000000, 0x0fb6640400000000, 0x4f1b1c3d00000000, + 0x8f7f342a00000000, 0xcf67aef600000000, 0x0f0386e100000000, + 0x4faefed800000000, 0x8fcad6cf00000000, 0xcff40faa00000000, + 0x0f9027bd00000000, 0x4f3d5f8400000000, 0x8f59779300000000, + 0x8e0b1ae600000000, 0x4e6f32f100000000, 0x0ec24ac800000000, + 0xcea662df00000000, 0x8e98bbba00000000, 0x4efc93ad00000000, + 0x0e51eb9400000000, 0xce35c38300000000, 0x8e2d595f00000000, + 0x4e49714800000000, 0x0ee4097100000000, 0xce80216600000000, + 0x8ebef80300000000, 0x4edad01400000000, 0x0e77a82d00000000, + 0xce13803a00000000, 0x0cd372c700000000, 0xccb75ad000000000, + 0x8c1a22e900000000, 0x4c7e0afe00000000, 0x0c40d39b00000000, + 0xcc24fb8c00000000, 0x8c8983b500000000, 0x4cedaba200000000, + 0x0cf5317e00000000, 0xcc91196900000000, 0x8c3c615000000000, + 0x4c58494700000000, 0x0c66902200000000, 0xcc02b83500000000, + 0x8cafc00c00000000, 0x4ccbe81b00000000, 0x4d99856e00000000, + 0x8dfdad7900000000, 0xcd50d54000000000, 0x0d34fd5700000000, + 0x4d0a243200000000, 0x8d6e0c2500000000, 0xcdc3741c00000000, + 0x0da75c0b00000000, 0x4dbfc6d700000000, 0x8ddbeec000000000, + 0xcd7696f900000000, 0x0d12beee00000000, 0x4d2c678b00000000, + 0x8d484f9c00000000, 0xcde537a500000000, 0x0d811fb200000000, + 0x0862a38500000000, 0xc8068b9200000000, 0x88abf3ab00000000, + 0x48cfdbbc00000000, 0x08f102d900000000, 0xc8952ace00000000, + 0x883852f700000000, 0x485c7ae000000000, 0x0844e03c00000000, + 0xc820c82b00000000, 0x888db01200000000, 0x48e9980500000000, + 0x08d7416000000000, 0xc8b3697700000000, 0x881e114e00000000, + 0x487a395900000000, 0x4928542c00000000, 0x894c7c3b00000000, + 0xc9e1040200000000, 0x09852c1500000000, 0x49bbf57000000000, + 0x89dfdd6700000000, 0xc972a55e00000000, 0x09168d4900000000, + 0x490e179500000000, 0x896a3f8200000000, 0xc9c747bb00000000, + 0x09a36fac00000000, 0x499db6c900000000, 0x89f99ede00000000, + 0xc954e6e700000000, 0x0930cef000000000, 0xcbf03c0d00000000, + 0x0b94141a00000000, 0x4b396c2300000000, 0x8b5d443400000000, + 0xcb639d5100000000, 0x0b07b54600000000, 0x4baacd7f00000000, + 0x8bcee56800000000, 0xcbd67fb400000000, 0x0bb257a300000000, + 0x4b1f2f9a00000000, 0x8b7b078d00000000, 0xcb45dee800000000, + 0x0b21f6ff00000000, 0x4b8c8ec600000000, 0x8be8a6d100000000, + 0x8abacba400000000, 0x4adee3b300000000, 0x0a739b8a00000000, + 0xca17b39d00000000, 0x8a296af800000000, 0x4a4d42ef00000000, + 0x0ae03ad600000000, 0xca8412c100000000, 0x8a9c881d00000000, + 0x4af8a00a00000000, 0x0a55d83300000000, 0xca31f02400000000, + 0x8a0f294100000000, 0x4a6b015600000000, 0x0ac6796f00000000, + 0xcaa2517800000000}, + {0x0000000000000000, 0xd4ea739b00000000, 0xe9d396ed00000000, + 0x3d39e57600000000, 0x93a15c0000000000, 0x474b2f9b00000000, + 0x7a72caed00000000, 0xae98b97600000000, 0x2643b90000000000, + 0xf2a9ca9b00000000, 0xcf902fed00000000, 0x1b7a5c7600000000, + 0xb5e2e50000000000, 0x6108969b00000000, 0x5c3173ed00000000, + 0x88db007600000000, 0x4c86720100000000, 0x986c019a00000000, + 0xa555e4ec00000000, 0x71bf977700000000, 0xdf272e0100000000, + 0x0bcd5d9a00000000, 0x36f4b8ec00000000, 0xe21ecb7700000000, + 0x6ac5cb0100000000, 0xbe2fb89a00000000, 0x83165dec00000000, + 0x57fc2e7700000000, 0xf964970100000000, 0x2d8ee49a00000000, + 0x10b701ec00000000, 0xc45d727700000000, 0x980ce50200000000, + 0x4ce6969900000000, 0x71df73ef00000000, 0xa535007400000000, + 0x0badb90200000000, 0xdf47ca9900000000, 0xe27e2fef00000000, + 0x36945c7400000000, 0xbe4f5c0200000000, 0x6aa52f9900000000, + 0x579ccaef00000000, 0x8376b97400000000, 0x2dee000200000000, + 0xf904739900000000, 0xc43d96ef00000000, 0x10d7e57400000000, + 0xd48a970300000000, 0x0060e49800000000, 0x3d5901ee00000000, + 0xe9b3727500000000, 0x472bcb0300000000, 0x93c1b89800000000, + 0xaef85dee00000000, 0x7a122e7500000000, 0xf2c92e0300000000, + 0x26235d9800000000, 0x1b1ab8ee00000000, 0xcff0cb7500000000, + 0x6168720300000000, 0xb582019800000000, 0x88bbe4ee00000000, + 0x5c51977500000000, 0x3019ca0500000000, 0xe4f3b99e00000000, + 0xd9ca5ce800000000, 0x0d202f7300000000, 0xa3b8960500000000, + 0x7752e59e00000000, 0x4a6b00e800000000, 0x9e81737300000000, + 0x165a730500000000, 0xc2b0009e00000000, 0xff89e5e800000000, + 0x2b63967300000000, 0x85fb2f0500000000, 0x51115c9e00000000, + 0x6c28b9e800000000, 0xb8c2ca7300000000, 0x7c9fb80400000000, + 0xa875cb9f00000000, 0x954c2ee900000000, 0x41a65d7200000000, + 0xef3ee40400000000, 0x3bd4979f00000000, 0x06ed72e900000000, + 0xd207017200000000, 0x5adc010400000000, 0x8e36729f00000000, + 0xb30f97e900000000, 0x67e5e47200000000, 0xc97d5d0400000000, + 0x1d972e9f00000000, 0x20aecbe900000000, 0xf444b87200000000, + 0xa8152f0700000000, 0x7cff5c9c00000000, 0x41c6b9ea00000000, + 0x952cca7100000000, 0x3bb4730700000000, 0xef5e009c00000000, + 0xd267e5ea00000000, 0x068d967100000000, 0x8e56960700000000, + 0x5abce59c00000000, 0x678500ea00000000, 0xb36f737100000000, + 0x1df7ca0700000000, 0xc91db99c00000000, 0xf4245cea00000000, + 0x20ce2f7100000000, 0xe4935d0600000000, 0x30792e9d00000000, + 0x0d40cbeb00000000, 0xd9aab87000000000, 0x7732010600000000, + 0xa3d8729d00000000, 0x9ee197eb00000000, 0x4a0be47000000000, + 0xc2d0e40600000000, 0x163a979d00000000, 0x2b0372eb00000000, + 0xffe9017000000000, 0x5171b80600000000, 0x859bcb9d00000000, + 0xb8a22eeb00000000, 0x6c485d7000000000, 0x6032940b00000000, + 0xb4d8e79000000000, 0x89e102e600000000, 0x5d0b717d00000000, + 0xf393c80b00000000, 0x2779bb9000000000, 0x1a405ee600000000, + 0xceaa2d7d00000000, 0x46712d0b00000000, 0x929b5e9000000000, + 0xafa2bbe600000000, 0x7b48c87d00000000, 0xd5d0710b00000000, + 0x013a029000000000, 0x3c03e7e600000000, 0xe8e9947d00000000, + 0x2cb4e60a00000000, 0xf85e959100000000, 0xc56770e700000000, + 0x118d037c00000000, 0xbf15ba0a00000000, 0x6bffc99100000000, + 0x56c62ce700000000, 0x822c5f7c00000000, 0x0af75f0a00000000, + 0xde1d2c9100000000, 0xe324c9e700000000, 0x37ceba7c00000000, + 0x9956030a00000000, 0x4dbc709100000000, 0x708595e700000000, + 0xa46fe67c00000000, 0xf83e710900000000, 0x2cd4029200000000, + 0x11ede7e400000000, 0xc507947f00000000, 0x6b9f2d0900000000, + 0xbf755e9200000000, 0x824cbbe400000000, 0x56a6c87f00000000, + 0xde7dc80900000000, 0x0a97bb9200000000, 0x37ae5ee400000000, + 0xe3442d7f00000000, 0x4ddc940900000000, 0x9936e79200000000, + 0xa40f02e400000000, 0x70e5717f00000000, 0xb4b8030800000000, + 0x6052709300000000, 0x5d6b95e500000000, 0x8981e67e00000000, + 0x27195f0800000000, 0xf3f32c9300000000, 0xcecac9e500000000, + 0x1a20ba7e00000000, 0x92fbba0800000000, 0x4611c99300000000, + 0x7b282ce500000000, 0xafc25f7e00000000, 0x015ae60800000000, + 0xd5b0959300000000, 0xe88970e500000000, 0x3c63037e00000000, + 0x502b5e0e00000000, 0x84c12d9500000000, 0xb9f8c8e300000000, + 0x6d12bb7800000000, 0xc38a020e00000000, 0x1760719500000000, + 0x2a5994e300000000, 0xfeb3e77800000000, 0x7668e70e00000000, + 0xa282949500000000, 0x9fbb71e300000000, 0x4b51027800000000, + 0xe5c9bb0e00000000, 0x3123c89500000000, 0x0c1a2de300000000, + 0xd8f05e7800000000, 0x1cad2c0f00000000, 0xc8475f9400000000, + 0xf57ebae200000000, 0x2194c97900000000, 0x8f0c700f00000000, + 0x5be6039400000000, 0x66dfe6e200000000, 0xb235957900000000, + 0x3aee950f00000000, 0xee04e69400000000, 0xd33d03e200000000, + 0x07d7707900000000, 0xa94fc90f00000000, 0x7da5ba9400000000, + 0x409c5fe200000000, 0x94762c7900000000, 0xc827bb0c00000000, + 0x1ccdc89700000000, 0x21f42de100000000, 0xf51e5e7a00000000, + 0x5b86e70c00000000, 0x8f6c949700000000, 0xb25571e100000000, + 0x66bf027a00000000, 0xee64020c00000000, 0x3a8e719700000000, + 0x07b794e100000000, 0xd35de77a00000000, 0x7dc55e0c00000000, + 0xa92f2d9700000000, 0x9416c8e100000000, 0x40fcbb7a00000000, + 0x84a1c90d00000000, 0x504bba9600000000, 0x6d725fe000000000, + 0xb9982c7b00000000, 0x1700950d00000000, 0xc3eae69600000000, + 0xfed303e000000000, 0x2a39707b00000000, 0xa2e2700d00000000, + 0x7608039600000000, 0x4b31e6e000000000, 0x9fdb957b00000000, + 0x31432c0d00000000, 0xe5a95f9600000000, 0xd890bae000000000, + 0x0c7ac97b00000000}, + {0x0000000000000000, 0x2765258100000000, 0x0fcc3bd900000000, + 0x28a91e5800000000, 0x5f9e066900000000, 0x78fb23e800000000, + 0x50523db000000000, 0x7737183100000000, 0xbe3c0dd200000000, + 0x9959285300000000, 0xb1f0360b00000000, 0x9695138a00000000, + 0xe1a20bbb00000000, 0xc6c72e3a00000000, 0xee6e306200000000, + 0xc90b15e300000000, 0x3d7f6b7f00000000, 0x1a1a4efe00000000, + 0x32b350a600000000, 0x15d6752700000000, 0x62e16d1600000000, + 0x4584489700000000, 0x6d2d56cf00000000, 0x4a48734e00000000, + 0x834366ad00000000, 0xa426432c00000000, 0x8c8f5d7400000000, + 0xabea78f500000000, 0xdcdd60c400000000, 0xfbb8454500000000, + 0xd3115b1d00000000, 0xf4747e9c00000000, 0x7afed6fe00000000, + 0x5d9bf37f00000000, 0x7532ed2700000000, 0x5257c8a600000000, + 0x2560d09700000000, 0x0205f51600000000, 0x2aaceb4e00000000, + 0x0dc9cecf00000000, 0xc4c2db2c00000000, 0xe3a7fead00000000, + 0xcb0ee0f500000000, 0xec6bc57400000000, 0x9b5cdd4500000000, + 0xbc39f8c400000000, 0x9490e69c00000000, 0xb3f5c31d00000000, + 0x4781bd8100000000, 0x60e4980000000000, 0x484d865800000000, + 0x6f28a3d900000000, 0x181fbbe800000000, 0x3f7a9e6900000000, + 0x17d3803100000000, 0x30b6a5b000000000, 0xf9bdb05300000000, + 0xded895d200000000, 0xf6718b8a00000000, 0xd114ae0b00000000, + 0xa623b63a00000000, 0x814693bb00000000, 0xa9ef8de300000000, + 0x8e8aa86200000000, 0xb5fadc2600000000, 0x929ff9a700000000, + 0xba36e7ff00000000, 0x9d53c27e00000000, 0xea64da4f00000000, + 0xcd01ffce00000000, 0xe5a8e19600000000, 0xc2cdc41700000000, + 0x0bc6d1f400000000, 0x2ca3f47500000000, 0x040aea2d00000000, + 0x236fcfac00000000, 0x5458d79d00000000, 0x733df21c00000000, + 0x5b94ec4400000000, 0x7cf1c9c500000000, 0x8885b75900000000, + 0xafe092d800000000, 0x87498c8000000000, 0xa02ca90100000000, + 0xd71bb13000000000, 0xf07e94b100000000, 0xd8d78ae900000000, + 0xffb2af6800000000, 0x36b9ba8b00000000, 0x11dc9f0a00000000, + 0x3975815200000000, 0x1e10a4d300000000, 0x6927bce200000000, + 0x4e42996300000000, 0x66eb873b00000000, 0x418ea2ba00000000, + 0xcf040ad800000000, 0xe8612f5900000000, 0xc0c8310100000000, + 0xe7ad148000000000, 0x909a0cb100000000, 0xb7ff293000000000, + 0x9f56376800000000, 0xb83312e900000000, 0x7138070a00000000, + 0x565d228b00000000, 0x7ef43cd300000000, 0x5991195200000000, + 0x2ea6016300000000, 0x09c324e200000000, 0x216a3aba00000000, + 0x060f1f3b00000000, 0xf27b61a700000000, 0xd51e442600000000, + 0xfdb75a7e00000000, 0xdad27fff00000000, 0xade567ce00000000, + 0x8a80424f00000000, 0xa2295c1700000000, 0x854c799600000000, + 0x4c476c7500000000, 0x6b2249f400000000, 0x438b57ac00000000, + 0x64ee722d00000000, 0x13d96a1c00000000, 0x34bc4f9d00000000, + 0x1c1551c500000000, 0x3b70744400000000, 0x6af5b94d00000000, + 0x4d909ccc00000000, 0x6539829400000000, 0x425ca71500000000, + 0x356bbf2400000000, 0x120e9aa500000000, 0x3aa784fd00000000, + 0x1dc2a17c00000000, 0xd4c9b49f00000000, 0xf3ac911e00000000, + 0xdb058f4600000000, 0xfc60aac700000000, 0x8b57b2f600000000, + 0xac32977700000000, 0x849b892f00000000, 0xa3feacae00000000, + 0x578ad23200000000, 0x70eff7b300000000, 0x5846e9eb00000000, + 0x7f23cc6a00000000, 0x0814d45b00000000, 0x2f71f1da00000000, + 0x07d8ef8200000000, 0x20bdca0300000000, 0xe9b6dfe000000000, + 0xced3fa6100000000, 0xe67ae43900000000, 0xc11fc1b800000000, + 0xb628d98900000000, 0x914dfc0800000000, 0xb9e4e25000000000, + 0x9e81c7d100000000, 0x100b6fb300000000, 0x376e4a3200000000, + 0x1fc7546a00000000, 0x38a271eb00000000, 0x4f9569da00000000, + 0x68f04c5b00000000, 0x4059520300000000, 0x673c778200000000, + 0xae37626100000000, 0x895247e000000000, 0xa1fb59b800000000, + 0x869e7c3900000000, 0xf1a9640800000000, 0xd6cc418900000000, + 0xfe655fd100000000, 0xd9007a5000000000, 0x2d7404cc00000000, + 0x0a11214d00000000, 0x22b83f1500000000, 0x05dd1a9400000000, + 0x72ea02a500000000, 0x558f272400000000, 0x7d26397c00000000, + 0x5a431cfd00000000, 0x9348091e00000000, 0xb42d2c9f00000000, + 0x9c8432c700000000, 0xbbe1174600000000, 0xccd60f7700000000, + 0xebb32af600000000, 0xc31a34ae00000000, 0xe47f112f00000000, + 0xdf0f656b00000000, 0xf86a40ea00000000, 0xd0c35eb200000000, + 0xf7a67b3300000000, 0x8091630200000000, 0xa7f4468300000000, + 0x8f5d58db00000000, 0xa8387d5a00000000, 0x613368b900000000, + 0x46564d3800000000, 0x6eff536000000000, 0x499a76e100000000, + 0x3ead6ed000000000, 0x19c84b5100000000, 0x3161550900000000, + 0x1604708800000000, 0xe2700e1400000000, 0xc5152b9500000000, + 0xedbc35cd00000000, 0xcad9104c00000000, 0xbdee087d00000000, + 0x9a8b2dfc00000000, 0xb22233a400000000, 0x9547162500000000, + 0x5c4c03c600000000, 0x7b29264700000000, 0x5380381f00000000, + 0x74e51d9e00000000, 0x03d205af00000000, 0x24b7202e00000000, + 0x0c1e3e7600000000, 0x2b7b1bf700000000, 0xa5f1b39500000000, + 0x8294961400000000, 0xaa3d884c00000000, 0x8d58adcd00000000, + 0xfa6fb5fc00000000, 0xdd0a907d00000000, 0xf5a38e2500000000, + 0xd2c6aba400000000, 0x1bcdbe4700000000, 0x3ca89bc600000000, + 0x1401859e00000000, 0x3364a01f00000000, 0x4453b82e00000000, + 0x63369daf00000000, 0x4b9f83f700000000, 0x6cfaa67600000000, + 0x988ed8ea00000000, 0xbfebfd6b00000000, 0x9742e33300000000, + 0xb027c6b200000000, 0xc710de8300000000, 0xe075fb0200000000, + 0xc8dce55a00000000, 0xefb9c0db00000000, 0x26b2d53800000000, + 0x01d7f0b900000000, 0x297eeee100000000, 0x0e1bcb6000000000, + 0x792cd35100000000, 0x5e49f6d000000000, 0x76e0e88800000000, + 0x5185cd0900000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f, + 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91, + 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e, + 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c, + 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02, + 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12, + 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567, + 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277, + 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679, + 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b, + 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4, + 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a, + 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0, + 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0, + 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91, + 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881, + 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173, + 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d, + 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912, + 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8, + 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6, + 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6, + 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b, + 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b, + 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75, + 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f, + 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00, + 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee, + 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c, + 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c, + 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d, + 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d, + 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67, + 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89, + 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706, + 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14, + 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a, + 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a, + 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f, + 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f, + 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591, + 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983, + 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c, + 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2, + 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8, + 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8, + 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89, + 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99, + 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b, + 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485, + 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a, + 0x36197165}, + {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382, + 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85, + 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06, + 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca, + 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e, + 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc, + 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616, + 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54, + 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10, + 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc, + 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f, + 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58, + 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef, + 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad, + 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b, + 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29, + 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6, + 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1, + 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622, + 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039, + 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d, + 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f, + 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32, + 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770, + 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034, + 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f, + 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc, + 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db, + 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154, + 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16, + 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0, + 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592, + 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca, + 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd, + 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e, + 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882, + 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6, + 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384, + 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1, + 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3, + 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7, + 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b, + 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8, + 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff, + 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7, + 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5, + 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23, + 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761, + 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee, + 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9, + 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a, + 0x1a3b93aa}, + {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a, + 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca, + 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3, + 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb, + 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c, + 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58, + 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed, + 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9, + 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e, + 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906, + 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f, + 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf, + 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0, + 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4, + 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769, + 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d, + 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632, + 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82, + 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb, + 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73, + 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484, + 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0, + 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5, + 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1, + 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516, + 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f, + 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946, + 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6, + 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9, + 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad, + 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820, + 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364, + 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab, + 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b, + 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62, + 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a, + 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd, + 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089, + 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c, + 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8, + 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f, + 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477, + 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e, + 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be, + 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71, + 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635, + 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8, + 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc, + 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3, + 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753, + 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a, + 0xe147d714}, + {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c, + 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b, + 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92, + 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4, + 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069, + 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526, + 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25, + 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a, + 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7, + 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491, + 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958, + 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f, + 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307, + 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648, + 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999, + 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6, + 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a, + 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d, + 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4, + 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61, + 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc, + 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3, + 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53, + 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c, + 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1, + 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c, + 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5, + 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92, + 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e, + 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771, + 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0, + 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def, + 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0, + 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7, + 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e, + 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58, + 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285, + 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca, + 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce, + 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81, + 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c, + 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a, + 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3, + 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4, + 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb, + 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4, + 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75, + 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a, + 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296, + 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1, + 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808, + 0x494f0c4b}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0x43147b17, 0x8628f62e, 0xc53c8d39, 0x0c51ec5d, + 0x4f45974a, 0x8a791a73, 0xc96d6164, 0x18a2d8bb, 0x5bb6a3ac, + 0x9e8a2e95, 0xdd9e5582, 0x14f334e6, 0x57e74ff1, 0x92dbc2c8, + 0xd1cfb9df, 0x7142c0ac, 0x3256bbbb, 0xf76a3682, 0xb47e4d95, + 0x7d132cf1, 0x3e0757e6, 0xfb3bdadf, 0xb82fa1c8, 0x69e01817, + 0x2af46300, 0xefc8ee39, 0xacdc952e, 0x65b1f44a, 0x26a58f5d, + 0xe3990264, 0xa08d7973, 0xa382f182, 0xe0968a95, 0x25aa07ac, + 0x66be7cbb, 0xafd31ddf, 0xecc766c8, 0x29fbebf1, 0x6aef90e6, + 0xbb202939, 0xf834522e, 0x3d08df17, 0x7e1ca400, 0xb771c564, + 0xf465be73, 0x3159334a, 0x724d485d, 0xd2c0312e, 0x91d44a39, + 0x54e8c700, 0x17fcbc17, 0xde91dd73, 0x9d85a664, 0x58b92b5d, + 0x1bad504a, 0xca62e995, 0x89769282, 0x4c4a1fbb, 0x0f5e64ac, + 0xc63305c8, 0x85277edf, 0x401bf3e6, 0x030f88f1, 0x070392de, + 0x4417e9c9, 0x812b64f0, 0xc23f1fe7, 0x0b527e83, 0x48460594, + 0x8d7a88ad, 0xce6ef3ba, 0x1fa14a65, 0x5cb53172, 0x9989bc4b, + 0xda9dc75c, 0x13f0a638, 0x50e4dd2f, 0x95d85016, 0xd6cc2b01, + 0x76415272, 0x35552965, 0xf069a45c, 0xb37ddf4b, 0x7a10be2f, + 0x3904c538, 0xfc384801, 0xbf2c3316, 0x6ee38ac9, 0x2df7f1de, + 0xe8cb7ce7, 0xabdf07f0, 0x62b26694, 0x21a61d83, 0xe49a90ba, + 0xa78eebad, 0xa481635c, 0xe795184b, 0x22a99572, 0x61bdee65, + 0xa8d08f01, 0xebc4f416, 0x2ef8792f, 0x6dec0238, 0xbc23bbe7, + 0xff37c0f0, 0x3a0b4dc9, 0x791f36de, 0xb07257ba, 0xf3662cad, + 0x365aa194, 0x754eda83, 0xd5c3a3f0, 0x96d7d8e7, 0x53eb55de, + 0x10ff2ec9, 0xd9924fad, 0x9a8634ba, 0x5fbab983, 0x1caec294, + 0xcd617b4b, 0x8e75005c, 0x4b498d65, 0x085df672, 0xc1309716, + 0x8224ec01, 0x47186138, 0x040c1a2f, 0x4f005566, 0x0c142e71, + 0xc928a348, 0x8a3cd85f, 0x4351b93b, 0x0045c22c, 0xc5794f15, + 0x866d3402, 0x57a28ddd, 0x14b6f6ca, 0xd18a7bf3, 0x929e00e4, + 0x5bf36180, 0x18e71a97, 0xdddb97ae, 0x9ecfecb9, 0x3e4295ca, + 0x7d56eedd, 0xb86a63e4, 0xfb7e18f3, 0x32137997, 0x71070280, + 0xb43b8fb9, 0xf72ff4ae, 0x26e04d71, 0x65f43666, 0xa0c8bb5f, + 0xe3dcc048, 0x2ab1a12c, 0x69a5da3b, 0xac995702, 0xef8d2c15, + 0xec82a4e4, 0xaf96dff3, 0x6aaa52ca, 0x29be29dd, 0xe0d348b9, + 0xa3c733ae, 0x66fbbe97, 0x25efc580, 0xf4207c5f, 0xb7340748, + 0x72088a71, 0x311cf166, 0xf8719002, 0xbb65eb15, 0x7e59662c, + 0x3d4d1d3b, 0x9dc06448, 0xded41f5f, 0x1be89266, 0x58fce971, + 0x91918815, 0xd285f302, 0x17b97e3b, 0x54ad052c, 0x8562bcf3, + 0xc676c7e4, 0x034a4add, 0x405e31ca, 0x893350ae, 0xca272bb9, + 0x0f1ba680, 0x4c0fdd97, 0x4803c7b8, 0x0b17bcaf, 0xce2b3196, + 0x8d3f4a81, 0x44522be5, 0x074650f2, 0xc27addcb, 0x816ea6dc, + 0x50a11f03, 0x13b56414, 0xd689e92d, 0x959d923a, 0x5cf0f35e, + 0x1fe48849, 0xdad80570, 0x99cc7e67, 0x39410714, 0x7a557c03, + 0xbf69f13a, 0xfc7d8a2d, 0x3510eb49, 0x7604905e, 0xb3381d67, + 0xf02c6670, 0x21e3dfaf, 0x62f7a4b8, 0xa7cb2981, 0xe4df5296, + 0x2db233f2, 0x6ea648e5, 0xab9ac5dc, 0xe88ebecb, 0xeb81363a, + 0xa8954d2d, 0x6da9c014, 0x2ebdbb03, 0xe7d0da67, 0xa4c4a170, + 0x61f82c49, 0x22ec575e, 0xf323ee81, 0xb0379596, 0x750b18af, + 0x361f63b8, 0xff7202dc, 0xbc6679cb, 0x795af4f2, 0x3a4e8fe5, + 0x9ac3f696, 0xd9d78d81, 0x1ceb00b8, 0x5fff7baf, 0x96921acb, + 0xd58661dc, 0x10baece5, 0x53ae97f2, 0x82612e2d, 0xc175553a, + 0x0449d803, 0x475da314, 0x8e30c270, 0xcd24b967, 0x0818345e, + 0x4b0c4f49}, + {0x00000000, 0x3e6bc2ef, 0x3dd0f504, 0x03bb37eb, 0x7aa0eb09, + 0x44cb29e6, 0x47701e0d, 0x791bdce2, 0xf440d713, 0xca2b15fc, + 0xc9902217, 0xf7fbe0f8, 0x8ee03c1a, 0xb08bfef5, 0xb330c91e, + 0x8d5b0bf1, 0xe881ae27, 0xd6ea6cc8, 0xd5515b23, 0xeb3a99cc, + 0x9221452e, 0xac4a87c1, 0xaff1b02a, 0x919a72c5, 0x1cc17934, + 0x22aabbdb, 0x21118c30, 0x1f7a4edf, 0x6661923d, 0x580a50d2, + 0x5bb16739, 0x65daa5d6, 0xd0035d4f, 0xee689fa0, 0xedd3a84b, + 0xd3b86aa4, 0xaaa3b646, 0x94c874a9, 0x97734342, 0xa91881ad, + 0x24438a5c, 0x1a2848b3, 0x19937f58, 0x27f8bdb7, 0x5ee36155, + 0x6088a3ba, 0x63339451, 0x5d5856be, 0x3882f368, 0x06e93187, + 0x0552066c, 0x3b39c483, 0x42221861, 0x7c49da8e, 0x7ff2ed65, + 0x41992f8a, 0xccc2247b, 0xf2a9e694, 0xf112d17f, 0xcf791390, + 0xb662cf72, 0x88090d9d, 0x8bb23a76, 0xb5d9f899, 0xa007ba9e, + 0x9e6c7871, 0x9dd74f9a, 0xa3bc8d75, 0xdaa75197, 0xe4cc9378, + 0xe777a493, 0xd91c667c, 0x54476d8d, 0x6a2caf62, 0x69979889, + 0x57fc5a66, 0x2ee78684, 0x108c446b, 0x13377380, 0x2d5cb16f, + 0x488614b9, 0x76edd656, 0x7556e1bd, 0x4b3d2352, 0x3226ffb0, + 0x0c4d3d5f, 0x0ff60ab4, 0x319dc85b, 0xbcc6c3aa, 0x82ad0145, + 0x811636ae, 0xbf7df441, 0xc66628a3, 0xf80dea4c, 0xfbb6dda7, + 0xc5dd1f48, 0x7004e7d1, 0x4e6f253e, 0x4dd412d5, 0x73bfd03a, + 0x0aa40cd8, 0x34cfce37, 0x3774f9dc, 0x091f3b33, 0x844430c2, + 0xba2ff22d, 0xb994c5c6, 0x87ff0729, 0xfee4dbcb, 0xc08f1924, + 0xc3342ecf, 0xfd5fec20, 0x988549f6, 0xa6ee8b19, 0xa555bcf2, + 0x9b3e7e1d, 0xe225a2ff, 0xdc4e6010, 0xdff557fb, 0xe19e9514, + 0x6cc59ee5, 0x52ae5c0a, 0x51156be1, 0x6f7ea90e, 0x166575ec, + 0x280eb703, 0x2bb580e8, 0x15de4207, 0x010905e6, 0x3f62c709, + 0x3cd9f0e2, 0x02b2320d, 0x7ba9eeef, 0x45c22c00, 0x46791beb, + 0x7812d904, 0xf549d2f5, 0xcb22101a, 0xc89927f1, 0xf6f2e51e, + 0x8fe939fc, 0xb182fb13, 0xb239ccf8, 0x8c520e17, 0xe988abc1, + 0xd7e3692e, 0xd4585ec5, 0xea339c2a, 0x932840c8, 0xad438227, + 0xaef8b5cc, 0x90937723, 0x1dc87cd2, 0x23a3be3d, 0x201889d6, + 0x1e734b39, 0x676897db, 0x59035534, 0x5ab862df, 0x64d3a030, + 0xd10a58a9, 0xef619a46, 0xecdaadad, 0xd2b16f42, 0xabaab3a0, + 0x95c1714f, 0x967a46a4, 0xa811844b, 0x254a8fba, 0x1b214d55, + 0x189a7abe, 0x26f1b851, 0x5fea64b3, 0x6181a65c, 0x623a91b7, + 0x5c515358, 0x398bf68e, 0x07e03461, 0x045b038a, 0x3a30c165, + 0x432b1d87, 0x7d40df68, 0x7efbe883, 0x40902a6c, 0xcdcb219d, + 0xf3a0e372, 0xf01bd499, 0xce701676, 0xb76bca94, 0x8900087b, + 0x8abb3f90, 0xb4d0fd7f, 0xa10ebf78, 0x9f657d97, 0x9cde4a7c, + 0xa2b58893, 0xdbae5471, 0xe5c5969e, 0xe67ea175, 0xd815639a, + 0x554e686b, 0x6b25aa84, 0x689e9d6f, 0x56f55f80, 0x2fee8362, + 0x1185418d, 0x123e7666, 0x2c55b489, 0x498f115f, 0x77e4d3b0, + 0x745fe45b, 0x4a3426b4, 0x332ffa56, 0x0d4438b9, 0x0eff0f52, + 0x3094cdbd, 0xbdcfc64c, 0x83a404a3, 0x801f3348, 0xbe74f1a7, + 0xc76f2d45, 0xf904efaa, 0xfabfd841, 0xc4d41aae, 0x710de237, + 0x4f6620d8, 0x4cdd1733, 0x72b6d5dc, 0x0bad093e, 0x35c6cbd1, + 0x367dfc3a, 0x08163ed5, 0x854d3524, 0xbb26f7cb, 0xb89dc020, + 0x86f602cf, 0xffedde2d, 0xc1861cc2, 0xc23d2b29, 0xfc56e9c6, + 0x998c4c10, 0xa7e78eff, 0xa45cb914, 0x9a377bfb, 0xe32ca719, + 0xdd4765f6, 0xdefc521d, 0xe09790f2, 0x6dcc9b03, 0x53a759ec, + 0x501c6e07, 0x6e77ace8, 0x176c700a, 0x2907b2e5, 0x2abc850e, + 0x14d747e1}, + {0x00000000, 0xc0df8ec1, 0xc1b96c58, 0x0166e299, 0x8273d9b0, + 0x42ac5771, 0x43cab5e8, 0x83153b29, 0x45e1c3ba, 0x853e4d7b, + 0x8458afe2, 0x44872123, 0xc7921a0a, 0x074d94cb, 0x062b7652, + 0xc6f4f893, 0xcbc4f6ae, 0x0b1b786f, 0x0a7d9af6, 0xcaa21437, + 0x49b72f1e, 0x8968a1df, 0x880e4346, 0x48d1cd87, 0x8e253514, + 0x4efabbd5, 0x4f9c594c, 0x8f43d78d, 0x0c56eca4, 0xcc896265, + 0xcdef80fc, 0x0d300e3d, 0xd78f9c86, 0x17501247, 0x1636f0de, + 0xd6e97e1f, 0x55fc4536, 0x9523cbf7, 0x9445296e, 0x549aa7af, + 0x926e5f3c, 0x52b1d1fd, 0x53d73364, 0x9308bda5, 0x101d868c, + 0xd0c2084d, 0xd1a4ead4, 0x117b6415, 0x1c4b6a28, 0xdc94e4e9, + 0xddf20670, 0x1d2d88b1, 0x9e38b398, 0x5ee73d59, 0x5f81dfc0, + 0x9f5e5101, 0x59aaa992, 0x99752753, 0x9813c5ca, 0x58cc4b0b, + 0xdbd97022, 0x1b06fee3, 0x1a601c7a, 0xdabf92bb, 0xef1948d6, + 0x2fc6c617, 0x2ea0248e, 0xee7faa4f, 0x6d6a9166, 0xadb51fa7, + 0xacd3fd3e, 0x6c0c73ff, 0xaaf88b6c, 0x6a2705ad, 0x6b41e734, + 0xab9e69f5, 0x288b52dc, 0xe854dc1d, 0xe9323e84, 0x29edb045, + 0x24ddbe78, 0xe40230b9, 0xe564d220, 0x25bb5ce1, 0xa6ae67c8, + 0x6671e909, 0x67170b90, 0xa7c88551, 0x613c7dc2, 0xa1e3f303, + 0xa085119a, 0x605a9f5b, 0xe34fa472, 0x23902ab3, 0x22f6c82a, + 0xe22946eb, 0x3896d450, 0xf8495a91, 0xf92fb808, 0x39f036c9, + 0xbae50de0, 0x7a3a8321, 0x7b5c61b8, 0xbb83ef79, 0x7d7717ea, + 0xbda8992b, 0xbcce7bb2, 0x7c11f573, 0xff04ce5a, 0x3fdb409b, + 0x3ebda202, 0xfe622cc3, 0xf35222fe, 0x338dac3f, 0x32eb4ea6, + 0xf234c067, 0x7121fb4e, 0xb1fe758f, 0xb0989716, 0x704719d7, + 0xb6b3e144, 0x766c6f85, 0x770a8d1c, 0xb7d503dd, 0x34c038f4, + 0xf41fb635, 0xf57954ac, 0x35a6da6d, 0x9f35e177, 0x5fea6fb6, + 0x5e8c8d2f, 0x9e5303ee, 0x1d4638c7, 0xdd99b606, 0xdcff549f, + 0x1c20da5e, 0xdad422cd, 0x1a0bac0c, 0x1b6d4e95, 0xdbb2c054, + 0x58a7fb7d, 0x987875bc, 0x991e9725, 0x59c119e4, 0x54f117d9, + 0x942e9918, 0x95487b81, 0x5597f540, 0xd682ce69, 0x165d40a8, + 0x173ba231, 0xd7e42cf0, 0x1110d463, 0xd1cf5aa2, 0xd0a9b83b, + 0x107636fa, 0x93630dd3, 0x53bc8312, 0x52da618b, 0x9205ef4a, + 0x48ba7df1, 0x8865f330, 0x890311a9, 0x49dc9f68, 0xcac9a441, + 0x0a162a80, 0x0b70c819, 0xcbaf46d8, 0x0d5bbe4b, 0xcd84308a, + 0xcce2d213, 0x0c3d5cd2, 0x8f2867fb, 0x4ff7e93a, 0x4e910ba3, + 0x8e4e8562, 0x837e8b5f, 0x43a1059e, 0x42c7e707, 0x821869c6, + 0x010d52ef, 0xc1d2dc2e, 0xc0b43eb7, 0x006bb076, 0xc69f48e5, + 0x0640c624, 0x072624bd, 0xc7f9aa7c, 0x44ec9155, 0x84331f94, + 0x8555fd0d, 0x458a73cc, 0x702ca9a1, 0xb0f32760, 0xb195c5f9, + 0x714a4b38, 0xf25f7011, 0x3280fed0, 0x33e61c49, 0xf3399288, + 0x35cd6a1b, 0xf512e4da, 0xf4740643, 0x34ab8882, 0xb7beb3ab, + 0x77613d6a, 0x7607dff3, 0xb6d85132, 0xbbe85f0f, 0x7b37d1ce, + 0x7a513357, 0xba8ebd96, 0x399b86bf, 0xf944087e, 0xf822eae7, + 0x38fd6426, 0xfe099cb5, 0x3ed61274, 0x3fb0f0ed, 0xff6f7e2c, + 0x7c7a4505, 0xbca5cbc4, 0xbdc3295d, 0x7d1ca79c, 0xa7a33527, + 0x677cbbe6, 0x661a597f, 0xa6c5d7be, 0x25d0ec97, 0xe50f6256, + 0xe46980cf, 0x24b60e0e, 0xe242f69d, 0x229d785c, 0x23fb9ac5, + 0xe3241404, 0x60312f2d, 0xa0eea1ec, 0xa1884375, 0x6157cdb4, + 0x6c67c389, 0xacb84d48, 0xaddeafd1, 0x6d012110, 0xee141a39, + 0x2ecb94f8, 0x2fad7661, 0xef72f8a0, 0x29860033, 0xe9598ef2, + 0xe83f6c6b, 0x28e0e2aa, 0xabf5d983, 0x6b2a5742, 0x6a4cb5db, + 0xaa933b1a}, + {0x00000000, 0x6f4ca59b, 0x9f9e3bec, 0xf0d29e77, 0x7f3b0603, + 0x1077a398, 0xe0a53def, 0x8fe99874, 0xfe760c06, 0x913aa99d, + 0x61e837ea, 0x0ea49271, 0x814d0a05, 0xee01af9e, 0x1ed331e9, + 0x719f9472, 0xfced180c, 0x93a1bd97, 0x637323e0, 0x0c3f867b, + 0x83d61e0f, 0xec9abb94, 0x1c4825e3, 0x73048078, 0x029b140a, + 0x6dd7b191, 0x9d052fe6, 0xf2498a7d, 0x7da01209, 0x12ecb792, + 0xe23e29e5, 0x8d728c7e, 0xf8db3118, 0x97979483, 0x67450af4, + 0x0809af6f, 0x87e0371b, 0xe8ac9280, 0x187e0cf7, 0x7732a96c, + 0x06ad3d1e, 0x69e19885, 0x993306f2, 0xf67fa369, 0x79963b1d, + 0x16da9e86, 0xe60800f1, 0x8944a56a, 0x04362914, 0x6b7a8c8f, + 0x9ba812f8, 0xf4e4b763, 0x7b0d2f17, 0x14418a8c, 0xe49314fb, + 0x8bdfb160, 0xfa402512, 0x950c8089, 0x65de1efe, 0x0a92bb65, + 0x857b2311, 0xea37868a, 0x1ae518fd, 0x75a9bd66, 0xf0b76330, + 0x9ffbc6ab, 0x6f2958dc, 0x0065fd47, 0x8f8c6533, 0xe0c0c0a8, + 0x10125edf, 0x7f5efb44, 0x0ec16f36, 0x618dcaad, 0x915f54da, + 0xfe13f141, 0x71fa6935, 0x1eb6ccae, 0xee6452d9, 0x8128f742, + 0x0c5a7b3c, 0x6316dea7, 0x93c440d0, 0xfc88e54b, 0x73617d3f, + 0x1c2dd8a4, 0xecff46d3, 0x83b3e348, 0xf22c773a, 0x9d60d2a1, + 0x6db24cd6, 0x02fee94d, 0x8d177139, 0xe25bd4a2, 0x12894ad5, + 0x7dc5ef4e, 0x086c5228, 0x6720f7b3, 0x97f269c4, 0xf8becc5f, + 0x7757542b, 0x181bf1b0, 0xe8c96fc7, 0x8785ca5c, 0xf61a5e2e, + 0x9956fbb5, 0x698465c2, 0x06c8c059, 0x8921582d, 0xe66dfdb6, + 0x16bf63c1, 0x79f3c65a, 0xf4814a24, 0x9bcdefbf, 0x6b1f71c8, + 0x0453d453, 0x8bba4c27, 0xe4f6e9bc, 0x142477cb, 0x7b68d250, + 0x0af74622, 0x65bbe3b9, 0x95697dce, 0xfa25d855, 0x75cc4021, + 0x1a80e5ba, 0xea527bcd, 0x851ede56, 0xe06fc760, 0x8f2362fb, + 0x7ff1fc8c, 0x10bd5917, 0x9f54c163, 0xf01864f8, 0x00cafa8f, + 0x6f865f14, 0x1e19cb66, 0x71556efd, 0x8187f08a, 0xeecb5511, + 0x6122cd65, 0x0e6e68fe, 0xfebcf689, 0x91f05312, 0x1c82df6c, + 0x73ce7af7, 0x831ce480, 0xec50411b, 0x63b9d96f, 0x0cf57cf4, + 0xfc27e283, 0x936b4718, 0xe2f4d36a, 0x8db876f1, 0x7d6ae886, + 0x12264d1d, 0x9dcfd569, 0xf28370f2, 0x0251ee85, 0x6d1d4b1e, + 0x18b4f678, 0x77f853e3, 0x872acd94, 0xe866680f, 0x678ff07b, + 0x08c355e0, 0xf811cb97, 0x975d6e0c, 0xe6c2fa7e, 0x898e5fe5, + 0x795cc192, 0x16106409, 0x99f9fc7d, 0xf6b559e6, 0x0667c791, + 0x692b620a, 0xe459ee74, 0x8b154bef, 0x7bc7d598, 0x148b7003, + 0x9b62e877, 0xf42e4dec, 0x04fcd39b, 0x6bb07600, 0x1a2fe272, + 0x756347e9, 0x85b1d99e, 0xeafd7c05, 0x6514e471, 0x0a5841ea, + 0xfa8adf9d, 0x95c67a06, 0x10d8a450, 0x7f9401cb, 0x8f469fbc, + 0xe00a3a27, 0x6fe3a253, 0x00af07c8, 0xf07d99bf, 0x9f313c24, + 0xeeaea856, 0x81e20dcd, 0x713093ba, 0x1e7c3621, 0x9195ae55, + 0xfed90bce, 0x0e0b95b9, 0x61473022, 0xec35bc5c, 0x837919c7, + 0x73ab87b0, 0x1ce7222b, 0x930eba5f, 0xfc421fc4, 0x0c9081b3, + 0x63dc2428, 0x1243b05a, 0x7d0f15c1, 0x8ddd8bb6, 0xe2912e2d, + 0x6d78b659, 0x023413c2, 0xf2e68db5, 0x9daa282e, 0xe8039548, + 0x874f30d3, 0x779daea4, 0x18d10b3f, 0x9738934b, 0xf87436d0, + 0x08a6a8a7, 0x67ea0d3c, 0x1675994e, 0x79393cd5, 0x89eba2a2, + 0xe6a70739, 0x694e9f4d, 0x06023ad6, 0xf6d0a4a1, 0x999c013a, + 0x14ee8d44, 0x7ba228df, 0x8b70b6a8, 0xe43c1333, 0x6bd58b47, + 0x04992edc, 0xf44bb0ab, 0x9b071530, 0xea988142, 0x85d424d9, + 0x7506baae, 0x1a4a1f35, 0x95a38741, 0xfaef22da, 0x0a3dbcad, + 0x65711936}}; + +#endif + +#endif + +#if N == 4 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xf1da05aa, 0x38c50d15, 0xc91f08bf, 0x718a1a2a, + 0x80501f80, 0x494f173f, 0xb8951295, 0xe3143454, 0x12ce31fe, + 0xdbd13941, 0x2a0b3ceb, 0x929e2e7e, 0x63442bd4, 0xaa5b236b, + 0x5b8126c1, 0x1d596ee9, 0xec836b43, 0x259c63fc, 0xd4466656, + 0x6cd374c3, 0x9d097169, 0x541679d6, 0xa5cc7c7c, 0xfe4d5abd, + 0x0f975f17, 0xc68857a8, 0x37525202, 0x8fc74097, 0x7e1d453d, + 0xb7024d82, 0x46d84828, 0x3ab2ddd2, 0xcb68d878, 0x0277d0c7, + 0xf3add56d, 0x4b38c7f8, 0xbae2c252, 0x73fdcaed, 0x8227cf47, + 0xd9a6e986, 0x287cec2c, 0xe163e493, 0x10b9e139, 0xa82cf3ac, + 0x59f6f606, 0x90e9feb9, 0x6133fb13, 0x27ebb33b, 0xd631b691, + 0x1f2ebe2e, 0xeef4bb84, 0x5661a911, 0xa7bbacbb, 0x6ea4a404, + 0x9f7ea1ae, 0xc4ff876f, 0x352582c5, 0xfc3a8a7a, 0x0de08fd0, + 0xb5759d45, 0x44af98ef, 0x8db09050, 0x7c6a95fa, 0x7565bba4, + 0x84bfbe0e, 0x4da0b6b1, 0xbc7ab31b, 0x04efa18e, 0xf535a424, + 0x3c2aac9b, 0xcdf0a931, 0x96718ff0, 0x67ab8a5a, 0xaeb482e5, + 0x5f6e874f, 0xe7fb95da, 0x16219070, 0xdf3e98cf, 0x2ee49d65, + 0x683cd54d, 0x99e6d0e7, 0x50f9d858, 0xa123ddf2, 0x19b6cf67, + 0xe86ccacd, 0x2173c272, 0xd0a9c7d8, 0x8b28e119, 0x7af2e4b3, + 0xb3edec0c, 0x4237e9a6, 0xfaa2fb33, 0x0b78fe99, 0xc267f626, + 0x33bdf38c, 0x4fd76676, 0xbe0d63dc, 0x77126b63, 0x86c86ec9, + 0x3e5d7c5c, 0xcf8779f6, 0x06987149, 0xf74274e3, 0xacc35222, + 0x5d195788, 0x94065f37, 0x65dc5a9d, 0xdd494808, 0x2c934da2, + 0xe58c451d, 0x145640b7, 0x528e089f, 0xa3540d35, 0x6a4b058a, + 0x9b910020, 0x230412b5, 0xd2de171f, 0x1bc11fa0, 0xea1b1a0a, + 0xb19a3ccb, 0x40403961, 0x895f31de, 0x78853474, 0xc01026e1, + 0x31ca234b, 0xf8d52bf4, 0x090f2e5e, 0xeacb7748, 0x1b1172e2, + 0xd20e7a5d, 0x23d47ff7, 0x9b416d62, 0x6a9b68c8, 0xa3846077, + 0x525e65dd, 0x09df431c, 0xf80546b6, 0x311a4e09, 0xc0c04ba3, + 0x78555936, 0x898f5c9c, 0x40905423, 0xb14a5189, 0xf79219a1, + 0x06481c0b, 0xcf5714b4, 0x3e8d111e, 0x8618038b, 0x77c20621, + 0xbedd0e9e, 0x4f070b34, 0x14862df5, 0xe55c285f, 0x2c4320e0, + 0xdd99254a, 0x650c37df, 0x94d63275, 0x5dc93aca, 0xac133f60, + 0xd079aa9a, 0x21a3af30, 0xe8bca78f, 0x1966a225, 0xa1f3b0b0, + 0x5029b51a, 0x9936bda5, 0x68ecb80f, 0x336d9ece, 0xc2b79b64, + 0x0ba893db, 0xfa729671, 0x42e784e4, 0xb33d814e, 0x7a2289f1, + 0x8bf88c5b, 0xcd20c473, 0x3cfac1d9, 0xf5e5c966, 0x043fcccc, + 0xbcaade59, 0x4d70dbf3, 0x846fd34c, 0x75b5d6e6, 0x2e34f027, + 0xdfeef58d, 0x16f1fd32, 0xe72bf898, 0x5fbeea0d, 0xae64efa7, + 0x677be718, 0x96a1e2b2, 0x9faeccec, 0x6e74c946, 0xa76bc1f9, + 0x56b1c453, 0xee24d6c6, 0x1ffed36c, 0xd6e1dbd3, 0x273bde79, + 0x7cbaf8b8, 0x8d60fd12, 0x447ff5ad, 0xb5a5f007, 0x0d30e292, + 0xfceae738, 0x35f5ef87, 0xc42fea2d, 0x82f7a205, 0x732da7af, + 0xba32af10, 0x4be8aaba, 0xf37db82f, 0x02a7bd85, 0xcbb8b53a, + 0x3a62b090, 0x61e39651, 0x903993fb, 0x59269b44, 0xa8fc9eee, + 0x10698c7b, 0xe1b389d1, 0x28ac816e, 0xd97684c4, 0xa51c113e, + 0x54c61494, 0x9dd91c2b, 0x6c031981, 0xd4960b14, 0x254c0ebe, + 0xec530601, 0x1d8903ab, 0x4608256a, 0xb7d220c0, 0x7ecd287f, + 0x8f172dd5, 0x37823f40, 0xc6583aea, 0x0f473255, 0xfe9d37ff, + 0xb8457fd7, 0x499f7a7d, 0x808072c2, 0x715a7768, 0xc9cf65fd, + 0x38156057, 0xf10a68e8, 0x00d06d42, 0x5b514b83, 0xaa8b4e29, + 0x63944696, 0x924e433c, 0x2adb51a9, 0xdb015403, 0x121e5cbc, + 0xe3c45916}, + {0x00000000, 0x0ee7e8d1, 0x1dcfd1a2, 0x13283973, 0x3b9fa344, + 0x35784b95, 0x265072e6, 0x28b79a37, 0x773f4688, 0x79d8ae59, + 0x6af0972a, 0x64177ffb, 0x4ca0e5cc, 0x42470d1d, 0x516f346e, + 0x5f88dcbf, 0xee7e8d10, 0xe09965c1, 0xf3b15cb2, 0xfd56b463, + 0xd5e12e54, 0xdb06c685, 0xc82efff6, 0xc6c91727, 0x9941cb98, + 0x97a62349, 0x848e1a3a, 0x8a69f2eb, 0xa2de68dc, 0xac39800d, + 0xbf11b97e, 0xb1f651af, 0x078c1c61, 0x096bf4b0, 0x1a43cdc3, + 0x14a42512, 0x3c13bf25, 0x32f457f4, 0x21dc6e87, 0x2f3b8656, + 0x70b35ae9, 0x7e54b238, 0x6d7c8b4b, 0x639b639a, 0x4b2cf9ad, + 0x45cb117c, 0x56e3280f, 0x5804c0de, 0xe9f29171, 0xe71579a0, + 0xf43d40d3, 0xfadaa802, 0xd26d3235, 0xdc8adae4, 0xcfa2e397, + 0xc1450b46, 0x9ecdd7f9, 0x902a3f28, 0x8302065b, 0x8de5ee8a, + 0xa55274bd, 0xabb59c6c, 0xb89da51f, 0xb67a4dce, 0x0f1838c2, + 0x01ffd013, 0x12d7e960, 0x1c3001b1, 0x34879b86, 0x3a607357, + 0x29484a24, 0x27afa2f5, 0x78277e4a, 0x76c0969b, 0x65e8afe8, + 0x6b0f4739, 0x43b8dd0e, 0x4d5f35df, 0x5e770cac, 0x5090e47d, + 0xe166b5d2, 0xef815d03, 0xfca96470, 0xf24e8ca1, 0xdaf91696, + 0xd41efe47, 0xc736c734, 0xc9d12fe5, 0x9659f35a, 0x98be1b8b, + 0x8b9622f8, 0x8571ca29, 0xadc6501e, 0xa321b8cf, 0xb00981bc, + 0xbeee696d, 0x089424a3, 0x0673cc72, 0x155bf501, 0x1bbc1dd0, + 0x330b87e7, 0x3dec6f36, 0x2ec45645, 0x2023be94, 0x7fab622b, + 0x714c8afa, 0x6264b389, 0x6c835b58, 0x4434c16f, 0x4ad329be, + 0x59fb10cd, 0x571cf81c, 0xe6eaa9b3, 0xe80d4162, 0xfb257811, + 0xf5c290c0, 0xdd750af7, 0xd392e226, 0xc0badb55, 0xce5d3384, + 0x91d5ef3b, 0x9f3207ea, 0x8c1a3e99, 0x82fdd648, 0xaa4a4c7f, + 0xa4ada4ae, 0xb7859ddd, 0xb962750c, 0x1e307184, 0x10d79955, + 0x03ffa026, 0x0d1848f7, 0x25afd2c0, 0x2b483a11, 0x38600362, + 0x3687ebb3, 0x690f370c, 0x67e8dfdd, 0x74c0e6ae, 0x7a270e7f, + 0x52909448, 0x5c777c99, 0x4f5f45ea, 0x41b8ad3b, 0xf04efc94, + 0xfea91445, 0xed812d36, 0xe366c5e7, 0xcbd15fd0, 0xc536b701, + 0xd61e8e72, 0xd8f966a3, 0x8771ba1c, 0x899652cd, 0x9abe6bbe, + 0x9459836f, 0xbcee1958, 0xb209f189, 0xa121c8fa, 0xafc6202b, + 0x19bc6de5, 0x175b8534, 0x0473bc47, 0x0a945496, 0x2223cea1, + 0x2cc42670, 0x3fec1f03, 0x310bf7d2, 0x6e832b6d, 0x6064c3bc, + 0x734cfacf, 0x7dab121e, 0x551c8829, 0x5bfb60f8, 0x48d3598b, + 0x4634b15a, 0xf7c2e0f5, 0xf9250824, 0xea0d3157, 0xe4ead986, + 0xcc5d43b1, 0xc2baab60, 0xd1929213, 0xdf757ac2, 0x80fda67d, + 0x8e1a4eac, 0x9d3277df, 0x93d59f0e, 0xbb620539, 0xb585ede8, + 0xa6add49b, 0xa84a3c4a, 0x11284946, 0x1fcfa197, 0x0ce798e4, + 0x02007035, 0x2ab7ea02, 0x245002d3, 0x37783ba0, 0x399fd371, + 0x66170fce, 0x68f0e71f, 0x7bd8de6c, 0x753f36bd, 0x5d88ac8a, + 0x536f445b, 0x40477d28, 0x4ea095f9, 0xff56c456, 0xf1b12c87, + 0xe29915f4, 0xec7efd25, 0xc4c96712, 0xca2e8fc3, 0xd906b6b0, + 0xd7e15e61, 0x886982de, 0x868e6a0f, 0x95a6537c, 0x9b41bbad, + 0xb3f6219a, 0xbd11c94b, 0xae39f038, 0xa0de18e9, 0x16a45527, + 0x1843bdf6, 0x0b6b8485, 0x058c6c54, 0x2d3bf663, 0x23dc1eb2, + 0x30f427c1, 0x3e13cf10, 0x619b13af, 0x6f7cfb7e, 0x7c54c20d, + 0x72b32adc, 0x5a04b0eb, 0x54e3583a, 0x47cb6149, 0x492c8998, + 0xf8dad837, 0xf63d30e6, 0xe5150995, 0xebf2e144, 0xc3457b73, + 0xcda293a2, 0xde8aaad1, 0xd06d4200, 0x8fe59ebf, 0x8102766e, + 0x922a4f1d, 0x9ccda7cc, 0xb47a3dfb, 0xba9dd52a, 0xa9b5ec59, + 0xa7520488}, + {0x00000000, 0x3c60e308, 0x78c1c610, 0x44a12518, 0xf1838c20, + 0xcde36f28, 0x89424a30, 0xb522a938, 0x38761e01, 0x0416fd09, + 0x40b7d811, 0x7cd73b19, 0xc9f59221, 0xf5957129, 0xb1345431, + 0x8d54b739, 0x70ec3c02, 0x4c8cdf0a, 0x082dfa12, 0x344d191a, + 0x816fb022, 0xbd0f532a, 0xf9ae7632, 0xc5ce953a, 0x489a2203, + 0x74fac10b, 0x305be413, 0x0c3b071b, 0xb919ae23, 0x85794d2b, + 0xc1d86833, 0xfdb88b3b, 0xe1d87804, 0xddb89b0c, 0x9919be14, + 0xa5795d1c, 0x105bf424, 0x2c3b172c, 0x689a3234, 0x54fad13c, + 0xd9ae6605, 0xe5ce850d, 0xa16fa015, 0x9d0f431d, 0x282dea25, + 0x144d092d, 0x50ec2c35, 0x6c8ccf3d, 0x91344406, 0xad54a70e, + 0xe9f58216, 0xd595611e, 0x60b7c826, 0x5cd72b2e, 0x18760e36, + 0x2416ed3e, 0xa9425a07, 0x9522b90f, 0xd1839c17, 0xede37f1f, + 0x58c1d627, 0x64a1352f, 0x20001037, 0x1c60f33f, 0x18c1f649, + 0x24a11541, 0x60003059, 0x5c60d351, 0xe9427a69, 0xd5229961, + 0x9183bc79, 0xade35f71, 0x20b7e848, 0x1cd70b40, 0x58762e58, + 0x6416cd50, 0xd1346468, 0xed548760, 0xa9f5a278, 0x95954170, + 0x682dca4b, 0x544d2943, 0x10ec0c5b, 0x2c8cef53, 0x99ae466b, + 0xa5cea563, 0xe16f807b, 0xdd0f6373, 0x505bd44a, 0x6c3b3742, + 0x289a125a, 0x14faf152, 0xa1d8586a, 0x9db8bb62, 0xd9199e7a, + 0xe5797d72, 0xf9198e4d, 0xc5796d45, 0x81d8485d, 0xbdb8ab55, + 0x089a026d, 0x34fae165, 0x705bc47d, 0x4c3b2775, 0xc16f904c, + 0xfd0f7344, 0xb9ae565c, 0x85ceb554, 0x30ec1c6c, 0x0c8cff64, + 0x482dda7c, 0x744d3974, 0x89f5b24f, 0xb5955147, 0xf134745f, + 0xcd549757, 0x78763e6f, 0x4416dd67, 0x00b7f87f, 0x3cd71b77, + 0xb183ac4e, 0x8de34f46, 0xc9426a5e, 0xf5228956, 0x4000206e, + 0x7c60c366, 0x38c1e67e, 0x04a10576, 0x3183ec92, 0x0de30f9a, + 0x49422a82, 0x7522c98a, 0xc00060b2, 0xfc6083ba, 0xb8c1a6a2, + 0x84a145aa, 0x09f5f293, 0x3595119b, 0x71343483, 0x4d54d78b, + 0xf8767eb3, 0xc4169dbb, 0x80b7b8a3, 0xbcd75bab, 0x416fd090, + 0x7d0f3398, 0x39ae1680, 0x05cef588, 0xb0ec5cb0, 0x8c8cbfb8, + 0xc82d9aa0, 0xf44d79a8, 0x7919ce91, 0x45792d99, 0x01d80881, + 0x3db8eb89, 0x889a42b1, 0xb4faa1b9, 0xf05b84a1, 0xcc3b67a9, + 0xd05b9496, 0xec3b779e, 0xa89a5286, 0x94fab18e, 0x21d818b6, + 0x1db8fbbe, 0x5919dea6, 0x65793dae, 0xe82d8a97, 0xd44d699f, + 0x90ec4c87, 0xac8caf8f, 0x19ae06b7, 0x25cee5bf, 0x616fc0a7, + 0x5d0f23af, 0xa0b7a894, 0x9cd74b9c, 0xd8766e84, 0xe4168d8c, + 0x513424b4, 0x6d54c7bc, 0x29f5e2a4, 0x159501ac, 0x98c1b695, + 0xa4a1559d, 0xe0007085, 0xdc60938d, 0x69423ab5, 0x5522d9bd, + 0x1183fca5, 0x2de31fad, 0x29421adb, 0x1522f9d3, 0x5183dccb, + 0x6de33fc3, 0xd8c196fb, 0xe4a175f3, 0xa00050eb, 0x9c60b3e3, + 0x113404da, 0x2d54e7d2, 0x69f5c2ca, 0x559521c2, 0xe0b788fa, + 0xdcd76bf2, 0x98764eea, 0xa416ade2, 0x59ae26d9, 0x65cec5d1, + 0x216fe0c9, 0x1d0f03c1, 0xa82daaf9, 0x944d49f1, 0xd0ec6ce9, + 0xec8c8fe1, 0x61d838d8, 0x5db8dbd0, 0x1919fec8, 0x25791dc0, + 0x905bb4f8, 0xac3b57f0, 0xe89a72e8, 0xd4fa91e0, 0xc89a62df, + 0xf4fa81d7, 0xb05ba4cf, 0x8c3b47c7, 0x3919eeff, 0x05790df7, + 0x41d828ef, 0x7db8cbe7, 0xf0ec7cde, 0xcc8c9fd6, 0x882dbace, + 0xb44d59c6, 0x016ff0fe, 0x3d0f13f6, 0x79ae36ee, 0x45ced5e6, + 0xb8765edd, 0x8416bdd5, 0xc0b798cd, 0xfcd77bc5, 0x49f5d2fd, + 0x759531f5, 0x313414ed, 0x0d54f7e5, 0x800040dc, 0xbc60a3d4, + 0xf8c186cc, 0xc4a165c4, 0x7183ccfc, 0x4de32ff4, 0x09420aec, + 0x3522e9e4}, + {0x00000000, 0x6307d924, 0xc60fb248, 0xa5086b6c, 0x576e62d1, + 0x3469bbf5, 0x9161d099, 0xf26609bd, 0xaedcc5a2, 0xcddb1c86, + 0x68d377ea, 0x0bd4aece, 0xf9b2a773, 0x9ab57e57, 0x3fbd153b, + 0x5cbacc1f, 0x86c88d05, 0xe5cf5421, 0x40c73f4d, 0x23c0e669, + 0xd1a6efd4, 0xb2a136f0, 0x17a95d9c, 0x74ae84b8, 0x281448a7, + 0x4b139183, 0xee1bfaef, 0x8d1c23cb, 0x7f7a2a76, 0x1c7df352, + 0xb975983e, 0xda72411a, 0xd6e01c4b, 0xb5e7c56f, 0x10efae03, + 0x73e87727, 0x818e7e9a, 0xe289a7be, 0x4781ccd2, 0x248615f6, + 0x783cd9e9, 0x1b3b00cd, 0xbe336ba1, 0xdd34b285, 0x2f52bb38, + 0x4c55621c, 0xe95d0970, 0x8a5ad054, 0x5028914e, 0x332f486a, + 0x96272306, 0xf520fa22, 0x0746f39f, 0x64412abb, 0xc14941d7, + 0xa24e98f3, 0xfef454ec, 0x9df38dc8, 0x38fbe6a4, 0x5bfc3f80, + 0xa99a363d, 0xca9def19, 0x6f958475, 0x0c925d51, 0x76b13ed7, + 0x15b6e7f3, 0xb0be8c9f, 0xd3b955bb, 0x21df5c06, 0x42d88522, + 0xe7d0ee4e, 0x84d7376a, 0xd86dfb75, 0xbb6a2251, 0x1e62493d, + 0x7d659019, 0x8f0399a4, 0xec044080, 0x490c2bec, 0x2a0bf2c8, + 0xf079b3d2, 0x937e6af6, 0x3676019a, 0x5571d8be, 0xa717d103, + 0xc4100827, 0x6118634b, 0x021fba6f, 0x5ea57670, 0x3da2af54, + 0x98aac438, 0xfbad1d1c, 0x09cb14a1, 0x6acccd85, 0xcfc4a6e9, + 0xacc37fcd, 0xa051229c, 0xc356fbb8, 0x665e90d4, 0x055949f0, + 0xf73f404d, 0x94389969, 0x3130f205, 0x52372b21, 0x0e8de73e, + 0x6d8a3e1a, 0xc8825576, 0xab858c52, 0x59e385ef, 0x3ae45ccb, + 0x9fec37a7, 0xfcebee83, 0x2699af99, 0x459e76bd, 0xe0961dd1, + 0x8391c4f5, 0x71f7cd48, 0x12f0146c, 0xb7f87f00, 0xd4ffa624, + 0x88456a3b, 0xeb42b31f, 0x4e4ad873, 0x2d4d0157, 0xdf2b08ea, + 0xbc2cd1ce, 0x1924baa2, 0x7a236386, 0xed627dae, 0x8e65a48a, + 0x2b6dcfe6, 0x486a16c2, 0xba0c1f7f, 0xd90bc65b, 0x7c03ad37, + 0x1f047413, 0x43beb80c, 0x20b96128, 0x85b10a44, 0xe6b6d360, + 0x14d0dadd, 0x77d703f9, 0xd2df6895, 0xb1d8b1b1, 0x6baaf0ab, + 0x08ad298f, 0xada542e3, 0xcea29bc7, 0x3cc4927a, 0x5fc34b5e, + 0xfacb2032, 0x99ccf916, 0xc5763509, 0xa671ec2d, 0x03798741, + 0x607e5e65, 0x921857d8, 0xf11f8efc, 0x5417e590, 0x37103cb4, + 0x3b8261e5, 0x5885b8c1, 0xfd8dd3ad, 0x9e8a0a89, 0x6cec0334, + 0x0febda10, 0xaae3b17c, 0xc9e46858, 0x955ea447, 0xf6597d63, + 0x5351160f, 0x3056cf2b, 0xc230c696, 0xa1371fb2, 0x043f74de, + 0x6738adfa, 0xbd4aece0, 0xde4d35c4, 0x7b455ea8, 0x1842878c, + 0xea248e31, 0x89235715, 0x2c2b3c79, 0x4f2ce55d, 0x13962942, + 0x7091f066, 0xd5999b0a, 0xb69e422e, 0x44f84b93, 0x27ff92b7, + 0x82f7f9db, 0xe1f020ff, 0x9bd34379, 0xf8d49a5d, 0x5ddcf131, + 0x3edb2815, 0xccbd21a8, 0xafbaf88c, 0x0ab293e0, 0x69b54ac4, + 0x350f86db, 0x56085fff, 0xf3003493, 0x9007edb7, 0x6261e40a, + 0x01663d2e, 0xa46e5642, 0xc7698f66, 0x1d1bce7c, 0x7e1c1758, + 0xdb147c34, 0xb813a510, 0x4a75acad, 0x29727589, 0x8c7a1ee5, + 0xef7dc7c1, 0xb3c70bde, 0xd0c0d2fa, 0x75c8b996, 0x16cf60b2, + 0xe4a9690f, 0x87aeb02b, 0x22a6db47, 0x41a10263, 0x4d335f32, + 0x2e348616, 0x8b3ced7a, 0xe83b345e, 0x1a5d3de3, 0x795ae4c7, + 0xdc528fab, 0xbf55568f, 0xe3ef9a90, 0x80e843b4, 0x25e028d8, + 0x46e7f1fc, 0xb481f841, 0xd7862165, 0x728e4a09, 0x1189932d, + 0xcbfbd237, 0xa8fc0b13, 0x0df4607f, 0x6ef3b95b, 0x9c95b0e6, + 0xff9269c2, 0x5a9a02ae, 0x399ddb8a, 0x65271795, 0x0620ceb1, + 0xa328a5dd, 0xc02f7cf9, 0x32497544, 0x514eac60, 0xf446c70c, + 0x97411e28}, + {0x00000000, 0x01b5fd1d, 0x036bfa3a, 0x02de0727, 0x06d7f474, + 0x07620969, 0x05bc0e4e, 0x0409f353, 0x0dafe8e8, 0x0c1a15f5, + 0x0ec412d2, 0x0f71efcf, 0x0b781c9c, 0x0acde181, 0x0813e6a6, + 0x09a61bbb, 0x1b5fd1d0, 0x1aea2ccd, 0x18342bea, 0x1981d6f7, + 0x1d8825a4, 0x1c3dd8b9, 0x1ee3df9e, 0x1f562283, 0x16f03938, + 0x1745c425, 0x159bc302, 0x142e3e1f, 0x1027cd4c, 0x11923051, + 0x134c3776, 0x12f9ca6b, 0x36bfa3a0, 0x370a5ebd, 0x35d4599a, + 0x3461a487, 0x306857d4, 0x31ddaac9, 0x3303adee, 0x32b650f3, + 0x3b104b48, 0x3aa5b655, 0x387bb172, 0x39ce4c6f, 0x3dc7bf3c, + 0x3c724221, 0x3eac4506, 0x3f19b81b, 0x2de07270, 0x2c558f6d, + 0x2e8b884a, 0x2f3e7557, 0x2b378604, 0x2a827b19, 0x285c7c3e, + 0x29e98123, 0x204f9a98, 0x21fa6785, 0x232460a2, 0x22919dbf, + 0x26986eec, 0x272d93f1, 0x25f394d6, 0x244669cb, 0x6d7f4740, + 0x6ccaba5d, 0x6e14bd7a, 0x6fa14067, 0x6ba8b334, 0x6a1d4e29, + 0x68c3490e, 0x6976b413, 0x60d0afa8, 0x616552b5, 0x63bb5592, + 0x620ea88f, 0x66075bdc, 0x67b2a6c1, 0x656ca1e6, 0x64d95cfb, + 0x76209690, 0x77956b8d, 0x754b6caa, 0x74fe91b7, 0x70f762e4, + 0x71429ff9, 0x739c98de, 0x722965c3, 0x7b8f7e78, 0x7a3a8365, + 0x78e48442, 0x7951795f, 0x7d588a0c, 0x7ced7711, 0x7e337036, + 0x7f868d2b, 0x5bc0e4e0, 0x5a7519fd, 0x58ab1eda, 0x591ee3c7, + 0x5d171094, 0x5ca2ed89, 0x5e7ceaae, 0x5fc917b3, 0x566f0c08, + 0x57daf115, 0x5504f632, 0x54b10b2f, 0x50b8f87c, 0x510d0561, + 0x53d30246, 0x5266ff5b, 0x409f3530, 0x412ac82d, 0x43f4cf0a, + 0x42413217, 0x4648c144, 0x47fd3c59, 0x45233b7e, 0x4496c663, + 0x4d30ddd8, 0x4c8520c5, 0x4e5b27e2, 0x4feedaff, 0x4be729ac, + 0x4a52d4b1, 0x488cd396, 0x49392e8b, 0xdafe8e80, 0xdb4b739d, + 0xd99574ba, 0xd82089a7, 0xdc297af4, 0xdd9c87e9, 0xdf4280ce, + 0xdef77dd3, 0xd7516668, 0xd6e49b75, 0xd43a9c52, 0xd58f614f, + 0xd186921c, 0xd0336f01, 0xd2ed6826, 0xd358953b, 0xc1a15f50, + 0xc014a24d, 0xc2caa56a, 0xc37f5877, 0xc776ab24, 0xc6c35639, + 0xc41d511e, 0xc5a8ac03, 0xcc0eb7b8, 0xcdbb4aa5, 0xcf654d82, + 0xced0b09f, 0xcad943cc, 0xcb6cbed1, 0xc9b2b9f6, 0xc80744eb, + 0xec412d20, 0xedf4d03d, 0xef2ad71a, 0xee9f2a07, 0xea96d954, + 0xeb232449, 0xe9fd236e, 0xe848de73, 0xe1eec5c8, 0xe05b38d5, + 0xe2853ff2, 0xe330c2ef, 0xe73931bc, 0xe68ccca1, 0xe452cb86, + 0xe5e7369b, 0xf71efcf0, 0xf6ab01ed, 0xf47506ca, 0xf5c0fbd7, + 0xf1c90884, 0xf07cf599, 0xf2a2f2be, 0xf3170fa3, 0xfab11418, + 0xfb04e905, 0xf9daee22, 0xf86f133f, 0xfc66e06c, 0xfdd31d71, + 0xff0d1a56, 0xfeb8e74b, 0xb781c9c0, 0xb63434dd, 0xb4ea33fa, + 0xb55fcee7, 0xb1563db4, 0xb0e3c0a9, 0xb23dc78e, 0xb3883a93, + 0xba2e2128, 0xbb9bdc35, 0xb945db12, 0xb8f0260f, 0xbcf9d55c, + 0xbd4c2841, 0xbf922f66, 0xbe27d27b, 0xacde1810, 0xad6be50d, + 0xafb5e22a, 0xae001f37, 0xaa09ec64, 0xabbc1179, 0xa962165e, + 0xa8d7eb43, 0xa171f0f8, 0xa0c40de5, 0xa21a0ac2, 0xa3aff7df, + 0xa7a6048c, 0xa613f991, 0xa4cdfeb6, 0xa57803ab, 0x813e6a60, + 0x808b977d, 0x8255905a, 0x83e06d47, 0x87e99e14, 0x865c6309, + 0x8482642e, 0x85379933, 0x8c918288, 0x8d247f95, 0x8ffa78b2, + 0x8e4f85af, 0x8a4676fc, 0x8bf38be1, 0x892d8cc6, 0x889871db, + 0x9a61bbb0, 0x9bd446ad, 0x990a418a, 0x98bfbc97, 0x9cb64fc4, + 0x9d03b2d9, 0x9fddb5fe, 0x9e6848e3, 0x97ce5358, 0x967bae45, + 0x94a5a962, 0x9510547f, 0x9119a72c, 0x90ac5a31, 0x92725d16, + 0x93c7a00b}, + {0x00000000, 0x6e8c1b41, 0xdd183682, 0xb3942dc3, 0x61416b45, + 0x0fcd7004, 0xbc595dc7, 0xd2d54686, 0xc282d68a, 0xac0ecdcb, + 0x1f9ae008, 0x7116fb49, 0xa3c3bdcf, 0xcd4fa68e, 0x7edb8b4d, + 0x1057900c, 0x5e74ab55, 0x30f8b014, 0x836c9dd7, 0xede08696, + 0x3f35c010, 0x51b9db51, 0xe22df692, 0x8ca1edd3, 0x9cf67ddf, + 0xf27a669e, 0x41ee4b5d, 0x2f62501c, 0xfdb7169a, 0x933b0ddb, + 0x20af2018, 0x4e233b59, 0xbce956aa, 0xd2654deb, 0x61f16028, + 0x0f7d7b69, 0xdda83def, 0xb32426ae, 0x00b00b6d, 0x6e3c102c, + 0x7e6b8020, 0x10e79b61, 0xa373b6a2, 0xcdffade3, 0x1f2aeb65, + 0x71a6f024, 0xc232dde7, 0xacbec6a6, 0xe29dfdff, 0x8c11e6be, + 0x3f85cb7d, 0x5109d03c, 0x83dc96ba, 0xed508dfb, 0x5ec4a038, + 0x3048bb79, 0x201f2b75, 0x4e933034, 0xfd071df7, 0x938b06b6, + 0x415e4030, 0x2fd25b71, 0x9c4676b2, 0xf2ca6df3, 0xa2a3ab15, + 0xcc2fb054, 0x7fbb9d97, 0x113786d6, 0xc3e2c050, 0xad6edb11, + 0x1efaf6d2, 0x7076ed93, 0x60217d9f, 0x0ead66de, 0xbd394b1d, + 0xd3b5505c, 0x016016da, 0x6fec0d9b, 0xdc782058, 0xb2f43b19, + 0xfcd70040, 0x925b1b01, 0x21cf36c2, 0x4f432d83, 0x9d966b05, + 0xf31a7044, 0x408e5d87, 0x2e0246c6, 0x3e55d6ca, 0x50d9cd8b, + 0xe34de048, 0x8dc1fb09, 0x5f14bd8f, 0x3198a6ce, 0x820c8b0d, + 0xec80904c, 0x1e4afdbf, 0x70c6e6fe, 0xc352cb3d, 0xadded07c, + 0x7f0b96fa, 0x11878dbb, 0xa213a078, 0xcc9fbb39, 0xdcc82b35, + 0xb2443074, 0x01d01db7, 0x6f5c06f6, 0xbd894070, 0xd3055b31, + 0x609176f2, 0x0e1d6db3, 0x403e56ea, 0x2eb24dab, 0x9d266068, + 0xf3aa7b29, 0x217f3daf, 0x4ff326ee, 0xfc670b2d, 0x92eb106c, + 0x82bc8060, 0xec309b21, 0x5fa4b6e2, 0x3128ada3, 0xe3fdeb25, + 0x8d71f064, 0x3ee5dda7, 0x5069c6e6, 0x9e36506b, 0xf0ba4b2a, + 0x432e66e9, 0x2da27da8, 0xff773b2e, 0x91fb206f, 0x226f0dac, + 0x4ce316ed, 0x5cb486e1, 0x32389da0, 0x81acb063, 0xef20ab22, + 0x3df5eda4, 0x5379f6e5, 0xe0eddb26, 0x8e61c067, 0xc042fb3e, + 0xaecee07f, 0x1d5acdbc, 0x73d6d6fd, 0xa103907b, 0xcf8f8b3a, + 0x7c1ba6f9, 0x1297bdb8, 0x02c02db4, 0x6c4c36f5, 0xdfd81b36, + 0xb1540077, 0x638146f1, 0x0d0d5db0, 0xbe997073, 0xd0156b32, + 0x22df06c1, 0x4c531d80, 0xffc73043, 0x914b2b02, 0x439e6d84, + 0x2d1276c5, 0x9e865b06, 0xf00a4047, 0xe05dd04b, 0x8ed1cb0a, + 0x3d45e6c9, 0x53c9fd88, 0x811cbb0e, 0xef90a04f, 0x5c048d8c, + 0x328896cd, 0x7cabad94, 0x1227b6d5, 0xa1b39b16, 0xcf3f8057, + 0x1deac6d1, 0x7366dd90, 0xc0f2f053, 0xae7eeb12, 0xbe297b1e, + 0xd0a5605f, 0x63314d9c, 0x0dbd56dd, 0xdf68105b, 0xb1e40b1a, + 0x027026d9, 0x6cfc3d98, 0x3c95fb7e, 0x5219e03f, 0xe18dcdfc, + 0x8f01d6bd, 0x5dd4903b, 0x33588b7a, 0x80cca6b9, 0xee40bdf8, + 0xfe172df4, 0x909b36b5, 0x230f1b76, 0x4d830037, 0x9f5646b1, + 0xf1da5df0, 0x424e7033, 0x2cc26b72, 0x62e1502b, 0x0c6d4b6a, + 0xbff966a9, 0xd1757de8, 0x03a03b6e, 0x6d2c202f, 0xdeb80dec, + 0xb03416ad, 0xa06386a1, 0xceef9de0, 0x7d7bb023, 0x13f7ab62, + 0xc122ede4, 0xafaef6a5, 0x1c3adb66, 0x72b6c027, 0x807cadd4, + 0xeef0b695, 0x5d649b56, 0x33e88017, 0xe13dc691, 0x8fb1ddd0, + 0x3c25f013, 0x52a9eb52, 0x42fe7b5e, 0x2c72601f, 0x9fe64ddc, + 0xf16a569d, 0x23bf101b, 0x4d330b5a, 0xfea72699, 0x902b3dd8, + 0xde080681, 0xb0841dc0, 0x03103003, 0x6d9c2b42, 0xbf496dc4, + 0xd1c57685, 0x62515b46, 0x0cdd4007, 0x1c8ad00b, 0x7206cb4a, + 0xc192e689, 0xaf1efdc8, 0x7dcbbb4e, 0x1347a00f, 0xa0d38dcc, + 0xce5f968d}, + {0x00000000, 0xe71da697, 0x154a4b6f, 0xf257edf8, 0x2a9496de, + 0xcd893049, 0x3fdeddb1, 0xd8c37b26, 0x55292dbc, 0xb2348b2b, + 0x406366d3, 0xa77ec044, 0x7fbdbb62, 0x98a01df5, 0x6af7f00d, + 0x8dea569a, 0xaa525b78, 0x4d4ffdef, 0xbf181017, 0x5805b680, + 0x80c6cda6, 0x67db6b31, 0x958c86c9, 0x7291205e, 0xff7b76c4, + 0x1866d053, 0xea313dab, 0x0d2c9b3c, 0xd5efe01a, 0x32f2468d, + 0xc0a5ab75, 0x27b80de2, 0x8fd5b0b1, 0x68c81626, 0x9a9ffbde, + 0x7d825d49, 0xa541266f, 0x425c80f8, 0xb00b6d00, 0x5716cb97, + 0xdafc9d0d, 0x3de13b9a, 0xcfb6d662, 0x28ab70f5, 0xf0680bd3, + 0x1775ad44, 0xe52240bc, 0x023fe62b, 0x2587ebc9, 0xc29a4d5e, + 0x30cda0a6, 0xd7d00631, 0x0f137d17, 0xe80edb80, 0x1a593678, + 0xfd4490ef, 0x70aec675, 0x97b360e2, 0x65e48d1a, 0x82f92b8d, + 0x5a3a50ab, 0xbd27f63c, 0x4f701bc4, 0xa86dbd53, 0xc4da6723, + 0x23c7c1b4, 0xd1902c4c, 0x368d8adb, 0xee4ef1fd, 0x0953576a, + 0xfb04ba92, 0x1c191c05, 0x91f34a9f, 0x76eeec08, 0x84b901f0, + 0x63a4a767, 0xbb67dc41, 0x5c7a7ad6, 0xae2d972e, 0x493031b9, + 0x6e883c5b, 0x89959acc, 0x7bc27734, 0x9cdfd1a3, 0x441caa85, + 0xa3010c12, 0x5156e1ea, 0xb64b477d, 0x3ba111e7, 0xdcbcb770, + 0x2eeb5a88, 0xc9f6fc1f, 0x11358739, 0xf62821ae, 0x047fcc56, + 0xe3626ac1, 0x4b0fd792, 0xac127105, 0x5e459cfd, 0xb9583a6a, + 0x619b414c, 0x8686e7db, 0x74d10a23, 0x93ccacb4, 0x1e26fa2e, + 0xf93b5cb9, 0x0b6cb141, 0xec7117d6, 0x34b26cf0, 0xd3afca67, + 0x21f8279f, 0xc6e58108, 0xe15d8cea, 0x06402a7d, 0xf417c785, + 0x130a6112, 0xcbc91a34, 0x2cd4bca3, 0xde83515b, 0x399ef7cc, + 0xb474a156, 0x536907c1, 0xa13eea39, 0x46234cae, 0x9ee03788, + 0x79fd911f, 0x8baa7ce7, 0x6cb7da70, 0x52c5c807, 0xb5d86e90, + 0x478f8368, 0xa09225ff, 0x78515ed9, 0x9f4cf84e, 0x6d1b15b6, + 0x8a06b321, 0x07ece5bb, 0xe0f1432c, 0x12a6aed4, 0xf5bb0843, + 0x2d787365, 0xca65d5f2, 0x3832380a, 0xdf2f9e9d, 0xf897937f, + 0x1f8a35e8, 0xedddd810, 0x0ac07e87, 0xd20305a1, 0x351ea336, + 0xc7494ece, 0x2054e859, 0xadbebec3, 0x4aa31854, 0xb8f4f5ac, + 0x5fe9533b, 0x872a281d, 0x60378e8a, 0x92606372, 0x757dc5e5, + 0xdd1078b6, 0x3a0dde21, 0xc85a33d9, 0x2f47954e, 0xf784ee68, + 0x109948ff, 0xe2cea507, 0x05d30390, 0x8839550a, 0x6f24f39d, + 0x9d731e65, 0x7a6eb8f2, 0xa2adc3d4, 0x45b06543, 0xb7e788bb, + 0x50fa2e2c, 0x774223ce, 0x905f8559, 0x620868a1, 0x8515ce36, + 0x5dd6b510, 0xbacb1387, 0x489cfe7f, 0xaf8158e8, 0x226b0e72, + 0xc576a8e5, 0x3721451d, 0xd03ce38a, 0x08ff98ac, 0xefe23e3b, + 0x1db5d3c3, 0xfaa87554, 0x961faf24, 0x710209b3, 0x8355e44b, + 0x644842dc, 0xbc8b39fa, 0x5b969f6d, 0xa9c17295, 0x4edcd402, + 0xc3368298, 0x242b240f, 0xd67cc9f7, 0x31616f60, 0xe9a21446, + 0x0ebfb2d1, 0xfce85f29, 0x1bf5f9be, 0x3c4df45c, 0xdb5052cb, + 0x2907bf33, 0xce1a19a4, 0x16d96282, 0xf1c4c415, 0x039329ed, + 0xe48e8f7a, 0x6964d9e0, 0x8e797f77, 0x7c2e928f, 0x9b333418, + 0x43f04f3e, 0xa4ede9a9, 0x56ba0451, 0xb1a7a2c6, 0x19ca1f95, + 0xfed7b902, 0x0c8054fa, 0xeb9df26d, 0x335e894b, 0xd4432fdc, + 0x2614c224, 0xc10964b3, 0x4ce33229, 0xabfe94be, 0x59a97946, + 0xbeb4dfd1, 0x6677a4f7, 0x816a0260, 0x733def98, 0x9420490f, + 0xb39844ed, 0x5485e27a, 0xa6d20f82, 0x41cfa915, 0x990cd233, + 0x7e1174a4, 0x8c46995c, 0x6b5b3fcb, 0xe6b16951, 0x01accfc6, + 0xf3fb223e, 0x14e684a9, 0xcc25ff8f, 0x2b385918, 0xd96fb4e0, + 0x3e721277}, + {0x00000000, 0xa58b900e, 0x9066265d, 0x35edb653, 0xfbbd4afb, + 0x5e36daf5, 0x6bdb6ca6, 0xce50fca8, 0x2c0b93b7, 0x898003b9, + 0xbc6db5ea, 0x19e625e4, 0xd7b6d94c, 0x723d4942, 0x47d0ff11, + 0xe25b6f1f, 0x5817276e, 0xfd9cb760, 0xc8710133, 0x6dfa913d, + 0xa3aa6d95, 0x0621fd9b, 0x33cc4bc8, 0x9647dbc6, 0x741cb4d9, + 0xd19724d7, 0xe47a9284, 0x41f1028a, 0x8fa1fe22, 0x2a2a6e2c, + 0x1fc7d87f, 0xba4c4871, 0xb02e4edc, 0x15a5ded2, 0x20486881, + 0x85c3f88f, 0x4b930427, 0xee189429, 0xdbf5227a, 0x7e7eb274, + 0x9c25dd6b, 0x39ae4d65, 0x0c43fb36, 0xa9c86b38, 0x67989790, + 0xc213079e, 0xf7feb1cd, 0x527521c3, 0xe83969b2, 0x4db2f9bc, + 0x785f4fef, 0xddd4dfe1, 0x13842349, 0xb60fb347, 0x83e20514, + 0x2669951a, 0xc432fa05, 0x61b96a0b, 0x5454dc58, 0xf1df4c56, + 0x3f8fb0fe, 0x9a0420f0, 0xafe996a3, 0x0a6206ad, 0xbb2d9bf9, + 0x1ea60bf7, 0x2b4bbda4, 0x8ec02daa, 0x4090d102, 0xe51b410c, + 0xd0f6f75f, 0x757d6751, 0x9726084e, 0x32ad9840, 0x07402e13, + 0xa2cbbe1d, 0x6c9b42b5, 0xc910d2bb, 0xfcfd64e8, 0x5976f4e6, + 0xe33abc97, 0x46b12c99, 0x735c9aca, 0xd6d70ac4, 0x1887f66c, + 0xbd0c6662, 0x88e1d031, 0x2d6a403f, 0xcf312f20, 0x6ababf2e, + 0x5f57097d, 0xfadc9973, 0x348c65db, 0x9107f5d5, 0xa4ea4386, + 0x0161d388, 0x0b03d525, 0xae88452b, 0x9b65f378, 0x3eee6376, + 0xf0be9fde, 0x55350fd0, 0x60d8b983, 0xc553298d, 0x27084692, + 0x8283d69c, 0xb76e60cf, 0x12e5f0c1, 0xdcb50c69, 0x793e9c67, + 0x4cd32a34, 0xe958ba3a, 0x5314f24b, 0xf69f6245, 0xc372d416, + 0x66f94418, 0xa8a9b8b0, 0x0d2228be, 0x38cf9eed, 0x9d440ee3, + 0x7f1f61fc, 0xda94f1f2, 0xef7947a1, 0x4af2d7af, 0x84a22b07, + 0x2129bb09, 0x14c40d5a, 0xb14f9d54, 0xad2a31b3, 0x08a1a1bd, + 0x3d4c17ee, 0x98c787e0, 0x56977b48, 0xf31ceb46, 0xc6f15d15, + 0x637acd1b, 0x8121a204, 0x24aa320a, 0x11478459, 0xb4cc1457, + 0x7a9ce8ff, 0xdf1778f1, 0xeafacea2, 0x4f715eac, 0xf53d16dd, + 0x50b686d3, 0x655b3080, 0xc0d0a08e, 0x0e805c26, 0xab0bcc28, + 0x9ee67a7b, 0x3b6dea75, 0xd936856a, 0x7cbd1564, 0x4950a337, + 0xecdb3339, 0x228bcf91, 0x87005f9f, 0xb2ede9cc, 0x176679c2, + 0x1d047f6f, 0xb88fef61, 0x8d625932, 0x28e9c93c, 0xe6b93594, + 0x4332a59a, 0x76df13c9, 0xd35483c7, 0x310fecd8, 0x94847cd6, + 0xa169ca85, 0x04e25a8b, 0xcab2a623, 0x6f39362d, 0x5ad4807e, + 0xff5f1070, 0x45135801, 0xe098c80f, 0xd5757e5c, 0x70feee52, + 0xbeae12fa, 0x1b2582f4, 0x2ec834a7, 0x8b43a4a9, 0x6918cbb6, + 0xcc935bb8, 0xf97eedeb, 0x5cf57de5, 0x92a5814d, 0x372e1143, + 0x02c3a710, 0xa748371e, 0x1607aa4a, 0xb38c3a44, 0x86618c17, + 0x23ea1c19, 0xedbae0b1, 0x483170bf, 0x7ddcc6ec, 0xd85756e2, + 0x3a0c39fd, 0x9f87a9f3, 0xaa6a1fa0, 0x0fe18fae, 0xc1b17306, + 0x643ae308, 0x51d7555b, 0xf45cc555, 0x4e108d24, 0xeb9b1d2a, + 0xde76ab79, 0x7bfd3b77, 0xb5adc7df, 0x102657d1, 0x25cbe182, + 0x8040718c, 0x621b1e93, 0xc7908e9d, 0xf27d38ce, 0x57f6a8c0, + 0x99a65468, 0x3c2dc466, 0x09c07235, 0xac4be23b, 0xa629e496, + 0x03a27498, 0x364fc2cb, 0x93c452c5, 0x5d94ae6d, 0xf81f3e63, + 0xcdf28830, 0x6879183e, 0x8a227721, 0x2fa9e72f, 0x1a44517c, + 0xbfcfc172, 0x719f3dda, 0xd414add4, 0xe1f91b87, 0x44728b89, + 0xfe3ec3f8, 0x5bb553f6, 0x6e58e5a5, 0xcbd375ab, 0x05838903, + 0xa008190d, 0x95e5af5e, 0x306e3f50, 0xd235504f, 0x77bec041, + 0x42537612, 0xe7d8e61c, 0x29881ab4, 0x8c038aba, 0xb9ee3ce9, + 0x1c65ace7}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0x0e908ba500000000, 0x5d26669000000000, + 0x53b6ed3500000000, 0xfb4abdfb00000000, 0xf5da365e00000000, + 0xa66cdb6b00000000, 0xa8fc50ce00000000, 0xb7930b2c00000000, + 0xb903808900000000, 0xeab56dbc00000000, 0xe425e61900000000, + 0x4cd9b6d700000000, 0x42493d7200000000, 0x11ffd04700000000, + 0x1f6f5be200000000, 0x6e27175800000000, 0x60b79cfd00000000, + 0x330171c800000000, 0x3d91fa6d00000000, 0x956daaa300000000, + 0x9bfd210600000000, 0xc84bcc3300000000, 0xc6db479600000000, + 0xd9b41c7400000000, 0xd72497d100000000, 0x84927ae400000000, + 0x8a02f14100000000, 0x22fea18f00000000, 0x2c6e2a2a00000000, + 0x7fd8c71f00000000, 0x71484cba00000000, 0xdc4e2eb000000000, + 0xd2dea51500000000, 0x8168482000000000, 0x8ff8c38500000000, + 0x2704934b00000000, 0x299418ee00000000, 0x7a22f5db00000000, + 0x74b27e7e00000000, 0x6bdd259c00000000, 0x654dae3900000000, + 0x36fb430c00000000, 0x386bc8a900000000, 0x9097986700000000, + 0x9e0713c200000000, 0xcdb1fef700000000, 0xc321755200000000, + 0xb26939e800000000, 0xbcf9b24d00000000, 0xef4f5f7800000000, + 0xe1dfd4dd00000000, 0x4923841300000000, 0x47b30fb600000000, + 0x1405e28300000000, 0x1a95692600000000, 0x05fa32c400000000, + 0x0b6ab96100000000, 0x58dc545400000000, 0x564cdff100000000, + 0xfeb08f3f00000000, 0xf020049a00000000, 0xa396e9af00000000, + 0xad06620a00000000, 0xf99b2dbb00000000, 0xf70ba61e00000000, + 0xa4bd4b2b00000000, 0xaa2dc08e00000000, 0x02d1904000000000, + 0x0c411be500000000, 0x5ff7f6d000000000, 0x51677d7500000000, + 0x4e08269700000000, 0x4098ad3200000000, 0x132e400700000000, + 0x1dbecba200000000, 0xb5429b6c00000000, 0xbbd210c900000000, + 0xe864fdfc00000000, 0xe6f4765900000000, 0x97bc3ae300000000, + 0x992cb14600000000, 0xca9a5c7300000000, 0xc40ad7d600000000, + 0x6cf6871800000000, 0x62660cbd00000000, 0x31d0e18800000000, + 0x3f406a2d00000000, 0x202f31cf00000000, 0x2ebfba6a00000000, + 0x7d09575f00000000, 0x7399dcfa00000000, 0xdb658c3400000000, + 0xd5f5079100000000, 0x8643eaa400000000, 0x88d3610100000000, + 0x25d5030b00000000, 0x2b4588ae00000000, 0x78f3659b00000000, + 0x7663ee3e00000000, 0xde9fbef000000000, 0xd00f355500000000, + 0x83b9d86000000000, 0x8d2953c500000000, 0x9246082700000000, + 0x9cd6838200000000, 0xcf606eb700000000, 0xc1f0e51200000000, + 0x690cb5dc00000000, 0x679c3e7900000000, 0x342ad34c00000000, + 0x3aba58e900000000, 0x4bf2145300000000, 0x45629ff600000000, + 0x16d472c300000000, 0x1844f96600000000, 0xb0b8a9a800000000, + 0xbe28220d00000000, 0xed9ecf3800000000, 0xe30e449d00000000, + 0xfc611f7f00000000, 0xf2f194da00000000, 0xa14779ef00000000, + 0xafd7f24a00000000, 0x072ba28400000000, 0x09bb292100000000, + 0x5a0dc41400000000, 0x549d4fb100000000, 0xb3312aad00000000, + 0xbda1a10800000000, 0xee174c3d00000000, 0xe087c79800000000, + 0x487b975600000000, 0x46eb1cf300000000, 0x155df1c600000000, + 0x1bcd7a6300000000, 0x04a2218100000000, 0x0a32aa2400000000, + 0x5984471100000000, 0x5714ccb400000000, 0xffe89c7a00000000, + 0xf17817df00000000, 0xa2cefaea00000000, 0xac5e714f00000000, + 0xdd163df500000000, 0xd386b65000000000, 0x80305b6500000000, + 0x8ea0d0c000000000, 0x265c800e00000000, 0x28cc0bab00000000, + 0x7b7ae69e00000000, 0x75ea6d3b00000000, 0x6a8536d900000000, + 0x6415bd7c00000000, 0x37a3504900000000, 0x3933dbec00000000, + 0x91cf8b2200000000, 0x9f5f008700000000, 0xcce9edb200000000, + 0xc279661700000000, 0x6f7f041d00000000, 0x61ef8fb800000000, + 0x3259628d00000000, 0x3cc9e92800000000, 0x9435b9e600000000, + 0x9aa5324300000000, 0xc913df7600000000, 0xc78354d300000000, + 0xd8ec0f3100000000, 0xd67c849400000000, 0x85ca69a100000000, + 0x8b5ae20400000000, 0x23a6b2ca00000000, 0x2d36396f00000000, + 0x7e80d45a00000000, 0x70105fff00000000, 0x0158134500000000, + 0x0fc898e000000000, 0x5c7e75d500000000, 0x52eefe7000000000, + 0xfa12aebe00000000, 0xf482251b00000000, 0xa734c82e00000000, + 0xa9a4438b00000000, 0xb6cb186900000000, 0xb85b93cc00000000, + 0xebed7ef900000000, 0xe57df55c00000000, 0x4d81a59200000000, + 0x43112e3700000000, 0x10a7c30200000000, 0x1e3748a700000000, + 0x4aaa071600000000, 0x443a8cb300000000, 0x178c618600000000, + 0x191cea2300000000, 0xb1e0baed00000000, 0xbf70314800000000, + 0xecc6dc7d00000000, 0xe25657d800000000, 0xfd390c3a00000000, + 0xf3a9879f00000000, 0xa01f6aaa00000000, 0xae8fe10f00000000, + 0x0673b1c100000000, 0x08e33a6400000000, 0x5b55d75100000000, + 0x55c55cf400000000, 0x248d104e00000000, 0x2a1d9beb00000000, + 0x79ab76de00000000, 0x773bfd7b00000000, 0xdfc7adb500000000, + 0xd157261000000000, 0x82e1cb2500000000, 0x8c71408000000000, + 0x931e1b6200000000, 0x9d8e90c700000000, 0xce387df200000000, + 0xc0a8f65700000000, 0x6854a69900000000, 0x66c42d3c00000000, + 0x3572c00900000000, 0x3be24bac00000000, 0x96e429a600000000, + 0x9874a20300000000, 0xcbc24f3600000000, 0xc552c49300000000, + 0x6dae945d00000000, 0x633e1ff800000000, 0x3088f2cd00000000, + 0x3e18796800000000, 0x2177228a00000000, 0x2fe7a92f00000000, + 0x7c51441a00000000, 0x72c1cfbf00000000, 0xda3d9f7100000000, + 0xd4ad14d400000000, 0x871bf9e100000000, 0x898b724400000000, + 0xf8c33efe00000000, 0xf653b55b00000000, 0xa5e5586e00000000, + 0xab75d3cb00000000, 0x0389830500000000, 0x0d1908a000000000, + 0x5eafe59500000000, 0x503f6e3000000000, 0x4f5035d200000000, + 0x41c0be7700000000, 0x1276534200000000, 0x1ce6d8e700000000, + 0xb41a882900000000, 0xba8a038c00000000, 0xe93ceeb900000000, + 0xe7ac651c00000000}, + {0x0000000000000000, 0x97a61de700000000, 0x6f4b4a1500000000, + 0xf8ed57f200000000, 0xde96942a00000000, 0x493089cd00000000, + 0xb1ddde3f00000000, 0x267bc3d800000000, 0xbc2d295500000000, + 0x2b8b34b200000000, 0xd366634000000000, 0x44c07ea700000000, + 0x62bbbd7f00000000, 0xf51da09800000000, 0x0df0f76a00000000, + 0x9a56ea8d00000000, 0x785b52aa00000000, 0xeffd4f4d00000000, + 0x171018bf00000000, 0x80b6055800000000, 0xa6cdc68000000000, + 0x316bdb6700000000, 0xc9868c9500000000, 0x5e20917200000000, + 0xc4767bff00000000, 0x53d0661800000000, 0xab3d31ea00000000, + 0x3c9b2c0d00000000, 0x1ae0efd500000000, 0x8d46f23200000000, + 0x75aba5c000000000, 0xe20db82700000000, 0xb1b0d58f00000000, + 0x2616c86800000000, 0xdefb9f9a00000000, 0x495d827d00000000, + 0x6f2641a500000000, 0xf8805c4200000000, 0x006d0bb000000000, + 0x97cb165700000000, 0x0d9dfcda00000000, 0x9a3be13d00000000, + 0x62d6b6cf00000000, 0xf570ab2800000000, 0xd30b68f000000000, + 0x44ad751700000000, 0xbc4022e500000000, 0x2be63f0200000000, + 0xc9eb872500000000, 0x5e4d9ac200000000, 0xa6a0cd3000000000, + 0x3106d0d700000000, 0x177d130f00000000, 0x80db0ee800000000, + 0x7836591a00000000, 0xef9044fd00000000, 0x75c6ae7000000000, + 0xe260b39700000000, 0x1a8de46500000000, 0x8d2bf98200000000, + 0xab503a5a00000000, 0x3cf627bd00000000, 0xc41b704f00000000, + 0x53bd6da800000000, 0x2367dac400000000, 0xb4c1c72300000000, + 0x4c2c90d100000000, 0xdb8a8d3600000000, 0xfdf14eee00000000, + 0x6a57530900000000, 0x92ba04fb00000000, 0x051c191c00000000, + 0x9f4af39100000000, 0x08ecee7600000000, 0xf001b98400000000, + 0x67a7a46300000000, 0x41dc67bb00000000, 0xd67a7a5c00000000, + 0x2e972dae00000000, 0xb931304900000000, 0x5b3c886e00000000, + 0xcc9a958900000000, 0x3477c27b00000000, 0xa3d1df9c00000000, + 0x85aa1c4400000000, 0x120c01a300000000, 0xeae1565100000000, + 0x7d474bb600000000, 0xe711a13b00000000, 0x70b7bcdc00000000, + 0x885aeb2e00000000, 0x1ffcf6c900000000, 0x3987351100000000, + 0xae2128f600000000, 0x56cc7f0400000000, 0xc16a62e300000000, + 0x92d70f4b00000000, 0x057112ac00000000, 0xfd9c455e00000000, + 0x6a3a58b900000000, 0x4c419b6100000000, 0xdbe7868600000000, + 0x230ad17400000000, 0xb4accc9300000000, 0x2efa261e00000000, + 0xb95c3bf900000000, 0x41b16c0b00000000, 0xd61771ec00000000, + 0xf06cb23400000000, 0x67caafd300000000, 0x9f27f82100000000, + 0x0881e5c600000000, 0xea8c5de100000000, 0x7d2a400600000000, + 0x85c717f400000000, 0x12610a1300000000, 0x341ac9cb00000000, + 0xa3bcd42c00000000, 0x5b5183de00000000, 0xccf79e3900000000, + 0x56a174b400000000, 0xc107695300000000, 0x39ea3ea100000000, + 0xae4c234600000000, 0x8837e09e00000000, 0x1f91fd7900000000, + 0xe77caa8b00000000, 0x70dab76c00000000, 0x07c8c55200000000, + 0x906ed8b500000000, 0x68838f4700000000, 0xff2592a000000000, + 0xd95e517800000000, 0x4ef84c9f00000000, 0xb6151b6d00000000, + 0x21b3068a00000000, 0xbbe5ec0700000000, 0x2c43f1e000000000, + 0xd4aea61200000000, 0x4308bbf500000000, 0x6573782d00000000, + 0xf2d565ca00000000, 0x0a38323800000000, 0x9d9e2fdf00000000, + 0x7f9397f800000000, 0xe8358a1f00000000, 0x10d8dded00000000, + 0x877ec00a00000000, 0xa10503d200000000, 0x36a31e3500000000, + 0xce4e49c700000000, 0x59e8542000000000, 0xc3bebead00000000, + 0x5418a34a00000000, 0xacf5f4b800000000, 0x3b53e95f00000000, + 0x1d282a8700000000, 0x8a8e376000000000, 0x7263609200000000, + 0xe5c57d7500000000, 0xb67810dd00000000, 0x21de0d3a00000000, + 0xd9335ac800000000, 0x4e95472f00000000, 0x68ee84f700000000, + 0xff48991000000000, 0x07a5cee200000000, 0x9003d30500000000, + 0x0a55398800000000, 0x9df3246f00000000, 0x651e739d00000000, + 0xf2b86e7a00000000, 0xd4c3ada200000000, 0x4365b04500000000, + 0xbb88e7b700000000, 0x2c2efa5000000000, 0xce23427700000000, + 0x59855f9000000000, 0xa168086200000000, 0x36ce158500000000, + 0x10b5d65d00000000, 0x8713cbba00000000, 0x7ffe9c4800000000, + 0xe85881af00000000, 0x720e6b2200000000, 0xe5a876c500000000, + 0x1d45213700000000, 0x8ae33cd000000000, 0xac98ff0800000000, + 0x3b3ee2ef00000000, 0xc3d3b51d00000000, 0x5475a8fa00000000, + 0x24af1f9600000000, 0xb309027100000000, 0x4be4558300000000, + 0xdc42486400000000, 0xfa398bbc00000000, 0x6d9f965b00000000, + 0x9572c1a900000000, 0x02d4dc4e00000000, 0x988236c300000000, + 0x0f242b2400000000, 0xf7c97cd600000000, 0x606f613100000000, + 0x4614a2e900000000, 0xd1b2bf0e00000000, 0x295fe8fc00000000, + 0xbef9f51b00000000, 0x5cf44d3c00000000, 0xcb5250db00000000, + 0x33bf072900000000, 0xa4191ace00000000, 0x8262d91600000000, + 0x15c4c4f100000000, 0xed29930300000000, 0x7a8f8ee400000000, + 0xe0d9646900000000, 0x777f798e00000000, 0x8f922e7c00000000, + 0x1834339b00000000, 0x3e4ff04300000000, 0xa9e9eda400000000, + 0x5104ba5600000000, 0xc6a2a7b100000000, 0x951fca1900000000, + 0x02b9d7fe00000000, 0xfa54800c00000000, 0x6df29deb00000000, + 0x4b895e3300000000, 0xdc2f43d400000000, 0x24c2142600000000, + 0xb36409c100000000, 0x2932e34c00000000, 0xbe94feab00000000, + 0x4679a95900000000, 0xd1dfb4be00000000, 0xf7a4776600000000, + 0x60026a8100000000, 0x98ef3d7300000000, 0x0f49209400000000, + 0xed4498b300000000, 0x7ae2855400000000, 0x820fd2a600000000, + 0x15a9cf4100000000, 0x33d20c9900000000, 0xa474117e00000000, + 0x5c99468c00000000, 0xcb3f5b6b00000000, 0x5169b1e600000000, + 0xc6cfac0100000000, 0x3e22fbf300000000, 0xa984e61400000000, + 0x8fff25cc00000000, 0x1859382b00000000, 0xe0b46fd900000000, + 0x7712723e00000000}, + {0x0000000000000000, 0x411b8c6e00000000, 0x823618dd00000000, + 0xc32d94b300000000, 0x456b416100000000, 0x0470cd0f00000000, + 0xc75d59bc00000000, 0x8646d5d200000000, 0x8ad682c200000000, + 0xcbcd0eac00000000, 0x08e09a1f00000000, 0x49fb167100000000, + 0xcfbdc3a300000000, 0x8ea64fcd00000000, 0x4d8bdb7e00000000, + 0x0c90571000000000, 0x55ab745e00000000, 0x14b0f83000000000, + 0xd79d6c8300000000, 0x9686e0ed00000000, 0x10c0353f00000000, + 0x51dbb95100000000, 0x92f62de200000000, 0xd3eda18c00000000, + 0xdf7df69c00000000, 0x9e667af200000000, 0x5d4bee4100000000, + 0x1c50622f00000000, 0x9a16b7fd00000000, 0xdb0d3b9300000000, + 0x1820af2000000000, 0x593b234e00000000, 0xaa56e9bc00000000, + 0xeb4d65d200000000, 0x2860f16100000000, 0x697b7d0f00000000, + 0xef3da8dd00000000, 0xae2624b300000000, 0x6d0bb00000000000, + 0x2c103c6e00000000, 0x20806b7e00000000, 0x619be71000000000, + 0xa2b673a300000000, 0xe3adffcd00000000, 0x65eb2a1f00000000, + 0x24f0a67100000000, 0xe7dd32c200000000, 0xa6c6beac00000000, + 0xfffd9de200000000, 0xbee6118c00000000, 0x7dcb853f00000000, + 0x3cd0095100000000, 0xba96dc8300000000, 0xfb8d50ed00000000, + 0x38a0c45e00000000, 0x79bb483000000000, 0x752b1f2000000000, + 0x3430934e00000000, 0xf71d07fd00000000, 0xb6068b9300000000, + 0x30405e4100000000, 0x715bd22f00000000, 0xb276469c00000000, + 0xf36dcaf200000000, 0x15aba3a200000000, 0x54b02fcc00000000, + 0x979dbb7f00000000, 0xd686371100000000, 0x50c0e2c300000000, + 0x11db6ead00000000, 0xd2f6fa1e00000000, 0x93ed767000000000, + 0x9f7d216000000000, 0xde66ad0e00000000, 0x1d4b39bd00000000, + 0x5c50b5d300000000, 0xda16600100000000, 0x9b0dec6f00000000, + 0x582078dc00000000, 0x193bf4b200000000, 0x4000d7fc00000000, + 0x011b5b9200000000, 0xc236cf2100000000, 0x832d434f00000000, + 0x056b969d00000000, 0x44701af300000000, 0x875d8e4000000000, + 0xc646022e00000000, 0xcad6553e00000000, 0x8bcdd95000000000, + 0x48e04de300000000, 0x09fbc18d00000000, 0x8fbd145f00000000, + 0xcea6983100000000, 0x0d8b0c8200000000, 0x4c9080ec00000000, + 0xbffd4a1e00000000, 0xfee6c67000000000, 0x3dcb52c300000000, + 0x7cd0dead00000000, 0xfa960b7f00000000, 0xbb8d871100000000, + 0x78a013a200000000, 0x39bb9fcc00000000, 0x352bc8dc00000000, + 0x743044b200000000, 0xb71dd00100000000, 0xf6065c6f00000000, + 0x704089bd00000000, 0x315b05d300000000, 0xf276916000000000, + 0xb36d1d0e00000000, 0xea563e4000000000, 0xab4db22e00000000, + 0x6860269d00000000, 0x297baaf300000000, 0xaf3d7f2100000000, + 0xee26f34f00000000, 0x2d0b67fc00000000, 0x6c10eb9200000000, + 0x6080bc8200000000, 0x219b30ec00000000, 0xe2b6a45f00000000, + 0xa3ad283100000000, 0x25ebfde300000000, 0x64f0718d00000000, + 0xa7dde53e00000000, 0xe6c6695000000000, 0x6b50369e00000000, + 0x2a4bbaf000000000, 0xe9662e4300000000, 0xa87da22d00000000, + 0x2e3b77ff00000000, 0x6f20fb9100000000, 0xac0d6f2200000000, + 0xed16e34c00000000, 0xe186b45c00000000, 0xa09d383200000000, + 0x63b0ac8100000000, 0x22ab20ef00000000, 0xa4edf53d00000000, + 0xe5f6795300000000, 0x26dbede000000000, 0x67c0618e00000000, + 0x3efb42c000000000, 0x7fe0ceae00000000, 0xbccd5a1d00000000, + 0xfdd6d67300000000, 0x7b9003a100000000, 0x3a8b8fcf00000000, + 0xf9a61b7c00000000, 0xb8bd971200000000, 0xb42dc00200000000, + 0xf5364c6c00000000, 0x361bd8df00000000, 0x770054b100000000, + 0xf146816300000000, 0xb05d0d0d00000000, 0x737099be00000000, + 0x326b15d000000000, 0xc106df2200000000, 0x801d534c00000000, + 0x4330c7ff00000000, 0x022b4b9100000000, 0x846d9e4300000000, + 0xc576122d00000000, 0x065b869e00000000, 0x47400af000000000, + 0x4bd05de000000000, 0x0acbd18e00000000, 0xc9e6453d00000000, + 0x88fdc95300000000, 0x0ebb1c8100000000, 0x4fa090ef00000000, + 0x8c8d045c00000000, 0xcd96883200000000, 0x94adab7c00000000, + 0xd5b6271200000000, 0x169bb3a100000000, 0x57803fcf00000000, + 0xd1c6ea1d00000000, 0x90dd667300000000, 0x53f0f2c000000000, + 0x12eb7eae00000000, 0x1e7b29be00000000, 0x5f60a5d000000000, + 0x9c4d316300000000, 0xdd56bd0d00000000, 0x5b1068df00000000, + 0x1a0be4b100000000, 0xd926700200000000, 0x983dfc6c00000000, + 0x7efb953c00000000, 0x3fe0195200000000, 0xfccd8de100000000, + 0xbdd6018f00000000, 0x3b90d45d00000000, 0x7a8b583300000000, + 0xb9a6cc8000000000, 0xf8bd40ee00000000, 0xf42d17fe00000000, + 0xb5369b9000000000, 0x761b0f2300000000, 0x3700834d00000000, + 0xb146569f00000000, 0xf05ddaf100000000, 0x33704e4200000000, + 0x726bc22c00000000, 0x2b50e16200000000, 0x6a4b6d0c00000000, + 0xa966f9bf00000000, 0xe87d75d100000000, 0x6e3ba00300000000, + 0x2f202c6d00000000, 0xec0db8de00000000, 0xad1634b000000000, + 0xa18663a000000000, 0xe09defce00000000, 0x23b07b7d00000000, + 0x62abf71300000000, 0xe4ed22c100000000, 0xa5f6aeaf00000000, + 0x66db3a1c00000000, 0x27c0b67200000000, 0xd4ad7c8000000000, + 0x95b6f0ee00000000, 0x569b645d00000000, 0x1780e83300000000, + 0x91c63de100000000, 0xd0ddb18f00000000, 0x13f0253c00000000, + 0x52eba95200000000, 0x5e7bfe4200000000, 0x1f60722c00000000, + 0xdc4de69f00000000, 0x9d566af100000000, 0x1b10bf2300000000, + 0x5a0b334d00000000, 0x9926a7fe00000000, 0xd83d2b9000000000, + 0x810608de00000000, 0xc01d84b000000000, 0x0330100300000000, + 0x422b9c6d00000000, 0xc46d49bf00000000, 0x8576c5d100000000, + 0x465b516200000000, 0x0740dd0c00000000, 0x0bd08a1c00000000, + 0x4acb067200000000, 0x89e692c100000000, 0xc8fd1eaf00000000, + 0x4ebbcb7d00000000, 0x0fa0471300000000, 0xcc8dd3a000000000, + 0x8d965fce00000000}, + {0x0000000000000000, 0x1dfdb50100000000, 0x3afa6b0300000000, + 0x2707de0200000000, 0x74f4d70600000000, 0x6909620700000000, + 0x4e0ebc0500000000, 0x53f3090400000000, 0xe8e8af0d00000000, + 0xf5151a0c00000000, 0xd212c40e00000000, 0xcfef710f00000000, + 0x9c1c780b00000000, 0x81e1cd0a00000000, 0xa6e6130800000000, + 0xbb1ba60900000000, 0xd0d15f1b00000000, 0xcd2cea1a00000000, + 0xea2b341800000000, 0xf7d6811900000000, 0xa425881d00000000, + 0xb9d83d1c00000000, 0x9edfe31e00000000, 0x8322561f00000000, + 0x3839f01600000000, 0x25c4451700000000, 0x02c39b1500000000, + 0x1f3e2e1400000000, 0x4ccd271000000000, 0x5130921100000000, + 0x76374c1300000000, 0x6bcaf91200000000, 0xa0a3bf3600000000, + 0xbd5e0a3700000000, 0x9a59d43500000000, 0x87a4613400000000, + 0xd457683000000000, 0xc9aadd3100000000, 0xeead033300000000, + 0xf350b63200000000, 0x484b103b00000000, 0x55b6a53a00000000, + 0x72b17b3800000000, 0x6f4cce3900000000, 0x3cbfc73d00000000, + 0x2142723c00000000, 0x0645ac3e00000000, 0x1bb8193f00000000, + 0x7072e02d00000000, 0x6d8f552c00000000, 0x4a888b2e00000000, + 0x57753e2f00000000, 0x0486372b00000000, 0x197b822a00000000, + 0x3e7c5c2800000000, 0x2381e92900000000, 0x989a4f2000000000, + 0x8567fa2100000000, 0xa260242300000000, 0xbf9d912200000000, + 0xec6e982600000000, 0xf1932d2700000000, 0xd694f32500000000, + 0xcb69462400000000, 0x40477f6d00000000, 0x5dbaca6c00000000, + 0x7abd146e00000000, 0x6740a16f00000000, 0x34b3a86b00000000, + 0x294e1d6a00000000, 0x0e49c36800000000, 0x13b4766900000000, + 0xa8afd06000000000, 0xb552656100000000, 0x9255bb6300000000, + 0x8fa80e6200000000, 0xdc5b076600000000, 0xc1a6b26700000000, + 0xe6a16c6500000000, 0xfb5cd96400000000, 0x9096207600000000, + 0x8d6b957700000000, 0xaa6c4b7500000000, 0xb791fe7400000000, + 0xe462f77000000000, 0xf99f427100000000, 0xde989c7300000000, + 0xc365297200000000, 0x787e8f7b00000000, 0x65833a7a00000000, + 0x4284e47800000000, 0x5f79517900000000, 0x0c8a587d00000000, + 0x1177ed7c00000000, 0x3670337e00000000, 0x2b8d867f00000000, + 0xe0e4c05b00000000, 0xfd19755a00000000, 0xda1eab5800000000, + 0xc7e31e5900000000, 0x9410175d00000000, 0x89eda25c00000000, + 0xaeea7c5e00000000, 0xb317c95f00000000, 0x080c6f5600000000, + 0x15f1da5700000000, 0x32f6045500000000, 0x2f0bb15400000000, + 0x7cf8b85000000000, 0x61050d5100000000, 0x4602d35300000000, + 0x5bff665200000000, 0x30359f4000000000, 0x2dc82a4100000000, + 0x0acff44300000000, 0x1732414200000000, 0x44c1484600000000, + 0x593cfd4700000000, 0x7e3b234500000000, 0x63c6964400000000, + 0xd8dd304d00000000, 0xc520854c00000000, 0xe2275b4e00000000, + 0xffdaee4f00000000, 0xac29e74b00000000, 0xb1d4524a00000000, + 0x96d38c4800000000, 0x8b2e394900000000, 0x808efeda00000000, + 0x9d734bdb00000000, 0xba7495d900000000, 0xa78920d800000000, + 0xf47a29dc00000000, 0xe9879cdd00000000, 0xce8042df00000000, + 0xd37df7de00000000, 0x686651d700000000, 0x759be4d600000000, + 0x529c3ad400000000, 0x4f618fd500000000, 0x1c9286d100000000, + 0x016f33d000000000, 0x2668edd200000000, 0x3b9558d300000000, + 0x505fa1c100000000, 0x4da214c000000000, 0x6aa5cac200000000, + 0x77587fc300000000, 0x24ab76c700000000, 0x3956c3c600000000, + 0x1e511dc400000000, 0x03aca8c500000000, 0xb8b70ecc00000000, + 0xa54abbcd00000000, 0x824d65cf00000000, 0x9fb0d0ce00000000, + 0xcc43d9ca00000000, 0xd1be6ccb00000000, 0xf6b9b2c900000000, + 0xeb4407c800000000, 0x202d41ec00000000, 0x3dd0f4ed00000000, + 0x1ad72aef00000000, 0x072a9fee00000000, 0x54d996ea00000000, + 0x492423eb00000000, 0x6e23fde900000000, 0x73de48e800000000, + 0xc8c5eee100000000, 0xd5385be000000000, 0xf23f85e200000000, + 0xefc230e300000000, 0xbc3139e700000000, 0xa1cc8ce600000000, + 0x86cb52e400000000, 0x9b36e7e500000000, 0xf0fc1ef700000000, + 0xed01abf600000000, 0xca0675f400000000, 0xd7fbc0f500000000, + 0x8408c9f100000000, 0x99f57cf000000000, 0xbef2a2f200000000, + 0xa30f17f300000000, 0x1814b1fa00000000, 0x05e904fb00000000, + 0x22eedaf900000000, 0x3f136ff800000000, 0x6ce066fc00000000, + 0x711dd3fd00000000, 0x561a0dff00000000, 0x4be7b8fe00000000, + 0xc0c981b700000000, 0xdd3434b600000000, 0xfa33eab400000000, + 0xe7ce5fb500000000, 0xb43d56b100000000, 0xa9c0e3b000000000, + 0x8ec73db200000000, 0x933a88b300000000, 0x28212eba00000000, + 0x35dc9bbb00000000, 0x12db45b900000000, 0x0f26f0b800000000, + 0x5cd5f9bc00000000, 0x41284cbd00000000, 0x662f92bf00000000, + 0x7bd227be00000000, 0x1018deac00000000, 0x0de56bad00000000, + 0x2ae2b5af00000000, 0x371f00ae00000000, 0x64ec09aa00000000, + 0x7911bcab00000000, 0x5e1662a900000000, 0x43ebd7a800000000, + 0xf8f071a100000000, 0xe50dc4a000000000, 0xc20a1aa200000000, + 0xdff7afa300000000, 0x8c04a6a700000000, 0x91f913a600000000, + 0xb6fecda400000000, 0xab0378a500000000, 0x606a3e8100000000, + 0x7d978b8000000000, 0x5a90558200000000, 0x476de08300000000, + 0x149ee98700000000, 0x09635c8600000000, 0x2e64828400000000, + 0x3399378500000000, 0x8882918c00000000, 0x957f248d00000000, + 0xb278fa8f00000000, 0xaf854f8e00000000, 0xfc76468a00000000, + 0xe18bf38b00000000, 0xc68c2d8900000000, 0xdb71988800000000, + 0xb0bb619a00000000, 0xad46d49b00000000, 0x8a410a9900000000, + 0x97bcbf9800000000, 0xc44fb69c00000000, 0xd9b2039d00000000, + 0xfeb5dd9f00000000, 0xe348689e00000000, 0x5853ce9700000000, + 0x45ae7b9600000000, 0x62a9a59400000000, 0x7f54109500000000, + 0x2ca7199100000000, 0x315aac9000000000, 0x165d729200000000, + 0x0ba0c79300000000}, + {0x0000000000000000, 0x24d9076300000000, 0x48b20fc600000000, + 0x6c6b08a500000000, 0xd1626e5700000000, 0xf5bb693400000000, + 0x99d0619100000000, 0xbd0966f200000000, 0xa2c5dcae00000000, + 0x861cdbcd00000000, 0xea77d36800000000, 0xceaed40b00000000, + 0x73a7b2f900000000, 0x577eb59a00000000, 0x3b15bd3f00000000, + 0x1fccba5c00000000, 0x058dc88600000000, 0x2154cfe500000000, + 0x4d3fc74000000000, 0x69e6c02300000000, 0xd4efa6d100000000, + 0xf036a1b200000000, 0x9c5da91700000000, 0xb884ae7400000000, + 0xa748142800000000, 0x8391134b00000000, 0xeffa1bee00000000, + 0xcb231c8d00000000, 0x762a7a7f00000000, 0x52f37d1c00000000, + 0x3e9875b900000000, 0x1a4172da00000000, 0x4b1ce0d600000000, + 0x6fc5e7b500000000, 0x03aeef1000000000, 0x2777e87300000000, + 0x9a7e8e8100000000, 0xbea789e200000000, 0xd2cc814700000000, + 0xf615862400000000, 0xe9d93c7800000000, 0xcd003b1b00000000, + 0xa16b33be00000000, 0x85b234dd00000000, 0x38bb522f00000000, + 0x1c62554c00000000, 0x70095de900000000, 0x54d05a8a00000000, + 0x4e91285000000000, 0x6a482f3300000000, 0x0623279600000000, + 0x22fa20f500000000, 0x9ff3460700000000, 0xbb2a416400000000, + 0xd74149c100000000, 0xf3984ea200000000, 0xec54f4fe00000000, + 0xc88df39d00000000, 0xa4e6fb3800000000, 0x803ffc5b00000000, + 0x3d369aa900000000, 0x19ef9dca00000000, 0x7584956f00000000, + 0x515d920c00000000, 0xd73eb17600000000, 0xf3e7b61500000000, + 0x9f8cbeb000000000, 0xbb55b9d300000000, 0x065cdf2100000000, + 0x2285d84200000000, 0x4eeed0e700000000, 0x6a37d78400000000, + 0x75fb6dd800000000, 0x51226abb00000000, 0x3d49621e00000000, + 0x1990657d00000000, 0xa499038f00000000, 0x804004ec00000000, + 0xec2b0c4900000000, 0xc8f20b2a00000000, 0xd2b379f000000000, + 0xf66a7e9300000000, 0x9a01763600000000, 0xbed8715500000000, + 0x03d117a700000000, 0x270810c400000000, 0x4b63186100000000, + 0x6fba1f0200000000, 0x7076a55e00000000, 0x54afa23d00000000, + 0x38c4aa9800000000, 0x1c1dadfb00000000, 0xa114cb0900000000, + 0x85cdcc6a00000000, 0xe9a6c4cf00000000, 0xcd7fc3ac00000000, + 0x9c2251a000000000, 0xb8fb56c300000000, 0xd4905e6600000000, + 0xf049590500000000, 0x4d403ff700000000, 0x6999389400000000, + 0x05f2303100000000, 0x212b375200000000, 0x3ee78d0e00000000, + 0x1a3e8a6d00000000, 0x765582c800000000, 0x528c85ab00000000, + 0xef85e35900000000, 0xcb5ce43a00000000, 0xa737ec9f00000000, + 0x83eeebfc00000000, 0x99af992600000000, 0xbd769e4500000000, + 0xd11d96e000000000, 0xf5c4918300000000, 0x48cdf77100000000, + 0x6c14f01200000000, 0x007ff8b700000000, 0x24a6ffd400000000, + 0x3b6a458800000000, 0x1fb342eb00000000, 0x73d84a4e00000000, + 0x57014d2d00000000, 0xea082bdf00000000, 0xced12cbc00000000, + 0xa2ba241900000000, 0x8663237a00000000, 0xae7d62ed00000000, + 0x8aa4658e00000000, 0xe6cf6d2b00000000, 0xc2166a4800000000, + 0x7f1f0cba00000000, 0x5bc60bd900000000, 0x37ad037c00000000, + 0x1374041f00000000, 0x0cb8be4300000000, 0x2861b92000000000, + 0x440ab18500000000, 0x60d3b6e600000000, 0xdddad01400000000, + 0xf903d77700000000, 0x9568dfd200000000, 0xb1b1d8b100000000, + 0xabf0aa6b00000000, 0x8f29ad0800000000, 0xe342a5ad00000000, + 0xc79ba2ce00000000, 0x7a92c43c00000000, 0x5e4bc35f00000000, + 0x3220cbfa00000000, 0x16f9cc9900000000, 0x093576c500000000, + 0x2dec71a600000000, 0x4187790300000000, 0x655e7e6000000000, + 0xd857189200000000, 0xfc8e1ff100000000, 0x90e5175400000000, + 0xb43c103700000000, 0xe561823b00000000, 0xc1b8855800000000, + 0xadd38dfd00000000, 0x890a8a9e00000000, 0x3403ec6c00000000, + 0x10daeb0f00000000, 0x7cb1e3aa00000000, 0x5868e4c900000000, + 0x47a45e9500000000, 0x637d59f600000000, 0x0f16515300000000, + 0x2bcf563000000000, 0x96c630c200000000, 0xb21f37a100000000, + 0xde743f0400000000, 0xfaad386700000000, 0xe0ec4abd00000000, + 0xc4354dde00000000, 0xa85e457b00000000, 0x8c87421800000000, + 0x318e24ea00000000, 0x1557238900000000, 0x793c2b2c00000000, + 0x5de52c4f00000000, 0x4229961300000000, 0x66f0917000000000, + 0x0a9b99d500000000, 0x2e429eb600000000, 0x934bf84400000000, + 0xb792ff2700000000, 0xdbf9f78200000000, 0xff20f0e100000000, + 0x7943d39b00000000, 0x5d9ad4f800000000, 0x31f1dc5d00000000, + 0x1528db3e00000000, 0xa821bdcc00000000, 0x8cf8baaf00000000, + 0xe093b20a00000000, 0xc44ab56900000000, 0xdb860f3500000000, + 0xff5f085600000000, 0x933400f300000000, 0xb7ed079000000000, + 0x0ae4616200000000, 0x2e3d660100000000, 0x42566ea400000000, + 0x668f69c700000000, 0x7cce1b1d00000000, 0x58171c7e00000000, + 0x347c14db00000000, 0x10a513b800000000, 0xadac754a00000000, + 0x8975722900000000, 0xe51e7a8c00000000, 0xc1c77def00000000, + 0xde0bc7b300000000, 0xfad2c0d000000000, 0x96b9c87500000000, + 0xb260cf1600000000, 0x0f69a9e400000000, 0x2bb0ae8700000000, + 0x47dba62200000000, 0x6302a14100000000, 0x325f334d00000000, + 0x1686342e00000000, 0x7aed3c8b00000000, 0x5e343be800000000, + 0xe33d5d1a00000000, 0xc7e45a7900000000, 0xab8f52dc00000000, + 0x8f5655bf00000000, 0x909aefe300000000, 0xb443e88000000000, + 0xd828e02500000000, 0xfcf1e74600000000, 0x41f881b400000000, + 0x652186d700000000, 0x094a8e7200000000, 0x2d93891100000000, + 0x37d2fbcb00000000, 0x130bfca800000000, 0x7f60f40d00000000, + 0x5bb9f36e00000000, 0xe6b0959c00000000, 0xc26992ff00000000, + 0xae029a5a00000000, 0x8adb9d3900000000, 0x9517276500000000, + 0xb1ce200600000000, 0xdda528a300000000, 0xf97c2fc000000000, + 0x4475493200000000, 0x60ac4e5100000000, 0x0cc746f400000000, + 0x281e419700000000}, + {0x0000000000000000, 0x08e3603c00000000, 0x10c6c17800000000, + 0x1825a14400000000, 0x208c83f100000000, 0x286fe3cd00000000, + 0x304a428900000000, 0x38a922b500000000, 0x011e763800000000, + 0x09fd160400000000, 0x11d8b74000000000, 0x193bd77c00000000, + 0x2192f5c900000000, 0x297195f500000000, 0x315434b100000000, + 0x39b7548d00000000, 0x023cec7000000000, 0x0adf8c4c00000000, + 0x12fa2d0800000000, 0x1a194d3400000000, 0x22b06f8100000000, + 0x2a530fbd00000000, 0x3276aef900000000, 0x3a95cec500000000, + 0x03229a4800000000, 0x0bc1fa7400000000, 0x13e45b3000000000, + 0x1b073b0c00000000, 0x23ae19b900000000, 0x2b4d798500000000, + 0x3368d8c100000000, 0x3b8bb8fd00000000, 0x0478d8e100000000, + 0x0c9bb8dd00000000, 0x14be199900000000, 0x1c5d79a500000000, + 0x24f45b1000000000, 0x2c173b2c00000000, 0x34329a6800000000, + 0x3cd1fa5400000000, 0x0566aed900000000, 0x0d85cee500000000, + 0x15a06fa100000000, 0x1d430f9d00000000, 0x25ea2d2800000000, + 0x2d094d1400000000, 0x352cec5000000000, 0x3dcf8c6c00000000, + 0x0644349100000000, 0x0ea754ad00000000, 0x1682f5e900000000, + 0x1e6195d500000000, 0x26c8b76000000000, 0x2e2bd75c00000000, + 0x360e761800000000, 0x3eed162400000000, 0x075a42a900000000, + 0x0fb9229500000000, 0x179c83d100000000, 0x1f7fe3ed00000000, + 0x27d6c15800000000, 0x2f35a16400000000, 0x3710002000000000, + 0x3ff3601c00000000, 0x49f6c11800000000, 0x4115a12400000000, + 0x5930006000000000, 0x51d3605c00000000, 0x697a42e900000000, + 0x619922d500000000, 0x79bc839100000000, 0x715fe3ad00000000, + 0x48e8b72000000000, 0x400bd71c00000000, 0x582e765800000000, + 0x50cd166400000000, 0x686434d100000000, 0x608754ed00000000, + 0x78a2f5a900000000, 0x7041959500000000, 0x4bca2d6800000000, + 0x43294d5400000000, 0x5b0cec1000000000, 0x53ef8c2c00000000, + 0x6b46ae9900000000, 0x63a5cea500000000, 0x7b806fe100000000, + 0x73630fdd00000000, 0x4ad45b5000000000, 0x42373b6c00000000, + 0x5a129a2800000000, 0x52f1fa1400000000, 0x6a58d8a100000000, + 0x62bbb89d00000000, 0x7a9e19d900000000, 0x727d79e500000000, + 0x4d8e19f900000000, 0x456d79c500000000, 0x5d48d88100000000, + 0x55abb8bd00000000, 0x6d029a0800000000, 0x65e1fa3400000000, + 0x7dc45b7000000000, 0x75273b4c00000000, 0x4c906fc100000000, + 0x44730ffd00000000, 0x5c56aeb900000000, 0x54b5ce8500000000, + 0x6c1cec3000000000, 0x64ff8c0c00000000, 0x7cda2d4800000000, + 0x74394d7400000000, 0x4fb2f58900000000, 0x475195b500000000, + 0x5f7434f100000000, 0x579754cd00000000, 0x6f3e767800000000, + 0x67dd164400000000, 0x7ff8b70000000000, 0x771bd73c00000000, + 0x4eac83b100000000, 0x464fe38d00000000, 0x5e6a42c900000000, + 0x568922f500000000, 0x6e20004000000000, 0x66c3607c00000000, + 0x7ee6c13800000000, 0x7605a10400000000, 0x92ec833100000000, + 0x9a0fe30d00000000, 0x822a424900000000, 0x8ac9227500000000, + 0xb26000c000000000, 0xba8360fc00000000, 0xa2a6c1b800000000, + 0xaa45a18400000000, 0x93f2f50900000000, 0x9b11953500000000, + 0x8334347100000000, 0x8bd7544d00000000, 0xb37e76f800000000, + 0xbb9d16c400000000, 0xa3b8b78000000000, 0xab5bd7bc00000000, + 0x90d06f4100000000, 0x98330f7d00000000, 0x8016ae3900000000, + 0x88f5ce0500000000, 0xb05cecb000000000, 0xb8bf8c8c00000000, + 0xa09a2dc800000000, 0xa8794df400000000, 0x91ce197900000000, + 0x992d794500000000, 0x8108d80100000000, 0x89ebb83d00000000, + 0xb1429a8800000000, 0xb9a1fab400000000, 0xa1845bf000000000, + 0xa9673bcc00000000, 0x96945bd000000000, 0x9e773bec00000000, + 0x86529aa800000000, 0x8eb1fa9400000000, 0xb618d82100000000, + 0xbefbb81d00000000, 0xa6de195900000000, 0xae3d796500000000, + 0x978a2de800000000, 0x9f694dd400000000, 0x874cec9000000000, + 0x8faf8cac00000000, 0xb706ae1900000000, 0xbfe5ce2500000000, + 0xa7c06f6100000000, 0xaf230f5d00000000, 0x94a8b7a000000000, + 0x9c4bd79c00000000, 0x846e76d800000000, 0x8c8d16e400000000, + 0xb424345100000000, 0xbcc7546d00000000, 0xa4e2f52900000000, + 0xac01951500000000, 0x95b6c19800000000, 0x9d55a1a400000000, + 0x857000e000000000, 0x8d9360dc00000000, 0xb53a426900000000, + 0xbdd9225500000000, 0xa5fc831100000000, 0xad1fe32d00000000, + 0xdb1a422900000000, 0xd3f9221500000000, 0xcbdc835100000000, + 0xc33fe36d00000000, 0xfb96c1d800000000, 0xf375a1e400000000, + 0xeb5000a000000000, 0xe3b3609c00000000, 0xda04341100000000, + 0xd2e7542d00000000, 0xcac2f56900000000, 0xc221955500000000, + 0xfa88b7e000000000, 0xf26bd7dc00000000, 0xea4e769800000000, + 0xe2ad16a400000000, 0xd926ae5900000000, 0xd1c5ce6500000000, + 0xc9e06f2100000000, 0xc1030f1d00000000, 0xf9aa2da800000000, + 0xf1494d9400000000, 0xe96cecd000000000, 0xe18f8cec00000000, + 0xd838d86100000000, 0xd0dbb85d00000000, 0xc8fe191900000000, + 0xc01d792500000000, 0xf8b45b9000000000, 0xf0573bac00000000, + 0xe8729ae800000000, 0xe091fad400000000, 0xdf629ac800000000, + 0xd781faf400000000, 0xcfa45bb000000000, 0xc7473b8c00000000, + 0xffee193900000000, 0xf70d790500000000, 0xef28d84100000000, + 0xe7cbb87d00000000, 0xde7cecf000000000, 0xd69f8ccc00000000, + 0xceba2d8800000000, 0xc6594db400000000, 0xfef06f0100000000, + 0xf6130f3d00000000, 0xee36ae7900000000, 0xe6d5ce4500000000, + 0xdd5e76b800000000, 0xd5bd168400000000, 0xcd98b7c000000000, + 0xc57bd7fc00000000, 0xfdd2f54900000000, 0xf531957500000000, + 0xed14343100000000, 0xe5f7540d00000000, 0xdc40008000000000, + 0xd4a360bc00000000, 0xcc86c1f800000000, 0xc465a1c400000000, + 0xfccc837100000000, 0xf42fe34d00000000, 0xec0a420900000000, + 0xe4e9223500000000}, + {0x0000000000000000, 0xd1e8e70e00000000, 0xa2d1cf1d00000000, + 0x7339281300000000, 0x44a39f3b00000000, 0x954b783500000000, + 0xe672502600000000, 0x379ab72800000000, 0x88463f7700000000, + 0x59aed87900000000, 0x2a97f06a00000000, 0xfb7f176400000000, + 0xcce5a04c00000000, 0x1d0d474200000000, 0x6e346f5100000000, + 0xbfdc885f00000000, 0x108d7eee00000000, 0xc16599e000000000, + 0xb25cb1f300000000, 0x63b456fd00000000, 0x542ee1d500000000, + 0x85c606db00000000, 0xf6ff2ec800000000, 0x2717c9c600000000, + 0x98cb419900000000, 0x4923a69700000000, 0x3a1a8e8400000000, + 0xebf2698a00000000, 0xdc68dea200000000, 0x0d8039ac00000000, + 0x7eb911bf00000000, 0xaf51f6b100000000, 0x611c8c0700000000, + 0xb0f46b0900000000, 0xc3cd431a00000000, 0x1225a41400000000, + 0x25bf133c00000000, 0xf457f43200000000, 0x876edc2100000000, + 0x56863b2f00000000, 0xe95ab37000000000, 0x38b2547e00000000, + 0x4b8b7c6d00000000, 0x9a639b6300000000, 0xadf92c4b00000000, + 0x7c11cb4500000000, 0x0f28e35600000000, 0xdec0045800000000, + 0x7191f2e900000000, 0xa07915e700000000, 0xd3403df400000000, + 0x02a8dafa00000000, 0x35326dd200000000, 0xe4da8adc00000000, + 0x97e3a2cf00000000, 0x460b45c100000000, 0xf9d7cd9e00000000, + 0x283f2a9000000000, 0x5b06028300000000, 0x8aeee58d00000000, + 0xbd7452a500000000, 0x6c9cb5ab00000000, 0x1fa59db800000000, + 0xce4d7ab600000000, 0xc238180f00000000, 0x13d0ff0100000000, + 0x60e9d71200000000, 0xb101301c00000000, 0x869b873400000000, + 0x5773603a00000000, 0x244a482900000000, 0xf5a2af2700000000, + 0x4a7e277800000000, 0x9b96c07600000000, 0xe8afe86500000000, + 0x39470f6b00000000, 0x0eddb84300000000, 0xdf355f4d00000000, + 0xac0c775e00000000, 0x7de4905000000000, 0xd2b566e100000000, + 0x035d81ef00000000, 0x7064a9fc00000000, 0xa18c4ef200000000, + 0x9616f9da00000000, 0x47fe1ed400000000, 0x34c736c700000000, + 0xe52fd1c900000000, 0x5af3599600000000, 0x8b1bbe9800000000, + 0xf822968b00000000, 0x29ca718500000000, 0x1e50c6ad00000000, + 0xcfb821a300000000, 0xbc8109b000000000, 0x6d69eebe00000000, + 0xa324940800000000, 0x72cc730600000000, 0x01f55b1500000000, + 0xd01dbc1b00000000, 0xe7870b3300000000, 0x366fec3d00000000, + 0x4556c42e00000000, 0x94be232000000000, 0x2b62ab7f00000000, + 0xfa8a4c7100000000, 0x89b3646200000000, 0x585b836c00000000, + 0x6fc1344400000000, 0xbe29d34a00000000, 0xcd10fb5900000000, + 0x1cf81c5700000000, 0xb3a9eae600000000, 0x62410de800000000, + 0x117825fb00000000, 0xc090c2f500000000, 0xf70a75dd00000000, + 0x26e292d300000000, 0x55dbbac000000000, 0x84335dce00000000, + 0x3befd59100000000, 0xea07329f00000000, 0x993e1a8c00000000, + 0x48d6fd8200000000, 0x7f4c4aaa00000000, 0xaea4ada400000000, + 0xdd9d85b700000000, 0x0c7562b900000000, 0x8471301e00000000, + 0x5599d71000000000, 0x26a0ff0300000000, 0xf748180d00000000, + 0xc0d2af2500000000, 0x113a482b00000000, 0x6203603800000000, + 0xb3eb873600000000, 0x0c370f6900000000, 0xdddfe86700000000, + 0xaee6c07400000000, 0x7f0e277a00000000, 0x4894905200000000, + 0x997c775c00000000, 0xea455f4f00000000, 0x3badb84100000000, + 0x94fc4ef000000000, 0x4514a9fe00000000, 0x362d81ed00000000, + 0xe7c566e300000000, 0xd05fd1cb00000000, 0x01b736c500000000, + 0x728e1ed600000000, 0xa366f9d800000000, 0x1cba718700000000, + 0xcd52968900000000, 0xbe6bbe9a00000000, 0x6f83599400000000, + 0x5819eebc00000000, 0x89f109b200000000, 0xfac821a100000000, + 0x2b20c6af00000000, 0xe56dbc1900000000, 0x34855b1700000000, + 0x47bc730400000000, 0x9654940a00000000, 0xa1ce232200000000, + 0x7026c42c00000000, 0x031fec3f00000000, 0xd2f70b3100000000, + 0x6d2b836e00000000, 0xbcc3646000000000, 0xcffa4c7300000000, + 0x1e12ab7d00000000, 0x29881c5500000000, 0xf860fb5b00000000, + 0x8b59d34800000000, 0x5ab1344600000000, 0xf5e0c2f700000000, + 0x240825f900000000, 0x57310dea00000000, 0x86d9eae400000000, + 0xb1435dcc00000000, 0x60abbac200000000, 0x139292d100000000, + 0xc27a75df00000000, 0x7da6fd8000000000, 0xac4e1a8e00000000, + 0xdf77329d00000000, 0x0e9fd59300000000, 0x390562bb00000000, + 0xe8ed85b500000000, 0x9bd4ada600000000, 0x4a3c4aa800000000, + 0x4649281100000000, 0x97a1cf1f00000000, 0xe498e70c00000000, + 0x3570000200000000, 0x02eab72a00000000, 0xd302502400000000, + 0xa03b783700000000, 0x71d39f3900000000, 0xce0f176600000000, + 0x1fe7f06800000000, 0x6cded87b00000000, 0xbd363f7500000000, + 0x8aac885d00000000, 0x5b446f5300000000, 0x287d474000000000, + 0xf995a04e00000000, 0x56c456ff00000000, 0x872cb1f100000000, + 0xf41599e200000000, 0x25fd7eec00000000, 0x1267c9c400000000, + 0xc38f2eca00000000, 0xb0b606d900000000, 0x615ee1d700000000, + 0xde82698800000000, 0x0f6a8e8600000000, 0x7c53a69500000000, + 0xadbb419b00000000, 0x9a21f6b300000000, 0x4bc911bd00000000, + 0x38f039ae00000000, 0xe918dea000000000, 0x2755a41600000000, + 0xf6bd431800000000, 0x85846b0b00000000, 0x546c8c0500000000, + 0x63f63b2d00000000, 0xb21edc2300000000, 0xc127f43000000000, + 0x10cf133e00000000, 0xaf139b6100000000, 0x7efb7c6f00000000, + 0x0dc2547c00000000, 0xdc2ab37200000000, 0xebb0045a00000000, + 0x3a58e35400000000, 0x4961cb4700000000, 0x98892c4900000000, + 0x37d8daf800000000, 0xe6303df600000000, 0x950915e500000000, + 0x44e1f2eb00000000, 0x737b45c300000000, 0xa293a2cd00000000, + 0xd1aa8ade00000000, 0x00426dd000000000, 0xbf9ee58f00000000, + 0x6e76028100000000, 0x1d4f2a9200000000, 0xcca7cd9c00000000, + 0xfb3d7ab400000000, 0x2ad59dba00000000, 0x59ecb5a900000000, + 0x880452a700000000}, + {0x0000000000000000, 0xaa05daf100000000, 0x150dc53800000000, + 0xbf081fc900000000, 0x2a1a8a7100000000, 0x801f508000000000, + 0x3f174f4900000000, 0x951295b800000000, 0x543414e300000000, + 0xfe31ce1200000000, 0x4139d1db00000000, 0xeb3c0b2a00000000, + 0x7e2e9e9200000000, 0xd42b446300000000, 0x6b235baa00000000, + 0xc126815b00000000, 0xe96e591d00000000, 0x436b83ec00000000, + 0xfc639c2500000000, 0x566646d400000000, 0xc374d36c00000000, + 0x6971099d00000000, 0xd679165400000000, 0x7c7ccca500000000, + 0xbd5a4dfe00000000, 0x175f970f00000000, 0xa85788c600000000, + 0x0252523700000000, 0x9740c78f00000000, 0x3d451d7e00000000, + 0x824d02b700000000, 0x2848d84600000000, 0xd2ddb23a00000000, + 0x78d868cb00000000, 0xc7d0770200000000, 0x6dd5adf300000000, + 0xf8c7384b00000000, 0x52c2e2ba00000000, 0xedcafd7300000000, + 0x47cf278200000000, 0x86e9a6d900000000, 0x2cec7c2800000000, + 0x93e463e100000000, 0x39e1b91000000000, 0xacf32ca800000000, + 0x06f6f65900000000, 0xb9fee99000000000, 0x13fb336100000000, + 0x3bb3eb2700000000, 0x91b631d600000000, 0x2ebe2e1f00000000, + 0x84bbf4ee00000000, 0x11a9615600000000, 0xbbacbba700000000, + 0x04a4a46e00000000, 0xaea17e9f00000000, 0x6f87ffc400000000, + 0xc582253500000000, 0x7a8a3afc00000000, 0xd08fe00d00000000, + 0x459d75b500000000, 0xef98af4400000000, 0x5090b08d00000000, + 0xfa956a7c00000000, 0xa4bb657500000000, 0x0ebebf8400000000, + 0xb1b6a04d00000000, 0x1bb37abc00000000, 0x8ea1ef0400000000, + 0x24a435f500000000, 0x9bac2a3c00000000, 0x31a9f0cd00000000, + 0xf08f719600000000, 0x5a8aab6700000000, 0xe582b4ae00000000, + 0x4f876e5f00000000, 0xda95fbe700000000, 0x7090211600000000, + 0xcf983edf00000000, 0x659de42e00000000, 0x4dd53c6800000000, + 0xe7d0e69900000000, 0x58d8f95000000000, 0xf2dd23a100000000, + 0x67cfb61900000000, 0xcdca6ce800000000, 0x72c2732100000000, + 0xd8c7a9d000000000, 0x19e1288b00000000, 0xb3e4f27a00000000, + 0x0cecedb300000000, 0xa6e9374200000000, 0x33fba2fa00000000, + 0x99fe780b00000000, 0x26f667c200000000, 0x8cf3bd3300000000, + 0x7666d74f00000000, 0xdc630dbe00000000, 0x636b127700000000, + 0xc96ec88600000000, 0x5c7c5d3e00000000, 0xf67987cf00000000, + 0x4971980600000000, 0xe37442f700000000, 0x2252c3ac00000000, + 0x8857195d00000000, 0x375f069400000000, 0x9d5adc6500000000, + 0x084849dd00000000, 0xa24d932c00000000, 0x1d458ce500000000, + 0xb740561400000000, 0x9f088e5200000000, 0x350d54a300000000, + 0x8a054b6a00000000, 0x2000919b00000000, 0xb512042300000000, + 0x1f17ded200000000, 0xa01fc11b00000000, 0x0a1a1bea00000000, + 0xcb3c9ab100000000, 0x6139404000000000, 0xde315f8900000000, + 0x7434857800000000, 0xe12610c000000000, 0x4b23ca3100000000, + 0xf42bd5f800000000, 0x5e2e0f0900000000, 0x4877cbea00000000, + 0xe272111b00000000, 0x5d7a0ed200000000, 0xf77fd42300000000, + 0x626d419b00000000, 0xc8689b6a00000000, 0x776084a300000000, + 0xdd655e5200000000, 0x1c43df0900000000, 0xb64605f800000000, + 0x094e1a3100000000, 0xa34bc0c000000000, 0x3659557800000000, + 0x9c5c8f8900000000, 0x2354904000000000, 0x89514ab100000000, + 0xa11992f700000000, 0x0b1c480600000000, 0xb41457cf00000000, + 0x1e118d3e00000000, 0x8b03188600000000, 0x2106c27700000000, + 0x9e0eddbe00000000, 0x340b074f00000000, 0xf52d861400000000, + 0x5f285ce500000000, 0xe020432c00000000, 0x4a2599dd00000000, + 0xdf370c6500000000, 0x7532d69400000000, 0xca3ac95d00000000, + 0x603f13ac00000000, 0x9aaa79d000000000, 0x30afa32100000000, + 0x8fa7bce800000000, 0x25a2661900000000, 0xb0b0f3a100000000, + 0x1ab5295000000000, 0xa5bd369900000000, 0x0fb8ec6800000000, + 0xce9e6d3300000000, 0x649bb7c200000000, 0xdb93a80b00000000, + 0x719672fa00000000, 0xe484e74200000000, 0x4e813db300000000, + 0xf189227a00000000, 0x5b8cf88b00000000, 0x73c420cd00000000, + 0xd9c1fa3c00000000, 0x66c9e5f500000000, 0xcccc3f0400000000, + 0x59deaabc00000000, 0xf3db704d00000000, 0x4cd36f8400000000, + 0xe6d6b57500000000, 0x27f0342e00000000, 0x8df5eedf00000000, + 0x32fdf11600000000, 0x98f82be700000000, 0x0deabe5f00000000, + 0xa7ef64ae00000000, 0x18e77b6700000000, 0xb2e2a19600000000, + 0xecccae9f00000000, 0x46c9746e00000000, 0xf9c16ba700000000, + 0x53c4b15600000000, 0xc6d624ee00000000, 0x6cd3fe1f00000000, + 0xd3dbe1d600000000, 0x79de3b2700000000, 0xb8f8ba7c00000000, + 0x12fd608d00000000, 0xadf57f4400000000, 0x07f0a5b500000000, + 0x92e2300d00000000, 0x38e7eafc00000000, 0x87eff53500000000, + 0x2dea2fc400000000, 0x05a2f78200000000, 0xafa72d7300000000, + 0x10af32ba00000000, 0xbaaae84b00000000, 0x2fb87df300000000, + 0x85bda70200000000, 0x3ab5b8cb00000000, 0x90b0623a00000000, + 0x5196e36100000000, 0xfb93399000000000, 0x449b265900000000, + 0xee9efca800000000, 0x7b8c691000000000, 0xd189b3e100000000, + 0x6e81ac2800000000, 0xc48476d900000000, 0x3e111ca500000000, + 0x9414c65400000000, 0x2b1cd99d00000000, 0x8119036c00000000, + 0x140b96d400000000, 0xbe0e4c2500000000, 0x010653ec00000000, + 0xab03891d00000000, 0x6a25084600000000, 0xc020d2b700000000, + 0x7f28cd7e00000000, 0xd52d178f00000000, 0x403f823700000000, + 0xea3a58c600000000, 0x5532470f00000000, 0xff379dfe00000000, + 0xd77f45b800000000, 0x7d7a9f4900000000, 0xc272808000000000, + 0x68775a7100000000, 0xfd65cfc900000000, 0x5760153800000000, + 0xe8680af100000000, 0x426dd00000000000, 0x834b515b00000000, + 0x294e8baa00000000, 0x9646946300000000, 0x3c434e9200000000, + 0xa951db2a00000000, 0x035401db00000000, 0xbc5c1e1200000000, + 0x1659c4e300000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87, + 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede, + 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab, + 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c, + 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1, + 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7, + 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e, + 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308, + 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5, + 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472, + 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07, + 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e, + 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa, + 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec, + 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6, + 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0, + 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3, + 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba, + 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf, + 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975, + 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8, + 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde, + 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a, + 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c, + 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1, + 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65, + 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410, + 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649, + 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a, + 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c, + 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946, + 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450, + 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e, + 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857, + 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022, + 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5, + 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758, + 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e, + 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d, + 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b, + 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6, + 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401, + 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74, + 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d, + 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073, + 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65, + 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f, + 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749, + 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a, + 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033, + 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846, + 0x0d7139d7}, + {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563, + 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f, + 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875, + 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536, + 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8, + 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43, + 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f, + 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184, + 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a, + 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39, + 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523, + 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f, + 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d, + 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6, + 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b, + 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0, + 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151, + 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d, + 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47, + 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a, + 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964, + 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef, + 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d, + 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6, + 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348, + 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53, + 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449, + 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645, + 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4, + 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f, + 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2, + 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69, + 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46, + 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a, + 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650, + 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13, + 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded, + 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366, + 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57, + 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc, + 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222, + 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61, + 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b, + 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277, + 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558, + 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3, + 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e, + 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5, + 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74, + 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78, + 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262, + 0x1c53e98a}, + {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b, + 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40, + 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580, + 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7, + 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a, + 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37, + 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75, + 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218, + 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5, + 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2, + 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02, + 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59, + 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1, + 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c, + 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a, + 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307, + 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486, + 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd, + 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d, + 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2, + 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f, + 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72, + 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8, + 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985, + 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268, + 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94, + 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454, + 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f, + 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e, + 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3, + 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915, + 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778, + 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821, + 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a, + 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba, + 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d, + 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560, + 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d, + 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe, + 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3, + 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e, + 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509, + 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9, + 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92, + 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb, + 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6, + 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50, + 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d, + 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc, + 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7, + 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927, + 0x3f88e851}, + {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96, + 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8, + 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0, + 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14, + 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7, + 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4, + 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe, + 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad, + 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e, + 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa, + 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2, + 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c, + 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab, + 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8, + 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d, + 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e, + 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7, + 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99, + 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1, + 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690, + 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933, + 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20, + 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf, + 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc, + 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f, + 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92, + 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca, + 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4, + 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd, + 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de, + 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb, + 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8, + 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474, + 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a, + 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252, + 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6, + 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55, + 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846, + 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7, + 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4, + 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47, + 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3, + 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb, + 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5, + 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49, + 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a, + 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f, + 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c, + 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305, + 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b, + 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523, + 0x3dee8ca6}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0x85d996dd, 0x4bb55c60, 0xce6ccabd, 0x966ab9c0, + 0x13b32f1d, 0xdddfe5a0, 0x5806737d, 0x6dd3035a, 0xe80a9587, + 0x26665f3a, 0xa3bfc9e7, 0xfbb9ba9a, 0x7e602c47, 0xb00ce6fa, + 0x35d57027, 0xdaa607b4, 0x5f7f9169, 0x91135bd4, 0x14cacd09, + 0x4cccbe74, 0xc91528a9, 0x0779e214, 0x82a074c9, 0xb77504ee, + 0x32ac9233, 0xfcc0588e, 0x7919ce53, 0x211fbd2e, 0xa4c62bf3, + 0x6aaae14e, 0xef737793, 0xf54b7eb3, 0x7092e86e, 0xbefe22d3, + 0x3b27b40e, 0x6321c773, 0xe6f851ae, 0x28949b13, 0xad4d0dce, + 0x98987de9, 0x1d41eb34, 0xd32d2189, 0x56f4b754, 0x0ef2c429, + 0x8b2b52f4, 0x45479849, 0xc09e0e94, 0x2fed7907, 0xaa34efda, + 0x64582567, 0xe181b3ba, 0xb987c0c7, 0x3c5e561a, 0xf2329ca7, + 0x77eb0a7a, 0x423e7a5d, 0xc7e7ec80, 0x098b263d, 0x8c52b0e0, + 0xd454c39d, 0x518d5540, 0x9fe19ffd, 0x1a380920, 0xab918dbd, + 0x2e481b60, 0xe024d1dd, 0x65fd4700, 0x3dfb347d, 0xb822a2a0, + 0x764e681d, 0xf397fec0, 0xc6428ee7, 0x439b183a, 0x8df7d287, + 0x082e445a, 0x50283727, 0xd5f1a1fa, 0x1b9d6b47, 0x9e44fd9a, + 0x71378a09, 0xf4ee1cd4, 0x3a82d669, 0xbf5b40b4, 0xe75d33c9, + 0x6284a514, 0xace86fa9, 0x2931f974, 0x1ce48953, 0x993d1f8e, + 0x5751d533, 0xd28843ee, 0x8a8e3093, 0x0f57a64e, 0xc13b6cf3, + 0x44e2fa2e, 0x5edaf30e, 0xdb0365d3, 0x156faf6e, 0x90b639b3, + 0xc8b04ace, 0x4d69dc13, 0x830516ae, 0x06dc8073, 0x3309f054, + 0xb6d06689, 0x78bcac34, 0xfd653ae9, 0xa5634994, 0x20badf49, + 0xeed615f4, 0x6b0f8329, 0x847cf4ba, 0x01a56267, 0xcfc9a8da, + 0x4a103e07, 0x12164d7a, 0x97cfdba7, 0x59a3111a, 0xdc7a87c7, + 0xe9aff7e0, 0x6c76613d, 0xa21aab80, 0x27c33d5d, 0x7fc54e20, + 0xfa1cd8fd, 0x34701240, 0xb1a9849d, 0x17256aa0, 0x92fcfc7d, + 0x5c9036c0, 0xd949a01d, 0x814fd360, 0x049645bd, 0xcafa8f00, + 0x4f2319dd, 0x7af669fa, 0xff2fff27, 0x3143359a, 0xb49aa347, + 0xec9cd03a, 0x694546e7, 0xa7298c5a, 0x22f01a87, 0xcd836d14, + 0x485afbc9, 0x86363174, 0x03efa7a9, 0x5be9d4d4, 0xde304209, + 0x105c88b4, 0x95851e69, 0xa0506e4e, 0x2589f893, 0xebe5322e, + 0x6e3ca4f3, 0x363ad78e, 0xb3e34153, 0x7d8f8bee, 0xf8561d33, + 0xe26e1413, 0x67b782ce, 0xa9db4873, 0x2c02deae, 0x7404add3, + 0xf1dd3b0e, 0x3fb1f1b3, 0xba68676e, 0x8fbd1749, 0x0a648194, + 0xc4084b29, 0x41d1ddf4, 0x19d7ae89, 0x9c0e3854, 0x5262f2e9, + 0xd7bb6434, 0x38c813a7, 0xbd11857a, 0x737d4fc7, 0xf6a4d91a, + 0xaea2aa67, 0x2b7b3cba, 0xe517f607, 0x60ce60da, 0x551b10fd, + 0xd0c28620, 0x1eae4c9d, 0x9b77da40, 0xc371a93d, 0x46a83fe0, + 0x88c4f55d, 0x0d1d6380, 0xbcb4e71d, 0x396d71c0, 0xf701bb7d, + 0x72d82da0, 0x2ade5edd, 0xaf07c800, 0x616b02bd, 0xe4b29460, + 0xd167e447, 0x54be729a, 0x9ad2b827, 0x1f0b2efa, 0x470d5d87, + 0xc2d4cb5a, 0x0cb801e7, 0x8961973a, 0x6612e0a9, 0xe3cb7674, + 0x2da7bcc9, 0xa87e2a14, 0xf0785969, 0x75a1cfb4, 0xbbcd0509, + 0x3e1493d4, 0x0bc1e3f3, 0x8e18752e, 0x4074bf93, 0xc5ad294e, + 0x9dab5a33, 0x1872ccee, 0xd61e0653, 0x53c7908e, 0x49ff99ae, + 0xcc260f73, 0x024ac5ce, 0x87935313, 0xdf95206e, 0x5a4cb6b3, + 0x94207c0e, 0x11f9ead3, 0x242c9af4, 0xa1f50c29, 0x6f99c694, + 0xea405049, 0xb2462334, 0x379fb5e9, 0xf9f37f54, 0x7c2ae989, + 0x93599e1a, 0x168008c7, 0xd8ecc27a, 0x5d3554a7, 0x053327da, + 0x80eab107, 0x4e867bba, 0xcb5fed67, 0xfe8a9d40, 0x7b530b9d, + 0xb53fc120, 0x30e657fd, 0x68e02480, 0xed39b25d, 0x235578e0, + 0xa68cee3d}, + {0x00000000, 0x76e10f9d, 0xadc46ee1, 0xdb25617c, 0x1b8fac19, + 0x6d6ea384, 0xb64bc2f8, 0xc0aacd65, 0x361e5933, 0x40ff56ae, + 0x9bda37d2, 0xed3b384f, 0x2d91f52a, 0x5b70fab7, 0x80559bcb, + 0xf6b49456, 0x6c3cb266, 0x1addbdfb, 0xc1f8dc87, 0xb719d31a, + 0x77b31e7f, 0x015211e2, 0xda77709e, 0xac967f03, 0x5a22eb55, + 0x2cc3e4c8, 0xf7e685b4, 0x81078a29, 0x41ad474c, 0x374c48d1, + 0xec6929ad, 0x9a882630, 0xd87864cd, 0xae996b50, 0x75bc0a2c, + 0x035d05b1, 0xc3f7c8d4, 0xb516c749, 0x6e33a635, 0x18d2a9a8, + 0xee663dfe, 0x98873263, 0x43a2531f, 0x35435c82, 0xf5e991e7, + 0x83089e7a, 0x582dff06, 0x2eccf09b, 0xb444d6ab, 0xc2a5d936, + 0x1980b84a, 0x6f61b7d7, 0xafcb7ab2, 0xd92a752f, 0x020f1453, + 0x74ee1bce, 0x825a8f98, 0xf4bb8005, 0x2f9ee179, 0x597feee4, + 0x99d52381, 0xef342c1c, 0x34114d60, 0x42f042fd, 0xf1f7b941, + 0x8716b6dc, 0x5c33d7a0, 0x2ad2d83d, 0xea781558, 0x9c991ac5, + 0x47bc7bb9, 0x315d7424, 0xc7e9e072, 0xb108efef, 0x6a2d8e93, + 0x1ccc810e, 0xdc664c6b, 0xaa8743f6, 0x71a2228a, 0x07432d17, + 0x9dcb0b27, 0xeb2a04ba, 0x300f65c6, 0x46ee6a5b, 0x8644a73e, + 0xf0a5a8a3, 0x2b80c9df, 0x5d61c642, 0xabd55214, 0xdd345d89, + 0x06113cf5, 0x70f03368, 0xb05afe0d, 0xc6bbf190, 0x1d9e90ec, + 0x6b7f9f71, 0x298fdd8c, 0x5f6ed211, 0x844bb36d, 0xf2aabcf0, + 0x32007195, 0x44e17e08, 0x9fc41f74, 0xe92510e9, 0x1f9184bf, + 0x69708b22, 0xb255ea5e, 0xc4b4e5c3, 0x041e28a6, 0x72ff273b, + 0xa9da4647, 0xdf3b49da, 0x45b36fea, 0x33526077, 0xe877010b, + 0x9e960e96, 0x5e3cc3f3, 0x28ddcc6e, 0xf3f8ad12, 0x8519a28f, + 0x73ad36d9, 0x054c3944, 0xde695838, 0xa88857a5, 0x68229ac0, + 0x1ec3955d, 0xc5e6f421, 0xb307fbbc, 0xe2ef7383, 0x940e7c1e, + 0x4f2b1d62, 0x39ca12ff, 0xf960df9a, 0x8f81d007, 0x54a4b17b, + 0x2245bee6, 0xd4f12ab0, 0xa210252d, 0x79354451, 0x0fd44bcc, + 0xcf7e86a9, 0xb99f8934, 0x62bae848, 0x145be7d5, 0x8ed3c1e5, + 0xf832ce78, 0x2317af04, 0x55f6a099, 0x955c6dfc, 0xe3bd6261, + 0x3898031d, 0x4e790c80, 0xb8cd98d6, 0xce2c974b, 0x1509f637, + 0x63e8f9aa, 0xa34234cf, 0xd5a33b52, 0x0e865a2e, 0x786755b3, + 0x3a97174e, 0x4c7618d3, 0x975379af, 0xe1b27632, 0x2118bb57, + 0x57f9b4ca, 0x8cdcd5b6, 0xfa3dda2b, 0x0c894e7d, 0x7a6841e0, + 0xa14d209c, 0xd7ac2f01, 0x1706e264, 0x61e7edf9, 0xbac28c85, + 0xcc238318, 0x56aba528, 0x204aaab5, 0xfb6fcbc9, 0x8d8ec454, + 0x4d240931, 0x3bc506ac, 0xe0e067d0, 0x9601684d, 0x60b5fc1b, + 0x1654f386, 0xcd7192fa, 0xbb909d67, 0x7b3a5002, 0x0ddb5f9f, + 0xd6fe3ee3, 0xa01f317e, 0x1318cac2, 0x65f9c55f, 0xbedca423, + 0xc83dabbe, 0x089766db, 0x7e766946, 0xa553083a, 0xd3b207a7, + 0x250693f1, 0x53e79c6c, 0x88c2fd10, 0xfe23f28d, 0x3e893fe8, + 0x48683075, 0x934d5109, 0xe5ac5e94, 0x7f2478a4, 0x09c57739, + 0xd2e01645, 0xa40119d8, 0x64abd4bd, 0x124adb20, 0xc96fba5c, + 0xbf8eb5c1, 0x493a2197, 0x3fdb2e0a, 0xe4fe4f76, 0x921f40eb, + 0x52b58d8e, 0x24548213, 0xff71e36f, 0x8990ecf2, 0xcb60ae0f, + 0xbd81a192, 0x66a4c0ee, 0x1045cf73, 0xd0ef0216, 0xa60e0d8b, + 0x7d2b6cf7, 0x0bca636a, 0xfd7ef73c, 0x8b9ff8a1, 0x50ba99dd, + 0x265b9640, 0xe6f15b25, 0x901054b8, 0x4b3535c4, 0x3dd43a59, + 0xa75c1c69, 0xd1bd13f4, 0x0a987288, 0x7c797d15, 0xbcd3b070, + 0xca32bfed, 0x1117de91, 0x67f6d10c, 0x9142455a, 0xe7a34ac7, + 0x3c862bbb, 0x4a672426, 0x8acde943, 0xfc2ce6de, 0x270987a2, + 0x51e8883f}, + {0x00000000, 0xe8dbfbb9, 0x91b186a8, 0x796a7d11, 0x63657c8a, + 0x8bbe8733, 0xf2d4fa22, 0x1a0f019b, 0x87cc89cf, 0x6f177276, + 0x167d0f67, 0xfea6f4de, 0xe4a9f545, 0x0c720efc, 0x751873ed, + 0x9dc38854, 0x4f9f6244, 0xa74499fd, 0xde2ee4ec, 0x36f51f55, + 0x2cfa1ece, 0xc421e577, 0xbd4b9866, 0x559063df, 0xc853eb8b, + 0x20881032, 0x59e26d23, 0xb139969a, 0xab369701, 0x43ed6cb8, + 0x3a8711a9, 0xd25cea10, 0x9e3ec588, 0x76e53e31, 0x0f8f4320, + 0xe754b899, 0xfd5bb902, 0x158042bb, 0x6cea3faa, 0x8431c413, + 0x19f24c47, 0xf129b7fe, 0x8843caef, 0x60983156, 0x7a9730cd, + 0x924ccb74, 0xeb26b665, 0x03fd4ddc, 0xd1a1a7cc, 0x397a5c75, + 0x40102164, 0xa8cbdadd, 0xb2c4db46, 0x5a1f20ff, 0x23755dee, + 0xcbaea657, 0x566d2e03, 0xbeb6d5ba, 0xc7dca8ab, 0x2f075312, + 0x35085289, 0xddd3a930, 0xa4b9d421, 0x4c622f98, 0x7d7bfbca, + 0x95a00073, 0xecca7d62, 0x041186db, 0x1e1e8740, 0xf6c57cf9, + 0x8faf01e8, 0x6774fa51, 0xfab77205, 0x126c89bc, 0x6b06f4ad, + 0x83dd0f14, 0x99d20e8f, 0x7109f536, 0x08638827, 0xe0b8739e, + 0x32e4998e, 0xda3f6237, 0xa3551f26, 0x4b8ee49f, 0x5181e504, + 0xb95a1ebd, 0xc03063ac, 0x28eb9815, 0xb5281041, 0x5df3ebf8, + 0x249996e9, 0xcc426d50, 0xd64d6ccb, 0x3e969772, 0x47fcea63, + 0xaf2711da, 0xe3453e42, 0x0b9ec5fb, 0x72f4b8ea, 0x9a2f4353, + 0x802042c8, 0x68fbb971, 0x1191c460, 0xf94a3fd9, 0x6489b78d, + 0x8c524c34, 0xf5383125, 0x1de3ca9c, 0x07eccb07, 0xef3730be, + 0x965d4daf, 0x7e86b616, 0xacda5c06, 0x4401a7bf, 0x3d6bdaae, + 0xd5b02117, 0xcfbf208c, 0x2764db35, 0x5e0ea624, 0xb6d55d9d, + 0x2b16d5c9, 0xc3cd2e70, 0xbaa75361, 0x527ca8d8, 0x4873a943, + 0xa0a852fa, 0xd9c22feb, 0x3119d452, 0xbbf0874e, 0x532b7cf7, + 0x2a4101e6, 0xc29afa5f, 0xd895fbc4, 0x304e007d, 0x49247d6c, + 0xa1ff86d5, 0x3c3c0e81, 0xd4e7f538, 0xad8d8829, 0x45567390, + 0x5f59720b, 0xb78289b2, 0xcee8f4a3, 0x26330f1a, 0xf46fe50a, + 0x1cb41eb3, 0x65de63a2, 0x8d05981b, 0x970a9980, 0x7fd16239, + 0x06bb1f28, 0xee60e491, 0x73a36cc5, 0x9b78977c, 0xe212ea6d, + 0x0ac911d4, 0x10c6104f, 0xf81debf6, 0x817796e7, 0x69ac6d5e, + 0x25ce42c6, 0xcd15b97f, 0xb47fc46e, 0x5ca43fd7, 0x46ab3e4c, + 0xae70c5f5, 0xd71ab8e4, 0x3fc1435d, 0xa202cb09, 0x4ad930b0, + 0x33b34da1, 0xdb68b618, 0xc167b783, 0x29bc4c3a, 0x50d6312b, + 0xb80dca92, 0x6a512082, 0x828adb3b, 0xfbe0a62a, 0x133b5d93, + 0x09345c08, 0xe1efa7b1, 0x9885daa0, 0x705e2119, 0xed9da94d, + 0x054652f4, 0x7c2c2fe5, 0x94f7d45c, 0x8ef8d5c7, 0x66232e7e, + 0x1f49536f, 0xf792a8d6, 0xc68b7c84, 0x2e50873d, 0x573afa2c, + 0xbfe10195, 0xa5ee000e, 0x4d35fbb7, 0x345f86a6, 0xdc847d1f, + 0x4147f54b, 0xa99c0ef2, 0xd0f673e3, 0x382d885a, 0x222289c1, + 0xcaf97278, 0xb3930f69, 0x5b48f4d0, 0x89141ec0, 0x61cfe579, + 0x18a59868, 0xf07e63d1, 0xea71624a, 0x02aa99f3, 0x7bc0e4e2, + 0x931b1f5b, 0x0ed8970f, 0xe6036cb6, 0x9f6911a7, 0x77b2ea1e, + 0x6dbdeb85, 0x8566103c, 0xfc0c6d2d, 0x14d79694, 0x58b5b90c, + 0xb06e42b5, 0xc9043fa4, 0x21dfc41d, 0x3bd0c586, 0xd30b3e3f, + 0xaa61432e, 0x42bab897, 0xdf7930c3, 0x37a2cb7a, 0x4ec8b66b, + 0xa6134dd2, 0xbc1c4c49, 0x54c7b7f0, 0x2dadcae1, 0xc5763158, + 0x172adb48, 0xfff120f1, 0x869b5de0, 0x6e40a659, 0x744fa7c2, + 0x9c945c7b, 0xe5fe216a, 0x0d25dad3, 0x90e65287, 0x783da93e, + 0x0157d42f, 0xe98c2f96, 0xf3832e0d, 0x1b58d5b4, 0x6232a8a5, + 0x8ae9531c}, + {0x00000000, 0x919168ae, 0x6325a087, 0xf2b4c829, 0x874c31d4, + 0x16dd597a, 0xe4699153, 0x75f8f9fd, 0x4f9f1373, 0xde0e7bdd, + 0x2cbab3f4, 0xbd2bdb5a, 0xc8d322a7, 0x59424a09, 0xabf68220, + 0x3a67ea8e, 0x9e3e27e6, 0x0faf4f48, 0xfd1b8761, 0x6c8aefcf, + 0x19721632, 0x88e37e9c, 0x7a57b6b5, 0xebc6de1b, 0xd1a13495, + 0x40305c3b, 0xb2849412, 0x2315fcbc, 0x56ed0541, 0xc77c6def, + 0x35c8a5c6, 0xa459cd68, 0x7d7b3f17, 0xecea57b9, 0x1e5e9f90, + 0x8fcff73e, 0xfa370ec3, 0x6ba6666d, 0x9912ae44, 0x0883c6ea, + 0x32e42c64, 0xa37544ca, 0x51c18ce3, 0xc050e44d, 0xb5a81db0, + 0x2439751e, 0xd68dbd37, 0x471cd599, 0xe34518f1, 0x72d4705f, + 0x8060b876, 0x11f1d0d8, 0x64092925, 0xf598418b, 0x072c89a2, + 0x96bde10c, 0xacda0b82, 0x3d4b632c, 0xcfffab05, 0x5e6ec3ab, + 0x2b963a56, 0xba0752f8, 0x48b39ad1, 0xd922f27f, 0xfaf67e2e, + 0x6b671680, 0x99d3dea9, 0x0842b607, 0x7dba4ffa, 0xec2b2754, + 0x1e9fef7d, 0x8f0e87d3, 0xb5696d5d, 0x24f805f3, 0xd64ccdda, + 0x47dda574, 0x32255c89, 0xa3b43427, 0x5100fc0e, 0xc09194a0, + 0x64c859c8, 0xf5593166, 0x07edf94f, 0x967c91e1, 0xe384681c, + 0x721500b2, 0x80a1c89b, 0x1130a035, 0x2b574abb, 0xbac62215, + 0x4872ea3c, 0xd9e38292, 0xac1b7b6f, 0x3d8a13c1, 0xcf3edbe8, + 0x5eafb346, 0x878d4139, 0x161c2997, 0xe4a8e1be, 0x75398910, + 0x00c170ed, 0x91501843, 0x63e4d06a, 0xf275b8c4, 0xc812524a, + 0x59833ae4, 0xab37f2cd, 0x3aa69a63, 0x4f5e639e, 0xdecf0b30, + 0x2c7bc319, 0xbdeaabb7, 0x19b366df, 0x88220e71, 0x7a96c658, + 0xeb07aef6, 0x9eff570b, 0x0f6e3fa5, 0xfddaf78c, 0x6c4b9f22, + 0x562c75ac, 0xc7bd1d02, 0x3509d52b, 0xa498bd85, 0xd1604478, + 0x40f12cd6, 0xb245e4ff, 0x23d48c51, 0xf4edfd5c, 0x657c95f2, + 0x97c85ddb, 0x06593575, 0x73a1cc88, 0xe230a426, 0x10846c0f, + 0x811504a1, 0xbb72ee2f, 0x2ae38681, 0xd8574ea8, 0x49c62606, + 0x3c3edffb, 0xadafb755, 0x5f1b7f7c, 0xce8a17d2, 0x6ad3daba, + 0xfb42b214, 0x09f67a3d, 0x98671293, 0xed9feb6e, 0x7c0e83c0, + 0x8eba4be9, 0x1f2b2347, 0x254cc9c9, 0xb4dda167, 0x4669694e, + 0xd7f801e0, 0xa200f81d, 0x339190b3, 0xc125589a, 0x50b43034, + 0x8996c24b, 0x1807aae5, 0xeab362cc, 0x7b220a62, 0x0edaf39f, + 0x9f4b9b31, 0x6dff5318, 0xfc6e3bb6, 0xc609d138, 0x5798b996, + 0xa52c71bf, 0x34bd1911, 0x4145e0ec, 0xd0d48842, 0x2260406b, + 0xb3f128c5, 0x17a8e5ad, 0x86398d03, 0x748d452a, 0xe51c2d84, + 0x90e4d479, 0x0175bcd7, 0xf3c174fe, 0x62501c50, 0x5837f6de, + 0xc9a69e70, 0x3b125659, 0xaa833ef7, 0xdf7bc70a, 0x4eeaafa4, + 0xbc5e678d, 0x2dcf0f23, 0x0e1b8372, 0x9f8aebdc, 0x6d3e23f5, + 0xfcaf4b5b, 0x8957b2a6, 0x18c6da08, 0xea721221, 0x7be37a8f, + 0x41849001, 0xd015f8af, 0x22a13086, 0xb3305828, 0xc6c8a1d5, + 0x5759c97b, 0xa5ed0152, 0x347c69fc, 0x9025a494, 0x01b4cc3a, + 0xf3000413, 0x62916cbd, 0x17699540, 0x86f8fdee, 0x744c35c7, + 0xe5dd5d69, 0xdfbab7e7, 0x4e2bdf49, 0xbc9f1760, 0x2d0e7fce, + 0x58f68633, 0xc967ee9d, 0x3bd326b4, 0xaa424e1a, 0x7360bc65, + 0xe2f1d4cb, 0x10451ce2, 0x81d4744c, 0xf42c8db1, 0x65bde51f, + 0x97092d36, 0x06984598, 0x3cffaf16, 0xad6ec7b8, 0x5fda0f91, + 0xce4b673f, 0xbbb39ec2, 0x2a22f66c, 0xd8963e45, 0x490756eb, + 0xed5e9b83, 0x7ccff32d, 0x8e7b3b04, 0x1fea53aa, 0x6a12aa57, + 0xfb83c2f9, 0x09370ad0, 0x98a6627e, 0xa2c188f0, 0x3350e05e, + 0xc1e42877, 0x507540d9, 0x258db924, 0xb41cd18a, 0x46a819a3, + 0xd739710d}}; + +#endif + +#endif + +#if N == 5 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xaf449247, 0x85f822cf, 0x2abcb088, 0xd08143df, + 0x7fc5d198, 0x55796110, 0xfa3df357, 0x7a7381ff, 0xd53713b8, + 0xff8ba330, 0x50cf3177, 0xaaf2c220, 0x05b65067, 0x2f0ae0ef, + 0x804e72a8, 0xf4e703fe, 0x5ba391b9, 0x711f2131, 0xde5bb376, + 0x24664021, 0x8b22d266, 0xa19e62ee, 0x0edaf0a9, 0x8e948201, + 0x21d01046, 0x0b6ca0ce, 0xa4283289, 0x5e15c1de, 0xf1515399, + 0xdbede311, 0x74a97156, 0x32bf01bd, 0x9dfb93fa, 0xb7472372, + 0x1803b135, 0xe23e4262, 0x4d7ad025, 0x67c660ad, 0xc882f2ea, + 0x48cc8042, 0xe7881205, 0xcd34a28d, 0x627030ca, 0x984dc39d, + 0x370951da, 0x1db5e152, 0xb2f17315, 0xc6580243, 0x691c9004, + 0x43a0208c, 0xece4b2cb, 0x16d9419c, 0xb99dd3db, 0x93216353, + 0x3c65f114, 0xbc2b83bc, 0x136f11fb, 0x39d3a173, 0x96973334, + 0x6caac063, 0xc3ee5224, 0xe952e2ac, 0x461670eb, 0x657e037a, + 0xca3a913d, 0xe08621b5, 0x4fc2b3f2, 0xb5ff40a5, 0x1abbd2e2, + 0x3007626a, 0x9f43f02d, 0x1f0d8285, 0xb04910c2, 0x9af5a04a, + 0x35b1320d, 0xcf8cc15a, 0x60c8531d, 0x4a74e395, 0xe53071d2, + 0x91990084, 0x3edd92c3, 0x1461224b, 0xbb25b00c, 0x4118435b, + 0xee5cd11c, 0xc4e06194, 0x6ba4f3d3, 0xebea817b, 0x44ae133c, + 0x6e12a3b4, 0xc15631f3, 0x3b6bc2a4, 0x942f50e3, 0xbe93e06b, + 0x11d7722c, 0x57c102c7, 0xf8859080, 0xd2392008, 0x7d7db24f, + 0x87404118, 0x2804d35f, 0x02b863d7, 0xadfcf190, 0x2db28338, + 0x82f6117f, 0xa84aa1f7, 0x070e33b0, 0xfd33c0e7, 0x527752a0, + 0x78cbe228, 0xd78f706f, 0xa3260139, 0x0c62937e, 0x26de23f6, + 0x899ab1b1, 0x73a742e6, 0xdce3d0a1, 0xf65f6029, 0x591bf26e, + 0xd95580c6, 0x76111281, 0x5cada209, 0xf3e9304e, 0x09d4c319, + 0xa690515e, 0x8c2ce1d6, 0x23687391, 0xcafc06f4, 0x65b894b3, + 0x4f04243b, 0xe040b67c, 0x1a7d452b, 0xb539d76c, 0x9f8567e4, + 0x30c1f5a3, 0xb08f870b, 0x1fcb154c, 0x3577a5c4, 0x9a333783, + 0x600ec4d4, 0xcf4a5693, 0xe5f6e61b, 0x4ab2745c, 0x3e1b050a, + 0x915f974d, 0xbbe327c5, 0x14a7b582, 0xee9a46d5, 0x41ded492, + 0x6b62641a, 0xc426f65d, 0x446884f5, 0xeb2c16b2, 0xc190a63a, + 0x6ed4347d, 0x94e9c72a, 0x3bad556d, 0x1111e5e5, 0xbe5577a2, + 0xf8430749, 0x5707950e, 0x7dbb2586, 0xd2ffb7c1, 0x28c24496, + 0x8786d6d1, 0xad3a6659, 0x027ef41e, 0x823086b6, 0x2d7414f1, + 0x07c8a479, 0xa88c363e, 0x52b1c569, 0xfdf5572e, 0xd749e7a6, + 0x780d75e1, 0x0ca404b7, 0xa3e096f0, 0x895c2678, 0x2618b43f, + 0xdc254768, 0x7361d52f, 0x59dd65a7, 0xf699f7e0, 0x76d78548, + 0xd993170f, 0xf32fa787, 0x5c6b35c0, 0xa656c697, 0x091254d0, + 0x23aee458, 0x8cea761f, 0xaf82058e, 0x00c697c9, 0x2a7a2741, + 0x853eb506, 0x7f034651, 0xd047d416, 0xfafb649e, 0x55bff6d9, + 0xd5f18471, 0x7ab51636, 0x5009a6be, 0xff4d34f9, 0x0570c7ae, + 0xaa3455e9, 0x8088e561, 0x2fcc7726, 0x5b650670, 0xf4219437, + 0xde9d24bf, 0x71d9b6f8, 0x8be445af, 0x24a0d7e8, 0x0e1c6760, + 0xa158f527, 0x2116878f, 0x8e5215c8, 0xa4eea540, 0x0baa3707, + 0xf197c450, 0x5ed35617, 0x746fe69f, 0xdb2b74d8, 0x9d3d0433, + 0x32799674, 0x18c526fc, 0xb781b4bb, 0x4dbc47ec, 0xe2f8d5ab, + 0xc8446523, 0x6700f764, 0xe74e85cc, 0x480a178b, 0x62b6a703, + 0xcdf23544, 0x37cfc613, 0x988b5454, 0xb237e4dc, 0x1d73769b, + 0x69da07cd, 0xc69e958a, 0xec222502, 0x4366b745, 0xb95b4412, + 0x161fd655, 0x3ca366dd, 0x93e7f49a, 0x13a98632, 0xbced1475, + 0x9651a4fd, 0x391536ba, 0xc328c5ed, 0x6c6c57aa, 0x46d0e722, + 0xe9947565}, + {0x00000000, 0x4e890ba9, 0x9d121752, 0xd39b1cfb, 0xe15528e5, + 0xafdc234c, 0x7c473fb7, 0x32ce341e, 0x19db578b, 0x57525c22, + 0x84c940d9, 0xca404b70, 0xf88e7f6e, 0xb60774c7, 0x659c683c, + 0x2b156395, 0x33b6af16, 0x7d3fa4bf, 0xaea4b844, 0xe02db3ed, + 0xd2e387f3, 0x9c6a8c5a, 0x4ff190a1, 0x01789b08, 0x2a6df89d, + 0x64e4f334, 0xb77fefcf, 0xf9f6e466, 0xcb38d078, 0x85b1dbd1, + 0x562ac72a, 0x18a3cc83, 0x676d5e2c, 0x29e45585, 0xfa7f497e, + 0xb4f642d7, 0x863876c9, 0xc8b17d60, 0x1b2a619b, 0x55a36a32, + 0x7eb609a7, 0x303f020e, 0xe3a41ef5, 0xad2d155c, 0x9fe32142, + 0xd16a2aeb, 0x02f13610, 0x4c783db9, 0x54dbf13a, 0x1a52fa93, + 0xc9c9e668, 0x8740edc1, 0xb58ed9df, 0xfb07d276, 0x289cce8d, + 0x6615c524, 0x4d00a6b1, 0x0389ad18, 0xd012b1e3, 0x9e9bba4a, + 0xac558e54, 0xe2dc85fd, 0x31479906, 0x7fce92af, 0xcedabc58, + 0x8053b7f1, 0x53c8ab0a, 0x1d41a0a3, 0x2f8f94bd, 0x61069f14, + 0xb29d83ef, 0xfc148846, 0xd701ebd3, 0x9988e07a, 0x4a13fc81, + 0x049af728, 0x3654c336, 0x78ddc89f, 0xab46d464, 0xe5cfdfcd, + 0xfd6c134e, 0xb3e518e7, 0x607e041c, 0x2ef70fb5, 0x1c393bab, + 0x52b03002, 0x812b2cf9, 0xcfa22750, 0xe4b744c5, 0xaa3e4f6c, + 0x79a55397, 0x372c583e, 0x05e26c20, 0x4b6b6789, 0x98f07b72, + 0xd67970db, 0xa9b7e274, 0xe73ee9dd, 0x34a5f526, 0x7a2cfe8f, + 0x48e2ca91, 0x066bc138, 0xd5f0ddc3, 0x9b79d66a, 0xb06cb5ff, + 0xfee5be56, 0x2d7ea2ad, 0x63f7a904, 0x51399d1a, 0x1fb096b3, + 0xcc2b8a48, 0x82a281e1, 0x9a014d62, 0xd48846cb, 0x07135a30, + 0x499a5199, 0x7b546587, 0x35dd6e2e, 0xe64672d5, 0xa8cf797c, + 0x83da1ae9, 0xcd531140, 0x1ec80dbb, 0x50410612, 0x628f320c, + 0x2c0639a5, 0xff9d255e, 0xb1142ef7, 0x46c47ef1, 0x084d7558, + 0xdbd669a3, 0x955f620a, 0xa7915614, 0xe9185dbd, 0x3a834146, + 0x740a4aef, 0x5f1f297a, 0x119622d3, 0xc20d3e28, 0x8c843581, + 0xbe4a019f, 0xf0c30a36, 0x235816cd, 0x6dd11d64, 0x7572d1e7, + 0x3bfbda4e, 0xe860c6b5, 0xa6e9cd1c, 0x9427f902, 0xdaaef2ab, + 0x0935ee50, 0x47bce5f9, 0x6ca9866c, 0x22208dc5, 0xf1bb913e, + 0xbf329a97, 0x8dfcae89, 0xc375a520, 0x10eeb9db, 0x5e67b272, + 0x21a920dd, 0x6f202b74, 0xbcbb378f, 0xf2323c26, 0xc0fc0838, + 0x8e750391, 0x5dee1f6a, 0x136714c3, 0x38727756, 0x76fb7cff, + 0xa5606004, 0xebe96bad, 0xd9275fb3, 0x97ae541a, 0x443548e1, + 0x0abc4348, 0x121f8fcb, 0x5c968462, 0x8f0d9899, 0xc1849330, + 0xf34aa72e, 0xbdc3ac87, 0x6e58b07c, 0x20d1bbd5, 0x0bc4d840, + 0x454dd3e9, 0x96d6cf12, 0xd85fc4bb, 0xea91f0a5, 0xa418fb0c, + 0x7783e7f7, 0x390aec5e, 0x881ec2a9, 0xc697c900, 0x150cd5fb, + 0x5b85de52, 0x694bea4c, 0x27c2e1e5, 0xf459fd1e, 0xbad0f6b7, + 0x91c59522, 0xdf4c9e8b, 0x0cd78270, 0x425e89d9, 0x7090bdc7, + 0x3e19b66e, 0xed82aa95, 0xa30ba13c, 0xbba86dbf, 0xf5216616, + 0x26ba7aed, 0x68337144, 0x5afd455a, 0x14744ef3, 0xc7ef5208, + 0x896659a1, 0xa2733a34, 0xecfa319d, 0x3f612d66, 0x71e826cf, + 0x432612d1, 0x0daf1978, 0xde340583, 0x90bd0e2a, 0xef739c85, + 0xa1fa972c, 0x72618bd7, 0x3ce8807e, 0x0e26b460, 0x40afbfc9, + 0x9334a332, 0xddbda89b, 0xf6a8cb0e, 0xb821c0a7, 0x6bbadc5c, + 0x2533d7f5, 0x17fde3eb, 0x5974e842, 0x8aeff4b9, 0xc466ff10, + 0xdcc53393, 0x924c383a, 0x41d724c1, 0x0f5e2f68, 0x3d901b76, + 0x731910df, 0xa0820c24, 0xee0b078d, 0xc51e6418, 0x8b976fb1, + 0x580c734a, 0x168578e3, 0x244b4cfd, 0x6ac24754, 0xb9595baf, + 0xf7d05006}, + {0x00000000, 0x8d88fde2, 0xc060fd85, 0x4de80067, 0x5bb0fd4b, + 0xd63800a9, 0x9bd000ce, 0x1658fd2c, 0xb761fa96, 0x3ae90774, + 0x77010713, 0xfa89faf1, 0xecd107dd, 0x6159fa3f, 0x2cb1fa58, + 0xa13907ba, 0xb5b2f36d, 0x383a0e8f, 0x75d20ee8, 0xf85af30a, + 0xee020e26, 0x638af3c4, 0x2e62f3a3, 0xa3ea0e41, 0x02d309fb, + 0x8f5bf419, 0xc2b3f47e, 0x4f3b099c, 0x5963f4b0, 0xd4eb0952, + 0x99030935, 0x148bf4d7, 0xb014e09b, 0x3d9c1d79, 0x70741d1e, + 0xfdfce0fc, 0xeba41dd0, 0x662ce032, 0x2bc4e055, 0xa64c1db7, + 0x07751a0d, 0x8afde7ef, 0xc715e788, 0x4a9d1a6a, 0x5cc5e746, + 0xd14d1aa4, 0x9ca51ac3, 0x112de721, 0x05a613f6, 0x882eee14, + 0xc5c6ee73, 0x484e1391, 0x5e16eebd, 0xd39e135f, 0x9e761338, + 0x13feeeda, 0xb2c7e960, 0x3f4f1482, 0x72a714e5, 0xff2fe907, + 0xe977142b, 0x64ffe9c9, 0x2917e9ae, 0xa49f144c, 0xbb58c777, + 0x36d03a95, 0x7b383af2, 0xf6b0c710, 0xe0e83a3c, 0x6d60c7de, + 0x2088c7b9, 0xad003a5b, 0x0c393de1, 0x81b1c003, 0xcc59c064, + 0x41d13d86, 0x5789c0aa, 0xda013d48, 0x97e93d2f, 0x1a61c0cd, + 0x0eea341a, 0x8362c9f8, 0xce8ac99f, 0x4302347d, 0x555ac951, + 0xd8d234b3, 0x953a34d4, 0x18b2c936, 0xb98bce8c, 0x3403336e, + 0x79eb3309, 0xf463ceeb, 0xe23b33c7, 0x6fb3ce25, 0x225bce42, + 0xafd333a0, 0x0b4c27ec, 0x86c4da0e, 0xcb2cda69, 0x46a4278b, + 0x50fcdaa7, 0xdd742745, 0x909c2722, 0x1d14dac0, 0xbc2ddd7a, + 0x31a52098, 0x7c4d20ff, 0xf1c5dd1d, 0xe79d2031, 0x6a15ddd3, + 0x27fdddb4, 0xaa752056, 0xbefed481, 0x33762963, 0x7e9e2904, + 0xf316d4e6, 0xe54e29ca, 0x68c6d428, 0x252ed44f, 0xa8a629ad, + 0x099f2e17, 0x8417d3f5, 0xc9ffd392, 0x44772e70, 0x522fd35c, + 0xdfa72ebe, 0x924f2ed9, 0x1fc7d33b, 0xadc088af, 0x2048754d, + 0x6da0752a, 0xe02888c8, 0xf67075e4, 0x7bf88806, 0x36108861, + 0xbb987583, 0x1aa17239, 0x97298fdb, 0xdac18fbc, 0x5749725e, + 0x41118f72, 0xcc997290, 0x817172f7, 0x0cf98f15, 0x18727bc2, + 0x95fa8620, 0xd8128647, 0x559a7ba5, 0x43c28689, 0xce4a7b6b, + 0x83a27b0c, 0x0e2a86ee, 0xaf138154, 0x229b7cb6, 0x6f737cd1, + 0xe2fb8133, 0xf4a37c1f, 0x792b81fd, 0x34c3819a, 0xb94b7c78, + 0x1dd46834, 0x905c95d6, 0xddb495b1, 0x503c6853, 0x4664957f, + 0xcbec689d, 0x860468fa, 0x0b8c9518, 0xaab592a2, 0x273d6f40, + 0x6ad56f27, 0xe75d92c5, 0xf1056fe9, 0x7c8d920b, 0x3165926c, + 0xbced6f8e, 0xa8669b59, 0x25ee66bb, 0x680666dc, 0xe58e9b3e, + 0xf3d66612, 0x7e5e9bf0, 0x33b69b97, 0xbe3e6675, 0x1f0761cf, + 0x928f9c2d, 0xdf679c4a, 0x52ef61a8, 0x44b79c84, 0xc93f6166, + 0x84d76101, 0x095f9ce3, 0x16984fd8, 0x9b10b23a, 0xd6f8b25d, + 0x5b704fbf, 0x4d28b293, 0xc0a04f71, 0x8d484f16, 0x00c0b2f4, + 0xa1f9b54e, 0x2c7148ac, 0x619948cb, 0xec11b529, 0xfa494805, + 0x77c1b5e7, 0x3a29b580, 0xb7a14862, 0xa32abcb5, 0x2ea24157, + 0x634a4130, 0xeec2bcd2, 0xf89a41fe, 0x7512bc1c, 0x38fabc7b, + 0xb5724199, 0x144b4623, 0x99c3bbc1, 0xd42bbba6, 0x59a34644, + 0x4ffbbb68, 0xc273468a, 0x8f9b46ed, 0x0213bb0f, 0xa68caf43, + 0x2b0452a1, 0x66ec52c6, 0xeb64af24, 0xfd3c5208, 0x70b4afea, + 0x3d5caf8d, 0xb0d4526f, 0x11ed55d5, 0x9c65a837, 0xd18da850, + 0x5c0555b2, 0x4a5da89e, 0xc7d5557c, 0x8a3d551b, 0x07b5a8f9, + 0x133e5c2e, 0x9eb6a1cc, 0xd35ea1ab, 0x5ed65c49, 0x488ea165, + 0xc5065c87, 0x88ee5ce0, 0x0566a102, 0xa45fa6b8, 0x29d75b5a, + 0x643f5b3d, 0xe9b7a6df, 0xffef5bf3, 0x7267a611, 0x3f8fa676, + 0xb2075b94}, + {0x00000000, 0x80f0171f, 0xda91287f, 0x5a613f60, 0x6e5356bf, + 0xeea341a0, 0xb4c27ec0, 0x343269df, 0xdca6ad7e, 0x5c56ba61, + 0x06378501, 0x86c7921e, 0xb2f5fbc1, 0x3205ecde, 0x6864d3be, + 0xe894c4a1, 0x623c5cbd, 0xe2cc4ba2, 0xb8ad74c2, 0x385d63dd, + 0x0c6f0a02, 0x8c9f1d1d, 0xd6fe227d, 0x560e3562, 0xbe9af1c3, + 0x3e6ae6dc, 0x640bd9bc, 0xe4fbcea3, 0xd0c9a77c, 0x5039b063, + 0x0a588f03, 0x8aa8981c, 0xc478b97a, 0x4488ae65, 0x1ee99105, + 0x9e19861a, 0xaa2befc5, 0x2adbf8da, 0x70bac7ba, 0xf04ad0a5, + 0x18de1404, 0x982e031b, 0xc24f3c7b, 0x42bf2b64, 0x768d42bb, + 0xf67d55a4, 0xac1c6ac4, 0x2cec7ddb, 0xa644e5c7, 0x26b4f2d8, + 0x7cd5cdb8, 0xfc25daa7, 0xc817b378, 0x48e7a467, 0x12869b07, + 0x92768c18, 0x7ae248b9, 0xfa125fa6, 0xa07360c6, 0x208377d9, + 0x14b11e06, 0x94410919, 0xce203679, 0x4ed02166, 0x538074b5, + 0xd37063aa, 0x89115cca, 0x09e14bd5, 0x3dd3220a, 0xbd233515, + 0xe7420a75, 0x67b21d6a, 0x8f26d9cb, 0x0fd6ced4, 0x55b7f1b4, + 0xd547e6ab, 0xe1758f74, 0x6185986b, 0x3be4a70b, 0xbb14b014, + 0x31bc2808, 0xb14c3f17, 0xeb2d0077, 0x6bdd1768, 0x5fef7eb7, + 0xdf1f69a8, 0x857e56c8, 0x058e41d7, 0xed1a8576, 0x6dea9269, + 0x378bad09, 0xb77bba16, 0x8349d3c9, 0x03b9c4d6, 0x59d8fbb6, + 0xd928eca9, 0x97f8cdcf, 0x1708dad0, 0x4d69e5b0, 0xcd99f2af, + 0xf9ab9b70, 0x795b8c6f, 0x233ab30f, 0xa3caa410, 0x4b5e60b1, + 0xcbae77ae, 0x91cf48ce, 0x113f5fd1, 0x250d360e, 0xa5fd2111, + 0xff9c1e71, 0x7f6c096e, 0xf5c49172, 0x7534866d, 0x2f55b90d, + 0xafa5ae12, 0x9b97c7cd, 0x1b67d0d2, 0x4106efb2, 0xc1f6f8ad, + 0x29623c0c, 0xa9922b13, 0xf3f31473, 0x7303036c, 0x47316ab3, + 0xc7c17dac, 0x9da042cc, 0x1d5055d3, 0xa700e96a, 0x27f0fe75, + 0x7d91c115, 0xfd61d60a, 0xc953bfd5, 0x49a3a8ca, 0x13c297aa, + 0x933280b5, 0x7ba64414, 0xfb56530b, 0xa1376c6b, 0x21c77b74, + 0x15f512ab, 0x950505b4, 0xcf643ad4, 0x4f942dcb, 0xc53cb5d7, + 0x45cca2c8, 0x1fad9da8, 0x9f5d8ab7, 0xab6fe368, 0x2b9ff477, + 0x71fecb17, 0xf10edc08, 0x199a18a9, 0x996a0fb6, 0xc30b30d6, + 0x43fb27c9, 0x77c94e16, 0xf7395909, 0xad586669, 0x2da87176, + 0x63785010, 0xe388470f, 0xb9e9786f, 0x39196f70, 0x0d2b06af, + 0x8ddb11b0, 0xd7ba2ed0, 0x574a39cf, 0xbfdefd6e, 0x3f2eea71, + 0x654fd511, 0xe5bfc20e, 0xd18dabd1, 0x517dbcce, 0x0b1c83ae, + 0x8bec94b1, 0x01440cad, 0x81b41bb2, 0xdbd524d2, 0x5b2533cd, + 0x6f175a12, 0xefe74d0d, 0xb586726d, 0x35766572, 0xdde2a1d3, + 0x5d12b6cc, 0x077389ac, 0x87839eb3, 0xb3b1f76c, 0x3341e073, + 0x6920df13, 0xe9d0c80c, 0xf4809ddf, 0x74708ac0, 0x2e11b5a0, + 0xaee1a2bf, 0x9ad3cb60, 0x1a23dc7f, 0x4042e31f, 0xc0b2f400, + 0x282630a1, 0xa8d627be, 0xf2b718de, 0x72470fc1, 0x4675661e, + 0xc6857101, 0x9ce44e61, 0x1c14597e, 0x96bcc162, 0x164cd67d, + 0x4c2de91d, 0xccddfe02, 0xf8ef97dd, 0x781f80c2, 0x227ebfa2, + 0xa28ea8bd, 0x4a1a6c1c, 0xcaea7b03, 0x908b4463, 0x107b537c, + 0x24493aa3, 0xa4b92dbc, 0xfed812dc, 0x7e2805c3, 0x30f824a5, + 0xb00833ba, 0xea690cda, 0x6a991bc5, 0x5eab721a, 0xde5b6505, + 0x843a5a65, 0x04ca4d7a, 0xec5e89db, 0x6cae9ec4, 0x36cfa1a4, + 0xb63fb6bb, 0x820ddf64, 0x02fdc87b, 0x589cf71b, 0xd86ce004, + 0x52c47818, 0xd2346f07, 0x88555067, 0x08a54778, 0x3c972ea7, + 0xbc6739b8, 0xe60606d8, 0x66f611c7, 0x8e62d566, 0x0e92c279, + 0x54f3fd19, 0xd403ea06, 0xe03183d9, 0x60c194c6, 0x3aa0aba6, + 0xba50bcb9}, + {0x00000000, 0x9570d495, 0xf190af6b, 0x64e07bfe, 0x38505897, + 0xad208c02, 0xc9c0f7fc, 0x5cb02369, 0x70a0b12e, 0xe5d065bb, + 0x81301e45, 0x1440cad0, 0x48f0e9b9, 0xdd803d2c, 0xb96046d2, + 0x2c109247, 0xe141625c, 0x7431b6c9, 0x10d1cd37, 0x85a119a2, + 0xd9113acb, 0x4c61ee5e, 0x288195a0, 0xbdf14135, 0x91e1d372, + 0x049107e7, 0x60717c19, 0xf501a88c, 0xa9b18be5, 0x3cc15f70, + 0x5821248e, 0xcd51f01b, 0x19f3c2f9, 0x8c83166c, 0xe8636d92, + 0x7d13b907, 0x21a39a6e, 0xb4d34efb, 0xd0333505, 0x4543e190, + 0x695373d7, 0xfc23a742, 0x98c3dcbc, 0x0db30829, 0x51032b40, + 0xc473ffd5, 0xa093842b, 0x35e350be, 0xf8b2a0a5, 0x6dc27430, + 0x09220fce, 0x9c52db5b, 0xc0e2f832, 0x55922ca7, 0x31725759, + 0xa40283cc, 0x8812118b, 0x1d62c51e, 0x7982bee0, 0xecf26a75, + 0xb042491c, 0x25329d89, 0x41d2e677, 0xd4a232e2, 0x33e785f2, + 0xa6975167, 0xc2772a99, 0x5707fe0c, 0x0bb7dd65, 0x9ec709f0, + 0xfa27720e, 0x6f57a69b, 0x434734dc, 0xd637e049, 0xb2d79bb7, + 0x27a74f22, 0x7b176c4b, 0xee67b8de, 0x8a87c320, 0x1ff717b5, + 0xd2a6e7ae, 0x47d6333b, 0x233648c5, 0xb6469c50, 0xeaf6bf39, + 0x7f866bac, 0x1b661052, 0x8e16c4c7, 0xa2065680, 0x37768215, + 0x5396f9eb, 0xc6e62d7e, 0x9a560e17, 0x0f26da82, 0x6bc6a17c, + 0xfeb675e9, 0x2a14470b, 0xbf64939e, 0xdb84e860, 0x4ef43cf5, + 0x12441f9c, 0x8734cb09, 0xe3d4b0f7, 0x76a46462, 0x5ab4f625, + 0xcfc422b0, 0xab24594e, 0x3e548ddb, 0x62e4aeb2, 0xf7947a27, + 0x937401d9, 0x0604d54c, 0xcb552557, 0x5e25f1c2, 0x3ac58a3c, + 0xafb55ea9, 0xf3057dc0, 0x6675a955, 0x0295d2ab, 0x97e5063e, + 0xbbf59479, 0x2e8540ec, 0x4a653b12, 0xdf15ef87, 0x83a5ccee, + 0x16d5187b, 0x72356385, 0xe745b710, 0x67cf0be4, 0xf2bfdf71, + 0x965fa48f, 0x032f701a, 0x5f9f5373, 0xcaef87e6, 0xae0ffc18, + 0x3b7f288d, 0x176fbaca, 0x821f6e5f, 0xe6ff15a1, 0x738fc134, + 0x2f3fe25d, 0xba4f36c8, 0xdeaf4d36, 0x4bdf99a3, 0x868e69b8, + 0x13febd2d, 0x771ec6d3, 0xe26e1246, 0xbede312f, 0x2baee5ba, + 0x4f4e9e44, 0xda3e4ad1, 0xf62ed896, 0x635e0c03, 0x07be77fd, + 0x92cea368, 0xce7e8001, 0x5b0e5494, 0x3fee2f6a, 0xaa9efbff, + 0x7e3cc91d, 0xeb4c1d88, 0x8fac6676, 0x1adcb2e3, 0x466c918a, + 0xd31c451f, 0xb7fc3ee1, 0x228cea74, 0x0e9c7833, 0x9becaca6, + 0xff0cd758, 0x6a7c03cd, 0x36cc20a4, 0xa3bcf431, 0xc75c8fcf, + 0x522c5b5a, 0x9f7dab41, 0x0a0d7fd4, 0x6eed042a, 0xfb9dd0bf, + 0xa72df3d6, 0x325d2743, 0x56bd5cbd, 0xc3cd8828, 0xefdd1a6f, + 0x7aadcefa, 0x1e4db504, 0x8b3d6191, 0xd78d42f8, 0x42fd966d, + 0x261ded93, 0xb36d3906, 0x54288e16, 0xc1585a83, 0xa5b8217d, + 0x30c8f5e8, 0x6c78d681, 0xf9080214, 0x9de879ea, 0x0898ad7f, + 0x24883f38, 0xb1f8ebad, 0xd5189053, 0x406844c6, 0x1cd867af, + 0x89a8b33a, 0xed48c8c4, 0x78381c51, 0xb569ec4a, 0x201938df, + 0x44f94321, 0xd18997b4, 0x8d39b4dd, 0x18496048, 0x7ca91bb6, + 0xe9d9cf23, 0xc5c95d64, 0x50b989f1, 0x3459f20f, 0xa129269a, + 0xfd9905f3, 0x68e9d166, 0x0c09aa98, 0x99797e0d, 0x4ddb4cef, + 0xd8ab987a, 0xbc4be384, 0x293b3711, 0x758b1478, 0xe0fbc0ed, + 0x841bbb13, 0x116b6f86, 0x3d7bfdc1, 0xa80b2954, 0xcceb52aa, + 0x599b863f, 0x052ba556, 0x905b71c3, 0xf4bb0a3d, 0x61cbdea8, + 0xac9a2eb3, 0x39eafa26, 0x5d0a81d8, 0xc87a554d, 0x94ca7624, + 0x01baa2b1, 0x655ad94f, 0xf02a0dda, 0xdc3a9f9d, 0x494a4b08, + 0x2daa30f6, 0xb8dae463, 0xe46ac70a, 0x711a139f, 0x15fa6861, + 0x808abcf4}, + {0x00000000, 0xcf9e17c8, 0x444d29d1, 0x8bd33e19, 0x889a53a2, + 0x4704446a, 0xccd77a73, 0x03496dbb, 0xca45a105, 0x05dbb6cd, + 0x8e0888d4, 0x41969f1c, 0x42dff2a7, 0x8d41e56f, 0x0692db76, + 0xc90cccbe, 0x4ffa444b, 0x80645383, 0x0bb76d9a, 0xc4297a52, + 0xc76017e9, 0x08fe0021, 0x832d3e38, 0x4cb329f0, 0x85bfe54e, + 0x4a21f286, 0xc1f2cc9f, 0x0e6cdb57, 0x0d25b6ec, 0xc2bba124, + 0x49689f3d, 0x86f688f5, 0x9ff48896, 0x506a9f5e, 0xdbb9a147, + 0x1427b68f, 0x176edb34, 0xd8f0ccfc, 0x5323f2e5, 0x9cbde52d, + 0x55b12993, 0x9a2f3e5b, 0x11fc0042, 0xde62178a, 0xdd2b7a31, + 0x12b56df9, 0x996653e0, 0x56f84428, 0xd00eccdd, 0x1f90db15, + 0x9443e50c, 0x5bddf2c4, 0x58949f7f, 0x970a88b7, 0x1cd9b6ae, + 0xd347a166, 0x1a4b6dd8, 0xd5d57a10, 0x5e064409, 0x919853c1, + 0x92d13e7a, 0x5d4f29b2, 0xd69c17ab, 0x19020063, 0xe498176d, + 0x2b0600a5, 0xa0d53ebc, 0x6f4b2974, 0x6c0244cf, 0xa39c5307, + 0x284f6d1e, 0xe7d17ad6, 0x2eddb668, 0xe143a1a0, 0x6a909fb9, + 0xa50e8871, 0xa647e5ca, 0x69d9f202, 0xe20acc1b, 0x2d94dbd3, + 0xab625326, 0x64fc44ee, 0xef2f7af7, 0x20b16d3f, 0x23f80084, + 0xec66174c, 0x67b52955, 0xa82b3e9d, 0x6127f223, 0xaeb9e5eb, + 0x256adbf2, 0xeaf4cc3a, 0xe9bda181, 0x2623b649, 0xadf08850, + 0x626e9f98, 0x7b6c9ffb, 0xb4f28833, 0x3f21b62a, 0xf0bfa1e2, + 0xf3f6cc59, 0x3c68db91, 0xb7bbe588, 0x7825f240, 0xb1293efe, + 0x7eb72936, 0xf564172f, 0x3afa00e7, 0x39b36d5c, 0xf62d7a94, + 0x7dfe448d, 0xb2605345, 0x3496dbb0, 0xfb08cc78, 0x70dbf261, + 0xbf45e5a9, 0xbc0c8812, 0x73929fda, 0xf841a1c3, 0x37dfb60b, + 0xfed37ab5, 0x314d6d7d, 0xba9e5364, 0x750044ac, 0x76492917, + 0xb9d73edf, 0x320400c6, 0xfd9a170e, 0x1241289b, 0xdddf3f53, + 0x560c014a, 0x99921682, 0x9adb7b39, 0x55456cf1, 0xde9652e8, + 0x11084520, 0xd804899e, 0x179a9e56, 0x9c49a04f, 0x53d7b787, + 0x509eda3c, 0x9f00cdf4, 0x14d3f3ed, 0xdb4de425, 0x5dbb6cd0, + 0x92257b18, 0x19f64501, 0xd66852c9, 0xd5213f72, 0x1abf28ba, + 0x916c16a3, 0x5ef2016b, 0x97fecdd5, 0x5860da1d, 0xd3b3e404, + 0x1c2df3cc, 0x1f649e77, 0xd0fa89bf, 0x5b29b7a6, 0x94b7a06e, + 0x8db5a00d, 0x422bb7c5, 0xc9f889dc, 0x06669e14, 0x052ff3af, + 0xcab1e467, 0x4162da7e, 0x8efccdb6, 0x47f00108, 0x886e16c0, + 0x03bd28d9, 0xcc233f11, 0xcf6a52aa, 0x00f44562, 0x8b277b7b, + 0x44b96cb3, 0xc24fe446, 0x0dd1f38e, 0x8602cd97, 0x499cda5f, + 0x4ad5b7e4, 0x854ba02c, 0x0e989e35, 0xc10689fd, 0x080a4543, + 0xc794528b, 0x4c476c92, 0x83d97b5a, 0x809016e1, 0x4f0e0129, + 0xc4dd3f30, 0x0b4328f8, 0xf6d93ff6, 0x3947283e, 0xb2941627, + 0x7d0a01ef, 0x7e436c54, 0xb1dd7b9c, 0x3a0e4585, 0xf590524d, + 0x3c9c9ef3, 0xf302893b, 0x78d1b722, 0xb74fa0ea, 0xb406cd51, + 0x7b98da99, 0xf04be480, 0x3fd5f348, 0xb9237bbd, 0x76bd6c75, + 0xfd6e526c, 0x32f045a4, 0x31b9281f, 0xfe273fd7, 0x75f401ce, + 0xba6a1606, 0x7366dab8, 0xbcf8cd70, 0x372bf369, 0xf8b5e4a1, + 0xfbfc891a, 0x34629ed2, 0xbfb1a0cb, 0x702fb703, 0x692db760, + 0xa6b3a0a8, 0x2d609eb1, 0xe2fe8979, 0xe1b7e4c2, 0x2e29f30a, + 0xa5facd13, 0x6a64dadb, 0xa3681665, 0x6cf601ad, 0xe7253fb4, + 0x28bb287c, 0x2bf245c7, 0xe46c520f, 0x6fbf6c16, 0xa0217bde, + 0x26d7f32b, 0xe949e4e3, 0x629adafa, 0xad04cd32, 0xae4da089, + 0x61d3b741, 0xea008958, 0x259e9e90, 0xec92522e, 0x230c45e6, + 0xa8df7bff, 0x67416c37, 0x6408018c, 0xab961644, 0x2045285d, + 0xefdb3f95}, + {0x00000000, 0x24825136, 0x4904a26c, 0x6d86f35a, 0x920944d8, + 0xb68b15ee, 0xdb0de6b4, 0xff8fb782, 0xff638ff1, 0xdbe1dec7, + 0xb6672d9d, 0x92e57cab, 0x6d6acb29, 0x49e89a1f, 0x246e6945, + 0x00ec3873, 0x25b619a3, 0x01344895, 0x6cb2bbcf, 0x4830eaf9, + 0xb7bf5d7b, 0x933d0c4d, 0xfebbff17, 0xda39ae21, 0xdad59652, + 0xfe57c764, 0x93d1343e, 0xb7536508, 0x48dcd28a, 0x6c5e83bc, + 0x01d870e6, 0x255a21d0, 0x4b6c3346, 0x6fee6270, 0x0268912a, + 0x26eac01c, 0xd965779e, 0xfde726a8, 0x9061d5f2, 0xb4e384c4, + 0xb40fbcb7, 0x908ded81, 0xfd0b1edb, 0xd9894fed, 0x2606f86f, + 0x0284a959, 0x6f025a03, 0x4b800b35, 0x6eda2ae5, 0x4a587bd3, + 0x27de8889, 0x035cd9bf, 0xfcd36e3d, 0xd8513f0b, 0xb5d7cc51, + 0x91559d67, 0x91b9a514, 0xb53bf422, 0xd8bd0778, 0xfc3f564e, + 0x03b0e1cc, 0x2732b0fa, 0x4ab443a0, 0x6e361296, 0x96d8668c, + 0xb25a37ba, 0xdfdcc4e0, 0xfb5e95d6, 0x04d12254, 0x20537362, + 0x4dd58038, 0x6957d10e, 0x69bbe97d, 0x4d39b84b, 0x20bf4b11, + 0x043d1a27, 0xfbb2ada5, 0xdf30fc93, 0xb2b60fc9, 0x96345eff, + 0xb36e7f2f, 0x97ec2e19, 0xfa6add43, 0xdee88c75, 0x21673bf7, + 0x05e56ac1, 0x6863999b, 0x4ce1c8ad, 0x4c0df0de, 0x688fa1e8, + 0x050952b2, 0x218b0384, 0xde04b406, 0xfa86e530, 0x9700166a, + 0xb382475c, 0xddb455ca, 0xf93604fc, 0x94b0f7a6, 0xb032a690, + 0x4fbd1112, 0x6b3f4024, 0x06b9b37e, 0x223be248, 0x22d7da3b, + 0x06558b0d, 0x6bd37857, 0x4f512961, 0xb0de9ee3, 0x945ccfd5, + 0xf9da3c8f, 0xdd586db9, 0xf8024c69, 0xdc801d5f, 0xb106ee05, + 0x9584bf33, 0x6a0b08b1, 0x4e895987, 0x230faadd, 0x078dfbeb, + 0x0761c398, 0x23e392ae, 0x4e6561f4, 0x6ae730c2, 0x95688740, + 0xb1ead676, 0xdc6c252c, 0xf8ee741a, 0xf6c1cb59, 0xd2439a6f, + 0xbfc56935, 0x9b473803, 0x64c88f81, 0x404adeb7, 0x2dcc2ded, + 0x094e7cdb, 0x09a244a8, 0x2d20159e, 0x40a6e6c4, 0x6424b7f2, + 0x9bab0070, 0xbf295146, 0xd2afa21c, 0xf62df32a, 0xd377d2fa, + 0xf7f583cc, 0x9a737096, 0xbef121a0, 0x417e9622, 0x65fcc714, + 0x087a344e, 0x2cf86578, 0x2c145d0b, 0x08960c3d, 0x6510ff67, + 0x4192ae51, 0xbe1d19d3, 0x9a9f48e5, 0xf719bbbf, 0xd39bea89, + 0xbdadf81f, 0x992fa929, 0xf4a95a73, 0xd02b0b45, 0x2fa4bcc7, + 0x0b26edf1, 0x66a01eab, 0x42224f9d, 0x42ce77ee, 0x664c26d8, + 0x0bcad582, 0x2f4884b4, 0xd0c73336, 0xf4456200, 0x99c3915a, + 0xbd41c06c, 0x981be1bc, 0xbc99b08a, 0xd11f43d0, 0xf59d12e6, + 0x0a12a564, 0x2e90f452, 0x43160708, 0x6794563e, 0x67786e4d, + 0x43fa3f7b, 0x2e7ccc21, 0x0afe9d17, 0xf5712a95, 0xd1f37ba3, + 0xbc7588f9, 0x98f7d9cf, 0x6019add5, 0x449bfce3, 0x291d0fb9, + 0x0d9f5e8f, 0xf210e90d, 0xd692b83b, 0xbb144b61, 0x9f961a57, + 0x9f7a2224, 0xbbf87312, 0xd67e8048, 0xf2fcd17e, 0x0d7366fc, + 0x29f137ca, 0x4477c490, 0x60f595a6, 0x45afb476, 0x612de540, + 0x0cab161a, 0x2829472c, 0xd7a6f0ae, 0xf324a198, 0x9ea252c2, + 0xba2003f4, 0xbacc3b87, 0x9e4e6ab1, 0xf3c899eb, 0xd74ac8dd, + 0x28c57f5f, 0x0c472e69, 0x61c1dd33, 0x45438c05, 0x2b759e93, + 0x0ff7cfa5, 0x62713cff, 0x46f36dc9, 0xb97cda4b, 0x9dfe8b7d, + 0xf0787827, 0xd4fa2911, 0xd4161162, 0xf0944054, 0x9d12b30e, + 0xb990e238, 0x461f55ba, 0x629d048c, 0x0f1bf7d6, 0x2b99a6e0, + 0x0ec38730, 0x2a41d606, 0x47c7255c, 0x6345746a, 0x9ccac3e8, + 0xb84892de, 0xd5ce6184, 0xf14c30b2, 0xf1a008c1, 0xd52259f7, + 0xb8a4aaad, 0x9c26fb9b, 0x63a94c19, 0x472b1d2f, 0x2aadee75, + 0x0e2fbf43}, + {0x00000000, 0x36f290f3, 0x6de521e6, 0x5b17b115, 0xdbca43cc, + 0xed38d33f, 0xb62f622a, 0x80ddf2d9, 0x6ce581d9, 0x5a17112a, + 0x0100a03f, 0x37f230cc, 0xb72fc215, 0x81dd52e6, 0xdacae3f3, + 0xec387300, 0xd9cb03b2, 0xef399341, 0xb42e2254, 0x82dcb2a7, + 0x0201407e, 0x34f3d08d, 0x6fe46198, 0x5916f16b, 0xb52e826b, + 0x83dc1298, 0xd8cba38d, 0xee39337e, 0x6ee4c1a7, 0x58165154, + 0x0301e041, 0x35f370b2, 0x68e70125, 0x5e1591d6, 0x050220c3, + 0x33f0b030, 0xb32d42e9, 0x85dfd21a, 0xdec8630f, 0xe83af3fc, + 0x040280fc, 0x32f0100f, 0x69e7a11a, 0x5f1531e9, 0xdfc8c330, + 0xe93a53c3, 0xb22de2d6, 0x84df7225, 0xb12c0297, 0x87de9264, + 0xdcc92371, 0xea3bb382, 0x6ae6415b, 0x5c14d1a8, 0x070360bd, + 0x31f1f04e, 0xddc9834e, 0xeb3b13bd, 0xb02ca2a8, 0x86de325b, + 0x0603c082, 0x30f15071, 0x6be6e164, 0x5d147197, 0xd1ce024a, + 0xe73c92b9, 0xbc2b23ac, 0x8ad9b35f, 0x0a044186, 0x3cf6d175, + 0x67e16060, 0x5113f093, 0xbd2b8393, 0x8bd91360, 0xd0cea275, + 0xe63c3286, 0x66e1c05f, 0x501350ac, 0x0b04e1b9, 0x3df6714a, + 0x080501f8, 0x3ef7910b, 0x65e0201e, 0x5312b0ed, 0xd3cf4234, + 0xe53dd2c7, 0xbe2a63d2, 0x88d8f321, 0x64e08021, 0x521210d2, + 0x0905a1c7, 0x3ff73134, 0xbf2ac3ed, 0x89d8531e, 0xd2cfe20b, + 0xe43d72f8, 0xb929036f, 0x8fdb939c, 0xd4cc2289, 0xe23eb27a, + 0x62e340a3, 0x5411d050, 0x0f066145, 0x39f4f1b6, 0xd5cc82b6, + 0xe33e1245, 0xb829a350, 0x8edb33a3, 0x0e06c17a, 0x38f45189, + 0x63e3e09c, 0x5511706f, 0x60e200dd, 0x5610902e, 0x0d07213b, + 0x3bf5b1c8, 0xbb284311, 0x8ddad3e2, 0xd6cd62f7, 0xe03ff204, + 0x0c078104, 0x3af511f7, 0x61e2a0e2, 0x57103011, 0xd7cdc2c8, + 0xe13f523b, 0xba28e32e, 0x8cda73dd, 0x78ed02d5, 0x4e1f9226, + 0x15082333, 0x23fab3c0, 0xa3274119, 0x95d5d1ea, 0xcec260ff, + 0xf830f00c, 0x1408830c, 0x22fa13ff, 0x79eda2ea, 0x4f1f3219, + 0xcfc2c0c0, 0xf9305033, 0xa227e126, 0x94d571d5, 0xa1260167, + 0x97d49194, 0xccc32081, 0xfa31b072, 0x7aec42ab, 0x4c1ed258, + 0x1709634d, 0x21fbf3be, 0xcdc380be, 0xfb31104d, 0xa026a158, + 0x96d431ab, 0x1609c372, 0x20fb5381, 0x7bece294, 0x4d1e7267, + 0x100a03f0, 0x26f89303, 0x7def2216, 0x4b1db2e5, 0xcbc0403c, + 0xfd32d0cf, 0xa62561da, 0x90d7f129, 0x7cef8229, 0x4a1d12da, + 0x110aa3cf, 0x27f8333c, 0xa725c1e5, 0x91d75116, 0xcac0e003, + 0xfc3270f0, 0xc9c10042, 0xff3390b1, 0xa42421a4, 0x92d6b157, + 0x120b438e, 0x24f9d37d, 0x7fee6268, 0x491cf29b, 0xa524819b, + 0x93d61168, 0xc8c1a07d, 0xfe33308e, 0x7eeec257, 0x481c52a4, + 0x130be3b1, 0x25f97342, 0xa923009f, 0x9fd1906c, 0xc4c62179, + 0xf234b18a, 0x72e94353, 0x441bd3a0, 0x1f0c62b5, 0x29fef246, + 0xc5c68146, 0xf33411b5, 0xa823a0a0, 0x9ed13053, 0x1e0cc28a, + 0x28fe5279, 0x73e9e36c, 0x451b739f, 0x70e8032d, 0x461a93de, + 0x1d0d22cb, 0x2bffb238, 0xab2240e1, 0x9dd0d012, 0xc6c76107, + 0xf035f1f4, 0x1c0d82f4, 0x2aff1207, 0x71e8a312, 0x471a33e1, + 0xc7c7c138, 0xf13551cb, 0xaa22e0de, 0x9cd0702d, 0xc1c401ba, + 0xf7369149, 0xac21205c, 0x9ad3b0af, 0x1a0e4276, 0x2cfcd285, + 0x77eb6390, 0x4119f363, 0xad218063, 0x9bd31090, 0xc0c4a185, + 0xf6363176, 0x76ebc3af, 0x4019535c, 0x1b0ee249, 0x2dfc72ba, + 0x180f0208, 0x2efd92fb, 0x75ea23ee, 0x4318b31d, 0xc3c541c4, + 0xf537d137, 0xae206022, 0x98d2f0d1, 0x74ea83d1, 0x42181322, + 0x190fa237, 0x2ffd32c4, 0xaf20c01d, 0x99d250ee, 0xc2c5e1fb, + 0xf4377108}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0xf390f23600000000, 0xe621e56d00000000, + 0x15b1175b00000000, 0xcc43cadb00000000, 0x3fd338ed00000000, + 0x2a622fb600000000, 0xd9f2dd8000000000, 0xd981e56c00000000, + 0x2a11175a00000000, 0x3fa0000100000000, 0xcc30f23700000000, + 0x15c22fb700000000, 0xe652dd8100000000, 0xf3e3cada00000000, + 0x007338ec00000000, 0xb203cbd900000000, 0x419339ef00000000, + 0x54222eb400000000, 0xa7b2dc8200000000, 0x7e40010200000000, + 0x8dd0f33400000000, 0x9861e46f00000000, 0x6bf1165900000000, + 0x6b822eb500000000, 0x9812dc8300000000, 0x8da3cbd800000000, + 0x7e3339ee00000000, 0xa7c1e46e00000000, 0x5451165800000000, + 0x41e0010300000000, 0xb270f33500000000, 0x2501e76800000000, + 0xd691155e00000000, 0xc320020500000000, 0x30b0f03300000000, + 0xe9422db300000000, 0x1ad2df8500000000, 0x0f63c8de00000000, + 0xfcf33ae800000000, 0xfc80020400000000, 0x0f10f03200000000, + 0x1aa1e76900000000, 0xe931155f00000000, 0x30c3c8df00000000, + 0xc3533ae900000000, 0xd6e22db200000000, 0x2572df8400000000, + 0x97022cb100000000, 0x6492de8700000000, 0x7123c9dc00000000, + 0x82b33bea00000000, 0x5b41e66a00000000, 0xa8d1145c00000000, + 0xbd60030700000000, 0x4ef0f13100000000, 0x4e83c9dd00000000, + 0xbd133beb00000000, 0xa8a22cb000000000, 0x5b32de8600000000, + 0x82c0030600000000, 0x7150f13000000000, 0x64e1e66b00000000, + 0x9771145d00000000, 0x4a02ced100000000, 0xb9923ce700000000, + 0xac232bbc00000000, 0x5fb3d98a00000000, 0x8641040a00000000, + 0x75d1f63c00000000, 0x6060e16700000000, 0x93f0135100000000, + 0x93832bbd00000000, 0x6013d98b00000000, 0x75a2ced000000000, + 0x86323ce600000000, 0x5fc0e16600000000, 0xac50135000000000, + 0xb9e1040b00000000, 0x4a71f63d00000000, 0xf801050800000000, + 0x0b91f73e00000000, 0x1e20e06500000000, 0xedb0125300000000, + 0x3442cfd300000000, 0xc7d23de500000000, 0xd2632abe00000000, + 0x21f3d88800000000, 0x2180e06400000000, 0xd210125200000000, + 0xc7a1050900000000, 0x3431f73f00000000, 0xedc32abf00000000, + 0x1e53d88900000000, 0x0be2cfd200000000, 0xf8723de400000000, + 0x6f0329b900000000, 0x9c93db8f00000000, 0x8922ccd400000000, + 0x7ab23ee200000000, 0xa340e36200000000, 0x50d0115400000000, + 0x4561060f00000000, 0xb6f1f43900000000, 0xb682ccd500000000, + 0x45123ee300000000, 0x50a329b800000000, 0xa333db8e00000000, + 0x7ac1060e00000000, 0x8951f43800000000, 0x9ce0e36300000000, + 0x6f70115500000000, 0xdd00e26000000000, 0x2e90105600000000, + 0x3b21070d00000000, 0xc8b1f53b00000000, 0x114328bb00000000, + 0xe2d3da8d00000000, 0xf762cdd600000000, 0x04f23fe000000000, + 0x0481070c00000000, 0xf711f53a00000000, 0xe2a0e26100000000, + 0x1130105700000000, 0xc8c2cdd700000000, 0x3b523fe100000000, + 0x2ee328ba00000000, 0xdd73da8c00000000, 0xd502ed7800000000, + 0x26921f4e00000000, 0x3323081500000000, 0xc0b3fa2300000000, + 0x194127a300000000, 0xead1d59500000000, 0xff60c2ce00000000, + 0x0cf030f800000000, 0x0c83081400000000, 0xff13fa2200000000, + 0xeaa2ed7900000000, 0x19321f4f00000000, 0xc0c0c2cf00000000, + 0x335030f900000000, 0x26e127a200000000, 0xd571d59400000000, + 0x670126a100000000, 0x9491d49700000000, 0x8120c3cc00000000, + 0x72b031fa00000000, 0xab42ec7a00000000, 0x58d21e4c00000000, + 0x4d63091700000000, 0xbef3fb2100000000, 0xbe80c3cd00000000, + 0x4d1031fb00000000, 0x58a126a000000000, 0xab31d49600000000, + 0x72c3091600000000, 0x8153fb2000000000, 0x94e2ec7b00000000, + 0x67721e4d00000000, 0xf0030a1000000000, 0x0393f82600000000, + 0x1622ef7d00000000, 0xe5b21d4b00000000, 0x3c40c0cb00000000, + 0xcfd032fd00000000, 0xda6125a600000000, 0x29f1d79000000000, + 0x2982ef7c00000000, 0xda121d4a00000000, 0xcfa30a1100000000, + 0x3c33f82700000000, 0xe5c125a700000000, 0x1651d79100000000, + 0x03e0c0ca00000000, 0xf07032fc00000000, 0x4200c1c900000000, + 0xb19033ff00000000, 0xa42124a400000000, 0x57b1d69200000000, + 0x8e430b1200000000, 0x7dd3f92400000000, 0x6862ee7f00000000, + 0x9bf21c4900000000, 0x9b8124a500000000, 0x6811d69300000000, + 0x7da0c1c800000000, 0x8e3033fe00000000, 0x57c2ee7e00000000, + 0xa4521c4800000000, 0xb1e30b1300000000, 0x4273f92500000000, + 0x9f0023a900000000, 0x6c90d19f00000000, 0x7921c6c400000000, + 0x8ab134f200000000, 0x5343e97200000000, 0xa0d31b4400000000, + 0xb5620c1f00000000, 0x46f2fe2900000000, 0x4681c6c500000000, + 0xb51134f300000000, 0xa0a023a800000000, 0x5330d19e00000000, + 0x8ac20c1e00000000, 0x7952fe2800000000, 0x6ce3e97300000000, + 0x9f731b4500000000, 0x2d03e87000000000, 0xde931a4600000000, + 0xcb220d1d00000000, 0x38b2ff2b00000000, 0xe14022ab00000000, + 0x12d0d09d00000000, 0x0761c7c600000000, 0xf4f135f000000000, + 0xf4820d1c00000000, 0x0712ff2a00000000, 0x12a3e87100000000, + 0xe1331a4700000000, 0x38c1c7c700000000, 0xcb5135f100000000, + 0xdee022aa00000000, 0x2d70d09c00000000, 0xba01c4c100000000, + 0x499136f700000000, 0x5c2021ac00000000, 0xafb0d39a00000000, + 0x76420e1a00000000, 0x85d2fc2c00000000, 0x9063eb7700000000, + 0x63f3194100000000, 0x638021ad00000000, 0x9010d39b00000000, + 0x85a1c4c000000000, 0x763136f600000000, 0xafc3eb7600000000, + 0x5c53194000000000, 0x49e20e1b00000000, 0xba72fc2d00000000, + 0x08020f1800000000, 0xfb92fd2e00000000, 0xee23ea7500000000, + 0x1db3184300000000, 0xc441c5c300000000, 0x37d137f500000000, + 0x226020ae00000000, 0xd1f0d29800000000, 0xd183ea7400000000, + 0x2213184200000000, 0x37a20f1900000000, 0xc432fd2f00000000, + 0x1dc020af00000000, 0xee50d29900000000, 0xfbe1c5c200000000, + 0x087137f400000000}, + {0x0000000000000000, 0x3651822400000000, 0x6ca2044900000000, + 0x5af3866d00000000, 0xd844099200000000, 0xee158bb600000000, + 0xb4e60ddb00000000, 0x82b78fff00000000, 0xf18f63ff00000000, + 0xc7dee1db00000000, 0x9d2d67b600000000, 0xab7ce59200000000, + 0x29cb6a6d00000000, 0x1f9ae84900000000, 0x45696e2400000000, + 0x7338ec0000000000, 0xa319b62500000000, 0x9548340100000000, + 0xcfbbb26c00000000, 0xf9ea304800000000, 0x7b5dbfb700000000, + 0x4d0c3d9300000000, 0x17ffbbfe00000000, 0x21ae39da00000000, + 0x5296d5da00000000, 0x64c757fe00000000, 0x3e34d19300000000, + 0x086553b700000000, 0x8ad2dc4800000000, 0xbc835e6c00000000, + 0xe670d80100000000, 0xd0215a2500000000, 0x46336c4b00000000, + 0x7062ee6f00000000, 0x2a91680200000000, 0x1cc0ea2600000000, + 0x9e7765d900000000, 0xa826e7fd00000000, 0xf2d5619000000000, + 0xc484e3b400000000, 0xb7bc0fb400000000, 0x81ed8d9000000000, + 0xdb1e0bfd00000000, 0xed4f89d900000000, 0x6ff8062600000000, + 0x59a9840200000000, 0x035a026f00000000, 0x350b804b00000000, + 0xe52ada6e00000000, 0xd37b584a00000000, 0x8988de2700000000, + 0xbfd95c0300000000, 0x3d6ed3fc00000000, 0x0b3f51d800000000, + 0x51ccd7b500000000, 0x679d559100000000, 0x14a5b99100000000, + 0x22f43bb500000000, 0x7807bdd800000000, 0x4e563ffc00000000, + 0xcce1b00300000000, 0xfab0322700000000, 0xa043b44a00000000, + 0x9612366e00000000, 0x8c66d89600000000, 0xba375ab200000000, + 0xe0c4dcdf00000000, 0xd6955efb00000000, 0x5422d10400000000, + 0x6273532000000000, 0x3880d54d00000000, 0x0ed1576900000000, + 0x7de9bb6900000000, 0x4bb8394d00000000, 0x114bbf2000000000, + 0x271a3d0400000000, 0xa5adb2fb00000000, 0x93fc30df00000000, + 0xc90fb6b200000000, 0xff5e349600000000, 0x2f7f6eb300000000, + 0x192eec9700000000, 0x43dd6afa00000000, 0x758ce8de00000000, + 0xf73b672100000000, 0xc16ae50500000000, 0x9b99636800000000, + 0xadc8e14c00000000, 0xdef00d4c00000000, 0xe8a18f6800000000, + 0xb252090500000000, 0x84038b2100000000, 0x06b404de00000000, + 0x30e586fa00000000, 0x6a16009700000000, 0x5c4782b300000000, + 0xca55b4dd00000000, 0xfc0436f900000000, 0xa6f7b09400000000, + 0x90a632b000000000, 0x1211bd4f00000000, 0x24403f6b00000000, + 0x7eb3b90600000000, 0x48e23b2200000000, 0x3bdad72200000000, + 0x0d8b550600000000, 0x5778d36b00000000, 0x6129514f00000000, + 0xe39edeb000000000, 0xd5cf5c9400000000, 0x8f3cdaf900000000, + 0xb96d58dd00000000, 0x694c02f800000000, 0x5f1d80dc00000000, + 0x05ee06b100000000, 0x33bf849500000000, 0xb1080b6a00000000, + 0x8759894e00000000, 0xddaa0f2300000000, 0xebfb8d0700000000, + 0x98c3610700000000, 0xae92e32300000000, 0xf461654e00000000, + 0xc230e76a00000000, 0x4087689500000000, 0x76d6eab100000000, + 0x2c256cdc00000000, 0x1a74eef800000000, 0x59cbc1f600000000, + 0x6f9a43d200000000, 0x3569c5bf00000000, 0x0338479b00000000, + 0x818fc86400000000, 0xb7de4a4000000000, 0xed2dcc2d00000000, + 0xdb7c4e0900000000, 0xa844a20900000000, 0x9e15202d00000000, + 0xc4e6a64000000000, 0xf2b7246400000000, 0x7000ab9b00000000, + 0x465129bf00000000, 0x1ca2afd200000000, 0x2af32df600000000, + 0xfad277d300000000, 0xcc83f5f700000000, 0x9670739a00000000, + 0xa021f1be00000000, 0x22967e4100000000, 0x14c7fc6500000000, + 0x4e347a0800000000, 0x7865f82c00000000, 0x0b5d142c00000000, + 0x3d0c960800000000, 0x67ff106500000000, 0x51ae924100000000, + 0xd3191dbe00000000, 0xe5489f9a00000000, 0xbfbb19f700000000, + 0x89ea9bd300000000, 0x1ff8adbd00000000, 0x29a92f9900000000, + 0x735aa9f400000000, 0x450b2bd000000000, 0xc7bca42f00000000, + 0xf1ed260b00000000, 0xab1ea06600000000, 0x9d4f224200000000, + 0xee77ce4200000000, 0xd8264c6600000000, 0x82d5ca0b00000000, + 0xb484482f00000000, 0x3633c7d000000000, 0x006245f400000000, + 0x5a91c39900000000, 0x6cc041bd00000000, 0xbce11b9800000000, + 0x8ab099bc00000000, 0xd0431fd100000000, 0xe6129df500000000, + 0x64a5120a00000000, 0x52f4902e00000000, 0x0807164300000000, + 0x3e56946700000000, 0x4d6e786700000000, 0x7b3ffa4300000000, + 0x21cc7c2e00000000, 0x179dfe0a00000000, 0x952a71f500000000, + 0xa37bf3d100000000, 0xf98875bc00000000, 0xcfd9f79800000000, + 0xd5ad196000000000, 0xe3fc9b4400000000, 0xb90f1d2900000000, + 0x8f5e9f0d00000000, 0x0de910f200000000, 0x3bb892d600000000, + 0x614b14bb00000000, 0x571a969f00000000, 0x24227a9f00000000, + 0x1273f8bb00000000, 0x48807ed600000000, 0x7ed1fcf200000000, + 0xfc66730d00000000, 0xca37f12900000000, 0x90c4774400000000, + 0xa695f56000000000, 0x76b4af4500000000, 0x40e52d6100000000, + 0x1a16ab0c00000000, 0x2c47292800000000, 0xaef0a6d700000000, + 0x98a124f300000000, 0xc252a29e00000000, 0xf40320ba00000000, + 0x873bccba00000000, 0xb16a4e9e00000000, 0xeb99c8f300000000, + 0xddc84ad700000000, 0x5f7fc52800000000, 0x692e470c00000000, + 0x33ddc16100000000, 0x058c434500000000, 0x939e752b00000000, + 0xa5cff70f00000000, 0xff3c716200000000, 0xc96df34600000000, + 0x4bda7cb900000000, 0x7d8bfe9d00000000, 0x277878f000000000, + 0x1129fad400000000, 0x621116d400000000, 0x544094f000000000, + 0x0eb3129d00000000, 0x38e290b900000000, 0xba551f4600000000, + 0x8c049d6200000000, 0xd6f71b0f00000000, 0xe0a6992b00000000, + 0x3087c30e00000000, 0x06d6412a00000000, 0x5c25c74700000000, + 0x6a74456300000000, 0xe8c3ca9c00000000, 0xde9248b800000000, + 0x8461ced500000000, 0xb2304cf100000000, 0xc108a0f100000000, + 0xf75922d500000000, 0xadaaa4b800000000, 0x9bfb269c00000000, + 0x194ca96300000000, 0x2f1d2b4700000000, 0x75eead2a00000000, + 0x43bf2f0e00000000}, + {0x0000000000000000, 0xc8179ecf00000000, 0xd1294d4400000000, + 0x193ed38b00000000, 0xa2539a8800000000, 0x6a44044700000000, + 0x737ad7cc00000000, 0xbb6d490300000000, 0x05a145ca00000000, + 0xcdb6db0500000000, 0xd488088e00000000, 0x1c9f964100000000, + 0xa7f2df4200000000, 0x6fe5418d00000000, 0x76db920600000000, + 0xbecc0cc900000000, 0x4b44fa4f00000000, 0x8353648000000000, + 0x9a6db70b00000000, 0x527a29c400000000, 0xe91760c700000000, + 0x2100fe0800000000, 0x383e2d8300000000, 0xf029b34c00000000, + 0x4ee5bf8500000000, 0x86f2214a00000000, 0x9fccf2c100000000, + 0x57db6c0e00000000, 0xecb6250d00000000, 0x24a1bbc200000000, + 0x3d9f684900000000, 0xf588f68600000000, 0x9688f49f00000000, + 0x5e9f6a5000000000, 0x47a1b9db00000000, 0x8fb6271400000000, + 0x34db6e1700000000, 0xfcccf0d800000000, 0xe5f2235300000000, + 0x2de5bd9c00000000, 0x9329b15500000000, 0x5b3e2f9a00000000, + 0x4200fc1100000000, 0x8a1762de00000000, 0x317a2bdd00000000, + 0xf96db51200000000, 0xe053669900000000, 0x2844f85600000000, + 0xddcc0ed000000000, 0x15db901f00000000, 0x0ce5439400000000, + 0xc4f2dd5b00000000, 0x7f9f945800000000, 0xb7880a9700000000, + 0xaeb6d91c00000000, 0x66a147d300000000, 0xd86d4b1a00000000, + 0x107ad5d500000000, 0x0944065e00000000, 0xc153989100000000, + 0x7a3ed19200000000, 0xb2294f5d00000000, 0xab179cd600000000, + 0x6300021900000000, 0x6d1798e400000000, 0xa500062b00000000, + 0xbc3ed5a000000000, 0x74294b6f00000000, 0xcf44026c00000000, + 0x07539ca300000000, 0x1e6d4f2800000000, 0xd67ad1e700000000, + 0x68b6dd2e00000000, 0xa0a143e100000000, 0xb99f906a00000000, + 0x71880ea500000000, 0xcae547a600000000, 0x02f2d96900000000, + 0x1bcc0ae200000000, 0xd3db942d00000000, 0x265362ab00000000, + 0xee44fc6400000000, 0xf77a2fef00000000, 0x3f6db12000000000, + 0x8400f82300000000, 0x4c1766ec00000000, 0x5529b56700000000, + 0x9d3e2ba800000000, 0x23f2276100000000, 0xebe5b9ae00000000, + 0xf2db6a2500000000, 0x3accf4ea00000000, 0x81a1bde900000000, + 0x49b6232600000000, 0x5088f0ad00000000, 0x989f6e6200000000, + 0xfb9f6c7b00000000, 0x3388f2b400000000, 0x2ab6213f00000000, + 0xe2a1bff000000000, 0x59ccf6f300000000, 0x91db683c00000000, + 0x88e5bbb700000000, 0x40f2257800000000, 0xfe3e29b100000000, + 0x3629b77e00000000, 0x2f1764f500000000, 0xe700fa3a00000000, + 0x5c6db33900000000, 0x947a2df600000000, 0x8d44fe7d00000000, + 0x455360b200000000, 0xb0db963400000000, 0x78cc08fb00000000, + 0x61f2db7000000000, 0xa9e545bf00000000, 0x12880cbc00000000, + 0xda9f927300000000, 0xc3a141f800000000, 0x0bb6df3700000000, + 0xb57ad3fe00000000, 0x7d6d4d3100000000, 0x64539eba00000000, + 0xac44007500000000, 0x1729497600000000, 0xdf3ed7b900000000, + 0xc600043200000000, 0x0e179afd00000000, 0x9b28411200000000, + 0x533fdfdd00000000, 0x4a010c5600000000, 0x8216929900000000, + 0x397bdb9a00000000, 0xf16c455500000000, 0xe85296de00000000, + 0x2045081100000000, 0x9e8904d800000000, 0x569e9a1700000000, + 0x4fa0499c00000000, 0x87b7d75300000000, 0x3cda9e5000000000, + 0xf4cd009f00000000, 0xedf3d31400000000, 0x25e44ddb00000000, + 0xd06cbb5d00000000, 0x187b259200000000, 0x0145f61900000000, + 0xc95268d600000000, 0x723f21d500000000, 0xba28bf1a00000000, + 0xa3166c9100000000, 0x6b01f25e00000000, 0xd5cdfe9700000000, + 0x1dda605800000000, 0x04e4b3d300000000, 0xccf32d1c00000000, + 0x779e641f00000000, 0xbf89fad000000000, 0xa6b7295b00000000, + 0x6ea0b79400000000, 0x0da0b58d00000000, 0xc5b72b4200000000, + 0xdc89f8c900000000, 0x149e660600000000, 0xaff32f0500000000, + 0x67e4b1ca00000000, 0x7eda624100000000, 0xb6cdfc8e00000000, + 0x0801f04700000000, 0xc0166e8800000000, 0xd928bd0300000000, + 0x113f23cc00000000, 0xaa526acf00000000, 0x6245f40000000000, + 0x7b7b278b00000000, 0xb36cb94400000000, 0x46e44fc200000000, + 0x8ef3d10d00000000, 0x97cd028600000000, 0x5fda9c4900000000, + 0xe4b7d54a00000000, 0x2ca04b8500000000, 0x359e980e00000000, + 0xfd8906c100000000, 0x43450a0800000000, 0x8b5294c700000000, + 0x926c474c00000000, 0x5a7bd98300000000, 0xe116908000000000, + 0x29010e4f00000000, 0x303fddc400000000, 0xf828430b00000000, + 0xf63fd9f600000000, 0x3e28473900000000, 0x271694b200000000, + 0xef010a7d00000000, 0x546c437e00000000, 0x9c7bddb100000000, + 0x85450e3a00000000, 0x4d5290f500000000, 0xf39e9c3c00000000, + 0x3b8902f300000000, 0x22b7d17800000000, 0xeaa04fb700000000, + 0x51cd06b400000000, 0x99da987b00000000, 0x80e44bf000000000, + 0x48f3d53f00000000, 0xbd7b23b900000000, 0x756cbd7600000000, + 0x6c526efd00000000, 0xa445f03200000000, 0x1f28b93100000000, + 0xd73f27fe00000000, 0xce01f47500000000, 0x06166aba00000000, + 0xb8da667300000000, 0x70cdf8bc00000000, 0x69f32b3700000000, + 0xa1e4b5f800000000, 0x1a89fcfb00000000, 0xd29e623400000000, + 0xcba0b1bf00000000, 0x03b72f7000000000, 0x60b72d6900000000, + 0xa8a0b3a600000000, 0xb19e602d00000000, 0x7989fee200000000, + 0xc2e4b7e100000000, 0x0af3292e00000000, 0x13cdfaa500000000, + 0xdbda646a00000000, 0x651668a300000000, 0xad01f66c00000000, + 0xb43f25e700000000, 0x7c28bb2800000000, 0xc745f22b00000000, + 0x0f526ce400000000, 0x166cbf6f00000000, 0xde7b21a000000000, + 0x2bf3d72600000000, 0xe3e449e900000000, 0xfada9a6200000000, + 0x32cd04ad00000000, 0x89a04dae00000000, 0x41b7d36100000000, + 0x588900ea00000000, 0x909e9e2500000000, 0x2e5292ec00000000, + 0xe6450c2300000000, 0xff7bdfa800000000, 0x376c416700000000, + 0x8c01086400000000, 0x441696ab00000000, 0x5d28452000000000, + 0x953fdbef00000000}, + {0x0000000000000000, 0x95d4709500000000, 0x6baf90f100000000, + 0xfe7be06400000000, 0x9758503800000000, 0x028c20ad00000000, + 0xfcf7c0c900000000, 0x6923b05c00000000, 0x2eb1a07000000000, + 0xbb65d0e500000000, 0x451e308100000000, 0xd0ca401400000000, + 0xb9e9f04800000000, 0x2c3d80dd00000000, 0xd24660b900000000, + 0x4792102c00000000, 0x5c6241e100000000, 0xc9b6317400000000, + 0x37cdd11000000000, 0xa219a18500000000, 0xcb3a11d900000000, + 0x5eee614c00000000, 0xa095812800000000, 0x3541f1bd00000000, + 0x72d3e19100000000, 0xe707910400000000, 0x197c716000000000, + 0x8ca801f500000000, 0xe58bb1a900000000, 0x705fc13c00000000, + 0x8e24215800000000, 0x1bf051cd00000000, 0xf9c2f31900000000, + 0x6c16838c00000000, 0x926d63e800000000, 0x07b9137d00000000, + 0x6e9aa32100000000, 0xfb4ed3b400000000, 0x053533d000000000, + 0x90e1434500000000, 0xd773536900000000, 0x42a723fc00000000, + 0xbcdcc39800000000, 0x2908b30d00000000, 0x402b035100000000, + 0xd5ff73c400000000, 0x2b8493a000000000, 0xbe50e33500000000, + 0xa5a0b2f800000000, 0x3074c26d00000000, 0xce0f220900000000, + 0x5bdb529c00000000, 0x32f8e2c000000000, 0xa72c925500000000, + 0x5957723100000000, 0xcc8302a400000000, 0x8b11128800000000, + 0x1ec5621d00000000, 0xe0be827900000000, 0x756af2ec00000000, + 0x1c4942b000000000, 0x899d322500000000, 0x77e6d24100000000, + 0xe232a2d400000000, 0xf285e73300000000, 0x675197a600000000, + 0x992a77c200000000, 0x0cfe075700000000, 0x65ddb70b00000000, + 0xf009c79e00000000, 0x0e7227fa00000000, 0x9ba6576f00000000, + 0xdc34474300000000, 0x49e037d600000000, 0xb79bd7b200000000, + 0x224fa72700000000, 0x4b6c177b00000000, 0xdeb867ee00000000, + 0x20c3878a00000000, 0xb517f71f00000000, 0xaee7a6d200000000, + 0x3b33d64700000000, 0xc548362300000000, 0x509c46b600000000, + 0x39bff6ea00000000, 0xac6b867f00000000, 0x5210661b00000000, + 0xc7c4168e00000000, 0x805606a200000000, 0x1582763700000000, + 0xebf9965300000000, 0x7e2de6c600000000, 0x170e569a00000000, + 0x82da260f00000000, 0x7ca1c66b00000000, 0xe975b6fe00000000, + 0x0b47142a00000000, 0x9e9364bf00000000, 0x60e884db00000000, + 0xf53cf44e00000000, 0x9c1f441200000000, 0x09cb348700000000, + 0xf7b0d4e300000000, 0x6264a47600000000, 0x25f6b45a00000000, + 0xb022c4cf00000000, 0x4e5924ab00000000, 0xdb8d543e00000000, + 0xb2aee46200000000, 0x277a94f700000000, 0xd901749300000000, + 0x4cd5040600000000, 0x572555cb00000000, 0xc2f1255e00000000, + 0x3c8ac53a00000000, 0xa95eb5af00000000, 0xc07d05f300000000, + 0x55a9756600000000, 0xabd2950200000000, 0x3e06e59700000000, + 0x7994f5bb00000000, 0xec40852e00000000, 0x123b654a00000000, + 0x87ef15df00000000, 0xeecca58300000000, 0x7b18d51600000000, + 0x8563357200000000, 0x10b745e700000000, 0xe40bcf6700000000, + 0x71dfbff200000000, 0x8fa45f9600000000, 0x1a702f0300000000, + 0x73539f5f00000000, 0xe687efca00000000, 0x18fc0fae00000000, + 0x8d287f3b00000000, 0xcaba6f1700000000, 0x5f6e1f8200000000, + 0xa115ffe600000000, 0x34c18f7300000000, 0x5de23f2f00000000, + 0xc8364fba00000000, 0x364dafde00000000, 0xa399df4b00000000, + 0xb8698e8600000000, 0x2dbdfe1300000000, 0xd3c61e7700000000, + 0x46126ee200000000, 0x2f31debe00000000, 0xbae5ae2b00000000, + 0x449e4e4f00000000, 0xd14a3eda00000000, 0x96d82ef600000000, + 0x030c5e6300000000, 0xfd77be0700000000, 0x68a3ce9200000000, + 0x01807ece00000000, 0x94540e5b00000000, 0x6a2fee3f00000000, + 0xfffb9eaa00000000, 0x1dc93c7e00000000, 0x881d4ceb00000000, + 0x7666ac8f00000000, 0xe3b2dc1a00000000, 0x8a916c4600000000, + 0x1f451cd300000000, 0xe13efcb700000000, 0x74ea8c2200000000, + 0x33789c0e00000000, 0xa6acec9b00000000, 0x58d70cff00000000, + 0xcd037c6a00000000, 0xa420cc3600000000, 0x31f4bca300000000, + 0xcf8f5cc700000000, 0x5a5b2c5200000000, 0x41ab7d9f00000000, + 0xd47f0d0a00000000, 0x2a04ed6e00000000, 0xbfd09dfb00000000, + 0xd6f32da700000000, 0x43275d3200000000, 0xbd5cbd5600000000, + 0x2888cdc300000000, 0x6f1addef00000000, 0xfacead7a00000000, + 0x04b54d1e00000000, 0x91613d8b00000000, 0xf8428dd700000000, + 0x6d96fd4200000000, 0x93ed1d2600000000, 0x06396db300000000, + 0x168e285400000000, 0x835a58c100000000, 0x7d21b8a500000000, + 0xe8f5c83000000000, 0x81d6786c00000000, 0x140208f900000000, + 0xea79e89d00000000, 0x7fad980800000000, 0x383f882400000000, + 0xadebf8b100000000, 0x539018d500000000, 0xc644684000000000, + 0xaf67d81c00000000, 0x3ab3a88900000000, 0xc4c848ed00000000, + 0x511c387800000000, 0x4aec69b500000000, 0xdf38192000000000, + 0x2143f94400000000, 0xb49789d100000000, 0xddb4398d00000000, + 0x4860491800000000, 0xb61ba97c00000000, 0x23cfd9e900000000, + 0x645dc9c500000000, 0xf189b95000000000, 0x0ff2593400000000, + 0x9a2629a100000000, 0xf30599fd00000000, 0x66d1e96800000000, + 0x98aa090c00000000, 0x0d7e799900000000, 0xef4cdb4d00000000, + 0x7a98abd800000000, 0x84e34bbc00000000, 0x11373b2900000000, + 0x78148b7500000000, 0xedc0fbe000000000, 0x13bb1b8400000000, + 0x866f6b1100000000, 0xc1fd7b3d00000000, 0x54290ba800000000, + 0xaa52ebcc00000000, 0x3f869b5900000000, 0x56a52b0500000000, + 0xc3715b9000000000, 0x3d0abbf400000000, 0xa8decb6100000000, + 0xb32e9aac00000000, 0x26faea3900000000, 0xd8810a5d00000000, + 0x4d557ac800000000, 0x2476ca9400000000, 0xb1a2ba0100000000, + 0x4fd95a6500000000, 0xda0d2af000000000, 0x9d9f3adc00000000, + 0x084b4a4900000000, 0xf630aa2d00000000, 0x63e4dab800000000, + 0x0ac76ae400000000, 0x9f131a7100000000, 0x6168fa1500000000, + 0xf4bc8a8000000000}, + {0x0000000000000000, 0x1f17f08000000000, 0x7f2891da00000000, + 0x603f615a00000000, 0xbf56536e00000000, 0xa041a3ee00000000, + 0xc07ec2b400000000, 0xdf69323400000000, 0x7eada6dc00000000, + 0x61ba565c00000000, 0x0185370600000000, 0x1e92c78600000000, + 0xc1fbf5b200000000, 0xdeec053200000000, 0xbed3646800000000, + 0xa1c494e800000000, 0xbd5c3c6200000000, 0xa24bcce200000000, + 0xc274adb800000000, 0xdd635d3800000000, 0x020a6f0c00000000, + 0x1d1d9f8c00000000, 0x7d22fed600000000, 0x62350e5600000000, + 0xc3f19abe00000000, 0xdce66a3e00000000, 0xbcd90b6400000000, + 0xa3cefbe400000000, 0x7ca7c9d000000000, 0x63b0395000000000, + 0x038f580a00000000, 0x1c98a88a00000000, 0x7ab978c400000000, + 0x65ae884400000000, 0x0591e91e00000000, 0x1a86199e00000000, + 0xc5ef2baa00000000, 0xdaf8db2a00000000, 0xbac7ba7000000000, + 0xa5d04af000000000, 0x0414de1800000000, 0x1b032e9800000000, + 0x7b3c4fc200000000, 0x642bbf4200000000, 0xbb428d7600000000, + 0xa4557df600000000, 0xc46a1cac00000000, 0xdb7dec2c00000000, + 0xc7e544a600000000, 0xd8f2b42600000000, 0xb8cdd57c00000000, + 0xa7da25fc00000000, 0x78b317c800000000, 0x67a4e74800000000, + 0x079b861200000000, 0x188c769200000000, 0xb948e27a00000000, + 0xa65f12fa00000000, 0xc66073a000000000, 0xd977832000000000, + 0x061eb11400000000, 0x1909419400000000, 0x793620ce00000000, + 0x6621d04e00000000, 0xb574805300000000, 0xaa6370d300000000, + 0xca5c118900000000, 0xd54be10900000000, 0x0a22d33d00000000, + 0x153523bd00000000, 0x750a42e700000000, 0x6a1db26700000000, + 0xcbd9268f00000000, 0xd4ced60f00000000, 0xb4f1b75500000000, + 0xabe647d500000000, 0x748f75e100000000, 0x6b98856100000000, + 0x0ba7e43b00000000, 0x14b014bb00000000, 0x0828bc3100000000, + 0x173f4cb100000000, 0x77002deb00000000, 0x6817dd6b00000000, + 0xb77eef5f00000000, 0xa8691fdf00000000, 0xc8567e8500000000, + 0xd7418e0500000000, 0x76851aed00000000, 0x6992ea6d00000000, + 0x09ad8b3700000000, 0x16ba7bb700000000, 0xc9d3498300000000, + 0xd6c4b90300000000, 0xb6fbd85900000000, 0xa9ec28d900000000, + 0xcfcdf89700000000, 0xd0da081700000000, 0xb0e5694d00000000, + 0xaff299cd00000000, 0x709babf900000000, 0x6f8c5b7900000000, + 0x0fb33a2300000000, 0x10a4caa300000000, 0xb1605e4b00000000, + 0xae77aecb00000000, 0xce48cf9100000000, 0xd15f3f1100000000, + 0x0e360d2500000000, 0x1121fda500000000, 0x711e9cff00000000, + 0x6e096c7f00000000, 0x7291c4f500000000, 0x6d86347500000000, + 0x0db9552f00000000, 0x12aea5af00000000, 0xcdc7979b00000000, + 0xd2d0671b00000000, 0xb2ef064100000000, 0xadf8f6c100000000, + 0x0c3c622900000000, 0x132b92a900000000, 0x7314f3f300000000, + 0x6c03037300000000, 0xb36a314700000000, 0xac7dc1c700000000, + 0xcc42a09d00000000, 0xd355501d00000000, 0x6ae900a700000000, + 0x75fef02700000000, 0x15c1917d00000000, 0x0ad661fd00000000, + 0xd5bf53c900000000, 0xcaa8a34900000000, 0xaa97c21300000000, + 0xb580329300000000, 0x1444a67b00000000, 0x0b5356fb00000000, + 0x6b6c37a100000000, 0x747bc72100000000, 0xab12f51500000000, + 0xb405059500000000, 0xd43a64cf00000000, 0xcb2d944f00000000, + 0xd7b53cc500000000, 0xc8a2cc4500000000, 0xa89dad1f00000000, + 0xb78a5d9f00000000, 0x68e36fab00000000, 0x77f49f2b00000000, + 0x17cbfe7100000000, 0x08dc0ef100000000, 0xa9189a1900000000, + 0xb60f6a9900000000, 0xd6300bc300000000, 0xc927fb4300000000, + 0x164ec97700000000, 0x095939f700000000, 0x696658ad00000000, + 0x7671a82d00000000, 0x1050786300000000, 0x0f4788e300000000, + 0x6f78e9b900000000, 0x706f193900000000, 0xaf062b0d00000000, + 0xb011db8d00000000, 0xd02ebad700000000, 0xcf394a5700000000, + 0x6efddebf00000000, 0x71ea2e3f00000000, 0x11d54f6500000000, + 0x0ec2bfe500000000, 0xd1ab8dd100000000, 0xcebc7d5100000000, + 0xae831c0b00000000, 0xb194ec8b00000000, 0xad0c440100000000, + 0xb21bb48100000000, 0xd224d5db00000000, 0xcd33255b00000000, + 0x125a176f00000000, 0x0d4de7ef00000000, 0x6d7286b500000000, + 0x7265763500000000, 0xd3a1e2dd00000000, 0xccb6125d00000000, + 0xac89730700000000, 0xb39e838700000000, 0x6cf7b1b300000000, + 0x73e0413300000000, 0x13df206900000000, 0x0cc8d0e900000000, + 0xdf9d80f400000000, 0xc08a707400000000, 0xa0b5112e00000000, + 0xbfa2e1ae00000000, 0x60cbd39a00000000, 0x7fdc231a00000000, + 0x1fe3424000000000, 0x00f4b2c000000000, 0xa130262800000000, + 0xbe27d6a800000000, 0xde18b7f200000000, 0xc10f477200000000, + 0x1e66754600000000, 0x017185c600000000, 0x614ee49c00000000, + 0x7e59141c00000000, 0x62c1bc9600000000, 0x7dd64c1600000000, + 0x1de92d4c00000000, 0x02feddcc00000000, 0xdd97eff800000000, + 0xc2801f7800000000, 0xa2bf7e2200000000, 0xbda88ea200000000, + 0x1c6c1a4a00000000, 0x037beaca00000000, 0x63448b9000000000, + 0x7c537b1000000000, 0xa33a492400000000, 0xbc2db9a400000000, + 0xdc12d8fe00000000, 0xc305287e00000000, 0xa524f83000000000, + 0xba3308b000000000, 0xda0c69ea00000000, 0xc51b996a00000000, + 0x1a72ab5e00000000, 0x05655bde00000000, 0x655a3a8400000000, + 0x7a4dca0400000000, 0xdb895eec00000000, 0xc49eae6c00000000, + 0xa4a1cf3600000000, 0xbbb63fb600000000, 0x64df0d8200000000, + 0x7bc8fd0200000000, 0x1bf79c5800000000, 0x04e06cd800000000, + 0x1878c45200000000, 0x076f34d200000000, 0x6750558800000000, + 0x7847a50800000000, 0xa72e973c00000000, 0xb83967bc00000000, + 0xd80606e600000000, 0xc711f66600000000, 0x66d5628e00000000, + 0x79c2920e00000000, 0x19fdf35400000000, 0x06ea03d400000000, + 0xd98331e000000000, 0xc694c16000000000, 0xa6aba03a00000000, + 0xb9bc50ba00000000}, + {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000, + 0x6700e84d00000000, 0x4bfdb05b00000000, 0xa90038d600000000, + 0xce00d09b00000000, 0x2cfd581600000000, 0x96fa61b700000000, + 0x7407e93a00000000, 0x1307017700000000, 0xf1fa89fa00000000, + 0xdd07d1ec00000000, 0x3ffa596100000000, 0x58fab12c00000000, + 0xba0739a100000000, 0x6df3b2b500000000, 0x8f0e3a3800000000, + 0xe80ed27500000000, 0x0af35af800000000, 0x260e02ee00000000, + 0xc4f38a6300000000, 0xa3f3622e00000000, 0x410eeaa300000000, + 0xfb09d30200000000, 0x19f45b8f00000000, 0x7ef4b3c200000000, + 0x9c093b4f00000000, 0xb0f4635900000000, 0x5209ebd400000000, + 0x3509039900000000, 0xd7f48b1400000000, 0x9be014b000000000, + 0x791d9c3d00000000, 0x1e1d747000000000, 0xfce0fcfd00000000, + 0xd01da4eb00000000, 0x32e02c6600000000, 0x55e0c42b00000000, + 0xb71d4ca600000000, 0x0d1a750700000000, 0xefe7fd8a00000000, + 0x88e715c700000000, 0x6a1a9d4a00000000, 0x46e7c55c00000000, + 0xa41a4dd100000000, 0xc31aa59c00000000, 0x21e72d1100000000, + 0xf613a60500000000, 0x14ee2e8800000000, 0x73eec6c500000000, + 0x91134e4800000000, 0xbdee165e00000000, 0x5f139ed300000000, + 0x3813769e00000000, 0xdaeefe1300000000, 0x60e9c7b200000000, + 0x82144f3f00000000, 0xe514a77200000000, 0x07e92fff00000000, + 0x2b1477e900000000, 0xc9e9ff6400000000, 0xaee9172900000000, + 0x4c149fa400000000, 0x77c758bb00000000, 0x953ad03600000000, + 0xf23a387b00000000, 0x10c7b0f600000000, 0x3c3ae8e000000000, + 0xdec7606d00000000, 0xb9c7882000000000, 0x5b3a00ad00000000, + 0xe13d390c00000000, 0x03c0b18100000000, 0x64c059cc00000000, + 0x863dd14100000000, 0xaac0895700000000, 0x483d01da00000000, + 0x2f3de99700000000, 0xcdc0611a00000000, 0x1a34ea0e00000000, + 0xf8c9628300000000, 0x9fc98ace00000000, 0x7d34024300000000, + 0x51c95a5500000000, 0xb334d2d800000000, 0xd4343a9500000000, + 0x36c9b21800000000, 0x8cce8bb900000000, 0x6e33033400000000, + 0x0933eb7900000000, 0xebce63f400000000, 0xc7333be200000000, + 0x25ceb36f00000000, 0x42ce5b2200000000, 0xa033d3af00000000, + 0xec274c0b00000000, 0x0edac48600000000, 0x69da2ccb00000000, + 0x8b27a44600000000, 0xa7dafc5000000000, 0x452774dd00000000, + 0x22279c9000000000, 0xc0da141d00000000, 0x7add2dbc00000000, + 0x9820a53100000000, 0xff204d7c00000000, 0x1dddc5f100000000, + 0x31209de700000000, 0xd3dd156a00000000, 0xb4ddfd2700000000, + 0x562075aa00000000, 0x81d4febe00000000, 0x6329763300000000, + 0x04299e7e00000000, 0xe6d416f300000000, 0xca294ee500000000, + 0x28d4c66800000000, 0x4fd42e2500000000, 0xad29a6a800000000, + 0x172e9f0900000000, 0xf5d3178400000000, 0x92d3ffc900000000, + 0x702e774400000000, 0x5cd32f5200000000, 0xbe2ea7df00000000, + 0xd92e4f9200000000, 0x3bd3c71f00000000, 0xaf88c0ad00000000, + 0x4d75482000000000, 0x2a75a06d00000000, 0xc88828e000000000, + 0xe47570f600000000, 0x0688f87b00000000, 0x6188103600000000, + 0x837598bb00000000, 0x3972a11a00000000, 0xdb8f299700000000, + 0xbc8fc1da00000000, 0x5e72495700000000, 0x728f114100000000, + 0x907299cc00000000, 0xf772718100000000, 0x158ff90c00000000, + 0xc27b721800000000, 0x2086fa9500000000, 0x478612d800000000, + 0xa57b9a5500000000, 0x8986c24300000000, 0x6b7b4ace00000000, + 0x0c7ba28300000000, 0xee862a0e00000000, 0x548113af00000000, + 0xb67c9b2200000000, 0xd17c736f00000000, 0x3381fbe200000000, + 0x1f7ca3f400000000, 0xfd812b7900000000, 0x9a81c33400000000, + 0x787c4bb900000000, 0x3468d41d00000000, 0xd6955c9000000000, + 0xb195b4dd00000000, 0x53683c5000000000, 0x7f95644600000000, + 0x9d68eccb00000000, 0xfa68048600000000, 0x18958c0b00000000, + 0xa292b5aa00000000, 0x406f3d2700000000, 0x276fd56a00000000, + 0xc5925de700000000, 0xe96f05f100000000, 0x0b928d7c00000000, + 0x6c92653100000000, 0x8e6fedbc00000000, 0x599b66a800000000, + 0xbb66ee2500000000, 0xdc66066800000000, 0x3e9b8ee500000000, + 0x1266d6f300000000, 0xf09b5e7e00000000, 0x979bb63300000000, + 0x75663ebe00000000, 0xcf61071f00000000, 0x2d9c8f9200000000, + 0x4a9c67df00000000, 0xa861ef5200000000, 0x849cb74400000000, + 0x66613fc900000000, 0x0161d78400000000, 0xe39c5f0900000000, + 0xd84f981600000000, 0x3ab2109b00000000, 0x5db2f8d600000000, + 0xbf4f705b00000000, 0x93b2284d00000000, 0x714fa0c000000000, + 0x164f488d00000000, 0xf4b2c00000000000, 0x4eb5f9a100000000, + 0xac48712c00000000, 0xcb48996100000000, 0x29b511ec00000000, + 0x054849fa00000000, 0xe7b5c17700000000, 0x80b5293a00000000, + 0x6248a1b700000000, 0xb5bc2aa300000000, 0x5741a22e00000000, + 0x30414a6300000000, 0xd2bcc2ee00000000, 0xfe419af800000000, + 0x1cbc127500000000, 0x7bbcfa3800000000, 0x994172b500000000, + 0x23464b1400000000, 0xc1bbc39900000000, 0xa6bb2bd400000000, + 0x4446a35900000000, 0x68bbfb4f00000000, 0x8a4673c200000000, + 0xed469b8f00000000, 0x0fbb130200000000, 0x43af8ca600000000, + 0xa152042b00000000, 0xc652ec6600000000, 0x24af64eb00000000, + 0x08523cfd00000000, 0xeaafb47000000000, 0x8daf5c3d00000000, + 0x6f52d4b000000000, 0xd555ed1100000000, 0x37a8659c00000000, + 0x50a88dd100000000, 0xb255055c00000000, 0x9ea85d4a00000000, + 0x7c55d5c700000000, 0x1b553d8a00000000, 0xf9a8b50700000000, + 0x2e5c3e1300000000, 0xcca1b69e00000000, 0xaba15ed300000000, + 0x495cd65e00000000, 0x65a18e4800000000, 0x875c06c500000000, + 0xe05cee8800000000, 0x02a1660500000000, 0xb8a65fa400000000, + 0x5a5bd72900000000, 0x3d5b3f6400000000, 0xdfa6b7e900000000, + 0xf35befff00000000, 0x11a6677200000000, 0x76a68f3f00000000, + 0x945b07b200000000}, + {0x0000000000000000, 0xa90b894e00000000, 0x5217129d00000000, + 0xfb1c9bd300000000, 0xe52855e100000000, 0x4c23dcaf00000000, + 0xb73f477c00000000, 0x1e34ce3200000000, 0x8b57db1900000000, + 0x225c525700000000, 0xd940c98400000000, 0x704b40ca00000000, + 0x6e7f8ef800000000, 0xc77407b600000000, 0x3c689c6500000000, + 0x9563152b00000000, 0x16afb63300000000, 0xbfa43f7d00000000, + 0x44b8a4ae00000000, 0xedb32de000000000, 0xf387e3d200000000, + 0x5a8c6a9c00000000, 0xa190f14f00000000, 0x089b780100000000, + 0x9df86d2a00000000, 0x34f3e46400000000, 0xcfef7fb700000000, + 0x66e4f6f900000000, 0x78d038cb00000000, 0xd1dbb18500000000, + 0x2ac72a5600000000, 0x83cca31800000000, 0x2c5e6d6700000000, + 0x8555e42900000000, 0x7e497ffa00000000, 0xd742f6b400000000, + 0xc976388600000000, 0x607db1c800000000, 0x9b612a1b00000000, + 0x326aa35500000000, 0xa709b67e00000000, 0x0e023f3000000000, + 0xf51ea4e300000000, 0x5c152dad00000000, 0x4221e39f00000000, + 0xeb2a6ad100000000, 0x1036f10200000000, 0xb93d784c00000000, + 0x3af1db5400000000, 0x93fa521a00000000, 0x68e6c9c900000000, + 0xc1ed408700000000, 0xdfd98eb500000000, 0x76d207fb00000000, + 0x8dce9c2800000000, 0x24c5156600000000, 0xb1a6004d00000000, + 0x18ad890300000000, 0xe3b112d000000000, 0x4aba9b9e00000000, + 0x548e55ac00000000, 0xfd85dce200000000, 0x0699473100000000, + 0xaf92ce7f00000000, 0x58bcdace00000000, 0xf1b7538000000000, + 0x0aabc85300000000, 0xa3a0411d00000000, 0xbd948f2f00000000, + 0x149f066100000000, 0xef839db200000000, 0x468814fc00000000, + 0xd3eb01d700000000, 0x7ae0889900000000, 0x81fc134a00000000, + 0x28f79a0400000000, 0x36c3543600000000, 0x9fc8dd7800000000, + 0x64d446ab00000000, 0xcddfcfe500000000, 0x4e136cfd00000000, + 0xe718e5b300000000, 0x1c047e6000000000, 0xb50ff72e00000000, + 0xab3b391c00000000, 0x0230b05200000000, 0xf92c2b8100000000, + 0x5027a2cf00000000, 0xc544b7e400000000, 0x6c4f3eaa00000000, + 0x9753a57900000000, 0x3e582c3700000000, 0x206ce20500000000, + 0x89676b4b00000000, 0x727bf09800000000, 0xdb7079d600000000, + 0x74e2b7a900000000, 0xdde93ee700000000, 0x26f5a53400000000, + 0x8ffe2c7a00000000, 0x91cae24800000000, 0x38c16b0600000000, + 0xc3ddf0d500000000, 0x6ad6799b00000000, 0xffb56cb000000000, + 0x56bee5fe00000000, 0xada27e2d00000000, 0x04a9f76300000000, + 0x1a9d395100000000, 0xb396b01f00000000, 0x488a2bcc00000000, + 0xe181a28200000000, 0x624d019a00000000, 0xcb4688d400000000, + 0x305a130700000000, 0x99519a4900000000, 0x8765547b00000000, + 0x2e6edd3500000000, 0xd57246e600000000, 0x7c79cfa800000000, + 0xe91ada8300000000, 0x401153cd00000000, 0xbb0dc81e00000000, + 0x1206415000000000, 0x0c328f6200000000, 0xa539062c00000000, + 0x5e259dff00000000, 0xf72e14b100000000, 0xf17ec44600000000, + 0x58754d0800000000, 0xa369d6db00000000, 0x0a625f9500000000, + 0x145691a700000000, 0xbd5d18e900000000, 0x4641833a00000000, + 0xef4a0a7400000000, 0x7a291f5f00000000, 0xd322961100000000, + 0x283e0dc200000000, 0x8135848c00000000, 0x9f014abe00000000, + 0x360ac3f000000000, 0xcd16582300000000, 0x641dd16d00000000, + 0xe7d1727500000000, 0x4edafb3b00000000, 0xb5c660e800000000, + 0x1ccde9a600000000, 0x02f9279400000000, 0xabf2aeda00000000, + 0x50ee350900000000, 0xf9e5bc4700000000, 0x6c86a96c00000000, + 0xc58d202200000000, 0x3e91bbf100000000, 0x979a32bf00000000, + 0x89aefc8d00000000, 0x20a575c300000000, 0xdbb9ee1000000000, + 0x72b2675e00000000, 0xdd20a92100000000, 0x742b206f00000000, + 0x8f37bbbc00000000, 0x263c32f200000000, 0x3808fcc000000000, + 0x9103758e00000000, 0x6a1fee5d00000000, 0xc314671300000000, + 0x5677723800000000, 0xff7cfb7600000000, 0x046060a500000000, + 0xad6be9eb00000000, 0xb35f27d900000000, 0x1a54ae9700000000, + 0xe148354400000000, 0x4843bc0a00000000, 0xcb8f1f1200000000, + 0x6284965c00000000, 0x99980d8f00000000, 0x309384c100000000, + 0x2ea74af300000000, 0x87acc3bd00000000, 0x7cb0586e00000000, + 0xd5bbd12000000000, 0x40d8c40b00000000, 0xe9d34d4500000000, + 0x12cfd69600000000, 0xbbc45fd800000000, 0xa5f091ea00000000, + 0x0cfb18a400000000, 0xf7e7837700000000, 0x5eec0a3900000000, + 0xa9c21e8800000000, 0x00c997c600000000, 0xfbd50c1500000000, + 0x52de855b00000000, 0x4cea4b6900000000, 0xe5e1c22700000000, + 0x1efd59f400000000, 0xb7f6d0ba00000000, 0x2295c59100000000, + 0x8b9e4cdf00000000, 0x7082d70c00000000, 0xd9895e4200000000, + 0xc7bd907000000000, 0x6eb6193e00000000, 0x95aa82ed00000000, + 0x3ca10ba300000000, 0xbf6da8bb00000000, 0x166621f500000000, + 0xed7aba2600000000, 0x4471336800000000, 0x5a45fd5a00000000, + 0xf34e741400000000, 0x0852efc700000000, 0xa159668900000000, + 0x343a73a200000000, 0x9d31faec00000000, 0x662d613f00000000, + 0xcf26e87100000000, 0xd112264300000000, 0x7819af0d00000000, + 0x830534de00000000, 0x2a0ebd9000000000, 0x859c73ef00000000, + 0x2c97faa100000000, 0xd78b617200000000, 0x7e80e83c00000000, + 0x60b4260e00000000, 0xc9bfaf4000000000, 0x32a3349300000000, + 0x9ba8bddd00000000, 0x0ecba8f600000000, 0xa7c021b800000000, + 0x5cdcba6b00000000, 0xf5d7332500000000, 0xebe3fd1700000000, + 0x42e8745900000000, 0xb9f4ef8a00000000, 0x10ff66c400000000, + 0x9333c5dc00000000, 0x3a384c9200000000, 0xc124d74100000000, + 0x682f5e0f00000000, 0x761b903d00000000, 0xdf10197300000000, + 0x240c82a000000000, 0x8d070bee00000000, 0x18641ec500000000, + 0xb16f978b00000000, 0x4a730c5800000000, 0xe378851600000000, + 0xfd4c4b2400000000, 0x5447c26a00000000, 0xaf5b59b900000000, + 0x0650d0f700000000}, + {0x0000000000000000, 0x479244af00000000, 0xcf22f88500000000, + 0x88b0bc2a00000000, 0xdf4381d000000000, 0x98d1c57f00000000, + 0x1061795500000000, 0x57f33dfa00000000, 0xff81737a00000000, + 0xb81337d500000000, 0x30a38bff00000000, 0x7731cf5000000000, + 0x20c2f2aa00000000, 0x6750b60500000000, 0xefe00a2f00000000, + 0xa8724e8000000000, 0xfe03e7f400000000, 0xb991a35b00000000, + 0x31211f7100000000, 0x76b35bde00000000, 0x2140662400000000, + 0x66d2228b00000000, 0xee629ea100000000, 0xa9f0da0e00000000, + 0x0182948e00000000, 0x4610d02100000000, 0xcea06c0b00000000, + 0x893228a400000000, 0xdec1155e00000000, 0x995351f100000000, + 0x11e3eddb00000000, 0x5671a97400000000, 0xbd01bf3200000000, + 0xfa93fb9d00000000, 0x722347b700000000, 0x35b1031800000000, + 0x62423ee200000000, 0x25d07a4d00000000, 0xad60c66700000000, + 0xeaf282c800000000, 0x4280cc4800000000, 0x051288e700000000, + 0x8da234cd00000000, 0xca30706200000000, 0x9dc34d9800000000, + 0xda51093700000000, 0x52e1b51d00000000, 0x1573f1b200000000, + 0x430258c600000000, 0x04901c6900000000, 0x8c20a04300000000, + 0xcbb2e4ec00000000, 0x9c41d91600000000, 0xdbd39db900000000, + 0x5363219300000000, 0x14f1653c00000000, 0xbc832bbc00000000, + 0xfb116f1300000000, 0x73a1d33900000000, 0x3433979600000000, + 0x63c0aa6c00000000, 0x2452eec300000000, 0xace252e900000000, + 0xeb70164600000000, 0x7a037e6500000000, 0x3d913aca00000000, + 0xb52186e000000000, 0xf2b3c24f00000000, 0xa540ffb500000000, + 0xe2d2bb1a00000000, 0x6a62073000000000, 0x2df0439f00000000, + 0x85820d1f00000000, 0xc21049b000000000, 0x4aa0f59a00000000, + 0x0d32b13500000000, 0x5ac18ccf00000000, 0x1d53c86000000000, + 0x95e3744a00000000, 0xd27130e500000000, 0x8400999100000000, + 0xc392dd3e00000000, 0x4b22611400000000, 0x0cb025bb00000000, + 0x5b43184100000000, 0x1cd15cee00000000, 0x9461e0c400000000, + 0xd3f3a46b00000000, 0x7b81eaeb00000000, 0x3c13ae4400000000, + 0xb4a3126e00000000, 0xf33156c100000000, 0xa4c26b3b00000000, + 0xe3502f9400000000, 0x6be093be00000000, 0x2c72d71100000000, + 0xc702c15700000000, 0x809085f800000000, 0x082039d200000000, + 0x4fb27d7d00000000, 0x1841408700000000, 0x5fd3042800000000, + 0xd763b80200000000, 0x90f1fcad00000000, 0x3883b22d00000000, + 0x7f11f68200000000, 0xf7a14aa800000000, 0xb0330e0700000000, + 0xe7c033fd00000000, 0xa052775200000000, 0x28e2cb7800000000, + 0x6f708fd700000000, 0x390126a300000000, 0x7e93620c00000000, + 0xf623de2600000000, 0xb1b19a8900000000, 0xe642a77300000000, + 0xa1d0e3dc00000000, 0x29605ff600000000, 0x6ef21b5900000000, + 0xc68055d900000000, 0x8112117600000000, 0x09a2ad5c00000000, + 0x4e30e9f300000000, 0x19c3d40900000000, 0x5e5190a600000000, + 0xd6e12c8c00000000, 0x9173682300000000, 0xf406fcca00000000, + 0xb394b86500000000, 0x3b24044f00000000, 0x7cb640e000000000, + 0x2b457d1a00000000, 0x6cd739b500000000, 0xe467859f00000000, + 0xa3f5c13000000000, 0x0b878fb000000000, 0x4c15cb1f00000000, + 0xc4a5773500000000, 0x8337339a00000000, 0xd4c40e6000000000, + 0x93564acf00000000, 0x1be6f6e500000000, 0x5c74b24a00000000, + 0x0a051b3e00000000, 0x4d975f9100000000, 0xc527e3bb00000000, + 0x82b5a71400000000, 0xd5469aee00000000, 0x92d4de4100000000, + 0x1a64626b00000000, 0x5df626c400000000, 0xf584684400000000, + 0xb2162ceb00000000, 0x3aa690c100000000, 0x7d34d46e00000000, + 0x2ac7e99400000000, 0x6d55ad3b00000000, 0xe5e5111100000000, + 0xa27755be00000000, 0x490743f800000000, 0x0e95075700000000, + 0x8625bb7d00000000, 0xc1b7ffd200000000, 0x9644c22800000000, + 0xd1d6868700000000, 0x59663aad00000000, 0x1ef47e0200000000, + 0xb686308200000000, 0xf114742d00000000, 0x79a4c80700000000, + 0x3e368ca800000000, 0x69c5b15200000000, 0x2e57f5fd00000000, + 0xa6e749d700000000, 0xe1750d7800000000, 0xb704a40c00000000, + 0xf096e0a300000000, 0x78265c8900000000, 0x3fb4182600000000, + 0x684725dc00000000, 0x2fd5617300000000, 0xa765dd5900000000, + 0xe0f799f600000000, 0x4885d77600000000, 0x0f1793d900000000, + 0x87a72ff300000000, 0xc0356b5c00000000, 0x97c656a600000000, + 0xd054120900000000, 0x58e4ae2300000000, 0x1f76ea8c00000000, + 0x8e0582af00000000, 0xc997c60000000000, 0x41277a2a00000000, + 0x06b53e8500000000, 0x5146037f00000000, 0x16d447d000000000, + 0x9e64fbfa00000000, 0xd9f6bf5500000000, 0x7184f1d500000000, + 0x3616b57a00000000, 0xbea6095000000000, 0xf9344dff00000000, + 0xaec7700500000000, 0xe95534aa00000000, 0x61e5888000000000, + 0x2677cc2f00000000, 0x7006655b00000000, 0x379421f400000000, + 0xbf249dde00000000, 0xf8b6d97100000000, 0xaf45e48b00000000, + 0xe8d7a02400000000, 0x60671c0e00000000, 0x27f558a100000000, + 0x8f87162100000000, 0xc815528e00000000, 0x40a5eea400000000, + 0x0737aa0b00000000, 0x50c497f100000000, 0x1756d35e00000000, + 0x9fe66f7400000000, 0xd8742bdb00000000, 0x33043d9d00000000, + 0x7496793200000000, 0xfc26c51800000000, 0xbbb481b700000000, + 0xec47bc4d00000000, 0xabd5f8e200000000, 0x236544c800000000, + 0x64f7006700000000, 0xcc854ee700000000, 0x8b170a4800000000, + 0x03a7b66200000000, 0x4435f2cd00000000, 0x13c6cf3700000000, + 0x54548b9800000000, 0xdce437b200000000, 0x9b76731d00000000, + 0xcd07da6900000000, 0x8a959ec600000000, 0x022522ec00000000, + 0x45b7664300000000, 0x12445bb900000000, 0x55d61f1600000000, + 0xdd66a33c00000000, 0x9af4e79300000000, 0x3286a91300000000, + 0x7514edbc00000000, 0xfda4519600000000, 0xba36153900000000, + 0xedc528c300000000, 0xaa576c6c00000000, 0x22e7d04600000000, + 0x657594e900000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59, + 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4, + 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67, + 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef, + 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97, + 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88, + 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687, + 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698, + 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0, + 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068, + 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb, + 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056, + 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016, + 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009, + 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028, + 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037, + 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a, + 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7, + 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054, + 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7, + 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af, + 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0, + 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4, + 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab, + 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3, + 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a, + 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9, + 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54, + 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09, + 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16, + 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37, + 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28, + 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e, + 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3, + 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40, + 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8, + 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0, + 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf, + 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6, + 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9, + 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1, + 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059, + 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca, + 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067, + 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031, + 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e, + 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f, + 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010, + 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d, + 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0, + 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073, + 0xd8ac6b35}, + {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2, + 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd, + 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696, + 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3, + 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f, + 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35, + 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5, + 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f, + 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673, + 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46, + 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d, + 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632, + 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28, + 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192, + 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c, + 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6, + 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0, + 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff, + 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4, + 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95, + 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9, + 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03, + 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7, + 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d, + 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151, + 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808, + 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343, + 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c, + 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a, + 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0, + 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e, + 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594, + 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6, + 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399, + 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2, + 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7, + 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb, + 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571, + 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289, + 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33, + 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f, + 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a, + 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461, + 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e, + 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c, + 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6, + 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918, + 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2, + 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484, + 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb, + 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0, + 0xa140efa8}, + {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706, + 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed, + 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289, + 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a, + 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214, + 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3, + 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3, + 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254, + 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a, + 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9, + 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad, + 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746, + 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060, + 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187, + 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef, + 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408, + 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e, + 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495, + 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1, + 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532, + 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c, + 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb, + 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb, + 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c, + 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42, + 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060, + 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04, + 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef, + 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99, + 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e, + 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16, + 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1, + 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7, + 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c, + 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38, + 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb, + 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5, + 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42, + 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62, + 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85, + 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb, + 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18, + 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c, + 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997, + 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1, + 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36, + 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e, + 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9, + 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf, + 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24, + 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040, + 0x917cd6a1}, + {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf, + 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd, + 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896, + 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9, + 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3, + 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f, + 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d, + 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1, + 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab, + 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4, + 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f, + 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d, + 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4, + 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978, + 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad, + 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621, + 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46, + 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854, + 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f, + 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a, + 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890, + 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c, + 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4, + 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238, + 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622, + 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab, + 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0, + 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2, + 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295, + 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19, + 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc, + 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140, + 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd, + 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf, + 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184, + 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb, + 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1, + 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d, + 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb, + 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257, + 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d, + 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22, + 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069, + 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b, + 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6, + 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a, + 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf, + 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33, + 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254, + 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146, + 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d, + 0x18ba364e}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0x43cba687, 0xc7903cd4, 0x845b9a53, 0xcf270873, + 0x8cecaef4, 0x08b734a7, 0x4b7c9220, 0x9e4f10e6, 0xdd84b661, + 0x59df2c32, 0x1a148ab5, 0x51681895, 0x12a3be12, 0x96f82441, + 0xd53382c6, 0x7d995117, 0x3e52f790, 0xba096dc3, 0xf9c2cb44, + 0xb2be5964, 0xf175ffe3, 0x752e65b0, 0x36e5c337, 0xe3d641f1, + 0xa01de776, 0x24467d25, 0x678ddba2, 0x2cf14982, 0x6f3aef05, + 0xeb617556, 0xa8aad3d1, 0xfa32a32e, 0xb9f905a9, 0x3da29ffa, + 0x7e69397d, 0x3515ab5d, 0x76de0dda, 0xf2859789, 0xb14e310e, + 0x647db3c8, 0x27b6154f, 0xa3ed8f1c, 0xe026299b, 0xab5abbbb, + 0xe8911d3c, 0x6cca876f, 0x2f0121e8, 0x87abf239, 0xc46054be, + 0x403bceed, 0x03f0686a, 0x488cfa4a, 0x0b475ccd, 0x8f1cc69e, + 0xccd76019, 0x19e4e2df, 0x5a2f4458, 0xde74de0b, 0x9dbf788c, + 0xd6c3eaac, 0x95084c2b, 0x1153d678, 0x529870ff, 0xf465465d, + 0xb7aee0da, 0x33f57a89, 0x703edc0e, 0x3b424e2e, 0x7889e8a9, + 0xfcd272fa, 0xbf19d47d, 0x6a2a56bb, 0x29e1f03c, 0xadba6a6f, + 0xee71cce8, 0xa50d5ec8, 0xe6c6f84f, 0x629d621c, 0x2156c49b, + 0x89fc174a, 0xca37b1cd, 0x4e6c2b9e, 0x0da78d19, 0x46db1f39, + 0x0510b9be, 0x814b23ed, 0xc280856a, 0x17b307ac, 0x5478a12b, + 0xd0233b78, 0x93e89dff, 0xd8940fdf, 0x9b5fa958, 0x1f04330b, + 0x5ccf958c, 0x0e57e573, 0x4d9c43f4, 0xc9c7d9a7, 0x8a0c7f20, + 0xc170ed00, 0x82bb4b87, 0x06e0d1d4, 0x452b7753, 0x9018f595, + 0xd3d35312, 0x5788c941, 0x14436fc6, 0x5f3ffde6, 0x1cf45b61, + 0x98afc132, 0xdb6467b5, 0x73ceb464, 0x300512e3, 0xb45e88b0, + 0xf7952e37, 0xbce9bc17, 0xff221a90, 0x7b7980c3, 0x38b22644, + 0xed81a482, 0xae4a0205, 0x2a119856, 0x69da3ed1, 0x22a6acf1, + 0x616d0a76, 0xe5369025, 0xa6fd36a2, 0xe8cb8cba, 0xab002a3d, + 0x2f5bb06e, 0x6c9016e9, 0x27ec84c9, 0x6427224e, 0xe07cb81d, + 0xa3b71e9a, 0x76849c5c, 0x354f3adb, 0xb114a088, 0xf2df060f, + 0xb9a3942f, 0xfa6832a8, 0x7e33a8fb, 0x3df80e7c, 0x9552ddad, + 0xd6997b2a, 0x52c2e179, 0x110947fe, 0x5a75d5de, 0x19be7359, + 0x9de5e90a, 0xde2e4f8d, 0x0b1dcd4b, 0x48d66bcc, 0xcc8df19f, + 0x8f465718, 0xc43ac538, 0x87f163bf, 0x03aaf9ec, 0x40615f6b, + 0x12f92f94, 0x51328913, 0xd5691340, 0x96a2b5c7, 0xddde27e7, + 0x9e158160, 0x1a4e1b33, 0x5985bdb4, 0x8cb63f72, 0xcf7d99f5, + 0x4b2603a6, 0x08eda521, 0x43913701, 0x005a9186, 0x84010bd5, + 0xc7caad52, 0x6f607e83, 0x2cabd804, 0xa8f04257, 0xeb3be4d0, + 0xa04776f0, 0xe38cd077, 0x67d74a24, 0x241ceca3, 0xf12f6e65, + 0xb2e4c8e2, 0x36bf52b1, 0x7574f436, 0x3e086616, 0x7dc3c091, + 0xf9985ac2, 0xba53fc45, 0x1caecae7, 0x5f656c60, 0xdb3ef633, + 0x98f550b4, 0xd389c294, 0x90426413, 0x1419fe40, 0x57d258c7, + 0x82e1da01, 0xc12a7c86, 0x4571e6d5, 0x06ba4052, 0x4dc6d272, + 0x0e0d74f5, 0x8a56eea6, 0xc99d4821, 0x61379bf0, 0x22fc3d77, + 0xa6a7a724, 0xe56c01a3, 0xae109383, 0xeddb3504, 0x6980af57, + 0x2a4b09d0, 0xff788b16, 0xbcb32d91, 0x38e8b7c2, 0x7b231145, + 0x305f8365, 0x739425e2, 0xf7cfbfb1, 0xb4041936, 0xe69c69c9, + 0xa557cf4e, 0x210c551d, 0x62c7f39a, 0x29bb61ba, 0x6a70c73d, + 0xee2b5d6e, 0xade0fbe9, 0x78d3792f, 0x3b18dfa8, 0xbf4345fb, + 0xfc88e37c, 0xb7f4715c, 0xf43fd7db, 0x70644d88, 0x33afeb0f, + 0x9b0538de, 0xd8ce9e59, 0x5c95040a, 0x1f5ea28d, 0x542230ad, + 0x17e9962a, 0x93b20c79, 0xd079aafe, 0x054a2838, 0x46818ebf, + 0xc2da14ec, 0x8111b26b, 0xca6d204b, 0x89a686cc, 0x0dfd1c9f, + 0x4e36ba18}, + {0x00000000, 0xe1b652ef, 0x836bd405, 0x62dd86ea, 0x06d7a80b, + 0xe761fae4, 0x85bc7c0e, 0x640a2ee1, 0x0cae5117, 0xed1803f8, + 0x8fc58512, 0x6e73d7fd, 0x0a79f91c, 0xebcfabf3, 0x89122d19, + 0x68a47ff6, 0x185ca32e, 0xf9eaf1c1, 0x9b37772b, 0x7a8125c4, + 0x1e8b0b25, 0xff3d59ca, 0x9de0df20, 0x7c568dcf, 0x14f2f239, + 0xf544a0d6, 0x9799263c, 0x762f74d3, 0x12255a32, 0xf39308dd, + 0x914e8e37, 0x70f8dcd8, 0x30b8465d, 0xd10e14b2, 0xb3d39258, + 0x5265c0b7, 0x366fee56, 0xd7d9bcb9, 0xb5043a53, 0x54b268bc, + 0x3c16174a, 0xdda045a5, 0xbf7dc34f, 0x5ecb91a0, 0x3ac1bf41, + 0xdb77edae, 0xb9aa6b44, 0x581c39ab, 0x28e4e573, 0xc952b79c, + 0xab8f3176, 0x4a396399, 0x2e334d78, 0xcf851f97, 0xad58997d, + 0x4ceecb92, 0x244ab464, 0xc5fce68b, 0xa7216061, 0x4697328e, + 0x229d1c6f, 0xc32b4e80, 0xa1f6c86a, 0x40409a85, 0x60708dba, + 0x81c6df55, 0xe31b59bf, 0x02ad0b50, 0x66a725b1, 0x8711775e, + 0xe5ccf1b4, 0x047aa35b, 0x6cdedcad, 0x8d688e42, 0xefb508a8, + 0x0e035a47, 0x6a0974a6, 0x8bbf2649, 0xe962a0a3, 0x08d4f24c, + 0x782c2e94, 0x999a7c7b, 0xfb47fa91, 0x1af1a87e, 0x7efb869f, + 0x9f4dd470, 0xfd90529a, 0x1c260075, 0x74827f83, 0x95342d6c, + 0xf7e9ab86, 0x165ff969, 0x7255d788, 0x93e38567, 0xf13e038d, + 0x10885162, 0x50c8cbe7, 0xb17e9908, 0xd3a31fe2, 0x32154d0d, + 0x561f63ec, 0xb7a93103, 0xd574b7e9, 0x34c2e506, 0x5c669af0, + 0xbdd0c81f, 0xdf0d4ef5, 0x3ebb1c1a, 0x5ab132fb, 0xbb076014, + 0xd9dae6fe, 0x386cb411, 0x489468c9, 0xa9223a26, 0xcbffbccc, + 0x2a49ee23, 0x4e43c0c2, 0xaff5922d, 0xcd2814c7, 0x2c9e4628, + 0x443a39de, 0xa58c6b31, 0xc751eddb, 0x26e7bf34, 0x42ed91d5, + 0xa35bc33a, 0xc18645d0, 0x2030173f, 0x81e66bae, 0x60503941, + 0x028dbfab, 0xe33bed44, 0x8731c3a5, 0x6687914a, 0x045a17a0, + 0xe5ec454f, 0x8d483ab9, 0x6cfe6856, 0x0e23eebc, 0xef95bc53, + 0x8b9f92b2, 0x6a29c05d, 0x08f446b7, 0xe9421458, 0x99bac880, + 0x780c9a6f, 0x1ad11c85, 0xfb674e6a, 0x9f6d608b, 0x7edb3264, + 0x1c06b48e, 0xfdb0e661, 0x95149997, 0x74a2cb78, 0x167f4d92, + 0xf7c91f7d, 0x93c3319c, 0x72756373, 0x10a8e599, 0xf11eb776, + 0xb15e2df3, 0x50e87f1c, 0x3235f9f6, 0xd383ab19, 0xb78985f8, + 0x563fd717, 0x34e251fd, 0xd5540312, 0xbdf07ce4, 0x5c462e0b, + 0x3e9ba8e1, 0xdf2dfa0e, 0xbb27d4ef, 0x5a918600, 0x384c00ea, + 0xd9fa5205, 0xa9028edd, 0x48b4dc32, 0x2a695ad8, 0xcbdf0837, + 0xafd526d6, 0x4e637439, 0x2cbef2d3, 0xcd08a03c, 0xa5acdfca, + 0x441a8d25, 0x26c70bcf, 0xc7715920, 0xa37b77c1, 0x42cd252e, + 0x2010a3c4, 0xc1a6f12b, 0xe196e614, 0x0020b4fb, 0x62fd3211, + 0x834b60fe, 0xe7414e1f, 0x06f71cf0, 0x642a9a1a, 0x859cc8f5, + 0xed38b703, 0x0c8ee5ec, 0x6e536306, 0x8fe531e9, 0xebef1f08, + 0x0a594de7, 0x6884cb0d, 0x893299e2, 0xf9ca453a, 0x187c17d5, + 0x7aa1913f, 0x9b17c3d0, 0xff1ded31, 0x1eabbfde, 0x7c763934, + 0x9dc06bdb, 0xf564142d, 0x14d246c2, 0x760fc028, 0x97b992c7, + 0xf3b3bc26, 0x1205eec9, 0x70d86823, 0x916e3acc, 0xd12ea049, + 0x3098f2a6, 0x5245744c, 0xb3f326a3, 0xd7f90842, 0x364f5aad, + 0x5492dc47, 0xb5248ea8, 0xdd80f15e, 0x3c36a3b1, 0x5eeb255b, + 0xbf5d77b4, 0xdb575955, 0x3ae10bba, 0x583c8d50, 0xb98adfbf, + 0xc9720367, 0x28c45188, 0x4a19d762, 0xabaf858d, 0xcfa5ab6c, + 0x2e13f983, 0x4cce7f69, 0xad782d86, 0xc5dc5270, 0x246a009f, + 0x46b78675, 0xa701d49a, 0xc30bfa7b, 0x22bda894, 0x40602e7e, + 0xa1d67c91}, + {0x00000000, 0x5880e2d7, 0xf106b474, 0xa98656a3, 0xe20d68e9, + 0xba8d8a3e, 0x130bdc9d, 0x4b8b3e4a, 0x851da109, 0xdd9d43de, + 0x741b157d, 0x2c9bf7aa, 0x6710c9e0, 0x3f902b37, 0x96167d94, + 0xce969f43, 0x0a3b4213, 0x52bba0c4, 0xfb3df667, 0xa3bd14b0, + 0xe8362afa, 0xb0b6c82d, 0x19309e8e, 0x41b07c59, 0x8f26e31a, + 0xd7a601cd, 0x7e20576e, 0x26a0b5b9, 0x6d2b8bf3, 0x35ab6924, + 0x9c2d3f87, 0xc4addd50, 0x14768426, 0x4cf666f1, 0xe5703052, + 0xbdf0d285, 0xf67beccf, 0xaefb0e18, 0x077d58bb, 0x5ffdba6c, + 0x916b252f, 0xc9ebc7f8, 0x606d915b, 0x38ed738c, 0x73664dc6, + 0x2be6af11, 0x8260f9b2, 0xdae01b65, 0x1e4dc635, 0x46cd24e2, + 0xef4b7241, 0xb7cb9096, 0xfc40aedc, 0xa4c04c0b, 0x0d461aa8, + 0x55c6f87f, 0x9b50673c, 0xc3d085eb, 0x6a56d348, 0x32d6319f, + 0x795d0fd5, 0x21dded02, 0x885bbba1, 0xd0db5976, 0x28ec084d, + 0x706cea9a, 0xd9eabc39, 0x816a5eee, 0xcae160a4, 0x92618273, + 0x3be7d4d0, 0x63673607, 0xadf1a944, 0xf5714b93, 0x5cf71d30, + 0x0477ffe7, 0x4ffcc1ad, 0x177c237a, 0xbefa75d9, 0xe67a970e, + 0x22d74a5e, 0x7a57a889, 0xd3d1fe2a, 0x8b511cfd, 0xc0da22b7, + 0x985ac060, 0x31dc96c3, 0x695c7414, 0xa7caeb57, 0xff4a0980, + 0x56cc5f23, 0x0e4cbdf4, 0x45c783be, 0x1d476169, 0xb4c137ca, + 0xec41d51d, 0x3c9a8c6b, 0x641a6ebc, 0xcd9c381f, 0x951cdac8, + 0xde97e482, 0x86170655, 0x2f9150f6, 0x7711b221, 0xb9872d62, + 0xe107cfb5, 0x48819916, 0x10017bc1, 0x5b8a458b, 0x030aa75c, + 0xaa8cf1ff, 0xf20c1328, 0x36a1ce78, 0x6e212caf, 0xc7a77a0c, + 0x9f2798db, 0xd4aca691, 0x8c2c4446, 0x25aa12e5, 0x7d2af032, + 0xb3bc6f71, 0xeb3c8da6, 0x42badb05, 0x1a3a39d2, 0x51b10798, + 0x0931e54f, 0xa0b7b3ec, 0xf837513b, 0x50d8119a, 0x0858f34d, + 0xa1dea5ee, 0xf95e4739, 0xb2d57973, 0xea559ba4, 0x43d3cd07, + 0x1b532fd0, 0xd5c5b093, 0x8d455244, 0x24c304e7, 0x7c43e630, + 0x37c8d87a, 0x6f483aad, 0xc6ce6c0e, 0x9e4e8ed9, 0x5ae35389, + 0x0263b15e, 0xabe5e7fd, 0xf365052a, 0xb8ee3b60, 0xe06ed9b7, + 0x49e88f14, 0x11686dc3, 0xdffef280, 0x877e1057, 0x2ef846f4, + 0x7678a423, 0x3df39a69, 0x657378be, 0xccf52e1d, 0x9475ccca, + 0x44ae95bc, 0x1c2e776b, 0xb5a821c8, 0xed28c31f, 0xa6a3fd55, + 0xfe231f82, 0x57a54921, 0x0f25abf6, 0xc1b334b5, 0x9933d662, + 0x30b580c1, 0x68356216, 0x23be5c5c, 0x7b3ebe8b, 0xd2b8e828, + 0x8a380aff, 0x4e95d7af, 0x16153578, 0xbf9363db, 0xe713810c, + 0xac98bf46, 0xf4185d91, 0x5d9e0b32, 0x051ee9e5, 0xcb8876a6, + 0x93089471, 0x3a8ec2d2, 0x620e2005, 0x29851e4f, 0x7105fc98, + 0xd883aa3b, 0x800348ec, 0x783419d7, 0x20b4fb00, 0x8932ada3, + 0xd1b24f74, 0x9a39713e, 0xc2b993e9, 0x6b3fc54a, 0x33bf279d, + 0xfd29b8de, 0xa5a95a09, 0x0c2f0caa, 0x54afee7d, 0x1f24d037, + 0x47a432e0, 0xee226443, 0xb6a28694, 0x720f5bc4, 0x2a8fb913, + 0x8309efb0, 0xdb890d67, 0x9002332d, 0xc882d1fa, 0x61048759, + 0x3984658e, 0xf712facd, 0xaf92181a, 0x06144eb9, 0x5e94ac6e, + 0x151f9224, 0x4d9f70f3, 0xe4192650, 0xbc99c487, 0x6c429df1, + 0x34c27f26, 0x9d442985, 0xc5c4cb52, 0x8e4ff518, 0xd6cf17cf, + 0x7f49416c, 0x27c9a3bb, 0xe95f3cf8, 0xb1dfde2f, 0x1859888c, + 0x40d96a5b, 0x0b525411, 0x53d2b6c6, 0xfa54e065, 0xa2d402b2, + 0x6679dfe2, 0x3ef93d35, 0x977f6b96, 0xcfff8941, 0x8474b70b, + 0xdcf455dc, 0x7572037f, 0x2df2e1a8, 0xe3647eeb, 0xbbe49c3c, + 0x1262ca9f, 0x4ae22848, 0x01691602, 0x59e9f4d5, 0xf06fa276, + 0xa8ef40a1}, + {0x00000000, 0x463b6765, 0x8c76ceca, 0xca4da9af, 0x59ebed4e, + 0x1fd08a2b, 0xd59d2384, 0x93a644e1, 0xb2d6db9d, 0xf4edbcf8, + 0x3ea01557, 0x789b7232, 0xeb3d36d3, 0xad0651b6, 0x674bf819, + 0x21709f7c, 0x25abc6e0, 0x6390a185, 0xa9dd082a, 0xefe66f4f, + 0x7c402bae, 0x3a7b4ccb, 0xf036e564, 0xb60d8201, 0x977d1d7d, + 0xd1467a18, 0x1b0bd3b7, 0x5d30b4d2, 0xce96f033, 0x88ad9756, + 0x42e03ef9, 0x04db599c, 0x0b50fc1a, 0x4d6b9b7f, 0x872632d0, + 0xc11d55b5, 0x52bb1154, 0x14807631, 0xdecddf9e, 0x98f6b8fb, + 0xb9862787, 0xffbd40e2, 0x35f0e94d, 0x73cb8e28, 0xe06dcac9, + 0xa656adac, 0x6c1b0403, 0x2a206366, 0x2efb3afa, 0x68c05d9f, + 0xa28df430, 0xe4b69355, 0x7710d7b4, 0x312bb0d1, 0xfb66197e, + 0xbd5d7e1b, 0x9c2de167, 0xda168602, 0x105b2fad, 0x566048c8, + 0xc5c60c29, 0x83fd6b4c, 0x49b0c2e3, 0x0f8ba586, 0x16a0f835, + 0x509b9f50, 0x9ad636ff, 0xdced519a, 0x4f4b157b, 0x0970721e, + 0xc33ddbb1, 0x8506bcd4, 0xa47623a8, 0xe24d44cd, 0x2800ed62, + 0x6e3b8a07, 0xfd9dcee6, 0xbba6a983, 0x71eb002c, 0x37d06749, + 0x330b3ed5, 0x753059b0, 0xbf7df01f, 0xf946977a, 0x6ae0d39b, + 0x2cdbb4fe, 0xe6961d51, 0xa0ad7a34, 0x81dde548, 0xc7e6822d, + 0x0dab2b82, 0x4b904ce7, 0xd8360806, 0x9e0d6f63, 0x5440c6cc, + 0x127ba1a9, 0x1df0042f, 0x5bcb634a, 0x9186cae5, 0xd7bdad80, + 0x441be961, 0x02208e04, 0xc86d27ab, 0x8e5640ce, 0xaf26dfb2, + 0xe91db8d7, 0x23501178, 0x656b761d, 0xf6cd32fc, 0xb0f65599, + 0x7abbfc36, 0x3c809b53, 0x385bc2cf, 0x7e60a5aa, 0xb42d0c05, + 0xf2166b60, 0x61b02f81, 0x278b48e4, 0xedc6e14b, 0xabfd862e, + 0x8a8d1952, 0xccb67e37, 0x06fbd798, 0x40c0b0fd, 0xd366f41c, + 0x955d9379, 0x5f103ad6, 0x192b5db3, 0x2c40f16b, 0x6a7b960e, + 0xa0363fa1, 0xe60d58c4, 0x75ab1c25, 0x33907b40, 0xf9ddd2ef, + 0xbfe6b58a, 0x9e962af6, 0xd8ad4d93, 0x12e0e43c, 0x54db8359, + 0xc77dc7b8, 0x8146a0dd, 0x4b0b0972, 0x0d306e17, 0x09eb378b, + 0x4fd050ee, 0x859df941, 0xc3a69e24, 0x5000dac5, 0x163bbda0, + 0xdc76140f, 0x9a4d736a, 0xbb3dec16, 0xfd068b73, 0x374b22dc, + 0x717045b9, 0xe2d60158, 0xa4ed663d, 0x6ea0cf92, 0x289ba8f7, + 0x27100d71, 0x612b6a14, 0xab66c3bb, 0xed5da4de, 0x7efbe03f, + 0x38c0875a, 0xf28d2ef5, 0xb4b64990, 0x95c6d6ec, 0xd3fdb189, + 0x19b01826, 0x5f8b7f43, 0xcc2d3ba2, 0x8a165cc7, 0x405bf568, + 0x0660920d, 0x02bbcb91, 0x4480acf4, 0x8ecd055b, 0xc8f6623e, + 0x5b5026df, 0x1d6b41ba, 0xd726e815, 0x911d8f70, 0xb06d100c, + 0xf6567769, 0x3c1bdec6, 0x7a20b9a3, 0xe986fd42, 0xafbd9a27, + 0x65f03388, 0x23cb54ed, 0x3ae0095e, 0x7cdb6e3b, 0xb696c794, + 0xf0ada0f1, 0x630be410, 0x25308375, 0xef7d2ada, 0xa9464dbf, + 0x8836d2c3, 0xce0db5a6, 0x04401c09, 0x427b7b6c, 0xd1dd3f8d, + 0x97e658e8, 0x5dabf147, 0x1b909622, 0x1f4bcfbe, 0x5970a8db, + 0x933d0174, 0xd5066611, 0x46a022f0, 0x009b4595, 0xcad6ec3a, + 0x8ced8b5f, 0xad9d1423, 0xeba67346, 0x21ebdae9, 0x67d0bd8c, + 0xf476f96d, 0xb24d9e08, 0x780037a7, 0x3e3b50c2, 0x31b0f544, + 0x778b9221, 0xbdc63b8e, 0xfbfd5ceb, 0x685b180a, 0x2e607f6f, + 0xe42dd6c0, 0xa216b1a5, 0x83662ed9, 0xc55d49bc, 0x0f10e013, + 0x492b8776, 0xda8dc397, 0x9cb6a4f2, 0x56fb0d5d, 0x10c06a38, + 0x141b33a4, 0x522054c1, 0x986dfd6e, 0xde569a0b, 0x4df0deea, + 0x0bcbb98f, 0xc1861020, 0x87bd7745, 0xa6cde839, 0xe0f68f5c, + 0x2abb26f3, 0x6c804196, 0xff260577, 0xb91d6212, 0x7350cbbd, + 0x356bacd8}}; + +#endif + +#endif + +#if N == 6 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0x3db1ecdc, 0x7b63d9b8, 0x46d23564, 0xf6c7b370, + 0xcb765fac, 0x8da46ac8, 0xb0158614, 0x36fe60a1, 0x0b4f8c7d, + 0x4d9db919, 0x702c55c5, 0xc039d3d1, 0xfd883f0d, 0xbb5a0a69, + 0x86ebe6b5, 0x6dfcc142, 0x504d2d9e, 0x169f18fa, 0x2b2ef426, + 0x9b3b7232, 0xa68a9eee, 0xe058ab8a, 0xdde94756, 0x5b02a1e3, + 0x66b34d3f, 0x2061785b, 0x1dd09487, 0xadc51293, 0x9074fe4f, + 0xd6a6cb2b, 0xeb1727f7, 0xdbf98284, 0xe6486e58, 0xa09a5b3c, + 0x9d2bb7e0, 0x2d3e31f4, 0x108fdd28, 0x565de84c, 0x6bec0490, + 0xed07e225, 0xd0b60ef9, 0x96643b9d, 0xabd5d741, 0x1bc05155, + 0x2671bd89, 0x60a388ed, 0x5d126431, 0xb60543c6, 0x8bb4af1a, + 0xcd669a7e, 0xf0d776a2, 0x40c2f0b6, 0x7d731c6a, 0x3ba1290e, + 0x0610c5d2, 0x80fb2367, 0xbd4acfbb, 0xfb98fadf, 0xc6291603, + 0x763c9017, 0x4b8d7ccb, 0x0d5f49af, 0x30eea573, 0x6c820349, + 0x5133ef95, 0x17e1daf1, 0x2a50362d, 0x9a45b039, 0xa7f45ce5, + 0xe1266981, 0xdc97855d, 0x5a7c63e8, 0x67cd8f34, 0x211fba50, + 0x1cae568c, 0xacbbd098, 0x910a3c44, 0xd7d80920, 0xea69e5fc, + 0x017ec20b, 0x3ccf2ed7, 0x7a1d1bb3, 0x47acf76f, 0xf7b9717b, + 0xca089da7, 0x8cdaa8c3, 0xb16b441f, 0x3780a2aa, 0x0a314e76, + 0x4ce37b12, 0x715297ce, 0xc14711da, 0xfcf6fd06, 0xba24c862, + 0x879524be, 0xb77b81cd, 0x8aca6d11, 0xcc185875, 0xf1a9b4a9, + 0x41bc32bd, 0x7c0dde61, 0x3adfeb05, 0x076e07d9, 0x8185e16c, + 0xbc340db0, 0xfae638d4, 0xc757d408, 0x7742521c, 0x4af3bec0, + 0x0c218ba4, 0x31906778, 0xda87408f, 0xe736ac53, 0xa1e49937, + 0x9c5575eb, 0x2c40f3ff, 0x11f11f23, 0x57232a47, 0x6a92c69b, + 0xec79202e, 0xd1c8ccf2, 0x971af996, 0xaaab154a, 0x1abe935e, + 0x270f7f82, 0x61dd4ae6, 0x5c6ca63a, 0xd9040692, 0xe4b5ea4e, + 0xa267df2a, 0x9fd633f6, 0x2fc3b5e2, 0x1272593e, 0x54a06c5a, + 0x69118086, 0xeffa6633, 0xd24b8aef, 0x9499bf8b, 0xa9285357, + 0x193dd543, 0x248c399f, 0x625e0cfb, 0x5fefe027, 0xb4f8c7d0, + 0x89492b0c, 0xcf9b1e68, 0xf22af2b4, 0x423f74a0, 0x7f8e987c, + 0x395cad18, 0x04ed41c4, 0x8206a771, 0xbfb74bad, 0xf9657ec9, + 0xc4d49215, 0x74c11401, 0x4970f8dd, 0x0fa2cdb9, 0x32132165, + 0x02fd8416, 0x3f4c68ca, 0x799e5dae, 0x442fb172, 0xf43a3766, + 0xc98bdbba, 0x8f59eede, 0xb2e80202, 0x3403e4b7, 0x09b2086b, + 0x4f603d0f, 0x72d1d1d3, 0xc2c457c7, 0xff75bb1b, 0xb9a78e7f, + 0x841662a3, 0x6f014554, 0x52b0a988, 0x14629cec, 0x29d37030, + 0x99c6f624, 0xa4771af8, 0xe2a52f9c, 0xdf14c340, 0x59ff25f5, + 0x644ec929, 0x229cfc4d, 0x1f2d1091, 0xaf389685, 0x92897a59, + 0xd45b4f3d, 0xe9eaa3e1, 0xb58605db, 0x8837e907, 0xcee5dc63, + 0xf35430bf, 0x4341b6ab, 0x7ef05a77, 0x38226f13, 0x059383cf, + 0x8378657a, 0xbec989a6, 0xf81bbcc2, 0xc5aa501e, 0x75bfd60a, + 0x480e3ad6, 0x0edc0fb2, 0x336de36e, 0xd87ac499, 0xe5cb2845, + 0xa3191d21, 0x9ea8f1fd, 0x2ebd77e9, 0x130c9b35, 0x55deae51, + 0x686f428d, 0xee84a438, 0xd33548e4, 0x95e77d80, 0xa856915c, + 0x18431748, 0x25f2fb94, 0x6320cef0, 0x5e91222c, 0x6e7f875f, + 0x53ce6b83, 0x151c5ee7, 0x28adb23b, 0x98b8342f, 0xa509d8f3, + 0xe3dbed97, 0xde6a014b, 0x5881e7fe, 0x65300b22, 0x23e23e46, + 0x1e53d29a, 0xae46548e, 0x93f7b852, 0xd5258d36, 0xe89461ea, + 0x0383461d, 0x3e32aac1, 0x78e09fa5, 0x45517379, 0xf544f56d, + 0xc8f519b1, 0x8e272cd5, 0xb396c009, 0x357d26bc, 0x08ccca60, + 0x4e1eff04, 0x73af13d8, 0xc3ba95cc, 0xfe0b7910, 0xb8d94c74, + 0x8568a0a8}, + {0x00000000, 0x69790b65, 0xd2f216ca, 0xbb8b1daf, 0x7e952bd5, + 0x17ec20b0, 0xac673d1f, 0xc51e367a, 0xfd2a57aa, 0x94535ccf, + 0x2fd84160, 0x46a14a05, 0x83bf7c7f, 0xeac6771a, 0x514d6ab5, + 0x383461d0, 0x2125a915, 0x485ca270, 0xf3d7bfdf, 0x9aaeb4ba, + 0x5fb082c0, 0x36c989a5, 0x8d42940a, 0xe43b9f6f, 0xdc0ffebf, + 0xb576f5da, 0x0efde875, 0x6784e310, 0xa29ad56a, 0xcbe3de0f, + 0x7068c3a0, 0x1911c8c5, 0x424b522a, 0x2b32594f, 0x90b944e0, + 0xf9c04f85, 0x3cde79ff, 0x55a7729a, 0xee2c6f35, 0x87556450, + 0xbf610580, 0xd6180ee5, 0x6d93134a, 0x04ea182f, 0xc1f42e55, + 0xa88d2530, 0x1306389f, 0x7a7f33fa, 0x636efb3f, 0x0a17f05a, + 0xb19cedf5, 0xd8e5e690, 0x1dfbd0ea, 0x7482db8f, 0xcf09c620, + 0xa670cd45, 0x9e44ac95, 0xf73da7f0, 0x4cb6ba5f, 0x25cfb13a, + 0xe0d18740, 0x89a88c25, 0x3223918a, 0x5b5a9aef, 0x8496a454, + 0xedefaf31, 0x5664b29e, 0x3f1db9fb, 0xfa038f81, 0x937a84e4, + 0x28f1994b, 0x4188922e, 0x79bcf3fe, 0x10c5f89b, 0xab4ee534, + 0xc237ee51, 0x0729d82b, 0x6e50d34e, 0xd5dbcee1, 0xbca2c584, + 0xa5b30d41, 0xccca0624, 0x77411b8b, 0x1e3810ee, 0xdb262694, + 0xb25f2df1, 0x09d4305e, 0x60ad3b3b, 0x58995aeb, 0x31e0518e, + 0x8a6b4c21, 0xe3124744, 0x260c713e, 0x4f757a5b, 0xf4fe67f4, + 0x9d876c91, 0xc6ddf67e, 0xafa4fd1b, 0x142fe0b4, 0x7d56ebd1, + 0xb848ddab, 0xd131d6ce, 0x6abacb61, 0x03c3c004, 0x3bf7a1d4, + 0x528eaab1, 0xe905b71e, 0x807cbc7b, 0x45628a01, 0x2c1b8164, + 0x97909ccb, 0xfee997ae, 0xe7f85f6b, 0x8e81540e, 0x350a49a1, + 0x5c7342c4, 0x996d74be, 0xf0147fdb, 0x4b9f6274, 0x22e66911, + 0x1ad208c1, 0x73ab03a4, 0xc8201e0b, 0xa159156e, 0x64472314, + 0x0d3e2871, 0xb6b535de, 0xdfcc3ebb, 0xd25c4ee9, 0xbb25458c, + 0x00ae5823, 0x69d75346, 0xacc9653c, 0xc5b06e59, 0x7e3b73f6, + 0x17427893, 0x2f761943, 0x460f1226, 0xfd840f89, 0x94fd04ec, + 0x51e33296, 0x389a39f3, 0x8311245c, 0xea682f39, 0xf379e7fc, + 0x9a00ec99, 0x218bf136, 0x48f2fa53, 0x8deccc29, 0xe495c74c, + 0x5f1edae3, 0x3667d186, 0x0e53b056, 0x672abb33, 0xdca1a69c, + 0xb5d8adf9, 0x70c69b83, 0x19bf90e6, 0xa2348d49, 0xcb4d862c, + 0x90171cc3, 0xf96e17a6, 0x42e50a09, 0x2b9c016c, 0xee823716, + 0x87fb3c73, 0x3c7021dc, 0x55092ab9, 0x6d3d4b69, 0x0444400c, + 0xbfcf5da3, 0xd6b656c6, 0x13a860bc, 0x7ad16bd9, 0xc15a7676, + 0xa8237d13, 0xb132b5d6, 0xd84bbeb3, 0x63c0a31c, 0x0ab9a879, + 0xcfa79e03, 0xa6de9566, 0x1d5588c9, 0x742c83ac, 0x4c18e27c, + 0x2561e919, 0x9eeaf4b6, 0xf793ffd3, 0x328dc9a9, 0x5bf4c2cc, + 0xe07fdf63, 0x8906d406, 0x56caeabd, 0x3fb3e1d8, 0x8438fc77, + 0xed41f712, 0x285fc168, 0x4126ca0d, 0xfaadd7a2, 0x93d4dcc7, + 0xabe0bd17, 0xc299b672, 0x7912abdd, 0x106ba0b8, 0xd57596c2, + 0xbc0c9da7, 0x07878008, 0x6efe8b6d, 0x77ef43a8, 0x1e9648cd, + 0xa51d5562, 0xcc645e07, 0x097a687d, 0x60036318, 0xdb887eb7, + 0xb2f175d2, 0x8ac51402, 0xe3bc1f67, 0x583702c8, 0x314e09ad, + 0xf4503fd7, 0x9d2934b2, 0x26a2291d, 0x4fdb2278, 0x1481b897, + 0x7df8b3f2, 0xc673ae5d, 0xaf0aa538, 0x6a149342, 0x036d9827, + 0xb8e68588, 0xd19f8eed, 0xe9abef3d, 0x80d2e458, 0x3b59f9f7, + 0x5220f292, 0x973ec4e8, 0xfe47cf8d, 0x45ccd222, 0x2cb5d947, + 0x35a41182, 0x5cdd1ae7, 0xe7560748, 0x8e2f0c2d, 0x4b313a57, + 0x22483132, 0x99c32c9d, 0xf0ba27f8, 0xc88e4628, 0xa1f74d4d, + 0x1a7c50e2, 0x73055b87, 0xb61b6dfd, 0xdf626698, 0x64e97b37, + 0x0d907052}, + {0x00000000, 0x7fc99b93, 0xff933726, 0x805aacb5, 0x2457680d, + 0x5b9ef39e, 0xdbc45f2b, 0xa40dc4b8, 0x48aed01a, 0x37674b89, + 0xb73de73c, 0xc8f47caf, 0x6cf9b817, 0x13302384, 0x936a8f31, + 0xeca314a2, 0x915da034, 0xee943ba7, 0x6ece9712, 0x11070c81, + 0xb50ac839, 0xcac353aa, 0x4a99ff1f, 0x3550648c, 0xd9f3702e, + 0xa63aebbd, 0x26604708, 0x59a9dc9b, 0xfda41823, 0x826d83b0, + 0x02372f05, 0x7dfeb496, 0xf9ca4629, 0x8603ddba, 0x0659710f, + 0x7990ea9c, 0xdd9d2e24, 0xa254b5b7, 0x220e1902, 0x5dc78291, + 0xb1649633, 0xcead0da0, 0x4ef7a115, 0x313e3a86, 0x9533fe3e, + 0xeafa65ad, 0x6aa0c918, 0x1569528b, 0x6897e61d, 0x175e7d8e, + 0x9704d13b, 0xe8cd4aa8, 0x4cc08e10, 0x33091583, 0xb353b936, + 0xcc9a22a5, 0x20393607, 0x5ff0ad94, 0xdfaa0121, 0xa0639ab2, + 0x046e5e0a, 0x7ba7c599, 0xfbfd692c, 0x8434f2bf, 0x28e58a13, + 0x572c1180, 0xd776bd35, 0xa8bf26a6, 0x0cb2e21e, 0x737b798d, + 0xf321d538, 0x8ce84eab, 0x604b5a09, 0x1f82c19a, 0x9fd86d2f, + 0xe011f6bc, 0x441c3204, 0x3bd5a997, 0xbb8f0522, 0xc4469eb1, + 0xb9b82a27, 0xc671b1b4, 0x462b1d01, 0x39e28692, 0x9def422a, + 0xe226d9b9, 0x627c750c, 0x1db5ee9f, 0xf116fa3d, 0x8edf61ae, + 0x0e85cd1b, 0x714c5688, 0xd5419230, 0xaa8809a3, 0x2ad2a516, + 0x551b3e85, 0xd12fcc3a, 0xaee657a9, 0x2ebcfb1c, 0x5175608f, + 0xf578a437, 0x8ab13fa4, 0x0aeb9311, 0x75220882, 0x99811c20, + 0xe64887b3, 0x66122b06, 0x19dbb095, 0xbdd6742d, 0xc21fefbe, + 0x4245430b, 0x3d8cd898, 0x40726c0e, 0x3fbbf79d, 0xbfe15b28, + 0xc028c0bb, 0x64250403, 0x1bec9f90, 0x9bb63325, 0xe47fa8b6, + 0x08dcbc14, 0x77152787, 0xf74f8b32, 0x888610a1, 0x2c8bd419, + 0x53424f8a, 0xd318e33f, 0xacd178ac, 0x51cb1426, 0x2e028fb5, + 0xae582300, 0xd191b893, 0x759c7c2b, 0x0a55e7b8, 0x8a0f4b0d, + 0xf5c6d09e, 0x1965c43c, 0x66ac5faf, 0xe6f6f31a, 0x993f6889, + 0x3d32ac31, 0x42fb37a2, 0xc2a19b17, 0xbd680084, 0xc096b412, + 0xbf5f2f81, 0x3f058334, 0x40cc18a7, 0xe4c1dc1f, 0x9b08478c, + 0x1b52eb39, 0x649b70aa, 0x88386408, 0xf7f1ff9b, 0x77ab532e, + 0x0862c8bd, 0xac6f0c05, 0xd3a69796, 0x53fc3b23, 0x2c35a0b0, + 0xa801520f, 0xd7c8c99c, 0x57926529, 0x285bfeba, 0x8c563a02, + 0xf39fa191, 0x73c50d24, 0x0c0c96b7, 0xe0af8215, 0x9f661986, + 0x1f3cb533, 0x60f52ea0, 0xc4f8ea18, 0xbb31718b, 0x3b6bdd3e, + 0x44a246ad, 0x395cf23b, 0x469569a8, 0xc6cfc51d, 0xb9065e8e, + 0x1d0b9a36, 0x62c201a5, 0xe298ad10, 0x9d513683, 0x71f22221, + 0x0e3bb9b2, 0x8e611507, 0xf1a88e94, 0x55a54a2c, 0x2a6cd1bf, + 0xaa367d0a, 0xd5ffe699, 0x792e9e35, 0x06e705a6, 0x86bda913, + 0xf9743280, 0x5d79f638, 0x22b06dab, 0xa2eac11e, 0xdd235a8d, + 0x31804e2f, 0x4e49d5bc, 0xce137909, 0xb1dae29a, 0x15d72622, + 0x6a1ebdb1, 0xea441104, 0x958d8a97, 0xe8733e01, 0x97baa592, + 0x17e00927, 0x682992b4, 0xcc24560c, 0xb3edcd9f, 0x33b7612a, + 0x4c7efab9, 0xa0ddee1b, 0xdf147588, 0x5f4ed93d, 0x208742ae, + 0x848a8616, 0xfb431d85, 0x7b19b130, 0x04d02aa3, 0x80e4d81c, + 0xff2d438f, 0x7f77ef3a, 0x00be74a9, 0xa4b3b011, 0xdb7a2b82, + 0x5b208737, 0x24e91ca4, 0xc84a0806, 0xb7839395, 0x37d93f20, + 0x4810a4b3, 0xec1d600b, 0x93d4fb98, 0x138e572d, 0x6c47ccbe, + 0x11b97828, 0x6e70e3bb, 0xee2a4f0e, 0x91e3d49d, 0x35ee1025, + 0x4a278bb6, 0xca7d2703, 0xb5b4bc90, 0x5917a832, 0x26de33a1, + 0xa6849f14, 0xd94d0487, 0x7d40c03f, 0x02895bac, 0x82d3f719, + 0xfd1a6c8a}, + {0x00000000, 0xa396284c, 0x9c5d56d9, 0x3fcb7e95, 0xe3cbabf3, + 0x405d83bf, 0x7f96fd2a, 0xdc00d566, 0x1ce651a7, 0xbf7079eb, + 0x80bb077e, 0x232d2f32, 0xff2dfa54, 0x5cbbd218, 0x6370ac8d, + 0xc0e684c1, 0x39cca34e, 0x9a5a8b02, 0xa591f597, 0x0607dddb, + 0xda0708bd, 0x799120f1, 0x465a5e64, 0xe5cc7628, 0x252af2e9, + 0x86bcdaa5, 0xb977a430, 0x1ae18c7c, 0xc6e1591a, 0x65777156, + 0x5abc0fc3, 0xf92a278f, 0x7399469c, 0xd00f6ed0, 0xefc41045, + 0x4c523809, 0x9052ed6f, 0x33c4c523, 0x0c0fbbb6, 0xaf9993fa, + 0x6f7f173b, 0xcce93f77, 0xf32241e2, 0x50b469ae, 0x8cb4bcc8, + 0x2f229484, 0x10e9ea11, 0xb37fc25d, 0x4a55e5d2, 0xe9c3cd9e, + 0xd608b30b, 0x759e9b47, 0xa99e4e21, 0x0a08666d, 0x35c318f8, + 0x965530b4, 0x56b3b475, 0xf5259c39, 0xcaeee2ac, 0x6978cae0, + 0xb5781f86, 0x16ee37ca, 0x2925495f, 0x8ab36113, 0xe7328d38, + 0x44a4a574, 0x7b6fdbe1, 0xd8f9f3ad, 0x04f926cb, 0xa76f0e87, + 0x98a47012, 0x3b32585e, 0xfbd4dc9f, 0x5842f4d3, 0x67898a46, + 0xc41fa20a, 0x181f776c, 0xbb895f20, 0x844221b5, 0x27d409f9, + 0xdefe2e76, 0x7d68063a, 0x42a378af, 0xe13550e3, 0x3d358585, + 0x9ea3adc9, 0xa168d35c, 0x02fefb10, 0xc2187fd1, 0x618e579d, + 0x5e452908, 0xfdd30144, 0x21d3d422, 0x8245fc6e, 0xbd8e82fb, + 0x1e18aab7, 0x94abcba4, 0x373de3e8, 0x08f69d7d, 0xab60b531, + 0x77606057, 0xd4f6481b, 0xeb3d368e, 0x48ab1ec2, 0x884d9a03, + 0x2bdbb24f, 0x1410ccda, 0xb786e496, 0x6b8631f0, 0xc81019bc, + 0xf7db6729, 0x544d4f65, 0xad6768ea, 0x0ef140a6, 0x313a3e33, + 0x92ac167f, 0x4eacc319, 0xed3aeb55, 0xd2f195c0, 0x7167bd8c, + 0xb181394d, 0x12171101, 0x2ddc6f94, 0x8e4a47d8, 0x524a92be, + 0xf1dcbaf2, 0xce17c467, 0x6d81ec2b, 0x15141c31, 0xb682347d, + 0x89494ae8, 0x2adf62a4, 0xf6dfb7c2, 0x55499f8e, 0x6a82e11b, + 0xc914c957, 0x09f24d96, 0xaa6465da, 0x95af1b4f, 0x36393303, + 0xea39e665, 0x49afce29, 0x7664b0bc, 0xd5f298f0, 0x2cd8bf7f, + 0x8f4e9733, 0xb085e9a6, 0x1313c1ea, 0xcf13148c, 0x6c853cc0, + 0x534e4255, 0xf0d86a19, 0x303eeed8, 0x93a8c694, 0xac63b801, + 0x0ff5904d, 0xd3f5452b, 0x70636d67, 0x4fa813f2, 0xec3e3bbe, + 0x668d5aad, 0xc51b72e1, 0xfad00c74, 0x59462438, 0x8546f15e, + 0x26d0d912, 0x191ba787, 0xba8d8fcb, 0x7a6b0b0a, 0xd9fd2346, + 0xe6365dd3, 0x45a0759f, 0x99a0a0f9, 0x3a3688b5, 0x05fdf620, + 0xa66bde6c, 0x5f41f9e3, 0xfcd7d1af, 0xc31caf3a, 0x608a8776, + 0xbc8a5210, 0x1f1c7a5c, 0x20d704c9, 0x83412c85, 0x43a7a844, + 0xe0318008, 0xdffafe9d, 0x7c6cd6d1, 0xa06c03b7, 0x03fa2bfb, + 0x3c31556e, 0x9fa77d22, 0xf2269109, 0x51b0b945, 0x6e7bc7d0, + 0xcdedef9c, 0x11ed3afa, 0xb27b12b6, 0x8db06c23, 0x2e26446f, + 0xeec0c0ae, 0x4d56e8e2, 0x729d9677, 0xd10bbe3b, 0x0d0b6b5d, + 0xae9d4311, 0x91563d84, 0x32c015c8, 0xcbea3247, 0x687c1a0b, + 0x57b7649e, 0xf4214cd2, 0x282199b4, 0x8bb7b1f8, 0xb47ccf6d, + 0x17eae721, 0xd70c63e0, 0x749a4bac, 0x4b513539, 0xe8c71d75, + 0x34c7c813, 0x9751e05f, 0xa89a9eca, 0x0b0cb686, 0x81bfd795, + 0x2229ffd9, 0x1de2814c, 0xbe74a900, 0x62747c66, 0xc1e2542a, + 0xfe292abf, 0x5dbf02f3, 0x9d598632, 0x3ecfae7e, 0x0104d0eb, + 0xa292f8a7, 0x7e922dc1, 0xdd04058d, 0xe2cf7b18, 0x41595354, + 0xb87374db, 0x1be55c97, 0x242e2202, 0x87b80a4e, 0x5bb8df28, + 0xf82ef764, 0xc7e589f1, 0x6473a1bd, 0xa495257c, 0x07030d30, + 0x38c873a5, 0x9b5e5be9, 0x475e8e8f, 0xe4c8a6c3, 0xdb03d856, + 0x7895f01a}, + {0x00000000, 0x2a283862, 0x545070c4, 0x7e7848a6, 0xa8a0e188, + 0x8288d9ea, 0xfcf0914c, 0xd6d8a92e, 0x8a30c551, 0xa018fd33, + 0xde60b595, 0xf4488df7, 0x229024d9, 0x08b81cbb, 0x76c0541d, + 0x5ce86c7f, 0xcf108ce3, 0xe538b481, 0x9b40fc27, 0xb168c445, + 0x67b06d6b, 0x4d985509, 0x33e01daf, 0x19c825cd, 0x452049b2, + 0x6f0871d0, 0x11703976, 0x3b580114, 0xed80a83a, 0xc7a89058, + 0xb9d0d8fe, 0x93f8e09c, 0x45501f87, 0x6f7827e5, 0x11006f43, + 0x3b285721, 0xedf0fe0f, 0xc7d8c66d, 0xb9a08ecb, 0x9388b6a9, + 0xcf60dad6, 0xe548e2b4, 0x9b30aa12, 0xb1189270, 0x67c03b5e, + 0x4de8033c, 0x33904b9a, 0x19b873f8, 0x8a409364, 0xa068ab06, + 0xde10e3a0, 0xf438dbc2, 0x22e072ec, 0x08c84a8e, 0x76b00228, + 0x5c983a4a, 0x00705635, 0x2a586e57, 0x542026f1, 0x7e081e93, + 0xa8d0b7bd, 0x82f88fdf, 0xfc80c779, 0xd6a8ff1b, 0x8aa03f0e, + 0xa088076c, 0xdef04fca, 0xf4d877a8, 0x2200de86, 0x0828e6e4, + 0x7650ae42, 0x5c789620, 0x0090fa5f, 0x2ab8c23d, 0x54c08a9b, + 0x7ee8b2f9, 0xa8301bd7, 0x821823b5, 0xfc606b13, 0xd6485371, + 0x45b0b3ed, 0x6f988b8f, 0x11e0c329, 0x3bc8fb4b, 0xed105265, + 0xc7386a07, 0xb94022a1, 0x93681ac3, 0xcf8076bc, 0xe5a84ede, + 0x9bd00678, 0xb1f83e1a, 0x67209734, 0x4d08af56, 0x3370e7f0, + 0x1958df92, 0xcff02089, 0xe5d818eb, 0x9ba0504d, 0xb188682f, + 0x6750c101, 0x4d78f963, 0x3300b1c5, 0x192889a7, 0x45c0e5d8, + 0x6fe8ddba, 0x1190951c, 0x3bb8ad7e, 0xed600450, 0xc7483c32, + 0xb9307494, 0x93184cf6, 0x00e0ac6a, 0x2ac89408, 0x54b0dcae, + 0x7e98e4cc, 0xa8404de2, 0x82687580, 0xfc103d26, 0xd6380544, + 0x8ad0693b, 0xa0f85159, 0xde8019ff, 0xf4a8219d, 0x227088b3, + 0x0858b0d1, 0x7620f877, 0x5c08c015, 0xce31785d, 0xe419403f, + 0x9a610899, 0xb04930fb, 0x669199d5, 0x4cb9a1b7, 0x32c1e911, + 0x18e9d173, 0x4401bd0c, 0x6e29856e, 0x1051cdc8, 0x3a79f5aa, + 0xeca15c84, 0xc68964e6, 0xb8f12c40, 0x92d91422, 0x0121f4be, + 0x2b09ccdc, 0x5571847a, 0x7f59bc18, 0xa9811536, 0x83a92d54, + 0xfdd165f2, 0xd7f95d90, 0x8b1131ef, 0xa139098d, 0xdf41412b, + 0xf5697949, 0x23b1d067, 0x0999e805, 0x77e1a0a3, 0x5dc998c1, + 0x8b6167da, 0xa1495fb8, 0xdf31171e, 0xf5192f7c, 0x23c18652, + 0x09e9be30, 0x7791f696, 0x5db9cef4, 0x0151a28b, 0x2b799ae9, + 0x5501d24f, 0x7f29ea2d, 0xa9f14303, 0x83d97b61, 0xfda133c7, + 0xd7890ba5, 0x4471eb39, 0x6e59d35b, 0x10219bfd, 0x3a09a39f, + 0xecd10ab1, 0xc6f932d3, 0xb8817a75, 0x92a94217, 0xce412e68, + 0xe469160a, 0x9a115eac, 0xb03966ce, 0x66e1cfe0, 0x4cc9f782, + 0x32b1bf24, 0x18998746, 0x44914753, 0x6eb97f31, 0x10c13797, + 0x3ae90ff5, 0xec31a6db, 0xc6199eb9, 0xb861d61f, 0x9249ee7d, + 0xcea18202, 0xe489ba60, 0x9af1f2c6, 0xb0d9caa4, 0x6601638a, + 0x4c295be8, 0x3251134e, 0x18792b2c, 0x8b81cbb0, 0xa1a9f3d2, + 0xdfd1bb74, 0xf5f98316, 0x23212a38, 0x0909125a, 0x77715afc, + 0x5d59629e, 0x01b10ee1, 0x2b993683, 0x55e17e25, 0x7fc94647, + 0xa911ef69, 0x8339d70b, 0xfd419fad, 0xd769a7cf, 0x01c158d4, + 0x2be960b6, 0x55912810, 0x7fb91072, 0xa961b95c, 0x8349813e, + 0xfd31c998, 0xd719f1fa, 0x8bf19d85, 0xa1d9a5e7, 0xdfa1ed41, + 0xf589d523, 0x23517c0d, 0x0979446f, 0x77010cc9, 0x5d2934ab, + 0xced1d437, 0xe4f9ec55, 0x9a81a4f3, 0xb0a99c91, 0x667135bf, + 0x4c590ddd, 0x3221457b, 0x18097d19, 0x44e11166, 0x6ec92904, + 0x10b161a2, 0x3a9959c0, 0xec41f0ee, 0xc669c88c, 0xb811802a, + 0x9239b848}, + {0x00000000, 0x4713f6fb, 0x8e27edf6, 0xc9341b0d, 0xc73eddad, + 0x802d2b56, 0x4919305b, 0x0e0ac6a0, 0x550cbd1b, 0x121f4be0, + 0xdb2b50ed, 0x9c38a616, 0x923260b6, 0xd521964d, 0x1c158d40, + 0x5b067bbb, 0xaa197a36, 0xed0a8ccd, 0x243e97c0, 0x632d613b, + 0x6d27a79b, 0x2a345160, 0xe3004a6d, 0xa413bc96, 0xff15c72d, + 0xb80631d6, 0x71322adb, 0x3621dc20, 0x382b1a80, 0x7f38ec7b, + 0xb60cf776, 0xf11f018d, 0x8f43f22d, 0xc85004d6, 0x01641fdb, + 0x4677e920, 0x487d2f80, 0x0f6ed97b, 0xc65ac276, 0x8149348d, + 0xda4f4f36, 0x9d5cb9cd, 0x5468a2c0, 0x137b543b, 0x1d71929b, + 0x5a626460, 0x93567f6d, 0xd4458996, 0x255a881b, 0x62497ee0, + 0xab7d65ed, 0xec6e9316, 0xe26455b6, 0xa577a34d, 0x6c43b840, + 0x2b504ebb, 0x70563500, 0x3745c3fb, 0xfe71d8f6, 0xb9622e0d, + 0xb768e8ad, 0xf07b1e56, 0x394f055b, 0x7e5cf3a0, 0xc5f6e21b, + 0x82e514e0, 0x4bd10fed, 0x0cc2f916, 0x02c83fb6, 0x45dbc94d, + 0x8cefd240, 0xcbfc24bb, 0x90fa5f00, 0xd7e9a9fb, 0x1eddb2f6, + 0x59ce440d, 0x57c482ad, 0x10d77456, 0xd9e36f5b, 0x9ef099a0, + 0x6fef982d, 0x28fc6ed6, 0xe1c875db, 0xa6db8320, 0xa8d14580, + 0xefc2b37b, 0x26f6a876, 0x61e55e8d, 0x3ae32536, 0x7df0d3cd, + 0xb4c4c8c0, 0xf3d73e3b, 0xfdddf89b, 0xbace0e60, 0x73fa156d, + 0x34e9e396, 0x4ab51036, 0x0da6e6cd, 0xc492fdc0, 0x83810b3b, + 0x8d8bcd9b, 0xca983b60, 0x03ac206d, 0x44bfd696, 0x1fb9ad2d, + 0x58aa5bd6, 0x919e40db, 0xd68db620, 0xd8877080, 0x9f94867b, + 0x56a09d76, 0x11b36b8d, 0xe0ac6a00, 0xa7bf9cfb, 0x6e8b87f6, + 0x2998710d, 0x2792b7ad, 0x60814156, 0xa9b55a5b, 0xeea6aca0, + 0xb5a0d71b, 0xf2b321e0, 0x3b873aed, 0x7c94cc16, 0x729e0ab6, + 0x358dfc4d, 0xfcb9e740, 0xbbaa11bb, 0x509cc277, 0x178f348c, + 0xdebb2f81, 0x99a8d97a, 0x97a21fda, 0xd0b1e921, 0x1985f22c, + 0x5e9604d7, 0x05907f6c, 0x42838997, 0x8bb7929a, 0xcca46461, + 0xc2aea2c1, 0x85bd543a, 0x4c894f37, 0x0b9ab9cc, 0xfa85b841, + 0xbd964eba, 0x74a255b7, 0x33b1a34c, 0x3dbb65ec, 0x7aa89317, + 0xb39c881a, 0xf48f7ee1, 0xaf89055a, 0xe89af3a1, 0x21aee8ac, + 0x66bd1e57, 0x68b7d8f7, 0x2fa42e0c, 0xe6903501, 0xa183c3fa, + 0xdfdf305a, 0x98ccc6a1, 0x51f8ddac, 0x16eb2b57, 0x18e1edf7, + 0x5ff21b0c, 0x96c60001, 0xd1d5f6fa, 0x8ad38d41, 0xcdc07bba, + 0x04f460b7, 0x43e7964c, 0x4ded50ec, 0x0afea617, 0xc3cabd1a, + 0x84d94be1, 0x75c64a6c, 0x32d5bc97, 0xfbe1a79a, 0xbcf25161, + 0xb2f897c1, 0xf5eb613a, 0x3cdf7a37, 0x7bcc8ccc, 0x20caf777, + 0x67d9018c, 0xaeed1a81, 0xe9feec7a, 0xe7f42ada, 0xa0e7dc21, + 0x69d3c72c, 0x2ec031d7, 0x956a206c, 0xd279d697, 0x1b4dcd9a, + 0x5c5e3b61, 0x5254fdc1, 0x15470b3a, 0xdc731037, 0x9b60e6cc, + 0xc0669d77, 0x87756b8c, 0x4e417081, 0x0952867a, 0x075840da, + 0x404bb621, 0x897fad2c, 0xce6c5bd7, 0x3f735a5a, 0x7860aca1, + 0xb154b7ac, 0xf6474157, 0xf84d87f7, 0xbf5e710c, 0x766a6a01, + 0x31799cfa, 0x6a7fe741, 0x2d6c11ba, 0xe4580ab7, 0xa34bfc4c, + 0xad413aec, 0xea52cc17, 0x2366d71a, 0x647521e1, 0x1a29d241, + 0x5d3a24ba, 0x940e3fb7, 0xd31dc94c, 0xdd170fec, 0x9a04f917, + 0x5330e21a, 0x142314e1, 0x4f256f5a, 0x083699a1, 0xc10282ac, + 0x86117457, 0x881bb2f7, 0xcf08440c, 0x063c5f01, 0x412fa9fa, + 0xb030a877, 0xf7235e8c, 0x3e174581, 0x7904b37a, 0x770e75da, + 0x301d8321, 0xf929982c, 0xbe3a6ed7, 0xe53c156c, 0xa22fe397, + 0x6b1bf89a, 0x2c080e61, 0x2202c8c1, 0x65113e3a, 0xac252537, + 0xeb36d3cc}, + {0x00000000, 0xa13984ee, 0x99020f9d, 0x383b8b73, 0xe975197b, + 0x484c9d95, 0x707716e6, 0xd14e9208, 0x099b34b7, 0xa8a2b059, + 0x90993b2a, 0x31a0bfc4, 0xe0ee2dcc, 0x41d7a922, 0x79ec2251, + 0xd8d5a6bf, 0x1336696e, 0xb20fed80, 0x8a3466f3, 0x2b0de21d, + 0xfa437015, 0x5b7af4fb, 0x63417f88, 0xc278fb66, 0x1aad5dd9, + 0xbb94d937, 0x83af5244, 0x2296d6aa, 0xf3d844a2, 0x52e1c04c, + 0x6ada4b3f, 0xcbe3cfd1, 0x266cd2dc, 0x87555632, 0xbf6edd41, + 0x1e5759af, 0xcf19cba7, 0x6e204f49, 0x561bc43a, 0xf72240d4, + 0x2ff7e66b, 0x8ece6285, 0xb6f5e9f6, 0x17cc6d18, 0xc682ff10, + 0x67bb7bfe, 0x5f80f08d, 0xfeb97463, 0x355abbb2, 0x94633f5c, + 0xac58b42f, 0x0d6130c1, 0xdc2fa2c9, 0x7d162627, 0x452dad54, + 0xe41429ba, 0x3cc18f05, 0x9df80beb, 0xa5c38098, 0x04fa0476, + 0xd5b4967e, 0x748d1290, 0x4cb699e3, 0xed8f1d0d, 0x4cd9a5b8, + 0xede02156, 0xd5dbaa25, 0x74e22ecb, 0xa5acbcc3, 0x0495382d, + 0x3caeb35e, 0x9d9737b0, 0x4542910f, 0xe47b15e1, 0xdc409e92, + 0x7d791a7c, 0xac378874, 0x0d0e0c9a, 0x353587e9, 0x940c0307, + 0x5fefccd6, 0xfed64838, 0xc6edc34b, 0x67d447a5, 0xb69ad5ad, + 0x17a35143, 0x2f98da30, 0x8ea15ede, 0x5674f861, 0xf74d7c8f, + 0xcf76f7fc, 0x6e4f7312, 0xbf01e11a, 0x1e3865f4, 0x2603ee87, + 0x873a6a69, 0x6ab57764, 0xcb8cf38a, 0xf3b778f9, 0x528efc17, + 0x83c06e1f, 0x22f9eaf1, 0x1ac26182, 0xbbfbe56c, 0x632e43d3, + 0xc217c73d, 0xfa2c4c4e, 0x5b15c8a0, 0x8a5b5aa8, 0x2b62de46, + 0x13595535, 0xb260d1db, 0x79831e0a, 0xd8ba9ae4, 0xe0811197, + 0x41b89579, 0x90f60771, 0x31cf839f, 0x09f408ec, 0xa8cd8c02, + 0x70182abd, 0xd121ae53, 0xe91a2520, 0x4823a1ce, 0x996d33c6, + 0x3854b728, 0x006f3c5b, 0xa156b8b5, 0x99b34b70, 0x388acf9e, + 0x00b144ed, 0xa188c003, 0x70c6520b, 0xd1ffd6e5, 0xe9c45d96, + 0x48fdd978, 0x90287fc7, 0x3111fb29, 0x092a705a, 0xa813f4b4, + 0x795d66bc, 0xd864e252, 0xe05f6921, 0x4166edcf, 0x8a85221e, + 0x2bbca6f0, 0x13872d83, 0xb2bea96d, 0x63f03b65, 0xc2c9bf8b, + 0xfaf234f8, 0x5bcbb016, 0x831e16a9, 0x22279247, 0x1a1c1934, + 0xbb259dda, 0x6a6b0fd2, 0xcb528b3c, 0xf369004f, 0x525084a1, + 0xbfdf99ac, 0x1ee61d42, 0x26dd9631, 0x87e412df, 0x56aa80d7, + 0xf7930439, 0xcfa88f4a, 0x6e910ba4, 0xb644ad1b, 0x177d29f5, + 0x2f46a286, 0x8e7f2668, 0x5f31b460, 0xfe08308e, 0xc633bbfd, + 0x670a3f13, 0xace9f0c2, 0x0dd0742c, 0x35ebff5f, 0x94d27bb1, + 0x459ce9b9, 0xe4a56d57, 0xdc9ee624, 0x7da762ca, 0xa572c475, + 0x044b409b, 0x3c70cbe8, 0x9d494f06, 0x4c07dd0e, 0xed3e59e0, + 0xd505d293, 0x743c567d, 0xd56aeec8, 0x74536a26, 0x4c68e155, + 0xed5165bb, 0x3c1ff7b3, 0x9d26735d, 0xa51df82e, 0x04247cc0, + 0xdcf1da7f, 0x7dc85e91, 0x45f3d5e2, 0xe4ca510c, 0x3584c304, + 0x94bd47ea, 0xac86cc99, 0x0dbf4877, 0xc65c87a6, 0x67650348, + 0x5f5e883b, 0xfe670cd5, 0x2f299edd, 0x8e101a33, 0xb62b9140, + 0x171215ae, 0xcfc7b311, 0x6efe37ff, 0x56c5bc8c, 0xf7fc3862, + 0x26b2aa6a, 0x878b2e84, 0xbfb0a5f7, 0x1e892119, 0xf3063c14, + 0x523fb8fa, 0x6a043389, 0xcb3db767, 0x1a73256f, 0xbb4aa181, + 0x83712af2, 0x2248ae1c, 0xfa9d08a3, 0x5ba48c4d, 0x639f073e, + 0xc2a683d0, 0x13e811d8, 0xb2d19536, 0x8aea1e45, 0x2bd39aab, + 0xe030557a, 0x4109d194, 0x79325ae7, 0xd80bde09, 0x09454c01, + 0xa87cc8ef, 0x9047439c, 0x317ec772, 0xe9ab61cd, 0x4892e523, + 0x70a96e50, 0xd190eabe, 0x00de78b6, 0xa1e7fc58, 0x99dc772b, + 0x38e5f3c5}, + {0x00000000, 0xe81790a1, 0x0b5e2703, 0xe349b7a2, 0x16bc4e06, + 0xfeabdea7, 0x1de26905, 0xf5f5f9a4, 0x2d789c0c, 0xc56f0cad, + 0x2626bb0f, 0xce312bae, 0x3bc4d20a, 0xd3d342ab, 0x309af509, + 0xd88d65a8, 0x5af13818, 0xb2e6a8b9, 0x51af1f1b, 0xb9b88fba, + 0x4c4d761e, 0xa45ae6bf, 0x4713511d, 0xaf04c1bc, 0x7789a414, + 0x9f9e34b5, 0x7cd78317, 0x94c013b6, 0x6135ea12, 0x89227ab3, + 0x6a6bcd11, 0x827c5db0, 0xb5e27030, 0x5df5e091, 0xbebc5733, + 0x56abc792, 0xa35e3e36, 0x4b49ae97, 0xa8001935, 0x40178994, + 0x989aec3c, 0x708d7c9d, 0x93c4cb3f, 0x7bd35b9e, 0x8e26a23a, + 0x6631329b, 0x85788539, 0x6d6f1598, 0xef134828, 0x0704d889, + 0xe44d6f2b, 0x0c5aff8a, 0xf9af062e, 0x11b8968f, 0xf2f1212d, + 0x1ae6b18c, 0xc26bd424, 0x2a7c4485, 0xc935f327, 0x21226386, + 0xd4d79a22, 0x3cc00a83, 0xdf89bd21, 0x379e2d80, 0xb0b5e621, + 0x58a27680, 0xbbebc122, 0x53fc5183, 0xa609a827, 0x4e1e3886, + 0xad578f24, 0x45401f85, 0x9dcd7a2d, 0x75daea8c, 0x96935d2e, + 0x7e84cd8f, 0x8b71342b, 0x6366a48a, 0x802f1328, 0x68388389, + 0xea44de39, 0x02534e98, 0xe11af93a, 0x090d699b, 0xfcf8903f, + 0x14ef009e, 0xf7a6b73c, 0x1fb1279d, 0xc73c4235, 0x2f2bd294, + 0xcc626536, 0x2475f597, 0xd1800c33, 0x39979c92, 0xdade2b30, + 0x32c9bb91, 0x05579611, 0xed4006b0, 0x0e09b112, 0xe61e21b3, + 0x13ebd817, 0xfbfc48b6, 0x18b5ff14, 0xf0a26fb5, 0x282f0a1d, + 0xc0389abc, 0x23712d1e, 0xcb66bdbf, 0x3e93441b, 0xd684d4ba, + 0x35cd6318, 0xdddaf3b9, 0x5fa6ae09, 0xb7b13ea8, 0x54f8890a, + 0xbcef19ab, 0x491ae00f, 0xa10d70ae, 0x4244c70c, 0xaa5357ad, + 0x72de3205, 0x9ac9a2a4, 0x79801506, 0x919785a7, 0x64627c03, + 0x8c75eca2, 0x6f3c5b00, 0x872bcba1, 0xba1aca03, 0x520d5aa2, + 0xb144ed00, 0x59537da1, 0xaca68405, 0x44b114a4, 0xa7f8a306, + 0x4fef33a7, 0x9762560f, 0x7f75c6ae, 0x9c3c710c, 0x742be1ad, + 0x81de1809, 0x69c988a8, 0x8a803f0a, 0x6297afab, 0xe0ebf21b, + 0x08fc62ba, 0xebb5d518, 0x03a245b9, 0xf657bc1d, 0x1e402cbc, + 0xfd099b1e, 0x151e0bbf, 0xcd936e17, 0x2584feb6, 0xc6cd4914, + 0x2edad9b5, 0xdb2f2011, 0x3338b0b0, 0xd0710712, 0x386697b3, + 0x0ff8ba33, 0xe7ef2a92, 0x04a69d30, 0xecb10d91, 0x1944f435, + 0xf1536494, 0x121ad336, 0xfa0d4397, 0x2280263f, 0xca97b69e, + 0x29de013c, 0xc1c9919d, 0x343c6839, 0xdc2bf898, 0x3f624f3a, + 0xd775df9b, 0x5509822b, 0xbd1e128a, 0x5e57a528, 0xb6403589, + 0x43b5cc2d, 0xaba25c8c, 0x48ebeb2e, 0xa0fc7b8f, 0x78711e27, + 0x90668e86, 0x732f3924, 0x9b38a985, 0x6ecd5021, 0x86dac080, + 0x65937722, 0x8d84e783, 0x0aaf2c22, 0xe2b8bc83, 0x01f10b21, + 0xe9e69b80, 0x1c136224, 0xf404f285, 0x174d4527, 0xff5ad586, + 0x27d7b02e, 0xcfc0208f, 0x2c89972d, 0xc49e078c, 0x316bfe28, + 0xd97c6e89, 0x3a35d92b, 0xd222498a, 0x505e143a, 0xb849849b, + 0x5b003339, 0xb317a398, 0x46e25a3c, 0xaef5ca9d, 0x4dbc7d3f, + 0xa5abed9e, 0x7d268836, 0x95311897, 0x7678af35, 0x9e6f3f94, + 0x6b9ac630, 0x838d5691, 0x60c4e133, 0x88d37192, 0xbf4d5c12, + 0x575accb3, 0xb4137b11, 0x5c04ebb0, 0xa9f11214, 0x41e682b5, + 0xa2af3517, 0x4ab8a5b6, 0x9235c01e, 0x7a2250bf, 0x996be71d, + 0x717c77bc, 0x84898e18, 0x6c9e1eb9, 0x8fd7a91b, 0x67c039ba, + 0xe5bc640a, 0x0dabf4ab, 0xeee24309, 0x06f5d3a8, 0xf3002a0c, + 0x1b17baad, 0xf85e0d0f, 0x10499dae, 0xc8c4f806, 0x20d368a7, + 0xc39adf05, 0x2b8d4fa4, 0xde78b600, 0x366f26a1, 0xd5269103, + 0x3d3101a2}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0xa19017e800000000, 0x03275e0b00000000, + 0xa2b749e300000000, 0x064ebc1600000000, 0xa7deabfe00000000, + 0x0569e21d00000000, 0xa4f9f5f500000000, 0x0c9c782d00000000, + 0xad0c6fc500000000, 0x0fbb262600000000, 0xae2b31ce00000000, + 0x0ad2c43b00000000, 0xab42d3d300000000, 0x09f59a3000000000, + 0xa8658dd800000000, 0x1838f15a00000000, 0xb9a8e6b200000000, + 0x1b1faf5100000000, 0xba8fb8b900000000, 0x1e764d4c00000000, + 0xbfe65aa400000000, 0x1d51134700000000, 0xbcc104af00000000, + 0x14a4897700000000, 0xb5349e9f00000000, 0x1783d77c00000000, + 0xb613c09400000000, 0x12ea356100000000, 0xb37a228900000000, + 0x11cd6b6a00000000, 0xb05d7c8200000000, 0x3070e2b500000000, + 0x91e0f55d00000000, 0x3357bcbe00000000, 0x92c7ab5600000000, + 0x363e5ea300000000, 0x97ae494b00000000, 0x351900a800000000, + 0x9489174000000000, 0x3cec9a9800000000, 0x9d7c8d7000000000, + 0x3fcbc49300000000, 0x9e5bd37b00000000, 0x3aa2268e00000000, + 0x9b32316600000000, 0x3985788500000000, 0x98156f6d00000000, + 0x284813ef00000000, 0x89d8040700000000, 0x2b6f4de400000000, + 0x8aff5a0c00000000, 0x2e06aff900000000, 0x8f96b81100000000, + 0x2d21f1f200000000, 0x8cb1e61a00000000, 0x24d46bc200000000, + 0x85447c2a00000000, 0x27f335c900000000, 0x8663222100000000, + 0x229ad7d400000000, 0x830ac03c00000000, 0x21bd89df00000000, + 0x802d9e3700000000, 0x21e6b5b000000000, 0x8076a25800000000, + 0x22c1ebbb00000000, 0x8351fc5300000000, 0x27a809a600000000, + 0x86381e4e00000000, 0x248f57ad00000000, 0x851f404500000000, + 0x2d7acd9d00000000, 0x8ceada7500000000, 0x2e5d939600000000, + 0x8fcd847e00000000, 0x2b34718b00000000, 0x8aa4666300000000, + 0x28132f8000000000, 0x8983386800000000, 0x39de44ea00000000, + 0x984e530200000000, 0x3af91ae100000000, 0x9b690d0900000000, + 0x3f90f8fc00000000, 0x9e00ef1400000000, 0x3cb7a6f700000000, + 0x9d27b11f00000000, 0x35423cc700000000, 0x94d22b2f00000000, + 0x366562cc00000000, 0x97f5752400000000, 0x330c80d100000000, + 0x929c973900000000, 0x302bdeda00000000, 0x91bbc93200000000, + 0x1196570500000000, 0xb00640ed00000000, 0x12b1090e00000000, + 0xb3211ee600000000, 0x17d8eb1300000000, 0xb648fcfb00000000, + 0x14ffb51800000000, 0xb56fa2f000000000, 0x1d0a2f2800000000, + 0xbc9a38c000000000, 0x1e2d712300000000, 0xbfbd66cb00000000, + 0x1b44933e00000000, 0xbad484d600000000, 0x1863cd3500000000, + 0xb9f3dadd00000000, 0x09aea65f00000000, 0xa83eb1b700000000, + 0x0a89f85400000000, 0xab19efbc00000000, 0x0fe01a4900000000, + 0xae700da100000000, 0x0cc7444200000000, 0xad5753aa00000000, + 0x0532de7200000000, 0xa4a2c99a00000000, 0x0615807900000000, + 0xa785979100000000, 0x037c626400000000, 0xa2ec758c00000000, + 0x005b3c6f00000000, 0xa1cb2b8700000000, 0x03ca1aba00000000, + 0xa25a0d5200000000, 0x00ed44b100000000, 0xa17d535900000000, + 0x0584a6ac00000000, 0xa414b14400000000, 0x06a3f8a700000000, + 0xa733ef4f00000000, 0x0f56629700000000, 0xaec6757f00000000, + 0x0c713c9c00000000, 0xade12b7400000000, 0x0918de8100000000, + 0xa888c96900000000, 0x0a3f808a00000000, 0xabaf976200000000, + 0x1bf2ebe000000000, 0xba62fc0800000000, 0x18d5b5eb00000000, + 0xb945a20300000000, 0x1dbc57f600000000, 0xbc2c401e00000000, + 0x1e9b09fd00000000, 0xbf0b1e1500000000, 0x176e93cd00000000, + 0xb6fe842500000000, 0x1449cdc600000000, 0xb5d9da2e00000000, + 0x11202fdb00000000, 0xb0b0383300000000, 0x120771d000000000, + 0xb397663800000000, 0x33baf80f00000000, 0x922aefe700000000, + 0x309da60400000000, 0x910db1ec00000000, 0x35f4441900000000, + 0x946453f100000000, 0x36d31a1200000000, 0x97430dfa00000000, + 0x3f26802200000000, 0x9eb697ca00000000, 0x3c01de2900000000, + 0x9d91c9c100000000, 0x39683c3400000000, 0x98f82bdc00000000, + 0x3a4f623f00000000, 0x9bdf75d700000000, 0x2b82095500000000, + 0x8a121ebd00000000, 0x28a5575e00000000, 0x893540b600000000, + 0x2dccb54300000000, 0x8c5ca2ab00000000, 0x2eebeb4800000000, + 0x8f7bfca000000000, 0x271e717800000000, 0x868e669000000000, + 0x24392f7300000000, 0x85a9389b00000000, 0x2150cd6e00000000, + 0x80c0da8600000000, 0x2277936500000000, 0x83e7848d00000000, + 0x222caf0a00000000, 0x83bcb8e200000000, 0x210bf10100000000, + 0x809be6e900000000, 0x2462131c00000000, 0x85f204f400000000, + 0x27454d1700000000, 0x86d55aff00000000, 0x2eb0d72700000000, + 0x8f20c0cf00000000, 0x2d97892c00000000, 0x8c079ec400000000, + 0x28fe6b3100000000, 0x896e7cd900000000, 0x2bd9353a00000000, + 0x8a4922d200000000, 0x3a145e5000000000, 0x9b8449b800000000, + 0x3933005b00000000, 0x98a317b300000000, 0x3c5ae24600000000, + 0x9dcaf5ae00000000, 0x3f7dbc4d00000000, 0x9eedaba500000000, + 0x3688267d00000000, 0x9718319500000000, 0x35af787600000000, + 0x943f6f9e00000000, 0x30c69a6b00000000, 0x91568d8300000000, + 0x33e1c46000000000, 0x9271d38800000000, 0x125c4dbf00000000, + 0xb3cc5a5700000000, 0x117b13b400000000, 0xb0eb045c00000000, + 0x1412f1a900000000, 0xb582e64100000000, 0x1735afa200000000, + 0xb6a5b84a00000000, 0x1ec0359200000000, 0xbf50227a00000000, + 0x1de76b9900000000, 0xbc777c7100000000, 0x188e898400000000, + 0xb91e9e6c00000000, 0x1ba9d78f00000000, 0xba39c06700000000, + 0x0a64bce500000000, 0xabf4ab0d00000000, 0x0943e2ee00000000, + 0xa8d3f50600000000, 0x0c2a00f300000000, 0xadba171b00000000, + 0x0f0d5ef800000000, 0xae9d491000000000, 0x06f8c4c800000000, + 0xa768d32000000000, 0x05df9ac300000000, 0xa44f8d2b00000000, + 0x00b678de00000000, 0xa1266f3600000000, 0x039126d500000000, + 0xa201313d00000000}, + {0x0000000000000000, 0xee8439a100000000, 0x9d0f029900000000, + 0x738b3b3800000000, 0x7b1975e900000000, 0x959d4c4800000000, + 0xe616777000000000, 0x08924ed100000000, 0xb7349b0900000000, + 0x59b0a2a800000000, 0x2a3b999000000000, 0xc4bfa03100000000, + 0xcc2deee000000000, 0x22a9d74100000000, 0x5122ec7900000000, + 0xbfa6d5d800000000, 0x6e69361300000000, 0x80ed0fb200000000, + 0xf366348a00000000, 0x1de20d2b00000000, 0x157043fa00000000, + 0xfbf47a5b00000000, 0x887f416300000000, 0x66fb78c200000000, + 0xd95dad1a00000000, 0x37d994bb00000000, 0x4452af8300000000, + 0xaad6962200000000, 0xa244d8f300000000, 0x4cc0e15200000000, + 0x3f4bda6a00000000, 0xd1cfe3cb00000000, 0xdcd26c2600000000, + 0x3256558700000000, 0x41dd6ebf00000000, 0xaf59571e00000000, + 0xa7cb19cf00000000, 0x494f206e00000000, 0x3ac41b5600000000, + 0xd44022f700000000, 0x6be6f72f00000000, 0x8562ce8e00000000, + 0xf6e9f5b600000000, 0x186dcc1700000000, 0x10ff82c600000000, + 0xfe7bbb6700000000, 0x8df0805f00000000, 0x6374b9fe00000000, + 0xb2bb5a3500000000, 0x5c3f639400000000, 0x2fb458ac00000000, + 0xc130610d00000000, 0xc9a22fdc00000000, 0x2726167d00000000, + 0x54ad2d4500000000, 0xba2914e400000000, 0x058fc13c00000000, + 0xeb0bf89d00000000, 0x9880c3a500000000, 0x7604fa0400000000, + 0x7e96b4d500000000, 0x90128d7400000000, 0xe399b64c00000000, + 0x0d1d8fed00000000, 0xb8a5d94c00000000, 0x5621e0ed00000000, + 0x25aadbd500000000, 0xcb2ee27400000000, 0xc3bcaca500000000, + 0x2d38950400000000, 0x5eb3ae3c00000000, 0xb037979d00000000, + 0x0f91424500000000, 0xe1157be400000000, 0x929e40dc00000000, + 0x7c1a797d00000000, 0x748837ac00000000, 0x9a0c0e0d00000000, + 0xe987353500000000, 0x07030c9400000000, 0xd6ccef5f00000000, + 0x3848d6fe00000000, 0x4bc3edc600000000, 0xa547d46700000000, + 0xadd59ab600000000, 0x4351a31700000000, 0x30da982f00000000, + 0xde5ea18e00000000, 0x61f8745600000000, 0x8f7c4df700000000, + 0xfcf776cf00000000, 0x12734f6e00000000, 0x1ae101bf00000000, + 0xf465381e00000000, 0x87ee032600000000, 0x696a3a8700000000, + 0x6477b56a00000000, 0x8af38ccb00000000, 0xf978b7f300000000, + 0x17fc8e5200000000, 0x1f6ec08300000000, 0xf1eaf92200000000, + 0x8261c21a00000000, 0x6ce5fbbb00000000, 0xd3432e6300000000, + 0x3dc717c200000000, 0x4e4c2cfa00000000, 0xa0c8155b00000000, + 0xa85a5b8a00000000, 0x46de622b00000000, 0x3555591300000000, + 0xdbd160b200000000, 0x0a1e837900000000, 0xe49abad800000000, + 0x971181e000000000, 0x7995b84100000000, 0x7107f69000000000, + 0x9f83cf3100000000, 0xec08f40900000000, 0x028ccda800000000, + 0xbd2a187000000000, 0x53ae21d100000000, 0x20251ae900000000, + 0xcea1234800000000, 0xc6336d9900000000, 0x28b7543800000000, + 0x5b3c6f0000000000, 0xb5b856a100000000, 0x704bb39900000000, + 0x9ecf8a3800000000, 0xed44b10000000000, 0x03c088a100000000, + 0x0b52c67000000000, 0xe5d6ffd100000000, 0x965dc4e900000000, + 0x78d9fd4800000000, 0xc77f289000000000, 0x29fb113100000000, + 0x5a702a0900000000, 0xb4f413a800000000, 0xbc665d7900000000, + 0x52e264d800000000, 0x21695fe000000000, 0xcfed664100000000, + 0x1e22858a00000000, 0xf0a6bc2b00000000, 0x832d871300000000, + 0x6da9beb200000000, 0x653bf06300000000, 0x8bbfc9c200000000, + 0xf834f2fa00000000, 0x16b0cb5b00000000, 0xa9161e8300000000, + 0x4792272200000000, 0x34191c1a00000000, 0xda9d25bb00000000, + 0xd20f6b6a00000000, 0x3c8b52cb00000000, 0x4f0069f300000000, + 0xa184505200000000, 0xac99dfbf00000000, 0x421de61e00000000, + 0x3196dd2600000000, 0xdf12e48700000000, 0xd780aa5600000000, + 0x390493f700000000, 0x4a8fa8cf00000000, 0xa40b916e00000000, + 0x1bad44b600000000, 0xf5297d1700000000, 0x86a2462f00000000, + 0x68267f8e00000000, 0x60b4315f00000000, 0x8e3008fe00000000, + 0xfdbb33c600000000, 0x133f0a6700000000, 0xc2f0e9ac00000000, + 0x2c74d00d00000000, 0x5fffeb3500000000, 0xb17bd29400000000, + 0xb9e99c4500000000, 0x576da5e400000000, 0x24e69edc00000000, + 0xca62a77d00000000, 0x75c472a500000000, 0x9b404b0400000000, + 0xe8cb703c00000000, 0x064f499d00000000, 0x0edd074c00000000, + 0xe0593eed00000000, 0x93d205d500000000, 0x7d563c7400000000, + 0xc8ee6ad500000000, 0x266a537400000000, 0x55e1684c00000000, + 0xbb6551ed00000000, 0xb3f71f3c00000000, 0x5d73269d00000000, + 0x2ef81da500000000, 0xc07c240400000000, 0x7fdaf1dc00000000, + 0x915ec87d00000000, 0xe2d5f34500000000, 0x0c51cae400000000, + 0x04c3843500000000, 0xea47bd9400000000, 0x99cc86ac00000000, + 0x7748bf0d00000000, 0xa6875cc600000000, 0x4803656700000000, + 0x3b885e5f00000000, 0xd50c67fe00000000, 0xdd9e292f00000000, + 0x331a108e00000000, 0x40912bb600000000, 0xae15121700000000, + 0x11b3c7cf00000000, 0xff37fe6e00000000, 0x8cbcc55600000000, + 0x6238fcf700000000, 0x6aaab22600000000, 0x842e8b8700000000, + 0xf7a5b0bf00000000, 0x1921891e00000000, 0x143c06f300000000, + 0xfab83f5200000000, 0x8933046a00000000, 0x67b73dcb00000000, + 0x6f25731a00000000, 0x81a14abb00000000, 0xf22a718300000000, + 0x1cae482200000000, 0xa3089dfa00000000, 0x4d8ca45b00000000, + 0x3e079f6300000000, 0xd083a6c200000000, 0xd811e81300000000, + 0x3695d1b200000000, 0x451eea8a00000000, 0xab9ad32b00000000, + 0x7a5530e000000000, 0x94d1094100000000, 0xe75a327900000000, + 0x09de0bd800000000, 0x014c450900000000, 0xefc87ca800000000, + 0x9c43479000000000, 0x72c77e3100000000, 0xcd61abe900000000, + 0x23e5924800000000, 0x506ea97000000000, 0xbeea90d100000000, + 0xb678de0000000000, 0x58fce7a100000000, 0x2b77dc9900000000, + 0xc5f3e53800000000}, + {0x0000000000000000, 0xfbf6134700000000, 0xf6ed278e00000000, + 0x0d1b34c900000000, 0xaddd3ec700000000, 0x562b2d8000000000, + 0x5b30194900000000, 0xa0c60a0e00000000, 0x1bbd0c5500000000, + 0xe04b1f1200000000, 0xed502bdb00000000, 0x16a6389c00000000, + 0xb660329200000000, 0x4d9621d500000000, 0x408d151c00000000, + 0xbb7b065b00000000, 0x367a19aa00000000, 0xcd8c0aed00000000, + 0xc0973e2400000000, 0x3b612d6300000000, 0x9ba7276d00000000, + 0x6051342a00000000, 0x6d4a00e300000000, 0x96bc13a400000000, + 0x2dc715ff00000000, 0xd63106b800000000, 0xdb2a327100000000, + 0x20dc213600000000, 0x801a2b3800000000, 0x7bec387f00000000, + 0x76f70cb600000000, 0x8d011ff100000000, 0x2df2438f00000000, + 0xd60450c800000000, 0xdb1f640100000000, 0x20e9774600000000, + 0x802f7d4800000000, 0x7bd96e0f00000000, 0x76c25ac600000000, + 0x8d34498100000000, 0x364f4fda00000000, 0xcdb95c9d00000000, + 0xc0a2685400000000, 0x3b547b1300000000, 0x9b92711d00000000, + 0x6064625a00000000, 0x6d7f569300000000, 0x968945d400000000, + 0x1b885a2500000000, 0xe07e496200000000, 0xed657dab00000000, + 0x16936eec00000000, 0xb65564e200000000, 0x4da377a500000000, + 0x40b8436c00000000, 0xbb4e502b00000000, 0x0035567000000000, + 0xfbc3453700000000, 0xf6d871fe00000000, 0x0d2e62b900000000, + 0xade868b700000000, 0x561e7bf000000000, 0x5b054f3900000000, + 0xa0f35c7e00000000, 0x1be2f6c500000000, 0xe014e58200000000, + 0xed0fd14b00000000, 0x16f9c20c00000000, 0xb63fc80200000000, + 0x4dc9db4500000000, 0x40d2ef8c00000000, 0xbb24fccb00000000, + 0x005ffa9000000000, 0xfba9e9d700000000, 0xf6b2dd1e00000000, + 0x0d44ce5900000000, 0xad82c45700000000, 0x5674d71000000000, + 0x5b6fe3d900000000, 0xa099f09e00000000, 0x2d98ef6f00000000, + 0xd66efc2800000000, 0xdb75c8e100000000, 0x2083dba600000000, + 0x8045d1a800000000, 0x7bb3c2ef00000000, 0x76a8f62600000000, + 0x8d5ee56100000000, 0x3625e33a00000000, 0xcdd3f07d00000000, + 0xc0c8c4b400000000, 0x3b3ed7f300000000, 0x9bf8ddfd00000000, + 0x600eceba00000000, 0x6d15fa7300000000, 0x96e3e93400000000, + 0x3610b54a00000000, 0xcde6a60d00000000, 0xc0fd92c400000000, + 0x3b0b818300000000, 0x9bcd8b8d00000000, 0x603b98ca00000000, + 0x6d20ac0300000000, 0x96d6bf4400000000, 0x2dadb91f00000000, + 0xd65baa5800000000, 0xdb409e9100000000, 0x20b68dd600000000, + 0x807087d800000000, 0x7b86949f00000000, 0x769da05600000000, + 0x8d6bb31100000000, 0x006aace000000000, 0xfb9cbfa700000000, + 0xf6878b6e00000000, 0x0d71982900000000, 0xadb7922700000000, + 0x5641816000000000, 0x5b5ab5a900000000, 0xa0aca6ee00000000, + 0x1bd7a0b500000000, 0xe021b3f200000000, 0xed3a873b00000000, + 0x16cc947c00000000, 0xb60a9e7200000000, 0x4dfc8d3500000000, + 0x40e7b9fc00000000, 0xbb11aabb00000000, 0x77c29c5000000000, + 0x8c348f1700000000, 0x812fbbde00000000, 0x7ad9a89900000000, + 0xda1fa29700000000, 0x21e9b1d000000000, 0x2cf2851900000000, + 0xd704965e00000000, 0x6c7f900500000000, 0x9789834200000000, + 0x9a92b78b00000000, 0x6164a4cc00000000, 0xc1a2aec200000000, + 0x3a54bd8500000000, 0x374f894c00000000, 0xccb99a0b00000000, + 0x41b885fa00000000, 0xba4e96bd00000000, 0xb755a27400000000, + 0x4ca3b13300000000, 0xec65bb3d00000000, 0x1793a87a00000000, + 0x1a889cb300000000, 0xe17e8ff400000000, 0x5a0589af00000000, + 0xa1f39ae800000000, 0xace8ae2100000000, 0x571ebd6600000000, + 0xf7d8b76800000000, 0x0c2ea42f00000000, 0x013590e600000000, + 0xfac383a100000000, 0x5a30dfdf00000000, 0xa1c6cc9800000000, + 0xacddf85100000000, 0x572beb1600000000, 0xf7ede11800000000, + 0x0c1bf25f00000000, 0x0100c69600000000, 0xfaf6d5d100000000, + 0x418dd38a00000000, 0xba7bc0cd00000000, 0xb760f40400000000, + 0x4c96e74300000000, 0xec50ed4d00000000, 0x17a6fe0a00000000, + 0x1abdcac300000000, 0xe14bd98400000000, 0x6c4ac67500000000, + 0x97bcd53200000000, 0x9aa7e1fb00000000, 0x6151f2bc00000000, + 0xc197f8b200000000, 0x3a61ebf500000000, 0x377adf3c00000000, + 0xcc8ccc7b00000000, 0x77f7ca2000000000, 0x8c01d96700000000, + 0x811aedae00000000, 0x7aecfee900000000, 0xda2af4e700000000, + 0x21dce7a000000000, 0x2cc7d36900000000, 0xd731c02e00000000, + 0x6c206a9500000000, 0x97d679d200000000, 0x9acd4d1b00000000, + 0x613b5e5c00000000, 0xc1fd545200000000, 0x3a0b471500000000, + 0x371073dc00000000, 0xcce6609b00000000, 0x779d66c000000000, + 0x8c6b758700000000, 0x8170414e00000000, 0x7a86520900000000, + 0xda40580700000000, 0x21b64b4000000000, 0x2cad7f8900000000, + 0xd75b6cce00000000, 0x5a5a733f00000000, 0xa1ac607800000000, + 0xacb754b100000000, 0x574147f600000000, 0xf7874df800000000, + 0x0c715ebf00000000, 0x016a6a7600000000, 0xfa9c793100000000, + 0x41e77f6a00000000, 0xba116c2d00000000, 0xb70a58e400000000, + 0x4cfc4ba300000000, 0xec3a41ad00000000, 0x17cc52ea00000000, + 0x1ad7662300000000, 0xe121756400000000, 0x41d2291a00000000, + 0xba243a5d00000000, 0xb73f0e9400000000, 0x4cc91dd300000000, + 0xec0f17dd00000000, 0x17f9049a00000000, 0x1ae2305300000000, + 0xe114231400000000, 0x5a6f254f00000000, 0xa199360800000000, + 0xac8202c100000000, 0x5774118600000000, 0xf7b21b8800000000, + 0x0c4408cf00000000, 0x015f3c0600000000, 0xfaa92f4100000000, + 0x77a830b000000000, 0x8c5e23f700000000, 0x8145173e00000000, + 0x7ab3047900000000, 0xda750e7700000000, 0x21831d3000000000, + 0x2c9829f900000000, 0xd76e3abe00000000, 0x6c153ce500000000, + 0x97e32fa200000000, 0x9af81b6b00000000, 0x610e082c00000000, + 0xc1c8022200000000, 0x3a3e116500000000, 0x372525ac00000000, + 0xccd336eb00000000}, + {0x0000000000000000, 0x6238282a00000000, 0xc470505400000000, + 0xa648787e00000000, 0x88e1a0a800000000, 0xead9888200000000, + 0x4c91f0fc00000000, 0x2ea9d8d600000000, 0x51c5308a00000000, + 0x33fd18a000000000, 0x95b560de00000000, 0xf78d48f400000000, + 0xd924902200000000, 0xbb1cb80800000000, 0x1d54c07600000000, + 0x7f6ce85c00000000, 0xe38c10cf00000000, 0x81b438e500000000, + 0x27fc409b00000000, 0x45c468b100000000, 0x6b6db06700000000, + 0x0955984d00000000, 0xaf1de03300000000, 0xcd25c81900000000, + 0xb249204500000000, 0xd071086f00000000, 0x7639701100000000, + 0x1401583b00000000, 0x3aa880ed00000000, 0x5890a8c700000000, + 0xfed8d0b900000000, 0x9ce0f89300000000, 0x871f504500000000, + 0xe527786f00000000, 0x436f001100000000, 0x2157283b00000000, + 0x0ffef0ed00000000, 0x6dc6d8c700000000, 0xcb8ea0b900000000, + 0xa9b6889300000000, 0xd6da60cf00000000, 0xb4e248e500000000, + 0x12aa309b00000000, 0x709218b100000000, 0x5e3bc06700000000, + 0x3c03e84d00000000, 0x9a4b903300000000, 0xf873b81900000000, + 0x6493408a00000000, 0x06ab68a000000000, 0xa0e310de00000000, + 0xc2db38f400000000, 0xec72e02200000000, 0x8e4ac80800000000, + 0x2802b07600000000, 0x4a3a985c00000000, 0x3556700000000000, + 0x576e582a00000000, 0xf126205400000000, 0x931e087e00000000, + 0xbdb7d0a800000000, 0xdf8ff88200000000, 0x79c780fc00000000, + 0x1bffa8d600000000, 0x0e3fa08a00000000, 0x6c0788a000000000, + 0xca4ff0de00000000, 0xa877d8f400000000, 0x86de002200000000, + 0xe4e6280800000000, 0x42ae507600000000, 0x2096785c00000000, + 0x5ffa900000000000, 0x3dc2b82a00000000, 0x9b8ac05400000000, + 0xf9b2e87e00000000, 0xd71b30a800000000, 0xb523188200000000, + 0x136b60fc00000000, 0x715348d600000000, 0xedb3b04500000000, + 0x8f8b986f00000000, 0x29c3e01100000000, 0x4bfbc83b00000000, + 0x655210ed00000000, 0x076a38c700000000, 0xa12240b900000000, + 0xc31a689300000000, 0xbc7680cf00000000, 0xde4ea8e500000000, + 0x7806d09b00000000, 0x1a3ef8b100000000, 0x3497206700000000, + 0x56af084d00000000, 0xf0e7703300000000, 0x92df581900000000, + 0x8920f0cf00000000, 0xeb18d8e500000000, 0x4d50a09b00000000, + 0x2f6888b100000000, 0x01c1506700000000, 0x63f9784d00000000, + 0xc5b1003300000000, 0xa789281900000000, 0xd8e5c04500000000, + 0xbadde86f00000000, 0x1c95901100000000, 0x7eadb83b00000000, + 0x500460ed00000000, 0x323c48c700000000, 0x947430b900000000, + 0xf64c189300000000, 0x6aace00000000000, 0x0894c82a00000000, + 0xaedcb05400000000, 0xcce4987e00000000, 0xe24d40a800000000, + 0x8075688200000000, 0x263d10fc00000000, 0x440538d600000000, + 0x3b69d08a00000000, 0x5951f8a000000000, 0xff1980de00000000, + 0x9d21a8f400000000, 0xb388702200000000, 0xd1b0580800000000, + 0x77f8207600000000, 0x15c0085c00000000, 0x5d7831ce00000000, + 0x3f4019e400000000, 0x9908619a00000000, 0xfb3049b000000000, + 0xd599916600000000, 0xb7a1b94c00000000, 0x11e9c13200000000, + 0x73d1e91800000000, 0x0cbd014400000000, 0x6e85296e00000000, + 0xc8cd511000000000, 0xaaf5793a00000000, 0x845ca1ec00000000, + 0xe66489c600000000, 0x402cf1b800000000, 0x2214d99200000000, + 0xbef4210100000000, 0xdccc092b00000000, 0x7a84715500000000, + 0x18bc597f00000000, 0x361581a900000000, 0x542da98300000000, + 0xf265d1fd00000000, 0x905df9d700000000, 0xef31118b00000000, + 0x8d0939a100000000, 0x2b4141df00000000, 0x497969f500000000, + 0x67d0b12300000000, 0x05e8990900000000, 0xa3a0e17700000000, + 0xc198c95d00000000, 0xda67618b00000000, 0xb85f49a100000000, + 0x1e1731df00000000, 0x7c2f19f500000000, 0x5286c12300000000, + 0x30bee90900000000, 0x96f6917700000000, 0xf4ceb95d00000000, + 0x8ba2510100000000, 0xe99a792b00000000, 0x4fd2015500000000, + 0x2dea297f00000000, 0x0343f1a900000000, 0x617bd98300000000, + 0xc733a1fd00000000, 0xa50b89d700000000, 0x39eb714400000000, + 0x5bd3596e00000000, 0xfd9b211000000000, 0x9fa3093a00000000, + 0xb10ad1ec00000000, 0xd332f9c600000000, 0x757a81b800000000, + 0x1742a99200000000, 0x682e41ce00000000, 0x0a1669e400000000, + 0xac5e119a00000000, 0xce6639b000000000, 0xe0cfe16600000000, + 0x82f7c94c00000000, 0x24bfb13200000000, 0x4687991800000000, + 0x5347914400000000, 0x317fb96e00000000, 0x9737c11000000000, + 0xf50fe93a00000000, 0xdba631ec00000000, 0xb99e19c600000000, + 0x1fd661b800000000, 0x7dee499200000000, 0x0282a1ce00000000, + 0x60ba89e400000000, 0xc6f2f19a00000000, 0xa4cad9b000000000, + 0x8a63016600000000, 0xe85b294c00000000, 0x4e13513200000000, + 0x2c2b791800000000, 0xb0cb818b00000000, 0xd2f3a9a100000000, + 0x74bbd1df00000000, 0x1683f9f500000000, 0x382a212300000000, + 0x5a12090900000000, 0xfc5a717700000000, 0x9e62595d00000000, + 0xe10eb10100000000, 0x8336992b00000000, 0x257ee15500000000, + 0x4746c97f00000000, 0x69ef11a900000000, 0x0bd7398300000000, + 0xad9f41fd00000000, 0xcfa769d700000000, 0xd458c10100000000, + 0xb660e92b00000000, 0x1028915500000000, 0x7210b97f00000000, + 0x5cb961a900000000, 0x3e81498300000000, 0x98c931fd00000000, + 0xfaf119d700000000, 0x859df18b00000000, 0xe7a5d9a100000000, + 0x41eda1df00000000, 0x23d589f500000000, 0x0d7c512300000000, + 0x6f44790900000000, 0xc90c017700000000, 0xab34295d00000000, + 0x37d4d1ce00000000, 0x55ecf9e400000000, 0xf3a4819a00000000, + 0x919ca9b000000000, 0xbf35716600000000, 0xdd0d594c00000000, + 0x7b45213200000000, 0x197d091800000000, 0x6611e14400000000, + 0x0429c96e00000000, 0xa261b11000000000, 0xc059993a00000000, + 0xeef041ec00000000, 0x8cc869c600000000, 0x2a8011b800000000, + 0x48b8399200000000}, + {0x0000000000000000, 0x4c2896a300000000, 0xd9565d9c00000000, + 0x957ecb3f00000000, 0xf3abcbe300000000, 0xbf835d4000000000, + 0x2afd967f00000000, 0x66d500dc00000000, 0xa751e61c00000000, + 0xeb7970bf00000000, 0x7e07bb8000000000, 0x322f2d2300000000, + 0x54fa2dff00000000, 0x18d2bb5c00000000, 0x8dac706300000000, + 0xc184e6c000000000, 0x4ea3cc3900000000, 0x028b5a9a00000000, + 0x97f591a500000000, 0xdbdd070600000000, 0xbd0807da00000000, + 0xf120917900000000, 0x645e5a4600000000, 0x2876cce500000000, + 0xe9f22a2500000000, 0xa5dabc8600000000, 0x30a477b900000000, + 0x7c8ce11a00000000, 0x1a59e1c600000000, 0x5671776500000000, + 0xc30fbc5a00000000, 0x8f272af900000000, 0x9c46997300000000, + 0xd06e0fd000000000, 0x4510c4ef00000000, 0x0938524c00000000, + 0x6fed529000000000, 0x23c5c43300000000, 0xb6bb0f0c00000000, + 0xfa9399af00000000, 0x3b177f6f00000000, 0x773fe9cc00000000, + 0xe24122f300000000, 0xae69b45000000000, 0xc8bcb48c00000000, + 0x8494222f00000000, 0x11eae91000000000, 0x5dc27fb300000000, + 0xd2e5554a00000000, 0x9ecdc3e900000000, 0x0bb308d600000000, + 0x479b9e7500000000, 0x214e9ea900000000, 0x6d66080a00000000, + 0xf818c33500000000, 0xb430559600000000, 0x75b4b35600000000, + 0x399c25f500000000, 0xace2eeca00000000, 0xe0ca786900000000, + 0x861f78b500000000, 0xca37ee1600000000, 0x5f49252900000000, + 0x1361b38a00000000, 0x388d32e700000000, 0x74a5a44400000000, + 0xe1db6f7b00000000, 0xadf3f9d800000000, 0xcb26f90400000000, + 0x870e6fa700000000, 0x1270a49800000000, 0x5e58323b00000000, + 0x9fdcd4fb00000000, 0xd3f4425800000000, 0x468a896700000000, + 0x0aa21fc400000000, 0x6c771f1800000000, 0x205f89bb00000000, + 0xb521428400000000, 0xf909d42700000000, 0x762efede00000000, + 0x3a06687d00000000, 0xaf78a34200000000, 0xe35035e100000000, + 0x8585353d00000000, 0xc9ada39e00000000, 0x5cd368a100000000, + 0x10fbfe0200000000, 0xd17f18c200000000, 0x9d578e6100000000, + 0x0829455e00000000, 0x4401d3fd00000000, 0x22d4d32100000000, + 0x6efc458200000000, 0xfb828ebd00000000, 0xb7aa181e00000000, + 0xa4cbab9400000000, 0xe8e33d3700000000, 0x7d9df60800000000, + 0x31b560ab00000000, 0x5760607700000000, 0x1b48f6d400000000, + 0x8e363deb00000000, 0xc21eab4800000000, 0x039a4d8800000000, + 0x4fb2db2b00000000, 0xdacc101400000000, 0x96e486b700000000, + 0xf031866b00000000, 0xbc1910c800000000, 0x2967dbf700000000, + 0x654f4d5400000000, 0xea6867ad00000000, 0xa640f10e00000000, + 0x333e3a3100000000, 0x7f16ac9200000000, 0x19c3ac4e00000000, + 0x55eb3aed00000000, 0xc095f1d200000000, 0x8cbd677100000000, + 0x4d3981b100000000, 0x0111171200000000, 0x946fdc2d00000000, + 0xd8474a8e00000000, 0xbe924a5200000000, 0xf2badcf100000000, + 0x67c417ce00000000, 0x2bec816d00000000, 0x311c141500000000, + 0x7d3482b600000000, 0xe84a498900000000, 0xa462df2a00000000, + 0xc2b7dff600000000, 0x8e9f495500000000, 0x1be1826a00000000, + 0x57c914c900000000, 0x964df20900000000, 0xda6564aa00000000, + 0x4f1baf9500000000, 0x0333393600000000, 0x65e639ea00000000, + 0x29ceaf4900000000, 0xbcb0647600000000, 0xf098f2d500000000, + 0x7fbfd82c00000000, 0x33974e8f00000000, 0xa6e985b000000000, + 0xeac1131300000000, 0x8c1413cf00000000, 0xc03c856c00000000, + 0x55424e5300000000, 0x196ad8f000000000, 0xd8ee3e3000000000, + 0x94c6a89300000000, 0x01b863ac00000000, 0x4d90f50f00000000, + 0x2b45f5d300000000, 0x676d637000000000, 0xf213a84f00000000, + 0xbe3b3eec00000000, 0xad5a8d6600000000, 0xe1721bc500000000, + 0x740cd0fa00000000, 0x3824465900000000, 0x5ef1468500000000, + 0x12d9d02600000000, 0x87a71b1900000000, 0xcb8f8dba00000000, + 0x0a0b6b7a00000000, 0x4623fdd900000000, 0xd35d36e600000000, + 0x9f75a04500000000, 0xf9a0a09900000000, 0xb588363a00000000, + 0x20f6fd0500000000, 0x6cde6ba600000000, 0xe3f9415f00000000, + 0xafd1d7fc00000000, 0x3aaf1cc300000000, 0x76878a6000000000, + 0x10528abc00000000, 0x5c7a1c1f00000000, 0xc904d72000000000, + 0x852c418300000000, 0x44a8a74300000000, 0x088031e000000000, + 0x9dfefadf00000000, 0xd1d66c7c00000000, 0xb7036ca000000000, + 0xfb2bfa0300000000, 0x6e55313c00000000, 0x227da79f00000000, + 0x099126f200000000, 0x45b9b05100000000, 0xd0c77b6e00000000, + 0x9cefedcd00000000, 0xfa3aed1100000000, 0xb6127bb200000000, + 0x236cb08d00000000, 0x6f44262e00000000, 0xaec0c0ee00000000, + 0xe2e8564d00000000, 0x77969d7200000000, 0x3bbe0bd100000000, + 0x5d6b0b0d00000000, 0x11439dae00000000, 0x843d569100000000, + 0xc815c03200000000, 0x4732eacb00000000, 0x0b1a7c6800000000, + 0x9e64b75700000000, 0xd24c21f400000000, 0xb499212800000000, + 0xf8b1b78b00000000, 0x6dcf7cb400000000, 0x21e7ea1700000000, + 0xe0630cd700000000, 0xac4b9a7400000000, 0x3935514b00000000, + 0x751dc7e800000000, 0x13c8c73400000000, 0x5fe0519700000000, + 0xca9e9aa800000000, 0x86b60c0b00000000, 0x95d7bf8100000000, + 0xd9ff292200000000, 0x4c81e21d00000000, 0x00a974be00000000, + 0x667c746200000000, 0x2a54e2c100000000, 0xbf2a29fe00000000, + 0xf302bf5d00000000, 0x3286599d00000000, 0x7eaecf3e00000000, + 0xebd0040100000000, 0xa7f892a200000000, 0xc12d927e00000000, + 0x8d0504dd00000000, 0x187bcfe200000000, 0x5453594100000000, + 0xdb7473b800000000, 0x975ce51b00000000, 0x02222e2400000000, + 0x4e0ab88700000000, 0x28dfb85b00000000, 0x64f72ef800000000, + 0xf189e5c700000000, 0xbda1736400000000, 0x7c2595a400000000, + 0x300d030700000000, 0xa573c83800000000, 0xe95b5e9b00000000, + 0x8f8e5e4700000000, 0xc3a6c8e400000000, 0x56d803db00000000, + 0x1af0957800000000}, + {0x0000000000000000, 0x939bc97f00000000, 0x263793ff00000000, + 0xb5ac5a8000000000, 0x0d68572400000000, 0x9ef39e5b00000000, + 0x2b5fc4db00000000, 0xb8c40da400000000, 0x1ad0ae4800000000, + 0x894b673700000000, 0x3ce73db700000000, 0xaf7cf4c800000000, + 0x17b8f96c00000000, 0x8423301300000000, 0x318f6a9300000000, + 0xa214a3ec00000000, 0x34a05d9100000000, 0xa73b94ee00000000, + 0x1297ce6e00000000, 0x810c071100000000, 0x39c80ab500000000, + 0xaa53c3ca00000000, 0x1fff994a00000000, 0x8c64503500000000, + 0x2e70f3d900000000, 0xbdeb3aa600000000, 0x0847602600000000, + 0x9bdca95900000000, 0x2318a4fd00000000, 0xb0836d8200000000, + 0x052f370200000000, 0x96b4fe7d00000000, 0x2946caf900000000, + 0xbadd038600000000, 0x0f71590600000000, 0x9cea907900000000, + 0x242e9ddd00000000, 0xb7b554a200000000, 0x02190e2200000000, + 0x9182c75d00000000, 0x339664b100000000, 0xa00dadce00000000, + 0x15a1f74e00000000, 0x863a3e3100000000, 0x3efe339500000000, + 0xad65faea00000000, 0x18c9a06a00000000, 0x8b52691500000000, + 0x1de6976800000000, 0x8e7d5e1700000000, 0x3bd1049700000000, + 0xa84acde800000000, 0x108ec04c00000000, 0x8315093300000000, + 0x36b953b300000000, 0xa5229acc00000000, 0x0736392000000000, + 0x94adf05f00000000, 0x2101aadf00000000, 0xb29a63a000000000, + 0x0a5e6e0400000000, 0x99c5a77b00000000, 0x2c69fdfb00000000, + 0xbff2348400000000, 0x138ae52800000000, 0x80112c5700000000, + 0x35bd76d700000000, 0xa626bfa800000000, 0x1ee2b20c00000000, + 0x8d797b7300000000, 0x38d521f300000000, 0xab4ee88c00000000, + 0x095a4b6000000000, 0x9ac1821f00000000, 0x2f6dd89f00000000, + 0xbcf611e000000000, 0x04321c4400000000, 0x97a9d53b00000000, + 0x22058fbb00000000, 0xb19e46c400000000, 0x272ab8b900000000, + 0xb4b171c600000000, 0x011d2b4600000000, 0x9286e23900000000, + 0x2a42ef9d00000000, 0xb9d926e200000000, 0x0c757c6200000000, + 0x9feeb51d00000000, 0x3dfa16f100000000, 0xae61df8e00000000, + 0x1bcd850e00000000, 0x88564c7100000000, 0x309241d500000000, + 0xa30988aa00000000, 0x16a5d22a00000000, 0x853e1b5500000000, + 0x3acc2fd100000000, 0xa957e6ae00000000, 0x1cfbbc2e00000000, + 0x8f60755100000000, 0x37a478f500000000, 0xa43fb18a00000000, + 0x1193eb0a00000000, 0x8208227500000000, 0x201c819900000000, + 0xb38748e600000000, 0x062b126600000000, 0x95b0db1900000000, + 0x2d74d6bd00000000, 0xbeef1fc200000000, 0x0b43454200000000, + 0x98d88c3d00000000, 0x0e6c724000000000, 0x9df7bb3f00000000, + 0x285be1bf00000000, 0xbbc028c000000000, 0x0304256400000000, + 0x909fec1b00000000, 0x2533b69b00000000, 0xb6a87fe400000000, + 0x14bcdc0800000000, 0x8727157700000000, 0x328b4ff700000000, + 0xa110868800000000, 0x19d48b2c00000000, 0x8a4f425300000000, + 0x3fe318d300000000, 0xac78d1ac00000000, 0x2614cb5100000000, + 0xb58f022e00000000, 0x002358ae00000000, 0x93b891d100000000, + 0x2b7c9c7500000000, 0xb8e7550a00000000, 0x0d4b0f8a00000000, + 0x9ed0c6f500000000, 0x3cc4651900000000, 0xaf5fac6600000000, + 0x1af3f6e600000000, 0x89683f9900000000, 0x31ac323d00000000, + 0xa237fb4200000000, 0x179ba1c200000000, 0x840068bd00000000, + 0x12b496c000000000, 0x812f5fbf00000000, 0x3483053f00000000, + 0xa718cc4000000000, 0x1fdcc1e400000000, 0x8c47089b00000000, + 0x39eb521b00000000, 0xaa709b6400000000, 0x0864388800000000, + 0x9bfff1f700000000, 0x2e53ab7700000000, 0xbdc8620800000000, + 0x050c6fac00000000, 0x9697a6d300000000, 0x233bfc5300000000, + 0xb0a0352c00000000, 0x0f5201a800000000, 0x9cc9c8d700000000, + 0x2965925700000000, 0xbafe5b2800000000, 0x023a568c00000000, + 0x91a19ff300000000, 0x240dc57300000000, 0xb7960c0c00000000, + 0x1582afe000000000, 0x8619669f00000000, 0x33b53c1f00000000, + 0xa02ef56000000000, 0x18eaf8c400000000, 0x8b7131bb00000000, + 0x3edd6b3b00000000, 0xad46a24400000000, 0x3bf25c3900000000, + 0xa869954600000000, 0x1dc5cfc600000000, 0x8e5e06b900000000, + 0x369a0b1d00000000, 0xa501c26200000000, 0x10ad98e200000000, + 0x8336519d00000000, 0x2122f27100000000, 0xb2b93b0e00000000, + 0x0715618e00000000, 0x948ea8f100000000, 0x2c4aa55500000000, + 0xbfd16c2a00000000, 0x0a7d36aa00000000, 0x99e6ffd500000000, + 0x359e2e7900000000, 0xa605e70600000000, 0x13a9bd8600000000, + 0x803274f900000000, 0x38f6795d00000000, 0xab6db02200000000, + 0x1ec1eaa200000000, 0x8d5a23dd00000000, 0x2f4e803100000000, + 0xbcd5494e00000000, 0x097913ce00000000, 0x9ae2dab100000000, + 0x2226d71500000000, 0xb1bd1e6a00000000, 0x041144ea00000000, + 0x978a8d9500000000, 0x013e73e800000000, 0x92a5ba9700000000, + 0x2709e01700000000, 0xb492296800000000, 0x0c5624cc00000000, + 0x9fcdedb300000000, 0x2a61b73300000000, 0xb9fa7e4c00000000, + 0x1beedda000000000, 0x887514df00000000, 0x3dd94e5f00000000, + 0xae42872000000000, 0x16868a8400000000, 0x851d43fb00000000, + 0x30b1197b00000000, 0xa32ad00400000000, 0x1cd8e48000000000, + 0x8f432dff00000000, 0x3aef777f00000000, 0xa974be0000000000, + 0x11b0b3a400000000, 0x822b7adb00000000, 0x3787205b00000000, + 0xa41ce92400000000, 0x06084ac800000000, 0x959383b700000000, + 0x203fd93700000000, 0xb3a4104800000000, 0x0b601dec00000000, + 0x98fbd49300000000, 0x2d578e1300000000, 0xbecc476c00000000, + 0x2878b91100000000, 0xbbe3706e00000000, 0x0e4f2aee00000000, + 0x9dd4e39100000000, 0x2510ee3500000000, 0xb68b274a00000000, + 0x03277dca00000000, 0x90bcb4b500000000, 0x32a8175900000000, + 0xa133de2600000000, 0x149f84a600000000, 0x87044dd900000000, + 0x3fc0407d00000000, 0xac5b890200000000, 0x19f7d38200000000, + 0x8a6c1afd00000000}, + {0x0000000000000000, 0x650b796900000000, 0xca16f2d200000000, + 0xaf1d8bbb00000000, 0xd52b957e00000000, 0xb020ec1700000000, + 0x1f3d67ac00000000, 0x7a361ec500000000, 0xaa572afd00000000, + 0xcf5c539400000000, 0x6041d82f00000000, 0x054aa14600000000, + 0x7f7cbf8300000000, 0x1a77c6ea00000000, 0xb56a4d5100000000, + 0xd061343800000000, 0x15a9252100000000, 0x70a25c4800000000, + 0xdfbfd7f300000000, 0xbab4ae9a00000000, 0xc082b05f00000000, + 0xa589c93600000000, 0x0a94428d00000000, 0x6f9f3be400000000, + 0xbffe0fdc00000000, 0xdaf576b500000000, 0x75e8fd0e00000000, + 0x10e3846700000000, 0x6ad59aa200000000, 0x0fdee3cb00000000, + 0xa0c3687000000000, 0xc5c8111900000000, 0x2a524b4200000000, + 0x4f59322b00000000, 0xe044b99000000000, 0x854fc0f900000000, + 0xff79de3c00000000, 0x9a72a75500000000, 0x356f2cee00000000, + 0x5064558700000000, 0x800561bf00000000, 0xe50e18d600000000, + 0x4a13936d00000000, 0x2f18ea0400000000, 0x552ef4c100000000, + 0x30258da800000000, 0x9f38061300000000, 0xfa337f7a00000000, + 0x3ffb6e6300000000, 0x5af0170a00000000, 0xf5ed9cb100000000, + 0x90e6e5d800000000, 0xead0fb1d00000000, 0x8fdb827400000000, + 0x20c609cf00000000, 0x45cd70a600000000, 0x95ac449e00000000, + 0xf0a73df700000000, 0x5fbab64c00000000, 0x3ab1cf2500000000, + 0x4087d1e000000000, 0x258ca88900000000, 0x8a91233200000000, + 0xef9a5a5b00000000, 0x54a4968400000000, 0x31afefed00000000, + 0x9eb2645600000000, 0xfbb91d3f00000000, 0x818f03fa00000000, + 0xe4847a9300000000, 0x4b99f12800000000, 0x2e92884100000000, + 0xfef3bc7900000000, 0x9bf8c51000000000, 0x34e54eab00000000, + 0x51ee37c200000000, 0x2bd8290700000000, 0x4ed3506e00000000, + 0xe1cedbd500000000, 0x84c5a2bc00000000, 0x410db3a500000000, + 0x2406cacc00000000, 0x8b1b417700000000, 0xee10381e00000000, + 0x942626db00000000, 0xf12d5fb200000000, 0x5e30d40900000000, + 0x3b3bad6000000000, 0xeb5a995800000000, 0x8e51e03100000000, + 0x214c6b8a00000000, 0x444712e300000000, 0x3e710c2600000000, + 0x5b7a754f00000000, 0xf467fef400000000, 0x916c879d00000000, + 0x7ef6ddc600000000, 0x1bfda4af00000000, 0xb4e02f1400000000, + 0xd1eb567d00000000, 0xabdd48b800000000, 0xced631d100000000, + 0x61cbba6a00000000, 0x04c0c30300000000, 0xd4a1f73b00000000, + 0xb1aa8e5200000000, 0x1eb705e900000000, 0x7bbc7c8000000000, + 0x018a624500000000, 0x64811b2c00000000, 0xcb9c909700000000, + 0xae97e9fe00000000, 0x6b5ff8e700000000, 0x0e54818e00000000, + 0xa1490a3500000000, 0xc442735c00000000, 0xbe746d9900000000, + 0xdb7f14f000000000, 0x74629f4b00000000, 0x1169e62200000000, + 0xc108d21a00000000, 0xa403ab7300000000, 0x0b1e20c800000000, + 0x6e1559a100000000, 0x1423476400000000, 0x71283e0d00000000, + 0xde35b5b600000000, 0xbb3eccdf00000000, 0xe94e5cd200000000, + 0x8c4525bb00000000, 0x2358ae0000000000, 0x4653d76900000000, + 0x3c65c9ac00000000, 0x596eb0c500000000, 0xf6733b7e00000000, + 0x9378421700000000, 0x4319762f00000000, 0x26120f4600000000, + 0x890f84fd00000000, 0xec04fd9400000000, 0x9632e35100000000, + 0xf3399a3800000000, 0x5c24118300000000, 0x392f68ea00000000, + 0xfce779f300000000, 0x99ec009a00000000, 0x36f18b2100000000, + 0x53faf24800000000, 0x29ccec8d00000000, 0x4cc795e400000000, + 0xe3da1e5f00000000, 0x86d1673600000000, 0x56b0530e00000000, + 0x33bb2a6700000000, 0x9ca6a1dc00000000, 0xf9add8b500000000, + 0x839bc67000000000, 0xe690bf1900000000, 0x498d34a200000000, + 0x2c864dcb00000000, 0xc31c179000000000, 0xa6176ef900000000, + 0x090ae54200000000, 0x6c019c2b00000000, 0x163782ee00000000, + 0x733cfb8700000000, 0xdc21703c00000000, 0xb92a095500000000, + 0x694b3d6d00000000, 0x0c40440400000000, 0xa35dcfbf00000000, + 0xc656b6d600000000, 0xbc60a81300000000, 0xd96bd17a00000000, + 0x76765ac100000000, 0x137d23a800000000, 0xd6b532b100000000, + 0xb3be4bd800000000, 0x1ca3c06300000000, 0x79a8b90a00000000, + 0x039ea7cf00000000, 0x6695dea600000000, 0xc988551d00000000, + 0xac832c7400000000, 0x7ce2184c00000000, 0x19e9612500000000, + 0xb6f4ea9e00000000, 0xd3ff93f700000000, 0xa9c98d3200000000, + 0xccc2f45b00000000, 0x63df7fe000000000, 0x06d4068900000000, + 0xbdeaca5600000000, 0xd8e1b33f00000000, 0x77fc388400000000, + 0x12f741ed00000000, 0x68c15f2800000000, 0x0dca264100000000, + 0xa2d7adfa00000000, 0xc7dcd49300000000, 0x17bde0ab00000000, + 0x72b699c200000000, 0xddab127900000000, 0xb8a06b1000000000, + 0xc29675d500000000, 0xa79d0cbc00000000, 0x0880870700000000, + 0x6d8bfe6e00000000, 0xa843ef7700000000, 0xcd48961e00000000, + 0x62551da500000000, 0x075e64cc00000000, 0x7d687a0900000000, + 0x1863036000000000, 0xb77e88db00000000, 0xd275f1b200000000, + 0x0214c58a00000000, 0x671fbce300000000, 0xc802375800000000, + 0xad094e3100000000, 0xd73f50f400000000, 0xb234299d00000000, + 0x1d29a22600000000, 0x7822db4f00000000, 0x97b8811400000000, + 0xf2b3f87d00000000, 0x5dae73c600000000, 0x38a50aaf00000000, + 0x4293146a00000000, 0x27986d0300000000, 0x8885e6b800000000, + 0xed8e9fd100000000, 0x3defabe900000000, 0x58e4d28000000000, + 0xf7f9593b00000000, 0x92f2205200000000, 0xe8c43e9700000000, + 0x8dcf47fe00000000, 0x22d2cc4500000000, 0x47d9b52c00000000, + 0x8211a43500000000, 0xe71add5c00000000, 0x480756e700000000, + 0x2d0c2f8e00000000, 0x573a314b00000000, 0x3231482200000000, + 0x9d2cc39900000000, 0xf827baf000000000, 0x28468ec800000000, + 0x4d4df7a100000000, 0xe2507c1a00000000, 0x875b057300000000, + 0xfd6d1bb600000000, 0x986662df00000000, 0x377be96400000000, + 0x5270900d00000000}, + {0x0000000000000000, 0xdcecb13d00000000, 0xb8d9637b00000000, + 0x6435d24600000000, 0x70b3c7f600000000, 0xac5f76cb00000000, + 0xc86aa48d00000000, 0x148615b000000000, 0xa160fe3600000000, + 0x7d8c4f0b00000000, 0x19b99d4d00000000, 0xc5552c7000000000, + 0xd1d339c000000000, 0x0d3f88fd00000000, 0x690a5abb00000000, + 0xb5e6eb8600000000, 0x42c1fc6d00000000, 0x9e2d4d5000000000, + 0xfa189f1600000000, 0x26f42e2b00000000, 0x32723b9b00000000, + 0xee9e8aa600000000, 0x8aab58e000000000, 0x5647e9dd00000000, + 0xe3a1025b00000000, 0x3f4db36600000000, 0x5b78612000000000, + 0x8794d01d00000000, 0x9312c5ad00000000, 0x4ffe749000000000, + 0x2bcba6d600000000, 0xf72717eb00000000, 0x8482f9db00000000, + 0x586e48e600000000, 0x3c5b9aa000000000, 0xe0b72b9d00000000, + 0xf4313e2d00000000, 0x28dd8f1000000000, 0x4ce85d5600000000, + 0x9004ec6b00000000, 0x25e207ed00000000, 0xf90eb6d000000000, + 0x9d3b649600000000, 0x41d7d5ab00000000, 0x5551c01b00000000, + 0x89bd712600000000, 0xed88a36000000000, 0x3164125d00000000, + 0xc64305b600000000, 0x1aafb48b00000000, 0x7e9a66cd00000000, + 0xa276d7f000000000, 0xb6f0c24000000000, 0x6a1c737d00000000, + 0x0e29a13b00000000, 0xd2c5100600000000, 0x6723fb8000000000, + 0xbbcf4abd00000000, 0xdffa98fb00000000, 0x031629c600000000, + 0x17903c7600000000, 0xcb7c8d4b00000000, 0xaf495f0d00000000, + 0x73a5ee3000000000, 0x4903826c00000000, 0x95ef335100000000, + 0xf1dae11700000000, 0x2d36502a00000000, 0x39b0459a00000000, + 0xe55cf4a700000000, 0x816926e100000000, 0x5d8597dc00000000, + 0xe8637c5a00000000, 0x348fcd6700000000, 0x50ba1f2100000000, + 0x8c56ae1c00000000, 0x98d0bbac00000000, 0x443c0a9100000000, + 0x2009d8d700000000, 0xfce569ea00000000, 0x0bc27e0100000000, + 0xd72ecf3c00000000, 0xb31b1d7a00000000, 0x6ff7ac4700000000, + 0x7b71b9f700000000, 0xa79d08ca00000000, 0xc3a8da8c00000000, + 0x1f446bb100000000, 0xaaa2803700000000, 0x764e310a00000000, + 0x127be34c00000000, 0xce97527100000000, 0xda1147c100000000, + 0x06fdf6fc00000000, 0x62c824ba00000000, 0xbe24958700000000, + 0xcd817bb700000000, 0x116dca8a00000000, 0x755818cc00000000, + 0xa9b4a9f100000000, 0xbd32bc4100000000, 0x61de0d7c00000000, + 0x05ebdf3a00000000, 0xd9076e0700000000, 0x6ce1858100000000, + 0xb00d34bc00000000, 0xd438e6fa00000000, 0x08d457c700000000, + 0x1c52427700000000, 0xc0bef34a00000000, 0xa48b210c00000000, + 0x7867903100000000, 0x8f4087da00000000, 0x53ac36e700000000, + 0x3799e4a100000000, 0xeb75559c00000000, 0xfff3402c00000000, + 0x231ff11100000000, 0x472a235700000000, 0x9bc6926a00000000, + 0x2e2079ec00000000, 0xf2ccc8d100000000, 0x96f91a9700000000, + 0x4a15abaa00000000, 0x5e93be1a00000000, 0x827f0f2700000000, + 0xe64add6100000000, 0x3aa66c5c00000000, 0x920604d900000000, + 0x4eeab5e400000000, 0x2adf67a200000000, 0xf633d69f00000000, + 0xe2b5c32f00000000, 0x3e59721200000000, 0x5a6ca05400000000, + 0x8680116900000000, 0x3366faef00000000, 0xef8a4bd200000000, + 0x8bbf999400000000, 0x575328a900000000, 0x43d53d1900000000, + 0x9f398c2400000000, 0xfb0c5e6200000000, 0x27e0ef5f00000000, + 0xd0c7f8b400000000, 0x0c2b498900000000, 0x681e9bcf00000000, + 0xb4f22af200000000, 0xa0743f4200000000, 0x7c988e7f00000000, + 0x18ad5c3900000000, 0xc441ed0400000000, 0x71a7068200000000, + 0xad4bb7bf00000000, 0xc97e65f900000000, 0x1592d4c400000000, + 0x0114c17400000000, 0xddf8704900000000, 0xb9cda20f00000000, + 0x6521133200000000, 0x1684fd0200000000, 0xca684c3f00000000, + 0xae5d9e7900000000, 0x72b12f4400000000, 0x66373af400000000, + 0xbadb8bc900000000, 0xdeee598f00000000, 0x0202e8b200000000, + 0xb7e4033400000000, 0x6b08b20900000000, 0x0f3d604f00000000, + 0xd3d1d17200000000, 0xc757c4c200000000, 0x1bbb75ff00000000, + 0x7f8ea7b900000000, 0xa362168400000000, 0x5445016f00000000, + 0x88a9b05200000000, 0xec9c621400000000, 0x3070d32900000000, + 0x24f6c69900000000, 0xf81a77a400000000, 0x9c2fa5e200000000, + 0x40c314df00000000, 0xf525ff5900000000, 0x29c94e6400000000, + 0x4dfc9c2200000000, 0x91102d1f00000000, 0x859638af00000000, + 0x597a899200000000, 0x3d4f5bd400000000, 0xe1a3eae900000000, + 0xdb0586b500000000, 0x07e9378800000000, 0x63dce5ce00000000, + 0xbf3054f300000000, 0xabb6414300000000, 0x775af07e00000000, + 0x136f223800000000, 0xcf83930500000000, 0x7a65788300000000, + 0xa689c9be00000000, 0xc2bc1bf800000000, 0x1e50aac500000000, + 0x0ad6bf7500000000, 0xd63a0e4800000000, 0xb20fdc0e00000000, + 0x6ee36d3300000000, 0x99c47ad800000000, 0x4528cbe500000000, + 0x211d19a300000000, 0xfdf1a89e00000000, 0xe977bd2e00000000, + 0x359b0c1300000000, 0x51aede5500000000, 0x8d426f6800000000, + 0x38a484ee00000000, 0xe44835d300000000, 0x807de79500000000, + 0x5c9156a800000000, 0x4817431800000000, 0x94fbf22500000000, + 0xf0ce206300000000, 0x2c22915e00000000, 0x5f877f6e00000000, + 0x836bce5300000000, 0xe75e1c1500000000, 0x3bb2ad2800000000, + 0x2f34b89800000000, 0xf3d809a500000000, 0x97eddbe300000000, + 0x4b016ade00000000, 0xfee7815800000000, 0x220b306500000000, + 0x463ee22300000000, 0x9ad2531e00000000, 0x8e5446ae00000000, + 0x52b8f79300000000, 0x368d25d500000000, 0xea6194e800000000, + 0x1d46830300000000, 0xc1aa323e00000000, 0xa59fe07800000000, + 0x7973514500000000, 0x6df544f500000000, 0xb119f5c800000000, + 0xd52c278e00000000, 0x09c096b300000000, 0xbc267d3500000000, + 0x60cacc0800000000, 0x04ff1e4e00000000, 0xd813af7300000000, + 0xcc95bac300000000, 0x10790bfe00000000, 0x744cd9b800000000, + 0xa8a0688500000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f, + 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999, + 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee, + 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615, + 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383, + 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb, + 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275, + 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d, + 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b, + 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460, + 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317, + 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1, + 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5, + 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd, + 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04, + 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c, + 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7, + 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11, + 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66, + 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7, + 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871, + 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309, + 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd, + 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85, + 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913, + 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d, + 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a, + 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc, + 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57, + 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f, + 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6, + 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e, + 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f, + 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289, + 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe, + 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05, + 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893, + 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb, + 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0, + 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8, + 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e, + 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5, + 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2, + 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574, + 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5, + 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add, + 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114, + 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c, + 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7, + 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701, + 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076, + 0x09cd8551}, + {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193, + 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2, + 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c, + 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71, + 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a, + 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d, + 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71, + 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436, + 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d, + 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000, + 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae, + 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf, + 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930, + 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277, + 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff, + 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8, + 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef, + 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e, + 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20, + 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95, + 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e, + 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9, + 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d, + 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a, + 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151, + 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4, + 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a, + 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b, + 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c, + 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b, + 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3, + 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4, + 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b, + 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a, + 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4, + 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189, + 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92, + 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5, + 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9, + 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe, + 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5, + 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8, + 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66, + 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707, + 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8, + 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f, + 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707, + 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40, + 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017, + 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876, + 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8, + 0x7bc97a0c}, + {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300, + 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0, + 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80, + 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701, + 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41, + 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81, + 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43, + 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83, + 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3, + 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42, + 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202, + 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2, + 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7, + 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407, + 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47, + 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87, + 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86, + 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46, + 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506, + 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44, + 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704, + 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4, + 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5, + 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505, + 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45, + 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f, + 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f, + 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f, + 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e, + 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e, + 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e, + 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce, + 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c, + 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc, + 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c, + 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d, + 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d, + 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d, + 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88, + 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48, + 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708, + 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89, + 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9, + 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309, + 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb, + 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b, + 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b, + 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b, + 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a, + 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a, + 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a, + 0x7851a2ca}, + {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb, + 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8, + 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0, + 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f, + 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a, + 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf, + 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5, + 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380, + 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815, + 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa, + 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2, + 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1, + 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1, + 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4, + 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa, + 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df, + 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6, + 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5, + 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad, + 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca, + 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f, + 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a, + 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8, + 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d, + 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708, + 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d, + 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865, + 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636, + 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f, + 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a, + 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744, + 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061, + 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0, + 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293, + 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb, + 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874, + 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1, + 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4, + 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f, + 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a, + 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f, + 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120, + 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778, + 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b, + 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a, + 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af, + 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81, + 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4, + 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd, + 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e, + 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6, + 0x566b6848}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0x9e83da9f, 0x7d01c4e4, 0xe3821e7b, 0xbb04f912, + 0x2587238d, 0xc6053df6, 0x5886e769, 0x7609f225, 0xe88a28ba, + 0x0b0836c1, 0x958bec5e, 0xcd0d0b37, 0x538ed1a8, 0xb00ccfd3, + 0x2e8f154c, 0xec12e44b, 0x72913ed4, 0x911320af, 0x0f90fa30, + 0x57161d59, 0xc995c7c6, 0x2a17d9bd, 0xb4940322, 0x9a1b166e, + 0x0498ccf1, 0xe71ad28a, 0x79990815, 0x211fef7c, 0xbf9c35e3, + 0x5c1e2b98, 0xc29df107, 0xd825c897, 0x46a61208, 0xa5240c73, + 0x3ba7d6ec, 0x63213185, 0xfda2eb1a, 0x1e20f561, 0x80a32ffe, + 0xae2c3ab2, 0x30afe02d, 0xd32dfe56, 0x4dae24c9, 0x1528c3a0, + 0x8bab193f, 0x68290744, 0xf6aadddb, 0x34372cdc, 0xaab4f643, + 0x4936e838, 0xd7b532a7, 0x8f33d5ce, 0x11b00f51, 0xf232112a, + 0x6cb1cbb5, 0x423edef9, 0xdcbd0466, 0x3f3f1a1d, 0xa1bcc082, + 0xf93a27eb, 0x67b9fd74, 0x843be30f, 0x1ab83990, 0xf14de1f4, + 0x6fce3b6b, 0x8c4c2510, 0x12cfff8f, 0x4a4918e6, 0xd4cac279, + 0x3748dc02, 0xa9cb069d, 0x874413d1, 0x19c7c94e, 0xfa45d735, + 0x64c60daa, 0x3c40eac3, 0xa2c3305c, 0x41412e27, 0xdfc2f4b8, + 0x1d5f05bf, 0x83dcdf20, 0x605ec15b, 0xfedd1bc4, 0xa65bfcad, + 0x38d82632, 0xdb5a3849, 0x45d9e2d6, 0x6b56f79a, 0xf5d52d05, + 0x1657337e, 0x88d4e9e1, 0xd0520e88, 0x4ed1d417, 0xad53ca6c, + 0x33d010f3, 0x29682963, 0xb7ebf3fc, 0x5469ed87, 0xcaea3718, + 0x926cd071, 0x0cef0aee, 0xef6d1495, 0x71eece0a, 0x5f61db46, + 0xc1e201d9, 0x22601fa2, 0xbce3c53d, 0xe4652254, 0x7ae6f8cb, + 0x9964e6b0, 0x07e73c2f, 0xc57acd28, 0x5bf917b7, 0xb87b09cc, + 0x26f8d353, 0x7e7e343a, 0xe0fdeea5, 0x037ff0de, 0x9dfc2a41, + 0xb3733f0d, 0x2df0e592, 0xce72fbe9, 0x50f12176, 0x0877c61f, + 0x96f41c80, 0x757602fb, 0xebf5d864, 0xa39db332, 0x3d1e69ad, + 0xde9c77d6, 0x401fad49, 0x18994a20, 0x861a90bf, 0x65988ec4, + 0xfb1b545b, 0xd5944117, 0x4b179b88, 0xa89585f3, 0x36165f6c, + 0x6e90b805, 0xf013629a, 0x13917ce1, 0x8d12a67e, 0x4f8f5779, + 0xd10c8de6, 0x328e939d, 0xac0d4902, 0xf48bae6b, 0x6a0874f4, + 0x898a6a8f, 0x1709b010, 0x3986a55c, 0xa7057fc3, 0x448761b8, + 0xda04bb27, 0x82825c4e, 0x1c0186d1, 0xff8398aa, 0x61004235, + 0x7bb87ba5, 0xe53ba13a, 0x06b9bf41, 0x983a65de, 0xc0bc82b7, + 0x5e3f5828, 0xbdbd4653, 0x233e9ccc, 0x0db18980, 0x9332531f, + 0x70b04d64, 0xee3397fb, 0xb6b57092, 0x2836aa0d, 0xcbb4b476, + 0x55376ee9, 0x97aa9fee, 0x09294571, 0xeaab5b0a, 0x74288195, + 0x2cae66fc, 0xb22dbc63, 0x51afa218, 0xcf2c7887, 0xe1a36dcb, + 0x7f20b754, 0x9ca2a92f, 0x022173b0, 0x5aa794d9, 0xc4244e46, + 0x27a6503d, 0xb9258aa2, 0x52d052c6, 0xcc538859, 0x2fd19622, + 0xb1524cbd, 0xe9d4abd4, 0x7757714b, 0x94d56f30, 0x0a56b5af, + 0x24d9a0e3, 0xba5a7a7c, 0x59d86407, 0xc75bbe98, 0x9fdd59f1, + 0x015e836e, 0xe2dc9d15, 0x7c5f478a, 0xbec2b68d, 0x20416c12, + 0xc3c37269, 0x5d40a8f6, 0x05c64f9f, 0x9b459500, 0x78c78b7b, + 0xe64451e4, 0xc8cb44a8, 0x56489e37, 0xb5ca804c, 0x2b495ad3, + 0x73cfbdba, 0xed4c6725, 0x0ece795e, 0x904da3c1, 0x8af59a51, + 0x147640ce, 0xf7f45eb5, 0x6977842a, 0x31f16343, 0xaf72b9dc, + 0x4cf0a7a7, 0xd2737d38, 0xfcfc6874, 0x627fb2eb, 0x81fdac90, + 0x1f7e760f, 0x47f89166, 0xd97b4bf9, 0x3af95582, 0xa47a8f1d, + 0x66e77e1a, 0xf864a485, 0x1be6bafe, 0x85656061, 0xdde38708, + 0x43605d97, 0xa0e243ec, 0x3e619973, 0x10ee8c3f, 0x8e6d56a0, + 0x6def48db, 0xf36c9244, 0xabea752d, 0x3569afb2, 0xd6ebb1c9, + 0x48686b56}, + {0x00000000, 0xc0642817, 0x80c9502e, 0x40ad7839, 0x0093a15c, + 0xc0f7894b, 0x805af172, 0x403ed965, 0x002643b9, 0xc0426bae, + 0x80ef1397, 0x408b3b80, 0x00b5e2e5, 0xc0d1caf2, 0x807cb2cb, + 0x40189adc, 0x414af7a9, 0x812edfbe, 0xc183a787, 0x01e78f90, + 0x41d956f5, 0x81bd7ee2, 0xc11006db, 0x01742ecc, 0x416cb410, + 0x81089c07, 0xc1a5e43e, 0x01c1cc29, 0x41ff154c, 0x819b3d5b, + 0xc1364562, 0x01526d75, 0xc3929f88, 0x03f6b79f, 0x435bcfa6, + 0x833fe7b1, 0xc3013ed4, 0x036516c3, 0x43c86efa, 0x83ac46ed, + 0xc3b4dc31, 0x03d0f426, 0x437d8c1f, 0x8319a408, 0xc3277d6d, + 0x0343557a, 0x43ee2d43, 0x838a0554, 0x82d86821, 0x42bc4036, + 0x0211380f, 0xc2751018, 0x824bc97d, 0x422fe16a, 0x02829953, + 0xc2e6b144, 0x82fe2b98, 0x429a038f, 0x02377bb6, 0xc25353a1, + 0x826d8ac4, 0x4209a2d3, 0x02a4daea, 0xc2c0f2fd, 0xc7234eca, + 0x074766dd, 0x47ea1ee4, 0x878e36f3, 0xc7b0ef96, 0x07d4c781, + 0x4779bfb8, 0x871d97af, 0xc7050d73, 0x07612564, 0x47cc5d5d, + 0x87a8754a, 0xc796ac2f, 0x07f28438, 0x475ffc01, 0x873bd416, + 0x8669b963, 0x460d9174, 0x06a0e94d, 0xc6c4c15a, 0x86fa183f, + 0x469e3028, 0x06334811, 0xc6576006, 0x864ffada, 0x462bd2cd, + 0x0686aaf4, 0xc6e282e3, 0x86dc5b86, 0x46b87391, 0x06150ba8, + 0xc67123bf, 0x04b1d142, 0xc4d5f955, 0x8478816c, 0x441ca97b, + 0x0422701e, 0xc4465809, 0x84eb2030, 0x448f0827, 0x049792fb, + 0xc4f3baec, 0x845ec2d5, 0x443aeac2, 0x040433a7, 0xc4601bb0, + 0x84cd6389, 0x44a94b9e, 0x45fb26eb, 0x859f0efc, 0xc53276c5, + 0x05565ed2, 0x456887b7, 0x850cafa0, 0xc5a1d799, 0x05c5ff8e, + 0x45dd6552, 0x85b94d45, 0xc514357c, 0x05701d6b, 0x454ec40e, + 0x852aec19, 0xc5879420, 0x05e3bc37, 0xcf41ed4f, 0x0f25c558, + 0x4f88bd61, 0x8fec9576, 0xcfd24c13, 0x0fb66404, 0x4f1b1c3d, + 0x8f7f342a, 0xcf67aef6, 0x0f0386e1, 0x4faefed8, 0x8fcad6cf, + 0xcff40faa, 0x0f9027bd, 0x4f3d5f84, 0x8f597793, 0x8e0b1ae6, + 0x4e6f32f1, 0x0ec24ac8, 0xcea662df, 0x8e98bbba, 0x4efc93ad, + 0x0e51eb94, 0xce35c383, 0x8e2d595f, 0x4e497148, 0x0ee40971, + 0xce802166, 0x8ebef803, 0x4edad014, 0x0e77a82d, 0xce13803a, + 0x0cd372c7, 0xccb75ad0, 0x8c1a22e9, 0x4c7e0afe, 0x0c40d39b, + 0xcc24fb8c, 0x8c8983b5, 0x4cedaba2, 0x0cf5317e, 0xcc911969, + 0x8c3c6150, 0x4c584947, 0x0c669022, 0xcc02b835, 0x8cafc00c, + 0x4ccbe81b, 0x4d99856e, 0x8dfdad79, 0xcd50d540, 0x0d34fd57, + 0x4d0a2432, 0x8d6e0c25, 0xcdc3741c, 0x0da75c0b, 0x4dbfc6d7, + 0x8ddbeec0, 0xcd7696f9, 0x0d12beee, 0x4d2c678b, 0x8d484f9c, + 0xcde537a5, 0x0d811fb2, 0x0862a385, 0xc8068b92, 0x88abf3ab, + 0x48cfdbbc, 0x08f102d9, 0xc8952ace, 0x883852f7, 0x485c7ae0, + 0x0844e03c, 0xc820c82b, 0x888db012, 0x48e99805, 0x08d74160, + 0xc8b36977, 0x881e114e, 0x487a3959, 0x4928542c, 0x894c7c3b, + 0xc9e10402, 0x09852c15, 0x49bbf570, 0x89dfdd67, 0xc972a55e, + 0x09168d49, 0x490e1795, 0x896a3f82, 0xc9c747bb, 0x09a36fac, + 0x499db6c9, 0x89f99ede, 0xc954e6e7, 0x0930cef0, 0xcbf03c0d, + 0x0b94141a, 0x4b396c23, 0x8b5d4434, 0xcb639d51, 0x0b07b546, + 0x4baacd7f, 0x8bcee568, 0xcbd67fb4, 0x0bb257a3, 0x4b1f2f9a, + 0x8b7b078d, 0xcb45dee8, 0x0b21f6ff, 0x4b8c8ec6, 0x8be8a6d1, + 0x8abacba4, 0x4adee3b3, 0x0a739b8a, 0xca17b39d, 0x8a296af8, + 0x4a4d42ef, 0x0ae03ad6, 0xca8412c1, 0x8a9c881d, 0x4af8a00a, + 0x0a55d833, 0xca31f024, 0x8a0f2941, 0x4a6b0156, 0x0ac6796f, + 0xcaa25178}, + {0x00000000, 0xd4ea739b, 0xe9d396ed, 0x3d39e576, 0x93a15c00, + 0x474b2f9b, 0x7a72caed, 0xae98b976, 0x2643b900, 0xf2a9ca9b, + 0xcf902fed, 0x1b7a5c76, 0xb5e2e500, 0x6108969b, 0x5c3173ed, + 0x88db0076, 0x4c867201, 0x986c019a, 0xa555e4ec, 0x71bf9777, + 0xdf272e01, 0x0bcd5d9a, 0x36f4b8ec, 0xe21ecb77, 0x6ac5cb01, + 0xbe2fb89a, 0x83165dec, 0x57fc2e77, 0xf9649701, 0x2d8ee49a, + 0x10b701ec, 0xc45d7277, 0x980ce502, 0x4ce69699, 0x71df73ef, + 0xa5350074, 0x0badb902, 0xdf47ca99, 0xe27e2fef, 0x36945c74, + 0xbe4f5c02, 0x6aa52f99, 0x579ccaef, 0x8376b974, 0x2dee0002, + 0xf9047399, 0xc43d96ef, 0x10d7e574, 0xd48a9703, 0x0060e498, + 0x3d5901ee, 0xe9b37275, 0x472bcb03, 0x93c1b898, 0xaef85dee, + 0x7a122e75, 0xf2c92e03, 0x26235d98, 0x1b1ab8ee, 0xcff0cb75, + 0x61687203, 0xb5820198, 0x88bbe4ee, 0x5c519775, 0x3019ca05, + 0xe4f3b99e, 0xd9ca5ce8, 0x0d202f73, 0xa3b89605, 0x7752e59e, + 0x4a6b00e8, 0x9e817373, 0x165a7305, 0xc2b0009e, 0xff89e5e8, + 0x2b639673, 0x85fb2f05, 0x51115c9e, 0x6c28b9e8, 0xb8c2ca73, + 0x7c9fb804, 0xa875cb9f, 0x954c2ee9, 0x41a65d72, 0xef3ee404, + 0x3bd4979f, 0x06ed72e9, 0xd2070172, 0x5adc0104, 0x8e36729f, + 0xb30f97e9, 0x67e5e472, 0xc97d5d04, 0x1d972e9f, 0x20aecbe9, + 0xf444b872, 0xa8152f07, 0x7cff5c9c, 0x41c6b9ea, 0x952cca71, + 0x3bb47307, 0xef5e009c, 0xd267e5ea, 0x068d9671, 0x8e569607, + 0x5abce59c, 0x678500ea, 0xb36f7371, 0x1df7ca07, 0xc91db99c, + 0xf4245cea, 0x20ce2f71, 0xe4935d06, 0x30792e9d, 0x0d40cbeb, + 0xd9aab870, 0x77320106, 0xa3d8729d, 0x9ee197eb, 0x4a0be470, + 0xc2d0e406, 0x163a979d, 0x2b0372eb, 0xffe90170, 0x5171b806, + 0x859bcb9d, 0xb8a22eeb, 0x6c485d70, 0x6032940b, 0xb4d8e790, + 0x89e102e6, 0x5d0b717d, 0xf393c80b, 0x2779bb90, 0x1a405ee6, + 0xceaa2d7d, 0x46712d0b, 0x929b5e90, 0xafa2bbe6, 0x7b48c87d, + 0xd5d0710b, 0x013a0290, 0x3c03e7e6, 0xe8e9947d, 0x2cb4e60a, + 0xf85e9591, 0xc56770e7, 0x118d037c, 0xbf15ba0a, 0x6bffc991, + 0x56c62ce7, 0x822c5f7c, 0x0af75f0a, 0xde1d2c91, 0xe324c9e7, + 0x37ceba7c, 0x9956030a, 0x4dbc7091, 0x708595e7, 0xa46fe67c, + 0xf83e7109, 0x2cd40292, 0x11ede7e4, 0xc507947f, 0x6b9f2d09, + 0xbf755e92, 0x824cbbe4, 0x56a6c87f, 0xde7dc809, 0x0a97bb92, + 0x37ae5ee4, 0xe3442d7f, 0x4ddc9409, 0x9936e792, 0xa40f02e4, + 0x70e5717f, 0xb4b80308, 0x60527093, 0x5d6b95e5, 0x8981e67e, + 0x27195f08, 0xf3f32c93, 0xcecac9e5, 0x1a20ba7e, 0x92fbba08, + 0x4611c993, 0x7b282ce5, 0xafc25f7e, 0x015ae608, 0xd5b09593, + 0xe88970e5, 0x3c63037e, 0x502b5e0e, 0x84c12d95, 0xb9f8c8e3, + 0x6d12bb78, 0xc38a020e, 0x17607195, 0x2a5994e3, 0xfeb3e778, + 0x7668e70e, 0xa2829495, 0x9fbb71e3, 0x4b510278, 0xe5c9bb0e, + 0x3123c895, 0x0c1a2de3, 0xd8f05e78, 0x1cad2c0f, 0xc8475f94, + 0xf57ebae2, 0x2194c979, 0x8f0c700f, 0x5be60394, 0x66dfe6e2, + 0xb2359579, 0x3aee950f, 0xee04e694, 0xd33d03e2, 0x07d77079, + 0xa94fc90f, 0x7da5ba94, 0x409c5fe2, 0x94762c79, 0xc827bb0c, + 0x1ccdc897, 0x21f42de1, 0xf51e5e7a, 0x5b86e70c, 0x8f6c9497, + 0xb25571e1, 0x66bf027a, 0xee64020c, 0x3a8e7197, 0x07b794e1, + 0xd35de77a, 0x7dc55e0c, 0xa92f2d97, 0x9416c8e1, 0x40fcbb7a, + 0x84a1c90d, 0x504bba96, 0x6d725fe0, 0xb9982c7b, 0x1700950d, + 0xc3eae696, 0xfed303e0, 0x2a39707b, 0xa2e2700d, 0x76080396, + 0x4b31e6e0, 0x9fdb957b, 0x31432c0d, 0xe5a95f96, 0xd890bae0, + 0x0c7ac97b}, + {0x00000000, 0x27652581, 0x0fcc3bd9, 0x28a91e58, 0x5f9e0669, + 0x78fb23e8, 0x50523db0, 0x77371831, 0xbe3c0dd2, 0x99592853, + 0xb1f0360b, 0x9695138a, 0xe1a20bbb, 0xc6c72e3a, 0xee6e3062, + 0xc90b15e3, 0x3d7f6b7f, 0x1a1a4efe, 0x32b350a6, 0x15d67527, + 0x62e16d16, 0x45844897, 0x6d2d56cf, 0x4a48734e, 0x834366ad, + 0xa426432c, 0x8c8f5d74, 0xabea78f5, 0xdcdd60c4, 0xfbb84545, + 0xd3115b1d, 0xf4747e9c, 0x7afed6fe, 0x5d9bf37f, 0x7532ed27, + 0x5257c8a6, 0x2560d097, 0x0205f516, 0x2aaceb4e, 0x0dc9cecf, + 0xc4c2db2c, 0xe3a7fead, 0xcb0ee0f5, 0xec6bc574, 0x9b5cdd45, + 0xbc39f8c4, 0x9490e69c, 0xb3f5c31d, 0x4781bd81, 0x60e49800, + 0x484d8658, 0x6f28a3d9, 0x181fbbe8, 0x3f7a9e69, 0x17d38031, + 0x30b6a5b0, 0xf9bdb053, 0xded895d2, 0xf6718b8a, 0xd114ae0b, + 0xa623b63a, 0x814693bb, 0xa9ef8de3, 0x8e8aa862, 0xb5fadc26, + 0x929ff9a7, 0xba36e7ff, 0x9d53c27e, 0xea64da4f, 0xcd01ffce, + 0xe5a8e196, 0xc2cdc417, 0x0bc6d1f4, 0x2ca3f475, 0x040aea2d, + 0x236fcfac, 0x5458d79d, 0x733df21c, 0x5b94ec44, 0x7cf1c9c5, + 0x8885b759, 0xafe092d8, 0x87498c80, 0xa02ca901, 0xd71bb130, + 0xf07e94b1, 0xd8d78ae9, 0xffb2af68, 0x36b9ba8b, 0x11dc9f0a, + 0x39758152, 0x1e10a4d3, 0x6927bce2, 0x4e429963, 0x66eb873b, + 0x418ea2ba, 0xcf040ad8, 0xe8612f59, 0xc0c83101, 0xe7ad1480, + 0x909a0cb1, 0xb7ff2930, 0x9f563768, 0xb83312e9, 0x7138070a, + 0x565d228b, 0x7ef43cd3, 0x59911952, 0x2ea60163, 0x09c324e2, + 0x216a3aba, 0x060f1f3b, 0xf27b61a7, 0xd51e4426, 0xfdb75a7e, + 0xdad27fff, 0xade567ce, 0x8a80424f, 0xa2295c17, 0x854c7996, + 0x4c476c75, 0x6b2249f4, 0x438b57ac, 0x64ee722d, 0x13d96a1c, + 0x34bc4f9d, 0x1c1551c5, 0x3b707444, 0x6af5b94d, 0x4d909ccc, + 0x65398294, 0x425ca715, 0x356bbf24, 0x120e9aa5, 0x3aa784fd, + 0x1dc2a17c, 0xd4c9b49f, 0xf3ac911e, 0xdb058f46, 0xfc60aac7, + 0x8b57b2f6, 0xac329777, 0x849b892f, 0xa3feacae, 0x578ad232, + 0x70eff7b3, 0x5846e9eb, 0x7f23cc6a, 0x0814d45b, 0x2f71f1da, + 0x07d8ef82, 0x20bdca03, 0xe9b6dfe0, 0xced3fa61, 0xe67ae439, + 0xc11fc1b8, 0xb628d989, 0x914dfc08, 0xb9e4e250, 0x9e81c7d1, + 0x100b6fb3, 0x376e4a32, 0x1fc7546a, 0x38a271eb, 0x4f9569da, + 0x68f04c5b, 0x40595203, 0x673c7782, 0xae376261, 0x895247e0, + 0xa1fb59b8, 0x869e7c39, 0xf1a96408, 0xd6cc4189, 0xfe655fd1, + 0xd9007a50, 0x2d7404cc, 0x0a11214d, 0x22b83f15, 0x05dd1a94, + 0x72ea02a5, 0x558f2724, 0x7d26397c, 0x5a431cfd, 0x9348091e, + 0xb42d2c9f, 0x9c8432c7, 0xbbe11746, 0xccd60f77, 0xebb32af6, + 0xc31a34ae, 0xe47f112f, 0xdf0f656b, 0xf86a40ea, 0xd0c35eb2, + 0xf7a67b33, 0x80916302, 0xa7f44683, 0x8f5d58db, 0xa8387d5a, + 0x613368b9, 0x46564d38, 0x6eff5360, 0x499a76e1, 0x3ead6ed0, + 0x19c84b51, 0x31615509, 0x16047088, 0xe2700e14, 0xc5152b95, + 0xedbc35cd, 0xcad9104c, 0xbdee087d, 0x9a8b2dfc, 0xb22233a4, + 0x95471625, 0x5c4c03c6, 0x7b292647, 0x5380381f, 0x74e51d9e, + 0x03d205af, 0x24b7202e, 0x0c1e3e76, 0x2b7b1bf7, 0xa5f1b395, + 0x82949614, 0xaa3d884c, 0x8d58adcd, 0xfa6fb5fc, 0xdd0a907d, + 0xf5a38e25, 0xd2c6aba4, 0x1bcdbe47, 0x3ca89bc6, 0x1401859e, + 0x3364a01f, 0x4453b82e, 0x63369daf, 0x4b9f83f7, 0x6cfaa676, + 0x988ed8ea, 0xbfebfd6b, 0x9742e333, 0xb027c6b2, 0xc710de83, + 0xe075fb02, 0xc8dce55a, 0xefb9c0db, 0x26b2d538, 0x01d7f0b9, + 0x297eeee1, 0x0e1bcb60, 0x792cd351, 0x5e49f6d0, 0x76e0e888, + 0x5185cd09}}; + +#endif + +#endif + +#endif + +local const z_crc_t FAR x2n_table[] = { + 0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000, + 0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467, + 0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0, + 0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169, + 0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37, + 0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a, + 0xc40ba6d0, 0xc4e22c3c}; diff --git a/lib/libesp32_lvgl/freetype/src/gzip/ftgzip.c b/lib/libesp32_lvgl/freetype/src/gzip/ftgzip.c index de7d0fdd5..ca6a2aabe 100644 --- a/lib/libesp32_lvgl/freetype/src/gzip/ftgzip.c +++ b/lib/libesp32_lvgl/freetype/src/gzip/ftgzip.c @@ -8,7 +8,7 @@ * parse compressed PCF fonts, as found with many X11 server * distributions. * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -69,10 +69,14 @@ /* */ /* so that configuration with `FT_CONFIG_OPTION_SYSTEM_ZLIB' might */ /* include the wrong `zconf.h' file, leading to errors. */ -#include "zlib.h" -#undef SLOW -#define SLOW 1 /* we can't use asm-optimized sources here! */ +#define ZEXPORT + /* prevent zlib functions from being visible outside their object files */ +#define ZEXTERN static + +#define HAVE_MEMCPY 1 +#define Z_SOLO 1 +#define Z_FREETYPE 1 #if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */ /* We disable the warning `conversion from XXX to YYY, */ @@ -83,24 +87,25 @@ #pragma warning( disable : 4244 ) #endif /* _MSC_VER */ - /* Urgh. `inflate_mask' must not be declared twice -- C++ doesn't like - this. We temporarily disable it and load all necessary header files. */ -#define NO_INFLATE_MASK -#include "zutil.h" -#include "inftrees.h" -#include "infblock.h" -#include "infcodes.h" -#include "infutil.h" -#undef NO_INFLATE_MASK +#if defined( __GNUC__ ) +#pragma GCC diagnostic push +#ifndef __cplusplus +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +#endif +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif - /* infutil.c must be included before infcodes.c */ #include "zutil.c" -#include "inftrees.c" -#include "infutil.c" -#include "infcodes.c" -#include "infblock.c" +#include "inffast.c" #include "inflate.c" +#include "inftrees.c" #include "adler32.c" +#include "crc32.c" + +#if defined( __GNUC__ ) +#pragma GCC diagnostic pop +#endif #if defined( _MSC_VER ) #pragma warning( pop ) @@ -121,48 +126,32 @@ 'malloc/free' */ static voidpf - ft_gzip_alloc( FT_Memory memory, - uInt items, - uInt size ) + ft_gzip_alloc( voidpf opaque, + uInt items, + uInt size ) { - FT_ULong sz = (FT_ULong)size * items; + FT_Memory memory = (FT_Memory)opaque; + FT_ULong sz = (FT_ULong)size * items; FT_Error error; - FT_Pointer p = NULL; + FT_Pointer p = NULL; - (void)FT_ALLOC( p, sz ); + /* allocate and zero out */ + FT_MEM_ALLOC( p, sz ); return p; } static void - ft_gzip_free( FT_Memory memory, - voidpf address ) + ft_gzip_free( voidpf opaque, + voidpf address ) { + FT_Memory memory = (FT_Memory)opaque; + + FT_MEM_FREE( address ); } - -#if !defined( FT_CONFIG_OPTION_SYSTEM_ZLIB ) && !defined( USE_ZLIB_ZCALLOC ) - - local voidpf - zcalloc ( voidpf opaque, - unsigned items, - unsigned size ) - { - return ft_gzip_alloc( (FT_Memory)opaque, items, size ); - } - - local void - zcfree( voidpf opaque, - voidpf ptr ) - { - ft_gzip_free( (FT_Memory)opaque, ptr ); - } - -#endif /* !SYSTEM_ZLIB && !USE_ZLIB_ZCALLOC */ - - /***************************************************************************/ /***************************************************************************/ /***** *****/ @@ -304,8 +293,8 @@ } /* initialize zlib -- there is no zlib header in the compressed stream */ - zstream->zalloc = (alloc_func)ft_gzip_alloc; - zstream->zfree = (free_func) ft_gzip_free; + zstream->zalloc = ft_gzip_alloc; + zstream->zfree = ft_gzip_free; zstream->opaque = stream->memory; zstream->avail_in = 0; @@ -462,12 +451,13 @@ FT_ULong count ) { FT_Error error = FT_Err_Ok; - FT_ULong delta; for (;;) { - delta = (FT_ULong)( zip->limit - zip->cursor ); + FT_ULong delta = (FT_ULong)( zip->limit - zip->cursor ); + + if ( delta >= count ) delta = count; @@ -671,7 +661,7 @@ FT_Byte* zip_buff = NULL; - if ( !FT_ALLOC( zip_buff, zip_size ) ) + if ( !FT_QALLOC( zip_buff, zip_size ) ) { FT_ULong count; @@ -741,20 +731,11 @@ stream.next_out = output; stream.avail_out = (uInt)*output_len; - stream.zalloc = (alloc_func)ft_gzip_alloc; - stream.zfree = (free_func) ft_gzip_free; + stream.zalloc = ft_gzip_alloc; + stream.zfree = ft_gzip_free; stream.opaque = memory; - /* This is a temporary fix and will be removed once the internal - * copy of zlib is updated to the newest version. The `|32' flag - * is only supported in the new versions of zlib to enable gzip - * encoded header. - */ -#ifdef FT_CONFIG_OPTION_SYSTEM_ZLIB err = inflateInit2( &stream, MAX_WBITS|32 ); -#else - err = inflateInit2( &stream, MAX_WBITS ); -#endif if ( err != Z_OK ) return FT_THROW( Invalid_Argument ); @@ -782,6 +763,9 @@ if ( err == Z_DATA_ERROR ) return FT_THROW( Invalid_Table ); + if ( err == Z_NEED_DICT ) + return FT_THROW( Invalid_Table ); + return FT_Err_Ok; } diff --git a/lib/libesp32_lvgl/freetype/src/gzip/ftzconf.h b/lib/libesp32_lvgl/freetype/src/gzip/ftzconf.h index 3abf0ba03..bf977d3e7 100644 --- a/lib/libesp32_lvgl/freetype/src/gzip/ftzconf.h +++ b/lib/libesp32_lvgl/freetype/src/gzip/ftzconf.h @@ -1,109 +1,258 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2002 Jean-loup Gailly. + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ -#ifndef _ZCONF_H -#define _ZCONF_H +#ifndef ZCONF_H +#define ZCONF_H /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". */ -#ifdef Z_PREFIX -# define deflateInit_ z_deflateInit_ -# define deflate z_deflate -# define deflateEnd z_deflateEnd -# define inflateInit_ z_inflateInit_ -# define inflate z_inflate -# define inflateEnd z_inflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateSetDictionary z_deflateSetDictionary -# define deflateCopy z_deflateCopy -# define deflateReset z_deflateReset -# define deflateParams z_deflateParams -# define inflateInit2_ z_inflateInit2_ -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateReset z_inflateReset -# define compress z_compress -# define compress2 z_compress2 -# define uncompress z_uncompress -# define adler32 z_adler32 -# define crc32 z_crc32 -# define get_crc_table z_get_crc_table +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET -# define Byte z_Byte -# define uInt z_uInt -# define uLong z_uLong -# define Bytef z_Bytef -# define charf z_charf -# define intf z_intf -# define uIntf z_uIntf -# define uLongf z_uLongf -# define voidpf z_voidpf -# define voidp z_voidp -#endif - -#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) -# define WIN32 -#endif -#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) -# ifndef __32BIT__ -# define __32BIT__ +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound # endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_combine_gen z_crc32_combine_gen +# define crc32_combine_gen64 z_crc32_combine_gen64 +# define crc32_combine_op z_crc32_combine_op +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + #endif + #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif - -/* WinCE doesn't have errno.h */ -#ifdef _WIN32_WCE -# define NO_ERRNO_H +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif #endif - /* * Compile with -DMAXSEG_64K if the alloc function cannot allocate more * than 64k bytes at a time (needed on systems with 16-bit int). */ -#if defined(MSDOS) && !defined(__32BIT__) +#ifdef SYS16BIT # define MAXSEG_64K #endif #ifdef MSDOS # define UNALIGNED_OK #endif -#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) -# define STDC -#endif -#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) +#ifdef __STDC_VERSION__ # ifndef STDC # define STDC # endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC #endif #ifndef STDC # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const +# define const /* note: need a more gentle solution here */ # endif #endif -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) -# define NO_DUMMY_DECL +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const #endif -/* Old Borland C and LCC incorrectly complains about missing returns: */ -#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) -# define NEED_DUMMY_RETURN -#endif - -#if defined(__LCC__) -# define NEED_DUMMY_RETURN +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong #endif /* Maximum value for memLevel in deflateInit2 */ @@ -133,7 +282,7 @@ Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes for small objects. */ @@ -147,75 +296,104 @@ # endif #endif +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, * just define FAR to be empty. */ -#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -#endif -#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) -# ifndef __32BIT__ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ # define SMALL_MEDIUM -# define FAR _far +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif # endif #endif -/* Compile with -DZLIB_DLL for Windows DLL support */ -#if defined(ZLIB_DLL) -# if defined(_WINDOWS) || defined(WINDOWS) +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI # ifdef FAR # undef FAR # endif -# include -# define ZEXPORT(x) x WINAPI -# ifdef WIN32 -# define ZEXPORTVA(x) x WINAPIV -# else -# define ZEXPORTVA(x) x FAR _cdecl _export +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN # endif -# endif -# if defined (__BORLANDC__) -# if (__BORLANDC__ >= 0x0500) && defined (WIN32) -# include -# define ZEXPORT(x) x __declspec(dllexport) WINAPI -# define ZEXPORTRVA(x) x __declspec(dllexport) WINAPIV +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV # else -# if defined (_Windows) && defined (__DLL__) -# define ZEXPORT(x) x _export -# define ZEXPORTVA(x) x _export -# endif +# define ZEXPORTVA FAR CDECL # endif # endif #endif +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif +#ifndef ZEXTERN +# define ZEXTERN extern +#endif #ifndef ZEXPORT -# define ZEXPORT(x) static x +# define ZEXPORT #endif #ifndef ZEXPORTVA -# define ZEXPORTVA(x) static x -#endif -#ifndef ZEXTERN -# define ZEXTERN(x) static x -#endif -#ifndef ZEXTERNDEF -# define ZEXTERNDEF(x) static x +# define ZEXPORTVA #endif #ifndef FAR -# define FAR +# define FAR #endif -#if !defined(MACOS) && !defined(TARGET_OS_MAC) +#if !defined(__MACTYPES__) typedef unsigned char Byte; /* 8 bits */ #endif typedef unsigned int uInt; /* 16 bits or more */ @@ -233,52 +411,137 @@ typedef uInt FAR uIntf; typedef uLong FAR uLongf; #ifdef STDC - typedef void FAR *voidpf; - typedef void *voidp; + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; #else - typedef Byte FAR *voidpf; - typedef Byte *voidp; + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; #endif -#ifdef HAVE_UNISTD_H -# include /* for off_t */ -# include /* for SEEK_* and off_t */ -# define z_off_t off_t +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif #endif -#ifndef SEEK_SET + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#ifndef Z_HAVE_UNISTD_H +# ifdef __WATCOMC__ +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_HAVE_UNISTD_H +# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif + #ifndef z_off_t -# define z_off_t long +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif #endif /* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) -# pragma map(deflateInit_,"DEIN") -# pragma map(deflateInit2_,"DEIN2") -# pragma map(deflateEnd,"DEEND") -# pragma map(inflateInit_,"ININ") -# pragma map(inflateInit2_,"ININ2") -# pragma map(inflateEnd,"INEND") -# pragma map(inflateSync,"INSY") -# pragma map(inflateSetDictionary,"INSEDI") -# pragma map(inflate_blocks,"INBL") -# pragma map(inflate_blocks_new,"INBLNE") -# pragma map(inflate_blocks_free,"INBLFR") -# pragma map(inflate_blocks_reset,"INBLRE") -# pragma map(inflate_codes_free,"INCOFR") -# pragma map(inflate_codes,"INCO") -# pragma map(inflate_fast,"INFA") -# pragma map(inflate_flush,"INFLU") -# pragma map(inflate_mask,"INMA") -# pragma map(inflate_set_dictionary,"INSEDI2") -# pragma map(inflate_copyright,"INCOPY") -# pragma map(inflate_trees_bits,"INTRBI") -# pragma map(inflate_trees_dynamic,"INTRDY") -# pragma map(inflate_trees_fixed,"INTRFI") -# pragma map(inflate_trees_free,"INTRFR") + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") #endif -#endif /* _ZCONF_H */ +#endif /* ZCONF_H */ diff --git a/lib/libesp32_lvgl/freetype/src/gzip/gzguts.h b/lib/libesp32_lvgl/freetype/src/gzip/gzguts.h new file mode 100644 index 000000000..4f09a52a7 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/gzip/gzguts.h @@ -0,0 +1,219 @@ +/* gzguts.h -- zlib internal header definitions for gz* operations + * Copyright (C) 2004-2019 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef _LARGEFILE64_SOURCE +# ifndef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE 1 +# endif +# ifdef _FILE_OFFSET_BITS +# undef _FILE_OFFSET_BITS +# endif +#endif + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include +#include "zlib.h" +#ifdef STDC +# include +# include +# include +#endif + +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE +#endif +#include + +#ifdef _WIN32 +# include +#endif + +#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) +# include +#endif + +#if defined(_WIN32) +# define WIDECHAR +#endif + +#ifdef WINAPI_FAMILY +# define open _open +# define read _read +# define write _write +# define close _close +#endif + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS +/* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 +/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +# ifdef VMS +# define NO_vsnprintf +# endif +# ifdef __OS400__ +# define NO_vsnprintf +# endif +# ifdef __MVS__ +# define NO_vsnprintf +# endif +#endif + +/* unlike snprintf (which is required in C99), _snprintf does not guarantee + null termination of the result -- however this is only used in gzlib.c where + the result is assured to fit in the space provided */ +#if defined(_MSC_VER) && _MSC_VER < 1900 +# define snprintf _snprintf +#endif + +#ifndef local +# define local static +#endif +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ + +/* gz* functions always use library allocation functions */ +#ifndef STDC + extern voidp malloc OF((uInt size)); + extern void free OF((voidpf ptr)); +#endif + +/* get errno and strerror definition */ +#if defined UNDER_CE +# include +# define zstrerror() gz_strwinerror((DWORD)GetLastError()) +#else +# ifndef NO_STRERROR +# include +# define zstrerror() strerror(errno) +# else +# define zstrerror() "stdio error (consult errno)" +# endif +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); +#endif + +/* default memLevel */ +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif + +/* default i/o buffer size -- double this for output when reading (this and + twice this must be able to fit in an unsigned type) */ +#define GZBUFSIZE 8192 + +/* gzip modes, also provide a little integrity check on the passed structure */ +#define GZ_NONE 0 +#define GZ_READ 7247 +#define GZ_WRITE 31153 +#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ + +/* values for gz_state how */ +#define LOOK 0 /* look for a gzip header */ +#define COPY__ 1 /* copy input directly */ +#define GZIP 2 /* decompress a gzip stream */ + +/* internal gzip file state data structure */ +typedef struct { + /* exposed contents for gzgetc() macro */ + struct gzFile_s x; /* "x" for exposed */ + /* x.have: number of bytes available at x.next */ + /* x.next: next output data to deliver or write */ + /* x.pos: current position in uncompressed data */ + /* used for both reading and writing */ + int mode; /* see gzip modes above */ + int fd; /* file descriptor */ + char *path; /* path or fd for error messages */ + unsigned size; /* buffer size, zero if not allocated yet */ + unsigned want; /* requested buffer size, default is GZBUFSIZE */ + unsigned char *in; /* input buffer (double-sized when writing) */ + unsigned char *out; /* output buffer (double-sized when reading) */ + int direct; /* 0 if processing gzip, 1 if transparent */ + /* just for reading */ + int how; /* 0: get header, 1: copy, 2: decompress */ + z_off64_t start; /* where the gzip data started, for rewinding */ + int eof; /* true if end of input file reached */ + int past; /* true if read requested past end */ + /* just for writing */ + int level; /* compression level */ + int strategy; /* compression strategy */ + int reset; /* true if a reset is pending after a Z_FINISH */ + /* seek request */ + z_off64_t skip; /* amount to skip (already rewound if backwards) */ + int seek; /* true if seek request pending */ + /* error information */ + int err; /* error code */ + char *msg; /* error message */ + /* zlib inflate or deflate stream */ + z_stream strm; /* stream structure in-place (not a pointer) */ +} gz_state; +typedef gz_state FAR *gz_statep; + +/* shared functions */ +void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +#if defined UNDER_CE +char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); +#endif + +/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t + value -- needed when comparing unsigned to z_off64_t, which is signed + (possible z_off64_t types off_t, off64_t, and long are all signed) */ +#ifdef INT_MAX +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) +#else +unsigned ZLIB_INTERNAL gz_intmax OF((void)); +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) +#endif diff --git a/lib/libesp32_lvgl/freetype/src/gzip/infblock.c b/lib/libesp32_lvgl/freetype/src/gzip/infblock.c deleted file mode 100644 index 2b4f0c2b5..000000000 --- a/lib/libesp32_lvgl/freetype/src/gzip/infblock.c +++ /dev/null @@ -1,392 +0,0 @@ -/* infblock.c -- interpret and process block types to last block - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "infblock.h" -#include "inftrees.h" -#include "infcodes.h" -#include "infutil.h" - - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -/* Table for deflate from PKZIP's appnote.txt. */ -local const uInt border[] = { /* Order of the bit length code lengths */ - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - -/* - Notes beyond the 1.93a appnote.txt: - - 1. Distance pointers never point before the beginning of the output - stream. - 2. Distance pointers can point back across blocks, up to 32k away. - 3. There is an implied maximum of 7 bits for the bit length table and - 15 bits for the actual data. - 4. If only one code exists, then it is encoded using one bit. (Zero - would be more efficient, but perhaps a little confusing.) If two - codes exist, they are coded using one bit each (0 and 1). - 5. There is no way of sending zero distance codes--a dummy must be - sent if there are none. (History: a pre 2.0 version of PKZIP would - store blocks with no distance codes, but this was discovered to be - too harsh a criterion.) Valid only for 1.93a. 2.04c does allow - zero distance codes, which is sent as one code of zero bits in - length. - 6. There are up to 286 literal/length codes. Code 256 represents the - end-of-block. Note however that the static length tree defines - 288 codes just to fill out the Huffman codes. Codes 286 and 287 - cannot be used though, since there is no length base or extra bits - defined for them. Similarily, there are up to 30 distance codes. - However, static trees define 32 codes (all 5 bits) to fill out the - Huffman codes, but the last two had better not show up in the data. - 7. Unzip can check dynamic Huffman blocks for complete code sets. - The exception is that a single code would not be complete (see #4). - 8. The five bits following the block type is really the number of - literal codes sent minus 257. - 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits - (1+6+6). Therefore, to output three times the length, you output - three codes (1+1+1), whereas to output four times the same length, - you only need two codes (1+3). Hmm. - 10. In the tree reconstruction algorithm, Code = Code + Increment - only if BitLength(i) is not zero. (Pretty obvious.) - 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) - 12. Note: length code 284 can represent 227-258, but length code 285 - really is 258. The last length deserves its own, short code - since it gets used a lot in very redundant files. The length - 258 is special since 258 - 3 (the min match length) is 255. - 13. The literal/length and distance code bit lengths are read as a - single stream of lengths. It is possible (and advantageous) for - a repeat code (16, 17, or 18) to go across the boundary between - the two sets of lengths. - */ - - -local void inflate_blocks_reset( /* s, z, c) */ -inflate_blocks_statef *s, -z_streamp z, -uLongf *c ) -{ - if (c != Z_NULL) - *c = s->check; - if (s->mode == BTREE || s->mode == DTREE) - ZFREE(z, s->sub.trees.blens); - if (s->mode == CODES) - inflate_codes_free(s->sub.decode.codes, z); - s->mode = TYPE; - s->bitk = 0; - s->bitb = 0; - s->read = s->write = s->window; - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); - Tracev((stderr, "inflate: blocks reset\n")); -} - - -local inflate_blocks_statef *inflate_blocks_new( /* z, c, w) */ -z_streamp z, -check_func c, -uInt w ) -{ - inflate_blocks_statef *s; - - if ((s = (inflate_blocks_statef *)ZALLOC - (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) - return s; - if ((s->hufts = - (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) - { - ZFREE(z, s); - return Z_NULL; - } - if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) - { - ZFREE(z, s->hufts); - ZFREE(z, s); - return Z_NULL; - } - s->end = s->window + w; - s->checkfn = c; - s->mode = TYPE; - Tracev((stderr, "inflate: blocks allocated\n")); - inflate_blocks_reset(s, z, Z_NULL); - return s; -} - - -local int inflate_blocks( /* s, z, r) */ -inflate_blocks_statef *s, -z_streamp z, -int r ) -{ - uInt t; /* temporary storage */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input based on current state */ - while (1) switch (s->mode) - { - case TYPE: - NEEDBITS(3) - t = (uInt)b & 7; - s->last = t & 1; - switch (t >> 1) - { - case 0: /* stored */ - Tracev((stderr, "inflate: stored block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - t = k & 7; /* go to byte boundary */ - DUMPBITS(t) - s->mode = LENS; /* get length of stored block */ - break; - case 1: /* fixed */ - Tracev((stderr, "inflate: fixed codes block%s\n", - s->last ? " (last)" : "")); - { - uInt bl, bd; - inflate_huft *tl, *td; - - inflate_trees_fixed(&bl, &bd, (const inflate_huft**)&tl, - (const inflate_huft**)&td, z); - s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); - if (s->sub.decode.codes == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - } - DUMPBITS(3) - s->mode = CODES; - break; - case 2: /* dynamic */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - s->mode = TABLE; - break; - case 3: /* illegal */ - DUMPBITS(3) - s->mode = BAD; - z->msg = (char*)"invalid block type"; - r = Z_DATA_ERROR; - LEAVE - } - break; - case LENS: - NEEDBITS(32) - if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) - { - s->mode = BAD; - z->msg = (char*)"invalid stored block lengths"; - r = Z_DATA_ERROR; - LEAVE - } - s->sub.left = (uInt)b & 0xffff; - b = k = 0; /* dump bits */ - Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); - s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); - break; - case STORED: - if (n == 0) - LEAVE - NEEDOUT - t = s->sub.left; - if (t > n) t = n; - if (t > m) t = m; - zmemcpy(q, p, t); - p += t; n -= t; - q += t; m -= t; - if ((s->sub.left -= t) != 0) - break; - Tracev((stderr, "inflate: stored end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - s->mode = s->last ? DRY : TYPE; - break; - case TABLE: - NEEDBITS(14) - s->sub.trees.table = t = (uInt)b & 0x3fff; -#ifndef PKZIP_BUG_WORKAROUND - if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) - { - s->mode = BAD; - z->msg = (char*)"too many length or distance symbols"; - r = Z_DATA_ERROR; - LEAVE - } -#endif - t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); - if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - DUMPBITS(14) - s->sub.trees.index = 0; - Tracev((stderr, "inflate: table sizes ok\n")); - s->mode = BTREE; - /* fall through */ - case BTREE: - while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) - { - NEEDBITS(3) - s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; - DUMPBITS(3) - } - while (s->sub.trees.index < 19) - s->sub.trees.blens[border[s->sub.trees.index++]] = 0; - s->sub.trees.bb = 7; - t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, - &s->sub.trees.tb, s->hufts, z); - if (t != Z_OK) - { - r = t; - if (r == Z_DATA_ERROR) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - } - LEAVE - } - s->sub.trees.index = 0; - Tracev((stderr, "inflate: bits tree ok\n")); - s->mode = DTREE; - /* fall through */ - case DTREE: - while (t = s->sub.trees.table, - s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) - { - inflate_huft *h; - uInt i, j, c; - - t = s->sub.trees.bb; - NEEDBITS(t) - h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); - t = h->bits; - c = h->base; - if (c < 16) - { - DUMPBITS(t) - s->sub.trees.blens[s->sub.trees.index++] = c; - } - else /* c == 16..18 */ - { - i = c == 18 ? 7 : c - 14; - j = c == 18 ? 11 : 3; - NEEDBITS(t + i) - DUMPBITS(t) - j += (uInt)b & inflate_mask[i]; - DUMPBITS(i) - i = s->sub.trees.index; - t = s->sub.trees.table; - if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || - (c == 16 && i < 1)) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - z->msg = (char*)"invalid bit length repeat"; - r = Z_DATA_ERROR; - LEAVE - } - c = c == 16 ? s->sub.trees.blens[i - 1] : 0; - do { - s->sub.trees.blens[i++] = c; - } while (--j); - s->sub.trees.index = i; - } - } - s->sub.trees.tb = Z_NULL; - { - uInt bl, bd; - inflate_huft *tl, *td; - inflate_codes_statef *c; - - bl = 9; /* must be <= 9 for lookahead assumptions */ - bd = 6; /* must be <= 9 for lookahead assumptions */ - t = s->sub.trees.table; - t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), - s->sub.trees.blens, &bl, &bd, &tl, &td, - s->hufts, z); - if (t != Z_OK) - { - if (t == (uInt)Z_DATA_ERROR) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - } - r = t; - LEAVE - } - Tracev((stderr, "inflate: trees ok\n")); - if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - s->sub.decode.codes = c; - } - ZFREE(z, s->sub.trees.blens); - s->mode = CODES; - /* fall through */ - case CODES: - UPDATE - if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) - return inflate_flush(s, z, r); - r = Z_OK; - inflate_codes_free(s->sub.decode.codes, z); - LOAD - Tracev((stderr, "inflate: codes end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - if (!s->last) - { - s->mode = TYPE; - break; - } - s->mode = DRY; - /* fall through */ - case DRY: - FLUSH - if (s->read != s->write) - LEAVE - s->mode = DONE; - /* fall through */ - case DONE: - r = Z_STREAM_END; - LEAVE - case BAD: - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -#ifdef NEED_DUMMY_RETURN - return 0; -#endif -} - - -local int inflate_blocks_free( /* s, z) */ -inflate_blocks_statef *s, -z_streamp z ) -{ - inflate_blocks_reset(s, z, Z_NULL); - ZFREE(z, s->window); - ZFREE(z, s->hufts); - ZFREE(z, s); - Tracev((stderr, "inflate: blocks freed\n")); - return Z_OK; -} - - diff --git a/lib/libesp32_lvgl/freetype/src/gzip/infblock.h b/lib/libesp32_lvgl/freetype/src/gzip/infblock.h deleted file mode 100644 index c2535a1e4..000000000 --- a/lib/libesp32_lvgl/freetype/src/gzip/infblock.h +++ /dev/null @@ -1,36 +0,0 @@ -/* infblock.h -- header to use infblock.c - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#ifndef _INFBLOCK_H -#define _INFBLOCK_H - -struct inflate_blocks_state; -typedef struct inflate_blocks_state FAR inflate_blocks_statef; - -local inflate_blocks_statef * inflate_blocks_new OF(( - z_streamp z, - check_func c, /* check function */ - uInt w)); /* window size */ - -local int inflate_blocks OF(( - inflate_blocks_statef *, - z_streamp , - int)); /* initial return code */ - -local void inflate_blocks_reset OF(( - inflate_blocks_statef *, - z_streamp , - uLongf *)); /* check value on output */ - -local int inflate_blocks_free OF(( - inflate_blocks_statef *, - z_streamp)); - -#endif /* _INFBLOCK_H */ diff --git a/lib/libesp32_lvgl/freetype/src/gzip/infcodes.c b/lib/libesp32_lvgl/freetype/src/gzip/infcodes.c deleted file mode 100644 index ba3065499..000000000 --- a/lib/libesp32_lvgl/freetype/src/gzip/infcodes.c +++ /dev/null @@ -1,254 +0,0 @@ -/* infcodes.c -- process literals and length/distance pairs - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" -#include "infblock.h" -#include "infcodes.h" -#include "infutil.h" - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - START, /* x: set up for LEN */ - LEN, /* i: get length/literal/eob next */ - LENEXT, /* i: getting length extra (have base) */ - DIST, /* i: get distance next */ - DISTEXT, /* i: getting distance extra */ - COPY, /* o: copying bytes in window, waiting for space */ - LIT, /* o: got literal, waiting for output space */ - WASH, /* o: got eob, possibly still output waiting */ - END, /* x: got eob and all data flushed */ - BADCODE} /* x: got error */ -inflate_codes_mode; - -/* inflate codes private state */ -struct inflate_codes_state { - - /* mode */ - inflate_codes_mode mode; /* current inflate_codes mode */ - - /* mode dependent information */ - uInt len; - union { - struct { - inflate_huft *tree; /* pointer into tree */ - uInt need; /* bits needed */ - } code; /* if LEN or DIST, where in tree */ - uInt lit; /* if LIT, literal */ - struct { - uInt get; /* bits to get for extra */ - uInt dist; /* distance back to copy from */ - } copy; /* if EXT or COPY, where and how much */ - } sub; /* submode */ - - /* mode independent information */ - Byte lbits; /* ltree bits decoded per branch */ - Byte dbits; /* dtree bits decoder per branch */ - inflate_huft *ltree; /* literal/length/eob tree */ - inflate_huft *dtree; /* distance tree */ - -}; - - -local inflate_codes_statef *inflate_codes_new( /* bl, bd, tl, td, z) */ -uInt bl, uInt bd, -inflate_huft *tl, -inflate_huft *td, /* need separate declaration for Borland C++ */ -z_streamp z ) -{ - inflate_codes_statef *c; - - if ((c = (inflate_codes_statef *) - ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) - { - c->mode = START; - c->lbits = (Byte)bl; - c->dbits = (Byte)bd; - c->ltree = tl; - c->dtree = td; - Tracev((stderr, "inflate: codes new\n")); - } - return c; -} - - -local int inflate_codes( /* s, z, r) */ -inflate_blocks_statef *s, -z_streamp z, -int r ) -{ - uInt j; /* temporary storage */ - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - Bytef *f; /* pointer to copy strings from */ - inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input and output based on current state */ - while (1) switch (c->mode) - { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - case START: /* x: set up for LEN */ -#ifndef SLOW - if (m >= 258 && n >= 10) - { - UPDATE - r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); - LOAD - if (r != Z_OK) - { - c->mode = r == Z_STREAM_END ? WASH : BADCODE; - break; - } - } -#endif /* !SLOW */ - c->sub.code.need = c->lbits; - c->sub.code.tree = c->ltree; - c->mode = LEN; - /* fall through */ - case LEN: /* i: get length/literal/eob next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e == 0) /* literal */ - { - c->sub.lit = t->base; - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", t->base)); - c->mode = LIT; - break; - } - if (e & 16) /* length */ - { - c->sub.copy.get = e & 15; - c->len = t->base; - c->mode = LENEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - if (e & 32) /* end of block */ - { - Tracevv((stderr, "inflate: end of block\n")); - c->mode = WASH; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = (char*)"invalid literal/length code"; - r = Z_DATA_ERROR; - LEAVE - case LENEXT: /* i: getting length extra (have base) */ - j = c->sub.copy.get; - NEEDBITS(j) - c->len += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - c->sub.code.need = c->dbits; - c->sub.code.tree = c->dtree; - Tracevv((stderr, "inflate: length %u\n", c->len)); - c->mode = DIST; - /* fall through */ - case DIST: /* i: get distance next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e & 16) /* distance */ - { - c->sub.copy.get = e & 15; - c->sub.copy.dist = t->base; - c->mode = DISTEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = (char*)"invalid distance code"; - r = Z_DATA_ERROR; - LEAVE - case DISTEXT: /* i: getting distance extra */ - j = c->sub.copy.get; - NEEDBITS(j) - c->sub.copy.dist += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); - c->mode = COPY; - /* fall through */ - case COPY: /* o: copying bytes in window, waiting for space */ - f = q - c->sub.copy.dist; - while (f < s->window) /* modulo window size-"while" instead */ - f += s->end - s->window; /* of "if" handles invalid distances */ - while (c->len) - { - NEEDOUT - OUTBYTE(*f++) - if (f == s->end) - f = s->window; - c->len--; - } - c->mode = START; - break; - case LIT: /* o: got literal, waiting for output space */ - NEEDOUT - OUTBYTE(c->sub.lit) - c->mode = START; - break; - case WASH: /* o: got eob, possibly more output */ - if (k > 7) /* return unused byte, if any */ - { - Assert(k < 16, "inflate_codes grabbed too many bytes") - k -= 8; - n++; - p--; /* can always return one */ - } - FLUSH - if (s->read != s->write) - LEAVE - c->mode = END; - /* fall through */ - case END: - r = Z_STREAM_END; - LEAVE - case BADCODE: /* x: got error */ - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -#ifdef NEED_DUMMY_RETURN - return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ -#endif -} - - -local void inflate_codes_free( /* c, z) */ -inflate_codes_statef *c, -z_streamp z ) -{ - ZFREE(z, c); - Tracev((stderr, "inflate: codes free\n")); -} diff --git a/lib/libesp32_lvgl/freetype/src/gzip/infcodes.h b/lib/libesp32_lvgl/freetype/src/gzip/infcodes.h deleted file mode 100644 index 154d7f896..000000000 --- a/lib/libesp32_lvgl/freetype/src/gzip/infcodes.h +++ /dev/null @@ -1,31 +0,0 @@ -/* infcodes.h -- header to use infcodes.c - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#ifndef _INFCODES_H -#define _INFCODES_H - -struct inflate_codes_state; -typedef struct inflate_codes_state FAR inflate_codes_statef; - -local inflate_codes_statef *inflate_codes_new OF(( - uInt, uInt, - inflate_huft *, inflate_huft *, - z_streamp )); - -local int inflate_codes OF(( - inflate_blocks_statef *, - z_streamp , - int)); - -local void inflate_codes_free OF(( - inflate_codes_statef *, - z_streamp )); - -#endif /* _INFCODES_H */ diff --git a/lib/libesp32_lvgl/freetype/src/gzip/inffast.c b/lib/libesp32_lvgl/freetype/src/gzip/inffast.c new file mode 100644 index 000000000..809737b13 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/gzip/inffast.c @@ -0,0 +1,323 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef ASMINF +# pragma message("Assembler code may have bugs -- use at your own risk") +#else + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast( + z_streamp strm, + unsigned start) +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code const *here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in; + last = in + (strm->avail_in - 5); + out = strm->next_out; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + here = lcode + (hold & lmask); + dolen: + op = (unsigned)(here->bits); + hold >>= op; + bits -= op; + op = (unsigned)(here->op); + if (op == 0) { /* literal */ + Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here->val)); + *out++ = (unsigned char)(here->val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here->val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + here = dcode + (hold & dmask); + dodist: + op = (unsigned)(here->bits); + hold >>= op; + bits -= op; + op = (unsigned)(here->op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here->val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + *out++ = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + *out++ = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + *out++ = *from++; + } while (--len); + continue; + } +#endif + } + from = window; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = window; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; + len -= 3; + } + if (len) { + *out++ = *from++; + if (len > 1) + *out++ = *from++; + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; + len -= 3; + } while (len > 2); + if (len) { + *out++ = *from++; + if (len > 1) + *out++ = *from++; + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode + here->val + (hold & ((1U << op) - 1)); + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode + here->val + (hold & ((1U << op) - 1)); + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in; + strm->next_out = out; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/lib/libesp32_lvgl/freetype/src/gzip/inffast.h b/lib/libesp32_lvgl/freetype/src/gzip/inffast.h new file mode 100644 index 000000000..684ae878c --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/gzip/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +static void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/lib/libesp32_lvgl/freetype/src/gzip/inffixed.h b/lib/libesp32_lvgl/freetype/src/gzip/inffixed.h index 4d4760ea0..d62832776 100644 --- a/lib/libesp32_lvgl/freetype/src/gzip/inffixed.h +++ b/lib/libesp32_lvgl/freetype/src/gzip/inffixed.h @@ -1,151 +1,94 @@ -/* inffixed.h -- table for decoding fixed codes - * Generated automatically by the maketree.c program - */ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ + /* WARNING: this file should *not* be used by applications. + It is part of the implementation of this library and is + subject to change. Applications should only use zlib.h. + */ -local const uInt fixed_bl = 9; -local const uInt fixed_bd = 5; -local const inflate_huft fixed_tl[] = { - {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, - {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, - {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, - {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, - {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, - {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, - {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, - {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, - {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, - {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, - {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, - {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, - {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, - {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, - {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, - {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, - {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, - {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, - {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, - {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, - {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, - {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, - {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, - {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, - {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, - {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, - {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, - {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, - {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, - {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, - {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, - {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, - {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, - {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, - {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, - {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, - {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, - {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, - {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, - {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, - {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, - {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, - {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, - {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, - {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, - {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, - {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, - {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, - {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, - {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, - {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, - {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, - {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, - {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, - {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, - {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, - {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, - {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, - {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, - {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, - {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, - {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, - {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, - {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, - {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, - {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, - {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, - {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, - {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, - {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, - {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, - {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, - {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, - {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, - {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, - {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, - {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, - {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, - {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, - {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, - {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, - {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, - {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, - {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, - {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, - {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, - {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, - {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, - {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, - {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, - {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, - {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, - {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, - {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, - {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, - {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, - {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, - {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, - {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, - {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, - {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, - {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, - {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, - {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, - {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, - {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, - {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, - {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, - {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, - {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, - {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, - {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, - {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, - {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, - {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, - {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, - {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, - {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, - {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, - {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, - {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, - {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, - {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, - {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} - }; -local const inflate_huft fixed_td[] = { - {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, - {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, - {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, - {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, - {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, - {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, - {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, - {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} - }; + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/lib/libesp32_lvgl/freetype/src/gzip/inflate.c b/lib/libesp32_lvgl/freetype/src/gzip/inflate.c index 95e265366..5117e2e26 100644 --- a/lib/libesp32_lvgl/freetype/src/gzip/inflate.c +++ b/lib/libesp32_lvgl/freetype/src/gzip/inflate.c @@ -1,283 +1,1605 @@ -/* inflate.c -- zlib interface to inflate modules - * Copyright (C) 1995-2002 Mark Adler +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + #include "zutil.h" -#include "infblock.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" -#define DONE INFLATE_DONE -#define BAD INFLATE_BAD +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif -typedef enum { - METHOD, /* waiting for method byte */ - FLAG, /* waiting for flag byte */ - DICT4, /* four dictionary check bytes to go */ - DICT3, /* three dictionary check bytes to go */ - DICT2, /* two dictionary check bytes to go */ - DICT1, /* one dictionary check byte to go */ - DICT0, /* waiting for inflateSetDictionary */ - BLOCKS, /* decompressing blocks */ - CHECK4, /* four check bytes to go */ - CHECK3, /* three check bytes to go */ - CHECK2, /* two check bytes to go */ - CHECK1, /* one check byte to go */ - DONE, /* finished check, done */ - BAD} /* got an error--stay here */ -inflate_mode; +/* function prototypes */ +local int inflateStateCheck OF((z_streamp strm)); +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + unsigned copy)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +#ifndef Z_FREETYPE +local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, + unsigned len)); +#endif -/* inflate private state */ -struct internal_state { - - /* mode */ - inflate_mode mode; /* current inflate mode */ - - /* mode dependent information */ - union { - uInt method; /* if FLAGS, method byte */ - struct { - uLong was; /* computed check value */ - uLong need; /* stream check value */ - } check; /* if CHECK, check values to compare */ - uInt marker; /* if BAD, inflateSync's marker bytes count */ - } sub; /* submode */ - - /* mode independent information */ - int nowrap; /* flag for no wrapper */ - uInt wbits; /* log2(window size) (8..15, defaults to 15) */ - inflate_blocks_statef - *blocks; /* current inflate_blocks state */ - -}; - - -ZEXPORT(int) inflateReset( /* z) */ -z_streamp z ) +local int inflateStateCheck( + z_streamp strm) { - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - z->total_in = z->total_out = 0; - z->msg = Z_NULL; - z->state->mode = z->state->nowrap ? BLOCKS : METHOD; - inflate_blocks_reset(z->state->blocks, z, Z_NULL); - Tracev((stderr, "inflate: reset\n")); - return Z_OK; + struct inflate_state FAR *state; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + state = (struct inflate_state FAR *)strm->state; + if (state == Z_NULL || state->strm != strm || + state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; } - -ZEXPORT(int) inflateEnd( /* z) */ -z_streamp z ) +int ZEXPORT inflateResetKeep( + z_streamp strm) { - if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->blocks != Z_NULL) - inflate_blocks_free(z->state->blocks, z); - ZFREE(z, z->state); - z->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->flags = -1; + state->dmax = 32768U; + state->head = Z_NULL; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; } - -ZEXPORT(int) inflateInit2_( /* z, w, version, stream_size) */ -z_streamp z, -int w, -const char *version, -int stream_size ) +int ZEXPORT inflateReset( + z_streamp strm) { - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != sizeof(z_stream)) - return Z_VERSION_ERROR; + struct inflate_state FAR *state; - /* initialize state */ - if (z == Z_NULL) - return Z_STREAM_ERROR; - z->msg = Z_NULL; - if (z->zalloc == Z_NULL) - { - z->zalloc = zcalloc; - z->opaque = (voidpf)0; - } - if (z->zfree == Z_NULL) z->zfree = zcfree; - if ((z->state = (struct internal_state FAR *) - ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) - return Z_MEM_ERROR; - z->state->blocks = Z_NULL; - - /* handle undocumented nowrap option (no zlib header or check) */ - z->state->nowrap = 0; - if (w < 0) - { - w = - w; - z->state->nowrap = 1; - } - - /* set window size */ - if (w < 8 || w > 15) - { - inflateEnd(z); - return Z_STREAM_ERROR; - } - z->state->wbits = (uInt)w; - - /* create inflate_blocks state */ - if ((z->state->blocks = - inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) - == Z_NULL) - { - inflateEnd(z); - return Z_MEM_ERROR; - } - Tracev((stderr, "inflate: allocated\n")); - - /* reset state */ - inflateReset(z); - return Z_OK; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return inflateResetKeep(strm); } - - -#undef NEEDBYTE -#define NEEDBYTE {if(z->avail_in==0)return r;r=f;} - -#undef NEXTBYTE -#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) - - -ZEXPORT(int) inflate( /* z, f) */ -z_streamp z, -int f ) +int ZEXPORT inflateReset2( + z_streamp strm, + int windowBits) { - int r; - uInt b; + int wrap; + struct inflate_state FAR *state; - if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) - return Z_STREAM_ERROR; - f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; - r = Z_BUF_ERROR; - while (1) switch (z->state->mode) - { - case METHOD: - NEEDBYTE - if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) - { - z->state->mode = BAD; - z->msg = (char*)"unknown compression method"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - if ((z->state->sub.method >> 4) + 8 > z->state->wbits) - { - z->state->mode = BAD; - z->msg = (char*)"invalid window size"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - z->state->mode = FLAG; - /* fall through */ - case FLAG: - NEEDBYTE - b = NEXTBYTE; - if (((z->state->sub.method << 8) + b) % 31) - { - z->state->mode = BAD; - z->msg = (char*)"incorrect header check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - Tracev((stderr, "inflate: zlib header ok\n")); - if (!(b & PRESET_DICT)) - { - z->state->mode = BLOCKS; - break; - } - z->state->mode = DICT4; - /* fall through */ - case DICT4: - NEEDBYTE - z->state->sub.check.need = (uLong)NEXTBYTE << 24; - z->state->mode = DICT3; - /* fall through */ - case DICT3: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 16; - z->state->mode = DICT2; - /* fall through */ - case DICT2: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 8; - z->state->mode = DICT1; - /* fall through */ - case DICT1: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE; - z->adler = z->state->sub.check.need; - z->state->mode = DICT0; - return Z_NEED_DICT; - case DICT0: - z->state->mode = BAD; - z->msg = (char*)"need dictionary"; - z->state->sub.marker = 0; /* can try inflateSync */ - return Z_STREAM_ERROR; - case BLOCKS: - r = inflate_blocks(z->state->blocks, z, r); - if (r == Z_DATA_ERROR) - { - z->state->mode = BAD; - z->state->sub.marker = 0; /* can try inflateSync */ - break; - } - if (r == Z_OK) - r = f; - if (r != Z_STREAM_END) - return r; - r = f; - inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); - if (z->state->nowrap) - { - z->state->mode = DONE; - break; - } - z->state->mode = CHECK4; - /* fall through */ - case CHECK4: - NEEDBYTE - z->state->sub.check.need = (uLong)NEXTBYTE << 24; - z->state->mode = CHECK3; - /* fall through */ - case CHECK3: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 16; - z->state->mode = CHECK2; - /* fall through */ - case CHECK2: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 8; - z->state->mode = CHECK1; - /* fall through */ - case CHECK1: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE; + /* get the state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; - if (z->state->sub.check.was != z->state->sub.check.need) - { - z->state->mode = BAD; - z->msg = (char*)"incorrect data check"; - z->state->sub.marker = 5; /* can't try inflateSync */ + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + if (windowBits < -15) + return Z_STREAM_ERROR; + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 5; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_( + z_streamp strm, + int windowBits, + const char *version, + int stream_size) +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->strm = strm; + state->window = Z_NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +#ifndef Z_FREETYPE + +int ZEXPORT inflateInit_( + z_streamp strm, + const char *version, + int stream_size) +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime( + z_streamp strm, + int bits, + int value) +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += (unsigned)value << state->bits; + state->bits += (uInt)bits; + return Z_OK; +} + +#endif /* !Z_FREETYPE */ + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables( + struct inflate_state FAR *state) +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, + state.lencode[low].bits, state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow( + z_streamp strm, + const Bytef *end, + unsigned copy) +{ + struct inflate_state FAR *state; + unsigned dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state->wsize) { + zmemcpy(state->window, end - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, end - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, end - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE_CHECK(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; break; - } - Tracev((stderr, "inflate: zlib check ok\n")); - z->state->mode = DONE; - /* fall through */ - case DONE: - return Z_STREAM_END; - case BAD: - return Z_DATA_ERROR; - default: - return Z_STREAM_ERROR; - } -#ifdef NEED_DUMMY_RETURN - return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate( + z_streamp strm, + int flush) +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (inflateStateCheck(strm) || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + if (state->wbits == 0) + state->wbits = 15; + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + if (len > 15 || len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + state->flags = 0; /* indicate zlib header */ + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + /* fallthrough */ + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + /* fallthrough */ + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + /* fallthrough */ + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + /* fallthrough */ + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL && + (len = state->head->extra_len - state->length) < + state->head->extra_max) { + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + /* fallthrough */ + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + /* fallthrough */ + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + /* fallthrough */ + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if ((state->wrap & 4) && hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = ZSWAP32(hold); + INITBITS(); + state->mode = DICT; + /* fallthrough */ + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + /* fallthrough */ + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + /* fallthrough */ + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + /* fallthrough */ + case COPY_: + state->mode = COPY; + /* fallthrough */ + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + /* fallthrough */ + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + /* fallthrough */ + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (const code FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + /* fallthrough */ + case LEN_: + state->mode = LEN; + /* fallthrough */ + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + /* fallthrough */ + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + /* fallthrough */ + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + /* fallthrough */ + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + /* fallthrough */ + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE_CHECK(state->check, put - out, out); + out = left; + if ((state->wrap & 4) && ( +#ifdef GUNZIP + state->flags ? hold : +#endif + ZSWAP32(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + /* fallthrough */ + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + /* fallthrough */ + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + /* fallthrough */ + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH))) + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE_CHECK(state->check, strm->next_out - out, out); + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd( + z_streamp strm) +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +#ifndef Z_FREETYPE + +int ZEXPORT inflateGetDictionary( + z_streamp strm, + Bytef *dictionary, + uInt *dictLength) +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, + state->whave - state->wnext); + zmemcpy(dictionary + state->whave - state->wnext, + state->window, state->wnext); + } + if (dictLength != Z_NULL) + *dictLength = state->whave; + return Z_OK; +} + +int ZEXPORT inflateSetDictionary( + z_streamp strm, + const Bytef *dictionary, + uInt dictLength) +{ + struct inflate_state FAR *state; + unsigned long dictid; + int ret; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary identifier */ + if (state->mode == DICT) { + dictid = adler32(0L, Z_NULL, 0); + dictid = adler32(dictid, dictionary, dictLength); + if (dictid != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength); + if (ret) { + state->mode = MEM; + return Z_MEM_ERROR; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader( + z_streamp strm, + gz_headerp head) +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch( + unsigned FAR *have, + const unsigned char FAR *buf, + unsigned len) +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync( + z_streamp strm) +{ + unsigned len; /* number of bytes to look at or looked at */ + int flags; /* temporary to save header status */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + if (state->flags == -1) + state->wrap = 0; /* if no header yet, treat as raw */ + else + state->wrap &= ~4; /* no point in computing a check value now */ + flags = state->flags; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->flags = flags; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint( + z_streamp strm) +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy( + z_streamp dest, + z_streamp source) +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (inflateStateCheck(source) || dest == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); + copy->strm = dest; + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine( + z_streamp strm, + int subvert) +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + state->sane = !subvert; + return Z_OK; +#else + (void)subvert; + state->sane = 1; + return Z_DATA_ERROR; #endif } +int ZEXPORT inflateValidate( + z_streamp strm, + int check) +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (check && state->wrap) + state->wrap |= 4; + else + state->wrap &= ~4; + return Z_OK; +} + +long ZEXPORT inflateMark( + z_streamp strm) +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) + return -(1L << 16); + state = (struct inflate_state FAR *)strm->state; + return (long)(((unsigned long)((long)state->back)) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} + +unsigned long ZEXPORT inflateCodesUsed( + z_streamp strm) +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) return (unsigned long)-1; + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); +} + +#endif /* !Z_FREETYPE */ diff --git a/lib/libesp32_lvgl/freetype/src/gzip/inflate.h b/lib/libesp32_lvgl/freetype/src/gzip/inflate.h new file mode 100644 index 000000000..c6f5a52e1 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/gzip/inflate.h @@ -0,0 +1,131 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2019 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef INFLATE_H +#define INFLATE_H + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD = 16180, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* State maintained between inflate() calls -- approximately 7K bytes, not + including the allocated sliding window, which is up to 32K bytes. */ +struct inflate_state { + z_streamp strm; /* pointer back to this zlib stream */ + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip, + bit 2 true to validate check value */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags, 0 if zlib, or + -1 if raw or no header yet */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; + +#endif /* INFLATE_H */ diff --git a/lib/libesp32_lvgl/freetype/src/gzip/inftrees.c b/lib/libesp32_lvgl/freetype/src/gzip/inftrees.c index 56f52b170..dd4965e9a 100644 --- a/lib/libesp32_lvgl/freetype/src/gzip/inftrees.c +++ b/lib/libesp32_lvgl/freetype/src/gzip/inftrees.c @@ -1,20 +1,15 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2002 Mark Adler + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" -#if !defined(BUILDFIXED) && !defined(STDC) -# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */ -#endif +#define MAXBITS 15 - -#if 0 -local const char inflate_copyright[] = - " inflate 1.1.4 Copyright 1995-2002 Mark Adler "; -#endif +static const char inflate_copyright[] = + " inflate 1.2.13 Copyright 1995-2022 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -22,447 +17,288 @@ local const char inflate_copyright[] = copyright string in the executable of your product. */ -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - - -local int huft_build OF(( - uIntf *, /* code lengths in bits */ - uInt, /* number of codes */ - uInt, /* number of "simple" codes */ - const uIntf *, /* list of base values for non-simple codes */ - const uIntf *, /* list of extra bits for non-simple codes */ - inflate_huft * FAR*,/* result: starting table */ - uIntf *, /* maximum lookup bits (returns actual) */ - inflate_huft *, /* space for trees */ - uInt *, /* hufts used in space */ - uIntf * )); /* space for values */ - -/* Tables for deflate from PKZIP's appnote.txt. */ -local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table( + codetype type, + unsigned short FAR *lens, + unsigned codes, + code FAR * FAR *table, + unsigned FAR *bits, + unsigned short FAR *work) +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + unsigned match; /* use base and extra for symbol >= match */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - /* see note #13 above about 258 */ -local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ -local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 194, 65}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; -local const uInt cpdext[30] = { /* Extra bits for distance codes */ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; -/* - Huffman code decoding is performed using a multi-level table lookup. - The fastest way to decode is to simply build a lookup table whose - size is determined by the longest code. However, the time it takes - to build this table can also be a factor if the data being decoded - is not very long. The most common codes are necessarily the - shortest codes, so those codes dominate the decoding time, and hence - the speed. The idea is you can have a shorter table that decodes the - shorter, more probable codes, and then point to subsidiary tables for - the longer codes. The time it costs to decode the longer codes is - then traded against the time it takes to make longer tables. + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. - This results of this trade are in the variables lbits and dbits - below. lbits is the number of bits the first level table for literal/ - length codes can decode in one step, and dbits is the same thing for - the distance codes. Subsequent tables are also less than or equal to - those sizes. These values may be adjusted either when all of the - codes are shorter than that, in which case the longest code length in - bits is used, or when the shortest code is *longer* than the requested - table size, in which case the length of the shortest code in bits is - used. + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. - There are two different values for the two tables, since they code a - different number of possibilities each. The literal/length table - codes 286 possible values, or in a flat code, a little over eight - bits. The distance table codes 30 possible values, or a little less - than five bits, flat. The optimum values for speed end up being - about one bit more than those, so lbits is 8+1 and dbits is 5+1. - The optimum values may differ though from machine to machine, and - possibly even between compilers. Your mileage may vary. - */ + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ -/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ -#define BMAX 15 /* maximum bit length of any code */ + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; -local int huft_build( /* b, n, s, d, e, t, m, hp, hn, v) */ -uIntf *b, /* code lengths in bits (all assumed <= BMAX) */ -uInt n, /* number of codes (assumed <= 288) */ -uInt s, /* number of simple-valued codes (0..s-1) */ -const uIntf *d, /* list of base values for non-simple codes */ -const uIntf *e, /* list of extra bits for non-simple codes */ -inflate_huft * FAR *t, /* result: starting table */ -uIntf *m, /* maximum lookup bits, returns actual */ -inflate_huft *hp, /* space for trees */ -uInt *hn, /* hufts used in space */ -uIntf *v /* working area: values in order of bit length */ -/* Given a list of code lengths and a maximum table size, make a set of - tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR - if the given code set is incomplete (the tables are still built in this - case), or Z_DATA_ERROR if the input is invalid. */ -) -{ + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; - uInt a; /* counter for codes of length k */ - uInt c[BMAX+1]; /* bit length count table */ - uInt f; /* i repeats in table every f entries */ - int g; /* maximum code length */ - int h; /* table level */ - uInt i; /* counter, current code */ - uInt j; /* counter */ - int k; /* number of bits in current code */ - int l; /* bits per table (returned in m) */ - uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ - uIntf *p; /* pointer into c[], b[], or v[] */ - inflate_huft *q; /* points to current table */ - struct inflate_huft_s r; /* table entry for structure assignment */ - inflate_huft *u[BMAX]; /* table stack */ - int w; /* bits before this table == (l * h) */ - uInt x[BMAX+1]; /* bit offsets, then code stack */ - uIntf *xp; /* pointer into x */ - int y; /* number of dummy codes added */ - uInt z; /* number of entries in current table */ + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; - /* Make compiler happy */ - r.base = 0; + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; - /* Generate counts for each bit length */ - p = c; -#define C0 *p++ = 0; -#define C2 C0 C0 C0 C0 -#define C4 C2 C2 C2 C2 - C4 /* clear c[]--assume BMAX+1 is 16 */ - p = b; i = n; - do { - c[*p++]++; /* assume all entries <= BMAX */ - } while (--i); - if (c[0] == n) /* null input--all zero length codes */ - { - *t = (inflate_huft *)Z_NULL; - *m = 0; - return Z_OK; - } + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. - /* Find minimum and maximum length, bound *m by those */ - l = *m; - for (j = 1; j <= BMAX; j++) - if (c[j]) - break; - k = j; /* minimum code length */ - if ((uInt)l < j) - l = j; - for (i = BMAX; i; i--) - if (c[i]) - break; - g = i; /* maximum code length */ - if ((uInt)l > i) - l = i; - *m = l; + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. - /* Adjust last length count to fill out codes, if needed */ - for (y = 1 << j; j < i; j++, y <<= 1) - if ((y -= c[j]) < 0) - return Z_DATA_ERROR; - if ((y -= c[i]) < 0) - return Z_DATA_ERROR; - c[i] += y; + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + match = 20; + break; + case LENS: + base = lbase; + extra = lext; + match = 257; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + match = 0; + } - /* Generate starting offsets into the value table for each length */ - x[1] = j = 0; - p = c + 1; xp = x + 2; - while (--i) { /* note that i == g from above */ - *xp++ = (j += *p++); - } + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + /* check available table space */ + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; - /* Make a table of values in order of bit lengths */ - p = b; i = 0; - do { - if ((j = *p++) != 0) - v[x[j]++] = i; - } while (++i < n); - n = x[g]; /* set n to length of v */ - - - /* Generate the Huffman codes and for each, make the table entries */ - x[0] = i = 0; /* first Huffman code is zero */ - p = v; /* grab values in bit order */ - h = -1; /* no tables yet--level -1 */ - w = -l; /* bits decoded == (l * h) */ - u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ - q = (inflate_huft *)Z_NULL; /* ditto */ - z = 0; /* ditto */ - - /* go through the bit lengths (k already is bits in shortest code) */ - for (; k <= g; k++) - { - a = c[k]; - while (a--) - { - /* here i is the Huffman code of length k bits for value *p */ - /* make tables up to required level */ - while (k > w + l) - { - h++; - w += l; /* previous table always l bits */ - - /* compute minimum size table less than or equal to l bits */ - z = g - w; - z = z > (uInt)l ? (uInt)l : z; /* table size upper limit */ - if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ - { /* too few codes for k-w bit table */ - f -= a + 1; /* deduct codes from patterns left */ - xp = c + k; - if (j < z) - while (++j < z) /* try smaller tables up to z bits */ - { - if ((f <<= 1) <= *++xp) - break; /* enough codes to use up j bits */ - f -= *xp; /* else deduct codes from patterns */ - } + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if (work[sym] + 1U < match) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if (work[sym] >= match) { + here.op = (unsigned char)(extra[work[sym] - match]); + here.val = base[work[sym] - match]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; } - z = 1 << j; /* table entries for j-bit table */ - /* allocate new table */ - if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ - return Z_DATA_ERROR; /* overflow of MANY */ - u[h] = q = hp + *hn; - *hn += z; + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); - /* connect to last table, if there is one */ - if (h) - { - x[h] = i; /* save pattern for backing up */ - r.bits = (Byte)l; /* bits to dump before this table */ - r.exop = (Byte)j; /* bits in this table */ - j = i >> (w - l); - r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ - u[h-1][j] = r; /* connect to last table */ + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; } else - *t = q; /* first table is returned result */ - } + huff = 0; - /* set up table entry in r */ - r.bits = (Byte)(k - w); - if (p >= v + n) - r.exop = 128 + 64; /* out of values--invalid code */ - else if (*p < s) - { - r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ - r.base = *p++; /* simple code is just the value */ - } - else - { - r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ - r.base = d[*p++ - s]; - } + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } - /* fill code-like entries with r */ - f = 1 << (k - w); - for (j = i >> w; j < z; j += f) - q[j] = r; + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; - /* backwards increment the k-bit code i */ - for (j = 1 << (k - 1); i & j; j >>= 1) - i ^= j; - i ^= j; + /* increment past last table */ + next += min; /* here min is 1 << curr */ - /* backup over finished tables */ - mask = (1 << w) - 1; /* needed on HP, cc -O bug */ - while ((i & mask) != x[h]) - { - h--; /* don't need to update q */ - w -= l; - mask = (1 << w) - 1; - } + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } } - } + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff != 0) { + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + next[huff] = here; + } - /* Return Z_BUF_ERROR if we were given an incomplete table */ - return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; -} - - -local int inflate_trees_bits( /* c, bb, tb, hp, z) */ -uIntf *c, /* 19 code lengths */ -uIntf *bb, /* bits tree desired/actual depth */ -inflate_huft * FAR *tb, /* bits tree result */ -inflate_huft *hp, /* space for trees */ -z_streamp z /* for messages */ -) -{ - int r; - uInt hn = 0; /* hufts used in space */ - uIntf *v; /* work area for huft_build */ - - if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, - tb, bb, hp, &hn, v); - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed dynamic bit lengths tree"; - else if (r == Z_BUF_ERROR || *bb == 0) - { - z->msg = (char*)"incomplete dynamic bit lengths tree"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; -} - - -local int inflate_trees_dynamic( /* nl, nd, c, bl, bd, tl, td, hp, z) */ -uInt nl, /* number of literal/length codes */ -uInt nd, /* number of distance codes */ -uIntf *c, /* that many (total) code lengths */ -uIntf *bl, /* literal desired/actual bit depth */ -uIntf *bd, /* distance desired/actual bit depth */ -inflate_huft * FAR *tl, /* literal/length tree result */ -inflate_huft * FAR *td, /* distance tree result */ -inflate_huft *hp, /* space for trees */ -z_streamp z /* for messages */ -) -{ - int r; - uInt hn = 0; /* hufts used in space */ - uIntf *v; /* work area for huft_build */ - - /* allocate work area */ - if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - - /* build literal/length tree */ - r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); - if (r != Z_OK || *bl == 0) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed literal/length tree"; - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"incomplete literal/length tree"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; - } - - /* build distance tree */ - r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); - if (r != Z_OK || (*bd == 0 && nl > 257)) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed distance tree"; - else if (r == Z_BUF_ERROR) { -#if 0 - { -#endif -#ifdef PKZIP_BUG_WORKAROUND - r = Z_OK; - } -#else - z->msg = (char*)"incomplete distance tree"; - r = Z_DATA_ERROR; - } - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"empty distance tree with lengths"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; -#endif - } - - /* done */ - ZFREE(z, v); - return Z_OK; -} - - -/* build fixed tables only once--keep them here */ -#ifdef BUILDFIXED -local int fixed_built = 0; -#define FIXEDH 544 /* number of hufts used by fixed tables */ -local inflate_huft fixed_mem[FIXEDH]; -local uInt fixed_bl; -local uInt fixed_bd; -local inflate_huft *fixed_tl; -local inflate_huft *fixed_td; -#else -#include "inffixed.h" -#endif - - -local int inflate_trees_fixed( /* bl, bd, tl, td, z) */ -uIntf *bl, /* literal desired/actual bit depth */ -uIntf *bd, /* distance desired/actual bit depth */ -const inflate_huft * FAR *tl, /* literal/length tree result */ -const inflate_huft * FAR *td, /* distance tree result */ -z_streamp z /* for memory allocation */ -) -{ -#ifdef BUILDFIXED - /* build fixed tables if not already */ - if (!fixed_built) - { - int k; /* temporary variable */ - uInt f = 0; /* number of hufts used in fixed_mem */ - uIntf *c; /* length list for huft_build */ - uIntf *v; /* work area for huft_build */ - - /* allocate memory */ - if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) - { - ZFREE(z, c); - return Z_MEM_ERROR; - } - - /* literal table */ - for (k = 0; k < 144; k++) - c[k] = 8; - for (; k < 256; k++) - c[k] = 9; - for (; k < 280; k++) - c[k] = 7; - for (; k < 288; k++) - c[k] = 8; - fixed_bl = 9; - huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, - fixed_mem, &f, v); - - /* distance table */ - for (k = 0; k < 30; k++) - c[k] = 5; - fixed_bd = 5; - huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, - fixed_mem, &f, v); - - /* done */ - ZFREE(z, v); - ZFREE(z, c); - fixed_built = 1; - } -#else - FT_UNUSED(z); -#endif - *bl = fixed_bl; - *bd = fixed_bd; - *tl = fixed_tl; - *td = fixed_td; - return Z_OK; + /* set return parameters */ + *table += used; + *bits = root; + return 0; } diff --git a/lib/libesp32_lvgl/freetype/src/gzip/inftrees.h b/lib/libesp32_lvgl/freetype/src/gzip/inftrees.h index 07bf2aa0b..a2207efb1 100644 --- a/lib/libesp32_lvgl/freetype/src/gzip/inftrees.h +++ b/lib/libesp32_lvgl/freetype/src/gzip/inftrees.h @@ -1,63 +1,67 @@ /* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2002 Mark Adler + * Copyright (C) 1995-2005, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ +#ifndef INFTREES_H +#define INFTREES_H + /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ -/* Huffman code lookup table entry--this entry is four bytes for machines - that have 16-bit pointers (e.g. PC's in the small or medium model). */ +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; -#ifndef _INFTREES_H -#define _INFTREES_H +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ -typedef struct inflate_huft_s FAR inflate_huft; +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) -struct inflate_huft_s { - union { - struct { - Byte Exop; /* number of extra bits or operation */ - Byte Bits; /* number of bits in this code or subcode */ - } what; - uInt pad; /* pad structure to a power of 2 (4 bytes for */ - } word; /* 16-bit, 8 bytes for 32-bit int's) */ - uInt base; /* literal, length base, distance base, - or table offset */ -}; +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; -/* Maximum size of dynamic tree. The maximum found in a long but non- - exhaustive search was 1004 huft structures (850 for length/literals - and 154 for distances, the latter actually the result of an - exhaustive search). The actual maximum is not known, but the - value below is more than safe. */ -#define MANY 1440 +static int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); -local int inflate_trees_bits OF(( - uIntf *, /* 19 code lengths */ - uIntf *, /* bits tree desired/actual depth */ - inflate_huft * FAR *, /* bits tree result */ - inflate_huft *, /* space for trees */ - z_streamp)); /* for messages */ - -local int inflate_trees_dynamic OF(( - uInt, /* number of literal/length codes */ - uInt, /* number of distance codes */ - uIntf *, /* that many (total) code lengths */ - uIntf *, /* literal desired/actual bit depth */ - uIntf *, /* distance desired/actual bit depth */ - inflate_huft * FAR *, /* literal/length tree result */ - inflate_huft * FAR *, /* distance tree result */ - inflate_huft *, /* space for trees */ - z_streamp)); /* for messages */ - -local int inflate_trees_fixed OF(( - uIntf *, /* literal desired/actual bit depth */ - uIntf *, /* distance desired/actual bit depth */ - const inflate_huft * FAR *, /* literal/length tree result */ - const inflate_huft * FAR *, /* distance tree result */ - z_streamp)); /* for memory allocation */ - -#endif /* _INFTREES_H */ +#endif /* INFTREES_H_ */ diff --git a/lib/libesp32_lvgl/freetype/src/gzip/infutil.c b/lib/libesp32_lvgl/freetype/src/gzip/infutil.c deleted file mode 100644 index 6087b4064..000000000 --- a/lib/libesp32_lvgl/freetype/src/gzip/infutil.c +++ /dev/null @@ -1,86 +0,0 @@ -/* inflate_util.c -- data and routines common to blocks and codes - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "infblock.h" -#include "inftrees.h" -#include "infcodes.h" -#include "infutil.h" - - -/* And'ing with mask[n] masks the lower n bits */ -local const uInt inflate_mask[17] = { - 0x0000, - 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -}; - - -/* copy as much as possible from the sliding window to the output area */ -local int inflate_flush( /* s, z, r) */ -inflate_blocks_statef *s, -z_streamp z, -int r ) -{ - uInt n; - Bytef *p; - Bytef *q; - - /* local copies of source and destination pointers */ - p = z->next_out; - q = s->read; - - /* compute number of bytes to copy as far as end of window */ - n = (uInt)((q <= s->write ? s->write : s->end) - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy as far as end of window */ - zmemcpy(p, q, n); - p += n; - q += n; - - /* see if more to copy at beginning of window */ - if (q == s->end) - { - /* wrap pointers */ - q = s->window; - if (s->write == s->end) - s->write = s->window; - - /* compute bytes to copy */ - n = (uInt)(s->write - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy */ - zmemcpy(p, q, n); - p += n; - q += n; - } - - /* update pointers */ - z->next_out = p; - s->read = q; - - /* done */ - return r; -} diff --git a/lib/libesp32_lvgl/freetype/src/gzip/infutil.h b/lib/libesp32_lvgl/freetype/src/gzip/infutil.h deleted file mode 100644 index cdf18b4f9..000000000 --- a/lib/libesp32_lvgl/freetype/src/gzip/infutil.h +++ /dev/null @@ -1,98 +0,0 @@ -/* infutil.h -- types and macros common to blocks and codes - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#ifndef _INFUTIL_H -#define _INFUTIL_H - -typedef enum { - TYPE, /* get type bits (3, including end bit) */ - LENS, /* get lengths for stored */ - STORED, /* processing stored block */ - TABLE, /* get table lengths */ - BTREE, /* get bit lengths tree for a dynamic block */ - DTREE, /* get length, distance trees for a dynamic block */ - CODES, /* processing fixed or dynamic block */ - DRY, /* output remaining window bytes */ - DONE, /* finished last block, done */ - BAD} /* got a data error--stuck here */ -inflate_block_mode; - -/* inflate blocks semi-private state */ -struct inflate_blocks_state { - - /* mode */ - inflate_block_mode mode; /* current inflate_block mode */ - - /* mode dependent information */ - union { - uInt left; /* if STORED, bytes left to copy */ - struct { - uInt table; /* table lengths (14 bits) */ - uInt index; /* index into blens (or border) */ - uIntf *blens; /* bit lengths of codes */ - uInt bb; /* bit length tree depth */ - inflate_huft *tb; /* bit length decoding tree */ - } trees; /* if DTREE, decoding info for trees */ - struct { - inflate_codes_statef - *codes; - } decode; /* if CODES, current state */ - } sub; /* submode */ - uInt last; /* true if this block is the last block */ - - /* mode independent information */ - uInt bitk; /* bits in bit buffer */ - uLong bitb; /* bit buffer */ - inflate_huft *hufts; /* single malloc for tree space */ - Bytef *window; /* sliding window */ - Bytef *end; /* one byte after sliding window */ - Bytef *read; /* window read pointer */ - Bytef *write; /* window write pointer */ - check_func checkfn; /* check function */ - uLong check; /* check on output */ - -}; - - -/* defines for inflate input/output */ -/* update pointers and return */ -#define UPDBITS {s->bitb=b;s->bitk=k;} -#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} -#define UPDOUT {s->write=q;} -#define UPDATE {UPDBITS UPDIN UPDOUT} -#define LEAVE {UPDATE return inflate_flush(s,z,r);} -/* get bytes and bits */ -#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} -#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} -#define NEXTBYTE (n--,*p++) -#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} -/* output bytes */ -#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) -#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} -#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} -#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} -#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} -#define OUTBYTE(a) {*q++=(Byte)(a);m--;} -/* load local pointers */ -#define LOAD {LOADIN LOADOUT} - -/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ -#ifndef NO_INFLATE_MASK -local const uInt inflate_mask[17]; -#endif - -/* copy as much as possible from the sliding window to the output area */ -local int inflate_flush OF(( - inflate_blocks_statef *, - z_streamp , - int)); - -#endif diff --git a/lib/libesp32_lvgl/freetype/src/gzip/patches/freetype-zlib.diff b/lib/libesp32_lvgl/freetype/src/gzip/patches/freetype-zlib.diff new file mode 100644 index 000000000..6ac76df62 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/gzip/patches/freetype-zlib.diff @@ -0,0 +1,469 @@ +[zlib] Fix zlib sources for compilation with FreeType + +We must ensure that they do not issue compiler errors or warnings when they +are compiled as part of `src/gzip/ftgzip.c`. + +* src/gzip/gzguts.h (COPY): Rename to... +(COPY__): ... this since `COPY` and `COPY_` conflict with enum values, +which have the same name in `zlib.h`. + +* src/gzip/inflate.c, src/gzip/adler32.c, src/gzip/crc32.c, +src/gzip/zutil.c: Omit unused function declarations and definitions when +`Z_FREETYPE` is defined. + +* src/gzip/inffast.h (inflate_fast): Declare as static. + +* src/gzip/inftrees.c (inflate_copyright): Declare as static. + +* src/gzip/zlib.h: Include `ftzconf.h` instead of `zconf.h` to avoid +conflicts with system-installed headers. +Omit unused function declarations when `Z_FREETYPE` is defined. +(inflateInit2)[Z_FREETYPE]: Provide proper declaration. + +* src/gzip/zutil.h: Use `ft_memxxx` functions instead of `memxxx`. +Omit unused function declarations when `Z_FREETYPE` is defined. + +* src/gzip/inflate.h, src/gzip/inftrees.h: Add header guard macros to +prevent compiler errors. + +* src/gzip/inftrees.h: Add header guard macros to prevent compiler errors. +(inflate_table): Declare as static. + +diff --git b/src/gzip/adler32.c a/src/gzip/adler32.c +index be5e8a247..aa032e1dd 100644 +--- b/src/gzip/adler32.c ++++ a/src/gzip/adler32.c +@@ -7,7 +7,9 @@ + + #include "zutil.h" + ++#ifndef Z_FREETYPE + local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); ++#endif + + #define BASE 65521U /* largest prime smaller than 65536 */ + #define NMAX 5552 +@@ -139,6 +141,8 @@ uLong ZEXPORT adler32( + return adler32_z(adler, buf, len); + } + ++#ifndef Z_FREETYPE ++ + /* ========================================================================= */ + local uLong adler32_combine_( + uLong adler1, +@@ -184,3 +188,5 @@ uLong ZEXPORT adler32_combine64( + { + return adler32_combine_(adler1, adler2, len2); + } ++ ++#endif /* !Z_FREETYPE */ +diff --git b/src/gzip/crc32.c a/src/gzip/crc32.c +index 3a52aa89d..6cd1b09d5 100644 +--- b/src/gzip/crc32.c ++++ a/src/gzip/crc32.c +@@ -103,9 +103,11 @@ + # define ARMCRC32 + #endif + ++#ifndef Z_FREETYPE + /* Local functions. */ + local z_crc_t multmodp OF((z_crc_t a, z_crc_t b)); + local z_crc_t x2nmodp OF((z_off64_t n, unsigned k)); ++#endif /* Z_FREETYPE */ + + #if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) + local z_word_t byte_swap OF((z_word_t word)); +@@ -544,6 +546,8 @@ local void braid(ltl, big, n, w) + * generation above. + */ + ++#ifndef Z_FREETYPE ++ + /* + Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial, + reflected. For speed, this requires that a not be zero. +@@ -600,6 +604,8 @@ const z_crc_t FAR * ZEXPORT get_crc_table() + return (const z_crc_t FAR *)crc_table; + } + ++#endif /* Z_FREETYPE */ ++ + /* ========================================================================= + * Use ARM machine instructions if available. This will compute the CRC about + * ten times faster than the braided calculation. This code does not check for +@@ -1077,6 +1083,8 @@ unsigned long ZEXPORT crc32( + return crc32_z(crc, buf, len); + } + ++#ifndef Z_FREETYPE ++ + /* ========================================================================= */ + uLong ZEXPORT crc32_combine64( + uLong crc1, +@@ -1123,3 +1131,5 @@ uLong ZEXPORT crc32_combine_op( + { + return multmodp(op, crc1) ^ (crc2 & 0xffffffff); + } ++ ++#endif /* Z_FREETYPE */ +diff --git b/src/gzip/gzguts.h a/src/gzip/gzguts.h +index 57faf3716..4f09a52a7 100644 +--- b/src/gzip/gzguts.h ++++ a/src/gzip/gzguts.h +@@ -163,7 +163,7 @@ + + /* values for gz_state how */ + #define LOOK 0 /* look for a gzip header */ +-#define COPY 1 /* copy input directly */ ++#define COPY__ 1 /* copy input directly */ + #define GZIP 2 /* decompress a gzip stream */ + + /* internal gzip file state data structure */ +diff --git b/src/gzip/inffast.h a/src/gzip/inffast.h +index e5c1aa4ca..684ae878c 100644 +--- b/src/gzip/inffast.h ++++ a/src/gzip/inffast.h +@@ -8,4 +8,4 @@ + subject to change. Applications should only use zlib.h. + */ + +-void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); ++static void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); +diff --git b/src/gzip/inflate.c a/src/gzip/inflate.c +index c9e566b03..5117e2e26 100644 +--- b/src/gzip/inflate.c ++++ a/src/gzip/inflate.c +@@ -99,8 +99,10 @@ local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + #ifdef BUILDFIXED + void makefixed OF((void)); + #endif ++#ifndef Z_FREETYPE + local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, + unsigned len)); ++#endif + + local int inflateStateCheck( + z_streamp strm) +@@ -239,6 +241,8 @@ int ZEXPORT inflateInit2_( + return ret; + } + ++#ifndef Z_FREETYPE ++ + int ZEXPORT inflateInit_( + z_streamp strm, + const char *version, +@@ -268,6 +272,8 @@ int ZEXPORT inflatePrime( + return Z_OK; + } + ++#endif /* !Z_FREETYPE */ ++ + /* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. +@@ -1315,6 +1321,8 @@ int ZEXPORT inflateEnd( + return Z_OK; + } + ++#ifndef Z_FREETYPE ++ + int ZEXPORT inflateGetDictionary( + z_streamp strm, + Bytef *dictionary, +@@ -1593,3 +1601,5 @@ unsigned long ZEXPORT inflateCodesUsed( + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); + } ++ ++#endif /* !Z_FREETYPE */ +diff --git b/src/gzip/inflate.h a/src/gzip/inflate.h +index f127b6b1f..c6f5a52e1 100644 +--- b/src/gzip/inflate.h ++++ a/src/gzip/inflate.h +@@ -3,6 +3,9 @@ + * For conditions of distribution and use, see copyright notice in zlib.h + */ + ++#ifndef INFLATE_H ++#define INFLATE_H ++ + /* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. +@@ -124,3 +127,5 @@ struct inflate_state { + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ + }; ++ ++#endif /* INFLATE_H */ +diff --git b/src/gzip/inftrees.c a/src/gzip/inftrees.c +index d8405a24c..dd4965e9a 100644 +--- b/src/gzip/inftrees.c ++++ a/src/gzip/inftrees.c +@@ -8,7 +8,7 @@ + + #define MAXBITS 15 + +-const char inflate_copyright[] = ++static const char inflate_copyright[] = + " inflate 1.2.13 Copyright 1995-2022 Mark Adler "; + /* + If you use the zlib library in a product, an acknowledgment is welcome +diff --git b/src/gzip/inftrees.h a/src/gzip/inftrees.h +index f53665311..a2207efb1 100644 +--- b/src/gzip/inftrees.h ++++ a/src/gzip/inftrees.h +@@ -3,6 +3,9 @@ + * For conditions of distribution and use, see copyright notice in zlib.h + */ + ++#ifndef INFTREES_H ++#define INFTREES_H ++ + /* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. +@@ -57,6 +60,8 @@ typedef enum { + DISTS + } codetype; + +-int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, ++static int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); ++ ++#endif /* INFTREES_H_ */ +diff --git b/src/gzip/zlib.h a/src/gzip/zlib.h +index 953cb5012..3f2f76e3c 100644 +--- b/src/gzip/zlib.h ++++ a/src/gzip/zlib.h +@@ -31,7 +31,7 @@ + #ifndef ZLIB_H + #define ZLIB_H + +-#include "zconf.h" ++#include "ftzconf.h" + + #ifdef __cplusplus + extern "C" { +@@ -211,6 +211,8 @@ typedef gz_header FAR *gz_headerp; + + #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + ++#ifndef Z_FREETYPE ++ + #define zlib_version zlibVersion() + /* for compatibility with versions < 1.0.2 */ + +@@ -373,6 +375,7 @@ ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); + deallocated). + */ + ++#endif /* !Z_FREETYPE */ + + /* + ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); +@@ -534,6 +537,8 @@ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); + The following functions are needed only in some special applications. + */ + ++#ifndef Z_FREETYPE ++ + /* + ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, +@@ -956,6 +961,8 @@ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + destination. + */ + ++#endif /* !Z_FREETYPE */ ++ + ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); + /* + This function is equivalent to inflateEnd followed by inflateInit, +@@ -980,6 +987,8 @@ ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + the windowBits parameter is invalid. + */ + ++#ifndef Z_FREETYPE ++ + ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +@@ -1069,6 +1078,8 @@ ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + stream state was inconsistent. + */ + ++#endif /* !Z_FREETYPE */ ++ + /* + ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); +@@ -1095,6 +1106,8 @@ typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); + typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + ++#ifndef Z_FREETYPE ++ + ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +@@ -1214,6 +1227,8 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); + 27-31: 0 (reserved) + */ + ++#endif /* !Z_FREETYPE */ ++ + #ifndef Z_SOLO + + /* utility functions */ +@@ -1765,6 +1780,8 @@ ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2)); + crc32_combine_op(). + */ + ++#ifndef Z_FREETYPE ++ + ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op)); + /* + Give the same result as crc32_combine(), using op in place of len2. op is +@@ -1822,6 +1839,19 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + ZLIB_VERSION, (int)sizeof(z_stream)) + #endif + ++#else /* Z_FREETYPE */ ++ ++ ++ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, ++ const char *version, int stream_size)); ++ ++# define inflateInit2(strm, windowBits) \ ++ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ ++ (int)sizeof(z_stream)) ++ ++#endif /* Z_FREETYPE */ ++ ++ + #ifndef Z_SOLO + + /* gzgetc() macro and its supporting function and exposed data structure. Note +@@ -1901,20 +1931,25 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ + + #else /* Z_SOLO */ + ++#ifndef Z_FREETYPE + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); ++#endif + + #endif /* !Z_SOLO */ + + /* undocumented functions */ ++#ifndef Z_FREETYPE + ZEXTERN const char * ZEXPORT zError OF((int)); + ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); + ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); + ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); + ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); + ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF((z_streamp)); ++#endif /* !Z_FREETYPE */ + ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); ++#ifndef Z_FREETYPE + ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); + #if defined(_WIN32) && !defined(Z_SOLO) + ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, +@@ -1927,6 +1962,7 @@ ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + va_list va)); + # endif + #endif ++#endif /* !Z_FREETYPE */ + + #ifdef __cplusplus + } +diff --git b/src/gzip/zutil.c a/src/gzip/zutil.c +index ef174ca64..542706ca0 100644 +--- b/src/gzip/zutil.c ++++ a/src/gzip/zutil.c +@@ -10,6 +10,8 @@ + # include "gzguts.h" + #endif + ++#ifndef Z_FREETYPE ++ + z_const char * const z_errmsg[10] = { + (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ + (z_const char *)"stream end", /* Z_STREAM_END 1 */ +@@ -138,6 +140,8 @@ const char * ZEXPORT zError( + return ERR_MSG(err); + } + ++#endif /* !Z_FREETYPE */ ++ + #if defined(_WIN32_WCE) && _WIN32_WCE < 0x800 + /* The older Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. +@@ -159,6 +163,8 @@ void ZLIB_INTERNAL zmemcpy( + } while (--len != 0); + } + ++#ifndef Z_FREETYPE ++ + int ZLIB_INTERNAL zmemcmp( + const Bytef* s1, + const Bytef* s2, +@@ -181,6 +187,7 @@ void ZLIB_INTERNAL zmemzero( + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); + } ++#endif /* !Z_FREETYPE */ + #endif + + #ifndef Z_SOLO +diff --git b/src/gzip/zutil.h a/src/gzip/zutil.h +index 0bc7f4ecd..055ba8b62 100644 +--- b/src/gzip/zutil.h ++++ a/src/gzip/zutil.h +@@ -53,8 +53,10 @@ typedef unsigned long ulg; + # endif + #endif + ++#ifndef Z_FREETYPE + extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ + /* (size given to avoid silly warnings with Visual C++) */ ++#endif /* !Z_FREETYPE */ + + #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +@@ -188,6 +190,8 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ + #pragma warn -8066 + #endif + ++#ifndef Z_FREETYPE ++ + /* provide prototypes for these when building zlib without LFS */ + #if !defined(_WIN32) && \ + (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) +@@ -196,6 +200,8 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ + ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t)); + #endif + ++#endif /* !Z_FREETYPE */ ++ + /* common defaults */ + + #ifndef OS_CODE +@@ -227,9 +233,9 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ + # define zmemcmp _fmemcmp + # define zmemzero(dest, len) _fmemset(dest, 0, len) + # else +-# define zmemcpy memcpy +-# define zmemcmp memcmp +-# define zmemzero(dest, len) memset(dest, 0, len) ++# define zmemcpy ft_memcpy ++# define zmemcmp ft_memcmp ++# define zmemzero(dest, len) ft_memset(dest, 0, len) + # endif + #else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); diff --git a/lib/libesp32_lvgl/freetype/src/gzip/rules.mk b/lib/libesp32_lvgl/freetype/src/gzip/rules.mk index 4ea823f8d..c76eacb1a 100644 --- a/lib/libesp32_lvgl/freetype/src/gzip/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/gzip/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 2002-2020 by +# Copyright (C) 2002-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, @@ -36,25 +36,23 @@ endif # # All source and header files get loaded by `ftgzip.c' only if SYSTEM_ZLIB # is not defined (regardless whether we have a `single' or a `multi' build). -# However, it doesn't harm if we add everything as a dependency -# unconditionally. # -GZIP_DRV_SRCS := $(GZIP_DIR)/adler32.c \ - $(GZIP_DIR)/ftzconf.h \ - $(GZIP_DIR)/infblock.c \ - $(GZIP_DIR)/infblock.h \ - $(GZIP_DIR)/infcodes.c \ - $(GZIP_DIR)/infcodes.h \ - $(GZIP_DIR)/inffixed.h \ - $(GZIP_DIR)/inflate.c \ - $(GZIP_DIR)/inftrees.c \ - $(GZIP_DIR)/inftrees.h \ - $(GZIP_DIR)/infutil.c \ - $(GZIP_DIR)/infutil.h \ - $(GZIP_DIR)/zlib.h \ - $(GZIP_DIR)/zutil.c \ - $(GZIP_DIR)/zutil.h - +ifeq ($(SYSTEM_ZLIB),) + GZIP_DRV_SRCS := $(GZIP_DIR)/adler32.c \ + $(GZIP_DIR)/crc32.c \ + $(GZIP_DIR)/crc32.h \ + $(GZIP_DIR)/ftzconf.h \ + $(GZIP_DIR)/inffast.c \ + $(GZIP_DIR)/inffast.h \ + $(GZIP_DIR)/inffixed.h \ + $(GZIP_DIR)/inflate.c \ + $(GZIP_DIR)/inflate.h \ + $(GZIP_DIR)/inftrees.c \ + $(GZIP_DIR)/inftrees.h \ + $(GZIP_DIR)/zlib.h \ + $(GZIP_DIR)/zutil.c \ + $(GZIP_DIR)/zutil.h +endif # gzip driver object(s) # diff --git a/lib/libesp32_lvgl/freetype/src/gzip/zlib.h b/lib/libesp32_lvgl/freetype/src/gzip/zlib.h index a4e82c6a0..3f2f76e3c 100644 --- a/lib/libesp32_lvgl/freetype/src/gzip/zlib.h +++ b/lib/libesp32_lvgl/freetype/src/gzip/zlib.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.1.4, March 11th, 2002 + version 1.2.13, October 13th, 2022 - Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -24,12 +24,12 @@ The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ -#ifndef _ZLIB_H -#define _ZLIB_H +#ifndef ZLIB_H +#define ZLIB_H #include "ftzconf.h" @@ -37,27 +37,45 @@ extern "C" { #endif -#define ZLIB_VERSION "1.1.4" +#define ZLIB_VERSION "1.2.13" +#define ZLIB_VERNUM 0x12d0 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 13 +#define ZLIB_VER_SUBREVISION 0 /* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed - data. This version of the library supports only one compression method - (deflation) but other algorithms will be added later and will have the same - stream interface. + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. - Compression can be done in a single step if the buffers are large - enough (for example if an input file is mmap'ed), or can be done by - repeated calls of the compression function. In the latter case, the - application must provide more input and/or consume the output + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output (providing more output space) before each call. - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio. + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never - crash even in case of corrupted input. + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. */ typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); @@ -66,68 +84,95 @@ typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ + z_const Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ + uLong total_in; /* total number of input bytes read so far */ - Bytef *next_out; /* next output byte should be put there */ + Bytef *next_out; /* next output byte will go here */ uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ + uLong total_out; /* total number of bytes output so far */ - char *msg; /* last error message, NULL if no error */ + z_const char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ - int data_type; /* best guess about the data type: ascii or binary */ - uLong adler; /* adler32 value of the uncompressed data */ + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; typedef z_stream FAR *z_streamp; /* - The application must update next_in and avail_in when avail_in has - dropped to zero. It must update next_out and avail_out when avail_out - has dropped to zero. The application must initialize zalloc, zfree and - opaque before calling the init function. All other fields are set by the - compression library and must not be updated by the application. + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the opaque value. - zalloc must return Z_NULL if there is not enough memory for the object. + zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this - if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, - pointers returned by zalloc for objects of exactly 65536 bytes *must* - have their offset normalized to zero. The default allocation function - provided by this library ensures this (see zutil.c). To reduce memory - requirements and avoid any allocation of 64K objects, at the expense of - compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). - The fields total_in and total_out can be used for statistics or - progress reports. After compression, total_in holds the total size of - the uncompressed data and may be saved for use in the decompressor - (particularly if the decompressor wants to decompress everything in - a single step). + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). */ /* constants */ #define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_PARTIAL_FLUSH 1 #define Z_SYNC_FLUSH 2 #define Z_FULL_FLUSH 3 #define Z_FINISH 4 -/* Allowed flush values; see deflate() below for details */ +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ #define Z_OK 0 #define Z_STREAM_END 1 @@ -138,8 +183,8 @@ typedef z_stream FAR *z_streamp; #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative - * values are errors, positive values are used for special but normal events. +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. */ #define Z_NO_COMPRESSION 0 @@ -150,636 +195,1523 @@ typedef z_stream FAR *z_streamp; #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 #define Z_DEFAULT_STRATEGY 0 /* compression strategy; see deflateInit2() below for details */ #define Z_BINARY 0 -#define Z_ASCII 1 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 -/* Possible values of the data_type field */ +/* Possible values of the data_type field for deflate() */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ +#ifndef Z_FREETYPE + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + /* basic functions */ +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is - not compatible with the zlib.h header file used by the application. - This check is automatically made by deflateInit and inflateInit. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. */ /* -ZEXTERN(int) deflateInit OF((z_streamp strm, int level)); +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. - If zalloc and zfree are set to Z_NULL, deflateInit updates them to - use default allocation functions. + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at - all (the input data is simply copied a block at a time). - Z_DEFAULT_COMPRESSION requests a default compromise between speed and - compression (currently equivalent to level 6). + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if level is not a valid compression level, + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). - msg is set to null if there is no error message. deflateInit does not - perform any compression: this will be done by deflate(). + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). */ +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); /* deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce some - output latency (reading input without producing any output) except when + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when forced to flush. - The detailed semantics are as follows. deflate performs one or both of the + The detailed semantics are as follows. deflate performs one or both of the following actions: - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not + accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). - Some output may be provided even if flush is not set. + should be set only when necessary. Some output may be provided even if + flush is zero. - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating avail_in or avail_out accordingly; avail_out - should never be zero before the call. The application can consume the - compressed output when it wants, for example when the output buffer is full - (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK - and with zero avail_out, it must be called again after making room in the - output buffer because there might be more output pending. + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more output + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. If the parameter flush is set to Z_SYNC_FLUSH, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In particular - avail_in is zero after the call if enough output space has been provided - before the call.) Flushing may degrade compression for some compression - algorithms and so it should be used only when necessary. + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. If flush is set to Z_FULL_FLUSH, all output is flushed as with Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - the compression. + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero - avail_out). + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there - was enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the - stream are deflateReset or deflateEnd. + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least - 0.1% larger than avail_in plus 12 bytes. If deflate does not return - Z_STREAM_END, then it must be called again as described above. + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) - deflate() may update data_type if it can make a good guess about - the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered - binary. This field is only for information purposes and does not affect - the compression algorithm in any manner. + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. */ +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. + This function discards any unprocessed input and does not flush any pending + output. deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, - msg may be set but then points to a static string (which must not be + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be deallocated). */ +#endif /* !Z_FREETYPE */ /* -ZEXTERN(int) inflateInit OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - Initializes the internal stream state for decompression. The fields + Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the exact - value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller. msg is set to null if there is no error - message. inflateInit does not perform any decompression apart from reading - the zlib header if present: this will be done by inflate(). (So next_in and - avail_in may be modified, but next_out and avail_out are unchanged.) + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. */ -ZEXTERN(int) inflate OF((z_streamp strm, int flush)); +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); /* inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may some - introduce some output latency (reading input without producing any output) - except when forced to flush. + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. - The detailed semantics are as follows. inflate performs one or both of the + The detailed semantics are as follows. inflate performs one or both of the following actions: - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing - will resume at this point for the next call of inflate(). + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there - is no more input data or no more space in the output buffer (see below - about the flush parameter). + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating the next_* and avail_* values accordingly. - The application can consume the uncompressed output when it wants, for - example when the output buffer is full (avail_out == 0), or after each - call of inflate(). If inflate returns Z_OK and with zero avail_out, it - must be called again after making room in the output buffer because there - might be more output pending. + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. - If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much - output as possible to the output buffer. The flushing behavior of inflate is - not specified for values of the flush parameter other than Z_SYNC_FLUSH - and Z_FINISH, but the current implementation actually flushes as much output - as possible anyway. + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step - (a single call of inflate), the parameter flush should be set to - Z_FINISH. In this case all pending input is processed and all pending - output is flushed; avail_out must be large enough to hold all the - uncompressed data. (The size of the uncompressed data may have been saved - by the compressor for this purpose.) The next operation on this stream must - be inflateEnd to deallocate the decompression state. The use of Z_FINISH - is never required, but can be used to inform inflate that a faster routine - may be used for the single inflate() call. + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. - If a preset dictionary is needed at this point (see inflateSetDictionary - below), inflate sets strm-adler to the adler32 checksum of the - dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise - it sets strm->adler to the adler32 checksum of all output produced - so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or - an error code as described below. At the end of the stream, inflate() - checks that its computed adler32 checksum is equal to that saved by the - compressor and returns Z_STREAM_END only if the checksum is correct. + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect - adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent - (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if no progress is possible or if there was not - enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR - case, the application may then call inflateSync to look for a good - compression block. + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. */ -ZEXTERN(int) inflateEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. + This function discards any unprocessed input and does not flush any pending + output. - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. */ + /* Advanced functions */ /* The following functions are needed only in some special applications. */ +#ifndef Z_FREETYPE + /* -ZEXTERN(int) deflateInit2 OF((z_streamp strm, +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy)); - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by - the caller. + This is another version of deflateInit with more compression options. The + fields zalloc, zfree and opaque must be initialized before by the caller. - The method parameter is the compression method. It must be Z_DEFLATED in + The method parameter is the compression method. It must be Z_DEFLATED in this version of the library. The windowBits parameter is the base two logarithm of the window size (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but - is slow and reduces compression ratio; memLevel=9 uses maximum memory - for optimal speed. The default value is 8. See zconf.h for total memory - usage as a function of windowBits and memLevel. + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. - The strategy parameter is used to tune the compression algorithm. Use the + The strategy parameter is used to tune the compression algorithm. Use the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match). Filtered data consists mostly of small values with a - somewhat random distribution. In this case, the compression algorithm is - tuned to compress them better. The effect of Z_FILTERED is to force more - Huffman coding and less string matching; it is somewhat intermediate - between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects - the compression ratio but not the correctness of the compressed output even - if it is not set appropriately. + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid - method). msg is set to null if there is no error message. deflateInit2 does - not perform any compression: this will be done by deflate(). + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). */ +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); /* Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any - call of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a + used strings preferably put towards the end of the dictionary. Using a dictionary is most useful when the data to be compressed is short and can be predicted with good accuracy; the data can then be compressed better than with the default empty dictionary. Depending on the size of the compression data structures selected by deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size in - deflate or deflate2. Thus the strings most likely to be useful should be - put at the end of the dictionary, not at the front. + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. - Upon return of this function, strm->adler is set to the Adler32 value + Upon return of this function, strm->adler is set to the Adler-32 value of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The Adler32 value + which dictionary has been used by the compressor. (The Adler-32 value applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). */ +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when several compression strategies will be tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed + data with a filter. The streams that will be discarded should then be freed by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and - can consume lots of memory. + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and + (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); /* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. - The stream will keep the same compression level and any other attributes - that may have been set by deflateInit2. + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). */ +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); /* Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be + interpretation of level and strategy is as in deflateInit2(). This can be used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different - strategy. If the compression level is changed, the input available so far - is compressed with the old level (and may be flushed); the new level will - take effect only at the next call of deflate(). + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if there have been any deflate() calls since the + state was initialized or reset, then the input available so far is + compressed with the old level and strategy using deflate(strm, Z_BLOCK). + There are three approaches for the compression levels 0, 1..3, and 4..9 + respectively. The new level and strategy will take effect at the next call + of deflate(). - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to - be compressed and flushed. In particular, strm->avail_out must be non-zero. + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR - if strm->avail_out was zero. + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. */ /* -ZEXTERN(int) inflateInit2 OF((z_streamp strm, +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, int windowBits)); - This is another version of inflateInit with an extra parameter. The + This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. The windowBits parameter is the base two logarithm of the maximum window size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. If a compressed stream with a larger window size is given as - input, inflate() will return with the error code Z_DATA_ERROR instead of - trying to allocate a larger window. + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative - memLevel). msg is set to null if there is no error message. inflateInit2 - does not perform any decompression apart from reading the zlib header if - present: this will be done by inflate(). (So next_in and avail_in may be - modified, but next_out and avail_out are unchanged.) + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will *not* automatically decode concatenated gzip members. + inflate() will return Z_STREAM_END at the end of the gzip member. The state + would need to be reset to continue decoding a subsequent gzip member. This + *must* be done if there is more data after a gzip member, in order for the + decompression to be compliant with the gzip standard (RFC 1952). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. */ +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); /* Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate - if this call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the Adler32 value returned by this call of - inflate. The compressor and decompressor must use exactly the same - dictionary (see deflateSetDictionary). + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect Adler32 value). inflateSetDictionary does not + expected one (incorrect Adler-32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); /* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is Z_NULL, then it is not set. - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been found, - or Z_STREAM_ERROR if the stream structure was inconsistent. In the success - case, the application may save the current value of total_in which - indicates where valid compressed data was found. In the error case, the - application may repeatedly call inflateSync, providing more input each time, - until success or end of the input data. + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. */ -ZEXTERN(int) inflateReset OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +#endif /* !Z_FREETYPE */ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); /* This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. - The stream will keep attributes that may have been set by inflateInit2. + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). */ +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +#ifndef Z_FREETYPE + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +#endif /* !Z_FREETYPE */ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +#ifndef Z_FREETYPE + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#endif /* !Z_FREETYPE */ + +#ifndef Z_SOLO /* utility functions */ /* - The following utility functions are implemented on top of the - basic stream-oriented functions. To simplify the interface, some - default options are assumed (compression level and memory usage, - standard memory allocation functions). The source code of these - utility functions can easily be modified if you need special options. + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. */ +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); /* Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be at least 0.1% larger than - sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the - compressed buffer. - This function can be used to compress a whole file at once if the - input file is mmap'ed. + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer. */ +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); /* - Compresses the source buffer into the destination buffer. The level + Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least 0.1% larger than sourceLen plus - 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); /* Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. */ +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ /* - Opens a gzip (.gz) file for reading or writing. The mode parameter - is as in fopen ("rb" or "wb") but can also include a compression level - ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for - Huffman only compression as in "wb1h". (See the description - of deflateInit2 for more information about the strategy parameter.) + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Open the gzip (.gz) file at path for reading and decompressing, or + compressing and writing. The mode parameter is as in fopen ("rb" or "wb") + but can also include a compression level ("wb9") or a strategy: 'f' for + filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", + 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression + as in "wb9F". (See the description of deflateInit2 for more information + about the strategy parameter.) 'T' will request transparent writing or + appending with no compression and not using the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. - gzopen returns NULL if the file could not be opened or if there was - insufficient memory to allocate the (de)compression state; errno - can be checked to distinguish the two cases (if errno is zero, the - zlib error is Z_MEM_ERROR). */ - -/* - gzdopen() associates a gzFile with the file descriptor fd. File - descriptors are obtained from calls like open, dup, creat, pipe or - fileno (in the file has been previously opened with fopen). - The mode parameter is as in gzopen. - The next call of gzclose on the returned gzFile will also close the - file descriptor fd, just like fclose(fdopen(fd), mode) closes the file - descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). - gzdopen returns NULL if there was insufficient memory to allocate - the (de)compression state. + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. */ +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); /* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. + Associate a gzFile with the file descriptor fd. File descriptors are + obtained from calls like open, dup, creat, pipe or fileno (if the file has + been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). */ +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); /* - Reads the given number of uncompressed bytes from the compressed file. - If the input file was not in gzip format, gzread copies the given number - of bytes into the buffer. - gzread returns the number of uncompressed bytes actually read (0 for - end of file, -1 for error). */ + Set the internal buffer size used by this library's functions for file to + size. The default buffer size is 8192 bytes. This function must be called + after gzopen() or gzdopen(), and before any other calls that read or write + the file. The buffer memory allocation is always deferred to the first read + or write. Three times that size in buffer space is allocated. A larger + buffer size of, for example, 64K or 128K bytes will noticeably increase the + speed of decompression (reading). -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes actually written - (0 in case of error). + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. */ +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); /* - Converts, formats, and writes the args to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written (0 in case of error). + Dynamically update the compression level and strategy for file. See the + description of deflateInit2 for the meaning of these parameters. Previously + provided data is flushed before applying the parameter changes. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. */ +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); /* - Writes the given null-terminated string to the compressed file, excluding + Read and decompress up to len uncompressed bytes from file into buf. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read and decompress up to nitems items of size size from file into buf, + otherwise operating as gzread() does. This duplicates the interface of + stdio's fread(), with size_t request and return types. If the library + defines size_t, then z_size_t is identical to size_t. If not, then z_size_t + is an unsigned integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevertheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, resetting and retrying on end-of-file, when size is not 1. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len)); +/* + Compress and write the len uncompressed bytes at buf to file. gzwrite + returns the number of uncompressed bytes written or 0 in case of error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + Compress and write nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Convert, format, compress, and write the arguments (...) to file under + control of the string format, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf(), + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Compress and write the given null-terminated string s to file, excluding the terminating null character. - gzputs returns the number of characters written, or -1 in case of error. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Read and decompress bytes from file into buf, until len-1 characters are + read, or until a newline character is read and transferred to buf, or an + end-of-file condition is encountered. If any characters are read or if len + is one, the string is terminated with a null character. If no characters + are read due to an end-of-file or len is less than one, then the buffer is + left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Compress and write c, converted to an unsigned char, into file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Read and decompress one byte from file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push c back onto the stream for file to be read as the first character on + the next read. At least one character of push-back is always allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flush all pending output to file. The parameter flush is as in the + deflate() function. The return value is the zlib error number (see function + gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. */ /* - Reads bytes from the compressed file until len-1 characters are read, or - a newline character is read and transferred to buf, or an end-of-file - condition is encountered. The string is then terminated with a null - character. - gzgets returns buf, or Z_NULL in case of error. -*/ +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); -/* - Writes c, converted to an unsigned char, into the compressed file. - gzputc returns the value that was written, or -1 in case of error. -*/ - -/* - Reads one byte from the compressed file. gzgetc returns this byte - or -1 in case of end of file or error. -*/ - -/* - Flushes all pending output into the compressed file. The parameter - flush is as in the deflate() function. The return value is the zlib - error number (see function gzerror below). gzflush returns Z_OK if - the flush parameter is Z_FINISH and all output could be flushed. - gzflush should be called only when strictly necessary because it can - degrade compression. -*/ - -/* - Sets the starting position for the next gzread or gzwrite on the - given compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); + Set the starting position to offset relative to whence for the next gzread + or gzwrite on file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are + extremely slow. If the file is opened for writing, only forward seeks are supported; gzseek then compresses a sequence of zeroes up to the new starting position. - gzseek returns the resulting offset location as measured in bytes from + gzseek returns the resulting offset location as measured in bytes from the beginning of the uncompressed stream, or -1 in case of error, in particular if the file is opened for writing and the new starting position would be before the current position. */ +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); /* - Rewinds the given file. This function is supported only for reading. + Rewind file. This function is supported only for reading. - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). */ /* - Returns the starting position for the next gzread or gzwrite on the - given compressed file. This position represents a number of bytes in the - uncompressed data stream. +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) + Return the starting position for the next gzread or gzwrite on file. + This position represents a number of bytes in the uncompressed data stream, + and is zero when starting, even if appending or reading a gzip stream from + the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) */ /* - Returns 1 when EOF has previously been detected reading the given - input stream, otherwise zero. +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Return the current compressed (actual) read or write offset of file. This + offset includes the count of bytes that precede the gzip stream, for example + when appending or when using gzdopen() for reading. When reading, the + offset does not include as yet unused buffered input. This information can + be used for a progress indicator. On error, gzoffset() returns -1. */ +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); /* - Flushes all pending output if necessary, closes the compressed file - and deallocates all the (de)compression state. The return value is the zlib - error number (see function gzerror below). + Return true (1) if the end-of-file indicator for file has been set while + reading, false (0) otherwise. Note that the end-of-file indicator is set + only if the read tried to go past the end of the input, but came up short. + Therefore, just like feof(), gzeof() may return false even if there is no + more data to read, in the event that the last read request was for the exact + number of bytes remaining in the input file. This will happen if the input + file size is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. */ +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); /* - Returns the error message for the last error which occurred on the - given compressed file. errnum is set to zlib error number. If an - error occurred in the file system and not in the compression library, - errnum is set to Z_ERRNO and the application may consult errno - to get the exact error code. + Return true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) */ +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flush all pending output for file, if necessary, close file and + deallocate the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Return the error message for the last error which occurred on file. + errnum is set to zlib error number. If an error occurred in the file system + and not in the compression library, errnum is set to Z_ERRNO and the + application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clear the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + /* checksum functions */ /* These functions are not related to compression but are exported - anyway because they might be useful in applications using the - compression library. + anyway because they might be useful in applications using the compression + library. */ -ZEXTERN(uLong) adler32 OF((uLong adler, const Bytef *buf, uInt len)); - +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is NULL, this function returns - the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. Usage example: + return the updated checksum. An Adler-32 value is in the range of a 32-bit + unsigned integer. If buf is Z_NULL, this function returns the required + initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: uLong adler = adler32(0L, Z_NULL, 0); @@ -789,11 +1721,32 @@ ZEXTERN(uLong) adler32 OF((uLong adler, const Bytef *buf, uInt len)); if (adler != original_adler) error(); */ +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); /* - Update a running crc with the bytes buf[0..len-1] and return the updated - crc. If buf is NULL, this function returns the required initial value - for the crc. Pre- and post-conditioning (one's complement) is performed - within this function so it shouldn't be done by the application. + Same as adler32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. + If buf is Z_NULL, this function returns the required initial value for the + crc. Pre- and post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the application. + Usage example: uLong crc = crc32(0L, Z_NULL, 0); @@ -804,27 +1757,215 @@ ZEXTERN(uLong) adler32 OF((uLong adler, const Bytef *buf, uInt len)); if (crc != original_crc) error(); */ +ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2)); + + Return the operator corresponding to length len2, to be used with + crc32_combine_op(). +*/ + +#ifndef Z_FREETYPE + +ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op)); +/* + Give the same result as crc32_combine(), using op in place of len2. op is + is generated from len2 by crc32_combine_gen(). This will be faster than + crc32_combine() if the generated op is used more than once. +*/ + /* various hacks, don't look :) */ /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ -ZEXTERN(int) inflateInit2_ OF((z_streamp strm, int windowBits, +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, const char *version, int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif +#else /* Z_FREETYPE */ + + +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); + +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) + +#endif /* Z_FREETYPE */ + + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# define z_crc32_combine_gen z_crc32_combine_gen64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# define crc32_combine_gen crc32_combine_gen64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); +#endif + +#else /* Z_SOLO */ + +#ifndef Z_FREETYPE + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); +#endif + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +#ifndef Z_FREETYPE +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF((z_streamp)); +#endif /* !Z_FREETYPE */ +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +#ifndef Z_FREETYPE +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif +#endif /* !Z_FREETYPE */ #ifdef __cplusplus } #endif -#endif /* _ZLIB_H */ +#endif /* ZLIB_H */ diff --git a/lib/libesp32_lvgl/freetype/src/gzip/zutil.c b/lib/libesp32_lvgl/freetype/src/gzip/zutil.c index 7ad0c1f81..542706ca0 100644 --- a/lib/libesp32_lvgl/freetype/src/gzip/zutil.c +++ b/lib/libesp32_lvgl/freetype/src/gzip/zutil.c @@ -1,23 +1,161 @@ /* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2002 Jean-loup Gailly. + * Copyright (C) 1995-2017 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include "zutil.h" - -#ifndef STDC -extern void exit OF((int)); +#ifndef Z_SOLO +# include "gzguts.h" #endif +#ifndef Z_FREETYPE + +z_const char * const z_errmsg[10] = { + (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ + (z_const char *)"stream end", /* Z_STREAM_END 1 */ + (z_const char *)"", /* Z_OK 0 */ + (z_const char *)"file error", /* Z_ERRNO (-1) */ + (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ + (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ + (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ + (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ + (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ + (z_const char *)"" +}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef ZLIB_DEBUG + flags += 1 << 8; +#endif + /* +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif + */ +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef ZLIB_DEBUG +#include +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error( + char *m) +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError( + int err) +{ + return ERR_MSG(err); +} + +#endif /* !Z_FREETYPE */ + +#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800 + /* The older Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif #ifndef HAVE_MEMCPY -void zmemcpy(dest, source, len) - Bytef* dest; - const Bytef* source; - uInt len; +void ZLIB_INTERNAL zmemcpy( + Bytef* dest, + const Bytef* source, + uInt len) { if (len == 0) return; do { @@ -25,10 +163,12 @@ void zmemcpy(dest, source, len) } while (--len != 0); } -int zmemcmp(s1, s2, len) - const Bytef* s1; - const Bytef* s2; - uInt len; +#ifndef Z_FREETYPE + +int ZLIB_INTERNAL zmemcmp( + const Bytef* s1, + const Bytef* s2, + uInt len) { uInt j; @@ -38,22 +178,25 @@ int zmemcmp(s1, s2, len) return 0; } -void zmemzero(dest, len) - Bytef* dest; - uInt len; +void ZLIB_INTERNAL zmemzero( + Bytef* dest, + uInt len) { if (len == 0) return; do { *dest++ = 0; /* ??? to be unrolled */ } while (--len != 0); } +#endif /* !Z_FREETYPE */ #endif -#if defined( MSDOS ) && defined( __TURBOC__ ) && !defined( MY_ZCALLOC ) -#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) -/* Small and medium model in Turbo C are for now limited to near allocation - * with reduced MAX_WBITS and MAX_MEM_LEVEL - */ +#ifndef Z_SOLO + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + # define MY_ZCALLOC /* Turbo C malloc() does not allow dynamic allocation of 64K bytes @@ -80,11 +223,13 @@ local ptr_table table[MAX_PTR]; * a protected system like OS/2. Use Microsoft C instead. */ -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) { - voidpf buf = opaque; /* just to make some compilers happy */ + voidpf buf; ulg bsize = (ulg)items*size; + (void)opaque; + /* If we allocate less than 65520 bytes, we assume that farmalloc * will return a usable pointer which doesn't have to be normalized. */ @@ -104,9 +249,12 @@ voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) return buf; } -void zcfree (voidpf opaque, voidpf ptr) +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { int n; + + (void)opaque; + if (*(ush*)&ptr != 0) { /* object < 64K */ farfree(ptr); return; @@ -122,14 +270,13 @@ void zcfree (voidpf opaque, voidpf ptr) next_ptr--; return; } - ptr = opaque; /* just to make some compilers happy */ Assert(0, "zcfree: ptr not found"); } -#endif -#endif /* MSDOS && __TURBOC__ */ + +#endif /* __TURBOC__ */ -#if defined(M_I86) && !defined(__32BIT__) && !defined( MY_ZCALLOC ) +#ifdef M_I86 /* Microsoft C in 16-bit mode */ # define MY_ZCALLOC @@ -139,43 +286,49 @@ void zcfree (voidpf opaque, voidpf ptr) # define _hfree hfree #endif -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) { - if (opaque) opaque = 0; /* to make compiler happy */ + (void)opaque; return _halloc((long)items, size); } -void zcfree (voidpf opaque, voidpf ptr) +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { - if (opaque) opaque = 0; /* to make compiler happy */ + (void)opaque; _hfree(ptr); } -#endif /* MSC */ +#endif /* M_I86 */ + +#endif /* SYS16BIT */ #ifndef MY_ZCALLOC /* Any system without a special alloc function */ #ifndef STDC -extern voidp ft_scalloc OF((uInt items, uInt size)); -extern void ft_sfree OF((voidpf ptr)); +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); #endif -voidpf zcalloc (opaque, items, size) - voidpf opaque; - unsigned items; - unsigned size; +voidpf ZLIB_INTERNAL zcalloc( + voidpf opaque, + unsigned items, + unsigned size) { - if (opaque) items += size - size; /* make compiler happy */ - return (voidpf)ft_scalloc(items, size); + (void)opaque; + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); } -void zcfree (opaque, ptr) - voidpf opaque; - voidpf ptr; +void ZLIB_INTERNAL zcfree( + voidpf opaque, + voidpf ptr) { - ft_sfree(ptr); - if (opaque) return; /* make compiler happy */ + (void)opaque; + free(ptr); } #endif /* MY_ZCALLOC */ + +#endif /* !Z_SOLO */ diff --git a/lib/libesp32_lvgl/freetype/src/gzip/zutil.h b/lib/libesp32_lvgl/freetype/src/gzip/zutil.h index c9688cd9c..055ba8b62 100644 --- a/lib/libesp32_lvgl/freetype/src/gzip/zutil.h +++ b/lib/libesp32_lvgl/freetype/src/gzip/zutil.h @@ -1,5 +1,5 @@ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2002 Jean-loup Gailly. + * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -10,26 +10,31 @@ /* @(#) $Id$ */ -#ifndef _Z_UTIL_H -#define _Z_UTIL_H +#ifndef ZUTIL_H +#define ZUTIL_H + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif #include "zlib.h" -#ifdef STDC -# include +#if defined(STDC) && !defined(Z_SOLO) +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include +# endif # include # include #endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include -#endif #ifndef local # define local static #endif -/* compile with -Dlocal if your debugger can't find static symbols */ +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ typedef unsigned char uch; typedef uch FAR uchf; @@ -37,9 +42,26 @@ typedef unsigned short ush; typedef ush FAR ushf; typedef unsigned long ulg; +#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC) +# include +# if (ULONG_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned long +# elif (ULLONG_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned long long +# elif (UINT_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned +# endif +#endif + +#ifndef Z_FREETYPE +extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ +#endif /* !Z_FREETYPE */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] #define ERR_RETURN(strm,err) \ - return (strm->msg = (char*)ERR_MSG(err), (err)) + return (strm->msg = ERR_MSG(err), (err)) /* To be used only when the state is known to be valid */ /* common constants */ @@ -69,90 +91,130 @@ typedef unsigned long ulg; /* target dependencies */ -#ifdef MSDOS +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) # define OS_CODE 0x00 -# if defined(__TURBOC__) || defined(__BORLANDC__) -# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) - /* Allow compilation with ANSI keywords only enabled */ - void _Cdecl farfree( void *block ); - void *_Cdecl farmalloc( unsigned long nbytes ); -# else -# include +# ifndef Z_SOLO +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include # endif -# else /* MSC or DJGPP */ # endif #endif -#ifdef OS2 -# define OS_CODE 0x06 -#endif - -#ifdef WIN32 /* Window 95 & Windows NT */ -# define OS_CODE 0x0b -#endif - -#if defined(VAXC) || defined(VMS) -# define OS_CODE 0x02 -# define F_OPEN(name, mode) \ - ft_fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") -#endif - #ifdef AMIGA -# define OS_CODE 0x01 +# define OS_CODE 1 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 2 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#ifdef __370__ +# if __TARGET_LIB__ < 0x20000000 +# define OS_CODE 4 +# elif __TARGET_LIB__ < 0x40000000 +# define OS_CODE 11 +# else +# define OS_CODE 8 +# endif #endif #if defined(ATARI) || defined(atarist) -# define OS_CODE 0x05 +# define OS_CODE 5 +#endif + +#ifdef OS2 +# define OS_CODE 6 +# if defined(M_I86) && !defined(Z_SOLO) +# include +# endif #endif #if defined(MACOS) || defined(TARGET_OS_MAC) -# define OS_CODE 0x07 -# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include /* for fdopen */ -# else -# ifndef fdopen -# define fdopen(fd,mode) NULL /* No fdopen() */ +# define OS_CODE 7 +# ifndef Z_SOLO +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif # endif # endif #endif -#ifdef __50SERIES /* Prime/PRIMOS */ -# define OS_CODE 0x0F +#ifdef __acorn +# define OS_CODE 13 #endif -#ifdef TOPS20 -# define OS_CODE 0x0a +#if defined(WIN32) && !defined(__CYGWIN__) +# define OS_CODE 10 +#endif + +#ifdef _BEOS_ +# define OS_CODE 16 +#endif + +#ifdef __TOS_OS400__ +# define OS_CODE 18 +#endif + +#ifdef __APPLE__ +# define OS_CODE 19 #endif #if defined(_BEOS_) || defined(RISCOS) # define fdopen(fd,mode) NULL /* No fdopen() */ #endif -#if (defined(_MSC_VER) && (_MSC_VER > 600)) -# define fdopen(fd,type) _fdopen(fd,type) +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif #endif +#if defined(__BORLANDC__) && !defined(MSDOS) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif - /* Common defaults */ +#ifndef Z_FREETYPE + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_WIN32) && \ + (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t)); +#endif + +#endif /* !Z_FREETYPE */ + + /* common defaults */ #ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ +# define OS_CODE 3 /* assume Unix */ #endif #ifndef F_OPEN -# define F_OPEN(name, mode) ft_fopen((name), (mode)) +# define F_OPEN(name, mode) fopen((name), (mode)) #endif /* functions */ -#ifdef HAVE_STRERROR - extern char *strerror OF((int)); -# define zstrerror(errnum) strerror(errnum) -#else -# define zstrerror(errnum) "" -#endif - -#if defined(pyr) +#if defined(pyr) || defined(Z_SOLO) # define NO_MEMCPY #endif #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) @@ -176,16 +238,16 @@ typedef unsigned long ulg; # define zmemzero(dest, len) ft_memset(dest, 0, len) # endif #else - extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); - extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); - extern void zmemzero OF((Bytef* dest, uInt len)); + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); #endif /* Diagnostic functions */ -#ifdef DEBUG +#ifdef ZLIB_DEBUG # include - extern int z_verbose; - extern void z_error OF((char *m)); + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;} @@ -201,15 +263,19 @@ typedef unsigned long ulg; # define Tracecv(c,x) #endif - -typedef uLong (*check_func) OF((uLong check, const Bytef *buf, - uInt len)); -local voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); -local void zcfree OF((voidpf opaque, voidpf ptr)); +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); + void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#endif #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} -#endif /* _Z_UTIL_H */ +/* Reverse the bytes in a 32-bit value */ +#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +#endif /* ZUTIL_H */ diff --git a/lib/libesp32_lvgl/freetype/src/lzw/ftlzw.c b/lib/libesp32_lvgl/freetype/src/lzw/ftlzw.c index ddb81e6e9..88383792a 100644 --- a/lib/libesp32_lvgl/freetype/src/lzw/ftlzw.c +++ b/lib/libesp32_lvgl/freetype/src/lzw/ftlzw.c @@ -8,7 +8,7 @@ * be used to parse compressed PCF fonts, as found with many X11 server * distributions. * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * Albert Chin-A-Young. * * based on code in `src/gzip/ftgzip.c' @@ -369,7 +369,7 @@ FT_ZERO( stream ); stream->memory = memory; - if ( !FT_NEW( zip ) ) + if ( !FT_QNEW( zip ) ) { error = ft_lzw_file_init( zip, stream, source ); if ( error ) @@ -383,7 +383,7 @@ stream->size = 0x7FFFFFFFL; /* don't know the real size! */ stream->pos = 0; - stream->base = 0; + stream->base = NULL; stream->read = ft_lzw_stream_io; stream->close = ft_lzw_stream_close; diff --git a/lib/libesp32_lvgl/freetype/src/lzw/ftzopen.c b/lib/libesp32_lvgl/freetype/src/lzw/ftzopen.c index 884d2ec74..e680c4de5 100644 --- a/lib/libesp32_lvgl/freetype/src/lzw/ftzopen.c +++ b/lib/libesp32_lvgl/freetype/src/lzw/ftzopen.c @@ -8,7 +8,7 @@ * be used to parse compressed PCF fonts, as found with many X11 server * distributions. * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * David Turner. * * This file is part of the FreeType project, and may only be used, @@ -127,6 +127,7 @@ new_size = new_size + ( new_size >> 1 ) + 4; + /* if relocating to heap */ if ( state->stack == state->stack_0 ) { state->stack = NULL; @@ -142,9 +143,13 @@ return -1; } - if ( FT_RENEW_ARRAY( state->stack, old_size, new_size ) ) + if ( FT_QREALLOC( state->stack, old_size, new_size ) ) return -1; + /* if relocating to heap */ + if ( old_size == 0 ) + FT_MEM_COPY( state->stack, state->stack_0, FT_LZW_DEFAULT_STACK_SIZE ); + state->stack_size = new_size; } return 0; @@ -310,7 +315,7 @@ state->phase = FT_LZW_PHASE_CODE; } - /* fall-through */ + FALL_THROUGH; case FT_LZW_PHASE_CODE: { @@ -368,7 +373,7 @@ state->phase = FT_LZW_PHASE_STACK; } - /* fall-through */ + FALL_THROUGH; case FT_LZW_PHASE_STACK: { diff --git a/lib/libesp32_lvgl/freetype/src/lzw/ftzopen.h b/lib/libesp32_lvgl/freetype/src/lzw/ftzopen.h index d8768f7b4..6c7563643 100644 --- a/lib/libesp32_lvgl/freetype/src/lzw/ftzopen.h +++ b/lib/libesp32_lvgl/freetype/src/lzw/ftzopen.h @@ -8,7 +8,7 @@ * be used to parse compressed PCF fonts, as found with many X11 server * distributions. * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * David Turner. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/lzw/rules.mk b/lib/libesp32_lvgl/freetype/src/lzw/rules.mk index 3468ee024..b750216fb 100644 --- a/lib/libesp32_lvgl/freetype/src/lzw/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/lzw/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 2004-2020 by +# Copyright (C) 2004-2023 by # Albert Chin-A-Young. # # based on `src/lzw/rules.mk' diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/module.mk b/lib/libesp32_lvgl/freetype/src/otvalid/module.mk index 67b9820d8..90138426e 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/module.mk +++ b/lib/libesp32_lvgl/freetype/src/otvalid/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 2004-2020 by +# Copyright (C) 2004-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/otvalid.c b/lib/libesp32_lvgl/freetype/src/otvalid/otvalid.c index d640209f6..3b1e23a6f 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/otvalid.c +++ b/lib/libesp32_lvgl/freetype/src/otvalid/otvalid.c @@ -4,7 +4,7 @@ * * FreeType validator for OpenType tables (body only). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/otvalid.h b/lib/libesp32_lvgl/freetype/src/otvalid/otvalid.h index 8208ff011..7edadb771 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/otvalid.h +++ b/lib/libesp32_lvgl/freetype/src/otvalid/otvalid.h @@ -4,7 +4,7 @@ * * OpenType table validation (specification only). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/otvbase.c b/lib/libesp32_lvgl/freetype/src/otvalid/otvbase.c index 250ae98ab..f449795f8 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/otvbase.c +++ b/lib/libesp32_lvgl/freetype/src/otvalid/otvbase.c @@ -4,7 +4,7 @@ * * OpenType BASE table validation (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/otvcommn.c b/lib/libesp32_lvgl/freetype/src/otvalid/otvcommn.c index faaa84687..b94d8a065 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/otvcommn.c +++ b/lib/libesp32_lvgl/freetype/src/otvalid/otvcommn.c @@ -4,7 +4,7 @@ * * OpenType common tables validation (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/otvcommn.h b/lib/libesp32_lvgl/freetype/src/otvalid/otvcommn.h index f9926034a..6702c0008 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/otvcommn.h +++ b/lib/libesp32_lvgl/freetype/src/otvalid/otvcommn.h @@ -4,7 +4,7 @@ * * OpenType common tables validation (specification). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -105,10 +105,11 @@ FT_BEGIN_HEADER FT_Byte* pp = (FT_Byte*)_size ## _p; \ \ \ - FT_TRACE3(( "\n" \ - "Invalid offset to optional table `%s'" \ - " set to zero.\n" \ - "\n", #_size )); \ + FT_TRACE3(( "\n" )); \ + FT_TRACE3(( "Invalid offset to optional table `%s'" \ + " set to zero.\n", \ + #_size )); \ + FT_TRACE3(( "\n" )); \ \ _size = pp[0] = pp[1] = 0; \ } \ @@ -127,10 +128,11 @@ FT_BEGIN_HEADER FT_Byte* pp = (FT_Byte*)_size ## _p; \ \ \ - FT_TRACE3(( "\n" \ - "Invalid offset to optional table `%s'" \ - " set to zero.\n" \ - "\n", #_size )); \ + FT_TRACE3(( "\n" )); \ + FT_TRACE3(( "Invalid offset to optional table `%s'" \ + " set to zero.\n", \ + #_size )); \ + FT_TRACE3(( "\n" )); \ \ _size = pp[0] = pp[1] = pp[2] = pp[3] = 0; \ } \ @@ -178,24 +180,24 @@ FT_BEGIN_HEADER #define OTV_ENTER \ FT_BEGIN_STMNT \ otvalid->debug_indent += 2; \ - FT_TRACE4(( "%*.s", otvalid->debug_indent, 0 )); \ + FT_TRACE4(( "%*.s", otvalid->debug_indent, "" )); \ FT_TRACE4(( "%s table\n", \ otvalid->debug_function_name[otvalid->nesting_level] )); \ FT_END_STMNT -#define OTV_NAME_ENTER( name ) \ - FT_BEGIN_STMNT \ - otvalid->debug_indent += 2; \ - FT_TRACE4(( "%*.s", otvalid->debug_indent, 0 )); \ - FT_TRACE4(( "%s table\n", name )); \ +#define OTV_NAME_ENTER( name ) \ + FT_BEGIN_STMNT \ + otvalid->debug_indent += 2; \ + FT_TRACE4(( "%*.s", otvalid->debug_indent, "" )); \ + FT_TRACE4(( "%s table\n", name )); \ FT_END_STMNT #define OTV_EXIT otvalid->debug_indent -= 2 -#define OTV_TRACE( s ) \ - FT_BEGIN_STMNT \ - FT_TRACE4(( "%*.s", otvalid->debug_indent, 0 )); \ - FT_TRACE4( s ); \ +#define OTV_TRACE( s ) \ + FT_BEGIN_STMNT \ + FT_TRACE4(( "%*.s", otvalid->debug_indent, "" )); \ + FT_TRACE4( s ); \ FT_END_STMNT #else /* !FT_DEBUG_LEVEL_TRACE */ diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/otverror.h b/lib/libesp32_lvgl/freetype/src/otvalid/otverror.h index 979e9cbd9..4c4049ca5 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/otverror.h +++ b/lib/libesp32_lvgl/freetype/src/otvalid/otverror.h @@ -4,7 +4,7 @@ * * OpenType validation module error codes (specification only). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/otvgdef.c b/lib/libesp32_lvgl/freetype/src/otvalid/otvgdef.c index 88874b847..d62e8187f 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/otvgdef.c +++ b/lib/libesp32_lvgl/freetype/src/otvalid/otvgdef.c @@ -4,7 +4,7 @@ * * OpenType GDEF table validation (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/otvgpos.c b/lib/libesp32_lvgl/freetype/src/otvalid/otvgpos.c index 29d56f91e..f6102afbc 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/otvgpos.c +++ b/lib/libesp32_lvgl/freetype/src/otvalid/otvgpos.c @@ -4,7 +4,7 @@ * * OpenType GPOS table validation (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/otvgpos.h b/lib/libesp32_lvgl/freetype/src/otvalid/otvgpos.h index 06a03a0e6..b5d0f5485 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/otvgpos.h +++ b/lib/libesp32_lvgl/freetype/src/otvalid/otvgpos.h @@ -4,7 +4,7 @@ * * OpenType GPOS table validator (specification). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/otvgsub.c b/lib/libesp32_lvgl/freetype/src/otvalid/otvgsub.c index f0d563ba9..5d40d9243 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/otvgsub.c +++ b/lib/libesp32_lvgl/freetype/src/otvalid/otvgsub.c @@ -4,7 +4,7 @@ * * OpenType GSUB table validation (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -61,7 +61,8 @@ { FT_Bytes Coverage; FT_Int DeltaGlyphID; - FT_Long idx; + FT_UInt first_cov, last_cov; + FT_UInt first_idx, last_idx; OTV_LIMIT_CHECK( 4 ); @@ -70,12 +71,21 @@ otv_Coverage_validate( Coverage, otvalid, -1 ); - idx = (FT_Long)otv_Coverage_get_first( Coverage ) + DeltaGlyphID; - if ( idx < 0 ) + first_cov = otv_Coverage_get_first( Coverage ); + last_cov = otv_Coverage_get_last( Coverage ); + + /* These additions are modulo 65536. */ + first_idx = (FT_UInt)( (FT_Int)first_cov + DeltaGlyphID ) & 0xFFFFU; + last_idx = (FT_UInt)( (FT_Int)last_cov + DeltaGlyphID ) & 0xFFFFU; + + /* Since the maximum number of glyphs is 2^16 - 1 = 65535, */ + /* the largest possible glyph index is 65534. For this */ + /* reason there can't be a wrap-around region, which would */ + /* imply the use of the invalid glyph index 65535. */ + if ( first_idx > last_idx ) FT_INVALID_DATA; - idx = (FT_Long)otv_Coverage_get_last( Coverage ) + DeltaGlyphID; - if ( (FT_UInt)idx >= otvalid->glyph_count ) + if ( last_idx >= otvalid->glyph_count ) FT_INVALID_DATA; } break; diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/otvjstf.c b/lib/libesp32_lvgl/freetype/src/otvalid/otvjstf.c index 79de7b809..712039c66 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/otvjstf.c +++ b/lib/libesp32_lvgl/freetype/src/otvalid/otvjstf.c @@ -4,7 +4,7 @@ * * OpenType JSTF table validation (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/otvmath.c b/lib/libesp32_lvgl/freetype/src/otvalid/otvmath.c index dfdeaaba7..01fd863c9 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/otvmath.c +++ b/lib/libesp32_lvgl/freetype/src/otvalid/otvmath.c @@ -4,7 +4,7 @@ * * OpenType MATH table validation (body). * - * Copyright (C) 2007-2020 by + * Copyright (C) 2007-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Written by George Williams. @@ -141,7 +141,7 @@ OTV_OPTIONAL_TABLE( DeviceTableOffset ); - /* OTV_NAME_ENTER( "MathKern" );*/ + /* OTV_NAME_ENTER( "MathKern" ); */ OTV_LIMIT_CHECK( 2 ); diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/otvmod.c b/lib/libesp32_lvgl/freetype/src/otvalid/otvmod.c index 0188b2701..d6057c5a4 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/otvmod.c +++ b/lib/libesp32_lvgl/freetype/src/otvalid/otvmod.c @@ -4,7 +4,7 @@ * * FreeType's OpenType validation module implementation (body). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -53,7 +53,7 @@ if ( error ) goto Exit; - if ( FT_ALLOC( *table, *table_len ) ) + if ( FT_QALLOC( *table, *table_len ) ) goto Exit; error = FT_Load_Sfnt_Table( face, tag, 0, *table, table_len ); @@ -94,7 +94,7 @@ */ if ( face->num_glyphs > 0xFFFFL ) { - FT_TRACE1(( "otv_validate: Invalid glyphs index (0x0000FFFF - 0x%08x) ", + FT_TRACE1(( "otv_validate: Invalid glyphs index (0x0000FFFF - 0x%08lx) ", face->num_glyphs )); FT_TRACE1(( "are not handled by OpenType tables\n" )); num_glyphs = 0xFFFF; diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/otvmod.h b/lib/libesp32_lvgl/freetype/src/otvalid/otvmod.h index efd6da035..f0e68dbc0 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/otvmod.h +++ b/lib/libesp32_lvgl/freetype/src/otvalid/otvmod.h @@ -5,7 +5,7 @@ * FreeType's OpenType validation module implementation * (specification). * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/otvalid/rules.mk b/lib/libesp32_lvgl/freetype/src/otvalid/rules.mk index 7f0169fd8..800cb8733 100644 --- a/lib/libesp32_lvgl/freetype/src/otvalid/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/otvalid/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 2004-2020 by +# Copyright (C) 2004-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/pcf/pcfdrivr.c b/lib/libesp32_lvgl/freetype/src/pcf/pcfdrivr.c index e9dd51752..f1dba0240 100644 --- a/lib/libesp32_lvgl/freetype/src/pcf/pcfdrivr.c +++ b/lib/libesp32_lvgl/freetype/src/pcf/pcfdrivr.c @@ -75,98 +75,82 @@ THE SOFTWARE. FT_CALLBACK_DEF( FT_Error ) - pcf_cmap_init( FT_CMap pcfcmap, /* PCF_CMap */ + pcf_cmap_init( FT_CMap cmap, /* PCF_CMap */ FT_Pointer init_data ) { - PCF_CMap cmap = (PCF_CMap)pcfcmap; - PCF_Face face = (PCF_Face)FT_CMAP_FACE( pcfcmap ); + PCF_CMap pcfcmap = (PCF_CMap)cmap; + PCF_Face face = (PCF_Face)FT_CMAP_FACE( cmap ); FT_UNUSED( init_data ); - cmap->enc = &face->enc; + pcfcmap->enc = &face->enc; return FT_Err_Ok; } FT_CALLBACK_DEF( void ) - pcf_cmap_done( FT_CMap pcfcmap ) /* PCF_CMap */ + pcf_cmap_done( FT_CMap cmap ) /* PCF_CMap */ { - PCF_CMap cmap = (PCF_CMap)pcfcmap; + PCF_CMap pcfcmap = (PCF_CMap)cmap; - cmap->enc = NULL; + pcfcmap->enc = NULL; } FT_CALLBACK_DEF( FT_UInt ) - pcf_cmap_char_index( FT_CMap pcfcmap, /* PCF_CMap */ + pcf_cmap_char_index( FT_CMap cmap, /* PCF_CMap */ FT_UInt32 charcode ) { - PCF_CMap cmap = (PCF_CMap)pcfcmap; - PCF_Enc enc = cmap->enc; - FT_UShort charcodeRow; - FT_UShort charcodeCol; + PCF_Enc enc = ( (PCF_CMap)cmap )->enc; + + FT_UInt32 i = ( charcode >> 8 ) - enc->firstRow; + FT_UInt32 j = ( charcode & 0xFF ) - enc->firstCol; + FT_UInt32 h = enc->lastRow - enc->firstRow + 1; + FT_UInt32 w = enc->lastCol - enc->firstCol + 1; - if ( charcode > (FT_UInt32)( enc->lastRow * 256 + enc->lastCol ) || - charcode < (FT_UInt32)( enc->firstRow * 256 + enc->firstCol ) ) + /* wrapped around "negative" values are also rejected */ + if ( i >= h || j >= w ) return 0; - charcodeRow = (FT_UShort)( charcode >> 8 ); - charcodeCol = (FT_UShort)( charcode & 0xFF ); - - if ( charcodeCol < enc->firstCol || - charcodeCol > enc->lastCol ) - return 0; - - return (FT_UInt)enc->offset[( charcodeRow - enc->firstRow ) * - ( enc->lastCol - enc->firstCol + 1 ) + - charcodeCol - enc->firstCol]; + return (FT_UInt)enc->offset[i * w + j]; } FT_CALLBACK_DEF( FT_UInt ) - pcf_cmap_char_next( FT_CMap pcfcmap, /* PCF_CMap */ + pcf_cmap_char_next( FT_CMap cmap, /* PCF_CMap */ FT_UInt32 *acharcode ) { - PCF_CMap cmap = (PCF_CMap)pcfcmap; - PCF_Enc enc = cmap->enc; - FT_UInt32 charcode = *acharcode; - FT_UShort charcodeRow; - FT_UShort charcodeCol; - FT_UInt result = 0; + PCF_Enc enc = ( (PCF_CMap)cmap )->enc; + FT_UInt32 charcode = *acharcode + 1; + + FT_UInt32 i = ( charcode >> 8 ) - enc->firstRow; + FT_UInt32 j = ( charcode & 0xFF ) - enc->firstCol; + FT_UInt32 h = enc->lastRow - enc->firstRow + 1; + FT_UInt32 w = enc->lastCol - enc->firstCol + 1; + + FT_UInt result = 0; - while ( charcode < (FT_UInt32)( enc->lastRow * 256 + enc->lastCol ) ) - { - charcode++; + /* adjust wrapped around "negative" values */ + if ( (FT_Int32)i < 0 ) + i = 0; + if ( (FT_Int32)j < 0 ) + j = 0; - if ( charcode < (FT_UInt32)( enc->firstRow * 256 + enc->firstCol ) ) - charcode = (FT_UInt32)( enc->firstRow * 256 + enc->firstCol ); - - charcodeRow = (FT_UShort)( charcode >> 8 ); - charcodeCol = (FT_UShort)( charcode & 0xFF ); - - if ( charcodeCol < enc->firstCol ) - charcodeCol = enc->firstCol; - else if ( charcodeCol > enc->lastCol ) + for ( ; i < h; i++, j = 0 ) + for ( ; j < w; j++ ) { - charcodeRow++; - charcodeCol = enc->firstCol; + result = (FT_UInt)enc->offset[i * w + j]; + if ( result != 0xFFFFU ) + goto Exit; } - charcode = (FT_UInt32)( charcodeRow * 256 + charcodeCol ); - - result = (FT_UInt)enc->offset[( charcodeRow - enc->firstRow ) * - ( enc->lastCol - enc->firstCol + 1 ) + - charcodeCol - enc->firstCol]; - if ( result != 0xFFFFU ) - break; - } - - *acharcode = charcode; + Exit: + *acharcode = ( ( i + enc->firstRow ) << 8 ) | ( j + enc->firstCol ); return result; } @@ -186,9 +170,9 @@ THE SOFTWARE. FT_CALLBACK_DEF( void ) - PCF_Face_Done( FT_Face pcfface ) /* PCF_Face */ + PCF_Face_Done( FT_Face face ) /* PCF_Face */ { - PCF_Face face = (PCF_Face)pcfface; + PCF_Face pcfface = (PCF_Face)face; FT_Memory memory; @@ -197,18 +181,18 @@ THE SOFTWARE. memory = FT_FACE_MEMORY( face ); - FT_FREE( face->metrics ); - FT_FREE( face->enc.offset ); + FT_FREE( pcfface->metrics ); + FT_FREE( pcfface->enc.offset ); /* free properties */ - if ( face->properties ) + if ( pcfface->properties ) { FT_Int i; - for ( i = 0; i < face->nprops; i++ ) + for ( i = 0; i < pcfface->nprops; i++ ) { - PCF_Property prop = &face->properties[i]; + PCF_Property prop = &pcfface->properties[i]; if ( prop ) @@ -219,33 +203,33 @@ THE SOFTWARE. } } - FT_FREE( face->properties ); + FT_FREE( pcfface->properties ); } - FT_FREE( face->toc.tables ); - FT_FREE( pcfface->family_name ); - FT_FREE( pcfface->style_name ); - FT_FREE( pcfface->available_sizes ); - FT_FREE( face->charset_encoding ); - FT_FREE( face->charset_registry ); + FT_FREE( pcfface->toc.tables ); + FT_FREE( face->family_name ); + FT_FREE( face->style_name ); + FT_FREE( face->available_sizes ); + FT_FREE( pcfface->charset_encoding ); + FT_FREE( pcfface->charset_registry ); /* close compressed stream if any */ - if ( pcfface->stream == &face->comp_stream ) + if ( face->stream == &pcfface->comp_stream ) { - FT_Stream_Close( &face->comp_stream ); - pcfface->stream = face->comp_source; + FT_Stream_Close( &pcfface->comp_stream ); + face->stream = pcfface->comp_source; } } FT_CALLBACK_DEF( FT_Error ) PCF_Face_Init( FT_Stream stream, - FT_Face pcfface, /* PCF_Face */ + FT_Face face, /* PCF_Face */ FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { - PCF_Face face = (PCF_Face)pcfface; + PCF_Face pcfface = (PCF_Face)face; FT_Error error; FT_UNUSED( num_params ); @@ -254,10 +238,10 @@ THE SOFTWARE. FT_TRACE2(( "PCF driver\n" )); - error = pcf_load_font( stream, face, face_index ); + error = pcf_load_font( stream, pcfface, face_index ); if ( error ) { - PCF_Face_Done( pcfface ); + PCF_Face_Done( face ); #if defined( FT_CONFIG_OPTION_USE_ZLIB ) || \ defined( FT_CONFIG_OPTION_USE_LZW ) || \ @@ -270,7 +254,7 @@ THE SOFTWARE. /* this didn't work, try gzip support! */ FT_TRACE2(( " ... try gzip stream\n" )); - error2 = FT_Stream_OpenGzip( &face->comp_stream, stream ); + error2 = FT_Stream_OpenGzip( &pcfface->comp_stream, stream ); if ( FT_ERR_EQ( error2, Unimplemented_Feature ) ) goto Fail; @@ -286,7 +270,7 @@ THE SOFTWARE. /* this didn't work, try LZW support! */ FT_TRACE2(( " ... try LZW stream\n" )); - error3 = FT_Stream_OpenLZW( &face->comp_stream, stream ); + error3 = FT_Stream_OpenLZW( &pcfface->comp_stream, stream ); if ( FT_ERR_EQ( error3, Unimplemented_Feature ) ) goto Fail; @@ -302,7 +286,7 @@ THE SOFTWARE. /* this didn't work, try Bzip2 support! */ FT_TRACE2(( " ... try Bzip2 stream\n" )); - error4 = FT_Stream_OpenBzip2( &face->comp_stream, stream ); + error4 = FT_Stream_OpenBzip2( &pcfface->comp_stream, stream ); if ( FT_ERR_EQ( error4, Unimplemented_Feature ) ) goto Fail; @@ -313,12 +297,12 @@ THE SOFTWARE. if ( error ) goto Fail; - face->comp_source = stream; - pcfface->stream = &face->comp_stream; + pcfface->comp_source = stream; + face->stream = &pcfface->comp_stream; - stream = pcfface->stream; + stream = face->stream; - error = pcf_load_font( stream, face, face_index ); + error = pcf_load_font( stream, pcfface, face_index ); if ( error ) goto Fail; @@ -342,14 +326,14 @@ THE SOFTWARE. else if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 ) { FT_ERROR(( "PCF_Face_Init: invalid face index\n" )); - PCF_Face_Done( pcfface ); + PCF_Face_Done( face ); return FT_THROW( Invalid_Argument ); } /* set up charmap */ { - FT_String *charset_registry = face->charset_registry; - FT_String *charset_encoding = face->charset_encoding; + FT_String *charset_registry = pcfface->charset_registry; + FT_String *charset_encoding = pcfface->charset_encoding; FT_Bool unicode_charmap = 0; @@ -365,13 +349,13 @@ THE SOFTWARE. ( s[2] == 'o' || s[2] == 'O' ) ) { s += 3; - if ( !ft_strcmp( s, "10646" ) || - ( !ft_strcmp( s, "8859" ) && - !ft_strcmp( face->charset_encoding, "1" ) ) ) + if ( !ft_strcmp( s, "10646" ) || + ( !ft_strcmp( s, "8859" ) && + !ft_strcmp( pcfface->charset_encoding, "1" ) ) ) unicode_charmap = 1; /* another name for ASCII */ - else if ( !ft_strcmp( s, "646.1991" ) && - !ft_strcmp( face->charset_encoding, "IRV" ) ) + else if ( !ft_strcmp( s, "646.1991" ) && + !ft_strcmp( pcfface->charset_encoding, "IRV" ) ) unicode_charmap = 1; } } @@ -380,7 +364,7 @@ THE SOFTWARE. FT_CharMapRec charmap; - charmap.face = FT_FACE( face ); + charmap.face = face; charmap.encoding = FT_ENCODING_NONE; /* initial platform/encoding should indicate unset status? */ charmap.platform_id = TT_PLATFORM_APPLE_UNICODE; @@ -402,7 +386,7 @@ THE SOFTWARE. Fail: FT_TRACE2(( " not a PCF file\n" )); - PCF_Face_Done( pcfface ); + PCF_Face_Done( face ); error = FT_THROW( Unknown_File_Format ); /* error */ goto Exit; } @@ -585,15 +569,16 @@ THE SOFTWARE. * */ - static FT_Error - pcf_get_bdf_property( PCF_Face face, + FT_CALLBACK_DEF( FT_Error ) + pcf_get_bdf_property( FT_Face face, /* PCF_Face */ const char* prop_name, BDF_PropertyRec *aproperty ) { + PCF_Face pcfface = (PCF_Face)face; PCF_Property prop; - prop = pcf_find_property( face, prop_name ); + prop = pcf_find_property( pcfface, prop_name ); if ( prop ) { if ( prop->isString ) @@ -606,7 +591,7 @@ THE SOFTWARE. if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) ) { - FT_TRACE1(( "pcf_get_bdf_property:" + FT_TRACE2(( "pcf_get_bdf_property:" " too large integer 0x%lx is truncated\n", prop->value.l )); } @@ -627,13 +612,16 @@ THE SOFTWARE. } - static FT_Error - pcf_get_charset_id( PCF_Face face, + FT_CALLBACK_DEF( FT_Error ) + pcf_get_charset_id( FT_Face face, /* PCF_Face */ const char* *acharset_encoding, const char* *acharset_registry ) { - *acharset_encoding = face->charset_encoding; - *acharset_registry = face->charset_registry; + PCF_Face pcfface = (PCF_Face)face; + + + *acharset_encoding = pcfface->charset_encoding; + *acharset_registry = pcfface->charset_registry; return FT_Err_Ok; } @@ -650,7 +638,7 @@ THE SOFTWARE. * PROPERTY SERVICE * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) pcf_property_set( FT_Module module, /* PCF_Driver */ const char* property_name, const void* value, @@ -705,16 +693,16 @@ THE SOFTWARE. #endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ - FT_TRACE0(( "pcf_property_set: missing property `%s'\n", + FT_TRACE2(( "pcf_property_set: missing property `%s'\n", property_name )); return FT_THROW( Missing_Property ); } - static FT_Error + FT_CALLBACK_DEF( FT_Error ) pcf_property_get( FT_Module module, /* PCF_Driver */ const char* property_name, - const void* value ) + void* value ) { #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES @@ -743,7 +731,7 @@ THE SOFTWARE. #endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ - FT_TRACE0(( "pcf_property_get: missing property `%s'\n", + FT_TRACE2(( "pcf_property_get: missing property `%s'\n", property_name )); return FT_THROW( Missing_Property ); } diff --git a/lib/libesp32_lvgl/freetype/src/pcf/pcfread.c b/lib/libesp32_lvgl/freetype/src/pcf/pcfread.c index 8817682cd..f167bcb8a 100644 --- a/lib/libesp32_lvgl/freetype/src/pcf/pcfread.c +++ b/lib/libesp32_lvgl/freetype/src/pcf/pcfread.c @@ -127,7 +127,7 @@ THE SOFTWARE. toc->count = FT_MIN( stream->size >> 4, 9 ); } - if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) ) + if ( FT_QNEW_ARRAY( face->toc.tables, toc->count ) ) return error; tables = face->toc.tables; @@ -238,7 +238,7 @@ THE SOFTWARE. { for ( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] ); j++ ) - if ( tables[i].type == (FT_UInt)( 1 << j ) ) + if ( tables[i].type == 1UL << j ) name = tableNames[j]; FT_TRACE4(( " %d: type=%s, format=0x%lX," @@ -501,8 +501,8 @@ THE SOFTWARE. if ( FT_READ_ULONG_LE( format ) ) goto Bail; - FT_TRACE4(( "pcf_get_properties:\n" - " format: 0x%lX (%s)\n", + FT_TRACE4(( "pcf_get_properties:\n" )); + FT_TRACE4(( " format: 0x%lX (%s)\n", format, PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" )); @@ -540,7 +540,7 @@ THE SOFTWARE. face->nprops = (int)nprops; - if ( FT_NEW_ARRAY( props, nprops ) ) + if ( FT_QNEW_ARRAY( props, nprops ) ) goto Bail; for ( i = 0; i < nprops; i++ ) @@ -607,13 +607,13 @@ THE SOFTWARE. } /* allocate one more byte so that we have a final null byte */ - if ( FT_NEW_ARRAY( strings, string_size + 1 ) ) + if ( FT_QALLOC( strings, string_size + 1 ) || + FT_STREAM_READ( strings, string_size ) ) goto Bail; - error = FT_Stream_Read( stream, (FT_Byte*)strings, string_size ); - if ( error ) - goto Bail; + strings[string_size] = '\0'; + /* zero out in case of failure */ if ( FT_NEW_ARRAY( properties, nprops ) ) goto Bail; @@ -697,8 +697,8 @@ THE SOFTWARE. if ( FT_READ_ULONG_LE( format ) ) goto Bail; - FT_TRACE4(( "pcf_get_metrics:\n" - " format: 0x%lX (%s, %s)\n", + FT_TRACE4(( "pcf_get_metrics:\n" )); + FT_TRACE4(( " format: 0x%lX (%s, %s)\n", format, PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB", PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) ? @@ -767,7 +767,7 @@ THE SOFTWARE. face->nmetrics = nmetrics + 1; - if ( FT_NEW_ARRAY( face->metrics, face->nmetrics ) ) + if ( FT_QNEW_ARRAY( face->metrics, face->nmetrics ) ) return error; /* we handle glyph index 0 later on */ @@ -840,17 +840,16 @@ THE SOFTWARE. FT_Stream_ExitFrame( stream ); - FT_TRACE4(( "pcf_get_bitmaps:\n" - " format: 0x%lX\n" - " (%s, %s,\n" - " padding=%d bit%s, scanning=%d bit%s)\n", - format, + FT_TRACE4(( "pcf_get_bitmaps:\n" )); + FT_TRACE4(( " format: 0x%lX\n", format )); + FT_TRACE4(( " (%s, %s,\n", PCF_BYTE_ORDER( format ) == MSBFirst ? "most significant byte first" : "least significant byte first", PCF_BIT_ORDER( format ) == MSBFirst ? "most significant bit first" - : "least significant bit first", + : "least significant bit first" )); + FT_TRACE4(( " padding=%d bit%s, scanning=%d bit%s)\n", 8 << PCF_GLYPH_PAD_INDEX( format ), ( 8 << PCF_GLYPH_PAD_INDEX( format ) ) == 1 ? "" : "s", 8 << PCF_SCAN_UNIT_INDEX( format ), @@ -1001,8 +1000,8 @@ THE SOFTWARE. if ( FT_READ_ULONG_LE( format ) ) goto Bail; - FT_TRACE4(( "pcf_get_encodings:\n" - " format: 0x%lX (%s)\n", + FT_TRACE4(( "pcf_get_encodings:\n" )); + FT_TRACE4(( " format: 0x%lX (%s)\n", format, PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" )); @@ -1021,11 +1020,11 @@ THE SOFTWARE. goto Bail; } - FT_TRACE4(( " firstCol 0x%X, lastCol 0x%X\n" - " firstRow 0x%X, lastRow 0x%X\n" - " defaultChar 0x%X\n", - enc->firstCol, enc->lastCol, - enc->firstRow, enc->lastRow, + FT_TRACE4(( " firstCol 0x%X, lastCol 0x%X\n", + enc->firstCol, enc->lastCol )); + FT_TRACE4(( " firstRow 0x%X, lastRow 0x%X\n", + enc->firstRow, enc->lastRow )); + FT_TRACE4(( " defaultChar 0x%X\n", enc->defaultChar )); /* sanity checks; we limit numbers of rows and columns to 256 */ @@ -1035,16 +1034,6 @@ THE SOFTWARE. enc->lastRow > 0xFF ) return FT_THROW( Invalid_Table ); - nencoding = (FT_ULong)( enc->lastCol - enc->firstCol + 1 ) * - (FT_ULong)( enc->lastRow - enc->firstRow + 1 ); - - if ( FT_NEW_ARRAY( enc->offset, nencoding ) ) - goto Bail; - - error = FT_Stream_EnterFrame( stream, 2 * nencoding ); - if ( error ) - goto Exit; - FT_TRACE5(( "\n" )); defaultCharRow = enc->defaultChar >> 8; @@ -1065,6 +1054,13 @@ THE SOFTWARE. defaultCharCol = enc->firstCol; } + nencoding = (FT_ULong)( enc->lastCol - enc->firstCol + 1 ) * + (FT_ULong)( enc->lastRow - enc->firstRow + 1 ); + + error = FT_Stream_EnterFrame( stream, 2 * nencoding ); + if ( error ) + goto Bail; + /* * FreeType mandates that glyph index 0 is the `undefined glyph', which * PCF calls the `default character'. However, FreeType needs glyph @@ -1088,8 +1084,8 @@ THE SOFTWARE. if ( defaultCharEncodingOffset == 0xFFFF ) { FT_TRACE0(( "pcf_get_encodings:" - " No glyph for default character,\n" - " " + " No glyph for default character,\n" )); + FT_TRACE0(( " " " setting it to the first glyph of the font\n" )); defaultCharEncodingOffset = 1; } @@ -1100,8 +1096,8 @@ THE SOFTWARE. if ( defaultCharEncodingOffset >= face->nmetrics ) { FT_TRACE0(( "pcf_get_encodings:" - " Invalid glyph index for default character,\n" - " " + " Invalid glyph index for default character,\n" )); + FT_TRACE0(( " " " setting it to the first glyph of the font\n" )); defaultCharEncodingOffset = 1; } @@ -1110,6 +1106,9 @@ THE SOFTWARE. /* copy metrics of default character to index 0 */ face->metrics[0] = face->metrics[defaultCharEncodingOffset]; + if ( FT_QNEW_ARRAY( enc->offset, nencoding ) ) + goto Bail; + /* now loop over all values */ offset = enc->offset; for ( i = enc->firstRow; i <= enc->lastRow; i++ ) @@ -1132,11 +1131,6 @@ THE SOFTWARE. } FT_Stream_ExitFrame( stream ); - return error; - - Exit: - FT_FREE( enc->offset ); - Bail: return error; } @@ -1208,10 +1202,10 @@ THE SOFTWARE. if ( FT_READ_ULONG_LE( format ) ) goto Bail; - FT_TRACE4(( "pcf_get_accel%s:\n" - " format: 0x%lX (%s, %s)\n", + FT_TRACE4(( "pcf_get_accel%s:\n", type == PCF_BDF_ACCELERATORS ? " (getting BDF accelerators)" - : "", + : "" )); + FT_TRACE4(( " format: 0x%lX (%s, %s)\n", format, PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB", PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ? @@ -1233,16 +1227,16 @@ THE SOFTWARE. } FT_TRACE5(( " noOverlap=%s, constantMetrics=%s," - " terminalFont=%s, constantWidth=%s\n" - " inkInside=%s, inkMetrics=%s, drawDirection=%s\n" - " fontAscent=%ld, fontDescent=%ld, maxOverlap=%ld\n", + " terminalFont=%s, constantWidth=%s\n", accel->noOverlap ? "yes" : "no", accel->constantMetrics ? "yes" : "no", accel->terminalFont ? "yes" : "no", - accel->constantWidth ? "yes" : "no", + accel->constantWidth ? "yes" : "no" )); + FT_TRACE5(( " inkInside=%s, inkMetrics=%s, drawDirection=%s\n", accel->inkInside ? "yes" : "no", accel->inkMetrics ? "yes" : "no", - accel->drawDirection ? "RTL" : "LTR", + accel->drawDirection ? "RTL" : "LTR" )); + FT_TRACE5(( " fontAscent=%ld, fontDescent=%ld, maxOverlap=%ld\n", accel->fontAscent, accel->fontDescent, accel->maxOverlap )); @@ -1369,7 +1363,7 @@ THE SOFTWARE. char* s; - if ( FT_ALLOC( face->style_name, len ) ) + if ( FT_QALLOC( face->style_name, len ) ) return error; s = face->style_name; @@ -1533,7 +1527,7 @@ THE SOFTWARE. { l += ft_strlen( foundry_prop->value.atom ) + 1; - if ( FT_NEW_ARRAY( root->family_name, l ) ) + if ( FT_QALLOC( root->family_name, l ) ) goto Exit; ft_strcpy( root->family_name, foundry_prop->value.atom ); @@ -1542,7 +1536,7 @@ THE SOFTWARE. } else { - if ( FT_NEW_ARRAY( root->family_name, l ) ) + if ( FT_QALLOC( root->family_name, l ) ) goto Exit; ft_strcpy( root->family_name, prop->value.atom ); @@ -1566,7 +1560,7 @@ THE SOFTWARE. root->num_glyphs = (FT_Long)face->nmetrics; root->num_fixed_sizes = 1; - if ( FT_NEW_ARRAY( root->available_sizes, 1 ) ) + if ( FT_NEW( root->available_sizes ) ) goto Exit; { @@ -1574,8 +1568,6 @@ THE SOFTWARE. FT_Short resolution_x = 0, resolution_y = 0; - FT_ZERO( bsize ); - /* for simplicity, we take absolute values of integer properties */ #if 0 @@ -1616,7 +1608,7 @@ THE SOFTWARE. else { /* this is a heuristical value */ - bsize->width = (FT_Short)FT_MulDiv( bsize->height, 2, 3 ); + bsize->width = ( bsize->height * 2 + 1 ) / 3; } prop = pcf_find_property( face, "POINT_SIZE" ); diff --git a/lib/libesp32_lvgl/freetype/src/pcf/pcfutil.c b/lib/libesp32_lvgl/freetype/src/pcf/pcfutil.c index 5d3c00791..957572691 100644 --- a/lib/libesp32_lvgl/freetype/src/pcf/pcfutil.c +++ b/lib/libesp32_lvgl/freetype/src/pcf/pcfutil.c @@ -57,6 +57,34 @@ in this Software without prior written authorization from The Open Group. } +#if defined( __clang__ ) || \ + ( defined( __GNUC__ ) && \ + ( __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 8 ) ) ) + +#define BSWAP16( x ) __builtin_bswap16( x ) +#define BSWAP32( x ) __builtin_bswap32( x ) + +#elif defined( _MSC_VER ) && _MSC_VER >= 1300 + +#pragma intrinsic( _byteswap_ushort ) +#pragma intrinsic( _byteswap_ulong ) + +#define BSWAP16( x ) _byteswap_ushort( x ) +#define BSWAP32( x ) _byteswap_ulong( x ) + +#else + +#define BSWAP16( x ) \ + (FT_UInt16)( ( ( ( x ) >> 8 ) & 0xff ) | \ + ( ( ( x ) & 0xff ) << 8 ) ) +#define BSWAP32( x ) \ + (FT_UInt32)( ( ( ( x ) & 0xff000000u ) >> 24 ) | \ + ( ( ( x ) & 0x00ff0000u ) >> 8 ) | \ + ( ( ( x ) & 0x0000ff00u ) << 8 ) | \ + ( ( ( x ) & 0x000000ffu ) << 24 ) ) + +#endif + /* * Invert byte order within each 16-bits of an array. */ @@ -65,15 +93,11 @@ in this Software without prior written authorization from The Open Group. TwoByteSwap( unsigned char* buf, size_t nbytes ) { - for ( ; nbytes >= 2; nbytes -= 2, buf += 2 ) - { - unsigned char c; + FT_UInt16* b = (FT_UInt16*)buf; - c = buf[0]; - buf[0] = buf[1]; - buf[1] = c; - } + for ( ; nbytes >= 2; nbytes -= 2, b++ ) + *b = BSWAP16( *b ); } /* @@ -84,19 +108,11 @@ in this Software without prior written authorization from The Open Group. FourByteSwap( unsigned char* buf, size_t nbytes ) { - for ( ; nbytes >= 4; nbytes -= 4, buf += 4 ) - { - unsigned char c; + FT_UInt32* b = (FT_UInt32*)buf; - c = buf[0]; - buf[0] = buf[3]; - buf[3] = c; - - c = buf[1]; - buf[1] = buf[2]; - buf[2] = c; - } + for ( ; nbytes >= 4; nbytes -= 4, b++ ) + *b = BSWAP32( *b ); } diff --git a/lib/libesp32_lvgl/freetype/src/pfr/module.mk b/lib/libesp32_lvgl/freetype/src/pfr/module.mk index 762353dda..388a38ed0 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/module.mk +++ b/lib/libesp32_lvgl/freetype/src/pfr/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 2002-2020 by +# Copyright (C) 2002-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/pfr/pfr.c b/lib/libesp32_lvgl/freetype/src/pfr/pfr.c index 9264c77df..d3738152d 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/pfr.c +++ b/lib/libesp32_lvgl/freetype/src/pfr/pfr.c @@ -4,7 +4,7 @@ * * FreeType PFR driver component. * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/pfr/pfrcmap.c b/lib/libesp32_lvgl/freetype/src/pfr/pfrcmap.c index ebc7b8439..08fe41d54 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/pfrcmap.c +++ b/lib/libesp32_lvgl/freetype/src/pfr/pfrcmap.c @@ -4,7 +4,7 @@ * * FreeType PFR cmap handling (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -24,17 +24,18 @@ FT_CALLBACK_DEF( FT_Error ) - pfr_cmap_init( PFR_CMap cmap, + pfr_cmap_init( FT_CMap cmap, /* PFR_CMap */ FT_Pointer pointer ) { - FT_Error error = FT_Err_Ok; - PFR_Face face = (PFR_Face)FT_CMAP_FACE( cmap ); + PFR_CMap pfrcmap = (PFR_CMap)cmap; + FT_Error error = FT_Err_Ok; + PFR_Face face = (PFR_Face)FT_CMAP_FACE( cmap ); FT_UNUSED( pointer ); - cmap->num_chars = face->phy_font.num_chars; - cmap->chars = face->phy_font.chars; + pfrcmap->num_chars = face->phy_font.num_chars; + pfrcmap->chars = face->phy_font.chars; /* just for safety, check that the character entries are correctly */ /* sorted in increasing character code order */ @@ -42,9 +43,9 @@ FT_UInt n; - for ( n = 1; n < cmap->num_chars; n++ ) + for ( n = 1; n < pfrcmap->num_chars; n++ ) { - if ( cmap->chars[n - 1].char_code >= cmap->chars[n].char_code ) + if ( pfrcmap->chars[n - 1].char_code >= pfrcmap->chars[n].char_code ) { error = FT_THROW( Invalid_Table ); goto Exit; @@ -58,29 +59,30 @@ FT_CALLBACK_DEF( void ) - pfr_cmap_done( PFR_CMap cmap ) + pfr_cmap_done( FT_CMap cmap ) /* PFR_CMap */ { - cmap->chars = NULL; - cmap->num_chars = 0; + PFR_CMap pfrcmap = (PFR_CMap)cmap; + + + pfrcmap->chars = NULL; + pfrcmap->num_chars = 0; } FT_CALLBACK_DEF( FT_UInt ) - pfr_cmap_char_index( PFR_CMap cmap, + pfr_cmap_char_index( FT_CMap cmap, /* PFR_CMap */ FT_UInt32 char_code ) { - FT_UInt min = 0; - FT_UInt max = cmap->num_chars; + PFR_CMap pfrcmap = (PFR_CMap)cmap; + FT_UInt min = 0; + FT_UInt max = pfrcmap->num_chars; + FT_UInt mid = min + ( max - min ) / 2; + PFR_Char gchar; while ( min < max ) { - PFR_Char gchar; - FT_UInt mid; - - - mid = min + ( max - min ) / 2; - gchar = cmap->chars + mid; + gchar = pfrcmap->chars + mid; if ( gchar->char_code == char_code ) return mid + 1; @@ -89,15 +91,21 @@ min = mid + 1; else max = mid; + + /* reasonable prediction in a continuous block */ + mid += char_code - gchar->char_code; + if ( mid >= max || mid < min ) + mid = min + ( max - min ) / 2; } return 0; } - FT_CALLBACK_DEF( FT_UInt32 ) - pfr_cmap_char_next( PFR_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + pfr_cmap_char_next( FT_CMap cmap, /* PFR_CMap */ FT_UInt32 *pchar_code ) { + PFR_CMap pfrcmap = (PFR_CMap)cmap; FT_UInt result = 0; FT_UInt32 char_code = *pchar_code + 1; @@ -105,15 +113,14 @@ Restart: { FT_UInt min = 0; - FT_UInt max = cmap->num_chars; - FT_UInt mid; + FT_UInt max = pfrcmap->num_chars; + FT_UInt mid = min + ( max - min ) / 2; PFR_Char gchar; while ( min < max ) { - mid = min + ( ( max - min ) >> 1 ); - gchar = cmap->chars + mid; + gchar = pfrcmap->chars + mid; if ( gchar->char_code == char_code ) { @@ -132,14 +139,19 @@ min = mid + 1; else max = mid; + + /* reasonable prediction in a continuous block */ + mid += char_code - gchar->char_code; + if ( mid >= max || mid < min ) + mid = min + ( max - min ) / 2; } /* we didn't find it, but we have a pair just above it */ char_code = 0; - if ( min < cmap->num_chars ) + if ( min < pfrcmap->num_chars ) { - gchar = cmap->chars + min; + gchar = pfrcmap->chars + min; result = min; if ( result != 0 ) { diff --git a/lib/libesp32_lvgl/freetype/src/pfr/pfrcmap.h b/lib/libesp32_lvgl/freetype/src/pfr/pfrcmap.h index a6d920c30..8110f175e 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/pfrcmap.h +++ b/lib/libesp32_lvgl/freetype/src/pfr/pfrcmap.h @@ -4,7 +4,7 @@ * * FreeType PFR cmap handling (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/pfr/pfrdrivr.c b/lib/libesp32_lvgl/freetype/src/pfr/pfrdrivr.c index b14320875..0048f5241 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/pfrdrivr.c +++ b/lib/libesp32_lvgl/freetype/src/pfr/pfrdrivr.c @@ -4,7 +4,7 @@ * * FreeType PFR driver interface (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -27,16 +27,16 @@ FT_CALLBACK_DEF( FT_Error ) - pfr_get_kerning( FT_Face pfrface, /* PFR_Face */ + pfr_get_kerning( FT_Face face, /* PFR_Face */ FT_UInt left, FT_UInt right, FT_Vector *avector ) { - PFR_Face face = (PFR_Face)pfrface; - PFR_PhyFont phys = &face->phy_font; + PFR_Face pfrface = (PFR_Face)face; + PFR_PhyFont phys = &pfrface->phy_font; - (void)pfr_face_get_kerning( pfrface, left, right, avector ); + (void)pfr_face_get_kerning( face, left, right, avector ); /* convert from metrics to outline units when necessary */ if ( phys->outline_resolution != phys->metrics_resolution ) @@ -62,12 +62,12 @@ */ FT_CALLBACK_DEF( FT_Error ) - pfr_get_advance( FT_Face pfrface, /* PFR_Face */ + pfr_get_advance( FT_Face face, /* PFR_Face */ FT_UInt gindex, FT_Pos *anadvance ) { - PFR_Face face = (PFR_Face)pfrface; - FT_Error error = FT_ERR( Invalid_Argument ); + PFR_Face pfrface = (PFR_Face)face; + FT_Error error = FT_ERR( Invalid_Argument ); *anadvance = 0; @@ -77,9 +77,9 @@ gindex--; - if ( face ) + if ( pfrface ) { - PFR_PhyFont phys = &face->phy_font; + PFR_PhyFont phys = &pfrface->phy_font; if ( gindex < phys->num_chars ) @@ -95,16 +95,16 @@ FT_CALLBACK_DEF( FT_Error ) - pfr_get_metrics( FT_Face pfrface, /* PFR_Face */ + pfr_get_metrics( FT_Face face, /* PFR_Face */ FT_UInt *anoutline_resolution, FT_UInt *ametrics_resolution, FT_Fixed *ametrics_x_scale, FT_Fixed *ametrics_y_scale ) { - PFR_Face face = (PFR_Face)pfrface; - PFR_PhyFont phys = &face->phy_font; + PFR_Face pfrface = (PFR_Face)face; + PFR_PhyFont phys = &pfrface->phy_font; FT_Fixed x_scale, y_scale; - FT_Size size = face->root.size; + FT_Size size = pfrface->root.size; if ( anoutline_resolution ) diff --git a/lib/libesp32_lvgl/freetype/src/pfr/pfrdrivr.h b/lib/libesp32_lvgl/freetype/src/pfr/pfrdrivr.h index 7646b4d1b..da14468d4 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/pfrdrivr.h +++ b/lib/libesp32_lvgl/freetype/src/pfr/pfrdrivr.h @@ -4,7 +4,7 @@ * * High-level Type PFR driver interface (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/pfr/pfrerror.h b/lib/libesp32_lvgl/freetype/src/pfr/pfrerror.h index 33460ef4f..5dfb254d6 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/pfrerror.h +++ b/lib/libesp32_lvgl/freetype/src/pfr/pfrerror.h @@ -4,7 +4,7 @@ * * PFR error codes (specification only). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/pfr/pfrgload.c b/lib/libesp32_lvgl/freetype/src/pfr/pfrgload.c index aa640c3b0..48cf27ec8 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/pfrgload.c +++ b/lib/libesp32_lvgl/freetype/src/pfr/pfrgload.c @@ -4,7 +4,7 @@ * * FreeType PFR glyph loader (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -42,8 +42,7 @@ { FT_ZERO( glyph ); - glyph->loader = loader; - glyph->path_begun = 0; + glyph->loader = loader; FT_GlyphLoader_Rewind( loader ); } @@ -409,7 +408,7 @@ break; case 6: /* horizontal to vertical curve */ - FT_TRACE6(( "- hv curve " )); + FT_TRACE6(( "- hv curve" )); args_format = 0xB8E; args_count = 3; break; @@ -561,8 +560,7 @@ FT_Byte* limit ) { FT_Error error = FT_Err_Ok; - FT_GlyphLoader loader = glyph->loader; - FT_Memory memory = loader->memory; + FT_Memory memory = glyph->loader->memory; PFR_SubGlyph subglyph; FT_UInt flags, i, count, org_count; FT_Int x_pos, y_pos; diff --git a/lib/libesp32_lvgl/freetype/src/pfr/pfrgload.h b/lib/libesp32_lvgl/freetype/src/pfr/pfrgload.h index f356b4c75..92a59bc5d 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/pfrgload.h +++ b/lib/libesp32_lvgl/freetype/src/pfr/pfrgload.h @@ -4,7 +4,7 @@ * * FreeType PFR glyph loader (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/pfr/pfrload.c b/lib/libesp32_lvgl/freetype/src/pfr/pfrload.c index a2832e55c..856a5942f 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/pfrload.c +++ b/lib/libesp32_lvgl/freetype/src/pfr/pfrload.c @@ -4,7 +4,7 @@ * * FreeType PFR loader (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -268,9 +268,7 @@ header->version > 4 || header->header_size < 58 || header->signature2 != 0x0D0A ) /* CR/LF */ - { result = 0; - } return result; } @@ -406,11 +404,9 @@ } if ( flags & PFR_LOG_BOLD ) - { log_font->bold_thickness = ( flags & PFR_LOG_2BYTE_BOLD ) ? PFR_NEXT_SHORT( p ) : PFR_NEXT_BYTE( p ); - } if ( flags & PFR_LOG_EXTRA_ITEMS ) { @@ -453,15 +449,16 @@ /* load bitmap strikes lists */ FT_CALLBACK_DEF( FT_Error ) - pfr_extra_item_load_bitmap_info( FT_Byte* p, - FT_Byte* limit, - PFR_PhyFont phy_font ) + pfr_extra_item_load_bitmap_info( FT_Byte* p, + FT_Byte* limit, + void* phy_font_ ) { - FT_Memory memory = phy_font->memory; - PFR_Strike strike; - FT_UInt flags0; - FT_UInt n, count, size1; - FT_Error error = FT_Err_Ok; + PFR_PhyFont phy_font = (PFR_PhyFont)phy_font_; + FT_Memory memory = phy_font->memory; + PFR_Strike strike; + FT_UInt flags0; + FT_UInt n, count, size1; + FT_Error error = FT_Err_Ok; PFR_CHECK( 5 ); @@ -553,19 +550,20 @@ * family. */ FT_CALLBACK_DEF( FT_Error ) - pfr_extra_item_load_font_id( FT_Byte* p, - FT_Byte* limit, - PFR_PhyFont phy_font ) + pfr_extra_item_load_font_id( FT_Byte* p, + FT_Byte* limit, + void* phy_font_ ) { - FT_Error error = FT_Err_Ok; - FT_Memory memory = phy_font->memory; - FT_UInt len = (FT_UInt)( limit - p ); + PFR_PhyFont phy_font = (PFR_PhyFont)phy_font_; + FT_Error error = FT_Err_Ok; + FT_Memory memory = phy_font->memory; + FT_UInt len = (FT_UInt)( limit - p ); if ( phy_font->font_id ) goto Exit; - if ( FT_ALLOC( phy_font->font_id, len + 1 ) ) + if ( FT_QALLOC( phy_font->font_id, len + 1 ) ) goto Exit; /* copy font ID name, and terminate it for safety */ @@ -579,14 +577,15 @@ /* load stem snap tables */ FT_CALLBACK_DEF( FT_Error ) - pfr_extra_item_load_stem_snaps( FT_Byte* p, - FT_Byte* limit, - PFR_PhyFont phy_font ) + pfr_extra_item_load_stem_snaps( FT_Byte* p, + FT_Byte* limit, + void* phy_font_ ) { - FT_UInt count, num_vert, num_horz; - FT_Int* snaps = NULL; - FT_Error error = FT_Err_Ok; - FT_Memory memory = phy_font->memory; + PFR_PhyFont phy_font = (PFR_PhyFont)phy_font_; + FT_UInt count, num_vert, num_horz; + FT_Int* snaps = NULL; + FT_Error error = FT_Err_Ok; + FT_Memory memory = phy_font->memory; if ( phy_font->vertical.stem_snaps ) @@ -601,10 +600,10 @@ PFR_CHECK( count * 2 ); - if ( FT_NEW_ARRAY( snaps, count ) ) + if ( FT_QNEW_ARRAY( snaps, count ) ) goto Exit; - phy_font->vertical.stem_snaps = snaps; + phy_font->vertical.stem_snaps = snaps; phy_font->horizontal.stem_snaps = snaps + num_vert; for ( ; count > 0; count--, snaps++ ) @@ -621,13 +620,13 @@ } - /* load kerning pair data */ FT_CALLBACK_DEF( FT_Error ) - pfr_extra_item_load_kerning_pairs( FT_Byte* p, - FT_Byte* limit, - PFR_PhyFont phy_font ) + pfr_extra_item_load_kerning_pairs( FT_Byte* p, + FT_Byte* limit, + void* phy_font_ ) { + PFR_PhyFont phy_font = (PFR_PhyFont)phy_font_; PFR_KernItem item = NULL; FT_Error error = FT_Err_Ok; FT_Memory memory = phy_font->memory; @@ -720,10 +719,10 @@ static const PFR_ExtraItemRec pfr_phy_font_extra_items[] = { - { 1, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_bitmap_info }, - { 2, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_font_id }, - { 3, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_stem_snaps }, - { 4, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_kerning_pairs }, + { 1, pfr_extra_item_load_bitmap_info }, + { 2, pfr_extra_item_load_font_id }, + { 3, pfr_extra_item_load_stem_snaps }, + { 4, pfr_extra_item_load_kerning_pairs }, { 0, NULL } }; @@ -761,7 +760,7 @@ if ( ok ) { - if ( FT_ALLOC( result, len + 1 ) ) + if ( FT_QALLOC( result, len + 1 ) ) goto Exit; FT_MEM_COPY( result, p, len ); @@ -857,8 +856,16 @@ phy_font->bbox.yMax = PFR_NEXT_SHORT( p ); phy_font->flags = flags = PFR_NEXT_BYTE( p ); + if ( !phy_font->outline_resolution || + !phy_font->metrics_resolution ) + { + error = FT_THROW( Invalid_Table ); + FT_ERROR(( "pfr_phy_font_load: invalid resolution\n" )); + goto Fail; + } + /* get the standard advance for non-proportional fonts */ - if ( !(flags & PFR_PHY_PROPORTIONAL) ) + if ( !( flags & PFR_PHY_PROPORTIONAL ) ) { PFR_CHECK( 2 ); phy_font->standard_advance = PFR_NEXT_SHORT( p ); @@ -869,14 +876,13 @@ { error = pfr_extra_items_parse( &p, limit, pfr_phy_font_extra_items, phy_font ); - if ( error ) goto Fail; } /* In certain fonts, the auxiliary bytes contain interesting */ /* information. These are not in the specification but can be */ - /* guessed by looking at the content of a few PFR0 fonts. */ + /* guessed by looking at the content of a few 'PFR0' fonts. */ PFR_CHECK( 3 ); num_aux = PFR_NEXT_ULONG( p ); @@ -953,7 +959,7 @@ PFR_CHECK( count * 2 ); - if ( FT_NEW_ARRAY( phy_font->blue_values, count ) ) + if ( FT_QNEW_ARRAY( phy_font->blue_values, count ) ) goto Fail; for ( n = 0; n < count; n++ ) @@ -975,6 +981,13 @@ phy_font->num_chars = count = PFR_NEXT_USHORT( p ); phy_font->chars_offset = offset + (FT_Offset)( p - stream->cursor ); + if ( !phy_font->num_chars ) + { + error = FT_THROW( Invalid_Table ); + FT_ERROR(( "pfr_phy_font_load: no glyphs\n" )); + goto Fail; + } + Size = 1 + 1 + 2; if ( flags & PFR_PHY_2BYTE_CHARCODE ) Size += 1; @@ -993,7 +1006,7 @@ PFR_CHECK_SIZE( count * Size ); - if ( FT_NEW_ARRAY( phy_font->chars, count ) ) + if ( FT_QNEW_ARRAY( phy_font->chars, count ) ) goto Fail; for ( n = 0; n < count; n++ ) diff --git a/lib/libesp32_lvgl/freetype/src/pfr/pfrload.h b/lib/libesp32_lvgl/freetype/src/pfr/pfrload.h index 7615b9ce1..d7b20a457 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/pfrload.h +++ b/lib/libesp32_lvgl/freetype/src/pfr/pfrload.h @@ -4,7 +4,7 @@ * * FreeType PFR loader (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/pfr/pfrobjs.c b/lib/libesp32_lvgl/freetype/src/pfr/pfrobjs.c index 918e7fd49..8ef17c663 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/pfrobjs.c +++ b/lib/libesp32_lvgl/freetype/src/pfr/pfrobjs.c @@ -4,7 +4,7 @@ * * FreeType PFR object methods (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -50,14 +50,14 @@ if ( !face ) return; - memory = pfrface->driver->root.memory; + memory = pfrface->memory; /* we don't want dangling pointers */ pfrface->family_name = NULL; pfrface->style_name = NULL; /* finalize the physical font record */ - pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY( face ) ); + pfr_phy_font_done( &face->phy_font, memory ); /* no need to finalize the logical font or the header */ FT_FREE( pfrface->available_sizes ); @@ -83,7 +83,11 @@ /* load the header and check it */ error = pfr_header_load( &face->header, stream ); if ( error ) + { + FT_TRACE2(( " not a PFR font\n" )); + error = FT_THROW( Unknown_File_Format ); goto Exit; + } if ( !pfr_header_check( &face->header ) ) { @@ -126,14 +130,14 @@ if ( error ) goto Exit; - /* now load the physical font descriptor */ + /* load the physical font descriptor */ error = pfr_phy_font_load( &face->phy_font, stream, face->log_font.phys_offset, face->log_font.phys_size ); if ( error ) goto Exit; - /* now set up all root face fields */ + /* set up all root face fields */ { PFR_PhyFont phy_font = &face->phy_font; @@ -156,7 +160,7 @@ if ( nn == phy_font->num_chars ) { if ( phy_font->num_strikes > 0 ) - pfrface->face_flags = 0; /* not scalable */ + pfrface->face_flags &= ~FT_FACE_FLAG_SCALABLE; else { FT_ERROR(( "pfr_face_init: font doesn't contain glyphs\n" )); @@ -166,7 +170,7 @@ } } - if ( ( phy_font->flags & PFR_PHY_PROPORTIONAL ) == 0 ) + if ( !( phy_font->flags & PFR_PHY_PROPORTIONAL ) ) pfrface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; if ( phy_font->flags & PFR_PHY_VERTICAL ) @@ -203,17 +207,17 @@ pfrface->height = (FT_Short)( ( pfrface->units_per_EM * 12 ) / 10 ); if ( pfrface->height < pfrface->ascender - pfrface->descender ) - pfrface->height = (FT_Short)(pfrface->ascender - pfrface->descender); + pfrface->height = (FT_Short)( pfrface->ascender - pfrface->descender ); if ( phy_font->num_strikes > 0 ) { FT_UInt n, count = phy_font->num_strikes; FT_Bitmap_Size* size; PFR_Strike strike; - FT_Memory memory = pfrface->stream->memory; + FT_Memory memory = pfrface->memory; - if ( FT_NEW_ARRAY( pfrface->available_sizes, count ) ) + if ( FT_QNEW_ARRAY( pfrface->available_sizes, count ) ) goto Exit; size = pfrface->available_sizes; @@ -334,7 +338,7 @@ } /* try to load an embedded bitmap */ - if ( ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) == 0 ) + if ( !( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) ) { error = pfr_slot_load_bitmap( slot, @@ -482,17 +486,16 @@ kerning->x = 0; kerning->y = 0; - if ( glyph1 > 0 ) - glyph1--; + /* PFR indexing skips .notdef, which becomes UINT_MAX */ + glyph1--; + glyph2--; - if ( glyph2 > 0 ) - glyph2--; - - /* convert glyph indices to character codes */ - if ( glyph1 > phy_font->num_chars || - glyph2 > phy_font->num_chars ) + /* check the array bounds, .notdef is automatically out */ + if ( glyph1 >= phy_font->num_chars || + glyph2 >= phy_font->num_chars ) goto Exit; + /* convert glyph indices to character codes */ code1 = phy_font->chars[glyph1].char_code; code2 = phy_font->chars[glyph2].char_code; pair = PFR_KERN_INDEX( code1, code2 ); diff --git a/lib/libesp32_lvgl/freetype/src/pfr/pfrobjs.h b/lib/libesp32_lvgl/freetype/src/pfr/pfrobjs.h index 808822f1c..fcf8c3812 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/pfrobjs.h +++ b/lib/libesp32_lvgl/freetype/src/pfr/pfrobjs.h @@ -4,7 +4,7 @@ * * FreeType PFR object methods (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/pfr/pfrsbit.c b/lib/libesp32_lvgl/freetype/src/pfr/pfrsbit.c index a6691e6d1..46a988e8e 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/pfrsbit.c +++ b/lib/libesp32_lvgl/freetype/src/pfr/pfrsbit.c @@ -4,7 +4,7 @@ * * FreeType PFR bitmap loader (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -282,7 +282,7 @@ FT_ULong* found_offset, FT_ULong* found_size ) { - FT_UInt min, max, char_len; + FT_UInt min, max, mid, char_len; FT_Bool two = FT_BOOL( *flags & PFR_BITMAP_2BYTE_CHARCODE ); FT_Byte* buff; @@ -310,8 +310,8 @@ if ( lim > limit ) { FT_TRACE0(( "pfr_lookup_bitmap_data:" - " number of bitmap records too large,\n" - " " + " number of bitmap records too large,\n" )); + FT_TRACE0(( " " " thus ignoring all bitmaps in this strike\n" )); *flags &= ~PFR_BITMAP_VALID_CHARCODES; } @@ -328,8 +328,8 @@ if ( (FT_Long)code <= prev_code ) { FT_TRACE0(( "pfr_lookup_bitmap_data:" - " bitmap records are not sorted,\n" - " " + " bitmap records are not sorted,\n" )); + FT_TRACE0(( " " " thus ignoring all bitmaps in this strike\n" )); *flags &= ~PFR_BITMAP_VALID_CHARCODES; break; @@ -349,14 +349,14 @@ min = 0; max = count; + mid = min + ( max - min ) / 2; /* binary search */ while ( min < max ) { - FT_UInt mid, code; + FT_UInt code; - mid = ( min + max ) >> 1; buff = base + mid * char_len; if ( two ) @@ -370,6 +370,11 @@ min = mid + 1; else goto Found_It; + + /* reasonable prediction in a continuous block */ + mid += char_code - code; + if ( mid >= max || mid < min ) + mid = min + ( max - min ) / 2; } Fail: @@ -391,7 +396,7 @@ } - /* load bitmap metrics. `*padvance' must be set to the default value */ + /* load bitmap metrics. `*aadvance' must be set to the default value */ /* before calling this function */ /* */ static FT_Error @@ -575,7 +580,7 @@ /*************************************************************************/ /*************************************************************************/ - FT_LOCAL( FT_Error ) + FT_LOCAL_DEF( FT_Error ) pfr_slot_load_bitmap( PFR_Slot glyph, PFR_Size size, FT_UInt glyph_index, @@ -628,7 +633,7 @@ if ( strike->flags & PFR_BITMAP_3BYTE_OFFSET ) char_len += 1; - /* access data directly in the frame to speed lookups */ + /* access data directly in the frame to speed up lookups */ if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) || FT_FRAME_ENTER( char_len * strike->num_bitmaps ) ) goto Exit; @@ -744,8 +749,8 @@ ypos > FT_INT_MAX - (FT_Long)ysize || ypos + (FT_Long)ysize < FT_INT_MIN ) { - FT_TRACE1(( "pfr_slot_load_bitmap:" )); - FT_TRACE1(( "huge bitmap glyph %ldx%ld over FT_GlyphSlot\n", + FT_TRACE1(( "pfr_slot_load_bitmap:" + " huge bitmap glyph %ldx%ld over FT_GlyphSlot\n", xpos, ypos )); error = FT_THROW( Invalid_Pixel_Size ); } diff --git a/lib/libesp32_lvgl/freetype/src/pfr/pfrsbit.h b/lib/libesp32_lvgl/freetype/src/pfr/pfrsbit.h index 8cb0de0d2..3e1dba9ae 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/pfrsbit.h +++ b/lib/libesp32_lvgl/freetype/src/pfr/pfrsbit.h @@ -4,7 +4,7 @@ * * FreeType PFR bitmap loader (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/pfr/pfrtypes.h b/lib/libesp32_lvgl/freetype/src/pfr/pfrtypes.h index 06fb82d51..2f8909f06 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/pfrtypes.h +++ b/lib/libesp32_lvgl/freetype/src/pfr/pfrtypes.h @@ -4,7 +4,7 @@ * * FreeType PFR data structures (specification only). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -109,7 +109,7 @@ FT_BEGIN_HEADER #define PFR_BITMAP_2BYTE_SIZE 0x02U #define PFR_BITMAP_3BYTE_OFFSET 0x04U - /*not part of the specification but used for implementation */ + /* not part of the specification but used for implementation */ #define PFR_BITMAP_CHARCODES_VALIDATED 0x40U #define PFR_BITMAP_VALID_CHARCODES 0x80U diff --git a/lib/libesp32_lvgl/freetype/src/pfr/rules.mk b/lib/libesp32_lvgl/freetype/src/pfr/rules.mk index a1fe82baf..50695fd28 100644 --- a/lib/libesp32_lvgl/freetype/src/pfr/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/pfr/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 2002-2020 by +# Copyright (C) 2002-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/psaux/afmparse.c b/lib/libesp32_lvgl/freetype/src/psaux/afmparse.c index 2d6a0d9a1..db08941de 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/afmparse.c +++ b/lib/libesp32_lvgl/freetype/src/psaux/afmparse.c @@ -4,7 +4,7 @@ * * AFM parser (body). * - * Copyright (C) 2006-2020 by + * Copyright (C) 2006-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -27,6 +27,16 @@ #include "psauxerr.h" + /************************************************************************** + * + * The macro FT_COMPONENT is used in trace mode. It is an implicit + * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log + * messages during execution. + */ +#undef FT_COMPONENT +#define FT_COMPONENT afmparse + + /************************************************************************** * * AFM_Stream @@ -553,7 +563,7 @@ } - FT_LOCAL( void ) + FT_LOCAL_DEF( void ) afm_parser_done( AFM_Parser parser ) { FT_Memory memory = parser->memory; @@ -586,21 +596,39 @@ static FT_Error afm_parse_track_kern( AFM_Parser parser ) { - AFM_FontInfo fi = parser->FontInfo; + AFM_FontInfo fi = parser->FontInfo; + AFM_Stream stream = parser->stream; AFM_TrackKern tk; - char* key; - FT_Offset len; - int n = -1; - FT_Int tmp; + + char* key; + FT_Offset len; + int n = -1; + FT_Int tmp; if ( afm_parser_read_int( parser, &tmp ) ) goto Fail; if ( tmp < 0 ) + { + FT_ERROR(( "afm_parse_track_kern: invalid number of track kerns\n" )); goto Fail; + } fi->NumTrackKern = (FT_UInt)tmp; + FT_TRACE3(( "afm_parse_track_kern: %u track kern%s expected\n", + fi->NumTrackKern, + fi->NumTrackKern == 1 ? "" : "s" )); + + /* Rough sanity check: The minimum line length of the `TrackKern` */ + /* command is 20 characters (including the EOL character). */ + if ( (FT_ULong)( stream->limit - stream->cursor ) / 20 < + fi->NumTrackKern ) + { + FT_ERROR(( "afm_parse_track_kern:" + " number of track kern entries exceeds stream size\n" )); + goto Fail; + } if ( fi->NumTrackKern ) { @@ -623,7 +651,10 @@ n++; if ( n >= (int)fi->NumTrackKern ) - goto Fail; + { + FT_ERROR(( "afm_parse_track_kern: too many track kern data\n" )); + goto Fail; + } tk = fi->TrackKerns + n; @@ -633,7 +664,12 @@ shared_vals[3].type = AFM_VALUE_TYPE_FIXED; shared_vals[4].type = AFM_VALUE_TYPE_FIXED; if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 ) + { + FT_ERROR(( "afm_parse_track_kern:" + " insufficient number of parameters for entry %d\n", + n )); goto Fail; + } tk->degree = shared_vals[0].u.i; tk->min_ptsize = shared_vals[1].u.f; @@ -646,7 +682,19 @@ case AFM_TOKEN_ENDTRACKKERN: case AFM_TOKEN_ENDKERNDATA: case AFM_TOKEN_ENDFONTMETRICS: - fi->NumTrackKern = (FT_UInt)( n + 1 ); + tmp = n + 1; + if ( (FT_UInt)tmp != fi->NumTrackKern ) + { + FT_TRACE1(( "afm_parse_track_kern: %s%d track kern entr%s seen\n", + tmp == 0 ? "" : "only ", + tmp, + tmp == 1 ? "y" : "ies" )); + fi->NumTrackKern = (FT_UInt)tmp; + } + else + FT_TRACE3(( "afm_parse_track_kern: %d track kern entr%s seen\n", + tmp, + tmp == 1 ? "y" : "ies" )); return FT_Err_Ok; case AFM_TOKEN_UNKNOWN: @@ -667,7 +715,7 @@ /* compare two kerning pairs */ - FT_CALLBACK_DEF( int ) + FT_COMPARE_DEF( int ) afm_compare_kern_pairs( const void* a, const void* b ) { @@ -690,7 +738,8 @@ static FT_Error afm_parse_kern_pairs( AFM_Parser parser ) { - AFM_FontInfo fi = parser->FontInfo; + AFM_FontInfo fi = parser->FontInfo; + AFM_Stream stream = parser->stream; AFM_KernPair kp; char* key; FT_Offset len; @@ -702,9 +751,26 @@ goto Fail; if ( tmp < 0 ) + { + FT_ERROR(( "afm_parse_kern_pairs: invalid number of kern pairs\n" )); goto Fail; + } fi->NumKernPair = (FT_UInt)tmp; + FT_TRACE3(( "afm_parse_kern_pairs: %u kern pair%s expected\n", + fi->NumKernPair, + fi->NumKernPair == 1 ? "" : "s" )); + + /* Rough sanity check: The minimum line length of the `KP`, */ + /* `KPH`,`KPX`, and `KPY` commands is 10 characters (including */ + /* the EOL character). */ + if ( (FT_ULong)( stream->limit - stream->cursor ) / 10 < + fi->NumKernPair ) + { + FT_ERROR(( "afm_parse_kern_pairs:" + " number of kern pairs exceeds stream size\n" )); + goto Fail; + } if ( fi->NumKernPair ) { @@ -734,7 +800,10 @@ n++; if ( n >= (int)fi->NumKernPair ) + { + FT_ERROR(( "afm_parse_kern_pairs: too many kern pairs\n" )); goto Fail; + } kp = fi->KernPairs + n; @@ -744,7 +813,12 @@ shared_vals[3].type = AFM_VALUE_TYPE_INTEGER; r = afm_parser_read_vals( parser, shared_vals, 4 ); if ( r < 3 ) + { + FT_ERROR(( "afm_parse_kern_pairs:" + " insufficient number of parameters for entry %d\n", + n )); goto Fail; + } /* index values can't be negative */ kp->index1 = shared_vals[0].u.u; @@ -766,7 +840,20 @@ case AFM_TOKEN_ENDKERNPAIRS: case AFM_TOKEN_ENDKERNDATA: case AFM_TOKEN_ENDFONTMETRICS: - fi->NumKernPair = (FT_UInt)( n + 1 ); + tmp = n + 1; + if ( (FT_UInt)tmp != fi->NumKernPair ) + { + FT_TRACE1(( "afm_parse_kern_pairs: %s%d kern pair%s seen\n", + tmp == 0 ? "" : "only ", + tmp, + tmp == 1 ? "" : "s" )); + fi->NumKernPair = (FT_UInt)tmp; + } + else + FT_TRACE3(( "afm_parse_kern_pairs: %d kern pair%s seen\n", + tmp, + tmp == 1 ? "" : "s" )); + ft_qsort( fi->KernPairs, fi->NumKernPair, sizeof ( AFM_KernPairRec ), afm_compare_kern_pairs ); @@ -792,22 +879,43 @@ char* key; FT_Offset len; + int have_trackkern = 0; + int have_kernpairs = 0; + while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) { switch ( afm_tokenize( key, len ) ) { case AFM_TOKEN_STARTTRACKKERN: + if ( have_trackkern ) + { + FT_ERROR(( "afm_parse_kern_data:" + " invalid second horizontal track kern section\n" )); + goto Fail; + } + error = afm_parse_track_kern( parser ); if ( error ) return error; + + have_trackkern = 1; break; case AFM_TOKEN_STARTKERNPAIRS: case AFM_TOKEN_STARTKERNPAIRS0: + if ( have_kernpairs ) + { + FT_ERROR(( "afm_parse_kern_data:" + " invalid second horizontal kern pair section\n" )); + goto Fail; + } + error = afm_parse_kern_pairs( parser ); if ( error ) return error; + + have_kernpairs = 1; break; case AFM_TOKEN_ENDKERNDATA: @@ -953,7 +1061,7 @@ if ( error ) goto Fail; /* we only support kern data, so ... */ - /* fall through */ + FALL_THROUGH; case AFM_TOKEN_ENDFONTMETRICS: return FT_Err_Ok; @@ -978,7 +1086,7 @@ #else /* T1_CONFIG_OPTION_NO_AFM */ /* ANSI C doesn't like empty source files */ - typedef int _afm_parse_dummy; + typedef int afm_parse_dummy_; #endif /* T1_CONFIG_OPTION_NO_AFM */ diff --git a/lib/libesp32_lvgl/freetype/src/psaux/afmparse.h b/lib/libesp32_lvgl/freetype/src/psaux/afmparse.h index 16a3a3e90..2d3b6e6e1 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/afmparse.h +++ b/lib/libesp32_lvgl/freetype/src/psaux/afmparse.h @@ -4,7 +4,7 @@ * * AFM parser (specification). * - * Copyright (C) 2006-2020 by + * Copyright (C) 2006-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/psaux/cffdecode.c b/lib/libesp32_lvgl/freetype/src/psaux/cffdecode.c index 3d2da1e03..562d17d22 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/cffdecode.c +++ b/lib/libesp32_lvgl/freetype/src/psaux/cffdecode.c @@ -4,7 +4,7 @@ * * PostScript CFF (Type 2) decoding routines (body). * - * Copyright (C) 2017-2020 by + * Copyright (C) 2017-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -248,7 +248,7 @@ else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ { - CFF_Font cff = (CFF_Font)(face->extra.data); + CFF_Font cff = (CFF_Font)( face->extra.data ); bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar ); @@ -1871,7 +1871,7 @@ case cff_op_put: { FT_Fixed val = args[0]; - FT_Int idx = (FT_Int)( args[1] >> 16 ); + FT_UInt idx = (FT_UInt)( args[1] >> 16 ); FT_TRACE4(( " put\n" )); @@ -1880,20 +1880,20 @@ /* didn't give a hard-coded size limit of the temporary */ /* storage array; instead, an argument of the */ /* `MultipleMaster' operator set the size */ - if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS ) + if ( idx < CFF_MAX_TRANS_ELEMENTS ) decoder->buildchar[idx] = val; } break; case cff_op_get: { - FT_Int idx = (FT_Int)( args[0] >> 16 ); + FT_UInt idx = (FT_UInt)( args[0] >> 16 ); FT_Fixed val = 0; FT_TRACE4(( " get\n" )); - if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS ) + if ( idx < CFF_MAX_TRANS_ELEMENTS ) val = decoder->buildchar[idx]; args[0] = val; @@ -1914,9 +1914,9 @@ /* this operator was removed from the Type2 specification */ /* in version 16-March-2000 */ { - FT_Int reg_idx = (FT_Int)args[0]; - FT_Int idx = (FT_Int)args[1]; - FT_Int count = (FT_Int)args[2]; + FT_UInt reg_idx = (FT_UInt)args[0]; + FT_UInt idx = (FT_UInt)args[1]; + FT_UInt count = (FT_UInt)args[2]; FT_TRACE4(( " load\n" )); @@ -1924,11 +1924,11 @@ /* since we currently don't handle interpolation of multiple */ /* master fonts, we store a vector [1 0 0 ...] in the */ /* temporary storage array regardless of the Registry index */ - if ( reg_idx >= 0 && reg_idx <= 2 && - idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS && - count >= 0 && count <= num_axes ) + if ( reg_idx <= 2 && + idx < CFF_MAX_TRANS_ELEMENTS && + count <= num_axes ) { - FT_Int end, i; + FT_UInt end, i; end = FT_MIN( idx + count, CFF_MAX_TRANS_ELEMENTS ); @@ -2153,7 +2153,7 @@ decoder->locals_bias ); - FT_TRACE4(( " callsubr (idx %d, entering level %d)\n", + FT_TRACE4(( " callsubr (idx %d, entering level %td)\n", idx, zone - decoder->zones + 1 )); @@ -2197,7 +2197,7 @@ decoder->globals_bias ); - FT_TRACE4(( " callgsubr (idx %d, entering level %d)\n", + FT_TRACE4(( " callgsubr (idx %d, entering level %td)\n", idx, zone - decoder->zones + 1 )); @@ -2236,7 +2236,7 @@ break; case cff_op_return: - FT_TRACE4(( " return (leaving level %d)\n", + FT_TRACE4(( " return (leaving level %td)\n", decoder->zone - decoder->zones )); if ( decoder->zone <= decoder->zones ) @@ -2271,7 +2271,8 @@ } /* while ip < limit */ - FT_TRACE4(( "..end..\n\n" )); + FT_TRACE4(( "..end..\n" )); + FT_TRACE4(( "\n" )); Fail: return error; diff --git a/lib/libesp32_lvgl/freetype/src/psaux/cffdecode.h b/lib/libesp32_lvgl/freetype/src/psaux/cffdecode.h index 77a496269..e8bb4001c 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/cffdecode.h +++ b/lib/libesp32_lvgl/freetype/src/psaux/cffdecode.h @@ -4,7 +4,7 @@ * * PostScript CFF (Type 2) decoding routines (specification). * - * Copyright (C) 2017-2020 by + * Copyright (C) 2017-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/psaux/module.mk b/lib/libesp32_lvgl/freetype/src/psaux/module.mk index 651db0142..c6fb4eb50 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/module.mk +++ b/lib/libesp32_lvgl/freetype/src/psaux/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psarrst.c b/lib/libesp32_lvgl/freetype/src/psaux/psarrst.c index 8751d275f..70313d283 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psarrst.c +++ b/lib/libesp32_lvgl/freetype/src/psaux/psarrst.c @@ -65,7 +65,6 @@ arrstack->error = error; arrstack->sizeItem = sizeItem; arrstack->allocated = 0; - arrstack->chunk = 10; /* chunks of 10 items */ arrstack->count = 0; arrstack->totalSize = 0; arrstack->ptr = NULL; @@ -110,7 +109,7 @@ FT_ASSERT( newSize > 0 ); /* avoid realloc with zero size */ - if ( !FT_REALLOC( arrstack->ptr, arrstack->totalSize, newSize ) ) + if ( !FT_QREALLOC( arrstack->ptr, arrstack->totalSize, newSize ) ) { arrstack->allocated = numElements; arrstack->totalSize = newSize; @@ -216,9 +215,9 @@ if ( arrstack->count == arrstack->allocated ) { - /* grow the buffer by one chunk */ + /* increase the buffer size */ if ( !cf2_arrstack_setNumElements( - arrstack, arrstack->allocated + arrstack->chunk ) ) + arrstack, arrstack->allocated * 2 + 16 ) ) { /* on error, ignore the push */ return; diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psarrst.h b/lib/libesp32_lvgl/freetype/src/psaux/psarrst.h index 098617b25..31e5330cc 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psarrst.h +++ b/lib/libesp32_lvgl/freetype/src/psaux/psarrst.h @@ -55,7 +55,6 @@ FT_BEGIN_HEADER size_t sizeItem; /* bytes per element */ size_t allocated; /* items allocated */ - size_t chunk; /* allocation increment in items */ size_t count; /* number of elements allocated */ size_t totalSize; /* total bytes allocated */ diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psaux.c b/lib/libesp32_lvgl/freetype/src/psaux/psaux.c index f4282222a..5879ed163 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psaux.c +++ b/lib/libesp32_lvgl/freetype/src/psaux/psaux.c @@ -4,7 +4,7 @@ * * FreeType auxiliary PostScript driver component (body only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psauxerr.h b/lib/libesp32_lvgl/freetype/src/psaux/psauxerr.h index 8b9a958ae..895ffa48c 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psauxerr.h +++ b/lib/libesp32_lvgl/freetype/src/psaux/psauxerr.h @@ -4,7 +4,7 @@ * * PS auxiliary module error codes (specification only). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psauxmod.c b/lib/libesp32_lvgl/freetype/src/psaux/psauxmod.c index e73ba2245..45e35aa53 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psauxmod.c +++ b/lib/libesp32_lvgl/freetype/src/psaux/psauxmod.c @@ -4,7 +4,7 @@ * * FreeType auxiliary PostScript module implementation (body). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psauxmod.h b/lib/libesp32_lvgl/freetype/src/psaux/psauxmod.h index a6bebe4b9..94dbf4881 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psauxmod.h +++ b/lib/libesp32_lvgl/freetype/src/psaux/psauxmod.h @@ -4,7 +4,7 @@ * * FreeType auxiliary PostScript module implementation (specification). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psblues.c b/lib/libesp32_lvgl/freetype/src/psaux/psblues.c index 3878e9bde..f9c864fea 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psblues.c +++ b/lib/libesp32_lvgl/freetype/src/psaux/psblues.c @@ -506,7 +506,8 @@ /* guarantee minimum of 1 pixel overshoot */ dsNew = FT_MIN( cf2_fixedRound( bottomHintEdge->dsCoord ), - blues->zone[i].dsFlatEdge - cf2_intToFixed( 1 ) ); + SUB_INT32( blues->zone[i].dsFlatEdge, + cf2_intToFixed( 1 ) ) ); } else diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psconv.c b/lib/libesp32_lvgl/freetype/src/psaux/psconv.c index 4cf5cd5d8..b9c7138d8 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psconv.c +++ b/lib/libesp32_lvgl/freetype/src/psaux/psconv.c @@ -4,7 +4,7 @@ * * Some convenience conversions (body). * - * Copyright (C) 2006-2020 by + * Copyright (C) 2006-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -535,11 +535,11 @@ if ( r & 1 ) { - *buffer = (FT_Byte)(*buffer + c); + *buffer = (FT_Byte)( *buffer + c ); buffer++; } else - *buffer = (FT_Byte)(c << 4); + *buffer = (FT_Byte)( c << 4 ); r++; } @@ -572,8 +572,8 @@ if ( p >= limit ) return 0; - if ( n > (FT_UInt)(limit - p) ) - n = (FT_UInt)(limit - p); + if ( n > (FT_UInt)( limit - p ) ) + n = (FT_UInt)( limit - p ); for ( r = 0; r < n; r++ ) { diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psconv.h b/lib/libesp32_lvgl/freetype/src/psaux/psconv.h index 833e82736..b7c3ee00b 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psconv.h +++ b/lib/libesp32_lvgl/freetype/src/psaux/psconv.h @@ -4,7 +4,7 @@ * * Some convenience conversions (specification). * - * Copyright (C) 2006-2020 by + * Copyright (C) 2006-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psfixed.h b/lib/libesp32_lvgl/freetype/src/psaux/psfixed.h index 7dff9ef1b..299d07637 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psfixed.h +++ b/lib/libesp32_lvgl/freetype/src/psaux/psfixed.h @@ -2,7 +2,7 @@ * * psfixed.h * - * Adobe's code for Fixed Point Mathematics (specification only). + * Adobe's code for Fixed-Point Mathematics (specification only). * * Copyright 2007-2013 Adobe Systems Incorporated. * @@ -43,10 +43,10 @@ FT_BEGIN_HEADER - /* rasterizer integer and fixed point arithmetic must be 32-bit */ + /* rasterizer integer and fixed-point arithmetic must be 32-bit */ #define CF2_Fixed CF2_F16Dot16 - typedef FT_Int32 CF2_Frac; /* 2.30 fixed point */ + typedef FT_Int32 CF2_Frac; /* 2.30 fixed-point */ #define CF2_FIXED_MAX ( (CF2_Fixed)0x7FFFFFFFL ) diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psft.c b/lib/libesp32_lvgl/freetype/src/psaux/psft.c index 41c16542c..618864e6e 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psft.c +++ b/lib/libesp32_lvgl/freetype/src/psaux/psft.c @@ -68,11 +68,10 @@ CF2_Fixed maxScale; - FT_ASSERT( unitsPerEm > 0 ); - if ( transform->a <= 0 || transform->d <= 0 ) return FT_THROW( Invalid_Size_Handle ); + FT_ASSERT( unitsPerEm > 0 ); FT_ASSERT( transform->b == 0 && transform->c == 0 ); FT_ASSERT( transform->tx == 0 && transform->ty == 0 ); @@ -297,7 +296,6 @@ cf2_getUnitsPerEm( PS_Decoder* decoder ) { FT_ASSERT( decoder && decoder->builder.face ); - FT_ASSERT( decoder->builder.face->units_per_EM ); return decoder->builder.face->units_per_EM; } @@ -742,13 +740,13 @@ /* For ordinary fonts get the character data stored in the face record. */ { glyph_data.pointer = type1->charstrings[glyph_index]; - glyph_data.length = (FT_Int)type1->charstrings_len[glyph_index]; + glyph_data.length = type1->charstrings_len[glyph_index]; } if ( !error ) { FT_Byte* charstring_base = (FT_Byte*)glyph_data.pointer; - FT_ULong charstring_len = (FT_ULong)glyph_data.length; + FT_ULong charstring_len = glyph_data.length; FT_ASSERT( charstring_base + charstring_len >= charstring_base ); @@ -778,7 +776,7 @@ face = (T1_Face)decoder->builder.face; data.pointer = buf->start; - data.length = (FT_Int)( buf->end - buf->start ); + data.length = (FT_UInt)( buf->end - buf->start ); if ( face->root.internal->incremental_interface ) face->root.internal->incremental_interface->funcs->free_glyph_data( diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psglue.h b/lib/libesp32_lvgl/freetype/src/psaux/psglue.h index 022aafbfc..63085d71c 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psglue.h +++ b/lib/libesp32_lvgl/freetype/src/psaux/psglue.h @@ -72,7 +72,7 @@ FT_BEGIN_HEADER } CF2_PathOp; - /* a matrix of fixed point values */ + /* a matrix of fixed-point values */ typedef struct CF2_Matrix_ { CF2_F16Dot16 a; diff --git a/lib/libesp32_lvgl/freetype/src/psaux/pshints.c b/lib/libesp32_lvgl/freetype/src/psaux/pshints.c index ce8cfca71..7bd08a9c9 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/pshints.c +++ b/lib/libesp32_lvgl/freetype/src/psaux/pshints.c @@ -310,7 +310,7 @@ CF2_Hint hint = &hintmap->edge[i]; - FT_TRACE6(( " %3ld %7.2f %7.2f %5d %s%s%s%s\n", + FT_TRACE6(( " %3zu %7.2f %7.2f %5d %s%s%s%s\n", hint->index, hint->csCoord / 65536.0, hint->dsCoord / ( hint->scale * 1.0 ), @@ -412,6 +412,12 @@ { FT_Bool isPair = cf2_hint_isPair( &hintmap->edge[i] ); + /* final amount to move edge or edge pair */ + CF2_Fixed move = 0; + + CF2_Fixed dsCoord_i; + CF2_Fixed dsCoord_j; + /* index of upper edge (same value for ghost hint) */ j = isPair ? i + 1 : i; @@ -422,11 +428,14 @@ FT_ASSERT( cf2_hint_isLocked( &hintmap->edge[i] ) == cf2_hint_isLocked( &hintmap->edge[j] ) ); + dsCoord_i = hintmap->edge[i].dsCoord; + dsCoord_j = hintmap->edge[j].dsCoord; + if ( !cf2_hint_isLocked( &hintmap->edge[i] ) ) { /* hint edge is not locked, we can adjust it */ - CF2_Fixed fracDown = cf2_fixedFraction( hintmap->edge[i].dsCoord ); - CF2_Fixed fracUp = cf2_fixedFraction( hintmap->edge[j].dsCoord ); + CF2_Fixed fracDown = cf2_fixedFraction( dsCoord_i ); + CF2_Fixed fracUp = cf2_fixedFraction( dsCoord_j ); /* calculate all four possibilities; moves down are negative */ CF2_Fixed downMoveDown = 0 - fracDown; @@ -443,9 +452,6 @@ /* smallest move down */ CF2_Fixed moveDown = FT_MAX( downMoveDown, upMoveDown ); - /* final amount to move edge or edge pair */ - CF2_Fixed move; - CF2_Fixed downMinCounter = CF2_MIN_COUNTER; CF2_Fixed upMinCounter = CF2_MIN_COUNTER; FT_Bool saveEdge = FALSE; @@ -467,16 +473,14 @@ /* is there room to move up? */ /* there is if we are at top of array or the next edge is at or */ /* beyond proposed move up? */ - if ( j >= hintmap->count - 1 || + if ( j >= hintmap->count - 1 || hintmap->edge[j + 1].dsCoord >= - ADD_INT32( hintmap->edge[j].dsCoord, - moveUp + upMinCounter ) ) + ADD_INT32( dsCoord_j, moveUp + upMinCounter ) ) { /* there is room to move up; is there also room to move down? */ - if ( i == 0 || + if ( i == 0 || hintmap->edge[i - 1].dsCoord <= - ADD_INT32( hintmap->edge[i].dsCoord, - moveDown - downMinCounter ) ) + ADD_INT32( dsCoord_i, moveDown - downMinCounter ) ) { /* move smaller absolute amount */ move = ( -moveDown < moveUp ) ? moveDown : moveUp; /* optimum */ @@ -487,10 +491,9 @@ else { /* is there room to move down? */ - if ( i == 0 || + if ( i == 0 || hintmap->edge[i - 1].dsCoord <= - ADD_INT32( hintmap->edge[i].dsCoord, - moveDown - downMinCounter ) ) + ADD_INT32( dsCoord_i, moveDown - downMinCounter ) ) { move = moveDown; /* true if non-optimum move */ @@ -524,17 +527,21 @@ } /* move the edge(s) */ - hintmap->edge[i].dsCoord = ADD_INT32( hintmap->edge[i].dsCoord, - move ); + hintmap->edge[i].dsCoord = ADD_INT32( dsCoord_i, move ); if ( isPair ) - hintmap->edge[j].dsCoord = ADD_INT32( hintmap->edge[j].dsCoord, - move ); + hintmap->edge[j].dsCoord = ADD_INT32( dsCoord_j, move ); } - /* assert there are no overlaps in device space */ + /* assert there are no overlaps in device space; */ + /* ignore tests if there was overflow (that is, if */ + /* operands have the same sign but the sum does not) */ FT_ASSERT( i == 0 || + ( ( dsCoord_i ^ move ) >= 0 && + ( dsCoord_i ^ hintmap->edge[i].dsCoord ) < 0 ) || hintmap->edge[i - 1].dsCoord <= hintmap->edge[i].dsCoord ); FT_ASSERT( i < j || + ( ( dsCoord_j ^ move ) >= 0 && + ( dsCoord_j ^ hintmap->edge[j].dsCoord ) < 0 ) || hintmap->edge[i].dsCoord <= hintmap->edge[j].dsCoord ); /* adjust the scales, avoiding divide by zero */ @@ -686,8 +693,10 @@ CF2_Fixed midpoint = cf2_hintmap_map( hintmap->initialHintMap, - ADD_INT32( secondHintEdge->csCoord, - firstHintEdge->csCoord ) / 2 ); + ADD_INT32( + firstHintEdge->csCoord, + SUB_INT32 ( secondHintEdge->csCoord, + firstHintEdge->csCoord ) / 2 ) ); CF2_Fixed halfWidth = FT_MulFix( SUB_INT32( secondHintEdge->csCoord, firstHintEdge->csCoord ) / 2, @@ -1022,10 +1031,17 @@ } } - FT_TRACE6(( "%s\n", initialMap ? "flags: [p]air [g]host [t]op" - " [b]ottom [L]ocked [S]ynthetic\n" - "Initial hintmap" - : "Hints:" )); +#ifdef FT_DEBUG_LEVEL_TRACE + if ( initialMap ) + { + FT_TRACE6(( "flags: [p]air [g]host [t]op" + " [b]ottom [L]ocked [S]ynthetic\n" )); + FT_TRACE6(( "Initial hintmap:\n" )); + } + else + FT_TRACE6(( "Hints:\n" )); +#endif + cf2_hintmap_dump( hintmap ); /* @@ -1040,7 +1056,7 @@ /* adjust positions of hint edges that are not locked to blue zones */ cf2_hintmap_adjustHints( hintmap ); - FT_TRACE6(( "(adjusted)\n" )); + FT_TRACE6(( "Hints adjusted:\n" )); cf2_hintmap_dump( hintmap ); /* save the position of all hints that were used in this hint map; */ diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psintrp.c b/lib/libesp32_lvgl/freetype/src/psaux/psintrp.c index 519c69444..6c640eebd 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psintrp.c +++ b/lib/libesp32_lvgl/freetype/src/psaux/psintrp.c @@ -469,7 +469,7 @@ */ FT_LOCAL_DEF( void ) cf2_interpT2CharString( CF2_Font font, - CF2_Buffer buf, + const CF2_Buffer buf, CF2_OutlineCallbacks callbacks, const FT_Vector* translation, FT_Bool doingSeac, @@ -1340,9 +1340,9 @@ if ( decoder->glyph_names == 0 ) #endif /* FT_CONFIG_OPTION_INCREMENTAL */ { - FT_ERROR(( - "cf2_interpT2CharString: (Type 1 seac)" - " glyph names table not available in this font\n" )); + FT_ERROR(( "cf2_interpT2CharString:\n" )); + FT_ERROR(( " (Type 1 seac) glyph names table" + " not available in this font\n" )); lastError = FT_THROW( Invalid_Glyph_Format ); goto exit; } @@ -1368,9 +1368,9 @@ if ( bchar_index < 0 || achar_index < 0 ) { - FT_ERROR(( - "cf2_interpT2CharString: (Type 1 seac)" - " invalid seac character code arguments\n" )); + FT_ERROR(( "cf2_interpT2CharString:\n" )); + FT_ERROR(( " (Type 1 seac) invalid" + " seac character code arguments\n" )); lastError = FT_THROW( Invalid_Glyph_Format ); goto exit; } @@ -1670,7 +1670,13 @@ */ count = cf2_stack_count( opStack ); - FT_ASSERT( (CF2_UInt)arg_cnt <= count ); + if ( (CF2_UInt)arg_cnt > count ) + { + FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" + " stack underflow\n" )); + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } opIdx += count - (CF2_UInt)arg_cnt; @@ -1893,24 +1899,25 @@ /* cvi( ) of BuildCharArray with */ /* WeightVector */ { - FT_Int idx; - PS_Blend blend = decoder->blend; + FT_UInt idx; + PS_Blend blend = decoder->blend; + FT_UInt len_buildchar = decoder->len_buildchar; if ( arg_cnt != 1 || !blend ) goto Unexpected_OtherSubr; - idx = cf2_stack_popInt( opStack ); + idx = (FT_UInt)cf2_stack_popInt( opStack ); - if ( idx < 0 || - (FT_UInt)idx + blend->num_designs > - decoder->len_buildchar ) + if ( len_buildchar < blend->num_designs || + len_buildchar - blend->num_designs < idx ) goto Unexpected_OtherSubr; - ft_memcpy( &decoder->buildchar[idx], - blend->weight_vector, - blend->num_designs * - sizeof ( blend->weight_vector[0] ) ); + if ( decoder->buildchar && blend->weight_vector ) + ft_memcpy( &decoder->buildchar[idx], + blend->weight_vector, + blend->num_designs * + sizeof ( blend->weight_vector[0] ) ); } break; @@ -2004,17 +2011,16 @@ /* 2 24 callothersubr */ /* ==> set BuildCharArray[cvi( )] = */ { - CF2_Int idx; + CF2_UInt idx; PS_Blend blend = decoder->blend; if ( arg_cnt != 2 || !blend ) goto Unexpected_OtherSubr; - idx = cf2_stack_popInt( opStack ); + idx = (CF2_UInt)cf2_stack_popInt( opStack ); - if ( idx < 0 || - (FT_UInt)idx >= decoder->len_buildchar ) + if ( idx >= decoder->len_buildchar ) goto Unexpected_OtherSubr; decoder->buildchar[idx] = @@ -2027,17 +2033,16 @@ /* ==> push BuildCharArray[cvi( idx )] */ /* onto T1 stack */ { - CF2_Int idx; + CF2_UInt idx; PS_Blend blend = decoder->blend; if ( arg_cnt != 1 || !blend ) goto Unexpected_OtherSubr; - idx = cf2_stack_popInt( opStack ); + idx = (CF2_UInt)cf2_stack_popInt( opStack ); - if ( idx < 0 || - (FT_UInt)idx >= decoder->len_buildchar ) + if ( idx >= decoder->len_buildchar ) goto Unexpected_OtherSubr; cf2_stack_pushFixed( opStack, @@ -2179,29 +2184,29 @@ case cf2_escPUT: { CF2_F16Dot16 val; - CF2_Int idx; + CF2_UInt idx; FT_TRACE4(( " put\n" )); - idx = cf2_stack_popInt( opStack ); + idx = (CF2_UInt)cf2_stack_popInt( opStack ); val = cf2_stack_popFixed( opStack ); - if ( idx >= 0 && idx < CF2_STORAGE_SIZE ) + if ( idx < CF2_STORAGE_SIZE ) storage[idx] = val; } continue; /* do not clear the stack */ case cf2_escGET: { - CF2_Int idx; + CF2_UInt idx; FT_TRACE4(( " get\n" )); - idx = cf2_stack_popInt( opStack ); + idx = (CF2_UInt)cf2_stack_popInt( opStack ); - if ( idx >= 0 && idx < CF2_STORAGE_SIZE ) + if ( idx < CF2_STORAGE_SIZE ) cf2_stack_pushFixed( opStack, storage[idx] ); } continue; /* do not clear the stack */ diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psintrp.h b/lib/libesp32_lvgl/freetype/src/psaux/psintrp.h index 669c09c0a..d8b9342ec 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psintrp.h +++ b/lib/libesp32_lvgl/freetype/src/psaux/psintrp.h @@ -65,7 +65,7 @@ FT_BEGIN_HEADER FT_LOCAL( void ) cf2_interpT2CharString( CF2_Font font, - CF2_Buffer charstring, + const CF2_Buffer buf, CF2_OutlineCallbacks callbacks, const FT_Vector* translation, FT_Bool doingSeac, diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psobjs.c b/lib/libesp32_lvgl/freetype/src/psaux/psobjs.c index defc4d4fc..8da755d0e 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psobjs.c +++ b/lib/libesp32_lvgl/freetype/src/psaux/psobjs.c @@ -4,7 +4,7 @@ * * Auxiliary functions for PostScript fonts (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -84,7 +84,6 @@ table->max_elems = count; table->init = 0xDEADBEEFUL; - table->num_elems = 0; table->block = NULL; table->capacity = 0; table->cursor = 0; @@ -99,45 +98,31 @@ } - static void - shift_elements( PS_Table table, - FT_Byte* old_base ) - { - FT_PtrDist delta = table->block - old_base; - FT_Byte** offset = table->elements; - FT_Byte** limit = offset + table->max_elems; - - - for ( ; offset < limit; offset++ ) - { - if ( offset[0] ) - offset[0] += delta; - } - } - - static FT_Error - reallocate_t1_table( PS_Table table, - FT_Offset new_size ) + ps_table_realloc( PS_Table table, + FT_Offset new_size ) { FT_Memory memory = table->memory; FT_Byte* old_base = table->block; FT_Error error; - /* allocate new base block */ - if ( FT_ALLOC( table->block, new_size ) ) - { - table->block = old_base; + /* (re)allocate the base block */ + if ( FT_REALLOC( table->block, table->capacity, new_size ) ) return error; - } - /* copy elements and shift offsets */ - if ( old_base ) + /* rebase offsets if necessary */ + if ( old_base && table->block != old_base ) { - FT_MEM_COPY( table->block, old_base, table->capacity ); - shift_elements( table, old_base ); - FT_FREE( old_base ); + FT_Byte** offset = table->elements; + FT_Byte** limit = offset + table->max_elems; + + + for ( ; offset < limit; offset++ ) + { + if ( *offset ) + *offset = table->block + ( *offset - old_base ); + } } table->capacity = new_size; @@ -204,7 +189,7 @@ new_size = FT_PAD_CEIL( new_size, 1024 ); } - error = reallocate_t1_table( table, new_size ); + error = ps_table_realloc( table, new_size ); if ( error ) return error; @@ -234,32 +219,12 @@ * @InOut: * table :: * The target table. - * - * @Note: - * This function does NOT release the heap's memory block. It is up - * to the caller to clean it, or reference it in its own structures. */ FT_LOCAL_DEF( void ) ps_table_done( PS_Table table ) { - FT_Memory memory = table->memory; - FT_Error error; - FT_Byte* old_base = table->block; - - - /* should never fail, because rec.cursor <= rec.size */ - if ( !old_base ) - return; - - if ( FT_ALLOC( table->block, table->cursor ) ) - return; - FT_MEM_COPY( table->block, old_base, table->cursor ); - shift_elements( table, old_base ); - - table->capacity = table->cursor; - FT_FREE( old_base ); - - FT_UNUSED( error ); + /* no problem if shrinking fails */ + ps_table_realloc( table, table->cursor ); } @@ -269,7 +234,7 @@ FT_Memory memory = table->memory; - if ( (FT_ULong)table->init == 0xDEADBEEFUL ) + if ( table->init == 0xDEADBEEFUL ) { FT_FREE( table->block ); FT_FREE( table->elements ); @@ -552,7 +517,7 @@ if ( *cur == '<' ) /* <...> */ { - if ( cur + 1 < limit && *(cur + 1) == '<' ) /* << */ + if ( cur + 1 < limit && *( cur + 1 ) == '<' ) /* << */ { cur++; cur++; @@ -595,10 +560,10 @@ if ( cur < limit && cur == parser->cursor ) { FT_ERROR(( "ps_parser_skip_PS_token:" - " current token is `%c' which is self-delimiting\n" - " " - " but invalid at this point\n", + " current token is `%c' which is self-delimiting\n", *cur )); + FT_ERROR(( " " + " but invalid at this point\n" )); error = FT_THROW( Invalid_File_Format ); } @@ -979,7 +944,7 @@ } len = (FT_UInt)( cur - *cursor ); - if ( cur >= limit || FT_ALLOC( result, len + 1 ) ) + if ( cur >= limit || FT_QALLOC( result, len + 1 ) ) return 0; /* now copy the string */ @@ -1098,7 +1063,6 @@ { FT_Byte* q = (FT_Byte*)objects[idx] + field->offset; FT_Long val; - FT_String* string = NULL; skip_spaces( &cur, limit ); @@ -1148,8 +1112,9 @@ case T1_FIELD_TYPE_STRING: case T1_FIELD_TYPE_KEY: { - FT_Memory memory = parser->memory; - FT_UInt len = (FT_UInt)( limit - cur ); + FT_Memory memory = parser->memory; + FT_UInt len = (FT_UInt)( limit - cur ); + FT_String* string = NULL; if ( cur >= limit ) @@ -1175,8 +1140,8 @@ else { FT_ERROR(( "ps_parser_load_field:" - " expected a name or string\n" - " " + " expected a name or string\n" )); + FT_ERROR(( " " " but found token of type %d instead\n", token.type )); error = FT_THROW( Invalid_File_Format ); @@ -1190,10 +1155,9 @@ FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n", field->ident )); FT_FREE( *(FT_String**)q ); - *(FT_String**)q = NULL; } - if ( FT_ALLOC( string, len + 1 ) ) + if ( FT_QALLOC( string, len + 1 ) ) goto Exit; FT_MEM_COPY( string, cur, len ); @@ -1248,7 +1212,7 @@ FT_UInt i; - if ( FT_NEW_ARRAY( temp, max_objects * 4 ) ) + if ( FT_QNEW_ARRAY( temp, max_objects * 4 ) ) goto Exit; for ( i = 0; i < 4; i++ ) @@ -1258,14 +1222,14 @@ if ( result < 0 || (FT_UInt)result < max_objects ) { FT_ERROR(( "ps_parser_load_field:" - " expected %d integer%s in the %s subarray\n" - " " - " of /FontBBox in the /Blend dictionary\n", + " expected %d integer%s in the %s subarray\n", max_objects, max_objects > 1 ? "s" : "", i == 0 ? "first" : ( i == 1 ? "second" : ( i == 2 ? "third" : "fourth" ) ) )); + FT_ERROR(( " " + " of /FontBBox in the /Blend dictionary\n" )); error = FT_THROW( Invalid_File_Format ); FT_FREE( temp ); diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psobjs.h b/lib/libesp32_lvgl/freetype/src/psaux/psobjs.h index fdad672b6..d5bce5410 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psobjs.h +++ b/lib/libesp32_lvgl/freetype/src/psaux/psobjs.h @@ -4,7 +4,7 @@ * * Auxiliary functions for PostScript fonts (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psstack.c b/lib/libesp32_lvgl/freetype/src/psaux/psstack.c index 7ae5256ef..797486588 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psstack.c +++ b/lib/libesp32_lvgl/freetype/src/psaux/psstack.c @@ -54,20 +54,18 @@ FT_Error* e, FT_UInt stackSize ) { - FT_Error error = FT_Err_Ok; /* for FT_NEW */ - + FT_Error error; /* for FT_QNEW */ CF2_Stack stack = NULL; - if ( FT_NEW( stack ) ) + if ( FT_QNEW( stack ) ) return NULL; - /* initialize the structure; FT_NEW zeroes it */ stack->memory = memory; stack->error = e; /* allocate the stack buffer */ - if ( FT_NEW_ARRAY( stack->buffer, stackSize ) ) + if ( FT_QNEW_ARRAY( stack->buffer, stackSize ) ) { FT_FREE( stack ); return NULL; diff --git a/lib/libesp32_lvgl/freetype/src/psaux/psstack.h b/lib/libesp32_lvgl/freetype/src/psaux/psstack.h index b9ef9edf1..907b42400 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/psstack.h +++ b/lib/libesp32_lvgl/freetype/src/psaux/psstack.h @@ -49,8 +49,8 @@ FT_BEGIN_HEADER { union { - CF2_Fixed r; /* 16.16 fixed point */ - CF2_Frac f; /* 2.30 fixed point (for font matrix) */ + CF2_Fixed r; /* 16.16 fixed-point */ + CF2_Frac f; /* 2.30 fixed-point (for font matrix) */ CF2_Int i; } u; diff --git a/lib/libesp32_lvgl/freetype/src/psaux/rules.mk b/lib/libesp32_lvgl/freetype/src/psaux/rules.mk index f49aecbc7..d542ab8ee 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/psaux/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/psaux/t1cmap.c b/lib/libesp32_lvgl/freetype/src/psaux/t1cmap.c index e21e93ca2..c4bcf599e 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/t1cmap.c +++ b/lib/libesp32_lvgl/freetype/src/psaux/t1cmap.c @@ -4,7 +4,7 @@ * * Type 1 character map support (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -50,8 +50,11 @@ FT_CALLBACK_DEF( void ) - t1_cmap_std_done( T1_CMapStd cmap ) + t1_cmap_std_done( FT_CMap cmap_ ) /* T1_CMapStd */ { + T1_CMapStd cmap = (T1_CMapStd)cmap_; + + cmap->num_glyphs = 0; cmap->glyph_names = NULL; cmap->sid_to_string = NULL; @@ -60,10 +63,11 @@ FT_CALLBACK_DEF( FT_UInt ) - t1_cmap_std_char_index( T1_CMapStd cmap, - FT_UInt32 char_code ) + t1_cmap_std_char_index( FT_CMap cmap, /* T1_CMapStd */ + FT_UInt32 char_code ) { - FT_UInt result = 0; + T1_CMapStd t1cmap = (T1_CMapStd)cmap; + FT_UInt result = 0; if ( char_code < 256 ) @@ -73,13 +77,13 @@ /* convert character code to Adobe SID string */ - code = cmap->code_to_sid[char_code]; - glyph_name = cmap->sid_to_string( code ); + code = t1cmap->code_to_sid[char_code]; + glyph_name = t1cmap->sid_to_string( code ); /* look for the corresponding glyph name */ - for ( n = 0; n < cmap->num_glyphs; n++ ) + for ( n = 0; n < t1cmap->num_glyphs; n++ ) { - const char* gname = cmap->glyph_names[n]; + const char* gname = t1cmap->glyph_names[n]; if ( gname && gname[0] == glyph_name[0] && @@ -95,9 +99,9 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - t1_cmap_std_char_next( T1_CMapStd cmap, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + t1_cmap_std_char_next( FT_CMap cmap, + FT_UInt32 *pchar_code ) { FT_UInt result = 0; FT_UInt32 char_code = *pchar_code + 1; @@ -120,13 +124,14 @@ FT_CALLBACK_DEF( FT_Error ) - t1_cmap_standard_init( T1_CMapStd cmap, + t1_cmap_standard_init( FT_CMap cmap, /* T1_CMapStd */ FT_Pointer pointer ) { + T1_CMapStd t1cmap = (T1_CMapStd)cmap; FT_UNUSED( pointer ); - t1_cmap_std_init( cmap, 0 ); + t1_cmap_std_init( t1cmap, 0 ); return 0; } @@ -150,13 +155,14 @@ FT_CALLBACK_DEF( FT_Error ) - t1_cmap_expert_init( T1_CMapStd cmap, + t1_cmap_expert_init( FT_CMap cmap, /* T1_CMapStd */ FT_Pointer pointer ) { + T1_CMapStd t1cmap = (T1_CMapStd)cmap; FT_UNUSED( pointer ); - t1_cmap_std_init( cmap, 1 ); + t1_cmap_std_init( t1cmap, 1 ); return 0; } @@ -188,20 +194,21 @@ FT_CALLBACK_DEF( FT_Error ) - t1_cmap_custom_init( T1_CMapCustom cmap, - FT_Pointer pointer ) + t1_cmap_custom_init( FT_CMap cmap, /* T1_CMapCustom */ + FT_Pointer pointer ) { - T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); - T1_Encoding encoding = &face->type1.encoding; + T1_CMapCustom t1cmap = (T1_CMapCustom)cmap; + T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); + T1_Encoding encoding = &face->type1.encoding; FT_UNUSED( pointer ); - cmap->first = (FT_UInt)encoding->code_first; - cmap->count = (FT_UInt)encoding->code_last - cmap->first; - cmap->indices = encoding->char_index; + t1cmap->first = (FT_UInt)encoding->code_first; + t1cmap->count = (FT_UInt)encoding->code_last - t1cmap->first; + t1cmap->indices = encoding->char_index; - FT_ASSERT( cmap->indices ); + FT_ASSERT( t1cmap->indices ); FT_ASSERT( encoding->code_first <= encoding->code_last ); return 0; @@ -209,45 +216,50 @@ FT_CALLBACK_DEF( void ) - t1_cmap_custom_done( T1_CMapCustom cmap ) + t1_cmap_custom_done( FT_CMap cmap ) /* T1_CMapCustom */ { - cmap->indices = NULL; - cmap->first = 0; - cmap->count = 0; + T1_CMapCustom t1cmap = (T1_CMapCustom)cmap; + + + t1cmap->indices = NULL; + t1cmap->first = 0; + t1cmap->count = 0; } FT_CALLBACK_DEF( FT_UInt ) - t1_cmap_custom_char_index( T1_CMapCustom cmap, - FT_UInt32 char_code ) + t1_cmap_custom_char_index( FT_CMap cmap, /* T1_CMapCustom */ + FT_UInt32 char_code ) { - FT_UInt result = 0; + T1_CMapCustom t1cmap = (T1_CMapCustom)cmap; + FT_UInt result = 0; - if ( ( char_code >= cmap->first ) && - ( char_code < ( cmap->first + cmap->count ) ) ) - result = cmap->indices[char_code]; + if ( char_code >= t1cmap->first && + char_code < ( t1cmap->first + t1cmap->count ) ) + result = t1cmap->indices[char_code]; return result; } - FT_CALLBACK_DEF( FT_UInt32 ) - t1_cmap_custom_char_next( T1_CMapCustom cmap, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + t1_cmap_custom_char_next( FT_CMap cmap, /* T1_CMapCustom */ + FT_UInt32 *pchar_code ) { - FT_UInt result = 0; - FT_UInt32 char_code = *pchar_code; + T1_CMapCustom t1cmap = (T1_CMapCustom)cmap; + FT_UInt result = 0; + FT_UInt32 char_code = *pchar_code; char_code++; - if ( char_code < cmap->first ) - char_code = cmap->first; + if ( char_code < t1cmap->first ) + char_code = t1cmap->first; - for ( ; char_code < ( cmap->first + cmap->count ); char_code++ ) + for ( ; char_code < ( t1cmap->first + t1cmap->count ); char_code++ ) { - result = cmap->indices[char_code]; + result = t1cmap->indices[char_code]; if ( result != 0 ) goto Exit; } @@ -287,20 +299,24 @@ /*************************************************************************/ FT_CALLBACK_DEF( const char * ) - psaux_get_glyph_name( T1_Face face, + psaux_get_glyph_name( void* face_, FT_UInt idx ) { + T1_Face face = (T1_Face)face_; + + return face->type1.glyph_names[idx]; } FT_CALLBACK_DEF( FT_Error ) - t1_cmap_unicode_init( PS_Unicodes unicodes, - FT_Pointer pointer ) + t1_cmap_unicode_init( FT_CMap cmap, /* PS_Unicodes */ + FT_Pointer pointer ) { - T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; FT_UNUSED( pointer ); @@ -311,17 +327,18 @@ return psnames->unicodes_init( memory, unicodes, (FT_UInt)face->type1.num_glyphs, - (PS_GetGlyphNameFunc)&psaux_get_glyph_name, + &psaux_get_glyph_name, (PS_FreeGlyphNameFunc)NULL, (FT_Pointer)face ); } FT_CALLBACK_DEF( void ) - t1_cmap_unicode_done( PS_Unicodes unicodes ) + t1_cmap_unicode_done( FT_CMap cmap ) /* PS_Unicodes */ { - FT_Face face = FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); + PS_Unicodes unicodes = (PS_Unicodes)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); FT_FREE( unicodes->maps ); @@ -330,23 +347,25 @@ FT_CALLBACK_DEF( FT_UInt ) - t1_cmap_unicode_char_index( PS_Unicodes unicodes, - FT_UInt32 char_code ) + t1_cmap_unicode_char_index( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 char_code ) { - T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; return psnames->unicodes_char_index( unicodes, char_code ); } - FT_CALLBACK_DEF( FT_UInt32 ) - t1_cmap_unicode_char_next( PS_Unicodes unicodes, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + t1_cmap_unicode_char_next( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 *pchar_code ) { - T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; return psnames->unicodes_char_next( unicodes, pchar_code ); diff --git a/lib/libesp32_lvgl/freetype/src/psaux/t1cmap.h b/lib/libesp32_lvgl/freetype/src/psaux/t1cmap.h index 031796510..b3702498a 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/t1cmap.h +++ b/lib/libesp32_lvgl/freetype/src/psaux/t1cmap.h @@ -4,7 +4,7 @@ * * Type 1 character map support (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/psaux/t1decode.c b/lib/libesp32_lvgl/freetype/src/psaux/t1decode.c index 2ed27ca19..4b6b969bc 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/t1decode.c +++ b/lib/libesp32_lvgl/freetype/src/psaux/t1decode.c @@ -4,7 +4,7 @@ * * PostScript Type 1 decoding routines (body). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -27,8 +27,11 @@ #include "psauxerr.h" + /* ensure proper sign extension */ -#define Fix2Int( f ) ( (FT_Int)(FT_Short)( (f) >> 16 ) ) +#define Fix2Int( f ) ( (FT_Int) (FT_Short)( (f) >> 16 ) ) +#define Fix2UInt( f ) ( (FT_UInt)(FT_Short)( (f) >> 16 ) ) + /************************************************************************** * @@ -517,7 +520,7 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( bol ) { - FT_TRACE5(( " (%d)", decoder->top - decoder->stack )); + FT_TRACE5(( " (%td)", decoder->top - decoder->stack )); bol = FALSE; } #endif @@ -1025,16 +1028,16 @@ /* 2 24 callothersubr */ /* ==> set BuildCharArray[cvi( )] = */ { - FT_Int idx; + FT_UInt idx; PS_Blend blend = decoder->blend; if ( arg_cnt != 2 || !blend ) goto Unexpected_OtherSubr; - idx = Fix2Int( top[1] ); + idx = Fix2UInt( top[1] ); - if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) + if ( idx >= decoder->len_buildchar ) goto Unexpected_OtherSubr; decoder->buildchar[idx] = top[0]; @@ -1046,16 +1049,16 @@ /* ==> push BuildCharArray[cvi( idx )] */ /* onto T1 stack */ { - FT_Int idx; + FT_UInt idx; PS_Blend blend = decoder->blend; if ( arg_cnt != 1 || !blend ) goto Unexpected_OtherSubr; - idx = Fix2Int( top[0] ); + idx = Fix2UInt( top[0] ); - if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) + if ( idx >= decoder->len_buildchar ) goto Unexpected_OtherSubr; top[0] = decoder->buildchar[idx]; @@ -1162,9 +1165,9 @@ if ( top - decoder->stack != num_args ) FT_TRACE0(( "t1_decoder_parse_charstrings:" " too much operands on the stack" - " (seen %d, expected %d)\n", + " (seen %td, expected %d)\n", top - decoder->stack, num_args )); - break; + break; } #endif /* FT_DEBUG_LEVEL_TRACE */ @@ -1209,7 +1212,7 @@ FT_TRACE4(( "BuildCharArray = [ " )); for ( i = 0; i < decoder->len_buildchar; i++ ) - FT_TRACE4(( "%d ", decoder->buildchar[i] )); + FT_TRACE4(( "%ld ", decoder->buildchar[i] )); FT_TRACE4(( "]\n" )); } @@ -1650,7 +1653,8 @@ } /* while ip < limit */ - FT_TRACE4(( "..end..\n\n" )); + FT_TRACE4(( "..end..\n" )); + FT_TRACE4(( "\n" )); Fail: return error; @@ -2070,7 +2074,8 @@ } /* while ip < limit */ - FT_TRACE4(( "..end..\n\n" )); + FT_TRACE4(( "..end..\n" )); + FT_TRACE4(( "\n" )); No_Width: FT_ERROR(( "t1_decoder_parse_metrics:" diff --git a/lib/libesp32_lvgl/freetype/src/psaux/t1decode.h b/lib/libesp32_lvgl/freetype/src/psaux/t1decode.h index b793504ac..0970def96 100644 --- a/lib/libesp32_lvgl/freetype/src/psaux/t1decode.h +++ b/lib/libesp32_lvgl/freetype/src/psaux/t1decode.h @@ -4,7 +4,7 @@ * * PostScript Type 1 decoding routines (specification). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/pshinter/module.mk b/lib/libesp32_lvgl/freetype/src/pshinter/module.mk index b440d2e76..dbc137dca 100644 --- a/lib/libesp32_lvgl/freetype/src/pshinter/module.mk +++ b/lib/libesp32_lvgl/freetype/src/pshinter/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/pshinter/pshalgo.c b/lib/libesp32_lvgl/freetype/src/pshinter/pshalgo.c index 920b9a74b..4f622e1e4 100644 --- a/lib/libesp32_lvgl/freetype/src/pshinter/pshalgo.c +++ b/lib/libesp32_lvgl/freetype/src/pshinter/pshalgo.c @@ -4,7 +4,7 @@ * * PostScript hinting algorithm (body). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used @@ -182,13 +182,13 @@ count = hints->num_hints; /* allocate our tables */ - if ( FT_NEW_ARRAY( table->sort, 2 * count ) || - FT_NEW_ARRAY( table->hints, count ) || - FT_NEW_ARRAY( table->zones, 2 * count + 1 ) ) + if ( FT_QNEW_ARRAY( table->sort, 2 * count ) || + FT_QNEW_ARRAY( table->hints, count ) || + FT_QNEW_ARRAY( table->zones, 2 * count + 1 ) ) goto Exit; table->max_hints = count; - table->sort_global = table->sort + count; + table->sort_global = FT_OFFSET( table->sort, count ); table->num_hints = 0; table->num_zones = 0; table->zone = NULL; @@ -305,17 +305,18 @@ /* now, sort the hints; they are guaranteed to not overlap */ /* so we can compare their "org_pos" field directly */ { - FT_Int i1, i2; + FT_UInt i1, i2; PSH_Hint hint1, hint2; PSH_Hint* sort = table->sort; /* a simple bubble sort will do, since in 99% of cases, the hints */ /* will be already sorted -- and the sort will be linear */ - for ( i1 = 1; i1 < (FT_Int)count; i1++ ) + for ( i1 = 1; i1 < count; i1++ ) { hint1 = sort[i1]; - for ( i2 = i1 - 1; i2 >= 0; i2-- ) + /* this loop stops when i2 wraps around after reaching 0 */ + for ( i2 = i1 - 1; i2 < i1; i2-- ) { hint2 = sort[i2]; @@ -515,7 +516,7 @@ if ( !psh_hint_is_fitted( parent ) ) psh_hint_align( parent, globals, dimension, glyph ); - /* keep original relation between hints, this is, use the */ + /* keep original relation between hints, that is, use the */ /* scaled distance between the centers of the hints to */ /* compute the new position */ par_org_center = parent->org_pos + ( parent->org_len >> 1 ); @@ -869,7 +870,7 @@ return; } -#endif /* DEBUG_HINTER*/ +#endif /* DEBUG_HINTER */ hint = table->hints; count = table->max_hints; @@ -1049,12 +1050,12 @@ } - static int + static PSH_Dir psh_compute_dir( FT_Pos dx, FT_Pos dy ) { - FT_Pos ax, ay; - int result = PSH_DIR_NONE; + FT_Pos ax, ay; + PSH_Dir result = PSH_DIR_NONE; ax = FT_ABS( dx ); @@ -1166,8 +1167,8 @@ memory = glyph->memory = globals->memory; /* allocate and setup points + contours arrays */ - if ( FT_NEW_ARRAY( glyph->points, outline->n_points ) || - FT_NEW_ARRAY( glyph->contours, outline->n_contours ) ) + if ( FT_QNEW_ARRAY( glyph->points, outline->n_points ) || + FT_QNEW_ARRAY( glyph->contours, outline->n_contours ) ) goto Exit; glyph->num_points = (FT_UInt)outline->n_points; @@ -1227,28 +1228,29 @@ FT_Pos dxi, dyi, dxo, dyo; + point->flags = 0; if ( !( outline->tags[n] & FT_CURVE_TAG_ON ) ) - point->flags = PSH_POINT_OFF; + psh_point_set_off( point ); dxi = vec[n].x - vec[n_prev].x; dyi = vec[n].y - vec[n_prev].y; - point->dir_in = (FT_Char)psh_compute_dir( dxi, dyi ); + point->dir_in = psh_compute_dir( dxi, dyi ); dxo = vec[n_next].x - vec[n].x; dyo = vec[n_next].y - vec[n].y; - point->dir_out = (FT_Char)psh_compute_dir( dxo, dyo ); + point->dir_out = psh_compute_dir( dxo, dyo ); /* detect smooth points */ - if ( point->flags & PSH_POINT_OFF ) - point->flags |= PSH_POINT_SMOOTH; + if ( psh_point_is_off( point ) ) + psh_point_set_smooth( point ); else if ( point->dir_in == point->dir_out ) { if ( point->dir_out != PSH_DIR_NONE || psh_corner_is_flat( dxi, dyi, dxo, dyo ) ) - point->flags |= PSH_POINT_SMOOTH; + psh_point_set_smooth( point ); } } } @@ -1403,16 +1405,13 @@ } - /* major_dir is the direction for points on the bottom/left of the stem; */ - /* Points on the top/right of the stem will have a direction of */ - /* -major_dir. */ - + /* the min and max are based on contour orientation and fill rule */ static void psh_hint_table_find_strong_points( PSH_Hint_Table table, PSH_Point point, FT_UInt count, FT_Int threshold, - FT_Int major_dir ) + PSH_Dir major_dir ) { PSH_Hint* sort = table->sort; FT_UInt num_hints = table->num_hints; @@ -1420,59 +1419,53 @@ for ( ; count > 0; count--, point++ ) { - FT_Int point_dir = 0; - FT_Pos org_u = point->org_u; + PSH_Dir point_dir; + FT_Pos org_u = point->org_u; if ( psh_point_is_strong( point ) ) continue; - if ( PSH_DIR_COMPARE( point->dir_in, major_dir ) ) - point_dir = point->dir_in; + point_dir = + (PSH_Dir)( ( point->dir_in | point->dir_out ) & major_dir ); - else if ( PSH_DIR_COMPARE( point->dir_out, major_dir ) ) - point_dir = point->dir_out; - - if ( point_dir ) + if ( point_dir & ( PSH_DIR_DOWN | PSH_DIR_RIGHT ) ) { - if ( point_dir == major_dir ) + FT_UInt nn; + + + for ( nn = 0; nn < num_hints; nn++ ) { - FT_UInt nn; + PSH_Hint hint = sort[nn]; + FT_Pos d = org_u - hint->org_pos; - for ( nn = 0; nn < num_hints; nn++ ) + if ( d < threshold && -d < threshold ) { - PSH_Hint hint = sort[nn]; - FT_Pos d = org_u - hint->org_pos; - - - if ( d < threshold && -d < threshold ) - { - psh_point_set_strong( point ); - point->flags2 |= PSH_POINT_EDGE_MIN; - point->hint = hint; - break; - } + psh_point_set_strong( point ); + point->flags2 |= PSH_POINT_EDGE_MIN; + point->hint = hint; + break; } } - else if ( point_dir == -major_dir ) + } + else if ( point_dir & ( PSH_DIR_UP | PSH_DIR_LEFT ) ) + { + FT_UInt nn; + + + for ( nn = 0; nn < num_hints; nn++ ) { - FT_UInt nn; + PSH_Hint hint = sort[nn]; + FT_Pos d = org_u - hint->org_pos - hint->org_len; - for ( nn = 0; nn < num_hints; nn++ ) + if ( d < threshold && -d < threshold ) { - PSH_Hint hint = sort[nn]; - FT_Pos d = org_u - hint->org_pos - hint->org_len; - - - if ( d < threshold && -d < threshold ) - { - psh_point_set_strong( point ); - point->flags2 |= PSH_POINT_EDGE_MAX; - point->hint = hint; - break; - } + psh_point_set_strong( point ); + point->flags2 |= PSH_POINT_EDGE_MAX; + point->hint = hint; + break; } } } @@ -1555,8 +1548,9 @@ /* the accepted shift for strong points in fractional pixels */ #define PSH_STRONG_THRESHOLD 32 - /* the maximum shift value in font units */ -#define PSH_STRONG_THRESHOLD_MAXIMUM 30 + /* the maximum shift value in font units tuned to distinguish */ + /* between stems and serifs in URW+ font collection */ +#define PSH_STRONG_THRESHOLD_MAXIMUM 12 /* find strong points in a glyph */ @@ -1571,7 +1565,7 @@ PS_Mask mask = table->hint_masks->masks; FT_UInt num_masks = table->hint_masks->num_masks; FT_UInt first = 0; - FT_Int major_dir = ( dimension == 0 ) ? PSH_DIR_VERTICAL + PSH_Dir major_dir = ( dimension == 0 ) ? PSH_DIR_VERTICAL : PSH_DIR_HORIZONTAL; PSH_Dimension dim = &glyph->globals->dimension[dimension]; FT_Fixed scale = dim->scale_mult; @@ -1656,8 +1650,8 @@ /* check tangents */ - if ( !PSH_DIR_COMPARE( point->dir_in, PSH_DIR_HORIZONTAL ) && - !PSH_DIR_COMPARE( point->dir_out, PSH_DIR_HORIZONTAL ) ) + if ( !( point->dir_in & PSH_DIR_HORIZONTAL ) && + !( point->dir_out & PSH_DIR_HORIZONTAL ) ) continue; /* skip strong points */ @@ -1805,7 +1799,7 @@ FT_Error error; - if ( FT_NEW_ARRAY( strongs, num_strongs ) ) + if ( FT_QNEW_ARRAY( strongs, num_strongs ) ) return; } @@ -2118,14 +2112,17 @@ FT_Fixed old_x_scale = x_scale; FT_Fixed old_y_scale = y_scale; - FT_Fixed scaled; - FT_Fixed fitted; + FT_Fixed scaled = 0; + FT_Fixed fitted = 0; FT_Bool rescale = FALSE; - scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale ); - fitted = FT_PIX_ROUND( scaled ); + if ( globals->blues.normal_top.count ) + { + scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale ); + fitted = FT_PIX_ROUND( scaled ); + } if ( fitted != 0 && scaled != fitted ) { diff --git a/lib/libesp32_lvgl/freetype/src/pshinter/pshalgo.h b/lib/libesp32_lvgl/freetype/src/pshinter/pshalgo.h index 5367a5d16..3f0ba28a6 100644 --- a/lib/libesp32_lvgl/freetype/src/pshinter/pshalgo.h +++ b/lib/libesp32_lvgl/freetype/src/pshinter/pshalgo.h @@ -4,7 +4,7 @@ * * PostScript hinting algorithm (specification). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -93,21 +93,17 @@ FT_BEGIN_HEADER typedef struct PSH_PointRec_* PSH_Point; typedef struct PSH_ContourRec_* PSH_Contour; - enum + typedef enum PSH_Dir_ { - PSH_DIR_NONE = 4, - PSH_DIR_UP = -1, - PSH_DIR_DOWN = 1, - PSH_DIR_LEFT = -2, - PSH_DIR_RIGHT = 2 - }; + PSH_DIR_NONE = 0, + PSH_DIR_UP = 1, + PSH_DIR_DOWN = 2, + PSH_DIR_VERTICAL = 1 | 2, + PSH_DIR_LEFT = 4, + PSH_DIR_RIGHT = 8, + PSH_DIR_HORIZONTAL = 4 | 8 -#define PSH_DIR_HORIZONTAL 2 -#define PSH_DIR_VERTICAL 1 - -#define PSH_DIR_COMPARE( d1, d2 ) ( (d1) == (d2) || (d1) == -(d2) ) -#define PSH_DIR_IS_HORIZONTAL( d ) PSH_DIR_COMPARE( d, PSH_DIR_HORIZONTAL ) -#define PSH_DIR_IS_VERTICAL( d ) PSH_DIR_COMPARE( d, PSH_DIR_VERTICAL ) + } PSH_Dir; /* the following bit-flags are computed once by the glyph */ @@ -160,8 +156,8 @@ FT_BEGIN_HEADER PSH_Contour contour; FT_UInt flags; FT_UInt flags2; - FT_Char dir_in; - FT_Char dir_out; + PSH_Dir dir_in; + PSH_Dir dir_out; PSH_Hint hint; FT_Pos org_u; FT_Pos org_v; @@ -199,10 +195,6 @@ FT_BEGIN_HEADER PSH_Globals globals; PSH_Hint_TableRec hint_tables[2]; - FT_Bool vertical; - FT_Int major_dir; - FT_Int minor_dir; - FT_Bool do_horz_hints; FT_Bool do_vert_hints; FT_Bool do_horz_snapping; diff --git a/lib/libesp32_lvgl/freetype/src/pshinter/pshglob.c b/lib/libesp32_lvgl/freetype/src/pshinter/pshglob.c index cdc1c3af0..d4c5eb32b 100644 --- a/lib/libesp32_lvgl/freetype/src/pshinter/pshglob.c +++ b/lib/libesp32_lvgl/freetype/src/pshinter/pshglob.c @@ -5,7 +5,7 @@ * PostScript hinter global hinting management (body). * Inspired by the new auto-hinter module. * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used @@ -650,7 +650,7 @@ FT_Error error; - if ( !FT_NEW( globals ) ) + if ( !FT_QNEW( globals ) ) { FT_UInt count; FT_Short* read; diff --git a/lib/libesp32_lvgl/freetype/src/pshinter/pshglob.h b/lib/libesp32_lvgl/freetype/src/pshinter/pshglob.h index 8181324e5..579eb2148 100644 --- a/lib/libesp32_lvgl/freetype/src/pshinter/pshglob.h +++ b/lib/libesp32_lvgl/freetype/src/pshinter/pshglob.h @@ -4,7 +4,7 @@ * * PostScript hinter global hinting management. * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/pshinter/pshinter.c b/lib/libesp32_lvgl/freetype/src/pshinter/pshinter.c index 3cca0ad7c..54ed41096 100644 --- a/lib/libesp32_lvgl/freetype/src/pshinter/pshinter.c +++ b/lib/libesp32_lvgl/freetype/src/pshinter/pshinter.c @@ -4,7 +4,7 @@ * * FreeType PostScript Hinting module * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/pshinter/pshmod.c b/lib/libesp32_lvgl/freetype/src/pshinter/pshmod.c index e0abd386f..974a99e01 100644 --- a/lib/libesp32_lvgl/freetype/src/pshinter/pshmod.c +++ b/lib/libesp32_lvgl/freetype/src/pshinter/pshmod.c @@ -4,7 +4,7 @@ * * FreeType PostScript hinter module implementation (body). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -37,8 +37,11 @@ /* finalize module */ FT_CALLBACK_DEF( void ) - ps_hinter_done( PS_Hinter_Module module ) + ps_hinter_done( FT_Module module_ ) /* PS_Hinter_Module */ { + PS_Hinter_Module module = (PS_Hinter_Module)module_; + + module->t1_funcs.hints = NULL; module->t2_funcs.hints = NULL; @@ -48,8 +51,10 @@ /* initialize module, create hints recorder and the interface */ FT_CALLBACK_DEF( FT_Error ) - ps_hinter_init( PS_Hinter_Module module ) + ps_hinter_init( FT_Module module_ ) /* PS_Hinter_Module */ { + PS_Hinter_Module module = (PS_Hinter_Module)module_; + FT_Memory memory = module->root.memory; void* ph = &module->ps_hints; diff --git a/lib/libesp32_lvgl/freetype/src/pshinter/pshmod.h b/lib/libesp32_lvgl/freetype/src/pshinter/pshmod.h index 2a6eb1c46..4bd781a35 100644 --- a/lib/libesp32_lvgl/freetype/src/pshinter/pshmod.h +++ b/lib/libesp32_lvgl/freetype/src/pshinter/pshmod.h @@ -4,7 +4,7 @@ * * PostScript hinter module interface (specification). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/pshinter/pshnterr.h b/lib/libesp32_lvgl/freetype/src/pshinter/pshnterr.h index d67955c41..97624952d 100644 --- a/lib/libesp32_lvgl/freetype/src/pshinter/pshnterr.h +++ b/lib/libesp32_lvgl/freetype/src/pshinter/pshnterr.h @@ -4,7 +4,7 @@ * * PS Hinter error codes (specification only). * - * Copyright (C) 2003-2020 by + * Copyright (C) 2003-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/pshinter/pshrec.c b/lib/libesp32_lvgl/freetype/src/pshinter/pshrec.c index bddccf2a6..680e6d013 100644 --- a/lib/libesp32_lvgl/freetype/src/pshinter/pshrec.c +++ b/lib/libesp32_lvgl/freetype/src/pshinter/pshrec.c @@ -4,7 +4,7 @@ * * FreeType PostScript hints recorder (body). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -63,16 +63,14 @@ { FT_UInt old_max = table->max_hints; FT_UInt new_max = count; - FT_Error error = FT_Err_Ok; + FT_Error error; - if ( new_max > old_max ) - { - /* try to grow the table */ - new_max = FT_PAD_CEIL( new_max, 8 ); - if ( !FT_RENEW_ARRAY( table->hints, old_max, new_max ) ) - table->max_hints = new_max; - } + /* try to grow the table */ + new_max = FT_PAD_CEIL( new_max, 8 ); + if ( !FT_QRENEW_ARRAY( table->hints, old_max, new_max ) ) + table->max_hints = new_max; + return error; } @@ -90,17 +88,14 @@ count = table->num_hints; count++; - if ( count >= table->max_hints ) + if ( count > table->max_hints ) { error = ps_hint_table_ensure( table, count, memory ); if ( error ) goto Exit; } - hint = table->hints + count - 1; - hint->pos = 0; - hint->len = 0; - hint->flags = 0; + hint = table->hints + count - 1; /* initialized upstream */ table->num_hints = count; @@ -136,14 +131,15 @@ FT_UInt count, FT_Memory memory ) { - FT_UInt old_max = ( mask->max_bits + 7 ) >> 3; - FT_UInt new_max = ( count + 7 ) >> 3; + FT_UInt old_max = mask->max_bits >> 3; + FT_UInt new_max = ( count + 7 ) >> 3; FT_Error error = FT_Err_Ok; if ( new_max > old_max ) { new_max = FT_PAD_CEIL( new_max, 8 ); + /* added bytes are zeroed here */ if ( !FT_RENEW_ARRAY( mask->bytes, old_max, new_max ) ) mask->max_bits = new_max * 8; } @@ -154,31 +150,15 @@ /* test a bit value in a given mask */ static FT_Int ps_mask_test_bit( PS_Mask mask, - FT_Int idx ) + FT_UInt idx ) { - if ( (FT_UInt)idx >= mask->num_bits ) + if ( idx >= mask->num_bits ) return 0; return mask->bytes[idx >> 3] & ( 0x80 >> ( idx & 7 ) ); } - /* clear a given bit */ - static void - ps_mask_clear_bit( PS_Mask mask, - FT_UInt idx ) - { - FT_Byte* p; - - - if ( idx >= mask->num_bits ) - return; - - p = mask->bytes + ( idx >> 3 ); - p[0] = (FT_Byte)( p[0] & ~( 0x80 >> ( idx & 7 ) ) ); - } - - /* set a given bit, possibly grow the mask */ static FT_Error ps_mask_set_bit( PS_Mask mask, @@ -269,6 +249,10 @@ mask = table->masks + count - 1; mask->num_bits = 0; mask->end_point = 0; + /* reused mask must be cleared */ + if ( mask->max_bits ) + FT_MEM_ZERO( mask->bytes, mask->max_bits >> 3 ); + table->num_masks = count; Exit: @@ -426,7 +410,7 @@ PS_Mask mask2 = table->masks + index2; FT_UInt count1 = mask1->num_bits; FT_UInt count2 = mask2->num_bits; - FT_Int delta; + FT_UInt delta; if ( count2 > 0 ) @@ -437,15 +421,14 @@ /* if "count2" is greater than "count1", we need to grow the */ - /* first bitset, and clear the highest bits */ + /* first bitset */ if ( count2 > count1 ) { error = ps_mask_ensure( mask1, count2, memory ); if ( error ) goto Exit; - for ( pos = count1; pos < count2; pos++ ) - ps_mask_clear_bit( mask1, pos ); + mask1->num_bits = count2; } /* merge (unite) the bitsets */ @@ -467,7 +450,7 @@ mask2->end_point = 0; /* number of masks to move */ - delta = (FT_Int)( table->num_masks - 1 - index2 ); + delta = table->num_masks - 1 - index2; if ( delta > 0 ) { /* move to end of table for reuse */ @@ -476,7 +459,7 @@ ft_memmove( mask2, mask2 + 1, - (FT_UInt)delta * sizeof ( PS_MaskRec ) ); + delta * sizeof ( PS_MaskRec ) ); mask2[delta] = dummy; } @@ -499,23 +482,18 @@ ps_mask_table_merge_all( PS_Mask_Table table, FT_Memory memory ) { - FT_Int index1, index2; + FT_UInt index1, index2; FT_Error error = FT_Err_Ok; - /* both loops go down to 0, thus FT_Int for index1 and index2 */ - for ( index1 = (FT_Int)table->num_masks - 1; index1 > 0; index1-- ) + /* the loops stop when unsigned indices wrap around after 0 */ + for ( index1 = table->num_masks - 1; index1 < table->num_masks; index1-- ) { - for ( index2 = index1 - 1; index2 >= 0; index2-- ) + for ( index2 = index1 - 1; index2 < index1; index2-- ) { - if ( ps_mask_table_test_intersect( table, - (FT_UInt)index1, - (FT_UInt)index2 ) ) + if ( ps_mask_table_test_intersect( table, index1, index2 ) ) { - error = ps_mask_table_merge( table, - (FT_UInt)index2, - (FT_UInt)index1, - memory ); + error = ps_mask_table_merge( table, index2, index1, memory ); if ( error ) goto Exit; @@ -652,7 +630,7 @@ FT_Int pos, FT_Int len, FT_Memory memory, - FT_Int *aindex ) + FT_UInt *aindex ) { FT_Error error = FT_Err_Ok; FT_UInt flags = 0; @@ -670,9 +648,6 @@ len = 0; } - if ( aindex ) - *aindex = -1; - /* now, lookup stem in the current hints table */ { PS_Mask mask; @@ -709,7 +684,7 @@ goto Exit; if ( aindex ) - *aindex = (FT_Int)idx; + *aindex = idx; } Exit: @@ -720,9 +695,9 @@ /* add a "hstem3/vstem3" counter to our dimension table */ static FT_Error ps_dimension_add_counter( PS_Dimension dim, - FT_Int hint1, - FT_Int hint2, - FT_Int hint3, + FT_UInt hint1, + FT_UInt hint2, + FT_UInt hint3, FT_Memory memory ) { FT_Error error = FT_Err_Ok; @@ -749,26 +724,17 @@ } /* now, set the bits for our hints in the counter mask */ - if ( hint1 >= 0 ) - { - error = ps_mask_set_bit( counter, (FT_UInt)hint1, memory ); - if ( error ) - goto Exit; - } + error = ps_mask_set_bit( counter, hint1, memory ); + if ( error ) + goto Exit; - if ( hint2 >= 0 ) - { - error = ps_mask_set_bit( counter, (FT_UInt)hint2, memory ); - if ( error ) - goto Exit; - } + error = ps_mask_set_bit( counter, hint2, memory ); + if ( error ) + goto Exit; - if ( hint3 >= 0 ) - { - error = ps_mask_set_bit( counter, (FT_UInt)hint3, memory ); - if ( error ) - goto Exit; - } + error = ps_mask_set_bit( counter, hint3, memory ); + if ( error ) + goto Exit; Exit: return error; @@ -799,7 +765,7 @@ /* destroy hints */ - FT_LOCAL( void ) + FT_LOCAL_DEF( void ) ps_hints_done( PS_Hints hints ) { FT_Memory memory = hints->memory; @@ -813,7 +779,7 @@ } - FT_LOCAL( void ) + FT_LOCAL_DEF( void ) ps_hints_init( PS_Hints hints, FT_Memory memory ) { @@ -885,10 +851,11 @@ /* add one Type1 counter stem to the current hints table */ static void - ps_hints_t1stem3( PS_Hints hints, + ps_hints_t1stem3( T1_Hints hints_, /* PS_Hints */ FT_UInt dimension, FT_Fixed* stems ) { + PS_Hints hints = (PS_Hints)hints_; FT_Error error = FT_Err_Ok; @@ -897,7 +864,7 @@ PS_Dimension dim; FT_Memory memory = hints->memory; FT_Int count; - FT_Int idx[3]; + FT_UInt idx[3]; /* limit "dimension" to 0..1 */ @@ -948,9 +915,10 @@ /* reset hints (only with Type 1 hints) */ static void - ps_hints_t1reset( PS_Hints hints, + ps_hints_t1reset( T1_Hints hints_, /* PS_Hints */ FT_UInt end_point ) { + PS_Hints hints = (PS_Hints)hints_; FT_Error error = FT_Err_Ok; @@ -987,11 +955,12 @@ /* Type2 "hintmask" operator, add a new hintmask to each direction */ static void - ps_hints_t2mask( PS_Hints hints, + ps_hints_t2mask( T2_Hints hints_, /* PS_Hints */ FT_UInt end_point, FT_UInt bit_count, const FT_Byte* bytes ) { + PS_Hints hints = (PS_Hints)hints_; FT_Error error; @@ -1033,10 +1002,11 @@ static void - ps_hints_t2counter( PS_Hints hints, + ps_hints_t2counter( T2_Hints hints_, /* PS_Hints */ FT_UInt bit_count, const FT_Byte* bytes ) { + PS_Hints hints = (PS_Hints)hints_; FT_Error error; @@ -1121,6 +1091,13 @@ ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_1 ); } + static FT_Error + t1_hints_close( T1_Hints hints, + FT_UInt end_point ) + { + return ps_hints_close( (PS_Hints)hints, end_point ); + } + static void t1_hints_stem( T1_Hints hints, FT_UInt dimension, @@ -1136,17 +1113,27 @@ } + static FT_Error + t1_hints_apply( T1_Hints hints, + FT_Outline* outline, + PSH_Globals globals, + FT_Render_Mode hint_mode ) + { + return ps_hints_apply( (PS_Hints)hints, outline, globals, hint_mode ); + } + + FT_LOCAL_DEF( void ) t1_hints_funcs_init( T1_Hints_FuncsRec* funcs ) { FT_ZERO( funcs ); funcs->open = (T1_Hints_OpenFunc) t1_hints_open; - funcs->close = (T1_Hints_CloseFunc) ps_hints_close; + funcs->close = (T1_Hints_CloseFunc) t1_hints_close; funcs->stem = (T1_Hints_SetStemFunc) t1_hints_stem; funcs->stem3 = (T1_Hints_SetStem3Func)ps_hints_t1stem3; funcs->reset = (T1_Hints_ResetFunc) ps_hints_t1reset; - funcs->apply = (T1_Hints_ApplyFunc) ps_hints_apply; + funcs->apply = (T1_Hints_ApplyFunc) t1_hints_apply; } @@ -1165,6 +1152,14 @@ } + static FT_Error + t2_hints_close( T2_Hints hints, + FT_UInt end_point ) + { + return ps_hints_close( (PS_Hints)hints, end_point ); + } + + static void t2_hints_stems( T2_Hints hints, FT_UInt dimension, @@ -1202,17 +1197,27 @@ } + static FT_Error + t2_hints_apply( T2_Hints hints, + FT_Outline* outline, + PSH_Globals globals, + FT_Render_Mode hint_mode ) + { + return ps_hints_apply( (PS_Hints)hints, outline, globals, hint_mode ); + } + + FT_LOCAL_DEF( void ) t2_hints_funcs_init( T2_Hints_FuncsRec* funcs ) { FT_ZERO( funcs ); - funcs->open = (T2_Hints_OpenFunc) t2_hints_open; - funcs->close = (T2_Hints_CloseFunc) ps_hints_close; - funcs->stems = (T2_Hints_StemsFunc) t2_hints_stems; - funcs->hintmask= (T2_Hints_MaskFunc) ps_hints_t2mask; - funcs->counter = (T2_Hints_CounterFunc)ps_hints_t2counter; - funcs->apply = (T2_Hints_ApplyFunc) ps_hints_apply; + funcs->open = (T2_Hints_OpenFunc) t2_hints_open; + funcs->close = (T2_Hints_CloseFunc) t2_hints_close; + funcs->stems = (T2_Hints_StemsFunc) t2_hints_stems; + funcs->hintmask = (T2_Hints_MaskFunc) ps_hints_t2mask; + funcs->counter = (T2_Hints_CounterFunc)ps_hints_t2counter; + funcs->apply = (T2_Hints_ApplyFunc) t2_hints_apply; } diff --git a/lib/libesp32_lvgl/freetype/src/pshinter/pshrec.h b/lib/libesp32_lvgl/freetype/src/pshinter/pshrec.h index b13c7be13..0b2484af1 100644 --- a/lib/libesp32_lvgl/freetype/src/pshinter/pshrec.h +++ b/lib/libesp32_lvgl/freetype/src/pshinter/pshrec.h @@ -4,7 +4,7 @@ * * Postscript (Type1/Type2) hints recorder (specification). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/pshinter/rules.mk b/lib/libesp32_lvgl/freetype/src/pshinter/rules.mk index c845c255c..50058e882 100644 --- a/lib/libesp32_lvgl/freetype/src/pshinter/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/pshinter/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 2001-2020 by +# Copyright (C) 2001-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/psnames/module.mk b/lib/libesp32_lvgl/freetype/src/psnames/module.mk index 675bb3713..1ee0ef8f7 100644 --- a/lib/libesp32_lvgl/freetype/src/psnames/module.mk +++ b/lib/libesp32_lvgl/freetype/src/psnames/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/psnames/psmodule.c b/lib/libesp32_lvgl/freetype/src/psnames/psmodule.c index b38f9d3b1..8203a0465 100644 --- a/lib/libesp32_lvgl/freetype/src/psnames/psmodule.c +++ b/lib/libesp32_lvgl/freetype/src/psnames/psmodule.c @@ -4,7 +4,7 @@ * * psnames module implementation (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -57,7 +57,7 @@ /* the name, as in `A.swash' or `e.final'; in this case, the */ /* VARIANT_BIT is set in the return value. */ /* */ - static FT_UInt32 + FT_CALLBACK_DEF( FT_UInt32 ) ps_unicode_value( const char* glyph_name ) { /* If the name begins with `uni', then the glyph name may be a */ @@ -155,31 +155,30 @@ /* Look for a non-initial dot in the glyph name in order to */ /* find variants like `A.swash', `e.final', etc. */ { - const char* p = glyph_name; - const char* dot = NULL; + FT_UInt32 value = 0; + const char* p = glyph_name; - for ( ; *p; p++ ) + for ( ; *p && *p != '.'; p++ ) + ; + + /* now look up the glyph in the Adobe Glyph List; */ + /* `.notdef', `.null' and the empty name are short cut */ + if ( p > glyph_name ) { - if ( *p == '.' && p > glyph_name ) - { - dot = p; - break; - } + value = (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p ); + + if ( *p == '.' ) + value |= (FT_UInt32)VARIANT_BIT; } - /* now look up the glyph in the Adobe Glyph List */ - if ( !dot ) - return (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p ); - else - return (FT_UInt32)( ft_get_adobe_glyph_index( glyph_name, dot ) | - VARIANT_BIT ); + return value; } } /* ft_qsort callback to sort the unicode map */ - FT_CALLBACK_DEF( int ) + FT_COMPARE_DEF( int ) compare_uni_maps( const void* a, const void* b ) { @@ -310,7 +309,7 @@ /* Build a table that maps Unicode values to glyph indices. */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) ps_unicodes_init( FT_Memory memory, PS_Unicodes table, FT_UInt num_glyphs, @@ -326,9 +325,8 @@ /* we first allocate the table */ table->num_maps = 0; - table->maps = NULL; - if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) ) + if ( !FT_QNEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) ) { FT_UInt n; FT_UInt count; @@ -343,7 +341,7 @@ const char* gname = get_glyph_name( glyph_data, n ); - if ( gname ) + if ( gname && *gname ) { ps_check_extra_glyph_name( gname, n, extra_glyphs, extra_glyph_list_states ); @@ -391,9 +389,9 @@ /* Reallocate if the number of used entries is much smaller. */ if ( count < num_glyphs / 2 ) { - (void)FT_RENEW_ARRAY( table->maps, - num_glyphs + EXTRA_GLYPH_LIST_SIZE, - count ); + FT_MEM_QRENEW_ARRAY( table->maps, + num_glyphs + EXTRA_GLYPH_LIST_SIZE, + count ); error = FT_Err_Ok; } @@ -410,25 +408,22 @@ } - static FT_UInt + FT_CALLBACK_DEF( FT_UInt ) ps_unicodes_char_index( PS_Unicodes table, FT_UInt32 unicode ) { - PS_UniMap *min, *max, *mid, *result = NULL; + PS_UniMap *result = NULL; + PS_UniMap *min = table->maps; + PS_UniMap *max = min + table->num_maps; + PS_UniMap *mid = min + ( ( max - min ) >> 1 ); /* Perform a binary search on the table. */ - - min = table->maps; - max = min + table->num_maps - 1; - - while ( min <= max ) + while ( min < max ) { FT_UInt32 base_glyph; - mid = min + ( ( max - min ) >> 1 ); - if ( mid->unicode == unicode ) { result = mid; @@ -440,13 +435,15 @@ if ( base_glyph == unicode ) result = mid; /* remember match but continue search for base glyph */ - if ( min == max ) - break; - if ( base_glyph < unicode ) min = mid + 1; else - max = mid - 1; + max = mid; + + /* reasonable prediction in a continuous block */ + mid += unicode - base_glyph; + if ( mid >= max || mid < min ) + mid = min + ( ( max - min ) >> 1 ); } if ( result ) @@ -456,7 +453,7 @@ } - static FT_UInt32 + FT_CALLBACK_DEF( FT_UInt ) ps_unicodes_char_next( PS_Unicodes table, FT_UInt32 *unicode ) { @@ -467,14 +464,13 @@ { FT_UInt min = 0; FT_UInt max = table->num_maps; - FT_UInt mid; + FT_UInt mid = min + ( ( max - min ) >> 1 ); PS_UniMap* map; FT_UInt32 base_glyph; while ( min < max ) { - mid = min + ( ( max - min ) >> 1 ); map = table->maps + mid; if ( map->unicode == char_code ) @@ -492,6 +488,11 @@ min = mid + 1; else max = mid; + + /* reasonable prediction in a continuous block */ + mid += char_code - base_glyph; + if ( mid >= max || mid < min ) + mid = min + ( max - min ) / 2; } if ( result ) @@ -517,7 +518,7 @@ #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ - static const char* + FT_CALLBACK_DEF( const char* ) ps_get_macintosh_name( FT_UInt name_index ) { if ( name_index >= FT_NUM_MAC_NAMES ) @@ -527,7 +528,7 @@ } - static const char* + FT_CALLBACK_DEF( const char* ) ps_get_standard_strings( FT_UInt sid ) { if ( sid >= FT_NUM_SID_NAMES ) @@ -542,13 +543,13 @@ FT_DEFINE_SERVICE_PSCMAPSREC( pscmaps_interface, - (PS_Unicode_ValueFunc) ps_unicode_value, /* unicode_value */ - (PS_Unicodes_InitFunc) ps_unicodes_init, /* unicodes_init */ - (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index, /* unicodes_char_index */ - (PS_Unicodes_CharNextFunc) ps_unicodes_char_next, /* unicodes_char_next */ + ps_unicode_value, /* PS_Unicode_ValueFunc unicode_value */ + ps_unicodes_init, /* PS_Unicodes_InitFunc unicodes_init */ + ps_unicodes_char_index, /* PS_Unicodes_CharIndexFunc unicodes_char_index */ + ps_unicodes_char_next, /* PS_Unicodes_CharNextFunc unicodes_char_next */ - (PS_Macintosh_NameFunc) ps_get_macintosh_name, /* macintosh_name */ - (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings */ + ps_get_macintosh_name, /* PS_Macintosh_NameFunc macintosh_name */ + ps_get_standard_strings, /* PS_Adobe_Std_StringsFunc adobe_std_strings */ t1_standard_encoding, /* adobe_std_encoding */ t1_expert_encoding /* adobe_expert_encoding */ @@ -559,13 +560,13 @@ FT_DEFINE_SERVICE_PSCMAPSREC( pscmaps_interface, - NULL, /* unicode_value */ - NULL, /* unicodes_init */ - NULL, /* unicodes_char_index */ - NULL, /* unicodes_char_next */ + NULL, /* PS_Unicode_ValueFunc unicode_value */ + NULL, /* PS_Unicodes_InitFunc unicodes_init */ + NULL, /* PS_Unicodes_CharIndexFunc unicodes_char_index */ + NULL, /* PS_Unicodes_CharNextFunc unicodes_char_next */ - (PS_Macintosh_NameFunc) ps_get_macintosh_name, /* macintosh_name */ - (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings */ + ps_get_macintosh_name, /* PS_Macintosh_NameFunc macintosh_name */ + ps_get_standard_strings, /* PS_Adobe_Std_StringsFunc adobe_std_strings */ t1_standard_encoding, /* adobe_std_encoding */ t1_expert_encoding /* adobe_expert_encoding */ @@ -611,9 +612,9 @@ PUT_PS_NAMES_SERVICE( (void*)&pscmaps_interface ), /* module specific interface */ - (FT_Module_Constructor)NULL, /* module_init */ - (FT_Module_Destructor) NULL, /* module_done */ - (FT_Module_Requester) PUT_PS_NAMES_SERVICE( psnames_get_service ) /* get_interface */ + NULL, /* FT_Module_Constructor module_init */ + NULL, /* FT_Module_Destructor module_done */ + PUT_PS_NAMES_SERVICE( psnames_get_service ) /* FT_Module_Requester get_interface */ ) diff --git a/lib/libesp32_lvgl/freetype/src/psnames/psmodule.h b/lib/libesp32_lvgl/freetype/src/psnames/psmodule.h index c85a9ecad..0904700bf 100644 --- a/lib/libesp32_lvgl/freetype/src/psnames/psmodule.h +++ b/lib/libesp32_lvgl/freetype/src/psnames/psmodule.h @@ -4,7 +4,7 @@ * * High-level psnames module interface (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/psnames/psnamerr.h b/lib/libesp32_lvgl/freetype/src/psnames/psnamerr.h index 154c701d0..0073f8228 100644 --- a/lib/libesp32_lvgl/freetype/src/psnames/psnamerr.h +++ b/lib/libesp32_lvgl/freetype/src/psnames/psnamerr.h @@ -4,7 +4,7 @@ * * PS names module error codes (specification only). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/psnames/psnames.c b/lib/libesp32_lvgl/freetype/src/psnames/psnames.c index cff36851b..93ed9332f 100644 --- a/lib/libesp32_lvgl/freetype/src/psnames/psnames.c +++ b/lib/libesp32_lvgl/freetype/src/psnames/psnames.c @@ -4,7 +4,7 @@ * * FreeType psnames module component (body only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/psnames/pstables.h b/lib/libesp32_lvgl/freetype/src/psnames/pstables.h index c215f16ff..7f92cce60 100644 --- a/lib/libesp32_lvgl/freetype/src/psnames/pstables.h +++ b/lib/libesp32_lvgl/freetype/src/psnames/pstables.h @@ -4,7 +4,7 @@ * * PostScript glyph names. * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/psnames/rules.mk b/lib/libesp32_lvgl/freetype/src/psnames/rules.mk index 14cdda3ad..8d7c58068 100644 --- a/lib/libesp32_lvgl/freetype/src/psnames/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/psnames/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/raster/ftmisc.h b/lib/libesp32_lvgl/freetype/src/raster/ftmisc.h index 6efe4a9a5..33dbfd631 100644 --- a/lib/libesp32_lvgl/freetype/src/raster/ftmisc.h +++ b/lib/libesp32_lvgl/freetype/src/raster/ftmisc.h @@ -5,7 +5,7 @@ * Miscellaneous macros for stand-alone rasterizer (specification * only). * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used @@ -47,11 +47,8 @@ typedef signed long FT_F26Dot6; typedef int FT_Error; -#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ - ( ( (FT_ULong)_x1 << 24 ) | \ - ( (FT_ULong)_x2 << 16 ) | \ - ( (FT_ULong)_x3 << 8 ) | \ - (FT_ULong)_x4 ) + +#define FT_STATIC_BYTE_CAST( type, var ) (type)(FT_Byte)(var) /* from include/freetype/ftsystem.h */ diff --git a/lib/libesp32_lvgl/freetype/src/raster/ftraster.c b/lib/libesp32_lvgl/freetype/src/raster/ftraster.c index 9f0a7976f..192ca0701 100644 --- a/lib/libesp32_lvgl/freetype/src/raster/ftraster.c +++ b/lib/libesp32_lvgl/freetype/src/raster/ftraster.c @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -149,9 +149,6 @@ /*************************************************************************/ /*************************************************************************/ - /* define DEBUG_RASTER if you want to compile a debugging version */ -/* #define DEBUG_RASTER */ - /*************************************************************************/ /*************************************************************************/ @@ -200,12 +197,13 @@ #define FT_THROW( e ) FT_ERR_CAT( Raster_Err_, e ) #endif -#define Raster_Err_None 0 -#define Raster_Err_Not_Ini -1 -#define Raster_Err_Overflow -2 -#define Raster_Err_Neg_Height -3 -#define Raster_Err_Invalid -4 -#define Raster_Err_Unsupported -5 +#define Raster_Err_Ok 0 +#define Raster_Err_Invalid_Outline -1 +#define Raster_Err_Cannot_Render_Glyph -2 +#define Raster_Err_Invalid_Argument -3 +#define Raster_Err_Raster_Overflow -4 +#define Raster_Err_Raster_Uninitialized -5 +#define Raster_Err_Raster_Negative_Height -6 #define ft_memset memset @@ -230,13 +228,6 @@ #include "rasterrs.h" -#define Raster_Err_None FT_Err_Ok -#define Raster_Err_Not_Ini Raster_Err_Raster_Uninitialized -#define Raster_Err_Overflow Raster_Err_Raster_Overflow -#define Raster_Err_Neg_Height Raster_Err_Raster_Negative_Height -#define Raster_Err_Invalid Raster_Err_Invalid_Outline -#define Raster_Err_Unsupported Raster_Err_Cannot_Render_Glyph - #endif /* !STANDALONE_ */ @@ -375,16 +366,6 @@ typedef PProfile* PProfileList; - /* Simple record used to implement a stack of bands, required */ - /* by the sub-banding mechanism */ - typedef struct black_TBand_ - { - Short y_min; /* band's minimum */ - Short y_max; /* band's maximum */ - - } black_TBand; - - #define AlignProfileSize \ ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( Long ) ) @@ -426,8 +407,8 @@ /* prototypes used for sweep function dispatch */ typedef void - Function_Sweep_Init( RAS_ARGS Short* min, - Short* max ); + Function_Sweep_Init( RAS_ARGS Short min, + Short max ); typedef void Function_Sweep_Span( RAS_ARGS Short y, @@ -492,10 +473,11 @@ Int numTurns; /* number of Y-turns in outline */ - TPoint* arc; /* current Bezier arc pointer */ + Byte dropOutControl; /* current drop_out control method */ UShort bWidth; /* target bitmap width */ PByte bOrigin; /* target bitmap bottom-left origin */ + PByte bLine; /* target bitmap current line */ Long lastX, lastY; Long minY, maxY; @@ -517,9 +499,6 @@ FT_Bitmap target; /* description of target bit/pixmap */ FT_Outline outline; - Long traceOfs; /* current offset in target bitmap */ - Short traceIncr; /* sweep's increment in target bitmap */ - /* dispatch variables */ Function_Sweep_Init* Proc_Sweep_Init; @@ -527,18 +506,6 @@ Function_Sweep_Span* Proc_Sweep_Drop; Function_Sweep_Step* Proc_Sweep_Step; - Byte dropOutControl; /* current drop_out control method */ - - Bool second_pass; /* indicates whether a horizontal pass */ - /* should be performed to control */ - /* drop-out accurately when calling */ - /* Render_Glyph. */ - - TPoint arcs[3 * MaxBezier + 1]; /* The Bezier stack */ - - black_TBand band_stack[16]; /* band stack used for sub-banding */ - Int band_top; /* band stack top */ - }; @@ -660,7 +627,7 @@ if ( ras.top >= ras.maxBuff ) { - ras.error = FT_THROW( Overflow ); + ras.error = FT_THROW( Raster_Overflow ); return FAILURE; } @@ -689,7 +656,7 @@ default: FT_ERROR(( "New_Profile: invalid profile direction\n" )); - ras.error = FT_THROW( Invalid ); + ras.error = FT_THROW( Invalid_Outline ); return FAILURE; } @@ -731,7 +698,7 @@ if ( h < 0 ) { FT_ERROR(( "End_Profile: negative height encountered\n" )); - ras.error = FT_THROW( Neg_Height ); + ras.error = FT_THROW( Raster_Negative_Height ); return FAILURE; } @@ -767,7 +734,7 @@ if ( ras.top >= ras.maxBuff ) { FT_TRACE1(( "overflow in End_Profile\n" )); - ras.error = FT_THROW( Overflow ); + ras.error = FT_THROW( Raster_Overflow ); return FAILURE; } @@ -822,7 +789,7 @@ ras.maxBuff--; if ( ras.maxBuff <= ras.top ) { - ras.error = FT_THROW( Overflow ); + ras.error = FT_THROW( Raster_Overflow ); return FAILURE; } ras.numTurns++; @@ -1086,7 +1053,7 @@ size = e2 - e1 + 1; if ( ras.top + size >= ras.maxBuff ) { - ras.error = FT_THROW( Overflow ); + ras.error = FT_THROW( Raster_Overflow ); return FAILURE; } @@ -1209,6 +1176,7 @@ */ static Bool Bezier_Up( RAS_ARGS Int degree, + TPoint* arc, TSplitter splitter, Long miny, Long maxy ) @@ -1216,13 +1184,11 @@ Long y1, y2, e, e2, e0; Short f1; - TPoint* arc; TPoint* start_arc; PLong top; - arc = ras.arc; y1 = arc[degree].y; y2 = arc[0].y; top = ras.top; @@ -1271,7 +1237,7 @@ if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff ) { ras.top = top; - ras.error = FT_THROW( Overflow ); + ras.error = FT_THROW( Raster_Overflow ); return FAILURE; } @@ -1314,7 +1280,6 @@ Fin: ras.top = top; - ras.arc -= degree; return SUCCESS; } @@ -1346,11 +1311,11 @@ */ static Bool Bezier_Down( RAS_ARGS Int degree, + TPoint* arc, TSplitter splitter, Long miny, Long maxy ) { - TPoint* arc = ras.arc; Bool result, fresh; @@ -1362,7 +1327,7 @@ fresh = ras.fresh; - result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny ); + result = Bezier_Up( RAS_VARS degree, arc, splitter, -maxy, -miny ); if ( fresh && !ras.fresh ) ras.cProfile->start = -ras.cProfile->start; @@ -1503,22 +1468,24 @@ { Long y1, y2, y3, x3, ymin, ymax; TStates state_bez; + TPoint arcs[2 * MaxBezier + 1]; /* The Bezier stack */ + TPoint* arc; /* current Bezier arc pointer */ - ras.arc = ras.arcs; - ras.arc[2].x = ras.lastX; - ras.arc[2].y = ras.lastY; - ras.arc[1].x = cx; - ras.arc[1].y = cy; - ras.arc[0].x = x; - ras.arc[0].y = y; + arc = arcs; + arc[2].x = ras.lastX; + arc[2].y = ras.lastY; + arc[1].x = cx; + arc[1].y = cy; + arc[0].x = x; + arc[0].y = y; do { - y1 = ras.arc[2].y; - y2 = ras.arc[1].y; - y3 = ras.arc[0].y; - x3 = ras.arc[0].x; + y1 = arc[2].y; + y2 = arc[1].y; + y3 = arc[0].y; + x3 = arc[0].x; /* first, categorize the Bezier arc */ @@ -1536,13 +1503,13 @@ if ( y2 < ymin || y2 > ymax ) { /* this arc has no given direction, split it! */ - Split_Conic( ras.arc ); - ras.arc += 2; + Split_Conic( arc ); + arc += 2; } else if ( y1 == y3 ) { /* this arc is flat, ignore it and pop it from the Bezier stack */ - ras.arc -= 2; + arc -= 2; } else { @@ -1569,15 +1536,18 @@ /* now call the appropriate routine */ if ( state_bez == Ascending_State ) { - if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) ) + if ( Bezier_Up( RAS_VARS 2, arc, Split_Conic, + ras.minY, ras.maxY ) ) goto Fail; } else - if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) ) + if ( Bezier_Down( RAS_VARS 2, arc, Split_Conic, + ras.minY, ras.maxY ) ) goto Fail; + arc -= 2; } - } while ( ras.arc >= ras.arcs ); + } while ( arc >= arcs ); ras.lastX = x3; ras.lastY = y3; @@ -1632,25 +1602,27 @@ { Long y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2; TStates state_bez; + TPoint arcs[3 * MaxBezier + 1]; /* The Bezier stack */ + TPoint* arc; /* current Bezier arc pointer */ - ras.arc = ras.arcs; - ras.arc[3].x = ras.lastX; - ras.arc[3].y = ras.lastY; - ras.arc[2].x = cx1; - ras.arc[2].y = cy1; - ras.arc[1].x = cx2; - ras.arc[1].y = cy2; - ras.arc[0].x = x; - ras.arc[0].y = y; + arc = arcs; + arc[3].x = ras.lastX; + arc[3].y = ras.lastY; + arc[2].x = cx1; + arc[2].y = cy1; + arc[1].x = cx2; + arc[1].y = cy2; + arc[0].x = x; + arc[0].y = y; do { - y1 = ras.arc[3].y; - y2 = ras.arc[2].y; - y3 = ras.arc[1].y; - y4 = ras.arc[0].y; - x4 = ras.arc[0].x; + y1 = arc[3].y; + y2 = arc[2].y; + y3 = arc[1].y; + y4 = arc[0].y; + x4 = arc[0].x; /* first, categorize the Bezier arc */ @@ -1679,13 +1651,13 @@ if ( ymin2 < ymin1 || ymax2 > ymax1 ) { /* this arc has no given direction, split it! */ - Split_Cubic( ras.arc ); - ras.arc += 3; + Split_Cubic( arc ); + arc += 3; } else if ( y1 == y4 ) { /* this arc is flat, ignore it and pop it from the Bezier stack */ - ras.arc -= 3; + arc -= 3; } else { @@ -1711,15 +1683,18 @@ /* compute intersections */ if ( state_bez == Ascending_State ) { - if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) ) + if ( Bezier_Up( RAS_VARS 3, arc, Split_Cubic, + ras.minY, ras.maxY ) ) goto Fail; } else - if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) ) + if ( Bezier_Down( RAS_VARS 3, arc, Split_Cubic, + ras.minY, ras.maxY ) ) goto Fail; + arc -= 3; } - } while ( ras.arc >= ras.arcs ); + } while ( arc >= arcs ); ras.lastX = x4; ras.lastY = y4; @@ -1767,9 +1742,9 @@ * SUCCESS on success, FAILURE on error. */ static Bool - Decompose_Curve( RAS_ARGS UShort first, - UShort last, - Int flipped ) + Decompose_Curve( RAS_ARGS Int first, + Int last, + Int flipped ) { FT_Vector v_last; FT_Vector v_control; @@ -1967,7 +1942,7 @@ return SUCCESS; Invalid_Outline: - ras.error = FT_THROW( Invalid ); + ras.error = FT_THROW( Invalid_Outline ); Fail: return FAILURE; @@ -1994,8 +1969,8 @@ static Bool Convert_Glyph( RAS_ARGS Int flipped ) { - Int i; - UInt start; + Int i; + Int first, last; ras.fProfile = NULL; @@ -2010,8 +1985,7 @@ ras.cProfile->offset = ras.top; ras.num_Profs = 0; - start = 0; - + last = -1; for ( i = 0; i < ras.outline.n_contours; i++ ) { PProfile lastProfile; @@ -2021,12 +1995,11 @@ ras.state = Unknown_State; ras.gProfile = NULL; - if ( Decompose_Curve( RAS_VARS (UShort)start, - (UShort)ras.outline.contours[i], - flipped ) ) - return FAILURE; + first = last + 1; + last = ras.outline.contours[i]; - start = (UShort)ras.outline.contours[i] + 1; + if ( Decompose_Curve( RAS_VARS first, last, flipped ) ) + return FAILURE; /* we must now check whether the extreme arcs join or not */ if ( FRAC( ras.lastY ) == 0 && @@ -2120,8 +2093,8 @@ * Removes an old profile from a linked list. */ static void - DelOld( PProfileList list, - PProfile profile ) + DelOld( PProfileList list, + const PProfile profile ) { PProfile *old, current; @@ -2214,16 +2187,13 @@ */ static void - Vertical_Sweep_Init( RAS_ARGS Short* min, - Short* max ) + Vertical_Sweep_Init( RAS_ARGS Short min, + Short max ) { - Long pitch = ras.target.pitch; - FT_UNUSED( max ); - ras.traceIncr = (Short)-pitch; - ras.traceOfs = -*min * pitch; + ras.bLine = ras.bOrigin - min * ras.target.pitch; } @@ -2234,8 +2204,7 @@ PProfile left, PProfile right ) { - Long e1, e2; - Byte* target; + Long e1, e2; Int dropOutControl = left->flags & 7; @@ -2248,8 +2217,8 @@ /* represent multiples of 1/(1<<12) = 1/4096 */ FT_TRACE7(( " y=%d x=[% .12f;% .12f]", y, - x1 / (double)ras.precision, - x2 / (double)ras.precision )); + (double)x1 / (double)ras.precision, + (double)x2 / (double)ras.precision )); /* Drop-out control */ @@ -2268,6 +2237,8 @@ if ( e2 >= 0 && e1 < ras.bWidth ) { + Byte* target; + Int c1, c2; Byte f1, f2; @@ -2285,7 +2256,7 @@ f1 = (Byte) ( 0xFF >> ( e1 & 7 ) ); f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) ); - target = ras.bOrigin + ras.traceOfs + c1; + target = ras.bLine + c1; c2 -= c1; if ( c2 > 0 ) @@ -2296,7 +2267,7 @@ /* This is due to the fact that, in the vast majority of cases, */ /* the span length in bytes is relatively small. */ while ( --c2 > 0 ) - *(++target) = 0xFF; + *( ++target ) = 0xFF; target[1] |= f2; } @@ -2321,8 +2292,8 @@ FT_TRACE7(( " y=%d x=[% .12f;% .12f]", y, - x1 / (double)ras.precision, - x2 / (double)ras.precision )); + (double)x1 / (double)ras.precision, + (double)x2 / (double)ras.precision )); /* Drop-out control */ @@ -2437,8 +2408,8 @@ c1 = (Short)( e1 >> 3 ); f1 = (Short)( e1 & 7 ); - if ( e1 >= 0 && e1 < ras.bWidth && - ras.bOrigin[ras.traceOfs + c1] & ( 0x80 >> f1 ) ) + if ( e1 >= 0 && e1 < ras.bWidth && + ras.bLine[c1] & ( 0x80 >> f1 ) ) goto Exit; } else @@ -2454,7 +2425,7 @@ c1 = (Short)( e1 >> 3 ); f1 = (Short)( e1 & 7 ); - ras.bOrigin[ras.traceOfs + c1] |= (char)( 0x80 >> f1 ); + ras.bLine[c1] |= (char)( 0x80 >> f1 ); } Exit: @@ -2465,7 +2436,7 @@ static void Vertical_Sweep_Step( RAS_ARG ) { - ras.traceOfs += ras.traceIncr; + ras.bLine -= ras.target.pitch; } @@ -2479,8 +2450,8 @@ */ static void - Horizontal_Sweep_Init( RAS_ARGS Short* min, - Short* max ) + Horizontal_Sweep_Init( RAS_ARGS Short min, + Short max ) { /* nothing, really */ FT_UNUSED_RASTER; @@ -2504,8 +2475,8 @@ FT_TRACE7(( " x=%d y=[% .12f;% .12f]", y, - x1 / (double)ras.precision, - x2 / (double)ras.precision )); + (double)x1 / (double)ras.precision, + (double)x2 / (double)ras.precision )); /* We should not need this procedure but the vertical sweep */ /* mishandles horizontal lines through pixel centers. So we */ @@ -2575,8 +2546,8 @@ FT_TRACE7(( " x=%d y=[% .12f;% .12f]", y, - x1 / (double)ras.precision, - x2 / (double)ras.precision )); + (double)x1 / (double)ras.precision, + (double)x2 / (double)ras.precision )); /* During the horizontal sweep, we only take care of drop-outs */ @@ -2744,13 +2715,13 @@ /* check the Y-turns */ if ( ras.numTurns == 0 ) { - ras.error = FT_THROW( Invalid ); + ras.error = FT_THROW( Invalid_Outline ); return FAILURE; } /* now initialize the sweep */ - ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y ); + ras.Proc_Sweep_Init( RAS_VARS min_Y, max_Y ); /* then compute the distance of each profile from min_Y */ @@ -2977,11 +2948,11 @@ FT_Outline_Get_CBox( const FT_Outline* outline, FT_BBox *acbox ) { - Long xMin, yMin, xMax, yMax; - - if ( outline && acbox ) { + Long xMin, yMin, xMax, yMax; + + if ( outline->n_points == 0 ) { xMin = 0; @@ -3039,63 +3010,54 @@ * Renderer error code. */ static int - Render_Single_Pass( RAS_ARGS Bool flipped ) + Render_Single_Pass( RAS_ARGS Bool flipped, + Int y_min, + Int y_max ) { - Short i, j, k; + Int y_mid; + Int band_top = 0; + Int band_stack[32]; /* enough to bisect 32-bit int bands */ - while ( ras.band_top >= 0 ) + while ( 1 ) { - ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision; - ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision; + ras.minY = (Long)y_min * ras.precision; + ras.maxY = (Long)y_max * ras.precision; ras.top = ras.buff; - ras.error = Raster_Err_None; + ras.error = Raster_Err_Ok; if ( Convert_Glyph( RAS_VARS flipped ) ) { - if ( ras.error != Raster_Err_Overflow ) - return FAILURE; - - ras.error = Raster_Err_None; + if ( ras.error != Raster_Err_Raster_Overflow ) + return ras.error; /* sub-banding */ -#ifdef DEBUG_RASTER - ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) ); -#endif + if ( y_min == y_max ) + return ras.error; /* still Raster_Overflow */ - i = ras.band_stack[ras.band_top].y_min; - j = ras.band_stack[ras.band_top].y_max; + y_mid = ( y_min + y_max ) >> 1; - k = (Short)( ( i + j ) / 2 ); - - if ( ras.band_top >= 7 || k < i ) - { - ras.band_top = 0; - ras.error = FT_THROW( Invalid ); - - return ras.error; - } - - ras.band_stack[ras.band_top + 1].y_min = k; - ras.band_stack[ras.band_top + 1].y_max = j; - - ras.band_stack[ras.band_top].y_max = (Short)( k - 1 ); - - ras.band_top++; + band_stack[band_top++] = y_min; + y_min = y_mid + 1; } else { if ( ras.fProfile ) if ( Draw_Sweep( RAS_VAR ) ) return ras.error; - ras.band_top--; + + if ( --band_top < 0 ) + break; + + y_max = y_min - 1; + y_min = band_stack[band_top]; } } - return SUCCESS; + return Raster_Err_Ok; } @@ -3132,9 +3094,6 @@ ras.dropOutControl += 1; } - ras.second_pass = (Bool)( !( ras.outline.flags & - FT_OUTLINE_SINGLE_PASS ) ); - /* Vertical Sweep */ FT_TRACE7(( "Vertical pass (ftraster)\n" )); @@ -3143,21 +3102,18 @@ ras.Proc_Sweep_Drop = Vertical_Sweep_Drop; ras.Proc_Sweep_Step = Vertical_Sweep_Step; - ras.band_top = 0; - ras.band_stack[0].y_min = 0; - ras.band_stack[0].y_max = (Short)( ras.target.rows - 1 ); - ras.bWidth = (UShort)ras.target.width; ras.bOrigin = (Byte*)ras.target.buffer; if ( ras.target.pitch > 0 ) ras.bOrigin += (Long)( ras.target.rows - 1 ) * ras.target.pitch; - if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 ) + error = Render_Single_Pass( RAS_VARS 0, 0, (Int)ras.target.rows - 1 ); + if ( error ) return error; /* Horizontal Sweep */ - if ( ras.second_pass && ras.dropOutControl != 2 ) + if ( !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS ) ) { FT_TRACE7(( "Horizontal pass (ftraster)\n" )); @@ -3166,22 +3122,12 @@ ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop; ras.Proc_Sweep_Step = Horizontal_Sweep_Step; - ras.band_top = 0; - ras.band_stack[0].y_min = 0; - ras.band_stack[0].y_max = (Short)( ras.target.width - 1 ); - - if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 ) + error = Render_Single_Pass( RAS_VARS 1, 0, (Int)ras.target.width - 1 ); + if ( error ) return error; } - return Raster_Err_None; - } - - - static void - ft_black_init( black_PRaster raster ) - { - FT_UNUSED( raster ); + return Raster_Err_Ok; } @@ -3202,7 +3148,6 @@ *araster = (FT_Raster)&the_raster; FT_ZERO( &the_raster ); - ft_black_init( &the_raster ); return 0; } @@ -3220,30 +3165,30 @@ static int - ft_black_new( FT_Memory memory, - black_PRaster *araster ) + ft_black_new( void* memory_, /* FT_Memory */ + FT_Raster *araster_ ) /* black_PRaster */ { + FT_Memory memory = (FT_Memory)memory_; + black_PRaster *araster = (black_PRaster*)araster_; + FT_Error error; black_PRaster raster = NULL; - *araster = 0; if ( !FT_NEW( raster ) ) - { raster->memory = memory; - ft_black_init( raster ); - *araster = raster; - } + *araster = raster; return error; } static void - ft_black_done( black_PRaster raster ) + ft_black_done( FT_Raster raster_ ) /* black_PRaster */ { - FT_Memory memory = (FT_Memory)raster->memory; + black_PRaster raster = (black_PRaster)raster_; + FT_Memory memory = (FT_Memory)raster->memory; FT_FREE( raster ); @@ -3292,38 +3237,36 @@ if ( !raster ) - return FT_THROW( Not_Ini ); + return FT_THROW( Raster_Uninitialized ); if ( !outline ) - return FT_THROW( Invalid ); + return FT_THROW( Invalid_Outline ); /* return immediately if the outline is empty */ if ( outline->n_points == 0 || outline->n_contours <= 0 ) - return Raster_Err_None; + return Raster_Err_Ok; if ( !outline->contours || !outline->points ) - return FT_THROW( Invalid ); + return FT_THROW( Invalid_Outline ); if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 ) - return FT_THROW( Invalid ); + return FT_THROW( Invalid_Outline ); /* this version of the raster does not support direct rendering, sorry */ - if ( params->flags & FT_RASTER_FLAG_DIRECT ) - return FT_THROW( Unsupported ); - - if ( params->flags & FT_RASTER_FLAG_AA ) - return FT_THROW( Unsupported ); + if ( params->flags & FT_RASTER_FLAG_DIRECT || + params->flags & FT_RASTER_FLAG_AA ) + return FT_THROW( Cannot_Render_Glyph ); if ( !target_map ) - return FT_THROW( Invalid ); + return FT_THROW( Invalid_Argument ); /* nothing to do */ if ( !target_map->width || !target_map->rows ) - return Raster_Err_None; + return Raster_Err_Ok; if ( !target_map->buffer ) - return FT_THROW( Invalid ); + return FT_THROW( Invalid_Argument ); ras.outline = *outline; ras.target = *target_map; @@ -3340,11 +3283,11 @@ FT_GLYPH_FORMAT_OUTLINE, - (FT_Raster_New_Func) ft_black_new, /* raster_new */ - (FT_Raster_Reset_Func) ft_black_reset, /* raster_reset */ - (FT_Raster_Set_Mode_Func)ft_black_set_mode, /* raster_set_mode */ - (FT_Raster_Render_Func) ft_black_render, /* raster_render */ - (FT_Raster_Done_Func) ft_black_done /* raster_done */ + ft_black_new, /* FT_Raster_New_Func raster_new */ + ft_black_reset, /* FT_Raster_Reset_Func raster_reset */ + ft_black_set_mode, /* FT_Raster_Set_Mode_Func raster_set_mode */ + ft_black_render, /* FT_Raster_Render_Func raster_render */ + ft_black_done /* FT_Raster_Done_Func raster_done */ ) diff --git a/lib/libesp32_lvgl/freetype/src/raster/ftraster.h b/lib/libesp32_lvgl/freetype/src/raster/ftraster.h index 1b2ee3c01..b511b3a99 100644 --- a/lib/libesp32_lvgl/freetype/src/raster/ftraster.h +++ b/lib/libesp32_lvgl/freetype/src/raster/ftraster.h @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used diff --git a/lib/libesp32_lvgl/freetype/src/raster/ftrend1.c b/lib/libesp32_lvgl/freetype/src/raster/ftrend1.c index 57fed9bc1..6d442b1ff 100644 --- a/lib/libesp32_lvgl/freetype/src/raster/ftrend1.c +++ b/lib/libesp32_lvgl/freetype/src/raster/ftrend1.c @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer interface (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -27,8 +27,11 @@ /* initialize renderer -- init its raster */ static FT_Error - ft_raster1_init( FT_Renderer render ) + ft_raster1_init( FT_Module module ) /* FT_Renderer */ { + FT_Renderer render = (FT_Renderer)module; + + render->clazz->raster_class->raster_reset( render->raster, NULL, 0 ); return FT_Err_Ok; @@ -188,18 +191,18 @@ NULL, /* module specific interface */ - (FT_Module_Constructor)ft_raster1_init, /* module_init */ - (FT_Module_Destructor) NULL, /* module_done */ - (FT_Module_Requester) NULL, /* get_interface */ + ft_raster1_init, /* FT_Module_Constructor module_init */ + NULL, /* FT_Module_Destructor module_done */ + NULL, /* FT_Module_Requester get_interface */ FT_GLYPH_FORMAT_OUTLINE, - (FT_Renderer_RenderFunc) ft_raster1_render, /* render_glyph */ - (FT_Renderer_TransformFunc)ft_raster1_transform, /* transform_glyph */ - (FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox, /* get_glyph_cbox */ - (FT_Renderer_SetModeFunc) ft_raster1_set_mode, /* set_mode */ + ft_raster1_render, /* FT_Renderer_RenderFunc render_glyph */ + ft_raster1_transform, /* FT_Renderer_TransformFunc transform_glyph */ + ft_raster1_get_cbox, /* FT_Renderer_GetCBoxFunc get_glyph_cbox */ + ft_raster1_set_mode, /* FT_Renderer_SetModeFunc set_mode */ - (FT_Raster_Funcs*)&ft_standard_raster /* raster_class */ + &ft_standard_raster /* FT_Raster_Funcs* raster_class */ ) diff --git a/lib/libesp32_lvgl/freetype/src/raster/ftrend1.h b/lib/libesp32_lvgl/freetype/src/raster/ftrend1.h index 3f6be5367..cec35c852 100644 --- a/lib/libesp32_lvgl/freetype/src/raster/ftrend1.h +++ b/lib/libesp32_lvgl/freetype/src/raster/ftrend1.h @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer interface (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/raster/module.mk b/lib/libesp32_lvgl/freetype/src/raster/module.mk index 3600732b1..6ad1aa77b 100644 --- a/lib/libesp32_lvgl/freetype/src/raster/module.mk +++ b/lib/libesp32_lvgl/freetype/src/raster/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/raster/raster.c b/lib/libesp32_lvgl/freetype/src/raster/raster.c index cd37943bf..82f474547 100644 --- a/lib/libesp32_lvgl/freetype/src/raster/raster.c +++ b/lib/libesp32_lvgl/freetype/src/raster/raster.c @@ -4,7 +4,7 @@ * * FreeType monochrome rasterer module component (body only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/raster/rasterrs.h b/lib/libesp32_lvgl/freetype/src/raster/rasterrs.h index a29651a6c..989d8b44b 100644 --- a/lib/libesp32_lvgl/freetype/src/raster/rasterrs.h +++ b/lib/libesp32_lvgl/freetype/src/raster/rasterrs.h @@ -4,7 +4,7 @@ * * monochrome renderer error codes (specification only). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/raster/rules.mk b/lib/libesp32_lvgl/freetype/src/raster/rules.mk index 3e949d774..031b85fb9 100644 --- a/lib/libesp32_lvgl/freetype/src/raster/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/raster/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/sdf/ftbsdf.c b/lib/libesp32_lvgl/freetype/src/sdf/ftbsdf.c new file mode 100644 index 000000000..e47273833 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/sdf/ftbsdf.c @@ -0,0 +1,1350 @@ +/**************************************************************************** + * + * ftbsdf.c + * + * Signed Distance Field support for bitmap fonts (body only). + * + * Copyright (C) 2020-2023 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * Written by Anuj Verma. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#include +#include +#include +#include + +#include "ftsdf.h" +#include "ftsdferrs.h" +#include "ftsdfcommon.h" + + + /************************************************************************** + * + * A brief technical overview of how the BSDF rasterizer works + * ----------------------------------------------------------- + * + * [Notes]: + * * SDF stands for Signed Distance Field everywhere. + * + * * BSDF stands for Bitmap to Signed Distance Field rasterizer. + * + * * This renderer converts rasterized bitmaps to SDF. There is another + * renderer called 'sdf', which generates SDF directly from outlines; + * see file `ftsdf.c` for more. + * + * * The idea of generating SDF from bitmaps is taken from two research + * papers, where one is dependent on the other: + * + * - Per-Erik Danielsson: Euclidean Distance Mapping + * http://webstaff.itn.liu.se/~stegu/JFA/Danielsson.pdf + * + * From this paper we use the eight-point sequential Euclidean + * distance mapping (8SED). This is the heart of the process used + * in this rasterizer. + * + * - Stefan Gustavson, Robin Strand: Anti-aliased Euclidean distance transform. + * http://weber.itn.liu.se/~stegu/aadist/edtaa_preprint.pdf + * + * The original 8SED algorithm discards the pixels' alpha values, + * which can contain information about the actual outline of the + * glyph. This paper takes advantage of those alpha values and + * approximates outline pretty accurately. + * + * * This rasterizer also works for monochrome bitmaps. However, the + * result is not as accurate since we don't have any way to + * approximate outlines from binary bitmaps. + * + * ======================================================================== + * + * Generating SDF from bitmap is done in several steps. + * + * (1) The only information we have is the bitmap itself. It can + * be monochrome or anti-aliased. If it is anti-aliased, pixel values + * are nothing but coverage values. These coverage values can be used + * to extract information about the outline of the image. For + * example, if the pixel's alpha value is 0.5, then we can safely + * assume that the outline passes through the center of the pixel. + * + * (2) Find edge pixels in the bitmap (see `bsdf_is_edge` for more). For + * all edge pixels we use the Anti-aliased Euclidean distance + * transform algorithm and compute approximate edge distances (see + * `compute_edge_distance` and/or the second paper for more). + * + * (3) Now that we have computed approximate distances for edge pixels we + * use the 8SED algorithm to basically sweep the entire bitmap and + * compute distances for the rest of the pixels. (Since the algorithm + * is pretty convoluted it is only explained briefly in a comment to + * function `edt8`. To see the actual algorithm refer to the first + * paper.) + * + * (4) Finally, compute the sign for each pixel. This is done in function + * `finalize_sdf`. The basic idea is that if a pixel's original + * alpha/coverage value is greater than 0.5 then it is 'inside' (and + * 'outside' otherwise). + * + * Pseudo Code: + * + * ``` + * b = source bitmap; + * t = target bitmap; + * dm = list of distances; // dimension equal to b + * + * foreach grid_point (x, y) in b: + * { + * if (is_edge(x, y)): + * dm = approximate_edge_distance(b, x, y); + * + * // do the 8SED on the distances + * edt8(dm); + * + * // determine the signs + * determine_signs(dm): + * + * // copy SDF data to the target bitmap + * copy(dm to t); + * } + * + */ + + + /************************************************************************** + * + * The macro FT_COMPONENT is used in trace mode. It is an implicit + * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log + * messages during execution. + */ +#undef FT_COMPONENT +#define FT_COMPONENT bsdf + + + /************************************************************************** + * + * useful macros + * + */ + +#define ONE 65536 /* 1 in 16.16 */ + + + /************************************************************************** + * + * structs + * + */ + + + /************************************************************************** + * + * @Struct: + * BSDF_TRaster + * + * @Description: + * This struct is used in place of @FT_Raster and is stored within the + * internal FreeType renderer struct. While rasterizing this is passed + * to the @FT_Raster_RenderFunc function, which then can be used however + * we want. + * + * @Fields: + * memory :: + * Used internally to allocate intermediate memory while raterizing. + * + */ + typedef struct BSDF_TRaster_ + { + FT_Memory memory; + + } BSDF_TRaster, *BSDF_PRaster; + + + /************************************************************************** + * + * @Struct: + * ED + * + * @Description: + * Euclidean distance. It gets used for Euclidean distance transforms; + * it can also be interpreted as an edge distance. + * + * @Fields: + * dist :: + * Vector length of the `prox` parameter. Can be squared or absolute + * depending on the `USE_SQUARED_DISTANCES` macro defined in file + * `ftsdfcommon.h`. + * + * prox :: + * Vector to the nearest edge. Can also be interpreted as shortest + * distance of a point. + * + * alpha :: + * Alpha value of the original bitmap from which we generate SDF. + * Needed for computing the gradient and determining the proper sign + * of a pixel. + * + */ + typedef struct ED_ + { + FT_16D16 dist; + FT_16D16_Vec prox; + FT_Byte alpha; + + } ED; + + + /************************************************************************** + * + * @Struct: + * BSDF_Worker + * + * @Description: + * A convenience struct that is passed to functions while generating + * SDF; most of those functions require the same parameters. + * + * @Fields: + * distance_map :: + * A one-dimensional array that gets interpreted as two-dimensional + * one. It contains the Euclidean distances of all points of the + * bitmap. + * + * width :: + * Width of the above `distance_map`. + * + * rows :: + * Number of rows in the above `distance_map`. + * + * params :: + * Internal parameters and properties required by the rasterizer. See + * file `ftsdf.h` for more. + * + */ + typedef struct BSDF_Worker_ + { + ED* distance_map; + + FT_Int width; + FT_Int rows; + + SDF_Raster_Params params; + + } BSDF_Worker; + + + /************************************************************************** + * + * initializer + * + */ + + static const ED zero_ed = { 0, { 0, 0 }, 0 }; + + + /************************************************************************** + * + * rasterizer functions + * + */ + + /************************************************************************** + * + * @Function: + * bsdf_is_edge + * + * @Description: + * Check whether a pixel is an edge pixel, i.e., whether it is + * surrounded by a completely black pixel (zero alpha), and the current + * pixel is not a completely black pixel. + * + * @Input: + * dm :: + * Array of distances. The parameter must point to the current + * pixel, i.e., the pixel that is to be checked for being an edge. + * + * x :: + * The x position of the current pixel. + * + * y :: + * The y position of the current pixel. + * + * w :: + * Width of the bitmap. + * + * r :: + * Number of rows in the bitmap. + * + * @Return: + * 1~if the current pixel is an edge pixel, 0~otherwise. + * + */ + +#ifdef CHECK_NEIGHBOR +#undef CHECK_NEIGHBOR +#endif + +#define CHECK_NEIGHBOR( x_offset, y_offset ) \ + do \ + { \ + if ( x + x_offset >= 0 && x + x_offset < w && \ + y + y_offset >= 0 && y + y_offset < r ) \ + { \ + num_neighbors++; \ + \ + to_check = dm + y_offset * w + x_offset; \ + if ( to_check->alpha == 0 ) \ + { \ + is_edge = 1; \ + goto Done; \ + } \ + } \ + } while ( 0 ) + + static FT_Bool + bsdf_is_edge( ED* dm, /* distance map */ + FT_Int x, /* x index of point to check */ + FT_Int y, /* y index of point to check */ + FT_Int w, /* width */ + FT_Int r ) /* rows */ + { + FT_Bool is_edge = 0; + ED* to_check = NULL; + FT_Int num_neighbors = 0; + + + if ( dm->alpha == 0 ) + goto Done; + + if ( dm->alpha > 0 && dm->alpha < 255 ) + { + is_edge = 1; + goto Done; + } + + /* up */ + CHECK_NEIGHBOR( 0, -1 ); + + /* down */ + CHECK_NEIGHBOR( 0, 1 ); + + /* left */ + CHECK_NEIGHBOR( -1, 0 ); + + /* right */ + CHECK_NEIGHBOR( 1, 0 ); + + /* up left */ + CHECK_NEIGHBOR( -1, -1 ); + + /* up right */ + CHECK_NEIGHBOR( 1, -1 ); + + /* down left */ + CHECK_NEIGHBOR( -1, 1 ); + + /* down right */ + CHECK_NEIGHBOR( 1, 1 ); + + if ( num_neighbors != 8 ) + is_edge = 1; + + Done: + return is_edge; + } + +#undef CHECK_NEIGHBOR + + + /************************************************************************** + * + * @Function: + * compute_edge_distance + * + * @Description: + * Approximate the outline and compute the distance from `current` + * to the approximated outline. + * + * @Input: + * current :: + * Array of Euclidean distances. `current` must point to the position + * for which the distance is to be caculated. We treat this array as + * a two-dimensional array mapped to a one-dimensional array. + * + * x :: + * The x coordinate of the `current` parameter in the array. + * + * y :: + * The y coordinate of the `current` parameter in the array. + * + * w :: + * The width of the distances array. + * + * r :: + * Number of rows in the distances array. + * + * @Return: + * A vector pointing to the approximate edge distance. + * + * @Note: + * This is a computationally expensive function. Try to reduce the + * number of calls to this function. Moreover, this must only be used + * for edge pixel positions. + * + */ + static FT_16D16_Vec + compute_edge_distance( ED* current, + FT_Int x, + FT_Int y, + FT_Int w, + FT_Int r ) + { + /* + * This function, based on the paper presented by Stefan Gustavson and + * Robin Strand, gets used to approximate edge distances from + * anti-aliased bitmaps. + * + * The algorithm is as follows. + * + * (1) In anti-aliased images, the pixel's alpha value is the coverage + * of the pixel by the outline. For example, if the alpha value is + * 0.5f we can assume that the outline passes through the center of + * the pixel. + * + * (2) For this reason we can use that alpha value to approximate the real + * distance of the pixel to edge pretty accurately. A simple + * approximation is `(0.5f - alpha)`, assuming that the outline is + * parallel to the x or y~axis. However, in this algorithm we use a + * different approximation which is quite accurate even for + * non-axis-aligned edges. + * + * (3) The only remaining piece of information that we cannot + * approximate directly from the alpha is the direction of the edge. + * This is where we use Sobel's operator to compute the gradient of + * the pixel. The gradient give us a pretty good approximation of + * the edge direction. We use a 3x3 kernel filter to compute the + * gradient. + * + * (4) After the above two steps we have both the direction and the + * distance to the edge which is used to generate the Signed + * Distance Field. + * + * References: + * + * - Anti-Aliased Euclidean Distance Transform: + * http://weber.itn.liu.se/~stegu/aadist/edtaa_preprint.pdf + * - Sobel Operator: + * https://en.wikipedia.org/wiki/Sobel_operator + */ + + FT_16D16_Vec g = { 0, 0 }; + FT_16D16 dist, current_alpha; + FT_16D16 a1, temp; + FT_16D16 gx, gy; + FT_16D16 alphas[9]; + + + /* Since our spread cannot be 0, this condition */ + /* can never be true. */ + if ( x <= 0 || x >= w - 1 || + y <= 0 || y >= r - 1 ) + return g; + + /* initialize the alphas */ + alphas[0] = 256 * (FT_16D16)current[-w - 1].alpha; + alphas[1] = 256 * (FT_16D16)current[-w ].alpha; + alphas[2] = 256 * (FT_16D16)current[-w + 1].alpha; + alphas[3] = 256 * (FT_16D16)current[ -1].alpha; + alphas[4] = 256 * (FT_16D16)current[ 0].alpha; + alphas[5] = 256 * (FT_16D16)current[ 1].alpha; + alphas[6] = 256 * (FT_16D16)current[ w - 1].alpha; + alphas[7] = 256 * (FT_16D16)current[ w ].alpha; + alphas[8] = 256 * (FT_16D16)current[ w + 1].alpha; + + current_alpha = alphas[4]; + + /* Compute the gradient using the Sobel operator. */ + /* In this case we use the following 3x3 filters: */ + /* */ + /* For x: | -1 0 -1 | */ + /* | -root(2) 0 root(2) | */ + /* | -1 0 1 | */ + /* */ + /* For y: | -1 -root(2) -1 | */ + /* | 0 0 0 | */ + /* | 1 root(2) 1 | */ + /* */ + /* [Note]: 92681 is root(2) in 16.16 format. */ + g.x = -alphas[0] - + FT_MulFix( alphas[3], 92681 ) - + alphas[6] + + alphas[2] + + FT_MulFix( alphas[5], 92681 ) + + alphas[8]; + + g.y = -alphas[0] - + FT_MulFix( alphas[1], 92681 ) - + alphas[2] + + alphas[6] + + FT_MulFix( alphas[7], 92681 ) + + alphas[8]; + + FT_Vector_NormLen( &g ); + + /* The gradient gives us the direction of the */ + /* edge for the current pixel. Once we have the */ + /* approximate direction of the edge, we can */ + /* approximate the edge distance much better. */ + + if ( g.x == 0 || g.y == 0 ) + dist = ONE / 2 - alphas[4]; + else + { + gx = g.x; + gy = g.y; + + gx = FT_ABS( gx ); + gy = FT_ABS( gy ); + + if ( gx < gy ) + { + temp = gx; + gx = gy; + gy = temp; + } + + a1 = FT_DivFix( gy, gx ) / 2; + + if ( current_alpha < a1 ) + dist = ( gx + gy ) / 2 - + square_root( 2 * FT_MulFix( gx, + FT_MulFix( gy, + current_alpha ) ) ); + + else if ( current_alpha < ( ONE - a1 ) ) + dist = FT_MulFix( ONE / 2 - current_alpha, gx ); + + else + dist = -( gx + gy ) / 2 + + square_root( 2 * FT_MulFix( gx, + FT_MulFix( gy, + ONE - current_alpha ) ) ); + } + + g.x = FT_MulFix( g.x, dist ); + g.y = FT_MulFix( g.y, dist ); + + return g; + } + + + /************************************************************************** + * + * @Function: + * bsdf_approximate_edge + * + * @Description: + * Loops over all the pixels and call `compute_edge_distance` only for + * edge pixels. This maked the process a lot faster since + * `compute_edge_distance` uses functions such as `FT_Vector_NormLen', + * which are quite slow. + * + * @InOut: + * worker :: + * Contains the distance map as well as all the relevant parameters + * required by the function. + * + * @Return: + * FreeType error, 0 means success. + * + * @Note: + * The function directly manipulates `worker->distance_map`. + * + */ + static FT_Error + bsdf_approximate_edge( BSDF_Worker* worker ) + { + FT_Error error = FT_Err_Ok; + FT_Int i, j; + FT_Int index; + ED* ed; + + + if ( !worker || !worker->distance_map ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + ed = worker->distance_map; + + for ( j = 0; j < worker->rows; j++ ) + { + for ( i = 0; i < worker->width; i++ ) + { + index = j * worker->width + i; + + if ( bsdf_is_edge( worker->distance_map + index, + i, j, + worker->width, + worker->rows ) ) + { + /* approximate the edge distance for edge pixels */ + ed[index].prox = compute_edge_distance( ed + index, + i, j, + worker->width, + worker->rows ); + ed[index].dist = VECTOR_LENGTH_16D16( ed[index].prox ); + } + else + { + /* for non-edge pixels assign far away distances */ + ed[index].dist = 400 * ONE; + ed[index].prox.x = 200 * ONE; + ed[index].prox.y = 200 * ONE; + } + } + } + + Exit: + return error; + } + + + /************************************************************************** + * + * @Function: + * bsdf_init_distance_map + * + * @Description: + * Initialize the distance map according to the '8-point sequential + * Euclidean distance mapping' (8SED) algorithm. Basically it copies + * the `source` bitmap alpha values to the `distance_map->alpha` + * parameter of `worker`. + * + * @Input: + * source :: + * Source bitmap to copy the data from. + * + * @Output: + * worker :: + * Target distance map to copy the data to. + * + * @Return: + * FreeType error, 0 means success. + * + */ + static FT_Error + bsdf_init_distance_map( const FT_Bitmap* source, + BSDF_Worker* worker ) + { + FT_Error error = FT_Err_Ok; + + FT_Int x_diff, y_diff; + FT_Int t_i, t_j, s_i, s_j; + FT_Byte* s; + ED* t; + + + /* again check the parameters (probably unnecessary) */ + if ( !source || !worker ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + /* Because of the way we convert a bitmap to SDF, */ + /* i.e., aligning the source to the center of the */ + /* target, the target's width and rows must be */ + /* checked before copying. */ + if ( worker->width < (FT_Int)source->width || + worker->rows < (FT_Int)source->rows ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + /* check pixel mode */ + if ( source->pixel_mode == FT_PIXEL_MODE_NONE ) + { + FT_ERROR(( "bsdf_copy_source_to_target:" + " Invalid pixel mode of source bitmap" )); + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + +#ifdef FT_DEBUG_LEVEL_TRACE + if ( source->pixel_mode == FT_PIXEL_MODE_MONO ) + { + FT_TRACE0(( "bsdf_copy_source_to_target:" + " The `bsdf' renderer can convert monochrome\n" )); + FT_TRACE0(( " " + " bitmaps to SDF but the results are not perfect\n" )); + FT_TRACE0(( " " + " because there is no way to approximate actual\n" )); + FT_TRACE0(( " " + " outlines from monochrome bitmaps. Consider\n" )); + FT_TRACE0(( " " + " using an anti-aliased bitmap instead.\n" )); + } +#endif + + /* Calculate the width and row differences */ + /* between target and source. */ + x_diff = worker->width - (int)source->width; + y_diff = worker->rows - (int)source->rows; + + x_diff /= 2; + y_diff /= 2; + + t = (ED*)worker->distance_map; + s = source->buffer; + + /* For now we only support pixel mode `FT_PIXEL_MODE_MONO` */ + /* and `FT_PIXEL_MODE_GRAY`. More will be added later. */ + /* */ + /* [NOTE]: We can also use @FT_Bitmap_Convert to convert */ + /* bitmap to 8bpp. To avoid extra allocation and */ + /* since the target bitmap can be 16bpp we manually */ + /* convert the source bitmap to the desired bpp. */ + + switch ( source->pixel_mode ) + { + case FT_PIXEL_MODE_MONO: + { + FT_Int t_width = worker->width; + FT_Int t_rows = worker->rows; + FT_Int s_width = (int)source->width; + FT_Int s_rows = (int)source->rows; + + + for ( t_j = 0; t_j < t_rows; t_j++ ) + { + for ( t_i = 0; t_i < t_width; t_i++ ) + { + FT_Int t_index = t_j * t_width + t_i; + FT_Int s_index; + FT_Int div, mod; + FT_Byte pixel, byte; + + + t[t_index] = zero_ed; + + s_i = t_i - x_diff; + s_j = t_j - y_diff; + + /* Assign 0 to padding similar to */ + /* the source bitmap. */ + if ( s_i < 0 || s_i >= s_width || + s_j < 0 || s_j >= s_rows ) + continue; + + if ( worker->params.flip_y ) + s_index = ( s_rows - s_j - 1 ) * source->pitch; + else + s_index = s_j * source->pitch; + + div = s_index + s_i / 8; + mod = 7 - s_i % 8; + + pixel = s[div]; + byte = (FT_Byte)( 1 << mod ); + + t[t_index].alpha = pixel & byte ? 255 : 0; + } + } + } + break; + + case FT_PIXEL_MODE_GRAY: + { + FT_Int t_width = worker->width; + FT_Int t_rows = worker->rows; + FT_Int s_width = (int)source->width; + FT_Int s_rows = (int)source->rows; + + + /* loop over all pixels and assign pixel values from source */ + for ( t_j = 0; t_j < t_rows; t_j++ ) + { + for ( t_i = 0; t_i < t_width; t_i++ ) + { + FT_Int t_index = t_j * t_width + t_i; + FT_Int s_index; + + + t[t_index] = zero_ed; + + s_i = t_i - x_diff; + s_j = t_j - y_diff; + + /* Assign 0 to padding similar to */ + /* the source bitmap. */ + if ( s_i < 0 || s_i >= s_width || + s_j < 0 || s_j >= s_rows ) + continue; + + if ( worker->params.flip_y ) + s_index = ( s_rows - s_j - 1 ) * s_width + s_i; + else + s_index = s_j * s_width + s_i; + + /* simply copy the alpha values */ + t[t_index].alpha = s[s_index]; + } + } + } + break; + + default: + FT_ERROR(( "bsdf_copy_source_to_target:" + " unsopported pixel mode of source bitmap\n" )); + + error = FT_THROW( Unimplemented_Feature ); + break; + } + + Exit: + return error; + } + + + /************************************************************************** + * + * @Function: + * compare_neighbor + * + * @Description: + * Compare neighbor pixel (which is defined by the offset) and update + * `current` distance if the new distance is shorter than the original. + * + * @Input: + * x_offset :: + * X offset of the neighbor to be checked. The offset is relative to + * the `current`. + * + * y_offset :: + * Y offset of the neighbor to be checked. The offset is relative to + * the `current`. + * + * width :: + * Width of the `current` array. + * + * @InOut: + * current :: + * Pointer into array of distances. This parameter must point to the + * position whose neighbor is to be checked. The array is treated as + * a two-dimensional array. + * + */ + static void + compare_neighbor( ED* current, + FT_Int x_offset, + FT_Int y_offset, + FT_Int width ) + { + ED* to_check; + FT_16D16 dist; + FT_16D16_Vec dist_vec; + + + to_check = current + ( y_offset * width ) + x_offset; + + /* + * While checking for the nearest point we first approximate the + * distance of `current` by adding the deviation (which is sqrt(2) at + * most). Only if the new value is less than the current value we + * calculate the actual distances using `FT_Vector_Length`. This last + * step can be omitted by using squared distances. + */ + + /* + * Approximate the distance. We subtract 1 to avoid precision errors, + * which could happen because the two directions can be opposite. + */ + dist = to_check->dist - ONE; + + if ( dist < current->dist ) + { + dist_vec = to_check->prox; + + dist_vec.x += x_offset * ONE; + dist_vec.y += y_offset * ONE; + dist = VECTOR_LENGTH_16D16( dist_vec ); + + if ( dist < current->dist ) + { + current->dist = dist; + current->prox = dist_vec; + } + } + } + + + /************************************************************************** + * + * @Function: + * first_pass + * + * @Description: + * First pass of the 8SED algorithm. Loop over the bitmap from top to + * bottom and scan each row left to right, updating the distances in + * `worker->distance_map`. + * + * @InOut: + * worker:: + * Contains all the relevant parameters. + * + */ + static void + first_pass( BSDF_Worker* worker ) + { + FT_Int i, j; /* iterators */ + FT_Int w, r; /* width, rows */ + ED* dm; /* distance map */ + + + dm = worker->distance_map; + w = worker->width; + r = worker->rows; + + /* Start scanning from top to bottom and sweep each */ + /* row back and forth comparing the distances of the */ + /* neighborhood. Leave the first row as it has no top */ + /* neighbor; it will be covered in the second scan of */ + /* the image (from bottom to top). */ + for ( j = 1; j < r; j++ ) + { + FT_Int index; + ED* current; + + + /* Forward pass of rows (left -> right). Leave the first */ + /* column, which gets covered in the backward pass. */ + for ( i = 1; i < w - 1; i++ ) + { + index = j * w + i; + current = dm + index; + + /* left-up */ + compare_neighbor( current, -1, -1, w ); + /* up */ + compare_neighbor( current, 0, -1, w ); + /* up-right */ + compare_neighbor( current, 1, -1, w ); + /* left */ + compare_neighbor( current, -1, 0, w ); + } + + /* Backward pass of rows (right -> left). Leave the last */ + /* column, which was already covered in the forward pass. */ + for ( i = w - 2; i >= 0; i-- ) + { + index = j * w + i; + current = dm + index; + + /* right */ + compare_neighbor( current, 1, 0, w ); + } + } + } + + + /************************************************************************** + * + * @Function: + * second_pass + * + * @Description: + * Second pass of the 8SED algorithm. Loop over the bitmap from bottom + * to top and scan each row left to right, updating the distances in + * `worker->distance_map`. + * + * @InOut: + * worker:: + * Contains all the relevant parameters. + * + */ + static void + second_pass( BSDF_Worker* worker ) + { + FT_Int i, j; /* iterators */ + FT_Int w, r; /* width, rows */ + ED* dm; /* distance map */ + + + dm = worker->distance_map; + w = worker->width; + r = worker->rows; + + /* Start scanning from bottom to top and sweep each */ + /* row back and forth comparing the distances of the */ + /* neighborhood. Leave the last row as it has no down */ + /* neighbor; it is already covered in the first scan */ + /* of the image (from top to bottom). */ + for ( j = r - 2; j >= 0; j-- ) + { + FT_Int index; + ED* current; + + + /* Forward pass of rows (left -> right). Leave the first */ + /* column, which gets covered in the backward pass. */ + for ( i = 1; i < w - 1; i++ ) + { + index = j * w + i; + current = dm + index; + + /* left-up */ + compare_neighbor( current, -1, 1, w ); + /* up */ + compare_neighbor( current, 0, 1, w ); + /* up-right */ + compare_neighbor( current, 1, 1, w ); + /* left */ + compare_neighbor( current, -1, 0, w ); + } + + /* Backward pass of rows (right -> left). Leave the last */ + /* column, which was already covered in the forward pass. */ + for ( i = w - 2; i >= 0; i-- ) + { + index = j * w + i; + current = dm + index; + + /* right */ + compare_neighbor( current, 1, 0, w ); + } + } + } + + + /************************************************************************** + * + * @Function: + * edt8 + * + * @Description: + * Compute the distance map of the a bitmap. Execute both first and + * second pass of the 8SED algorithm. + * + * @InOut: + * worker:: + * Contains all the relevant parameters. + * + * @Return: + * FreeType error, 0 means success. + * + */ + static FT_Error + edt8( BSDF_Worker* worker ) + { + FT_Error error = FT_Err_Ok; + + + if ( !worker || !worker->distance_map ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + /* first scan of the image */ + first_pass( worker ); + + /* second scan of the image */ + second_pass( worker ); + + Exit: + return error; + } + + + /************************************************************************** + * + * @Function: + * finalize_sdf + * + * @Description: + * Copy the SDF data from `worker->distance_map` to the `target` bitmap. + * Also transform the data to output format, (which is 6.10 fixed-point + * format at the moment). + * + * @Input: + * worker :: + * Contains source distance map and other SDF data. + * + * @Output: + * target :: + * Target bitmap to which the SDF data is copied to. + * + * @Return: + * FreeType error, 0 means success. + * + */ + static FT_Error + finalize_sdf( BSDF_Worker* worker, + const FT_Bitmap* target ) + { + FT_Error error = FT_Err_Ok; + + FT_Int w, r; + FT_Int i, j; + + FT_SDFFormat* t_buffer; + FT_16D16 sp_sq, spread; + + + if ( !worker || !target ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + w = (int)target->width; + r = (int)target->rows; + t_buffer = (FT_SDFFormat*)target->buffer; + + if ( w != worker->width || + r != worker->rows ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + spread = (FT_16D16)FT_INT_16D16( worker->params.spread ); + +#if USE_SQUARED_DISTANCES + sp_sq = (FT_16D16)FT_INT_16D16( worker->params.spread * + worker->params.spread ); +#else + sp_sq = (FT_16D16)FT_INT_16D16( worker->params.spread ); +#endif + + for ( j = 0; j < r; j++ ) + { + for ( i = 0; i < w; i++ ) + { + FT_Int index; + FT_16D16 dist; + FT_SDFFormat final_dist; + FT_Char sign; + + + index = j * w + i; + dist = worker->distance_map[index].dist; + + if ( dist < 0 || dist > sp_sq ) + dist = sp_sq; + +#if USE_SQUARED_DISTANCES + dist = square_root( dist ); +#endif + + /* We assume that if the pixel is inside a contour */ + /* its coverage value must be > 127. */ + sign = worker->distance_map[index].alpha < 127 ? -1 : 1; + + /* flip the sign according to the property */ + if ( worker->params.flip_sign ) + sign = -sign; + + /* concatenate from 16.16 to appropriate format */ + final_dist = map_fixed_to_sdf( dist * sign, spread ); + + t_buffer[index] = final_dist; + } + } + + Exit: + return error; + } + + + /************************************************************************** + * + * interface functions + * + */ + + /* called when adding a new module through @FT_Add_Module */ + static FT_Error + bsdf_raster_new( void* memory_, /* FT_Memory */ + FT_Raster* araster_ ) /* BSDF_PRaster* */ + { + FT_Memory memory = (FT_Memory)memory_; + BSDF_PRaster* araster = (BSDF_PRaster*)araster_; + + FT_Error error; + BSDF_PRaster raster = NULL; + + + if ( !FT_NEW( raster ) ) + raster->memory = memory; + + *araster = raster; + + return error; + } + + + /* unused */ + static void + bsdf_raster_reset( FT_Raster raster, + unsigned char* pool_base, + unsigned long pool_size ) + { + FT_UNUSED( raster ); + FT_UNUSED( pool_base ); + FT_UNUSED( pool_size ); + } + + + /* unused */ + static FT_Error + bsdf_raster_set_mode( FT_Raster raster, + unsigned long mode, + void* args ) + { + FT_UNUSED( raster ); + FT_UNUSED( mode ); + FT_UNUSED( args ); + + return FT_Err_Ok; + } + + + /* called while rendering through @FT_Render_Glyph */ + static FT_Error + bsdf_raster_render( FT_Raster raster, + const FT_Raster_Params* params ) + { + FT_Error error = FT_Err_Ok; + FT_Memory memory = NULL; + + const FT_Bitmap* source = NULL; + const FT_Bitmap* target = NULL; + + BSDF_TRaster* bsdf_raster = (BSDF_TRaster*)raster; + BSDF_Worker worker; + + const SDF_Raster_Params* sdf_params = (const SDF_Raster_Params*)params; + + + worker.distance_map = NULL; + + /* check for valid parameters */ + if ( !raster || !params ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + /* check whether the flag is set */ + if ( sdf_params->root.flags != FT_RASTER_FLAG_SDF ) + { + error = FT_THROW( Raster_Corrupted ); + goto Exit; + } + + source = (const FT_Bitmap*)sdf_params->root.source; + target = (const FT_Bitmap*)sdf_params->root.target; + + /* check source and target bitmap */ + if ( !source || !target ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + memory = bsdf_raster->memory; + if ( !memory ) + { + FT_TRACE0(( "bsdf_raster_render: Raster not set up properly,\n" )); + FT_TRACE0(( " unable to find memory handle.\n" )); + + error = FT_THROW( Invalid_Handle ); + goto Exit; + } + + /* check whether spread is set properly */ + if ( sdf_params->spread > MAX_SPREAD || + sdf_params->spread < MIN_SPREAD ) + { + FT_TRACE0(( "bsdf_raster_render:" + " The `spread' field of `SDF_Raster_Params'\n" )); + FT_TRACE0(( " " + " is invalid; the value of this field must be\n" )); + FT_TRACE0(( " " + " within [%d, %d].\n", + MIN_SPREAD, MAX_SPREAD )); + FT_TRACE0(( " " + " Also, you must pass `SDF_Raster_Params'\n" )); + FT_TRACE0(( " " + " instead of the default `FT_Raster_Params'\n" )); + FT_TRACE0(( " " + " while calling this function and set the fields\n" )); + FT_TRACE0(( " " + " accordingly.\n" )); + + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + /* set up the worker */ + + /* allocate the distance map */ + if ( FT_QALLOC_MULT( worker.distance_map, target->rows, + target->width * sizeof ( *worker.distance_map ) ) ) + goto Exit; + + worker.width = (int)target->width; + worker.rows = (int)target->rows; + worker.params = *sdf_params; + + FT_CALL( bsdf_init_distance_map( source, &worker ) ); + FT_CALL( bsdf_approximate_edge( &worker ) ); + FT_CALL( edt8( &worker ) ); + FT_CALL( finalize_sdf( &worker, target ) ); + + FT_TRACE0(( "bsdf_raster_render: Total memory used = %ld\n", + worker.width * worker.rows * + (long)sizeof ( *worker.distance_map ) )); + + Exit: + if ( worker.distance_map ) + FT_FREE( worker.distance_map ); + + return error; + } + + + /* called while deleting `FT_Library` only if the module is added */ + static void + bsdf_raster_done( FT_Raster raster ) + { + FT_Memory memory = (FT_Memory)((BSDF_TRaster*)raster)->memory; + + + FT_FREE( raster ); + } + + + FT_DEFINE_RASTER_FUNCS( + ft_bitmap_sdf_raster, + + FT_GLYPH_FORMAT_BITMAP, + + (FT_Raster_New_Func) bsdf_raster_new, /* raster_new */ + (FT_Raster_Reset_Func) bsdf_raster_reset, /* raster_reset */ + (FT_Raster_Set_Mode_Func)bsdf_raster_set_mode, /* raster_set_mode */ + (FT_Raster_Render_Func) bsdf_raster_render, /* raster_render */ + (FT_Raster_Done_Func) bsdf_raster_done /* raster_done */ + ) + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/sdf/ftsdf.c b/lib/libesp32_lvgl/freetype/src/sdf/ftsdf.c new file mode 100644 index 000000000..bc4625d98 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/sdf/ftsdf.c @@ -0,0 +1,3932 @@ +/**************************************************************************** + * + * ftsdf.c + * + * Signed Distance Field support for outline fonts (body). + * + * Copyright (C) 2020-2023 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * Written by Anuj Verma. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#include +#include +#include +#include +#include +#include "ftsdf.h" + +#include "ftsdferrs.h" + + + /************************************************************************** + * + * A brief technical overview of how the SDF rasterizer works + * ---------------------------------------------------------- + * + * [Notes]: + * * SDF stands for Signed Distance Field everywhere. + * + * * This renderer generates SDF directly from outlines. There is + * another renderer called 'bsdf', which converts bitmaps to SDF; see + * file `ftbsdf.c` for more. + * + * * The basic idea of generating the SDF is taken from Viktor Chlumsky's + * research paper. The paper explains both single and multi-channel + * SDF, however, this implementation only generates single-channel SDF. + * + * Chlumsky, Viktor: Shape Decomposition for Multi-channel Distance + * Fields. Master's thesis. Czech Technical University in Prague, + * Faculty of InformationTechnology, 2015. + * + * For more information: https://github.com/Chlumsky/msdfgen + * + * ======================================================================== + * + * Generating SDF from outlines is pretty straightforward. + * + * (1) We have a set of contours that make the outline of a shape/glyph. + * Each contour comprises of several edges, with three types of edges. + * + * * line segments + * * conic Bezier curves + * * cubic Bezier curves + * + * (2) Apart from the outlines we also have a two-dimensional grid, namely + * the bitmap that is used to represent the final SDF data. + * + * (3) In order to generate SDF, our task is to find shortest signed + * distance from each grid point to the outline. The 'signed + * distance' means that if the grid point is filled by any contour + * then its sign is positive, otherwise it is negative. The pseudo + * code is as follows. + * + * ``` + * foreach grid_point (x, y): + * { + * int min_dist = INT_MAX; + * + * foreach contour in outline: + * { + * foreach edge in contour: + * { + * // get shortest distance from point (x, y) to the edge + * d = get_min_dist(x, y, edge); + * + * if (d < min_dist) + * min_dist = d; + * } + * + * bitmap[x, y] = min_dist; + * } + * } + * ``` + * + * (4) After running this algorithm the bitmap contains information about + * the shortest distance from each point to the outline of the shape. + * Of course, while this is the most straightforward way of generating + * SDF, we use various optimizations in our implementation. See the + * `sdf_generate_*' functions in this file for all details. + * + * The optimization currently used by default is subdivision; see + * function `sdf_generate_subdivision` for more. + * + * Also, to see how we compute the shortest distance from a point to + * each type of edge, check out the `get_min_distance_*' functions. + * + */ + + + /************************************************************************** + * + * The macro FT_COMPONENT is used in trace mode. It is an implicit + * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log + * messages during execution. + */ +#undef FT_COMPONENT +#define FT_COMPONENT sdf + + + /************************************************************************** + * + * definitions + * + */ + + /* + * If set to 1, the rasterizer uses Newton-Raphson's method for finding + * the shortest distance from a point to a conic curve. + * + * If set to 0, an analytical method gets used instead, which computes the + * roots of a cubic polynomial to find the shortest distance. However, + * the analytical method can currently underflow; we thus use Newton's + * method by default. + */ +#ifndef USE_NEWTON_FOR_CONIC +#define USE_NEWTON_FOR_CONIC 1 +#endif + + /* + * The number of intervals a Bezier curve gets sampled and checked to find + * the shortest distance. + */ +#define MAX_NEWTON_DIVISIONS 4 + + /* + * The number of steps of Newton's iterations in each interval of the + * Bezier curve. Basically, we run Newton's approximation + * + * x -= Q(t) / Q'(t) + * + * for each division to get the shortest distance. + */ +#define MAX_NEWTON_STEPS 4 + + /* + * The epsilon distance (in 16.16 fractional units) used for corner + * resolving. If the difference of two distances is less than this value + * they will be checked for a corner if they are ambiguous. + */ +#define CORNER_CHECK_EPSILON 32 + +#if 0 + /* + * Coarse grid dimension. Will probably be removed in the future because + * coarse grid optimization is the slowest algorithm. + */ +#define CG_DIMEN 8 +#endif + + + /************************************************************************** + * + * macros + * + */ + +#define MUL_26D6( a, b ) ( ( ( a ) * ( b ) ) / 64 ) +#define VEC_26D6_DOT( p, q ) ( MUL_26D6( p.x, q.x ) + \ + MUL_26D6( p.y, q.y ) ) + + + /************************************************************************** + * + * structures and enums + * + */ + + /************************************************************************** + * + * @Struct: + * SDF_TRaster + * + * @Description: + * This struct is used in place of @FT_Raster and is stored within the + * internal FreeType renderer struct. While rasterizing it is passed to + * the @FT_Raster_RenderFunc function, which then can be used however we + * want. + * + * @Fields: + * memory :: + * Used internally to allocate intermediate memory while raterizing. + * + */ + typedef struct SDF_TRaster_ + { + FT_Memory memory; + + } SDF_TRaster, *SDF_PRaster; + + + /************************************************************************** + * + * @Enum: + * SDF_Edge_Type + * + * @Description: + * Enumeration of all curve types present in fonts. + * + * @Fields: + * SDF_EDGE_UNDEFINED :: + * Undefined edge, simply used to initialize and detect errors. + * + * SDF_EDGE_LINE :: + * Line segment with start and end point. + * + * SDF_EDGE_CONIC :: + * A conic/quadratic Bezier curve with start, end, and one control + * point. + * + * SDF_EDGE_CUBIC :: + * A cubic Bezier curve with start, end, and two control points. + * + */ + typedef enum SDF_Edge_Type_ + { + SDF_EDGE_UNDEFINED = 0, + SDF_EDGE_LINE = 1, + SDF_EDGE_CONIC = 2, + SDF_EDGE_CUBIC = 3 + + } SDF_Edge_Type; + + + /************************************************************************** + * + * @Enum: + * SDF_Contour_Orientation + * + * @Description: + * Enumeration of all orientation values of a contour. We determine the + * orientation by calculating the area covered by a contour. Contrary + * to values returned by @FT_Outline_Get_Orientation, + * `SDF_Contour_Orientation` is independent of the fill rule, which can + * be different for different font formats. + * + * @Fields: + * SDF_ORIENTATION_NONE :: + * Undefined orientation, used for initialization and error detection. + * + * SDF_ORIENTATION_CW :: + * Clockwise orientation (positive area covered). + * + * SDF_ORIENTATION_CCW :: + * Counter-clockwise orientation (negative area covered). + * + * @Note: + * See @FT_Outline_Get_Orientation for more details. + * + */ + typedef enum SDF_Contour_Orientation_ + { + SDF_ORIENTATION_NONE = 0, + SDF_ORIENTATION_CW = 1, + SDF_ORIENTATION_CCW = 2 + + } SDF_Contour_Orientation; + + + /************************************************************************** + * + * @Struct: + * SDF_Edge + * + * @Description: + * Represent an edge of a contour. + * + * @Fields: + * start_pos :: + * Start position of an edge. Valid for all types of edges. + * + * end_pos :: + * Etart position of an edge. Valid for all types of edges. + * + * control_a :: + * A control point of the edge. Valid only for `SDF_EDGE_CONIC` + * and `SDF_EDGE_CUBIC`. + * + * control_b :: + * Another control point of the edge. Valid only for + * `SDF_EDGE_CONIC`. + * + * edge_type :: + * Type of the edge, see @SDF_Edge_Type for all possible edge types. + * + * next :: + * Used to create a singly linked list, which can be interpreted + * as a contour. + * + */ + typedef struct SDF_Edge_ + { + FT_26D6_Vec start_pos; + FT_26D6_Vec end_pos; + FT_26D6_Vec control_a; + FT_26D6_Vec control_b; + + SDF_Edge_Type edge_type; + + struct SDF_Edge_* next; + + } SDF_Edge; + + + /************************************************************************** + * + * @Struct: + * SDF_Contour + * + * @Description: + * Represent a complete contour, which contains a list of edges. + * + * @Fields: + * last_pos :: + * Contains the value of `end_pos' of the last edge in the list of + * edges. Useful while decomposing the outline with + * @FT_Outline_Decompose. + * + * edges :: + * Linked list of all the edges that make the contour. + * + * next :: + * Used to create a singly linked list, which can be interpreted as a + * complete shape or @FT_Outline. + * + */ + typedef struct SDF_Contour_ + { + FT_26D6_Vec last_pos; + SDF_Edge* edges; + + struct SDF_Contour_* next; + + } SDF_Contour; + + + /************************************************************************** + * + * @Struct: + * SDF_Shape + * + * @Description: + * Represent a complete shape, which is the decomposition of + * @FT_Outline. + * + * @Fields: + * memory :: + * Used internally to allocate memory. + * + * contours :: + * Linked list of all the contours that make the shape. + * + */ + typedef struct SDF_Shape_ + { + FT_Memory memory; + SDF_Contour* contours; + + } SDF_Shape; + + + /************************************************************************** + * + * @Struct: + * SDF_Signed_Distance + * + * @Description: + * Represent signed distance of a point, i.e., the distance of the edge + * nearest to the point. + * + * @Fields: + * distance :: + * Distance of the point from the nearest edge. Can be squared or + * absolute depending on the `USE_SQUARED_DISTANCES` macro defined in + * file `ftsdfcommon.h`. + * + * cross :: + * Cross product of the shortest distance vector (i.e., the vector + * from the point to the nearest edge) and the direction of the edge + * at the nearest point. This is used to resolve ambiguities of + * `sign`. + * + * sign :: + * A value used to indicate whether the distance vector is outside or + * inside the contour corresponding to the edge. + * + * @Note: + * `sign` may or may not be correct, therefore it must be checked + * properly in case there is an ambiguity. + * + */ + typedef struct SDF_Signed_Distance_ + { + FT_16D16 distance; + FT_16D16 cross; + FT_Char sign; + + } SDF_Signed_Distance; + + + /************************************************************************** + * + * @Struct: + * SDF_Params + * + * @Description: + * Yet another internal parameters required by the rasterizer. + * + * @Fields: + * orientation :: + * This is not the @SDF_Contour_Orientation value but @FT_Orientation, + * which determines whether clockwise-oriented outlines are to be + * filled or counter-clockwise-oriented ones. + * + * flip_sign :: + * If set to true, flip the sign. By default the points filled by the + * outline are positive. + * + * flip_y :: + * If set to true the output bitmap is upside-down. Can be useful + * because OpenGL and DirectX use different coordinate systems for + * textures. + * + * overload_sign :: + * In the subdivision and bounding box optimization, the default + * outside sign is taken as -1. This parameter can be used to modify + * that behaviour. For example, while generating SDF for a single + * counter-clockwise contour, the outside sign should be 1. + * + */ + typedef struct SDF_Params_ + { + FT_Orientation orientation; + FT_Bool flip_sign; + FT_Bool flip_y; + + FT_Int overload_sign; + + } SDF_Params; + + + /************************************************************************** + * + * constants, initializer, and destructor + * + */ + + static + const FT_Vector zero_vector = { 0, 0 }; + + static + const SDF_Edge null_edge = { { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, + SDF_EDGE_UNDEFINED, NULL }; + + static + const SDF_Contour null_contour = { { 0, 0 }, NULL, NULL }; + + static + const SDF_Shape null_shape = { NULL, NULL }; + + static + const SDF_Signed_Distance max_sdf = { INT_MAX, 0, 0 }; + + + /* Create a new @SDF_Edge on the heap and assigns the `edge` */ + /* pointer to the newly allocated memory. */ + static FT_Error + sdf_edge_new( FT_Memory memory, + SDF_Edge** edge ) + { + FT_Error error = FT_Err_Ok; + SDF_Edge* ptr = NULL; + + + if ( !memory || !edge ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + if ( !FT_QNEW( ptr ) ) + { + *ptr = null_edge; + *edge = ptr; + } + + Exit: + return error; + } + + + /* Free the allocated `edge` variable. */ + static void + sdf_edge_done( FT_Memory memory, + SDF_Edge** edge ) + { + if ( !memory || !edge || !*edge ) + return; + + FT_FREE( *edge ); + } + + + /* Create a new @SDF_Contour on the heap and assign */ + /* the `contour` pointer to the newly allocated memory. */ + static FT_Error + sdf_contour_new( FT_Memory memory, + SDF_Contour** contour ) + { + FT_Error error = FT_Err_Ok; + SDF_Contour* ptr = NULL; + + + if ( !memory || !contour ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + if ( !FT_QNEW( ptr ) ) + { + *ptr = null_contour; + *contour = ptr; + } + + Exit: + return error; + } + + + /* Free the allocated `contour` variable. */ + /* Also free the list of edges. */ + static void + sdf_contour_done( FT_Memory memory, + SDF_Contour** contour ) + { + SDF_Edge* edges; + SDF_Edge* temp; + + + if ( !memory || !contour || !*contour ) + return; + + edges = (*contour)->edges; + + /* release all edges */ + while ( edges ) + { + temp = edges; + edges = edges->next; + + sdf_edge_done( memory, &temp ); + } + + FT_FREE( *contour ); + } + + + /* Create a new @SDF_Shape on the heap and assign */ + /* the `shape` pointer to the newly allocated memory. */ + static FT_Error + sdf_shape_new( FT_Memory memory, + SDF_Shape** shape ) + { + FT_Error error = FT_Err_Ok; + SDF_Shape* ptr = NULL; + + + if ( !memory || !shape ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + if ( !FT_QNEW( ptr ) ) + { + *ptr = null_shape; + ptr->memory = memory; + *shape = ptr; + } + + Exit: + return error; + } + + + /* Free the allocated `shape` variable. */ + /* Also free the list of contours. */ + static void + sdf_shape_done( SDF_Shape** shape ) + { + FT_Memory memory; + SDF_Contour* contours; + SDF_Contour* temp; + + + if ( !shape || !*shape ) + return; + + memory = (*shape)->memory; + contours = (*shape)->contours; + + if ( !memory ) + return; + + /* release all contours */ + while ( contours ) + { + temp = contours; + contours = contours->next; + + sdf_contour_done( memory, &temp ); + } + + /* release the allocated shape struct */ + FT_FREE( *shape ); + } + + + /************************************************************************** + * + * shape decomposition functions + * + */ + + /* This function is called when starting a new contour at `to`, */ + /* which gets added to the shape's list. */ + static FT_Error + sdf_move_to( const FT_26D6_Vec* to, + void* user ) + { + SDF_Shape* shape = ( SDF_Shape* )user; + SDF_Contour* contour = NULL; + + FT_Error error = FT_Err_Ok; + FT_Memory memory = shape->memory; + + + if ( !to || !user ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + FT_CALL( sdf_contour_new( memory, &contour ) ); + + contour->last_pos = *to; + contour->next = shape->contours; + shape->contours = contour; + + Exit: + return error; + } + + + /* This function is called when there is a line in the */ + /* contour. The line starts at the previous edge point and */ + /* stops at `to`. */ + static FT_Error + sdf_line_to( const FT_26D6_Vec* to, + void* user ) + { + SDF_Shape* shape = ( SDF_Shape* )user; + SDF_Edge* edge = NULL; + SDF_Contour* contour = NULL; + + FT_Error error = FT_Err_Ok; + FT_Memory memory = shape->memory; + + + if ( !to || !user ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + contour = shape->contours; + + if ( contour->last_pos.x == to->x && + contour->last_pos.y == to->y ) + goto Exit; + + FT_CALL( sdf_edge_new( memory, &edge ) ); + + edge->edge_type = SDF_EDGE_LINE; + edge->start_pos = contour->last_pos; + edge->end_pos = *to; + + edge->next = contour->edges; + contour->edges = edge; + contour->last_pos = *to; + + Exit: + return error; + } + + + /* This function is called when there is a conic Bezier curve */ + /* in the contour. The curve starts at the previous edge point */ + /* and stops at `to`, with control point `control_1`. */ + static FT_Error + sdf_conic_to( const FT_26D6_Vec* control_1, + const FT_26D6_Vec* to, + void* user ) + { + SDF_Shape* shape = ( SDF_Shape* )user; + SDF_Edge* edge = NULL; + SDF_Contour* contour = NULL; + + FT_Error error = FT_Err_Ok; + FT_Memory memory = shape->memory; + + + if ( !control_1 || !to || !user ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + contour = shape->contours; + + /* If the control point coincides with any of the end points */ + /* then it is a line and should be treated as one to avoid */ + /* unnecessary complexity later in the algorithm. */ + if ( ( contour->last_pos.x == control_1->x && + contour->last_pos.y == control_1->y ) || + ( control_1->x == to->x && + control_1->y == to->y ) ) + { + sdf_line_to( to, user ); + goto Exit; + } + + FT_CALL( sdf_edge_new( memory, &edge ) ); + + edge->edge_type = SDF_EDGE_CONIC; + edge->start_pos = contour->last_pos; + edge->control_a = *control_1; + edge->end_pos = *to; + + edge->next = contour->edges; + contour->edges = edge; + contour->last_pos = *to; + + Exit: + return error; + } + + + /* This function is called when there is a cubic Bezier curve */ + /* in the contour. The curve starts at the previous edge point */ + /* and stops at `to`, with two control points `control_1` and */ + /* `control_2`. */ + static FT_Error + sdf_cubic_to( const FT_26D6_Vec* control_1, + const FT_26D6_Vec* control_2, + const FT_26D6_Vec* to, + void* user ) + { + SDF_Shape* shape = ( SDF_Shape* )user; + SDF_Edge* edge = NULL; + SDF_Contour* contour = NULL; + + FT_Error error = FT_Err_Ok; + FT_Memory memory = shape->memory; + + + if ( !control_2 || !control_1 || !to || !user ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + contour = shape->contours; + + FT_CALL( sdf_edge_new( memory, &edge ) ); + + edge->edge_type = SDF_EDGE_CUBIC; + edge->start_pos = contour->last_pos; + edge->control_a = *control_1; + edge->control_b = *control_2; + edge->end_pos = *to; + + edge->next = contour->edges; + contour->edges = edge; + contour->last_pos = *to; + + Exit: + return error; + } + + + /* Construct the structure to hold all four outline */ + /* decomposition functions. */ + FT_DEFINE_OUTLINE_FUNCS( + sdf_decompose_funcs, + + (FT_Outline_MoveTo_Func) sdf_move_to, /* move_to */ + (FT_Outline_LineTo_Func) sdf_line_to, /* line_to */ + (FT_Outline_ConicTo_Func)sdf_conic_to, /* conic_to */ + (FT_Outline_CubicTo_Func)sdf_cubic_to, /* cubic_to */ + + 0, /* shift */ + 0 /* delta */ + ) + + + /* Decompose `outline` and put it into the `shape` structure. */ + static FT_Error + sdf_outline_decompose( FT_Outline* outline, + SDF_Shape* shape ) + { + FT_Error error = FT_Err_Ok; + + + if ( !outline || !shape ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + error = FT_Outline_Decompose( outline, + &sdf_decompose_funcs, + (void*)shape ); + + Exit: + return error; + } + + + /************************************************************************** + * + * utility functions + * + */ + + /* Return the control box of an edge. The control box is a rectangle */ + /* in which all the control points can fit tightly. */ + static FT_CBox + get_control_box( SDF_Edge edge ) + { + FT_CBox cbox = { 0, 0, 0, 0 }; + FT_Bool is_set = 0; + + + switch ( edge.edge_type ) + { + case SDF_EDGE_CUBIC: + cbox.xMin = edge.control_b.x; + cbox.xMax = edge.control_b.x; + cbox.yMin = edge.control_b.y; + cbox.yMax = edge.control_b.y; + + is_set = 1; + FALL_THROUGH; + + case SDF_EDGE_CONIC: + if ( is_set ) + { + cbox.xMin = edge.control_a.x < cbox.xMin + ? edge.control_a.x + : cbox.xMin; + cbox.xMax = edge.control_a.x > cbox.xMax + ? edge.control_a.x + : cbox.xMax; + + cbox.yMin = edge.control_a.y < cbox.yMin + ? edge.control_a.y + : cbox.yMin; + cbox.yMax = edge.control_a.y > cbox.yMax + ? edge.control_a.y + : cbox.yMax; + } + else + { + cbox.xMin = edge.control_a.x; + cbox.xMax = edge.control_a.x; + cbox.yMin = edge.control_a.y; + cbox.yMax = edge.control_a.y; + + is_set = 1; + } + FALL_THROUGH; + + case SDF_EDGE_LINE: + if ( is_set ) + { + cbox.xMin = edge.start_pos.x < cbox.xMin + ? edge.start_pos.x + : cbox.xMin; + cbox.xMax = edge.start_pos.x > cbox.xMax + ? edge.start_pos.x + : cbox.xMax; + + cbox.yMin = edge.start_pos.y < cbox.yMin + ? edge.start_pos.y + : cbox.yMin; + cbox.yMax = edge.start_pos.y > cbox.yMax + ? edge.start_pos.y + : cbox.yMax; + } + else + { + cbox.xMin = edge.start_pos.x; + cbox.xMax = edge.start_pos.x; + cbox.yMin = edge.start_pos.y; + cbox.yMax = edge.start_pos.y; + } + + cbox.xMin = edge.end_pos.x < cbox.xMin + ? edge.end_pos.x + : cbox.xMin; + cbox.xMax = edge.end_pos.x > cbox.xMax + ? edge.end_pos.x + : cbox.xMax; + + cbox.yMin = edge.end_pos.y < cbox.yMin + ? edge.end_pos.y + : cbox.yMin; + cbox.yMax = edge.end_pos.y > cbox.yMax + ? edge.end_pos.y + : cbox.yMax; + + break; + + default: + break; + } + + return cbox; + } + + + /* Return orientation of a single contour. */ + /* Note that the orientation is independent of the fill rule! */ + /* So, for TTF a clockwise-oriented contour has to be filled */ + /* and the opposite for OTF fonts. */ + static SDF_Contour_Orientation + get_contour_orientation ( SDF_Contour* contour ) + { + SDF_Edge* head = NULL; + FT_26D6 area = 0; + + + /* return none if invalid parameters */ + if ( !contour || !contour->edges ) + return SDF_ORIENTATION_NONE; + + head = contour->edges; + + /* Calculate the area of the control box for all edges. */ + while ( head ) + { + switch ( head->edge_type ) + { + case SDF_EDGE_LINE: + area += MUL_26D6( ( head->end_pos.x - head->start_pos.x ), + ( head->end_pos.y + head->start_pos.y ) ); + break; + + case SDF_EDGE_CONIC: + area += MUL_26D6( head->control_a.x - head->start_pos.x, + head->control_a.y + head->start_pos.y ); + area += MUL_26D6( head->end_pos.x - head->control_a.x, + head->end_pos.y + head->control_a.y ); + break; + + case SDF_EDGE_CUBIC: + area += MUL_26D6( head->control_a.x - head->start_pos.x, + head->control_a.y + head->start_pos.y ); + area += MUL_26D6( head->control_b.x - head->control_a.x, + head->control_b.y + head->control_a.y ); + area += MUL_26D6( head->end_pos.x - head->control_b.x, + head->end_pos.y + head->control_b.y ); + break; + + default: + return SDF_ORIENTATION_NONE; + } + + head = head->next; + } + + /* Clockwise contours cover a positive area, and counter-clockwise */ + /* contours cover a negative area. */ + if ( area > 0 ) + return SDF_ORIENTATION_CW; + else + return SDF_ORIENTATION_CCW; + } + + + /* This function is exactly the same as the one */ + /* in the smooth renderer. It splits a conic */ + /* into two conics exactly half way at t = 0.5. */ + static void + split_conic( FT_26D6_Vec* base ) + { + FT_26D6 a, b; + + + base[4].x = base[2].x; + a = base[0].x + base[1].x; + b = base[1].x + base[2].x; + base[3].x = b / 2; + base[2].x = ( a + b ) / 4; + base[1].x = a / 2; + + base[4].y = base[2].y; + a = base[0].y + base[1].y; + b = base[1].y + base[2].y; + base[3].y = b / 2; + base[2].y = ( a + b ) / 4; + base[1].y = a / 2; + } + + + /* This function is exactly the same as the one */ + /* in the smooth renderer. It splits a cubic */ + /* into two cubics exactly half way at t = 0.5. */ + static void + split_cubic( FT_26D6_Vec* base ) + { + FT_26D6 a, b, c; + + + base[6].x = base[3].x; + a = base[0].x + base[1].x; + b = base[1].x + base[2].x; + c = base[2].x + base[3].x; + base[5].x = c / 2; + c += b; + base[4].x = c / 4; + base[1].x = a / 2; + a += b; + base[2].x = a / 4; + base[3].x = ( a + c ) / 8; + + base[6].y = base[3].y; + a = base[0].y + base[1].y; + b = base[1].y + base[2].y; + c = base[2].y + base[3].y; + base[5].y = c / 2; + c += b; + base[4].y = c / 4; + base[1].y = a / 2; + a += b; + base[2].y = a / 4; + base[3].y = ( a + c ) / 8; + } + + + /* Split a conic Bezier curve into a number of lines */ + /* and add them to `out'. */ + /* */ + /* This function uses recursion; we thus need */ + /* parameter `max_splits' for stopping. */ + static FT_Error + split_sdf_conic( FT_Memory memory, + FT_26D6_Vec* control_points, + FT_UInt max_splits, + SDF_Edge** out ) + { + FT_Error error = FT_Err_Ok; + FT_26D6_Vec cpos[5]; + SDF_Edge* left,* right; + + + if ( !memory || !out ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + /* split conic outline */ + cpos[0] = control_points[0]; + cpos[1] = control_points[1]; + cpos[2] = control_points[2]; + + split_conic( cpos ); + + /* If max number of splits is done */ + /* then stop and add the lines to */ + /* the list. */ + if ( max_splits <= 2 ) + goto Append; + + /* Otherwise keep splitting. */ + FT_CALL( split_sdf_conic( memory, &cpos[0], max_splits / 2, out ) ); + FT_CALL( split_sdf_conic( memory, &cpos[2], max_splits / 2, out ) ); + + /* [NOTE]: This is not an efficient way of */ + /* splitting the curve. Check the deviation */ + /* instead and stop if the deviation is less */ + /* than a pixel. */ + + goto Exit; + + Append: + /* Do allocation and add the lines to the list. */ + + FT_CALL( sdf_edge_new( memory, &left ) ); + FT_CALL( sdf_edge_new( memory, &right ) ); + + left->start_pos = cpos[0]; + left->end_pos = cpos[2]; + left->edge_type = SDF_EDGE_LINE; + + right->start_pos = cpos[2]; + right->end_pos = cpos[4]; + right->edge_type = SDF_EDGE_LINE; + + left->next = right; + right->next = (*out); + *out = left; + + Exit: + return error; + } + + + /* Split a cubic Bezier curve into a number of lines */ + /* and add them to `out`. */ + /* */ + /* This function uses recursion; we thus need */ + /* parameter `max_splits' for stopping. */ + static FT_Error + split_sdf_cubic( FT_Memory memory, + FT_26D6_Vec* control_points, + FT_UInt max_splits, + SDF_Edge** out ) + { + FT_Error error = FT_Err_Ok; + FT_26D6_Vec cpos[7]; + SDF_Edge* left, *right; + const FT_26D6 threshold = ONE_PIXEL / 4; + + + if ( !memory || !out ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + /* split the cubic */ + cpos[0] = control_points[0]; + cpos[1] = control_points[1]; + cpos[2] = control_points[2]; + cpos[3] = control_points[3]; + + /* If the segment is flat enough we won't get any benefit by */ + /* splitting it further, so we can just stop splitting. */ + /* */ + /* Check the deviation of the Bezier curve and stop if it is */ + /* smaller than the pre-defined `threshold` value. */ + if ( FT_ABS( 2 * cpos[0].x - 3 * cpos[1].x + cpos[3].x ) < threshold && + FT_ABS( 2 * cpos[0].y - 3 * cpos[1].y + cpos[3].y ) < threshold && + FT_ABS( cpos[0].x - 3 * cpos[2].x + 2 * cpos[3].x ) < threshold && + FT_ABS( cpos[0].y - 3 * cpos[2].y + 2 * cpos[3].y ) < threshold ) + { + split_cubic( cpos ); + goto Append; + } + + split_cubic( cpos ); + + /* If max number of splits is done */ + /* then stop and add the lines to */ + /* the list. */ + if ( max_splits <= 2 ) + goto Append; + + /* Otherwise keep splitting. */ + FT_CALL( split_sdf_cubic( memory, &cpos[0], max_splits / 2, out ) ); + FT_CALL( split_sdf_cubic( memory, &cpos[3], max_splits / 2, out ) ); + + /* [NOTE]: This is not an efficient way of */ + /* splitting the curve. Check the deviation */ + /* instead and stop if the deviation is less */ + /* than a pixel. */ + + goto Exit; + + Append: + /* Do allocation and add the lines to the list. */ + + FT_CALL( sdf_edge_new( memory, &left) ); + FT_CALL( sdf_edge_new( memory, &right) ); + + left->start_pos = cpos[0]; + left->end_pos = cpos[3]; + left->edge_type = SDF_EDGE_LINE; + + right->start_pos = cpos[3]; + right->end_pos = cpos[6]; + right->edge_type = SDF_EDGE_LINE; + + left->next = right; + right->next = (*out); + *out = left; + + Exit: + return error; + } + + + /* Subdivide an entire shape into line segments */ + /* such that it doesn't look visually different */ + /* from the original curve. */ + static FT_Error + split_sdf_shape( SDF_Shape* shape ) + { + FT_Error error = FT_Err_Ok; + FT_Memory memory; + + SDF_Contour* contours; + SDF_Contour* new_contours = NULL; + + + if ( !shape || !shape->memory ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + contours = shape->contours; + memory = shape->memory; + + /* for each contour */ + while ( contours ) + { + SDF_Edge* edges = contours->edges; + SDF_Edge* new_edges = NULL; + + SDF_Contour* tempc; + + + /* for each edge */ + while ( edges ) + { + SDF_Edge* edge = edges; + SDF_Edge* temp; + + switch ( edge->edge_type ) + { + case SDF_EDGE_LINE: + /* Just create a duplicate edge in case */ + /* it is a line. We can use the same edge. */ + FT_CALL( sdf_edge_new( memory, &temp ) ); + + ft_memcpy( temp, edge, sizeof ( *edge ) ); + + temp->next = new_edges; + new_edges = temp; + break; + + case SDF_EDGE_CONIC: + /* Subdivide the curve and add it to the list. */ + { + FT_26D6_Vec ctrls[3]; + FT_26D6 dx, dy; + FT_UInt num_splits; + + + ctrls[0] = edge->start_pos; + ctrls[1] = edge->control_a; + ctrls[2] = edge->end_pos; + + dx = FT_ABS( ctrls[2].x + ctrls[0].x - 2 * ctrls[1].x ); + dy = FT_ABS( ctrls[2].y + ctrls[0].y - 2 * ctrls[1].y ); + if ( dx < dy ) + dx = dy; + + /* Calculate the number of necessary bisections. Each */ + /* bisection causes a four-fold reduction of the deviation, */ + /* hence we bisect the Bezier curve until the deviation */ + /* becomes less than 1/8 of a pixel. For more details */ + /* check file `ftgrays.c`. */ + num_splits = 1; + while ( dx > ONE_PIXEL / 8 ) + { + dx >>= 2; + num_splits <<= 1; + } + + error = split_sdf_conic( memory, ctrls, num_splits, &new_edges ); + } + break; + + case SDF_EDGE_CUBIC: + /* Subdivide the curve and add it to the list. */ + { + FT_26D6_Vec ctrls[4]; + + + ctrls[0] = edge->start_pos; + ctrls[1] = edge->control_a; + ctrls[2] = edge->control_b; + ctrls[3] = edge->end_pos; + + error = split_sdf_cubic( memory, ctrls, 32, &new_edges ); + } + break; + + default: + error = FT_THROW( Invalid_Argument ); + } + + if ( error != FT_Err_Ok ) + goto Exit; + + edges = edges->next; + } + + /* add to the contours list */ + FT_CALL( sdf_contour_new( memory, &tempc ) ); + + tempc->next = new_contours; + tempc->edges = new_edges; + new_contours = tempc; + new_edges = NULL; + + /* deallocate the contour */ + tempc = contours; + contours = contours->next; + + sdf_contour_done( memory, &tempc ); + } + + shape->contours = new_contours; + + Exit: + return error; + } + + + /************************************************************************** + * + * for debugging + * + */ + +#ifdef FT_DEBUG_LEVEL_TRACE + + static void + sdf_shape_dump( SDF_Shape* shape ) + { + FT_UInt num_contours = 0; + + FT_UInt total_edges = 0; + FT_UInt total_lines = 0; + FT_UInt total_conic = 0; + FT_UInt total_cubic = 0; + + SDF_Contour* contour_list; + + + if ( !shape ) + { + FT_TRACE5(( "sdf_shape_dump: null shape\n" )); + return; + } + + contour_list = shape->contours; + + FT_TRACE5(( "sdf_shape_dump (values are in 26.6 format):\n" )); + + while ( contour_list ) + { + FT_UInt num_edges = 0; + SDF_Edge* edge_list; + SDF_Contour* contour = contour_list; + + + FT_TRACE5(( " Contour %d\n", num_contours )); + + edge_list = contour->edges; + + while ( edge_list ) + { + SDF_Edge* edge = edge_list; + + + FT_TRACE5(( " %3d: ", num_edges )); + + switch ( edge->edge_type ) + { + case SDF_EDGE_LINE: + FT_TRACE5(( "Line: (%ld, %ld) -- (%ld, %ld)\n", + edge->start_pos.x, edge->start_pos.y, + edge->end_pos.x, edge->end_pos.y )); + total_lines++; + break; + + case SDF_EDGE_CONIC: + FT_TRACE5(( "Conic: (%ld, %ld) .. (%ld, %ld) .. (%ld, %ld)\n", + edge->start_pos.x, edge->start_pos.y, + edge->control_a.x, edge->control_a.y, + edge->end_pos.x, edge->end_pos.y )); + total_conic++; + break; + + case SDF_EDGE_CUBIC: + FT_TRACE5(( "Cubic: (%ld, %ld) .. (%ld, %ld)" + " .. (%ld, %ld) .. (%ld %ld)\n", + edge->start_pos.x, edge->start_pos.y, + edge->control_a.x, edge->control_a.y, + edge->control_b.x, edge->control_b.y, + edge->end_pos.x, edge->end_pos.y )); + total_cubic++; + break; + + default: + break; + } + + num_edges++; + total_edges++; + edge_list = edge_list->next; + } + + num_contours++; + contour_list = contour_list->next; + } + + FT_TRACE5(( "\n" )); + FT_TRACE5(( " total number of contours = %d\n", num_contours )); + FT_TRACE5(( " total number of edges = %d\n", total_edges )); + FT_TRACE5(( " |__lines = %d\n", total_lines )); + FT_TRACE5(( " |__conic = %d\n", total_conic )); + FT_TRACE5(( " |__cubic = %d\n", total_cubic )); + } + +#endif /* FT_DEBUG_LEVEL_TRACE */ + + + /************************************************************************** + * + * math functions + * + */ + +#if !USE_NEWTON_FOR_CONIC + + /* [NOTE]: All the functions below down until rasterizer */ + /* can be avoided if we decide to subdivide the */ + /* curve into lines. */ + + /* This function uses Newton's iteration to find */ + /* the cube root of a fixed-point integer. */ + static FT_16D16 + cube_root( FT_16D16 val ) + { + /* [IMPORTANT]: This function is not good as it may */ + /* not break, so use a lookup table instead. Or we */ + /* can use an algorithm similar to `square_root`. */ + + FT_Int v, g, c; + + + if ( val == 0 || + val == -FT_INT_16D16( 1 ) || + val == FT_INT_16D16( 1 ) ) + return val; + + v = val < 0 ? -val : val; + g = square_root( v ); + c = 0; + + while ( 1 ) + { + c = FT_MulFix( FT_MulFix( g, g ), g ) - v; + c = FT_DivFix( c, 3 * FT_MulFix( g, g ) ); + + g -= c; + + if ( ( c < 0 ? -c : c ) < 30 ) + break; + } + + return val < 0 ? -g : g; + } + + + /* Calculate the perpendicular by using '1 - base^2'. */ + /* Then use arctan to compute the angle. */ + static FT_16D16 + arc_cos( FT_16D16 val ) + { + FT_16D16 p; + FT_16D16 b = val; + FT_16D16 one = FT_INT_16D16( 1 ); + + + if ( b > one ) + b = one; + if ( b < -one ) + b = -one; + + p = one - FT_MulFix( b, b ); + p = square_root( p ); + + return FT_Atan2( b, p ); + } + + + /* Compute roots of a quadratic polynomial, assign them to `out`, */ + /* and return number of real roots. */ + /* */ + /* The procedure can be found at */ + /* */ + /* https://mathworld.wolfram.com/QuadraticFormula.html */ + static FT_UShort + solve_quadratic_equation( FT_26D6 a, + FT_26D6 b, + FT_26D6 c, + FT_16D16 out[2] ) + { + FT_16D16 discriminant = 0; + + + a = FT_26D6_16D16( a ); + b = FT_26D6_16D16( b ); + c = FT_26D6_16D16( c ); + + if ( a == 0 ) + { + if ( b == 0 ) + return 0; + else + { + out[0] = FT_DivFix( -c, b ); + + return 1; + } + } + + discriminant = FT_MulFix( b, b ) - 4 * FT_MulFix( a, c ); + + if ( discriminant < 0 ) + return 0; + else if ( discriminant == 0 ) + { + out[0] = FT_DivFix( -b, 2 * a ); + + return 1; + } + else + { + discriminant = square_root( discriminant ); + + out[0] = FT_DivFix( -b + discriminant, 2 * a ); + out[1] = FT_DivFix( -b - discriminant, 2 * a ); + + return 2; + } + } + + + /* Compute roots of a cubic polynomial, assign them to `out`, */ + /* and return number of real roots. */ + /* */ + /* The procedure can be found at */ + /* */ + /* https://mathworld.wolfram.com/CubicFormula.html */ + static FT_UShort + solve_cubic_equation( FT_26D6 a, + FT_26D6 b, + FT_26D6 c, + FT_26D6 d, + FT_16D16 out[3] ) + { + FT_16D16 q = 0; /* intermediate */ + FT_16D16 r = 0; /* intermediate */ + + FT_16D16 a2 = b; /* x^2 coefficients */ + FT_16D16 a1 = c; /* x coefficients */ + FT_16D16 a0 = d; /* constant */ + + FT_16D16 q3 = 0; + FT_16D16 r2 = 0; + FT_16D16 a23 = 0; + FT_16D16 a22 = 0; + FT_16D16 a1x2 = 0; + + + /* cutoff value for `a` to be a cubic, otherwise solve quadratic */ + if ( a == 0 || FT_ABS( a ) < 16 ) + return solve_quadratic_equation( b, c, d, out ); + + if ( d == 0 ) + { + out[0] = 0; + + return solve_quadratic_equation( a, b, c, out + 1 ) + 1; + } + + /* normalize the coefficients; this also makes them 16.16 */ + a2 = FT_DivFix( a2, a ); + a1 = FT_DivFix( a1, a ); + a0 = FT_DivFix( a0, a ); + + /* compute intermediates */ + a1x2 = FT_MulFix( a1, a2 ); + a22 = FT_MulFix( a2, a2 ); + a23 = FT_MulFix( a22, a2 ); + + q = ( 3 * a1 - a22 ) / 9; + r = ( 9 * a1x2 - 27 * a0 - 2 * a23 ) / 54; + + /* [BUG]: `q3` and `r2` still cause underflow. */ + + q3 = FT_MulFix( q, q ); + q3 = FT_MulFix( q3, q ); + + r2 = FT_MulFix( r, r ); + + if ( q3 < 0 && r2 < -q3 ) + { + FT_16D16 t = 0; + + + q3 = square_root( -q3 ); + t = FT_DivFix( r, q3 ); + + if ( t > ( 1 << 16 ) ) + t = ( 1 << 16 ); + if ( t < -( 1 << 16 ) ) + t = -( 1 << 16 ); + + t = arc_cos( t ); + a2 /= 3; + q = 2 * square_root( -q ); + + out[0] = FT_MulFix( q, FT_Cos( t / 3 ) ) - a2; + out[1] = FT_MulFix( q, FT_Cos( ( t + FT_ANGLE_PI * 2 ) / 3 ) ) - a2; + out[2] = FT_MulFix( q, FT_Cos( ( t + FT_ANGLE_PI * 4 ) / 3 ) ) - a2; + + return 3; + } + + else if ( r2 == -q3 ) + { + FT_16D16 s = 0; + + + s = cube_root( r ); + a2 /= -3; + + out[0] = a2 + ( 2 * s ); + out[1] = a2 - s; + + return 2; + } + + else + { + FT_16D16 s = 0; + FT_16D16 t = 0; + FT_16D16 dis = 0; + + + if ( q3 == 0 ) + dis = FT_ABS( r ); + else + dis = square_root( q3 + r2 ); + + s = cube_root( r + dis ); + t = cube_root( r - dis ); + a2 /= -3; + out[0] = ( a2 + ( s + t ) ); + + return 1; + } + } + +#endif /* !USE_NEWTON_FOR_CONIC */ + + + /*************************************************************************/ + /*************************************************************************/ + /** **/ + /** RASTERIZER **/ + /** **/ + /*************************************************************************/ + /*************************************************************************/ + + /************************************************************************** + * + * @Function: + * resolve_corner + * + * @Description: + * At some places on the grid two edges can give opposite directions; + * this happens when the closest point is on one of the endpoint. In + * that case we need to check the proper sign. + * + * This can be visualized by an example: + * + * ``` + * x + * + * o + * ^ \ + * / \ + * / \ + * (a) / \ (b) + * / \ + * / \ + * / v + * ``` + * + * Suppose `x` is the point whose shortest distance from an arbitrary + * contour we want to find out. It is clear that `o` is the nearest + * point on the contour. Now to determine the sign we do a cross + * product of the shortest distance vector and the edge direction, i.e., + * + * ``` + * => sign = cross(x - o, direction(a)) + * ``` + * + * Using the right hand thumb rule we can see that the sign will be + * positive. + * + * If we use `b', however, we have + * + * ``` + * => sign = cross(x - o, direction(b)) + * ``` + * + * In this case the sign will be negative. To determine the correct + * sign we thus divide the plane in two halves and check which plane the + * point lies in. + * + * ``` + * | + * x | + * | + * o + * ^|\ + * / | \ + * / | \ + * (a) / | \ (b) + * / | \ + * / \ + * / v + * ``` + * + * We can see that `x` lies in the plane of `a`, so we take the sign + * determined by `a`. This test can be easily done by calculating the + * orthogonality and taking the greater one. + * + * The orthogonality is simply the sinus of the two vectors (i.e., + * x - o) and the corresponding direction. We efficiently pre-compute + * the orthogonality with the corresponding `get_min_distance_*` + * functions. + * + * @Input: + * sdf1 :: + * First signed distance (can be any of `a` or `b`). + * + * sdf1 :: + * Second signed distance (can be any of `a` or `b`). + * + * @Return: + * The correct signed distance, which is computed by using the above + * algorithm. + * + * @Note: + * The function does not care about the actual distance, it simply + * returns the signed distance which has a larger cross product. As a + * consequence, this function should not be used if the two distances + * are fairly apart. In that case simply use the signed distance with + * a shorter absolute distance. + * + */ + static SDF_Signed_Distance + resolve_corner( SDF_Signed_Distance sdf1, + SDF_Signed_Distance sdf2 ) + { + return FT_ABS( sdf1.cross ) > FT_ABS( sdf2.cross ) ? sdf1 : sdf2; + } + + + /************************************************************************** + * + * @Function: + * get_min_distance_line + * + * @Description: + * Find the shortest distance from the `line` segment to a given `point` + * and assign it to `out`. Use it for line segments only. + * + * @Input: + * line :: + * The line segment to which the shortest distance is to be computed. + * + * point :: + * Point from which the shortest distance is to be computed. + * + * @Output: + * out :: + * Signed distance from `point` to `line`. + * + * @Return: + * FreeType error, 0 means success. + * + * @Note: + * The `line' parameter must have an edge type of `SDF_EDGE_LINE`. + * + */ + static FT_Error + get_min_distance_line( SDF_Edge* line, + FT_26D6_Vec point, + SDF_Signed_Distance* out ) + { + /* + * In order to calculate the shortest distance from a point to + * a line segment, we do the following. Let's assume that + * + * ``` + * a = start point of the line segment + * b = end point of the line segment + * p = point from which shortest distance is to be calculated + * ``` + * + * (1) Write the parametric equation of the line. + * + * ``` + * point_on_line = a + (b - a) * t (t is the factor) + * ``` + * + * (2) Find the projection of point `p` on the line. The projection + * will be perpendicular to the line, which allows us to get the + * solution by making the dot product zero. + * + * ``` + * (point_on_line - a) . (p - point_on_line) = 0 + * + * (point_on_line) + * (a) x-------o----------------x (b) + * |_| + * | + * | + * (p) + * ``` + * + * (3) Simplification of the above equation yields the factor of + * `point_on_line`: + * + * ``` + * t = ((p - a) . (b - a)) / |b - a|^2 + * ``` + * + * (4) We clamp factor `t` between [0.0f, 1.0f] because `point_on_line` + * can be outside of the line segment: + * + * ``` + * (point_on_line) + * (a) x------------------------x (b) -----o--- + * |_| + * | + * | + * (p) + * ``` + * + * (5) Finally, the distance we are interested in is + * + * ``` + * |point_on_line - p| + * ``` + */ + + FT_Error error = FT_Err_Ok; + + FT_Vector a; /* start position */ + FT_Vector b; /* end position */ + FT_Vector p; /* current point */ + + FT_26D6_Vec line_segment; /* `b` - `a` */ + FT_26D6_Vec p_sub_a; /* `p` - `a` */ + + FT_26D6 sq_line_length; /* squared length of `line_segment` */ + FT_16D16 factor; /* factor of the nearest point */ + FT_26D6 cross; /* used to determine sign */ + + FT_16D16_Vec nearest_point; /* `point_on_line` */ + FT_16D16_Vec nearest_vector; /* `p` - `nearest_point` */ + + + if ( !line || !out ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + if ( line->edge_type != SDF_EDGE_LINE ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + a = line->start_pos; + b = line->end_pos; + p = point; + + line_segment.x = b.x - a.x; + line_segment.y = b.y - a.y; + + p_sub_a.x = p.x - a.x; + p_sub_a.y = p.y - a.y; + + sq_line_length = ( line_segment.x * line_segment.x ) / 64 + + ( line_segment.y * line_segment.y ) / 64; + + /* currently factor is 26.6 */ + factor = ( p_sub_a.x * line_segment.x ) / 64 + + ( p_sub_a.y * line_segment.y ) / 64; + + /* now factor is 16.16 */ + factor = FT_DivFix( factor, sq_line_length ); + + /* clamp the factor between 0.0 and 1.0 in fixed-point */ + if ( factor > FT_INT_16D16( 1 ) ) + factor = FT_INT_16D16( 1 ); + if ( factor < 0 ) + factor = 0; + + nearest_point.x = FT_MulFix( FT_26D6_16D16( line_segment.x ), + factor ); + nearest_point.y = FT_MulFix( FT_26D6_16D16( line_segment.y ), + factor ); + + nearest_point.x = FT_26D6_16D16( a.x ) + nearest_point.x; + nearest_point.y = FT_26D6_16D16( a.y ) + nearest_point.y; + + nearest_vector.x = nearest_point.x - FT_26D6_16D16( p.x ); + nearest_vector.y = nearest_point.y - FT_26D6_16D16( p.y ); + + cross = FT_MulFix( nearest_vector.x, line_segment.y ) - + FT_MulFix( nearest_vector.y, line_segment.x ); + + /* assign the output */ + out->sign = cross < 0 ? 1 : -1; + out->distance = VECTOR_LENGTH_16D16( nearest_vector ); + + /* Instead of finding `cross` for checking corner we */ + /* directly set it here. This is more efficient */ + /* because if the distance is perpendicular we can */ + /* directly set it to 1. */ + if ( factor != 0 && factor != FT_INT_16D16( 1 ) ) + out->cross = FT_INT_16D16( 1 ); + else + { + /* [OPTIMIZATION]: Pre-compute this direction. */ + /* If not perpendicular then compute `cross`. */ + FT_Vector_NormLen( &line_segment ); + FT_Vector_NormLen( &nearest_vector ); + + out->cross = FT_MulFix( line_segment.x, nearest_vector.y ) - + FT_MulFix( line_segment.y, nearest_vector.x ); + } + + Exit: + return error; + } + + + /************************************************************************** + * + * @Function: + * get_min_distance_conic + * + * @Description: + * Find the shortest distance from the `conic` Bezier curve to a given + * `point` and assign it to `out`. Use it for conic/quadratic curves + * only. + * + * @Input: + * conic :: + * The conic Bezier curve to which the shortest distance is to be + * computed. + * + * point :: + * Point from which the shortest distance is to be computed. + * + * @Output: + * out :: + * Signed distance from `point` to `conic`. + * + * @Return: + * FreeType error, 0 means success. + * + * @Note: + * The `conic` parameter must have an edge type of `SDF_EDGE_CONIC`. + * + */ + +#if !USE_NEWTON_FOR_CONIC + + /* + * The function uses an analytical method to find the shortest distance + * which is faster than the Newton-Raphson method, but has underflows at + * the moment. Use Newton's method if you can see artifacts in the SDF. + */ + static FT_Error + get_min_distance_conic( SDF_Edge* conic, + FT_26D6_Vec point, + SDF_Signed_Distance* out ) + { + /* + * The procedure to find the shortest distance from a point to a + * quadratic Bezier curve is similar to the line segment algorithm. The + * shortest distance is perpendicular to the Bezier curve; the only + * difference from line is that there can be more than one + * perpendicular, and we also have to check the endpoints, because the + * perpendicular may not be the shortest. + * + * Let's assume that + * ``` + * p0 = first endpoint + * p1 = control point + * p2 = second endpoint + * p = point from which shortest distance is to be calculated + * ``` + * + * (1) The equation of a quadratic Bezier curve can be written as + * + * ``` + * B(t) = (1 - t)^2 * p0 + 2(1 - t)t * p1 + t^2 * p2 + * ``` + * + * with `t` a factor in the range [0.0f, 1.0f]. This equation can + * be rewritten as + * + * ``` + * B(t) = t^2 * (p0 - 2p1 + p2) + 2t * (p1 - p0) + p0 + * ``` + * + * With + * + * ``` + * A = p0 - 2p1 + p2 + * B = p1 - p0 + * ``` + * + * we have + * + * ``` + * B(t) = t^2 * A + 2t * B + p0 + * ``` + * + * (2) The derivative of the last equation above is + * + * ``` + * B'(t) = 2 *(tA + B) + * ``` + * + * (3) To find the shortest distance from `p` to `B(t)` we find the + * point on the curve at which the shortest distance vector (i.e., + * `B(t) - p`) and the direction (i.e., `B'(t)`) make 90 degrees. + * In other words, we make the dot product zero. + * + * ``` + * (B(t) - p) . (B'(t)) = 0 + * (t^2 * A + 2t * B + p0 - p) . (2 * (tA + B)) = 0 + * ``` + * + * After simplifying we get a cubic equation + * + * ``` + * at^3 + bt^2 + ct + d = 0 + * ``` + * + * with + * + * ``` + * a = A.A + * b = 3A.B + * c = 2B.B + A.p0 - A.p + * d = p0.B - p.B + * ``` + * + * (4) Now the roots of the equation can be computed using 'Cardano's + * Cubic formula'; we clamp the roots in the range [0.0f, 1.0f]. + * + * [note]: `B` and `B(t)` are different in the above equations. + */ + + FT_Error error = FT_Err_Ok; + + FT_26D6_Vec aA, bB; /* A, B in the above comment */ + FT_26D6_Vec nearest_point = { 0, 0 }; + /* point on curve nearest to `point` */ + FT_26D6_Vec direction; /* direction of curve at `nearest_point` */ + + FT_26D6_Vec p0, p1, p2; /* control points of a conic curve */ + FT_26D6_Vec p; /* `point` to which shortest distance */ + + FT_26D6 a, b, c, d; /* cubic coefficients */ + + FT_16D16 roots[3] = { 0, 0, 0 }; /* real roots of the cubic eq. */ + FT_16D16 min_factor; /* factor at `nearest_point` */ + FT_16D16 cross; /* to determine the sign */ + FT_16D16 min = FT_INT_MAX; /* shortest squared distance */ + + FT_UShort num_roots; /* number of real roots of cubic */ + FT_UShort i; + + + if ( !conic || !out ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + if ( conic->edge_type != SDF_EDGE_CONIC ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + p0 = conic->start_pos; + p1 = conic->control_a; + p2 = conic->end_pos; + p = point; + + /* compute substitution coefficients */ + aA.x = p0.x - 2 * p1.x + p2.x; + aA.y = p0.y - 2 * p1.y + p2.y; + + bB.x = p1.x - p0.x; + bB.y = p1.y - p0.y; + + /* compute cubic coefficients */ + a = VEC_26D6_DOT( aA, aA ); + + b = 3 * VEC_26D6_DOT( aA, bB ); + + c = 2 * VEC_26D6_DOT( bB, bB ) + + VEC_26D6_DOT( aA, p0 ) - + VEC_26D6_DOT( aA, p ); + + d = VEC_26D6_DOT( p0, bB ) - + VEC_26D6_DOT( p, bB ); + + /* find the roots */ + num_roots = solve_cubic_equation( a, b, c, d, roots ); + + if ( num_roots == 0 ) + { + roots[0] = 0; + roots[1] = FT_INT_16D16( 1 ); + num_roots = 2; + } + + /* [OPTIMIZATION]: Check the roots, clamp them and discard */ + /* duplicate roots. */ + + /* convert these values to 16.16 for further computation */ + aA.x = FT_26D6_16D16( aA.x ); + aA.y = FT_26D6_16D16( aA.y ); + + bB.x = FT_26D6_16D16( bB.x ); + bB.y = FT_26D6_16D16( bB.y ); + + p0.x = FT_26D6_16D16( p0.x ); + p0.y = FT_26D6_16D16( p0.y ); + + p.x = FT_26D6_16D16( p.x ); + p.y = FT_26D6_16D16( p.y ); + + for ( i = 0; i < num_roots; i++ ) + { + FT_16D16 t = roots[i]; + FT_16D16 t2 = 0; + FT_16D16 dist = 0; + + FT_16D16_Vec curve_point; + FT_16D16_Vec dist_vector; + + /* + * Ideally we should discard the roots which are outside the range + * [0.0, 1.0] and check the endpoints of the Bezier curve, but Behdad + * Esfahbod proved the following lemma. + * + * Lemma: + * + * (1) If the closest point on the curve [0, 1] is to the endpoint at + * `t` = 1 and the cubic has no real roots at `t` = 1 then the + * cubic must have a real root at some `t` > 1. + * + * (2) Similarly, if the closest point on the curve [0, 1] is to the + * endpoint at `t` = 0 and the cubic has no real roots at `t` = 0 + * then the cubic must have a real root at some `t` < 0. + * + * Now because of this lemma we only need to clamp the roots and that + * will take care of the endpoints. + * + * For more details see + * + * https://lists.nongnu.org/archive/html/freetype-devel/2020-06/msg00147.html + */ + + if ( t < 0 ) + t = 0; + if ( t > FT_INT_16D16( 1 ) ) + t = FT_INT_16D16( 1 ); + + t2 = FT_MulFix( t, t ); + + /* B(t) = t^2 * A + 2t * B + p0 - p */ + curve_point.x = FT_MulFix( aA.x, t2 ) + + 2 * FT_MulFix( bB.x, t ) + p0.x; + curve_point.y = FT_MulFix( aA.y, t2 ) + + 2 * FT_MulFix( bB.y, t ) + p0.y; + + /* `curve_point` - `p` */ + dist_vector.x = curve_point.x - p.x; + dist_vector.y = curve_point.y - p.y; + + dist = VECTOR_LENGTH_16D16( dist_vector ); + + if ( dist < min ) + { + min = dist; + nearest_point = curve_point; + min_factor = t; + } + } + + /* B'(t) = 2 * (tA + B) */ + direction.x = 2 * FT_MulFix( aA.x, min_factor ) + 2 * bB.x; + direction.y = 2 * FT_MulFix( aA.y, min_factor ) + 2 * bB.y; + + /* determine the sign */ + cross = FT_MulFix( nearest_point.x - p.x, direction.y ) - + FT_MulFix( nearest_point.y - p.y, direction.x ); + + /* assign the values */ + out->distance = min; + out->sign = cross < 0 ? 1 : -1; + + if ( min_factor != 0 && min_factor != FT_INT_16D16( 1 ) ) + out->cross = FT_INT_16D16( 1 ); /* the two are perpendicular */ + else + { + /* convert to nearest vector */ + nearest_point.x -= FT_26D6_16D16( p.x ); + nearest_point.y -= FT_26D6_16D16( p.y ); + + /* compute `cross` if not perpendicular */ + FT_Vector_NormLen( &direction ); + FT_Vector_NormLen( &nearest_point ); + + out->cross = FT_MulFix( direction.x, nearest_point.y ) - + FT_MulFix( direction.y, nearest_point.x ); + } + + Exit: + return error; + } + +#else /* USE_NEWTON_FOR_CONIC */ + + /* + * The function uses Newton's approximation to find the shortest distance, + * which is a bit slower than the analytical method but doesn't cause + * underflow. + */ + static FT_Error + get_min_distance_conic( SDF_Edge* conic, + FT_26D6_Vec point, + SDF_Signed_Distance* out ) + { + /* + * This method uses Newton-Raphson's approximation to find the shortest + * distance from a point to a conic curve. It does not involve solving + * any cubic equation, that is why there is no risk of underflow. + * + * Let's assume that + * + * ``` + * p0 = first endpoint + * p1 = control point + * p3 = second endpoint + * p = point from which shortest distance is to be calculated + * ``` + * + * (1) The equation of a quadratic Bezier curve can be written as + * + * ``` + * B(t) = (1 - t)^2 * p0 + 2(1 - t)t * p1 + t^2 * p2 + * ``` + * + * with `t` the factor in the range [0.0f, 1.0f]. The above + * equation can be rewritten as + * + * ``` + * B(t) = t^2 * (p0 - 2p1 + p2) + 2t * (p1 - p0) + p0 + * ``` + * + * With + * + * ``` + * A = p0 - 2p1 + p2 + * B = 2 * (p1 - p0) + * ``` + * + * we have + * + * ``` + * B(t) = t^2 * A + t * B + p0 + * ``` + * + * (2) The derivative of the above equation is + * + * ``` + * B'(t) = 2t * A + B + * ``` + * + * (3) The second derivative of the above equation is + * + * ``` + * B''(t) = 2A + * ``` + * + * (4) The equation `P(t)` of the distance from point `p` to the curve + * can be written as + * + * ``` + * P(t) = t^2 * A + t^2 * B + p0 - p + * ``` + * + * With + * + * ``` + * C = p0 - p + * ``` + * + * we have + * + * ``` + * P(t) = t^2 * A + t * B + C + * ``` + * + * (5) Finally, the equation of the angle between `B(t)` and `P(t)` can + * be written as + * + * ``` + * Q(t) = P(t) . B'(t) + * ``` + * + * (6) Our task is to find a value of `t` such that the above equation + * `Q(t)` becomes zero, that is, the point-to-curve vector makes + * 90~degrees with the curve. We solve this with the Newton-Raphson + * method. + * + * (7) We first assume an arbitrary value of factor `t`, which we then + * improve. + * + * ``` + * t := Q(t) / Q'(t) + * ``` + * + * Putting the value of `Q(t)` from the above equation gives + * + * ``` + * t := P(t) . B'(t) / derivative(P(t) . B'(t)) + * t := P(t) . B'(t) / + * (P'(t) . B'(t) + P(t) . B''(t)) + * ``` + * + * Note that `P'(t)` is the same as `B'(t)` because the constant is + * gone due to the derivative. + * + * (8) Finally we get the equation to improve the factor as + * + * ``` + * t := P(t) . B'(t) / + * (B'(t) . B'(t) + P(t) . B''(t)) + * ``` + * + * [note]: `B` and `B(t)` are different in the above equations. + */ + + FT_Error error = FT_Err_Ok; + + FT_26D6_Vec aA, bB, cC; /* A, B, C in the above comment */ + FT_26D6_Vec nearest_point = { 0, 0 }; + /* point on curve nearest to `point` */ + FT_26D6_Vec direction; /* direction of curve at `nearest_point` */ + + FT_26D6_Vec p0, p1, p2; /* control points of a conic curve */ + FT_26D6_Vec p; /* `point` to which shortest distance */ + + FT_16D16 min_factor = 0; /* factor at `nearest_point' */ + FT_16D16 cross; /* to determine the sign */ + FT_16D16 min = FT_INT_MAX; /* shortest squared distance */ + + FT_UShort iterations; + FT_UShort steps; + + + if ( !conic || !out ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + if ( conic->edge_type != SDF_EDGE_CONIC ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + p0 = conic->start_pos; + p1 = conic->control_a; + p2 = conic->end_pos; + p = point; + + /* compute substitution coefficients */ + aA.x = p0.x - 2 * p1.x + p2.x; + aA.y = p0.y - 2 * p1.y + p2.y; + + bB.x = 2 * ( p1.x - p0.x ); + bB.y = 2 * ( p1.y - p0.y ); + + cC.x = p0.x; + cC.y = p0.y; + + /* do Newton's iterations */ + for ( iterations = 0; iterations <= MAX_NEWTON_DIVISIONS; iterations++ ) + { + FT_16D16 factor = FT_INT_16D16( iterations ) / MAX_NEWTON_DIVISIONS; + FT_16D16 factor2; + FT_16D16 length; + + FT_16D16_Vec curve_point; /* point on the curve */ + FT_16D16_Vec dist_vector; /* `curve_point` - `p` */ + + FT_26D6_Vec d1; /* first derivative */ + FT_26D6_Vec d2; /* second derivative */ + + FT_16D16 temp1; + FT_16D16 temp2; + + + for ( steps = 0; steps < MAX_NEWTON_STEPS; steps++ ) + { + factor2 = FT_MulFix( factor, factor ); + + /* B(t) = t^2 * A + t * B + p0 */ + curve_point.x = FT_MulFix( aA.x, factor2 ) + + FT_MulFix( bB.x, factor ) + cC.x; + curve_point.y = FT_MulFix( aA.y, factor2 ) + + FT_MulFix( bB.y, factor ) + cC.y; + + /* convert to 16.16 */ + curve_point.x = FT_26D6_16D16( curve_point.x ); + curve_point.y = FT_26D6_16D16( curve_point.y ); + + /* P(t) in the comment */ + dist_vector.x = curve_point.x - FT_26D6_16D16( p.x ); + dist_vector.y = curve_point.y - FT_26D6_16D16( p.y ); + + length = VECTOR_LENGTH_16D16( dist_vector ); + + if ( length < min ) + { + min = length; + min_factor = factor; + nearest_point = curve_point; + } + + /* This is Newton's approximation. */ + /* */ + /* t := P(t) . B'(t) / */ + /* (B'(t) . B'(t) + P(t) . B''(t)) */ + + /* B'(t) = 2tA + B */ + d1.x = FT_MulFix( aA.x, 2 * factor ) + bB.x; + d1.y = FT_MulFix( aA.y, 2 * factor ) + bB.y; + + /* B''(t) = 2A */ + d2.x = 2 * aA.x; + d2.y = 2 * aA.y; + + dist_vector.x /= 1024; + dist_vector.y /= 1024; + + /* temp1 = P(t) . B'(t) */ + temp1 = VEC_26D6_DOT( dist_vector, d1 ); + + /* temp2 = B'(t) . B'(t) + P(t) . B''(t) */ + temp2 = VEC_26D6_DOT( d1, d1 ) + + VEC_26D6_DOT( dist_vector, d2 ); + + factor -= FT_DivFix( temp1, temp2 ); + + if ( factor < 0 || factor > FT_INT_16D16( 1 ) ) + break; + } + } + + /* B'(t) = 2t * A + B */ + direction.x = 2 * FT_MulFix( aA.x, min_factor ) + bB.x; + direction.y = 2 * FT_MulFix( aA.y, min_factor ) + bB.y; + + /* determine the sign */ + cross = FT_MulFix( nearest_point.x - FT_26D6_16D16( p.x ), + direction.y ) - + FT_MulFix( nearest_point.y - FT_26D6_16D16( p.y ), + direction.x ); + + /* assign the values */ + out->distance = min; + out->sign = cross < 0 ? 1 : -1; + + if ( min_factor != 0 && min_factor != FT_INT_16D16( 1 ) ) + out->cross = FT_INT_16D16( 1 ); /* the two are perpendicular */ + else + { + /* convert to nearest vector */ + nearest_point.x -= FT_26D6_16D16( p.x ); + nearest_point.y -= FT_26D6_16D16( p.y ); + + /* compute `cross` if not perpendicular */ + FT_Vector_NormLen( &direction ); + FT_Vector_NormLen( &nearest_point ); + + out->cross = FT_MulFix( direction.x, nearest_point.y ) - + FT_MulFix( direction.y, nearest_point.x ); + } + + Exit: + return error; + } + + +#endif /* USE_NEWTON_FOR_CONIC */ + + + /************************************************************************** + * + * @Function: + * get_min_distance_cubic + * + * @Description: + * Find the shortest distance from the `cubic` Bezier curve to a given + * `point` and assigns it to `out`. Use it for cubic curves only. + * + * @Input: + * cubic :: + * The cubic Bezier curve to which the shortest distance is to be + * computed. + * + * point :: + * Point from which the shortest distance is to be computed. + * + * @Output: + * out :: + * Signed distance from `point` to `cubic`. + * + * @Return: + * FreeType error, 0 means success. + * + * @Note: + * The function uses Newton's approximation to find the shortest + * distance. Another way would be to divide the cubic into conic or + * subdivide the curve into lines, but that is not implemented. + * + * The `cubic` parameter must have an edge type of `SDF_EDGE_CUBIC`. + * + */ + static FT_Error + get_min_distance_cubic( SDF_Edge* cubic, + FT_26D6_Vec point, + SDF_Signed_Distance* out ) + { + /* + * The procedure to find the shortest distance from a point to a cubic + * Bezier curve is similar to quadratic curve algorithm. The only + * difference is that while calculating factor `t`, instead of a cubic + * polynomial equation we have to find the roots of a 5th degree + * polynomial equation. Solving this would require a significant amount + * of time, and still the results may not be accurate. We are thus + * going to directly approximate the value of `t` using the Newton-Raphson + * method. + * + * Let's assume that + * + * ``` + * p0 = first endpoint + * p1 = first control point + * p2 = second control point + * p3 = second endpoint + * p = point from which shortest distance is to be calculated + * ``` + * + * (1) The equation of a cubic Bezier curve can be written as + * + * ``` + * B(t) = (1 - t)^3 * p0 + 3(1 - t)^2 t * p1 + + * 3(1 - t)t^2 * p2 + t^3 * p3 + * ``` + * + * The equation can be expanded and written as + * + * ``` + * B(t) = t^3 * (-p0 + 3p1 - 3p2 + p3) + + * 3t^2 * (p0 - 2p1 + p2) + 3t * (-p0 + p1) + p0 + * ``` + * + * With + * + * ``` + * A = -p0 + 3p1 - 3p2 + p3 + * B = 3(p0 - 2p1 + p2) + * C = 3(-p0 + p1) + * ``` + * + * we have + * + * ``` + * B(t) = t^3 * A + t^2 * B + t * C + p0 + * ``` + * + * (2) The derivative of the above equation is + * + * ``` + * B'(t) = 3t^2 * A + 2t * B + C + * ``` + * + * (3) The second derivative of the above equation is + * + * ``` + * B''(t) = 6t * A + 2B + * ``` + * + * (4) The equation `P(t)` of the distance from point `p` to the curve + * can be written as + * + * ``` + * P(t) = t^3 * A + t^2 * B + t * C + p0 - p + * ``` + * + * With + * + * ``` + * D = p0 - p + * ``` + * + * we have + * + * ``` + * P(t) = t^3 * A + t^2 * B + t * C + D + * ``` + * + * (5) Finally the equation of the angle between `B(t)` and `P(t)` can + * be written as + * + * ``` + * Q(t) = P(t) . B'(t) + * ``` + * + * (6) Our task is to find a value of `t` such that the above equation + * `Q(t)` becomes zero, that is, the point-to-curve vector makes + * 90~degree with curve. We solve this with the Newton-Raphson + * method. + * + * (7) We first assume an arbitrary value of factor `t`, which we then + * improve. + * + * ``` + * t := Q(t) / Q'(t) + * ``` + * + * Putting the value of `Q(t)` from the above equation gives + * + * ``` + * t := P(t) . B'(t) / derivative(P(t) . B'(t)) + * t := P(t) . B'(t) / + * (P'(t) . B'(t) + P(t) . B''(t)) + * ``` + * + * Note that `P'(t)` is the same as `B'(t)` because the constant is + * gone due to the derivative. + * + * (8) Finally we get the equation to improve the factor as + * + * ``` + * t := P(t) . B'(t) / + * (B'(t) . B'( t ) + P(t) . B''(t)) + * ``` + * + * [note]: `B` and `B(t)` are different in the above equations. + */ + + FT_Error error = FT_Err_Ok; + + FT_26D6_Vec aA, bB, cC, dD; /* A, B, C, D in the above comment */ + FT_16D16_Vec nearest_point = { 0, 0 }; + /* point on curve nearest to `point` */ + FT_16D16_Vec direction; /* direction of curve at `nearest_point` */ + + FT_26D6_Vec p0, p1, p2, p3; /* control points of a cubic curve */ + FT_26D6_Vec p; /* `point` to which shortest distance */ + + FT_16D16 min_factor = 0; /* factor at shortest distance */ + FT_16D16 min_factor_sq = 0; /* factor at shortest distance */ + FT_16D16 cross; /* to determine the sign */ + FT_16D16 min = FT_INT_MAX; /* shortest distance */ + + FT_UShort iterations; + FT_UShort steps; + + + if ( !cubic || !out ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + if ( cubic->edge_type != SDF_EDGE_CUBIC ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + p0 = cubic->start_pos; + p1 = cubic->control_a; + p2 = cubic->control_b; + p3 = cubic->end_pos; + p = point; + + /* compute substitution coefficients */ + aA.x = -p0.x + 3 * ( p1.x - p2.x ) + p3.x; + aA.y = -p0.y + 3 * ( p1.y - p2.y ) + p3.y; + + bB.x = 3 * ( p0.x - 2 * p1.x + p2.x ); + bB.y = 3 * ( p0.y - 2 * p1.y + p2.y ); + + cC.x = 3 * ( p1.x - p0.x ); + cC.y = 3 * ( p1.y - p0.y ); + + dD.x = p0.x; + dD.y = p0.y; + + for ( iterations = 0; iterations <= MAX_NEWTON_DIVISIONS; iterations++ ) + { + FT_16D16 factor = FT_INT_16D16( iterations ) / MAX_NEWTON_DIVISIONS; + + FT_16D16 factor2; /* factor^2 */ + FT_16D16 factor3; /* factor^3 */ + FT_16D16 length; + + FT_16D16_Vec curve_point; /* point on the curve */ + FT_16D16_Vec dist_vector; /* `curve_point' - `p' */ + + FT_26D6_Vec d1; /* first derivative */ + FT_26D6_Vec d2; /* second derivative */ + + FT_16D16 temp1; + FT_16D16 temp2; + + + for ( steps = 0; steps < MAX_NEWTON_STEPS; steps++ ) + { + factor2 = FT_MulFix( factor, factor ); + factor3 = FT_MulFix( factor2, factor ); + + /* B(t) = t^3 * A + t^2 * B + t * C + D */ + curve_point.x = FT_MulFix( aA.x, factor3 ) + + FT_MulFix( bB.x, factor2 ) + + FT_MulFix( cC.x, factor ) + dD.x; + curve_point.y = FT_MulFix( aA.y, factor3 ) + + FT_MulFix( bB.y, factor2 ) + + FT_MulFix( cC.y, factor ) + dD.y; + + /* convert to 16.16 */ + curve_point.x = FT_26D6_16D16( curve_point.x ); + curve_point.y = FT_26D6_16D16( curve_point.y ); + + /* P(t) in the comment */ + dist_vector.x = curve_point.x - FT_26D6_16D16( p.x ); + dist_vector.y = curve_point.y - FT_26D6_16D16( p.y ); + + length = VECTOR_LENGTH_16D16( dist_vector ); + + if ( length < min ) + { + min = length; + min_factor = factor; + min_factor_sq = factor2; + nearest_point = curve_point; + } + + /* This the Newton's approximation. */ + /* */ + /* t := P(t) . B'(t) / */ + /* (B'(t) . B'(t) + P(t) . B''(t)) */ + + /* B'(t) = 3t^2 * A + 2t * B + C */ + d1.x = FT_MulFix( aA.x, 3 * factor2 ) + + FT_MulFix( bB.x, 2 * factor ) + cC.x; + d1.y = FT_MulFix( aA.y, 3 * factor2 ) + + FT_MulFix( bB.y, 2 * factor ) + cC.y; + + /* B''(t) = 6t * A + 2B */ + d2.x = FT_MulFix( aA.x, 6 * factor ) + 2 * bB.x; + d2.y = FT_MulFix( aA.y, 6 * factor ) + 2 * bB.y; + + dist_vector.x /= 1024; + dist_vector.y /= 1024; + + /* temp1 = P(t) . B'(t) */ + temp1 = VEC_26D6_DOT( dist_vector, d1 ); + + /* temp2 = B'(t) . B'(t) + P(t) . B''(t) */ + temp2 = VEC_26D6_DOT( d1, d1 ) + + VEC_26D6_DOT( dist_vector, d2 ); + + factor -= FT_DivFix( temp1, temp2 ); + + if ( factor < 0 || factor > FT_INT_16D16( 1 ) ) + break; + } + } + + /* B'(t) = 3t^2 * A + 2t * B + C */ + direction.x = FT_MulFix( aA.x, 3 * min_factor_sq ) + + FT_MulFix( bB.x, 2 * min_factor ) + cC.x; + direction.y = FT_MulFix( aA.y, 3 * min_factor_sq ) + + FT_MulFix( bB.y, 2 * min_factor ) + cC.y; + + /* determine the sign */ + cross = FT_MulFix( nearest_point.x - FT_26D6_16D16( p.x ), + direction.y ) - + FT_MulFix( nearest_point.y - FT_26D6_16D16( p.y ), + direction.x ); + + /* assign the values */ + out->distance = min; + out->sign = cross < 0 ? 1 : -1; + + if ( min_factor != 0 && min_factor != FT_INT_16D16( 1 ) ) + out->cross = FT_INT_16D16( 1 ); /* the two are perpendicular */ + else + { + /* convert to nearest vector */ + nearest_point.x -= FT_26D6_16D16( p.x ); + nearest_point.y -= FT_26D6_16D16( p.y ); + + /* compute `cross` if not perpendicular */ + FT_Vector_NormLen( &direction ); + FT_Vector_NormLen( &nearest_point ); + + out->cross = FT_MulFix( direction.x, nearest_point.y ) - + FT_MulFix( direction.y, nearest_point.x ); + } + + Exit: + return error; + } + + + /************************************************************************** + * + * @Function: + * sdf_edge_get_min_distance + * + * @Description: + * Find shortest distance from `point` to any type of `edge`. It checks + * the edge type and then calls the relevant `get_min_distance_*` + * function. + * + * @Input: + * edge :: + * An edge to which the shortest distance is to be computed. + * + * point :: + * Point from which the shortest distance is to be computed. + * + * @Output: + * out :: + * Signed distance from `point` to `edge`. + * + * @Return: + * FreeType error, 0 means success. + * + */ + static FT_Error + sdf_edge_get_min_distance( SDF_Edge* edge, + FT_26D6_Vec point, + SDF_Signed_Distance* out ) + { + FT_Error error = FT_Err_Ok; + + + if ( !edge || !out ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + /* edge-specific distance calculation */ + switch ( edge->edge_type ) + { + case SDF_EDGE_LINE: + get_min_distance_line( edge, point, out ); + break; + + case SDF_EDGE_CONIC: + get_min_distance_conic( edge, point, out ); + break; + + case SDF_EDGE_CUBIC: + get_min_distance_cubic( edge, point, out ); + break; + + default: + error = FT_THROW( Invalid_Argument ); + } + + Exit: + return error; + } + + + /* `sdf_generate' is not used at the moment */ +#if 0 + + #error "DO NOT USE THIS!" + #error "The function still outputs 16-bit data, which might cause memory" + #error "corruption. If required I will add this later." + + /************************************************************************** + * + * @Function: + * sdf_contour_get_min_distance + * + * @Description: + * Iterate over all edges that make up the contour, find the shortest + * distance from a point to this contour, and assigns result to `out`. + * + * @Input: + * contour :: + * A contour to which the shortest distance is to be computed. + * + * point :: + * Point from which the shortest distance is to be computed. + * + * @Output: + * out :: + * Signed distance from the `point' to the `contour'. + * + * @Return: + * FreeType error, 0 means success. + * + * @Note: + * The function does not return a signed distance for each edge which + * makes up the contour, it simply returns the shortest of all the + * edges. + * + */ + static FT_Error + sdf_contour_get_min_distance( SDF_Contour* contour, + FT_26D6_Vec point, + SDF_Signed_Distance* out ) + { + FT_Error error = FT_Err_Ok; + SDF_Signed_Distance min_dist = max_sdf; + SDF_Edge* edge_list; + + + if ( !contour || !out ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + edge_list = contour->edges; + + /* iterate over all the edges manually */ + while ( edge_list ) + { + SDF_Signed_Distance current_dist = max_sdf; + FT_16D16 diff; + + + FT_CALL( sdf_edge_get_min_distance( edge_list, + point, + ¤t_dist ) ); + + if ( current_dist.distance >= 0 ) + { + diff = current_dist.distance - min_dist.distance; + + + if ( FT_ABS( diff ) < CORNER_CHECK_EPSILON ) + min_dist = resolve_corner( min_dist, current_dist ); + else if ( diff < 0 ) + min_dist = current_dist; + } + else + FT_TRACE0(( "sdf_contour_get_min_distance: Overflow.\n" )); + + edge_list = edge_list->next; + } + + *out = min_dist; + + Exit: + return error; + } + + + /************************************************************************** + * + * @Function: + * sdf_generate + * + * @Description: + * This is the main function that is responsible for generating signed + * distance fields. The function does not align or compute the size of + * `bitmap`; therefore the calling application must set up `bitmap` + * properly and transform the `shape' appropriately in advance. + * + * Currently we check all pixels against all contours and all edges. + * + * @Input: + * internal_params :: + * Internal parameters and properties required by the rasterizer. See + * @SDF_Params for more. + * + * shape :: + * A complete shape which is used to generate SDF. + * + * spread :: + * Maximum distances to be allowed in the output bitmap. + * + * @Output: + * bitmap :: + * The output bitmap which will contain the SDF information. + * + * @Return: + * FreeType error, 0 means success. + * + */ + static FT_Error + sdf_generate( const SDF_Params internal_params, + const SDF_Shape* shape, + FT_UInt spread, + const FT_Bitmap* bitmap ) + { + FT_Error error = FT_Err_Ok; + + FT_UInt width = 0; + FT_UInt rows = 0; + FT_UInt x = 0; /* used to loop in x direction, i.e., width */ + FT_UInt y = 0; /* used to loop in y direction, i.e., rows */ + FT_UInt sp_sq = 0; /* `spread` [* `spread`] as a 16.16 fixed value */ + + FT_Short* buffer; + + + if ( !shape || !bitmap ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + if ( spread < MIN_SPREAD || spread > MAX_SPREAD ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + width = bitmap->width; + rows = bitmap->rows; + buffer = (FT_Short*)bitmap->buffer; + + if ( USE_SQUARED_DISTANCES ) + sp_sq = FT_INT_16D16( spread * spread ); + else + sp_sq = FT_INT_16D16( spread ); + + if ( width == 0 || rows == 0 ) + { + FT_TRACE0(( "sdf_generate:" + " Cannot render glyph with width/height == 0\n" )); + FT_TRACE0(( " " + " (width, height provided [%d, %d])\n", + width, rows )); + + error = FT_THROW( Cannot_Render_Glyph ); + goto Exit; + } + + /* loop over all rows */ + for ( y = 0; y < rows; y++ ) + { + /* loop over all pixels of a row */ + for ( x = 0; x < width; x++ ) + { + /* `grid_point` is the current pixel position; */ + /* our task is to find the shortest distance */ + /* from this point to the entire shape. */ + FT_26D6_Vec grid_point = zero_vector; + SDF_Signed_Distance min_dist = max_sdf; + SDF_Contour* contour_list; + + FT_UInt index; + FT_Short value; + + + grid_point.x = FT_INT_26D6( x ); + grid_point.y = FT_INT_26D6( y ); + + /* This `grid_point' is at the corner, but we */ + /* use the center of the pixel. */ + grid_point.x += FT_INT_26D6( 1 ) / 2; + grid_point.y += FT_INT_26D6( 1 ) / 2; + + contour_list = shape->contours; + + /* iterate over all contours manually */ + while ( contour_list ) + { + SDF_Signed_Distance current_dist = max_sdf; + + + FT_CALL( sdf_contour_get_min_distance( contour_list, + grid_point, + ¤t_dist ) ); + + if ( current_dist.distance < min_dist.distance ) + min_dist = current_dist; + + contour_list = contour_list->next; + } + + /* [OPTIMIZATION]: if (min_dist > sp_sq) then simply clamp */ + /* the value to spread to avoid square_root */ + + /* clamp the values to spread */ + if ( min_dist.distance > sp_sq ) + min_dist.distance = sp_sq; + + /* square_root the values and fit in a 6.10 fixed-point */ + if ( USE_SQUARED_DISTANCES ) + min_dist.distance = square_root( min_dist.distance ); + + if ( internal_params.orientation == FT_ORIENTATION_FILL_LEFT ) + min_dist.sign = -min_dist.sign; + if ( internal_params.flip_sign ) + min_dist.sign = -min_dist.sign; + + min_dist.distance /= 64; /* convert from 16.16 to 22.10 */ + + value = min_dist.distance & 0x0000FFFF; /* truncate to 6.10 */ + value *= min_dist.sign; + + if ( internal_params.flip_y ) + index = y * width + x; + else + index = ( rows - y - 1 ) * width + x; + + buffer[index] = value; + } + } + + Exit: + return error; + } + +#endif /* 0 */ + + + /************************************************************************** + * + * @Function: + * sdf_generate_bounding_box + * + * @Description: + * This function does basically the same thing as `sdf_generate` above + * but more efficiently. + * + * Instead of checking all pixels against all edges, we loop over all + * edges and only check pixels around the control box of the edge; the + * control box is increased by the spread in all directions. Anything + * outside of the control box that exceeds `spread` doesn't need to be + * computed. + * + * Lastly, to determine the sign of unchecked pixels, we do a single + * pass of all rows starting with a '+' sign and flipping when we come + * across a '-' sign and continue. This also eliminates the possibility + * of overflow because we only check the proximity of the curve. + * Therefore we can use squared distanced safely. + * + * @Input: + * internal_params :: + * Internal parameters and properties required by the rasterizer. + * See @SDF_Params for more. + * + * shape :: + * A complete shape which is used to generate SDF. + * + * spread :: + * Maximum distances to be allowed in the output bitmap. + * + * @Output: + * bitmap :: + * The output bitmap which will contain the SDF information. + * + * @Return: + * FreeType error, 0 means success. + * + */ + static FT_Error + sdf_generate_bounding_box( const SDF_Params internal_params, + const SDF_Shape* shape, + FT_UInt spread, + const FT_Bitmap* bitmap ) + { + FT_Error error = FT_Err_Ok; + FT_Memory memory = NULL; + + FT_Int width, rows, i, j; + FT_Int sp_sq; /* max value to check */ + + SDF_Contour* contours; /* list of all contours */ + FT_SDFFormat* buffer; /* the bitmap buffer */ + + /* This buffer has the same size in indices as the */ + /* bitmap buffer. When we check a pixel position for */ + /* a shortest distance we keep it in this buffer. */ + /* This way we can find out which pixel is set, */ + /* and also determine the signs properly. */ + SDF_Signed_Distance* dists = NULL; + + const FT_16D16 fixed_spread = (FT_16D16)FT_INT_16D16( spread ); + + + if ( !shape || !bitmap ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + if ( spread < MIN_SPREAD || spread > MAX_SPREAD ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + memory = shape->memory; + if ( !memory ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + if ( FT_ALLOC( dists, + bitmap->width * bitmap->rows * sizeof ( *dists ) ) ) + goto Exit; + + contours = shape->contours; + width = (FT_Int)bitmap->width; + rows = (FT_Int)bitmap->rows; + buffer = (FT_SDFFormat*)bitmap->buffer; + + if ( USE_SQUARED_DISTANCES ) + sp_sq = FT_INT_16D16( (FT_Int)( spread * spread ) ); + else + sp_sq = fixed_spread; + + if ( width == 0 || rows == 0 ) + { + FT_TRACE0(( "sdf_generate:" + " Cannot render glyph with width/height == 0\n" )); + FT_TRACE0(( " " + " (width, height provided [%d, %d])", width, rows )); + + error = FT_THROW( Cannot_Render_Glyph ); + goto Exit; + } + + /* loop over all contours */ + while ( contours ) + { + SDF_Edge* edges = contours->edges; + + + /* loop over all edges */ + while ( edges ) + { + FT_CBox cbox; + FT_Int x, y; + + + /* get the control box and increase it by `spread' */ + cbox = get_control_box( *edges ); + + cbox.xMin = ( cbox.xMin - 63 ) / 64 - ( FT_Pos )spread; + cbox.xMax = ( cbox.xMax + 63 ) / 64 + ( FT_Pos )spread; + cbox.yMin = ( cbox.yMin - 63 ) / 64 - ( FT_Pos )spread; + cbox.yMax = ( cbox.yMax + 63 ) / 64 + ( FT_Pos )spread; + + /* now loop over the pixels in the control box. */ + for ( y = cbox.yMin; y < cbox.yMax; y++ ) + { + for ( x = cbox.xMin; x < cbox.xMax; x++ ) + { + FT_26D6_Vec grid_point = zero_vector; + SDF_Signed_Distance dist = max_sdf; + FT_UInt index = 0; + FT_16D16 diff = 0; + + + if ( x < 0 || x >= width ) + continue; + if ( y < 0 || y >= rows ) + continue; + + grid_point.x = FT_INT_26D6( x ); + grid_point.y = FT_INT_26D6( y ); + + /* This `grid_point` is at the corner, but we */ + /* use the center of the pixel. */ + grid_point.x += FT_INT_26D6( 1 ) / 2; + grid_point.y += FT_INT_26D6( 1 ) / 2; + + FT_CALL( sdf_edge_get_min_distance( edges, + grid_point, + &dist ) ); + + if ( internal_params.orientation == FT_ORIENTATION_FILL_LEFT ) + dist.sign = -dist.sign; + + /* ignore if the distance is greater than spread; */ + /* otherwise it creates artifacts due to the wrong sign */ + if ( dist.distance > sp_sq ) + continue; + + /* take the square root of the distance if required */ + if ( USE_SQUARED_DISTANCES ) + dist.distance = square_root( dist.distance ); + + if ( internal_params.flip_y ) + index = (FT_UInt)( y * width + x ); + else + index = (FT_UInt)( ( rows - y - 1 ) * width + x ); + + /* check whether the pixel is set or not */ + if ( dists[index].sign == 0 ) + dists[index] = dist; + else + { + diff = FT_ABS( dists[index].distance - dist.distance ); + + if ( diff <= CORNER_CHECK_EPSILON ) + dists[index] = resolve_corner( dists[index], dist ); + else if ( dists[index].distance > dist.distance ) + dists[index] = dist; + } + } + } + + edges = edges->next; + } + + contours = contours->next; + } + + /* final pass */ + for ( j = 0; j < rows; j++ ) + { + /* We assume the starting pixel of each row is outside. */ + FT_Char current_sign = -1; + FT_UInt index; + + + if ( internal_params.overload_sign != 0 ) + current_sign = internal_params.overload_sign < 0 ? -1 : 1; + + for ( i = 0; i < width; i++ ) + { + index = (FT_UInt)( j * width + i ); + + /* if the pixel is not set */ + /* its shortest distance is more than `spread` */ + if ( dists[index].sign == 0 ) + dists[index].distance = fixed_spread; + else + current_sign = dists[index].sign; + + /* clamp the values */ + if ( dists[index].distance > fixed_spread ) + dists[index].distance = fixed_spread; + + /* flip sign if required */ + dists[index].distance *= internal_params.flip_sign ? -current_sign + : current_sign; + + /* concatenate to appropriate format */ + buffer[index] = map_fixed_to_sdf( dists[index].distance, + fixed_spread ); + } + } + + Exit: + FT_FREE( dists ); + return error; + } + + + /************************************************************************** + * + * @Function: + * sdf_generate_subdivision + * + * @Description: + * Subdivide the shape into a number of straight lines, then use the + * above `sdf_generate_bounding_box` function to generate the SDF. + * + * Note: After calling this function `shape` no longer has the original + * edges, it only contains lines. + * + * @Input: + * internal_params :: + * Internal parameters and properties required by the rasterizer. + * See @SDF_Params for more. + * + * shape :: + * A complete shape which is used to generate SDF. + * + * spread :: + * Maximum distances to be allowed inthe output bitmap. + * + * @Output: + * bitmap :: + * The output bitmap which will contain the SDF information. + * + * @Return: + * FreeType error, 0 means success. + * + */ + static FT_Error + sdf_generate_subdivision( const SDF_Params internal_params, + SDF_Shape* shape, + FT_UInt spread, + const FT_Bitmap* bitmap ) + { + /* + * Thanks to Alexei for providing the idea of this optimization. + * + * We take advantage of two facts. + * + * (1) Computing the shortest distance from a point to a line segment is + * very fast. + * (2) We don't have to compute the shortest distance for the entire + * two-dimensional grid. + * + * Both ideas lead to the following optimization. + * + * (1) Split the outlines into a number of line segments. + * + * (2) For each line segment, only process its neighborhood. + * + * (3) Compute the closest distance to the line only for neighborhood + * grid points. + * + * This greatly reduces the number of grid points to check. + */ + + FT_Error error = FT_Err_Ok; + + + FT_CALL( split_sdf_shape( shape ) ); + FT_CALL( sdf_generate_bounding_box( internal_params, + shape, spread, bitmap ) ); + + Exit: + return error; + } + + + /************************************************************************** + * + * @Function: + * sdf_generate_with_overlaps + * + * @Description: + * This function can be used to generate SDF for glyphs with overlapping + * contours. The function generates SDF for contours separately on + * separate bitmaps (to generate SDF it uses + * `sdf_generate_subdivision`). At the end it simply combines all the + * SDF into the output bitmap; this fixes all the signs and removes + * overlaps. + * + * @Input: + * internal_params :: + * Internal parameters and properties required by the rasterizer. See + * @SDF_Params for more. + * + * shape :: + * A complete shape which is used to generate SDF. + * + * spread :: + * Maximum distances to be allowed in the output bitmap. + * + * @Output: + * bitmap :: + * The output bitmap which will contain the SDF information. + * + * @Return: + * FreeType error, 0 means success. + * + * @Note: + * The function cannot generate a proper SDF for glyphs with + * self-intersecting contours because we cannot separate them into two + * separate bitmaps. In case of self-intersecting contours it is + * necessary to remove the overlaps before generating the SDF. + * + */ + static FT_Error + sdf_generate_with_overlaps( SDF_Params internal_params, + SDF_Shape* shape, + FT_UInt spread, + const FT_Bitmap* bitmap ) + { + FT_Error error = FT_Err_Ok; + + FT_Int num_contours; /* total number of contours */ + FT_Int i, j; /* iterators */ + FT_Int width, rows; /* width and rows of the bitmap */ + FT_Bitmap* bitmaps; /* separate bitmaps for contours */ + + SDF_Contour* contour; /* temporary variable to iterate */ + SDF_Contour* temp_contour; /* temporary contour */ + SDF_Contour* head; /* head of the contour list */ + SDF_Shape temp_shape; /* temporary shape */ + + FT_Memory memory; /* to allocate memory */ + FT_SDFFormat* t; /* target bitmap buffer */ + FT_Bool flip_sign; /* flip sign? */ + + /* orientation of all the separate contours */ + SDF_Contour_Orientation* orientations; + + + bitmaps = NULL; + orientations = NULL; + head = NULL; + + if ( !shape || !bitmap || !shape->memory ) + return FT_THROW( Invalid_Argument ); + + /* Disable `flip_sign` to avoid extra complication */ + /* during the combination phase. */ + flip_sign = internal_params.flip_sign; + internal_params.flip_sign = 0; + + contour = shape->contours; + memory = shape->memory; + temp_shape.memory = memory; + width = (FT_Int)bitmap->width; + rows = (FT_Int)bitmap->rows; + num_contours = 0; + + /* find the number of contours in the shape */ + while ( contour ) + { + num_contours++; + contour = contour->next; + } + + /* allocate the bitmaps to generate SDF for separate contours */ + if ( FT_ALLOC( bitmaps, + (FT_UInt)num_contours * sizeof ( *bitmaps ) ) ) + goto Exit; + + /* allocate array to hold orientation for all contours */ + if ( FT_ALLOC( orientations, + (FT_UInt)num_contours * sizeof ( *orientations ) ) ) + goto Exit; + + contour = shape->contours; + + /* Iterate over all contours and generate SDF separately. */ + for ( i = 0; i < num_contours; i++ ) + { + /* initialize the corresponding bitmap */ + FT_Bitmap_Init( &bitmaps[i] ); + + bitmaps[i].width = bitmap->width; + bitmaps[i].rows = bitmap->rows; + bitmaps[i].pitch = bitmap->pitch; + bitmaps[i].num_grays = bitmap->num_grays; + bitmaps[i].pixel_mode = bitmap->pixel_mode; + + /* allocate memory for the buffer */ + if ( FT_ALLOC( bitmaps[i].buffer, + bitmap->rows * (FT_UInt)bitmap->pitch ) ) + goto Exit; + + /* determine the orientation */ + orientations[i] = get_contour_orientation( contour ); + + /* The `overload_sign` property is specific to */ + /* `sdf_generate_bounding_box`. This basically */ + /* overloads the default sign of the outside */ + /* pixels, which is necessary for */ + /* counter-clockwise contours. */ + if ( orientations[i] == SDF_ORIENTATION_CCW && + internal_params.orientation == FT_ORIENTATION_FILL_RIGHT ) + internal_params.overload_sign = 1; + else if ( orientations[i] == SDF_ORIENTATION_CW && + internal_params.orientation == FT_ORIENTATION_FILL_LEFT ) + internal_params.overload_sign = 1; + else + internal_params.overload_sign = 0; + + /* Make `contour->next` NULL so that there is */ + /* one contour in the list. Also hold the next */ + /* contour in a temporary variable so as to */ + /* restore the original value. */ + temp_contour = contour->next; + contour->next = NULL; + + /* Use `temp_shape` to hold the new contour. */ + /* Now, `temp_shape` has only one contour. */ + temp_shape.contours = contour; + + /* finally generate the SDF */ + FT_CALL( sdf_generate_subdivision( internal_params, + &temp_shape, + spread, + &bitmaps[i] ) ); + + /* Restore the original `next` variable. */ + contour->next = temp_contour; + + /* Since `split_sdf_shape` deallocated the original */ + /* contours list we need to assign the new value to */ + /* the shape's contour. */ + temp_shape.contours->next = head; + head = temp_shape.contours; + + /* Simply flip the orientation in case of post-script fonts */ + /* so as to avoid modificatons in the combining phase. */ + if ( internal_params.orientation == FT_ORIENTATION_FILL_LEFT ) + { + if ( orientations[i] == SDF_ORIENTATION_CW ) + orientations[i] = SDF_ORIENTATION_CCW; + else if ( orientations[i] == SDF_ORIENTATION_CCW ) + orientations[i] = SDF_ORIENTATION_CW; + } + + contour = contour->next; + } + + /* assign the new contour list to `shape->contours` */ + shape->contours = head; + + /* cast the output bitmap buffer */ + t = (FT_SDFFormat*)bitmap->buffer; + + /* Iterate over all pixels and combine all separate */ + /* contours. These are the rules for combining: */ + /* */ + /* (1) For all clockwise contours, compute the largest */ + /* value. Name this as `val_c`. */ + /* (2) For all counter-clockwise contours, compute the */ + /* smallest value. Name this as `val_ac`. */ + /* (3) Now, finally use the smaller value of `val_c' */ + /* and `val_ac'. */ + for ( j = 0; j < rows; j++ ) + { + for ( i = 0; i < width; i++ ) + { + FT_Int id = j * width + i; /* index of current pixel */ + FT_Int c; /* contour iterator */ + + FT_SDFFormat val_c = 0; /* max clockwise value */ + FT_SDFFormat val_ac = UCHAR_MAX; /* min counter-clockwise val */ + + + /* iterate through all the contours */ + for ( c = 0; c < num_contours; c++ ) + { + /* current contour value */ + FT_SDFFormat temp = ( (FT_SDFFormat*)bitmaps[c].buffer )[id]; + + + if ( orientations[c] == SDF_ORIENTATION_CW ) + val_c = FT_MAX( val_c, temp ); /* clockwise */ + else + val_ac = FT_MIN( val_ac, temp ); /* counter-clockwise */ + } + + /* Finally find the smaller of the two and assign to output. */ + /* Also apply `flip_sign` if set. */ + t[id] = FT_MIN( val_c, val_ac ); + + if ( flip_sign ) + t[id] = invert_sign( t[id] ); + } + } + + Exit: + /* deallocate orientations array */ + if ( orientations ) + FT_FREE( orientations ); + + /* deallocate temporary bitmaps */ + if ( bitmaps ) + { + if ( num_contours == 0 ) + error = FT_THROW( Raster_Corrupted ); + else + { + for ( i = 0; i < num_contours; i++ ) + FT_FREE( bitmaps[i].buffer ); + + FT_FREE( bitmaps ); + } + } + + /* restore the `flip_sign` property */ + internal_params.flip_sign = flip_sign; + + return error; + } + + + /************************************************************************** + * + * interface functions + * + */ + + static FT_Error + sdf_raster_new( void* memory_, /* FT_Memory */ + FT_Raster* araster_ ) /* SDF_PRaster* */ + { + FT_Memory memory = (FT_Memory)memory_; + SDF_PRaster* araster = (SDF_PRaster*)araster_; + + + FT_Error error; + SDF_PRaster raster = NULL; + + + if ( !FT_NEW( raster ) ) + raster->memory = memory; + + *araster = raster; + + return error; + } + + + static void + sdf_raster_reset( FT_Raster raster, + unsigned char* pool_base, + unsigned long pool_size ) + { + FT_UNUSED( raster ); + FT_UNUSED( pool_base ); + FT_UNUSED( pool_size ); + } + + + static FT_Error + sdf_raster_set_mode( FT_Raster raster, + unsigned long mode, + void* args ) + { + FT_UNUSED( raster ); + FT_UNUSED( mode ); + FT_UNUSED( args ); + + return FT_Err_Ok; + } + + + static FT_Error + sdf_raster_render( FT_Raster raster, + const FT_Raster_Params* params ) + { + FT_Error error = FT_Err_Ok; + SDF_TRaster* sdf_raster = (SDF_TRaster*)raster; + FT_Outline* outline = NULL; + const SDF_Raster_Params* sdf_params = (const SDF_Raster_Params*)params; + + FT_Memory memory = NULL; + SDF_Shape* shape = NULL; + SDF_Params internal_params; + + + /* check for valid arguments */ + if ( !sdf_raster || !sdf_params ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + outline = (FT_Outline*)sdf_params->root.source; + + /* check whether outline is valid */ + if ( !outline ) + { + error = FT_THROW( Invalid_Outline ); + goto Exit; + } + + /* if the outline is empty, return */ + if ( outline->n_points <= 0 || outline->n_contours <= 0 ) + goto Exit; + + /* check whether the outline has valid fields */ + if ( !outline->contours || !outline->points ) + { + error = FT_THROW( Invalid_Outline ); + goto Exit; + } + + /* check whether spread is set properly */ + if ( sdf_params->spread > MAX_SPREAD || + sdf_params->spread < MIN_SPREAD ) + { + FT_TRACE0(( "sdf_raster_render:" + " The `spread' field of `SDF_Raster_Params' is invalid,\n" )); + FT_TRACE0(( " " + " the value of this field must be within [%d, %d].\n", + MIN_SPREAD, MAX_SPREAD )); + FT_TRACE0(( " " + " Also, you must pass `SDF_Raster_Params' instead of\n" )); + FT_TRACE0(( " " + " the default `FT_Raster_Params' while calling\n" )); + FT_TRACE0(( " " + " this function and set the fields properly.\n" )); + + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + memory = sdf_raster->memory; + if ( !memory ) + { + FT_TRACE0(( "sdf_raster_render:" + " Raster not setup properly,\n" )); + FT_TRACE0(( " " + " unable to find memory handle.\n" )); + + error = FT_THROW( Invalid_Handle ); + goto Exit; + } + + /* set up the parameters */ + internal_params.orientation = FT_Outline_Get_Orientation( outline ); + internal_params.flip_sign = sdf_params->flip_sign; + internal_params.flip_y = sdf_params->flip_y; + internal_params.overload_sign = 0; + + FT_CALL( sdf_shape_new( memory, &shape ) ); + + FT_CALL( sdf_outline_decompose( outline, shape ) ); + + if ( sdf_params->overlaps ) + FT_CALL( sdf_generate_with_overlaps( internal_params, + shape, sdf_params->spread, + sdf_params->root.target ) ); + else + FT_CALL( sdf_generate_subdivision( internal_params, + shape, sdf_params->spread, + sdf_params->root.target ) ); + + if ( shape ) + sdf_shape_done( &shape ); + + Exit: + return error; + } + + + static void + sdf_raster_done( FT_Raster raster ) + { + FT_Memory memory = (FT_Memory)((SDF_TRaster*)raster)->memory; + + + FT_FREE( raster ); + } + + + FT_DEFINE_RASTER_FUNCS( + ft_sdf_raster, + + FT_GLYPH_FORMAT_OUTLINE, + + (FT_Raster_New_Func) sdf_raster_new, /* raster_new */ + (FT_Raster_Reset_Func) sdf_raster_reset, /* raster_reset */ + (FT_Raster_Set_Mode_Func)sdf_raster_set_mode, /* raster_set_mode */ + (FT_Raster_Render_Func) sdf_raster_render, /* raster_render */ + (FT_Raster_Done_Func) sdf_raster_done /* raster_done */ + ) + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/sdf/ftsdf.h b/lib/libesp32_lvgl/freetype/src/sdf/ftsdf.h new file mode 100644 index 000000000..234c075b0 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/sdf/ftsdf.h @@ -0,0 +1,97 @@ +/**************************************************************************** + * + * ftsdf.h + * + * Signed Distance Field support (specification). + * + * Copyright (C) 2020-2023 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * Written by Anuj Verma. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#ifndef FTSDF_H_ +#define FTSDF_H_ + +#include +#include FT_CONFIG_CONFIG_H +#include + +/* common properties and function */ +#include "ftsdfcommon.h" + +FT_BEGIN_HEADER + + /************************************************************************** + * + * @struct: + * SDF_Raster_Params + * + * @description: + * This struct must be passed to the raster render function + * @FT_Raster_RenderFunc instead of @FT_Raster_Params because the + * rasterizer requires some additional information to render properly. + * + * @fields: + * root :: + * The native raster parameters structure. + * + * spread :: + * This is an essential parameter/property required by the renderer. + * `spread` defines the maximum unsigned value that is present in the + * final SDF output. For the default value check file + * `ftsdfcommon.h`. + * + * flip_sign :: + * By default positive values indicate positions inside of contours, + * i.e., filled by a contour. If this property is true then that + * output will be the opposite of the default, i.e., negative values + * indicate positions inside of contours. + * + * flip_y :: + * Setting this parameter to true maked the output image flipped + * along the y-axis. + * + * overlaps :: + * Set this to true to generate SDF for glyphs having overlapping + * contours. The overlapping support is limited to glyphs that do not + * have self-intersecting contours. Also, removing overlaps require a + * considerable amount of extra memory; additionally, it will not work + * if generating SDF from bitmap. + * + * @note: + * All properties are valid for both the 'sdf' and 'bsdf' renderers; the + * exception is `overlaps`, which gets ignored by the 'bsdf' renderer. + * + */ + typedef struct SDF_Raster_Params_ + { + FT_Raster_Params root; + FT_UInt spread; + FT_Bool flip_sign; + FT_Bool flip_y; + FT_Bool overlaps; + + } SDF_Raster_Params; + + + /* rasterizer to convert outline to SDF */ + FT_EXPORT_VAR( const FT_Raster_Funcs ) ft_sdf_raster; + + /* rasterizer to convert bitmap to SDF */ + FT_EXPORT_VAR( const FT_Raster_Funcs ) ft_bitmap_sdf_raster; + +FT_END_HEADER + +#endif /* FTSDF_H_ */ + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/sdf/ftsdfcommon.c b/lib/libesp32_lvgl/freetype/src/sdf/ftsdfcommon.c new file mode 100644 index 000000000..5052201e2 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/sdf/ftsdfcommon.c @@ -0,0 +1,147 @@ +/**************************************************************************** + * + * ftsdfcommon.c + * + * Auxiliary data for Signed Distance Field support (body). + * + * Copyright (C) 2020-2023 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * Written by Anuj Verma. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#include "ftsdf.h" +#include "ftsdfcommon.h" + + + /************************************************************************** + * + * common functions + * + */ + + /* + * Original algorithm: + * + * https://github.com/chmike/fpsqrt + * + * Use this to compute the square root of a 16.16 fixed-point number. + */ + FT_LOCAL_DEF( FT_16D16 ) + square_root( FT_16D16 val ) + { + FT_ULong t, q, b, r; + + + r = (FT_ULong)val; + b = 0x40000000L; + q = 0; + + while ( b > 0x40L ) + { + t = q + b; + + if ( r >= t ) + { + r -= t; + q = t + b; + } + + r <<= 1; + b >>= 1; + } + + q >>= 8; + + return (FT_16D16)q; + } + + + /************************************************************************** + * + * format and sign manipulating functions + * + */ + + /* + * Convert 16.16 fixed-point values to the desired output format. + * In this case we reduce 16.16 fixed-point values to normalized + * 8-bit values. + * + * The `max_value` in the parameter is the maximum value in the + * distance field map and is equal to the spread. We normalize + * the distances using this value instead of computing the maximum + * value for the entire bitmap. + * + * You can use this function to map the 16.16 signed values to any + * format required. Do note that the output buffer is 8-bit, so only + * use an 8-bit format for `FT_SDFFormat`, or increase the buffer size in + * `ftsdfrend.c`. + */ + FT_LOCAL_DEF( FT_SDFFormat ) + map_fixed_to_sdf( FT_16D16 dist, + FT_16D16 max_value ) + { + FT_SDFFormat out; + FT_16D16 udist; + + + /* normalize the distance values */ + dist = FT_DivFix( dist, max_value ); + + udist = dist < 0 ? -dist : dist; + + /* Reduce the distance values to 8 bits. */ + /* */ + /* Since +1/-1 in 16.16 takes the 16th bit, we right-shift */ + /* the number by 9 to make it fit into the 7-bit range. */ + /* */ + /* One bit is reserved for the sign. */ + udist >>= 9; + + /* Since `char` can only store a maximum positive value */ + /* of 127 we need to make sure it does not wrap around and */ + /* give a negative value. */ + if ( dist > 0 && udist > 127 ) + udist = 127; + if ( dist < 0 && udist > 128 ) + udist = 128; + + /* Output the data; negative values are from [0, 127] and positive */ + /* from [128, 255]. One important thing is that negative values */ + /* are inverted here, that means [0, 128] maps to [-128, 0] linearly. */ + /* More on that in `freetype.h` near the documentation of */ + /* `FT_RENDER_MODE_SDF`. */ + out = dist < 0 ? 128 - (FT_SDFFormat)udist + : (FT_SDFFormat)udist + 128; + + return out; + } + + + /* + * Invert the signed distance packed into the corresponding format. + * So if the values are negative they will become positive in the + * chosen format. + * + * [Note]: This function should only be used after converting the + * 16.16 signed distance values to `FT_SDFFormat`. If that + * conversion has not been done, then simply invert the sign + * and use the above function to pack the values. + */ + FT_LOCAL_DEF( FT_SDFFormat ) + invert_sign( FT_SDFFormat dist ) + { + return 255 - dist; + } + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/sdf/ftsdfcommon.h b/lib/libesp32_lvgl/freetype/src/sdf/ftsdfcommon.h new file mode 100644 index 000000000..60ca9773e --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/sdf/ftsdfcommon.h @@ -0,0 +1,141 @@ +/**************************************************************************** + * + * ftsdfcommon.h + * + * Auxiliary data for Signed Distance Field support (specification). + * + * Copyright (C) 2020-2023 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * Written by Anuj Verma. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + + /**************************************************** + * + * This file contains common functions and properties + * for both the 'sdf' and 'bsdf' renderers. + * + */ + +#ifndef FTSDFCOMMON_H_ +#define FTSDFCOMMON_H_ + +#include +#include FT_CONFIG_CONFIG_H +#include + + +FT_BEGIN_HEADER + + + /************************************************************************** + * + * default values (cannot be set individually for each renderer) + * + */ + + /* default spread value */ +#define DEFAULT_SPREAD 8 + /* minimum spread supported by the renderer */ +#define MIN_SPREAD 2 + /* maximum spread supported by the renderer */ +#define MAX_SPREAD 32 + /* pixel size in 26.6 */ +#define ONE_PIXEL ( 1 << 6 ) + + + /************************************************************************** + * + * common definitions (cannot be set individually for each renderer) + * + */ + + /* If this macro is set to 1 the rasterizer uses squared distances for */ + /* computation. It can greatly improve the performance but there is a */ + /* chance of overflow and artifacts. You can safely use it up to a */ + /* pixel size of 128. */ +#ifndef USE_SQUARED_DISTANCES +#define USE_SQUARED_DISTANCES 0 +#endif + + + /************************************************************************** + * + * common macros + * + */ + + /* convert int to 26.6 fixed-point */ +#define FT_INT_26D6( x ) ( x * 64 ) + /* convert int to 16.16 fixed-point */ +#define FT_INT_16D16( x ) ( x * 65536 ) + /* convert 26.6 to 16.16 fixed-point */ +#define FT_26D6_16D16( x ) ( x * 1024 ) + + + /* Convenience macro to call a function; it */ + /* jumps to label `Exit` if an error occurs. */ +#define FT_CALL( x ) do \ + { \ + error = ( x ); \ + if ( error != FT_Err_Ok ) \ + goto Exit; \ + } while ( 0 ) + + + /* + * The macro `VECTOR_LENGTH_16D16` computes either squared distances or + * actual distances, depending on the value of `USE_SQUARED_DISTANCES`. + * + * By using squared distances the performance can be greatly improved but + * there is a risk of overflow. + */ +#if USE_SQUARED_DISTANCES +#define VECTOR_LENGTH_16D16( v ) ( FT_MulFix( v.x, v.x ) + \ + FT_MulFix( v.y, v.y ) ) +#else +#define VECTOR_LENGTH_16D16( v ) FT_Vector_Length( &v ) +#endif + + + /************************************************************************** + * + * common typedefs + * + */ + + typedef FT_Vector FT_26D6_Vec; /* with 26.6 fixed-point components */ + typedef FT_Vector FT_16D16_Vec; /* with 16.16 fixed-point components */ + + typedef FT_Int32 FT_16D16; /* 16.16 fixed-point representation */ + typedef FT_Int32 FT_26D6; /* 26.6 fixed-point representation */ + typedef FT_Byte FT_SDFFormat; /* format to represent SDF data */ + + typedef FT_BBox FT_CBox; /* control box of a curve */ + + + FT_LOCAL( FT_16D16 ) + square_root( FT_16D16 val ); + + FT_LOCAL( FT_SDFFormat ) + map_fixed_to_sdf( FT_16D16 dist, + FT_16D16 max_value ); + + FT_LOCAL( FT_SDFFormat ) + invert_sign( FT_SDFFormat dist ); + + +FT_END_HEADER + +#endif /* FTSDFCOMMON_H_ */ + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/sdf/ftsdferrs.h b/lib/libesp32_lvgl/freetype/src/sdf/ftsdferrs.h new file mode 100644 index 000000000..519db0fc2 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/sdf/ftsdferrs.h @@ -0,0 +1,37 @@ +/**************************************************************************** + * + * ftsdferrs.h + * + * Signed Distance Field error codes (specification only). + * + * Copyright (C) 2020-2023 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * Written by Anuj Verma. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#ifndef FTSDFERRS_H_ +#define FTSDFERRS_H_ + +#include + +#undef FTERRORS_H_ + +#undef FT_ERR_PREFIX +#define FT_ERR_PREFIX Sdf_Err_ +#define FT_ERR_BASE FT_Mod_Err_Sdf + +#include + +#endif /* FTSDFERRS_H_ */ + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/sdf/ftsdfrend.c b/lib/libesp32_lvgl/freetype/src/sdf/ftsdfrend.c new file mode 100644 index 000000000..5610c119f --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/sdf/ftsdfrend.c @@ -0,0 +1,603 @@ +/**************************************************************************** + * + * ftsdfrend.c + * + * Signed Distance Field renderer interface (body). + * + * Copyright (C) 2020-2023 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * Written by Anuj Verma. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#include +#include +#include +#include +#include +#include "ftsdfrend.h" +#include "ftsdf.h" + +#include "ftsdferrs.h" + + + /************************************************************************** + * + * The macro FT_COMPONENT is used in trace mode. It is an implicit + * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log + * messages during execution. + */ +#undef FT_COMPONENT +#define FT_COMPONENT sdf + + + /************************************************************************** + * + * macros and default property values + * + */ +#define SDF_RENDERER( rend ) ( (SDF_Renderer)rend ) + + + /************************************************************************** + * + * for setting properties + * + */ + + /* property setter function */ + static FT_Error + sdf_property_set( FT_Module module, + const char* property_name, + const void* value, + FT_Bool value_is_string ) + { + FT_Error error = FT_Err_Ok; + SDF_Renderer render = SDF_RENDERER( FT_RENDERER( module ) ); + + FT_UNUSED( value_is_string ); + + + if ( ft_strcmp( property_name, "spread" ) == 0 ) + { + FT_Int val = *(const FT_Int*)value; + + + if ( val > MAX_SPREAD || val < MIN_SPREAD ) + { + FT_TRACE0(( "[sdf] sdf_property_set:" + " the `spread' property can have a value\n" )); + FT_TRACE0(( " " + " within range [%d, %d] (value provided: %d)\n", + MIN_SPREAD, MAX_SPREAD, val )); + + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + render->spread = (FT_UInt)val; + FT_TRACE7(( "[sdf] sdf_property_set:" + " updated property `spread' to %d\n", val )); + } + + else if ( ft_strcmp( property_name, "flip_sign" ) == 0 ) + { + FT_Int val = *(const FT_Int*)value; + + + render->flip_sign = val ? 1 : 0; + FT_TRACE7(( "[sdf] sdf_property_set:" + " updated property `flip_sign' to %d\n", val )); + } + + else if ( ft_strcmp( property_name, "flip_y" ) == 0 ) + { + FT_Int val = *(const FT_Int*)value; + + + render->flip_y = val ? 1 : 0; + FT_TRACE7(( "[sdf] sdf_property_set:" + " updated property `flip_y' to %d\n", val )); + } + + else if ( ft_strcmp( property_name, "overlaps" ) == 0 ) + { + FT_Bool val = *(const FT_Bool*)value; + + + render->overlaps = val; + FT_TRACE7(( "[sdf] sdf_property_set:" + " updated property `overlaps' to %d\n", val )); + } + + else + { + FT_TRACE0(( "[sdf] sdf_property_set:" + " missing property `%s'\n", property_name )); + error = FT_THROW( Missing_Property ); + } + + Exit: + return error; + } + + + /* property getter function */ + static FT_Error + sdf_property_get( FT_Module module, + const char* property_name, + void* value ) + { + FT_Error error = FT_Err_Ok; + SDF_Renderer render = SDF_RENDERER( FT_RENDERER( module ) ); + + + if ( ft_strcmp( property_name, "spread" ) == 0 ) + { + FT_UInt* val = (FT_UInt*)value; + + + *val = render->spread; + } + + else if ( ft_strcmp( property_name, "flip_sign" ) == 0 ) + { + FT_Int* val = (FT_Int*)value; + + + *val = render->flip_sign; + } + + else if ( ft_strcmp( property_name, "flip_y" ) == 0 ) + { + FT_Int* val = (FT_Int*)value; + + + *val = render->flip_y; + } + + else if ( ft_strcmp( property_name, "overlaps" ) == 0 ) + { + FT_Int* val = (FT_Int*)value; + + + *val = render->overlaps; + } + + else + { + FT_TRACE0(( "[sdf] sdf_property_get:" + " missing property `%s'\n", property_name )); + error = FT_THROW( Missing_Property ); + } + + return error; + } + + + FT_DEFINE_SERVICE_PROPERTIESREC( + sdf_service_properties, + + (FT_Properties_SetFunc)sdf_property_set, /* set_property */ + (FT_Properties_GetFunc)sdf_property_get ) /* get_property */ + + + FT_DEFINE_SERVICEDESCREC1( + sdf_services, + + FT_SERVICE_ID_PROPERTIES, &sdf_service_properties ) + + + static FT_Module_Interface + ft_sdf_requester( FT_Module module, + const char* module_interface ) + { + FT_UNUSED( module ); + + return ft_service_list_lookup( sdf_services, module_interface ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /** **/ + /** OUTLINE TO SDF CONVERTER **/ + /** **/ + /*************************************************************************/ + /*************************************************************************/ + + /************************************************************************** + * + * interface functions + * + */ + + static FT_Error + ft_sdf_init( FT_Module module ) /* SDF_Renderer */ + { + SDF_Renderer sdf_render = SDF_RENDERER( module ); + + + sdf_render->spread = DEFAULT_SPREAD; + sdf_render->flip_sign = 0; + sdf_render->flip_y = 0; + sdf_render->overlaps = 0; + + return FT_Err_Ok; + } + + + static void + ft_sdf_done( FT_Module module ) + { + FT_UNUSED( module ); + } + + + /* generate signed distance field from a glyph's slot image */ + static FT_Error + ft_sdf_render( FT_Renderer module, + FT_GlyphSlot slot, + FT_Render_Mode mode, + const FT_Vector* origin ) + { + FT_Error error = FT_Err_Ok; + FT_Outline* outline = &slot->outline; + FT_Bitmap* bitmap = &slot->bitmap; + FT_Memory memory = NULL; + FT_Renderer render = NULL; + + FT_Pos x_shift = 0; + FT_Pos y_shift = 0; + + FT_Pos x_pad = 0; + FT_Pos y_pad = 0; + + SDF_Raster_Params params; + SDF_Renderer sdf_module = SDF_RENDERER( module ); + + + render = &sdf_module->root; + memory = render->root.memory; + + /* check whether slot format is correct before rendering */ + if ( slot->format != render->glyph_format ) + { + error = FT_THROW( Invalid_Glyph_Format ); + goto Exit; + } + + /* check whether render mode is correct */ + if ( mode != FT_RENDER_MODE_SDF ) + { + error = FT_THROW( Cannot_Render_Glyph ); + goto Exit; + } + + /* deallocate the previously allocated bitmap */ + if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) + { + FT_FREE( bitmap->buffer ); + slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; + } + + /* preset the bitmap using the glyph's outline; */ + /* the sdf bitmap is similar to an anti-aliased bitmap */ + /* with a slightly bigger size and different pixel mode */ + if ( ft_glyphslot_preset_bitmap( slot, FT_RENDER_MODE_NORMAL, origin ) ) + { + error = FT_THROW( Raster_Overflow ); + goto Exit; + } + + /* nothing to render */ + if ( !bitmap->rows || !bitmap->pitch ) + goto Exit; + + /* the padding will simply be equal to the `spread' */ + x_pad = sdf_module->spread; + y_pad = sdf_module->spread; + + /* apply the padding; will be in all the directions */ + bitmap->rows += y_pad * 2; + bitmap->width += x_pad * 2; + + /* ignore the pitch, pixel mode and set custom */ + bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; + bitmap->pitch = (int)( bitmap->width ); + bitmap->num_grays = 255; + + /* allocate new buffer */ + if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) ) + goto Exit; + + slot->internal->flags |= FT_GLYPH_OWN_BITMAP; + + slot->bitmap_top += y_pad; + slot->bitmap_left -= x_pad; + + x_shift = 64 * -slot->bitmap_left; + y_shift = 64 * -slot->bitmap_top; + y_shift += 64 * (FT_Int)bitmap->rows; + + if ( origin ) + { + x_shift += origin->x; + y_shift += origin->y; + } + + /* translate outline to render it into the bitmap */ + if ( x_shift || y_shift ) + FT_Outline_Translate( outline, x_shift, y_shift ); + + /* set up parameters */ + params.root.target = bitmap; + params.root.source = outline; + params.root.flags = FT_RASTER_FLAG_SDF; + params.spread = sdf_module->spread; + params.flip_sign = sdf_module->flip_sign; + params.flip_y = sdf_module->flip_y; + params.overlaps = sdf_module->overlaps; + + /* render the outline */ + error = render->raster_render( render->raster, + (const FT_Raster_Params*)¶ms ); + + /* transform the outline back to the original state */ + if ( x_shift || y_shift ) + FT_Outline_Translate( outline, -x_shift, -y_shift ); + + Exit: + if ( !error ) + { + /* the glyph is successfully rendered to a bitmap */ + slot->format = FT_GLYPH_FORMAT_BITMAP; + } + else if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) + { + FT_FREE( bitmap->buffer ); + slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; + } + + return error; + } + + + /* transform the glyph using matrix and/or delta */ + static FT_Error + ft_sdf_transform( FT_Renderer render, + FT_GlyphSlot slot, + const FT_Matrix* matrix, + const FT_Vector* delta ) + { + FT_Error error = FT_Err_Ok; + + + if ( slot->format != render->glyph_format ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + if ( matrix ) + FT_Outline_Transform( &slot->outline, matrix ); + + if ( delta ) + FT_Outline_Translate( &slot->outline, delta->x, delta->y ); + + Exit: + return error; + } + + + /* return the control box of a glyph's outline */ + static void + ft_sdf_get_cbox( FT_Renderer render, + FT_GlyphSlot slot, + FT_BBox* cbox ) + { + FT_ZERO( cbox ); + + if ( slot->format == render->glyph_format ) + FT_Outline_Get_CBox( &slot->outline, cbox ); + } + + + /* set render specific modes or attributes */ + static FT_Error + ft_sdf_set_mode( FT_Renderer render, + FT_ULong mode_tag, + FT_Pointer data ) + { + /* pass it to the rasterizer */ + return render->clazz->raster_class->raster_set_mode( render->raster, + mode_tag, + data ); + } + + + FT_DEFINE_RENDERER( + ft_sdf_renderer_class, + + FT_MODULE_RENDERER, + sizeof ( SDF_Renderer_Module ), + + "sdf", + 0x10000L, + 0x20000L, + + NULL, + + (FT_Module_Constructor)ft_sdf_init, + (FT_Module_Destructor) ft_sdf_done, + (FT_Module_Requester) ft_sdf_requester, + + FT_GLYPH_FORMAT_OUTLINE, + + (FT_Renderer_RenderFunc) ft_sdf_render, /* render_glyph */ + (FT_Renderer_TransformFunc)ft_sdf_transform, /* transform_glyph */ + (FT_Renderer_GetCBoxFunc) ft_sdf_get_cbox, /* get_glyph_cbox */ + (FT_Renderer_SetModeFunc) ft_sdf_set_mode, /* set_mode */ + + (FT_Raster_Funcs*)&ft_sdf_raster /* raster_class */ + ) + + + /*************************************************************************/ + /*************************************************************************/ + /** **/ + /** BITMAP TO SDF CONVERTER **/ + /** **/ + /*************************************************************************/ + /*************************************************************************/ + + /* generate signed distance field from glyph's bitmap */ + static FT_Error + ft_bsdf_render( FT_Renderer module, + FT_GlyphSlot slot, + FT_Render_Mode mode, + const FT_Vector* origin ) + { + FT_Error error = FT_Err_Ok; + FT_Memory memory = NULL; + + FT_Bitmap* bitmap = &slot->bitmap; + FT_Renderer render = NULL; + FT_Bitmap target; + + FT_Pos x_pad = 0; + FT_Pos y_pad = 0; + + SDF_Raster_Params params; + SDF_Renderer sdf_module = SDF_RENDERER( module ); + + + /* initialize the bitmap in case any error occurs */ + FT_Bitmap_Init( &target ); + + render = &sdf_module->root; + memory = render->root.memory; + + /* check whether slot format is correct before rendering */ + if ( slot->format != render->glyph_format ) + { + error = FT_THROW( Invalid_Glyph_Format ); + goto Exit; + } + + /* check whether render mode is correct */ + if ( mode != FT_RENDER_MODE_SDF ) + { + error = FT_THROW( Cannot_Render_Glyph ); + goto Exit; + } + + if ( origin ) + { + FT_ERROR(( "ft_bsdf_render: can't translate the bitmap\n" )); + + error = FT_THROW( Unimplemented_Feature ); + goto Exit; + } + + /* nothing to render */ + if ( !bitmap->rows || !bitmap->pitch ) + goto Exit; + + /* Do not generate SDF if the bitmap is not owned by the */ + /* glyph: it might be that the source buffer is already freed. */ + if ( !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) ) + { + FT_ERROR(( "ft_bsdf_render: can't generate SDF from" + " unowned source bitmap\n" )); + + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + FT_Bitmap_New( &target ); + + /* padding will simply be equal to `spread` */ + x_pad = sdf_module->spread; + y_pad = sdf_module->spread; + + /* apply padding, which extends to all directions */ + target.rows = bitmap->rows + y_pad * 2; + target.width = bitmap->width + x_pad * 2; + + /* set up the target bitmap */ + target.pixel_mode = FT_PIXEL_MODE_GRAY; + target.pitch = (int)( target.width ); + target.num_grays = 255; + + if ( FT_ALLOC_MULT( target.buffer, target.rows, target.pitch ) ) + goto Exit; + + /* set up parameters */ + params.root.target = ⌖ + params.root.source = bitmap; + params.root.flags = FT_RASTER_FLAG_SDF; + params.spread = sdf_module->spread; + params.flip_sign = sdf_module->flip_sign; + params.flip_y = sdf_module->flip_y; + + error = render->raster_render( render->raster, + (const FT_Raster_Params*)¶ms ); + + Exit: + if ( !error ) + { + /* the glyph is successfully converted to a SDF */ + if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) + FT_FREE( bitmap->buffer ); + + slot->bitmap = target; + slot->bitmap_top += y_pad; + slot->bitmap_left -= x_pad; + + if ( target.buffer ) + slot->internal->flags |= FT_GLYPH_OWN_BITMAP; + } + else if ( target.buffer ) + FT_FREE( target.buffer ); + + return error; + } + + + FT_DEFINE_RENDERER( + ft_bitmap_sdf_renderer_class, + + FT_MODULE_RENDERER, + sizeof ( SDF_Renderer_Module ), + + "bsdf", + 0x10000L, + 0x20000L, + + NULL, + + (FT_Module_Constructor)ft_sdf_init, + (FT_Module_Destructor) ft_sdf_done, + (FT_Module_Requester) ft_sdf_requester, + + FT_GLYPH_FORMAT_BITMAP, + + (FT_Renderer_RenderFunc) ft_bsdf_render, /* render_glyph */ + (FT_Renderer_TransformFunc)ft_sdf_transform, /* transform_glyph */ + (FT_Renderer_GetCBoxFunc) ft_sdf_get_cbox, /* get_glyph_cbox */ + (FT_Renderer_SetModeFunc) ft_sdf_set_mode, /* set_mode */ + + (FT_Raster_Funcs*)&ft_bitmap_sdf_raster /* raster_class */ + ) + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/sdf/ftsdfrend.h b/lib/libesp32_lvgl/freetype/src/sdf/ftsdfrend.h new file mode 100644 index 000000000..571ac833d --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/sdf/ftsdfrend.h @@ -0,0 +1,118 @@ +/**************************************************************************** + * + * ftsdfrend.h + * + * Signed Distance Field renderer interface (specification). + * + * Copyright (C) 2020-2023 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * Written by Anuj Verma. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#ifndef FTSDFREND_H_ +#define FTSDFREND_H_ + +#include +#include +#include + +FT_BEGIN_HEADER + + + /************************************************************************** + * + * @struct: + * SDF_Renderer_Module + * + * @description: + * This struct extends the native renderer struct `FT_RendererRec`. It + * is basically used to store various parameters required by the + * renderer and some additional parameters that can be used to tweak the + * output of the renderer. + * + * @fields: + * root :: + * The native rendere struct. + * + * spread :: + * This is an essential parameter/property required by the renderer. + * `spread` defines the maximum unsigned value that is present in the + * final SDF output. For the default value check file + * `ftsdfcommon.h`. + * + * flip_sign :: + * By default positive values indicate positions inside of contours, + * i.e., filled by a contour. If this property is true then that + * output will be the opposite of the default, i.e., negative values + * indicate positions inside of contours. + * + * flip_y :: + * Setting this parameter to true makes the output image flipped + * along the y-axis. + * + * overlaps :: + * Set this to true to generate SDF for glyphs having overlapping + * contours. The overlapping support is limited to glyphs that do not + * have self-intersecting contours. Also, removing overlaps require a + * considerable amount of extra memory; additionally, it will not work + * if generating SDF from bitmap. + * + * @note: + * All properties except `overlaps` are valid for both the 'sdf' and + * 'bsdf' renderers. + * + */ + typedef struct SDF_Renderer_Module_ + { + FT_RendererRec root; + FT_UInt spread; + FT_Bool flip_sign; + FT_Bool flip_y; + FT_Bool overlaps; + + } SDF_Renderer_Module, *SDF_Renderer; + + + /************************************************************************** + * + * @renderer: + * ft_sdf_renderer_class + * + * @description: + * Renderer to convert @FT_Outline to signed distance fields. + * + */ + FT_DECLARE_RENDERER( ft_sdf_renderer_class ) + + + /************************************************************************** + * + * @renderer: + * ft_bitmap_sdf_renderer_class + * + * @description: + * This is not exactly a renderer; it is just a converter that + * transforms bitmaps to signed distance fields. + * + * @note: + * This is not a separate module, it is part of the 'sdf' module. + * + */ + FT_DECLARE_RENDERER( ft_bitmap_sdf_renderer_class ) + + +FT_END_HEADER + +#endif /* FTSDFREND_H_ */ + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/sdf/module.mk b/lib/libesp32_lvgl/freetype/src/sdf/module.mk new file mode 100644 index 000000000..e896d20e6 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/sdf/module.mk @@ -0,0 +1,29 @@ +# +# FreeType 2 Signed Distance Field module definition +# + + +# Copyright (C) 2020-2023 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +FTMODULE_H_COMMANDS += SDF_RENDERER +FTMODULE_H_COMMANDS += BSDF_RENDERER + +define SDF_RENDERER +$(OPEN_DRIVER) FT_Renderer_Class, ft_sdf_renderer_class $(CLOSE_DRIVER) +$(ECHO_DRIVER)sdf $(ECHO_DRIVER_DESC)signed distance field renderer$(ECHO_DRIVER_DONE) +endef + +define BSDF_RENDERER +$(OPEN_DRIVER) FT_Renderer_Class, ft_bitmap_sdf_renderer_class $(CLOSE_DRIVER) +$(ECHO_DRIVER)bsdf $(ECHO_DRIVER_DESC)bitmap to signed distance field converter$(ECHO_DRIVER_DONE) +endef + +#EOF diff --git a/lib/libesp32_lvgl/freetype/src/sdf/rules.mk b/lib/libesp32_lvgl/freetype/src/sdf/rules.mk new file mode 100644 index 000000000..d7742413c --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/sdf/rules.mk @@ -0,0 +1,78 @@ +# +# FreeType 2 Signed Distance Field driver configuration rules +# + + +# Copyright (C) 2020-2023 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# sdf driver directory +# +SDF_DIR := $(SRC_DIR)/sdf + + +# compilation flags for the driver +# +SDF_COMPILE := $(CC) $(ANSIFLAGS) \ + $I$(subst /,$(COMPILER_SEP),$(SDF_DIR)) \ + $(INCLUDE_FLAGS) \ + $(FT_CFLAGS) + + +# sdf driver sources (i.e., C files) +# +SDF_DRV_SRC := $(SDF_DIR)/ftsdfrend.c \ + $(SDF_DIR)/ftsdf.c \ + $(SDF_DIR)/ftbsdf.c \ + $(SDF_DIR)/ftsdfcommon.c + + +# sdf driver headers +# +SDF_DRV_H := $(SDF_DIR)/ftsdfrend.h \ + $(SDF_DIR)/ftsdf.h \ + $(SDF_DIR)/ftsdferrs.h \ + $(SDF_DIR)/ftsdfcommon.h + + +# sdf driver object(s) +# +# SDF_DRV_OBJ_M is used during `multi' builds. +# SDF_DRV_OBJ_S is used during `single' builds. +# +SDF_DRV_OBJ_M := $(SDF_DRV_SRC:$(SDF_DIR)/%.c=$(OBJ_DIR)/%.$O) +SDF_DRV_OBJ_S := $(OBJ_DIR)/sdf.$O + + +# sdf driver source file for single build +# +SDF_DRV_SRC_S := $(SDF_DIR)/sdf.c + + +# sdf driver - single object +# +$(SDF_DRV_OBJ_S): $(SDF_DRV_SRC_S) $(SDF_DRV_SRC) \ + $(FREETYPE_H) $(SDF_DRV_H) + $(SDF_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(SDF_DRV_SRC_S)) + + +# sdf driver - multiple objects +# +$(OBJ_DIR)/%.$O: $(SDF_DIR)/%.c $(FREETYPE_H) $(SDF_DRV_H) + $(SDF_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) + + +# update main driver list +# +DRV_OBJS_S += $(SDF_DRV_OBJ_S) +DRV_OBJS_M += $(SDF_DRV_OBJ_M) + + +# EOF diff --git a/lib/libesp32_lvgl/freetype/src/sdf/sdf.c b/lib/libesp32_lvgl/freetype/src/sdf/sdf.c new file mode 100644 index 000000000..c159b0812 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/sdf/sdf.c @@ -0,0 +1,29 @@ +/**************************************************************************** + * + * sdf.c + * + * FreeType Signed Distance Field renderer module component (body only). + * + * Copyright (C) 2020-2023 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * Written by Anuj Verma. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include "ftsdfrend.c" +#include "ftsdfcommon.c" +#include "ftbsdf.c" +#include "ftsdf.c" + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/module.mk b/lib/libesp32_lvgl/freetype/src/sfnt/module.mk index 0f459d842..4491a1b22 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/module.mk +++ b/lib/libesp32_lvgl/freetype/src/sfnt/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/pngshim.c b/lib/libesp32_lvgl/freetype/src/sfnt/pngshim.c index f55016122..33712162e 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/pngshim.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/pngshim.c @@ -4,7 +4,7 @@ * * PNG Bitmap glyph support. * - * Copyright (C) 2013-2020 by + * Copyright (C) 2013-2023 by * Google, Inc. * Written by Stuart Gill and Behdad Esfahbod. * @@ -239,7 +239,7 @@ *e = FT_THROW( Invalid_Stream_Read ); png_error( png, NULL ); - return; + /* return; (never reached) */ } ft_memcpy( data, stream->cursor, length ); @@ -270,7 +270,10 @@ int bitdepth, color_type, interlace; FT_Int i; - png_byte* *rows = NULL; /* pacify compiler */ + + /* `rows` gets modified within a 'setjmp' scope; */ + /* we thus need the `volatile` keyword. */ + png_byte* *volatile rows = NULL; if ( x_offset < 0 || @@ -364,7 +367,7 @@ } /* transform transparency to alpha */ - if ( png_get_valid(png, info, PNG_INFO_tRNS ) ) + if ( png_get_valid( png, info, PNG_INFO_tRNS ) ) png_set_tRNS_to_alpha( png ); if ( bitdepth == 16 ) @@ -384,7 +387,7 @@ png_set_filler( png, 0xFF, PNG_FILLER_AFTER ); /* recheck header after setting EXPAND options */ - png_read_update_info(png, info ); + png_read_update_info( png, info ); png_get_IHDR( png, info, &imgWidth, &imgHeight, &bitdepth, &color_type, &interlace, @@ -403,9 +406,7 @@ switch ( color_type ) { - default: - /* Shouldn't happen, but fall through. */ - + default: /* Shouldn't happen, but ... */ case PNG_COLOR_TYPE_RGB_ALPHA: png_set_read_user_transform_fn( png, premultiply_data ); break; @@ -427,7 +428,7 @@ goto DestroyExit; } - if ( FT_NEW_ARRAY( rows, imgHeight ) ) + if ( FT_QNEW_ARRAY( rows, imgHeight ) ) { error = FT_THROW( Out_Of_Memory ); goto DestroyExit; @@ -438,11 +439,11 @@ png_read_image( png, rows ); - FT_FREE( rows ); - png_read_end( png, info ); DestroyExit: + /* even if reading fails with longjmp, rows must be freed */ + FT_FREE( rows ); png_destroy_read_struct( &png, &info, NULL ); FT_Stream_Close( &stream ); @@ -453,7 +454,7 @@ #else /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */ /* ANSI C doesn't like empty source files */ - typedef int _pngshim_dummy; + typedef int pngshim_dummy_; #endif /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */ diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/pngshim.h b/lib/libesp32_lvgl/freetype/src/sfnt/pngshim.h index 2d6e83d69..903bd2bc3 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/pngshim.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/pngshim.h @@ -4,7 +4,7 @@ * * PNG Bitmap glyph support. * - * Copyright (C) 2013-2020 by + * Copyright (C) 2013-2023 by * Google, Inc. * Written by Stuart Gill and Behdad Esfahbod. * diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/rules.mk b/lib/libesp32_lvgl/freetype/src/sfnt/rules.mk index f56ef060e..4d2d7e8d8 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/sfnt/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, @@ -36,6 +36,7 @@ SFNT_DRV_SRC := $(SFNT_DIR)/pngshim.c \ $(SFNT_DIR)/ttbdf.c \ $(SFNT_DIR)/ttcmap.c \ $(SFNT_DIR)/ttcolr.c \ + $(SFNT_DIR)/ttsvg.c \ $(SFNT_DIR)/ttcpal.c \ $(SFNT_DIR)/ttkern.c \ $(SFNT_DIR)/ttload.c \ diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/sfdriver.c b/lib/libesp32_lvgl/freetype/src/sfnt/sfdriver.c index 0460339a7..0925940b0 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/sfdriver.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/sfdriver.c @@ -4,7 +4,7 @@ * * High-level SFNT driver interface (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -36,6 +36,10 @@ #include "ttcpal.h" #endif +#ifdef FT_CONFIG_OPTION_SVG +#include "ttsvg.h" +#endif + #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES #include "ttpost.h" #endif @@ -75,41 +79,57 @@ * */ - static void* - get_sfnt_table( TT_Face face, + FT_CALLBACK_DEF( FT_Error ) + sfnt_load_table( FT_Face face, /* TT_Face */ + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ) + { + TT_Face ttface = (TT_Face)face; + + + return tt_face_load_any( ttface, tag, offset, buffer, length ); + } + + + FT_CALLBACK_DEF( void* ) + get_sfnt_table( FT_Face face, /* TT_Face */ FT_Sfnt_Tag tag ) { + TT_Face ttface = (TT_Face)face; + void* table; switch ( tag ) { case FT_SFNT_HEAD: - table = &face->header; + table = &ttface->header; break; case FT_SFNT_HHEA: - table = &face->horizontal; + table = &ttface->horizontal; break; case FT_SFNT_VHEA: - table = face->vertical_info ? &face->vertical : NULL; + table = ttface->vertical_info ? &ttface->vertical : NULL; break; case FT_SFNT_OS2: - table = ( face->os2.version == 0xFFFFU ) ? NULL : &face->os2; + table = ( ttface->os2.version == 0xFFFFU ) ? NULL : &ttface->os2; break; case FT_SFNT_POST: - table = &face->postscript; + table = &ttface->postscript; break; case FT_SFNT_MAXP: - table = &face->max_profile; + table = &ttface->max_profile; break; case FT_SFNT_PCLT: - table = face->pclt.Version ? &face->pclt : NULL; + table = ttface->pclt.Version ? &ttface->pclt : NULL; break; default: @@ -120,26 +140,29 @@ } - static FT_Error - sfnt_table_info( TT_Face face, + FT_CALLBACK_DEF( FT_Error ) + sfnt_table_info( FT_Face face, /* TT_Face */ FT_UInt idx, FT_ULong *tag, FT_ULong *offset, FT_ULong *length ) { + TT_Face ttface = (TT_Face)face; + + if ( !offset || !length ) return FT_THROW( Invalid_Argument ); if ( !tag ) - *length = face->num_tables; + *length = ttface->num_tables; else { - if ( idx >= face->num_tables ) + if ( idx >= ttface->num_tables ) return FT_THROW( Table_Missing ); - *tag = face->dir_tables[idx].Tag; - *offset = face->dir_tables[idx].Offset; - *length = face->dir_tables[idx].Length; + *tag = ttface->dir_tables[idx].Tag; + *offset = ttface->dir_tables[idx].Offset; + *length = ttface->dir_tables[idx].Length; } return FT_Err_Ok; @@ -149,9 +172,9 @@ FT_DEFINE_SERVICE_SFNT_TABLEREC( sfnt_service_sfnt_table, - (FT_SFNT_TableLoadFunc)tt_face_load_any, /* load_table */ - (FT_SFNT_TableGetFunc) get_sfnt_table, /* get_table */ - (FT_SFNT_TableInfoFunc)sfnt_table_info /* table_info */ + sfnt_load_table, /* FT_SFNT_TableLoadFunc load_table */ + get_sfnt_table, /* FT_SFNT_TableGetFunc get_table */ + sfnt_table_info /* FT_SFNT_TableInfoFunc table_info */ ) @@ -162,7 +185,7 @@ * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) sfnt_get_glyph_name( FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, @@ -180,7 +203,7 @@ } - static FT_UInt + FT_CALLBACK_DEF( FT_UInt ) sfnt_get_name_index( FT_Face face, const FT_String* glyph_name ) { @@ -217,8 +240,8 @@ FT_DEFINE_SERVICE_GLYPHDICTREC( sfnt_service_glyph_dict, - (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name, /* get_name */ - (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index /* name_index */ + sfnt_get_glyph_name, /* FT_GlyphDict_GetNameFunc get_name */ + sfnt_get_name_index /* FT_GlyphDict_NameIndexFunc name_index */ ) #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ @@ -374,61 +397,61 @@ { case 15: k4 ^= (FT_UInt32)tail[14] << 16; - /* fall through */ + FALL_THROUGH; case 14: k4 ^= (FT_UInt32)tail[13] << 8; - /* fall through */ + FALL_THROUGH; case 13: k4 ^= (FT_UInt32)tail[12]; k4 *= c4; k4 = ROTL32( k4, 18 ); k4 *= c1; h4 ^= k4; - /* fall through */ + FALL_THROUGH; case 12: k3 ^= (FT_UInt32)tail[11] << 24; - /* fall through */ + FALL_THROUGH; case 11: k3 ^= (FT_UInt32)tail[10] << 16; - /* fall through */ + FALL_THROUGH; case 10: k3 ^= (FT_UInt32)tail[9] << 8; - /* fall through */ + FALL_THROUGH; case 9: k3 ^= (FT_UInt32)tail[8]; k3 *= c3; k3 = ROTL32( k3, 17 ); k3 *= c4; h3 ^= k3; - /* fall through */ + FALL_THROUGH; case 8: k2 ^= (FT_UInt32)tail[7] << 24; - /* fall through */ + FALL_THROUGH; case 7: k2 ^= (FT_UInt32)tail[6] << 16; - /* fall through */ + FALL_THROUGH; case 6: k2 ^= (FT_UInt32)tail[5] << 8; - /* fall through */ + FALL_THROUGH; case 5: k2 ^= (FT_UInt32)tail[4]; k2 *= c2; k2 = ROTL32( k2, 16 ); k2 *= c3; h2 ^= k2; - /* fall through */ + FALL_THROUGH; case 4: k1 ^= (FT_UInt32)tail[3] << 24; - /* fall through */ + FALL_THROUGH; case 3: k1 ^= (FT_UInt32)tail[2] << 16; - /* fall through */ + FALL_THROUGH; case 2: k1 ^= (FT_UInt32)tail[1] << 8; - /* fall through */ + FALL_THROUGH; case 1: k1 ^= (FT_UInt32)tail[0]; k1 *= c1; @@ -491,17 +514,15 @@ char_type_func char_type, FT_Bool report_invalid_characters ) { - FT_Error error = FT_Err_Ok; + FT_Error error; char* result = NULL; FT_String* r; FT_Char* p; FT_UInt len; - FT_UNUSED( error ); - - if ( FT_ALLOC( result, entry->stringLength / 2 + 1 ) ) + if ( FT_QALLOC( result, entry->stringLength / 2 + 1 ) ) return NULL; if ( FT_STREAM_SEEK( entry->stringOffset ) || @@ -521,15 +542,14 @@ FT_TRACE0(( "get_win_string:" " Character 0x%X invalid in PS name string\n", ((unsigned)p[0])*256 + (unsigned)p[1] )); - break; + continue; } } - if ( !len ) - *r = '\0'; + *r = '\0'; FT_FRAME_EXIT(); - if ( !len ) + if ( r != result ) return result; get_win_string_error: @@ -550,17 +570,15 @@ char_type_func char_type, FT_Bool report_invalid_characters ) { - FT_Error error = FT_Err_Ok; + FT_Error error; char* result = NULL; FT_String* r; FT_Char* p; FT_UInt len; - FT_UNUSED( error ); - - if ( FT_ALLOC( result, entry->stringLength + 1 ) ) + if ( FT_QALLOC( result, entry->stringLength + 1 ) ) return NULL; if ( FT_STREAM_SEEK( entry->stringOffset ) || @@ -580,15 +598,14 @@ FT_TRACE0(( "get_apple_string:" " Character `%c' (0x%X) invalid in PS name string\n", *p, *p )); - break; + continue; } } - if ( !len ) - *r = '\0'; + *r = '\0'; FT_FRAME_EXIT(); - if ( !len ) + if ( r != result ) return result; get_apple_string_error: @@ -602,7 +619,7 @@ } - static FT_Bool + FT_CALLBACK_DEF( FT_Bool ) sfnt_get_name_id( TT_Face face, FT_UShort id, FT_Int *win, @@ -657,7 +674,7 @@ /* - * Find the shortest decimal representation of a 16.16 fixed point + * Find the shortest decimal representation of a 16.16 fixed-point * number. The function fills `buf' with the result, returning a pointer * to the position after the representation's last byte. */ @@ -733,7 +750,7 @@ an equivalent representation of `fixed'. The above FOR loop always finds the larger of the two values; I - verified this by iterating over all possible fixed point numbers. + verified this by iterating over all possible fixed-point numbers. If the remainder is 17232*10, both values are equally good, and we take the next even number (following IEEE 754's `round to nearest, @@ -741,7 +758,7 @@ If the remainder is smaller than 17232*10, the lower of the two numbers is nearer to the exact result (values 17232 and 34480 were - also found by testing all possible fixed point values). + also found by testing all possible fixed-point values). We use this to find a shorter decimal representation. If not ending with digit zero, we take the representation with less error. @@ -819,9 +836,9 @@ if ( !found ) { - /* as a last resort we try the family name; note that this is */ - /* not in the Adobe TechNote, but GX fonts (which predate the */ - /* TechNote) benefit from this behaviour */ + /* according to the 'name' documentation in the OpenType */ + /* specification the font family name is to be used if the */ + /* typographic family name is missing, so let's do that */ found = sfnt_get_name_id( face, TT_NAME_ID_FONT_FAMILY, &win, @@ -853,6 +870,10 @@ { FT_TRACE0(( "sfnt_get_var_ps_name:" " No valid PS name prefix for font instances found\n" )); + /* XXX It probably makes sense to never let this fail */ + /* since an arbitrary prefix should work, too. */ + /* On the other hand, it is very unlikely that */ + /* we ever reach this code at all. */ return NULL; } @@ -868,8 +889,8 @@ result[len] = '\0'; FT_TRACE0(( "sfnt_get_var_ps_name:" - " Shortening variation PS name prefix\n" - " " + " Shortening variation PS name prefix\n" )); + FT_TRACE0(( " " " to %d characters\n", len )); } @@ -920,16 +941,16 @@ if ( !subfamily_name ) { FT_TRACE1(( "sfnt_get_var_ps_name:" - " can't construct named instance PS name;\n" - " " + " can't construct named instance PS name;\n" )); + FT_TRACE1(( " " " trying to construct normal instance PS name\n" )); goto construct_instance_name; } /* after the prefix we have character `-' followed by the */ /* subfamily name (using only characters a-z, A-Z, and 0-9) */ - if ( FT_ALLOC( result, face->var_postscript_prefix_len + - 1 + ft_strlen( subfamily_name ) + 1 ) ) + if ( FT_QALLOC( result, face->var_postscript_prefix_len + + 1 + ft_strlen( subfamily_name ) + 1 ) ) return NULL; ft_strcpy( result, face->var_postscript_prefix ); @@ -957,9 +978,9 @@ construct_instance_name: axis = mm_var->axis; - if ( FT_ALLOC( result, - face->var_postscript_prefix_len + - num_coords * MAX_VALUE_DESCRIPTOR_LEN + 1 ) ) + if ( FT_QALLOC( result, + face->var_postscript_prefix_len + + num_coords * MAX_VALUE_DESCRIPTOR_LEN + 1 ) ) return NULL; p = result; @@ -993,6 +1014,7 @@ if ( t != ' ' && ft_isalnum( t ) ) *p++ = t; } + *p++ = '\0'; } check_length: @@ -1040,47 +1062,49 @@ #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ - static const char* - sfnt_get_ps_name( TT_Face face ) + FT_CALLBACK_DEF( const char* ) + sfnt_get_ps_name( FT_Face face ) /* TT_Face */ { + TT_Face ttface = (TT_Face)face; + FT_Int found, win, apple; const char* result = NULL; - if ( face->postscript_name ) - return face->postscript_name; + if ( ttface->postscript_name ) + return ttface->postscript_name; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( face->blend && - ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || - FT_IS_VARIATION( FT_FACE( face ) ) ) ) + if ( ttface->blend && + ( FT_IS_NAMED_INSTANCE( face ) || + FT_IS_VARIATION( face ) ) ) { - face->postscript_name = sfnt_get_var_ps_name( face ); - return face->postscript_name; + ttface->postscript_name = sfnt_get_var_ps_name( ttface ); + return ttface->postscript_name; } #endif /* scan the name table to see whether we have a Postscript name here, */ /* either in Macintosh or Windows platform encodings */ - found = sfnt_get_name_id( face, TT_NAME_ID_PS_NAME, &win, &apple ); + found = sfnt_get_name_id( ttface, TT_NAME_ID_PS_NAME, &win, &apple ); if ( !found ) return NULL; /* prefer Windows entries over Apple */ if ( win != -1 ) - result = get_win_string( face->root.memory, - face->name_table.stream, - face->name_table.names + win, + result = get_win_string( FT_FACE_MEMORY( face ), + ttface->name_table.stream, + ttface->name_table.names + win, sfnt_is_postscript, 1 ); if ( !result && apple != -1 ) - result = get_apple_string( face->root.memory, - face->name_table.stream, - face->name_table.names + apple, + result = get_apple_string( FT_FACE_MEMORY( face ), + ttface->name_table.stream, + ttface->name_table.names + apple, sfnt_is_postscript, 1 ); - face->postscript_name = result; + ttface->postscript_name = result; return result; } @@ -1089,7 +1113,7 @@ FT_DEFINE_SERVICE_PSFONTNAMEREC( sfnt_service_ps_name, - (FT_PsName_GetFunc)sfnt_get_ps_name /* get_ps_font_name */ + sfnt_get_ps_name /* FT_PsName_GetFunc get_ps_font_name */ ) @@ -1099,14 +1123,14 @@ FT_DEFINE_SERVICE_TTCMAPSREC( tt_service_get_cmap_info, - (TT_CMap_Info_GetFunc)tt_get_cmap_info /* get_cmap_info */ + tt_get_cmap_info /* TT_CMap_Info_GetFunc get_cmap_info */ ) #ifdef TT_CONFIG_OPTION_BDF static FT_Error - sfnt_get_charset_id( TT_Face face, + sfnt_get_charset_id( FT_Face face, const char* *acharset_encoding, const char* *acharset_registry ) { @@ -1144,8 +1168,8 @@ FT_DEFINE_SERVICE_BDFRec( sfnt_service_bdf, - (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id, /* get_charset_id */ - (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop /* get_property */ + sfnt_get_charset_id, /* FT_BDF_GetCharsetIdFunc get_charset_id */ + tt_face_find_bdf_prop /* FT_BDF_GetPropertyFunc get_property */ ) @@ -1213,6 +1237,14 @@ #define PUT_COLOR_LAYERS( a ) NULL #endif +#ifdef FT_CONFIG_OPTION_SVG +#define PUT_SVG_SUPPORT( a ) a +#else +#define PUT_SVG_SUPPORT( a ) NULL +#endif + +#define PUT_COLOR_LAYERS_V1( a ) PUT_COLOR_LAYERS( a ) + #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES #define PUT_PS_NAMES( a ) a #else @@ -1271,9 +1303,9 @@ /* TT_Free_Table_Func free_eblc */ PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike ), - /* TT_Set_SBit_Strike_Func set_sbit_strike */ + /* TT_Set_SBit_Strike_Func set_sbit_strike */ PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ), - /* TT_Load_Strike_Metrics_Func load_strike_metrics */ + /* TT_Load_Strike_Metrics_Func load_strike_metrics */ PUT_COLOR_LAYERS( tt_face_load_cpal ), /* TT_Load_Table_Func load_cpal */ @@ -1287,13 +1319,32 @@ /* TT_Set_Palette_Func set_palette */ PUT_COLOR_LAYERS( tt_face_get_colr_layer ), /* TT_Get_Colr_Layer_Func get_colr_layer */ + + PUT_COLOR_LAYERS_V1( tt_face_get_colr_glyph_paint ), + /* TT_Get_Color_Glyph_Paint_Func get_colr_glyph_paint */ + PUT_COLOR_LAYERS_V1( tt_face_get_color_glyph_clipbox ), + /* TT_Get_Color_Glyph_ClipBox_Func get_clipbox */ + PUT_COLOR_LAYERS_V1( tt_face_get_paint_layers ), + /* TT_Get_Paint_Layers_Func get_paint_layers */ + PUT_COLOR_LAYERS_V1( tt_face_get_colorline_stops ), + /* TT_Get_Paint get_paint */ + PUT_COLOR_LAYERS_V1( tt_face_get_paint ), + /* TT_Get_Colorline_Stops_Func get_colorline_stops */ + PUT_COLOR_LAYERS( tt_face_colr_blend_layer ), /* TT_Blend_Colr_Func colr_blend */ tt_face_get_metrics, /* TT_Get_Metrics_Func get_metrics */ tt_face_get_name, /* TT_Get_Name_Func get_name */ - sfnt_get_name_id /* TT_Get_Name_ID_Func get_name_id */ + sfnt_get_name_id, /* TT_Get_Name_ID_Func get_name_id */ + + PUT_SVG_SUPPORT( tt_face_load_svg ), + /* TT_Load_Table_Func load_svg */ + PUT_SVG_SUPPORT( tt_face_free_svg ), + /* TT_Free_Table_Func free_svg */ + PUT_SVG_SUPPORT( tt_face_load_svg_doc ) + /* TT_Load_Svg_Doc_Func load_svg_doc */ ) @@ -1309,9 +1360,9 @@ (const void*)&sfnt_interface, /* module specific interface */ - (FT_Module_Constructor)NULL, /* module_init */ - (FT_Module_Destructor) NULL, /* module_done */ - (FT_Module_Requester) sfnt_get_interface /* get_interface */ + NULL, /* FT_Module_Constructor module_init */ + NULL, /* FT_Module_Destructor module_done */ + sfnt_get_interface /* FT_Module_Requester get_interface */ ) diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/sfdriver.h b/lib/libesp32_lvgl/freetype/src/sfnt/sfdriver.h index 1ac270632..2445958b6 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/sfdriver.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/sfdriver.h @@ -4,7 +4,7 @@ * * High-level SFNT driver interface (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/sferrors.h b/lib/libesp32_lvgl/freetype/src/sfnt/sferrors.h index 55c3e76b6..e7a8eb04b 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/sferrors.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/sferrors.h @@ -4,7 +4,7 @@ * * SFNT error codes (specification only). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/sfnt.c b/lib/libesp32_lvgl/freetype/src/sfnt/sfnt.c index 471239ff0..8e4f08a90 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/sfnt.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/sfnt.c @@ -4,7 +4,7 @@ * * Single object library component. * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -27,6 +27,7 @@ #include "ttcmap.c" #include "ttcolr.c" #include "ttcpal.c" +#include "ttsvg.c" #include "ttkern.c" #include "ttload.c" diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/sfobjs.c b/lib/libesp32_lvgl/freetype/src/sfnt/sfobjs.c index 39460be2e..f5d66ef84 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/sfobjs.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/sfobjs.c @@ -4,7 +4,7 @@ * * SFNT object management (base). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -65,7 +65,7 @@ len = (FT_UInt)entry->stringLength / 2; - if ( FT_NEW_ARRAY( string, len + 1 ) ) + if ( FT_QNEW_ARRAY( string, len + 1 ) ) return NULL; for ( n = 0; n < len; n++ ) @@ -100,7 +100,7 @@ len = (FT_UInt)entry->stringLength; - if ( FT_NEW_ARRAY( string, len + 1 ) ) + if ( FT_QNEW_ARRAY( string, len + 1 ) ) return NULL; for ( n = 0; n < len; n++ ) @@ -360,17 +360,27 @@ FT_FRAME_END }; +#ifndef FT_CONFIG_OPTION_USE_BROTLI + FT_UNUSED( face_instance_index ); + FT_UNUSED( woff2_num_faces ); +#endif + face->ttc_header.tag = 0; face->ttc_header.version = 0; face->ttc_header.count = 0; +#if defined( FT_CONFIG_OPTION_USE_ZLIB ) || \ + defined( FT_CONFIG_OPTION_USE_BROTLI ) retry: +#endif + offset = FT_STREAM_POS(); if ( FT_READ_ULONG( tag ) ) return error; +#ifdef FT_CONFIG_OPTION_USE_ZLIB if ( tag == TTAG_wOFF ) { FT_TRACE2(( "sfnt_open_font: file is a WOFF; synthesizing SFNT\n" )); @@ -386,7 +396,9 @@ stream = face->root.stream; goto retry; } +#endif +#ifdef FT_CONFIG_OPTION_USE_BROTLI if ( tag == TTAG_wOF2 ) { FT_TRACE2(( "sfnt_open_font: file is a WOFF2; synthesizing SFNT\n" )); @@ -405,6 +417,7 @@ stream = face->root.stream; goto retry; } +#endif if ( tag != 0x00010000UL && tag != TTAG_ttcf && @@ -446,7 +459,7 @@ return FT_THROW( Array_Too_Large ); /* now read the offsets of each font in the file */ - if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ) + if ( FT_QNEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ) return error; if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) ) @@ -464,7 +477,7 @@ face->ttc_header.version = 1 << 16; face->ttc_header.count = 1; - if ( FT_NEW( face->ttc_header.offsets ) ) + if ( FT_QNEW( face->ttc_header.offsets ) ) return error; face->ttc_header.offsets[0] = offset; @@ -521,17 +534,23 @@ 0 ); } - if ( !face->var ) + if ( !face->tt_var ) { /* we want the metrics variations interface */ /* from the `truetype' module only */ FT_Module tt_module = FT_Get_Module( library, "truetype" ); - face->var = ft_module_get_service( tt_module, - FT_SERVICE_ID_METRICS_VARIATIONS, - 0 ); + face->tt_var = ft_module_get_service( tt_module, + FT_SERVICE_ID_METRICS_VARIATIONS, + 0 ); } + + if ( !face->face_var ) + face->face_var = ft_module_get_service( + &face->root.driver->root, + FT_SERVICE_ID_METRICS_VARIATIONS, + 0 ); #endif FT_TRACE2(( "SFNT driver\n" )); @@ -553,7 +572,7 @@ face_index = FT_ABS( face_instance_index ) & 0xFFFF; /* value -(N+1) requests information on index N */ - if ( face_instance_index < 0 ) + if ( face_instance_index < 0 && face_index > 0 ) face_index--; if ( face_index >= face->ttc_header.count ) @@ -643,8 +662,8 @@ */ if ( ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) && - !( FT_ALLOC( default_values, num_axes * 4 ) || - FT_ALLOC( instance_values, num_axes * 4 ) ) ) + !( FT_QALLOC( default_values, num_axes * 4 ) || + FT_QALLOC( instance_values, num_axes * 4 ) ) ) { /* the current stream position is 16 bytes after the table start */ FT_ULong array_start = FT_STREAM_POS() - 16 + offset; @@ -679,6 +698,9 @@ instance_offset += instance_size; } + /* named instance indices start with value 1 */ + face->var_default_named_instance = i + 1; + if ( i == num_instances ) { /* no default instance in named instance table; */ @@ -771,17 +793,23 @@ FT_Int num_params, FT_Parameter* params ) { - FT_Error error; + FT_Error error; #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES - FT_Error psnames_error; + FT_Error psnames_error; #endif - FT_Bool has_outline; - FT_Bool is_apple_sbit; - FT_Bool is_apple_sbix; - FT_Bool has_CBLC; - FT_Bool has_CBDT; - FT_Bool ignore_typographic_family = FALSE; - FT_Bool ignore_typographic_subfamily = FALSE; + + FT_Bool has_outline; + FT_Bool is_apple_sbit; + + FT_Bool has_CBLC; + FT_Bool has_CBDT; + FT_Bool has_EBLC; + FT_Bool has_bloc; + FT_Bool has_sbix; + + FT_Bool ignore_typographic_family = FALSE; + FT_Bool ignore_typographic_subfamily = FALSE; + FT_Bool ignore_sbix = FALSE; SFNT_Service sfnt = (SFNT_Service)face->sfnt; @@ -800,6 +828,8 @@ ignore_typographic_family = TRUE; else if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY ) ignore_typographic_subfamily = TRUE; + else if ( params[i].tag == FT_PARAM_TAG_IGNORE_SBIX ) + ignore_sbix = TRUE; } } @@ -820,7 +850,8 @@ /* it doesn't contain outlines. */ /* */ - FT_TRACE2(( "sfnt_load_face: %p\n\n", (void *)face )); + FT_TRACE2(( "sfnt_load_face: %p\n", (void *)face )); + FT_TRACE2(( "\n" )); /* do we have outlines in there? */ #ifdef FT_CONFIG_OPTION_INCREMENTAL @@ -834,14 +865,17 @@ tt_face_lookup_table( face, TTAG_CFF2 ) ); #endif - is_apple_sbit = 0; - is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 ); + /* check which sbit formats are present */ + has_CBLC = !face->goto_table( face, TTAG_CBLC, stream, 0 ); + has_CBDT = !face->goto_table( face, TTAG_CBDT, stream, 0 ); + has_EBLC = !face->goto_table( face, TTAG_EBLC, stream, 0 ); + has_bloc = !face->goto_table( face, TTAG_bloc, stream, 0 ); + has_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 ); - /* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf' - * outline rendered on top. We don't support that yet, so just ignore - * the 'glyf' outline and advertise it as a bitmap-only font. */ - if ( is_apple_sbix ) - has_outline = FALSE; + is_apple_sbit = FALSE; + + if ( ignore_sbix ) + has_sbix = FALSE; /* if this font doesn't contain outlines, we try to load */ /* a `bhed' table */ @@ -853,16 +887,13 @@ /* load the font header (`head' table) if this isn't an Apple */ /* sbit font file */ - if ( !is_apple_sbit || is_apple_sbix ) + if ( !is_apple_sbit || has_sbix ) { LOAD_( head ); if ( error ) goto Exit; } - has_CBLC = !face->goto_table( face, TTAG_CBLC, stream, 0 ); - has_CBDT = !face->goto_table( face, TTAG_CBDT, stream, 0 ); - /* Ignore outlines for CBLC/CBDT fonts. */ if ( has_CBLC || has_CBDT ) has_outline = FALSE; @@ -972,7 +1003,11 @@ /* the optional tables */ /* embedded bitmap support */ - if ( sfnt->load_eblc ) + /* TODO: Replace this clumsy check for all possible sbit tables */ + /* with something better (for example, by passing a parameter */ + /* to suppress 'sbix' loading). */ + if ( sfnt->load_eblc && + ( has_CBLC || has_EBLC || has_bloc || has_sbix ) ) LOAD_( eblc ); /* colored glyph support */ @@ -982,6 +1017,10 @@ LOAD_( colr ); } + /* OpenType-SVG glyph support */ + if ( sfnt->load_svg ) + LOAD_( svg ); + /* consider the pclt, kerning, and gasp tables as optional */ LOAD_( pclt ); LOAD_( gasp ); @@ -1024,6 +1063,16 @@ GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); } +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + { + FT_Memory memory = face->root.memory; + + + if ( FT_STRDUP( face->non_var_style_name, face->root.style_name ) ) + goto Exit; + } +#endif + /* now set up root fields */ { FT_Face root = &face->root; @@ -1036,11 +1085,19 @@ */ if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC || face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX || - face->colr ) + face->colr || + face->svg ) flags |= FT_FACE_FLAG_COLOR; /* color glyphs */ if ( has_outline == TRUE ) - flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ + { + /* by default (and for backward compatibility) we handle */ + /* fonts with an 'sbix' table as bitmap-only */ + if ( has_sbix ) + flags |= FT_FACE_FLAG_SBIX; /* with 'sbix' bitmaps */ + else + flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ + } /* The sfnt driver only supports bitmap fonts natively, thus we */ /* don't set FT_FACE_FLAG_HINTER. */ @@ -1069,13 +1126,7 @@ /* Don't bother to load the tables unless somebody asks for them. */ /* No need to do work which will (probably) not be used. */ if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) - { - if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 && - tt_face_lookup_table( face, TTAG_gvar ) != 0 ) - flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; - if ( tt_face_lookup_table( face, TTAG_CFF2 ) != 0 ) - flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; - } + flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; #endif root->face_flags = flags; @@ -1149,9 +1200,10 @@ } /* synthesize Unicode charmap if one is missing */ - if ( !has_unicode ) + if ( !has_unicode && + root->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) { - FT_CharMapRec cmaprec; + FT_CharMapRec cmaprec; cmaprec.face = root; @@ -1188,7 +1240,7 @@ if ( count > 0 ) { - FT_Memory memory = face->root.stream->memory; + FT_Memory memory = face->root.memory; FT_UShort em_size = face->header.Units_Per_EM; FT_Short avgwidth = face->os2.xAvgCharWidth; FT_Size_Metrics metrics; @@ -1207,7 +1259,7 @@ /* of `FT_Face', we map `available_sizes' indices to strike */ /* indices */ if ( FT_NEW_ARRAY( root->available_sizes, count ) || - FT_NEW_ARRAY( sbit_strike_map, count ) ) + FT_QNEW_ARRAY( sbit_strike_map, count ) ) goto Exit; bsize_idx = 0; @@ -1236,7 +1288,7 @@ } /* reduce array size to the actually used elements */ - (void)FT_RENEW_ARRAY( sbit_strike_map, count, bsize_idx ); + FT_MEM_QRENEW_ARRAY( sbit_strike_map, count, bsize_idx ); /* from now on, all strike indices are mapped */ /* using `sbit_strike_map' */ @@ -1262,7 +1314,8 @@ * * Set up metrics. */ - if ( FT_IS_SCALABLE( root ) ) + if ( FT_IS_SCALABLE( root ) || + FT_HAS_SBIX( root ) ) { /* XXX What about if outline header is missing */ /* (e.g. sfnt wrapped bitmap)? */ @@ -1401,6 +1454,12 @@ sfnt->free_cpal( face ); sfnt->free_colr( face ); } + +#ifdef FT_CONFIG_OPTION_SVG + /* free SVG data */ + if ( sfnt->free_svg ) + sfnt->free_svg( face ); +#endif } #ifdef TT_CONFIG_OPTION_BDF @@ -1460,6 +1519,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_FREE( face->var_postscript_prefix ); + FT_FREE( face->non_var_style_name ); #endif /* freeing glyph color palette data */ diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/sfobjs.h b/lib/libesp32_lvgl/freetype/src/sfnt/sfobjs.h index e8e304208..906aebbf9 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/sfobjs.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/sfobjs.h @@ -4,7 +4,7 @@ * * SFNT object management (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff.c b/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff.c index f0a32e1e0..7c0ce2205 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff.c @@ -4,7 +4,7 @@ * * WOFF format management (base). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -23,6 +23,9 @@ #include +#ifdef FT_CONFIG_OPTION_USE_ZLIB + + /************************************************************************** * * The macro FT_COMPONENT is used in trace mode. It is an implicit @@ -61,12 +64,11 @@ FT_FREE( stream->base ); stream->size = 0; - stream->base = NULL; stream->close = NULL; } - FT_CALLBACK_DEF( int ) + FT_COMPARE_DEF( int ) compare_offsets( const void* a, const void* b ) { @@ -109,7 +111,7 @@ FT_ULong sfnt_offset; FT_Int nn; - FT_ULong old_tag = 0; + FT_Tag old_tag = 0; static const FT_Frame_Field woff_header_fields[] = { @@ -160,8 +162,7 @@ } /* Don't trust `totalSfntSize' before thorough checks. */ - if ( FT_ALLOC( sfnt, 12 + woff.num_tables * 16UL ) || - FT_NEW( sfnt_stream ) ) + if ( FT_QALLOC( sfnt, 12 ) || FT_NEW( sfnt_stream ) ) goto Exit; sfnt_header = sfnt; @@ -194,13 +195,13 @@ /* tag value, the tables themselves are not. We thus have to */ /* sort them by offset and check that they don't overlap. */ - if ( FT_NEW_ARRAY( tables, woff.num_tables ) || - FT_NEW_ARRAY( indices, woff.num_tables ) ) + if ( FT_QNEW_ARRAY( tables, woff.num_tables ) || + FT_QNEW_ARRAY( indices, woff.num_tables ) ) goto Exit; - FT_TRACE2(( "\n" - " tag offset compLen origLen checksum\n" - " -------------------------------------------\n" )); + FT_TRACE2(( "\n" )); + FT_TRACE2(( " tag offset compLen origLen checksum\n" )); + FT_TRACE2(( " -------------------------------------------\n" )); if ( FT_FRAME_ENTER( 20L * woff.num_tables ) ) goto Exit; @@ -326,9 +327,7 @@ } /* Now use `totalSfntSize'. */ - if ( FT_REALLOC( sfnt, - 12 + woff.num_tables * 16UL, - woff.totalSfntSize ) ) + if ( FT_QREALLOC( sfnt, 12, woff.totalSfntSize ) ) goto Exit; sfnt_header = sfnt + 12; @@ -360,8 +359,6 @@ } else { -#ifdef FT_CONFIG_OPTION_USE_ZLIB - /* Uncompress with zlib. */ FT_ULong output_len = table->OrigLength; @@ -377,13 +374,6 @@ error = FT_THROW( Invalid_Table ); goto Exit1; } - -#else /* !FT_CONFIG_OPTION_USE_ZLIB */ - - error = FT_THROW( Unimplemented_Feature ); - goto Exit1; - -#endif /* !FT_CONFIG_OPTION_USE_ZLIB */ } FT_FRAME_EXIT(); @@ -433,5 +423,12 @@ #undef WRITE_USHORT #undef WRITE_ULONG +#else /* !FT_CONFIG_OPTION_USE_ZLIB */ + + /* ANSI C doesn't like empty source files */ + typedef int sfwoff_dummy_; + +#endif /* !FT_CONFIG_OPTION_USE_ZLIB */ + /* END */ diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff.h b/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff.h index d177ab116..d43842273 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff.h @@ -4,7 +4,7 @@ * * WOFFF format management (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -26,12 +26,15 @@ FT_BEGIN_HEADER +#ifdef FT_CONFIG_OPTION_USE_ZLIB FT_LOCAL( FT_Error ) woff_open_font( FT_Stream stream, TT_Face face ); +#endif + FT_END_HEADER #endif /* SFWOFF_H_ */ diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff2.c b/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff2.c index 5c8202f82..2be44a347 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff2.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff2.c @@ -4,7 +4,7 @@ * * WOFF2 format management (base). * - * Copyright (C) 2019-2020 by + * Copyright (C) 2019-2023 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -26,8 +26,6 @@ #include -#endif - /************************************************************************** * @@ -38,6 +36,8 @@ #undef FT_COMPONENT #define FT_COMPONENT sfwoff2 + /* An arbitrary, heuristic size limit (67MByte) for expanded WOFF2 data. */ +#define MAX_SFNT_SIZE ( 1 << 26 ) #define READ_255USHORT( var ) FT_SET_ERROR( Read255UShort( stream, &var ) ) @@ -86,6 +86,8 @@ #define BBOX_STREAM 5 #define INSTRUCTION_STREAM 6 +#define HAVE_OVERLAP_SIMPLE_BITMAP 0x1 + static void stream_close( FT_Stream stream ) @@ -96,20 +98,19 @@ FT_FREE( stream->base ); stream->size = 0; - stream->base = NULL; stream->close = NULL; } - FT_CALLBACK_DEF( int ) + FT_COMPARE_DEF( int ) compare_tags( const void* a, const void* b ) { WOFF2_Table table1 = *(WOFF2_Table*)a; WOFF2_Table table2 = *(WOFF2_Table*)b; - FT_ULong tag1 = table1->Tag; - FT_ULong tag2 = table2->Tag; + FT_Tag tag1 = table1->Tag; + FT_Tag tag2 = table2->Tag; if ( tag1 > tag2 ) @@ -230,9 +231,9 @@ { FT_TRACE6(( "Reallocating %lu to %lu.\n", *dst_size, (*offset + size) )); - if ( FT_REALLOC( dst, - (FT_ULong)( *dst_size ), - (FT_ULong)( *offset + size ) ) ) + if ( FT_QREALLOC( dst, + (FT_ULong)( *dst_size ), + (FT_ULong)( *offset + size ) ) ) goto Exit; *dst_size = *offset + size; @@ -316,8 +317,6 @@ const FT_Byte* src, FT_ULong src_size ) { -#ifdef FT_CONFIG_OPTION_USE_BROTLI - /* this cast is only of importance on 32bit systems; */ /* we don't validate it */ FT_Offset uncompressed_size = (FT_Offset)dst_size; @@ -338,20 +337,13 @@ FT_TRACE2(( "woff2_decompress: Brotli stream decompressed.\n" )); return FT_Err_Ok; - -#else /* !FT_CONFIG_OPTION_USE_BROTLI */ - - FT_ERROR(( "woff2_decompress: Brotli support not available.\n" )); - return FT_THROW( Unimplemented_Feature ); - -#endif /* !FT_CONFIG_OPTION_USE_BROTLI */ } static WOFF2_Table find_table( WOFF2_Table* tables, FT_UShort num_tables, - FT_ULong tag ) + FT_Tag tag ) { FT_Int i; @@ -534,6 +526,7 @@ const WOFF2_Point points, FT_UShort n_contours, FT_UShort instruction_len, + FT_Bool have_overlap, FT_Byte* dst, FT_ULong dst_size, FT_ULong* glyph_size ) @@ -561,6 +554,9 @@ FT_Int dy = point.y - last_y; + if ( i == 0 && have_overlap ) + flag |= GLYF_OVERLAP_SIMPLE; + if ( dx == 0 ) flag |= GLYF_THIS_X_IS_SAME; else if ( dx > -256 && dx < 256 ) @@ -790,7 +786,7 @@ goto Fail; loca_buf_size = loca_values_size * offset_size; - if ( FT_NEW_ARRAY( loca_buf, loca_buf_size ) ) + if ( FT_QALLOC( loca_buf, loca_buf_size ) ) goto Fail; dst = loca_buf; @@ -845,15 +841,18 @@ FT_UInt num_substreams = 7; + FT_UShort option_flags; FT_UShort num_glyphs; FT_UShort index_format; FT_ULong expected_loca_length; FT_UInt offset; FT_UInt i; FT_ULong points_size; - FT_ULong bitmap_length; FT_ULong glyph_buf_size; FT_ULong bbox_bitmap_offset; + FT_ULong bbox_bitmap_length; + FT_ULong overlap_bitmap_offset = 0; + FT_ULong overlap_bitmap_length = 0; const FT_ULong glyf_start = *out_offset; FT_ULong dest_offset = *out_offset; @@ -866,18 +865,20 @@ WOFF2_Point points = NULL; - if ( FT_NEW_ARRAY( substreams, num_substreams ) ) + if ( FT_QNEW_ARRAY( substreams, num_substreams ) ) goto Fail; - if ( FT_STREAM_SKIP( 4 ) ) + if ( FT_STREAM_SKIP( 2 ) ) + goto Fail; + if ( FT_READ_USHORT( option_flags ) ) goto Fail; if ( FT_READ_USHORT( num_glyphs ) ) goto Fail; if ( FT_READ_USHORT( index_format ) ) goto Fail; - FT_TRACE4(( "num_glyphs = %u; index_format = %u\n", - num_glyphs, index_format )); + FT_TRACE4(( "option_flags = %u; num_glyphs = %u; index_format = %u\n", + option_flags, num_glyphs, index_format )); info->num_glyphs = num_glyphs; @@ -890,7 +891,7 @@ if ( info->loca_table->dst_length != expected_loca_length ) goto Fail; - offset = ( 2 + num_substreams ) * 4; + offset = 2 + 2 + 2 + 2 + ( num_substreams * 4 ); if ( offset > info->glyf_table->TransformLength ) goto Fail; @@ -913,21 +914,36 @@ offset += substream_size; } - if ( FT_NEW_ARRAY( loca_values, num_glyphs + 1 ) ) + if ( option_flags & HAVE_OVERLAP_SIMPLE_BITMAP ) + { + /* Size of overlapBitmap = floor((numGlyphs + 7) / 8) */ + overlap_bitmap_length = ( num_glyphs + 7U ) >> 3; + if ( overlap_bitmap_length > info->glyf_table->TransformLength - offset ) + goto Fail; + + overlap_bitmap_offset = pos + offset; + + FT_TRACE5(( " Overlap bitmap: offset = %lu; size = %lu;\n", + overlap_bitmap_offset, overlap_bitmap_length )); + offset += overlap_bitmap_length; + } + + if ( FT_QNEW_ARRAY( loca_values, num_glyphs + 1 ) ) goto Fail; points_size = 0; bbox_bitmap_offset = substreams[BBOX_STREAM].offset; /* Size of bboxBitmap = 4 * floor((numGlyphs + 31) / 32) */ - bitmap_length = ( ( num_glyphs + 31U ) >> 5 ) << 2; - substreams[BBOX_STREAM].offset += bitmap_length; + bbox_bitmap_length = ( ( num_glyphs + 31U ) >> 5 ) << 2; + /* bboxStreamSize is the combined size of bboxBitmap and bboxStream. */ + substreams[BBOX_STREAM].offset += bbox_bitmap_length; glyph_buf_size = WOFF2_DEFAULT_GLYPH_BUF; - if ( FT_NEW_ARRAY( glyph_buf, glyph_buf_size ) ) + if ( FT_QALLOC( glyph_buf, glyph_buf_size ) ) goto Fail; - if ( FT_NEW_ARRAY( info->x_mins, num_glyphs ) ) + if ( FT_QNEW_ARRAY( info->x_mins, num_glyphs ) ) goto Fail; for ( i = 0; i < num_glyphs; ++i ) @@ -959,7 +975,7 @@ /* composite glyph */ FT_Bool have_instructions = FALSE; FT_UShort instruction_size = 0; - FT_ULong composite_size; + FT_ULong composite_size = 0; FT_ULong size_needed; FT_Byte* pointer = NULL; @@ -985,7 +1001,7 @@ size_needed = 12 + composite_size + instruction_size; if ( glyph_buf_size < size_needed ) { - if ( FT_RENEW_ARRAY( glyph_buf, glyph_buf_size, size_needed ) ) + if ( FT_QREALLOC( glyph_buf, glyph_buf_size, size_needed ) ) goto Fail; glyph_buf_size = size_needed; } @@ -1037,8 +1053,11 @@ FT_ULong flag_size; FT_ULong triplet_size; FT_ULong triplet_bytes_used; - FT_Byte* flags_buf = NULL; - FT_Byte* triplet_buf = NULL; + FT_Bool have_overlap = FALSE; + FT_Byte overlap_bitmap; + FT_ULong overlap_offset; + FT_Byte* flags_buf = NULL; + FT_Byte* triplet_buf = NULL; FT_UShort instruction_size; FT_ULong size_needed; FT_Int end_point; @@ -1047,7 +1066,18 @@ FT_Byte* pointer = NULL; - if ( FT_NEW_ARRAY( n_points_arr, n_contours ) ) + /* Set `have_overlap`. */ + if ( overlap_bitmap_offset ) + { + overlap_offset = overlap_bitmap_offset + ( i >> 3 ); + if ( FT_STREAM_SEEK( overlap_offset ) || + FT_READ_BYTE( overlap_bitmap ) ) + goto Fail; + if ( overlap_bitmap & ( 0x80 >> ( i & 7 ) ) ) + have_overlap = TRUE; + } + + if ( FT_QNEW_ARRAY( n_points_arr, n_contours ) ) goto Fail; if ( FT_STREAM_SEEK( substreams[N_POINTS_STREAM].offset ) ) @@ -1084,7 +1114,7 @@ /* Create array to store point information. */ points_size = total_n_points; - if ( FT_NEW_ARRAY( points, points_size ) ) + if ( FT_QNEW_ARRAY( points, points_size ) ) goto Fail; if ( triplet_decode( flags_buf, @@ -1113,7 +1143,7 @@ instruction_size; if ( glyph_buf_size < size_needed ) { - if ( FT_RENEW_ARRAY( glyph_buf, glyph_buf_size, size_needed ) ) + if ( FT_QREALLOC( glyph_buf, glyph_buf_size, size_needed ) ) goto Fail; glyph_buf_size = size_needed; } @@ -1167,6 +1197,7 @@ points, n_contours, instruction_size, + have_overlap, glyph_buf, glyph_buf_size, &glyph_size ) ) @@ -1197,8 +1228,7 @@ *glyf_checksum += compute_ULong_sum( glyph_buf, glyph_size ); /* Store x_mins, may be required to reconstruct `hmtx'. */ - if ( n_contours > 0 ) - info->x_mins[i] = (FT_Short)x_min; + info->x_mins[i] = (FT_Short)x_min; } info->glyf_table->dst_length = dest_offset - info->glyf_table->dst_offset; @@ -1315,7 +1345,7 @@ offset_size = index_format ? 4 : 2; /* Create `x_mins' array. */ - if ( FT_NEW_ARRAY( info->x_mins, num_glyphs ) ) + if ( FT_QNEW_ARRAY( info->x_mins, num_glyphs ) ) return error; loca_offset = info->loca_table->src_offset; @@ -1403,8 +1433,8 @@ if ( num_hmetrics < 1 ) goto Fail; - if ( FT_NEW_ARRAY( advance_widths, num_hmetrics ) || - FT_NEW_ARRAY( lsbs, num_glyphs ) ) + if ( FT_QNEW_ARRAY( advance_widths, num_hmetrics ) || + FT_QNEW_ARRAY( lsbs, num_glyphs ) ) goto Fail; /* Read `advanceWidth' stream. Always present. */ @@ -1455,7 +1485,7 @@ /* Build the hmtx table. */ hmtx_table_size = 2 * num_hmetrics + 2 * num_glyphs; - if ( FT_NEW_ARRAY( hmtx_table, hmtx_table_size ) ) + if ( FT_QALLOC( hmtx_table, hmtx_table_size ) ) goto Fail; dst = hmtx_table; @@ -1512,10 +1542,10 @@ { /* Memory management of `transformed_buf' is handled by the caller. */ - FT_Error error = FT_Err_Ok; - FT_Stream stream = NULL; - FT_Byte* buf_cursor = NULL; - FT_Byte* table_entry = NULL; + FT_Error error = FT_Err_Ok; + FT_Stream stream = NULL; + FT_Byte* buf_cursor = NULL; + FT_Byte table_entry[16]; /* We are reallocating memory for `sfnt', so its pointer may change. */ FT_Byte* sfnt = *sfnt_bytes; @@ -1556,10 +1586,6 @@ } } - /* Create buffer for table entries. */ - if ( FT_NEW_ARRAY( table_entry, 16 ) ) - goto Fail; - /* Create a stream for the uncompressed buffer. */ if ( FT_NEW( stream ) ) goto Fail; @@ -1722,7 +1748,6 @@ /* Set pointer of sfnt stream to its correct value. */ *sfnt_bytes = sfnt; - FT_FREE( table_entry ); FT_Stream_Close( stream ); FT_FREE( stream ); @@ -1735,7 +1760,6 @@ /* Set pointer of sfnt stream to its correct value. */ *sfnt_bytes = sfnt; - FT_FREE( table_entry ); FT_Stream_Close( stream ); FT_FREE( stream ); @@ -1848,15 +1872,14 @@ woff2.ttc_fonts = NULL; /* Read table directory. */ - if ( FT_NEW_ARRAY( tables, woff2.num_tables ) || - FT_NEW_ARRAY( indices, woff2.num_tables ) ) + if ( FT_QNEW_ARRAY( tables, woff2.num_tables ) || + FT_QNEW_ARRAY( indices, woff2.num_tables ) ) goto Exit; - FT_TRACE2(( - "\n" - " tag flags transform origLen transformLen offset\n" - " -----------------------------------------------------------\n" )); - /* " XXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX" */ + FT_TRACE2(( "\n" )); + FT_TRACE2(( " tag flags transform origLen transformLen offset\n" )); + FT_TRACE2(( " -----------------------------------------------------------\n" )); + /* " XXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX" */ for ( nn = 0; nn < woff2.num_tables; nn++ ) { @@ -1921,10 +1944,11 @@ goto Exit; } + table->flags = flags; table->src_offset = src_offset; table->src_length = table->TransformLength; src_offset += table->TransformLength; - table->flags = flags; + table->dst_offset = 0; FT_TRACE2(( " %c%c%c%c %08d %08d %08ld %08ld %08ld\n", (FT_Char)( table->Tag >> 24 ), @@ -1982,6 +2006,7 @@ FT_TRACE4(( "Number of fonts in TTC: %d\n", woff2.num_fonts )); + /* pre-zero pointers within in case of failure */ if ( FT_NEW_ARRAY( woff2.ttc_fonts, woff2.num_fonts ) ) goto Exit; @@ -1995,7 +2020,7 @@ if ( FT_READ_ULONG( ttc_font->flavor ) ) goto Exit; - if ( FT_NEW_ARRAY( ttc_font->table_indices, ttc_font->num_tables ) ) + if ( FT_QNEW_ARRAY( ttc_font->table_indices, ttc_font->num_tables ) ) goto Exit; FT_TRACE5(( "Number of tables in font %d: %d\n", @@ -2076,7 +2101,7 @@ error = FT_THROW( Invalid_Table ); goto Exit; } - file_offset = ROUND4(woff2.metaOffset + woff2.metaLength); + file_offset = ROUND4( woff2.metaOffset + woff2.metaLength ); } if ( woff2.privOffset ) @@ -2086,7 +2111,7 @@ error = FT_THROW( Invalid_Table ); goto Exit; } - file_offset = ROUND4(woff2.privOffset + woff2.privLength); + file_offset = ROUND4( woff2.privOffset + woff2.privLength ); } if ( file_offset != ( ROUND4( woff2.length ) ) ) @@ -2098,7 +2123,7 @@ /* Validate requested face index. */ *num_faces = woff2.num_fonts; /* value -(N+1) requests information on index N */ - if ( *face_instance_index < 0 ) + if ( *face_instance_index < 0 && face_index > 0 ) face_index--; if ( face_index >= woff2.num_fonts ) @@ -2119,8 +2144,8 @@ /* Create a temporary array. */ - if ( FT_NEW_ARRAY( temp_indices, - ttc_font->num_tables ) ) + if ( FT_QNEW_ARRAY( temp_indices, + ttc_font->num_tables ) ) goto Exit; FT_TRACE4(( "Storing tables for TTC face index %d.\n", face_index )); @@ -2128,9 +2153,9 @@ temp_indices[nn] = indices[ttc_font->table_indices[nn]]; /* Resize array to required size. */ - if ( FT_RENEW_ARRAY( indices, - woff2.num_tables, - ttc_font->num_tables ) ) + if ( FT_QRENEW_ARRAY( indices, + woff2.num_tables, + ttc_font->num_tables ) ) goto Exit; for ( nn = 0; nn < ttc_font->num_tables; nn++ ) @@ -2157,9 +2182,8 @@ else sfnt_size = woff2.totalSfntSize; - /* Value 1<<26 = 67108864 is heuristic. */ - if (sfnt_size >= (1 << 26)) - sfnt_size = 1 << 26; + if ( sfnt_size >= MAX_SFNT_SIZE ) + sfnt_size = MAX_SFNT_SIZE; #ifdef FT_DEBUG_LEVEL_TRACE if ( sfnt_size != woff2.totalSfntSize ) @@ -2170,8 +2194,8 @@ } /* Write sfnt header. */ - if ( FT_ALLOC( sfnt, sfnt_size ) || - FT_NEW( sfnt_stream ) ) + if ( FT_QALLOC( sfnt, sfnt_size ) || + FT_NEW( sfnt_stream ) ) goto Exit; sfnt_header = sfnt; @@ -2209,22 +2233,46 @@ sizeof ( WOFF2_Table ), compare_tags ); + /* reject fonts that have multiple tables with the same tag */ + for ( nn = 1; nn < woff2.num_tables; nn++ ) + { + FT_Tag tag = indices[nn]->Tag; + + + if ( tag == indices[nn - 1]->Tag ) + { + FT_ERROR(( "woff2_open_font:" + " multiple tables with tag `%c%c%c%c'.\n", + (FT_Char)( tag >> 24 ), + (FT_Char)( tag >> 16 ), + (FT_Char)( tag >> 8 ), + (FT_Char)( tag ) )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + } + if ( woff2.uncompressed_size < 1 ) { error = FT_THROW( Invalid_Table ); goto Exit; } - if ( woff2.uncompressed_size > sfnt_size ) + /* We must not blindly trust `uncompressed_size` since its */ + /* value might be corrupted. If it is too large, reject the */ + /* font. In other words, we don't accept a WOFF2 font that */ + /* expands to something larger than MAX_SFNT_SIZE. If ever */ + /* necessary, this limit can be easily adjusted. */ + if ( woff2.uncompressed_size > MAX_SFNT_SIZE ) { - FT_ERROR(( "woff2_open_font: SFNT table lengths are too large.\n" )); - error = FT_THROW( Invalid_Table ); + FT_ERROR(( "Uncompressed font too large.\n" )); + error = FT_THROW( Array_Too_Large ); goto Exit; } /* Allocate memory for uncompressed table data. */ - if ( FT_ALLOC( uncompressed_buf, woff2.uncompressed_size ) || - FT_FRAME_ENTER( woff2.totalCompressedSize ) ) + if ( FT_QALLOC( uncompressed_buf, woff2.uncompressed_size ) || + FT_FRAME_ENTER( woff2.totalCompressedSize ) ) goto Exit; /* Uncompress the stream. */ @@ -2255,9 +2303,9 @@ { FT_TRACE5(( "Trimming sfnt stream from %lu to %lu.\n", sfnt_size, woff2.actual_sfnt_size )); - if ( FT_REALLOC( sfnt, - (FT_ULong)( sfnt_size ), - (FT_ULong)( woff2.actual_sfnt_size ) ) ) + if ( FT_QREALLOC( sfnt, + (FT_ULong)( sfnt_size ), + (FT_ULong)( woff2.actual_sfnt_size ) ) ) goto Exit; } @@ -2333,5 +2381,12 @@ #undef BBOX_STREAM #undef INSTRUCTION_STREAM +#else /* !FT_CONFIG_OPTION_USE_BROTLI */ + + /* ANSI C doesn't like empty source files */ + typedef int sfwoff2_dummy_; + +#endif /* !FT_CONFIG_OPTION_USE_BROTLI */ + /* END */ diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff2.h b/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff2.h index 798f66bd0..4901286ee 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff2.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/sfwoff2.h @@ -4,7 +4,7 @@ * * WOFFF2 format management (specification). * - * Copyright (C) 2019-2020 by + * Copyright (C) 2019-2023 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -26,6 +26,7 @@ FT_BEGIN_HEADER +#ifdef FT_CONFIG_OPTION_USE_BROTLI /* Leave the first byte open to store `flag_byte'. */ #define WOFF2_FLAGS_TRANSFORM 1 << 8 @@ -55,6 +56,7 @@ FT_BEGIN_HEADER #define GLYF_REPEAT 1 << 3 #define GLYF_THIS_X_IS_SAME 1 << 4 #define GLYF_THIS_Y_IS_SAME 1 << 5 +#define GLYF_OVERLAP_SIMPLE 1 << 6 /* Other constants */ #define CONTOUR_OFFSET_END_POINT 10 @@ -66,6 +68,7 @@ FT_BEGIN_HEADER FT_Int* face_index, FT_Long* num_faces ); +#endif /* FT_CONFIG_OPTION_USE_BROTLI */ FT_END_HEADER diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttbdf.c b/lib/libesp32_lvgl/freetype/src/sfnt/ttbdf.c index a287d3afc..536fa7467 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttbdf.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttbdf.c @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded BDF properties (body). * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -136,13 +136,14 @@ FT_LOCAL_DEF( FT_Error ) - tt_face_find_bdf_prop( TT_Face face, + tt_face_find_bdf_prop( FT_Face face, /* TT_Face */ const char* property_name, BDF_PropertyRec *aprop ) { - TT_BDF bdf = &face->bdf; - FT_Size size = FT_FACE( face )->size; - FT_Error error = FT_Err_Ok; + TT_Face ttface = (TT_Face)face; + TT_BDF bdf = &ttface->bdf; + FT_Size size = FT_FACE_SIZE( face ); + FT_Error error = FT_Err_Ok; FT_Byte* p; FT_UInt count; FT_Byte* strike; @@ -153,7 +154,7 @@ if ( bdf->loaded == 0 ) { - error = tt_face_load_bdf_props( face, FT_FACE( face )->stream ); + error = tt_face_load_bdf_props( ttface, FT_FACE_STREAM( face ) ); if ( error ) goto Exit; } @@ -248,7 +249,7 @@ #else /* !TT_CONFIG_OPTION_BDF */ /* ANSI C doesn't like empty source files */ - typedef int _tt_bdf_dummy; + typedef int tt_bdf_dummy_; #endif /* !TT_CONFIG_OPTION_BDF */ diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttbdf.h b/lib/libesp32_lvgl/freetype/src/sfnt/ttbdf.h index e60c01cb8..0d7a0acec 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttbdf.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttbdf.h @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded BDF properties (specification). * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -34,7 +34,7 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - tt_face_find_bdf_prop( TT_Face face, + tt_face_find_bdf_prop( FT_Face face, const char* property_name, BDF_PropertyRec *aprop ); diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttcmap.c b/lib/libesp32_lvgl/freetype/src/sfnt/ttcmap.c index 556a71219..9ba25dcbc 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttcmap.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttcmap.c @@ -4,7 +4,7 @@ * * TrueType character mapping table (cmap) support (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -59,10 +59,14 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap_init( TT_CMap cmap, - FT_Byte* table ) + tt_cmap_init( FT_CMap cmap, /* TT_CMap */ + void* table_ ) { - cmap->data = table; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = (FT_Byte*)table_; + + + ttcmap->data = table; return FT_Err_Ok; } @@ -128,21 +132,23 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap0_char_index( TT_CMap cmap, + tt_cmap0_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; return char_code < 256 ? table[6 + char_code] : 0; } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap0_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap0_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt32 charcode = *pchar_code; FT_UInt32 result = 0; FT_UInt gindex = 0; @@ -165,10 +171,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap0_get_info( TT_CMap cmap, + tt_cmap0_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 0; @@ -453,10 +460,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap2_char_index( TT_CMap cmap, + tt_cmap2_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* subheader; @@ -465,7 +473,7 @@ if ( subheader ) { FT_Byte* p = subheader; - FT_UInt idx = (FT_UInt)(char_code & 0xFF); + FT_UInt idx = (FT_UInt)( char_code & 0xFF ); FT_UInt start, count; FT_Int delta; FT_UInt offset; @@ -491,11 +499,12 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap2_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap2_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pcharcode ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt gindex = 0; FT_UInt32 result = 0; FT_UInt32 charcode = *pcharcode + 1; @@ -579,10 +588,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap2_get_info( TT_CMap cmap, + tt_cmap2_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 2; @@ -706,18 +716,20 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap4_init( TT_CMap4 cmap, - FT_Byte* table ) + tt_cmap4_init( FT_CMap cmap, /* TT_CMap4 */ + void* table_ ) { + TT_CMap4 ttcmap = (TT_CMap4)cmap; + FT_Byte* table = (FT_Byte*)table_; FT_Byte* p; - cmap->cmap.data = table; + ttcmap->cmap.data = table; - p = table + 6; - cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1; - cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; - cmap->cur_gindex = 0; + p = table + 6; + ttcmap->num_ranges = FT_PEEK_USHORT( p ) >> 1; + ttcmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; + ttcmap->cur_gindex = 0; return FT_Err_Ok; } @@ -755,7 +767,7 @@ cmap->cur_start == 0xFFFFU && cmap->cur_end == 0xFFFFU ) { - TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; @@ -788,15 +800,12 @@ static void tt_cmap4_next( TT_CMap4 cmap ) { - TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; FT_UInt charcode; - if ( cmap->cur_charcode >= 0xFFFFUL ) - goto Fail; - charcode = (FT_UInt)cmap->cur_charcode + 1; if ( charcode < cmap->cur_start ) @@ -882,7 +891,6 @@ charcode = cmap->cur_start; } - Fail: cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; cmap->cur_gindex = 0; } @@ -916,6 +924,16 @@ length = (FT_UInt)( valid->limit - table ); } + /* it also happens that the `length' field is too small; */ + /* this is easy to correct */ + if ( length < (FT_UInt)( valid->limit - table ) ) + { + if ( valid->level >= FT_VALIDATE_PARANOID ) + FT_INVALID_DATA; + + length = (FT_UInt)( valid->limit - table ); + } + if ( length < 16 ) FT_INVALID_TOO_SHORT; @@ -1087,32 +1105,26 @@ FT_UInt32* pcharcode, FT_Bool next ) { - TT_Face face = (TT_Face)cmap->cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; FT_UInt num_segs2, start, end, offset; FT_Int delta; FT_UInt i, num_segs; - FT_UInt32 charcode = *pcharcode; + FT_UInt32 charcode = *pcharcode + next; FT_UInt gindex = 0; FT_Byte* p; FT_Byte* q; p = cmap->data + 6; - num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); - - num_segs = num_segs2 >> 1; + num_segs = TT_PEEK_USHORT( p ) >> 1; if ( !num_segs ) return 0; - if ( next ) - charcode++; - - if ( charcode > 0xFFFFU ) - return 0; + num_segs2 = num_segs << 1; /* linear search */ p = cmap->data + 14; /* ends table */ @@ -1222,37 +1234,30 @@ FT_UInt32* pcharcode, FT_Bool next ) { - TT_Face face = (TT_Face)cmap->cmap.charmap.face; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); FT_Byte* limit = face->cmap_table + face->cmap_size; FT_UInt num_segs2, start, end, offset; FT_Int delta; FT_UInt max, min, mid, num_segs; - FT_UInt charcode = (FT_UInt)*pcharcode; + FT_UInt charcode = (FT_UInt)*pcharcode + next; FT_UInt gindex = 0; FT_Byte* p; p = cmap->data + 6; - num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); + num_segs = TT_PEEK_USHORT( p ) >> 1; - if ( !num_segs2 ) + if ( !num_segs ) return 0; - num_segs = num_segs2 >> 1; - - /* make compiler happy */ - mid = num_segs; - end = 0xFFFFU; - - if ( next ) - charcode++; + num_segs2 = num_segs << 1; min = 0; max = num_segs; /* binary search */ - while ( min < max ) + do { mid = ( min + max ) >> 1; p = cmap->data + 14 + mid * 2; @@ -1435,6 +1440,7 @@ break; } } + while ( min < max ); if ( next ) { @@ -1444,12 +1450,8 @@ /* if `charcode' is not in any segment, then `mid' is */ /* the segment nearest to `charcode' */ - if ( charcode > end ) - { - mid++; - if ( mid == num_segs ) - return 0; - } + if ( charcode > end && ++mid == num_segs ) + return 0; if ( tt_cmap4_set_range( cmap4, mid ) ) { @@ -1464,7 +1466,6 @@ cmap4->cur_gindex = gindex; else { - cmap4->cur_charcode = charcode; tt_cmap4_next( cmap4 ); gindex = cmap4->cur_gindex; } @@ -1479,31 +1480,35 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap4_char_index( TT_CMap cmap, + tt_cmap4_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { + TT_CMap ttcmap = (TT_CMap)cmap; + + if ( char_code >= 0x10000UL ) return 0; - if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) - return tt_cmap4_char_map_linear( cmap, &char_code, 0 ); + if ( ttcmap->flags & TT_CMAP_FLAG_UNSORTED ) + return tt_cmap4_char_map_linear( ttcmap, &char_code, 0 ); else - return tt_cmap4_char_map_binary( cmap, &char_code, 0 ); + return tt_cmap4_char_map_binary( ttcmap, &char_code, 0 ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap4_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap4_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { + TT_CMap ttcmap = (TT_CMap)cmap; FT_UInt gindex; if ( *pchar_code >= 0xFFFFU ) return 0; - if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) - gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 ); + if ( ttcmap->flags & TT_CMAP_FLAG_UNSORTED ) + gindex = tt_cmap4_char_map_linear( ttcmap, pchar_code, 1 ); else { TT_CMap4 cmap4 = (TT_CMap4)cmap; @@ -1518,7 +1523,7 @@ *pchar_code = cmap4->cur_charcode; } else - gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 ); + gindex = tt_cmap4_char_map_binary( ttcmap, pchar_code, 1 ); } return gindex; @@ -1526,10 +1531,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap4_get_info( TT_CMap cmap, + tt_cmap4_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 4; @@ -1630,10 +1636,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap6_char_index( TT_CMap cmap, + tt_cmap6_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* p = table + 6; FT_UInt start = TT_NEXT_USHORT( p ); @@ -1651,11 +1658,12 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap6_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap6_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt32 result = 0; FT_UInt32 char_code = *pchar_code + 1; FT_UInt gindex = 0; @@ -1696,10 +1704,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap6_get_info( TT_CMap cmap, + tt_cmap6_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 4; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 4; cmap_info->format = 6; @@ -1890,10 +1899,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap8_char_index( TT_CMap cmap, + tt_cmap8_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* p = table + 8204; FT_UInt32 num_groups = TT_NEXT_ULONG( p ); @@ -1922,15 +1932,16 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap8_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap8_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Face face = cmap->cmap.charmap.face; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); FT_UInt32 result = 0; FT_UInt32 char_code; FT_UInt gindex = 0; - FT_Byte* table = cmap->data; + FT_Byte* table = ttcmap->data; FT_Byte* p = table + 8204; FT_UInt32 num_groups = TT_NEXT_ULONG( p ); FT_UInt32 start, end, start_id; @@ -1990,10 +2001,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap8_get_info( TT_CMap cmap, + tt_cmap8_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 8; @@ -2094,10 +2106,11 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap10_char_index( TT_CMap cmap, + tt_cmap10_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt result = 0; FT_Byte* p = table + 12; FT_UInt32 start = TT_NEXT_ULONG( p ); @@ -2120,11 +2133,12 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap10_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap10_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { - FT_Byte* table = cmap->data; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* table = ttcmap->data; FT_UInt32 char_code; FT_UInt gindex = 0; FT_Byte* p = table + 12; @@ -2162,10 +2176,11 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap10_get_info( TT_CMap cmap, + tt_cmap10_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 10; @@ -2243,15 +2258,19 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap12_init( TT_CMap12 cmap, - FT_Byte* table ) + tt_cmap12_init( FT_CMap cmap, /* TT_CMap12 */ + void* table_ ) { - cmap->cmap.data = table; + TT_CMap12 ttcmap = (TT_CMap12)cmap; + FT_Byte* table = (FT_Byte*)table_; - table += 12; - cmap->num_groups = FT_PEEK_ULONG( table ); - cmap->valid = 0; + ttcmap->cmap.data = table; + + table += 12; + ttcmap->num_groups = FT_PEEK_ULONG( table ); + + ttcmap->valid = 0; return FT_Err_Ok; } @@ -2321,23 +2340,21 @@ /* cmap->cur_group should be set up properly by caller */ /* */ static void - tt_cmap12_next( TT_CMap12 cmap ) + tt_cmap12_next( FT_CMap cmap ) /* TT_CMap12 */ { - FT_Face face = cmap->cmap.cmap.charmap.face; - FT_Byte* p; - FT_ULong start, end, start_id, char_code; - FT_ULong n; - FT_UInt gindex; + TT_CMap12 ttcmap = (TT_CMap12)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Byte* p; + FT_ULong start, end, start_id, char_code; + FT_ULong n; + FT_UInt gindex; - if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) - goto Fail; + char_code = ttcmap->cur_charcode + 1; - char_code = cmap->cur_charcode + 1; - - for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) + for ( n = ttcmap->cur_group; n < ttcmap->num_groups; n++ ) { - p = cmap->cmap.data + 16 + 12 * n; + p = ttcmap->cmap.data + 16 + 12 * n; start = TT_NEXT_ULONG( p ); end = TT_NEXT_ULONG( p ); start_id = TT_PEEK_ULONG( p ); @@ -2369,16 +2386,16 @@ if ( gindex >= (FT_UInt)face->num_glyphs ) continue; - cmap->cur_charcode = char_code; - cmap->cur_gindex = gindex; - cmap->cur_group = n; + ttcmap->cur_charcode = char_code; + ttcmap->cur_gindex = gindex; + ttcmap->cur_group = n; return; } } Fail: - cmap->valid = 0; + ttcmap->valid = 0; } @@ -2390,7 +2407,7 @@ FT_UInt gindex = 0; FT_Byte* p = cmap->data + 12; FT_UInt32 num_groups = TT_PEEK_ULONG( p ); - FT_UInt32 char_code = *pchar_code; + FT_UInt32 char_code = *pchar_code + next; FT_UInt32 start, end, start_id; FT_UInt32 max, min, mid; @@ -2398,23 +2415,11 @@ if ( !num_groups ) return 0; - /* make compiler happy */ - mid = num_groups; - end = 0xFFFFFFFFUL; - - if ( next ) - { - if ( char_code >= 0xFFFFFFFFUL ) - return 0; - - char_code++; - } - min = 0; max = num_groups; /* binary search */ - while ( min < max ) + do { mid = ( min + max ) >> 1; p = cmap->data + 16 + 12 * mid; @@ -2438,22 +2443,19 @@ break; } } + while ( min < max ); if ( next ) { - FT_Face face = cmap->cmap.charmap.face; + FT_Face face = FT_CMAP_FACE( cmap ); TT_CMap12 cmap12 = (TT_CMap12)cmap; /* if `char_code' is not in any group, then `mid' is */ /* the group nearest to `char_code' */ - if ( char_code > end ) - { - mid++; - if ( mid == num_groups ) - return 0; - } + if ( char_code > end && ++mid == num_groups ) + return 0; cmap12->valid = 1; cmap12->cur_charcode = char_code; @@ -2464,7 +2466,7 @@ if ( !gindex ) { - tt_cmap12_next( cmap12 ); + tt_cmap12_next( FT_CMAP( cmap12 ) ); if ( cmap12->valid ) gindex = cmap12->cur_gindex; @@ -2480,25 +2482,28 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap12_char_index( TT_CMap cmap, + tt_cmap12_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - return tt_cmap12_char_map_binary( cmap, &char_code, 0 ); + return tt_cmap12_char_map_binary( (TT_CMap)cmap, &char_code, 0 ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap12_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap12_char_next( FT_CMap cmap, /* TT_CMap12 */ FT_UInt32 *pchar_code ) { TT_CMap12 cmap12 = (TT_CMap12)cmap; FT_UInt gindex; + if ( *pchar_code >= 0xFFFFFFFFUL ) + return 0; + /* no need to search */ if ( cmap12->valid && cmap12->cur_charcode == *pchar_code ) { - tt_cmap12_next( cmap12 ); + tt_cmap12_next( FT_CMAP( cmap12 ) ); if ( cmap12->valid ) { gindex = cmap12->cur_gindex; @@ -2508,17 +2513,18 @@ gindex = 0; } else - gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 ); + gindex = tt_cmap12_char_map_binary( (TT_CMap)cmap, pchar_code, 1 ); return gindex; } FT_CALLBACK_DEF( FT_Error ) - tt_cmap12_get_info( TT_CMap cmap, + tt_cmap12_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 12; @@ -2596,15 +2602,19 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap13_init( TT_CMap13 cmap, - FT_Byte* table ) + tt_cmap13_init( FT_CMap cmap, /* TT_CMap13 */ + void* table_ ) { - cmap->cmap.data = table; + TT_CMap13 ttcmap = (TT_CMap13)cmap; + FT_Byte* table = (FT_Byte*)table_; - table += 12; - cmap->num_groups = FT_PEEK_ULONG( table ); - cmap->valid = 0; + ttcmap->cmap.data = table; + + table += 12; + ttcmap->num_groups = FT_PEEK_ULONG( table ); + + ttcmap->valid = 0; return FT_Err_Ok; } @@ -2669,23 +2679,21 @@ /* cmap->cur_group should be set up properly by caller */ /* */ static void - tt_cmap13_next( TT_CMap13 cmap ) + tt_cmap13_next( FT_CMap cmap ) /* TT_CMap13 */ { - FT_Face face = cmap->cmap.cmap.charmap.face; - FT_Byte* p; - FT_ULong start, end, glyph_id, char_code; - FT_ULong n; - FT_UInt gindex; + TT_CMap13 ttcmap = (TT_CMap13)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Byte* p; + FT_ULong start, end, glyph_id, char_code; + FT_ULong n; + FT_UInt gindex; - if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) - goto Fail; + char_code = ttcmap->cur_charcode + 1; - char_code = cmap->cur_charcode + 1; - - for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) + for ( n = ttcmap->cur_group; n < ttcmap->num_groups; n++ ) { - p = cmap->cmap.data + 16 + 12 * n; + p = ttcmap->cmap.data + 16 + 12 * n; start = TT_NEXT_ULONG( p ); end = TT_NEXT_ULONG( p ); glyph_id = TT_PEEK_ULONG( p ); @@ -2699,17 +2707,16 @@ if ( gindex && gindex < (FT_UInt)face->num_glyphs ) { - cmap->cur_charcode = char_code; - cmap->cur_gindex = gindex; - cmap->cur_group = n; + ttcmap->cur_charcode = char_code; + ttcmap->cur_gindex = gindex; + ttcmap->cur_group = n; return; } } } - Fail: - cmap->valid = 0; + ttcmap->valid = 0; } @@ -2721,7 +2728,7 @@ FT_UInt gindex = 0; FT_Byte* p = cmap->data + 12; FT_UInt32 num_groups = TT_PEEK_ULONG( p ); - FT_UInt32 char_code = *pchar_code; + FT_UInt32 char_code = *pchar_code + next; FT_UInt32 start, end; FT_UInt32 max, min, mid; @@ -2729,23 +2736,11 @@ if ( !num_groups ) return 0; - /* make compiler happy */ - mid = num_groups; - end = 0xFFFFFFFFUL; - - if ( next ) - { - if ( char_code >= 0xFFFFFFFFUL ) - return 0; - - char_code++; - } - min = 0; max = num_groups; /* binary search */ - while ( min < max ) + do { mid = ( min + max ) >> 1; p = cmap->data + 16 + 12 * mid; @@ -2764,6 +2759,7 @@ break; } } + while ( min < max ); if ( next ) { @@ -2774,12 +2770,8 @@ /* if `char_code' is not in any group, then `mid' is */ /* the group nearest to `char_code' */ - if ( char_code > end ) - { - mid++; - if ( mid == num_groups ) - return 0; - } + if ( char_code > end && ++mid == num_groups ) + return 0; cmap13->valid = 1; cmap13->cur_charcode = char_code; @@ -2790,7 +2782,7 @@ if ( !gindex ) { - tt_cmap13_next( cmap13 ); + tt_cmap13_next( FT_CMAP( cmap13 ) ); if ( cmap13->valid ) gindex = cmap13->cur_gindex; @@ -2806,25 +2798,28 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap13_char_index( TT_CMap cmap, + tt_cmap13_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { - return tt_cmap13_char_map_binary( cmap, &char_code, 0 ); + return tt_cmap13_char_map_binary( (TT_CMap)cmap, &char_code, 0 ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap13_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap13_char_next( FT_CMap cmap, /* TT_CMap13 */ FT_UInt32 *pchar_code ) { TT_CMap13 cmap13 = (TT_CMap13)cmap; FT_UInt gindex; + if ( *pchar_code >= 0xFFFFFFFFUL ) + return 0; + /* no need to search */ if ( cmap13->valid && cmap13->cur_charcode == *pchar_code ) { - tt_cmap13_next( cmap13 ); + tt_cmap13_next( FT_CMAP( cmap13 ) ); if ( cmap13->valid ) { gindex = cmap13->cur_gindex; @@ -2834,17 +2829,18 @@ gindex = 0; } else - gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 ); + gindex = tt_cmap13_char_map_binary( (TT_CMap)cmap, pchar_code, 1 ); return gindex; } FT_CALLBACK_DEF( FT_Error ) - tt_cmap13_get_info( TT_CMap cmap, + tt_cmap13_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { - FT_Byte* p = cmap->data + 8; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = ttcmap->data + 8; cmap_info->format = 13; @@ -2959,14 +2955,15 @@ FT_CALLBACK_DEF( void ) - tt_cmap14_done( TT_CMap14 cmap ) + tt_cmap14_done( FT_CMap cmap ) /* TT_CMap14 */ { - FT_Memory memory = cmap->memory; + TT_CMap14 ttcmap = (TT_CMap14)cmap; + FT_Memory memory = ttcmap->memory; - cmap->max_results = 0; - if ( memory && cmap->results ) - FT_FREE( cmap->results ); + ttcmap->max_results = 0; + if ( memory && ttcmap->results ) + FT_FREE( ttcmap->results ); } @@ -2994,15 +2991,19 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap14_init( TT_CMap14 cmap, - FT_Byte* table ) + tt_cmap14_init( FT_CMap cmap, /* TT_CMap14 */ + void* table_ ) { - cmap->cmap.data = table; + TT_CMap14 ttcmap = (TT_CMap14)cmap; + FT_Byte* table = (FT_Byte*)table_; - table += 6; - cmap->num_selectors = FT_PEEK_ULONG( table ); - cmap->max_results = 0; - cmap->results = NULL; + + ttcmap->cmap.data = table; + + table += 6; + ttcmap->num_selectors = FT_PEEK_ULONG( table ); + ttcmap->max_results = 0; + ttcmap->results = NULL; return FT_Err_Ok; } @@ -3132,7 +3133,7 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap14_char_index( TT_CMap cmap, + tt_cmap14_char_index( FT_CMap cmap, FT_UInt32 char_code ) { FT_UNUSED( cmap ); @@ -3143,8 +3144,8 @@ } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap14_char_next( TT_CMap cmap, + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap14_char_next( FT_CMap cmap, FT_UInt32 *pchar_code ) { FT_UNUSED( cmap ); @@ -3156,7 +3157,7 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap14_get_info( TT_CMap cmap, + tt_cmap14_get_info( FT_CharMap cmap, TT_CMapInfo *cmap_info ) { FT_UNUSED( cmap ); @@ -3270,12 +3271,16 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap14_char_var_index( TT_CMap cmap, - TT_CMap ucmap, + tt_cmap14_char_var_index( FT_CMap cmap, /* TT_CMap */ + FT_CMap ucmap, /* TT_CMap */ FT_UInt32 charcode, FT_UInt32 variantSelector ) { - FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); + TT_CMap ttcmap = (TT_CMap)cmap; + TT_CMap ttucmap = (TT_CMap)ucmap; + + FT_Byte* p = tt_cmap14_find_variant( ttcmap->data + 6, + variantSelector ); FT_ULong defOff; FT_ULong nondefOff; @@ -3286,16 +3291,16 @@ defOff = TT_NEXT_ULONG( p ); nondefOff = TT_PEEK_ULONG( p ); - if ( defOff != 0 && - tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) + if ( defOff != 0 && + tt_cmap14_char_map_def_binary( ttcmap->data + defOff, charcode ) ) { /* This is the default variant of this charcode. GID not stored */ /* here; stored in the normal Unicode charmap instead. */ - return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode ); + return ttucmap->cmap.clazz->char_index( &ttucmap->cmap, charcode ); } if ( nondefOff != 0 ) - return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, + return tt_cmap14_char_map_nondef_binary( ttcmap->data + nondefOff, charcode ); return 0; @@ -3303,11 +3308,13 @@ FT_CALLBACK_DEF( FT_Int ) - tt_cmap14_char_var_isdefault( TT_CMap cmap, + tt_cmap14_char_var_isdefault( FT_CMap cmap, /* TT_CMap */ FT_UInt32 charcode, FT_UInt32 variantSelector ) { - FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte* p = tt_cmap14_find_variant( ttcmap->data + 6, + variantSelector ); FT_ULong defOff; FT_ULong nondefOff; @@ -3318,13 +3325,13 @@ defOff = TT_NEXT_ULONG( p ); nondefOff = TT_NEXT_ULONG( p ); - if ( defOff != 0 && - tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) + if ( defOff != 0 && + tt_cmap14_char_map_def_binary( ttcmap->data + defOff, charcode ) ) return 1; - if ( nondefOff != 0 && - tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, - charcode ) != 0 ) + if ( nondefOff != 0 && + tt_cmap14_char_map_nondef_binary( ttcmap->data + nondefOff, + charcode ) != 0 ) return 0; return -1; @@ -3332,12 +3339,13 @@ FT_CALLBACK_DEF( FT_UInt32* ) - tt_cmap14_variants( TT_CMap cmap, + tt_cmap14_variants( FT_CMap cmap, /* TT_CMap14 */ FT_Memory memory ) { + TT_CMap ttcmap = (TT_CMap)cmap; TT_CMap14 cmap14 = (TT_CMap14)cmap; FT_UInt32 count = cmap14->num_selectors; - FT_Byte* p = cmap->data + 10; + FT_Byte* p = ttcmap->data + 10; FT_UInt32* result; FT_UInt32 i; @@ -3358,13 +3366,14 @@ FT_CALLBACK_DEF( FT_UInt32 * ) - tt_cmap14_char_variants( TT_CMap cmap, + tt_cmap14_char_variants( FT_CMap cmap, /* TT_CMap14 */ FT_Memory memory, FT_UInt32 charCode ) { - TT_CMap14 cmap14 = (TT_CMap14) cmap; + TT_CMap ttcmap = (TT_CMap)cmap; + TT_CMap14 cmap14 = (TT_CMap14)cmap; FT_UInt32 count = cmap14->num_selectors; - FT_Byte* p = cmap->data + 10; + FT_Byte* p = ttcmap->data + 10; FT_UInt32* q; @@ -3378,12 +3387,12 @@ FT_ULong nondefOff = TT_NEXT_ULONG( p ); - if ( ( defOff != 0 && - tt_cmap14_char_map_def_binary( cmap->data + defOff, - charCode ) ) || - ( nondefOff != 0 && - tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, - charCode ) != 0 ) ) + if ( ( defOff != 0 && + tt_cmap14_char_map_def_binary( ttcmap->data + defOff, + charCode ) ) || + ( nondefOff != 0 && + tt_cmap14_char_map_nondef_binary( ttcmap->data + nondefOff, + charCode ) != 0 ) ) { q[0] = varSel; q++; @@ -3479,15 +3488,16 @@ FT_CALLBACK_DEF( FT_UInt32 * ) - tt_cmap14_variant_chars( TT_CMap cmap, + tt_cmap14_variant_chars( FT_CMap cmap, /* TT_CMap */ FT_Memory memory, FT_UInt32 variantSelector ) { - FT_Byte *p = tt_cmap14_find_variant( cmap->data + 6, - variantSelector ); - FT_Int i; - FT_ULong defOff; - FT_ULong nondefOff; + TT_CMap ttcmap = (TT_CMap)cmap; + FT_Byte *p = tt_cmap14_find_variant( ttcmap->data + 6, + variantSelector ); + FT_Int i; + FT_ULong defOff; + FT_ULong nondefOff; if ( !p ) @@ -3500,16 +3510,16 @@ return NULL; if ( defOff == 0 ) - return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, + return tt_cmap14_get_nondef_chars( ttcmap, ttcmap->data + nondefOff, memory ); else if ( nondefOff == 0 ) - return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, + return tt_cmap14_get_def_chars( ttcmap, ttcmap->data + defOff, memory ); else { /* Both a default and a non-default glyph set? That's probably not */ /* good font design, but the spec allows for it... */ - TT_CMap14 cmap14 = (TT_CMap14) cmap; + TT_CMap14 cmap14 = (TT_CMap14)cmap; FT_UInt32 numRanges; FT_UInt32 numMappings; FT_UInt32 duni; @@ -3521,18 +3531,18 @@ FT_UInt32 *ret; - p = cmap->data + nondefOff; - dp = cmap->data + defOff; + p = ttcmap->data + nondefOff; + dp = ttcmap->data + defOff; numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); dcnt = tt_cmap14_def_char_count( dp ); numRanges = (FT_UInt32)TT_NEXT_ULONG( dp ); if ( numMappings == 0 ) - return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, + return tt_cmap14_get_def_chars( ttcmap, ttcmap->data + defOff, memory ); if ( dcnt == 0 ) - return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, + return tt_cmap14_get_nondef_chars( ttcmap, ttcmap->data + nondefOff, memory ); if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) ) @@ -3654,9 +3664,10 @@ #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES FT_CALLBACK_DEF( const char * ) - tt_get_glyph_name( TT_Face face, + tt_get_glyph_name( void* face_, /* TT_Face */ FT_UInt idx ) { + TT_Face face = (TT_Face)face_; FT_String* PSname = NULL; @@ -3667,12 +3678,13 @@ FT_CALLBACK_DEF( FT_Error ) - tt_cmap_unicode_init( PS_Unicodes unicodes, - FT_Pointer pointer ) + tt_cmap_unicode_init( FT_CMap cmap, /* PS_Unicodes */ + FT_Pointer pointer ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; FT_UNUSED( pointer ); @@ -3683,17 +3695,18 @@ return psnames->unicodes_init( memory, unicodes, face->root.num_glyphs, - (PS_GetGlyphNameFunc)&tt_get_glyph_name, + &tt_get_glyph_name, (PS_FreeGlyphNameFunc)NULL, (FT_Pointer)face ); } FT_CALLBACK_DEF( void ) - tt_cmap_unicode_done( PS_Unicodes unicodes ) + tt_cmap_unicode_done( FT_CMap cmap ) /* PS_Unicodes */ { - FT_Face face = FT_CMAP_FACE( unicodes ); - FT_Memory memory = FT_FACE_MEMORY( face ); + PS_Unicodes unicodes = (PS_Unicodes)cmap; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); FT_FREE( unicodes->maps ); @@ -3702,23 +3715,25 @@ FT_CALLBACK_DEF( FT_UInt ) - tt_cmap_unicode_char_index( PS_Unicodes unicodes, - FT_UInt32 char_code ) + tt_cmap_unicode_char_index( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 char_code ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; return psnames->unicodes_char_index( unicodes, char_code ); } - FT_CALLBACK_DEF( FT_UInt32 ) - tt_cmap_unicode_char_next( PS_Unicodes unicodes, - FT_UInt32 *pchar_code ) + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap_unicode_char_next( FT_CMap cmap, /* PS_Unicodes */ + FT_UInt32 *pchar_code ) { - TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + PS_Unicodes unicodes = (PS_Unicodes)cmap; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; return psnames->unicodes_char_next( unicodes, pchar_code ); @@ -3869,13 +3884,14 @@ } - FT_LOCAL( FT_Error ) + FT_LOCAL_DEF( FT_Error ) tt_get_cmap_info( FT_CharMap charmap, TT_CMapInfo *cmap_info ) { - FT_CMap cmap = (FT_CMap)charmap; + FT_CMap cmap = FT_CMAP( charmap ); TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz; + if ( clazz->get_cmap_info ) return clazz->get_cmap_info( charmap, cmap_info ); else diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttcmap.h b/lib/libesp32_lvgl/freetype/src/sfnt/ttcmap.h index c7d7c21d2..ff52917ed 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttcmap.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttcmap.h @@ -4,7 +4,7 @@ * * TrueType character mapping table (cmap) support (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttcmapc.h b/lib/libesp32_lvgl/freetype/src/sfnt/ttcmapc.h index 2e4ce5075..0af48c247 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttcmapc.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttcmapc.h @@ -4,7 +4,7 @@ * * TT CMAP classes definitions (specification only). * - * Copyright (C) 2009-2020 by + * Copyright (C) 2009-2023 by * Oran Agra and Mickey Gabel. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttcolr.c b/lib/libesp32_lvgl/freetype/src/sfnt/ttcolr.c index 9025e356c..281e7135e 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttcolr.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttcolr.c @@ -4,8 +4,8 @@ * * TrueType and OpenType colored glyph layer support (body). * - * Copyright (C) 2018-2020 by - * David Turner, Robert Wilhelm, and Werner Lemberg. + * Copyright (C) 2018-2023 by + * David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg. * * Originally written by Shao Yu Zhang . * @@ -27,11 +27,16 @@ */ +#include #include #include #include #include +#include +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include +#endif #ifdef TT_CONFIG_OPTION_COLOR_LAYERS @@ -39,12 +44,52 @@ /* NOTE: These are the table sizes calculated through the specs. */ -#define BASE_GLYPH_SIZE 6U -#define LAYER_SIZE 4U -#define COLR_HEADER_SIZE 14U +#define BASE_GLYPH_SIZE 6U +#define BASE_GLYPH_PAINT_RECORD_SIZE 6U +#define LAYER_V1_LIST_PAINT_OFFSET_SIZE 4U +#define LAYER_V1_LIST_NUM_LAYERS_SIZE 4U +#define COLOR_STOP_SIZE 6U +#define VAR_IDX_BASE_SIZE 4U +#define LAYER_SIZE 4U +/* https://docs.microsoft.com/en-us/typography/opentype/spec/colr#colr-header */ +/* 3 * uint16 + 2 * Offset32 */ +#define COLRV0_HEADER_SIZE 14U +/* COLRV0_HEADER_SIZE + 5 * Offset32 */ +#define COLRV1_HEADER_SIZE 34U - typedef struct BaseGlyphRecord_ +#define ENSURE_READ_BYTES( byte_size ) \ + if ( p < colr->paints_start_v1 || \ + p > (FT_Byte*)colr->table + colr->table_size - byte_size ) \ + return 0 + + + typedef enum FT_PaintFormat_Internal_ + { + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SOLID = 3, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_LINEAR_GRADIENT = 5, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_RADIAL_GRADIENT = 7, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SWEEP_GRADIENT = 9, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSFORM = 13, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSLATE = 15, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE = 17, + FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER = 18, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER = 19, + FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM = 20, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM = 21, + FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER = 22, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER = 23, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE = 25, + FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER = 26, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER = 27, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW = 29, + FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER = 30, + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER = 31, + + } FT_PaintFormat_Internal; + + + typedef struct BaseGlyphRecord_ { FT_UShort gid; FT_UShort first_layer_index; @@ -53,7 +98,16 @@ } BaseGlyphRecord; - typedef struct Colr_ + typedef struct BaseGlyphV1Record_ + { + FT_UShort gid; + /* Offset from start of BaseGlyphV1List, i.e., from base_glyphs_v1. */ + FT_ULong paint_offset; + + } BaseGlyphV1Record; + + + typedef struct Colr_ { FT_UShort version; FT_UShort num_base_glyphs; @@ -62,7 +116,29 @@ FT_Byte* base_glyphs; FT_Byte* layers; - /* The memory which backs up the `COLR' table. */ + FT_ULong num_base_glyphs_v1; + /* Points at beginning of BaseGlyphV1List. */ + FT_Byte* base_glyphs_v1; + + FT_ULong num_layers_v1; + FT_Byte* layers_v1; + + FT_Byte* clip_list; + + /* + * Paint tables start at the minimum of the end of the LayerList and the + * end of the BaseGlyphList. Record this location in a field here for + * safety checks when accessing paint tables. + */ + FT_Byte* paints_start_v1; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + /* Item Variation Store for variable 'COLR' v1. */ + GX_ItemVarStoreRec var_store; + GX_DeltaSetIdxMapRec delta_set_idx_map; +#endif + + /* The memory that backs up the `COLR' table. */ void* table; FT_ULong table_size; @@ -88,11 +164,18 @@ FT_Byte* table = NULL; FT_Byte* p = NULL; + /* Needed for reading array lengths in referenced tables. */ + FT_Byte* p1 = NULL; Colr* colr = NULL; FT_ULong base_glyph_offset, layer_offset; + FT_ULong base_glyphs_offset_v1, num_base_glyphs_v1; + FT_ULong layer_offset_v1, num_layers_v1, clip_list_offset; FT_ULong table_size; +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + FT_ULong colr_offset_in_stream; +#endif /* `COLR' always needs `CPAL' */ @@ -103,8 +186,12 @@ if ( error ) goto NoColr; - if ( table_size < COLR_HEADER_SIZE ) - goto InvalidTable; +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + colr_offset_in_stream = FT_STREAM_POS(); +#endif + + if ( table_size < COLRV0_HEADER_SIZE ) + goto NoColr; if ( FT_FRAME_EXTRACT( table_size, table ) ) goto NoColr; @@ -115,7 +202,7 @@ goto NoColr; colr->version = FT_NEXT_USHORT( p ); - if ( colr->version != 0 ) + if ( colr->version != 0 && colr->version != 1 ) goto InvalidTable; colr->num_base_glyphs = FT_NEXT_USHORT( p ); @@ -135,6 +222,131 @@ if ( colr->num_layers * LAYER_SIZE > table_size - layer_offset ) goto InvalidTable; + if ( colr->version == 1 ) + { + if ( table_size < COLRV1_HEADER_SIZE ) + goto InvalidTable; + + base_glyphs_offset_v1 = FT_NEXT_ULONG( p ); + + if ( base_glyphs_offset_v1 >= table_size - 4 ) + goto InvalidTable; + + p1 = (FT_Byte*)( table + base_glyphs_offset_v1 ); + num_base_glyphs_v1 = FT_PEEK_ULONG( p1 ); + + if ( num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE > + table_size - base_glyphs_offset_v1 ) + goto InvalidTable; + + colr->num_base_glyphs_v1 = num_base_glyphs_v1; + colr->base_glyphs_v1 = p1; + + layer_offset_v1 = FT_NEXT_ULONG( p ); + + if ( layer_offset_v1 >= table_size ) + goto InvalidTable; + + if ( layer_offset_v1 ) + { + if ( layer_offset_v1 >= table_size - 4 ) + goto InvalidTable; + + p1 = (FT_Byte*)( table + layer_offset_v1 ); + num_layers_v1 = FT_PEEK_ULONG( p1 ); + + if ( num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE > + table_size - layer_offset_v1 ) + goto InvalidTable; + + colr->num_layers_v1 = num_layers_v1; + colr->layers_v1 = p1; + + colr->paints_start_v1 = + FT_MIN( colr->base_glyphs_v1 + + colr->num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE, + colr->layers_v1 + + colr->num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE ); + } + else + { + colr->num_layers_v1 = 0; + colr->layers_v1 = 0; + colr->paints_start_v1 = + colr->base_glyphs_v1 + + colr->num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE; + } + + clip_list_offset = FT_NEXT_ULONG( p ); + + if ( clip_list_offset >= table_size ) + goto InvalidTable; + + if ( clip_list_offset ) + colr->clip_list = (FT_Byte*)( table + clip_list_offset ); + else + colr->clip_list = 0; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + colr->var_store.dataCount = 0; + colr->var_store.varData = NULL; + colr->var_store.axisCount = 0; + colr->var_store.regionCount = 0; + colr->var_store.varRegionList = 0; + + colr->delta_set_idx_map.mapCount = 0; + colr->delta_set_idx_map.outerIndex = NULL; + colr->delta_set_idx_map.innerIndex = NULL; + + if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) + { + FT_ULong var_idx_map_offset, var_store_offset; + + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + + + var_idx_map_offset = FT_NEXT_ULONG( p ); + + if ( var_idx_map_offset >= table_size ) + goto InvalidTable; + + var_store_offset = FT_NEXT_ULONG( p ); + if ( var_store_offset >= table_size ) + goto InvalidTable; + + if ( var_store_offset ) + { + /* If variation info has not been initialized yet, try doing so, */ + /* otherwise loading the variation store will fail as it */ + /* requires access to `blend` for checking the number of axes. */ + if ( !face->blend ) + if ( mm->get_mm_var( FT_FACE( face ), NULL ) ) + goto InvalidTable; + + /* Try loading `VarIdxMap` and `VarStore`. */ + error = mm->load_item_var_store( + FT_FACE( face ), + colr_offset_in_stream + var_store_offset, + &colr->var_store ); + if ( error != FT_Err_Ok ) + goto InvalidTable; + } + + if ( colr->var_store.axisCount && var_idx_map_offset ) + { + error = mm->load_delta_set_idx_map( + FT_FACE( face ), + colr_offset_in_stream + var_idx_map_offset, + &colr->delta_set_idx_map, + &colr->var_store, + table_size ); + if ( error != FT_Err_Ok ) + goto InvalidTable; + } + } +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + } + colr->base_glyphs = (FT_Byte*)( table + base_glyph_offset ); colr->layers = (FT_Byte*)( table + layer_offset ); colr->table = table; @@ -145,6 +357,18 @@ return FT_Err_Ok; InvalidTable: +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + { + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + + + mm->done_delta_set_idx_map( FT_FACE( face ), + &colr->delta_set_idx_map ); + mm->done_item_var_store( FT_FACE( face ), + &colr->var_store ); + } +#endif + error = FT_THROW( Invalid_Table ); NoColr: @@ -166,6 +390,17 @@ if ( colr ) { +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + { + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + + + mm->done_delta_set_idx_map( FT_FACE( face ), + &colr->delta_set_idx_map ); + mm->done_item_var_store( FT_FACE( face ), + &colr->var_store ); + } +#endif FT_FRAME_RELEASE( colr->table ); FT_FREE( colr ); } @@ -174,17 +409,17 @@ static FT_Bool find_base_glyph_record( FT_Byte* base_glyph_begin, - FT_Int num_base_glyph, + FT_UInt num_base_glyph, FT_UInt glyph_id, BaseGlyphRecord* record ) { - FT_Int min = 0; - FT_Int max = num_base_glyph - 1; + FT_UInt min = 0; + FT_UInt max = num_base_glyph; - while ( min <= max ) + while ( min < max ) { - FT_Int mid = min + ( max - min ) / 2; + FT_UInt mid = min + ( max - min ) / 2; FT_Byte* p = base_glyph_begin + mid * BASE_GLYPH_SIZE; FT_UShort gid = FT_NEXT_USHORT( p ); @@ -193,7 +428,7 @@ if ( gid < glyph_id ) min = mid + 1; else if (gid > glyph_id ) - max = mid - 1; + max = mid; else { record->gid = gid; @@ -248,7 +483,9 @@ iterator->p = colr->layers + offset; } - if ( iterator->layer >= iterator->num_layers ) + if ( iterator->layer >= iterator->num_layers || + iterator->p < colr->layers || + iterator->p >= ( (FT_Byte*)colr->table + colr->table_size ) ) return 0; *aglyph_index = FT_NEXT_USHORT( iterator->p ); @@ -265,6 +502,1240 @@ } + static FT_Bool + read_color_line( Colr* colr, + FT_Byte* color_line_p, + FT_ColorLine* colorline, + FT_Bool read_variable ) + { + FT_Byte* p = color_line_p; + FT_PaintExtend paint_extend; + + + ENSURE_READ_BYTES( 3 ); + + paint_extend = (FT_PaintExtend)FT_NEXT_BYTE( p ); + if ( paint_extend > FT_COLR_PAINT_EXTEND_REFLECT ) + return 0; + + colorline->extend = paint_extend; + + colorline->color_stop_iterator.num_color_stops = FT_NEXT_USHORT( p ); + colorline->color_stop_iterator.p = p; + colorline->color_stop_iterator.current_color_stop = 0; + colorline->color_stop_iterator.read_variable = read_variable; + + return 1; + } + + + /* + * Read a paint offset for `FT_Paint*` objects that have them and check + * whether it is within reasonable limits within the font and the COLR + * table. + * + * Return 1 on success, 0 on failure. + */ + static FT_Bool + get_child_table_pointer ( Colr* colr, + FT_Byte* paint_base, + FT_Byte** p, + FT_Byte** child_table_pointer ) + { + FT_UInt32 paint_offset; + FT_Byte* child_table_p; + + + if ( !child_table_pointer ) + return 0; + + if ( *p < colr->paints_start_v1 || + *p > (FT_Byte*)colr->table + colr->table_size - 1 - 3 ) + return 0; + + paint_offset = FT_NEXT_UOFF3( *p ); + if ( !paint_offset ) + return 0; + + child_table_p = (FT_Byte*)( paint_base + paint_offset ); + + if ( child_table_p < colr->paints_start_v1 || + child_table_p >= ( (FT_Byte*)colr->table + colr->table_size ) ) + return 0; + + *child_table_pointer = child_table_p; + return 1; + } + + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + + static FT_Bool + get_deltas_for_var_index_base ( TT_Face face, + Colr* colr, + FT_ULong var_index_base, + FT_UInt num_deltas, + FT_ItemVarDelta* deltas ) + { + FT_UInt outer_index = 0; + FT_UInt inner_index = 0; + FT_ULong loop_var_index = var_index_base; + + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + + FT_UInt i = 0; + + + if ( var_index_base == 0xFFFFFFFF ) + { + for ( i = 0; i < num_deltas; ++i ) + deltas[i] = 0; + return 1; + } + + for ( i = 0; i < num_deltas; ++i ) + { + loop_var_index = var_index_base + i; + + if ( colr->delta_set_idx_map.innerIndex ) + { + if ( loop_var_index >= colr->delta_set_idx_map.mapCount ) + loop_var_index = colr->delta_set_idx_map.mapCount - 1; + + outer_index = colr->delta_set_idx_map.outerIndex[loop_var_index]; + inner_index = colr->delta_set_idx_map.innerIndex[loop_var_index]; + } + else + { + outer_index = 0; + inner_index = loop_var_index; + } + + deltas[i] = mm->get_item_delta( FT_FACE( face ), &colr->var_store, + outer_index, inner_index ); + } + + return 1; + } + +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + + + static FT_Bool + read_paint( TT_Face face, + Colr* colr, + FT_Byte* p, + FT_COLR_Paint* apaint ) + { + FT_Byte* paint_base = p; + FT_Byte* child_table_p = NULL; + FT_Bool do_read_var = FALSE; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + FT_ULong var_index_base = 0; + /* Longest varIndexBase offset is 5 in the spec. */ + FT_ItemVarDelta item_deltas[6] = { 0, 0, 0, 0, 0, 0 }; +#else + FT_UNUSED( face ); +#endif + + + if ( !p || !colr || !colr->table ) + return 0; + + /* The last byte of the 'COLR' table is at 'size-1'; subtract 1 of */ + /* that to account for the expected format byte we are going to read. */ + if ( p < colr->paints_start_v1 || + p > (FT_Byte*)colr->table + colr->table_size - 2 ) + return 0; + + apaint->format = (FT_PaintFormat)FT_NEXT_BYTE( p ); + + if ( apaint->format >= FT_COLR_PAINT_FORMAT_MAX ) + return 0; + + if ( apaint->format == FT_COLR_PAINTFORMAT_COLR_LAYERS ) + { + /* Initialize layer iterator/ */ + FT_Byte num_layers; + FT_UInt32 first_layer_index; + + + num_layers = FT_NEXT_BYTE( p ); + if ( num_layers > colr->num_layers_v1 ) + return 0; + + first_layer_index = FT_NEXT_ULONG( p ); + if ( first_layer_index + num_layers > colr->num_layers_v1 ) + return 0; + + apaint->u.colr_layers.layer_iterator.num_layers = num_layers; + apaint->u.colr_layers.layer_iterator.layer = 0; + /* TODO: Check whether pointer is outside colr? */ + apaint->u.colr_layers.layer_iterator.p = + colr->layers_v1 + + LAYER_V1_LIST_NUM_LAYERS_SIZE + + LAYER_V1_LIST_PAINT_OFFSET_SIZE * first_layer_index; + + return 1; + } + + else if ( apaint->format == FT_COLR_PAINTFORMAT_SOLID || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SOLID ) + { + ENSURE_READ_BYTES( 4 ); + apaint->u.solid.color.palette_index = FT_NEXT_USHORT( p ); + apaint->u.solid.color.alpha = FT_NEXT_SHORT( p ); + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SOLID ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG( p ); + + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 1, + item_deltas ) ) + return 0; + + apaint->u.solid.color.alpha += (FT_F2Dot14)item_deltas[0]; + } +#endif + + apaint->format = FT_COLR_PAINTFORMAT_SOLID; + + return 1; + } + + else if ( apaint->format == FT_COLR_PAINTFORMAT_COLR_GLYPH ) + { + ENSURE_READ_BYTES(2); + apaint->u.colr_glyph.glyphID = FT_NEXT_USHORT( p ); + + return 1; + } + + /* + * Grouped below here are all paint formats that have an offset to a + * child paint table as the first entry (for example, a color line or a + * child paint table). Retrieve that and determine whether that paint + * offset is valid first. + */ + + if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) ) + return 0; + + if ( apaint->format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT || + ( do_read_var = + ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_LINEAR_GRADIENT ) ) ) + { + if ( !read_color_line( colr, + child_table_p, + &apaint->u.linear_gradient.colorline, + do_read_var ) ) + return 0; + + /* + * In order to support variations expose these as FT_Fixed 16.16 + * values so that we can support fractional values after + * interpolation. + */ + ENSURE_READ_BYTES( 12 ); + apaint->u.linear_gradient.p0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.linear_gradient.p0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.linear_gradient.p1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.linear_gradient.p1.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.linear_gradient.p2.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.linear_gradient.p2.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( do_read_var ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG ( p ); + + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 6, + item_deltas ) ) + return 0; + + apaint->u.linear_gradient.p0.x += INT_TO_FIXED( item_deltas[0] ); + apaint->u.linear_gradient.p0.y += INT_TO_FIXED( item_deltas[1] ); + apaint->u.linear_gradient.p1.x += INT_TO_FIXED( item_deltas[2] ); + apaint->u.linear_gradient.p1.y += INT_TO_FIXED( item_deltas[3] ); + apaint->u.linear_gradient.p2.x += INT_TO_FIXED( item_deltas[4] ); + apaint->u.linear_gradient.p2.y += INT_TO_FIXED( item_deltas[5] ); + } +#endif + + apaint->format = FT_COLR_PAINTFORMAT_LINEAR_GRADIENT; + + return 1; + } + + else if ( apaint->format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT || + ( do_read_var = + ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_RADIAL_GRADIENT ) ) ) + { + FT_Pos tmp; + + + if ( !read_color_line( colr, + child_table_p, + &apaint->u.radial_gradient.colorline, + do_read_var ) ) + return 0; + + + /* In the OpenType specification, `r0` and `r1` are defined as */ + /* `UFWORD`. Since FreeType doesn't have a corresponding 16.16 */ + /* format we convert to `FWORD` and replace negative values with */ + /* (32bit) `FT_INT_MAX`. */ + + ENSURE_READ_BYTES( 12 ); + + apaint->u.radial_gradient.c0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.radial_gradient.c0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + + tmp = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.radial_gradient.r0 = tmp < 0 ? FT_INT_MAX : tmp; + + apaint->u.radial_gradient.c1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.radial_gradient.c1.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + + tmp = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.radial_gradient.r1 = tmp < 0 ? FT_INT_MAX : tmp; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( do_read_var ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG ( p ); + + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 6, + item_deltas ) ) + return 0; + + apaint->u.radial_gradient.c0.x += INT_TO_FIXED( item_deltas[0] ); + apaint->u.radial_gradient.c0.y += INT_TO_FIXED( item_deltas[1] ); + + // TODO: Anything to be done about UFWORD deltas here? + apaint->u.radial_gradient.r0 += INT_TO_FIXED( item_deltas[2] ); + + apaint->u.radial_gradient.c1.x += INT_TO_FIXED( item_deltas[3] ); + apaint->u.radial_gradient.c1.y += INT_TO_FIXED( item_deltas[4] ); + + apaint->u.radial_gradient.r1 += INT_TO_FIXED( item_deltas[5] ); + } +#endif + + apaint->format = FT_COLR_PAINTFORMAT_RADIAL_GRADIENT; + + return 1; + } + + else if ( apaint->format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT || + ( do_read_var = + ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SWEEP_GRADIENT ) ) ) + { + if ( !read_color_line( colr, + child_table_p, + &apaint->u.sweep_gradient.colorline, + do_read_var) ) + return 0; + + ENSURE_READ_BYTES( 8 ); + + apaint->u.sweep_gradient.center.x = + INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.sweep_gradient.center.y = + INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + + apaint->u.sweep_gradient.start_angle = + F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.sweep_gradient.end_angle = + F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( do_read_var ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG ( p ); + + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4, + item_deltas ) ) + return 0; + + // TODO: Handle overflow? + apaint->u.sweep_gradient.center.x += INT_TO_FIXED( item_deltas[0] ); + apaint->u.sweep_gradient.center.y += INT_TO_FIXED( item_deltas[1] ); + + apaint->u.sweep_gradient.start_angle += + F2DOT14_TO_FIXED( item_deltas[2] ); + apaint->u.sweep_gradient.end_angle += + F2DOT14_TO_FIXED( item_deltas[3] ); + } +#endif + apaint->format = FT_COLR_PAINTFORMAT_SWEEP_GRADIENT; + + return 1; + } + + if ( apaint->format == FT_COLR_PAINTFORMAT_GLYPH ) + { + ENSURE_READ_BYTES( 2 ); + apaint->u.glyph.paint.p = child_table_p; + apaint->u.glyph.paint.insert_root_transform = 0; + apaint->u.glyph.glyphID = FT_NEXT_USHORT( p ); + + return 1; + } + + else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSFORM || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSFORM ) + { + apaint->u.transform.paint.p = child_table_p; + apaint->u.transform.paint.insert_root_transform = 0; + + if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) ) + return 0; + + p = child_table_p; + + /* + * The following matrix coefficients are encoded as + * OpenType 16.16 fixed-point values. + */ + ENSURE_READ_BYTES( 24 ); + apaint->u.transform.affine.xx = FT_NEXT_LONG( p ); + apaint->u.transform.affine.yx = FT_NEXT_LONG( p ); + apaint->u.transform.affine.xy = FT_NEXT_LONG( p ); + apaint->u.transform.affine.yy = FT_NEXT_LONG( p ); + apaint->u.transform.affine.dx = FT_NEXT_LONG( p ); + apaint->u.transform.affine.dy = FT_NEXT_LONG( p ); + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSFORM ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG( p ); + + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 6, + item_deltas ) ) + return 0; + + apaint->u.transform.affine.xx += (FT_Fixed)item_deltas[0]; + apaint->u.transform.affine.yx += (FT_Fixed)item_deltas[1]; + apaint->u.transform.affine.xy += (FT_Fixed)item_deltas[2]; + apaint->u.transform.affine.yy += (FT_Fixed)item_deltas[3]; + apaint->u.transform.affine.dx += (FT_Fixed)item_deltas[4]; + apaint->u.transform.affine.dy += (FT_Fixed)item_deltas[5]; + } +#endif + + apaint->format = FT_COLR_PAINTFORMAT_TRANSFORM; + + return 1; + } + + else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSLATE || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSLATE ) + { + apaint->u.translate.paint.p = child_table_p; + apaint->u.translate.paint.insert_root_transform = 0; + + ENSURE_READ_BYTES( 4 ); + apaint->u.translate.dx = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.translate.dy = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSLATE ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG( p ); + + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 2, + item_deltas ) ) + return 0; + + apaint->u.translate.dx += INT_TO_FIXED( item_deltas[0] ); + apaint->u.translate.dy += INT_TO_FIXED( item_deltas[1] ); + } +#endif + + apaint->format = FT_COLR_PAINTFORMAT_TRANSLATE; + + return 1; + } + + else if ( apaint->format >= FT_COLR_PAINTFORMAT_SCALE && + (FT_PaintFormat_Internal)apaint->format <= + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER ) + { + apaint->u.scale.paint.p = child_table_p; + apaint->u.scale.paint.insert_root_transform = 0; + + /* All scale paints get at least one scale value. */ + ENSURE_READ_BYTES( 2 ); + apaint->u.scale.scale_x = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); + + /* Non-uniform ones read an extra y value. */ + if ( apaint->format == FT_COLR_PAINTFORMAT_SCALE || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER ) + { + ENSURE_READ_BYTES( 2 ); + apaint->u.scale.scale_y = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); + } + else + apaint->u.scale.scale_y = apaint->u.scale.scale_x; + + /* Scale paints that have a center read center coordinates, */ + /* otherwise the center is (0,0). */ + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER ) + { + ENSURE_READ_BYTES( 4 ); + apaint->u.scale.center_x = INT_TO_FIXED( FT_NEXT_SHORT ( p ) ); + apaint->u.scale.center_y = INT_TO_FIXED( FT_NEXT_SHORT ( p ) ); + } + else + { + apaint->u.scale.center_x = 0; + apaint->u.scale.center_y = 0; + } + + /* Base values set, now handle variations. */ + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG( p ); + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE ) + { + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 2, + item_deltas ) ) + return 0; + + apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] ); + apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[1] ); + } + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER ) + { + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4, + item_deltas ) ) + return 0; + + apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] ); + apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[1] ); + apaint->u.scale.center_x += INT_TO_FIXED( item_deltas[2] ); + apaint->u.scale.center_y += INT_TO_FIXED( item_deltas[3] ); + } + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM ) + { + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 1, + item_deltas ) ) + return 0; + + apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] ); + apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[0] ); + } + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER ) + { + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 3, + item_deltas ) ) + return 0; + + apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] ); + apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[0] ); + apaint->u.scale.center_x += INT_TO_FIXED( item_deltas[1] ); + apaint->u.scale.center_y += INT_TO_FIXED( item_deltas[2] ); + } + } +#endif + + /* FT 'COLR' v1 API output format always returns fully defined */ + /* structs; we thus set the format to the public API value. */ + apaint->format = FT_COLR_PAINTFORMAT_SCALE; + + return 1; + } + + else if ( apaint->format == FT_COLR_PAINTFORMAT_ROTATE || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER ) + { + apaint->u.rotate.paint.p = child_table_p; + apaint->u.rotate.paint.insert_root_transform = 0; + + ENSURE_READ_BYTES( 2 ); + apaint->u.rotate.angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER ) + { + ENSURE_READ_BYTES( 4 ); + apaint->u.rotate.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.rotate.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + } + else + { + apaint->u.rotate.center_x = 0; + apaint->u.rotate.center_y = 0; + } + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER ) + { + FT_UInt num_deltas = 0; + + + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG( p ); + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER ) + num_deltas = 3; + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE ) + num_deltas = 1; + + if ( num_deltas > 0 ) + { + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, + num_deltas, item_deltas ) ) + return 0; + + apaint->u.rotate.angle += F2DOT14_TO_FIXED( item_deltas[0] ); + + if ( num_deltas == 3 ) + { + apaint->u.rotate.center_x += INT_TO_FIXED( item_deltas[1] ); + apaint->u.rotate.center_y += INT_TO_FIXED( item_deltas[2] ); + } + } + } +#endif + + apaint->format = FT_COLR_PAINTFORMAT_ROTATE; + + + return 1; + } + + else if ( apaint->format == FT_COLR_PAINTFORMAT_SKEW || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER ) + { + apaint->u.skew.paint.p = child_table_p; + apaint->u.skew.paint.insert_root_transform = 0; + + ENSURE_READ_BYTES( 4 ); + apaint->u.skew.x_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.skew.y_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER ) + { + ENSURE_READ_BYTES( 4 ); + apaint->u.skew.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + apaint->u.skew.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); + } + else + { + apaint->u.skew.center_x = 0; + apaint->u.skew.center_y = 0; + } + + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW || + (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER ) + { + ENSURE_READ_BYTES( 4 ); + var_index_base = FT_NEXT_ULONG( p ); + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW ) + { + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 2, + item_deltas ) ) + return 0; + + apaint->u.skew.x_skew_angle += F2DOT14_TO_FIXED( item_deltas[0] ); + apaint->u.skew.y_skew_angle += F2DOT14_TO_FIXED( item_deltas[1] ); + } + + if ( (FT_PaintFormat_Internal)apaint->format == + FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER ) + { + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4, + item_deltas ) ) + return 0; + + apaint->u.skew.x_skew_angle += F2DOT14_TO_FIXED( item_deltas[0] ); + apaint->u.skew.y_skew_angle += F2DOT14_TO_FIXED( item_deltas[1] ); + apaint->u.skew.center_x += INT_TO_FIXED( item_deltas[2] ); + apaint->u.skew.center_y += INT_TO_FIXED( item_deltas[3] ); + } + } +#endif + + apaint->format = FT_COLR_PAINTFORMAT_SKEW; + + return 1; + } + + else if ( apaint->format == FT_COLR_PAINTFORMAT_COMPOSITE ) + { + FT_UInt composite_mode; + + + apaint->u.composite.source_paint.p = child_table_p; + apaint->u.composite.source_paint.insert_root_transform = 0; + + ENSURE_READ_BYTES( 1 ); + composite_mode = FT_NEXT_BYTE( p ); + if ( composite_mode >= FT_COLR_COMPOSITE_MAX ) + return 0; + + apaint->u.composite.composite_mode = (FT_Composite_Mode)composite_mode; + + if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) ) + return 0; + + apaint->u.composite.backdrop_paint.p = + child_table_p; + apaint->u.composite.backdrop_paint.insert_root_transform = + 0; + + return 1; + } + + return 0; + } + + + static FT_Bool + find_base_glyph_v1_record( FT_Byte * base_glyph_begin, + FT_UInt num_base_glyph, + FT_UInt glyph_id, + BaseGlyphV1Record *record ) + { + FT_UInt min = 0; + FT_UInt max = num_base_glyph; + + + while ( min < max ) + { + FT_UInt mid = min + ( max - min ) / 2; + + /* + * `base_glyph_begin` is the beginning of `BaseGlyphV1List`; + * skip `numBaseGlyphV1Records` by adding 4 to start binary search + * in the array of `BaseGlyphV1Record`. + */ + FT_Byte *p = base_glyph_begin + 4 + mid * BASE_GLYPH_PAINT_RECORD_SIZE; + + FT_UShort gid = FT_NEXT_USHORT( p ); + + + if ( gid < glyph_id ) + min = mid + 1; + else if (gid > glyph_id ) + max = mid; + else + { + record->gid = gid; + record->paint_offset = FT_NEXT_ULONG ( p ); + return 1; + } + } + + return 0; + } + + + FT_LOCAL_DEF( FT_Bool ) + tt_face_get_colr_glyph_paint( TT_Face face, + FT_UInt base_glyph, + FT_Color_Root_Transform root_transform, + FT_OpaquePaint* opaque_paint ) + { + Colr* colr = (Colr*)face->colr; + BaseGlyphV1Record base_glyph_v1_record; + FT_Byte* p; + + if ( !colr || !colr->table ) + return 0; + + if ( colr->version < 1 || !colr->num_base_glyphs_v1 || + !colr->base_glyphs_v1 ) + return 0; + + if ( opaque_paint->p ) + return 0; + + if ( !find_base_glyph_v1_record( colr->base_glyphs_v1, + colr->num_base_glyphs_v1, + base_glyph, + &base_glyph_v1_record ) ) + return 0; + + if ( !base_glyph_v1_record.paint_offset || + base_glyph_v1_record.paint_offset > colr->table_size ) + return 0; + + p = (FT_Byte*)( colr->base_glyphs_v1 + + base_glyph_v1_record.paint_offset ); + if ( p >= ( (FT_Byte*)colr->table + colr->table_size ) ) + return 0; + + opaque_paint->p = p; + + if ( root_transform == FT_COLOR_INCLUDE_ROOT_TRANSFORM ) + opaque_paint->insert_root_transform = 1; + else + opaque_paint->insert_root_transform = 0; + + return 1; + } + + + FT_LOCAL_DEF( FT_Bool ) + tt_face_get_color_glyph_clipbox( TT_Face face, + FT_UInt base_glyph, + FT_ClipBox* clip_box ) + { + Colr* colr; + + FT_Byte *p, *p1, *clip_base, *limit; + + FT_Byte clip_list_format; + FT_ULong num_clip_boxes, i; + FT_UShort gid_start, gid_end; + FT_UInt32 clip_box_offset; + FT_Byte format; + + const FT_Byte num_corners = 4; + FT_Vector corners[4]; + FT_Byte j; + FT_BBox font_clip_box; + + + colr = (Colr*)face->colr; + if ( !colr ) + return 0; + + if ( !colr->clip_list ) + return 0; + + p = colr->clip_list; + + /* Limit points to the first byte after the end of the color table. */ + /* Thus, in subsequent limit checks below we need to check whether the */ + /* read pointer is strictly greater than a position offset by certain */ + /* field sizes to the left of that position. */ + limit = (FT_Byte*)colr->table + colr->table_size; + + /* Check whether we can extract one `uint8` and one `uint32`. */ + if ( p > limit - ( 1 + 4 ) ) + return 0; + + clip_base = p; + clip_list_format = FT_NEXT_BYTE ( p ); + + /* Format byte used here to be able to upgrade ClipList for >16bit */ + /* glyph ids; for now we can expect it to be 1. */ + if ( !( clip_list_format == 1 ) ) + return 0; + + num_clip_boxes = FT_NEXT_ULONG( p ); + + /* Check whether we can extract two `uint16` and one `Offset24`, */ + /* `num_clip_boxes` times. */ + if ( colr->table_size / ( 2 + 2 + 3 ) < num_clip_boxes || + p > limit - ( 2 + 2 + 3 ) * num_clip_boxes ) + return 0; + + for ( i = 0; i < num_clip_boxes; ++i ) + { + gid_start = FT_NEXT_USHORT( p ); + gid_end = FT_NEXT_USHORT( p ); + clip_box_offset = FT_NEXT_UOFF3( p ); + + if ( base_glyph >= gid_start && base_glyph <= gid_end ) + { + p1 = (FT_Byte*)( clip_base + clip_box_offset ); + + /* Check whether we can extract one `uint8`. */ + if ( p1 > limit - 1 ) + return 0; + + format = FT_NEXT_BYTE( p1 ); + + if ( format > 2 ) + return 0; + + /* Check whether we can extract four `FWORD`. */ + if ( p1 > limit - ( 2 + 2 + 2 + 2 ) ) + return 0; + + /* `face->root.size->metrics.x_scale` and `y_scale` are factors */ + /* that scale a font unit value in integers to a 26.6 fixed value */ + /* according to the requested size, see for example */ + /* `ft_recompute_scaled_metrics`. */ + font_clip_box.xMin = FT_MulFix( FT_NEXT_SHORT( p1 ), + face->root.size->metrics.x_scale ); + font_clip_box.yMin = FT_MulFix( FT_NEXT_SHORT( p1 ), + face->root.size->metrics.y_scale ); + font_clip_box.xMax = FT_MulFix( FT_NEXT_SHORT( p1 ), + face->root.size->metrics.x_scale ); + font_clip_box.yMax = FT_MulFix( FT_NEXT_SHORT( p1 ), + face->root.size->metrics.y_scale ); + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( format == 2 ) + { + FT_ULong var_index_base = 0; + /* varIndexBase offset for clipbox is 3 at most. */ + FT_ItemVarDelta item_deltas[4] = { 0, 0, 0, 0 }; + + + /* Check whether we can extract a 32-bit varIndexBase now. */ + if ( p1 > limit - 4 ) + return 0; + + var_index_base = FT_NEXT_ULONG( p1 ); + + if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4, + item_deltas ) ) + return 0; + + font_clip_box.xMin += + FT_MulFix( item_deltas[0], face->root.size->metrics.x_scale ); + font_clip_box.yMin += + FT_MulFix( item_deltas[1], face->root.size->metrics.y_scale ); + font_clip_box.xMax += + FT_MulFix( item_deltas[2], face->root.size->metrics.x_scale ); + font_clip_box.yMax += + FT_MulFix( item_deltas[3], face->root.size->metrics.y_scale ); + } +#endif + + /* Make 4 corner points (xMin, yMin), (xMax, yMax) and transform */ + /* them. If we we would only transform two corner points and */ + /* span a rectangle based on those, the rectangle may become too */ + /* small to cover the glyph. */ + corners[0].x = font_clip_box.xMin; + corners[1].x = font_clip_box.xMin; + corners[2].x = font_clip_box.xMax; + corners[3].x = font_clip_box.xMax; + + corners[0].y = font_clip_box.yMin; + corners[1].y = font_clip_box.yMax; + corners[2].y = font_clip_box.yMax; + corners[3].y = font_clip_box.yMin; + + for ( j = 0; j < num_corners; ++j ) + { + if ( face->root.internal->transform_flags & 1 ) + FT_Vector_Transform( &corners[j], + &face->root.internal->transform_matrix ); + + if ( face->root.internal->transform_flags & 2 ) + { + corners[j].x += face->root.internal->transform_delta.x; + corners[j].y += face->root.internal->transform_delta.y; + } + } + + clip_box->bottom_left = corners[0]; + clip_box->top_left = corners[1]; + clip_box->top_right = corners[2]; + clip_box->bottom_right = corners[3]; + + return 1; + } + } + + return 0; + } + + + FT_LOCAL_DEF( FT_Bool ) + tt_face_get_paint_layers( TT_Face face, + FT_LayerIterator* iterator, + FT_OpaquePaint* opaque_paint ) + { + FT_Byte* p = NULL; + FT_Byte* p_first_layer = NULL; + FT_Byte* p_paint = NULL; + FT_UInt32 paint_offset; + + Colr* colr; + + + if ( iterator->layer == iterator->num_layers ) + return 0; + + colr = (Colr*)face->colr; + if ( !colr ) + return 0; + + /* + * We have an iterator pointing at a paint offset as part of the + * `paintOffset` array in `LayerV1List`. + */ + p = iterator->p; + + /* + * Do a cursor sanity check of the iterator. Counting backwards from + * where it stands, we need to end up at a position after the beginning + * of the `LayerV1List` table and not after the end of the + * `LayerV1List`. + */ + p_first_layer = p - + iterator->layer * LAYER_V1_LIST_PAINT_OFFSET_SIZE - + LAYER_V1_LIST_NUM_LAYERS_SIZE; + if ( p_first_layer < (FT_Byte*)colr->layers_v1 ) + return 0; + if ( p_first_layer >= (FT_Byte*)( + colr->layers_v1 + LAYER_V1_LIST_NUM_LAYERS_SIZE + + colr->num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE ) ) + return 0; + + /* + * Before reading, ensure that `p` is within 'COLR' v1 and we can read a + * 4-byte ULONG. + */ + if ( p < colr->layers_v1 || + p > (FT_Byte*)colr->table + colr->table_size - 4 ) + return 0; + + paint_offset = + FT_NEXT_ULONG( p ); + opaque_paint->insert_root_transform = + 0; + + p_paint = (FT_Byte*)( colr->layers_v1 + paint_offset ); + + if ( p_paint < colr->paints_start_v1 || + p_paint >= ( (FT_Byte*)colr->table + colr->table_size ) ) + return 0; + + opaque_paint->p = p_paint; + + iterator->p = p; + + iterator->layer++; + + return 1; + } + + + FT_LOCAL_DEF( FT_Bool ) + tt_face_get_colorline_stops( TT_Face face, + FT_ColorStop* color_stop, + FT_ColorStopIterator *iterator ) + { + Colr* colr = (Colr*)face->colr; + + FT_Byte* p; + FT_ULong var_index_base; + FT_Byte* last_entry_p = NULL; + FT_UInt entry_size = COLOR_STOP_SIZE; + + + if ( !colr || !colr->table || !iterator ) + return 0; + + if ( iterator->current_color_stop >= iterator->num_color_stops ) + return 0; + + if ( iterator->read_variable ) + entry_size += VAR_IDX_BASE_SIZE; + + /* Calculate the start pointer for the last to-be-read (Var)ColorStop */ + /* and check whether we can read a full (Var)ColorStop at that */ + /* position by comparing it to the position that is the size of one */ + /* (Var)ColorStop before the end of the 'COLR' table. */ + last_entry_p = + iterator->p + ( iterator->num_color_stops - 1 - + iterator->current_color_stop ) * entry_size; + if ( iterator->p < colr->paints_start_v1 || + last_entry_p > (FT_Byte*)colr->table + + colr->table_size - entry_size ) + return 0; + + /* Iterator points at first `ColorStop` of `ColorLine`. */ + p = iterator->p; + + color_stop->stop_offset = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); + + color_stop->color.palette_index = FT_NEXT_USHORT( p ); + + color_stop->color.alpha = FT_NEXT_SHORT( p ); + + if ( iterator->read_variable ) + { + /* Pointer p needs to be advanced independently of whether we intend */ + /* to take variable deltas into account or not. Otherwise iteration */ + /* would fail due to wrong offsets. */ + var_index_base = FT_NEXT_ULONG( p ); + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + { + FT_Int item_deltas[2]; + + + if ( !get_deltas_for_var_index_base( face, colr, + var_index_base, + 2, + item_deltas ) ) + return 0; + + color_stop->stop_offset += F2DOT14_TO_FIXED( item_deltas[0] ); + color_stop->color.alpha += (FT_F2Dot14)item_deltas[1]; + } +#else + FT_UNUSED( var_index_base ); +#endif + } + + iterator->p = p; + iterator->current_color_stop++; + + return 1; + } + + + FT_LOCAL_DEF( FT_Bool ) + tt_face_get_paint( TT_Face face, + FT_OpaquePaint opaque_paint, + FT_COLR_Paint* paint ) + { + Colr* colr = (Colr*)face->colr; + FT_OpaquePaint next_paint; + FT_Matrix ft_root_scale; + + if ( !colr || !colr->base_glyphs_v1 || !colr->table ) + return 0; + + if ( opaque_paint.insert_root_transform ) + { + /* 'COLR' v1 glyph information is returned in unscaled coordinates, + * i.e., `FT_Size` is not applied or multiplied into the values. When + * client applications draw color glyphs, they can request to include + * a top-level transform, which includes the active `x_scale` and + * `y_scale` information for scaling the glyph, as well the additional + * transform and translate configured through `FT_Set_Transform`. + * This allows client applications to apply this top-level transform + * to the graphics context first and only once, then have gradient and + * contour scaling applied correctly when performing the additional + * drawing operations for subsequenct paints. Prepare this initial + * transform here. + */ + paint->format = FT_COLR_PAINTFORMAT_TRANSFORM; + + next_paint.p = opaque_paint.p; + next_paint.insert_root_transform = 0; + paint->u.transform.paint = next_paint; + + /* `x_scale` and `y_scale` are in 26.6 format, representing the scale + * factor to get from font units to requested size. However, expected + * return values are in 16.16, so we shift accordingly with rounding. + */ + ft_root_scale.xx = ( face->root.size->metrics.x_scale + 32 ) >> 6; + ft_root_scale.xy = 0; + ft_root_scale.yx = 0; + ft_root_scale.yy = ( face->root.size->metrics.y_scale + 32 ) >> 6; + + if ( face->root.internal->transform_flags & 1 ) + FT_Matrix_Multiply( &face->root.internal->transform_matrix, + &ft_root_scale ); + + paint->u.transform.affine.xx = ft_root_scale.xx; + paint->u.transform.affine.xy = ft_root_scale.xy; + paint->u.transform.affine.yx = ft_root_scale.yx; + paint->u.transform.affine.yy = ft_root_scale.yy; + + /* The translation is specified in 26.6 format and, according to the + * documentation of `FT_Set_Translate`, is performed on the character + * size given in the last call to `FT_Set_Char_Size`. The + * 'PaintTransform' paint table's `FT_Affine23` format expects + * values in 16.16 format, thus we need to shift by 10 bits. + */ + if ( face->root.internal->transform_flags & 2 ) + { + paint->u.transform.affine.dx = + face->root.internal->transform_delta.x * ( 1 << 10 ); + paint->u.transform.affine.dy = + face->root.internal->transform_delta.y * ( 1 << 10 ); + } + else + { + paint->u.transform.affine.dx = 0; + paint->u.transform.affine.dy = 0; + } + + return 1; + } + + return read_paint( face, colr, opaque_paint.p, paint ); + } + + FT_LOCAL_DEF( FT_Error ) tt_face_colr_blend_layer( TT_Face face, FT_UInt color_index, @@ -443,7 +1914,7 @@ #else /* !TT_CONFIG_OPTION_COLOR_LAYERS */ /* ANSI C doesn't like empty source files */ - typedef int _tt_colr_dummy; + typedef int tt_colr_dummy_; #endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */ diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttcolr.h b/lib/libesp32_lvgl/freetype/src/sfnt/ttcolr.h index 641216266..20c85f035 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttcolr.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttcolr.h @@ -4,7 +4,7 @@ * * TrueType and OpenType colored glyph layer support (specification). * - * Copyright (C) 2018-2020 by + * Copyright (C) 2018-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Originally written by Shao Yu Zhang . @@ -42,6 +42,32 @@ FT_BEGIN_HEADER FT_UInt *acolor_index, FT_LayerIterator* iterator ); + FT_LOCAL( FT_Bool ) + tt_face_get_colr_glyph_paint( TT_Face face, + FT_UInt base_glyph, + FT_Color_Root_Transform root_transform, + FT_OpaquePaint* paint ); + + FT_LOCAL( FT_Bool ) + tt_face_get_color_glyph_clipbox( TT_Face face, + FT_UInt base_glyph, + FT_ClipBox* clip_box ); + + FT_LOCAL( FT_Bool ) + tt_face_get_paint_layers( TT_Face face, + FT_LayerIterator* iterator, + FT_OpaquePaint* paint ); + + FT_LOCAL( FT_Bool ) + tt_face_get_colorline_stops( TT_Face face, + FT_ColorStop* color_stop, + FT_ColorStopIterator* iterator ); + + FT_LOCAL( FT_Bool ) + tt_face_get_paint( TT_Face face, + FT_OpaquePaint opaque_paint, + FT_COLR_Paint* paint ); + FT_LOCAL( FT_Error ) tt_face_colr_blend_layer( TT_Face face, FT_UInt color_index, diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttcpal.c b/lib/libesp32_lvgl/freetype/src/sfnt/ttcpal.c index 9c514bafe..46ae08596 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttcpal.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttcpal.c @@ -4,7 +4,7 @@ * * TrueType and OpenType color palette support (body). * - * Copyright (C) 2018-2020 by + * Copyright (C) 2018-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Originally written by Shao Yu Zhang . @@ -303,7 +303,7 @@ #else /* !TT_CONFIG_OPTION_COLOR_LAYERS */ /* ANSI C doesn't like empty source files */ - typedef int _tt_cpal_dummy; + typedef int tt_cpal_dummy_; #endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */ diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttcpal.h b/lib/libesp32_lvgl/freetype/src/sfnt/ttcpal.h index b544be696..8e9913f0c 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttcpal.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttcpal.h @@ -4,7 +4,7 @@ * * TrueType and OpenType color palette support (specification). * - * Copyright (C) 2018-2020 by + * Copyright (C) 2018-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Originally written by Shao Yu Zhang . diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttkern.c b/lib/libesp32_lvgl/freetype/src/sfnt/ttkern.c index d4a70c785..a47d08bd6 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttkern.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttkern.c @@ -5,7 +5,7 @@ * Load the basic TrueType kerning table. This doesn't handle * kerning data within the GPOS table at the moment. * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -94,7 +94,7 @@ p_next = p; - p += 2; /* skip version */ + p += 2; /* skip version */ length = FT_NEXT_USHORT( p ); coverage = FT_NEXT_USHORT( p ); @@ -144,7 +144,7 @@ cur_pair = FT_NEXT_ULONG( p ); - if ( cur_pair <= old_pair ) + if ( cur_pair < old_pair ) break; p += 2; @@ -187,11 +187,18 @@ FT_UInt left_glyph, FT_UInt right_glyph ) { - FT_Int result = 0; - FT_UInt count, mask; - FT_Byte* p = face->kern_table; - FT_Byte* p_limit = p + face->kern_table_size; + FT_Int result = 0; + FT_UInt count, mask; + FT_Byte* p; + FT_Byte* p_limit; + + + if ( !face->kern_table ) + return result; + + p = face->kern_table; + p_limit = p + face->kern_table_size; p += 4; mask = 0x0001; diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttkern.h b/lib/libesp32_lvgl/freetype/src/sfnt/ttkern.h index f44b5bdeb..960c7da49 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttkern.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttkern.h @@ -5,7 +5,7 @@ * Load the basic TrueType kerning table. This doesn't handle * kerning data within the GPOS table at the moment. * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttload.c b/lib/libesp32_lvgl/freetype/src/sfnt/ttload.c index 4b46f4135..7b44e9cd2 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttload.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttload.c @@ -5,7 +5,7 @@ * Load the basic TrueType tables, i.e., tables that can be either in * TTF or OTF fonts (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -205,9 +205,8 @@ if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) ) { - nn--; FT_TRACE2(( "check_table_dir:" - " can read only %d table%s in font (instead of %d)\n", + " can read only %hu table%s in font (instead of %hu)\n", nn, nn == 1 ? "" : "s", sfnt->num_tables )); sfnt->num_tables = nn; break; @@ -217,7 +216,7 @@ if ( table.Offset > stream->size ) { - FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn )); + FT_TRACE2(( "check_table_dir: table entry %hu invalid\n", nn )); continue; } else if ( table.Length > stream->size - table.Offset ) @@ -232,7 +231,7 @@ valid_entries++; else { - FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn )); + FT_TRACE2(( "check_table_dir: table entry %hu invalid\n", nn )); continue; } } @@ -381,7 +380,7 @@ /* load the table directory */ - FT_TRACE2(( "-- Number of tables: %10u\n", sfnt.num_tables )); + FT_TRACE2(( "-- Number of tables: %10hu\n", sfnt.num_tables )); FT_TRACE2(( "-- Format version: 0x%08lx\n", sfnt.format_tag )); if ( sfnt.format_tag != TTAG_OTTO ) @@ -416,9 +415,9 @@ FT_FRAME_ENTER( sfnt.num_tables * 16L ) ) goto Exit; - FT_TRACE2(( "\n" - " tag offset length checksum\n" - " ----------------------------------\n" )); + FT_TRACE2(( "\n" )); + FT_TRACE2(( " tag offset length checksum\n" )); + FT_TRACE2(( " ----------------------------------\n" )); valid_entries = 0; for ( nn = 0; nn < sfnt.num_tables; nn++ ) @@ -505,7 +504,15 @@ FT_FRAME_EXIT(); - FT_TRACE2(( "table directory loaded\n\n" )); + if ( !valid_entries ) + { + FT_TRACE2(( "tt_face_load_font_dir: no valid tables found\n" )); + error = FT_THROW( Unknown_File_Format ); + goto Exit; + } + + FT_TRACE2(( "table directory loaded\n" )); + FT_TRACE2(( "\n" )); Exit: return error; @@ -671,8 +678,8 @@ if ( FT_STREAM_READ_FIELDS( header_fields, header ) ) goto Exit; - FT_TRACE3(( "Units per EM: %4u\n", header->Units_Per_EM )); - FT_TRACE3(( "IndexToLoc: %4d\n", header->Index_To_Loc_Format )); + FT_TRACE3(( "Units per EM: %4hu\n", header->Units_Per_EM )); + FT_TRACE3(( "IndexToLoc: %4hd\n", header->Index_To_Loc_Format )); Exit: return error; @@ -794,15 +801,15 @@ if ( maxProfile->maxTwilightPoints > ( 0xFFFFU - 4 ) ) { FT_TRACE0(( "tt_face_load_maxp:" - " too much twilight points in `maxp' table;\n" - " " + " too much twilight points in `maxp' table;\n" )); + FT_TRACE0(( " " " some glyphs might be rendered incorrectly\n" )); maxProfile->maxTwilightPoints = 0xFFFFU - 4; } } - FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs )); + FT_TRACE3(( "numGlyphs: %hu\n", maxProfile->numGlyphs )); Exit: return error; @@ -836,6 +843,8 @@ FT_ULong table_pos, table_len; FT_ULong storage_start, storage_limit; TT_NameTable table; + TT_Name names = NULL; + TT_LangTag langTags = NULL; static const FT_Frame_Field name_table_fields[] = { @@ -916,13 +925,13 @@ storage_start += 2 + 4 * table->numLangTagRecords; /* allocate language tag records array */ - if ( FT_NEW_ARRAY( table->langTags, table->numLangTagRecords ) || - FT_FRAME_ENTER( table->numLangTagRecords * 4 ) ) + if ( FT_QNEW_ARRAY( langTags, table->numLangTagRecords ) || + FT_FRAME_ENTER( table->numLangTagRecords * 4 ) ) goto Exit; /* load language tags */ { - TT_LangTag entry = table->langTags; + TT_LangTag entry = langTags; TT_LangTag limit = FT_OFFSET( entry, table->numLangTagRecords ); @@ -938,7 +947,13 @@ /* invalid entry; ignore it */ entry->stringLength = 0; } + + /* mark the string as not yet loaded */ + entry->string = NULL; } + + table->langTags = langTags; + langTags = NULL; } FT_FRAME_EXIT(); @@ -947,14 +962,15 @@ } /* allocate name records array */ - if ( FT_NEW_ARRAY( table->names, table->numNameRecords ) || - FT_FRAME_ENTER( table->numNameRecords * 12 ) ) + if ( FT_QNEW_ARRAY( names, table->numNameRecords ) || + FT_FRAME_ENTER( table->numNameRecords * 12 ) ) goto Exit; /* load name records */ { - TT_Name entry = table->names; + TT_Name entry = names; FT_UInt count = table->numNameRecords; + FT_UInt valid = 0; for ( ; count > 0; count-- ) @@ -987,15 +1003,20 @@ } } + /* mark the string as not yet converted */ + entry->string = NULL; + + valid++; entry++; } /* reduce array size to the actually used elements */ - count = (FT_UInt)( entry - table->names ); - (void)FT_RENEW_ARRAY( table->names, - table->numNameRecords, - count ); - table->numNameRecords = count; + FT_MEM_QRENEW_ARRAY( names, + table->numNameRecords, + valid ); + table->names = names; + names = NULL; + table->numNameRecords = valid; } FT_FRAME_EXIT(); @@ -1004,6 +1025,8 @@ face->num_names = (FT_UShort)table->numNameRecords; Exit: + FT_FREE( names ); + FT_FREE( langTags ); return error; } @@ -1249,11 +1272,11 @@ } } - FT_TRACE3(( "sTypoAscender: %4d\n", os2->sTypoAscender )); - FT_TRACE3(( "sTypoDescender: %4d\n", os2->sTypoDescender )); - FT_TRACE3(( "usWinAscent: %4u\n", os2->usWinAscent )); - FT_TRACE3(( "usWinDescent: %4u\n", os2->usWinDescent )); - FT_TRACE3(( "fsSelection: 0x%2x\n", os2->fsSelection )); + FT_TRACE3(( "sTypoAscender: %4hd\n", os2->sTypoAscender )); + FT_TRACE3(( "sTypoDescender: %4hd\n", os2->sTypoDescender )); + FT_TRACE3(( "usWinAscent: %4hu\n", os2->usWinAscent )); + FT_TRACE3(( "usWinDescent: %4hu\n", os2->usWinDescent )); + FT_TRACE3(( "fsSelection: 0x%2hx\n", os2->fsSelection )); Exit: return error; @@ -1311,6 +1334,12 @@ if ( FT_STREAM_READ_FIELDS( post_fields, post ) ) return error; + if ( post->FormatType != 0x00030000L && + post->FormatType != 0x00025000L && + post->FormatType != 0x00020000L && + post->FormatType != 0x00010000L ) + return FT_THROW( Invalid_Post_Table_Format ); + /* we don't load the glyph names, we do that in another */ /* module (ttpost). */ @@ -1410,8 +1439,8 @@ FT_Error error; FT_Memory memory = stream->memory; - FT_UInt j,num_ranges; - TT_GaspRange gaspranges = NULL; + FT_UShort j, num_ranges; + TT_GaspRange gasp_ranges = NULL; /* the gasp table is optional */ @@ -1422,8 +1451,8 @@ if ( FT_FRAME_ENTER( 4L ) ) goto Exit; - face->gasp.version = FT_GET_USHORT(); - face->gasp.numRanges = FT_GET_USHORT(); + face->gasp.version = FT_GET_USHORT(); + num_ranges = FT_GET_USHORT(); FT_FRAME_EXIT(); @@ -1435,29 +1464,31 @@ goto Exit; } - num_ranges = face->gasp.numRanges; - FT_TRACE3(( "numRanges: %u\n", num_ranges )); + FT_TRACE3(( "numRanges: %hu\n", num_ranges )); - if ( FT_QNEW_ARRAY( face->gasp.gaspRanges, num_ranges ) || - FT_FRAME_ENTER( num_ranges * 4L ) ) + if ( FT_QNEW_ARRAY( gasp_ranges, num_ranges ) || + FT_FRAME_ENTER( num_ranges * 4L ) ) goto Exit; - gaspranges = face->gasp.gaspRanges; - for ( j = 0; j < num_ranges; j++ ) { - gaspranges[j].maxPPEM = FT_GET_USHORT(); - gaspranges[j].gaspFlag = FT_GET_USHORT(); + gasp_ranges[j].maxPPEM = FT_GET_USHORT(); + gasp_ranges[j].gaspFlag = FT_GET_USHORT(); - FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n", + FT_TRACE3(( "gaspRange %hu: rangeMaxPPEM %5hu, rangeGaspBehavior 0x%hx\n", j, - gaspranges[j].maxPPEM, - gaspranges[j].gaspFlag )); + gasp_ranges[j].maxPPEM, + gasp_ranges[j].gaspFlag )); } + face->gasp.gaspRanges = gasp_ranges; + gasp_ranges = NULL; + face->gasp.numRanges = num_ranges; + FT_FRAME_EXIT(); Exit: + FT_FREE( gasp_ranges ); return error; } diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttload.h b/lib/libesp32_lvgl/freetype/src/sfnt/ttload.h index 4e53d8b78..1499dd573 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttload.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttload.h @@ -5,7 +5,7 @@ * Load the basic TrueType tables, i.e., tables that can be either in * TTF or OTF fonts (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttmtx.c b/lib/libesp32_lvgl/freetype/src/sfnt/ttmtx.c index 021123336..38ee9ae72 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttmtx.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttmtx.c @@ -4,7 +4,7 @@ * * Load the metrics tables common to TTF and OTF fonts (body). * - * Copyright (C) 2006-2020 by + * Copyright (C) 2006-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -239,7 +239,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_Service_MetricsVariations var = - (FT_Service_MetricsVariations)face->var; + (FT_Service_MetricsVariations)face->tt_var; #endif @@ -306,7 +306,7 @@ } #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( var ) + if ( var && face->blend ) { FT_Face f = FT_FACE( face ); FT_Int a = (FT_Int)*aadvance; diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttmtx.h b/lib/libesp32_lvgl/freetype/src/sfnt/ttmtx.h index dba65ca9b..56d2b6276 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttmtx.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttmtx.h @@ -4,7 +4,7 @@ * * Load the metrics tables common to TTF and OTF fonts (specification). * - * Copyright (C) 2006-2020 by + * Copyright (C) 2006-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttpost.c b/lib/libesp32_lvgl/freetype/src/sfnt/ttpost.c index e93a4bf1b..1dfad4298 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttpost.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttpost.c @@ -5,7 +5,7 @@ * PostScript name table processing for TrueType and OpenType fonts * (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -58,7 +58,7 @@ #define MAC_NAME( x ) (FT_String*)psnames->macintosh_name( (FT_UInt)(x) ) -#else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ +#else /* !FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ /* Otherwise, we ignore the `psnames' module, and provide our own */ @@ -152,155 +152,109 @@ }; -#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ +#endif /* !FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ static FT_Error - load_format_20( TT_Face face, - FT_Stream stream, - FT_ULong post_limit ) + load_format_20( TT_Post_Names names, + FT_Stream stream, + FT_UShort num_glyphs, + FT_ULong post_len ) { FT_Memory memory = stream->memory; FT_Error error; - FT_Int num_glyphs; - FT_UShort num_names; + FT_UShort n; + FT_UShort num_names = 0; FT_UShort* glyph_indices = NULL; - FT_Char** name_strings = NULL; + FT_Byte** name_strings = NULL; + FT_Byte* q; - if ( FT_READ_USHORT( num_glyphs ) ) - goto Exit; - - /* UNDOCUMENTED! The number of glyphs in this table can be smaller */ - /* than the value in the maxp table (cf. cyberbit.ttf). */ - - /* There already exist fonts which have more than 32768 glyph names */ - /* in this table, so the test for this threshold has been dropped. */ - - if ( num_glyphs > face->max_profile.numGlyphs ) + if ( (FT_ULong)num_glyphs * 2 > post_len ) { error = FT_THROW( Invalid_File_Format ); goto Exit; } - /* load the indices */ + /* load the indices and note their maximum */ + if ( FT_QNEW_ARRAY( glyph_indices, num_glyphs ) || + FT_FRAME_ENTER( num_glyphs * 2 ) ) + goto Fail; + + q = (FT_Byte*)stream->cursor; + + for ( n = 0; n < num_glyphs; n++ ) { - FT_Int n; + FT_UShort idx = FT_NEXT_USHORT( q ); - if ( FT_NEW_ARRAY ( glyph_indices, num_glyphs ) || - FT_FRAME_ENTER( num_glyphs * 2L ) ) - goto Fail; + if ( idx > num_names ) + num_names = idx; - for ( n = 0; n < num_glyphs; n++ ) - glyph_indices[n] = FT_GET_USHORT(); - - FT_FRAME_EXIT(); + glyph_indices[n] = idx; } - /* compute number of names stored in table */ - { - FT_Int n; + FT_FRAME_EXIT(); - - num_names = 0; - - for ( n = 0; n < num_glyphs; n++ ) - { - FT_Int idx; - - - idx = glyph_indices[n]; - if ( idx >= 258 ) - { - idx -= 257; - if ( idx > num_names ) - num_names = (FT_UShort)idx; - } - } - } + /* compute number of names stored in the table */ + num_names = num_names > 257 ? num_names - 257 : 0; /* now load the name strings */ + if ( num_names ) { - FT_UShort n; + FT_ULong p; + FT_Byte* strings; - if ( FT_NEW_ARRAY( name_strings, num_names ) ) + post_len -= (FT_ULong)num_glyphs * 2; + + if ( FT_QALLOC( name_strings, num_names * sizeof ( FT_Byte* ) + + post_len + 1 ) ) goto Fail; - for ( n = 0; n < num_names; n++ ) + strings = (FT_Byte*)( name_strings + num_names ); + if ( FT_STREAM_READ( strings, post_len ) ) + goto Fail; + + /* convert from Pascal- to C-strings and set pointers */ + for ( p = 0, n = 0; p < post_len && n < num_names; n++ ) { - FT_UInt len; + FT_UInt len = strings[p]; - if ( FT_STREAM_POS() >= post_limit ) - break; - else + if ( len > 63U ) { - FT_TRACE6(( "load_format_20: %ld byte left in post table\n", - post_limit - FT_STREAM_POS() )); - - if ( FT_READ_BYTE( len ) ) - goto Fail1; + error = FT_THROW( Invalid_File_Format ); + goto Fail; } - if ( len > post_limit || - FT_STREAM_POS() > post_limit - len ) - { - FT_Int d = (FT_Int)post_limit - (FT_Int)FT_STREAM_POS(); - - - FT_ERROR(( "load_format_20:" - " exceeding string length (%d)," - " truncating at end of post table (%d byte left)\n", - len, d )); - len = (FT_UInt)FT_MAX( 0, d ); - } - - if ( FT_NEW_ARRAY( name_strings[n], len + 1 ) || - FT_STREAM_READ( name_strings[n], len ) ) - goto Fail1; - - name_strings[n][len] = '\0'; + strings[p] = 0; + name_strings[n] = strings + p + 1; + p += len + 1; } + strings[post_len] = 0; + /* deal with missing or insufficient string data */ if ( n < num_names ) { - FT_ERROR(( "load_format_20:" - " all entries in post table are already parsed," - " using NULL names for gid %d - %d\n", - n, num_names - 1 )); + FT_TRACE4(( "load_format_20: %hu PostScript names are truncated\n", + num_names - n )); + for ( ; n < num_names; n++ ) - if ( FT_NEW_ARRAY( name_strings[n], 1 ) ) - goto Fail1; - else - name_strings[n][0] = '\0'; + name_strings[n] = strings + post_len; } } /* all right, set table fields and exit successfully */ - { - TT_Post_20 table = &face->postscript_names.names.format_20; + names->num_glyphs = num_glyphs; + names->num_names = num_names; + names->glyph_indices = glyph_indices; + names->glyph_names = name_strings; - - table->num_glyphs = (FT_UShort)num_glyphs; - table->num_names = (FT_UShort)num_names; - table->glyph_indices = glyph_indices; - table->glyph_names = name_strings; - } return FT_Err_Ok; - Fail1: - { - FT_UShort n; - - - for ( n = 0; n < num_names; n++ ) - FT_FREE( name_strings[n] ); - } - Fail: FT_FREE( name_strings ); FT_FREE( glyph_indices ); @@ -311,66 +265,55 @@ static FT_Error - load_format_25( TT_Face face, - FT_Stream stream, - FT_ULong post_limit ) + load_format_25( TT_Post_Names names, + FT_Stream stream, + FT_UShort num_glyphs, + FT_ULong post_len ) { FT_Memory memory = stream->memory; FT_Error error; - FT_Int num_glyphs; - FT_Char* offset_table = NULL; - - FT_UNUSED( post_limit ); + FT_UShort n; + FT_UShort* glyph_indices = NULL; + FT_Byte* q; - if ( FT_READ_USHORT( num_glyphs ) ) - goto Exit; - - /* check the number of glyphs */ - if ( num_glyphs > face->max_profile.numGlyphs || - num_glyphs > 258 || - num_glyphs < 1 ) + /* check the number of glyphs, including the theoretical limit */ + if ( num_glyphs > post_len || + num_glyphs > 258 + 128 ) { error = FT_THROW( Invalid_File_Format ); goto Exit; } - if ( FT_NEW_ARRAY( offset_table, num_glyphs ) || - FT_STREAM_READ( offset_table, num_glyphs ) ) + /* load the indices and check their Mac range */ + if ( FT_QNEW_ARRAY( glyph_indices, num_glyphs ) || + FT_FRAME_ENTER( num_glyphs ) ) goto Fail; - /* now check the offset table */ + q = (FT_Byte*)stream->cursor; + + for ( n = 0; n < num_glyphs; n++ ) { - FT_Int n; + FT_Int idx = n + FT_NEXT_CHAR( q ); - for ( n = 0; n < num_glyphs; n++ ) - { - FT_Long idx = (FT_Long)n + offset_table[n]; + if ( idx < 0 || idx > 257 ) + idx = 0; - - if ( idx < 0 || idx > num_glyphs ) - { - error = FT_THROW( Invalid_File_Format ); - goto Fail; - } - } + glyph_indices[n] = (FT_UShort)idx; } + FT_FRAME_EXIT(); + /* OK, set table fields and exit successfully */ - { - TT_Post_25 table = &face->postscript_names.names.format_25; - - - table->num_glyphs = (FT_UShort)num_glyphs; - table->offsets = offset_table; - } + names->num_glyphs = num_glyphs; + names->glyph_indices = glyph_indices; return FT_Err_Ok; Fail: - FT_FREE( offset_table ); + FT_FREE( glyph_indices ); Exit: return error; @@ -380,40 +323,37 @@ static FT_Error load_post_names( TT_Face face ) { - FT_Stream stream; - FT_Error error; - FT_Fixed format; + FT_Error error = FT_Err_Ok; + FT_Stream stream = face->root.stream; + FT_Fixed format = face->postscript.FormatType; FT_ULong post_len; - FT_ULong post_limit; + FT_UShort num_glyphs; - /* get a stream for the face's resource */ - stream = face->root.stream; - /* seek to the beginning of the PS names table */ error = face->goto_table( face, TTAG_post, stream, &post_len ); if ( error ) goto Exit; - post_limit = FT_STREAM_POS() + post_len; - - format = face->postscript.FormatType; - - /* go to beginning of subtable */ - if ( FT_STREAM_SKIP( 32 ) ) + /* UNDOCUMENTED! The number of glyphs in this table can be smaller */ + /* than the value in the maxp table (cf. cyberbit.ttf). */ + if ( post_len < 34 || + FT_STREAM_SKIP( 32 ) || + FT_READ_USHORT( num_glyphs ) || + num_glyphs > face->max_profile.numGlyphs || + num_glyphs == 0 ) goto Exit; - /* now read postscript table */ + /* now read postscript names data */ if ( format == 0x00020000L ) - error = load_format_20( face, stream, post_limit ); + error = load_format_20( &face->postscript_names, stream, + num_glyphs, post_len - 34 ); else if ( format == 0x00025000L ) - error = load_format_25( face, stream, post_limit ); - else - error = FT_THROW( Invalid_File_Format ); - - face->postscript_names.loaded = 1; + error = load_format_25( &face->postscript_names, stream, + num_glyphs, post_len - 34 ); Exit: + face->postscript_names.loaded = 1; /* even if failed */ return error; } @@ -423,37 +363,20 @@ { FT_Memory memory = face->root.memory; TT_Post_Names names = &face->postscript_names; - FT_Fixed format; - if ( names->loaded ) + if ( names->num_glyphs ) { - format = face->postscript.FormatType; - - if ( format == 0x00020000L ) - { - TT_Post_20 table = &names->names.format_20; - FT_UShort n; - - - FT_FREE( table->glyph_indices ); - table->num_glyphs = 0; - - for ( n = 0; n < table->num_names; n++ ) - FT_FREE( table->glyph_names[n] ); - - FT_FREE( table->glyph_names ); - table->num_names = 0; - } - else if ( format == 0x00025000L ) - { - TT_Post_25 table = &names->names.format_25; - - - FT_FREE( table->offsets ); - table->num_glyphs = 0; - } + FT_FREE( names->glyph_indices ); + names->num_glyphs = 0; } + + if ( names->num_names ) + { + FT_FREE( names->glyph_names ); + names->num_names = 0; + } + names->loaded = 0; } @@ -489,7 +412,6 @@ FT_String** PSname ) { FT_Error error; - TT_Post_Names names; FT_Fixed format; #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES @@ -509,8 +431,6 @@ return FT_THROW( Unimplemented_Feature ); #endif - names = &face->postscript_names; - /* `.notdef' by default */ *PSname = MAC_NAME( 0 ); @@ -521,9 +441,10 @@ if ( idx < 258 ) /* paranoid checking */ *PSname = MAC_NAME( idx ); } - else if ( format == 0x00020000L ) + else if ( format == 0x00020000L || + format == 0x00025000L ) { - TT_Post_20 table = &names->names.format_20; + TT_Post_Names names = &face->postscript_names; if ( !names->loaded ) @@ -533,43 +454,29 @@ goto End; } - if ( idx < (FT_UInt)table->num_glyphs ) + if ( idx < (FT_UInt)names->num_glyphs ) { - FT_UShort name_index = table->glyph_indices[idx]; + FT_UShort name_index = names->glyph_indices[idx]; if ( name_index < 258 ) *PSname = MAC_NAME( name_index ); - else - *PSname = (FT_String*)table->glyph_names[name_index - 258]; + else /* only for version 2.0 */ + *PSname = (FT_String*)names->glyph_names[name_index - 258]; } } - else if ( format == 0x00025000L ) - { - TT_Post_25 table = &names->names.format_25; - - - if ( !names->loaded ) - { - error = load_post_names( face ); - if ( error ) - goto End; - } - - if ( idx < (FT_UInt)table->num_glyphs ) /* paranoid checking */ - *PSname = MAC_NAME( (FT_Int)idx + table->offsets[idx] ); - } /* nothing to do for format == 0x00030000L */ End: + /* post format errors ignored */ return FT_Err_Ok; } #else /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ /* ANSI C doesn't like empty source files */ - typedef int _tt_post_dummy; + typedef int tt_post_dummy_; #endif /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttpost.h b/lib/libesp32_lvgl/freetype/src/sfnt/ttpost.h index 94c7d1680..528f1c5f2 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttpost.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttpost.h @@ -5,7 +5,7 @@ * PostScript name table processing for TrueType and OpenType fonts * (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttsbit.c b/lib/libesp32_lvgl/freetype/src/sfnt/ttsbit.c index 9dd441971..03f90a628 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttsbit.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttsbit.c @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded bitmap support (body). * - * Copyright (C) 2005-2020 by + * Copyright (C) 2005-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Copyright 2013 by Google, Inc. @@ -172,13 +172,8 @@ goto Exit; } - /* we currently don't support bit 1; however, it is better to */ - /* draw at least something... */ if ( flags == 3 ) - FT_TRACE1(( "tt_face_load_sbit_strikes:" - " sbix overlay not supported yet\n" - " " - " expect bad rendering results\n" )); + face->root.face_flags |= FT_FACE_FLAG_SBIX_OVERLAY; /* * Count the number of strikes available in the table. We are a bit @@ -240,8 +235,8 @@ if ( !face->ebdt_size ) { FT_TRACE2(( "tt_face_load_sbit_strikes:" - " no embedded bitmap data table found;\n" - " " + " no embedded bitmap data table found;\n" )); + FT_TRACE2(( " " " resetting number of strikes to zero\n" )); face->sbit_num_strikes = 0; } @@ -345,8 +340,8 @@ if ( metrics->ascender == 0 ) { FT_TRACE2(( "tt_face_load_strike_metrics:" - " sanitizing invalid ascender and descender\n" - " " + " sanitizing invalid ascender and descender\n" )); + FT_TRACE2(( " " " values for strike %ld (%dppem, %dppem)\n", strike_index, metrics->x_ppem, metrics->y_ppem )); @@ -374,8 +369,8 @@ if ( metrics->height == 0 ) { FT_TRACE2(( "tt_face_load_strike_metrics:" - " sanitizing invalid height value\n" - " " + " sanitizing invalid height value\n" )); + FT_TRACE2(( " " " for strike (%d, %d)\n", metrics->x_ppem, metrics->y_ppem )); metrics->height = metrics->y_ppem * 64; @@ -390,11 +385,9 @@ /* set the scale values (in 16.16 units) so advances */ /* from the hmtx and vmtx table are scaled correctly */ - metrics->x_scale = FT_MulDiv( metrics->x_ppem, - 64 * 0x10000, + metrics->x_scale = FT_DivFix( metrics->x_ppem * 64, face->header.Units_Per_EM ); - metrics->y_scale = FT_MulDiv( metrics->y_ppem, - 64 * 0x10000, + metrics->y_scale = FT_DivFix( metrics->y_ppem * 64, face->header.Units_Per_EM ); return FT_Err_Ok; @@ -404,9 +397,9 @@ { FT_Stream stream = face->root.stream; FT_UInt offset; - FT_UShort upem, ppem, resolution; + FT_UShort ppem, resolution; TT_HoriHeader *hori; - FT_Pos ppem_; /* to reduce casts */ + FT_Fixed scale; FT_Error error; FT_Byte* p; @@ -429,32 +422,23 @@ FT_FRAME_EXIT(); - upem = face->header.Units_Per_EM; - hori = &face->horizontal; - metrics->x_ppem = ppem; metrics->y_ppem = ppem; - ppem_ = (FT_Pos)ppem; + scale = FT_DivFix( ppem * 64, face->header.Units_Per_EM ); + hori = &face->horizontal; - metrics->ascender = - FT_MulDiv( hori->Ascender, ppem_ * 64, upem ); - metrics->descender = - FT_MulDiv( hori->Descender, ppem_ * 64, upem ); - metrics->height = - FT_MulDiv( hori->Ascender - hori->Descender + hori->Line_Gap, - ppem_ * 64, upem ); - metrics->max_advance = - FT_MulDiv( hori->advance_Width_Max, ppem_ * 64, upem ); + metrics->ascender = FT_MulFix( hori->Ascender, scale ); + metrics->descender = FT_MulFix( hori->Descender, scale ); + metrics->height = + FT_MulFix( hori->Ascender - hori->Descender + hori->Line_Gap, + scale ); + metrics->max_advance = FT_MulFix( hori->advance_Width_Max, scale ); /* set the scale values (in 16.16 units) so advances */ /* from the hmtx and vmtx table are scaled correctly */ - metrics->x_scale = FT_MulDiv( metrics->x_ppem, - 64 * 0x10000, - face->header.Units_Per_EM ); - metrics->y_scale = FT_MulDiv( metrics->y_ppem, - 64 * 0x10000, - face->header.Units_Per_EM ); + metrics->x_scale = scale; + metrics->y_scale = scale; return error; } @@ -726,6 +710,9 @@ pitch = bitmap->pitch; line = bitmap->buffer; + if ( !line ) + goto Exit; + width = decoder->metrics->width; height = decoder->metrics->height; @@ -1206,7 +1193,7 @@ goto Fail; p += 1; /* skip padding */ - /* fall-through */ + FALL_THROUGH; case 9: loader = tt_sbit_decoder_load_compound; @@ -1573,23 +1560,40 @@ if ( !error ) { - FT_Short abearing; + FT_Short abearing; /* not used here */ FT_UShort aadvance; tt_face_get_metrics( face, FALSE, glyph_index, &abearing, &aadvance ); metrics->horiBearingX = (FT_Short)originOffsetX; - metrics->horiBearingY = (FT_Short)( -originOffsetY + metrics->height ); + metrics->vertBearingX = (FT_Short)originOffsetX; + + metrics->horiBearingY = (FT_Short)( originOffsetY + metrics->height ); + metrics->vertBearingY = (FT_Short)originOffsetY; + metrics->horiAdvance = (FT_UShort)( aadvance * face->root.size->metrics.x_ppem / face->header.Units_Per_EM ); + + if ( face->vertical_info ) + tt_face_get_metrics( face, TRUE, glyph_index, &abearing, &aadvance ); + else if ( face->os2.version != 0xFFFFU ) + aadvance = (FT_UShort)FT_ABS( face->os2.sTypoAscender - + face->os2.sTypoDescender ); + else + aadvance = (FT_UShort)FT_ABS( face->horizontal.Ascender - + face->horizontal.Descender ); + + metrics->vertAdvance = (FT_UShort)( aadvance * + face->root.size->metrics.x_ppem / + face->header.Units_Per_EM ); } return error; } - FT_LOCAL( FT_Error ) + FT_LOCAL_DEF( FT_Error ) tt_face_load_sbit_image( TT_Face face, FT_ULong strike_index, FT_UInt glyph_index, @@ -1673,7 +1677,7 @@ #else /* !TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ /* ANSI C doesn't like empty source files */ - typedef int _tt_sbit_dummy; + typedef int tt_sbit_dummy_; #endif /* !TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttsbit.h b/lib/libesp32_lvgl/freetype/src/sfnt/ttsbit.h index b867e43a6..07e2db461 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/ttsbit.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttsbit.h @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded bitmap support (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttsvg.c b/lib/libesp32_lvgl/freetype/src/sfnt/ttsvg.c new file mode 100644 index 000000000..4461d483b --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttsvg.c @@ -0,0 +1,413 @@ +/**************************************************************************** + * + * ttsvg.c + * + * OpenType SVG Color (specification). + * + * Copyright (C) 2022-2023 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + + /************************************************************************** + * + * 'SVG' table specification: + * + * https://docs.microsoft.com/en-us/typography/opentype/spec/svg + * + */ + +#include +#include +#include +#include +#include +#include +#include + + +#ifdef FT_CONFIG_OPTION_SVG + +#include "ttsvg.h" + + + /* NOTE: These table sizes are given by the specification. */ +#define SVG_TABLE_HEADER_SIZE (10U) +#define SVG_DOCUMENT_RECORD_SIZE (12U) +#define SVG_DOCUMENT_LIST_MINIMUM_SIZE (2U + SVG_DOCUMENT_RECORD_SIZE) +#define SVG_MINIMUM_SIZE (SVG_TABLE_HEADER_SIZE + \ + SVG_DOCUMENT_LIST_MINIMUM_SIZE) + + + typedef struct Svg_ + { + FT_UShort version; /* table version (starting at 0) */ + FT_UShort num_entries; /* number of SVG document records */ + + FT_Byte* svg_doc_list; /* pointer to the start of SVG Document List */ + + void* table; /* memory that backs up SVG */ + FT_ULong table_size; + + } Svg; + + + /************************************************************************** + * + * The macro FT_COMPONENT is used in trace mode. It is an implicit + * parameter of the FT_TRACE() and FT_ERROR() macros, usued to print/log + * messages during execution. + */ +#undef FT_COMPONENT +#define FT_COMPONENT ttsvg + + + FT_LOCAL_DEF( FT_Error ) + tt_face_load_svg( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = face->root.memory; + + FT_ULong table_size; + FT_Byte* table = NULL; + FT_Byte* p = NULL; + Svg* svg = NULL; + FT_ULong offsetToSVGDocumentList; + + + error = face->goto_table( face, TTAG_SVG, stream, &table_size ); + if ( error ) + goto NoSVG; + + if ( table_size < SVG_MINIMUM_SIZE ) + goto InvalidTable; + + if ( FT_FRAME_EXTRACT( table_size, table ) ) + goto NoSVG; + + /* Allocate memory for the SVG object */ + if ( FT_NEW( svg ) ) + goto NoSVG; + + p = table; + svg->version = FT_NEXT_USHORT( p ); + offsetToSVGDocumentList = FT_NEXT_ULONG( p ); + + if ( offsetToSVGDocumentList < SVG_TABLE_HEADER_SIZE || + offsetToSVGDocumentList > table_size - + SVG_DOCUMENT_LIST_MINIMUM_SIZE ) + goto InvalidTable; + + svg->svg_doc_list = (FT_Byte*)( table + offsetToSVGDocumentList ); + + p = svg->svg_doc_list; + svg->num_entries = FT_NEXT_USHORT( p ); + + FT_TRACE3(( "version: %d\n", svg->version )); + FT_TRACE3(( "number of entries: %d\n", svg->num_entries )); + + if ( offsetToSVGDocumentList + 2U + + svg->num_entries * SVG_DOCUMENT_RECORD_SIZE > table_size ) + goto InvalidTable; + + svg->table = table; + svg->table_size = table_size; + + face->svg = svg; + face->root.face_flags |= FT_FACE_FLAG_SVG; + + return FT_Err_Ok; + + InvalidTable: + error = FT_THROW( Invalid_Table ); + + NoSVG: + FT_FRAME_RELEASE( table ); + FT_FREE( svg ); + face->svg = NULL; + + return error; + } + + + FT_LOCAL_DEF( void ) + tt_face_free_svg( TT_Face face ) + { + FT_Memory memory = face->root.memory; + FT_Stream stream = face->root.stream; + + Svg* svg = (Svg*)face->svg; + + + if ( svg ) + { + FT_FRAME_RELEASE( svg->table ); + FT_FREE( svg ); + } + } + + + typedef struct Svg_doc_ + { + FT_UShort start_glyph_id; + FT_UShort end_glyph_id; + + FT_ULong offset; + FT_ULong length; + + } Svg_doc; + + + static Svg_doc + extract_svg_doc( FT_Byte* stream ) + { + Svg_doc doc; + + + doc.start_glyph_id = FT_NEXT_USHORT( stream ); + doc.end_glyph_id = FT_NEXT_USHORT( stream ); + + doc.offset = FT_NEXT_ULONG( stream ); + doc.length = FT_NEXT_ULONG( stream ); + + return doc; + } + + + static FT_Int + compare_svg_doc( Svg_doc doc, + FT_UInt glyph_index ) + { + if ( glyph_index < doc.start_glyph_id ) + return -1; + else if ( glyph_index > doc.end_glyph_id ) + return 1; + else + return 0; + } + + + static FT_Error + find_doc( FT_Byte* document_records, + FT_UShort num_entries, + FT_UInt glyph_index, + FT_ULong *doc_offset, + FT_ULong *doc_length, + FT_UShort *start_glyph, + FT_UShort *end_glyph ) + { + FT_Error error; + + Svg_doc start_doc; + Svg_doc mid_doc = { 0, 0, 0, 0 }; /* pacify compiler */ + Svg_doc end_doc; + + FT_Bool found = FALSE; + FT_UInt i = 0; + + FT_UInt start_index = 0; + FT_UInt end_index = num_entries - 1; + FT_Int comp_res; + + + /* search algorithm */ + if ( num_entries == 0 ) + { + error = FT_THROW( Invalid_Table ); + return error; + } + + start_doc = extract_svg_doc( document_records + start_index * 12 ); + end_doc = extract_svg_doc( document_records + end_index * 12 ); + + if ( ( compare_svg_doc( start_doc, glyph_index ) == -1 ) || + ( compare_svg_doc( end_doc, glyph_index ) == 1 ) ) + { + error = FT_THROW( Invalid_Glyph_Index ); + return error; + } + + while ( start_index <= end_index ) + { + i = ( start_index + end_index ) / 2; + mid_doc = extract_svg_doc( document_records + i * 12 ); + comp_res = compare_svg_doc( mid_doc, glyph_index ); + + if ( comp_res == 1 ) + { + start_index = i + 1; + start_doc = extract_svg_doc( document_records + start_index * 4 ); + } + else if ( comp_res == -1 ) + { + end_index = i - 1; + end_doc = extract_svg_doc( document_records + end_index * 4 ); + } + else + { + found = TRUE; + break; + } + } + /* search algorithm end */ + + if ( found != TRUE ) + { + FT_TRACE5(( "SVG glyph not found\n" )); + error = FT_THROW( Invalid_Glyph_Index ); + } + else + { + *doc_offset = mid_doc.offset; + *doc_length = mid_doc.length; + + *start_glyph = mid_doc.start_glyph_id; + *end_glyph = mid_doc.end_glyph_id; + + error = FT_Err_Ok; + } + + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + tt_face_load_svg_doc( FT_GlyphSlot glyph, + FT_UInt glyph_index ) + { + FT_Error error = FT_Err_Ok; + TT_Face face = (TT_Face)glyph->face; + FT_Memory memory = face->root.memory; + Svg* svg = (Svg*)face->svg; + + FT_Byte* doc_list; + FT_ULong doc_limit; + + FT_Byte* doc; + FT_ULong doc_offset; + FT_ULong doc_length; + FT_UShort doc_start_glyph_id; + FT_UShort doc_end_glyph_id; + + FT_SVG_Document svg_document = (FT_SVG_Document)glyph->other; + + + FT_ASSERT( !( svg == NULL ) ); + + doc_list = svg->svg_doc_list; + + error = find_doc( doc_list + 2, svg->num_entries, glyph_index, + &doc_offset, &doc_length, + &doc_start_glyph_id, &doc_end_glyph_id ); + if ( error != FT_Err_Ok ) + goto Exit; + + doc_limit = svg->table_size - + (FT_ULong)( doc_list - (FT_Byte*)svg->table ); + if ( doc_offset > doc_limit || + doc_length > doc_limit - doc_offset ) + { + error = FT_THROW( Invalid_Table ); + goto Exit; + } + + doc = doc_list + doc_offset; + + if ( doc_length > 6 && + doc[0] == 0x1F && + doc[1] == 0x8B && + doc[2] == 0x08 ) + { +#ifdef FT_CONFIG_OPTION_USE_ZLIB + + FT_ULong uncomp_size; + FT_Byte* uncomp_buffer = NULL; + + + /* + * Get the size of the original document. This helps in allotting the + * buffer to accommodate the uncompressed version. The last 4 bytes + * of the compressed document are equal to the original size modulo + * 2^32. Since the size of SVG documents is less than 2^32 bytes we + * can use this accurately. The four bytes are stored in + * little-endian format. + */ + FT_TRACE4(( "SVG document is GZIP compressed\n" )); + uncomp_size = (FT_ULong)doc[doc_length - 1] << 24 | + (FT_ULong)doc[doc_length - 2] << 16 | + (FT_ULong)doc[doc_length - 3] << 8 | + (FT_ULong)doc[doc_length - 4]; + + if ( FT_QALLOC( uncomp_buffer, uncomp_size ) ) + goto Exit; + + error = FT_Gzip_Uncompress( memory, + uncomp_buffer, + &uncomp_size, + doc, + doc_length ); + if ( error ) + { + FT_FREE( uncomp_buffer ); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + + glyph->internal->flags |= FT_GLYPH_OWN_GZIP_SVG; + + doc = uncomp_buffer; + doc_length = uncomp_size; + +#else /* !FT_CONFIG_OPTION_USE_ZLIB */ + + error = FT_THROW( Unimplemented_Feature ); + goto Exit; + +#endif /* !FT_CONFIG_OPTION_USE_ZLIB */ + } + + svg_document->svg_document = doc; + svg_document->svg_document_length = doc_length; + + svg_document->metrics = glyph->face->size->metrics; + svg_document->units_per_EM = glyph->face->units_per_EM; + + svg_document->start_glyph_id = doc_start_glyph_id; + svg_document->end_glyph_id = doc_end_glyph_id; + + svg_document->transform.xx = 0x10000; + svg_document->transform.xy = 0; + svg_document->transform.yx = 0; + svg_document->transform.yy = 0x10000; + + svg_document->delta.x = 0; + svg_document->delta.y = 0; + + FT_TRACE5(( "start_glyph_id: %d\n", doc_start_glyph_id )); + FT_TRACE5(( "end_glyph_id: %d\n", doc_end_glyph_id )); + FT_TRACE5(( "svg_document:\n" )); + FT_TRACE5(( " %.*s\n", (FT_UInt)doc_length, doc )); + + glyph->other = svg_document; + + Exit: + return error; + } + +#else /* !FT_CONFIG_OPTION_SVG */ + + /* ANSI C doesn't like empty source files */ + typedef int tt_svg_dummy_; + +#endif /* !FT_CONFIG_OPTION_SVG */ + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/ttsvg.h b/lib/libesp32_lvgl/freetype/src/sfnt/ttsvg.h new file mode 100644 index 000000000..3f32321de --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/sfnt/ttsvg.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * + * ttsvg.h + * + * OpenType SVG Color (specification). + * + * Copyright (C) 2022-2023 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + +#ifndef TTSVG_H_ +#define TTSVG_H_ + +#include +#include + + +FT_BEGIN_HEADER + + FT_LOCAL( FT_Error ) + tt_face_load_svg( TT_Face face, + FT_Stream stream ); + + FT_LOCAL( void ) + tt_face_free_svg( TT_Face face ); + + FT_LOCAL( FT_Error ) + tt_face_load_svg_doc( FT_GlyphSlot glyph, + FT_UInt glyph_index ); + +FT_END_HEADER + +#endif /* TTSVG_H_ */ + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/woff2tags.c b/lib/libesp32_lvgl/freetype/src/sfnt/woff2tags.c index fd9f2e6c5..eeedd9906 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/woff2tags.c +++ b/lib/libesp32_lvgl/freetype/src/sfnt/woff2tags.c @@ -4,7 +4,7 @@ * * WOFF2 Font table tags (base). * - * Copyright (C) 2019-2020 by + * Copyright (C) 2019-2023 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -17,6 +17,9 @@ #include + +#ifdef FT_CONFIG_OPTION_USE_BROTLI + #include "woff2tags.h" /* @@ -28,10 +31,10 @@ * * for details. */ - FT_LOCAL_DEF( FT_ULong ) + FT_LOCAL_DEF( FT_Tag ) woff2_known_tags( FT_Byte index ) { - const FT_ULong known_tags[63] = + static const FT_Tag known_tags[63] = { FT_MAKE_TAG('c', 'm', 'a', 'p'), /* 0 */ FT_MAKE_TAG('h', 'e', 'a', 'd'), /* 1 */ @@ -105,5 +108,12 @@ return known_tags[index]; } +#else /* !FT_CONFIG_OPTION_USE_BROTLI */ + + /* ANSI C doesn't like empty source files */ + typedef int woff2tags_dummy_; + +#endif /* !FT_CONFIG_OPTION_USE_BROTLI */ + /* END */ diff --git a/lib/libesp32_lvgl/freetype/src/sfnt/woff2tags.h b/lib/libesp32_lvgl/freetype/src/sfnt/woff2tags.h index c437c77aa..1201848e5 100644 --- a/lib/libesp32_lvgl/freetype/src/sfnt/woff2tags.h +++ b/lib/libesp32_lvgl/freetype/src/sfnt/woff2tags.h @@ -2,9 +2,9 @@ * * woff2tags.h * - * WOFFF2 Font table tags (specification). + * WOFF2 Font table tags (specification). * - * Copyright (C) 2019-2020 by + * Copyright (C) 2019-2023 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -26,10 +26,12 @@ FT_BEGIN_HEADER +#ifdef FT_CONFIG_OPTION_USE_BROTLI - FT_LOCAL( FT_ULong ) + FT_LOCAL( FT_Tag ) woff2_known_tags( FT_Byte index ); +#endif FT_END_HEADER diff --git a/lib/libesp32_lvgl/freetype/src/smooth/ftgrays.c b/lib/libesp32_lvgl/freetype/src/smooth/ftgrays.c index 681900fd4..0918272f8 100644 --- a/lib/libesp32_lvgl/freetype/src/smooth/ftgrays.c +++ b/lib/libesp32_lvgl/freetype/src/smooth/ftgrays.c @@ -4,7 +4,7 @@ * * A new `perfect' anti-aliasing renderer (body). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -149,14 +149,10 @@ #define FT_INT_MAX INT_MAX #define FT_ULONG_MAX ULONG_MAX -#define ADD_LONG( a, b ) \ - (long)( (unsigned long)(a) + (unsigned long)(b) ) -#define SUB_LONG( a, b ) \ - (long)( (unsigned long)(a) - (unsigned long)(b) ) -#define MUL_LONG( a, b ) \ - (long)( (unsigned long)(a) * (unsigned long)(b) ) -#define NEG_LONG( a ) \ - (long)( -(unsigned long)(a) ) +#define ADD_INT( a, b ) \ + (int)( (unsigned int)(a) + (unsigned int)(b) ) + +#define FT_STATIC_BYTE_CAST( type, var ) (type)(unsigned char)(var) #define ft_memset memset @@ -168,10 +164,11 @@ typedef ptrdiff_t FT_PtrDist; -#define ErrRaster_Invalid_Mode -2 -#define ErrRaster_Invalid_Outline -1 -#define ErrRaster_Invalid_Argument -3 -#define ErrRaster_Memory_Overflow -4 +#define Smooth_Err_Ok 0 +#define Smooth_Err_Invalid_Outline -1 +#define Smooth_Err_Cannot_Render_Glyph -2 +#define Smooth_Err_Invalid_Argument -3 +#define Smooth_Err_Raster_Overflow -4 #define FT_BEGIN_HEADER #define FT_END_HEADER @@ -229,23 +226,26 @@ typedef ptrdiff_t FT_PtrDist; #define FT_ERROR( varformat ) FT_Message varformat #endif -#define FT_THROW( e ) \ - ( FT_Throw( FT_ERR_CAT( ErrRaster_, e ), \ - __LINE__, \ - __FILE__ ) | \ - FT_ERR_CAT( ErrRaster_, e ) ) +#define FT_THROW( e ) \ + ( FT_Throw( FT_ERR_CAT( Smooth_Err_, e ), \ + __LINE__, \ + __FILE__ ) | \ + FT_ERR_CAT( Smooth_Err_, e ) ) #else /* !FT_DEBUG_LEVEL_TRACE */ #define FT_TRACE5( x ) do { } while ( 0 ) /* nothing */ #define FT_TRACE7( x ) do { } while ( 0 ) /* nothing */ #define FT_ERROR( x ) do { } while ( 0 ) /* nothing */ -#define FT_THROW( e ) FT_ERR_CAT( ErrRaster_, e ) - +#define FT_THROW( e ) FT_ERR_CAT( Smooth_Err_, e ) #endif /* !FT_DEBUG_LEVEL_TRACE */ +#define FT_Trace_Enable() do { } while ( 0 ) /* nothing */ +#define FT_Trace_Disable() do { } while ( 0 ) /* nothing */ + + #define FT_DEFINE_OUTLINE_FUNCS( class_, \ move_to_, line_to_, \ conic_to_, cubic_to_, \ @@ -278,6 +278,8 @@ typedef ptrdiff_t FT_PtrDist; #else /* !STANDALONE_ */ +#include +#include FT_CONFIG_CONFIG_H #include "ftgrays.h" #include #include @@ -286,10 +288,6 @@ typedef ptrdiff_t FT_PtrDist; #include "ftsmerrs.h" -#define Smooth_Err_Invalid_Mode Smooth_Err_Cannot_Render_Glyph -#define Smooth_Err_Memory_Overflow Smooth_Err_Out_Of_Memory -#define ErrRaster_Memory_Overflow Smooth_Err_Out_Of_Memory - #endif /* !STANDALONE_ */ @@ -335,7 +333,9 @@ typedef ptrdiff_t FT_PtrDist; #define PIXEL_BITS 8 #define ONE_PIXEL ( 1 << PIXEL_BITS ) +#undef TRUNC #define TRUNC( x ) (TCoord)( (x) >> PIXEL_BITS ) +#undef FRACT #define FRACT( x ) (TCoord)( (x) & ( ONE_PIXEL - 1 ) ) #if PIXEL_BITS >= 6 @@ -362,7 +362,7 @@ typedef ptrdiff_t FT_PtrDist; } \ FT_END_STMNT -#ifdef __arm__ +#if defined( __GNUC__ ) && __GNUC__ < 7 && defined( __arm__ ) /* Work around a bug specific to GCC which make the compiler fail to */ /* optimize a division and modulo operation on the same parameters */ /* into a single call to `__aeabi_idivmod'. See */ @@ -382,14 +382,58 @@ typedef ptrdiff_t FT_PtrDist; #endif /* __arm__ */ - /* These macros speed up repetitive divisions by replacing them */ - /* with multiplications and right shifts. */ -#define FT_UDIVPREP( c, b ) \ - long b ## _r = c ? (long)( FT_ULONG_MAX >> PIXEL_BITS ) / ( b ) \ - : 0 -#define FT_UDIV( a, b ) \ - (TCoord)( ( (unsigned long)( a ) * (unsigned long)( b ## _r ) ) >> \ - ( sizeof( long ) * FT_CHAR_BIT - PIXEL_BITS ) ) + /* Calculating coverages for a slanted line requires a division each */ + /* time the line crosses from cell to cell. These macros speed up */ + /* the repetitive divisions by replacing them with multiplications */ + /* and right shifts so that at most two divisions are performed for */ + /* each slanted line. Nevertheless, these divisions are noticeable */ + /* in the overall performance because flattened curves produce a */ + /* very large number of slanted lines. */ + /* */ + /* The division results here are always within ONE_PIXEL. Therefore */ + /* the shift magnitude should be at least PIXEL_BITS wider than the */ + /* divisors to provide sufficient accuracy of the multiply-shift. */ + /* It should not exceed (64 - PIXEL_BITS) to prevent overflowing and */ + /* leave enough room for 64-bit unsigned multiplication however. */ +#define FT_UDIVPREP( c, b ) \ + FT_Int64 b ## _r = c ? (FT_Int64)0xFFFFFFFF / ( b ) : 0 +#define FT_UDIV( a, b ) \ + (TCoord)( ( (FT_UInt64)( a ) * (FT_UInt64)( b ## _r ) ) >> 32 ) + + + /* Scale area and apply fill rule to calculate the coverage byte. */ + /* The top fill bit is used for the non-zero rule. The eighth */ + /* fill bit is used for the even-odd rule. The higher coverage */ + /* bytes are either clamped for the non-zero-rule or discarded */ + /* later for the even-odd rule. */ +#define FT_FILL_RULE( coverage, area, fill ) \ + FT_BEGIN_STMNT \ + coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) ); \ + if ( coverage & fill ) \ + coverage = ~coverage; \ + if ( coverage > 255 && fill & INT_MIN ) \ + coverage = 255; \ + FT_END_STMNT + + + /* It is faster to write small spans byte-by-byte than calling */ + /* `memset'. This is mainly due to the cost of the function call. */ +#define FT_GRAY_SET( d, s, count ) \ + FT_BEGIN_STMNT \ + unsigned char* q = d; \ + switch ( count ) \ + { \ + case 7: *q++ = (unsigned char)s; FALL_THROUGH; \ + case 6: *q++ = (unsigned char)s; FALL_THROUGH; \ + case 5: *q++ = (unsigned char)s; FALL_THROUGH; \ + case 4: *q++ = (unsigned char)s; FALL_THROUGH; \ + case 3: *q++ = (unsigned char)s; FALL_THROUGH; \ + case 2: *q++ = (unsigned char)s; FALL_THROUGH; \ + case 1: *q = (unsigned char)s; FALL_THROUGH; \ + case 0: break; \ + default: FT_MEM_SET( d, s, count ); \ + } \ + FT_END_STMNT /************************************************************************** @@ -432,7 +476,7 @@ typedef ptrdiff_t FT_PtrDist; #endif /* FT_Span buffer size for direct rendering only */ -#define FT_MAX_GRAY_SPANS 10 +#define FT_MAX_GRAY_SPANS 16 #if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */ @@ -447,28 +491,24 @@ typedef ptrdiff_t FT_PtrDist; { ft_jmp_buf jump_buffer; - TCoord ex, ey; - TCoord min_ex, max_ex; + TCoord min_ex, max_ex; /* min and max integer pixel coordinates */ TCoord min_ey, max_ey; + TCoord count_ey; /* same as (max_ey - min_ey) */ - TArea area; - TCoord cover; - int invalid; + PCell cell; /* current cell */ + PCell cell_free; /* call allocation next free slot */ + PCell cell_null; /* last cell, used as dumpster and limit */ - PCell* ycells; - PCell cells; - FT_PtrDist max_cells; - FT_PtrDist num_cells; + PCell* ycells; /* array of cell linked-lists; one per */ + /* vertical coordinate in the current band */ - TPos x, y; + TPos x, y; /* last point position */ - FT_Outline outline; - TPixmap target; + FT_Outline outline; /* input outline */ + TPixmap target; /* target pixmap */ FT_Raster_Span_Func render_span; void* render_span_data; - FT_Span spans[FT_MAX_GRAY_SPANS]; - int num_spans; } gray_TWorker, *gray_PWorker; @@ -476,17 +516,25 @@ typedef ptrdiff_t FT_PtrDist; #pragma warning( pop ) #endif - #ifndef FT_STATIC_RASTER #define ras (*worker) #else static gray_TWorker ras; #endif + /* The |x| value of the null cell. Must be the largest possible */ + /* integer value stored in a `TCell.x` field. */ +#define CELL_MAX_X_VALUE INT_MAX + + +#define FT_INTEGRATE( ras, a, b ) \ + ras.cell->cover = ADD_INT( ras.cell->cover, a ), \ + ras.cell->area = ADD_INT( ras.cell->area, (a) * (TArea)(b) ) + typedef struct gray_TRaster_ { - void* memory; + void* memory; } gray_TRaster, *gray_PRaster; @@ -508,7 +556,7 @@ typedef ptrdiff_t FT_PtrDist; printf( "%3d:", y ); - for ( ; cell != NULL; cell = cell->next ) + for ( ; cell != ras.cell_null; cell = cell->next ) printf( " (%3d, c:%4d, a:%6d)", cell->x, cell->cover, cell->area ); printf( "\n" ); @@ -518,50 +566,6 @@ typedef ptrdiff_t FT_PtrDist; #endif /* FT_DEBUG_LEVEL_TRACE */ - /************************************************************************** - * - * Record the current cell in the linked list. - */ - static void - gray_record_cell( RAS_ARG ) - { - PCell *pcell, cell; - TCoord x = ras.ex; - - - pcell = &ras.ycells[ras.ey - ras.min_ey]; - while ( ( cell = *pcell ) ) - { - if ( cell->x > x ) - break; - - if ( cell->x == x ) - goto Found; - - pcell = &cell->next; - } - - if ( ras.num_cells >= ras.max_cells ) - ft_longjmp( ras.jump_buffer, 1 ); - - /* insert new cell */ - cell = ras.cells + ras.num_cells++; - cell->x = x; - cell->area = ras.area; - cell->cover = ras.cover; - - cell->next = *pcell; - *pcell = cell; - - return; - - Found: - /* update old cell */ - cell->area += ras.area; - cell->cover += ras.cover; - } - - /************************************************************************** * * Set the current cell to a new position. @@ -570,9 +574,9 @@ typedef ptrdiff_t FT_PtrDist; gray_set_cell( RAS_ARG_ TCoord ex, TCoord ey ) { - /* Move the cell pointer to a new position. We set the `invalid' */ - /* flag to indicate that the cell isn't part of those we're interested */ - /* in during the render phase. This means that: */ + /* Move the cell pointer to a new position in the linked list. We use */ + /* a dumpster null cell for everything outside of the clipping region */ + /* during the render phase. This means that: */ /* */ /* . the new vertical position must be within min_ey..max_ey-1. */ /* . the new horizontal position must be strictly less than max_ex */ @@ -580,21 +584,51 @@ typedef ptrdiff_t FT_PtrDist; /* Note that if a cell is to the left of the clipping region, it is */ /* actually set to the (min_ex-1) horizontal position. */ - /* record the current one if it is valid and substantial */ - if ( !ras.invalid && ( ras.area || ras.cover ) ) - gray_record_cell( RAS_VAR ); + TCoord ey_index = ey - ras.min_ey; - ras.area = 0; - ras.cover = 0; - ras.ex = FT_MAX( ex, ras.min_ex - 1 ); - ras.ey = ey; - ras.invalid = ( ey >= ras.max_ey || ey < ras.min_ey || - ex >= ras.max_ex ); + if ( ey_index < 0 || ey_index >= ras.count_ey || ex >= ras.max_ex ) + ras.cell = ras.cell_null; + else + { + PCell* pcell = ras.ycells + ey_index; + PCell cell; + + + ex = FT_MAX( ex, ras.min_ex - 1 ); + + while ( 1 ) + { + cell = *pcell; + + if ( cell->x > ex ) + break; + + if ( cell->x == ex ) + goto Found; + + pcell = &cell->next; + } + + /* insert new cell */ + cell = ras.cell_free++; + if ( cell >= ras.cell_null ) + ft_longjmp( ras.jump_buffer, 1 ); + + cell->x = ex; + cell->area = 0; + cell->cover = 0; + + cell->next = *pcell; + *pcell = cell; + + Found: + ras.cell = cell; + } } -#ifndef FT_LONG64 +#ifndef FT_INT64 /************************************************************************** * @@ -622,8 +656,8 @@ typedef ptrdiff_t FT_PtrDist; return; } - fx1 = FRACT( x1 ); - fx2 = FRACT( x2 ); + fx1 = FRACT( x1 ); + fx2 = FRACT( x2 ); /* everything is located in a single cell. That is easy! */ /* */ @@ -655,10 +689,9 @@ typedef ptrdiff_t FT_PtrDist; /* XXX: y-delta and x-delta below should be related. */ FT_DIV_MOD( TCoord, p, dx, delta, mod ); - ras.area += (TArea)( ( fx1 + first ) * delta ); - ras.cover += delta; - y1 += delta; - ex1 += incr; + FT_INTEGRATE( ras, delta, fx1 + first ); + y1 += delta; + ex1 += incr; gray_set_cell( RAS_VAR_ ex1, ey ); if ( ex1 != ex2 ) @@ -679,10 +712,9 @@ typedef ptrdiff_t FT_PtrDist; delta++; } - ras.area += (TArea)( ONE_PIXEL * delta ); - ras.cover += delta; - y1 += delta; - ex1 += incr; + FT_INTEGRATE( ras, delta, ONE_PIXEL ); + y1 += delta; + ex1 += incr; gray_set_cell( RAS_VAR_ ex1, ey ); } while ( ex1 != ex2 ); } @@ -690,10 +722,7 @@ typedef ptrdiff_t FT_PtrDist; fx1 = ONE_PIXEL - first; End: - dy = y2 - y1; - - ras.area += (TArea)( ( fx1 + fx2 ) * dy ); - ras.cover += dy; + FT_INTEGRATE( ras, y2 - y1, fx1 + fx2 ); } @@ -736,7 +765,6 @@ typedef ptrdiff_t FT_PtrDist; { TCoord ex = TRUNC( ras.x ); TCoord two_fx = FRACT( ras.x ) << 1; - TArea area; if ( dy > 0) @@ -750,27 +778,23 @@ typedef ptrdiff_t FT_PtrDist; incr = -1; } - delta = first - fy1; - ras.area += (TArea)two_fx * delta; - ras.cover += delta; - ey1 += incr; + delta = first - fy1; + FT_INTEGRATE( ras, delta, two_fx); + ey1 += incr; gray_set_cell( RAS_VAR_ ex, ey1 ); delta = first + first - ONE_PIXEL; - area = (TArea)two_fx * delta; while ( ey1 != ey2 ) { - ras.area += area; - ras.cover += delta; - ey1 += incr; + FT_INTEGRATE( ras, delta, two_fx); + ey1 += incr; gray_set_cell( RAS_VAR_ ex, ey1 ); } - delta = fy2 - ONE_PIXEL + first; - ras.area += (TArea)two_fx * delta; - ras.cover += delta; + delta = fy2 - ONE_PIXEL + first; + FT_INTEGRATE( ras, delta, two_fx); goto End; } @@ -883,8 +907,7 @@ typedef ptrdiff_t FT_PtrDist; do { fy2 = ONE_PIXEL; - ras.cover += ( fy2 - fy1 ); - ras.area += ( fy2 - fy1 ) * fx1 * 2; + FT_INTEGRATE( ras, fy2 - fy1, fx1 * 2 ); fy1 = 0; ey1++; gray_set_cell( RAS_VAR_ ex1, ey1 ); @@ -893,8 +916,7 @@ typedef ptrdiff_t FT_PtrDist; do { fy2 = 0; - ras.cover += ( fy2 - fy1 ); - ras.area += ( fy2 - fy1 ) * fx1 * 2; + FT_INTEGRATE( ras, fy2 - fy1, fx1 * 2 ); fy1 = ONE_PIXEL; ey1--; gray_set_cell( RAS_VAR_ ex1, ey1 ); @@ -902,7 +924,7 @@ typedef ptrdiff_t FT_PtrDist; } else /* any other line */ { - TPos prod = dx * (TPos)fy1 - dy * (TPos)fx1; + FT_Int64 prod = dx * (FT_Int64)fy1 - dy * (FT_Int64)fx1; FT_UDIVPREP( ex1 != ex2, dx ); FT_UDIVPREP( ey1 != ey2, dy ); @@ -912,72 +934,309 @@ typedef ptrdiff_t FT_PtrDist; /* also easily updated when moving from one cell to the next. */ do { - if ( prod <= 0 && - prod - dx * ONE_PIXEL > 0 ) /* left */ + if ( prod - dx * ONE_PIXEL > 0 && + prod <= 0 ) /* left */ { fx2 = 0; fy2 = FT_UDIV( -prod, -dx ); prod -= dy * ONE_PIXEL; - ras.cover += ( fy2 - fy1 ); - ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 ); + FT_INTEGRATE( ras, fy2 - fy1, fx1 + fx2 ); fx1 = ONE_PIXEL; fy1 = fy2; ex1--; } - else if ( prod - dx * ONE_PIXEL <= 0 && - prod - dx * ONE_PIXEL + dy * ONE_PIXEL > 0 ) /* up */ + else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL > 0 && + prod - dx * ONE_PIXEL <= 0 ) /* up */ { prod -= dx * ONE_PIXEL; fx2 = FT_UDIV( -prod, dy ); fy2 = ONE_PIXEL; - ras.cover += ( fy2 - fy1 ); - ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 ); + FT_INTEGRATE( ras, fy2 - fy1, fx1 + fx2 ); fx1 = fx2; fy1 = 0; ey1++; } - else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 && - prod + dy * ONE_PIXEL >= 0 ) /* right */ + else if ( prod + dy * ONE_PIXEL >= 0 && + prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 ) /* right */ { prod += dy * ONE_PIXEL; fx2 = ONE_PIXEL; fy2 = FT_UDIV( prod, dx ); - ras.cover += ( fy2 - fy1 ); - ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 ); + FT_INTEGRATE( ras, fy2 - fy1, fx1 + fx2 ); fx1 = 0; fy1 = fy2; ex1++; } - else /* ( prod + dy * ONE_PIXEL < 0 && - prod > 0 ) down */ + else /* ( prod > 0 && + prod + dy * ONE_PIXEL < 0 ) down */ { fx2 = FT_UDIV( prod, -dy ); fy2 = 0; prod += dx * ONE_PIXEL; - ras.cover += ( fy2 - fy1 ); - ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 ); + FT_INTEGRATE( ras, fy2 - fy1, fx1 + fx2 ); fx1 = fx2; fy1 = ONE_PIXEL; ey1--; } gray_set_cell( RAS_VAR_ ex1, ey1 ); + } while ( ex1 != ex2 || ey1 != ey2 ); } fx2 = FRACT( to_x ); fy2 = FRACT( to_y ); - ras.cover += ( fy2 - fy1 ); - ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 ); + FT_INTEGRATE( ras, fy2 - fy1, fx1 + fx2 ); End: - ras.x = to_x; - ras.y = to_y; + ras.x = to_x; + ras.y = to_y; } #endif + /* + * Benchmarking shows that using DDA to flatten the quadratic Bézier arcs + * is slightly faster in the following cases: + * + * - When the host CPU is 64-bit. + * - When SSE2 SIMD registers and instructions are available (even on + * x86). + * + * For other cases, using binary splits is actually slightly faster. + */ +#if ( defined( __SSE2__ ) || \ + defined( __x86_64__ ) || \ + defined( _M_AMD64 ) || \ + ( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 ) ) && \ + !defined( __VMS ) +# define FT_SSE2 1 +#else +# define FT_SSE2 0 +#endif + +#if FT_SSE2 || \ + defined( __aarch64__ ) || \ + defined( _M_ARM64 ) +# define BEZIER_USE_DDA 1 +#else +# define BEZIER_USE_DDA 0 +#endif + + /* + * For now, the code that depends on `BEZIER_USE_DDA` requires `FT_Int64` + * to be defined. If `FT_INT64` is not defined, meaning there is no + * 64-bit type available, disable it to avoid compilation errors. See for + * example https://gitlab.freedesktop.org/freetype/freetype/-/issues/1071. + */ +#if !defined( FT_INT64 ) +# undef BEZIER_USE_DDA +# define BEZIER_USE_DDA 0 +#endif + +#if BEZIER_USE_DDA + +#if FT_SSE2 +# include +#endif + +#define LEFT_SHIFT( a, b ) (FT_Int64)( (FT_UInt64)(a) << (b) ) + + + static void + gray_render_conic( RAS_ARG_ const FT_Vector* control, + const FT_Vector* to ) + { + FT_Vector p0, p1, p2; + TPos ax, ay, bx, by, dx, dy; + int shift; + + FT_Int64 rx, ry; + FT_Int64 qx, qy; + FT_Int64 px, py; + + FT_UInt count; + + + p0.x = ras.x; + p0.y = ras.y; + p1.x = UPSCALE( control->x ); + p1.y = UPSCALE( control->y ); + p2.x = UPSCALE( to->x ); + p2.y = UPSCALE( to->y ); + + /* short-cut the arc that crosses the current band */ + if ( ( TRUNC( p0.y ) >= ras.max_ey && + TRUNC( p1.y ) >= ras.max_ey && + TRUNC( p2.y ) >= ras.max_ey ) || + ( TRUNC( p0.y ) < ras.min_ey && + TRUNC( p1.y ) < ras.min_ey && + TRUNC( p2.y ) < ras.min_ey ) ) + { + ras.x = p2.x; + ras.y = p2.y; + return; + } + + bx = p1.x - p0.x; + by = p1.y - p0.y; + ax = p2.x - p1.x - bx; /* p0.x + p2.x - 2 * p1.x */ + ay = p2.y - p1.y - by; /* p0.y + p2.y - 2 * p1.y */ + + dx = FT_ABS( ax ); + dy = FT_ABS( ay ); + if ( dx < dy ) + dx = dy; + + if ( dx <= ONE_PIXEL / 4 ) + { + gray_render_line( RAS_VAR_ p2.x, p2.y ); + return; + } + + /* We can calculate the number of necessary bisections because */ + /* each bisection predictably reduces deviation exactly 4-fold. */ + /* Even 32-bit deviation would vanish after 16 bisections. */ + shift = 0; + do + { + dx >>= 2; + shift += 1; + + } while ( dx > ONE_PIXEL / 4 ); + + /* + * The (P0,P1,P2) arc equation, for t in [0,1] range: + * + * P(t) = P0*(1-t)^2 + P1*2*t*(1-t) + P2*t^2 + * + * P(t) = P0 + 2*(P1-P0)*t + (P0+P2-2*P1)*t^2 + * = P0 + 2*B*t + A*t^2 + * + * for A = P0 + P2 - 2*P1 + * and B = P1 - P0 + * + * Let's consider the difference when advancing by a small + * parameter h: + * + * Q(h,t) = P(t+h) - P(t) = 2*B*h + A*h^2 + 2*A*h*t + * + * And then its own difference: + * + * R(h,t) = Q(h,t+h) - Q(h,t) = 2*A*h*h = R (constant) + * + * Since R is always a constant, it is possible to compute + * successive positions with: + * + * P = P0 + * Q = Q(h,0) = 2*B*h + A*h*h + * R = 2*A*h*h + * + * loop: + * P += Q + * Q += R + * EMIT(P) + * + * To ensure accurate results, perform computations on 64-bit + * values, after scaling them by 2^32. + * + * h = 1 / 2^N + * + * R << 32 = 2 * A << (32 - N - N) + * = A << (33 - 2*N) + * + * Q << 32 = (2 * B << (32 - N)) + (A << (32 - N - N)) + * = (B << (33 - N)) + (A << (32 - 2*N)) + */ + +#if FT_SSE2 + /* Experience shows that for small shift values, */ + /* SSE2 is actually slower. */ + if ( shift > 2 ) + { + union + { + struct { FT_Int64 ax, ay, bx, by; } i; + struct { __m128i a, b; } vec; + + } u; + + union + { + struct { FT_Int32 px_lo, px_hi, py_lo, py_hi; } i; + __m128i vec; + + } v; + + __m128i a, b; + __m128i r, q, q2; + __m128i p; + + + u.i.ax = ax; + u.i.ay = ay; + u.i.bx = bx; + u.i.by = by; + + a = _mm_load_si128( &u.vec.a ); + b = _mm_load_si128( &u.vec.b ); + + r = _mm_slli_epi64( a, 33 - 2 * shift ); + q = _mm_slli_epi64( b, 33 - shift ); + q2 = _mm_slli_epi64( a, 32 - 2 * shift ); + + q = _mm_add_epi64( q2, q ); + + v.i.px_lo = 0; + v.i.px_hi = p0.x; + v.i.py_lo = 0; + v.i.py_hi = p0.y; + + p = _mm_load_si128( &v.vec ); + + for ( count = 1U << shift; count > 0; count-- ) + { + p = _mm_add_epi64( p, q ); + q = _mm_add_epi64( q, r ); + + _mm_store_si128( &v.vec, p ); + + gray_render_line( RAS_VAR_ v.i.px_hi, v.i.py_hi ); + } + + return; + } +#endif /* FT_SSE2 */ + + rx = LEFT_SHIFT( ax, 33 - 2 * shift ); + ry = LEFT_SHIFT( ay, 33 - 2 * shift ); + + qx = LEFT_SHIFT( bx, 33 - shift ) + LEFT_SHIFT( ax, 32 - 2 * shift ); + qy = LEFT_SHIFT( by, 33 - shift ) + LEFT_SHIFT( ay, 32 - 2 * shift ); + + px = LEFT_SHIFT( p0.x, 32 ); + py = LEFT_SHIFT( p0.y, 32 ); + + for ( count = 1U << shift; count > 0; count-- ) + { + px += qx; + py += qy; + qx += rx; + qy += ry; + + gray_render_line( RAS_VAR_ (FT_Pos)( px >> 32 ), + (FT_Pos)( py >> 32 ) ); + } + } + +#else /* !BEZIER_USE_DDA */ + + /* + * Note that multiple attempts to speed up the function below + * with SSE2 intrinsics, using various data layouts, have turned + * out to be slower than the non-SIMD code below. + */ static void gray_split_conic( FT_Vector* base ) { @@ -1007,7 +1266,7 @@ typedef ptrdiff_t FT_PtrDist; FT_Vector bez_stack[16 * 2 + 1]; /* enough to accommodate bisections */ FT_Vector* arc = bez_stack; TPos dx, dy; - int draw, split; + int draw; arc[0].x = UPSCALE( to->x ); @@ -1050,7 +1309,9 @@ typedef ptrdiff_t FT_PtrDist; /* many times as there are trailing zeros in the counter. */ do { - split = draw & ( -draw ); /* isolate the rightmost 1-bit */ + int split = draw & ( -draw ); /* isolate the rightmost 1-bit */ + + while ( ( split >>= 1 ) ) { gray_split_conic( arc ); @@ -1063,7 +1324,17 @@ typedef ptrdiff_t FT_PtrDist; } while ( --draw ); } +#endif /* !BEZIER_USE_DDA */ + + /* + * For cubic Bézier, binary splits are still faster than DDA + * because the splits are adaptive to how quickly each sub-arc + * approaches their chord trisection points. + * + * It might be useful to experiment with SSE2 to speed up + * `gray_split_cubic`, though. + */ static void gray_split_cubic( FT_Vector* base ) { @@ -1157,8 +1428,10 @@ typedef ptrdiff_t FT_PtrDist; static int gray_move_to( const FT_Vector* to, - gray_PWorker worker ) + void* worker_ ) /* gray_PWorker */ { + gray_PWorker worker = (gray_PWorker)worker_; + TPos x, y; @@ -1176,8 +1449,11 @@ typedef ptrdiff_t FT_PtrDist; static int gray_line_to( const FT_Vector* to, - gray_PWorker worker ) + void* worker_ ) /* gray_PWorker */ { + gray_PWorker worker = (gray_PWorker)worker_; + + gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) ); return 0; } @@ -1186,8 +1462,11 @@ typedef ptrdiff_t FT_PtrDist; static int gray_conic_to( const FT_Vector* control, const FT_Vector* to, - gray_PWorker worker ) + void* worker_ ) /* gray_PWorker */ { + gray_PWorker worker = (gray_PWorker)worker_; + + gray_render_conic( RAS_VAR_ control, to ); return 0; } @@ -1197,100 +1476,22 @@ typedef ptrdiff_t FT_PtrDist; gray_cubic_to( const FT_Vector* control1, const FT_Vector* control2, const FT_Vector* to, - gray_PWorker worker ) + void* worker_ ) /* gray_PWorker */ { + gray_PWorker worker = (gray_PWorker)worker_; + + gray_render_cubic( RAS_VAR_ control1, control2, to ); return 0; } - static void - gray_hline( RAS_ARG_ TCoord x, - TCoord y, - TArea coverage, - TCoord acount ) - { - /* scale the coverage from 0..(ONE_PIXEL*ONE_PIXEL*2) to 0..256 */ - coverage >>= PIXEL_BITS * 2 + 1 - 8; - - /* compute the line's coverage depending on the outline fill rule */ - if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) - { - coverage &= 511; - - if ( coverage >= 256 ) - coverage = 511 - coverage; - } - else /* default non-zero winding rule */ - { - if ( coverage < 0 ) - coverage = ~coverage; /* the same as -coverage - 1 */ - - if ( coverage >= 256 ) - coverage = 255; - } - - if ( ras.num_spans >= 0 ) /* for FT_RASTER_FLAG_DIRECT only */ - { - FT_Span* span = ras.spans + ras.num_spans++; - - - span->x = (short)x; - span->len = (unsigned short)acount; - span->coverage = (unsigned char)coverage; - - if ( ras.num_spans == FT_MAX_GRAY_SPANS ) - { - /* flush the span buffer and reset the count */ - ras.render_span( y, ras.num_spans, ras.spans, ras.render_span_data ); - ras.num_spans = 0; - } - } - else - { - unsigned char* q = ras.target.origin - ras.target.pitch * y + x; - unsigned char c = (unsigned char)coverage; - - - /* For small-spans it is faster to do it by ourselves than - * calling `memset'. This is mainly due to the cost of the - * function call. - */ - switch ( acount ) - { - case 7: - *q++ = c; - /* fall through */ - case 6: - *q++ = c; - /* fall through */ - case 5: - *q++ = c; - /* fall through */ - case 4: - *q++ = c; - /* fall through */ - case 3: - *q++ = c; - /* fall through */ - case 2: - *q++ = c; - /* fall through */ - case 1: - *q = c; - /* fall through */ - case 0: - break; - default: - FT_MEM_SET( q, c, acount ); - } - } - } - - static void gray_sweep( RAS_ARG ) { + int fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100 + : INT_MIN; + int coverage; int y; @@ -1299,31 +1500,120 @@ typedef ptrdiff_t FT_PtrDist; PCell cell = ras.ycells[y - ras.min_ey]; TCoord x = ras.min_ex; TArea cover = 0; - TArea area; + + unsigned char* line = ras.target.origin - ras.target.pitch * y; - for ( ; cell != NULL; cell = cell->next ) + for ( ; cell != ras.cell_null; cell = cell->next ) { + TArea area; + + if ( cover != 0 && cell->x > x ) - gray_hline( RAS_VAR_ x, y, cover, cell->x - x ); + { + FT_FILL_RULE( coverage, cover, fill ); + FT_GRAY_SET( line + x, coverage, cell->x - x ); + } cover += (TArea)cell->cover * ( ONE_PIXEL * 2 ); area = cover - cell->area; if ( area != 0 && cell->x >= ras.min_ex ) - gray_hline( RAS_VAR_ cell->x, y, area, 1 ); + { + FT_FILL_RULE( coverage, area, fill ); + line[cell->x] = (unsigned char)coverage; + } x = cell->x + 1; } - if ( cover != 0 ) - gray_hline( RAS_VAR_ x, y, cover, ras.max_ex - x ); + if ( cover != 0 ) /* only if cropped */ + { + FT_FILL_RULE( coverage, cover, fill ); + FT_GRAY_SET( line + x, coverage, ras.max_ex - x ); + } + } + } - if ( ras.num_spans > 0 ) /* for FT_RASTER_FLAG_DIRECT only */ + + static void + gray_sweep_direct( RAS_ARG ) + { + int fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100 + : INT_MIN; + int coverage; + int y; + + FT_Span span[FT_MAX_GRAY_SPANS]; + int n = 0; + + + for ( y = ras.min_ey; y < ras.max_ey; y++ ) + { + PCell cell = ras.ycells[y - ras.min_ey]; + TCoord x = ras.min_ex; + TArea cover = 0; + + + for ( ; cell != ras.cell_null; cell = cell->next ) + { + TArea area; + + + if ( cover != 0 && cell->x > x ) + { + FT_FILL_RULE( coverage, cover, fill ); + + span[n].coverage = (unsigned char)coverage; + span[n].x = (short)x; + span[n].len = (unsigned short)( cell->x - x ); + + if ( ++n == FT_MAX_GRAY_SPANS ) + { + /* flush the span buffer and reset the count */ + ras.render_span( y, n, span, ras.render_span_data ); + n = 0; + } + } + + cover += (TArea)cell->cover * ( ONE_PIXEL * 2 ); + area = cover - cell->area; + + if ( area != 0 && cell->x >= ras.min_ex ) + { + FT_FILL_RULE( coverage, area, fill ); + + span[n].coverage = (unsigned char)coverage; + span[n].x = (short)cell->x; + span[n].len = 1; + + if ( ++n == FT_MAX_GRAY_SPANS ) + { + /* flush the span buffer and reset the count */ + ras.render_span( y, n, span, ras.render_span_data ); + n = 0; + } + } + + x = cell->x + 1; + } + + if ( cover != 0 ) /* only if cropped */ + { + FT_FILL_RULE( coverage, cover, fill ); + + span[n].coverage = (unsigned char)coverage; + span[n].x = (short)x; + span[n].len = (unsigned short)( ras.max_ex - x ); + + ++n; + } + + if ( n ) { /* flush the span buffer and reset the count */ - ras.render_span( y, ras.num_spans, ras.spans, ras.render_span_data ); - ras.num_spans = 0; + ras.render_span( y, n, span, ras.render_span_data ); + n = 0; } } } @@ -1388,6 +1678,8 @@ typedef ptrdiff_t FT_PtrDist; int n; /* index of contour in outline */ int first; /* index of first point in contour */ + int last; /* index of last point in contour */ + char tag; /* current point's state */ int shift; @@ -1402,18 +1694,17 @@ typedef ptrdiff_t FT_PtrDist; shift = func_interface->shift; delta = func_interface->delta; - first = 0; + last = -1; for ( n = 0; n < outline->n_contours; n++ ) { - int last; /* index of last point in contour */ - - - FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n )); + FT_TRACE5(( "FT_Outline_Decompose: Contour %d\n", n )); + first = last + 1; last = outline->contours[n]; - if ( last < 0 ) + if ( last < first ) goto Invalid_Outline; + limit = outline->points + last; v_start = outline->points[first]; @@ -1596,15 +1887,13 @@ typedef ptrdiff_t FT_PtrDist; v_start.x / 64.0, v_start.y / 64.0 )); error = func_interface->line_to( &v_start, user ); - Close: + Close: if ( error ) goto Exit; - - first = last + 1; } FT_TRACE5(( "FT_Outline_Decompose: Done\n", n )); - return 0; + return Smooth_Err_Ok; Exit: FT_TRACE5(( "FT_Outline_Decompose: Error 0x%x\n", error )); @@ -1631,10 +1920,10 @@ typedef ptrdiff_t FT_PtrDist; static int - gray_convert_glyph_inner( RAS_ARG, + gray_convert_glyph_inner( RAS_ARG_ int continued ) { - int error; + volatile int error; if ( ft_setjmp( ras.jump_buffer ) == 0 ) @@ -1645,18 +1934,15 @@ typedef ptrdiff_t FT_PtrDist; if ( continued ) FT_Trace_Enable(); - if ( !ras.invalid ) - gray_record_cell( RAS_VAR ); - - FT_TRACE7(( "band [%d..%d]: %ld cell%s\n", + FT_TRACE7(( "band [%d..%d]: %td cell%s remaining/\n", ras.min_ey, ras.max_ey, - ras.num_cells, - ras.num_cells == 1 ? "" : "s" )); + ras.cell_null - ras.cell_free, + ras.cell_null - ras.cell_free == 1 ? "" : "s" )); } else { - error = FT_THROW( Memory_Overflow ); + error = FT_THROW( Raster_Overflow ); FT_TRACE7(( "band [%d..%d]: to be bisected\n", ras.min_ey, ras.max_ey )); @@ -1682,7 +1968,16 @@ typedef ptrdiff_t FT_PtrDist; int continued = 0; + /* Initialize the null cell at the end of the poll. */ + ras.cell_null = buffer + FT_MAX_GRAY_POOL - 1; + ras.cell_null->x = CELL_MAX_X_VALUE; + ras.cell_null->area = 0; + ras.cell_null->cover = 0; + ras.cell_null->next = NULL; + /* set up vertical bands */ + ras.ycells = (PCell*)buffer; + if ( height > n ) { /* two divisions rounded up */ @@ -1690,13 +1985,6 @@ typedef ptrdiff_t FT_PtrDist; height = ( height + n - 1 ) / n; } - /* memory management */ - n = ( height * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) / sizeof ( TCell ); - - ras.cells = buffer + n; - ras.max_cells = (FT_PtrDist)( FT_MAX_GRAY_POOL - n ); - ras.ycells = (PCell*)buffer; - for ( y = yMin; y < yMax; ) { ras.min_ey = y; @@ -1710,27 +1998,37 @@ typedef ptrdiff_t FT_PtrDist; do { TCoord width = band[0] - band[1]; + TCoord w; int error; - FT_MEM_ZERO( ras.ycells, height * sizeof ( PCell ) ); + for ( w = 0; w < width; ++w ) + ras.ycells[w] = ras.cell_null; - ras.num_cells = 0; - ras.invalid = 1; + /* memory management: skip ycells */ + n = ( (size_t)width * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) / + sizeof ( TCell ); + + ras.cell_free = buffer + n; + ras.cell = ras.cell_null; ras.min_ey = band[1]; ras.max_ey = band[0]; + ras.count_ey = width; - error = gray_convert_glyph_inner( RAS_VAR, continued ); + error = gray_convert_glyph_inner( RAS_VAR_ continued ); continued = 1; if ( !error ) { - gray_sweep( RAS_VAR ); + if ( ras.render_span ) /* for FT_RASTER_FLAG_DIRECT only */ + gray_sweep_direct( RAS_VAR ); + else + gray_sweep( RAS_VAR ); band--; continue; } - else if ( error != ErrRaster_Memory_Overflow ) - return 1; + else if ( error != Smooth_Err_Raster_Overflow ) + return error; /* render pool overflow; we will reduce the render band by half */ width >>= 1; @@ -1739,7 +2037,7 @@ typedef ptrdiff_t FT_PtrDist; if ( width == 0 ) { FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" )); - return 1; + return FT_THROW( Raster_Overflow ); } band++; @@ -1748,7 +2046,7 @@ typedef ptrdiff_t FT_PtrDist; } while ( band >= bands ); } - return 0; + return Smooth_Err_Ok; } @@ -1769,14 +2067,14 @@ typedef ptrdiff_t FT_PtrDist; /* this version does not support monochrome rendering */ if ( !( params->flags & FT_RASTER_FLAG_AA ) ) - return FT_THROW( Invalid_Mode ); + return FT_THROW( Cannot_Render_Glyph ); if ( !outline ) return FT_THROW( Invalid_Outline ); /* return immediately if the outline is empty */ if ( outline->n_points == 0 || outline->n_contours <= 0 ) - return 0; + return Smooth_Err_Ok; if ( !outline->contours || !outline->points ) return FT_THROW( Invalid_Outline ); @@ -1790,11 +2088,10 @@ typedef ptrdiff_t FT_PtrDist; if ( params->flags & FT_RASTER_FLAG_DIRECT ) { if ( !params->gray_spans ) - return 0; + return Smooth_Err_Ok; ras.render_span = (FT_Raster_Span_Func)params->gray_spans; ras.render_span_data = params->user; - ras.num_spans = 0; ras.min_ex = params->clip_box.xMin; ras.min_ey = params->clip_box.yMin; @@ -1809,7 +2106,7 @@ typedef ptrdiff_t FT_PtrDist; /* nothing to do */ if ( !target_map->width || !target_map->rows ) - return 0; + return Smooth_Err_Ok; if ( !target_map->buffer ) return FT_THROW( Invalid_Argument ); @@ -1824,7 +2121,6 @@ typedef ptrdiff_t FT_PtrDist; ras.render_span = (FT_Raster_Span_Func)NULL; ras.render_span_data = NULL; - ras.num_spans = -1; /* invalid */ ras.min_ex = 0; ras.min_ey = 0; @@ -1834,7 +2130,7 @@ typedef ptrdiff_t FT_PtrDist; /* exit if nothing to do */ if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey ) - return 0; + return Smooth_Err_Ok; return gray_convert_glyph( RAS_VAR ); } @@ -1871,19 +2167,20 @@ typedef ptrdiff_t FT_PtrDist; #else /* !STANDALONE_ */ static int - gray_raster_new( FT_Memory memory, - FT_Raster* araster ) + gray_raster_new( void* memory_, + FT_Raster* araster_ ) { + FT_Memory memory = (FT_Memory)memory_; + gray_PRaster* araster = (gray_PRaster*)araster_; + FT_Error error; gray_PRaster raster = NULL; - *araster = 0; - if ( !FT_ALLOC( raster, sizeof ( gray_TRaster ) ) ) - { + if ( !FT_NEW( raster ) ) raster->memory = memory; - *araster = (FT_Raster)raster; - } + + *araster = raster; return error; } diff --git a/lib/libesp32_lvgl/freetype/src/smooth/ftgrays.h b/lib/libesp32_lvgl/freetype/src/smooth/ftgrays.h index caba63283..a5001bf40 100644 --- a/lib/libesp32_lvgl/freetype/src/smooth/ftgrays.h +++ b/lib/libesp32_lvgl/freetype/src/smooth/ftgrays.h @@ -4,7 +4,7 @@ * * FreeType smooth renderer declaration * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/smooth/ftsmerrs.h b/lib/libesp32_lvgl/freetype/src/smooth/ftsmerrs.h index e93f3df9b..f4ac93dc4 100644 --- a/lib/libesp32_lvgl/freetype/src/smooth/ftsmerrs.h +++ b/lib/libesp32_lvgl/freetype/src/smooth/ftsmerrs.h @@ -4,7 +4,7 @@ * * smooth renderer error codes (specification only). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/smooth/ftsmooth.c b/lib/libesp32_lvgl/freetype/src/smooth/ftsmooth.c index 5d66bd6fc..9b0e8886c 100644 --- a/lib/libesp32_lvgl/freetype/src/smooth/ftsmooth.c +++ b/lib/libesp32_lvgl/freetype/src/smooth/ftsmooth.c @@ -4,7 +4,7 @@ * * Anti-aliasing renderer interface (body). * - * Copyright (C) 2000-2020 by + * Copyright (C) 2000-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -87,8 +87,10 @@ /* initialize renderer -- init its raster */ static FT_Error - ft_smooth_init( FT_Renderer render ) + ft_smooth_init( FT_Module module ) /* FT_Renderer */ { + FT_Renderer render = (FT_Renderer)module; + FT_Vector* sub = render->root.library->lcd_geometry; @@ -111,8 +113,10 @@ ft_smooth_lcd_spans( int y, int count, const FT_Span* spans, - TOrigin* target ) + void* target_ ) /* TOrigin* */ { + TOrigin* target = (TOrigin*)target_; + unsigned char* dst_line = target->origin - y * target->pitch; unsigned char* dst; unsigned short w; @@ -141,7 +145,7 @@ /* Set up direct rendering to record them on each third byte. */ params.source = outline; params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT; - params.gray_spans = (FT_SpanFunc)ft_smooth_lcd_spans; + params.gray_spans = ft_smooth_lcd_spans; params.user = ⌖ params.clip_box.xMin = 0; @@ -256,8 +260,11 @@ /* initialize renderer -- init its raster */ static FT_Error - ft_smooth_init( FT_Renderer render ) + ft_smooth_init( FT_Module module ) /* FT_Renderer */ { + FT_Renderer render = (FT_Renderer)module; + + /* set up default LCD filtering */ FT_Library_SetLcdFilter( render->root.library, FT_LCD_FILTER_DEFAULT ); @@ -340,8 +347,11 @@ ft_smooth_overlap_spans( int y, int count, const FT_Span* spans, - TOrigin* target ) + void* target_ ) { + TOrigin* target = (TOrigin*)target_; + + unsigned char* dst = target->origin - ( y / SCALE ) * target->pitch; unsigned short x; unsigned int cover, sum; @@ -386,7 +396,7 @@ /* Set up direct rendering to average oversampled spans. */ params.source = outline; params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT; - params.gray_spans = (FT_SpanFunc)ft_smooth_overlap_spans; + params.gray_spans = ft_smooth_overlap_spans; params.user = ⌖ params.clip_box.xMin = 0; diff --git a/lib/libesp32_lvgl/freetype/src/smooth/ftsmooth.h b/lib/libesp32_lvgl/freetype/src/smooth/ftsmooth.h index 22a88d54e..f8bdc9938 100644 --- a/lib/libesp32_lvgl/freetype/src/smooth/ftsmooth.h +++ b/lib/libesp32_lvgl/freetype/src/smooth/ftsmooth.h @@ -4,7 +4,7 @@ * * Anti-aliasing renderer interface (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/smooth/module.mk b/lib/libesp32_lvgl/freetype/src/smooth/module.mk index 9b1507f1e..82ab2fa59 100644 --- a/lib/libesp32_lvgl/freetype/src/smooth/module.mk +++ b/lib/libesp32_lvgl/freetype/src/smooth/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/smooth/rules.mk b/lib/libesp32_lvgl/freetype/src/smooth/rules.mk index b08056fac..5d89c7540 100644 --- a/lib/libesp32_lvgl/freetype/src/smooth/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/smooth/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/smooth/smooth.c b/lib/libesp32_lvgl/freetype/src/smooth/smooth.c index 04b531c08..9a0b824c2 100644 --- a/lib/libesp32_lvgl/freetype/src/smooth/smooth.c +++ b/lib/libesp32_lvgl/freetype/src/smooth/smooth.c @@ -4,7 +4,7 @@ * * FreeType anti-aliasing rasterer module component (body only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/svg/ftsvg.c b/lib/libesp32_lvgl/freetype/src/svg/ftsvg.c new file mode 100644 index 000000000..ba237f638 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/svg/ftsvg.c @@ -0,0 +1,355 @@ +/**************************************************************************** + * + * ftsvg.c + * + * The FreeType SVG renderer interface (body). + * + * Copyright (C) 2022-2023 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "ftsvg.h" +#include "svgtypes.h" + + + /************************************************************************** + * + * The macro FT_COMPONENT is used in trace mode. It is an implicit + * parameter of the FT_TRACE() and FT_ERROR() macros, usued to print/log + * messages during execution. + */ +#undef FT_COMPONENT +#define FT_COMPONENT otsvg + + +#ifdef FT_CONFIG_OPTION_SVG + + /* ft_svg_init */ + static FT_Error + ft_svg_init( FT_Module module ) + { + SVG_Renderer render = (SVG_Renderer)module; + + FT_Error error = FT_Err_Ok; + + + render->loaded = FALSE; + render->hooks_set = FALSE; + + return error; + } + + + static void + ft_svg_done( FT_Module module ) + { + SVG_Renderer render = (SVG_Renderer)module; + + + if ( render->loaded == TRUE && + render->hooks_set == TRUE ) + render->hooks.free_svg( &render->state ); + + render->loaded = FALSE; + } + + + static FT_Error + ft_svg_preset_slot( FT_Module module, + FT_GlyphSlot slot, + FT_Bool cache ) + { + SVG_Renderer svg_renderer = (SVG_Renderer)module; + SVG_RendererHooks hooks = svg_renderer->hooks; + + + if ( svg_renderer->hooks_set == FALSE ) + { + FT_TRACE1(( "Hooks are NOT set. Can't render OT-SVG glyphs\n" )); + return FT_THROW( Missing_SVG_Hooks ); + } + + if ( svg_renderer->loaded == FALSE ) + { + FT_TRACE3(( "ft_svg_preset_slot: first presetting call," + " calling init hook\n" )); + hooks.init_svg( &svg_renderer->state ); + + svg_renderer->loaded = TRUE; + } + + return hooks.preset_slot( slot, cache, &svg_renderer->state ); + } + + + static FT_Error + ft_svg_render( FT_Renderer renderer, + FT_GlyphSlot slot, + FT_Render_Mode mode, + const FT_Vector* origin ) + { + SVG_Renderer svg_renderer = (SVG_Renderer)renderer; + + FT_Library library = renderer->root.library; + FT_Memory memory = library->memory; + FT_Error error; + + FT_ULong size_image_buffer; + + SVG_RendererHooks hooks = svg_renderer->hooks; + + + FT_UNUSED( mode ); + FT_UNUSED( origin ); + + if ( mode != FT_RENDER_MODE_NORMAL ) + return FT_THROW( Bad_Argument ); + + if ( svg_renderer->hooks_set == FALSE ) + { + FT_TRACE1(( "Hooks are NOT set. Can't render OT-SVG glyphs\n" )); + return FT_THROW( Missing_SVG_Hooks ); + } + + if ( svg_renderer->loaded == FALSE ) + { + FT_TRACE3(( "ft_svg_render: first rendering, calling init hook\n" )); + error = hooks.init_svg( &svg_renderer->state ); + + svg_renderer->loaded = TRUE; + } + + ft_svg_preset_slot( (FT_Module)renderer, slot, TRUE ); + + size_image_buffer = (FT_ULong)slot->bitmap.pitch * slot->bitmap.rows; + /* No `FT_QALLOC` here since we need a clean, empty canvas */ + /* to start with. */ + if ( FT_ALLOC( slot->bitmap.buffer, size_image_buffer ) ) + return error; + + error = hooks.render_svg( slot, &svg_renderer->state ); + if ( error ) + FT_FREE( slot->bitmap.buffer ); + else + slot->internal->flags |= FT_GLYPH_OWN_BITMAP; + + return error; + } + + + static const SVG_Interface svg_interface = + { + ft_svg_preset_slot /* Preset_Bitmap_Func preset_slot */ + }; + + + static FT_Error + ft_svg_property_set( FT_Module module, + const char* property_name, + const void* value, + FT_Bool value_is_string ) + { + FT_Error error = FT_Err_Ok; + SVG_Renderer renderer = (SVG_Renderer)module; + + + if ( !ft_strcmp( property_name, "svg-hooks" ) ) + { + SVG_RendererHooks* hooks; + + + if ( value_is_string == TRUE ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + hooks = (SVG_RendererHooks*)value; + + if ( !hooks->init_svg || + !hooks->free_svg || + !hooks->render_svg || + !hooks->preset_slot ) + { + FT_TRACE0(( "ft_svg_property_set:" + " SVG rendering hooks not set because\n" )); + FT_TRACE0(( " " + " at least one function pointer is NULL\n" )); + + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + renderer->hooks = *hooks; + renderer->hooks_set = TRUE; + } + else + error = FT_THROW( Missing_Property ); + + Exit: + return error; + } + + + static FT_Error + ft_svg_property_get( FT_Module module, + const char* property_name, + void* value ) + { + FT_Error error = FT_Err_Ok; + SVG_Renderer renderer = (SVG_Renderer)module; + + + if ( !ft_strcmp( property_name, "svg-hooks" ) ) + { + SVG_RendererHooks* hooks = (SVG_RendererHooks*)value; + + + *hooks = renderer->hooks; + } + else + error = FT_THROW( Missing_Property ); + + return error; + } + + + FT_DEFINE_SERVICE_PROPERTIESREC( + ft_svg_service_properties, + + ft_svg_property_set, /* FT_Properties_SetFunc set_property */ + ft_svg_property_get /* FT_Properties_GetFunc get_property */ + ) + + + FT_DEFINE_SERVICEDESCREC1( + ft_svg_services, + FT_SERVICE_ID_PROPERTIES, &ft_svg_service_properties ) + + + FT_CALLBACK_DEF( FT_Module_Interface ) + ft_svg_get_interface( FT_Module module, + const char* ft_svg_interface ) + { + FT_Module_Interface result; + + + FT_UNUSED( module ); + + result = ft_service_list_lookup( ft_svg_services, ft_svg_interface ); + if ( result ) + return result; + + return 0; + } + + + static FT_Error + ft_svg_transform( FT_Renderer renderer, + FT_GlyphSlot slot, + const FT_Matrix* _matrix, + const FT_Vector* _delta ) + { + FT_SVG_Document doc = (FT_SVG_Document)slot->other; + FT_Matrix* matrix = (FT_Matrix*)_matrix; + FT_Vector* delta = (FT_Vector*)_delta; + + FT_Matrix tmp_matrix; + FT_Vector tmp_delta; + + FT_Matrix a, b; + FT_Pos x, y; + + + FT_UNUSED( renderer ); + + if ( !matrix ) + { + tmp_matrix.xx = 0x10000; + tmp_matrix.xy = 0; + tmp_matrix.yx = 0; + tmp_matrix.yy = 0x10000; + + matrix = &tmp_matrix; + } + + if ( !delta ) + { + tmp_delta.x = 0; + tmp_delta.y = 0; + + delta = &tmp_delta; + } + + a = doc->transform; + b = *matrix; + FT_Matrix_Multiply( &b, &a ); + + + x = ADD_LONG( ADD_LONG( FT_MulFix( matrix->xx, doc->delta.x ), + FT_MulFix( matrix->xy, doc->delta.y ) ), + delta->x ); + y = ADD_LONG( ADD_LONG( FT_MulFix( matrix->yx, doc->delta.x ), + FT_MulFix( matrix->yy, doc->delta.y ) ), + delta->y ); + + doc->delta.x = x; + doc->delta.y = y; + doc->transform = a; + + return FT_Err_Ok; + } + +#endif /* FT_CONFIG_OPTION_SVG */ + + +#ifdef FT_CONFIG_OPTION_SVG +#define PUT_SVG_MODULE( a ) a +#define SVG_GLYPH_FORMAT FT_GLYPH_FORMAT_SVG +#else +#define PUT_SVG_MODULE( a ) NULL +#define SVG_GLYPH_FORMAT FT_GLYPH_FORMAT_NONE +#endif + + + FT_DEFINE_RENDERER( + ft_svg_renderer_class, + + FT_MODULE_RENDERER, + sizeof ( SVG_RendererRec ), + + "ot-svg", + 0x10000L, + 0x20000L, + + (const void*)PUT_SVG_MODULE( &svg_interface ), /* module specific interface */ + + PUT_SVG_MODULE( ft_svg_init ), /* FT_Module_Constructor module_init */ + PUT_SVG_MODULE( ft_svg_done ), /* FT_Module_Destructor module_done */ + PUT_SVG_MODULE( ft_svg_get_interface ), /* FT_Module_Requester get_interface */ + + SVG_GLYPH_FORMAT, + + PUT_SVG_MODULE( ft_svg_render ), /* FT_Renderer_RenderFunc render_glyph */ + PUT_SVG_MODULE( ft_svg_transform ), /* FT_Renderer_TransformFunc transform_glyph */ + NULL, /* FT_Renderer_GetCBoxFunc get_glyph_cbox */ + NULL, /* FT_Renderer_SetModeFunc set_mode */ + NULL /* FT_Raster_Funcs* raster_class */ + ) + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/svg/ftsvg.h b/lib/libesp32_lvgl/freetype/src/svg/ftsvg.h new file mode 100644 index 000000000..9c496caa1 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/svg/ftsvg.h @@ -0,0 +1,35 @@ +/**************************************************************************** + * + * ftsvg.h + * + * The FreeType SVG renderer interface (specification). + * + * Copyright (C) 2022-2023 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + +#ifndef FTSVG_H_ +#define FTSVG_H_ + +#include +#include +#include + + +FT_BEGIN_HEADER + + FT_DECLARE_RENDERER( ft_svg_renderer_class ) + +FT_END_HEADER + +#endif /* FTSVG_H_ */ + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/svg/module.mk b/lib/libesp32_lvgl/freetype/src/svg/module.mk new file mode 100644 index 000000000..00beca60f --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/svg/module.mk @@ -0,0 +1,23 @@ +# +# FreeType 2 SVG renderer module definition +# + + +# Copyright (C) 2022-2023 by +# David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +FTMODULE_H_COMMANDS += SVG_MODULE + +define SVG_MODULE +$(OPEN_DRIVER) FT_Renderer_Class, ft_svg_renderer_class $(CLOSE_DRIVER) +$(ECHO_DRIVER)ot-svg $(ECHO_DRIVER_DESC)OT-SVG glyph renderer module$(ECHO_DRIVER_DONE) +endef + +# EOF diff --git a/lib/libesp32_lvgl/freetype/src/svg/rules.mk b/lib/libesp32_lvgl/freetype/src/svg/rules.mk new file mode 100644 index 000000000..4f4409755 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/svg/rules.mk @@ -0,0 +1,70 @@ +# +# FreeType 2 SVG renderer module build rules +# + + +# Copyright (C) 2022-2023 by +# David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# SVG renderer driver directory +# +SVG_DIR := $(SRC_DIR)/svg + +# compilation flags for the driver +# +SVG_COMPILE := $(CC) $(ANSIFLAGS) \ + $I$(subst /,$(COMPILER_SEP),$(SVG_DIR)) \ + $(INCLUDE_FLAGS) \ + $(FT_CFLAGS) + +# SVG renderer sources (i.e., C files) +# +SVG_DRV_SRC := $(SVG_DIR)/ftsvg.c + + +# SVG renderer headers +# +SVG_DRV_H := $(SVG_DIR)/ftsvg.h \ + $(SVG_DIR)/svgtypes.h + + +# SVG renderer object(s) +# +# SVG_DRV_OBJ_M is used during `multi' builds. +# SVG_DRV_OBJ_S is used during `single' builds. +# +SVG_DRV_OBJ_M := $(SVG_DRV_SRC:$(SVG_DIR)/%.c=$(OBJ_DIR)/%.$O) +SVG_DRV_OBJ_S := $(OBJ_DIR)/svg.$O + +# SVG renderer source file for single build +# +SVG_DRV_SRC_S := $(SVG_DIR)/svg.c + + +# SVG renderer - single object +# +$(SVG_DRV_OBJ_S): $(SVG_DRV_SRC_S) $(SVG_DRV_SRC) \ + $(FREETYPE_H) $(SVG_DRV_H) + $(SVG_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(SVG_DRV_SRC_S)) + + +# SVG renderer - multiple objects +# +$(OBJ_DIR)/%.$O: $(SVG_DIR)/%.c $(FREETYPE_H) $(SVG_DRV_H) + $(SVG_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<) + + +# update main driver object lists +# +DRV_OBJS_S += $(SVG_DRV_OBJ_S) +DRV_OBJS_M += $(SVG_DRV_OBJ_M) + + +# EOF diff --git a/lib/libesp32_lvgl/freetype/src/svg/svg.c b/lib/libesp32_lvgl/freetype/src/svg/svg.c new file mode 100644 index 000000000..373c28ed9 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/svg/svg.c @@ -0,0 +1,24 @@ +/**************************************************************************** + * + * svg.c + * + * FreeType SVG renderer module component (body only). + * + * Copyright (C) 2022-2023 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include "svgtypes.h" +#include "ftsvg.c" + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/svg/svgtypes.h b/lib/libesp32_lvgl/freetype/src/svg/svgtypes.h new file mode 100644 index 000000000..1d608032c --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/svg/svgtypes.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * + * svgtypes.h + * + * The FreeType SVG renderer internal types (specification). + * + * Copyright (C) 2022-2023 by + * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + +#ifndef SVGTYPES_H_ +#define SVGTYPES_H_ + +#include +#include +#include +#include + + + typedef struct SVG_RendererRec_ + { + FT_RendererRec root; /* this inherits FT_RendererRec */ + FT_Bool loaded; + FT_Bool hooks_set; + SVG_RendererHooks hooks; /* this holds hooks for SVG rendering */ + FT_Pointer state; /* a place for hooks to store state, if needed */ + + } SVG_RendererRec; + + typedef struct SVG_RendererRec_* SVG_Renderer; + +#endif /* SVGTYPES_H_ */ + + +/* EOF */ diff --git a/lib/libesp32_lvgl/freetype/src/tools/afblue.pl b/lib/libesp32_lvgl/freetype/src/tools/afblue.pl new file mode 100644 index 000000000..1098e30ab --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/afblue.pl @@ -0,0 +1,551 @@ +#! /usr/bin/perl -w +# -*- Perl -*- +# +# afblue.pl +# +# Process a blue zone character data file. +# +# Copyright (C) 2013-2023 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, +# modified, and distributed under the terms of the FreeType project +# license, LICENSE.TXT. By continuing to use, modify, or distribute +# this file you indicate that you have read the license and +# understand and accept it fully. + +use strict; +use warnings; +use English '-no_match_vars'; +use open ':std', ':encoding(UTF-8)'; + + +my $prog = $PROGRAM_NAME; +$prog =~ s| .* / ||x; # Remove path. + +die "usage: $prog datafile < infile > outfile\n" if $#ARGV != 0; + + +my $datafile = $ARGV[0]; + +my %diversions; # The extracted and massaged data from `datafile'. +my @else_stack; # Booleans to track else-clauses. +my @name_stack; # Stack of integers used for names of aux. variables. + +my $curr_enum; # Name of the current enumeration. +my $curr_array; # Name of the current array. +my $curr_max; # Name of the current maximum value. + +my $curr_enum_element; # Name of the current enumeration element. +my $curr_offset; # The offset relative to current aux. variable. +my $curr_elem_size; # The number of non-space characters in the current string or + # the number of elements in the current block. + +my $have_sections = 0; # Boolean; set if start of a section has been seen. +my $have_strings; # Boolean; set if current section contains strings. +my $have_blocks; # Boolean; set if current section contains blocks. + +my $have_enum_element; # Boolean; set if we have an enumeration element. +my $in_string; # Boolean; set if a string has been parsed. + +my $num_sections = 0; # Number of sections seen so far. + +my $last_aux; # Name of last auxiliary variable. + + +# Regular expressions. + +# [] [] ':' [] '\n' +my $section_re = qr/ ^ \s* (\S+) \s+ (\S+) \s+ (\S+) \s* : \s* $ /x; + +# [] [] '\n' +my $enum_element_re = qr/ ^ \s* ( [A-Za-z0-9_]+ ) \s* $ /x; + +# '#' '\n' +my $preprocessor_re = qr/ ^ \# /x; + +# [] '/' '/' '\n' +my $comment_re = qr| ^ \s* // |x; + +# empty line +my $whitespace_only_re = qr/ ^ \s* $ /x; + +# [] '"' '"' [] '\n' ( doesn't contain newlines) +my $string_re = qr/ ^ \s* + " ( (?> (?: (?> [^"\\]+ ) | \\. )* ) ) " + \s* $ /x; + +# [] '{' '}' [] '\n' ( can contain newlines) +my $block_start_re = qr/ ^ \s* \{ /x; + +# We need the capturing group for `split' to make it return the separator +# tokens (i.e., the opening and closing brace) also. +my $brace_re = qr/ ( [{}] ) /x; + + +sub Warn +{ + my $message = shift; + warn "$datafile:$INPUT_LINE_NUMBER: warning: $message\n"; +} + + +sub Die +{ + my $message = shift; + die "$datafile:$INPUT_LINE_NUMBER: error: $message\n"; +} + + +my $warned_before = 0; + +sub warn_before +{ + Warn("data before first section gets ignored") unless $warned_before; + $warned_before = 1; +} + + +sub strip_newline +{ + chomp; + s/ \x0D $ //x; +} + + +sub end_curr_string +{ + # Append final null byte to string. + if ($have_strings) + { + push @{$diversions{$curr_array}}, " '\\0',\n" if $in_string; + + $curr_offset++; + $in_string = 0; + } +} + + +sub update_max_elem_size +{ + if ($curr_elem_size) + { + my $max = pop @{$diversions{$curr_max}}; + $max = $curr_elem_size if $curr_elem_size > $max; + push @{$diversions{$curr_max}}, $max; + } +} + + +sub convert_non_ascii_char +{ + # A UTF-8 character outside of the printable ASCII range, with possibly a + # leading backslash character. + my $s = shift; + + # Here we count characters, not bytes. + $curr_elem_size += length $s; + + utf8::encode($s); + $s = uc unpack 'H*', $s; + + $curr_offset += $s =~ s/\G(..)/'\\x$1', /sg; + + return $s; +} + + +sub convert_ascii_chars +{ + # A series of ASCII characters in the printable range. + my $s = shift; + + # We reduce multiple space characters to a single one. + $s =~ s/ +/ /g; + + # Count all non-space characters. Note that `()' applies a list context + # to the capture that is used to count the elements. + $curr_elem_size += () = $s =~ /[^ ]/g; + + $curr_offset += $s =~ s/\G(.)/'$1', /g; + + return $s; +} + + +sub convert_literal +{ + my $s = shift; + my $orig = $s; + + # ASCII printables and space + my $safe_re = '\x20-\x7E'; + # ASCII printables and space, no backslash + my $safe_no_backslash_re = '\x20-\x5B\x5D-\x7E'; + + $s =~ s{ + (?: \\? ( [^$safe_re] ) + | ( (?: [$safe_no_backslash_re] + | \\ [$safe_re] )+ ) ) + } + { + defined($1) ? convert_non_ascii_char($1) + : convert_ascii_chars($2) + }egx; + + # We assume that `$orig' doesn't contain `*/' + return $s . " /* $orig */"; +} + + +sub aux_name +{ + return "af_blue_" . $num_sections. "_" . join('_', @name_stack); +} + + +sub aux_name_next +{ + $name_stack[$#name_stack]++; + my $name = aux_name(); + $name_stack[$#name_stack]--; + + return $name; +} + + +sub enum_val_string +{ + # Build string that holds code to save the current offset in an + # enumeration element. + my $aux = shift; + + my $add = ($last_aux eq "af_blue_" . $num_sections . "_0" ) + ? "" + : "$last_aux + "; + + return " $aux = $add$curr_offset,\n"; +} + + + +# Process data file. + +open(DATA, $datafile) || die "$prog: can't open \`$datafile': $OS_ERROR\n"; + +while () +{ + strip_newline(); + + next if /$comment_re/; + next if /$whitespace_only_re/; + + if (/$section_re/) + { + Warn("previous section is empty") if ($have_sections + && !$have_strings + && !$have_blocks); + + end_curr_string(); + update_max_elem_size(); + + # Save captured groups from `section_re'. + $curr_enum = $1; + $curr_array = $2; + $curr_max = $3; + + $curr_enum_element = ""; + $curr_offset = 0; + + Warn("overwriting already defined enumeration \`$curr_enum'") + if exists($diversions{$curr_enum}); + Warn("overwriting already defined array \`$curr_array'") + if exists($diversions{$curr_array}); + Warn("overwriting already defined maximum value \`$curr_max'") + if exists($diversions{$curr_max}); + + $diversions{$curr_enum} = []; + $diversions{$curr_array} = []; + $diversions{$curr_max} = []; + + push @{$diversions{$curr_max}}, 0; + + @name_stack = (); + push @name_stack, 0; + + $have_sections = 1; + $have_strings = 0; + $have_blocks = 0; + + $have_enum_element = 0; + $in_string = 0; + + $num_sections++; + $curr_elem_size = 0; + + $last_aux = aux_name(); + + next; + } + + if (/$preprocessor_re/) + { + if ($have_sections) + { + # Having preprocessor conditionals complicates the computation of + # correct offset values. We have to introduce auxiliary enumeration + # elements with the name `af_blue____...' that store + # offsets to be used in conditional clauses. `' is the number of + # sections seen so far, `' is the number of `#if' and `#endif' + # conditionals seen so far in the topmost level, `' the number of + # `#if' and `#endif' conditionals seen so far one level deeper, etc. + # As a consequence, uneven values are used within a clause, and even + # values after a clause, since the C standard doesn't allow the + # redefinition of an enumeration value. For example, the name + # `af_blue_5_1_6' is used to construct enumeration values in the fifth + # section after the third (second-level) if-clause within the first + # (top-level) if-clause. After the first top-level clause has + # finished, `af_blue_5_2' is used. The current offset is then + # relative to the value stored in the current auxiliary element. + + if (/ ^ \# \s* if /x) + { + push @else_stack, 0; + + $name_stack[$#name_stack]++; + + push @{$diversions{$curr_enum}}, enum_val_string(aux_name()); + $last_aux = aux_name(); + + push @name_stack, 0; + + $curr_offset = 0; + } + elsif (/ ^ \# \s* elif /x) + { + Die("unbalanced #elif") unless @else_stack; + + pop @name_stack; + + push @{$diversions{$curr_enum}}, enum_val_string(aux_name_next()); + $last_aux = aux_name(); + + push @name_stack, 0; + + $curr_offset = 0; + } + elsif (/ ^ \# \s* else /x) + { + my $prev_else = pop @else_stack; + Die("unbalanced #else") unless defined($prev_else); + Die("#else already seen") if $prev_else; + push @else_stack, 1; + + pop @name_stack; + + push @{$diversions{$curr_enum}}, enum_val_string(aux_name_next()); + $last_aux = aux_name(); + + push @name_stack, 0; + + $curr_offset = 0; + } + elsif (/ ^ (\# \s*) endif /x) + { + my $prev_else = pop @else_stack; + Die("unbalanced #endif") unless defined($prev_else); + + pop @name_stack; + + # If there is no else-clause for an if-clause, we add one. This is + # necessary to have correct offsets. + if (!$prev_else) + { + # Use amount of whitespace from `endif'. + push @{$diversions{$curr_enum}}, enum_val_string(aux_name_next()) + . $1 . "else\n"; + $last_aux = aux_name(); + + $curr_offset = 0; + } + + $name_stack[$#name_stack]++; + + push @{$diversions{$curr_enum}}, enum_val_string(aux_name()); + $last_aux = aux_name(); + + $curr_offset = 0; + } + + # Handle (probably continued) preprocessor lines. + CONTINUED_LOOP: + { + do + { + strip_newline(); + + push @{$diversions{$curr_enum}}, $ARG . "\n"; + push @{$diversions{$curr_array}}, $ARG . "\n"; + + last CONTINUED_LOOP unless / \\ $ /x; + + } while (); + } + } + else + { + warn_before(); + } + + next; + } + + if (/$enum_element_re/) + { + end_curr_string(); + update_max_elem_size(); + + $curr_enum_element = $1; + $have_enum_element = 1; + $curr_elem_size = 0; + + next; + } + + if (/$string_re/) + { + if ($have_sections) + { + Die("strings and blocks can't be mixed in a section") if $have_blocks; + + # Save captured group from `string_re'. + my $string = $1; + + if ($have_enum_element) + { + push @{$diversions{$curr_enum}}, enum_val_string($curr_enum_element); + $have_enum_element = 0; + } + + $string = convert_literal($string); + + push @{$diversions{$curr_array}}, " $string\n"; + + $have_strings = 1; + $in_string = 1; + } + else + { + warn_before(); + } + + next; + } + + if (/$block_start_re/) + { + if ($have_sections) + { + Die("strings and blocks can't be mixed in a section") if $have_strings; + + my $depth = 0; + my $block = ""; + my $block_end = 0; + + # Count braces while getting the block. + BRACE_LOOP: + { + do + { + strip_newline(); + + foreach my $substring (split(/$brace_re/)) + { + if ($block_end) + { + Die("invalid data after last matching closing brace") + if $substring !~ /$whitespace_only_re/; + } + + $block .= $substring; + + if ($substring eq '{') + { + $depth++; + } + elsif ($substring eq '}') + { + $depth--; + + $block_end = 1 if $depth == 0; + } + } + + # If we are here, we have run out of substrings, so get next line + # or exit. + last BRACE_LOOP if $block_end; + + $block .= "\n"; + + } while (); + } + + if ($have_enum_element) + { + push @{$diversions{$curr_enum}}, enum_val_string($curr_enum_element); + $have_enum_element = 0; + } + + push @{$diversions{$curr_array}}, $block . ",\n"; + + $curr_offset++; + $curr_elem_size++; + + $have_blocks = 1; + } + else + { + warn_before(); + } + + next; + } + + # Garbage. We weren't able to parse the data. + Die("syntax error"); +} + +# Finalize data. +end_curr_string(); +update_max_elem_size(); + + +# Filter stdin to stdout, replacing `@...@' templates. + +sub emit_diversion +{ + my $diversion_name = shift; + return (exists($diversions{$1})) ? "@{$diversions{$1}}" + : "@" . $diversion_name . "@"; +} + + +$LIST_SEPARATOR = ''; + +my $s1 = "This file has been generated by the Perl script \`$prog',"; +my $s1len = length $s1; +my $s2 = "using data from file \`$datafile'."; +my $s2len = length $s2; +my $slen = ($s1len > $s2len) ? $s1len : $s2len; + +print "/* " . $s1 . " " x ($slen - $s1len) . " */\n" + . "/* " . $s2 . " " x ($slen - $s2len) . " */\n" + . "\n"; + +while () +{ + s/ @ ( [A-Za-z0-9_]+? ) @ / emit_diversion($1) /egx; + print; +} + +# EOF diff --git a/lib/libesp32_lvgl/freetype/src/tools/apinames.c b/lib/libesp32_lvgl/freetype/src/tools/apinames.c new file mode 100644 index 000000000..dfa258fd7 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/apinames.c @@ -0,0 +1,556 @@ +/* + * This little program is used to parse the FreeType headers and + * find the declaration of all public APIs. This is easy, because + * they all look like the following: + * + * FT_EXPORT( return_type ) + * function_name( function arguments ); + * + * You must pass the list of header files as arguments. Wildcards are + * accepted if you are using GCC for compilation (and probably by + * other compilers too). + * + * Author: FreeType team, 2005-2019 + * + * This code is explicitly placed into the public domain. + * + */ + +#include +#include +#include +#include +#include + +#include "vms_shorten_symbol.c" + +#define PROGRAM_NAME "apinames" +#define PROGRAM_VERSION "0.5" + +#define LINEBUFF_SIZE 1024 + + +typedef enum OutputFormat_ +{ + OUTPUT_LIST = 0, /* output the list of names, one per line */ + OUTPUT_WINDOWS_DEF, /* output a Windows .DEF file for Visual C++ or Mingw */ + OUTPUT_BORLAND_DEF, /* output a Windows .DEF file for Borland C++ */ + OUTPUT_WATCOM_LBC, /* output a Watcom Linker Command File */ + OUTPUT_VMS_OPT, /* output an OpenVMS Linker Option File */ + OUTPUT_NETWARE_IMP, /* output a NetWare ImportFile */ + OUTPUT_GNU_VERMAP /* output a version map for GNU or Solaris linker */ + +} OutputFormat; + + +static void +panic( const char* fmt, + ... ) +{ + va_list ap; + + + fprintf( stderr, "PANIC: " ); + + va_start( ap, fmt ); + vfprintf( stderr, fmt, ap ); + va_end( ap ); + + fprintf( stderr, "\n" ); + + exit(2); +} + + +typedef struct NameRec_ +{ + char* name; + unsigned int hash; + +} NameRec, *Name; + + +static Name the_names; +static int num_names; +static int max_names; + + +static void +names_add( const char* name, + const char* end ) +{ + unsigned int h; + int nn, len; + Name nm; + + + if ( end <= name ) + return; + + /* compute hash value */ + len = (int)( end - name ); + h = 0; + + for ( nn = 0; nn < len; nn++ ) + h = h * 33 + name[nn]; + + /* check for an pre-existing name */ + for ( nn = 0; nn < num_names; nn++ ) + { + nm = the_names + nn; + + if ( (int)nm->hash == h && + memcmp( name, nm->name, len ) == 0 && + nm->name[len] == 0 ) + return; + } + + /* add new name */ + if ( num_names >= max_names ) + { + max_names += ( max_names >> 1 ) + 4; + the_names = (NameRec*)realloc( the_names, + sizeof ( the_names[0] ) * max_names ); + if ( !the_names ) + panic( "not enough memory" ); + } + nm = &the_names[num_names++]; + + nm->hash = h; + nm->name = (char*)malloc( len + 1 ); + if ( !nm->name ) + panic( "not enough memory" ); + + memcpy( nm->name, name, len ); + nm->name[len] = 0; +} + + +static int +name_compare( const void* name1, + const void* name2 ) +{ + Name n1 = (Name)name1; + Name n2 = (Name)name2; + + return strcmp( n1->name, n2->name ); +} + + +static void +names_sort( void ) +{ + qsort( the_names, (size_t)num_names, + sizeof ( the_names[0] ), name_compare ); +} + + +static void +names_dump( FILE* out, + OutputFormat format, + const char* dll_name ) +{ + int nn; + + + switch ( format ) + { + case OUTPUT_WINDOWS_DEF: + if ( dll_name ) + fprintf( out, "LIBRARY %s\n", dll_name ); + + fprintf( out, "DESCRIPTION FreeType 2 DLL\n" ); + fprintf( out, "EXPORTS\n" ); + + for ( nn = 0; nn < num_names; nn++ ) + fprintf( out, " %s\n", the_names[nn].name ); + + break; + + case OUTPUT_BORLAND_DEF: + if ( dll_name ) + fprintf( out, "LIBRARY %s\n", dll_name ); + + fprintf( out, "DESCRIPTION FreeType 2 DLL\n" ); + fprintf( out, "EXPORTS\n" ); + + for ( nn = 0; nn < num_names; nn++ ) + fprintf( out, " _%s\n", the_names[nn].name ); + + break; + + case OUTPUT_WATCOM_LBC: + { + const char* dot; + + + if ( !dll_name ) + { + fprintf( stderr, + "you must provide a DLL name with the -d option!\n" ); + exit( 4 ); + } + + /* we must omit the `.dll' suffix from the library name */ + dot = strchr( dll_name, '.' ); + if ( dot ) + { + char temp[512]; + int len = dot - dll_name; + + + if ( len > (int)( sizeof ( temp ) - 1 ) ) + len = sizeof ( temp ) - 1; + + memcpy( temp, dll_name, len ); + temp[len] = 0; + + dll_name = (const char*)temp; + } + + for ( nn = 0; nn < num_names; nn++ ) + fprintf( out, "++_%s.%s.%s\n", + the_names[nn].name, dll_name, the_names[nn].name ); + } + + break; + + case OUTPUT_VMS_OPT: + fprintf( out, "case_sensitive=YES\n" ); + + for ( nn = 0; nn < num_names; nn++ ) + { + char short_symbol[32]; + + + if ( vms_shorten_symbol( the_names[nn].name, short_symbol, 1 ) == -1 ) + panic( "could not shorten name '%s'", the_names[nn].name ); + fprintf( out, "symbol_vector = ( %s = PROCEDURE)\n", short_symbol ); + + /* Also emit a 64-bit symbol, as created by the `vms_auto64` tool. */ + /* It has the string '64__' appended to its name. */ + strcat( the_names[nn].name , "64__" ); + if ( vms_shorten_symbol( the_names[nn].name, short_symbol, 1 ) == -1 ) + panic( "could not shorten name '%s'", the_names[nn].name ); + fprintf( out, "symbol_vector = ( %s = PROCEDURE)\n", short_symbol ); + } + + break; + + case OUTPUT_NETWARE_IMP: + if ( dll_name ) + fprintf( out, " (%s)\n", dll_name ); + + for ( nn = 0; nn < num_names - 1; nn++ ) + fprintf( out, " %s,\n", the_names[nn].name ); + fprintf( out, " %s\n", the_names[num_names - 1].name ); + + break; + + case OUTPUT_GNU_VERMAP: + fprintf( out, "{\n\tglobal:\n" ); + + for ( nn = 0; nn < num_names; nn++ ) + fprintf( out, "\t\t%s;\n", the_names[nn].name ); + + fprintf( out, "\tlocal:\n\t\t*;\n};\n" ); + + break; + + default: /* LIST */ + for ( nn = 0; nn < num_names; nn++ ) + fprintf( out, "%s\n", the_names[nn].name ); + + break; + } +} + + +/* states of the line parser */ + +typedef enum State_ +{ + STATE_START = 0, /* waiting for FT_EXPORT keyword and return type */ + STATE_TYPE /* type was read, waiting for function name */ + +} State; + + +static int +read_header_file( FILE* file, + int verbose ) +{ + static char buff[LINEBUFF_SIZE + 1]; + State state = STATE_START; + + + while ( !feof( file ) ) + { + char* p; + + + if ( !fgets( buff, LINEBUFF_SIZE, file ) ) + break; + + p = buff; + + /* skip leading whitespace */ + while ( *p && ( *p == ' ' || *p == '\\' ) ) + p++; + + /* skip empty lines */ + if ( *p == '\n' || *p == '\r' ) + continue; + + switch ( state ) + { + case STATE_START: + if ( memcmp( p, "FT_EXPORT(", 10 ) != 0 ) + break; + + p += 10; + for (;;) + { + if ( *p == 0 || *p == '\n' || *p == '\r' ) + goto NextLine; + + if ( *p == ')' ) + { + p++; + break; + } + + p++; + } + + state = STATE_TYPE; + + /* + * Sometimes, the name is just after `FT_EXPORT(...)', so skip + * whitespace and fall-through if we find an alphanumeric character. + */ + while ( *p == ' ' || *p == '\t' ) + p++; + + if ( !isalpha( *p ) ) + break; + + /* fall-through */ + + case STATE_TYPE: + { + char* name = p; + + + while ( isalnum( *p ) || *p == '_' ) + p++; + + if ( p > name ) + { + if ( verbose ) + fprintf( stderr, ">>> %.*s\n", (int)( p - name ), name ); + + names_add( name, p ); + } + + state = STATE_START; + } + + break; + + default: + ; + } + +NextLine: + ; + } /* end of while loop */ + + return 0; +} + + +static void +usage( void ) +{ + static const char* const format = + "%s %s: extract FreeType API names from header files\n" + "\n" + "This program extracts the list of public FreeType API functions.\n" + "It receives a list of header files as an argument and\n" + "generates a sorted list of unique identifiers in various formats.\n" + "\n" + "usage: %s header1 [options] [header2 ...]\n" + "\n" + "options: - parse the contents of stdin, ignore arguments\n" + " -v verbose mode, output sent to standard error\n" + " -oFILE write output to FILE instead of standard output\n" + " -dNAME indicate DLL file name, 'freetype.dll' by default\n" + " -w output .DEF file for Visual C++ and Mingw\n" + " -wB output .DEF file for Borland C++\n" + " -wW output Watcom Linker Response File\n" + " -wV output OpenVMS Linker Options File\n" + " -wN output NetWare Import File\n" + " -wL output version map for GNU or Solaris linker\n" + "\n"; + + fprintf( stderr, + format, + PROGRAM_NAME, + PROGRAM_VERSION, + PROGRAM_NAME ); + + exit( 1 ); +} + + +int +main( int argc, + const char* const* argv ) +{ + int from_stdin = 0; + int verbose = 0; + OutputFormat format = OUTPUT_LIST; /* the default */ + FILE* out = stdout; + const char* library_name = NULL; + + + if ( argc < 2 ) + usage(); + + /* `-' used as a single argument means read source file from stdin */ + while ( argc > 1 && argv[1][0] == '-' ) + { + const char* arg = argv[1]; + + + switch ( arg[1] ) + { + case 'v': + verbose = 1; + + break; + + case 'o': + if ( arg[2] == 0 ) + { + if ( argc < 2 ) + usage(); + + arg = argv[2]; + argv++; + argc--; + } + else + arg += 2; + + out = fopen( arg, "wt" ); + if ( !out ) + { + fprintf( stderr, "could not open '%s' for writing\n", arg ); + exit( 3 ); + } + + break; + + case 'd': + if ( arg[2] == 0 ) + { + if ( argc < 2 ) + usage(); + + arg = argv[2]; + argv++; + argc--; + } + else + arg += 2; + + library_name = arg; + + break; + + case 'w': + format = OUTPUT_WINDOWS_DEF; + + switch ( arg[2] ) + { + case 'B': + format = OUTPUT_BORLAND_DEF; + break; + + case 'W': + format = OUTPUT_WATCOM_LBC; + break; + + case 'V': + format = OUTPUT_VMS_OPT; + break; + + case 'N': + format = OUTPUT_NETWARE_IMP; + break; + + case 'L': + format = OUTPUT_GNU_VERMAP; + break; + + case 0: + break; + + default: + usage(); + } + + break; + + case 0: + from_stdin = 1; + + break; + + default: + usage(); + } + + argc--; + argv++; + + } /* end of while loop */ + + if ( from_stdin ) + read_header_file( stdin, verbose ); + else + { + for ( --argc, argv++; argc > 0; argc--, argv++ ) + { + FILE* file = fopen( argv[0], "rb" ); + + + if ( !file ) + fprintf( stderr, "unable to open '%s'\n", argv[0] ); + else + { + if ( verbose ) + fprintf( stderr, "opening '%s'\n", argv[0] ); + + read_header_file( file, verbose ); + fclose( file ); + } + } + } + + if ( num_names == 0 ) + panic( "could not find exported functions\n" ); + + names_sort(); + names_dump( out, format, library_name ); + + if ( out != stdout ) + fclose( out ); + + return 0; +} + + +/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/tools/chktrcmp.py b/lib/libesp32_lvgl/freetype/src/tools/chktrcmp.py new file mode 100755 index 000000000..d072a8786 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/chktrcmp.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +# +# Check trace components in FreeType 2 source. +# Author: suzuki toshiya, 2009, 2013, 2020 +# +# This code is explicitly into the public domain. + +import sys +import os +import re + +SRC_FILE_LIST = [] +USED_COMPONENT = {} +KNOWN_COMPONENT = {} + +SRC_FILE_DIRS = ["src"] +TRACE_DEF_FILES = ["include/freetype/internal/fttrace.h"] + + +def usage(): + print("Usage: %s [option]" % sys.argv[0]) + print("Search used-but-defined and defined-but-not-used trace_XXX macros") + print("") + print(" --help:") + print(" Show this help") + print("") + print(" --src-dirs=dir1:dir2:...") + print(" Specify the directories of C source files to be checked") + print(" Default is %s" % ":".join(SRC_FILE_DIRS)) + print("") + print(" --def-files=file1:file2:...") + print(" Specify the header files including FT_TRACE_DEF()") + print(" Default is %s" % ":".join(TRACE_DEF_FILES)) + print("") + + +# -------------------------------------------------------------- +# Parse command line options +# +for i in range(1, len(sys.argv)): + if sys.argv[i].startswith("--help"): + usage() + exit(0) + if sys.argv[i].startswith("--src-dirs="): + SRC_FILE_DIRS = sys.argv[i].replace("--src-dirs=", "", 1).split(":") + elif sys.argv[i].startswith("--def-files="): + TRACE_DEF_FILES = sys.argv[i].replace("--def-files=", "", 1).split(":") + +# -------------------------------------------------------------- +# Scan C source and header files using trace macros. +# + +c_pathname_pat = re.compile('^.*\.[ch]$', re.IGNORECASE) +trace_use_pat = re.compile('^[ \t]*#define[ \t]+FT_COMPONENT[ \t]+') + +for d in SRC_FILE_DIRS: + for (p, dlst, flst) in os.walk(d): + for f in flst: + if c_pathname_pat.match(f) is not None: + src_pathname = os.path.join(p, f) + + line_num = 0 + for src_line in open(src_pathname, 'r'): + line_num = line_num + 1 + src_line = src_line.strip() + if trace_use_pat.match(src_line) is not None: + component_name = trace_use_pat.sub('', src_line) + if component_name in USED_COMPONENT: + USED_COMPONENT[component_name]\ + .append("%s:%d" % (src_pathname, line_num)) + else: + USED_COMPONENT[component_name] =\ + ["%s:%d" % (src_pathname, line_num)] + +# -------------------------------------------------------------- +# Scan header file(s) defining trace macros. +# + +trace_def_pat_opn = re.compile('^.*FT_TRACE_DEF[ \t]*\([ \t]*') +trace_def_pat_cls = re.compile('[ \t\)].*$') + +for f in TRACE_DEF_FILES: + line_num = 0 + for hdr_line in open(f, 'r'): + line_num = line_num + 1 + hdr_line = hdr_line.strip() + if trace_def_pat_opn.match(hdr_line) is not None: + component_name = trace_def_pat_opn.sub('', hdr_line) + component_name = trace_def_pat_cls.sub('', component_name) + if component_name in KNOWN_COMPONENT: + print("trace component %s is defined twice," + " see %s and fttrace.h:%d" % + (component_name, KNOWN_COMPONENT[component_name], + line_num)) + else: + KNOWN_COMPONENT[component_name] =\ + "%s:%d" % (os.path.basename(f), line_num) + +# -------------------------------------------------------------- +# Compare the used and defined trace macros. +# + +print("# Trace component used in the implementations but not defined in " + "fttrace.h.") +cmpnt = list(USED_COMPONENT.keys()) +cmpnt.sort() +for c in cmpnt: + if c not in KNOWN_COMPONENT: + print("Trace component %s (used in %s) is not defined." % + (c, ", ".join(USED_COMPONENT[c]))) + +print("# Trace component is defined but not used in the implementations.") +cmpnt = list(KNOWN_COMPONENT.keys()) +cmpnt.sort() +for c in cmpnt: + if c not in USED_COMPONENT: + if c != "any": + print("Trace component %s (defined in %s) is not used." % + (c, KNOWN_COMPONENT[c])) diff --git a/lib/libesp32_lvgl/freetype/src/tools/cordic.py b/lib/libesp32_lvgl/freetype/src/tools/cordic.py new file mode 100644 index 000000000..651142988 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/cordic.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +# compute arctangent table for CORDIC computations in fttrigon.c +import math + +# units = 64*65536.0 # don't change !! +units = 180 * 2 ** 16 +scale = units / math.pi +shrink = 1.0 +angles2 = [] + +print("") +print("table of arctan( 1/2^n ) for PI = " + repr(units / 65536.0) + " units") + +for n in range(1, 32): + + x = 0.5 ** n # tangent value + + angle = math.atan(x) # arctangent + angle2 = round(angle * scale) # arctangent in FT_Angle units + + if angle2 <= 0: + break + + angles2.append(repr(int(angle2))) + shrink /= math.sqrt(1 + x * x) + +print(", ".join(angles2)) +print("shrink factor = " + repr(shrink)) +print("shrink factor 2 = " + repr(int(shrink * (2 ** 32)))) +print("expansion factor = " + repr(1 / shrink)) +print("") diff --git a/lib/libesp32_lvgl/freetype/src/tools/ftrandom/Makefile b/lib/libesp32_lvgl/freetype/src/tools/ftrandom/Makefile new file mode 100644 index 000000000..24dc49c56 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/ftrandom/Makefile @@ -0,0 +1,45 @@ +# TOP_DIR and OBJ_DIR should be set by the user to the right directories, +# if necessary. + +TOP_DIR ?= ../../.. +OBJ_DIR ?= $(TOP_DIR)/objs + + +# The setup below is for gcc on a Unix-like platform, +# where FreeType has been set up to create a static library +# (which is the default). + +VPATH = $(OBJ_DIR) \ + $(OBJ_DIR)/.libs + +SRC_DIR = $(TOP_DIR)/src/tools/ftrandom + +CC = gcc +WFLAGS = -Wmissing-prototypes \ + -Wunused \ + -Wimplicit \ + -Wreturn-type \ + -Wparentheses \ + -pedantic \ + -Wformat \ + -Wchar-subscripts \ + -Wsequence-point +CFLAGS = $(WFLAGS) \ + -g +INCLUDES = -I $(TOP_DIR)/include +LDFLAGS = +LIBS = -lm \ + -lz \ + -lpng \ + -lbz2 \ + -lharfbuzz + +all: $(OBJ_DIR)/ftrandom + +$(OBJ_DIR)/ftrandom.o: $(SRC_DIR)/ftrandom.c + $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< + +$(OBJ_DIR)/ftrandom: $(OBJ_DIR)/ftrandom.o libfreetype.a + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +# EOF diff --git a/lib/libesp32_lvgl/freetype/src/tools/ftrandom/README b/lib/libesp32_lvgl/freetype/src/tools/ftrandom/README new file mode 100644 index 000000000..7c610864b --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/ftrandom/README @@ -0,0 +1,69 @@ +ftrandom +======== + +This program expects a set of directories containing good fonts, and a set +of extensions of fonts to be tested. It will randomly pick a font, copy it, +introduce an error and then test it. + +The FreeType tests are quite basic; for each erroneous font ftrandom + + . forks off a new tester, + . initializes the library, + . opens each font in the file, + . loads each glyph, + . optionally reviews the contours of the glyph, + . optionally rasterizes the glyph, and + . closes the face. + +If a tester takes longer than 20 seconds, ftrandom saves the erroneous font +and continues. If the tester exits normally or with an error, then the +superstructure removes the test font and continues. + + +Command line options +-------------------- + + --all Test every font in the directory(ies) no matter + what its extension. + --check-outlines Call `FT_Outline_Decompose' on each glyph. + --dir Append to the list of directories to search + for good fonts. No recursive search. + --error-count Introduce single-byte errors into the + erroneous fonts (default: 1). + --error-fraction Multiply the file size of the font by and + introduce that many errors into the erroneous + font file. should be in the range [0;1] + (default: 0.0). + --ext Add to the set of font types tested. + --help Print out this list of options. + --nohints Specify FT_LOAD_NO_HINTING when loading glyphs. + --rasterize Call `FT_Render_Glyph' as well as loading it. + --result This is the directory in which test files are + placed. + --test Run a single test on a pre-generated testcase. + This is done in the current process so it can be + debugged more easily. + +The default font extensions tested by ftrandom are + + .ttf .otf .ttc .cid .pfb .pfa .bdf .pcf .pfr .fon .otb .cff + +The default font directory is controlled by the macro `GOOD_FONTS_DIR' in +the source code (and can be thus specified during compilation); its default +value is + + /usr/local/share/fonts + +The default result directory is `results' (in the current directory). + + +Compilation +----------- + +Two possible solutions. + +. Run ftrandom within a debugging tool like `valgrind' to catch various + memory issues. + +. Compile FreeType with sanitizer flags as provided by gcc or clang, for + example, then link it with ftrandom. diff --git a/lib/libesp32_lvgl/freetype/src/tools/ftrandom/ftrandom.c b/lib/libesp32_lvgl/freetype/src/tools/ftrandom/ftrandom.c new file mode 100644 index 000000000..0ee765e52 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/ftrandom/ftrandom.c @@ -0,0 +1,720 @@ +/* Copyright (C) 2005, 2007, 2008, 2013 by George Williams */ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + + * The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* modified by Werner Lemberg */ +/* This file is now part of the FreeType library */ + + +#define _XOPEN_SOURCE 600 /* for `kill', `strdup', `random', and `srandom' */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define true 1 +#define false 0 +#define forever for (;;) + + + static int check_outlines = false; + static int nohints = false; + static int rasterize = false; + static char* results_dir = "results"; + +#define GOOD_FONTS_DIR "/usr/local/share/fonts" + + static char* default_dir_list[] = + { + GOOD_FONTS_DIR, + NULL + }; + + static char* default_ext_list[] = + { + "ttf", + "otf", + "ttc", + "cid", + "pfb", + "pfa", + "bdf", + "pcf", + "pfr", + "fon", + "otb", + "cff", + NULL + }; + + static unsigned int error_count = 1; + static double error_fraction = 0.0; + + static FT_F26Dot6 font_size = 12 * 64; + + static struct fontlist + { + char* name; + long len; + unsigned int isbinary: 1; + unsigned int isascii: 1; + unsigned int ishex: 1; + + } *fontlist; + + static unsigned int fcnt; + + + static int + FT_MoveTo( const FT_Vector *to, + void *user ) + { + FT_UNUSED( to ); + FT_UNUSED( user ); + + return 0; + } + + + static int + FT_LineTo( const FT_Vector *to, + void *user ) + { + FT_UNUSED( to ); + FT_UNUSED( user ); + + return 0; + } + + + static int + FT_ConicTo( const FT_Vector *_cp, + const FT_Vector *to, + void *user ) + { + FT_UNUSED( _cp ); + FT_UNUSED( to ); + FT_UNUSED( user ); + + return 0; + } + + + static int + FT_CubicTo( const FT_Vector *cp1, + const FT_Vector *cp2, + const FT_Vector *to, + void *user ) + { + FT_UNUSED( cp1 ); + FT_UNUSED( cp2 ); + FT_UNUSED( to ); + FT_UNUSED( user ); + + return 0; + } + + + static FT_Outline_Funcs outlinefuncs = + { + FT_MoveTo, + FT_LineTo, + FT_ConicTo, + FT_CubicTo, + 0, 0 /* No shift, no delta */ + }; + + + static void + TestFace( FT_Face face ) + { + unsigned int gid; + int load_flags = FT_LOAD_DEFAULT; + + + if ( check_outlines && + FT_IS_SCALABLE( face ) ) + load_flags = FT_LOAD_NO_BITMAP; + + if ( nohints ) + load_flags |= FT_LOAD_NO_HINTING; + + FT_Set_Char_Size( face, 0, font_size, 72, 72 ); + + for ( gid = 0; gid < face->num_glyphs; gid++ ) + { + if ( check_outlines && + FT_IS_SCALABLE( face ) ) + { + if ( !FT_Load_Glyph( face, gid, load_flags ) ) + FT_Outline_Decompose( &face->glyph->outline, &outlinefuncs, NULL ); + } + else + FT_Load_Glyph( face, gid, load_flags ); + + if ( rasterize ) + FT_Render_Glyph( face->glyph, ft_render_mode_normal ); + } + + FT_Done_Face( face ); + } + + + static void + ExecuteTest( char* testfont ) + { + FT_Library context; + FT_Face face; + + + if ( FT_Init_FreeType( &context ) ) + { + fprintf( stderr, "Can't initialize FreeType.\n" ); + exit( 1 ); + } + + if ( FT_New_Face( context, testfont, 0, &face ) ) + { + /* The font is erroneous, so if this fails that's ok. */ + exit( 0 ); + } + + if ( face->num_faces == 1 ) + TestFace( face ); + else + { + long i, num; + + + num = face->num_faces; + FT_Done_Face( face ); + + for ( i = 0; i < num; i++ ) + { + if ( !FT_New_Face( context, testfont, i, &face ) ) + TestFace( face ); + } + } + + FT_Done_FreeType( context ); + + exit( 0 ); + } + + + static int + extmatch( char* filename, + char** extensions ) + { + int i; + char* pt; + + + if ( !extensions ) + return true; + + pt = strrchr( filename, '.' ); + if ( !pt ) + return false; + if ( pt < strrchr( filename, '/' ) ) + return false; + + for ( i = 0; extensions[i] != NULL; i++ ) + if ( strcasecmp( pt + 1, extensions[i] ) == 0 || + strcasecmp( pt, extensions[i] ) == 0 ) + return true; + + return false; + } + + + static void + figurefiletype( struct fontlist* item ) + { + FILE* foo; + + + item->isbinary = item->isascii = item->ishex = false; + + foo = fopen( item->name, "rb" ); + if ( foo ) + { + /* Try to guess the file type from the first few characters... */ + int ch1 = getc( foo ); + int ch2 = getc( foo ); + int ch3 = getc( foo ); + int ch4 = getc( foo ); + + + fclose( foo ); + + if ( ( ch1 == 0 && ch2 == 1 && ch3 == 0 && ch4 == 0 ) || + ( ch1 == 'O' && ch2 == 'T' && ch3 == 'T' && ch4 == 'O' ) || + ( ch1 == 't' && ch2 == 'r' && ch3 == 'u' && ch4 == 'e' ) || + ( ch1 == 't' && ch2 == 't' && ch3 == 'c' && ch4 == 'f' ) ) + { + /* ttf, otf, ttc files */ + item->isbinary = true; + } + else if ( ch1 == 0x80 && ch2 == '\01' ) + { + /* PFB header */ + item->isbinary = true; + } + else if ( ch1 == '%' && ch2 == '!' ) + { + /* Random PostScript */ + if ( strstr( item->name, ".pfa" ) || + strstr( item->name, ".PFA" ) ) + item->ishex = true; + else + item->isascii = true; + } + else if ( ch1 == 1 && ch2 == 0 && ch3 == 4 ) + { + /* Bare CFF */ + item->isbinary = true; + } + else if ( ch1 == 'S' && ch2 == 'T' && ch3 == 'A' && ch4 == 'R' ) + { + /* BDF */ + item->ishex = true; + } + else if ( ch1 == 'P' && ch2 == 'F' && ch3 == 'R' && ch4 == '0' ) + { + /* PFR */ + item->isbinary = true; + } + else if ( ( ch1 == '\1' && ch2 == 'f' && ch3 == 'c' && ch4 == 'p' ) || + ( ch1 == 'M' && ch2 == 'Z' ) ) + { + /* Windows FON */ + item->isbinary = true; + } + else + { + fprintf( stderr, + "Can't recognize file type of `%s', assuming binary\n", + item->name ); + item->isbinary = true; + } + } + else + { + fprintf( stderr, "Can't open `%s' for typing the file.\n", + item->name ); + item->isbinary = true; + } + } + + + static void + FindFonts( char** fontdirs, + char** extensions ) + { + int i; + unsigned int max; + char buffer[1025]; + struct stat statb; + + + max = 0; + fcnt = 0; + + for ( i = 0; fontdirs[i] != NULL; i++ ) + { + DIR* examples; + struct dirent* ent; + + + examples = opendir( fontdirs[i] ); + if ( !examples ) + { + fprintf( stderr, + "Can't open example font directory `%s'\n", + fontdirs[i] ); + exit( 1 ); + } + + while ( ( ent = readdir( examples ) ) != NULL ) + { + snprintf( buffer, sizeof ( buffer ), + "%s/%s", fontdirs[i], ent->d_name ); + if ( stat( buffer, &statb ) == -1 || S_ISDIR( statb.st_mode ) ) + continue; + if ( !extensions || extmatch( buffer, extensions ) ) + { + if ( fcnt >= max ) + { + max += 100; + fontlist = realloc( fontlist, max * sizeof ( struct fontlist ) ); + if ( !fontlist ) + { + fprintf( stderr, "Can't allocate memory\n" ); + exit( 1 ); + } + } + + fontlist[fcnt].name = strdup( buffer ); + fontlist[fcnt].len = statb.st_size; + + figurefiletype( &fontlist[fcnt] ); + fcnt++; + } + } + + closedir( examples ); + } + + if ( fcnt == 0 ) + { + fprintf( stderr, "Can't find matching font files.\n" ); + exit( 1 ); + } + + fontlist[fcnt].name = NULL; + } + + + static unsigned int + getErrorCnt( struct fontlist* item ) + { + if ( error_count == 0 && error_fraction == 0.0 ) + return 0; + + return error_count + (unsigned int)( error_fraction * item->len ); + } + + + static int + getRandom( int low, + int high ) + { + if ( low - high < 0x10000L ) + return low + ( ( random() >> 8 ) % ( high + 1 - low ) ); + + return low + ( random() % ( high + 1 - low ) ); + } + + + static int + copyfont( struct fontlist* item, + char* newfont ) + { + static char buffer[8096]; + FILE *good, *newf; + size_t len; + unsigned int i, err_cnt; + + + good = fopen( item->name, "r" ); + if ( !good ) + { + fprintf( stderr, "Can't open `%s'\n", item->name ); + return false; + } + + newf = fopen( newfont, "w+" ); + if ( !newf ) + { + fprintf( stderr, "Can't create temporary output file `%s'\n", + newfont ); + exit( 1 ); + } + + while ( ( len = fread( buffer, 1, sizeof ( buffer ), good ) ) > 0 ) + fwrite( buffer, 1, len, newf ); + + fclose( good ); + + err_cnt = getErrorCnt( item ); + for ( i = 0; i < err_cnt; i++ ) + { + fseek( newf, getRandom( 0, (int)( item->len - 1 ) ), SEEK_SET ); + + if ( item->isbinary ) + putc( getRandom( 0, 0xFF ), newf ); + else if ( item->isascii ) + putc( getRandom( 0x20, 0x7E ), newf ); + else + { + int hex = getRandom( 0, 15 ); + + + if ( hex < 10 ) + hex += '0'; + else + hex += 'A' - 10; + + putc( hex, newf ); + } + } + + if ( ferror( newf ) ) + { + fclose( newf ); + unlink( newfont ); + return false; + } + + fclose( newf ); + + return true; + } + + + static int child_pid; + + static void + abort_test( int sig ) + { + FT_UNUSED( sig ); + + /* If a time-out happens, then kill the child */ + kill( child_pid, SIGFPE ); + write( 2, "Timeout... ", 11 ); + } + + + static void + do_test( void ) + { + int i = getRandom( 0, (int)( fcnt - 1 ) ); + static int test_num = 0; + char buffer[1024]; + + + snprintf( buffer, 1024, "%s/test%d", results_dir, test_num++ ); + + if ( copyfont ( &fontlist[i], buffer ) ) + { + signal( SIGALRM, abort_test ); + /* Anything that takes more than 20 seconds */ + /* to parse and/or rasterize is an error. */ + alarm( 20 ); + if ( ( child_pid = fork() ) == 0 ) + ExecuteTest( buffer ); + else if ( child_pid != -1 ) + { + int status; + + + waitpid( child_pid, &status, 0 ); + alarm( 0 ); + if ( WIFSIGNALED ( status ) ) + printf( "Error found in file `%s'\n", buffer ); + else + unlink( buffer ); + } + else + { + fprintf( stderr, "Can't fork test case.\n" ); + exit( 1 ); + } + alarm( 0 ); + } + } + + + static void + usage( FILE* out, + char* name ) + { + char** d = default_dir_list; + char** e = default_ext_list; + + + fprintf( out, "%s [options] -- Generate random erroneous fonts\n" + " and attempt to parse them with FreeType.\n\n", name ); + + fprintf( out, " --all All non-directory files are assumed to be fonts.\n" ); + fprintf( out, " --check-outlines Make sure we can parse the outlines of each glyph.\n" ); + fprintf( out, " --dir Append to list of font search directories\n" + " (no recursive search).\n" ); + fprintf( out, " --error-count Introduce single byte errors into each font\n" + " (default: 1)\n" ); + fprintf( out, " --error-fraction Introduce *filesize single byte errors\n" + " into each font (default: 0.0).\n" ); + fprintf( out, " --ext Add to list of extensions indicating fonts.\n" ); + fprintf( out, " --help Print this.\n" ); + fprintf( out, " --nohints Turn off hinting.\n" ); + fprintf( out, " --rasterize Attempt to rasterize each glyph.\n" ); + fprintf( out, " --results Place the created test fonts into \n" + " (default: `results')\n" ); + fprintf( out, " --size Use the given font size for the tests.\n" ); + fprintf( out, " --test Run a single test on an already existing file.\n" ); + fprintf( out, "\n" ); + + fprintf( out, "Default font extensions:\n" ); + fprintf( out, " " ); + while ( *e ) + fprintf( out, " .%s", *e++ ); + fprintf( out, "\n" ); + + fprintf( out, "Default font directories:\n" ); + fprintf( out, " " ); + while ( *d ) + fprintf( out, " %s", *d++ ); + fprintf( out, "\n" ); + } + + + int + main( int argc, + char** argv ) + { + char **dirs, **exts; + int dcnt = 0, ecnt = 0, rset = false, allexts = false; + int i; + time_t now; + char* testfile = NULL; + + + dirs = calloc( (size_t)( argc + 1 ), sizeof ( char ** ) ); + exts = calloc( (size_t)( argc + 1 ), sizeof ( char ** ) ); + + for ( i = 1; i < argc; i++ ) + { + char* pt = argv[i]; + char* end; + + + if ( pt[0] == '-' && pt[1] == '-' ) + pt++; + + if ( strcmp( pt, "-all" ) == 0 ) + allexts = true; + else if ( strcmp( pt, "-check-outlines" ) == 0 ) + check_outlines = true; + else if ( strcmp( pt, "-dir" ) == 0 ) + dirs[dcnt++] = argv[++i]; + else if ( strcmp( pt, "-error-count" ) == 0 ) + { + if ( !rset ) + error_fraction = 0.0; + rset = true; + error_count = (unsigned int)strtoul( argv[++i], &end, 10 ); + if ( *end != '\0' ) + { + fprintf( stderr, "Bad value for error-count: %s\n", argv[i] ); + exit( 1 ); + } + } + else if ( strcmp( pt, "-error-fraction" ) == 0 ) + { + if ( !rset ) + error_count = 0; + rset = true; + error_fraction = strtod( argv[++i], &end ); + if ( *end != '\0' ) + { + fprintf( stderr, "Bad value for error-fraction: %s\n", argv[i] ); + exit( 1 ); + } + if ( error_fraction < 0.0 || error_fraction > 1.0 ) + { + fprintf( stderr, "error-fraction must be in the range [0;1]\n" ); + exit( 1 ); + } + } + else if ( strcmp( pt, "-ext" ) == 0 ) + exts[ecnt++] = argv[++i]; + else if ( strcmp( pt, "-help" ) == 0 ) + { + usage( stdout, argv[0] ); + exit( 0 ); + } + else if ( strcmp( pt, "-nohints" ) == 0 ) + nohints = true; + else if ( strcmp( pt, "-rasterize" ) == 0 ) + rasterize = true; + else if ( strcmp( pt, "-results" ) == 0 ) + results_dir = argv[++i]; + else if ( strcmp( pt, "-size" ) == 0 ) + { + font_size = (FT_F26Dot6)( strtod( argv[++i], &end ) * 64 ); + if ( *end != '\0' || font_size < 64 ) + { + fprintf( stderr, "Bad value for size: %s\n", argv[i] ); + exit( 1 ); + } + } + else if ( strcmp( pt, "-test" ) == 0 ) + testfile = argv[++i]; + else + { + usage( stderr, argv[0] ); + exit( 1 ); + } + } + + if ( allexts ) + { + free( exts ); + exts = NULL; + } + else if ( ecnt == 0 ) + { + free( exts ); + exts = default_ext_list; + } + + if ( dcnt == 0 ) + { + free( dirs ); + dirs = default_dir_list; + } + + if ( testfile ) + ExecuteTest( testfile ); /* This should never return */ + + time( &now ); + srandom( (unsigned int)now ); + + FindFonts( dirs, exts ); + mkdir( results_dir, 0755 ); + + forever + do_test(); + + return 0; + } + + +/* EOF */ diff --git a/lib/libesp32_lvgl/freetype/src/tools/glnames.py b/lib/libesp32_lvgl/freetype/src/tools/glnames.py new file mode 100644 index 000000000..41509dbc2 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/glnames.py @@ -0,0 +1,5533 @@ +#!/usr/bin/env python3 + +# +# FreeType 2 glyph name builder +# +# Copyright (C) 1996-2023 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +""" +usage: %s + + This python script generates the glyph names tables defined in the + `psnames' module. + + Its single argument is the name of the header file to be created. +""" + +import os.path +import struct +import sys + +# This table lists the glyphs according to the Macintosh specification. +# It is used by the TrueType Postscript names table. +# +# See +# +# https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6post.html +# +# for the official list. +# +mac_standard_names = [ + # 0 + ".notdef", ".null", "nonmarkingreturn", "space", "exclam", + "quotedbl", "numbersign", "dollar", "percent", "ampersand", + + # 10 + "quotesingle", "parenleft", "parenright", "asterisk", "plus", + "comma", "hyphen", "period", "slash", "zero", + + # 20 + "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "colon", + + # 30 + "semicolon", "less", "equal", "greater", "question", + "at", "A", "B", "C", "D", + + # 40 + "E", "F", "G", "H", "I", + "J", "K", "L", "M", "N", + + # 50 + "O", "P", "Q", "R", "S", + "T", "U", "V", "W", "X", + + # 60 + "Y", "Z", "bracketleft", "backslash", "bracketright", + "asciicircum", "underscore", "grave", "a", "b", + + # 70 + "c", "d", "e", "f", "g", + "h", "i", "j", "k", "l", + + # 80 + "m", "n", "o", "p", "q", + "r", "s", "t", "u", "v", + + # 90 + "w", "x", "y", "z", "braceleft", + "bar", "braceright", "asciitilde", "Adieresis", "Aring", + + # 100 + "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", + "aacute", "agrave", "acircumflex", "adieresis", "atilde", + + # 110 + "aring", "ccedilla", "eacute", "egrave", "ecircumflex", + "edieresis", "iacute", "igrave", "icircumflex", "idieresis", + + # 120 + "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", + "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", + + # 130 + "dagger", "degree", "cent", "sterling", "section", + "bullet", "paragraph", "germandbls", "registered", "copyright", + + # 140 + "trademark", "acute", "dieresis", "notequal", "AE", + "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", + + # 150 + "yen", "mu", "partialdiff", "summation", "product", + "pi", "integral", "ordfeminine", "ordmasculine", "Omega", + + # 160 + "ae", "oslash", "questiondown", "exclamdown", "logicalnot", + "radical", "florin", "approxequal", "Delta", "guillemotleft", + + # 170 + "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde", + "Otilde", "OE", "oe", "endash", "emdash", + + # 180 + "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", + "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", + + # 190 + "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", + "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", + "Acircumflex", + + # 200 + "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", + "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", + + # 210 + "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", + "dotlessi", "circumflex", "tilde", "macron", "breve", + + # 220 + "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", + "caron", "Lslash", "lslash", "Scaron", "scaron", + + # 230 + "Zcaron", "zcaron", "brokenbar", "Eth", "eth", + "Yacute", "yacute", "Thorn", "thorn", "minus", + + # 240 + "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf", + "onequarter", "threequarters", "franc", "Gbreve", "gbreve", + + # 250 + "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute", + "Ccaron", "ccaron", "dcroat" +] + +# The list of standard `SID' glyph names. For the official list, +# see Annex A of document at +# +# https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf +# +sid_standard_names = [ + # 0 + ".notdef", "space", "exclam", "quotedbl", "numbersign", + "dollar", "percent", "ampersand", "quoteright", "parenleft", + + # 10 + "parenright", "asterisk", "plus", "comma", "hyphen", + "period", "slash", "zero", "one", "two", + + # 20 + "three", "four", "five", "six", "seven", + "eight", "nine", "colon", "semicolon", "less", + + # 30 + "equal", "greater", "question", "at", "A", + "B", "C", "D", "E", "F", + + # 40 + "G", "H", "I", "J", "K", + "L", "M", "N", "O", "P", + + # 50 + "Q", "R", "S", "T", "U", + "V", "W", "X", "Y", "Z", + + # 60 + "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", + "quoteleft", "a", "b", "c", "d", + + # 70 + "e", "f", "g", "h", "i", + "j", "k", "l", "m", "n", + + # 80 + "o", "p", "q", "r", "s", + "t", "u", "v", "w", "x", + + # 90 + "y", "z", "braceleft", "bar", "braceright", + "asciitilde", "exclamdown", "cent", "sterling", "fraction", + + # 100 + "yen", "florin", "section", "currency", "quotesingle", + "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", + + # 110 + "fl", "endash", "dagger", "daggerdbl", "periodcentered", + "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", + + # 120 + "guillemotright", "ellipsis", "perthousand", "questiondown", "grave", + "acute", "circumflex", "tilde", "macron", "breve", + + # 130 + "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut", + "ogonek", "caron", "emdash", "AE", "ordfeminine", + + # 140 + "Lslash", "Oslash", "OE", "ordmasculine", "ae", + "dotlessi", "lslash", "oslash", "oe", "germandbls", + + # 150 + "onesuperior", "logicalnot", "mu", "trademark", "Eth", + "onehalf", "plusminus", "Thorn", "onequarter", "divide", + + # 160 + "brokenbar", "degree", "thorn", "threequarters", "twosuperior", + "registered", "minus", "eth", "multiply", "threesuperior", + + # 170 + "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", + "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex", + + # 180 + "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", + "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", + + # 190 + "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex", + "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", + + # 200 + "aacute", "acircumflex", "adieresis", "agrave", "aring", + "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis", + + # 210 + "egrave", "iacute", "icircumflex", "idieresis", "igrave", + "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", + + # 220 + "otilde", "scaron", "uacute", "ucircumflex", "udieresis", + "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall", + + # 230 + "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", + "Acutesmall", + "parenleftsuperior", "parenrightsuperior", "twodotenleader", + "onedotenleader", "zerooldstyle", + + # 240 + "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", + "commasuperior", + + # 250 + "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", + "bsuperior", + "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", + + # 260 + "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", + "tsuperior", "ff", "ffi", "ffl", "parenleftinferior", + + # 270 + "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", + "Asmall", + "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", + + # 280 + "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", + "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", + + # 290 + "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", + "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", + + # 300 + "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", + "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", + "Dieresissmall", + + # 310 + "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash", + "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", + "questiondownsmall", + + # 320 + "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", + "twothirds", "zerosuperior", "foursuperior", "fivesuperior", + "sixsuperior", + + # 330 + "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", + "oneinferior", + "twoinferior", "threeinferior", "fourinferior", "fiveinferior", + "sixinferior", + + # 340 + "seveninferior", "eightinferior", "nineinferior", "centinferior", + "dollarinferior", + "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", + "Acircumflexsmall", + + # 350 + "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", + "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", + "Igravesmall", + + # 360 + "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", + "Ntildesmall", + "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", + "Odieresissmall", + + # 370 + "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", + "Ucircumflexsmall", + "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall", + "001.000", + + # 380 + "001.001", "001.002", "001.003", "Black", "Bold", + "Book", "Light", "Medium", "Regular", "Roman", + + # 390 + "Semibold" +] + +# This table maps character codes of the Adobe Standard Type 1 +# encoding to glyph indices in the sid_standard_names table. +# +t1_standard_encoding = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 0, 111, 112, 113, + 114, 0, 115, 116, 117, 118, 119, 120, 121, 122, + 0, 123, 0, 124, 125, 126, 127, 128, 129, 130, + + 131, 0, 132, 133, 0, 134, 135, 136, 137, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 138, 0, 139, 0, 0, + 0, 0, 140, 141, 142, 143, 0, 0, 0, 0, + 0, 144, 0, 0, 0, 145, 0, 0, 146, 147, + + 148, 149, 0, 0, 0, 0 +] + +# This table maps character codes of the Adobe Expert Type 1 +# encoding to glyph indices in the sid_standard_names table. +# +t1_expert_encoding = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 229, 230, 0, 231, 232, 233, 234, + 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, + + 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, + 249, 250, 251, 252, 0, 253, 254, 255, 256, 257, + 0, 0, 0, 258, 0, 0, 259, 260, 261, 262, + 0, 0, 263, 264, 265, 0, 266, 109, 110, 267, + 268, 269, 0, 270, 271, 272, 273, 274, 275, 276, + + 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 304, 305, 306, 0, 0, 307, 308, 309, 310, + 311, 0, 312, 0, 0, 313, 0, 0, 314, 315, + 0, 0, 316, 317, 318, 0, 0, 0, 158, 155, + 163, 319, 320, 321, 322, 323, 324, 325, 0, 0, + + 326, 150, 164, 169, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, + + 373, 374, 375, 376, 377, 378 +] + +# This data has been taken literally from the files `glyphlist.txt' +# and `zapfdingbats.txt' version 2.0, Sept 2002. It is available from +# +# https://github.com/adobe-type-tools/agl-aglfn +# +adobe_glyph_list = """\ +A;0041 +AE;00C6 +AEacute;01FC +AEmacron;01E2 +AEsmall;F7E6 +Aacute;00C1 +Aacutesmall;F7E1 +Abreve;0102 +Abreveacute;1EAE +Abrevecyrillic;04D0 +Abrevedotbelow;1EB6 +Abrevegrave;1EB0 +Abrevehookabove;1EB2 +Abrevetilde;1EB4 +Acaron;01CD +Acircle;24B6 +Acircumflex;00C2 +Acircumflexacute;1EA4 +Acircumflexdotbelow;1EAC +Acircumflexgrave;1EA6 +Acircumflexhookabove;1EA8 +Acircumflexsmall;F7E2 +Acircumflextilde;1EAA +Acute;F6C9 +Acutesmall;F7B4 +Acyrillic;0410 +Adblgrave;0200 +Adieresis;00C4 +Adieresiscyrillic;04D2 +Adieresismacron;01DE +Adieresissmall;F7E4 +Adotbelow;1EA0 +Adotmacron;01E0 +Agrave;00C0 +Agravesmall;F7E0 +Ahookabove;1EA2 +Aiecyrillic;04D4 +Ainvertedbreve;0202 +Alpha;0391 +Alphatonos;0386 +Amacron;0100 +Amonospace;FF21 +Aogonek;0104 +Aring;00C5 +Aringacute;01FA +Aringbelow;1E00 +Aringsmall;F7E5 +Asmall;F761 +Atilde;00C3 +Atildesmall;F7E3 +Aybarmenian;0531 +B;0042 +Bcircle;24B7 +Bdotaccent;1E02 +Bdotbelow;1E04 +Becyrillic;0411 +Benarmenian;0532 +Beta;0392 +Bhook;0181 +Blinebelow;1E06 +Bmonospace;FF22 +Brevesmall;F6F4 +Bsmall;F762 +Btopbar;0182 +C;0043 +Caarmenian;053E +Cacute;0106 +Caron;F6CA +Caronsmall;F6F5 +Ccaron;010C +Ccedilla;00C7 +Ccedillaacute;1E08 +Ccedillasmall;F7E7 +Ccircle;24B8 +Ccircumflex;0108 +Cdot;010A +Cdotaccent;010A +Cedillasmall;F7B8 +Chaarmenian;0549 +Cheabkhasiancyrillic;04BC +Checyrillic;0427 +Chedescenderabkhasiancyrillic;04BE +Chedescendercyrillic;04B6 +Chedieresiscyrillic;04F4 +Cheharmenian;0543 +Chekhakassiancyrillic;04CB +Cheverticalstrokecyrillic;04B8 +Chi;03A7 +Chook;0187 +Circumflexsmall;F6F6 +Cmonospace;FF23 +Coarmenian;0551 +Csmall;F763 +D;0044 +DZ;01F1 +DZcaron;01C4 +Daarmenian;0534 +Dafrican;0189 +Dcaron;010E +Dcedilla;1E10 +Dcircle;24B9 +Dcircumflexbelow;1E12 +Dcroat;0110 +Ddotaccent;1E0A +Ddotbelow;1E0C +Decyrillic;0414 +Deicoptic;03EE +Delta;2206 +Deltagreek;0394 +Dhook;018A +Dieresis;F6CB +DieresisAcute;F6CC +DieresisGrave;F6CD +Dieresissmall;F7A8 +Digammagreek;03DC +Djecyrillic;0402 +Dlinebelow;1E0E +Dmonospace;FF24 +Dotaccentsmall;F6F7 +Dslash;0110 +Dsmall;F764 +Dtopbar;018B +Dz;01F2 +Dzcaron;01C5 +Dzeabkhasiancyrillic;04E0 +Dzecyrillic;0405 +Dzhecyrillic;040F +E;0045 +Eacute;00C9 +Eacutesmall;F7E9 +Ebreve;0114 +Ecaron;011A +Ecedillabreve;1E1C +Echarmenian;0535 +Ecircle;24BA +Ecircumflex;00CA +Ecircumflexacute;1EBE +Ecircumflexbelow;1E18 +Ecircumflexdotbelow;1EC6 +Ecircumflexgrave;1EC0 +Ecircumflexhookabove;1EC2 +Ecircumflexsmall;F7EA +Ecircumflextilde;1EC4 +Ecyrillic;0404 +Edblgrave;0204 +Edieresis;00CB +Edieresissmall;F7EB +Edot;0116 +Edotaccent;0116 +Edotbelow;1EB8 +Efcyrillic;0424 +Egrave;00C8 +Egravesmall;F7E8 +Eharmenian;0537 +Ehookabove;1EBA +Eightroman;2167 +Einvertedbreve;0206 +Eiotifiedcyrillic;0464 +Elcyrillic;041B +Elevenroman;216A +Emacron;0112 +Emacronacute;1E16 +Emacrongrave;1E14 +Emcyrillic;041C +Emonospace;FF25 +Encyrillic;041D +Endescendercyrillic;04A2 +Eng;014A +Enghecyrillic;04A4 +Enhookcyrillic;04C7 +Eogonek;0118 +Eopen;0190 +Epsilon;0395 +Epsilontonos;0388 +Ercyrillic;0420 +Ereversed;018E +Ereversedcyrillic;042D +Escyrillic;0421 +Esdescendercyrillic;04AA +Esh;01A9 +Esmall;F765 +Eta;0397 +Etarmenian;0538 +Etatonos;0389 +Eth;00D0 +Ethsmall;F7F0 +Etilde;1EBC +Etildebelow;1E1A +Euro;20AC +Ezh;01B7 +Ezhcaron;01EE +Ezhreversed;01B8 +F;0046 +Fcircle;24BB +Fdotaccent;1E1E +Feharmenian;0556 +Feicoptic;03E4 +Fhook;0191 +Fitacyrillic;0472 +Fiveroman;2164 +Fmonospace;FF26 +Fourroman;2163 +Fsmall;F766 +G;0047 +GBsquare;3387 +Gacute;01F4 +Gamma;0393 +Gammaafrican;0194 +Gangiacoptic;03EA +Gbreve;011E +Gcaron;01E6 +Gcedilla;0122 +Gcircle;24BC +Gcircumflex;011C +Gcommaaccent;0122 +Gdot;0120 +Gdotaccent;0120 +Gecyrillic;0413 +Ghadarmenian;0542 +Ghemiddlehookcyrillic;0494 +Ghestrokecyrillic;0492 +Gheupturncyrillic;0490 +Ghook;0193 +Gimarmenian;0533 +Gjecyrillic;0403 +Gmacron;1E20 +Gmonospace;FF27 +Grave;F6CE +Gravesmall;F760 +Gsmall;F767 +Gsmallhook;029B +Gstroke;01E4 +H;0048 +H18533;25CF +H18543;25AA +H18551;25AB +H22073;25A1 +HPsquare;33CB +Haabkhasiancyrillic;04A8 +Hadescendercyrillic;04B2 +Hardsigncyrillic;042A +Hbar;0126 +Hbrevebelow;1E2A +Hcedilla;1E28 +Hcircle;24BD +Hcircumflex;0124 +Hdieresis;1E26 +Hdotaccent;1E22 +Hdotbelow;1E24 +Hmonospace;FF28 +Hoarmenian;0540 +Horicoptic;03E8 +Hsmall;F768 +Hungarumlaut;F6CF +Hungarumlautsmall;F6F8 +Hzsquare;3390 +I;0049 +IAcyrillic;042F +IJ;0132 +IUcyrillic;042E +Iacute;00CD +Iacutesmall;F7ED +Ibreve;012C +Icaron;01CF +Icircle;24BE +Icircumflex;00CE +Icircumflexsmall;F7EE +Icyrillic;0406 +Idblgrave;0208 +Idieresis;00CF +Idieresisacute;1E2E +Idieresiscyrillic;04E4 +Idieresissmall;F7EF +Idot;0130 +Idotaccent;0130 +Idotbelow;1ECA +Iebrevecyrillic;04D6 +Iecyrillic;0415 +Ifraktur;2111 +Igrave;00CC +Igravesmall;F7EC +Ihookabove;1EC8 +Iicyrillic;0418 +Iinvertedbreve;020A +Iishortcyrillic;0419 +Imacron;012A +Imacroncyrillic;04E2 +Imonospace;FF29 +Iniarmenian;053B +Iocyrillic;0401 +Iogonek;012E +Iota;0399 +Iotaafrican;0196 +Iotadieresis;03AA +Iotatonos;038A +Ismall;F769 +Istroke;0197 +Itilde;0128 +Itildebelow;1E2C +Izhitsacyrillic;0474 +Izhitsadblgravecyrillic;0476 +J;004A +Jaarmenian;0541 +Jcircle;24BF +Jcircumflex;0134 +Jecyrillic;0408 +Jheharmenian;054B +Jmonospace;FF2A +Jsmall;F76A +K;004B +KBsquare;3385 +KKsquare;33CD +Kabashkircyrillic;04A0 +Kacute;1E30 +Kacyrillic;041A +Kadescendercyrillic;049A +Kahookcyrillic;04C3 +Kappa;039A +Kastrokecyrillic;049E +Kaverticalstrokecyrillic;049C +Kcaron;01E8 +Kcedilla;0136 +Kcircle;24C0 +Kcommaaccent;0136 +Kdotbelow;1E32 +Keharmenian;0554 +Kenarmenian;053F +Khacyrillic;0425 +Kheicoptic;03E6 +Khook;0198 +Kjecyrillic;040C +Klinebelow;1E34 +Kmonospace;FF2B +Koppacyrillic;0480 +Koppagreek;03DE +Ksicyrillic;046E +Ksmall;F76B +L;004C +LJ;01C7 +LL;F6BF +Lacute;0139 +Lambda;039B +Lcaron;013D +Lcedilla;013B +Lcircle;24C1 +Lcircumflexbelow;1E3C +Lcommaaccent;013B +Ldot;013F +Ldotaccent;013F +Ldotbelow;1E36 +Ldotbelowmacron;1E38 +Liwnarmenian;053C +Lj;01C8 +Ljecyrillic;0409 +Llinebelow;1E3A +Lmonospace;FF2C +Lslash;0141 +Lslashsmall;F6F9 +Lsmall;F76C +M;004D +MBsquare;3386 +Macron;F6D0 +Macronsmall;F7AF +Macute;1E3E +Mcircle;24C2 +Mdotaccent;1E40 +Mdotbelow;1E42 +Menarmenian;0544 +Mmonospace;FF2D +Msmall;F76D +Mturned;019C +Mu;039C +N;004E +NJ;01CA +Nacute;0143 +Ncaron;0147 +Ncedilla;0145 +Ncircle;24C3 +Ncircumflexbelow;1E4A +Ncommaaccent;0145 +Ndotaccent;1E44 +Ndotbelow;1E46 +Nhookleft;019D +Nineroman;2168 +Nj;01CB +Njecyrillic;040A +Nlinebelow;1E48 +Nmonospace;FF2E +Nowarmenian;0546 +Nsmall;F76E +Ntilde;00D1 +Ntildesmall;F7F1 +Nu;039D +O;004F +OE;0152 +OEsmall;F6FA +Oacute;00D3 +Oacutesmall;F7F3 +Obarredcyrillic;04E8 +Obarreddieresiscyrillic;04EA +Obreve;014E +Ocaron;01D1 +Ocenteredtilde;019F +Ocircle;24C4 +Ocircumflex;00D4 +Ocircumflexacute;1ED0 +Ocircumflexdotbelow;1ED8 +Ocircumflexgrave;1ED2 +Ocircumflexhookabove;1ED4 +Ocircumflexsmall;F7F4 +Ocircumflextilde;1ED6 +Ocyrillic;041E +Odblacute;0150 +Odblgrave;020C +Odieresis;00D6 +Odieresiscyrillic;04E6 +Odieresissmall;F7F6 +Odotbelow;1ECC +Ogoneksmall;F6FB +Ograve;00D2 +Ogravesmall;F7F2 +Oharmenian;0555 +Ohm;2126 +Ohookabove;1ECE +Ohorn;01A0 +Ohornacute;1EDA +Ohorndotbelow;1EE2 +Ohorngrave;1EDC +Ohornhookabove;1EDE +Ohorntilde;1EE0 +Ohungarumlaut;0150 +Oi;01A2 +Oinvertedbreve;020E +Omacron;014C +Omacronacute;1E52 +Omacrongrave;1E50 +Omega;2126 +Omegacyrillic;0460 +Omegagreek;03A9 +Omegaroundcyrillic;047A +Omegatitlocyrillic;047C +Omegatonos;038F +Omicron;039F +Omicrontonos;038C +Omonospace;FF2F +Oneroman;2160 +Oogonek;01EA +Oogonekmacron;01EC +Oopen;0186 +Oslash;00D8 +Oslashacute;01FE +Oslashsmall;F7F8 +Osmall;F76F +Ostrokeacute;01FE +Otcyrillic;047E +Otilde;00D5 +Otildeacute;1E4C +Otildedieresis;1E4E +Otildesmall;F7F5 +P;0050 +Pacute;1E54 +Pcircle;24C5 +Pdotaccent;1E56 +Pecyrillic;041F +Peharmenian;054A +Pemiddlehookcyrillic;04A6 +Phi;03A6 +Phook;01A4 +Pi;03A0 +Piwrarmenian;0553 +Pmonospace;FF30 +Psi;03A8 +Psicyrillic;0470 +Psmall;F770 +Q;0051 +Qcircle;24C6 +Qmonospace;FF31 +Qsmall;F771 +R;0052 +Raarmenian;054C +Racute;0154 +Rcaron;0158 +Rcedilla;0156 +Rcircle;24C7 +Rcommaaccent;0156 +Rdblgrave;0210 +Rdotaccent;1E58 +Rdotbelow;1E5A +Rdotbelowmacron;1E5C +Reharmenian;0550 +Rfraktur;211C +Rho;03A1 +Ringsmall;F6FC +Rinvertedbreve;0212 +Rlinebelow;1E5E +Rmonospace;FF32 +Rsmall;F772 +Rsmallinverted;0281 +Rsmallinvertedsuperior;02B6 +S;0053 +SF010000;250C +SF020000;2514 +SF030000;2510 +SF040000;2518 +SF050000;253C +SF060000;252C +SF070000;2534 +SF080000;251C +SF090000;2524 +SF100000;2500 +SF110000;2502 +SF190000;2561 +SF200000;2562 +SF210000;2556 +SF220000;2555 +SF230000;2563 +SF240000;2551 +SF250000;2557 +SF260000;255D +SF270000;255C +SF280000;255B +SF360000;255E +SF370000;255F +SF380000;255A +SF390000;2554 +SF400000;2569 +SF410000;2566 +SF420000;2560 +SF430000;2550 +SF440000;256C +SF450000;2567 +SF460000;2568 +SF470000;2564 +SF480000;2565 +SF490000;2559 +SF500000;2558 +SF510000;2552 +SF520000;2553 +SF530000;256B +SF540000;256A +Sacute;015A +Sacutedotaccent;1E64 +Sampigreek;03E0 +Scaron;0160 +Scarondotaccent;1E66 +Scaronsmall;F6FD +Scedilla;015E +Schwa;018F +Schwacyrillic;04D8 +Schwadieresiscyrillic;04DA +Scircle;24C8 +Scircumflex;015C +Scommaaccent;0218 +Sdotaccent;1E60 +Sdotbelow;1E62 +Sdotbelowdotaccent;1E68 +Seharmenian;054D +Sevenroman;2166 +Shaarmenian;0547 +Shacyrillic;0428 +Shchacyrillic;0429 +Sheicoptic;03E2 +Shhacyrillic;04BA +Shimacoptic;03EC +Sigma;03A3 +Sixroman;2165 +Smonospace;FF33 +Softsigncyrillic;042C +Ssmall;F773 +Stigmagreek;03DA +T;0054 +Tau;03A4 +Tbar;0166 +Tcaron;0164 +Tcedilla;0162 +Tcircle;24C9 +Tcircumflexbelow;1E70 +Tcommaaccent;0162 +Tdotaccent;1E6A +Tdotbelow;1E6C +Tecyrillic;0422 +Tedescendercyrillic;04AC +Tenroman;2169 +Tetsecyrillic;04B4 +Theta;0398 +Thook;01AC +Thorn;00DE +Thornsmall;F7FE +Threeroman;2162 +Tildesmall;F6FE +Tiwnarmenian;054F +Tlinebelow;1E6E +Tmonospace;FF34 +Toarmenian;0539 +Tonefive;01BC +Tonesix;0184 +Tonetwo;01A7 +Tretroflexhook;01AE +Tsecyrillic;0426 +Tshecyrillic;040B +Tsmall;F774 +Twelveroman;216B +Tworoman;2161 +U;0055 +Uacute;00DA +Uacutesmall;F7FA +Ubreve;016C +Ucaron;01D3 +Ucircle;24CA +Ucircumflex;00DB +Ucircumflexbelow;1E76 +Ucircumflexsmall;F7FB +Ucyrillic;0423 +Udblacute;0170 +Udblgrave;0214 +Udieresis;00DC +Udieresisacute;01D7 +Udieresisbelow;1E72 +Udieresiscaron;01D9 +Udieresiscyrillic;04F0 +Udieresisgrave;01DB +Udieresismacron;01D5 +Udieresissmall;F7FC +Udotbelow;1EE4 +Ugrave;00D9 +Ugravesmall;F7F9 +Uhookabove;1EE6 +Uhorn;01AF +Uhornacute;1EE8 +Uhorndotbelow;1EF0 +Uhorngrave;1EEA +Uhornhookabove;1EEC +Uhorntilde;1EEE +Uhungarumlaut;0170 +Uhungarumlautcyrillic;04F2 +Uinvertedbreve;0216 +Ukcyrillic;0478 +Umacron;016A +Umacroncyrillic;04EE +Umacrondieresis;1E7A +Umonospace;FF35 +Uogonek;0172 +Upsilon;03A5 +Upsilon1;03D2 +Upsilonacutehooksymbolgreek;03D3 +Upsilonafrican;01B1 +Upsilondieresis;03AB +Upsilondieresishooksymbolgreek;03D4 +Upsilonhooksymbol;03D2 +Upsilontonos;038E +Uring;016E +Ushortcyrillic;040E +Usmall;F775 +Ustraightcyrillic;04AE +Ustraightstrokecyrillic;04B0 +Utilde;0168 +Utildeacute;1E78 +Utildebelow;1E74 +V;0056 +Vcircle;24CB +Vdotbelow;1E7E +Vecyrillic;0412 +Vewarmenian;054E +Vhook;01B2 +Vmonospace;FF36 +Voarmenian;0548 +Vsmall;F776 +Vtilde;1E7C +W;0057 +Wacute;1E82 +Wcircle;24CC +Wcircumflex;0174 +Wdieresis;1E84 +Wdotaccent;1E86 +Wdotbelow;1E88 +Wgrave;1E80 +Wmonospace;FF37 +Wsmall;F777 +X;0058 +Xcircle;24CD +Xdieresis;1E8C +Xdotaccent;1E8A +Xeharmenian;053D +Xi;039E +Xmonospace;FF38 +Xsmall;F778 +Y;0059 +Yacute;00DD +Yacutesmall;F7FD +Yatcyrillic;0462 +Ycircle;24CE +Ycircumflex;0176 +Ydieresis;0178 +Ydieresissmall;F7FF +Ydotaccent;1E8E +Ydotbelow;1EF4 +Yericyrillic;042B +Yerudieresiscyrillic;04F8 +Ygrave;1EF2 +Yhook;01B3 +Yhookabove;1EF6 +Yiarmenian;0545 +Yicyrillic;0407 +Yiwnarmenian;0552 +Ymonospace;FF39 +Ysmall;F779 +Ytilde;1EF8 +Yusbigcyrillic;046A +Yusbigiotifiedcyrillic;046C +Yuslittlecyrillic;0466 +Yuslittleiotifiedcyrillic;0468 +Z;005A +Zaarmenian;0536 +Zacute;0179 +Zcaron;017D +Zcaronsmall;F6FF +Zcircle;24CF +Zcircumflex;1E90 +Zdot;017B +Zdotaccent;017B +Zdotbelow;1E92 +Zecyrillic;0417 +Zedescendercyrillic;0498 +Zedieresiscyrillic;04DE +Zeta;0396 +Zhearmenian;053A +Zhebrevecyrillic;04C1 +Zhecyrillic;0416 +Zhedescendercyrillic;0496 +Zhedieresiscyrillic;04DC +Zlinebelow;1E94 +Zmonospace;FF3A +Zsmall;F77A +Zstroke;01B5 +a;0061 +aabengali;0986 +aacute;00E1 +aadeva;0906 +aagujarati;0A86 +aagurmukhi;0A06 +aamatragurmukhi;0A3E +aarusquare;3303 +aavowelsignbengali;09BE +aavowelsigndeva;093E +aavowelsigngujarati;0ABE +abbreviationmarkarmenian;055F +abbreviationsigndeva;0970 +abengali;0985 +abopomofo;311A +abreve;0103 +abreveacute;1EAF +abrevecyrillic;04D1 +abrevedotbelow;1EB7 +abrevegrave;1EB1 +abrevehookabove;1EB3 +abrevetilde;1EB5 +acaron;01CE +acircle;24D0 +acircumflex;00E2 +acircumflexacute;1EA5 +acircumflexdotbelow;1EAD +acircumflexgrave;1EA7 +acircumflexhookabove;1EA9 +acircumflextilde;1EAB +acute;00B4 +acutebelowcmb;0317 +acutecmb;0301 +acutecomb;0301 +acutedeva;0954 +acutelowmod;02CF +acutetonecmb;0341 +acyrillic;0430 +adblgrave;0201 +addakgurmukhi;0A71 +adeva;0905 +adieresis;00E4 +adieresiscyrillic;04D3 +adieresismacron;01DF +adotbelow;1EA1 +adotmacron;01E1 +ae;00E6 +aeacute;01FD +aekorean;3150 +aemacron;01E3 +afii00208;2015 +afii08941;20A4 +afii10017;0410 +afii10018;0411 +afii10019;0412 +afii10020;0413 +afii10021;0414 +afii10022;0415 +afii10023;0401 +afii10024;0416 +afii10025;0417 +afii10026;0418 +afii10027;0419 +afii10028;041A +afii10029;041B +afii10030;041C +afii10031;041D +afii10032;041E +afii10033;041F +afii10034;0420 +afii10035;0421 +afii10036;0422 +afii10037;0423 +afii10038;0424 +afii10039;0425 +afii10040;0426 +afii10041;0427 +afii10042;0428 +afii10043;0429 +afii10044;042A +afii10045;042B +afii10046;042C +afii10047;042D +afii10048;042E +afii10049;042F +afii10050;0490 +afii10051;0402 +afii10052;0403 +afii10053;0404 +afii10054;0405 +afii10055;0406 +afii10056;0407 +afii10057;0408 +afii10058;0409 +afii10059;040A +afii10060;040B +afii10061;040C +afii10062;040E +afii10063;F6C4 +afii10064;F6C5 +afii10065;0430 +afii10066;0431 +afii10067;0432 +afii10068;0433 +afii10069;0434 +afii10070;0435 +afii10071;0451 +afii10072;0436 +afii10073;0437 +afii10074;0438 +afii10075;0439 +afii10076;043A +afii10077;043B +afii10078;043C +afii10079;043D +afii10080;043E +afii10081;043F +afii10082;0440 +afii10083;0441 +afii10084;0442 +afii10085;0443 +afii10086;0444 +afii10087;0445 +afii10088;0446 +afii10089;0447 +afii10090;0448 +afii10091;0449 +afii10092;044A +afii10093;044B +afii10094;044C +afii10095;044D +afii10096;044E +afii10097;044F +afii10098;0491 +afii10099;0452 +afii10100;0453 +afii10101;0454 +afii10102;0455 +afii10103;0456 +afii10104;0457 +afii10105;0458 +afii10106;0459 +afii10107;045A +afii10108;045B +afii10109;045C +afii10110;045E +afii10145;040F +afii10146;0462 +afii10147;0472 +afii10148;0474 +afii10192;F6C6 +afii10193;045F +afii10194;0463 +afii10195;0473 +afii10196;0475 +afii10831;F6C7 +afii10832;F6C8 +afii10846;04D9 +afii299;200E +afii300;200F +afii301;200D +afii57381;066A +afii57388;060C +afii57392;0660 +afii57393;0661 +afii57394;0662 +afii57395;0663 +afii57396;0664 +afii57397;0665 +afii57398;0666 +afii57399;0667 +afii57400;0668 +afii57401;0669 +afii57403;061B +afii57407;061F +afii57409;0621 +afii57410;0622 +afii57411;0623 +afii57412;0624 +afii57413;0625 +afii57414;0626 +afii57415;0627 +afii57416;0628 +afii57417;0629 +afii57418;062A +afii57419;062B +afii57420;062C +afii57421;062D +afii57422;062E +afii57423;062F +afii57424;0630 +afii57425;0631 +afii57426;0632 +afii57427;0633 +afii57428;0634 +afii57429;0635 +afii57430;0636 +afii57431;0637 +afii57432;0638 +afii57433;0639 +afii57434;063A +afii57440;0640 +afii57441;0641 +afii57442;0642 +afii57443;0643 +afii57444;0644 +afii57445;0645 +afii57446;0646 +afii57448;0648 +afii57449;0649 +afii57450;064A +afii57451;064B +afii57452;064C +afii57453;064D +afii57454;064E +afii57455;064F +afii57456;0650 +afii57457;0651 +afii57458;0652 +afii57470;0647 +afii57505;06A4 +afii57506;067E +afii57507;0686 +afii57508;0698 +afii57509;06AF +afii57511;0679 +afii57512;0688 +afii57513;0691 +afii57514;06BA +afii57519;06D2 +afii57534;06D5 +afii57636;20AA +afii57645;05BE +afii57658;05C3 +afii57664;05D0 +afii57665;05D1 +afii57666;05D2 +afii57667;05D3 +afii57668;05D4 +afii57669;05D5 +afii57670;05D6 +afii57671;05D7 +afii57672;05D8 +afii57673;05D9 +afii57674;05DA +afii57675;05DB +afii57676;05DC +afii57677;05DD +afii57678;05DE +afii57679;05DF +afii57680;05E0 +afii57681;05E1 +afii57682;05E2 +afii57683;05E3 +afii57684;05E4 +afii57685;05E5 +afii57686;05E6 +afii57687;05E7 +afii57688;05E8 +afii57689;05E9 +afii57690;05EA +afii57694;FB2A +afii57695;FB2B +afii57700;FB4B +afii57705;FB1F +afii57716;05F0 +afii57717;05F1 +afii57718;05F2 +afii57723;FB35 +afii57793;05B4 +afii57794;05B5 +afii57795;05B6 +afii57796;05BB +afii57797;05B8 +afii57798;05B7 +afii57799;05B0 +afii57800;05B2 +afii57801;05B1 +afii57802;05B3 +afii57803;05C2 +afii57804;05C1 +afii57806;05B9 +afii57807;05BC +afii57839;05BD +afii57841;05BF +afii57842;05C0 +afii57929;02BC +afii61248;2105 +afii61289;2113 +afii61352;2116 +afii61573;202C +afii61574;202D +afii61575;202E +afii61664;200C +afii63167;066D +afii64937;02BD +agrave;00E0 +agujarati;0A85 +agurmukhi;0A05 +ahiragana;3042 +ahookabove;1EA3 +aibengali;0990 +aibopomofo;311E +aideva;0910 +aiecyrillic;04D5 +aigujarati;0A90 +aigurmukhi;0A10 +aimatragurmukhi;0A48 +ainarabic;0639 +ainfinalarabic;FECA +aininitialarabic;FECB +ainmedialarabic;FECC +ainvertedbreve;0203 +aivowelsignbengali;09C8 +aivowelsigndeva;0948 +aivowelsigngujarati;0AC8 +akatakana;30A2 +akatakanahalfwidth;FF71 +akorean;314F +alef;05D0 +alefarabic;0627 +alefdageshhebrew;FB30 +aleffinalarabic;FE8E +alefhamzaabovearabic;0623 +alefhamzaabovefinalarabic;FE84 +alefhamzabelowarabic;0625 +alefhamzabelowfinalarabic;FE88 +alefhebrew;05D0 +aleflamedhebrew;FB4F +alefmaddaabovearabic;0622 +alefmaddaabovefinalarabic;FE82 +alefmaksuraarabic;0649 +alefmaksurafinalarabic;FEF0 +alefmaksurainitialarabic;FEF3 +alefmaksuramedialarabic;FEF4 +alefpatahhebrew;FB2E +alefqamatshebrew;FB2F +aleph;2135 +allequal;224C +alpha;03B1 +alphatonos;03AC +amacron;0101 +amonospace;FF41 +ampersand;0026 +ampersandmonospace;FF06 +ampersandsmall;F726 +amsquare;33C2 +anbopomofo;3122 +angbopomofo;3124 +angkhankhuthai;0E5A +angle;2220 +anglebracketleft;3008 +anglebracketleftvertical;FE3F +anglebracketright;3009 +anglebracketrightvertical;FE40 +angleleft;2329 +angleright;232A +angstrom;212B +anoteleia;0387 +anudattadeva;0952 +anusvarabengali;0982 +anusvaradeva;0902 +anusvaragujarati;0A82 +aogonek;0105 +apaatosquare;3300 +aparen;249C +apostrophearmenian;055A +apostrophemod;02BC +apple;F8FF +approaches;2250 +approxequal;2248 +approxequalorimage;2252 +approximatelyequal;2245 +araeaekorean;318E +araeakorean;318D +arc;2312 +arighthalfring;1E9A +aring;00E5 +aringacute;01FB +aringbelow;1E01 +arrowboth;2194 +arrowdashdown;21E3 +arrowdashleft;21E0 +arrowdashright;21E2 +arrowdashup;21E1 +arrowdblboth;21D4 +arrowdbldown;21D3 +arrowdblleft;21D0 +arrowdblright;21D2 +arrowdblup;21D1 +arrowdown;2193 +arrowdownleft;2199 +arrowdownright;2198 +arrowdownwhite;21E9 +arrowheaddownmod;02C5 +arrowheadleftmod;02C2 +arrowheadrightmod;02C3 +arrowheadupmod;02C4 +arrowhorizex;F8E7 +arrowleft;2190 +arrowleftdbl;21D0 +arrowleftdblstroke;21CD +arrowleftoverright;21C6 +arrowleftwhite;21E6 +arrowright;2192 +arrowrightdblstroke;21CF +arrowrightheavy;279E +arrowrightoverleft;21C4 +arrowrightwhite;21E8 +arrowtableft;21E4 +arrowtabright;21E5 +arrowup;2191 +arrowupdn;2195 +arrowupdnbse;21A8 +arrowupdownbase;21A8 +arrowupleft;2196 +arrowupleftofdown;21C5 +arrowupright;2197 +arrowupwhite;21E7 +arrowvertex;F8E6 +asciicircum;005E +asciicircummonospace;FF3E +asciitilde;007E +asciitildemonospace;FF5E +ascript;0251 +ascriptturned;0252 +asmallhiragana;3041 +asmallkatakana;30A1 +asmallkatakanahalfwidth;FF67 +asterisk;002A +asteriskaltonearabic;066D +asteriskarabic;066D +asteriskmath;2217 +asteriskmonospace;FF0A +asterisksmall;FE61 +asterism;2042 +asuperior;F6E9 +asymptoticallyequal;2243 +at;0040 +atilde;00E3 +atmonospace;FF20 +atsmall;FE6B +aturned;0250 +aubengali;0994 +aubopomofo;3120 +audeva;0914 +augujarati;0A94 +augurmukhi;0A14 +aulengthmarkbengali;09D7 +aumatragurmukhi;0A4C +auvowelsignbengali;09CC +auvowelsigndeva;094C +auvowelsigngujarati;0ACC +avagrahadeva;093D +aybarmenian;0561 +ayin;05E2 +ayinaltonehebrew;FB20 +ayinhebrew;05E2 +b;0062 +babengali;09AC +backslash;005C +backslashmonospace;FF3C +badeva;092C +bagujarati;0AAC +bagurmukhi;0A2C +bahiragana;3070 +bahtthai;0E3F +bakatakana;30D0 +bar;007C +barmonospace;FF5C +bbopomofo;3105 +bcircle;24D1 +bdotaccent;1E03 +bdotbelow;1E05 +beamedsixteenthnotes;266C +because;2235 +becyrillic;0431 +beharabic;0628 +behfinalarabic;FE90 +behinitialarabic;FE91 +behiragana;3079 +behmedialarabic;FE92 +behmeeminitialarabic;FC9F +behmeemisolatedarabic;FC08 +behnoonfinalarabic;FC6D +bekatakana;30D9 +benarmenian;0562 +bet;05D1 +beta;03B2 +betasymbolgreek;03D0 +betdagesh;FB31 +betdageshhebrew;FB31 +bethebrew;05D1 +betrafehebrew;FB4C +bhabengali;09AD +bhadeva;092D +bhagujarati;0AAD +bhagurmukhi;0A2D +bhook;0253 +bihiragana;3073 +bikatakana;30D3 +bilabialclick;0298 +bindigurmukhi;0A02 +birusquare;3331 +blackcircle;25CF +blackdiamond;25C6 +blackdownpointingtriangle;25BC +blackleftpointingpointer;25C4 +blackleftpointingtriangle;25C0 +blacklenticularbracketleft;3010 +blacklenticularbracketleftvertical;FE3B +blacklenticularbracketright;3011 +blacklenticularbracketrightvertical;FE3C +blacklowerlefttriangle;25E3 +blacklowerrighttriangle;25E2 +blackrectangle;25AC +blackrightpointingpointer;25BA +blackrightpointingtriangle;25B6 +blacksmallsquare;25AA +blacksmilingface;263B +blacksquare;25A0 +blackstar;2605 +blackupperlefttriangle;25E4 +blackupperrighttriangle;25E5 +blackuppointingsmalltriangle;25B4 +blackuppointingtriangle;25B2 +blank;2423 +blinebelow;1E07 +block;2588 +bmonospace;FF42 +bobaimaithai;0E1A +bohiragana;307C +bokatakana;30DC +bparen;249D +bqsquare;33C3 +braceex;F8F4 +braceleft;007B +braceleftbt;F8F3 +braceleftmid;F8F2 +braceleftmonospace;FF5B +braceleftsmall;FE5B +bracelefttp;F8F1 +braceleftvertical;FE37 +braceright;007D +bracerightbt;F8FE +bracerightmid;F8FD +bracerightmonospace;FF5D +bracerightsmall;FE5C +bracerighttp;F8FC +bracerightvertical;FE38 +bracketleft;005B +bracketleftbt;F8F0 +bracketleftex;F8EF +bracketleftmonospace;FF3B +bracketlefttp;F8EE +bracketright;005D +bracketrightbt;F8FB +bracketrightex;F8FA +bracketrightmonospace;FF3D +bracketrighttp;F8F9 +breve;02D8 +brevebelowcmb;032E +brevecmb;0306 +breveinvertedbelowcmb;032F +breveinvertedcmb;0311 +breveinverteddoublecmb;0361 +bridgebelowcmb;032A +bridgeinvertedbelowcmb;033A +brokenbar;00A6 +bstroke;0180 +bsuperior;F6EA +btopbar;0183 +buhiragana;3076 +bukatakana;30D6 +bullet;2022 +bulletinverse;25D8 +bulletoperator;2219 +bullseye;25CE +c;0063 +caarmenian;056E +cabengali;099A +cacute;0107 +cadeva;091A +cagujarati;0A9A +cagurmukhi;0A1A +calsquare;3388 +candrabindubengali;0981 +candrabinducmb;0310 +candrabindudeva;0901 +candrabindugujarati;0A81 +capslock;21EA +careof;2105 +caron;02C7 +caronbelowcmb;032C +caroncmb;030C +carriagereturn;21B5 +cbopomofo;3118 +ccaron;010D +ccedilla;00E7 +ccedillaacute;1E09 +ccircle;24D2 +ccircumflex;0109 +ccurl;0255 +cdot;010B +cdotaccent;010B +cdsquare;33C5 +cedilla;00B8 +cedillacmb;0327 +cent;00A2 +centigrade;2103 +centinferior;F6DF +centmonospace;FFE0 +centoldstyle;F7A2 +centsuperior;F6E0 +chaarmenian;0579 +chabengali;099B +chadeva;091B +chagujarati;0A9B +chagurmukhi;0A1B +chbopomofo;3114 +cheabkhasiancyrillic;04BD +checkmark;2713 +checyrillic;0447 +chedescenderabkhasiancyrillic;04BF +chedescendercyrillic;04B7 +chedieresiscyrillic;04F5 +cheharmenian;0573 +chekhakassiancyrillic;04CC +cheverticalstrokecyrillic;04B9 +chi;03C7 +chieuchacirclekorean;3277 +chieuchaparenkorean;3217 +chieuchcirclekorean;3269 +chieuchkorean;314A +chieuchparenkorean;3209 +chochangthai;0E0A +chochanthai;0E08 +chochingthai;0E09 +chochoethai;0E0C +chook;0188 +cieucacirclekorean;3276 +cieucaparenkorean;3216 +cieuccirclekorean;3268 +cieuckorean;3148 +cieucparenkorean;3208 +cieucuparenkorean;321C +circle;25CB +circlemultiply;2297 +circleot;2299 +circleplus;2295 +circlepostalmark;3036 +circlewithlefthalfblack;25D0 +circlewithrighthalfblack;25D1 +circumflex;02C6 +circumflexbelowcmb;032D +circumflexcmb;0302 +clear;2327 +clickalveolar;01C2 +clickdental;01C0 +clicklateral;01C1 +clickretroflex;01C3 +club;2663 +clubsuitblack;2663 +clubsuitwhite;2667 +cmcubedsquare;33A4 +cmonospace;FF43 +cmsquaredsquare;33A0 +coarmenian;0581 +colon;003A +colonmonetary;20A1 +colonmonospace;FF1A +colonsign;20A1 +colonsmall;FE55 +colontriangularhalfmod;02D1 +colontriangularmod;02D0 +comma;002C +commaabovecmb;0313 +commaaboverightcmb;0315 +commaaccent;F6C3 +commaarabic;060C +commaarmenian;055D +commainferior;F6E1 +commamonospace;FF0C +commareversedabovecmb;0314 +commareversedmod;02BD +commasmall;FE50 +commasuperior;F6E2 +commaturnedabovecmb;0312 +commaturnedmod;02BB +compass;263C +congruent;2245 +contourintegral;222E +control;2303 +controlACK;0006 +controlBEL;0007 +controlBS;0008 +controlCAN;0018 +controlCR;000D +controlDC1;0011 +controlDC2;0012 +controlDC3;0013 +controlDC4;0014 +controlDEL;007F +controlDLE;0010 +controlEM;0019 +controlENQ;0005 +controlEOT;0004 +controlESC;001B +controlETB;0017 +controlETX;0003 +controlFF;000C +controlFS;001C +controlGS;001D +controlHT;0009 +controlLF;000A +controlNAK;0015 +controlRS;001E +controlSI;000F +controlSO;000E +controlSOT;0002 +controlSTX;0001 +controlSUB;001A +controlSYN;0016 +controlUS;001F +controlVT;000B +copyright;00A9 +copyrightsans;F8E9 +copyrightserif;F6D9 +cornerbracketleft;300C +cornerbracketlefthalfwidth;FF62 +cornerbracketleftvertical;FE41 +cornerbracketright;300D +cornerbracketrighthalfwidth;FF63 +cornerbracketrightvertical;FE42 +corporationsquare;337F +cosquare;33C7 +coverkgsquare;33C6 +cparen;249E +cruzeiro;20A2 +cstretched;0297 +curlyand;22CF +curlyor;22CE +currency;00A4 +cyrBreve;F6D1 +cyrFlex;F6D2 +cyrbreve;F6D4 +cyrflex;F6D5 +d;0064 +daarmenian;0564 +dabengali;09A6 +dadarabic;0636 +dadeva;0926 +dadfinalarabic;FEBE +dadinitialarabic;FEBF +dadmedialarabic;FEC0 +dagesh;05BC +dageshhebrew;05BC +dagger;2020 +daggerdbl;2021 +dagujarati;0AA6 +dagurmukhi;0A26 +dahiragana;3060 +dakatakana;30C0 +dalarabic;062F +dalet;05D3 +daletdagesh;FB33 +daletdageshhebrew;FB33 +dalethatafpatah;05D3 05B2 +dalethatafpatahhebrew;05D3 05B2 +dalethatafsegol;05D3 05B1 +dalethatafsegolhebrew;05D3 05B1 +dalethebrew;05D3 +dalethiriq;05D3 05B4 +dalethiriqhebrew;05D3 05B4 +daletholam;05D3 05B9 +daletholamhebrew;05D3 05B9 +daletpatah;05D3 05B7 +daletpatahhebrew;05D3 05B7 +daletqamats;05D3 05B8 +daletqamatshebrew;05D3 05B8 +daletqubuts;05D3 05BB +daletqubutshebrew;05D3 05BB +daletsegol;05D3 05B6 +daletsegolhebrew;05D3 05B6 +daletsheva;05D3 05B0 +daletshevahebrew;05D3 05B0 +dalettsere;05D3 05B5 +dalettserehebrew;05D3 05B5 +dalfinalarabic;FEAA +dammaarabic;064F +dammalowarabic;064F +dammatanaltonearabic;064C +dammatanarabic;064C +danda;0964 +dargahebrew;05A7 +dargalefthebrew;05A7 +dasiapneumatacyrilliccmb;0485 +dblGrave;F6D3 +dblanglebracketleft;300A +dblanglebracketleftvertical;FE3D +dblanglebracketright;300B +dblanglebracketrightvertical;FE3E +dblarchinvertedbelowcmb;032B +dblarrowleft;21D4 +dblarrowright;21D2 +dbldanda;0965 +dblgrave;F6D6 +dblgravecmb;030F +dblintegral;222C +dbllowline;2017 +dbllowlinecmb;0333 +dbloverlinecmb;033F +dblprimemod;02BA +dblverticalbar;2016 +dblverticallineabovecmb;030E +dbopomofo;3109 +dbsquare;33C8 +dcaron;010F +dcedilla;1E11 +dcircle;24D3 +dcircumflexbelow;1E13 +dcroat;0111 +ddabengali;09A1 +ddadeva;0921 +ddagujarati;0AA1 +ddagurmukhi;0A21 +ddalarabic;0688 +ddalfinalarabic;FB89 +dddhadeva;095C +ddhabengali;09A2 +ddhadeva;0922 +ddhagujarati;0AA2 +ddhagurmukhi;0A22 +ddotaccent;1E0B +ddotbelow;1E0D +decimalseparatorarabic;066B +decimalseparatorpersian;066B +decyrillic;0434 +degree;00B0 +dehihebrew;05AD +dehiragana;3067 +deicoptic;03EF +dekatakana;30C7 +deleteleft;232B +deleteright;2326 +delta;03B4 +deltaturned;018D +denominatorminusonenumeratorbengali;09F8 +dezh;02A4 +dhabengali;09A7 +dhadeva;0927 +dhagujarati;0AA7 +dhagurmukhi;0A27 +dhook;0257 +dialytikatonos;0385 +dialytikatonoscmb;0344 +diamond;2666 +diamondsuitwhite;2662 +dieresis;00A8 +dieresisacute;F6D7 +dieresisbelowcmb;0324 +dieresiscmb;0308 +dieresisgrave;F6D8 +dieresistonos;0385 +dihiragana;3062 +dikatakana;30C2 +dittomark;3003 +divide;00F7 +divides;2223 +divisionslash;2215 +djecyrillic;0452 +dkshade;2593 +dlinebelow;1E0F +dlsquare;3397 +dmacron;0111 +dmonospace;FF44 +dnblock;2584 +dochadathai;0E0E +dodekthai;0E14 +dohiragana;3069 +dokatakana;30C9 +dollar;0024 +dollarinferior;F6E3 +dollarmonospace;FF04 +dollaroldstyle;F724 +dollarsmall;FE69 +dollarsuperior;F6E4 +dong;20AB +dorusquare;3326 +dotaccent;02D9 +dotaccentcmb;0307 +dotbelowcmb;0323 +dotbelowcomb;0323 +dotkatakana;30FB +dotlessi;0131 +dotlessj;F6BE +dotlessjstrokehook;0284 +dotmath;22C5 +dottedcircle;25CC +doubleyodpatah;FB1F +doubleyodpatahhebrew;FB1F +downtackbelowcmb;031E +downtackmod;02D5 +dparen;249F +dsuperior;F6EB +dtail;0256 +dtopbar;018C +duhiragana;3065 +dukatakana;30C5 +dz;01F3 +dzaltone;02A3 +dzcaron;01C6 +dzcurl;02A5 +dzeabkhasiancyrillic;04E1 +dzecyrillic;0455 +dzhecyrillic;045F +e;0065 +eacute;00E9 +earth;2641 +ebengali;098F +ebopomofo;311C +ebreve;0115 +ecandradeva;090D +ecandragujarati;0A8D +ecandravowelsigndeva;0945 +ecandravowelsigngujarati;0AC5 +ecaron;011B +ecedillabreve;1E1D +echarmenian;0565 +echyiwnarmenian;0587 +ecircle;24D4 +ecircumflex;00EA +ecircumflexacute;1EBF +ecircumflexbelow;1E19 +ecircumflexdotbelow;1EC7 +ecircumflexgrave;1EC1 +ecircumflexhookabove;1EC3 +ecircumflextilde;1EC5 +ecyrillic;0454 +edblgrave;0205 +edeva;090F +edieresis;00EB +edot;0117 +edotaccent;0117 +edotbelow;1EB9 +eegurmukhi;0A0F +eematragurmukhi;0A47 +efcyrillic;0444 +egrave;00E8 +egujarati;0A8F +eharmenian;0567 +ehbopomofo;311D +ehiragana;3048 +ehookabove;1EBB +eibopomofo;311F +eight;0038 +eightarabic;0668 +eightbengali;09EE +eightcircle;2467 +eightcircleinversesansserif;2791 +eightdeva;096E +eighteencircle;2471 +eighteenparen;2485 +eighteenperiod;2499 +eightgujarati;0AEE +eightgurmukhi;0A6E +eighthackarabic;0668 +eighthangzhou;3028 +eighthnotebeamed;266B +eightideographicparen;3227 +eightinferior;2088 +eightmonospace;FF18 +eightoldstyle;F738 +eightparen;247B +eightperiod;248F +eightpersian;06F8 +eightroman;2177 +eightsuperior;2078 +eightthai;0E58 +einvertedbreve;0207 +eiotifiedcyrillic;0465 +ekatakana;30A8 +ekatakanahalfwidth;FF74 +ekonkargurmukhi;0A74 +ekorean;3154 +elcyrillic;043B +element;2208 +elevencircle;246A +elevenparen;247E +elevenperiod;2492 +elevenroman;217A +ellipsis;2026 +ellipsisvertical;22EE +emacron;0113 +emacronacute;1E17 +emacrongrave;1E15 +emcyrillic;043C +emdash;2014 +emdashvertical;FE31 +emonospace;FF45 +emphasismarkarmenian;055B +emptyset;2205 +enbopomofo;3123 +encyrillic;043D +endash;2013 +endashvertical;FE32 +endescendercyrillic;04A3 +eng;014B +engbopomofo;3125 +enghecyrillic;04A5 +enhookcyrillic;04C8 +enspace;2002 +eogonek;0119 +eokorean;3153 +eopen;025B +eopenclosed;029A +eopenreversed;025C +eopenreversedclosed;025E +eopenreversedhook;025D +eparen;24A0 +epsilon;03B5 +epsilontonos;03AD +equal;003D +equalmonospace;FF1D +equalsmall;FE66 +equalsuperior;207C +equivalence;2261 +erbopomofo;3126 +ercyrillic;0440 +ereversed;0258 +ereversedcyrillic;044D +escyrillic;0441 +esdescendercyrillic;04AB +esh;0283 +eshcurl;0286 +eshortdeva;090E +eshortvowelsigndeva;0946 +eshreversedloop;01AA +eshsquatreversed;0285 +esmallhiragana;3047 +esmallkatakana;30A7 +esmallkatakanahalfwidth;FF6A +estimated;212E +esuperior;F6EC +eta;03B7 +etarmenian;0568 +etatonos;03AE +eth;00F0 +etilde;1EBD +etildebelow;1E1B +etnahtafoukhhebrew;0591 +etnahtafoukhlefthebrew;0591 +etnahtahebrew;0591 +etnahtalefthebrew;0591 +eturned;01DD +eukorean;3161 +euro;20AC +evowelsignbengali;09C7 +evowelsigndeva;0947 +evowelsigngujarati;0AC7 +exclam;0021 +exclamarmenian;055C +exclamdbl;203C +exclamdown;00A1 +exclamdownsmall;F7A1 +exclammonospace;FF01 +exclamsmall;F721 +existential;2203 +ezh;0292 +ezhcaron;01EF +ezhcurl;0293 +ezhreversed;01B9 +ezhtail;01BA +f;0066 +fadeva;095E +fagurmukhi;0A5E +fahrenheit;2109 +fathaarabic;064E +fathalowarabic;064E +fathatanarabic;064B +fbopomofo;3108 +fcircle;24D5 +fdotaccent;1E1F +feharabic;0641 +feharmenian;0586 +fehfinalarabic;FED2 +fehinitialarabic;FED3 +fehmedialarabic;FED4 +feicoptic;03E5 +female;2640 +ff;FB00 +ffi;FB03 +ffl;FB04 +fi;FB01 +fifteencircle;246E +fifteenparen;2482 +fifteenperiod;2496 +figuredash;2012 +filledbox;25A0 +filledrect;25AC +finalkaf;05DA +finalkafdagesh;FB3A +finalkafdageshhebrew;FB3A +finalkafhebrew;05DA +finalkafqamats;05DA 05B8 +finalkafqamatshebrew;05DA 05B8 +finalkafsheva;05DA 05B0 +finalkafshevahebrew;05DA 05B0 +finalmem;05DD +finalmemhebrew;05DD +finalnun;05DF +finalnunhebrew;05DF +finalpe;05E3 +finalpehebrew;05E3 +finaltsadi;05E5 +finaltsadihebrew;05E5 +firsttonechinese;02C9 +fisheye;25C9 +fitacyrillic;0473 +five;0035 +fivearabic;0665 +fivebengali;09EB +fivecircle;2464 +fivecircleinversesansserif;278E +fivedeva;096B +fiveeighths;215D +fivegujarati;0AEB +fivegurmukhi;0A6B +fivehackarabic;0665 +fivehangzhou;3025 +fiveideographicparen;3224 +fiveinferior;2085 +fivemonospace;FF15 +fiveoldstyle;F735 +fiveparen;2478 +fiveperiod;248C +fivepersian;06F5 +fiveroman;2174 +fivesuperior;2075 +fivethai;0E55 +fl;FB02 +florin;0192 +fmonospace;FF46 +fmsquare;3399 +fofanthai;0E1F +fofathai;0E1D +fongmanthai;0E4F +forall;2200 +four;0034 +fourarabic;0664 +fourbengali;09EA +fourcircle;2463 +fourcircleinversesansserif;278D +fourdeva;096A +fourgujarati;0AEA +fourgurmukhi;0A6A +fourhackarabic;0664 +fourhangzhou;3024 +fourideographicparen;3223 +fourinferior;2084 +fourmonospace;FF14 +fournumeratorbengali;09F7 +fouroldstyle;F734 +fourparen;2477 +fourperiod;248B +fourpersian;06F4 +fourroman;2173 +foursuperior;2074 +fourteencircle;246D +fourteenparen;2481 +fourteenperiod;2495 +fourthai;0E54 +fourthtonechinese;02CB +fparen;24A1 +fraction;2044 +franc;20A3 +g;0067 +gabengali;0997 +gacute;01F5 +gadeva;0917 +gafarabic;06AF +gaffinalarabic;FB93 +gafinitialarabic;FB94 +gafmedialarabic;FB95 +gagujarati;0A97 +gagurmukhi;0A17 +gahiragana;304C +gakatakana;30AC +gamma;03B3 +gammalatinsmall;0263 +gammasuperior;02E0 +gangiacoptic;03EB +gbopomofo;310D +gbreve;011F +gcaron;01E7 +gcedilla;0123 +gcircle;24D6 +gcircumflex;011D +gcommaaccent;0123 +gdot;0121 +gdotaccent;0121 +gecyrillic;0433 +gehiragana;3052 +gekatakana;30B2 +geometricallyequal;2251 +gereshaccenthebrew;059C +gereshhebrew;05F3 +gereshmuqdamhebrew;059D +germandbls;00DF +gershayimaccenthebrew;059E +gershayimhebrew;05F4 +getamark;3013 +ghabengali;0998 +ghadarmenian;0572 +ghadeva;0918 +ghagujarati;0A98 +ghagurmukhi;0A18 +ghainarabic;063A +ghainfinalarabic;FECE +ghaininitialarabic;FECF +ghainmedialarabic;FED0 +ghemiddlehookcyrillic;0495 +ghestrokecyrillic;0493 +gheupturncyrillic;0491 +ghhadeva;095A +ghhagurmukhi;0A5A +ghook;0260 +ghzsquare;3393 +gihiragana;304E +gikatakana;30AE +gimarmenian;0563 +gimel;05D2 +gimeldagesh;FB32 +gimeldageshhebrew;FB32 +gimelhebrew;05D2 +gjecyrillic;0453 +glottalinvertedstroke;01BE +glottalstop;0294 +glottalstopinverted;0296 +glottalstopmod;02C0 +glottalstopreversed;0295 +glottalstopreversedmod;02C1 +glottalstopreversedsuperior;02E4 +glottalstopstroke;02A1 +glottalstopstrokereversed;02A2 +gmacron;1E21 +gmonospace;FF47 +gohiragana;3054 +gokatakana;30B4 +gparen;24A2 +gpasquare;33AC +gradient;2207 +grave;0060 +gravebelowcmb;0316 +gravecmb;0300 +gravecomb;0300 +gravedeva;0953 +gravelowmod;02CE +gravemonospace;FF40 +gravetonecmb;0340 +greater;003E +greaterequal;2265 +greaterequalorless;22DB +greatermonospace;FF1E +greaterorequivalent;2273 +greaterorless;2277 +greateroverequal;2267 +greatersmall;FE65 +gscript;0261 +gstroke;01E5 +guhiragana;3050 +guillemotleft;00AB +guillemotright;00BB +guilsinglleft;2039 +guilsinglright;203A +gukatakana;30B0 +guramusquare;3318 +gysquare;33C9 +h;0068 +haabkhasiancyrillic;04A9 +haaltonearabic;06C1 +habengali;09B9 +hadescendercyrillic;04B3 +hadeva;0939 +hagujarati;0AB9 +hagurmukhi;0A39 +haharabic;062D +hahfinalarabic;FEA2 +hahinitialarabic;FEA3 +hahiragana;306F +hahmedialarabic;FEA4 +haitusquare;332A +hakatakana;30CF +hakatakanahalfwidth;FF8A +halantgurmukhi;0A4D +hamzaarabic;0621 +hamzadammaarabic;0621 064F +hamzadammatanarabic;0621 064C +hamzafathaarabic;0621 064E +hamzafathatanarabic;0621 064B +hamzalowarabic;0621 +hamzalowkasraarabic;0621 0650 +hamzalowkasratanarabic;0621 064D +hamzasukunarabic;0621 0652 +hangulfiller;3164 +hardsigncyrillic;044A +harpoonleftbarbup;21BC +harpoonrightbarbup;21C0 +hasquare;33CA +hatafpatah;05B2 +hatafpatah16;05B2 +hatafpatah23;05B2 +hatafpatah2f;05B2 +hatafpatahhebrew;05B2 +hatafpatahnarrowhebrew;05B2 +hatafpatahquarterhebrew;05B2 +hatafpatahwidehebrew;05B2 +hatafqamats;05B3 +hatafqamats1b;05B3 +hatafqamats28;05B3 +hatafqamats34;05B3 +hatafqamatshebrew;05B3 +hatafqamatsnarrowhebrew;05B3 +hatafqamatsquarterhebrew;05B3 +hatafqamatswidehebrew;05B3 +hatafsegol;05B1 +hatafsegol17;05B1 +hatafsegol24;05B1 +hatafsegol30;05B1 +hatafsegolhebrew;05B1 +hatafsegolnarrowhebrew;05B1 +hatafsegolquarterhebrew;05B1 +hatafsegolwidehebrew;05B1 +hbar;0127 +hbopomofo;310F +hbrevebelow;1E2B +hcedilla;1E29 +hcircle;24D7 +hcircumflex;0125 +hdieresis;1E27 +hdotaccent;1E23 +hdotbelow;1E25 +he;05D4 +heart;2665 +heartsuitblack;2665 +heartsuitwhite;2661 +hedagesh;FB34 +hedageshhebrew;FB34 +hehaltonearabic;06C1 +heharabic;0647 +hehebrew;05D4 +hehfinalaltonearabic;FBA7 +hehfinalalttwoarabic;FEEA +hehfinalarabic;FEEA +hehhamzaabovefinalarabic;FBA5 +hehhamzaaboveisolatedarabic;FBA4 +hehinitialaltonearabic;FBA8 +hehinitialarabic;FEEB +hehiragana;3078 +hehmedialaltonearabic;FBA9 +hehmedialarabic;FEEC +heiseierasquare;337B +hekatakana;30D8 +hekatakanahalfwidth;FF8D +hekutaarusquare;3336 +henghook;0267 +herutusquare;3339 +het;05D7 +hethebrew;05D7 +hhook;0266 +hhooksuperior;02B1 +hieuhacirclekorean;327B +hieuhaparenkorean;321B +hieuhcirclekorean;326D +hieuhkorean;314E +hieuhparenkorean;320D +hihiragana;3072 +hikatakana;30D2 +hikatakanahalfwidth;FF8B +hiriq;05B4 +hiriq14;05B4 +hiriq21;05B4 +hiriq2d;05B4 +hiriqhebrew;05B4 +hiriqnarrowhebrew;05B4 +hiriqquarterhebrew;05B4 +hiriqwidehebrew;05B4 +hlinebelow;1E96 +hmonospace;FF48 +hoarmenian;0570 +hohipthai;0E2B +hohiragana;307B +hokatakana;30DB +hokatakanahalfwidth;FF8E +holam;05B9 +holam19;05B9 +holam26;05B9 +holam32;05B9 +holamhebrew;05B9 +holamnarrowhebrew;05B9 +holamquarterhebrew;05B9 +holamwidehebrew;05B9 +honokhukthai;0E2E +hookabovecomb;0309 +hookcmb;0309 +hookpalatalizedbelowcmb;0321 +hookretroflexbelowcmb;0322 +hoonsquare;3342 +horicoptic;03E9 +horizontalbar;2015 +horncmb;031B +hotsprings;2668 +house;2302 +hparen;24A3 +hsuperior;02B0 +hturned;0265 +huhiragana;3075 +huiitosquare;3333 +hukatakana;30D5 +hukatakanahalfwidth;FF8C +hungarumlaut;02DD +hungarumlautcmb;030B +hv;0195 +hyphen;002D +hypheninferior;F6E5 +hyphenmonospace;FF0D +hyphensmall;FE63 +hyphensuperior;F6E6 +hyphentwo;2010 +i;0069 +iacute;00ED +iacyrillic;044F +ibengali;0987 +ibopomofo;3127 +ibreve;012D +icaron;01D0 +icircle;24D8 +icircumflex;00EE +icyrillic;0456 +idblgrave;0209 +ideographearthcircle;328F +ideographfirecircle;328B +ideographicallianceparen;323F +ideographiccallparen;323A +ideographiccentrecircle;32A5 +ideographicclose;3006 +ideographiccomma;3001 +ideographiccommaleft;FF64 +ideographiccongratulationparen;3237 +ideographiccorrectcircle;32A3 +ideographicearthparen;322F +ideographicenterpriseparen;323D +ideographicexcellentcircle;329D +ideographicfestivalparen;3240 +ideographicfinancialcircle;3296 +ideographicfinancialparen;3236 +ideographicfireparen;322B +ideographichaveparen;3232 +ideographichighcircle;32A4 +ideographiciterationmark;3005 +ideographiclaborcircle;3298 +ideographiclaborparen;3238 +ideographicleftcircle;32A7 +ideographiclowcircle;32A6 +ideographicmedicinecircle;32A9 +ideographicmetalparen;322E +ideographicmoonparen;322A +ideographicnameparen;3234 +ideographicperiod;3002 +ideographicprintcircle;329E +ideographicreachparen;3243 +ideographicrepresentparen;3239 +ideographicresourceparen;323E +ideographicrightcircle;32A8 +ideographicsecretcircle;3299 +ideographicselfparen;3242 +ideographicsocietyparen;3233 +ideographicspace;3000 +ideographicspecialparen;3235 +ideographicstockparen;3231 +ideographicstudyparen;323B +ideographicsunparen;3230 +ideographicsuperviseparen;323C +ideographicwaterparen;322C +ideographicwoodparen;322D +ideographiczero;3007 +ideographmetalcircle;328E +ideographmooncircle;328A +ideographnamecircle;3294 +ideographsuncircle;3290 +ideographwatercircle;328C +ideographwoodcircle;328D +ideva;0907 +idieresis;00EF +idieresisacute;1E2F +idieresiscyrillic;04E5 +idotbelow;1ECB +iebrevecyrillic;04D7 +iecyrillic;0435 +ieungacirclekorean;3275 +ieungaparenkorean;3215 +ieungcirclekorean;3267 +ieungkorean;3147 +ieungparenkorean;3207 +igrave;00EC +igujarati;0A87 +igurmukhi;0A07 +ihiragana;3044 +ihookabove;1EC9 +iibengali;0988 +iicyrillic;0438 +iideva;0908 +iigujarati;0A88 +iigurmukhi;0A08 +iimatragurmukhi;0A40 +iinvertedbreve;020B +iishortcyrillic;0439 +iivowelsignbengali;09C0 +iivowelsigndeva;0940 +iivowelsigngujarati;0AC0 +ij;0133 +ikatakana;30A4 +ikatakanahalfwidth;FF72 +ikorean;3163 +ilde;02DC +iluyhebrew;05AC +imacron;012B +imacroncyrillic;04E3 +imageorapproximatelyequal;2253 +imatragurmukhi;0A3F +imonospace;FF49 +increment;2206 +infinity;221E +iniarmenian;056B +integral;222B +integralbottom;2321 +integralbt;2321 +integralex;F8F5 +integraltop;2320 +integraltp;2320 +intersection;2229 +intisquare;3305 +invbullet;25D8 +invcircle;25D9 +invsmileface;263B +iocyrillic;0451 +iogonek;012F +iota;03B9 +iotadieresis;03CA +iotadieresistonos;0390 +iotalatin;0269 +iotatonos;03AF +iparen;24A4 +irigurmukhi;0A72 +ismallhiragana;3043 +ismallkatakana;30A3 +ismallkatakanahalfwidth;FF68 +issharbengali;09FA +istroke;0268 +isuperior;F6ED +iterationhiragana;309D +iterationkatakana;30FD +itilde;0129 +itildebelow;1E2D +iubopomofo;3129 +iucyrillic;044E +ivowelsignbengali;09BF +ivowelsigndeva;093F +ivowelsigngujarati;0ABF +izhitsacyrillic;0475 +izhitsadblgravecyrillic;0477 +j;006A +jaarmenian;0571 +jabengali;099C +jadeva;091C +jagujarati;0A9C +jagurmukhi;0A1C +jbopomofo;3110 +jcaron;01F0 +jcircle;24D9 +jcircumflex;0135 +jcrossedtail;029D +jdotlessstroke;025F +jecyrillic;0458 +jeemarabic;062C +jeemfinalarabic;FE9E +jeeminitialarabic;FE9F +jeemmedialarabic;FEA0 +jeharabic;0698 +jehfinalarabic;FB8B +jhabengali;099D +jhadeva;091D +jhagujarati;0A9D +jhagurmukhi;0A1D +jheharmenian;057B +jis;3004 +jmonospace;FF4A +jparen;24A5 +jsuperior;02B2 +k;006B +kabashkircyrillic;04A1 +kabengali;0995 +kacute;1E31 +kacyrillic;043A +kadescendercyrillic;049B +kadeva;0915 +kaf;05DB +kafarabic;0643 +kafdagesh;FB3B +kafdageshhebrew;FB3B +kaffinalarabic;FEDA +kafhebrew;05DB +kafinitialarabic;FEDB +kafmedialarabic;FEDC +kafrafehebrew;FB4D +kagujarati;0A95 +kagurmukhi;0A15 +kahiragana;304B +kahookcyrillic;04C4 +kakatakana;30AB +kakatakanahalfwidth;FF76 +kappa;03BA +kappasymbolgreek;03F0 +kapyeounmieumkorean;3171 +kapyeounphieuphkorean;3184 +kapyeounpieupkorean;3178 +kapyeounssangpieupkorean;3179 +karoriisquare;330D +kashidaautoarabic;0640 +kashidaautonosidebearingarabic;0640 +kasmallkatakana;30F5 +kasquare;3384 +kasraarabic;0650 +kasratanarabic;064D +kastrokecyrillic;049F +katahiraprolongmarkhalfwidth;FF70 +kaverticalstrokecyrillic;049D +kbopomofo;310E +kcalsquare;3389 +kcaron;01E9 +kcedilla;0137 +kcircle;24DA +kcommaaccent;0137 +kdotbelow;1E33 +keharmenian;0584 +kehiragana;3051 +kekatakana;30B1 +kekatakanahalfwidth;FF79 +kenarmenian;056F +kesmallkatakana;30F6 +kgreenlandic;0138 +khabengali;0996 +khacyrillic;0445 +khadeva;0916 +khagujarati;0A96 +khagurmukhi;0A16 +khaharabic;062E +khahfinalarabic;FEA6 +khahinitialarabic;FEA7 +khahmedialarabic;FEA8 +kheicoptic;03E7 +khhadeva;0959 +khhagurmukhi;0A59 +khieukhacirclekorean;3278 +khieukhaparenkorean;3218 +khieukhcirclekorean;326A +khieukhkorean;314B +khieukhparenkorean;320A +khokhaithai;0E02 +khokhonthai;0E05 +khokhuatthai;0E03 +khokhwaithai;0E04 +khomutthai;0E5B +khook;0199 +khorakhangthai;0E06 +khzsquare;3391 +kihiragana;304D +kikatakana;30AD +kikatakanahalfwidth;FF77 +kiroguramusquare;3315 +kiromeetorusquare;3316 +kirosquare;3314 +kiyeokacirclekorean;326E +kiyeokaparenkorean;320E +kiyeokcirclekorean;3260 +kiyeokkorean;3131 +kiyeokparenkorean;3200 +kiyeoksioskorean;3133 +kjecyrillic;045C +klinebelow;1E35 +klsquare;3398 +kmcubedsquare;33A6 +kmonospace;FF4B +kmsquaredsquare;33A2 +kohiragana;3053 +kohmsquare;33C0 +kokaithai;0E01 +kokatakana;30B3 +kokatakanahalfwidth;FF7A +kooposquare;331E +koppacyrillic;0481 +koreanstandardsymbol;327F +koroniscmb;0343 +kparen;24A6 +kpasquare;33AA +ksicyrillic;046F +ktsquare;33CF +kturned;029E +kuhiragana;304F +kukatakana;30AF +kukatakanahalfwidth;FF78 +kvsquare;33B8 +kwsquare;33BE +l;006C +labengali;09B2 +lacute;013A +ladeva;0932 +lagujarati;0AB2 +lagurmukhi;0A32 +lakkhangyaothai;0E45 +lamaleffinalarabic;FEFC +lamalefhamzaabovefinalarabic;FEF8 +lamalefhamzaaboveisolatedarabic;FEF7 +lamalefhamzabelowfinalarabic;FEFA +lamalefhamzabelowisolatedarabic;FEF9 +lamalefisolatedarabic;FEFB +lamalefmaddaabovefinalarabic;FEF6 +lamalefmaddaaboveisolatedarabic;FEF5 +lamarabic;0644 +lambda;03BB +lambdastroke;019B +lamed;05DC +lameddagesh;FB3C +lameddageshhebrew;FB3C +lamedhebrew;05DC +lamedholam;05DC 05B9 +lamedholamdagesh;05DC 05B9 05BC +lamedholamdageshhebrew;05DC 05B9 05BC +lamedholamhebrew;05DC 05B9 +lamfinalarabic;FEDE +lamhahinitialarabic;FCCA +laminitialarabic;FEDF +lamjeeminitialarabic;FCC9 +lamkhahinitialarabic;FCCB +lamlamhehisolatedarabic;FDF2 +lammedialarabic;FEE0 +lammeemhahinitialarabic;FD88 +lammeeminitialarabic;FCCC +lammeemjeeminitialarabic;FEDF FEE4 FEA0 +lammeemkhahinitialarabic;FEDF FEE4 FEA8 +largecircle;25EF +lbar;019A +lbelt;026C +lbopomofo;310C +lcaron;013E +lcedilla;013C +lcircle;24DB +lcircumflexbelow;1E3D +lcommaaccent;013C +ldot;0140 +ldotaccent;0140 +ldotbelow;1E37 +ldotbelowmacron;1E39 +leftangleabovecmb;031A +lefttackbelowcmb;0318 +less;003C +lessequal;2264 +lessequalorgreater;22DA +lessmonospace;FF1C +lessorequivalent;2272 +lessorgreater;2276 +lessoverequal;2266 +lesssmall;FE64 +lezh;026E +lfblock;258C +lhookretroflex;026D +lira;20A4 +liwnarmenian;056C +lj;01C9 +ljecyrillic;0459 +ll;F6C0 +lladeva;0933 +llagujarati;0AB3 +llinebelow;1E3B +llladeva;0934 +llvocalicbengali;09E1 +llvocalicdeva;0961 +llvocalicvowelsignbengali;09E3 +llvocalicvowelsigndeva;0963 +lmiddletilde;026B +lmonospace;FF4C +lmsquare;33D0 +lochulathai;0E2C +logicaland;2227 +logicalnot;00AC +logicalnotreversed;2310 +logicalor;2228 +lolingthai;0E25 +longs;017F +lowlinecenterline;FE4E +lowlinecmb;0332 +lowlinedashed;FE4D +lozenge;25CA +lparen;24A7 +lslash;0142 +lsquare;2113 +lsuperior;F6EE +ltshade;2591 +luthai;0E26 +lvocalicbengali;098C +lvocalicdeva;090C +lvocalicvowelsignbengali;09E2 +lvocalicvowelsigndeva;0962 +lxsquare;33D3 +m;006D +mabengali;09AE +macron;00AF +macronbelowcmb;0331 +macroncmb;0304 +macronlowmod;02CD +macronmonospace;FFE3 +macute;1E3F +madeva;092E +magujarati;0AAE +magurmukhi;0A2E +mahapakhhebrew;05A4 +mahapakhlefthebrew;05A4 +mahiragana;307E +maichattawalowleftthai;F895 +maichattawalowrightthai;F894 +maichattawathai;0E4B +maichattawaupperleftthai;F893 +maieklowleftthai;F88C +maieklowrightthai;F88B +maiekthai;0E48 +maiekupperleftthai;F88A +maihanakatleftthai;F884 +maihanakatthai;0E31 +maitaikhuleftthai;F889 +maitaikhuthai;0E47 +maitholowleftthai;F88F +maitholowrightthai;F88E +maithothai;0E49 +maithoupperleftthai;F88D +maitrilowleftthai;F892 +maitrilowrightthai;F891 +maitrithai;0E4A +maitriupperleftthai;F890 +maiyamokthai;0E46 +makatakana;30DE +makatakanahalfwidth;FF8F +male;2642 +mansyonsquare;3347 +maqafhebrew;05BE +mars;2642 +masoracirclehebrew;05AF +masquare;3383 +mbopomofo;3107 +mbsquare;33D4 +mcircle;24DC +mcubedsquare;33A5 +mdotaccent;1E41 +mdotbelow;1E43 +meemarabic;0645 +meemfinalarabic;FEE2 +meeminitialarabic;FEE3 +meemmedialarabic;FEE4 +meemmeeminitialarabic;FCD1 +meemmeemisolatedarabic;FC48 +meetorusquare;334D +mehiragana;3081 +meizierasquare;337E +mekatakana;30E1 +mekatakanahalfwidth;FF92 +mem;05DE +memdagesh;FB3E +memdageshhebrew;FB3E +memhebrew;05DE +menarmenian;0574 +merkhahebrew;05A5 +merkhakefulahebrew;05A6 +merkhakefulalefthebrew;05A6 +merkhalefthebrew;05A5 +mhook;0271 +mhzsquare;3392 +middledotkatakanahalfwidth;FF65 +middot;00B7 +mieumacirclekorean;3272 +mieumaparenkorean;3212 +mieumcirclekorean;3264 +mieumkorean;3141 +mieumpansioskorean;3170 +mieumparenkorean;3204 +mieumpieupkorean;316E +mieumsioskorean;316F +mihiragana;307F +mikatakana;30DF +mikatakanahalfwidth;FF90 +minus;2212 +minusbelowcmb;0320 +minuscircle;2296 +minusmod;02D7 +minusplus;2213 +minute;2032 +miribaarusquare;334A +mirisquare;3349 +mlonglegturned;0270 +mlsquare;3396 +mmcubedsquare;33A3 +mmonospace;FF4D +mmsquaredsquare;339F +mohiragana;3082 +mohmsquare;33C1 +mokatakana;30E2 +mokatakanahalfwidth;FF93 +molsquare;33D6 +momathai;0E21 +moverssquare;33A7 +moverssquaredsquare;33A8 +mparen;24A8 +mpasquare;33AB +mssquare;33B3 +msuperior;F6EF +mturned;026F +mu;00B5 +mu1;00B5 +muasquare;3382 +muchgreater;226B +muchless;226A +mufsquare;338C +mugreek;03BC +mugsquare;338D +muhiragana;3080 +mukatakana;30E0 +mukatakanahalfwidth;FF91 +mulsquare;3395 +multiply;00D7 +mumsquare;339B +munahhebrew;05A3 +munahlefthebrew;05A3 +musicalnote;266A +musicalnotedbl;266B +musicflatsign;266D +musicsharpsign;266F +mussquare;33B2 +muvsquare;33B6 +muwsquare;33BC +mvmegasquare;33B9 +mvsquare;33B7 +mwmegasquare;33BF +mwsquare;33BD +n;006E +nabengali;09A8 +nabla;2207 +nacute;0144 +nadeva;0928 +nagujarati;0AA8 +nagurmukhi;0A28 +nahiragana;306A +nakatakana;30CA +nakatakanahalfwidth;FF85 +napostrophe;0149 +nasquare;3381 +nbopomofo;310B +nbspace;00A0 +ncaron;0148 +ncedilla;0146 +ncircle;24DD +ncircumflexbelow;1E4B +ncommaaccent;0146 +ndotaccent;1E45 +ndotbelow;1E47 +nehiragana;306D +nekatakana;30CD +nekatakanahalfwidth;FF88 +newsheqelsign;20AA +nfsquare;338B +ngabengali;0999 +ngadeva;0919 +ngagujarati;0A99 +ngagurmukhi;0A19 +ngonguthai;0E07 +nhiragana;3093 +nhookleft;0272 +nhookretroflex;0273 +nieunacirclekorean;326F +nieunaparenkorean;320F +nieuncieuckorean;3135 +nieuncirclekorean;3261 +nieunhieuhkorean;3136 +nieunkorean;3134 +nieunpansioskorean;3168 +nieunparenkorean;3201 +nieunsioskorean;3167 +nieuntikeutkorean;3166 +nihiragana;306B +nikatakana;30CB +nikatakanahalfwidth;FF86 +nikhahitleftthai;F899 +nikhahitthai;0E4D +nine;0039 +ninearabic;0669 +ninebengali;09EF +ninecircle;2468 +ninecircleinversesansserif;2792 +ninedeva;096F +ninegujarati;0AEF +ninegurmukhi;0A6F +ninehackarabic;0669 +ninehangzhou;3029 +nineideographicparen;3228 +nineinferior;2089 +ninemonospace;FF19 +nineoldstyle;F739 +nineparen;247C +nineperiod;2490 +ninepersian;06F9 +nineroman;2178 +ninesuperior;2079 +nineteencircle;2472 +nineteenparen;2486 +nineteenperiod;249A +ninethai;0E59 +nj;01CC +njecyrillic;045A +nkatakana;30F3 +nkatakanahalfwidth;FF9D +nlegrightlong;019E +nlinebelow;1E49 +nmonospace;FF4E +nmsquare;339A +nnabengali;09A3 +nnadeva;0923 +nnagujarati;0AA3 +nnagurmukhi;0A23 +nnnadeva;0929 +nohiragana;306E +nokatakana;30CE +nokatakanahalfwidth;FF89 +nonbreakingspace;00A0 +nonenthai;0E13 +nonuthai;0E19 +noonarabic;0646 +noonfinalarabic;FEE6 +noonghunnaarabic;06BA +noonghunnafinalarabic;FB9F +noonhehinitialarabic;FEE7 FEEC +nooninitialarabic;FEE7 +noonjeeminitialarabic;FCD2 +noonjeemisolatedarabic;FC4B +noonmedialarabic;FEE8 +noonmeeminitialarabic;FCD5 +noonmeemisolatedarabic;FC4E +noonnoonfinalarabic;FC8D +notcontains;220C +notelement;2209 +notelementof;2209 +notequal;2260 +notgreater;226F +notgreaternorequal;2271 +notgreaternorless;2279 +notidentical;2262 +notless;226E +notlessnorequal;2270 +notparallel;2226 +notprecedes;2280 +notsubset;2284 +notsucceeds;2281 +notsuperset;2285 +nowarmenian;0576 +nparen;24A9 +nssquare;33B1 +nsuperior;207F +ntilde;00F1 +nu;03BD +nuhiragana;306C +nukatakana;30CC +nukatakanahalfwidth;FF87 +nuktabengali;09BC +nuktadeva;093C +nuktagujarati;0ABC +nuktagurmukhi;0A3C +numbersign;0023 +numbersignmonospace;FF03 +numbersignsmall;FE5F +numeralsigngreek;0374 +numeralsignlowergreek;0375 +numero;2116 +nun;05E0 +nundagesh;FB40 +nundageshhebrew;FB40 +nunhebrew;05E0 +nvsquare;33B5 +nwsquare;33BB +nyabengali;099E +nyadeva;091E +nyagujarati;0A9E +nyagurmukhi;0A1E +o;006F +oacute;00F3 +oangthai;0E2D +obarred;0275 +obarredcyrillic;04E9 +obarreddieresiscyrillic;04EB +obengali;0993 +obopomofo;311B +obreve;014F +ocandradeva;0911 +ocandragujarati;0A91 +ocandravowelsigndeva;0949 +ocandravowelsigngujarati;0AC9 +ocaron;01D2 +ocircle;24DE +ocircumflex;00F4 +ocircumflexacute;1ED1 +ocircumflexdotbelow;1ED9 +ocircumflexgrave;1ED3 +ocircumflexhookabove;1ED5 +ocircumflextilde;1ED7 +ocyrillic;043E +odblacute;0151 +odblgrave;020D +odeva;0913 +odieresis;00F6 +odieresiscyrillic;04E7 +odotbelow;1ECD +oe;0153 +oekorean;315A +ogonek;02DB +ogonekcmb;0328 +ograve;00F2 +ogujarati;0A93 +oharmenian;0585 +ohiragana;304A +ohookabove;1ECF +ohorn;01A1 +ohornacute;1EDB +ohorndotbelow;1EE3 +ohorngrave;1EDD +ohornhookabove;1EDF +ohorntilde;1EE1 +ohungarumlaut;0151 +oi;01A3 +oinvertedbreve;020F +okatakana;30AA +okatakanahalfwidth;FF75 +okorean;3157 +olehebrew;05AB +omacron;014D +omacronacute;1E53 +omacrongrave;1E51 +omdeva;0950 +omega;03C9 +omega1;03D6 +omegacyrillic;0461 +omegalatinclosed;0277 +omegaroundcyrillic;047B +omegatitlocyrillic;047D +omegatonos;03CE +omgujarati;0AD0 +omicron;03BF +omicrontonos;03CC +omonospace;FF4F +one;0031 +onearabic;0661 +onebengali;09E7 +onecircle;2460 +onecircleinversesansserif;278A +onedeva;0967 +onedotenleader;2024 +oneeighth;215B +onefitted;F6DC +onegujarati;0AE7 +onegurmukhi;0A67 +onehackarabic;0661 +onehalf;00BD +onehangzhou;3021 +oneideographicparen;3220 +oneinferior;2081 +onemonospace;FF11 +onenumeratorbengali;09F4 +oneoldstyle;F731 +oneparen;2474 +oneperiod;2488 +onepersian;06F1 +onequarter;00BC +oneroman;2170 +onesuperior;00B9 +onethai;0E51 +onethird;2153 +oogonek;01EB +oogonekmacron;01ED +oogurmukhi;0A13 +oomatragurmukhi;0A4B +oopen;0254 +oparen;24AA +openbullet;25E6 +option;2325 +ordfeminine;00AA +ordmasculine;00BA +orthogonal;221F +oshortdeva;0912 +oshortvowelsigndeva;094A +oslash;00F8 +oslashacute;01FF +osmallhiragana;3049 +osmallkatakana;30A9 +osmallkatakanahalfwidth;FF6B +ostrokeacute;01FF +osuperior;F6F0 +otcyrillic;047F +otilde;00F5 +otildeacute;1E4D +otildedieresis;1E4F +oubopomofo;3121 +overline;203E +overlinecenterline;FE4A +overlinecmb;0305 +overlinedashed;FE49 +overlinedblwavy;FE4C +overlinewavy;FE4B +overscore;00AF +ovowelsignbengali;09CB +ovowelsigndeva;094B +ovowelsigngujarati;0ACB +p;0070 +paampssquare;3380 +paasentosquare;332B +pabengali;09AA +pacute;1E55 +padeva;092A +pagedown;21DF +pageup;21DE +pagujarati;0AAA +pagurmukhi;0A2A +pahiragana;3071 +paiyannoithai;0E2F +pakatakana;30D1 +palatalizationcyrilliccmb;0484 +palochkacyrillic;04C0 +pansioskorean;317F +paragraph;00B6 +parallel;2225 +parenleft;0028 +parenleftaltonearabic;FD3E +parenleftbt;F8ED +parenleftex;F8EC +parenleftinferior;208D +parenleftmonospace;FF08 +parenleftsmall;FE59 +parenleftsuperior;207D +parenlefttp;F8EB +parenleftvertical;FE35 +parenright;0029 +parenrightaltonearabic;FD3F +parenrightbt;F8F8 +parenrightex;F8F7 +parenrightinferior;208E +parenrightmonospace;FF09 +parenrightsmall;FE5A +parenrightsuperior;207E +parenrighttp;F8F6 +parenrightvertical;FE36 +partialdiff;2202 +paseqhebrew;05C0 +pashtahebrew;0599 +pasquare;33A9 +patah;05B7 +patah11;05B7 +patah1d;05B7 +patah2a;05B7 +patahhebrew;05B7 +patahnarrowhebrew;05B7 +patahquarterhebrew;05B7 +patahwidehebrew;05B7 +pazerhebrew;05A1 +pbopomofo;3106 +pcircle;24DF +pdotaccent;1E57 +pe;05E4 +pecyrillic;043F +pedagesh;FB44 +pedageshhebrew;FB44 +peezisquare;333B +pefinaldageshhebrew;FB43 +peharabic;067E +peharmenian;057A +pehebrew;05E4 +pehfinalarabic;FB57 +pehinitialarabic;FB58 +pehiragana;307A +pehmedialarabic;FB59 +pekatakana;30DA +pemiddlehookcyrillic;04A7 +perafehebrew;FB4E +percent;0025 +percentarabic;066A +percentmonospace;FF05 +percentsmall;FE6A +period;002E +periodarmenian;0589 +periodcentered;00B7 +periodhalfwidth;FF61 +periodinferior;F6E7 +periodmonospace;FF0E +periodsmall;FE52 +periodsuperior;F6E8 +perispomenigreekcmb;0342 +perpendicular;22A5 +perthousand;2030 +peseta;20A7 +pfsquare;338A +phabengali;09AB +phadeva;092B +phagujarati;0AAB +phagurmukhi;0A2B +phi;03C6 +phi1;03D5 +phieuphacirclekorean;327A +phieuphaparenkorean;321A +phieuphcirclekorean;326C +phieuphkorean;314D +phieuphparenkorean;320C +philatin;0278 +phinthuthai;0E3A +phisymbolgreek;03D5 +phook;01A5 +phophanthai;0E1E +phophungthai;0E1C +phosamphaothai;0E20 +pi;03C0 +pieupacirclekorean;3273 +pieupaparenkorean;3213 +pieupcieuckorean;3176 +pieupcirclekorean;3265 +pieupkiyeokkorean;3172 +pieupkorean;3142 +pieupparenkorean;3205 +pieupsioskiyeokkorean;3174 +pieupsioskorean;3144 +pieupsiostikeutkorean;3175 +pieupthieuthkorean;3177 +pieuptikeutkorean;3173 +pihiragana;3074 +pikatakana;30D4 +pisymbolgreek;03D6 +piwrarmenian;0583 +plus;002B +plusbelowcmb;031F +pluscircle;2295 +plusminus;00B1 +plusmod;02D6 +plusmonospace;FF0B +plussmall;FE62 +plussuperior;207A +pmonospace;FF50 +pmsquare;33D8 +pohiragana;307D +pointingindexdownwhite;261F +pointingindexleftwhite;261C +pointingindexrightwhite;261E +pointingindexupwhite;261D +pokatakana;30DD +poplathai;0E1B +postalmark;3012 +postalmarkface;3020 +pparen;24AB +precedes;227A +prescription;211E +primemod;02B9 +primereversed;2035 +product;220F +projective;2305 +prolongedkana;30FC +propellor;2318 +propersubset;2282 +propersuperset;2283 +proportion;2237 +proportional;221D +psi;03C8 +psicyrillic;0471 +psilipneumatacyrilliccmb;0486 +pssquare;33B0 +puhiragana;3077 +pukatakana;30D7 +pvsquare;33B4 +pwsquare;33BA +q;0071 +qadeva;0958 +qadmahebrew;05A8 +qafarabic;0642 +qaffinalarabic;FED6 +qafinitialarabic;FED7 +qafmedialarabic;FED8 +qamats;05B8 +qamats10;05B8 +qamats1a;05B8 +qamats1c;05B8 +qamats27;05B8 +qamats29;05B8 +qamats33;05B8 +qamatsde;05B8 +qamatshebrew;05B8 +qamatsnarrowhebrew;05B8 +qamatsqatanhebrew;05B8 +qamatsqatannarrowhebrew;05B8 +qamatsqatanquarterhebrew;05B8 +qamatsqatanwidehebrew;05B8 +qamatsquarterhebrew;05B8 +qamatswidehebrew;05B8 +qarneyparahebrew;059F +qbopomofo;3111 +qcircle;24E0 +qhook;02A0 +qmonospace;FF51 +qof;05E7 +qofdagesh;FB47 +qofdageshhebrew;FB47 +qofhatafpatah;05E7 05B2 +qofhatafpatahhebrew;05E7 05B2 +qofhatafsegol;05E7 05B1 +qofhatafsegolhebrew;05E7 05B1 +qofhebrew;05E7 +qofhiriq;05E7 05B4 +qofhiriqhebrew;05E7 05B4 +qofholam;05E7 05B9 +qofholamhebrew;05E7 05B9 +qofpatah;05E7 05B7 +qofpatahhebrew;05E7 05B7 +qofqamats;05E7 05B8 +qofqamatshebrew;05E7 05B8 +qofqubuts;05E7 05BB +qofqubutshebrew;05E7 05BB +qofsegol;05E7 05B6 +qofsegolhebrew;05E7 05B6 +qofsheva;05E7 05B0 +qofshevahebrew;05E7 05B0 +qoftsere;05E7 05B5 +qoftserehebrew;05E7 05B5 +qparen;24AC +quarternote;2669 +qubuts;05BB +qubuts18;05BB +qubuts25;05BB +qubuts31;05BB +qubutshebrew;05BB +qubutsnarrowhebrew;05BB +qubutsquarterhebrew;05BB +qubutswidehebrew;05BB +question;003F +questionarabic;061F +questionarmenian;055E +questiondown;00BF +questiondownsmall;F7BF +questiongreek;037E +questionmonospace;FF1F +questionsmall;F73F +quotedbl;0022 +quotedblbase;201E +quotedblleft;201C +quotedblmonospace;FF02 +quotedblprime;301E +quotedblprimereversed;301D +quotedblright;201D +quoteleft;2018 +quoteleftreversed;201B +quotereversed;201B +quoteright;2019 +quoterightn;0149 +quotesinglbase;201A +quotesingle;0027 +quotesinglemonospace;FF07 +r;0072 +raarmenian;057C +rabengali;09B0 +racute;0155 +radeva;0930 +radical;221A +radicalex;F8E5 +radoverssquare;33AE +radoverssquaredsquare;33AF +radsquare;33AD +rafe;05BF +rafehebrew;05BF +ragujarati;0AB0 +ragurmukhi;0A30 +rahiragana;3089 +rakatakana;30E9 +rakatakanahalfwidth;FF97 +ralowerdiagonalbengali;09F1 +ramiddlediagonalbengali;09F0 +ramshorn;0264 +ratio;2236 +rbopomofo;3116 +rcaron;0159 +rcedilla;0157 +rcircle;24E1 +rcommaaccent;0157 +rdblgrave;0211 +rdotaccent;1E59 +rdotbelow;1E5B +rdotbelowmacron;1E5D +referencemark;203B +reflexsubset;2286 +reflexsuperset;2287 +registered;00AE +registersans;F8E8 +registerserif;F6DA +reharabic;0631 +reharmenian;0580 +rehfinalarabic;FEAE +rehiragana;308C +rehyehaleflamarabic;0631 FEF3 FE8E 0644 +rekatakana;30EC +rekatakanahalfwidth;FF9A +resh;05E8 +reshdageshhebrew;FB48 +reshhatafpatah;05E8 05B2 +reshhatafpatahhebrew;05E8 05B2 +reshhatafsegol;05E8 05B1 +reshhatafsegolhebrew;05E8 05B1 +reshhebrew;05E8 +reshhiriq;05E8 05B4 +reshhiriqhebrew;05E8 05B4 +reshholam;05E8 05B9 +reshholamhebrew;05E8 05B9 +reshpatah;05E8 05B7 +reshpatahhebrew;05E8 05B7 +reshqamats;05E8 05B8 +reshqamatshebrew;05E8 05B8 +reshqubuts;05E8 05BB +reshqubutshebrew;05E8 05BB +reshsegol;05E8 05B6 +reshsegolhebrew;05E8 05B6 +reshsheva;05E8 05B0 +reshshevahebrew;05E8 05B0 +reshtsere;05E8 05B5 +reshtserehebrew;05E8 05B5 +reversedtilde;223D +reviahebrew;0597 +reviamugrashhebrew;0597 +revlogicalnot;2310 +rfishhook;027E +rfishhookreversed;027F +rhabengali;09DD +rhadeva;095D +rho;03C1 +rhook;027D +rhookturned;027B +rhookturnedsuperior;02B5 +rhosymbolgreek;03F1 +rhotichookmod;02DE +rieulacirclekorean;3271 +rieulaparenkorean;3211 +rieulcirclekorean;3263 +rieulhieuhkorean;3140 +rieulkiyeokkorean;313A +rieulkiyeoksioskorean;3169 +rieulkorean;3139 +rieulmieumkorean;313B +rieulpansioskorean;316C +rieulparenkorean;3203 +rieulphieuphkorean;313F +rieulpieupkorean;313C +rieulpieupsioskorean;316B +rieulsioskorean;313D +rieulthieuthkorean;313E +rieultikeutkorean;316A +rieulyeorinhieuhkorean;316D +rightangle;221F +righttackbelowcmb;0319 +righttriangle;22BF +rihiragana;308A +rikatakana;30EA +rikatakanahalfwidth;FF98 +ring;02DA +ringbelowcmb;0325 +ringcmb;030A +ringhalfleft;02BF +ringhalfleftarmenian;0559 +ringhalfleftbelowcmb;031C +ringhalfleftcentered;02D3 +ringhalfright;02BE +ringhalfrightbelowcmb;0339 +ringhalfrightcentered;02D2 +rinvertedbreve;0213 +rittorusquare;3351 +rlinebelow;1E5F +rlongleg;027C +rlonglegturned;027A +rmonospace;FF52 +rohiragana;308D +rokatakana;30ED +rokatakanahalfwidth;FF9B +roruathai;0E23 +rparen;24AD +rrabengali;09DC +rradeva;0931 +rragurmukhi;0A5C +rreharabic;0691 +rrehfinalarabic;FB8D +rrvocalicbengali;09E0 +rrvocalicdeva;0960 +rrvocalicgujarati;0AE0 +rrvocalicvowelsignbengali;09C4 +rrvocalicvowelsigndeva;0944 +rrvocalicvowelsigngujarati;0AC4 +rsuperior;F6F1 +rtblock;2590 +rturned;0279 +rturnedsuperior;02B4 +ruhiragana;308B +rukatakana;30EB +rukatakanahalfwidth;FF99 +rupeemarkbengali;09F2 +rupeesignbengali;09F3 +rupiah;F6DD +ruthai;0E24 +rvocalicbengali;098B +rvocalicdeva;090B +rvocalicgujarati;0A8B +rvocalicvowelsignbengali;09C3 +rvocalicvowelsigndeva;0943 +rvocalicvowelsigngujarati;0AC3 +s;0073 +sabengali;09B8 +sacute;015B +sacutedotaccent;1E65 +sadarabic;0635 +sadeva;0938 +sadfinalarabic;FEBA +sadinitialarabic;FEBB +sadmedialarabic;FEBC +sagujarati;0AB8 +sagurmukhi;0A38 +sahiragana;3055 +sakatakana;30B5 +sakatakanahalfwidth;FF7B +sallallahoualayhewasallamarabic;FDFA +samekh;05E1 +samekhdagesh;FB41 +samekhdageshhebrew;FB41 +samekhhebrew;05E1 +saraaathai;0E32 +saraaethai;0E41 +saraaimaimalaithai;0E44 +saraaimaimuanthai;0E43 +saraamthai;0E33 +saraathai;0E30 +saraethai;0E40 +saraiileftthai;F886 +saraiithai;0E35 +saraileftthai;F885 +saraithai;0E34 +saraothai;0E42 +saraueeleftthai;F888 +saraueethai;0E37 +saraueleftthai;F887 +sarauethai;0E36 +sarauthai;0E38 +sarauuthai;0E39 +sbopomofo;3119 +scaron;0161 +scarondotaccent;1E67 +scedilla;015F +schwa;0259 +schwacyrillic;04D9 +schwadieresiscyrillic;04DB +schwahook;025A +scircle;24E2 +scircumflex;015D +scommaaccent;0219 +sdotaccent;1E61 +sdotbelow;1E63 +sdotbelowdotaccent;1E69 +seagullbelowcmb;033C +second;2033 +secondtonechinese;02CA +section;00A7 +seenarabic;0633 +seenfinalarabic;FEB2 +seeninitialarabic;FEB3 +seenmedialarabic;FEB4 +segol;05B6 +segol13;05B6 +segol1f;05B6 +segol2c;05B6 +segolhebrew;05B6 +segolnarrowhebrew;05B6 +segolquarterhebrew;05B6 +segoltahebrew;0592 +segolwidehebrew;05B6 +seharmenian;057D +sehiragana;305B +sekatakana;30BB +sekatakanahalfwidth;FF7E +semicolon;003B +semicolonarabic;061B +semicolonmonospace;FF1B +semicolonsmall;FE54 +semivoicedmarkkana;309C +semivoicedmarkkanahalfwidth;FF9F +sentisquare;3322 +sentosquare;3323 +seven;0037 +sevenarabic;0667 +sevenbengali;09ED +sevencircle;2466 +sevencircleinversesansserif;2790 +sevendeva;096D +seveneighths;215E +sevengujarati;0AED +sevengurmukhi;0A6D +sevenhackarabic;0667 +sevenhangzhou;3027 +sevenideographicparen;3226 +seveninferior;2087 +sevenmonospace;FF17 +sevenoldstyle;F737 +sevenparen;247A +sevenperiod;248E +sevenpersian;06F7 +sevenroman;2176 +sevensuperior;2077 +seventeencircle;2470 +seventeenparen;2484 +seventeenperiod;2498 +seventhai;0E57 +sfthyphen;00AD +shaarmenian;0577 +shabengali;09B6 +shacyrillic;0448 +shaddaarabic;0651 +shaddadammaarabic;FC61 +shaddadammatanarabic;FC5E +shaddafathaarabic;FC60 +shaddafathatanarabic;0651 064B +shaddakasraarabic;FC62 +shaddakasratanarabic;FC5F +shade;2592 +shadedark;2593 +shadelight;2591 +shademedium;2592 +shadeva;0936 +shagujarati;0AB6 +shagurmukhi;0A36 +shalshelethebrew;0593 +shbopomofo;3115 +shchacyrillic;0449 +sheenarabic;0634 +sheenfinalarabic;FEB6 +sheeninitialarabic;FEB7 +sheenmedialarabic;FEB8 +sheicoptic;03E3 +sheqel;20AA +sheqelhebrew;20AA +sheva;05B0 +sheva115;05B0 +sheva15;05B0 +sheva22;05B0 +sheva2e;05B0 +shevahebrew;05B0 +shevanarrowhebrew;05B0 +shevaquarterhebrew;05B0 +shevawidehebrew;05B0 +shhacyrillic;04BB +shimacoptic;03ED +shin;05E9 +shindagesh;FB49 +shindageshhebrew;FB49 +shindageshshindot;FB2C +shindageshshindothebrew;FB2C +shindageshsindot;FB2D +shindageshsindothebrew;FB2D +shindothebrew;05C1 +shinhebrew;05E9 +shinshindot;FB2A +shinshindothebrew;FB2A +shinsindot;FB2B +shinsindothebrew;FB2B +shook;0282 +sigma;03C3 +sigma1;03C2 +sigmafinal;03C2 +sigmalunatesymbolgreek;03F2 +sihiragana;3057 +sikatakana;30B7 +sikatakanahalfwidth;FF7C +siluqhebrew;05BD +siluqlefthebrew;05BD +similar;223C +sindothebrew;05C2 +siosacirclekorean;3274 +siosaparenkorean;3214 +sioscieuckorean;317E +sioscirclekorean;3266 +sioskiyeokkorean;317A +sioskorean;3145 +siosnieunkorean;317B +siosparenkorean;3206 +siospieupkorean;317D +siostikeutkorean;317C +six;0036 +sixarabic;0666 +sixbengali;09EC +sixcircle;2465 +sixcircleinversesansserif;278F +sixdeva;096C +sixgujarati;0AEC +sixgurmukhi;0A6C +sixhackarabic;0666 +sixhangzhou;3026 +sixideographicparen;3225 +sixinferior;2086 +sixmonospace;FF16 +sixoldstyle;F736 +sixparen;2479 +sixperiod;248D +sixpersian;06F6 +sixroman;2175 +sixsuperior;2076 +sixteencircle;246F +sixteencurrencydenominatorbengali;09F9 +sixteenparen;2483 +sixteenperiod;2497 +sixthai;0E56 +slash;002F +slashmonospace;FF0F +slong;017F +slongdotaccent;1E9B +smileface;263A +smonospace;FF53 +sofpasuqhebrew;05C3 +softhyphen;00AD +softsigncyrillic;044C +sohiragana;305D +sokatakana;30BD +sokatakanahalfwidth;FF7F +soliduslongoverlaycmb;0338 +solidusshortoverlaycmb;0337 +sorusithai;0E29 +sosalathai;0E28 +sosothai;0E0B +sosuathai;0E2A +space;0020 +spacehackarabic;0020 +spade;2660 +spadesuitblack;2660 +spadesuitwhite;2664 +sparen;24AE +squarebelowcmb;033B +squarecc;33C4 +squarecm;339D +squarediagonalcrosshatchfill;25A9 +squarehorizontalfill;25A4 +squarekg;338F +squarekm;339E +squarekmcapital;33CE +squareln;33D1 +squarelog;33D2 +squaremg;338E +squaremil;33D5 +squaremm;339C +squaremsquared;33A1 +squareorthogonalcrosshatchfill;25A6 +squareupperlefttolowerrightfill;25A7 +squareupperrighttolowerleftfill;25A8 +squareverticalfill;25A5 +squarewhitewithsmallblack;25A3 +srsquare;33DB +ssabengali;09B7 +ssadeva;0937 +ssagujarati;0AB7 +ssangcieuckorean;3149 +ssanghieuhkorean;3185 +ssangieungkorean;3180 +ssangkiyeokkorean;3132 +ssangnieunkorean;3165 +ssangpieupkorean;3143 +ssangsioskorean;3146 +ssangtikeutkorean;3138 +ssuperior;F6F2 +sterling;00A3 +sterlingmonospace;FFE1 +strokelongoverlaycmb;0336 +strokeshortoverlaycmb;0335 +subset;2282 +subsetnotequal;228A +subsetorequal;2286 +succeeds;227B +suchthat;220B +suhiragana;3059 +sukatakana;30B9 +sukatakanahalfwidth;FF7D +sukunarabic;0652 +summation;2211 +sun;263C +superset;2283 +supersetnotequal;228B +supersetorequal;2287 +svsquare;33DC +syouwaerasquare;337C +t;0074 +tabengali;09A4 +tackdown;22A4 +tackleft;22A3 +tadeva;0924 +tagujarati;0AA4 +tagurmukhi;0A24 +taharabic;0637 +tahfinalarabic;FEC2 +tahinitialarabic;FEC3 +tahiragana;305F +tahmedialarabic;FEC4 +taisyouerasquare;337D +takatakana;30BF +takatakanahalfwidth;FF80 +tatweelarabic;0640 +tau;03C4 +tav;05EA +tavdages;FB4A +tavdagesh;FB4A +tavdageshhebrew;FB4A +tavhebrew;05EA +tbar;0167 +tbopomofo;310A +tcaron;0165 +tccurl;02A8 +tcedilla;0163 +tcheharabic;0686 +tchehfinalarabic;FB7B +tchehinitialarabic;FB7C +tchehmedialarabic;FB7D +tchehmeeminitialarabic;FB7C FEE4 +tcircle;24E3 +tcircumflexbelow;1E71 +tcommaaccent;0163 +tdieresis;1E97 +tdotaccent;1E6B +tdotbelow;1E6D +tecyrillic;0442 +tedescendercyrillic;04AD +teharabic;062A +tehfinalarabic;FE96 +tehhahinitialarabic;FCA2 +tehhahisolatedarabic;FC0C +tehinitialarabic;FE97 +tehiragana;3066 +tehjeeminitialarabic;FCA1 +tehjeemisolatedarabic;FC0B +tehmarbutaarabic;0629 +tehmarbutafinalarabic;FE94 +tehmedialarabic;FE98 +tehmeeminitialarabic;FCA4 +tehmeemisolatedarabic;FC0E +tehnoonfinalarabic;FC73 +tekatakana;30C6 +tekatakanahalfwidth;FF83 +telephone;2121 +telephoneblack;260E +telishagedolahebrew;05A0 +telishaqetanahebrew;05A9 +tencircle;2469 +tenideographicparen;3229 +tenparen;247D +tenperiod;2491 +tenroman;2179 +tesh;02A7 +tet;05D8 +tetdagesh;FB38 +tetdageshhebrew;FB38 +tethebrew;05D8 +tetsecyrillic;04B5 +tevirhebrew;059B +tevirlefthebrew;059B +thabengali;09A5 +thadeva;0925 +thagujarati;0AA5 +thagurmukhi;0A25 +thalarabic;0630 +thalfinalarabic;FEAC +thanthakhatlowleftthai;F898 +thanthakhatlowrightthai;F897 +thanthakhatthai;0E4C +thanthakhatupperleftthai;F896 +theharabic;062B +thehfinalarabic;FE9A +thehinitialarabic;FE9B +thehmedialarabic;FE9C +thereexists;2203 +therefore;2234 +theta;03B8 +theta1;03D1 +thetasymbolgreek;03D1 +thieuthacirclekorean;3279 +thieuthaparenkorean;3219 +thieuthcirclekorean;326B +thieuthkorean;314C +thieuthparenkorean;320B +thirteencircle;246C +thirteenparen;2480 +thirteenperiod;2494 +thonangmonthothai;0E11 +thook;01AD +thophuthaothai;0E12 +thorn;00FE +thothahanthai;0E17 +thothanthai;0E10 +thothongthai;0E18 +thothungthai;0E16 +thousandcyrillic;0482 +thousandsseparatorarabic;066C +thousandsseparatorpersian;066C +three;0033 +threearabic;0663 +threebengali;09E9 +threecircle;2462 +threecircleinversesansserif;278C +threedeva;0969 +threeeighths;215C +threegujarati;0AE9 +threegurmukhi;0A69 +threehackarabic;0663 +threehangzhou;3023 +threeideographicparen;3222 +threeinferior;2083 +threemonospace;FF13 +threenumeratorbengali;09F6 +threeoldstyle;F733 +threeparen;2476 +threeperiod;248A +threepersian;06F3 +threequarters;00BE +threequartersemdash;F6DE +threeroman;2172 +threesuperior;00B3 +threethai;0E53 +thzsquare;3394 +tihiragana;3061 +tikatakana;30C1 +tikatakanahalfwidth;FF81 +tikeutacirclekorean;3270 +tikeutaparenkorean;3210 +tikeutcirclekorean;3262 +tikeutkorean;3137 +tikeutparenkorean;3202 +tilde;02DC +tildebelowcmb;0330 +tildecmb;0303 +tildecomb;0303 +tildedoublecmb;0360 +tildeoperator;223C +tildeoverlaycmb;0334 +tildeverticalcmb;033E +timescircle;2297 +tipehahebrew;0596 +tipehalefthebrew;0596 +tippigurmukhi;0A70 +titlocyrilliccmb;0483 +tiwnarmenian;057F +tlinebelow;1E6F +tmonospace;FF54 +toarmenian;0569 +tohiragana;3068 +tokatakana;30C8 +tokatakanahalfwidth;FF84 +tonebarextrahighmod;02E5 +tonebarextralowmod;02E9 +tonebarhighmod;02E6 +tonebarlowmod;02E8 +tonebarmidmod;02E7 +tonefive;01BD +tonesix;0185 +tonetwo;01A8 +tonos;0384 +tonsquare;3327 +topatakthai;0E0F +tortoiseshellbracketleft;3014 +tortoiseshellbracketleftsmall;FE5D +tortoiseshellbracketleftvertical;FE39 +tortoiseshellbracketright;3015 +tortoiseshellbracketrightsmall;FE5E +tortoiseshellbracketrightvertical;FE3A +totaothai;0E15 +tpalatalhook;01AB +tparen;24AF +trademark;2122 +trademarksans;F8EA +trademarkserif;F6DB +tretroflexhook;0288 +triagdn;25BC +triaglf;25C4 +triagrt;25BA +triagup;25B2 +ts;02A6 +tsadi;05E6 +tsadidagesh;FB46 +tsadidageshhebrew;FB46 +tsadihebrew;05E6 +tsecyrillic;0446 +tsere;05B5 +tsere12;05B5 +tsere1e;05B5 +tsere2b;05B5 +tserehebrew;05B5 +tserenarrowhebrew;05B5 +tserequarterhebrew;05B5 +tserewidehebrew;05B5 +tshecyrillic;045B +tsuperior;F6F3 +ttabengali;099F +ttadeva;091F +ttagujarati;0A9F +ttagurmukhi;0A1F +tteharabic;0679 +ttehfinalarabic;FB67 +ttehinitialarabic;FB68 +ttehmedialarabic;FB69 +tthabengali;09A0 +tthadeva;0920 +tthagujarati;0AA0 +tthagurmukhi;0A20 +tturned;0287 +tuhiragana;3064 +tukatakana;30C4 +tukatakanahalfwidth;FF82 +tusmallhiragana;3063 +tusmallkatakana;30C3 +tusmallkatakanahalfwidth;FF6F +twelvecircle;246B +twelveparen;247F +twelveperiod;2493 +twelveroman;217B +twentycircle;2473 +twentyhangzhou;5344 +twentyparen;2487 +twentyperiod;249B +two;0032 +twoarabic;0662 +twobengali;09E8 +twocircle;2461 +twocircleinversesansserif;278B +twodeva;0968 +twodotenleader;2025 +twodotleader;2025 +twodotleadervertical;FE30 +twogujarati;0AE8 +twogurmukhi;0A68 +twohackarabic;0662 +twohangzhou;3022 +twoideographicparen;3221 +twoinferior;2082 +twomonospace;FF12 +twonumeratorbengali;09F5 +twooldstyle;F732 +twoparen;2475 +twoperiod;2489 +twopersian;06F2 +tworoman;2171 +twostroke;01BB +twosuperior;00B2 +twothai;0E52 +twothirds;2154 +u;0075 +uacute;00FA +ubar;0289 +ubengali;0989 +ubopomofo;3128 +ubreve;016D +ucaron;01D4 +ucircle;24E4 +ucircumflex;00FB +ucircumflexbelow;1E77 +ucyrillic;0443 +udattadeva;0951 +udblacute;0171 +udblgrave;0215 +udeva;0909 +udieresis;00FC +udieresisacute;01D8 +udieresisbelow;1E73 +udieresiscaron;01DA +udieresiscyrillic;04F1 +udieresisgrave;01DC +udieresismacron;01D6 +udotbelow;1EE5 +ugrave;00F9 +ugujarati;0A89 +ugurmukhi;0A09 +uhiragana;3046 +uhookabove;1EE7 +uhorn;01B0 +uhornacute;1EE9 +uhorndotbelow;1EF1 +uhorngrave;1EEB +uhornhookabove;1EED +uhorntilde;1EEF +uhungarumlaut;0171 +uhungarumlautcyrillic;04F3 +uinvertedbreve;0217 +ukatakana;30A6 +ukatakanahalfwidth;FF73 +ukcyrillic;0479 +ukorean;315C +umacron;016B +umacroncyrillic;04EF +umacrondieresis;1E7B +umatragurmukhi;0A41 +umonospace;FF55 +underscore;005F +underscoredbl;2017 +underscoremonospace;FF3F +underscorevertical;FE33 +underscorewavy;FE4F +union;222A +universal;2200 +uogonek;0173 +uparen;24B0 +upblock;2580 +upperdothebrew;05C4 +upsilon;03C5 +upsilondieresis;03CB +upsilondieresistonos;03B0 +upsilonlatin;028A +upsilontonos;03CD +uptackbelowcmb;031D +uptackmod;02D4 +uragurmukhi;0A73 +uring;016F +ushortcyrillic;045E +usmallhiragana;3045 +usmallkatakana;30A5 +usmallkatakanahalfwidth;FF69 +ustraightcyrillic;04AF +ustraightstrokecyrillic;04B1 +utilde;0169 +utildeacute;1E79 +utildebelow;1E75 +uubengali;098A +uudeva;090A +uugujarati;0A8A +uugurmukhi;0A0A +uumatragurmukhi;0A42 +uuvowelsignbengali;09C2 +uuvowelsigndeva;0942 +uuvowelsigngujarati;0AC2 +uvowelsignbengali;09C1 +uvowelsigndeva;0941 +uvowelsigngujarati;0AC1 +v;0076 +vadeva;0935 +vagujarati;0AB5 +vagurmukhi;0A35 +vakatakana;30F7 +vav;05D5 +vavdagesh;FB35 +vavdagesh65;FB35 +vavdageshhebrew;FB35 +vavhebrew;05D5 +vavholam;FB4B +vavholamhebrew;FB4B +vavvavhebrew;05F0 +vavyodhebrew;05F1 +vcircle;24E5 +vdotbelow;1E7F +vecyrillic;0432 +veharabic;06A4 +vehfinalarabic;FB6B +vehinitialarabic;FB6C +vehmedialarabic;FB6D +vekatakana;30F9 +venus;2640 +verticalbar;007C +verticallineabovecmb;030D +verticallinebelowcmb;0329 +verticallinelowmod;02CC +verticallinemod;02C8 +vewarmenian;057E +vhook;028B +vikatakana;30F8 +viramabengali;09CD +viramadeva;094D +viramagujarati;0ACD +visargabengali;0983 +visargadeva;0903 +visargagujarati;0A83 +vmonospace;FF56 +voarmenian;0578 +voicediterationhiragana;309E +voicediterationkatakana;30FE +voicedmarkkana;309B +voicedmarkkanahalfwidth;FF9E +vokatakana;30FA +vparen;24B1 +vtilde;1E7D +vturned;028C +vuhiragana;3094 +vukatakana;30F4 +w;0077 +wacute;1E83 +waekorean;3159 +wahiragana;308F +wakatakana;30EF +wakatakanahalfwidth;FF9C +wakorean;3158 +wasmallhiragana;308E +wasmallkatakana;30EE +wattosquare;3357 +wavedash;301C +wavyunderscorevertical;FE34 +wawarabic;0648 +wawfinalarabic;FEEE +wawhamzaabovearabic;0624 +wawhamzaabovefinalarabic;FE86 +wbsquare;33DD +wcircle;24E6 +wcircumflex;0175 +wdieresis;1E85 +wdotaccent;1E87 +wdotbelow;1E89 +wehiragana;3091 +weierstrass;2118 +wekatakana;30F1 +wekorean;315E +weokorean;315D +wgrave;1E81 +whitebullet;25E6 +whitecircle;25CB +whitecircleinverse;25D9 +whitecornerbracketleft;300E +whitecornerbracketleftvertical;FE43 +whitecornerbracketright;300F +whitecornerbracketrightvertical;FE44 +whitediamond;25C7 +whitediamondcontainingblacksmalldiamond;25C8 +whitedownpointingsmalltriangle;25BF +whitedownpointingtriangle;25BD +whiteleftpointingsmalltriangle;25C3 +whiteleftpointingtriangle;25C1 +whitelenticularbracketleft;3016 +whitelenticularbracketright;3017 +whiterightpointingsmalltriangle;25B9 +whiterightpointingtriangle;25B7 +whitesmallsquare;25AB +whitesmilingface;263A +whitesquare;25A1 +whitestar;2606 +whitetelephone;260F +whitetortoiseshellbracketleft;3018 +whitetortoiseshellbracketright;3019 +whiteuppointingsmalltriangle;25B5 +whiteuppointingtriangle;25B3 +wihiragana;3090 +wikatakana;30F0 +wikorean;315F +wmonospace;FF57 +wohiragana;3092 +wokatakana;30F2 +wokatakanahalfwidth;FF66 +won;20A9 +wonmonospace;FFE6 +wowaenthai;0E27 +wparen;24B2 +wring;1E98 +wsuperior;02B7 +wturned;028D +wynn;01BF +x;0078 +xabovecmb;033D +xbopomofo;3112 +xcircle;24E7 +xdieresis;1E8D +xdotaccent;1E8B +xeharmenian;056D +xi;03BE +xmonospace;FF58 +xparen;24B3 +xsuperior;02E3 +y;0079 +yaadosquare;334E +yabengali;09AF +yacute;00FD +yadeva;092F +yaekorean;3152 +yagujarati;0AAF +yagurmukhi;0A2F +yahiragana;3084 +yakatakana;30E4 +yakatakanahalfwidth;FF94 +yakorean;3151 +yamakkanthai;0E4E +yasmallhiragana;3083 +yasmallkatakana;30E3 +yasmallkatakanahalfwidth;FF6C +yatcyrillic;0463 +ycircle;24E8 +ycircumflex;0177 +ydieresis;00FF +ydotaccent;1E8F +ydotbelow;1EF5 +yeharabic;064A +yehbarreearabic;06D2 +yehbarreefinalarabic;FBAF +yehfinalarabic;FEF2 +yehhamzaabovearabic;0626 +yehhamzaabovefinalarabic;FE8A +yehhamzaaboveinitialarabic;FE8B +yehhamzaabovemedialarabic;FE8C +yehinitialarabic;FEF3 +yehmedialarabic;FEF4 +yehmeeminitialarabic;FCDD +yehmeemisolatedarabic;FC58 +yehnoonfinalarabic;FC94 +yehthreedotsbelowarabic;06D1 +yekorean;3156 +yen;00A5 +yenmonospace;FFE5 +yeokorean;3155 +yeorinhieuhkorean;3186 +yerahbenyomohebrew;05AA +yerahbenyomolefthebrew;05AA +yericyrillic;044B +yerudieresiscyrillic;04F9 +yesieungkorean;3181 +yesieungpansioskorean;3183 +yesieungsioskorean;3182 +yetivhebrew;059A +ygrave;1EF3 +yhook;01B4 +yhookabove;1EF7 +yiarmenian;0575 +yicyrillic;0457 +yikorean;3162 +yinyang;262F +yiwnarmenian;0582 +ymonospace;FF59 +yod;05D9 +yoddagesh;FB39 +yoddageshhebrew;FB39 +yodhebrew;05D9 +yodyodhebrew;05F2 +yodyodpatahhebrew;FB1F +yohiragana;3088 +yoikorean;3189 +yokatakana;30E8 +yokatakanahalfwidth;FF96 +yokorean;315B +yosmallhiragana;3087 +yosmallkatakana;30E7 +yosmallkatakanahalfwidth;FF6E +yotgreek;03F3 +yoyaekorean;3188 +yoyakorean;3187 +yoyakthai;0E22 +yoyingthai;0E0D +yparen;24B4 +ypogegrammeni;037A +ypogegrammenigreekcmb;0345 +yr;01A6 +yring;1E99 +ysuperior;02B8 +ytilde;1EF9 +yturned;028E +yuhiragana;3086 +yuikorean;318C +yukatakana;30E6 +yukatakanahalfwidth;FF95 +yukorean;3160 +yusbigcyrillic;046B +yusbigiotifiedcyrillic;046D +yuslittlecyrillic;0467 +yuslittleiotifiedcyrillic;0469 +yusmallhiragana;3085 +yusmallkatakana;30E5 +yusmallkatakanahalfwidth;FF6D +yuyekorean;318B +yuyeokorean;318A +yyabengali;09DF +yyadeva;095F +z;007A +zaarmenian;0566 +zacute;017A +zadeva;095B +zagurmukhi;0A5B +zaharabic;0638 +zahfinalarabic;FEC6 +zahinitialarabic;FEC7 +zahiragana;3056 +zahmedialarabic;FEC8 +zainarabic;0632 +zainfinalarabic;FEB0 +zakatakana;30B6 +zaqefgadolhebrew;0595 +zaqefqatanhebrew;0594 +zarqahebrew;0598 +zayin;05D6 +zayindagesh;FB36 +zayindageshhebrew;FB36 +zayinhebrew;05D6 +zbopomofo;3117 +zcaron;017E +zcircle;24E9 +zcircumflex;1E91 +zcurl;0291 +zdot;017C +zdotaccent;017C +zdotbelow;1E93 +zecyrillic;0437 +zedescendercyrillic;0499 +zedieresiscyrillic;04DF +zehiragana;305C +zekatakana;30BC +zero;0030 +zeroarabic;0660 +zerobengali;09E6 +zerodeva;0966 +zerogujarati;0AE6 +zerogurmukhi;0A66 +zerohackarabic;0660 +zeroinferior;2080 +zeromonospace;FF10 +zerooldstyle;F730 +zeropersian;06F0 +zerosuperior;2070 +zerothai;0E50 +zerowidthjoiner;FEFF +zerowidthnonjoiner;200C +zerowidthspace;200B +zeta;03B6 +zhbopomofo;3113 +zhearmenian;056A +zhebrevecyrillic;04C2 +zhecyrillic;0436 +zhedescendercyrillic;0497 +zhedieresiscyrillic;04DD +zihiragana;3058 +zikatakana;30B8 +zinorhebrew;05AE +zlinebelow;1E95 +zmonospace;FF5A +zohiragana;305E +zokatakana;30BE +zparen;24B5 +zretroflexhook;0290 +zstroke;01B6 +zuhiragana;305A +zukatakana;30BA +a100;275E +a101;2761 +a102;2762 +a103;2763 +a104;2764 +a105;2710 +a106;2765 +a107;2766 +a108;2767 +a109;2660 +a10;2721 +a110;2665 +a111;2666 +a112;2663 +a117;2709 +a118;2708 +a119;2707 +a11;261B +a120;2460 +a121;2461 +a122;2462 +a123;2463 +a124;2464 +a125;2465 +a126;2466 +a127;2467 +a128;2468 +a129;2469 +a12;261E +a130;2776 +a131;2777 +a132;2778 +a133;2779 +a134;277A +a135;277B +a136;277C +a137;277D +a138;277E +a139;277F +a13;270C +a140;2780 +a141;2781 +a142;2782 +a143;2783 +a144;2784 +a145;2785 +a146;2786 +a147;2787 +a148;2788 +a149;2789 +a14;270D +a150;278A +a151;278B +a152;278C +a153;278D +a154;278E +a155;278F +a156;2790 +a157;2791 +a158;2792 +a159;2793 +a15;270E +a160;2794 +a161;2192 +a162;27A3 +a163;2194 +a164;2195 +a165;2799 +a166;279B +a167;279C +a168;279D +a169;279E +a16;270F +a170;279F +a171;27A0 +a172;27A1 +a173;27A2 +a174;27A4 +a175;27A5 +a176;27A6 +a177;27A7 +a178;27A8 +a179;27A9 +a17;2711 +a180;27AB +a181;27AD +a182;27AF +a183;27B2 +a184;27B3 +a185;27B5 +a186;27B8 +a187;27BA +a188;27BB +a189;27BC +a18;2712 +a190;27BD +a191;27BE +a192;279A +a193;27AA +a194;27B6 +a195;27B9 +a196;2798 +a197;27B4 +a198;27B7 +a199;27AC +a19;2713 +a1;2701 +a200;27AE +a201;27B1 +a202;2703 +a203;2750 +a204;2752 +a205;276E +a206;2770 +a20;2714 +a21;2715 +a22;2716 +a23;2717 +a24;2718 +a25;2719 +a26;271A +a27;271B +a28;271C +a29;2722 +a2;2702 +a30;2723 +a31;2724 +a32;2725 +a33;2726 +a34;2727 +a35;2605 +a36;2729 +a37;272A +a38;272B +a39;272C +a3;2704 +a40;272D +a41;272E +a42;272F +a43;2730 +a44;2731 +a45;2732 +a46;2733 +a47;2734 +a48;2735 +a49;2736 +a4;260E +a50;2737 +a51;2738 +a52;2739 +a53;273A +a54;273B +a55;273C +a56;273D +a57;273E +a58;273F +a59;2740 +a5;2706 +a60;2741 +a61;2742 +a62;2743 +a63;2744 +a64;2745 +a65;2746 +a66;2747 +a67;2748 +a68;2749 +a69;274A +a6;271D +a70;274B +a71;25CF +a72;274D +a73;25A0 +a74;274F +a75;2751 +a76;25B2 +a77;25BC +a78;25C6 +a79;2756 +a7;271E +a81;25D7 +a82;2758 +a83;2759 +a84;275A +a85;276F +a86;2771 +a87;2772 +a88;2773 +a89;2768 +a8;271F +a90;2769 +a91;276C +a92;276D +a93;276A +a94;276B +a95;2774 +a96;2775 +a97;275B +a98;275C +a99;275D +a9;2720 +""" + + +# string table management +# +class StringTable: + def __init__(self, name_list, master_table_name): + self.names = name_list + self.master_table = master_table_name + self.indices = {} + index = 0 + + for name in name_list: + self.indices[name] = index + index += len(name) + 1 + + self.total = index + + def dump(self, file): + write = file.write + write("#ifndef DEFINE_PS_TABLES_DATA\n") + write("#ifdef __cplusplus\n") + write(' extern "C"\n') + write("#else\n") + write(" extern\n") + write("#endif\n") + write("#endif\n") + write(" const char " + self.master_table + + "[" + repr(self.total) + "]\n") + write("#ifdef DEFINE_PS_TABLES_DATA\n") + write(" =\n") + write(" {\n") + + line = "" + for name in self.names: + line += " '" + line += "','".join(list(name)) + line += "', 0,\n" + + write(line) + write(" }\n") + write("#endif /* DEFINE_PS_TABLES_DATA */\n") + write(" ;\n\n\n") + + def dump_sublist(self, file, table_name, macro_name, sublist): + write = file.write + write("#define " + macro_name + " " + repr(len(sublist)) + "\n\n") + + write(" /* Values are offsets into the `" + + self.master_table + "' table */\n\n") + write("#ifndef DEFINE_PS_TABLES_DATA\n") + write("#ifdef __cplusplus\n") + write(' extern "C"\n') + write("#else\n") + write(" extern\n") + write("#endif\n") + write("#endif\n") + write(" const short " + table_name + + "[" + macro_name + "]\n") + write("#ifdef DEFINE_PS_TABLES_DATA\n") + write(" =\n") + write(" {\n") + + line = " " + comma = "" + col = 0 + + for name in sublist: + line += comma + line += "%4d" % self.indices[name] + col += 1 + comma = "," + if col == 14: + col = 0 + comma = ",\n " + + write(line) + write("\n") + write(" }\n") + write("#endif /* DEFINE_PS_TABLES_DATA */\n") + write(" ;\n\n\n") + + +# We now store the Adobe Glyph List in compressed form. The list is put +# into a data structure called `trie' (because it has a tree-like +# appearance). Consider, for example, that you want to store the +# following name mapping: +# +# A => 1 +# Aacute => 6 +# Abalon => 2 +# Abstract => 4 +# +# It is possible to store the entries as follows. +# +# A => 1 +# | +# +-acute => 6 +# | +# +-b +# | +# +-alon => 2 +# | +# +-stract => 4 +# +# We see that each node in the trie has: +# +# - one or more `letters' +# - an optional value +# - zero or more child nodes +# +# The first step is to call +# +# root = StringNode( "", 0 ) +# for word in map.values(): +# root.add( word, map[word] ) +# +# which creates a large trie where each node has only one children. +# +# Executing +# +# root = root.optimize() +# +# optimizes the trie by merging the letters of successive nodes whenever +# possible. +# +# Each node of the trie is stored as follows. +# +# - First the node's letter, according to the following scheme. We +# use the fact that in the AGL no name contains character codes > 127. +# +# name bitsize description +# ---------------------------------------------------------------- +# notlast 1 Set to 1 if this is not the last letter +# in the word. +# ascii 7 The letter's ASCII value. +# +# - The letter is followed by a children count and the value of the +# current key (if any). Again we can do some optimization because all +# AGL entries are from the BMP; this means that 16 bits are sufficient +# to store its Unicode values. Additionally, no node has more than +# 127 children. +# +# name bitsize description +# ----------------------------------------- +# hasvalue 1 Set to 1 if a 16-bit Unicode value follows. +# num_children 7 Number of children. Can be 0 only if +# `hasvalue' is set to 1. +# value 16 Optional Unicode value. +# +# - A node is finished by a list of 16bit absolute offsets to the +# children, which must be sorted in increasing order of their first +# letter. +# +# For simplicity, all 16bit quantities are stored in big-endian order. +# +# The root node has first letter = 0, and no value. +# +class StringNode: + def __init__(self, letter, value): + self.letter = letter + self.value = value + self.children = {} + + def __cmp__(self, other): + return ord(self.letter[0]) - ord(other.letter[0]) + + def __lt__(self, other): + return self.letter[0] < other.letter[0] + + def add(self, word, value): + if len(word) == 0: + self.value = value + return + + letter = word[0] + word = word[1:] + + if letter in self.children: + child = self.children[letter] + else: + child = StringNode(letter, 0) + self.children[letter] = child + + child.add(word, value) + + def optimize(self): + # optimize all children first + children = list(self.children.values()) + self.children = {} + + for child in children: + self.children[child.letter[0]] = child.optimize() + + # don't optimize if there's a value, + # if we don't have any child or if we + # have more than one child + if (self.value != 0) or (not children) or len(children) > 1: + return self + + child = children[0] + + self.letter += child.letter + self.value = child.value + self.children = child.children + + return self + + def dump_debug(self, write, margin): + # this is used during debugging + line = margin + "+-" + if len(self.letter) == 0: + line += "" + else: + line += self.letter + + if self.value: + line += " => " + repr(self.value) + + write(line + "\n") + + if self.children: + margin += "| " + for child in self.children.values(): + child.dump_debug(write, margin) + + def locate(self, index): + self.index = index + if len(self.letter) > 0: + index += len(self.letter) + 1 + else: + index += 2 + + if self.value != 0: + index += 2 + + children = list(self.children.values()) + children.sort() + + index += 2 * len(children) + for child in children: + index = child.locate(index) + + return index + + def store(self, storage): + # write the letters + length = len(self.letter) + if length == 0: + storage += struct.pack("B", 0) + else: + for n in range(length): + val = ord(self.letter[n]) + if n < length - 1: + val += 128 + storage += struct.pack("B", val) + + # write the count + children = list(self.children.values()) + children.sort() + + count = len(children) + + if self.value != 0: + storage += struct.pack("!BH", count + 128, self.value) + else: + storage += struct.pack("B", count) + + for child in children: + storage += struct.pack("!H", child.index) + + for child in children: + storage = child.store(storage) + + return storage + + +def adobe_glyph_values(): + """return the list of glyph names and their unicode values""" + + lines = adobe_glyph_list.split("\n") + glyphs = [] + values = [] + + for line in lines: + if line: + fields = line.split(';') + # print fields[1] + ' - ' + fields[0] + subfields = fields[1].split(' ') + if len(subfields) == 1: + glyphs.append(fields[0]) + values.append(fields[1]) + + return glyphs, values + + +def filter_glyph_names(alist, filter): + """filter `alist' by taking _out_ all glyph names that are in `filter'""" + + count = 0 + extras = [] + + for name in alist: + try: + filtered_index = filter.index(name) + except: + extras.append(name) + + return extras + + +def dump_encoding(file, encoding_name, encoding_list): + """dump a given encoding""" + + write = file.write + write(" /* the following are indices into the SID name table */\n") + write("#ifndef DEFINE_PS_TABLES_DATA\n") + write("#ifdef __cplusplus\n") + write(' extern "C"\n') + write("#else\n") + write(" extern\n") + write("#endif\n") + write("#endif\n") + write(" const unsigned short " + encoding_name + + "[" + repr(len(encoding_list)) + "]\n") + write("#ifdef DEFINE_PS_TABLES_DATA\n") + write(" =\n") + write(" {\n") + + line = " " + comma = "" + col = 0 + for value in encoding_list: + line += comma + line += "%3d" % value + comma = "," + col += 1 + if col == 16: + col = 0 + comma = ",\n " + + write(line) + write("\n") + write(" }\n") + write("#endif /* DEFINE_PS_TABLES_DATA */\n") + write(" ;\n\n\n") + + +def dump_array(the_array, write, array_name): + """dumps a given encoding""" + + write("#ifndef DEFINE_PS_TABLES_DATA\n") + write("#ifdef __cplusplus\n") + write(' extern "C"\n') + write("#else\n") + write(" extern\n") + write("#endif\n") + write("#endif\n") + write(" const unsigned char " + array_name + + "[" + repr(len(the_array)) + "L]\n") + write("#ifdef DEFINE_PS_TABLES_DATA\n") + write(" =\n") + write(" {\n") + + line = "" + comma = " " + col = 0 + + for value in the_array: + line += comma + line += "%3d" % value + comma = "," + col += 1 + + if col == 16: + col = 0 + comma = ",\n " + + if len(line) > 1024: + write(line) + line = "" + + write(line) + write("\n") + write(" }\n") + write("#endif /* DEFINE_PS_TABLES_DATA */\n") + write(" ;\n\n\n") + + +def main(): + """main program body""" + + if len(sys.argv) != 2: + print(__doc__ % sys.argv[0]) + sys.exit(1) + + file = open(sys.argv[1], "w") + write = file.write + + count_sid = len(sid_standard_names) + + # `mac_extras' contains the list of glyph names in the Macintosh standard + # encoding which are not in the SID Standard Names. + # + mac_extras = filter_glyph_names(mac_standard_names, sid_standard_names) + + # `base_list' contains the names of our final glyph names table. + # It consists of the `mac_extras' glyph names, followed by the SID + # standard names. + # + mac_extras_count = len(mac_extras) + base_list = mac_extras + sid_standard_names + + write("/*\n") + write(" *\n") + write(" * %-71s\n" % os.path.basename(sys.argv[1])) + write(" *\n") + write(" * PostScript glyph names.\n") + write(" *\n") + write(" * Copyright 2005-2022 by\n") + write(" * David Turner, Robert Wilhelm, and Werner Lemberg.\n") + write(" *\n") + write(" * This file is part of the FreeType project, and may only be " + "used,\n") + write(" * modified, and distributed under the terms of the FreeType " + "project\n") + write(" * license, LICENSE.TXT. By continuing to use, modify, or " + "distribute\n") + write(" * this file you indicate that you have read the license and\n") + write(" * understand and accept it fully.\n") + write(" *\n") + write(" */\n") + write("\n") + write("\n") + write(" /* This file has been generated automatically -- do not edit! */" + "\n") + write("\n") + write("\n") + + # dump final glyph list (mac extras + sid standard names) + # + st = StringTable(base_list, "ft_standard_glyph_names") + + st.dump(file) + st.dump_sublist(file, "ft_mac_names", + "FT_NUM_MAC_NAMES", mac_standard_names) + st.dump_sublist(file, "ft_sid_names", + "FT_NUM_SID_NAMES", sid_standard_names) + + dump_encoding(file, "t1_standard_encoding", t1_standard_encoding) + dump_encoding(file, "t1_expert_encoding", t1_expert_encoding) + + # dump the AGL in its compressed form + # + agl_glyphs, agl_values = adobe_glyph_values() + dictionary = StringNode("", 0) + + for g in range(len(agl_glyphs)): + dictionary.add(agl_glyphs[g], eval("0x" + agl_values[g])) + + dictionary = dictionary.optimize() + dict_len = dictionary.locate(0) + dict_array = dictionary.store(b"") + + write("""\ + /* + * This table is a compressed version of the Adobe Glyph List (AGL), + * optimized for efficient searching. It has been generated by the + * `glnames.py' python script located in the `src/tools' directory. + * + * The lookup function to get the Unicode value for a given string + * is defined below the table. + */ + +#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + +""") + + dump_array(dict_array, write, "ft_adobe_glyph_list") + + # write the lookup routine now + # + write("""\ +#ifdef DEFINE_PS_TABLES + /* + * This function searches the compressed table efficiently. + */ + static unsigned long + ft_get_adobe_glyph_index( const char* name, + const char* limit ) + { + int c = 0; + int count, min, max; + const unsigned char* p = ft_adobe_glyph_list; + + + if ( name == 0 || name >= limit ) + goto NotFound; + + c = *name++; + count = p[1]; + p += 2; + + min = 0; + max = count; + + while ( min < max ) + { + int mid = ( min + max ) >> 1; + const unsigned char* q = p + mid * 2; + int c2; + + + q = ft_adobe_glyph_list + ( ( (int)q[0] << 8 ) | q[1] ); + + c2 = q[0] & 127; + if ( c2 == c ) + { + p = q; + goto Found; + } + if ( c2 < c ) + min = mid + 1; + else + max = mid; + } + goto NotFound; + + Found: + for (;;) + { + /* assert (*p & 127) == c */ + + if ( name >= limit ) + { + if ( (p[0] & 128) == 0 && + (p[1] & 128) != 0 ) + return (unsigned long)( ( (int)p[2] << 8 ) | p[3] ); + + goto NotFound; + } + c = *name++; + if ( p[0] & 128 ) + { + p++; + if ( c != (p[0] & 127) ) + goto NotFound; + + continue; + } + + p++; + count = p[0] & 127; + if ( p[0] & 128 ) + p += 2; + + p++; + + for ( ; count > 0; count--, p += 2 ) + { + int offset = ( (int)p[0] << 8 ) | p[1]; + const unsigned char* q = ft_adobe_glyph_list + offset; + + if ( c == ( q[0] & 127 ) ) + { + p = q; + goto NextIter; + } + } + goto NotFound; + + NextIter: + ; + } + + NotFound: + return 0; + } +#endif /* DEFINE_PS_TABLES */ + +#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ + +""") + + if 0: # generate unit test, or don't + # + # now write the unit test to check that everything works OK + # + write("#ifdef TEST\n\n") + + write("static const char* const the_names[] = {\n") + for name in agl_glyphs: + write(' "' + name + '",\n') + write(" 0\n};\n") + + write("static const unsigned long the_values[] = {\n") + for val in agl_values: + write(' 0x' + val + ',\n') + write(" 0\n};\n") + + write(""" +#include +#include +#include + +int +main( void ) +{ +int result = 0; +const char* const* names = the_names; +const unsigned long* values = the_values; + + +for ( ; *names; names++, values++ ) +{ + const char* name = *names; + unsigned long reference = *values; + unsigned long value; + + + value = ft_get_adobe_glyph_index( name, name + strlen( name ) ); + if ( value != reference ) + { + result = 1; + fprintf( stderr, "name '%s' => %04x instead of %04x\\n", + name, value, reference ); + } +} + +return result; +} +""") + + write("#endif /* TEST */\n") + + write("\n/* END */\n") + + +# Now run the main routine +# +main() + +# END diff --git a/lib/libesp32_lvgl/freetype/src/tools/make_distribution_archives.py b/lib/libesp32_lvgl/freetype/src/tools/make_distribution_archives.py new file mode 100755 index 000000000..f29eb128c --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/make_distribution_archives.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python3 +"""Generate distribution archives for a given FreeType 2 release.""" + +from __future__ import print_function + +import argparse +import atexit +import os +import shutil +import subprocess +import sys +import tempfile + +_TOP_DIR = os.path.abspath(os.path.join(__file__, "..", "..", "..")) +_SCRIPT_DIR = os.path.dirname(os.path.join(_TOP_DIR, "builds", "meson", "")) + + +def get_cmd_output(cmd, cwd=None): + """Run a command and return its output as a string.""" + if cwd is not None: + out = subprocess.check_output(cmd, cwd=cwd) + else: + out = subprocess.check_output(cmd) + return out.decode("utf-8").rstrip() + + +def is_git_dir_clean(git_dir): + """Return True iff |git_dir| is a git directory in clean state.""" + out = get_cmd_output(["git", "status", "--porcelain"], cwd=git_dir) + return len(out) == 0 + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + + parser.add_argument( + "--source_dir", default=_TOP_DIR, help="Source directory path." + ) + + parser.add_argument( + "--version", + help=( + "Specify alternate FreeType version (it is otherwise extracted" + " from current sources by default)." + ), + ) + + parser.add_argument( + "--gnu-config-dir", + help=( + "Path of input directory containing recent `config.guess` and" + " `config.sub` files from GNU config." + ), + ) + + parser.add_argument( + "--build-dir", + help="Specify build directory. Only used for debugging this script.", + ) + + parser.add_argument( + "--ignore-clean-check", + action="store_true", + help=( + "Do not check for a clean source git repository. Only used for" + " debugging this script." + ), + ) + + parser.add_argument( + "output_dir", help="Output directory for generated archives." + ) + + args = parser.parse_args() + + git_dir = args.source_dir if args.source_dir else _TOP_DIR + if not args.ignore_clean_check and not is_git_dir_clean(git_dir): + sys.stderr.write( + "ERROR: Your git repository is not in a clean state: %s\n" + % git_dir + ) + return 1 + + if args.version: + version = args.version + else: + # Extract FreeType version from sources. + version = get_cmd_output( + [ + sys.executable, + os.path.join(_SCRIPT_DIR, "extract_freetype_version.py"), + os.path.join(_TOP_DIR, "include", "freetype", "freetype.h"), + ] + ) + + # Determine the build directory. This will be a temporary file that is + # cleaned up on script exit by default, unless --build-dir=DIR is used, + # in which case we only create and empty the directory, but never remove + # its content on exit. + if args.build_dir: + build_dir = args.build_dir + if not os.path.exists(build_dir): + os.makedirs(build_dir) + else: + # Remove anything from the build directory, if any. + for item in os.listdir(build_dir): + file_path = os.path.join(build_dir, item) + if os.path.isdir(file_path): + shutil.rmtree(file_path) + else: + os.unlink(file_path) + else: + # Create a temporary directory, and ensure it is removed on exit. + build_dir = tempfile.mkdtemp(prefix="freetype-dist-") + + def clean_build_dir(): + shutil.rmtree(build_dir) + + atexit.register(clean_build_dir) + + # Copy all source files known to git into $BUILD_DIR/freetype-$VERSION + # with the exception of .gitignore and .mailmap files. + source_files = [ + f + for f in get_cmd_output(["git", "ls-files"], cwd=git_dir).split("\n") + if os.path.basename(f) not in (".gitignore", ".mailmap") + ] + + freetype_dir = "freetype-" + version + tmp_src_dir = os.path.join(build_dir, freetype_dir) + os.makedirs(tmp_src_dir) + + for src in source_files: + dst = os.path.join(tmp_src_dir, src) + dst_dir = os.path.dirname(dst) + if not os.path.exists(dst_dir): + os.makedirs(dst_dir) + shutil.copy(os.path.join(git_dir, src), dst) + + # Run autogen.sh in directory. + subprocess.check_call(["/bin/sh", "autogen.sh"], cwd=tmp_src_dir) + shutil.rmtree( + os.path.join(tmp_src_dir, "builds", "unix", "autom4te.cache") + ) + + # Copy config.guess and config.sub if possible! + if args.gnu_config_dir: + for f in ("config.guess", "config.sub"): + shutil.copy( + os.path.join(args.gnu_config_dir, f), + os.path.join(tmp_src_dir, "builds", "unix", f), + ) + + # Generate reference documentation under docs/ + subprocess.check_call( + [ + sys.executable, + os.path.join(_SCRIPT_DIR, "generate_reference_docs.py"), + "--input-dir", + tmp_src_dir, + "--version", + version, + "--output-dir", + os.path.join(tmp_src_dir, "docs"), + ] + ) + + shutil.rmtree(os.path.join(tmp_src_dir, "docs", "markdown")) + os.unlink(os.path.join(tmp_src_dir, "docs", "mkdocs.yml")) + + # Generate our archives + freetype_tar = freetype_dir + ".tar" + + subprocess.check_call( + ["tar", "-H", "ustar", "-chf", freetype_tar, freetype_dir], + cwd=build_dir, + ) + + subprocess.check_call( + ["gzip", "-9", "--keep", freetype_tar], cwd=build_dir + ) + + subprocess.check_call(["xz", "--keep", freetype_tar], cwd=build_dir) + + ftwinversion = "ft" + "".join(version.split(".")) + subprocess.check_call( + ["zip", "-qlr9", ftwinversion + ".zip", freetype_dir], cwd=build_dir + ) + + # Copy file to output directory now. + if not os.path.exists(args.output_dir): + os.makedirs(args.output_dir) + + for f in ( + freetype_tar + ".gz", + freetype_tar + ".xz", + ftwinversion + ".zip", + ): + shutil.copy( + os.path.join(build_dir, f), os.path.join(args.output_dir, f) + ) + + # Done! + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/lib/libesp32_lvgl/freetype/src/tools/no-copyright b/lib/libesp32_lvgl/freetype/src/tools/no-copyright new file mode 100644 index 000000000..e171b76f3 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/no-copyright @@ -0,0 +1,66 @@ +# Files that don't get a copyright, or which are taken from elsewhere. +# +# All lines in this file are patterns (relative to the top-level directory), +# including the comment lines; this means that e.g. `FTL.TXT' matches all +# files that have this string in the file name (including the path relative +# to the current directory, always starting with `./'). +# +# Don't put empty lines into this file! +# +builds/unix/pkg.m4 +# +docs/FTL.TXT +docs/GPLv2.TXT +# +include/freetype/internal/fthash.h +# +src/base/fthash.c +src/base/md5.c +src/base/md5.h +# +src/bdf/bdf.c +src/bdf/bdf.h +src/bdf/bdfdrivr.c +src/bdf/bdfdrivr.h +src/bdf/bdferror.h +src/bdf/bdflib.c +src/bdf/module.mk +src/bdf/README +src/bdf/rules.mk +# +src/pcf/module.mk +src/pcf/pcf.c +src/pcf/pcf.h +src/pcf/pcfdrivr.c +src/pcf/pcfdrivr.h +src/pcf/pcferror.h +src/pcf/pcfread.c +src/pcf/pcfread.h +src/pcf/pcfutil.c +src/pcf/pcfutil.h +src/pcf/README +src/pcf/rules.mk +# +src/gzip/adler32.c +src/gzip/ftzconf.c +src/gzip/infblock.c +src/gzip/infblock.h +src/gzip/infcodes.c +src/gzip/infcodes.h +src/gzip/inffixed.h +src/gzip/inflate.c +src/gzip/inftrees.c +src/gzip/inftrees.h +src/gzip/infutil.c +src/gzip/infutil.h +src/gzip/zconf.h +src/gzip/zlib.h +src/gzip/zutil.c +src/gzip/zutil.h +# +src/tools/apinames.c +src/tools/ftrandom/ftrandom.c +# +subprojects/dlg +# +# EOF diff --git a/lib/libesp32_lvgl/freetype/src/tools/test_afm.c b/lib/libesp32_lvgl/freetype/src/tools/test_afm.c new file mode 100644 index 000000000..a4b226898 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/test_afm.c @@ -0,0 +1,156 @@ +/* + * gcc -DFT2_BUILD_LIBRARY -I../../include -o test_afm test_afm.c \ + * -L../../objs/.libs -lfreetype -lz -static + */ +#include +#include +#include + + void dump_fontinfo( AFM_FontInfo fi ) + { + FT_UInt i; + + + printf( "This AFM is for %sCID font.\n\n", + ( fi->IsCIDFont ) ? "" : "non-" ); + + printf( "FontBBox: %.2f %.2f %.2f %.2f\n", fi->FontBBox.xMin / 65536., + fi->FontBBox.yMin / 65536., + fi->FontBBox.xMax / 65536., + fi->FontBBox.yMax / 65536. ); + printf( "Ascender: %.2f\n", fi->Ascender / 65536. ); + printf( "Descender: %.2f\n\n", fi->Descender / 65536. ); + + if ( fi->NumTrackKern ) + printf( "There are %d sets of track kernings:\n", + fi->NumTrackKern ); + else + printf( "There is no track kerning.\n" ); + + for ( i = 0; i < fi->NumTrackKern; i++ ) + { + AFM_TrackKern tk = fi->TrackKerns + i; + + + printf( "\t%2d: %5.2f %5.2f %5.2f %5.2f\n", tk->degree, + tk->min_ptsize / 65536., + tk->min_kern / 65536., + tk->max_ptsize / 65536., + tk->max_kern / 65536. ); + } + + printf( "\n" ); + + if ( fi->NumKernPair ) + printf( "There are %d kerning pairs:\n", + fi->NumKernPair ); + else + printf( "There is no kerning pair.\n" ); + + for ( i = 0; i < fi->NumKernPair; i++ ) + { + AFM_KernPair kp = fi->KernPairs + i; + + + printf( "\t%3d + %3d => (%4d, %4d)\n", kp->index1, + kp->index2, + kp->x, + kp->y ); + } + + } + + int + dummy_get_index( const char* name, + FT_Offset len, + void* user_data ) + { + if ( len ) + return name[0]; + else + return 0; + } + + FT_Error + parse_afm( FT_Library library, + FT_Stream stream, + AFM_FontInfo fi ) + { + PSAux_Service psaux; + AFM_ParserRec parser; + FT_Error error = FT_Err_Ok; + + + psaux = (PSAux_Service)FT_Get_Module_Interface( library, "psaux" ); + if ( !psaux || !psaux->afm_parser_funcs ) + return -1; + + error = FT_Stream_EnterFrame( stream, stream->size ); + if ( error ) + return error; + + error = psaux->afm_parser_funcs->init( &parser, + library->memory, + stream->cursor, + stream->limit ); + if ( error ) + return error; + + parser.FontInfo = fi; + parser.get_index = dummy_get_index; + + error = psaux->afm_parser_funcs->parse( &parser ); + + psaux->afm_parser_funcs->done( &parser ); + + return error; + } + + + int main( int argc, + char** argv ) + { + FT_Library library; + FT_StreamRec stream; + FT_Error error = FT_Err_Ok; + AFM_FontInfoRec fi; + + + if ( argc < 2 ) + return FT_ERR( Invalid_Argument ); + + error = FT_Init_FreeType( &library ); + if ( error ) + return error; + + FT_ZERO( &stream ); + error = FT_Stream_Open( &stream, argv[1] ); + if ( error ) + goto Exit; + stream.memory = library->memory; + + FT_ZERO( &fi ); + error = parse_afm( library, &stream, &fi ); + + if ( !error ) + { + FT_Memory memory = library->memory; + + + dump_fontinfo( &fi ); + + if ( fi.KernPairs ) + FT_FREE( fi.KernPairs ); + if ( fi.TrackKerns ) + FT_FREE( fi.TrackKerns ); + } + else + printf( "parse error\n" ); + + FT_Stream_Close( &stream ); + + Exit: + FT_Done_FreeType( library ); + + return error; + } diff --git a/lib/libesp32_lvgl/freetype/src/tools/test_bbox.c b/lib/libesp32_lvgl/freetype/src/tools/test_bbox.c new file mode 100644 index 000000000..d9fd93299 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/test_bbox.c @@ -0,0 +1,187 @@ +#include +#include + + +#include /* for clock() */ + +/* SunOS 4.1.* does not define CLOCKS_PER_SEC, so include */ +/* to get the HZ macro which is the equivalent. */ +#if defined(__sun__) && !defined(SVR4) && !defined(__SVR4) +#include +#define CLOCKS_PER_SEC HZ +#endif + + static long + get_time( void ) + { + return clock() * 10000L / CLOCKS_PER_SEC; + } + + + + + /* test bbox computations */ + +#define XSCALE 65536 +#define XX(x) ((FT_Pos)(x*XSCALE)) +#define XVEC(x,y) { XX(x), XX(y) } +#define XVAL(x) ((x)/(1.0*XSCALE)) + + /* dummy outline #1 */ + static FT_Vector dummy_vec_1[4] = + { +#if 1 + XVEC( 408.9111, 535.3164 ), + XVEC( 455.8887, 634.396 ), + XVEC( -37.8765, 786.2207 ), + XVEC( 164.6074, 535.3164 ) +#else + { (FT_Int32)0x0198E93DL , (FT_Int32)0x021750FFL }, /* 408.9111, 535.3164 */ + { (FT_Int32)0x01C7E312L , (FT_Int32)0x027A6560L }, /* 455.8887, 634.3960 */ + { (FT_Int32)0xFFDA1F9EL , (FT_Int32)0x0312387FL }, /* -37.8765, 786.2207 */ + { (FT_Int32)0x00A49B7EL , (FT_Int32)0x021750FFL } /* 164.6074, 535.3164 */ +#endif + }; + + static char dummy_tag_1[4] = + { + FT_CURVE_TAG_ON, + FT_CURVE_TAG_CUBIC, + FT_CURVE_TAG_CUBIC, + FT_CURVE_TAG_ON + }; + + static short dummy_contour_1[1] = + { + 3 + }; + + static FT_Outline dummy_outline_1 = + { + 1, + 4, + dummy_vec_1, + dummy_tag_1, + dummy_contour_1, + 0 + }; + + + /* dummy outline #2 */ + static FT_Vector dummy_vec_2[4] = + { + XVEC( 100.0, 100.0 ), + XVEC( 100.0, 200.0 ), + XVEC( 200.0, 200.0 ), + XVEC( 200.0, 133.0 ) + }; + + static FT_Outline dummy_outline_2 = + { + 1, + 4, + dummy_vec_2, + dummy_tag_1, + dummy_contour_1, + 0 + }; + + + /* dummy outline #3 with bbox of [0 100 128 128] precisely */ + static FT_Vector dummy_vec_3[4] = + { + XVEC( 100.0, 127.0 ), + XVEC( 200.0, 127.0 ), + XVEC( 0.0, 136.0 ), + XVEC( 0.0, 100.0 ) + }; + + static FT_Outline dummy_outline_3 = + { + 1, + 4, + dummy_vec_3, + dummy_tag_1, + dummy_contour_1, + 0 + }; + + + static void + dump_outline( FT_Outline* outline ) + { + FT_BBox bbox; + + /* compute and display cbox */ + FT_Outline_Get_CBox( outline, &bbox ); + printf( "cbox = [%.2f %.2f %.2f %.2f]\n", + XVAL( bbox.xMin ), + XVAL( bbox.yMin ), + XVAL( bbox.xMax ), + XVAL( bbox.yMax ) ); + + /* compute and display bbox */ + FT_Outline_Get_BBox( outline, &bbox ); + printf( "bbox = [%.2f %.2f %.2f %.2f]\n", + XVAL( bbox.xMin ), + XVAL( bbox.yMin ), + XVAL( bbox.xMax ), + XVAL( bbox.yMax ) ); + } + + + + static void + profile_outline( FT_Outline* outline, + long repeat ) + { + FT_BBox bbox; + long count; + long time0; + + time0 = get_time(); + for ( count = repeat; count > 0; count-- ) + FT_Outline_Get_CBox( outline, &bbox ); + + time0 = get_time() - time0; + printf( "time = %6.3f cbox = [%8.4f %8.4f %8.4f %8.4f]\n", + ((double)time0/10000.0), + XVAL( bbox.xMin ), + XVAL( bbox.yMin ), + XVAL( bbox.xMax ), + XVAL( bbox.yMax ) ); + printf( "cbox_hex = [%08X %08X %08X %08X]\n", + bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax ); + + + time0 = get_time(); + for ( count = repeat; count > 0; count-- ) + FT_Outline_Get_BBox( outline, &bbox ); + + time0 = get_time() - time0; + printf( "time = %6.3f bbox = [%8.4f %8.4f %8.4f %8.4f]\n", + ((double)time0/10000.0), + XVAL( bbox.xMin ), + XVAL( bbox.yMin ), + XVAL( bbox.xMax ), + XVAL( bbox.yMax ) ); + printf( "bbox_hex = [%08X %08X %08X %08X]\n", + bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax ); + } + +#define REPEAT 1000000L + + int main( int argc, char** argv ) + { + printf( "outline #1\n" ); + profile_outline( &dummy_outline_1, REPEAT ); + + printf( "outline #2\n" ); + profile_outline( &dummy_outline_2, REPEAT ); + + printf( "outline #3\n" ); + profile_outline( &dummy_outline_3, REPEAT ); + + return 0; + } + diff --git a/lib/libesp32_lvgl/freetype/src/tools/test_trig.c b/lib/libesp32_lvgl/freetype/src/tools/test_trig.c new file mode 100644 index 000000000..4f3410ab3 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/test_trig.c @@ -0,0 +1,257 @@ +#include +#include + +#include +#include + +#define PI 3.14159265358979323846 +#define SPI (PI/FT_ANGLE_PI) + +/* the precision in 16.16 fixed-point checks. Expect between 2 and 5 */ +/* noise LSB bits during operations, due to rounding errors.. */ +#define THRESHOLD 64 + + static error = 0; + + static void + test_cos( void ) + { + int i; + + + for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000L ) + { + FT_Fixed f1, f2; + double d2; + + + f1 = FT_Cos(i); + d2 = cos( i*SPI ); + f2 = (FT_Fixed)(d2*65536.0); + + if ( abs( f2-f1 ) > THRESHOLD ) + { + error = 1; + printf( "FT_Cos[%3d] = %.7f cos[%3d] = %.7f\n", + (i >> 16), f1/65536.0, (i >> 16), d2 ); + } + } + } + + + static void + test_sin( void ) + { + int i; + + + for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000L ) + { + FT_Fixed f1, f2; + double d2; + + + f1 = FT_Sin(i); + d2 = sin( i*SPI ); + f2 = (FT_Fixed)(d2*65536.0); + + if ( abs( f2-f1 ) > THRESHOLD ) + { + error = 1; + printf( "FT_Sin[%3d] = %.7f sin[%3d] = %.7f\n", + (i >> 16), f1/65536.0, (i >> 16), d2 ); + } + } + } + + + static void + test_tan( void ) + { + int i; + + + for ( i = 0; i < FT_ANGLE_PI2 - 0x2000000L; i += 0x10000L ) + { + FT_Fixed f1, f2; + double d2; + + + f1 = FT_Tan(i); + d2 = tan( i*SPI ); + f2 = (FT_Fixed)(d2*65536.0); + + if ( abs( f2-f1 ) > THRESHOLD ) + { + error = 1; + printf( "FT_Tan[%3d] = %.7f tan[%3d] = %.7f\n", + (i >> 16), f1/65536.0, (i >> 16), d2 ); + } + } + } + + + static void + test_atan2( void ) + { + int i; + + + for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000L ) + { + FT_Fixed c2, s2; + double l, a, c1, s1; + int j; + + + l = 5.0; + a = i*SPI; + + c1 = l * cos(a); + s1 = l * sin(a); + + c2 = (FT_Fixed)(c1*65536.0); + s2 = (FT_Fixed)(s1*65536.0); + + j = FT_Atan2( c2, s2 ); + if ( j < 0 ) + j += FT_ANGLE_2PI; + + if ( abs( i - j ) > 1 ) + { + printf( "FT_Atan2( %.7f, %.7f ) = %.5f, atan = %.5f\n", + c2/65536.0, s2/65536.0, j/65536.0, i/65536.0 ); + } + } + } + + + static void + test_unit( void ) + { + int i; + + + for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000L ) + { + FT_Vector v; + double a, c1, s1; + FT_Fixed c2, s2; + + + FT_Vector_Unit( &v, i ); + a = ( i*SPI ); + c1 = cos(a); + s1 = sin(a); + c2 = (FT_Fixed)(c1*65536.0); + s2 = (FT_Fixed)(s1*65536.0); + + if ( abs( v.x-c2 ) > THRESHOLD || + abs( v.y-s2 ) > THRESHOLD ) + { + error = 1; + printf( "FT_Vector_Unit[%3d] = ( %.7f, %.7f ) vec = ( %.7f, %.7f )\n", + (i >> 16), + v.x/65536.0, v.y/65536.0, + c1, s1 ); + } + } + } + + + static void + test_length( void ) + { + int i; + + + for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000L ) + { + FT_Vector v; + FT_Fixed l, l2; + + + l = (FT_Fixed)(500.0*65536.0); + v.x = (FT_Fixed)( l * cos( i*SPI ) ); + v.y = (FT_Fixed)( l * sin( i*SPI ) ); + l2 = FT_Vector_Length( &v ); + + if ( abs( l2-l ) > THRESHOLD ) + { + error = 1; + printf( "FT_Length( %.7f, %.7f ) = %.5f, length = %.5f\n", + v.x/65536.0, v.y/65536.0, l2/65536.0, l/65536.0 ); + } + } + } + + + static void + test_rotate( void ) + { + int rotate; + + + for ( rotate = 0; rotate < FT_ANGLE_2PI; rotate += 0x10000L ) + { + double ra, cra, sra; + int i; + + + ra = rotate*SPI; + cra = cos( ra ); + sra = sin( ra ); + + for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000L ) + { + FT_Fixed c2, s2, c4, s4; + FT_Vector v; + double l, a, c1, s1, c3, s3; + + + l = 500.0; + a = i*SPI; + + c1 = l * cos(a); + s1 = l * sin(a); + + v.x = c2 = (FT_Fixed)(c1*65536.0); + v.y = s2 = (FT_Fixed)(s1*65536.0); + + FT_Vector_Rotate( &v, rotate ); + + c3 = c1 * cra - s1 * sra; + s3 = c1 * sra + s1 * cra; + + c4 = (FT_Fixed)(c3*65536.0); + s4 = (FT_Fixed)(s3*65536.0); + + if ( abs( c4 - v.x ) > THRESHOLD || + abs( s4 - v.y ) > THRESHOLD ) + { + error = 1; + printf( "FT_Rotate( (%.7f,%.7f), %.5f ) = ( %.7f, %.7f ), rot = ( %.7f, %.7f )\n", + c1, s1, ra, + c2/65536.0, s2/65536.0, + c4/65536.0, s4/65536.0 ); + } + } + } + } + + + int main( void ) + { + test_cos(); + test_sin(); + test_tan(); + test_atan2(); + test_unit(); + test_length(); + test_rotate(); + + if (!error) + printf( "trigonometry test ok !\n" ); + + return !error; + } diff --git a/lib/libesp32_lvgl/freetype/src/tools/update-copyright b/lib/libesp32_lvgl/freetype/src/tools/update-copyright new file mode 100755 index 000000000..674823ceb --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/update-copyright @@ -0,0 +1,14 @@ +#!/bin/sh + +# Run the `update-copyright-year' script on all files in the git repository, +# taking care of exceptions stored in file `no-copyright'. + +topdir=`git rev-parse --show-toplevel` +toolsdir=`dirname $0` + +git ls-files --full-name $topdir \ +| sed "s|^|$topdir/|" \ +| grep -vFf $toolsdir/no-copyright \ +| xargs $toolsdir/update-copyright-year + +# EOF diff --git a/lib/libesp32_lvgl/freetype/src/tools/update-copyright-year b/lib/libesp32_lvgl/freetype/src/tools/update-copyright-year new file mode 100755 index 000000000..b0b60fb88 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/update-copyright-year @@ -0,0 +1,157 @@ +eval '(exit $?0)' && eval 'exec perl -wS -i "$0" ${1+"$@"}' + & eval 'exec perl -wS -i "$0" $argv:q' + if 0; + +# Copyright (C) 2015-2023 by +# Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + +# [Note: This script is expected to be called by the shell, which in turn +# calls perl automatically. The nifty start-up code above is based on +# gnulib's `update-copyright' script; it is a more portable replacement for +# the shebang, using the first `perl' program in the shell's path instead.] + +# Usage: +# +# update-copyright-year file1 [file2 ...] + + +# This script handles copyright entries like +# +# Copyright 2000 by +# foobar +# +# or +# +# /* Copyright (c) 2000, 2001, 2004-2007 by */ +# /* foobar */ +# +# and replaces them uniformly with +# +# Copyright (C) 2000-2021 +# foobar +# +# and +# +# /* Copyright (C) 2000-2021 by */ +# /* foobar */ +# +# (assuming that the current year is 2021). As can be seen, the line length +# is retained if there is non-whitespace after the word `by' on the same +# line. + +use strict; + + +my (undef, undef, undef, + undef, undef, $year, + undef, undef, undef) = localtime(time); +$year += 1900; + +my $replaced = 0; + + +# Loop over all input files; option `-i' (issued at the very beginning of +# this script) makes perl edit them in-place. +while (<>) +{ + # Only handle the first copyright notice in a file. + if (!$replaced) + { + # First try: Search multiple copyright years. + s { + (?.*) + Copyright + (?(\ + + | \ +\(C\)\ +)) + (?[12][0-9][0-9][0-9]) + (?.+) + (?[12][0-9][0-9][0-9]) + (?\ +) + by + (?\ *) + (?.*) + } + { + # Fill line to the same length (if appropriate); we skip the middle + # part but insert `(C)', three spaces, and `-'. + my $space = length($+{space1}) + + length($+{middle}) + + length($+{space2}) + + length($+{space3}) + - (length("(C)") + 3 + 1); + + print "$+{begin}"; + print "Copyright\ (C)\ $+{first}-$year\ by"; + print ' ' x $space if length($+{end}); + print "$+{end}\n"; + $replaced = 1; + }ex + || + # Second try: Search a single copyright year. + s { + (?.*) + Copyright + (?(\ + + | \ +\(C\)\ +)) + (?[12][0-9][0-9][0-9]) + (?\ +) + by + (?\ *) + (?.*) + } + { + if ($+{first} < $year) + { + # Fill line to the same length (if appropriate); we insert three + # spaces, the string `(C)', a `-', and the current year. + my $space = length($+{space1}) + + length($+{space2}) + + length($+{space3}) + - (length($year) + length("(C)") + 3 + 1); + + print "$+{begin}"; + print "Copyright\ (C)\ $+{first}-$year\ by"; + # If $space is negative this inserts nothing. + print ' ' x $space if length($+{end}); + print "$+{end}\n"; + $replaced = 1; + } + else + { + # Fill line to the same length (if appropriate); we insert three + # spaces and the string `(C)'. + my $space = length($+{space1}) + + length($+{space2}) + + length($+{space3}) + - (length("(C)") + 3); + + print "$+{begin}"; + print "Copyright\ (C)\ $+{first}\ by"; + # If $space is negative this inserts nothing. + print ' ' x $space if length($+{end}); + print "$+{end}\n"; + $replaced = 1; + } + }ex + || + # Otherwise print line unaltered. + print; + } + else + { + print; + } +} +continue +{ + # Reset $replaced before processing the next file. + $replaced = 0 if eof; +} + +# EOF diff --git a/lib/libesp32_lvgl/freetype/src/tools/vms_shorten_symbol.c b/lib/libesp32_lvgl/freetype/src/tools/vms_shorten_symbol.c new file mode 100644 index 000000000..81f2a7187 --- /dev/null +++ b/lib/libesp32_lvgl/freetype/src/tools/vms_shorten_symbol.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2010, 2017 Craig A. Berry + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* vms_shorten_symbol + * + * This program provides shortening of long symbols (> 31 characters) using the + * same mechanism as the OpenVMS C compiler. The basic procedure is to compute + * an AUTODIN II checksum of the entire symbol, encode the checksum in base32, + * and glue together a shortened symbol from the first 23 characters of the + * original symbol plus the encoded checksum appended. The output format is + * the same used in the name mangler database, stored by default in + * [.CXX_REPOSITORY]CXX$DEMANGLER_DB. + * + * To obtain the same result as CC/NAMES=SHORTENED, run like so: + * + * $ mcr []vms_shorten_symbol "Please_forgive_this_absurdly_long_symbol_name" + * PLEASE_FORGIVE_THIS_ABS1ARO4QU$Please_forgive_this_absurdly_long_symbol_name + * + * To obtain the same result as CC/NAMES=(SHORTENED,AS_IS), pass a non-zero + * value as the second argument, like so: + * + * $ mcr []vms_shorten_symbol "Please_forgive_this_absurdly_long_symbol_name" 1 + * Please_forgive_this_abs3rv8rnn$Please_forgive_this_absurdly_long_symbol_name + */ + +#include +#include +#include +#include + +#ifdef __VMS +#define UINT32 unsigned int +#else +#include +#define UINT32 uint32_t +#endif + +extern UINT32 crc32(const char *input_string); +extern int u32_to_base32(UINT32 input, char *output); +extern int vms_shorten_symbol(const char *symbol, char *shortened, char as_is_flag); + +/* + * This routine implements the AUTODIN II polynomial. + */ + +UINT32 +crc32(const char *input_string) +{ + +/* + * CRC code and data based partly on FreeBSD implementation, which + * notes: + * + * The crc32 functions and data was originally written by Spencer + * Garrett and was cleaned from the PostgreSQL source + * tree via the files contrib/ltree/crc32.[ch]. No license was + * included, therefore it is assumed that this code is public + * domain. Attribution still noted. + * + * (I think they mean "gleaned" not "cleaned".) + */ + + static const UINT32 autodin_ii_table[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, + }; + + UINT32 crc = ~0U; + char *c; + for (c = (char *)input_string; *c; ++c) + crc = (crc >> 8) ^ autodin_ii_table[(crc ^ *c) & 0xff]; + return ~crc; +} + +/* + * This is the RFC2938 variant of base32, not RFC3548, Crockford's, or + * other newer variant. It produces an 8-byte encoded character string + * (plus trailing null) from a 32-bit integer input. + */ + +int +u32_to_base32(UINT32 input, char *output) +{ + static const char base32hex_table[32] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v' + }; + int i; + + /* + * Grab lowest 5 bits and look up conversion in table. Lather, rinse, + * repeat for a total of 7, 5-bit chunks to accommodate 32 bits of input. + */ + for (i = 0; i < 7; i++) { + output[6 - i] = base32hex_table[input & 0x1f]; + input >>= 5; /* position to look at next 5 */ + } + output[7] = '$'; /* It's DEC, so use '$' not '=' to pad. */ + output[8] = '\0'; + return 0; +} + +/* + * Take an input symbol name of arbitrary length and produce a symbol shortened + * to 31 characters. The shortened symbol consists of the first 23 characters + * of the original symbol plus the 8 characters of the encoded checksum. The + * third argument is a boolean indicating whether to emulate the compiler's + * /NAMES=AS_IS option. When false (the compiler's default), the shortened + * symbol will be upper cased. When the original symbol is 31 characters or + * fewer in length, no checksum will be appended and the original symbol is + * returned verbatim (though upper cased if the as_is_flag is false). + */ + +int +vms_shorten_symbol(const char *input_symbol, char *shortened, char as_is_flag) +{ + char b32str[9]; + UINT32 crc; + char *c, *symbol; + int symlen; + + symlen = strlen(input_symbol); + symbol = (char *)malloc(symlen + 1); + if (symbol == NULL) + return -1; + + strncpy(symbol, input_symbol, symlen); + symbol[symlen] = '\0'; + + if (!as_is_flag) { + for (c = symbol; *c; c++) + *c = toupper(*c); + } + + if (symlen <= 31) { + strncpy(shortened, symbol, symlen); + shortened[symlen] = '\0'; + free(symbol); + return 0; + } + + /* + * Compute the checksum on the whole symbol. + */ + + crc = crc32(symbol); + + /* The compiler does not use the inverted checksum, so we invert it + * back before encoding in base32. + */ + + if (u32_to_base32(~crc, (char *)&b32str) == -1) { + free(symbol); + return -1; + } + + if (!as_is_flag) { + for (c = (char *)&b32str; *c; c++) + *c = toupper(*c); + } + + sprintf(shortened, "%.23s%.8s", symbol, b32str); + shortened[31] = '\0'; + free(symbol); + return 0; +} + +#ifdef TEST_MAIN +int +main(int argc, char **argv) +{ + char short_symbol[32]; + char as_is_flag = 0; + + if (argc < 2) { + fprintf(stderr, "Usage: %s []\n", argv[0]); + exit(EXIT_FAILURE); + } + if (argc > 2) + as_is_flag = 1; + + if (vms_shorten_symbol(argv[1], (char *)&short_symbol, as_is_flag) == -1) { + fprintf(stderr, "Symbol shortening failed\n"); + exit(EXIT_FAILURE); + } + + printf("%s%s\n", (char *)&short_symbol, argv[1]); +} +#endif diff --git a/lib/libesp32_lvgl/freetype/src/truetype/module.mk b/lib/libesp32_lvgl/freetype/src/truetype/module.mk index 2d8d39d1f..5d44ac1f4 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/module.mk +++ b/lib/libesp32_lvgl/freetype/src/truetype/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/truetype/rules.mk b/lib/libesp32_lvgl/freetype/src/truetype/rules.mk index 2f6fecfc4..dde26de1c 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/truetype/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, @@ -33,8 +33,7 @@ TT_DRV_SRC := $(TT_DIR)/ttdriver.c \ $(TT_DIR)/ttgxvar.c \ $(TT_DIR)/ttinterp.c \ $(TT_DIR)/ttobjs.c \ - $(TT_DIR)/ttpload.c \ - $(TT_DIR)/ttsubpix.c + $(TT_DIR)/ttpload.c # TrueType driver headers # diff --git a/lib/libesp32_lvgl/freetype/src/truetype/truetype.c b/lib/libesp32_lvgl/freetype/src/truetype/truetype.c index 41b6808a8..fcc0ea334 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/truetype.c +++ b/lib/libesp32_lvgl/freetype/src/truetype/truetype.c @@ -4,7 +4,7 @@ * * FreeType TrueType driver component (body only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -24,7 +24,6 @@ #include "ttinterp.c" #include "ttobjs.c" /* object manager */ #include "ttpload.c" /* tables loader */ -#include "ttsubpix.c" /* END */ diff --git a/lib/libesp32_lvgl/freetype/src/truetype/ttdriver.c b/lib/libesp32_lvgl/freetype/src/truetype/ttdriver.c index bf830b141..d1496fec7 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/ttdriver.c +++ b/lib/libesp32_lvgl/freetype/src/truetype/ttdriver.c @@ -4,7 +4,7 @@ * * TrueType font driver implementation (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -57,7 +57,7 @@ * PROPERTY SERVICE * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) tt_property_set( FT_Module module, /* TT_Driver */ const char* property_name, const void* value, @@ -93,31 +93,36 @@ interpreter_version = *iv; } - if ( interpreter_version == TT_INTERPRETER_VERSION_35 -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - || interpreter_version == TT_INTERPRETER_VERSION_38 -#endif + switch ( interpreter_version ) + { + case TT_INTERPRETER_VERSION_35: + driver->interpreter_version = TT_INTERPRETER_VERSION_35; + break; + + case TT_INTERPRETER_VERSION_38: + case TT_INTERPRETER_VERSION_40: #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - || interpreter_version == TT_INTERPRETER_VERSION_40 + driver->interpreter_version = TT_INTERPRETER_VERSION_40; + break; #endif - ) - driver->interpreter_version = interpreter_version; - else + + default: error = FT_ERR( Unimplemented_Feature ); + } return error; } - FT_TRACE0(( "tt_property_set: missing property `%s'\n", + FT_TRACE2(( "tt_property_set: missing property `%s'\n", property_name )); return FT_THROW( Missing_Property ); } - static FT_Error + FT_CALLBACK_DEF( FT_Error ) tt_property_get( FT_Module module, /* TT_Driver */ const char* property_name, - const void* value ) + void* value ) { FT_Error error = FT_Err_Ok; TT_Driver driver = (TT_Driver)module; @@ -135,7 +140,7 @@ return error; } - FT_TRACE0(( "tt_property_get: missing property `%s'\n", + FT_TRACE2(( "tt_property_get: missing property `%s'\n", property_name )); return FT_THROW( Missing_Property ); } @@ -144,8 +149,8 @@ FT_DEFINE_SERVICE_PROPERTIESREC( tt_service_properties, - (FT_Properties_SetFunc)tt_property_set, /* set_property */ - (FT_Properties_GetFunc)tt_property_get /* get_property */ + tt_property_set, /* FT_Properties_SetFunc set_property */ + tt_property_get /* FT_Properties_GetFunc get_property */ ) @@ -198,35 +203,35 @@ * * They can be implemented by format-specific interfaces. */ - static FT_Error - tt_get_kerning( FT_Face ttface, /* TT_Face */ + FT_CALLBACK_DEF( FT_Error ) + tt_get_kerning( FT_Face face, /* TT_Face */ FT_UInt left_glyph, FT_UInt right_glyph, FT_Vector* kerning ) { - TT_Face face = (TT_Face)ttface; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + TT_Face ttface = (TT_Face)face; + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; kerning->x = 0; kerning->y = 0; if ( sfnt ) - kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph ); + kerning->x = sfnt->get_kerning( ttface, left_glyph, right_glyph ); return 0; } - static FT_Error - tt_get_advances( FT_Face ttface, + FT_CALLBACK_DEF( FT_Error ) + tt_get_advances( FT_Face face, /* TT_Face */ FT_UInt start, FT_UInt count, FT_Int32 flags, FT_Fixed *advances ) { FT_UInt nn; - TT_Face face = (TT_Face)ttface; + TT_Face ttface = (TT_Face)face; /* XXX: TODO: check for sbits */ @@ -235,8 +240,8 @@ { #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without VVAR table */ - if ( ( FT_IS_NAMED_INSTANCE( ttface ) || FT_IS_VARIATION( ttface ) ) && - !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) + if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && + !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif @@ -247,7 +252,7 @@ /* since we don't need `tsb', we use zero for `yMax' parameter */ - TT_Get_VMetrics( face, start + nn, 0, &tsb, &ah ); + TT_Get_VMetrics( ttface, start + nn, 0, &tsb, &ah ); advances[nn] = ah; } } @@ -255,8 +260,8 @@ { #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without HVAR table */ - if ( ( FT_IS_NAMED_INSTANCE( ttface ) || FT_IS_VARIATION( ttface ) ) && - !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) + if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && + !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif @@ -266,7 +271,7 @@ FT_UShort aw; - TT_Get_HMetrics( face, start + nn, &lsb, &aw ); + TT_Get_HMetrics( ttface, start + nn, &lsb, &aw ); advances[nn] = aw; } } @@ -290,7 +295,7 @@ #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - static FT_Error + FT_CALLBACK_DEF( FT_Error ) tt_size_select( FT_Size size, FT_ULong strike_index ) { @@ -306,7 +311,7 @@ /* use the scaled metrics, even when tt_size_reset fails */ FT_Select_Metrics( size->face, strike_index ); - tt_size_reset( ttsize, 0 ); /* ignore return value */ + tt_size_reset( ttsize ); /* ignore return value */ } else { @@ -327,7 +332,7 @@ #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) tt_size_request( FT_Size size, FT_Size_Request req ) { @@ -354,11 +359,20 @@ #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ - FT_Request_Metrics( size->face, req ); + { + FT_Error err = FT_Request_Metrics( size->face, req ); + + + if ( err ) + { + error = err; + goto Exit; + } + } if ( FT_IS_SCALABLE( size->face ) ) { - error = tt_size_reset( ttsize, 0 ); + error = tt_size_reset( ttsize ); #ifdef TT_USE_BYTECODE_INTERPRETER /* for the `MPS' bytecode instruction we need the point size */ @@ -382,6 +396,7 @@ #endif } + Exit: return error; } @@ -416,15 +431,15 @@ * @Return: * FreeType error code. 0 means success. */ - static FT_Error - tt_glyph_load( FT_GlyphSlot ttslot, /* TT_GlyphSlot */ - FT_Size ttsize, /* TT_Size */ + FT_CALLBACK_DEF( FT_Error ) + tt_glyph_load( FT_GlyphSlot slot, /* TT_GlyphSlot */ + FT_Size size, /* TT_Size */ FT_UInt glyph_index, FT_Int32 load_flags ) { - TT_GlyphSlot slot = (TT_GlyphSlot)ttslot; - TT_Size size = (TT_Size)ttsize; - FT_Face face = ttslot->face; + TT_GlyphSlot ttslot = (TT_GlyphSlot)slot; + TT_Size ttsize = (TT_Size)size; + FT_Face face = ttslot->face; FT_Error error; @@ -466,12 +481,12 @@ } /* use hinted metrics only if we load a glyph with hinting */ - size->metrics = ( load_flags & FT_LOAD_NO_HINTING ) - ? &ttsize->metrics - : &size->hinted_metrics; + ttsize->metrics = ( load_flags & FT_LOAD_NO_HINTING ) + ? &size->metrics + : &ttsize->hinted_metrics; /* now fill in the glyph slot with outline/bitmap/layered */ - error = TT_Load_Glyph( size, slot, glyph_index, load_flags ); + error = TT_Load_Glyph( ttsize, ttslot, glyph_index, load_flags ); /* force drop-out mode to 2 - irrelevant now */ /* slot->outline.dropout_mode = 2; */ @@ -497,34 +512,47 @@ FT_DEFINE_SERVICE_MULTIMASTERSREC( tt_service_gx_multi_masters, - (FT_Get_MM_Func) NULL, /* get_mm */ - (FT_Set_MM_Design_Func) NULL, /* set_mm_design */ - (FT_Set_MM_Blend_Func) TT_Set_MM_Blend, /* set_mm_blend */ - (FT_Get_MM_Blend_Func) TT_Get_MM_Blend, /* get_mm_blend */ - (FT_Get_MM_Var_Func) TT_Get_MM_Var, /* get_mm_var */ - (FT_Set_Var_Design_Func) TT_Set_Var_Design, /* set_var_design */ - (FT_Get_Var_Design_Func) TT_Get_Var_Design, /* get_var_design */ - (FT_Set_Instance_Func) TT_Set_Named_Instance, /* set_instance */ - (FT_Set_MM_WeightVector_Func)NULL, /* set_mm_weightvector */ - (FT_Get_MM_WeightVector_Func)NULL, /* get_mm_weightvector */ + NULL, /* FT_Get_MM_Func get_mm */ + NULL, /* FT_Set_MM_Design_Func set_mm_design */ + TT_Set_MM_Blend, /* FT_Set_MM_Blend_Func set_mm_blend */ + TT_Get_MM_Blend, /* FT_Get_MM_Blend_Func get_mm_blend */ + TT_Get_MM_Var, /* FT_Get_MM_Var_Func get_mm_var */ + TT_Set_Var_Design, /* FT_Set_Var_Design_Func set_var_design */ + TT_Get_Var_Design, /* FT_Get_Var_Design_Func get_var_design */ + TT_Set_Named_Instance, /* FT_Set_Named_Instance_Func set_named_instance */ + TT_Get_Default_Named_Instance, + /* FT_Get_Default_Named_Instance_Func get_default_named_instance */ + NULL, /* FT_Set_MM_WeightVector_Func set_mm_weightvector */ + NULL, /* FT_Get_MM_WeightVector_Func get_mm_weightvector */ - (FT_Get_Var_Blend_Func) tt_get_var_blend, /* get_var_blend */ - (FT_Done_Blend_Func) tt_done_blend /* done_blend */ + tt_construct_ps_name, /* FT_Construct_PS_Name_Func construct_ps_name */ + tt_var_load_delta_set_index_mapping, + /* FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map */ + tt_var_load_item_variation_store, + /* FT_Var_Load_Item_Var_Store_Func load_item_variation_store */ + tt_var_get_item_delta, /* FT_Var_Get_Item_Delta_Func get_item_delta */ + tt_var_done_item_variation_store, + /* FT_Var_Done_Item_Var_Store_Func done_item_variation_store */ + tt_var_done_delta_set_index_map, + /* FT_Var_Done_Delta_Set_Idx_Map_Func done_delta_set_index_map */ + tt_get_var_blend, /* FT_Get_Var_Blend_Func get_var_blend */ + tt_done_blend /* FT_Done_Blend_Func done_blend */ ) FT_DEFINE_SERVICE_METRICSVARIATIONSREC( tt_service_metrics_variations, - (FT_HAdvance_Adjust_Func)tt_hadvance_adjust, /* hadvance_adjust */ - (FT_LSB_Adjust_Func) NULL, /* lsb_adjust */ - (FT_RSB_Adjust_Func) NULL, /* rsb_adjust */ + tt_hadvance_adjust, /* FT_HAdvance_Adjust_Func hadvance_adjust */ + NULL, /* FT_LSB_Adjust_Func lsb_adjust */ + NULL, /* FT_RSB_Adjust_Func rsb_adjust */ - (FT_VAdvance_Adjust_Func)tt_vadvance_adjust, /* vadvance_adjust */ - (FT_TSB_Adjust_Func) NULL, /* tsb_adjust */ - (FT_BSB_Adjust_Func) NULL, /* bsb_adjust */ - (FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */ + tt_vadvance_adjust, /* FT_VAdvance_Adjust_Func vadvance_adjust */ + NULL, /* FT_TSB_Adjust_Func tsb_adjust */ + NULL, /* FT_BSB_Adjust_Func bsb_adjust */ + NULL, /* FT_VOrg_Adjust_Func vorg_adjust */ - (FT_Metrics_Adjust_Func) tt_apply_mvar /* metrics_adjust */ + tt_apply_mvar, /* FT_Metrics_Adjust_Func metrics_adjust */ + tt_size_reset_height /* FT_Size_Reset_Func size_reset */ ) #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ diff --git a/lib/libesp32_lvgl/freetype/src/truetype/ttdriver.h b/lib/libesp32_lvgl/freetype/src/truetype/ttdriver.h index ee1438eb6..757a66f42 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/ttdriver.h +++ b/lib/libesp32_lvgl/freetype/src/truetype/ttdriver.h @@ -4,7 +4,7 @@ * * High-level TrueType driver interface (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/truetype/tterrors.h b/lib/libesp32_lvgl/freetype/src/truetype/tterrors.h index efeafd3a1..008ee9985 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/tterrors.h +++ b/lib/libesp32_lvgl/freetype/src/truetype/tterrors.h @@ -4,7 +4,7 @@ * * TrueType error codes (specification only). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/truetype/ttgload.c b/lib/libesp32_lvgl/freetype/src/truetype/ttgload.c index 1dd319dcb..dc427e8a1 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/ttgload.c +++ b/lib/libesp32_lvgl/freetype/src/truetype/ttgload.c @@ -4,7 +4,7 @@ * * TrueType Glyph Loader (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -35,7 +35,6 @@ #endif #include "tterrors.h" -#include "ttsubpix.h" /************************************************************************** @@ -152,9 +151,6 @@ FT_UInt glyph_index ) { TT_Face face = loader->face; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); -#endif FT_Error error; FT_Stream stream = loader->stream; @@ -183,24 +179,17 @@ loader->top_bearing = top_bearing; loader->vadvance = advance_height; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 && - loader->exec ) +#ifdef FT_CONFIG_OPTION_INCREMENTAL + /* With the incremental interface, these values are set by */ + /* a call to `tt_get_metrics_incremental'. */ + if ( face->root.internal->incremental_interface == NULL ) +#endif { - loader->exec->sph_tweak_flags = 0; - - /* This may not be the right place for this, but it works... */ - /* Note that we have to unconditionally load the tweaks since */ - /* it is possible that glyphs individually switch ClearType's */ - /* backward compatibility mode on and off. */ - sph_set_tweaks( loader, glyph_index ); - } -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - - if ( !loader->linear_def ) - { - loader->linear_def = 1; - loader->linear = advance_width; + if ( !loader->linear_def ) + { + loader->linear_def = 1; + loader->linear = advance_width; + } } return FT_Err_Ok; @@ -210,8 +199,8 @@ #ifdef FT_CONFIG_OPTION_INCREMENTAL static void - tt_get_metrics_incr_overrides( TT_Loader loader, - FT_UInt glyph_index ) + tt_get_metrics_incremental( TT_Loader loader, + FT_UInt glyph_index ) { TT_Face face = loader->face; @@ -355,17 +344,16 @@ FT_Byte* p = load->cursor; FT_Byte* limit = load->limit; FT_GlyphLoader gloader = load->gloader; + FT_Outline* outline = &gloader->current.outline; FT_Int n_contours = load->n_contours; - FT_Outline* outline; - FT_UShort n_ins; FT_Int n_points; + FT_UShort n_ins; FT_Byte *flag, *flag_limit; FT_Byte c, count; FT_Vector *vec, *vec_limit; FT_Pos x, y; - FT_Short *cont, *cont_limit, prev_cont; - FT_Int xy_size = 0; + FT_Short *cont, *cont_limit, last; /* check that we can add the contours to the glyph */ @@ -373,40 +361,26 @@ if ( error ) goto Fail; + /* check space for contours array + instructions count */ + if ( n_contours >= 0xFFF || p + 2 * n_contours + 2 > limit ) + goto Invalid_Outline; + /* reading the contours' endpoints & number of points */ - cont = gloader->current.outline.contours; + cont = outline->contours; cont_limit = cont + n_contours; - /* check space for contours array + instructions count */ - if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit ) - goto Invalid_Outline; - - prev_cont = FT_NEXT_SHORT( p ); - - if ( n_contours > 0 ) - cont[0] = prev_cont; - - if ( prev_cont < 0 ) - goto Invalid_Outline; - - for ( cont++; cont < cont_limit; cont++ ) + last = -1; + for ( ; cont < cont_limit; cont++ ) { - cont[0] = FT_NEXT_SHORT( p ); - if ( cont[0] <= prev_cont ) - { - /* unordered contours: this is invalid */ + *cont = FT_NEXT_SHORT( p ); + + if ( *cont <= last ) goto Invalid_Outline; - } - prev_cont = cont[0]; + + last = *cont; } - n_points = 0; - if ( n_contours > 0 ) - { - n_points = cont[-1] + 1; - if ( n_points < 0 ) - goto Invalid_Outline; - } + n_points = last + 1; FT_TRACE5(( " # of points: %d\n", n_points )); @@ -415,59 +389,48 @@ if ( error ) goto Fail; - /* reading the bytecode instructions */ - load->glyph->control_len = 0; - load->glyph->control_data = NULL; - - if ( p + 2 > limit ) - goto Invalid_Outline; - + /* space checked above */ n_ins = FT_NEXT_USHORT( p ); FT_TRACE5(( " Instructions size: %u\n", n_ins )); + /* check instructions size */ + if ( p + n_ins > limit ) + { + FT_TRACE1(( "TT_Load_Simple_Glyph: excessive instruction count\n" )); + error = FT_THROW( Too_Many_Hints ); + goto Fail; + } + #ifdef TT_USE_BYTECODE_INTERPRETER if ( IS_HINTED( load->load_flags ) ) { - FT_ULong tmp; + TT_ExecContext exec = load->exec; + FT_Memory memory = exec->memory; - /* check instructions size */ - if ( ( limit - p ) < n_ins ) - { - FT_TRACE1(( "TT_Load_Simple_Glyph: instruction count mismatch\n" )); - error = FT_THROW( Too_Many_Hints ); - goto Fail; - } + if ( exec->glyphSize ) + FT_FREE( exec->glyphIns ); + exec->glyphSize = 0; /* we don't trust `maxSizeOfInstructions' in the `maxp' table */ - /* and thus update the bytecode array size by ourselves */ - - tmp = load->exec->glyphSize; - error = Update_Max( load->exec->memory, - &tmp, - sizeof ( FT_Byte ), - (void*)&load->exec->glyphIns, - n_ins ); - - load->exec->glyphSize = (FT_UShort)tmp; - if ( error ) - return error; - - load->glyph->control_len = n_ins; - load->glyph->control_data = load->exec->glyphIns; - + /* and thus allocate the bytecode array size by ourselves */ if ( n_ins ) - FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins ); + { + if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) ) + return error; + + FT_MEM_COPY( exec->glyphIns, p, (FT_Long)n_ins ); + + exec->glyphSize = n_ins; + } } #endif /* TT_USE_BYTECODE_INTERPRETER */ p += n_ins; - outline = &gloader->current.outline; - /* reading the point tags */ flag = (FT_Byte*)outline->tags; flag_limit = flag + n_points; @@ -505,9 +468,6 @@ flag = (FT_Byte*)outline->tags; x = 0; - if ( p + xy_size > limit ) - goto Invalid_Outline; - for ( ; vec < vec_limit; vec++, flag++ ) { FT_Pos delta = 0; @@ -537,7 +497,7 @@ /* reading the Y coordinates */ - vec = gloader->current.outline.points; + vec = outline->points; vec_limit = vec + n_points; flag = (FT_Byte*)outline->tags; y = 0; @@ -730,18 +690,20 @@ if ( subglyph->flags & WE_HAVE_A_SCALE ) FT_TRACE7(( " scaling: %f\n", - subglyph->transform.xx / 65536.0 )); + (double)subglyph->transform.xx / 65536 )); else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) FT_TRACE7(( " scaling: x=%f, y=%f\n", - subglyph->transform.xx / 65536.0, - subglyph->transform.yy / 65536.0 )); + (double)subglyph->transform.xx / 65536, + (double)subglyph->transform.yy / 65536 )); else if ( subglyph->flags & WE_HAVE_A_2X2 ) - FT_TRACE7(( " scaling: xx=%f, yx=%f\n" - " xy=%f, yy=%f\n", - subglyph->transform.xx / 65536.0, - subglyph->transform.yx / 65536.0, - subglyph->transform.xy / 65536.0, - subglyph->transform.yy / 65536.0 )); + { + FT_TRACE7(( " scaling: xx=%f, yx=%f\n", + (double)subglyph->transform.xx / 65536, + (double)subglyph->transform.yx / 65536 )); + FT_TRACE7(( " xy=%f, yy=%f\n", + (double)subglyph->transform.xy / 65536, + (double)subglyph->transform.yy / 65536 )); + } subglyph++; } @@ -792,7 +754,7 @@ FT_UInt start_point, FT_UInt start_contour ) { - zone->n_points = (FT_UShort)load->outline.n_points - + zone->n_points = (FT_UShort)load->outline.n_points + 4 - (FT_UShort)start_point; zone->n_contours = load->outline.n_contours - (FT_Short)start_contour; @@ -818,8 +780,7 @@ TT_Hint_Glyph( TT_Loader loader, FT_Bool is_composite ) { -#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \ - defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL TT_Face face = loader->face; TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); #endif @@ -827,35 +788,34 @@ TT_GlyphZone zone = &loader->zone; #ifdef TT_USE_BYTECODE_INTERPRETER - FT_Long n_ins; + TT_ExecContext exec = loader->exec; + FT_Long n_ins = exec->glyphSize; #else FT_UNUSED( is_composite ); #endif #ifdef TT_USE_BYTECODE_INTERPRETER - n_ins = loader->glyph->control_len; - /* save original point positions in `org' array */ if ( n_ins > 0 ) FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points ); /* Reset graphics state. */ - loader->exec->GS = loader->size->GS; + exec->GS = loader->size->GS; /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */ /* completely refer to the (already) hinted subglyphs. */ if ( is_composite ) { - loader->exec->metrics.x_scale = 1 << 16; - loader->exec->metrics.y_scale = 1 << 16; + exec->metrics.x_scale = 1 << 16; + exec->metrics.y_scale = 1 << 16; FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points ); } else { - loader->exec->metrics.x_scale = loader->size->metrics->x_scale; - loader->exec->metrics.y_scale = loader->size->metrics->y_scale; + exec->metrics.x_scale = loader->size->metrics->x_scale; + exec->metrics.y_scale = loader->size->metrics->y_scale; } #endif @@ -875,53 +835,37 @@ { FT_Error error; - FT_GlyphLoader gloader = loader->gloader; - FT_Outline current_outline = gloader->current.outline; + TT_Set_CodeRange( exec, tt_coderange_glyph, exec->glyphIns, n_ins ); - TT_Set_CodeRange( loader->exec, tt_coderange_glyph, - loader->exec->glyphIns, n_ins ); + exec->is_composite = is_composite; + exec->pts = *zone; - loader->exec->is_composite = is_composite; - loader->exec->pts = *zone; - - error = TT_Run_Context( loader->exec ); - if ( error && loader->exec->pedantic_hinting ) + error = TT_Run_Context( exec ); + if ( error && exec->pedantic_hinting ) return error; /* store drop-out mode in bits 5-7; set bit 2 also as a marker */ - current_outline.tags[0] |= - ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE; + loader->gloader->current.outline.tags[0] |= + ( exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE; } #endif -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL /* Save possibly modified glyph phantom points unless in v40 backward */ /* compatibility mode, where no movement on the x axis means no reason */ /* to change bearings or advance widths. */ - if ( !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && - loader->exec->backward_compatibility ) ) - { -#endif - loader->pp1 = zone->cur[zone->n_points - 4]; - loader->pp2 = zone->cur[zone->n_points - 3]; - loader->pp3 = zone->cur[zone->n_points - 2]; - loader->pp4 = zone->cur[zone->n_points - 1]; + #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - } + if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && + exec->backward_compatibility ) + return FT_Err_Ok; #endif -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) - { - if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN ) - FT_Outline_EmboldenXY( &loader->gloader->current.outline, -24, 0 ); - - else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN ) - FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 ); - } -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ + loader->pp1 = zone->cur[zone->n_points - 4]; + loader->pp2 = zone->cur[zone->n_points - 3]; + loader->pp3 = zone->cur[zone->n_points - 2]; + loader->pp4 = zone->cur[zone->n_points - 1]; return FT_Err_Ok; } @@ -940,10 +884,10 @@ static FT_Error TT_Process_Simple_Glyph( TT_Loader loader ) { - FT_GlyphLoader gloader = loader->gloader; - FT_Error error = FT_Err_Ok; - FT_Outline* outline; - FT_Int n_points; + FT_Error error = FT_Err_Ok; + FT_GlyphLoader gloader = loader->gloader; + FT_Outline* outline = &gloader->current.outline; + FT_Int n_points = outline->n_points; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_Memory memory = loader->face->root.memory; @@ -951,49 +895,25 @@ #endif - outline = &gloader->current.outline; - n_points = outline->n_points; - /* set phantom points */ - outline->points[n_points ] = loader->pp1; outline->points[n_points + 1] = loader->pp2; outline->points[n_points + 2] = loader->pp3; outline->points[n_points + 3] = loader->pp4; - outline->tags[n_points ] = 0; - outline->tags[n_points + 1] = 0; - outline->tags[n_points + 2] = 0; - outline->tags[n_points + 3] = 0; - n_points += 4; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) ) { - if ( FT_NEW_ARRAY( unrounded, n_points ) ) + if ( FT_QNEW_ARRAY( unrounded, n_points ) ) goto Exit; /* Deltas apply to the unscaled data. */ - error = TT_Vary_Apply_Glyph_Deltas( loader->face, - loader->glyph_index, + error = TT_Vary_Apply_Glyph_Deltas( loader, outline, - unrounded, - (FT_UInt)n_points ); - - /* recalculate linear horizontal and vertical advances */ - /* if we don't have HVAR and VVAR, respectively */ - - /* XXX: change all FreeType modules to store `linear' and `vadvance' */ - /* in 26.6 format before the `base' module scales them to 16.16 */ - if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) - loader->linear = FT_PIX_ROUND( unrounded[n_points - 3].x - - unrounded[n_points - 4].x ) / 64; - if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) - loader->vadvance = FT_PIX_ROUND( unrounded[n_points - 1].x - - unrounded[n_points - 2].x ) / 64; - + unrounded ); if ( error ) goto Exit; } @@ -1005,20 +925,10 @@ tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 ); FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur, - loader->zone.n_points + 4 ); + loader->zone.n_points ); } { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - TT_Face face = loader->face; - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); - - FT_String* family = face->root.family_name; - FT_UInt ppem = loader->size->metrics->x_ppem; - FT_String* style = face->root.style_name; - FT_UInt x_scale_factor = 1000; -#endif - FT_Vector* vec = outline->points; FT_Vector* limit = outline->points + n_points; @@ -1028,52 +938,6 @@ FT_Bool do_scale = FALSE; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) - { - /* scale, but only if enabled and only if TT hinting is being used */ - if ( IS_HINTED( loader->load_flags ) ) - x_scale_factor = sph_test_tweak_x_scaling( face, - family, - ppem, - style, - loader->glyph_index ); - /* scale the glyph */ - if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 || - x_scale_factor != 1000 ) - { - x_scale = FT_MulDiv( loader->size->metrics->x_scale, - (FT_Long)x_scale_factor, 1000 ); - y_scale = loader->size->metrics->y_scale; - - /* compensate for any scaling by de/emboldening; */ - /* the amount was determined via experimentation */ - if ( x_scale_factor != 1000 && ppem > 11 ) - { -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_Vector* orig_points = outline->points; - - - if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) ) - outline->points = unrounded; -#endif - FT_Outline_EmboldenXY( outline, - FT_MulFix( 1280 * ppem, - 1000 - x_scale_factor ), - 0 ); -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) ) - outline->points = orig_points; -#endif - } - do_scale = TRUE; - } - } - else - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - { /* scale the glyph */ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) @@ -1095,8 +959,8 @@ for ( ; vec < limit; vec++, u++ ) { - vec->x = ( FT_MulFix( u->x, x_scale ) + 32 ) >> 6; - vec->y = ( FT_MulFix( u->y, y_scale ) + 32 ) >> 6; + vec->x = ADD_LONG( FT_MulFix( u->x, x_scale ), 32 ) >> 6; + vec->y = ADD_LONG( FT_MulFix( u->y, y_scale ), 32 ) >> 6; } } else @@ -1147,11 +1011,7 @@ } if ( IS_HINTED( loader->load_flags ) ) - { - loader->zone.n_points += 4; - error = TT_Hint_Glyph( loader, 0 ); - } #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT Exit: @@ -1219,8 +1079,8 @@ p1 = gloader->base.outline.points + k; p2 = gloader->base.outline.points + l; - x = p1->x - p2->x; - y = p1->y - p2->y; + x = SUB_LONG( p1->x, p2->x ); + y = SUB_LONG( p1->y, p2->y ); } else { @@ -1346,12 +1206,12 @@ FT_UInt start_contour ) { FT_Error error; - FT_Outline* outline; + FT_Outline* outline = &loader->gloader->base.outline; + FT_Stream stream = loader->stream; + FT_UShort n_ins; FT_UInt i; - outline = &loader->gloader->base.outline; - /* make room for phantom points */ error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader, outline->n_points + 4, @@ -1364,60 +1224,43 @@ outline->points[outline->n_points + 2] = loader->pp3; outline->points[outline->n_points + 3] = loader->pp4; - outline->tags[outline->n_points ] = 0; - outline->tags[outline->n_points + 1] = 0; - outline->tags[outline->n_points + 2] = 0; - outline->tags[outline->n_points + 3] = 0; - #ifdef TT_USE_BYTECODE_INTERPRETER { - FT_Stream stream = loader->stream; - FT_UShort n_ins, max_ins; - FT_ULong tmp; + TT_ExecContext exec = loader->exec; + FT_Memory memory = exec->memory; + if ( exec->glyphSize ) + FT_FREE( exec->glyphIns ); + exec->glyphSize = 0; + /* TT_Load_Composite_Glyph only gives us the offset of instructions */ /* so we read them here */ if ( FT_STREAM_SEEK( loader->ins_pos ) || FT_READ_USHORT( n_ins ) ) return error; - FT_TRACE5(( " Instructions size = %d\n", n_ins )); + FT_TRACE5(( " Instructions size = %hu\n", n_ins )); - /* check it */ - max_ins = loader->face->max_profile.maxSizeOfInstructions; - if ( n_ins > max_ins ) - { - /* don't trust `maxSizeOfInstructions'; */ - /* only do a rough safety check */ - if ( (FT_Int)n_ins > loader->byte_len ) - { - FT_TRACE1(( "TT_Process_Composite_Glyph:" - " too many instructions (%d) for glyph with length %d\n", - n_ins, loader->byte_len )); - return FT_THROW( Too_Many_Hints ); - } - - tmp = loader->exec->glyphSize; - error = Update_Max( loader->exec->memory, - &tmp, - sizeof ( FT_Byte ), - (void*)&loader->exec->glyphIns, - n_ins ); - - loader->exec->glyphSize = (FT_UShort)tmp; - if ( error ) - return error; - } - else if ( n_ins == 0 ) + if ( !n_ins ) return FT_Err_Ok; - if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) ) + /* don't trust `maxSizeOfInstructions'; */ + /* only do a rough safety check */ + if ( n_ins > loader->byte_len ) + { + FT_TRACE1(( "TT_Process_Composite_Glyph:" + " too many instructions (%hu) for glyph with length %u\n", + n_ins, loader->byte_len )); + return FT_THROW( Too_Many_Hints ); + } + + if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) || + FT_STREAM_READ( exec->glyphIns, n_ins ) ) return error; - loader->glyph->control_data = loader->exec->glyphIns; - loader->glyph->control_len = n_ins; + exec->glyphSize = n_ins; } #endif @@ -1427,11 +1270,9 @@ /* Some points are likely touched during execution of */ /* instructions on components. So let's untouch them. */ - for ( i = 0; i < loader->zone.n_points; i++ ) + for ( i = 0; i < loader->zone.n_points - 4U; i++ ) loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH; - loader->zone.n_points += 4; - return TT_Hint_Glyph( loader, 1 ); } @@ -1523,45 +1364,31 @@ static void tt_loader_set_pp( TT_Loader loader ) { - FT_Bool subpixel_hinting = 0; - FT_Bool grayscale = 0; - FT_Bool use_aw_2 = 0; - -#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face ); -#endif - - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) - { - subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting - : 0; - grayscale = loader->exec ? loader->exec->grayscale - : 0; - } -#endif -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) - { - subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting_lean - : 0; - grayscale = loader->exec ? loader->exec->grayscale_cleartype - : 0; - } -#endif - - use_aw_2 = FT_BOOL( subpixel_hinting && grayscale ); - loader->pp1.x = loader->bbox.xMin - loader->left_bearing; loader->pp1.y = 0; loader->pp2.x = loader->pp1.x + loader->advance; loader->pp2.y = 0; - loader->pp3.x = use_aw_2 ? loader->advance / 2 : 0; + loader->pp3.x = 0; loader->pp3.y = loader->bbox.yMax + loader->top_bearing; - loader->pp4.x = use_aw_2 ? loader->advance / 2 : 0; + loader->pp4.x = 0; loader->pp4.y = loader->pp3.y - loader->vadvance; + +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + { + TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face ); + + + if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && + loader->exec && + loader->exec->subpixel_hinting_lean && + loader->exec->grayscale_cleartype ) + { + loader->pp3.x = loader->advance / 2; + loader->pp4.x = loader->advance / 2; + } + } +#endif } @@ -1677,16 +1504,21 @@ FT_ZERO( &inc_stream ); FT_Stream_OpenMemory( &inc_stream, glyph_data.pointer, - (FT_ULong)glyph_data.length ); + glyph_data.length ); loader->stream = &inc_stream; } else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ + { + FT_ULong len; - offset = tt_face_get_location( face, glyph_index, - (FT_UInt*)&loader->byte_len ); + + offset = tt_face_get_location( FT_FACE( face ), glyph_index, &len ); + + loader->byte_len = (FT_UInt)len; + } if ( loader->byte_len > 0 ) { @@ -1705,7 +1537,7 @@ error = face->access_glyph_frame( loader, glyph_index, face->glyf_offset + offset, - (FT_UInt)loader->byte_len ); + loader->byte_len ); if ( error ) goto Exit; @@ -1739,13 +1571,11 @@ if ( loader->byte_len == 0 || loader->n_contours == 0 ) { - /* must initialize points before (possibly) overriding */ - /* glyph metrics from the incremental interface */ +#ifdef FT_CONFIG_OPTION_INCREMENTAL + tt_get_metrics_incremental( loader, glyph_index ); +#endif tt_loader_set_pp( loader ); -#ifdef FT_CONFIG_OPTION_INCREMENTAL - tt_get_metrics_incr_overrides( loader, glyph_index ); -#endif #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT @@ -1755,57 +1585,29 @@ /* a small outline structure with four elements for */ /* communication with `TT_Vary_Apply_Glyph_Deltas' */ FT_Vector points[4]; - char tags[4] = { 1, 1, 1, 1 }; - short contours[4] = { 0, 1, 2, 3 }; FT_Outline outline; /* unrounded values */ FT_Vector unrounded[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} }; - points[0].x = loader->pp1.x; - points[0].y = loader->pp1.y; - points[1].x = loader->pp2.x; - points[1].y = loader->pp2.y; + points[0] = loader->pp1; + points[1] = loader->pp2; + points[2] = loader->pp3; + points[3] = loader->pp4; - points[2].x = loader->pp3.x; - points[2].y = loader->pp3.y; - points[3].x = loader->pp4.x; - points[3].y = loader->pp4.y; - - outline.n_points = 4; - outline.n_contours = 4; + outline.n_points = 0; + outline.n_contours = 0; outline.points = points; - outline.tags = tags; - outline.contours = contours; + outline.tags = NULL; + outline.contours = NULL; /* this must be done before scaling */ - error = TT_Vary_Apply_Glyph_Deltas( loader->face, - glyph_index, + error = TT_Vary_Apply_Glyph_Deltas( loader, &outline, - unrounded, - (FT_UInt)outline.n_points ); + unrounded ); if ( error ) goto Exit; - - loader->pp1.x = points[0].x; - loader->pp1.y = points[0].y; - loader->pp2.x = points[1].x; - loader->pp2.y = points[1].y; - - loader->pp3.x = points[2].x; - loader->pp3.y = points[2].y; - loader->pp4.x = points[3].x; - loader->pp4.y = points[3].y; - - /* recalculate linear horizontal and vertical advances */ - /* if we don't have HVAR and VVAR, respectively */ - if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) - loader->linear = FT_PIX_ROUND( unrounded[1].x - - unrounded[0].x ) / 64; - if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) - loader->vadvance = FT_PIX_ROUND( unrounded[3].x - - unrounded[2].x ) / 64; } #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ @@ -1828,13 +1630,11 @@ goto Exit; } - /* must initialize phantom points before (possibly) overriding */ - /* glyph metrics from the incremental interface */ +#ifdef FT_CONFIG_OPTION_INCREMENTAL + tt_get_metrics_incremental( loader, glyph_index ); +#endif tt_loader_set_pp( loader ); -#ifdef FT_CONFIG_OPTION_INCREMENTAL - tt_get_metrics_incr_overrides( loader, glyph_index ); -#endif /***********************************************************************/ /***********************************************************************/ @@ -1844,7 +1644,7 @@ /* (which consists of 10 bytes) */ error = face->access_glyph_frame( loader, glyph_index, face->glyf_offset + offset + 10, - (FT_UInt)loader->byte_len - 10 ); + loader->byte_len - 10 ); if ( error ) goto Exit; @@ -1898,7 +1698,7 @@ /* clear the nodes filled by sibling chains */ node = ft_list_get_node_at( &loader->composites, recurse_count ); for ( node2 = node; node2; node2 = node2->next ) - node2->data = (void*)FT_ULONG_MAX; + node2->data = (void*)-1; /* check whether we already have a composite glyph with this index */ if ( FT_List_Find( &loader->composites, @@ -1915,7 +1715,7 @@ else { - if ( FT_NEW( node ) ) + if ( FT_QNEW( node ) ) goto Exit; node->data = FT_UINT_TO_POINTER( glyph_index ); FT_List_Add( &loader->composites, node ); @@ -1944,10 +1744,7 @@ short i, limit; FT_SubGlyph subglyph; - FT_Outline outline; - FT_Vector* points = NULL; - char* tags = NULL; - short* contours = NULL; + FT_Outline outline = { 0, 0, NULL, NULL, NULL, 0 }; FT_Vector* unrounded = NULL; @@ -1955,19 +1752,14 @@ /* construct an outline structure for */ /* communication with `TT_Vary_Apply_Glyph_Deltas' */ - outline.n_points = (short)( gloader->current.num_subglyphs + 4 ); - outline.n_contours = outline.n_points; - - outline.points = NULL; - outline.tags = NULL; - outline.contours = NULL; - - if ( FT_NEW_ARRAY( points, outline.n_points ) || - FT_NEW_ARRAY( tags, outline.n_points ) || - FT_NEW_ARRAY( contours, outline.n_points ) || - FT_NEW_ARRAY( unrounded, outline.n_points ) ) + if ( FT_QNEW_ARRAY( outline.points, limit + 4 ) || + FT_QNEW_ARRAY( outline.tags, limit ) || + FT_QNEW_ARRAY( outline.contours, limit ) || + FT_QNEW_ARRAY( unrounded, limit + 4 ) ) goto Exit1; + outline.n_contours = outline.n_points = limit; + subglyph = gloader->current.subglyphs; for ( i = 0; i < limit; i++, subglyph++ ) @@ -1975,47 +1767,22 @@ /* applying deltas for anchor points doesn't make sense, */ /* but we don't have to specially check this since */ /* unused delta values are zero anyways */ - points[i].x = subglyph->arg1; - points[i].y = subglyph->arg2; - tags[i] = 1; - contours[i] = i; + outline.points[i].x = subglyph->arg1; + outline.points[i].y = subglyph->arg2; + outline.tags[i] = ON_CURVE_POINT; + outline.contours[i] = i; } - points[i].x = loader->pp1.x; - points[i].y = loader->pp1.y; - tags[i] = 1; - contours[i] = i; - - i++; - points[i].x = loader->pp2.x; - points[i].y = loader->pp2.y; - tags[i] = 1; - contours[i] = i; - - i++; - points[i].x = loader->pp3.x; - points[i].y = loader->pp3.y; - tags[i] = 1; - contours[i] = i; - - i++; - points[i].x = loader->pp4.x; - points[i].y = loader->pp4.y; - tags[i] = 1; - contours[i] = i; - - outline.points = points; - outline.tags = tags; - outline.contours = contours; + outline.points[i++] = loader->pp1; + outline.points[i++] = loader->pp2; + outline.points[i++] = loader->pp3; + outline.points[i ] = loader->pp4; /* this call provides additional offsets */ /* for each component's translation */ - if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas( - face, - glyph_index, - &outline, - unrounded, - (FT_UInt)outline.n_points ) ) ) + if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas( loader, + &outline, + unrounded ) ) ) goto Exit1; subglyph = gloader->current.subglyphs; @@ -2024,32 +1791,11 @@ { if ( subglyph->flags & ARGS_ARE_XY_VALUES ) { - subglyph->arg1 = (FT_Int16)points[i].x; - subglyph->arg2 = (FT_Int16)points[i].y; + subglyph->arg1 = (FT_Int16)outline.points[i].x; + subglyph->arg2 = (FT_Int16)outline.points[i].y; } } - loader->pp1.x = points[i + 0].x; - loader->pp1.y = points[i + 0].y; - loader->pp2.x = points[i + 1].x; - loader->pp2.y = points[i + 1].y; - - loader->pp3.x = points[i + 2].x; - loader->pp3.y = points[i + 2].y; - loader->pp4.x = points[i + 3].x; - loader->pp4.y = points[i + 3].y; - - /* recalculate linear horizontal and vertical advances */ - /* if we don't have HVAR and VVAR, respectively */ - if ( !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) - loader->linear = - FT_PIX_ROUND( unrounded[outline.n_points - 3].x - - unrounded[outline.n_points - 4].x ) / 64; - if ( !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) - loader->vadvance = - FT_PIX_ROUND( unrounded[outline.n_points - 1].x - - unrounded[outline.n_points - 2].x ) / 64; - Exit1: FT_FREE( outline.points ); FT_FREE( outline.tags ); @@ -2100,7 +1846,7 @@ FT_UInt num_base_subgs = gloader->base.num_subglyphs; FT_Stream old_stream = loader->stream; - FT_Int old_byte_len = loader->byte_len; + FT_UInt old_byte_len = loader->byte_len; FT_GlyphLoader_Add( gloader ); @@ -2225,16 +1971,11 @@ compute_glyph_metrics( TT_Loader loader, FT_UInt glyph_index ) { - TT_Face face = loader->face; -#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \ - defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); -#endif - + TT_Face face = loader->face; + TT_Size size = loader->size; + TT_GlyphSlot glyph = loader->glyph; FT_BBox bbox; FT_Fixed y_scale; - TT_GlyphSlot glyph = loader->glyph; - TT_Size size = loader->size; y_scale = 0x10000L; @@ -2252,53 +1993,10 @@ glyph->metrics.horiBearingX = bbox.xMin; glyph->metrics.horiBearingY = bbox.yMax; - glyph->metrics.horiAdvance = SUB_LONG(loader->pp2.x, loader->pp1.x); - - /* Adjust advance width to the value contained in the hdmx table */ - /* unless FT_LOAD_COMPUTE_METRICS is set or backward compatibility */ - /* mode of the v40 interpreter is active. See `ttinterp.h' for */ - /* details on backward compatibility mode. */ - if ( -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && - ( loader->exec && loader->exec->backward_compatibility ) ) && -#endif - !face->postscript.isFixedPitch && - IS_HINTED( loader->load_flags ) && - !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) ) - { - FT_Byte* widthp; - - - widthp = tt_face_get_device_metrics( face, - size->metrics->x_ppem, - glyph_index ); - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) - { - FT_Bool ignore_x_mode; - - - ignore_x_mode = FT_BOOL( FT_LOAD_TARGET_MODE( loader->load_flags ) != - FT_RENDER_MODE_MONO ); - - if ( widthp && - ( ( ignore_x_mode && loader->exec->compatible_widths ) || - !ignore_x_mode || - SPH_OPTION_BITMAP_WIDTHS ) ) - glyph->metrics.horiAdvance = *widthp * 64; - } - else - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - - { - if ( widthp ) - glyph->metrics.horiAdvance = *widthp * 64; - } - } + if ( loader->widthp ) + glyph->metrics.horiAdvance = loader->widthp[glyph_index] * 64; + else + glyph->metrics.horiAdvance = SUB_LONG( loader->pp2.x, loader->pp1.x ); /* set glyph dimensions */ glyph->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin ); @@ -2415,17 +2113,13 @@ FT_UInt glyph_index, FT_Int32 load_flags ) { - TT_Face face; - SFNT_Service sfnt; - FT_Stream stream; + TT_Face face = (TT_Face)glyph->face; + SFNT_Service sfnt = (SFNT_Service)face->sfnt; + FT_Stream stream = face->root.stream; FT_Error error; TT_SBit_MetricsRec sbit_metrics; - face = (TT_Face)glyph->face; - sfnt = (SFNT_Service)face->sfnt; - stream = face->root.stream; - error = sfnt->load_sbit_image( face, size->strike_index, glyph_index, @@ -2476,22 +2170,18 @@ FT_Int32 load_flags, FT_Bool glyf_table_only ) { - TT_Face face; - FT_Stream stream; + TT_Face face = (TT_Face)glyph->face; + FT_Stream stream = face->root.stream; #ifdef TT_USE_BYTECODE_INTERPRETER FT_Error error; FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); -#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \ - defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face ); +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( glyph->face ); #endif #endif - face = (TT_Face)glyph->face; - stream = face->root.stream; - FT_ZERO( loader ); #ifdef TT_USE_BYTECODE_INTERPRETER @@ -2506,20 +2196,6 @@ FT_Bool grayscale_cleartype; #endif -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - FT_Bool subpixel_hinting = FALSE; - -#if 0 - /* not used yet */ - FT_Bool compatible_widths; - FT_Bool symmetrical_smoothing; - FT_Bool bgr; - FT_Bool vertical_lcd; - FT_Bool subpixel_positioned; - FT_Bool gray_cleartype; -#endif -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - FT_Bool reexecute = FALSE; @@ -2539,6 +2215,9 @@ if ( !exec ) return FT_THROW( Could_Not_Find_Context ); + grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != + FT_RENDER_MODE_MONO ); + #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) { @@ -2555,6 +2234,7 @@ FT_BOOL( subpixel_hinting_lean && ( load_flags & FT_LOAD_TARGET_LCD_V ) ); + grayscale = FT_BOOL( grayscale && !subpixel_hinting_lean ); } else { @@ -2564,111 +2244,11 @@ } #endif -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) - { - subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) != - FT_RENDER_MODE_MONO ) && - SPH_OPTION_SET_SUBPIXEL ); - - if ( subpixel_hinting ) - grayscale = FALSE; - else if ( SPH_OPTION_SET_GRAYSCALE ) - { - grayscale = TRUE; - subpixel_hinting = FALSE; - } - else - grayscale = FALSE; - - if ( FT_IS_TRICKY( glyph->face ) ) - subpixel_hinting = FALSE; - - exec->ignore_x_mode = subpixel_hinting || grayscale; - exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; - if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) - exec->rasterizer_version = TT_INTERPRETER_VERSION_35; - -#if 1 - exec->compatible_widths = SPH_OPTION_SET_COMPATIBLE_WIDTHS; - exec->symmetrical_smoothing = TRUE; - exec->bgr = FALSE; - exec->vertical_lcd = FALSE; - exec->subpixel_positioned = TRUE; - exec->gray_cleartype = FALSE; -#else /* 0 */ - exec->compatible_widths = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_COMPATIBLE_WIDTHS ); - exec->symmetrical_smoothing = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_SYMMETRICAL_SMOOTHING ); - exec->bgr = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_BGR ); - exec->vertical_lcd = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_VERTICAL_LCD ); - exec->subpixel_positioned = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_SUBPIXEL_POSITIONED ); - exec->gray_cleartype = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - TT_LOAD_GRAY_CLEARTYPE ); -#endif /* 0 */ - - } - else - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) - grayscale = FT_BOOL( !subpixel_hinting_lean && - FT_LOAD_TARGET_MODE( load_flags ) != - FT_RENDER_MODE_MONO ); - else -#endif - grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - FT_RENDER_MODE_MONO ); - error = TT_Load_Context( exec, face, size ); if ( error ) return error; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) { - /* a change from mono to subpixel rendering (and vice versa) */ - /* requires a re-execution of the CVT program */ - if ( subpixel_hinting != exec->subpixel_hinting ) - { - FT_TRACE4(( "tt_loader_init: subpixel hinting change," - " re-executing `prep' table\n" )); - - exec->subpixel_hinting = subpixel_hinting; - reexecute = TRUE; - } - - /* a change from mono to grayscale rendering (and vice versa) */ - /* requires a re-execution of the CVT program */ - if ( grayscale != exec->grayscale ) - { - FT_TRACE4(( "tt_loader_init: grayscale hinting change," - " re-executing `prep' table\n" )); - - exec->grayscale = grayscale; - reexecute = TRUE; - } - } - else - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - - { - #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) { @@ -2713,6 +2293,9 @@ error = tt_size_run_prep( size, pedantic ); if ( error ) return error; + error = TT_Load_Context( exec, face, size ); + if ( error ) + return error; } /* check whether the cvt program has disabled hinting */ @@ -2723,17 +2306,48 @@ if ( exec->GS.instruct_control & 2 ) exec->GS = tt_default_graphics_state; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* check whether we have a font hinted for ClearType -- */ - /* note that this flag can also be modified in a glyph's bytecode */ - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 && - exec->GS.instruct_control & 4 ) - exec->ignore_x_mode = 0; -#endif +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* + * Toggle backward compatibility according to what font wants, except + * when + * + * 1) we have a `tricky' font that heavily relies on the interpreter to + * render glyphs correctly, for example DFKai-SB, or + * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested. + * + * In those cases, backward compatibility needs to be turned off to get + * correct rendering. The rendering is then completely up to the + * font's programming. + * + */ + if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && + subpixel_hinting_lean && + !FT_IS_TRICKY( glyph->face ) ) + exec->backward_compatibility = !( exec->GS.instruct_control & 4 ); + else + exec->backward_compatibility = FALSE; +#endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */ exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); loader->exec = exec; loader->instructions = exec->glyphIns; + + /* Use the hdmx table if any unless FT_LOAD_COMPUTE_METRICS */ + /* is set or backward compatibility mode of the v38 or v40 */ + /* interpreters is active. See `ttinterp.h' for details on */ + /* backward compatibility mode. */ + if ( IS_HINTED( loader->load_flags ) && + !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) && +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && + exec->backward_compatibility ) && +#endif + !face->postscript.isFixedPitch ) + { + loader->widthp = size->widthp; + } + else + loader->widthp = NULL; } #endif /* TT_USE_BYTECODE_INTERPRETER */ @@ -2781,11 +2395,12 @@ * A function used to load a single glyph within a given glyph slot, * for a given size. * - * @Input: + * @InOut: * glyph :: * A handle to a target slot object where the glyph * will be loaded. * + * @Input: * size :: * A handle to the source face size at which the glyph * must be scaled/loaded. @@ -2809,6 +2424,7 @@ FT_UInt glyph_index, FT_Int32 load_flags ) { + TT_Face face = (TT_Face)glyph->face; FT_Error error; TT_LoaderRec loader; @@ -2833,8 +2449,6 @@ /* if we have a bitmap-only font, return an empty glyph */ if ( !FT_IS_SCALABLE( glyph->face ) ) { - TT_Face face = (TT_Face)glyph->face; - FT_Short left_bearing = 0; FT_Short top_bearing = 0; @@ -2890,7 +2504,8 @@ } else { - if ( FT_IS_SCALABLE( glyph->face ) ) + if ( FT_IS_SCALABLE( glyph->face ) || + FT_HAS_SBIX( glyph->face ) ) { /* for the bbox we need the header only */ (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE ); @@ -2899,6 +2514,35 @@ glyph->linearHoriAdvance = loader.linear; glyph->linearVertAdvance = loader.vadvance; + /* Bitmaps from the 'sbix' table need special treatment: */ + /* if there is a glyph contour, the bitmap origin must be */ + /* shifted to be relative to the lower left corner of the */ + /* glyph bounding box, also taking the left-side bearing */ + /* (or top bearing) into account. */ + if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX && + loader.n_contours > 0 ) + { + FT_Int bitmap_left; + FT_Int bitmap_top; + + + if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) + { + /* This is a guess, since Apple's CoreText engine doesn't */ + /* really do vertical typesetting. */ + bitmap_left = loader.bbox.xMin; + bitmap_top = loader.top_bearing; + } + else + { + bitmap_left = loader.left_bearing; + bitmap_top = loader.bbox.yMin; + } + + glyph->bitmap_left += FT_MulFix( bitmap_left, x_scale ) >> 6; + glyph->bitmap_top += FT_MulFix( bitmap_top, y_scale ) >> 6; + } + /* sanity checks: if `xxxAdvance' in the sbit metric */ /* structure isn't set, use `linearXXXAdvance' */ if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance ) @@ -2913,6 +2557,12 @@ } } + if ( load_flags & FT_LOAD_SBITS_ONLY ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */ @@ -2922,16 +2572,79 @@ goto Exit; } - if ( load_flags & FT_LOAD_SBITS_ONLY ) +#ifdef FT_CONFIG_OPTION_SVG + + /* check for OT-SVG */ + if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 && + ( load_flags & FT_LOAD_COLOR ) && + face->svg ) + { + SFNT_Service sfnt = (SFNT_Service)face->sfnt; + + + FT_TRACE3(( "Trying to load SVG glyph\n" )); + + error = sfnt->load_svg_doc( glyph, glyph_index ); + if ( !error ) + { + FT_Fixed x_scale = size->root.metrics.x_scale; + FT_Fixed y_scale = size->root.metrics.y_scale; + + FT_Short leftBearing; + FT_Short topBearing; + FT_UShort advanceX; + FT_UShort advanceY; + + + FT_TRACE3(( "Successfully loaded SVG glyph\n" )); + + glyph->format = FT_GLYPH_FORMAT_SVG; + + sfnt->get_metrics( face, + FALSE, + glyph_index, + &leftBearing, + &advanceX ); + sfnt->get_metrics( face, + TRUE, + glyph_index, + &topBearing, + &advanceY ); + + glyph->linearHoriAdvance = advanceX; + glyph->linearVertAdvance = advanceY; + + glyph->metrics.horiAdvance = FT_MulFix( advanceX, x_scale ); + glyph->metrics.vertAdvance = FT_MulFix( advanceY, y_scale ); + + return error; + } + + FT_TRACE3(( "Failed to load SVG glyph\n" )); + } + + /* return immediately if we only want SVG glyphs */ + if ( load_flags & FT_LOAD_SVG_ONLY ) { error = FT_THROW( Invalid_Argument ); goto Exit; } +#endif /* FT_CONFIG_OPTION_SVG */ + error = tt_loader_init( &loader, size, glyph, load_flags, FALSE ); if ( error ) goto Exit; + /* done if we are only interested in the `hdmx` advance */ + if ( load_flags & FT_LOAD_ADVANCE_ONLY && + !( load_flags & FT_LOAD_VERTICAL_LAYOUT ) && + loader.widthp ) + { + glyph->metrics.horiAdvance = loader.widthp[glyph_index] * 64; + goto Done; + } + glyph->format = FT_GLYPH_FORMAT_OUTLINE; glyph->num_subglyphs = 0; glyph->outline.flags = 0; @@ -2962,6 +2675,9 @@ if ( IS_HINTED( load_flags ) ) { + glyph->control_data = loader.exec->glyphIns; + glyph->control_len = loader.exec->glyphSize; + if ( loader.exec->GS.scan_control ) { /* convert scan conversion mode to FT_OUTLINE_XXX flags */ @@ -3010,6 +2726,7 @@ glyph->outline.n_points, glyph->outline.flags )); + Done: tt_loader_done( &loader ); Exit: diff --git a/lib/libesp32_lvgl/freetype/src/truetype/ttgload.h b/lib/libesp32_lvgl/freetype/src/truetype/ttgload.h index 8f72cd558..f18637dce 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/ttgload.h +++ b/lib/libesp32_lvgl/freetype/src/truetype/ttgload.h @@ -4,7 +4,7 @@ * * TrueType Glyph Loader (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/truetype/ttgxvar.c b/lib/libesp32_lvgl/freetype/src/truetype/ttgxvar.c index b462263de..ad4f266b2 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/ttgxvar.c +++ b/lib/libesp32_lvgl/freetype/src/truetype/ttgxvar.c @@ -4,7 +4,7 @@ * * TrueType GX Font Variation loader * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. * * This file is part of the FreeType project, and may only be used, @@ -42,8 +42,10 @@ #include #include #include FT_CONFIG_CONFIG_H +#include #include #include +#include #include #include #include @@ -151,9 +153,7 @@ FT_UInt i, j; FT_UShort first; FT_Memory memory = stream->memory; - FT_Error error = FT_Err_Ok; - - FT_UNUSED( error ); + FT_Error error; *point_cnt = 0; @@ -178,7 +178,7 @@ /* in the nested loops below we increase `i' twice; */ /* it is faster to simply allocate one more slot */ /* than to add another test within the loop */ - if ( FT_NEW_ARRAY( points, n + 1 ) ) + if ( FT_QNEW_ARRAY( points, n + 1 ) ) return NULL; *point_cnt = n; @@ -264,55 +264,78 @@ FT_Fixed *deltas = NULL; FT_UInt runcnt, cnt; FT_UInt i, j; + FT_UInt bytes_used; FT_Memory memory = stream->memory; - FT_Error error = FT_Err_Ok; - - FT_UNUSED( error ); + FT_Error error; - if ( delta_cnt > size ) - { - FT_TRACE1(( "ft_var_readpackeddeltas: number of points too large\n" )); - return NULL; - } - - if ( FT_NEW_ARRAY( deltas, delta_cnt ) ) + if ( FT_QNEW_ARRAY( deltas, delta_cnt ) ) return NULL; - i = 0; - while ( i < delta_cnt ) + i = 0; + bytes_used = 0; + + while ( i < delta_cnt && bytes_used < size ) { runcnt = FT_GET_BYTE(); cnt = runcnt & GX_DT_DELTA_RUN_COUNT_MASK; + bytes_used++; + if ( runcnt & GX_DT_DELTAS_ARE_ZERO ) { - /* `runcnt' zeroes get added */ + /* `cnt` + 1 zeroes get added */ for ( j = 0; j <= cnt && i < delta_cnt; j++ ) deltas[i++] = 0; } else if ( runcnt & GX_DT_DELTAS_ARE_WORDS ) { - /* `runcnt' shorts from the stack */ + /* `cnt` + 1 shorts from the stack */ + bytes_used += 2 * ( cnt + 1 ); + if ( bytes_used > size ) + { + FT_TRACE1(( "ft_var_readpackeddeltas:" + " number of short deltas too large\n" )); + goto Fail; + } + for ( j = 0; j <= cnt && i < delta_cnt; j++ ) deltas[i++] = FT_intToFixed( FT_GET_SHORT() ); } else { - /* `runcnt' signed bytes from the stack */ + /* `cnt` + 1 signed bytes from the stack */ + bytes_used += cnt + 1; + if ( bytes_used > size ) + { + FT_TRACE1(( "ft_var_readpackeddeltas:" + " number of byte deltas too large\n" )); + goto Fail; + } + for ( j = 0; j <= cnt && i < delta_cnt; j++ ) deltas[i++] = FT_intToFixed( FT_GET_CHAR() ); } if ( j <= cnt ) { - /* bad format */ - FT_FREE( deltas ); - return NULL; + FT_TRACE1(( "ft_var_readpackeddeltas:" + " number of deltas too large\n" )); + goto Fail; } } + if ( i < delta_cnt ) + { + FT_TRACE1(( "ft_var_readpackeddeltas: not enough deltas\n" )); + goto Fail; + } + return deltas; + + Fail: + FT_FREE( deltas ); + return NULL; } @@ -332,17 +355,24 @@ static void ft_var_load_avar( TT_Face face ) { - FT_Stream stream = FT_FACE_STREAM( face ); - FT_Memory memory = stream->memory; + FT_Error error; + FT_Stream stream = FT_FACE_STREAM( face ); + FT_Memory memory = stream->memory; + FT_Int i, j; + GX_Blend blend = face->blend; GX_AVarSegment segment; - FT_Error error = FT_Err_Ok; - FT_Long version; - FT_Long axisCount; - FT_Int i, j; - FT_ULong table_len; + GX_AVarTable table; - FT_UNUSED( error ); + FT_Long version; + FT_Long axisCount; + FT_ULong table_len; + +#ifndef TT_CONFIG_OPTION_NO_BORING_EXPANSION + FT_ULong table_offset; + FT_ULong store_offset; + FT_ULong axisMap_offset; +#endif FT_TRACE2(( "AVAR " )); @@ -355,13 +385,21 @@ return; } +#ifndef TT_CONFIG_OPTION_NO_BORING_EXPANSION + table_offset = FT_STREAM_POS(); +#endif + if ( FT_FRAME_ENTER( table_len ) ) return; version = FT_GET_LONG(); axisCount = FT_GET_LONG(); - if ( version != 0x00010000L ) + if ( version != 0x00010000L +#ifndef TT_CONFIG_OPTION_NO_BORING_EXPANSION + && version != 0x00020000L +#endif + ) { FT_TRACE2(( "bad table version\n" )); goto Exit; @@ -371,31 +409,35 @@ if ( axisCount != (FT_Long)blend->mmvar->num_axis ) { - FT_TRACE2(( "ft_var_load_avar: number of axes in `avar' and `fvar'\n" - " table are different\n" )); + FT_TRACE2(( "ft_var_load_avar:" + " number of axes in `avar' and `fvar'\n" )); + FT_TRACE2(( " table are different\n" )); goto Exit; } - if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) ) + if ( FT_NEW( blend->avar_table ) ) + goto Exit; + table = blend->avar_table; + + if ( FT_QNEW_ARRAY( table->avar_segment, axisCount ) ) goto Exit; - segment = &blend->avar_segment[0]; + segment = &table->avar_segment[0]; for ( i = 0; i < axisCount; i++, segment++ ) { FT_TRACE5(( " axis %d:\n", i )); segment->pairCount = FT_GET_USHORT(); - if ( (FT_ULong)segment->pairCount * 4 > table_len || - FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) ) + if ( (FT_ULong)segment->pairCount * 4 > table_len || + FT_QNEW_ARRAY( segment->correspondence, segment->pairCount ) ) { /* Failure. Free everything we have done so far. We must do */ /* it right now since loading the `avar' table is optional. */ for ( j = i - 1; j >= 0; j-- ) - FT_FREE( blend->avar_segment[j].correspondence ); + FT_FREE( table->avar_segment[j].correspondence ); - FT_FREE( blend->avar_segment ); - blend->avar_segment = NULL; + FT_FREE( table->avar_segment ); goto Exit; } @@ -407,35 +449,70 @@ FT_fdot14ToFixed( FT_GET_SHORT() ); FT_TRACE5(( " mapping %.5f to %.5f\n", - segment->correspondence[j].fromCoord / 65536.0, - segment->correspondence[j].toCoord / 65536.0 )); + (double)segment->correspondence[j].fromCoord / 65536, + (double)segment->correspondence[j].toCoord / 65536 )); } FT_TRACE5(( "\n" )); } +#ifndef TT_CONFIG_OPTION_NO_BORING_EXPANSION + if ( version < 0x00020000L ) + goto Exit; + + axisMap_offset = FT_GET_ULONG(); + store_offset = FT_GET_ULONG(); + + if ( store_offset ) + { + error = tt_var_load_item_variation_store( + FT_FACE( face ), + table_offset + store_offset, + &table->itemStore ); + if ( error ) + goto Exit; + } + + if ( axisMap_offset ) + { + error = tt_var_load_delta_set_index_mapping( + FT_FACE( face ), + table_offset + axisMap_offset, + &table->axisMap, + &table->itemStore, + table_len ); + if ( error ) + goto Exit; + } +#endif + + Exit: FT_FRAME_EXIT(); } - static FT_Error - ft_var_load_item_variation_store( TT_Face face, + FT_LOCAL_DEF( FT_Error ) + tt_var_load_item_variation_store( FT_Face face, /* TT_Face */ FT_ULong offset, GX_ItemVarStore itemStore ) { + TT_Face ttface = (TT_Face)face; FT_Stream stream = FT_FACE_STREAM( face ); FT_Memory memory = stream->memory; FT_Error error; FT_UShort format; FT_ULong region_offset; - FT_UInt i, j, k; - FT_UInt shortDeltaCount; - GX_Blend blend = face->blend; - GX_ItemVarData varData; + FT_UInt data_count; + FT_UShort axis_count; + FT_UInt region_count; + FT_UInt i, j; + FT_Bool long_words; + + GX_Blend blend = ttface->blend; FT_ULong* dataOffsetArray = NULL; @@ -445,31 +522,31 @@ if ( format != 1 ) { - FT_TRACE2(( "ft_var_load_item_variation_store: bad store format %d\n", + FT_TRACE2(( "tt_var_load_item_variation_store: bad store format %d\n", format )); error = FT_THROW( Invalid_Table ); goto Exit; } /* read top level fields */ - if ( FT_READ_ULONG( region_offset ) || - FT_READ_USHORT( itemStore->dataCount ) ) + if ( FT_READ_ULONG( region_offset ) || + FT_READ_USHORT( data_count ) ) goto Exit; /* we need at least one entry in `itemStore->varData' */ - if ( !itemStore->dataCount ) + if ( !data_count ) { - FT_TRACE2(( "ft_var_load_item_variation_store: missing varData\n" )); + FT_TRACE2(( "tt_var_load_item_variation_store: missing varData\n" )); error = FT_THROW( Invalid_Table ); goto Exit; } /* make temporary copy of item variation data offsets; */ /* we will parse region list first, then come back */ - if ( FT_NEW_ARRAY( dataOffsetArray, itemStore->dataCount ) ) + if ( FT_QNEW_ARRAY( dataOffsetArray, data_count ) ) goto Exit; - for ( i = 0; i < itemStore->dataCount; i++ ) + for ( i = 0; i < data_count; i++ ) { if ( FT_READ_ULONG( dataOffsetArray[i] ) ) goto Exit; @@ -479,30 +556,40 @@ if ( FT_STREAM_SEEK( offset + region_offset ) ) goto Exit; - if ( FT_READ_USHORT( itemStore->axisCount ) || - FT_READ_USHORT( itemStore->regionCount ) ) + if ( FT_READ_USHORT( axis_count ) || + FT_READ_USHORT( region_count ) ) goto Exit; - if ( itemStore->axisCount != (FT_Long)blend->mmvar->num_axis ) + if ( axis_count != (FT_Long)blend->mmvar->num_axis ) { - FT_TRACE2(( "ft_var_load_item_variation_store:" - " number of axes in item variation store\n" - " " + FT_TRACE2(( "tt_var_load_item_variation_store:" + " number of axes in item variation store\n" )); + FT_TRACE2(( " " " and `fvar' table are different\n" )); error = FT_THROW( Invalid_Table ); goto Exit; } + itemStore->axisCount = axis_count; - if ( FT_NEW_ARRAY( itemStore->varRegionList, itemStore->regionCount ) ) + /* new constraint in OpenType 1.8.4 */ + if ( region_count >= 32768U ) + { + FT_TRACE2(( "tt_var_load_item_variation_store:" + " too many variation region tables\n" )); + error = FT_THROW( Invalid_Table ); goto Exit; + } + + if ( FT_NEW_ARRAY( itemStore->varRegionList, region_count ) ) + goto Exit; + itemStore->regionCount = region_count; for ( i = 0; i < itemStore->regionCount; i++ ) { GX_AxisCoords axisCoords; - if ( FT_NEW_ARRAY( itemStore->varRegionList[i].axisList, - itemStore->axisCount ) ) + if ( FT_NEW_ARRAY( itemStore->varRegionList[i].axisList, axis_count ) ) goto Exit; axisCoords = itemStore->varRegionList[i].axisList; @@ -526,44 +613,56 @@ /* end of region list parse */ /* use dataOffsetArray now to parse varData items */ - if ( FT_NEW_ARRAY( itemStore->varData, itemStore->dataCount ) ) + if ( FT_NEW_ARRAY( itemStore->varData, data_count ) ) goto Exit; + itemStore->dataCount = data_count; - for ( i = 0; i < itemStore->dataCount; i++ ) + for ( i = 0; i < data_count; i++ ) { - varData = &itemStore->varData[i]; + GX_ItemVarData varData = &itemStore->varData[i]; + + FT_UInt item_count; + FT_UShort word_delta_count; + FT_UInt region_idx_count; + FT_UInt per_region_size; + if ( FT_STREAM_SEEK( offset + dataOffsetArray[i] ) ) goto Exit; - if ( FT_READ_USHORT( varData->itemCount ) || - FT_READ_USHORT( shortDeltaCount ) || - FT_READ_USHORT( varData->regionIdxCount ) ) + if ( FT_READ_USHORT( item_count ) || + FT_READ_USHORT( word_delta_count ) || + FT_READ_USHORT( region_idx_count ) ) goto Exit; + long_words = !!( word_delta_count & 0x8000 ); + word_delta_count &= 0x7FFF; + /* check some data consistency */ - if ( shortDeltaCount > varData->regionIdxCount ) + if ( word_delta_count > region_idx_count ) { FT_TRACE2(( "bad short count %d or region count %d\n", - shortDeltaCount, - varData->regionIdxCount )); + word_delta_count, + region_idx_count )); error = FT_THROW( Invalid_Table ); goto Exit; } - if ( varData->regionIdxCount > itemStore->regionCount ) + if ( region_idx_count > itemStore->regionCount ) { FT_TRACE2(( "inconsistent regionCount %d in varData[%d]\n", - varData->regionIdxCount, + region_idx_count, i )); error = FT_THROW( Invalid_Table ); goto Exit; } /* parse region indices */ - if ( FT_NEW_ARRAY( varData->regionIndices, - varData->regionIdxCount ) ) + if ( FT_NEW_ARRAY( varData->regionIndices, region_idx_count ) ) goto Exit; + varData->regionIdxCount = region_idx_count; + varData->wordDeltaCount = word_delta_count; + varData->longWords = long_words; for ( j = 0; j < varData->regionIdxCount; j++ ) { @@ -579,43 +678,22 @@ } } - /* Parse delta set. */ - /* */ - /* On input, deltas are (shortDeltaCount + regionIdxCount) bytes */ - /* each; on output, deltas are expanded to `regionIdxCount' shorts */ - /* each. */ - if ( FT_NEW_ARRAY( varData->deltaSet, - varData->regionIdxCount * varData->itemCount ) ) + per_region_size = word_delta_count + region_idx_count; + if ( long_words ) + per_region_size *= 2; + + if ( FT_NEW_ARRAY( varData->deltaSet, per_region_size * item_count ) ) goto Exit; - - /* the delta set is stored as a 2-dimensional array of shorts; */ - /* sign-extend signed bytes to signed shorts */ - for ( j = 0; j < varData->itemCount * varData->regionIdxCount; ) + if ( FT_Stream_Read( stream, + varData->deltaSet, + per_region_size * item_count ) ) { - for ( k = 0; k < shortDeltaCount; k++, j++ ) - { - /* read the short deltas */ - FT_Short delta; - - - if ( FT_READ_SHORT( delta ) ) - goto Exit; - - varData->deltaSet[j] = delta; - } - - for ( ; k < varData->regionIdxCount; k++, j++ ) - { - /* read the (signed) byte deltas */ - FT_Char delta; - - - if ( FT_READ_CHAR( delta ) ) - goto Exit; - - varData->deltaSet[j] = delta; - } + FT_TRACE2(( "deltaSet read failed." )); + error = FT_THROW( Invalid_Table ); + goto Exit; } + + varData->itemCount = item_count; } Exit: @@ -625,41 +703,70 @@ } - static FT_Error - ft_var_load_delta_set_index_mapping( TT_Face face, + FT_LOCAL_DEF( FT_Error ) + tt_var_load_delta_set_index_mapping( FT_Face face, /* TT_Face */ FT_ULong offset, GX_DeltaSetIdxMap map, - GX_ItemVarStore itemStore ) + GX_ItemVarStore itemStore, + FT_ULong table_len ) { FT_Stream stream = FT_FACE_STREAM( face ); FT_Memory memory = stream->memory; - FT_Error error; + FT_Error error; - FT_UShort format; - FT_UInt entrySize; - FT_UInt innerBitCount; - FT_UInt innerIndexMask; - FT_UInt i, j; + FT_Byte format; + FT_Byte entryFormat; + FT_UInt entrySize; + FT_UInt innerBitCount; + FT_UInt innerIndexMask; + FT_ULong i; + FT_UInt j; - if ( FT_STREAM_SEEK( offset ) || - FT_READ_USHORT( format ) || - FT_READ_USHORT( map->mapCount ) ) + if ( FT_STREAM_SEEK( offset ) || + FT_READ_BYTE( format ) || + FT_READ_BYTE( entryFormat ) ) goto Exit; - if ( format & 0xFFC0 ) + if ( format == 0 ) + { + if ( FT_READ_USHORT( map->mapCount ) ) + goto Exit; + } + else if ( format == 1 ) /* new in OpenType 1.9 */ + { + if ( FT_READ_ULONG( map->mapCount ) ) + goto Exit; + } + else { FT_TRACE2(( "bad map format %d\n", format )); error = FT_THROW( Invalid_Table ); goto Exit; } + if ( entryFormat & 0xC0 ) + { + FT_TRACE2(( "bad entry format %d\n", format )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + /* bytes per entry: 1, 2, 3, or 4 */ - entrySize = ( ( format & 0x0030 ) >> 4 ) + 1; - innerBitCount = ( format & 0x000F ) + 1; + entrySize = ( ( entryFormat & 0x30 ) >> 4 ) + 1; + innerBitCount = ( entryFormat & 0x0F ) + 1; innerIndexMask = ( 1 << innerBitCount ) - 1; + /* rough sanity check */ + if ( map->mapCount * entrySize > table_len ) + { + FT_TRACE1(( "tt_var_load_delta_set_index_mapping:" + " invalid number of delta-set index mappings\n" )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + if ( FT_NEW_ARRAY( map->innerIndex, map->mapCount ) ) goto Exit; @@ -684,11 +791,21 @@ mapData = ( mapData << 8 ) | data; } + /* new in OpenType 1.8.4 */ + if ( mapData == 0xFFFFFFFFUL ) + { + /* no variation data for this item */ + map->outerIndex[i] = 0xFFFFU; + map->innerIndex[i] = 0xFFFFU; + + continue; + } + outerIndex = mapData >> innerBitCount; if ( outerIndex >= itemStore->dataCount ) { - FT_TRACE2(( "outerIndex[%d] == %d out of range\n", + FT_TRACE2(( "outerIndex[%ld] == %d out of range\n", i, outerIndex )); error = FT_THROW( Invalid_Table ); @@ -701,7 +818,7 @@ if ( innerIndex >= itemStore->varData[outerIndex].itemCount ) { - FT_TRACE2(( "innerIndex[%d] == %d out of range\n", + FT_TRACE2(( "innerIndex[%ld] == %d out of range\n", i, innerIndex )); error = FT_THROW( Invalid_Table ); @@ -813,8 +930,8 @@ table = blend->hvar_table; } - error = ft_var_load_item_variation_store( - face, + error = tt_var_load_item_variation_store( + FT_FACE( face ), table_offset + store_offset, &table->itemStore ); if ( error ) @@ -822,11 +939,12 @@ if ( widthMap_offset ) { - error = ft_var_load_delta_set_index_mapping( - face, + error = tt_var_load_delta_set_index_mapping( + FT_FACE( face ), table_offset + widthMap_offset, &table->widthMap, - &table->itemStore ); + &table->itemStore, + table_len ); if ( error ) goto Exit; } @@ -863,26 +981,86 @@ } - static FT_Int - ft_var_get_item_delta( TT_Face face, + FT_LOCAL_DEF( FT_ItemVarDelta ) + tt_var_get_item_delta( FT_Face face, /* TT_Face */ GX_ItemVarStore itemStore, FT_UInt outerIndex, FT_UInt innerIndex ) { - GX_ItemVarData varData; - FT_Short* deltaSet; + TT_Face ttface = (TT_Face)face; + FT_Stream stream = FT_FACE_STREAM( face ); + FT_Memory memory = stream->memory; + FT_Error error = FT_Err_Ok; - FT_UInt master, j; - FT_Fixed netAdjustment = 0; /* accumulated adjustment */ - FT_Fixed scaledDelta; - FT_Fixed delta; + GX_ItemVarData varData; + FT_ItemVarDelta* deltaSet = NULL; + FT_ItemVarDelta deltaSetStack[16]; + FT_Fixed* scalars = NULL; + FT_Fixed scalarsStack[16]; + + FT_UInt master, j; + FT_ItemVarDelta returnValue = 0; + FT_UInt per_region_size; + FT_Byte* bytes; + + + if ( !ttface->blend || !ttface->blend->normalizedcoords ) + return 0; + + /* OpenType 1.8.4+: No variation data for this item */ + /* as indices have special value 0xFFFF. */ + if ( outerIndex == 0xFFFF && innerIndex == 0xFFFF ) + return 0; /* See pseudo code from `Font Variations Overview' */ /* in the OpenType specification. */ - varData = &itemStore->varData[outerIndex]; - deltaSet = &varData->deltaSet[varData->regionIdxCount * innerIndex]; + if ( outerIndex >= itemStore->dataCount ) + return 0; /* Out of range. */ + + varData = &itemStore->varData[outerIndex]; + + if ( innerIndex >= varData->itemCount ) + return 0; /* Out of range. */ + + if ( varData->regionIdxCount < 16 ) + { + deltaSet = deltaSetStack; + scalars = scalarsStack; + } + else + { + if ( FT_QNEW_ARRAY( deltaSet, varData->regionIdxCount ) ) + goto Exit; + if ( FT_QNEW_ARRAY( scalars, varData->regionIdxCount ) ) + goto Exit; + } + + /* Parse delta set. */ + /* */ + /* Deltas are (word_delta_count + region_idx_count) bytes each */ + /* if `longWords` isn't set, and twice as much otherwise. */ + per_region_size = varData->wordDeltaCount + varData->regionIdxCount; + if ( varData->longWords ) + per_region_size *= 2; + + bytes = varData->deltaSet + per_region_size * innerIndex; + + if ( varData->longWords ) + { + for ( master = 0; master < varData->wordDeltaCount; master++ ) + deltaSet[master] = FT_NEXT_LONG( bytes ); + for ( ; master < varData->regionIdxCount; master++ ) + deltaSet[master] = FT_NEXT_SHORT( bytes ); + } + else + { + for ( master = 0; master < varData->wordDeltaCount; master++ ) + deltaSet[master] = FT_NEXT_SHORT( bytes ); + for ( ; master < varData->regionIdxCount; master++ ) + deltaSet[master] = FT_NEXT_CHAR( bytes ); + } /* outer loop steps through master designs to be blended */ for ( master = 0; master < varData->regionIdxCount; master++ ) @@ -911,40 +1089,59 @@ else if ( axis->peakCoord == 0 ) continue; - else if ( face->blend->normalizedcoords[j] == axis->peakCoord ) + else if ( ttface->blend->normalizedcoords[j] == axis->peakCoord ) continue; /* ignore this region if coords are out of range */ - else if ( face->blend->normalizedcoords[j] <= axis->startCoord || - face->blend->normalizedcoords[j] >= axis->endCoord ) + else if ( ttface->blend->normalizedcoords[j] <= axis->startCoord || + ttface->blend->normalizedcoords[j] >= axis->endCoord ) { scalar = 0; break; } /* cumulative product of all the axis scalars */ - else if ( face->blend->normalizedcoords[j] < axis->peakCoord ) + else if ( ttface->blend->normalizedcoords[j] < axis->peakCoord ) scalar = FT_MulDiv( scalar, - face->blend->normalizedcoords[j] - axis->startCoord, + ttface->blend->normalizedcoords[j] - axis->startCoord, axis->peakCoord - axis->startCoord ); else scalar = FT_MulDiv( scalar, - axis->endCoord - face->blend->normalizedcoords[j], + axis->endCoord - ttface->blend->normalizedcoords[j], axis->endCoord - axis->peakCoord ); + } /* per-axis loop */ - /* get the scaled delta for this region */ - delta = FT_intToFixed( deltaSet[master] ); - scaledDelta = FT_MulFix( scalar, delta ); - - /* accumulate the adjustments from each region */ - netAdjustment = netAdjustment + scaledDelta; + scalars[master] = scalar; } /* per-region loop */ - return FT_fixedToInt( netAdjustment ); + + /* Compute the scaled delta for this region. + * + * From: https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#item-variation-store-header-and-item-variation-data-subtables: + * + * `Fixed` is a 32-bit (16.16) type and, in the general case, requires + * 32-bit deltas. As described above, the `DeltaSet` record can + * accommodate deltas that are, logically, either 16-bit or 32-bit. + * When scaled deltas are applied to `Fixed` values, the `Fixed` value + * is treated like a 32-bit integer. + * + * `FT_MulAddFix` internally uses 64-bit precision; it thus can handle + * deltas ranging from small 8-bit to large 32-bit values that are + * applied to 16.16 `FT_Fixed` / OpenType `Fixed` values. + */ + returnValue = FT_MulAddFix( scalars, deltaSet, varData->regionIdxCount ); + + Exit: + if ( scalars != scalarsStack ) + FT_FREE( scalars ); + if ( deltaSet != deltaSetStack ) + FT_FREE( deltaSet ); + + return returnValue; } @@ -1037,35 +1234,27 @@ } else { - GX_ItemVarData varData; - - /* no widthMap data */ outerIndex = 0; innerIndex = gindex; - - varData = &table->itemStore.varData[outerIndex]; - if ( gindex >= varData->itemCount ) - { - FT_TRACE2(( "gindex %d out of range\n", gindex )); - error = FT_THROW( Invalid_Argument ); - goto Exit; - } } - delta = ft_var_get_item_delta( face, + delta = tt_var_get_item_delta( FT_FACE( face ), &table->itemStore, outerIndex, innerIndex ); - FT_TRACE5(( "%s value %d adjusted by %d unit%s (%s)\n", - vertical ? "vertical height" : "horizontal width", - *avalue, - delta, - delta == 1 ? "" : "s", - vertical ? "VVAR" : "HVAR" )); + if ( delta ) + { + FT_TRACE5(( "%s value %d adjusted by %d unit%s (%s)\n", + vertical ? "vertical height" : "horizontal width", + *avalue, + delta, + delta == 1 ? "" : "s", + vertical ? "VVAR" : "HVAR" )); - *avalue += delta; + *avalue = ADD_INT( *avalue, delta ); + } Exit: return error; @@ -1073,20 +1262,20 @@ FT_LOCAL_DEF( FT_Error ) - tt_hadvance_adjust( TT_Face face, + tt_hadvance_adjust( FT_Face face, /* TT_Face */ FT_UInt gindex, FT_Int *avalue ) { - return tt_hvadvance_adjust( face, gindex, avalue, 0 ); + return tt_hvadvance_adjust( (TT_Face)face, gindex, avalue, 0 ); } FT_LOCAL_DEF( FT_Error ) - tt_vadvance_adjust( TT_Face face, + tt_vadvance_adjust( FT_Face face, /* TT_Face */ FT_UInt gindex, FT_Int *avalue ) { - return tt_hvadvance_adjust( face, gindex, avalue, 1 ); + return tt_hvadvance_adjust( (TT_Face)face, gindex, avalue, 1 ); } @@ -1232,8 +1421,8 @@ records_offset = FT_STREAM_POS(); - error = ft_var_load_item_variation_store( - face, + error = tt_var_load_item_variation_store( + FT_FACE( face ), table_offset + store_offset, &blend->mvar_table->itemStore ); if ( error ) @@ -1248,7 +1437,7 @@ return; value = blend->mvar_table->values; - limit = value + blend->mvar_table->valueCount; + limit = FT_OFFSET( value, blend->mvar_table->valueCount ); itemStore = &blend->mvar_table->itemStore; for ( ; value < limit; value++ ) @@ -1257,6 +1446,13 @@ value->outerIndex = FT_GET_USHORT(); value->innerIndex = FT_GET_USHORT(); + /* new in OpenType 1.8.4 */ + if ( value->outerIndex == 0xFFFFU && value->innerIndex == 0xFFFFU ) + { + /* no variation data for this item */ + continue; + } + if ( value->outerIndex >= itemStore->dataCount || value->innerIndex >= itemStore->varData[value->outerIndex] .itemCount ) @@ -1274,7 +1470,7 @@ FT_TRACE2(( "loaded\n" )); value = blend->mvar_table->values; - limit = value + blend->mvar_table->valueCount; + limit = FT_OFFSET( value, blend->mvar_table->valueCount ); /* save original values of the data MVAR is going to modify */ for ( ; value < limit; value++ ) @@ -1299,15 +1495,14 @@ static FT_Error - tt_size_reset_iterator( FT_ListNode node, + ft_size_reset_iterator( FT_ListNode node, void* user ) { - TT_Size size = (TT_Size)node->data; - - FT_UNUSED( user ); + FT_Size size = (FT_Size)node->data; + FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)user; - tt_size_reset( size, 1 ); + var->size_reset( size ); return FT_Err_Ok; } @@ -1326,33 +1521,36 @@ * The font face. */ FT_LOCAL_DEF( void ) - tt_apply_mvar( TT_Face face ) + tt_apply_mvar( FT_Face face ) /* TT_Face */ { - GX_Blend blend = face->blend; + TT_Face ttface = (TT_Face)face; + + GX_Blend blend = ttface->blend; GX_Value value, limit; + FT_Short mvar_hasc_delta = 0; FT_Short mvar_hdsc_delta = 0; FT_Short mvar_hlgp_delta = 0; - if ( !( face->variation_support & TT_FACE_FLAG_VAR_MVAR ) ) + if ( !( ttface->variation_support & TT_FACE_FLAG_VAR_MVAR ) ) return; value = blend->mvar_table->values; - limit = value + blend->mvar_table->valueCount; + limit = FT_OFFSET( value, blend->mvar_table->valueCount ); for ( ; value < limit; value++ ) { - FT_Short* p = ft_var_get_value_pointer( face, value->tag ); + FT_Short* p = ft_var_get_value_pointer( ttface, value->tag ); FT_Int delta; - delta = ft_var_get_item_delta( face, + delta = tt_var_get_item_delta( face, &blend->mvar_table->itemStore, value->outerIndex, value->innerIndex ); - if ( p ) + if ( p && delta ) { FT_TRACE5(( "value %c%c%c%c (%d unit%s) adjusted by %d unit%s (MVAR)\n", (FT_Char)( value->tag >> 24 ), @@ -1380,7 +1578,8 @@ /* adjust all derived values */ { - FT_Face root = &face->root; + FT_Service_MetricsVariations var = + (FT_Service_MetricsVariations)ttface->face_var; /* * Apply the deltas of hasc, hdsc and hlgp to the FT_Face's ascender, @@ -1408,24 +1607,25 @@ * whether they were actually changed or the font had the OS/2 table's * fsSelection's bit 7 (USE_TYPO_METRICS) set. */ - FT_Short current_line_gap = root->height - root->ascender + - root->descender; + FT_Short current_line_gap = face->height - face->ascender + + face->descender; - root->ascender = root->ascender + mvar_hasc_delta; - root->descender = root->descender + mvar_hdsc_delta; - root->height = root->ascender - root->descender + + face->ascender = face->ascender + mvar_hasc_delta; + face->descender = face->descender + mvar_hdsc_delta; + face->height = face->ascender - face->descender + current_line_gap + mvar_hlgp_delta; - root->underline_position = face->postscript.underlinePosition - - face->postscript.underlineThickness / 2; - root->underline_thickness = face->postscript.underlineThickness; + face->underline_position = ttface->postscript.underlinePosition - + ttface->postscript.underlineThickness / 2; + face->underline_thickness = ttface->postscript.underlineThickness; - /* iterate over all FT_Size objects and call `tt_size_reset' */ - /* to propagate the metrics changes */ - FT_List_Iterate( &root->sizes_list, - tt_size_reset_iterator, - NULL ); + /* iterate over all FT_Size objects and call `var->size_reset' */ + /* to propagate the metrics changes */ + if ( var && var->size_reset ) + FT_List_Iterate( &face->sizes_list, + ft_size_reset_iterator, + (void*)var ); } } @@ -1515,8 +1715,9 @@ if ( gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis ) { - FT_TRACE1(( "ft_var_load_gvar: number of axes in `gvar' and `cvar'\n" - " table are different\n" )); + FT_TRACE1(( "ft_var_load_gvar:" + " number of axes in `gvar' and `cvar'\n" )); + FT_TRACE1(( " table are different\n" )); error = FT_THROW( Invalid_Table ); goto Exit; } @@ -1558,7 +1759,7 @@ goto Exit; /* offsets (one more offset than glyphs, to mark size of last) */ - if ( FT_NEW_ARRAY( blend->glyphoffsets, gvar_head.glyphCount + 1 ) ) + if ( FT_QNEW_ARRAY( blend->glyphoffsets, gvar_head.glyphCount + 1 ) ) goto Fail2; if ( gvar_head.flags & 1 ) @@ -1637,8 +1838,8 @@ goto Fail; } - if ( FT_NEW_ARRAY( blend->tuplecoords, - gvar_head.axisCount * gvar_head.globalCoordCount ) ) + if ( FT_QNEW_ARRAY( blend->tuplecoords, + gvar_head.axisCount * gvar_head.globalCoordCount ) ) goto Fail2; for ( i = 0; i < gvar_head.globalCoordCount; i++ ) @@ -1649,7 +1850,7 @@ blend->tuplecoords[i * gvar_head.axisCount + j] = FT_fdot14ToFixed( FT_GET_SHORT() ); FT_TRACE5(( "%.5f ", - blend->tuplecoords[i * gvar_head.axisCount + j] / 65536.0 )); + (double)blend->tuplecoords[i * gvar_head.axisCount + j] / 65536 )); } FT_TRACE5(( "]\n" )); } @@ -1720,7 +1921,7 @@ for ( i = 0; i < blend->num_axis; i++ ) { FT_TRACE6(( " axis %d coordinate %.5f:\n", - i, blend->normalizedcoords[i] / 65536.0 )); + i, (double)blend->normalizedcoords[i] / 65536 )); /* It's not clear why (for intermediate tuples) we don't need */ /* to check against start/end -- the documentation says we don't. */ @@ -1743,7 +1944,7 @@ if ( blend->normalizedcoords[i] == tuple_coords[i] ) { FT_TRACE6(( " tuple coordinate %.5f fits perfectly\n", - tuple_coords[i] / 65536.0 )); + (double)tuple_coords[i] / 65536 )); /* `apply' does not change */ continue; } @@ -1756,13 +1957,13 @@ blend->normalizedcoords[i] > FT_MAX( 0, tuple_coords[i] ) ) { FT_TRACE6(( " tuple coordinate %.5f is exceeded, stop\n", - tuple_coords[i] / 65536.0 )); + (double)tuple_coords[i] / 65536 )); apply = 0; break; } FT_TRACE6(( " tuple coordinate %.5f fits\n", - tuple_coords[i] / 65536.0 )); + (double)tuple_coords[i] / 65536 )); apply = FT_MulDiv( apply, blend->normalizedcoords[i], tuple_coords[i] ); @@ -1776,15 +1977,15 @@ { FT_TRACE6(( " intermediate tuple range ]%.5f;%.5f[ is exceeded," " stop\n", - im_start_coords[i] / 65536.0, - im_end_coords[i] / 65536.0 )); + (double)im_start_coords[i] / 65536, + (double)im_end_coords[i] / 65536 )); apply = 0; break; } FT_TRACE6(( " intermediate tuple range ]%.5f;%.5f[ fits\n", - im_start_coords[i] / 65536.0, - im_end_coords[i] / 65536.0 )); + (double)im_start_coords[i] / 65536, + (double)im_end_coords[i] / 65536 )); if ( blend->normalizedcoords[i] < tuple_coords[i] ) apply = FT_MulDiv( apply, blend->normalizedcoords[i] - im_start_coords[i], @@ -1796,7 +1997,7 @@ } } - FT_TRACE6(( " apply factor is %.5f\n", apply / 65536.0 )); + FT_TRACE6(( " apply factor is %.5f\n", (double)apply / 65536 )); return apply; } @@ -1810,12 +2011,18 @@ FT_Fixed* coords, FT_Fixed* normalized ) { + FT_Error error = FT_Err_Ok; + FT_Memory memory = face->root.memory; + FT_UInt i, j; + GX_Blend blend; FT_MM_Var* mmvar; - FT_UInt i, j; FT_Var_Axis* a; GX_AVarSegment av; + FT_Fixed* new_normalized = NULL; + FT_Fixed* old_normalized; + blend = face->blend; mmvar = blend->mmvar; @@ -1838,28 +2045,25 @@ FT_Fixed coord = coords[i]; - FT_TRACE5(( " %d: %.5f\n", i, coord / 65536.0 )); + FT_TRACE5(( " %d: %.5f\n", i, (double)coord / 65536 )); if ( coord > a->maximum || coord < a->minimum ) { - FT_TRACE1(( - "ft_var_to_normalized: design coordinate %.5f\n" - " is out of range [%.5f;%.5f]; clamping\n", - coord / 65536.0, - a->minimum / 65536.0, - a->maximum / 65536.0 )); - - if ( coord > a->maximum ) - coord = a->maximum; - else - coord = a->minimum; + FT_TRACE1(( "ft_var_to_normalized: design coordinate %.5f\n", + (double)coord / 65536 )); + FT_TRACE1(( " is out of range [%.5f;%.5f];" + " clamping\n", + (double)a->minimum / 65536, + (double)a->maximum / 65536 )); } - if ( coord < a->def ) - normalized[i] = -FT_DivFix( SUB_LONG( coord, a->def ), - SUB_LONG( a->minimum, a->def ) ); - else if ( coord > a->def ) - normalized[i] = FT_DivFix( SUB_LONG( coord, a->def ), + if ( coord > a->def ) + normalized[i] = coord >= a->maximum ? 0x10000L : + FT_DivFix( SUB_LONG( coord, a->def ), SUB_LONG( a->maximum, a->def ) ); + else if ( coord < a->def ) + normalized[i] = coord <= a->minimum ? -0x10000L : + FT_DivFix( SUB_LONG( coord, a->def ), + SUB_LONG( a->def, a->minimum ) ); else normalized[i] = 0; } @@ -1869,31 +2073,92 @@ for ( ; i < mmvar->num_axis; i++ ) normalized[i] = 0; - if ( blend->avar_segment ) + if ( blend->avar_table ) { + GX_AVarTable table = blend->avar_table; + + FT_TRACE5(( "normalized design coordinates" " before applying `avar' data:\n" )); - av = blend->avar_segment; - for ( i = 0; i < mmvar->num_axis; i++, av++ ) + if ( table->avar_segment ) { - for ( j = 1; j < (FT_UInt)av->pairCount; j++ ) - { - if ( normalized[i] < av->correspondence[j].fromCoord ) - { - FT_TRACE5(( " %.5f\n", normalized[i] / 65536.0 )); + av = table->avar_segment; - normalized[i] = - FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord, - av->correspondence[j].toCoord - - av->correspondence[j - 1].toCoord, - av->correspondence[j].fromCoord - - av->correspondence[j - 1].fromCoord ) + - av->correspondence[j - 1].toCoord; - break; + for ( i = 0; i < mmvar->num_axis; i++, av++ ) + { + for ( j = 1; j < (FT_UInt)av->pairCount; j++ ) + { + if ( normalized[i] < av->correspondence[j].fromCoord ) + { + FT_TRACE5(( " %.5f\n", (double)normalized[i] / 65536 )); + + normalized[i] = + FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord, + av->correspondence[j].toCoord - + av->correspondence[j - 1].toCoord, + av->correspondence[j].fromCoord - + av->correspondence[j - 1].fromCoord ) + + av->correspondence[j - 1].toCoord; + break; + } } } } + + if ( table->itemStore.varData ) + { + if ( FT_QNEW_ARRAY( new_normalized, mmvar->num_axis ) ) + return; + + /* Install our half-normalized coordinates for the next */ + /* Item Variation Store to work with. */ + old_normalized = face->blend->normalizedcoords; + face->blend->normalizedcoords = normalized; + + for ( i = 0; i < mmvar->num_axis; i++ ) + { + FT_Fixed v = normalized[i]; + FT_UInt innerIndex = i; + FT_UInt outerIndex = 0; + FT_Int delta; + + + if ( table->axisMap.innerIndex ) + { + FT_UInt idx = i; + + + if ( idx >= table->axisMap.mapCount ) + idx = table->axisMap.mapCount - 1; + + outerIndex = table->axisMap.outerIndex[idx]; + innerIndex = table->axisMap.innerIndex[idx]; + } + + delta = tt_var_get_item_delta( FT_FACE( face ), + &table->itemStore, + outerIndex, + innerIndex ); + + v += delta << 2; + + /* Clamp value range. */ + v = v >= 0x10000L ? 0x10000 : v; + v = v <= -0x10000L ? -0x10000 : v; + + new_normalized[i] = v; + } + + for ( i = 0; i < mmvar->num_axis; i++ ) + { + normalized[i] = new_normalized[i]; + } + + face->blend->normalizedcoords = old_normalized; + + FT_FREE( new_normalized ); + } } } @@ -1930,9 +2195,9 @@ for ( ; i < num_coords; i++ ) design[i] = 0; - if ( blend->avar_segment ) + if ( blend->avar_table && blend->avar_table->avar_segment ) { - GX_AVarSegment av = blend->avar_segment; + GX_AVarSegment av = blend->avar_table->avar_segment; FT_TRACE5(( "design coordinates" @@ -1952,7 +2217,7 @@ av->correspondence[j - 1].toCoord ) + av->correspondence[j - 1].fromCoord; - FT_TRACE5(( " %.5f\n", design[i] / 65536.0 )); + FT_TRACE5(( " %.5f\n", (double)design[i] / 65536 )); break; } } @@ -2033,11 +2298,12 @@ * FreeType error code. 0 means success. */ FT_LOCAL_DEF( FT_Error ) - TT_Get_MM_Var( TT_Face face, + TT_Get_MM_Var( FT_Face face, /* TT_Face */ FT_MM_Var* *master ) { - FT_Stream stream = face->root.stream; - FT_Memory memory = face->root.memory; + TT_Face ttface = (TT_Face)face; + FT_Stream stream = FT_FACE_STREAM( face ); + FT_Memory memory = FT_FACE_MEMORY( face ); FT_ULong table_len; FT_Error error = FT_Err_Ok; FT_ULong fvar_start = 0; @@ -2049,7 +2315,7 @@ FT_Var_Axis* a; FT_Fixed* c; FT_Var_Named_Style* ns; - GX_FVar_Head fvar_head; + GX_FVar_Head fvar_head = { 0, 0, 0, 0, 0, 0 }; FT_Bool usePsName = 0; FT_UInt num_instances; FT_UInt num_axes; @@ -2097,32 +2363,23 @@ FT_FRAME_END }; + /* `num_instances` holds the number of all named instances including */ + /* the default instance, which might be missing in the table of named */ + /* instances (in 'fvar'). This value is validated in `sfobjs.c` and */ + /* may be reset to 0 if consistency checks fail. */ + num_instances = (FT_UInt)face->style_flags >> 16; /* read the font data and set up the internal representation */ /* if not already done */ - need_init = !face->blend; + need_init = !ttface->blend; if ( need_init ) { FT_TRACE2(( "FVAR " )); - /* both `fvar' and `gvar' must be present */ - if ( FT_SET_ERROR( face->goto_table( face, TTAG_gvar, - stream, &table_len ) ) ) - { - /* CFF2 is an alternate to gvar here */ - if ( FT_SET_ERROR( face->goto_table( face, TTAG_CFF2, + if ( FT_SET_ERROR( ttface->goto_table( ttface, TTAG_fvar, stream, &table_len ) ) ) - { - FT_TRACE1(( "\n" - "TT_Get_MM_Var: `gvar' or `CFF2' table is missing\n" )); - goto Exit; - } - } - - if ( FT_SET_ERROR( face->goto_table( face, TTAG_fvar, - stream, &table_len ) ) ) { FT_TRACE1(( "is missing\n" )); goto Exit; @@ -2135,6 +2392,17 @@ if ( FT_STREAM_READ_FIELDS( fvar_fields, &fvar_head ) ) goto Exit; + /* If `num_instances` is larger, synthetization of the default */ + /* instance is required. If `num_instances` is smaller, */ + /* however, the value has been reset to 0 in `sfnt_init_face` */ + /* (in `sfobjs.c`); in this case we have underallocated `mmvar` */ + /* structs. */ + if ( num_instances < fvar_head.instanceCount ) + { + error = FT_THROW( Invalid_Table ); + goto Exit; + } + usePsName = FT_BOOL( fvar_head.instanceSize == 6 + 4 * fvar_head.axisCount ); @@ -2144,19 +2412,14 @@ fvar_head.axisCount, fvar_head.axisCount == 1 ? "is" : "es" )); - if ( FT_NEW( face->blend ) ) + if ( FT_NEW( ttface->blend ) ) goto Exit; - num_axes = fvar_head.axisCount; - face->blend->num_axis = num_axes; + num_axes = fvar_head.axisCount; + ttface->blend->num_axis = num_axes; } else - num_axes = face->blend->num_axis; - - /* `num_instances' holds the number of all named instances, */ - /* including the default instance which might be missing */ - /* in fvar's table of named instances */ - num_instances = (FT_UInt)face->root.style_flags >> 16; + num_axes = ttface->blend->num_axis; /* prepare storage area for MM data; this cannot overflow */ /* 32-bit arithmetic because of the size limits used in the */ @@ -2185,16 +2448,16 @@ if ( need_init ) { - face->blend->mmvar_len = mmvar_size + - axis_flags_size + - axis_size + - namedstyle_size + - next_coords_size + - next_name_size; + ttface->blend->mmvar_len = mmvar_size + + axis_flags_size + + axis_size + + namedstyle_size + + next_coords_size + + next_name_size; - if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) + if ( FT_ALLOC( mmvar, ttface->blend->mmvar_len ) ) goto Exit; - face->blend->mmvar = mmvar; + ttface->blend->mmvar = mmvar; /* set up pointers and offsets into the `mmvar' array; */ /* the data gets filled in later on */ @@ -2285,9 +2548,9 @@ " %10.5f %10.5f %10.5f 0x%04X%s\n", i, a->name, - a->minimum / 65536.0, - a->def / 65536.0, - a->maximum / 65536.0, + (double)a->minimum / 65536, + (double)a->def / 65536, + (double)a->maximum / 65536, *axis_flags, invalid ? " (invalid, disabled)" : "" )); #endif @@ -2300,27 +2563,27 @@ /* named instance coordinates are stored as design coordinates; */ /* we have to convert them to normalized coordinates also */ - if ( FT_NEW_ARRAY( face->blend->normalized_stylecoords, + if ( FT_NEW_ARRAY( ttface->blend->normalized_stylecoords, num_axes * num_instances ) ) goto Exit; - if ( fvar_head.instanceCount && !face->blend->avar_loaded ) + if ( fvar_head.instanceCount && !ttface->blend->avar_loaded ) { FT_ULong offset = FT_STREAM_POS(); - ft_var_load_avar( face ); + ft_var_load_avar( ttface ); if ( FT_STREAM_SEEK( offset ) ) goto Exit; } - FT_TRACE5(( "%d instance%s\n", + FT_TRACE5(( "%d named instance%s\n", fvar_head.instanceCount, fvar_head.instanceCount == 1 ? "" : "s" )); ns = mmvar->namedstyle; - nsc = face->blend->normalized_stylecoords; + nsc = ttface->blend->normalized_stylecoords; for ( i = 0; i < fvar_head.instanceCount; i++, ns++ ) { /* PostScript names add 2 bytes to the instance record size */ @@ -2343,7 +2606,7 @@ #ifdef FT_DEBUG_LEVEL_TRACE { - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; FT_String* strname = NULL; FT_String* psname = NULL; @@ -2355,7 +2618,7 @@ if ( ns->strid != 0xFFFF ) { - (void)sfnt->get_name( face, + (void)sfnt->get_name( ttface, (FT_UShort)ns->strid, &strname ); if ( strname && !ft_strcmp( strname, ".notdef" ) ) @@ -2364,7 +2627,7 @@ if ( ns->psid != 0xFFFF ) { - (void)sfnt->get_name( face, + (void)sfnt->get_name( ttface, (FT_UShort)ns->psid, &psname ); if ( psname && !ft_strcmp( psname, ".notdef" ) ) @@ -2373,7 +2636,7 @@ (void)FT_STREAM_SEEK( pos ); - FT_TRACE5(( " instance %d (%s%s%s, %s%s%s)\n", + FT_TRACE5(( " named instance %d (%s%s%s, %s%s%s)\n", i, strname ? "name: `" : "", strname ? strname : "unnamed", @@ -2387,7 +2650,7 @@ } #endif /* FT_DEBUG_LEVEL_TRACE */ - ft_var_to_normalized( face, num_axes, ns->coords, nsc ); + ft_var_to_normalized( ttface, num_axes, ns->coords, nsc ); nsc += num_axes; FT_FRAME_EXIT(); @@ -2395,15 +2658,17 @@ if ( num_instances != fvar_head.instanceCount ) { - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; FT_Int found, dummy1, dummy2; FT_UInt strid = ~0U; - /* the default instance is missing in array the */ - /* of named instances; try to synthesize an entry */ - found = sfnt->get_name_id( face, + /* The default instance is missing in array the */ + /* of named instances; try to synthesize an entry. */ + /* If this fails, `default_named_instance` remains */ + /* at value zero, which doesn't do any harm. */ + found = sfnt->get_name_id( ttface, TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY, &dummy1, &dummy2 ); @@ -2411,7 +2676,7 @@ strid = TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY; else { - found = sfnt->get_name_id( face, + found = sfnt->get_name_id( ttface, TT_NAME_ID_FONT_SUBFAMILY, &dummy1, &dummy2 ); @@ -2421,7 +2686,7 @@ if ( found ) { - found = sfnt->get_name_id( face, + found = sfnt->get_name_id( ttface, TT_NAME_ID_PS_NAME, &dummy1, &dummy2 ); @@ -2430,6 +2695,9 @@ FT_TRACE5(( "TT_Get_MM_Var:" " Adding default instance to named instances\n" )); + /* named instance indices start with value 1 */ + ttface->var_default_named_instance = num_instances; + ns = &mmvar->namedstyle[fvar_head.instanceCount]; ns->strid = strid; @@ -2443,7 +2711,7 @@ } } - ft_var_load_mvar( face ); + ft_var_load_mvar( ttface ); } /* fill the output array if requested */ @@ -2453,9 +2721,9 @@ FT_UInt n; - if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) + if ( FT_ALLOC( mmvar, ttface->blend->mmvar_len ) ) goto Exit; - FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len ); + FT_MEM_COPY( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len ); axis_flags = (FT_UShort*)( (char*)mmvar + mmvar_size ); @@ -2488,6 +2756,8 @@ a->name = (char*)"OpticalSize"; else if ( a->tag == TTAG_slnt ) a->name = (char*)"Slant"; + else if ( a->tag == TTAG_ital ) + a->name = (char*)"Italic"; next_name += 5; a++; @@ -2529,7 +2799,7 @@ if ( !face->blend ) { - if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) + if ( FT_SET_ERROR( TT_Get_MM_Var( FT_FACE( face ), NULL ) ) ) goto Exit; } @@ -2544,17 +2814,17 @@ num_coords = mmvar->num_axis; } - FT_TRACE5(( "TT_Set_MM_Blend:\n" - " normalized design coordinates:\n" )); + FT_TRACE5(( "TT_Set_MM_Blend:\n" )); + FT_TRACE5(( " normalized design coordinates:\n" )); for ( i = 0; i < num_coords; i++ ) { - FT_TRACE5(( " %.5f\n", coords[i] / 65536.0 )); + FT_TRACE5(( " %.5f\n", (double)coords[i] / 65536 )); if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L ) { - FT_TRACE1(( "TT_Set_MM_Blend: normalized design coordinate %.5f\n" - " is out of range [-1;1]\n", - coords[i] / 65536.0 )); + FT_TRACE1(( "TT_Set_MM_Blend: normalized design coordinate %.5f\n", + (double)coords[i] / 65536 )); + FT_TRACE1(( " is out of range [-1;1]\n" )); error = FT_THROW( Invalid_Argument ); goto Exit; } @@ -2563,8 +2833,16 @@ FT_TRACE5(( "\n" )); if ( !face->is_cff2 && !blend->glyphoffsets ) - if ( FT_SET_ERROR( ft_var_load_gvar( face ) ) ) + { + /* While a missing 'gvar' table is acceptable, for example for */ + /* fonts that only vary metrics information or 'COLR' v1 */ + /* `PaintVar*` tables, an incorrect SFNT table offset or size */ + /* for 'gvar', or an inconsistent 'gvar' table is not. */ + error = ft_var_load_gvar( face ); + if ( error != FT_Err_Table_Missing && error != FT_Err_Ok ) goto Exit; + error = FT_Err_Ok; + } if ( !blend->coords ) { @@ -2606,26 +2884,29 @@ } } - if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ) + if ( !have_diff ) { - FT_UInt instance_index = (FT_UInt)face->root.face_index >> 16; + if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ) + { + FT_UInt instance_index = (FT_UInt)face->root.face_index >> 16; - c = blend->normalizedcoords + i; - n = blend->normalized_stylecoords + - ( instance_index - 1 ) * mmvar->num_axis + - i; + c = blend->normalizedcoords + i; + n = blend->normalized_stylecoords + + ( instance_index - 1 ) * mmvar->num_axis + + i; - for ( j = i; j < mmvar->num_axis; j++, n++, c++ ) - if ( *c != *n ) - have_diff = 1; - } - else - { - c = blend->normalizedcoords + i; - for ( j = i; j < mmvar->num_axis; j++, c++ ) - if ( *c != 0 ) - have_diff = 1; + for ( j = i; j < mmvar->num_axis; j++, n++, c++ ) + if ( *c != *n ) + have_diff = 1; + } + else + { + c = blend->normalizedcoords + i; + for ( j = i; j < mmvar->num_axis; j++, c++ ) + if ( *c != 0 ) + have_diff = 1; + } } /* return value -1 indicates `no change' */ @@ -2652,9 +2933,10 @@ } blend->num_axis = mmvar->num_axis; - FT_MEM_COPY( blend->normalizedcoords, - coords, - num_coords * sizeof ( FT_Fixed ) ); + if ( coords ) + FT_MEM_COPY( blend->normalizedcoords, + coords, + num_coords * sizeof ( FT_Fixed ) ); if ( set_design_coords ) ft_var_to_design( face, @@ -2672,7 +2954,6 @@ /* The cvt table has been loaded already; every time we change the */ /* blend we may need to reload and remodify the cvt table. */ FT_FREE( face->cvt ); - face->cvt = NULL; error = tt_face_load_cvt( face, face->root.stream ); break; @@ -2689,10 +2970,6 @@ } } - /* enforce recomputation of the PostScript name; */ - FT_FREE( face->postscript_name ); - face->postscript_name = NULL; - Exit: return error; } @@ -2724,26 +3001,15 @@ * An array of `num_coords', each between [-1,1]. * * @Return: - * FreeType error code. 0 means success. + * FreeType error code. 0 means success, -1 means success and unchanged + * axis values. */ FT_LOCAL_DEF( FT_Error ) - TT_Set_MM_Blend( TT_Face face, + TT_Set_MM_Blend( FT_Face face, /* TT_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error; - - - error = tt_set_mm_blend( face, num_coords, coords, 1 ); - if ( error ) - return error; - - if ( num_coords ) - face->root.face_flags |= FT_FACE_FLAG_VARIATION; - else - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; - - return FT_Err_Ok; + return tt_set_mm_blend( (TT_Face)face, num_coords, coords, 1 ); } @@ -2771,31 +3037,34 @@ * An array of `num_coords', each between [-1,1]. * * @Return: - * FreeType error code. 0 means success. + * FreeType error code. 0 means success, -1 means success and unchanged + * axis values. */ FT_LOCAL_DEF( FT_Error ) - TT_Get_MM_Blend( TT_Face face, + TT_Get_MM_Blend( FT_Face face, /* TT_Face */ FT_UInt num_coords, FT_Fixed* coords ) { + TT_Face ttface = (TT_Face)face; + FT_Error error = FT_Err_Ok; GX_Blend blend; FT_UInt i, nc; - if ( !face->blend ) + if ( !ttface->blend ) { if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) return error; } - blend = face->blend; + blend = ttface->blend; if ( !blend->coords ) { /* select default instance coordinates */ /* if no instance is selected yet */ - if ( FT_SET_ERROR( tt_set_mm_blend( face, 0, NULL, 1 ) ) ) + if ( FT_SET_ERROR( tt_set_mm_blend( ttface, 0, NULL, 1 ) ) ) return error; } @@ -2808,7 +3077,7 @@ nc = blend->num_axis; } - if ( face->doblend ) + if ( ttface->doblend ) { for ( i = 0; i < nc; i++ ) coords[i] = blend->normalizedcoords[i]; @@ -2855,15 +3124,16 @@ * FreeType error code. 0 means success. */ FT_LOCAL_DEF( FT_Error ) - TT_Set_Var_Design( TT_Face face, + TT_Set_Var_Design( FT_Face face, /* TT_Face */ FT_UInt num_coords, FT_Fixed* coords ) { + TT_Face ttface = (TT_Face)face; FT_Error error = FT_Err_Ok; GX_Blend blend; FT_MM_Var* mmvar; FT_UInt i; - FT_Memory memory = face->root.memory; + FT_Memory memory = FT_FACE_MEMORY( face ); FT_Fixed* c; FT_Fixed* n; @@ -2872,13 +3142,13 @@ FT_Bool have_diff = 0; - if ( !face->blend ) + if ( !ttface->blend ) { if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) goto Exit; } - blend = face->blend; + blend = ttface->blend; mmvar = blend->mmvar; if ( num_coords > mmvar->num_axis ) @@ -2906,13 +3176,13 @@ } } - if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ) + if ( FT_IS_NAMED_INSTANCE( face ) ) { FT_UInt instance_index; FT_Var_Named_Style* named_style; - instance_index = (FT_UInt)face->root.face_index >> 16; + instance_index = (FT_UInt)face->face_index >> 16; named_style = mmvar->namedstyle + instance_index - 1; n = named_style->coords + num_coords; @@ -2949,22 +3219,17 @@ if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) ) goto Exit; - if ( !face->blend->avar_loaded ) - ft_var_load_avar( face ); + if ( !ttface->blend->avar_loaded ) + ft_var_load_avar( ttface ); - FT_TRACE5(( "TT_Set_Var_Design:\n" - " normalized design coordinates:\n" )); - ft_var_to_normalized( face, num_coords, blend->coords, normalized ); + FT_TRACE5(( "TT_Set_Var_Design:\n" )); + FT_TRACE5(( " normalized design coordinates:\n" )); + ft_var_to_normalized( ttface, num_coords, blend->coords, normalized ); - error = tt_set_mm_blend( face, mmvar->num_axis, normalized, 0 ); + error = tt_set_mm_blend( ttface, mmvar->num_axis, normalized, 0 ); if ( error ) goto Exit; - if ( num_coords ) - face->root.face_flags |= FT_FACE_FLAG_VARIATION; - else - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; - Exit: FT_FREE( normalized ); return error; @@ -2997,28 +3262,29 @@ * FreeType error code. 0~means success. */ FT_LOCAL_DEF( FT_Error ) - TT_Get_Var_Design( TT_Face face, + TT_Get_Var_Design( FT_Face face, /* TT_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error = FT_Err_Ok; + TT_Face ttface = (TT_Face)face; + FT_Error error = FT_Err_Ok; GX_Blend blend; FT_UInt i, nc; - if ( !face->blend ) + if ( !ttface->blend ) { if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) return error; } - blend = face->blend; + blend = ttface->blend; if ( !blend->coords ) { /* select default instance coordinates */ /* if no instance is selected yet */ - if ( FT_SET_ERROR( tt_set_mm_blend( face, 0, NULL, 1 ) ) ) + if ( FT_SET_ERROR( tt_set_mm_blend( ttface, 0, NULL, 1 ) ) ) return error; } @@ -3031,7 +3297,7 @@ nc = blend->num_axis; } - if ( face->doblend ) + if ( ttface->doblend ) { for ( i = 0; i < nc; i++ ) coords[i] = blend->coords[i]; @@ -3067,29 +3333,33 @@ * Value 0 indicates to not use an instance. * * @Return: - * FreeType error code. 0~means success. + * FreeType error code. 0~means success, -1 means success and unchanged + * axis values. */ FT_LOCAL_DEF( FT_Error ) - TT_Set_Named_Instance( TT_Face face, + TT_Set_Named_Instance( FT_Face face, /* TT_Face */ FT_UInt instance_index ) { + TT_Face ttface = (TT_Face)face; FT_Error error; GX_Blend blend; FT_MM_Var* mmvar; + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_UInt num_instances; - if ( !face->blend ) + if ( !ttface->blend ) { if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) goto Exit; } - blend = face->blend; + blend = ttface->blend; mmvar = blend->mmvar; - num_instances = (FT_UInt)face->root.style_flags >> 16; + num_instances = (FT_UInt)face->style_flags >> 16; /* `instance_index' starts with value 1, thus `>' */ if ( instance_index > num_instances ) @@ -3100,8 +3370,7 @@ if ( instance_index > 0 ) { - FT_Memory memory = face->root.memory; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; FT_Var_Named_Style* named_style; FT_String* style_name; @@ -3109,40 +3378,89 @@ named_style = mmvar->namedstyle + instance_index - 1; - error = sfnt->get_name( face, + error = sfnt->get_name( ttface, (FT_UShort)named_style->strid, &style_name ); if ( error ) goto Exit; /* set (or replace) style name */ - FT_FREE( face->root.style_name ); - face->root.style_name = style_name; + FT_FREE( face->style_name ); + face->style_name = style_name; /* finally, select the named instance */ error = TT_Set_Var_Design( face, mmvar->num_axis, named_style->coords ); - if ( error ) - { - /* internal error code -1 means `no change' */ - if ( error == -1 ) - error = FT_Err_Ok; - goto Exit; - } } else + { + /* restore non-VF style name */ + FT_FREE( face->style_name ); + if ( FT_STRDUP( face->style_name, ttface->non_var_style_name ) ) + goto Exit; error = TT_Set_Var_Design( face, 0, NULL ); - - face->root.face_index = ( instance_index << 16 ) | - ( face->root.face_index & 0xFFFFL ); - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; + } Exit: return error; } + /************************************************************************** + * + * @Function: + * TT_Get_Default_Named_Instance + * + * @Description: + * Get the default named instance. + * + * @Input: + * face :: + * A handle to the source face. + * + * @Output: + * instance_index :: + * The default named instance index. + * + * @Return: + * FreeType error code. 0~means success. + */ + FT_LOCAL_DEF( FT_Error ) + TT_Get_Default_Named_Instance( FT_Face face, + FT_UInt *instance_index ) + { + TT_Face ttface = (TT_Face)face; + FT_Error error = FT_Err_Ok; + + + if ( !ttface->blend ) + { + if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) + goto Exit; + } + + *instance_index = ttface->var_default_named_instance; + + Exit: + return error; + } + + + /* This function triggers (lazy) recomputation of the `postscript_name` */ + /* field in `TT_Face`. */ + + FT_LOCAL_DEF( void ) + tt_construct_ps_name( FT_Face face ) + { + TT_Face ttface = (TT_Face)face; + FT_Memory memory = FT_FACE_MEMORY( face ); + + + FT_FREE( ttface->postscript_name ); + } + + /*************************************************************************/ /*************************************************************************/ /***** *****/ @@ -3152,6 +3470,8 @@ /*************************************************************************/ +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + static FT_Error tt_cvt_ready_iterator( FT_ListNode node, void* user ) @@ -3166,6 +3486,9 @@ return FT_Err_Ok; } +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + /************************************************************************** * @@ -3194,6 +3517,8 @@ tt_face_vary_cvt( TT_Face face, FT_Stream stream ) { +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + FT_Error error; FT_Memory memory = stream->memory; @@ -3229,16 +3554,16 @@ if ( !blend ) { - FT_TRACE2(( "\n" - "tt_face_vary_cvt: no blend specified\n" )); + FT_TRACE2(( "\n" )); + FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" )); error = FT_Err_Ok; goto Exit; } if ( !face->cvt ) { - FT_TRACE2(( "\n" - "tt_face_vary_cvt: no `cvt ' table\n" )); + FT_TRACE2(( "\n" )); + FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" )); error = FT_Err_Ok; goto Exit; } @@ -3388,6 +3713,7 @@ } else { + localpoints = NULL; points = sharedpoints; point_count = spoint_count; } @@ -3397,9 +3723,7 @@ point_count == 0 ? face->cvt_size : point_count ); - if ( !points || - !deltas || - ( localpoints == ALL_POINTS && point_count != face->cvt_size ) ) + if ( !points || !deltas ) ; /* failure, ignore it */ else if ( localpoints == ALL_POINTS ) @@ -3425,10 +3749,10 @@ { FT_TRACE7(( " %d: %f -> %f\n", j, - ( FT_fdot6ToFixed( face->cvt[j] ) + - old_cvt_delta ) / 65536.0, - ( FT_fdot6ToFixed( face->cvt[j] ) + - cvt_deltas[j] ) / 65536.0 )); + (double)( FT_fdot6ToFixed( face->cvt[j] ) + + old_cvt_delta ) / 65536, + (double)( FT_fdot6ToFixed( face->cvt[j] ) + + cvt_deltas[j] ) / 65536 )); count++; } #endif @@ -3467,10 +3791,10 @@ { FT_TRACE7(( " %d: %f -> %f\n", pindex, - ( FT_fdot6ToFixed( face->cvt[pindex] ) + - old_cvt_delta ) / 65536.0, - ( FT_fdot6ToFixed( face->cvt[pindex] ) + - cvt_deltas[pindex] ) / 65536.0 )); + (double)( FT_fdot6ToFixed( face->cvt[pindex] ) + + old_cvt_delta ) / 65536, + (double)( FT_fdot6ToFixed( face->cvt[pindex] ) + + cvt_deltas[pindex] ) / 65536 )); count++; } #endif @@ -3514,6 +3838,16 @@ NULL ); return error; + +#else /* !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + FT_UNUSED( face ); + FT_UNUSED( stream ); + + return FT_Err_Ok; + +#endif /* !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + } @@ -3725,20 +4059,12 @@ * @Description: * Apply the appropriate deltas to the current glyph. * - * @Input: - * face :: - * A handle to the target face object. - * - * glyph_index :: - * The index of the glyph being modified. - * - * n_points :: - * The number of the points in the glyph, including - * phantom points. - * * @InOut: + * loader :: + * A handle to the loader object. + * * outline :: - * The outline to change. + * The outline to change, with appended phantom points. * * @Output: * unrounded :: @@ -3749,15 +4075,16 @@ * FreeType error code. 0 means success. */ FT_LOCAL_DEF( FT_Error ) - TT_Vary_Apply_Glyph_Deltas( TT_Face face, - FT_UInt glyph_index, + TT_Vary_Apply_Glyph_Deltas( TT_Loader loader, FT_Outline* outline, - FT_Vector* unrounded, - FT_UInt n_points ) + FT_Vector* unrounded ) { FT_Error error; - FT_Stream stream = face->root.stream; - FT_Memory memory = stream->memory; + TT_Face face = loader->face; + FT_Stream stream = face->root.stream; + FT_Memory memory = stream->memory; + FT_UInt glyph_index = loader->glyph_index; + FT_UInt n_points = (FT_UInt)outline->n_points + 4; FT_Vector* points_org = NULL; /* coordinates in 16.16 format */ FT_Vector* points_out = NULL; /* coordinates in 16.16 format */ @@ -3975,50 +4302,22 @@ FT_Fixed point_delta_y = FT_MulFix( deltas_y[j], apply ); - if ( j < n_points - 4 ) - { - point_deltas_x[j] = old_point_delta_x + point_delta_x; - point_deltas_y[j] = old_point_delta_y + point_delta_y; - } - else - { - /* To avoid double adjustment of advance width or height, */ - /* adjust phantom points only if there is no HVAR or VVAR */ - /* support, respectively. */ - if ( j == ( n_points - 4 ) && - !( face->variation_support & - TT_FACE_FLAG_VAR_LSB ) ) - point_deltas_x[j] = old_point_delta_x + point_delta_x; - - else if ( j == ( n_points - 3 ) && - !( face->variation_support & - TT_FACE_FLAG_VAR_HADVANCE ) ) - point_deltas_x[j] = old_point_delta_x + point_delta_x; - - else if ( j == ( n_points - 2 ) && - !( face->variation_support & - TT_FACE_FLAG_VAR_TSB ) ) - point_deltas_y[j] = old_point_delta_y + point_delta_y; - - else if ( j == ( n_points - 1 ) && - !( face->variation_support & - TT_FACE_FLAG_VAR_VADVANCE ) ) - point_deltas_y[j] = old_point_delta_y + point_delta_y; - } + point_deltas_x[j] = old_point_delta_x + point_delta_x; + point_deltas_y[j] = old_point_delta_y + point_delta_y; #ifdef FT_DEBUG_LEVEL_TRACE if ( point_delta_x || point_delta_y ) { FT_TRACE7(( " %d: (%f, %f) -> (%f, %f)\n", j, - ( FT_intToFixed( outline->points[j].x ) + - old_point_delta_x ) / 65536.0, - ( FT_intToFixed( outline->points[j].y ) + - old_point_delta_y ) / 65536.0, - ( FT_intToFixed( outline->points[j].x ) + - point_deltas_x[j] ) / 65536.0, - ( FT_intToFixed( outline->points[j].y ) + - point_deltas_y[j] ) / 65536.0 )); + (double)( FT_intToFixed( outline->points[j].x ) + + old_point_delta_x ) / 65536, + (double)( FT_intToFixed( outline->points[j].y ) + + old_point_delta_y ) / 65536, + (double)( FT_intToFixed( outline->points[j].x ) + + point_deltas_x[j] ) / 65536, + (double)( FT_intToFixed( outline->points[j].y ) + + point_deltas_y[j] ) / 65536 )); count++; } #endif @@ -4077,50 +4376,22 @@ FT_Pos point_delta_y = points_out[j].y - points_org[j].y; - if ( j < n_points - 4 ) - { - point_deltas_x[j] = old_point_delta_x + point_delta_x; - point_deltas_y[j] = old_point_delta_y + point_delta_y; - } - else - { - /* To avoid double adjustment of advance width or height, */ - /* adjust phantom points only if there is no HVAR or VVAR */ - /* support, respectively. */ - if ( j == ( n_points - 4 ) && - !( face->variation_support & - TT_FACE_FLAG_VAR_LSB ) ) - point_deltas_x[j] = old_point_delta_x + point_delta_x; - - else if ( j == ( n_points - 3 ) && - !( face->variation_support & - TT_FACE_FLAG_VAR_HADVANCE ) ) - point_deltas_x[j] = old_point_delta_x + point_delta_x; - - else if ( j == ( n_points - 2 ) && - !( face->variation_support & - TT_FACE_FLAG_VAR_TSB ) ) - point_deltas_y[j] = old_point_delta_y + point_delta_y; - - else if ( j == ( n_points - 1 ) && - !( face->variation_support & - TT_FACE_FLAG_VAR_VADVANCE ) ) - point_deltas_y[j] = old_point_delta_y + point_delta_y; - } + point_deltas_x[j] = old_point_delta_x + point_delta_x; + point_deltas_y[j] = old_point_delta_y + point_delta_y; #ifdef FT_DEBUG_LEVEL_TRACE if ( point_delta_x || point_delta_y ) { FT_TRACE7(( " %d: (%f, %f) -> (%f, %f)\n", j, - ( FT_intToFixed( outline->points[j].x ) + - old_point_delta_x ) / 65536.0, - ( FT_intToFixed( outline->points[j].y ) + - old_point_delta_y ) / 65536.0, - ( FT_intToFixed( outline->points[j].x ) + - point_deltas_x[j] ) / 65536.0, - ( FT_intToFixed( outline->points[j].y ) + - point_deltas_y[j] ) / 65536.0 )); + (double)( FT_intToFixed( outline->points[j].x ) + + old_point_delta_x ) / 65536, + (double)( FT_intToFixed( outline->points[j].y ) + + old_point_delta_y ) / 65536, + (double)( FT_intToFixed( outline->points[j].x ) + + point_deltas_x[j] ) / 65536, + (double)( FT_intToFixed( outline->points[j].y ) + + point_deltas_y[j] ) / 65536 )); count++; } #endif @@ -4144,6 +4415,24 @@ FT_TRACE5(( "\n" )); + /* To avoid double adjustment of advance width or height, */ + /* do not move phantom points if there is HVAR or VVAR */ + /* support, respectively. */ + if ( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) + { + point_deltas_x[n_points - 4] = 0; + point_deltas_y[n_points - 4] = 0; + point_deltas_x[n_points - 3] = 0; + point_deltas_y[n_points - 3] = 0; + } + if ( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) + { + point_deltas_x[n_points - 2] = 0; + point_deltas_y[n_points - 2] = 0; + point_deltas_x[n_points - 1] = 0; + point_deltas_y[n_points - 1] = 0; + } + for ( i = 0; i < n_points; i++ ) { unrounded[i].x += FT_fixedToFdot6( point_deltas_x[i] ); @@ -4153,6 +4442,24 @@ outline->points[i].y += FT_fixedToInt( point_deltas_y[i] ); } + /* To avoid double adjustment of advance width or height, */ + /* adjust phantom points only if there is no HVAR or VVAR */ + /* support, respectively. */ + if ( !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) + { + loader->pp1 = outline->points[n_points - 4]; + loader->pp2 = outline->points[n_points - 3]; + loader->linear = FT_PIX_ROUND( unrounded[n_points - 3].x - + unrounded[n_points - 4].x ) / 64; + } + if ( !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) + { + loader->pp3 = outline->points[n_points - 2]; + loader->pp4 = outline->points[n_points - 1]; + loader->vadvance = FT_PIX_ROUND( unrounded[n_points - 1].y - + unrounded[n_points - 2].y ) / 64; + } + Fail3: FT_FREE( point_deltas_x ); FT_FREE( point_deltas_y ); @@ -4186,22 +4493,25 @@ * the MM machinery in case it isn't loaded yet. */ FT_LOCAL_DEF( FT_Error ) - tt_get_var_blend( TT_Face face, + tt_get_var_blend( FT_Face face, /* TT_Face */ FT_UInt *num_coords, FT_Fixed* *coords, FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ) { - if ( face->blend ) + TT_Face ttface = (TT_Face)face; + + + if ( ttface->blend ) { if ( num_coords ) - *num_coords = face->blend->num_axis; + *num_coords = ttface->blend->num_axis; if ( coords ) - *coords = face->blend->coords; + *coords = ttface->blend->coords; if ( normalizedcoords ) - *normalizedcoords = face->blend->normalizedcoords; + *normalizedcoords = ttface->blend->normalizedcoords; if ( mm_var ) - *mm_var = face->blend->mmvar; + *mm_var = ttface->blend->mmvar; } else { @@ -4217,8 +4527,8 @@ } - static void - ft_var_done_item_variation_store( TT_Face face, + FT_LOCAL_DEF( void ) + tt_var_done_item_variation_store( FT_Face face, GX_ItemVarStore itemStore ) { FT_Memory memory = FT_FACE_MEMORY( face ); @@ -4246,6 +4556,18 @@ } + FT_LOCAL_DEF( void ) + tt_var_done_delta_set_index_map( FT_Face face, + GX_DeltaSetIdxMap deltaSetIdxMap ) + { + FT_Memory memory = FT_FACE_MEMORY( face ); + + + FT_FREE( deltaSetIdxMap->innerIndex ); + FT_FREE( deltaSetIdxMap->outerIndex ); + } + + /************************************************************************** * * @Function: @@ -4255,10 +4577,11 @@ * Free the blend internal data structure. */ FT_LOCAL_DEF( void ) - tt_done_blend( TT_Face face ) + tt_done_blend( FT_Face face ) { + TT_Face ttface = (TT_Face)face; FT_Memory memory = FT_FACE_MEMORY( face ); - GX_Blend blend = face->blend; + GX_Blend blend = ttface->blend; if ( blend ) @@ -4274,36 +4597,47 @@ FT_FREE( blend->normalized_stylecoords ); FT_FREE( blend->mmvar ); - if ( blend->avar_segment ) + if ( blend->avar_table ) { - for ( i = 0; i < num_axes; i++ ) - FT_FREE( blend->avar_segment[i].correspondence ); - FT_FREE( blend->avar_segment ); + if ( blend->avar_table->avar_segment ) + { + for ( i = 0; i < num_axes; i++ ) + FT_FREE( blend->avar_table->avar_segment[i].correspondence ); + FT_FREE( blend->avar_table->avar_segment ); + } + + tt_var_done_item_variation_store( face, + &blend->avar_table->itemStore ); + + tt_var_done_delta_set_index_map( face, + &blend->avar_table->axisMap ); + + FT_FREE( blend->avar_table ); } if ( blend->hvar_table ) { - ft_var_done_item_variation_store( face, + tt_var_done_item_variation_store( face, &blend->hvar_table->itemStore ); - FT_FREE( blend->hvar_table->widthMap.innerIndex ); - FT_FREE( blend->hvar_table->widthMap.outerIndex ); + tt_var_done_delta_set_index_map( face, + &blend->hvar_table->widthMap ); FT_FREE( blend->hvar_table ); } if ( blend->vvar_table ) { - ft_var_done_item_variation_store( face, + tt_var_done_item_variation_store( face, &blend->vvar_table->itemStore ); - FT_FREE( blend->vvar_table->widthMap.innerIndex ); - FT_FREE( blend->vvar_table->widthMap.outerIndex ); + tt_var_done_delta_set_index_map( face, + &blend->vvar_table->widthMap ); FT_FREE( blend->vvar_table ); } if ( blend->mvar_table ) { - ft_var_done_item_variation_store( face, + tt_var_done_item_variation_store( face, &blend->mvar_table->itemStore ); FT_FREE( blend->mvar_table->values ); @@ -4319,7 +4653,7 @@ #else /* !TT_CONFIG_OPTION_GX_VAR_SUPPORT */ /* ANSI C doesn't like empty source files */ - typedef int _tt_gxvar_dummy; + typedef int tt_gxvar_dummy_; #endif /* !TT_CONFIG_OPTION_GX_VAR_SUPPORT */ diff --git a/lib/libesp32_lvgl/freetype/src/truetype/ttgxvar.h b/lib/libesp32_lvgl/freetype/src/truetype/ttgxvar.h index 26e89bcf7..e3da6d170 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/ttgxvar.h +++ b/lib/libesp32_lvgl/freetype/src/truetype/ttgxvar.h @@ -4,7 +4,7 @@ * * TrueType GX Font Variation loader (specification) * - * Copyright (C) 2004-2020 by + * Copyright (C) 2004-2023 by * David Turner, Robert Wilhelm, Werner Lemberg and George Williams. * * This file is part of the FreeType project, and may only be used, @@ -20,6 +20,7 @@ #define TTGXVAR_H_ +#include #include "ttobjs.h" @@ -62,55 +63,21 @@ FT_BEGIN_HEADER } GX_AVarSegmentRec, *GX_AVarSegment; - typedef struct GX_ItemVarDataRec_ + /************************************************************************** + * + * @Struct: + * GX_AVarTableRec + * + * @Description: + * Data from the `avar' table. + */ + typedef struct GX_AVarTableRec_ { - FT_UInt itemCount; /* number of delta sets per item */ - FT_UInt regionIdxCount; /* number of region indices in this data */ - FT_UInt* regionIndices; /* array of `regionCount' indices; */ - /* these index `varRegionList' */ - FT_Short* deltaSet; /* array of `itemCount' deltas */ - /* use `innerIndex' for this array */ + GX_AVarSegment avar_segment; /* avar_segment[num_axis] */ + GX_ItemVarStoreRec itemStore; /* Item Variation Store */ + GX_DeltaSetIdxMapRec axisMap; /* Axis Mapping */ - } GX_ItemVarDataRec, *GX_ItemVarData; - - - /* contribution of one axis to a region */ - typedef struct GX_AxisCoordsRec_ - { - FT_Fixed startCoord; - FT_Fixed peakCoord; /* zero means no effect (factor = 1) */ - FT_Fixed endCoord; - - } GX_AxisCoordsRec, *GX_AxisCoords; - - - typedef struct GX_VarRegionRec_ - { - GX_AxisCoords axisList; /* array of axisCount records */ - - } GX_VarRegionRec, *GX_VarRegion; - - - /* item variation store */ - typedef struct GX_ItemVarStoreRec_ - { - FT_UInt dataCount; - GX_ItemVarData varData; /* array of dataCount records; */ - /* use `outerIndex' for this array */ - FT_UShort axisCount; - FT_UInt regionCount; /* total number of regions defined */ - GX_VarRegion varRegionList; - - } GX_ItemVarStoreRec, *GX_ItemVarStore; - - - typedef struct GX_DeltaSetIdxMapRec_ - { - FT_UInt mapCount; - FT_UInt* outerIndex; /* indices to item var data */ - FT_UInt* innerIndex; /* indices to delta set */ - - } GX_DeltaSetIdxMapRec, *GX_DeltaSetIdxMap; + } GX_AVarTableRec, *GX_AVarTable; /************************************************************************** @@ -245,7 +212,7 @@ FT_BEGIN_HEADER * A Boolean; if set, FreeType tried to load (and parse) the `avar' * table. * - * avar_segment :: + * avar_table :: * Data from the `avar' table. * * hvar_loaded :: @@ -310,7 +277,7 @@ FT_BEGIN_HEADER /* normalized_stylecoords[num_namedstyles][num_axis] */ FT_Bool avar_loaded; - GX_AVarSegment avar_segment; /* avar_segment[num_axis] */ + GX_AVarTable avar_table; FT_Bool hvar_loaded; FT_Bool hvar_checked; @@ -376,70 +343,103 @@ FT_BEGIN_HEADER #define TTAG_wdth FT_MAKE_TAG( 'w', 'd', 't', 'h' ) #define TTAG_opsz FT_MAKE_TAG( 'o', 'p', 's', 'z' ) #define TTAG_slnt FT_MAKE_TAG( 's', 'l', 'n', 't' ) +#define TTAG_ital FT_MAKE_TAG( 'i', 't', 'a', 'l' ) FT_LOCAL( FT_Error ) - TT_Set_MM_Blend( TT_Face face, + TT_Set_MM_Blend( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - TT_Get_MM_Blend( TT_Face face, + TT_Get_MM_Blend( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - TT_Set_Var_Design( TT_Face face, + TT_Set_Var_Design( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - TT_Get_MM_Var( TT_Face face, + TT_Get_MM_Var( FT_Face face, FT_MM_Var* *master ); FT_LOCAL( FT_Error ) - TT_Get_Var_Design( TT_Face face, + TT_Get_Var_Design( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - TT_Set_Named_Instance( TT_Face face, + TT_Set_Named_Instance( FT_Face face, FT_UInt instance_index ); + FT_LOCAL( FT_Error ) + TT_Get_Default_Named_Instance( FT_Face face, + FT_UInt *instance_index ); + + FT_LOCAL( void ) + tt_construct_ps_name( FT_Face face ); + FT_LOCAL( FT_Error ) tt_face_vary_cvt( TT_Face face, FT_Stream stream ); FT_LOCAL( FT_Error ) - TT_Vary_Apply_Glyph_Deltas( TT_Face face, - FT_UInt glyph_index, + TT_Vary_Apply_Glyph_Deltas( TT_Loader loader, FT_Outline* outline, - FT_Vector* unrounded, - FT_UInt n_points ); + FT_Vector* unrounded ); FT_LOCAL( FT_Error ) - tt_hadvance_adjust( TT_Face face, + tt_hadvance_adjust( FT_Face face, FT_UInt gindex, FT_Int *adelta ); FT_LOCAL( FT_Error ) - tt_vadvance_adjust( TT_Face face, + tt_vadvance_adjust( FT_Face face, FT_UInt gindex, FT_Int *adelta ); FT_LOCAL( void ) - tt_apply_mvar( TT_Face face ); + tt_apply_mvar( FT_Face face ); FT_LOCAL( FT_Error ) - tt_get_var_blend( TT_Face face, + tt_var_load_item_variation_store( FT_Face face, + FT_ULong offset, + GX_ItemVarStore itemStore ); + + FT_LOCAL( FT_Error ) + tt_var_load_delta_set_index_mapping( FT_Face face, + FT_ULong offset, + GX_DeltaSetIdxMap map, + GX_ItemVarStore itemStore, + FT_ULong table_len ); + + FT_LOCAL( FT_ItemVarDelta ) + tt_var_get_item_delta( FT_Face face, + GX_ItemVarStore itemStore, + FT_UInt outerIndex, + FT_UInt innerIndex ); + + FT_LOCAL( void ) + tt_var_done_item_variation_store( FT_Face face, + GX_ItemVarStore itemStore ); + + FT_LOCAL( void ) + tt_var_done_delta_set_index_map( FT_Face face, + GX_DeltaSetIdxMap deltaSetIdxMap ); + + + FT_LOCAL( FT_Error ) + tt_get_var_blend( FT_Face face, FT_UInt *num_coords, FT_Fixed* *coords, FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ); FT_LOCAL( void ) - tt_done_blend( TT_Face face ); + tt_done_blend( FT_Face face ); #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ diff --git a/lib/libesp32_lvgl/freetype/src/truetype/ttinterp.c b/lib/libesp32_lvgl/freetype/src/truetype/ttinterp.c index 0c3cb10ae..79df4555d 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/ttinterp.c +++ b/lib/libesp32_lvgl/freetype/src/truetype/ttinterp.c @@ -4,7 +4,7 @@ * * TrueType bytecode interpreter (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -29,7 +29,6 @@ #include "ttinterp.h" #include "tterrors.h" -#include "ttsubpix.h" #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT #include "ttgxvar.h" #endif @@ -52,12 +51,6 @@ ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \ TT_INTERPRETER_VERSION_35 ) -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY -#define SUBPIXEL_HINTING_INFINALITY \ - ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \ - TT_INTERPRETER_VERSION_38 ) -#endif - #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL #define SUBPIXEL_HINTING_MINIMAL \ ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \ @@ -251,6 +244,14 @@ FT_FREE( exec->stack ); exec->stackSize = 0; + /* free glyf cvt working area */ + FT_FREE( exec->glyfCvt ); + exec->glyfCvtSize = 0; + + /* free glyf storage working area */ + FT_FREE( exec->glyfStorage ); + exec->glyfStoreSize = 0; + /* free call stack */ FT_FREE( exec->callStack ); exec->callSize = 0; @@ -267,115 +268,6 @@ } - /************************************************************************** - * - * @Function: - * Init_Context - * - * @Description: - * Initializes a context object. - * - * @Input: - * memory :: - * A handle to the parent memory object. - * - * @InOut: - * exec :: - * A handle to the target execution context. - * - * @Return: - * FreeType error code. 0 means success. - */ - static FT_Error - Init_Context( TT_ExecContext exec, - FT_Memory memory ) - { - FT_Error error; - - - FT_TRACE1(( "Init_Context: new object at %p\n", (void *)exec )); - - exec->memory = memory; - exec->callSize = 32; - - if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) ) - goto Fail_Memory; - - /* all values in the context are set to 0 already, but this is */ - /* here as a remainder */ - exec->maxPoints = 0; - exec->maxContours = 0; - - exec->stackSize = 0; - exec->glyphSize = 0; - - exec->stack = NULL; - exec->glyphIns = NULL; - - exec->face = NULL; - exec->size = NULL; - - return FT_Err_Ok; - - Fail_Memory: - FT_ERROR(( "Init_Context: not enough memory for %p\n", (void *)exec )); - TT_Done_Context( exec ); - - return error; - } - - - /************************************************************************** - * - * @Function: - * Update_Max - * - * @Description: - * Checks the size of a buffer and reallocates it if necessary. - * - * @Input: - * memory :: - * A handle to the parent memory object. - * - * multiplier :: - * The size in bytes of each element in the buffer. - * - * new_max :: - * The new capacity (size) of the buffer. - * - * @InOut: - * size :: - * The address of the buffer's current size expressed - * in elements. - * - * buff :: - * The address of the buffer base pointer. - * - * @Return: - * FreeType error code. 0 means success. - */ - FT_LOCAL_DEF( FT_Error ) - Update_Max( FT_Memory memory, - FT_ULong* size, - FT_ULong multiplier, - void* _pbuff, - FT_ULong new_max ) - { - FT_Error error; - void** pbuff = (void**)_pbuff; - - - if ( *size < new_max ) - { - if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) ) - return error; - *size = new_max; - } - - return FT_Err_Ok; - } - - /************************************************************************** * * @Function: @@ -400,6 +292,8 @@ * * @Note: * Only the glyph loader and debugger should call this function. + * + * Note that not all members of `TT_ExecContext` get initialized. */ FT_LOCAL_DEF( FT_Error ) TT_Load_Context( TT_ExecContext exec, @@ -407,9 +301,9 @@ TT_Size size ) { FT_Int i; - FT_ULong tmp; TT_MaxProfile* maxp; FT_Error error; + FT_Memory memory = exec->memory; exec->face = face; @@ -454,25 +348,15 @@ /* XXX: We reserve a little more elements on the stack to deal safely */ /* with broken fonts like arialbs, courbs, timesbs, etc. */ - tmp = (FT_ULong)exec->stackSize; - error = Update_Max( exec->memory, - &tmp, - sizeof ( FT_F26Dot6 ), - (void*)&exec->stack, - maxp->maxStackElements + 32 ); - exec->stackSize = (FT_Long)tmp; - if ( error ) + if ( FT_QRENEW_ARRAY( exec->stack, + exec->stackSize, + maxp->maxStackElements + 32 ) ) return error; + exec->stackSize = maxp->maxStackElements + 32; - tmp = exec->glyphSize; - error = Update_Max( exec->memory, - &tmp, - sizeof ( FT_Byte ), - (void*)&exec->glyphIns, - maxp->maxSizeOfInstructions ); - exec->glyphSize = (FT_UShort)tmp; - if ( error ) - return error; + /* free previous glyph code range */ + FT_FREE( exec->glyphIns ); + exec->glyphSize = 0; exec->pts.n_points = 0; exec->pts.n_contours = 0; @@ -609,19 +493,19 @@ memory = driver->root.root.memory; - /* allocate object */ + /* allocate object and zero everything inside */ if ( FT_NEW( exec ) ) goto Fail; - /* initialize it; in case of error this deallocates `exec' too */ - error = Init_Context( exec, memory ); - if ( error ) - goto Fail; + /* create callStack here, other allocations delayed */ + exec->memory = memory; + exec->callSize = 32; - return exec; + if ( FT_QNEW_ARRAY( exec->callStack, exec->callSize ) ) + FT_FREE( exec ); Fail: - return NULL; + return exec; } @@ -1572,11 +1456,37 @@ } + static void + Modify_CVT_Check( TT_ExecContext exc ) + { + if ( exc->iniRange == tt_coderange_glyph && + exc->cvt != exc->glyfCvt ) + { + FT_Memory memory = exc->memory; + FT_Error error; + + + FT_MEM_QRENEW_ARRAY( exc->glyfCvt, exc->glyfCvtSize, exc->cvtSize ); + exc->error = error; + if ( error ) + return; + + exc->glyfCvtSize = exc->cvtSize; + FT_ARRAY_COPY( exc->glyfCvt, exc->cvt, exc->glyfCvtSize ); + exc->cvt = exc->glyfCvt; + } + } + + FT_CALLBACK_DEF( void ) Write_CVT( TT_ExecContext exc, FT_ULong idx, FT_F26Dot6 value ) { + Modify_CVT_Check( exc ); + if ( exc->error ) + return; + exc->cvt[idx] = value; } @@ -1586,6 +1496,10 @@ FT_ULong idx, FT_F26Dot6 value ) { + Modify_CVT_Check( exc ); + if ( exc->error ) + return; + exc->cvt[idx] = FT_DivFix( value, Current_Ratio( exc ) ); } @@ -1595,6 +1509,10 @@ FT_ULong idx, FT_F26Dot6 value ) { + Modify_CVT_Check( exc ); + if ( exc->error ) + return; + exc->cvt[idx] = ADD_LONG( exc->cvt[idx], value ); } @@ -1604,6 +1522,10 @@ FT_ULong idx, FT_F26Dot6 value ) { + Modify_CVT_Check( exc ); + if ( exc->error ) + return; + exc->cvt[idx] = ADD_LONG( exc->cvt[idx], FT_DivFix( value, Current_Ratio( exc ) ) ); } @@ -1756,17 +1678,6 @@ if ( v != 0 ) { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - ( !exc->ignore_x_mode || - ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) ) - zone->cur[point].x = ADD_LONG( zone->cur[point].x, - FT_MulDiv( distance, - v, - exc->F_dot_P ) ); - else -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL /* Exception to the post-IUP curfew: Allow the x component of */ /* diagonal moves, but only post-IUP. DejaVu tries to adjust */ @@ -1872,12 +1783,6 @@ FT_UShort point, FT_F26Dot6 distance ) { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && !exc->ignore_x_mode ) - zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance ); - else -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility ) zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance ); @@ -3081,28 +2986,7 @@ args[0] = 0; } else - { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* subpixel hinting - avoid Typeman Dstroke and */ - /* IStroke and Vacuform rounds */ - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - ( ( I == 24 && - ( exc->face->sph_found_func_flags & - ( SPH_FDEF_SPACING_1 | - SPH_FDEF_SPACING_2 ) ) ) || - ( I == 22 && - ( exc->sph_in_func_flags & - SPH_FDEF_TYPEMAN_STROKES ) ) || - ( I == 8 && - ( exc->face->sph_found_func_flags & - SPH_FDEF_VACUFORM_ROUND_1 ) && - exc->iup_called ) ) ) - args[0] = 0; - else -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - args[0] = exc->storage[I]; - } + args[0] = exc->storage[I]; } @@ -3125,7 +3009,28 @@ ARRAY_BOUND_ERROR; } else + { + if ( exc->iniRange == tt_coderange_glyph && + exc->storage != exc->glyfStorage ) + { + FT_Memory memory = exc->memory; + FT_Error error; + + + FT_MEM_QRENEW_ARRAY( exc->glyfStorage, + exc->glyfStoreSize, + exc->storeSize ); + exc->error = error; + if ( error ) + return; + + exc->glyfStoreSize = exc->storeSize; + FT_ARRAY_COPY( exc->glyfStorage, exc->storage, exc->glyfStoreSize ); + exc->storage = exc->glyfStorage; + } + exc->storage[I] = args[1]; + } } @@ -3525,7 +3430,7 @@ return; } - exc->IP += args[0]; + exc->IP = ADD_LONG( exc->IP, args[0] ); if ( exc->IP < 0 || ( exc->callTop > 0 && exc->IP > exc->callStack[exc->callTop - 1].Def->end ) ) @@ -3595,109 +3500,9 @@ TT_DefRecord* rec; TT_DefRecord* limit; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* arguments to opcodes are skipped by `SKIP_Code' */ - FT_Byte opcode_pattern[9][12] = { - /* #0 inline delta function 1 */ - { - 0x4B, /* PPEM */ - 0x53, /* GTEQ */ - 0x23, /* SWAP */ - 0x4B, /* PPEM */ - 0x51, /* LTEQ */ - 0x5A, /* AND */ - 0x58, /* IF */ - 0x38, /* SHPIX */ - 0x1B, /* ELSE */ - 0x21, /* POP */ - 0x21, /* POP */ - 0x59 /* EIF */ - }, - /* #1 inline delta function 2 */ - { - 0x4B, /* PPEM */ - 0x54, /* EQ */ - 0x58, /* IF */ - 0x38, /* SHPIX */ - 0x1B, /* ELSE */ - 0x21, /* POP */ - 0x21, /* POP */ - 0x59 /* EIF */ - }, - /* #2 diagonal stroke function */ - { - 0x20, /* DUP */ - 0x20, /* DUP */ - 0xB0, /* PUSHB_1 */ - /* 1 */ - 0x60, /* ADD */ - 0x46, /* GC_cur */ - 0xB0, /* PUSHB_1 */ - /* 64 */ - 0x23, /* SWAP */ - 0x42 /* WS */ - }, - /* #3 VacuFormRound function */ - { - 0x45, /* RCVT */ - 0x23, /* SWAP */ - 0x46, /* GC_cur */ - 0x60, /* ADD */ - 0x20, /* DUP */ - 0xB0 /* PUSHB_1 */ - /* 38 */ - }, - /* #4 TTFautohint bytecode (old) */ - { - 0x20, /* DUP */ - 0x64, /* ABS */ - 0xB0, /* PUSHB_1 */ - /* 32 */ - 0x60, /* ADD */ - 0x66, /* FLOOR */ - 0x23, /* SWAP */ - 0xB0 /* PUSHB_1 */ - }, - /* #5 spacing function 1 */ - { - 0x01, /* SVTCA_x */ - 0xB0, /* PUSHB_1 */ - /* 24 */ - 0x43, /* RS */ - 0x58 /* IF */ - }, - /* #6 spacing function 2 */ - { - 0x01, /* SVTCA_x */ - 0x18, /* RTG */ - 0xB0, /* PUSHB_1 */ - /* 24 */ - 0x43, /* RS */ - 0x58 /* IF */ - }, - /* #7 TypeMan Talk DiagEndCtrl function */ - { - 0x01, /* SVTCA_x */ - 0x20, /* DUP */ - 0xB0, /* PUSHB_1 */ - /* 3 */ - 0x25, /* CINDEX */ - }, - /* #8 TypeMan Talk Align */ - { - 0x06, /* SPVTL */ - 0x7D, /* RDTG */ - }, - }; - FT_UShort opcode_patterns = 9; - FT_UShort opcode_pointer[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - FT_UShort opcode_size[9] = { 12, 8, 8, 6, 7, 4, 5, 4, 2 }; - FT_UShort i; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - /* FDEF is only allowed in `prep' or `fpgm' */ - if ( exc->curRange == tt_coderange_glyph ) + if ( exc->iniRange == tt_coderange_glyph ) { exc->error = FT_THROW( DEF_In_Glyf_Bytecode ); return; @@ -3739,136 +3544,15 @@ rec->opc = (FT_UInt16)n; rec->start = exc->IP + 1; rec->active = TRUE; - rec->inline_delta = FALSE; - rec->sph_fdef_flags = 0x0000; if ( n > exc->maxFunc ) exc->maxFunc = (FT_UInt16)n; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* We don't know for sure these are typeman functions, */ - /* however they are only active when RS 22 is called */ - if ( n >= 64 && n <= 66 ) - rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_STROKES; -#endif - /* Now skip the whole function definition. */ /* We don't allow nested IDEFS & FDEFs. */ while ( SkipCode( exc ) == SUCCESS ) { - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( SUBPIXEL_HINTING_INFINALITY ) - { - for ( i = 0; i < opcode_patterns; i++ ) - { - if ( opcode_pointer[i] < opcode_size[i] && - exc->opcode == opcode_pattern[i][opcode_pointer[i]] ) - { - opcode_pointer[i] += 1; - - if ( opcode_pointer[i] == opcode_size[i] ) - { - FT_TRACE6(( "sph: Function %d, opcode ptrn: %d, %s %s\n", - i, n, - exc->face->root.family_name, - exc->face->root.style_name )); - - switch ( i ) - { - case 0: - rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_1; - exc->face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_1; - break; - - case 1: - rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_2; - exc->face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_2; - break; - - case 2: - switch ( n ) - { - /* needs to be implemented still */ - case 58: - rec->sph_fdef_flags |= SPH_FDEF_DIAGONAL_STROKE; - exc->face->sph_found_func_flags |= SPH_FDEF_DIAGONAL_STROKE; - } - break; - - case 3: - switch ( n ) - { - case 0: - rec->sph_fdef_flags |= SPH_FDEF_VACUFORM_ROUND_1; - exc->face->sph_found_func_flags |= SPH_FDEF_VACUFORM_ROUND_1; - } - break; - - case 4: - /* probably not necessary to detect anymore */ - rec->sph_fdef_flags |= SPH_FDEF_TTFAUTOHINT_1; - exc->face->sph_found_func_flags |= SPH_FDEF_TTFAUTOHINT_1; - break; - - case 5: - switch ( n ) - { - case 0: - case 1: - case 2: - case 4: - case 7: - case 8: - rec->sph_fdef_flags |= SPH_FDEF_SPACING_1; - exc->face->sph_found_func_flags |= SPH_FDEF_SPACING_1; - } - break; - - case 6: - switch ( n ) - { - case 0: - case 1: - case 2: - case 4: - case 7: - case 8: - rec->sph_fdef_flags |= SPH_FDEF_SPACING_2; - exc->face->sph_found_func_flags |= SPH_FDEF_SPACING_2; - } - break; - - case 7: - rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; - exc->face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; - break; - - case 8: -#if 0 - rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; - exc->face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL; -#endif - break; - } - opcode_pointer[i] = 0; - } - } - - else - opcode_pointer[i] = 0; - } - - /* Set sph_compatibility_mode only when deltas are detected */ - exc->face->sph_compatibility_mode = - ( ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_1 ) | - ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ); - } - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - switch ( exc->opcode ) { case 0x89: /* IDEF */ @@ -3896,10 +3580,6 @@ TT_CallRec* pRec; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - exc->sph_in_func_flags = 0x0000; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - if ( exc->callTop <= 0 ) /* We encountered an ENDF without a call */ { exc->error = FT_THROW( ENDF_In_Exec_Stream ); @@ -3987,17 +3667,6 @@ if ( !def->active ) goto Fail; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - ( ( exc->iup_called && - ( exc->sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) || - ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) ) - goto Fail; - else - exc->sph_in_func_flags = def->sph_fdef_flags; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - /* check the call stack */ if ( exc->callTop >= exc->callSize ) { @@ -4075,15 +3744,6 @@ if ( !def->active ) goto Fail; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) - goto Fail; - else - exc->sph_in_func_flags = def->sph_fdef_flags; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - /* check stack */ if ( exc->callTop >= exc->callSize ) { @@ -4133,7 +3793,7 @@ /* we enable IDEF only in `prep' or `fpgm' */ - if ( exc->curRange == tt_coderange_glyph ) + if ( exc->iniRange == tt_coderange_glyph ) { exc->error = FT_THROW( DEF_In_Glyf_Bytecode ); return; @@ -4362,7 +4022,7 @@ if ( ( opcode & 1 ) != 0 ) { - C = B; /* counter clockwise rotation */ + C = B; /* counter-clockwise rotation */ B = A; A = NEG_LONG( C ); } @@ -4989,14 +4649,6 @@ } } -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */ - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - FT_ABS( D ) == 64 ) - D += 1; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - args[0] = D; } @@ -5050,7 +4702,7 @@ if ( ( opcode & 1 ) != 0 ) { - C = B; /* counter clockwise rotation */ + C = B; /* counter-clockwise rotation */ B = A; A = NEG_LONG( C ); } @@ -5074,7 +4726,7 @@ if ( ( opcode & 1 ) != 0 ) { - C = B; /* counter clockwise rotation */ + C = B; /* counter-clockwise rotation */ B = A; A = NEG_LONG( C ); } @@ -5248,18 +4900,16 @@ } } - exc->GS.instruct_control &= ~(FT_Byte)Kf; - exc->GS.instruct_control |= (FT_Byte)L; - - if ( K == 3 ) + /* INSTCTRL should only be used in the CVT program */ + if ( exc->iniRange == tt_coderange_cvt ) { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* INSTCTRL modifying flag 3 also has an effect */ - /* outside of the CVT program */ - if ( SUBPIXEL_HINTING_INFINALITY ) - exc->ignore_x_mode = FT_BOOL( L == 4 ); -#endif + exc->GS.instruct_control &= ~(FT_Byte)Kf; + exc->GS.instruct_control |= (FT_Byte)L; + } + /* except to change the subpixel flags temporarily */ + else if ( exc->iniRange == tt_coderange_glyph && K == 3 ) + { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL /* Native ClearType fonts sign a waiver that turns off all backward */ /* compatibility hacks and lets them program points to the grid like */ @@ -5268,6 +4918,8 @@ exc->backward_compatibility = !FT_BOOL( L == 4 ); #endif } + else if ( exc->pedantic_hinting ) + exc->error = FT_THROW( Invalid_Reference ); } @@ -5589,12 +5241,6 @@ } } else -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* doesn't follow Cleartype spec but produces better result */ - if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode ) - Move_Zp2_Point( exc, point, 0, dy, TRUE ); - else -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ Move_Zp2_Point( exc, point, dx, dy, TRUE ); exc->GS.loop--; @@ -5755,76 +5401,6 @@ } } else -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode ) - { - FT_Int B1, B2; - - - /* If not using ignore_x_mode rendering, allow ZP2 move. */ - /* If inline deltas aren't allowed, skip ZP2 move. */ - /* If using ignore_x_mode rendering, allow ZP2 point move if: */ - /* - freedom vector is y and sph_compatibility_mode is off */ - /* - the glyph is composite and the move is in the Y direction */ - /* - the glyph is specifically set to allow SHPIX moves */ - /* - the move is on a previously Y-touched point */ - - /* save point for later comparison */ - B1 = exc->zp2.cur[point].y; - - if ( exc->face->sph_compatibility_mode ) - { - if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) - dy = FT_PIX_ROUND( B1 + dy ) - B1; - - /* skip post-iup deltas */ - if ( exc->iup_called && - ( ( exc->sph_in_func_flags & SPH_FDEF_INLINE_DELTA_1 ) || - ( exc->sph_in_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ) ) - goto Skip; - - if ( !( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) && - ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || - ( exc->zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y ) || - ( exc->sph_tweak_flags & SPH_TWEAK_DO_SHPIX ) ) ) - Move_Zp2_Point( exc, point, 0, dy, TRUE ); - - /* save new point */ - if ( exc->GS.freeVector.y != 0 ) - { - B2 = exc->zp2.cur[point].y; - - /* reverse any disallowed moves */ - if ( ( B1 & 63 ) == 0 && - ( B2 & 63 ) != 0 && - B1 != B2 ) - Move_Zp2_Point( exc, point, 0, NEG_LONG( dy ), TRUE ); - } - } - else if ( exc->GS.freeVector.y != 0 ) - { - Move_Zp2_Point( exc, point, dx, dy, TRUE ); - - /* save new point */ - B2 = exc->zp2.cur[point].y; - - /* reverse any disallowed moves */ - if ( ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) && - ( B1 & 63 ) != 0 && - ( B2 & 63 ) != 0 && - B1 != B2 ) - Move_Zp2_Point( exc, - point, - NEG_LONG( dx ), - NEG_LONG( dy ), - TRUE ); - } - else if ( exc->sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL ) - Move_Zp2_Point( exc, point, dx, dy, TRUE ); - } - else -#endif #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL if ( SUBPIXEL_HINTING_MINIMAL && exc->backward_compatibility ) @@ -5844,9 +5420,6 @@ #endif Move_Zp2_Point( exc, point, dx, dy, TRUE ); -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - Skip: -#endif exc->GS.loop--; } @@ -5891,28 +5464,6 @@ distance = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 ); -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* subpixel hinting - make MSIRP respect CVT cut-in; */ - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) - { - FT_F26Dot6 control_value_cutin = exc->GS.control_value_cutin; - FT_F26Dot6 delta; - - - if ( !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) - control_value_cutin = 0; - - delta = SUB_LONG( distance, args[1] ); - if ( delta < 0 ) - delta = NEG_LONG( delta ); - - if ( delta >= control_value_cutin ) - distance = args[1]; - } -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - exc->func_move( exc, &exc->zp1, point, @@ -5953,14 +5504,7 @@ if ( ( exc->opcode & 1 ) != 0 ) { cur_dist = FAST_PROJECT( &exc->zp0.cur[point] ); -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) - distance = SUB_LONG( Round_None( exc, cur_dist, 3 ), cur_dist ); - else -#endif - distance = SUB_LONG( exc->func_round( exc, cur_dist, 3 ), cur_dist ); + distance = SUB_LONG( exc->func_round( exc, cur_dist, 3 ), cur_dist ); } else distance = 0; @@ -6023,27 +5567,12 @@ if ( exc->GS.gep0 == 0 ) /* If in twilight zone */ { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* Only adjust if not in sph_compatibility_mode or ignore_x_mode. */ - /* Determined via experimentation and may be incorrect... */ - if ( !( SUBPIXEL_HINTING_INFINALITY && - ( exc->ignore_x_mode && - exc->face->sph_compatibility_mode ) ) ) -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - exc->zp0.org[point].x = TT_MulFix14( distance, + exc->zp0.org[point].x = TT_MulFix14( distance, exc->GS.freeVector.x ); exc->zp0.org[point].y = TT_MulFix14( distance, exc->GS.freeVector.y ); exc->zp0.cur[point] = exc->zp0.org[point]; } -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - ( exc->sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) && - distance > 0 && - exc->GS.freeVector.y != 0 ) - distance = 0; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ org_dist = FAST_PROJECT( &exc->zp0.cur[point] ); @@ -6053,15 +5582,6 @@ FT_F26Dot6 delta; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 && - exc->GS.freeVector.y == 0 && - !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) - control_value_cutin = 0; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - delta = SUB_LONG( distance, org_dist ); if ( delta < 0 ) delta = NEG_LONG( delta ); @@ -6069,14 +5589,7 @@ if ( delta > control_value_cutin ) distance = org_dist; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) - distance = Round_None( exc, distance, 3 ); - else -#endif - distance = exc->func_round( exc, distance, 3 ); + distance = exc->func_round( exc, distance, 3 ); } exc->func_move( exc, &exc->zp0, point, SUB_LONG( distance, org_dist ) ); @@ -6169,14 +5682,7 @@ if ( ( exc->opcode & 4 ) != 0 ) { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 ) - distance = Round_None( exc, org_dist, exc->opcode & 3 ); - else -#endif - distance = exc->func_round( exc, org_dist, exc->opcode & 3 ); + distance = exc->func_round( exc, org_dist, exc->opcode & 3 ); } else distance = Round_None( exc, org_dist, exc->opcode & 3 ); @@ -6188,14 +5694,6 @@ FT_F26Dot6 minimum_distance = exc->GS.minimum_distance; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 && - !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) - minimum_distance = 0; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - if ( org_dist >= 0 ) { if ( distance < minimum_distance ) @@ -6338,41 +5836,7 @@ distance = exc->func_round( exc, cvt_dist, exc->opcode & 3 ); } else - { - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /* do cvt cut-in always in MIRP for sph */ - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.gep0 == exc->GS.gep1 ) - { - FT_F26Dot6 control_value_cutin = exc->GS.control_value_cutin; - - - if ( exc->GS.freeVector.x != 0 && - !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) - control_value_cutin = 0; - - if ( exc->GS.freeVector.y != 0 && - ( exc->sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) ) - { - if ( cur_dist < -64 ) - cvt_dist -= 16; - else if ( cur_dist > 64 && cur_dist < 84 ) - cvt_dist += 32; - } - - delta = SUB_LONG( cvt_dist, org_dist ); - if ( delta < 0 ) - delta = NEG_LONG( delta ); - - if ( delta > control_value_cutin ) - cvt_dist = org_dist; - } -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - distance = Round_None( exc, cvt_dist, exc->opcode & 3 ); - } /* minimum distance test */ @@ -6381,14 +5845,6 @@ FT_F26Dot6 minimum_distance = exc->GS.minimum_distance; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 && - !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) ) - minimum_distance = 0; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - if ( org_dist >= 0 ) { if ( distance < minimum_distance ) @@ -6401,51 +5857,10 @@ } } -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.y != 0 ) - { - FT_Int B1, B2; - - - B1 = exc->zp1.cur[point].y; - - /* Round moves if necessary */ - if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) - distance = FT_PIX_ROUND( B1 + distance - cur_dist ) - B1 + cur_dist; - - if ( ( exc->opcode & 16 ) == 0 && - ( exc->opcode & 8 ) == 0 && - ( exc->sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) ) - distance += 64; - - exc->func_move( exc, - &exc->zp1, - point, - SUB_LONG( distance, cur_dist ) ); - - B2 = exc->zp1.cur[point].y; - - /* Reverse move if necessary */ - if ( ( exc->face->sph_compatibility_mode && - ( B1 & 63 ) == 0 && - ( B2 & 63 ) != 0 ) || - ( ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) && - ( B1 & 63 ) != 0 && - ( B2 & 63 ) != 0 ) ) - exc->func_move( exc, - &exc->zp1, - point, - SUB_LONG( cur_dist, distance ) ); - } - else -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - - exc->func_move( exc, - &exc->zp1, - point, - SUB_LONG( distance, cur_dist ) ); + exc->func_move( exc, + &exc->zp1, + point, + SUB_LONG( distance, cur_dist ) ); Fail: exc->GS.rp1 = exc->GS.rp0; @@ -6470,17 +5885,6 @@ FT_F26Dot6 distance; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->iup_called && - ( exc->sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) ) - { - exc->error = FT_THROW( Invalid_Reference ); - goto Fail; - } -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - if ( exc->top < exc->GS.loop || BOUNDS( exc->GS.rp0, exc->zp0.n_points ) ) { @@ -6855,7 +6259,7 @@ static void - _iup_worker_shift( IUP_Worker worker, + iup_worker_shift_( IUP_Worker worker, FT_UInt p1, FT_UInt p2, FT_UInt p ) @@ -6877,7 +6281,7 @@ static void - _iup_worker_interpolate( IUP_Worker worker, + iup_worker_interpolate_( IUP_Worker worker, FT_UInt p1, FT_UInt p2, FT_UInt ref1, @@ -7039,16 +6443,6 @@ contour = 0; point = 0; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode ) - { - exc->iup_called = TRUE; - if ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_IUP ) - return; - } -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - do { end_point = exc->pts.contours[contour] - exc->pts.first_point; @@ -7071,7 +6465,7 @@ { if ( ( exc->pts.tags[point] & mask ) != 0 ) { - _iup_worker_interpolate( &V, + iup_worker_interpolate_( &V, cur_touched + 1, point - 1, cur_touched, @@ -7083,17 +6477,17 @@ } if ( cur_touched == first_touched ) - _iup_worker_shift( &V, first_point, end_point, cur_touched ); + iup_worker_shift_( &V, first_point, end_point, cur_touched ); else { - _iup_worker_interpolate( &V, + iup_worker_interpolate_( &V, (FT_UShort)( cur_touched + 1 ), end_point, cur_touched, first_touched ); if ( first_touched > 0 ) - _iup_worker_interpolate( &V, + iup_worker_interpolate_( &V, first_point, first_touched - 1, cur_touched, @@ -7121,14 +6515,6 @@ FT_Long B; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->iup_called && - ( exc->sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) ) - goto Fail; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - P = (FT_ULong)exc->func_cur_ppem( exc ); nump = (FT_ULong)args[0]; /* some points theoretically may occur more than once, thus UShort isn't enough */ @@ -7181,87 +6567,21 @@ B++; B *= 1L << ( 6 - exc->GS.delta_shift ); -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( SUBPIXEL_HINTING_INFINALITY ) - { - /* - * Allow delta move if - * - * - not using ignore_x_mode rendering, - * - glyph is specifically set to allow it, or - * - glyph is composite and freedom vector is not in subpixel - * direction. - */ - if ( !exc->ignore_x_mode || - ( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ) || - ( exc->is_composite && exc->GS.freeVector.y != 0 ) ) - exc->func_move( exc, &exc->zp0, A, B ); - - /* Otherwise, apply subpixel hinting and compatibility mode */ - /* rules, always skipping deltas in subpixel direction. */ - else if ( exc->ignore_x_mode && exc->GS.freeVector.y != 0 ) - { - FT_UShort B1, B2; - - - /* save the y value of the point now; compare after move */ - B1 = (FT_UShort)exc->zp0.cur[A].y; - - /* Standard subpixel hinting: Allow y move for y-touched */ - /* points. This messes up DejaVu ... */ - if ( !exc->face->sph_compatibility_mode && - ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) ) - exc->func_move( exc, &exc->zp0, A, B ); - - /* compatibility mode */ - else if ( exc->face->sph_compatibility_mode && - !( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) ) - { - if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) - B = FT_PIX_ROUND( B1 + B ) - B1; - - /* Allow delta move if using sph_compatibility_mode, */ - /* IUP has not been called, and point is touched on Y. */ - if ( !exc->iup_called && - ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) ) - exc->func_move( exc, &exc->zp0, A, B ); - } - - B2 = (FT_UShort)exc->zp0.cur[A].y; - - /* Reverse this move if it results in a disallowed move */ - if ( exc->GS.freeVector.y != 0 && - ( ( exc->face->sph_compatibility_mode && - ( B1 & 63 ) == 0 && - ( B2 & 63 ) != 0 ) || - ( ( exc->sph_tweak_flags & - SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP ) && - ( B1 & 63 ) != 0 && - ( B2 & 63 ) != 0 ) ) ) - exc->func_move( exc, &exc->zp0, A, NEG_LONG( B ) ); - } - } - else -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - - { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* See `ttinterp.h' for details on backward compatibility */ - /* mode. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backward_compatibility ) - { - if ( !( exc->iupx_called && exc->iupy_called ) && - ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || - ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) ) ) - exc->func_move( exc, &exc->zp0, A, B ); - } - else -#endif + /* See `ttinterp.h' for details on backward compatibility */ + /* mode. */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility ) + { + if ( !( exc->iupx_called && exc->iupy_called ) && + ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || + ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) ) ) exc->func_move( exc, &exc->zp0, A, B ); } + else +#endif + exc->func_move( exc, &exc->zp0, A, B ); } } else @@ -7364,14 +6684,6 @@ * GETINFO[]: GET INFOrmation * Opcode range: 0x88 * Stack: uint32 --> uint32 - * - * XXX: UNDOCUMENTED: Selector bits higher than 9 are currently (May - * 2015) not documented in the OpenType specification. - * - * Selector bit 11 is incorrectly described as bit 8, while the - * real meaning of bit 8 (vertical LCD subpixels) stays - * undocumented. The same mistake can be found in Greg Hitchcock's - * whitepaper. */ static void Ins_GETINFO( TT_ExecContext exc, @@ -7383,31 +6695,8 @@ K = 0; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - /********************************* - * RASTERIZER VERSION - * Selector Bit: 0 - * Return Bit(s): 0-7 - */ - if ( SUBPIXEL_HINTING_INFINALITY && - ( args[0] & 1 ) != 0 && - exc->subpixel_hinting ) - { - if ( exc->ignore_x_mode ) - { - /* if in ClearType backward compatibility mode, */ - /* we sometimes change the TrueType version dynamically */ - K = exc->rasterizer_version; - FT_TRACE6(( "Setting rasterizer version %d\n", - exc->rasterizer_version )); - } - else - K = TT_INTERPRETER_VERSION_38; - } - else -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - if ( ( args[0] & 1 ) != 0 ) - K = driver->interpreter_version; + if ( ( args[0] & 1 ) != 0 ) + K = driver->interpreter_version; /********************************* * GLYPH ROTATED @@ -7430,8 +6719,6 @@ * VARIATION GLYPH * Selector Bit: 3 * Return Bit(s): 10 - * - * XXX: UNDOCUMENTED! */ if ( (args[0] & 8 ) != 0 && exc->face->blend ) K |= 1 << 10; @@ -7506,89 +6793,6 @@ } #endif -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( SUBPIXEL_HINTING_INFINALITY && - exc->rasterizer_version >= TT_INTERPRETER_VERSION_35 ) - { - - if ( exc->rasterizer_version >= 37 ) - { - /********************************* - * HINTING FOR SUBPIXEL - * Selector Bit: 6 - * Return Bit(s): 13 - */ - if ( ( args[0] & 64 ) != 0 && exc->subpixel_hinting ) - K |= 1 << 13; - - /********************************* - * COMPATIBLE WIDTHS ENABLED - * Selector Bit: 7 - * Return Bit(s): 14 - * - * Functionality still needs to be added - */ - if ( ( args[0] & 128 ) != 0 && exc->compatible_widths ) - K |= 1 << 14; - - /********************************* - * VERTICAL LCD SUBPIXELS? - * Selector Bit: 8 - * Return Bit(s): 15 - * - * Functionality still needs to be added - */ - if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd ) - K |= 1 << 15; - - /********************************* - * HINTING FOR BGR? - * Selector Bit: 9 - * Return Bit(s): 16 - * - * Functionality still needs to be added - */ - if ( ( args[0] & 512 ) != 0 && exc->bgr ) - K |= 1 << 16; - - if ( exc->rasterizer_version >= 38 ) - { - /********************************* - * SUBPIXEL POSITIONED? - * Selector Bit: 10 - * Return Bit(s): 17 - * - * Functionality still needs to be added - */ - if ( ( args[0] & 1024 ) != 0 && exc->subpixel_positioned ) - K |= 1 << 17; - - /********************************* - * SYMMETRICAL SMOOTHING - * Selector Bit: 11 - * Return Bit(s): 18 - * - * Functionality still needs to be added - */ - if ( ( args[0] & 2048 ) != 0 && exc->symmetrical_smoothing ) - K |= 1 << 18; - - /********************************* - * GRAY CLEARTYPE - * Selector Bit: 12 - * Return Bit(s): 19 - * - * Functionality still needs to be added - */ - if ( ( args[0] & 4096 ) != 0 && exc->gray_cleartype ) - K |= 1 << 19; - } - } - } - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - args[0] = K; } @@ -7723,54 +6927,14 @@ /* documentation is in ttinterp.h */ FT_EXPORT_DEF( FT_Error ) - TT_RunIns( TT_ExecContext exc ) + TT_RunIns( void* exec ) { + TT_ExecContext exc = (TT_ExecContext)exec; + FT_ULong ins_counter = 0; /* executed instructions counter */ FT_ULong num_twilight_points; FT_UShort i; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - FT_Byte opcode_pattern[1][2] = { - /* #8 TypeMan Talk Align */ - { - 0x06, /* SPVTL */ - 0x7D, /* RDTG */ - }, - }; - FT_UShort opcode_patterns = 1; - FT_UShort opcode_pointer[1] = { 0 }; - FT_UShort opcode_size[1] = { 1 }; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - exc->iup_called = FALSE; -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* - * Toggle backward compatibility according to what font wants, except - * when - * - * 1) we have a `tricky' font that heavily relies on the interpreter to - * render glyphs correctly, for example DFKai-SB, or - * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested. - * - * In those cases, backward compatibility needs to be turned off to get - * correct rendering. The rendering is then completely up to the - * font's programming. - * - */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->subpixel_hinting_lean && - !FT_IS_TRICKY( &exc->face->root ) ) - exc->backward_compatibility = !( exc->GS.instruct_control & 4 ); - else - exc->backward_compatibility = FALSE; - - exc->iupx_called = FALSE; - exc->iupy_called = FALSE; -#endif /* We restrict the number of twilight points to a reasonable, */ /* heuristic value to avoid slow execution of malformed bytecode. */ @@ -7781,8 +6945,8 @@ if ( num_twilight_points > 0xFFFFU ) num_twilight_points = 0xFFFFU; - FT_TRACE5(( "TT_RunIns: Resetting number of twilight points\n" - " from %d to the more reasonable value %ld\n", + FT_TRACE5(( "TT_RunIns: Resetting number of twilight points\n" )); + FT_TRACE5(( " from %d to the more reasonable value %ld\n", exc->twilight.n_points, num_twilight_points )); exc->twilight.n_points = (FT_UShort)num_twilight_points; @@ -7842,14 +7006,23 @@ exc->func_move_cvt = Move_CVT; } + exc->iniRange = exc->curRange; + Compute_Funcs( exc ); Compute_Round( exc, (FT_Byte)exc->GS.round_state ); + /* These flags cancel execution of some opcodes after IUP is called */ +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + exc->iupx_called = FALSE; + exc->iupy_called = FALSE; +#endif + do { exc->opcode = exc->code[exc->IP]; #ifdef FT_DEBUG_LEVEL_TRACE + if ( ft_trace_levels[trace_ttinterp] >= 6 ) { FT_Long cnt = FT_MIN( 8, exc->top ); FT_Long n; @@ -7907,7 +7080,7 @@ /* a variable number of arguments */ /* it is the job of the application to `activate' GX handling, */ - /* this is, calling any of the GX API functions on the current */ + /* that is, calling any of the GX API functions on the current */ /* font to select a variation instance */ if ( exc->face->blend ) exc->new_top = exc->args + exc->face->blend->num_axis; @@ -7928,39 +7101,6 @@ exc->step_ins = TRUE; exc->error = FT_Err_Ok; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - if ( SUBPIXEL_HINTING_INFINALITY ) - { - for ( i = 0; i < opcode_patterns; i++ ) - { - if ( opcode_pointer[i] < opcode_size[i] && - exc->opcode == opcode_pattern[i][opcode_pointer[i]] ) - { - opcode_pointer[i] += 1; - - if ( opcode_pointer[i] == opcode_size[i] ) - { - FT_TRACE6(( "sph: opcode ptrn: %d, %s %s\n", - i, - exc->face->root.family_name, - exc->face->root.style_name )); - - switch ( i ) - { - case 0: - break; - } - opcode_pointer[i] = 0; - } - } - else - opcode_pointer[i] = 0; - } - } - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - { FT_Long* args = exc->stack + exc->args; FT_Byte opcode = exc->opcode; @@ -8467,7 +7607,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT case 0x91: /* it is the job of the application to `activate' GX handling, */ - /* this is, calling any of the GX API functions on the current */ + /* that is, calling any of the GX API functions on the current */ /* font to select a variation instance */ if ( exc->face->blend ) Ins_GETVARIATION( exc, args ); @@ -8567,7 +7707,10 @@ /* increment instruction counter and check if we didn't */ /* run this program for too long (e.g. infinite loops). */ if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES ) - return FT_THROW( Execution_Too_Long ); + { + exc->error = FT_THROW( Execution_Too_Long ); + goto LErrorLabel_; + } LSuiteLabel_: if ( exc->IP >= exc->codeSize ) @@ -8586,6 +7729,7 @@ FT_TRACE4(( " %ld instruction%s executed\n", ins_counter, ins_counter == 1 ? "" : "s" )); + return FT_Err_Ok; LErrorCodeOverflow_: @@ -8601,7 +7745,7 @@ #else /* !TT_USE_BYTECODE_INTERPRETER */ /* ANSI C doesn't like empty source files */ - typedef int _tt_interp_dummy; + typedef int tt_interp_dummy_; #endif /* !TT_USE_BYTECODE_INTERPRETER */ diff --git a/lib/libesp32_lvgl/freetype/src/truetype/ttinterp.h b/lib/libesp32_lvgl/freetype/src/truetype/ttinterp.h index 6a83705a6..e98e258fe 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/ttinterp.h +++ b/lib/libesp32_lvgl/freetype/src/truetype/ttinterp.h @@ -4,7 +4,7 @@ * * TrueType bytecode interpreter (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -98,83 +98,45 @@ FT_BEGIN_HEADER } TT_CallRec, *TT_CallStack; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - /************************************************************************** - * - * These structures define rules used to tweak subpixel hinting for - * various fonts. "", 0, "", NULL value indicates to match any value. - */ - -#define SPH_MAX_NAME_SIZE 32 -#define SPH_MAX_CLASS_MEMBERS 100 - - typedef struct SPH_TweakRule_ - { - const char family[SPH_MAX_NAME_SIZE]; - const FT_UInt ppem; - const char style[SPH_MAX_NAME_SIZE]; - const FT_ULong glyph; - - } SPH_TweakRule; - - - typedef struct SPH_ScaleRule_ - { - const char family[SPH_MAX_NAME_SIZE]; - const FT_UInt ppem; - const char style[SPH_MAX_NAME_SIZE]; - const FT_ULong glyph; - const FT_ULong scale; - - } SPH_ScaleRule; - - - typedef struct SPH_Font_Class_ - { - const char name[SPH_MAX_NAME_SIZE]; - const char member[SPH_MAX_CLASS_MEMBERS][SPH_MAX_NAME_SIZE]; - - } SPH_Font_Class; - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - - /************************************************************************** * * The main structure for the interpreter which collects all necessary * variables and states. + * + * Members that are initialized by `TT_Load_Context` are marked with '!'. + * Members that are initialized by `TT_Run_Context` are marked with '@'. */ typedef struct TT_ExecContextRec_ { - TT_Face face; - TT_Size size; + TT_Face face; /* ! */ + TT_Size size; /* ! */ FT_Memory memory; /* instructions state */ FT_Error error; /* last execution error */ - FT_Long top; /* top of exec. stack */ + FT_Long top; /* @ top of exec. stack */ - FT_Long stackSize; /* size of exec. stack */ - FT_Long* stack; /* current exec. stack */ + FT_Long stackSize; /* ! size of exec. stack */ + FT_Long* stack; /* ! current exec. stack */ FT_Long args; - FT_Long new_top; /* new top after exec. */ + FT_Long new_top; /* new top after exec. */ - TT_GlyphZoneRec zp0, /* zone records */ - zp1, - zp2, - pts, - twilight; + TT_GlyphZoneRec zp0, /* @! zone records */ + zp1, /* @! */ + zp2, /* @! */ + pts, /* ! */ + twilight; /* ! */ - FT_Long pointSize; /* in 26.6 format */ - FT_Size_Metrics metrics; - TT_Size_Metrics tt_metrics; /* size metrics */ + FT_Long pointSize; /* ! in 26.6 format */ + FT_Size_Metrics metrics; /* ! */ + TT_Size_Metrics tt_metrics; /* ! size metrics */ - TT_GraphicsState GS; /* current graphics state */ + TT_GraphicsState GS; /* !@ current graphics state */ + FT_Int iniRange; /* initial code range number */ FT_Int curRange; /* current code range number */ FT_Byte* code; /* current code range */ FT_Long IP; /* current instruction pointer */ @@ -185,43 +147,47 @@ FT_BEGIN_HEADER FT_Bool step_ins; /* true if the interpreter must */ /* increment IP after ins. exec */ - FT_ULong cvtSize; - FT_Long* cvt; + FT_ULong cvtSize; /* ! */ + FT_Long* cvt; /* ! */ + FT_ULong glyfCvtSize; + FT_Long* glyfCvt; /* cvt working copy for glyph */ - FT_UInt glyphSize; /* glyph instructions buffer size */ - FT_Byte* glyphIns; /* glyph instructions buffer */ + FT_UInt glyphSize; /* ! glyph instructions buffer size */ + FT_Byte* glyphIns; /* ! glyph instructions buffer */ - FT_UInt numFDefs; /* number of function defs */ - FT_UInt maxFDefs; /* maximum number of function defs */ - TT_DefArray FDefs; /* table of FDefs entries */ + FT_UInt numFDefs; /* ! number of function defs */ + FT_UInt maxFDefs; /* ! maximum number of function defs */ + TT_DefArray FDefs; /* table of FDefs entries */ - FT_UInt numIDefs; /* number of instruction defs */ - FT_UInt maxIDefs; /* maximum number of ins defs */ - TT_DefArray IDefs; /* table of IDefs entries */ + FT_UInt numIDefs; /* ! number of instruction defs */ + FT_UInt maxIDefs; /* ! maximum number of ins defs */ + TT_DefArray IDefs; /* table of IDefs entries */ - FT_UInt maxFunc; /* maximum function index */ - FT_UInt maxIns; /* maximum instruction index */ + FT_UInt maxFunc; /* ! maximum function index */ + FT_UInt maxIns; /* ! maximum instruction index */ - FT_Int callTop, /* top of call stack during execution */ - callSize; /* size of call stack */ - TT_CallStack callStack; /* call stack */ + FT_Int callTop, /* @ top of call stack during execution */ + callSize; /* size of call stack */ + TT_CallStack callStack; /* call stack */ FT_UShort maxPoints; /* capacity of this context's `pts' */ FT_Short maxContours; /* record, expressed in points and */ /* contours. */ - TT_CodeRangeTable codeRangeTable; /* table of valid code ranges */ - /* useful for the debugger */ + TT_CodeRangeTable codeRangeTable; /* ! table of valid code ranges */ + /* useful for the debugger */ - FT_UShort storeSize; /* size of current storage */ - FT_Long* storage; /* storage area */ + FT_UShort storeSize; /* ! size of current storage */ + FT_Long* storage; /* ! storage area */ + FT_UShort glyfStoreSize; + FT_Long* glyfStorage; /* storage working copy for glyph */ FT_F26Dot6 period; /* values used for the */ FT_F26Dot6 phase; /* `SuperRounding' */ FT_F26Dot6 threshold; - FT_Bool instruction_trap; /* If `True', the interpreter will */ - /* exit after each instruction */ + FT_Bool instruction_trap; /* ! If `True', the interpreter */ + /* exits after each instruction */ TT_GraphicsState default_GS; /* graphics state resulting from */ /* the prep program */ @@ -238,7 +204,7 @@ FT_BEGIN_HEADER func_dualproj, /* current dual proj. function */ func_freeProj; /* current freedom proj. func */ - TT_Move_Func func_move; /* current point move function */ + TT_Move_Func func_move; /* current point move function */ TT_Move_Func func_move_orig; /* move original position function */ TT_Cur_Ppem_Func func_cur_ppem; /* get current proj. ppem value */ @@ -391,38 +357,6 @@ FT_BEGIN_HEADER FT_Bool grayscale_cleartype; #endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */ -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - TT_Round_Func func_round_sphn; /* subpixel rounding function */ - - FT_Bool subpixel_hinting; /* Using subpixel hinting? */ - FT_Bool ignore_x_mode; /* Standard rendering mode for */ - /* subpixel hinting. On if gray */ - /* or subpixel hinting is on. */ - - /* The following 6 aren't fully implemented but here for MS rasterizer */ - /* compatibility. */ - FT_Bool compatible_widths; /* compatible widths? */ - FT_Bool symmetrical_smoothing; /* symmetrical_smoothing? */ - FT_Bool bgr; /* bgr instead of rgb? */ - FT_Bool vertical_lcd; /* long side of LCD subpixel */ - /* rectangles is horizontal */ - FT_Bool subpixel_positioned; /* subpixel positioned */ - /* (DirectWrite ClearType)? */ - FT_Bool gray_cleartype; /* ClearType hinting but */ - /* grayscale rendering */ - - FT_Int rasterizer_version; /* MS rasterizer version */ - - FT_Bool iup_called; /* IUP called for glyph? */ - - FT_ULong sph_tweak_flags; /* flags to control */ - /* hint tweaks */ - - FT_ULong sph_in_func_flags; /* flags to indicate if in */ - /* special functions */ - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - /* We maintain two counters (in addition to the instruction counter) */ /* that act as loop detectors for LOOPCALL and jump opcodes with */ /* negative arguments. */ @@ -452,14 +386,6 @@ FT_BEGIN_HEADER FT_LOCAL( void ) TT_Clear_CodeRange( TT_ExecContext exec, FT_Int range ); - - - FT_LOCAL( FT_Error ) - Update_Max( FT_Memory memory, - FT_ULong* size, - FT_ULong multiplier, - void* _pbuff, - FT_ULong new_max ); #endif /* TT_USE_BYTECODE_INTERPRETER */ @@ -469,16 +395,15 @@ FT_BEGIN_HEADER * TT_New_Context * * @Description: - * Queries the face context for a given font. Note that there is - * now a _single_ execution context in the TrueType driver which is - * shared among faces. + * Create a `TT_ExecContext`. Note that there is now an execution + * context per `TT_Size` that is not shared among faces. * * @Input: - * face :: - * A handle to the source face object. + * driver :: + * A handle to the driver, used for memory allocation. * * @Return: - * A handle to the execution context. Initialized for `face'. + * A handle to a new empty execution context. * * @Note: * Only the glyph loader and debugger should call this function. @@ -529,7 +454,7 @@ FT_BEGIN_HEADER * invoked by the TrueType debugger. */ FT_EXPORT( FT_Error ) - TT_RunIns( TT_ExecContext exec ); + TT_RunIns( void* exec ); FT_END_HEADER diff --git a/lib/libesp32_lvgl/freetype/src/truetype/ttobjs.c b/lib/libesp32_lvgl/freetype/src/truetype/ttobjs.c index 06d456955..5b56af711 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/ttobjs.c +++ b/lib/libesp32_lvgl/freetype/src/truetype/ttobjs.c @@ -4,7 +4,7 @@ * * Objects manager (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -140,7 +140,31 @@ return error; } -#endif /* TT_USE_BYTECODE_INTERPRETER */ + + + /* + * Fonts embedded in PDFs are made unique by prepending randomization + * prefixes to their names: as defined in Section 5.5.3, 'Font Subsets', + * of the PDF Reference, they consist of 6 uppercase letters followed by + * the `+` sign. For safety, we do not skip prefixes violating this rule. + */ + + static const FT_String* + tt_skip_pdffont_random_tag( const FT_String* name ) + { + unsigned int i; + + + if ( ft_strlen( name ) < 8 || name[6] != '+' ) + return name; + + for ( i = 0; i < 6; i++ ) + if ( !ft_isupper( name[i] ) ) + return name; + + FT_TRACE7(( "name without randomization tag: %s\n", name + 7 )); + return name + 7; + } /* Compare the face with a list of well-known `tricky' fonts. */ @@ -151,7 +175,7 @@ { #define TRICK_NAMES_MAX_CHARACTERS 19 -#define TRICK_NAMES_COUNT 26 +#define TRICK_NAMES_COUNT 20 static const char trick_names[TRICK_NAMES_COUNT] [TRICK_NAMES_MAX_CHARACTERS + 1] = @@ -171,22 +195,28 @@ "DFGirl-W6-WIN-BF", /* dftt-h6.ttf; version 1.00, 1993 */ "DFGothic-EB", /* DynaLab Inc. 1992-1995 */ "DFGyoSho-Lt", /* DynaLab Inc. 1992-1995 */ - "DFHei-Md-HK-BF", /* maybe DynaLab Inc. */ + "DFHei", /* DynaLab Inc. 1992-1995 [DFHei-Bd-WIN-HK-BF] */ + /* covers "DFHei-Md-HK-BF", maybe DynaLab Inc. */ + "DFHSGothic-W5", /* DynaLab Inc. 1992-1995 */ "DFHSMincho-W3", /* DynaLab Inc. 1992-1995 */ "DFHSMincho-W7", /* DynaLab Inc. 1992-1995 */ "DFKaiSho-SB", /* dfkaisb.ttf */ - "DFKaiShu", - "DFKaiShu-Md-HK-BF", /* maybe DynaLab Inc. */ + "DFKaiShu", /* covers "DFKaiShu-Md-HK-BF", maybe DynaLab Inc. */ "DFKai-SB", /* kaiu.ttf; version 3.00, 1998 [DFKaiShu-SB-Estd-BF] */ - "DFMing-Bd-HK-BF", /* maybe DynaLab Inc. */ + + "DFMing", /* DynaLab Inc. 1992-1995 [DFMing-Md-WIN-HK-BF] */ + /* covers "DFMing-Bd-HK-BF", maybe DynaLab Inc. */ + "DLC", /* dftt-m7.ttf; version 1.00, 1993 [DLCMingBold] */ /* dftt-f5.ttf; version 1.00, 1993 [DLCFongSung] */ - "DLCHayMedium", /* dftt-b5.ttf; version 1.00, 1993 */ - "DLCHayBold", /* dftt-b7.ttf; version 1.00, 1993 */ - "DLCKaiMedium", /* dftt-k5.ttf; version 1.00, 1992 */ - "DLCLiShu", /* dftt-l5.ttf; version 1.00, 1992 */ - "DLCRoundBold", /* dftt-r7.ttf; version 1.00, 1993 */ + /* covers following */ + /* "DLCHayMedium", dftt-b5.ttf; version 1.00, 1993 */ + /* "DLCHayBold", dftt-b7.ttf; version 1.00, 1993 */ + /* "DLCKaiMedium", dftt-k5.ttf; version 1.00, 1992 */ + /* "DLCLiShu", dftt-l5.ttf; version 1.00, 1992 */ + /* "DLCRoundBold", dftt-r7.ttf; version 1.00, 1993 */ + "HuaTianKaiTi?", /* htkt2.ttf */ "HuaTianSongTi?", /* htst3.ttf */ "Ming(for ISO10646)", /* hkscsiic.ttf; version 0.12, 2007 [Ming] */ @@ -199,10 +229,12 @@ }; int nn; + const FT_String* name_without_tag; + name_without_tag = tt_skip_pdffont_random_tag( name ); for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ ) - if ( ft_strstr( name, trick_names[nn] ) ) + if ( ft_strstr( name_without_tag, trick_names[nn] ) ) return TRUE; return FALSE; @@ -277,10 +309,11 @@ tt_check_trickyness_sfnt_ids( TT_Face face ) { #define TRICK_SFNT_IDS_PER_FACE 3 -#define TRICK_SFNT_IDS_NUM_FACES 29 +#define TRICK_SFNT_IDS_NUM_FACES 31 static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES] - [TRICK_SFNT_IDS_PER_FACE] = { + [TRICK_SFNT_IDS_PER_FACE] = + { #define TRICK_SFNT_ID_cvt 0 #define TRICK_SFNT_ID_fpgm 1 @@ -430,6 +463,16 @@ { 0x00170003UL, 0x00000060UL }, /* cvt */ { 0xDBB4306EUL, 0x000058AAUL }, /* fpgm */ { 0xD643482AUL, 0x00000035UL } /* prep */ + }, + { /* DFHei-Bd-WIN-HK-BF, issue #1087 */ + { 0x1269EB58UL, 0x00000350UL }, /* cvt */ + { 0x5CD5957AUL, 0x00006A4EUL }, /* fpgm */ + { 0xF758323AUL, 0x00000380UL } /* prep */ + }, + { /* DFMing-Md-WIN-HK-BF, issue #1087 */ + { 0x122FEB0BUL, 0x00000350UL }, /* cvt */ + { 0x7F10919AUL, 0x000070A9UL }, /* fpgm */ + { 0x7CD7E7B7UL, 0x0000025CUL } /* prep */ } }; @@ -510,17 +553,27 @@ /* For first, check the face name for quick check. */ if ( face->family_name && tt_check_trickyness_family( face->family_name ) ) + { + FT_TRACE3(( "found as a tricky font" + " by its family name: %s\n", face->family_name )); return TRUE; + } /* Type42 fonts may lack `name' tables, we thus try to identify */ /* tricky fonts by checking the checksums of Type42-persistent */ /* sfnt tables (`cvt', `fpgm', and `prep'). */ if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) ) + { + FT_TRACE3(( "found as a tricky font" + " by its cvt/fpgm/prep table checksum\n" )); return TRUE; + } return FALSE; } +#endif /* TT_USE_BYTECODE_INTERPRETER */ + /* Check whether `.notdef' is the only glyph in the `loca' table. */ static FT_Bool @@ -529,7 +582,7 @@ FT_Bool result = FALSE; TT_Face face = (TT_Face)ttface; - FT_UInt asize; + FT_ULong asize; FT_ULong i; FT_ULong glyph_index = 0; FT_UInt count = 0; @@ -537,7 +590,7 @@ for( i = 0; i < face->num_locations; i++ ) { - tt_face_get_location( face, i, &asize ); + tt_face_get_location( ttface, i, &asize ); if ( asize > 0 ) { count += 1; @@ -666,14 +719,17 @@ if ( error ) goto Exit; +#ifdef TT_USE_BYTECODE_INTERPRETER if ( tt_check_trickyness( ttface ) ) ttface->face_flags |= FT_FACE_FLAG_TRICKY; +#endif error = tt_face_load_hdmx( face, stream ); if ( error ) goto Exit; - if ( FT_IS_SCALABLE( ttface ) ) + if ( FT_IS_SCALABLE( ttface ) || + FT_HAS_SBIX( ttface ) ) { #ifdef FT_CONFIG_OPTION_INCREMENTAL if ( !ttface->internal->incremental_interface ) @@ -712,8 +768,8 @@ tt_check_single_notdef( ttface ) ) { FT_TRACE5(( "tt_face_init:" - " Only the `.notdef' glyph has an outline.\n" - " " + " Only the `.notdef' glyph has an outline.\n" )); + FT_TRACE5(( " " " Resetting scalable flag to FALSE.\n" )); ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE; @@ -722,7 +778,6 @@ } #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - { FT_UInt instance_index = (FT_UInt)face_index >> 16; @@ -730,14 +785,11 @@ if ( FT_HAS_MULTIPLE_MASTERS( ttface ) && instance_index > 0 ) { - error = TT_Set_Named_Instance( face, instance_index ); + error = FT_Set_Named_Instance( ttface, instance_index ); if ( error ) goto Exit; - - tt_apply_mvar( face ); } } - #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ /* initialize standard glyph loading routines */ @@ -803,7 +855,7 @@ face->cvt_program_size = 0; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - tt_done_blend( face ); + tt_done_blend( ttface ); face->blend = NULL; #endif } @@ -949,7 +1001,7 @@ { size->cvt[i] = FT_MulFix( face->cvt[i], scale ); FT_TRACE6(( " %3d: %f (%f)\n", - i, face->cvt[i] / 64.0, size->cvt[i] / 64.0 )); + i, (double)face->cvt[i] / 64, (double)size->cvt[i] / 64 )); } FT_TRACE6(( "\n" )); @@ -1190,11 +1242,11 @@ /* rescale CVT when needed */ if ( size->cvt_ready < 0 ) { - FT_UInt i; + FT_UShort i; /* all twilight points are originally zero */ - for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ ) + for ( i = 0; i < size->twilight.n_points; i++ ) { size->twilight.org[i].x = 0; size->twilight.org[i].y = 0; @@ -1203,7 +1255,7 @@ } /* clear storage area */ - for ( i = 0; i < (FT_UInt)size->storage_size; i++ ) + for ( i = 0; i < size->storage_size; i++ ) size->storage[i] = 0; size->GS = tt_default_graphics_state; @@ -1283,39 +1335,29 @@ /************************************************************************** * * @Function: - * tt_size_reset + * tt_size_reset_height * * @Description: - * Reset a TrueType size when resolutions and character dimensions - * have been changed. + * Recompute a TrueType size's ascender, descender, and height + * when resolutions and character dimensions have been changed. + * Used for variation fonts as an iterator function. * * @Input: - * size :: - * A handle to the target size object. - * - * only_height :: - * Only recompute ascender, descender, and height; - * this flag is used for variation fonts where - * `tt_size_reset' is used as an iterator function. + * ft_size :: + * A handle to the target TT_Size object. This function will be called + * through a `FT_Size_Reset_Func` pointer which takes `FT_Size`. This + * function must take `FT_Size` as a result. The passed `FT_Size` is + * expected to point to a `TT_Size`. */ FT_LOCAL_DEF( FT_Error ) - tt_size_reset( TT_Size size, - FT_Bool only_height ) + tt_size_reset_height( FT_Size ft_size ) { - TT_Face face; - FT_Size_Metrics* size_metrics; - - - face = (TT_Face)size->root.face; - - /* nothing to do for CFF2 */ - if ( face->is_cff2 ) - return FT_Err_Ok; + TT_Size size = (TT_Size)ft_size; + TT_Face face = (TT_Face)size->root.face; + FT_Size_Metrics* size_metrics = &size->hinted_metrics; size->ttmetrics.valid = FALSE; - size_metrics = &size->hinted_metrics; - /* copy the result from base layer */ *size_metrics = size->root.metrics; @@ -1342,12 +1384,34 @@ size->ttmetrics.valid = TRUE; - if ( only_height ) - { - /* we must not recompute the scaling values here since */ - /* `tt_size_reset' was already called (with only_height = 0) */ - return FT_Err_Ok; - } + return FT_Err_Ok; + } + + + /************************************************************************** + * + * @Function: + * tt_size_reset + * + * @Description: + * Reset a TrueType size when resolutions and character dimensions + * have been changed. + * + * @Input: + * size :: + * A handle to the target size object. + */ + FT_LOCAL_DEF( FT_Error ) + tt_size_reset( TT_Size size ) + { + FT_Error error; + TT_Face face = (TT_Face)size->root.face; + FT_Size_Metrics* size_metrics = &size->hinted_metrics; + + + error = tt_size_reset_height( (FT_Size)size ); + if ( error ) + return error; if ( face->header.Flags & 8 ) { @@ -1381,6 +1445,8 @@ size->ttmetrics.y_ratio = 0x10000L; } + size->widthp = tt_face_get_device_metrics( face, size_metrics->x_ppem, 0 ); + size->metrics = size_metrics; #ifdef TT_USE_BYTECODE_INTERPRETER @@ -1415,9 +1481,6 @@ TT_Driver driver = (TT_Driver)ttdriver; driver->interpreter_version = TT_INTERPRETER_VERSION_35; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - driver->interpreter_version = TT_INTERPRETER_VERSION_38; -#endif #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL driver->interpreter_version = TT_INTERPRETER_VERSION_40; #endif diff --git a/lib/libesp32_lvgl/freetype/src/truetype/ttobjs.h b/lib/libesp32_lvgl/freetype/src/truetype/ttobjs.h index d986deabc..40eb37b4c 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/ttobjs.h +++ b/lib/libesp32_lvgl/freetype/src/truetype/ttobjs.h @@ -4,7 +4,7 @@ * * Objects manager (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -162,8 +162,6 @@ FT_BEGIN_HEADER FT_Long end; /* where does it end? */ FT_UInt opc; /* function #, or instruction code */ FT_Bool active; /* is it active? */ - FT_Bool inline_delta; /* is function that defines inline delta? */ - FT_ULong sph_fdef_flags; /* flags to identify special functions */ } TT_DefRecord, *TT_DefArray; @@ -282,6 +280,8 @@ FT_BEGIN_HEADER TT_Size_Metrics ttmetrics; + FT_Byte* widthp; /* glyph widths from the hdmx table */ + FT_ULong strike_index; /* 0xFFFFFFFF to indicate invalid */ #ifdef TT_USE_BYTECODE_INTERPRETER @@ -389,8 +389,10 @@ FT_BEGIN_HEADER #endif /* TT_USE_BYTECODE_INTERPRETER */ FT_LOCAL( FT_Error ) - tt_size_reset( TT_Size size, - FT_Bool only_height ); + tt_size_reset_height( FT_Size size ); + + FT_LOCAL( FT_Error ) + tt_size_reset( TT_Size size ); /************************************************************************** diff --git a/lib/libesp32_lvgl/freetype/src/truetype/ttpload.c b/lib/libesp32_lvgl/freetype/src/truetype/ttpload.c index b1255b88c..54a64c7b4 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/ttpload.c +++ b/lib/libesp32_lvgl/freetype/src/truetype/ttpload.c @@ -4,7 +4,7 @@ * * TrueType-specific tables loader (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -98,36 +98,23 @@ goto Exit; } - if ( face->header.Index_To_Loc_Format != 0 ) - { - shift = 2; + shift = face->header.Index_To_Loc_Format != 0 ? 2 : 1; - if ( table_len >= 0x40000L ) - { - FT_TRACE2(( "table too large\n" )); - table_len = 0x3FFFFL; - } - face->num_locations = table_len >> shift; - } - else + if ( table_len > 0x10000UL << shift ) { - shift = 1; - - if ( table_len >= 0x20000L ) - { - FT_TRACE2(( "table too large\n" )); - table_len = 0x1FFFFL; - } - face->num_locations = table_len >> shift; + FT_TRACE2(( "table too large\n" )); + table_len = 0x10000UL << shift; } + face->num_locations = table_len >> shift; + if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 ) { FT_TRACE2(( "glyph count mismatch! loca: %ld, maxp: %ld\n", face->num_locations - 1, face->root.num_glyphs )); /* we only handle the case where `maxp' gives a larger value */ - if ( face->num_locations <= (FT_ULong)face->root.num_glyphs ) + if ( face->num_locations < (FT_ULong)face->root.num_glyphs + 1 ) { FT_ULong new_loca_len = ( (FT_ULong)face->root.num_glyphs + 1 ) << shift; @@ -193,10 +180,11 @@ FT_LOCAL_DEF( FT_ULong ) - tt_face_get_location( TT_Face face, - FT_UInt gindex, - FT_UInt *asize ) + tt_face_get_location( FT_Face face, /* TT_Face */ + FT_UInt gindex, + FT_ULong *asize ) { + TT_Face ttface = (TT_Face)face; FT_ULong pos1, pos2; FT_Byte* p; FT_Byte* p_limit; @@ -204,12 +192,12 @@ pos1 = pos2 = 0; - if ( gindex < face->num_locations ) + if ( gindex < ttface->num_locations ) { - if ( face->header.Index_To_Loc_Format != 0 ) + if ( ttface->header.Index_To_Loc_Format != 0 ) { - p = face->glyph_locations + gindex * 4; - p_limit = face->glyph_locations + face->num_locations * 4; + p = ttface->glyph_locations + gindex * 4; + p_limit = ttface->glyph_locations + ttface->num_locations * 4; pos1 = FT_NEXT_ULONG( p ); pos2 = pos1; @@ -219,8 +207,8 @@ } else { - p = face->glyph_locations + gindex * 2; - p_limit = face->glyph_locations + face->num_locations * 2; + p = ttface->glyph_locations + gindex * 2; + p_limit = ttface->glyph_locations + ttface->num_locations * 2; pos1 = FT_NEXT_USHORT( p ); pos2 = pos1; @@ -234,36 +222,39 @@ } /* Check broken location data. */ - if ( pos1 > face->glyf_len ) + if ( pos1 > ttface->glyf_len ) { FT_TRACE1(( "tt_face_get_location:" - " too large offset (0x%08lx) found for glyph index %d,\n" - " " + " too large offset (0x%08lx) found for glyph index %d,\n", + pos1, gindex )); + FT_TRACE1(( " " " exceeding the end of `glyf' table (0x%08lx)\n", - pos1, gindex, face->glyf_len )); + ttface->glyf_len )); *asize = 0; return 0; } - if ( pos2 > face->glyf_len ) + if ( pos2 > ttface->glyf_len ) { /* We try to sanitize the last `loca' entry. */ - if ( gindex == face->num_locations - 2 ) + if ( gindex == ttface->num_locations - 2 ) { FT_TRACE1(( "tt_face_get_location:" - " too large size (%ld bytes) found for glyph index %d,\n" - " " + " too large size (%ld bytes) found for glyph index %d,\n", + pos2 - pos1, gindex )); + FT_TRACE1(( " " " truncating at the end of `glyf' table to %ld bytes\n", - pos2 - pos1, gindex, face->glyf_len - pos1 )); - pos2 = face->glyf_len; + ttface->glyf_len - pos1 )); + pos2 = ttface->glyf_len; } else { FT_TRACE1(( "tt_face_get_location:" - " too large offset (0x%08lx) found for glyph index %d,\n" - " " + " too large offset (0x%08lx) found for glyph index %d,\n", + pos2, gindex + 1 )); + FT_TRACE1(( " " " exceeding the end of `glyf' table (0x%08lx)\n", - pos2, gindex + 1, face->glyf_len )); + ttface->glyf_len )); *asize = 0; return 0; } @@ -278,9 +269,9 @@ /* We get (intentionally) a wrong, non-zero result in case the */ /* `glyf' table is missing. */ if ( pos2 >= pos1 ) - *asize = (FT_UInt)( pos2 - pos1 ); + *asize = (FT_ULong)( pos2 - pos1 ); else - *asize = (FT_UInt)( face->glyf_len - pos1 ); + *asize = (FT_ULong)( ttface->glyf_len - pos1 ); return pos1; } @@ -344,7 +335,7 @@ face->cvt_size = table_len / 2; - if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) ) + if ( FT_QNEW_ARRAY( face->cvt, face->cvt_size ) ) goto Exit; if ( FT_FRAME_ENTER( face->cvt_size * 2L ) ) @@ -508,6 +499,14 @@ } + FT_COMPARE_DEF( int ) + compare_ppem( const void* a, + const void* b ) + { + return **(FT_Byte**)a - **(FT_Byte**)b; + } + + /************************************************************************** * * @Function: @@ -557,12 +556,6 @@ num_records = FT_NEXT_USHORT( p ); record_size = FT_NEXT_ULONG( p ); - /* The maximum number of bytes in an hdmx device record is the */ - /* maximum number of glyphs + 2; this is 0xFFFF + 2, thus */ - /* explaining why `record_size' is a long (which we read as */ - /* unsigned long for convenience). In practice, two bytes are */ - /* sufficient to hold the size value. */ - /* */ /* There are at least two fonts, HANNOM-A and HANNOM-B version */ /* 2.0 (2005), which get this wrong: The upper two bytes of */ /* the size value are set to 0xFF instead of 0x00. We catch */ @@ -571,32 +564,46 @@ if ( record_size >= 0xFFFF0000UL ) record_size &= 0xFFFFU; + FT_TRACE2(( "Hdmx " )); + /* The limit for `num_records' is a heuristic value. */ - if ( num_records > 255 || - ( num_records > 0 && - ( record_size > 0x10001L || - record_size < 4 ) ) ) + if ( num_records > 255 || num_records == 0 ) { - error = FT_THROW( Invalid_File_Format ); + FT_TRACE2(( "with unreasonable %u records rejected\n", num_records )); goto Fail; } - if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) ) + /* Out-of-spec tables are rejected. The record size must be */ + /* equal to the number of glyphs + 2 + 32-bit padding. */ + if ( (FT_Long)record_size != ( ( face->root.num_glyphs + 2 + 3 ) & ~3 ) ) + { + FT_TRACE2(( "with record size off by %ld bytes rejected\n", + (FT_Long)record_size - + ( ( face->root.num_glyphs + 2 + 3 ) & ~3 ) )); + goto Fail; + } + + if ( FT_QNEW_ARRAY( face->hdmx_records, num_records ) ) goto Fail; for ( nn = 0; nn < num_records; nn++ ) { if ( p + record_size > limit ) break; - - face->hdmx_record_sizes[nn] = p[0]; - p += record_size; + face->hdmx_records[nn] = p; + p += record_size; } + /* The records must be already sorted by ppem but it does not */ + /* hurt to make sure so that the binary search works later. */ + ft_qsort( face->hdmx_records, nn, sizeof ( FT_Byte* ), compare_ppem ); + face->hdmx_record_count = nn; face->hdmx_table_size = table_size; face->hdmx_record_size = record_size; + FT_TRACE2(( "%ux%lu loaded\n", num_records, record_size )); + Exit: return error; @@ -614,7 +621,7 @@ FT_Memory memory = stream->memory; - FT_FREE( face->hdmx_record_sizes ); + FT_FREE( face->hdmx_records ); FT_FRAME_RELEASE( face->hdmx_table ); } @@ -622,27 +629,34 @@ /************************************************************************** * * Return the advance width table for a given pixel size if it is found - * in the font's `hdmx' table (if any). + * in the font's `hdmx' table (if any). The records must be sorted for + * the binary search to work properly. */ FT_LOCAL_DEF( FT_Byte* ) tt_face_get_device_metrics( TT_Face face, FT_UInt ppem, FT_UInt gindex ) { - FT_UInt nn; - FT_Byte* result = NULL; - FT_ULong record_size = face->hdmx_record_size; - FT_Byte* record = FT_OFFSET( face->hdmx_table, 8 ); + FT_UInt min = 0; + FT_UInt max = face->hdmx_record_count; + FT_UInt mid; + FT_Byte* result = NULL; - for ( nn = 0; nn < face->hdmx_record_count; nn++ ) - if ( face->hdmx_record_sizes[nn] == ppem ) + while ( min < max ) + { + mid = ( min + max ) >> 1; + + if ( face->hdmx_records[mid][0] > ppem ) + max = mid; + else if ( face->hdmx_records[mid][0] < ppem ) + min = mid + 1; + else { - gindex += 2; - if ( gindex < record_size ) - result = record + nn * record_size + gindex; + result = face->hdmx_records[mid] + 2 + gindex; break; } + } return result; } diff --git a/lib/libesp32_lvgl/freetype/src/truetype/ttpload.h b/lib/libesp32_lvgl/freetype/src/truetype/ttpload.h index bb669e027..ed229fa46 100644 --- a/lib/libesp32_lvgl/freetype/src/truetype/ttpload.h +++ b/lib/libesp32_lvgl/freetype/src/truetype/ttpload.h @@ -4,7 +4,7 @@ * * TrueType-specific tables loader (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -31,9 +31,9 @@ FT_BEGIN_HEADER FT_Stream stream ); FT_LOCAL( FT_ULong ) - tt_face_get_location( TT_Face face, - FT_UInt gindex, - FT_UInt *asize ); + tt_face_get_location( FT_Face face, + FT_UInt gindex, + FT_ULong *asize ); FT_LOCAL( void ) tt_face_done_loca( TT_Face face ); diff --git a/lib/libesp32_lvgl/freetype/src/truetype/ttsubpix.c b/lib/libesp32_lvgl/freetype/src/truetype/ttsubpix.c deleted file mode 100644 index 56667deaf..000000000 --- a/lib/libesp32_lvgl/freetype/src/truetype/ttsubpix.c +++ /dev/null @@ -1,1013 +0,0 @@ -/**************************************************************************** - * - * ttsubpix.c - * - * TrueType Subpixel Hinting. - * - * Copyright (C) 2010-2020 by - * David Turner, Robert Wilhelm, and Werner Lemberg. - * - * This file is part of the FreeType project, and may only be used, - * modified, and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "ttsubpix.h" - - -#if defined( TT_USE_BYTECODE_INTERPRETER ) && \ - defined( TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY ) - - /************************************************************************** - * - * These rules affect how the TT Interpreter does hinting, with the - * goal of doing subpixel hinting by (in general) ignoring x moves. - * Some of these rules are fixes that go above and beyond the - * stated techniques in the MS whitepaper on Cleartype, due to - * artifacts in many glyphs. So, these rules make some glyphs render - * better than they do in the MS rasterizer. - * - * "" string or 0 int/char indicates to apply to all glyphs. - * "-" used as dummy placeholders, but any non-matching string works. - * - * Some of this could arguably be implemented in fontconfig, however: - * - * - Fontconfig can't set things on a glyph-by-glyph basis. - * - The tweaks that happen here are very low-level, from an average - * user's point of view and are best implemented in the hinter. - * - * The goal is to make the subpixel hinting techniques as generalized - * as possible across all fonts to prevent the need for extra rules such - * as these. - * - * The rule structure is designed so that entirely new rules can easily - * be added when a new compatibility feature is discovered. - * - * The rule structures could also use some enhancement to handle ranges. - * - * ****************** WORK IN PROGRESS ******************* - */ - - /* These are `classes' of fonts that can be grouped together and used in */ - /* rules below. A blank entry "" is required at the end of these! */ -#define FAMILY_CLASS_RULES_SIZE 7 - - static const SPH_Font_Class FAMILY_CLASS_Rules - [FAMILY_CLASS_RULES_SIZE] = - { - { "MS Legacy Fonts", - { "Aharoni", - "Andale Mono", - "Andalus", - "Angsana New", - "AngsanaUPC", - "Arabic Transparent", - "Arial Black", - "Arial Narrow", - "Arial Unicode MS", - "Arial", - "Batang", - "Browallia New", - "BrowalliaUPC", - "Comic Sans MS", - "Cordia New", - "CordiaUPC", - "Courier New", - "DFKai-SB", - "David Transparent", - "David", - "DilleniaUPC", - "Estrangelo Edessa", - "EucrosiaUPC", - "FangSong_GB2312", - "Fixed Miriam Transparent", - "FrankRuehl", - "Franklin Gothic Medium", - "FreesiaUPC", - "Garamond", - "Gautami", - "Georgia", - "Gulim", - "Impact", - "IrisUPC", - "JasmineUPC", - "KaiTi_GB2312", - "KodchiangUPC", - "Latha", - "Levenim MT", - "LilyUPC", - "Lucida Console", - "Lucida Sans Unicode", - "MS Gothic", - "MS Mincho", - "MV Boli", - "Mangal", - "Marlett", - "Microsoft Sans Serif", - "Mingliu", - "Miriam Fixed", - "Miriam Transparent", - "Miriam", - "Narkisim", - "Palatino Linotype", - "Raavi", - "Rod Transparent", - "Rod", - "Shruti", - "SimHei", - "Simplified Arabic Fixed", - "Simplified Arabic", - "Simsun", - "Sylfaen", - "Symbol", - "Tahoma", - "Times New Roman", - "Traditional Arabic", - "Trebuchet MS", - "Tunga", - "Verdana", - "Webdings", - "Wingdings", - "", - }, - }, - { "Core MS Legacy Fonts", - { "Arial Black", - "Arial Narrow", - "Arial Unicode MS", - "Arial", - "Comic Sans MS", - "Courier New", - "Garamond", - "Georgia", - "Impact", - "Lucida Console", - "Lucida Sans Unicode", - "Microsoft Sans Serif", - "Palatino Linotype", - "Tahoma", - "Times New Roman", - "Trebuchet MS", - "Verdana", - "", - }, - }, - { "Apple Legacy Fonts", - { "Geneva", - "Times", - "Monaco", - "Century", - "Chalkboard", - "Lobster", - "Century Gothic", - "Optima", - "Lucida Grande", - "Gill Sans", - "Baskerville", - "Helvetica", - "Helvetica Neue", - "", - }, - }, - { "Legacy Sans Fonts", - { "Andale Mono", - "Arial Unicode MS", - "Arial", - "Century Gothic", - "Comic Sans MS", - "Franklin Gothic Medium", - "Geneva", - "Lucida Console", - "Lucida Grande", - "Lucida Sans Unicode", - "Lucida Sans Typewriter", - "Microsoft Sans Serif", - "Monaco", - "Tahoma", - "Trebuchet MS", - "Verdana", - "", - }, - }, - - { "Misc Legacy Fonts", - { "Dark Courier", "", }, }, - { "Verdana Clones", - { "DejaVu Sans", - "Bitstream Vera Sans", "", }, }, - { "Verdana and Clones", - { "DejaVu Sans", - "Bitstream Vera Sans", - "Verdana", "", }, }, - }; - - - /* Define this to force natural (i.e. not bitmap-compatible) widths. */ - /* The default leans strongly towards natural widths except for a few */ - /* legacy fonts where a selective combination produces nicer results. */ -/* #define FORCE_NATURAL_WIDTHS */ - - - /* Define `classes' of styles that can be grouped together and used in */ - /* rules below. A blank entry "" is required at the end of these! */ -#define STYLE_CLASS_RULES_SIZE 5 - - static const SPH_Font_Class STYLE_CLASS_Rules - [STYLE_CLASS_RULES_SIZE] = - { - { "Regular Class", - { "Regular", - "Book", - "Medium", - "Roman", - "Normal", - "", - }, - }, - { "Regular/Italic Class", - { "Regular", - "Book", - "Medium", - "Italic", - "Oblique", - "Roman", - "Normal", - "", - }, - }, - { "Bold/BoldItalic Class", - { "Bold", - "Bold Italic", - "Black", - "", - }, - }, - { "Bold/Italic/BoldItalic Class", - { "Bold", - "Bold Italic", - "Black", - "Italic", - "Oblique", - "", - }, - }, - { "Regular/Bold Class", - { "Regular", - "Book", - "Medium", - "Normal", - "Roman", - "Bold", - "Black", - "", - }, - }, - }; - - - /* Force special legacy fixes for fonts. */ -#define COMPATIBILITY_MODE_RULES_SIZE 1 - - static const SPH_TweakRule COMPATIBILITY_MODE_Rules - [COMPATIBILITY_MODE_RULES_SIZE] = - { - { "Verdana Clones", 0, "", 0 }, - }; - - - /* Don't do subpixel (ignore_x_mode) hinting; do normal hinting. */ -#define PIXEL_HINTING_RULES_SIZE 2 - - static const SPH_TweakRule PIXEL_HINTING_Rules - [PIXEL_HINTING_RULES_SIZE] = - { - /* these characters are almost always safe */ - { "Courier New", 12, "Italic", 'z' }, - { "Courier New", 11, "Italic", 'z' }, - }; - - - /* Subpixel hinting ignores SHPIX rules on X. Force SHPIX for these. */ -#define DO_SHPIX_RULES_SIZE 1 - - static const SPH_TweakRule DO_SHPIX_Rules - [DO_SHPIX_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Skip Y moves that start with a point that is not on a Y pixel */ - /* boundary and don't move that point to a Y pixel boundary. */ -#define SKIP_NONPIXEL_Y_MOVES_RULES_SIZE 4 - - static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules - [SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] = - { - /* fix vwxyz thinness*/ - { "Consolas", 0, "", 0 }, - /* Fix thin middle stems */ - { "Core MS Legacy Fonts", 0, "Regular", 0 }, - /* Cyrillic small letter I */ - { "Legacy Sans Fonts", 0, "", 0 }, - /* Fix artifacts with some Regular & Bold */ - { "Verdana Clones", 0, "", 0 }, - }; - - -#define SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 - - static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions - [SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = - { - /* Fixes < and > */ - { "Courier New", 0, "Regular", 0 }, - }; - - - /* Skip Y moves that start with a point that is not on a Y pixel */ - /* boundary and don't move that point to a Y pixel boundary. */ -#define SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE 2 - - static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_DELTAP_Rules - [SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE] = - { - /* Maintain thickness of diagonal in 'N' */ - { "Times New Roman", 0, "Regular/Bold Class", 'N' }, - { "Georgia", 0, "Regular/Bold Class", 'N' }, - }; - - - /* Skip Y moves that move a point off a Y pixel boundary. */ -#define SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE 1 - - static const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules - [SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - -#define SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 - - static const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules_Exceptions - [SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Round moves that don't move a point to a Y pixel boundary. */ -#define ROUND_NONPIXEL_Y_MOVES_RULES_SIZE 2 - - static const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules - [ROUND_NONPIXEL_Y_MOVES_RULES_SIZE] = - { - /* Droid font instructions don't snap Y to pixels */ - { "Droid Sans", 0, "Regular/Italic Class", 0 }, - { "Droid Sans Mono", 0, "", 0 }, - }; - - -#define ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 - - static const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions - [ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Allow a Direct_Move along X freedom vector if matched. */ -#define ALLOW_X_DMOVE_RULES_SIZE 1 - - static const SPH_TweakRule ALLOW_X_DMOVE_Rules - [ALLOW_X_DMOVE_RULES_SIZE] = - { - /* Fixes vanishing diagonal in 4 */ - { "Verdana", 0, "Regular", '4' }, - }; - - - /* Return MS rasterizer version 35 if matched. */ -#define RASTERIZER_35_RULES_SIZE 8 - - static const SPH_TweakRule RASTERIZER_35_Rules - [RASTERIZER_35_RULES_SIZE] = - { - /* This seems to be the only way to make these look good */ - { "Times New Roman", 0, "Regular", 'i' }, - { "Times New Roman", 0, "Regular", 'j' }, - { "Times New Roman", 0, "Regular", 'm' }, - { "Times New Roman", 0, "Regular", 'r' }, - { "Times New Roman", 0, "Regular", 'a' }, - { "Times New Roman", 0, "Regular", 'n' }, - { "Times New Roman", 0, "Regular", 'p' }, - { "Times", 0, "", 0 }, - }; - - - /* Don't round to the subpixel grid. Round to pixel grid. */ -#define NORMAL_ROUND_RULES_SIZE 1 - - static const SPH_TweakRule NORMAL_ROUND_Rules - [NORMAL_ROUND_RULES_SIZE] = - { - /* Fix serif thickness for certain ppems */ - /* Can probably be generalized somehow */ - { "Courier New", 0, "", 0 }, - }; - - - /* Skip IUP instructions if matched. */ -#define SKIP_IUP_RULES_SIZE 1 - - static const SPH_TweakRule SKIP_IUP_Rules - [SKIP_IUP_RULES_SIZE] = - { - { "Arial", 13, "Regular", 'a' }, - }; - - - /* Skip MIAP Twilight hack if matched. */ -#define MIAP_HACK_RULES_SIZE 1 - - static const SPH_TweakRule MIAP_HACK_Rules - [MIAP_HACK_RULES_SIZE] = - { - { "Geneva", 12, "", 0 }, - }; - - - /* Skip DELTAP instructions if matched. */ -#define ALWAYS_SKIP_DELTAP_RULES_SIZE 23 - - static const SPH_TweakRule ALWAYS_SKIP_DELTAP_Rules - [ALWAYS_SKIP_DELTAP_RULES_SIZE] = - { - { "Georgia", 0, "Regular", 'k' }, - /* fix various problems with e in different versions */ - { "Trebuchet MS", 14, "Regular", 'e' }, - { "Trebuchet MS", 13, "Regular", 'e' }, - { "Trebuchet MS", 15, "Regular", 'e' }, - { "Trebuchet MS", 0, "Italic", 'v' }, - { "Trebuchet MS", 0, "Italic", 'w' }, - { "Trebuchet MS", 0, "Regular", 'Y' }, - { "Arial", 11, "Regular", 's' }, - /* prevent problems with '3' and others */ - { "Verdana", 10, "Regular", 0 }, - { "Verdana", 9, "Regular", 0 }, - /* Cyrillic small letter short I */ - { "Legacy Sans Fonts", 0, "", 0x438 }, - { "Legacy Sans Fonts", 0, "", 0x439 }, - { "Arial", 10, "Regular", '6' }, - { "Arial", 0, "Bold/BoldItalic Class", 'a' }, - /* Make horizontal stems consistent with the rest */ - { "Arial", 24, "Bold", 'a' }, - { "Arial", 25, "Bold", 'a' }, - { "Arial", 24, "Bold", 's' }, - { "Arial", 25, "Bold", 's' }, - { "Arial", 34, "Bold", 's' }, - { "Arial", 35, "Bold", 's' }, - { "Arial", 36, "Bold", 's' }, - { "Arial", 25, "Regular", 's' }, - { "Arial", 26, "Regular", 's' }, - }; - - - /* Always do DELTAP instructions if matched. */ -#define ALWAYS_DO_DELTAP_RULES_SIZE 1 - - static const SPH_TweakRule ALWAYS_DO_DELTAP_Rules - [ALWAYS_DO_DELTAP_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Don't allow ALIGNRP after IUP. */ -#define NO_ALIGNRP_AFTER_IUP_RULES_SIZE 1 - - static const SPH_TweakRule NO_ALIGNRP_AFTER_IUP_Rules - [NO_ALIGNRP_AFTER_IUP_RULES_SIZE] = - { - /* Prevent creation of dents in outline */ - { "-", 0, "", 0 }, - }; - - - /* Don't allow DELTAP after IUP. */ -#define NO_DELTAP_AFTER_IUP_RULES_SIZE 1 - - static const SPH_TweakRule NO_DELTAP_AFTER_IUP_Rules - [NO_DELTAP_AFTER_IUP_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Don't allow CALL after IUP. */ -#define NO_CALL_AFTER_IUP_RULES_SIZE 1 - - static const SPH_TweakRule NO_CALL_AFTER_IUP_Rules - [NO_CALL_AFTER_IUP_RULES_SIZE] = - { - /* Prevent creation of dents in outline */ - { "-", 0, "", 0 }, - }; - - - /* De-embolden these glyphs slightly. */ -#define DEEMBOLDEN_RULES_SIZE 9 - - static const SPH_TweakRule DEEMBOLDEN_Rules - [DEEMBOLDEN_RULES_SIZE] = - { - { "Courier New", 0, "Bold", 'A' }, - { "Courier New", 0, "Bold", 'W' }, - { "Courier New", 0, "Bold", 'w' }, - { "Courier New", 0, "Bold", 'M' }, - { "Courier New", 0, "Bold", 'X' }, - { "Courier New", 0, "Bold", 'K' }, - { "Courier New", 0, "Bold", 'x' }, - { "Courier New", 0, "Bold", 'z' }, - { "Courier New", 0, "Bold", 'v' }, - }; - - - /* Embolden these glyphs slightly. */ -#define EMBOLDEN_RULES_SIZE 2 - - static const SPH_TweakRule EMBOLDEN_Rules - [EMBOLDEN_RULES_SIZE] = - { - { "Courier New", 0, "Regular", 0 }, - { "Courier New", 0, "Italic", 0 }, - }; - - - /* This is a CVT hack that makes thick horizontal stems on 2, 5, 7 */ - /* similar to Windows XP. */ -#define TIMES_NEW_ROMAN_HACK_RULES_SIZE 12 - - static const SPH_TweakRule TIMES_NEW_ROMAN_HACK_Rules - [TIMES_NEW_ROMAN_HACK_RULES_SIZE] = - { - { "Times New Roman", 16, "Italic", '2' }, - { "Times New Roman", 16, "Italic", '5' }, - { "Times New Roman", 16, "Italic", '7' }, - { "Times New Roman", 16, "Regular", '2' }, - { "Times New Roman", 16, "Regular", '5' }, - { "Times New Roman", 16, "Regular", '7' }, - { "Times New Roman", 17, "Italic", '2' }, - { "Times New Roman", 17, "Italic", '5' }, - { "Times New Roman", 17, "Italic", '7' }, - { "Times New Roman", 17, "Regular", '2' }, - { "Times New Roman", 17, "Regular", '5' }, - { "Times New Roman", 17, "Regular", '7' }, - }; - - - /* This fudges distance on 2 to get rid of the vanishing stem issue. */ - /* A real solution to this is certainly welcome. */ -#define COURIER_NEW_2_HACK_RULES_SIZE 15 - - static const SPH_TweakRule COURIER_NEW_2_HACK_Rules - [COURIER_NEW_2_HACK_RULES_SIZE] = - { - { "Courier New", 10, "Regular", '2' }, - { "Courier New", 11, "Regular", '2' }, - { "Courier New", 12, "Regular", '2' }, - { "Courier New", 13, "Regular", '2' }, - { "Courier New", 14, "Regular", '2' }, - { "Courier New", 15, "Regular", '2' }, - { "Courier New", 16, "Regular", '2' }, - { "Courier New", 17, "Regular", '2' }, - { "Courier New", 18, "Regular", '2' }, - { "Courier New", 19, "Regular", '2' }, - { "Courier New", 20, "Regular", '2' }, - { "Courier New", 21, "Regular", '2' }, - { "Courier New", 22, "Regular", '2' }, - { "Courier New", 23, "Regular", '2' }, - { "Courier New", 24, "Regular", '2' }, - }; - - -#ifndef FORCE_NATURAL_WIDTHS - - /* Use compatible widths with these glyphs. Compatible widths is always */ - /* on when doing B/W TrueType instructing, but is used selectively here, */ - /* typically on glyphs with 3 or more vertical stems. */ -#define COMPATIBLE_WIDTHS_RULES_SIZE 38 - - static const SPH_TweakRule COMPATIBLE_WIDTHS_Rules - [COMPATIBLE_WIDTHS_RULES_SIZE] = - { - { "Arial Unicode MS", 12, "Regular Class", 'm' }, - { "Arial Unicode MS", 14, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Arial", 10, "Regular Class", 0x448 }, - { "Arial", 11, "Regular Class", 'm' }, - { "Arial", 12, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Arial", 12, "Regular Class", 0x448 }, - { "Arial", 13, "Regular Class", 0x448 }, - { "Arial", 14, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Arial", 14, "Regular Class", 0x448 }, - { "Arial", 15, "Regular Class", 0x448 }, - { "Arial", 17, "Regular Class", 'm' }, - { "DejaVu Sans", 15, "Regular Class", 0 }, - { "Microsoft Sans Serif", 11, "Regular Class", 0 }, - { "Microsoft Sans Serif", 12, "Regular Class", 0 }, - { "Segoe UI", 11, "Regular Class", 0 }, - { "Monaco", 0, "Regular Class", 0 }, - { "Segoe UI", 12, "Regular Class", 'm' }, - { "Segoe UI", 14, "Regular Class", 'm' }, - { "Tahoma", 11, "Regular Class", 0 }, - { "Times New Roman", 16, "Regular Class", 'c' }, - { "Times New Roman", 16, "Regular Class", 'm' }, - { "Times New Roman", 16, "Regular Class", 'o' }, - { "Times New Roman", 16, "Regular Class", 'w' }, - { "Trebuchet MS", 11, "Regular Class", 0 }, - { "Trebuchet MS", 12, "Regular Class", 0 }, - { "Trebuchet MS", 14, "Regular Class", 0 }, - { "Trebuchet MS", 15, "Regular Class", 0 }, - { "Ubuntu", 12, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Verdana", 10, "Regular Class", 0x448 }, - { "Verdana", 11, "Regular Class", 0x448 }, - { "Verdana and Clones", 12, "Regular Class", 'i' }, - { "Verdana and Clones", 12, "Regular Class", 'j' }, - { "Verdana and Clones", 12, "Regular Class", 'l' }, - { "Verdana and Clones", 12, "Regular Class", 'm' }, - { "Verdana and Clones", 13, "Regular Class", 'i' }, - { "Verdana and Clones", 13, "Regular Class", 'j' }, - { "Verdana and Clones", 13, "Regular Class", 'l' }, - { "Verdana and Clones", 14, "Regular Class", 'm' }, - }; - - - /* Scaling slightly in the x-direction prior to hinting results in */ - /* more visually pleasing glyphs in certain cases. */ - /* This sometimes needs to be coordinated with compatible width rules. */ - /* A value of 1000 corresponds to a scaled value of 1.0. */ - -#define X_SCALING_RULES_SIZE 50 - - static const SPH_ScaleRule X_SCALING_Rules[X_SCALING_RULES_SIZE] = - { - { "DejaVu Sans", 12, "Regular Class", 'm', 950 }, - { "Verdana and Clones", 12, "Regular Class", 'a', 1100 }, - { "Verdana and Clones", 13, "Regular Class", 'a', 1050 }, - { "Arial", 11, "Regular Class", 'm', 975 }, - { "Arial", 12, "Regular Class", 'm', 1050 }, - /* Cyrillic small letter el */ - { "Arial", 13, "Regular Class", 0x43B, 950 }, - { "Arial", 13, "Regular Class", 'o', 950 }, - { "Arial", 13, "Regular Class", 'e', 950 }, - { "Arial", 14, "Regular Class", 'm', 950 }, - /* Cyrillic small letter el */ - { "Arial", 15, "Regular Class", 0x43B, 925 }, - { "Bitstream Vera Sans", 10, "Regular/Italic Class", 0, 1100 }, - { "Bitstream Vera Sans", 12, "Regular/Italic Class", 0, 1050 }, - { "Bitstream Vera Sans", 16, "Regular Class", 0, 1050 }, - { "Bitstream Vera Sans", 9, "Regular/Italic Class", 0, 1050 }, - { "DejaVu Sans", 12, "Regular Class", 'l', 975 }, - { "DejaVu Sans", 12, "Regular Class", 'i', 975 }, - { "DejaVu Sans", 12, "Regular Class", 'j', 975 }, - { "DejaVu Sans", 13, "Regular Class", 'l', 950 }, - { "DejaVu Sans", 13, "Regular Class", 'i', 950 }, - { "DejaVu Sans", 13, "Regular Class", 'j', 950 }, - { "DejaVu Sans", 10, "Regular/Italic Class", 0, 1100 }, - { "DejaVu Sans", 12, "Regular/Italic Class", 0, 1050 }, - { "Georgia", 10, "", 0, 1050 }, - { "Georgia", 11, "", 0, 1100 }, - { "Georgia", 12, "", 0, 1025 }, - { "Georgia", 13, "", 0, 1050 }, - { "Georgia", 16, "", 0, 1050 }, - { "Georgia", 17, "", 0, 1030 }, - { "Liberation Sans", 12, "Regular Class", 'm', 1100 }, - { "Lucida Grande", 11, "Regular Class", 'm', 1100 }, - { "Microsoft Sans Serif", 11, "Regular Class", 'm', 950 }, - { "Microsoft Sans Serif", 12, "Regular Class", 'm', 1050 }, - { "Segoe UI", 12, "Regular Class", 'H', 1050 }, - { "Segoe UI", 12, "Regular Class", 'm', 1050 }, - { "Segoe UI", 14, "Regular Class", 'm', 1050 }, - { "Tahoma", 11, "Regular Class", 'i', 975 }, - { "Tahoma", 11, "Regular Class", 'l', 975 }, - { "Tahoma", 11, "Regular Class", 'j', 900 }, - { "Tahoma", 11, "Regular Class", 'm', 918 }, - { "Verdana", 10, "Regular/Italic Class", 0, 1100 }, - { "Verdana", 12, "Regular Class", 'm', 975 }, - { "Verdana", 12, "Regular/Italic Class", 0, 1050 }, - { "Verdana", 13, "Regular/Italic Class", 'i', 950 }, - { "Verdana", 13, "Regular/Italic Class", 'j', 950 }, - { "Verdana", 13, "Regular/Italic Class", 'l', 950 }, - { "Verdana", 16, "Regular Class", 0, 1050 }, - { "Verdana", 9, "Regular/Italic Class", 0, 1050 }, - { "Times New Roman", 16, "Regular Class", 'm', 918 }, - { "Trebuchet MS", 11, "Regular Class", 'm', 800 }, - { "Trebuchet MS", 12, "Regular Class", 'm', 800 }, - }; - -#else - -#define COMPATIBLE_WIDTHS_RULES_SIZE 1 - - static const SPH_TweakRule COMPATIBLE_WIDTHS_Rules - [COMPATIBLE_WIDTHS_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - -#define X_SCALING_RULES_SIZE 1 - - static const SPH_ScaleRule X_SCALING_Rules - [X_SCALING_RULES_SIZE] = - { - { "-", 0, "", 0, 1000 }, - }; - -#endif /* FORCE_NATURAL_WIDTHS */ - - - static FT_Bool - is_member_of_family_class( const FT_String* detected_font_name, - const FT_String* rule_font_name ) - { - FT_UInt i, j; - - - /* Does font name match rule family? */ - if ( ft_strcmp( detected_font_name, rule_font_name ) == 0 ) - return TRUE; - - /* Is font name a wildcard ""? */ - if ( ft_strcmp( rule_font_name, "" ) == 0 ) - return TRUE; - - /* Is font name contained in a class list? */ - for ( i = 0; i < FAMILY_CLASS_RULES_SIZE; i++ ) - { - if ( ft_strcmp( FAMILY_CLASS_Rules[i].name, rule_font_name ) == 0 ) - { - for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ ) - { - if ( ft_strcmp( FAMILY_CLASS_Rules[i].member[j], "" ) == 0 ) - continue; - if ( ft_strcmp( FAMILY_CLASS_Rules[i].member[j], - detected_font_name ) == 0 ) - return TRUE; - } - } - } - - return FALSE; - } - - - static FT_Bool - is_member_of_style_class( const FT_String* detected_font_style, - const FT_String* rule_font_style ) - { - FT_UInt i, j; - - - /* Does font style match rule style? */ - if ( ft_strcmp( detected_font_style, rule_font_style ) == 0 ) - return TRUE; - - /* Is font style a wildcard ""? */ - if ( ft_strcmp( rule_font_style, "" ) == 0 ) - return TRUE; - - /* Is font style contained in a class list? */ - for ( i = 0; i < STYLE_CLASS_RULES_SIZE; i++ ) - { - if ( ft_strcmp( STYLE_CLASS_Rules[i].name, rule_font_style ) == 0 ) - { - for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ ) - { - if ( ft_strcmp( STYLE_CLASS_Rules[i].member[j], "" ) == 0 ) - continue; - if ( ft_strcmp( STYLE_CLASS_Rules[i].member[j], - detected_font_style ) == 0 ) - return TRUE; - } - } - } - - return FALSE; - } - - - FT_LOCAL_DEF( FT_Bool ) - sph_test_tweak( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index, - const SPH_TweakRule* rule, - FT_UInt num_rules ) - { - FT_UInt i; - - - /* rule checks may be able to be optimized further */ - for ( i = 0; i < num_rules; i++ ) - { - if ( family && - ( is_member_of_family_class ( family, rule[i].family ) ) ) - if ( rule[i].ppem == 0 || - rule[i].ppem == ppem ) - if ( style && - is_member_of_style_class ( style, rule[i].style ) ) - if ( rule[i].glyph == 0 || - FT_Get_Char_Index( (FT_Face)face, - rule[i].glyph ) == glyph_index ) - return TRUE; - } - - return FALSE; - } - - - static FT_UInt - scale_test_tweak( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index, - const SPH_ScaleRule* rule, - FT_UInt num_rules ) - { - FT_UInt i; - - - /* rule checks may be able to be optimized further */ - for ( i = 0; i < num_rules; i++ ) - { - if ( family && - ( is_member_of_family_class ( family, rule[i].family ) ) ) - if ( rule[i].ppem == 0 || - rule[i].ppem == ppem ) - if ( style && - is_member_of_style_class( style, rule[i].style ) ) - if ( rule[i].glyph == 0 || - FT_Get_Char_Index( (FT_Face)face, - rule[i].glyph ) == glyph_index ) - return rule[i].scale; - } - - return 1000; - } - - - FT_LOCAL_DEF( FT_UInt ) - sph_test_tweak_x_scaling( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index ) - { - return scale_test_tweak( face, family, ppem, style, glyph_index, - X_SCALING_Rules, X_SCALING_RULES_SIZE ); - } - - -#define TWEAK_RULES( x ) \ - if ( sph_test_tweak( face, family, ppem, style, glyph_index, \ - x##_Rules, x##_RULES_SIZE ) ) \ - loader->exec->sph_tweak_flags |= SPH_TWEAK_##x; - -#define TWEAK_RULES_EXCEPTIONS( x ) \ - if ( sph_test_tweak( face, family, ppem, style, glyph_index, \ - x##_Rules_Exceptions, x##_RULES_EXCEPTIONS_SIZE ) ) \ - loader->exec->sph_tweak_flags &= ~SPH_TWEAK_##x; - - - FT_LOCAL_DEF( void ) - sph_set_tweaks( TT_Loader loader, - FT_UInt glyph_index ) - { - TT_Face face = loader->face; - FT_String* family = face->root.family_name; - FT_UInt ppem = loader->size->metrics->x_ppem; - FT_String* style = face->root.style_name; - - - /* don't apply rules if style isn't set */ - if ( !face->root.style_name ) - return; - -#ifdef SPH_DEBUG_MORE_VERBOSE - printf( "%s,%d,%s,%c=%d ", - family, ppem, style, glyph_index, glyph_index ); -#endif - - TWEAK_RULES( PIXEL_HINTING ); - - if ( loader->exec->sph_tweak_flags & SPH_TWEAK_PIXEL_HINTING ) - { - loader->exec->ignore_x_mode = FALSE; - return; - } - - TWEAK_RULES( ALLOW_X_DMOVE ); - TWEAK_RULES( ALWAYS_DO_DELTAP ); - TWEAK_RULES( ALWAYS_SKIP_DELTAP ); - TWEAK_RULES( DEEMBOLDEN ); - TWEAK_RULES( DO_SHPIX ); - TWEAK_RULES( EMBOLDEN ); - TWEAK_RULES( MIAP_HACK ); - TWEAK_RULES( NORMAL_ROUND ); - TWEAK_RULES( NO_ALIGNRP_AFTER_IUP ); - TWEAK_RULES( NO_CALL_AFTER_IUP ); - TWEAK_RULES( NO_DELTAP_AFTER_IUP ); - TWEAK_RULES( RASTERIZER_35 ); - TWEAK_RULES( SKIP_IUP ); - - TWEAK_RULES( SKIP_OFFPIXEL_Y_MOVES ); - TWEAK_RULES_EXCEPTIONS( SKIP_OFFPIXEL_Y_MOVES ); - - TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES_DELTAP ); - - TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES ); - TWEAK_RULES_EXCEPTIONS( SKIP_NONPIXEL_Y_MOVES ); - - TWEAK_RULES( ROUND_NONPIXEL_Y_MOVES ); - TWEAK_RULES_EXCEPTIONS( ROUND_NONPIXEL_Y_MOVES ); - - if ( loader->exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) - { - if ( loader->exec->rasterizer_version != TT_INTERPRETER_VERSION_35 ) - { - loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35; - loader->exec->size->cvt_ready = -1; - - tt_size_ready_bytecode( - loader->exec->size, - FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) ); - } - else - loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35; - } - else - { - if ( loader->exec->rasterizer_version != - SPH_OPTION_SET_RASTERIZER_VERSION ) - { - loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; - loader->exec->size->cvt_ready = -1; - - tt_size_ready_bytecode( - loader->exec->size, - FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) ); - } - else - loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; - } - - if ( IS_HINTED( loader->load_flags ) ) - { - TWEAK_RULES( TIMES_NEW_ROMAN_HACK ); - TWEAK_RULES( COURIER_NEW_2_HACK ); - } - - if ( sph_test_tweak( face, family, ppem, style, glyph_index, - COMPATIBILITY_MODE_Rules, COMPATIBILITY_MODE_RULES_SIZE ) ) - loader->exec->face->sph_compatibility_mode = TRUE; - - - if ( IS_HINTED( loader->load_flags ) ) - { - if ( sph_test_tweak( face, family, ppem, style, glyph_index, - COMPATIBLE_WIDTHS_Rules, COMPATIBLE_WIDTHS_RULES_SIZE ) ) - loader->exec->compatible_widths |= TRUE; - } - } - -#else /* !(TT_USE_BYTECODE_INTERPRETER && */ - /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY) */ - - /* ANSI C doesn't like empty source files */ - typedef int _tt_subpix_dummy; - -#endif /* !(TT_USE_BYTECODE_INTERPRETER && */ - /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY) */ - - -/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/truetype/ttsubpix.h b/lib/libesp32_lvgl/freetype/src/truetype/ttsubpix.h deleted file mode 100644 index 229a6cf05..000000000 --- a/lib/libesp32_lvgl/freetype/src/truetype/ttsubpix.h +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** - * - * ttsubpix.h - * - * TrueType Subpixel Hinting. - * - * Copyright (C) 2010-2020 by - * David Turner, Robert Wilhelm, and Werner Lemberg. - * - * This file is part of the FreeType project, and may only be used, - * modified, and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - */ - - -#ifndef TTSUBPIX_H_ -#define TTSUBPIX_H_ - -#include "ttobjs.h" -#include "ttinterp.h" - - -FT_BEGIN_HEADER - - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - /************************************************************************** - * - * ID flags to identify special functions at FDEF and runtime. - * - */ -#define SPH_FDEF_INLINE_DELTA_1 0x0000001 -#define SPH_FDEF_INLINE_DELTA_2 0x0000002 -#define SPH_FDEF_DIAGONAL_STROKE 0x0000004 -#define SPH_FDEF_VACUFORM_ROUND_1 0x0000008 -#define SPH_FDEF_TTFAUTOHINT_1 0x0000010 -#define SPH_FDEF_SPACING_1 0x0000020 -#define SPH_FDEF_SPACING_2 0x0000040 -#define SPH_FDEF_TYPEMAN_STROKES 0x0000080 -#define SPH_FDEF_TYPEMAN_DIAGENDCTRL 0x0000100 - - - /************************************************************************** - * - * Tweak flags that are set for each glyph by the below rules. - * - */ -#define SPH_TWEAK_ALLOW_X_DMOVE 0x0000001UL -#define SPH_TWEAK_ALWAYS_DO_DELTAP 0x0000002UL -#define SPH_TWEAK_ALWAYS_SKIP_DELTAP 0x0000004UL -#define SPH_TWEAK_COURIER_NEW_2_HACK 0x0000008UL -#define SPH_TWEAK_DEEMBOLDEN 0x0000010UL -#define SPH_TWEAK_DO_SHPIX 0x0000020UL -#define SPH_TWEAK_EMBOLDEN 0x0000040UL -#define SPH_TWEAK_MIAP_HACK 0x0000080UL -#define SPH_TWEAK_NORMAL_ROUND 0x0000100UL -#define SPH_TWEAK_NO_ALIGNRP_AFTER_IUP 0x0000200UL -#define SPH_TWEAK_NO_CALL_AFTER_IUP 0x0000400UL -#define SPH_TWEAK_NO_DELTAP_AFTER_IUP 0x0000800UL -#define SPH_TWEAK_PIXEL_HINTING 0x0001000UL -#define SPH_TWEAK_RASTERIZER_35 0x0002000UL -#define SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES 0x0004000UL -#define SPH_TWEAK_SKIP_IUP 0x0008000UL -#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES 0x0010000UL -#define SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES 0x0020000UL -#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK 0x0040000UL -#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP 0x0080000UL - - - FT_LOCAL( FT_Bool ) - sph_test_tweak( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index, - const SPH_TweakRule* rule, - FT_UInt num_rules ); - - FT_LOCAL( FT_UInt ) - sph_test_tweak_x_scaling( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index ); - - FT_LOCAL( void ) - sph_set_tweaks( TT_Loader loader, - FT_UInt glyph_index ); - - - /* These macros are defined absent a method for setting them */ -#define SPH_OPTION_BITMAP_WIDTHS FALSE -#define SPH_OPTION_SET_SUBPIXEL TRUE -#define SPH_OPTION_SET_GRAYSCALE FALSE -#define SPH_OPTION_SET_COMPATIBLE_WIDTHS FALSE -#define SPH_OPTION_SET_RASTERIZER_VERSION 38 - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - - -FT_END_HEADER - -#endif /* TTSUBPIX_H_ */ - - -/* END */ diff --git a/lib/libesp32_lvgl/freetype/src/type1/module.mk b/lib/libesp32_lvgl/freetype/src/type1/module.mk index cffb774b4..33bceff8a 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/module.mk +++ b/lib/libesp32_lvgl/freetype/src/type1/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/type1/rules.mk b/lib/libesp32_lvgl/freetype/src/type1/rules.mk index 213e61924..efe744b77 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/type1/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/type1/t1afm.c b/lib/libesp32_lvgl/freetype/src/type1/t1afm.c index b9cd66b04..d9b9398b0 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/t1afm.c +++ b/lib/libesp32_lvgl/freetype/src/type1/t1afm.c @@ -4,7 +4,7 @@ * * AFM support for Type 1 fonts (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -83,7 +83,7 @@ /* compare two kerning pairs */ - FT_CALLBACK_DEF( int ) + FT_COMPARE_DEF( int ) compare_kern_pairs( const void* a, const void* b ) { @@ -178,7 +178,6 @@ /* temporarily. If we find no PostScript charmap, then just use */ /* the default and hope it is the right one. */ oldcharmap = t1_face->charmap; - charmap = NULL; for ( n = 0; n < t1_face->num_charmaps; n++ ) { @@ -186,9 +185,7 @@ /* check against PostScript pseudo platform */ if ( charmap->platform_id == 7 ) { - error = FT_Set_Charmap( t1_face, charmap ); - if ( error ) - goto Exit; + t1_face->charmap = charmap; break; } } @@ -203,16 +200,13 @@ kp->index1 = FT_Get_Char_Index( t1_face, p[0] ); kp->index2 = FT_Get_Char_Index( t1_face, p[1] ); - kp->x = (FT_Int)FT_PEEK_SHORT_LE(p + 2); + kp->x = (FT_Int)FT_PEEK_SHORT_LE( p + 2 ); kp->y = 0; kp++; } - if ( oldcharmap ) - error = FT_Set_Charmap( t1_face, oldcharmap ); - if ( error ) - goto Exit; + t1_face->charmap = oldcharmap; /* now, sort the kern pairs according to their glyph indices */ ft_qsort( fi->KernPairs, fi->NumKernPair, sizeof ( AFM_KernPairRec ), @@ -302,9 +296,14 @@ t1_face->bbox.xMax = ( fi->FontBBox.xMax + 0xFFFF ) >> 16; t1_face->bbox.yMax = ( fi->FontBBox.yMax + 0xFFFF ) >> 16; - /* no `U' suffix here to 0x8000! */ - t1_face->ascender = (FT_Short)( ( fi->Ascender + 0x8000 ) >> 16 ); - t1_face->descender = (FT_Short)( ( fi->Descender + 0x8000 ) >> 16 ); + /* ascender and descender are optional and could both be zero */ + /* check if values are meaningful before overriding defaults */ + if ( fi->Ascender > fi->Descender ) + { + /* no `U' suffix here to 0x8000! */ + t1_face->ascender = (FT_Short)( ( fi->Ascender + 0x8000 ) >> 16 ); + t1_face->descender = (FT_Short)( ( fi->Descender + 0x8000 ) >> 16 ); + } if ( fi->NumKernPair ) { @@ -406,7 +405,7 @@ #else /* T1_CONFIG_OPTION_NO_AFM */ /* ANSI C doesn't like empty source files */ - typedef int _t1_afm_dummy; + typedef int t1_afm_dummy_; #endif /* T1_CONFIG_OPTION_NO_AFM */ diff --git a/lib/libesp32_lvgl/freetype/src/type1/t1afm.h b/lib/libesp32_lvgl/freetype/src/type1/t1afm.h index edf919c79..e0d5aa5a8 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/t1afm.h +++ b/lib/libesp32_lvgl/freetype/src/type1/t1afm.h @@ -4,7 +4,7 @@ * * AFM support for Type 1 fonts (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/type1/t1driver.c b/lib/libesp32_lvgl/freetype/src/type1/t1driver.c index b786a8781..a4cdf372a 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/t1driver.c +++ b/lib/libesp32_lvgl/freetype/src/type1/t1driver.c @@ -4,7 +4,7 @@ * * Type 1 driver interface (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -56,28 +56,32 @@ * */ - static FT_Error - t1_get_glyph_name( T1_Face face, + FT_CALLBACK_DEF( FT_Error ) + t1_get_glyph_name( FT_Face face, /* T1_Face */ FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max ) { - FT_STRCPYN( buffer, face->type1.glyph_names[glyph_index], buffer_max ); + T1_Face t1face = (T1_Face)face; + + + FT_STRCPYN( buffer, t1face->type1.glyph_names[glyph_index], buffer_max ); return FT_Err_Ok; } - static FT_UInt - t1_get_name_index( T1_Face face, + FT_CALLBACK_DEF( FT_UInt ) + t1_get_name_index( FT_Face face, /* T1_Face */ const FT_String* glyph_name ) { - FT_Int i; + T1_Face t1face = (T1_Face)face; + FT_Int i; - for ( i = 0; i < face->type1.num_glyphs; i++ ) + for ( i = 0; i < t1face->type1.num_glyphs; i++ ) { - FT_String* gname = face->type1.glyph_names[i]; + FT_String* gname = t1face->type1.glyph_names[i]; if ( !ft_strcmp( glyph_name, gname ) ) @@ -90,8 +94,8 @@ static const FT_Service_GlyphDictRec t1_service_glyph_dict = { - (FT_GlyphDict_GetNameFunc) t1_get_glyph_name, /* get_name */ - (FT_GlyphDict_NameIndexFunc)t1_get_name_index /* name_index */ + t1_get_glyph_name, /* FT_GlyphDict_GetNameFunc get_name */ + t1_get_name_index /* FT_GlyphDict_NameIndexFunc name_index */ }; @@ -101,9 +105,12 @@ */ static const char* - t1_get_ps_name( T1_Face face ) + t1_get_ps_name( FT_Face face ) /* T1_Face */ { - return (const char*) face->type1.font_name; + T1_Face t1face = (T1_Face)face; + + + return (const char*) t1face->type1.font_name; } @@ -121,19 +128,28 @@ #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT static const FT_Service_MultiMastersRec t1_service_multi_masters = { - (FT_Get_MM_Func) T1_Get_Multi_Master, /* get_mm */ - (FT_Set_MM_Design_Func) T1_Set_MM_Design, /* set_mm_design */ - (FT_Set_MM_Blend_Func) T1_Set_MM_Blend, /* set_mm_blend */ - (FT_Get_MM_Blend_Func) T1_Get_MM_Blend, /* get_mm_blend */ - (FT_Get_MM_Var_Func) T1_Get_MM_Var, /* get_mm_var */ - (FT_Set_Var_Design_Func) T1_Set_Var_Design, /* set_var_design */ - (FT_Get_Var_Design_Func) T1_Get_Var_Design, /* get_var_design */ - (FT_Set_Instance_Func) T1_Reset_MM_Blend, /* set_instance */ - (FT_Set_MM_WeightVector_Func)T1_Set_MM_WeightVector, /* set_mm_weightvector */ - (FT_Get_MM_WeightVector_Func)T1_Get_MM_WeightVector, /* get_mm_weightvector */ + T1_Get_Multi_Master, /* FT_Get_MM_Func get_mm */ + T1_Set_MM_Design, /* FT_Set_MM_Design_Func set_mm_design */ + T1_Set_MM_Blend, /* FT_Set_MM_Blend_Func set_mm_blend */ + T1_Get_MM_Blend, /* FT_Get_MM_Blend_Func get_mm_blend */ + T1_Get_MM_Var, /* FT_Get_MM_Var_Func get_mm_var */ + T1_Set_Var_Design, /* FT_Set_Var_Design_Func set_var_design */ + T1_Get_Var_Design, /* FT_Get_Var_Design_Func get_var_design */ + T1_Reset_MM_Blend, /* FT_Set_Named_Instance_Func set_named_instance */ + NULL, /* FT_Get_Default_Named_Instance_Func get_default_named_instance */ + T1_Set_MM_WeightVector, + /* FT_Set_MM_WeightVector_Func set_mm_weightvector */ + T1_Get_MM_WeightVector, + /* FT_Get_MM_WeightVector_Func get_mm_weightvector */ - (FT_Get_Var_Blend_Func) NULL, /* get_var_blend */ - (FT_Done_Blend_Func) T1_Done_Blend /* done_blend */ + NULL, /* FT_Construct_PS_Name_Func construct_ps_name */ + NULL, /* FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map */ + NULL, /* FT_Var_Load_Item_Var_Store_Func load_item_variation_store */ + NULL, /* FT_Var_Get_Item_Delta_Func get_item_delta */ + NULL, /* FT_Var_Done_Item_Var_Store_Func done_item_variation_store */ + NULL, /* FT_Var_Done_Delta_Set_Idx_Map_Func done_delta_set_index_map */ + NULL, /* FT_Get_Var_Blend_Func get_var_blend */ + T1_Done_Blend /* FT_Done_Blend_Func done_blend */ }; #endif @@ -621,11 +637,11 @@ static const FT_Service_PsInfoRec t1_service_ps_info = { - (PS_GetFontInfoFunc) t1_ps_get_font_info, /* ps_get_font_info */ - (PS_GetFontExtraFunc) t1_ps_get_font_extra, /* ps_get_font_extra */ - (PS_HasGlyphNamesFunc) t1_ps_has_glyph_names, /* ps_has_glyph_names */ - (PS_GetFontPrivateFunc)t1_ps_get_font_private, /* ps_get_font_private */ - (PS_GetFontValueFunc) t1_ps_get_font_value, /* ps_get_font_value */ + t1_ps_get_font_info, /* PS_GetFontInfoFunc ps_get_font_info */ + t1_ps_get_font_extra, /* PS_GetFontExtraFunc ps_get_font_extra */ + t1_ps_has_glyph_names, /* PS_HasGlyphNamesFunc ps_has_glyph_names */ + t1_ps_get_font_private, /* PS_GetFontPrivateFunc ps_get_font_private */ + t1_ps_get_font_value, /* PS_GetFontValueFunc ps_get_font_value */ }; @@ -645,9 +661,9 @@ FT_DEFINE_SERVICE_PROPERTIESREC( t1_service_properties, - (FT_Properties_SetFunc)ps_property_set, /* set_property */ - (FT_Properties_GetFunc)ps_property_get ) /* get_property */ - + ps_property_set, /* FT_Properties_SetFunc set_property */ + ps_property_get /* FT_Properties_GetFunc get_property */ + ) /* * SERVICE LIST diff --git a/lib/libesp32_lvgl/freetype/src/type1/t1driver.h b/lib/libesp32_lvgl/freetype/src/type1/t1driver.h index e7eae0b88..ee7fcf43e 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/t1driver.h +++ b/lib/libesp32_lvgl/freetype/src/type1/t1driver.h @@ -4,7 +4,7 @@ * * High-level Type 1 driver interface (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/type1/t1errors.h b/lib/libesp32_lvgl/freetype/src/type1/t1errors.h index ad03a3d32..2fbd1e513 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/t1errors.h +++ b/lib/libesp32_lvgl/freetype/src/type1/t1errors.h @@ -4,7 +4,7 @@ * * Type 1 error codes (specification only). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/type1/t1gload.c b/lib/libesp32_lvgl/freetype/src/type1/t1gload.c index d16b81f24..a32a4649d 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/t1gload.c +++ b/lib/libesp32_lvgl/freetype/src/type1/t1gload.c @@ -4,7 +4,7 @@ * * Type 1 Glyph Loader (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -79,7 +79,7 @@ /* For ordinary fonts get the character data stored in the face record. */ { char_string->pointer = type1->charstrings[glyph_index]; - char_string->length = (FT_Int)type1->charstrings_len[glyph_index]; + char_string->length = type1->charstrings_len[glyph_index]; } if ( !error ) @@ -264,7 +264,7 @@ } FT_TRACE6(( "T1_Compute_Max_Advance: max advance: %f\n", - *max_advance / 65536.0 )); + (double)*max_advance / 65536 )); psaux->t1_decoder_funcs->done( &decoder ); diff --git a/lib/libesp32_lvgl/freetype/src/type1/t1gload.h b/lib/libesp32_lvgl/freetype/src/type1/t1gload.h index 9947507c8..c06484758 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/t1gload.h +++ b/lib/libesp32_lvgl/freetype/src/type1/t1gload.h @@ -4,7 +4,7 @@ * * Type 1 Glyph Loader (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/type1/t1load.c b/lib/libesp32_lvgl/freetype/src/type1/t1load.c index 84986007b..be7cd0fd5 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/t1load.c +++ b/lib/libesp32_lvgl/freetype/src/type1/t1load.c @@ -4,7 +4,7 @@ * * Type 1 font loader (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -73,7 +73,8 @@ #ifdef FT_CONFIG_OPTION_INCREMENTAL -#define IS_INCREMENTAL FT_BOOL( face->root.internal->incremental_interface ) +#define IS_INCREMENTAL \ + FT_BOOL( FT_FACE( face )->internal->incremental_interface ) #else #define IS_INCREMENTAL 0 #endif @@ -117,6 +118,9 @@ goto Exit; blend->num_default_design_vector = 0; + blend->weight_vector = NULL; + blend->default_weight_vector = NULL; + blend->design_pos[0] = NULL; face->blend = blend; } @@ -130,14 +134,11 @@ /* allocate the blend `private' and `font_info' dictionaries */ - if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs ) || - FT_NEW_ARRAY( blend->privates [1], num_designs ) || - FT_NEW_ARRAY( blend->bboxes [1], num_designs ) || - FT_NEW_ARRAY( blend->weight_vector, num_designs * 2 ) ) + if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs ) || + FT_NEW_ARRAY( blend->privates [1], num_designs ) || + FT_NEW_ARRAY( blend->bboxes [1], num_designs ) ) goto Exit; - blend->default_weight_vector = blend->weight_vector + num_designs; - blend->font_infos[0] = &face->type1.font_info; blend->privates [0] = &face->type1.private_dict; blend->bboxes [0] = &face->type1.font_bbox; @@ -164,21 +165,6 @@ blend->num_axis = num_axis; } - /* allocate the blend design pos table if needed */ - num_designs = blend->num_designs; - num_axis = blend->num_axis; - if ( num_designs && num_axis && blend->design_pos[0] == 0 ) - { - FT_UInt n; - - - if ( FT_NEW_ARRAY( blend->design_pos[0], num_designs * num_axis ) ) - goto Exit; - - for ( n = 1; n < num_designs; n++ ) - blend->design_pos[n] = blend->design_pos[0] + num_axis * n; - } - Exit: return error; @@ -189,10 +175,11 @@ FT_LOCAL_DEF( FT_Error ) - T1_Get_Multi_Master( T1_Face face, + T1_Get_Multi_Master( FT_Face face, /* T1_Face */ FT_Multi_Master* master ) { - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + PS_Blend blend = t1face->blend; FT_UInt n; FT_Error error; @@ -240,11 +227,12 @@ for ( j = 1; j < axismap->num_points; j++ ) { if ( ncv <= axismap->blend_points[j] ) - return INT_TO_FIXED( axismap->design_points[j - 1] ) + - ( axismap->design_points[j] - axismap->design_points[j - 1] ) * - FT_DivFix( ncv - axismap->blend_points[j - 1], - axismap->blend_points[j] - - axismap->blend_points[j - 1] ); + return INT_TO_FIXED( axismap->design_points[j - 1] + + FT_MulDiv( ncv - axismap->blend_points[j - 1], + axismap->design_points[j] - + axismap->design_points[j - 1], + axismap->blend_points[j] - + axismap->blend_points[j - 1] ) ); } return INT_TO_FIXED( axismap->design_points[axismap->num_points - 1] ); @@ -299,16 +287,17 @@ * arguments needed by the GX var distortable fonts. */ FT_LOCAL_DEF( FT_Error ) - T1_Get_MM_Var( T1_Face face, + T1_Get_MM_Var( FT_Face face, /* T1_Face */ FT_MM_Var* *master ) { - FT_Memory memory = face->root.memory; - FT_MM_Var *mmvar = NULL; + T1_Face t1face = (T1_Face)face; + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_MM_Var *mmvar = NULL; FT_Multi_Master mmaster; FT_Error error; FT_UInt i; FT_Fixed axiscoords[T1_MAX_MM_AXIS]; - PS_Blend blend = face->blend; + PS_Blend blend = t1face->blend; FT_UShort* axis_flags; FT_Offset mmvar_size; @@ -334,9 +323,9 @@ sizeof ( FT_UShort ) ); axis_size = mmaster.num_axis * sizeof ( FT_Var_Axis ); - if ( FT_ALLOC( mmvar, mmvar_size + - axis_flags_size + - axis_size ) ) + if ( FT_QALLOC( mmvar, mmvar_size + + axis_flags_size + + axis_size ) ) goto Exit; mmvar->num_axis = mmaster.num_axis; @@ -347,8 +336,7 @@ /* to make `FT_Get_Var_Axis_Flags' work: the function expects that the */ /* values directly follow the data of `FT_MM_Var' */ axis_flags = (FT_UShort*)( (char*)mmvar + mmvar_size ); - for ( i = 0; i < mmaster.num_axis; i++ ) - axis_flags[i] = 0; + FT_ARRAY_ZERO( axis_flags, mmaster.num_axis ); mmvar->axis = (FT_Var_Axis*)( (char*)axis_flags + axis_flags_size ); mmvar->namedstyle = NULL; @@ -370,6 +358,10 @@ mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'd', 't', 'h' ); else if ( ft_strcmp( mmvar->axis[i].name, "OpticalSize" ) == 0 ) mmvar->axis[i].tag = FT_MAKE_TAG( 'o', 'p', 's', 'z' ); + else if ( ft_strcmp( mmvar->axis[i].name, "Slant" ) == 0 ) + mmvar->axis[i].tag = FT_MAKE_TAG( 's', 'l', 'n', 't' ); + else if ( ft_strcmp( mmvar->axis[i].name, "Italic" ) == 0 ) + mmvar->axis[i].tag = FT_MAKE_TAG( 'i', 't', 'a', 'l' ); } mm_weights_unmap( blend->default_weight_vector, @@ -449,32 +441,21 @@ FT_LOCAL_DEF( FT_Error ) - T1_Set_MM_Blend( T1_Face face, + T1_Set_MM_Blend( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error; - - - error = t1_set_mm_blend( face, num_coords, coords ); - if ( error ) - return error; - - if ( num_coords ) - face->root.face_flags |= FT_FACE_FLAG_VARIATION; - else - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; - - return FT_Err_Ok; + return t1_set_mm_blend( (T1_Face)face, num_coords, coords ); } FT_LOCAL_DEF( FT_Error ) - T1_Get_MM_Blend( T1_Face face, + T1_Get_MM_Blend( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + PS_Blend blend = t1face->blend; FT_Fixed axiscoords[4]; FT_UInt i, nc; @@ -505,11 +486,12 @@ FT_LOCAL_DEF( FT_Error ) - T1_Set_MM_WeightVector( T1_Face face, + T1_Set_MM_WeightVector( FT_Face face, /* T1_Face */ FT_UInt len, FT_Fixed* weightvector ) { - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + PS_Blend blend = t1face->blend; FT_UInt i, n; @@ -533,11 +515,6 @@ for ( ; i < blend->num_designs; i++ ) blend->weight_vector[i] = (FT_Fixed)0; - - if ( len ) - face->root.face_flags |= FT_FACE_FLAG_VARIATION; - else - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; } return FT_Err_Ok; @@ -545,11 +522,12 @@ FT_LOCAL_DEF( FT_Error ) - T1_Get_MM_WeightVector( T1_Face face, + T1_Get_MM_WeightVector( FT_Face face, /* T1_Face */ FT_UInt* len, FT_Fixed* weightvector ) { - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + PS_Blend blend = t1face->blend; FT_UInt i; @@ -574,13 +552,14 @@ FT_LOCAL_DEF( FT_Error ) - T1_Set_MM_Design( T1_Face face, + T1_Set_MM_Design( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Long* coords ) { + T1_Face t1face = (T1_Face)face; FT_Error error; - PS_Blend blend = face->blend; - FT_UInt n, p; + PS_Blend blend = t1face->blend; + FT_UInt n; FT_Fixed final_blends[T1_MAX_MM_DESIGNS]; @@ -599,7 +578,7 @@ PS_DesignMap map = blend->design_map + n; FT_Long* designs = map->design_points; FT_Fixed* blends = map->blend_points; - FT_Int before = -1, after = -1; + FT_Int p, before = -1, after = -1; /* use a default value if we don't have a coordinate */ @@ -608,7 +587,7 @@ else design = ( designs[map->num_points - 1] - designs[0] ) / 2; - for ( p = 0; p < (FT_UInt)map->num_points; p++ ) + for ( p = 0; p < (FT_Int)map->num_points; p++ ) { FT_Long p_design = designs[p]; @@ -622,11 +601,11 @@ if ( design < p_design ) { - after = (FT_Int)p; + after = p; break; } - before = (FT_Int)p; + before = p; } /* now interpolate if necessary */ @@ -645,15 +624,10 @@ final_blends[n] = the_blend; } - error = t1_set_mm_blend( face, blend->num_axis, final_blends ); + error = t1_set_mm_blend( t1face, blend->num_axis, final_blends ); if ( error ) return error; - if ( num_coords ) - face->root.face_flags |= FT_FACE_FLAG_VARIATION; - else - face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; - return FT_Err_Ok; } @@ -661,7 +635,7 @@ /* MM fonts don't have named instances, so only the design is reset */ FT_LOCAL_DEF( FT_Error ) - T1_Reset_MM_Blend( T1_Face face, + T1_Reset_MM_Blend( FT_Face face, FT_UInt instance_index ) { FT_UNUSED( instance_index ); @@ -676,7 +650,7 @@ * arguments needed by the GX var distortable fonts. */ FT_LOCAL_DEF( FT_Error ) - T1_Set_Var_Design( T1_Face face, + T1_Set_Var_Design( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { @@ -695,11 +669,12 @@ FT_LOCAL_DEF( FT_Error ) - T1_Get_Var_Design( T1_Face face, + T1_Get_Var_Design( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + PS_Blend blend = t1face->blend; FT_Fixed axiscoords[4]; FT_UInt i, nc; @@ -731,10 +706,11 @@ FT_LOCAL_DEF( void ) - T1_Done_Blend( T1_Face face ) + T1_Done_Blend( FT_Face face ) /* T1_Face */ { - FT_Memory memory = face->root.memory; - PS_Blend blend = face->blend; + T1_Face t1face = (T1_Face)face; + FT_Memory memory = FT_FACE_MEMORY( face ); + PS_Blend blend = t1face->blend; if ( blend ) @@ -779,20 +755,22 @@ dmap->num_points = 0; } - FT_FREE( face->blend ); + FT_FREE( t1face->blend ); } } static void - parse_blend_axis_types( T1_Face face, - T1_Loader loader ) + parse_blend_axis_types( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; FT_Int n, num_axis; - FT_Error error = FT_Err_Ok; + FT_Error error = FT_Err_Ok; PS_Blend blend; - FT_Memory memory; + FT_Memory memory = FT_FACE_MEMORY( face ); /* take an array of objects */ @@ -812,14 +790,13 @@ } /* allocate blend if necessary */ - error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); + error = t1_allocate_blend( t1face, 0, (FT_UInt)num_axis ); if ( error ) goto Exit; FT_TRACE4(( " [" )); - blend = face->blend; - memory = face->root.memory; + blend = t1face->blend; /* each token is an immediate containing the name of the axis */ for ( n = 0; n < num_axis; n++ ) @@ -851,7 +828,7 @@ FT_FREE( name ); } - if ( FT_ALLOC( blend->axis_names[n], len + 1 ) ) + if ( FT_QALLOC( blend->axis_names[n], len + 1 ) ) goto Exit; name = (FT_Byte*)blend->axis_names[n]; @@ -867,17 +844,21 @@ static void - parse_blend_design_positions( T1_Face face, - T1_Loader loader ) + parse_blend_design_positions( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS]; FT_Int num_designs; - FT_Int num_axis; - T1_Parser parser = &loader->parser; + FT_Int num_axis = 0; /* make compiler happy */ + T1_Parser parser = &loader->parser; + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Error error = FT_Err_Ok; + FT_Fixed* design_pos[T1_MAX_MM_DESIGNS]; - FT_Error error = FT_Err_Ok; - PS_Blend blend; + design_pos[0] = NULL; /* get the array of design tokens -- compute number of designs */ T1_ToTokenArray( parser, design_tokens, @@ -899,12 +880,10 @@ { FT_Byte* old_cursor = parser->root.cursor; FT_Byte* old_limit = parser->root.limit; - FT_Int n; + FT_Int n, nn; + PS_Blend blend; - blend = face->blend; - num_axis = 0; /* make compiler happy */ - FT_TRACE4(( " [" )); for ( n = 0; n < num_designs; n++ ) @@ -932,12 +911,18 @@ } num_axis = n_axis; - error = t1_allocate_blend( face, + error = t1_allocate_blend( t1face, (FT_UInt)num_designs, (FT_UInt)num_axis ); if ( error ) goto Exit; - blend = face->blend; + + /* allocate a blend design pos table */ + if ( FT_QNEW_ARRAY( design_pos[0], num_designs * num_axis ) ) + goto Exit; + + for ( nn = 1; nn < num_designs; nn++ ) + design_pos[nn] = design_pos[0] + num_axis * nn; } else if ( n_axis != num_axis ) { @@ -955,8 +940,8 @@ parser->root.cursor = token2->start; parser->root.limit = token2->limit; - blend->design_pos[n][axis] = T1_ToFixed( parser, 0 ); - FT_TRACE4(( " %f", (double)blend->design_pos[n][axis] / 65536 )); + design_pos[n][axis] = T1_ToFixed( parser, 0 ); + FT_TRACE4(( " %f", (double)design_pos[n][axis] / 65536 )); } FT_TRACE4(( "]" )) ; } @@ -965,17 +950,31 @@ loader->parser.root.cursor = old_cursor; loader->parser.root.limit = old_limit; + + /* a valid BlendDesignPosition has been parsed */ + blend = t1face->blend; + if ( blend->design_pos[0] ) + FT_FREE( blend->design_pos[0] ); + + for ( n = 0; n < num_designs; n++ ) + { + blend->design_pos[n] = design_pos[n]; + design_pos[n] = NULL; + } } Exit: + FT_FREE( design_pos[0] ); loader->parser.root.error = error; } static void - parse_blend_design_map( T1_Face face, - T1_Loader loader ) + parse_blend_design_map( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; FT_Error error = FT_Err_Ok; T1_Parser parser = &loader->parser; PS_Blend blend; @@ -983,7 +982,7 @@ FT_Int n, num_axis; FT_Byte* old_cursor; FT_Byte* old_limit; - FT_Memory memory = face->root.memory; + FT_Memory memory = FT_FACE_MEMORY( face ); T1_ToTokenArray( parser, axis_tokens, @@ -1004,10 +1003,10 @@ old_cursor = parser->root.cursor; old_limit = parser->root.limit; - error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); + error = t1_allocate_blend( t1face, 0, (FT_UInt)num_axis ); if ( error ) goto Exit; - blend = face->blend; + blend = t1face->blend; FT_TRACE4(( " [" )); @@ -1044,7 +1043,7 @@ } /* allocate design map data */ - if ( FT_NEW_ARRAY( map->design_points, num_points * 2 ) ) + if ( FT_QNEW_ARRAY( map->design_points, num_points * 2 ) ) goto Exit; map->blend_points = map->design_points + num_points; map->num_points = (FT_Byte)num_points; @@ -1082,14 +1081,17 @@ static void - parse_weight_vector( T1_Face face, - T1_Loader loader ) + parse_weight_vector( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS]; FT_Int num_designs; FT_Error error = FT_Err_Ok; + FT_Memory memory = FT_FACE_MEMORY( face ); T1_Parser parser = &loader->parser; - PS_Blend blend = face->blend; + PS_Blend blend = t1face->blend; T1_Token token; FT_Int n; FT_Byte* old_cursor; @@ -1114,21 +1116,27 @@ if ( !blend || !blend->num_designs ) { - error = t1_allocate_blend( face, (FT_UInt)num_designs, 0 ); + error = t1_allocate_blend( t1face, (FT_UInt)num_designs, 0 ); if ( error ) goto Exit; - blend = face->blend; + blend = t1face->blend; } else if ( blend->num_designs != (FT_UInt)num_designs ) { FT_ERROR(( "parse_weight_vector:" - " /BlendDesignPosition and /WeightVector have\n" - " " + " /BlendDesignPosition and /WeightVector have\n" )); + FT_ERROR(( " " " different number of elements\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } + if ( !blend->weight_vector ) + if ( FT_QNEW_ARRAY( blend->weight_vector, num_designs * 2 ) ) + goto Exit; + + blend->default_weight_vector = blend->weight_vector + num_designs; + old_cursor = parser->root.cursor; old_limit = parser->root.limit; @@ -1159,11 +1167,15 @@ /* e.g., /BuildCharArray [0 0 0 0 0 0 0 0] def */ /* we're only interested in the number of array elements */ static void - parse_buildchar( T1_Face face, - T1_Loader loader ) + parse_buildchar( FT_Face face, /* T1_Face */ + void* loader_ ) { - face->len_buildchar = (FT_UInt)T1_ToFixedArray( &loader->parser, - 0, NULL, 0 ); + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; + + + t1face->len_buildchar = (FT_UInt)T1_ToFixedArray( &loader->parser, + 0, NULL, 0 ); #ifdef FT_DEBUG_LEVEL_TRACE { @@ -1171,7 +1183,7 @@ FT_TRACE4(( " [" )); - for ( i = 0; i < face->len_buildchar; i++ ) + for ( i = 0; i < t1face->len_buildchar; i++ ) FT_TRACE4(( " 0" )); FT_TRACE4(( "]\n" )); @@ -1307,9 +1319,9 @@ else { FT_TRACE1(( "t1_load_keyword: ignoring keyword `%s'" - " which is not valid at this point\n" - " (probably due to missing keywords)\n", + " which is not valid at this point\n", field->ident )); + FT_TRACE1(( " (probably due to missing keywords)\n" )); error = FT_Err_Ok; } @@ -1321,9 +1333,10 @@ static void - parse_private( T1_Face face, - T1_Loader loader ) + parse_private( FT_Face face, + void* loader_ ) { + T1_Loader loader = (T1_Loader)loader_; FT_UNUSED( face ); loader->keywords_encountered |= T1_PRIVATE; @@ -1387,13 +1400,14 @@ /* and `/CharStrings' dictionaries. */ static void - t1_parse_font_matrix( T1_Face face, - T1_Loader loader ) + t1_parse_font_matrix( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_Parser parser = &loader->parser; - FT_Matrix* matrix = &face->type1.font_matrix; - FT_Vector* offset = &face->type1.font_offset; - FT_Face root = (FT_Face)&face->root; + FT_Matrix* matrix = &t1face->type1.font_matrix; + FT_Vector* offset = &t1face->type1.font_offset; FT_Fixed temp[6]; FT_Fixed temp_scale; FT_Int result; @@ -1429,7 +1443,7 @@ if ( temp_scale != 0x10000L ) { /* set units per EM based on FontMatrix values */ - root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); + face->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); temp[0] = FT_DivFix( temp[0], temp_scale ); temp[1] = FT_DivFix( temp[1], temp_scale ); @@ -1457,14 +1471,16 @@ static void - parse_encoding( T1_Face face, - T1_Loader loader ) + parse_encoding( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_Parser parser = &loader->parser; FT_Byte* cur; FT_Byte* limit = parser->root.limit; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)t1face->psaux; T1_Skip_Spaces( parser ); @@ -1480,7 +1496,7 @@ /* and we must load it now */ if ( ft_isdigit( *cur ) || *cur == '[' ) { - T1_Encoding encode = &face->type1.encoding; + T1_Encoding encode = &t1face->type1.encoding; FT_Int count, array_size, n; PS_Table char_table = &loader->encoding_table; FT_Memory memory = parser->root.memory; @@ -1520,8 +1536,8 @@ /* we use a T1_Table to store our charnames */ loader->num_chars = encode->num_chars = array_size; - if ( FT_NEW_ARRAY( encode->char_index, array_size ) || - FT_NEW_ARRAY( encode->char_name, array_size ) || + if ( FT_QNEW_ARRAY( encode->char_index, array_size ) || + FT_QNEW_ARRAY( encode->char_name, array_size ) || FT_SET_ERROR( psaux->ps_table_funcs->init( char_table, array_size, memory ) ) ) { @@ -1662,7 +1678,7 @@ FT_TRACE4(( "]\n" )); #endif - face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; + t1face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; parser->root.cursor = cur; } @@ -1673,21 +1689,21 @@ if ( cur + 17 < limit && ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) { - face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; + t1face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; FT_TRACE4(( " StandardEncoding\n" )); } else if ( cur + 15 < limit && ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) { - face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; + t1face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; FT_TRACE4(( " ExpertEncoding\n" )); } else if ( cur + 18 < limit && ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) { - face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; + t1face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; FT_TRACE4(( " ISOLatin1Encoding\n" )); } @@ -1701,9 +1717,11 @@ static void - parse_subrs( T1_Face face, - T1_Loader loader ) + parse_subrs( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_Parser parser = &loader->parser; PS_Table table = &loader->subrs; FT_Memory memory = parser->root.memory; @@ -1711,7 +1729,7 @@ FT_Int num_subrs; FT_UInt count; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)t1face->psaux; T1_Skip_Spaces( parser ); @@ -1755,14 +1773,14 @@ */ FT_TRACE0(( "parse_subrs: adjusting number of subroutines" - " (from %d to %ld)\n", + " (from %d to %zu)\n", num_subrs, ( parser->root.limit - parser->root.cursor ) >> 3 )); num_subrs = ( parser->root.limit - parser->root.cursor ) >> 3; if ( !loader->subrs_hash ) { - if ( FT_NEW( loader->subrs_hash ) ) + if ( FT_QNEW( loader->subrs_hash ) ) goto Fail; error = ft_hash_num_init( loader->subrs_hash, memory ); @@ -1843,7 +1861,7 @@ /* */ /* thanks to Tom Kacvinsky for pointing this out */ /* */ - if ( face->type1.private_dict.lenIV >= 0 ) + if ( t1face->type1.private_dict.lenIV >= 0 ) { FT_Byte* temp = NULL; @@ -1851,20 +1869,22 @@ /* some fonts define empty subr records -- this is not totally */ /* compliant to the specification (which says they should at */ /* least contain a `return'), but we support them anyway */ - if ( size < (FT_ULong)face->type1.private_dict.lenIV ) + if ( size < (FT_ULong)t1face->type1.private_dict.lenIV ) { error = FT_THROW( Invalid_File_Format ); goto Fail; } /* t1_decrypt() shouldn't write to base -- make temporary copy */ - if ( FT_ALLOC( temp, size ) ) + if ( FT_QALLOC( temp, size ) ) goto Fail; FT_MEM_COPY( temp, base, size ); psaux->t1_decrypt( temp, size, 4330 ); - size -= (FT_ULong)face->type1.private_dict.lenIV; - error = T1_Add_Table( table, (FT_Int)idx, - temp + face->type1.private_dict.lenIV, size ); + size -= (FT_ULong)t1face->type1.private_dict.lenIV; + error = T1_Add_Table( table, + (FT_Int)idx, + temp + t1face->type1.private_dict.lenIV, + size ); FT_FREE( temp ); } else @@ -1896,9 +1916,11 @@ static void - parse_charstrings( T1_Face face, - T1_Loader loader ) + parse_charstrings( FT_Face face, /* T1_Face */ + void* loader_ ) { + T1_Face t1face = (T1_Face)face; + T1_Loader loader = (T1_Loader)loader_; T1_Parser parser = &loader->parser; PS_Table code_table = &loader->charstrings; PS_Table name_table = &loader->glyph_names; @@ -1906,7 +1928,7 @@ FT_Memory memory = parser->root.memory; FT_Error error; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)t1face->psaux; FT_Byte* cur = parser->root.cursor; FT_Byte* limit = parser->root.limit; @@ -1926,7 +1948,7 @@ if ( num_glyphs > ( limit - cur ) >> 3 ) { FT_TRACE0(( "parse_charstrings: adjusting number of glyphs" - " (from %d to %ld)\n", + " (from %d to %zu)\n", num_glyphs, ( limit - cur ) >> 3 )); num_glyphs = ( limit - cur ) >> 3; } @@ -2047,34 +2069,36 @@ name_table->elements[n][len] = '\0'; /* record index of /.notdef */ - if ( *cur == '.' && + if ( *cur == '.' && ft_strcmp( ".notdef", - (const char*)(name_table->elements[n]) ) == 0 ) + (const char*)( name_table->elements[n] ) ) == 0 ) { notdef_index = n; notdef_found = 1; } - if ( face->type1.private_dict.lenIV >= 0 && + if ( t1face->type1.private_dict.lenIV >= 0 && n < num_glyphs + TABLE_EXTEND ) { FT_Byte* temp = NULL; - if ( size <= (FT_ULong)face->type1.private_dict.lenIV ) + if ( size <= (FT_ULong)t1face->type1.private_dict.lenIV ) { error = FT_THROW( Invalid_File_Format ); goto Fail; } /* t1_decrypt() shouldn't write to base -- make temporary copy */ - if ( FT_ALLOC( temp, size ) ) + if ( FT_QALLOC( temp, size ) ) goto Fail; FT_MEM_COPY( temp, base, size ); psaux->t1_decrypt( temp, size, 4330 ); - size -= (FT_ULong)face->type1.private_dict.lenIV; - error = T1_Add_Table( code_table, n, - temp + face->type1.private_dict.lenIV, size ); + size -= (FT_ULong)t1face->type1.private_dict.lenIV; + error = T1_Add_Table( code_table, + n, + temp + t1face->type1.private_dict.lenIV, + size ); FT_FREE( temp ); } else @@ -2321,8 +2345,8 @@ /* in valid Type 1 fonts we don't see `RD' or `-|' directly */ /* since those tokens are handled by parse_subrs and */ /* parse_charstrings */ - else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' && - have_integer ) + else if ( *cur == 'R' && cur + 6 < limit && *( cur + 1 ) == 'D' && + have_integer ) { FT_ULong s; FT_Byte* b; @@ -2334,8 +2358,8 @@ have_integer = 0; } - else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' && - have_integer ) + else if ( *cur == '-' && cur + 6 < limit && *( cur + 1 ) == '|' && + have_integer ) { FT_ULong s; FT_Byte* b; @@ -2556,7 +2580,7 @@ { FT_ERROR(( "T1_Open_Face:" " number-of-designs != 2 ^^ number-of-axes\n" )); - T1_Done_Blend( face ); + T1_Done_Blend( FT_FACE( face ) ); } if ( face->blend && @@ -2576,9 +2600,17 @@ /* font as a normal PS font */ if ( face->blend && ( !face->blend->num_designs || !face->blend->num_axis ) ) - T1_Done_Blend( face ); + T1_Done_Blend( FT_FACE( face ) ); - /* another safety check */ + /* the font may have no valid WeightVector */ + if ( face->blend && !face->blend->weight_vector ) + T1_Done_Blend( FT_FACE( face ) ); + + /* the font may have no valid BlendDesignPositions */ + if ( face->blend && !face->blend->design_pos[0] ) + T1_Done_Blend( FT_FACE( face ) ); + + /* the font may have no valid BlendDesignMap */ if ( face->blend ) { FT_UInt i; @@ -2587,7 +2619,7 @@ for ( i = 0; i < face->blend->num_axis; i++ ) if ( !face->blend->design_map[i].num_points ) { - T1_Done_Blend( face ); + T1_Done_Blend( FT_FACE( face ) ); break; } } diff --git a/lib/libesp32_lvgl/freetype/src/type1/t1load.h b/lib/libesp32_lvgl/freetype/src/type1/t1load.h index 4396415c2..d8c9d2d8a 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/t1load.h +++ b/lib/libesp32_lvgl/freetype/src/type1/t1load.h @@ -4,7 +4,7 @@ * * Type 1 font loader (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -66,52 +66,52 @@ FT_BEGIN_HEADER #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT FT_LOCAL( FT_Error ) - T1_Get_Multi_Master( T1_Face face, + T1_Get_Multi_Master( FT_Face face, FT_Multi_Master* master ); FT_LOCAL( FT_Error ) - T1_Get_MM_Var( T1_Face face, + T1_Get_MM_Var( FT_Face face, FT_MM_Var* *master ); FT_LOCAL( FT_Error ) - T1_Set_MM_Blend( T1_Face face, + T1_Set_MM_Blend( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - T1_Get_MM_Blend( T1_Face face, + T1_Get_MM_Blend( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - T1_Set_MM_Design( T1_Face face, + T1_Set_MM_Design( FT_Face face, FT_UInt num_coords, FT_Long* coords ); FT_LOCAL( FT_Error ) - T1_Reset_MM_Blend( T1_Face face, + T1_Reset_MM_Blend( FT_Face face, FT_UInt instance_index ); FT_LOCAL( FT_Error ) - T1_Get_Var_Design( T1_Face face, + T1_Get_Var_Design( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( FT_Error ) - T1_Set_Var_Design( T1_Face face, + T1_Set_Var_Design( FT_Face face, FT_UInt num_coords, FT_Fixed* coords ); FT_LOCAL( void ) - T1_Done_Blend( T1_Face face ); + T1_Done_Blend( FT_Face face ); FT_LOCAL( FT_Error ) - T1_Set_MM_WeightVector( T1_Face face, + T1_Set_MM_WeightVector( FT_Face face, FT_UInt len, FT_Fixed* weightvector ); FT_LOCAL( FT_Error ) - T1_Get_MM_WeightVector( T1_Face face, + T1_Get_MM_WeightVector( FT_Face face, FT_UInt* len, FT_Fixed* weightvector ); diff --git a/lib/libesp32_lvgl/freetype/src/type1/t1objs.c b/lib/libesp32_lvgl/freetype/src/type1/t1objs.c index 3b918b733..69e4fd506 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/t1objs.c +++ b/lib/libesp32_lvgl/freetype/src/type1/t1objs.c @@ -4,7 +4,7 @@ * * Type 1 objects manager (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -116,11 +116,15 @@ T1_Size_Request( FT_Size t1size, /* T1_Size */ FT_Size_Request req ) { + FT_Error error; + T1_Size size = (T1_Size)t1size; PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size ); - FT_Request_Metrics( size->root.face, req ); + error = FT_Request_Metrics( size->root.face, req ); + if ( error ) + goto Exit; if ( funcs ) funcs->set_scale( (PSH_Globals)t1size->internal->module_data, @@ -128,7 +132,8 @@ size->root.metrics.y_scale, 0, 0 ); - return FT_Err_Ok; + Exit: + return error; } @@ -141,7 +146,9 @@ FT_LOCAL_DEF( void ) T1_GlyphSlot_Done( FT_GlyphSlot slot ) { - slot->internal->glyph_hints = NULL; + /* `slot->internal` might be NULL in out-of-memory situations. */ + if ( slot->internal ) + slot->internal->glyph_hints = NULL; } @@ -160,8 +167,7 @@ FT_Module module; - module = FT_Get_Module( slot->face->driver->root.library, - "pshinter" ); + module = FT_Get_Module( slot->library, "pshinter" ); if ( module ) { T1_Hints_Funcs funcs; @@ -217,11 +223,10 @@ { FT_FREE( face->buildchar ); - face->buildchar = NULL; face->len_buildchar = 0; } - T1_Done_Blend( face ); + T1_Done_Blend( t1face ); face->blend = NULL; #endif @@ -284,7 +289,8 @@ * * @Input: * stream :: - * input stream where to load font data. + * Dummy argument for compatibility with the `FT_Face_InitFunc` API. + * Ignored. The stream should be passed through `face->root.stream`. * * face_index :: * The index of the font face in the resource. @@ -598,11 +604,7 @@ /* set default property values, cf. `ftt1drv.h' */ -#ifdef T1_CONFIG_OPTION_OLD_ENGINE - driver->hinting_engine = FT_HINTING_FREETYPE; -#else driver->hinting_engine = FT_HINTING_ADOBE; -#endif driver->no_stem_darkening = TRUE; diff --git a/lib/libesp32_lvgl/freetype/src/type1/t1objs.h b/lib/libesp32_lvgl/freetype/src/type1/t1objs.h index 536be8ba1..03847b27e 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/t1objs.h +++ b/lib/libesp32_lvgl/freetype/src/type1/t1objs.h @@ -4,7 +4,7 @@ * * Type 1 objects manager (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/type1/t1parse.c b/lib/libesp32_lvgl/freetype/src/type1/t1parse.c index 74cf38bde..6dec6c16c 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/t1parse.c +++ b/lib/libesp32_lvgl/freetype/src/type1/t1parse.c @@ -4,7 +4,7 @@ * * Type 1 parser (body). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -221,7 +221,7 @@ else { /* read segment in memory -- this is clumsy, but so does the format */ - if ( FT_ALLOC( parser->base_dict, size ) || + if ( FT_QALLOC( parser->base_dict, size ) || FT_STREAM_READ( parser->base_dict, size ) ) goto Exit; parser->base_len = size; @@ -302,8 +302,8 @@ goto Fail; } - if ( FT_STREAM_SEEK( start_pos ) || - FT_ALLOC( parser->private_dict, parser->private_len ) ) + if ( FT_STREAM_SEEK( start_pos ) || + FT_QALLOC( parser->private_dict, parser->private_len ) ) goto Fail; parser->private_len = 0; @@ -330,50 +330,25 @@ /* the private dict. Otherwise, simply overwrite into the base */ /* dictionary block in the heap. */ - /* first of all, look at the `eexec' keyword */ + /* First look for the `eexec' keyword. Ensure `eexec' is real -- */ + /* it could be in a comment or string (as e.g. in u003043t.gsf */ + /* from ghostscript). */ FT_Byte* cur = parser->base_dict; FT_Byte* limit = cur + parser->base_len; FT_Pointer pos_lf; FT_Bool test_cr; - Again: - for (;;) - { - if ( cur[0] == 'e' && - cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */ - /* whitespace + 4 chars */ - { - if ( cur[1] == 'e' && - cur[2] == 'x' && - cur[3] == 'e' && - cur[4] == 'c' ) - break; - } - cur++; - if ( cur >= limit ) - { - FT_ERROR(( "T1_Get_Private_Dict:" - " could not find `eexec' keyword\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - } - - /* check whether `eexec' was real -- it could be in a comment */ - /* or string (as e.g. in u003043t.gsf from ghostscript) */ - parser->root.cursor = parser->base_dict; - /* set limit to `eexec' + whitespace + 4 characters */ - parser->root.limit = cur + 10; + parser->root.limit = parser->base_dict + parser->base_len; cur = parser->root.cursor; limit = parser->root.limit; while ( cur < limit ) { - if ( cur[0] == 'e' && - cur + 5 < limit ) + /* 9 = 5 letters for `eexec' + whitespace + 4 chars */ + if ( cur[0] == 'e' && cur + 9 < limit ) { if ( cur[1] == 'e' && cur[2] == 'x' && @@ -389,21 +364,9 @@ cur = parser->root.cursor; } - /* we haven't found the correct `eexec'; go back and continue */ - /* searching */ - - cur = limit; - limit = parser->base_dict + parser->base_len; - - if ( cur >= limit ) - { - FT_ERROR(( "T1_Get_Private_Dict:" - " premature end in private dictionary\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - goto Again; + FT_ERROR(( "T1_Get_Private_Dict: could not find `eexec' keyword\n" )); + error = FT_THROW( Invalid_File_Format ); + goto Exit; /* now determine where to write the _encrypted_ binary private */ /* dictionary. We overwrite the base dictionary for disk-based */ @@ -450,7 +413,7 @@ if ( parser->in_memory ) { /* note that we allocate one more byte to put a terminating `0' */ - if ( FT_ALLOC( parser->private_dict, size + 1 ) ) + if ( FT_QALLOC( parser->private_dict, size + 1 ) ) goto Fail; parser->private_len = size; } diff --git a/lib/libesp32_lvgl/freetype/src/type1/t1parse.h b/lib/libesp32_lvgl/freetype/src/type1/t1parse.h index 1ea0110b5..0d9a2865d 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/t1parse.h +++ b/lib/libesp32_lvgl/freetype/src/type1/t1parse.h @@ -4,7 +4,7 @@ * * Type 1 parser (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/type1/t1tokens.h b/lib/libesp32_lvgl/freetype/src/type1/t1tokens.h index c09420355..40f360926 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/t1tokens.h +++ b/lib/libesp32_lvgl/freetype/src/type1/t1tokens.h @@ -4,7 +4,7 @@ * * Type 1 tokenizer (specification). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/type1/type1.c b/lib/libesp32_lvgl/freetype/src/type1/type1.c index cadee7899..d9bd8cad9 100644 --- a/lib/libesp32_lvgl/freetype/src/type1/type1.c +++ b/lib/libesp32_lvgl/freetype/src/type1/type1.c @@ -4,7 +4,7 @@ * * FreeType Type 1 driver component (body only). * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/type42/module.mk b/lib/libesp32_lvgl/freetype/src/type42/module.mk index 6ef3a95ea..d98b12319 100644 --- a/lib/libesp32_lvgl/freetype/src/type42/module.mk +++ b/lib/libesp32_lvgl/freetype/src/type42/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 2002-2020 by +# Copyright (C) 2002-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/type42/rules.mk b/lib/libesp32_lvgl/freetype/src/type42/rules.mk index f4ce91a3b..41cb358d3 100644 --- a/lib/libesp32_lvgl/freetype/src/type42/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/type42/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 2002-2020 by +# Copyright (C) 2002-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/type42/t42drivr.c b/lib/libesp32_lvgl/freetype/src/type42/t42drivr.c index 90898b432..ee5fd44a9 100644 --- a/lib/libesp32_lvgl/freetype/src/type42/t42drivr.c +++ b/lib/libesp32_lvgl/freetype/src/type42/t42drivr.c @@ -4,7 +4,7 @@ * * High-level Type 42 driver interface (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * Roberto Alameda. * * This file is part of the FreeType project, and may only be used, @@ -56,33 +56,41 @@ * */ - static FT_Error - t42_get_glyph_name( T42_Face face, + FT_CALLBACK_DEF( FT_Error ) + t42_get_glyph_name( FT_Face face, /* T42_Face */ FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max ) { - FT_STRCPYN( buffer, face->type1.glyph_names[glyph_index], buffer_max ); + T42_Face t42face = (T42_Face)face; + + + FT_STRCPYN( buffer, + t42face->type1.glyph_names[glyph_index], + buffer_max ); return FT_Err_Ok; } - static FT_UInt - t42_get_name_index( T42_Face face, + FT_CALLBACK_DEF( FT_UInt ) + t42_get_name_index( FT_Face face, /* T42_Face */ const FT_String* glyph_name ) { - FT_Int i; + T42_Face t42face = (T42_Face)face; + FT_Int i; - for ( i = 0; i < face->type1.num_glyphs; i++ ) + for ( i = 0; i < t42face->type1.num_glyphs; i++ ) { - FT_String* gname = face->type1.glyph_names[i]; + FT_String* gname = t42face->type1.glyph_names[i]; if ( glyph_name[0] == gname[0] && !ft_strcmp( glyph_name, gname ) ) - return (FT_UInt)ft_strtol( (const char *)face->type1.charstrings[i], - NULL, 10 ); + return (FT_UInt)ft_strtol( + (const char *)t42face->type1.charstrings[i], + NULL, + 10 ); } return 0; @@ -102,10 +110,13 @@ * */ - static const char* - t42_get_ps_font_name( T42_Face face ) + FT_CALLBACK_DEF( const char* ) + t42_get_ps_font_name( FT_Face face ) /* T42_Face */ { - return (const char*)face->type1.font_name; + T42_Face t42face = (T42_Face)face; + + + return (const char*)t42face->type1.font_name; } @@ -121,7 +132,7 @@ * */ - static FT_Error + FT_CALLBACK_DEF( FT_Error ) t42_ps_get_font_info( FT_Face face, PS_FontInfoRec* afont_info ) { @@ -131,7 +142,7 @@ } - static FT_Error + FT_CALLBACK_DEF( FT_Error ) t42_ps_get_font_extra( FT_Face face, PS_FontExtraRec* afont_extra ) { @@ -141,7 +152,7 @@ } - static FT_Int + FT_CALLBACK_DEF( FT_Int ) t42_ps_has_glyph_names( FT_Face face ) { FT_UNUSED( face ); @@ -150,22 +161,13 @@ } - static FT_Error - t42_ps_get_font_private( FT_Face face, - PS_PrivateRec* afont_private ) - { - *afont_private = ((T42_Face)face)->type1.private_dict; - - return FT_Err_Ok; - } - - static const FT_Service_PsInfoRec t42_service_ps_info = { (PS_GetFontInfoFunc) t42_ps_get_font_info, /* ps_get_font_info */ (PS_GetFontExtraFunc) t42_ps_get_font_extra, /* ps_get_font_extra */ (PS_HasGlyphNamesFunc) t42_ps_has_glyph_names, /* ps_has_glyph_names */ - (PS_GetFontPrivateFunc)t42_ps_get_font_private, /* ps_get_font_private */ + /* Type42 fonts don't have a Private dict */ + (PS_GetFontPrivateFunc)NULL, /* ps_get_font_private */ /* not implemented */ (PS_GetFontValueFunc) NULL /* ps_get_font_value */ }; diff --git a/lib/libesp32_lvgl/freetype/src/type42/t42drivr.h b/lib/libesp32_lvgl/freetype/src/type42/t42drivr.h index 8bf2afc75..ec7da18cc 100644 --- a/lib/libesp32_lvgl/freetype/src/type42/t42drivr.h +++ b/lib/libesp32_lvgl/freetype/src/type42/t42drivr.h @@ -4,7 +4,7 @@ * * High-level Type 42 driver interface (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * Roberto Alameda. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/type42/t42error.h b/lib/libesp32_lvgl/freetype/src/type42/t42error.h index e48132ec0..dcea9c4f6 100644 --- a/lib/libesp32_lvgl/freetype/src/type42/t42error.h +++ b/lib/libesp32_lvgl/freetype/src/type42/t42error.h @@ -4,7 +4,7 @@ * * Type 42 error codes (specification only). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/type42/t42objs.c b/lib/libesp32_lvgl/freetype/src/type42/t42objs.c index 6acfcdf40..bf4028e75 100644 --- a/lib/libesp32_lvgl/freetype/src/type42/t42objs.c +++ b/lib/libesp32_lvgl/freetype/src/type42/t42objs.c @@ -4,7 +4,7 @@ * * Type 42 objects manager (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * Roberto Alameda. * * This file is part of the FreeType project, and may only be used, @@ -44,14 +44,8 @@ parser = &loader.parser; - if ( FT_ALLOC( face->ttf_data, 12 ) ) - goto Exit; - - /* while parsing the font we always update `face->ttf_size' so that */ - /* even in case of buggy data (which might lead to premature end of */ - /* scanning without causing an error) the call to `FT_Open_Face' in */ - /* `T42_Face_Init' passes the correct size */ - face->ttf_size = 12; + face->ttf_data = NULL; + face->ttf_size = 0; error = t42_parser_init( parser, face->root.stream, @@ -152,6 +146,11 @@ Exit: t42_loader_done( &loader ); + if ( error ) + { + FT_FREE( face->ttf_data ); + face->ttf_size = 0; + } return error; } @@ -510,7 +509,8 @@ error = FT_New_Size( t42face->ttf_face, &ttsize ); - t42size->ttsize = ttsize; + if ( !error ) + t42size->ttsize = ttsize; FT_Activate_Size( ttsize ); @@ -582,6 +582,7 @@ FT_Face face = t42slot->face; T42_Face t42face = (T42_Face)face; FT_GlyphSlot ttslot; + FT_Memory memory = face->memory; FT_Error error = FT_Err_Ok; @@ -593,9 +594,15 @@ else { error = FT_New_GlyphSlot( t42face->ttf_face, &ttslot ); - slot->ttslot = ttslot; + if ( !error ) + slot->ttslot = ttslot; } + /* share the loader so that the autohinter can see it */ + FT_GlyphLoader_Done( slot->ttslot->internal->loader ); + FT_FREE( slot->ttslot->internal ); + slot->ttslot->internal = t42slot->internal; + return error; } @@ -606,6 +613,8 @@ T42_GlyphSlot slot = (T42_GlyphSlot)t42slot; + /* do not destroy the inherited internal structure just yet */ + slot->ttslot->internal = NULL; FT_Done_GlyphSlot( slot->ttslot ); } diff --git a/lib/libesp32_lvgl/freetype/src/type42/t42objs.h b/lib/libesp32_lvgl/freetype/src/type42/t42objs.h index 69f5cffd4..33e6215e1 100644 --- a/lib/libesp32_lvgl/freetype/src/type42/t42objs.h +++ b/lib/libesp32_lvgl/freetype/src/type42/t42objs.h @@ -4,7 +4,7 @@ * * Type 42 objects manager (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * Roberto Alameda. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/type42/t42parse.c b/lib/libesp32_lvgl/freetype/src/type42/t42parse.c index 98507699f..f96a43b14 100644 --- a/lib/libesp32_lvgl/freetype/src/type42/t42parse.c +++ b/lib/libesp32_lvgl/freetype/src/type42/t42parse.c @@ -4,7 +4,7 @@ * * Type 42 font parser (body). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * Roberto Alameda. * * This file is part of the FreeType project, and may only be used, @@ -34,19 +34,19 @@ static void - t42_parse_font_matrix( T42_Face face, - T42_Loader loader ); + t42_parse_font_matrix( FT_Face face, + void* loader_ ); static void - t42_parse_encoding( T42_Face face, - T42_Loader loader ); + t42_parse_encoding( FT_Face face, + void* loader_ ); static void - t42_parse_charstrings( T42_Face face, - T42_Loader loader ); + t42_parse_charstrings( FT_Face face, + void* loader_ ); static void - t42_parse_sfnts( T42_Face face, - T42_Loader loader ); + t42_parse_sfnts( FT_Face face, + void* loader_ ); /* as Type42 fonts have no Private dict, */ @@ -92,7 +92,7 @@ #undef T1CODE #define T1CODE T1_FIELD_LOCATION_BBOX - T1_FIELD_BBOX("FontBBox", xMin, 0 ) + T1_FIELD_BBOX( "FontBBox", xMin, 0 ) T1_FIELD_CALLBACK( "FontMatrix", t42_parse_font_matrix, 0 ) T1_FIELD_CALLBACK( "Encoding", t42_parse_encoding, 0 ) @@ -197,7 +197,7 @@ else { /* read segment in memory */ - if ( FT_ALLOC( parser->base_dict, size ) || + if ( FT_QALLOC( parser->base_dict, size ) || FT_STREAM_READ( parser->base_dict, size ) ) goto Exit; @@ -241,12 +241,14 @@ static void - t42_parse_font_matrix( T42_Face face, - T42_Loader loader ) + t42_parse_font_matrix( FT_Face face, /* T42_Face */ + void* loader_ ) { - T42_Parser parser = &loader->parser; - FT_Matrix* matrix = &face->type1.font_matrix; - FT_Vector* offset = &face->type1.font_offset; + T42_Face t42face = (T42_Face)face; + T42_Loader loader = (T42_Loader)loader_; + T42_Parser parser = &loader->parser; + FT_Matrix* matrix = &t42face->type1.font_matrix; + FT_Vector* offset = &t42face->type1.font_offset; FT_Fixed temp[6]; FT_Fixed temp_scale; FT_Int result; @@ -299,14 +301,16 @@ static void - t42_parse_encoding( T42_Face face, - T42_Loader loader ) + t42_parse_encoding( FT_Face face, + void* loader_ ) { - T42_Parser parser = &loader->parser; + T42_Face t42face = (T42_Face)face; + T42_Loader loader = (T42_Loader)loader_; + T42_Parser parser = &loader->parser; FT_Byte* cur; - FT_Byte* limit = parser->root.limit; + FT_Byte* limit = parser->root.limit; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)t42face->psaux; T1_Skip_Spaces( parser ); @@ -322,7 +326,7 @@ /* and we must load it now */ if ( ft_isdigit( *cur ) || *cur == '[' ) { - T1_Encoding encode = &face->type1.encoding; + T1_Encoding encode = &t42face->type1.encoding; FT_Int count, n; PS_Table char_table = &loader->encoding_table; FT_Memory memory = parser->root.memory; @@ -363,8 +367,8 @@ /* we use a T1_Table to store our charnames */ loader->num_chars = encode->num_chars = count; - if ( FT_NEW_ARRAY( encode->char_index, count ) || - FT_NEW_ARRAY( encode->char_name, count ) || + if ( FT_QNEW_ARRAY( encode->char_index, count ) || + FT_QNEW_ARRAY( encode->char_name, count ) || FT_SET_ERROR( psaux->ps_table_funcs->init( char_table, count, memory ) ) ) { @@ -493,8 +497,8 @@ T1_Skip_Spaces( parser ); } - face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; - parser->root.cursor = cur; + t42face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; + parser->root.cursor = cur; } /* Otherwise, we should have either `StandardEncoding', */ @@ -503,15 +507,15 @@ { if ( cur + 17 < limit && ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) - face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; + t42face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; else if ( cur + 15 < limit && ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) - face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; + t42face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; else if ( cur + 18 < limit && ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) - face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; + t42face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; else parser->root.error = FT_ERR( Ignore ); @@ -529,16 +533,19 @@ static void - t42_parse_sfnts( T42_Face face, - T42_Loader loader ) + t42_parse_sfnts( FT_Face face, + void* loader_ ) { + T42_Face t42face = (T42_Face)face; + T42_Loader loader = (T42_Loader)loader_; T42_Parser parser = &loader->parser; FT_Memory memory = parser->root.memory; FT_Byte* cur; FT_Byte* limit = parser->root.limit; FT_Error error; FT_Int num_tables = 0; - FT_Long count; + FT_Long ttf_count; + FT_Long ttf_reserved; FT_ULong n, string_size, old_string_size, real_size; FT_Byte* string_buf = NULL; @@ -546,6 +553,9 @@ T42_Load_Status status; + /** There should only be one sfnts array, but free any previous. */ + FT_FREE( t42face->ttf_data ); + t42face->ttf_size = 0; /* The format is */ /* */ @@ -574,7 +584,13 @@ status = BEFORE_START; string_size = 0; old_string_size = 0; - count = 0; + ttf_count = 0; + ttf_reserved = 12; + if ( FT_QALLOC( t42face->ttf_data, ttf_reserved ) ) + goto Fail; + + FT_TRACE2(( "\n" )); + FT_TRACE2(( "t42_parse_sfnts:\n" )); while ( parser->root.cursor < limit ) { @@ -586,6 +602,7 @@ if ( *cur == ']' ) { parser->root.cursor++; + t42face->ttf_size = ttf_count; goto Exit; } @@ -611,7 +628,7 @@ error = FT_THROW( Invalid_File_Format ); goto Fail; } - if ( FT_REALLOC( string_buf, old_string_size, string_size ) ) + if ( FT_QREALLOC( string_buf, old_string_size, string_size ) ) goto Fail; allocated = 1; @@ -680,6 +697,9 @@ goto Fail; } + FT_TRACE2(( " PS string size %5lu bytes, offset 0x%08lx (%lu)\n", + string_size, ttf_count, ttf_count )); + /* The whole TTF is now loaded into `string_buf'. We are */ /* checking its contents while copying it to `ttf_data'. */ @@ -691,50 +711,64 @@ { case BEFORE_START: /* load offset table, 12 bytes */ - if ( count < 12 ) + if ( ttf_count < 12 ) { - face->ttf_data[count++] = string_buf[n]; + t42face->ttf_data[ttf_count++] = string_buf[n]; continue; } else { - num_tables = 16 * face->ttf_data[4] + face->ttf_data[5]; - status = BEFORE_TABLE_DIR; - face->ttf_size = 12 + 16 * num_tables; + FT_Long ttf_reserved_prev = ttf_reserved; - if ( (FT_Long)size < face->ttf_size ) + + num_tables = 16 * t42face->ttf_data[4] + t42face->ttf_data[5]; + status = BEFORE_TABLE_DIR; + ttf_reserved = 12 + 16 * num_tables; + + FT_TRACE2(( " SFNT directory contains %d tables\n", + num_tables )); + + if ( (FT_Long)size < ttf_reserved ) { FT_ERROR(( "t42_parse_sfnts: invalid data in sfnts array\n" )); error = FT_THROW( Invalid_File_Format ); goto Fail; } - if ( FT_REALLOC( face->ttf_data, 12, face->ttf_size ) ) + if ( FT_QREALLOC( t42face->ttf_data, ttf_reserved_prev, + ttf_reserved ) ) goto Fail; } - /* fall through */ + FALL_THROUGH; case BEFORE_TABLE_DIR: /* the offset table is read; read the table directory */ - if ( count < face->ttf_size ) + if ( ttf_count < ttf_reserved ) { - face->ttf_data[count++] = string_buf[n]; + t42face->ttf_data[ttf_count++] = string_buf[n]; continue; } else { int i; FT_ULong len; + FT_Long ttf_reserved_prev = ttf_reserved; + FT_TRACE2(( "\n" )); + FT_TRACE2(( " table length\n" )); + FT_TRACE2(( " ------------------------------\n" )); + for ( i = 0; i < num_tables; i++ ) { - FT_Byte* p = face->ttf_data + 12 + 16 * i + 12; + FT_Byte* p = t42face->ttf_data + 12 + 16 * i + 12; len = FT_PEEK_ULONG( p ); + FT_TRACE2(( " %4i 0x%08lx (%lu)\n", i, len, len )); + if ( len > size || - face->ttf_size > (FT_Long)( size - len ) ) + ttf_reserved > (FT_Long)( size - len ) ) { FT_ERROR(( "t42_parse_sfnts:" " invalid data in sfnts array\n" )); @@ -743,26 +777,31 @@ } /* Pad to a 4-byte boundary length */ - face->ttf_size += (FT_Long)( ( len + 3 ) & ~3U ); + ttf_reserved += (FT_Long)( ( len + 3 ) & ~3U ); } + ttf_reserved += 1; status = OTHER_TABLES; - if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables, - face->ttf_size + 1 ) ) + FT_TRACE2(( "\n" )); + FT_TRACE2(( " allocating %ld bytes\n", ttf_reserved )); + FT_TRACE2(( "\n" )); + + if ( FT_QREALLOC( t42face->ttf_data, ttf_reserved_prev, + ttf_reserved ) ) goto Fail; } - /* fall through */ + FALL_THROUGH; case OTHER_TABLES: /* all other tables are just copied */ - if ( count >= face->ttf_size ) + if ( ttf_count >= ttf_reserved ) { FT_ERROR(( "t42_parse_sfnts: too much binary data\n" )); error = FT_THROW( Invalid_File_Format ); goto Fail; } - face->ttf_data[count++] = string_buf[n]; + t42face->ttf_data[ttf_count++] = string_buf[n]; } } @@ -776,15 +815,22 @@ parser->root.error = error; Exit: + if ( parser->root.error ) + { + FT_FREE( t42face->ttf_data ); + t42face->ttf_size = 0; + } if ( allocated ) FT_FREE( string_buf ); } static void - t42_parse_charstrings( T42_Face face, - T42_Loader loader ) + t42_parse_charstrings( FT_Face face, /* T42_Face */ + void* loader_ ) { + T42_Face t42face = (T42_Face)face; + T42_Loader loader = (T42_Loader)loader_; T42_Parser parser = &loader->parser; PS_Table code_table = &loader->charstrings; PS_Table name_table = &loader->glyph_names; @@ -792,7 +838,7 @@ FT_Memory memory = parser->root.memory; FT_Error error; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)t42face->psaux; FT_Byte* cur; FT_Byte* limit = parser->root.limit; @@ -826,7 +872,7 @@ if ( loader->num_glyphs > ( limit - parser->root.cursor ) >> 2 ) { FT_TRACE0(( "t42_parse_charstrings: adjusting number of glyphs" - " (from %d to %ld)\n", + " (from %d to %zu)\n", loader->num_glyphs, ( limit - parser->root.cursor ) >> 2 )); loader->num_glyphs = ( limit - parser->root.cursor ) >> 2; @@ -970,9 +1016,9 @@ name_table->elements[n][len] = '\0'; /* record index of /.notdef */ - if ( *cur == '.' && + if ( *cur == '.' && ft_strcmp( ".notdef", - (const char*)(name_table->elements[n]) ) == 0 ) + (const char*)( name_table->elements[n] ) ) == 0 ) { notdef_index = n; notdef_found = 1; diff --git a/lib/libesp32_lvgl/freetype/src/type42/t42parse.h b/lib/libesp32_lvgl/freetype/src/type42/t42parse.h index 2ccf052d7..5741c5413 100644 --- a/lib/libesp32_lvgl/freetype/src/type42/t42parse.h +++ b/lib/libesp32_lvgl/freetype/src/type42/t42parse.h @@ -4,7 +4,7 @@ * * Type 42 font parser (specification). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * Roberto Alameda. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/type42/t42types.h b/lib/libesp32_lvgl/freetype/src/type42/t42types.h index ba0cc2142..0bfe14ee4 100644 --- a/lib/libesp32_lvgl/freetype/src/type42/t42types.h +++ b/lib/libesp32_lvgl/freetype/src/type42/t42types.h @@ -4,7 +4,7 @@ * * Type 42 font data types (specification only). * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * Roberto Alameda. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/type42/type42.c b/lib/libesp32_lvgl/freetype/src/type42/type42.c index 012559e2f..8d2302c8e 100644 --- a/lib/libesp32_lvgl/freetype/src/type42/type42.c +++ b/lib/libesp32_lvgl/freetype/src/type42/type42.c @@ -4,7 +4,7 @@ * * FreeType Type 42 driver component. * - * Copyright (C) 2002-2020 by + * Copyright (C) 2002-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/winfonts/fnterrs.h b/lib/libesp32_lvgl/freetype/src/winfonts/fnterrs.h index 550de386f..dafdb07b4 100644 --- a/lib/libesp32_lvgl/freetype/src/winfonts/fnterrs.h +++ b/lib/libesp32_lvgl/freetype/src/winfonts/fnterrs.h @@ -4,7 +4,7 @@ * * Win FNT/FON error codes (specification only). * - * Copyright (C) 2001-2020 by + * Copyright (C) 2001-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/lib/libesp32_lvgl/freetype/src/winfonts/module.mk b/lib/libesp32_lvgl/freetype/src/winfonts/module.mk index 4614c55fd..78a290065 100644 --- a/lib/libesp32_lvgl/freetype/src/winfonts/module.mk +++ b/lib/libesp32_lvgl/freetype/src/winfonts/module.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/winfonts/rules.mk b/lib/libesp32_lvgl/freetype/src/winfonts/rules.mk index e73ef5ea9..b39c519e0 100644 --- a/lib/libesp32_lvgl/freetype/src/winfonts/rules.mk +++ b/lib/libesp32_lvgl/freetype/src/winfonts/rules.mk @@ -3,7 +3,7 @@ # -# Copyright (C) 1996-2020 by +# Copyright (C) 1996-2023 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/lib/libesp32_lvgl/freetype/src/winfonts/winfnt.c b/lib/libesp32_lvgl/freetype/src/winfonts/winfnt.c index e83312d16..1160e4ef3 100644 --- a/lib/libesp32_lvgl/freetype/src/winfonts/winfnt.c +++ b/lib/libesp32_lvgl/freetype/src/winfonts/winfnt.c @@ -4,7 +4,7 @@ * * FreeType font driver for Windows FNT/FON files * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * Copyright 2003 Huw D M Davies for Codeweavers * Copyright 2007 Dmitry Timoshkov for Codeweavers @@ -217,7 +217,11 @@ /* first of all, read the FNT header */ if ( FT_STREAM_SEEK( font->offset ) || FT_STREAM_READ_FIELDS( winfnt_header_fields, header ) ) + { + FT_TRACE2(( " not a Windows FNT file\n" )); + error = FT_THROW( Unknown_File_Format ); goto Exit; + } /* check header */ if ( header->version != 0x200 && @@ -284,7 +288,10 @@ /* does it begin with an MZ header? */ if ( FT_STREAM_SEEK( 0 ) || FT_STREAM_READ_FIELDS( winmz_header_fields, &mz_header ) ) + { + error = FT_ERR( Unknown_File_Format ); goto Exit; + } error = FT_ERR( Unknown_File_Format ); if ( mz_header.magic == WINFNT_MZ_MAGIC ) @@ -345,6 +352,10 @@ count = FT_GET_USHORT_LE(); + FT_TRACE2(( type_id == 0x8007U ? "RT_FONTDIR count %hu\n" : + type_id == 0x8008U ? "RT_FONT count %hu\n" : "", + count )); + if ( type_id == 0x8008U ) { font_count = count; @@ -420,12 +431,12 @@ goto Exit; FT_TRACE2(( "magic %04lx, machine %02x, number_of_sections %u, " - "size_of_optional_header %02x\n" - "magic32 %02x, rsrc_virtual_address %04lx, " - "rsrc_size %04lx\n", + "size_of_optional_header %02x\n", pe32_header.magic, pe32_header.machine, pe32_header.number_of_sections, - pe32_header.size_of_optional_header, + pe32_header.size_of_optional_header )); + FT_TRACE2(( "magic32 %02x, rsrc_virtual_address %04lx, " + "rsrc_size %04lx\n", pe32_header.magic32, pe32_header.rsrc_virtual_address, pe32_header.rsrc_size )); @@ -478,7 +489,7 @@ &dir_entry1 ) ) goto Exit; - if ( !(dir_entry1.offset & 0x80000000UL ) /* DataIsDirectory */ ) + if ( !( dir_entry1.offset & 0x80000000UL ) /* DataIsDirectory */ ) { error = FT_THROW( Invalid_File_Format ); goto Exit; @@ -502,7 +513,7 @@ &dir_entry2 ) ) goto Exit; - if ( !(dir_entry2.offset & 0x80000000UL ) /* DataIsDirectory */ ) + if ( !( dir_entry2.offset & 0x80000000UL ) /* DataIsDirectory */ ) { error = FT_THROW( Invalid_File_Format ); goto Exit; @@ -613,31 +624,34 @@ static FT_Error - fnt_cmap_init( FNT_CMap cmap, + fnt_cmap_init( FT_CMap cmap, /* FNT_CMap */ FT_Pointer pointer ) { - FNT_Face face = (FNT_Face)FT_CMAP_FACE( cmap ); - FNT_Font font = face->font; + FNT_CMap fntcmap = (FNT_CMap)cmap; + FNT_Face face = (FNT_Face)FT_CMAP_FACE( cmap ); + FNT_Font font = face->font; FT_UNUSED( pointer ); - cmap->first = (FT_UInt32) font->header.first_char; - cmap->count = (FT_UInt32)( font->header.last_char - cmap->first + 1 ); + fntcmap->first = (FT_UInt32)font->header.first_char; + fntcmap->count = (FT_UInt32)( font->header.last_char - + fntcmap->first + 1 ); return 0; } static FT_UInt - fnt_cmap_char_index( FNT_CMap cmap, + fnt_cmap_char_index( FT_CMap cmap, /* FNT_CMap */ FT_UInt32 char_code ) { - FT_UInt gindex = 0; + FNT_CMap fntcmap = (FNT_CMap)cmap; + FT_UInt gindex = 0; - char_code -= cmap->first; - if ( char_code < cmap->count ) + char_code -= fntcmap->first; + if ( char_code < fntcmap->count ) /* we artificially increase the glyph index; */ /* FNT_Load_Glyph reverts to the right one */ gindex = (FT_UInt)( char_code + 1 ); @@ -645,26 +659,27 @@ } - static FT_UInt32 - fnt_cmap_char_next( FNT_CMap cmap, + static FT_UInt + fnt_cmap_char_next( FT_CMap cmap, /* FNT_CMap */ FT_UInt32 *pchar_code ) { - FT_UInt gindex = 0; - FT_UInt32 result = 0; + FNT_CMap fntcmap = (FNT_CMap)cmap; + FT_UInt gindex = 0; + FT_UInt32 result = 0; FT_UInt32 char_code = *pchar_code + 1; - if ( char_code <= cmap->first ) + if ( char_code <= fntcmap->first ) { - result = cmap->first; + result = fntcmap->first; gindex = 1; } else { - char_code -= cmap->first; - if ( char_code < cmap->count ) + char_code -= fntcmap->first; + if ( char_code < fntcmap->count ) { - result = cmap->first + char_code; + result = fntcmap->first + char_code; gindex = (FT_UInt)( char_code + 1 ); } } @@ -793,7 +808,7 @@ root->style_flags |= FT_STYLE_FLAG_BOLD; /* set up the `fixed_sizes' array */ - if ( FT_NEW_ARRAY( root->available_sizes, 1 ) ) + if ( FT_QNEW( root->available_sizes ) ) goto Fail; root->num_fixed_sizes = 1; @@ -885,10 +900,10 @@ } family_size = font->header.file_size - font->header.face_name_offset; /* Some broken fonts don't delimit the face name with a final */ - /* NULL byte -- the frame is erroneously one byte too small. */ + /* null byte -- the frame is erroneously one byte too small. */ /* We thus allocate one more byte, setting it explicitly to */ /* zero. */ - if ( FT_ALLOC( font->family_name, family_size + 1 ) ) + if ( FT_QALLOC( font->family_name, family_size + 1 ) ) goto Fail; FT_MEM_COPY( font->family_name, @@ -897,9 +912,10 @@ font->family_name[family_size] = '\0'; - if ( FT_REALLOC( font->family_name, - family_size, - ft_strlen( font->family_name ) + 1 ) ) + /* shrink it to the actual length */ + if ( FT_QREALLOC( font->family_name, + family_size + 1, + ft_strlen( font->family_name ) + 1 ) ) goto Fail; root->family_name = font->family_name; @@ -1094,7 +1110,7 @@ /* note: since glyphs are stored in columns and not in rows we */ /* can't use ft_glyphslot_set_bitmap */ - if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, pitch ) ) + if ( FT_QALLOC_MULT( bitmap->buffer, bitmap->rows, pitch ) ) goto Exit; column = (FT_Byte*)bitmap->buffer; diff --git a/lib/libesp32_lvgl/freetype/src/winfonts/winfnt.h b/lib/libesp32_lvgl/freetype/src/winfonts/winfnt.h index 3367c7715..2f75b9e86 100644 --- a/lib/libesp32_lvgl/freetype/src/winfonts/winfnt.h +++ b/lib/libesp32_lvgl/freetype/src/winfonts/winfnt.h @@ -4,7 +4,7 @@ * * FreeType font driver for Windows FNT/FON files * - * Copyright (C) 1996-2020 by + * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * Copyright 2007 Dmitry Timoshkov for Codeweavers * diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/LVGL_API_Reference.md b/lib/libesp32_lvgl/lv_binding_berry/generate/LVGL_API_Reference.md new file mode 100644 index 000000000..117a701e1 --- /dev/null +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/LVGL_API_Reference.md @@ -0,0 +1,1514 @@ +# LVGL Berry API Reference + +[//]: # (**********************************************************************) +[//]: # (* Generated code, don't edit *) +[//]: # (**********************************************************************) + + +## module `lv` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +anim_count_running||int|[lv_anim_count_running](https://docs.lvgl.io/9.0/search.html?q=lv_anim_count_running) +anim_delete|\, comptr|bool|[lv_anim_delete](https://docs.lvgl.io/9.0/search.html?q=lv_anim_delete) +anim_delete_all|||[lv_anim_delete_all](https://docs.lvgl.io/9.0/search.html?q=lv_anim_delete_all) +anim_get|\, comptr|lv.anim|[lv_anim_get](https://docs.lvgl.io/9.0/search.html?q=lv_anim_get) +anim_get_timer||lv.timer|[lv_anim_get_timer](https://docs.lvgl.io/9.0/search.html?q=lv_anim_get_timer) +anim_refr_now|||[lv_anim_refr_now](https://docs.lvgl.io/9.0/search.html?q=lv_anim_refr_now) +anim_speed|int|int|[lv_anim_speed](https://docs.lvgl.io/9.0/search.html?q=lv_anim_speed) +anim_speed_clamped|int, int, int|int|[lv_anim_speed_clamped](https://docs.lvgl.io/9.0/search.html?q=lv_anim_speed_clamped) +area_align|lv.area, lv.area, int, int, int||[lv_area_align](https://docs.lvgl.io/9.0/search.html?q=lv_area_align) +area_copy|lv.area, lv.area||[lv_area_copy](https://docs.lvgl.io/9.0/search.html?q=lv_area_copy) +area_get_height|lv.area|int|[lv_area_get_height](https://docs.lvgl.io/9.0/search.html?q=lv_area_get_height) +area_get_size|lv.area|int|[lv_area_get_size](https://docs.lvgl.io/9.0/search.html?q=lv_area_get_size) +area_get_width|lv.area|int|[lv_area_get_width](https://docs.lvgl.io/9.0/search.html?q=lv_area_get_width) +area_increase|lv.area, int, int||[lv_area_increase](https://docs.lvgl.io/9.0/search.html?q=lv_area_increase) +area_move|lv.area, int, int||[lv_area_move](https://docs.lvgl.io/9.0/search.html?q=lv_area_move) +area_set|lv.area, int, int, int, int||[lv_area_set](https://docs.lvgl.io/9.0/search.html?q=lv_area_set) +area_set_height|lv.area, int||[lv_area_set_height](https://docs.lvgl.io/9.0/search.html?q=lv_area_set_height) +area_set_width|lv.area, int||[lv_area_set_width](https://docs.lvgl.io/9.0/search.html?q=lv_area_set_width) +canvas_buf_size|int, int, int, int|int|[lv_canvas_buf_size](https://docs.lvgl.io/9.0/search.html?q=lv_canvas_buf_size) +clamp_height|int, int, int, int|int|[lv_clamp_height](https://docs.lvgl.io/9.0/search.html?q=lv_clamp_height) +clamp_width|int, int, int, int|int|[lv_clamp_width](https://docs.lvgl.io/9.0/search.html?q=lv_clamp_width) +color32_eq|int, int|bool|[lv_color32_eq](https://docs.lvgl.io/9.0/search.html?q=lv_color32_eq) +color32_make|int, int, int, int|int|[lv_color32_make](https://docs.lvgl.io/9.0/search.html?q=lv_color32_make) +color_16_16_mix|int, int, int|int|[lv_color_16_16_mix](https://docs.lvgl.io/9.0/search.html?q=lv_color_16_16_mix) +color_black||lv.color|[lv_color_black](https://docs.lvgl.io/9.0/search.html?q=lv_color_black) +color_brightness|lv.color|int|[lv_color_brightness](https://docs.lvgl.io/9.0/search.html?q=lv_color_brightness) +color_darken|lv.color, int|lv.color|[lv_color_darken](https://docs.lvgl.io/9.0/search.html?q=lv_color_darken) +color_eq|lv.color, lv.color|bool|[lv_color_eq](https://docs.lvgl.io/9.0/search.html?q=lv_color_eq) +color_format_get_bpp|int|int|[lv_color_format_get_bpp](https://docs.lvgl.io/9.0/search.html?q=lv_color_format_get_bpp) +color_format_get_size|int|int|[lv_color_format_get_size](https://docs.lvgl.io/9.0/search.html?q=lv_color_format_get_size) +color_format_has_alpha|int|bool|[lv_color_format_has_alpha](https://docs.lvgl.io/9.0/search.html?q=lv_color_format_has_alpha) +color_hex|int|lv.color|[lv_color_hex](https://docs.lvgl.io/9.0/search.html?q=lv_color_hex) +color_hex3|int|lv.color|[lv_color_hex3](https://docs.lvgl.io/9.0/search.html?q=lv_color_hex3) +color_hsv_to_rgb|int, int, int|lv.color|[lv_color_hsv_to_rgb](https://docs.lvgl.io/9.0/search.html?q=lv_color_hsv_to_rgb) +color_lighten|lv.color, int|lv.color|[lv_color_lighten](https://docs.lvgl.io/9.0/search.html?q=lv_color_lighten) +color_make|int, int, int|lv.color|[lv_color_make](https://docs.lvgl.io/9.0/search.html?q=lv_color_make) +color_mix|lv.color, lv.color, int|lv.color|[lv_color_mix](https://docs.lvgl.io/9.0/search.html?q=lv_color_mix) +color_mix32|int, int|int|[lv_color_mix32](https://docs.lvgl.io/9.0/search.html?q=lv_color_mix32) +color_rgb_to_hsv|int, int, int|int|[lv_color_rgb_to_hsv](https://docs.lvgl.io/9.0/search.html?q=lv_color_rgb_to_hsv) +color_to_32|lv.color, int|int|[lv_color_to_32](https://docs.lvgl.io/9.0/search.html?q=lv_color_to_32) +color_to_hsv|lv.color|int|[lv_color_to_hsv](https://docs.lvgl.io/9.0/search.html?q=lv_color_to_hsv) +color_to_int|lv.color|int|[lv_color_to_int](https://docs.lvgl.io/9.0/search.html?q=lv_color_to_int) +color_to_u16|lv.color|int|[lv_color_to_u16](https://docs.lvgl.io/9.0/search.html?q=lv_color_to_u16) +color_to_u32|lv.color|int|[lv_color_to_u32](https://docs.lvgl.io/9.0/search.html?q=lv_color_to_u32) +color_white||lv.color|[lv_color_white](https://docs.lvgl.io/9.0/search.html?q=lv_color_white) +display_create|int, int|lv.display|[lv_display_create](https://docs.lvgl.io/9.0/search.html?q=lv_display_create) +display_get_default||lv.display|[lv_display_get_default](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_default) +dpx|int|int|[lv_dpx](https://docs.lvgl.io/9.0/search.html?q=lv_dpx) +draw_arc|comptr, lv.draw_arc_dsc||[lv_draw_arc](https://docs.lvgl.io/9.0/search.html?q=lv_draw_arc) +draw_arc_dsc_init|lv.draw_arc_dsc||[lv_draw_arc_dsc_init](https://docs.lvgl.io/9.0/search.html?q=lv_draw_arc_dsc_init) +draw_arc_get_area|int, int, int, int, int, int, bool, lv.area||[lv_draw_arc_get_area](https://docs.lvgl.io/9.0/search.html?q=lv_draw_arc_get_area) +draw_character|comptr, lv.draw_label_dsc, comptr, int||[lv_draw_character](https://docs.lvgl.io/9.0/search.html?q=lv_draw_character) +draw_create_unit|int|comptr|[lv_draw_create_unit](https://docs.lvgl.io/9.0/search.html?q=lv_draw_create_unit) +draw_deinit|||[lv_draw_deinit](https://docs.lvgl.io/9.0/search.html?q=lv_draw_deinit) +draw_dispatch|||[lv_draw_dispatch](https://docs.lvgl.io/9.0/search.html?q=lv_draw_dispatch) +draw_dispatch_layer|lv.display, comptr|bool|[lv_draw_dispatch_layer](https://docs.lvgl.io/9.0/search.html?q=lv_draw_dispatch_layer) +draw_dispatch_request|||[lv_draw_dispatch_request](https://docs.lvgl.io/9.0/search.html?q=lv_draw_dispatch_request) +draw_dispatch_wait_for_request|||[lv_draw_dispatch_wait_for_request](https://docs.lvgl.io/9.0/search.html?q=lv_draw_dispatch_wait_for_request) +draw_init|||[lv_draw_init](https://docs.lvgl.io/9.0/search.html?q=lv_draw_init) +draw_label|comptr, lv.draw_label_dsc, lv.area||[lv_draw_label](https://docs.lvgl.io/9.0/search.html?q=lv_draw_label) +draw_label_dsc_init|lv.draw_label_dsc||[lv_draw_label_dsc_init](https://docs.lvgl.io/9.0/search.html?q=lv_draw_label_dsc_init) +draw_layer_alloc_buf|comptr|comptr|[lv_draw_layer_alloc_buf](https://docs.lvgl.io/9.0/search.html?q=lv_draw_layer_alloc_buf) +draw_layer_create|comptr, int, lv.area|comptr|[lv_draw_layer_create](https://docs.lvgl.io/9.0/search.html?q=lv_draw_layer_create) +draw_layer_go_to_xy|comptr, int, int|comptr|[lv_draw_layer_go_to_xy](https://docs.lvgl.io/9.0/search.html?q=lv_draw_layer_go_to_xy) +draw_line|comptr, lv.draw_line_dsc||[lv_draw_line](https://docs.lvgl.io/9.0/search.html?q=lv_draw_line) +draw_line_dsc_init|lv.draw_line_dsc||[lv_draw_line_dsc_init](https://docs.lvgl.io/9.0/search.html?q=lv_draw_line_dsc_init) +draw_rect|comptr, lv.draw_rect_dsc, lv.area||[lv_draw_rect](https://docs.lvgl.io/9.0/search.html?q=lv_draw_rect) +draw_rect_dsc_init|lv.draw_rect_dsc||[lv_draw_rect_dsc_init](https://docs.lvgl.io/9.0/search.html?q=lv_draw_rect_dsc_init) +draw_vector|comptr||[lv_draw_vector](https://docs.lvgl.io/9.0/search.html?q=lv_draw_vector) +event_register_id||int|[lv_event_register_id](https://docs.lvgl.io/9.0/search.html?q=lv_event_register_id) +font_get_glyph_width|lv.font, int, int|int|[lv_font_get_glyph_width](https://docs.lvgl.io/9.0/search.html?q=lv_font_get_glyph_width) +font_get_line_height|lv.font|int|[lv_font_get_line_height](https://docs.lvgl.io/9.0/search.html?q=lv_font_get_line_height) +font_set_kerning|lv.font, int||[lv_font_set_kerning](https://docs.lvgl.io/9.0/search.html?q=lv_font_set_kerning) +get_hor_res||int|[lv_get_hor_res](https://docs.lvgl.io/9.0/search.html?q=lv_get_hor_res) +get_ts_calibration||lv.ts_calibration|[lv_get_ts_calibration](https://docs.lvgl.io/9.0/search.html?q=lv_get_ts_calibration) +get_ver_res||int|[lv_get_ver_res](https://docs.lvgl.io/9.0/search.html?q=lv_get_ver_res) +group_by_index|int|lv.group|[lv_group_by_index](https://docs.lvgl.io/9.0/search.html?q=lv_group_by_index) +group_get_count||int|[lv_group_get_count](https://docs.lvgl.io/9.0/search.html?q=lv_group_get_count) +group_get_default||lv.group|[lv_group_get_default](https://docs.lvgl.io/9.0/search.html?q=lv_group_get_default) +indev_active||lv.indev|[lv_indev_active](https://docs.lvgl.io/9.0/search.html?q=lv_indev_active) +indev_create||lv.indev|[lv_indev_create](https://docs.lvgl.io/9.0/search.html?q=lv_indev_create) +indev_get_active_obj||lv.obj|[lv_indev_get_active_obj](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_active_obj) +indev_read_timer_cb|lv.timer||[lv_indev_read_timer_cb](https://docs.lvgl.io/9.0/search.html?q=lv_indev_read_timer_cb) +layer_bottom||lv.obj|[lv_layer_bottom](https://docs.lvgl.io/9.0/search.html?q=lv_layer_bottom) +layer_sys||lv.obj|[lv_layer_sys](https://docs.lvgl.io/9.0/search.html?q=lv_layer_sys) +layer_top||lv.obj|[lv_layer_top](https://docs.lvgl.io/9.0/search.html?q=lv_layer_top) +obj_assign_id|lv.obj_class, lv.obj||[lv_obj_assign_id](https://docs.lvgl.io/9.0/search.html?q=lv_obj_assign_id) +obj_class_create_obj|lv.obj_class, lv.obj|lv.obj|[lv_obj_class_create_obj](https://docs.lvgl.io/9.0/search.html?q=lv_obj_class_create_obj) +obj_delete_anim_completed_cb|lv.anim||[lv_obj_delete_anim_completed_cb](https://docs.lvgl.io/9.0/search.html?q=lv_obj_delete_anim_completed_cb) +obj_enable_style_refresh|bool||[lv_obj_enable_style_refresh](https://docs.lvgl.io/9.0/search.html?q=lv_obj_enable_style_refresh) +obj_event_base|lv.obj_class, lv.event|int|[lv_obj_event_base](https://docs.lvgl.io/9.0/search.html?q=lv_obj_event_base) +obj_redraw|comptr, lv.obj||[lv_obj_redraw](https://docs.lvgl.io/9.0/search.html?q=lv_obj_redraw) +obj_report_style_change|lv.style||[lv_obj_report_style_change](https://docs.lvgl.io/9.0/search.html?q=lv_obj_report_style_change) +obj_style_get_selector_part|int|int|[lv_obj_style_get_selector_part](https://docs.lvgl.io/9.0/search.html?q=lv_obj_style_get_selector_part) +obj_style_get_selector_state|int|int|[lv_obj_style_get_selector_state](https://docs.lvgl.io/9.0/search.html?q=lv_obj_style_get_selector_state) +objid_builtin_destroy|||[lv_objid_builtin_destroy](https://docs.lvgl.io/9.0/search.html?q=lv_objid_builtin_destroy) +pct|int|int|[lv_pct](https://docs.lvgl.io/9.0/search.html?q=lv_pct) +pct_to_px|int, int|int|[lv_pct_to_px](https://docs.lvgl.io/9.0/search.html?q=lv_pct_to_px) +point_from_precise|lv.point_precise|int|[lv_point_from_precise](https://docs.lvgl.io/9.0/search.html?q=lv_point_from_precise) +point_precise_set|lv.point_precise, int, int||[lv_point_precise_set](https://docs.lvgl.io/9.0/search.html?q=lv_point_precise_set) +point_precise_swap|lv.point_precise, lv.point_precise||[lv_point_precise_swap](https://docs.lvgl.io/9.0/search.html?q=lv_point_precise_swap) +point_set|comptr, int, int||[lv_point_set](https://docs.lvgl.io/9.0/search.html?q=lv_point_set) +point_swap|comptr, comptr||[lv_point_swap](https://docs.lvgl.io/9.0/search.html?q=lv_point_swap) +point_transform|comptr, int, int, int, comptr, bool||[lv_point_transform](https://docs.lvgl.io/9.0/search.html?q=lv_point_transform) +refr_now|lv.display||[lv_refr_now](https://docs.lvgl.io/9.0/search.html?q=lv_refr_now) +scale_section_set_range|comptr, int, int||[lv_scale_section_set_range](https://docs.lvgl.io/9.0/search.html?q=lv_scale_section_set_range) +scale_section_set_style|comptr, int, lv.style||[lv_scale_section_set_style](https://docs.lvgl.io/9.0/search.html?q=lv_scale_section_set_style) +scr_act||lv.obj|[lv_screen_active](https://docs.lvgl.io/9.0/search.html?q=lv_screen_active) +scr_load|lv.obj||[lv_screen_load](https://docs.lvgl.io/9.0/search.html?q=lv_screen_load) +scr_load_anim|lv.obj, int, int, int, bool||[lv_screen_load_anim](https://docs.lvgl.io/9.0/search.html?q=lv_screen_load_anim) +screen_active||lv.obj|[lv_screen_active](https://docs.lvgl.io/9.0/search.html?q=lv_screen_active) +screen_load|lv.obj||[lv_screen_load](https://docs.lvgl.io/9.0/search.html?q=lv_screen_load) +screen_load_anim|lv.obj, int, int, int, bool||[lv_screen_load_anim](https://docs.lvgl.io/9.0/search.html?q=lv_screen_load_anim) +span_set_text|lv.spangroup, string||[lv_span_set_text](https://docs.lvgl.io/9.0/search.html?q=lv_span_set_text) +span_set_text_static|lv.spangroup, string||[lv_span_set_text_static](https://docs.lvgl.io/9.0/search.html?q=lv_span_set_text_static) +span_stack_deinit|||[lv_span_stack_deinit](https://docs.lvgl.io/9.0/search.html?q=lv_span_stack_deinit) +span_stack_init|||[lv_span_stack_init](https://docs.lvgl.io/9.0/search.html?q=lv_span_stack_init) +style_get_num_custom_props||int|[lv_style_get_num_custom_props](https://docs.lvgl.io/9.0/search.html?q=lv_style_get_num_custom_props) +style_prop_get_default|int|int|[lv_style_prop_get_default](https://docs.lvgl.io/9.0/search.html?q=lv_style_prop_get_default) +style_prop_has_flag|int, int|bool|[lv_style_prop_has_flag](https://docs.lvgl.io/9.0/search.html?q=lv_style_prop_has_flag) +style_register_prop|int|int|[lv_style_register_prop](https://docs.lvgl.io/9.0/search.html?q=lv_style_register_prop) +task_handler||int|[lv_task_handler](https://docs.lvgl.io/9.0/search.html?q=lv_task_handler) +theme_apply|lv.obj||[lv_theme_apply](https://docs.lvgl.io/9.0/search.html?q=lv_theme_apply) +theme_get_color_primary|lv.obj|lv.color|[lv_theme_get_color_primary](https://docs.lvgl.io/9.0/search.html?q=lv_theme_get_color_primary) +theme_get_color_secondary|lv.obj|lv.color|[lv_theme_get_color_secondary](https://docs.lvgl.io/9.0/search.html?q=lv_theme_get_color_secondary) +theme_get_font_large|lv.obj|lv.font|[lv_theme_get_font_large](https://docs.lvgl.io/9.0/search.html?q=lv_theme_get_font_large) +theme_get_font_normal|lv.obj|lv.font|[lv_theme_get_font_normal](https://docs.lvgl.io/9.0/search.html?q=lv_theme_get_font_normal) +theme_get_font_small|lv.obj|lv.font|[lv_theme_get_font_small](https://docs.lvgl.io/9.0/search.html?q=lv_theme_get_font_small) +theme_get_from_obj|lv.obj|lv.theme|[lv_theme_get_from_obj](https://docs.lvgl.io/9.0/search.html?q=lv_theme_get_from_obj) +theme_haspmota_init|lv.display, lv.color, lv.color, bool, lv.font|lv.theme|[lv_theme_haspmota_init](https://docs.lvgl.io/9.0/search.html?q=lv_theme_haspmota_init) +theme_haspmota_is_inited||bool|[lv_theme_haspmota_is_inited](https://docs.lvgl.io/9.0/search.html?q=lv_theme_haspmota_is_inited) +theme_set_parent|lv.theme, lv.theme||[lv_theme_set_parent](https://docs.lvgl.io/9.0/search.html?q=lv_theme_set_parent) +timer_create|\, int, \|lv.timer|[lv_timer_create](https://docs.lvgl.io/9.0/search.html?q=lv_timer_create) +timer_create_basic||lv.timer|[lv_timer_create_basic](https://docs.lvgl.io/9.0/search.html?q=lv_timer_create_basic) +timer_enable|bool||[lv_timer_enable](https://docs.lvgl.io/9.0/search.html?q=lv_timer_enable) +timer_get_idle||int|[lv_timer_get_idle](https://docs.lvgl.io/9.0/search.html?q=lv_timer_get_idle) +timer_get_time_until_next||int|[lv_timer_get_time_until_next](https://docs.lvgl.io/9.0/search.html?q=lv_timer_get_time_until_next) +timer_handler||int|[lv_timer_handler](https://docs.lvgl.io/9.0/search.html?q=lv_timer_handler) +timer_handler_run_in_period|int|int|[lv_timer_handler_run_in_period](https://docs.lvgl.io/9.0/search.html?q=lv_timer_handler_run_in_period) +timer_periodic_handler|||[lv_timer_periodic_handler](https://docs.lvgl.io/9.0/search.html?q=lv_timer_periodic_handler) +vector_clear_area|comptr, lv.area||[lv_vector_clear_area](https://docs.lvgl.io/9.0/search.html?q=lv_vector_clear_area) +vector_dsc_add_path|comptr, comptr||[lv_vector_dsc_add_path](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_add_path) +vector_dsc_create|comptr|comptr|[lv_vector_dsc_create](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_create) +vector_dsc_delete|comptr||[lv_vector_dsc_delete](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_delete) +vector_dsc_identity|comptr||[lv_vector_dsc_identity](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_identity) +vector_dsc_rotate|comptr, f||[lv_vector_dsc_rotate](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_rotate) +vector_dsc_scale|comptr, f, f||[lv_vector_dsc_scale](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_scale) +vector_dsc_set_blend_mode|comptr, int||[lv_vector_dsc_set_blend_mode](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_blend_mode) +vector_dsc_set_fill_color|comptr, lv.color||[lv_vector_dsc_set_fill_color](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_fill_color) +vector_dsc_set_fill_color32|comptr, int||[lv_vector_dsc_set_fill_color32](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_fill_color32) +vector_dsc_set_fill_image|comptr, lv.draw_image_dsc||[lv_vector_dsc_set_fill_image](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_fill_image) +vector_dsc_set_fill_linear_gradient|comptr, lv.grad_dsc, int||[lv_vector_dsc_set_fill_linear_gradient](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_fill_linear_gradient) +vector_dsc_set_fill_opa|comptr, int||[lv_vector_dsc_set_fill_opa](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_fill_opa) +vector_dsc_set_fill_radial_gradient|comptr, lv.grad_dsc, f, f, f, int||[lv_vector_dsc_set_fill_radial_gradient](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_fill_radial_gradient) +vector_dsc_set_fill_rule|comptr, int||[lv_vector_dsc_set_fill_rule](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_fill_rule) +vector_dsc_set_stroke_cap|comptr, int||[lv_vector_dsc_set_stroke_cap](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_stroke_cap) +vector_dsc_set_stroke_color|comptr, lv.color||[lv_vector_dsc_set_stroke_color](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_stroke_color) +vector_dsc_set_stroke_color32|comptr, int||[lv_vector_dsc_set_stroke_color32](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_stroke_color32) +vector_dsc_set_stroke_dash|comptr, lv.float_arr, int||[lv_vector_dsc_set_stroke_dash](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_stroke_dash) +vector_dsc_set_stroke_join|comptr, int||[lv_vector_dsc_set_stroke_join](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_stroke_join) +vector_dsc_set_stroke_linear_gradient|comptr, lv.grad_dsc, int||[lv_vector_dsc_set_stroke_linear_gradient](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_stroke_linear_gradient) +vector_dsc_set_stroke_miter_limit|comptr, int||[lv_vector_dsc_set_stroke_miter_limit](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_stroke_miter_limit) +vector_dsc_set_stroke_opa|comptr, int||[lv_vector_dsc_set_stroke_opa](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_stroke_opa) +vector_dsc_set_stroke_radial_gradient|comptr, lv.grad_dsc, f, f, f, int||[lv_vector_dsc_set_stroke_radial_gradient](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_stroke_radial_gradient) +vector_dsc_set_stroke_width|comptr, f||[lv_vector_dsc_set_stroke_width](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_set_stroke_width) +vector_dsc_skew|comptr, f, f||[lv_vector_dsc_skew](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_skew) +vector_dsc_translate|comptr, f, f||[lv_vector_dsc_translate](https://docs.lvgl.io/9.0/search.html?q=lv_vector_dsc_translate) +vector_path_append_path|comptr, comptr||[lv_vector_path_append_path](https://docs.lvgl.io/9.0/search.html?q=lv_vector_path_append_path) +vector_path_append_rect|comptr, lv.area, f, f||[lv_vector_path_append_rect](https://docs.lvgl.io/9.0/search.html?q=lv_vector_path_append_rect) +vector_path_clear|comptr||[lv_vector_path_clear](https://docs.lvgl.io/9.0/search.html?q=lv_vector_path_clear) +vector_path_close|comptr||[lv_vector_path_close](https://docs.lvgl.io/9.0/search.html?q=lv_vector_path_close) +vector_path_copy|comptr, comptr||[lv_vector_path_copy](https://docs.lvgl.io/9.0/search.html?q=lv_vector_path_copy) +vector_path_create|int|comptr|[lv_vector_path_create](https://docs.lvgl.io/9.0/search.html?q=lv_vector_path_create) +vector_path_delete|comptr||[lv_vector_path_delete](https://docs.lvgl.io/9.0/search.html?q=lv_vector_path_delete) +version_info||string|[lv_version_info](https://docs.lvgl.io/9.0/search.html?q=lv_version_info) +version_major||int|[lv_version_major](https://docs.lvgl.io/9.0/search.html?q=lv_version_major) +version_minor||int|[lv_version_minor](https://docs.lvgl.io/9.0/search.html?q=lv_version_minor) +version_patch||int|[lv_version_patch](https://docs.lvgl.io/9.0/search.html?q=lv_version_patch) + +## Core classes + +### class `lv.anim` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +custom_delete|comptr|bool|[lv_anim_custom_delete](https://docs.lvgl.io/9.0/search.html?q=lv_anim_custom_delete) +custom_get|comptr|lv.anim|[lv_anim_custom_get](https://docs.lvgl.io/9.0/search.html?q=lv_anim_custom_get) +get_delay||int|[lv_anim_get_delay](https://docs.lvgl.io/9.0/search.html?q=lv_anim_get_delay) +get_playtime||int|[lv_anim_get_playtime](https://docs.lvgl.io/9.0/search.html?q=lv_anim_get_playtime) +get_repeat_count||int|[lv_anim_get_repeat_count](https://docs.lvgl.io/9.0/search.html?q=lv_anim_get_repeat_count) +get_time||int|[lv_anim_get_time](https://docs.lvgl.io/9.0/search.html?q=lv_anim_get_time) +get_user_data||comptr|[lv_anim_get_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_anim_get_user_data) +init|||[lv_anim_init](https://docs.lvgl.io/9.0/search.html?q=lv_anim_init) +set_bezier3_param|int, int, int, int||[lv_anim_set_bezier3_param](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_bezier3_param) +set_completed_cb|comptr||[lv_anim_set_completed_cb](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_completed_cb) +set_custom_exec_cb|comptr||[lv_anim_set_custom_exec_cb](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_custom_exec_cb) +set_delay|int||[lv_anim_set_delay](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_delay) +set_duration|int||[lv_anim_set_duration](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_duration) +set_early_apply|bool||[lv_anim_set_early_apply](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_early_apply) +set_exec_cb|comptr||[lv_anim_set_exec_cb](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_exec_cb) +set_get_value_cb|comptr||[lv_anim_set_get_value_cb](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_get_value_cb) +set_path_cb|comptr||[lv_anim_set_path_cb](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_path_cb) +set_playback_delay|int||[lv_anim_set_playback_delay](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_playback_delay) +set_playback_duration|int||[lv_anim_set_playback_duration](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_playback_duration) +set_playback_time|int||[lv_anim_set_playback_time](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_playback_time) +set_ready_cb|comptr||[lv_anim_set_completed_cb](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_completed_cb) +set_repeat_count|int||[lv_anim_set_repeat_count](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_repeat_count) +set_repeat_delay|int||[lv_anim_set_repeat_delay](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_repeat_delay) +set_start_cb|comptr||[lv_anim_set_start_cb](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_start_cb) +set_time|int||[lv_anim_set_time](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_time) +set_user_data|\||[lv_anim_set_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_user_data) +set_values|int, int||[lv_anim_set_values](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_values) +set_var|\||[lv_anim_set_var](https://docs.lvgl.io/9.0/search.html?q=lv_anim_set_var) +start||lv.anim|[lv_anim_start](https://docs.lvgl.io/9.0/search.html?q=lv_anim_start) + +### class `lv.display` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +add_event_cb|\, int, \||[lv_display_add_event_cb](https://docs.lvgl.io/9.0/search.html?q=lv_display_add_event_cb) +del|||[lv_display_delete](https://docs.lvgl.io/9.0/search.html?q=lv_display_delete) +delete|||[lv_display_delete](https://docs.lvgl.io/9.0/search.html?q=lv_display_delete) +delete_event|int|bool|[lv_display_delete_event](https://docs.lvgl.io/9.0/search.html?q=lv_display_delete_event) +delete_refr_timer|||[lv_display_delete_refr_timer](https://docs.lvgl.io/9.0/search.html?q=lv_display_delete_refr_timer) +dpx|int|int|[lv_display_dpx](https://docs.lvgl.io/9.0/search.html?q=lv_display_dpx) +enable_invalidation|bool||[lv_display_enable_invalidation](https://docs.lvgl.io/9.0/search.html?q=lv_display_enable_invalidation) +enable_invalidation|bool||[lv_display_enable_invalidation](https://docs.lvgl.io/9.0/search.html?q=lv_display_enable_invalidation) +get_angle||int|[lv_display_get_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_rotation) +get_antialiasing||bool|[lv_display_get_antialiasing](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_antialiasing) +get_antialiasing||bool|[lv_display_get_antialiasing](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_antialiasing) +get_color_format||int|[lv_display_get_color_format](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_color_format) +get_dpi||int|[lv_display_get_dpi](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_dpi) +get_dpi||int|[lv_display_get_dpi](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_dpi) +get_driver_data||comptr|[lv_display_get_driver_data](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_driver_data) +get_event_count||int|[lv_display_get_event_count](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_event_count) +get_hor_res||int|[lv_display_get_horizontal_resolution](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_horizontal_resolution) +get_horizontal_resolution||int|[lv_display_get_horizontal_resolution](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_horizontal_resolution) +get_inactive_time||int|[lv_display_get_inactive_time](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_inactive_time) +get_inactive_time||int|[lv_display_get_inactive_time](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_inactive_time) +get_layer_bottom||lv.obj|[lv_display_get_layer_bottom](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_layer_bottom) +get_layer_sys||lv.obj|[lv_display_get_layer_sys](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_layer_sys) +get_layer_sys||lv.obj|[lv_display_get_layer_sys](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_layer_sys) +get_layer_top||lv.obj|[lv_display_get_layer_top](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_layer_top) +get_layer_top||lv.obj|[lv_display_get_layer_top](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_layer_top) +get_next||lv.display|[lv_display_get_next](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_next) +get_next||lv.display|[lv_display_get_next](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_next) +get_offset_x||int|[lv_display_get_offset_x](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_offset_x) +get_offset_x||int|[lv_display_get_offset_x](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_offset_x) +get_offset_y||int|[lv_display_get_offset_y](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_offset_y) +get_offset_y||int|[lv_display_get_offset_y](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_offset_y) +get_physical_hor_res||int|[lv_display_get_physical_horizontal_resolution](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_physical_horizontal_resolution) +get_physical_horizontal_resolution||int|[lv_display_get_physical_horizontal_resolution](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_physical_horizontal_resolution) +get_physical_ver_res||int|[lv_display_get_physical_vertical_resolution](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_physical_vertical_resolution) +get_physical_vertical_resolution||int|[lv_display_get_physical_vertical_resolution](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_physical_vertical_resolution) +get_refr_timer||lv.timer|[lv_display_get_refr_timer](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_refr_timer) +get_rotation||int|[lv_display_get_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_rotation) +get_rotation||int|[lv_display_get_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_rotation) +get_scr_act||lv.obj|[lv_display_get_screen_active](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_screen_active) +get_scr_prev||lv.obj|[lv_display_get_screen_prev](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_screen_prev) +get_screen_active||lv.obj|[lv_display_get_screen_active](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_screen_active) +get_screen_prev||lv.obj|[lv_display_get_screen_prev](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_screen_prev) +get_theme||lv.theme|[lv_display_get_theme](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_theme) +get_theme||lv.theme|[lv_display_get_theme](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_theme) +get_user_data||comptr|[lv_display_get_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_user_data) +get_ver_res||int|[lv_display_get_vertical_resolution](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_vertical_resolution) +get_vertical_resolution||int|[lv_display_get_vertical_resolution](https://docs.lvgl.io/9.0/search.html?q=lv_display_get_vertical_resolution) +is_double_buffered||bool|[lv_display_is_double_buffered](https://docs.lvgl.io/9.0/search.html?q=lv_display_is_double_buffered) +is_invalidation_enabled||bool|[lv_display_is_invalidation_enabled](https://docs.lvgl.io/9.0/search.html?q=lv_display_is_invalidation_enabled) +is_invalidation_enabled||bool|[lv_display_is_invalidation_enabled](https://docs.lvgl.io/9.0/search.html?q=lv_display_is_invalidation_enabled) +remove|||[lv_display_delete](https://docs.lvgl.io/9.0/search.html?q=lv_display_delete) +remove_event_cb_with_user_data|\, \|int|[lv_display_remove_event_cb_with_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_display_remove_event_cb_with_user_data) +send_event|int, \|int|[lv_display_send_event](https://docs.lvgl.io/9.0/search.html?q=lv_display_send_event) +send_event|int, \|int|[lv_display_send_event](https://docs.lvgl.io/9.0/search.html?q=lv_display_send_event) +set_angle|int||[lv_display_set_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_rotation) +set_antialiasing|bool||[lv_display_set_antialiasing](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_antialiasing) +set_buffers|\, \, int, int||[lv_display_set_buffers](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_buffers) +set_color_format|int||[lv_display_set_color_format](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_color_format) +set_default|||[lv_display_set_default](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_default) +set_default|||[lv_display_set_default](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_default) +set_dpi|int||[lv_display_set_dpi](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_dpi) +set_driver_data|\||[lv_display_set_driver_data](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_driver_data) +set_offset|int, int||[lv_display_set_offset](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_offset) +set_physical_resolution|int, int||[lv_display_set_physical_resolution](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_physical_resolution) +set_render_mode|int||[lv_display_set_render_mode](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_render_mode) +set_resolution|int, int||[lv_display_set_resolution](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_resolution) +set_rotation|int||[lv_display_set_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_rotation) +set_rotation|int||[lv_display_set_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_rotation) +set_theme|lv.theme||[lv_display_set_theme](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_theme) +set_theme|lv.theme||[lv_display_set_theme](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_theme) +set_user_data|\||[lv_display_set_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_display_set_user_data) +trig_activity|||[lv_display_trigger_activity](https://docs.lvgl.io/9.0/search.html?q=lv_display_trigger_activity) +trigger_activity|||[lv_display_trigger_activity](https://docs.lvgl.io/9.0/search.html?q=lv_display_trigger_activity) + +### class `lv.event` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +get_code||int|[lv_event_get_code](https://docs.lvgl.io/9.0/search.html?q=lv_event_get_code) +get_cover_area||lv.area|[lv_event_get_cover_area](https://docs.lvgl.io/9.0/search.html?q=lv_event_get_cover_area) +get_current_target||comptr|[lv_event_get_current_target](https://docs.lvgl.io/9.0/search.html?q=lv_event_get_current_target) +get_current_target_obj||lv.obj|[lv_event_get_current_target_obj](https://docs.lvgl.io/9.0/search.html?q=lv_event_get_current_target_obj) +get_hit_test_info||comptr|[lv_event_get_hit_test_info](https://docs.lvgl.io/9.0/search.html?q=lv_event_get_hit_test_info) +get_indev||lv.indev|[lv_event_get_indev](https://docs.lvgl.io/9.0/search.html?q=lv_event_get_indev) +get_key||int|[lv_event_get_key](https://docs.lvgl.io/9.0/search.html?q=lv_event_get_key) +get_layer||comptr|[lv_event_get_layer](https://docs.lvgl.io/9.0/search.html?q=lv_event_get_layer) +get_old_size||lv.area|[lv_event_get_old_size](https://docs.lvgl.io/9.0/search.html?q=lv_event_get_old_size) +get_param||comptr|[lv_event_get_param](https://docs.lvgl.io/9.0/search.html?q=lv_event_get_param) +get_scroll_anim||lv.anim|[lv_event_get_scroll_anim](https://docs.lvgl.io/9.0/search.html?q=lv_event_get_scroll_anim) +get_self_size_info||comptr|[lv_event_get_self_size_info](https://docs.lvgl.io/9.0/search.html?q=lv_event_get_self_size_info) +get_target||comptr|[lv_event_get_target](https://docs.lvgl.io/9.0/search.html?q=lv_event_get_target) +get_target_obj||lv.obj|[lv_event_get_target_obj](https://docs.lvgl.io/9.0/search.html?q=lv_event_get_target_obj) +get_user_data||comptr|[lv_event_get_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_event_get_user_data) +set_cover_res|int||[lv_event_set_cover_res](https://docs.lvgl.io/9.0/search.html?q=lv_event_set_cover_res) +set_ext_draw_size|int||[lv_event_set_ext_draw_size](https://docs.lvgl.io/9.0/search.html?q=lv_event_set_ext_draw_size) +stop_bubbling|||[lv_event_stop_bubbling](https://docs.lvgl.io/9.0/search.html?q=lv_event_stop_bubbling) +stop_processing|||[lv_event_stop_processing](https://docs.lvgl.io/9.0/search.html?q=lv_event_stop_processing) + +### class `lv.group` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +add_obj|lv.obj||[lv_group_add_obj](https://docs.lvgl.io/9.0/search.html?q=lv_group_add_obj) +del|||[lv_group_delete](https://docs.lvgl.io/9.0/search.html?q=lv_group_delete) +delete|||[lv_group_delete](https://docs.lvgl.io/9.0/search.html?q=lv_group_delete) +focus_freeze|bool||[lv_group_focus_freeze](https://docs.lvgl.io/9.0/search.html?q=lv_group_focus_freeze) +focus_next|||[lv_group_focus_next](https://docs.lvgl.io/9.0/search.html?q=lv_group_focus_next) +focus_obj|||[lv_group_focus_obj](https://docs.lvgl.io/9.0/search.html?q=lv_group_focus_obj) +focus_prev|||[lv_group_focus_prev](https://docs.lvgl.io/9.0/search.html?q=lv_group_focus_prev) +get_edge_cb||callback|[lv_group_get_edge_cb](https://docs.lvgl.io/9.0/search.html?q=lv_group_get_edge_cb) +get_editing||bool|[lv_group_get_editing](https://docs.lvgl.io/9.0/search.html?q=lv_group_get_editing) +get_focus_cb||lv.group_focus_cb|[lv_group_get_focus_cb](https://docs.lvgl.io/9.0/search.html?q=lv_group_get_focus_cb) +get_focused||lv.obj|[lv_group_get_focused](https://docs.lvgl.io/9.0/search.html?q=lv_group_get_focused) +get_obj_count||int|[lv_group_get_obj_count](https://docs.lvgl.io/9.0/search.html?q=lv_group_get_obj_count) +get_wrap||bool|[lv_group_get_wrap](https://docs.lvgl.io/9.0/search.html?q=lv_group_get_wrap) +remove|||[lv_group_delete](https://docs.lvgl.io/9.0/search.html?q=lv_group_delete) +remove_all_objs|||[lv_group_remove_all_objs](https://docs.lvgl.io/9.0/search.html?q=lv_group_remove_all_objs) +remove_obj|||[lv_group_remove_obj](https://docs.lvgl.io/9.0/search.html?q=lv_group_remove_obj) +send_data|int|int|[lv_group_send_data](https://docs.lvgl.io/9.0/search.html?q=lv_group_send_data) +set_default|||[lv_group_set_default](https://docs.lvgl.io/9.0/search.html?q=lv_group_set_default) +set_default|||[lv_group_set_default](https://docs.lvgl.io/9.0/search.html?q=lv_group_set_default) +set_editing|bool||[lv_group_set_editing](https://docs.lvgl.io/9.0/search.html?q=lv_group_set_editing) +set_focus_cb|\||[lv_group_set_focus_cb](https://docs.lvgl.io/9.0/search.html?q=lv_group_set_focus_cb) +set_refocus_policy|int||[lv_group_set_refocus_policy](https://docs.lvgl.io/9.0/search.html?q=lv_group_set_refocus_policy) +set_wrap|bool||[lv_group_set_wrap](https://docs.lvgl.io/9.0/search.html?q=lv_group_set_wrap) +swap_obj|lv.obj||[lv_group_swap_obj](https://docs.lvgl.io/9.0/search.html?q=lv_group_swap_obj) + +### class `lv.indev` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +add_event_cb|\, int, \||[lv_indev_add_event_cb](https://docs.lvgl.io/9.0/search.html?q=lv_indev_add_event_cb) +del|||[lv_indev_delete](https://docs.lvgl.io/9.0/search.html?q=lv_indev_delete) +delete|||[lv_indev_delete](https://docs.lvgl.io/9.0/search.html?q=lv_indev_delete) +enable|bool||[lv_indev_enable](https://docs.lvgl.io/9.0/search.html?q=lv_indev_enable) +get_disp||lv.display|[lv_indev_get_display](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_display) +get_display||lv.display|[lv_indev_get_display](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_display) +get_driver_data||comptr|[lv_indev_get_driver_data](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_driver_data) +get_event_count||int|[lv_indev_get_event_count](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_event_count) +get_gesture_dir||int|[lv_indev_get_gesture_dir](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_gesture_dir) +get_group||lv.group|[lv_indev_get_group](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_group) +get_key||int|[lv_indev_get_key](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_key) +get_mode||int|[lv_indev_get_mode](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_mode) +get_next||lv.indev|[lv_indev_get_next](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_next) +get_next||lv.indev|[lv_indev_get_next](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_next) +get_point|comptr||[lv_indev_get_point](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_point) +get_read_timer||lv.timer|[lv_indev_get_read_timer](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_read_timer) +get_scroll_dir||int|[lv_indev_get_scroll_dir](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_scroll_dir) +get_scroll_obj||lv.obj|[lv_indev_get_scroll_obj](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_scroll_obj) +get_state||int|[lv_indev_get_state](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_state) +get_type||int|[lv_indev_get_type](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_type) +get_user_data||comptr|[lv_indev_get_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_user_data) +get_vect|comptr||[lv_indev_get_vect](https://docs.lvgl.io/9.0/search.html?q=lv_indev_get_vect) +read|||[lv_indev_read](https://docs.lvgl.io/9.0/search.html?q=lv_indev_read) +remove|||[lv_indev_delete](https://docs.lvgl.io/9.0/search.html?q=lv_indev_delete) +remove_event|int|bool|[lv_indev_remove_event](https://docs.lvgl.io/9.0/search.html?q=lv_indev_remove_event) +remove_event_cb_with_user_data|\, \|int|[lv_indev_remove_event_cb_with_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_indev_remove_event_cb_with_user_data) +reset|lv.obj||[lv_indev_reset](https://docs.lvgl.io/9.0/search.html?q=lv_indev_reset) +reset_long_press|||[lv_indev_reset_long_press](https://docs.lvgl.io/9.0/search.html?q=lv_indev_reset_long_press) +search_obj|comptr|lv.obj|[lv_indev_search_obj](https://docs.lvgl.io/9.0/search.html?q=lv_indev_search_obj) +send_event|int, \|int|[lv_indev_send_event](https://docs.lvgl.io/9.0/search.html?q=lv_indev_send_event) +send_event|int, \|int|[lv_indev_send_event](https://docs.lvgl.io/9.0/search.html?q=lv_indev_send_event) +set_button_points|lv.point_arr||[lv_indev_set_button_points](https://docs.lvgl.io/9.0/search.html?q=lv_indev_set_button_points) +set_cursor|lv.obj||[lv_indev_set_cursor](https://docs.lvgl.io/9.0/search.html?q=lv_indev_set_cursor) +set_disp|lv.display||[lv_indev_set_display](https://docs.lvgl.io/9.0/search.html?q=lv_indev_set_display) +set_display|lv.display||[lv_indev_set_display](https://docs.lvgl.io/9.0/search.html?q=lv_indev_set_display) +set_driver_data|\||[lv_indev_set_driver_data](https://docs.lvgl.io/9.0/search.html?q=lv_indev_set_driver_data) +set_group|lv.group||[lv_indev_set_group](https://docs.lvgl.io/9.0/search.html?q=lv_indev_set_group) +set_mode|int||[lv_indev_set_mode](https://docs.lvgl.io/9.0/search.html?q=lv_indev_set_mode) +set_type|int||[lv_indev_set_type](https://docs.lvgl.io/9.0/search.html?q=lv_indev_set_type) +set_user_data|\||[lv_indev_set_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_indev_set_user_data) +wait_release|||[lv_indev_wait_release](https://docs.lvgl.io/9.0/search.html?q=lv_indev_wait_release) + +### class `lv.style` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +is_const||bool|[lv_style_is_const](https://docs.lvgl.io/9.0/search.html?q=lv_style_is_const) +is_empty||bool|[lv_style_is_empty](https://docs.lvgl.io/9.0/search.html?q=lv_style_is_empty) +remove_prop|int|bool|[lv_style_remove_prop](https://docs.lvgl.io/9.0/search.html?q=lv_style_remove_prop) +reset|||[lv_style_reset](https://docs.lvgl.io/9.0/search.html?q=lv_style_reset) +set_align|int||[lv_style_set_align](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_align) +set_anim|lv.anim||[lv_style_set_anim](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_anim) +set_anim_duration|int||[lv_style_set_anim_duration](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_anim_duration) +set_anim_time|int||[lv_style_set_anim_duration](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_anim_duration) +set_arc_color|lv.color||[lv_style_set_arc_color](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_arc_color) +set_arc_image_src|\||[lv_style_set_arc_image_src](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_arc_image_src) +set_arc_opa|int||[lv_style_set_arc_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_arc_opa) +set_arc_rounded|bool||[lv_style_set_arc_rounded](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_arc_rounded) +set_arc_width|int||[lv_style_set_arc_width](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_arc_width) +set_base_dir|int||[lv_style_set_base_dir](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_base_dir) +set_bg_color|lv.color||[lv_style_set_bg_color](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_color) +set_bg_grad|lv.grad_dsc||[lv_style_set_bg_grad](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_grad) +set_bg_grad_color|lv.color||[lv_style_set_bg_grad_color](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_grad_color) +set_bg_grad_dir|int||[lv_style_set_bg_grad_dir](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_grad_dir) +set_bg_grad_opa|int||[lv_style_set_bg_grad_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_grad_opa) +set_bg_grad_stop|int||[lv_style_set_bg_grad_stop](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_grad_stop) +set_bg_image_opa|int||[lv_style_set_bg_image_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_image_opa) +set_bg_image_recolor|lv.color||[lv_style_set_bg_image_recolor](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_image_recolor) +set_bg_image_recolor_opa|int||[lv_style_set_bg_image_recolor_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_image_recolor_opa) +set_bg_image_src|\||[lv_style_set_bg_image_src](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_image_src) +set_bg_image_tiled|bool||[lv_style_set_bg_image_tiled](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_image_tiled) +set_bg_img_opa|int||[lv_style_set_bg_image_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_image_opa) +set_bg_img_recolor|lv.color||[lv_style_set_bg_image_recolor](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_image_recolor) +set_bg_img_recolor_opa|int||[lv_style_set_bg_image_recolor_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_image_recolor_opa) +set_bg_img_src|\||[lv_style_set_bg_image_src](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_image_src) +set_bg_img_tiled|bool||[lv_style_set_bg_image_tiled](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_image_tiled) +set_bg_main_opa|int||[lv_style_set_bg_main_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_main_opa) +set_bg_main_stop|int||[lv_style_set_bg_main_stop](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_main_stop) +set_bg_opa|int||[lv_style_set_bg_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_bg_opa) +set_blend_mode|int||[lv_style_set_blend_mode](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_blend_mode) +set_border_color|lv.color||[lv_style_set_border_color](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_border_color) +set_border_opa|int||[lv_style_set_border_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_border_opa) +set_border_post|bool||[lv_style_set_border_post](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_border_post) +set_border_side|int||[lv_style_set_border_side](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_border_side) +set_border_width|int||[lv_style_set_border_width](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_border_width) +set_clip_corner|bool||[lv_style_set_clip_corner](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_clip_corner) +set_color_filter_dsc|lv.color_filter_dsc||[lv_style_set_color_filter_dsc](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_color_filter_dsc) +set_color_filter_opa|int||[lv_style_set_color_filter_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_color_filter_opa) +set_flex_cross_place|int||[lv_style_set_flex_cross_place](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_flex_cross_place) +set_flex_flow|int||[lv_style_set_flex_flow](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_flex_flow) +set_flex_grow|int||[lv_style_set_flex_grow](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_flex_grow) +set_flex_main_place|int||[lv_style_set_flex_main_place](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_flex_main_place) +set_flex_track_place|int||[lv_style_set_flex_track_place](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_flex_track_place) +set_grid_cell_column_pos|int||[lv_style_set_grid_cell_column_pos](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_grid_cell_column_pos) +set_grid_cell_column_span|int||[lv_style_set_grid_cell_column_span](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_grid_cell_column_span) +set_grid_cell_row_pos|int||[lv_style_set_grid_cell_row_pos](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_grid_cell_row_pos) +set_grid_cell_row_span|int||[lv_style_set_grid_cell_row_span](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_grid_cell_row_span) +set_grid_cell_x_align|int||[lv_style_set_grid_cell_x_align](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_grid_cell_x_align) +set_grid_cell_y_align|int||[lv_style_set_grid_cell_y_align](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_grid_cell_y_align) +set_grid_column_align|int||[lv_style_set_grid_column_align](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_grid_column_align) +set_grid_column_dsc_array|lv.int_arr||[lv_style_set_grid_column_dsc_array](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_grid_column_dsc_array) +set_grid_row_align|int||[lv_style_set_grid_row_align](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_grid_row_align) +set_grid_row_dsc_array|lv.int_arr||[lv_style_set_grid_row_dsc_array](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_grid_row_dsc_array) +set_height|int||[lv_style_set_height](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_height) +set_image_opa|int||[lv_style_set_image_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_image_opa) +set_image_recolor|lv.color||[lv_style_set_image_recolor](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_image_recolor) +set_image_recolor_opa|int||[lv_style_set_image_recolor_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_image_recolor_opa) +set_img_opa|int||[lv_style_set_image_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_image_opa) +set_img_recolor|lv.color||[lv_style_set_image_recolor](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_image_recolor) +set_img_recolor_opa|int||[lv_style_set_image_recolor_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_image_recolor_opa) +set_layout|int||[lv_style_set_layout](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_layout) +set_length|int||[lv_style_set_length](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_length) +set_line_color|lv.color||[lv_style_set_line_color](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_line_color) +set_line_dash_gap|int||[lv_style_set_line_dash_gap](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_line_dash_gap) +set_line_dash_width|int||[lv_style_set_line_dash_width](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_line_dash_width) +set_line_opa|int||[lv_style_set_line_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_line_opa) +set_line_rounded|bool||[lv_style_set_line_rounded](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_line_rounded) +set_line_width|int||[lv_style_set_line_width](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_line_width) +set_margin_bottom|int||[lv_style_set_margin_bottom](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_margin_bottom) +set_margin_left|int||[lv_style_set_margin_left](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_margin_left) +set_margin_right|int||[lv_style_set_margin_right](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_margin_right) +set_margin_top|int||[lv_style_set_margin_top](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_margin_top) +set_max_height|int||[lv_style_set_max_height](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_max_height) +set_max_width|int||[lv_style_set_max_width](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_max_width) +set_min_height|int||[lv_style_set_min_height](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_min_height) +set_min_width|int||[lv_style_set_min_width](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_min_width) +set_opa|int||[lv_style_set_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_opa) +set_opa_layered|int||[lv_style_set_opa_layered](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_opa_layered) +set_outline_color|lv.color||[lv_style_set_outline_color](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_outline_color) +set_outline_opa|int||[lv_style_set_outline_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_outline_opa) +set_outline_pad|int||[lv_style_set_outline_pad](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_outline_pad) +set_outline_width|int||[lv_style_set_outline_width](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_outline_width) +set_pad_all|int||[lv_style_set_pad_all](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_pad_all) +set_pad_bottom|int||[lv_style_set_pad_bottom](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_pad_bottom) +set_pad_column|int||[lv_style_set_pad_column](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_pad_column) +set_pad_gap|int||[lv_style_set_pad_gap](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_pad_gap) +set_pad_hor|int||[lv_style_set_pad_hor](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_pad_hor) +set_pad_left|int||[lv_style_set_pad_left](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_pad_left) +set_pad_right|int||[lv_style_set_pad_right](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_pad_right) +set_pad_row|int||[lv_style_set_pad_row](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_pad_row) +set_pad_top|int||[lv_style_set_pad_top](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_pad_top) +set_pad_ver|int||[lv_style_set_pad_ver](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_pad_ver) +set_prop|int, int||[lv_style_set_prop](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_prop) +set_radius|int||[lv_style_set_radius](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_radius) +set_shadow_color|lv.color||[lv_style_set_shadow_color](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_shadow_color) +set_shadow_offset_x|int||[lv_style_set_shadow_offset_x](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_shadow_offset_x) +set_shadow_offset_y|int||[lv_style_set_shadow_offset_y](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_shadow_offset_y) +set_shadow_ofs_x|int||[lv_style_set_shadow_offset_x](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_shadow_offset_x) +set_shadow_ofs_y|int||[lv_style_set_shadow_offset_y](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_shadow_offset_y) +set_shadow_opa|int||[lv_style_set_shadow_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_shadow_opa) +set_shadow_spread|int||[lv_style_set_shadow_spread](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_shadow_spread) +set_shadow_width|int||[lv_style_set_shadow_width](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_shadow_width) +set_size|int, int||[lv_style_set_size](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_size) +set_text_align|int||[lv_style_set_text_align](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_text_align) +set_text_color|lv.color||[lv_style_set_text_color](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_text_color) +set_text_decor|int||[lv_style_set_text_decor](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_text_decor) +set_text_font|lv.font||[lv_style_set_text_font](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_text_font) +set_text_letter_space|int||[lv_style_set_text_letter_space](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_text_letter_space) +set_text_line_space|int||[lv_style_set_text_line_space](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_text_line_space) +set_text_opa|int||[lv_style_set_text_opa](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_text_opa) +set_transform_angle|int||[lv_style_set_transform_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_transform_rotation) +set_transform_height|int||[lv_style_set_transform_height](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_transform_height) +set_transform_pivot_x|int||[lv_style_set_transform_pivot_x](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_transform_pivot_x) +set_transform_pivot_y|int||[lv_style_set_transform_pivot_y](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_transform_pivot_y) +set_transform_rotation|int||[lv_style_set_transform_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_transform_rotation) +set_transform_scale|int||[lv_style_set_transform_scale](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_transform_scale) +set_transform_scale_x|int||[lv_style_set_transform_scale_x](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_transform_scale_x) +set_transform_scale_y|int||[lv_style_set_transform_scale_y](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_transform_scale_y) +set_transform_skew_x|int||[lv_style_set_transform_skew_x](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_transform_skew_x) +set_transform_skew_y|int||[lv_style_set_transform_skew_y](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_transform_skew_y) +set_transform_width|int||[lv_style_set_transform_width](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_transform_width) +set_transform_zoom|int||[lv_style_set_transform_scale](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_transform_scale) +set_transition|lv.style_transition_dsc||[lv_style_set_transition](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_transition) +set_translate_x|int||[lv_style_set_translate_x](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_translate_x) +set_translate_y|int||[lv_style_set_translate_y](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_translate_y) +set_width|int||[lv_style_set_width](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_width) +set_x|int||[lv_style_set_x](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_x) +set_y|int||[lv_style_set_y](https://docs.lvgl.io/9.0/search.html?q=lv_style_set_y) + +### class `lv.timer` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +del|||[lv_timer_delete](https://docs.lvgl.io/9.0/search.html?q=lv_timer_delete) +delete|||[lv_timer_delete](https://docs.lvgl.io/9.0/search.html?q=lv_timer_delete) +get_next||lv.timer|[lv_timer_get_next](https://docs.lvgl.io/9.0/search.html?q=lv_timer_get_next) +get_next||lv.timer|[lv_timer_get_next](https://docs.lvgl.io/9.0/search.html?q=lv_timer_get_next) +get_paused||bool|[lv_timer_get_paused](https://docs.lvgl.io/9.0/search.html?q=lv_timer_get_paused) +get_user_data||comptr|[lv_timer_get_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_timer_get_user_data) +pause|||[lv_timer_pause](https://docs.lvgl.io/9.0/search.html?q=lv_timer_pause) +ready|||[lv_timer_ready](https://docs.lvgl.io/9.0/search.html?q=lv_timer_ready) +remove|||[lv_timer_delete](https://docs.lvgl.io/9.0/search.html?q=lv_timer_delete) +reset|||[lv_timer_reset](https://docs.lvgl.io/9.0/search.html?q=lv_timer_reset) +resume|||[lv_timer_resume](https://docs.lvgl.io/9.0/search.html?q=lv_timer_resume) +set_auto_delete|bool||[lv_timer_set_auto_delete](https://docs.lvgl.io/9.0/search.html?q=lv_timer_set_auto_delete) +set_cb|\||[lv_timer_set_cb](https://docs.lvgl.io/9.0/search.html?q=lv_timer_set_cb) +set_period|int||[lv_timer_set_period](https://docs.lvgl.io/9.0/search.html?q=lv_timer_set_period) +set_repeat_count|int||[lv_timer_set_repeat_count](https://docs.lvgl.io/9.0/search.html?q=lv_timer_set_repeat_count) +set_user_data|\||[lv_timer_set_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_timer_set_user_data) + +## Widgets + +### widget `lv.obj` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +add_event_cb|\, int, \||[lv_obj_add_event_cb](https://docs.lvgl.io/9.0/search.html?q=lv_obj_add_event_cb) +add_flag|int||[lv_obj_add_flag](https://docs.lvgl.io/9.0/search.html?q=lv_obj_add_flag) +add_state|int||[lv_obj_add_state](https://docs.lvgl.io/9.0/search.html?q=lv_obj_add_state) +add_style|lv.style, int||[lv_obj_add_style](https://docs.lvgl.io/9.0/search.html?q=lv_obj_add_style) +align|int, int, int||[lv_obj_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_align) +align_to|lv.obj, int, int, int||[lv_obj_align_to](https://docs.lvgl.io/9.0/search.html?q=lv_obj_align_to) +allocate_spec_attr|||[lv_obj_allocate_spec_attr](https://docs.lvgl.io/9.0/search.html?q=lv_obj_allocate_spec_attr) +area_is_visible|lv.area|bool|[lv_obj_area_is_visible](https://docs.lvgl.io/9.0/search.html?q=lv_obj_area_is_visible) +calculate_ext_draw_size|int|int|[lv_obj_calculate_ext_draw_size](https://docs.lvgl.io/9.0/search.html?q=lv_obj_calculate_ext_draw_size) +calculate_style_text_align|int, string|int|[lv_obj_calculate_style_text_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_calculate_style_text_align) +center|||[lv_obj_center](https://docs.lvgl.io/9.0/search.html?q=lv_obj_center) +check_type|lv.obj_class|bool|[lv_obj_check_type](https://docs.lvgl.io/9.0/search.html?q=lv_obj_check_type) +class_init_obj|||[lv_obj_class_init_obj](https://docs.lvgl.io/9.0/search.html?q=lv_obj_class_init_obj) +clean|||[lv_obj_clean](https://docs.lvgl.io/9.0/search.html?q=lv_obj_clean) +clear_flag|int||[lv_obj_remove_flag](https://docs.lvgl.io/9.0/search.html?q=lv_obj_remove_flag) +clear_state|int||[lv_obj_remove_state](https://docs.lvgl.io/9.0/search.html?q=lv_obj_remove_state) +del|||[lv_obj_delete](https://docs.lvgl.io/9.0/search.html?q=lv_obj_delete) +del_async|||[lv_obj_delete_async](https://docs.lvgl.io/9.0/search.html?q=lv_obj_delete_async) +delete|||[lv_obj_delete](https://docs.lvgl.io/9.0/search.html?q=lv_obj_delete) +delete_async|||[lv_obj_delete_async](https://docs.lvgl.io/9.0/search.html?q=lv_obj_delete_async) +delete_delayed|int||[lv_obj_delete_delayed](https://docs.lvgl.io/9.0/search.html?q=lv_obj_delete_delayed) +dump_tree|||[lv_obj_dump_tree](https://docs.lvgl.io/9.0/search.html?q=lv_obj_dump_tree) +fade_in|int, int||[lv_obj_fade_in](https://docs.lvgl.io/9.0/search.html?q=lv_obj_fade_in) +fade_out|int, int||[lv_obj_fade_out](https://docs.lvgl.io/9.0/search.html?q=lv_obj_fade_out) +free_id|||[lv_obj_free_id](https://docs.lvgl.io/9.0/search.html?q=lv_obj_free_id) +get_child|int|lv.obj|[lv_obj_get_child](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_child) +get_child_by_type|int, lv.obj_class|lv.obj|[lv_obj_get_child_by_type](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_child_by_type) +get_child_cnt||int|[lv_obj_get_child_count](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_child_count) +get_child_count||int|[lv_obj_get_child_count](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_child_count) +get_child_count_by_type|lv.obj_class|int|[lv_obj_get_child_count_by_type](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_child_count_by_type) +get_class||lv.obj_class|[lv_obj_get_class](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_class) +get_click_area|lv.area||[lv_obj_get_click_area](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_click_area) +get_content_coords|lv.area||[lv_obj_get_content_coords](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_content_coords) +get_content_height||int|[lv_obj_get_content_height](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_content_height) +get_content_width||int|[lv_obj_get_content_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_content_width) +get_coords|lv.area||[lv_obj_get_coords](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_coords) +get_disp||lv.display|[lv_obj_get_display](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_display) +get_display||lv.display|[lv_obj_get_display](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_display) +get_event_count||int|[lv_obj_get_event_count](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_event_count) +get_group||lv.group|[lv_obj_get_group](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_group) +get_height||int|[lv_obj_get_height](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_height) +get_index||int|[lv_obj_get_index](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_index) +get_index_by_type|lv.obj_class|int|[lv_obj_get_index_by_type](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_index_by_type) +get_parent||lv.obj|[lv_obj_get_parent](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_parent) +get_screen||lv.obj|[lv_obj_get_screen](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_screen) +get_scroll_bottom||int|[lv_obj_get_scroll_bottom](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_scroll_bottom) +get_scroll_dir||int|[lv_obj_get_scroll_dir](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_scroll_dir) +get_scroll_end|comptr||[lv_obj_get_scroll_end](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_scroll_end) +get_scroll_left||int|[lv_obj_get_scroll_left](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_scroll_left) +get_scroll_right||int|[lv_obj_get_scroll_right](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_scroll_right) +get_scroll_snap_x||int|[lv_obj_get_scroll_snap_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_scroll_snap_x) +get_scroll_snap_y||int|[lv_obj_get_scroll_snap_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_scroll_snap_y) +get_scroll_top||int|[lv_obj_get_scroll_top](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_scroll_top) +get_scroll_x||int|[lv_obj_get_scroll_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_scroll_x) +get_scroll_y||int|[lv_obj_get_scroll_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_scroll_y) +get_scrollbar_area|lv.area, lv.area||[lv_obj_get_scrollbar_area](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_scrollbar_area) +get_scrollbar_mode||int|[lv_obj_get_scrollbar_mode](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_scrollbar_mode) +get_self_height||int|[lv_obj_get_self_height](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_self_height) +get_self_width||int|[lv_obj_get_self_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_self_width) +get_sibling|int|lv.obj|[lv_obj_get_sibling](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_sibling) +get_sibling_by_type|int, lv.obj_class|lv.obj|[lv_obj_get_sibling_by_type](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_sibling_by_type) +get_state||int|[lv_obj_get_state](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_state) +get_style_align|int|int|[lv_obj_get_style_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_align) +get_style_anim|int|lv.anim|[lv_obj_get_style_anim](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_anim) +get_style_anim_duration|int|int|[lv_obj_get_style_anim_duration](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_anim_duration) +get_style_anim_time|int|int|[lv_obj_get_style_anim_duration](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_anim_duration) +get_style_arc_color|int|lv.color|[lv_obj_get_style_arc_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_arc_color) +get_style_arc_color_filtered|int|lv.color|[lv_obj_get_style_arc_color_filtered](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_arc_color_filtered) +get_style_arc_image_src|int|comptr|[lv_obj_get_style_arc_image_src](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_arc_image_src) +get_style_arc_opa|int|int|[lv_obj_get_style_arc_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_arc_opa) +get_style_arc_rounded|int|bool|[lv_obj_get_style_arc_rounded](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_arc_rounded) +get_style_arc_width|int|int|[lv_obj_get_style_arc_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_arc_width) +get_style_base_dir|int|int|[lv_obj_get_style_base_dir](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_base_dir) +get_style_bg_color|int|lv.color|[lv_obj_get_style_bg_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_color) +get_style_bg_color_filtered|int|lv.color|[lv_obj_get_style_bg_color_filtered](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_color_filtered) +get_style_bg_grad|int|lv.grad_dsc|[lv_obj_get_style_bg_grad](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_grad) +get_style_bg_grad_color|int|lv.color|[lv_obj_get_style_bg_grad_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_grad_color) +get_style_bg_grad_color_filtered|int|lv.color|[lv_obj_get_style_bg_grad_color_filtered](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_grad_color_filtered) +get_style_bg_grad_dir|int|int|[lv_obj_get_style_bg_grad_dir](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_grad_dir) +get_style_bg_grad_opa|int|int|[lv_obj_get_style_bg_grad_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_grad_opa) +get_style_bg_grad_stop|int|int|[lv_obj_get_style_bg_grad_stop](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_grad_stop) +get_style_bg_image_opa|int|int|[lv_obj_get_style_bg_image_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_image_opa) +get_style_bg_image_recolor|int|lv.color|[lv_obj_get_style_bg_image_recolor](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_image_recolor) +get_style_bg_image_recolor_filtered|int|lv.color|[lv_obj_get_style_bg_image_recolor_filtered](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_image_recolor_filtered) +get_style_bg_image_recolor_opa|int|int|[lv_obj_get_style_bg_image_recolor_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_image_recolor_opa) +get_style_bg_image_src|int|comptr|[lv_obj_get_style_bg_image_src](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_image_src) +get_style_bg_image_tiled|int|bool|[lv_obj_get_style_bg_image_tiled](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_image_tiled) +get_style_bg_main_opa|int|int|[lv_obj_get_style_bg_main_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_main_opa) +get_style_bg_main_stop|int|int|[lv_obj_get_style_bg_main_stop](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_main_stop) +get_style_bg_opa|int|int|[lv_obj_get_style_bg_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_bg_opa) +get_style_blend_mode|int|int|[lv_obj_get_style_blend_mode](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_blend_mode) +get_style_border_color|int|lv.color|[lv_obj_get_style_border_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_border_color) +get_style_border_color_filtered|int|lv.color|[lv_obj_get_style_border_color_filtered](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_border_color_filtered) +get_style_border_opa|int|int|[lv_obj_get_style_border_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_border_opa) +get_style_border_post|int|bool|[lv_obj_get_style_border_post](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_border_post) +get_style_border_side|int|int|[lv_obj_get_style_border_side](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_border_side) +get_style_border_width|int|int|[lv_obj_get_style_border_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_border_width) +get_style_clip_corner|int|bool|[lv_obj_get_style_clip_corner](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_clip_corner) +get_style_color_filter_dsc|int|lv.color_filter_dsc|[lv_obj_get_style_color_filter_dsc](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_color_filter_dsc) +get_style_color_filter_opa|int|int|[lv_obj_get_style_color_filter_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_color_filter_opa) +get_style_flex_cross_place|int|int|[lv_obj_get_style_flex_cross_place](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_flex_cross_place) +get_style_flex_flow|int|int|[lv_obj_get_style_flex_flow](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_flex_flow) +get_style_flex_grow|int|int|[lv_obj_get_style_flex_grow](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_flex_grow) +get_style_flex_main_place|int|int|[lv_obj_get_style_flex_main_place](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_flex_main_place) +get_style_flex_track_place|int|int|[lv_obj_get_style_flex_track_place](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_flex_track_place) +get_style_grid_cell_column_pos|int|int|[lv_obj_get_style_grid_cell_column_pos](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_grid_cell_column_pos) +get_style_grid_cell_column_span|int|int|[lv_obj_get_style_grid_cell_column_span](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_grid_cell_column_span) +get_style_grid_cell_row_pos|int|int|[lv_obj_get_style_grid_cell_row_pos](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_grid_cell_row_pos) +get_style_grid_cell_row_span|int|int|[lv_obj_get_style_grid_cell_row_span](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_grid_cell_row_span) +get_style_grid_cell_x_align|int|int|[lv_obj_get_style_grid_cell_x_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_grid_cell_x_align) +get_style_grid_cell_y_align|int|int|[lv_obj_get_style_grid_cell_y_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_grid_cell_y_align) +get_style_grid_column_align|int|int|[lv_obj_get_style_grid_column_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_grid_column_align) +get_style_grid_column_dsc_array|int|lv.int_arr|[lv_obj_get_style_grid_column_dsc_array](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_grid_column_dsc_array) +get_style_grid_row_align|int|int|[lv_obj_get_style_grid_row_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_grid_row_align) +get_style_grid_row_dsc_array|int|lv.int_arr|[lv_obj_get_style_grid_row_dsc_array](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_grid_row_dsc_array) +get_style_height|int|int|[lv_obj_get_style_height](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_height) +get_style_image_opa|int|int|[lv_obj_get_style_image_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_image_opa) +get_style_image_recolor|int|lv.color|[lv_obj_get_style_image_recolor](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_image_recolor) +get_style_image_recolor_filtered|int|lv.color|[lv_obj_get_style_image_recolor_filtered](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_image_recolor_filtered) +get_style_image_recolor_opa|int|int|[lv_obj_get_style_image_recolor_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_image_recolor_opa) +get_style_img_opa|int|int|[lv_obj_get_style_image_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_image_opa) +get_style_img_recolor|int|lv.color|[lv_obj_get_style_image_recolor](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_image_recolor) +get_style_img_recolor_filtered|int|lv.color|[lv_obj_get_style_image_recolor_filtered](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_image_recolor_filtered) +get_style_img_recolor_opa|int|int|[lv_obj_get_style_image_recolor_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_image_recolor_opa) +get_style_layout|int|int|[lv_obj_get_style_layout](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_layout) +get_style_length|int|int|[lv_obj_get_style_length](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_length) +get_style_line_color|int|lv.color|[lv_obj_get_style_line_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_line_color) +get_style_line_color_filtered|int|lv.color|[lv_obj_get_style_line_color_filtered](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_line_color_filtered) +get_style_line_dash_gap|int|int|[lv_obj_get_style_line_dash_gap](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_line_dash_gap) +get_style_line_dash_width|int|int|[lv_obj_get_style_line_dash_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_line_dash_width) +get_style_line_opa|int|int|[lv_obj_get_style_line_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_line_opa) +get_style_line_rounded|int|bool|[lv_obj_get_style_line_rounded](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_line_rounded) +get_style_line_width|int|int|[lv_obj_get_style_line_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_line_width) +get_style_margin_bottom|int|int|[lv_obj_get_style_margin_bottom](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_margin_bottom) +get_style_margin_left|int|int|[lv_obj_get_style_margin_left](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_margin_left) +get_style_margin_right|int|int|[lv_obj_get_style_margin_right](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_margin_right) +get_style_margin_top|int|int|[lv_obj_get_style_margin_top](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_margin_top) +get_style_max_height|int|int|[lv_obj_get_style_max_height](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_max_height) +get_style_max_width|int|int|[lv_obj_get_style_max_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_max_width) +get_style_min_height|int|int|[lv_obj_get_style_min_height](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_min_height) +get_style_min_width|int|int|[lv_obj_get_style_min_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_min_width) +get_style_opa|int|int|[lv_obj_get_style_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_opa) +get_style_opa_layered|int|int|[lv_obj_get_style_opa_layered](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_opa_layered) +get_style_opa_recursive|int|int|[lv_obj_get_style_opa_recursive](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_opa_recursive) +get_style_outline_color|int|lv.color|[lv_obj_get_style_outline_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_outline_color) +get_style_outline_color_filtered|int|lv.color|[lv_obj_get_style_outline_color_filtered](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_outline_color_filtered) +get_style_outline_opa|int|int|[lv_obj_get_style_outline_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_outline_opa) +get_style_outline_pad|int|int|[lv_obj_get_style_outline_pad](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_outline_pad) +get_style_outline_width|int|int|[lv_obj_get_style_outline_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_outline_width) +get_style_pad_bottom|int|int|[lv_obj_get_style_pad_bottom](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_pad_bottom) +get_style_pad_column|int|int|[lv_obj_get_style_pad_column](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_pad_column) +get_style_pad_left|int|int|[lv_obj_get_style_pad_left](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_pad_left) +get_style_pad_right|int|int|[lv_obj_get_style_pad_right](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_pad_right) +get_style_pad_row|int|int|[lv_obj_get_style_pad_row](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_pad_row) +get_style_pad_top|int|int|[lv_obj_get_style_pad_top](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_pad_top) +get_style_prop|int, int|int|[lv_obj_get_style_prop](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_prop) +get_style_radius|int|int|[lv_obj_get_style_radius](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_radius) +get_style_shadow_color|int|lv.color|[lv_obj_get_style_shadow_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_shadow_color) +get_style_shadow_color_filtered|int|lv.color|[lv_obj_get_style_shadow_color_filtered](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_shadow_color_filtered) +get_style_shadow_offset_x|int|int|[lv_obj_get_style_shadow_offset_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_shadow_offset_x) +get_style_shadow_offset_y|int|int|[lv_obj_get_style_shadow_offset_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_shadow_offset_y) +get_style_shadow_ofs_x|int|int|[lv_obj_get_style_shadow_offset_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_shadow_offset_x) +get_style_shadow_ofs_y|int|int|[lv_obj_get_style_shadow_offset_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_shadow_offset_y) +get_style_shadow_opa|int|int|[lv_obj_get_style_shadow_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_shadow_opa) +get_style_shadow_spread|int|int|[lv_obj_get_style_shadow_spread](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_shadow_spread) +get_style_shadow_width|int|int|[lv_obj_get_style_shadow_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_shadow_width) +get_style_space_bottom|int|int|[lv_obj_get_style_space_bottom](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_space_bottom) +get_style_space_left|int|int|[lv_obj_get_style_space_left](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_space_left) +get_style_space_right|int|int|[lv_obj_get_style_space_right](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_space_right) +get_style_space_top|int|int|[lv_obj_get_style_space_top](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_space_top) +get_style_text_align|int|int|[lv_obj_get_style_text_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_text_align) +get_style_text_color|int|lv.color|[lv_obj_get_style_text_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_text_color) +get_style_text_color_filtered|int|lv.color|[lv_obj_get_style_text_color_filtered](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_text_color_filtered) +get_style_text_decor|int|int|[lv_obj_get_style_text_decor](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_text_decor) +get_style_text_font|int|lv.font|[lv_obj_get_style_text_font](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_text_font) +get_style_text_letter_space|int|int|[lv_obj_get_style_text_letter_space](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_text_letter_space) +get_style_text_line_space|int|int|[lv_obj_get_style_text_line_space](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_text_line_space) +get_style_text_opa|int|int|[lv_obj_get_style_text_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_text_opa) +get_style_transform_angle|int|int|[lv_obj_get_style_transform_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_transform_rotation) +get_style_transform_height|int|int|[lv_obj_get_style_transform_height](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_transform_height) +get_style_transform_pivot_x|int|int|[lv_obj_get_style_transform_pivot_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_transform_pivot_x) +get_style_transform_pivot_y|int|int|[lv_obj_get_style_transform_pivot_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_transform_pivot_y) +get_style_transform_rotation|int|int|[lv_obj_get_style_transform_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_transform_rotation) +get_style_transform_scale_x|int|int|[lv_obj_get_style_transform_scale_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_transform_scale_x) +get_style_transform_scale_x_safe|int|int|[lv_obj_get_style_transform_scale_x_safe](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_transform_scale_x_safe) +get_style_transform_scale_y|int|int|[lv_obj_get_style_transform_scale_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_transform_scale_y) +get_style_transform_scale_y_safe|int|int|[lv_obj_get_style_transform_scale_y_safe](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_transform_scale_y_safe) +get_style_transform_skew_x|int|int|[lv_obj_get_style_transform_skew_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_transform_skew_x) +get_style_transform_skew_y|int|int|[lv_obj_get_style_transform_skew_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_transform_skew_y) +get_style_transform_width|int|int|[lv_obj_get_style_transform_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_transform_width) +get_style_transition|int|lv.style_transition_dsc|[lv_obj_get_style_transition](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_transition) +get_style_translate_x|int|int|[lv_obj_get_style_translate_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_translate_x) +get_style_translate_y|int|int|[lv_obj_get_style_translate_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_translate_y) +get_style_width|int|int|[lv_obj_get_style_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_width) +get_style_x|int|int|[lv_obj_get_style_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_x) +get_style_y|int|int|[lv_obj_get_style_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_style_y) +get_transformed_area|lv.area, bool, bool||[lv_obj_get_transformed_area](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_transformed_area) +get_user_data||comptr|[lv_obj_get_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_user_data) +get_width||int|[lv_obj_get_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_width) +get_width||int|[lv_obj_get_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_width) +get_x||int|[lv_obj_get_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_x) +get_x2||int|[lv_obj_get_x2](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_x2) +get_x_aligned||int|[lv_obj_get_x_aligned](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_x_aligned) +get_y||int|[lv_obj_get_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_y) +get_y2||int|[lv_obj_get_y2](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_y2) +get_y_aligned||int|[lv_obj_get_y_aligned](https://docs.lvgl.io/9.0/search.html?q=lv_obj_get_y_aligned) +has_class|lv.obj_class|bool|[lv_obj_has_class](https://docs.lvgl.io/9.0/search.html?q=lv_obj_has_class) +has_flag|int|bool|[lv_obj_has_flag](https://docs.lvgl.io/9.0/search.html?q=lv_obj_has_flag) +has_flag_any|int|bool|[lv_obj_has_flag_any](https://docs.lvgl.io/9.0/search.html?q=lv_obj_has_flag_any) +has_state|int|bool|[lv_obj_has_state](https://docs.lvgl.io/9.0/search.html?q=lv_obj_has_state) +has_style_prop|int, int|bool|[lv_obj_has_style_prop](https://docs.lvgl.io/9.0/search.html?q=lv_obj_has_style_prop) +hit_test|comptr|bool|[lv_obj_hit_test](https://docs.lvgl.io/9.0/search.html?q=lv_obj_hit_test) +init_draw_arc_dsc|int, lv.draw_arc_dsc||[lv_obj_init_draw_arc_dsc](https://docs.lvgl.io/9.0/search.html?q=lv_obj_init_draw_arc_dsc) +init_draw_image_dsc|int, lv.draw_image_dsc||[lv_obj_init_draw_image_dsc](https://docs.lvgl.io/9.0/search.html?q=lv_obj_init_draw_image_dsc) +init_draw_label_dsc|int, lv.draw_label_dsc||[lv_obj_init_draw_label_dsc](https://docs.lvgl.io/9.0/search.html?q=lv_obj_init_draw_label_dsc) +init_draw_line_dsc|int, lv.draw_line_dsc||[lv_obj_init_draw_line_dsc](https://docs.lvgl.io/9.0/search.html?q=lv_obj_init_draw_line_dsc) +init_draw_rect_dsc|int, lv.draw_rect_dsc||[lv_obj_init_draw_rect_dsc](https://docs.lvgl.io/9.0/search.html?q=lv_obj_init_draw_rect_dsc) +invalidate|||[lv_obj_invalidate](https://docs.lvgl.io/9.0/search.html?q=lv_obj_invalidate) +invalidate_area|lv.area||[lv_obj_invalidate_area](https://docs.lvgl.io/9.0/search.html?q=lv_obj_invalidate_area) +is_editable||bool|[lv_obj_is_editable](https://docs.lvgl.io/9.0/search.html?q=lv_obj_is_editable) +is_group_def||bool|[lv_obj_is_group_def](https://docs.lvgl.io/9.0/search.html?q=lv_obj_is_group_def) +is_layout_positioned||bool|[lv_obj_is_layout_positioned](https://docs.lvgl.io/9.0/search.html?q=lv_obj_is_layout_positioned) +is_scrolling||bool|[lv_obj_is_scrolling](https://docs.lvgl.io/9.0/search.html?q=lv_obj_is_scrolling) +is_valid||bool|[lv_obj_is_valid](https://docs.lvgl.io/9.0/search.html?q=lv_obj_is_valid) +is_visible||bool|[lv_obj_is_visible](https://docs.lvgl.io/9.0/search.html?q=lv_obj_is_visible) +mark_layout_as_dirty|||[lv_obj_mark_layout_as_dirty](https://docs.lvgl.io/9.0/search.html?q=lv_obj_mark_layout_as_dirty) +move_background|||[lv_obj_move_background](https://docs.lvgl.io/9.0/search.html?q=lv_obj_move_background) +move_children_by|int, int, bool||[lv_obj_move_children_by](https://docs.lvgl.io/9.0/search.html?q=lv_obj_move_children_by) +move_foreground|||[lv_obj_move_foreground](https://docs.lvgl.io/9.0/search.html?q=lv_obj_move_foreground) +move_to|int, int||[lv_obj_move_to](https://docs.lvgl.io/9.0/search.html?q=lv_obj_move_to) +move_to_index|int||[lv_obj_move_to_index](https://docs.lvgl.io/9.0/search.html?q=lv_obj_move_to_index) +readjust_scroll|int||[lv_obj_readjust_scroll](https://docs.lvgl.io/9.0/search.html?q=lv_obj_readjust_scroll) +refr_pos|||[lv_obj_refr_pos](https://docs.lvgl.io/9.0/search.html?q=lv_obj_refr_pos) +refr_size||bool|[lv_obj_refr_size](https://docs.lvgl.io/9.0/search.html?q=lv_obj_refr_size) +refresh_ext_draw_size|||[lv_obj_refresh_ext_draw_size](https://docs.lvgl.io/9.0/search.html?q=lv_obj_refresh_ext_draw_size) +refresh_self_size||bool|[lv_obj_refresh_self_size](https://docs.lvgl.io/9.0/search.html?q=lv_obj_refresh_self_size) +refresh_style|int, int||[lv_obj_refresh_style](https://docs.lvgl.io/9.0/search.html?q=lv_obj_refresh_style) +remove|||[lv_obj_delete](https://docs.lvgl.io/9.0/search.html?q=lv_obj_delete) +remove_event|int|bool|[lv_obj_remove_event](https://docs.lvgl.io/9.0/search.html?q=lv_obj_remove_event) +remove_event_cb|\|bool|[lv_obj_remove_event_cb](https://docs.lvgl.io/9.0/search.html?q=lv_obj_remove_event_cb) +remove_event_cb_with_user_data|\, \|int|[lv_obj_remove_event_cb_with_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_obj_remove_event_cb_with_user_data) +remove_flag|int||[lv_obj_remove_flag](https://docs.lvgl.io/9.0/search.html?q=lv_obj_remove_flag) +remove_local_style_prop|int, int|bool|[lv_obj_remove_local_style_prop](https://docs.lvgl.io/9.0/search.html?q=lv_obj_remove_local_style_prop) +remove_state|int||[lv_obj_remove_state](https://docs.lvgl.io/9.0/search.html?q=lv_obj_remove_state) +remove_style|lv.style, int||[lv_obj_remove_style](https://docs.lvgl.io/9.0/search.html?q=lv_obj_remove_style) +remove_style_all|||[lv_obj_remove_style_all](https://docs.lvgl.io/9.0/search.html?q=lv_obj_remove_style_all) +replace_style|lv.style, lv.style, int|bool|[lv_obj_replace_style](https://docs.lvgl.io/9.0/search.html?q=lv_obj_replace_style) +scroll_by|int, int, int||[lv_obj_scroll_by](https://docs.lvgl.io/9.0/search.html?q=lv_obj_scroll_by) +scroll_by_bounded|int, int, int||[lv_obj_scroll_by_bounded](https://docs.lvgl.io/9.0/search.html?q=lv_obj_scroll_by_bounded) +scroll_to|int, int, int||[lv_obj_scroll_to](https://docs.lvgl.io/9.0/search.html?q=lv_obj_scroll_to) +scroll_to_view|int||[lv_obj_scroll_to_view](https://docs.lvgl.io/9.0/search.html?q=lv_obj_scroll_to_view) +scroll_to_view_recursive|int||[lv_obj_scroll_to_view_recursive](https://docs.lvgl.io/9.0/search.html?q=lv_obj_scroll_to_view_recursive) +scroll_to_x|int, int||[lv_obj_scroll_to_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_scroll_to_x) +scroll_to_y|int, int||[lv_obj_scroll_to_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_scroll_to_y) +scrollbar_invalidate|||[lv_obj_scrollbar_invalidate](https://docs.lvgl.io/9.0/search.html?q=lv_obj_scrollbar_invalidate) +send_event|int, \|int|[lv_obj_send_event](https://docs.lvgl.io/9.0/search.html?q=lv_obj_send_event) +send_event|int, \|int|[lv_obj_send_event](https://docs.lvgl.io/9.0/search.html?q=lv_obj_send_event) +set_align|int||[lv_obj_set_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_align) +set_content_height|int||[lv_obj_set_content_height](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_content_height) +set_content_width|int||[lv_obj_set_content_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_content_width) +set_ext_click_area|int||[lv_obj_set_ext_click_area](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_ext_click_area) +set_height|int||[lv_obj_set_height](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_height) +set_layout|int||[lv_obj_set_layout](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_layout) +set_local_style_prop|int, int, int||[lv_obj_set_local_style_prop](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_local_style_prop) +set_parent|lv.obj||[lv_obj_set_parent](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_parent) +set_pos|int, int||[lv_obj_set_pos](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_pos) +set_scroll_dir|int||[lv_obj_set_scroll_dir](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_scroll_dir) +set_scroll_snap_x|int||[lv_obj_set_scroll_snap_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_scroll_snap_x) +set_scroll_snap_y|int||[lv_obj_set_scroll_snap_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_scroll_snap_y) +set_scrollbar_mode|int||[lv_obj_set_scrollbar_mode](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_scrollbar_mode) +set_size|int, int||[lv_obj_set_size](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_size) +set_state|int, bool||[lv_obj_set_state](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_state) +set_style_align|int, int||[lv_obj_set_style_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_align) +set_style_anim|lv.anim, int||[lv_obj_set_style_anim](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_anim) +set_style_anim_duration|int, int||[lv_obj_set_style_anim_duration](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_anim_duration) +set_style_anim_time|int, int||[lv_obj_set_style_anim_duration](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_anim_duration) +set_style_arc_color|lv.color, int||[lv_obj_set_style_arc_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_arc_color) +set_style_arc_image_src|\, int||[lv_obj_set_style_arc_image_src](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_arc_image_src) +set_style_arc_opa|int, int||[lv_obj_set_style_arc_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_arc_opa) +set_style_arc_rounded|bool, int||[lv_obj_set_style_arc_rounded](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_arc_rounded) +set_style_arc_width|int, int||[lv_obj_set_style_arc_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_arc_width) +set_style_base_dir|int, int||[lv_obj_set_style_base_dir](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_base_dir) +set_style_bg_color|lv.color, int||[lv_obj_set_style_bg_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_bg_color) +set_style_bg_grad|lv.grad_dsc, int||[lv_obj_set_style_bg_grad](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_bg_grad) +set_style_bg_grad_color|lv.color, int||[lv_obj_set_style_bg_grad_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_bg_grad_color) +set_style_bg_grad_dir|int, int||[lv_obj_set_style_bg_grad_dir](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_bg_grad_dir) +set_style_bg_grad_opa|int, int||[lv_obj_set_style_bg_grad_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_bg_grad_opa) +set_style_bg_grad_stop|int, int||[lv_obj_set_style_bg_grad_stop](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_bg_grad_stop) +set_style_bg_image_opa|int, int||[lv_obj_set_style_bg_image_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_bg_image_opa) +set_style_bg_image_recolor|lv.color, int||[lv_obj_set_style_bg_image_recolor](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_bg_image_recolor) +set_style_bg_image_recolor_opa|int, int||[lv_obj_set_style_bg_image_recolor_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_bg_image_recolor_opa) +set_style_bg_image_src|\, int||[lv_obj_set_style_bg_image_src](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_bg_image_src) +set_style_bg_image_tiled|bool, int||[lv_obj_set_style_bg_image_tiled](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_bg_image_tiled) +set_style_bg_main_opa|int, int||[lv_obj_set_style_bg_main_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_bg_main_opa) +set_style_bg_main_stop|int, int||[lv_obj_set_style_bg_main_stop](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_bg_main_stop) +set_style_bg_opa|int, int||[lv_obj_set_style_bg_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_bg_opa) +set_style_blend_mode|int, int||[lv_obj_set_style_blend_mode](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_blend_mode) +set_style_border_color|lv.color, int||[lv_obj_set_style_border_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_border_color) +set_style_border_opa|int, int||[lv_obj_set_style_border_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_border_opa) +set_style_border_post|bool, int||[lv_obj_set_style_border_post](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_border_post) +set_style_border_side|int, int||[lv_obj_set_style_border_side](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_border_side) +set_style_border_width|int, int||[lv_obj_set_style_border_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_border_width) +set_style_clip_corner|bool, int||[lv_obj_set_style_clip_corner](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_clip_corner) +set_style_color_filter_dsc|lv.color_filter_dsc, int||[lv_obj_set_style_color_filter_dsc](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_color_filter_dsc) +set_style_color_filter_opa|int, int||[lv_obj_set_style_color_filter_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_color_filter_opa) +set_style_flex_cross_place|int, int||[lv_obj_set_style_flex_cross_place](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_flex_cross_place) +set_style_flex_flow|int, int||[lv_obj_set_style_flex_flow](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_flex_flow) +set_style_flex_grow|int, int||[lv_obj_set_style_flex_grow](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_flex_grow) +set_style_flex_main_place|int, int||[lv_obj_set_style_flex_main_place](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_flex_main_place) +set_style_flex_track_place|int, int||[lv_obj_set_style_flex_track_place](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_flex_track_place) +set_style_grid_cell_column_pos|int, int||[lv_obj_set_style_grid_cell_column_pos](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_grid_cell_column_pos) +set_style_grid_cell_column_span|int, int||[lv_obj_set_style_grid_cell_column_span](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_grid_cell_column_span) +set_style_grid_cell_row_pos|int, int||[lv_obj_set_style_grid_cell_row_pos](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_grid_cell_row_pos) +set_style_grid_cell_row_span|int, int||[lv_obj_set_style_grid_cell_row_span](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_grid_cell_row_span) +set_style_grid_cell_x_align|int, int||[lv_obj_set_style_grid_cell_x_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_grid_cell_x_align) +set_style_grid_cell_y_align|int, int||[lv_obj_set_style_grid_cell_y_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_grid_cell_y_align) +set_style_grid_column_align|int, int||[lv_obj_set_style_grid_column_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_grid_column_align) +set_style_grid_column_dsc_array|lv.int_arr, int||[lv_obj_set_style_grid_column_dsc_array](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_grid_column_dsc_array) +set_style_grid_row_align|int, int||[lv_obj_set_style_grid_row_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_grid_row_align) +set_style_grid_row_dsc_array|lv.int_arr, int||[lv_obj_set_style_grid_row_dsc_array](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_grid_row_dsc_array) +set_style_height|int, int||[lv_obj_set_style_height](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_height) +set_style_image_opa|int, int||[lv_obj_set_style_image_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_image_opa) +set_style_image_recolor|lv.color, int||[lv_obj_set_style_image_recolor](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_image_recolor) +set_style_image_recolor_opa|int, int||[lv_obj_set_style_image_recolor_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_image_recolor_opa) +set_style_img_opa|int, int||[lv_obj_set_style_image_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_image_opa) +set_style_img_recolor|lv.color, int||[lv_obj_set_style_image_recolor](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_image_recolor) +set_style_img_recolor_opa|int, int||[lv_obj_set_style_image_recolor_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_image_recolor_opa) +set_style_layout|int, int||[lv_obj_set_style_layout](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_layout) +set_style_length|int, int||[lv_obj_set_style_length](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_length) +set_style_line_color|lv.color, int||[lv_obj_set_style_line_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_line_color) +set_style_line_dash_gap|int, int||[lv_obj_set_style_line_dash_gap](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_line_dash_gap) +set_style_line_dash_width|int, int||[lv_obj_set_style_line_dash_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_line_dash_width) +set_style_line_opa|int, int||[lv_obj_set_style_line_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_line_opa) +set_style_line_rounded|bool, int||[lv_obj_set_style_line_rounded](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_line_rounded) +set_style_line_width|int, int||[lv_obj_set_style_line_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_line_width) +set_style_margin_all|int, int||[lv_obj_set_style_margin_all](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_margin_all) +set_style_margin_bottom|int, int||[lv_obj_set_style_margin_bottom](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_margin_bottom) +set_style_margin_hor|int, int||[lv_obj_set_style_margin_hor](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_margin_hor) +set_style_margin_left|int, int||[lv_obj_set_style_margin_left](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_margin_left) +set_style_margin_right|int, int||[lv_obj_set_style_margin_right](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_margin_right) +set_style_margin_top|int, int||[lv_obj_set_style_margin_top](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_margin_top) +set_style_margin_ver|int, int||[lv_obj_set_style_margin_ver](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_margin_ver) +set_style_max_height|int, int||[lv_obj_set_style_max_height](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_max_height) +set_style_max_width|int, int||[lv_obj_set_style_max_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_max_width) +set_style_min_height|int, int||[lv_obj_set_style_min_height](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_min_height) +set_style_min_width|int, int||[lv_obj_set_style_min_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_min_width) +set_style_opa|int, int||[lv_obj_set_style_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_opa) +set_style_opa_layered|int, int||[lv_obj_set_style_opa_layered](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_opa_layered) +set_style_outline_color|lv.color, int||[lv_obj_set_style_outline_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_outline_color) +set_style_outline_opa|int, int||[lv_obj_set_style_outline_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_outline_opa) +set_style_outline_pad|int, int||[lv_obj_set_style_outline_pad](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_outline_pad) +set_style_outline_width|int, int||[lv_obj_set_style_outline_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_outline_width) +set_style_pad_all|int, int||[lv_obj_set_style_pad_all](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_pad_all) +set_style_pad_bottom|int, int||[lv_obj_set_style_pad_bottom](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_pad_bottom) +set_style_pad_column|int, int||[lv_obj_set_style_pad_column](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_pad_column) +set_style_pad_gap|int, int||[lv_obj_set_style_pad_gap](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_pad_gap) +set_style_pad_hor|int, int||[lv_obj_set_style_pad_hor](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_pad_hor) +set_style_pad_left|int, int||[lv_obj_set_style_pad_left](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_pad_left) +set_style_pad_right|int, int||[lv_obj_set_style_pad_right](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_pad_right) +set_style_pad_row|int, int||[lv_obj_set_style_pad_row](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_pad_row) +set_style_pad_top|int, int||[lv_obj_set_style_pad_top](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_pad_top) +set_style_pad_ver|int, int||[lv_obj_set_style_pad_ver](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_pad_ver) +set_style_radius|int, int||[lv_obj_set_style_radius](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_radius) +set_style_shadow_color|lv.color, int||[lv_obj_set_style_shadow_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_shadow_color) +set_style_shadow_offset_x|int, int||[lv_obj_set_style_shadow_offset_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_shadow_offset_x) +set_style_shadow_offset_y|int, int||[lv_obj_set_style_shadow_offset_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_shadow_offset_y) +set_style_shadow_ofs_x|int, int||[lv_obj_set_style_shadow_offset_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_shadow_offset_x) +set_style_shadow_ofs_y|int, int||[lv_obj_set_style_shadow_offset_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_shadow_offset_y) +set_style_shadow_opa|int, int||[lv_obj_set_style_shadow_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_shadow_opa) +set_style_shadow_spread|int, int||[lv_obj_set_style_shadow_spread](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_shadow_spread) +set_style_shadow_width|int, int||[lv_obj_set_style_shadow_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_shadow_width) +set_style_size|int, int, int||[lv_obj_set_style_size](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_size) +set_style_text_align|int, int||[lv_obj_set_style_text_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_text_align) +set_style_text_color|lv.color, int||[lv_obj_set_style_text_color](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_text_color) +set_style_text_decor|int, int||[lv_obj_set_style_text_decor](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_text_decor) +set_style_text_font|lv.font, int||[lv_obj_set_style_text_font](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_text_font) +set_style_text_letter_space|int, int||[lv_obj_set_style_text_letter_space](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_text_letter_space) +set_style_text_line_space|int, int||[lv_obj_set_style_text_line_space](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_text_line_space) +set_style_text_opa|int, int||[lv_obj_set_style_text_opa](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_text_opa) +set_style_transform_angle|int, int||[lv_obj_set_style_transform_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_transform_rotation) +set_style_transform_height|int, int||[lv_obj_set_style_transform_height](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_transform_height) +set_style_transform_pivot_x|int, int||[lv_obj_set_style_transform_pivot_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_transform_pivot_x) +set_style_transform_pivot_y|int, int||[lv_obj_set_style_transform_pivot_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_transform_pivot_y) +set_style_transform_rotation|int, int||[lv_obj_set_style_transform_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_transform_rotation) +set_style_transform_scale|int, int||[lv_obj_set_style_transform_scale](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_transform_scale) +set_style_transform_scale_x|int, int||[lv_obj_set_style_transform_scale_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_transform_scale_x) +set_style_transform_scale_y|int, int||[lv_obj_set_style_transform_scale_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_transform_scale_y) +set_style_transform_skew_x|int, int||[lv_obj_set_style_transform_skew_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_transform_skew_x) +set_style_transform_skew_y|int, int||[lv_obj_set_style_transform_skew_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_transform_skew_y) +set_style_transform_width|int, int||[lv_obj_set_style_transform_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_transform_width) +set_style_transform_zoom|int, int||[lv_obj_set_style_transform_scale](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_transform_scale) +set_style_transition|lv.style_transition_dsc, int||[lv_obj_set_style_transition](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_transition) +set_style_translate_x|int, int||[lv_obj_set_style_translate_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_translate_x) +set_style_translate_y|int, int||[lv_obj_set_style_translate_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_translate_y) +set_style_width|int, int||[lv_obj_set_style_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_width) +set_style_x|int, int||[lv_obj_set_style_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_x) +set_style_y|int, int||[lv_obj_set_style_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_style_y) +set_user_data|\||[lv_obj_set_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_user_data) +set_width|int||[lv_obj_set_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_width) +set_x|int||[lv_obj_set_x](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_x) +set_y|int||[lv_obj_set_y](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_y) +stringify_id|comptr, int|string|[lv_obj_stringify_id](https://docs.lvgl.io/9.0/search.html?q=lv_obj_stringify_id) +swap|lv.obj||[lv_obj_swap](https://docs.lvgl.io/9.0/search.html?q=lv_obj_swap) +transform_point|comptr, bool, bool||[lv_obj_transform_point](https://docs.lvgl.io/9.0/search.html?q=lv_obj_transform_point) +update_flag|int, bool||[lv_obj_update_flag](https://docs.lvgl.io/9.0/search.html?q=lv_obj_update_flag) +update_layout|||[lv_obj_update_layout](https://docs.lvgl.io/9.0/search.html?q=lv_obj_update_layout) +update_snap|int||[lv_obj_update_snap](https://docs.lvgl.io/9.0/search.html?q=lv_obj_update_snap) + +### widget `lv.arc` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +align_obj_to_angle|lv.obj, int||[lv_arc_align_obj_to_angle](https://docs.lvgl.io/9.0/search.html?q=lv_arc_align_obj_to_angle) +get_angle||int|[lv_arc_get_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_arc_get_rotation) +get_angle_end||int|[lv_arc_get_angle_end](https://docs.lvgl.io/9.0/search.html?q=lv_arc_get_angle_end) +get_angle_start||int|[lv_arc_get_angle_start](https://docs.lvgl.io/9.0/search.html?q=lv_arc_get_angle_start) +get_bg_angle_end||int|[lv_arc_get_bg_angle_end](https://docs.lvgl.io/9.0/search.html?q=lv_arc_get_bg_angle_end) +get_bg_angle_start||int|[lv_arc_get_bg_angle_start](https://docs.lvgl.io/9.0/search.html?q=lv_arc_get_bg_angle_start) +get_knob_offset||int|[lv_arc_get_knob_offset](https://docs.lvgl.io/9.0/search.html?q=lv_arc_get_knob_offset) +get_max_value||int|[lv_arc_get_max_value](https://docs.lvgl.io/9.0/search.html?q=lv_arc_get_max_value) +get_min_value||int|[lv_arc_get_min_value](https://docs.lvgl.io/9.0/search.html?q=lv_arc_get_min_value) +get_mode||int|[lv_arc_get_mode](https://docs.lvgl.io/9.0/search.html?q=lv_arc_get_mode) +get_rotation||int|[lv_arc_get_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_arc_get_rotation) +get_rotation||int|[lv_arc_get_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_arc_get_rotation) +get_value||int|[lv_arc_get_value](https://docs.lvgl.io/9.0/search.html?q=lv_arc_get_value) +rotate_obj_to_angle|lv.obj, int||[lv_arc_rotate_obj_to_angle](https://docs.lvgl.io/9.0/search.html?q=lv_arc_rotate_obj_to_angle) +set_angle|int||[lv_arc_set_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_arc_set_rotation) +set_angles|int, int||[lv_arc_set_angles](https://docs.lvgl.io/9.0/search.html?q=lv_arc_set_angles) +set_bg_angles|int, int||[lv_arc_set_bg_angles](https://docs.lvgl.io/9.0/search.html?q=lv_arc_set_bg_angles) +set_bg_end_angle|int||[lv_arc_set_bg_end_angle](https://docs.lvgl.io/9.0/search.html?q=lv_arc_set_bg_end_angle) +set_bg_start_angle|int||[lv_arc_set_bg_start_angle](https://docs.lvgl.io/9.0/search.html?q=lv_arc_set_bg_start_angle) +set_change_rate|int||[lv_arc_set_change_rate](https://docs.lvgl.io/9.0/search.html?q=lv_arc_set_change_rate) +set_end_angle|int||[lv_arc_set_end_angle](https://docs.lvgl.io/9.0/search.html?q=lv_arc_set_end_angle) +set_knob_offset|int||[lv_arc_set_knob_offset](https://docs.lvgl.io/9.0/search.html?q=lv_arc_set_knob_offset) +set_mode|int||[lv_arc_set_mode](https://docs.lvgl.io/9.0/search.html?q=lv_arc_set_mode) +set_range|int, int||[lv_arc_set_range](https://docs.lvgl.io/9.0/search.html?q=lv_arc_set_range) +set_rotation|int||[lv_arc_set_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_arc_set_rotation) +set_rotation|int||[lv_arc_set_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_arc_set_rotation) +set_start_angle|int||[lv_arc_set_start_angle](https://docs.lvgl.io/9.0/search.html?q=lv_arc_set_start_angle) +set_value|int||[lv_arc_set_value](https://docs.lvgl.io/9.0/search.html?q=lv_arc_set_value) + +### widget `lv.bar` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +get_max_value||int|[lv_bar_get_max_value](https://docs.lvgl.io/9.0/search.html?q=lv_bar_get_max_value) +get_min_value||int|[lv_bar_get_min_value](https://docs.lvgl.io/9.0/search.html?q=lv_bar_get_min_value) +get_mode||int|[lv_bar_get_mode](https://docs.lvgl.io/9.0/search.html?q=lv_bar_get_mode) +get_start_value||int|[lv_bar_get_start_value](https://docs.lvgl.io/9.0/search.html?q=lv_bar_get_start_value) +get_value||int|[lv_bar_get_value](https://docs.lvgl.io/9.0/search.html?q=lv_bar_get_value) +is_symmetrical||bool|[lv_bar_is_symmetrical](https://docs.lvgl.io/9.0/search.html?q=lv_bar_is_symmetrical) +set_mode|int||[lv_bar_set_mode](https://docs.lvgl.io/9.0/search.html?q=lv_bar_set_mode) +set_range|int, int||[lv_bar_set_range](https://docs.lvgl.io/9.0/search.html?q=lv_bar_set_range) +set_start_value|int, int||[lv_bar_set_start_value](https://docs.lvgl.io/9.0/search.html?q=lv_bar_set_start_value) +set_value|int, int||[lv_bar_set_value](https://docs.lvgl.io/9.0/search.html?q=lv_bar_set_value) + +### widget `lv.button` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- + +### widget `lv.buttonmatrix` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +_btn_text|int|string|[lv_buttonmatrix_get_button_text](https://docs.lvgl.io/9.0/search.html?q=lv_buttonmatrix_get_button_text) +clear_button_ctrl|int, int||[lv_buttonmatrix_clear_button_ctrl](https://docs.lvgl.io/9.0/search.html?q=lv_buttonmatrix_clear_button_ctrl) +clear_button_ctrl_all|int||[lv_buttonmatrix_clear_button_ctrl_all](https://docs.lvgl.io/9.0/search.html?q=lv_buttonmatrix_clear_button_ctrl_all) +get_button_text|int|string|[lv_buttonmatrix_get_button_text](https://docs.lvgl.io/9.0/search.html?q=lv_buttonmatrix_get_button_text) +get_map||comptr|[lv_buttonmatrix_get_map](https://docs.lvgl.io/9.0/search.html?q=lv_buttonmatrix_get_map) +get_one_checked||bool|[lv_buttonmatrix_get_one_checked](https://docs.lvgl.io/9.0/search.html?q=lv_buttonmatrix_get_one_checked) +get_popovers||bool|[lv_buttonmatrix_get_popovers](https://docs.lvgl.io/9.0/search.html?q=lv_buttonmatrix_get_popovers) +get_selected_button||int|[lv_buttonmatrix_get_selected_button](https://docs.lvgl.io/9.0/search.html?q=lv_buttonmatrix_get_selected_button) +has_button_ctrl|int, int|bool|[lv_buttonmatrix_has_button_ctrl](https://docs.lvgl.io/9.0/search.html?q=lv_buttonmatrix_has_button_ctrl) +set_button_ctrl|int, int||[lv_buttonmatrix_set_button_ctrl](https://docs.lvgl.io/9.0/search.html?q=lv_buttonmatrix_set_button_ctrl) +set_button_ctrl_all|int||[lv_buttonmatrix_set_button_ctrl_all](https://docs.lvgl.io/9.0/search.html?q=lv_buttonmatrix_set_button_ctrl_all) +set_button_width|int, int||[lv_buttonmatrix_set_button_width](https://docs.lvgl.io/9.0/search.html?q=lv_buttonmatrix_set_button_width) +set_map|lv.str_arr||[lv_buttonmatrix_set_map](https://docs.lvgl.io/9.0/search.html?q=lv_buttonmatrix_set_map) +set_one_checked|bool||[lv_buttonmatrix_set_one_checked](https://docs.lvgl.io/9.0/search.html?q=lv_buttonmatrix_set_one_checked) +set_selected_button|int||[lv_buttonmatrix_set_selected_button](https://docs.lvgl.io/9.0/search.html?q=lv_buttonmatrix_set_selected_button) + +### widget `lv.canvas` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +fill_bg|lv.color, int||[lv_canvas_fill_bg](https://docs.lvgl.io/9.0/search.html?q=lv_canvas_fill_bg) +finish_layer|comptr||[lv_canvas_finish_layer](https://docs.lvgl.io/9.0/search.html?q=lv_canvas_finish_layer) +get_buf||comptr|[lv_canvas_get_buf](https://docs.lvgl.io/9.0/search.html?q=lv_canvas_get_buf) +get_image||lv.image_dsc|[lv_canvas_get_image](https://docs.lvgl.io/9.0/search.html?q=lv_canvas_get_image) +get_px|int, int|int|[lv_canvas_get_px](https://docs.lvgl.io/9.0/search.html?q=lv_canvas_get_px) +init_layer|comptr||[lv_canvas_init_layer](https://docs.lvgl.io/9.0/search.html?q=lv_canvas_init_layer) +set_buffer|\, int, int, int||[lv_canvas_set_buffer](https://docs.lvgl.io/9.0/search.html?q=lv_canvas_set_buffer) +set_palette|int, int||[lv_canvas_set_palette](https://docs.lvgl.io/9.0/search.html?q=lv_canvas_set_palette) +set_px|int, int, lv.color, int||[lv_canvas_set_px](https://docs.lvgl.io/9.0/search.html?q=lv_canvas_set_px) + +### widget `lv.checkbox` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +get_text||string|[lv_checkbox_get_text](https://docs.lvgl.io/9.0/search.html?q=lv_checkbox_get_text) +set_text|string||[lv_checkbox_set_text](https://docs.lvgl.io/9.0/search.html?q=lv_checkbox_set_text) +set_text_static|string||[lv_checkbox_set_text_static](https://docs.lvgl.io/9.0/search.html?q=lv_checkbox_set_text_static) + +### widget `lv.dropdown` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +add_option|string, int||[lv_dropdown_add_option](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_add_option) +clear_options|||[lv_dropdown_clear_options](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_clear_options) +close|||[lv_dropdown_close](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_close) +get_dir||int|[lv_dropdown_get_dir](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_get_dir) +get_list||lv.obj|[lv_dropdown_get_list](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_get_list) +get_option_cnt||int|[lv_dropdown_get_option_count](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_get_option_count) +get_option_count||int|[lv_dropdown_get_option_count](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_get_option_count) +get_option_index|string|int|[lv_dropdown_get_option_index](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_get_option_index) +get_options||string|[lv_dropdown_get_options](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_get_options) +get_selected||int|[lv_dropdown_get_selected](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_get_selected) +get_selected_highlight||bool|[lv_dropdown_get_selected_highlight](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_get_selected_highlight) +get_selected_str|comptr, int||[lv_dropdown_get_selected_str](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_get_selected_str) +get_symbol||string|[lv_dropdown_get_symbol](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_get_symbol) +get_text||string|[lv_dropdown_get_text](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_get_text) +is_open||bool|[lv_dropdown_is_open](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_is_open) +open|||[lv_dropdown_open](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_open) +set_dir|int||[lv_dropdown_set_dir](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_set_dir) +set_options|string||[lv_dropdown_set_options](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_set_options) +set_options_static|string||[lv_dropdown_set_options_static](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_set_options_static) +set_selected|int||[lv_dropdown_set_selected](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_set_selected) +set_selected_highlight|bool||[lv_dropdown_set_selected_highlight](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_set_selected_highlight) +set_symbol|\||[lv_dropdown_set_symbol](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_set_symbol) +set_text|string||[lv_dropdown_set_text](https://docs.lvgl.io/9.0/search.html?q=lv_dropdown_set_text) + +### widget `lv.image` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +get_angle||int|[lv_image_get_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_rotation) +get_antialias||bool|[lv_image_get_antialias](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_antialias) +get_blend_mode||int|[lv_image_get_blend_mode](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_blend_mode) +get_inner_align||int|[lv_image_get_inner_align](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_inner_align) +get_offset_x||int|[lv_image_get_offset_x](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_offset_x) +get_offset_x||int|[lv_image_get_offset_x](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_offset_x) +get_offset_y||int|[lv_image_get_offset_y](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_offset_y) +get_offset_y||int|[lv_image_get_offset_y](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_offset_y) +get_pivot|comptr||[lv_image_get_pivot](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_pivot) +get_rotation||int|[lv_image_get_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_rotation) +get_rotation||int|[lv_image_get_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_rotation) +get_scale||int|[lv_image_get_scale](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_scale) +get_scale_x||int|[lv_image_get_scale_x](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_scale_x) +get_scale_y||int|[lv_image_get_scale_y](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_scale_y) +get_src||comptr|[lv_image_get_src](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_src) +get_zoom||int|[lv_image_get_scale](https://docs.lvgl.io/9.0/search.html?q=lv_image_get_scale) +set_angle|int||[lv_image_set_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_image_set_rotation) +set_antialias|bool||[lv_image_set_antialias](https://docs.lvgl.io/9.0/search.html?q=lv_image_set_antialias) +set_blend_mode|int||[lv_image_set_blend_mode](https://docs.lvgl.io/9.0/search.html?q=lv_image_set_blend_mode) +set_inner_align|int||[lv_image_set_inner_align](https://docs.lvgl.io/9.0/search.html?q=lv_image_set_inner_align) +set_offset_x|int||[lv_image_set_offset_x](https://docs.lvgl.io/9.0/search.html?q=lv_image_set_offset_x) +set_offset_y|int||[lv_image_set_offset_y](https://docs.lvgl.io/9.0/search.html?q=lv_image_set_offset_y) +set_pivot|int, int||[lv_image_set_pivot](https://docs.lvgl.io/9.0/search.html?q=lv_image_set_pivot) +set_rotation|int||[lv_image_set_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_image_set_rotation) +set_rotation|int||[lv_image_set_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_image_set_rotation) +set_scale|int||[lv_image_set_scale](https://docs.lvgl.io/9.0/search.html?q=lv_image_set_scale) +set_scale_x|int||[lv_image_set_scale_x](https://docs.lvgl.io/9.0/search.html?q=lv_image_set_scale_x) +set_scale_y|int||[lv_image_set_scale_y](https://docs.lvgl.io/9.0/search.html?q=lv_image_set_scale_y) +set_src|\||[lv_image_set_src](https://docs.lvgl.io/9.0/search.html?q=lv_image_set_src) +set_tasmota_logo|||[lv_image_set_tasmota_logo](https://docs.lvgl.io/9.0/search.html?q=lv_image_set_tasmota_logo) +set_zoom|int||[lv_image_set_scale](https://docs.lvgl.io/9.0/search.html?q=lv_image_set_scale) + +### widget `lv.label` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +cut_text|int, int||[lv_label_cut_text](https://docs.lvgl.io/9.0/search.html?q=lv_label_cut_text) +get_letter_on|comptr, bool|int|[lv_label_get_letter_on](https://docs.lvgl.io/9.0/search.html?q=lv_label_get_letter_on) +get_letter_pos|int, comptr||[lv_label_get_letter_pos](https://docs.lvgl.io/9.0/search.html?q=lv_label_get_letter_pos) +get_long_mode||int|[lv_label_get_long_mode](https://docs.lvgl.io/9.0/search.html?q=lv_label_get_long_mode) +get_text||string|[lv_label_get_text](https://docs.lvgl.io/9.0/search.html?q=lv_label_get_text) +get_text_selection_end||int|[lv_label_get_text_selection_end](https://docs.lvgl.io/9.0/search.html?q=lv_label_get_text_selection_end) +get_text_selection_start||int|[lv_label_get_text_selection_start](https://docs.lvgl.io/9.0/search.html?q=lv_label_get_text_selection_start) +ins_text|int, string||[lv_label_ins_text](https://docs.lvgl.io/9.0/search.html?q=lv_label_ins_text) +is_char_under_pos|comptr|bool|[lv_label_is_char_under_pos](https://docs.lvgl.io/9.0/search.html?q=lv_label_is_char_under_pos) +set_long_mode|int||[lv_label_set_long_mode](https://docs.lvgl.io/9.0/search.html?q=lv_label_set_long_mode) +set_text|string||[lv_label_set_text](https://docs.lvgl.io/9.0/search.html?q=lv_label_set_text) +set_text_fmt|string, [\]||[lv_label_set_text_fmt](https://docs.lvgl.io/9.0/search.html?q=lv_label_set_text_fmt) +set_text_selection_end|int||[lv_label_set_text_selection_end](https://docs.lvgl.io/9.0/search.html?q=lv_label_set_text_selection_end) +set_text_selection_start|int||[lv_label_set_text_selection_start](https://docs.lvgl.io/9.0/search.html?q=lv_label_set_text_selection_start) +set_text_static|string||[lv_label_set_text_static](https://docs.lvgl.io/9.0/search.html?q=lv_label_set_text_static) + +### widget `lv.line` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +get_y_invert||bool|[lv_line_get_y_invert](https://docs.lvgl.io/9.0/search.html?q=lv_line_get_y_invert) +set_points|lv.point_arr, int||[lv_line_set_points](https://docs.lvgl.io/9.0/search.html?q=lv_line_set_points) +set_y_invert|bool||[lv_line_set_y_invert](https://docs.lvgl.io/9.0/search.html?q=lv_line_set_y_invert) + +### widget `lv.roller` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +get_option_cnt||int|[lv_roller_get_option_count](https://docs.lvgl.io/9.0/search.html?q=lv_roller_get_option_count) +get_option_count||int|[lv_roller_get_option_count](https://docs.lvgl.io/9.0/search.html?q=lv_roller_get_option_count) +get_options||string|[lv_roller_get_options](https://docs.lvgl.io/9.0/search.html?q=lv_roller_get_options) +get_selected||int|[lv_roller_get_selected](https://docs.lvgl.io/9.0/search.html?q=lv_roller_get_selected) +get_selected_str|comptr, int||[lv_roller_get_selected_str](https://docs.lvgl.io/9.0/search.html?q=lv_roller_get_selected_str) +set_options|string, int||[lv_roller_set_options](https://docs.lvgl.io/9.0/search.html?q=lv_roller_set_options) +set_selected|int, int||[lv_roller_set_selected](https://docs.lvgl.io/9.0/search.html?q=lv_roller_set_selected) +set_visible_row_cnt|int||[lv_roller_set_visible_row_count](https://docs.lvgl.io/9.0/search.html?q=lv_roller_set_visible_row_count) +set_visible_row_count|int||[lv_roller_set_visible_row_count](https://docs.lvgl.io/9.0/search.html?q=lv_roller_set_visible_row_count) + +### widget `lv.slider` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +get_left_value||int|[lv_slider_get_left_value](https://docs.lvgl.io/9.0/search.html?q=lv_slider_get_left_value) +get_max_value||int|[lv_slider_get_max_value](https://docs.lvgl.io/9.0/search.html?q=lv_slider_get_max_value) +get_min_value||int|[lv_slider_get_min_value](https://docs.lvgl.io/9.0/search.html?q=lv_slider_get_min_value) +get_mode||int|[lv_slider_get_mode](https://docs.lvgl.io/9.0/search.html?q=lv_slider_get_mode) +get_value||int|[lv_slider_get_value](https://docs.lvgl.io/9.0/search.html?q=lv_slider_get_value) +is_dragged||bool|[lv_slider_is_dragged](https://docs.lvgl.io/9.0/search.html?q=lv_slider_is_dragged) +is_symmetrical||bool|[lv_slider_is_symmetrical](https://docs.lvgl.io/9.0/search.html?q=lv_slider_is_symmetrical) +set_left_value|int, int||[lv_slider_set_left_value](https://docs.lvgl.io/9.0/search.html?q=lv_slider_set_left_value) +set_mode|int||[lv_slider_set_mode](https://docs.lvgl.io/9.0/search.html?q=lv_slider_set_mode) +set_range|int, int||[lv_slider_set_range](https://docs.lvgl.io/9.0/search.html?q=lv_slider_set_range) +set_value|int, int||[lv_slider_set_value](https://docs.lvgl.io/9.0/search.html?q=lv_slider_set_value) + +### widget `lv.switch` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- + +### widget `lv.table` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +add_cell_ctrl|int, int, int||[lv_table_add_cell_ctrl](https://docs.lvgl.io/9.0/search.html?q=lv_table_add_cell_ctrl) +clear_cell_ctrl|int, int, int||[lv_table_clear_cell_ctrl](https://docs.lvgl.io/9.0/search.html?q=lv_table_clear_cell_ctrl) +get_cell_user_data|int, int|comptr|[lv_table_get_cell_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_table_get_cell_user_data) +get_cell_value|int, int|string|[lv_table_get_cell_value](https://docs.lvgl.io/9.0/search.html?q=lv_table_get_cell_value) +get_col_cnt||int|[lv_table_get_column_count](https://docs.lvgl.io/9.0/search.html?q=lv_table_get_column_count) +get_col_width|int|int|[lv_table_get_column_width](https://docs.lvgl.io/9.0/search.html?q=lv_table_get_column_width) +get_column_count||int|[lv_table_get_column_count](https://docs.lvgl.io/9.0/search.html?q=lv_table_get_column_count) +get_column_width|int|int|[lv_table_get_column_width](https://docs.lvgl.io/9.0/search.html?q=lv_table_get_column_width) +get_row_cnt||int|[lv_table_get_row_count](https://docs.lvgl.io/9.0/search.html?q=lv_table_get_row_count) +get_row_count||int|[lv_table_get_row_count](https://docs.lvgl.io/9.0/search.html?q=lv_table_get_row_count) +get_selected_cell|lv.int_arr, lv.int_arr||[lv_table_get_selected_cell](https://docs.lvgl.io/9.0/search.html?q=lv_table_get_selected_cell) +has_cell_ctrl|int, int, int|bool|[lv_table_has_cell_ctrl](https://docs.lvgl.io/9.0/search.html?q=lv_table_has_cell_ctrl) +set_cell_user_data|int, int, \||[lv_table_set_cell_user_data](https://docs.lvgl.io/9.0/search.html?q=lv_table_set_cell_user_data) +set_cell_value|int, int, string||[lv_table_set_cell_value](https://docs.lvgl.io/9.0/search.html?q=lv_table_set_cell_value) +set_cell_value_fmt|int, int, string, [\]||[lv_table_set_cell_value_fmt](https://docs.lvgl.io/9.0/search.html?q=lv_table_set_cell_value_fmt) +set_col_cnt|int||[lv_table_set_column_count](https://docs.lvgl.io/9.0/search.html?q=lv_table_set_column_count) +set_col_width|int, int||[lv_table_set_column_width](https://docs.lvgl.io/9.0/search.html?q=lv_table_set_column_width) +set_column_count|int||[lv_table_set_column_count](https://docs.lvgl.io/9.0/search.html?q=lv_table_set_column_count) +set_column_width|int, int||[lv_table_set_column_width](https://docs.lvgl.io/9.0/search.html?q=lv_table_set_column_width) +set_row_cnt|int||[lv_table_set_row_count](https://docs.lvgl.io/9.0/search.html?q=lv_table_set_row_count) +set_row_count|int||[lv_table_set_row_count](https://docs.lvgl.io/9.0/search.html?q=lv_table_set_row_count) + +### widget `lv.textarea` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +add_char|int||[lv_textarea_add_char](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_add_char) +add_text|string||[lv_textarea_add_text](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_add_text) +clear_selection|||[lv_textarea_clear_selection](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_clear_selection) +cursor_down|||[lv_textarea_cursor_down](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_cursor_down) +cursor_left|||[lv_textarea_cursor_left](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_cursor_left) +cursor_right|||[lv_textarea_cursor_right](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_cursor_right) +cursor_up|||[lv_textarea_cursor_up](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_cursor_up) +delete_char|||[lv_textarea_delete_char](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_delete_char) +delete_char_forward|||[lv_textarea_delete_char_forward](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_delete_char_forward) +get_accepted_chars||string|[lv_textarea_get_accepted_chars](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_get_accepted_chars) +get_current_char||int|[lv_textarea_get_current_char](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_get_current_char) +get_cursor_click_pos||bool|[lv_textarea_get_cursor_click_pos](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_get_cursor_click_pos) +get_cursor_pos||int|[lv_textarea_get_cursor_pos](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_get_cursor_pos) +get_label||lv.obj|[lv_textarea_get_label](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_get_label) +get_max_length||int|[lv_textarea_get_max_length](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_get_max_length) +get_one_line||bool|[lv_textarea_get_one_line](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_get_one_line) +get_password_bullet||string|[lv_textarea_get_password_bullet](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_get_password_bullet) +get_password_mode||bool|[lv_textarea_get_password_mode](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_get_password_mode) +get_password_show_time||int|[lv_textarea_get_password_show_time](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_get_password_show_time) +get_placeholder_text||string|[lv_textarea_get_placeholder_text](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_get_placeholder_text) +get_text||string|[lv_textarea_get_text](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_get_text) +get_text_selection||bool|[lv_textarea_get_text_selection](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_get_text_selection) +set_accepted_chars|string||[lv_textarea_set_accepted_chars](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_set_accepted_chars) +set_align|int||[lv_textarea_set_align](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_set_align) +set_cursor_click_pos|bool||[lv_textarea_set_cursor_click_pos](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_set_cursor_click_pos) +set_cursor_pos|int||[lv_textarea_set_cursor_pos](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_set_cursor_pos) +set_insert_replace|string||[lv_textarea_set_insert_replace](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_set_insert_replace) +set_max_length|int||[lv_textarea_set_max_length](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_set_max_length) +set_one_line|bool||[lv_textarea_set_one_line](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_set_one_line) +set_password_bullet|string||[lv_textarea_set_password_bullet](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_set_password_bullet) +set_password_mode|bool||[lv_textarea_set_password_mode](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_set_password_mode) +set_password_show_time|int||[lv_textarea_set_password_show_time](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_set_password_show_time) +set_placeholder_text|string||[lv_textarea_set_placeholder_text](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_set_placeholder_text) +set_text|string||[lv_textarea_set_text](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_set_text) +set_text_selection|bool||[lv_textarea_set_text_selection](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_set_text_selection) +text_is_selected||bool|[lv_textarea_text_is_selected](https://docs.lvgl.io/9.0/search.html?q=lv_textarea_text_is_selected) + +### widget `lv.spangroup` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +delete_span|lv.spangroup||[lv_spangroup_delete_span](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_delete_span) +get_align||int|[lv_spangroup_get_align](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_get_align) +get_child|int|lv.spangroup|[lv_spangroup_get_child](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_get_child) +get_expand_height|int|int|[lv_spangroup_get_expand_height](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_get_expand_height) +get_expand_width|int|int|[lv_spangroup_get_expand_width](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_get_expand_width) +get_indent||int|[lv_spangroup_get_indent](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_get_indent) +get_max_line_height||int|[lv_spangroup_get_max_line_height](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_get_max_line_height) +get_max_lines||int|[lv_spangroup_get_max_lines](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_get_max_lines) +get_mode||int|[lv_spangroup_get_mode](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_get_mode) +get_overflow||int|[lv_spangroup_get_overflow](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_get_overflow) +get_span_count||int|[lv_spangroup_get_span_count](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_get_span_count) +new_span||lv.spangroup|[lv_spangroup_new_span](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_new_span) +refr_mode|||[lv_spangroup_refr_mode](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_refr_mode) +set_align|int||[lv_spangroup_set_align](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_set_align) +set_indent|int||[lv_spangroup_set_indent](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_set_indent) +set_max_lines|int||[lv_spangroup_set_max_lines](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_set_max_lines) +set_mode|int||[lv_spangroup_set_mode](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_set_mode) +set_overflow|int||[lv_spangroup_set_overflow](https://docs.lvgl.io/9.0/search.html?q=lv_spangroup_set_overflow) + +### widget `lv.scale` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +add_section||comptr|[lv_scale_add_section](https://docs.lvgl.io/9.0/search.html?q=lv_scale_add_section) +get_angle_range||int|[lv_scale_get_angle_range](https://docs.lvgl.io/9.0/search.html?q=lv_scale_get_angle_range) +get_label_show||bool|[lv_scale_get_label_show](https://docs.lvgl.io/9.0/search.html?q=lv_scale_get_label_show) +get_major_tick_every||int|[lv_scale_get_major_tick_every](https://docs.lvgl.io/9.0/search.html?q=lv_scale_get_major_tick_every) +get_mode||int|[lv_scale_get_mode](https://docs.lvgl.io/9.0/search.html?q=lv_scale_get_mode) +get_range_max_value||int|[lv_scale_get_range_max_value](https://docs.lvgl.io/9.0/search.html?q=lv_scale_get_range_max_value) +get_range_min_value||int|[lv_scale_get_range_min_value](https://docs.lvgl.io/9.0/search.html?q=lv_scale_get_range_min_value) +get_total_tick_count||int|[lv_scale_get_total_tick_count](https://docs.lvgl.io/9.0/search.html?q=lv_scale_get_total_tick_count) +set_angle|int||[lv_scale_set_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_scale_set_rotation) +set_angle_range|int||[lv_scale_set_angle_range](https://docs.lvgl.io/9.0/search.html?q=lv_scale_set_angle_range) +set_image_needle_value|lv.obj, int||[lv_scale_set_image_needle_value](https://docs.lvgl.io/9.0/search.html?q=lv_scale_set_image_needle_value) +set_label_show|bool||[lv_scale_set_label_show](https://docs.lvgl.io/9.0/search.html?q=lv_scale_set_label_show) +set_line_needle_value|lv.obj, int, int||[lv_scale_set_line_needle_value](https://docs.lvgl.io/9.0/search.html?q=lv_scale_set_line_needle_value) +set_major_tick_every|int||[lv_scale_set_major_tick_every](https://docs.lvgl.io/9.0/search.html?q=lv_scale_set_major_tick_every) +set_mode|int||[lv_scale_set_mode](https://docs.lvgl.io/9.0/search.html?q=lv_scale_set_mode) +set_post_draw|bool||[lv_scale_set_post_draw](https://docs.lvgl.io/9.0/search.html?q=lv_scale_set_post_draw) +set_range|int, int||[lv_scale_set_range](https://docs.lvgl.io/9.0/search.html?q=lv_scale_set_range) +set_rotation|int||[lv_scale_set_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_scale_set_rotation) +set_rotation|int||[lv_scale_set_rotation](https://docs.lvgl.io/9.0/search.html?q=lv_scale_set_rotation) +set_text_src|lv.str_arr||[lv_scale_set_text_src](https://docs.lvgl.io/9.0/search.html?q=lv_scale_set_text_src) +set_total_tick_count|int||[lv_scale_set_total_tick_count](https://docs.lvgl.io/9.0/search.html?q=lv_scale_set_total_tick_count) + +### widget `lv.chart` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +add_cursor|lv.color, int|lv.chart_cursor|[lv_chart_add_cursor](https://docs.lvgl.io/9.0/search.html?q=lv_chart_add_cursor) +add_series|lv.color, int|lv.chart_series|[lv_chart_add_series](https://docs.lvgl.io/9.0/search.html?q=lv_chart_add_series) +get_cursor_point|lv.chart_cursor|int|[lv_chart_get_cursor_point](https://docs.lvgl.io/9.0/search.html?q=lv_chart_get_cursor_point) +get_first_point_center_offset||int|[lv_chart_get_first_point_center_offset](https://docs.lvgl.io/9.0/search.html?q=lv_chart_get_first_point_center_offset) +get_point_count||int|[lv_chart_get_point_count](https://docs.lvgl.io/9.0/search.html?q=lv_chart_get_point_count) +get_point_pos_by_id|lv.chart_series, int, comptr||[lv_chart_get_point_pos_by_id](https://docs.lvgl.io/9.0/search.html?q=lv_chart_get_point_pos_by_id) +get_pressed_point||int|[lv_chart_get_pressed_point](https://docs.lvgl.io/9.0/search.html?q=lv_chart_get_pressed_point) +get_series_next|lv.chart_series|lv.chart_series|[lv_chart_get_series_next](https://docs.lvgl.io/9.0/search.html?q=lv_chart_get_series_next) +get_type||int|[lv_chart_get_type](https://docs.lvgl.io/9.0/search.html?q=lv_chart_get_type) +get_x_array|lv.chart_series|lv.int_arr|[lv_chart_get_x_array](https://docs.lvgl.io/9.0/search.html?q=lv_chart_get_x_array) +get_x_start_point|lv.chart_series|int|[lv_chart_get_x_start_point](https://docs.lvgl.io/9.0/search.html?q=lv_chart_get_x_start_point) +get_y_array|lv.chart_series|lv.int_arr|[lv_chart_get_y_array](https://docs.lvgl.io/9.0/search.html?q=lv_chart_get_y_array) +hide_series|lv.chart_series, bool||[lv_chart_hide_series](https://docs.lvgl.io/9.0/search.html?q=lv_chart_hide_series) +refresh|||[lv_chart_refresh](https://docs.lvgl.io/9.0/search.html?q=lv_chart_refresh) +remove_series|lv.chart_series||[lv_chart_remove_series](https://docs.lvgl.io/9.0/search.html?q=lv_chart_remove_series) +set_all_value|lv.chart_series, int||[lv_chart_set_all_value](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_all_value) +set_cursor_point|lv.chart_cursor, lv.chart_series, int||[lv_chart_set_cursor_point](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_cursor_point) +set_cursor_pos|lv.chart_cursor, comptr||[lv_chart_set_cursor_pos](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_cursor_pos) +set_div_line_count|int, int||[lv_chart_set_div_line_count](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_div_line_count) +set_ext_x_array|lv.chart_series, lv.int_arr||[lv_chart_set_ext_x_array](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_ext_x_array) +set_ext_y_array|lv.chart_series, lv.int_arr||[lv_chart_set_ext_y_array](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_ext_y_array) +set_next_value|lv.chart_series, int||[lv_chart_set_next_value](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_next_value) +set_next_value2|lv.chart_series, int, int||[lv_chart_set_next_value2](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_next_value2) +set_point_count|int||[lv_chart_set_point_count](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_point_count) +set_range|int, int, int||[lv_chart_set_range](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_range) +set_series_color|lv.chart_series, lv.color||[lv_chart_set_series_color](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_series_color) +set_type|int||[lv_chart_set_type](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_type) +set_update_mode|int||[lv_chart_set_update_mode](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_update_mode) +set_value_by_id|lv.chart_series, int, int||[lv_chart_set_value_by_id](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_value_by_id) +set_value_by_id2|lv.chart_series, int, int, int||[lv_chart_set_value_by_id2](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_value_by_id2) +set_x_start_point|lv.chart_series, int||[lv_chart_set_x_start_point](https://docs.lvgl.io/9.0/search.html?q=lv_chart_set_x_start_point) + +### widget `lv.imagebutton` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +set_src|int, \, \, \||[lv_imagebutton_set_src](https://docs.lvgl.io/9.0/search.html?q=lv_imagebutton_set_src) +set_state|int||[lv_imagebutton_set_state](https://docs.lvgl.io/9.0/search.html?q=lv_imagebutton_set_state) + +### widget `lv.led` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +get_brightness||int|[lv_led_get_brightness](https://docs.lvgl.io/9.0/search.html?q=lv_led_get_brightness) +off|||[lv_led_off](https://docs.lvgl.io/9.0/search.html?q=lv_led_off) +on|||[lv_led_on](https://docs.lvgl.io/9.0/search.html?q=lv_led_on) +set_brightness|int||[lv_led_set_brightness](https://docs.lvgl.io/9.0/search.html?q=lv_led_set_brightness) +set_color|lv.color||[lv_led_set_color](https://docs.lvgl.io/9.0/search.html?q=lv_led_set_color) +toggle|||[lv_led_toggle](https://docs.lvgl.io/9.0/search.html?q=lv_led_toggle) + +### widget `lv.msgbox` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +add_close_button||lv.obj|[lv_msgbox_add_close_button](https://docs.lvgl.io/9.0/search.html?q=lv_msgbox_add_close_button) +add_footer_button|string|lv.obj|[lv_msgbox_add_footer_button](https://docs.lvgl.io/9.0/search.html?q=lv_msgbox_add_footer_button) +add_header_button|\|lv.obj|[lv_msgbox_add_header_button](https://docs.lvgl.io/9.0/search.html?q=lv_msgbox_add_header_button) +add_text|string|lv.obj|[lv_msgbox_add_text](https://docs.lvgl.io/9.0/search.html?q=lv_msgbox_add_text) +add_title|string|lv.obj|[lv_msgbox_add_title](https://docs.lvgl.io/9.0/search.html?q=lv_msgbox_add_title) +close|||[lv_msgbox_close](https://docs.lvgl.io/9.0/search.html?q=lv_msgbox_close) +close_async|||[lv_msgbox_close_async](https://docs.lvgl.io/9.0/search.html?q=lv_msgbox_close_async) +get_content||lv.obj|[lv_msgbox_get_content](https://docs.lvgl.io/9.0/search.html?q=lv_msgbox_get_content) +get_footer||lv.obj|[lv_msgbox_get_footer](https://docs.lvgl.io/9.0/search.html?q=lv_msgbox_get_footer) +get_header||lv.obj|[lv_msgbox_get_header](https://docs.lvgl.io/9.0/search.html?q=lv_msgbox_get_header) +get_title||lv.obj|[lv_msgbox_get_title](https://docs.lvgl.io/9.0/search.html?q=lv_msgbox_get_title) + +### widget `lv.spinbox` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +decrement|||[lv_spinbox_decrement](https://docs.lvgl.io/9.0/search.html?q=lv_spinbox_decrement) +get_rollover||bool|[lv_spinbox_get_rollover](https://docs.lvgl.io/9.0/search.html?q=lv_spinbox_get_rollover) +get_step||int|[lv_spinbox_get_step](https://docs.lvgl.io/9.0/search.html?q=lv_spinbox_get_step) +get_value||int|[lv_spinbox_get_value](https://docs.lvgl.io/9.0/search.html?q=lv_spinbox_get_value) +increment|||[lv_spinbox_increment](https://docs.lvgl.io/9.0/search.html?q=lv_spinbox_increment) +set_cursor_pos|int||[lv_spinbox_set_cursor_pos](https://docs.lvgl.io/9.0/search.html?q=lv_spinbox_set_cursor_pos) +set_digit_format|int, int||[lv_spinbox_set_digit_format](https://docs.lvgl.io/9.0/search.html?q=lv_spinbox_set_digit_format) +set_digit_step_direction|int||[lv_spinbox_set_digit_step_direction](https://docs.lvgl.io/9.0/search.html?q=lv_spinbox_set_digit_step_direction) +set_range|int, int||[lv_spinbox_set_range](https://docs.lvgl.io/9.0/search.html?q=lv_spinbox_set_range) +set_rollover|bool||[lv_spinbox_set_rollover](https://docs.lvgl.io/9.0/search.html?q=lv_spinbox_set_rollover) +set_step|int||[lv_spinbox_set_step](https://docs.lvgl.io/9.0/search.html?q=lv_spinbox_set_step) +set_value|int||[lv_spinbox_set_value](https://docs.lvgl.io/9.0/search.html?q=lv_spinbox_set_value) +step_next|||[lv_spinbox_step_next](https://docs.lvgl.io/9.0/search.html?q=lv_spinbox_step_next) +step_prev|||[lv_spinbox_step_prev](https://docs.lvgl.io/9.0/search.html?q=lv_spinbox_step_prev) + +### widget `lv.spinner` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +set_anim_params|int, int||[lv_spinner_set_anim_params](https://docs.lvgl.io/9.0/search.html?q=lv_spinner_set_anim_params) + +### widget `lv.keyboard` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +_btn_text|int|string|[lv_keyboard_get_button_text](https://docs.lvgl.io/9.0/search.html?q=lv_keyboard_get_button_text) +get_button_text|int|string|[lv_keyboard_get_button_text](https://docs.lvgl.io/9.0/search.html?q=lv_keyboard_get_button_text) +get_map_array||comptr|[lv_keyboard_get_map_array](https://docs.lvgl.io/9.0/search.html?q=lv_keyboard_get_map_array) +get_mode||int|[lv_keyboard_get_mode](https://docs.lvgl.io/9.0/search.html?q=lv_keyboard_get_mode) +get_selected_button||int|[lv_keyboard_get_selected_button](https://docs.lvgl.io/9.0/search.html?q=lv_keyboard_get_selected_button) +get_textarea||lv.obj|[lv_keyboard_get_textarea](https://docs.lvgl.io/9.0/search.html?q=lv_keyboard_get_textarea) +set_mode|int||[lv_keyboard_set_mode](https://docs.lvgl.io/9.0/search.html?q=lv_keyboard_set_mode) +set_popovers|bool||[lv_keyboard_set_popovers](https://docs.lvgl.io/9.0/search.html?q=lv_keyboard_set_popovers) +set_textarea|lv.obj||[lv_keyboard_set_textarea](https://docs.lvgl.io/9.0/search.html?q=lv_keyboard_set_textarea) + +### widget `lv.tabview` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +add_tab|string|lv.obj|[lv_tabview_add_tab](https://docs.lvgl.io/9.0/search.html?q=lv_tabview_add_tab) +get_content||lv.obj|[lv_tabview_get_content](https://docs.lvgl.io/9.0/search.html?q=lv_tabview_get_content) +get_tab_act||int|[lv_tabview_get_tab_active](https://docs.lvgl.io/9.0/search.html?q=lv_tabview_get_tab_active) +get_tab_active||int|[lv_tabview_get_tab_active](https://docs.lvgl.io/9.0/search.html?q=lv_tabview_get_tab_active) +get_tab_bar||lv.obj|[lv_tabview_get_tab_bar](https://docs.lvgl.io/9.0/search.html?q=lv_tabview_get_tab_bar) +get_tab_btns||lv.obj|[lv_tabview_get_tab_bar](https://docs.lvgl.io/9.0/search.html?q=lv_tabview_get_tab_bar) +get_tab_count||int|[lv_tabview_get_tab_count](https://docs.lvgl.io/9.0/search.html?q=lv_tabview_get_tab_count) +rename_tab|int, string||[lv_tabview_rename_tab](https://docs.lvgl.io/9.0/search.html?q=lv_tabview_rename_tab) +set_act|int, int||[lv_tabview_set_active](https://docs.lvgl.io/9.0/search.html?q=lv_tabview_set_active) +set_active|int, int||[lv_tabview_set_active](https://docs.lvgl.io/9.0/search.html?q=lv_tabview_set_active) +set_tab_bar_position|int||[lv_tabview_set_tab_bar_position](https://docs.lvgl.io/9.0/search.html?q=lv_tabview_set_tab_bar_position) +set_tab_bar_size|int||[lv_tabview_set_tab_bar_size](https://docs.lvgl.io/9.0/search.html?q=lv_tabview_set_tab_bar_size) + +### widget `lv.tileview` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +add_tile|int, int, int|lv.obj|[lv_tileview_add_tile](https://docs.lvgl.io/9.0/search.html?q=lv_tileview_add_tile) +get_tile_act||lv.obj|[lv_tileview_get_tile_active](https://docs.lvgl.io/9.0/search.html?q=lv_tileview_get_tile_active) +get_tile_active||lv.obj|[lv_tileview_get_tile_active](https://docs.lvgl.io/9.0/search.html?q=lv_tileview_get_tile_active) +set_tile|lv.obj, int||[lv_tileview_set_tile](https://docs.lvgl.io/9.0/search.html?q=lv_tileview_set_tile) +set_tile_by_index|int, int, int||[lv_tileview_set_tile_by_index](https://docs.lvgl.io/9.0/search.html?q=lv_tileview_set_tile_by_index) +set_tile_id|int, int, int||[lv_tileview_set_tile_by_index](https://docs.lvgl.io/9.0/search.html?q=lv_tileview_set_tile_by_index) + +### widget `lv.list` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +_btn_text|lv.obj|string|[lv_list_get_button_text](https://docs.lvgl.io/9.0/search.html?q=lv_list_get_button_text) +add_btn|\, string|lv.obj|[lv_list_add_button](https://docs.lvgl.io/9.0/search.html?q=lv_list_add_button) +add_button|\, string|lv.obj|[lv_list_add_button](https://docs.lvgl.io/9.0/search.html?q=lv_list_add_button) +add_text|string|lv.obj|[lv_list_add_text](https://docs.lvgl.io/9.0/search.html?q=lv_list_add_text) +get_button_text|lv.obj|string|[lv_list_get_button_text](https://docs.lvgl.io/9.0/search.html?q=lv_list_get_button_text) +set_btn_text|lv.obj, string||[lv_list_set_button_text](https://docs.lvgl.io/9.0/search.html?q=lv_list_set_button_text) +set_button_text|lv.obj, string||[lv_list_set_button_text](https://docs.lvgl.io/9.0/search.html?q=lv_list_set_button_text) + +### widget `lv.animimg` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +get_duration||int|[lv_animimg_get_duration](https://docs.lvgl.io/9.0/search.html?q=lv_animimg_get_duration) +get_repeat_count||int|[lv_animimg_get_repeat_count](https://docs.lvgl.io/9.0/search.html?q=lv_animimg_get_repeat_count) +get_src_count||int|[lv_animimg_get_src_count](https://docs.lvgl.io/9.0/search.html?q=lv_animimg_get_src_count) +set_duration|int||[lv_animimg_set_duration](https://docs.lvgl.io/9.0/search.html?q=lv_animimg_set_duration) +set_repeat_count|int||[lv_animimg_set_repeat_count](https://docs.lvgl.io/9.0/search.html?q=lv_animimg_set_repeat_count) +set_src|comptr, int||[lv_animimg_set_src](https://docs.lvgl.io/9.0/search.html?q=lv_animimg_set_src) +start|||[lv_animimg_start](https://docs.lvgl.io/9.0/search.html?q=lv_animimg_start) + +### widget `lv.calendar` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +get_btnmatrix||lv.obj|[lv_calendar_get_btnmatrix](https://docs.lvgl.io/9.0/search.html?q=lv_calendar_get_btnmatrix) +get_highlighted_dates_num||int|[lv_calendar_get_highlighted_dates_num](https://docs.lvgl.io/9.0/search.html?q=lv_calendar_get_highlighted_dates_num) +header_dropdown_set_year_list|string||[lv_calendar_header_dropdown_set_year_list](https://docs.lvgl.io/9.0/search.html?q=lv_calendar_header_dropdown_set_year_list) +set_day_names|comptr||[lv_calendar_set_day_names](https://docs.lvgl.io/9.0/search.html?q=lv_calendar_set_day_names) +set_showed_date|int, int||[lv_calendar_set_showed_date](https://docs.lvgl.io/9.0/search.html?q=lv_calendar_set_showed_date) +set_today_date|int, int, int||[lv_calendar_set_today_date](https://docs.lvgl.io/9.0/search.html?q=lv_calendar_set_today_date) + +### widget `lv.menu` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +back_button_is_root|lv.obj|bool|[lv_menu_back_button_is_root](https://docs.lvgl.io/9.0/search.html?q=lv_menu_back_button_is_root) +clear_history|||[lv_menu_clear_history](https://docs.lvgl.io/9.0/search.html?q=lv_menu_clear_history) +get_cur_main_page||lv.obj|[lv_menu_get_cur_main_page](https://docs.lvgl.io/9.0/search.html?q=lv_menu_get_cur_main_page) +get_cur_sidebar_page||lv.obj|[lv_menu_get_cur_sidebar_page](https://docs.lvgl.io/9.0/search.html?q=lv_menu_get_cur_sidebar_page) +get_main_header||lv.obj|[lv_menu_get_main_header](https://docs.lvgl.io/9.0/search.html?q=lv_menu_get_main_header) +get_main_header_back_button||lv.obj|[lv_menu_get_main_header_back_button](https://docs.lvgl.io/9.0/search.html?q=lv_menu_get_main_header_back_button) +get_sidebar_header||lv.obj|[lv_menu_get_sidebar_header](https://docs.lvgl.io/9.0/search.html?q=lv_menu_get_sidebar_header) +get_sidebar_header_back_button||lv.obj|[lv_menu_get_sidebar_header_back_button](https://docs.lvgl.io/9.0/search.html?q=lv_menu_get_sidebar_header_back_button) +set_load_page_event|lv.obj, lv.obj||[lv_menu_set_load_page_event](https://docs.lvgl.io/9.0/search.html?q=lv_menu_set_load_page_event) +set_mode_header|int||[lv_menu_set_mode_header](https://docs.lvgl.io/9.0/search.html?q=lv_menu_set_mode_header) +set_mode_root_back_button|int||[lv_menu_set_mode_root_back_button](https://docs.lvgl.io/9.0/search.html?q=lv_menu_set_mode_root_back_button) +set_page|lv.obj||[lv_menu_set_page](https://docs.lvgl.io/9.0/search.html?q=lv_menu_set_page) +set_page_title|comptr||[lv_menu_set_page_title](https://docs.lvgl.io/9.0/search.html?q=lv_menu_set_page_title) +set_page_title_static|comptr||[lv_menu_set_page_title_static](https://docs.lvgl.io/9.0/search.html?q=lv_menu_set_page_title_static) +set_sidebar_page|lv.obj||[lv_menu_set_sidebar_page](https://docs.lvgl.io/9.0/search.html?q=lv_menu_set_sidebar_page) + +### widget `lv.qrcode` + +Method|Arguments|Return type|LVGL equivalent +:---|:---|:---|:--- +set_dark_color|lv.color||[lv_qrcode_set_dark_color](https://docs.lvgl.io/9.0/search.html?q=lv_qrcode_set_dark_color) +set_light_color|lv.color||[lv_qrcode_set_light_color](https://docs.lvgl.io/9.0/search.html?q=lv_qrcode_set_light_color) +set_size|int||[lv_qrcode_set_size](https://docs.lvgl.io/9.0/search.html?q=lv_qrcode_set_size) +update|\, int|int|[lv_qrcode_update](https://docs.lvgl.io/9.0/search.html?q=lv_qrcode_update) + diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h index c880b3918..47009cd7c 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h @@ -12,118 +12,138 @@ extern "C" { /* `lv_style` methods */ const be_ntv_func_def_t lv_style_func[] = { - { "get_prop", { (const void*) &lv_style_get_prop, "i", "(lv.lv_style)i(lv.lv_style_value)" } }, - { "get_prop_inlined", { (const void*) &lv_style_get_prop_inlined, "i", "(lv.lv_style)i(lv.lv_style_value)" } }, - { "is_empty", { (const void*) &lv_style_is_empty, "b", "(lv.lv_style)" } }, - { "remove_prop", { (const void*) &lv_style_remove_prop, "b", "(lv.lv_style)i" } }, - { "reset", { (const void*) &lv_style_reset, "", "(lv.lv_style)" } }, - { "set_align", { (const void*) &lv_style_set_align, "", "(lv.lv_style)i" } }, - { "set_anim", { (const void*) &lv_style_set_anim, "", "(lv.lv_style)(lv.lv_anim)" } }, - { "set_anim_speed", { (const void*) &lv_style_set_anim_speed, "", "(lv.lv_style)i" } }, - { "set_anim_time", { (const void*) &lv_style_set_anim_time, "", "(lv.lv_style)i" } }, - { "set_arc_color", { (const void*) &lv_style_set_arc_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_arc_img_src", { (const void*) &lv_style_set_arc_img_src, "", "(lv.lv_style)." } }, - { "set_arc_opa", { (const void*) &lv_style_set_arc_opa, "", "(lv.lv_style)i" } }, - { "set_arc_rounded", { (const void*) &lv_style_set_arc_rounded, "", "(lv.lv_style)b" } }, - { "set_arc_width", { (const void*) &lv_style_set_arc_width, "", "(lv.lv_style)i" } }, - { "set_base_dir", { (const void*) &lv_style_set_base_dir, "", "(lv.lv_style)i" } }, - { "set_bg_color", { (const void*) &lv_style_set_bg_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_bg_dither_mode", { (const void*) &lv_style_set_bg_dither_mode, "", "(lv.lv_style)i" } }, - { "set_bg_grad", { (const void*) &lv_style_set_bg_grad, "", "(lv.lv_style)(lv.lv_grad_dsc)" } }, - { "set_bg_grad_color", { (const void*) &lv_style_set_bg_grad_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_bg_grad_dir", { (const void*) &lv_style_set_bg_grad_dir, "", "(lv.lv_style)i" } }, - { "set_bg_grad_stop", { (const void*) &lv_style_set_bg_grad_stop, "", "(lv.lv_style)i" } }, - { "set_bg_img_opa", { (const void*) &lv_style_set_bg_img_opa, "", "(lv.lv_style)i" } }, - { "set_bg_img_recolor", { (const void*) &lv_style_set_bg_img_recolor, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_bg_img_recolor_opa", { (const void*) &lv_style_set_bg_img_recolor_opa, "", "(lv.lv_style)i" } }, - { "set_bg_img_src", { (const void*) &lv_style_set_bg_img_src, "", "(lv.lv_style)." } }, - { "set_bg_img_tiled", { (const void*) &lv_style_set_bg_img_tiled, "", "(lv.lv_style)b" } }, - { "set_bg_main_stop", { (const void*) &lv_style_set_bg_main_stop, "", "(lv.lv_style)i" } }, - { "set_bg_opa", { (const void*) &lv_style_set_bg_opa, "", "(lv.lv_style)i" } }, - { "set_blend_mode", { (const void*) &lv_style_set_blend_mode, "", "(lv.lv_style)i" } }, - { "set_border_color", { (const void*) &lv_style_set_border_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_border_opa", { (const void*) &lv_style_set_border_opa, "", "(lv.lv_style)i" } }, - { "set_border_post", { (const void*) &lv_style_set_border_post, "", "(lv.lv_style)b" } }, - { "set_border_side", { (const void*) &lv_style_set_border_side, "", "(lv.lv_style)i" } }, - { "set_border_width", { (const void*) &lv_style_set_border_width, "", "(lv.lv_style)i" } }, - { "set_clip_corner", { (const void*) &lv_style_set_clip_corner, "", "(lv.lv_style)b" } }, - { "set_color_filter_dsc", { (const void*) &lv_style_set_color_filter_dsc, "", "(lv.lv_style)(lv.lv_color_filter_dsc)" } }, - { "set_color_filter_opa", { (const void*) &lv_style_set_color_filter_opa, "", "(lv.lv_style)i" } }, - { "set_flex_cross_place", { (const void*) &lv_style_set_flex_cross_place, "", "(lv.lv_style)i" } }, - { "set_flex_flow", { (const void*) &lv_style_set_flex_flow, "", "(lv.lv_style)i" } }, - { "set_flex_grow", { (const void*) &lv_style_set_flex_grow, "", "(lv.lv_style)i" } }, - { "set_flex_main_place", { (const void*) &lv_style_set_flex_main_place, "", "(lv.lv_style)i" } }, - { "set_flex_track_place", { (const void*) &lv_style_set_flex_track_place, "", "(lv.lv_style)i" } }, - { "set_grid_cell_column_pos", { (const void*) &lv_style_set_grid_cell_column_pos, "", "(lv.lv_style)i" } }, - { "set_grid_cell_column_span", { (const void*) &lv_style_set_grid_cell_column_span, "", "(lv.lv_style)i" } }, - { "set_grid_cell_row_pos", { (const void*) &lv_style_set_grid_cell_row_pos, "", "(lv.lv_style)i" } }, - { "set_grid_cell_row_span", { (const void*) &lv_style_set_grid_cell_row_span, "", "(lv.lv_style)i" } }, - { "set_grid_cell_x_align", { (const void*) &lv_style_set_grid_cell_x_align, "", "(lv.lv_style)i" } }, - { "set_grid_cell_y_align", { (const void*) &lv_style_set_grid_cell_y_align, "", "(lv.lv_style)i" } }, - { "set_grid_column_align", { (const void*) &lv_style_set_grid_column_align, "", "(lv.lv_style)i" } }, - { "set_grid_column_dsc_array", { (const void*) &lv_style_set_grid_column_dsc_array, "", "(lv.lv_style)(lv.lv_coord_arr)" } }, - { "set_grid_row_align", { (const void*) &lv_style_set_grid_row_align, "", "(lv.lv_style)i" } }, - { "set_grid_row_dsc_array", { (const void*) &lv_style_set_grid_row_dsc_array, "", "(lv.lv_style)(lv.lv_coord_arr)" } }, - { "set_height", { (const void*) &lv_style_set_height, "", "(lv.lv_style)i" } }, - { "set_img_opa", { (const void*) &lv_style_set_img_opa, "", "(lv.lv_style)i" } }, - { "set_img_recolor", { (const void*) &lv_style_set_img_recolor, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_img_recolor_opa", { (const void*) &lv_style_set_img_recolor_opa, "", "(lv.lv_style)i" } }, - { "set_layout", { (const void*) &lv_style_set_layout, "", "(lv.lv_style)i" } }, - { "set_line_color", { (const void*) &lv_style_set_line_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_line_dash_gap", { (const void*) &lv_style_set_line_dash_gap, "", "(lv.lv_style)i" } }, - { "set_line_dash_width", { (const void*) &lv_style_set_line_dash_width, "", "(lv.lv_style)i" } }, - { "set_line_opa", { (const void*) &lv_style_set_line_opa, "", "(lv.lv_style)i" } }, - { "set_line_rounded", { (const void*) &lv_style_set_line_rounded, "", "(lv.lv_style)b" } }, - { "set_line_width", { (const void*) &lv_style_set_line_width, "", "(lv.lv_style)i" } }, - { "set_max_height", { (const void*) &lv_style_set_max_height, "", "(lv.lv_style)i" } }, - { "set_max_width", { (const void*) &lv_style_set_max_width, "", "(lv.lv_style)i" } }, - { "set_min_height", { (const void*) &lv_style_set_min_height, "", "(lv.lv_style)i" } }, - { "set_min_width", { (const void*) &lv_style_set_min_width, "", "(lv.lv_style)i" } }, - { "set_opa", { (const void*) &lv_style_set_opa, "", "(lv.lv_style)i" } }, - { "set_opa_layered", { (const void*) &lv_style_set_opa_layered, "", "(lv.lv_style)i" } }, - { "set_outline_color", { (const void*) &lv_style_set_outline_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_outline_opa", { (const void*) &lv_style_set_outline_opa, "", "(lv.lv_style)i" } }, - { "set_outline_pad", { (const void*) &lv_style_set_outline_pad, "", "(lv.lv_style)i" } }, - { "set_outline_width", { (const void*) &lv_style_set_outline_width, "", "(lv.lv_style)i" } }, - { "set_pad_all", { (const void*) &lv_style_set_pad_all, "", "(lv.lv_style)i" } }, - { "set_pad_bottom", { (const void*) &lv_style_set_pad_bottom, "", "(lv.lv_style)i" } }, - { "set_pad_column", { (const void*) &lv_style_set_pad_column, "", "(lv.lv_style)i" } }, - { "set_pad_gap", { (const void*) &lv_style_set_pad_gap, "", "(lv.lv_style)i" } }, - { "set_pad_hor", { (const void*) &lv_style_set_pad_hor, "", "(lv.lv_style)i" } }, - { "set_pad_left", { (const void*) &lv_style_set_pad_left, "", "(lv.lv_style)i" } }, - { "set_pad_right", { (const void*) &lv_style_set_pad_right, "", "(lv.lv_style)i" } }, - { "set_pad_row", { (const void*) &lv_style_set_pad_row, "", "(lv.lv_style)i" } }, - { "set_pad_top", { (const void*) &lv_style_set_pad_top, "", "(lv.lv_style)i" } }, - { "set_pad_ver", { (const void*) &lv_style_set_pad_ver, "", "(lv.lv_style)i" } }, - { "set_prop", { (const void*) &lv_style_set_prop, "", "(lv.lv_style)ii" } }, - { "set_prop_meta", { (const void*) &lv_style_set_prop_meta, "", "(lv.lv_style)ii" } }, - { "set_radius", { (const void*) &lv_style_set_radius, "", "(lv.lv_style)i" } }, - { "set_shadow_color", { (const void*) &lv_style_set_shadow_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_shadow_ofs_x", { (const void*) &lv_style_set_shadow_ofs_x, "", "(lv.lv_style)i" } }, - { "set_shadow_ofs_y", { (const void*) &lv_style_set_shadow_ofs_y, "", "(lv.lv_style)i" } }, - { "set_shadow_opa", { (const void*) &lv_style_set_shadow_opa, "", "(lv.lv_style)i" } }, - { "set_shadow_spread", { (const void*) &lv_style_set_shadow_spread, "", "(lv.lv_style)i" } }, - { "set_shadow_width", { (const void*) &lv_style_set_shadow_width, "", "(lv.lv_style)i" } }, - { "set_size", { (const void*) &lv_style_set_size, "", "(lv.lv_style)i" } }, - { "set_text_align", { (const void*) &lv_style_set_text_align, "", "(lv.lv_style)i" } }, - { "set_text_color", { (const void*) &lv_style_set_text_color, "", "(lv.lv_style)(lv.lv_color)" } }, - { "set_text_decor", { (const void*) &lv_style_set_text_decor, "", "(lv.lv_style)i" } }, - { "set_text_font", { (const void*) &lv_style_set_text_font, "", "(lv.lv_style)(lv.lv_font)" } }, - { "set_text_letter_space", { (const void*) &lv_style_set_text_letter_space, "", "(lv.lv_style)i" } }, - { "set_text_line_space", { (const void*) &lv_style_set_text_line_space, "", "(lv.lv_style)i" } }, - { "set_text_opa", { (const void*) &lv_style_set_text_opa, "", "(lv.lv_style)i" } }, - { "set_transform_angle", { (const void*) &lv_style_set_transform_angle, "", "(lv.lv_style)i" } }, - { "set_transform_height", { (const void*) &lv_style_set_transform_height, "", "(lv.lv_style)i" } }, - { "set_transform_pivot_x", { (const void*) &lv_style_set_transform_pivot_x, "", "(lv.lv_style)i" } }, - { "set_transform_pivot_y", { (const void*) &lv_style_set_transform_pivot_y, "", "(lv.lv_style)i" } }, - { "set_transform_width", { (const void*) &lv_style_set_transform_width, "", "(lv.lv_style)i" } }, - { "set_transform_zoom", { (const void*) &lv_style_set_transform_zoom, "", "(lv.lv_style)i" } }, - { "set_transition", { (const void*) &lv_style_set_transition, "", "(lv.lv_style)(lv.lv_style_transition_dsc)" } }, - { "set_translate_x", { (const void*) &lv_style_set_translate_x, "", "(lv.lv_style)i" } }, - { "set_translate_y", { (const void*) &lv_style_set_translate_y, "", "(lv.lv_style)i" } }, - { "set_width", { (const void*) &lv_style_set_width, "", "(lv.lv_style)i" } }, - { "set_x", { (const void*) &lv_style_set_x, "", "(lv.lv_style)i" } }, - { "set_y", { (const void*) &lv_style_set_y, "", "(lv.lv_style)i" } }, + { "is_const", { (const void*) &lv_style_is_const, "b", "(lv.style)" } }, + { "is_empty", { (const void*) &lv_style_is_empty, "b", "(lv.style)" } }, + { "remove_prop", { (const void*) &lv_style_remove_prop, "b", "(lv.style)i" } }, + { "reset", { (const void*) &lv_style_reset, "", "(lv.style)" } }, + { "set_align", { (const void*) &lv_style_set_align, "", "(lv.style)i" } }, + { "set_anim", { (const void*) &lv_style_set_anim, "", "(lv.style)(lv.anim)" } }, + { "set_anim_duration", { (const void*) &lv_style_set_anim_duration, "", "(lv.style)i" } }, + { "set_anim_time", { (const void*) &lv_style_set_anim_duration, "", "(lv.style)i" } }, + { "set_arc_color", { (const void*) &lv_style_set_arc_color, "", "(lv.style)(lv.color)" } }, + { "set_arc_image_src", { (const void*) &lv_style_set_arc_image_src, "", "(lv.style)." } }, + { "set_arc_opa", { (const void*) &lv_style_set_arc_opa, "", "(lv.style)i" } }, + { "set_arc_rounded", { (const void*) &lv_style_set_arc_rounded, "", "(lv.style)b" } }, + { "set_arc_width", { (const void*) &lv_style_set_arc_width, "", "(lv.style)i" } }, + { "set_base_dir", { (const void*) &lv_style_set_base_dir, "", "(lv.style)i" } }, + { "set_bg_color", { (const void*) &lv_style_set_bg_color, "", "(lv.style)(lv.color)" } }, + { "set_bg_grad", { (const void*) &lv_style_set_bg_grad, "", "(lv.style)(lv.grad_dsc)" } }, + { "set_bg_grad_color", { (const void*) &lv_style_set_bg_grad_color, "", "(lv.style)(lv.color)" } }, + { "set_bg_grad_dir", { (const void*) &lv_style_set_bg_grad_dir, "", "(lv.style)i" } }, + { "set_bg_grad_opa", { (const void*) &lv_style_set_bg_grad_opa, "", "(lv.style)i" } }, + { "set_bg_grad_stop", { (const void*) &lv_style_set_bg_grad_stop, "", "(lv.style)i" } }, + { "set_bg_image_opa", { (const void*) &lv_style_set_bg_image_opa, "", "(lv.style)i" } }, + { "set_bg_image_recolor", { (const void*) &lv_style_set_bg_image_recolor, "", "(lv.style)(lv.color)" } }, + { "set_bg_image_recolor_opa", { (const void*) &lv_style_set_bg_image_recolor_opa, "", "(lv.style)i" } }, + { "set_bg_image_src", { (const void*) &lv_style_set_bg_image_src, "", "(lv.style)." } }, + { "set_bg_image_tiled", { (const void*) &lv_style_set_bg_image_tiled, "", "(lv.style)b" } }, + { "set_bg_img_opa", { (const void*) &lv_style_set_bg_image_opa, "", "(lv.style)i" } }, + { "set_bg_img_recolor", { (const void*) &lv_style_set_bg_image_recolor, "", "(lv.style)(lv.color)" } }, + { "set_bg_img_recolor_opa", { (const void*) &lv_style_set_bg_image_recolor_opa, "", "(lv.style)i" } }, + { "set_bg_img_src", { (const void*) &lv_style_set_bg_image_src, "", "(lv.style)." } }, + { "set_bg_img_tiled", { (const void*) &lv_style_set_bg_image_tiled, "", "(lv.style)b" } }, + { "set_bg_main_opa", { (const void*) &lv_style_set_bg_main_opa, "", "(lv.style)i" } }, + { "set_bg_main_stop", { (const void*) &lv_style_set_bg_main_stop, "", "(lv.style)i" } }, + { "set_bg_opa", { (const void*) &lv_style_set_bg_opa, "", "(lv.style)i" } }, + { "set_blend_mode", { (const void*) &lv_style_set_blend_mode, "", "(lv.style)i" } }, + { "set_border_color", { (const void*) &lv_style_set_border_color, "", "(lv.style)(lv.color)" } }, + { "set_border_opa", { (const void*) &lv_style_set_border_opa, "", "(lv.style)i" } }, + { "set_border_post", { (const void*) &lv_style_set_border_post, "", "(lv.style)b" } }, + { "set_border_side", { (const void*) &lv_style_set_border_side, "", "(lv.style)i" } }, + { "set_border_width", { (const void*) &lv_style_set_border_width, "", "(lv.style)i" } }, + { "set_clip_corner", { (const void*) &lv_style_set_clip_corner, "", "(lv.style)b" } }, + { "set_color_filter_dsc", { (const void*) &lv_style_set_color_filter_dsc, "", "(lv.style)(lv.color_filter_dsc)" } }, + { "set_color_filter_opa", { (const void*) &lv_style_set_color_filter_opa, "", "(lv.style)i" } }, + { "set_flex_cross_place", { (const void*) &lv_style_set_flex_cross_place, "", "(lv.style)i" } }, + { "set_flex_flow", { (const void*) &lv_style_set_flex_flow, "", "(lv.style)i" } }, + { "set_flex_grow", { (const void*) &lv_style_set_flex_grow, "", "(lv.style)i" } }, + { "set_flex_main_place", { (const void*) &lv_style_set_flex_main_place, "", "(lv.style)i" } }, + { "set_flex_track_place", { (const void*) &lv_style_set_flex_track_place, "", "(lv.style)i" } }, + { "set_grid_cell_column_pos", { (const void*) &lv_style_set_grid_cell_column_pos, "", "(lv.style)i" } }, + { "set_grid_cell_column_span", { (const void*) &lv_style_set_grid_cell_column_span, "", "(lv.style)i" } }, + { "set_grid_cell_row_pos", { (const void*) &lv_style_set_grid_cell_row_pos, "", "(lv.style)i" } }, + { "set_grid_cell_row_span", { (const void*) &lv_style_set_grid_cell_row_span, "", "(lv.style)i" } }, + { "set_grid_cell_x_align", { (const void*) &lv_style_set_grid_cell_x_align, "", "(lv.style)i" } }, + { "set_grid_cell_y_align", { (const void*) &lv_style_set_grid_cell_y_align, "", "(lv.style)i" } }, + { "set_grid_column_align", { (const void*) &lv_style_set_grid_column_align, "", "(lv.style)i" } }, + { "set_grid_column_dsc_array", { (const void*) &lv_style_set_grid_column_dsc_array, "", "(lv.style)(lv.int_arr)" } }, + { "set_grid_row_align", { (const void*) &lv_style_set_grid_row_align, "", "(lv.style)i" } }, + { "set_grid_row_dsc_array", { (const void*) &lv_style_set_grid_row_dsc_array, "", "(lv.style)(lv.int_arr)" } }, + { "set_height", { (const void*) &lv_style_set_height, "", "(lv.style)i" } }, + { "set_image_opa", { (const void*) &lv_style_set_image_opa, "", "(lv.style)i" } }, + { "set_image_recolor", { (const void*) &lv_style_set_image_recolor, "", "(lv.style)(lv.color)" } }, + { "set_image_recolor_opa", { (const void*) &lv_style_set_image_recolor_opa, "", "(lv.style)i" } }, + { "set_img_opa", { (const void*) &lv_style_set_image_opa, "", "(lv.style)i" } }, + { "set_img_recolor", { (const void*) &lv_style_set_image_recolor, "", "(lv.style)(lv.color)" } }, + { "set_img_recolor_opa", { (const void*) &lv_style_set_image_recolor_opa, "", "(lv.style)i" } }, + { "set_layout", { (const void*) &lv_style_set_layout, "", "(lv.style)i" } }, + { "set_length", { (const void*) &lv_style_set_length, "", "(lv.style)i" } }, + { "set_line_color", { (const void*) &lv_style_set_line_color, "", "(lv.style)(lv.color)" } }, + { "set_line_dash_gap", { (const void*) &lv_style_set_line_dash_gap, "", "(lv.style)i" } }, + { "set_line_dash_width", { (const void*) &lv_style_set_line_dash_width, "", "(lv.style)i" } }, + { "set_line_opa", { (const void*) &lv_style_set_line_opa, "", "(lv.style)i" } }, + { "set_line_rounded", { (const void*) &lv_style_set_line_rounded, "", "(lv.style)b" } }, + { "set_line_width", { (const void*) &lv_style_set_line_width, "", "(lv.style)i" } }, + { "set_margin_bottom", { (const void*) &lv_style_set_margin_bottom, "", "(lv.style)i" } }, + { "set_margin_left", { (const void*) &lv_style_set_margin_left, "", "(lv.style)i" } }, + { "set_margin_right", { (const void*) &lv_style_set_margin_right, "", "(lv.style)i" } }, + { "set_margin_top", { (const void*) &lv_style_set_margin_top, "", "(lv.style)i" } }, + { "set_max_height", { (const void*) &lv_style_set_max_height, "", "(lv.style)i" } }, + { "set_max_width", { (const void*) &lv_style_set_max_width, "", "(lv.style)i" } }, + { "set_min_height", { (const void*) &lv_style_set_min_height, "", "(lv.style)i" } }, + { "set_min_width", { (const void*) &lv_style_set_min_width, "", "(lv.style)i" } }, + { "set_opa", { (const void*) &lv_style_set_opa, "", "(lv.style)i" } }, + { "set_opa_layered", { (const void*) &lv_style_set_opa_layered, "", "(lv.style)i" } }, + { "set_outline_color", { (const void*) &lv_style_set_outline_color, "", "(lv.style)(lv.color)" } }, + { "set_outline_opa", { (const void*) &lv_style_set_outline_opa, "", "(lv.style)i" } }, + { "set_outline_pad", { (const void*) &lv_style_set_outline_pad, "", "(lv.style)i" } }, + { "set_outline_width", { (const void*) &lv_style_set_outline_width, "", "(lv.style)i" } }, + { "set_pad_all", { (const void*) &lv_style_set_pad_all, "", "(lv.style)i" } }, + { "set_pad_bottom", { (const void*) &lv_style_set_pad_bottom, "", "(lv.style)i" } }, + { "set_pad_column", { (const void*) &lv_style_set_pad_column, "", "(lv.style)i" } }, + { "set_pad_gap", { (const void*) &lv_style_set_pad_gap, "", "(lv.style)i" } }, + { "set_pad_hor", { (const void*) &lv_style_set_pad_hor, "", "(lv.style)i" } }, + { "set_pad_left", { (const void*) &lv_style_set_pad_left, "", "(lv.style)i" } }, + { "set_pad_right", { (const void*) &lv_style_set_pad_right, "", "(lv.style)i" } }, + { "set_pad_row", { (const void*) &lv_style_set_pad_row, "", "(lv.style)i" } }, + { "set_pad_top", { (const void*) &lv_style_set_pad_top, "", "(lv.style)i" } }, + { "set_pad_ver", { (const void*) &lv_style_set_pad_ver, "", "(lv.style)i" } }, + { "set_prop", { (const void*) &lv_style_set_prop, "", "(lv.style)ii" } }, + { "set_radius", { (const void*) &lv_style_set_radius, "", "(lv.style)i" } }, + { "set_shadow_color", { (const void*) &lv_style_set_shadow_color, "", "(lv.style)(lv.color)" } }, + { "set_shadow_offset_x", { (const void*) &lv_style_set_shadow_offset_x, "", "(lv.style)i" } }, + { "set_shadow_offset_y", { (const void*) &lv_style_set_shadow_offset_y, "", "(lv.style)i" } }, + { "set_shadow_ofs_x", { (const void*) &lv_style_set_shadow_offset_x, "", "(lv.style)i" } }, + { "set_shadow_ofs_y", { (const void*) &lv_style_set_shadow_offset_y, "", "(lv.style)i" } }, + { "set_shadow_opa", { (const void*) &lv_style_set_shadow_opa, "", "(lv.style)i" } }, + { "set_shadow_spread", { (const void*) &lv_style_set_shadow_spread, "", "(lv.style)i" } }, + { "set_shadow_width", { (const void*) &lv_style_set_shadow_width, "", "(lv.style)i" } }, + { "set_size", { (const void*) &lv_style_set_size, "", "(lv.style)ii" } }, + { "set_text_align", { (const void*) &lv_style_set_text_align, "", "(lv.style)i" } }, + { "set_text_color", { (const void*) &lv_style_set_text_color, "", "(lv.style)(lv.color)" } }, + { "set_text_decor", { (const void*) &lv_style_set_text_decor, "", "(lv.style)i" } }, + { "set_text_font", { (const void*) &lv_style_set_text_font, "", "(lv.style)(lv.font)" } }, + { "set_text_letter_space", { (const void*) &lv_style_set_text_letter_space, "", "(lv.style)i" } }, + { "set_text_line_space", { (const void*) &lv_style_set_text_line_space, "", "(lv.style)i" } }, + { "set_text_opa", { (const void*) &lv_style_set_text_opa, "", "(lv.style)i" } }, + { "set_transform_angle", { (const void*) &lv_style_set_transform_rotation, "", "(lv.style)i" } }, + { "set_transform_height", { (const void*) &lv_style_set_transform_height, "", "(lv.style)i" } }, + { "set_transform_pivot_x", { (const void*) &lv_style_set_transform_pivot_x, "", "(lv.style)i" } }, + { "set_transform_pivot_y", { (const void*) &lv_style_set_transform_pivot_y, "", "(lv.style)i" } }, + { "set_transform_rotation", { (const void*) &lv_style_set_transform_rotation, "", "(lv.style)i" } }, + { "set_transform_scale", { (const void*) &lv_style_set_transform_scale, "", "(lv.style)i" } }, + { "set_transform_scale_x", { (const void*) &lv_style_set_transform_scale_x, "", "(lv.style)i" } }, + { "set_transform_scale_y", { (const void*) &lv_style_set_transform_scale_y, "", "(lv.style)i" } }, + { "set_transform_skew_x", { (const void*) &lv_style_set_transform_skew_x, "", "(lv.style)i" } }, + { "set_transform_skew_y", { (const void*) &lv_style_set_transform_skew_y, "", "(lv.style)i" } }, + { "set_transform_width", { (const void*) &lv_style_set_transform_width, "", "(lv.style)i" } }, + { "set_transform_zoom", { (const void*) &lv_style_set_transform_scale, "", "(lv.style)i" } }, + { "set_transition", { (const void*) &lv_style_set_transition, "", "(lv.style)(lv.style_transition_dsc)" } }, + { "set_translate_x", { (const void*) &lv_style_set_translate_x, "", "(lv.style)i" } }, + { "set_translate_y", { (const void*) &lv_style_set_translate_y, "", "(lv.style)i" } }, + { "set_width", { (const void*) &lv_style_set_width, "", "(lv.style)i" } }, + { "set_x", { (const void*) &lv_style_set_x, "", "(lv.style)i" } }, + { "set_y", { (const void*) &lv_style_set_y, "", "(lv.style)i" } }, }; /* `lv_font` methods */ @@ -138,872 +158,1081 @@ const be_ntv_func_def_t lv_color_func[] = { const be_ntv_func_def_t lv_theme_func[] = { }; -/* `lv_img` methods */ -#ifdef BE_LV_WIDGET_IMG -const be_ntv_func_def_t lv_img_func[] = { - { "get_angle", { (const void*) &lv_img_get_angle, "i", "(lv.lv_obj)" } }, - { "get_antialias", { (const void*) &lv_img_get_antialias, "b", "(lv.lv_obj)" } }, - { "get_offset_x", { (const void*) &lv_img_get_offset_x, "i", "(lv.lv_obj)" } }, - { "get_offset_y", { (const void*) &lv_img_get_offset_y, "i", "(lv.lv_obj)" } }, - { "get_pivot", { (const void*) &lv_img_get_pivot, "", "(lv.lv_obj)(lv.lv_point)" } }, - { "get_size_mode", { (const void*) &lv_img_get_size_mode, "i", "(lv.lv_obj)" } }, - { "get_src", { (const void*) &lv_img_get_src, ".", "(lv.lv_obj)" } }, - { "get_zoom", { (const void*) &lv_img_get_zoom, "i", "(lv.lv_obj)" } }, - { "set_angle", { (const void*) &lv_img_set_angle, "", "(lv.lv_obj)i" } }, - { "set_antialias", { (const void*) &lv_img_set_antialias, "", "(lv.lv_obj)b" } }, - { "set_offset_x", { (const void*) &lv_img_set_offset_x, "", "(lv.lv_obj)i" } }, - { "set_offset_y", { (const void*) &lv_img_set_offset_y, "", "(lv.lv_obj)i" } }, - { "set_pivot", { (const void*) &lv_img_set_pivot, "", "(lv.lv_obj)ii" } }, - { "set_size_mode", { (const void*) &lv_img_set_size_mode, "", "(lv.lv_obj)i" } }, - { "set_src", { (const void*) &lv_img_set_src, "", "(lv.lv_obj)." } }, - { "set_tasmota_logo", { (const void*) &lv_img_set_tasmota_logo, "", "(lv.lv_obj)" } }, - { "set_zoom", { (const void*) &lv_img_set_zoom, "", "(lv.lv_obj)i" } }, -}; -#endif // BE_LV_WIDGET_IMG - -/* `lv_disp` methods */ -const be_ntv_func_def_t lv_disp_func[] = { - { "clean_dcache", { (const void*) &lv_disp_clean_dcache, "", "(lv.lv_disp)" } }, - { "dpx", { (const void*) &lv_disp_dpx, "i", "(lv.lv_disp)i" } }, - { "enable_invalidation", { (const void*) &lv_disp_enable_invalidation, "", "(lv.lv_disp)b" } }, - { "get_inactive_time", { (const void*) &lv_disp_get_inactive_time, "i", "(lv.lv_disp)" } }, - { "get_layer_sys", { (const void*) &lv_disp_get_layer_sys, "lv.lv_obj", "(lv.lv_disp)" } }, - { "get_layer_top", { (const void*) &lv_disp_get_layer_top, "lv.lv_obj", "(lv.lv_disp)" } }, - { "get_scr_act", { (const void*) &lv_disp_get_scr_act, "lv.lv_obj", "(lv.lv_disp)" } }, - { "get_scr_prev", { (const void*) &lv_disp_get_scr_prev, "lv.lv_obj", "(lv.lv_disp)" } }, - { "get_theme", { (const void*) &lv_disp_get_theme, "lv.lv_theme", "(lv.lv_disp)" } }, - { "is_invalidation_enabled", { (const void*) &lv_disp_is_invalidation_enabled, "b", "(lv.lv_disp)" } }, - { "load_scr", { (const void*) &lv_disp_load_scr, "", "(lv.lv_obj)" } }, - { "set_bg_color", { (const void*) &lv_disp_set_bg_color, "", "(lv.lv_disp)(lv.lv_color)" } }, - { "set_bg_image", { (const void*) &lv_disp_set_bg_image, "", "(lv.lv_disp)." } }, - { "set_bg_opa", { (const void*) &lv_disp_set_bg_opa, "", "(lv.lv_disp)i" } }, - { "set_theme", { (const void*) &lv_disp_set_theme, "", "(lv.lv_disp)(lv.lv_theme)" } }, - { "trig_activity", { (const void*) &lv_disp_trig_activity, "", "(lv.lv_disp)" } }, -}; - -/* `lv_obj` methods */ -const be_ntv_func_def_t lv_obj_func[] = { - { "add_event_cb", { (const void*) &lv_obj_add_event_cb, "c", "(lv.lv_obj)^lv_event_cb^i." } }, - { "add_flag", { (const void*) &lv_obj_add_flag, "", "(lv.lv_obj)i" } }, - { "add_state", { (const void*) &lv_obj_add_state, "", "(lv.lv_obj)i" } }, - { "add_style", { (const void*) &lv_obj_add_style, "", "(lv.lv_obj)(lv.lv_style)i" } }, - { "align", { (const void*) &lv_obj_align, "", "(lv.lv_obj)iii" } }, - { "align_to", { (const void*) &lv_obj_align_to, "", "(lv.lv_obj)(lv.lv_obj)iii" } }, - { "allocate_spec_attr", { (const void*) &lv_obj_allocate_spec_attr, "", "(lv.lv_obj)" } }, - { "area_is_visible", { (const void*) &lv_obj_area_is_visible, "b", "(lv.lv_obj)(lv.lv_area)" } }, - { "calculate_ext_draw_size", { (const void*) &lv_obj_calculate_ext_draw_size, "i", "(lv.lv_obj)i" } }, - { "calculate_style_text_align", { (const void*) &lv_obj_calculate_style_text_align, "i", "(lv.lv_obj)is" } }, - { "center", { (const void*) &lv_obj_center, "", "(lv.lv_obj)" } }, - { "check_type", { (const void*) &lv_obj_check_type, "b", "(lv.lv_obj)(lv.lv_obj_class)" } }, - { "class_init_obj", { (const void*) &lv_obj_class_init_obj, "", "(lv.lv_obj)" } }, - { "clean", { (const void*) &lv_obj_clean, "", "(lv.lv_obj)" } }, - { "clear_flag", { (const void*) &lv_obj_clear_flag, "", "(lv.lv_obj)i" } }, - { "clear_state", { (const void*) &lv_obj_clear_state, "", "(lv.lv_obj)i" } }, - { "del", { (const void*) &lv_obj_del, "", "(lv.lv_obj)" } }, - { "del_async", { (const void*) &lv_obj_del_async, "", "(lv.lv_obj)" } }, - { "del_delayed", { (const void*) &lv_obj_del_delayed, "", "(lv.lv_obj)i" } }, - { "dpx", { (const void*) &lv_obj_dpx, "i", "(lv.lv_obj)i" } }, - { "fade_in", { (const void*) &lv_obj_fade_in, "", "(lv.lv_obj)ii" } }, - { "fade_out", { (const void*) &lv_obj_fade_out, "", "(lv.lv_obj)ii" } }, - { "get_child", { (const void*) &lv_obj_get_child, "lv.lv_obj", "(lv.lv_obj)i" } }, - { "get_child_cnt", { (const void*) &lv_obj_get_child_cnt, "i", "(lv.lv_obj)" } }, - { "get_child_id", { (const void*) &lv_obj_get_child_id, "i", "(lv.lv_obj)" } }, - { "get_class", { (const void*) &lv_obj_get_class, "lv.lv_obj_class", "(lv.lv_obj)" } }, - { "get_click_area", { (const void*) &lv_obj_get_click_area, "", "(lv.lv_obj)(lv.lv_area)" } }, - { "get_content_coords", { (const void*) &lv_obj_get_content_coords, "", "(lv.lv_obj)(lv.lv_area)" } }, - { "get_content_height", { (const void*) &lv_obj_get_content_height, "i", "(lv.lv_obj)" } }, - { "get_content_width", { (const void*) &lv_obj_get_content_width, "i", "(lv.lv_obj)" } }, - { "get_coords", { (const void*) &lv_obj_get_coords, "", "(lv.lv_obj)(lv.lv_area)" } }, - { "get_disp", { (const void*) &lv_obj_get_disp, "lv.lv_disp", "(lv.lv_obj)" } }, - { "get_event_user_data", { (const void*) &lv_obj_get_event_user_data, ".", "(lv.lv_obj)^lv_event_cb^" } }, - { "get_group", { (const void*) &lv_obj_get_group, ".", "(lv.lv_obj)" } }, - { "get_height", { (const void*) &lv_obj_get_height, "i", "(lv.lv_obj)" } }, - { "get_index", { (const void*) &lv_obj_get_index, "i", "(lv.lv_obj)" } }, - { "get_local_style_prop", { (const void*) &lv_obj_get_local_style_prop, "i", "(lv.lv_obj)i(lv.lv_style_value)i" } }, - { "get_parent", { (const void*) &lv_obj_get_parent, "lv.lv_obj", "(lv.lv_obj)" } }, - { "get_screen", { (const void*) &lv_obj_get_screen, "lv.lv_obj", "(lv.lv_obj)" } }, - { "get_scroll_bottom", { (const void*) &lv_obj_get_scroll_bottom, "i", "(lv.lv_obj)" } }, - { "get_scroll_dir", { (const void*) &lv_obj_get_scroll_dir, "i", "(lv.lv_obj)" } }, - { "get_scroll_end", { (const void*) &lv_obj_get_scroll_end, "", "(lv.lv_obj)(lv.lv_point)" } }, - { "get_scroll_left", { (const void*) &lv_obj_get_scroll_left, "i", "(lv.lv_obj)" } }, - { "get_scroll_right", { (const void*) &lv_obj_get_scroll_right, "i", "(lv.lv_obj)" } }, - { "get_scroll_snap_x", { (const void*) &lv_obj_get_scroll_snap_x, "i", "(lv.lv_obj)" } }, - { "get_scroll_snap_y", { (const void*) &lv_obj_get_scroll_snap_y, "i", "(lv.lv_obj)" } }, - { "get_scroll_top", { (const void*) &lv_obj_get_scroll_top, "i", "(lv.lv_obj)" } }, - { "get_scroll_x", { (const void*) &lv_obj_get_scroll_x, "i", "(lv.lv_obj)" } }, - { "get_scroll_y", { (const void*) &lv_obj_get_scroll_y, "i", "(lv.lv_obj)" } }, - { "get_scrollbar_area", { (const void*) &lv_obj_get_scrollbar_area, "", "(lv.lv_obj)(lv.lv_area)(lv.lv_area)" } }, - { "get_scrollbar_mode", { (const void*) &lv_obj_get_scrollbar_mode, "i", "(lv.lv_obj)" } }, - { "get_self_height", { (const void*) &lv_obj_get_self_height, "i", "(lv.lv_obj)" } }, - { "get_self_width", { (const void*) &lv_obj_get_self_width, "i", "(lv.lv_obj)" } }, - { "get_state", { (const void*) &lv_obj_get_state, "i", "(lv.lv_obj)" } }, - { "get_style_align", { (const void*) &lv_obj_get_style_align, "i", "(lv.lv_obj)i" } }, - { "get_style_anim", { (const void*) &lv_obj_get_style_anim, "lv.lv_anim", "(lv.lv_obj)i" } }, - { "get_style_anim_speed", { (const void*) &lv_obj_get_style_anim_speed, "i", "(lv.lv_obj)i" } }, - { "get_style_anim_time", { (const void*) &lv_obj_get_style_anim_time, "i", "(lv.lv_obj)i" } }, - { "get_style_arc_color", { (const void*) &lv_obj_get_style_arc_color, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_arc_color_filtered", { (const void*) &lv_obj_get_style_arc_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_arc_img_src", { (const void*) &lv_obj_get_style_arc_img_src, ".", "(lv.lv_obj)i" } }, - { "get_style_arc_opa", { (const void*) &lv_obj_get_style_arc_opa, "i", "(lv.lv_obj)i" } }, - { "get_style_arc_rounded", { (const void*) &lv_obj_get_style_arc_rounded, "b", "(lv.lv_obj)i" } }, - { "get_style_arc_width", { (const void*) &lv_obj_get_style_arc_width, "i", "(lv.lv_obj)i" } }, - { "get_style_base_dir", { (const void*) &lv_obj_get_style_base_dir, "i", "(lv.lv_obj)i" } }, - { "get_style_bg_color", { (const void*) &lv_obj_get_style_bg_color, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_bg_color_filtered", { (const void*) &lv_obj_get_style_bg_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_bg_dither_mode", { (const void*) &lv_obj_get_style_bg_dither_mode, "i", "(lv.lv_obj)i" } }, - { "get_style_bg_grad", { (const void*) &lv_obj_get_style_bg_grad, "lv.lv_grad_dsc", "(lv.lv_obj)i" } }, - { "get_style_bg_grad_color", { (const void*) &lv_obj_get_style_bg_grad_color, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_bg_grad_color_filtered", { (const void*) &lv_obj_get_style_bg_grad_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_bg_grad_dir", { (const void*) &lv_obj_get_style_bg_grad_dir, "i", "(lv.lv_obj)i" } }, - { "get_style_bg_grad_stop", { (const void*) &lv_obj_get_style_bg_grad_stop, "i", "(lv.lv_obj)i" } }, - { "get_style_bg_img_opa", { (const void*) &lv_obj_get_style_bg_img_opa, "i", "(lv.lv_obj)i" } }, - { "get_style_bg_img_recolor", { (const void*) &lv_obj_get_style_bg_img_recolor, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_bg_img_recolor_filtered", { (const void*) &lv_obj_get_style_bg_img_recolor_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_bg_img_recolor_opa", { (const void*) &lv_obj_get_style_bg_img_recolor_opa, "i", "(lv.lv_obj)i" } }, - { "get_style_bg_img_src", { (const void*) &lv_obj_get_style_bg_img_src, ".", "(lv.lv_obj)i" } }, - { "get_style_bg_img_tiled", { (const void*) &lv_obj_get_style_bg_img_tiled, "b", "(lv.lv_obj)i" } }, - { "get_style_bg_main_stop", { (const void*) &lv_obj_get_style_bg_main_stop, "i", "(lv.lv_obj)i" } }, - { "get_style_bg_opa", { (const void*) &lv_obj_get_style_bg_opa, "i", "(lv.lv_obj)i" } }, - { "get_style_blend_mode", { (const void*) &lv_obj_get_style_blend_mode, "i", "(lv.lv_obj)i" } }, - { "get_style_border_color", { (const void*) &lv_obj_get_style_border_color, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_border_color_filtered", { (const void*) &lv_obj_get_style_border_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_border_opa", { (const void*) &lv_obj_get_style_border_opa, "i", "(lv.lv_obj)i" } }, - { "get_style_border_post", { (const void*) &lv_obj_get_style_border_post, "b", "(lv.lv_obj)i" } }, - { "get_style_border_side", { (const void*) &lv_obj_get_style_border_side, "i", "(lv.lv_obj)i" } }, - { "get_style_border_width", { (const void*) &lv_obj_get_style_border_width, "i", "(lv.lv_obj)i" } }, - { "get_style_clip_corner", { (const void*) &lv_obj_get_style_clip_corner, "b", "(lv.lv_obj)i" } }, - { "get_style_color_filter_dsc", { (const void*) &lv_obj_get_style_color_filter_dsc, "lv.lv_color_filter_dsc", "(lv.lv_obj)i" } }, - { "get_style_color_filter_opa", { (const void*) &lv_obj_get_style_color_filter_opa, "i", "(lv.lv_obj)i" } }, - { "get_style_flex_cross_place", { (const void*) &lv_obj_get_style_flex_cross_place, "i", "(lv.lv_obj)i" } }, - { "get_style_flex_flow", { (const void*) &lv_obj_get_style_flex_flow, "i", "(lv.lv_obj)i" } }, - { "get_style_flex_grow", { (const void*) &lv_obj_get_style_flex_grow, "i", "(lv.lv_obj)i" } }, - { "get_style_flex_main_place", { (const void*) &lv_obj_get_style_flex_main_place, "i", "(lv.lv_obj)i" } }, - { "get_style_flex_track_place", { (const void*) &lv_obj_get_style_flex_track_place, "i", "(lv.lv_obj)i" } }, - { "get_style_grid_cell_column_pos", { (const void*) &lv_obj_get_style_grid_cell_column_pos, "i", "(lv.lv_obj)i" } }, - { "get_style_grid_cell_column_span", { (const void*) &lv_obj_get_style_grid_cell_column_span, "i", "(lv.lv_obj)i" } }, - { "get_style_grid_cell_row_pos", { (const void*) &lv_obj_get_style_grid_cell_row_pos, "i", "(lv.lv_obj)i" } }, - { "get_style_grid_cell_row_span", { (const void*) &lv_obj_get_style_grid_cell_row_span, "i", "(lv.lv_obj)i" } }, - { "get_style_grid_cell_x_align", { (const void*) &lv_obj_get_style_grid_cell_x_align, "i", "(lv.lv_obj)i" } }, - { "get_style_grid_cell_y_align", { (const void*) &lv_obj_get_style_grid_cell_y_align, "i", "(lv.lv_obj)i" } }, - { "get_style_grid_column_align", { (const void*) &lv_obj_get_style_grid_column_align, "i", "(lv.lv_obj)i" } }, - { "get_style_grid_column_dsc_array", { (const void*) &lv_obj_get_style_grid_column_dsc_array, "c", "(lv.lv_obj)i" } }, - { "get_style_grid_row_align", { (const void*) &lv_obj_get_style_grid_row_align, "i", "(lv.lv_obj)i" } }, - { "get_style_grid_row_dsc_array", { (const void*) &lv_obj_get_style_grid_row_dsc_array, "c", "(lv.lv_obj)i" } }, - { "get_style_height", { (const void*) &lv_obj_get_style_height, "i", "(lv.lv_obj)i" } }, - { "get_style_img_opa", { (const void*) &lv_obj_get_style_img_opa, "i", "(lv.lv_obj)i" } }, - { "get_style_img_recolor", { (const void*) &lv_obj_get_style_img_recolor, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_img_recolor_filtered", { (const void*) &lv_obj_get_style_img_recolor_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_img_recolor_opa", { (const void*) &lv_obj_get_style_img_recolor_opa, "i", "(lv.lv_obj)i" } }, - { "get_style_layout", { (const void*) &lv_obj_get_style_layout, "i", "(lv.lv_obj)i" } }, - { "get_style_line_color", { (const void*) &lv_obj_get_style_line_color, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_line_color_filtered", { (const void*) &lv_obj_get_style_line_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_line_dash_gap", { (const void*) &lv_obj_get_style_line_dash_gap, "i", "(lv.lv_obj)i" } }, - { "get_style_line_dash_width", { (const void*) &lv_obj_get_style_line_dash_width, "i", "(lv.lv_obj)i" } }, - { "get_style_line_opa", { (const void*) &lv_obj_get_style_line_opa, "i", "(lv.lv_obj)i" } }, - { "get_style_line_rounded", { (const void*) &lv_obj_get_style_line_rounded, "b", "(lv.lv_obj)i" } }, - { "get_style_line_width", { (const void*) &lv_obj_get_style_line_width, "i", "(lv.lv_obj)i" } }, - { "get_style_max_height", { (const void*) &lv_obj_get_style_max_height, "i", "(lv.lv_obj)i" } }, - { "get_style_max_width", { (const void*) &lv_obj_get_style_max_width, "i", "(lv.lv_obj)i" } }, - { "get_style_min_height", { (const void*) &lv_obj_get_style_min_height, "i", "(lv.lv_obj)i" } }, - { "get_style_min_width", { (const void*) &lv_obj_get_style_min_width, "i", "(lv.lv_obj)i" } }, - { "get_style_opa", { (const void*) &lv_obj_get_style_opa, "i", "(lv.lv_obj)i" } }, - { "get_style_opa_layered", { (const void*) &lv_obj_get_style_opa_layered, "i", "(lv.lv_obj)i" } }, - { "get_style_opa_recursive", { (const void*) &lv_obj_get_style_opa_recursive, "i", "(lv.lv_obj)i" } }, - { "get_style_outline_color", { (const void*) &lv_obj_get_style_outline_color, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_outline_color_filtered", { (const void*) &lv_obj_get_style_outline_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_outline_opa", { (const void*) &lv_obj_get_style_outline_opa, "i", "(lv.lv_obj)i" } }, - { "get_style_outline_pad", { (const void*) &lv_obj_get_style_outline_pad, "i", "(lv.lv_obj)i" } }, - { "get_style_outline_width", { (const void*) &lv_obj_get_style_outline_width, "i", "(lv.lv_obj)i" } }, - { "get_style_pad_bottom", { (const void*) &lv_obj_get_style_pad_bottom, "i", "(lv.lv_obj)i" } }, - { "get_style_pad_column", { (const void*) &lv_obj_get_style_pad_column, "i", "(lv.lv_obj)i" } }, - { "get_style_pad_left", { (const void*) &lv_obj_get_style_pad_left, "i", "(lv.lv_obj)i" } }, - { "get_style_pad_right", { (const void*) &lv_obj_get_style_pad_right, "i", "(lv.lv_obj)i" } }, - { "get_style_pad_row", { (const void*) &lv_obj_get_style_pad_row, "i", "(lv.lv_obj)i" } }, - { "get_style_pad_top", { (const void*) &lv_obj_get_style_pad_top, "i", "(lv.lv_obj)i" } }, - { "get_style_prop", { (const void*) &lv_obj_get_style_prop, "i", "(lv.lv_obj)ii" } }, - { "get_style_radius", { (const void*) &lv_obj_get_style_radius, "i", "(lv.lv_obj)i" } }, - { "get_style_shadow_color", { (const void*) &lv_obj_get_style_shadow_color, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_shadow_color_filtered", { (const void*) &lv_obj_get_style_shadow_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_shadow_ofs_x", { (const void*) &lv_obj_get_style_shadow_ofs_x, "i", "(lv.lv_obj)i" } }, - { "get_style_shadow_ofs_y", { (const void*) &lv_obj_get_style_shadow_ofs_y, "i", "(lv.lv_obj)i" } }, - { "get_style_shadow_opa", { (const void*) &lv_obj_get_style_shadow_opa, "i", "(lv.lv_obj)i" } }, - { "get_style_shadow_spread", { (const void*) &lv_obj_get_style_shadow_spread, "i", "(lv.lv_obj)i" } }, - { "get_style_shadow_width", { (const void*) &lv_obj_get_style_shadow_width, "i", "(lv.lv_obj)i" } }, - { "get_style_text_align", { (const void*) &lv_obj_get_style_text_align, "i", "(lv.lv_obj)i" } }, - { "get_style_text_color", { (const void*) &lv_obj_get_style_text_color, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_text_color_filtered", { (const void*) &lv_obj_get_style_text_color_filtered, "lv.lv_color", "(lv.lv_obj)i" } }, - { "get_style_text_decor", { (const void*) &lv_obj_get_style_text_decor, "i", "(lv.lv_obj)i" } }, - { "get_style_text_font", { (const void*) &lv_obj_get_style_text_font, "lv.lv_font", "(lv.lv_obj)i" } }, - { "get_style_text_letter_space", { (const void*) &lv_obj_get_style_text_letter_space, "i", "(lv.lv_obj)i" } }, - { "get_style_text_line_space", { (const void*) &lv_obj_get_style_text_line_space, "i", "(lv.lv_obj)i" } }, - { "get_style_text_opa", { (const void*) &lv_obj_get_style_text_opa, "i", "(lv.lv_obj)i" } }, - { "get_style_transform_angle", { (const void*) &lv_obj_get_style_transform_angle, "i", "(lv.lv_obj)i" } }, - { "get_style_transform_height", { (const void*) &lv_obj_get_style_transform_height, "i", "(lv.lv_obj)i" } }, - { "get_style_transform_pivot_x", { (const void*) &lv_obj_get_style_transform_pivot_x, "i", "(lv.lv_obj)i" } }, - { "get_style_transform_pivot_y", { (const void*) &lv_obj_get_style_transform_pivot_y, "i", "(lv.lv_obj)i" } }, - { "get_style_transform_width", { (const void*) &lv_obj_get_style_transform_width, "i", "(lv.lv_obj)i" } }, - { "get_style_transform_zoom", { (const void*) &lv_obj_get_style_transform_zoom, "i", "(lv.lv_obj)i" } }, - { "get_style_transform_zoom_safe", { (const void*) &lv_obj_get_style_transform_zoom_safe, "i", "(lv.lv_obj)i" } }, - { "get_style_transition", { (const void*) &lv_obj_get_style_transition, "lv.lv_style_transition_dsc", "(lv.lv_obj)i" } }, - { "get_style_translate_x", { (const void*) &lv_obj_get_style_translate_x, "i", "(lv.lv_obj)i" } }, - { "get_style_translate_y", { (const void*) &lv_obj_get_style_translate_y, "i", "(lv.lv_obj)i" } }, - { "get_style_width", { (const void*) &lv_obj_get_style_width, "i", "(lv.lv_obj)i" } }, - { "get_style_x", { (const void*) &lv_obj_get_style_x, "i", "(lv.lv_obj)i" } }, - { "get_style_y", { (const void*) &lv_obj_get_style_y, "i", "(lv.lv_obj)i" } }, - { "get_transformed_area", { (const void*) &lv_obj_get_transformed_area, "", "(lv.lv_obj)(lv.lv_area)bb" } }, - { "get_user_data", { (const void*) &lv_obj_get_user_data, ".", "(lv.lv_obj)" } }, - { "get_width", { (const void*) &lv_obj_get_width, "i", "(lv.lv_obj)" } }, - { "get_x", { (const void*) &lv_obj_get_x, "i", "(lv.lv_obj)" } }, - { "get_x2", { (const void*) &lv_obj_get_x2, "i", "(lv.lv_obj)" } }, - { "get_x_aligned", { (const void*) &lv_obj_get_x_aligned, "i", "(lv.lv_obj)" } }, - { "get_y", { (const void*) &lv_obj_get_y, "i", "(lv.lv_obj)" } }, - { "get_y2", { (const void*) &lv_obj_get_y2, "i", "(lv.lv_obj)" } }, - { "get_y_aligned", { (const void*) &lv_obj_get_y_aligned, "i", "(lv.lv_obj)" } }, - { "has_class", { (const void*) &lv_obj_has_class, "b", "(lv.lv_obj)(lv.lv_obj_class)" } }, - { "has_flag", { (const void*) &lv_obj_has_flag, "b", "(lv.lv_obj)i" } }, - { "has_flag_any", { (const void*) &lv_obj_has_flag_any, "b", "(lv.lv_obj)i" } }, - { "has_state", { (const void*) &lv_obj_has_state, "b", "(lv.lv_obj)i" } }, - { "hit_test", { (const void*) &lv_obj_hit_test, "b", "(lv.lv_obj)(lv.lv_point)" } }, - { "init_draw_arc_dsc", { (const void*) &lv_obj_init_draw_arc_dsc, "", "(lv.lv_obj)i(lv.lv_draw_arc_dsc)" } }, - { "init_draw_img_dsc", { (const void*) &lv_obj_init_draw_img_dsc, "", "(lv.lv_obj)i(lv.lv_draw_img_dsc)" } }, - { "init_draw_label_dsc", { (const void*) &lv_obj_init_draw_label_dsc, "", "(lv.lv_obj)i(lv.lv_draw_label_dsc)" } }, - { "init_draw_line_dsc", { (const void*) &lv_obj_init_draw_line_dsc, "", "(lv.lv_obj)i(lv.lv_draw_line_dsc)" } }, - { "init_draw_rect_dsc", { (const void*) &lv_obj_init_draw_rect_dsc, "", "(lv.lv_obj)i(lv.lv_draw_rect_dsc)" } }, - { "invalidate", { (const void*) &lv_obj_invalidate, "", "(lv.lv_obj)" } }, - { "invalidate_area", { (const void*) &lv_obj_invalidate_area, "", "(lv.lv_obj)(lv.lv_area)" } }, - { "is_editable", { (const void*) &lv_obj_is_editable, "b", "(lv.lv_obj)" } }, - { "is_group_def", { (const void*) &lv_obj_is_group_def, "b", "(lv.lv_obj)" } }, - { "is_layout_positioned", { (const void*) &lv_obj_is_layout_positioned, "b", "(lv.lv_obj)" } }, - { "is_scrolling", { (const void*) &lv_obj_is_scrolling, "b", "(lv.lv_obj)" } }, - { "is_valid", { (const void*) &lv_obj_is_valid, "b", "(lv.lv_obj)" } }, - { "is_visible", { (const void*) &lv_obj_is_visible, "b", "(lv.lv_obj)" } }, - { "mark_layout_as_dirty", { (const void*) &lv_obj_mark_layout_as_dirty, "", "(lv.lv_obj)" } }, - { "move_background", { (const void*) &lv_obj_move_background, "", "(lv.lv_obj)" } }, - { "move_children_by", { (const void*) &lv_obj_move_children_by, "", "(lv.lv_obj)iib" } }, - { "move_foreground", { (const void*) &lv_obj_move_foreground, "", "(lv.lv_obj)" } }, - { "move_to", { (const void*) &lv_obj_move_to, "", "(lv.lv_obj)ii" } }, - { "move_to_index", { (const void*) &lv_obj_move_to_index, "", "(lv.lv_obj)i" } }, - { "readjust_scroll", { (const void*) &lv_obj_readjust_scroll, "", "(lv.lv_obj)i" } }, - { "refr_pos", { (const void*) &lv_obj_refr_pos, "", "(lv.lv_obj)" } }, - { "refr_size", { (const void*) &lv_obj_refr_size, "b", "(lv.lv_obj)" } }, - { "refresh_ext_draw_size", { (const void*) &lv_obj_refresh_ext_draw_size, "", "(lv.lv_obj)" } }, - { "refresh_self_size", { (const void*) &lv_obj_refresh_self_size, "b", "(lv.lv_obj)" } }, - { "refresh_style", { (const void*) &lv_obj_refresh_style, "", "(lv.lv_obj)ii" } }, - { "remove_event_cb", { (const void*) &lv_obj_remove_event_cb, "b", "(lv.lv_obj)." } }, - { "remove_event_cb_with_user_data", { (const void*) &lv_obj_remove_event_cb_with_user_data, "b", "(lv.lv_obj).." } }, - { "remove_event_dsc", { (const void*) &lv_obj_remove_event_dsc, "b", "(lv.lv_obj)c" } }, - { "remove_local_style_prop", { (const void*) &lv_obj_remove_local_style_prop, "b", "(lv.lv_obj)ii" } }, - { "remove_style", { (const void*) &lv_obj_remove_style, "", "(lv.lv_obj)(lv.lv_style)i" } }, - { "remove_style_all", { (const void*) &lv_obj_remove_style_all, "", "(lv.lv_obj)" } }, - { "scroll_by", { (const void*) &lv_obj_scroll_by, "", "(lv.lv_obj)iii" } }, - { "scroll_by_bounded", { (const void*) &lv_obj_scroll_by_bounded, "", "(lv.lv_obj)iii" } }, - { "scroll_to", { (const void*) &lv_obj_scroll_to, "", "(lv.lv_obj)iii" } }, - { "scroll_to_view", { (const void*) &lv_obj_scroll_to_view, "", "(lv.lv_obj)i" } }, - { "scroll_to_view_recursive", { (const void*) &lv_obj_scroll_to_view_recursive, "", "(lv.lv_obj)i" } }, - { "scroll_to_x", { (const void*) &lv_obj_scroll_to_x, "", "(lv.lv_obj)ii" } }, - { "scroll_to_y", { (const void*) &lv_obj_scroll_to_y, "", "(lv.lv_obj)ii" } }, - { "scrollbar_invalidate", { (const void*) &lv_obj_scrollbar_invalidate, "", "(lv.lv_obj)" } }, - { "set_align", { (const void*) &lv_obj_set_align, "", "(lv.lv_obj)i" } }, - { "set_content_height", { (const void*) &lv_obj_set_content_height, "", "(lv.lv_obj)i" } }, - { "set_content_width", { (const void*) &lv_obj_set_content_width, "", "(lv.lv_obj)i" } }, - { "set_ext_click_area", { (const void*) &lv_obj_set_ext_click_area, "", "(lv.lv_obj)i" } }, - { "set_flex_align", { (const void*) &lv_obj_set_flex_align, "", "(lv.lv_obj)iii" } }, - { "set_flex_flow", { (const void*) &lv_obj_set_flex_flow, "", "(lv.lv_obj)i" } }, - { "set_flex_grow", { (const void*) &lv_obj_set_flex_grow, "", "(lv.lv_obj)i" } }, - { "set_grid_align", { (const void*) &lv_obj_set_grid_align, "", "(lv.lv_obj)ii" } }, - { "set_grid_cell", { (const void*) &lv_obj_set_grid_cell, "", "(lv.lv_obj)iiiiii" } }, - { "set_grid_dsc_array", { (const void*) &lv_obj_set_grid_dsc_array, "", "(lv.lv_obj)(lv.lv_coord_arr)(lv.lv_coord_arr)" } }, - { "set_height", { (const void*) &lv_obj_set_height, "", "(lv.lv_obj)i" } }, - { "set_layout", { (const void*) &lv_obj_set_layout, "", "(lv.lv_obj)i" } }, - { "set_local_style_prop", { (const void*) &lv_obj_set_local_style_prop, "", "(lv.lv_obj)iii" } }, - { "set_local_style_prop_meta", { (const void*) &lv_obj_set_local_style_prop_meta, "", "(lv.lv_obj)iii" } }, - { "set_parent", { (const void*) &lv_obj_set_parent, "", "(lv.lv_obj)(lv.lv_obj)" } }, - { "set_pos", { (const void*) &lv_obj_set_pos, "", "(lv.lv_obj)ii" } }, - { "set_scroll_dir", { (const void*) &lv_obj_set_scroll_dir, "", "(lv.lv_obj)i" } }, - { "set_scroll_snap_x", { (const void*) &lv_obj_set_scroll_snap_x, "", "(lv.lv_obj)i" } }, - { "set_scroll_snap_y", { (const void*) &lv_obj_set_scroll_snap_y, "", "(lv.lv_obj)i" } }, - { "set_scrollbar_mode", { (const void*) &lv_obj_set_scrollbar_mode, "", "(lv.lv_obj)i" } }, - { "set_size", { (const void*) &lv_obj_set_size, "", "(lv.lv_obj)ii" } }, - { "set_style_align", { (const void*) &lv_obj_set_style_align, "", "(lv.lv_obj)ii" } }, - { "set_style_anim", { (const void*) &lv_obj_set_style_anim, "", "(lv.lv_obj)(lv.lv_anim)i" } }, - { "set_style_anim_speed", { (const void*) &lv_obj_set_style_anim_speed, "", "(lv.lv_obj)ii" } }, - { "set_style_anim_time", { (const void*) &lv_obj_set_style_anim_time, "", "(lv.lv_obj)ii" } }, - { "set_style_arc_color", { (const void*) &lv_obj_set_style_arc_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_arc_img_src", { (const void*) &lv_obj_set_style_arc_img_src, "", "(lv.lv_obj).i" } }, - { "set_style_arc_opa", { (const void*) &lv_obj_set_style_arc_opa, "", "(lv.lv_obj)ii" } }, - { "set_style_arc_rounded", { (const void*) &lv_obj_set_style_arc_rounded, "", "(lv.lv_obj)bi" } }, - { "set_style_arc_width", { (const void*) &lv_obj_set_style_arc_width, "", "(lv.lv_obj)ii" } }, - { "set_style_base_dir", { (const void*) &lv_obj_set_style_base_dir, "", "(lv.lv_obj)ii" } }, - { "set_style_bg_color", { (const void*) &lv_obj_set_style_bg_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_bg_dither_mode", { (const void*) &lv_obj_set_style_bg_dither_mode, "", "(lv.lv_obj)ii" } }, - { "set_style_bg_grad", { (const void*) &lv_obj_set_style_bg_grad, "", "(lv.lv_obj)(lv.lv_grad_dsc)i" } }, - { "set_style_bg_grad_color", { (const void*) &lv_obj_set_style_bg_grad_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_bg_grad_dir", { (const void*) &lv_obj_set_style_bg_grad_dir, "", "(lv.lv_obj)ii" } }, - { "set_style_bg_grad_stop", { (const void*) &lv_obj_set_style_bg_grad_stop, "", "(lv.lv_obj)ii" } }, - { "set_style_bg_img_opa", { (const void*) &lv_obj_set_style_bg_img_opa, "", "(lv.lv_obj)ii" } }, - { "set_style_bg_img_recolor", { (const void*) &lv_obj_set_style_bg_img_recolor, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_bg_img_recolor_opa", { (const void*) &lv_obj_set_style_bg_img_recolor_opa, "", "(lv.lv_obj)ii" } }, - { "set_style_bg_img_src", { (const void*) &lv_obj_set_style_bg_img_src, "", "(lv.lv_obj).i" } }, - { "set_style_bg_img_tiled", { (const void*) &lv_obj_set_style_bg_img_tiled, "", "(lv.lv_obj)bi" } }, - { "set_style_bg_main_stop", { (const void*) &lv_obj_set_style_bg_main_stop, "", "(lv.lv_obj)ii" } }, - { "set_style_bg_opa", { (const void*) &lv_obj_set_style_bg_opa, "", "(lv.lv_obj)ii" } }, - { "set_style_blend_mode", { (const void*) &lv_obj_set_style_blend_mode, "", "(lv.lv_obj)ii" } }, - { "set_style_border_color", { (const void*) &lv_obj_set_style_border_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_border_opa", { (const void*) &lv_obj_set_style_border_opa, "", "(lv.lv_obj)ii" } }, - { "set_style_border_post", { (const void*) &lv_obj_set_style_border_post, "", "(lv.lv_obj)bi" } }, - { "set_style_border_side", { (const void*) &lv_obj_set_style_border_side, "", "(lv.lv_obj)ii" } }, - { "set_style_border_width", { (const void*) &lv_obj_set_style_border_width, "", "(lv.lv_obj)ii" } }, - { "set_style_clip_corner", { (const void*) &lv_obj_set_style_clip_corner, "", "(lv.lv_obj)bi" } }, - { "set_style_color_filter_dsc", { (const void*) &lv_obj_set_style_color_filter_dsc, "", "(lv.lv_obj)(lv.lv_color_filter_dsc)i" } }, - { "set_style_color_filter_opa", { (const void*) &lv_obj_set_style_color_filter_opa, "", "(lv.lv_obj)ii" } }, - { "set_style_flex_cross_place", { (const void*) &lv_obj_set_style_flex_cross_place, "", "(lv.lv_obj)ii" } }, - { "set_style_flex_flow", { (const void*) &lv_obj_set_style_flex_flow, "", "(lv.lv_obj)ii" } }, - { "set_style_flex_grow", { (const void*) &lv_obj_set_style_flex_grow, "", "(lv.lv_obj)ii" } }, - { "set_style_flex_main_place", { (const void*) &lv_obj_set_style_flex_main_place, "", "(lv.lv_obj)ii" } }, - { "set_style_flex_track_place", { (const void*) &lv_obj_set_style_flex_track_place, "", "(lv.lv_obj)ii" } }, - { "set_style_grid_cell_column_pos", { (const void*) &lv_obj_set_style_grid_cell_column_pos, "", "(lv.lv_obj)ii" } }, - { "set_style_grid_cell_column_span", { (const void*) &lv_obj_set_style_grid_cell_column_span, "", "(lv.lv_obj)ii" } }, - { "set_style_grid_cell_row_pos", { (const void*) &lv_obj_set_style_grid_cell_row_pos, "", "(lv.lv_obj)ii" } }, - { "set_style_grid_cell_row_span", { (const void*) &lv_obj_set_style_grid_cell_row_span, "", "(lv.lv_obj)ii" } }, - { "set_style_grid_cell_x_align", { (const void*) &lv_obj_set_style_grid_cell_x_align, "", "(lv.lv_obj)ii" } }, - { "set_style_grid_cell_y_align", { (const void*) &lv_obj_set_style_grid_cell_y_align, "", "(lv.lv_obj)ii" } }, - { "set_style_grid_column_align", { (const void*) &lv_obj_set_style_grid_column_align, "", "(lv.lv_obj)ii" } }, - { "set_style_grid_column_dsc_array", { (const void*) &lv_obj_set_style_grid_column_dsc_array, "", "(lv.lv_obj)(lv.lv_coord_arr)i" } }, - { "set_style_grid_row_align", { (const void*) &lv_obj_set_style_grid_row_align, "", "(lv.lv_obj)ii" } }, - { "set_style_grid_row_dsc_array", { (const void*) &lv_obj_set_style_grid_row_dsc_array, "", "(lv.lv_obj)(lv.lv_coord_arr)i" } }, - { "set_style_height", { (const void*) &lv_obj_set_style_height, "", "(lv.lv_obj)ii" } }, - { "set_style_img_opa", { (const void*) &lv_obj_set_style_img_opa, "", "(lv.lv_obj)ii" } }, - { "set_style_img_recolor", { (const void*) &lv_obj_set_style_img_recolor, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_img_recolor_opa", { (const void*) &lv_obj_set_style_img_recolor_opa, "", "(lv.lv_obj)ii" } }, - { "set_style_layout", { (const void*) &lv_obj_set_style_layout, "", "(lv.lv_obj)ii" } }, - { "set_style_line_color", { (const void*) &lv_obj_set_style_line_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_line_dash_gap", { (const void*) &lv_obj_set_style_line_dash_gap, "", "(lv.lv_obj)ii" } }, - { "set_style_line_dash_width", { (const void*) &lv_obj_set_style_line_dash_width, "", "(lv.lv_obj)ii" } }, - { "set_style_line_opa", { (const void*) &lv_obj_set_style_line_opa, "", "(lv.lv_obj)ii" } }, - { "set_style_line_rounded", { (const void*) &lv_obj_set_style_line_rounded, "", "(lv.lv_obj)bi" } }, - { "set_style_line_width", { (const void*) &lv_obj_set_style_line_width, "", "(lv.lv_obj)ii" } }, - { "set_style_max_height", { (const void*) &lv_obj_set_style_max_height, "", "(lv.lv_obj)ii" } }, - { "set_style_max_width", { (const void*) &lv_obj_set_style_max_width, "", "(lv.lv_obj)ii" } }, - { "set_style_min_height", { (const void*) &lv_obj_set_style_min_height, "", "(lv.lv_obj)ii" } }, - { "set_style_min_width", { (const void*) &lv_obj_set_style_min_width, "", "(lv.lv_obj)ii" } }, - { "set_style_opa", { (const void*) &lv_obj_set_style_opa, "", "(lv.lv_obj)ii" } }, - { "set_style_opa_layered", { (const void*) &lv_obj_set_style_opa_layered, "", "(lv.lv_obj)ii" } }, - { "set_style_outline_color", { (const void*) &lv_obj_set_style_outline_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_outline_opa", { (const void*) &lv_obj_set_style_outline_opa, "", "(lv.lv_obj)ii" } }, - { "set_style_outline_pad", { (const void*) &lv_obj_set_style_outline_pad, "", "(lv.lv_obj)ii" } }, - { "set_style_outline_width", { (const void*) &lv_obj_set_style_outline_width, "", "(lv.lv_obj)ii" } }, - { "set_style_pad_all", { (const void*) &lv_obj_set_style_pad_all, "", "(lv.lv_obj)ii" } }, - { "set_style_pad_bottom", { (const void*) &lv_obj_set_style_pad_bottom, "", "(lv.lv_obj)ii" } }, - { "set_style_pad_column", { (const void*) &lv_obj_set_style_pad_column, "", "(lv.lv_obj)ii" } }, - { "set_style_pad_gap", { (const void*) &lv_obj_set_style_pad_gap, "", "(lv.lv_obj)ii" } }, - { "set_style_pad_hor", { (const void*) &lv_obj_set_style_pad_hor, "", "(lv.lv_obj)ii" } }, - { "set_style_pad_left", { (const void*) &lv_obj_set_style_pad_left, "", "(lv.lv_obj)ii" } }, - { "set_style_pad_right", { (const void*) &lv_obj_set_style_pad_right, "", "(lv.lv_obj)ii" } }, - { "set_style_pad_row", { (const void*) &lv_obj_set_style_pad_row, "", "(lv.lv_obj)ii" } }, - { "set_style_pad_top", { (const void*) &lv_obj_set_style_pad_top, "", "(lv.lv_obj)ii" } }, - { "set_style_pad_ver", { (const void*) &lv_obj_set_style_pad_ver, "", "(lv.lv_obj)ii" } }, - { "set_style_radius", { (const void*) &lv_obj_set_style_radius, "", "(lv.lv_obj)ii" } }, - { "set_style_shadow_color", { (const void*) &lv_obj_set_style_shadow_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_shadow_ofs_x", { (const void*) &lv_obj_set_style_shadow_ofs_x, "", "(lv.lv_obj)ii" } }, - { "set_style_shadow_ofs_y", { (const void*) &lv_obj_set_style_shadow_ofs_y, "", "(lv.lv_obj)ii" } }, - { "set_style_shadow_opa", { (const void*) &lv_obj_set_style_shadow_opa, "", "(lv.lv_obj)ii" } }, - { "set_style_shadow_spread", { (const void*) &lv_obj_set_style_shadow_spread, "", "(lv.lv_obj)ii" } }, - { "set_style_shadow_width", { (const void*) &lv_obj_set_style_shadow_width, "", "(lv.lv_obj)ii" } }, - { "set_style_size", { (const void*) &lv_obj_set_style_size, "", "(lv.lv_obj)ii" } }, - { "set_style_text_align", { (const void*) &lv_obj_set_style_text_align, "", "(lv.lv_obj)ii" } }, - { "set_style_text_color", { (const void*) &lv_obj_set_style_text_color, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "set_style_text_decor", { (const void*) &lv_obj_set_style_text_decor, "", "(lv.lv_obj)ii" } }, - { "set_style_text_font", { (const void*) &lv_obj_set_style_text_font, "", "(lv.lv_obj)(lv.lv_font)i" } }, - { "set_style_text_letter_space", { (const void*) &lv_obj_set_style_text_letter_space, "", "(lv.lv_obj)ii" } }, - { "set_style_text_line_space", { (const void*) &lv_obj_set_style_text_line_space, "", "(lv.lv_obj)ii" } }, - { "set_style_text_opa", { (const void*) &lv_obj_set_style_text_opa, "", "(lv.lv_obj)ii" } }, - { "set_style_transform_angle", { (const void*) &lv_obj_set_style_transform_angle, "", "(lv.lv_obj)ii" } }, - { "set_style_transform_height", { (const void*) &lv_obj_set_style_transform_height, "", "(lv.lv_obj)ii" } }, - { "set_style_transform_pivot_x", { (const void*) &lv_obj_set_style_transform_pivot_x, "", "(lv.lv_obj)ii" } }, - { "set_style_transform_pivot_y", { (const void*) &lv_obj_set_style_transform_pivot_y, "", "(lv.lv_obj)ii" } }, - { "set_style_transform_width", { (const void*) &lv_obj_set_style_transform_width, "", "(lv.lv_obj)ii" } }, - { "set_style_transform_zoom", { (const void*) &lv_obj_set_style_transform_zoom, "", "(lv.lv_obj)ii" } }, - { "set_style_transition", { (const void*) &lv_obj_set_style_transition, "", "(lv.lv_obj)(lv.lv_style_transition_dsc)i" } }, - { "set_style_translate_x", { (const void*) &lv_obj_set_style_translate_x, "", "(lv.lv_obj)ii" } }, - { "set_style_translate_y", { (const void*) &lv_obj_set_style_translate_y, "", "(lv.lv_obj)ii" } }, - { "set_style_width", { (const void*) &lv_obj_set_style_width, "", "(lv.lv_obj)ii" } }, - { "set_style_x", { (const void*) &lv_obj_set_style_x, "", "(lv.lv_obj)ii" } }, - { "set_style_y", { (const void*) &lv_obj_set_style_y, "", "(lv.lv_obj)ii" } }, - { "set_tile", { (const void*) &lv_obj_set_tile, "", "(lv.lv_obj)(lv.lv_obj)i" } }, - { "set_tile_id", { (const void*) &lv_obj_set_tile_id, "", "(lv.lv_obj)iii" } }, - { "set_user_data", { (const void*) &lv_obj_set_user_data, "", "(lv.lv_obj)." } }, - { "set_width", { (const void*) &lv_obj_set_width, "", "(lv.lv_obj)i" } }, - { "set_x", { (const void*) &lv_obj_set_x, "", "(lv.lv_obj)i" } }, - { "set_y", { (const void*) &lv_obj_set_y, "", "(lv.lv_obj)i" } }, - { "swap", { (const void*) &lv_obj_swap, "", "(lv.lv_obj)(lv.lv_obj)" } }, - { "transform_point", { (const void*) &lv_obj_transform_point, "", "(lv.lv_obj)(lv.lv_point)bb" } }, - { "tree_walk", { (const void*) &lv_obj_tree_walk, "", "(lv.lv_obj)^lv_obj_tree_walk_cb^." } }, - { "update_layout", { (const void*) &lv_obj_update_layout, "", "(lv.lv_obj)" } }, - { "update_snap", { (const void*) &lv_obj_update_snap, "", "(lv.lv_obj)i" } }, +/* `lv_image` methods */ +#ifdef BE_LV_WIDGET_IMAGE +const be_ntv_func_def_t lv_image_func[] = { + { "get_angle", { (const void*) &lv_image_get_rotation, "i", "(lv.obj)" } }, + { "get_antialias", { (const void*) &lv_image_get_antialias, "b", "(lv.obj)" } }, + { "get_blend_mode", { (const void*) &lv_image_get_blend_mode, "i", "(lv.obj)" } }, + { "get_inner_align", { (const void*) &lv_image_get_inner_align, "i", "(lv.obj)" } }, + { "get_offset_x", { (const void*) &lv_image_get_offset_x, "i", "(lv.obj)" } }, + { "get_offset_y", { (const void*) &lv_image_get_offset_y, "i", "(lv.obj)" } }, + { "get_pivot", { (const void*) &lv_image_get_pivot, "", "(lv.obj)c" } }, + { "get_rotation", { (const void*) &lv_image_get_rotation, "i", "(lv.obj)" } }, + { "get_scale", { (const void*) &lv_image_get_scale, "i", "(lv.obj)" } }, + { "get_scale_x", { (const void*) &lv_image_get_scale_x, "i", "(lv.obj)" } }, + { "get_scale_y", { (const void*) &lv_image_get_scale_y, "i", "(lv.obj)" } }, + { "get_src", { (const void*) &lv_image_get_src, "c", "(lv.obj)" } }, + { "get_zoom", { (const void*) &lv_image_get_scale, "i", "(lv.obj)" } }, + { "set_angle", { (const void*) &lv_image_set_rotation, "", "(lv.obj)i" } }, + { "set_antialias", { (const void*) &lv_image_set_antialias, "", "(lv.obj)b" } }, + { "set_blend_mode", { (const void*) &lv_image_set_blend_mode, "", "(lv.obj)i" } }, + { "set_inner_align", { (const void*) &lv_image_set_inner_align, "", "(lv.obj)i" } }, + { "set_offset_x", { (const void*) &lv_image_set_offset_x, "", "(lv.obj)i" } }, + { "set_offset_y", { (const void*) &lv_image_set_offset_y, "", "(lv.obj)i" } }, + { "set_pivot", { (const void*) &lv_image_set_pivot, "", "(lv.obj)ii" } }, + { "set_rotation", { (const void*) &lv_image_set_rotation, "", "(lv.obj)i" } }, + { "set_scale", { (const void*) &lv_image_set_scale, "", "(lv.obj)i" } }, + { "set_scale_x", { (const void*) &lv_image_set_scale_x, "", "(lv.obj)i" } }, + { "set_scale_y", { (const void*) &lv_image_set_scale_y, "", "(lv.obj)i" } }, + { "set_src", { (const void*) &lv_image_set_src, "", "(lv.obj)." } }, + { "set_tasmota_logo", { (const void*) &lv_image_set_tasmota_logo, "", "(lv.obj)" } }, + { "set_zoom", { (const void*) &lv_image_set_scale, "", "(lv.obj)i" } }, }; +#endif // BE_LV_WIDGET_IMAGE /* `lv_group` methods */ const be_ntv_func_def_t lv_group_func[] = { - { "add_obj", { (const void*) &lv_group_add_obj, "", "(lv.lv_group)(lv.lv_obj)" } }, - { "del", { (const void*) &lv_group_del, "", "(lv.lv_group)" } }, - { "focus_freeze", { (const void*) &lv_group_focus_freeze, "", "(lv.lv_group)b" } }, - { "focus_next", { (const void*) &lv_group_focus_next, "", "(lv.lv_group)" } }, - { "focus_obj", { (const void*) &lv_group_focus_obj, "", "(lv.lv_obj)" } }, - { "focus_prev", { (const void*) &lv_group_focus_prev, "", "(lv.lv_group)" } }, - { "get_edge_cb", { (const void*) &lv_group_get_edge_cb, "C", "(lv.lv_group)" } }, - { "get_editing", { (const void*) &lv_group_get_editing, "b", "(lv.lv_group)" } }, - { "get_focus_cb", { (const void*) &lv_group_get_focus_cb, "lv.lv_group_focus_cb", "(lv.lv_group)" } }, - { "get_focused", { (const void*) &lv_group_get_focused, "lv.lv_obj", "(lv.lv_group)" } }, - { "get_obj_count", { (const void*) &lv_group_get_obj_count, "i", "(lv.lv_group)" } }, - { "get_wrap", { (const void*) &lv_group_get_wrap, "b", "(lv.lv_group)" } }, - { "remove_all_objs", { (const void*) &lv_group_remove_all_objs, "", "(lv.lv_group)" } }, - { "remove_obj", { (const void*) &lv_group_remove_obj, "", "(lv.lv_obj)" } }, - { "send_data", { (const void*) &lv_group_send_data, "i", "(lv.lv_group)i" } }, - { "set_default", { (const void*) &lv_group_set_default, "", "(lv.lv_group)" } }, - { "set_edge_cb", { (const void*) &lv_group_set_edge_cb, "", "(lv.lv_group)^lv_group_edge_cb^" } }, - { "set_editing", { (const void*) &lv_group_set_editing, "", "(lv.lv_group)b" } }, - { "set_focus_cb", { (const void*) &lv_group_set_focus_cb, "", "(lv.lv_group)^lv_group_focus_cb^" } }, - { "set_refocus_policy", { (const void*) &lv_group_set_refocus_policy, "", "(lv.lv_group)i" } }, - { "set_wrap", { (const void*) &lv_group_set_wrap, "", "(lv.lv_group)b" } }, - { "swap_obj", { (const void*) &lv_group_swap_obj, "", "(lv.lv_obj)(lv.lv_obj)" } }, + { "add_obj", { (const void*) &lv_group_add_obj, "", "(lv.group)(lv.obj)" } }, + { "del", { (const void*) &lv_group_delete, "", "(lv.group)" } }, + { "delete", { (const void*) &lv_group_delete, "", "(lv.group)" } }, + { "focus_freeze", { (const void*) &lv_group_focus_freeze, "", "(lv.group)b" } }, + { "focus_next", { (const void*) &lv_group_focus_next, "", "(lv.group)" } }, + { "focus_obj", { (const void*) &lv_group_focus_obj, "", "(lv.obj)" } }, + { "focus_prev", { (const void*) &lv_group_focus_prev, "", "(lv.group)" } }, + { "get_edge_cb", { (const void*) &lv_group_get_edge_cb, "C", "(lv.group)" } }, + { "get_editing", { (const void*) &lv_group_get_editing, "b", "(lv.group)" } }, + { "get_focus_cb", { (const void*) &lv_group_get_focus_cb, "lv.group_focus_cb", "(lv.group)" } }, + { "get_focused", { (const void*) &lv_group_get_focused, "lv.obj", "(lv.group)" } }, + { "get_obj_count", { (const void*) &lv_group_get_obj_count, "i", "(lv.group)" } }, + { "get_wrap", { (const void*) &lv_group_get_wrap, "b", "(lv.group)" } }, + { "remove", { (const void*) &lv_group_delete, "", "(lv.group)" } }, + { "remove_all_objs", { (const void*) &lv_group_remove_all_objs, "", "(lv.group)" } }, + { "remove_obj", { (const void*) &lv_group_remove_obj, "", "(lv.obj)" } }, + { "send_data", { (const void*) &lv_group_send_data, "i", "(lv.group)i" } }, + { "set_default", { (const void*) &lv_group_set_default, "", "(lv.group)" } }, + { "set_editing", { (const void*) &lv_group_set_editing, "", "(lv.group)b" } }, + { "set_focus_cb", { (const void*) &lv_group_set_focus_cb, "", "(lv.group)^lv_group_focus_cb^" } }, + { "set_refocus_policy", { (const void*) &lv_group_set_refocus_policy, "", "(lv.group)i" } }, + { "set_wrap", { (const void*) &lv_group_set_wrap, "", "(lv.group)b" } }, + { "swap_obj", { (const void*) &lv_group_swap_obj, "", "(lv.obj)(lv.obj)" } }, +}; + +/* `lv_obj` methods */ +#ifdef BE_LV_WIDGET_OBJ +const be_ntv_func_def_t lv_obj_func[] = { + { "add_event_cb", { (const void*) &lv_obj_add_event_cb, "", "(lv.obj)^lv_event_cb^i." } }, + { "add_flag", { (const void*) &lv_obj_add_flag, "", "(lv.obj)i" } }, + { "add_state", { (const void*) &lv_obj_add_state, "", "(lv.obj)i" } }, + { "add_style", { (const void*) &lv_obj_add_style, "", "(lv.obj)(lv.style)i" } }, + { "align", { (const void*) &lv_obj_align, "", "(lv.obj)iii" } }, + { "align_to", { (const void*) &lv_obj_align_to, "", "(lv.obj)(lv.obj)iii" } }, + { "allocate_spec_attr", { (const void*) &lv_obj_allocate_spec_attr, "", "(lv.obj)" } }, + { "area_is_visible", { (const void*) &lv_obj_area_is_visible, "b", "(lv.obj)(lv.area)" } }, + { "calculate_ext_draw_size", { (const void*) &lv_obj_calculate_ext_draw_size, "i", "(lv.obj)i" } }, + { "calculate_style_text_align", { (const void*) &lv_obj_calculate_style_text_align, "i", "(lv.obj)is" } }, + { "center", { (const void*) &lv_obj_center, "", "(lv.obj)" } }, + { "check_type", { (const void*) &lv_obj_check_type, "b", "(lv.obj)(lv.obj_class)" } }, + { "class_init_obj", { (const void*) &lv_obj_class_init_obj, "", "(lv.obj)" } }, + { "clean", { (const void*) &lv_obj_clean, "", "(lv.obj)" } }, + { "clear_flag", { (const void*) &lv_obj_remove_flag, "", "(lv.obj)i" } }, + { "clear_state", { (const void*) &lv_obj_remove_state, "", "(lv.obj)i" } }, + { "del", { (const void*) &lv_obj_delete, "", "(lv.obj)" } }, + { "del_async", { (const void*) &lv_obj_delete_async, "", "(lv.obj)" } }, + { "delete", { (const void*) &lv_obj_delete, "", "(lv.obj)" } }, + { "delete_async", { (const void*) &lv_obj_delete_async, "", "(lv.obj)" } }, + { "delete_delayed", { (const void*) &lv_obj_delete_delayed, "", "(lv.obj)i" } }, + { "dump_tree", { (const void*) &lv_obj_dump_tree, "", "(lv.obj)" } }, + { "fade_in", { (const void*) &lv_obj_fade_in, "", "(lv.obj)ii" } }, + { "fade_out", { (const void*) &lv_obj_fade_out, "", "(lv.obj)ii" } }, + { "free_id", { (const void*) &lv_obj_free_id, "", "(lv.obj)" } }, + { "get_child", { (const void*) &lv_obj_get_child, "lv.obj", "(lv.obj)i" } }, + { "get_child_by_type", { (const void*) &lv_obj_get_child_by_type, "lv.obj", "(lv.obj)i(lv.obj_class)" } }, + { "get_child_cnt", { (const void*) &lv_obj_get_child_count, "i", "(lv.obj)" } }, + { "get_child_count", { (const void*) &lv_obj_get_child_count, "i", "(lv.obj)" } }, + { "get_child_count_by_type", { (const void*) &lv_obj_get_child_count_by_type, "i", "(lv.obj)(lv.obj_class)" } }, + { "get_class", { (const void*) &lv_obj_get_class, "lv.obj_class", "(lv.obj)" } }, + { "get_click_area", { (const void*) &lv_obj_get_click_area, "", "(lv.obj)(lv.area)" } }, + { "get_content_coords", { (const void*) &lv_obj_get_content_coords, "", "(lv.obj)(lv.area)" } }, + { "get_content_height", { (const void*) &lv_obj_get_content_height, "i", "(lv.obj)" } }, + { "get_content_width", { (const void*) &lv_obj_get_content_width, "i", "(lv.obj)" } }, + { "get_coords", { (const void*) &lv_obj_get_coords, "", "(lv.obj)(lv.area)" } }, + { "get_disp", { (const void*) &lv_obj_get_display, "lv.display", "(lv.obj)" } }, + { "get_display", { (const void*) &lv_obj_get_display, "lv.display", "(lv.obj)" } }, + { "get_event_count", { (const void*) &lv_obj_get_event_count, "i", "(lv.obj)" } }, + { "get_group", { (const void*) &lv_obj_get_group, "lv.group", "(lv.obj)" } }, + { "get_height", { (const void*) &lv_obj_get_height, "i", "(lv.obj)" } }, + { "get_index", { (const void*) &lv_obj_get_index, "i", "(lv.obj)" } }, + { "get_index_by_type", { (const void*) &lv_obj_get_index_by_type, "i", "(lv.obj)(lv.obj_class)" } }, + { "get_parent", { (const void*) &lv_obj_get_parent, "lv.obj", "(lv.obj)" } }, + { "get_screen", { (const void*) &lv_obj_get_screen, "lv.obj", "(lv.obj)" } }, + { "get_scroll_bottom", { (const void*) &lv_obj_get_scroll_bottom, "i", "(lv.obj)" } }, + { "get_scroll_dir", { (const void*) &lv_obj_get_scroll_dir, "i", "(lv.obj)" } }, + { "get_scroll_end", { (const void*) &lv_obj_get_scroll_end, "", "(lv.obj)c" } }, + { "get_scroll_left", { (const void*) &lv_obj_get_scroll_left, "i", "(lv.obj)" } }, + { "get_scroll_right", { (const void*) &lv_obj_get_scroll_right, "i", "(lv.obj)" } }, + { "get_scroll_snap_x", { (const void*) &lv_obj_get_scroll_snap_x, "i", "(lv.obj)" } }, + { "get_scroll_snap_y", { (const void*) &lv_obj_get_scroll_snap_y, "i", "(lv.obj)" } }, + { "get_scroll_top", { (const void*) &lv_obj_get_scroll_top, "i", "(lv.obj)" } }, + { "get_scroll_x", { (const void*) &lv_obj_get_scroll_x, "i", "(lv.obj)" } }, + { "get_scroll_y", { (const void*) &lv_obj_get_scroll_y, "i", "(lv.obj)" } }, + { "get_scrollbar_area", { (const void*) &lv_obj_get_scrollbar_area, "", "(lv.obj)(lv.area)(lv.area)" } }, + { "get_scrollbar_mode", { (const void*) &lv_obj_get_scrollbar_mode, "i", "(lv.obj)" } }, + { "get_self_height", { (const void*) &lv_obj_get_self_height, "i", "(lv.obj)" } }, + { "get_self_width", { (const void*) &lv_obj_get_self_width, "i", "(lv.obj)" } }, + { "get_sibling", { (const void*) &lv_obj_get_sibling, "lv.obj", "(lv.obj)i" } }, + { "get_sibling_by_type", { (const void*) &lv_obj_get_sibling_by_type, "lv.obj", "(lv.obj)i(lv.obj_class)" } }, + { "get_state", { (const void*) &lv_obj_get_state, "i", "(lv.obj)" } }, + { "get_style_align", { (const void*) &lv_obj_get_style_align, "i", "(lv.obj)i" } }, + { "get_style_anim", { (const void*) &lv_obj_get_style_anim, "lv.anim", "(lv.obj)i" } }, + { "get_style_anim_duration", { (const void*) &lv_obj_get_style_anim_duration, "i", "(lv.obj)i" } }, + { "get_style_anim_time", { (const void*) &lv_obj_get_style_anim_duration, "i", "(lv.obj)i" } }, + { "get_style_arc_color", { (const void*) &lv_obj_get_style_arc_color, "lv.color", "(lv.obj)i" } }, + { "get_style_arc_color_filtered", { (const void*) &lv_obj_get_style_arc_color_filtered, "lv.color", "(lv.obj)i" } }, + { "get_style_arc_image_src", { (const void*) &lv_obj_get_style_arc_image_src, "c", "(lv.obj)i" } }, + { "get_style_arc_opa", { (const void*) &lv_obj_get_style_arc_opa, "i", "(lv.obj)i" } }, + { "get_style_arc_rounded", { (const void*) &lv_obj_get_style_arc_rounded, "b", "(lv.obj)i" } }, + { "get_style_arc_width", { (const void*) &lv_obj_get_style_arc_width, "i", "(lv.obj)i" } }, + { "get_style_base_dir", { (const void*) &lv_obj_get_style_base_dir, "i", "(lv.obj)i" } }, + { "get_style_bg_color", { (const void*) &lv_obj_get_style_bg_color, "lv.color", "(lv.obj)i" } }, + { "get_style_bg_color_filtered", { (const void*) &lv_obj_get_style_bg_color_filtered, "lv.color", "(lv.obj)i" } }, + { "get_style_bg_grad", { (const void*) &lv_obj_get_style_bg_grad, "lv.grad_dsc", "(lv.obj)i" } }, + { "get_style_bg_grad_color", { (const void*) &lv_obj_get_style_bg_grad_color, "lv.color", "(lv.obj)i" } }, + { "get_style_bg_grad_color_filtered", { (const void*) &lv_obj_get_style_bg_grad_color_filtered, "lv.color", "(lv.obj)i" } }, + { "get_style_bg_grad_dir", { (const void*) &lv_obj_get_style_bg_grad_dir, "i", "(lv.obj)i" } }, + { "get_style_bg_grad_opa", { (const void*) &lv_obj_get_style_bg_grad_opa, "i", "(lv.obj)i" } }, + { "get_style_bg_grad_stop", { (const void*) &lv_obj_get_style_bg_grad_stop, "i", "(lv.obj)i" } }, + { "get_style_bg_image_opa", { (const void*) &lv_obj_get_style_bg_image_opa, "i", "(lv.obj)i" } }, + { "get_style_bg_image_recolor", { (const void*) &lv_obj_get_style_bg_image_recolor, "lv.color", "(lv.obj)i" } }, + { "get_style_bg_image_recolor_filtered", { (const void*) &lv_obj_get_style_bg_image_recolor_filtered, "lv.color", "(lv.obj)i" } }, + { "get_style_bg_image_recolor_opa", { (const void*) &lv_obj_get_style_bg_image_recolor_opa, "i", "(lv.obj)i" } }, + { "get_style_bg_image_src", { (const void*) &lv_obj_get_style_bg_image_src, "c", "(lv.obj)i" } }, + { "get_style_bg_image_tiled", { (const void*) &lv_obj_get_style_bg_image_tiled, "b", "(lv.obj)i" } }, + { "get_style_bg_main_opa", { (const void*) &lv_obj_get_style_bg_main_opa, "i", "(lv.obj)i" } }, + { "get_style_bg_main_stop", { (const void*) &lv_obj_get_style_bg_main_stop, "i", "(lv.obj)i" } }, + { "get_style_bg_opa", { (const void*) &lv_obj_get_style_bg_opa, "i", "(lv.obj)i" } }, + { "get_style_blend_mode", { (const void*) &lv_obj_get_style_blend_mode, "i", "(lv.obj)i" } }, + { "get_style_border_color", { (const void*) &lv_obj_get_style_border_color, "lv.color", "(lv.obj)i" } }, + { "get_style_border_color_filtered", { (const void*) &lv_obj_get_style_border_color_filtered, "lv.color", "(lv.obj)i" } }, + { "get_style_border_opa", { (const void*) &lv_obj_get_style_border_opa, "i", "(lv.obj)i" } }, + { "get_style_border_post", { (const void*) &lv_obj_get_style_border_post, "b", "(lv.obj)i" } }, + { "get_style_border_side", { (const void*) &lv_obj_get_style_border_side, "i", "(lv.obj)i" } }, + { "get_style_border_width", { (const void*) &lv_obj_get_style_border_width, "i", "(lv.obj)i" } }, + { "get_style_clip_corner", { (const void*) &lv_obj_get_style_clip_corner, "b", "(lv.obj)i" } }, + { "get_style_color_filter_dsc", { (const void*) &lv_obj_get_style_color_filter_dsc, "lv.color_filter_dsc", "(lv.obj)i" } }, + { "get_style_color_filter_opa", { (const void*) &lv_obj_get_style_color_filter_opa, "i", "(lv.obj)i" } }, + { "get_style_flex_cross_place", { (const void*) &lv_obj_get_style_flex_cross_place, "i", "(lv.obj)i" } }, + { "get_style_flex_flow", { (const void*) &lv_obj_get_style_flex_flow, "i", "(lv.obj)i" } }, + { "get_style_flex_grow", { (const void*) &lv_obj_get_style_flex_grow, "i", "(lv.obj)i" } }, + { "get_style_flex_main_place", { (const void*) &lv_obj_get_style_flex_main_place, "i", "(lv.obj)i" } }, + { "get_style_flex_track_place", { (const void*) &lv_obj_get_style_flex_track_place, "i", "(lv.obj)i" } }, + { "get_style_grid_cell_column_pos", { (const void*) &lv_obj_get_style_grid_cell_column_pos, "i", "(lv.obj)i" } }, + { "get_style_grid_cell_column_span", { (const void*) &lv_obj_get_style_grid_cell_column_span, "i", "(lv.obj)i" } }, + { "get_style_grid_cell_row_pos", { (const void*) &lv_obj_get_style_grid_cell_row_pos, "i", "(lv.obj)i" } }, + { "get_style_grid_cell_row_span", { (const void*) &lv_obj_get_style_grid_cell_row_span, "i", "(lv.obj)i" } }, + { "get_style_grid_cell_x_align", { (const void*) &lv_obj_get_style_grid_cell_x_align, "i", "(lv.obj)i" } }, + { "get_style_grid_cell_y_align", { (const void*) &lv_obj_get_style_grid_cell_y_align, "i", "(lv.obj)i" } }, + { "get_style_grid_column_align", { (const void*) &lv_obj_get_style_grid_column_align, "i", "(lv.obj)i" } }, + { "get_style_grid_column_dsc_array", { (const void*) &lv_obj_get_style_grid_column_dsc_array, "lv.int_arr", "(lv.obj)i" } }, + { "get_style_grid_row_align", { (const void*) &lv_obj_get_style_grid_row_align, "i", "(lv.obj)i" } }, + { "get_style_grid_row_dsc_array", { (const void*) &lv_obj_get_style_grid_row_dsc_array, "lv.int_arr", "(lv.obj)i" } }, + { "get_style_height", { (const void*) &lv_obj_get_style_height, "i", "(lv.obj)i" } }, + { "get_style_image_opa", { (const void*) &lv_obj_get_style_image_opa, "i", "(lv.obj)i" } }, + { "get_style_image_recolor", { (const void*) &lv_obj_get_style_image_recolor, "lv.color", "(lv.obj)i" } }, + { "get_style_image_recolor_filtered", { (const void*) &lv_obj_get_style_image_recolor_filtered, "lv.color", "(lv.obj)i" } }, + { "get_style_image_recolor_opa", { (const void*) &lv_obj_get_style_image_recolor_opa, "i", "(lv.obj)i" } }, + { "get_style_img_opa", { (const void*) &lv_obj_get_style_image_opa, "i", "(lv.obj)i" } }, + { "get_style_img_recolor", { (const void*) &lv_obj_get_style_image_recolor, "lv.color", "(lv.obj)i" } }, + { "get_style_img_recolor_filtered", { (const void*) &lv_obj_get_style_image_recolor_filtered, "lv.color", "(lv.obj)i" } }, + { "get_style_img_recolor_opa", { (const void*) &lv_obj_get_style_image_recolor_opa, "i", "(lv.obj)i" } }, + { "get_style_layout", { (const void*) &lv_obj_get_style_layout, "i", "(lv.obj)i" } }, + { "get_style_length", { (const void*) &lv_obj_get_style_length, "i", "(lv.obj)i" } }, + { "get_style_line_color", { (const void*) &lv_obj_get_style_line_color, "lv.color", "(lv.obj)i" } }, + { "get_style_line_color_filtered", { (const void*) &lv_obj_get_style_line_color_filtered, "lv.color", "(lv.obj)i" } }, + { "get_style_line_dash_gap", { (const void*) &lv_obj_get_style_line_dash_gap, "i", "(lv.obj)i" } }, + { "get_style_line_dash_width", { (const void*) &lv_obj_get_style_line_dash_width, "i", "(lv.obj)i" } }, + { "get_style_line_opa", { (const void*) &lv_obj_get_style_line_opa, "i", "(lv.obj)i" } }, + { "get_style_line_rounded", { (const void*) &lv_obj_get_style_line_rounded, "b", "(lv.obj)i" } }, + { "get_style_line_width", { (const void*) &lv_obj_get_style_line_width, "i", "(lv.obj)i" } }, + { "get_style_margin_bottom", { (const void*) &lv_obj_get_style_margin_bottom, "i", "(lv.obj)i" } }, + { "get_style_margin_left", { (const void*) &lv_obj_get_style_margin_left, "i", "(lv.obj)i" } }, + { "get_style_margin_right", { (const void*) &lv_obj_get_style_margin_right, "i", "(lv.obj)i" } }, + { "get_style_margin_top", { (const void*) &lv_obj_get_style_margin_top, "i", "(lv.obj)i" } }, + { "get_style_max_height", { (const void*) &lv_obj_get_style_max_height, "i", "(lv.obj)i" } }, + { "get_style_max_width", { (const void*) &lv_obj_get_style_max_width, "i", "(lv.obj)i" } }, + { "get_style_min_height", { (const void*) &lv_obj_get_style_min_height, "i", "(lv.obj)i" } }, + { "get_style_min_width", { (const void*) &lv_obj_get_style_min_width, "i", "(lv.obj)i" } }, + { "get_style_opa", { (const void*) &lv_obj_get_style_opa, "i", "(lv.obj)i" } }, + { "get_style_opa_layered", { (const void*) &lv_obj_get_style_opa_layered, "i", "(lv.obj)i" } }, + { "get_style_opa_recursive", { (const void*) &lv_obj_get_style_opa_recursive, "i", "(lv.obj)i" } }, + { "get_style_outline_color", { (const void*) &lv_obj_get_style_outline_color, "lv.color", "(lv.obj)i" } }, + { "get_style_outline_color_filtered", { (const void*) &lv_obj_get_style_outline_color_filtered, "lv.color", "(lv.obj)i" } }, + { "get_style_outline_opa", { (const void*) &lv_obj_get_style_outline_opa, "i", "(lv.obj)i" } }, + { "get_style_outline_pad", { (const void*) &lv_obj_get_style_outline_pad, "i", "(lv.obj)i" } }, + { "get_style_outline_width", { (const void*) &lv_obj_get_style_outline_width, "i", "(lv.obj)i" } }, + { "get_style_pad_bottom", { (const void*) &lv_obj_get_style_pad_bottom, "i", "(lv.obj)i" } }, + { "get_style_pad_column", { (const void*) &lv_obj_get_style_pad_column, "i", "(lv.obj)i" } }, + { "get_style_pad_left", { (const void*) &lv_obj_get_style_pad_left, "i", "(lv.obj)i" } }, + { "get_style_pad_right", { (const void*) &lv_obj_get_style_pad_right, "i", "(lv.obj)i" } }, + { "get_style_pad_row", { (const void*) &lv_obj_get_style_pad_row, "i", "(lv.obj)i" } }, + { "get_style_pad_top", { (const void*) &lv_obj_get_style_pad_top, "i", "(lv.obj)i" } }, + { "get_style_prop", { (const void*) &lv_obj_get_style_prop, "i", "(lv.obj)ii" } }, + { "get_style_radius", { (const void*) &lv_obj_get_style_radius, "i", "(lv.obj)i" } }, + { "get_style_shadow_color", { (const void*) &lv_obj_get_style_shadow_color, "lv.color", "(lv.obj)i" } }, + { "get_style_shadow_color_filtered", { (const void*) &lv_obj_get_style_shadow_color_filtered, "lv.color", "(lv.obj)i" } }, + { "get_style_shadow_offset_x", { (const void*) &lv_obj_get_style_shadow_offset_x, "i", "(lv.obj)i" } }, + { "get_style_shadow_offset_y", { (const void*) &lv_obj_get_style_shadow_offset_y, "i", "(lv.obj)i" } }, + { "get_style_shadow_ofs_x", { (const void*) &lv_obj_get_style_shadow_offset_x, "i", "(lv.obj)i" } }, + { "get_style_shadow_ofs_y", { (const void*) &lv_obj_get_style_shadow_offset_y, "i", "(lv.obj)i" } }, + { "get_style_shadow_opa", { (const void*) &lv_obj_get_style_shadow_opa, "i", "(lv.obj)i" } }, + { "get_style_shadow_spread", { (const void*) &lv_obj_get_style_shadow_spread, "i", "(lv.obj)i" } }, + { "get_style_shadow_width", { (const void*) &lv_obj_get_style_shadow_width, "i", "(lv.obj)i" } }, + { "get_style_space_bottom", { (const void*) &lv_obj_get_style_space_bottom, "i", "(lv.obj)i" } }, + { "get_style_space_left", { (const void*) &lv_obj_get_style_space_left, "i", "(lv.obj)i" } }, + { "get_style_space_right", { (const void*) &lv_obj_get_style_space_right, "i", "(lv.obj)i" } }, + { "get_style_space_top", { (const void*) &lv_obj_get_style_space_top, "i", "(lv.obj)i" } }, + { "get_style_text_align", { (const void*) &lv_obj_get_style_text_align, "i", "(lv.obj)i" } }, + { "get_style_text_color", { (const void*) &lv_obj_get_style_text_color, "lv.color", "(lv.obj)i" } }, + { "get_style_text_color_filtered", { (const void*) &lv_obj_get_style_text_color_filtered, "lv.color", "(lv.obj)i" } }, + { "get_style_text_decor", { (const void*) &lv_obj_get_style_text_decor, "i", "(lv.obj)i" } }, + { "get_style_text_font", { (const void*) &lv_obj_get_style_text_font, "lv.font", "(lv.obj)i" } }, + { "get_style_text_letter_space", { (const void*) &lv_obj_get_style_text_letter_space, "i", "(lv.obj)i" } }, + { "get_style_text_line_space", { (const void*) &lv_obj_get_style_text_line_space, "i", "(lv.obj)i" } }, + { "get_style_text_opa", { (const void*) &lv_obj_get_style_text_opa, "i", "(lv.obj)i" } }, + { "get_style_transform_angle", { (const void*) &lv_obj_get_style_transform_rotation, "i", "(lv.obj)i" } }, + { "get_style_transform_height", { (const void*) &lv_obj_get_style_transform_height, "i", "(lv.obj)i" } }, + { "get_style_transform_pivot_x", { (const void*) &lv_obj_get_style_transform_pivot_x, "i", "(lv.obj)i" } }, + { "get_style_transform_pivot_y", { (const void*) &lv_obj_get_style_transform_pivot_y, "i", "(lv.obj)i" } }, + { "get_style_transform_rotation", { (const void*) &lv_obj_get_style_transform_rotation, "i", "(lv.obj)i" } }, + { "get_style_transform_scale_x", { (const void*) &lv_obj_get_style_transform_scale_x, "i", "(lv.obj)i" } }, + { "get_style_transform_scale_x_safe", { (const void*) &lv_obj_get_style_transform_scale_x_safe, "i", "(lv.obj)i" } }, + { "get_style_transform_scale_y", { (const void*) &lv_obj_get_style_transform_scale_y, "i", "(lv.obj)i" } }, + { "get_style_transform_scale_y_safe", { (const void*) &lv_obj_get_style_transform_scale_y_safe, "i", "(lv.obj)i" } }, + { "get_style_transform_skew_x", { (const void*) &lv_obj_get_style_transform_skew_x, "i", "(lv.obj)i" } }, + { "get_style_transform_skew_y", { (const void*) &lv_obj_get_style_transform_skew_y, "i", "(lv.obj)i" } }, + { "get_style_transform_width", { (const void*) &lv_obj_get_style_transform_width, "i", "(lv.obj)i" } }, + { "get_style_transition", { (const void*) &lv_obj_get_style_transition, "lv.style_transition_dsc", "(lv.obj)i" } }, + { "get_style_translate_x", { (const void*) &lv_obj_get_style_translate_x, "i", "(lv.obj)i" } }, + { "get_style_translate_y", { (const void*) &lv_obj_get_style_translate_y, "i", "(lv.obj)i" } }, + { "get_style_width", { (const void*) &lv_obj_get_style_width, "i", "(lv.obj)i" } }, + { "get_style_x", { (const void*) &lv_obj_get_style_x, "i", "(lv.obj)i" } }, + { "get_style_y", { (const void*) &lv_obj_get_style_y, "i", "(lv.obj)i" } }, + { "get_transformed_area", { (const void*) &lv_obj_get_transformed_area, "", "(lv.obj)(lv.area)bb" } }, + { "get_user_data", { (const void*) &lv_obj_get_user_data, "c", "(lv.obj)" } }, + { "get_width", { (const void*) &lv_obj_get_width, "i", "(lv.obj)" } }, + { "get_x", { (const void*) &lv_obj_get_x, "i", "(lv.obj)" } }, + { "get_x2", { (const void*) &lv_obj_get_x2, "i", "(lv.obj)" } }, + { "get_x_aligned", { (const void*) &lv_obj_get_x_aligned, "i", "(lv.obj)" } }, + { "get_y", { (const void*) &lv_obj_get_y, "i", "(lv.obj)" } }, + { "get_y2", { (const void*) &lv_obj_get_y2, "i", "(lv.obj)" } }, + { "get_y_aligned", { (const void*) &lv_obj_get_y_aligned, "i", "(lv.obj)" } }, + { "has_class", { (const void*) &lv_obj_has_class, "b", "(lv.obj)(lv.obj_class)" } }, + { "has_flag", { (const void*) &lv_obj_has_flag, "b", "(lv.obj)i" } }, + { "has_flag_any", { (const void*) &lv_obj_has_flag_any, "b", "(lv.obj)i" } }, + { "has_state", { (const void*) &lv_obj_has_state, "b", "(lv.obj)i" } }, + { "has_style_prop", { (const void*) &lv_obj_has_style_prop, "b", "(lv.obj)ii" } }, + { "hit_test", { (const void*) &lv_obj_hit_test, "b", "(lv.obj)c" } }, + { "init_draw_arc_dsc", { (const void*) &lv_obj_init_draw_arc_dsc, "", "(lv.obj)i(lv.draw_arc_dsc)" } }, + { "init_draw_image_dsc", { (const void*) &lv_obj_init_draw_image_dsc, "", "(lv.obj)i(lv.draw_image_dsc)" } }, + { "init_draw_label_dsc", { (const void*) &lv_obj_init_draw_label_dsc, "", "(lv.obj)i(lv.draw_label_dsc)" } }, + { "init_draw_line_dsc", { (const void*) &lv_obj_init_draw_line_dsc, "", "(lv.obj)i(lv.draw_line_dsc)" } }, + { "init_draw_rect_dsc", { (const void*) &lv_obj_init_draw_rect_dsc, "", "(lv.obj)i(lv.draw_rect_dsc)" } }, + { "invalidate", { (const void*) &lv_obj_invalidate, "", "(lv.obj)" } }, + { "invalidate_area", { (const void*) &lv_obj_invalidate_area, "", "(lv.obj)(lv.area)" } }, + { "is_editable", { (const void*) &lv_obj_is_editable, "b", "(lv.obj)" } }, + { "is_group_def", { (const void*) &lv_obj_is_group_def, "b", "(lv.obj)" } }, + { "is_layout_positioned", { (const void*) &lv_obj_is_layout_positioned, "b", "(lv.obj)" } }, + { "is_scrolling", { (const void*) &lv_obj_is_scrolling, "b", "(lv.obj)" } }, + { "is_valid", { (const void*) &lv_obj_is_valid, "b", "(lv.obj)" } }, + { "is_visible", { (const void*) &lv_obj_is_visible, "b", "(lv.obj)" } }, + { "mark_layout_as_dirty", { (const void*) &lv_obj_mark_layout_as_dirty, "", "(lv.obj)" } }, + { "move_background", { (const void*) &lv_obj_move_background, "", "(lv.obj)" } }, + { "move_children_by", { (const void*) &lv_obj_move_children_by, "", "(lv.obj)iib" } }, + { "move_foreground", { (const void*) &lv_obj_move_foreground, "", "(lv.obj)" } }, + { "move_to", { (const void*) &lv_obj_move_to, "", "(lv.obj)ii" } }, + { "move_to_index", { (const void*) &lv_obj_move_to_index, "", "(lv.obj)i" } }, + { "readjust_scroll", { (const void*) &lv_obj_readjust_scroll, "", "(lv.obj)i" } }, + { "refr_pos", { (const void*) &lv_obj_refr_pos, "", "(lv.obj)" } }, + { "refr_size", { (const void*) &lv_obj_refr_size, "b", "(lv.obj)" } }, + { "refresh_ext_draw_size", { (const void*) &lv_obj_refresh_ext_draw_size, "", "(lv.obj)" } }, + { "refresh_self_size", { (const void*) &lv_obj_refresh_self_size, "b", "(lv.obj)" } }, + { "refresh_style", { (const void*) &lv_obj_refresh_style, "", "(lv.obj)ii" } }, + { "remove", { (const void*) &lv_obj_delete, "", "(lv.obj)" } }, + { "remove_event", { (const void*) &lv_obj_remove_event, "b", "(lv.obj)i" } }, + { "remove_event_cb", { (const void*) &lv_obj_remove_event_cb, "b", "(lv.obj)." } }, + { "remove_event_cb_with_user_data", { (const void*) &lv_obj_remove_event_cb_with_user_data, "i", "(lv.obj).." } }, + { "remove_flag", { (const void*) &lv_obj_remove_flag, "", "(lv.obj)i" } }, + { "remove_local_style_prop", { (const void*) &lv_obj_remove_local_style_prop, "b", "(lv.obj)ii" } }, + { "remove_state", { (const void*) &lv_obj_remove_state, "", "(lv.obj)i" } }, + { "remove_style", { (const void*) &lv_obj_remove_style, "", "(lv.obj)(lv.style)i" } }, + { "remove_style_all", { (const void*) &lv_obj_remove_style_all, "", "(lv.obj)" } }, + { "replace_style", { (const void*) &lv_obj_replace_style, "b", "(lv.obj)(lv.style)(lv.style)i" } }, + { "scroll_by", { (const void*) &lv_obj_scroll_by, "", "(lv.obj)iii" } }, + { "scroll_by_bounded", { (const void*) &lv_obj_scroll_by_bounded, "", "(lv.obj)iii" } }, + { "scroll_to", { (const void*) &lv_obj_scroll_to, "", "(lv.obj)iii" } }, + { "scroll_to_view", { (const void*) &lv_obj_scroll_to_view, "", "(lv.obj)i" } }, + { "scroll_to_view_recursive", { (const void*) &lv_obj_scroll_to_view_recursive, "", "(lv.obj)i" } }, + { "scroll_to_x", { (const void*) &lv_obj_scroll_to_x, "", "(lv.obj)ii" } }, + { "scroll_to_y", { (const void*) &lv_obj_scroll_to_y, "", "(lv.obj)ii" } }, + { "scrollbar_invalidate", { (const void*) &lv_obj_scrollbar_invalidate, "", "(lv.obj)" } }, + { "send_event", { (const void*) &lv_obj_send_event, "i", "(lv.obj)i." } }, + { "set_align", { (const void*) &lv_obj_set_align, "", "(lv.obj)i" } }, + { "set_content_height", { (const void*) &lv_obj_set_content_height, "", "(lv.obj)i" } }, + { "set_content_width", { (const void*) &lv_obj_set_content_width, "", "(lv.obj)i" } }, + { "set_ext_click_area", { (const void*) &lv_obj_set_ext_click_area, "", "(lv.obj)i" } }, + { "set_height", { (const void*) &lv_obj_set_height, "", "(lv.obj)i" } }, + { "set_layout", { (const void*) &lv_obj_set_layout, "", "(lv.obj)i" } }, + { "set_local_style_prop", { (const void*) &lv_obj_set_local_style_prop, "", "(lv.obj)iii" } }, + { "set_parent", { (const void*) &lv_obj_set_parent, "", "(lv.obj)(lv.obj)" } }, + { "set_pos", { (const void*) &lv_obj_set_pos, "", "(lv.obj)ii" } }, + { "set_scroll_dir", { (const void*) &lv_obj_set_scroll_dir, "", "(lv.obj)i" } }, + { "set_scroll_snap_x", { (const void*) &lv_obj_set_scroll_snap_x, "", "(lv.obj)i" } }, + { "set_scroll_snap_y", { (const void*) &lv_obj_set_scroll_snap_y, "", "(lv.obj)i" } }, + { "set_scrollbar_mode", { (const void*) &lv_obj_set_scrollbar_mode, "", "(lv.obj)i" } }, + { "set_size", { (const void*) &lv_obj_set_size, "", "(lv.obj)ii" } }, + { "set_state", { (const void*) &lv_obj_set_state, "", "(lv.obj)ib" } }, + { "set_style_align", { (const void*) &lv_obj_set_style_align, "", "(lv.obj)ii" } }, + { "set_style_anim", { (const void*) &lv_obj_set_style_anim, "", "(lv.obj)(lv.anim)i" } }, + { "set_style_anim_duration", { (const void*) &lv_obj_set_style_anim_duration, "", "(lv.obj)ii" } }, + { "set_style_anim_time", { (const void*) &lv_obj_set_style_anim_duration, "", "(lv.obj)ii" } }, + { "set_style_arc_color", { (const void*) &lv_obj_set_style_arc_color, "", "(lv.obj)(lv.color)i" } }, + { "set_style_arc_image_src", { (const void*) &lv_obj_set_style_arc_image_src, "", "(lv.obj).i" } }, + { "set_style_arc_opa", { (const void*) &lv_obj_set_style_arc_opa, "", "(lv.obj)ii" } }, + { "set_style_arc_rounded", { (const void*) &lv_obj_set_style_arc_rounded, "", "(lv.obj)bi" } }, + { "set_style_arc_width", { (const void*) &lv_obj_set_style_arc_width, "", "(lv.obj)ii" } }, + { "set_style_base_dir", { (const void*) &lv_obj_set_style_base_dir, "", "(lv.obj)ii" } }, + { "set_style_bg_color", { (const void*) &lv_obj_set_style_bg_color, "", "(lv.obj)(lv.color)i" } }, + { "set_style_bg_grad", { (const void*) &lv_obj_set_style_bg_grad, "", "(lv.obj)(lv.grad_dsc)i" } }, + { "set_style_bg_grad_color", { (const void*) &lv_obj_set_style_bg_grad_color, "", "(lv.obj)(lv.color)i" } }, + { "set_style_bg_grad_dir", { (const void*) &lv_obj_set_style_bg_grad_dir, "", "(lv.obj)ii" } }, + { "set_style_bg_grad_opa", { (const void*) &lv_obj_set_style_bg_grad_opa, "", "(lv.obj)ii" } }, + { "set_style_bg_grad_stop", { (const void*) &lv_obj_set_style_bg_grad_stop, "", "(lv.obj)ii" } }, + { "set_style_bg_image_opa", { (const void*) &lv_obj_set_style_bg_image_opa, "", "(lv.obj)ii" } }, + { "set_style_bg_image_recolor", { (const void*) &lv_obj_set_style_bg_image_recolor, "", "(lv.obj)(lv.color)i" } }, + { "set_style_bg_image_recolor_opa", { (const void*) &lv_obj_set_style_bg_image_recolor_opa, "", "(lv.obj)ii" } }, + { "set_style_bg_image_src", { (const void*) &lv_obj_set_style_bg_image_src, "", "(lv.obj).i" } }, + { "set_style_bg_image_tiled", { (const void*) &lv_obj_set_style_bg_image_tiled, "", "(lv.obj)bi" } }, + { "set_style_bg_main_opa", { (const void*) &lv_obj_set_style_bg_main_opa, "", "(lv.obj)ii" } }, + { "set_style_bg_main_stop", { (const void*) &lv_obj_set_style_bg_main_stop, "", "(lv.obj)ii" } }, + { "set_style_bg_opa", { (const void*) &lv_obj_set_style_bg_opa, "", "(lv.obj)ii" } }, + { "set_style_blend_mode", { (const void*) &lv_obj_set_style_blend_mode, "", "(lv.obj)ii" } }, + { "set_style_border_color", { (const void*) &lv_obj_set_style_border_color, "", "(lv.obj)(lv.color)i" } }, + { "set_style_border_opa", { (const void*) &lv_obj_set_style_border_opa, "", "(lv.obj)ii" } }, + { "set_style_border_post", { (const void*) &lv_obj_set_style_border_post, "", "(lv.obj)bi" } }, + { "set_style_border_side", { (const void*) &lv_obj_set_style_border_side, "", "(lv.obj)ii" } }, + { "set_style_border_width", { (const void*) &lv_obj_set_style_border_width, "", "(lv.obj)ii" } }, + { "set_style_clip_corner", { (const void*) &lv_obj_set_style_clip_corner, "", "(lv.obj)bi" } }, + { "set_style_color_filter_dsc", { (const void*) &lv_obj_set_style_color_filter_dsc, "", "(lv.obj)(lv.color_filter_dsc)i" } }, + { "set_style_color_filter_opa", { (const void*) &lv_obj_set_style_color_filter_opa, "", "(lv.obj)ii" } }, + { "set_style_flex_cross_place", { (const void*) &lv_obj_set_style_flex_cross_place, "", "(lv.obj)ii" } }, + { "set_style_flex_flow", { (const void*) &lv_obj_set_style_flex_flow, "", "(lv.obj)ii" } }, + { "set_style_flex_grow", { (const void*) &lv_obj_set_style_flex_grow, "", "(lv.obj)ii" } }, + { "set_style_flex_main_place", { (const void*) &lv_obj_set_style_flex_main_place, "", "(lv.obj)ii" } }, + { "set_style_flex_track_place", { (const void*) &lv_obj_set_style_flex_track_place, "", "(lv.obj)ii" } }, + { "set_style_grid_cell_column_pos", { (const void*) &lv_obj_set_style_grid_cell_column_pos, "", "(lv.obj)ii" } }, + { "set_style_grid_cell_column_span", { (const void*) &lv_obj_set_style_grid_cell_column_span, "", "(lv.obj)ii" } }, + { "set_style_grid_cell_row_pos", { (const void*) &lv_obj_set_style_grid_cell_row_pos, "", "(lv.obj)ii" } }, + { "set_style_grid_cell_row_span", { (const void*) &lv_obj_set_style_grid_cell_row_span, "", "(lv.obj)ii" } }, + { "set_style_grid_cell_x_align", { (const void*) &lv_obj_set_style_grid_cell_x_align, "", "(lv.obj)ii" } }, + { "set_style_grid_cell_y_align", { (const void*) &lv_obj_set_style_grid_cell_y_align, "", "(lv.obj)ii" } }, + { "set_style_grid_column_align", { (const void*) &lv_obj_set_style_grid_column_align, "", "(lv.obj)ii" } }, + { "set_style_grid_column_dsc_array", { (const void*) &lv_obj_set_style_grid_column_dsc_array, "", "(lv.obj)(lv.int_arr)i" } }, + { "set_style_grid_row_align", { (const void*) &lv_obj_set_style_grid_row_align, "", "(lv.obj)ii" } }, + { "set_style_grid_row_dsc_array", { (const void*) &lv_obj_set_style_grid_row_dsc_array, "", "(lv.obj)(lv.int_arr)i" } }, + { "set_style_height", { (const void*) &lv_obj_set_style_height, "", "(lv.obj)ii" } }, + { "set_style_image_opa", { (const void*) &lv_obj_set_style_image_opa, "", "(lv.obj)ii" } }, + { "set_style_image_recolor", { (const void*) &lv_obj_set_style_image_recolor, "", "(lv.obj)(lv.color)i" } }, + { "set_style_image_recolor_opa", { (const void*) &lv_obj_set_style_image_recolor_opa, "", "(lv.obj)ii" } }, + { "set_style_img_opa", { (const void*) &lv_obj_set_style_image_opa, "", "(lv.obj)ii" } }, + { "set_style_img_recolor", { (const void*) &lv_obj_set_style_image_recolor, "", "(lv.obj)(lv.color)i" } }, + { "set_style_img_recolor_opa", { (const void*) &lv_obj_set_style_image_recolor_opa, "", "(lv.obj)ii" } }, + { "set_style_layout", { (const void*) &lv_obj_set_style_layout, "", "(lv.obj)ii" } }, + { "set_style_length", { (const void*) &lv_obj_set_style_length, "", "(lv.obj)ii" } }, + { "set_style_line_color", { (const void*) &lv_obj_set_style_line_color, "", "(lv.obj)(lv.color)i" } }, + { "set_style_line_dash_gap", { (const void*) &lv_obj_set_style_line_dash_gap, "", "(lv.obj)ii" } }, + { "set_style_line_dash_width", { (const void*) &lv_obj_set_style_line_dash_width, "", "(lv.obj)ii" } }, + { "set_style_line_opa", { (const void*) &lv_obj_set_style_line_opa, "", "(lv.obj)ii" } }, + { "set_style_line_rounded", { (const void*) &lv_obj_set_style_line_rounded, "", "(lv.obj)bi" } }, + { "set_style_line_width", { (const void*) &lv_obj_set_style_line_width, "", "(lv.obj)ii" } }, + { "set_style_margin_all", { (const void*) &lv_obj_set_style_margin_all, "", "(lv.obj)ii" } }, + { "set_style_margin_bottom", { (const void*) &lv_obj_set_style_margin_bottom, "", "(lv.obj)ii" } }, + { "set_style_margin_hor", { (const void*) &lv_obj_set_style_margin_hor, "", "(lv.obj)ii" } }, + { "set_style_margin_left", { (const void*) &lv_obj_set_style_margin_left, "", "(lv.obj)ii" } }, + { "set_style_margin_right", { (const void*) &lv_obj_set_style_margin_right, "", "(lv.obj)ii" } }, + { "set_style_margin_top", { (const void*) &lv_obj_set_style_margin_top, "", "(lv.obj)ii" } }, + { "set_style_margin_ver", { (const void*) &lv_obj_set_style_margin_ver, "", "(lv.obj)ii" } }, + { "set_style_max_height", { (const void*) &lv_obj_set_style_max_height, "", "(lv.obj)ii" } }, + { "set_style_max_width", { (const void*) &lv_obj_set_style_max_width, "", "(lv.obj)ii" } }, + { "set_style_min_height", { (const void*) &lv_obj_set_style_min_height, "", "(lv.obj)ii" } }, + { "set_style_min_width", { (const void*) &lv_obj_set_style_min_width, "", "(lv.obj)ii" } }, + { "set_style_opa", { (const void*) &lv_obj_set_style_opa, "", "(lv.obj)ii" } }, + { "set_style_opa_layered", { (const void*) &lv_obj_set_style_opa_layered, "", "(lv.obj)ii" } }, + { "set_style_outline_color", { (const void*) &lv_obj_set_style_outline_color, "", "(lv.obj)(lv.color)i" } }, + { "set_style_outline_opa", { (const void*) &lv_obj_set_style_outline_opa, "", "(lv.obj)ii" } }, + { "set_style_outline_pad", { (const void*) &lv_obj_set_style_outline_pad, "", "(lv.obj)ii" } }, + { "set_style_outline_width", { (const void*) &lv_obj_set_style_outline_width, "", "(lv.obj)ii" } }, + { "set_style_pad_all", { (const void*) &lv_obj_set_style_pad_all, "", "(lv.obj)ii" } }, + { "set_style_pad_bottom", { (const void*) &lv_obj_set_style_pad_bottom, "", "(lv.obj)ii" } }, + { "set_style_pad_column", { (const void*) &lv_obj_set_style_pad_column, "", "(lv.obj)ii" } }, + { "set_style_pad_gap", { (const void*) &lv_obj_set_style_pad_gap, "", "(lv.obj)ii" } }, + { "set_style_pad_hor", { (const void*) &lv_obj_set_style_pad_hor, "", "(lv.obj)ii" } }, + { "set_style_pad_left", { (const void*) &lv_obj_set_style_pad_left, "", "(lv.obj)ii" } }, + { "set_style_pad_right", { (const void*) &lv_obj_set_style_pad_right, "", "(lv.obj)ii" } }, + { "set_style_pad_row", { (const void*) &lv_obj_set_style_pad_row, "", "(lv.obj)ii" } }, + { "set_style_pad_top", { (const void*) &lv_obj_set_style_pad_top, "", "(lv.obj)ii" } }, + { "set_style_pad_ver", { (const void*) &lv_obj_set_style_pad_ver, "", "(lv.obj)ii" } }, + { "set_style_radius", { (const void*) &lv_obj_set_style_radius, "", "(lv.obj)ii" } }, + { "set_style_shadow_color", { (const void*) &lv_obj_set_style_shadow_color, "", "(lv.obj)(lv.color)i" } }, + { "set_style_shadow_offset_x", { (const void*) &lv_obj_set_style_shadow_offset_x, "", "(lv.obj)ii" } }, + { "set_style_shadow_offset_y", { (const void*) &lv_obj_set_style_shadow_offset_y, "", "(lv.obj)ii" } }, + { "set_style_shadow_ofs_x", { (const void*) &lv_obj_set_style_shadow_offset_x, "", "(lv.obj)ii" } }, + { "set_style_shadow_ofs_y", { (const void*) &lv_obj_set_style_shadow_offset_y, "", "(lv.obj)ii" } }, + { "set_style_shadow_opa", { (const void*) &lv_obj_set_style_shadow_opa, "", "(lv.obj)ii" } }, + { "set_style_shadow_spread", { (const void*) &lv_obj_set_style_shadow_spread, "", "(lv.obj)ii" } }, + { "set_style_shadow_width", { (const void*) &lv_obj_set_style_shadow_width, "", "(lv.obj)ii" } }, + { "set_style_size", { (const void*) &lv_obj_set_style_size, "", "(lv.obj)iii" } }, + { "set_style_text_align", { (const void*) &lv_obj_set_style_text_align, "", "(lv.obj)ii" } }, + { "set_style_text_color", { (const void*) &lv_obj_set_style_text_color, "", "(lv.obj)(lv.color)i" } }, + { "set_style_text_decor", { (const void*) &lv_obj_set_style_text_decor, "", "(lv.obj)ii" } }, + { "set_style_text_font", { (const void*) &lv_obj_set_style_text_font, "", "(lv.obj)(lv.font)i" } }, + { "set_style_text_letter_space", { (const void*) &lv_obj_set_style_text_letter_space, "", "(lv.obj)ii" } }, + { "set_style_text_line_space", { (const void*) &lv_obj_set_style_text_line_space, "", "(lv.obj)ii" } }, + { "set_style_text_opa", { (const void*) &lv_obj_set_style_text_opa, "", "(lv.obj)ii" } }, + { "set_style_transform_angle", { (const void*) &lv_obj_set_style_transform_rotation, "", "(lv.obj)ii" } }, + { "set_style_transform_height", { (const void*) &lv_obj_set_style_transform_height, "", "(lv.obj)ii" } }, + { "set_style_transform_pivot_x", { (const void*) &lv_obj_set_style_transform_pivot_x, "", "(lv.obj)ii" } }, + { "set_style_transform_pivot_y", { (const void*) &lv_obj_set_style_transform_pivot_y, "", "(lv.obj)ii" } }, + { "set_style_transform_rotation", { (const void*) &lv_obj_set_style_transform_rotation, "", "(lv.obj)ii" } }, + { "set_style_transform_scale", { (const void*) &lv_obj_set_style_transform_scale, "", "(lv.obj)ii" } }, + { "set_style_transform_scale_x", { (const void*) &lv_obj_set_style_transform_scale_x, "", "(lv.obj)ii" } }, + { "set_style_transform_scale_y", { (const void*) &lv_obj_set_style_transform_scale_y, "", "(lv.obj)ii" } }, + { "set_style_transform_skew_x", { (const void*) &lv_obj_set_style_transform_skew_x, "", "(lv.obj)ii" } }, + { "set_style_transform_skew_y", { (const void*) &lv_obj_set_style_transform_skew_y, "", "(lv.obj)ii" } }, + { "set_style_transform_width", { (const void*) &lv_obj_set_style_transform_width, "", "(lv.obj)ii" } }, + { "set_style_transform_zoom", { (const void*) &lv_obj_set_style_transform_scale, "", "(lv.obj)ii" } }, + { "set_style_transition", { (const void*) &lv_obj_set_style_transition, "", "(lv.obj)(lv.style_transition_dsc)i" } }, + { "set_style_translate_x", { (const void*) &lv_obj_set_style_translate_x, "", "(lv.obj)ii" } }, + { "set_style_translate_y", { (const void*) &lv_obj_set_style_translate_y, "", "(lv.obj)ii" } }, + { "set_style_width", { (const void*) &lv_obj_set_style_width, "", "(lv.obj)ii" } }, + { "set_style_x", { (const void*) &lv_obj_set_style_x, "", "(lv.obj)ii" } }, + { "set_style_y", { (const void*) &lv_obj_set_style_y, "", "(lv.obj)ii" } }, + { "set_user_data", { (const void*) &lv_obj_set_user_data, "", "(lv.obj)." } }, + { "set_width", { (const void*) &lv_obj_set_width, "", "(lv.obj)i" } }, + { "set_x", { (const void*) &lv_obj_set_x, "", "(lv.obj)i" } }, + { "set_y", { (const void*) &lv_obj_set_y, "", "(lv.obj)i" } }, + { "stringify_id", { (const void*) &lv_obj_stringify_id, "s", "(lv.obj)ci" } }, + { "swap", { (const void*) &lv_obj_swap, "", "(lv.obj)(lv.obj)" } }, + { "transform_point", { (const void*) &lv_obj_transform_point, "", "(lv.obj)cbb" } }, + { "update_flag", { (const void*) &lv_obj_update_flag, "", "(lv.obj)ib" } }, + { "update_layout", { (const void*) &lv_obj_update_layout, "", "(lv.obj)" } }, + { "update_snap", { (const void*) &lv_obj_update_snap, "", "(lv.obj)i" } }, +}; +#endif // BE_LV_WIDGET_OBJ + +/* `lv_event` methods */ +const be_ntv_func_def_t lv_event_func[] = { + { "get_code", { (const void*) &lv_event_get_code, "i", "(lv.event)" } }, + { "get_cover_area", { (const void*) &lv_event_get_cover_area, "lv.area", "(lv.event)" } }, + { "get_current_target", { (const void*) &lv_event_get_current_target, "c", "(lv.event)" } }, + { "get_current_target_obj", { (const void*) &lv_event_get_current_target_obj, "lv.obj", "(lv.event)" } }, + { "get_hit_test_info", { (const void*) &lv_event_get_hit_test_info, "c", "(lv.event)" } }, + { "get_indev", { (const void*) &lv_event_get_indev, "lv.indev", "(lv.event)" } }, + { "get_key", { (const void*) &lv_event_get_key, "i", "(lv.event)" } }, + { "get_layer", { (const void*) &lv_event_get_layer, "c", "(lv.event)" } }, + { "get_old_size", { (const void*) &lv_event_get_old_size, "lv.area", "(lv.event)" } }, + { "get_param", { (const void*) &lv_event_get_param, "c", "(lv.event)" } }, + { "get_scroll_anim", { (const void*) &lv_event_get_scroll_anim, "lv.anim", "(lv.event)" } }, + { "get_self_size_info", { (const void*) &lv_event_get_self_size_info, "c", "(lv.event)" } }, + { "get_target", { (const void*) &lv_event_get_target, "c", "(lv.event)" } }, + { "get_target_obj", { (const void*) &lv_event_get_target_obj, "lv.obj", "(lv.event)" } }, + { "get_user_data", { (const void*) &lv_event_get_user_data, "c", "(lv.event)" } }, + { "set_cover_res", { (const void*) &lv_event_set_cover_res, "", "(lv.event)i" } }, + { "set_ext_draw_size", { (const void*) &lv_event_set_ext_draw_size, "", "(lv.event)i" } }, + { "stop_bubbling", { (const void*) &lv_event_stop_bubbling, "", "(lv.event)" } }, + { "stop_processing", { (const void*) &lv_event_stop_processing, "", "(lv.event)" } }, +}; + +/* `lv_display` methods */ +const be_ntv_func_def_t lv_display_func[] = { + { "add_event_cb", { (const void*) &lv_display_add_event_cb, "", "(lv.display)^lv_event_cb^i." } }, + { "del", { (const void*) &lv_display_delete, "", "(lv.display)" } }, + { "delete", { (const void*) &lv_display_delete, "", "(lv.display)" } }, + { "delete_event", { (const void*) &lv_display_delete_event, "b", "(lv.display)i" } }, + { "delete_refr_timer", { (const void*) &lv_display_delete_refr_timer, "", "(lv.display)" } }, + { "dpx", { (const void*) &lv_display_dpx, "i", "(lv.display)i" } }, + { "enable_invalidation", { (const void*) &lv_display_enable_invalidation, "", "(lv.display)b" } }, + { "get_angle", { (const void*) &lv_display_get_rotation, "i", "(lv.display)" } }, + { "get_antialiasing", { (const void*) &lv_display_get_antialiasing, "b", "(lv.display)" } }, + { "get_color_format", { (const void*) &lv_display_get_color_format, "i", "(lv.display)" } }, + { "get_dpi", { (const void*) &lv_display_get_dpi, "i", "(lv.display)" } }, + { "get_driver_data", { (const void*) &lv_display_get_driver_data, "c", "(lv.display)" } }, + { "get_event_count", { (const void*) &lv_display_get_event_count, "i", "(lv.display)" } }, + { "get_hor_res", { (const void*) &lv_display_get_horizontal_resolution, "i", "(lv.display)" } }, + { "get_horizontal_resolution", { (const void*) &lv_display_get_horizontal_resolution, "i", "(lv.display)" } }, + { "get_inactive_time", { (const void*) &lv_display_get_inactive_time, "i", "(lv.display)" } }, + { "get_layer_bottom", { (const void*) &lv_display_get_layer_bottom, "lv.obj", "(lv.display)" } }, + { "get_layer_sys", { (const void*) &lv_display_get_layer_sys, "lv.obj", "(lv.display)" } }, + { "get_layer_top", { (const void*) &lv_display_get_layer_top, "lv.obj", "(lv.display)" } }, + { "get_next", { (const void*) &lv_display_get_next, "lv.display", "(lv.display)" } }, + { "get_offset_x", { (const void*) &lv_display_get_offset_x, "i", "(lv.display)" } }, + { "get_offset_y", { (const void*) &lv_display_get_offset_y, "i", "(lv.display)" } }, + { "get_physical_hor_res", { (const void*) &lv_display_get_physical_horizontal_resolution, "i", "(lv.display)" } }, + { "get_physical_horizontal_resolution", { (const void*) &lv_display_get_physical_horizontal_resolution, "i", "(lv.display)" } }, + { "get_physical_ver_res", { (const void*) &lv_display_get_physical_vertical_resolution, "i", "(lv.display)" } }, + { "get_physical_vertical_resolution", { (const void*) &lv_display_get_physical_vertical_resolution, "i", "(lv.display)" } }, + { "get_refr_timer", { (const void*) &lv_display_get_refr_timer, "lv.timer", "(lv.display)" } }, + { "get_rotation", { (const void*) &lv_display_get_rotation, "i", "(lv.display)" } }, + { "get_scr_act", { (const void*) &lv_display_get_screen_active, "lv.obj", "(lv.display)" } }, + { "get_scr_prev", { (const void*) &lv_display_get_screen_prev, "lv.obj", "(lv.display)" } }, + { "get_screen_active", { (const void*) &lv_display_get_screen_active, "lv.obj", "(lv.display)" } }, + { "get_screen_prev", { (const void*) &lv_display_get_screen_prev, "lv.obj", "(lv.display)" } }, + { "get_theme", { (const void*) &lv_display_get_theme, "lv.theme", "(lv.display)" } }, + { "get_user_data", { (const void*) &lv_display_get_user_data, "c", "(lv.display)" } }, + { "get_ver_res", { (const void*) &lv_display_get_vertical_resolution, "i", "(lv.display)" } }, + { "get_vertical_resolution", { (const void*) &lv_display_get_vertical_resolution, "i", "(lv.display)" } }, + { "is_double_buffered", { (const void*) &lv_display_is_double_buffered, "b", "(lv.display)" } }, + { "is_invalidation_enabled", { (const void*) &lv_display_is_invalidation_enabled, "b", "(lv.display)" } }, + { "remove", { (const void*) &lv_display_delete, "", "(lv.display)" } }, + { "remove_event_cb_with_user_data", { (const void*) &lv_display_remove_event_cb_with_user_data, "i", "(lv.display).." } }, + { "send_event", { (const void*) &lv_display_send_event, "i", "(lv.display)i." } }, + { "set_angle", { (const void*) &lv_display_set_rotation, "", "(lv.display)i" } }, + { "set_antialiasing", { (const void*) &lv_display_set_antialiasing, "", "(lv.display)b" } }, + { "set_buffers", { (const void*) &lv_display_set_buffers, "", "(lv.display)..ii" } }, + { "set_color_format", { (const void*) &lv_display_set_color_format, "", "(lv.display)i" } }, + { "set_default", { (const void*) &lv_display_set_default, "", "(lv.display)" } }, + { "set_dpi", { (const void*) &lv_display_set_dpi, "", "(lv.display)i" } }, + { "set_driver_data", { (const void*) &lv_display_set_driver_data, "", "(lv.display)." } }, + { "set_offset", { (const void*) &lv_display_set_offset, "", "(lv.display)ii" } }, + { "set_physical_resolution", { (const void*) &lv_display_set_physical_resolution, "", "(lv.display)ii" } }, + { "set_render_mode", { (const void*) &lv_display_set_render_mode, "", "(lv.display)i" } }, + { "set_resolution", { (const void*) &lv_display_set_resolution, "", "(lv.display)ii" } }, + { "set_rotation", { (const void*) &lv_display_set_rotation, "", "(lv.display)i" } }, + { "set_theme", { (const void*) &lv_display_set_theme, "", "(lv.display)(lv.theme)" } }, + { "set_user_data", { (const void*) &lv_display_set_user_data, "", "(lv.display)." } }, + { "trig_activity", { (const void*) &lv_display_trigger_activity, "", "(lv.display)" } }, + { "trigger_activity", { (const void*) &lv_display_trigger_activity, "", "(lv.display)" } }, }; /* `lv_indev` methods */ const be_ntv_func_def_t lv_indev_func[] = { - { "enable", { (const void*) &lv_indev_enable, "", "(lv.lv_indev)b" } }, - { "get_gesture_dir", { (const void*) &lv_indev_get_gesture_dir, "i", "(lv.lv_indev)" } }, - { "get_key", { (const void*) &lv_indev_get_key, "i", "(lv.lv_indev)" } }, - { "get_point", { (const void*) &lv_indev_get_point, "", "(lv.lv_indev)(lv.lv_point)" } }, - { "get_scroll_dir", { (const void*) &lv_indev_get_scroll_dir, "i", "(lv.lv_indev)" } }, - { "get_scroll_obj", { (const void*) &lv_indev_get_scroll_obj, "lv.lv_obj", "(lv.lv_indev)" } }, - { "get_type", { (const void*) &lv_indev_get_type, "i", "(lv.lv_indev)" } }, - { "get_vect", { (const void*) &lv_indev_get_vect, "", "(lv.lv_indev)(lv.lv_point)" } }, - { "reset", { (const void*) &lv_indev_reset, "", "(lv.lv_indev)(lv.lv_obj)" } }, - { "reset_long_press", { (const void*) &lv_indev_reset_long_press, "", "(lv.lv_indev)" } }, - { "search_obj", { (const void*) &lv_indev_search_obj, "lv.lv_obj", "(lv.lv_obj)(lv.lv_point)" } }, - { "set_button_points", { (const void*) &lv_indev_set_button_points, "", "(lv.lv_indev)(lv.lv_point_arr)" } }, - { "set_cursor", { (const void*) &lv_indev_set_cursor, "", "(lv.lv_indev)(lv.lv_obj)" } }, - { "set_group", { (const void*) &lv_indev_set_group, "", "(lv.lv_indev)(lv.lv_group)" } }, - { "wait_release", { (const void*) &lv_indev_wait_release, "", "(lv.lv_indev)" } }, + { "add_event_cb", { (const void*) &lv_indev_add_event_cb, "", "(lv.indev)^lv_event_cb^i." } }, + { "del", { (const void*) &lv_indev_delete, "", "(lv.indev)" } }, + { "delete", { (const void*) &lv_indev_delete, "", "(lv.indev)" } }, + { "enable", { (const void*) &lv_indev_enable, "", "(lv.indev)b" } }, + { "get_disp", { (const void*) &lv_indev_get_display, "lv.display", "(lv.indev)" } }, + { "get_display", { (const void*) &lv_indev_get_display, "lv.display", "(lv.indev)" } }, + { "get_driver_data", { (const void*) &lv_indev_get_driver_data, "c", "(lv.indev)" } }, + { "get_event_count", { (const void*) &lv_indev_get_event_count, "i", "(lv.indev)" } }, + { "get_gesture_dir", { (const void*) &lv_indev_get_gesture_dir, "i", "(lv.indev)" } }, + { "get_group", { (const void*) &lv_indev_get_group, "lv.group", "(lv.indev)" } }, + { "get_key", { (const void*) &lv_indev_get_key, "i", "(lv.indev)" } }, + { "get_mode", { (const void*) &lv_indev_get_mode, "i", "(lv.indev)" } }, + { "get_next", { (const void*) &lv_indev_get_next, "lv.indev", "(lv.indev)" } }, + { "get_point", { (const void*) &lv_indev_get_point, "", "(lv.indev)c" } }, + { "get_read_timer", { (const void*) &lv_indev_get_read_timer, "lv.timer", "(lv.indev)" } }, + { "get_scroll_dir", { (const void*) &lv_indev_get_scroll_dir, "i", "(lv.indev)" } }, + { "get_scroll_obj", { (const void*) &lv_indev_get_scroll_obj, "lv.obj", "(lv.indev)" } }, + { "get_state", { (const void*) &lv_indev_get_state, "i", "(lv.indev)" } }, + { "get_type", { (const void*) &lv_indev_get_type, "i", "(lv.indev)" } }, + { "get_user_data", { (const void*) &lv_indev_get_user_data, "c", "(lv.indev)" } }, + { "get_vect", { (const void*) &lv_indev_get_vect, "", "(lv.indev)c" } }, + { "read", { (const void*) &lv_indev_read, "", "(lv.indev)" } }, + { "remove", { (const void*) &lv_indev_delete, "", "(lv.indev)" } }, + { "remove_event", { (const void*) &lv_indev_remove_event, "b", "(lv.indev)i" } }, + { "remove_event_cb_with_user_data", { (const void*) &lv_indev_remove_event_cb_with_user_data, "i", "(lv.indev).." } }, + { "reset", { (const void*) &lv_indev_reset, "", "(lv.indev)(lv.obj)" } }, + { "reset_long_press", { (const void*) &lv_indev_reset_long_press, "", "(lv.indev)" } }, + { "search_obj", { (const void*) &lv_indev_search_obj, "lv.obj", "(lv.obj)c" } }, + { "send_event", { (const void*) &lv_indev_send_event, "i", "(lv.indev)i." } }, + { "set_button_points", { (const void*) &lv_indev_set_button_points, "", "(lv.indev)(lv.point_arr)" } }, + { "set_cursor", { (const void*) &lv_indev_set_cursor, "", "(lv.indev)(lv.obj)" } }, + { "set_disp", { (const void*) &lv_indev_set_display, "", "(lv.indev)(lv.display)" } }, + { "set_display", { (const void*) &lv_indev_set_display, "", "(lv.indev)(lv.display)" } }, + { "set_driver_data", { (const void*) &lv_indev_set_driver_data, "", "(lv.indev)." } }, + { "set_group", { (const void*) &lv_indev_set_group, "", "(lv.indev)(lv.group)" } }, + { "set_mode", { (const void*) &lv_indev_set_mode, "", "(lv.indev)i" } }, + { "set_type", { (const void*) &lv_indev_set_type, "", "(lv.indev)i" } }, + { "set_user_data", { (const void*) &lv_indev_set_user_data, "", "(lv.indev)." } }, + { "wait_release", { (const void*) &lv_indev_wait_release, "", "(lv.indev)" } }, }; /* `lv_qrcode` methods */ #ifdef BE_LV_WIDGET_QRCODE const be_ntv_func_def_t lv_qrcode_func[] = { - { "delete", { (const void*) &lv_qrcode_delete, "", "(lv.lv_obj)" } }, - { "update", { (const void*) &lv_qrcode_update, "i", "(lv.lv_obj).i" } }, + { "set_dark_color", { (const void*) &lv_qrcode_set_dark_color, "", "(lv.obj)(lv.color)" } }, + { "set_light_color", { (const void*) &lv_qrcode_set_light_color, "", "(lv.obj)(lv.color)" } }, + { "set_size", { (const void*) &lv_qrcode_set_size, "", "(lv.obj)i" } }, + { "update", { (const void*) &lv_qrcode_update, "i", "(lv.obj).i" } }, }; #endif // BE_LV_WIDGET_QRCODE -/* `lv_chart` methods */ -#ifdef BE_LV_WIDGET_CHART -const be_ntv_func_def_t lv_chart_func[] = { - { "add_cursor", { (const void*) &lv_chart_add_cursor, "lv.lv_chart_cursor", "(lv.lv_obj)(lv.lv_color)i" } }, - { "add_series", { (const void*) &lv_chart_add_series, "lv.lv_chart_series", "(lv.lv_obj)(lv.lv_color)i" } }, - { "get_cursor_point", { (const void*) &lv_chart_get_cursor_point, "i", "(lv.lv_obj)(lv.lv_chart_cursor)" } }, - { "get_point_count", { (const void*) &lv_chart_get_point_count, "i", "(lv.lv_obj)" } }, - { "get_point_pos_by_id", { (const void*) &lv_chart_get_point_pos_by_id, "", "(lv.lv_obj)(lv.lv_chart_series)i(lv.lv_point)" } }, - { "get_pressed_point", { (const void*) &lv_chart_get_pressed_point, "i", "(lv.lv_obj)" } }, - { "get_series_next", { (const void*) &lv_chart_get_series_next, "lv.lv_chart_series", "(lv.lv_obj)(lv.lv_chart_series)" } }, - { "get_type", { (const void*) &lv_chart_get_type, "i", "(lv.lv_obj)" } }, - { "get_x_array", { (const void*) &lv_chart_get_x_array, "c", "(lv.lv_obj)(lv.lv_chart_series)" } }, - { "get_x_start_point", { (const void*) &lv_chart_get_x_start_point, "i", "(lv.lv_obj)(lv.lv_chart_series)" } }, - { "get_y_array", { (const void*) &lv_chart_get_y_array, "c", "(lv.lv_obj)(lv.lv_chart_series)" } }, - { "get_zoom_x", { (const void*) &lv_chart_get_zoom_x, "i", "(lv.lv_obj)" } }, - { "get_zoom_y", { (const void*) &lv_chart_get_zoom_y, "i", "(lv.lv_obj)" } }, - { "hide_series", { (const void*) &lv_chart_hide_series, "", "(lv.lv_obj)(lv.lv_chart_series)b" } }, - { "refresh", { (const void*) &lv_chart_refresh, "", "(lv.lv_obj)" } }, - { "remove_series", { (const void*) &lv_chart_remove_series, "", "(lv.lv_obj)(lv.lv_chart_series)" } }, - { "set_all_value", { (const void*) &lv_chart_set_all_value, "", "(lv.lv_obj)(lv.lv_chart_series)i" } }, - { "set_axis_tick", { (const void*) &lv_chart_set_axis_tick, "", "(lv.lv_obj)iiiiibi" } }, - { "set_cursor_point", { (const void*) &lv_chart_set_cursor_point, "", "(lv.lv_obj)(lv.lv_chart_cursor)(lv.lv_chart_series)i" } }, - { "set_cursor_pos", { (const void*) &lv_chart_set_cursor_pos, "", "(lv.lv_obj)(lv.lv_chart_cursor)(lv.lv_point)" } }, - { "set_div_line_count", { (const void*) &lv_chart_set_div_line_count, "", "(lv.lv_obj)ii" } }, - { "set_ext_x_array", { (const void*) &lv_chart_set_ext_x_array, "", "(lv.lv_obj)(lv.lv_chart_series)(lv.lv_coord_arr)" } }, - { "set_ext_y_array", { (const void*) &lv_chart_set_ext_y_array, "", "(lv.lv_obj)(lv.lv_chart_series)(lv.lv_coord_arr)" } }, - { "set_next_value", { (const void*) &lv_chart_set_next_value, "", "(lv.lv_obj)(lv.lv_chart_series)i" } }, - { "set_next_value2", { (const void*) &lv_chart_set_next_value2, "", "(lv.lv_obj)(lv.lv_chart_series)ii" } }, - { "set_point_count", { (const void*) &lv_chart_set_point_count, "", "(lv.lv_obj)i" } }, - { "set_range", { (const void*) &lv_chart_set_range, "", "(lv.lv_obj)iii" } }, - { "set_series_color", { (const void*) &lv_chart_set_series_color, "", "(lv.lv_obj)(lv.lv_chart_series)(lv.lv_color)" } }, - { "set_type", { (const void*) &lv_chart_set_type, "", "(lv.lv_obj)i" } }, - { "set_update_mode", { (const void*) &lv_chart_set_update_mode, "", "(lv.lv_obj)i" } }, - { "set_value_by_id", { (const void*) &lv_chart_set_value_by_id, "", "(lv.lv_obj)(lv.lv_chart_series)ii" } }, - { "set_value_by_id2", { (const void*) &lv_chart_set_value_by_id2, "", "(lv.lv_obj)(lv.lv_chart_series)iii" } }, - { "set_x_start_point", { (const void*) &lv_chart_set_x_start_point, "", "(lv.lv_obj)(lv.lv_chart_series)i" } }, - { "set_zoom_x", { (const void*) &lv_chart_set_zoom_x, "", "(lv.lv_obj)i" } }, - { "set_zoom_y", { (const void*) &lv_chart_set_zoom_y, "", "(lv.lv_obj)i" } }, -}; -#endif // BE_LV_WIDGET_CHART - -/* `lv_colorwheel` methods */ -#ifdef BE_LV_WIDGET_COLORWHEEL -const be_ntv_func_def_t lv_colorwheel_func[] = { - { "get_color_mode", { (const void*) &lv_colorwheel_get_color_mode, "i", "(lv.lv_obj)" } }, - { "get_color_mode_fixed", { (const void*) &lv_colorwheel_get_color_mode_fixed, "b", "(lv.lv_obj)" } }, - { "get_hsv", { (const void*) &lv_colorwheel_get_hsv, "i", "(lv.lv_obj)" } }, - { "get_rgb", { (const void*) &lv_colorwheel_get_rgb, "lv.lv_color", "(lv.lv_obj)" } }, - { "set_hsv", { (const void*) &lv_colorwheel_set_hsv, "b", "(lv.lv_obj)i" } }, - { "set_mode", { (const void*) &lv_colorwheel_set_mode, "", "(lv.lv_obj)i" } }, - { "set_mode_fixed", { (const void*) &lv_colorwheel_set_mode_fixed, "", "(lv.lv_obj)b" } }, - { "set_rgb", { (const void*) &lv_colorwheel_set_rgb, "b", "(lv.lv_obj)(lv.lv_color)" } }, -}; -#endif // BE_LV_WIDGET_COLORWHEEL - -/* `lv_imgbtn` methods */ -#ifdef BE_LV_WIDGET_IMGBTN -const be_ntv_func_def_t lv_imgbtn_func[] = { - { "set_src", { (const void*) &lv_imgbtn_set_src, "", "(lv.lv_obj)i..." } }, - { "set_state", { (const void*) &lv_imgbtn_set_state, "", "(lv.lv_obj)i" } }, -}; -#endif // BE_LV_WIDGET_IMGBTN - -/* `lv_keyboard` methods */ -#ifdef BE_LV_WIDGET_KEYBOARD -const be_ntv_func_def_t lv_keyboard_func[] = { - { "get_btn_text", { (const void*) &lv_keyboard_get_btn_text, "s", "(lv.lv_obj)i" } }, - { "get_map_array", { (const void*) &lv_keyboard_get_map_array, "c", "(lv.lv_obj)" } }, - { "get_mode", { (const void*) &lv_keyboard_get_mode, "i", "(lv.lv_obj)" } }, - { "get_selected_btn", { (const void*) &lv_keyboard_get_selected_btn, "i", "(lv.lv_obj)" } }, - { "get_textarea", { (const void*) &lv_keyboard_get_textarea, "lv.lv_obj", "(lv.lv_obj)" } }, - { "set_map", { (const void*) &lv_keyboard_set_map, "", "(lv.lv_obj)i(lv.str_arr)(lv.lv_btnmatrix_ctrl)" } }, - { "set_mode", { (const void*) &lv_keyboard_set_mode, "", "(lv.lv_obj)i" } }, - { "set_popovers", { (const void*) &lv_keyboard_set_popovers, "", "(lv.lv_obj)b" } }, - { "set_textarea", { (const void*) &lv_keyboard_set_textarea, "", "(lv.lv_obj)(lv.lv_obj)" } }, -}; -#endif // BE_LV_WIDGET_KEYBOARD - -/* `lv_btnmatrix` methods */ -#ifdef BE_LV_WIDGET_BTNMATRIX -const be_ntv_func_def_t lv_btnmatrix_func[] = { - { "clear_btn_ctrl", { (const void*) &lv_btnmatrix_clear_btn_ctrl, "", "(lv.lv_obj)ii" } }, - { "clear_btn_ctrl_all", { (const void*) &lv_btnmatrix_clear_btn_ctrl_all, "", "(lv.lv_obj)i" } }, - { "get_btn_text", { (const void*) &lv_btnmatrix_get_btn_text, "s", "(lv.lv_obj)i" } }, - { "get_map", { (const void*) &lv_btnmatrix_get_map, "c", "(lv.lv_obj)" } }, - { "get_one_checked", { (const void*) &lv_btnmatrix_get_one_checked, "b", "(lv.lv_obj)" } }, - { "get_popovers", { (const void*) &lv_btnmatrix_get_popovers, "b", "(lv.lv_obj)" } }, - { "get_selected_btn", { (const void*) &lv_btnmatrix_get_selected_btn, "i", "(lv.lv_obj)" } }, - { "has_btn_ctrl", { (const void*) &lv_btnmatrix_has_btn_ctrl, "b", "(lv.lv_obj)ii" } }, - { "set_btn_ctrl", { (const void*) &lv_btnmatrix_set_btn_ctrl, "", "(lv.lv_obj)ii" } }, - { "set_btn_ctrl_all", { (const void*) &lv_btnmatrix_set_btn_ctrl_all, "", "(lv.lv_obj)i" } }, - { "set_btn_width", { (const void*) &lv_btnmatrix_set_btn_width, "", "(lv.lv_obj)ii" } }, - { "set_ctrl_map", { (const void*) &lv_btnmatrix_set_ctrl_map, "", "(lv.lv_obj)(lv.lv_btnmatrix_ctrl)" } }, - { "set_map", { (const void*) &lv_btnmatrix_set_map, "", "(lv.lv_obj)(lv.str_arr)" } }, - { "set_one_checked", { (const void*) &lv_btnmatrix_set_one_checked, "", "(lv.lv_obj)b" } }, - { "set_selected_btn", { (const void*) &lv_btnmatrix_set_selected_btn, "", "(lv.lv_obj)i" } }, -}; -#endif // BE_LV_WIDGET_BTNMATRIX - -/* `lv_led` methods */ -#ifdef BE_LV_WIDGET_LED -const be_ntv_func_def_t lv_led_func[] = { - { "get_brightness", { (const void*) &lv_led_get_brightness, "i", "(lv.lv_obj)" } }, - { "off", { (const void*) &lv_led_off, "", "(lv.lv_obj)" } }, - { "on", { (const void*) &lv_led_on, "", "(lv.lv_obj)" } }, - { "set_brightness", { (const void*) &lv_led_set_brightness, "", "(lv.lv_obj)i" } }, - { "set_color", { (const void*) &lv_led_set_color, "", "(lv.lv_obj)(lv.lv_color)" } }, - { "toggle", { (const void*) &lv_led_toggle, "", "(lv.lv_obj)" } }, -}; -#endif // BE_LV_WIDGET_LED - -/* `lv_list` methods */ -#ifdef BE_LV_WIDGET_LIST -const be_ntv_func_def_t lv_list_func[] = { - { "add_btn", { (const void*) &lv_list_add_btn, "lv.lv_obj", "(lv.lv_obj).s" } }, - { "add_text", { (const void*) &lv_list_add_text, "lv.lv_obj", "(lv.lv_obj)s" } }, - { "get_btn_text", { (const void*) &lv_list_get_btn_text, "s", "(lv.lv_obj)(lv.lv_obj)" } }, -}; -#endif // BE_LV_WIDGET_LIST - -/* `lv_meter` methods */ -#ifdef BE_LV_WIDGET_METER -const be_ntv_func_def_t lv_meter_func[] = { - { "add_arc", { (const void*) &lv_meter_add_arc, "lv.lv_meter_indicator", "(lv.lv_obj)(lv.lv_meter_scale)i(lv.lv_color)i" } }, - { "add_needle_img", { (const void*) &lv_meter_add_needle_img, "lv.lv_meter_indicator", "(lv.lv_obj)(lv.lv_meter_scale).ii" } }, - { "add_needle_line", { (const void*) &lv_meter_add_needle_line, "lv.lv_meter_indicator", "(lv.lv_obj)(lv.lv_meter_scale)i(lv.lv_color)i" } }, - { "add_scale", { (const void*) &lv_meter_add_scale, "lv.lv_meter_scale", "(lv.lv_obj)" } }, - { "add_scale_lines", { (const void*) &lv_meter_add_scale_lines, "lv.lv_meter_indicator", "(lv.lv_obj)(lv.lv_meter_scale)(lv.lv_color)(lv.lv_color)bi" } }, - { "set_indicator_end_value", { (const void*) &lv_meter_set_indicator_end_value, "", "(lv.lv_obj)(lv.lv_meter_indicator)i" } }, - { "set_indicator_start_value", { (const void*) &lv_meter_set_indicator_start_value, "", "(lv.lv_obj)(lv.lv_meter_indicator)i" } }, - { "set_indicator_value", { (const void*) &lv_meter_set_indicator_value, "", "(lv.lv_obj)(lv.lv_meter_indicator)i" } }, - { "set_scale_major_ticks", { (const void*) &lv_meter_set_scale_major_ticks, "", "(lv.lv_obj)(lv.lv_meter_scale)iii(lv.lv_color)i" } }, - { "set_scale_range", { (const void*) &lv_meter_set_scale_range, "", "(lv.lv_obj)(lv.lv_meter_scale)iiii" } }, - { "set_scale_ticks", { (const void*) &lv_meter_set_scale_ticks, "", "(lv.lv_obj)(lv.lv_meter_scale)iii(lv.lv_color)" } }, -}; -#endif // BE_LV_WIDGET_METER - -/* `lv_msgbox` methods */ -#ifdef BE_LV_WIDGET_MSGBOX -const be_ntv_func_def_t lv_msgbox_func[] = { - { "close", { (const void*) &lv_msgbox_close, "", "(lv.lv_obj)" } }, - { "close_async", { (const void*) &lv_msgbox_close_async, "", "(lv.lv_obj)" } }, - { "get_active_btn", { (const void*) &lv_msgbox_get_active_btn, "i", "(lv.lv_obj)" } }, - { "get_active_btn_text", { (const void*) &lv_msgbox_get_active_btn_text, "s", "(lv.lv_obj)" } }, - { "get_btns", { (const void*) &lv_msgbox_get_btns, "lv.lv_obj", "(lv.lv_obj)" } }, - { "get_close_btn", { (const void*) &lv_msgbox_get_close_btn, "lv.lv_obj", "(lv.lv_obj)" } }, - { "get_content", { (const void*) &lv_msgbox_get_content, "lv.lv_obj", "(lv.lv_obj)" } }, - { "get_text", { (const void*) &lv_msgbox_get_text, "lv.lv_obj", "(lv.lv_obj)" } }, - { "get_title", { (const void*) &lv_msgbox_get_title, "lv.lv_obj", "(lv.lv_obj)" } }, -}; -#endif // BE_LV_WIDGET_MSGBOX - -/* `lv_spinbox` methods */ -#ifdef BE_LV_WIDGET_SPINBOX -const be_ntv_func_def_t lv_spinbox_func[] = { - { "decrement", { (const void*) &lv_spinbox_decrement, "", "(lv.lv_obj)" } }, - { "get_rollover", { (const void*) &lv_spinbox_get_rollover, "b", "(lv.lv_obj)" } }, - { "get_step", { (const void*) &lv_spinbox_get_step, "i", "(lv.lv_obj)" } }, - { "get_value", { (const void*) &lv_spinbox_get_value, "i", "(lv.lv_obj)" } }, - { "increment", { (const void*) &lv_spinbox_increment, "", "(lv.lv_obj)" } }, - { "set_cursor_pos", { (const void*) &lv_spinbox_set_cursor_pos, "", "(lv.lv_obj)i" } }, - { "set_digit_format", { (const void*) &lv_spinbox_set_digit_format, "", "(lv.lv_obj)ii" } }, - { "set_digit_step_direction", { (const void*) &lv_spinbox_set_digit_step_direction, "", "(lv.lv_obj)i" } }, - { "set_range", { (const void*) &lv_spinbox_set_range, "", "(lv.lv_obj)ii" } }, - { "set_rollover", { (const void*) &lv_spinbox_set_rollover, "", "(lv.lv_obj)b" } }, - { "set_step", { (const void*) &lv_spinbox_set_step, "", "(lv.lv_obj)i" } }, - { "set_value", { (const void*) &lv_spinbox_set_value, "", "(lv.lv_obj)i" } }, - { "step_next", { (const void*) &lv_spinbox_step_next, "", "(lv.lv_obj)" } }, - { "step_prev", { (const void*) &lv_spinbox_step_prev, "", "(lv.lv_obj)" } }, -}; -#endif // BE_LV_WIDGET_SPINBOX - -/* `lv_spinner` methods */ -#ifdef BE_LV_WIDGET_SPINNER -const be_ntv_func_def_t lv_spinner_func[] = { -}; -#endif // BE_LV_WIDGET_SPINNER - -/* `lv_tabview` methods */ -#ifdef BE_LV_WIDGET_TABVIEW -const be_ntv_func_def_t lv_tabview_func[] = { - { "add_tab", { (const void*) &lv_tabview_add_tab, "lv.lv_obj", "(lv.lv_obj)s" } }, - { "get_content", { (const void*) &lv_tabview_get_content, "lv.lv_obj", "(lv.lv_obj)" } }, - { "get_tab_act", { (const void*) &lv_tabview_get_tab_act, "i", "(lv.lv_obj)" } }, - { "get_tab_btns", { (const void*) &lv_tabview_get_tab_btns, "lv.lv_obj", "(lv.lv_obj)" } }, - { "rename_tab", { (const void*) &lv_tabview_rename_tab, "", "(lv.lv_obj)is" } }, - { "set_act", { (const void*) &lv_tabview_set_act, "", "(lv.lv_obj)ii" } }, -}; -#endif // BE_LV_WIDGET_TABVIEW - -/* `lv_tileview` methods */ -#ifdef BE_LV_WIDGET_TILEVIEW -const be_ntv_func_def_t lv_tileview_func[] = { - { "add_tile", { (const void*) &lv_tileview_add_tile, "lv.lv_obj", "(lv.lv_obj)iii" } }, - { "get_tile_act", { (const void*) &lv_tileview_get_tile_act, "lv.lv_obj", "(lv.lv_obj)" } }, -}; -#endif // BE_LV_WIDGET_TILEVIEW - /* `lv_anim` methods */ const be_ntv_func_def_t lv_anim_func[] = { - { "custom_del", { (const void*) &lv_anim_custom_del, "b", "(lv.lv_anim)c" } }, - { "custom_get", { (const void*) &lv_anim_custom_get, "lv.lv_anim", "(lv.lv_anim)c" } }, - { "get_delay", { (const void*) &lv_anim_get_delay, "i", "(lv.lv_anim)" } }, - { "get_playtime", { (const void*) &lv_anim_get_playtime, "i", "(lv.lv_anim)" } }, - { "get_user_data", { (const void*) &lv_anim_get_user_data, ".", "(lv.lv_anim)" } }, - { "init", { (const void*) &lv_anim_init, "", "(lv.lv_anim)" } }, - { "set_custom_exec_cb", { (const void*) &lv_anim_set_custom_exec_cb, "", "(lv.lv_anim)c" } }, - { "set_delay", { (const void*) &lv_anim_set_delay, "", "(lv.lv_anim)i" } }, - { "set_deleted_cb", { (const void*) &lv_anim_set_deleted_cb, "", "(lv.lv_anim)^lv_anim_deleted_cb^" } }, - { "set_early_apply", { (const void*) &lv_anim_set_early_apply, "", "(lv.lv_anim)b" } }, - { "set_exec_cb", { (const void*) &lv_anim_set_exec_cb, "", "(lv.lv_anim)c" } }, - { "set_get_value_cb", { (const void*) &lv_anim_set_get_value_cb, "", "(lv.lv_anim)c" } }, - { "set_path_cb", { (const void*) &lv_anim_set_path_cb, "", "(lv.lv_anim)c" } }, - { "set_playback_delay", { (const void*) &lv_anim_set_playback_delay, "", "(lv.lv_anim)i" } }, - { "set_playback_time", { (const void*) &lv_anim_set_playback_time, "", "(lv.lv_anim)i" } }, - { "set_ready_cb", { (const void*) &lv_anim_set_ready_cb, "", "(lv.lv_anim)c" } }, - { "set_repeat_count", { (const void*) &lv_anim_set_repeat_count, "", "(lv.lv_anim)i" } }, - { "set_repeat_delay", { (const void*) &lv_anim_set_repeat_delay, "", "(lv.lv_anim)i" } }, - { "set_start_cb", { (const void*) &lv_anim_set_start_cb, "", "(lv.lv_anim)c" } }, - { "set_time", { (const void*) &lv_anim_set_time, "", "(lv.lv_anim)i" } }, - { "set_user_data", { (const void*) &lv_anim_set_user_data, "", "(lv.lv_anim)." } }, - { "set_values", { (const void*) &lv_anim_set_values, "", "(lv.lv_anim)ii" } }, - { "set_var", { (const void*) &lv_anim_set_var, "", "(lv.lv_anim)." } }, - { "start", { (const void*) &lv_anim_start, "lv.lv_anim", "(lv.lv_anim)" } }, + { "custom_delete", { (const void*) &lv_anim_custom_delete, "b", "(lv.anim)c" } }, + { "custom_get", { (const void*) &lv_anim_custom_get, "lv.anim", "(lv.anim)c" } }, + { "get_delay", { (const void*) &lv_anim_get_delay, "i", "(lv.anim)" } }, + { "get_playtime", { (const void*) &lv_anim_get_playtime, "i", "(lv.anim)" } }, + { "get_repeat_count", { (const void*) &lv_anim_get_repeat_count, "i", "(lv.anim)" } }, + { "get_time", { (const void*) &lv_anim_get_time, "i", "(lv.anim)" } }, + { "get_user_data", { (const void*) &lv_anim_get_user_data, "c", "(lv.anim)" } }, + { "init", { (const void*) &lv_anim_init, "", "(lv.anim)" } }, + { "set_bezier3_param", { (const void*) &lv_anim_set_bezier3_param, "", "(lv.anim)iiii" } }, + { "set_completed_cb", { (const void*) &lv_anim_set_completed_cb, "", "(lv.anim)c" } }, + { "set_custom_exec_cb", { (const void*) &lv_anim_set_custom_exec_cb, "", "(lv.anim)c" } }, + { "set_delay", { (const void*) &lv_anim_set_delay, "", "(lv.anim)i" } }, + { "set_duration", { (const void*) &lv_anim_set_duration, "", "(lv.anim)i" } }, + { "set_early_apply", { (const void*) &lv_anim_set_early_apply, "", "(lv.anim)b" } }, + { "set_exec_cb", { (const void*) &lv_anim_set_exec_cb, "", "(lv.anim)c" } }, + { "set_get_value_cb", { (const void*) &lv_anim_set_get_value_cb, "", "(lv.anim)c" } }, + { "set_path_cb", { (const void*) &lv_anim_set_path_cb, "", "(lv.anim)c" } }, + { "set_playback_delay", { (const void*) &lv_anim_set_playback_delay, "", "(lv.anim)i" } }, + { "set_playback_duration", { (const void*) &lv_anim_set_playback_duration, "", "(lv.anim)i" } }, + { "set_playback_time", { (const void*) &lv_anim_set_playback_time, "", "(lv.anim)i" } }, + { "set_ready_cb", { (const void*) &lv_anim_set_completed_cb, "", "(lv.anim)c" } }, + { "set_repeat_count", { (const void*) &lv_anim_set_repeat_count, "", "(lv.anim)i" } }, + { "set_repeat_delay", { (const void*) &lv_anim_set_repeat_delay, "", "(lv.anim)i" } }, + { "set_start_cb", { (const void*) &lv_anim_set_start_cb, "", "(lv.anim)c" } }, + { "set_time", { (const void*) &lv_anim_set_time, "", "(lv.anim)i" } }, + { "set_user_data", { (const void*) &lv_anim_set_user_data, "", "(lv.anim)." } }, + { "set_values", { (const void*) &lv_anim_set_values, "", "(lv.anim)ii" } }, + { "set_var", { (const void*) &lv_anim_set_var, "", "(lv.anim)." } }, + { "start", { (const void*) &lv_anim_start, "lv.anim", "(lv.anim)" } }, }; /* `lv_timer` methods */ const be_ntv_func_def_t lv_timer_func[] = { - { "del", { (const void*) &lv_timer_del, "", "(lv.lv_timer)" } }, - { "get_next", { (const void*) &lv_timer_get_next, "lv.lv_timer", "(lv.lv_timer)" } }, - { "pause", { (const void*) &lv_timer_pause, "", "(lv.lv_timer)" } }, - { "ready", { (const void*) &lv_timer_ready, "", "(lv.lv_timer)" } }, - { "reset", { (const void*) &lv_timer_reset, "", "(lv.lv_timer)" } }, - { "resume", { (const void*) &lv_timer_resume, "", "(lv.lv_timer)" } }, - { "set_cb", { (const void*) &lv_timer_set_cb, "", "(lv.lv_timer)^lv_timer_cb^" } }, - { "set_period", { (const void*) &lv_timer_set_period, "", "(lv.lv_timer)i" } }, - { "set_repeat_count", { (const void*) &lv_timer_set_repeat_count, "", "(lv.lv_timer)i" } }, + { "del", { (const void*) &lv_timer_delete, "", "(lv.timer)" } }, + { "delete", { (const void*) &lv_timer_delete, "", "(lv.timer)" } }, + { "get_next", { (const void*) &lv_timer_get_next, "lv.timer", "(lv.timer)" } }, + { "get_paused", { (const void*) &lv_timer_get_paused, "b", "(lv.timer)" } }, + { "get_user_data", { (const void*) &lv_timer_get_user_data, "c", "(lv.timer)" } }, + { "pause", { (const void*) &lv_timer_pause, "", "(lv.timer)" } }, + { "ready", { (const void*) &lv_timer_ready, "", "(lv.timer)" } }, + { "remove", { (const void*) &lv_timer_delete, "", "(lv.timer)" } }, + { "reset", { (const void*) &lv_timer_reset, "", "(lv.timer)" } }, + { "resume", { (const void*) &lv_timer_resume, "", "(lv.timer)" } }, + { "set_auto_delete", { (const void*) &lv_timer_set_auto_delete, "", "(lv.timer)b" } }, + { "set_cb", { (const void*) &lv_timer_set_cb, "", "(lv.timer)^lv_timer_cb^" } }, + { "set_period", { (const void*) &lv_timer_set_period, "", "(lv.timer)i" } }, + { "set_repeat_count", { (const void*) &lv_timer_set_repeat_count, "", "(lv.timer)i" } }, + { "set_user_data", { (const void*) &lv_timer_set_user_data, "", "(lv.timer)." } }, }; +/* `lv_animimg` methods */ +#ifdef BE_LV_WIDGET_ANIMIMG +const be_ntv_func_def_t lv_animimg_func[] = { + { "get_duration", { (const void*) &lv_animimg_get_duration, "i", "(lv.obj)" } }, + { "get_repeat_count", { (const void*) &lv_animimg_get_repeat_count, "i", "(lv.obj)" } }, + { "get_src_count", { (const void*) &lv_animimg_get_src_count, "i", "(lv.obj)" } }, + { "set_duration", { (const void*) &lv_animimg_set_duration, "", "(lv.obj)i" } }, + { "set_repeat_count", { (const void*) &lv_animimg_set_repeat_count, "", "(lv.obj)i" } }, + { "set_src", { (const void*) &lv_animimg_set_src, "", "(lv.obj)ci" } }, + { "start", { (const void*) &lv_animimg_start, "", "(lv.obj)" } }, +}; +#endif // BE_LV_WIDGET_ANIMIMG + /* `lv_arc` methods */ #ifdef BE_LV_WIDGET_ARC const be_ntv_func_def_t lv_arc_func[] = { - { "align_obj_to_angle", { (const void*) &lv_arc_align_obj_to_angle, "", "(lv.lv_obj)(lv.lv_obj)i" } }, - { "get_angle_end", { (const void*) &lv_arc_get_angle_end, "i", "(lv.lv_obj)" } }, - { "get_angle_start", { (const void*) &lv_arc_get_angle_start, "i", "(lv.lv_obj)" } }, - { "get_bg_angle_end", { (const void*) &lv_arc_get_bg_angle_end, "i", "(lv.lv_obj)" } }, - { "get_bg_angle_start", { (const void*) &lv_arc_get_bg_angle_start, "i", "(lv.lv_obj)" } }, - { "get_max_value", { (const void*) &lv_arc_get_max_value, "i", "(lv.lv_obj)" } }, - { "get_min_value", { (const void*) &lv_arc_get_min_value, "i", "(lv.lv_obj)" } }, - { "get_mode", { (const void*) &lv_arc_get_mode, "i", "(lv.lv_obj)" } }, - { "get_value", { (const void*) &lv_arc_get_value, "i", "(lv.lv_obj)" } }, - { "rotate_obj_to_angle", { (const void*) &lv_arc_rotate_obj_to_angle, "", "(lv.lv_obj)(lv.lv_obj)i" } }, - { "set_angles", { (const void*) &lv_arc_set_angles, "", "(lv.lv_obj)ii" } }, - { "set_bg_angles", { (const void*) &lv_arc_set_bg_angles, "", "(lv.lv_obj)ii" } }, - { "set_bg_end_angle", { (const void*) &lv_arc_set_bg_end_angle, "", "(lv.lv_obj)i" } }, - { "set_bg_start_angle", { (const void*) &lv_arc_set_bg_start_angle, "", "(lv.lv_obj)i" } }, - { "set_change_rate", { (const void*) &lv_arc_set_change_rate, "", "(lv.lv_obj)i" } }, - { "set_end_angle", { (const void*) &lv_arc_set_end_angle, "", "(lv.lv_obj)i" } }, - { "set_mode", { (const void*) &lv_arc_set_mode, "", "(lv.lv_obj)i" } }, - { "set_range", { (const void*) &lv_arc_set_range, "", "(lv.lv_obj)ii" } }, - { "set_rotation", { (const void*) &lv_arc_set_rotation, "", "(lv.lv_obj)i" } }, - { "set_start_angle", { (const void*) &lv_arc_set_start_angle, "", "(lv.lv_obj)i" } }, - { "set_value", { (const void*) &lv_arc_set_value, "", "(lv.lv_obj)i" } }, + { "align_obj_to_angle", { (const void*) &lv_arc_align_obj_to_angle, "", "(lv.obj)(lv.obj)i" } }, + { "get_angle", { (const void*) &lv_arc_get_rotation, "i", "(lv.obj)" } }, + { "get_angle_end", { (const void*) &lv_arc_get_angle_end, "i", "(lv.obj)" } }, + { "get_angle_start", { (const void*) &lv_arc_get_angle_start, "i", "(lv.obj)" } }, + { "get_bg_angle_end", { (const void*) &lv_arc_get_bg_angle_end, "i", "(lv.obj)" } }, + { "get_bg_angle_start", { (const void*) &lv_arc_get_bg_angle_start, "i", "(lv.obj)" } }, + { "get_knob_offset", { (const void*) &lv_arc_get_knob_offset, "i", "(lv.obj)" } }, + { "get_max_value", { (const void*) &lv_arc_get_max_value, "i", "(lv.obj)" } }, + { "get_min_value", { (const void*) &lv_arc_get_min_value, "i", "(lv.obj)" } }, + { "get_mode", { (const void*) &lv_arc_get_mode, "i", "(lv.obj)" } }, + { "get_rotation", { (const void*) &lv_arc_get_rotation, "i", "(lv.obj)" } }, + { "get_value", { (const void*) &lv_arc_get_value, "i", "(lv.obj)" } }, + { "rotate_obj_to_angle", { (const void*) &lv_arc_rotate_obj_to_angle, "", "(lv.obj)(lv.obj)i" } }, + { "set_angle", { (const void*) &lv_arc_set_rotation, "", "(lv.obj)i" } }, + { "set_angles", { (const void*) &lv_arc_set_angles, "", "(lv.obj)ii" } }, + { "set_bg_angles", { (const void*) &lv_arc_set_bg_angles, "", "(lv.obj)ii" } }, + { "set_bg_end_angle", { (const void*) &lv_arc_set_bg_end_angle, "", "(lv.obj)i" } }, + { "set_bg_start_angle", { (const void*) &lv_arc_set_bg_start_angle, "", "(lv.obj)i" } }, + { "set_change_rate", { (const void*) &lv_arc_set_change_rate, "", "(lv.obj)i" } }, + { "set_end_angle", { (const void*) &lv_arc_set_end_angle, "", "(lv.obj)i" } }, + { "set_knob_offset", { (const void*) &lv_arc_set_knob_offset, "", "(lv.obj)i" } }, + { "set_mode", { (const void*) &lv_arc_set_mode, "", "(lv.obj)i" } }, + { "set_range", { (const void*) &lv_arc_set_range, "", "(lv.obj)ii" } }, + { "set_rotation", { (const void*) &lv_arc_set_rotation, "", "(lv.obj)i" } }, + { "set_start_angle", { (const void*) &lv_arc_set_start_angle, "", "(lv.obj)i" } }, + { "set_value", { (const void*) &lv_arc_set_value, "", "(lv.obj)i" } }, }; #endif // BE_LV_WIDGET_ARC /* `lv_bar` methods */ #ifdef BE_LV_WIDGET_BAR const be_ntv_func_def_t lv_bar_func[] = { - { "get_max_value", { (const void*) &lv_bar_get_max_value, "i", "(lv.lv_obj)" } }, - { "get_min_value", { (const void*) &lv_bar_get_min_value, "i", "(lv.lv_obj)" } }, - { "get_mode", { (const void*) &lv_bar_get_mode, "i", "(lv.lv_obj)" } }, - { "get_start_value", { (const void*) &lv_bar_get_start_value, "i", "(lv.lv_obj)" } }, - { "get_value", { (const void*) &lv_bar_get_value, "i", "(lv.lv_obj)" } }, - { "set_mode", { (const void*) &lv_bar_set_mode, "", "(lv.lv_obj)i" } }, - { "set_range", { (const void*) &lv_bar_set_range, "", "(lv.lv_obj)ii" } }, - { "set_start_value", { (const void*) &lv_bar_set_start_value, "", "(lv.lv_obj)ii" } }, - { "set_value", { (const void*) &lv_bar_set_value, "", "(lv.lv_obj)ii" } }, + { "get_max_value", { (const void*) &lv_bar_get_max_value, "i", "(lv.obj)" } }, + { "get_min_value", { (const void*) &lv_bar_get_min_value, "i", "(lv.obj)" } }, + { "get_mode", { (const void*) &lv_bar_get_mode, "i", "(lv.obj)" } }, + { "get_start_value", { (const void*) &lv_bar_get_start_value, "i", "(lv.obj)" } }, + { "get_value", { (const void*) &lv_bar_get_value, "i", "(lv.obj)" } }, + { "is_symmetrical", { (const void*) &lv_bar_is_symmetrical, "b", "(lv.obj)" } }, + { "set_mode", { (const void*) &lv_bar_set_mode, "", "(lv.obj)i" } }, + { "set_range", { (const void*) &lv_bar_set_range, "", "(lv.obj)ii" } }, + { "set_start_value", { (const void*) &lv_bar_set_start_value, "", "(lv.obj)ii" } }, + { "set_value", { (const void*) &lv_bar_set_value, "", "(lv.obj)ii" } }, }; #endif // BE_LV_WIDGET_BAR -/* `lv_btn` methods */ -#ifdef BE_LV_WIDGET_BTN -const be_ntv_func_def_t lv_btn_func[] = { +/* `lv_button` methods */ +#ifdef BE_LV_WIDGET_BUTTON +const be_ntv_func_def_t lv_button_func[] = { }; -#endif // BE_LV_WIDGET_BTN +#endif // BE_LV_WIDGET_BUTTON + +/* `lv_buttonmatrix` methods */ +#ifdef BE_LV_WIDGET_BUTTONMATRIX +const be_ntv_func_def_t lv_buttonmatrix_func[] = { + { "_btn_text", { (const void*) &lv_buttonmatrix_get_button_text, "s", "(lv.obj)i" } }, + { "clear_button_ctrl", { (const void*) &lv_buttonmatrix_clear_button_ctrl, "", "(lv.obj)ii" } }, + { "clear_button_ctrl_all", { (const void*) &lv_buttonmatrix_clear_button_ctrl_all, "", "(lv.obj)i" } }, + { "get_button_text", { (const void*) &lv_buttonmatrix_get_button_text, "s", "(lv.obj)i" } }, + { "get_map", { (const void*) &lv_buttonmatrix_get_map, "c", "(lv.obj)" } }, + { "get_one_checked", { (const void*) &lv_buttonmatrix_get_one_checked, "b", "(lv.obj)" } }, + { "get_popovers", { (const void*) &lv_buttonmatrix_get_popovers, "b", "(lv.obj)" } }, + { "get_selected_button", { (const void*) &lv_buttonmatrix_get_selected_button, "i", "(lv.obj)" } }, + { "has_button_ctrl", { (const void*) &lv_buttonmatrix_has_button_ctrl, "b", "(lv.obj)ii" } }, + { "set_button_ctrl", { (const void*) &lv_buttonmatrix_set_button_ctrl, "", "(lv.obj)ii" } }, + { "set_button_ctrl_all", { (const void*) &lv_buttonmatrix_set_button_ctrl_all, "", "(lv.obj)i" } }, + { "set_button_width", { (const void*) &lv_buttonmatrix_set_button_width, "", "(lv.obj)ii" } }, + { "set_map", { (const void*) &lv_buttonmatrix_set_map, "", "(lv.obj)(lv.str_arr)" } }, + { "set_one_checked", { (const void*) &lv_buttonmatrix_set_one_checked, "", "(lv.obj)b" } }, + { "set_selected_button", { (const void*) &lv_buttonmatrix_set_selected_button, "", "(lv.obj)i" } }, +}; +#endif // BE_LV_WIDGET_BUTTONMATRIX + +/* `lv_calendar` methods */ +#ifdef BE_LV_WIDGET_CALENDAR +const be_ntv_func_def_t lv_calendar_func[] = { + { "get_btnmatrix", { (const void*) &lv_calendar_get_btnmatrix, "lv.obj", "(lv.obj)" } }, + { "get_highlighted_dates_num", { (const void*) &lv_calendar_get_highlighted_dates_num, "i", "(lv.obj)" } }, + { "header_dropdown_set_year_list", { (const void*) &lv_calendar_header_dropdown_set_year_list, "", "(lv.obj)s" } }, + { "set_day_names", { (const void*) &lv_calendar_set_day_names, "", "(lv.obj)c" } }, + { "set_showed_date", { (const void*) &lv_calendar_set_showed_date, "", "(lv.obj)ii" } }, + { "set_today_date", { (const void*) &lv_calendar_set_today_date, "", "(lv.obj)iii" } }, +}; +#endif // BE_LV_WIDGET_CALENDAR /* `lv_canvas` methods */ #ifdef BE_LV_WIDGET_CANVAS const be_ntv_func_def_t lv_canvas_func[] = { - { "blur_hor", { (const void*) &lv_canvas_blur_hor, "", "(lv.lv_obj)(lv.lv_area)i" } }, - { "blur_ver", { (const void*) &lv_canvas_blur_ver, "", "(lv.lv_obj)(lv.lv_area)i" } }, - { "copy_buf", { (const void*) &lv_canvas_copy_buf, "", "(lv.lv_obj).iiii" } }, - { "draw_arc", { (const void*) &lv_canvas_draw_arc, "", "(lv.lv_obj)iiiii(lv.lv_draw_arc_dsc)" } }, - { "draw_img", { (const void*) &lv_canvas_draw_img, "", "(lv.lv_obj)ii.(lv.lv_draw_img_dsc)" } }, - { "draw_line", { (const void*) &lv_canvas_draw_line, "", "(lv.lv_obj)(lv.lv_point_arr)i(lv.lv_draw_line_dsc)" } }, - { "draw_polygon", { (const void*) &lv_canvas_draw_polygon, "", "(lv.lv_obj)(lv.lv_point_arr)i(lv.lv_draw_rect_dsc)" } }, - { "draw_rect", { (const void*) &lv_canvas_draw_rect, "", "(lv.lv_obj)iiii(lv.lv_draw_rect_dsc)" } }, - { "draw_text", { (const void*) &lv_canvas_draw_text, "", "(lv.lv_obj)iii(lv.lv_draw_label_dsc)s" } }, - { "fill_bg", { (const void*) &lv_canvas_fill_bg, "", "(lv.lv_obj)(lv.lv_color)i" } }, - { "get_img", { (const void*) &lv_canvas_get_img, "lv.lv_img_dsc", "(lv.lv_obj)" } }, - { "get_px", { (const void*) &lv_canvas_get_px, "lv.lv_color", "(lv.lv_obj)ii" } }, - { "set_buffer", { (const void*) &lv_canvas_set_buffer, "", "(lv.lv_obj).iii" } }, - { "set_palette", { (const void*) &lv_canvas_set_palette, "", "(lv.lv_obj)i(lv.lv_color)" } }, - { "set_px", { (const void*) &lv_canvas_set_px, "", "(lv.lv_obj)ii(lv.lv_color)" } }, - { "set_px_color", { (const void*) &lv_canvas_set_px_color, "", "(lv.lv_obj)ii(lv.lv_color)" } }, - { "set_px_opa", { (const void*) &lv_canvas_set_px_opa, "", "(lv.lv_obj)iii" } }, - { "transform", { (const void*) &lv_canvas_transform, "", "(lv.lv_obj)(lv.lv_img_dsc)iiiiiib" } }, + { "fill_bg", { (const void*) &lv_canvas_fill_bg, "", "(lv.obj)(lv.color)i" } }, + { "finish_layer", { (const void*) &lv_canvas_finish_layer, "", "(lv.obj)c" } }, + { "get_buf", { (const void*) &lv_canvas_get_buf, "c", "(lv.obj)" } }, + { "get_image", { (const void*) &lv_canvas_get_image, "lv.image_dsc", "(lv.obj)" } }, + { "get_px", { (const void*) &lv_canvas_get_px, "i", "(lv.obj)ii" } }, + { "init_layer", { (const void*) &lv_canvas_init_layer, "", "(lv.obj)c" } }, + { "set_buffer", { (const void*) &lv_canvas_set_buffer, "", "(lv.obj).iii" } }, + { "set_palette", { (const void*) &lv_canvas_set_palette, "", "(lv.obj)ii" } }, + { "set_px", { (const void*) &lv_canvas_set_px, "", "(lv.obj)ii(lv.color)i" } }, }; #endif // BE_LV_WIDGET_CANVAS +/* `lv_chart` methods */ +#ifdef BE_LV_WIDGET_CHART +const be_ntv_func_def_t lv_chart_func[] = { + { "add_cursor", { (const void*) &lv_chart_add_cursor, "lv.chart_cursor", "(lv.obj)(lv.color)i" } }, + { "add_series", { (const void*) &lv_chart_add_series, "lv.chart_series", "(lv.obj)(lv.color)i" } }, + { "get_cursor_point", { (const void*) &lv_chart_get_cursor_point, "i", "(lv.obj)(lv.chart_cursor)" } }, + { "get_first_point_center_offset", { (const void*) &lv_chart_get_first_point_center_offset, "i", "(lv.obj)" } }, + { "get_point_count", { (const void*) &lv_chart_get_point_count, "i", "(lv.obj)" } }, + { "get_point_pos_by_id", { (const void*) &lv_chart_get_point_pos_by_id, "", "(lv.obj)(lv.chart_series)ic" } }, + { "get_pressed_point", { (const void*) &lv_chart_get_pressed_point, "i", "(lv.obj)" } }, + { "get_series_next", { (const void*) &lv_chart_get_series_next, "lv.chart_series", "(lv.obj)(lv.chart_series)" } }, + { "get_type", { (const void*) &lv_chart_get_type, "i", "(lv.obj)" } }, + { "get_x_array", { (const void*) &lv_chart_get_x_array, "lv.int_arr", "(lv.obj)(lv.chart_series)" } }, + { "get_x_start_point", { (const void*) &lv_chart_get_x_start_point, "i", "(lv.obj)(lv.chart_series)" } }, + { "get_y_array", { (const void*) &lv_chart_get_y_array, "lv.int_arr", "(lv.obj)(lv.chart_series)" } }, + { "hide_series", { (const void*) &lv_chart_hide_series, "", "(lv.obj)(lv.chart_series)b" } }, + { "refresh", { (const void*) &lv_chart_refresh, "", "(lv.obj)" } }, + { "remove_series", { (const void*) &lv_chart_remove_series, "", "(lv.obj)(lv.chart_series)" } }, + { "set_all_value", { (const void*) &lv_chart_set_all_value, "", "(lv.obj)(lv.chart_series)i" } }, + { "set_cursor_point", { (const void*) &lv_chart_set_cursor_point, "", "(lv.obj)(lv.chart_cursor)(lv.chart_series)i" } }, + { "set_cursor_pos", { (const void*) &lv_chart_set_cursor_pos, "", "(lv.obj)(lv.chart_cursor)c" } }, + { "set_div_line_count", { (const void*) &lv_chart_set_div_line_count, "", "(lv.obj)ii" } }, + { "set_ext_x_array", { (const void*) &lv_chart_set_ext_x_array, "", "(lv.obj)(lv.chart_series)(lv.int_arr)" } }, + { "set_ext_y_array", { (const void*) &lv_chart_set_ext_y_array, "", "(lv.obj)(lv.chart_series)(lv.int_arr)" } }, + { "set_next_value", { (const void*) &lv_chart_set_next_value, "", "(lv.obj)(lv.chart_series)i" } }, + { "set_next_value2", { (const void*) &lv_chart_set_next_value2, "", "(lv.obj)(lv.chart_series)ii" } }, + { "set_point_count", { (const void*) &lv_chart_set_point_count, "", "(lv.obj)i" } }, + { "set_range", { (const void*) &lv_chart_set_range, "", "(lv.obj)iii" } }, + { "set_series_color", { (const void*) &lv_chart_set_series_color, "", "(lv.obj)(lv.chart_series)(lv.color)" } }, + { "set_type", { (const void*) &lv_chart_set_type, "", "(lv.obj)i" } }, + { "set_update_mode", { (const void*) &lv_chart_set_update_mode, "", "(lv.obj)i" } }, + { "set_value_by_id", { (const void*) &lv_chart_set_value_by_id, "", "(lv.obj)(lv.chart_series)ii" } }, + { "set_value_by_id2", { (const void*) &lv_chart_set_value_by_id2, "", "(lv.obj)(lv.chart_series)iii" } }, + { "set_x_start_point", { (const void*) &lv_chart_set_x_start_point, "", "(lv.obj)(lv.chart_series)i" } }, +}; +#endif // BE_LV_WIDGET_CHART + /* `lv_checkbox` methods */ #ifdef BE_LV_WIDGET_CHECKBOX const be_ntv_func_def_t lv_checkbox_func[] = { - { "get_text", { (const void*) &lv_checkbox_get_text, "s", "(lv.lv_obj)" } }, - { "set_text", { (const void*) &lv_checkbox_set_text, "", "(lv.lv_obj)s" } }, - { "set_text_static", { (const void*) &lv_checkbox_set_text_static, "", "(lv.lv_obj)s" } }, + { "get_text", { (const void*) &lv_checkbox_get_text, "s", "(lv.obj)" } }, + { "set_text", { (const void*) &lv_checkbox_set_text, "", "(lv.obj)s" } }, + { "set_text_static", { (const void*) &lv_checkbox_set_text_static, "", "(lv.obj)s" } }, }; #endif // BE_LV_WIDGET_CHECKBOX /* `lv_dropdown` methods */ #ifdef BE_LV_WIDGET_DROPDOWN const be_ntv_func_def_t lv_dropdown_func[] = { - { "add_option", { (const void*) &lv_dropdown_add_option, "", "(lv.lv_obj)si" } }, - { "clear_options", { (const void*) &lv_dropdown_clear_options, "", "(lv.lv_obj)" } }, - { "close", { (const void*) &lv_dropdown_close, "", "(lv.lv_obj)" } }, - { "get_dir", { (const void*) &lv_dropdown_get_dir, "i", "(lv.lv_obj)" } }, - { "get_list", { (const void*) &lv_dropdown_get_list, "lv.lv_obj", "(lv.lv_obj)" } }, - { "get_option_cnt", { (const void*) &lv_dropdown_get_option_cnt, "i", "(lv.lv_obj)" } }, - { "get_option_index", { (const void*) &lv_dropdown_get_option_index, "i", "(lv.lv_obj)s" } }, - { "get_options", { (const void*) &lv_dropdown_get_options, "s", "(lv.lv_obj)" } }, - { "get_selected", { (const void*) &lv_dropdown_get_selected, "i", "(lv.lv_obj)" } }, - { "get_selected_highlight", { (const void*) &lv_dropdown_get_selected_highlight, "b", "(lv.lv_obj)" } }, - { "get_selected_str", { (const void*) &lv_dropdown_get_selected_str, "", "(lv.lv_obj)ci" } }, - { "get_symbol", { (const void*) &lv_dropdown_get_symbol, "s", "(lv.lv_obj)" } }, - { "get_text", { (const void*) &lv_dropdown_get_text, "s", "(lv.lv_obj)" } }, - { "is_open", { (const void*) &lv_dropdown_is_open, "b", "(lv.lv_obj)" } }, - { "open", { (const void*) &lv_dropdown_open, "", "(lv.lv_obj)" } }, - { "set_dir", { (const void*) &lv_dropdown_set_dir, "", "(lv.lv_obj)i" } }, - { "set_options", { (const void*) &lv_dropdown_set_options, "", "(lv.lv_obj)s" } }, - { "set_options_static", { (const void*) &lv_dropdown_set_options_static, "", "(lv.lv_obj)s" } }, - { "set_selected", { (const void*) &lv_dropdown_set_selected, "", "(lv.lv_obj)i" } }, - { "set_selected_highlight", { (const void*) &lv_dropdown_set_selected_highlight, "", "(lv.lv_obj)b" } }, - { "set_symbol", { (const void*) &lv_dropdown_set_symbol, "", "(lv.lv_obj)." } }, - { "set_text", { (const void*) &lv_dropdown_set_text, "", "(lv.lv_obj)s" } }, + { "add_option", { (const void*) &lv_dropdown_add_option, "", "(lv.obj)si" } }, + { "clear_options", { (const void*) &lv_dropdown_clear_options, "", "(lv.obj)" } }, + { "close", { (const void*) &lv_dropdown_close, "", "(lv.obj)" } }, + { "get_dir", { (const void*) &lv_dropdown_get_dir, "i", "(lv.obj)" } }, + { "get_list", { (const void*) &lv_dropdown_get_list, "lv.obj", "(lv.obj)" } }, + { "get_option_cnt", { (const void*) &lv_dropdown_get_option_count, "i", "(lv.obj)" } }, + { "get_option_count", { (const void*) &lv_dropdown_get_option_count, "i", "(lv.obj)" } }, + { "get_option_index", { (const void*) &lv_dropdown_get_option_index, "i", "(lv.obj)s" } }, + { "get_options", { (const void*) &lv_dropdown_get_options, "s", "(lv.obj)" } }, + { "get_selected", { (const void*) &lv_dropdown_get_selected, "i", "(lv.obj)" } }, + { "get_selected_highlight", { (const void*) &lv_dropdown_get_selected_highlight, "b", "(lv.obj)" } }, + { "get_selected_str", { (const void*) &lv_dropdown_get_selected_str, "", "(lv.obj)ci" } }, + { "get_symbol", { (const void*) &lv_dropdown_get_symbol, "s", "(lv.obj)" } }, + { "get_text", { (const void*) &lv_dropdown_get_text, "s", "(lv.obj)" } }, + { "is_open", { (const void*) &lv_dropdown_is_open, "b", "(lv.obj)" } }, + { "open", { (const void*) &lv_dropdown_open, "", "(lv.obj)" } }, + { "set_dir", { (const void*) &lv_dropdown_set_dir, "", "(lv.obj)i" } }, + { "set_options", { (const void*) &lv_dropdown_set_options, "", "(lv.obj)s" } }, + { "set_options_static", { (const void*) &lv_dropdown_set_options_static, "", "(lv.obj)s" } }, + { "set_selected", { (const void*) &lv_dropdown_set_selected, "", "(lv.obj)i" } }, + { "set_selected_highlight", { (const void*) &lv_dropdown_set_selected_highlight, "", "(lv.obj)b" } }, + { "set_symbol", { (const void*) &lv_dropdown_set_symbol, "", "(lv.obj)." } }, + { "set_text", { (const void*) &lv_dropdown_set_text, "", "(lv.obj)s" } }, }; #endif // BE_LV_WIDGET_DROPDOWN +/* `lv_imagebutton` methods */ +#ifdef BE_LV_WIDGET_IMAGEBUTTON +const be_ntv_func_def_t lv_imagebutton_func[] = { + { "set_src", { (const void*) &lv_imagebutton_set_src, "", "(lv.obj)i..." } }, + { "set_state", { (const void*) &lv_imagebutton_set_state, "", "(lv.obj)i" } }, +}; +#endif // BE_LV_WIDGET_IMAGEBUTTON + +/* `lv_keyboard` methods */ +#ifdef BE_LV_WIDGET_KEYBOARD +const be_ntv_func_def_t lv_keyboard_func[] = { + { "_btn_text", { (const void*) &lv_keyboard_get_button_text, "s", "(lv.obj)i" } }, + { "get_button_text", { (const void*) &lv_keyboard_get_button_text, "s", "(lv.obj)i" } }, + { "get_map_array", { (const void*) &lv_keyboard_get_map_array, "c", "(lv.obj)" } }, + { "get_mode", { (const void*) &lv_keyboard_get_mode, "i", "(lv.obj)" } }, + { "get_selected_button", { (const void*) &lv_keyboard_get_selected_button, "i", "(lv.obj)" } }, + { "get_textarea", { (const void*) &lv_keyboard_get_textarea, "lv.obj", "(lv.obj)" } }, + { "set_mode", { (const void*) &lv_keyboard_set_mode, "", "(lv.obj)i" } }, + { "set_popovers", { (const void*) &lv_keyboard_set_popovers, "", "(lv.obj)b" } }, + { "set_textarea", { (const void*) &lv_keyboard_set_textarea, "", "(lv.obj)(lv.obj)" } }, +}; +#endif // BE_LV_WIDGET_KEYBOARD + /* `lv_label` methods */ #ifdef BE_LV_WIDGET_LABEL const be_ntv_func_def_t lv_label_func[] = { - { "cut_text", { (const void*) &lv_label_cut_text, "", "(lv.lv_obj)ii" } }, - { "get_letter_on", { (const void*) &lv_label_get_letter_on, "i", "(lv.lv_obj)(lv.lv_point)" } }, - { "get_letter_pos", { (const void*) &lv_label_get_letter_pos, "", "(lv.lv_obj)i(lv.lv_point)" } }, - { "get_long_mode", { (const void*) &lv_label_get_long_mode, "i", "(lv.lv_obj)" } }, - { "get_recolor", { (const void*) &lv_label_get_recolor, "b", "(lv.lv_obj)" } }, - { "get_text", { (const void*) &lv_label_get_text, "s", "(lv.lv_obj)" } }, - { "get_text_selection_end", { (const void*) &lv_label_get_text_selection_end, "i", "(lv.lv_obj)" } }, - { "get_text_selection_start", { (const void*) &lv_label_get_text_selection_start, "i", "(lv.lv_obj)" } }, - { "ins_text", { (const void*) &lv_label_ins_text, "", "(lv.lv_obj)is" } }, - { "is_char_under_pos", { (const void*) &lv_label_is_char_under_pos, "b", "(lv.lv_obj)(lv.lv_point)" } }, - { "set_long_mode", { (const void*) &lv_label_set_long_mode, "", "(lv.lv_obj)i" } }, - { "set_recolor", { (const void*) &lv_label_set_recolor, "", "(lv.lv_obj)b" } }, - { "set_text", { (const void*) &lv_label_set_text, "", "(lv.lv_obj)s" } }, - { "set_text_fmt", { (const void*) &lv_label_set_text_fmt, "", "(lv.lv_obj)s[......]" } }, - { "set_text_sel_end", { (const void*) &lv_label_set_text_sel_end, "", "(lv.lv_obj)i" } }, - { "set_text_sel_start", { (const void*) &lv_label_set_text_sel_start, "", "(lv.lv_obj)i" } }, - { "set_text_static", { (const void*) &lv_label_set_text_static, "", "(lv.lv_obj)s" } }, + { "cut_text", { (const void*) &lv_label_cut_text, "", "(lv.obj)ii" } }, + { "get_letter_on", { (const void*) &lv_label_get_letter_on, "i", "(lv.obj)cb" } }, + { "get_letter_pos", { (const void*) &lv_label_get_letter_pos, "", "(lv.obj)ic" } }, + { "get_long_mode", { (const void*) &lv_label_get_long_mode, "i", "(lv.obj)" } }, + { "get_text", { (const void*) &lv_label_get_text, "s", "(lv.obj)" } }, + { "get_text_selection_end", { (const void*) &lv_label_get_text_selection_end, "i", "(lv.obj)" } }, + { "get_text_selection_start", { (const void*) &lv_label_get_text_selection_start, "i", "(lv.obj)" } }, + { "ins_text", { (const void*) &lv_label_ins_text, "", "(lv.obj)is" } }, + { "is_char_under_pos", { (const void*) &lv_label_is_char_under_pos, "b", "(lv.obj)c" } }, + { "set_long_mode", { (const void*) &lv_label_set_long_mode, "", "(lv.obj)i" } }, + { "set_text", { (const void*) &lv_label_set_text, "", "(lv.obj)s" } }, + { "set_text_fmt", { (const void*) &lv_label_set_text_fmt, "", "(lv.obj)s[......]" } }, + { "set_text_selection_end", { (const void*) &lv_label_set_text_selection_end, "", "(lv.obj)i" } }, + { "set_text_selection_start", { (const void*) &lv_label_set_text_selection_start, "", "(lv.obj)i" } }, + { "set_text_static", { (const void*) &lv_label_set_text_static, "", "(lv.obj)s" } }, }; #endif // BE_LV_WIDGET_LABEL +/* `lv_led` methods */ +#ifdef BE_LV_WIDGET_LED +const be_ntv_func_def_t lv_led_func[] = { + { "get_brightness", { (const void*) &lv_led_get_brightness, "i", "(lv.obj)" } }, + { "off", { (const void*) &lv_led_off, "", "(lv.obj)" } }, + { "on", { (const void*) &lv_led_on, "", "(lv.obj)" } }, + { "set_brightness", { (const void*) &lv_led_set_brightness, "", "(lv.obj)i" } }, + { "set_color", { (const void*) &lv_led_set_color, "", "(lv.obj)(lv.color)" } }, + { "toggle", { (const void*) &lv_led_toggle, "", "(lv.obj)" } }, +}; +#endif // BE_LV_WIDGET_LED + /* `lv_line` methods */ #ifdef BE_LV_WIDGET_LINE const be_ntv_func_def_t lv_line_func[] = { - { "get_y_invert", { (const void*) &lv_line_get_y_invert, "b", "(lv.lv_obj)" } }, - { "set_points", { (const void*) &lv_line_set_points, "", "(lv.lv_obj)(lv.lv_point_arr)i" } }, - { "set_y_invert", { (const void*) &lv_line_set_y_invert, "", "(lv.lv_obj)b" } }, + { "get_y_invert", { (const void*) &lv_line_get_y_invert, "b", "(lv.obj)" } }, + { "set_points", { (const void*) &lv_line_set_points, "", "(lv.obj)(lv.point_arr)i" } }, + { "set_y_invert", { (const void*) &lv_line_set_y_invert, "", "(lv.obj)b" } }, }; #endif // BE_LV_WIDGET_LINE +/* `lv_list` methods */ +#ifdef BE_LV_WIDGET_LIST +const be_ntv_func_def_t lv_list_func[] = { + { "_btn_text", { (const void*) &lv_list_get_button_text, "s", "(lv.obj)(lv.obj)" } }, + { "add_btn", { (const void*) &lv_list_add_button, "lv.obj", "(lv.obj).s" } }, + { "add_button", { (const void*) &lv_list_add_button, "lv.obj", "(lv.obj).s" } }, + { "add_text", { (const void*) &lv_list_add_text, "lv.obj", "(lv.obj)s" } }, + { "get_button_text", { (const void*) &lv_list_get_button_text, "s", "(lv.obj)(lv.obj)" } }, + { "set_btn_text", { (const void*) &lv_list_set_button_text, "", "(lv.obj)(lv.obj)s" } }, + { "set_button_text", { (const void*) &lv_list_set_button_text, "", "(lv.obj)(lv.obj)s" } }, +}; +#endif // BE_LV_WIDGET_LIST + +/* `lv_menu` methods */ +#ifdef BE_LV_WIDGET_MENU +const be_ntv_func_def_t lv_menu_func[] = { + { "back_button_is_root", { (const void*) &lv_menu_back_button_is_root, "b", "(lv.obj)(lv.obj)" } }, + { "clear_history", { (const void*) &lv_menu_clear_history, "", "(lv.obj)" } }, + { "get_cur_main_page", { (const void*) &lv_menu_get_cur_main_page, "lv.obj", "(lv.obj)" } }, + { "get_cur_sidebar_page", { (const void*) &lv_menu_get_cur_sidebar_page, "lv.obj", "(lv.obj)" } }, + { "get_main_header", { (const void*) &lv_menu_get_main_header, "lv.obj", "(lv.obj)" } }, + { "get_main_header_back_button", { (const void*) &lv_menu_get_main_header_back_button, "lv.obj", "(lv.obj)" } }, + { "get_sidebar_header", { (const void*) &lv_menu_get_sidebar_header, "lv.obj", "(lv.obj)" } }, + { "get_sidebar_header_back_button", { (const void*) &lv_menu_get_sidebar_header_back_button, "lv.obj", "(lv.obj)" } }, + { "set_load_page_event", { (const void*) &lv_menu_set_load_page_event, "", "(lv.obj)(lv.obj)(lv.obj)" } }, + { "set_mode_header", { (const void*) &lv_menu_set_mode_header, "", "(lv.obj)i" } }, + { "set_mode_root_back_button", { (const void*) &lv_menu_set_mode_root_back_button, "", "(lv.obj)i" } }, + { "set_page", { (const void*) &lv_menu_set_page, "", "(lv.obj)(lv.obj)" } }, + { "set_page_title", { (const void*) &lv_menu_set_page_title, "", "(lv.obj)c" } }, + { "set_page_title_static", { (const void*) &lv_menu_set_page_title_static, "", "(lv.obj)c" } }, + { "set_sidebar_page", { (const void*) &lv_menu_set_sidebar_page, "", "(lv.obj)(lv.obj)" } }, +}; +#endif // BE_LV_WIDGET_MENU + +/* `lv_msgbox` methods */ +#ifdef BE_LV_WIDGET_MSGBOX +const be_ntv_func_def_t lv_msgbox_func[] = { + { "add_close_button", { (const void*) &lv_msgbox_add_close_button, "lv.obj", "(lv.obj)" } }, + { "add_footer_button", { (const void*) &lv_msgbox_add_footer_button, "lv.obj", "(lv.obj)s" } }, + { "add_header_button", { (const void*) &lv_msgbox_add_header_button, "lv.obj", "(lv.obj)." } }, + { "add_text", { (const void*) &lv_msgbox_add_text, "lv.obj", "(lv.obj)s" } }, + { "add_title", { (const void*) &lv_msgbox_add_title, "lv.obj", "(lv.obj)s" } }, + { "close", { (const void*) &lv_msgbox_close, "", "(lv.obj)" } }, + { "close_async", { (const void*) &lv_msgbox_close_async, "", "(lv.obj)" } }, + { "get_content", { (const void*) &lv_msgbox_get_content, "lv.obj", "(lv.obj)" } }, + { "get_footer", { (const void*) &lv_msgbox_get_footer, "lv.obj", "(lv.obj)" } }, + { "get_header", { (const void*) &lv_msgbox_get_header, "lv.obj", "(lv.obj)" } }, + { "get_title", { (const void*) &lv_msgbox_get_title, "lv.obj", "(lv.obj)" } }, +}; +#endif // BE_LV_WIDGET_MSGBOX + /* `lv_roller` methods */ #ifdef BE_LV_WIDGET_ROLLER const be_ntv_func_def_t lv_roller_func[] = { - { "get_option_cnt", { (const void*) &lv_roller_get_option_cnt, "i", "(lv.lv_obj)" } }, - { "get_options", { (const void*) &lv_roller_get_options, "s", "(lv.lv_obj)" } }, - { "get_selected", { (const void*) &lv_roller_get_selected, "i", "(lv.lv_obj)" } }, - { "get_selected_str", { (const void*) &lv_roller_get_selected_str, "", "(lv.lv_obj)ci" } }, - { "set_options", { (const void*) &lv_roller_set_options, "", "(lv.lv_obj)si" } }, - { "set_selected", { (const void*) &lv_roller_set_selected, "", "(lv.lv_obj)ii" } }, - { "set_visible_row_count", { (const void*) &lv_roller_set_visible_row_count, "", "(lv.lv_obj)i" } }, + { "get_option_cnt", { (const void*) &lv_roller_get_option_count, "i", "(lv.obj)" } }, + { "get_option_count", { (const void*) &lv_roller_get_option_count, "i", "(lv.obj)" } }, + { "get_options", { (const void*) &lv_roller_get_options, "s", "(lv.obj)" } }, + { "get_selected", { (const void*) &lv_roller_get_selected, "i", "(lv.obj)" } }, + { "get_selected_str", { (const void*) &lv_roller_get_selected_str, "", "(lv.obj)ci" } }, + { "set_options", { (const void*) &lv_roller_set_options, "", "(lv.obj)si" } }, + { "set_selected", { (const void*) &lv_roller_set_selected, "", "(lv.obj)ii" } }, + { "set_visible_row_cnt", { (const void*) &lv_roller_set_visible_row_count, "", "(lv.obj)i" } }, + { "set_visible_row_count", { (const void*) &lv_roller_set_visible_row_count, "", "(lv.obj)i" } }, }; #endif // BE_LV_WIDGET_ROLLER +/* `lv_scale` methods */ +#ifdef BE_LV_WIDGET_SCALE +const be_ntv_func_def_t lv_scale_func[] = { + { "add_section", { (const void*) &lv_scale_add_section, "c", "(lv.obj)" } }, + { "get_angle_range", { (const void*) &lv_scale_get_angle_range, "i", "(lv.obj)" } }, + { "get_label_show", { (const void*) &lv_scale_get_label_show, "b", "(lv.obj)" } }, + { "get_major_tick_every", { (const void*) &lv_scale_get_major_tick_every, "i", "(lv.obj)" } }, + { "get_mode", { (const void*) &lv_scale_get_mode, "i", "(lv.obj)" } }, + { "get_range_max_value", { (const void*) &lv_scale_get_range_max_value, "i", "(lv.obj)" } }, + { "get_range_min_value", { (const void*) &lv_scale_get_range_min_value, "i", "(lv.obj)" } }, + { "get_total_tick_count", { (const void*) &lv_scale_get_total_tick_count, "i", "(lv.obj)" } }, + { "set_angle", { (const void*) &lv_scale_set_rotation, "", "(lv.obj)i" } }, + { "set_angle_range", { (const void*) &lv_scale_set_angle_range, "", "(lv.obj)i" } }, + { "set_image_needle_value", { (const void*) &lv_scale_set_image_needle_value, "", "(lv.obj)(lv.obj)i" } }, + { "set_label_show", { (const void*) &lv_scale_set_label_show, "", "(lv.obj)b" } }, + { "set_line_needle_value", { (const void*) &lv_scale_set_line_needle_value, "", "(lv.obj)(lv.obj)ii" } }, + { "set_major_tick_every", { (const void*) &lv_scale_set_major_tick_every, "", "(lv.obj)i" } }, + { "set_mode", { (const void*) &lv_scale_set_mode, "", "(lv.obj)i" } }, + { "set_post_draw", { (const void*) &lv_scale_set_post_draw, "", "(lv.obj)b" } }, + { "set_range", { (const void*) &lv_scale_set_range, "", "(lv.obj)ii" } }, + { "set_rotation", { (const void*) &lv_scale_set_rotation, "", "(lv.obj)i" } }, + { "set_text_src", { (const void*) &lv_scale_set_text_src, "", "(lv.obj)(lv.str_arr)" } }, + { "set_total_tick_count", { (const void*) &lv_scale_set_total_tick_count, "", "(lv.obj)i" } }, +}; +#endif // BE_LV_WIDGET_SCALE + /* `lv_slider` methods */ #ifdef BE_LV_WIDGET_SLIDER const be_ntv_func_def_t lv_slider_func[] = { - { "get_left_value", { (const void*) &lv_slider_get_left_value, "i", "(lv.lv_obj)" } }, - { "get_max_value", { (const void*) &lv_slider_get_max_value, "i", "(lv.lv_obj)" } }, - { "get_min_value", { (const void*) &lv_slider_get_min_value, "i", "(lv.lv_obj)" } }, - { "get_mode", { (const void*) &lv_slider_get_mode, "i", "(lv.lv_obj)" } }, - { "get_value", { (const void*) &lv_slider_get_value, "i", "(lv.lv_obj)" } }, - { "is_dragged", { (const void*) &lv_slider_is_dragged, "b", "(lv.lv_obj)" } }, - { "set_left_value", { (const void*) &lv_slider_set_left_value, "", "(lv.lv_obj)ii" } }, - { "set_mode", { (const void*) &lv_slider_set_mode, "", "(lv.lv_obj)i" } }, - { "set_range", { (const void*) &lv_slider_set_range, "", "(lv.lv_obj)ii" } }, - { "set_value", { (const void*) &lv_slider_set_value, "", "(lv.lv_obj)ii" } }, + { "get_left_value", { (const void*) &lv_slider_get_left_value, "i", "(lv.obj)" } }, + { "get_max_value", { (const void*) &lv_slider_get_max_value, "i", "(lv.obj)" } }, + { "get_min_value", { (const void*) &lv_slider_get_min_value, "i", "(lv.obj)" } }, + { "get_mode", { (const void*) &lv_slider_get_mode, "i", "(lv.obj)" } }, + { "get_value", { (const void*) &lv_slider_get_value, "i", "(lv.obj)" } }, + { "is_dragged", { (const void*) &lv_slider_is_dragged, "b", "(lv.obj)" } }, + { "is_symmetrical", { (const void*) &lv_slider_is_symmetrical, "b", "(lv.obj)" } }, + { "set_left_value", { (const void*) &lv_slider_set_left_value, "", "(lv.obj)ii" } }, + { "set_mode", { (const void*) &lv_slider_set_mode, "", "(lv.obj)i" } }, + { "set_range", { (const void*) &lv_slider_set_range, "", "(lv.obj)ii" } }, + { "set_value", { (const void*) &lv_slider_set_value, "", "(lv.obj)ii" } }, }; #endif // BE_LV_WIDGET_SLIDER +/* `lv_spangroup` methods */ +#ifdef BE_LV_WIDGET_SPANGROUP +const be_ntv_func_def_t lv_spangroup_func[] = { + { "delete_span", { (const void*) &lv_spangroup_delete_span, "", "(lv.obj)(lv.spangroup)" } }, + { "get_align", { (const void*) &lv_spangroup_get_align, "i", "(lv.obj)" } }, + { "get_child", { (const void*) &lv_spangroup_get_child, "lv.spangroup", "(lv.obj)i" } }, + { "get_expand_height", { (const void*) &lv_spangroup_get_expand_height, "i", "(lv.obj)i" } }, + { "get_expand_width", { (const void*) &lv_spangroup_get_expand_width, "i", "(lv.obj)i" } }, + { "get_indent", { (const void*) &lv_spangroup_get_indent, "i", "(lv.obj)" } }, + { "get_max_line_height", { (const void*) &lv_spangroup_get_max_line_height, "i", "(lv.obj)" } }, + { "get_max_lines", { (const void*) &lv_spangroup_get_max_lines, "i", "(lv.obj)" } }, + { "get_mode", { (const void*) &lv_spangroup_get_mode, "i", "(lv.obj)" } }, + { "get_overflow", { (const void*) &lv_spangroup_get_overflow, "i", "(lv.obj)" } }, + { "get_span_count", { (const void*) &lv_spangroup_get_span_count, "i", "(lv.obj)" } }, + { "new_span", { (const void*) &lv_spangroup_new_span, "lv.spangroup", "(lv.obj)" } }, + { "refr_mode", { (const void*) &lv_spangroup_refr_mode, "", "(lv.obj)" } }, + { "set_align", { (const void*) &lv_spangroup_set_align, "", "(lv.obj)i" } }, + { "set_indent", { (const void*) &lv_spangroup_set_indent, "", "(lv.obj)i" } }, + { "set_max_lines", { (const void*) &lv_spangroup_set_max_lines, "", "(lv.obj)i" } }, + { "set_mode", { (const void*) &lv_spangroup_set_mode, "", "(lv.obj)i" } }, + { "set_overflow", { (const void*) &lv_spangroup_set_overflow, "", "(lv.obj)i" } }, +}; +#endif // BE_LV_WIDGET_SPANGROUP + +/* `lv_spinbox` methods */ +#ifdef BE_LV_WIDGET_SPINBOX +const be_ntv_func_def_t lv_spinbox_func[] = { + { "decrement", { (const void*) &lv_spinbox_decrement, "", "(lv.obj)" } }, + { "get_rollover", { (const void*) &lv_spinbox_get_rollover, "b", "(lv.obj)" } }, + { "get_step", { (const void*) &lv_spinbox_get_step, "i", "(lv.obj)" } }, + { "get_value", { (const void*) &lv_spinbox_get_value, "i", "(lv.obj)" } }, + { "increment", { (const void*) &lv_spinbox_increment, "", "(lv.obj)" } }, + { "set_cursor_pos", { (const void*) &lv_spinbox_set_cursor_pos, "", "(lv.obj)i" } }, + { "set_digit_format", { (const void*) &lv_spinbox_set_digit_format, "", "(lv.obj)ii" } }, + { "set_digit_step_direction", { (const void*) &lv_spinbox_set_digit_step_direction, "", "(lv.obj)i" } }, + { "set_range", { (const void*) &lv_spinbox_set_range, "", "(lv.obj)ii" } }, + { "set_rollover", { (const void*) &lv_spinbox_set_rollover, "", "(lv.obj)b" } }, + { "set_step", { (const void*) &lv_spinbox_set_step, "", "(lv.obj)i" } }, + { "set_value", { (const void*) &lv_spinbox_set_value, "", "(lv.obj)i" } }, + { "step_next", { (const void*) &lv_spinbox_step_next, "", "(lv.obj)" } }, + { "step_prev", { (const void*) &lv_spinbox_step_prev, "", "(lv.obj)" } }, +}; +#endif // BE_LV_WIDGET_SPINBOX + +/* `lv_spinner` methods */ +#ifdef BE_LV_WIDGET_SPINNER +const be_ntv_func_def_t lv_spinner_func[] = { + { "set_anim_params", { (const void*) &lv_spinner_set_anim_params, "", "(lv.obj)ii" } }, +}; +#endif // BE_LV_WIDGET_SPINNER + /* `lv_switch` methods */ #ifdef BE_LV_WIDGET_SWITCH const be_ntv_func_def_t lv_switch_func[] = { @@ -1013,93 +1242,134 @@ const be_ntv_func_def_t lv_switch_func[] = { /* `lv_table` methods */ #ifdef BE_LV_WIDGET_TABLE const be_ntv_func_def_t lv_table_func[] = { - { "add_cell_ctrl", { (const void*) &lv_table_add_cell_ctrl, "", "(lv.lv_obj)iii" } }, - { "clear_cell_ctrl", { (const void*) &lv_table_clear_cell_ctrl, "", "(lv.lv_obj)iii" } }, - { "get_cell_user_data", { (const void*) &lv_table_get_cell_user_data, ".", "(lv.lv_obj)ii" } }, - { "get_cell_value", { (const void*) &lv_table_get_cell_value, "s", "(lv.lv_obj)ii" } }, - { "get_col_cnt", { (const void*) &lv_table_get_col_cnt, "i", "(lv.lv_obj)" } }, - { "get_col_width", { (const void*) &lv_table_get_col_width, "i", "(lv.lv_obj)i" } }, - { "get_row_cnt", { (const void*) &lv_table_get_row_cnt, "i", "(lv.lv_obj)" } }, - { "get_selected_cell", { (const void*) &lv_table_get_selected_cell, "", "(lv.lv_obj)(lv.uint16)(lv.uint16)" } }, - { "has_cell_ctrl", { (const void*) &lv_table_has_cell_ctrl, "b", "(lv.lv_obj)iii" } }, - { "set_cell_user_data", { (const void*) &lv_table_set_cell_user_data, "", "(lv.lv_obj)ii." } }, - { "set_cell_value", { (const void*) &lv_table_set_cell_value, "", "(lv.lv_obj)iis" } }, - { "set_cell_value_fmt", { (const void*) &lv_table_set_cell_value_fmt, "", "(lv.lv_obj)iis[......]" } }, - { "set_col_cnt", { (const void*) &lv_table_set_col_cnt, "", "(lv.lv_obj)i" } }, - { "set_col_width", { (const void*) &lv_table_set_col_width, "", "(lv.lv_obj)ii" } }, - { "set_row_cnt", { (const void*) &lv_table_set_row_cnt, "", "(lv.lv_obj)i" } }, + { "add_cell_ctrl", { (const void*) &lv_table_add_cell_ctrl, "", "(lv.obj)iii" } }, + { "clear_cell_ctrl", { (const void*) &lv_table_clear_cell_ctrl, "", "(lv.obj)iii" } }, + { "get_cell_user_data", { (const void*) &lv_table_get_cell_user_data, "c", "(lv.obj)ii" } }, + { "get_cell_value", { (const void*) &lv_table_get_cell_value, "s", "(lv.obj)ii" } }, + { "get_col_cnt", { (const void*) &lv_table_get_column_count, "i", "(lv.obj)" } }, + { "get_col_width", { (const void*) &lv_table_get_column_width, "i", "(lv.obj)i" } }, + { "get_column_count", { (const void*) &lv_table_get_column_count, "i", "(lv.obj)" } }, + { "get_column_width", { (const void*) &lv_table_get_column_width, "i", "(lv.obj)i" } }, + { "get_row_cnt", { (const void*) &lv_table_get_row_count, "i", "(lv.obj)" } }, + { "get_row_count", { (const void*) &lv_table_get_row_count, "i", "(lv.obj)" } }, + { "get_selected_cell", { (const void*) &lv_table_get_selected_cell, "", "(lv.obj)(lv.int_arr)(lv.int_arr)" } }, + { "has_cell_ctrl", { (const void*) &lv_table_has_cell_ctrl, "b", "(lv.obj)iii" } }, + { "set_cell_user_data", { (const void*) &lv_table_set_cell_user_data, "", "(lv.obj)ii." } }, + { "set_cell_value", { (const void*) &lv_table_set_cell_value, "", "(lv.obj)iis" } }, + { "set_cell_value_fmt", { (const void*) &lv_table_set_cell_value_fmt, "", "(lv.obj)iis[......]" } }, + { "set_col_cnt", { (const void*) &lv_table_set_column_count, "", "(lv.obj)i" } }, + { "set_col_width", { (const void*) &lv_table_set_column_width, "", "(lv.obj)ii" } }, + { "set_column_count", { (const void*) &lv_table_set_column_count, "", "(lv.obj)i" } }, + { "set_column_width", { (const void*) &lv_table_set_column_width, "", "(lv.obj)ii" } }, + { "set_row_cnt", { (const void*) &lv_table_set_row_count, "", "(lv.obj)i" } }, + { "set_row_count", { (const void*) &lv_table_set_row_count, "", "(lv.obj)i" } }, }; #endif // BE_LV_WIDGET_TABLE +/* `lv_tabview` methods */ +#ifdef BE_LV_WIDGET_TABVIEW +const be_ntv_func_def_t lv_tabview_func[] = { + { "add_tab", { (const void*) &lv_tabview_add_tab, "lv.obj", "(lv.obj)s" } }, + { "get_content", { (const void*) &lv_tabview_get_content, "lv.obj", "(lv.obj)" } }, + { "get_tab_act", { (const void*) &lv_tabview_get_tab_active, "i", "(lv.obj)" } }, + { "get_tab_active", { (const void*) &lv_tabview_get_tab_active, "i", "(lv.obj)" } }, + { "get_tab_bar", { (const void*) &lv_tabview_get_tab_bar, "lv.obj", "(lv.obj)" } }, + { "get_tab_btns", { (const void*) &lv_tabview_get_tab_bar, "lv.obj", "(lv.obj)" } }, + { "get_tab_count", { (const void*) &lv_tabview_get_tab_count, "i", "(lv.obj)" } }, + { "rename_tab", { (const void*) &lv_tabview_rename_tab, "", "(lv.obj)is" } }, + { "set_act", { (const void*) &lv_tabview_set_active, "", "(lv.obj)ii" } }, + { "set_active", { (const void*) &lv_tabview_set_active, "", "(lv.obj)ii" } }, + { "set_tab_bar_position", { (const void*) &lv_tabview_set_tab_bar_position, "", "(lv.obj)i" } }, + { "set_tab_bar_size", { (const void*) &lv_tabview_set_tab_bar_size, "", "(lv.obj)i" } }, +}; +#endif // BE_LV_WIDGET_TABVIEW + /* `lv_textarea` methods */ #ifdef BE_LV_WIDGET_TEXTAREA const be_ntv_func_def_t lv_textarea_func[] = { - { "add_char", { (const void*) &lv_textarea_add_char, "", "(lv.lv_obj)i" } }, - { "add_text", { (const void*) &lv_textarea_add_text, "", "(lv.lv_obj)s" } }, - { "clear_selection", { (const void*) &lv_textarea_clear_selection, "", "(lv.lv_obj)" } }, - { "cursor_down", { (const void*) &lv_textarea_cursor_down, "", "(lv.lv_obj)" } }, - { "cursor_left", { (const void*) &lv_textarea_cursor_left, "", "(lv.lv_obj)" } }, - { "cursor_right", { (const void*) &lv_textarea_cursor_right, "", "(lv.lv_obj)" } }, - { "cursor_up", { (const void*) &lv_textarea_cursor_up, "", "(lv.lv_obj)" } }, - { "del_char", { (const void*) &lv_textarea_del_char, "", "(lv.lv_obj)" } }, - { "del_char_forward", { (const void*) &lv_textarea_del_char_forward, "", "(lv.lv_obj)" } }, - { "get_accepted_chars", { (const void*) &lv_textarea_get_accepted_chars, "s", "(lv.lv_obj)" } }, - { "get_cursor_click_pos", { (const void*) &lv_textarea_get_cursor_click_pos, "b", "(lv.lv_obj)" } }, - { "get_cursor_pos", { (const void*) &lv_textarea_get_cursor_pos, "i", "(lv.lv_obj)" } }, - { "get_label", { (const void*) &lv_textarea_get_label, "lv.lv_obj", "(lv.lv_obj)" } }, - { "get_max_length", { (const void*) &lv_textarea_get_max_length, "i", "(lv.lv_obj)" } }, - { "get_one_line", { (const void*) &lv_textarea_get_one_line, "b", "(lv.lv_obj)" } }, - { "get_password_bullet", { (const void*) &lv_textarea_get_password_bullet, "s", "(lv.lv_obj)" } }, - { "get_password_mode", { (const void*) &lv_textarea_get_password_mode, "b", "(lv.lv_obj)" } }, - { "get_password_show_time", { (const void*) &lv_textarea_get_password_show_time, "i", "(lv.lv_obj)" } }, - { "get_placeholder_text", { (const void*) &lv_textarea_get_placeholder_text, "s", "(lv.lv_obj)" } }, - { "get_text", { (const void*) &lv_textarea_get_text, "s", "(lv.lv_obj)" } }, - { "get_text_selection", { (const void*) &lv_textarea_get_text_selection, "b", "(lv.lv_obj)" } }, - { "set_accepted_chars", { (const void*) &lv_textarea_set_accepted_chars, "", "(lv.lv_obj)s" } }, - { "set_align", { (const void*) &lv_textarea_set_align, "", "(lv.lv_obj)i" } }, - { "set_cursor_click_pos", { (const void*) &lv_textarea_set_cursor_click_pos, "", "(lv.lv_obj)b" } }, - { "set_cursor_pos", { (const void*) &lv_textarea_set_cursor_pos, "", "(lv.lv_obj)i" } }, - { "set_insert_replace", { (const void*) &lv_textarea_set_insert_replace, "", "(lv.lv_obj)s" } }, - { "set_max_length", { (const void*) &lv_textarea_set_max_length, "", "(lv.lv_obj)i" } }, - { "set_one_line", { (const void*) &lv_textarea_set_one_line, "", "(lv.lv_obj)b" } }, - { "set_password_bullet", { (const void*) &lv_textarea_set_password_bullet, "", "(lv.lv_obj)s" } }, - { "set_password_mode", { (const void*) &lv_textarea_set_password_mode, "", "(lv.lv_obj)b" } }, - { "set_password_show_time", { (const void*) &lv_textarea_set_password_show_time, "", "(lv.lv_obj)i" } }, - { "set_placeholder_text", { (const void*) &lv_textarea_set_placeholder_text, "", "(lv.lv_obj)s" } }, - { "set_text", { (const void*) &lv_textarea_set_text, "", "(lv.lv_obj)s" } }, - { "set_text_selection", { (const void*) &lv_textarea_set_text_selection, "", "(lv.lv_obj)b" } }, - { "text_is_selected", { (const void*) &lv_textarea_text_is_selected, "b", "(lv.lv_obj)" } }, + { "add_char", { (const void*) &lv_textarea_add_char, "", "(lv.obj)i" } }, + { "add_text", { (const void*) &lv_textarea_add_text, "", "(lv.obj)s" } }, + { "clear_selection", { (const void*) &lv_textarea_clear_selection, "", "(lv.obj)" } }, + { "cursor_down", { (const void*) &lv_textarea_cursor_down, "", "(lv.obj)" } }, + { "cursor_left", { (const void*) &lv_textarea_cursor_left, "", "(lv.obj)" } }, + { "cursor_right", { (const void*) &lv_textarea_cursor_right, "", "(lv.obj)" } }, + { "cursor_up", { (const void*) &lv_textarea_cursor_up, "", "(lv.obj)" } }, + { "delete_char", { (const void*) &lv_textarea_delete_char, "", "(lv.obj)" } }, + { "delete_char_forward", { (const void*) &lv_textarea_delete_char_forward, "", "(lv.obj)" } }, + { "get_accepted_chars", { (const void*) &lv_textarea_get_accepted_chars, "s", "(lv.obj)" } }, + { "get_current_char", { (const void*) &lv_textarea_get_current_char, "i", "(lv.obj)" } }, + { "get_cursor_click_pos", { (const void*) &lv_textarea_get_cursor_click_pos, "b", "(lv.obj)" } }, + { "get_cursor_pos", { (const void*) &lv_textarea_get_cursor_pos, "i", "(lv.obj)" } }, + { "get_label", { (const void*) &lv_textarea_get_label, "lv.obj", "(lv.obj)" } }, + { "get_max_length", { (const void*) &lv_textarea_get_max_length, "i", "(lv.obj)" } }, + { "get_one_line", { (const void*) &lv_textarea_get_one_line, "b", "(lv.obj)" } }, + { "get_password_bullet", { (const void*) &lv_textarea_get_password_bullet, "s", "(lv.obj)" } }, + { "get_password_mode", { (const void*) &lv_textarea_get_password_mode, "b", "(lv.obj)" } }, + { "get_password_show_time", { (const void*) &lv_textarea_get_password_show_time, "i", "(lv.obj)" } }, + { "get_placeholder_text", { (const void*) &lv_textarea_get_placeholder_text, "s", "(lv.obj)" } }, + { "get_text", { (const void*) &lv_textarea_get_text, "s", "(lv.obj)" } }, + { "get_text_selection", { (const void*) &lv_textarea_get_text_selection, "b", "(lv.obj)" } }, + { "set_accepted_chars", { (const void*) &lv_textarea_set_accepted_chars, "", "(lv.obj)s" } }, + { "set_align", { (const void*) &lv_textarea_set_align, "", "(lv.obj)i" } }, + { "set_cursor_click_pos", { (const void*) &lv_textarea_set_cursor_click_pos, "", "(lv.obj)b" } }, + { "set_cursor_pos", { (const void*) &lv_textarea_set_cursor_pos, "", "(lv.obj)i" } }, + { "set_insert_replace", { (const void*) &lv_textarea_set_insert_replace, "", "(lv.obj)s" } }, + { "set_max_length", { (const void*) &lv_textarea_set_max_length, "", "(lv.obj)i" } }, + { "set_one_line", { (const void*) &lv_textarea_set_one_line, "", "(lv.obj)b" } }, + { "set_password_bullet", { (const void*) &lv_textarea_set_password_bullet, "", "(lv.obj)s" } }, + { "set_password_mode", { (const void*) &lv_textarea_set_password_mode, "", "(lv.obj)b" } }, + { "set_password_show_time", { (const void*) &lv_textarea_set_password_show_time, "", "(lv.obj)i" } }, + { "set_placeholder_text", { (const void*) &lv_textarea_set_placeholder_text, "", "(lv.obj)s" } }, + { "set_text", { (const void*) &lv_textarea_set_text, "", "(lv.obj)s" } }, + { "set_text_selection", { (const void*) &lv_textarea_set_text_selection, "", "(lv.obj)b" } }, + { "text_is_selected", { (const void*) &lv_textarea_text_is_selected, "b", "(lv.obj)" } }, }; #endif // BE_LV_WIDGET_TEXTAREA +/* `lv_tileview` methods */ +#ifdef BE_LV_WIDGET_TILEVIEW +const be_ntv_func_def_t lv_tileview_func[] = { + { "add_tile", { (const void*) &lv_tileview_add_tile, "lv.obj", "(lv.obj)iii" } }, + { "get_tile_act", { (const void*) &lv_tileview_get_tile_active, "lv.obj", "(lv.obj)" } }, + { "get_tile_active", { (const void*) &lv_tileview_get_tile_active, "lv.obj", "(lv.obj)" } }, + { "set_tile", { (const void*) &lv_tileview_set_tile, "", "(lv.obj)(lv.obj)i" } }, + { "set_tile_by_index", { (const void*) &lv_tileview_set_tile_by_index, "", "(lv.obj)iii" } }, + { "set_tile_id", { (const void*) &lv_tileview_set_tile_by_index, "", "(lv.obj)iii" } }, +}; +#endif // BE_LV_WIDGET_TILEVIEW + extern const bclass be_class_lv_anim; +extern const bclass be_class_lv_animimg; extern const bclass be_class_lv_arc; extern const bclass be_class_lv_bar; -extern const bclass be_class_lv_btn; -extern const bclass be_class_lv_btnmatrix; +extern const bclass be_class_lv_button; +extern const bclass be_class_lv_buttonmatrix; +extern const bclass be_class_lv_calendar; extern const bclass be_class_lv_canvas; extern const bclass be_class_lv_chart; extern const bclass be_class_lv_checkbox; extern const bclass be_class_lv_color; -extern const bclass be_class_lv_colorwheel; -extern const bclass be_class_lv_disp; +extern const bclass be_class_lv_display; extern const bclass be_class_lv_dropdown; +extern const bclass be_class_lv_event; extern const bclass be_class_lv_font; extern const bclass be_class_lv_group; -extern const bclass be_class_lv_img; -extern const bclass be_class_lv_imgbtn; +extern const bclass be_class_lv_image; +extern const bclass be_class_lv_imagebutton; extern const bclass be_class_lv_indev; extern const bclass be_class_lv_keyboard; extern const bclass be_class_lv_label; extern const bclass be_class_lv_led; extern const bclass be_class_lv_line; extern const bclass be_class_lv_list; -extern const bclass be_class_lv_meter; +extern const bclass be_class_lv_menu; extern const bclass be_class_lv_msgbox; extern const bclass be_class_lv_obj; extern const bclass be_class_lv_qrcode; extern const bclass be_class_lv_roller; +extern const bclass be_class_lv_scale; extern const bclass be_class_lv_slider; +extern const bclass be_class_lv_spangroup; extern const bclass be_class_lv_spinbox; extern const bclass be_class_lv_spinner; extern const bclass be_class_lv_style; @@ -1115,18 +1385,24 @@ extern const bclass be_class_lv_timer; // map of clases const be_ntv_class_def_t lv_classes[] = { { "lv_anim", &be_class_lv_anim, lv_anim_func, sizeof(lv_anim_func) / sizeof(lv_anim_func[0]) }, +#ifdef BE_LV_WIDGET_ANIMIMG + { "lv_animimg", &be_class_lv_animimg, lv_animimg_func, sizeof(lv_animimg_func) / sizeof(lv_animimg_func[0]) }, +#endif // BE_LV_WIDGET_ANIMIMG #ifdef BE_LV_WIDGET_ARC { "lv_arc", &be_class_lv_arc, lv_arc_func, sizeof(lv_arc_func) / sizeof(lv_arc_func[0]) }, #endif // BE_LV_WIDGET_ARC #ifdef BE_LV_WIDGET_BAR { "lv_bar", &be_class_lv_bar, lv_bar_func, sizeof(lv_bar_func) / sizeof(lv_bar_func[0]) }, #endif // BE_LV_WIDGET_BAR -#ifdef BE_LV_WIDGET_BTN - { "lv_btn", &be_class_lv_btn, lv_btn_func, sizeof(lv_btn_func) / sizeof(lv_btn_func[0]) }, -#endif // BE_LV_WIDGET_BTN -#ifdef BE_LV_WIDGET_BTNMATRIX - { "lv_btnmatrix", &be_class_lv_btnmatrix, lv_btnmatrix_func, sizeof(lv_btnmatrix_func) / sizeof(lv_btnmatrix_func[0]) }, -#endif // BE_LV_WIDGET_BTNMATRIX +#ifdef BE_LV_WIDGET_BUTTON + { "lv_button", &be_class_lv_button, lv_button_func, sizeof(lv_button_func) / sizeof(lv_button_func[0]) }, +#endif // BE_LV_WIDGET_BUTTON +#ifdef BE_LV_WIDGET_BUTTONMATRIX + { "lv_buttonmatrix", &be_class_lv_buttonmatrix, lv_buttonmatrix_func, sizeof(lv_buttonmatrix_func) / sizeof(lv_buttonmatrix_func[0]) }, +#endif // BE_LV_WIDGET_BUTTONMATRIX +#ifdef BE_LV_WIDGET_CALENDAR + { "lv_calendar", &be_class_lv_calendar, lv_calendar_func, sizeof(lv_calendar_func) / sizeof(lv_calendar_func[0]) }, +#endif // BE_LV_WIDGET_CALENDAR #ifdef BE_LV_WIDGET_CANVAS { "lv_canvas", &be_class_lv_canvas, lv_canvas_func, sizeof(lv_canvas_func) / sizeof(lv_canvas_func[0]) }, #endif // BE_LV_WIDGET_CANVAS @@ -1137,21 +1413,19 @@ const be_ntv_class_def_t lv_classes[] = { { "lv_checkbox", &be_class_lv_checkbox, lv_checkbox_func, sizeof(lv_checkbox_func) / sizeof(lv_checkbox_func[0]) }, #endif // BE_LV_WIDGET_CHECKBOX { "lv_color", &be_class_lv_color, lv_color_func, sizeof(lv_color_func) / sizeof(lv_color_func[0]) }, -#ifdef BE_LV_WIDGET_COLORWHEEL - { "lv_colorwheel", &be_class_lv_colorwheel, lv_colorwheel_func, sizeof(lv_colorwheel_func) / sizeof(lv_colorwheel_func[0]) }, -#endif // BE_LV_WIDGET_COLORWHEEL - { "lv_disp", &be_class_lv_disp, lv_disp_func, sizeof(lv_disp_func) / sizeof(lv_disp_func[0]) }, + { "lv_display", &be_class_lv_display, lv_display_func, sizeof(lv_display_func) / sizeof(lv_display_func[0]) }, #ifdef BE_LV_WIDGET_DROPDOWN { "lv_dropdown", &be_class_lv_dropdown, lv_dropdown_func, sizeof(lv_dropdown_func) / sizeof(lv_dropdown_func[0]) }, #endif // BE_LV_WIDGET_DROPDOWN + { "lv_event", &be_class_lv_event, lv_event_func, sizeof(lv_event_func) / sizeof(lv_event_func[0]) }, { "lv_font", &be_class_lv_font, lv_font_func, sizeof(lv_font_func) / sizeof(lv_font_func[0]) }, { "lv_group", &be_class_lv_group, lv_group_func, sizeof(lv_group_func) / sizeof(lv_group_func[0]) }, -#ifdef BE_LV_WIDGET_IMG - { "lv_img", &be_class_lv_img, lv_img_func, sizeof(lv_img_func) / sizeof(lv_img_func[0]) }, -#endif // BE_LV_WIDGET_IMG -#ifdef BE_LV_WIDGET_IMGBTN - { "lv_imgbtn", &be_class_lv_imgbtn, lv_imgbtn_func, sizeof(lv_imgbtn_func) / sizeof(lv_imgbtn_func[0]) }, -#endif // BE_LV_WIDGET_IMGBTN +#ifdef BE_LV_WIDGET_IMAGE + { "lv_image", &be_class_lv_image, lv_image_func, sizeof(lv_image_func) / sizeof(lv_image_func[0]) }, +#endif // BE_LV_WIDGET_IMAGE +#ifdef BE_LV_WIDGET_IMAGEBUTTON + { "lv_imagebutton", &be_class_lv_imagebutton, lv_imagebutton_func, sizeof(lv_imagebutton_func) / sizeof(lv_imagebutton_func[0]) }, +#endif // BE_LV_WIDGET_IMAGEBUTTON { "lv_indev", &be_class_lv_indev, lv_indev_func, sizeof(lv_indev_func) / sizeof(lv_indev_func[0]) }, #ifdef BE_LV_WIDGET_KEYBOARD { "lv_keyboard", &be_class_lv_keyboard, lv_keyboard_func, sizeof(lv_keyboard_func) / sizeof(lv_keyboard_func[0]) }, @@ -1168,22 +1442,30 @@ const be_ntv_class_def_t lv_classes[] = { #ifdef BE_LV_WIDGET_LIST { "lv_list", &be_class_lv_list, lv_list_func, sizeof(lv_list_func) / sizeof(lv_list_func[0]) }, #endif // BE_LV_WIDGET_LIST -#ifdef BE_LV_WIDGET_METER - { "lv_meter", &be_class_lv_meter, lv_meter_func, sizeof(lv_meter_func) / sizeof(lv_meter_func[0]) }, -#endif // BE_LV_WIDGET_METER +#ifdef BE_LV_WIDGET_MENU + { "lv_menu", &be_class_lv_menu, lv_menu_func, sizeof(lv_menu_func) / sizeof(lv_menu_func[0]) }, +#endif // BE_LV_WIDGET_MENU #ifdef BE_LV_WIDGET_MSGBOX { "lv_msgbox", &be_class_lv_msgbox, lv_msgbox_func, sizeof(lv_msgbox_func) / sizeof(lv_msgbox_func[0]) }, #endif // BE_LV_WIDGET_MSGBOX +#ifdef BE_LV_WIDGET_OBJ { "lv_obj", &be_class_lv_obj, lv_obj_func, sizeof(lv_obj_func) / sizeof(lv_obj_func[0]) }, +#endif // BE_LV_WIDGET_OBJ #ifdef BE_LV_WIDGET_QRCODE { "lv_qrcode", &be_class_lv_qrcode, lv_qrcode_func, sizeof(lv_qrcode_func) / sizeof(lv_qrcode_func[0]) }, #endif // BE_LV_WIDGET_QRCODE #ifdef BE_LV_WIDGET_ROLLER { "lv_roller", &be_class_lv_roller, lv_roller_func, sizeof(lv_roller_func) / sizeof(lv_roller_func[0]) }, #endif // BE_LV_WIDGET_ROLLER +#ifdef BE_LV_WIDGET_SCALE + { "lv_scale", &be_class_lv_scale, lv_scale_func, sizeof(lv_scale_func) / sizeof(lv_scale_func[0]) }, +#endif // BE_LV_WIDGET_SCALE #ifdef BE_LV_WIDGET_SLIDER { "lv_slider", &be_class_lv_slider, lv_slider_func, sizeof(lv_slider_func) / sizeof(lv_slider_func[0]) }, #endif // BE_LV_WIDGET_SLIDER +#ifdef BE_LV_WIDGET_SPANGROUP + { "lv_spangroup", &be_class_lv_spangroup, lv_spangroup_func, sizeof(lv_spangroup_func) / sizeof(lv_spangroup_func[0]) }, +#endif // BE_LV_WIDGET_SPANGROUP #ifdef BE_LV_WIDGET_SPINBOX { "lv_spinbox", &be_class_lv_spinbox, lv_spinbox_func, sizeof(lv_spinbox_func) / sizeof(lv_spinbox_func[0]) }, #endif // BE_LV_WIDGET_SPINBOX @@ -1215,126 +1497,159 @@ const size_t lv_classes_size = sizeof(lv_classes) / sizeof(lv_classes[0]); /* `lv_font` methods */ /* `lv_color` methods */ /* `lv_theme` methods */ - /* `lv_img` methods */ -#ifdef BE_LV_WIDGET_IMG - int be_ntv_lv_img_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_img_create, "+_p", "(lv.lv_obj)"); } -#endif // BE_LV_WIDGET_IMG - /* `lv_disp` methods */ - /* `lv_obj` methods */ - int be_ntv_lv_obj_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_obj_create, "+_p", "(lv.lv_obj)"); } + /* `lv_image` methods */ +#ifdef BE_LV_WIDGET_IMAGE + int be_ntv_lv_image_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_image_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_IMAGE /* `lv_group` methods */ int be_ntv_lv_group_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_group_create, "+_p", ""); } + /* `lv_obj` methods */ +#ifdef BE_LV_WIDGET_OBJ + int be_ntv_lv_obj_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_obj_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_OBJ + /* `lv_event` methods */ + /* `lv_display` methods */ /* `lv_indev` methods */ /* `lv_qrcode` methods */ #ifdef BE_LV_WIDGET_QRCODE - int be_ntv_lv_qrcode_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_qrcode_create, "+_p", "(lv.lv_obj)i(lv.lv_color)(lv.lv_color)"); } + int be_ntv_lv_qrcode_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_qrcode_create, "+_p", "(lv.obj)"); } #endif // BE_LV_WIDGET_QRCODE - /* `lv_chart` methods */ -#ifdef BE_LV_WIDGET_CHART - int be_ntv_lv_chart_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_chart_create, "+_p", "(lv.lv_obj)"); } -#endif // BE_LV_WIDGET_CHART - /* `lv_colorwheel` methods */ -#ifdef BE_LV_WIDGET_COLORWHEEL - int be_ntv_lv_colorwheel_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_colorwheel_create, "+_p", "(lv.lv_obj)b"); } -#endif // BE_LV_WIDGET_COLORWHEEL - /* `lv_imgbtn` methods */ -#ifdef BE_LV_WIDGET_IMGBTN - int be_ntv_lv_imgbtn_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_imgbtn_create, "+_p", "(lv.lv_obj)"); } -#endif // BE_LV_WIDGET_IMGBTN - /* `lv_keyboard` methods */ -#ifdef BE_LV_WIDGET_KEYBOARD - int be_ntv_lv_keyboard_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_keyboard_create, "+_p", "(lv.lv_obj)"); } -#endif // BE_LV_WIDGET_KEYBOARD - /* `lv_btnmatrix` methods */ -#ifdef BE_LV_WIDGET_BTNMATRIX - int be_ntv_lv_btnmatrix_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_btnmatrix_create, "+_p", "(lv.lv_obj)"); } -#endif // BE_LV_WIDGET_BTNMATRIX - /* `lv_led` methods */ -#ifdef BE_LV_WIDGET_LED - int be_ntv_lv_led_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_led_create, "+_p", "(lv.lv_obj)"); } -#endif // BE_LV_WIDGET_LED - /* `lv_list` methods */ -#ifdef BE_LV_WIDGET_LIST - int be_ntv_lv_list_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_list_create, "+_p", "(lv.lv_obj)"); } -#endif // BE_LV_WIDGET_LIST - /* `lv_meter` methods */ -#ifdef BE_LV_WIDGET_METER - int be_ntv_lv_meter_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_meter_create, "+_p", "(lv.lv_obj)"); } -#endif // BE_LV_WIDGET_METER - /* `lv_msgbox` methods */ -#ifdef BE_LV_WIDGET_MSGBOX - int be_ntv_lv_msgbox_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_msgbox_create, "+_p", "(lv.lv_obj)ss(lv.str_arr)b"); } -#endif // BE_LV_WIDGET_MSGBOX - /* `lv_spinbox` methods */ -#ifdef BE_LV_WIDGET_SPINBOX - int be_ntv_lv_spinbox_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_spinbox_create, "+_p", "(lv.lv_obj)"); } -#endif // BE_LV_WIDGET_SPINBOX - /* `lv_spinner` methods */ -#ifdef BE_LV_WIDGET_SPINNER - int be_ntv_lv_spinner_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_spinner_create, "+_p", "(lv.lv_obj)ii"); } -#endif // BE_LV_WIDGET_SPINNER - /* `lv_tabview` methods */ -#ifdef BE_LV_WIDGET_TABVIEW - int be_ntv_lv_tabview_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_tabview_create, "+_p", "(lv.lv_obj)ii"); } -#endif // BE_LV_WIDGET_TABVIEW - /* `lv_tileview` methods */ -#ifdef BE_LV_WIDGET_TILEVIEW - int be_ntv_lv_tileview_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_tileview_create, "+_p", "(lv.lv_obj)"); } -#endif // BE_LV_WIDGET_TILEVIEW /* `lv_anim` methods */ /* `lv_timer` methods */ + /* `lv_animimg` methods */ +#ifdef BE_LV_WIDGET_ANIMIMG + int be_ntv_lv_animimg_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_animimg_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_ANIMIMG /* `lv_arc` methods */ #ifdef BE_LV_WIDGET_ARC - int be_ntv_lv_arc_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_arc_create, "+_p", "(lv.lv_obj)"); } + int be_ntv_lv_arc_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_arc_create, "+_p", "(lv.obj)"); } #endif // BE_LV_WIDGET_ARC /* `lv_bar` methods */ #ifdef BE_LV_WIDGET_BAR - int be_ntv_lv_bar_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_bar_create, "+_p", "(lv.lv_obj)"); } + int be_ntv_lv_bar_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_bar_create, "+_p", "(lv.obj)"); } #endif // BE_LV_WIDGET_BAR - /* `lv_btn` methods */ -#ifdef BE_LV_WIDGET_BTN - int be_ntv_lv_btn_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_btn_create, "+_p", "(lv.lv_obj)"); } -#endif // BE_LV_WIDGET_BTN + /* `lv_button` methods */ +#ifdef BE_LV_WIDGET_BUTTON + int be_ntv_lv_button_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_button_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_BUTTON + /* `lv_buttonmatrix` methods */ +#ifdef BE_LV_WIDGET_BUTTONMATRIX + int be_ntv_lv_buttonmatrix_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_buttonmatrix_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_BUTTONMATRIX + /* `lv_calendar` methods */ +#ifdef BE_LV_WIDGET_CALENDAR + int be_ntv_lv_calendar_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_calendar_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_CALENDAR +#ifdef BE_LV_WIDGET_CALENDAR + int be_ntv_lv_calendar_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_calendar_header_arrow_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_CALENDAR +#ifdef BE_LV_WIDGET_CALENDAR + int be_ntv_lv_calendar_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_calendar_header_dropdown_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_CALENDAR /* `lv_canvas` methods */ #ifdef BE_LV_WIDGET_CANVAS - int be_ntv_lv_canvas_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_canvas_create, "+_p", "(lv.lv_obj)"); } + int be_ntv_lv_canvas_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_canvas_create, "+_p", "(lv.obj)"); } #endif // BE_LV_WIDGET_CANVAS + /* `lv_chart` methods */ +#ifdef BE_LV_WIDGET_CHART + int be_ntv_lv_chart_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_chart_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_CHART /* `lv_checkbox` methods */ #ifdef BE_LV_WIDGET_CHECKBOX - int be_ntv_lv_checkbox_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_checkbox_create, "+_p", "(lv.lv_obj)"); } + int be_ntv_lv_checkbox_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_checkbox_create, "+_p", "(lv.obj)"); } #endif // BE_LV_WIDGET_CHECKBOX /* `lv_dropdown` methods */ #ifdef BE_LV_WIDGET_DROPDOWN - int be_ntv_lv_dropdown_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_dropdown_create, "+_p", "(lv.lv_obj)"); } + int be_ntv_lv_dropdown_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_dropdown_create, "+_p", "(lv.obj)"); } #endif // BE_LV_WIDGET_DROPDOWN + /* `lv_imagebutton` methods */ +#ifdef BE_LV_WIDGET_IMAGEBUTTON + int be_ntv_lv_imagebutton_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_imagebutton_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_IMAGEBUTTON + /* `lv_keyboard` methods */ +#ifdef BE_LV_WIDGET_KEYBOARD + int be_ntv_lv_keyboard_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_keyboard_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_KEYBOARD /* `lv_label` methods */ #ifdef BE_LV_WIDGET_LABEL - int be_ntv_lv_label_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_label_create, "+_p", "(lv.lv_obj)"); } + int be_ntv_lv_label_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_label_create, "+_p", "(lv.obj)"); } #endif // BE_LV_WIDGET_LABEL + /* `lv_led` methods */ +#ifdef BE_LV_WIDGET_LED + int be_ntv_lv_led_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_led_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_LED /* `lv_line` methods */ #ifdef BE_LV_WIDGET_LINE - int be_ntv_lv_line_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_line_create, "+_p", "(lv.lv_obj)"); } + int be_ntv_lv_line_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_line_create, "+_p", "(lv.obj)"); } #endif // BE_LV_WIDGET_LINE + /* `lv_list` methods */ +#ifdef BE_LV_WIDGET_LIST + int be_ntv_lv_list_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_list_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_LIST + /* `lv_menu` methods */ +#ifdef BE_LV_WIDGET_MENU + int be_ntv_lv_menu_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_menu_cont_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_MENU +#ifdef BE_LV_WIDGET_MENU + int be_ntv_lv_menu_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_menu_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_MENU +#ifdef BE_LV_WIDGET_MENU + int be_ntv_lv_menu_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_menu_page_create, "+_p", "(lv.obj)c"); } +#endif // BE_LV_WIDGET_MENU +#ifdef BE_LV_WIDGET_MENU + int be_ntv_lv_menu_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_menu_section_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_MENU +#ifdef BE_LV_WIDGET_MENU + int be_ntv_lv_menu_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_menu_separator_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_MENU + /* `lv_msgbox` methods */ +#ifdef BE_LV_WIDGET_MSGBOX + int be_ntv_lv_msgbox_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_msgbox_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_MSGBOX /* `lv_roller` methods */ #ifdef BE_LV_WIDGET_ROLLER - int be_ntv_lv_roller_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_roller_create, "+_p", "(lv.lv_obj)"); } + int be_ntv_lv_roller_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_roller_create, "+_p", "(lv.obj)"); } #endif // BE_LV_WIDGET_ROLLER + /* `lv_scale` methods */ +#ifdef BE_LV_WIDGET_SCALE + int be_ntv_lv_scale_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_scale_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_SCALE /* `lv_slider` methods */ #ifdef BE_LV_WIDGET_SLIDER - int be_ntv_lv_slider_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_slider_create, "+_p", "(lv.lv_obj)"); } + int be_ntv_lv_slider_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_slider_create, "+_p", "(lv.obj)"); } #endif // BE_LV_WIDGET_SLIDER + /* `lv_spangroup` methods */ +#ifdef BE_LV_WIDGET_SPANGROUP + int be_ntv_lv_spangroup_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_spangroup_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_SPANGROUP + /* `lv_spinbox` methods */ +#ifdef BE_LV_WIDGET_SPINBOX + int be_ntv_lv_spinbox_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_spinbox_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_SPINBOX + /* `lv_spinner` methods */ +#ifdef BE_LV_WIDGET_SPINNER + int be_ntv_lv_spinner_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_spinner_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_SPINNER /* `lv_switch` methods */ #ifdef BE_LV_WIDGET_SWITCH - int be_ntv_lv_switch_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_switch_create, "+_p", "(lv.lv_obj)"); } + int be_ntv_lv_switch_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_switch_create, "+_p", "(lv.obj)"); } #endif // BE_LV_WIDGET_SWITCH /* `lv_table` methods */ #ifdef BE_LV_WIDGET_TABLE - int be_ntv_lv_table_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_table_create, "+_p", "(lv.lv_obj)"); } + int be_ntv_lv_table_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_table_create, "+_p", "(lv.obj)"); } #endif // BE_LV_WIDGET_TABLE + /* `lv_tabview` methods */ +#ifdef BE_LV_WIDGET_TABVIEW + int be_ntv_lv_tabview_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_tabview_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_TABVIEW /* `lv_textarea` methods */ #ifdef BE_LV_WIDGET_TEXTAREA - int be_ntv_lv_textarea_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_textarea_create, "+_p", "(lv.lv_obj)"); } + int be_ntv_lv_textarea_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_textarea_create, "+_p", "(lv.obj)"); } #endif // BE_LV_WIDGET_TEXTAREA + /* `lv_tileview` methods */ +#ifdef BE_LV_WIDGET_TILEVIEW + int be_ntv_lv_tileview_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_tileview_create, "+_p", "(lv.obj)"); } +#endif // BE_LV_WIDGET_TILEVIEW // create font either empty or from parameter on stack int lvbe_font_create(bvm *vm) { return be_call_c_func(vm, NULL, "+_p", ""); } diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c index e040b1212..da333e5b6 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c @@ -22,175 +22,193 @@ extern int lv0_load_font(bvm *vm); extern lv_ts_calibration_t * lv_get_ts_calibration(void); static int lv_get_hor_res(void) { - return lv_disp_get_hor_res(lv_disp_get_default()); + return lv_display_get_horizontal_resolution(NULL); } static int lv_get_ver_res(void) { - return lv_disp_get_ver_res(lv_disp_get_default()); + return lv_display_get_vertical_resolution(NULL); } /* `lv` methods */ const be_ntv_func_def_t lv_func[] = { { "anim_count_running", { (const void*) &lv_anim_count_running, "i", "" } }, - { "anim_del", { (const void*) &lv_anim_del, "b", ".c" } }, - { "anim_del_all", { (const void*) &lv_anim_del_all, "", "" } }, - { "anim_get", { (const void*) &lv_anim_get, "lv.lv_anim", ".c" } }, - { "anim_get_timer", { (const void*) &lv_anim_get_timer, "lv.lv_timer", "" } }, + { "anim_delete", { (const void*) &lv_anim_delete, "b", ".c" } }, + { "anim_delete_all", { (const void*) &lv_anim_delete_all, "", "" } }, + { "anim_get", { (const void*) &lv_anim_get, "lv.anim", ".c" } }, + { "anim_get_timer", { (const void*) &lv_anim_get_timer, "lv.timer", "" } }, { "anim_refr_now", { (const void*) &lv_anim_refr_now, "", "" } }, - { "anim_speed_to_time", { (const void*) &lv_anim_speed_to_time, "i", "iii" } }, - { "area_align", { (const void*) &lv_area_align, "", "(lv.lv_area)(lv.lv_area)iii" } }, - { "area_copy", { (const void*) &lv_area_copy, "", "(lv.lv_area)(lv.lv_area)" } }, - { "area_get_height", { (const void*) &lv_area_get_height, "i", "(lv.lv_area)" } }, - { "area_get_size", { (const void*) &lv_area_get_size, "i", "(lv.lv_area)" } }, - { "area_get_width", { (const void*) &lv_area_get_width, "i", "(lv.lv_area)" } }, - { "area_increase", { (const void*) &lv_area_increase, "", "(lv.lv_area)ii" } }, - { "area_move", { (const void*) &lv_area_move, "", "(lv.lv_area)ii" } }, - { "area_set", { (const void*) &lv_area_set, "", "(lv.lv_area)iiii" } }, - { "area_set_height", { (const void*) &lv_area_set_height, "", "(lv.lv_area)i" } }, - { "area_set_width", { (const void*) &lv_area_set_width, "", "(lv.lv_area)i" } }, - { "atan2", { (const void*) &lv_atan2, "i", "ii" } }, - { "bezier3", { (const void*) &lv_bezier3, "i", "iiiii" } }, + { "anim_speed", { (const void*) &lv_anim_speed, "i", "i" } }, + { "anim_speed_clamped", { (const void*) &lv_anim_speed_clamped, "i", "iii" } }, + { "area_align", { (const void*) &lv_area_align, "", "(lv.area)(lv.area)iii" } }, + { "area_copy", { (const void*) &lv_area_copy, "", "(lv.area)(lv.area)" } }, + { "area_get_height", { (const void*) &lv_area_get_height, "i", "(lv.area)" } }, + { "area_get_size", { (const void*) &lv_area_get_size, "i", "(lv.area)" } }, + { "area_get_width", { (const void*) &lv_area_get_width, "i", "(lv.area)" } }, + { "area_increase", { (const void*) &lv_area_increase, "", "(lv.area)ii" } }, + { "area_move", { (const void*) &lv_area_move, "", "(lv.area)ii" } }, + { "area_set", { (const void*) &lv_area_set, "", "(lv.area)iiii" } }, + { "area_set_height", { (const void*) &lv_area_set_height, "", "(lv.area)i" } }, + { "area_set_width", { (const void*) &lv_area_set_width, "", "(lv.area)i" } }, + { "canvas_buf_size", { (const void*) &lv_canvas_buf_size, "i", "iiii" } }, { "clamp_height", { (const void*) &lv_clamp_height, "i", "iiii" } }, { "clamp_width", { (const void*) &lv_clamp_width, "i", "iiii" } }, - { "color_black", { (const void*) &lv_color_black, "lv.lv_color", "" } }, - { "color_brightness", { (const void*) &lv_color_brightness, "i", "(lv.lv_color)" } }, - { "color_change_lightness", { (const void*) &lv_color_change_lightness, "lv.lv_color", "(lv.lv_color)i" } }, - { "color_chroma_key", { (const void*) &lv_color_chroma_key, "lv.lv_color", "" } }, - { "color_darken", { (const void*) &lv_color_darken, "lv.lv_color", "(lv.lv_color)i" } }, - { "color_fill", { (const void*) &lv_color_fill, "", "(lv.lv_color)(lv.lv_color)i" } }, - { "color_filter_dsc_init", { (const void*) &lv_color_filter_dsc_init, "", "(lv.lv_color_filter_dsc)^lv_color_filter_cb^" } }, - { "color_hex", { (const void*) &lv_color_hex, "lv.lv_color", "i" } }, - { "color_hex3", { (const void*) &lv_color_hex3, "lv.lv_color", "i" } }, - { "color_hsv_to_rgb", { (const void*) &lv_color_hsv_to_rgb, "lv.lv_color", "iii" } }, - { "color_lighten", { (const void*) &lv_color_lighten, "lv.lv_color", "(lv.lv_color)i" } }, - { "color_make", { (const void*) &lv_color_make, "lv.lv_color", "iii" } }, - { "color_mix", { (const void*) &lv_color_mix, "lv.lv_color", "(lv.lv_color)(lv.lv_color)i" } }, - { "color_mix_premult", { (const void*) &lv_color_mix_premult, "lv.lv_color", "(lv.uint16)(lv.lv_color)i" } }, - { "color_mix_with_alpha", { (const void*) &lv_color_mix_with_alpha, "", "(lv.lv_color)i(lv.lv_color)i(lv.lv_color)(lv.lv_opa)" } }, - { "color_premult", { (const void*) &lv_color_premult, "", "(lv.lv_color)i(lv.uint16)" } }, + { "color32_eq", { (const void*) &lv_color32_eq, "b", "ii" } }, + { "color32_make", { (const void*) &lv_color32_make, "i", "iiii" } }, + { "color_16_16_mix", { (const void*) &lv_color_16_16_mix, "i", "iii" } }, + { "color_black", { (const void*) &lv_color_black, "lv.color", "" } }, + { "color_brightness", { (const void*) &lv_color_brightness, "i", "(lv.color)" } }, + { "color_darken", { (const void*) &lv_color_darken, "lv.color", "(lv.color)i" } }, + { "color_eq", { (const void*) &lv_color_eq, "b", "(lv.color)(lv.color)" } }, + { "color_format_get_bpp", { (const void*) &lv_color_format_get_bpp, "i", "i" } }, + { "color_format_get_size", { (const void*) &lv_color_format_get_size, "i", "i" } }, + { "color_format_has_alpha", { (const void*) &lv_color_format_has_alpha, "b", "i" } }, + { "color_hex", { (const void*) &lv_color_hex, "lv.color", "i" } }, + { "color_hex3", { (const void*) &lv_color_hex3, "lv.color", "i" } }, + { "color_hsv_to_rgb", { (const void*) &lv_color_hsv_to_rgb, "lv.color", "iii" } }, + { "color_lighten", { (const void*) &lv_color_lighten, "lv.color", "(lv.color)i" } }, + { "color_make", { (const void*) &lv_color_make, "lv.color", "iii" } }, + { "color_mix", { (const void*) &lv_color_mix, "lv.color", "(lv.color)(lv.color)i" } }, + { "color_mix32", { (const void*) &lv_color_mix32, "i", "ii" } }, { "color_rgb_to_hsv", { (const void*) &lv_color_rgb_to_hsv, "i", "iii" } }, - { "color_to1", { (const void*) &lv_color_to1, "i", "(lv.lv_color)" } }, - { "color_to16", { (const void*) &lv_color_to16, "i", "(lv.lv_color)" } }, - { "color_to32", { (const void*) &lv_color_to32, "i", "(lv.lv_color)" } }, - { "color_to8", { (const void*) &lv_color_to8, "i", "(lv.lv_color)" } }, - { "color_to_hsv", { (const void*) &lv_color_to_hsv, "i", "(lv.lv_color)" } }, - { "color_white", { (const void*) &lv_color_white, "lv.lv_color", "" } }, + { "color_to_32", { (const void*) &lv_color_to_32, "i", "(lv.color)i" } }, + { "color_to_hsv", { (const void*) &lv_color_to_hsv, "i", "(lv.color)" } }, + { "color_to_int", { (const void*) &lv_color_to_int, "i", "(lv.color)" } }, + { "color_to_u16", { (const void*) &lv_color_to_u16, "i", "(lv.color)" } }, + { "color_to_u32", { (const void*) &lv_color_to_u32, "i", "(lv.color)" } }, + { "color_white", { (const void*) &lv_color_white, "lv.color", "" } }, + { "display_create", { (const void*) &lv_display_create, "lv.display", "ii" } }, + { "display_get_default", { (const void*) &lv_display_get_default, "lv.display", "" } }, { "dpx", { (const void*) &lv_dpx, "i", "i" } }, - { "draw_arc", { (const void*) &lv_draw_arc, "", "(lv.lv_draw_ctx)(lv.lv_draw_arc_dsc)(lv.lv_point)iii" } }, - { "draw_arc_dsc_init", { (const void*) &lv_draw_arc_dsc_init, "", "(lv.lv_draw_arc_dsc)" } }, - { "draw_arc_get_area", { (const void*) &lv_draw_arc_get_area, "", "iiiiiib(lv.lv_area)" } }, - { "draw_img", { (const void*) &lv_draw_img, "", "(lv.lv_draw_ctx)(lv.lv_draw_img_dsc)(lv.lv_area)." } }, - { "draw_img_decoded", { (const void*) &lv_draw_img_decoded, "", "(lv.lv_draw_ctx)(lv.lv_draw_img_dsc)(lv.lv_area)ci" } }, - { "draw_img_dsc_init", { (const void*) &lv_draw_img_dsc_init, "", "(lv.lv_draw_img_dsc)" } }, + { "draw_arc", { (const void*) &lv_draw_arc, "", "c(lv.draw_arc_dsc)" } }, + { "draw_arc_dsc_init", { (const void*) &lv_draw_arc_dsc_init, "", "(lv.draw_arc_dsc)" } }, + { "draw_arc_get_area", { (const void*) &lv_draw_arc_get_area, "", "iiiiiib(lv.area)" } }, + { "draw_character", { (const void*) &lv_draw_character, "", "c(lv.draw_label_dsc)ci" } }, + { "draw_create_unit", { (const void*) &lv_draw_create_unit, "c", "i" } }, + { "draw_deinit", { (const void*) &lv_draw_deinit, "", "" } }, + { "draw_dispatch", { (const void*) &lv_draw_dispatch, "", "" } }, + { "draw_dispatch_layer", { (const void*) &lv_draw_dispatch_layer, "b", "(lv.display)c" } }, + { "draw_dispatch_request", { (const void*) &lv_draw_dispatch_request, "", "" } }, + { "draw_dispatch_wait_for_request", { (const void*) &lv_draw_dispatch_wait_for_request, "", "" } }, { "draw_init", { (const void*) &lv_draw_init, "", "" } }, - { "draw_label", { (const void*) &lv_draw_label, "", "(lv.lv_draw_ctx)(lv.lv_draw_label_dsc)(lv.lv_area)s(lv.lv_draw_label_hint)" } }, - { "draw_label_dsc_init", { (const void*) &lv_draw_label_dsc_init, "", "(lv.lv_draw_label_dsc)" } }, - { "draw_layer_adjust", { (const void*) &lv_draw_layer_adjust, "", "(lv.lv_draw_ctx)(lv.lv_draw_layer_ctx)(lv.lv_draw_layer_flags)" } }, - { "draw_layer_blend", { (const void*) &lv_draw_layer_blend, "", "(lv.lv_draw_ctx)(lv.lv_draw_layer_ctx)(lv.lv_draw_img_dsc)" } }, - { "draw_layer_create", { (const void*) &lv_draw_layer_create, "lv.lv_draw_layer_ctx", "(lv.lv_draw_ctx)(lv.lv_area)(lv.lv_draw_layer_flags)" } }, - { "draw_layer_destroy", { (const void*) &lv_draw_layer_destroy, "", "(lv.lv_draw_ctx)(lv.lv_draw_layer_ctx)" } }, - { "draw_letter", { (const void*) &lv_draw_letter, "", "(lv.lv_draw_ctx)(lv.lv_draw_label_dsc)(lv.lv_point)i" } }, - { "draw_line", { (const void*) &lv_draw_line, "", "(lv.lv_draw_ctx)(lv.lv_draw_line_dsc)(lv.lv_point)(lv.lv_point)" } }, - { "draw_line_dsc_init", { (const void*) &lv_draw_line_dsc_init, "", "(lv.lv_draw_line_dsc)" } }, - { "draw_mask_add", { (const void*) &lv_draw_mask_add, "i", ".." } }, - { "draw_mask_angle_init", { (const void*) &lv_draw_mask_angle_init, "", "(lv.lv_draw_mask_angle_param)iiii" } }, - { "draw_mask_apply", { (const void*) &lv_draw_mask_apply, "i", "(lv.lv_opa)iii" } }, - { "draw_mask_apply_ids", { (const void*) &lv_draw_mask_apply_ids, "i", "(lv.lv_opa)iii(lv.int16)i" } }, - { "draw_mask_fade_init", { (const void*) &lv_draw_mask_fade_init, "", "(lv.lv_draw_mask_fade_param)(lv.lv_area)iiii" } }, - { "draw_mask_free_param", { (const void*) &lv_draw_mask_free_param, "", "." } }, - { "draw_mask_get_cnt", { (const void*) &lv_draw_mask_get_cnt, "i", "" } }, - { "draw_mask_is_any", { (const void*) &lv_draw_mask_is_any, "b", "(lv.lv_area)" } }, - { "draw_mask_line_angle_init", { (const void*) &lv_draw_mask_line_angle_init, "", "(lv.lv_draw_mask_line_param)iiii" } }, - { "draw_mask_line_points_init", { (const void*) &lv_draw_mask_line_points_init, "", "(lv.lv_draw_mask_line_param)iiiii" } }, - { "draw_mask_map_init", { (const void*) &lv_draw_mask_map_init, "", "(lv.lv_draw_mask_map_param)(lv.lv_area)(lv.lv_opa)" } }, - { "draw_mask_polygon_init", { (const void*) &lv_draw_mask_polygon_init, "", "(lv.lv_draw_mask_polygon_param)(lv.lv_point)i" } }, - { "draw_mask_radius_init", { (const void*) &lv_draw_mask_radius_init, "", "(lv.lv_draw_mask_radius_param)(lv.lv_area)ib" } }, - { "draw_mask_remove_custom", { (const void*) &lv_draw_mask_remove_custom, ".", "." } }, - { "draw_mask_remove_id", { (const void*) &lv_draw_mask_remove_id, ".", "i" } }, - { "draw_polygon", { (const void*) &lv_draw_polygon, "", "(lv.lv_draw_ctx)(lv.lv_draw_rect_dsc)(lv.lv_point_arr)i" } }, - { "draw_rect", { (const void*) &lv_draw_rect, "", "(lv.lv_draw_ctx)(lv.lv_draw_rect_dsc)(lv.lv_area)" } }, - { "draw_rect_dsc_init", { (const void*) &lv_draw_rect_dsc_init, "", "(lv.lv_draw_rect_dsc)" } }, - { "draw_transform", { (const void*) &lv_draw_transform, "", "(lv.lv_draw_ctx)(lv.lv_area).iii(lv.lv_draw_img_dsc)i(lv.lv_color)(lv.lv_opa)" } }, - { "draw_triangle", { (const void*) &lv_draw_triangle, "", "(lv.lv_draw_ctx)(lv.lv_draw_rect_dsc)(lv.lv_point_arr)" } }, - { "draw_wait_for_finish", { (const void*) &lv_draw_wait_for_finish, "", "(lv.lv_draw_ctx)" } }, + { "draw_label", { (const void*) &lv_draw_label, "", "c(lv.draw_label_dsc)(lv.area)" } }, + { "draw_label_dsc_init", { (const void*) &lv_draw_label_dsc_init, "", "(lv.draw_label_dsc)" } }, + { "draw_layer_alloc_buf", { (const void*) &lv_draw_layer_alloc_buf, "c", "c" } }, + { "draw_layer_create", { (const void*) &lv_draw_layer_create, "c", "ci(lv.area)" } }, + { "draw_layer_go_to_xy", { (const void*) &lv_draw_layer_go_to_xy, "c", "cii" } }, + { "draw_line", { (const void*) &lv_draw_line, "", "c(lv.draw_line_dsc)" } }, + { "draw_line_dsc_init", { (const void*) &lv_draw_line_dsc_init, "", "(lv.draw_line_dsc)" } }, + { "draw_rect", { (const void*) &lv_draw_rect, "", "c(lv.draw_rect_dsc)(lv.area)" } }, + { "draw_rect_dsc_init", { (const void*) &lv_draw_rect_dsc_init, "", "(lv.draw_rect_dsc)" } }, + { "draw_vector", { (const void*) &lv_draw_vector, "", "c" } }, { "event_register_id", { (const void*) &lv_event_register_id, "i", "" } }, - { "event_send", { (const void*) &lv_event_send, "i", "(lv.lv_obj)i." } }, - { "event_set_cover_res", { (const void*) &lv_event_set_cover_res, "", "(lv.lv_event)(lv.lv_cover_res)" } }, - { "event_set_ext_draw_size", { (const void*) &lv_event_set_ext_draw_size, "", "(lv.lv_event)i" } }, - { "event_stop_bubbling", { (const void*) &lv_event_stop_bubbling, "", "(lv.lv_event)" } }, - { "event_stop_processing", { (const void*) &lv_event_stop_processing, "", "(lv.lv_event)" } }, - { "flex_init", { (const void*) &lv_flex_init, "", "" } }, - { "font_get_glyph_bitmap", { (const void*) &lv_font_get_glyph_bitmap, "c", "(lv.lv_font)i" } }, - { "font_get_glyph_dsc", { (const void*) &lv_font_get_glyph_dsc, "b", "(lv.lv_font)(lv.lv_font_glyph_dsc)ii" } }, - { "font_get_glyph_width", { (const void*) &lv_font_get_glyph_width, "i", "(lv.lv_font)ii" } }, - { "font_get_line_height", { (const void*) &lv_font_get_line_height, "i", "(lv.lv_font)" } }, + { "font_get_glyph_width", { (const void*) &lv_font_get_glyph_width, "i", "(lv.font)ii" } }, + { "font_get_line_height", { (const void*) &lv_font_get_line_height, "i", "(lv.font)" } }, + { "font_set_kerning", { (const void*) &lv_font_set_kerning, "", "(lv.font)i" } }, { "get_hor_res", { (const void*) &lv_get_hor_res, "i", "" } }, - { "get_ts_calibration", { (const void*) &lv_get_ts_calibration, "lv.lv_ts_calibration", "" } }, + { "get_ts_calibration", { (const void*) &lv_get_ts_calibration, "lv.ts_calibration", "" } }, { "get_ver_res", { (const void*) &lv_get_ver_res, "i", "" } }, - { "grid_fr", { (const void*) &lv_grid_fr, "i", "i" } }, - { "grid_init", { (const void*) &lv_grid_init, "", "" } }, - { "group_get_default", { (const void*) &lv_group_get_default, "lv.lv_group", "" } }, - { "img_src_get_type", { (const void*) &lv_img_src_get_type, "i", "." } }, - { "indev_get_act", { (const void*) &lv_indev_get_act, "lv.lv_indev", "" } }, - { "indev_get_obj_act", { (const void*) &lv_indev_get_obj_act, "lv.lv_obj", "" } }, - { "indev_get_read_timer", { (const void*) &lv_indev_get_read_timer, "lv.lv_timer", "(lv.lv_disp)" } }, - { "indev_read_timer_cb", { (const void*) &lv_indev_read_timer_cb, "", "(lv.lv_timer)" } }, - { "is_initialized", { (const void*) &lv_is_initialized, "b", "" } }, - { "layer_sys", { (const void*) &lv_layer_sys, "lv.lv_obj", "" } }, - { "layer_top", { (const void*) &lv_layer_top, "lv.lv_obj", "" } }, - { "layout_register", { (const void*) &lv_layout_register, "i", "^lv_layout_update_cb^." } }, - { "map", { (const void*) &lv_map, "i", "iiiii" } }, - { "obj_class_create_obj", { (const void*) &lv_obj_class_create_obj, "lv.lv_obj", "(lv._lv_obj_class)(lv.lv_obj)" } }, - { "obj_del_anim_ready_cb", { (const void*) &lv_obj_del_anim_ready_cb, "", "(lv.lv_anim)" } }, - { "obj_draw_dsc_init", { (const void*) &lv_obj_draw_dsc_init, "", "(lv.lv_obj_draw_part_dsc)(lv.lv_draw_ctx)" } }, - { "obj_draw_part_check_type", { (const void*) &lv_obj_draw_part_check_type, "b", "(lv.lv_obj_draw_part_dsc)(lv._lv_obj_class)i" } }, + { "group_by_index", { (const void*) &lv_group_by_index, "lv.group", "i" } }, + { "group_get_count", { (const void*) &lv_group_get_count, "i", "" } }, + { "group_get_default", { (const void*) &lv_group_get_default, "lv.group", "" } }, + { "indev_active", { (const void*) &lv_indev_active, "lv.indev", "" } }, + { "indev_create", { (const void*) &lv_indev_create, "lv.indev", "" } }, + { "indev_get_active_obj", { (const void*) &lv_indev_get_active_obj, "lv.obj", "" } }, + { "indev_read_timer_cb", { (const void*) &lv_indev_read_timer_cb, "", "(lv.timer)" } }, + { "layer_bottom", { (const void*) &lv_layer_bottom, "lv.obj", "" } }, + { "layer_sys", { (const void*) &lv_layer_sys, "lv.obj", "" } }, + { "layer_top", { (const void*) &lv_layer_top, "lv.obj", "" } }, + { "obj_assign_id", { (const void*) &lv_obj_assign_id, "", "(lv.obj_class)(lv.obj)" } }, + { "obj_class_create_obj", { (const void*) &lv_obj_class_create_obj, "lv.obj", "(lv.obj_class)(lv.obj)" } }, + { "obj_delete_anim_completed_cb", { (const void*) &lv_obj_delete_anim_completed_cb, "", "(lv.anim)" } }, { "obj_enable_style_refresh", { (const void*) &lv_obj_enable_style_refresh, "", "b" } }, - { "obj_event_base", { (const void*) &lv_obj_event_base, "i", "(lv.lv_obj_class)(lv.lv_event)" } }, - { "obj_redraw", { (const void*) &lv_obj_redraw, "", "(lv.lv_draw_ctx)(lv.lv_obj)" } }, - { "obj_report_style_change", { (const void*) &lv_obj_report_style_change, "", "(lv.lv_style)" } }, + { "obj_event_base", { (const void*) &lv_obj_event_base, "i", "(lv.obj_class)(lv.event)" } }, + { "obj_redraw", { (const void*) &lv_obj_redraw, "", "c(lv.obj)" } }, + { "obj_report_style_change", { (const void*) &lv_obj_report_style_change, "", "(lv.style)" } }, { "obj_style_get_selector_part", { (const void*) &lv_obj_style_get_selector_part, "i", "i" } }, { "obj_style_get_selector_state", { (const void*) &lv_obj_style_get_selector_state, "i", "i" } }, - { "palette_darken", { (const void*) &lv_palette_darken, "lv.lv_color", "ii" } }, - { "palette_lighten", { (const void*) &lv_palette_lighten, "lv.lv_color", "ii" } }, - { "palette_main", { (const void*) &lv_palette_main, "lv.lv_color", "i" } }, + { "objid_builtin_destroy", { (const void*) &lv_objid_builtin_destroy, "", "" } }, { "pct", { (const void*) &lv_pct, "i", "i" } }, - { "point_transform", { (const void*) &lv_point_transform, "", "(lv.lv_point)ii(lv.lv_point)" } }, - { "rand", { (const void*) &lv_rand, "i", "ii" } }, - { "refr_now", { (const void*) &lv_refr_now, "", "(lv.lv_disp)" } }, - { "scr_act", { (const void*) &lv_scr_act, "lv.lv_obj", "" } }, - { "scr_load", { (const void*) &lv_scr_load, "", "(lv.lv_obj)" } }, - { "scr_load_anim", { (const void*) &lv_scr_load_anim, "", "(lv.lv_obj)iiib" } }, - { "sqrt", { (const void*) &lv_sqrt, "", "i(lv.lv_sqrt_res)i" } }, + { "pct_to_px", { (const void*) &lv_pct_to_px, "i", "ii" } }, + { "point_from_precise", { (const void*) &lv_point_from_precise, "i", "(lv.point_precise)" } }, + { "point_precise_set", { (const void*) &lv_point_precise_set, "", "(lv.point_precise)ii" } }, + { "point_precise_swap", { (const void*) &lv_point_precise_swap, "", "(lv.point_precise)(lv.point_precise)" } }, + { "point_set", { (const void*) &lv_point_set, "", "cii" } }, + { "point_swap", { (const void*) &lv_point_swap, "", "cc" } }, + { "point_transform", { (const void*) &lv_point_transform, "", "ciiicb" } }, + { "refr_now", { (const void*) &lv_refr_now, "", "(lv.display)" } }, + { "scale_section_set_range", { (const void*) &lv_scale_section_set_range, "", "cii" } }, + { "scale_section_set_style", { (const void*) &lv_scale_section_set_style, "", "ci(lv.style)" } }, + { "scr_act", { (const void*) &lv_screen_active, "lv.obj", "" } }, + { "scr_load", { (const void*) &lv_screen_load, "", "(lv.obj)" } }, + { "scr_load_anim", { (const void*) &lv_screen_load_anim, "", "(lv.obj)iiib" } }, + { "screen_active", { (const void*) &lv_screen_active, "lv.obj", "" } }, + { "screen_load", { (const void*) &lv_screen_load, "", "(lv.obj)" } }, + { "screen_load_anim", { (const void*) &lv_screen_load_anim, "", "(lv.obj)iiib" } }, + { "span_set_text", { (const void*) &lv_span_set_text, "", "(lv.spangroup)s" } }, + { "span_set_text_static", { (const void*) &lv_span_set_text_static, "", "(lv.spangroup)s" } }, + { "span_stack_deinit", { (const void*) &lv_span_stack_deinit, "", "" } }, + { "span_stack_init", { (const void*) &lv_span_stack_init, "", "" } }, { "style_get_num_custom_props", { (const void*) &lv_style_get_num_custom_props, "i", "" } }, { "style_prop_get_default", { (const void*) &lv_style_prop_get_default, "i", "i" } }, { "style_prop_has_flag", { (const void*) &lv_style_prop_has_flag, "b", "ii" } }, { "style_register_prop", { (const void*) &lv_style_register_prop, "i", "i" } }, - { "style_transition_dsc_init", { (const void*) &lv_style_transition_dsc_init, "", "(lv.lv_style_transition_dsc)(lv.lv_style_prop)cii." } }, { "task_handler", { (const void*) &lv_task_handler, "i", "" } }, - { "theme_apply", { (const void*) &lv_theme_apply, "", "(lv.lv_obj)" } }, - { "theme_default_get", { (const void*) &lv_theme_default_get, "lv.lv_theme", "" } }, - { "theme_default_init", { (const void*) &lv_theme_default_init, "lv.lv_theme", "(lv.lv_disp)(lv.lv_color)(lv.lv_color)b(lv.lv_font)" } }, - { "theme_default_is_inited", { (const void*) &lv_theme_default_is_inited, "b", "" } }, - { "theme_get_color_primary", { (const void*) &lv_theme_get_color_primary, "lv.lv_color", "(lv.lv_obj)" } }, - { "theme_get_color_secondary", { (const void*) &lv_theme_get_color_secondary, "lv.lv_color", "(lv.lv_obj)" } }, - { "theme_get_font_large", { (const void*) &lv_theme_get_font_large, "lv.lv_font", "(lv.lv_obj)" } }, - { "theme_get_font_normal", { (const void*) &lv_theme_get_font_normal, "lv.lv_font", "(lv.lv_obj)" } }, - { "theme_get_font_small", { (const void*) &lv_theme_get_font_small, "lv.lv_font", "(lv.lv_obj)" } }, - { "theme_get_from_obj", { (const void*) &lv_theme_get_from_obj, "lv.lv_theme", "(lv.lv_obj)" } }, - { "theme_haspmota_init", { (const void*) &lv_theme_haspmota_init, "lv.lv_theme", "(lv.lv_disp)(lv.lv_color)(lv.lv_color)b(lv.lv_font)" } }, + { "theme_apply", { (const void*) &lv_theme_apply, "", "(lv.obj)" } }, + { "theme_get_color_primary", { (const void*) &lv_theme_get_color_primary, "lv.color", "(lv.obj)" } }, + { "theme_get_color_secondary", { (const void*) &lv_theme_get_color_secondary, "lv.color", "(lv.obj)" } }, + { "theme_get_font_large", { (const void*) &lv_theme_get_font_large, "lv.font", "(lv.obj)" } }, + { "theme_get_font_normal", { (const void*) &lv_theme_get_font_normal, "lv.font", "(lv.obj)" } }, + { "theme_get_font_small", { (const void*) &lv_theme_get_font_small, "lv.font", "(lv.obj)" } }, + { "theme_get_from_obj", { (const void*) &lv_theme_get_from_obj, "lv.theme", "(lv.obj)" } }, + { "theme_haspmota_init", { (const void*) &lv_theme_haspmota_init, "lv.theme", "(lv.display)(lv.color)(lv.color)b(lv.font)" } }, { "theme_haspmota_is_inited", { (const void*) &lv_theme_haspmota_is_inited, "b", "" } }, - { "theme_mono_init", { (const void*) &lv_theme_mono_init, "lv.lv_theme", "(lv.lv_disp)b(lv.lv_font)" } }, - { "theme_mono_is_inited", { (const void*) &lv_theme_mono_is_inited, "b", "" } }, - { "theme_set_apply_cb", { (const void*) &lv_theme_set_apply_cb, "", "(lv.lv_theme)^lv_theme_apply_cb^" } }, - { "theme_set_parent", { (const void*) &lv_theme_set_parent, "", "(lv.lv_theme)(lv.lv_theme)" } }, - { "timer_create", { (const void*) &lv_timer_create, "lv.lv_timer", "^lv_timer_cb^i." } }, - { "timer_create_basic", { (const void*) &lv_timer_create_basic, "lv.lv_timer", "" } }, + { "theme_set_parent", { (const void*) &lv_theme_set_parent, "", "(lv.theme)(lv.theme)" } }, + { "timer_create", { (const void*) &lv_timer_create, "lv.timer", "^lv_timer_cb^i." } }, + { "timer_create_basic", { (const void*) &lv_timer_create_basic, "lv.timer", "" } }, { "timer_enable", { (const void*) &lv_timer_enable, "", "b" } }, { "timer_get_idle", { (const void*) &lv_timer_get_idle, "i", "" } }, + { "timer_get_time_until_next", { (const void*) &lv_timer_get_time_until_next, "i", "" } }, { "timer_handler", { (const void*) &lv_timer_handler, "i", "" } }, { "timer_handler_run_in_period", { (const void*) &lv_timer_handler_run_in_period, "i", "i" } }, - { "trigo_cos", { (const void*) &lv_trigo_cos, "i", "i" } }, - { "trigo_sin", { (const void*) &lv_trigo_sin, "i", "i" } }, + { "timer_periodic_handler", { (const void*) &lv_timer_periodic_handler, "", "" } }, + { "vector_clear_area", { (const void*) &lv_vector_clear_area, "", "c(lv.area)" } }, + { "vector_dsc_add_path", { (const void*) &lv_vector_dsc_add_path, "", "cc" } }, + { "vector_dsc_create", { (const void*) &lv_vector_dsc_create, "c", "c" } }, + { "vector_dsc_delete", { (const void*) &lv_vector_dsc_delete, "", "c" } }, + { "vector_dsc_identity", { (const void*) &lv_vector_dsc_identity, "", "c" } }, + { "vector_dsc_rotate", { (const void*) &lv_vector_dsc_rotate, "", "cf" } }, + { "vector_dsc_scale", { (const void*) &lv_vector_dsc_scale, "", "cff" } }, + { "vector_dsc_set_blend_mode", { (const void*) &lv_vector_dsc_set_blend_mode, "", "ci" } }, + { "vector_dsc_set_fill_color", { (const void*) &lv_vector_dsc_set_fill_color, "", "c(lv.color)" } }, + { "vector_dsc_set_fill_color32", { (const void*) &lv_vector_dsc_set_fill_color32, "", "ci" } }, + { "vector_dsc_set_fill_image", { (const void*) &lv_vector_dsc_set_fill_image, "", "c(lv.draw_image_dsc)" } }, + { "vector_dsc_set_fill_linear_gradient", { (const void*) &lv_vector_dsc_set_fill_linear_gradient, "", "c(lv.grad_dsc)i" } }, + { "vector_dsc_set_fill_opa", { (const void*) &lv_vector_dsc_set_fill_opa, "", "ci" } }, + { "vector_dsc_set_fill_radial_gradient", { (const void*) &lv_vector_dsc_set_fill_radial_gradient, "", "c(lv.grad_dsc)fffi" } }, + { "vector_dsc_set_fill_rule", { (const void*) &lv_vector_dsc_set_fill_rule, "", "ci" } }, + { "vector_dsc_set_stroke_cap", { (const void*) &lv_vector_dsc_set_stroke_cap, "", "ci" } }, + { "vector_dsc_set_stroke_color", { (const void*) &lv_vector_dsc_set_stroke_color, "", "c(lv.color)" } }, + { "vector_dsc_set_stroke_color32", { (const void*) &lv_vector_dsc_set_stroke_color32, "", "ci" } }, + { "vector_dsc_set_stroke_dash", { (const void*) &lv_vector_dsc_set_stroke_dash, "", "c(lv.float_arr)i" } }, + { "vector_dsc_set_stroke_join", { (const void*) &lv_vector_dsc_set_stroke_join, "", "ci" } }, + { "vector_dsc_set_stroke_linear_gradient", { (const void*) &lv_vector_dsc_set_stroke_linear_gradient, "", "c(lv.grad_dsc)i" } }, + { "vector_dsc_set_stroke_miter_limit", { (const void*) &lv_vector_dsc_set_stroke_miter_limit, "", "ci" } }, + { "vector_dsc_set_stroke_opa", { (const void*) &lv_vector_dsc_set_stroke_opa, "", "ci" } }, + { "vector_dsc_set_stroke_radial_gradient", { (const void*) &lv_vector_dsc_set_stroke_radial_gradient, "", "c(lv.grad_dsc)fffi" } }, + { "vector_dsc_set_stroke_width", { (const void*) &lv_vector_dsc_set_stroke_width, "", "cf" } }, + { "vector_dsc_skew", { (const void*) &lv_vector_dsc_skew, "", "cff" } }, + { "vector_dsc_translate", { (const void*) &lv_vector_dsc_translate, "", "cff" } }, + { "vector_path_append_path", { (const void*) &lv_vector_path_append_path, "", "cc" } }, + { "vector_path_append_rect", { (const void*) &lv_vector_path_append_rect, "", "c(lv.area)ff" } }, + { "vector_path_clear", { (const void*) &lv_vector_path_clear, "", "c" } }, + { "vector_path_close", { (const void*) &lv_vector_path_close, "", "c" } }, + { "vector_path_copy", { (const void*) &lv_vector_path_copy, "", "cc" } }, + { "vector_path_create", { (const void*) &lv_vector_path_create, "c", "i" } }, + { "vector_path_delete", { (const void*) &lv_vector_path_delete, "", "c" } }, + { "version_info", { (const void*) &lv_version_info, "s", "" } }, + { "version_major", { (const void*) &lv_version_major, "i", "" } }, + { "version_minor", { (const void*) &lv_version_minor, "i", "" } }, + { "version_patch", { (const void*) &lv_version_patch, "i", "" } }, }; const size_t lv_func_size = sizeof(lv_func) / sizeof(lv_func[0]); @@ -222,18 +240,14 @@ const be_const_member_t lv0_constants[] = { { "ALIGN_TOP_LEFT", be_cconst_int(LV_ALIGN_TOP_LEFT) }, { "ALIGN_TOP_MID", be_cconst_int(LV_ALIGN_TOP_MID) }, { "ALIGN_TOP_RIGHT", be_cconst_int(LV_ALIGN_TOP_RIGHT) }, - { "ANIM_IMG_PART_MAIN", be_cconst_int(LV_ANIM_IMG_PART_MAIN) }, + { "ANIM_IMAGE_PART_MAIN", be_cconst_int(LV_ANIM_IMAGE_PART_MAIN) }, { "ANIM_OFF", be_cconst_int(LV_ANIM_OFF) }, { "ANIM_ON", be_cconst_int(LV_ANIM_ON) }, { "ANIM_PLAYTIME_INFINITE", be_cconst_int(LV_ANIM_PLAYTIME_INFINITE) }, { "ANIM_REPEAT_INFINITE", be_cconst_int(LV_ANIM_REPEAT_INFINITE) }, - { "ARC_DRAW_PART_BACKGROUND", be_cconst_int(LV_ARC_DRAW_PART_BACKGROUND) }, - { "ARC_DRAW_PART_FOREGROUND", be_cconst_int(LV_ARC_DRAW_PART_FOREGROUND) }, - { "ARC_DRAW_PART_KNOB", be_cconst_int(LV_ARC_DRAW_PART_KNOB) }, { "ARC_MODE_NORMAL", be_cconst_int(LV_ARC_MODE_NORMAL) }, { "ARC_MODE_REVERSE", be_cconst_int(LV_ARC_MODE_REVERSE) }, { "ARC_MODE_SYMMETRICAL", be_cconst_int(LV_ARC_MODE_SYMMETRICAL) }, - { "BAR_DRAW_PART_INDICATOR", be_cconst_int(LV_BAR_DRAW_PART_INDICATOR) }, { "BAR_MODE_NORMAL", be_cconst_int(LV_BAR_MODE_NORMAL) }, { "BAR_MODE_RANGE", be_cconst_int(LV_BAR_MODE_RANGE) }, { "BAR_MODE_SYMMETRICAL", be_cconst_int(LV_BAR_MODE_SYMMETRICAL) }, @@ -245,7 +259,6 @@ const be_const_member_t lv0_constants[] = { { "BLEND_MODE_ADDITIVE", be_cconst_int(LV_BLEND_MODE_ADDITIVE) }, { "BLEND_MODE_MULTIPLY", be_cconst_int(LV_BLEND_MODE_MULTIPLY) }, { "BLEND_MODE_NORMAL", be_cconst_int(LV_BLEND_MODE_NORMAL) }, - { "BLEND_MODE_REPLACE", be_cconst_int(LV_BLEND_MODE_REPLACE) }, { "BLEND_MODE_SUBTRACTIVE", be_cconst_int(LV_BLEND_MODE_SUBTRACTIVE) }, { "BORDER_SIDE_BOTTOM", be_cconst_int(LV_BORDER_SIDE_BOTTOM) }, { "BORDER_SIDE_FULL", be_cconst_int(LV_BORDER_SIDE_FULL) }, @@ -254,29 +267,30 @@ const be_const_member_t lv0_constants[] = { { "BORDER_SIDE_NONE", be_cconst_int(LV_BORDER_SIDE_NONE) }, { "BORDER_SIDE_RIGHT", be_cconst_int(LV_BORDER_SIDE_RIGHT) }, { "BORDER_SIDE_TOP", be_cconst_int(LV_BORDER_SIDE_TOP) }, - { "BTNMATRIX_BTN_NONE", be_cconst_int(LV_BTNMATRIX_BTN_NONE) }, - { "BTNMATRIX_CTRL_CHECKABLE", be_cconst_int(LV_BTNMATRIX_CTRL_CHECKABLE) }, - { "BTNMATRIX_CTRL_CHECKED", be_cconst_int(LV_BTNMATRIX_CTRL_CHECKED) }, - { "BTNMATRIX_CTRL_CLICK_TRIG", be_cconst_int(LV_BTNMATRIX_CTRL_CLICK_TRIG) }, - { "BTNMATRIX_CTRL_CUSTOM_1", be_cconst_int(LV_BTNMATRIX_CTRL_CUSTOM_1) }, - { "BTNMATRIX_CTRL_CUSTOM_2", be_cconst_int(LV_BTNMATRIX_CTRL_CUSTOM_2) }, - { "BTNMATRIX_CTRL_DISABLED", be_cconst_int(LV_BTNMATRIX_CTRL_DISABLED) }, - { "BTNMATRIX_CTRL_HIDDEN", be_cconst_int(LV_BTNMATRIX_CTRL_HIDDEN) }, - { "BTNMATRIX_CTRL_NO_REPEAT", be_cconst_int(LV_BTNMATRIX_CTRL_NO_REPEAT) }, - { "BTNMATRIX_CTRL_POPOVER", be_cconst_int(LV_BTNMATRIX_CTRL_POPOVER) }, - { "BTNMATRIX_CTRL_RECOLOR", be_cconst_int(LV_BTNMATRIX_CTRL_RECOLOR) }, - { "BTNMATRIX_DRAW_PART_BTN", be_cconst_int(LV_BTNMATRIX_DRAW_PART_BTN) }, + { "BTNMATRIX_BTN_NONE", be_cconst_int(LV_BUTTONMATRIX_BUTTON_NONE) }, + { "BTNMATRIX_CTRL_CHECKABLE", be_cconst_int(LV_BUTTONMATRIX_CTRL_CHECKABLE) }, + { "BTNMATRIX_CTRL_CHECKED", be_cconst_int(LV_BUTTONMATRIX_CTRL_CHECKED) }, + { "BTNMATRIX_CTRL_CLICK_TRIG", be_cconst_int(LV_BUTTONMATRIX_CTRL_CLICK_TRIG) }, + { "BTNMATRIX_CTRL_CUSTOM_1", be_cconst_int(LV_BUTTONMATRIX_CTRL_CUSTOM_1) }, + { "BTNMATRIX_CTRL_CUSTOM_2", be_cconst_int(LV_BUTTONMATRIX_CTRL_CUSTOM_2) }, + { "BTNMATRIX_CTRL_DISABLED", be_cconst_int(LV_BUTTONMATRIX_CTRL_DISABLED) }, + { "BTNMATRIX_CTRL_HIDDEN", be_cconst_int(LV_BUTTONMATRIX_CTRL_HIDDEN) }, + { "BTNMATRIX_CTRL_NO_REPEAT", be_cconst_int(LV_BUTTONMATRIX_CTRL_NO_REPEAT) }, + { "BTNMATRIX_CTRL_POPOVER", be_cconst_int(LV_BUTTONMATRIX_CTRL_POPOVER) }, + { "BUTTONMATRIX_BUTTON_NONE", be_cconst_int(LV_BUTTONMATRIX_BUTTON_NONE) }, + { "BUTTONMATRIX_CTRL_CHECKABLE", be_cconst_int(LV_BUTTONMATRIX_CTRL_CHECKABLE) }, + { "BUTTONMATRIX_CTRL_CHECKED", be_cconst_int(LV_BUTTONMATRIX_CTRL_CHECKED) }, + { "BUTTONMATRIX_CTRL_CLICK_TRIG", be_cconst_int(LV_BUTTONMATRIX_CTRL_CLICK_TRIG) }, + { "BUTTONMATRIX_CTRL_CUSTOM_1", be_cconst_int(LV_BUTTONMATRIX_CTRL_CUSTOM_1) }, + { "BUTTONMATRIX_CTRL_CUSTOM_2", be_cconst_int(LV_BUTTONMATRIX_CTRL_CUSTOM_2) }, + { "BUTTONMATRIX_CTRL_DISABLED", be_cconst_int(LV_BUTTONMATRIX_CTRL_DISABLED) }, + { "BUTTONMATRIX_CTRL_HIDDEN", be_cconst_int(LV_BUTTONMATRIX_CTRL_HIDDEN) }, + { "BUTTONMATRIX_CTRL_NO_REPEAT", be_cconst_int(LV_BUTTONMATRIX_CTRL_NO_REPEAT) }, + { "BUTTONMATRIX_CTRL_POPOVER", be_cconst_int(LV_BUTTONMATRIX_CTRL_POPOVER) }, { "CHART_AXIS_PRIMARY_X", be_cconst_int(LV_CHART_AXIS_PRIMARY_X) }, { "CHART_AXIS_PRIMARY_Y", be_cconst_int(LV_CHART_AXIS_PRIMARY_Y) }, { "CHART_AXIS_SECONDARY_X", be_cconst_int(LV_CHART_AXIS_SECONDARY_X) }, { "CHART_AXIS_SECONDARY_Y", be_cconst_int(LV_CHART_AXIS_SECONDARY_Y) }, - { "CHART_DRAW_PART_BAR", be_cconst_int(LV_CHART_DRAW_PART_BAR) }, - { "CHART_DRAW_PART_CURSOR", be_cconst_int(LV_CHART_DRAW_PART_CURSOR) }, - { "CHART_DRAW_PART_DIV_LINE_HOR", be_cconst_int(LV_CHART_DRAW_PART_DIV_LINE_HOR) }, - { "CHART_DRAW_PART_DIV_LINE_INIT", be_cconst_int(LV_CHART_DRAW_PART_DIV_LINE_INIT) }, - { "CHART_DRAW_PART_DIV_LINE_VER", be_cconst_int(LV_CHART_DRAW_PART_DIV_LINE_VER) }, - { "CHART_DRAW_PART_LINE_AND_POINT", be_cconst_int(LV_CHART_DRAW_PART_LINE_AND_POINT) }, - { "CHART_DRAW_PART_TICK_LABEL", be_cconst_int(LV_CHART_DRAW_PART_TICK_LABEL) }, { "CHART_POINT_NONE", be_cconst_int(LV_CHART_POINT_NONE) }, { "CHART_TYPE_BAR", be_cconst_int(LV_CHART_TYPE_BAR) }, { "CHART_TYPE_LINE", be_cconst_int(LV_CHART_TYPE_LINE) }, @@ -284,16 +298,40 @@ const be_const_member_t lv0_constants[] = { { "CHART_TYPE_SCATTER", be_cconst_int(LV_CHART_TYPE_SCATTER) }, { "CHART_UPDATE_MODE_CIRCULAR", be_cconst_int(LV_CHART_UPDATE_MODE_CIRCULAR) }, { "CHART_UPDATE_MODE_SHIFT", be_cconst_int(LV_CHART_UPDATE_MODE_SHIFT) }, - { "CHECKBOX_DRAW_PART_BOX", be_cconst_int(LV_CHECKBOX_DRAW_PART_BOX) }, - { "COLORWHEEL_MODE_HUE", be_cconst_int(LV_COLORWHEEL_MODE_HUE) }, - { "COLORWHEEL_MODE_SATURATION", be_cconst_int(LV_COLORWHEEL_MODE_SATURATION) }, - { "COLORWHEEL_MODE_VALUE", be_cconst_int(LV_COLORWHEEL_MODE_VALUE) }, - { "COLOR_16_SWAP", be_cconst_int(LV_COLOR_16_SWAP) }, { "COLOR_AQUA", be_cconst_int(0x00FFFF) }, { "COLOR_BLACK", be_cconst_int(0x000000) }, { "COLOR_BLUE", be_cconst_int(0x0000FF) }, { "COLOR_CYAN", be_cconst_int(0x00FFFF) }, { "COLOR_DEPTH", be_cconst_int(LV_COLOR_DEPTH) }, + { "COLOR_FORMAT_A1", be_cconst_int(LV_COLOR_FORMAT_A1) }, + { "COLOR_FORMAT_A2", be_cconst_int(LV_COLOR_FORMAT_A2) }, + { "COLOR_FORMAT_A4", be_cconst_int(LV_COLOR_FORMAT_A4) }, + { "COLOR_FORMAT_A8", be_cconst_int(LV_COLOR_FORMAT_A8) }, + { "COLOR_FORMAT_ARGB8888", be_cconst_int(LV_COLOR_FORMAT_ARGB8888) }, + { "COLOR_FORMAT_I1", be_cconst_int(LV_COLOR_FORMAT_I1) }, + { "COLOR_FORMAT_I2", be_cconst_int(LV_COLOR_FORMAT_I2) }, + { "COLOR_FORMAT_I4", be_cconst_int(LV_COLOR_FORMAT_I4) }, + { "COLOR_FORMAT_I400", be_cconst_int(LV_COLOR_FORMAT_I400) }, + { "COLOR_FORMAT_I420", be_cconst_int(LV_COLOR_FORMAT_I420) }, + { "COLOR_FORMAT_I422", be_cconst_int(LV_COLOR_FORMAT_I422) }, + { "COLOR_FORMAT_I444", be_cconst_int(LV_COLOR_FORMAT_I444) }, + { "COLOR_FORMAT_I8", be_cconst_int(LV_COLOR_FORMAT_I8) }, + { "COLOR_FORMAT_L8", be_cconst_int(LV_COLOR_FORMAT_L8) }, + { "COLOR_FORMAT_NATIVE", be_cconst_int(LV_COLOR_FORMAT_NATIVE) }, + { "COLOR_FORMAT_NATIVE_WITH_ALPHA", be_cconst_int(LV_COLOR_FORMAT_NATIVE_WITH_ALPHA) }, + { "COLOR_FORMAT_NV12", be_cconst_int(LV_COLOR_FORMAT_NV12) }, + { "COLOR_FORMAT_NV21", be_cconst_int(LV_COLOR_FORMAT_NV21) }, + { "COLOR_FORMAT_RAW", be_cconst_int(LV_COLOR_FORMAT_RAW) }, + { "COLOR_FORMAT_RAW_ALPHA", be_cconst_int(LV_COLOR_FORMAT_RAW_ALPHA) }, + { "COLOR_FORMAT_RGB565", be_cconst_int(LV_COLOR_FORMAT_RGB565) }, + { "COLOR_FORMAT_RGB565A8", be_cconst_int(LV_COLOR_FORMAT_RGB565A8) }, + { "COLOR_FORMAT_RGB888", be_cconst_int(LV_COLOR_FORMAT_RGB888) }, + { "COLOR_FORMAT_UNKNOWN", be_cconst_int(LV_COLOR_FORMAT_UNKNOWN) }, + { "COLOR_FORMAT_UYVY", be_cconst_int(LV_COLOR_FORMAT_UYVY) }, + { "COLOR_FORMAT_XRGB8888", be_cconst_int(LV_COLOR_FORMAT_XRGB8888) }, + { "COLOR_FORMAT_YUV_END", be_cconst_int(LV_COLOR_FORMAT_YUV_END) }, + { "COLOR_FORMAT_YUV_START", be_cconst_int(LV_COLOR_FORMAT_YUV_START) }, + { "COLOR_FORMAT_YUY2", be_cconst_int(LV_COLOR_FORMAT_YUY2) }, { "COLOR_GRAY", be_cconst_int(0x808080) }, { "COLOR_GREEN", be_cconst_int(0x008000) }, { "COLOR_LIME", be_cconst_int(0x00FF00) }, @@ -321,30 +359,40 @@ const be_const_member_t lv0_constants[] = { { "DIR_RIGHT", be_cconst_int(LV_DIR_RIGHT) }, { "DIR_TOP", be_cconst_int(LV_DIR_TOP) }, { "DIR_VER", be_cconst_int(LV_DIR_VER) }, - { "DISP_ROT_180", be_cconst_int(LV_DISP_ROT_180) }, - { "DISP_ROT_270", be_cconst_int(LV_DISP_ROT_270) }, - { "DISP_ROT_90", be_cconst_int(LV_DISP_ROT_90) }, - { "DISP_ROT_NONE", be_cconst_int(LV_DISP_ROT_NONE) }, - { "DITHER_ERR_DIFF", be_cconst_int(LV_DITHER_ERR_DIFF) }, - { "DITHER_NONE", be_cconst_int(LV_DITHER_NONE) }, - { "DITHER_ORDERED", be_cconst_int(LV_DITHER_ORDERED) }, - { "DRAW_LAYER_FLAG_CAN_SUBDIVIDE", be_cconst_int(LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) }, - { "DRAW_LAYER_FLAG_HAS_ALPHA", be_cconst_int(LV_DRAW_LAYER_FLAG_HAS_ALPHA) }, - { "DRAW_LAYER_FLAG_NONE", be_cconst_int(LV_DRAW_LAYER_FLAG_NONE) }, - { "DRAW_MASK_LINE_SIDE_BOTTOM", be_cconst_int(LV_DRAW_MASK_LINE_SIDE_BOTTOM) }, - { "DRAW_MASK_LINE_SIDE_LEFT", be_cconst_int(LV_DRAW_MASK_LINE_SIDE_LEFT) }, - { "DRAW_MASK_LINE_SIDE_RIGHT", be_cconst_int(LV_DRAW_MASK_LINE_SIDE_RIGHT) }, - { "DRAW_MASK_LINE_SIDE_TOP", be_cconst_int(LV_DRAW_MASK_LINE_SIDE_TOP) }, - { "DRAW_MASK_RES_CHANGED", be_cconst_int(LV_DRAW_MASK_RES_CHANGED) }, - { "DRAW_MASK_RES_FULL_COVER", be_cconst_int(LV_DRAW_MASK_RES_FULL_COVER) }, - { "DRAW_MASK_RES_TRANSP", be_cconst_int(LV_DRAW_MASK_RES_TRANSP) }, - { "DRAW_MASK_RES_UNKNOWN", be_cconst_int(LV_DRAW_MASK_RES_UNKNOWN) }, - { "DRAW_MASK_TYPE_ANGLE", be_cconst_int(LV_DRAW_MASK_TYPE_ANGLE) }, - { "DRAW_MASK_TYPE_FADE", be_cconst_int(LV_DRAW_MASK_TYPE_FADE) }, - { "DRAW_MASK_TYPE_LINE", be_cconst_int(LV_DRAW_MASK_TYPE_LINE) }, - { "DRAW_MASK_TYPE_MAP", be_cconst_int(LV_DRAW_MASK_TYPE_MAP) }, - { "DRAW_MASK_TYPE_POLYGON", be_cconst_int(LV_DRAW_MASK_TYPE_POLYGON) }, - { "DRAW_MASK_TYPE_RADIUS", be_cconst_int(LV_DRAW_MASK_TYPE_RADIUS) }, + { "DISPLAY_RENDER_MODE_DIRECT", be_cconst_int(LV_DISPLAY_RENDER_MODE_DIRECT) }, + { "DISPLAY_RENDER_MODE_FULL", be_cconst_int(LV_DISPLAY_RENDER_MODE_FULL) }, + { "DISPLAY_RENDER_MODE_PARTIAL", be_cconst_int(LV_DISPLAY_RENDER_MODE_PARTIAL) }, + { "DISPLAY_ROTATION_0", be_cconst_int(LV_DISPLAY_ROTATION_0) }, + { "DISPLAY_ROTATION_180", be_cconst_int(LV_DISPLAY_ROTATION_180) }, + { "DISPLAY_ROTATION_270", be_cconst_int(LV_DISPLAY_ROTATION_270) }, + { "DISPLAY_ROTATION_90", be_cconst_int(LV_DISPLAY_ROTATION_90) }, + { "DISP_RENDER_MODE_DIRECT", be_cconst_int(LV_DISPLAY_RENDER_MODE_DIRECT) }, + { "DISP_RENDER_MODE_FULL", be_cconst_int(LV_DISPLAY_RENDER_MODE_FULL) }, + { "DISP_RENDER_MODE_PARTIAL", be_cconst_int(LV_DISPLAY_RENDER_MODE_PARTIAL) }, + { "DISP_ROTATION_0", be_cconst_int(LV_DISPLAY_ROTATION_0) }, + { "DISP_ROTATION_180", be_cconst_int(LV_DISPLAY_ROTATION_180) }, + { "DISP_ROTATION_270", be_cconst_int(LV_DISPLAY_ROTATION_270) }, + { "DISP_ROTATION_90", be_cconst_int(LV_DISPLAY_ROTATION_90) }, + { "DRAW_LETTER_BITMAP_FORMAT_A8", be_cconst_int(LV_DRAW_LETTER_BITMAP_FORMAT_A8) }, + { "DRAW_LETTER_BITMAP_FORMAT_IMAGE", be_cconst_int(LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE) }, + { "DRAW_LETTER_BITMAP_FORMAT_INVALID", be_cconst_int(LV_DRAW_LETTER_BITMAP_FORMAT_INVALID) }, + { "DRAW_LETTER_VECTOR_FORMAT", be_cconst_int(LV_DRAW_LETTER_VECTOR_FORMAT) }, + { "DRAW_TASK_STATE_IN_PROGRESS", be_cconst_int(LV_DRAW_TASK_STATE_IN_PROGRESS) }, + { "DRAW_TASK_STATE_QUEUED", be_cconst_int(LV_DRAW_TASK_STATE_QUEUED) }, + { "DRAW_TASK_STATE_READY", be_cconst_int(LV_DRAW_TASK_STATE_READY) }, + { "DRAW_TASK_STATE_WAITING", be_cconst_int(LV_DRAW_TASK_STATE_WAITING) }, + { "DRAW_TASK_TYPE_ARC", be_cconst_int(LV_DRAW_TASK_TYPE_ARC) }, + { "DRAW_TASK_TYPE_BORDER", be_cconst_int(LV_DRAW_TASK_TYPE_BORDER) }, + { "DRAW_TASK_TYPE_BOX_SHADOW", be_cconst_int(LV_DRAW_TASK_TYPE_BOX_SHADOW) }, + { "DRAW_TASK_TYPE_FILL", be_cconst_int(LV_DRAW_TASK_TYPE_FILL) }, + { "DRAW_TASK_TYPE_IMAGE", be_cconst_int(LV_DRAW_TASK_TYPE_IMAGE) }, + { "DRAW_TASK_TYPE_LABEL", be_cconst_int(LV_DRAW_TASK_TYPE_LABEL) }, + { "DRAW_TASK_TYPE_LAYER", be_cconst_int(LV_DRAW_TASK_TYPE_LAYER) }, + { "DRAW_TASK_TYPE_LINE", be_cconst_int(LV_DRAW_TASK_TYPE_LINE) }, + { "DRAW_TASK_TYPE_MASK_BITMAP", be_cconst_int(LV_DRAW_TASK_TYPE_MASK_BITMAP) }, + { "DRAW_TASK_TYPE_MASK_RECTANGLE", be_cconst_int(LV_DRAW_TASK_TYPE_MASK_RECTANGLE) }, + { "DRAW_TASK_TYPE_TRIANGLE", be_cconst_int(LV_DRAW_TASK_TYPE_TRIANGLE) }, + { "DRAW_TASK_TYPE_VECTOR", be_cconst_int(LV_DRAW_TASK_TYPE_VECTOR) }, { "DROPDOWN_POS_LAST", be_cconst_int(LV_DROPDOWN_POS_LAST) }, { "EVENT_ALL", be_cconst_int(LV_EVENT_ALL) }, { "EVENT_CANCEL", be_cconst_int(LV_EVENT_CANCEL) }, @@ -352,22 +400,27 @@ const be_const_member_t lv0_constants[] = { { "EVENT_CHILD_CREATED", be_cconst_int(LV_EVENT_CHILD_CREATED) }, { "EVENT_CHILD_DELETED", be_cconst_int(LV_EVENT_CHILD_DELETED) }, { "EVENT_CLICKED", be_cconst_int(LV_EVENT_CLICKED) }, + { "EVENT_COLOR_FORMAT_CHANGED", be_cconst_int(LV_EVENT_COLOR_FORMAT_CHANGED) }, { "EVENT_COVER_CHECK", be_cconst_int(LV_EVENT_COVER_CHECK) }, + { "EVENT_CREATE", be_cconst_int(LV_EVENT_CREATE) }, { "EVENT_DEFOCUSED", be_cconst_int(LV_EVENT_DEFOCUSED) }, { "EVENT_DELETE", be_cconst_int(LV_EVENT_DELETE) }, { "EVENT_DRAW_MAIN", be_cconst_int(LV_EVENT_DRAW_MAIN) }, { "EVENT_DRAW_MAIN_BEGIN", be_cconst_int(LV_EVENT_DRAW_MAIN_BEGIN) }, { "EVENT_DRAW_MAIN_END", be_cconst_int(LV_EVENT_DRAW_MAIN_END) }, - { "EVENT_DRAW_PART_BEGIN", be_cconst_int(LV_EVENT_DRAW_PART_BEGIN) }, - { "EVENT_DRAW_PART_END", be_cconst_int(LV_EVENT_DRAW_PART_END) }, { "EVENT_DRAW_POST", be_cconst_int(LV_EVENT_DRAW_POST) }, { "EVENT_DRAW_POST_BEGIN", be_cconst_int(LV_EVENT_DRAW_POST_BEGIN) }, { "EVENT_DRAW_POST_END", be_cconst_int(LV_EVENT_DRAW_POST_END) }, + { "EVENT_DRAW_TASK_ADDED", be_cconst_int(LV_EVENT_DRAW_TASK_ADDED) }, + { "EVENT_FLUSH_FINISH", be_cconst_int(LV_EVENT_FLUSH_FINISH) }, + { "EVENT_FLUSH_START", be_cconst_int(LV_EVENT_FLUSH_START) }, { "EVENT_FOCUSED", be_cconst_int(LV_EVENT_FOCUSED) }, { "EVENT_GESTURE", be_cconst_int(LV_EVENT_GESTURE) }, { "EVENT_GET_SELF_SIZE", be_cconst_int(LV_EVENT_GET_SELF_SIZE) }, { "EVENT_HIT_TEST", be_cconst_int(LV_EVENT_HIT_TEST) }, + { "EVENT_INDEV_RESET", be_cconst_int(LV_EVENT_INDEV_RESET) }, { "EVENT_INSERT", be_cconst_int(LV_EVENT_INSERT) }, + { "EVENT_INVALIDATE_AREA", be_cconst_int(LV_EVENT_INVALIDATE_AREA) }, { "EVENT_KEY", be_cconst_int(LV_EVENT_KEY) }, { "EVENT_LAYOUT_CHANGED", be_cconst_int(LV_EVENT_LAYOUT_CHANGED) }, { "EVENT_LEAVE", be_cconst_int(LV_EVENT_LEAVE) }, @@ -380,7 +433,13 @@ const be_const_member_t lv0_constants[] = { { "EVENT_READY", be_cconst_int(LV_EVENT_READY) }, { "EVENT_REFRESH", be_cconst_int(LV_EVENT_REFRESH) }, { "EVENT_REFR_EXT_DRAW_SIZE", be_cconst_int(LV_EVENT_REFR_EXT_DRAW_SIZE) }, + { "EVENT_REFR_READY", be_cconst_int(LV_EVENT_REFR_READY) }, + { "EVENT_REFR_REQUEST", be_cconst_int(LV_EVENT_REFR_REQUEST) }, + { "EVENT_REFR_START", be_cconst_int(LV_EVENT_REFR_START) }, { "EVENT_RELEASED", be_cconst_int(LV_EVENT_RELEASED) }, + { "EVENT_RENDER_READY", be_cconst_int(LV_EVENT_RENDER_READY) }, + { "EVENT_RENDER_START", be_cconst_int(LV_EVENT_RENDER_START) }, + { "EVENT_RESOLUTION_CHANGED", be_cconst_int(LV_EVENT_RESOLUTION_CHANGED) }, { "EVENT_SCREEN_LOADED", be_cconst_int(LV_EVENT_SCREEN_LOADED) }, { "EVENT_SCREEN_LOAD_START", be_cconst_int(LV_EVENT_SCREEN_LOAD_START) }, { "EVENT_SCREEN_UNLOADED", be_cconst_int(LV_EVENT_SCREEN_UNLOADED) }, @@ -388,24 +447,12 @@ const be_const_member_t lv0_constants[] = { { "EVENT_SCROLL", be_cconst_int(LV_EVENT_SCROLL) }, { "EVENT_SCROLL_BEGIN", be_cconst_int(LV_EVENT_SCROLL_BEGIN) }, { "EVENT_SCROLL_END", be_cconst_int(LV_EVENT_SCROLL_END) }, + { "EVENT_SCROLL_THROW_BEGIN", be_cconst_int(LV_EVENT_SCROLL_THROW_BEGIN) }, { "EVENT_SHORT_CLICKED", be_cconst_int(LV_EVENT_SHORT_CLICKED) }, { "EVENT_SIZE_CHANGED", be_cconst_int(LV_EVENT_SIZE_CHANGED) }, { "EVENT_STYLE_CHANGED", be_cconst_int(LV_EVENT_STYLE_CHANGED) }, { "EVENT_VALUE_CHANGED", be_cconst_int(LV_EVENT_VALUE_CHANGED) }, - { "FLEX_ALIGN_CENTER", be_cconst_int(LV_FLEX_ALIGN_CENTER) }, - { "FLEX_ALIGN_END", be_cconst_int(LV_FLEX_ALIGN_END) }, - { "FLEX_ALIGN_SPACE_AROUND", be_cconst_int(LV_FLEX_ALIGN_SPACE_AROUND) }, - { "FLEX_ALIGN_SPACE_BETWEEN", be_cconst_int(LV_FLEX_ALIGN_SPACE_BETWEEN) }, - { "FLEX_ALIGN_SPACE_EVENLY", be_cconst_int(LV_FLEX_ALIGN_SPACE_EVENLY) }, - { "FLEX_ALIGN_START", be_cconst_int(LV_FLEX_ALIGN_START) }, - { "FLEX_FLOW_COLUMN", be_cconst_int(LV_FLEX_FLOW_COLUMN) }, - { "FLEX_FLOW_COLUMN_REVERSE", be_cconst_int(LV_FLEX_FLOW_COLUMN_REVERSE) }, - { "FLEX_FLOW_COLUMN_WRAP", be_cconst_int(LV_FLEX_FLOW_COLUMN_WRAP) }, - { "FLEX_FLOW_COLUMN_WRAP_REVERSE", be_cconst_int(LV_FLEX_FLOW_COLUMN_WRAP_REVERSE) }, - { "FLEX_FLOW_ROW", be_cconst_int(LV_FLEX_FLOW_ROW) }, - { "FLEX_FLOW_ROW_REVERSE", be_cconst_int(LV_FLEX_FLOW_ROW_REVERSE) }, - { "FLEX_FLOW_ROW_WRAP", be_cconst_int(LV_FLEX_FLOW_ROW_WRAP) }, - { "FLEX_FLOW_ROW_WRAP_REVERSE", be_cconst_int(LV_FLEX_FLOW_ROW_WRAP_REVERSE) }, + { "EVENT_VSYNC", be_cconst_int(LV_EVENT_VSYNC) }, { "FS_MODE_RD", be_cconst_int(LV_FS_MODE_RD) }, { "FS_MODE_WR", be_cconst_int(LV_FS_MODE_WR) }, { "FS_RES_BUSY", be_cconst_int(LV_FS_RES_BUSY) }, @@ -430,59 +477,49 @@ const be_const_member_t lv0_constants[] = { { "GRAD_DIR_HOR", be_cconst_int(LV_GRAD_DIR_HOR) }, { "GRAD_DIR_NONE", be_cconst_int(LV_GRAD_DIR_NONE) }, { "GRAD_DIR_VER", be_cconst_int(LV_GRAD_DIR_VER) }, - { "GRID_ALIGN_CENTER", be_cconst_int(LV_GRID_ALIGN_CENTER) }, - { "GRID_ALIGN_END", be_cconst_int(LV_GRID_ALIGN_END) }, - { "GRID_ALIGN_SPACE_AROUND", be_cconst_int(LV_GRID_ALIGN_SPACE_AROUND) }, - { "GRID_ALIGN_SPACE_BETWEEN", be_cconst_int(LV_GRID_ALIGN_SPACE_BETWEEN) }, - { "GRID_ALIGN_SPACE_EVENLY", be_cconst_int(LV_GRID_ALIGN_SPACE_EVENLY) }, - { "GRID_ALIGN_START", be_cconst_int(LV_GRID_ALIGN_START) }, - { "GRID_ALIGN_STRETCH", be_cconst_int(LV_GRID_ALIGN_STRETCH) }, - { "GRID_CONTENT", be_cconst_int(LV_GRID_CONTENT) }, { "GRID_FR", be_cconst_int(LV_GRID_FR(0)) }, - { "GRID_TEMPLATE_LAST", be_cconst_int(LV_GRID_TEMPLATE_LAST) }, { "GROUP_REFOCUS_POLICY_NEXT", be_cconst_int(LV_GROUP_REFOCUS_POLICY_NEXT) }, { "GROUP_REFOCUS_POLICY_PREV", be_cconst_int(LV_GROUP_REFOCUS_POLICY_PREV) }, - { "IMGBTN_STATE_CHECKED_DISABLED", be_cconst_int(LV_IMGBTN_STATE_CHECKED_DISABLED) }, - { "IMGBTN_STATE_CHECKED_PRESSED", be_cconst_int(LV_IMGBTN_STATE_CHECKED_PRESSED) }, - { "IMGBTN_STATE_CHECKED_RELEASED", be_cconst_int(LV_IMGBTN_STATE_CHECKED_RELEASED) }, - { "IMGBTN_STATE_DISABLED", be_cconst_int(LV_IMGBTN_STATE_DISABLED) }, - { "IMGBTN_STATE_PRESSED", be_cconst_int(LV_IMGBTN_STATE_PRESSED) }, - { "IMGBTN_STATE_RELEASED", be_cconst_int(LV_IMGBTN_STATE_RELEASED) }, - { "IMG_CF_ALPHA_1BIT", be_cconst_int(LV_IMG_CF_ALPHA_1BIT) }, - { "IMG_CF_ALPHA_2BIT", be_cconst_int(LV_IMG_CF_ALPHA_2BIT) }, - { "IMG_CF_ALPHA_4BIT", be_cconst_int(LV_IMG_CF_ALPHA_4BIT) }, - { "IMG_CF_ALPHA_8BIT", be_cconst_int(LV_IMG_CF_ALPHA_8BIT) }, - { "IMG_CF_INDEXED_1BIT", be_cconst_int(LV_IMG_CF_INDEXED_1BIT) }, - { "IMG_CF_INDEXED_2BIT", be_cconst_int(LV_IMG_CF_INDEXED_2BIT) }, - { "IMG_CF_INDEXED_4BIT", be_cconst_int(LV_IMG_CF_INDEXED_4BIT) }, - { "IMG_CF_INDEXED_8BIT", be_cconst_int(LV_IMG_CF_INDEXED_8BIT) }, - { "IMG_CF_RAW", be_cconst_int(LV_IMG_CF_RAW) }, - { "IMG_CF_RAW_ALPHA", be_cconst_int(LV_IMG_CF_RAW_ALPHA) }, - { "IMG_CF_RAW_CHROMA_KEYED", be_cconst_int(LV_IMG_CF_RAW_CHROMA_KEYED) }, - { "IMG_CF_RGB565", be_cconst_int(LV_IMG_CF_RGB565) }, - { "IMG_CF_RGB565A8", be_cconst_int(LV_IMG_CF_RGB565A8) }, - { "IMG_CF_RGB888", be_cconst_int(LV_IMG_CF_RGB888) }, - { "IMG_CF_RGBA5658", be_cconst_int(LV_IMG_CF_RGBA5658) }, - { "IMG_CF_RGBA8888", be_cconst_int(LV_IMG_CF_RGBA8888) }, - { "IMG_CF_RGBX8888", be_cconst_int(LV_IMG_CF_RGBX8888) }, - { "IMG_CF_TRUE_COLOR", be_cconst_int(LV_IMG_CF_TRUE_COLOR) }, - { "IMG_CF_TRUE_COLOR_ALPHA", be_cconst_int(LV_IMG_CF_TRUE_COLOR_ALPHA) }, - { "IMG_CF_TRUE_COLOR_CHROMA_KEYED", be_cconst_int(LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) }, - { "IMG_CF_UNKNOWN", be_cconst_int(LV_IMG_CF_UNKNOWN) }, - { "IMG_SIZE_MODE_REAL", be_cconst_int(LV_IMG_SIZE_MODE_REAL) }, - { "IMG_SIZE_MODE_VIRTUAL", be_cconst_int(LV_IMG_SIZE_MODE_VIRTUAL) }, - { "IMG_SRC_FILE", be_cconst_int(LV_IMG_SRC_FILE) }, - { "IMG_SRC_SYMBOL", be_cconst_int(LV_IMG_SRC_SYMBOL) }, - { "IMG_SRC_UNKNOWN", be_cconst_int(LV_IMG_SRC_UNKNOWN) }, - { "IMG_SRC_VARIABLE", be_cconst_int(LV_IMG_SRC_VARIABLE) }, - { "IMG_ZOOM_NONE", be_cconst_int(LV_IMG_ZOOM_NONE) }, - { "INDEV_STATE_PRESSED", be_cconst_int(LV_INDEV_STATE_PRESSED) }, - { "INDEV_STATE_RELEASED", be_cconst_int(LV_INDEV_STATE_RELEASED) }, - { "INDEV_TYPE_BUTTON", be_cconst_int(LV_INDEV_TYPE_BUTTON) }, - { "INDEV_TYPE_ENCODER", be_cconst_int(LV_INDEV_TYPE_ENCODER) }, - { "INDEV_TYPE_KEYPAD", be_cconst_int(LV_INDEV_TYPE_KEYPAD) }, - { "INDEV_TYPE_NONE", be_cconst_int(LV_INDEV_TYPE_NONE) }, - { "INDEV_TYPE_POINTER", be_cconst_int(LV_INDEV_TYPE_POINTER) }, + { "IMAGEBUTTON_STATE_CHECKED_DISABLED", be_cconst_int(LV_IMAGEBUTTON_STATE_CHECKED_DISABLED) }, + { "IMAGEBUTTON_STATE_CHECKED_PRESSED", be_cconst_int(LV_IMAGEBUTTON_STATE_CHECKED_PRESSED) }, + { "IMAGEBUTTON_STATE_CHECKED_RELEASED", be_cconst_int(LV_IMAGEBUTTON_STATE_CHECKED_RELEASED) }, + { "IMAGEBUTTON_STATE_DISABLED", be_cconst_int(LV_IMAGEBUTTON_STATE_DISABLED) }, + { "IMAGEBUTTON_STATE_PRESSED", be_cconst_int(LV_IMAGEBUTTON_STATE_PRESSED) }, + { "IMAGEBUTTON_STATE_RELEASED", be_cconst_int(LV_IMAGEBUTTON_STATE_RELEASED) }, + { "IMAGE_ALIGN_BOTTOM_LEFT", be_cconst_int(LV_IMAGE_ALIGN_BOTTOM_LEFT) }, + { "IMAGE_ALIGN_BOTTOM_MID", be_cconst_int(LV_IMAGE_ALIGN_BOTTOM_MID) }, + { "IMAGE_ALIGN_BOTTOM_RIGHT", be_cconst_int(LV_IMAGE_ALIGN_BOTTOM_RIGHT) }, + { "IMAGE_ALIGN_CENTER", be_cconst_int(LV_IMAGE_ALIGN_CENTER) }, + { "IMAGE_ALIGN_DEFAULT", be_cconst_int(LV_IMAGE_ALIGN_DEFAULT) }, + { "IMAGE_ALIGN_LEFT_MID", be_cconst_int(LV_IMAGE_ALIGN_LEFT_MID) }, + { "IMAGE_ALIGN_RIGHT_MID", be_cconst_int(LV_IMAGE_ALIGN_RIGHT_MID) }, + { "IMAGE_ALIGN_STRETCH", be_cconst_int(LV_IMAGE_ALIGN_STRETCH) }, + { "IMAGE_ALIGN_TILE", be_cconst_int(LV_IMAGE_ALIGN_TILE) }, + { "IMAGE_ALIGN_TOP_LEFT", be_cconst_int(LV_IMAGE_ALIGN_TOP_LEFT) }, + { "IMAGE_ALIGN_TOP_MID", be_cconst_int(LV_IMAGE_ALIGN_TOP_MID) }, + { "IMAGE_ALIGN_TOP_RIGHT", be_cconst_int(LV_IMAGE_ALIGN_TOP_RIGHT) }, + { "IMAGE_COMPRESS_LZ4", be_cconst_int(LV_IMAGE_COMPRESS_LZ4) }, + { "IMAGE_COMPRESS_NONE", be_cconst_int(LV_IMAGE_COMPRESS_NONE) }, + { "IMAGE_COMPRESS_RLE", be_cconst_int(LV_IMAGE_COMPRESS_RLE) }, + { "IMAGE_FLAGS_ALLOCATED", be_cconst_int(LV_IMAGE_FLAGS_ALLOCATED) }, + { "IMAGE_FLAGS_COMPRESSED", be_cconst_int(LV_IMAGE_FLAGS_COMPRESSED) }, + { "IMAGE_FLAGS_MODIFIABLE", be_cconst_int(LV_IMAGE_FLAGS_MODIFIABLE) }, + { "IMAGE_FLAGS_PREMULTIPLIED", be_cconst_int(LV_IMAGE_FLAGS_PREMULTIPLIED) }, + { "IMAGE_FLAGS_USER1", be_cconst_int(LV_IMAGE_FLAGS_USER1) }, + { "IMAGE_FLAGS_USER2", be_cconst_int(LV_IMAGE_FLAGS_USER2) }, + { "IMAGE_FLAGS_USER3", be_cconst_int(LV_IMAGE_FLAGS_USER3) }, + { "IMAGE_FLAGS_USER4", be_cconst_int(LV_IMAGE_FLAGS_USER4) }, + { "IMAGE_FLAGS_USER5", be_cconst_int(LV_IMAGE_FLAGS_USER5) }, + { "IMAGE_FLAGS_USER6", be_cconst_int(LV_IMAGE_FLAGS_USER6) }, + { "IMAGE_FLAGS_USER7", be_cconst_int(LV_IMAGE_FLAGS_USER7) }, + { "IMAGE_FLAGS_USER8", be_cconst_int(LV_IMAGE_FLAGS_USER8) }, + { "IMAGE_FLAGS_VECTORS", be_cconst_int(LV_IMAGE_FLAGS_VECTORS) }, + { "IMAGE_SRC_FILE", be_cconst_int(LV_IMAGE_SRC_FILE) }, + { "IMAGE_SRC_SYMBOL", be_cconst_int(LV_IMAGE_SRC_SYMBOL) }, + { "IMAGE_SRC_UNKNOWN", be_cconst_int(LV_IMAGE_SRC_UNKNOWN) }, + { "IMAGE_SRC_VARIABLE", be_cconst_int(LV_IMAGE_SRC_VARIABLE) }, + { "INDEV_STATE_PR", be_cconst_int(LV_INDEV_STATE_PRESSED) }, + { "INDEV_STATE_REL", be_cconst_int(LV_INDEV_STATE_RELEASED) }, { "KEYBOARD_MODE_NUMBER", be_cconst_int(LV_KEYBOARD_MODE_NUMBER) }, { "KEYBOARD_MODE_SPECIAL", be_cconst_int(LV_KEYBOARD_MODE_SPECIAL) }, { "KEYBOARD_MODE_TEXT_LOWER", be_cconst_int(LV_KEYBOARD_MODE_TEXT_LOWER) }, @@ -516,7 +553,6 @@ const be_const_member_t lv0_constants[] = { { "LAYER_TYPE_TRANSFORM", be_cconst_int(LV_LAYER_TYPE_TRANSFORM) }, { ">LAYOUT_FLEX", be_ctype(be_LV_LAYOUT_FLEX) }, { ">LAYOUT_GRID", be_ctype(be_LV_LAYOUT_GRID) }, - { "LED_DRAW_PART_RECTANGLE", be_cconst_int(LV_LED_DRAW_PART_RECTANGLE) }, { "LOG_LEVEL_ERROR", be_cconst_int(LV_LOG_LEVEL_ERROR) }, { "LOG_LEVEL_INFO", be_cconst_int(LV_LOG_LEVEL_INFO) }, { "LOG_LEVEL_NONE", be_cconst_int(LV_LOG_LEVEL_NONE) }, @@ -526,25 +562,16 @@ const be_const_member_t lv0_constants[] = { { "MENU_HEADER_BOTTOM_FIXED", be_cconst_int(LV_MENU_HEADER_BOTTOM_FIXED) }, { "MENU_HEADER_TOP_FIXED", be_cconst_int(LV_MENU_HEADER_TOP_FIXED) }, { "MENU_HEADER_TOP_UNFIXED", be_cconst_int(LV_MENU_HEADER_TOP_UNFIXED) }, - { "MENU_ROOT_BACK_BTN_DISABLED", be_cconst_int(LV_MENU_ROOT_BACK_BTN_DISABLED) }, - { "MENU_ROOT_BACK_BTN_ENABLED", be_cconst_int(LV_MENU_ROOT_BACK_BTN_ENABLED) }, - { "METER_DRAW_PART_ARC", be_cconst_int(LV_METER_DRAW_PART_ARC) }, - { "METER_DRAW_PART_NEEDLE_IMG", be_cconst_int(LV_METER_DRAW_PART_NEEDLE_IMG) }, - { "METER_DRAW_PART_NEEDLE_LINE", be_cconst_int(LV_METER_DRAW_PART_NEEDLE_LINE) }, - { "METER_DRAW_PART_TICK", be_cconst_int(LV_METER_DRAW_PART_TICK) }, - { "METER_INDICATOR_TYPE_ARC", be_cconst_int(LV_METER_INDICATOR_TYPE_ARC) }, - { "METER_INDICATOR_TYPE_NEEDLE_IMG", be_cconst_int(LV_METER_INDICATOR_TYPE_NEEDLE_IMG) }, - { "METER_INDICATOR_TYPE_NEEDLE_LINE", be_cconst_int(LV_METER_INDICATOR_TYPE_NEEDLE_LINE) }, - { "METER_INDICATOR_TYPE_SCALE_LINES", be_cconst_int(LV_METER_INDICATOR_TYPE_SCALE_LINES) }, + { "MENU_ROOT_BACK_BUTTON_DISABLED", be_cconst_int(LV_MENU_ROOT_BACK_BUTTON_DISABLED) }, + { "MENU_ROOT_BACK_BUTTON_ENABLED", be_cconst_int(LV_MENU_ROOT_BACK_BUTTON_ENABLED) }, { "OBJ_CLASS_EDITABLE_FALSE", be_cconst_int(LV_OBJ_CLASS_EDITABLE_FALSE) }, { "OBJ_CLASS_EDITABLE_INHERIT", be_cconst_int(LV_OBJ_CLASS_EDITABLE_INHERIT) }, { "OBJ_CLASS_EDITABLE_TRUE", be_cconst_int(LV_OBJ_CLASS_EDITABLE_TRUE) }, { "OBJ_CLASS_GROUP_DEF_FALSE", be_cconst_int(LV_OBJ_CLASS_GROUP_DEF_FALSE) }, { "OBJ_CLASS_GROUP_DEF_INHERIT", be_cconst_int(LV_OBJ_CLASS_GROUP_DEF_INHERIT) }, { "OBJ_CLASS_GROUP_DEF_TRUE", be_cconst_int(LV_OBJ_CLASS_GROUP_DEF_TRUE) }, - { "OBJ_DRAW_PART_BORDER_POST", be_cconst_int(LV_OBJ_DRAW_PART_BORDER_POST) }, - { "OBJ_DRAW_PART_RECTANGLE", be_cconst_int(LV_OBJ_DRAW_PART_RECTANGLE) }, - { "OBJ_DRAW_PART_SCROLLBAR", be_cconst_int(LV_OBJ_DRAW_PART_SCROLLBAR) }, + { "OBJ_CLASS_THEME_INHERITABLE_FALSE", be_cconst_int(LV_OBJ_CLASS_THEME_INHERITABLE_FALSE) }, + { "OBJ_CLASS_THEME_INHERITABLE_TRUE", be_cconst_int(LV_OBJ_CLASS_THEME_INHERITABLE_TRUE) }, { "OBJ_FLAG_ADV_HITTEST", be_cconst_int(LV_OBJ_FLAG_ADV_HITTEST) }, { "OBJ_FLAG_CHECKABLE", be_cconst_int(LV_OBJ_FLAG_CHECKABLE) }, { "OBJ_FLAG_CLICKABLE", be_cconst_int(LV_OBJ_FLAG_CLICKABLE) }, @@ -568,6 +595,7 @@ const be_const_member_t lv0_constants[] = { { "OBJ_FLAG_SCROLL_ONE", be_cconst_int(LV_OBJ_FLAG_SCROLL_ONE) }, { "OBJ_FLAG_SCROLL_ON_FOCUS", be_cconst_int(LV_OBJ_FLAG_SCROLL_ON_FOCUS) }, { "OBJ_FLAG_SCROLL_WITH_ARROW", be_cconst_int(LV_OBJ_FLAG_SCROLL_WITH_ARROW) }, + { "OBJ_FLAG_SEND_DRAW_TASK_EVENTS", be_cconst_int(LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS) }, { "OBJ_FLAG_SNAPPABLE", be_cconst_int(LV_OBJ_FLAG_SNAPPABLE) }, { "OBJ_FLAG_USER_1", be_cconst_int(LV_OBJ_FLAG_USER_1) }, { "OBJ_FLAG_USER_2", be_cconst_int(LV_OBJ_FLAG_USER_2) }, @@ -621,12 +649,25 @@ const be_const_member_t lv0_constants[] = { { "PART_SCROLLBAR", be_cconst_int(LV_PART_SCROLLBAR) }, { "PART_SELECTED", be_cconst_int(LV_PART_SELECTED) }, { "PART_TEXTAREA_PLACEHOLDER", be_cconst_int(LV_PART_TEXTAREA_PLACEHOLDER) }, - { "PART_TICKS", be_cconst_int(LV_PART_TICKS) }, { "RADIUS_CIRCLE", be_cconst_int(LV_RADIUS_CIRCLE) }, - { "RES_INV", be_cconst_int(LV_RES_INV) }, - { "RES_OK", be_cconst_int(LV_RES_OK) }, + { "RB_COLOR_BLACK", be_cconst_int(LV_RB_COLOR_BLACK) }, + { "RB_COLOR_RED", be_cconst_int(LV_RB_COLOR_RED) }, + { "RESULT_INVALID", be_cconst_int(LV_RESULT_INVALID) }, + { "RESULT_OK", be_cconst_int(LV_RESULT_OK) }, + { "RES_INV", be_cconst_int(LV_RESULT_INVALID) }, + { "RES_OK", be_cconst_int(LV_RESULT_OK) }, { "ROLLER_MODE_INFINITE", be_cconst_int(LV_ROLLER_MODE_INFINITE) }, { "ROLLER_MODE_NORMAL", be_cconst_int(LV_ROLLER_MODE_NORMAL) }, + { "SCALE_LABEL_ENABLED_DEFAULT", be_cconst_int(LV_SCALE_LABEL_ENABLED_DEFAULT) }, + { "SCALE_MAJOR_TICK_EVERY_DEFAULT", be_cconst_int(LV_SCALE_MAJOR_TICK_EVERY_DEFAULT) }, + { "SCALE_MODE_HORIZONTAL_BOTTOM", be_cconst_int(LV_SCALE_MODE_HORIZONTAL_BOTTOM) }, + { "SCALE_MODE_HORIZONTAL_TOP", be_cconst_int(LV_SCALE_MODE_HORIZONTAL_TOP) }, + { "SCALE_MODE_ROUND_INNER", be_cconst_int(LV_SCALE_MODE_ROUND_INNER) }, + { "SCALE_MODE_ROUND_OUTER", be_cconst_int(LV_SCALE_MODE_ROUND_OUTER) }, + { "SCALE_MODE_VERTICAL_LEFT", be_cconst_int(LV_SCALE_MODE_VERTICAL_LEFT) }, + { "SCALE_MODE_VERTICAL_RIGHT", be_cconst_int(LV_SCALE_MODE_VERTICAL_RIGHT) }, + { "SCALE_NONE", be_cconst_int(LV_SCALE_NONE) }, + { "SCALE_TOTAL_TICK_COUNT_DEFAULT", be_cconst_int(LV_SCALE_TOTAL_TICK_COUNT_DEFAULT) }, { "SCROLLBAR_MODE_ACTIVE", be_cconst_int(LV_SCROLLBAR_MODE_ACTIVE) }, { "SCROLLBAR_MODE_AUTO", be_cconst_int(LV_SCROLLBAR_MODE_AUTO) }, { "SCROLLBAR_MODE_OFF", be_cconst_int(LV_SCROLLBAR_MODE_OFF) }, @@ -652,8 +693,6 @@ const be_const_member_t lv0_constants[] = { { "SCR_LOAD_ANIM_OVER_RIGHT", be_cconst_int(LV_SCR_LOAD_ANIM_OVER_RIGHT) }, { "SCR_LOAD_ANIM_OVER_TOP", be_cconst_int(LV_SCR_LOAD_ANIM_OVER_TOP) }, { "SIZE_CONTENT", be_cconst_int(LV_SIZE_CONTENT) }, - { "SLIDER_DRAW_PART_KNOB", be_cconst_int(LV_SLIDER_DRAW_PART_KNOB) }, - { "SLIDER_DRAW_PART_KNOB_LEFT", be_cconst_int(LV_SLIDER_DRAW_PART_KNOB_LEFT) }, { "SLIDER_MODE_NORMAL", be_cconst_int(LV_SLIDER_MODE_NORMAL) }, { "SLIDER_MODE_RANGE", be_cconst_int(LV_SLIDER_MODE_RANGE) }, { "SLIDER_MODE_SYMMETRICAL", be_cconst_int(LV_SLIDER_MODE_SYMMETRICAL) }, @@ -676,27 +715,29 @@ const be_const_member_t lv0_constants[] = { { "STATE_USER_2", be_cconst_int(LV_STATE_USER_2) }, { "STATE_USER_3", be_cconst_int(LV_STATE_USER_3) }, { "STATE_USER_4", be_cconst_int(LV_STATE_USER_4) }, + { "STRIDE_AUTO", be_cconst_int(LV_STRIDE_AUTO) }, { "STYLE_ALIGN", be_cconst_int(LV_STYLE_ALIGN) }, { "STYLE_ANIM", be_cconst_int(LV_STYLE_ANIM) }, - { "STYLE_ANIM_SPEED", be_cconst_int(LV_STYLE_ANIM_SPEED) }, - { "STYLE_ANIM_TIME", be_cconst_int(LV_STYLE_ANIM_TIME) }, + { "STYLE_ANIM_DURATION", be_cconst_int(LV_STYLE_ANIM_DURATION) }, + { "STYLE_ANIM_TIME", be_cconst_int(LV_STYLE_ANIM_DURATION) }, { "STYLE_ARC_COLOR", be_cconst_int(LV_STYLE_ARC_COLOR) }, - { "STYLE_ARC_IMG_SRC", be_cconst_int(LV_STYLE_ARC_IMG_SRC) }, + { "STYLE_ARC_IMAGE_SRC", be_cconst_int(LV_STYLE_ARC_IMAGE_SRC) }, { "STYLE_ARC_OPA", be_cconst_int(LV_STYLE_ARC_OPA) }, { "STYLE_ARC_ROUNDED", be_cconst_int(LV_STYLE_ARC_ROUNDED) }, { "STYLE_ARC_WIDTH", be_cconst_int(LV_STYLE_ARC_WIDTH) }, { "STYLE_BASE_DIR", be_cconst_int(LV_STYLE_BASE_DIR) }, { "STYLE_BG_COLOR", be_cconst_int(LV_STYLE_BG_COLOR) }, - { "STYLE_BG_DITHER_MODE", be_cconst_int(LV_STYLE_BG_DITHER_MODE) }, { "STYLE_BG_GRAD", be_cconst_int(LV_STYLE_BG_GRAD) }, { "STYLE_BG_GRAD_COLOR", be_cconst_int(LV_STYLE_BG_GRAD_COLOR) }, { "STYLE_BG_GRAD_DIR", be_cconst_int(LV_STYLE_BG_GRAD_DIR) }, + { "STYLE_BG_GRAD_OPA", be_cconst_int(LV_STYLE_BG_GRAD_OPA) }, { "STYLE_BG_GRAD_STOP", be_cconst_int(LV_STYLE_BG_GRAD_STOP) }, - { "STYLE_BG_IMG_OPA", be_cconst_int(LV_STYLE_BG_IMG_OPA) }, - { "STYLE_BG_IMG_RECOLOR", be_cconst_int(LV_STYLE_BG_IMG_RECOLOR) }, - { "STYLE_BG_IMG_RECOLOR_OPA", be_cconst_int(LV_STYLE_BG_IMG_RECOLOR_OPA) }, - { "STYLE_BG_IMG_SRC", be_cconst_int(LV_STYLE_BG_IMG_SRC) }, - { "STYLE_BG_IMG_TILED", be_cconst_int(LV_STYLE_BG_IMG_TILED) }, + { "STYLE_BG_IMAGE_OPA", be_cconst_int(LV_STYLE_BG_IMAGE_OPA) }, + { "STYLE_BG_IMAGE_RECOLOR", be_cconst_int(LV_STYLE_BG_IMAGE_RECOLOR) }, + { "STYLE_BG_IMAGE_RECOLOR_OPA", be_cconst_int(LV_STYLE_BG_IMAGE_RECOLOR_OPA) }, + { "STYLE_BG_IMAGE_SRC", be_cconst_int(LV_STYLE_BG_IMAGE_SRC) }, + { "STYLE_BG_IMAGE_TILED", be_cconst_int(LV_STYLE_BG_IMAGE_TILED) }, + { "STYLE_BG_MAIN_OPA", be_cconst_int(LV_STYLE_BG_MAIN_OPA) }, { "STYLE_BG_MAIN_STOP", be_cconst_int(LV_STYLE_BG_MAIN_STOP) }, { "STYLE_BG_OPA", be_cconst_int(LV_STYLE_BG_OPA) }, { "STYLE_BLEND_MODE", be_cconst_int(LV_STYLE_BLEND_MODE) }, @@ -708,17 +749,40 @@ const be_const_member_t lv0_constants[] = { { "STYLE_CLIP_CORNER", be_cconst_int(LV_STYLE_CLIP_CORNER) }, { "STYLE_COLOR_FILTER_DSC", be_cconst_int(LV_STYLE_COLOR_FILTER_DSC) }, { "STYLE_COLOR_FILTER_OPA", be_cconst_int(LV_STYLE_COLOR_FILTER_OPA) }, + { "STYLE_FLEX_CROSS_PLACE", be_cconst_int(LV_STYLE_FLEX_CROSS_PLACE) }, + { "STYLE_FLEX_FLOW", be_cconst_int(LV_STYLE_FLEX_FLOW) }, + { "STYLE_FLEX_GROW", be_cconst_int(LV_STYLE_FLEX_GROW) }, + { "STYLE_FLEX_MAIN_PLACE", be_cconst_int(LV_STYLE_FLEX_MAIN_PLACE) }, + { "STYLE_FLEX_TRACK_PLACE", be_cconst_int(LV_STYLE_FLEX_TRACK_PLACE) }, + { "STYLE_GRID_CELL_COLUMN_POS", be_cconst_int(LV_STYLE_GRID_CELL_COLUMN_POS) }, + { "STYLE_GRID_CELL_COLUMN_SPAN", be_cconst_int(LV_STYLE_GRID_CELL_COLUMN_SPAN) }, + { "STYLE_GRID_CELL_ROW_POS", be_cconst_int(LV_STYLE_GRID_CELL_ROW_POS) }, + { "STYLE_GRID_CELL_ROW_SPAN", be_cconst_int(LV_STYLE_GRID_CELL_ROW_SPAN) }, + { "STYLE_GRID_CELL_X_ALIGN", be_cconst_int(LV_STYLE_GRID_CELL_X_ALIGN) }, + { "STYLE_GRID_CELL_Y_ALIGN", be_cconst_int(LV_STYLE_GRID_CELL_Y_ALIGN) }, + { "STYLE_GRID_COLUMN_ALIGN", be_cconst_int(LV_STYLE_GRID_COLUMN_ALIGN) }, + { "STYLE_GRID_COLUMN_DSC_ARRAY", be_cconst_int(LV_STYLE_GRID_COLUMN_DSC_ARRAY) }, + { "STYLE_GRID_ROW_ALIGN", be_cconst_int(LV_STYLE_GRID_ROW_ALIGN) }, + { "STYLE_GRID_ROW_DSC_ARRAY", be_cconst_int(LV_STYLE_GRID_ROW_DSC_ARRAY) }, { "STYLE_HEIGHT", be_cconst_int(LV_STYLE_HEIGHT) }, - { "STYLE_IMG_OPA", be_cconst_int(LV_STYLE_IMG_OPA) }, - { "STYLE_IMG_RECOLOR", be_cconst_int(LV_STYLE_IMG_RECOLOR) }, - { "STYLE_IMG_RECOLOR_OPA", be_cconst_int(LV_STYLE_IMG_RECOLOR_OPA) }, + { "STYLE_IMAGE_OPA", be_cconst_int(LV_STYLE_IMAGE_OPA) }, + { "STYLE_IMAGE_RECOLOR", be_cconst_int(LV_STYLE_IMAGE_RECOLOR) }, + { "STYLE_IMAGE_RECOLOR_OPA", be_cconst_int(LV_STYLE_IMAGE_RECOLOR_OPA) }, + { "STYLE_IMG_OPA", be_cconst_int(LV_STYLE_IMAGE_OPA) }, + { "STYLE_IMG_RECOLOR", be_cconst_int(LV_STYLE_IMAGE_RECOLOR) }, + { "STYLE_IMG_RECOLOR_OPA", be_cconst_int(LV_STYLE_IMAGE_RECOLOR_OPA) }, { "STYLE_LAYOUT", be_cconst_int(LV_STYLE_LAYOUT) }, + { "STYLE_LENGTH", be_cconst_int(LV_STYLE_LENGTH) }, { "STYLE_LINE_COLOR", be_cconst_int(LV_STYLE_LINE_COLOR) }, { "STYLE_LINE_DASH_GAP", be_cconst_int(LV_STYLE_LINE_DASH_GAP) }, { "STYLE_LINE_DASH_WIDTH", be_cconst_int(LV_STYLE_LINE_DASH_WIDTH) }, { "STYLE_LINE_OPA", be_cconst_int(LV_STYLE_LINE_OPA) }, { "STYLE_LINE_ROUNDED", be_cconst_int(LV_STYLE_LINE_ROUNDED) }, { "STYLE_LINE_WIDTH", be_cconst_int(LV_STYLE_LINE_WIDTH) }, + { "STYLE_MARGIN_BOTTOM", be_cconst_int(LV_STYLE_MARGIN_BOTTOM) }, + { "STYLE_MARGIN_LEFT", be_cconst_int(LV_STYLE_MARGIN_LEFT) }, + { "STYLE_MARGIN_RIGHT", be_cconst_int(LV_STYLE_MARGIN_RIGHT) }, + { "STYLE_MARGIN_TOP", be_cconst_int(LV_STYLE_MARGIN_TOP) }, { "STYLE_MAX_HEIGHT", be_cconst_int(LV_STYLE_MAX_HEIGHT) }, { "STYLE_MAX_WIDTH", be_cconst_int(LV_STYLE_MAX_WIDTH) }, { "STYLE_MIN_HEIGHT", be_cconst_int(LV_STYLE_MIN_HEIGHT) }, @@ -739,11 +803,12 @@ const be_const_member_t lv0_constants[] = { { "STYLE_PROP_INV", be_cconst_int(LV_STYLE_PROP_INV) }, { "STYLE_RADIUS", be_cconst_int(LV_STYLE_RADIUS) }, { "STYLE_RES_FOUND", be_cconst_int(LV_STYLE_RES_FOUND) }, - { "STYLE_RES_INHERIT", be_cconst_int(LV_STYLE_RES_INHERIT) }, { "STYLE_RES_NOT_FOUND", be_cconst_int(LV_STYLE_RES_NOT_FOUND) }, { "STYLE_SHADOW_COLOR", be_cconst_int(LV_STYLE_SHADOW_COLOR) }, - { "STYLE_SHADOW_OFS_X", be_cconst_int(LV_STYLE_SHADOW_OFS_X) }, - { "STYLE_SHADOW_OFS_Y", be_cconst_int(LV_STYLE_SHADOW_OFS_Y) }, + { "STYLE_SHADOW_OFFSET_X", be_cconst_int(LV_STYLE_SHADOW_OFFSET_X) }, + { "STYLE_SHADOW_OFFSET_Y", be_cconst_int(LV_STYLE_SHADOW_OFFSET_Y) }, + { "STYLE_SHADOW_OFS_X", be_cconst_int(LV_STYLE_SHADOW_OFFSET_X) }, + { "STYLE_SHADOW_OFS_Y", be_cconst_int(LV_STYLE_SHADOW_OFFSET_Y) }, { "STYLE_SHADOW_OPA", be_cconst_int(LV_STYLE_SHADOW_OPA) }, { "STYLE_SHADOW_SPREAD", be_cconst_int(LV_STYLE_SHADOW_SPREAD) }, { "STYLE_SHADOW_WIDTH", be_cconst_int(LV_STYLE_SHADOW_WIDTH) }, @@ -754,12 +819,16 @@ const be_const_member_t lv0_constants[] = { { "STYLE_TEXT_LETTER_SPACE", be_cconst_int(LV_STYLE_TEXT_LETTER_SPACE) }, { "STYLE_TEXT_LINE_SPACE", be_cconst_int(LV_STYLE_TEXT_LINE_SPACE) }, { "STYLE_TEXT_OPA", be_cconst_int(LV_STYLE_TEXT_OPA) }, - { "STYLE_TRANSFORM_ANGLE", be_cconst_int(LV_STYLE_TRANSFORM_ANGLE) }, + { "STYLE_TRANSFORM_ANGLE", be_cconst_int(LV_STYLE_TRANSFORM_ROTATION) }, { "STYLE_TRANSFORM_HEIGHT", be_cconst_int(LV_STYLE_TRANSFORM_HEIGHT) }, { "STYLE_TRANSFORM_PIVOT_X", be_cconst_int(LV_STYLE_TRANSFORM_PIVOT_X) }, { "STYLE_TRANSFORM_PIVOT_Y", be_cconst_int(LV_STYLE_TRANSFORM_PIVOT_Y) }, + { "STYLE_TRANSFORM_ROTATION", be_cconst_int(LV_STYLE_TRANSFORM_ROTATION) }, + { "STYLE_TRANSFORM_SCALE_X", be_cconst_int(LV_STYLE_TRANSFORM_SCALE_X) }, + { "STYLE_TRANSFORM_SCALE_Y", be_cconst_int(LV_STYLE_TRANSFORM_SCALE_Y) }, + { "STYLE_TRANSFORM_SKEW_X", be_cconst_int(LV_STYLE_TRANSFORM_SKEW_X) }, + { "STYLE_TRANSFORM_SKEW_Y", be_cconst_int(LV_STYLE_TRANSFORM_SKEW_Y) }, { "STYLE_TRANSFORM_WIDTH", be_cconst_int(LV_STYLE_TRANSFORM_WIDTH) }, - { "STYLE_TRANSFORM_ZOOM", be_cconst_int(LV_STYLE_TRANSFORM_ZOOM) }, { "STYLE_TRANSITION", be_cconst_int(LV_STYLE_TRANSITION) }, { "STYLE_TRANSLATE_X", be_cconst_int(LV_STYLE_TRANSLATE_X) }, { "STYLE_TRANSLATE_Y", be_cconst_int(LV_STYLE_TRANSLATE_Y) }, @@ -832,22 +901,51 @@ const be_const_member_t lv0_constants[] = { { "TABLE_CELL_CTRL_MERGE_RIGHT", be_cconst_int(LV_TABLE_CELL_CTRL_MERGE_RIGHT) }, { "TABLE_CELL_CTRL_TEXT_CROP", be_cconst_int(LV_TABLE_CELL_CTRL_TEXT_CROP) }, { "TABLE_CELL_NONE", be_cconst_int(LV_TABLE_CELL_NONE) }, - { "TABLE_DRAW_PART_CELL", be_cconst_int(LV_TABLE_DRAW_PART_CELL) }, { "TEXTAREA_CURSOR_LAST", be_cconst_int(LV_TEXTAREA_CURSOR_LAST) }, { "TEXT_ALIGN_AUTO", be_cconst_int(LV_TEXT_ALIGN_AUTO) }, { "TEXT_ALIGN_CENTER", be_cconst_int(LV_TEXT_ALIGN_CENTER) }, { "TEXT_ALIGN_LEFT", be_cconst_int(LV_TEXT_ALIGN_LEFT) }, { "TEXT_ALIGN_RIGHT", be_cconst_int(LV_TEXT_ALIGN_RIGHT) }, - { "TEXT_CMD_STATE_IN", be_cconst_int(LV_TEXT_CMD_STATE_IN) }, - { "TEXT_CMD_STATE_PAR", be_cconst_int(LV_TEXT_CMD_STATE_PAR) }, - { "TEXT_CMD_STATE_WAIT", be_cconst_int(LV_TEXT_CMD_STATE_WAIT) }, { "TEXT_DECOR_NONE", be_cconst_int(LV_TEXT_DECOR_NONE) }, { "TEXT_DECOR_STRIKETHROUGH", be_cconst_int(LV_TEXT_DECOR_STRIKETHROUGH) }, { "TEXT_DECOR_UNDERLINE", be_cconst_int(LV_TEXT_DECOR_UNDERLINE) }, { "TEXT_FLAG_EXPAND", be_cconst_int(LV_TEXT_FLAG_EXPAND) }, { "TEXT_FLAG_FIT", be_cconst_int(LV_TEXT_FLAG_FIT) }, { "TEXT_FLAG_NONE", be_cconst_int(LV_TEXT_FLAG_NONE) }, - { "TEXT_FLAG_RECOLOR", be_cconst_int(LV_TEXT_FLAG_RECOLOR) }, + { "VECTOR_BLEND_ADDITIVE", be_cconst_int(LV_VECTOR_BLEND_ADDITIVE) }, + { "VECTOR_BLEND_DST_IN", be_cconst_int(LV_VECTOR_BLEND_DST_IN) }, + { "VECTOR_BLEND_DST_OVER", be_cconst_int(LV_VECTOR_BLEND_DST_OVER) }, + { "VECTOR_BLEND_MULTIPLY", be_cconst_int(LV_VECTOR_BLEND_MULTIPLY) }, + { "VECTOR_BLEND_NONE", be_cconst_int(LV_VECTOR_BLEND_NONE) }, + { "VECTOR_BLEND_SCREEN", be_cconst_int(LV_VECTOR_BLEND_SCREEN) }, + { "VECTOR_BLEND_SRC_IN", be_cconst_int(LV_VECTOR_BLEND_SRC_IN) }, + { "VECTOR_BLEND_SRC_OVER", be_cconst_int(LV_VECTOR_BLEND_SRC_OVER) }, + { "VECTOR_BLEND_SUBTRACTIVE", be_cconst_int(LV_VECTOR_BLEND_SUBTRACTIVE) }, + { "VECTOR_DRAW_STYLE_GRADIENT", be_cconst_int(LV_VECTOR_DRAW_STYLE_GRADIENT) }, + { "VECTOR_DRAW_STYLE_PATTERN", be_cconst_int(LV_VECTOR_DRAW_STYLE_PATTERN) }, + { "VECTOR_DRAW_STYLE_SOLID", be_cconst_int(LV_VECTOR_DRAW_STYLE_SOLID) }, + { "VECTOR_FILL_EVENODD", be_cconst_int(LV_VECTOR_FILL_EVENODD) }, + { "VECTOR_FILL_NONZERO", be_cconst_int(LV_VECTOR_FILL_NONZERO) }, + { "VECTOR_GRADIENT_SPREAD_PAD", be_cconst_int(LV_VECTOR_GRADIENT_SPREAD_PAD) }, + { "VECTOR_GRADIENT_SPREAD_REFLECT", be_cconst_int(LV_VECTOR_GRADIENT_SPREAD_REFLECT) }, + { "VECTOR_GRADIENT_SPREAD_REPEAT", be_cconst_int(LV_VECTOR_GRADIENT_SPREAD_REPEAT) }, + { "VECTOR_GRADIENT_STYLE_LINEAR", be_cconst_int(LV_VECTOR_GRADIENT_STYLE_LINEAR) }, + { "VECTOR_GRADIENT_STYLE_RADIAL", be_cconst_int(LV_VECTOR_GRADIENT_STYLE_RADIAL) }, + { "VECTOR_PATH_OP_CLOSE", be_cconst_int(LV_VECTOR_PATH_OP_CLOSE) }, + { "VECTOR_PATH_OP_CUBIC_TO", be_cconst_int(LV_VECTOR_PATH_OP_CUBIC_TO) }, + { "VECTOR_PATH_OP_LINE_TO", be_cconst_int(LV_VECTOR_PATH_OP_LINE_TO) }, + { "VECTOR_PATH_OP_MOVE_TO", be_cconst_int(LV_VECTOR_PATH_OP_MOVE_TO) }, + { "VECTOR_PATH_OP_QUAD_TO", be_cconst_int(LV_VECTOR_PATH_OP_QUAD_TO) }, + { "VECTOR_PATH_QUALITY_HIGH", be_cconst_int(LV_VECTOR_PATH_QUALITY_HIGH) }, + { "VECTOR_PATH_QUALITY_LOW", be_cconst_int(LV_VECTOR_PATH_QUALITY_LOW) }, + { "VECTOR_PATH_QUALITY_MEDIUM", be_cconst_int(LV_VECTOR_PATH_QUALITY_MEDIUM) }, + { "VECTOR_STROKE_CAP_BUTT", be_cconst_int(LV_VECTOR_STROKE_CAP_BUTT) }, + { "VECTOR_STROKE_CAP_ROUND", be_cconst_int(LV_VECTOR_STROKE_CAP_ROUND) }, + { "VECTOR_STROKE_CAP_SQUARE", be_cconst_int(LV_VECTOR_STROKE_CAP_SQUARE) }, + { "VECTOR_STROKE_JOIN_BEVEL", be_cconst_int(LV_VECTOR_STROKE_JOIN_BEVEL) }, + { "VECTOR_STROKE_JOIN_MITER", be_cconst_int(LV_VECTOR_STROKE_JOIN_MITER) }, + { "VECTOR_STROKE_JOIN_ROUND", be_cconst_int(LV_VECTOR_STROKE_JOIN_ROUND) }, + { "ZOOM_NONE", be_cconst_int(LV_SCALE_NONE) }, { "&anim_path_bounce", be_cconst_ptr(&lv_anim_path_bounce) }, { "&anim_path_ease_in", be_cconst_ptr(&lv_anim_path_ease_in) }, { "&anim_path_ease_in_out", be_cconst_ptr(&lv_anim_path_ease_in_out) }, diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c index 3a734f566..83015cef2 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c @@ -30,118 +30,138 @@ extern int lvbe_theme_create(bvm *vm); /* `lv_style` external functions definitions */ -extern int lvbe_style_set_flex_flow(bvm *vm); -extern int lvbe_style_set_flex_main_place(bvm *vm); +extern int lvbe_style_is_const(bvm *vm); +extern int lvbe_style_is_empty(bvm *vm); +extern int lvbe_style_remove_prop(bvm *vm); +extern int lvbe_style_reset(bvm *vm); +extern int lvbe_style_set_align(bvm *vm); +extern int lvbe_style_set_anim(bvm *vm); +extern int lvbe_style_set_anim_duration(bvm *vm); +extern int lvbe_style_set_anim_duration(bvm *vm); +extern int lvbe_style_set_arc_color(bvm *vm); +extern int lvbe_style_set_arc_image_src(bvm *vm); +extern int lvbe_style_set_arc_opa(bvm *vm); +extern int lvbe_style_set_arc_rounded(bvm *vm); +extern int lvbe_style_set_arc_width(bvm *vm); +extern int lvbe_style_set_base_dir(bvm *vm); +extern int lvbe_style_set_bg_color(bvm *vm); +extern int lvbe_style_set_bg_grad(bvm *vm); +extern int lvbe_style_set_bg_grad_color(bvm *vm); +extern int lvbe_style_set_bg_grad_dir(bvm *vm); +extern int lvbe_style_set_bg_grad_opa(bvm *vm); +extern int lvbe_style_set_bg_grad_stop(bvm *vm); +extern int lvbe_style_set_bg_image_opa(bvm *vm); +extern int lvbe_style_set_bg_image_recolor(bvm *vm); +extern int lvbe_style_set_bg_image_recolor_opa(bvm *vm); +extern int lvbe_style_set_bg_image_src(bvm *vm); +extern int lvbe_style_set_bg_image_tiled(bvm *vm); +extern int lvbe_style_set_bg_image_opa(bvm *vm); +extern int lvbe_style_set_bg_image_recolor(bvm *vm); +extern int lvbe_style_set_bg_image_recolor_opa(bvm *vm); +extern int lvbe_style_set_bg_image_src(bvm *vm); +extern int lvbe_style_set_bg_image_tiled(bvm *vm); +extern int lvbe_style_set_bg_main_opa(bvm *vm); +extern int lvbe_style_set_bg_main_stop(bvm *vm); +extern int lvbe_style_set_bg_opa(bvm *vm); +extern int lvbe_style_set_blend_mode(bvm *vm); +extern int lvbe_style_set_border_color(bvm *vm); +extern int lvbe_style_set_border_opa(bvm *vm); +extern int lvbe_style_set_border_post(bvm *vm); +extern int lvbe_style_set_border_side(bvm *vm); +extern int lvbe_style_set_border_width(bvm *vm); +extern int lvbe_style_set_clip_corner(bvm *vm); +extern int lvbe_style_set_color_filter_dsc(bvm *vm); +extern int lvbe_style_set_color_filter_opa(bvm *vm); extern int lvbe_style_set_flex_cross_place(bvm *vm); -extern int lvbe_style_set_flex_track_place(bvm *vm); +extern int lvbe_style_set_flex_flow(bvm *vm); extern int lvbe_style_set_flex_grow(bvm *vm); -extern int lvbe_style_set_grid_row_dsc_array(bvm *vm); -extern int lvbe_style_set_grid_column_dsc_array(bvm *vm); -extern int lvbe_style_set_grid_row_align(bvm *vm); -extern int lvbe_style_set_grid_column_align(bvm *vm); +extern int lvbe_style_set_flex_main_place(bvm *vm); +extern int lvbe_style_set_flex_track_place(bvm *vm); extern int lvbe_style_set_grid_cell_column_pos(bvm *vm); extern int lvbe_style_set_grid_cell_column_span(bvm *vm); extern int lvbe_style_set_grid_cell_row_pos(bvm *vm); extern int lvbe_style_set_grid_cell_row_span(bvm *vm); extern int lvbe_style_set_grid_cell_x_align(bvm *vm); extern int lvbe_style_set_grid_cell_y_align(bvm *vm); -extern int lvbe_style_reset(bvm *vm); -extern int lvbe_style_remove_prop(bvm *vm); -extern int lvbe_style_set_prop(bvm *vm); -extern int lvbe_style_set_prop_meta(bvm *vm); -extern int lvbe_style_get_prop(bvm *vm); -extern int lvbe_style_get_prop_inlined(bvm *vm); -extern int lvbe_style_is_empty(bvm *vm); -extern int lvbe_style_set_size(bvm *vm); -extern int lvbe_style_set_pad_all(bvm *vm); -extern int lvbe_style_set_pad_hor(bvm *vm); -extern int lvbe_style_set_pad_ver(bvm *vm); -extern int lvbe_style_set_pad_gap(bvm *vm); -extern int lvbe_style_set_width(bvm *vm); -extern int lvbe_style_set_min_width(bvm *vm); -extern int lvbe_style_set_max_width(bvm *vm); +extern int lvbe_style_set_grid_column_align(bvm *vm); +extern int lvbe_style_set_grid_column_dsc_array(bvm *vm); +extern int lvbe_style_set_grid_row_align(bvm *vm); +extern int lvbe_style_set_grid_row_dsc_array(bvm *vm); extern int lvbe_style_set_height(bvm *vm); -extern int lvbe_style_set_min_height(bvm *vm); +extern int lvbe_style_set_image_opa(bvm *vm); +extern int lvbe_style_set_image_recolor(bvm *vm); +extern int lvbe_style_set_image_recolor_opa(bvm *vm); +extern int lvbe_style_set_image_opa(bvm *vm); +extern int lvbe_style_set_image_recolor(bvm *vm); +extern int lvbe_style_set_image_recolor_opa(bvm *vm); +extern int lvbe_style_set_layout(bvm *vm); +extern int lvbe_style_set_length(bvm *vm); +extern int lvbe_style_set_line_color(bvm *vm); +extern int lvbe_style_set_line_dash_gap(bvm *vm); +extern int lvbe_style_set_line_dash_width(bvm *vm); +extern int lvbe_style_set_line_opa(bvm *vm); +extern int lvbe_style_set_line_rounded(bvm *vm); +extern int lvbe_style_set_line_width(bvm *vm); +extern int lvbe_style_set_margin_bottom(bvm *vm); +extern int lvbe_style_set_margin_left(bvm *vm); +extern int lvbe_style_set_margin_right(bvm *vm); +extern int lvbe_style_set_margin_top(bvm *vm); extern int lvbe_style_set_max_height(bvm *vm); -extern int lvbe_style_set_x(bvm *vm); -extern int lvbe_style_set_y(bvm *vm); -extern int lvbe_style_set_align(bvm *vm); -extern int lvbe_style_set_transform_width(bvm *vm); -extern int lvbe_style_set_transform_height(bvm *vm); -extern int lvbe_style_set_translate_x(bvm *vm); -extern int lvbe_style_set_translate_y(bvm *vm); -extern int lvbe_style_set_transform_zoom(bvm *vm); -extern int lvbe_style_set_transform_angle(bvm *vm); -extern int lvbe_style_set_transform_pivot_x(bvm *vm); -extern int lvbe_style_set_transform_pivot_y(bvm *vm); -extern int lvbe_style_set_pad_top(bvm *vm); -extern int lvbe_style_set_pad_bottom(bvm *vm); -extern int lvbe_style_set_pad_left(bvm *vm); -extern int lvbe_style_set_pad_right(bvm *vm); -extern int lvbe_style_set_pad_row(bvm *vm); -extern int lvbe_style_set_pad_column(bvm *vm); -extern int lvbe_style_set_bg_color(bvm *vm); -extern int lvbe_style_set_bg_opa(bvm *vm); -extern int lvbe_style_set_bg_grad_color(bvm *vm); -extern int lvbe_style_set_bg_grad_dir(bvm *vm); -extern int lvbe_style_set_bg_main_stop(bvm *vm); -extern int lvbe_style_set_bg_grad_stop(bvm *vm); -extern int lvbe_style_set_bg_grad(bvm *vm); -extern int lvbe_style_set_bg_dither_mode(bvm *vm); -extern int lvbe_style_set_bg_img_src(bvm *vm); -extern int lvbe_style_set_bg_img_opa(bvm *vm); -extern int lvbe_style_set_bg_img_recolor(bvm *vm); -extern int lvbe_style_set_bg_img_recolor_opa(bvm *vm); -extern int lvbe_style_set_bg_img_tiled(bvm *vm); -extern int lvbe_style_set_border_color(bvm *vm); -extern int lvbe_style_set_border_opa(bvm *vm); -extern int lvbe_style_set_border_width(bvm *vm); -extern int lvbe_style_set_border_side(bvm *vm); -extern int lvbe_style_set_border_post(bvm *vm); -extern int lvbe_style_set_outline_width(bvm *vm); +extern int lvbe_style_set_max_width(bvm *vm); +extern int lvbe_style_set_min_height(bvm *vm); +extern int lvbe_style_set_min_width(bvm *vm); +extern int lvbe_style_set_opa(bvm *vm); +extern int lvbe_style_set_opa_layered(bvm *vm); extern int lvbe_style_set_outline_color(bvm *vm); extern int lvbe_style_set_outline_opa(bvm *vm); extern int lvbe_style_set_outline_pad(bvm *vm); -extern int lvbe_style_set_shadow_width(bvm *vm); -extern int lvbe_style_set_shadow_ofs_x(bvm *vm); -extern int lvbe_style_set_shadow_ofs_y(bvm *vm); -extern int lvbe_style_set_shadow_spread(bvm *vm); +extern int lvbe_style_set_outline_width(bvm *vm); +extern int lvbe_style_set_pad_all(bvm *vm); +extern int lvbe_style_set_pad_bottom(bvm *vm); +extern int lvbe_style_set_pad_column(bvm *vm); +extern int lvbe_style_set_pad_gap(bvm *vm); +extern int lvbe_style_set_pad_hor(bvm *vm); +extern int lvbe_style_set_pad_left(bvm *vm); +extern int lvbe_style_set_pad_right(bvm *vm); +extern int lvbe_style_set_pad_row(bvm *vm); +extern int lvbe_style_set_pad_top(bvm *vm); +extern int lvbe_style_set_pad_ver(bvm *vm); +extern int lvbe_style_set_prop(bvm *vm); +extern int lvbe_style_set_radius(bvm *vm); extern int lvbe_style_set_shadow_color(bvm *vm); +extern int lvbe_style_set_shadow_offset_x(bvm *vm); +extern int lvbe_style_set_shadow_offset_y(bvm *vm); +extern int lvbe_style_set_shadow_offset_x(bvm *vm); +extern int lvbe_style_set_shadow_offset_y(bvm *vm); extern int lvbe_style_set_shadow_opa(bvm *vm); -extern int lvbe_style_set_img_opa(bvm *vm); -extern int lvbe_style_set_img_recolor(bvm *vm); -extern int lvbe_style_set_img_recolor_opa(bvm *vm); -extern int lvbe_style_set_line_width(bvm *vm); -extern int lvbe_style_set_line_dash_width(bvm *vm); -extern int lvbe_style_set_line_dash_gap(bvm *vm); -extern int lvbe_style_set_line_rounded(bvm *vm); -extern int lvbe_style_set_line_color(bvm *vm); -extern int lvbe_style_set_line_opa(bvm *vm); -extern int lvbe_style_set_arc_width(bvm *vm); -extern int lvbe_style_set_arc_rounded(bvm *vm); -extern int lvbe_style_set_arc_color(bvm *vm); -extern int lvbe_style_set_arc_opa(bvm *vm); -extern int lvbe_style_set_arc_img_src(bvm *vm); +extern int lvbe_style_set_shadow_spread(bvm *vm); +extern int lvbe_style_set_shadow_width(bvm *vm); +extern int lvbe_style_set_size(bvm *vm); +extern int lvbe_style_set_text_align(bvm *vm); extern int lvbe_style_set_text_color(bvm *vm); -extern int lvbe_style_set_text_opa(bvm *vm); +extern int lvbe_style_set_text_decor(bvm *vm); extern int lvbe_style_set_text_font(bvm *vm); extern int lvbe_style_set_text_letter_space(bvm *vm); extern int lvbe_style_set_text_line_space(bvm *vm); -extern int lvbe_style_set_text_decor(bvm *vm); -extern int lvbe_style_set_text_align(bvm *vm); -extern int lvbe_style_set_radius(bvm *vm); -extern int lvbe_style_set_clip_corner(bvm *vm); -extern int lvbe_style_set_opa(bvm *vm); -extern int lvbe_style_set_opa_layered(bvm *vm); -extern int lvbe_style_set_color_filter_dsc(bvm *vm); -extern int lvbe_style_set_color_filter_opa(bvm *vm); -extern int lvbe_style_set_anim(bvm *vm); -extern int lvbe_style_set_anim_time(bvm *vm); -extern int lvbe_style_set_anim_speed(bvm *vm); +extern int lvbe_style_set_text_opa(bvm *vm); +extern int lvbe_style_set_transform_rotation(bvm *vm); +extern int lvbe_style_set_transform_height(bvm *vm); +extern int lvbe_style_set_transform_pivot_x(bvm *vm); +extern int lvbe_style_set_transform_pivot_y(bvm *vm); +extern int lvbe_style_set_transform_rotation(bvm *vm); +extern int lvbe_style_set_transform_scale(bvm *vm); +extern int lvbe_style_set_transform_scale_x(bvm *vm); +extern int lvbe_style_set_transform_scale_y(bvm *vm); +extern int lvbe_style_set_transform_skew_x(bvm *vm); +extern int lvbe_style_set_transform_skew_y(bvm *vm); +extern int lvbe_style_set_transform_width(bvm *vm); +extern int lvbe_style_set_transform_scale(bvm *vm); extern int lvbe_style_set_transition(bvm *vm); -extern int lvbe_style_set_blend_mode(bvm *vm); -extern int lvbe_style_set_layout(bvm *vm); -extern int lvbe_style_set_base_dir(bvm *vm); +extern int lvbe_style_set_translate_x(bvm *vm); +extern int lvbe_style_set_translate_y(bvm *vm); +extern int lvbe_style_set_width(bvm *vm); +extern int lvbe_style_set_x(bvm *vm); +extern int lvbe_style_set_y(bvm *vm); /* `lv_font` external functions definitions */ @@ -149,913 +169,1189 @@ extern int lvbe_style_set_base_dir(bvm *vm); /* `lv_theme` external functions definitions */ -/* `lv_img` external functions definitions */ -extern int lvbe_img_set_tasmota_logo(bvm *vm); -extern int lvbe_img_create(bvm *vm); -extern int lvbe_img_set_src(bvm *vm); -extern int lvbe_img_set_offset_x(bvm *vm); -extern int lvbe_img_set_offset_y(bvm *vm); -extern int lvbe_img_set_angle(bvm *vm); -extern int lvbe_img_set_pivot(bvm *vm); -extern int lvbe_img_set_zoom(bvm *vm); -extern int lvbe_img_set_antialias(bvm *vm); -extern int lvbe_img_set_size_mode(bvm *vm); -extern int lvbe_img_get_src(bvm *vm); -extern int lvbe_img_get_offset_x(bvm *vm); -extern int lvbe_img_get_offset_y(bvm *vm); -extern int lvbe_img_get_angle(bvm *vm); -extern int lvbe_img_get_pivot(bvm *vm); -extern int lvbe_img_get_zoom(bvm *vm); -extern int lvbe_img_get_antialias(bvm *vm); -extern int lvbe_img_get_size_mode(bvm *vm); +/* `lv_image` external functions definitions */ +extern int lvbe_image_create(bvm *vm); +extern int lvbe_image_get_rotation(bvm *vm); +extern int lvbe_image_get_antialias(bvm *vm); +extern int lvbe_image_get_blend_mode(bvm *vm); +extern int lvbe_image_get_inner_align(bvm *vm); +extern int lvbe_image_get_offset_x(bvm *vm); +extern int lvbe_image_get_offset_x(bvm *vm); +extern int lvbe_image_get_offset_y(bvm *vm); +extern int lvbe_image_get_offset_y(bvm *vm); +extern int lvbe_image_get_pivot(bvm *vm); +extern int lvbe_image_get_rotation(bvm *vm); +extern int lvbe_image_get_rotation(bvm *vm); +extern int lvbe_image_get_scale(bvm *vm); +extern int lvbe_image_get_scale_x(bvm *vm); +extern int lvbe_image_get_scale_y(bvm *vm); +extern int lvbe_image_get_src(bvm *vm); +extern int lvbe_image_get_scale(bvm *vm); +extern int lvbe_image_set_rotation(bvm *vm); +extern int lvbe_image_set_antialias(bvm *vm); +extern int lvbe_image_set_blend_mode(bvm *vm); +extern int lvbe_image_set_inner_align(bvm *vm); +extern int lvbe_image_set_offset_x(bvm *vm); +extern int lvbe_image_set_offset_y(bvm *vm); +extern int lvbe_image_set_pivot(bvm *vm); +extern int lvbe_image_set_rotation(bvm *vm); +extern int lvbe_image_set_rotation(bvm *vm); +extern int lvbe_image_set_scale(bvm *vm); +extern int lvbe_image_set_scale_x(bvm *vm); +extern int lvbe_image_set_scale_y(bvm *vm); +extern int lvbe_image_set_src(bvm *vm); +extern int lvbe_image_set_tasmota_logo(bvm *vm); +extern int lvbe_image_set_scale(bvm *vm); -/* `lv_disp` external functions definitions */ -extern int lvbe_disp_get_scr_act(bvm *vm); -extern int lvbe_disp_get_scr_prev(bvm *vm); -extern int lvbe_disp_load_scr(bvm *vm); -extern int lvbe_disp_get_layer_top(bvm *vm); -extern int lvbe_disp_get_layer_sys(bvm *vm); -extern int lvbe_disp_set_theme(bvm *vm); -extern int lvbe_disp_get_theme(bvm *vm); -extern int lvbe_disp_set_bg_color(bvm *vm); -extern int lvbe_disp_set_bg_image(bvm *vm); -extern int lvbe_disp_set_bg_opa(bvm *vm); -extern int lvbe_disp_get_inactive_time(bvm *vm); -extern int lvbe_disp_trig_activity(bvm *vm); -extern int lvbe_disp_clean_dcache(bvm *vm); -extern int lvbe_disp_enable_invalidation(bvm *vm); -extern int lvbe_disp_is_invalidation_enabled(bvm *vm); -extern int lvbe_disp_dpx(bvm *vm); +/* `lv_group` external functions definitions */ +extern int lvbe_group_add_obj(bvm *vm); +extern int lvbe_group_create(bvm *vm); +extern int lvbe_group_delete(bvm *vm); +extern int lvbe_group_delete(bvm *vm); +extern int lvbe_group_focus_freeze(bvm *vm); +extern int lvbe_group_focus_next(bvm *vm); +extern int lvbe_group_focus_obj(bvm *vm); +extern int lvbe_group_focus_prev(bvm *vm); +extern int lvbe_group_get_edge_cb(bvm *vm); +extern int lvbe_group_get_editing(bvm *vm); +extern int lvbe_group_get_focus_cb(bvm *vm); +extern int lvbe_group_get_focused(bvm *vm); +extern int lvbe_group_get_obj_count(bvm *vm); +extern int lvbe_group_get_wrap(bvm *vm); +extern int lvbe_group_delete(bvm *vm); +extern int lvbe_group_remove_all_objs(bvm *vm); +extern int lvbe_group_remove_obj(bvm *vm); +extern int lvbe_group_send_data(bvm *vm); +extern int lvbe_group_set_default(bvm *vm); +extern int lvbe_group_set_default(bvm *vm); +extern int lvbe_group_set_editing(bvm *vm); +extern int lvbe_group_set_focus_cb(bvm *vm); +extern int lvbe_group_set_refocus_policy(bvm *vm); +extern int lvbe_group_set_wrap(bvm *vm); +extern int lvbe_group_swap_obj(bvm *vm); /* `lv_obj` external functions definitions */ extern int lvbe_obj_add_event_cb(bvm *vm); -extern int lvbe_obj_remove_event_cb(bvm *vm); -extern int lvbe_obj_remove_event_cb_with_user_data(bvm *vm); -extern int lvbe_obj_remove_event_dsc(bvm *vm); -extern int lvbe_obj_get_event_user_data(bvm *vm); -extern int lvbe_obj_create(bvm *vm); extern int lvbe_obj_add_flag(bvm *vm); -extern int lvbe_obj_clear_flag(bvm *vm); extern int lvbe_obj_add_state(bvm *vm); -extern int lvbe_obj_clear_state(bvm *vm); -extern int lvbe_obj_set_user_data(bvm *vm); -extern int lvbe_obj_has_flag(bvm *vm); -extern int lvbe_obj_has_flag_any(bvm *vm); -extern int lvbe_obj_get_state(bvm *vm); -extern int lvbe_obj_has_state(bvm *vm); -extern int lvbe_obj_get_group(bvm *vm); -extern int lvbe_obj_get_user_data(bvm *vm); -extern int lvbe_obj_allocate_spec_attr(bvm *vm); -extern int lvbe_obj_check_type(bvm *vm); -extern int lvbe_obj_has_class(bvm *vm); -extern int lvbe_obj_get_class(bvm *vm); -extern int lvbe_obj_is_valid(bvm *vm); -extern int lvbe_obj_dpx(bvm *vm); -extern int lvbe_obj_class_init_obj(bvm *vm); -extern int lvbe_obj_is_editable(bvm *vm); -extern int lvbe_obj_is_group_def(bvm *vm); -extern int lvbe_obj_init_draw_rect_dsc(bvm *vm); -extern int lvbe_obj_init_draw_label_dsc(bvm *vm); -extern int lvbe_obj_init_draw_img_dsc(bvm *vm); -extern int lvbe_obj_init_draw_line_dsc(bvm *vm); -extern int lvbe_obj_init_draw_arc_dsc(bvm *vm); -extern int lvbe_obj_calculate_ext_draw_size(bvm *vm); -extern int lvbe_obj_refresh_ext_draw_size(bvm *vm); -extern int lvbe_obj_set_pos(bvm *vm); -extern int lvbe_obj_set_x(bvm *vm); -extern int lvbe_obj_set_y(bvm *vm); -extern int lvbe_obj_set_size(bvm *vm); -extern int lvbe_obj_refr_size(bvm *vm); -extern int lvbe_obj_set_width(bvm *vm); -extern int lvbe_obj_set_height(bvm *vm); -extern int lvbe_obj_set_content_width(bvm *vm); -extern int lvbe_obj_set_content_height(bvm *vm); -extern int lvbe_obj_set_layout(bvm *vm); -extern int lvbe_obj_is_layout_positioned(bvm *vm); -extern int lvbe_obj_mark_layout_as_dirty(bvm *vm); -extern int lvbe_obj_update_layout(bvm *vm); -extern int lvbe_obj_set_align(bvm *vm); +extern int lvbe_obj_add_style(bvm *vm); extern int lvbe_obj_align(bvm *vm); extern int lvbe_obj_align_to(bvm *vm); -extern int lvbe_obj_center(bvm *vm); -extern int lvbe_obj_get_coords(bvm *vm); -extern int lvbe_obj_get_x(bvm *vm); -extern int lvbe_obj_get_x2(bvm *vm); -extern int lvbe_obj_get_y(bvm *vm); -extern int lvbe_obj_get_y2(bvm *vm); -extern int lvbe_obj_get_x_aligned(bvm *vm); -extern int lvbe_obj_get_y_aligned(bvm *vm); -extern int lvbe_obj_get_width(bvm *vm); -extern int lvbe_obj_get_height(bvm *vm); -extern int lvbe_obj_get_content_width(bvm *vm); -extern int lvbe_obj_get_content_height(bvm *vm); -extern int lvbe_obj_get_content_coords(bvm *vm); -extern int lvbe_obj_get_self_width(bvm *vm); -extern int lvbe_obj_get_self_height(bvm *vm); -extern int lvbe_obj_refresh_self_size(bvm *vm); -extern int lvbe_obj_refr_pos(bvm *vm); -extern int lvbe_obj_move_to(bvm *vm); -extern int lvbe_obj_move_children_by(bvm *vm); -extern int lvbe_obj_transform_point(bvm *vm); -extern int lvbe_obj_get_transformed_area(bvm *vm); -extern int lvbe_obj_invalidate_area(bvm *vm); -extern int lvbe_obj_invalidate(bvm *vm); +extern int lvbe_obj_allocate_spec_attr(bvm *vm); extern int lvbe_obj_area_is_visible(bvm *vm); -extern int lvbe_obj_is_visible(bvm *vm); -extern int lvbe_obj_set_ext_click_area(bvm *vm); -extern int lvbe_obj_get_click_area(bvm *vm); -extern int lvbe_obj_hit_test(bvm *vm); -extern int lvbe_obj_set_scrollbar_mode(bvm *vm); -extern int lvbe_obj_set_scroll_dir(bvm *vm); -extern int lvbe_obj_set_scroll_snap_x(bvm *vm); -extern int lvbe_obj_set_scroll_snap_y(bvm *vm); -extern int lvbe_obj_get_scrollbar_mode(bvm *vm); -extern int lvbe_obj_get_scroll_dir(bvm *vm); -extern int lvbe_obj_get_scroll_snap_x(bvm *vm); -extern int lvbe_obj_get_scroll_snap_y(bvm *vm); -extern int lvbe_obj_get_scroll_x(bvm *vm); -extern int lvbe_obj_get_scroll_y(bvm *vm); -extern int lvbe_obj_get_scroll_top(bvm *vm); -extern int lvbe_obj_get_scroll_bottom(bvm *vm); -extern int lvbe_obj_get_scroll_left(bvm *vm); -extern int lvbe_obj_get_scroll_right(bvm *vm); -extern int lvbe_obj_get_scroll_end(bvm *vm); -extern int lvbe_obj_scroll_by(bvm *vm); -extern int lvbe_obj_scroll_by_bounded(bvm *vm); -extern int lvbe_obj_scroll_to(bvm *vm); -extern int lvbe_obj_scroll_to_x(bvm *vm); -extern int lvbe_obj_scroll_to_y(bvm *vm); -extern int lvbe_obj_scroll_to_view(bvm *vm); -extern int lvbe_obj_scroll_to_view_recursive(bvm *vm); -extern int lvbe_obj_is_scrolling(bvm *vm); -extern int lvbe_obj_update_snap(bvm *vm); -extern int lvbe_obj_get_scrollbar_area(bvm *vm); -extern int lvbe_obj_scrollbar_invalidate(bvm *vm); -extern int lvbe_obj_readjust_scroll(bvm *vm); -extern int lvbe_obj_add_style(bvm *vm); -extern int lvbe_obj_remove_style(bvm *vm); -extern int lvbe_obj_remove_style_all(bvm *vm); -extern int lvbe_obj_refresh_style(bvm *vm); -extern int lvbe_obj_get_style_prop(bvm *vm); -extern int lvbe_obj_set_local_style_prop(bvm *vm); -extern int lvbe_obj_set_local_style_prop_meta(bvm *vm); -extern int lvbe_obj_get_local_style_prop(bvm *vm); -extern int lvbe_obj_remove_local_style_prop(bvm *vm); +extern int lvbe_obj_calculate_ext_draw_size(bvm *vm); +extern int lvbe_obj_calculate_style_text_align(bvm *vm); +extern int lvbe_obj_center(bvm *vm); +extern int lvbe_obj_check_type(bvm *vm); +extern int lvbe_obj_class_init_obj(bvm *vm); +extern int lvbe_obj_clean(bvm *vm); +extern int lvbe_obj_remove_flag(bvm *vm); +extern int lvbe_obj_remove_state(bvm *vm); +extern int lvbe_obj_create(bvm *vm); +extern int lvbe_obj_delete(bvm *vm); +extern int lvbe_obj_delete_async(bvm *vm); +extern int lvbe_obj_delete(bvm *vm); +extern int lvbe_obj_delete_async(bvm *vm); +extern int lvbe_obj_delete_delayed(bvm *vm); +extern int lvbe_obj_dump_tree(bvm *vm); extern int lvbe_obj_fade_in(bvm *vm); extern int lvbe_obj_fade_out(bvm *vm); -extern int lvbe_obj_set_style_pad_all(bvm *vm); -extern int lvbe_obj_set_style_pad_hor(bvm *vm); -extern int lvbe_obj_set_style_pad_ver(bvm *vm); -extern int lvbe_obj_set_style_pad_gap(bvm *vm); -extern int lvbe_obj_set_style_size(bvm *vm); -extern int lvbe_obj_calculate_style_text_align(bvm *vm); -extern int lvbe_obj_get_style_transform_zoom_safe(bvm *vm); -extern int lvbe_obj_get_style_opa_recursive(bvm *vm); -extern int lvbe_obj_get_style_width(bvm *vm); -extern int lvbe_obj_get_style_min_width(bvm *vm); -extern int lvbe_obj_get_style_max_width(bvm *vm); -extern int lvbe_obj_get_style_height(bvm *vm); -extern int lvbe_obj_get_style_min_height(bvm *vm); -extern int lvbe_obj_get_style_max_height(bvm *vm); -extern int lvbe_obj_get_style_x(bvm *vm); -extern int lvbe_obj_get_style_y(bvm *vm); +extern int lvbe_obj_free_id(bvm *vm); +extern int lvbe_obj_get_child(bvm *vm); +extern int lvbe_obj_get_child_by_type(bvm *vm); +extern int lvbe_obj_get_child_count(bvm *vm); +extern int lvbe_obj_get_child_count(bvm *vm); +extern int lvbe_obj_get_child_count_by_type(bvm *vm); +extern int lvbe_obj_get_class(bvm *vm); +extern int lvbe_obj_get_click_area(bvm *vm); +extern int lvbe_obj_get_content_coords(bvm *vm); +extern int lvbe_obj_get_content_height(bvm *vm); +extern int lvbe_obj_get_content_width(bvm *vm); +extern int lvbe_obj_get_coords(bvm *vm); +extern int lvbe_obj_get_display(bvm *vm); +extern int lvbe_obj_get_display(bvm *vm); +extern int lvbe_obj_get_event_count(bvm *vm); +extern int lvbe_obj_get_group(bvm *vm); +extern int lvbe_obj_get_height(bvm *vm); +extern int lvbe_obj_get_index(bvm *vm); +extern int lvbe_obj_get_index_by_type(bvm *vm); +extern int lvbe_obj_get_parent(bvm *vm); +extern int lvbe_obj_get_screen(bvm *vm); +extern int lvbe_obj_get_scroll_bottom(bvm *vm); +extern int lvbe_obj_get_scroll_dir(bvm *vm); +extern int lvbe_obj_get_scroll_end(bvm *vm); +extern int lvbe_obj_get_scroll_left(bvm *vm); +extern int lvbe_obj_get_scroll_right(bvm *vm); +extern int lvbe_obj_get_scroll_snap_x(bvm *vm); +extern int lvbe_obj_get_scroll_snap_y(bvm *vm); +extern int lvbe_obj_get_scroll_top(bvm *vm); +extern int lvbe_obj_get_scroll_x(bvm *vm); +extern int lvbe_obj_get_scroll_y(bvm *vm); +extern int lvbe_obj_get_scrollbar_area(bvm *vm); +extern int lvbe_obj_get_scrollbar_mode(bvm *vm); +extern int lvbe_obj_get_self_height(bvm *vm); +extern int lvbe_obj_get_self_width(bvm *vm); +extern int lvbe_obj_get_sibling(bvm *vm); +extern int lvbe_obj_get_sibling_by_type(bvm *vm); +extern int lvbe_obj_get_state(bvm *vm); extern int lvbe_obj_get_style_align(bvm *vm); -extern int lvbe_obj_get_style_transform_width(bvm *vm); -extern int lvbe_obj_get_style_transform_height(bvm *vm); -extern int lvbe_obj_get_style_translate_x(bvm *vm); -extern int lvbe_obj_get_style_translate_y(bvm *vm); -extern int lvbe_obj_get_style_transform_zoom(bvm *vm); -extern int lvbe_obj_get_style_transform_angle(bvm *vm); -extern int lvbe_obj_get_style_transform_pivot_x(bvm *vm); -extern int lvbe_obj_get_style_transform_pivot_y(bvm *vm); -extern int lvbe_obj_get_style_pad_top(bvm *vm); -extern int lvbe_obj_get_style_pad_bottom(bvm *vm); -extern int lvbe_obj_get_style_pad_left(bvm *vm); -extern int lvbe_obj_get_style_pad_right(bvm *vm); -extern int lvbe_obj_get_style_pad_row(bvm *vm); -extern int lvbe_obj_get_style_pad_column(bvm *vm); +extern int lvbe_obj_get_style_anim(bvm *vm); +extern int lvbe_obj_get_style_anim_duration(bvm *vm); +extern int lvbe_obj_get_style_anim_duration(bvm *vm); +extern int lvbe_obj_get_style_arc_color(bvm *vm); +extern int lvbe_obj_get_style_arc_color_filtered(bvm *vm); +extern int lvbe_obj_get_style_arc_image_src(bvm *vm); +extern int lvbe_obj_get_style_arc_opa(bvm *vm); +extern int lvbe_obj_get_style_arc_rounded(bvm *vm); +extern int lvbe_obj_get_style_arc_width(bvm *vm); +extern int lvbe_obj_get_style_base_dir(bvm *vm); extern int lvbe_obj_get_style_bg_color(bvm *vm); extern int lvbe_obj_get_style_bg_color_filtered(bvm *vm); -extern int lvbe_obj_get_style_bg_opa(bvm *vm); +extern int lvbe_obj_get_style_bg_grad(bvm *vm); extern int lvbe_obj_get_style_bg_grad_color(bvm *vm); extern int lvbe_obj_get_style_bg_grad_color_filtered(bvm *vm); extern int lvbe_obj_get_style_bg_grad_dir(bvm *vm); -extern int lvbe_obj_get_style_bg_main_stop(bvm *vm); +extern int lvbe_obj_get_style_bg_grad_opa(bvm *vm); extern int lvbe_obj_get_style_bg_grad_stop(bvm *vm); -extern int lvbe_obj_get_style_bg_grad(bvm *vm); -extern int lvbe_obj_get_style_bg_dither_mode(bvm *vm); -extern int lvbe_obj_get_style_bg_img_src(bvm *vm); -extern int lvbe_obj_get_style_bg_img_opa(bvm *vm); -extern int lvbe_obj_get_style_bg_img_recolor(bvm *vm); -extern int lvbe_obj_get_style_bg_img_recolor_filtered(bvm *vm); -extern int lvbe_obj_get_style_bg_img_recolor_opa(bvm *vm); -extern int lvbe_obj_get_style_bg_img_tiled(bvm *vm); +extern int lvbe_obj_get_style_bg_image_opa(bvm *vm); +extern int lvbe_obj_get_style_bg_image_recolor(bvm *vm); +extern int lvbe_obj_get_style_bg_image_recolor_filtered(bvm *vm); +extern int lvbe_obj_get_style_bg_image_recolor_opa(bvm *vm); +extern int lvbe_obj_get_style_bg_image_src(bvm *vm); +extern int lvbe_obj_get_style_bg_image_tiled(bvm *vm); +extern int lvbe_obj_get_style_bg_main_opa(bvm *vm); +extern int lvbe_obj_get_style_bg_main_stop(bvm *vm); +extern int lvbe_obj_get_style_bg_opa(bvm *vm); +extern int lvbe_obj_get_style_blend_mode(bvm *vm); extern int lvbe_obj_get_style_border_color(bvm *vm); extern int lvbe_obj_get_style_border_color_filtered(bvm *vm); extern int lvbe_obj_get_style_border_opa(bvm *vm); -extern int lvbe_obj_get_style_border_width(bvm *vm); -extern int lvbe_obj_get_style_border_side(bvm *vm); extern int lvbe_obj_get_style_border_post(bvm *vm); -extern int lvbe_obj_get_style_outline_width(bvm *vm); -extern int lvbe_obj_get_style_outline_color(bvm *vm); -extern int lvbe_obj_get_style_outline_color_filtered(bvm *vm); -extern int lvbe_obj_get_style_outline_opa(bvm *vm); -extern int lvbe_obj_get_style_outline_pad(bvm *vm); -extern int lvbe_obj_get_style_shadow_width(bvm *vm); -extern int lvbe_obj_get_style_shadow_ofs_x(bvm *vm); -extern int lvbe_obj_get_style_shadow_ofs_y(bvm *vm); -extern int lvbe_obj_get_style_shadow_spread(bvm *vm); -extern int lvbe_obj_get_style_shadow_color(bvm *vm); -extern int lvbe_obj_get_style_shadow_color_filtered(bvm *vm); -extern int lvbe_obj_get_style_shadow_opa(bvm *vm); -extern int lvbe_obj_get_style_img_opa(bvm *vm); -extern int lvbe_obj_get_style_img_recolor(bvm *vm); -extern int lvbe_obj_get_style_img_recolor_filtered(bvm *vm); -extern int lvbe_obj_get_style_img_recolor_opa(bvm *vm); -extern int lvbe_obj_get_style_line_width(bvm *vm); -extern int lvbe_obj_get_style_line_dash_width(bvm *vm); -extern int lvbe_obj_get_style_line_dash_gap(bvm *vm); -extern int lvbe_obj_get_style_line_rounded(bvm *vm); -extern int lvbe_obj_get_style_line_color(bvm *vm); -extern int lvbe_obj_get_style_line_color_filtered(bvm *vm); -extern int lvbe_obj_get_style_line_opa(bvm *vm); -extern int lvbe_obj_get_style_arc_width(bvm *vm); -extern int lvbe_obj_get_style_arc_rounded(bvm *vm); -extern int lvbe_obj_get_style_arc_color(bvm *vm); -extern int lvbe_obj_get_style_arc_color_filtered(bvm *vm); -extern int lvbe_obj_get_style_arc_opa(bvm *vm); -extern int lvbe_obj_get_style_arc_img_src(bvm *vm); -extern int lvbe_obj_get_style_text_color(bvm *vm); -extern int lvbe_obj_get_style_text_color_filtered(bvm *vm); -extern int lvbe_obj_get_style_text_opa(bvm *vm); -extern int lvbe_obj_get_style_text_font(bvm *vm); -extern int lvbe_obj_get_style_text_letter_space(bvm *vm); -extern int lvbe_obj_get_style_text_line_space(bvm *vm); -extern int lvbe_obj_get_style_text_decor(bvm *vm); -extern int lvbe_obj_get_style_text_align(bvm *vm); -extern int lvbe_obj_get_style_radius(bvm *vm); +extern int lvbe_obj_get_style_border_side(bvm *vm); +extern int lvbe_obj_get_style_border_width(bvm *vm); extern int lvbe_obj_get_style_clip_corner(bvm *vm); -extern int lvbe_obj_get_style_opa(bvm *vm); -extern int lvbe_obj_get_style_opa_layered(bvm *vm); extern int lvbe_obj_get_style_color_filter_dsc(bvm *vm); extern int lvbe_obj_get_style_color_filter_opa(bvm *vm); -extern int lvbe_obj_get_style_anim(bvm *vm); -extern int lvbe_obj_get_style_anim_time(bvm *vm); -extern int lvbe_obj_get_style_anim_speed(bvm *vm); -extern int lvbe_obj_get_style_transition(bvm *vm); -extern int lvbe_obj_get_style_blend_mode(bvm *vm); -extern int lvbe_obj_get_style_layout(bvm *vm); -extern int lvbe_obj_get_style_base_dir(bvm *vm); -extern int lvbe_obj_set_style_width(bvm *vm); -extern int lvbe_obj_set_style_min_width(bvm *vm); -extern int lvbe_obj_set_style_max_width(bvm *vm); -extern int lvbe_obj_set_style_height(bvm *vm); -extern int lvbe_obj_set_style_min_height(bvm *vm); -extern int lvbe_obj_set_style_max_height(bvm *vm); -extern int lvbe_obj_set_style_x(bvm *vm); -extern int lvbe_obj_set_style_y(bvm *vm); -extern int lvbe_obj_set_style_align(bvm *vm); -extern int lvbe_obj_set_style_transform_width(bvm *vm); -extern int lvbe_obj_set_style_transform_height(bvm *vm); -extern int lvbe_obj_set_style_translate_x(bvm *vm); -extern int lvbe_obj_set_style_translate_y(bvm *vm); -extern int lvbe_obj_set_style_transform_zoom(bvm *vm); -extern int lvbe_obj_set_style_transform_angle(bvm *vm); -extern int lvbe_obj_set_style_transform_pivot_x(bvm *vm); -extern int lvbe_obj_set_style_transform_pivot_y(bvm *vm); -extern int lvbe_obj_set_style_pad_top(bvm *vm); -extern int lvbe_obj_set_style_pad_bottom(bvm *vm); -extern int lvbe_obj_set_style_pad_left(bvm *vm); -extern int lvbe_obj_set_style_pad_right(bvm *vm); -extern int lvbe_obj_set_style_pad_row(bvm *vm); -extern int lvbe_obj_set_style_pad_column(bvm *vm); -extern int lvbe_obj_set_style_bg_color(bvm *vm); -extern int lvbe_obj_set_style_bg_opa(bvm *vm); -extern int lvbe_obj_set_style_bg_grad_color(bvm *vm); -extern int lvbe_obj_set_style_bg_grad_dir(bvm *vm); -extern int lvbe_obj_set_style_bg_main_stop(bvm *vm); -extern int lvbe_obj_set_style_bg_grad_stop(bvm *vm); -extern int lvbe_obj_set_style_bg_grad(bvm *vm); -extern int lvbe_obj_set_style_bg_dither_mode(bvm *vm); -extern int lvbe_obj_set_style_bg_img_src(bvm *vm); -extern int lvbe_obj_set_style_bg_img_opa(bvm *vm); -extern int lvbe_obj_set_style_bg_img_recolor(bvm *vm); -extern int lvbe_obj_set_style_bg_img_recolor_opa(bvm *vm); -extern int lvbe_obj_set_style_bg_img_tiled(bvm *vm); -extern int lvbe_obj_set_style_border_color(bvm *vm); -extern int lvbe_obj_set_style_border_opa(bvm *vm); -extern int lvbe_obj_set_style_border_width(bvm *vm); -extern int lvbe_obj_set_style_border_side(bvm *vm); -extern int lvbe_obj_set_style_border_post(bvm *vm); -extern int lvbe_obj_set_style_outline_width(bvm *vm); -extern int lvbe_obj_set_style_outline_color(bvm *vm); -extern int lvbe_obj_set_style_outline_opa(bvm *vm); -extern int lvbe_obj_set_style_outline_pad(bvm *vm); -extern int lvbe_obj_set_style_shadow_width(bvm *vm); -extern int lvbe_obj_set_style_shadow_ofs_x(bvm *vm); -extern int lvbe_obj_set_style_shadow_ofs_y(bvm *vm); -extern int lvbe_obj_set_style_shadow_spread(bvm *vm); -extern int lvbe_obj_set_style_shadow_color(bvm *vm); -extern int lvbe_obj_set_style_shadow_opa(bvm *vm); -extern int lvbe_obj_set_style_img_opa(bvm *vm); -extern int lvbe_obj_set_style_img_recolor(bvm *vm); -extern int lvbe_obj_set_style_img_recolor_opa(bvm *vm); -extern int lvbe_obj_set_style_line_width(bvm *vm); -extern int lvbe_obj_set_style_line_dash_width(bvm *vm); -extern int lvbe_obj_set_style_line_dash_gap(bvm *vm); -extern int lvbe_obj_set_style_line_rounded(bvm *vm); -extern int lvbe_obj_set_style_line_color(bvm *vm); -extern int lvbe_obj_set_style_line_opa(bvm *vm); -extern int lvbe_obj_set_style_arc_width(bvm *vm); -extern int lvbe_obj_set_style_arc_rounded(bvm *vm); -extern int lvbe_obj_set_style_arc_color(bvm *vm); -extern int lvbe_obj_set_style_arc_opa(bvm *vm); -extern int lvbe_obj_set_style_arc_img_src(bvm *vm); -extern int lvbe_obj_set_style_text_color(bvm *vm); -extern int lvbe_obj_set_style_text_opa(bvm *vm); -extern int lvbe_obj_set_style_text_font(bvm *vm); -extern int lvbe_obj_set_style_text_letter_space(bvm *vm); -extern int lvbe_obj_set_style_text_line_space(bvm *vm); -extern int lvbe_obj_set_style_text_decor(bvm *vm); -extern int lvbe_obj_set_style_text_align(bvm *vm); -extern int lvbe_obj_set_style_radius(bvm *vm); -extern int lvbe_obj_set_style_clip_corner(bvm *vm); -extern int lvbe_obj_set_style_opa(bvm *vm); -extern int lvbe_obj_set_style_opa_layered(bvm *vm); -extern int lvbe_obj_set_style_color_filter_dsc(bvm *vm); -extern int lvbe_obj_set_style_color_filter_opa(bvm *vm); -extern int lvbe_obj_set_style_anim(bvm *vm); -extern int lvbe_obj_set_style_anim_time(bvm *vm); -extern int lvbe_obj_set_style_anim_speed(bvm *vm); -extern int lvbe_obj_set_style_transition(bvm *vm); -extern int lvbe_obj_set_style_blend_mode(bvm *vm); -extern int lvbe_obj_set_style_layout(bvm *vm); -extern int lvbe_obj_set_style_base_dir(bvm *vm); -extern int lvbe_obj_del(bvm *vm); -extern int lvbe_obj_clean(bvm *vm); -extern int lvbe_obj_del_delayed(bvm *vm); -extern int lvbe_obj_del_async(bvm *vm); -extern int lvbe_obj_set_parent(bvm *vm); -extern int lvbe_obj_swap(bvm *vm); -extern int lvbe_obj_move_to_index(bvm *vm); -extern int lvbe_obj_get_screen(bvm *vm); -extern int lvbe_obj_get_disp(bvm *vm); -extern int lvbe_obj_get_parent(bvm *vm); -extern int lvbe_obj_get_child(bvm *vm); -extern int lvbe_obj_get_child_cnt(bvm *vm); -extern int lvbe_obj_get_index(bvm *vm); -extern int lvbe_obj_tree_walk(bvm *vm); -extern int lvbe_obj_set_flex_flow(bvm *vm); -extern int lvbe_obj_set_flex_align(bvm *vm); -extern int lvbe_obj_set_flex_grow(bvm *vm); -extern int lvbe_obj_set_style_flex_flow(bvm *vm); -extern int lvbe_obj_set_style_flex_main_place(bvm *vm); -extern int lvbe_obj_set_style_flex_cross_place(bvm *vm); -extern int lvbe_obj_set_style_flex_track_place(bvm *vm); -extern int lvbe_obj_set_style_flex_grow(bvm *vm); -extern int lvbe_obj_get_style_flex_flow(bvm *vm); -extern int lvbe_obj_get_style_flex_main_place(bvm *vm); extern int lvbe_obj_get_style_flex_cross_place(bvm *vm); -extern int lvbe_obj_get_style_flex_track_place(bvm *vm); +extern int lvbe_obj_get_style_flex_flow(bvm *vm); extern int lvbe_obj_get_style_flex_grow(bvm *vm); -extern int lvbe_obj_set_grid_dsc_array(bvm *vm); -extern int lvbe_obj_set_grid_align(bvm *vm); -extern int lvbe_obj_set_grid_cell(bvm *vm); -extern int lvbe_obj_set_style_grid_row_dsc_array(bvm *vm); -extern int lvbe_obj_set_style_grid_column_dsc_array(bvm *vm); -extern int lvbe_obj_set_style_grid_row_align(bvm *vm); -extern int lvbe_obj_set_style_grid_column_align(bvm *vm); -extern int lvbe_obj_set_style_grid_cell_column_pos(bvm *vm); -extern int lvbe_obj_set_style_grid_cell_column_span(bvm *vm); -extern int lvbe_obj_set_style_grid_cell_row_pos(bvm *vm); -extern int lvbe_obj_set_style_grid_cell_row_span(bvm *vm); -extern int lvbe_obj_set_style_grid_cell_x_align(bvm *vm); -extern int lvbe_obj_set_style_grid_cell_y_align(bvm *vm); -extern int lvbe_obj_get_style_grid_row_dsc_array(bvm *vm); -extern int lvbe_obj_get_style_grid_column_dsc_array(bvm *vm); -extern int lvbe_obj_get_style_grid_row_align(bvm *vm); -extern int lvbe_obj_get_style_grid_column_align(bvm *vm); +extern int lvbe_obj_get_style_flex_main_place(bvm *vm); +extern int lvbe_obj_get_style_flex_track_place(bvm *vm); extern int lvbe_obj_get_style_grid_cell_column_pos(bvm *vm); extern int lvbe_obj_get_style_grid_cell_column_span(bvm *vm); extern int lvbe_obj_get_style_grid_cell_row_pos(bvm *vm); extern int lvbe_obj_get_style_grid_cell_row_span(bvm *vm); extern int lvbe_obj_get_style_grid_cell_x_align(bvm *vm); extern int lvbe_obj_get_style_grid_cell_y_align(bvm *vm); -extern int lvbe_obj_set_tile(bvm *vm); -extern int lvbe_obj_set_tile_id(bvm *vm); -extern int lvbe_obj_move_foreground(bvm *vm); +extern int lvbe_obj_get_style_grid_column_align(bvm *vm); +extern int lvbe_obj_get_style_grid_column_dsc_array(bvm *vm); +extern int lvbe_obj_get_style_grid_row_align(bvm *vm); +extern int lvbe_obj_get_style_grid_row_dsc_array(bvm *vm); +extern int lvbe_obj_get_style_height(bvm *vm); +extern int lvbe_obj_get_style_image_opa(bvm *vm); +extern int lvbe_obj_get_style_image_recolor(bvm *vm); +extern int lvbe_obj_get_style_image_recolor_filtered(bvm *vm); +extern int lvbe_obj_get_style_image_recolor_opa(bvm *vm); +extern int lvbe_obj_get_style_image_opa(bvm *vm); +extern int lvbe_obj_get_style_image_recolor(bvm *vm); +extern int lvbe_obj_get_style_image_recolor_filtered(bvm *vm); +extern int lvbe_obj_get_style_image_recolor_opa(bvm *vm); +extern int lvbe_obj_get_style_layout(bvm *vm); +extern int lvbe_obj_get_style_length(bvm *vm); +extern int lvbe_obj_get_style_line_color(bvm *vm); +extern int lvbe_obj_get_style_line_color_filtered(bvm *vm); +extern int lvbe_obj_get_style_line_dash_gap(bvm *vm); +extern int lvbe_obj_get_style_line_dash_width(bvm *vm); +extern int lvbe_obj_get_style_line_opa(bvm *vm); +extern int lvbe_obj_get_style_line_rounded(bvm *vm); +extern int lvbe_obj_get_style_line_width(bvm *vm); +extern int lvbe_obj_get_style_margin_bottom(bvm *vm); +extern int lvbe_obj_get_style_margin_left(bvm *vm); +extern int lvbe_obj_get_style_margin_right(bvm *vm); +extern int lvbe_obj_get_style_margin_top(bvm *vm); +extern int lvbe_obj_get_style_max_height(bvm *vm); +extern int lvbe_obj_get_style_max_width(bvm *vm); +extern int lvbe_obj_get_style_min_height(bvm *vm); +extern int lvbe_obj_get_style_min_width(bvm *vm); +extern int lvbe_obj_get_style_opa(bvm *vm); +extern int lvbe_obj_get_style_opa_layered(bvm *vm); +extern int lvbe_obj_get_style_opa_recursive(bvm *vm); +extern int lvbe_obj_get_style_outline_color(bvm *vm); +extern int lvbe_obj_get_style_outline_color_filtered(bvm *vm); +extern int lvbe_obj_get_style_outline_opa(bvm *vm); +extern int lvbe_obj_get_style_outline_pad(bvm *vm); +extern int lvbe_obj_get_style_outline_width(bvm *vm); +extern int lvbe_obj_get_style_pad_bottom(bvm *vm); +extern int lvbe_obj_get_style_pad_column(bvm *vm); +extern int lvbe_obj_get_style_pad_left(bvm *vm); +extern int lvbe_obj_get_style_pad_right(bvm *vm); +extern int lvbe_obj_get_style_pad_row(bvm *vm); +extern int lvbe_obj_get_style_pad_top(bvm *vm); +extern int lvbe_obj_get_style_prop(bvm *vm); +extern int lvbe_obj_get_style_radius(bvm *vm); +extern int lvbe_obj_get_style_shadow_color(bvm *vm); +extern int lvbe_obj_get_style_shadow_color_filtered(bvm *vm); +extern int lvbe_obj_get_style_shadow_offset_x(bvm *vm); +extern int lvbe_obj_get_style_shadow_offset_y(bvm *vm); +extern int lvbe_obj_get_style_shadow_offset_x(bvm *vm); +extern int lvbe_obj_get_style_shadow_offset_y(bvm *vm); +extern int lvbe_obj_get_style_shadow_opa(bvm *vm); +extern int lvbe_obj_get_style_shadow_spread(bvm *vm); +extern int lvbe_obj_get_style_shadow_width(bvm *vm); +extern int lvbe_obj_get_style_space_bottom(bvm *vm); +extern int lvbe_obj_get_style_space_left(bvm *vm); +extern int lvbe_obj_get_style_space_right(bvm *vm); +extern int lvbe_obj_get_style_space_top(bvm *vm); +extern int lvbe_obj_get_style_text_align(bvm *vm); +extern int lvbe_obj_get_style_text_color(bvm *vm); +extern int lvbe_obj_get_style_text_color_filtered(bvm *vm); +extern int lvbe_obj_get_style_text_decor(bvm *vm); +extern int lvbe_obj_get_style_text_font(bvm *vm); +extern int lvbe_obj_get_style_text_letter_space(bvm *vm); +extern int lvbe_obj_get_style_text_line_space(bvm *vm); +extern int lvbe_obj_get_style_text_opa(bvm *vm); +extern int lvbe_obj_get_style_transform_rotation(bvm *vm); +extern int lvbe_obj_get_style_transform_height(bvm *vm); +extern int lvbe_obj_get_style_transform_pivot_x(bvm *vm); +extern int lvbe_obj_get_style_transform_pivot_y(bvm *vm); +extern int lvbe_obj_get_style_transform_rotation(bvm *vm); +extern int lvbe_obj_get_style_transform_scale_x(bvm *vm); +extern int lvbe_obj_get_style_transform_scale_x_safe(bvm *vm); +extern int lvbe_obj_get_style_transform_scale_y(bvm *vm); +extern int lvbe_obj_get_style_transform_scale_y_safe(bvm *vm); +extern int lvbe_obj_get_style_transform_skew_x(bvm *vm); +extern int lvbe_obj_get_style_transform_skew_y(bvm *vm); +extern int lvbe_obj_get_style_transform_width(bvm *vm); +extern int lvbe_obj_get_style_transition(bvm *vm); +extern int lvbe_obj_get_style_translate_x(bvm *vm); +extern int lvbe_obj_get_style_translate_y(bvm *vm); +extern int lvbe_obj_get_style_width(bvm *vm); +extern int lvbe_obj_get_style_x(bvm *vm); +extern int lvbe_obj_get_style_y(bvm *vm); +extern int lvbe_obj_get_transformed_area(bvm *vm); +extern int lvbe_obj_get_user_data(bvm *vm); +extern int lvbe_obj_get_width(bvm *vm); +extern int lvbe_obj_get_width(bvm *vm); +extern int lvbe_obj_get_x(bvm *vm); +extern int lvbe_obj_get_x2(bvm *vm); +extern int lvbe_obj_get_x_aligned(bvm *vm); +extern int lvbe_obj_get_y(bvm *vm); +extern int lvbe_obj_get_y2(bvm *vm); +extern int lvbe_obj_get_y_aligned(bvm *vm); +extern int lvbe_obj_has_class(bvm *vm); +extern int lvbe_obj_has_flag(bvm *vm); +extern int lvbe_obj_has_flag_any(bvm *vm); +extern int lvbe_obj_has_state(bvm *vm); +extern int lvbe_obj_has_style_prop(bvm *vm); +extern int lvbe_obj_hit_test(bvm *vm); +extern int lvbe_obj_init_draw_arc_dsc(bvm *vm); +extern int lvbe_obj_init_draw_image_dsc(bvm *vm); +extern int lvbe_obj_init_draw_label_dsc(bvm *vm); +extern int lvbe_obj_init_draw_line_dsc(bvm *vm); +extern int lvbe_obj_init_draw_rect_dsc(bvm *vm); +extern int lvbe_obj_invalidate(bvm *vm); +extern int lvbe_obj_invalidate_area(bvm *vm); +extern int lvbe_obj_is_editable(bvm *vm); +extern int lvbe_obj_is_group_def(bvm *vm); +extern int lvbe_obj_is_layout_positioned(bvm *vm); +extern int lvbe_obj_is_scrolling(bvm *vm); +extern int lvbe_obj_is_valid(bvm *vm); +extern int lvbe_obj_is_visible(bvm *vm); +extern int lvbe_obj_mark_layout_as_dirty(bvm *vm); extern int lvbe_obj_move_background(bvm *vm); -extern int lvbe_obj_get_child_id(bvm *vm); +extern int lvbe_obj_move_children_by(bvm *vm); +extern int lvbe_obj_move_foreground(bvm *vm); +extern int lvbe_obj_move_to(bvm *vm); +extern int lvbe_obj_move_to_index(bvm *vm); +extern int lvbe_obj_readjust_scroll(bvm *vm); +extern int lvbe_obj_refr_pos(bvm *vm); +extern int lvbe_obj_refr_size(bvm *vm); +extern int lvbe_obj_refresh_ext_draw_size(bvm *vm); +extern int lvbe_obj_refresh_self_size(bvm *vm); +extern int lvbe_obj_refresh_style(bvm *vm); +extern int lvbe_obj_delete(bvm *vm); +extern int lvbe_obj_remove_event(bvm *vm); +extern int lvbe_obj_remove_event_cb(bvm *vm); +extern int lvbe_obj_remove_event_cb_with_user_data(bvm *vm); +extern int lvbe_obj_remove_flag(bvm *vm); +extern int lvbe_obj_remove_local_style_prop(bvm *vm); +extern int lvbe_obj_remove_state(bvm *vm); +extern int lvbe_obj_remove_style(bvm *vm); +extern int lvbe_obj_remove_style_all(bvm *vm); +extern int lvbe_obj_replace_style(bvm *vm); +extern int lvbe_obj_scroll_by(bvm *vm); +extern int lvbe_obj_scroll_by_bounded(bvm *vm); +extern int lvbe_obj_scroll_to(bvm *vm); +extern int lvbe_obj_scroll_to_view(bvm *vm); +extern int lvbe_obj_scroll_to_view_recursive(bvm *vm); +extern int lvbe_obj_scroll_to_x(bvm *vm); +extern int lvbe_obj_scroll_to_y(bvm *vm); +extern int lvbe_obj_scrollbar_invalidate(bvm *vm); +extern int lvbe_obj_send_event(bvm *vm); +extern int lvbe_obj_send_event(bvm *vm); +extern int lvbe_obj_set_align(bvm *vm); +extern int lvbe_obj_set_content_height(bvm *vm); +extern int lvbe_obj_set_content_width(bvm *vm); +extern int lvbe_obj_set_ext_click_area(bvm *vm); +extern int lvbe_obj_set_height(bvm *vm); +extern int lvbe_obj_set_layout(bvm *vm); +extern int lvbe_obj_set_local_style_prop(bvm *vm); +extern int lvbe_obj_set_parent(bvm *vm); +extern int lvbe_obj_set_pos(bvm *vm); +extern int lvbe_obj_set_scroll_dir(bvm *vm); +extern int lvbe_obj_set_scroll_snap_x(bvm *vm); +extern int lvbe_obj_set_scroll_snap_y(bvm *vm); +extern int lvbe_obj_set_scrollbar_mode(bvm *vm); +extern int lvbe_obj_set_size(bvm *vm); +extern int lvbe_obj_set_state(bvm *vm); +extern int lvbe_obj_set_style_align(bvm *vm); +extern int lvbe_obj_set_style_anim(bvm *vm); +extern int lvbe_obj_set_style_anim_duration(bvm *vm); +extern int lvbe_obj_set_style_anim_duration(bvm *vm); +extern int lvbe_obj_set_style_arc_color(bvm *vm); +extern int lvbe_obj_set_style_arc_image_src(bvm *vm); +extern int lvbe_obj_set_style_arc_opa(bvm *vm); +extern int lvbe_obj_set_style_arc_rounded(bvm *vm); +extern int lvbe_obj_set_style_arc_width(bvm *vm); +extern int lvbe_obj_set_style_base_dir(bvm *vm); +extern int lvbe_obj_set_style_bg_color(bvm *vm); +extern int lvbe_obj_set_style_bg_grad(bvm *vm); +extern int lvbe_obj_set_style_bg_grad_color(bvm *vm); +extern int lvbe_obj_set_style_bg_grad_dir(bvm *vm); +extern int lvbe_obj_set_style_bg_grad_opa(bvm *vm); +extern int lvbe_obj_set_style_bg_grad_stop(bvm *vm); +extern int lvbe_obj_set_style_bg_image_opa(bvm *vm); +extern int lvbe_obj_set_style_bg_image_recolor(bvm *vm); +extern int lvbe_obj_set_style_bg_image_recolor_opa(bvm *vm); +extern int lvbe_obj_set_style_bg_image_src(bvm *vm); +extern int lvbe_obj_set_style_bg_image_tiled(bvm *vm); +extern int lvbe_obj_set_style_bg_main_opa(bvm *vm); +extern int lvbe_obj_set_style_bg_main_stop(bvm *vm); +extern int lvbe_obj_set_style_bg_opa(bvm *vm); +extern int lvbe_obj_set_style_blend_mode(bvm *vm); +extern int lvbe_obj_set_style_border_color(bvm *vm); +extern int lvbe_obj_set_style_border_opa(bvm *vm); +extern int lvbe_obj_set_style_border_post(bvm *vm); +extern int lvbe_obj_set_style_border_side(bvm *vm); +extern int lvbe_obj_set_style_border_width(bvm *vm); +extern int lvbe_obj_set_style_clip_corner(bvm *vm); +extern int lvbe_obj_set_style_color_filter_dsc(bvm *vm); +extern int lvbe_obj_set_style_color_filter_opa(bvm *vm); +extern int lvbe_obj_set_style_flex_cross_place(bvm *vm); +extern int lvbe_obj_set_style_flex_flow(bvm *vm); +extern int lvbe_obj_set_style_flex_grow(bvm *vm); +extern int lvbe_obj_set_style_flex_main_place(bvm *vm); +extern int lvbe_obj_set_style_flex_track_place(bvm *vm); +extern int lvbe_obj_set_style_grid_cell_column_pos(bvm *vm); +extern int lvbe_obj_set_style_grid_cell_column_span(bvm *vm); +extern int lvbe_obj_set_style_grid_cell_row_pos(bvm *vm); +extern int lvbe_obj_set_style_grid_cell_row_span(bvm *vm); +extern int lvbe_obj_set_style_grid_cell_x_align(bvm *vm); +extern int lvbe_obj_set_style_grid_cell_y_align(bvm *vm); +extern int lvbe_obj_set_style_grid_column_align(bvm *vm); +extern int lvbe_obj_set_style_grid_column_dsc_array(bvm *vm); +extern int lvbe_obj_set_style_grid_row_align(bvm *vm); +extern int lvbe_obj_set_style_grid_row_dsc_array(bvm *vm); +extern int lvbe_obj_set_style_height(bvm *vm); +extern int lvbe_obj_set_style_image_opa(bvm *vm); +extern int lvbe_obj_set_style_image_recolor(bvm *vm); +extern int lvbe_obj_set_style_image_recolor_opa(bvm *vm); +extern int lvbe_obj_set_style_image_opa(bvm *vm); +extern int lvbe_obj_set_style_image_recolor(bvm *vm); +extern int lvbe_obj_set_style_image_recolor_opa(bvm *vm); +extern int lvbe_obj_set_style_layout(bvm *vm); +extern int lvbe_obj_set_style_length(bvm *vm); +extern int lvbe_obj_set_style_line_color(bvm *vm); +extern int lvbe_obj_set_style_line_dash_gap(bvm *vm); +extern int lvbe_obj_set_style_line_dash_width(bvm *vm); +extern int lvbe_obj_set_style_line_opa(bvm *vm); +extern int lvbe_obj_set_style_line_rounded(bvm *vm); +extern int lvbe_obj_set_style_line_width(bvm *vm); +extern int lvbe_obj_set_style_margin_all(bvm *vm); +extern int lvbe_obj_set_style_margin_bottom(bvm *vm); +extern int lvbe_obj_set_style_margin_hor(bvm *vm); +extern int lvbe_obj_set_style_margin_left(bvm *vm); +extern int lvbe_obj_set_style_margin_right(bvm *vm); +extern int lvbe_obj_set_style_margin_top(bvm *vm); +extern int lvbe_obj_set_style_margin_ver(bvm *vm); +extern int lvbe_obj_set_style_max_height(bvm *vm); +extern int lvbe_obj_set_style_max_width(bvm *vm); +extern int lvbe_obj_set_style_min_height(bvm *vm); +extern int lvbe_obj_set_style_min_width(bvm *vm); +extern int lvbe_obj_set_style_opa(bvm *vm); +extern int lvbe_obj_set_style_opa_layered(bvm *vm); +extern int lvbe_obj_set_style_outline_color(bvm *vm); +extern int lvbe_obj_set_style_outline_opa(bvm *vm); +extern int lvbe_obj_set_style_outline_pad(bvm *vm); +extern int lvbe_obj_set_style_outline_width(bvm *vm); +extern int lvbe_obj_set_style_pad_all(bvm *vm); +extern int lvbe_obj_set_style_pad_bottom(bvm *vm); +extern int lvbe_obj_set_style_pad_column(bvm *vm); +extern int lvbe_obj_set_style_pad_gap(bvm *vm); +extern int lvbe_obj_set_style_pad_hor(bvm *vm); +extern int lvbe_obj_set_style_pad_left(bvm *vm); +extern int lvbe_obj_set_style_pad_right(bvm *vm); +extern int lvbe_obj_set_style_pad_row(bvm *vm); +extern int lvbe_obj_set_style_pad_top(bvm *vm); +extern int lvbe_obj_set_style_pad_ver(bvm *vm); +extern int lvbe_obj_set_style_radius(bvm *vm); +extern int lvbe_obj_set_style_shadow_color(bvm *vm); +extern int lvbe_obj_set_style_shadow_offset_x(bvm *vm); +extern int lvbe_obj_set_style_shadow_offset_y(bvm *vm); +extern int lvbe_obj_set_style_shadow_offset_x(bvm *vm); +extern int lvbe_obj_set_style_shadow_offset_y(bvm *vm); +extern int lvbe_obj_set_style_shadow_opa(bvm *vm); +extern int lvbe_obj_set_style_shadow_spread(bvm *vm); +extern int lvbe_obj_set_style_shadow_width(bvm *vm); +extern int lvbe_obj_set_style_size(bvm *vm); +extern int lvbe_obj_set_style_text_align(bvm *vm); +extern int lvbe_obj_set_style_text_color(bvm *vm); +extern int lvbe_obj_set_style_text_decor(bvm *vm); +extern int lvbe_obj_set_style_text_font(bvm *vm); +extern int lvbe_obj_set_style_text_letter_space(bvm *vm); +extern int lvbe_obj_set_style_text_line_space(bvm *vm); +extern int lvbe_obj_set_style_text_opa(bvm *vm); +extern int lvbe_obj_set_style_transform_rotation(bvm *vm); +extern int lvbe_obj_set_style_transform_height(bvm *vm); +extern int lvbe_obj_set_style_transform_pivot_x(bvm *vm); +extern int lvbe_obj_set_style_transform_pivot_y(bvm *vm); +extern int lvbe_obj_set_style_transform_rotation(bvm *vm); +extern int lvbe_obj_set_style_transform_scale(bvm *vm); +extern int lvbe_obj_set_style_transform_scale_x(bvm *vm); +extern int lvbe_obj_set_style_transform_scale_y(bvm *vm); +extern int lvbe_obj_set_style_transform_skew_x(bvm *vm); +extern int lvbe_obj_set_style_transform_skew_y(bvm *vm); +extern int lvbe_obj_set_style_transform_width(bvm *vm); +extern int lvbe_obj_set_style_transform_scale(bvm *vm); +extern int lvbe_obj_set_style_transition(bvm *vm); +extern int lvbe_obj_set_style_translate_x(bvm *vm); +extern int lvbe_obj_set_style_translate_y(bvm *vm); +extern int lvbe_obj_set_style_width(bvm *vm); +extern int lvbe_obj_set_style_x(bvm *vm); +extern int lvbe_obj_set_style_y(bvm *vm); +extern int lvbe_obj_set_user_data(bvm *vm); +extern int lvbe_obj_set_width(bvm *vm); +extern int lvbe_obj_set_x(bvm *vm); +extern int lvbe_obj_set_y(bvm *vm); +extern int lvbe_obj_stringify_id(bvm *vm); +extern int lvbe_obj_swap(bvm *vm); +extern int lvbe_obj_transform_point(bvm *vm); +extern int lvbe_obj_update_flag(bvm *vm); +extern int lvbe_obj_update_layout(bvm *vm); +extern int lvbe_obj_update_snap(bvm *vm); -/* `lv_group` external functions definitions */ -extern int lvbe_group_create(bvm *vm); -extern int lvbe_group_del(bvm *vm); -extern int lvbe_group_set_default(bvm *vm); -extern int lvbe_group_add_obj(bvm *vm); -extern int lvbe_group_swap_obj(bvm *vm); -extern int lvbe_group_remove_obj(bvm *vm); -extern int lvbe_group_remove_all_objs(bvm *vm); -extern int lvbe_group_focus_obj(bvm *vm); -extern int lvbe_group_focus_next(bvm *vm); -extern int lvbe_group_focus_prev(bvm *vm); -extern int lvbe_group_focus_freeze(bvm *vm); -extern int lvbe_group_send_data(bvm *vm); -extern int lvbe_group_set_focus_cb(bvm *vm); -extern int lvbe_group_set_edge_cb(bvm *vm); -extern int lvbe_group_set_refocus_policy(bvm *vm); -extern int lvbe_group_set_editing(bvm *vm); -extern int lvbe_group_set_wrap(bvm *vm); -extern int lvbe_group_get_focused(bvm *vm); -extern int lvbe_group_get_focus_cb(bvm *vm); -extern int lvbe_group_get_edge_cb(bvm *vm); -extern int lvbe_group_get_editing(bvm *vm); -extern int lvbe_group_get_wrap(bvm *vm); -extern int lvbe_group_get_obj_count(bvm *vm); +/* `lv_event` external functions definitions */ +extern int lvbe_event_get_code(bvm *vm); +extern int lvbe_event_get_cover_area(bvm *vm); +extern int lvbe_event_get_current_target(bvm *vm); +extern int lvbe_event_get_current_target_obj(bvm *vm); +extern int lvbe_event_get_hit_test_info(bvm *vm); +extern int lvbe_event_get_indev(bvm *vm); +extern int lvbe_event_get_key(bvm *vm); +extern int lvbe_event_get_layer(bvm *vm); +extern int lvbe_event_get_old_size(bvm *vm); +extern int lvbe_event_get_param(bvm *vm); +extern int lvbe_event_get_scroll_anim(bvm *vm); +extern int lvbe_event_get_self_size_info(bvm *vm); +extern int lvbe_event_get_target(bvm *vm); +extern int lvbe_event_get_target_obj(bvm *vm); +extern int lvbe_event_get_user_data(bvm *vm); +extern int lvbe_event_set_cover_res(bvm *vm); +extern int lvbe_event_set_ext_draw_size(bvm *vm); +extern int lvbe_event_stop_bubbling(bvm *vm); +extern int lvbe_event_stop_processing(bvm *vm); + +/* `lv_display` external functions definitions */ +extern int lvbe_display_add_event_cb(bvm *vm); +extern int lvbe_display_delete(bvm *vm); +extern int lvbe_display_delete(bvm *vm); +extern int lvbe_display_delete_event(bvm *vm); +extern int lvbe_display_delete_refr_timer(bvm *vm); +extern int lvbe_display_dpx(bvm *vm); +extern int lvbe_display_enable_invalidation(bvm *vm); +extern int lvbe_display_enable_invalidation(bvm *vm); +extern int lvbe_display_get_rotation(bvm *vm); +extern int lvbe_display_get_antialiasing(bvm *vm); +extern int lvbe_display_get_antialiasing(bvm *vm); +extern int lvbe_display_get_color_format(bvm *vm); +extern int lvbe_display_get_dpi(bvm *vm); +extern int lvbe_display_get_dpi(bvm *vm); +extern int lvbe_display_get_driver_data(bvm *vm); +extern int lvbe_display_get_event_count(bvm *vm); +extern int lvbe_display_get_horizontal_resolution(bvm *vm); +extern int lvbe_display_get_horizontal_resolution(bvm *vm); +extern int lvbe_display_get_inactive_time(bvm *vm); +extern int lvbe_display_get_inactive_time(bvm *vm); +extern int lvbe_display_get_layer_bottom(bvm *vm); +extern int lvbe_display_get_layer_sys(bvm *vm); +extern int lvbe_display_get_layer_sys(bvm *vm); +extern int lvbe_display_get_layer_top(bvm *vm); +extern int lvbe_display_get_layer_top(bvm *vm); +extern int lvbe_display_get_next(bvm *vm); +extern int lvbe_display_get_next(bvm *vm); +extern int lvbe_display_get_offset_x(bvm *vm); +extern int lvbe_display_get_offset_x(bvm *vm); +extern int lvbe_display_get_offset_y(bvm *vm); +extern int lvbe_display_get_offset_y(bvm *vm); +extern int lvbe_display_get_physical_horizontal_resolution(bvm *vm); +extern int lvbe_display_get_physical_horizontal_resolution(bvm *vm); +extern int lvbe_display_get_physical_vertical_resolution(bvm *vm); +extern int lvbe_display_get_physical_vertical_resolution(bvm *vm); +extern int lvbe_display_get_refr_timer(bvm *vm); +extern int lvbe_display_get_rotation(bvm *vm); +extern int lvbe_display_get_rotation(bvm *vm); +extern int lvbe_display_get_screen_active(bvm *vm); +extern int lvbe_display_get_screen_prev(bvm *vm); +extern int lvbe_display_get_screen_active(bvm *vm); +extern int lvbe_display_get_screen_prev(bvm *vm); +extern int lvbe_display_get_theme(bvm *vm); +extern int lvbe_display_get_theme(bvm *vm); +extern int lvbe_display_get_user_data(bvm *vm); +extern int lvbe_display_get_vertical_resolution(bvm *vm); +extern int lvbe_display_get_vertical_resolution(bvm *vm); +extern int lvbe_display_is_double_buffered(bvm *vm); +extern int lvbe_display_is_invalidation_enabled(bvm *vm); +extern int lvbe_display_is_invalidation_enabled(bvm *vm); +extern int lvbe_display_delete(bvm *vm); +extern int lvbe_display_remove_event_cb_with_user_data(bvm *vm); +extern int lvbe_display_send_event(bvm *vm); +extern int lvbe_display_send_event(bvm *vm); +extern int lvbe_display_set_rotation(bvm *vm); +extern int lvbe_display_set_antialiasing(bvm *vm); +extern int lvbe_display_set_buffers(bvm *vm); +extern int lvbe_display_set_color_format(bvm *vm); +extern int lvbe_display_set_default(bvm *vm); +extern int lvbe_display_set_default(bvm *vm); +extern int lvbe_display_set_dpi(bvm *vm); +extern int lvbe_display_set_driver_data(bvm *vm); +extern int lvbe_display_set_offset(bvm *vm); +extern int lvbe_display_set_physical_resolution(bvm *vm); +extern int lvbe_display_set_render_mode(bvm *vm); +extern int lvbe_display_set_resolution(bvm *vm); +extern int lvbe_display_set_rotation(bvm *vm); +extern int lvbe_display_set_rotation(bvm *vm); +extern int lvbe_display_set_theme(bvm *vm); +extern int lvbe_display_set_theme(bvm *vm); +extern int lvbe_display_set_user_data(bvm *vm); +extern int lvbe_display_trigger_activity(bvm *vm); +extern int lvbe_display_trigger_activity(bvm *vm); /* `lv_indev` external functions definitions */ +extern int lvbe_indev_add_event_cb(bvm *vm); +extern int lvbe_indev_delete(bvm *vm); +extern int lvbe_indev_delete(bvm *vm); extern int lvbe_indev_enable(bvm *vm); -extern int lvbe_indev_get_type(bvm *vm); -extern int lvbe_indev_reset(bvm *vm); -extern int lvbe_indev_reset_long_press(bvm *vm); -extern int lvbe_indev_set_cursor(bvm *vm); -extern int lvbe_indev_set_group(bvm *vm); -extern int lvbe_indev_set_button_points(bvm *vm); -extern int lvbe_indev_get_point(bvm *vm); +extern int lvbe_indev_get_display(bvm *vm); +extern int lvbe_indev_get_display(bvm *vm); +extern int lvbe_indev_get_driver_data(bvm *vm); +extern int lvbe_indev_get_event_count(bvm *vm); extern int lvbe_indev_get_gesture_dir(bvm *vm); +extern int lvbe_indev_get_group(bvm *vm); extern int lvbe_indev_get_key(bvm *vm); +extern int lvbe_indev_get_mode(bvm *vm); +extern int lvbe_indev_get_next(bvm *vm); +extern int lvbe_indev_get_next(bvm *vm); +extern int lvbe_indev_get_point(bvm *vm); +extern int lvbe_indev_get_read_timer(bvm *vm); extern int lvbe_indev_get_scroll_dir(bvm *vm); extern int lvbe_indev_get_scroll_obj(bvm *vm); +extern int lvbe_indev_get_state(bvm *vm); +extern int lvbe_indev_get_type(bvm *vm); +extern int lvbe_indev_get_user_data(bvm *vm); extern int lvbe_indev_get_vect(bvm *vm); -extern int lvbe_indev_wait_release(bvm *vm); +extern int lvbe_indev_read(bvm *vm); +extern int lvbe_indev_delete(bvm *vm); +extern int lvbe_indev_remove_event(bvm *vm); +extern int lvbe_indev_remove_event_cb_with_user_data(bvm *vm); +extern int lvbe_indev_reset(bvm *vm); +extern int lvbe_indev_reset_long_press(bvm *vm); extern int lvbe_indev_search_obj(bvm *vm); +extern int lvbe_indev_send_event(bvm *vm); +extern int lvbe_indev_send_event(bvm *vm); +extern int lvbe_indev_set_button_points(bvm *vm); +extern int lvbe_indev_set_cursor(bvm *vm); +extern int lvbe_indev_set_display(bvm *vm); +extern int lvbe_indev_set_display(bvm *vm); +extern int lvbe_indev_set_driver_data(bvm *vm); +extern int lvbe_indev_set_group(bvm *vm); +extern int lvbe_indev_set_mode(bvm *vm); +extern int lvbe_indev_set_type(bvm *vm); +extern int lvbe_indev_set_user_data(bvm *vm); +extern int lvbe_indev_wait_release(bvm *vm); /* `lv_qrcode` external functions definitions */ extern int lvbe_qrcode_create(bvm *vm); +extern int lvbe_qrcode_set_dark_color(bvm *vm); +extern int lvbe_qrcode_set_light_color(bvm *vm); +extern int lvbe_qrcode_set_size(bvm *vm); extern int lvbe_qrcode_update(bvm *vm); -extern int lvbe_qrcode_delete(bvm *vm); - -/* `lv_chart` external functions definitions */ -extern int lvbe_chart_create(bvm *vm); -extern int lvbe_chart_set_type(bvm *vm); -extern int lvbe_chart_set_point_count(bvm *vm); -extern int lvbe_chart_set_range(bvm *vm); -extern int lvbe_chart_set_update_mode(bvm *vm); -extern int lvbe_chart_set_div_line_count(bvm *vm); -extern int lvbe_chart_set_zoom_x(bvm *vm); -extern int lvbe_chart_set_zoom_y(bvm *vm); -extern int lvbe_chart_get_zoom_x(bvm *vm); -extern int lvbe_chart_get_zoom_y(bvm *vm); -extern int lvbe_chart_set_axis_tick(bvm *vm); -extern int lvbe_chart_get_type(bvm *vm); -extern int lvbe_chart_get_point_count(bvm *vm); -extern int lvbe_chart_get_x_start_point(bvm *vm); -extern int lvbe_chart_get_point_pos_by_id(bvm *vm); -extern int lvbe_chart_refresh(bvm *vm); -extern int lvbe_chart_add_series(bvm *vm); -extern int lvbe_chart_remove_series(bvm *vm); -extern int lvbe_chart_hide_series(bvm *vm); -extern int lvbe_chart_set_series_color(bvm *vm); -extern int lvbe_chart_set_x_start_point(bvm *vm); -extern int lvbe_chart_get_series_next(bvm *vm); -extern int lvbe_chart_add_cursor(bvm *vm); -extern int lvbe_chart_set_cursor_pos(bvm *vm); -extern int lvbe_chart_set_cursor_point(bvm *vm); -extern int lvbe_chart_get_cursor_point(bvm *vm); -extern int lvbe_chart_set_all_value(bvm *vm); -extern int lvbe_chart_set_next_value(bvm *vm); -extern int lvbe_chart_set_next_value2(bvm *vm); -extern int lvbe_chart_set_value_by_id(bvm *vm); -extern int lvbe_chart_set_value_by_id2(bvm *vm); -extern int lvbe_chart_set_ext_y_array(bvm *vm); -extern int lvbe_chart_set_ext_x_array(bvm *vm); -extern int lvbe_chart_get_y_array(bvm *vm); -extern int lvbe_chart_get_x_array(bvm *vm); -extern int lvbe_chart_get_pressed_point(bvm *vm); - -/* `lv_colorwheel` external functions definitions */ -extern int lvbe_colorwheel_create(bvm *vm); -extern int lvbe_colorwheel_set_hsv(bvm *vm); -extern int lvbe_colorwheel_set_rgb(bvm *vm); -extern int lvbe_colorwheel_set_mode(bvm *vm); -extern int lvbe_colorwheel_set_mode_fixed(bvm *vm); -extern int lvbe_colorwheel_get_hsv(bvm *vm); -extern int lvbe_colorwheel_get_rgb(bvm *vm); -extern int lvbe_colorwheel_get_color_mode(bvm *vm); -extern int lvbe_colorwheel_get_color_mode_fixed(bvm *vm); - -/* `lv_imgbtn` external functions definitions */ -extern int lvbe_imgbtn_create(bvm *vm); -extern int lvbe_imgbtn_set_src(bvm *vm); -extern int lvbe_imgbtn_set_state(bvm *vm); - -/* `lv_keyboard` external functions definitions */ -extern int lvbe_keyboard_create(bvm *vm); -extern int lvbe_keyboard_set_textarea(bvm *vm); -extern int lvbe_keyboard_set_mode(bvm *vm); -extern int lvbe_keyboard_set_popovers(bvm *vm); -extern int lvbe_keyboard_set_map(bvm *vm); -extern int lvbe_keyboard_get_textarea(bvm *vm); -extern int lvbe_keyboard_get_mode(bvm *vm); -extern int lvbe_keyboard_get_map_array(bvm *vm); -extern int lvbe_keyboard_get_selected_btn(bvm *vm); -extern int lvbe_keyboard_get_btn_text(bvm *vm); - -/* `lv_btnmatrix` external functions definitions */ -extern int lvbe_btnmatrix_get_popovers(bvm *vm); -extern int lvbe_btnmatrix_create(bvm *vm); -extern int lvbe_btnmatrix_set_map(bvm *vm); -extern int lvbe_btnmatrix_set_ctrl_map(bvm *vm); -extern int lvbe_btnmatrix_set_selected_btn(bvm *vm); -extern int lvbe_btnmatrix_set_btn_ctrl(bvm *vm); -extern int lvbe_btnmatrix_clear_btn_ctrl(bvm *vm); -extern int lvbe_btnmatrix_set_btn_ctrl_all(bvm *vm); -extern int lvbe_btnmatrix_clear_btn_ctrl_all(bvm *vm); -extern int lvbe_btnmatrix_set_btn_width(bvm *vm); -extern int lvbe_btnmatrix_set_one_checked(bvm *vm); -extern int lvbe_btnmatrix_get_map(bvm *vm); -extern int lvbe_btnmatrix_get_selected_btn(bvm *vm); -extern int lvbe_btnmatrix_get_btn_text(bvm *vm); -extern int lvbe_btnmatrix_has_btn_ctrl(bvm *vm); -extern int lvbe_btnmatrix_get_one_checked(bvm *vm); - -/* `lv_led` external functions definitions */ -extern int lvbe_led_create(bvm *vm); -extern int lvbe_led_set_color(bvm *vm); -extern int lvbe_led_set_brightness(bvm *vm); -extern int lvbe_led_on(bvm *vm); -extern int lvbe_led_off(bvm *vm); -extern int lvbe_led_toggle(bvm *vm); -extern int lvbe_led_get_brightness(bvm *vm); - -/* `lv_list` external functions definitions */ -extern int lvbe_list_create(bvm *vm); -extern int lvbe_list_add_text(bvm *vm); -extern int lvbe_list_add_btn(bvm *vm); -extern int lvbe_list_get_btn_text(bvm *vm); - -/* `lv_meter` external functions definitions */ -extern int lvbe_meter_create(bvm *vm); -extern int lvbe_meter_add_scale(bvm *vm); -extern int lvbe_meter_set_scale_ticks(bvm *vm); -extern int lvbe_meter_set_scale_major_ticks(bvm *vm); -extern int lvbe_meter_set_scale_range(bvm *vm); -extern int lvbe_meter_add_needle_line(bvm *vm); -extern int lvbe_meter_add_needle_img(bvm *vm); -extern int lvbe_meter_add_arc(bvm *vm); -extern int lvbe_meter_add_scale_lines(bvm *vm); -extern int lvbe_meter_set_indicator_value(bvm *vm); -extern int lvbe_meter_set_indicator_start_value(bvm *vm); -extern int lvbe_meter_set_indicator_end_value(bvm *vm); - -/* `lv_msgbox` external functions definitions */ -extern int lvbe_msgbox_create(bvm *vm); -extern int lvbe_msgbox_get_title(bvm *vm); -extern int lvbe_msgbox_get_close_btn(bvm *vm); -extern int lvbe_msgbox_get_text(bvm *vm); -extern int lvbe_msgbox_get_content(bvm *vm); -extern int lvbe_msgbox_get_btns(bvm *vm); -extern int lvbe_msgbox_get_active_btn(bvm *vm); -extern int lvbe_msgbox_get_active_btn_text(bvm *vm); -extern int lvbe_msgbox_close(bvm *vm); -extern int lvbe_msgbox_close_async(bvm *vm); - -/* `lv_spinbox` external functions definitions */ -extern int lvbe_spinbox_create(bvm *vm); -extern int lvbe_spinbox_set_value(bvm *vm); -extern int lvbe_spinbox_set_rollover(bvm *vm); -extern int lvbe_spinbox_set_digit_format(bvm *vm); -extern int lvbe_spinbox_set_step(bvm *vm); -extern int lvbe_spinbox_set_range(bvm *vm); -extern int lvbe_spinbox_set_cursor_pos(bvm *vm); -extern int lvbe_spinbox_set_digit_step_direction(bvm *vm); -extern int lvbe_spinbox_get_rollover(bvm *vm); -extern int lvbe_spinbox_get_value(bvm *vm); -extern int lvbe_spinbox_get_step(bvm *vm); -extern int lvbe_spinbox_step_next(bvm *vm); -extern int lvbe_spinbox_step_prev(bvm *vm); -extern int lvbe_spinbox_increment(bvm *vm); -extern int lvbe_spinbox_decrement(bvm *vm); - -/* `lv_spinner` external functions definitions */ -extern int lvbe_spinner_create(bvm *vm); - -/* `lv_tabview` external functions definitions */ -extern int lvbe_tabview_create(bvm *vm); -extern int lvbe_tabview_add_tab(bvm *vm); -extern int lvbe_tabview_rename_tab(bvm *vm); -extern int lvbe_tabview_get_content(bvm *vm); -extern int lvbe_tabview_get_tab_btns(bvm *vm); -extern int lvbe_tabview_set_act(bvm *vm); -extern int lvbe_tabview_get_tab_act(bvm *vm); - -/* `lv_tileview` external functions definitions */ -extern int lvbe_tileview_create(bvm *vm); -extern int lvbe_tileview_add_tile(bvm *vm); -extern int lvbe_tileview_get_tile_act(bvm *vm); /* `lv_anim` external functions definitions */ -extern int lvbe_anim_init(bvm *vm); -extern int lvbe_anim_set_var(bvm *vm); -extern int lvbe_anim_set_exec_cb(bvm *vm); -extern int lvbe_anim_set_time(bvm *vm); -extern int lvbe_anim_set_delay(bvm *vm); -extern int lvbe_anim_set_values(bvm *vm); -extern int lvbe_anim_set_custom_exec_cb(bvm *vm); -extern int lvbe_anim_set_path_cb(bvm *vm); -extern int lvbe_anim_set_start_cb(bvm *vm); -extern int lvbe_anim_set_get_value_cb(bvm *vm); -extern int lvbe_anim_set_ready_cb(bvm *vm); -extern int lvbe_anim_set_deleted_cb(bvm *vm); -extern int lvbe_anim_set_playback_time(bvm *vm); -extern int lvbe_anim_set_playback_delay(bvm *vm); -extern int lvbe_anim_set_repeat_count(bvm *vm); -extern int lvbe_anim_set_repeat_delay(bvm *vm); -extern int lvbe_anim_set_early_apply(bvm *vm); -extern int lvbe_anim_set_user_data(bvm *vm); -extern int lvbe_anim_start(bvm *vm); +extern int lvbe_anim_custom_delete(bvm *vm); +extern int lvbe_anim_custom_get(bvm *vm); extern int lvbe_anim_get_delay(bvm *vm); extern int lvbe_anim_get_playtime(bvm *vm); +extern int lvbe_anim_get_repeat_count(bvm *vm); +extern int lvbe_anim_get_time(bvm *vm); extern int lvbe_anim_get_user_data(bvm *vm); -extern int lvbe_anim_custom_del(bvm *vm); -extern int lvbe_anim_custom_get(bvm *vm); +extern int lvbe_anim_init(bvm *vm); +extern int lvbe_anim_set_bezier3_param(bvm *vm); +extern int lvbe_anim_set_completed_cb(bvm *vm); +extern int lvbe_anim_set_custom_exec_cb(bvm *vm); +extern int lvbe_anim_set_delay(bvm *vm); +extern int lvbe_anim_set_duration(bvm *vm); +extern int lvbe_anim_set_early_apply(bvm *vm); +extern int lvbe_anim_set_exec_cb(bvm *vm); +extern int lvbe_anim_set_get_value_cb(bvm *vm); +extern int lvbe_anim_set_path_cb(bvm *vm); +extern int lvbe_anim_set_playback_delay(bvm *vm); +extern int lvbe_anim_set_playback_duration(bvm *vm); +extern int lvbe_anim_set_playback_time(bvm *vm); +extern int lvbe_anim_set_completed_cb(bvm *vm); +extern int lvbe_anim_set_repeat_count(bvm *vm); +extern int lvbe_anim_set_repeat_delay(bvm *vm); +extern int lvbe_anim_set_start_cb(bvm *vm); +extern int lvbe_anim_set_time(bvm *vm); +extern int lvbe_anim_set_user_data(bvm *vm); +extern int lvbe_anim_set_values(bvm *vm); +extern int lvbe_anim_set_var(bvm *vm); +extern int lvbe_anim_start(bvm *vm); /* `lv_timer` external functions definitions */ -extern int lvbe_timer_del(bvm *vm); +extern int lvbe_timer_delete(bvm *vm); +extern int lvbe_timer_delete(bvm *vm); +extern int lvbe_timer_get_next(bvm *vm); +extern int lvbe_timer_get_next(bvm *vm); +extern int lvbe_timer_get_paused(bvm *vm); +extern int lvbe_timer_get_user_data(bvm *vm); extern int lvbe_timer_pause(bvm *vm); +extern int lvbe_timer_ready(bvm *vm); +extern int lvbe_timer_delete(bvm *vm); +extern int lvbe_timer_reset(bvm *vm); extern int lvbe_timer_resume(bvm *vm); +extern int lvbe_timer_set_auto_delete(bvm *vm); extern int lvbe_timer_set_cb(bvm *vm); extern int lvbe_timer_set_period(bvm *vm); -extern int lvbe_timer_ready(bvm *vm); extern int lvbe_timer_set_repeat_count(bvm *vm); -extern int lvbe_timer_reset(bvm *vm); -extern int lvbe_timer_get_next(bvm *vm); +extern int lvbe_timer_set_user_data(bvm *vm); + +/* `lv_animimg` external functions definitions */ +extern int lvbe_animimg_create(bvm *vm); +extern int lvbe_animimg_get_duration(bvm *vm); +extern int lvbe_animimg_get_repeat_count(bvm *vm); +extern int lvbe_animimg_get_src_count(bvm *vm); +extern int lvbe_animimg_set_duration(bvm *vm); +extern int lvbe_animimg_set_repeat_count(bvm *vm); +extern int lvbe_animimg_set_src(bvm *vm); +extern int lvbe_animimg_start(bvm *vm); /* `lv_arc` external functions definitions */ -extern int lvbe_arc_create(bvm *vm); -extern int lvbe_arc_set_start_angle(bvm *vm); -extern int lvbe_arc_set_end_angle(bvm *vm); -extern int lvbe_arc_set_angles(bvm *vm); -extern int lvbe_arc_set_bg_start_angle(bvm *vm); -extern int lvbe_arc_set_bg_end_angle(bvm *vm); -extern int lvbe_arc_set_bg_angles(bvm *vm); -extern int lvbe_arc_set_rotation(bvm *vm); -extern int lvbe_arc_set_mode(bvm *vm); -extern int lvbe_arc_set_value(bvm *vm); -extern int lvbe_arc_set_range(bvm *vm); -extern int lvbe_arc_set_change_rate(bvm *vm); -extern int lvbe_arc_get_angle_start(bvm *vm); -extern int lvbe_arc_get_angle_end(bvm *vm); -extern int lvbe_arc_get_bg_angle_start(bvm *vm); -extern int lvbe_arc_get_bg_angle_end(bvm *vm); -extern int lvbe_arc_get_value(bvm *vm); -extern int lvbe_arc_get_min_value(bvm *vm); -extern int lvbe_arc_get_max_value(bvm *vm); -extern int lvbe_arc_get_mode(bvm *vm); extern int lvbe_arc_align_obj_to_angle(bvm *vm); +extern int lvbe_arc_create(bvm *vm); +extern int lvbe_arc_get_rotation(bvm *vm); +extern int lvbe_arc_get_angle_end(bvm *vm); +extern int lvbe_arc_get_angle_start(bvm *vm); +extern int lvbe_arc_get_bg_angle_end(bvm *vm); +extern int lvbe_arc_get_bg_angle_start(bvm *vm); +extern int lvbe_arc_get_knob_offset(bvm *vm); +extern int lvbe_arc_get_max_value(bvm *vm); +extern int lvbe_arc_get_min_value(bvm *vm); +extern int lvbe_arc_get_mode(bvm *vm); +extern int lvbe_arc_get_rotation(bvm *vm); +extern int lvbe_arc_get_rotation(bvm *vm); +extern int lvbe_arc_get_value(bvm *vm); extern int lvbe_arc_rotate_obj_to_angle(bvm *vm); +extern int lvbe_arc_set_rotation(bvm *vm); +extern int lvbe_arc_set_angles(bvm *vm); +extern int lvbe_arc_set_bg_angles(bvm *vm); +extern int lvbe_arc_set_bg_end_angle(bvm *vm); +extern int lvbe_arc_set_bg_start_angle(bvm *vm); +extern int lvbe_arc_set_change_rate(bvm *vm); +extern int lvbe_arc_set_end_angle(bvm *vm); +extern int lvbe_arc_set_knob_offset(bvm *vm); +extern int lvbe_arc_set_mode(bvm *vm); +extern int lvbe_arc_set_range(bvm *vm); +extern int lvbe_arc_set_rotation(bvm *vm); +extern int lvbe_arc_set_rotation(bvm *vm); +extern int lvbe_arc_set_start_angle(bvm *vm); +extern int lvbe_arc_set_value(bvm *vm); /* `lv_bar` external functions definitions */ extern int lvbe_bar_create(bvm *vm); -extern int lvbe_bar_set_value(bvm *vm); -extern int lvbe_bar_set_start_value(bvm *vm); -extern int lvbe_bar_set_range(bvm *vm); -extern int lvbe_bar_set_mode(bvm *vm); -extern int lvbe_bar_get_value(bvm *vm); -extern int lvbe_bar_get_start_value(bvm *vm); -extern int lvbe_bar_get_min_value(bvm *vm); extern int lvbe_bar_get_max_value(bvm *vm); +extern int lvbe_bar_get_min_value(bvm *vm); extern int lvbe_bar_get_mode(bvm *vm); +extern int lvbe_bar_get_start_value(bvm *vm); +extern int lvbe_bar_get_value(bvm *vm); +extern int lvbe_bar_is_symmetrical(bvm *vm); +extern int lvbe_bar_set_mode(bvm *vm); +extern int lvbe_bar_set_range(bvm *vm); +extern int lvbe_bar_set_start_value(bvm *vm); +extern int lvbe_bar_set_value(bvm *vm); -/* `lv_btn` external functions definitions */ -extern int lvbe_btn_create(bvm *vm); +/* `lv_button` external functions definitions */ +extern int lvbe_button_create(bvm *vm); + +/* `lv_buttonmatrix` external functions definitions */ +extern int lvbe_buttonmatrix_get_button_text(bvm *vm); +extern int lvbe_buttonmatrix_clear_button_ctrl(bvm *vm); +extern int lvbe_buttonmatrix_clear_button_ctrl_all(bvm *vm); +extern int lvbe_buttonmatrix_create(bvm *vm); +extern int lvbe_buttonmatrix_get_button_text(bvm *vm); +extern int lvbe_buttonmatrix_get_map(bvm *vm); +extern int lvbe_buttonmatrix_get_one_checked(bvm *vm); +extern int lvbe_buttonmatrix_get_popovers(bvm *vm); +extern int lvbe_buttonmatrix_get_selected_button(bvm *vm); +extern int lvbe_buttonmatrix_has_button_ctrl(bvm *vm); +extern int lvbe_buttonmatrix_set_button_ctrl(bvm *vm); +extern int lvbe_buttonmatrix_set_button_ctrl_all(bvm *vm); +extern int lvbe_buttonmatrix_set_button_width(bvm *vm); +extern int lvbe_buttonmatrix_set_map(bvm *vm); +extern int lvbe_buttonmatrix_set_one_checked(bvm *vm); +extern int lvbe_buttonmatrix_set_selected_button(bvm *vm); + +/* `lv_calendar` external functions definitions */ +extern int lvbe_calendar_create(bvm *vm); +extern int lvbe_calendar_get_btnmatrix(bvm *vm); +extern int lvbe_calendar_get_highlighted_dates_num(bvm *vm); +extern int lvbe_calendar_header_arrow_create(bvm *vm); +extern int lvbe_calendar_header_dropdown_create(bvm *vm); +extern int lvbe_calendar_header_dropdown_set_year_list(bvm *vm); +extern int lvbe_calendar_set_day_names(bvm *vm); +extern int lvbe_calendar_set_showed_date(bvm *vm); +extern int lvbe_calendar_set_today_date(bvm *vm); /* `lv_canvas` external functions definitions */ extern int lvbe_canvas_create(bvm *vm); -extern int lvbe_canvas_set_buffer(bvm *vm); -extern int lvbe_canvas_set_px_color(bvm *vm); -extern int lvbe_canvas_set_px(bvm *vm); -extern int lvbe_canvas_set_px_opa(bvm *vm); -extern int lvbe_canvas_set_palette(bvm *vm); -extern int lvbe_canvas_get_px(bvm *vm); -extern int lvbe_canvas_get_img(bvm *vm); -extern int lvbe_canvas_copy_buf(bvm *vm); -extern int lvbe_canvas_transform(bvm *vm); -extern int lvbe_canvas_blur_hor(bvm *vm); -extern int lvbe_canvas_blur_ver(bvm *vm); extern int lvbe_canvas_fill_bg(bvm *vm); -extern int lvbe_canvas_draw_rect(bvm *vm); -extern int lvbe_canvas_draw_text(bvm *vm); -extern int lvbe_canvas_draw_img(bvm *vm); -extern int lvbe_canvas_draw_line(bvm *vm); -extern int lvbe_canvas_draw_polygon(bvm *vm); -extern int lvbe_canvas_draw_arc(bvm *vm); +extern int lvbe_canvas_finish_layer(bvm *vm); +extern int lvbe_canvas_get_buf(bvm *vm); +extern int lvbe_canvas_get_image(bvm *vm); +extern int lvbe_canvas_get_px(bvm *vm); +extern int lvbe_canvas_init_layer(bvm *vm); +extern int lvbe_canvas_set_buffer(bvm *vm); +extern int lvbe_canvas_set_palette(bvm *vm); +extern int lvbe_canvas_set_px(bvm *vm); + +/* `lv_chart` external functions definitions */ +extern int lvbe_chart_add_cursor(bvm *vm); +extern int lvbe_chart_add_series(bvm *vm); +extern int lvbe_chart_create(bvm *vm); +extern int lvbe_chart_get_cursor_point(bvm *vm); +extern int lvbe_chart_get_first_point_center_offset(bvm *vm); +extern int lvbe_chart_get_point_count(bvm *vm); +extern int lvbe_chart_get_point_pos_by_id(bvm *vm); +extern int lvbe_chart_get_pressed_point(bvm *vm); +extern int lvbe_chart_get_series_next(bvm *vm); +extern int lvbe_chart_get_type(bvm *vm); +extern int lvbe_chart_get_x_array(bvm *vm); +extern int lvbe_chart_get_x_start_point(bvm *vm); +extern int lvbe_chart_get_y_array(bvm *vm); +extern int lvbe_chart_hide_series(bvm *vm); +extern int lvbe_chart_refresh(bvm *vm); +extern int lvbe_chart_remove_series(bvm *vm); +extern int lvbe_chart_set_all_value(bvm *vm); +extern int lvbe_chart_set_cursor_point(bvm *vm); +extern int lvbe_chart_set_cursor_pos(bvm *vm); +extern int lvbe_chart_set_div_line_count(bvm *vm); +extern int lvbe_chart_set_ext_x_array(bvm *vm); +extern int lvbe_chart_set_ext_y_array(bvm *vm); +extern int lvbe_chart_set_next_value(bvm *vm); +extern int lvbe_chart_set_next_value2(bvm *vm); +extern int lvbe_chart_set_point_count(bvm *vm); +extern int lvbe_chart_set_range(bvm *vm); +extern int lvbe_chart_set_series_color(bvm *vm); +extern int lvbe_chart_set_type(bvm *vm); +extern int lvbe_chart_set_update_mode(bvm *vm); +extern int lvbe_chart_set_value_by_id(bvm *vm); +extern int lvbe_chart_set_value_by_id2(bvm *vm); +extern int lvbe_chart_set_x_start_point(bvm *vm); /* `lv_checkbox` external functions definitions */ extern int lvbe_checkbox_create(bvm *vm); +extern int lvbe_checkbox_get_text(bvm *vm); extern int lvbe_checkbox_set_text(bvm *vm); extern int lvbe_checkbox_set_text_static(bvm *vm); -extern int lvbe_checkbox_get_text(bvm *vm); /* `lv_dropdown` external functions definitions */ -extern int lvbe_dropdown_create(bvm *vm); -extern int lvbe_dropdown_set_text(bvm *vm); -extern int lvbe_dropdown_set_options(bvm *vm); -extern int lvbe_dropdown_set_options_static(bvm *vm); extern int lvbe_dropdown_add_option(bvm *vm); extern int lvbe_dropdown_clear_options(bvm *vm); -extern int lvbe_dropdown_set_selected(bvm *vm); -extern int lvbe_dropdown_set_dir(bvm *vm); -extern int lvbe_dropdown_set_symbol(bvm *vm); -extern int lvbe_dropdown_set_selected_highlight(bvm *vm); +extern int lvbe_dropdown_close(bvm *vm); +extern int lvbe_dropdown_create(bvm *vm); +extern int lvbe_dropdown_get_dir(bvm *vm); extern int lvbe_dropdown_get_list(bvm *vm); -extern int lvbe_dropdown_get_text(bvm *vm); +extern int lvbe_dropdown_get_option_count(bvm *vm); +extern int lvbe_dropdown_get_option_count(bvm *vm); +extern int lvbe_dropdown_get_option_index(bvm *vm); extern int lvbe_dropdown_get_options(bvm *vm); extern int lvbe_dropdown_get_selected(bvm *vm); -extern int lvbe_dropdown_get_option_cnt(bvm *vm); -extern int lvbe_dropdown_get_selected_str(bvm *vm); -extern int lvbe_dropdown_get_option_index(bvm *vm); -extern int lvbe_dropdown_get_symbol(bvm *vm); extern int lvbe_dropdown_get_selected_highlight(bvm *vm); -extern int lvbe_dropdown_get_dir(bvm *vm); -extern int lvbe_dropdown_open(bvm *vm); -extern int lvbe_dropdown_close(bvm *vm); +extern int lvbe_dropdown_get_selected_str(bvm *vm); +extern int lvbe_dropdown_get_symbol(bvm *vm); +extern int lvbe_dropdown_get_text(bvm *vm); extern int lvbe_dropdown_is_open(bvm *vm); +extern int lvbe_dropdown_open(bvm *vm); +extern int lvbe_dropdown_set_dir(bvm *vm); +extern int lvbe_dropdown_set_options(bvm *vm); +extern int lvbe_dropdown_set_options_static(bvm *vm); +extern int lvbe_dropdown_set_selected(bvm *vm); +extern int lvbe_dropdown_set_selected_highlight(bvm *vm); +extern int lvbe_dropdown_set_symbol(bvm *vm); +extern int lvbe_dropdown_set_text(bvm *vm); + +/* `lv_imagebutton` external functions definitions */ +extern int lvbe_imagebutton_create(bvm *vm); +extern int lvbe_imagebutton_set_src(bvm *vm); +extern int lvbe_imagebutton_set_state(bvm *vm); + +/* `lv_keyboard` external functions definitions */ +extern int lvbe_keyboard_get_button_text(bvm *vm); +extern int lvbe_keyboard_create(bvm *vm); +extern int lvbe_keyboard_get_button_text(bvm *vm); +extern int lvbe_keyboard_get_map_array(bvm *vm); +extern int lvbe_keyboard_get_mode(bvm *vm); +extern int lvbe_keyboard_get_selected_button(bvm *vm); +extern int lvbe_keyboard_get_textarea(bvm *vm); +extern int lvbe_keyboard_set_mode(bvm *vm); +extern int lvbe_keyboard_set_popovers(bvm *vm); +extern int lvbe_keyboard_set_textarea(bvm *vm); /* `lv_label` external functions definitions */ extern int lvbe_label_create(bvm *vm); +extern int lvbe_label_cut_text(bvm *vm); +extern int lvbe_label_get_letter_on(bvm *vm); +extern int lvbe_label_get_letter_pos(bvm *vm); +extern int lvbe_label_get_long_mode(bvm *vm); +extern int lvbe_label_get_text(bvm *vm); +extern int lvbe_label_get_text_selection_end(bvm *vm); +extern int lvbe_label_get_text_selection_start(bvm *vm); +extern int lvbe_label_ins_text(bvm *vm); +extern int lvbe_label_is_char_under_pos(bvm *vm); +extern int lvbe_label_set_long_mode(bvm *vm); extern int lvbe_label_set_text(bvm *vm); extern int lvbe_label_set_text_fmt(bvm *vm); +extern int lvbe_label_set_text_selection_end(bvm *vm); +extern int lvbe_label_set_text_selection_start(bvm *vm); extern int lvbe_label_set_text_static(bvm *vm); -extern int lvbe_label_set_long_mode(bvm *vm); -extern int lvbe_label_set_recolor(bvm *vm); -extern int lvbe_label_set_text_sel_start(bvm *vm); -extern int lvbe_label_set_text_sel_end(bvm *vm); -extern int lvbe_label_get_text(bvm *vm); -extern int lvbe_label_get_long_mode(bvm *vm); -extern int lvbe_label_get_recolor(bvm *vm); -extern int lvbe_label_get_letter_pos(bvm *vm); -extern int lvbe_label_get_letter_on(bvm *vm); -extern int lvbe_label_is_char_under_pos(bvm *vm); -extern int lvbe_label_get_text_selection_start(bvm *vm); -extern int lvbe_label_get_text_selection_end(bvm *vm); -extern int lvbe_label_ins_text(bvm *vm); -extern int lvbe_label_cut_text(bvm *vm); + +/* `lv_led` external functions definitions */ +extern int lvbe_led_create(bvm *vm); +extern int lvbe_led_get_brightness(bvm *vm); +extern int lvbe_led_off(bvm *vm); +extern int lvbe_led_on(bvm *vm); +extern int lvbe_led_set_brightness(bvm *vm); +extern int lvbe_led_set_color(bvm *vm); +extern int lvbe_led_toggle(bvm *vm); /* `lv_line` external functions definitions */ extern int lvbe_line_create(bvm *vm); +extern int lvbe_line_get_y_invert(bvm *vm); extern int lvbe_line_set_points(bvm *vm); extern int lvbe_line_set_y_invert(bvm *vm); -extern int lvbe_line_get_y_invert(bvm *vm); + +/* `lv_list` external functions definitions */ +extern int lvbe_list_get_button_text(bvm *vm); +extern int lvbe_list_add_button(bvm *vm); +extern int lvbe_list_add_button(bvm *vm); +extern int lvbe_list_add_text(bvm *vm); +extern int lvbe_list_create(bvm *vm); +extern int lvbe_list_get_button_text(bvm *vm); +extern int lvbe_list_set_button_text(bvm *vm); +extern int lvbe_list_set_button_text(bvm *vm); + +/* `lv_menu` external functions definitions */ +extern int lvbe_menu_back_button_is_root(bvm *vm); +extern int lvbe_menu_clear_history(bvm *vm); +extern int lvbe_menu_cont_create(bvm *vm); +extern int lvbe_menu_create(bvm *vm); +extern int lvbe_menu_get_cur_main_page(bvm *vm); +extern int lvbe_menu_get_cur_sidebar_page(bvm *vm); +extern int lvbe_menu_get_main_header(bvm *vm); +extern int lvbe_menu_get_main_header_back_button(bvm *vm); +extern int lvbe_menu_get_sidebar_header(bvm *vm); +extern int lvbe_menu_get_sidebar_header_back_button(bvm *vm); +extern int lvbe_menu_page_create(bvm *vm); +extern int lvbe_menu_section_create(bvm *vm); +extern int lvbe_menu_separator_create(bvm *vm); +extern int lvbe_menu_set_load_page_event(bvm *vm); +extern int lvbe_menu_set_mode_header(bvm *vm); +extern int lvbe_menu_set_mode_root_back_button(bvm *vm); +extern int lvbe_menu_set_page(bvm *vm); +extern int lvbe_menu_set_page_title(bvm *vm); +extern int lvbe_menu_set_page_title_static(bvm *vm); +extern int lvbe_menu_set_sidebar_page(bvm *vm); + +/* `lv_msgbox` external functions definitions */ +extern int lvbe_msgbox_add_close_button(bvm *vm); +extern int lvbe_msgbox_add_footer_button(bvm *vm); +extern int lvbe_msgbox_add_header_button(bvm *vm); +extern int lvbe_msgbox_add_text(bvm *vm); +extern int lvbe_msgbox_add_title(bvm *vm); +extern int lvbe_msgbox_close(bvm *vm); +extern int lvbe_msgbox_close_async(bvm *vm); +extern int lvbe_msgbox_create(bvm *vm); +extern int lvbe_msgbox_get_content(bvm *vm); +extern int lvbe_msgbox_get_footer(bvm *vm); +extern int lvbe_msgbox_get_header(bvm *vm); +extern int lvbe_msgbox_get_title(bvm *vm); /* `lv_roller` external functions definitions */ extern int lvbe_roller_create(bvm *vm); +extern int lvbe_roller_get_option_count(bvm *vm); +extern int lvbe_roller_get_option_count(bvm *vm); +extern int lvbe_roller_get_options(bvm *vm); +extern int lvbe_roller_get_selected(bvm *vm); +extern int lvbe_roller_get_selected_str(bvm *vm); extern int lvbe_roller_set_options(bvm *vm); extern int lvbe_roller_set_selected(bvm *vm); extern int lvbe_roller_set_visible_row_count(bvm *vm); -extern int lvbe_roller_get_selected(bvm *vm); -extern int lvbe_roller_get_selected_str(bvm *vm); -extern int lvbe_roller_get_options(bvm *vm); -extern int lvbe_roller_get_option_cnt(bvm *vm); +extern int lvbe_roller_set_visible_row_count(bvm *vm); + +/* `lv_scale` external functions definitions */ +extern int lvbe_scale_add_section(bvm *vm); +extern int lvbe_scale_create(bvm *vm); +extern int lvbe_scale_get_angle_range(bvm *vm); +extern int lvbe_scale_get_label_show(bvm *vm); +extern int lvbe_scale_get_major_tick_every(bvm *vm); +extern int lvbe_scale_get_mode(bvm *vm); +extern int lvbe_scale_get_range_max_value(bvm *vm); +extern int lvbe_scale_get_range_min_value(bvm *vm); +extern int lvbe_scale_get_total_tick_count(bvm *vm); +extern int lvbe_scale_set_rotation(bvm *vm); +extern int lvbe_scale_set_angle_range(bvm *vm); +extern int lvbe_scale_set_image_needle_value(bvm *vm); +extern int lvbe_scale_set_label_show(bvm *vm); +extern int lvbe_scale_set_line_needle_value(bvm *vm); +extern int lvbe_scale_set_major_tick_every(bvm *vm); +extern int lvbe_scale_set_mode(bvm *vm); +extern int lvbe_scale_set_post_draw(bvm *vm); +extern int lvbe_scale_set_range(bvm *vm); +extern int lvbe_scale_set_rotation(bvm *vm); +extern int lvbe_scale_set_rotation(bvm *vm); +extern int lvbe_scale_set_text_src(bvm *vm); +extern int lvbe_scale_set_total_tick_count(bvm *vm); /* `lv_slider` external functions definitions */ extern int lvbe_slider_create(bvm *vm); -extern int lvbe_slider_set_value(bvm *vm); -extern int lvbe_slider_set_left_value(bvm *vm); -extern int lvbe_slider_set_range(bvm *vm); -extern int lvbe_slider_set_mode(bvm *vm); -extern int lvbe_slider_get_value(bvm *vm); extern int lvbe_slider_get_left_value(bvm *vm); -extern int lvbe_slider_get_min_value(bvm *vm); extern int lvbe_slider_get_max_value(bvm *vm); -extern int lvbe_slider_is_dragged(bvm *vm); +extern int lvbe_slider_get_min_value(bvm *vm); extern int lvbe_slider_get_mode(bvm *vm); +extern int lvbe_slider_get_value(bvm *vm); +extern int lvbe_slider_is_dragged(bvm *vm); +extern int lvbe_slider_is_symmetrical(bvm *vm); +extern int lvbe_slider_set_left_value(bvm *vm); +extern int lvbe_slider_set_mode(bvm *vm); +extern int lvbe_slider_set_range(bvm *vm); +extern int lvbe_slider_set_value(bvm *vm); + +/* `lv_spangroup` external functions definitions */ +extern int lvbe_spangroup_create(bvm *vm); +extern int lvbe_spangroup_delete_span(bvm *vm); +extern int lvbe_spangroup_get_align(bvm *vm); +extern int lvbe_spangroup_get_child(bvm *vm); +extern int lvbe_spangroup_get_expand_height(bvm *vm); +extern int lvbe_spangroup_get_expand_width(bvm *vm); +extern int lvbe_spangroup_get_indent(bvm *vm); +extern int lvbe_spangroup_get_max_line_height(bvm *vm); +extern int lvbe_spangroup_get_max_lines(bvm *vm); +extern int lvbe_spangroup_get_mode(bvm *vm); +extern int lvbe_spangroup_get_overflow(bvm *vm); +extern int lvbe_spangroup_get_span_count(bvm *vm); +extern int lvbe_spangroup_new_span(bvm *vm); +extern int lvbe_spangroup_refr_mode(bvm *vm); +extern int lvbe_spangroup_set_align(bvm *vm); +extern int lvbe_spangroup_set_indent(bvm *vm); +extern int lvbe_spangroup_set_max_lines(bvm *vm); +extern int lvbe_spangroup_set_mode(bvm *vm); +extern int lvbe_spangroup_set_overflow(bvm *vm); + +/* `lv_spinbox` external functions definitions */ +extern int lvbe_spinbox_create(bvm *vm); +extern int lvbe_spinbox_decrement(bvm *vm); +extern int lvbe_spinbox_get_rollover(bvm *vm); +extern int lvbe_spinbox_get_step(bvm *vm); +extern int lvbe_spinbox_get_value(bvm *vm); +extern int lvbe_spinbox_increment(bvm *vm); +extern int lvbe_spinbox_set_cursor_pos(bvm *vm); +extern int lvbe_spinbox_set_digit_format(bvm *vm); +extern int lvbe_spinbox_set_digit_step_direction(bvm *vm); +extern int lvbe_spinbox_set_range(bvm *vm); +extern int lvbe_spinbox_set_rollover(bvm *vm); +extern int lvbe_spinbox_set_step(bvm *vm); +extern int lvbe_spinbox_set_value(bvm *vm); +extern int lvbe_spinbox_step_next(bvm *vm); +extern int lvbe_spinbox_step_prev(bvm *vm); + +/* `lv_spinner` external functions definitions */ +extern int lvbe_spinner_create(bvm *vm); +extern int lvbe_spinner_set_anim_params(bvm *vm); /* `lv_switch` external functions definitions */ extern int lvbe_switch_create(bvm *vm); /* `lv_table` external functions definitions */ -extern int lvbe_table_create(bvm *vm); -extern int lvbe_table_set_cell_value(bvm *vm); -extern int lvbe_table_set_cell_value_fmt(bvm *vm); -extern int lvbe_table_set_row_cnt(bvm *vm); -extern int lvbe_table_set_col_cnt(bvm *vm); -extern int lvbe_table_set_col_width(bvm *vm); extern int lvbe_table_add_cell_ctrl(bvm *vm); extern int lvbe_table_clear_cell_ctrl(bvm *vm); -extern int lvbe_table_set_cell_user_data(bvm *vm); -extern int lvbe_table_get_cell_value(bvm *vm); -extern int lvbe_table_get_row_cnt(bvm *vm); -extern int lvbe_table_get_col_cnt(bvm *vm); -extern int lvbe_table_get_col_width(bvm *vm); -extern int lvbe_table_has_cell_ctrl(bvm *vm); -extern int lvbe_table_get_selected_cell(bvm *vm); +extern int lvbe_table_create(bvm *vm); extern int lvbe_table_get_cell_user_data(bvm *vm); +extern int lvbe_table_get_cell_value(bvm *vm); +extern int lvbe_table_get_column_count(bvm *vm); +extern int lvbe_table_get_column_width(bvm *vm); +extern int lvbe_table_get_column_count(bvm *vm); +extern int lvbe_table_get_column_width(bvm *vm); +extern int lvbe_table_get_row_count(bvm *vm); +extern int lvbe_table_get_row_count(bvm *vm); +extern int lvbe_table_get_selected_cell(bvm *vm); +extern int lvbe_table_has_cell_ctrl(bvm *vm); +extern int lvbe_table_set_cell_user_data(bvm *vm); +extern int lvbe_table_set_cell_value(bvm *vm); +extern int lvbe_table_set_cell_value_fmt(bvm *vm); +extern int lvbe_table_set_column_count(bvm *vm); +extern int lvbe_table_set_column_width(bvm *vm); +extern int lvbe_table_set_column_count(bvm *vm); +extern int lvbe_table_set_column_width(bvm *vm); +extern int lvbe_table_set_row_count(bvm *vm); +extern int lvbe_table_set_row_count(bvm *vm); + +/* `lv_tabview` external functions definitions */ +extern int lvbe_tabview_add_tab(bvm *vm); +extern int lvbe_tabview_create(bvm *vm); +extern int lvbe_tabview_get_content(bvm *vm); +extern int lvbe_tabview_get_tab_active(bvm *vm); +extern int lvbe_tabview_get_tab_active(bvm *vm); +extern int lvbe_tabview_get_tab_bar(bvm *vm); +extern int lvbe_tabview_get_tab_bar(bvm *vm); +extern int lvbe_tabview_get_tab_count(bvm *vm); +extern int lvbe_tabview_rename_tab(bvm *vm); +extern int lvbe_tabview_set_active(bvm *vm); +extern int lvbe_tabview_set_active(bvm *vm); +extern int lvbe_tabview_set_tab_bar_position(bvm *vm); +extern int lvbe_tabview_set_tab_bar_size(bvm *vm); /* `lv_textarea` external functions definitions */ -extern int lvbe_textarea_create(bvm *vm); extern int lvbe_textarea_add_char(bvm *vm); extern int lvbe_textarea_add_text(bvm *vm); -extern int lvbe_textarea_del_char(bvm *vm); -extern int lvbe_textarea_del_char_forward(bvm *vm); -extern int lvbe_textarea_set_text(bvm *vm); -extern int lvbe_textarea_set_placeholder_text(bvm *vm); -extern int lvbe_textarea_set_cursor_pos(bvm *vm); -extern int lvbe_textarea_set_cursor_click_pos(bvm *vm); -extern int lvbe_textarea_set_password_mode(bvm *vm); -extern int lvbe_textarea_set_password_bullet(bvm *vm); -extern int lvbe_textarea_set_one_line(bvm *vm); -extern int lvbe_textarea_set_accepted_chars(bvm *vm); -extern int lvbe_textarea_set_max_length(bvm *vm); -extern int lvbe_textarea_set_insert_replace(bvm *vm); -extern int lvbe_textarea_set_text_selection(bvm *vm); -extern int lvbe_textarea_set_password_show_time(bvm *vm); -extern int lvbe_textarea_set_align(bvm *vm); -extern int lvbe_textarea_get_text(bvm *vm); -extern int lvbe_textarea_get_placeholder_text(bvm *vm); -extern int lvbe_textarea_get_label(bvm *vm); -extern int lvbe_textarea_get_cursor_pos(bvm *vm); -extern int lvbe_textarea_get_cursor_click_pos(bvm *vm); -extern int lvbe_textarea_get_password_mode(bvm *vm); -extern int lvbe_textarea_get_password_bullet(bvm *vm); -extern int lvbe_textarea_get_one_line(bvm *vm); -extern int lvbe_textarea_get_accepted_chars(bvm *vm); -extern int lvbe_textarea_get_max_length(bvm *vm); -extern int lvbe_textarea_text_is_selected(bvm *vm); -extern int lvbe_textarea_get_text_selection(bvm *vm); -extern int lvbe_textarea_get_password_show_time(bvm *vm); extern int lvbe_textarea_clear_selection(bvm *vm); -extern int lvbe_textarea_cursor_right(bvm *vm); -extern int lvbe_textarea_cursor_left(bvm *vm); +extern int lvbe_textarea_create(bvm *vm); extern int lvbe_textarea_cursor_down(bvm *vm); +extern int lvbe_textarea_cursor_left(bvm *vm); +extern int lvbe_textarea_cursor_right(bvm *vm); extern int lvbe_textarea_cursor_up(bvm *vm); +extern int lvbe_textarea_delete_char(bvm *vm); +extern int lvbe_textarea_delete_char_forward(bvm *vm); +extern int lvbe_textarea_get_accepted_chars(bvm *vm); +extern int lvbe_textarea_get_current_char(bvm *vm); +extern int lvbe_textarea_get_cursor_click_pos(bvm *vm); +extern int lvbe_textarea_get_cursor_pos(bvm *vm); +extern int lvbe_textarea_get_label(bvm *vm); +extern int lvbe_textarea_get_max_length(bvm *vm); +extern int lvbe_textarea_get_one_line(bvm *vm); +extern int lvbe_textarea_get_password_bullet(bvm *vm); +extern int lvbe_textarea_get_password_mode(bvm *vm); +extern int lvbe_textarea_get_password_show_time(bvm *vm); +extern int lvbe_textarea_get_placeholder_text(bvm *vm); +extern int lvbe_textarea_get_text(bvm *vm); +extern int lvbe_textarea_get_text_selection(bvm *vm); +extern int lvbe_textarea_set_accepted_chars(bvm *vm); +extern int lvbe_textarea_set_align(bvm *vm); +extern int lvbe_textarea_set_cursor_click_pos(bvm *vm); +extern int lvbe_textarea_set_cursor_pos(bvm *vm); +extern int lvbe_textarea_set_insert_replace(bvm *vm); +extern int lvbe_textarea_set_max_length(bvm *vm); +extern int lvbe_textarea_set_one_line(bvm *vm); +extern int lvbe_textarea_set_password_bullet(bvm *vm); +extern int lvbe_textarea_set_password_mode(bvm *vm); +extern int lvbe_textarea_set_password_show_time(bvm *vm); +extern int lvbe_textarea_set_placeholder_text(bvm *vm); +extern int lvbe_textarea_set_text(bvm *vm); +extern int lvbe_textarea_set_text_selection(bvm *vm); +extern int lvbe_textarea_text_is_selected(bvm *vm); + +/* `lv_tileview` external functions definitions */ +extern int lvbe_tileview_add_tile(bvm *vm); +extern int lvbe_tileview_create(bvm *vm); +extern int lvbe_tileview_get_tile_active(bvm *vm); +extern int lvbe_tileview_get_tile_active(bvm *vm); +extern int lvbe_tileview_set_tile(bvm *vm); +extern int lvbe_tileview_set_tile_by_index(bvm *vm); +extern int lvbe_tileview_set_tile_by_index(bvm *vm); extern int be_ntv_lv_style_init(bvm *vm); extern int be_ntv_lv_font_init(bvm *vm); extern int be_ntv_lv_color_init(bvm *vm); extern int be_ntv_lv_theme_init(bvm *vm); -extern int be_ntv_lv_img_init(bvm *vm); -extern int be_ntv_lv_disp_init(bvm *vm); -extern int be_ntv_lv_obj_init(bvm *vm); +extern int be_ntv_lv_image_init(bvm *vm); extern int be_ntv_lv_group_init(bvm *vm); +extern int be_ntv_lv_obj_init(bvm *vm); +extern int be_ntv_lv_event_init(bvm *vm); +extern int be_ntv_lv_display_init(bvm *vm); extern int be_ntv_lv_indev_init(bvm *vm); extern int be_ntv_lv_qrcode_init(bvm *vm); -extern int be_ntv_lv_chart_init(bvm *vm); -extern int be_ntv_lv_colorwheel_init(bvm *vm); -extern int be_ntv_lv_imgbtn_init(bvm *vm); -extern int be_ntv_lv_keyboard_init(bvm *vm); -extern int be_ntv_lv_btnmatrix_init(bvm *vm); -extern int be_ntv_lv_led_init(bvm *vm); -extern int be_ntv_lv_list_init(bvm *vm); -extern int be_ntv_lv_meter_init(bvm *vm); -extern int be_ntv_lv_msgbox_init(bvm *vm); -extern int be_ntv_lv_spinbox_init(bvm *vm); -extern int be_ntv_lv_spinner_init(bvm *vm); -extern int be_ntv_lv_tabview_init(bvm *vm); -extern int be_ntv_lv_tileview_init(bvm *vm); extern int be_ntv_lv_anim_init(bvm *vm); extern int be_ntv_lv_timer_init(bvm *vm); +extern int be_ntv_lv_animimg_init(bvm *vm); extern int be_ntv_lv_arc_init(bvm *vm); extern int be_ntv_lv_bar_init(bvm *vm); -extern int be_ntv_lv_btn_init(bvm *vm); +extern int be_ntv_lv_button_init(bvm *vm); +extern int be_ntv_lv_buttonmatrix_init(bvm *vm); +extern int be_ntv_lv_calendar_init(bvm *vm); extern int be_ntv_lv_canvas_init(bvm *vm); +extern int be_ntv_lv_chart_init(bvm *vm); extern int be_ntv_lv_checkbox_init(bvm *vm); extern int be_ntv_lv_dropdown_init(bvm *vm); +extern int be_ntv_lv_imagebutton_init(bvm *vm); +extern int be_ntv_lv_keyboard_init(bvm *vm); extern int be_ntv_lv_label_init(bvm *vm); +extern int be_ntv_lv_led_init(bvm *vm); extern int be_ntv_lv_line_init(bvm *vm); +extern int be_ntv_lv_list_init(bvm *vm); +extern int be_ntv_lv_menu_init(bvm *vm); +extern int be_ntv_lv_msgbox_init(bvm *vm); extern int be_ntv_lv_roller_init(bvm *vm); +extern int be_ntv_lv_scale_init(bvm *vm); extern int be_ntv_lv_slider_init(bvm *vm); +extern int be_ntv_lv_spangroup_init(bvm *vm); +extern int be_ntv_lv_spinbox_init(bvm *vm); +extern int be_ntv_lv_spinner_init(bvm *vm); extern int be_ntv_lv_switch_init(bvm *vm); extern int be_ntv_lv_table_init(bvm *vm); +extern int be_ntv_lv_tabview_init(bvm *vm); extern int be_ntv_lv_textarea_init(bvm *vm); +extern int be_ntv_lv_tileview_init(bvm *vm); extern const bclass be_class_lv_anim; +extern const bclass be_class_lv_animimg; extern const bclass be_class_lv_arc; extern const bclass be_class_lv_bar; -extern const bclass be_class_lv_btn; -extern const bclass be_class_lv_btnmatrix; +extern const bclass be_class_lv_button; +extern const bclass be_class_lv_buttonmatrix; +extern const bclass be_class_lv_calendar; extern const bclass be_class_lv_canvas; extern const bclass be_class_lv_chart; extern const bclass be_class_lv_checkbox; extern const bclass be_class_lv_color; -extern const bclass be_class_lv_colorwheel; -extern const bclass be_class_lv_disp; +extern const bclass be_class_lv_display; extern const bclass be_class_lv_dropdown; +extern const bclass be_class_lv_event; extern const bclass be_class_lv_font; extern const bclass be_class_lv_group; -extern const bclass be_class_lv_img; -extern const bclass be_class_lv_imgbtn; +extern const bclass be_class_lv_image; +extern const bclass be_class_lv_imagebutton; extern const bclass be_class_lv_indev; extern const bclass be_class_lv_keyboard; extern const bclass be_class_lv_label; extern const bclass be_class_lv_led; extern const bclass be_class_lv_line; extern const bclass be_class_lv_list; -extern const bclass be_class_lv_meter; +extern const bclass be_class_lv_menu; extern const bclass be_class_lv_msgbox; extern const bclass be_class_lv_obj; extern const bclass be_class_lv_qrcode; extern const bclass be_class_lv_roller; +extern const bclass be_class_lv_scale; extern const bclass be_class_lv_slider; +extern const bclass be_class_lv_spangroup; extern const bclass be_class_lv_spinbox; extern const bclass be_class_lv_spinner; extern const bclass be_class_lv_style; @@ -1122,11 +1418,11 @@ class be_class_lv_indev (scope: global, name: lv_indev, strings: weak) { @const_object_info_end */ /******************************************************************** -** Solidified class: lv_disp +** Solidified class: lv_display ********************************************************************/ -#include "be_fixed_be_class_lv_disp.h" +#include "be_fixed_be_class_lv_display.h" /* @const_object_info_begin -class be_class_lv_disp (scope: global, name: lv_disp, strings: weak) { +class be_class_lv_display (scope: global, name: lv_display, strings: weak) { _p, var init, func(lv0_init) tostring, func(lv_x_tostring) @@ -1160,6 +1456,19 @@ class be_class_lv_anim (scope: global, name: lv_anim, strings: weak) { } @const_object_info_end */ +/******************************************************************** +** Solidified class: lv_event +********************************************************************/ +#include "be_fixed_be_class_lv_event.h" +/* @const_object_info_begin +class be_class_lv_event (scope: global, name: lv_event, strings: weak) { + _p, var + init, func(lv0_init) + tostring, func(lv_x_tostring) + member, func(lv_x_member) +} +@const_object_info_end */ + /******************************************************************** ** Solidified class: lv_font ********************************************************************/ @@ -1203,13 +1512,13 @@ extern void arc_anim_end_angle(void * obj, int32_t v); /******************************************************************** -** Solidified class: lv_img +** Solidified class: lv_image ********************************************************************/ -#include "be_fixed_be_class_lv_img.h" +#include "be_fixed_be_class_lv_image.h" /* @const_object_info_begin -class be_class_lv_img (scope: global, name: lv_img, super: be_class_lv_obj, strings: weak) { - _class, comptr(&lv_img_class) - init, func(be_ntv_lv_img_init) +class be_class_lv_image (scope: global, name: lv_image, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_image_class) + init, func(be_ntv_lv_image_init) } @const_object_info_end */ @@ -1225,147 +1534,13 @@ class be_class_lv_qrcode (scope: global, name: lv_qrcode, super: be_class_lv_obj @const_object_info_end */ /******************************************************************** -** Solidified class: lv_chart +** Solidified class: lv_animimg ********************************************************************/ -#include "be_fixed_be_class_lv_chart.h" +#include "be_fixed_be_class_lv_animimg.h" /* @const_object_info_begin -class be_class_lv_chart (scope: global, name: lv_chart, super: be_class_lv_obj, strings: weak) { - _class, comptr(&lv_chart_class) - init, func(be_ntv_lv_chart_init) -} -@const_object_info_end */ - -/******************************************************************** -** Solidified class: lv_colorwheel -********************************************************************/ -#include "be_fixed_be_class_lv_colorwheel.h" -/* @const_object_info_begin -class be_class_lv_colorwheel (scope: global, name: lv_colorwheel, super: be_class_lv_obj, strings: weak) { - _class, comptr(&lv_colorwheel_class) - init, func(be_ntv_lv_colorwheel_init) -} -@const_object_info_end */ - -/******************************************************************** -** Solidified class: lv_imgbtn -********************************************************************/ -#include "be_fixed_be_class_lv_imgbtn.h" -/* @const_object_info_begin -class be_class_lv_imgbtn (scope: global, name: lv_imgbtn, super: be_class_lv_obj, strings: weak) { - _class, comptr(&lv_imgbtn_class) - init, func(be_ntv_lv_imgbtn_init) -} -@const_object_info_end */ - -/******************************************************************** -** Solidified class: lv_keyboard -********************************************************************/ -#include "be_fixed_be_class_lv_keyboard.h" -/* @const_object_info_begin -class be_class_lv_keyboard (scope: global, name: lv_keyboard, super: be_class_lv_btnmatrix, strings: weak) { - _class, comptr(&lv_keyboard_class) - init, func(be_ntv_lv_keyboard_init) -} -@const_object_info_end */ - -/******************************************************************** -** Solidified class: lv_btnmatrix -********************************************************************/ -#include "be_fixed_be_class_lv_btnmatrix.h" -/* @const_object_info_begin -class be_class_lv_btnmatrix (scope: global, name: lv_btnmatrix, super: be_class_lv_obj, strings: weak) { - _class, comptr(&lv_btnmatrix_class) - init, func(be_ntv_lv_btnmatrix_init) -} -@const_object_info_end */ - -/******************************************************************** -** Solidified class: lv_led -********************************************************************/ -#include "be_fixed_be_class_lv_led.h" -/* @const_object_info_begin -class be_class_lv_led (scope: global, name: lv_led, super: be_class_lv_obj, strings: weak) { - _class, comptr(&lv_led_class) - init, func(be_ntv_lv_led_init) -} -@const_object_info_end */ - -/******************************************************************** -** Solidified class: lv_list -********************************************************************/ -#include "be_fixed_be_class_lv_list.h" -/* @const_object_info_begin -class be_class_lv_list (scope: global, name: lv_list, super: be_class_lv_obj, strings: weak) { - _class, comptr(&lv_list_class) - init, func(be_ntv_lv_list_init) -} -@const_object_info_end */ - -/******************************************************************** -** Solidified class: lv_meter -********************************************************************/ -#include "be_fixed_be_class_lv_meter.h" -/* @const_object_info_begin -class be_class_lv_meter (scope: global, name: lv_meter, super: be_class_lv_obj, strings: weak) { - _class, comptr(&lv_meter_class) - init, func(be_ntv_lv_meter_init) -} -@const_object_info_end */ - -/******************************************************************** -** Solidified class: lv_msgbox -********************************************************************/ -#include "be_fixed_be_class_lv_msgbox.h" -/* @const_object_info_begin -class be_class_lv_msgbox (scope: global, name: lv_msgbox, super: be_class_lv_obj, strings: weak) { - _class, comptr(&lv_msgbox_class) - init, func(be_ntv_lv_msgbox_init) -} -@const_object_info_end */ - -/******************************************************************** -** Solidified class: lv_spinbox -********************************************************************/ -#include "be_fixed_be_class_lv_spinbox.h" -/* @const_object_info_begin -class be_class_lv_spinbox (scope: global, name: lv_spinbox, super: be_class_lv_textarea, strings: weak) { - _class, comptr(&lv_spinbox_class) - init, func(be_ntv_lv_spinbox_init) -} -@const_object_info_end */ - -/******************************************************************** -** Solidified class: lv_spinner -********************************************************************/ -#include "be_fixed_be_class_lv_spinner.h" -/* @const_object_info_begin -class be_class_lv_spinner (scope: global, name: lv_spinner, super: be_class_lv_arc, strings: weak) { - _class, comptr(&lv_spinner_class) - init, func(be_ntv_lv_spinner_init) - _arc_anim_start_angle, comptr(&arc_anim_start_angle) - _arc_anim_end_angle, comptr(&arc_anim_end_angle) -} -@const_object_info_end */ - -/******************************************************************** -** Solidified class: lv_tabview -********************************************************************/ -#include "be_fixed_be_class_lv_tabview.h" -/* @const_object_info_begin -class be_class_lv_tabview (scope: global, name: lv_tabview, super: be_class_lv_obj, strings: weak) { - _class, comptr(&lv_tabview_class) - init, func(be_ntv_lv_tabview_init) -} -@const_object_info_end */ - -/******************************************************************** -** Solidified class: lv_tileview -********************************************************************/ -#include "be_fixed_be_class_lv_tileview.h" -/* @const_object_info_begin -class be_class_lv_tileview (scope: global, name: lv_tileview, super: be_class_lv_obj, strings: weak) { - _class, comptr(&lv_tileview_class) - init, func(be_ntv_lv_tileview_init) +class be_class_lv_animimg (scope: global, name: lv_animimg, super: be_class_lv_image, strings: weak) { + _class, comptr(&lv_animimg_class) + init, func(be_ntv_lv_animimg_init) } @const_object_info_end */ @@ -1392,13 +1567,35 @@ class be_class_lv_bar (scope: global, name: lv_bar, super: be_class_lv_obj, stri @const_object_info_end */ /******************************************************************** -** Solidified class: lv_btn +** Solidified class: lv_button ********************************************************************/ -#include "be_fixed_be_class_lv_btn.h" +#include "be_fixed_be_class_lv_button.h" /* @const_object_info_begin -class be_class_lv_btn (scope: global, name: lv_btn, super: be_class_lv_obj, strings: weak) { - _class, comptr(&lv_btn_class) - init, func(be_ntv_lv_btn_init) +class be_class_lv_button (scope: global, name: lv_button, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_button_class) + init, func(be_ntv_lv_button_init) +} +@const_object_info_end */ + +/******************************************************************** +** Solidified class: lv_buttonmatrix +********************************************************************/ +#include "be_fixed_be_class_lv_buttonmatrix.h" +/* @const_object_info_begin +class be_class_lv_buttonmatrix (scope: global, name: lv_buttonmatrix, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_buttonmatrix_class) + init, func(be_ntv_lv_buttonmatrix_init) +} +@const_object_info_end */ + +/******************************************************************** +** Solidified class: lv_calendar +********************************************************************/ +#include "be_fixed_be_class_lv_calendar.h" +/* @const_object_info_begin +class be_class_lv_calendar (scope: global, name: lv_calendar, super: be_class_lv_buttonmatrix, strings: weak) { + _class, comptr(&lv_calendar_class) + init, func(be_ntv_lv_calendar_init) } @const_object_info_end */ @@ -1407,12 +1604,23 @@ class be_class_lv_btn (scope: global, name: lv_btn, super: be_class_lv_obj, stri ********************************************************************/ #include "be_fixed_be_class_lv_canvas.h" /* @const_object_info_begin -class be_class_lv_canvas (scope: global, name: lv_canvas, super: be_class_lv_img, strings: weak) { +class be_class_lv_canvas (scope: global, name: lv_canvas, super: be_class_lv_image, strings: weak) { _class, comptr(&lv_canvas_class) init, func(be_ntv_lv_canvas_init) } @const_object_info_end */ +/******************************************************************** +** Solidified class: lv_chart +********************************************************************/ +#include "be_fixed_be_class_lv_chart.h" +/* @const_object_info_begin +class be_class_lv_chart (scope: global, name: lv_chart, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_chart_class) + init, func(be_ntv_lv_chart_init) +} +@const_object_info_end */ + /******************************************************************** ** Solidified class: lv_checkbox ********************************************************************/ @@ -1435,6 +1643,28 @@ class be_class_lv_dropdown (scope: global, name: lv_dropdown, super: be_class_lv } @const_object_info_end */ +/******************************************************************** +** Solidified class: lv_imagebutton +********************************************************************/ +#include "be_fixed_be_class_lv_imagebutton.h" +/* @const_object_info_begin +class be_class_lv_imagebutton (scope: global, name: lv_imagebutton, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_imagebutton_class) + init, func(be_ntv_lv_imagebutton_init) +} +@const_object_info_end */ + +/******************************************************************** +** Solidified class: lv_keyboard +********************************************************************/ +#include "be_fixed_be_class_lv_keyboard.h" +/* @const_object_info_begin +class be_class_lv_keyboard (scope: global, name: lv_keyboard, super: be_class_lv_buttonmatrix, strings: weak) { + _class, comptr(&lv_keyboard_class) + init, func(be_ntv_lv_keyboard_init) +} +@const_object_info_end */ + /******************************************************************** ** Solidified class: lv_label ********************************************************************/ @@ -1446,6 +1676,17 @@ class be_class_lv_label (scope: global, name: lv_label, super: be_class_lv_obj, } @const_object_info_end */ +/******************************************************************** +** Solidified class: lv_led +********************************************************************/ +#include "be_fixed_be_class_lv_led.h" +/* @const_object_info_begin +class be_class_lv_led (scope: global, name: lv_led, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_led_class) + init, func(be_ntv_lv_led_init) +} +@const_object_info_end */ + /******************************************************************** ** Solidified class: lv_line ********************************************************************/ @@ -1457,6 +1698,39 @@ class be_class_lv_line (scope: global, name: lv_line, super: be_class_lv_obj, st } @const_object_info_end */ +/******************************************************************** +** Solidified class: lv_list +********************************************************************/ +#include "be_fixed_be_class_lv_list.h" +/* @const_object_info_begin +class be_class_lv_list (scope: global, name: lv_list, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_list_class) + init, func(be_ntv_lv_list_init) +} +@const_object_info_end */ + +/******************************************************************** +** Solidified class: lv_menu +********************************************************************/ +#include "be_fixed_be_class_lv_menu.h" +/* @const_object_info_begin +class be_class_lv_menu (scope: global, name: lv_menu, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_menu_class) + init, func(be_ntv_lv_menu_init) +} +@const_object_info_end */ + +/******************************************************************** +** Solidified class: lv_msgbox +********************************************************************/ +#include "be_fixed_be_class_lv_msgbox.h" +/* @const_object_info_begin +class be_class_lv_msgbox (scope: global, name: lv_msgbox, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_msgbox_class) + init, func(be_ntv_lv_msgbox_init) +} +@const_object_info_end */ + /******************************************************************** ** Solidified class: lv_roller ********************************************************************/ @@ -1468,6 +1742,17 @@ class be_class_lv_roller (scope: global, name: lv_roller, super: be_class_lv_obj } @const_object_info_end */ +/******************************************************************** +** Solidified class: lv_scale +********************************************************************/ +#include "be_fixed_be_class_lv_scale.h" +/* @const_object_info_begin +class be_class_lv_scale (scope: global, name: lv_scale, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_scale_class) + init, func(be_ntv_lv_scale_init) +} +@const_object_info_end */ + /******************************************************************** ** Solidified class: lv_slider ********************************************************************/ @@ -1479,6 +1764,39 @@ class be_class_lv_slider (scope: global, name: lv_slider, super: be_class_lv_obj } @const_object_info_end */ +/******************************************************************** +** Solidified class: lv_spangroup +********************************************************************/ +#include "be_fixed_be_class_lv_spangroup.h" +/* @const_object_info_begin +class be_class_lv_spangroup (scope: global, name: lv_spangroup, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_spangroup_class) + init, func(be_ntv_lv_spangroup_init) +} +@const_object_info_end */ + +/******************************************************************** +** Solidified class: lv_spinbox +********************************************************************/ +#include "be_fixed_be_class_lv_spinbox.h" +/* @const_object_info_begin +class be_class_lv_spinbox (scope: global, name: lv_spinbox, super: be_class_lv_textarea, strings: weak) { + _class, comptr(&lv_spinbox_class) + init, func(be_ntv_lv_spinbox_init) +} +@const_object_info_end */ + +/******************************************************************** +** Solidified class: lv_spinner +********************************************************************/ +#include "be_fixed_be_class_lv_spinner.h" +/* @const_object_info_begin +class be_class_lv_spinner (scope: global, name: lv_spinner, super: be_class_lv_arc, strings: weak) { + _class, comptr(&lv_spinner_class) + init, func(be_ntv_lv_spinner_init) +} +@const_object_info_end */ + /******************************************************************** ** Solidified class: lv_switch ********************************************************************/ @@ -1501,6 +1819,17 @@ class be_class_lv_table (scope: global, name: lv_table, super: be_class_lv_obj, } @const_object_info_end */ +/******************************************************************** +** Solidified class: lv_tabview +********************************************************************/ +#include "be_fixed_be_class_lv_tabview.h" +/* @const_object_info_begin +class be_class_lv_tabview (scope: global, name: lv_tabview, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_tabview_class) + init, func(be_ntv_lv_tabview_init) +} +@const_object_info_end */ + /******************************************************************** ** Solidified class: lv_textarea ********************************************************************/ @@ -1512,3 +1841,14 @@ class be_class_lv_textarea (scope: global, name: lv_textarea, super: be_class_lv } @const_object_info_end */ +/******************************************************************** +** Solidified class: lv_tileview +********************************************************************/ +#include "be_fixed_be_class_lv_tileview.h" +/* @const_object_info_begin +class be_class_lv_tileview (scope: global, name: lv_tileview, super: be_class_lv_obj, strings: weak) { + _class, comptr(&lv_tileview_class) + init, func(be_ntv_lv_tileview_init) +} +@const_object_info_end */ + diff --git a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h index 8828e0c3e..ddb97acd4 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h +++ b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h @@ -112,77 +112,51 @@ SYMBOL_NEW_LINE="\xef\xA2\xA2" SYMBOL_DUMMY="\xEF\xA3\xBF" SYMBOL_BULLET="\xE2\x80\xA2" + +// LVGL 8 to 9 compatibility + +LV_DISP_ROTATION_0=LV_DISPLAY_ROTATION_0 +LV_DISP_ROTATION_90=LV_DISPLAY_ROTATION_90 +LV_DISP_ROTATION_180=LV_DISPLAY_ROTATION_180 +LV_DISP_ROTATION_270=LV_DISPLAY_ROTATION_270 + +LV_DISP_RENDER_MODE_PARTIAL=LV_DISPLAY_RENDER_MODE_PARTIAL +LV_DISP_RENDER_MODE_DIRECT=LV_DISPLAY_RENDER_MODE_DIRECT +LV_DISP_RENDER_MODE_FULL=LV_DISPLAY_RENDER_MODE_FULL + +LV_BTNMATRIX_BTN_NONE=LV_BUTTONMATRIX_BUTTON_NONE + +LV_BTNMATRIX_CTRL_HIDDEN=LV_BUTTONMATRIX_CTRL_HIDDEN +LV_BTNMATRIX_CTRL_NO_REPEAT=LV_BUTTONMATRIX_CTRL_NO_REPEAT +LV_BTNMATRIX_CTRL_DISABLED=LV_BUTTONMATRIX_CTRL_DISABLED +LV_BTNMATRIX_CTRL_CHECKABLE=LV_BUTTONMATRIX_CTRL_CHECKABLE +LV_BTNMATRIX_CTRL_CHECKED=LV_BUTTONMATRIX_CTRL_CHECKED +LV_BTNMATRIX_CTRL_CLICK_TRIG=LV_BUTTONMATRIX_CTRL_CLICK_TRIG +LV_BTNMATRIX_CTRL_POPOVER=LV_BUTTONMATRIX_CTRL_POPOVER +LV_BTNMATRIX_CTRL_CUSTOM_1=LV_BUTTONMATRIX_CTRL_CUSTOM_1 +LV_BTNMATRIX_CTRL_CUSTOM_2=LV_BUTTONMATRIX_CTRL_CUSTOM_2 + +LV_RES_OK=LV_RESULT_OK +LV_RES_INV=LV_RESULT_INVALID + +LV_INDEV_STATE_PR=LV_INDEV_STATE_PRESSED +LV_INDEV_STATE_REL=LV_INDEV_STATE_RELEASED + +LV_STYLE_ANIM_TIME=LV_STYLE_ANIM_DURATION +LV_STYLE_IMG_OPA=LV_STYLE_IMAGE_OPA +LV_STYLE_IMG_RECOLOR=LV_STYLE_IMAGE_RECOLOR +LV_STYLE_IMG_RECOLOR_OPA=LV_STYLE_IMAGE_RECOLOR_OPA +LV_STYLE_SHADOW_OFS_X=LV_STYLE_SHADOW_OFFSET_X +LV_STYLE_SHADOW_OFS_Y=LV_STYLE_SHADOW_OFFSET_Y +LV_STYLE_TRANSFORM_ANGLE=LV_STYLE_TRANSFORM_ROTATION + +LV_ZOOM_NONE=LV_SCALE_NONE // ====================================================================== // Generated from headers // ====================================================================== -// File: ../../lvgl/src/core/lv_disp.h -LV_SCR_LOAD_ANIM_NONE -LV_SCR_LOAD_ANIM_OVER_LEFT -LV_SCR_LOAD_ANIM_OVER_RIGHT -LV_SCR_LOAD_ANIM_OVER_TOP -LV_SCR_LOAD_ANIM_OVER_BOTTOM -LV_SCR_LOAD_ANIM_MOVE_LEFT -LV_SCR_LOAD_ANIM_MOVE_RIGHT -LV_SCR_LOAD_ANIM_MOVE_TOP -LV_SCR_LOAD_ANIM_MOVE_BOTTOM -LV_SCR_LOAD_ANIM_FADE_IN -LV_SCR_LOAD_ANIM_FADE_ON -LV_SCR_LOAD_ANIM_FADE_OUT -LV_SCR_LOAD_ANIM_OUT_LEFT -LV_SCR_LOAD_ANIM_OUT_RIGHT -LV_SCR_LOAD_ANIM_OUT_TOP -LV_SCR_LOAD_ANIM_OUT_BOTTOM - -// File: ../../lvgl/src/core/lv_event.h -LV_EVENT_ALL -LV_EVENT_PRESSED -LV_EVENT_PRESSING -LV_EVENT_PRESS_LOST -LV_EVENT_SHORT_CLICKED -LV_EVENT_LONG_PRESSED -LV_EVENT_LONG_PRESSED_REPEAT -LV_EVENT_CLICKED -LV_EVENT_RELEASED -LV_EVENT_SCROLL_BEGIN -LV_EVENT_SCROLL_END -LV_EVENT_SCROLL -LV_EVENT_GESTURE -LV_EVENT_KEY -LV_EVENT_FOCUSED -LV_EVENT_DEFOCUSED -LV_EVENT_LEAVE -LV_EVENT_HIT_TEST -LV_EVENT_COVER_CHECK -LV_EVENT_REFR_EXT_DRAW_SIZE -LV_EVENT_DRAW_MAIN_BEGIN -LV_EVENT_DRAW_MAIN -LV_EVENT_DRAW_MAIN_END -LV_EVENT_DRAW_POST_BEGIN -LV_EVENT_DRAW_POST -LV_EVENT_DRAW_POST_END -LV_EVENT_DRAW_PART_BEGIN -LV_EVENT_DRAW_PART_END -LV_EVENT_VALUE_CHANGED -LV_EVENT_INSERT -LV_EVENT_REFRESH -LV_EVENT_READY -LV_EVENT_CANCEL -LV_EVENT_DELETE -LV_EVENT_CHILD_CHANGED -LV_EVENT_CHILD_CREATED -LV_EVENT_CHILD_DELETED -LV_EVENT_SCREEN_UNLOAD_START -LV_EVENT_SCREEN_LOAD_START -LV_EVENT_SCREEN_LOADED -LV_EVENT_SCREEN_UNLOADED -LV_EVENT_SIZE_CHANGED -LV_EVENT_STYLE_CHANGED -LV_EVENT_LAYOUT_CHANGED -LV_EVENT_GET_SELF_SIZE -LV_EVENT_PREPROCESS - +// File: ../../lvgl/src/core/lv_global.h // File: ../../lvgl/src/core/lv_group.h LV_KEY_UP LV_KEY_DOWN @@ -199,8 +173,6 @@ LV_KEY_END LV_GROUP_REFOCUS_POLICY_NEXT LV_GROUP_REFOCUS_POLICY_PREV -// File: ../../lvgl/src/core/lv_indev.h -// File: ../../lvgl/src/core/lv_indev_scroll.h // File: ../../lvgl/src/core/lv_obj.h LV_STATE_DEFAULT LV_STATE_CHECKED @@ -223,7 +195,6 @@ LV_PART_INDICATOR LV_PART_KNOB LV_PART_SELECTED LV_PART_ITEMS -LV_PART_TICKS LV_PART_CURSOR LV_PART_CUSTOM_FIRST LV_PART_ANY @@ -248,7 +219,9 @@ LV_OBJ_FLAG_GESTURE_BUBBLE LV_OBJ_FLAG_ADV_HITTEST LV_OBJ_FLAG_IGNORE_LAYOUT LV_OBJ_FLAG_FLOATING +LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS LV_OBJ_FLAG_OVERFLOW_VISIBLE +LV_OBJ_FLAG_FLEX_IN_NEW_TRACK LV_OBJ_FLAG_LAYOUT_1 LV_OBJ_FLAG_LAYOUT_2 LV_OBJ_FLAG_WIDGET_1 @@ -258,10 +231,6 @@ LV_OBJ_FLAG_USER_2 LV_OBJ_FLAG_USER_3 LV_OBJ_FLAG_USER_4 -LV_OBJ_DRAW_PART_RECTANGLE -LV_OBJ_DRAW_PART_BORDER_POST -LV_OBJ_DRAW_PART_SCROLLBAR - // File: ../../lvgl/src/core/lv_obj_class.h LV_OBJ_CLASS_EDITABLE_INHERIT LV_OBJ_CLASS_EDITABLE_TRUE @@ -271,16 +240,21 @@ LV_OBJ_CLASS_GROUP_DEF_INHERIT LV_OBJ_CLASS_GROUP_DEF_TRUE LV_OBJ_CLASS_GROUP_DEF_FALSE -// File: ../../lvgl/src/core/lv_obj_draw.h -LV_COVER_RES_COVER -LV_COVER_RES_NOT_COVER -LV_COVER_RES_MASKED +LV_OBJ_CLASS_THEME_INHERITABLE_FALSE +LV_OBJ_CLASS_THEME_INHERITABLE_TRUE +// File: ../../lvgl/src/core/lv_obj_draw.h LV_LAYER_TYPE_NONE LV_LAYER_TYPE_SIMPLE LV_LAYER_TYPE_TRANSFORM +// File: ../../lvgl/src/core/lv_obj_event.h +LV_COVER_RES_COVER +LV_COVER_RES_NOT_COVER +LV_COVER_RES_MASKED + // File: ../../lvgl/src/core/lv_obj_pos.h +// File: ../../lvgl/src/core/lv_obj_property.h // File: ../../lvgl/src/core/lv_obj_scroll.h LV_SCROLLBAR_MODE_OFF LV_SCROLLBAR_MODE_ON @@ -300,200 +274,134 @@ LV_OBJ_TREE_WALK_SKIP_CHILDREN LV_OBJ_TREE_WALK_END // File: ../../lvgl/src/core/lv_refr.h -// File: ../../lvgl/src/core/lv_theme.h +// File: ../../lvgl/src/display/lv_display.h +LV_DISPLAY_ROTATION_0 +LV_DISPLAY_ROTATION_90 +LV_DISPLAY_ROTATION_180 +LV_DISPLAY_ROTATION_270 +LV_DISPLAY_RENDER_MODE_PARTIAL +LV_DISPLAY_RENDER_MODE_DIRECT +LV_DISPLAY_RENDER_MODE_FULL + +LV_SCR_LOAD_ANIM_NONE +LV_SCR_LOAD_ANIM_OVER_LEFT +LV_SCR_LOAD_ANIM_OVER_RIGHT +LV_SCR_LOAD_ANIM_OVER_TOP +LV_SCR_LOAD_ANIM_OVER_BOTTOM +LV_SCR_LOAD_ANIM_MOVE_LEFT +LV_SCR_LOAD_ANIM_MOVE_RIGHT +LV_SCR_LOAD_ANIM_MOVE_TOP +LV_SCR_LOAD_ANIM_MOVE_BOTTOM +LV_SCR_LOAD_ANIM_FADE_IN +LV_SCR_LOAD_ANIM_FADE_ON +LV_SCR_LOAD_ANIM_FADE_OUT +LV_SCR_LOAD_ANIM_OUT_LEFT +LV_SCR_LOAD_ANIM_OUT_RIGHT +LV_SCR_LOAD_ANIM_OUT_TOP +LV_SCR_LOAD_ANIM_OUT_BOTTOM + // File: ../../lvgl/src/draw/lv_draw.h +LV_DRAW_TASK_TYPE_FILL +LV_DRAW_TASK_TYPE_BORDER +LV_DRAW_TASK_TYPE_BOX_SHADOW +LV_DRAW_TASK_TYPE_LABEL +LV_DRAW_TASK_TYPE_IMAGE +LV_DRAW_TASK_TYPE_LAYER +LV_DRAW_TASK_TYPE_LINE +LV_DRAW_TASK_TYPE_ARC +LV_DRAW_TASK_TYPE_TRIANGLE +LV_DRAW_TASK_TYPE_MASK_RECTANGLE +LV_DRAW_TASK_TYPE_MASK_BITMAP +LV_DRAW_TASK_TYPE_VECTOR + +LV_DRAW_TASK_STATE_WAITING +LV_DRAW_TASK_STATE_QUEUED +LV_DRAW_TASK_STATE_IN_PROGRESS +LV_DRAW_TASK_STATE_READY + // File: ../../lvgl/src/draw/lv_draw_arc.h -// File: ../../lvgl/src/draw/lv_draw_img.h +// File: ../../lvgl/src/draw/lv_draw_buf.h +LV_STRIDE_AUTO +// File: ../../lvgl/src/draw/lv_draw_image.h // File: ../../lvgl/src/draw/lv_draw_label.h -// File: ../../lvgl/src/draw/lv_draw_layer.h -LV_DRAW_LAYER_FLAG_NONE -LV_DRAW_LAYER_FLAG_HAS_ALPHA -LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE +LV_DRAW_LETTER_BITMAP_FORMAT_INVALID +LV_DRAW_LETTER_BITMAP_FORMAT_A8 +LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE +LV_DRAW_LETTER_VECTOR_FORMAT // File: ../../lvgl/src/draw/lv_draw_line.h // File: ../../lvgl/src/draw/lv_draw_mask.h -LV_DRAW_MASK_RES_TRANSP -LV_DRAW_MASK_RES_FULL_COVER -LV_DRAW_MASK_RES_CHANGED -LV_DRAW_MASK_RES_UNKNOWN -LV_DRAW_MASK_TYPE_LINE -LV_DRAW_MASK_TYPE_ANGLE -LV_DRAW_MASK_TYPE_RADIUS -LV_DRAW_MASK_TYPE_FADE -LV_DRAW_MASK_TYPE_MAP -LV_DRAW_MASK_TYPE_POLYGON - -LV_DRAW_MASK_LINE_SIDE_LEFT -LV_DRAW_MASK_LINE_SIDE_RIGHT -LV_DRAW_MASK_LINE_SIDE_TOP -LV_DRAW_MASK_LINE_SIDE_BOTTOM - // File: ../../lvgl/src/draw/lv_draw_rect.h LV_RADIUS_CIRCLE -// File: ../../lvgl/src/draw/lv_draw_transform.h // File: ../../lvgl/src/draw/lv_draw_triangle.h -// File: ../../lvgl/src/draw/lv_img_buf.h -LV_IMG_CF_UNKNOWN -LV_IMG_CF_RAW -LV_IMG_CF_RAW_ALPHA -LV_IMG_CF_RAW_CHROMA_KEYED -LV_IMG_CF_TRUE_COLOR -LV_IMG_CF_TRUE_COLOR_ALPHA -LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED -LV_IMG_CF_INDEXED_1BIT -LV_IMG_CF_INDEXED_2BIT -LV_IMG_CF_INDEXED_4BIT -LV_IMG_CF_INDEXED_8BIT -LV_IMG_CF_ALPHA_1BIT -LV_IMG_CF_ALPHA_2BIT -LV_IMG_CF_ALPHA_4BIT -LV_IMG_CF_ALPHA_8BIT -LV_IMG_CF_RGB888 -LV_IMG_CF_RGBA8888 -LV_IMG_CF_RGBX8888 -LV_IMG_CF_RGB565 -LV_IMG_CF_RGBA5658 -LV_IMG_CF_RGB565A8 +// File: ../../lvgl/src/draw/lv_draw_vector.h +LV_VECTOR_FILL_NONZERO +LV_VECTOR_FILL_EVENODD -// File: ../../lvgl/src/draw/lv_img_cache.h -// File: ../../lvgl/src/draw/lv_img_decoder.h -LV_IMG_SRC_VARIABLE -LV_IMG_SRC_FILE -LV_IMG_SRC_SYMBOL -LV_IMG_SRC_UNKNOWN +LV_VECTOR_STROKE_CAP_BUTT +LV_VECTOR_STROKE_CAP_SQUARE +LV_VECTOR_STROKE_CAP_ROUND -// File: ../../lvgl/src/extra/layouts/flex/lv_flex.h -LV_FLEX_ALIGN_START -LV_FLEX_ALIGN_END -LV_FLEX_ALIGN_CENTER -LV_FLEX_ALIGN_SPACE_EVENLY -LV_FLEX_ALIGN_SPACE_AROUND -LV_FLEX_ALIGN_SPACE_BETWEEN +LV_VECTOR_STROKE_JOIN_MITER +LV_VECTOR_STROKE_JOIN_BEVEL +LV_VECTOR_STROKE_JOIN_ROUND -LV_FLEX_FLOW_ROW -LV_FLEX_FLOW_COLUMN -LV_FLEX_FLOW_ROW_WRAP -LV_FLEX_FLOW_ROW_REVERSE -LV_FLEX_FLOW_ROW_WRAP_REVERSE -LV_FLEX_FLOW_COLUMN_WRAP -LV_FLEX_FLOW_COLUMN_REVERSE -LV_FLEX_FLOW_COLUMN_WRAP_REVERSE +LV_VECTOR_PATH_QUALITY_MEDIUM +LV_VECTOR_PATH_QUALITY_HIGH +LV_VECTOR_PATH_QUALITY_LOW -LV_OBJ_FLAG_FLEX_IN_NEW_TRACK -// File: ../../lvgl/src/extra/layouts/grid/lv_grid.h -LV_GRID_ALIGN_START -LV_GRID_ALIGN_CENTER -LV_GRID_ALIGN_END -LV_GRID_ALIGN_STRETCH -LV_GRID_ALIGN_SPACE_EVENLY -LV_GRID_ALIGN_SPACE_AROUND -LV_GRID_ALIGN_SPACE_BETWEEN +LV_VECTOR_BLEND_SRC_OVER +LV_VECTOR_BLEND_SRC_IN +LV_VECTOR_BLEND_DST_OVER +LV_VECTOR_BLEND_DST_IN +LV_VECTOR_BLEND_SCREEN +LV_VECTOR_BLEND_MULTIPLY +LV_VECTOR_BLEND_NONE +LV_VECTOR_BLEND_ADDITIVE +LV_VECTOR_BLEND_SUBTRACTIVE -LV_GRID_CONTENT -LV_GRID_TEMPLATE_LAST -// File: ../../lvgl/src/extra/layouts/lv_layouts.h -// File: ../../lvgl/src/extra/widgets/animimg/lv_animimg.h -LV_ANIM_IMG_PART_MAIN +LV_VECTOR_PATH_OP_MOVE_TO +LV_VECTOR_PATH_OP_LINE_TO +LV_VECTOR_PATH_OP_QUAD_TO +LV_VECTOR_PATH_OP_CUBIC_TO +LV_VECTOR_PATH_OP_CLOSE -// File: ../../lvgl/src/extra/widgets/calendar/lv_calendar.h -// File: ../../lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.h -// File: ../../lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.h -// File: ../../lvgl/src/extra/widgets/chart/lv_chart.h -LV_CHART_TYPE_NONE -LV_CHART_TYPE_LINE -LV_CHART_TYPE_BAR -LV_CHART_TYPE_SCATTER +LV_VECTOR_DRAW_STYLE_SOLID +LV_VECTOR_DRAW_STYLE_PATTERN +LV_VECTOR_DRAW_STYLE_GRADIENT -LV_CHART_UPDATE_MODE_SHIFT -LV_CHART_UPDATE_MODE_CIRCULAR +LV_VECTOR_GRADIENT_SPREAD_PAD +LV_VECTOR_GRADIENT_SPREAD_REPEAT +LV_VECTOR_GRADIENT_SPREAD_REFLECT -LV_CHART_AXIS_PRIMARY_Y -LV_CHART_AXIS_SECONDARY_Y -LV_CHART_AXIS_PRIMARY_X -LV_CHART_AXIS_SECONDARY_X -LV_CHART_DRAW_PART_DIV_LINE_INIT -LV_CHART_DRAW_PART_DIV_LINE_HOR -LV_CHART_DRAW_PART_DIV_LINE_VER -LV_CHART_DRAW_PART_LINE_AND_POINT -LV_CHART_DRAW_PART_BAR -LV_CHART_DRAW_PART_CURSOR -LV_CHART_DRAW_PART_TICK_LABEL +LV_VECTOR_GRADIENT_STYLE_LINEAR +LV_VECTOR_GRADIENT_STYLE_RADIAL -LV_CHART_POINT_NONE -// File: ../../lvgl/src/extra/widgets/colorwheel/lv_colorwheel.h -LV_COLORWHEEL_MODE_HUE -LV_COLORWHEEL_MODE_SATURATION -LV_COLORWHEEL_MODE_VALUE -// File: ../../lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h -LV_IMGBTN_STATE_RELEASED -LV_IMGBTN_STATE_PRESSED -LV_IMGBTN_STATE_DISABLED -LV_IMGBTN_STATE_CHECKED_RELEASED -LV_IMGBTN_STATE_CHECKED_PRESSED -LV_IMGBTN_STATE_CHECKED_DISABLED +// File: ../../lvgl/src/draw/lv_image_buf.h +LV_IMAGE_FLAGS_PREMULTIPLIED +LV_IMAGE_FLAGS_MODIFIABLE +LV_IMAGE_FLAGS_VECTORS +LV_IMAGE_FLAGS_COMPRESSED +LV_IMAGE_FLAGS_ALLOCATED +LV_IMAGE_FLAGS_USER1 +LV_IMAGE_FLAGS_USER2 +LV_IMAGE_FLAGS_USER3 +LV_IMAGE_FLAGS_USER4 +LV_IMAGE_FLAGS_USER5 +LV_IMAGE_FLAGS_USER6 +LV_IMAGE_FLAGS_USER7 +LV_IMAGE_FLAGS_USER8 -// File: ../../lvgl/src/extra/widgets/keyboard/lv_keyboard.h -LV_KEYBOARD_MODE_TEXT_LOWER -LV_KEYBOARD_MODE_TEXT_UPPER -LV_KEYBOARD_MODE_SPECIAL -LV_KEYBOARD_MODE_NUMBER -LV_KEYBOARD_MODE_USER_1 -LV_KEYBOARD_MODE_USER_2 -LV_KEYBOARD_MODE_USER_3 -LV_KEYBOARD_MODE_USER_4 +LV_IMAGE_COMPRESS_NONE +LV_IMAGE_COMPRESS_RLE +LV_IMAGE_COMPRESS_LZ4 -// File: ../../lvgl/src/extra/widgets/led/lv_led.h -LV_LED_DRAW_PART_RECTANGLE +// File: ../../lvgl/src/draw/lv_image_decoder.h +LV_IMAGE_SRC_VARIABLE +LV_IMAGE_SRC_FILE +LV_IMAGE_SRC_SYMBOL +LV_IMAGE_SRC_UNKNOWN -// File: ../../lvgl/src/extra/widgets/list/lv_list.h -// File: ../../lvgl/src/extra/widgets/lv_widgets.h -// File: ../../lvgl/src/extra/widgets/menu/lv_menu.h -LV_MENU_HEADER_TOP_FIXED -LV_MENU_HEADER_TOP_UNFIXED -LV_MENU_HEADER_BOTTOM_FIXED -LV_MENU_ROOT_BACK_BTN_DISABLED -LV_MENU_ROOT_BACK_BTN_ENABLED -// File: ../../lvgl/src/extra/widgets/meter/lv_meter.h -LV_METER_INDICATOR_TYPE_NEEDLE_IMG -LV_METER_INDICATOR_TYPE_NEEDLE_LINE -LV_METER_INDICATOR_TYPE_SCALE_LINES -LV_METER_INDICATOR_TYPE_ARC - -LV_METER_DRAW_PART_ARC -LV_METER_DRAW_PART_NEEDLE_LINE -LV_METER_DRAW_PART_NEEDLE_IMG -LV_METER_DRAW_PART_TICK - -// File: ../../lvgl/src/extra/widgets/msgbox/lv_msgbox.h -// File: ../../lvgl/src/extra/widgets/span/lv_span.h -LV_SPAN_OVERFLOW_CLIP -LV_SPAN_OVERFLOW_ELLIPSIS - -LV_SPAN_MODE_FIXED -LV_SPAN_MODE_EXPAND -LV_SPAN_MODE_BREAK - -// File: ../../lvgl/src/extra/widgets/spinbox/lv_spinbox.h -// File: ../../lvgl/src/extra/widgets/spinner/lv_spinner.h -// File: ../../lvgl/src/extra/widgets/tabview/lv_tabview.h -// File: ../../lvgl/src/extra/widgets/tileview/lv_tileview.h -// File: ../../lvgl/src/extra/widgets/win/lv_win.h -// File: ../../lvgl/src/hal/lv_hal.h -// File: ../../lvgl/src/hal/lv_hal_disp.h -LV_DISP_ROT_NONE -LV_DISP_ROT_90 -LV_DISP_ROT_180 -LV_DISP_ROT_270 -// File: ../../lvgl/src/hal/lv_hal_indev.h -LV_INDEV_TYPE_NONE -LV_INDEV_TYPE_POINTER -LV_INDEV_TYPE_KEYPAD -LV_INDEV_TYPE_BUTTON -LV_INDEV_TYPE_ENCODER - -LV_INDEV_STATE_RELEASED -LV_INDEV_STATE_PRESSED -// File: ../../lvgl/src/hal/lv_hal_tick.h // File: ../../lvgl/src/misc/lv_anim.h LV_ANIM_OFF LV_ANIM_ON @@ -537,6 +445,7 @@ LV_DIR_ALL LV_SIZE_CONTENT LV_COORD_MAX LV_COORD_MIN +// File: ../../lvgl/src/misc/lv_array.h // File: ../../lvgl/src/misc/lv_assert.h // File: ../../lvgl/src/misc/lv_async.h // File: ../../lvgl/src/misc/lv_bidi.h @@ -561,29 +470,104 @@ LV_OPA_90 LV_OPA_100 LV_OPA_COVER -LV_PALETTE_RED -LV_PALETTE_PINK -LV_PALETTE_PURPLE -LV_PALETTE_DEEP_PURPLE -LV_PALETTE_INDIGO -LV_PALETTE_BLUE -LV_PALETTE_LIGHT_BLUE -LV_PALETTE_CYAN -LV_PALETTE_TEAL -LV_PALETTE_GREEN -LV_PALETTE_LIGHT_GREEN -LV_PALETTE_LIME -LV_PALETTE_YELLOW -LV_PALETTE_AMBER -LV_PALETTE_ORANGE -LV_PALETTE_DEEP_ORANGE -LV_PALETTE_BROWN -LV_PALETTE_BLUE_GREY -LV_PALETTE_GREY -LV_PALETTE_NONE +LV_COLOR_FORMAT_UNKNOWN +LV_COLOR_FORMAT_RAW +LV_COLOR_FORMAT_RAW_ALPHA +LV_COLOR_FORMAT_L8 +LV_COLOR_FORMAT_I1 +LV_COLOR_FORMAT_I2 +LV_COLOR_FORMAT_I4 +LV_COLOR_FORMAT_I8 +LV_COLOR_FORMAT_A8 +LV_COLOR_FORMAT_RGB565 +LV_COLOR_FORMAT_RGB565A8 +LV_COLOR_FORMAT_RGB888 +LV_COLOR_FORMAT_ARGB8888 +LV_COLOR_FORMAT_XRGB8888 +LV_COLOR_FORMAT_A1 +LV_COLOR_FORMAT_A2 +LV_COLOR_FORMAT_A4 +LV_COLOR_FORMAT_YUV_START +LV_COLOR_FORMAT_I420 +LV_COLOR_FORMAT_I422 +LV_COLOR_FORMAT_I444 +LV_COLOR_FORMAT_I400 +LV_COLOR_FORMAT_NV21 +LV_COLOR_FORMAT_NV12 +LV_COLOR_FORMAT_YUY2 +LV_COLOR_FORMAT_UYVY +LV_COLOR_FORMAT_YUV_END +LV_COLOR_FORMAT_NATIVE +LV_COLOR_FORMAT_NATIVE +LV_COLOR_FORMAT_NATIVE_WITH_ALPHA +LV_COLOR_FORMAT_NATIVE +LV_COLOR_FORMAT_NATIVE_WITH_ALPHA +LV_COLOR_FORMAT_NATIVE +LV_COLOR_FORMAT_NATIVE_WITH_ALPHA LV_COLOR_DEPTH -LV_COLOR_16_SWAP +// File: ../../lvgl/src/misc/lv_color_op.h +// File: ../../lvgl/src/misc/lv_event.h +LV_EVENT_ALL +LV_EVENT_PRESSED +LV_EVENT_PRESSING +LV_EVENT_PRESS_LOST +LV_EVENT_SHORT_CLICKED +LV_EVENT_LONG_PRESSED +LV_EVENT_LONG_PRESSED_REPEAT +LV_EVENT_CLICKED +LV_EVENT_RELEASED +LV_EVENT_SCROLL_BEGIN +LV_EVENT_SCROLL_THROW_BEGIN +LV_EVENT_SCROLL_END +LV_EVENT_SCROLL +LV_EVENT_GESTURE +LV_EVENT_KEY +LV_EVENT_FOCUSED +LV_EVENT_DEFOCUSED +LV_EVENT_LEAVE +LV_EVENT_HIT_TEST +LV_EVENT_INDEV_RESET +LV_EVENT_COVER_CHECK +LV_EVENT_REFR_EXT_DRAW_SIZE +LV_EVENT_DRAW_MAIN_BEGIN +LV_EVENT_DRAW_MAIN +LV_EVENT_DRAW_MAIN_END +LV_EVENT_DRAW_POST_BEGIN +LV_EVENT_DRAW_POST +LV_EVENT_DRAW_POST_END +LV_EVENT_DRAW_TASK_ADDED +LV_EVENT_VALUE_CHANGED +LV_EVENT_INSERT +LV_EVENT_REFRESH +LV_EVENT_READY +LV_EVENT_CANCEL +LV_EVENT_CREATE +LV_EVENT_DELETE +LV_EVENT_CHILD_CHANGED +LV_EVENT_CHILD_CREATED +LV_EVENT_CHILD_DELETED +LV_EVENT_SCREEN_UNLOAD_START +LV_EVENT_SCREEN_LOAD_START +LV_EVENT_SCREEN_LOADED +LV_EVENT_SCREEN_UNLOADED +LV_EVENT_SIZE_CHANGED +LV_EVENT_STYLE_CHANGED +LV_EVENT_LAYOUT_CHANGED +LV_EVENT_GET_SELF_SIZE +LV_EVENT_INVALIDATE_AREA +LV_EVENT_RESOLUTION_CHANGED +LV_EVENT_COLOR_FORMAT_CHANGED +LV_EVENT_REFR_REQUEST +LV_EVENT_REFR_START +LV_EVENT_REFR_READY +LV_EVENT_RENDER_START +LV_EVENT_RENDER_READY +LV_EVENT_FLUSH_START +LV_EVENT_FLUSH_FINISH +LV_EVENT_VSYNC +LV_EVENT_PREPROCESS + // File: ../../lvgl/src/misc/lv_fs.h LV_FS_RES_OK LV_FS_RES_HW_ERR @@ -606,7 +590,6 @@ LV_FS_SEEK_SET LV_FS_SEEK_CUR LV_FS_SEEK_END -// File: ../../lvgl/src/misc/lv_gc.h // File: ../../lvgl/src/misc/lv_ll.h // File: ../../lvgl/src/misc/lv_log.h LV_LOG_LEVEL_TRACE @@ -617,14 +600,38 @@ LV_LOG_LEVEL_USER LV_LOG_LEVEL_NONE // File: ../../lvgl/src/misc/lv_lru.h // File: ../../lvgl/src/misc/lv_math.h -// File: ../../lvgl/src/misc/lv_mem.h -// File: ../../lvgl/src/misc/lv_printf.h +// File: ../../lvgl/src/misc/lv_palette.h +LV_PALETTE_RED +LV_PALETTE_PINK +LV_PALETTE_PURPLE +LV_PALETTE_DEEP_PURPLE +LV_PALETTE_INDIGO +LV_PALETTE_BLUE +LV_PALETTE_LIGHT_BLUE +LV_PALETTE_CYAN +LV_PALETTE_TEAL +LV_PALETTE_GREEN +LV_PALETTE_LIGHT_GREEN +LV_PALETTE_LIME +LV_PALETTE_YELLOW +LV_PALETTE_AMBER +LV_PALETTE_ORANGE +LV_PALETTE_DEEP_ORANGE +LV_PALETTE_BROWN +LV_PALETTE_BLUE_GREY +LV_PALETTE_GREY +LV_PALETTE_NONE + +// File: ../../lvgl/src/misc/lv_profiler.h +// File: ../../lvgl/src/misc/lv_profiler_builtin.h +// File: ../../lvgl/src/misc/lv_rb.h +LV_RB_COLOR_RED +LV_RB_COLOR_BLACK // File: ../../lvgl/src/misc/lv_style.h LV_BLEND_MODE_NORMAL LV_BLEND_MODE_ADDITIVE LV_BLEND_MODE_SUBTRACTIVE LV_BLEND_MODE_MULTIPLY -LV_BLEND_MODE_REPLACE LV_TEXT_DECOR_NONE LV_TEXT_DECOR_UNDERLINE @@ -642,21 +649,17 @@ LV_GRAD_DIR_NONE LV_GRAD_DIR_VER LV_GRAD_DIR_HOR -LV_DITHER_NONE -LV_DITHER_ORDERED -LV_DITHER_ERR_DIFF - LV_STYLE_PROP_INV LV_STYLE_WIDTH +LV_STYLE_HEIGHT +LV_STYLE_LENGTH LV_STYLE_MIN_WIDTH LV_STYLE_MAX_WIDTH -LV_STYLE_HEIGHT LV_STYLE_MIN_HEIGHT LV_STYLE_MAX_HEIGHT LV_STYLE_X LV_STYLE_Y LV_STYLE_ALIGN -LV_STYLE_LAYOUT LV_STYLE_RADIUS LV_STYLE_PAD_TOP LV_STYLE_PAD_BOTTOM @@ -664,24 +667,30 @@ LV_STYLE_PAD_LEFT LV_STYLE_PAD_RIGHT LV_STYLE_PAD_ROW LV_STYLE_PAD_COLUMN -LV_STYLE_BASE_DIR -LV_STYLE_CLIP_CORNER +LV_STYLE_LAYOUT +LV_STYLE_MARGIN_TOP +LV_STYLE_MARGIN_BOTTOM +LV_STYLE_MARGIN_LEFT +LV_STYLE_MARGIN_RIGHT LV_STYLE_BG_COLOR LV_STYLE_BG_OPA -LV_STYLE_BG_GRAD_COLOR LV_STYLE_BG_GRAD_DIR LV_STYLE_BG_MAIN_STOP LV_STYLE_BG_GRAD_STOP +LV_STYLE_BG_GRAD_COLOR +LV_STYLE_BG_MAIN_OPA +LV_STYLE_BG_GRAD_OPA LV_STYLE_BG_GRAD -LV_STYLE_BG_DITHER_MODE -LV_STYLE_BG_IMG_SRC -LV_STYLE_BG_IMG_OPA -LV_STYLE_BG_IMG_RECOLOR -LV_STYLE_BG_IMG_RECOLOR_OPA -LV_STYLE_BG_IMG_TILED +LV_STYLE_BASE_DIR +LV_STYLE_BG_IMAGE_SRC +LV_STYLE_BG_IMAGE_OPA +LV_STYLE_BG_IMAGE_RECOLOR +LV_STYLE_BG_IMAGE_RECOLOR_OPA +LV_STYLE_BG_IMAGE_TILED +LV_STYLE_CLIP_CORNER +LV_STYLE_BORDER_WIDTH LV_STYLE_BORDER_COLOR LV_STYLE_BORDER_OPA -LV_STYLE_BORDER_WIDTH LV_STYLE_BORDER_SIDE LV_STYLE_BORDER_POST LV_STYLE_OUTLINE_WIDTH @@ -689,14 +698,14 @@ LV_STYLE_OUTLINE_COLOR LV_STYLE_OUTLINE_OPA LV_STYLE_OUTLINE_PAD LV_STYLE_SHADOW_WIDTH -LV_STYLE_SHADOW_OFS_X -LV_STYLE_SHADOW_OFS_Y -LV_STYLE_SHADOW_SPREAD LV_STYLE_SHADOW_COLOR LV_STYLE_SHADOW_OPA -LV_STYLE_IMG_OPA -LV_STYLE_IMG_RECOLOR -LV_STYLE_IMG_RECOLOR_OPA +LV_STYLE_SHADOW_OFFSET_X +LV_STYLE_SHADOW_OFFSET_Y +LV_STYLE_SHADOW_SPREAD +LV_STYLE_IMAGE_OPA +LV_STYLE_IMAGE_RECOLOR +LV_STYLE_IMAGE_RECOLOR_OPA LV_STYLE_LINE_WIDTH LV_STYLE_LINE_DASH_WIDTH LV_STYLE_LINE_DASH_GAP @@ -707,7 +716,7 @@ LV_STYLE_ARC_WIDTH LV_STYLE_ARC_ROUNDED LV_STYLE_ARC_COLOR LV_STYLE_ARC_OPA -LV_STYLE_ARC_IMG_SRC +LV_STYLE_ARC_IMAGE_SRC LV_STYLE_TEXT_COLOR LV_STYLE_TEXT_OPA LV_STYLE_TEXT_FONT @@ -720,89 +729,136 @@ LV_STYLE_OPA_LAYERED LV_STYLE_COLOR_FILTER_DSC LV_STYLE_COLOR_FILTER_OPA LV_STYLE_ANIM -LV_STYLE_ANIM_TIME -LV_STYLE_ANIM_SPEED +LV_STYLE_ANIM_DURATION LV_STYLE_TRANSITION LV_STYLE_BLEND_MODE LV_STYLE_TRANSFORM_WIDTH LV_STYLE_TRANSFORM_HEIGHT LV_STYLE_TRANSLATE_X LV_STYLE_TRANSLATE_Y -LV_STYLE_TRANSFORM_ZOOM -LV_STYLE_TRANSFORM_ANGLE +LV_STYLE_TRANSFORM_SCALE_X +LV_STYLE_TRANSFORM_SCALE_Y +LV_STYLE_TRANSFORM_ROTATION LV_STYLE_TRANSFORM_PIVOT_X LV_STYLE_TRANSFORM_PIVOT_Y +LV_STYLE_TRANSFORM_SKEW_X +LV_STYLE_TRANSFORM_SKEW_Y +LV_STYLE_FLEX_FLOW +LV_STYLE_FLEX_MAIN_PLACE +LV_STYLE_FLEX_CROSS_PLACE +LV_STYLE_FLEX_TRACK_PLACE +LV_STYLE_FLEX_GROW +LV_STYLE_GRID_COLUMN_ALIGN +LV_STYLE_GRID_ROW_ALIGN +LV_STYLE_GRID_ROW_DSC_ARRAY +LV_STYLE_GRID_COLUMN_DSC_ARRAY +LV_STYLE_GRID_CELL_COLUMN_POS +LV_STYLE_GRID_CELL_COLUMN_SPAN +LV_STYLE_GRID_CELL_X_ALIGN +LV_STYLE_GRID_CELL_ROW_POS +LV_STYLE_GRID_CELL_ROW_SPAN +LV_STYLE_GRID_CELL_Y_ALIGN LV_STYLE_PROP_ANY LV_STYLE_RES_NOT_FOUND LV_STYLE_RES_FOUND -LV_STYLE_RES_INHERIT -LV_IMG_ZOOM_NONE + +LV_SCALE_NONE // File: ../../lvgl/src/misc/lv_style_gen.h // File: ../../lvgl/src/misc/lv_templ.h -// File: ../../lvgl/src/misc/lv_timer.h -// File: ../../lvgl/src/misc/lv_tlsf.h -// File: ../../lvgl/src/misc/lv_txt.h +// File: ../../lvgl/src/misc/lv_text.h LV_TEXT_FLAG_NONE -LV_TEXT_FLAG_RECOLOR LV_TEXT_FLAG_EXPAND LV_TEXT_FLAG_FIT -LV_TEXT_CMD_STATE_WAIT -LV_TEXT_CMD_STATE_PAR -LV_TEXT_CMD_STATE_IN - LV_TEXT_ALIGN_AUTO LV_TEXT_ALIGN_LEFT LV_TEXT_ALIGN_CENTER LV_TEXT_ALIGN_RIGHT -// File: ../../lvgl/src/misc/lv_txt_ap.h +// File: ../../lvgl/src/misc/lv_text_ap.h +// File: ../../lvgl/src/misc/lv_timer.h // File: ../../lvgl/src/misc/lv_types.h -LV_RES_INV -LV_RES_OK +LV_RESULT_INVALID +LV_RESULT_OK // File: ../../lvgl/src/misc/lv_utils.h -// File: ../../lvgl/src/widgets/lv_arc.h +// File: ../../lvgl/src/widgets/animimage/lv_animimage.h +LV_ANIM_IMAGE_PART_MAIN + +// File: ../../lvgl/src/widgets/arc/lv_arc.h LV_ARC_MODE_NORMAL LV_ARC_MODE_SYMMETRICAL LV_ARC_MODE_REVERSE -LV_ARC_DRAW_PART_BACKGROUND -LV_ARC_DRAW_PART_FOREGROUND -LV_ARC_DRAW_PART_KNOB - -// File: ../../lvgl/src/widgets/lv_bar.h +// File: ../../lvgl/src/widgets/bar/lv_bar.h LV_BAR_MODE_NORMAL LV_BAR_MODE_SYMMETRICAL LV_BAR_MODE_RANGE -LV_BAR_DRAW_PART_INDICATOR +// File: ../../lvgl/src/widgets/button/lv_button.h +// File: ../../lvgl/src/widgets/buttonmatrix/lv_buttonmatrix.h +LV_BUTTONMATRIX_CTRL_HIDDEN +LV_BUTTONMATRIX_CTRL_NO_REPEAT +LV_BUTTONMATRIX_CTRL_DISABLED +LV_BUTTONMATRIX_CTRL_CHECKABLE +LV_BUTTONMATRIX_CTRL_CHECKED +LV_BUTTONMATRIX_CTRL_CLICK_TRIG +LV_BUTTONMATRIX_CTRL_POPOVER +LV_BUTTONMATRIX_CTRL_CUSTOM_1 +LV_BUTTONMATRIX_CTRL_CUSTOM_2 -// File: ../../lvgl/src/widgets/lv_btn.h -// File: ../../lvgl/src/widgets/lv_btnmatrix.h -LV_BTNMATRIX_CTRL_HIDDEN -LV_BTNMATRIX_CTRL_NO_REPEAT -LV_BTNMATRIX_CTRL_DISABLED -LV_BTNMATRIX_CTRL_CHECKABLE -LV_BTNMATRIX_CTRL_CHECKED -LV_BTNMATRIX_CTRL_CLICK_TRIG -LV_BTNMATRIX_CTRL_POPOVER -LV_BTNMATRIX_CTRL_RECOLOR -LV_BTNMATRIX_CTRL_CUSTOM_1 -LV_BTNMATRIX_CTRL_CUSTOM_2 +LV_BUTTONMATRIX_BUTTON_NONE +// File: ../../lvgl/src/widgets/calendar/lv_calendar.h +// File: ../../lvgl/src/widgets/calendar/lv_calendar_header_arrow.h +// File: ../../lvgl/src/widgets/calendar/lv_calendar_header_dropdown.h +// File: ../../lvgl/src/widgets/canvas/lv_canvas.h +// File: ../../lvgl/src/widgets/chart/lv_chart.h +LV_CHART_TYPE_NONE +LV_CHART_TYPE_LINE +LV_CHART_TYPE_BAR +LV_CHART_TYPE_SCATTER -LV_BTNMATRIX_DRAW_PART_BTN +LV_CHART_UPDATE_MODE_SHIFT +LV_CHART_UPDATE_MODE_CIRCULAR -LV_BTNMATRIX_BTN_NONE -// File: ../../lvgl/src/widgets/lv_canvas.h -// File: ../../lvgl/src/widgets/lv_checkbox.h -LV_CHECKBOX_DRAW_PART_BOX - -// File: ../../lvgl/src/widgets/lv_dropdown.h +LV_CHART_AXIS_PRIMARY_Y +LV_CHART_AXIS_SECONDARY_Y +LV_CHART_AXIS_PRIMARY_X +LV_CHART_AXIS_SECONDARY_X +LV_CHART_POINT_NONE +// File: ../../lvgl/src/widgets/checkbox/lv_checkbox.h +// File: ../../lvgl/src/widgets/dropdown/lv_dropdown.h LV_DROPDOWN_POS_LAST -// File: ../../lvgl/src/widgets/lv_img.h -LV_IMG_SIZE_MODE_VIRTUAL -LV_IMG_SIZE_MODE_REAL +// File: ../../lvgl/src/widgets/image/lv_image.h +LV_IMAGE_ALIGN_DEFAULT +LV_IMAGE_ALIGN_TOP_LEFT +LV_IMAGE_ALIGN_TOP_MID +LV_IMAGE_ALIGN_TOP_RIGHT +LV_IMAGE_ALIGN_BOTTOM_LEFT +LV_IMAGE_ALIGN_BOTTOM_MID +LV_IMAGE_ALIGN_BOTTOM_RIGHT +LV_IMAGE_ALIGN_LEFT_MID +LV_IMAGE_ALIGN_RIGHT_MID +LV_IMAGE_ALIGN_CENTER +LV_IMAGE_ALIGN_STRETCH +LV_IMAGE_ALIGN_TILE -// File: ../../lvgl/src/widgets/lv_label.h +// File: ../../lvgl/src/widgets/imagebutton/lv_imagebutton.h +LV_IMAGEBUTTON_STATE_RELEASED +LV_IMAGEBUTTON_STATE_PRESSED +LV_IMAGEBUTTON_STATE_DISABLED +LV_IMAGEBUTTON_STATE_CHECKED_RELEASED +LV_IMAGEBUTTON_STATE_CHECKED_PRESSED +LV_IMAGEBUTTON_STATE_CHECKED_DISABLED + +// File: ../../lvgl/src/widgets/keyboard/lv_keyboard.h +LV_KEYBOARD_MODE_TEXT_LOWER +LV_KEYBOARD_MODE_TEXT_UPPER +LV_KEYBOARD_MODE_SPECIAL +LV_KEYBOARD_MODE_NUMBER +LV_KEYBOARD_MODE_USER_1 +LV_KEYBOARD_MODE_USER_2 +LV_KEYBOARD_MODE_USER_3 +LV_KEYBOARD_MODE_USER_4 +// File: ../../lvgl/src/widgets/label/lv_label.h LV_LABEL_LONG_WRAP LV_LABEL_LONG_DOT LV_LABEL_LONG_SCROLL @@ -812,21 +868,46 @@ LV_LABEL_LONG_CLIP LV_LABEL_DOT_NUM LV_LABEL_POS_LAST LV_LABEL_TEXT_SELECTION_OFF -// File: ../../lvgl/src/widgets/lv_line.h -// File: ../../lvgl/src/widgets/lv_objx_templ.h -// File: ../../lvgl/src/widgets/lv_roller.h +// File: ../../lvgl/src/widgets/led/lv_led.h +// File: ../../lvgl/src/widgets/line/lv_line.h +// File: ../../lvgl/src/widgets/list/lv_list.h +// File: ../../lvgl/src/widgets/menu/lv_menu.h +LV_MENU_HEADER_TOP_FIXED +LV_MENU_HEADER_TOP_UNFIXED +LV_MENU_HEADER_BOTTOM_FIXED +LV_MENU_ROOT_BACK_BUTTON_DISABLED +LV_MENU_ROOT_BACK_BUTTON_ENABLED +// File: ../../lvgl/src/widgets/msgbox/lv_msgbox.h +// File: ../../lvgl/src/widgets/objx_templ/lv_objx_templ.h +// File: ../../lvgl/src/widgets/roller/lv_roller.h LV_ROLLER_MODE_NORMAL LV_ROLLER_MODE_INFINITE -// File: ../../lvgl/src/widgets/lv_slider.h +// File: ../../lvgl/src/widgets/scale/lv_scale.h +LV_SCALE_MODE_HORIZONTAL_TOP +LV_SCALE_MODE_HORIZONTAL_BOTTOM +LV_SCALE_MODE_VERTICAL_LEFT +LV_SCALE_MODE_VERTICAL_RIGHT +LV_SCALE_MODE_ROUND_INNER +LV_SCALE_MODE_ROUND_OUTER +LV_SCALE_TOTAL_TICK_COUNT_DEFAULT +LV_SCALE_MAJOR_TICK_EVERY_DEFAULT +LV_SCALE_LABEL_ENABLED_DEFAULT +// File: ../../lvgl/src/widgets/slider/lv_slider.h LV_SLIDER_MODE_NORMAL LV_SLIDER_MODE_SYMMETRICAL LV_SLIDER_MODE_RANGE -LV_SLIDER_DRAW_PART_KNOB -LV_SLIDER_DRAW_PART_KNOB_LEFT +// File: ../../lvgl/src/widgets/span/lv_span.h +LV_SPAN_OVERFLOW_CLIP +LV_SPAN_OVERFLOW_ELLIPSIS -// File: ../../lvgl/src/widgets/lv_switch.h -// File: ../../lvgl/src/widgets/lv_table.h +LV_SPAN_MODE_FIXED +LV_SPAN_MODE_EXPAND +LV_SPAN_MODE_BREAK +// File: ../../lvgl/src/widgets/spinbox/lv_spinbox.h +// File: ../../lvgl/src/widgets/spinner/lv_spinner.h +// File: ../../lvgl/src/widgets/switch/lv_switch.h +// File: ../../lvgl/src/widgets/table/lv_table.h LV_TABLE_CELL_CTRL_MERGE_RIGHT LV_TABLE_CELL_CTRL_TEXT_CROP LV_TABLE_CELL_CTRL_CUSTOM_1 @@ -834,10 +915,11 @@ LV_TABLE_CELL_CTRL_CUSTOM_2 LV_TABLE_CELL_CTRL_CUSTOM_3 LV_TABLE_CELL_CTRL_CUSTOM_4 -LV_TABLE_DRAW_PART_CELL - LV_TABLE_CELL_NONE -// File: ../../lvgl/src/widgets/lv_textarea.h +// File: ../../lvgl/src/widgets/tabview/lv_tabview.h +// File: ../../lvgl/src/widgets/textarea/lv_textarea.h LV_PART_TEXTAREA_PLACEHOLDER LV_TEXTAREA_CURSOR_LAST +// File: ../../lvgl/src/widgets/tileview/lv_tileview.h +// File: ../../lvgl/src/widgets/win/lv_win.h diff --git a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h index edfa2f4f5..7104025ba 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h +++ b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h @@ -3,15 +3,9 @@ // Extract function signatures from LVGL APIs in headers // Custom Tasmota functions -void lv_img_set_tasmota_logo(lv_obj_t * img); +void lv_image_set_tasmota_logo(lv_obj_t * img); lv_ts_calibration_t * lv_get_ts_calibration(void); -// ====================================================================== -// Artificial -// ====================================================================== - -lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix); - // ====================================================================== // LV top level functions // ====================================================================== @@ -20,84 +14,668 @@ lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix); lv_coord_t lv_get_hor_res(void); lv_coord_t lv_get_ver_res(void); -// layers -//static inline lv_obj_t * lv_layer_sys(void); -//static inline lv_obj_t * lv_layer_top(void); - // ====================================================================== // Generated from headers // ====================================================================== -// ../../lvgl/src/core/lv_disp.h -lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp) -lv_obj_t * lv_disp_get_scr_prev(lv_disp_t * disp) -void lv_disp_load_scr(lv_obj_t * scr) -lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp) -lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp) -void lv_disp_set_theme(lv_disp_t * disp, lv_theme_t * th) -lv_theme_t * lv_disp_get_theme(lv_disp_t * disp) -void lv_disp_set_bg_color(lv_disp_t * disp, lv_color_t color) -void lv_disp_set_bg_image(lv_disp_t * disp, const void * img_src) -void lv_disp_set_bg_opa(lv_disp_t * disp, lv_opa_t opa) -void lv_scr_load_anim(lv_obj_t * scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del) -uint32_t lv_disp_get_inactive_time(const lv_disp_t * disp) -void lv_disp_trig_activity(lv_disp_t * disp) -void lv_disp_clean_dcache(lv_disp_t * disp) -void lv_disp_enable_invalidation(lv_disp_t * disp, bool en) -bool lv_disp_is_invalidation_enabled(lv_disp_t * disp) -static inline lv_obj_t * lv_scr_act(void) -static inline lv_obj_t * lv_layer_top(void) -static inline lv_obj_t * lv_layer_sys(void) -static inline void lv_scr_load(lv_obj_t * scr) -static inline lv_coord_t lv_dpx(lv_coord_t n) -static inline lv_coord_t lv_disp_dpx(const lv_disp_t * disp, lv_coord_t n) +// ../../lvgl/src/../lvgl.h +static inline int lv_version_major(void) +static inline int lv_version_minor(void) +static inline int lv_version_patch(void) +static inline const char * lv_version_info(void) -// ../../lvgl/src/core/lv_event.h -lv_res_t lv_event_send(struct _lv_obj_t * obj, lv_event_code_t event_code, void * param) -lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e) -void lv_event_stop_bubbling(lv_event_t * e) -void lv_event_stop_processing(lv_event_t * e) -uint32_t lv_event_register_id(void) -struct _lv_event_dsc_t * lv_obj_add_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data) -bool lv_obj_remove_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb) -bool lv_obj_remove_event_cb_with_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb, const void * event_user_data) -bool lv_obj_remove_event_dsc(struct _lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc) -void * lv_obj_get_event_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb) -void lv_event_set_ext_draw_size(lv_event_t * e, lv_coord_t size) -void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res) +// ../../lvgl/src/core/lv_global.h +lv_global_t * lv_global_default(void) // ../../lvgl/src/core/lv_group.h lv_group_t * lv_group_create(void) -void lv_group_del(lv_group_t * group) +void lv_group_delete(lv_group_t * group) void lv_group_set_default(lv_group_t * group) lv_group_t * lv_group_get_default(void) -void lv_group_add_obj(lv_group_t * group, struct _lv_obj_t * obj) -void lv_group_swap_obj(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2) -void lv_group_remove_obj(struct _lv_obj_t * obj) +void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj) +void lv_group_swap_obj(lv_obj_t * obj1, lv_obj_t * obj2) +void lv_group_remove_obj(lv_obj_t * obj) void lv_group_remove_all_objs(lv_group_t * group) -void lv_group_focus_obj(struct _lv_obj_t * obj) +void lv_group_focus_obj(lv_obj_t * obj) void lv_group_focus_next(lv_group_t * group) void lv_group_focus_prev(lv_group_t * group) void lv_group_focus_freeze(lv_group_t * group, bool en) -lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c) +lv_result_t lv_group_send_data(lv_group_t * group, uint32_t c) void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb) void lv_group_set_edge_cb(lv_group_t * group, lv_group_edge_cb_t edge_cb) void lv_group_set_refocus_policy(lv_group_t * group, lv_group_refocus_policy_t policy) void lv_group_set_editing(lv_group_t * group, bool edit) void lv_group_set_wrap(lv_group_t * group, bool en) -struct _lv_obj_t * lv_group_get_focused(const lv_group_t * group) +lv_obj_t * lv_group_get_focused(const lv_group_t * group) lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group) lv_group_edge_cb_t lv_group_get_edge_cb(const lv_group_t * group) bool lv_group_get_editing(const lv_group_t * group) bool lv_group_get_wrap(lv_group_t * group) uint32_t lv_group_get_obj_count(lv_group_t * group) +uint32_t lv_group_get_count(void) +lv_group_t * lv_group_by_index(uint32_t index) -// ../../lvgl/src/core/lv_indev.h +// ../../lvgl/src/core/lv_obj.h +lv_obj_t * lv_obj_create(lv_obj_t * parent) +void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f) +void lv_obj_remove_flag(lv_obj_t * obj, lv_obj_flag_t f) +void lv_obj_update_flag(lv_obj_t * obj, lv_obj_flag_t f, bool v) +void lv_obj_add_state(lv_obj_t * obj, lv_state_t state) +void lv_obj_remove_state(lv_obj_t * obj, lv_state_t state) +void lv_obj_set_state(lv_obj_t * obj, lv_state_t state, bool v) +static inline void lv_obj_set_user_data(lv_obj_t * obj, void * user_data) +bool lv_obj_has_flag(const lv_obj_t * obj, lv_obj_flag_t f) +bool lv_obj_has_flag_any(const lv_obj_t * obj, lv_obj_flag_t f) +lv_state_t lv_obj_get_state(const lv_obj_t * obj) +bool lv_obj_has_state(const lv_obj_t * obj, lv_state_t state) +lv_group_t * lv_obj_get_group(const lv_obj_t * obj) +static inline void * lv_obj_get_user_data(lv_obj_t * obj) +void lv_obj_allocate_spec_attr(lv_obj_t * obj) +bool lv_obj_check_type(const lv_obj_t * obj, const lv_obj_class_t * class_p) +bool lv_obj_has_class(const lv_obj_t * obj, const lv_obj_class_t * class_p) +const lv_obj_class_t * lv_obj_get_class(const lv_obj_t * obj) +bool lv_obj_is_valid(const lv_obj_t * obj) +void lv_obj_assign_id(const lv_obj_class_t * class_p, lv_obj_t * obj) +void lv_obj_free_id(lv_obj_t * obj) +const char * lv_obj_stringify_id(lv_obj_t * obj, char * buf, uint32_t len) +void lv_objid_builtin_destroy(void) + +// ../../lvgl/src/core/lv_obj_class.h +lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * parent) +void lv_obj_class_init_obj(lv_obj_t * obj) +bool lv_obj_is_editable(lv_obj_t * obj) +bool lv_obj_is_group_def(lv_obj_t * obj) + +// ../../lvgl/src/core/lv_obj_draw.h +void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t * draw_dsc) +void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc) +void lv_obj_init_draw_image_dsc(lv_obj_t * obj, uint32_t part, lv_draw_image_dsc_t * draw_dsc) +void lv_obj_init_draw_line_dsc(lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc) +void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc) +int32_t lv_obj_calculate_ext_draw_size(lv_obj_t * obj, uint32_t part) +void lv_obj_refresh_ext_draw_size(lv_obj_t * obj) + +// ../../lvgl/src/core/lv_obj_event.h +lv_result_t lv_obj_send_event(lv_obj_t * obj, lv_event_code_t event_code, void * param) +lv_result_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e) +lv_obj_t * lv_event_get_current_target_obj(lv_event_t * e) +lv_obj_t * lv_event_get_target_obj(lv_event_t * e) +void lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data) +uint32_t lv_obj_get_event_count(lv_obj_t * obj) +lv_event_dsc_t * lv_obj_get_event_dsc(lv_obj_t * obj, uint32_t index) +bool lv_obj_remove_event(lv_obj_t * obj, uint32_t index) +bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb) +uint32_t lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj, lv_event_cb_t event_cb, void * user_data) +lv_indev_t * lv_event_get_indev(lv_event_t * e) +lv_layer_t * lv_event_get_layer(lv_event_t * e) +const lv_area_t * lv_event_get_old_size(lv_event_t * e) +uint32_t lv_event_get_key(lv_event_t * e) +lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e) +void lv_event_set_ext_draw_size(lv_event_t * e, int32_t size) +lv_point_t * lv_event_get_self_size_info(lv_event_t * e) +lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e) +const lv_area_t * lv_event_get_cover_area(lv_event_t * e) +void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res) +lv_draw_task_t * lv_event_get_draw_task(lv_event_t * e) + +// ../../lvgl/src/core/lv_obj_pos.h +void lv_obj_set_pos(lv_obj_t * obj, int32_t x, int32_t y) +void lv_obj_set_x(lv_obj_t * obj, int32_t x) +void lv_obj_set_y(lv_obj_t * obj, int32_t y) +void lv_obj_set_size(lv_obj_t * obj, int32_t w, int32_t h) +bool lv_obj_refr_size(lv_obj_t * obj) +void lv_obj_set_width(lv_obj_t * obj, int32_t w) +void lv_obj_set_height(lv_obj_t * obj, int32_t h) +void lv_obj_set_content_width(lv_obj_t * obj, int32_t w) +void lv_obj_set_content_height(lv_obj_t * obj, int32_t h) +void lv_obj_set_layout(lv_obj_t * obj, uint32_t layout) +bool lv_obj_is_layout_positioned(const lv_obj_t * obj) +void lv_obj_mark_layout_as_dirty(lv_obj_t * obj) +void lv_obj_update_layout(const lv_obj_t * obj) +void lv_obj_set_align(lv_obj_t * obj, lv_align_t align) +void lv_obj_align(lv_obj_t * obj, lv_align_t align, int32_t x_ofs, int32_t y_ofs) +void lv_obj_align_to(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, int32_t x_ofs, int32_t y_ofs) +static inline void lv_obj_center(lv_obj_t * obj) +void lv_obj_get_coords(const lv_obj_t * obj, lv_area_t * coords) +int32_t lv_obj_get_x(const lv_obj_t * obj) +int32_t lv_obj_get_x2(const lv_obj_t * obj) +int32_t lv_obj_get_y(const lv_obj_t * obj) +int32_t lv_obj_get_y2(const lv_obj_t * obj) +int32_t lv_obj_get_x_aligned(const lv_obj_t * obj) +int32_t lv_obj_get_y_aligned(const lv_obj_t * obj) +int32_t lv_obj_get_width(const lv_obj_t * obj) +int32_t lv_obj_get_height(const lv_obj_t * obj) +int32_t lv_obj_get_content_width(const lv_obj_t * obj) +int32_t lv_obj_get_content_height(const lv_obj_t * obj) +void lv_obj_get_content_coords(const lv_obj_t * obj, lv_area_t * area) +int32_t lv_obj_get_self_width(const lv_obj_t * obj) +int32_t lv_obj_get_self_height(const lv_obj_t * obj) +bool lv_obj_refresh_self_size(lv_obj_t * obj) +void lv_obj_refr_pos(lv_obj_t * obj) +void lv_obj_move_to(lv_obj_t * obj, int32_t x, int32_t y) +void lv_obj_move_children_by(lv_obj_t * obj, int32_t x_diff, int32_t y_diff, bool ignore_floating) +void lv_obj_transform_point(const lv_obj_t * obj, lv_point_t * p, bool recursive, bool inv) +void lv_obj_get_transformed_area(const lv_obj_t * obj, lv_area_t * area, bool recursive, bool inv) +void lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area) +void lv_obj_invalidate(const lv_obj_t * obj) +bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area) +bool lv_obj_is_visible(const lv_obj_t * obj) +void lv_obj_set_ext_click_area(lv_obj_t * obj, int32_t size) +void lv_obj_get_click_area(const lv_obj_t * obj, lv_area_t * area) +bool lv_obj_hit_test(lv_obj_t * obj, const lv_point_t * point) +int32_t lv_clamp_width(int32_t width, int32_t min_width, int32_t max_width, int32_t ref_width) +int32_t lv_clamp_height(int32_t height, int32_t min_height, int32_t max_height, int32_t ref_height) + +// ../../lvgl/src/core/lv_obj_property.h + +// ../../lvgl/src/core/lv_obj_scroll.h +void lv_obj_set_scrollbar_mode(lv_obj_t * obj, lv_scrollbar_mode_t mode) +void lv_obj_set_scroll_dir(lv_obj_t * obj, lv_dir_t dir) +void lv_obj_set_scroll_snap_x(lv_obj_t * obj, lv_scroll_snap_t align) +void lv_obj_set_scroll_snap_y(lv_obj_t * obj, lv_scroll_snap_t align) +lv_scrollbar_mode_t lv_obj_get_scrollbar_mode(const lv_obj_t * obj) +lv_dir_t lv_obj_get_scroll_dir(const lv_obj_t * obj) +lv_scroll_snap_t lv_obj_get_scroll_snap_x(const lv_obj_t * obj) +lv_scroll_snap_t lv_obj_get_scroll_snap_y(const lv_obj_t * obj) +int32_t lv_obj_get_scroll_x(const lv_obj_t * obj) +int32_t lv_obj_get_scroll_y(const lv_obj_t * obj) +int32_t lv_obj_get_scroll_top(lv_obj_t * obj) +int32_t lv_obj_get_scroll_bottom(lv_obj_t * obj) +int32_t lv_obj_get_scroll_left(lv_obj_t * obj) +int32_t lv_obj_get_scroll_right(lv_obj_t * obj) +void lv_obj_get_scroll_end(lv_obj_t * obj, lv_point_t * end) +void lv_obj_scroll_by(lv_obj_t * obj, int32_t x, int32_t y, lv_anim_enable_t anim_en) +void lv_obj_scroll_by_bounded(lv_obj_t * obj, int32_t dx, int32_t dy, lv_anim_enable_t anim_en) +void lv_obj_scroll_to(lv_obj_t * obj, int32_t x, int32_t y, lv_anim_enable_t anim_en) +void lv_obj_scroll_to_x(lv_obj_t * obj, int32_t x, lv_anim_enable_t anim_en) +void lv_obj_scroll_to_y(lv_obj_t * obj, int32_t y, lv_anim_enable_t anim_en) +void lv_obj_scroll_to_view(lv_obj_t * obj, lv_anim_enable_t anim_en) +void lv_obj_scroll_to_view_recursive(lv_obj_t * obj, lv_anim_enable_t anim_en) +bool lv_obj_is_scrolling(const lv_obj_t * obj) +void lv_obj_update_snap(lv_obj_t * obj, lv_anim_enable_t anim_en) +void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor, lv_area_t * ver) +void lv_obj_scrollbar_invalidate(lv_obj_t * obj) +void lv_obj_readjust_scroll(lv_obj_t * obj, lv_anim_enable_t anim_en) + +// ../../lvgl/src/core/lv_obj_style.h +void lv_obj_add_style(lv_obj_t * obj, const lv_style_t * style, lv_style_selector_t selector) +bool lv_obj_replace_style(lv_obj_t * obj, const lv_style_t * old_style, const lv_style_t * new_style, lv_style_selector_t selector) +void lv_obj_remove_style(lv_obj_t * obj, const lv_style_t * style, lv_style_selector_t selector) +void lv_obj_remove_style_all(lv_obj_t * obj) +void lv_obj_report_style_change(lv_style_t * style) +void lv_obj_refresh_style(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop) +void lv_obj_enable_style_refresh(bool en) +lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop) +bool lv_obj_has_style_prop(const lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop) +void lv_obj_set_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value, lv_style_selector_t selector) +lv_style_res_t lv_obj_get_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, lv_style_selector_t selector) +bool lv_obj_remove_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector) +void lv_obj_fade_in(lv_obj_t * obj, uint32_t time, uint32_t delay) +void lv_obj_fade_out(lv_obj_t * obj, uint32_t time, uint32_t delay) +static inline lv_state_t lv_obj_style_get_selector_state(lv_style_selector_t selector) +static inline lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector) +static inline void lv_obj_set_style_pad_all(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +static inline void lv_obj_set_style_pad_hor(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +static inline void lv_obj_set_style_pad_ver(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +static inline void lv_obj_set_style_margin_all(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +static inline void lv_obj_set_style_margin_hor(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +static inline void lv_obj_set_style_margin_ver(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +static inline void lv_obj_set_style_pad_gap(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +static inline void lv_obj_set_style_size(lv_obj_t * obj, int32_t width, int32_t height, lv_style_selector_t selector) +static inline void lv_obj_set_style_transform_scale(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +static inline int32_t lv_obj_get_style_space_left(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_space_right(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_space_top(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_space_bottom(const lv_obj_t * obj, uint32_t part) +lv_text_align_t lv_obj_calculate_style_text_align(const lv_obj_t * obj, lv_part_t part, const char * txt) +static inline int32_t lv_obj_get_style_transform_scale_x_safe(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_scale_y_safe(const lv_obj_t * obj, uint32_t part) +lv_opa_t lv_obj_get_style_opa_recursive(const lv_obj_t * obj, lv_part_t part) + +// ../../lvgl/src/core/lv_obj_style_gen.h +static inline int32_t lv_obj_get_style_width(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_min_width(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_max_width(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_height(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_min_height(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_max_height(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_length(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_x(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_y(const lv_obj_t * obj, uint32_t part) +static inline lv_align_t lv_obj_get_style_align(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_width(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_height(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_translate_x(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_translate_y(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_scale_x(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_scale_y(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_rotation(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_pivot_x(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_pivot_y(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_skew_x(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_skew_y(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_pad_top(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_pad_bottom(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_pad_left(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_pad_right(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_pad_row(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_pad_column(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_margin_top(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_margin_bottom(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_margin_left(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_margin_right(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_bg_color(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_bg_color_filtered(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_bg_opa(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_bg_grad_color(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_bg_grad_color_filtered(const lv_obj_t * obj, uint32_t part) +static inline lv_grad_dir_t lv_obj_get_style_bg_grad_dir(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_bg_main_stop(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_bg_grad_stop(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_bg_main_opa(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_bg_grad_opa(const lv_obj_t * obj, uint32_t part) +static inline const lv_grad_dsc_t * lv_obj_get_style_bg_grad(const lv_obj_t * obj, uint32_t part) +static inline const void * lv_obj_get_style_bg_image_src(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_bg_image_opa(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_bg_image_recolor(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_bg_image_recolor_filtered(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_bg_image_recolor_opa(const lv_obj_t * obj, uint32_t part) +static inline bool lv_obj_get_style_bg_image_tiled(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_border_color(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_border_color_filtered(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_border_opa(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_border_width(const lv_obj_t * obj, uint32_t part) +static inline lv_border_side_t lv_obj_get_style_border_side(const lv_obj_t * obj, uint32_t part) +static inline bool lv_obj_get_style_border_post(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_outline_width(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_outline_color(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_outline_color_filtered(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_outline_opa(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_outline_pad(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_shadow_width(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_shadow_offset_x(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_shadow_offset_y(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_shadow_spread(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_shadow_color(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_shadow_color_filtered(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_shadow_opa(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_image_opa(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_image_recolor(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_image_recolor_filtered(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_image_recolor_opa(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_line_width(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_line_dash_width(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_line_dash_gap(const lv_obj_t * obj, uint32_t part) +static inline bool lv_obj_get_style_line_rounded(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_line_color(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_line_color_filtered(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_line_opa(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_arc_width(const lv_obj_t * obj, uint32_t part) +static inline bool lv_obj_get_style_arc_rounded(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_arc_color(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_arc_color_filtered(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_arc_opa(const lv_obj_t * obj, uint32_t part) +static inline const void * lv_obj_get_style_arc_image_src(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_text_color(const lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_text_color_filtered(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_text_opa(const lv_obj_t * obj, uint32_t part) +static inline const lv_font_t * lv_obj_get_style_text_font(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_text_letter_space(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_text_line_space(const lv_obj_t * obj, uint32_t part) +static inline lv_text_decor_t lv_obj_get_style_text_decor(const lv_obj_t * obj, uint32_t part) +static inline lv_text_align_t lv_obj_get_style_text_align(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_radius(const lv_obj_t * obj, uint32_t part) +static inline bool lv_obj_get_style_clip_corner(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_opa(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_opa_layered(const lv_obj_t * obj, uint32_t part) +static inline const lv_color_filter_dsc_t * lv_obj_get_style_color_filter_dsc(const lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_color_filter_opa(const lv_obj_t * obj, uint32_t part) +static inline const lv_anim_t * lv_obj_get_style_anim(const lv_obj_t * obj, uint32_t part) +static inline uint32_t lv_obj_get_style_anim_duration(const lv_obj_t * obj, uint32_t part) +static inline const lv_style_transition_dsc_t * lv_obj_get_style_transition(const lv_obj_t * obj, uint32_t part) +static inline lv_blend_mode_t lv_obj_get_style_blend_mode(const lv_obj_t * obj, uint32_t part) +static inline uint16_t lv_obj_get_style_layout(const lv_obj_t * obj, uint32_t part) +static inline lv_base_dir_t lv_obj_get_style_base_dir(const lv_obj_t * obj, uint32_t part) +static inline lv_flex_flow_t lv_obj_get_style_flex_flow(const lv_obj_t * obj, uint32_t part) +static inline lv_flex_align_t lv_obj_get_style_flex_main_place(const lv_obj_t * obj, uint32_t part) +static inline lv_flex_align_t lv_obj_get_style_flex_cross_place(const lv_obj_t * obj, uint32_t part) +static inline lv_flex_align_t lv_obj_get_style_flex_track_place(const lv_obj_t * obj, uint32_t part) +static inline uint8_t lv_obj_get_style_flex_grow(const lv_obj_t * obj, uint32_t part) +static inline const int32_t * lv_obj_get_style_grid_column_dsc_array(const lv_obj_t * obj, uint32_t part) +static inline lv_grid_align_t lv_obj_get_style_grid_column_align(const lv_obj_t * obj, uint32_t part) +static inline const int32_t * lv_obj_get_style_grid_row_dsc_array(const lv_obj_t * obj, uint32_t part) +static inline lv_grid_align_t lv_obj_get_style_grid_row_align(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_grid_cell_column_pos(const lv_obj_t * obj, uint32_t part) +static inline lv_grid_align_t lv_obj_get_style_grid_cell_x_align(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_grid_cell_column_span(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_grid_cell_row_pos(const lv_obj_t * obj, uint32_t part) +static inline lv_grid_align_t lv_obj_get_style_grid_cell_y_align(const lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_grid_cell_row_span(const lv_obj_t * obj, uint32_t part) +void lv_obj_set_style_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_min_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_max_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_min_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_max_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_length(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_align(lv_obj_t * obj, lv_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_translate_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_translate_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_scale_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_scale_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_rotation(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_pivot_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_pivot_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_skew_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_skew_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_pad_top(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_pad_bottom(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_pad_left(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_pad_right(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_pad_row(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_pad_column(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_margin_top(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_margin_bottom(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_margin_left(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_margin_right(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_grad_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_grad_dir(lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_main_stop(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_grad_stop(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_main_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_grad_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_grad(lv_obj_t * obj, const lv_grad_dsc_t * value, lv_style_selector_t selector) +void lv_obj_set_style_bg_image_src(lv_obj_t * obj, const void * value, lv_style_selector_t selector) +void lv_obj_set_style_bg_image_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_image_recolor(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_image_recolor_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_image_tiled(lv_obj_t * obj, bool value, lv_style_selector_t selector) +void lv_obj_set_style_border_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_border_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_border_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_border_side(lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector) +void lv_obj_set_style_border_post(lv_obj_t * obj, bool value, lv_style_selector_t selector) +void lv_obj_set_style_outline_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_outline_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_outline_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_outline_pad(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_shadow_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_shadow_offset_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_shadow_offset_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_shadow_spread(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_shadow_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_shadow_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_image_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_image_recolor(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_image_recolor_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_line_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_line_dash_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_line_dash_gap(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_line_rounded(lv_obj_t * obj, bool value, lv_style_selector_t selector) +void lv_obj_set_style_line_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_line_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_arc_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_arc_rounded(lv_obj_t * obj, bool value, lv_style_selector_t selector) +void lv_obj_set_style_arc_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_arc_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_arc_image_src(lv_obj_t * obj, const void * value, lv_style_selector_t selector) +void lv_obj_set_style_text_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_text_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_text_font(lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector) +void lv_obj_set_style_text_letter_space(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_text_line_space(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_text_decor(lv_obj_t * obj, lv_text_decor_t value, lv_style_selector_t selector) +void lv_obj_set_style_text_align(lv_obj_t * obj, lv_text_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_radius(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_clip_corner(lv_obj_t * obj, bool value, lv_style_selector_t selector) +void lv_obj_set_style_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_opa_layered(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_color_filter_dsc(lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector) +void lv_obj_set_style_color_filter_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_anim(lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector) +void lv_obj_set_style_anim_duration(lv_obj_t * obj, uint32_t value, lv_style_selector_t selector) +void lv_obj_set_style_transition(lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector) +void lv_obj_set_style_blend_mode(lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector) +void lv_obj_set_style_layout(lv_obj_t * obj, uint16_t value, lv_style_selector_t selector) +void lv_obj_set_style_base_dir(lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector) +void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector) +void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector) +void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const int32_t * value, lv_style_selector_t selector) +void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const int32_t * value, lv_style_selector_t selector) +void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) + +// ../../lvgl/src/core/lv_obj_tree.h +void lv_obj_delete(lv_obj_t * obj) +void lv_obj_clean(lv_obj_t * obj) +void lv_obj_delete_delayed(lv_obj_t * obj, uint32_t delay_ms) +void lv_obj_delete_anim_completed_cb(lv_anim_t * a) +void lv_obj_delete_async(lv_obj_t * obj) +void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent) +void lv_obj_swap(lv_obj_t * obj1, lv_obj_t * obj2) +void lv_obj_move_to_index(lv_obj_t * obj, int32_t index) +lv_obj_t * lv_obj_get_screen(const lv_obj_t * obj) +lv_display_t * lv_obj_get_display(const lv_obj_t * obj) +lv_obj_t * lv_obj_get_parent(const lv_obj_t * obj) +lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, int32_t idx) +lv_obj_t * lv_obj_get_child_by_type(const lv_obj_t * obj, int32_t idx, const lv_obj_class_t * class_p) +lv_obj_t * lv_obj_get_sibling(const lv_obj_t * obj, int32_t idx) +lv_obj_t * lv_obj_get_sibling_by_type(const lv_obj_t * obj, int32_t idx, const lv_obj_class_t * class_p) +uint32_t lv_obj_get_child_count(const lv_obj_t * obj) +uint32_t lv_obj_get_child_count_by_type(const lv_obj_t * obj, const lv_obj_class_t * class_p) +int32_t lv_obj_get_index(const lv_obj_t * obj) +int32_t lv_obj_get_index_by_type(const lv_obj_t * obj, const lv_obj_class_t * class_p) +void lv_obj_tree_walk(lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data) +void lv_obj_dump_tree(lv_obj_t * start_ob) + +// ../../lvgl/src/core/lv_refr.h +void lv_refr_now(lv_display_t * disp) +void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj) + +// ../../lvgl/src/display/lv_display.h +lv_display_t * lv_display_create(int32_t hor_res, int32_t ver_res) +void lv_display_delete(lv_display_t * disp) +void lv_display_set_default(lv_display_t * disp) +lv_display_t * lv_display_get_default(void) +lv_display_t * lv_display_get_next(lv_display_t * disp) +void lv_display_set_resolution(lv_display_t * disp, int32_t hor_res, int32_t ver_res) +void lv_display_set_physical_resolution(lv_display_t * disp, int32_t hor_res, int32_t ver_res) +void lv_display_set_offset(lv_display_t * disp, int32_t x, int32_t y) +void lv_display_set_rotation(lv_display_t * disp, lv_display_rotation_t rotation) +void lv_display_set_dpi(lv_display_t * disp, int32_t dpi) +int32_t lv_display_get_horizontal_resolution(const lv_display_t * disp) +int32_t lv_display_get_vertical_resolution(const lv_display_t * disp) +int32_t lv_display_get_physical_horizontal_resolution(const lv_display_t * disp) +int32_t lv_display_get_physical_vertical_resolution(const lv_display_t * disp) +int32_t lv_display_get_offset_x(const lv_display_t * disp) +int32_t lv_display_get_offset_y(const lv_display_t * disp) +lv_display_rotation_t lv_display_get_rotation(lv_display_t * disp) +int32_t lv_display_get_dpi(const lv_display_t * disp) +void lv_display_set_buffers(lv_display_t * disp, void * buf1, void * buf2, uint32_t buf_size, lv_display_render_mode_t render_mode) +void lv_display_set_draw_buffers(lv_display_t * disp, lv_draw_buf_t * buf1, lv_draw_buf_t * buf2) +void lv_display_set_render_mode(lv_display_t * disp, lv_display_render_mode_t render_mode) +void lv_display_set_flush_cb(lv_display_t * disp, lv_display_flush_cb_t flush_cb) +void lv_display_set_flush_wait_cb(lv_display_t * disp, lv_display_flush_wait_cb_t wait_cb) +void lv_display_set_color_format(lv_display_t * disp, lv_color_format_t color_format) +lv_color_format_t lv_display_get_color_format(lv_display_t * disp) +void lv_display_set_antialiasing(lv_display_t * disp, bool en) +bool lv_display_get_antialiasing(lv_display_t * disp) +bool lv_display_is_double_buffered(lv_display_t * disp) +lv_obj_t * lv_display_get_screen_active(lv_display_t * disp) +lv_obj_t * lv_display_get_screen_prev(lv_display_t * disp) +lv_obj_t * lv_display_get_layer_top(lv_display_t * disp) +lv_obj_t * lv_display_get_layer_sys(lv_display_t * disp) +lv_obj_t * lv_display_get_layer_bottom(lv_display_t * disp) +void lv_screen_load(struct _lv_obj_t * scr) +void lv_screen_load_anim(lv_obj_t * scr, lv_screen_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del) +static inline lv_obj_t * lv_screen_active(void) +static inline lv_obj_t * lv_layer_top(void) +static inline lv_obj_t * lv_layer_sys(void) +static inline lv_obj_t * lv_layer_bottom(void) +void lv_display_add_event_cb(lv_display_t * disp, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data) +uint32_t lv_display_get_event_count(lv_display_t * disp) +lv_event_dsc_t * lv_display_get_event_dsc(lv_display_t * disp, uint32_t index) +bool lv_display_delete_event(lv_display_t * disp, uint32_t index) +uint32_t lv_display_remove_event_cb_with_user_data(lv_display_t * disp, lv_event_cb_t event_cb, void * user_data) +lv_result_t lv_display_send_event(lv_display_t * disp, lv_event_code_t code, void * param) +void lv_display_set_theme(lv_display_t * disp, lv_theme_t * th) +lv_theme_t * lv_display_get_theme(lv_display_t * disp) +uint32_t lv_display_get_inactive_time(const lv_display_t * disp) +void lv_display_trigger_activity(lv_display_t * disp) +void lv_display_enable_invalidation(lv_display_t * disp, bool en) +bool lv_display_is_invalidation_enabled(lv_display_t * disp) +lv_timer_t * lv_display_get_refr_timer(lv_display_t * disp) +void lv_display_delete_refr_timer(lv_display_t * disp) +void lv_display_set_user_data(lv_display_t * disp, void * user_data) +void lv_display_set_driver_data(lv_display_t * disp, void * driver_data) +void * lv_display_get_user_data(lv_display_t * disp) +void * lv_display_get_driver_data(lv_display_t * disp) +static inline int32_t lv_dpx(int32_t n) +static inline int32_t lv_display_dpx(const lv_display_t * disp, int32_t n) + +// ../../lvgl/src/display/lv_display_private.h + +// ../../lvgl/src/draw/lv_draw.h +void lv_draw_init(void) +void lv_draw_deinit(void) +void * lv_draw_create_unit(size_t size) +lv_draw_task_t * lv_draw_add_task(lv_layer_t * layer, const lv_area_t * coords) +void lv_draw_finalize_task_creation(lv_layer_t * layer, lv_draw_task_t * t) +void lv_draw_dispatch(void) +bool lv_draw_dispatch_layer(lv_display_t * disp, lv_layer_t * layer) +void lv_draw_dispatch_wait_for_request(void) +void lv_draw_dispatch_request(void) +lv_draw_task_t * lv_draw_get_next_available_task(lv_layer_t * layer, lv_draw_task_t * t_prev, uint8_t draw_unit_id) +uint32_t lv_draw_get_dependent_count(lv_draw_task_t * t_check) +lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t color_format, const lv_area_t * area) +void * lv_draw_layer_alloc_buf(lv_layer_t * layer) +void * lv_draw_layer_go_to_xy(lv_layer_t * layer, int32_t x, int32_t y) + +// ../../lvgl/src/draw/lv_draw_arc.h +void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc) +void lv_draw_arc(lv_layer_t * layer, const lv_draw_arc_dsc_t * dsc) +void lv_draw_arc_get_area(int32_t x, int32_t y, uint16_t radius, lv_value_precise_t start_angle, lv_value_precise_t end_angle, int32_t w, bool rounded, lv_area_t * area) + +// ../../lvgl/src/draw/lv_draw_label.h +void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc) +void lv_draw_glyph_dsc_init(lv_draw_glyph_dsc_t * dsc) +void lv_draw_label(lv_layer_t * layer, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords) +void lv_draw_character(lv_layer_t * layer, lv_draw_label_dsc_t * dsc, const lv_point_t * point, uint32_t unicode_letter) +void lv_draw_label_iterate_characters(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords, lv_draw_glyph_cb_t cb) + +// ../../lvgl/src/draw/lv_draw_line.h +void lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc) +void lv_draw_line(lv_layer_t * layer, const lv_draw_line_dsc_t * dsc) + +// ../../lvgl/src/draw/lv_draw_mask.h +void lv_draw_mask_rect_dsc_init(lv_draw_mask_rect_dsc_t * dsc) +void lv_draw_mask_rect(lv_layer_t * layer, const lv_draw_mask_rect_dsc_t * dsc) + +// ../../lvgl/src/draw/lv_draw_rect.h +void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc) +void lv_draw_fill_dsc_init(lv_draw_fill_dsc_t * dsc) +void lv_draw_border_dsc_init(lv_draw_border_dsc_t * dsc) +void lv_draw_box_shadow_dsc_init(lv_draw_box_shadow_dsc_t * dsc) +void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) + +// ../../lvgl/src/draw/lv_draw_triangle.h +void lv_draw_triangle_dsc_init(lv_draw_triangle_dsc_t * draw_dsc) +void lv_draw_triangle(lv_layer_t * layer, const lv_draw_triangle_dsc_t * draw_dsc) + +// ../../lvgl/src/draw/lv_draw_vector.h +void lv_matrix_identity(lv_matrix_t * matrix) +void lv_matrix_translate(lv_matrix_t * matrix, float tx, float ty) +void lv_matrix_scale(lv_matrix_t * matrix, float scale_x, float scale_y) +void lv_matrix_rotate(lv_matrix_t * matrix, float degree) +void lv_matrix_skew(lv_matrix_t * matrix, float skew_x, float skew_y) +void lv_matrix_multiply(lv_matrix_t * matrix, const lv_matrix_t * matrix2) +lv_vector_path_t * lv_vector_path_create(lv_vector_path_quality_t quality) +void lv_vector_path_copy(lv_vector_path_t * target_path, const lv_vector_path_t * path) +void lv_vector_path_clear(lv_vector_path_t * path) +void lv_vector_path_delete(lv_vector_path_t * path) +void lv_vector_path_move_to(lv_vector_path_t * path, const lv_fpoint_t * p) +void lv_vector_path_line_to(lv_vector_path_t * path, const lv_fpoint_t * p) +void lv_vector_path_quad_to(lv_vector_path_t * path, const lv_fpoint_t * p1, const lv_fpoint_t * p2) +void lv_vector_path_cubic_to(lv_vector_path_t * path, const lv_fpoint_t * p1, const lv_fpoint_t * p2, const lv_fpoint_t * p3) +void lv_vector_path_close(lv_vector_path_t * path) +void lv_vector_path_append_rect(lv_vector_path_t * path, const lv_area_t * rect, float rx, float ry) +void lv_vector_path_append_circle(lv_vector_path_t * path, const lv_fpoint_t * c, float rx, float ry) +void lv_vector_path_append_path(lv_vector_path_t * path, const lv_vector_path_t * subpath) +lv_vector_dsc_t * lv_vector_dsc_create(lv_layer_t * layer) +void lv_vector_dsc_delete(lv_vector_dsc_t * dsc) +void lv_vector_dsc_set_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix) +void lv_vector_dsc_set_blend_mode(lv_vector_dsc_t * dsc, lv_vector_blend_t blend) +void lv_vector_dsc_set_fill_color32(lv_vector_dsc_t * dsc, lv_color32_t color) +void lv_vector_dsc_set_fill_color(lv_vector_dsc_t * dsc, lv_color_t color) +void lv_vector_dsc_set_fill_opa(lv_vector_dsc_t * dsc, lv_opa_t opa) +void lv_vector_dsc_set_fill_rule(lv_vector_dsc_t * dsc, lv_vector_fill_t rule) +void lv_vector_dsc_set_fill_image(lv_vector_dsc_t * dsc, const lv_draw_image_dsc_t * img_dsc) +void lv_vector_dsc_set_fill_linear_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, lv_vector_gradient_spread_t spread) +void lv_vector_dsc_set_fill_radial_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, float cx, float cy, float radius, lv_vector_gradient_spread_t spread) +void lv_vector_dsc_set_fill_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix) +void lv_vector_dsc_set_stroke_color32(lv_vector_dsc_t * dsc, lv_color32_t color) +void lv_vector_dsc_set_stroke_color(lv_vector_dsc_t * dsc, lv_color_t color) +void lv_vector_dsc_set_stroke_opa(lv_vector_dsc_t * dsc, lv_opa_t opa) +void lv_vector_dsc_set_stroke_width(lv_vector_dsc_t * dsc, float width) +void lv_vector_dsc_set_stroke_dash(lv_vector_dsc_t * dsc, float * dash_pattern, uint16_t dash_count) +void lv_vector_dsc_set_stroke_cap(lv_vector_dsc_t * dsc, lv_vector_stroke_cap_t cap) +void lv_vector_dsc_set_stroke_join(lv_vector_dsc_t * dsc, lv_vector_stroke_join_t join) +void lv_vector_dsc_set_stroke_miter_limit(lv_vector_dsc_t * dsc, uint16_t miter_limit) +void lv_vector_dsc_set_stroke_linear_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, lv_vector_gradient_spread_t spread) +void lv_vector_dsc_set_stroke_radial_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, float cx, float cy, float radius, lv_vector_gradient_spread_t spread) +void lv_vector_dsc_set_stroke_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix) +void lv_vector_dsc_identity(lv_vector_dsc_t * dsc) +void lv_vector_dsc_scale(lv_vector_dsc_t * dsc, float scale_x, float scale_y) +void lv_vector_dsc_rotate(lv_vector_dsc_t * dsc, float degree) +void lv_vector_dsc_translate(lv_vector_dsc_t * dsc, float tx, float ty) +void lv_vector_dsc_skew(lv_vector_dsc_t * dsc, float skew_x, float skew_y) +void lv_vector_dsc_add_path(lv_vector_dsc_t * dsc, const lv_vector_path_t * path) +void lv_vector_clear_area(lv_vector_dsc_t * dsc, const lv_area_t * rect) +void lv_draw_vector(lv_vector_dsc_t * dsc) + +// ../../lvgl/src/font/lv_font.h +const void * lv_font_get_glyph_bitmap(lv_font_glyph_dsc_t * g_dsc, uint32_t letter, lv_draw_buf_t * draw_buf) +bool lv_font_get_glyph_dsc(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t letter, uint32_t letter_next) +uint16_t lv_font_get_glyph_width(const lv_font_t * font, uint32_t letter, uint32_t letter_next) +static inline int32_t lv_font_get_line_height(const lv_font_t * font) +void lv_font_set_kerning(lv_font_t * font, lv_font_kerning_t kerning) + +// ../../lvgl/src/indev/lv_indev.h +lv_indev_t * lv_indev_create(void) +void lv_indev_delete(lv_indev_t * indev) +lv_indev_t * lv_indev_get_next(lv_indev_t * indev) +void lv_indev_read(lv_indev_t * indev) void lv_indev_read_timer_cb(lv_timer_t * timer) void lv_indev_enable(lv_indev_t * indev, bool en) -lv_indev_t * lv_indev_get_act(void) +lv_indev_t * lv_indev_active(void) +void lv_indev_set_type(lv_indev_t * indev, lv_indev_type_t indev_type) +void lv_indev_set_read_cb(lv_indev_t * indev, lv_indev_read_cb_t read_cb) +void lv_indev_set_user_data(lv_indev_t * indev, void * user_data) +void lv_indev_set_driver_data(lv_indev_t * indev, void * driver_data) lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev) +lv_indev_read_cb_t lv_indev_get_read_cb(lv_indev_t * indev) +lv_indev_state_t lv_indev_get_state(const lv_indev_t * indev) +lv_group_t * lv_indev_get_group(const lv_indev_t * indev) +void lv_indev_set_display(lv_indev_t * indev, struct _lv_display_t * disp) +lv_display_t * lv_indev_get_display(const lv_indev_t * indev) +void * lv_indev_get_user_data(const lv_indev_t * indev) +void * lv_indev_get_driver_data(const lv_indev_t * indev) void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj) void lv_indev_reset_long_press(lv_indev_t * indev) void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj) @@ -110,357 +688,295 @@ lv_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev) lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev) void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point) void lv_indev_wait_release(lv_indev_t * indev) -lv_obj_t * lv_indev_get_obj_act(void) -lv_timer_t * lv_indev_get_read_timer(lv_disp_t * indev) +lv_obj_t * lv_indev_get_active_obj(void) +lv_timer_t * lv_indev_get_read_timer(lv_indev_t * indev) +void lv_indev_set_mode(lv_indev_t * indev, lv_indev_mode_t mode) +lv_indev_mode_t lv_indev_get_mode(lv_indev_t * indev) lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point) +void lv_indev_add_event_cb(lv_indev_t * indev, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data) +uint32_t lv_indev_get_event_count(lv_indev_t * indev) +lv_event_dsc_t * lv_indev_get_event_dsc(lv_indev_t * indev, uint32_t index) +bool lv_indev_remove_event(lv_indev_t * indev, uint32_t index) +uint32_t lv_indev_remove_event_cb_with_user_data(lv_indev_t * indev, lv_event_cb_t event_cb, void * user_data) +lv_result_t lv_indev_send_event(lv_indev_t * indev, lv_event_code_t code, void * param) -// ../../lvgl/src/core/lv_indev_scroll.h +// ../../lvgl/src/libs/qrcode/lv_qrcode.h +lv_obj_t * lv_qrcode_create(lv_obj_t * parent) +void lv_qrcode_set_size(lv_obj_t * obj, int32_t size) +void lv_qrcode_set_dark_color(lv_obj_t * obj, lv_color_t color) +void lv_qrcode_set_light_color(lv_obj_t * obj, lv_color_t color) +lv_result_t lv_qrcode_update(lv_obj_t * obj, const void * data, uint32_t data_len) -// ../../lvgl/src/core/lv_obj.h -bool lv_is_initialized(void) -lv_obj_t * lv_obj_create(lv_obj_t * parent) -void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f) -void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f) -void lv_obj_add_state(lv_obj_t * obj, lv_state_t state) -void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state) -static inline void lv_obj_set_user_data(lv_obj_t * obj, void * user_data) -bool lv_obj_has_flag(const lv_obj_t * obj, lv_obj_flag_t f) -bool lv_obj_has_flag_any(const lv_obj_t * obj, lv_obj_flag_t f) -lv_state_t lv_obj_get_state(const lv_obj_t * obj) -bool lv_obj_has_state(const lv_obj_t * obj, lv_state_t state) -void * lv_obj_get_group(const lv_obj_t * obj) -static inline void * lv_obj_get_user_data(lv_obj_t * obj) -void lv_obj_allocate_spec_attr(lv_obj_t * obj) -bool lv_obj_check_type(const lv_obj_t * obj, const lv_obj_class_t * class_p) -bool lv_obj_has_class(const lv_obj_t * obj, const lv_obj_class_t * class_p) -const lv_obj_class_t * lv_obj_get_class(const lv_obj_t * obj) -bool lv_obj_is_valid(const lv_obj_t * obj) -static inline lv_coord_t lv_obj_dpx(const lv_obj_t * obj, lv_coord_t n) +// ../../lvgl/src/lv_api_map.h +static inline uint32_t lv_task_handler(void) +static inline void lv_obj_move_foreground(lv_obj_t * obj) +static inline void lv_obj_move_background(lv_obj_t * obj) -// ../../lvgl/src/core/lv_obj_class.h -struct _lv_obj_t * lv_obj_class_create_obj(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * parent) -void lv_obj_class_init_obj(struct _lv_obj_t * obj) -bool lv_obj_is_editable(struct _lv_obj_t * obj) -bool lv_obj_is_group_def(struct _lv_obj_t * obj) +// ../../lvgl/src/misc/lv_anim.h +void lv_anim_init(lv_anim_t * a) +static inline void lv_anim_set_var(lv_anim_t * a, void * var) +static inline void lv_anim_set_exec_cb(lv_anim_t * a, lv_anim_exec_xcb_t exec_cb) +static inline void lv_anim_set_duration(lv_anim_t * a, uint32_t duration) +static inline void lv_anim_set_time(lv_anim_t * a, uint32_t duration) +static inline void lv_anim_set_delay(lv_anim_t * a, uint32_t delay) +static inline void lv_anim_set_values(lv_anim_t * a, int32_t start, int32_t end) +static inline void lv_anim_set_custom_exec_cb(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) +static inline void lv_anim_set_path_cb(lv_anim_t * a, lv_anim_path_cb_t path_cb) +static inline void lv_anim_set_start_cb(lv_anim_t * a, lv_anim_start_cb_t start_cb) +static inline void lv_anim_set_get_value_cb(lv_anim_t * a, lv_anim_get_value_cb_t get_value_cb) +static inline void lv_anim_set_completed_cb(lv_anim_t * a, lv_anim_completed_cb_t completed_cb) +static inline void lv_anim_set_deleted_cb(lv_anim_t * a, lv_anim_deleted_cb_t deleted_cb) +static inline void lv_anim_set_playback_duration(lv_anim_t * a, uint32_t duration) +static inline void lv_anim_set_playback_time(lv_anim_t * a, uint32_t duration) +static inline void lv_anim_set_playback_delay(lv_anim_t * a, uint32_t delay) +static inline void lv_anim_set_repeat_count(lv_anim_t * a, uint16_t cnt) +static inline void lv_anim_set_repeat_delay(lv_anim_t * a, uint32_t delay) +static inline void lv_anim_set_early_apply(lv_anim_t * a, bool en) +static inline void lv_anim_set_user_data(lv_anim_t * a, void * user_data) +static inline void lv_anim_set_bezier3_param(lv_anim_t * a, int16_t x1, int16_t y1, int16_t x2, int16_t y2) +lv_anim_t * lv_anim_start(const lv_anim_t * a) +static inline uint32_t lv_anim_get_delay(const lv_anim_t * a) +uint32_t lv_anim_get_playtime(const lv_anim_t * a) +static inline uint32_t lv_anim_get_time(const lv_anim_t * a) +static inline uint16_t lv_anim_get_repeat_count(const lv_anim_t * a) +static inline void * lv_anim_get_user_data(const lv_anim_t * a) +bool lv_anim_delete(void * var, lv_anim_exec_xcb_t exec_cb) +void lv_anim_delete_all(void) +lv_anim_t * lv_anim_get(void * var, lv_anim_exec_xcb_t exec_cb) +lv_timer_t * lv_anim_get_timer(void) +static inline bool lv_anim_custom_delete(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) +static inline lv_anim_t * lv_anim_custom_get(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) +uint16_t lv_anim_count_running(void) +uint32_t lv_anim_speed(uint32_t speed) +uint32_t lv_anim_speed_clamped(uint32_t speed, uint32_t min_time, uint32_t max_time) +void lv_anim_refr_now(void) -// ../../lvgl/src/core/lv_obj_draw.h -void lv_obj_init_draw_rect_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t * draw_dsc) -void lv_obj_init_draw_label_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc) -void lv_obj_init_draw_img_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc) -void lv_obj_init_draw_line_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc) -void lv_obj_init_draw_arc_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc) -lv_coord_t lv_obj_calculate_ext_draw_size(struct _lv_obj_t * obj, uint32_t part) -void lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc, lv_draw_ctx_t * draw_ctx) -bool lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc, const struct _lv_obj_class_t * class_p, uint32_t type) -void lv_obj_refresh_ext_draw_size(struct _lv_obj_t * obj) +// ../../lvgl/src/misc/lv_area.h +void lv_area_set(lv_area_t * area_p, int32_t x1, int32_t y1, int32_t x2, int32_t y2) +inline static void lv_area_copy(lv_area_t * dest, const lv_area_t * src) +static inline int32_t lv_area_get_width(const lv_area_t * area_p) +static inline int32_t lv_area_get_height(const lv_area_t * area_p) +void lv_area_set_width(lv_area_t * area_p, int32_t w) +void lv_area_set_height(lv_area_t * area_p, int32_t h) +uint32_t lv_area_get_size(const lv_area_t * area_p) +void lv_area_increase(lv_area_t * area, int32_t w_extra, int32_t h_extra) +void lv_area_move(lv_area_t * area, int32_t x_ofs, int32_t y_ofs) +void lv_area_align(const lv_area_t * base, lv_area_t * to_align, lv_align_t align, int32_t ofs_x, int32_t ofs_y) +void lv_point_transform(lv_point_t * p, int32_t angle, int32_t scale_x, int32_t scale_y, const lv_point_t * pivot, bool zoom_first) +static inline lv_point_t lv_point_from_precise(const lv_point_precise_t * p) +static inline lv_point_precise_t lv_point_to_precise(const lv_point_t * p) +static inline void lv_point_set(lv_point_t * p, int32_t x, int32_t y) +static inline void lv_point_precise_set(lv_point_precise_t * p, lv_value_precise_t x, lv_value_precise_t y) +static inline void lv_point_swap(lv_point_t * p1, lv_point_t * p2) +static inline void lv_point_precise_swap(lv_point_precise_t * p1, lv_point_precise_t * p2) +static inline int32_t lv_pct(int32_t x) +static inline int32_t lv_pct_to_px(int32_t v, int32_t base) -// ../../lvgl/src/core/lv_obj_pos.h -void lv_obj_set_pos(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y) -void lv_obj_set_x(struct _lv_obj_t * obj, lv_coord_t x) -void lv_obj_set_y(struct _lv_obj_t * obj, lv_coord_t y) -void lv_obj_set_size(struct _lv_obj_t * obj, lv_coord_t w, lv_coord_t h) -bool lv_obj_refr_size(struct _lv_obj_t * obj) -void lv_obj_set_width(struct _lv_obj_t * obj, lv_coord_t w) -void lv_obj_set_height(struct _lv_obj_t * obj, lv_coord_t h) -void lv_obj_set_content_width(struct _lv_obj_t * obj, lv_coord_t w) -void lv_obj_set_content_height(struct _lv_obj_t * obj, lv_coord_t h) -void lv_obj_set_layout(struct _lv_obj_t * obj, uint32_t layout) -bool lv_obj_is_layout_positioned(const struct _lv_obj_t * obj) -void lv_obj_mark_layout_as_dirty(struct _lv_obj_t * obj) -void lv_obj_update_layout(const struct _lv_obj_t * obj) -uint32_t lv_layout_register(lv_layout_update_cb_t cb, void * user_data) -void lv_obj_set_align(struct _lv_obj_t * obj, lv_align_t align) -void lv_obj_align(struct _lv_obj_t * obj, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs) -void lv_obj_align_to(struct _lv_obj_t * obj, const struct _lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs) -static inline void lv_obj_center(struct _lv_obj_t * obj) -void lv_obj_get_coords(const struct _lv_obj_t * obj, lv_area_t * coords) -lv_coord_t lv_obj_get_x(const struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_x2(const struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_y(const struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_y2(const struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_x_aligned(const struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_y_aligned(const struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_width(const struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_height(const struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_content_width(const struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_content_height(const struct _lv_obj_t * obj) -void lv_obj_get_content_coords(const struct _lv_obj_t * obj, lv_area_t * area) -lv_coord_t lv_obj_get_self_width(const struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_self_height(const struct _lv_obj_t * obj) -bool lv_obj_refresh_self_size(struct _lv_obj_t * obj) -void lv_obj_refr_pos(struct _lv_obj_t * obj) -void lv_obj_move_to(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y) -void lv_obj_move_children_by(struct _lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_diff, bool ignore_floating) -void lv_obj_transform_point(const struct _lv_obj_t * obj, lv_point_t * p, bool recursive, bool inv) -void lv_obj_get_transformed_area(const struct _lv_obj_t * obj, lv_area_t * area, bool recursive, bool inv) -void lv_obj_invalidate_area(const struct _lv_obj_t * obj, const lv_area_t * area) -void lv_obj_invalidate(const struct _lv_obj_t * obj) -bool lv_obj_area_is_visible(const struct _lv_obj_t * obj, lv_area_t * area) -bool lv_obj_is_visible(const struct _lv_obj_t * obj) -void lv_obj_set_ext_click_area(struct _lv_obj_t * obj, lv_coord_t size) -void lv_obj_get_click_area(const struct _lv_obj_t * obj, lv_area_t * area) -bool lv_obj_hit_test(struct _lv_obj_t * obj, const lv_point_t * point) -lv_coord_t lv_clamp_width(lv_coord_t width, lv_coord_t min_width, lv_coord_t max_width, lv_coord_t ref_width) -lv_coord_t lv_clamp_height(lv_coord_t height, lv_coord_t min_height, lv_coord_t max_height, lv_coord_t ref_height) +// ../../lvgl/src/misc/lv_color.h +uint8_t lv_color_format_get_bpp(lv_color_format_t cf) +static inline uint8_t lv_color_format_get_size(lv_color_format_t cf) +bool lv_color_format_has_alpha(lv_color_format_t src_cf) +lv_color32_t lv_color_to_32(lv_color_t color, lv_opa_t opa) +static inline uint32_t lv_color_to_int(lv_color_t c) +static inline bool lv_color_eq(lv_color_t c1, lv_color_t c2) +static inline bool lv_color32_eq(lv_color32_t c1, lv_color32_t c2) +static inline lv_color_t lv_color_hex(uint32_t c) +static inline lv_color_t lv_color_make(uint8_t r, uint8_t g, uint8_t b) +static inline lv_color32_t lv_color32_make(uint8_t r, uint8_t g, uint8_t b, uint8_t a) +static inline lv_color_t lv_color_hex3(uint32_t c) +uint16_t lv_color_to_u16(lv_color_t color) +uint32_t lv_color_to_u32(lv_color_t color) +static inline uint16_t lv_color_16_16_mix(uint16_t c1, uint16_t c2, uint8_t mix) +lv_color_t lv_color_lighten(lv_color_t c, lv_opa_t lvl) +lv_color_t lv_color_darken(lv_color_t c, lv_opa_t lvl) +lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v) +lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8) +lv_color_hsv_t lv_color_to_hsv(lv_color_t color) +static inline lv_color_t lv_color_white(void) +static inline lv_color_t lv_color_black(void) +static inline void lv_color_premultiply(lv_color32_t * c) +static inline void lv_color16_premultiply(lv_color16_t * c, lv_opa_t a) -// ../../lvgl/src/core/lv_obj_scroll.h -void lv_obj_set_scrollbar_mode(struct _lv_obj_t * obj, lv_scrollbar_mode_t mode) -void lv_obj_set_scroll_dir(struct _lv_obj_t * obj, lv_dir_t dir) -void lv_obj_set_scroll_snap_x(struct _lv_obj_t * obj, lv_scroll_snap_t align) -void lv_obj_set_scroll_snap_y(struct _lv_obj_t * obj, lv_scroll_snap_t align) -lv_scrollbar_mode_t lv_obj_get_scrollbar_mode(const struct _lv_obj_t * obj) -lv_dir_t lv_obj_get_scroll_dir(const struct _lv_obj_t * obj) -lv_scroll_snap_t lv_obj_get_scroll_snap_x(const struct _lv_obj_t * obj) -lv_scroll_snap_t lv_obj_get_scroll_snap_y(const struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_scroll_x(const struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_scroll_y(const struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_scroll_top(struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_scroll_bottom(struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_scroll_left(struct _lv_obj_t * obj) -lv_coord_t lv_obj_get_scroll_right(struct _lv_obj_t * obj) -void lv_obj_get_scroll_end(struct _lv_obj_t * obj, lv_point_t * end) -void lv_obj_scroll_by(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en) -void lv_obj_scroll_by_bounded(struct _lv_obj_t * obj, lv_coord_t dx, lv_coord_t dy, lv_anim_enable_t anim_en) -void lv_obj_scroll_to(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en) -void lv_obj_scroll_to_x(struct _lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t anim_en) -void lv_obj_scroll_to_y(struct _lv_obj_t * obj, lv_coord_t y, lv_anim_enable_t anim_en) -void lv_obj_scroll_to_view(struct _lv_obj_t * obj, lv_anim_enable_t anim_en) -void lv_obj_scroll_to_view_recursive(struct _lv_obj_t * obj, lv_anim_enable_t anim_en) -bool lv_obj_is_scrolling(const struct _lv_obj_t * obj) -void lv_obj_update_snap(struct _lv_obj_t * obj, lv_anim_enable_t anim_en) -void lv_obj_get_scrollbar_area(struct _lv_obj_t * obj, lv_area_t * hor, lv_area_t * ver) -void lv_obj_scrollbar_invalidate(struct _lv_obj_t * obj) -void lv_obj_readjust_scroll(struct _lv_obj_t * obj, lv_anim_enable_t anim_en) +// ../../lvgl/src/misc/lv_color_op.h +static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix) +static inline lv_color32_t lv_color_mix32(lv_color32_t fg, lv_color32_t bg) +static inline uint8_t lv_color_brightness(lv_color_t c) +static inline void lv_color_filter_dsc_init(lv_color_filter_dsc_t * dsc, lv_color_filter_cb_t cb) -// ../../lvgl/src/core/lv_obj_style.h -void lv_obj_add_style(struct _lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector) -void lv_obj_remove_style(struct _lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector) -static inline void lv_obj_remove_style_all(struct _lv_obj_t * obj) -void lv_obj_report_style_change(lv_style_t * style) -void lv_obj_refresh_style(struct _lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop) -void lv_obj_enable_style_refresh(bool en) -lv_style_value_t lv_obj_get_style_prop(const struct _lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop) -void lv_obj_set_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value, lv_style_selector_t selector) -void lv_obj_set_local_style_prop_meta(struct _lv_obj_t * obj, lv_style_prop_t prop, uint16_t meta, lv_style_selector_t selector) -lv_style_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, lv_style_selector_t selector) -bool lv_obj_remove_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector) -void lv_obj_fade_in(struct _lv_obj_t * obj, uint32_t time, uint32_t delay) -void lv_obj_fade_out(struct _lv_obj_t * obj, uint32_t time, uint32_t delay) -lv_state_t lv_obj_style_get_selector_state(lv_style_selector_t selector) -lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector) -static inline void lv_obj_set_style_pad_all(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -static inline void lv_obj_set_style_pad_hor(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -static inline void lv_obj_set_style_pad_ver(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -static inline void lv_obj_set_style_pad_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -static inline void lv_obj_set_style_size(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -lv_text_align_t lv_obj_calculate_style_text_align(const struct _lv_obj_t * obj, lv_part_t part, const char * txt) -static inline lv_coord_t lv_obj_get_style_transform_zoom_safe(const struct _lv_obj_t * obj, uint32_t part) -lv_opa_t lv_obj_get_style_opa_recursive(const struct _lv_obj_t * obj, lv_part_t part) +// ../../lvgl/src/misc/lv_event.h +lv_result_t lv_event_send(lv_event_list_t * list, lv_event_t * e, bool preprocess) +void lv_event_add(lv_event_list_t * list, lv_event_cb_t cb, lv_event_code_t filter, void * user_data) +uint32_t lv_event_get_count(lv_event_list_t * list) +lv_event_dsc_t * lv_event_get_dsc(lv_event_list_t * list, uint32_t index) +lv_event_cb_t lv_event_dsc_get_cb(lv_event_dsc_t * dsc) +void * lv_event_dsc_get_user_data(lv_event_dsc_t * dsc) +bool lv_event_remove(lv_event_list_t * list, uint32_t index) +void lv_event_remove_all(lv_event_list_t * list) +void * lv_event_get_target(lv_event_t * e) +void * lv_event_get_current_target(lv_event_t * e) +lv_event_code_t lv_event_get_code(lv_event_t * e) +void * lv_event_get_param(lv_event_t * e) +void * lv_event_get_user_data(lv_event_t * e) +void lv_event_stop_bubbling(lv_event_t * e) +void lv_event_stop_processing(lv_event_t * e) +uint32_t lv_event_register_id(void) -// ../../lvgl/src/core/lv_obj_style_gen.h -static inline lv_coord_t lv_obj_get_style_width(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_min_width(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_max_width(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_height(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_min_height(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_max_height(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_x(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_y(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_align_t lv_obj_get_style_align(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_transform_width(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_transform_height(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_translate_x(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_translate_y(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_transform_zoom(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_transform_angle(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_transform_pivot_x(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_transform_pivot_y(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_pad_top(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_pad_bottom(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_pad_left(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_pad_right(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_pad_row(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_pad_column(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_bg_color(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_bg_color_filtered(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_opa_t lv_obj_get_style_bg_opa(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_bg_grad_color(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_bg_grad_color_filtered(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_grad_dir_t lv_obj_get_style_bg_grad_dir(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_bg_main_stop(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_bg_grad_stop(const struct _lv_obj_t * obj, uint32_t part) -static inline const lv_grad_dsc_t * lv_obj_get_style_bg_grad(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_dither_mode_t lv_obj_get_style_bg_dither_mode(const struct _lv_obj_t * obj, uint32_t part) -static inline const void * lv_obj_get_style_bg_img_src(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_opa_t lv_obj_get_style_bg_img_opa(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_bg_img_recolor(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_bg_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_opa_t lv_obj_get_style_bg_img_recolor_opa(const struct _lv_obj_t * obj, uint32_t part) -static inline bool lv_obj_get_style_bg_img_tiled(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_border_color(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_border_color_filtered(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_opa_t lv_obj_get_style_border_opa(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_border_width(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_border_side_t lv_obj_get_style_border_side(const struct _lv_obj_t * obj, uint32_t part) -static inline bool lv_obj_get_style_border_post(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_outline_width(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_outline_color(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_outline_color_filtered(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_opa_t lv_obj_get_style_outline_opa(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_outline_pad(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_shadow_width(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_shadow_ofs_x(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_shadow_ofs_y(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_shadow_spread(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_shadow_color(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_shadow_color_filtered(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_opa_t lv_obj_get_style_shadow_opa(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_opa_t lv_obj_get_style_img_opa(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_img_recolor(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_opa_t lv_obj_get_style_img_recolor_opa(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_line_width(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_line_dash_width(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_line_dash_gap(const struct _lv_obj_t * obj, uint32_t part) -static inline bool lv_obj_get_style_line_rounded(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_line_color(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_line_color_filtered(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_opa_t lv_obj_get_style_line_opa(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_arc_width(const struct _lv_obj_t * obj, uint32_t part) -static inline bool lv_obj_get_style_arc_rounded(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_arc_color(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_arc_color_filtered(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_opa_t lv_obj_get_style_arc_opa(const struct _lv_obj_t * obj, uint32_t part) -static inline const void * lv_obj_get_style_arc_img_src(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_text_color(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_color_t lv_obj_get_style_text_color_filtered(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_opa_t lv_obj_get_style_text_opa(const struct _lv_obj_t * obj, uint32_t part) -static inline const lv_font_t * lv_obj_get_style_text_font(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_text_letter_space(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_text_line_space(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_text_decor_t lv_obj_get_style_text_decor(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_text_align_t lv_obj_get_style_text_align(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_radius(const struct _lv_obj_t * obj, uint32_t part) -static inline bool lv_obj_get_style_clip_corner(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_opa_t lv_obj_get_style_opa(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_opa_t lv_obj_get_style_opa_layered(const struct _lv_obj_t * obj, uint32_t part) -static inline const lv_color_filter_dsc_t * lv_obj_get_style_color_filter_dsc(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_opa_t lv_obj_get_style_color_filter_opa(const struct _lv_obj_t * obj, uint32_t part) -static inline const lv_anim_t * lv_obj_get_style_anim(const struct _lv_obj_t * obj, uint32_t part) -static inline uint32_t lv_obj_get_style_anim_time(const struct _lv_obj_t * obj, uint32_t part) -static inline uint32_t lv_obj_get_style_anim_speed(const struct _lv_obj_t * obj, uint32_t part) -static inline const lv_style_transition_dsc_t * lv_obj_get_style_transition(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_blend_mode_t lv_obj_get_style_blend_mode(const struct _lv_obj_t * obj, uint32_t part) -static inline uint16_t lv_obj_get_style_layout(const struct _lv_obj_t * obj, uint32_t part) -static inline lv_base_dir_t lv_obj_get_style_base_dir(const struct _lv_obj_t * obj, uint32_t part) -void lv_obj_set_style_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_min_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_max_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_min_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_max_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_align(struct _lv_obj_t * obj, lv_align_t value, lv_style_selector_t selector) -void lv_obj_set_style_transform_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_transform_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_translate_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_translate_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_transform_zoom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_transform_angle(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_transform_pivot_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_transform_pivot_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_pad_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_pad_bottom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_pad_left(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_pad_right(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_pad_row(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_pad_column(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_bg_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) -void lv_obj_set_style_bg_grad_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_bg_grad_dir(struct _lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector) -void lv_obj_set_style_bg_main_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_bg_grad_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_bg_grad(struct _lv_obj_t * obj, const lv_grad_dsc_t * value, lv_style_selector_t selector) -void lv_obj_set_style_bg_dither_mode(struct _lv_obj_t * obj, lv_dither_mode_t value, lv_style_selector_t selector) -void lv_obj_set_style_bg_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector) -void lv_obj_set_style_bg_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) -void lv_obj_set_style_bg_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_bg_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) -void lv_obj_set_style_bg_img_tiled(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) -void lv_obj_set_style_border_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_border_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) -void lv_obj_set_style_border_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_border_side(struct _lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector) -void lv_obj_set_style_border_post(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) -void lv_obj_set_style_outline_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_outline_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_outline_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) -void lv_obj_set_style_outline_pad(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_shadow_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_shadow_ofs_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_shadow_ofs_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_shadow_spread(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_shadow_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) -void lv_obj_set_style_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) -void lv_obj_set_style_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) -void lv_obj_set_style_line_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_line_dash_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) -void lv_obj_set_style_line_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) -void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) -void lv_obj_set_style_arc_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) -void lv_obj_set_style_arc_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector) -void lv_obj_set_style_text_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) -void lv_obj_set_style_text_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) -void lv_obj_set_style_text_font(struct _lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector) -void lv_obj_set_style_text_letter_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_text_line_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_text_decor(struct _lv_obj_t * obj, lv_text_decor_t value, lv_style_selector_t selector) -void lv_obj_set_style_text_align(struct _lv_obj_t * obj, lv_text_align_t value, lv_style_selector_t selector) -void lv_obj_set_style_radius(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_clip_corner(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) -void lv_obj_set_style_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) -void lv_obj_set_style_opa_layered(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) -void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector) -void lv_obj_set_style_color_filter_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) -void lv_obj_set_style_anim(struct _lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector) -void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector) -void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector) -void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector) -void lv_obj_set_style_blend_mode(struct _lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector) -void lv_obj_set_style_layout(struct _lv_obj_t * obj, uint16_t value, lv_style_selector_t selector) -void lv_obj_set_style_base_dir(struct _lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector) +// ../../lvgl/src/misc/lv_style.h +void lv_style_init(lv_style_t * style) +void lv_style_reset(lv_style_t * style) +static inline bool lv_style_is_const(const lv_style_t * style) +lv_style_prop_t lv_style_register_prop(uint8_t flag) +lv_style_prop_t lv_style_get_num_custom_props(void) +bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop) +void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_t value) +lv_style_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value) +void lv_style_transition_dsc_init(lv_style_transition_dsc_t * tr, const lv_style_prop_t props[], lv_anim_path_cb_t path_cb, uint32_t time, uint32_t delay, void * user_data) +lv_style_value_t lv_style_prop_get_default(lv_style_prop_t prop) +static inline lv_style_res_t lv_style_get_prop_inlined(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value) +bool lv_style_is_empty(const lv_style_t * style) +static inline void lv_style_set_size(lv_style_t * style, int32_t width, int32_t height) +static inline void lv_style_set_pad_all(lv_style_t * style, int32_t value) +static inline void lv_style_set_pad_hor(lv_style_t * style, int32_t value) +static inline void lv_style_set_pad_ver(lv_style_t * style, int32_t value) +static inline void lv_style_set_pad_gap(lv_style_t * style, int32_t value) +static inline void lv_style_set_transform_scale(lv_style_t * style, int32_t value) +static inline bool lv_style_prop_has_flag(lv_style_prop_t prop, uint8_t flag) -// ../../lvgl/src/core/lv_obj_tree.h -void lv_obj_del(struct _lv_obj_t * obj) -void lv_obj_clean(struct _lv_obj_t * obj) -void lv_obj_del_delayed(struct _lv_obj_t * obj, uint32_t delay_ms) -void lv_obj_del_anim_ready_cb(lv_anim_t * a) -void lv_obj_del_async(struct _lv_obj_t * obj) -void lv_obj_set_parent(struct _lv_obj_t * obj, struct _lv_obj_t * parent) -void lv_obj_swap(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2) -void lv_obj_move_to_index(struct _lv_obj_t * obj, int32_t index) -struct _lv_obj_t * lv_obj_get_screen(const struct _lv_obj_t * obj) -lv_disp_t * lv_obj_get_disp(const struct _lv_obj_t * obj) -struct _lv_obj_t * lv_obj_get_parent(const struct _lv_obj_t * obj) -struct _lv_obj_t * lv_obj_get_child(const struct _lv_obj_t * obj, int32_t id) -uint32_t lv_obj_get_child_cnt(const struct _lv_obj_t * obj) -uint32_t lv_obj_get_index(const struct _lv_obj_t * obj) -void lv_obj_tree_walk(struct _lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data) +// ../../lvgl/src/misc/lv_style_gen.h +void lv_style_set_width(lv_style_t * style, int32_t value) +void lv_style_set_min_width(lv_style_t * style, int32_t value) +void lv_style_set_max_width(lv_style_t * style, int32_t value) +void lv_style_set_height(lv_style_t * style, int32_t value) +void lv_style_set_min_height(lv_style_t * style, int32_t value) +void lv_style_set_max_height(lv_style_t * style, int32_t value) +void lv_style_set_length(lv_style_t * style, int32_t value) +void lv_style_set_x(lv_style_t * style, int32_t value) +void lv_style_set_y(lv_style_t * style, int32_t value) +void lv_style_set_align(lv_style_t * style, lv_align_t value) +void lv_style_set_transform_width(lv_style_t * style, int32_t value) +void lv_style_set_transform_height(lv_style_t * style, int32_t value) +void lv_style_set_translate_x(lv_style_t * style, int32_t value) +void lv_style_set_translate_y(lv_style_t * style, int32_t value) +void lv_style_set_transform_scale_x(lv_style_t * style, int32_t value) +void lv_style_set_transform_scale_y(lv_style_t * style, int32_t value) +void lv_style_set_transform_rotation(lv_style_t * style, int32_t value) +void lv_style_set_transform_pivot_x(lv_style_t * style, int32_t value) +void lv_style_set_transform_pivot_y(lv_style_t * style, int32_t value) +void lv_style_set_transform_skew_x(lv_style_t * style, int32_t value) +void lv_style_set_transform_skew_y(lv_style_t * style, int32_t value) +void lv_style_set_pad_top(lv_style_t * style, int32_t value) +void lv_style_set_pad_bottom(lv_style_t * style, int32_t value) +void lv_style_set_pad_left(lv_style_t * style, int32_t value) +void lv_style_set_pad_right(lv_style_t * style, int32_t value) +void lv_style_set_pad_row(lv_style_t * style, int32_t value) +void lv_style_set_pad_column(lv_style_t * style, int32_t value) +void lv_style_set_margin_top(lv_style_t * style, int32_t value) +void lv_style_set_margin_bottom(lv_style_t * style, int32_t value) +void lv_style_set_margin_left(lv_style_t * style, int32_t value) +void lv_style_set_margin_right(lv_style_t * style, int32_t value) +void lv_style_set_bg_color(lv_style_t * style, lv_color_t value) +void lv_style_set_bg_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_bg_grad_color(lv_style_t * style, lv_color_t value) +void lv_style_set_bg_grad_dir(lv_style_t * style, lv_grad_dir_t value) +void lv_style_set_bg_main_stop(lv_style_t * style, int32_t value) +void lv_style_set_bg_grad_stop(lv_style_t * style, int32_t value) +void lv_style_set_bg_main_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_bg_grad_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_bg_grad(lv_style_t * style, const lv_grad_dsc_t * value) +void lv_style_set_bg_image_src(lv_style_t * style, const void * value) +void lv_style_set_bg_image_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_bg_image_recolor(lv_style_t * style, lv_color_t value) +void lv_style_set_bg_image_recolor_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_bg_image_tiled(lv_style_t * style, bool value) +void lv_style_set_border_color(lv_style_t * style, lv_color_t value) +void lv_style_set_border_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_border_width(lv_style_t * style, int32_t value) +void lv_style_set_border_side(lv_style_t * style, lv_border_side_t value) +void lv_style_set_border_post(lv_style_t * style, bool value) +void lv_style_set_outline_width(lv_style_t * style, int32_t value) +void lv_style_set_outline_color(lv_style_t * style, lv_color_t value) +void lv_style_set_outline_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_outline_pad(lv_style_t * style, int32_t value) +void lv_style_set_shadow_width(lv_style_t * style, int32_t value) +void lv_style_set_shadow_offset_x(lv_style_t * style, int32_t value) +void lv_style_set_shadow_offset_y(lv_style_t * style, int32_t value) +void lv_style_set_shadow_spread(lv_style_t * style, int32_t value) +void lv_style_set_shadow_color(lv_style_t * style, lv_color_t value) +void lv_style_set_shadow_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_image_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_image_recolor(lv_style_t * style, lv_color_t value) +void lv_style_set_image_recolor_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_line_width(lv_style_t * style, int32_t value) +void lv_style_set_line_dash_width(lv_style_t * style, int32_t value) +void lv_style_set_line_dash_gap(lv_style_t * style, int32_t value) +void lv_style_set_line_rounded(lv_style_t * style, bool value) +void lv_style_set_line_color(lv_style_t * style, lv_color_t value) +void lv_style_set_line_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_arc_width(lv_style_t * style, int32_t value) +void lv_style_set_arc_rounded(lv_style_t * style, bool value) +void lv_style_set_arc_color(lv_style_t * style, lv_color_t value) +void lv_style_set_arc_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_arc_image_src(lv_style_t * style, const void * value) +void lv_style_set_text_color(lv_style_t * style, lv_color_t value) +void lv_style_set_text_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_text_font(lv_style_t * style, const lv_font_t * value) +void lv_style_set_text_letter_space(lv_style_t * style, int32_t value) +void lv_style_set_text_line_space(lv_style_t * style, int32_t value) +void lv_style_set_text_decor(lv_style_t * style, lv_text_decor_t value) +void lv_style_set_text_align(lv_style_t * style, lv_text_align_t value) +void lv_style_set_radius(lv_style_t * style, int32_t value) +void lv_style_set_clip_corner(lv_style_t * style, bool value) +void lv_style_set_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_opa_layered(lv_style_t * style, lv_opa_t value) +void lv_style_set_color_filter_dsc(lv_style_t * style, const lv_color_filter_dsc_t * value) +void lv_style_set_color_filter_opa(lv_style_t * style, lv_opa_t value) +void lv_style_set_anim(lv_style_t * style, const lv_anim_t * value) +void lv_style_set_anim_duration(lv_style_t * style, uint32_t value) +void lv_style_set_transition(lv_style_t * style, const lv_style_transition_dsc_t * value) +void lv_style_set_blend_mode(lv_style_t * style, lv_blend_mode_t value) +void lv_style_set_layout(lv_style_t * style, uint16_t value) +void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value) +void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value) +void lv_style_set_flex_main_place(lv_style_t * style, lv_flex_align_t value) +void lv_style_set_flex_cross_place(lv_style_t * style, lv_flex_align_t value) +void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value) +void lv_style_set_flex_grow(lv_style_t * style, uint8_t value) +void lv_style_set_grid_column_dsc_array(lv_style_t * style, const int32_t * value) +void lv_style_set_grid_column_align(lv_style_t * style, lv_grid_align_t value) +void lv_style_set_grid_row_dsc_array(lv_style_t * style, const int32_t * value) +void lv_style_set_grid_row_align(lv_style_t * style, lv_grid_align_t value) +void lv_style_set_grid_cell_column_pos(lv_style_t * style, int32_t value) +void lv_style_set_grid_cell_x_align(lv_style_t * style, lv_grid_align_t value) +void lv_style_set_grid_cell_column_span(lv_style_t * style, int32_t value) +void lv_style_set_grid_cell_row_pos(lv_style_t * style, int32_t value) +void lv_style_set_grid_cell_y_align(lv_style_t * style, lv_grid_align_t value) +void lv_style_set_grid_cell_row_span(lv_style_t * style, int32_t value) -// ../../lvgl/src/core/lv_refr.h -void lv_refr_now(lv_disp_t * disp) -void lv_obj_redraw(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj) +// ../../lvgl/src/misc/lv_timer.h +uint32_t lv_timer_handler(void) +static inline uint32_t lv_timer_handler_run_in_period(uint32_t period) +void lv_timer_periodic_handler(void) +void lv_timer_handler_set_resume_cb(lv_timer_handler_resume_cb_t cb, void * data) +lv_timer_t * lv_timer_create_basic(void) +lv_timer_t * lv_timer_create(lv_timer_cb_t timer_xcb, uint32_t period, void * user_data) +void lv_timer_delete(lv_timer_t * timer) +void lv_timer_pause(lv_timer_t * timer) +void lv_timer_resume(lv_timer_t * timer) +void lv_timer_set_cb(lv_timer_t * timer, lv_timer_cb_t timer_cb) +void lv_timer_set_period(lv_timer_t * timer, uint32_t period) +void lv_timer_ready(lv_timer_t * timer) +void lv_timer_set_repeat_count(lv_timer_t * timer, int32_t repeat_count) +void lv_timer_set_auto_delete(lv_timer_t * timer, bool auto_delete) +void lv_timer_set_user_data(lv_timer_t * timer, void * user_data) +void lv_timer_reset(lv_timer_t * timer) +void lv_timer_enable(bool en) +uint32_t lv_timer_get_idle(void) +uint32_t lv_timer_get_time_until_next(void) +lv_timer_t * lv_timer_get_next(lv_timer_t * timer) +static inline void * lv_timer_get_user_data(lv_timer_t * timer) +static inline bool lv_timer_get_paused(lv_timer_t * timer) -// ../../lvgl/src/core/lv_theme.h +// ../../lvgl/src/themes/lv_theme.h lv_theme_t * lv_theme_get_from_obj(lv_obj_t * obj) void lv_theme_apply(lv_obj_t * obj) void lv_theme_set_parent(lv_theme_t * new_theme, lv_theme_t * parent) @@ -471,535 +987,45 @@ const lv_font_t * lv_theme_get_font_large(lv_obj_t * obj) lv_color_t lv_theme_get_color_primary(lv_obj_t * obj) lv_color_t lv_theme_get_color_secondary(lv_obj_t * obj) -// ../../lvgl/src/draw/lv_draw.h -void lv_draw_init(void) -void lv_draw_wait_for_finish(lv_draw_ctx_t * draw_ctx) +// ../../lvgl/src/widgets/animimage/lv_animimage.h +lv_obj_t * lv_animimg_create(lv_obj_t * parent) +void lv_animimg_set_src(lv_obj_t * img, const void * dsc[], size_t num) +void lv_animimg_start(lv_obj_t * obj) +void lv_animimg_set_duration(lv_obj_t * img, uint32_t duration) +void lv_animimg_set_repeat_count(lv_obj_t * img, uint32_t count) +const void ** lv_animimg_get_src(lv_obj_t * img) +uint8_t lv_animimg_get_src_count(lv_obj_t * img) +uint32_t lv_animimg_get_duration(lv_obj_t * img) +uint32_t lv_animimg_get_repeat_count(lv_obj_t * img) -// ../../lvgl/src/draw/lv_draw_arc.h -void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc) -void lv_draw_arc(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, uint16_t radius, uint16_t start_angle, uint16_t end_angle) -void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle, lv_coord_t w, bool rounded, lv_area_t * area) - -// ../../lvgl/src/draw/lv_draw_img.h -void lv_draw_img_dsc_init(lv_draw_img_dsc_t * dsc) -void lv_draw_img(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, const lv_area_t * coords, const void * src) -void lv_draw_img_decoded(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format) -lv_img_src_t lv_img_src_get_type(const void * src) - -// ../../lvgl/src/draw/lv_draw_label.h -void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc) -void lv_draw_label(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords, const char * txt, lv_draw_label_hint_t * hint) -void lv_draw_letter(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p, uint32_t letter) - -// ../../lvgl/src/draw/lv_draw_layer.h -struct _lv_draw_layer_ctx_t * lv_draw_layer_create(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * layer_area, lv_draw_layer_flags_t flags) -void lv_draw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, lv_draw_layer_flags_t flags) -void lv_draw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, lv_draw_img_dsc_t * draw_dsc) -void lv_draw_layer_destroy(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx) - -// ../../lvgl/src/draw/lv_draw_line.h -void lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc) -void lv_draw_line(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1, const lv_point_t * point2) - -// ../../lvgl/src/draw/lv_draw_mask.h -static inline uint8_t lv_draw_mask_get_cnt(void) -static inline bool lv_draw_mask_is_any(const lv_area_t * a) -int16_t lv_draw_mask_add(void * param, void * custom_id) -lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len) -lv_draw_mask_res_t lv_draw_mask_apply_ids(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len, const int16_t * ids, int16_t ids_count) -void * lv_draw_mask_remove_id(int16_t id) -void * lv_draw_mask_remove_custom(void * custom_id) -void lv_draw_mask_free_param(void * p) -uint8_t lv_draw_mask_get_cnt(void) -bool lv_draw_mask_is_any(const lv_area_t * a) -void lv_draw_mask_line_points_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x, lv_coord_t p2y, lv_draw_mask_line_side_t side) -void lv_draw_mask_line_angle_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t py, int16_t angle, lv_draw_mask_line_side_t side) -void lv_draw_mask_angle_init(lv_draw_mask_angle_param_t * param, lv_coord_t vertex_x, lv_coord_t vertex_y, lv_coord_t start_angle, lv_coord_t end_angle) -void lv_draw_mask_radius_init(lv_draw_mask_radius_param_t * param, const lv_area_t * rect, lv_coord_t radius, bool inv) -void lv_draw_mask_fade_init(lv_draw_mask_fade_param_t * param, const lv_area_t * coords, lv_opa_t opa_top, lv_coord_t y_top, lv_opa_t opa_bottom, lv_coord_t y_bottom) -void lv_draw_mask_map_init(lv_draw_mask_map_param_t * param, const lv_area_t * coords, const lv_opa_t * map) -void lv_draw_mask_polygon_init(lv_draw_mask_polygon_param_t * param, const lv_point_t * points, uint16_t point_cnt) - -// ../../lvgl/src/draw/lv_draw_rect.h -void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc) -void lv_draw_rect(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) - -// ../../lvgl/src/draw/lv_draw_transform.h -void lv_draw_transform(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf) - -// ../../lvgl/src/draw/lv_draw_triangle.h -void lv_draw_polygon(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[], uint16_t point_cnt) -void lv_draw_triangle(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[]) - -// ../../lvgl/src/draw/lv_img_buf.h - -// ../../lvgl/src/draw/lv_img_cache.h - -// ../../lvgl/src/draw/lv_img_decoder.h - -// ../../lvgl/src/extra/layouts/flex/lv_flex.h -void lv_flex_init(void) -void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow) -void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place, lv_flex_align_t track_cross_place) -void lv_obj_set_flex_grow(lv_obj_t * obj, uint8_t grow) -void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value) -void lv_style_set_flex_main_place(lv_style_t * style, lv_flex_align_t value) -void lv_style_set_flex_cross_place(lv_style_t * style, lv_flex_align_t value) -void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value) -void lv_style_set_flex_grow(lv_style_t * style, uint8_t value) -void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector) -void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) -void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) -void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) -void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector) -static inline lv_flex_flow_t lv_obj_get_style_flex_flow(const lv_obj_t * obj, uint32_t part) -static inline lv_flex_align_t lv_obj_get_style_flex_main_place(const lv_obj_t * obj, uint32_t part) -static inline lv_flex_align_t lv_obj_get_style_flex_cross_place(const lv_obj_t * obj, uint32_t part) -static inline lv_flex_align_t lv_obj_get_style_flex_track_place(const lv_obj_t * obj, uint32_t part) -static inline uint8_t lv_obj_get_style_flex_grow(const lv_obj_t * obj, uint32_t part) - -// ../../lvgl/src/extra/layouts/grid/lv_grid.h -void lv_grid_init(void) -void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const lv_coord_t col_dsc[], const lv_coord_t row_dsc[]) -void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid_align_t row_align) -void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t column_align, uint8_t col_pos, uint8_t col_span, lv_grid_align_t row_align, uint8_t row_pos, uint8_t row_span) -static inline lv_coord_t lv_grid_fr(uint8_t x) -void lv_style_set_grid_row_dsc_array(lv_style_t * style, const lv_coord_t value[]) -void lv_style_set_grid_column_dsc_array(lv_style_t * style, const lv_coord_t value[]) -void lv_style_set_grid_row_align(lv_style_t * style, lv_grid_align_t value) -void lv_style_set_grid_column_align(lv_style_t * style, lv_grid_align_t value) -void lv_style_set_grid_cell_column_pos(lv_style_t * style, lv_coord_t value) -void lv_style_set_grid_cell_column_span(lv_style_t * style, lv_coord_t value) -void lv_style_set_grid_cell_row_pos(lv_style_t * style, lv_coord_t value) -void lv_style_set_grid_cell_row_span(lv_style_t * style, lv_coord_t value) -void lv_style_set_grid_cell_x_align(lv_style_t * style, lv_coord_t value) -void lv_style_set_grid_cell_y_align(lv_style_t * style, lv_coord_t value) -void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector) -void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector) -void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) -void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) -void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -static inline const lv_coord_t * lv_obj_get_style_grid_row_dsc_array(const lv_obj_t * obj, uint32_t part) -static inline const lv_coord_t * lv_obj_get_style_grid_column_dsc_array(const lv_obj_t * obj, uint32_t part) -static inline lv_grid_align_t lv_obj_get_style_grid_row_align(const lv_obj_t * obj, uint32_t part) -static inline lv_grid_align_t lv_obj_get_style_grid_column_align(const lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_grid_cell_column_pos(const lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_grid_cell_column_span(const lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_grid_cell_row_pos(const lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_grid_cell_row_span(const lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_grid_cell_x_align(const lv_obj_t * obj, uint32_t part) -static inline lv_coord_t lv_obj_get_style_grid_cell_y_align(const lv_obj_t * obj, uint32_t part) - -// ../../lvgl/src/extra/layouts/lv_layouts.h - -// ../../lvgl/src/extra/libs/qrcode/lv_qrcode.h -lv_obj_t * lv_qrcode_create(lv_obj_t * parent, lv_coord_t size, lv_color_t dark_color, lv_color_t light_color) -lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_len) -void lv_qrcode_delete(lv_obj_t * qrcode) - -// ../../lvgl/src/extra/themes/default/lv_theme_default.h -lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font) -lv_theme_t * lv_theme_default_get(void) -bool lv_theme_default_is_inited(void) - -// ../../lvgl/src/extra/themes/mono/lv_theme_mono.h -lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t * font) -bool lv_theme_mono_is_inited(void) - -// ../../lvgl/src/extra/widgets/chart/lv_chart.h -lv_obj_t * lv_chart_create(lv_obj_t * parent) -void lv_chart_set_type(lv_obj_t * obj, lv_chart_type_t type) -void lv_chart_set_point_count(lv_obj_t * obj, uint16_t cnt) -void lv_chart_set_range(lv_obj_t * obj, lv_chart_axis_t axis, lv_coord_t min, lv_coord_t max) -void lv_chart_set_update_mode(lv_obj_t * obj, lv_chart_update_mode_t update_mode) -void lv_chart_set_div_line_count(lv_obj_t * obj, uint8_t hdiv, uint8_t vdiv) -void lv_chart_set_zoom_x(lv_obj_t * obj, uint16_t zoom_x) -void lv_chart_set_zoom_y(lv_obj_t * obj, uint16_t zoom_y) -uint16_t lv_chart_get_zoom_x(const lv_obj_t * obj) -uint16_t lv_chart_get_zoom_y(const lv_obj_t * obj) -void lv_chart_set_axis_tick(lv_obj_t * obj, lv_chart_axis_t axis, lv_coord_t major_len, lv_coord_t minor_len, lv_coord_t major_cnt, lv_coord_t minor_cnt, bool label_en, lv_coord_t draw_size) -lv_chart_type_t lv_chart_get_type(const lv_obj_t * obj) -uint16_t lv_chart_get_point_count(const lv_obj_t * obj) -uint16_t lv_chart_get_x_start_point(const lv_obj_t * obj, lv_chart_series_t * ser) -void lv_chart_get_point_pos_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_point_t * p_out) -void lv_chart_refresh(lv_obj_t * obj) -lv_chart_series_t * lv_chart_add_series(lv_obj_t * obj, lv_color_t color, lv_chart_axis_t axis) -void lv_chart_remove_series(lv_obj_t * obj, lv_chart_series_t * series) -void lv_chart_hide_series(lv_obj_t * chart, lv_chart_series_t * series, bool hide) -void lv_chart_set_series_color(lv_obj_t * chart, lv_chart_series_t * series, lv_color_t color) -void lv_chart_set_x_start_point(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id) -lv_chart_series_t * lv_chart_get_series_next(const lv_obj_t * chart, const lv_chart_series_t * ser) -lv_chart_cursor_t * lv_chart_add_cursor(lv_obj_t * obj, lv_color_t color, lv_dir_t dir) -void lv_chart_set_cursor_pos(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_point_t * pos) -void lv_chart_set_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_chart_series_t * ser, uint16_t point_id) -lv_point_t lv_chart_get_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * cursor) -void lv_chart_set_all_value(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t value) -void lv_chart_set_next_value(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t value) -void lv_chart_set_next_value2(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t x_value, lv_coord_t y_value) -void lv_chart_set_value_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_coord_t value) -void lv_chart_set_value_by_id2(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_coord_t x_value, lv_coord_t y_value) -void lv_chart_set_ext_y_array(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t array[]) -void lv_chart_set_ext_x_array(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t array[]) -lv_coord_t * lv_chart_get_y_array(const lv_obj_t * obj, lv_chart_series_t * ser) -lv_coord_t * lv_chart_get_x_array(const lv_obj_t * obj, lv_chart_series_t * ser) -uint32_t lv_chart_get_pressed_point(const lv_obj_t * obj) - -// ../../lvgl/src/extra/widgets/colorwheel/lv_colorwheel.h -lv_obj_t * lv_colorwheel_create(lv_obj_t * parent, bool knob_recolor) -bool lv_colorwheel_set_hsv(lv_obj_t * obj, lv_color_hsv_t hsv) -bool lv_colorwheel_set_rgb(lv_obj_t * obj, lv_color_t color) -void lv_colorwheel_set_mode(lv_obj_t * obj, lv_colorwheel_mode_t mode) -void lv_colorwheel_set_mode_fixed(lv_obj_t * obj, bool fixed) -lv_color_hsv_t lv_colorwheel_get_hsv(lv_obj_t * obj) -lv_color_t lv_colorwheel_get_rgb(lv_obj_t * obj) -lv_colorwheel_mode_t lv_colorwheel_get_color_mode(lv_obj_t * obj) -bool lv_colorwheel_get_color_mode_fixed(lv_obj_t * obj) - -// ../../lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h -lv_obj_t * lv_imgbtn_create(lv_obj_t * parent) -void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_imgbtn_state_t state, const void * src_left, const void * src_mid, const void * src_right) -void lv_imgbtn_set_state(lv_obj_t * imgbtn, lv_imgbtn_state_t state) - -// ../../lvgl/src/extra/widgets/keyboard/lv_keyboard.h -lv_obj_t * lv_keyboard_create(lv_obj_t * parent) -void lv_keyboard_set_textarea(lv_obj_t * kb, lv_obj_t * ta) -void lv_keyboard_set_mode(lv_obj_t * kb, lv_keyboard_mode_t mode) -void lv_keyboard_set_popovers(lv_obj_t * kb, bool en) -void lv_keyboard_set_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const char * map[], const lv_btnmatrix_ctrl_t ctrl_map[]) -lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * kb) -lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * kb) -bool lv_btnmatrix_get_popovers(const lv_obj_t * obj) -static inline const char ** lv_keyboard_get_map_array(const lv_obj_t * kb) -static inline uint16_t lv_keyboard_get_selected_btn(const lv_obj_t * obj) -static inline const char * lv_keyboard_get_btn_text(const lv_obj_t * obj, uint16_t btn_id) - -// ../../lvgl/src/extra/widgets/led/lv_led.h -lv_obj_t * lv_led_create(lv_obj_t * parent) -void lv_led_set_color(lv_obj_t * led, lv_color_t color) -void lv_led_set_brightness(lv_obj_t * led, uint8_t bright) -void lv_led_on(lv_obj_t * led) -void lv_led_off(lv_obj_t * led) -void lv_led_toggle(lv_obj_t * led) -uint8_t lv_led_get_brightness(const lv_obj_t * obj) - -// ../../lvgl/src/extra/widgets/list/lv_list.h -lv_obj_t * lv_list_create(lv_obj_t * parent) -lv_obj_t * lv_list_add_text(lv_obj_t * list, const char * txt) -lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * icon, const char * txt) -const char * lv_list_get_btn_text(lv_obj_t * list, lv_obj_t * btn) - -// ../../lvgl/src/extra/widgets/meter/lv_meter.h -lv_obj_t * lv_meter_create(lv_obj_t * parent) -lv_meter_scale_t * lv_meter_add_scale(lv_obj_t * obj) -void lv_meter_set_scale_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t cnt, uint16_t width, uint16_t len, lv_color_t color) -void lv_meter_set_scale_major_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t nth, uint16_t width, uint16_t len, lv_color_t color, int16_t label_gap) -void lv_meter_set_scale_range(lv_obj_t * obj, lv_meter_scale_t * scale, int32_t min, int32_t max, uint32_t angle_range, uint32_t rotation) -lv_meter_indicator_t * lv_meter_add_needle_line(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, lv_color_t color, int16_t r_mod) -lv_meter_indicator_t * lv_meter_add_needle_img(lv_obj_t * obj, lv_meter_scale_t * scale, const void * src, lv_coord_t pivot_x, lv_coord_t pivot_y) -lv_meter_indicator_t * lv_meter_add_arc(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, lv_color_t color, int16_t r_mod) -lv_meter_indicator_t * lv_meter_add_scale_lines(lv_obj_t * obj, lv_meter_scale_t * scale, lv_color_t color_start, lv_color_t color_end, bool local, int16_t width_mod) -void lv_meter_set_indicator_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value) -void lv_meter_set_indicator_start_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value) -void lv_meter_set_indicator_end_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value) - -// ../../lvgl/src/extra/widgets/msgbox/lv_msgbox.h -lv_obj_t * lv_msgbox_create(lv_obj_t * parent, const char * title, const char * txt, const char * btn_txts[], bool add_close_btn) -lv_obj_t * lv_msgbox_get_title(lv_obj_t * obj) -lv_obj_t * lv_msgbox_get_close_btn(lv_obj_t * obj) -lv_obj_t * lv_msgbox_get_text(lv_obj_t * obj) -lv_obj_t * lv_msgbox_get_content(lv_obj_t * obj) -lv_obj_t * lv_msgbox_get_btns(lv_obj_t * obj) -uint16_t lv_msgbox_get_active_btn(lv_obj_t * mbox) -const char * lv_msgbox_get_active_btn_text(lv_obj_t * mbox) -void lv_msgbox_close(lv_obj_t * mbox) -void lv_msgbox_close_async(lv_obj_t * mbox) - -// ../../lvgl/src/extra/widgets/spinbox/lv_spinbox.h -lv_obj_t * lv_spinbox_create(lv_obj_t * parent) -void lv_spinbox_set_value(lv_obj_t * obj, int32_t i) -void lv_spinbox_set_rollover(lv_obj_t * obj, bool b) -void lv_spinbox_set_digit_format(lv_obj_t * obj, uint8_t digit_count, uint8_t separator_position) -void lv_spinbox_set_step(lv_obj_t * obj, uint32_t step) -void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max) -void lv_spinbox_set_cursor_pos(lv_obj_t * obj, uint8_t pos) -void lv_spinbox_set_digit_step_direction(lv_obj_t * obj, lv_dir_t direction) -bool lv_spinbox_get_rollover(lv_obj_t * obj) -int32_t lv_spinbox_get_value(lv_obj_t * obj) -int32_t lv_spinbox_get_step(lv_obj_t * obj) -void lv_spinbox_step_next(lv_obj_t * obj) -void lv_spinbox_step_prev(lv_obj_t * obj) -void lv_spinbox_increment(lv_obj_t * obj) -void lv_spinbox_decrement(lv_obj_t * obj) - -// ../../lvgl/src/extra/widgets/spinner/lv_spinner.h -lv_obj_t * lv_spinner_create(lv_obj_t * parent, uint32_t time, uint32_t arc_length) - -// ../../lvgl/src/extra/widgets/tabview/lv_tabview.h -lv_obj_t * lv_tabview_create(lv_obj_t * parent, lv_dir_t tab_pos, lv_coord_t tab_size) -lv_obj_t * lv_tabview_add_tab(lv_obj_t * tv, const char * name) -void lv_tabview_rename_tab(lv_obj_t * obj, uint32_t tab_id, const char * new_name) -lv_obj_t * lv_tabview_get_content(lv_obj_t * tv) -lv_obj_t * lv_tabview_get_tab_btns(lv_obj_t * tv) -void lv_tabview_set_act(lv_obj_t * obj, uint32_t id, lv_anim_enable_t anim_en) -uint16_t lv_tabview_get_tab_act(lv_obj_t * tv) - -// ../../lvgl/src/extra/widgets/tileview/lv_tileview.h -lv_obj_t * lv_tileview_create(lv_obj_t * parent) -lv_obj_t * lv_tileview_add_tile(lv_obj_t * tv, uint8_t col_id, uint8_t row_id, lv_dir_t dir) -void lv_obj_set_tile(lv_obj_t * tv, lv_obj_t * tile_obj, lv_anim_enable_t anim_en) -void lv_obj_set_tile_id(lv_obj_t * tv, uint32_t col_id, uint32_t row_id, lv_anim_enable_t anim_en) -lv_obj_t * lv_tileview_get_tile_act(lv_obj_t * obj) - -// ../../lvgl/src/font/lv_font.h -const uint8_t * lv_font_get_glyph_bitmap(const lv_font_t * font_p, uint32_t letter) -bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_out, uint32_t letter, uint32_t letter_next) -uint16_t lv_font_get_glyph_width(const lv_font_t * font, uint32_t letter, uint32_t letter_next) -static inline lv_coord_t lv_font_get_line_height(const lv_font_t * font_p) - -// ../../lvgl/src/lv_api_map.h -static inline uint32_t lv_task_handler(void) -static inline void lv_obj_move_foreground(lv_obj_t * obj) -static inline void lv_obj_move_background(lv_obj_t * obj) -static inline uint32_t lv_obj_get_child_id(const struct _lv_obj_t * obj) - -// ../../lvgl/src/misc/lv_anim.h -void lv_anim_init(lv_anim_t * a) -static inline void lv_anim_set_var(lv_anim_t * a, void * var) -static inline void lv_anim_set_exec_cb(lv_anim_t * a, lv_anim_exec_xcb_t exec_cb) -static inline void lv_anim_set_time(lv_anim_t * a, uint32_t duration) -static inline void lv_anim_set_delay(lv_anim_t * a, uint32_t delay) -static inline void lv_anim_set_values(lv_anim_t * a, int32_t start, int32_t end) -static inline void lv_anim_set_custom_exec_cb(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) -static inline void lv_anim_set_path_cb(lv_anim_t * a, lv_anim_path_cb_t path_cb) -static inline void lv_anim_set_start_cb(lv_anim_t * a, lv_anim_start_cb_t start_cb) -static inline void lv_anim_set_get_value_cb(lv_anim_t * a, lv_anim_get_value_cb_t get_value_cb) -static inline void lv_anim_set_ready_cb(lv_anim_t * a, lv_anim_ready_cb_t ready_cb) -static inline void lv_anim_set_deleted_cb(lv_anim_t * a, lv_anim_deleted_cb_t deleted_cb) -static inline void lv_anim_set_playback_time(lv_anim_t * a, uint32_t time) -static inline void lv_anim_set_playback_delay(lv_anim_t * a, uint32_t delay) -static inline void lv_anim_set_repeat_count(lv_anim_t * a, uint16_t cnt) -static inline void lv_anim_set_repeat_delay(lv_anim_t * a, uint32_t delay) -static inline void lv_anim_set_early_apply(lv_anim_t * a, bool en) -static inline void lv_anim_set_user_data(lv_anim_t * a, void * user_data) -lv_anim_t * lv_anim_start(const lv_anim_t * a) -static inline uint32_t lv_anim_get_delay(lv_anim_t * a) -uint32_t lv_anim_get_playtime(lv_anim_t * a) -static inline void * lv_anim_get_user_data(lv_anim_t * a) -bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb) -void lv_anim_del_all(void) -lv_anim_t * lv_anim_get(void * var, lv_anim_exec_xcb_t exec_cb) -struct _lv_timer_t * lv_anim_get_timer(void) -static inline bool lv_anim_custom_del(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) -static inline lv_anim_t * lv_anim_custom_get(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) -uint16_t lv_anim_count_running(void) -uint32_t lv_anim_speed_to_time(uint32_t speed, int32_t start, int32_t end) -void lv_anim_refr_now(void) - -// ../../lvgl/src/misc/lv_area.h -void lv_area_set(lv_area_t * area_p, lv_coord_t x1, lv_coord_t y1, lv_coord_t x2, lv_coord_t y2) -inline static void lv_area_copy(lv_area_t * dest, const lv_area_t * src) -static inline lv_coord_t lv_area_get_width(const lv_area_t * area_p) -static inline lv_coord_t lv_area_get_height(const lv_area_t * area_p) -void lv_area_set_width(lv_area_t * area_p, lv_coord_t w) -void lv_area_set_height(lv_area_t * area_p, lv_coord_t h) -uint32_t lv_area_get_size(const lv_area_t * area_p) -void lv_area_increase(lv_area_t * area, lv_coord_t w_extra, lv_coord_t h_extra) -void lv_area_move(lv_area_t * area, lv_coord_t x_ofs, lv_coord_t y_ofs) -void lv_area_align(const lv_area_t * base, lv_area_t * to_align, lv_align_t align, lv_coord_t ofs_x, lv_coord_t ofs_y) -void lv_point_transform(lv_point_t * p, int32_t angle, int32_t zoom, const lv_point_t * pivot) -static inline lv_coord_t lv_pct(lv_coord_t x) - -// ../../lvgl/src/misc/lv_color.h -static inline uint8_t lv_color_to1(lv_color_t color) -static inline uint8_t lv_color_to8(lv_color_t color) -static inline uint16_t lv_color_to16(lv_color_t color) -static inline uint32_t lv_color_to32(lv_color_t color) -static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix) -static inline void lv_color_premult(lv_color_t c, uint8_t mix, uint16_t * out) -static inline lv_color_t lv_color_mix_premult(uint16_t * premult_c1, lv_color_t c2, uint8_t mix) -static inline void lv_color_mix_with_alpha(lv_color_t bg_color, lv_opa_t bg_opa, lv_color_t fg_color, lv_opa_t fg_opa, lv_color_t * res_color, lv_opa_t * res_opa) -static inline uint8_t lv_color_brightness(lv_color_t color) -static inline lv_color_t lv_color_make(uint8_t r, uint8_t g, uint8_t b) -static inline lv_color_t lv_color_hex(uint32_t c) -static inline lv_color_t lv_color_hex3(uint32_t c) -static inline void lv_color_filter_dsc_init(lv_color_filter_dsc_t * dsc, lv_color_filter_cb_t cb) -void lv_color_fill(lv_color_t * buf, lv_color_t color, uint32_t px_num) -lv_color_t lv_color_lighten(lv_color_t c, lv_opa_t lvl) -lv_color_t lv_color_darken(lv_color_t c, lv_opa_t lvl) -lv_color_t lv_color_change_lightness(lv_color_t c, lv_opa_t lvl) -lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v) -lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8) -lv_color_hsv_t lv_color_to_hsv(lv_color_t color) -static inline lv_color_t lv_color_chroma_key(void) -lv_color_t lv_palette_main(lv_palette_t p) -static inline lv_color_t lv_color_white(void) -static inline lv_color_t lv_color_black(void) -lv_color_t lv_palette_lighten(lv_palette_t p, uint8_t lvl) -lv_color_t lv_palette_darken(lv_palette_t p, uint8_t lvl) - -// ../../lvgl/src/misc/lv_math.h -int16_t lv_trigo_sin(int16_t angle) -static inline int16_t lv_trigo_cos(int16_t angle) -uint32_t lv_bezier3(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) -uint16_t lv_atan2(int x, int y) -void lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask) -int32_t lv_map(int32_t x, int32_t min_in, int32_t max_in, int32_t min_out, int32_t max_out) -uint32_t lv_rand(uint32_t min, uint32_t max) - -// ../../lvgl/src/misc/lv_style.h -void lv_style_init(lv_style_t * style) -void lv_style_reset(lv_style_t * style) -lv_style_prop_t lv_style_register_prop(uint8_t flag) -lv_style_prop_t lv_style_get_num_custom_props(void) -bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop) -void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_t value) -void lv_style_set_prop_meta(lv_style_t * style, lv_style_prop_t prop, uint16_t meta) -lv_style_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value) -void lv_style_transition_dsc_init(lv_style_transition_dsc_t * tr, const lv_style_prop_t props[], lv_anim_path_cb_t path_cb, uint32_t time, uint32_t delay, void * user_data) -lv_style_value_t lv_style_prop_get_default(lv_style_prop_t prop) -static inline lv_style_res_t lv_style_get_prop_inlined(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value) -bool lv_style_is_empty(const lv_style_t * style) -static inline void lv_style_set_size(lv_style_t * style, lv_coord_t value) -static inline void lv_style_set_pad_all(lv_style_t * style, lv_coord_t value) -static inline void lv_style_set_pad_hor(lv_style_t * style, lv_coord_t value) -static inline void lv_style_set_pad_ver(lv_style_t * style, lv_coord_t value) -static inline void lv_style_set_pad_gap(lv_style_t * style, lv_coord_t value) -static inline bool lv_style_prop_has_flag(lv_style_prop_t prop, uint8_t flag) - -// ../../lvgl/src/misc/lv_style_gen.h -void lv_style_set_width(lv_style_t * style, lv_coord_t value) -void lv_style_set_min_width(lv_style_t * style, lv_coord_t value) -void lv_style_set_max_width(lv_style_t * style, lv_coord_t value) -void lv_style_set_height(lv_style_t * style, lv_coord_t value) -void lv_style_set_min_height(lv_style_t * style, lv_coord_t value) -void lv_style_set_max_height(lv_style_t * style, lv_coord_t value) -void lv_style_set_x(lv_style_t * style, lv_coord_t value) -void lv_style_set_y(lv_style_t * style, lv_coord_t value) -void lv_style_set_align(lv_style_t * style, lv_align_t value) -void lv_style_set_transform_width(lv_style_t * style, lv_coord_t value) -void lv_style_set_transform_height(lv_style_t * style, lv_coord_t value) -void lv_style_set_translate_x(lv_style_t * style, lv_coord_t value) -void lv_style_set_translate_y(lv_style_t * style, lv_coord_t value) -void lv_style_set_transform_zoom(lv_style_t * style, lv_coord_t value) -void lv_style_set_transform_angle(lv_style_t * style, lv_coord_t value) -void lv_style_set_transform_pivot_x(lv_style_t * style, lv_coord_t value) -void lv_style_set_transform_pivot_y(lv_style_t * style, lv_coord_t value) -void lv_style_set_pad_top(lv_style_t * style, lv_coord_t value) -void lv_style_set_pad_bottom(lv_style_t * style, lv_coord_t value) -void lv_style_set_pad_left(lv_style_t * style, lv_coord_t value) -void lv_style_set_pad_right(lv_style_t * style, lv_coord_t value) -void lv_style_set_pad_row(lv_style_t * style, lv_coord_t value) -void lv_style_set_pad_column(lv_style_t * style, lv_coord_t value) -void lv_style_set_bg_color(lv_style_t * style, lv_color_t value) -void lv_style_set_bg_opa(lv_style_t * style, lv_opa_t value) -void lv_style_set_bg_grad_color(lv_style_t * style, lv_color_t value) -void lv_style_set_bg_grad_dir(lv_style_t * style, lv_grad_dir_t value) -void lv_style_set_bg_main_stop(lv_style_t * style, lv_coord_t value) -void lv_style_set_bg_grad_stop(lv_style_t * style, lv_coord_t value) -void lv_style_set_bg_grad(lv_style_t * style, const lv_grad_dsc_t * value) -void lv_style_set_bg_dither_mode(lv_style_t * style, lv_dither_mode_t value) -void lv_style_set_bg_img_src(lv_style_t * style, const void * value) -void lv_style_set_bg_img_opa(lv_style_t * style, lv_opa_t value) -void lv_style_set_bg_img_recolor(lv_style_t * style, lv_color_t value) -void lv_style_set_bg_img_recolor_opa(lv_style_t * style, lv_opa_t value) -void lv_style_set_bg_img_tiled(lv_style_t * style, bool value) -void lv_style_set_border_color(lv_style_t * style, lv_color_t value) -void lv_style_set_border_opa(lv_style_t * style, lv_opa_t value) -void lv_style_set_border_width(lv_style_t * style, lv_coord_t value) -void lv_style_set_border_side(lv_style_t * style, lv_border_side_t value) -void lv_style_set_border_post(lv_style_t * style, bool value) -void lv_style_set_outline_width(lv_style_t * style, lv_coord_t value) -void lv_style_set_outline_color(lv_style_t * style, lv_color_t value) -void lv_style_set_outline_opa(lv_style_t * style, lv_opa_t value) -void lv_style_set_outline_pad(lv_style_t * style, lv_coord_t value) -void lv_style_set_shadow_width(lv_style_t * style, lv_coord_t value) -void lv_style_set_shadow_ofs_x(lv_style_t * style, lv_coord_t value) -void lv_style_set_shadow_ofs_y(lv_style_t * style, lv_coord_t value) -void lv_style_set_shadow_spread(lv_style_t * style, lv_coord_t value) -void lv_style_set_shadow_color(lv_style_t * style, lv_color_t value) -void lv_style_set_shadow_opa(lv_style_t * style, lv_opa_t value) -void lv_style_set_img_opa(lv_style_t * style, lv_opa_t value) -void lv_style_set_img_recolor(lv_style_t * style, lv_color_t value) -void lv_style_set_img_recolor_opa(lv_style_t * style, lv_opa_t value) -void lv_style_set_line_width(lv_style_t * style, lv_coord_t value) -void lv_style_set_line_dash_width(lv_style_t * style, lv_coord_t value) -void lv_style_set_line_dash_gap(lv_style_t * style, lv_coord_t value) -void lv_style_set_line_rounded(lv_style_t * style, bool value) -void lv_style_set_line_color(lv_style_t * style, lv_color_t value) -void lv_style_set_line_opa(lv_style_t * style, lv_opa_t value) -void lv_style_set_arc_width(lv_style_t * style, lv_coord_t value) -void lv_style_set_arc_rounded(lv_style_t * style, bool value) -void lv_style_set_arc_color(lv_style_t * style, lv_color_t value) -void lv_style_set_arc_opa(lv_style_t * style, lv_opa_t value) -void lv_style_set_arc_img_src(lv_style_t * style, const void * value) -void lv_style_set_text_color(lv_style_t * style, lv_color_t value) -void lv_style_set_text_opa(lv_style_t * style, lv_opa_t value) -void lv_style_set_text_font(lv_style_t * style, const lv_font_t * value) -void lv_style_set_text_letter_space(lv_style_t * style, lv_coord_t value) -void lv_style_set_text_line_space(lv_style_t * style, lv_coord_t value) -void lv_style_set_text_decor(lv_style_t * style, lv_text_decor_t value) -void lv_style_set_text_align(lv_style_t * style, lv_text_align_t value) -void lv_style_set_radius(lv_style_t * style, lv_coord_t value) -void lv_style_set_clip_corner(lv_style_t * style, bool value) -void lv_style_set_opa(lv_style_t * style, lv_opa_t value) -void lv_style_set_opa_layered(lv_style_t * style, lv_opa_t value) -void lv_style_set_color_filter_dsc(lv_style_t * style, const lv_color_filter_dsc_t * value) -void lv_style_set_color_filter_opa(lv_style_t * style, lv_opa_t value) -void lv_style_set_anim(lv_style_t * style, const lv_anim_t * value) -void lv_style_set_anim_time(lv_style_t * style, uint32_t value) -void lv_style_set_anim_speed(lv_style_t * style, uint32_t value) -void lv_style_set_transition(lv_style_t * style, const lv_style_transition_dsc_t * value) -void lv_style_set_blend_mode(lv_style_t * style, lv_blend_mode_t value) -void lv_style_set_layout(lv_style_t * style, uint16_t value) -void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value) - -// ../../lvgl/src/misc/lv_timer.h -uint32_t lv_timer_handler(void) -static inline uint32_t lv_timer_handler_run_in_period(uint32_t ms) -lv_timer_t * lv_timer_create_basic(void) -lv_timer_t * lv_timer_create(lv_timer_cb_t timer_xcb, uint32_t period, void * user_data) -void lv_timer_del(lv_timer_t * timer) -void lv_timer_pause(lv_timer_t * timer) -void lv_timer_resume(lv_timer_t * timer) -void lv_timer_set_cb(lv_timer_t * timer, lv_timer_cb_t timer_cb) -void lv_timer_set_period(lv_timer_t * timer, uint32_t period) -void lv_timer_ready(lv_timer_t * timer) -void lv_timer_set_repeat_count(lv_timer_t * timer, int32_t repeat_count) -void lv_timer_reset(lv_timer_t * timer) -void lv_timer_enable(bool en) -uint8_t lv_timer_get_idle(void) -lv_timer_t * lv_timer_get_next(lv_timer_t * timer) - -// ../../lvgl/src/widgets/lv_arc.h +// ../../lvgl/src/widgets/arc/lv_arc.h lv_obj_t * lv_arc_create(lv_obj_t * parent) -void lv_arc_set_start_angle(lv_obj_t * obj, uint16_t start) -void lv_arc_set_end_angle(lv_obj_t * obj, uint16_t end) -void lv_arc_set_angles(lv_obj_t * obj, uint16_t start, uint16_t end) -void lv_arc_set_bg_start_angle(lv_obj_t * obj, uint16_t start) -void lv_arc_set_bg_end_angle(lv_obj_t * obj, uint16_t end) -void lv_arc_set_bg_angles(lv_obj_t * obj, uint16_t start, uint16_t end) -void lv_arc_set_rotation(lv_obj_t * obj, uint16_t rotation) +void lv_arc_set_start_angle(lv_obj_t * obj, lv_value_precise_t start) +void lv_arc_set_end_angle(lv_obj_t * obj, lv_value_precise_t end) +void lv_arc_set_angles(lv_obj_t * obj, lv_value_precise_t start, lv_value_precise_t end) +void lv_arc_set_bg_start_angle(lv_obj_t * obj, lv_value_precise_t start) +void lv_arc_set_bg_end_angle(lv_obj_t * obj, lv_value_precise_t end) +void lv_arc_set_bg_angles(lv_obj_t * obj, lv_value_precise_t start, lv_value_precise_t end) +void lv_arc_set_rotation(lv_obj_t * obj, int32_t rotation) void lv_arc_set_mode(lv_obj_t * obj, lv_arc_mode_t type) -void lv_arc_set_value(lv_obj_t * obj, int16_t value) -void lv_arc_set_range(lv_obj_t * obj, int16_t min, int16_t max) -void lv_arc_set_change_rate(lv_obj_t * obj, uint16_t rate) -uint16_t lv_arc_get_angle_start(lv_obj_t * obj) -uint16_t lv_arc_get_angle_end(lv_obj_t * obj) -uint16_t lv_arc_get_bg_angle_start(lv_obj_t * obj) -uint16_t lv_arc_get_bg_angle_end(lv_obj_t * obj) -int16_t lv_arc_get_value(const lv_obj_t * obj) -int16_t lv_arc_get_min_value(const lv_obj_t * obj) -int16_t lv_arc_get_max_value(const lv_obj_t * obj) +void lv_arc_set_value(lv_obj_t * obj, int32_t value) +void lv_arc_set_range(lv_obj_t * obj, int32_t min, int32_t max) +void lv_arc_set_change_rate(lv_obj_t * obj, uint32_t rate) +void lv_arc_set_knob_offset(lv_obj_t * obj, int32_t offset) +lv_value_precise_t lv_arc_get_angle_start(lv_obj_t * obj) +lv_value_precise_t lv_arc_get_angle_end(lv_obj_t * obj) +lv_value_precise_t lv_arc_get_bg_angle_start(lv_obj_t * obj) +lv_value_precise_t lv_arc_get_bg_angle_end(lv_obj_t * obj) +int32_t lv_arc_get_value(const lv_obj_t * obj) +int32_t lv_arc_get_min_value(const lv_obj_t * obj) +int32_t lv_arc_get_max_value(const lv_obj_t * obj) lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj) -void lv_arc_align_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_align, lv_coord_t r_offset) -void lv_arc_rotate_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_rotate, lv_coord_t r_offset) +int32_t lv_arc_get_rotation(const lv_obj_t * obj) +int32_t lv_arc_get_knob_offset(const lv_obj_t * obj) +void lv_arc_align_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_align, int32_t r_offset) +void lv_arc_rotate_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_rotate, int32_t r_offset) -// ../../lvgl/src/widgets/lv_bar.h +// ../../lvgl/src/widgets/bar/lv_bar.h lv_obj_t * lv_bar_create(lv_obj_t * parent) void lv_bar_set_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim) void lv_bar_set_start_value(lv_obj_t * obj, int32_t start_value, lv_anim_enable_t anim) @@ -1010,70 +1036,120 @@ int32_t lv_bar_get_start_value(const lv_obj_t * obj) int32_t lv_bar_get_min_value(const lv_obj_t * obj) int32_t lv_bar_get_max_value(const lv_obj_t * obj) lv_bar_mode_t lv_bar_get_mode(lv_obj_t * obj) +bool lv_bar_is_symmetrical(lv_obj_t * obj) -// ../../lvgl/src/widgets/lv_btn.h -lv_obj_t * lv_btn_create(lv_obj_t * parent) +// ../../lvgl/src/widgets/button/lv_button.h +lv_obj_t * lv_button_create(lv_obj_t * parent) -// ../../lvgl/src/widgets/lv_btnmatrix.h -lv_obj_t * lv_btnmatrix_create(lv_obj_t * parent) -void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]) -void lv_btnmatrix_set_ctrl_map(lv_obj_t * obj, const lv_btnmatrix_ctrl_t ctrl_map[]) -void lv_btnmatrix_set_selected_btn(lv_obj_t * obj, uint16_t btn_id) -void lv_btnmatrix_set_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl) -void lv_btnmatrix_clear_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl) -void lv_btnmatrix_set_btn_ctrl_all(lv_obj_t * obj, lv_btnmatrix_ctrl_t ctrl) -void lv_btnmatrix_clear_btn_ctrl_all(lv_obj_t * obj, lv_btnmatrix_ctrl_t ctrl) -void lv_btnmatrix_set_btn_width(lv_obj_t * obj, uint16_t btn_id, uint8_t width) -void lv_btnmatrix_set_one_checked(lv_obj_t * obj, bool en) -const char ** lv_btnmatrix_get_map(const lv_obj_t * obj) -uint16_t lv_btnmatrix_get_selected_btn(const lv_obj_t * obj) -const char * lv_btnmatrix_get_btn_text(const lv_obj_t * obj, uint16_t btn_id) -bool lv_btnmatrix_has_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl) -bool lv_btnmatrix_get_one_checked(const lv_obj_t * obj) +// ../../lvgl/src/widgets/buttonmatrix/lv_buttonmatrix.h +lv_obj_t * lv_buttonmatrix_create(lv_obj_t * parent) +void lv_buttonmatrix_set_map(lv_obj_t * obj, const char * map[]) +void lv_buttonmatrix_set_ctrl_map(lv_obj_t * obj, const lv_buttonmatrix_ctrl_t ctrl_map[]) +void lv_buttonmatrix_set_selected_button(lv_obj_t * obj, uint32_t btn_id) +void lv_buttonmatrix_set_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl) +void lv_buttonmatrix_clear_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl) +void lv_buttonmatrix_set_button_ctrl_all(lv_obj_t * obj, lv_buttonmatrix_ctrl_t ctrl) +void lv_buttonmatrix_clear_button_ctrl_all(lv_obj_t * obj, lv_buttonmatrix_ctrl_t ctrl) +void lv_buttonmatrix_set_button_width(lv_obj_t * obj, uint32_t btn_id, uint32_t width) +void lv_buttonmatrix_set_one_checked(lv_obj_t * obj, bool en) +const char ** lv_buttonmatrix_get_map(const lv_obj_t * obj) +uint32_t lv_buttonmatrix_get_selected_button(const lv_obj_t * obj) +const char * lv_buttonmatrix_get_button_text(const lv_obj_t * obj, uint32_t btn_id) +bool lv_buttonmatrix_has_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl) +bool lv_buttonmatrix_get_one_checked(const lv_obj_t * obj) -// ../../lvgl/src/widgets/lv_canvas.h +// ../../lvgl/src/widgets/calendar/lv_calendar.h +lv_obj_t * lv_calendar_create(lv_obj_t * parent) +void lv_calendar_set_today_date(lv_obj_t * obj, uint32_t year, uint32_t month, uint32_t day) +void lv_calendar_set_showed_date(lv_obj_t * obj, uint32_t year, uint32_t month) +void lv_calendar_set_highlighted_dates(lv_obj_t * obj, lv_calendar_date_t highlighted[], size_t date_num) +void lv_calendar_set_day_names(lv_obj_t * obj, const char ** day_names) +lv_obj_t * lv_calendar_get_btnmatrix(const lv_obj_t * obj) +const lv_calendar_date_t * lv_calendar_get_today_date(const lv_obj_t * calendar) +const lv_calendar_date_t * lv_calendar_get_showed_date(const lv_obj_t * calendar) +lv_calendar_date_t * lv_calendar_get_highlighted_dates(const lv_obj_t * calendar) +size_t lv_calendar_get_highlighted_dates_num(const lv_obj_t * calendar) +lv_result_t lv_calendar_get_pressed_date(const lv_obj_t * calendar, lv_calendar_date_t * date) + +// ../../lvgl/src/widgets/calendar/lv_calendar_header_arrow.h +lv_obj_t * lv_calendar_header_arrow_create(lv_obj_t * parent) + +// ../../lvgl/src/widgets/calendar/lv_calendar_header_dropdown.h +lv_obj_t * lv_calendar_header_dropdown_create(lv_obj_t * parent) +void lv_calendar_header_dropdown_set_year_list(lv_obj_t * parent, const char * years_list) + +// ../../lvgl/src/widgets/canvas/lv_canvas.h lv_obj_t * lv_canvas_create(lv_obj_t * parent) -void lv_canvas_set_buffer(lv_obj_t * canvas, void * buf, lv_coord_t w, lv_coord_t h, lv_img_cf_t cf) -void lv_canvas_set_px_color(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c) -static inline void lv_canvas_set_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c) -void lv_canvas_set_px_opa(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_opa_t opa) -void lv_canvas_set_palette(lv_obj_t * canvas, uint8_t id, lv_color_t c) -lv_color_t lv_canvas_get_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y) -lv_img_dsc_t * lv_canvas_get_img(lv_obj_t * canvas) -void lv_canvas_copy_buf(lv_obj_t * canvas, const void * to_copy, lv_coord_t x, lv_coord_t y, lv_coord_t w, lv_coord_t h) -void lv_canvas_transform(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, uint16_t zoom, lv_coord_t offset_x, lv_coord_t offset_y, int32_t pivot_x, int32_t pivot_y, bool antialias) -void lv_canvas_blur_hor(lv_obj_t * canvas, const lv_area_t * area, uint16_t r) -void lv_canvas_blur_ver(lv_obj_t * canvas, const lv_area_t * area, uint16_t r) -void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color, lv_opa_t opa) -void lv_canvas_draw_rect(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t w, lv_coord_t h, const lv_draw_rect_dsc_t * draw_dsc) -void lv_canvas_draw_text(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t max_w, lv_draw_label_dsc_t * draw_dsc, const char * txt) -void lv_canvas_draw_img(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, const void * src, const lv_draw_img_dsc_t * draw_dsc) -void lv_canvas_draw_line(lv_obj_t * canvas, const lv_point_t points[], uint32_t point_cnt, const lv_draw_line_dsc_t * draw_dsc) -void lv_canvas_draw_polygon(lv_obj_t * canvas, const lv_point_t points[], uint32_t point_cnt, const lv_draw_rect_dsc_t * draw_dsc) -void lv_canvas_draw_arc(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t r, int32_t start_angle, int32_t end_angle, const lv_draw_arc_dsc_t * draw_dsc) +void lv_canvas_set_buffer(lv_obj_t * obj, void * buf, int32_t w, int32_t h, lv_color_format_t cf) +void lv_canvas_set_draw_buf(lv_obj_t * obj, lv_draw_buf_t * draw_buf) +void lv_canvas_set_px(lv_obj_t * obj, int32_t x, int32_t y, lv_color_t color, lv_opa_t opa) +void lv_canvas_set_palette(lv_obj_t * canvas, uint8_t id, lv_color32_t c) +lv_draw_buf_t * lv_canvas_get_draw_buf(lv_obj_t * obj) +lv_color32_t lv_canvas_get_px(lv_obj_t * obj, int32_t x, int32_t y) +lv_image_dsc_t * lv_canvas_get_image(lv_obj_t * canvas) +const void * lv_canvas_get_buf(lv_obj_t * canvas) +void lv_canvas_copy_buf(lv_obj_t * obj, const lv_area_t * canvas_area, lv_draw_buf_t * dest_buf, const lv_area_t * dest_area) +void lv_canvas_fill_bg(lv_obj_t * obj, lv_color_t color, lv_opa_t opa) +void lv_canvas_init_layer(lv_obj_t * canvas, lv_layer_t * layer) +void lv_canvas_finish_layer(lv_obj_t * canvas, lv_layer_t * layer) +static inline uint32_t lv_canvas_buf_size(int32_t w, int32_t h, uint8_t bpp, uint8_t stride) -// ../../lvgl/src/widgets/lv_checkbox.h +// ../../lvgl/src/widgets/chart/lv_chart.h +lv_obj_t * lv_chart_create(lv_obj_t * parent) +void lv_chart_set_type(lv_obj_t * obj, lv_chart_type_t type) +void lv_chart_set_point_count(lv_obj_t * obj, uint32_t cnt) +void lv_chart_set_range(lv_obj_t * obj, lv_chart_axis_t axis, int32_t min, int32_t max) +void lv_chart_set_update_mode(lv_obj_t * obj, lv_chart_update_mode_t update_mode) +void lv_chart_set_div_line_count(lv_obj_t * obj, uint8_t hdiv, uint8_t vdiv) +lv_chart_type_t lv_chart_get_type(const lv_obj_t * obj) +uint32_t lv_chart_get_point_count(const lv_obj_t * obj) +uint32_t lv_chart_get_x_start_point(const lv_obj_t * obj, lv_chart_series_t * ser) +void lv_chart_get_point_pos_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t id, lv_point_t * p_out) +void lv_chart_refresh(lv_obj_t * obj) +lv_chart_series_t * lv_chart_add_series(lv_obj_t * obj, lv_color_t color, lv_chart_axis_t axis) +void lv_chart_remove_series(lv_obj_t * obj, lv_chart_series_t * series) +void lv_chart_hide_series(lv_obj_t * chart, lv_chart_series_t * series, bool hide) +void lv_chart_set_series_color(lv_obj_t * chart, lv_chart_series_t * series, lv_color_t color) +void lv_chart_set_x_start_point(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t id) +lv_chart_series_t * lv_chart_get_series_next(const lv_obj_t * chart, const lv_chart_series_t * ser) +lv_chart_cursor_t * lv_chart_add_cursor(lv_obj_t * obj, lv_color_t color, lv_dir_t dir) +void lv_chart_set_cursor_pos(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_point_t * pos) +void lv_chart_set_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_chart_series_t * ser, uint32_t point_id) +lv_point_t lv_chart_get_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * cursor) +void lv_chart_set_all_value(lv_obj_t * obj, lv_chart_series_t * ser, int32_t value) +void lv_chart_set_next_value(lv_obj_t * obj, lv_chart_series_t * ser, int32_t value) +void lv_chart_set_next_value2(lv_obj_t * obj, lv_chart_series_t * ser, int32_t x_value, int32_t y_value) +void lv_chart_set_value_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t id, int32_t value) +void lv_chart_set_value_by_id2(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t id, int32_t x_value, int32_t y_value) +void lv_chart_set_ext_y_array(lv_obj_t * obj, lv_chart_series_t * ser, int32_t array[]) +void lv_chart_set_ext_x_array(lv_obj_t * obj, lv_chart_series_t * ser, int32_t array[]) +int32_t * lv_chart_get_y_array(const lv_obj_t * obj, lv_chart_series_t * ser) +int32_t * lv_chart_get_x_array(const lv_obj_t * obj, lv_chart_series_t * ser) +uint32_t lv_chart_get_pressed_point(const lv_obj_t * obj) +int32_t lv_chart_get_first_point_center_offset(lv_obj_t * obj) + +// ../../lvgl/src/widgets/checkbox/lv_checkbox.h lv_obj_t * lv_checkbox_create(lv_obj_t * parent) void lv_checkbox_set_text(lv_obj_t * obj, const char * txt) void lv_checkbox_set_text_static(lv_obj_t * obj, const char * txt) const char * lv_checkbox_get_text(const lv_obj_t * obj) -// ../../lvgl/src/widgets/lv_dropdown.h +// ../../lvgl/src/widgets/dropdown/lv_dropdown.h lv_obj_t * lv_dropdown_create(lv_obj_t * parent) void lv_dropdown_set_text(lv_obj_t * obj, const char * txt) void lv_dropdown_set_options(lv_obj_t * obj, const char * options) void lv_dropdown_set_options_static(lv_obj_t * obj, const char * options) void lv_dropdown_add_option(lv_obj_t * obj, const char * option, uint32_t pos) void lv_dropdown_clear_options(lv_obj_t * obj) -void lv_dropdown_set_selected(lv_obj_t * obj, uint16_t sel_opt) +void lv_dropdown_set_selected(lv_obj_t * obj, uint32_t sel_opt) void lv_dropdown_set_dir(lv_obj_t * obj, lv_dir_t dir) void lv_dropdown_set_symbol(lv_obj_t * obj, const void * symbol) void lv_dropdown_set_selected_highlight(lv_obj_t * obj, bool en) lv_obj_t * lv_dropdown_get_list(lv_obj_t * obj) const char * lv_dropdown_get_text(lv_obj_t * obj) const char * lv_dropdown_get_options(const lv_obj_t * obj) -uint16_t lv_dropdown_get_selected(const lv_obj_t * obj) -uint16_t lv_dropdown_get_option_cnt(const lv_obj_t * obj) +uint32_t lv_dropdown_get_selected(const lv_obj_t * obj) +uint32_t lv_dropdown_get_option_count(const lv_obj_t * obj) void lv_dropdown_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_size) int32_t lv_dropdown_get_option_index(lv_obj_t * obj, const char * option) const char * lv_dropdown_get_symbol(lv_obj_t * obj) @@ -1083,64 +1159,162 @@ void lv_dropdown_open(lv_obj_t * dropdown_obj) void lv_dropdown_close(lv_obj_t * obj) bool lv_dropdown_is_open(lv_obj_t * obj) -// ../../lvgl/src/widgets/lv_img.h -lv_obj_t * lv_img_create(lv_obj_t * parent) -void lv_img_set_src(lv_obj_t * obj, const void * src) -void lv_img_set_offset_x(lv_obj_t * obj, lv_coord_t x) -void lv_img_set_offset_y(lv_obj_t * obj, lv_coord_t y) -void lv_img_set_angle(lv_obj_t * obj, int16_t angle) -void lv_img_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) -void lv_img_set_zoom(lv_obj_t * obj, uint16_t zoom) -void lv_img_set_antialias(lv_obj_t * obj, bool antialias) -void lv_img_set_size_mode(lv_obj_t * obj, lv_img_size_mode_t mode) -const void * lv_img_get_src(lv_obj_t * obj) -lv_coord_t lv_img_get_offset_x(lv_obj_t * obj) -lv_coord_t lv_img_get_offset_y(lv_obj_t * obj) -uint16_t lv_img_get_angle(lv_obj_t * obj) -void lv_img_get_pivot(lv_obj_t * obj, lv_point_t * pivot) -uint16_t lv_img_get_zoom(lv_obj_t * obj) -bool lv_img_get_antialias(lv_obj_t * obj) -lv_img_size_mode_t lv_img_get_size_mode(lv_obj_t * obj) +// ../../lvgl/src/widgets/image/lv_image.h +lv_obj_t * lv_image_create(lv_obj_t * parent) +void lv_image_set_src(lv_obj_t * obj, const void * src) +void lv_image_set_offset_x(lv_obj_t * obj, int32_t x) +void lv_image_set_offset_y(lv_obj_t * obj, int32_t y) +void lv_image_set_rotation(lv_obj_t * obj, int32_t angle) +void lv_image_set_pivot(lv_obj_t * obj, int32_t x, int32_t y) +void lv_image_set_scale(lv_obj_t * obj, uint32_t zoom) +void lv_image_set_scale_x(lv_obj_t * obj, uint32_t zoom) +void lv_image_set_scale_y(lv_obj_t * obj, uint32_t zoom) +void lv_image_set_blend_mode(lv_obj_t * obj, lv_blend_mode_t blend_mode) +void lv_image_set_antialias(lv_obj_t * obj, bool antialias) +void lv_image_set_inner_align(lv_obj_t * obj, lv_image_align_t align) +const void * lv_image_get_src(lv_obj_t * obj) +int32_t lv_image_get_offset_x(lv_obj_t * obj) +int32_t lv_image_get_offset_y(lv_obj_t * obj) +int32_t lv_image_get_rotation(lv_obj_t * obj) +void lv_image_get_pivot(lv_obj_t * obj, lv_point_t * pivot) +int32_t lv_image_get_scale(lv_obj_t * obj) +int32_t lv_image_get_scale_x(lv_obj_t * obj) +int32_t lv_image_get_scale_y(lv_obj_t * obj) +lv_blend_mode_t lv_image_get_blend_mode(lv_obj_t * obj) +bool lv_image_get_antialias(lv_obj_t * obj) +lv_image_align_t lv_image_get_inner_align(lv_obj_t * obj) -// ../../lvgl/src/widgets/lv_label.h +// ../../lvgl/src/widgets/imagebutton/lv_imagebutton.h +lv_obj_t * lv_imagebutton_create(lv_obj_t * parent) +void lv_imagebutton_set_src(lv_obj_t * imagebutton, lv_imagebutton_state_t state, const void * src_left, const void * src_mid, const void * src_right) +void lv_imagebutton_set_state(lv_obj_t * imagebutton, lv_imagebutton_state_t state) + +// ../../lvgl/src/widgets/keyboard/lv_keyboard.h +lv_obj_t * lv_keyboard_create(lv_obj_t * parent) +void lv_keyboard_set_textarea(lv_obj_t * kb, lv_obj_t * ta) +void lv_keyboard_set_mode(lv_obj_t * kb, lv_keyboard_mode_t mode) +void lv_keyboard_set_popovers(lv_obj_t * kb, bool en) +void lv_keyboard_set_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const char * map[], const lv_buttonmatrix_ctrl_t ctrl_map[]) +lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * kb) +lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * kb) +bool lv_buttonmatrix_get_popovers(const lv_obj_t * obj) +static inline const char ** lv_keyboard_get_map_array(const lv_obj_t * kb) +static inline uint32_t lv_keyboard_get_selected_button(const lv_obj_t * obj) +static inline const char * lv_keyboard_get_button_text(const lv_obj_t * obj, uint32_t btn_id) + +// ../../lvgl/src/widgets/label/lv_label.h lv_obj_t * lv_label_create(lv_obj_t * parent) void lv_label_set_text(lv_obj_t * obj, const char * text) void lv_label_set_text_fmt(lv_obj_t * obj, const char * fmt, ...) LV_FORMAT_ATTRIBUTE(2, 3) void lv_label_set_text_static(lv_obj_t * obj, const char * text) void lv_label_set_long_mode(lv_obj_t * obj, lv_label_long_mode_t long_mode) -void lv_label_set_recolor(lv_obj_t * obj, bool en) -void lv_label_set_text_sel_start(lv_obj_t * obj, uint32_t index) -void lv_label_set_text_sel_end(lv_obj_t * obj, uint32_t index) +void lv_label_set_text_selection_start(lv_obj_t * obj, uint32_t index) +void lv_label_set_text_selection_end(lv_obj_t * obj, uint32_t index) char * lv_label_get_text(const lv_obj_t * obj) lv_label_long_mode_t lv_label_get_long_mode(const lv_obj_t * obj) -bool lv_label_get_recolor(const lv_obj_t * obj) void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t * pos) -uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in) +uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in, bool bidi) bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos) uint32_t lv_label_get_text_selection_start(const lv_obj_t * obj) uint32_t lv_label_get_text_selection_end(const lv_obj_t * obj) void lv_label_ins_text(lv_obj_t * obj, uint32_t pos, const char * txt) void lv_label_cut_text(lv_obj_t * obj, uint32_t pos, uint32_t cnt) -// ../../lvgl/src/widgets/lv_line.h +// ../../lvgl/src/widgets/led/lv_led.h +lv_obj_t * lv_led_create(lv_obj_t * parent) +void lv_led_set_color(lv_obj_t * led, lv_color_t color) +void lv_led_set_brightness(lv_obj_t * led, uint8_t bright) +void lv_led_on(lv_obj_t * led) +void lv_led_off(lv_obj_t * led) +void lv_led_toggle(lv_obj_t * led) +uint8_t lv_led_get_brightness(const lv_obj_t * obj) + +// ../../lvgl/src/widgets/line/lv_line.h lv_obj_t * lv_line_create(lv_obj_t * parent) -void lv_line_set_points(lv_obj_t * obj, const lv_point_t points[], uint16_t point_num) +void lv_line_set_points(lv_obj_t * obj, const lv_point_precise_t points[], uint32_t point_num) void lv_line_set_y_invert(lv_obj_t * obj, bool en) bool lv_line_get_y_invert(const lv_obj_t * obj) -// ../../lvgl/src/widgets/lv_objx_templ.h +// ../../lvgl/src/widgets/list/lv_list.h +lv_obj_t * lv_list_create(lv_obj_t * parent) +lv_obj_t * lv_list_add_text(lv_obj_t * list, const char * txt) +lv_obj_t * lv_list_add_button(lv_obj_t * list, const void * icon, const char * txt) +const char * lv_list_get_button_text(lv_obj_t * list, lv_obj_t * btn) +void lv_list_set_button_text(lv_obj_t * list, lv_obj_t * btn, const char * txt) -// ../../lvgl/src/widgets/lv_roller.h +// ../../lvgl/src/widgets/menu/lv_menu.h +lv_obj_t * lv_menu_create(lv_obj_t * parent) +lv_obj_t * lv_menu_page_create(lv_obj_t * parent, char const * const title) +lv_obj_t * lv_menu_cont_create(lv_obj_t * parent) +lv_obj_t * lv_menu_section_create(lv_obj_t * parent) +lv_obj_t * lv_menu_separator_create(lv_obj_t * parent) +void lv_menu_set_page(lv_obj_t * obj, lv_obj_t * page) +void lv_menu_set_page_title(lv_obj_t * page, char const * const title) +void lv_menu_set_page_title_static(lv_obj_t * page, char const * const title) +void lv_menu_set_sidebar_page(lv_obj_t * obj, lv_obj_t * page) +void lv_menu_set_mode_header(lv_obj_t * obj, lv_menu_mode_header_t mode) +void lv_menu_set_mode_root_back_button(lv_obj_t * obj, lv_menu_mode_root_back_button_t mode) +void lv_menu_set_load_page_event(lv_obj_t * menu, lv_obj_t * obj, lv_obj_t * page) +lv_obj_t * lv_menu_get_cur_main_page(lv_obj_t * obj) +lv_obj_t * lv_menu_get_cur_sidebar_page(lv_obj_t * obj) +lv_obj_t * lv_menu_get_main_header(lv_obj_t * obj) +lv_obj_t * lv_menu_get_main_header_back_button(lv_obj_t * obj) +lv_obj_t * lv_menu_get_sidebar_header(lv_obj_t * obj) +lv_obj_t * lv_menu_get_sidebar_header_back_button(lv_obj_t * obj) +bool lv_menu_back_button_is_root(lv_obj_t * menu, lv_obj_t * obj) +void lv_menu_clear_history(lv_obj_t * obj) + +// ../../lvgl/src/widgets/msgbox/lv_msgbox.h +lv_obj_t * lv_msgbox_create(lv_obj_t * parent) +lv_obj_t * lv_msgbox_add_title(lv_obj_t * obj, const char * title) +lv_obj_t * lv_msgbox_add_header_button(lv_obj_t * obj, const void * icon) +lv_obj_t * lv_msgbox_add_text(lv_obj_t * obj, const char * text) +lv_obj_t * lv_msgbox_add_footer_button(lv_obj_t * obj, const char * text) +lv_obj_t * lv_msgbox_add_close_button(lv_obj_t * obj) +lv_obj_t * lv_msgbox_get_header(lv_obj_t * obj) +lv_obj_t * lv_msgbox_get_footer(lv_obj_t * obj) +lv_obj_t * lv_msgbox_get_content(lv_obj_t * obj) +lv_obj_t * lv_msgbox_get_title(lv_obj_t * obj) +void lv_msgbox_close(lv_obj_t * mbox) +void lv_msgbox_close_async(lv_obj_t * mbox) + +// ../../lvgl/src/widgets/objx_templ/lv_objx_templ.h + +// ../../lvgl/src/widgets/roller/lv_roller.h lv_obj_t * lv_roller_create(lv_obj_t * parent) void lv_roller_set_options(lv_obj_t * obj, const char * options, lv_roller_mode_t mode) -void lv_roller_set_selected(lv_obj_t * obj, uint16_t sel_opt, lv_anim_enable_t anim) -void lv_roller_set_visible_row_count(lv_obj_t * obj, uint8_t row_cnt) -uint16_t lv_roller_get_selected(const lv_obj_t * obj) +void lv_roller_set_selected(lv_obj_t * obj, uint32_t sel_opt, lv_anim_enable_t anim) +void lv_roller_set_visible_row_count(lv_obj_t * obj, uint32_t row_cnt) +uint32_t lv_roller_get_selected(const lv_obj_t * obj) void lv_roller_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_size) const char * lv_roller_get_options(const lv_obj_t * obj) -uint16_t lv_roller_get_option_cnt(const lv_obj_t * obj) +uint32_t lv_roller_get_option_count(const lv_obj_t * obj) -// ../../lvgl/src/widgets/lv_slider.h +// ../../lvgl/src/widgets/scale/lv_scale.h +lv_obj_t * lv_scale_create(lv_obj_t * parent) +void lv_scale_set_mode(lv_obj_t * obj, lv_scale_mode_t mode) +void lv_scale_set_total_tick_count(lv_obj_t * obj, uint32_t total_tick_count) +void lv_scale_set_major_tick_every(lv_obj_t * obj, uint32_t major_tick_every) +void lv_scale_set_label_show(lv_obj_t * obj, bool show_label) +void lv_scale_set_range(lv_obj_t * obj, int32_t min, int32_t max) +void lv_scale_set_angle_range(lv_obj_t * obj, uint32_t angle_range) +void lv_scale_set_rotation(lv_obj_t * obj, int32_t rotation) +void lv_scale_set_line_needle_value(lv_obj_t * obj, lv_obj_t * needle_line, int32_t needle_length, int32_t value) +void lv_scale_set_image_needle_value(lv_obj_t * obj, lv_obj_t * needle_img, int32_t value) +void lv_scale_set_text_src(lv_obj_t * obj, const char * txt_src[]) +void lv_scale_set_post_draw(lv_obj_t * obj, bool en) +lv_scale_section_t * lv_scale_add_section(lv_obj_t * obj) +void lv_scale_section_set_range(lv_scale_section_t * section, int32_t minor_range, int32_t major_range) +void lv_scale_section_set_style(lv_scale_section_t * section, uint32_t part, lv_style_t * section_part_style) +lv_scale_mode_t lv_scale_get_mode(lv_obj_t * obj) +int32_t lv_scale_get_total_tick_count(lv_obj_t * obj) +int32_t lv_scale_get_major_tick_every(lv_obj_t * obj) +bool lv_scale_get_label_show(lv_obj_t * obj) +uint32_t lv_scale_get_angle_range(lv_obj_t * obj) +int32_t lv_scale_get_range_min_value(lv_obj_t * obj) +int32_t lv_scale_get_range_max_value(lv_obj_t * obj) + +// ../../lvgl/src/widgets/slider/lv_slider.h lv_obj_t * lv_slider_create(lv_obj_t * parent) static inline void lv_slider_set_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim) static inline void lv_slider_set_left_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim) @@ -1152,34 +1326,93 @@ static inline int32_t lv_slider_get_min_value(const lv_obj_t * obj) static inline int32_t lv_slider_get_max_value(const lv_obj_t * obj) bool lv_slider_is_dragged(const lv_obj_t * obj) static inline lv_slider_mode_t lv_slider_get_mode(lv_obj_t * slider) +static inline bool lv_slider_is_symmetrical(lv_obj_t * obj) -// ../../lvgl/src/widgets/lv_switch.h +// ../../lvgl/src/widgets/span/lv_span.h +void lv_span_stack_init(void) +void lv_span_stack_deinit(void) +lv_obj_t * lv_spangroup_create(lv_obj_t * parent) +lv_span_t * lv_spangroup_new_span(lv_obj_t * obj) +void lv_spangroup_delete_span(lv_obj_t * obj, lv_span_t * span) +void lv_span_set_text(lv_span_t * span, const char * text) +void lv_span_set_text_static(lv_span_t * span, const char * text) +void lv_spangroup_set_align(lv_obj_t * obj, lv_text_align_t align) +void lv_spangroup_set_overflow(lv_obj_t * obj, lv_span_overflow_t overflow) +void lv_spangroup_set_indent(lv_obj_t * obj, int32_t indent) +void lv_spangroup_set_mode(lv_obj_t * obj, lv_span_mode_t mode) +void lv_spangroup_set_max_lines(lv_obj_t * obj, int32_t lines) +lv_span_t * lv_spangroup_get_child(const lv_obj_t * obj, int32_t id) +uint32_t lv_spangroup_get_span_count(const lv_obj_t * obj) +lv_text_align_t lv_spangroup_get_align(lv_obj_t * obj) +lv_span_overflow_t lv_spangroup_get_overflow(lv_obj_t * obj) +int32_t lv_spangroup_get_indent(lv_obj_t * obj) +lv_span_mode_t lv_spangroup_get_mode(lv_obj_t * obj) +int32_t lv_spangroup_get_max_lines(lv_obj_t * obj) +int32_t lv_spangroup_get_max_line_height(lv_obj_t * obj) +uint32_t lv_spangroup_get_expand_width(lv_obj_t * obj, uint32_t max_width) +int32_t lv_spangroup_get_expand_height(lv_obj_t * obj, int32_t width) +void lv_spangroup_refr_mode(lv_obj_t * obj) + +// ../../lvgl/src/widgets/spinbox/lv_spinbox.h +lv_obj_t * lv_spinbox_create(lv_obj_t * parent) +void lv_spinbox_set_value(lv_obj_t * obj, int32_t v) +void lv_spinbox_set_rollover(lv_obj_t * obj, bool rollover) +void lv_spinbox_set_digit_format(lv_obj_t * obj, uint32_t digit_count, uint32_t sep_pos) +void lv_spinbox_set_step(lv_obj_t * obj, uint32_t step) +void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max) +void lv_spinbox_set_cursor_pos(lv_obj_t * obj, uint32_t pos) +void lv_spinbox_set_digit_step_direction(lv_obj_t * obj, lv_dir_t direction) +bool lv_spinbox_get_rollover(lv_obj_t * obj) +int32_t lv_spinbox_get_value(lv_obj_t * obj) +int32_t lv_spinbox_get_step(lv_obj_t * obj) +void lv_spinbox_step_next(lv_obj_t * obj) +void lv_spinbox_step_prev(lv_obj_t * obj) +void lv_spinbox_increment(lv_obj_t * obj) +void lv_spinbox_decrement(lv_obj_t * obj) + +// ../../lvgl/src/widgets/spinner/lv_spinner.h +lv_obj_t * lv_spinner_create(lv_obj_t * parent) +void lv_spinner_set_anim_params(lv_obj_t * obj, uint32_t t, uint32_t angle) + +// ../../lvgl/src/widgets/switch/lv_switch.h lv_obj_t * lv_switch_create(lv_obj_t * parent) -// ../../lvgl/src/widgets/lv_table.h +// ../../lvgl/src/widgets/table/lv_table.h lv_obj_t * lv_table_create(lv_obj_t * parent) -void lv_table_set_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col, const char * txt) -void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, const char * fmt, ...) -void lv_table_set_row_cnt(lv_obj_t * obj, uint16_t row_cnt) -void lv_table_set_col_cnt(lv_obj_t * obj, uint16_t col_cnt) -void lv_table_set_col_width(lv_obj_t * obj, uint16_t col_id, lv_coord_t w) -void lv_table_add_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl) -void lv_table_clear_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl) +void lv_table_set_cell_value(lv_obj_t * obj, uint32_t row, uint32_t col, const char * txt) +void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint32_t row, uint32_t col, const char * fmt, ...) LV_FORMAT_ATTRIBUTE(4, 5) +void lv_table_set_row_count(lv_obj_t * obj, uint32_t row_cnt) +void lv_table_set_column_count(lv_obj_t * obj, uint32_t col_cnt) +void lv_table_set_column_width(lv_obj_t * obj, uint32_t col_id, int32_t w) +void lv_table_add_cell_ctrl(lv_obj_t * obj, uint32_t row, uint32_t col, lv_table_cell_ctrl_t ctrl) +void lv_table_clear_cell_ctrl(lv_obj_t * obj, uint32_t row, uint32_t col, lv_table_cell_ctrl_t ctrl) void lv_table_set_cell_user_data(lv_obj_t * obj, uint16_t row, uint16_t col, void * user_data) -const char * lv_table_get_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col) -uint16_t lv_table_get_row_cnt(lv_obj_t * obj) -uint16_t lv_table_get_col_cnt(lv_obj_t * obj) -lv_coord_t lv_table_get_col_width(lv_obj_t * obj, uint16_t col) -bool lv_table_has_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl) -void lv_table_get_selected_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col) +const char * lv_table_get_cell_value(lv_obj_t * obj, uint32_t row, uint32_t col) +uint32_t lv_table_get_row_count(lv_obj_t * obj) +uint32_t lv_table_get_column_count(lv_obj_t * obj) +int32_t lv_table_get_column_width(lv_obj_t * obj, uint32_t col) +bool lv_table_has_cell_ctrl(lv_obj_t * obj, uint32_t row, uint32_t col, lv_table_cell_ctrl_t ctrl) +void lv_table_get_selected_cell(lv_obj_t * obj, uint32_t * row, uint32_t * col) void * lv_table_get_cell_user_data(lv_obj_t * obj, uint16_t row, uint16_t col) -// ../../lvgl/src/widgets/lv_textarea.h +// ../../lvgl/src/widgets/tabview/lv_tabview.h +lv_obj_t * lv_tabview_create(lv_obj_t * parent) +lv_obj_t * lv_tabview_add_tab(lv_obj_t * obj, const char * name) +void lv_tabview_rename_tab(lv_obj_t * obj, uint32_t idx, const char * new_name) +void lv_tabview_set_active(lv_obj_t * obj, uint32_t idx, lv_anim_enable_t anim_en) +void lv_tabview_set_tab_bar_position(lv_obj_t * obj, lv_dir_t dir) +void lv_tabview_set_tab_bar_size(lv_obj_t * obj, int32_t size) +uint32_t lv_tabview_get_tab_count(lv_obj_t * obj) +uint32_t lv_tabview_get_tab_active(lv_obj_t * obj) +lv_obj_t * lv_tabview_get_content(lv_obj_t * obj) +lv_obj_t * lv_tabview_get_tab_bar(lv_obj_t * obj) + +// ../../lvgl/src/widgets/textarea/lv_textarea.h lv_obj_t * lv_textarea_create(lv_obj_t * parent) void lv_textarea_add_char(lv_obj_t * obj, uint32_t c) void lv_textarea_add_text(lv_obj_t * obj, const char * txt) -void lv_textarea_del_char(lv_obj_t * obj) -void lv_textarea_del_char_forward(lv_obj_t * obj) +void lv_textarea_delete_char(lv_obj_t * obj) +void lv_textarea_delete_char_forward(lv_obj_t * obj) void lv_textarea_set_text(lv_obj_t * obj, const char * txt) void lv_textarea_set_placeholder_text(lv_obj_t * obj, const char * txt) void lv_textarea_set_cursor_pos(lv_obj_t * obj, int32_t pos) @@ -1191,7 +1424,7 @@ void lv_textarea_set_accepted_chars(lv_obj_t * obj, const char * list) void lv_textarea_set_max_length(lv_obj_t * obj, uint32_t num) void lv_textarea_set_insert_replace(lv_obj_t * obj, const char * txt) void lv_textarea_set_text_selection(lv_obj_t * obj, bool en) -void lv_textarea_set_password_show_time(lv_obj_t * obj, uint16_t time) +void lv_textarea_set_password_show_time(lv_obj_t * obj, uint32_t time) void lv_textarea_set_align(lv_obj_t * obj, lv_text_align_t align) const char * lv_textarea_get_text(const lv_obj_t * obj) const char * lv_textarea_get_placeholder_text(lv_obj_t * obj) @@ -1205,14 +1438,24 @@ const char * lv_textarea_get_accepted_chars(lv_obj_t * obj) uint32_t lv_textarea_get_max_length(lv_obj_t * obj) bool lv_textarea_text_is_selected(const lv_obj_t * obj) bool lv_textarea_get_text_selection(lv_obj_t * obj) -uint16_t lv_textarea_get_password_show_time(lv_obj_t * obj) +uint32_t lv_textarea_get_password_show_time(lv_obj_t * obj) +uint32_t lv_textarea_get_current_char(lv_obj_t * obj) void lv_textarea_clear_selection(lv_obj_t * obj) void lv_textarea_cursor_right(lv_obj_t * obj) void lv_textarea_cursor_left(lv_obj_t * obj) void lv_textarea_cursor_down(lv_obj_t * obj) void lv_textarea_cursor_up(lv_obj_t * obj) +// ../../lvgl/src/widgets/tileview/lv_tileview.h +lv_obj_t * lv_tileview_create(lv_obj_t * parent) +lv_obj_t * lv_tileview_add_tile(lv_obj_t * tv, uint8_t col_id, uint8_t row_id, lv_dir_t dir) +void lv_tileview_set_tile(lv_obj_t * tv, lv_obj_t * tile_obj, lv_anim_enable_t anim_en) +void lv_tileview_set_tile_by_index(lv_obj_t * tv, uint32_t col_id, uint32_t row_id, lv_anim_enable_t anim_en) +lv_obj_t * lv_tileview_get_tile_active(lv_obj_t * obj) + +// ../../lvgl/src/widgets/win/lv_win.h + // ../../LVGL_assets/src/lv_theme_haspmota.h -lv_theme_t * lv_theme_haspmota_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font) +lv_theme_t * lv_theme_haspmota_init(lv_display_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font) bool lv_theme_haspmota_is_inited(void) diff --git a/lib/libesp32_lvgl/lv_binding_berry/src/be_lvgl_ctypes_definitions.c b/lib/libesp32_lvgl/lv_binding_berry/src/be_lvgl_ctypes_definitions.c index 7df88b6cd..d57902231 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/src/be_lvgl_ctypes_definitions.c +++ b/lib/libesp32_lvgl/lv_binding_berry/src/be_lvgl_ctypes_definitions.c @@ -12,443 +12,240 @@ static const char * be_ctypes_instance_mappings[]; /* forward definition */ -const be_ctypes_structure_t be_lv_coord = { - 2, /* size in bytes */ - 1, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[1]) { - { "v", 0, 0, 0, ctypes_i16, 0 }, -}}; - const be_ctypes_structure_t be_lv_point = { - 4, /* size in bytes */ + 8, /* size in bytes */ 2, /* number of elements */ be_ctypes_instance_mappings, (const be_ctypes_structure_item_t[2]) { - { "x", 0, 0, 0, ctypes_i16, 0 }, - { "y", 2, 0, 0, ctypes_i16, 0 }, + { "x", 0, 0, 0, ctypes_i32, 0 }, + { "y", 4, 0, 0, ctypes_i32, 0 }, +}}; + +const be_ctypes_structure_t be_lv_point_precise = { + 8, /* size in bytes */ + 2, /* number of elements */ + be_ctypes_instance_mappings, + (const be_ctypes_structure_item_t[2]) { + { "x", 0, 0, 0, ctypes_i32, 0 }, + { "y", 4, 0, 0, ctypes_i32, 0 }, }}; const be_ctypes_structure_t be_lv_area = { - 8, /* size in bytes */ + 16, /* size in bytes */ 4, /* number of elements */ be_ctypes_instance_mappings, (const be_ctypes_structure_item_t[4]) { - { "x1", 0, 0, 0, ctypes_i16, 0 }, - { "x2", 4, 0, 0, ctypes_i16, 0 }, - { "y1", 2, 0, 0, ctypes_i16, 0 }, - { "y2", 6, 0, 0, ctypes_i16, 0 }, + { "x1", 0, 0, 0, ctypes_i32, 0 }, + { "x2", 8, 0, 0, ctypes_i32, 0 }, + { "y1", 4, 0, 0, ctypes_i32, 0 }, + { "y2", 12, 0, 0, ctypes_i32, 0 }, }}; const be_ctypes_structure_t be_lv_gradient_stop = { - 4, /* size in bytes */ - 2, /* number of elements */ + 8, /* size in bytes */ + 3, /* number of elements */ be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[2]) { - { "color", 0, 0, 0, ctypes_u16, 1 }, - { "frac", 2, 0, 0, ctypes_u8, 0 }, + (const be_ctypes_structure_item_t[3]) { + { "color", 0, 0, 0, ctypes_u24, 1 }, + { "frac", 4, 0, 0, ctypes_u8, 0 }, + { "opa", 3, 0, 0, ctypes_u8, 0 }, }}; const be_ctypes_structure_t be_lv_grad_dsc = { - 12, /* size in bytes */ - 7, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[7]) { - { "dir", 8, 0, 3, ctypes_bf, 0 }, - { "dither", 8, 3, 3, ctypes_bf, 0 }, - { "stops_0_color", 0, 0, 0, ctypes_u16, 1 }, - { "stops_0_frac", 2, 0, 0, ctypes_u8, 0 }, - { "stops_1_color", 4, 0, 0, ctypes_u16, 1 }, - { "stops_1_frac", 6, 0, 0, ctypes_u8, 0 }, - { "stops_count", 7, 0, 0, ctypes_u8, 0 }, -}}; - -const be_ctypes_structure_t be_lv_draw_rect_dsc = { - 60, /* size in bytes */ - 32, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[32]) { - { "bg_color", 4, 0, 0, ctypes_u16, 1 }, - { "bg_grad_dir", 16, 0, 3, ctypes_bf, 0 }, - { "bg_grad_dither", 16, 3, 3, ctypes_bf, 0 }, - { "bg_grad_stops_0_color", 8, 0, 0, ctypes_u16, 1 }, - { "bg_grad_stops_0_frac", 10, 0, 0, ctypes_u8, 0 }, - { "bg_grad_stops_1_color", 12, 0, 0, ctypes_u16, 1 }, - { "bg_grad_stops_1_frac", 14, 0, 0, ctypes_u8, 0 }, - { "bg_grad_stops_count", 15, 0, 0, ctypes_u8, 0 }, - { "bg_img_opa", 30, 0, 0, ctypes_u8, 0 }, - { "bg_img_recolor", 28, 0, 0, ctypes_u16, 1 }, - { "bg_img_recolor_opa", 31, 0, 0, ctypes_u8, 0 }, - { "bg_img_src", 20, 0, 0, ctypes_ptr32, 0 }, - { "bg_img_symbol_font", 24, 0, 0, ctypes_ptr32, 0 }, - { "bg_img_tiled", 32, 0, 0, ctypes_u8, 0 }, - { "bg_opa", 3, 0, 0, ctypes_u8, 0 }, - { "blend_mode", 2, 0, 0, ctypes_u8, 0 }, - { "border_color", 34, 0, 0, ctypes_u16, 1 }, - { "border_opa", 38, 0, 0, ctypes_u8, 0 }, - { "border_post", 39, 0, 1, ctypes_bf, 0 }, - { "border_side", 39, 1, 5, ctypes_bf, 0 }, - { "border_width", 36, 0, 0, ctypes_i16, 0 }, - { "outline_color", 40, 0, 0, ctypes_u16, 1 }, - { "outline_opa", 46, 0, 0, ctypes_u8, 0 }, - { "outline_pad", 44, 0, 0, ctypes_i16, 0 }, - { "outline_width", 42, 0, 0, ctypes_i16, 0 }, - { "radius", 0, 0, 0, ctypes_i16, 0 }, - { "shadow_color", 48, 0, 0, ctypes_u16, 1 }, - { "shadow_ofs_x", 52, 0, 0, ctypes_i16, 0 }, - { "shadow_ofs_y", 54, 0, 0, ctypes_i16, 0 }, - { "shadow_opa", 58, 0, 0, ctypes_u8, 0 }, - { "shadow_spread", 56, 0, 0, ctypes_i16, 0 }, - { "shadow_width", 50, 0, 0, ctypes_i16, 0 }, -}}; - -const be_ctypes_structure_t be_lv_draw_line_dsc = { - 12, /* size in bytes */ - 9, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[9]) { - { "blend_mode", 9, 0, 2, ctypes_bf, 0 }, - { "color", 0, 0, 0, ctypes_u16, 1 }, - { "dash_gap", 6, 0, 0, ctypes_i16, 0 }, - { "dash_width", 4, 0, 0, ctypes_i16, 0 }, - { "opa", 8, 0, 0, ctypes_u8, 0 }, - { "raw_end", 9, 4, 1, ctypes_bf, 0 }, - { "round_end", 9, 3, 1, ctypes_bf, 0 }, - { "round_start", 9, 2, 1, ctypes_bf, 0 }, - { "width", 2, 0, 0, ctypes_i16, 0 }, -}}; - -const be_ctypes_structure_t be_lv_draw_arc_dsc = { 16, /* size in bytes */ 8, /* number of elements */ be_ctypes_instance_mappings, (const be_ctypes_structure_item_t[8]) { - { "blend_mode", 13, 0, 2, ctypes_bf, 0 }, - { "color", 0, 0, 0, ctypes_u16, 1 }, - { "end_angle", 6, 0, 0, ctypes_u16, 0 }, - { "img_src", 8, 0, 0, ctypes_ptr32, 0 }, - { "opa", 12, 0, 0, ctypes_u8, 0 }, - { "rounded", 13, 2, 1, ctypes_bf, 0 }, - { "start_angle", 4, 0, 0, ctypes_u16, 0 }, - { "width", 2, 0, 0, ctypes_i16, 0 }, + { "dir", 14, 0, 3, ctypes_bf, 0 }, + { "stops_0_color", 0, 0, 0, ctypes_u24, 1 }, + { "stops_0_frac", 4, 0, 0, ctypes_u8, 0 }, + { "stops_0_opa", 3, 0, 0, ctypes_u8, 0 }, + { "stops_1_color", 8, 0, 0, ctypes_u24, 1 }, + { "stops_1_frac", 12, 0, 0, ctypes_u8, 0 }, + { "stops_1_opa", 11, 0, 0, ctypes_u8, 0 }, + { "stops_count", 13, 0, 0, ctypes_u8, 0 }, }}; -const be_ctypes_structure_t be_lv_draw_img_dsc = { - 24, /* size in bytes */ - 10, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[10]) { - { "angle", 0, 0, 0, ctypes_i16, 0 }, - { "antialias", 20, 0, 1, ctypes_bf, 0 }, - { "blend_mode", 12, 0, 4, ctypes_bf, 0 }, - { "frame_id", 16, 0, 0, ctypes_i32, 0 }, - { "opa", 11, 0, 0, ctypes_u8, 0 }, - { "pivot_x", 4, 0, 0, ctypes_i16, 0 }, - { "pivot_y", 6, 0, 0, ctypes_i16, 0 }, - { "recolor", 8, 0, 0, ctypes_u16, 1 }, - { "recolor_opa", 10, 0, 0, ctypes_u8, 0 }, - { "zoom", 2, 0, 0, ctypes_u16, 0 }, -}}; - -const be_ctypes_structure_t be_lv_obj_draw_part_dsc = { - 72, /* size in bytes */ - 18, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[18]) { - { "arc_dsc", 32, 0, 0, ctypes_ptr32, 0 }, - { "class_p", 4, 0, 0, ctypes_ptr32, 0 }, - { "draw_area", 12, 0, 0, ctypes_ptr32, 0 }, - { "draw_ctx", 0, 0, 0, ctypes_ptr32, 0 }, - { "id", 56, 0, 0, ctypes_u32, 0 }, - { "img_dsc", 28, 0, 0, ctypes_ptr32, 0 }, - { "label_dsc", 20, 0, 0, ctypes_ptr32, 0 }, - { "line_dsc", 24, 0, 0, ctypes_ptr32, 0 }, - { "p1", 36, 0, 0, ctypes_ptr32, 0 }, - { "p2", 40, 0, 0, ctypes_ptr32, 0 }, - { "part", 52, 0, 0, ctypes_u32, 0 }, - { "radius", 60, 0, 0, ctypes_i16, 0 }, - { "rect_dsc", 16, 0, 0, ctypes_ptr32, 0 }, - { "sub_part_ptr", 68, 0, 0, ctypes_ptr32, 0 }, - { "text", 44, 0, 0, ctypes_ptr32, 0 }, - { "text_length", 48, 0, 0, ctypes_u32, 0 }, - { "type", 8, 0, 0, ctypes_u32, 0 }, - { "value", 64, 0, 0, ctypes_i32, 0 }, -}}; - -const be_ctypes_structure_t be_lv_draw_layer_ctx = { - 40, /* size in bytes */ - 14, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[14]) { - { "area_act_x1", 8, 0, 0, ctypes_i16, 0 }, - { "area_act_x2", 12, 0, 0, ctypes_i16, 0 }, - { "area_act_y1", 10, 0, 0, ctypes_i16, 0 }, - { "area_act_y2", 14, 0, 0, ctypes_i16, 0 }, - { "area_full_x1", 0, 0, 0, ctypes_i16, 0 }, - { "area_full_x2", 4, 0, 0, ctypes_i16, 0 }, - { "area_full_y1", 2, 0, 0, ctypes_i16, 0 }, - { "area_full_y2", 6, 0, 0, ctypes_i16, 0 }, - { "buf", 32, 0, 0, ctypes_ptr32, 0 }, - { "buf_area", 28, 0, 0, ctypes_ptr32, 0 }, - { "clip_area", 24, 0, 0, ctypes_ptr32, 0 }, - { "max_row_with_alpha", 16, 0, 0, ctypes_i16, 0 }, - { "max_row_with_no_alpha", 18, 0, 0, ctypes_i16, 0 }, - { "screen_transp", 36, 0, 0, ctypes_u8, 0 }, -}}; - -const be_ctypes_structure_t be_lv_draw_mask_common_dsc = { - 8, /* size in bytes */ - 2, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[2]) { - { "cb", 0, 0, 0, ctypes_ptr32, 0 }, - { "type", 4, 0, 0, ctypes_u8, 0 }, -}}; - -const be_ctypes_structure_t be_lv_draw_mask_line_param_cfg = { - 12, /* size in bytes */ - 5, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[5]) { - { "p1_x", 0, 0, 0, ctypes_i16, 0 }, - { "p1_y", 2, 0, 0, ctypes_i16, 0 }, - { "p2_x", 4, 0, 0, ctypes_i16, 0 }, - { "p2_y", 6, 0, 0, ctypes_i16, 0 }, - { "side", 8, 0, 2, ctypes_bf, 0 }, -}}; - -const be_ctypes_structure_t be_lv_draw_mask_line_param = { - 44, /* size in bytes */ - 15, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[15]) { - { "cfg_p1_x", 8, 0, 0, ctypes_i16, 0 }, - { "cfg_p1_y", 10, 0, 0, ctypes_i16, 0 }, - { "cfg_p2_x", 12, 0, 0, ctypes_i16, 0 }, - { "cfg_p2_y", 14, 0, 0, ctypes_i16, 0 }, - { "cfg_side", 16, 0, 2, ctypes_bf, 0 }, - { "dsc_cb", 0, 0, 0, ctypes_ptr32, 0 }, - { "dsc_type", 4, 0, 0, ctypes_u8, 0 }, - { "flat", 40, 0, 1, ctypes_bf, 0 }, - { "inv", 40, 1, 1, ctypes_bf, 0 }, - { "origo_x", 20, 0, 0, ctypes_i16, 0 }, - { "origo_y", 22, 0, 0, ctypes_i16, 0 }, - { "spx", 36, 0, 0, ctypes_i32, 0 }, - { "steep", 32, 0, 0, ctypes_i32, 0 }, - { "xy_steep", 24, 0, 0, ctypes_i32, 0 }, - { "yx_steep", 28, 0, 0, ctypes_i32, 0 }, -}}; - -const be_ctypes_structure_t be_lv_draw_mask_angle_param_cfg = { - 8, /* size in bytes */ - 4, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[4]) { - { "end_angle", 6, 0, 0, ctypes_i16, 0 }, - { "start_angle", 4, 0, 0, ctypes_i16, 0 }, - { "vertex_p_x", 0, 0, 0, ctypes_i16, 0 }, - { "vertex_p_y", 2, 0, 0, ctypes_i16, 0 }, -}}; - -const be_ctypes_structure_t be_lv_draw_mask_angle_param = { - 104, /* size in bytes */ - 37, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[37]) { - { "cfg_end_angle", 14, 0, 0, ctypes_i16, 0 }, - { "cfg_start_angle", 12, 0, 0, ctypes_i16, 0 }, - { "cfg_vertex_p_x", 8, 0, 0, ctypes_i16, 0 }, - { "cfg_vertex_p_y", 10, 0, 0, ctypes_i16, 0 }, - { "delta_deg", 102, 0, 0, ctypes_u16, 0 }, - { "dsc_cb", 0, 0, 0, ctypes_ptr32, 0 }, - { "dsc_type", 4, 0, 0, ctypes_u8, 0 }, - { "end_line_cfg_p1_x", 68, 0, 0, ctypes_i16, 0 }, - { "end_line_cfg_p1_y", 70, 0, 0, ctypes_i16, 0 }, - { "end_line_cfg_p2_x", 72, 0, 0, ctypes_i16, 0 }, - { "end_line_cfg_p2_y", 74, 0, 0, ctypes_i16, 0 }, - { "end_line_cfg_side", 76, 0, 2, ctypes_bf, 0 }, - { "end_line_dsc_cb", 60, 0, 0, ctypes_ptr32, 0 }, - { "end_line_dsc_type", 64, 0, 0, ctypes_u8, 0 }, - { "end_line_flat", 100, 0, 1, ctypes_bf, 0 }, - { "end_line_inv", 100, 1, 1, ctypes_bf, 0 }, - { "end_line_origo_x", 80, 0, 0, ctypes_i16, 0 }, - { "end_line_origo_y", 82, 0, 0, ctypes_i16, 0 }, - { "end_line_spx", 96, 0, 0, ctypes_i32, 0 }, - { "end_line_steep", 92, 0, 0, ctypes_i32, 0 }, - { "end_line_xy_steep", 84, 0, 0, ctypes_i32, 0 }, - { "end_line_yx_steep", 88, 0, 0, ctypes_i32, 0 }, - { "start_line_cfg_p1_x", 24, 0, 0, ctypes_i16, 0 }, - { "start_line_cfg_p1_y", 26, 0, 0, ctypes_i16, 0 }, - { "start_line_cfg_p2_x", 28, 0, 0, ctypes_i16, 0 }, - { "start_line_cfg_p2_y", 30, 0, 0, ctypes_i16, 0 }, - { "start_line_cfg_side", 32, 0, 2, ctypes_bf, 0 }, - { "start_line_dsc_cb", 16, 0, 0, ctypes_ptr32, 0 }, - { "start_line_dsc_type", 20, 0, 0, ctypes_u8, 0 }, - { "start_line_flat", 56, 0, 1, ctypes_bf, 0 }, - { "start_line_inv", 56, 1, 1, ctypes_bf, 0 }, - { "start_line_origo_x", 36, 0, 0, ctypes_i16, 0 }, - { "start_line_origo_y", 38, 0, 0, ctypes_i16, 0 }, - { "start_line_spx", 52, 0, 0, ctypes_i32, 0 }, - { "start_line_steep", 48, 0, 0, ctypes_i32, 0 }, - { "start_line_xy_steep", 40, 0, 0, ctypes_i32, 0 }, - { "start_line_yx_steep", 44, 0, 0, ctypes_i32, 0 }, -}}; - -const be_ctypes_structure_t be_lv_draw_mask_radius_param_cfg = { - 12, /* size in bytes */ - 6, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[6]) { - { "outer", 10, 0, 1, ctypes_bf, 0 }, - { "radius", 8, 0, 0, ctypes_i16, 0 }, - { "rect_x1", 0, 0, 0, ctypes_i16, 0 }, - { "rect_x2", 4, 0, 0, ctypes_i16, 0 }, - { "rect_y1", 2, 0, 0, ctypes_i16, 0 }, - { "rect_y2", 6, 0, 0, ctypes_i16, 0 }, -}}; - -const be_ctypes_structure_t be_lv_draw_mask_radius_circle_dsc = { +const be_ctypes_structure_t be_lv_draw_dsc_base = { 28, /* size in bytes */ 7, /* number of elements */ be_ctypes_instance_mappings, (const be_ctypes_structure_item_t[7]) { - { "buf", 0, 0, 0, ctypes_ptr32, 0 }, - { "cir_opa", 4, 0, 0, ctypes_ptr32, 0 }, - { "life", 16, 0, 0, ctypes_i32, 0 }, - { "opa_start_on_y", 12, 0, 0, ctypes_ptr32, 0 }, - { "radius", 24, 0, 0, ctypes_i16, 0 }, - { "used_cnt", 20, 0, 0, ctypes_u32, 0 }, - { "x_start_on_y", 8, 0, 0, ctypes_ptr32, 0 }, + { "dsc_size", 20, 0, 0, ctypes_u32, 0 }, + { "id1", 8, 0, 0, ctypes_u32, 0 }, + { "id2", 12, 0, 0, ctypes_u32, 0 }, + { "layer", 16, 0, 0, ctypes_ptr32, 0 }, + { "obj", 0, 0, 0, ctypes_ptr32, 0 }, + { "part", 4, 0, 0, ctypes_u32, 0 }, + { "user_data", 24, 0, 0, ctypes_ptr32, 0 }, }}; -const be_ctypes_structure_t be_lv_draw_mask_radius_param = { - 48, /* size in bytes */ - 15, /* number of elements */ +const be_ctypes_structure_t be_lv_draw_rect_dsc = { + 124, /* size in bytes */ + 39, /* number of elements */ be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[15]) { - { "cfg_outer", 18, 0, 1, ctypes_bf, 0 }, - { "cfg_radius", 16, 0, 0, ctypes_i16, 0 }, - { "cfg_rect_x1", 8, 0, 0, ctypes_i16, 0 }, - { "cfg_rect_x2", 12, 0, 0, ctypes_i16, 0 }, - { "cfg_rect_y1", 10, 0, 0, ctypes_i16, 0 }, - { "cfg_rect_y2", 14, 0, 0, ctypes_i16, 0 }, - { "circle_buf", 20, 0, 0, ctypes_ptr32, 0 }, - { "circle_cir_opa", 24, 0, 0, ctypes_ptr32, 0 }, - { "circle_life", 36, 0, 0, ctypes_i32, 0 }, - { "circle_opa_start_on_y", 32, 0, 0, ctypes_ptr32, 0 }, - { "circle_radius", 44, 0, 0, ctypes_i16, 0 }, - { "circle_used_cnt", 40, 0, 0, ctypes_u32, 0 }, - { "circle_x_start_on_y", 28, 0, 0, ctypes_ptr32, 0 }, - { "dsc_cb", 0, 0, 0, ctypes_ptr32, 0 }, - { "dsc_type", 4, 0, 0, ctypes_u8, 0 }, + (const be_ctypes_structure_item_t[39]) { + { "base_dsc_size", 20, 0, 0, ctypes_u32, 0 }, + { "base_id1", 8, 0, 0, ctypes_u32, 0 }, + { "base_id2", 12, 0, 0, ctypes_u32, 0 }, + { "base_layer", 16, 0, 0, ctypes_ptr32, 0 }, + { "base_obj", 0, 0, 0, ctypes_ptr32, 0 }, + { "base_part", 4, 0, 0, ctypes_u32, 0 }, + { "base_user_data", 24, 0, 0, ctypes_ptr32, 0 }, + { "bg_color", 36, 0, 0, ctypes_u24, 1 }, + { "bg_grad_dir", 54, 0, 3, ctypes_bf, 0 }, + { "bg_grad_stops_0_color", 40, 0, 0, ctypes_u24, 1 }, + { "bg_grad_stops_0_frac", 44, 0, 0, ctypes_u8, 0 }, + { "bg_grad_stops_0_opa", 43, 0, 0, ctypes_u8, 0 }, + { "bg_grad_stops_1_color", 48, 0, 0, ctypes_u24, 1 }, + { "bg_grad_stops_1_frac", 52, 0, 0, ctypes_u8, 0 }, + { "bg_grad_stops_1_opa", 51, 0, 0, ctypes_u8, 0 }, + { "bg_grad_stops_count", 53, 0, 0, ctypes_u8, 0 }, + { "bg_img_opa", 67, 0, 0, ctypes_u8, 0 }, + { "bg_img_recolor", 64, 0, 0, ctypes_u24, 1 }, + { "bg_img_recolor_opa", 68, 0, 0, ctypes_u8, 0 }, + { "bg_img_src", 56, 0, 0, ctypes_ptr32, 0 }, + { "bg_img_symbol_font", 60, 0, 0, ctypes_ptr32, 0 }, + { "bg_img_tiled", 69, 0, 0, ctypes_u8, 0 }, + { "bg_opa", 32, 0, 0, ctypes_u8, 0 }, + { "border_color", 72, 0, 0, ctypes_u24, 1 }, + { "border_opa", 80, 0, 0, ctypes_u8, 0 }, + { "border_post", 81, 0, 1, ctypes_bf, 0 }, + { "border_side", 81, 1, 5, ctypes_bf, 0 }, + { "border_width", 76, 0, 0, ctypes_i32, 0 }, + { "outline_color", 84, 0, 0, ctypes_u24, 1 }, + { "outline_opa", 96, 0, 0, ctypes_u8, 0 }, + { "outline_pad", 92, 0, 0, ctypes_i32, 0 }, + { "outline_width", 88, 0, 0, ctypes_i32, 0 }, + { "radius", 28, 0, 0, ctypes_i32, 0 }, + { "shadow_color", 100, 0, 0, ctypes_u24, 1 }, + { "shadow_ofs_x", 108, 0, 0, ctypes_i32, 0 }, + { "shadow_ofs_y", 112, 0, 0, ctypes_i32, 0 }, + { "shadow_opa", 120, 0, 0, ctypes_u8, 0 }, + { "shadow_spread", 116, 0, 0, ctypes_i32, 0 }, + { "shadow_width", 104, 0, 0, ctypes_i32, 0 }, }}; -const be_ctypes_structure_t be_lv_draw_mask_fade_param_cfg = { - 16, /* size in bytes */ - 8, /* number of elements */ +const be_ctypes_structure_t be_lv_draw_line_dsc = { + 64, /* size in bytes */ + 20, /* number of elements */ be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[8]) { - { "coords_x1", 0, 0, 0, ctypes_i16, 0 }, - { "coords_x2", 4, 0, 0, ctypes_i16, 0 }, - { "coords_y1", 2, 0, 0, ctypes_i16, 0 }, - { "coords_y2", 6, 0, 0, ctypes_i16, 0 }, - { "opa_bottom", 13, 0, 0, ctypes_u8, 0 }, - { "opa_top", 12, 0, 0, ctypes_u8, 0 }, - { "y_bottom", 10, 0, 0, ctypes_i16, 0 }, - { "y_top", 8, 0, 0, ctypes_i16, 0 }, + (const be_ctypes_structure_item_t[20]) { + { "base_dsc_size", 20, 0, 0, ctypes_u32, 0 }, + { "base_id1", 8, 0, 0, ctypes_u32, 0 }, + { "base_id2", 12, 0, 0, ctypes_u32, 0 }, + { "base_layer", 16, 0, 0, ctypes_ptr32, 0 }, + { "base_obj", 0, 0, 0, ctypes_ptr32, 0 }, + { "base_part", 4, 0, 0, ctypes_u32, 0 }, + { "base_user_data", 24, 0, 0, ctypes_ptr32, 0 }, + { "blend_mode", 61, 0, 2, ctypes_bf, 0 }, + { "color", 44, 0, 0, ctypes_u24, 1 }, + { "dash_gap", 56, 0, 0, ctypes_i32, 0 }, + { "dash_width", 52, 0, 0, ctypes_i32, 0 }, + { "opa", 60, 0, 0, ctypes_u8, 0 }, + { "p1_x", 28, 0, 0, ctypes_i32, 0 }, + { "p1_y", 32, 0, 0, ctypes_i32, 0 }, + { "p2_x", 36, 0, 0, ctypes_i32, 0 }, + { "p2_y", 40, 0, 0, ctypes_i32, 0 }, + { "raw_end", 61, 4, 1, ctypes_bf, 0 }, + { "round_end", 61, 3, 1, ctypes_bf, 0 }, + { "round_start", 61, 2, 1, ctypes_bf, 0 }, + { "width", 48, 0, 0, ctypes_i32, 0 }, }}; -const be_ctypes_structure_t be_lv_draw_mask_fade_param = { - 24, /* size in bytes */ - 10, /* number of elements */ +const be_ctypes_structure_t be_lv_draw_arc_dsc = { + 64, /* size in bytes */ + 17, /* number of elements */ be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[10]) { - { "cfg_coords_x1", 8, 0, 0, ctypes_i16, 0 }, - { "cfg_coords_x2", 12, 0, 0, ctypes_i16, 0 }, - { "cfg_coords_y1", 10, 0, 0, ctypes_i16, 0 }, - { "cfg_coords_y2", 14, 0, 0, ctypes_i16, 0 }, - { "cfg_opa_bottom", 21, 0, 0, ctypes_u8, 0 }, - { "cfg_opa_top", 20, 0, 0, ctypes_u8, 0 }, - { "cfg_y_bottom", 18, 0, 0, ctypes_i16, 0 }, - { "cfg_y_top", 16, 0, 0, ctypes_i16, 0 }, - { "dsc_cb", 0, 0, 0, ctypes_ptr32, 0 }, - { "dsc_type", 4, 0, 0, ctypes_u8, 0 }, + (const be_ctypes_structure_item_t[17]) { + { "base_dsc_size", 20, 0, 0, ctypes_u32, 0 }, + { "base_id1", 8, 0, 0, ctypes_u32, 0 }, + { "base_id2", 12, 0, 0, ctypes_u32, 0 }, + { "base_layer", 16, 0, 0, ctypes_ptr32, 0 }, + { "base_obj", 0, 0, 0, ctypes_ptr32, 0 }, + { "base_part", 4, 0, 0, ctypes_u32, 0 }, + { "base_user_data", 24, 0, 0, ctypes_ptr32, 0 }, + { "center_x", 44, 0, 0, ctypes_i32, 0 }, + { "center_y", 48, 0, 0, ctypes_i32, 0 }, + { "color", 28, 0, 0, ctypes_u24, 1 }, + { "end_angle", 40, 0, 0, ctypes_i32, 0 }, + { "img_src", 56, 0, 0, ctypes_ptr32, 0 }, + { "opa", 60, 0, 0, ctypes_u8, 0 }, + { "radius", 52, 0, 0, ctypes_u16, 0 }, + { "rounded", 61, 0, 1, ctypes_bf, 0 }, + { "start_angle", 36, 0, 0, ctypes_i32, 0 }, + { "width", 32, 0, 0, ctypes_i32, 0 }, }}; -const be_ctypes_structure_t be_lv_draw_mask_map_param_cfg = { +const be_ctypes_structure_t be_lv_image_header = { 12, /* size in bytes */ - 5, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[5]) { - { "coords_x1", 0, 0, 0, ctypes_i16, 0 }, - { "coords_x2", 4, 0, 0, ctypes_i16, 0 }, - { "coords_y1", 2, 0, 0, ctypes_i16, 0 }, - { "coords_y2", 6, 0, 0, ctypes_i16, 0 }, - { "map", 8, 0, 0, ctypes_ptr32, 0 }, -}}; - -const be_ctypes_structure_t be_lv_draw_mask_map_param = { - 20, /* size in bytes */ 7, /* number of elements */ be_ctypes_instance_mappings, (const be_ctypes_structure_item_t[7]) { - { "cfg_coords_x1", 8, 0, 0, ctypes_i16, 0 }, - { "cfg_coords_x2", 12, 0, 0, ctypes_i16, 0 }, - { "cfg_coords_y1", 10, 0, 0, ctypes_i16, 0 }, - { "cfg_coords_y2", 14, 0, 0, ctypes_i16, 0 }, - { "cfg_map", 16, 0, 0, ctypes_ptr32, 0 }, - { "dsc_cb", 0, 0, 0, ctypes_ptr32, 0 }, - { "dsc_type", 4, 0, 0, ctypes_u8, 0 }, + { "cf", 1, 0, 0, ctypes_u8, 0 }, + { "flags", 2, 0, 0, ctypes_u16, 0 }, + { "h", 6, 0, 0, ctypes_u16, 0 }, + { "magic", 0, 0, 0, ctypes_u8, 0 }, + { "reserved_2", 10, 0, 0, ctypes_u16, 0 }, + { "stride", 8, 0, 0, ctypes_u16, 0 }, + { "w", 4, 0, 0, ctypes_u16, 0 }, }}; -const be_ctypes_structure_t be_lv_draw_mask_polygon_param_cfg = { - 8, /* size in bytes */ - 2, /* number of elements */ +const be_ctypes_structure_t be_lv_draw_image_dsc = { + 84, /* size in bytes */ + 29, /* number of elements */ be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[2]) { - { "point_cnt", 4, 0, 0, ctypes_u16, 0 }, - { "points", 0, 0, 0, ctypes_ptr32, 0 }, -}}; - -const be_ctypes_structure_t be_lv_draw_mask_polygon_param = { - 16, /* size in bytes */ - 4, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[4]) { - { "cfg_point_cnt", 12, 0, 0, ctypes_u16, 0 }, - { "cfg_points", 8, 0, 0, ctypes_ptr32, 0 }, - { "dsc_cb", 0, 0, 0, ctypes_ptr32, 0 }, - { "dsc_type", 4, 0, 0, ctypes_u8, 0 }, -}}; - -const be_ctypes_structure_t be_lv_draw_mask_saved = { - 8, /* size in bytes */ - 2, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[2]) { - { "custom_id", 4, 0, 0, ctypes_ptr32, 0 }, - { "param", 0, 0, 0, ctypes_ptr32, 0 }, + (const be_ctypes_structure_item_t[29]) { + { "antialias", 77, 4, 1, ctypes_bf, 0 }, + { "base_dsc_size", 20, 0, 0, ctypes_u32, 0 }, + { "base_id1", 8, 0, 0, ctypes_u32, 0 }, + { "base_id2", 12, 0, 0, ctypes_u32, 0 }, + { "base_layer", 16, 0, 0, ctypes_ptr32, 0 }, + { "base_obj", 0, 0, 0, ctypes_ptr32, 0 }, + { "base_part", 4, 0, 0, ctypes_u32, 0 }, + { "base_user_data", 24, 0, 0, ctypes_ptr32, 0 }, + { "blend_mode", 77, 0, 4, ctypes_bf, 0 }, + { "header_cf", 33, 0, 0, ctypes_u8, 0 }, + { "header_flags", 34, 0, 0, ctypes_u16, 0 }, + { "header_h", 38, 0, 0, ctypes_u16, 0 }, + { "header_magic", 32, 0, 0, ctypes_u8, 0 }, + { "header_reserved_2", 42, 0, 0, ctypes_u16, 0 }, + { "header_stride", 40, 0, 0, ctypes_u16, 0 }, + { "header_w", 36, 0, 0, ctypes_u16, 0 }, + { "opa", 76, 0, 0, ctypes_u8, 0 }, + { "pivot_x", 64, 0, 0, ctypes_i32, 0 }, + { "pivot_y", 68, 0, 0, ctypes_i32, 0 }, + { "recolor", 72, 0, 0, ctypes_u24, 1 }, + { "recolor_opa", 75, 0, 0, ctypes_u8, 0 }, + { "rotation", 44, 0, 0, ctypes_i32, 0 }, + { "scale_x", 48, 0, 0, ctypes_i32, 0 }, + { "scale_y", 52, 0, 0, ctypes_i32, 0 }, + { "skew_x", 56, 0, 0, ctypes_i32, 0 }, + { "skew_y", 60, 0, 0, ctypes_i32, 0 }, + { "src", 28, 0, 0, ctypes_ptr32, 0 }, + { "sup", 80, 0, 0, ctypes_ptr32, 0 }, + { "tile", 77, 5, 1, ctypes_bf, 0 }, }}; const be_ctypes_structure_t be_lv_meter_scale = { - 36, /* size in bytes */ + 40, /* size in bytes */ 14, /* number of elements */ be_ctypes_instance_mappings, (const be_ctypes_structure_item_t[14]) { - { "angle_range", 30, 0, 0, ctypes_u16, 0 }, - { "label_gap", 16, 0, 0, ctypes_i16, 0 }, - { "max", 24, 0, 0, ctypes_i32, 0 }, - { "min", 20, 0, 0, ctypes_i32, 0 }, - { "r_mod", 28, 0, 0, ctypes_i16, 0 }, - { "rotation", 32, 0, 0, ctypes_i16, 0 }, - { "tick_cnt", 2, 0, 0, ctypes_u16, 0 }, - { "tick_color", 0, 0, 0, ctypes_u16, 1 }, - { "tick_length", 4, 0, 0, ctypes_u16, 0 }, - { "tick_major_color", 8, 0, 0, ctypes_u16, 1 }, - { "tick_major_length", 12, 0, 0, ctypes_u16, 0 }, - { "tick_major_nth", 10, 0, 0, ctypes_u16, 0 }, - { "tick_major_width", 14, 0, 0, ctypes_u16, 0 }, - { "tick_width", 6, 0, 0, ctypes_u16, 0 }, + { "angle_range", 34, 0, 0, ctypes_u16, 0 }, + { "label_gap", 22, 0, 0, ctypes_i16, 0 }, + { "max", 28, 0, 0, ctypes_i32, 0 }, + { "min", 24, 0, 0, ctypes_i32, 0 }, + { "r_mod", 32, 0, 0, ctypes_i16, 0 }, + { "rotation", 36, 0, 0, ctypes_i16, 0 }, + { "tick_cnt", 4, 0, 0, ctypes_u16, 0 }, + { "tick_color", 0, 0, 0, ctypes_u24, 1 }, + { "tick_length", 6, 0, 0, ctypes_u16, 0 }, + { "tick_major_color", 12, 0, 0, ctypes_u24, 1 }, + { "tick_major_length", 18, 0, 0, ctypes_u16, 0 }, + { "tick_major_nth", 16, 0, 0, ctypes_u16, 0 }, + { "tick_major_width", 20, 0, 0, ctypes_u16, 0 }, + { "tick_width", 8, 0, 0, ctypes_u16, 0 }, }}; const be_ctypes_structure_t be_lv_meter_indicator = { @@ -467,63 +264,52 @@ const be_ctypes_structure_t be_lv_meter_indicator = { }}; const be_ctypes_structure_t be_lv_chart_series = { - 16, /* size in bytes */ + 20, /* size in bytes */ 9, /* number of elements */ be_ctypes_instance_mappings, (const be_ctypes_structure_item_t[9]) { - { "color", 8, 0, 0, ctypes_u16, 1 }, - { "hidden", 12, 0, 1, ctypes_bf, 0 }, - { "start_point", 10, 0, 0, ctypes_u16, 0 }, - { "x_axis_sec", 12, 3, 1, ctypes_bf, 0 }, - { "x_ext_buf_assigned", 12, 1, 1, ctypes_bf, 0 }, + { "color", 8, 0, 0, ctypes_u24, 1 }, + { "hidden", 16, 0, 1, ctypes_bf, 0 }, + { "start_point", 12, 0, 0, ctypes_u32, 0 }, + { "x_axis_sec", 16, 3, 1, ctypes_bf, 0 }, + { "x_ext_buf_assigned", 16, 1, 1, ctypes_bf, 0 }, { "x_points", 0, 0, 0, ctypes_ptr32, 0 }, - { "y_axis_sec", 12, 4, 1, ctypes_bf, 0 }, - { "y_ext_buf_assigned", 12, 2, 1, ctypes_bf, 0 }, + { "y_axis_sec", 16, 4, 1, ctypes_bf, 0 }, + { "y_ext_buf_assigned", 16, 2, 1, ctypes_bf, 0 }, { "y_points", 4, 0, 0, ctypes_ptr32, 0 }, }}; const be_ctypes_structure_t be_lv_chart_cursor = { - 16, /* size in bytes */ + 24, /* size in bytes */ 7, /* number of elements */ be_ctypes_instance_mappings, (const be_ctypes_structure_item_t[7]) { - { "color", 6, 0, 0, ctypes_u16, 1 }, - { "dir", 12, 0, 0, ctypes_u8, 0 }, - { "point_id", 4, 0, 0, ctypes_u16, 0 }, - { "pos_set", 13, 0, 1, ctypes_bf, 0 }, - { "pos_x", 0, 0, 0, ctypes_i16, 0 }, - { "pos_y", 2, 0, 0, ctypes_i16, 0 }, - { "ser", 8, 0, 0, ctypes_ptr32, 0 }, -}}; - -const be_ctypes_structure_t be_lv_chart_tick_dsc = { - 12, /* size in bytes */ - 6, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[6]) { - { "draw_size", 4, 0, 0, ctypes_i16, 0 }, - { "label_en", 9, 6, 1, ctypes_bf, 0 }, - { "major_cnt", 7, 7, 15, ctypes_bf, 0 }, - { "major_len", 0, 0, 0, ctypes_i16, 0 }, - { "minor_cnt", 6, 0, 15, ctypes_bf, 0 }, - { "minor_len", 2, 0, 0, ctypes_i16, 0 }, + { "color", 12, 0, 0, ctypes_u24, 1 }, + { "dir", 20, 0, 0, ctypes_u8, 0 }, + { "point_id", 8, 0, 0, ctypes_i32, 0 }, + { "pos_set", 21, 0, 1, ctypes_bf, 0 }, + { "pos_x", 0, 0, 0, ctypes_i32, 0 }, + { "pos_y", 4, 0, 0, ctypes_i32, 0 }, + { "ser", 16, 0, 0, ctypes_ptr32, 0 }, }}; const be_ctypes_structure_t be_lv_obj_class = { - 28, /* size in bytes */ - 10, /* number of elements */ + 36, /* size in bytes */ + 12, /* number of elements */ be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[10]) { + (const be_ctypes_structure_item_t[12]) { { "base_class", 0, 0, 0, ctypes_ptr32, 0 }, { "constructor_cb", 4, 0, 0, ctypes_ptr32, 0 }, { "destructor_cb", 8, 0, 0, ctypes_ptr32, 0 }, - { "editable", 24, 0, 2, ctypes_bf, 0 }, - { "event_cb", 16, 0, 0, ctypes_ptr32, 0 }, - { "group_def", 24, 2, 2, ctypes_bf, 0 }, - { "height_def", 22, 0, 0, ctypes_i16, 0 }, - { "instance_size", 24, 4, 16, ctypes_bf, 0 }, - { "user_data", 12, 0, 0, ctypes_ptr32, 0 }, - { "width_def", 20, 0, 0, ctypes_i16, 0 }, + { "editable", 32, 0, 2, ctypes_bf, 0 }, + { "event_cb", 12, 0, 0, ctypes_ptr32, 0 }, + { "group_def", 32, 2, 2, ctypes_bf, 0 }, + { "height_def", 28, 0, 0, ctypes_i32, 0 }, + { "instance_size", 32, 4, 16, ctypes_bf, 0 }, + { "name", 20, 0, 0, ctypes_ptr32, 0 }, + { "theme_inheritable", 34, 4, 1, ctypes_bf, 0 }, + { "user_data", 16, 0, 0, ctypes_ptr32, 0 }, + { "width_def", 24, 0, 0, ctypes_i32, 0 }, }}; const be_ctypes_structure_t be_lv_event = { @@ -542,39 +328,20 @@ const be_ctypes_structure_t be_lv_event = { { "user_data", 12, 0, 0, ctypes_ptr32, 0 }, }}; -const be_ctypes_structure_t be_lv_sqrt_res = { - 4, /* size in bytes */ - 2, /* number of elements */ +const be_ctypes_structure_t be_lv_image_dsc = { + 20, /* size in bytes */ + 9, /* number of elements */ be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[2]) { - { "f", 2, 0, 0, ctypes_u16, 0 }, - { "i", 0, 0, 0, ctypes_u16, 0 }, -}}; - -const be_ctypes_structure_t be_lv_img_header = { - 4, /* size in bytes */ - 5, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[5]) { - { "always_zero", 0, 5, 3, ctypes_bf, 0 }, - { "cf", 0, 0, 5, ctypes_bf, 0 }, - { "h", 2, 5, 11, ctypes_bf, 0 }, - { "reserved", 1, 0, 2, ctypes_bf, 0 }, - { "w", 1, 2, 11, ctypes_bf, 0 }, -}}; - -const be_ctypes_structure_t be_lv_img_dsc = { - 12, /* size in bytes */ - 7, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[7]) { - { "data", 8, 0, 0, ctypes_ptr32, 0 }, - { "data_size", 4, 0, 0, ctypes_u32, 0 }, - { "header_always_zero", 0, 5, 3, ctypes_bf, 0 }, - { "header_cf", 0, 0, 5, ctypes_bf, 0 }, - { "header_h", 2, 5, 11, ctypes_bf, 0 }, - { "header_reserved", 1, 0, 2, ctypes_bf, 0 }, - { "header_w", 1, 2, 11, ctypes_bf, 0 }, + (const be_ctypes_structure_item_t[9]) { + { "data", 16, 0, 0, ctypes_ptr32, 0 }, + { "data_size", 12, 0, 0, ctypes_u32, 0 }, + { "header_cf", 1, 0, 0, ctypes_u8, 0 }, + { "header_flags", 2, 0, 0, ctypes_u16, 0 }, + { "header_h", 6, 0, 0, ctypes_u16, 0 }, + { "header_magic", 0, 0, 0, ctypes_u8, 0 }, + { "header_reserved_2", 10, 0, 0, ctypes_u16, 0 }, + { "header_stride", 8, 0, 0, ctypes_u16, 0 }, + { "header_w", 4, 0, 0, ctypes_u16, 0 }, }}; const be_ctypes_structure_t be_lv_style_transition_dsc = { @@ -600,9 +367,10 @@ const be_ctypes_structure_t be_lv_color_filter_dsc = { const be_ctypes_structure_t be_lv_timer_ntv = { 24, /* size in bytes */ - 6, /* number of elements */ + 7, /* number of elements */ be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[6]) { + (const be_ctypes_structure_item_t[7]) { + { "auto_delete", 20, 1, 1, ctypes_bf, 0 }, { "last_run", 4, 0, 0, ctypes_u32, 0 }, { "paused", 20, 0, 1, ctypes_bf, 0 }, { "period", 0, 0, 0, ctypes_u32, 0 }, @@ -611,212 +379,91 @@ const be_ctypes_structure_t be_lv_timer_ntv = { { "user_data", 12, 0, 0, ctypes_ptr32, 0 }, }}; -const be_ctypes_structure_t be_lv_anim_ntv = { - 72, /* size in bytes */ - 21, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[21]) { - { "act_time", 48, 0, 0, ctypes_i32, 0 }, - { "current_value", 36, 0, 0, ctypes_i32, 0 }, - { "deleted_cb", 16, 0, 0, ctypes_ptr32, 0 }, - { "early_apply", 68, 0, 1, ctypes_bf, 0 }, - { "end_value", 40, 0, 0, ctypes_i32, 0 }, - { "exec_cb", 4, 0, 0, ctypes_ptr32, 0 }, - { "get_value_cb", 20, 0, 0, ctypes_ptr32, 0 }, - { "path_cb", 28, 0, 0, ctypes_ptr32, 0 }, - { "playback_delay", 52, 0, 0, ctypes_u32, 0 }, - { "playback_now", 68, 1, 1, ctypes_bf, 0 }, - { "playback_time", 56, 0, 0, ctypes_u32, 0 }, - { "ready_cb", 12, 0, 0, ctypes_ptr32, 0 }, - { "repeat_cnt", 64, 0, 0, ctypes_u32, 0 }, - { "repeat_delay", 60, 0, 0, ctypes_u32, 0 }, - { "run_round", 68, 2, 1, ctypes_bf, 0 }, - { "start_cb", 8, 0, 0, ctypes_ptr32, 0 }, - { "start_cb_called", 68, 3, 1, ctypes_bf, 0 }, - { "start_value", 32, 0, 0, ctypes_i32, 0 }, - { "time", 44, 0, 0, ctypes_i32, 0 }, - { "user_data", 24, 0, 0, ctypes_ptr32, 0 }, - { "var", 0, 0, 0, ctypes_ptr32, 0 }, -}}; - -const be_ctypes_structure_t be_lv_draw_ctx = { - 88, /* size in bytes */ - 26, /* number of elements */ - be_ctypes_instance_mappings, - (const be_ctypes_structure_item_t[26]) { - { "buf", 0, 0, 0, ctypes_ptr32, 0 }, - { "buf_area_x1", 4, 0, 0, ctypes_i16, 0 }, - { "buf_area_x2", 8, 0, 0, ctypes_i16, 0 }, - { "buf_area_y1", 6, 0, 0, ctypes_i16, 0 }, - { "buf_area_y2", 10, 0, 0, ctypes_i16, 0 }, - { "buffer_copy", 60, 0, 0, ctypes_ptr32, 0 }, - { "clip_area_x1", 12, 0, 0, ctypes_i16, 0 }, - { "clip_area_x2", 16, 0, 0, ctypes_i16, 0 }, - { "clip_area_y1", 14, 0, 0, ctypes_i16, 0 }, - { "clip_area_y2", 18, 0, 0, ctypes_i16, 0 }, - { "draw_arc", 24, 0, 0, ctypes_ptr32, 0 }, - { "draw_bg", 52, 0, 0, ctypes_ptr32, 0 }, - { "draw_img", 32, 0, 0, ctypes_ptr32, 0 }, - { "draw_img_decoded", 28, 0, 0, ctypes_ptr32, 0 }, - { "draw_letter", 36, 0, 0, ctypes_ptr32, 0 }, - { "draw_line", 40, 0, 0, ctypes_ptr32, 0 }, - { "draw_polygon", 44, 0, 0, ctypes_ptr32, 0 }, - { "draw_rect", 20, 0, 0, ctypes_ptr32, 0 }, - { "draw_transform", 48, 0, 0, ctypes_ptr32, 0 }, - { "layer_adjust", 68, 0, 0, ctypes_ptr32, 0 }, - { "layer_blend", 72, 0, 0, ctypes_ptr32, 0 }, - { "layer_destroy", 76, 0, 0, ctypes_ptr32, 0 }, - { "layer_init", 64, 0, 0, ctypes_ptr32, 0 }, - { "layer_instance_size", 80, 0, 0, ctypes_u32, 0 }, - { "user_data", 84, 0, 0, ctypes_ptr32, 0 }, - { "wait_for_finish", 56, 0, 0, ctypes_ptr32, 0 }, -}}; - const be_ctypes_structure_t be_lv_ts_calibration = { - 12, /* size in bytes */ + 20, /* size in bytes */ 5, /* number of elements */ be_ctypes_instance_mappings, (const be_ctypes_structure_item_t[5]) { - { "raw_x", 0, 0, 0, ctypes_i16, 0 }, - { "raw_y", 2, 0, 0, ctypes_i16, 0 }, - { "state", 8, 0, 0, ctypes_i32, 0 }, - { "x", 4, 0, 0, ctypes_i16, 0 }, - { "y", 6, 0, 0, ctypes_i16, 0 }, + { "raw_x", 0, 0, 0, ctypes_i32, 0 }, + { "raw_y", 4, 0, 0, ctypes_i32, 0 }, + { "state", 16, 0, 0, ctypes_i32, 0 }, + { "x", 8, 0, 0, ctypes_i32, 0 }, + { "y", 12, 0, 0, ctypes_i32, 0 }, }}; static const char * be_ctypes_instance_mappings[] = { - "lv_color", + "lv.color", NULL }; -static be_define_ctypes_class(lv_anim_ntv, &be_lv_anim_ntv, &be_class_ctypes_bytes, "lv_anim_ntv"); static be_define_ctypes_class(lv_area, &be_lv_area, &be_class_ctypes_bytes, "lv_area"); static be_define_ctypes_class(lv_chart_cursor, &be_lv_chart_cursor, &be_class_ctypes_bytes, "lv_chart_cursor"); static be_define_ctypes_class(lv_chart_series, &be_lv_chart_series, &be_class_ctypes_bytes, "lv_chart_series"); -static be_define_ctypes_class(lv_chart_tick_dsc, &be_lv_chart_tick_dsc, &be_class_ctypes_bytes, "lv_chart_tick_dsc"); static be_define_ctypes_class(lv_color_filter_dsc, &be_lv_color_filter_dsc, &be_class_ctypes_bytes, "lv_color_filter_dsc"); -static be_define_ctypes_class(lv_coord, &be_lv_coord, &be_class_ctypes_bytes, "lv_coord"); static be_define_ctypes_class(lv_draw_arc_dsc, &be_lv_draw_arc_dsc, &be_class_ctypes_bytes, "lv_draw_arc_dsc"); -static be_define_ctypes_class(lv_draw_ctx, &be_lv_draw_ctx, &be_class_ctypes_bytes, "lv_draw_ctx"); -static be_define_ctypes_class(lv_draw_img_dsc, &be_lv_draw_img_dsc, &be_class_ctypes_bytes, "lv_draw_img_dsc"); -static be_define_ctypes_class(lv_draw_layer_ctx, &be_lv_draw_layer_ctx, &be_class_ctypes_bytes, "lv_draw_layer_ctx"); +static be_define_ctypes_class(lv_draw_dsc_base, &be_lv_draw_dsc_base, &be_class_ctypes_bytes, "lv_draw_dsc_base"); +static be_define_ctypes_class(lv_draw_image_dsc, &be_lv_draw_image_dsc, &be_class_ctypes_bytes, "lv_draw_image_dsc"); static be_define_ctypes_class(lv_draw_line_dsc, &be_lv_draw_line_dsc, &be_class_ctypes_bytes, "lv_draw_line_dsc"); -static be_define_ctypes_class(lv_draw_mask_angle_param, &be_lv_draw_mask_angle_param, &be_class_ctypes_bytes, "lv_draw_mask_angle_param"); -static be_define_ctypes_class(lv_draw_mask_angle_param_cfg, &be_lv_draw_mask_angle_param_cfg, &be_class_ctypes_bytes, "lv_draw_mask_angle_param_cfg"); -static be_define_ctypes_class(lv_draw_mask_common_dsc, &be_lv_draw_mask_common_dsc, &be_class_ctypes_bytes, "lv_draw_mask_common_dsc"); -static be_define_ctypes_class(lv_draw_mask_fade_param, &be_lv_draw_mask_fade_param, &be_class_ctypes_bytes, "lv_draw_mask_fade_param"); -static be_define_ctypes_class(lv_draw_mask_fade_param_cfg, &be_lv_draw_mask_fade_param_cfg, &be_class_ctypes_bytes, "lv_draw_mask_fade_param_cfg"); -static be_define_ctypes_class(lv_draw_mask_line_param, &be_lv_draw_mask_line_param, &be_class_ctypes_bytes, "lv_draw_mask_line_param"); -static be_define_ctypes_class(lv_draw_mask_line_param_cfg, &be_lv_draw_mask_line_param_cfg, &be_class_ctypes_bytes, "lv_draw_mask_line_param_cfg"); -static be_define_ctypes_class(lv_draw_mask_map_param, &be_lv_draw_mask_map_param, &be_class_ctypes_bytes, "lv_draw_mask_map_param"); -static be_define_ctypes_class(lv_draw_mask_map_param_cfg, &be_lv_draw_mask_map_param_cfg, &be_class_ctypes_bytes, "lv_draw_mask_map_param_cfg"); -static be_define_ctypes_class(lv_draw_mask_polygon_param, &be_lv_draw_mask_polygon_param, &be_class_ctypes_bytes, "lv_draw_mask_polygon_param"); -static be_define_ctypes_class(lv_draw_mask_polygon_param_cfg, &be_lv_draw_mask_polygon_param_cfg, &be_class_ctypes_bytes, "lv_draw_mask_polygon_param_cfg"); -static be_define_ctypes_class(lv_draw_mask_radius_circle_dsc, &be_lv_draw_mask_radius_circle_dsc, &be_class_ctypes_bytes, "lv_draw_mask_radius_circle_dsc"); -static be_define_ctypes_class(lv_draw_mask_radius_param, &be_lv_draw_mask_radius_param, &be_class_ctypes_bytes, "lv_draw_mask_radius_param"); -static be_define_ctypes_class(lv_draw_mask_radius_param_cfg, &be_lv_draw_mask_radius_param_cfg, &be_class_ctypes_bytes, "lv_draw_mask_radius_param_cfg"); -static be_define_ctypes_class(lv_draw_mask_saved, &be_lv_draw_mask_saved, &be_class_ctypes_bytes, "lv_draw_mask_saved"); static be_define_ctypes_class(lv_draw_rect_dsc, &be_lv_draw_rect_dsc, &be_class_ctypes_bytes, "lv_draw_rect_dsc"); static be_define_ctypes_class(lv_event, &be_lv_event, &be_class_ctypes_bytes, "lv_event"); static be_define_ctypes_class(lv_grad_dsc, &be_lv_grad_dsc, &be_class_ctypes_bytes, "lv_grad_dsc"); static be_define_ctypes_class(lv_gradient_stop, &be_lv_gradient_stop, &be_class_ctypes_bytes, "lv_gradient_stop"); -static be_define_ctypes_class(lv_img_dsc, &be_lv_img_dsc, &be_class_ctypes_bytes, "lv_img_dsc"); -static be_define_ctypes_class(lv_img_header, &be_lv_img_header, &be_class_ctypes_bytes, "lv_img_header"); +static be_define_ctypes_class(lv_image_dsc, &be_lv_image_dsc, &be_class_ctypes_bytes, "lv_image_dsc"); +static be_define_ctypes_class(lv_image_header, &be_lv_image_header, &be_class_ctypes_bytes, "lv_image_header"); static be_define_ctypes_class(lv_meter_indicator, &be_lv_meter_indicator, &be_class_ctypes_bytes, "lv_meter_indicator"); static be_define_ctypes_class(lv_meter_scale, &be_lv_meter_scale, &be_class_ctypes_bytes, "lv_meter_scale"); static be_define_ctypes_class(lv_obj_class, &be_lv_obj_class, &be_class_ctypes_bytes, "lv_obj_class"); -static be_define_ctypes_class(lv_obj_draw_part_dsc, &be_lv_obj_draw_part_dsc, &be_class_ctypes_bytes, "lv_obj_draw_part_dsc"); static be_define_ctypes_class(lv_point, &be_lv_point, &be_class_ctypes_bytes, "lv_point"); -static be_define_ctypes_class(lv_sqrt_res, &be_lv_sqrt_res, &be_class_ctypes_bytes, "lv_sqrt_res"); +static be_define_ctypes_class(lv_point_precise, &be_lv_point_precise, &be_class_ctypes_bytes, "lv_point_precise"); static be_define_ctypes_class(lv_style_transition_dsc, &be_lv_style_transition_dsc, &be_class_ctypes_bytes, "lv_style_transition_dsc"); static be_define_ctypes_class(lv_timer_ntv, &be_lv_timer_ntv, &be_class_ctypes_bytes, "lv_timer_ntv"); static be_define_ctypes_class(lv_ts_calibration, &be_lv_ts_calibration, &be_class_ctypes_bytes, "lv_ts_calibration"); void be_load_ctypes_lvgl_definitions_lib(bvm *vm) { - ctypes_register_class(vm, &be_class_lv_anim_ntv); ctypes_register_class(vm, &be_class_lv_area); ctypes_register_class(vm, &be_class_lv_chart_cursor); ctypes_register_class(vm, &be_class_lv_chart_series); - ctypes_register_class(vm, &be_class_lv_chart_tick_dsc); ctypes_register_class(vm, &be_class_lv_color_filter_dsc); - ctypes_register_class(vm, &be_class_lv_coord); ctypes_register_class(vm, &be_class_lv_draw_arc_dsc); - ctypes_register_class(vm, &be_class_lv_draw_ctx); - ctypes_register_class(vm, &be_class_lv_draw_img_dsc); - ctypes_register_class(vm, &be_class_lv_draw_layer_ctx); + ctypes_register_class(vm, &be_class_lv_draw_dsc_base); + ctypes_register_class(vm, &be_class_lv_draw_image_dsc); ctypes_register_class(vm, &be_class_lv_draw_line_dsc); - ctypes_register_class(vm, &be_class_lv_draw_mask_angle_param); - ctypes_register_class(vm, &be_class_lv_draw_mask_angle_param_cfg); - ctypes_register_class(vm, &be_class_lv_draw_mask_common_dsc); - ctypes_register_class(vm, &be_class_lv_draw_mask_fade_param); - ctypes_register_class(vm, &be_class_lv_draw_mask_fade_param_cfg); - ctypes_register_class(vm, &be_class_lv_draw_mask_line_param); - ctypes_register_class(vm, &be_class_lv_draw_mask_line_param_cfg); - ctypes_register_class(vm, &be_class_lv_draw_mask_map_param); - ctypes_register_class(vm, &be_class_lv_draw_mask_map_param_cfg); - ctypes_register_class(vm, &be_class_lv_draw_mask_polygon_param); - ctypes_register_class(vm, &be_class_lv_draw_mask_polygon_param_cfg); - ctypes_register_class(vm, &be_class_lv_draw_mask_radius_circle_dsc); - ctypes_register_class(vm, &be_class_lv_draw_mask_radius_param); - ctypes_register_class(vm, &be_class_lv_draw_mask_radius_param_cfg); - ctypes_register_class(vm, &be_class_lv_draw_mask_saved); ctypes_register_class(vm, &be_class_lv_draw_rect_dsc); ctypes_register_class(vm, &be_class_lv_event); ctypes_register_class(vm, &be_class_lv_grad_dsc); ctypes_register_class(vm, &be_class_lv_gradient_stop); - ctypes_register_class(vm, &be_class_lv_img_dsc); - ctypes_register_class(vm, &be_class_lv_img_header); + ctypes_register_class(vm, &be_class_lv_image_dsc); + ctypes_register_class(vm, &be_class_lv_image_header); ctypes_register_class(vm, &be_class_lv_meter_indicator); ctypes_register_class(vm, &be_class_lv_meter_scale); ctypes_register_class(vm, &be_class_lv_obj_class); - ctypes_register_class(vm, &be_class_lv_obj_draw_part_dsc); ctypes_register_class(vm, &be_class_lv_point); - ctypes_register_class(vm, &be_class_lv_sqrt_res); + ctypes_register_class(vm, &be_class_lv_point_precise); ctypes_register_class(vm, &be_class_lv_style_transition_dsc); ctypes_register_class(vm, &be_class_lv_timer_ntv); ctypes_register_class(vm, &be_class_lv_ts_calibration); } be_ctypes_class_by_name_t be_ctypes_lvgl_classes[] = { - { "lv_anim_ntv", &be_class_lv_anim_ntv }, { "lv_area", &be_class_lv_area }, { "lv_chart_cursor", &be_class_lv_chart_cursor }, { "lv_chart_series", &be_class_lv_chart_series }, - { "lv_chart_tick_dsc", &be_class_lv_chart_tick_dsc }, { "lv_color_filter_dsc", &be_class_lv_color_filter_dsc }, - { "lv_coord", &be_class_lv_coord }, { "lv_draw_arc_dsc", &be_class_lv_draw_arc_dsc }, - { "lv_draw_ctx", &be_class_lv_draw_ctx }, - { "lv_draw_img_dsc", &be_class_lv_draw_img_dsc }, - { "lv_draw_layer_ctx", &be_class_lv_draw_layer_ctx }, + { "lv_draw_dsc_base", &be_class_lv_draw_dsc_base }, + { "lv_draw_image_dsc", &be_class_lv_draw_image_dsc }, { "lv_draw_line_dsc", &be_class_lv_draw_line_dsc }, - { "lv_draw_mask_angle_param", &be_class_lv_draw_mask_angle_param }, - { "lv_draw_mask_angle_param_cfg", &be_class_lv_draw_mask_angle_param_cfg }, - { "lv_draw_mask_common_dsc", &be_class_lv_draw_mask_common_dsc }, - { "lv_draw_mask_fade_param", &be_class_lv_draw_mask_fade_param }, - { "lv_draw_mask_fade_param_cfg", &be_class_lv_draw_mask_fade_param_cfg }, - { "lv_draw_mask_line_param", &be_class_lv_draw_mask_line_param }, - { "lv_draw_mask_line_param_cfg", &be_class_lv_draw_mask_line_param_cfg }, - { "lv_draw_mask_map_param", &be_class_lv_draw_mask_map_param }, - { "lv_draw_mask_map_param_cfg", &be_class_lv_draw_mask_map_param_cfg }, - { "lv_draw_mask_polygon_param", &be_class_lv_draw_mask_polygon_param }, - { "lv_draw_mask_polygon_param_cfg", &be_class_lv_draw_mask_polygon_param_cfg }, - { "lv_draw_mask_radius_circle_dsc", &be_class_lv_draw_mask_radius_circle_dsc }, - { "lv_draw_mask_radius_param", &be_class_lv_draw_mask_radius_param }, - { "lv_draw_mask_radius_param_cfg", &be_class_lv_draw_mask_radius_param_cfg }, - { "lv_draw_mask_saved", &be_class_lv_draw_mask_saved }, { "lv_draw_rect_dsc", &be_class_lv_draw_rect_dsc }, { "lv_event", &be_class_lv_event }, { "lv_grad_dsc", &be_class_lv_grad_dsc }, { "lv_gradient_stop", &be_class_lv_gradient_stop }, - { "lv_img_dsc", &be_class_lv_img_dsc }, - { "lv_img_header", &be_class_lv_img_header }, + { "lv_image_dsc", &be_class_lv_image_dsc }, + { "lv_image_header", &be_class_lv_image_header }, { "lv_meter_indicator", &be_class_lv_meter_indicator }, { "lv_meter_scale", &be_class_lv_meter_scale }, { "lv_obj_class", &be_class_lv_obj_class }, - { "lv_obj_draw_part_dsc", &be_class_lv_obj_draw_part_dsc }, { "lv_point", &be_class_lv_point }, - { "lv_sqrt_res", &be_class_lv_sqrt_res }, + { "lv_point_precise", &be_class_lv_point_precise }, { "lv_style_transition_dsc", &be_class_lv_style_transition_dsc }, { "lv_timer_ntv", &be_class_lv_timer_ntv }, { "lv_ts_calibration", &be_class_lv_ts_calibration }, diff --git a/lib/libesp32_lvgl/lv_binding_berry/src/embedded/berry_ctypes.py b/lib/libesp32_lvgl/lv_binding_berry/src/embedded/berry_ctypes.py index 789267cd6..c1cd83133 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/src/embedded/berry_ctypes.py +++ b/lib/libesp32_lvgl/lv_binding_berry/src/embedded/berry_ctypes.py @@ -69,25 +69,31 @@ types = { # default is little_endian i32 = 14 +i24 = 13 i16 = 12 i8 = 11 u32 = 4 +u24 = 3 u16 = 2 u8 = 1 # explicit little endian le_i32 = 14 +le_i24 = 13 le_i16 = 12 le_i8 = 11 le_u32 = 4 +le_u24 = 3 le_u16 = 2 le_u8 = 1 # big endian be_i32 = -14 +be_i26 = -13 be_i16 = -12 be_i8 = -11 be_u32 = -4 +be_u24 = -3 be_u16 = -2 be_u8 = -1 @@ -121,16 +127,20 @@ bf_16 = 116 type_mapping = { 14: "ctypes_i32", + 13: "ctypes_i24", 12: "ctypes_i16", 11: "ctypes_i8", 4: "ctypes_u32", + 3: "ctypes_u24", 2: "ctypes_u16", 1: "ctypes_u8", -14:"ctypes_be_i32", # big endian + -13:"ctypes_be_i24", -12:"ctypes_be_i16", -11:"ctypes_be_i8", -4: "ctypes_be_u32", + -3: "ctypes_be_u24", -2: "ctypes_be_u16", -1: "ctypes_be_u8", @@ -300,8 +310,9 @@ class structure: #- ensure alignment to 1/2/4 bytes -# def align(self, n): + if n == 3: n = 4 # 3 bytes are aligned to 4 byest boundaries if n != 1 and n != 2 and n != 4: - raise Exception("acceptable values are 1/2/4") + raise Exception(f"acceptable values are 1/2/3/4 {n=}") #- align to byte boundary if we're in a bitfield -# if self.bit_offset != 0: diff --git a/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lv.be b/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lv.be index 83aab911c..4a5de5759 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lv.be +++ b/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lv.be @@ -17,5 +17,12 @@ def lv_module_init(lv_solidified) var lv_new = module("lv") # create a dynamic module lv_new.member = lv_solidified.member # lv_new.lv_solidified = lv_solidified + + # add mapping from LVGL 8 legacy names and LVGL 9 + lv_new.scr_act = lv_solidified.screen_active + lv_new.img = lv_solidified.image + lv_new.disp = lv_solidified.display + lv_new.btn = lv_solidified.button + lv_new.btnmatrix = lv_solidified.buttonmatrix return lv_new end diff --git a/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lvgl_ctypes.py b/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lvgl_ctypes.py index a6649f7fe..f511b1425 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lvgl_ctypes.py +++ b/lib/libesp32_lvgl/lv_binding_berry/src/embedded/lvgl_ctypes.py @@ -17,13 +17,12 @@ print("""/******************************************************************** ct.print_types() lv_style_int = ct.i16 -lv_color = [ct.u16, "lv_color"] # cast to the class instance, constructor is called with 2 args: (nil, value) +lv_color = [ct.u24, "lv.color"] # cast to the class instance, constructor is called with 2 args: (nil, value) lv_grad_dir = ct.u8 lv_meter_indicator_type_t = ct.u8 lv_opa = ct.u8 lv_blend_mode = ct.u8 lv_align = ct.u8 -lv_coord_t = ct.i16 lv_bidi_dir = ct.u8 lv_txt_flag = ct.u8 lv_text_decor = ct.u8 @@ -31,6 +30,8 @@ lv_font = ct.u32 lv_blend_mode = ct.u8 lv_draw_mask_line_side = ct.u8 lv_dir = ct.u8 +lv_coord_t = ct.i32 +lv_value_precise = ct.i32 uint8_t_1 = ct.bf_1 uint8_t_2 = ct.bf_2 uint8_t_3 = ct.bf_3 @@ -44,47 +45,125 @@ uint16_t_15 = ct.bf_15 uint16_t_16 = ct.bf_16 uint32_t = ct.u32 int32_t = ct.i32 +size_t = ct.u32 ptr = ct.ptr32 -lv_coord = [ # valid LVGL8.3 - [lv_coord_t, "v"], -] -lv_coord = ct.structure(lv_coord, "lv_coord") - -lv_point = [ # valid LVGL8.3 - [lv_coord_t, "x"], - [lv_coord_t, "y"], +lv_point = [ # valid LVGL9 + [int32_t, "x"], + [int32_t, "y"], ] lv_point = ct.structure(lv_point, "lv_point") -lv_area = [ # valid LVGL8.3 - [lv_coord_t, "x1"], - [lv_coord_t, "y1"], - [lv_coord_t, "x2"], - [lv_coord_t, "y2"], +# typedef struct { +# lv_value_precise_t x; +# lv_value_precise_t y; +# } lv_point_precise_t; +lv_point_precise = [ # valid LVGL9 + [lv_value_precise, "x"], + [lv_value_precise, "y"], +] +lv_point_precise = ct.structure(lv_point_precise, "lv_point_precise") + +lv_area = [ # valid LVGL9 + [int32_t, "x1"], + [int32_t, "y1"], + [int32_t, "x2"], + [int32_t, "y2"], ] lv_area = ct.structure(lv_area, "lv_area") ####################################################################### -# lv_grad_dsc -lv_gradient_stop = [ # valid LVGL8.3 +# +# typedef struct { +# lv_color_t color; /**< The stop color */ +# lv_opa_t opa; /**< The opacity of the color*/ +# uint8_t frac; /**< The stop position in 1/255 unit */ +# } lv_gradient_stop_t; +lv_gradient_stop = [ # valid LVGL9 [lv_color, "color"], + [lv_opa, "opa"], [uint8_t, "frac"], ] lv_gradient_stop = ct.structure(lv_gradient_stop, "lv_gradient_stop") -lv_grad_dsc = [ # valid LVGL8.3 +# typedef struct { +# lv_gradient_stop_t stops[LV_GRADIENT_MAX_STOPS]; /**< A gradient stop array */ +# uint8_t stops_count; /**< The number of used stops in the array */ +# lv_grad_dir_t dir : 3; /**< The gradient direction. +# * Any of LV_GRAD_DIR_HOR, LV_GRAD_DIR_VER, LV_GRAD_DIR_NONE */ +# } lv_grad_dsc_t; +lv_grad_dsc = [ # valid LVGL9 [lv_gradient_stop, "stops_0"], [lv_gradient_stop, "stops_1"], [uint8_t, "stops_count"], [uint8_t_3, "dir"], - [uint8_t_3, "dither"], ] lv_grad_dsc = ct.structure(lv_grad_dsc, "lv_grad_dsc") -lv_draw_rect_dsc = [ # valid LVGL8.3 - [lv_coord_t, "radius"], - [lv_blend_mode, "blend_mode"], + +# typedef struct { +# lv_obj_t * obj; +# uint32_t part; +# uint32_t id1; +# uint32_t id2; +# lv_layer_t * layer; +# size_t dsc_size; +# void * user_data; +# } lv_draw_dsc_base_t; +lv_draw_dsc_base = [ # valid LVGL9 + [ptr, "obj"], + [uint32_t, "part"], + [uint32_t, "id1"], + [uint32_t, "id2"], + [ptr, "layer"], + [size_t, "dsc_size"], + [ptr, "user_data"], +] +lv_draw_dsc_base = ct.structure(lv_draw_dsc_base, "lv_draw_dsc_base") + +# typedef struct { +# lv_draw_dsc_base_t base; + +# int32_t radius; + +# /*Background*/ +# lv_opa_t bg_opa; +# lv_color_t bg_color; /**< First element of a gradient is a color, so it maps well here*/ +# lv_grad_dsc_t bg_grad; + +# /*Background img*/ +# const void * bg_image_src; +# const void * bg_image_symbol_font; +# lv_color_t bg_image_recolor; +# lv_opa_t bg_image_opa; +# lv_opa_t bg_image_recolor_opa; +# uint8_t bg_image_tiled; + +# /*Border*/ +# lv_color_t border_color; +# int32_t border_width; +# lv_opa_t border_opa; +# lv_border_side_t border_side : 5; +# uint8_t border_post : 1; /*The border will be drawn later*/ + +# /*Outline*/ +# lv_color_t outline_color; +# int32_t outline_width; +# int32_t outline_pad; +# lv_opa_t outline_opa; + +# /*Shadow*/ +# lv_color_t shadow_color; +# int32_t shadow_width; +# int32_t shadow_offset_x; +# int32_t shadow_offset_y; +# int32_t shadow_spread; +# lv_opa_t shadow_opa; +# } lv_draw_rect_dsc_t; +lv_draw_rect_dsc = [ # valid LVGL9 + [lv_draw_dsc_base, "base"], + + [int32_t, "radius"], #/*Background*/ [lv_opa, "bg_opa"], @@ -101,32 +180,51 @@ lv_draw_rect_dsc = [ # valid LVGL8.3 #/*Border*/ [lv_color, "border_color"], - [lv_coord_t, "border_width"], + [int32_t, "border_width"], [lv_opa, "border_opa"], [uint8_t_1, "border_post"], [uint8_t_5, "border_side"], #/*Outline*/ [lv_color, "outline_color"], - [lv_coord_t, "outline_width"], - [lv_coord_t, "outline_pad"], + [int32_t, "outline_width"], + [int32_t, "outline_pad"], [lv_opa, "outline_opa"], #/*Shadow*/ [lv_color, "shadow_color"], - [lv_coord_t, "shadow_width"], - [lv_coord_t, "shadow_ofs_x"], - [lv_coord_t, "shadow_ofs_y"], - [lv_coord_t, "shadow_spread"], + [int32_t, "shadow_width"], + [int32_t, "shadow_ofs_x"], + [int32_t, "shadow_ofs_y"], + [int32_t, "shadow_spread"], [lv_opa, "shadow_opa"], ] lv_draw_rect_dsc = ct.structure(lv_draw_rect_dsc, "lv_draw_rect_dsc") -lv_draw_line_dsc = [ # valid LVGL8.3 +# typedef struct { +# lv_draw_dsc_base_t base; + +# lv_point_precise_t p1; +# lv_point_precise_t p2; +# lv_color_t color; +# int32_t width; +# int32_t dash_width; +# int32_t dash_gap; +# lv_opa_t opa; +# lv_blend_mode_t blend_mode : 2; +# uint8_t round_start : 1; +# uint8_t round_end : 1; +# uint8_t raw_end : 1; /*Do not bother with perpendicular line ending if it's not visible for any reason*/ +# } lv_draw_line_dsc_t; +lv_draw_line_dsc = [ # valid LVGL9 + [lv_draw_dsc_base, "base"], + + [lv_point_precise, "p1"], + [lv_point_precise, "p2"], [lv_color, "color"], - [lv_coord_t, "width"], - [lv_coord_t, "dash_width"], - [lv_coord_t, "dash_gap"], + [int32_t, "width"], + [int32_t, "dash_width"], + [int32_t, "dash_gap"], [lv_opa, "opa"], [uint8_t_2, "blend_mode"], [uint8_t_1, "round_start"], @@ -135,21 +233,92 @@ lv_draw_line_dsc = [ # valid LVGL8.3 ] lv_draw_line_dsc = ct.structure(lv_draw_line_dsc, "lv_draw_line_dsc") +# typedef struct { +# lv_draw_dsc_base_t base; + +# lv_color_t color; +# int32_t width; +# lv_value_precise_t start_angle; +# lv_value_precise_t end_angle; +# lv_point_t center; +# uint16_t radius; +# const void * img_src; +# lv_opa_t opa; +# uint8_t rounded : 1; +# } lv_draw_arc_dsc_t; lv_draw_arc_dsc = [ # valid LVGL8.3 + [lv_draw_dsc_base, "base"], + [lv_color, "color"], - [lv_coord_t, "width"], - [uint16_t, "start_angle"], - [uint16_t, "end_angle"], + [int32_t, "width"], + [lv_value_precise, "start_angle"], + [lv_value_precise, "end_angle"], + [lv_point, "center"], + [uint16_t, "radius"], [ptr, "img_src"], [lv_opa, "opa"], - [uint8_t_2, "blend_mode"], [uint8_t_1, "rounded"], ] lv_draw_arc_dsc = ct.structure(lv_draw_arc_dsc, "lv_draw_arc_dsc") -lv_draw_img_dsc = [ # valid LVGL8.3 - [int16_t, "angle"], - [uint16_t, "zoom"], + +# typedef struct { +# uint32_t magic: 8; /*Magic number. Must be LV_IMAGE_HEADER_MAGIC*/ +# uint32_t cf : 8; /*Color format: See `lv_color_format_t`*/ +# uint32_t flags: 16; /*Image flags, see `lv_image_flags_t`*/ + +# uint32_t w: 16; +# uint32_t h: 16; +# uint32_t stride: 16; /*Number of bytes in a row*/ +# uint32_t reserved_2: 16; /*Reserved to be used later*/ +# } lv_image_header_t; + +lv_image_header = [ # valid LVGL9 + [uint8_t, "magic"], + [uint8_t, "cf"], + [uint16_t, "flags"], + + [uint16_t, "w"], + [uint16_t, "h"], + [uint16_t, "stride"], + [uint16_t, "reserved_2"], +] +lv_image_header = ct.structure(lv_image_header, "lv_image_header") + +# typedef struct _lv_draw_image_dsc_t { +# lv_draw_dsc_base_t base; + +# const void * src; +# lv_image_header_t header; + +# int32_t rotation; +# int32_t scale_x; +# int32_t scale_y; +# int32_t skew_x; +# int32_t skew_y; +# lv_point_t pivot; + +# lv_color_t recolor; +# lv_opa_t recolor_opa; + +# lv_opa_t opa; +# lv_blend_mode_t blend_mode : 4; + +# uint16_t antialias : 1; +# uint16_t tile : 1; +# lv_draw_image_sup_t * sup; +# } lv_draw_image_dsc_t; +lv_draw_image_dsc = [ # valid LVGL9 + [lv_draw_dsc_base, "base"], + + [ptr, "src"], + [lv_image_header, "header"], + + [int32_t, "rotation"], + [int32_t, "scale_x"], + [int32_t, "scale_y"], + [int32_t, "skew_x"], + [int32_t, "skew_y"], [lv_point, "pivot"], [lv_color, "recolor"], @@ -157,186 +326,186 @@ lv_draw_img_dsc = [ # valid LVGL8.3 [lv_opa, "opa"], [uint8_t_4, "blend_mode"], - - [int32_t, "frame_id"], [uint8_t_1, "antialias"], + [uint8_t_1, "tile"], + [ptr, "sup"], ] -lv_draw_img_dsc = ct.structure(lv_draw_img_dsc, "lv_draw_img_dsc") +lv_draw_image_dsc = ct.structure(lv_draw_image_dsc, "lv_draw_image_dsc") -lv_obj_draw_part_dsc = [ # valid LVGL8.3 - [ptr, "draw_ctx"], - [ptr, "class_p"], - [uint32_t, "type"], - [ptr, "draw_area"], - [ptr, "rect_dsc"], - [ptr, "label_dsc"], - [ptr, "line_dsc"], - [ptr, "img_dsc"], - [ptr, "arc_dsc"], - [ptr, "p1"], - [ptr, "p2"], - [ptr, "text"], - [uint32_t, "text_length"], - [uint32_t, "part"], - [uint32_t, "id"], - [lv_coord_t, "radius"], - [int32_t, "value"], - [ptr, "sub_part_ptr"], -] -lv_obj_draw_part_dsc = ct.structure(lv_obj_draw_part_dsc, "lv_obj_draw_part_dsc") +# lv_obj_draw_part_dsc = [ # valid LVGL8.3 +# [ptr, "draw_ctx"], +# [ptr, "class_p"], +# [uint32_t, "type"], +# [ptr, "draw_area"], +# [ptr, "rect_dsc"], +# [ptr, "label_dsc"], +# [ptr, "line_dsc"], +# [ptr, "img_dsc"], +# [ptr, "arc_dsc"], +# [ptr, "p1"], +# [ptr, "p2"], +# [ptr, "text"], +# [uint32_t, "text_length"], +# [uint32_t, "part"], +# [uint32_t, "id"], +# [lv_coord_t, "radius"], +# [int32_t, "value"], +# [ptr, "sub_part_ptr"], +# ] +# lv_obj_draw_part_dsc = ct.structure(lv_obj_draw_part_dsc, "lv_obj_draw_part_dsc") -lv_draw_layer_ctx = [ # valid LVGL8.3 - [lv_area, "area_full"], - [lv_area, "area_act"], - [lv_coord_t, "max_row_with_alpha"], - [lv_coord_t, "max_row_with_no_alpha"], - [ptr, "buf"], - [ptr, "clip_area"], - [ptr, "buf_area"], - [ptr, "buf"], - [uint8_t, "screen_transp"], -] -lv_draw_layer_ctx = ct.structure(lv_draw_layer_ctx, "lv_draw_layer_ctx") +# lv_draw_layer_ctx = [ # valid LVGL8.3 +# [lv_area, "area_full"], +# [lv_area, "area_act"], +# [lv_coord_t, "max_row_with_alpha"], +# [lv_coord_t, "max_row_with_no_alpha"], +# [ptr, "buf"], +# [ptr, "clip_area"], +# [ptr, "buf_area"], +# [ptr, "buf"], +# [uint8_t, "screen_transp"], +# ] +# lv_draw_layer_ctx = ct.structure(lv_draw_layer_ctx, "lv_draw_layer_ctx") #- --------- lv_mask --------- -# -lv_draw_mask_xcb = ptr # callback -lv_draw_mask_type = ct.u8 -lv_draw_mask_line_side = ct.u8 +# lv_draw_mask_xcb = ptr # callback +# lv_draw_mask_type = ct.u8 +# lv_draw_mask_line_side = ct.u8 -lv_draw_mask_common_dsc = [ # valid LVGL8.3 - [lv_draw_mask_xcb, "cb"], - [lv_draw_mask_type, "type"], -] -lv_draw_mask_common_dsc = ct.structure(lv_draw_mask_common_dsc, "lv_draw_mask_common_dsc") +# lv_draw_mask_common_dsc = [ # valid LVGL8.3 +# [lv_draw_mask_xcb, "cb"], +# [lv_draw_mask_type, "type"], +# ] +# lv_draw_mask_common_dsc = ct.structure(lv_draw_mask_common_dsc, "lv_draw_mask_common_dsc") -lv_draw_mask_line_param_cfg = [ # valid LVGL8.3 - #/*First point */ - [lv_point, "p1"], +# lv_draw_mask_line_param_cfg = [ # valid LVGL8.3 +# #/*First point */ +# [lv_point, "p1"], - #/*Second point*/ - [lv_point, "p2"], +# #/*Second point*/ +# [lv_point, "p2"], - #/*Which side to keep?*/ - [uint8_t_2, "side"], -] -lv_draw_mask_line_param_cfg = ct.structure(lv_draw_mask_line_param_cfg, "lv_draw_mask_line_param_cfg") +# #/*Which side to keep?*/ +# [uint8_t_2, "side"], +# ] +# lv_draw_mask_line_param_cfg = ct.structure(lv_draw_mask_line_param_cfg, "lv_draw_mask_line_param_cfg") -lv_draw_mask_line_param = [ # valid LVGL8.3 - #/*The first element must be the common descriptor*/ - [lv_draw_mask_common_dsc, "dsc"], - [lv_draw_mask_line_param_cfg, "cfg"], - #/*A point of the line*/ - [lv_point, "origo"], - #/* X / (1024*Y) steepness (X is 0..1023 range). What is the change of X in 1024 Y?*/ - [int32_t, "xy_steep"], - #/* Y / (1024*X) steepness (Y is 0..1023 range). What is the change of Y in 1024 X?*/ - [int32_t, "yx_steep"], - #/*Helper which stores yx_steep for flat lines and xy_steep for steep (non flat) lines */ - [int32_t, "steep"], - #/*Steepness in 1 px in 0..255 range. Used only by flat lines. */ - [int32_t, "spx"], - #/*1: It's a flat line? (Near to horizontal)*/ - [uint8_t_1, "flat"], - #/* Invert the mask. The default is: Keep the left part. - # * It is used to select left/right/top/bottom*/ - [uint8_t_1, "inv"], -] -lv_draw_mask_line_param = ct.structure(lv_draw_mask_line_param, "lv_draw_mask_line_param") +# lv_draw_mask_line_param = [ # valid LVGL8.3 +# #/*The first element must be the common descriptor*/ +# [lv_draw_mask_common_dsc, "dsc"], +# [lv_draw_mask_line_param_cfg, "cfg"], +# #/*A point of the line*/ +# [lv_point, "origo"], +# #/* X / (1024*Y) steepness (X is 0..1023 range). What is the change of X in 1024 Y?*/ +# [int32_t, "xy_steep"], +# #/* Y / (1024*X) steepness (Y is 0..1023 range). What is the change of Y in 1024 X?*/ +# [int32_t, "yx_steep"], +# #/*Helper which stores yx_steep for flat lines and xy_steep for steep (non flat) lines */ +# [int32_t, "steep"], +# #/*Steepness in 1 px in 0..255 range. Used only by flat lines. */ +# [int32_t, "spx"], +# #/*1: It's a flat line? (Near to horizontal)*/ +# [uint8_t_1, "flat"], +# #/* Invert the mask. The default is: Keep the left part. +# # * It is used to select left/right/top/bottom*/ +# [uint8_t_1, "inv"], +# ] +# lv_draw_mask_line_param = ct.structure(lv_draw_mask_line_param, "lv_draw_mask_line_param") -lv_draw_mask_angle_param_cfg = [ # valid LVGL8.3 - [lv_point, "vertex_p"], - [lv_coord_t, "start_angle"], - [lv_coord_t, "end_angle"], -] -lv_draw_mask_angle_param_cfg = ct.structure(lv_draw_mask_angle_param_cfg, "lv_draw_mask_angle_param_cfg") +# lv_draw_mask_angle_param_cfg = [ # valid LVGL8.3 +# [lv_point, "vertex_p"], +# [lv_coord_t, "start_angle"], +# [lv_coord_t, "end_angle"], +# ] +# lv_draw_mask_angle_param_cfg = ct.structure(lv_draw_mask_angle_param_cfg, "lv_draw_mask_angle_param_cfg") -lv_draw_mask_angle_param = [ # valid LVGL8.3 - #/*The first element must be the common descriptor*/ - [lv_draw_mask_common_dsc, "dsc"], - [lv_draw_mask_angle_param_cfg, "cfg"], +# lv_draw_mask_angle_param = [ # valid LVGL8.3 +# #/*The first element must be the common descriptor*/ +# [lv_draw_mask_common_dsc, "dsc"], +# [lv_draw_mask_angle_param_cfg, "cfg"], - [lv_draw_mask_line_param, "start_line"], - [lv_draw_mask_line_param, "end_line"], - [uint16_t, "delta_deg"], -] -lv_draw_mask_angle_param = ct.structure(lv_draw_mask_angle_param, "lv_draw_mask_angle_param") +# [lv_draw_mask_line_param, "start_line"], +# [lv_draw_mask_line_param, "end_line"], +# [uint16_t, "delta_deg"], +# ] +# lv_draw_mask_angle_param = ct.structure(lv_draw_mask_angle_param, "lv_draw_mask_angle_param") -lv_draw_mask_radius_param_cfg = [ # valid LVGL8.3 - [lv_area, "rect"], - [lv_coord_t, "radius"], - [uint8_t_1, "outer"], -] -lv_draw_mask_radius_param_cfg = ct.structure(lv_draw_mask_radius_param_cfg, "lv_draw_mask_radius_param_cfg") +# lv_draw_mask_radius_param_cfg = [ # valid LVGL8.3 +# [lv_area, "rect"], +# [lv_coord_t, "radius"], +# [uint8_t_1, "outer"], +# ] +# lv_draw_mask_radius_param_cfg = ct.structure(lv_draw_mask_radius_param_cfg, "lv_draw_mask_radius_param_cfg") -lv_draw_mask_radius_circle_dsc = [ # valid LVGL8.3 - [ptr, "buf"], - [ptr, "cir_opa"], - [ptr, "x_start_on_y"], - [ptr, "opa_start_on_y"], - [int32_t, "life"], - [uint32_t, "used_cnt"], - [lv_coord_t, "radius"], -] -lv_draw_mask_radius_circle_dsc = ct.structure(lv_draw_mask_radius_circle_dsc, "lv_draw_mask_radius_circle_dsc") +# lv_draw_mask_radius_circle_dsc = [ # valid LVGL8.3 +# [ptr, "buf"], +# [ptr, "cir_opa"], +# [ptr, "x_start_on_y"], +# [ptr, "opa_start_on_y"], +# [int32_t, "life"], +# [uint32_t, "used_cnt"], +# [lv_coord_t, "radius"], +# ] +# lv_draw_mask_radius_circle_dsc = ct.structure(lv_draw_mask_radius_circle_dsc, "lv_draw_mask_radius_circle_dsc") -lv_draw_mask_radius_param = [ # valid LVGL8.3 - #/*The first element must be the common descriptor*/ - [lv_draw_mask_common_dsc, "dsc"], - [lv_draw_mask_radius_param_cfg, "cfg"], - [lv_draw_mask_radius_circle_dsc, "circle"], -] -lv_draw_mask_radius_param = ct.structure(lv_draw_mask_radius_param, "lv_draw_mask_radius_param") +# lv_draw_mask_radius_param = [ # valid LVGL8.3 +# #/*The first element must be the common descriptor*/ +# [lv_draw_mask_common_dsc, "dsc"], +# [lv_draw_mask_radius_param_cfg, "cfg"], +# [lv_draw_mask_radius_circle_dsc, "circle"], +# ] +# lv_draw_mask_radius_param = ct.structure(lv_draw_mask_radius_param, "lv_draw_mask_radius_param") -lv_draw_mask_fade_param_cfg = [ # valid LVGL8.3 - [lv_area, "coords"], - [lv_coord_t, "y_top"], - [lv_coord_t, "y_bottom"], - [lv_opa, "opa_top"], - [lv_opa, "opa_bottom"], -] -lv_draw_mask_fade_param_cfg = ct.structure(lv_draw_mask_fade_param_cfg, "lv_draw_mask_fade_param_cfg") +# lv_draw_mask_fade_param_cfg = [ # valid LVGL8.3 +# [lv_area, "coords"], +# [lv_coord_t, "y_top"], +# [lv_coord_t, "y_bottom"], +# [lv_opa, "opa_top"], +# [lv_opa, "opa_bottom"], +# ] +# lv_draw_mask_fade_param_cfg = ct.structure(lv_draw_mask_fade_param_cfg, "lv_draw_mask_fade_param_cfg") -lv_draw_mask_fade_param = [ # valid LVGL8.3 - # /*The first element must be the common descriptor*/ - [lv_draw_mask_common_dsc, "dsc"], - [lv_draw_mask_fade_param_cfg, "cfg"], -] -lv_draw_mask_fade_param = ct.structure(lv_draw_mask_fade_param, "lv_draw_mask_fade_param") +# lv_draw_mask_fade_param = [ # valid LVGL8.3 +# # /*The first element must be the common descriptor*/ +# [lv_draw_mask_common_dsc, "dsc"], +# [lv_draw_mask_fade_param_cfg, "cfg"], +# ] +# lv_draw_mask_fade_param = ct.structure(lv_draw_mask_fade_param, "lv_draw_mask_fade_param") -lv_draw_mask_map_param_cfg = [ # valid LVGL8.3 - [lv_area, "coords"], - [ptr, "map"], -] -lv_draw_mask_map_param_cfg = ct.structure(lv_draw_mask_map_param_cfg, "lv_draw_mask_map_param_cfg") +# lv_draw_mask_map_param_cfg = [ # valid LVGL8.3 +# [lv_area, "coords"], +# [ptr, "map"], +# ] +# lv_draw_mask_map_param_cfg = ct.structure(lv_draw_mask_map_param_cfg, "lv_draw_mask_map_param_cfg") -lv_draw_mask_map_param = [ # valid LVGL8.3 - [lv_draw_mask_common_dsc, "dsc"], - [lv_draw_mask_map_param_cfg, "cfg"], -] -lv_draw_mask_map_param = ct.structure(lv_draw_mask_map_param, "lv_draw_mask_map_param") +# lv_draw_mask_map_param = [ # valid LVGL8.3 +# [lv_draw_mask_common_dsc, "dsc"], +# [lv_draw_mask_map_param_cfg, "cfg"], +# ] +# lv_draw_mask_map_param = ct.structure(lv_draw_mask_map_param, "lv_draw_mask_map_param") -lv_draw_mask_polygon_param_cfg = [ # valid LVGL8.3 - [ptr, "points"], - [uint16_t, "point_cnt"], -] -lv_draw_mask_polygon_param_cfg = ct.structure(lv_draw_mask_polygon_param_cfg, "lv_draw_mask_polygon_param_cfg") +# lv_draw_mask_polygon_param_cfg = [ # valid LVGL8.3 +# [ptr, "points"], +# [uint16_t, "point_cnt"], +# ] +# lv_draw_mask_polygon_param_cfg = ct.structure(lv_draw_mask_polygon_param_cfg, "lv_draw_mask_polygon_param_cfg") -lv_draw_mask_polygon_param = [ # valid LVGL8.3 - [lv_draw_mask_common_dsc, "dsc"], - [lv_draw_mask_polygon_param_cfg, "cfg"], -] -lv_draw_mask_polygon_param = ct.structure(lv_draw_mask_polygon_param, "lv_draw_mask_polygon_param") +# lv_draw_mask_polygon_param = [ # valid LVGL8.3 +# [lv_draw_mask_common_dsc, "dsc"], +# [lv_draw_mask_polygon_param_cfg, "cfg"], +# ] +# lv_draw_mask_polygon_param = ct.structure(lv_draw_mask_polygon_param, "lv_draw_mask_polygon_param") -lv_draw_mask_saved = [ # valid LVGL8.3 - [ptr, "param"], - [ptr, "custom_id"], -] -lv_draw_mask_saved = ct.structure(lv_draw_mask_saved, "lv_draw_mask_saved") +# lv_draw_mask_saved = [ # valid LVGL8.3 +# [ptr, "param"], +# [ptr, "custom_id"], +# ] +# lv_draw_mask_saved = ct.structure(lv_draw_mask_saved, "lv_draw_mask_saved") # lv_meter @@ -430,11 +599,22 @@ lv_meter_indicator = ct.structure(lv_meter_indicator, "lv_meter_indicator") # ] # lv_meter_indicator_scale_lines = ct.structure(lv_meter_indicator_scale_lines, "lv_meter_indicator_scale_lines") -lv_chart_series = [ # valid LVGL8.3 +# typedef struct { +# int32_t * x_points; +# int32_t * y_points; +# lv_color_t color; +# uint32_t start_point; +# uint32_t hidden : 1; +# uint32_t x_ext_buf_assigned : 1; +# uint32_t y_ext_buf_assigned : 1; +# uint32_t x_axis_sec : 1; +# uint32_t y_axis_sec : 1; +# } lv_chart_series_t; +lv_chart_series = [ # valid LVGL9 [ptr, "x_points"], [ptr, "y_points"], [lv_color, "color"], - [uint16_t, "start_point"], + [uint32_t, "start_point"], [uint8_t_1, "hidden"], [uint8_t_1, "x_ext_buf_assigned"], [uint8_t_1, "y_ext_buf_assigned"], @@ -443,9 +623,17 @@ lv_chart_series = [ # valid LVGL8.3 ] lv_chart_series = ct.structure(lv_chart_series, "lv_chart_series") -lv_chart_cursor = [ # valid LVGL8.3 +# typedef struct { +# lv_point_t pos; +# int32_t point_id; +# lv_color_t color; +# lv_chart_series_t * ser; +# lv_dir_t dir; +# uint32_t pos_set: 1; /*1: pos is set; 0: point_id is set*/ +# } lv_chart_cursor_t; +lv_chart_cursor = [ # valid LVGL9 [lv_point, "pos"], - [uint16_t, "point_id"], + [int32_t, "point_id"], [lv_color, "color"], [ptr, "ser"], [lv_dir, "dir"], @@ -453,15 +641,15 @@ lv_chart_cursor = [ # valid LVGL8.3 ] lv_chart_cursor = ct.structure(lv_chart_cursor, "lv_chart_cursor") -lv_chart_tick_dsc = [ # valid LVGL8.3 - [lv_coord_t, "major_len"], - [lv_coord_t, "minor_len"], - [lv_coord_t, "draw_size"], - [uint16_t_15, "minor_cnt"], - [uint16_t_15, "major_cnt"], - [uint8_t_1, "label_en"], -] -lv_chart_tick_dsc = ct.structure(lv_chart_tick_dsc, "lv_chart_tick_dsc") +# lv_chart_tick_dsc = [ # valid LVGL8.3 +# [lv_coord_t, "major_len"], +# [lv_coord_t, "minor_len"], +# [lv_coord_t, "draw_size"], +# [uint16_t_15, "minor_cnt"], +# [uint16_t_15, "major_cnt"], +# [uint8_t_1, "label_en"], +# ] +# lv_chart_tick_dsc = ct.structure(lv_chart_tick_dsc, "lv_chart_tick_dsc") #- --------- class system --------- -# @@ -473,21 +661,59 @@ destructor_cb = ptr # callback event_cb = ptr # callback lv_event_code = ct.i32 -lv_obj_class = [ # valid LVGL8.3 +# struct _lv_obj_class_t { +# const lv_obj_class_t * base_class; +# /*class_p is the final class while obj->class_p is the class currently being [de]constructed.*/ +# void (*constructor_cb)(const lv_obj_class_t * class_p, lv_obj_t * obj); +# void (*destructor_cb)(const lv_obj_class_t * class_p, lv_obj_t * obj); + +# /*class_p is the class in which event is being processed.*/ +# void (*event_cb)(const lv_obj_class_t * class_p, lv_event_t * e); /**< Widget type specific event function*/ + +# #if LV_USE_OBJ_PROPERTY +# uint32_t prop_index_start; +# uint32_t prop_index_end; +# const lv_property_ops_t * properties; +# uint32_t properties_count; +# #endif + +# void * user_data; +# const char * name; +# int32_t width_def; +# int32_t height_def; +# uint32_t editable : 2; /**< Value from ::lv_obj_class_editable_t*/ +# uint32_t group_def : 2; /**< Value from ::lv_obj_class_group_def_t*/ +# uint32_t instance_size : 16; +# uint32_t theme_inheritable : 1; /**< Value from ::lv_obj_class_theme_inheritable_t*/ +# }; +lv_obj_class = [ # valid LVGL9 [lv_obj_class_ptr, "base_class"], [constructor_cb, "constructor_cb"], [destructor_cb, "destructor_cb"], - [ptr, "user_data"], [event_cb, "event_cb"], - [lv_coord_t, "width_def"], - [lv_coord_t, "height_def"], + [ptr, "user_data"], + [ptr, "name"], + [int32_t, "width_def"], + [int32_t, "height_def"], [uint8_t_2, "editable"], [uint8_t_2, "group_def"], [uint16_t_16, "instance_size"], + [uint8_t_1, "theme_inheritable"], ] lv_obj_class = ct.structure(lv_obj_class, "lv_obj_class") -lv_event = [ # valid LVGL8.3 +# struct _lv_event_t { +# void * current_target; +# void * original_target; +# lv_event_code_t code; +# void * user_data; +# void * param; +# lv_event_t * prev; +# uint8_t deleted : 1; +# uint8_t stop_processing : 1; +# uint8_t stop_bubbling : 1; +# }; +lv_event = [ # valid LVGL9 [lv_obj_ptr, "target"], [lv_obj_ptr, "current_target"], [lv_event_code, "code"], @@ -500,33 +726,31 @@ lv_event = [ # valid LVGL8.3 ] lv_event = ct.structure(lv_event, "lv_event") -lv_sqrt_res = [ # valid LVGL8.3 - [uint16_t, "i"], - [uint16_t, "f"], -] -lv_sqrt_res = ct.structure(lv_sqrt_res, "lv_sqrt_res") - ####################################################################### -# lv_img structures -lv_img_header = [ # valid LVGL8.3 - [uint8_t_5, "cf"], - [uint8_t_3, "always_zero"], - [uint8_t_2, "reserved"], - [uint8_t_11, "w"], - [uint8_t_11, "h"], -] -lv_img_header = ct.structure(lv_img_header, "lv_img_header") +# lv_image structures -lv_img_dsc = [ # valid LVGL8.3 - [lv_img_header, "header"], +# typedef struct { +# lv_image_header_t header; /**< A header describing the basics of the image*/ +# uint32_t data_size; /**< Size of the image in bytes*/ +# const uint8_t * data; /**< Pointer to the data of the image*/ +# } lv_image_dsc_t; +lv_image_dsc = [ # valid LVGL9 + [lv_image_header, "header"], [uint32_t, "data_size"], [ptr, "data"], ] -lv_img_dsc = ct.structure(lv_img_dsc, "lv_img_dsc") +lv_image_dsc = ct.structure(lv_image_dsc, "lv_image_dsc") ####################################################################### # lv_style -lv_style_transition_dsc = [ # valid LVGL8.3 +# typedef struct { +# const lv_style_prop_t * props; /**< An array with the properties to animate.*/ +# void * user_data; /**< A custom user data that will be passed to the animation's user_data */ +# lv_anim_path_cb_t path_xcb; /**< A path for the animation.*/ +# uint32_t time; /**< Duration of the transition in [ms]*/ +# uint32_t delay; /**< Delay before the transition in [ms]*/ +# } lv_style_transition_dsc_t; +lv_style_transition_dsc = [ # valid LVGL9 [ptr, "props"], [ptr, "user_data"], [ptr, "path_xcb"], @@ -544,7 +768,11 @@ lv_style_transition_dsc = ct.structure(lv_style_transition_dsc, "lv_style_transi # ] # lv_color_hsv = ct.structure(lv_color_hsv, "lv_color_hsv") -lv_color_filter_dsc = [ # valid LVGL8.3 +# typedef struct _lv_color_filter_dsc_t { +# lv_color_filter_cb_t filter_cb; +# void * user_data; +# } lv_color_filter_dsc_t; +lv_color_filter_dsc = [ # valid LVGL9 [ptr, "filter_cb"], [ptr, "user_data"], ] @@ -552,72 +780,131 @@ lv_color_filter_dsc = ct.structure(lv_color_filter_dsc, "lv_color_filter_dsc") ####################################################################### # lv_timer native, superseded by lv_timer -lv_timer_ntv = [ # valid LVGL8.3 + +# struct _lv_timer_t { +# uint32_t period; /**< How often the timer should run*/ +# uint32_t last_run; /**< Last time the timer ran*/ +# lv_timer_cb_t timer_cb; /**< Timer function*/ +# void * user_data; /**< Custom user data*/ +# int32_t repeat_count; /**< 1: One time; -1 : infinity; n>0: residual times*/ +# uint32_t paused : 1; +# uint32_t auto_delete : 1; +# }; +lv_timer_ntv = [ # valid LVGL9 [uint32_t, "period"], [uint32_t, "last_run"], [ptr, "timer_cb"], [ptr, "user_data"], [int32_t, "repeat_count"], [uint8_t_1, "paused"], + [uint8_t_1, "auto_delete"], ] lv_timer_ntv = ct.structure(lv_timer_ntv, "lv_timer_ntv") # ####################################################################### # lv_anim native structure, is superseded by lv_anim -lv_anim_ntv = [ # valid LVGL8.3 - [ptr, "var"], - [ptr, "exec_cb"], - [ptr, "start_cb"], - [ptr, "ready_cb"], - [ptr, "deleted_cb"], - [ptr, "get_value_cb"], - [ptr, "user_data"], +# /** Describes an animation*/ +# struct _lv_anim_t { +# void * var; /** self.make_cb(f, obj, name)) + # general cb for events + # self.general_event_cb = cb.gen_cb(self._dispatch_event_cb) # load extra modules import lv_extra end @@ -68,11 +71,11 @@ class LVGL_glob var event_ptr = introspect.toptr(event_ptr_i) # use always the same instance of lv.lv_event by changing pointer, create a new the first time - if self.event self.event._change_buffer(event_ptr) + if self.event self.event._p = event_ptr else self.event = lv.lv_event(event_ptr) end - var target = self.event.target # LVGL native object as target of the event (comptr) + var target = self.event.get_target() # LVGL native object as target of the event (comptr) var obj = self.get_object_from_ptr(target) # get the corresponding Berry LVGL object previously recorded as its container var f = self.cb_event_closure[target] # get the closure or closure list known for this object if type(f) == 'function' # if only one callback, just use it @@ -188,14 +191,22 @@ class LVGL_glob obj.widget_destructor(cl) end end + # called by event handler + # input: + # cl_ptr: (int) pointer to class structure + # e_ptr: (int) pointer to event object def widget_event_impl(cl_ptr, e_ptr) import introspect + # tasmota.log(f'>>>: widget_event_impl cl_ptr {cl_ptr=} e_ptr {e_ptr=}') var cl = lv.lv_obj_class(cl_ptr) - var event = lv.lv_event(e_ptr) - var obj_ptr = event.target - var obj = self.get_object_from_ptr(obj_ptr) + var event = lv.lv_event(introspect.toptr(e_ptr)) + # tasmota.log(f'>>>: widget_event_impl cl {cl=} event {event=}') + # var obj_ptr = event.target + var obj_ptr = event.get_target_obj() + var obj = self.get_object_from_ptr(obj_ptr._p) + # tasmota.log(f">>>: widget_event_impl {obj_ptr=} {obj=}") if type(obj) == 'instance' - if event.code == lv.EVENT_DELETE && introspect.get(obj, 'before_del') + if event.get_code() == lv.EVENT_DELETE && introspect.get(obj, 'before_del') obj.before_del(cl, event) elif introspect.get(obj, 'widget_event') obj.widget_event(cl, event) @@ -241,12 +252,13 @@ class LVGL_glob self.widget_cb() # set up all structures obj_class_struct = self.widget_struct_default.copy() # get a copy of the structure with pre-defined callbacks obj_class_struct.base_class = super(obj)._class - if introspect.get(obj, 'widget_width_def') obj_class_struct.width_def = obj.widget_width_def end - if introspect.get(obj, 'widget_height_def') obj_class_struct.height_def = obj.widget_height_def end - if introspect.get(obj, 'widget_editable') obj_class_struct.editable = obj.widget_editable end - if introspect.get(obj, 'widget_group_def') obj_class_struct.group_def = obj.widget_group_def end - if introspect.get(obj, 'widget_instance_size') obj_class_struct.instance_size = obj.widget_instance_size end - + if introspect.contains(obj, 'widget_width_def') obj_class_struct.width_def = obj.widget_width_def end + if introspect.contains(obj, 'widget_height_def') obj_class_struct.height_def = obj.widget_height_def end + if introspect.contains(obj, 'widget_editable') obj_class_struct.editable = obj.widget_editable end + if introspect.contains(obj, 'widget_group_def') obj_class_struct.group_def = obj.widget_group_def end + if introspect.contains(obj, 'widget_instance_size') obj_class_struct.instance_size = obj.widget_instance_size end + + # tasmota.log(f'>>>: {obj_class_struct=} map {obj_class_struct.tomap()}') #- keep a copy of the structure to avoid GC and reuse if needed -# self.widget_struct_by_class[obj_classname] = obj_class_struct end @@ -256,101 +268,30 @@ class LVGL_glob self.register_obj(obj) obj.class_init_obj() end + + # # new simplified way to implement a custom widget by just adding an event cb + # # + # # input: + # # lvovj: (instance of lv_obj of sub-class) the instance that will receive events + # # event_filter: lvgl event_filter + # # + # # The method `event_cb(lv_event)` will be called + # # + # # TODO: make sure that the instance to the berry object is still valid and was not GCed + # def add_event_cb(lvobj, event_filter) + # import introspect + # var cb = self.general_event_cb + # #lvovj.add_event_cb() + # end + + # # the function called by LVGL and dispatching to the right object + # # + # # TODO + # static def _dispatch_event_cb(event_int) + # end + end -# _lvgl = LVGL_glob() - -# class lv_custom_widget : lv.lv_obj -# # static widget_width_def -# # static widget_height_def -# # static widget_editable -# # static widget_group_def -# # static widget_instance_size -# # -# var percentage # value to display, range 0..100 -# var p1, p2, area, line_dsc # instances of objects kept to avoid re-instanciating at each call - -# def init(parent) -# _lvgl.create_custom_widget(self, parent) -# # own values -# self.percentage = 100 -# # pre-allocate buffers -# self.p1 = lv.lv_point() -# self.p2 = lv.lv_point() -# self.area = lv.lv_area() -# self.line_dsc = lv.lv_draw_line_dsc() -# end - -# # def widget_constructor(cl) -# # print("widget_constructor", cl) -# # end - -# # def widget_destructor(cl) -# # print("widget_destructor", cl) -# # end - -# def widget_event(cl, event) -# var res = lv.obj_event_base(cl, event) -# if res != lv.RES_OK return end - -# def atleast1(x) if x >= 1 return x else return 1 end end -# # the model is that we have 4 bars and inter-bar (1/4 of width) -# var height = self.get_height() -# var width = self.get_width() - -# var inter_bar = atleast1(width / 15) -# var bar = atleast1((width - inter_bar * 3) / 4) -# var bar_offset = bar / 2 - -# var code = event.code -# if code == lv.EVENT_DRAW_MAIN -# var clip_area = lv.lv_area(event.param) -# print("widget_event DRAW", clip_area.tomap()) -# # lv.event_send(self, lv.EVENT_DRAW_MAIN, clip_area) - -# # get coordinates of object -# self.get_coords(self.area) -# var x_ofs = self.area.x1 -# var y_ofs = self.area.y1 - -# lv.draw_line_dsc_init(self.line_dsc) # initialize lv.lv_draw_line_dsc structure -# self.init_draw_line_dsc(lv.PART_MAIN, self.line_dsc) - -# self.line_dsc.round_start = 1 -# self.line_dsc.round_end = 1 -# self.line_dsc.width = bar - -# var on_color = self.get_style_line_color(lv.PART_MAIN | lv.STATE_DEFAULT) -# var off_color = self.get_style_bg_color(lv.PART_MAIN | lv.STATE_DEFAULT) - -# lv.event_send(self, lv.EVENT_DRAW_PART_BEGIN, self.line_dsc) -# for i:0..3 # 4 bars -# self.line_dsc.color = self.percentage >= (i+1)*20 ? on_color : off_color -# self.p1.y = y_ofs + height - 1 - bar_offset -# self.p1.x = x_ofs + i * (bar + inter_bar) + bar_offset -# self.p2.y = y_ofs + ((3 - i) * (height - bar)) / 4 + bar_offset -# self.p2.x = self.p1.x -# lv.draw_line(self.p1, self.p2, clip_area, self.line_dsc) -# end -# lv.event_send(self, lv.EVENT_DRAW_PART_END, self.line_dsc) - -# end -# end - -# def set_percentage(v) -# var old_bars = self.percentage / 5 -# if v > 100 v = 100 end -# if v < 0 v = 0 end -# self.percentage = v -# if old_bars != v / 5 -# self.invalidate() # be frugal and avoid updating the widget if it's not needed -# end -# end - -# def get_percentage() -# return self.percentage -# end -# end # ########## ########## ########## ########## ########## ########## ########## ########## diff --git a/lib/libesp32_lvgl/lv_binding_berry/src/lv_berry.c b/lib/libesp32_lvgl/lv_binding_berry/src/lv_berry.c index 745e550c5..0d82c3fab 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/src/lv_berry.c +++ b/lib/libesp32_lvgl/lv_binding_berry/src/lv_berry.c @@ -7,6 +7,24 @@ #include +// Backport configuration from LVGL 8 to LVGL 9 +#ifdef BE_LV_WIDGET_BTN + #undef BE_LV_WIDGET_BUTTON + #define BE_LV_WIDGET_BUTTON +#endif +#ifdef BE_LV_WIDGET_BTNMATRIX + #undef BE_LV_WIDGET_BUTTONMATRIX + #define BE_LV_WIDGET_BUTTONMATRIX +#endif +#ifdef BE_LV_WIDGET_IMG + #undef BE_LV_WIDGET_IMAGE + #define BE_LV_WIDGET_IMAGE +#endif +#ifdef BE_LV_WIDGET_IMGBTN + #undef BE_LV_WIDGET_IMAGEBUTTON + #define BE_LV_WIDGET_IMAGEBUTTON +#endif + #include "../generate/be_lv_c_mapping.h" /*********************************************************************************************\ @@ -163,7 +181,9 @@ int lv_x_member(bvm *vm) { be_pop(vm, 1); } // berry_log_C("lv_x_member method not found"); - be_return_nil(vm); + /* not found, return module 'undefined' */ + be_getmodule(vm, "undefined"); + be_return(vm); } be_raise(vm, "type_error", NULL); } @@ -179,37 +199,34 @@ int lv_x_member(bvm *vm) { // 3/ if no Arg2, color is 0x000000 (black) int lco_init(bvm *vm) { int argc = be_top(vm); - lv_color_t lv_color = {}; // default value is all zeroes (black) + uint32_t color32 = 0; if (argc > 1) { if (be_isint(vm, 2)) { // color is RGB 24 bits - lv_color = lv_color_hex(be_toint(vm, 2)); + color32 = be_toint(vm, 2); } else if (be_iscomptr(vm, 2)) { - lv_color.full = (intptr_t) be_tocomptr(vm, 2); + color32 = (intptr_t) be_tocomptr(vm, 2); } } - be_pushint(vm, lv_color_to_uint32(lv_color)); + be_pushint(vm, color32); be_setmember(vm, 1, "_p"); be_return_nil(vm); } int lco_tostring(bvm *vm) { - lv_color_t lv_color = {}; be_getmember(vm, 1, "_p"); - uint32_t ntv_color = be_toint(vm, -1); - lv_color = lv_color_from_uint32(ntv_color); - uint32_t color = lv_color_to32(lv_color) & 0xFFFFFF; + uint32_t color32 = be_toint(vm, -1); be_pop(vm, 1); // remove attribute - char s[48]; - snprintf(s, sizeof(s), "lv_color(0x%06x - native:0x%04x)", color, ntv_color); + char s[32]; + snprintf(s, sizeof(s), "lv_color(0x%06x)", color32); be_pushnstring(vm, s, strlen(s)); /* make escape string from buffer */ be_return(vm); } int lco_toint(bvm *vm) { be_getmember(vm, 1, "_p"); - uint32_t ntv_color = be_toint(vm, -1); - be_pushint(vm, ntv_color); + uint32_t color32 = be_toint(vm, -1); + be_pushint(vm, color32); be_return(vm); } @@ -234,7 +251,7 @@ int lv0_lvobj__void_call(bvm *vm, fn_lvobj__void func) { int lv0_load_font(bvm *vm) { int argc = be_top(vm); if (argc == 1 && be_isstring(vm, 1)) { - lv_font_t * font = lv_font_load(be_tostring(vm, 1)); + lv_font_t * font = lv_binfont_create(be_tostring(vm, 1)); if (font != NULL) { be_find_global_or_module_member(vm, "lv.lv_font"); be_pushcomptr(vm, font); diff --git a/lib/libesp32_lvgl/lv_binding_berry/src/lv_berry.h b/lib/libesp32_lvgl/lv_binding_berry/src/lv_berry.h index e494e1187..6c2934546 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/src/lv_berry.h +++ b/lib/libesp32_lvgl/lv_binding_berry/src/lv_berry.h @@ -10,22 +10,10 @@ extern "C" { #include "berry.h" #include "lvgl.h" -/*********************************************************************************************\ - * Support for lv_color -\*********************************************************************************************/ -inline lv_color_t lv_color_from_uint32(uint32_t ucol) { - lv_color_t * col = (lv_color_t*) &ucol; - return *col; -} -inline uint32_t lv_color_to_uint32(lv_color_t col) { - uint16_t *p = (uint16_t*) &col; - return *p; -} - extern void be_load_lvgl_classes(bvm *vm); // TODO temporary fix -extern void lv_img_set_tasmota_logo(lv_obj_t * img); +extern void lv_image_set_tasmota_logo(lv_obj_t * img); // used for ToushScreen calibration typedef struct lv_ts_calibration_t { diff --git a/lib/libesp32_lvgl/lv_binding_berry/src/lv_mem_core_berry.c b/lib/libesp32_lvgl/lv_binding_berry/src/lv_mem_core_berry.c new file mode 100644 index 000000000..ba746995b --- /dev/null +++ b/lib/libesp32_lvgl/lv_binding_berry/src/lv_mem_core_berry.c @@ -0,0 +1,97 @@ +/** + * @file lv_malloc_core_berry.c + */ + +/********************* + * INCLUDES + *********************/ +#include "../../lvgl/src/stdlib/lv_mem.h" +#if LV_USE_STDLIB_MALLOC == LV_STDLIB_CUSTOM +#include +// #if LV_USE_STDLIB_MALLOC == LV_STDLIB_CUSTOM +// #include "../../stdlib/lv_mem.h" +// #include "include/lv_mp_mem_custom_include.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_mem_init(void) +{ + return; /*Nothing to init*/ +} + +void lv_mem_deinit(void) +{ + return; /*Nothing to deinit*/ + +} + +lv_mem_pool_t lv_mem_add_pool(void * mem, size_t bytes) +{ + /*Not supported*/ + LV_UNUSED(mem); + LV_UNUSED(bytes); + return NULL; +} + +void lv_mem_remove_pool(lv_mem_pool_t pool) +{ + /*Not supported*/ + LV_UNUSED(pool); + return; +} + +void * lv_malloc_core(size_t size) +{ + return lvbe_malloc(size); +} + +void * lv_realloc_core(void * p, size_t new_size) +{ + return lvbe_realloc(p, new_size); +} + +void lv_free_core(void * p) +{ + lvbe_free(p); +} + +void lv_mem_monitor_core(lv_mem_monitor_t * mon_p) +{ + /*Not supported*/ + LV_UNUSED(mon_p); + return; +} + +lv_result_t lv_mem_test_core(void) +{ + /*Not supported*/ + return LV_RESULT_OK; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_STDLIB_CUSTOM*/ diff --git a/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lv.h b/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lv.h index 97cb28eb9..c8a8c84e7 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lv.h +++ b/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lv.h @@ -17,19 +17,39 @@ be_local_closure(lv_module_init, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ + ( &(const bvalue[12]) { /* constants */ /* K0 */ be_nested_str_weak(lv), /* K1 */ be_nested_str_weak(member), + /* K2 */ be_nested_str_weak(scr_act), + /* K3 */ be_nested_str_weak(screen_active), + /* K4 */ be_nested_str_weak(img), + /* K5 */ be_nested_str_weak(image), + /* K6 */ be_nested_str_weak(disp), + /* K7 */ be_nested_str_weak(display), + /* K8 */ be_nested_str_weak(btn), + /* K9 */ be_nested_str_weak(button), + /* K10 */ be_nested_str_weak(btnmatrix), + /* K11 */ be_nested_str_weak(buttonmatrix), }), be_str_weak(lv_module_init), &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ + ( &(const binstruction[16]) { /* code */ 0x6004000B, // 0000 GETGBL R1 G11 0x58080000, // 0001 LDCONST R2 K0 0x7C040200, // 0002 CALL R1 1 0x88080101, // 0003 GETMBR R2 R0 K1 0x90060202, // 0004 SETMBR R1 K1 R2 - 0x80040200, // 0005 RET 1 R1 + 0x88080103, // 0005 GETMBR R2 R0 K3 + 0x90060402, // 0006 SETMBR R1 K2 R2 + 0x88080105, // 0007 GETMBR R2 R0 K5 + 0x90060802, // 0008 SETMBR R1 K4 R2 + 0x88080107, // 0009 GETMBR R2 R0 K7 + 0x90060C02, // 000A SETMBR R1 K6 R2 + 0x88080109, // 000B GETMBR R2 R0 K9 + 0x90061002, // 000C SETMBR R1 K8 R2 + 0x8808010B, // 000D GETMBR R2 R0 K11 + 0x90061402, // 000E SETMBR R1 K10 R2 + 0x80040200, // 000F RET 1 R1 }) ) ); diff --git a/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lvgl_extra.h b/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lvgl_extra.h index 8ac966889..1e68423b7 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lvgl_extra.h +++ b/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lvgl_extra.h @@ -4,6 +4,413 @@ \********************************************************************/ #include "be_constobj.h" +extern const bclass be_class_lv_str_arr; + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(lv_str_arr_init, /* name */ + be_nested_proto( + 11, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(l), + /* K1 */ be_nested_str_weak(init), + /* K2 */ be_nested_str_weak(introspect), + /* K3 */ be_nested_str_weak(add), + /* K4 */ be_nested_str_weak(toptr), + /* K5 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[31]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x60080003, // 0001 GETGBL R2 G3 + 0x5C0C0000, // 0002 MOVE R3 R0 + 0x7C080200, // 0003 CALL R2 1 + 0x8C080501, // 0004 GETMET R2 R2 K1 + 0x6010000C, // 0005 GETGBL R4 G12 + 0x5C140200, // 0006 MOVE R5 R1 + 0x7C100200, // 0007 CALL R4 1 + 0x54160003, // 0008 LDINT R5 4 + 0x08100805, // 0009 MUL R4 R4 R5 + 0x7C080400, // 000A CALL R2 2 + 0xA40A0400, // 000B IMPORT R2 K2 + 0x600C0010, // 000C GETGBL R3 G16 + 0x5C100200, // 000D MOVE R4 R1 + 0x7C0C0200, // 000E CALL R3 1 + 0xA802000A, // 000F EXBLK 0 #001B + 0x5C100600, // 0010 MOVE R4 R3 + 0x7C100000, // 0011 CALL R4 0 + 0x8C140103, // 0012 GETMET R5 R0 K3 + 0x601C0009, // 0013 GETGBL R7 G9 + 0x8C200504, // 0014 GETMET R8 R2 K4 + 0x5C280800, // 0015 MOVE R10 R4 + 0x7C200400, // 0016 CALL R8 2 + 0x7C1C0200, // 0017 CALL R7 1 + 0x54220003, // 0018 LDINT R8 4 + 0x7C140600, // 0019 CALL R5 3 + 0x7001FFF4, // 001A JMP #0010 + 0x580C0005, // 001B LDCONST R3 K5 + 0xAC0C0200, // 001C CATCH R3 1 0 + 0xB0080000, // 001D RAISE 2 R0 R0 + 0x80000000, // 001E RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: lv_str_arr +********************************************************************/ +extern const bclass be_class_bytes; +be_local_class(lv_str_arr, + 1, + &be_class_bytes, + be_nested_map(2, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(init, -1), be_const_closure(lv_str_arr_init_closure) }, + { be_const_key_weak(l, 0), be_const_var(0) }, + })), + be_str_weak(lv_str_arr) +); + +extern const bclass be_class_lv_int_arr; + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(lv_int_arr_init, /* name */ + be_nested_proto( + 9, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 8]) { /* constants */ + /* K0 */ be_nested_str_weak(instance), + /* K1 */ be_nested_str_weak(init), + /* K2 */ be_nested_str_weak(add), + /* K3 */ be_nested_str_weak(stop_iteration), + /* K4 */ be_nested_str_weak(ptr), + /* K5 */ be_nested_str_weak(int), + /* K6 */ be_nested_str_weak(value_error), + /* K7 */ be_nested_str_weak(argument_X20must_X20be_X20a_X20list_X20or_X20a_X20pointer_X2Bsize), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[58]) { /* code */ + 0x600C0004, // 0000 GETGBL R3 G4 + 0x5C100200, // 0001 MOVE R4 R1 + 0x7C0C0200, // 0002 CALL R3 1 + 0x1C0C0700, // 0003 EQ R3 R3 K0 + 0x780E001F, // 0004 JMPF R3 #0025 + 0x600C000F, // 0005 GETGBL R3 G15 + 0x5C100200, // 0006 MOVE R4 R1 + 0x60140012, // 0007 GETGBL R5 G18 + 0x7C0C0400, // 0008 CALL R3 2 + 0x780E001A, // 0009 JMPF R3 #0025 + 0x600C0003, // 000A GETGBL R3 G3 + 0x5C100000, // 000B MOVE R4 R0 + 0x7C0C0200, // 000C CALL R3 1 + 0x8C0C0701, // 000D GETMET R3 R3 K1 + 0x6014000C, // 000E GETGBL R5 G12 + 0x5C180200, // 000F MOVE R6 R1 + 0x7C140200, // 0010 CALL R5 1 + 0x541A0003, // 0011 LDINT R6 4 + 0x08140A06, // 0012 MUL R5 R5 R6 + 0x7C0C0400, // 0013 CALL R3 2 + 0x600C0010, // 0014 GETGBL R3 G16 + 0x5C100200, // 0015 MOVE R4 R1 + 0x7C0C0200, // 0016 CALL R3 1 + 0xA8020008, // 0017 EXBLK 0 #0021 + 0x5C100600, // 0018 MOVE R4 R3 + 0x7C100000, // 0019 CALL R4 0 + 0x8C140102, // 001A GETMET R5 R0 K2 + 0x601C0009, // 001B GETGBL R7 G9 + 0x5C200800, // 001C MOVE R8 R4 + 0x7C1C0200, // 001D CALL R7 1 + 0x54220003, // 001E LDINT R8 4 + 0x7C140600, // 001F CALL R5 3 + 0x7001FFF6, // 0020 JMP #0018 + 0x580C0003, // 0021 LDCONST R3 K3 + 0xAC0C0200, // 0022 CATCH R3 1 0 + 0xB0080000, // 0023 RAISE 2 R0 R0 + 0x70020013, // 0024 JMP #0039 + 0x600C0004, // 0025 GETGBL R3 G4 + 0x5C100200, // 0026 MOVE R4 R1 + 0x7C0C0200, // 0027 CALL R3 1 + 0x1C0C0704, // 0028 EQ R3 R3 K4 + 0x780E000D, // 0029 JMPF R3 #0038 + 0x600C0004, // 002A GETGBL R3 G4 + 0x5C100400, // 002B MOVE R4 R2 + 0x7C0C0200, // 002C CALL R3 1 + 0x1C0C0705, // 002D EQ R3 R3 K5 + 0x780E0008, // 002E JMPF R3 #0038 + 0x600C0003, // 002F GETGBL R3 G3 + 0x5C100000, // 0030 MOVE R4 R0 + 0x7C0C0200, // 0031 CALL R3 1 + 0x8C0C0701, // 0032 GETMET R3 R3 K1 + 0x5C140200, // 0033 MOVE R5 R1 + 0x541A0003, // 0034 LDINT R6 4 + 0x08180406, // 0035 MUL R6 R2 R6 + 0x7C0C0600, // 0036 CALL R3 3 + 0x70020000, // 0037 JMP #0039 + 0xB0060D07, // 0038 RAISE 1 K6 K7 + 0x80000000, // 0039 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: item +********************************************************************/ +be_local_closure(lv_int_arr_item, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(get), + }), + be_str_weak(item), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x8C080100, // 0000 GETMET R2 R0 K0 + 0x54120003, // 0001 LDINT R4 4 + 0x08100204, // 0002 MUL R4 R1 R4 + 0x54160003, // 0003 LDINT R5 4 + 0x7C080600, // 0004 CALL R2 3 + 0x80040400, // 0005 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: setitem +********************************************************************/ +be_local_closure(lv_int_arr_setitem, /* name */ + be_nested_proto( + 8, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(set), + }), + be_str_weak(setitem), + &be_const_str_solidified, + ( &(const binstruction[ 7]) { /* code */ + 0x8C0C0100, // 0000 GETMET R3 R0 K0 + 0x54160003, // 0001 LDINT R5 4 + 0x08140205, // 0002 MUL R5 R1 R5 + 0x5C180400, // 0003 MOVE R6 R2 + 0x541E0003, // 0004 LDINT R7 4 + 0x7C0C0800, // 0005 CALL R3 4 + 0x80000000, // 0006 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: lv_int_arr +********************************************************************/ +extern const bclass be_class_bytes; +be_local_class(lv_int_arr, + 0, + &be_class_bytes, + be_nested_map(3, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(init, -1), be_const_closure(lv_int_arr_init_closure) }, + { be_const_key_weak(item, -1), be_const_closure(lv_int_arr_item_closure) }, + { be_const_key_weak(setitem, -1), be_const_closure(lv_int_arr_setitem_closure) }, + })), + be_str_weak(lv_int_arr) +); + +extern const bclass be_class_lv_point_arr; + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(lv_point_arr_init, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[11]) { /* constants */ + /* K0 */ be_nested_str_weak(instance), + /* K1 */ be_nested_str_weak(value_error), + /* K2 */ be_nested_str_weak(argument_X20must_X20be_X20a_X20list), + /* K3 */ be_nested_str_weak(init), + /* K4 */ be_nested_str_weak(lv), + /* K5 */ be_nested_str_weak(lv_point), + /* K6 */ be_nested_str_weak(elements_X20must_X20be_X20a_X20lv_point), + /* K7 */ be_nested_str_weak(add), + /* K8 */ be_nested_str_weak(x), + /* K9 */ be_nested_str_weak(y), + /* K10 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[52]) { /* code */ + 0x60080004, // 0000 GETGBL R2 G4 + 0x5C0C0200, // 0001 MOVE R3 R1 + 0x7C080200, // 0002 CALL R2 1 + 0x20080500, // 0003 NE R2 R2 K0 + 0x740A0004, // 0004 JMPT R2 #000A + 0x6008000F, // 0005 GETGBL R2 G15 + 0x5C0C0200, // 0006 MOVE R3 R1 + 0x60100012, // 0007 GETGBL R4 G18 + 0x7C080400, // 0008 CALL R2 2 + 0x740A0000, // 0009 JMPT R2 #000B + 0xB0060302, // 000A RAISE 1 K1 K2 + 0x60080003, // 000B GETGBL R2 G3 + 0x5C0C0000, // 000C MOVE R3 R0 + 0x7C080200, // 000D CALL R2 1 + 0x8C080503, // 000E GETMET R2 R2 K3 + 0x6010000C, // 000F GETGBL R4 G12 + 0x5C140200, // 0010 MOVE R5 R1 + 0x7C100200, // 0011 CALL R4 1 + 0x54160007, // 0012 LDINT R5 8 + 0x08100805, // 0013 MUL R4 R4 R5 + 0x7C080400, // 0014 CALL R2 2 + 0x60080010, // 0015 GETGBL R2 G16 + 0x5C0C0200, // 0016 MOVE R3 R1 + 0x7C080200, // 0017 CALL R2 1 + 0xA8020016, // 0018 EXBLK 0 #0030 + 0x5C0C0400, // 0019 MOVE R3 R2 + 0x7C0C0000, // 001A CALL R3 0 + 0x60100004, // 001B GETGBL R4 G4 + 0x5C140600, // 001C MOVE R5 R3 + 0x7C100200, // 001D CALL R4 1 + 0x20100900, // 001E NE R4 R4 K0 + 0x74120005, // 001F JMPT R4 #0026 + 0x6010000F, // 0020 GETGBL R4 G15 + 0x5C140600, // 0021 MOVE R5 R3 + 0xB81A0800, // 0022 GETNGBL R6 K4 + 0x88180D05, // 0023 GETMBR R6 R6 K5 + 0x7C100400, // 0024 CALL R4 2 + 0x74120000, // 0025 JMPT R4 #0027 + 0xB0060306, // 0026 RAISE 1 K1 K6 + 0x8C100107, // 0027 GETMET R4 R0 K7 + 0x88180708, // 0028 GETMBR R6 R3 K8 + 0x541E0003, // 0029 LDINT R7 4 + 0x7C100600, // 002A CALL R4 3 + 0x8C100107, // 002B GETMET R4 R0 K7 + 0x88180709, // 002C GETMBR R6 R3 K9 + 0x541E0003, // 002D LDINT R7 4 + 0x7C100600, // 002E CALL R4 3 + 0x7001FFE8, // 002F JMP #0019 + 0x5808000A, // 0030 LDCONST R2 K10 + 0xAC080200, // 0031 CATCH R2 1 0 + 0xB0080000, // 0032 RAISE 2 R0 R0 + 0x80000000, // 0033 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified class: lv_point_arr +********************************************************************/ +extern const bclass be_class_bytes; +be_local_class(lv_point_arr, + 0, + &be_class_bytes, + be_nested_map(1, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_weak(init, -1), be_const_closure(lv_point_arr_init_closure) }, + })), + be_str_weak(lv_point_arr) +); + +/******************************************************************** +** Solidified function: _anonymous_ +********************************************************************/ +be_local_closure(lv_extra__anonymous_, /* name */ + be_nested_proto( + 4, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[12]) { /* constants */ + /* K0 */ be_nested_str_weak(global), + /* K1 */ be_nested_str_weak(lv), + /* K2 */ be_nested_str_weak(lv_coord_arr), + /* K3 */ be_nested_str_weak(lv_int_arr), + /* K4 */ be_nested_str_weak(lv_point_arr), + /* K5 */ be_nested_str_weak(coord_arr), + /* K6 */ be_nested_str_weak(int_arr), + /* K7 */ be_nested_str_weak(point_arr), + /* K8 */ be_nested_str_weak(style_prop_arr), + /* K9 */ be_nested_str_weak(lv_style_prop_arr), + /* K10 */ be_nested_str_weak(str_arr), + /* K11 */ be_nested_str_weak(lv_str_arr), + }), + be_str_weak(_anonymous_), + &be_const_str_solidified, + ( &(const binstruction[19]) { /* code */ + 0xA4060000, // 0000 IMPORT R1 K0 + 0x88080301, // 0001 GETMBR R2 R1 K1 + 0x880C0102, // 0002 GETMBR R3 R0 K2 + 0x900A0403, // 0003 SETMBR R2 K2 R3 + 0x880C0103, // 0004 GETMBR R3 R0 K3 + 0x900A0603, // 0005 SETMBR R2 K3 R3 + 0x880C0104, // 0006 GETMBR R3 R0 K4 + 0x900A0803, // 0007 SETMBR R2 K4 R3 + 0x880C0102, // 0008 GETMBR R3 R0 K2 + 0x900A0A03, // 0009 SETMBR R2 K5 R3 + 0x880C0103, // 000A GETMBR R3 R0 K3 + 0x900A0C03, // 000B SETMBR R2 K6 R3 + 0x880C0104, // 000C GETMBR R3 R0 K4 + 0x900A0E03, // 000D SETMBR R2 K7 R3 + 0x880C0109, // 000E GETMBR R3 R0 K9 + 0x900A1003, // 000F SETMBR R2 K8 R3 + 0x880C010B, // 0010 GETMBR R3 R0 K11 + 0x900A1403, // 0011 SETMBR R2 K10 R3 + 0x80040000, // 0012 RET 1 R0 + }) + ) +); +/*******************************************************************/ + + extern const bclass be_class_lv_style_prop_arr; /******************************************************************** @@ -88,159 +495,6 @@ be_local_class(lv_style_prop_arr, be_str_weak(lv_style_prop_arr) ); -extern const bclass be_class_lv_point_arr; - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(lv_point_arr_init, /* name */ - be_nested_proto( - 8, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[12]) { /* constants */ - /* K0 */ be_nested_str_weak(instance), - /* K1 */ be_nested_str_weak(value_error), - /* K2 */ be_nested_str_weak(argument_X20must_X20be_X20a_X20list), - /* K3 */ be_nested_str_weak(init), - /* K4 */ be_nested_str_weak(lv), - /* K5 */ be_nested_str_weak(lv_point), - /* K6 */ be_nested_str_weak(elements_X20must_X20be_X20a_X20lv_point), - /* K7 */ be_nested_str_weak(add), - /* K8 */ be_nested_str_weak(x), - /* K9 */ be_const_int(2), - /* K10 */ be_nested_str_weak(y), - /* K11 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[52]) { /* code */ - 0x60080004, // 0000 GETGBL R2 G4 - 0x5C0C0200, // 0001 MOVE R3 R1 - 0x7C080200, // 0002 CALL R2 1 - 0x20080500, // 0003 NE R2 R2 K0 - 0x740A0004, // 0004 JMPT R2 #000A - 0x6008000F, // 0005 GETGBL R2 G15 - 0x5C0C0200, // 0006 MOVE R3 R1 - 0x60100012, // 0007 GETGBL R4 G18 - 0x7C080400, // 0008 CALL R2 2 - 0x740A0000, // 0009 JMPT R2 #000B - 0xB0060302, // 000A RAISE 1 K1 K2 - 0x60080003, // 000B GETGBL R2 G3 - 0x5C0C0000, // 000C MOVE R3 R0 - 0x7C080200, // 000D CALL R2 1 - 0x8C080503, // 000E GETMET R2 R2 K3 - 0x6010000C, // 000F GETGBL R4 G12 - 0x5C140200, // 0010 MOVE R5 R1 - 0x7C100200, // 0011 CALL R4 1 - 0x54160003, // 0012 LDINT R5 4 - 0x08100805, // 0013 MUL R4 R4 R5 - 0x7C080400, // 0014 CALL R2 2 - 0x60080010, // 0015 GETGBL R2 G16 - 0x5C0C0200, // 0016 MOVE R3 R1 - 0x7C080200, // 0017 CALL R2 1 - 0xA8020016, // 0018 EXBLK 0 #0030 - 0x5C0C0400, // 0019 MOVE R3 R2 - 0x7C0C0000, // 001A CALL R3 0 - 0x60100004, // 001B GETGBL R4 G4 - 0x5C140600, // 001C MOVE R5 R3 - 0x7C100200, // 001D CALL R4 1 - 0x20100900, // 001E NE R4 R4 K0 - 0x74120005, // 001F JMPT R4 #0026 - 0x6010000F, // 0020 GETGBL R4 G15 - 0x5C140600, // 0021 MOVE R5 R3 - 0xB81A0800, // 0022 GETNGBL R6 K4 - 0x88180D05, // 0023 GETMBR R6 R6 K5 - 0x7C100400, // 0024 CALL R4 2 - 0x74120000, // 0025 JMPT R4 #0027 - 0xB0060306, // 0026 RAISE 1 K1 K6 - 0x8C100107, // 0027 GETMET R4 R0 K7 - 0x88180708, // 0028 GETMBR R6 R3 K8 - 0x581C0009, // 0029 LDCONST R7 K9 - 0x7C100600, // 002A CALL R4 3 - 0x8C100107, // 002B GETMET R4 R0 K7 - 0x8818070A, // 002C GETMBR R6 R3 K10 - 0x581C0009, // 002D LDCONST R7 K9 - 0x7C100600, // 002E CALL R4 3 - 0x7001FFE8, // 002F JMP #0019 - 0x5808000B, // 0030 LDCONST R2 K11 - 0xAC080200, // 0031 CATCH R2 1 0 - 0xB0080000, // 0032 RAISE 2 R0 R0 - 0x80000000, // 0033 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: lv_point_arr -********************************************************************/ -extern const bclass be_class_bytes; -be_local_class(lv_point_arr, - 0, - &be_class_bytes, - be_nested_map(1, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(init, -1), be_const_closure(lv_point_arr_init_closure) }, - })), - be_str_weak(lv_point_arr) -); - -/******************************************************************** -** Solidified function: _anonymous_ -********************************************************************/ -be_local_closure(lv_extra__anonymous_, /* name */ - be_nested_proto( - 4, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[10]) { /* constants */ - /* K0 */ be_nested_str_weak(global), - /* K1 */ be_nested_str_weak(lv), - /* K2 */ be_nested_str_weak(lv_coord_arr), - /* K3 */ be_nested_str_weak(lv_point_arr), - /* K4 */ be_nested_str_weak(coord_arr), - /* K5 */ be_nested_str_weak(point_arr), - /* K6 */ be_nested_str_weak(style_prop_arr), - /* K7 */ be_nested_str_weak(lv_style_prop_arr), - /* K8 */ be_nested_str_weak(str_arr), - /* K9 */ be_nested_str_weak(lv_str_arr), - }), - be_str_weak(_anonymous_), - &be_const_str_solidified, - ( &(const binstruction[15]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0x88080301, // 0001 GETMBR R2 R1 K1 - 0x880C0102, // 0002 GETMBR R3 R0 K2 - 0x900A0403, // 0003 SETMBR R2 K2 R3 - 0x880C0103, // 0004 GETMBR R3 R0 K3 - 0x900A0603, // 0005 SETMBR R2 K3 R3 - 0x880C0102, // 0006 GETMBR R3 R0 K2 - 0x900A0803, // 0007 SETMBR R2 K4 R3 - 0x880C0103, // 0008 GETMBR R3 R0 K3 - 0x900A0A03, // 0009 SETMBR R2 K5 R3 - 0x880C0107, // 000A GETMBR R3 R0 K7 - 0x900A0C03, // 000B SETMBR R2 K6 R3 - 0x880C0109, // 000C GETMBR R3 R0 K9 - 0x900A1003, // 000D SETMBR R2 K8 R3 - 0x80040000, // 000E RET 1 R0 - }) - ) -); -/*******************************************************************/ - - extern const bclass be_class_lv_coord_arr; /******************************************************************** @@ -256,30 +510,29 @@ be_local_closure(lv_coord_arr_init, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ + ( &(const bvalue[ 8]) { /* constants */ /* K0 */ be_nested_str_weak(instance), /* K1 */ be_nested_str_weak(init), - /* K2 */ be_const_int(2), - /* K3 */ be_nested_str_weak(add), - /* K4 */ be_nested_str_weak(stop_iteration), - /* K5 */ be_nested_str_weak(ptr), - /* K6 */ be_nested_str_weak(int), - /* K7 */ be_nested_str_weak(value_error), - /* K8 */ be_nested_str_weak(argument_X20must_X20be_X20a_X20list_X20or_X20a_X20pointer_X2Bsize), + /* K2 */ be_nested_str_weak(add), + /* K3 */ be_nested_str_weak(stop_iteration), + /* K4 */ be_nested_str_weak(ptr), + /* K5 */ be_nested_str_weak(int), + /* K6 */ be_nested_str_weak(value_error), + /* K7 */ be_nested_str_weak(argument_X20must_X20be_X20a_X20list_X20or_X20a_X20pointer_X2Bsize), }), be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[56]) { /* code */ + ( &(const binstruction[58]) { /* code */ 0x600C0004, // 0000 GETGBL R3 G4 0x5C100200, // 0001 MOVE R4 R1 0x7C0C0200, // 0002 CALL R3 1 0x1C0C0700, // 0003 EQ R3 R3 K0 - 0x780E001E, // 0004 JMPF R3 #0024 + 0x780E001F, // 0004 JMPF R3 #0025 0x600C000F, // 0005 GETGBL R3 G15 0x5C100200, // 0006 MOVE R4 R1 0x60140012, // 0007 GETGBL R5 G18 0x7C0C0400, // 0008 CALL R3 2 - 0x780E0019, // 0009 JMPF R3 #0024 + 0x780E001A, // 0009 JMPF R3 #0025 0x600C0003, // 000A GETGBL R3 G3 0x5C100000, // 000B MOVE R4 R0 0x7C0C0200, // 000C CALL R3 1 @@ -287,45 +540,47 @@ be_local_closure(lv_coord_arr_init, /* name */ 0x6014000C, // 000E GETGBL R5 G12 0x5C180200, // 000F MOVE R6 R1 0x7C140200, // 0010 CALL R5 1 - 0x08140B02, // 0011 MUL R5 R5 K2 - 0x7C0C0400, // 0012 CALL R3 2 - 0x600C0010, // 0013 GETGBL R3 G16 - 0x5C100200, // 0014 MOVE R4 R1 - 0x7C0C0200, // 0015 CALL R3 1 - 0xA8020008, // 0016 EXBLK 0 #0020 - 0x5C100600, // 0017 MOVE R4 R3 - 0x7C100000, // 0018 CALL R4 0 - 0x8C140103, // 0019 GETMET R5 R0 K3 - 0x601C0009, // 001A GETGBL R7 G9 - 0x5C200800, // 001B MOVE R8 R4 - 0x7C1C0200, // 001C CALL R7 1 - 0x58200002, // 001D LDCONST R8 K2 - 0x7C140600, // 001E CALL R5 3 - 0x7001FFF6, // 001F JMP #0017 - 0x580C0004, // 0020 LDCONST R3 K4 - 0xAC0C0200, // 0021 CATCH R3 1 0 - 0xB0080000, // 0022 RAISE 2 R0 R0 - 0x70020012, // 0023 JMP #0037 - 0x600C0004, // 0024 GETGBL R3 G4 - 0x5C100200, // 0025 MOVE R4 R1 - 0x7C0C0200, // 0026 CALL R3 1 - 0x1C0C0705, // 0027 EQ R3 R3 K5 - 0x780E000C, // 0028 JMPF R3 #0036 - 0x600C0004, // 0029 GETGBL R3 G4 - 0x5C100400, // 002A MOVE R4 R2 - 0x7C0C0200, // 002B CALL R3 1 - 0x1C0C0706, // 002C EQ R3 R3 K6 - 0x780E0007, // 002D JMPF R3 #0036 - 0x600C0003, // 002E GETGBL R3 G3 - 0x5C100000, // 002F MOVE R4 R0 - 0x7C0C0200, // 0030 CALL R3 1 - 0x8C0C0701, // 0031 GETMET R3 R3 K1 - 0x5C140200, // 0032 MOVE R5 R1 - 0x08180502, // 0033 MUL R6 R2 K2 - 0x7C0C0600, // 0034 CALL R3 3 - 0x70020000, // 0035 JMP #0037 - 0xB0060F08, // 0036 RAISE 1 K7 K8 - 0x80000000, // 0037 RET 0 + 0x541A0003, // 0011 LDINT R6 4 + 0x08140A06, // 0012 MUL R5 R5 R6 + 0x7C0C0400, // 0013 CALL R3 2 + 0x600C0010, // 0014 GETGBL R3 G16 + 0x5C100200, // 0015 MOVE R4 R1 + 0x7C0C0200, // 0016 CALL R3 1 + 0xA8020008, // 0017 EXBLK 0 #0021 + 0x5C100600, // 0018 MOVE R4 R3 + 0x7C100000, // 0019 CALL R4 0 + 0x8C140102, // 001A GETMET R5 R0 K2 + 0x601C0009, // 001B GETGBL R7 G9 + 0x5C200800, // 001C MOVE R8 R4 + 0x7C1C0200, // 001D CALL R7 1 + 0x54220003, // 001E LDINT R8 4 + 0x7C140600, // 001F CALL R5 3 + 0x7001FFF6, // 0020 JMP #0018 + 0x580C0003, // 0021 LDCONST R3 K3 + 0xAC0C0200, // 0022 CATCH R3 1 0 + 0xB0080000, // 0023 RAISE 2 R0 R0 + 0x70020013, // 0024 JMP #0039 + 0x600C0004, // 0025 GETGBL R3 G4 + 0x5C100200, // 0026 MOVE R4 R1 + 0x7C0C0200, // 0027 CALL R3 1 + 0x1C0C0704, // 0028 EQ R3 R3 K4 + 0x780E000D, // 0029 JMPF R3 #0038 + 0x600C0004, // 002A GETGBL R3 G4 + 0x5C100400, // 002B MOVE R4 R2 + 0x7C0C0200, // 002C CALL R3 1 + 0x1C0C0705, // 002D EQ R3 R3 K5 + 0x780E0008, // 002E JMPF R3 #0038 + 0x600C0003, // 002F GETGBL R3 G3 + 0x5C100000, // 0030 MOVE R4 R0 + 0x7C0C0200, // 0031 CALL R3 1 + 0x8C0C0701, // 0032 GETMET R3 R3 K1 + 0x5C140200, // 0033 MOVE R5 R1 + 0x541A0003, // 0034 LDINT R6 4 + 0x08180406, // 0035 MUL R6 R2 R6 + 0x7C0C0600, // 0036 CALL R3 3 + 0x70020000, // 0037 JMP #0039 + 0xB0060D07, // 0038 RAISE 1 K6 K7 + 0x80000000, // 0039 RET 0 }) ) ); @@ -345,18 +600,18 @@ be_local_closure(lv_coord_arr_item, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ + ( &(const bvalue[ 1]) { /* constants */ /* K0 */ be_nested_str_weak(get), - /* K1 */ be_const_int(2), }), be_str_weak(item), &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ + ( &(const binstruction[ 6]) { /* code */ 0x8C080100, // 0000 GETMET R2 R0 K0 - 0x08100301, // 0001 MUL R4 R1 K1 - 0x58140001, // 0002 LDCONST R5 K1 - 0x7C080600, // 0003 CALL R2 3 - 0x80040400, // 0004 RET 1 R2 + 0x54120003, // 0001 LDINT R4 4 + 0x08100204, // 0002 MUL R4 R1 R4 + 0x54160003, // 0003 LDINT R5 4 + 0x7C080600, // 0004 CALL R2 3 + 0x80040400, // 0005 RET 1 R2 }) ) ); @@ -376,19 +631,19 @@ be_local_closure(lv_coord_arr_setitem, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ + ( &(const bvalue[ 1]) { /* constants */ /* K0 */ be_nested_str_weak(set), - /* K1 */ be_const_int(2), }), be_str_weak(setitem), &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ + ( &(const binstruction[ 7]) { /* code */ 0x8C0C0100, // 0000 GETMET R3 R0 K0 - 0x08140301, // 0001 MUL R5 R1 K1 - 0x5C180400, // 0002 MOVE R6 R2 - 0x581C0001, // 0003 LDCONST R7 K1 - 0x7C0C0800, // 0004 CALL R3 4 - 0x80000000, // 0005 RET 0 + 0x54160003, // 0001 LDINT R5 4 + 0x08140205, // 0002 MUL R5 R1 R5 + 0x5C180400, // 0003 MOVE R6 R2 + 0x541E0003, // 0004 LDINT R7 4 + 0x7C0C0800, // 0005 CALL R3 4 + 0x80000000, // 0006 RET 0 }) ) ); @@ -411,96 +666,19 @@ be_local_class(lv_coord_arr, be_str_weak(lv_coord_arr) ); -extern const bclass be_class_lv_str_arr; - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(lv_str_arr_init, /* name */ - be_nested_proto( - 11, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(l), - /* K1 */ be_nested_str_weak(init), - /* K2 */ be_nested_str_weak(introspect), - /* K3 */ be_nested_str_weak(add), - /* K4 */ be_nested_str_weak(toptr), - /* K5 */ be_nested_str_weak(stop_iteration), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[31]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x60080003, // 0001 GETGBL R2 G3 - 0x5C0C0000, // 0002 MOVE R3 R0 - 0x7C080200, // 0003 CALL R2 1 - 0x8C080501, // 0004 GETMET R2 R2 K1 - 0x6010000C, // 0005 GETGBL R4 G12 - 0x5C140200, // 0006 MOVE R5 R1 - 0x7C100200, // 0007 CALL R4 1 - 0x54160003, // 0008 LDINT R5 4 - 0x08100805, // 0009 MUL R4 R4 R5 - 0x7C080400, // 000A CALL R2 2 - 0xA40A0400, // 000B IMPORT R2 K2 - 0x600C0010, // 000C GETGBL R3 G16 - 0x5C100200, // 000D MOVE R4 R1 - 0x7C0C0200, // 000E CALL R3 1 - 0xA802000A, // 000F EXBLK 0 #001B - 0x5C100600, // 0010 MOVE R4 R3 - 0x7C100000, // 0011 CALL R4 0 - 0x8C140103, // 0012 GETMET R5 R0 K3 - 0x601C0009, // 0013 GETGBL R7 G9 - 0x8C200504, // 0014 GETMET R8 R2 K4 - 0x5C280800, // 0015 MOVE R10 R4 - 0x7C200400, // 0016 CALL R8 2 - 0x7C1C0200, // 0017 CALL R7 1 - 0x54220003, // 0018 LDINT R8 4 - 0x7C140600, // 0019 CALL R5 3 - 0x7001FFF4, // 001A JMP #0010 - 0x580C0005, // 001B LDCONST R3 K5 - 0xAC0C0200, // 001C CATCH R3 1 0 - 0xB0080000, // 001D RAISE 2 R0 R0 - 0x80000000, // 001E RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified class: lv_str_arr -********************************************************************/ -extern const bclass be_class_bytes; -be_local_class(lv_str_arr, - 1, - &be_class_bytes, - be_nested_map(2, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(init, -1), be_const_closure(lv_str_arr_init_closure) }, - { be_const_key_weak(l, 0), be_const_var(0) }, - })), - be_str_weak(lv_str_arr) -); - /******************************************************************** ** Solidified module: lv_extra ********************************************************************/ be_local_module(lv_extra, "lv_extra", - be_nested_map(5, + be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(init, -1), be_const_closure(lv_extra__anonymous__closure) }, - { be_const_key_weak(lv_coord_arr, -1), be_const_class(be_class_lv_coord_arr) }, - { be_const_key_weak(lv_str_arr, -1), be_const_class(be_class_lv_str_arr) }, + { be_const_key_weak(lv_coord_arr, 4), be_const_class(be_class_lv_coord_arr) }, + { be_const_key_weak(lv_int_arr, -1), be_const_class(be_class_lv_int_arr) }, { be_const_key_weak(lv_point_arr, -1), be_const_class(be_class_lv_point_arr) }, - { be_const_key_weak(lv_style_prop_arr, 2), be_const_class(be_class_lv_style_prop_arr) }, + { be_const_key_weak(init, -1), be_const_closure(lv_extra__anonymous__closure) }, + { be_const_key_weak(lv_style_prop_arr, -1), be_const_class(be_class_lv_style_prop_arr) }, + { be_const_key_weak(lv_str_arr, 0), be_const_class(be_class_lv_str_arr) }, })) ); BE_EXPORT_VARIABLE be_define_const_native_module(lv_extra); diff --git a/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lvgl_glob.h b/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lvgl_glob.h index de8ef361a..862f36e6e 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lvgl_glob.h +++ b/lib/libesp32_lvgl/lv_binding_berry/src/solidify/solidified_lvgl_glob.h @@ -7,172 +7,87 @@ extern const bclass be_class_LVGL_glob; /******************************************************************** -** Solidified function: get_object_from_ptr +** Solidified function: get_event_cb ********************************************************************/ -be_local_closure(LVGL_glob_get_object_from_ptr, /* name */ +be_local_closure(LVGL_glob_get_event_cb, /* name */ be_nested_proto( - 5, /* nstack */ + 9, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(cb_obj), - /* K1 */ be_nested_str_weak(find), + 1, /* has sup protos */ + ( &(const struct bproto*[ 1]) { + be_nested_proto( + 5, /* nstack */ + 1, /* argc */ + 0, /* varg */ + 1, /* has upvals */ + ( &(const bupvaldesc[ 2]) { /* upvals */ + be_local_const_upval(1, 0), + be_local_const_upval(1, 4), + }), + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(lvgl_event_dispatch), + }), + be_str_weak(_X3Clambda_X3E), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0x68040000, // 0000 GETUPV R1 U0 + 0x8C040300, // 0001 GETMET R1 R1 K0 + 0x680C0001, // 0002 GETUPV R3 U1 + 0x5C100000, // 0003 MOVE R4 R0 + 0x7C040600, // 0004 CALL R1 3 + 0x80040200, // 0005 RET 1 R1 + }) + ), }), - be_str_weak(get_object_from_ptr), + 1, /* has constants */ + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(event_cb), + /* K1 */ be_nested_str_weak(cb), + /* K2 */ be_nested_str_weak(gen_cb), + /* K3 */ be_nested_str_weak(push), + /* K4 */ be_nested_str_weak(stop_iteration), + }), + be_str_weak(get_event_cb), &be_const_str_solidified, - ( &(const binstruction[10]) { /* code */ + ( &(const binstruction[32]) { /* code */ 0x88080100, // 0000 GETMBR R2 R0 K0 0x4C0C0000, // 0001 LDNIL R3 - 0x20080403, // 0002 NE R2 R2 R3 - 0x780A0004, // 0003 JMPF R2 #0009 - 0x88080100, // 0004 GETMBR R2 R0 K0 - 0x8C080501, // 0005 GETMET R2 R2 K1 - 0x5C100200, // 0006 MOVE R4 R1 - 0x7C080400, // 0007 CALL R2 2 - 0x80040400, // 0008 RET 1 R2 - 0x80000000, // 0009 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: create_custom_widget -********************************************************************/ -be_local_closure(LVGL_glob_create_custom_widget, /* name */ - be_nested_proto( - 10, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[27]) { /* constants */ - /* K0 */ be_nested_str_weak(introspect), - /* K1 */ be_nested_str_weak(lv), - /* K2 */ be_nested_str_weak(lv_obj), - /* K3 */ be_nested_str_weak(value_error), - /* K4 */ be_nested_str_weak(arg_X20must_X20be_X20a_X20subclass_X20of_X20lv_obj), - /* K5 */ be_nested_str_weak(widget_struct_by_class), - /* K6 */ be_nested_str_weak(find), - /* K7 */ be_nested_str_weak(widget_cb), - /* K8 */ be_nested_str_weak(widget_struct_default), - /* K9 */ be_nested_str_weak(copy), - /* K10 */ be_nested_str_weak(base_class), - /* K11 */ be_nested_str_weak(_class), - /* K12 */ be_nested_str_weak(get), - /* K13 */ be_nested_str_weak(widget_width_def), - /* K14 */ be_nested_str_weak(width_def), - /* K15 */ be_nested_str_weak(widget_height_def), - /* K16 */ be_nested_str_weak(height_def), - /* K17 */ be_nested_str_weak(widget_editable), - /* K18 */ be_nested_str_weak(editable), - /* K19 */ be_nested_str_weak(widget_group_def), - /* K20 */ be_nested_str_weak(group_def), - /* K21 */ be_nested_str_weak(widget_instance_size), - /* K22 */ be_nested_str_weak(instance_size), - /* K23 */ be_nested_str_weak(obj_class_create_obj), - /* K24 */ be_nested_str_weak(_p), - /* K25 */ be_nested_str_weak(register_obj), - /* K26 */ be_nested_str_weak(class_init_obj), - }), - be_str_weak(create_custom_widget), - &be_const_str_solidified, - ( &(const binstruction[86]) { /* code */ - 0xA40E0000, // 0000 IMPORT R3 K0 - 0x6010000F, // 0001 GETGBL R4 G15 - 0x5C140200, // 0002 MOVE R5 R1 - 0xB81A0200, // 0003 GETNGBL R6 K1 - 0x88180D02, // 0004 GETMBR R6 R6 K2 - 0x7C100400, // 0005 CALL R4 2 - 0x74120000, // 0006 JMPT R4 #0008 - 0xB0060704, // 0007 RAISE 1 K3 K4 - 0x88100105, // 0008 GETMBR R4 R0 K5 - 0x4C140000, // 0009 LDNIL R5 - 0x1C100805, // 000A EQ R4 R4 R5 - 0x78120002, // 000B JMPF R4 #000F - 0x60100013, // 000C GETGBL R4 G19 - 0x7C100000, // 000D CALL R4 0 - 0x90020A04, // 000E SETMBR R0 K5 R4 - 0x60100005, // 000F GETGBL R4 G5 - 0x5C140200, // 0010 MOVE R5 R1 - 0x7C100200, // 0011 CALL R4 1 - 0x88140105, // 0012 GETMBR R5 R0 K5 - 0x8C140B06, // 0013 GETMET R5 R5 K6 - 0x5C1C0800, // 0014 MOVE R7 R4 - 0x7C140400, // 0015 CALL R5 2 - 0x4C180000, // 0016 LDNIL R6 - 0x1C180A06, // 0017 EQ R6 R5 R6 - 0x781A002F, // 0018 JMPF R6 #0049 - 0x8C180107, // 0019 GETMET R6 R0 K7 - 0x7C180200, // 001A CALL R6 1 - 0x88180108, // 001B GETMBR R6 R0 K8 - 0x8C180D09, // 001C GETMET R6 R6 K9 - 0x7C180200, // 001D CALL R6 1 - 0x5C140C00, // 001E MOVE R5 R6 - 0x60180003, // 001F GETGBL R6 G3 - 0x5C1C0200, // 0020 MOVE R7 R1 - 0x7C180200, // 0021 CALL R6 1 - 0x88180D0B, // 0022 GETMBR R6 R6 K11 - 0x90161406, // 0023 SETMBR R5 K10 R6 - 0x8C18070C, // 0024 GETMET R6 R3 K12 - 0x5C200200, // 0025 MOVE R8 R1 - 0x5824000D, // 0026 LDCONST R9 K13 - 0x7C180600, // 0027 CALL R6 3 - 0x781A0001, // 0028 JMPF R6 #002B - 0x8818030D, // 0029 GETMBR R6 R1 K13 - 0x90161C06, // 002A SETMBR R5 K14 R6 - 0x8C18070C, // 002B GETMET R6 R3 K12 - 0x5C200200, // 002C MOVE R8 R1 - 0x5824000F, // 002D LDCONST R9 K15 - 0x7C180600, // 002E CALL R6 3 - 0x781A0001, // 002F JMPF R6 #0032 - 0x8818030F, // 0030 GETMBR R6 R1 K15 - 0x90162006, // 0031 SETMBR R5 K16 R6 - 0x8C18070C, // 0032 GETMET R6 R3 K12 - 0x5C200200, // 0033 MOVE R8 R1 - 0x58240011, // 0034 LDCONST R9 K17 - 0x7C180600, // 0035 CALL R6 3 - 0x781A0001, // 0036 JMPF R6 #0039 - 0x88180311, // 0037 GETMBR R6 R1 K17 - 0x90162406, // 0038 SETMBR R5 K18 R6 - 0x8C18070C, // 0039 GETMET R6 R3 K12 - 0x5C200200, // 003A MOVE R8 R1 - 0x58240013, // 003B LDCONST R9 K19 - 0x7C180600, // 003C CALL R6 3 - 0x781A0001, // 003D JMPF R6 #0040 - 0x88180313, // 003E GETMBR R6 R1 K19 - 0x90162806, // 003F SETMBR R5 K20 R6 - 0x8C18070C, // 0040 GETMET R6 R3 K12 - 0x5C200200, // 0041 MOVE R8 R1 - 0x58240015, // 0042 LDCONST R9 K21 - 0x7C180600, // 0043 CALL R6 3 - 0x781A0001, // 0044 JMPF R6 #0047 - 0x88180315, // 0045 GETMBR R6 R1 K21 - 0x90162C06, // 0046 SETMBR R5 K22 R6 - 0x88180105, // 0047 GETMBR R6 R0 K5 - 0x98180805, // 0048 SETIDX R6 R4 R5 - 0xB81A0200, // 0049 GETNGBL R6 K1 - 0x8C180D17, // 004A GETMET R6 R6 K23 - 0x5C200A00, // 004B MOVE R8 R5 - 0x5C240400, // 004C MOVE R9 R2 - 0x7C180600, // 004D CALL R6 3 - 0x881C0D18, // 004E GETMBR R7 R6 K24 - 0x90063007, // 004F SETMBR R1 K24 R7 - 0x8C1C0119, // 0050 GETMET R7 R0 K25 - 0x5C240200, // 0051 MOVE R9 R1 - 0x7C1C0400, // 0052 CALL R7 2 - 0x8C1C031A, // 0053 GETMET R7 R1 K26 - 0x7C1C0200, // 0054 CALL R7 1 - 0x80000000, // 0055 RET 0 + 0x1C080403, // 0002 EQ R2 R2 R3 + 0x780A0002, // 0003 JMPF R2 #0007 + 0x60080012, // 0004 GETGBL R2 G18 + 0x7C080000, // 0005 CALL R2 0 + 0x90020002, // 0006 SETMBR R0 K0 R2 + 0x88080100, // 0007 GETMBR R2 R0 K0 + 0x600C0010, // 0008 GETGBL R3 G16 + 0x6010000C, // 0009 GETGBL R4 G12 + 0x5C140400, // 000A MOVE R5 R2 + 0x7C100200, // 000B CALL R4 1 + 0x40100801, // 000C CONNECT R4 R4 R1 + 0x7C0C0200, // 000D CALL R3 1 + 0xA802000A, // 000E EXBLK 0 #001A + 0x5C100600, // 000F MOVE R4 R3 + 0x7C100000, // 0010 CALL R4 0 + 0xB8160200, // 0011 GETNGBL R5 K1 + 0x8C140B02, // 0012 GETMET R5 R5 K2 + 0x841C0000, // 0013 CLOSURE R7 P0 + 0x7C140400, // 0014 CALL R5 2 + 0x8C180503, // 0015 GETMET R6 R2 K3 + 0x5C200A00, // 0016 MOVE R8 R5 + 0x7C180400, // 0017 CALL R6 2 + 0xA00C0000, // 0018 CLOSE R3 + 0x7001FFF4, // 0019 JMP #000F + 0x580C0004, // 001A LDCONST R3 K4 + 0xAC0C0200, // 001B CATCH R3 1 0 + 0xB0080000, // 001C RAISE 2 R0 R0 + 0x940C0401, // 001D GETIDX R3 R2 R1 + 0xA0000000, // 001E CLOSE R0 + 0x80040600, // 001F RET 1 R3 }) ) ); @@ -252,310 +167,6 @@ be_local_closure(LVGL_glob_add_cb_event_closure, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: _anonymous_ -********************************************************************/ -be_local_closure(LVGL_glob__anonymous_, /* name */ - be_nested_proto( - 2, /* nstack */ - 0, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(LVG_X3A_X20call_X20to_X20unsupported_X20callback), - }), - be_str_weak(_anonymous_), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x60000001, // 0000 GETGBL R0 G1 - 0x58040000, // 0001 LDCONST R1 K0 - 0x7C000200, // 0002 CALL R0 1 - 0x80000000, // 0003 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: widget_ctor_impl -********************************************************************/ -be_local_closure(LVGL_glob_widget_ctor_impl, /* name */ - be_nested_proto( - 10, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(introspect), - /* K1 */ be_nested_str_weak(lv), - /* K2 */ be_nested_str_weak(lv_obj_class), - /* K3 */ be_nested_str_weak(get_object_from_ptr), - /* K4 */ be_nested_str_weak(cb_obj), - /* K5 */ be_nested_str_weak(find), - /* K6 */ be_nested_str_weak(instance), - /* K7 */ be_nested_str_weak(get), - /* K8 */ be_nested_str_weak(widget_constructor), - }), - be_str_weak(widget_ctor_impl), - &be_const_str_solidified, - ( &(const binstruction[29]) { /* code */ - 0xA40E0000, // 0000 IMPORT R3 K0 - 0xB8120200, // 0001 GETNGBL R4 K1 - 0x8C100902, // 0002 GETMET R4 R4 K2 - 0x5C180200, // 0003 MOVE R6 R1 - 0x7C100400, // 0004 CALL R4 2 - 0x8C140103, // 0005 GETMET R5 R0 K3 - 0x5C1C0400, // 0006 MOVE R7 R2 - 0x7C140400, // 0007 CALL R5 2 - 0x88180104, // 0008 GETMBR R6 R0 K4 - 0x8C180D05, // 0009 GETMET R6 R6 K5 - 0x5C200A00, // 000A MOVE R8 R5 - 0x7C180400, // 000B CALL R6 2 - 0x781A0001, // 000C JMPF R6 #000F - 0x88180104, // 000D GETMBR R6 R0 K4 - 0x94140C05, // 000E GETIDX R5 R6 R5 - 0x60180004, // 000F GETGBL R6 G4 - 0x5C1C0A00, // 0010 MOVE R7 R5 - 0x7C180200, // 0011 CALL R6 1 - 0x1C180D06, // 0012 EQ R6 R6 K6 - 0x781A0007, // 0013 JMPF R6 #001C - 0x8C180707, // 0014 GETMET R6 R3 K7 - 0x5C200A00, // 0015 MOVE R8 R5 - 0x58240008, // 0016 LDCONST R9 K8 - 0x7C180600, // 0017 CALL R6 3 - 0x781A0002, // 0018 JMPF R6 #001C - 0x8C180B08, // 0019 GETMET R6 R5 K8 - 0x5C200800, // 001A MOVE R8 R4 - 0x7C180400, // 001B CALL R6 2 - 0x80000000, // 001C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: deregister_obj -********************************************************************/ -be_local_closure(LVGL_glob_deregister_obj, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(cb_obj), - /* K1 */ be_nested_str_weak(remove), - /* K2 */ be_nested_str_weak(cb_event_closure), - }), - be_str_weak(deregister_obj), - &be_const_str_solidified, - ( &(const binstruction[17]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x20080403, // 0002 NE R2 R2 R3 - 0x780A0003, // 0003 JMPF R2 #0008 - 0x88080100, // 0004 GETMBR R2 R0 K0 - 0x8C080501, // 0005 GETMET R2 R2 K1 - 0x5C100200, // 0006 MOVE R4 R1 - 0x7C080400, // 0007 CALL R2 2 - 0x88080102, // 0008 GETMBR R2 R0 K2 - 0x4C0C0000, // 0009 LDNIL R3 - 0x20080403, // 000A NE R2 R2 R3 - 0x780A0003, // 000B JMPF R2 #0010 - 0x88080102, // 000C GETMBR R2 R0 K2 - 0x8C080501, // 000D GETMET R2 R2 K1 - 0x5C100200, // 000E MOVE R4 R1 - 0x7C080400, // 000F CALL R2 2 - 0x80000000, // 0010 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: widget_event_impl -********************************************************************/ -be_local_closure(LVGL_glob_widget_event_impl, /* name */ - be_nested_proto( - 12, /* nstack */ - 3, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[12]) { /* constants */ - /* K0 */ be_nested_str_weak(introspect), - /* K1 */ be_nested_str_weak(lv), - /* K2 */ be_nested_str_weak(lv_obj_class), - /* K3 */ be_nested_str_weak(lv_event), - /* K4 */ be_nested_str_weak(target), - /* K5 */ be_nested_str_weak(get_object_from_ptr), - /* K6 */ be_nested_str_weak(instance), - /* K7 */ be_nested_str_weak(code), - /* K8 */ be_nested_str_weak(EVENT_DELETE), - /* K9 */ be_nested_str_weak(get), - /* K10 */ be_nested_str_weak(before_del), - /* K11 */ be_nested_str_weak(widget_event), - }), - be_str_weak(widget_event_impl), - &be_const_str_solidified, - ( &(const binstruction[43]) { /* code */ - 0xA40E0000, // 0000 IMPORT R3 K0 - 0xB8120200, // 0001 GETNGBL R4 K1 - 0x8C100902, // 0002 GETMET R4 R4 K2 - 0x5C180200, // 0003 MOVE R6 R1 - 0x7C100400, // 0004 CALL R4 2 - 0xB8160200, // 0005 GETNGBL R5 K1 - 0x8C140B03, // 0006 GETMET R5 R5 K3 - 0x5C1C0400, // 0007 MOVE R7 R2 - 0x7C140400, // 0008 CALL R5 2 - 0x88180B04, // 0009 GETMBR R6 R5 K4 - 0x8C1C0105, // 000A GETMET R7 R0 K5 - 0x5C240C00, // 000B MOVE R9 R6 - 0x7C1C0400, // 000C CALL R7 2 - 0x60200004, // 000D GETGBL R8 G4 - 0x5C240E00, // 000E MOVE R9 R7 - 0x7C200200, // 000F CALL R8 1 - 0x1C201106, // 0010 EQ R8 R8 K6 - 0x78220017, // 0011 JMPF R8 #002A - 0x88200B07, // 0012 GETMBR R8 R5 K7 - 0xB8260200, // 0013 GETNGBL R9 K1 - 0x88241308, // 0014 GETMBR R9 R9 K8 - 0x1C201009, // 0015 EQ R8 R8 R9 - 0x78220009, // 0016 JMPF R8 #0021 - 0x8C200709, // 0017 GETMET R8 R3 K9 - 0x5C280E00, // 0018 MOVE R10 R7 - 0x582C000A, // 0019 LDCONST R11 K10 - 0x7C200600, // 001A CALL R8 3 - 0x78220004, // 001B JMPF R8 #0021 - 0x8C200F0A, // 001C GETMET R8 R7 K10 - 0x5C280800, // 001D MOVE R10 R4 - 0x5C2C0A00, // 001E MOVE R11 R5 - 0x7C200600, // 001F CALL R8 3 - 0x70020008, // 0020 JMP #002A - 0x8C200709, // 0021 GETMET R8 R3 K9 - 0x5C280E00, // 0022 MOVE R10 R7 - 0x582C000B, // 0023 LDCONST R11 K11 - 0x7C200600, // 0024 CALL R8 3 - 0x78220003, // 0025 JMPF R8 #002A - 0x8C200F0B, // 0026 GETMET R8 R7 K11 - 0x5C280800, // 0027 MOVE R10 R4 - 0x5C2C0A00, // 0028 MOVE R11 R5 - 0x7C200600, // 0029 CALL R8 3 - 0x80000000, // 002A RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: remove_cb -********************************************************************/ -be_local_closure(LVGL_glob_remove_cb, /* name */ - be_nested_proto( - 7, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(introspect), - /* K1 */ be_nested_str_weak(_p), - /* K2 */ be_nested_str_weak(deregister_obj), - }), - be_str_weak(remove_cb), - &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0x880C0301, // 0001 GETMBR R3 R1 K1 - 0x8C100102, // 0002 GETMET R4 R0 K2 - 0x5C180600, // 0003 MOVE R6 R3 - 0x7C100400, // 0004 CALL R4 2 - 0x80000000, // 0005 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: lvgl_timer_dispatch -********************************************************************/ -be_local_closure(LVGL_glob_lvgl_timer_dispatch, /* name */ - be_nested_proto( - 8, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(introspect), - /* K1 */ be_nested_str_weak(toptr), - /* K2 */ be_nested_str_weak(cb_event_closure), - /* K3 */ be_nested_str_weak(function), - /* K4 */ be_const_int(0), - /* K5 */ be_const_int(1), - }), - be_str_weak(lvgl_timer_dispatch), - &be_const_str_solidified, - ( &(const binstruction[27]) { /* code */ - 0xA40A0000, // 0000 IMPORT R2 K0 - 0x8C0C0501, // 0001 GETMET R3 R2 K1 - 0x5C140200, // 0002 MOVE R5 R1 - 0x7C0C0400, // 0003 CALL R3 2 - 0x88100102, // 0004 GETMBR R4 R0 K2 - 0x94100803, // 0005 GETIDX R4 R4 R3 - 0x60140004, // 0006 GETGBL R5 G4 - 0x5C180800, // 0007 MOVE R6 R4 - 0x7C140200, // 0008 CALL R5 1 - 0x1C140B03, // 0009 EQ R5 R5 K3 - 0x78160003, // 000A JMPF R5 #000F - 0x5C140800, // 000B MOVE R5 R4 - 0x5C180600, // 000C MOVE R6 R3 - 0x7C140200, // 000D CALL R5 1 - 0x7002000A, // 000E JMP #001A - 0x58140004, // 000F LDCONST R5 K4 - 0x6018000C, // 0010 GETGBL R6 G12 - 0x5C1C0800, // 0011 MOVE R7 R4 - 0x7C180200, // 0012 CALL R6 1 - 0x14180A06, // 0013 LT R6 R5 R6 - 0x781A0004, // 0014 JMPF R6 #001A - 0x94180805, // 0015 GETIDX R6 R4 R5 - 0x5C1C0600, // 0016 MOVE R7 R3 - 0x7C180200, // 0017 CALL R6 1 - 0x00140B05, // 0018 ADD R5 R5 K5 - 0x7001FFF5, // 0019 JMP #0010 - 0x80000000, // 001A RET 0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: make_cb ********************************************************************/ @@ -717,87 +328,56 @@ be_local_closure(LVGL_glob_make_cb, /* name */ /******************************************************************** -** Solidified function: get_event_cb +** Solidified function: lvgl_timer_dispatch ********************************************************************/ -be_local_closure(LVGL_glob_get_event_cb, /* name */ +be_local_closure(LVGL_glob_lvgl_timer_dispatch, /* name */ be_nested_proto( - 9, /* nstack */ + 8, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ - 1, /* has sup protos */ - ( &(const struct bproto*[ 1]) { - be_nested_proto( - 5, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 1, /* has upvals */ - ( &(const bupvaldesc[ 2]) { /* upvals */ - be_local_const_upval(1, 0), - be_local_const_upval(1, 4), - }), - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(lvgl_event_dispatch), - }), - be_str_weak(_X3Clambda_X3E), - &be_const_str_solidified, - ( &(const binstruction[ 6]) { /* code */ - 0x68040000, // 0000 GETUPV R1 U0 - 0x8C040300, // 0001 GETMET R1 R1 K0 - 0x680C0001, // 0002 GETUPV R3 U1 - 0x5C100000, // 0003 MOVE R4 R0 - 0x7C040600, // 0004 CALL R1 3 - 0x80040200, // 0005 RET 1 R1 - }) - ), - }), + 0, /* has sup protos */ + NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(event_cb), - /* K1 */ be_nested_str_weak(cb), - /* K2 */ be_nested_str_weak(gen_cb), - /* K3 */ be_nested_str_weak(push), - /* K4 */ be_nested_str_weak(stop_iteration), + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(introspect), + /* K1 */ be_nested_str_weak(toptr), + /* K2 */ be_nested_str_weak(cb_event_closure), + /* K3 */ be_nested_str_weak(function), + /* K4 */ be_const_int(0), + /* K5 */ be_const_int(1), }), - be_str_weak(get_event_cb), + be_str_weak(lvgl_timer_dispatch), &be_const_str_solidified, - ( &(const binstruction[32]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x1C080403, // 0002 EQ R2 R2 R3 - 0x780A0002, // 0003 JMPF R2 #0007 - 0x60080012, // 0004 GETGBL R2 G18 - 0x7C080000, // 0005 CALL R2 0 - 0x90020002, // 0006 SETMBR R0 K0 R2 - 0x88080100, // 0007 GETMBR R2 R0 K0 - 0x600C0010, // 0008 GETGBL R3 G16 - 0x6010000C, // 0009 GETGBL R4 G12 - 0x5C140400, // 000A MOVE R5 R2 - 0x7C100200, // 000B CALL R4 1 - 0x40100801, // 000C CONNECT R4 R4 R1 - 0x7C0C0200, // 000D CALL R3 1 - 0xA802000A, // 000E EXBLK 0 #001A - 0x5C100600, // 000F MOVE R4 R3 - 0x7C100000, // 0010 CALL R4 0 - 0xB8160200, // 0011 GETNGBL R5 K1 - 0x8C140B02, // 0012 GETMET R5 R5 K2 - 0x841C0000, // 0013 CLOSURE R7 P0 - 0x7C140400, // 0014 CALL R5 2 - 0x8C180503, // 0015 GETMET R6 R2 K3 - 0x5C200A00, // 0016 MOVE R8 R5 - 0x7C180400, // 0017 CALL R6 2 - 0xA00C0000, // 0018 CLOSE R3 - 0x7001FFF4, // 0019 JMP #000F - 0x580C0004, // 001A LDCONST R3 K4 - 0xAC0C0200, // 001B CATCH R3 1 0 - 0xB0080000, // 001C RAISE 2 R0 R0 - 0x940C0401, // 001D GETIDX R3 R2 R1 - 0xA0000000, // 001E CLOSE R0 - 0x80040600, // 001F RET 1 R3 + ( &(const binstruction[27]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0x8C0C0501, // 0001 GETMET R3 R2 K1 + 0x5C140200, // 0002 MOVE R5 R1 + 0x7C0C0400, // 0003 CALL R3 2 + 0x88100102, // 0004 GETMBR R4 R0 K2 + 0x94100803, // 0005 GETIDX R4 R4 R3 + 0x60140004, // 0006 GETGBL R5 G4 + 0x5C180800, // 0007 MOVE R6 R4 + 0x7C140200, // 0008 CALL R5 1 + 0x1C140B03, // 0009 EQ R5 R5 K3 + 0x78160003, // 000A JMPF R5 #000F + 0x5C140800, // 000B MOVE R5 R4 + 0x5C180600, // 000C MOVE R6 R3 + 0x7C140200, // 000D CALL R5 1 + 0x7002000A, // 000E JMP #001A + 0x58140004, // 000F LDCONST R5 K4 + 0x6018000C, // 0010 GETGBL R6 G12 + 0x5C1C0800, // 0011 MOVE R7 R4 + 0x7C180200, // 0012 CALL R6 1 + 0x14180A06, // 0013 LT R6 R5 R6 + 0x781A0004, // 0014 JMPF R6 #001A + 0x94180805, // 0015 GETIDX R6 R4 R5 + 0x5C1C0600, // 0016 MOVE R7 R3 + 0x7C180200, // 0017 CALL R6 1 + 0x00140B05, // 0018 ADD R5 R5 K5 + 0x7001FFF5, // 0019 JMP #0010 + 0x80000000, // 001A RET 0 }) ) ); @@ -821,60 +401,103 @@ be_local_closure(LVGL_glob_lvgl_event_dispatch, /* name */ /* K0 */ be_nested_str_weak(introspect), /* K1 */ be_nested_str_weak(toptr), /* K2 */ be_nested_str_weak(event), - /* K3 */ be_nested_str_weak(_change_buffer), + /* K3 */ be_nested_str_weak(_p), /* K4 */ be_nested_str_weak(lv), /* K5 */ be_nested_str_weak(lv_event), - /* K6 */ be_nested_str_weak(target), + /* K6 */ be_nested_str_weak(get_target), /* K7 */ be_nested_str_weak(get_object_from_ptr), /* K8 */ be_nested_str_weak(cb_event_closure), /* K9 */ be_nested_str_weak(function), }), be_str_weak(lvgl_event_dispatch), &be_const_str_solidified, - ( &(const binstruction[43]) { /* code */ + ( &(const binstruction[42]) { /* code */ 0xA40E0000, // 0000 IMPORT R3 K0 0x8C100701, // 0001 GETMET R4 R3 K1 0x5C180400, // 0002 MOVE R6 R2 0x7C100400, // 0003 CALL R4 2 0x88140102, // 0004 GETMBR R5 R0 K2 - 0x78160004, // 0005 JMPF R5 #000B + 0x78160002, // 0005 JMPF R5 #0009 0x88140102, // 0006 GETMBR R5 R0 K2 - 0x8C140B03, // 0007 GETMET R5 R5 K3 - 0x5C1C0800, // 0008 MOVE R7 R4 - 0x7C140400, // 0009 CALL R5 2 - 0x70020004, // 000A JMP #0010 - 0xB8160800, // 000B GETNGBL R5 K4 - 0x8C140B05, // 000C GETMET R5 R5 K5 - 0x5C1C0800, // 000D MOVE R7 R4 - 0x7C140400, // 000E CALL R5 2 - 0x90020405, // 000F SETMBR R0 K2 R5 - 0x88140102, // 0010 GETMBR R5 R0 K2 - 0x88140B06, // 0011 GETMBR R5 R5 K6 - 0x8C180107, // 0012 GETMET R6 R0 K7 - 0x5C200A00, // 0013 MOVE R8 R5 - 0x7C180400, // 0014 CALL R6 2 - 0x881C0108, // 0015 GETMBR R7 R0 K8 - 0x941C0E05, // 0016 GETIDX R7 R7 R5 - 0x60200004, // 0017 GETGBL R8 G4 - 0x5C240E00, // 0018 MOVE R9 R7 - 0x7C200200, // 0019 CALL R8 1 - 0x1C201109, // 001A EQ R8 R8 K9 - 0x78220004, // 001B JMPF R8 #0021 - 0x5C200E00, // 001C MOVE R8 R7 - 0x5C240C00, // 001D MOVE R9 R6 - 0x88280102, // 001E GETMBR R10 R0 K2 - 0x7C200400, // 001F CALL R8 2 - 0x70020008, // 0020 JMP #002A - 0x6020000C, // 0021 GETGBL R8 G12 - 0x5C240E00, // 0022 MOVE R9 R7 - 0x7C200200, // 0023 CALL R8 1 - 0x14200208, // 0024 LT R8 R1 R8 - 0x78220003, // 0025 JMPF R8 #002A - 0x94200E01, // 0026 GETIDX R8 R7 R1 - 0x5C240C00, // 0027 MOVE R9 R6 - 0x88280102, // 0028 GETMBR R10 R0 K2 - 0x7C200400, // 0029 CALL R8 2 - 0x80000000, // 002A RET 0 + 0x90160604, // 0007 SETMBR R5 K3 R4 + 0x70020004, // 0008 JMP #000E + 0xB8160800, // 0009 GETNGBL R5 K4 + 0x8C140B05, // 000A GETMET R5 R5 K5 + 0x5C1C0800, // 000B MOVE R7 R4 + 0x7C140400, // 000C CALL R5 2 + 0x90020405, // 000D SETMBR R0 K2 R5 + 0x88140102, // 000E GETMBR R5 R0 K2 + 0x8C140B06, // 000F GETMET R5 R5 K6 + 0x7C140200, // 0010 CALL R5 1 + 0x8C180107, // 0011 GETMET R6 R0 K7 + 0x5C200A00, // 0012 MOVE R8 R5 + 0x7C180400, // 0013 CALL R6 2 + 0x881C0108, // 0014 GETMBR R7 R0 K8 + 0x941C0E05, // 0015 GETIDX R7 R7 R5 + 0x60200004, // 0016 GETGBL R8 G4 + 0x5C240E00, // 0017 MOVE R9 R7 + 0x7C200200, // 0018 CALL R8 1 + 0x1C201109, // 0019 EQ R8 R8 K9 + 0x78220004, // 001A JMPF R8 #0020 + 0x5C200E00, // 001B MOVE R8 R7 + 0x5C240C00, // 001C MOVE R9 R6 + 0x88280102, // 001D GETMBR R10 R0 K2 + 0x7C200400, // 001E CALL R8 2 + 0x70020008, // 001F JMP #0029 + 0x6020000C, // 0020 GETGBL R8 G12 + 0x5C240E00, // 0021 MOVE R9 R7 + 0x7C200200, // 0022 CALL R8 1 + 0x14200208, // 0023 LT R8 R1 R8 + 0x78220003, // 0024 JMPF R8 #0029 + 0x94200E01, // 0025 GETIDX R8 R7 R1 + 0x5C240C00, // 0026 MOVE R9 R6 + 0x88280102, // 0027 GETMBR R10 R0 K2 + 0x7C200400, // 0028 CALL R8 2 + 0x80000000, // 0029 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: deregister_obj +********************************************************************/ +be_local_closure(LVGL_glob_deregister_obj, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(cb_obj), + /* K1 */ be_nested_str_weak(remove), + /* K2 */ be_nested_str_weak(cb_event_closure), + }), + be_str_weak(deregister_obj), + &be_const_str_solidified, + ( &(const binstruction[17]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x20080403, // 0002 NE R2 R2 R3 + 0x780A0003, // 0003 JMPF R2 #0008 + 0x88080100, // 0004 GETMBR R2 R0 K0 + 0x8C080501, // 0005 GETMET R2 R2 K1 + 0x5C100200, // 0006 MOVE R4 R1 + 0x7C080400, // 0007 CALL R2 2 + 0x88080102, // 0008 GETMBR R2 R0 K2 + 0x4C0C0000, // 0009 LDNIL R3 + 0x20080403, // 000A NE R2 R2 R3 + 0x780A0003, // 000B JMPF R2 #0010 + 0x88080102, // 000C GETMBR R2 R0 K2 + 0x8C080501, // 000D GETMET R2 R2 K1 + 0x5C100200, // 000E MOVE R4 R1 + 0x7C080400, // 000F CALL R2 2 + 0x80000000, // 0010 RET 0 }) ) ); @@ -929,6 +552,91 @@ be_local_closure(LVGL_glob_register_obj, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: widget_event_impl +********************************************************************/ +be_local_closure(LVGL_glob_widget_event_impl, /* name */ + be_nested_proto( + 12, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[14]) { /* constants */ + /* K0 */ be_nested_str_weak(introspect), + /* K1 */ be_nested_str_weak(lv), + /* K2 */ be_nested_str_weak(lv_obj_class), + /* K3 */ be_nested_str_weak(lv_event), + /* K4 */ be_nested_str_weak(toptr), + /* K5 */ be_nested_str_weak(get_target_obj), + /* K6 */ be_nested_str_weak(get_object_from_ptr), + /* K7 */ be_nested_str_weak(_p), + /* K8 */ be_nested_str_weak(instance), + /* K9 */ be_nested_str_weak(get_code), + /* K10 */ be_nested_str_weak(EVENT_DELETE), + /* K11 */ be_nested_str_weak(get), + /* K12 */ be_nested_str_weak(before_del), + /* K13 */ be_nested_str_weak(widget_event), + }), + be_str_weak(widget_event_impl), + &be_const_str_solidified, + ( &(const binstruction[47]) { /* code */ + 0xA40E0000, // 0000 IMPORT R3 K0 + 0xB8120200, // 0001 GETNGBL R4 K1 + 0x8C100902, // 0002 GETMET R4 R4 K2 + 0x5C180200, // 0003 MOVE R6 R1 + 0x7C100400, // 0004 CALL R4 2 + 0xB8160200, // 0005 GETNGBL R5 K1 + 0x8C140B03, // 0006 GETMET R5 R5 K3 + 0x8C1C0704, // 0007 GETMET R7 R3 K4 + 0x5C240400, // 0008 MOVE R9 R2 + 0x7C1C0400, // 0009 CALL R7 2 + 0x7C140400, // 000A CALL R5 2 + 0x8C180B05, // 000B GETMET R6 R5 K5 + 0x7C180200, // 000C CALL R6 1 + 0x8C1C0106, // 000D GETMET R7 R0 K6 + 0x88240D07, // 000E GETMBR R9 R6 K7 + 0x7C1C0400, // 000F CALL R7 2 + 0x60200004, // 0010 GETGBL R8 G4 + 0x5C240E00, // 0011 MOVE R9 R7 + 0x7C200200, // 0012 CALL R8 1 + 0x1C201108, // 0013 EQ R8 R8 K8 + 0x78220018, // 0014 JMPF R8 #002E + 0x8C200B09, // 0015 GETMET R8 R5 K9 + 0x7C200200, // 0016 CALL R8 1 + 0xB8260200, // 0017 GETNGBL R9 K1 + 0x8824130A, // 0018 GETMBR R9 R9 K10 + 0x1C201009, // 0019 EQ R8 R8 R9 + 0x78220009, // 001A JMPF R8 #0025 + 0x8C20070B, // 001B GETMET R8 R3 K11 + 0x5C280E00, // 001C MOVE R10 R7 + 0x582C000C, // 001D LDCONST R11 K12 + 0x7C200600, // 001E CALL R8 3 + 0x78220004, // 001F JMPF R8 #0025 + 0x8C200F0C, // 0020 GETMET R8 R7 K12 + 0x5C280800, // 0021 MOVE R10 R4 + 0x5C2C0A00, // 0022 MOVE R11 R5 + 0x7C200600, // 0023 CALL R8 3 + 0x70020008, // 0024 JMP #002E + 0x8C20070B, // 0025 GETMET R8 R3 K11 + 0x5C280E00, // 0026 MOVE R10 R7 + 0x582C000D, // 0027 LDCONST R11 K13 + 0x7C200600, // 0028 CALL R8 3 + 0x78220003, // 0029 JMPF R8 #002E + 0x8C200F0D, // 002A GETMET R8 R7 K13 + 0x5C280800, // 002B MOVE R10 R4 + 0x5C2C0A00, // 002C MOVE R11 R5 + 0x7C200600, // 002D CALL R8 3 + 0x80000000, // 002E RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: widget_dtor_impl ********************************************************************/ @@ -982,6 +690,97 @@ be_local_closure(LVGL_glob_widget_dtor_impl, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: widget_ctor_impl +********************************************************************/ +be_local_closure(LVGL_glob_widget_ctor_impl, /* name */ + be_nested_proto( + 10, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(introspect), + /* K1 */ be_nested_str_weak(lv), + /* K2 */ be_nested_str_weak(lv_obj_class), + /* K3 */ be_nested_str_weak(get_object_from_ptr), + /* K4 */ be_nested_str_weak(cb_obj), + /* K5 */ be_nested_str_weak(find), + /* K6 */ be_nested_str_weak(instance), + /* K7 */ be_nested_str_weak(get), + /* K8 */ be_nested_str_weak(widget_constructor), + }), + be_str_weak(widget_ctor_impl), + &be_const_str_solidified, + ( &(const binstruction[29]) { /* code */ + 0xA40E0000, // 0000 IMPORT R3 K0 + 0xB8120200, // 0001 GETNGBL R4 K1 + 0x8C100902, // 0002 GETMET R4 R4 K2 + 0x5C180200, // 0003 MOVE R6 R1 + 0x7C100400, // 0004 CALL R4 2 + 0x8C140103, // 0005 GETMET R5 R0 K3 + 0x5C1C0400, // 0006 MOVE R7 R2 + 0x7C140400, // 0007 CALL R5 2 + 0x88180104, // 0008 GETMBR R6 R0 K4 + 0x8C180D05, // 0009 GETMET R6 R6 K5 + 0x5C200A00, // 000A MOVE R8 R5 + 0x7C180400, // 000B CALL R6 2 + 0x781A0001, // 000C JMPF R6 #000F + 0x88180104, // 000D GETMBR R6 R0 K4 + 0x94140C05, // 000E GETIDX R5 R6 R5 + 0x60180004, // 000F GETGBL R6 G4 + 0x5C1C0A00, // 0010 MOVE R7 R5 + 0x7C180200, // 0011 CALL R6 1 + 0x1C180D06, // 0012 EQ R6 R6 K6 + 0x781A0007, // 0013 JMPF R6 #001C + 0x8C180707, // 0014 GETMET R6 R3 K7 + 0x5C200A00, // 0015 MOVE R8 R5 + 0x58240008, // 0016 LDCONST R9 K8 + 0x7C180600, // 0017 CALL R6 3 + 0x781A0002, // 0018 JMPF R6 #001C + 0x8C180B08, // 0019 GETMET R6 R5 K8 + 0x5C200800, // 001A MOVE R8 R4 + 0x7C180400, // 001B CALL R6 2 + 0x80000000, // 001C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: _anonymous_ +********************************************************************/ +be_local_closure(LVGL_glob__anonymous_, /* name */ + be_nested_proto( + 2, /* nstack */ + 0, /* argc */ + 0, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(LVG_X3A_X20call_X20to_X20unsupported_X20callback), + }), + be_str_weak(_anonymous_), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x60000001, // 0000 GETGBL R0 G1 + 0x58040000, // 0001 LDCONST R1 K0 + 0x7C000200, // 0002 CALL R0 1 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: init ********************************************************************/ @@ -1043,6 +842,179 @@ be_local_closure(LVGL_glob_init, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: get_object_from_ptr +********************************************************************/ +be_local_closure(LVGL_glob_get_object_from_ptr, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(cb_obj), + /* K1 */ be_nested_str_weak(find), + }), + be_str_weak(get_object_from_ptr), + &be_const_str_solidified, + ( &(const binstruction[10]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x20080403, // 0002 NE R2 R2 R3 + 0x780A0004, // 0003 JMPF R2 #0009 + 0x88080100, // 0004 GETMBR R2 R0 K0 + 0x8C080501, // 0005 GETMET R2 R2 K1 + 0x5C100200, // 0006 MOVE R4 R1 + 0x7C080400, // 0007 CALL R2 2 + 0x80040400, // 0008 RET 1 R2 + 0x80000000, // 0009 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: create_custom_widget +********************************************************************/ +be_local_closure(LVGL_glob_create_custom_widget, /* name */ + be_nested_proto( + 10, /* nstack */ + 3, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[27]) { /* constants */ + /* K0 */ be_nested_str_weak(introspect), + /* K1 */ be_nested_str_weak(lv), + /* K2 */ be_nested_str_weak(lv_obj), + /* K3 */ be_nested_str_weak(value_error), + /* K4 */ be_nested_str_weak(arg_X20must_X20be_X20a_X20subclass_X20of_X20lv_obj), + /* K5 */ be_nested_str_weak(widget_struct_by_class), + /* K6 */ be_nested_str_weak(find), + /* K7 */ be_nested_str_weak(widget_cb), + /* K8 */ be_nested_str_weak(widget_struct_default), + /* K9 */ be_nested_str_weak(copy), + /* K10 */ be_nested_str_weak(base_class), + /* K11 */ be_nested_str_weak(_class), + /* K12 */ be_nested_str_weak(contains), + /* K13 */ be_nested_str_weak(widget_width_def), + /* K14 */ be_nested_str_weak(width_def), + /* K15 */ be_nested_str_weak(widget_height_def), + /* K16 */ be_nested_str_weak(height_def), + /* K17 */ be_nested_str_weak(widget_editable), + /* K18 */ be_nested_str_weak(editable), + /* K19 */ be_nested_str_weak(widget_group_def), + /* K20 */ be_nested_str_weak(group_def), + /* K21 */ be_nested_str_weak(widget_instance_size), + /* K22 */ be_nested_str_weak(instance_size), + /* K23 */ be_nested_str_weak(obj_class_create_obj), + /* K24 */ be_nested_str_weak(_p), + /* K25 */ be_nested_str_weak(register_obj), + /* K26 */ be_nested_str_weak(class_init_obj), + }), + be_str_weak(create_custom_widget), + &be_const_str_solidified, + ( &(const binstruction[86]) { /* code */ + 0xA40E0000, // 0000 IMPORT R3 K0 + 0x6010000F, // 0001 GETGBL R4 G15 + 0x5C140200, // 0002 MOVE R5 R1 + 0xB81A0200, // 0003 GETNGBL R6 K1 + 0x88180D02, // 0004 GETMBR R6 R6 K2 + 0x7C100400, // 0005 CALL R4 2 + 0x74120000, // 0006 JMPT R4 #0008 + 0xB0060704, // 0007 RAISE 1 K3 K4 + 0x88100105, // 0008 GETMBR R4 R0 K5 + 0x4C140000, // 0009 LDNIL R5 + 0x1C100805, // 000A EQ R4 R4 R5 + 0x78120002, // 000B JMPF R4 #000F + 0x60100013, // 000C GETGBL R4 G19 + 0x7C100000, // 000D CALL R4 0 + 0x90020A04, // 000E SETMBR R0 K5 R4 + 0x60100005, // 000F GETGBL R4 G5 + 0x5C140200, // 0010 MOVE R5 R1 + 0x7C100200, // 0011 CALL R4 1 + 0x88140105, // 0012 GETMBR R5 R0 K5 + 0x8C140B06, // 0013 GETMET R5 R5 K6 + 0x5C1C0800, // 0014 MOVE R7 R4 + 0x7C140400, // 0015 CALL R5 2 + 0x4C180000, // 0016 LDNIL R6 + 0x1C180A06, // 0017 EQ R6 R5 R6 + 0x781A002F, // 0018 JMPF R6 #0049 + 0x8C180107, // 0019 GETMET R6 R0 K7 + 0x7C180200, // 001A CALL R6 1 + 0x88180108, // 001B GETMBR R6 R0 K8 + 0x8C180D09, // 001C GETMET R6 R6 K9 + 0x7C180200, // 001D CALL R6 1 + 0x5C140C00, // 001E MOVE R5 R6 + 0x60180003, // 001F GETGBL R6 G3 + 0x5C1C0200, // 0020 MOVE R7 R1 + 0x7C180200, // 0021 CALL R6 1 + 0x88180D0B, // 0022 GETMBR R6 R6 K11 + 0x90161406, // 0023 SETMBR R5 K10 R6 + 0x8C18070C, // 0024 GETMET R6 R3 K12 + 0x5C200200, // 0025 MOVE R8 R1 + 0x5824000D, // 0026 LDCONST R9 K13 + 0x7C180600, // 0027 CALL R6 3 + 0x781A0001, // 0028 JMPF R6 #002B + 0x8818030D, // 0029 GETMBR R6 R1 K13 + 0x90161C06, // 002A SETMBR R5 K14 R6 + 0x8C18070C, // 002B GETMET R6 R3 K12 + 0x5C200200, // 002C MOVE R8 R1 + 0x5824000F, // 002D LDCONST R9 K15 + 0x7C180600, // 002E CALL R6 3 + 0x781A0001, // 002F JMPF R6 #0032 + 0x8818030F, // 0030 GETMBR R6 R1 K15 + 0x90162006, // 0031 SETMBR R5 K16 R6 + 0x8C18070C, // 0032 GETMET R6 R3 K12 + 0x5C200200, // 0033 MOVE R8 R1 + 0x58240011, // 0034 LDCONST R9 K17 + 0x7C180600, // 0035 CALL R6 3 + 0x781A0001, // 0036 JMPF R6 #0039 + 0x88180311, // 0037 GETMBR R6 R1 K17 + 0x90162406, // 0038 SETMBR R5 K18 R6 + 0x8C18070C, // 0039 GETMET R6 R3 K12 + 0x5C200200, // 003A MOVE R8 R1 + 0x58240013, // 003B LDCONST R9 K19 + 0x7C180600, // 003C CALL R6 3 + 0x781A0001, // 003D JMPF R6 #0040 + 0x88180313, // 003E GETMBR R6 R1 K19 + 0x90162806, // 003F SETMBR R5 K20 R6 + 0x8C18070C, // 0040 GETMET R6 R3 K12 + 0x5C200200, // 0041 MOVE R8 R1 + 0x58240015, // 0042 LDCONST R9 K21 + 0x7C180600, // 0043 CALL R6 3 + 0x781A0001, // 0044 JMPF R6 #0047 + 0x88180315, // 0045 GETMBR R6 R1 K21 + 0x90162C06, // 0046 SETMBR R5 K22 R6 + 0x88180105, // 0047 GETMBR R6 R0 K5 + 0x98180805, // 0048 SETIDX R6 R4 R5 + 0xB81A0200, // 0049 GETNGBL R6 K1 + 0x8C180D17, // 004A GETMET R6 R6 K23 + 0x5C200A00, // 004B MOVE R8 R5 + 0x5C240400, // 004C MOVE R9 R2 + 0x7C180600, // 004D CALL R6 3 + 0x881C0D18, // 004E GETMBR R7 R6 K24 + 0x90063007, // 004F SETMBR R1 K24 R7 + 0x8C1C0119, // 0050 GETMET R7 R0 K25 + 0x5C240200, // 0051 MOVE R9 R1 + 0x7C1C0400, // 0052 CALL R7 2 + 0x8C1C031A, // 0053 GETMET R7 R1 K26 + 0x7C1C0200, // 0054 CALL R7 1 + 0x80000000, // 0055 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: widget_cb ********************************************************************/ @@ -1212,41 +1184,75 @@ be_local_closure(LVGL_glob_widget_cb, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: remove_cb +********************************************************************/ +be_local_closure(LVGL_glob_remove_cb, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(introspect), + /* K1 */ be_nested_str_weak(_p), + /* K2 */ be_nested_str_weak(deregister_obj), + }), + be_str_weak(remove_cb), + &be_const_str_solidified, + ( &(const binstruction[ 6]) { /* code */ + 0xA40A0000, // 0000 IMPORT R2 K0 + 0x880C0301, // 0001 GETMBR R3 R1 K1 + 0x8C100102, // 0002 GETMET R4 R0 K2 + 0x5C180600, // 0003 MOVE R6 R3 + 0x7C100400, // 0004 CALL R4 2 + 0x80000000, // 0005 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified class: LVGL_glob ********************************************************************/ be_local_class(LVGL_glob, - 11, + 12, NULL, - be_nested_map(27, + be_nested_map(28, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(get_object_from_ptr, -1), be_const_closure(LVGL_glob_get_object_from_ptr_closure) }, - { be_const_key_weak(create_custom_widget, 18), be_const_closure(LVGL_glob_create_custom_widget_closure) }, - { be_const_key_weak(widget_cb, -1), be_const_closure(LVGL_glob_widget_cb_closure) }, - { be_const_key_weak(add_cb_event_closure, -1), be_const_closure(LVGL_glob_add_cb_event_closure_closure) }, - { be_const_key_weak(cb_do_nothing, -1), be_const_static_closure(LVGL_glob__anonymous__closure) }, - { be_const_key_weak(widget_dtor_cb, -1), be_const_var(7) }, - { be_const_key_weak(event_cb, -1), be_const_var(2) }, - { be_const_key_weak(widget_ctor_impl, -1), be_const_closure(LVGL_glob_widget_ctor_impl_closure) }, - { be_const_key_weak(null_cb, 25), be_const_var(5) }, - { be_const_key_weak(deregister_obj, 6), be_const_closure(LVGL_glob_deregister_obj_closure) }, - { be_const_key_weak(widget_event_impl, -1), be_const_closure(LVGL_glob_widget_event_impl_closure) }, - { be_const_key_weak(remove_cb, -1), be_const_closure(LVGL_glob_remove_cb_closure) }, - { be_const_key_weak(widget_ctor_cb, -1), be_const_var(6) }, - { be_const_key_weak(lvgl_timer_dispatch, -1), be_const_closure(LVGL_glob_lvgl_timer_dispatch_closure) }, - { be_const_key_weak(init, 22), be_const_closure(LVGL_glob_init_closure) }, - { be_const_key_weak(event, -1), be_const_var(4) }, { be_const_key_weak(get_event_cb, -1), be_const_closure(LVGL_glob_get_event_cb_closure) }, - { be_const_key_weak(lvgl_event_dispatch, -1), be_const_closure(LVGL_glob_lvgl_event_dispatch_closure) }, - { be_const_key_weak(widget_event_cb, 23), be_const_var(8) }, { be_const_key_weak(cb_event_closure, -1), be_const_var(1) }, + { be_const_key_weak(lvgl_timer_dispatch, -1), be_const_closure(LVGL_glob_lvgl_timer_dispatch_closure) }, + { be_const_key_weak(deregister_obj, -1), be_const_closure(LVGL_glob_deregister_obj_closure) }, + { be_const_key_weak(event_cb, 2), be_const_var(2) }, { be_const_key_weak(register_obj, -1), be_const_closure(LVGL_glob_register_obj_closure) }, + { be_const_key_weak(lvgl_event_dispatch, 20), be_const_closure(LVGL_glob_lvgl_event_dispatch_closure) }, + { be_const_key_weak(widget_event_impl, -1), be_const_closure(LVGL_glob_widget_event_impl_closure) }, + { be_const_key_weak(widget_ctor_cb, 16), be_const_var(7) }, + { be_const_key_weak(make_cb, 3), be_const_closure(LVGL_glob_make_cb_closure) }, + { be_const_key_weak(create_custom_widget, 5), be_const_closure(LVGL_glob_create_custom_widget_closure) }, + { be_const_key_weak(event, -1), be_const_var(4) }, + { be_const_key_weak(get_object_from_ptr, -1), be_const_closure(LVGL_glob_get_object_from_ptr_closure) }, + { be_const_key_weak(widget_struct_default, 7), be_const_var(10) }, { be_const_key_weak(widget_dtor_impl, -1), be_const_closure(LVGL_glob_widget_dtor_impl_closure) }, + { be_const_key_weak(widget_ctor_impl, -1), be_const_closure(LVGL_glob_widget_ctor_impl_closure) }, + { be_const_key_weak(general_event_cb, -1), be_const_var(5) }, + { be_const_key_weak(cb_do_nothing, -1), be_const_static_closure(LVGL_glob__anonymous__closure) }, + { be_const_key_weak(widget_event_cb, 17), be_const_var(9) }, + { be_const_key_weak(init, -1), be_const_closure(LVGL_glob_init_closure) }, { be_const_key_weak(timer_cb, -1), be_const_var(3) }, - { be_const_key_weak(make_cb, -1), be_const_closure(LVGL_glob_make_cb_closure) }, - { be_const_key_weak(cb_obj, 14), be_const_var(0) }, - { be_const_key_weak(widget_struct_default, -1), be_const_var(9) }, - { be_const_key_weak(widget_struct_by_class, 2), be_const_var(10) }, + { be_const_key_weak(widget_dtor_cb, 12), be_const_var(8) }, + { be_const_key_weak(cb_obj, 10), be_const_var(0) }, + { be_const_key_weak(widget_cb, -1), be_const_closure(LVGL_glob_widget_cb_closure) }, + { be_const_key_weak(null_cb, -1), be_const_var(6) }, + { be_const_key_weak(add_cb_event_closure, 4), be_const_closure(LVGL_glob_add_cb_event_closure_closure) }, + { be_const_key_weak(widget_struct_by_class, -1), be_const_var(11) }, + { be_const_key_weak(remove_cb, -1), be_const_closure(LVGL_glob_remove_cb_closure) }, })), be_str_weak(LVGL_glob) ); diff --git a/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py b/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py index 2820a7682..5ea74ba2d 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py +++ b/lib/libesp32_lvgl/lv_binding_berry/tools/convert.py @@ -6,186 +6,16 @@ lv_module_file = "../mapping/lv_enum.h" out_prefix = "../generate/" lvgl_prefix = "../generate/" +doc_prefix = "../generate/" be_lv_defines = "be_lv_defines.h" be_lv_c_mapping = "be_lv_c_mapping.h" be_lv_widgets_libs = "be_lvgl_widgets_lib.c" be_lv_lvgl_module = "be_lvgl_module.c" +be_lv_lvgl_doc = "LVGL_API_Reference.md" -# detect a function definition all -# Ex: 'void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent);' -# Group 1: 'void' -# Group 2: 'lv_obj_set_parent' -# Group 3: 'lv_obj_t * obj, lv_obj_t * parent' -parse_func_def = re.compile("(.*?)\s(\w+)\((.*?)\)") - -# parse call argument type -# Ex: 'const lv_obj_t * parent' -> 'const ', 'lv_obj_t', ' * ', 'parent' -# Ex: 'bool auto_fit' -> '', 'bool', ' ', 'auto_fit' -parse_arg = re.compile("(\w+\s+)?(\w+)([\*\s]+)(\w+)(\[\])?") - -return_types = { - "void": "", - "bool": "b", - "int": "i", - "uint8_t": "i", - "uint16_t": "i", - "int16_t": "i", - "uint32_t": "i", - "int32_t": "i", - "void *": ".", - "const void *": ".", - "char *": "c", - "uint8_t *": "c", - "const char *": "s", - "retchar *": "s", - "constchar *": "s", # special construct - "lv_obj_user_data_t": "i", - - "lv_objmask_mask_t *": ".", - - "lv_coord_t": "i", - "lv_res_t": "i", - "lv_style_int_t": "i", - "lv_opa_t": "i", - "lv_drag_dir_t": "i", - "lv_bidi_dir_t": "i", - "lv_state_t": "i", - "lv_arc_type_t":"i", - "lv_chart_axis_t":"i", - "lv_bar_type_t":"i", - "lv_btn_state_t":"i", - "lv_point_t":"i", - "lv_chart_type_t":"i", - "lv_fit_t":"i", - "lv_cpicker_color_mode_t":"i", - "lv_dropdown_dir_t":"i", - "lv_layout_t":"i", - "lv_color_hsv_t":"i", - "lv_label_long_mode_t": "i", - "lv_label_align_t": "i", - "lv_scrollbar_mode_t": "i", - "lv_spinbox_part_t": "i", - "lv_spinner_style_t": "i", - "lv_anim_value_t": "i", - "lv_switch_part_t": "i", - "lv_label_align_t": "i", - "lv_tabview_btns_pos_t": "i", - "lv_textarea_style_t": "i", - "lv_slider_type_t": "i", - "lv_spinner_type_t": "i", - "lv_spinner_dir_t": "i", - "lv_blend_mode_t": "i", - "lv_grad_dir_t": "i", - "lv_border_side_t": "i", - "lv_align_t": "i", - "lv_keyboard_mode_t": "i", - "lv_indev_type_t": "i", - "lv_event_t": "i", - "lv_signal_t": "i", - "lv_img_cf_t": "i", - "lv_draw_mask_line_side_t": "i", - "lv_style_property_t": "i", - "lv_dir_t": "i", - "lv_part_t": "i", - "lv_base_dir_t": "i", - "lv_text_decor_t": "i", - "lv_text_align_t": "i", - "lv_arc_mode_t": "i", - "lv_bar_mode_t": "i", - "lv_event_code_t": "i", - "lv_obj_flag_t": "i", - "lv_slider_mode_t": "i", - "lv_scroll_snap_t": "i", - "lv_style_value_t": "i", - "lv_img_src_t": "i", - "lv_colorwheel_mode_t": "i", - "lv_scr_load_anim_t": "i", - "lv_style_selector_t": "i", - "lv_draw_mask_res_t": "i", - "lv_img_size_mode_t": "i", - "lv_palette_t": "i", - "lv_style_prop_t": "i", - "lv_dither_mode_t": "i", - "lv_chart_update_mode_t": "i", - "lv_style_res_t": "i", - # layouts - "lv_flex_align_t": "i", - "lv_flex_flow_t": "i", - "lv_grid_align_t": "i", - - "_lv_event_dsc_t *": "c", - # lv_anim - "lv_anim_t *": "lv_anim", - "lv_anim_enable_t": "i", - "lv_anim_exec_xcb_t": "c", - "lv_anim_custom_exec_cb_t": "c", - "lv_anim_get_value_cb_t": "c", - "lv_anim_path_cb_t": "c", - "lv_anim_ready_cb_t": "c", - "lv_anim_start_cb_t": "c", - # lv_imgbtn - "lv_imgbtn_state_t": "i", - # lv_btnmatrix - "lv_btnmatrix_ctrl_t": "i", - - "lv_group_refocus_policy_t": "i", - "lv_roller_mode_t": "i", - "lv_table_cell_ctrl_t": "i", - - # arrays - "constchar * []": "str_arr", - "char * []": "str_arr", - "lv_coord_t []": "lv_coord_arr", - "lv_point_t []": "lv_point_arr", - - # "lv_signal_cb_t": "c", - # "lv_design_cb_t": "c", - # "lv_event_cb_t": "c", - # "lv_group_focus_cb_t": "c", - - # ctypes objects - "lv_area_t *": "lv_area", - "lv_meter_scale_t *": "lv_meter_scale", - "lv_meter_indicator_t *": "lv_meter_indicator", - "lv_obj_class_t *": "lv_obj_class", - "lv_chart_series_t *": "lv_chart_series", - "lv_chart_cursor_t *": "lv_chart_cursor", - - "_lv_obj_t *": "lv_obj", - "lv_obj_t *": "lv_obj", - "lv_color_t": "lv_color", - "lv_style_t *": "lv_style", - "lv_group_t *": "lv_group", - "lv_font_t *": "lv_font", - "lv_theme_t *": "lv_theme", - "lv_disp_t *": "lv_disp", - "lv_indev_t *": "lv_indev", - "lv_img_header_t *": "lv_img_header", - "lv_img_dsc_t *": "lv_img_dsc", - "lv_ts_calibration_t *": "lv_ts_calibration", - "lv_style_transition_dsc_t *": "lv_style_transition_dsc", - "lv_draw_ctx_t *": "lv_draw_ctx", - "_lv_draw_ctx_t *": "lv_draw_ctx", - "_lv_draw_layer_ctx_t *": "lv_draw_layer_ctx", - "lv_grad_dsc_t *": "lv_grad_dsc", - "lv_sqrt_res_t *": "lv_sqrt_res", - # "lv_color_hsv_t *": "lv_color_hsv", - "lv_color_filter_dsc_t *": "lv_color_filter_dsc", - "lv_timer_t *": "lv_timer", - "_lv_timer_t *": "lv_timer", - "lv_coord_t *": "c", # treat as a simple pointer, decoding needs to be done at Berry level - "char **": "c", # treat as a simple pointer, decoding needs to be done at Berry level - "constchar **": "c", # treat as a simple pointer, decoding needs to be done at Berry level - - # callbacks - "lv_group_focus_cb_t": "lv_group_focus_cb", - "lv_event_cb_t": "lv_event_cb", - "lv_timer_cb_t": "lv_timer_cb", -} lv = {} -lvs = [] # special case for case for lv_style lv0 = [] # function in lvlg module lv_module = [] lv_cb_types = ['lv_group_focus_cb', 'lv_event_cb', 'lv_timer_cb', @@ -200,38 +30,587 @@ lv['color'] = [] lv['theme'] = [] # standard widgets -lv_widgets = ['arc', 'bar', 'btn', 'btnmatrix', 'canvas', 'checkbox', - 'dropdown', 'img', 'label', 'line', 'roller', 'slider', - 'switch', 'table', 'textarea' ] +lv_widgets = ['obj', + 'arc', 'bar', 'button', 'buttonmatrix', 'canvas', 'checkbox', + 'dropdown', 'image', 'label', 'line', 'roller', 'slider', + 'switch', 'table', 'textarea', + # added in LVGL 9 + 'spangroup', 'scale', + ] # extra widgets -lv_widgets = lv_widgets + [ 'chart', 'colorwheel', 'imgbtn', 'led', 'meter', 'msgbox', 'spinbox', 'spinner', 'keyboard' , 'tabview', 'tileview' , 'list'] +lv_widgets = lv_widgets + [ 'chart', 'imagebutton', 'led', 'msgbox', 'spinbox', 'spinner', 'keyboard', 'tabview', 'tileview' , 'list', + 'animimg', 'calendar', 'menu'] # add qrcode lv_widgets = lv_widgets + [ 'qrcode' ] -lv_prefix = ['obj', 'group', 'style', 'indev', 'disp', 'timer', 'anim'] + lv_widgets +lv_prefix = ['group', 'style', 'indev', 'display', 'timer', 'anim', 'event'] + lv_widgets # define here widget inheritance because it's hard to deduce from source lv_widget_inheritance = { - "animing": "img", - "calendar": "btnmatrix", - "keyboard": "btnmatrix", - "list_btn": "btn", + "animimage": "image", + "calendar": "buttonmatrix", + "keyboard": "buttonmatrix", + "list_button": "button", "list_text": "label", "spinbox": "textarea", "spinner": "arc", # lv_spinner is a subclass of lv_arc - "canvas": "img", + "canvas": "image", "roller_label": "label", + "animimg": "image", } # contains any custom attribute we need to add to a widget lv_widget_custom_ptr = { - "spinner": { - "_arc_anim_start_angle": "comptr(&arc_anim_start_angle)", - "_arc_anim_end_angle": "comptr(&arc_anim_end_angle)", - } + # "spinner": { + # "_arc_anim_start_angle": "comptr(&arc_anim_start_angle)", + # "_arc_anim_end_angle": "comptr(&arc_anim_end_angle)", + # } } + +compress_lv_type = True # if True, convert `lv.lv_` to `lv.` to reduce the size of mapping + +class lvgl_function: + def __init__(self, c_func_name, c_ret_type, c_argc, c_args_doc_list, orig_func_name, be_name): + # change "lv.lv_" into "lv." + c_args_doc = ', '.join(c_args_doc_list) + if compress_lv_type: + c_argc = re.sub(r"lv\.lv_", "lv.", c_argc) + c_args_doc = re.sub(r"lv\.lv_", "lv.", c_args_doc) + self.c_args_doc = c_args_doc + + self.c_func_name = c_func_name + self.orig_func_name = orig_func_name + self.be_name = be_name + if c_ret_type == '.': c_ret_type = 'c' # if return type is '.', return a comptr + self.c_argc = c_argc + if len(c_ret_type) > 1: + if compress_lv_type: + c_ret_type = "lv." + re.sub(r"^lv_", "", c_ret_type) + else: + c_ret_type = "lv." + c_ret_type + self.c_ret_type = c_ret_type + self.c_ret_type_doc = type_mapper.return_type_to_doc(c_ret_type) + + # return a key/value pair: be_name, C string for this method or function + def add_C_line_to_map(self, map): + # if c_ret_type is an object, prefix with `lv.` + be_ret_type = self.c_ret_type + + map[self.be_name] = f" {{ \"{self.be_name}\", {{ (const void*) &{self.orig_func_name}, \"{be_ret_type}\", \"{self.c_argc}\" }} }}," + +# enter some synonyms so that names in LVGL 8 are mapped to their LVGL 9 equivalent +synonym_functions = { + # functions + "scr_act": "screen_active", + "set_zoom": "set_scale", + "get_zoom": "get_scale", + "set_angle": "set_rotation", + "get_angle": "get_rotation", + "clear_flag": "remove_flag", + "clear_state": "remove_state", + "set_style_img_opa": "set_style_image_opa", + "set_style_img_recolor": "set_style_image_recolor", + "set_style_img_recolor_opa": "set_style_image_recolor_opa", + "set_bg_img_opa": "set_bg_image_opa", + "set_bg_img_recolor": "set_bg_image_recolor", + "set_bg_img_recolor_opa": "set_bg_image_recolor_opa", + "set_bg_img_src": "set_bg_image_src", + "set_bg_img_tiled": "set_bg_image_tiled", + + "del": "delete", + "del_async": "delete_async", + "clear_flag": "remove_flag", + "clear_state": "remove_state", + + "set_disp": "set_display", + "get_act": "active", + "scr_act": "screen_active", + "scr_load": "screen_load", + "remove": "delete", + "set_default": "set_default", + "get_default": "get_default", + "get_next": "get_next", + "set_rotation": "set_rotation", + "get_hor_res": "get_horizontal_resolution", + "get_ver_res": "get_vertical_resolution", + "get_physical_hor_res": "get_physical_horizontal_resolution", + "get_physical_ver_res": "get_physical_vertical_resolution", + "get_offset_x": "get_offset_x", + "get_offset_y": "get_offset_y", + "get_rotation": "get_rotation", + "get_dpi": "get_dpi", + "get_antialiasing": "get_antialiasing", + "flush_ready": "flush_ready", + "flush_is_last": "flush_is_last", + "get_scr_act": "get_screen_active", + "get_scr_prev": "get_screen_prev", + "load_scr": "lv_screen_load", + "get_layer_top": "get_layer_top", + "get_layer_sys": "get_layer_sys", + "send_event": "send_event", + "set_theme": "set_theme", + "get_theme": "get_theme", + "get_inactive_time": "get_inactive_time", + "trig_activity": "trigger_activity", + "enable_invalidation": "enable_invalidation", + "is_invalidation_enabled": "is_invalidation_enabled", + + "del_all": "delete_all", + "set_ready_cb": "set_completed_cb", + + "get_size": "get_size", + "get_width": "get_width", + + "set_btn_text": "set_button_text", + "_btn_text": "get_button_text", + "add_btn": "add_button", + + "get_tab_btns": "get_tab_bar", + "get_tab_act": "get_tab_active", + "set_act": "set_active", + + "get_tile_act": "get_tile_active", + "set_tile_id": "set_tile_by_index", + + "set_visible_row_cnt": "set_visible_row_count", + "get_option_cnt": "get_option_count", + + "set_col_cnt": "set_column_count", + "set_row_cnt": "set_row_count", + "get_col_cnt": "get_column_count", + "get_row_cnt": "get_row_count", + "set_col_width": "set_column_width", + "get_col_width": "get_column_width", + + "get_option_cnt": "get_option_count", + + "get_child_cnt": "get_child_count", + "get_disp": "get_display", + "delete_anim_ready_cb": "delete_anim_completed_cb", + + "get_style_anim_time": "get_style_anim_duration", + "get_style_img_opa": "get_style_image_opa", + "get_style_img_recolor": "get_style_image_recolor", + "get_style_img_recolor_filtered": "get_style_image_recolor_filtered", + "get_style_img_recolor_opa": "get_style_image_recolor_opa", + "get_style_shadow_ofs_x": "get_style_shadow_offset_x", + "get_style_shadow_ofs_y": "get_style_shadow_offset_y", + "get_style_transform_angle": "get_style_transform_rotation", + + "set_style_anim_time": "set_style_anim_duration", + "set_style_img_opa": "set_style_image_opa", + "set_style_img_recolor": "set_style_image_recolor", + "set_style_img_recolor_opa": "set_style_image_recolor_opa", + "set_style_shadow_ofs_x": "set_style_shadow_offset_x", + "set_style_shadow_ofs_y": "set_style_shadow_offset_y", + "set_style_transform_zoom": "set_style_transform_scale", + "set_style_transform_angle": "set_style_transform_rotation", + + "set_anim_time": "set_anim_duration", + "set_img_opa": "set_image_opa", + "set_img_recolor": "set_image_recolor", + "set_img_recolor_opa": "set_image_recolor_opa", + "set_shadow_ofs_x": "set_shadow_offset_x", + "set_shadow_ofs_y": "set_shadow_offset_y", + "set_transform_angle": "set_transform_rotation", + "set_transform_zoom": "set_transform_scale", + + "scr_load_anim": "screen_load_anim", +} + +def get_synonyms(name): + return [k for k,v in synonym_functions.items() if v == name] + +# The following class takes a C++ type and returns all information about Berry type +class type_mapper_class: + # detect a function definition all + # Ex: 'void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent);' + # Group 1: 'void' + # Group 2: 'lv_obj_set_parent' + # Group 3: 'lv_obj_t * obj, lv_obj_t * parent' + parse_func_regex = re.compile("(.*?)\s(\w+)\((.*?)\)") + + # parse call argument type + # Ex: 'const lv_obj_t * parent' -> 'const ', 'lv_obj_t', ' * ', 'parent' + # Ex: 'bool auto_fit' -> '', 'bool', ' ', 'auto_fit' + parse_arg_regex = re.compile("(\w+\s+)?(\w+)([\*\s]+)(\w+)(\[\])?") + + # the following types are skipped without warning, because it would be too complex to adapt (so we don't map any function using or returning these types) + skipping_type = [ + "lv_global_t *", # reading globals is not useful in Berry + "lv_event_dsc_t *", # internal implementation, use functions instead + "lv_draw_task_t *", # skip low-level tasks for now + "lv_draw_buf_t *", # low-level + "lv_calendar_date_t *", # skip calendar for now + "lv_vector_dsc_t", # see later if we need this + "lv_point_precise_t", # see later if we need this + "void **", # edge case of lv_animimg_get_src() + "lv_matrix_t *", + "lv_event_list_t *", + "lv_style_value_t *", + "lv_fpoint_t *", + "lv_draw_fill_dsc_t *", + "lv_draw_mask_rect_dsc_t *", + "lv_draw_triangle_dsc_t *", + "lv_font_glyph_dsc_t *", + "lv_buttonmatrix_ctrl_t []", + "lv_group_edge_cb_t", + "lv_obj_tree_walk_cb_t", + "lv_display_flush_cb_t", + "lv_display_flush_wait_cb_t", + "lv_draw_glyph_dsc_t *", + "lv_draw_unit_t *", + "lv_draw_border_dsc_t *", + "lv_draw_box_shadow_dsc_t *", + "lv_anim_deleted_cb_t", + "lv_timer_handler_resume_cb_t", + "lv_theme_apply_cb_t", + "lv_color32_t *", + "lv_color16_t *", + "lv_color_filter_cb_t", + "lv_style_prop_t []", + "lv_calendar_date_t []", + "lv_indev_read_cb_t", + ] + + return_types = { + # "void": "", # treated in code directly, it doesn't work well with regex since there is no variable name + "bool": "b", + "int": "i", + "uint8_t": "i", + "uint16_t": "i", + "int16_t": "i", + "uint32_t": "i", + "int32_t": "i", + "void *": ".", + # "const void *": ".", + "char *": "c", + # "uint8_t *": "c", + "size_t": "i", + # "const char *": "s", + "retchar *": "s", + "constchar *": "s", # special construct + # "lv_obj_user_data_t": "i", + "lv_result_t": "i", + "float": "f", + + "lv_coord_t": "i", + "lv_opa_t": "i", + "lv_state_t": "i", + "lv_chart_axis_t":"i", + "lv_point_t":"i", + "lv_chart_type_t":"i", + # "lv_layout_t":"i", + "lv_color_hsv_t":"i", + "lv_label_long_mode_t": "i", + "lv_scrollbar_mode_t": "i", + "lv_blend_mode_t": "i", + "lv_grad_dir_t": "i", + "lv_border_side_t": "i", + "lv_align_t": "i", + "lv_keyboard_mode_t": "i", + "lv_indev_type_t": "i", + "lv_indev_mode_t": "i", + "lv_indev_state_t": "i", + # "lv_event_t": "i", + "lv_dir_t": "i", + "lv_part_t": "i", + "lv_base_dir_t": "i", + "lv_text_decor_t": "i", + "lv_text_align_t": "i", + "lv_arc_mode_t": "i", + "lv_bar_mode_t": "i", + "lv_event_code_t": "i", + "lv_obj_flag_t": "i", + "lv_slider_mode_t": "i", + "lv_scroll_snap_t": "i", + "lv_style_value_t": "i", + # "lv_image_src_t": "i", + "lv_style_selector_t": "i", + # "lv_palette_t": "i", + "lv_style_prop_t": "i", + "lv_chart_update_mode_t": "i", + "lv_style_res_t": "i", + # LVGL 9 + "lv_image_align_t": "i", + "lv_display_rotation_t": "i", + "lv_color_format_t": "i", + "lv_value_precise_t": "i", + "lv_color32_t": "i", + "lv_scale_mode_t": "i", + "lv_span_overflow_t": "i", + "lv_span_mode_t": "i", + "lv_vector_path_t *": "c", # treat as opaque pointer + "lv_vector_dsc_t *": "c", # treat as opaque pointer + "lv_scale_section_t *": "c", # treat as opaque pointer + "lv_point_t *": "c", # treat as opaque pointer + "lv_hit_test_info_t *": "c", # treat as opaque pointer + "lv_screen_load_anim_t": "i", + "lv_display_render_mode_t": "i", + "lv_vector_gradient_spread_t": "i", + "lv_cover_res_t": "i", + "lv_vector_path_quality_t": "i", + "lv_vector_blend_t": "i", + "lv_vector_fill_t": "i", + "lv_vector_stroke_cap_t": "i", + "lv_vector_stroke_join_t": "i", + "lv_font_kerning_t": "i", + "lv_menu_mode_header_t": "i", + "lv_menu_mode_root_back_button_t": "i", + "lv_point_precise_t []": "lv_point_arr", + + "int32_t *": "lv_int_arr", + "int32_t []": "lv_int_arr", + "uint32_t *": "lv_int_arr", + "float *": "lv_float_arr", + # layouts + "lv_flex_align_t": "i", + "lv_flex_flow_t": "i", + "lv_grid_align_t": "i", + + # lv_anim + "lv_anim_t *": "lv_anim", + "lv_anim_enable_t": "i", + "lv_anim_exec_xcb_t": "c", + "lv_anim_custom_exec_cb_t": "c", + "lv_anim_get_value_cb_t": "c", + "lv_anim_path_cb_t": "c", + "lv_anim_completed_cb_t": "c", + "lv_anim_start_cb_t": "c", + # lv_imagebutton + "lv_imagebutton_state_t": "i", + # lv_buttonmatrix + "lv_buttonmatrix_ctrl_t": "i", + + "lv_group_refocus_policy_t": "i", + "lv_roller_mode_t": "i", + "lv_table_cell_ctrl_t": "i", + + # arrays + "constchar * []": "str_arr", + # "char * []": "str_arr", + # "lv_coord_t []": "lv_coord_arr", + # "lv_point_t []": "lv_point_arr", + + # ctypes objects + "lv_area_t *": "lv_area", + "lv_obj_class_t *": "lv_obj_class", + "lv_chart_series_t *": "lv_chart_series", + "lv_chart_cursor_t *": "lv_chart_cursor", + "lv_draw_label_dsc_t *": "lv_draw_label_dsc", + "lv_draw_rect_dsc_t *": "lv_draw_rect_dsc", + "lv_draw_line_dsc_t *": "lv_draw_line_dsc", + "lv_draw_arc_dsc_t *": "lv_draw_arc_dsc", + "lv_point_precise_t *": "lv_point_precise", + "lv_draw_image_dsc_t *": "lv_draw_image_dsc", + + "_lv_obj_t *": "lv_obj", + "lv_obj_t *": "lv_obj", + "lv_event_t *": "lv_event", + "lv_color_t": "lv_color", + "lv_style_t *": "lv_style", + "lv_group_t *": "lv_group", + "lv_font_t *": "lv_font", + "lv_theme_t *": "lv_theme", + "lv_display_t *": "lv_display", + '_lv_display_t *': "lv_display", + "lv_indev_t *": "lv_indev", + "lv_point_t []": "lv_point_arr", + "lv_span_t *": "lv_spangroup", + # "lv_image_header_t *": "lv_image_header", + "lv_image_dsc_t *": "lv_image_dsc", + "lv_ts_calibration_t *": "lv_ts_calibration", + "lv_style_transition_dsc_t *": "lv_style_transition_dsc", + "lv_layer_t *": "c", # LVGL9 + # "_lv_draw_layer_ctx_t *": "lv_draw_layer_ctx", + "lv_grad_dsc_t *": "lv_grad_dsc", + "lv_color_filter_dsc_t *": "lv_color_filter_dsc", + "lv_timer_t *": "lv_timer", + # "_lv_timer_t *": "lv_timer", + # "lv_coord_t *": "lv_coord_arr", + # "char **": "lv_str_arr", # treat as a simple pointer, decoding needs to be done at Berry level + "constchar **": "c", # treat as a simple pointer, decoding needs to be done at Berry level + "void * []": "c", # treat as a simple pointer, decoding needs to be done at Berry level + + # callbacks + "lv_group_focus_cb_t": "lv_group_focus_cb", + "lv_event_cb_t": "lv_event_cb", + "lv_timer_cb_t": "lv_timer_cb", + } + + lv_cb_types = ['lv_group_focus_cb', 'lv_event_cb', 'lv_timer_cb', + 'lv_constructor_cb', # 'constructor_cb', addition to LVGL8, also works for 'destructor_cb' + 'lv_group_edge_cb', # new in LVGL9 + ] + + # how to transform a type used for Berry mapping into user-explicit + return_types_for_doc = { + "i": "int", + "b": "bool", + "s": "string", + "c": "comptr", + "C": "callback", + ".": "\\", + } + + def return_type_to_doc(self, type): + return type_mapper_class.return_types_for_doc.get(type, type) + + def __init__(self) -> None: + # create a map to count each time a C type is converted to Berry, and catch those that are never used + # also provide some stats + self.return_types_count = { k:0 for k in type_mapper_class.return_types.keys() } + self.unhandled_types = {} + + # convert a C return type to the string representation for the Berry parser + # using return_types + def c_convert_type(self, c_ctype, try_without_t): + # try name first + be_ret = type_mapper_class.return_types.get(c_ctype) + if be_ret: + self.return_types_count[c_ctype] += 1 + return be_ret + + if try_without_t: + c_ctype_without_t = re.sub(r"^(\w+?)_t", "\\1", c_ctype) + # print(f">>> ctype '{c_ctype}' '{c_ctype_without_t}'") + be_ret = type_mapper_class.return_types.get(c_ctype_without_t) + if be_ret: + self.return_types_count[c_ctype_without_t] += 1 + return be_ret + + return None # fallback + + def type_is_unhandled(self, t): + self.unhandled_types[t] = self.unhandled_types.get(t, 0) + 1 + + def dump_return_types_stats(self, dump_all): + for k in sorted(self.unhandled_types, key=self.unhandled_types.get, reverse=True): + print(f"> Unhandled type '{k}' ({self.unhandled_types[k]})", file=sys.stderr) + if dump_all: + for k in sorted(self.return_types_count, key=self.return_types_count.get, reverse=True): + print(f"# '{k}': {self.return_types_count[k]}", file=sys.stderr) + + else: + # dump only unused + return_types_count_filtered = [k for k,v in self.return_types_count.items() if v == 0] + for k in return_types_count_filtered: + print(f"# mapping not used '{k}'", file=sys.stderr) + + def clean_c_line(self, l_raw): + l_raw = re.sub('//.*$', '', l_raw) # remove trailing comments + l_raw = re.sub('LV_ATTRIBUTE_FAST_MEM ', '', l_raw) # remove LV_ATTRIBUTE_FAST_MEM marker + l_raw = re.sub('\s+', ' ', l_raw) # replace any multi-space with a single space + l_raw = l_raw.strip(" \t\n\r") # remove leading or trailing spaces + l_raw = re.sub('static ', '', l_raw) # remove `static` qualifier + l_raw = re.sub('inline ', '', l_raw) # remove `inline` qualifier + l_raw = re.sub('const\s+char\s*\*', 'constchar *', l_raw) + l_raw = re.sub('^char\s*\*', 'retchar *', l_raw) # special case for returning a char* + l_raw = re.sub('const ', '', l_raw) + l_raw = re.sub('struct ', '', l_raw) + return l_raw + + def parse_c_line(self, l_raw): + g = type_mapper_class.parse_func_regex.search(l_raw) + if g: + c_return_type = g.group(1) + c_func_name = g.group(2) + c_arg_types = g.group(3) + return (c_return_type, c_func_name, c_arg_types) + else: + return (None, None, None) + + def get_widget_return_type(self, c_type): + c_ret = self.c_convert_type(c_type, False) + c_ctype_without_t = re.sub(r"_t$", "", c_type) + if c_ret: + pass # done + elif c_type == "void": + c_ret = "" + elif c_ctype_without_t in type_mapper_class.lv_cb_types: + c_ret = "C" # general callback, if not already captured by explicit type + elif c_type not in type_mapper_class.skipping_type: + print(f" // Skipping unsupported return type '{c_type}'", file=sys.stderr) + self.type_is_unhandled(c_type) + c_ret = None + + # print(f">>> get_widget_return_type '{c_type}' -> '{c_ret}'", file=sys.stderr) + return c_ret + + def get_widget_arg_type(self, c_return_type, c_func_name, c_arg_types): + # convert arguments + c_args = "" + c_args_doc = [] + args_raw = [ x.strip(" \t\n\r") for x in c_arg_types.split(",") ] # split by comma and strip + # print(args_raw) + for arg_raw in args_raw: + + # check if `void` + if arg_raw == 'void': # Special case for 'void' which can't be captured easily in regex + break + + if arg_raw == '...': # Special case for '...' which can't be captured easily in regex + # '...' + c_args += "[......]" # allow 6 additional parameters by default + c_args_doc.append("[\\]") + break + + # Ex: 'const lv_obj_t * parent' -> 'const ', 'lv_obj_t', ' * ', 'parent', '' + # Ex: 'bool auto_fit' -> '', 'bool', ' ', 'auto_fit', '' + # Ex: 'const lv_coord_t value[]' -> 'const', 'lv_coord_t', '', 'value', '[]' + ga = type_mapper_class.parse_arg_regex.search(arg_raw) + if ga: # parsing ok? + # ga.group(1) is first modifier like `const`, we don't use them + ga_type = ga.group(2) # main type + ga_ptr = ( ga.group(3).strip(" \t\n\r") == "*" ) # (bool) is it a pointer + ga_2ptr = ( ga.group(3).strip(" \t\n\r") == "**" ) # (bool) is it a pointer to a pointer + ga_name = ga.group(4) # main type name + ga_array = ga.group(5) # is it an array `[]` + # print(f"raw='{arg_raw}' {ga_type=} {ga_ptr=} {ga_name=} {ga_array=}") + + ga_full_type = ga_type # rebuild a complete type with modifier + if ga_ptr: ga_full_type += " *" + if ga_2ptr: ga_full_type += " **" + if ga_array: ga_full_type += " []" + + be_type = self.c_convert_type(ga_full_type, True) + + if be_type == None: + # no match, unsupported type + if ga_full_type not in type_mapper_class.skipping_type: + self.type_is_unhandled(ga_full_type) + # print(f" // Unsupported argument type '{arg_raw}'", file=sys.stderr) + return (None, None) + + # if the type is a single letter, we just add it + if len(be_type) == 1 and be_type != 'C': # callbacks are different + c_args += be_type + c_args_doc.append(type_mapper.return_type_to_doc(be_type)) + else: + if be_type.endswith("_cb"): + if 'remove_' in c_func_name: # if the call is to remove the cb, just treat as an 'anything' parameter + c_args += "." + c_args_doc.append("\\") + else: + # it's a callback type, we encode it differently + if be_type not in lv_cb_types: + lv_cb_types.append(be_type) + c_args += "^" + be_type + "^" + c_args_doc.append('\\') + else: + # we have a high-level type that we treat as a class name, enclose in parenthesis + c_args += "(" + "lv." + be_type + ")" + c_args_doc.append("lv." + be_type) + else: + print(f" // unable to parse arguments '{arg_raw}'", file=sys.stderr) + + # print(f">>> get_widget_arg_type '{c_arg_types}' -> '{c_args}'", file=sys.stderr) + return (c_args, c_args_doc) + +type_mapper = type_mapper_class() + def try_int(s): try: v = int(s) @@ -239,121 +618,61 @@ def try_int(s): except ValueError: return None -# convert a C return type to the string representation for the Berry parser -# using return_types -def c_convert_ret_type(c_ret): - return return_types.get(c_ret, "") - # parse widgets files containing most function calls with open(lv_widgets_file) as f: for l_raw in f: - l_raw = re.sub('//.*$', '', l_raw) # remove trailing comments - l_raw = re.sub('LV_ATTRIBUTE_FAST_MEM ', '', l_raw) # remove LV_ATTRIBUTE_FAST_MEM marker - l_raw = re.sub('\s+', ' ', l_raw) # replace any multi-space with a single space - l_raw = l_raw.strip(" \t\n\r") # remove leading or trailing spaces - l_raw = re.sub('static ', '', l_raw) - l_raw = re.sub('inline ', '', l_raw) - l_raw = re.sub('const\s+char\s*\*', 'constchar *', l_raw) - l_raw = re.sub('^char\s*\*', 'retchar *', l_raw) # special case for returning a char* - l_raw = re.sub('const ', '', l_raw) - l_raw = re.sub('struct ', '', l_raw) + l_raw = type_mapper.clean_c_line(l_raw) if (len(l_raw) == 0): continue - g = parse_func_def.search(l_raw) - if g: - # print(l_raw, g.group(3)) - # if match, we parse the line - # Ex: 'void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent);' - ret_type = g.group(1) # return type of the function - # Ex: ret_type -> 'void' + (c_return_type, c_func_name, c_arg_types) = type_mapper.parse_c_line(l_raw) + if (c_return_type == None): continue - ret_type_without_t = re.sub(r"_t$", "", ret_type) - if ret_type in return_types: - # convert return type - c_ret = c_convert_ret_type(ret_type) - elif ret_type_without_t in lv_cb_types: - c_ret = "C" # general callback, if not already captured by explicit type - else: - print(f" // Skipping unsupported return type: {ret_type}") - continue + c_ret = type_mapper.get_widget_return_type(c_return_type) + if c_ret == None: continue # skip if nothing to return + # convert arguments + (c_args, c_args_doc_list) = type_mapper.get_widget_arg_type(c_return_type, c_func_name, c_arg_types) + if c_args == None: continue # skip if nothing to return - # convert arguments - c_args = "" - args_raw = [ x.strip(" \t\n\r") for x in g.group(3).split(",") ] # split by comma and strip - # print(args_raw) - func_name = g.group(2) - for arg_raw in args_raw: - # Ex: 'const lv_obj_t * parent' -> 'const ', 'lv_obj_t', ' * ', 'parent', '' - # Ex: 'bool auto_fit' -> '', 'bool', ' ', 'auto_fit', '' - # Ex: 'const lv_coord_t value[]' -> 'const', 'lv_coord_t', '', 'value', '[]' - ga = parse_arg.search(arg_raw) - # print(f"g={g} ga={ga}") - if ga or arg_raw == '...': # parsing ok? Special case for '...' which can't be captured easily in regex - if arg_raw != '...': - ga_type = ga.group(2) - ga_ptr = ( ga.group(3).strip(" \t\n\r") == "*" ) # boolean - ga_name = ga.group(4) - ga_array = ga.group(5) - ga_type_ptr = ga_type - if ga_ptr: ga_type_ptr += " *" - if ga_array: ga_type_ptr += " []" - if ga_type_ptr in return_types: - ga_type = return_types[ga_type_ptr] - else: - # remove the trailing '_t' of type name if any - ga_type = re.sub(r"_t$", "", ga_type) - - # if the type is a single letter, we just add it - if len(ga_type) == 1 and ga_type != 'C': # callbacks are different - c_args += ga_type - else: - if ga_type.endswith("_cb"): - if 'remove_' in func_name: # if the call is to remove the cb, just treat as an 'anything' parameter - c_args += "." - else: - # it's a callback type, we encode it differently - if ga_type not in lv_cb_types: - lv_cb_types.append(ga_type) - c_args += "^" + ga_type + "^" - else: - # we have a high-level type that we treat as a class name, enclose in parenthesis - c_args += "(" + "lv." + ga_type + ")" - else: - # '...' - c_args += "[......]" # allow 6 additional parameters + # analyze function name and determine if it needs to be assigned to a specific class + # Ex: c_func_name -> 'lv_obj_set_parent' + if c_func_name.startswith("_"): continue # skip low-level + if c_func_name.startswith("lv_debug_"): continue # skip debug - # analyze function name and determine if it needs to be assigned to a specific class - # Ex: func_name -> 'lv_obj_set_parent' - if func_name.startswith("_"): continue # skip low-level - if func_name.startswith("lv_debug_"): continue # skip debug + be_func_name = "" - c_func_name = "" + if c_func_name == "lv_style_init": + continue # no need for init as it would collied with native init (and called behind the scene anyways) - if func_name == "lv_style_init": - continue # no need for init as it would collied with native init (and called behind the scene anyways) + found = False + for subtype in lv_prefix: + if c_func_name.startswith("lv_" + subtype + "_"): + be_name = re.sub("^lv_" + subtype + "_", '', c_func_name) + be_func_name = "lvbe_" + subtype + "_" + be_name + if subtype not in lv: lv[subtype] = [] # add entry + is_right_type = c_args.startswith(f"(lv.lv_{subtype})") # check if first arg matches class + is_obj_arg1 = c_args.startswith("(lv.lv_obj)") # or first arg is lv_obj + is_group_create = (subtype == 'group') and (c_func_name == 'lv_group_create') + if is_right_type or is_obj_arg1 or is_group_create: + # remove first argument which is implicit + c_args_doc_list = c_args_doc_list[1:] + lv[subtype].append(lvgl_function(be_func_name, c_ret, c_args, c_args_doc_list, c_func_name, be_name)) + # add synonyms + syn = get_synonyms(be_name) + for n in syn: lv[subtype].append(lvgl_function(be_func_name, c_ret, c_args, c_args_doc_list, c_func_name, n)) - found = False - for subtype in lv_prefix: - if func_name.startswith("lv_" + subtype + "_"): - be_name = re.sub("^lv_" + subtype + "_", '', func_name) - c_func_name = "lvbe_" + subtype + "_" + be_name - if subtype not in lv: lv[subtype] = [] # add entry - is_right_type = c_args.startswith(f"(lv.lv_{subtype})") # check if first arg matches class - is_obj_arg1 = c_args.startswith(f"(lv.lv_obj)") # or first arg is lv_obj - is_group_create = (subtype == 'group') and (func_name == 'lv_group_create') - if is_right_type or is_obj_arg1 or is_group_create: - lv[subtype].append( [ c_func_name, c_ret, c_args, func_name, be_name ] ) - found = True - break + found = True + break - if found: continue - # not found, we treat it as lv top level function - be_name = re.sub("^lv_", '', func_name) - lv0.append( [ func_name, c_ret, c_args, func_name, be_name ] ) - # print(lv0[-1]) + if found: continue + # not found, we treat it as lv top level function + be_name = re.sub("^lv_", '', c_func_name) + lv0.append(lvgl_function(be_func_name, c_ret, c_args, c_args_doc_list, c_func_name, be_name)) + # add synonyms + syn = get_synonyms(be_name) + for n in syn: lv0.append(lvgl_function(be_func_name, c_ret, c_args, c_args_doc_list, c_func_name, n)) -print("| callback types"+str(lv_cb_types)) +print("| callback types"+str(lv_cb_types), file=sys.stderr) # parse module file containing numerical constants with open(lv_module_file) as f: @@ -387,6 +706,66 @@ with open(lv_module_file) as f: lv_module.append( [k, v] ) # keep as string or None +# documentation in Markdown for `lv` module +sys.stdout = open(doc_prefix + be_lv_lvgl_doc, 'w') +print("""# LVGL Berry API Reference + +[//]: # (**********************************************************************) +[//]: # (* Generated code, don't edit *) +[//]: # (**********************************************************************) + +""") + +# Start with `lv` module +print("## module `lv`") +print() +print("Method|Arguments|Return type|LVGL equivalent") +print(":---|:---|:---|:---") + +for f in sorted(lv0, key=lambda x: x.be_name): + print(f"{f.be_name}|{f.c_args_doc}|{f.c_ret_type_doc}|[{f.orig_func_name}](https://docs.lvgl.io/9.0/search.html?q={f.orig_func_name})") + +print() + +# Continue with core classes +print("## Core classes") +print() + +for subtype, flv in sorted(lv.items()): + if subtype not in lv_widgets and len(flv) > 0: + print(f"### class `lv.{subtype}`") + print() + print("Method|Arguments|Return type|LVGL equivalent") + print(":---|:---|:---|:---") + for f in sorted(flv, key=lambda x: x.be_name): + if f.c_func_name.endswith("_create"): + pass + # skip create function that are handled in object constructor (no `create` method) + else: + print(f"{f.be_name}|{f.c_args_doc}|{f.c_ret_type_doc}|[{f.orig_func_name}](https://docs.lvgl.io/9.0/search.html?q={f.orig_func_name})") + print() + +# Continue with Widgets +print("## Widgets") +print() +for subtype in lv_widgets: + flv = lv.get(subtype) + if flv: + print(f"### widget `lv.{subtype}`") + print() + print("Method|Arguments|Return type|LVGL equivalent") + print(":---|:---|:---|:---") + for f in sorted(flv, key=lambda x: x.be_name): + if f.c_func_name.endswith("_create"): + pass + # skip create function that are handled in object constructor (no `create` method) + else: + print(f"{f.be_name}|{f.c_args_doc}|{f.c_ret_type_doc}|[{f.orig_func_name}](https://docs.lvgl.io/9.0/search.html?q={f.orig_func_name})") + print() + + +sys.stdout.close() + sys.stdout = open(out_prefix + be_lv_c_mapping, 'w') print(""" /******************************************************************** @@ -408,21 +787,13 @@ for subtype, flv in lv.items(): print(f"const be_ntv_func_def_t lv_{subtype}_func[] = {{") func_out = {} # used to sort output - for f in flv: - c_func_name = f[0] - c_ret_type = f[1] - c_argc = f[2] - if c_argc is not None: c_argc = "\"" + c_argc + "\"" - orig_func_name = f[3] - be_name = f[4] - # if c_ret_type is an object, prefix with `lv.` - if len(c_ret_type) > 1: c_ret_type = "lv." + c_ret_type + for f in sorted(flv, key=lambda x: x.be_name): - if c_func_name.endswith("_create"): + if f.c_func_name.endswith("_create"): pass - # c_ret_type = f"+lv_{subtype}" + # skip create function that are handled in object constructor (no `create` method) else: - func_out[be_name] = f" {{ \"{be_name}\", {{ (const void*) &{orig_func_name}, \"{c_ret_type}\", { c_argc if c_argc else 'nullptr'} }} }}," + f.add_C_line_to_map(func_out) for be_name in sorted(func_out): print(func_out[be_name]) @@ -443,7 +814,6 @@ print(f""" const be_ntv_class_def_t lv_classes[] = {{""") for subtype in sorted(lv): -# for subtype, flv in lv.items(): if subtype in lv_widgets: print(f"#ifdef BE_LV_WIDGET_{subtype.upper()}") print(f" {{ \"lv_{subtype}\", &be_class_lv_{subtype}, lv_{subtype}_func, sizeof(lv_{subtype}_func) / sizeof(lv_{subtype}_func[0]) }},") @@ -459,24 +829,15 @@ const size_t lv_classes_size = sizeof(lv_classes) / sizeof(lv_classes[0]); # keep only create for subtype, flv in lv.items(): print(f" /* `lv_{subtype}` methods */") - for f in flv: - c_func_name = f[0] - c_ret_type = f[1] - c_argc = f[2] - if c_argc is not None: c_argc = "\"" + c_argc + "\"" - orig_func_name = f[3] - - # if c_ret_type is an object, prefix with `lv.` - if len(c_ret_type) > 1: c_ret_type = "lv." + c_ret_type - - if c_func_name.endswith("_create"): + for f in sorted(flv, key=lambda x: x.be_name): + if f.c_func_name.endswith("_create"): c_ret_type = "+_p" # constructor, init method does not return any value if subtype in lv_widgets: print(f"#ifdef BE_LV_WIDGET_{subtype.upper()}") - print(f" int be_ntv_lv_{subtype}_init(bvm *vm) {{ return be_call_c_func(vm, (void*) &{orig_func_name}, \"{c_ret_type}\", { c_argc if c_argc else 'nullptr'}); }}") + print(f" int be_ntv_lv_{subtype}_init(bvm *vm) {{ return be_call_c_func(vm, (void*) &{f.orig_func_name}, \"{c_ret_type}\", \"{f.c_argc}\"); }}") print(f"#endif // BE_LV_WIDGET_{subtype.upper()}") else: - print(f" int be_ntv_lv_{subtype}_init(bvm *vm) {{ return be_call_c_func(vm, (void*) &{orig_func_name}, \"{c_ret_type}\", { c_argc if c_argc else 'nullptr'}); }}") + print(f" int be_ntv_lv_{subtype}_init(bvm *vm) {{ return be_call_c_func(vm, (void*) &{f.orig_func_name}, \"{c_ret_type}\", \"{f.c_argc}\"); }}") print(""" // create font either empty or from parameter on stack @@ -535,9 +896,8 @@ extern int lvbe_theme_create(bvm *vm); # for subtype, flv in lv.items(): print(f"/* `lv_{subtype}` external functions definitions */") - for f in flv: - c_func_name = f[0] - print(f"extern int {c_func_name}(bvm *vm);") + for f in sorted(flv, key=lambda x: x.be_name): + print(f"extern int {f.c_func_name}(bvm *vm);") print() @@ -608,11 +968,11 @@ class be_class_lv_indev (scope: global, name: lv_indev, strings: weak) { @const_object_info_end */ /******************************************************************** -** Solidified class: lv_disp +** Solidified class: lv_display ********************************************************************/ -#include "be_fixed_be_class_lv_disp.h" +#include "be_fixed_be_class_lv_display.h" /* @const_object_info_begin -class be_class_lv_disp (scope: global, name: lv_disp, strings: weak) { +class be_class_lv_display (scope: global, name: lv_display, strings: weak) { _p, var init, func(lv0_init) tostring, func(lv_x_tostring) @@ -646,6 +1006,19 @@ class be_class_lv_anim (scope: global, name: lv_anim, strings: weak) { } @const_object_info_end */ +/******************************************************************** +** Solidified class: lv_event +********************************************************************/ +#include "be_fixed_be_class_lv_event.h" +/* @const_object_info_begin +class be_class_lv_event (scope: global, name: lv_event, strings: weak) { + _p, var + init, func(lv0_init) + tostring, func(lv_x_tostring) + member, func(lv_x_member) +} +@const_object_info_end */ + /******************************************************************** ** Solidified class: lv_font ********************************************************************/ @@ -691,6 +1064,7 @@ extern void arc_anim_end_angle(void * obj, int32_t v); for subtype, flv in lv.items(): + if subtype == 'obj': continue # 'obj' has a special implementation # special version for widgets if subtype in lv_widgets: super_class = lv_widget_inheritance.get(subtype, "obj") # get superclass, default to lv_obj @@ -740,10 +1114,10 @@ extern int lv0_load_font(bvm *vm); extern lv_ts_calibration_t * lv_get_ts_calibration(void); static int lv_get_hor_res(void) { - return lv_disp_get_hor_res(lv_disp_get_default()); + return lv_display_get_horizontal_resolution(NULL); } static int lv_get_ver_res(void) { - return lv_disp_get_ver_res(lv_disp_get_default()); + return lv_display_get_vertical_resolution(NULL); } /* `lv` methods */ @@ -752,17 +1126,27 @@ const be_ntv_func_def_t lv_func[] = { func_out = {} # used to sort output for f in lv0: - c_func_name = f[0] - c_ret_type = f[1] - c_argc = f[2] - if c_argc is not None: c_argc = "\"" + c_argc + "\"" - orig_func_name = f[3] - be_name = f[4] + f.add_C_line_to_map(func_out) + # c_func_name = f[0] + # c_ret_type = f[1] + # c_argc = f[2] + # if c_argc is not None: c_argc = "\"" + c_argc + "\"" + # orig_func_name = f[3] + # be_name = f[4] - # if c_ret_type is an object, prefix with `lv.` - if len(c_ret_type) > 1: c_ret_type = "lv." + c_ret_type + # # if c_ret_type is an object, prefix with `lv.` + # # if len(c_ret_type) > 1: c_ret_type = "lv." + c_ret_type + # if len(c_ret_type) > 1: c_ret_type = "lv." + c_ret_type + + # func_out[be_name] = f" {{ \"{be_name}\", {{ (const void*) &{orig_func_name}, \"{c_ret_type}\", { c_argc if c_argc else 'nullptr'} }} }}," + + + # # any synonyms? + # f_synonyms = get_synonyms(be_name) + # if f_synonyms: + # for new_be_name in f_synonyms: + # func_out[new_be_name] = f" {{ \"{new_be_name}\", {{ (const void*) &{orig_func_name}, \"{c_ret_type}\", { c_argc if c_argc else 'nullptr'} }} }}," - func_out[be_name] = f" {{ \"{be_name}\", {{ (const void*) &{orig_func_name}, \"{c_ret_type}\", { c_argc if c_argc else 'nullptr'} }} }}," for be_name in sorted(func_out): print(func_out[be_name]) @@ -846,3 +1230,4 @@ module lv (scope: global, file: lv) { print("/********************************************************************/") sys.stdout.close() +type_mapper.dump_return_types_stats(False) # True would dump all stats, False only unused diff --git a/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py b/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py index 356768783..fad19e18f 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py +++ b/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py @@ -51,43 +51,35 @@ def clean_source(raw): lv_src_prefix = "../../lvgl/src/" lv_fun_globs = [ "lv_api*.h", - "widgets/*.h", # all widgets - # "extra/widgets/*/*.h", - "extra/widgets/chart/*.h", - "extra/widgets/colorwheel/*.h", - "extra/widgets/imgbtn/*.h", - "extra/widgets/led/*.h", - "extra/widgets/meter/*.h", - "extra/widgets/msgbox/*.h", - "extra/widgets/spinbox/*.h", - "extra/widgets/spinner/*.h", - "extra/widgets/keyboard/*.h", - "extra/widgets/tabview/*.h", - "extra/widgets/tileview/*.h", - "extra/widgets/list/*.h", - "extra/themes/default/*.h", - "extra/themes/mono/*.h", - "extra/layouts/**/*.h", - "extra/libs/qrcode/lv_qrcode.h", + "widgets/*/*.h", # all widgets + "libs/qrcode/lv_qrcode.h", "core/*.h", - "draw/*.h", + "indev/lv_indev.h", + # "draw/*.h", + "themes/lv_theme.h", + "draw/lv_draw_arc.h", + "draw/lv_draw_label.h", + "draw/lv_draw_line.h", + "draw/lv_draw_mask.h", + "draw/lv_draw_rect.h", + "draw/lv_draw_triangle.h", + "draw/lv_draw_vector.h", + "draw/lv_draw.h", + "display/*.h", "misc/lv_anim.h", - "misc/lv_style_gen.h", - "misc/lv_color.h", - "misc/lv_style.h", - "misc/lv_math.h", "misc/lv_area.h", + "misc/lv_color.h", + "misc/lv_color_op.h", + "misc/lv_event.h", + "misc/lv_style_gen.h", + "misc/lv_style.h", "misc/lv_timer.h", "font/lv_font.h", - #"**/*.h", + # add version information + "../lvgl.h", ] headers_names = list_files(lv_src_prefix, lv_fun_globs) headers_names += list_files("../../LVGL_assets/src/", ["lv_theme_haspmota.h"]) -# headers_names += ["lv_pre_style.h"] # for LVGL v7, add pre-generated style functions from C preprocessor - -# unit test -# headers_names = [ '../../lib/libesp32_lvgl/LVGL/src/lv_widgets/lv_btn.h' ] -# headers_names = [ '../../lib/libesp32_lvgl/LVGL/src/lv_api_map.h' ] output_filename = "../mapping/lv_funcs.h" sys.stdout = open(output_filename, 'w', encoding='utf-8') @@ -97,15 +89,9 @@ print(""" // Extract function signatures from LVGL APIs in headers // Custom Tasmota functions -void lv_img_set_tasmota_logo(lv_obj_t * img); +void lv_image_set_tasmota_logo(lv_obj_t * img); lv_ts_calibration_t * lv_get_ts_calibration(void); -// ====================================================================== -// Artificial -// ====================================================================== - -lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix); - // ====================================================================== // LV top level functions // ====================================================================== @@ -114,10 +100,6 @@ lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix); lv_coord_t lv_get_hor_res(void); lv_coord_t lv_get_ver_res(void); -// layers -//static inline lv_obj_t * lv_layer_sys(void); -//static inline lv_obj_t * lv_layer_top(void); - // ====================================================================== // Generated from headers // ====================================================================== @@ -161,21 +143,26 @@ for header_name in headers_names: "^lv_debug", # all debug functions "^lv_init", "^lv_deinit", "^lv_templ_", - "^lv_imgbtn_get_src_", # LV_IMGBTN_TILED == 0 - "^lv_imgbtn_set_src_tiled",# !LV_IMGBTN_TILED + "^lv_imagebutton_get_src_", # LV_IMGBTN_TILED == 0 + "^lv_imagebitton_set_src_tiled",# !LV_IMGBTN_TILED #"^lv_disp_", "^lv_refr_get_fps_", # no LV_USE_PERF_MONITOR - "^lv_img_cache_", - "^lv_img_decoder_", - "^lv_img_cf_", - "^lv_img_buf_", + "^lv_image_cache_", + "^lv_image_decoder_", + "^lv_image_cf_", + "^lv_image_buf_", "^lv_indev_scroll_", "^lv_pow", "^lv_keyboard_def_event_cb", # need to fix conditional include - "^lv_event_get_", # event_getters not needed + # "^lv_event_get_", # event_getters not needed "^lv_refr_reset_fps_counter", "^lv_refr_get_fps_avg", "^lv_anim_path_", # callbacks for animation are moved to constants + # LV_USE_OBJ_PROPERTY 0 + "^lv_obj_set_property", + "^lv_obj_set_properties", + "^lv_obj_get_property", + "^lv_win_", ]: if re.search(exclude_pattern, fun_name): exclude = True if exclude: continue @@ -195,7 +182,8 @@ lv_fun_globs = [ "draw/*.h", "hal/*.h", "misc/*.h", - "widgets/*.h", + "widgets/*/*.h", + "display/lv_display.h", "extra/widgets/**/*.h", "extra/layouts/**/*.h", ] @@ -317,6 +305,45 @@ SYMBOL_NEW_LINE="\\xef\\xA2\\xA2" SYMBOL_DUMMY="\\xEF\\xA3\\xBF" SYMBOL_BULLET="\\xE2\\x80\\xA2" + +// LVGL 8 to 9 compatibility + +LV_DISP_ROTATION_0=LV_DISPLAY_ROTATION_0 +LV_DISP_ROTATION_90=LV_DISPLAY_ROTATION_90 +LV_DISP_ROTATION_180=LV_DISPLAY_ROTATION_180 +LV_DISP_ROTATION_270=LV_DISPLAY_ROTATION_270 + +LV_DISP_RENDER_MODE_PARTIAL=LV_DISPLAY_RENDER_MODE_PARTIAL +LV_DISP_RENDER_MODE_DIRECT=LV_DISPLAY_RENDER_MODE_DIRECT +LV_DISP_RENDER_MODE_FULL=LV_DISPLAY_RENDER_MODE_FULL + +LV_BTNMATRIX_BTN_NONE=LV_BUTTONMATRIX_BUTTON_NONE + +LV_BTNMATRIX_CTRL_HIDDEN=LV_BUTTONMATRIX_CTRL_HIDDEN +LV_BTNMATRIX_CTRL_NO_REPEAT=LV_BUTTONMATRIX_CTRL_NO_REPEAT +LV_BTNMATRIX_CTRL_DISABLED=LV_BUTTONMATRIX_CTRL_DISABLED +LV_BTNMATRIX_CTRL_CHECKABLE=LV_BUTTONMATRIX_CTRL_CHECKABLE +LV_BTNMATRIX_CTRL_CHECKED=LV_BUTTONMATRIX_CTRL_CHECKED +LV_BTNMATRIX_CTRL_CLICK_TRIG=LV_BUTTONMATRIX_CTRL_CLICK_TRIG +LV_BTNMATRIX_CTRL_POPOVER=LV_BUTTONMATRIX_CTRL_POPOVER +LV_BTNMATRIX_CTRL_CUSTOM_1=LV_BUTTONMATRIX_CTRL_CUSTOM_1 +LV_BTNMATRIX_CTRL_CUSTOM_2=LV_BUTTONMATRIX_CTRL_CUSTOM_2 + +LV_RES_OK=LV_RESULT_OK +LV_RES_INV=LV_RESULT_INVALID + +LV_INDEV_STATE_PR=LV_INDEV_STATE_PRESSED +LV_INDEV_STATE_REL=LV_INDEV_STATE_RELEASED + +LV_STYLE_ANIM_TIME=LV_STYLE_ANIM_DURATION +LV_STYLE_IMG_OPA=LV_STYLE_IMAGE_OPA +LV_STYLE_IMG_RECOLOR=LV_STYLE_IMAGE_RECOLOR +LV_STYLE_IMG_RECOLOR_OPA=LV_STYLE_IMAGE_RECOLOR_OPA +LV_STYLE_SHADOW_OFS_X=LV_STYLE_SHADOW_OFFSET_X +LV_STYLE_SHADOW_OFS_Y=LV_STYLE_SHADOW_OFFSET_Y +LV_STYLE_TRANSFORM_ANGLE=LV_STYLE_TRANSFORM_ROTATION + +LV_ZOOM_NONE=LV_SCALE_NONE // ====================================================================== // Generated from headers @@ -329,8 +356,12 @@ for header_name in headers_names: print(f"// File: {header_name}") # extract enums - enums = re.findall('enum\s+{(.*?)}', raw, flags=re.DOTALL) + enums = re.findall('enum\s+\w*\s*{(.*?)}', raw, flags=re.DOTALL) for enum in enums: # iterate on all matches + # exclude LV_PROPERTY_ID + # we compile with `#define LV_USE_OBJ_PROPERTY 0` + # and remove all instances of `LV_PROPERTY_ID(OBJ, FLAG_START, LV_PROPERTY_TYPE_INT, 0),` + if re.search('LV_PROPERTY_ID', enum): continue # remove enums defined via a macro enum = re.sub('\S+\((.*?),.*?\),', '\\1,', enum) # turn 'LV_STYLE_PROP_INIT(LV_STYLE_SIZE, 0x0, LV_STYLE_ID_VALUE + 3, LV_STYLE_ATTR_NONE),' into 'LV_STYLE_SIZE' # @@ -343,9 +374,10 @@ for header_name in headers_names: # item is ready exclude = False - for exclude_prefix in ["_", "LV_BIDI_DIR_", "LV_FONT_", "LV_IMG_CF_RESERVED_", "LV_IMG_CF_USER_", + for exclude_prefix in ["_", "LV_BIDI_DIR_", "LV_FONT_", "LV_SIGNAL_", "LV_TEMPL_", "LV_TASK_PRIO_", "LV_THEME_", - "LV_LRU_"]: + "LV_LRU_", + "LV_KEYBOARD_MODE_TEXT_ARABIC"]: if enum_item.startswith(exclude_prefix): exclude = True if exclude: continue diff --git a/lib/libesp32_lvgl/lvgl/README.md b/lib/libesp32_lvgl/lvgl/README.md index aea07a841..49b1e0b02 100644 --- a/lib/libesp32_lvgl/lvgl/README.md +++ b/lib/libesp32_lvgl/lvgl/README.md @@ -1,186 +1,478 @@ -

LVGL - Light and Versatile Graphics Library

-

- + + +

+ English | 中文 | Português do Brasil | 日本語

+
+

-LVGL provides everything you need to create an embedded GUI with easy-to-use graphical elements, beautiful visual effects and a low memory footprint. + 

-

-Website · -Docs · -Forum · -Services · -Interactive examples -

Light and Versatile Graphics Library


+
+ +   +  +
+
+

+Website | +Docs | +Forum | +Demos | +Services | +SquareLine Studio +

+
+## :ledger: Overview -**English** | [中文](./README_zh.md) | [Português do Brasil](./README_pt_BR.md) +**Mature and Well-known**
+LVGL is the most popular free and open source embedded graphics library to create beautiful UIs for any MCU, MPU and display type. It's supported by industry leading vendors and projects like  Arm, STM32, NXP, Espressif, Nuvoton, Arduino, RT-Thread, Zephyr, NuttX, Adafruit and many more. +**Feature Rich**
+It has all the features to create modern and beautiful GUIs: 30+ built-in widgets, a powerful style system, web inspired layout managers, and a typography system supporting many languages. To integrate LVGL into your platform, all you need is at least 32kB RAM and 128 kB Flash, a C compiler, a frame buffer, and at least an 1/10 screen sized buffer for rendering. ---- +**UI Editor**
+SquareLine Studio is a professional yet affordable drag and drop UI editor for LVGL. It runs on Windows, Linux and MacOS too and you can try it out even without registering to the website. -#### Table of content -- [Overview](#overview) -- [Get started](#get-started) -- [Examples](#examples) -- [Services](#services) -- [Contributing](#contributing) +**Services**
+Our team is ready to help you with graphics design, UI implementation and consulting services. Contact us if you need some support during the development of your next GUI project. -## Overview -### Features -* Powerful [building blocks](https://docs.lvgl.io/master/widgets/index.html): buttons, charts, lists, sliders, images, etc. -* Advanced graphics engine: animations, anti-aliasing, opacity, smooth scrolling, blending modes, etc -* Supports [various input devices](https://docs.lvgl.io/master/overview/indev.html): touchscreen, mouse, keyboard, encoder, buttons, etc. -* Supports [multiple displays](https://docs.lvgl.io/master/overview/display.html) -* Hardware independent, can be use with any microcontroller and display -* Scalable to operate with little memory (64 kB Flash, 16 kB RAM) -* Multi-language support with UTF-8 handling, CJK, Bidirectional and Arabic script support -* Fully customizable graphical elements via [CSS-like styles](https://docs.lvgl.io/master/overview/style.html) -* Powerful layouts inspired by CSS: [Flexbox](https://docs.lvgl.io/master/layouts/flex.html) and [Grid](https://docs.lvgl.io/master/layouts/grid.html) -* OS, External memory and GPU are supported but not required. (built in support for STM32 DMA2D, SWM341 DMA2D, and NXP PXP and VGLite) -* Smooth rendering even with a [single frame buffer](https://docs.lvgl.io/master/porting/display.html) -* Written in C and compatible with C++ -* Micropython Binding exposes [LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings) -* [Simulator](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) to develop on PC without embedded hardware -* 100+ simple [Examples](https://github.com/lvgl/lvgl/tree/master/examples) -* [Documentation](http://docs.lvgl.io/) and API references online and in PDF +## :rocket: Features -### Requirements -Basically, every modern controller (which is able to drive a display) is suitable to run LVGL. The minimal requirements are: - - - - - - - - - - - - - - - +**Free and Portable** + - A fully portable C (C++ compatible) library with no external dependencies. + - Can be compiled to any MCU or MPU, with any (RT)OS. + - Supports monochrome, ePaper, OLED or TFT displays, or even monitors. [Porting Guide](https://docs.lvgl.io/master/porting/project.html) + - Distributed under the MIT license, so you can easily use it in commercial projects too. + - Needs only 32kB RAM and 128 kB Flash, a frame buffer, and at least an 1/10 screen sized buffer for rendering. + - OS, External memory and GPU are supported but not required. - - - - - +**Widgets, Styles, Layouts and more** + - 30+ built-in [Widgets](https://docs.lvgl.io/master/widgets/index.html):  Button, Label, Slider, Chart, Keyboard, Meter, Arc, Table and many more. + - Flexible [Style system](https://docs.lvgl.io/master/overview/style.html) with  ~100 style properties to customize any part of the widgets in any state. + - [Flexbox](https://docs.lvgl.io/master/layouts/flex.html) and [Grid](https://docs.lvgl.io/master/layouts/grid.html)-like layouts engines to automatically size and position the widgets in a responsive way. + - Texts are rendered with UTF-8 encoding supporting CJK, Thai, Hindi, Arabic, Persian writing systems. + - Word wrapping, kerning, text scrolling, sub-pixel rendering, Pinyin-IME Chinese input, Emojis in texts. + - Rendering engine supporting animations, anti-aliasing, opacity, smooth scrolling, shadows, image transformation, etc   + - Supports Mouse, Touchpad, Keypad, Keyboard, External buttons, Encoder [Input devices](https://docs.lvgl.io/master/porting/indev.html). + - [Multiple display](https://docs.lvgl.io/master/overview/disp.html#multiple-display-support) support. - - - - - +**Binding and Build Support** + - [Micropython Binding](https://blog.lvgl.io/2019-02-20/micropython-bindings) exposes LVGL API + - [PikaScript Binding](https://blog.lvgl.io/2022-08-24/pikascript-and-lvgl) python on MCU lighter and easier. + - No custom build system is used. You can build LVGL as you build the other files of your project. + - Support for Make and [CMake](https://docs.lvgl.io/master/get-started/platforms/cmake.html) is included out of the box. + - [Develop on PC](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) and use the same UI code on embedded hardware. + - Convert the C UI code to HTML file with our [Emscripten port](https://github.com/lvgl/lv_web_emscripten). - - - - - +**Docs, Tools, and Services** + - Detailed [Documentation](https://docs.lvgl.io/) with [100+ simple examples](https://docs.lvgl.io/master/index.html) + - [SquareLine Studio](https://squareline.io/) - A professional and easy-to-use UI editor software to speed up and simplify the UI development. + - [Services](https://lvgl.io/services) such as User interface design, Implementation and Consulting to make UI development simpler and faster. - - - - -
Name MinimalRecommended
Architecture16, 32 or 64 bit microcontroller or processor
Clock > 16 MHz > 48 MHz
Flash/ROM > 64 kB > 180 kB
Static RAM > 16 kB > 48 kB
Draw buffer > 1 × hor. res. pixels > 1/10 screen size
Compiler C99 or newer
+## :heart: Sponsor -*Note that the memory usage might vary depending on the architecture, compiler and build options.* +If LVGL saved you a lot of time and money or you just had fun using it, consider [Supporting its Development](https://github.com/sponsors/lvgl). -### Supported platforms -LVGL is completely platform independent and can be used with any MCU that fulfills the requirements. -Just to mention some platforms: -- NXP: Kinetis, LPC, iMX, iMX RT -- STM32F1, STM32F3, STM32F4, STM32F7, STM32L4, STM32L5, STM32H7 -- Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ -- [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb) -- [Raspberry Pi](https://github.com/lvgl/lv_port_linux_frame_buffer) -- [Espressif ESP32](https://github.com/lvgl/lv_port_esp32) -- [Infineon Aurix](https://github.com/lvgl/lv_port_aurix) -- Nordic NRF52 Bluetooth modules -- Quectel modems -- [SYNWIT SWM341](http://www.synwit.cn/) +**How do we spend the donations?**
+Our goal is to provide financial compensation for people who do the most for LVGL. It means not only the maintainers but anyone who implements a great feature should get a payment from the accumulated money. We use the donations to cover our operational costs like servers and related services. -LVGL is also available as: -- [Arduino library](https://docs.lvgl.io/master/get-started/platforms/arduino.html) +**How to donate?**
+We use [GitHub Sponsors](https://github.com/sponsors/lvgl) where you can easily send one time or recurring donations. You can also see all of our expenses in a transparent way. + +**How to get paid for your contribution?**
+If someone implements or fixes an issue labeled as [Sponsored](https://github.com/lvgl/lvgl/labels/Sponsored) he or she will get a payment for that work. We estimate the required time, complexity and importance of the issue and set a price accordingly. To jump in just comment on a [Sponsored](https://github.com/lvgl/lvgl/labels/Sponsored) issue saying "Hi, I'd like to deal with it. This is how I'm planning to fix/implement it...". A work is considered ready when it's approved and merged by a maintainer. After that you can submit and expense at [opencollective.com](https://opencollective.com/lvgl) and you will receive the payment in a few days. + +**Organizations supporting LVGL**
+[![Sponsors of LVGL](https://opencollective.com/lvgl/organizations.svg?width=600)](https://opencollective.com/lvgl) + +**Individuals supporting LVGL**
+[![Backers of LVGL](https://opencollective.com/lvgl/individuals.svg?width=600)](https://opencollective.com/lvgl) + +## :package: Packages +LVGL is available as: +- [Arduino library](https://docs.lvgl.io/master/integration/framework/arduino.html) - [PlatformIO package](https://registry.platformio.org/libraries/lvgl/lvgl) -- [Zephyr library](https://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_LVGL.html) -- [ESP32 component](https://docs.lvgl.io/master/get-started/platforms/espressif.html) +- [Zephyr library](https://docs.lvgl.io/master/integration/os/zephyr.html) +- [ESP-IDF(ESP32) component](https://components.espressif.com/components/lvgl/lvgl) - [NXP MCUXpresso component](https://www.nxp.com/design/software/embedded-software/lvgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY) -- [NuttX library](https://docs.lvgl.io/master/get-started/os/nuttx.html) -- [RT-Thread RTOS](https://docs.lvgl.io/master/get-started/os/rt-thread.html) +- [NuttX library](https://docs.lvgl.io/master/integration/os/nuttx.html) +- [RT-Thread RTOS](https://docs.lvgl.io/master/integration/os/rt-thread.html) +- CMSIS-Pack +- [RIOT OS package](https://doc.riot-os.org/group__pkg__lvgl.html#details) -## Get started -This list shows the recommended way of learning the library: -1. Check the [Online demos](https://lvgl.io/demos) to see LVGL in action (3 minutes) -2. Read the [Introduction](https://docs.lvgl.io/master/intro/index.html) page of the documentation (5 minutes) -3. Get familiar with the basics on the [Quick overview](https://docs.lvgl.io/master/get-started/quick-overview.html) page (15 minutes) -4. Set up a [Simulator](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) (10 minutes) -5. Try out some [Examples](https://github.com/lvgl/lvgl/tree/master/examples) -6. Port LVGL to a board. See the [Porting](https://docs.lvgl.io/master/porting/index.html) guide or check the ready to use [Projects](https://github.com/lvgl?q=lv_port_) -7. Read the [Overview](https://docs.lvgl.io/master/overview/index.html) page to get a better understanding of the library (2-3 hours) -8. Check the documentation of the [Widgets](https://docs.lvgl.io/master/widgets/index.html) to see their features and usage -9. If you have questions go to the [Forum](http://forum.lvgl.io/) -10. Read the [Contributing](https://docs.lvgl.io/master/CONTRIBUTING.html) guide to see how you can help to improve LVGL (15 minutes) +## :robot: Examples -## Examples +See some examples of creating widgets, using layouts and applying styles. You will find C and MicroPython code, and links to try out or edit the examples in an online MicroPython editor. -For more examples see the [examples](https://github.com/lvgl/lvgl/tree/master/examples) folder. +For more examples check out the [Examples](https://github.com/lvgl/lvgl/tree/master/examples) folder. -![LVGL button with label example](https://github.com/lvgl/lvgl/raw/master/docs/misc/btn_example.png) -### C +### Hello world label + +![Simple Hello world label example in LVGL](https://github.com/kisvegabor/test/raw/master/readme_example_1.png) + +
+ C code + ```c -lv_obj_t * btn = lv_btn_create(lv_scr_act()); /*Add a button to the current screen*/ -lv_obj_set_pos(btn, 10, 10); /*Set its position*/ -lv_obj_set_size(btn, 100, 50); /*Set its size*/ -lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL); /*Assign a callback to the button*/ +/*Change the active screen's background color*/ +lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0x003a57), LV_PART_MAIN); -lv_obj_t * label = lv_label_create(btn); /*Add a label to the button*/ -lv_label_set_text(label, "Button"); /*Set the labels text*/ -lv_obj_center(label); /*Align the label to the center*/ +/*Create a white label, set its text and align it to the center*/ +lv_obj_t * label = lv_label_create(lv_screen_active()); +lv_label_set_text(label, "Hello world"); +lv_obj_set_style_text_color(lv_screen_active(), lv_color_hex(0xffffff), LV_PART_MAIN); +lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); +``` +
+ +
+ MicroPython code | Online Simulator + +```python +# Change the active screen's background color +scr = lv.screen_active() +scr.set_style_bg_color(lv.color_hex(0x003a57), lv.PART.MAIN) + +# Create a white label, set its text and align it to the center +label = lv.label(lv.screen_active()) +label.set_text("Hello world") +label.set_style_text_color(lv.color_hex(0xffffff), lv.PART.MAIN) +label.align(lv.ALIGN.CENTER, 0, 0) +``` +
+
+ +### Button with Click Event + +![LVGL button with label example](https://github.com/kisvegabor/test/raw/master/readme_example_2.gif) + +
+ C code + +```c +lv_obj_t * button = lv_button_create(lv_screen_active());                   /*Add a button to the current screen*/ +lv_obj_center(button);                                     /*Set its position*/ +lv_obj_set_size(button, 100, 50);                                  /*Set its size*/ +lv_obj_add_event_cb(button, button_event_cb, LV_EVENT_CLICKED, NULL); /*Assign a callback to the button*/ + +lv_obj_t * label = lv_label_create(button);                        /*Add a label to the button*/ +lv_label_set_text(label, "Button");                             /*Set the labels text*/ +lv_obj_center(label);                                           /*Align the label to the center*/ ... -void btn_event_cb(lv_event_t * e) +void button_event_cb(lv_event_t * e) { - printf("Clicked\n"); +  printf("Clicked\n"); } ``` -### Micropython -Learn more about [Micropython](https://docs.lvgl.io/master/get-started/bindings/micropython.html). +
+ +
+ MicroPython code | Online Simulator + ```python -def btn_event_cb(e): - print("Clicked") +def button_event_cb(e): +  print("Clicked") # Create a Button and a Label -btn = lv.btn(lv.scr_act()) -btn.set_pos(10, 10) -btn.set_size(100, 50) -btn.add_event_cb(btn_event_cb, lv.EVENT.CLICKED, None) +button = lv.button(lv.screen_active()) +button.center() +button.set_size(100, 50) +button.add_event_cb(button_event_cb, lv.EVENT.CLICKED, None) -label = lv.label(btn) +label = lv.label(button) label.set_text("Button") label.center() ``` +
+
-## Services -LVGL Kft was established to provide a solid background for LVGL library. We offer several type of services to help you in UI development: -- Graphics design -- UI implementation -- Consulting/Support +### Checkboxes with Layout +![Checkboxes with layout in LVGL](https://github.com/kisvegabor/test/raw/master/readme_example_3.gif) -For more information see https://lvgl.io/services -Feel free to contact us if you have any questions. +
+ C code + +```c + +lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_COLUMN); +lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER); + +lv_obj_t * cb; +cb = lv_checkbox_create(lv_screen_active()); +lv_checkbox_set_text(cb, "Apple"); +lv_obj_add_event_cb(cb, event_handler, LV_EVENT_ALL, NULL); + +cb = lv_checkbox_create(lv_screen_active()); +lv_checkbox_set_text(cb, "Banana"); +lv_obj_add_state(cb, LV_STATE_CHECKED); +lv_obj_add_event_cb(cb, event_handler, LV_EVENT_ALL, NULL); + +cb = lv_checkbox_create(lv_screen_active()); +lv_checkbox_set_text(cb, "Lemon"); +lv_obj_add_state(cb, LV_STATE_DISABLED); +lv_obj_add_event_cb(cb, event_handler, LV_EVENT_ALL, NULL); + +cb = lv_checkbox_create(lv_screen_active()); +lv_obj_add_state(cb, LV_STATE_CHECKED | LV_STATE_DISABLED); +lv_checkbox_set_text(cb, "Melon\nand a new line"); +lv_obj_add_event_cb(cb, event_handler, LV_EVENT_ALL, NULL); +``` + +
+ +
+ MicroPython code | Online Simulator + +```python +def event_handler(e): + code = e.get_code() + obj = e.get_target_obj() + if code == lv.EVENT.VALUE_CHANGED: + txt = obj.get_text() + if obj.get_state() & lv.STATE.CHECKED: + state = "Checked" + else: + state = "Unchecked" + print(txt + ":" + state) -## Contributing -LVGL is an open project and contribution is very welcome. There are many ways to contribute from simply speaking about your project, through writing examples, improving the documentation, fixing bugs to hosting your own project under the LVGL organization. +lv.screen_active().set_flex_flow(lv.FLEX_FLOW.COLUMN) +lv.screen_active().set_flex_align(lv.FLEX_ALIGN.CENTER, lv.FLEX_ALIGN.START, lv.FLEX_ALIGN.CENTER) + +cb = lv.checkbox(lv.screen_active()) +cb.set_text("Apple") +cb.add_event_cb(event_handler, lv.EVENT.ALL, None) + +cb = lv.checkbox(lv.screen_active()) +cb.set_text("Banana") +cb.add_state(lv.STATE.CHECKED) +cb.add_event_cb(event_handler, lv.EVENT.ALL, None) + +cb = lv.checkbox(lv.screen_active()) +cb.set_text("Lemon") +cb.add_state(lv.STATE.DISABLED) +cb.add_event_cb(event_handler, lv.EVENT.ALL, None) + +cb = lv.checkbox(lv.screen_active()) +cb.add_state(lv.STATE.CHECKED | lv.STATE.DISABLED) +cb.set_text("Melon") +cb.add_event_cb(event_handler, lv.EVENT.ALL, None) +``` + +
+
+ +### Styling a Slider +![Styling a slider with LVGL](https://github.com/kisvegabor/test/raw/master/readme_example_4.gif) + + +
+ C code + +```c +lv_obj_t * slider = lv_slider_create(lv_screen_active()); +lv_slider_set_value(slider, 70, LV_ANIM_OFF); +lv_obj_set_size(slider, 300, 20); +lv_obj_center(slider); + +/*Add local styles to MAIN part (background rectangle)*/ +lv_obj_set_style_bg_color(slider, lv_color_hex(0x0F1215), LV_PART_MAIN); +lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN); +lv_obj_set_style_border_color(slider, lv_color_hex(0x333943), LV_PART_MAIN); +lv_obj_set_style_border_width(slider, 5, LV_PART_MAIN); +lv_obj_set_style_pad_all(slider, 5, LV_PART_MAIN); + +/*Create a reusable style sheet for the INDICATOR part*/ +static lv_style_t style_indicator; +lv_style_init(&style_indicator); +lv_style_set_bg_color(&style_indicator, lv_color_hex(0x37B9F5)); +lv_style_set_bg_grad_color(&style_indicator, lv_color_hex(0x1464F0)); +lv_style_set_bg_grad_dir(&style_indicator, LV_GRAD_DIR_HOR); +lv_style_set_shadow_color(&style_indicator, lv_color_hex(0x37B9F5)); +lv_style_set_shadow_width(&style_indicator, 15); +lv_style_set_shadow_spread(&style_indicator, 5); +4 +/*Add the style sheet to the slider's INDICATOR part*/ +lv_obj_add_style(slider, &style_indicator, LV_PART_INDICATOR); + +/*Add the same style to the KNOB part too and locally overwrite some properties*/ +lv_obj_add_style(slider, &style_indicator, LV_PART_KNOB); + +lv_obj_set_style_outline_color(slider, lv_color_hex(0x0096FF), LV_PART_KNOB); +lv_obj_set_style_outline_width(slider, 3, LV_PART_KNOB); +lv_obj_set_style_outline_pad(slider, -5, LV_PART_KNOB); +lv_obj_set_style_shadow_spread(slider, 2, LV_PART_KNOB); +``` + +
+ +
+ MicroPython code | +Online Simulator + + + +```python +# Create a slider and add the style +slider = lv.slider(lv.screen_active()) +slider.set_value(70, lv.ANIM.OFF) +slider.set_size(300, 20) +slider.center() + +# Add local styles to MAIN part (background rectangle) +slider.set_style_bg_color(lv.color_hex(0x0F1215), lv.PART.MAIN) +slider.set_style_bg_opa(255, lv.PART.MAIN) +slider.set_style_border_color(lv.color_hex(0x333943), lv.PART.MAIN) +slider.set_style_border_width(5, lv.PART.MAIN) +slider.set_style_pad_all(5, lv.PART.MAIN) + +# Create a reusable style sheet for the INDICATOR part +style_indicator = lv.style_t() +style_indicator.init() +style_indicator.set_bg_color(lv.color_hex(0x37B9F5)) +style_indicator.set_bg_grad_color(lv.color_hex(0x1464F0)) +style_indicator.set_bg_grad_dir(lv.GRAD_DIR.HOR) +style_indicator.set_shadow_color(lv.color_hex(0x37B9F5)) +style_indicator.set_shadow_width(15) +style_indicator.set_shadow_spread(5) + +# Add the style sheet to the slider's INDICATOR part +slider.add_style(style_indicator, lv.PART.INDICATOR) +slider.add_style(style_indicator, lv.PART.KNOB) + +# Add the same style to the KNOB part too and locally overwrite some properties +slider.set_style_outline_color(lv.color_hex(0x0096FF), lv.PART.KNOB) +slider.set_style_outline_width(3, lv.PART.KNOB) +slider.set_style_outline_pad(-5, lv.PART.KNOB) +slider.set_style_shadow_spread(2, lv.PART.KNOB) +``` +
+
+ +### English, Hebrew (mixed LTR-RTL) and Chinese texts + +![English, Hebrew and Chinese texts with LVGL](https://github.com/kisvegabor/test/raw/master/readme_example_5.png) + +
+ C code + +```c +lv_obj_t * ltr_label = lv_label_create(lv_screen_active()); +lv_label_set_text(ltr_label, "In modern terminology, a microcontroller is similar to a system on a chip (SoC)."); +lv_obj_set_style_text_font(ltr_label, &lv_font_montserrat_16, 0); +lv_obj_set_width(ltr_label, 310); +lv_obj_align(ltr_label, LV_ALIGN_TOP_LEFT, 5, 5); + +lv_obj_t * rtl_label = lv_label_create(lv_screen_active()); +lv_label_set_text(rtl_label,"מעבד, או בשמו המלא יחידת עיבוד מרכזית (באנגלית: CPU - Central Processing Unit)."); +lv_obj_set_style_base_dir(rtl_label, LV_BASE_DIR_RTL, 0); +lv_obj_set_style_text_font(rtl_label, &lv_font_dejavu_16_persian_hebrew, 0); +lv_obj_set_width(rtl_label, 310); +lv_obj_align(rtl_label, LV_ALIGN_LEFT_MID, 5, 0); + +lv_obj_t * cz_label = lv_label_create(lv_screen_active()); +lv_label_set_text(cz_label, + "嵌入式系统(Embedded System),\n是一种嵌入机械或电气系统内部、具有专一功能和实时计算性能的计算机系统。"); +lv_obj_set_style_text_font(cz_label, &lv_font_simsun_16_cjk, 0); +lv_obj_set_width(cz_label, 310); +lv_obj_align(cz_label, LV_ALIGN_BOTTOM_LEFT, 5, -5); +``` + +
+ +
+ MicroPython code | Online Simulator + +```python +ltr_label = lv.label(lv.screen_active()) +ltr_label.set_text("In modern terminology, a microcontroller is similar to a system on a chip (SoC).") +ltr_label.set_style_text_font(lv.font_montserrat_16, 0); + +ltr_label.set_width(310) +ltr_label.align(lv.ALIGN.TOP_LEFT, 5, 5) + +rtl_label = lv.label(lv.screen_active()) +rtl_label.set_text("מעבד, או בשמו המלא יחידת עיבוד מרכזית (באנגלית: CPU - Central Processing Unit).") +rtl_label.set_style_base_dir(lv.BASE_DIR.RTL, 0) +rtl_label.set_style_text_font(lv.font_dejavu_16_persian_hebrew, 0) +rtl_label.set_width(310) +rtl_label.align(lv.ALIGN.LEFT_MID, 5, 0) + +font_simsun_16_cjk = lv.font_load("S:../../assets/font/lv_font_simsun_16_cjk.fnt") + +cz_label = lv.label(lv.screen_active()) +cz_label.set_style_text_font(font_simsun_16_cjk, 0) +cz_label.set_text("嵌入式系统(Embedded System),\n是一种嵌入机械或电气系统内部、具有专一功能和实时计算性能的计算机系统。") +cz_label.set_width(310) +cz_label.align(lv.ALIGN.BOTTOM_LEFT, 5, -5) + +``` +
+ +## :arrow_forward: Get started +This list will guide you to get started with LVGL step-by-step. + +**Get Familiar with LVGL** + + 1. Check the [Online demos](https://lvgl.io/demos) to see LVGL in action (3 minutes) + 2. Read the [Introduction](https://docs.lvgl.io/master/intro/index.html) page of the documentation (5 minutes) + 3. Get familiar with the basics on the [Quick overview](https://docs.lvgl.io/master/get-started/quick-overview.html) page (15 minutes) + +**Start to Use LVGL** + + 4. Set up a [Simulator](https://docs.lvgl.io/master/integration/ide/pc-simulator.html#simulator) (10 minutes) + 5. Try out some [Examples](https://github.com/lvgl/lvgl/tree/master/examples) + 6. Port LVGL to a board. See the [Porting](https://docs.lvgl.io/master/porting/index.html) guide or check the ready to use [Projects](https://github.com/lvgl?q=lv_port_) + +**Become a Pro** + + 7. Read the [Overview](https://docs.lvgl.io/master/overview/index.html) page to get a better understanding of the library (2-3 hours) + 8. Check the documentation of the [Widgets](https://docs.lvgl.io/master/widgets/index.html) to see their features and usage + +**Get Help and Help Others** + + 9. If you have questions go to the [Forum](http://forum.lvgl.io/) + 10. Read the [Contributing](https://docs.lvgl.io/master/CONTRIBUTING.html) guide to see how you can help to improve LVGL (15 minutes) + +**Go for More** + + 11. Download and try out [SquareLine Studio](https://squareline.io/). + 12. Contact us for [Services](https://lvgl.io/services). + + +## :handshake: Services +LVGL LLC was established to provide a solid background for LVGL library and to offer several type of services to help you in UI development. With 15+ years of experience in the user interface and graphics industry we can help you the bring your UI to the next level. + +- **Graphics design** Our in-house graphics designers are experts in creating beautiful modern designs which fit to your product and the resources of your hardware. +- **UI implementation** We can also implement your UI based on the design you or we have created. You can be sure that we will make the most out of your hardware and LVGL. If a feature or widget is missing from LVGL, don't worry, we will implement it for you. +- **Consulting and Support** We can support you with consulting as well to avoid pricey and time consuming mistakes during the UI development. +- **Board certification** For companies who are offering development boards, or production ready kits we do board certification which shows how board can run LVGL. + + +Check out our [Demos](https://lvgl.io/demos) as reference. For more information take look at the [Services page](https://lvgl.io/services). + +[Contact us](https://lvgl.io/#contact) and tell how we can help. + + +## :star2: Contributing +LVGL is an open project and contribution is very welcome. There are many ways to contribute from simply speaking about your project, through writing examples, improving the documentation, fixing bugs or even hosting your own project under the LVGL organization. For a detailed description of contribution opportunities visit the [Contributing](https://docs.lvgl.io/master/CONTRIBUTING.html) section of the documentation. +More than 300 people already left their fingerprint in LVGL. Be one them! See your here! :slightly_smiling_face: + + + + + +... and many other. diff --git a/lib/libesp32_lvgl/lvgl/README_Tasmota.md b/lib/libesp32_lvgl/lvgl/README_Tasmota.md index b9fa2c667..623deb724 100644 --- a/lib/libesp32_lvgl/lvgl/README_Tasmota.md +++ b/lib/libesp32_lvgl/lvgl/README_Tasmota.md @@ -21,4 +21,8 @@ because parameters depend on Tasmota defines and presence of PSRAM. ## lv_spinner -Both function `arc_anim_start_angle()` and `arc_anim_end_angle()` are made non-static. This allows to search for `lv_anim` object based on their `exec_cb` callbacks and change properties on-the-fly. \ No newline at end of file +Both function `arc_anim_start_angle()` and `arc_anim_end_angle()` are made non-static. This allows to search for `lv_anim` object based on their `exec_cb` callbacks and change properties on-the-fly. + +## LVGL 9 + +Temporarily rename `lv_image_set_inner_align` to `lv_image_set_inner_align` until solved in LVGL repo. diff --git a/lib/libesp32_lvgl/lvgl/README_pt_BR.md b/lib/libesp32_lvgl/lvgl/README_pt_BR.md deleted file mode 100644 index f62f0a0f8..000000000 --- a/lib/libesp32_lvgl/lvgl/README_pt_BR.md +++ /dev/null @@ -1,206 +0,0 @@ -

LVGL - Biblioteca gráfica leve e versátil

-

- -

-

- O LVGL fornece tudo o que você precisa para criar uma GUI incorporada com elementos gráficos fáceis de usar, belos efeitos visuais e um baixo consumo de memória. -

-

- Site · - Documentação · - Fórum · - Serviços · - Exemplos interativos -

- -[English](./README.md) | [中文](./README_zh.md) | **Português do Brasil** - ---- - -### Tabela de conteúdo - -- [Visão Geral](#visão-geral) -- [Iniciando](#iniciando) -- [Exemplos](#exemplos) -- [Serviços](#serviços) -- [Contribuindo](#contribuindo) - -## Visão Geral - -### Recursos -* Poderosos [widgets](https://docs.lvgl.io/master/widgets/index.html): botões, gráficos, listas, controles deslizantes (sliders), imagens, etc. -* Mecanismo gráfico avançado: animações, anti-aliasing, opacidade, rolagem suave, modos de mesclagem (blending modes), etc. -* Suporte à [vários dispositivos de entrada](https://docs.lvgl.io/master/overview/indev.html): tela sensível ao toque, mouse, teclado, codificador, botões, etc. -* Suporte à [vários monitores](https://docs.lvgl.io/master/overview/display.html) -* Pode ser usado com qualquer microcontrolador e display, independente do hardware -* Escalável para operar com pouca memória (64 kB Flash, 16 kB RAM) -* Suporte multilíngue com manipulação UTF-8, suporte ao alfabeto bidirecional, árabe e CJK (Chinês, Japonês e Coreano) -* Elementos gráficos totalmente personalizáveis por meio de [CSS](https://docs.lvgl.io/master/overview/style.html) -* Layouts poderosos inspirados em CSS: [Flexbox](https://docs.lvgl.io/master/layouts/flex.html) e [Grid](https://docs.lvgl.io/master/layouts/grid.html) -* SO, memória externa e GPU são suportados, mas não obrigatórios. (suporte integrado para STM32 DMA2D, SWM341 DMA2D e NXP PXP e VGLite) -* Renderização suave mesmo com um [buffer de quadro único](https://docs.lvgl.io/master/porting/display.html) (single frame buffer) -* Escrito em C e compatível com C++ -* Uso do LittlevGL com Micropython simplificado com [LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings) -* [Simulador](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) para desenvolver no PC sem hardware embutido -* Mais de 100 [exemplos simples](https://github.com/lvgl/lvgl/tree/master/examples) -* [Documentação](http://docs.lvgl.io/) e referências de API online e em PDF - -### Requerimentos -Basicamente, todo controlador moderno (que é capaz de acionar um display) é adequado para executar LVGL. Os requisitos mínimos são: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Nome - - Minímo - - Recomendado -
- Arquitetura - Microcontrolador ou processador de 16, 32 ou 64 bits
- Clock - > 16 MHz> 48 MHz
- Flash/ROM - > 64 kB> 180 kB
- RAM estática - > 16 kB> 48 kB
- Draw buffer - > 1 × hor. res. pixels> tamanho da tela de 1/10
- Compilador - Padrão C99 ou mais recente
- -*Observe que o uso de memória pode variar dependendo da arquitetura, do compilador e das opções de compilação.* - -### Plataformas suportadas -O LVGL é completamente independente de plataforma e pode ser usado com qualquer MCU que atenda aos requisitos. -Apenas para citar algumas plataformas: - -- NXP: Kinetis, LPC, iMX, iMX RT -- STM32F1, STM32F3, STM32F4, STM32F7, STM32L4, STM32L5, STM32H7 -- Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ -- [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb) -- [Raspberry Pi](http://www.vk3erw.com/index.php/16-software/63-raspberry-pi-official-7-touchscreen-and-littlevgl) -- [Espressif ESP32](https://github.com/lvgl/lv_port_esp32) -- [Infineon Aurix](https://github.com/lvgl/lv_port_aurix) -- Nordic NRF52 Bluetooth modules -- Quectel modems -- [SYNWIT SWM341](https://www.synwit.cn/) - -LVGL também está disponível para: -- [Arduino library](https://docs.lvgl.io/master/get-started/platforms/arduino.html) -- [PlatformIO package](https://registry.platformio.org/libraries/lvgl/lvgl) -- [Zephyr library](https://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_LVGL.html) -- [ESP32 component](https://docs.lvgl.io/master/get-started/platforms/espressif.html) -- [NXP MCUXpresso component](https://www.nxp.com/design/software/embedded-software/lvgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY) -- [NuttX library](https://docs.lvgl.io/master/get-started/os/nuttx.html) -- [RT-Thread RTOS](https://docs.lvgl.io/master/get-started/os/rt-thread.html) - -## Iniciando -Esta lista mostra a maneira recomendada de aprender sobre a biblioteca: - -1. Confira as [demos on-line](https://lvgl.io/demos) para ver o LVGL em ação (3 minutos) -2. Leia a [introdução](https://docs.lvgl.io/master/intro/index.html) da documentação (5 minutos) -3. Familiarize-se com o básico da [Visão geral rápida](https://docs.lvgl.io/master/get-started/quick-overview.html) (15 minutos) -4. Configure um [simulador](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html) (10 minutos) -5. Experimente alguns [Exemplos](https://github.com/lvgl/lvgl/tree/master/examples) -6. Placa para porta LVGL. Veja o guia [porting](https://docs.lvgl.io/master/porting/index.html) ou verifique o pronto para usar [Projects](https://github.com/lvgl?q=lv_port_) -7. Leia a [visão geral](https://docs.lvgl.io/master/overview/index.html) para entender melhor a biblioteca (2-3 horas) -8. Verifique a documentação dos [widgets](https://docs.lvgl.io/master/widgets/index.html) para ver seus recursos e como utilizá-los -9. Se você tiver dúvidas, acesse o [fórum](http://forum.lvgl.io/) -10. Leia o guia de [contribuição](https://docs.lvgl.io/master/CONTRIBUTING.html) para ver como você pode ajudar a melhorar o LVGL (15 minutos) - -## Exemplos -Para mais exemplos, veja a pasta [examples](https://github.com/lvgl/lvgl/tree/master/examples). - -![Exemplo de botão LVGL com rótulo (label)](https://github.com/lvgl/lvgl/raw/master/docs/misc/btn_example.png) - -### C - -```c -lv_obj_t * button = lv_btn_create(lv_scr_act()); /* Adiciona um botão à tela atual */ -lv_obj_set_pos(button, 10, 10); /* Define uma posição ao botão na tela */ -lv_obj_set_size(button, 100, 50); /* Define o tamanho */ -lv_obj_add_event_cb(button, button_event_callback, LV_EVENT_CLICKED, NULL); /* Atribui um retorno de chamada (callback) */ - -lv_obj_t * label = lv_label_create(button); /* Adiciona um rótulo (label) */ -lv_label_set_text(label, "Clique aqui"); /* Define o texto do rótulo (label) */ -lv_obj_center(label); /* Alinha o texto ao centro */ -... - -void button_event_callback(lv_event_t * e) -{ - printf("Clicado\n"); -} -``` - -### Micropython -Saiba mais em [Micropython](https://docs.lvgl.io/master/get-started/bindings/micropython.html) - -```python -def button_event_callback(event): - print("Clicado") - -# Cria um botão e um rótulo (label) -button = lv.btn(lv.scr_act()) -button.set_pos(10, 10) -button.set_size(100, 50) -button.add_event_cb(button_event_callback, lv.EVENT.CLICKED, None) - -label = lv.label(button) -label.set_text("Cliquq aqui") -label.center() -``` - -## Serviços -O LVGL Kft foi estabelecido para fornecer uma base sólida para a biblioteca LVGL. Oferecemos vários tipos de serviços -para ajudá-lo no desenvolvimento da interface do usuário: - -- Design gráfico -- Implementação de IU -- Consultoria/Suporte - -Para mais informações, consulte [LVGL Serviços](https://lvgl.io/services). Sinta-se à vontade para entrar em contato -conosco se tiver alguma dúvida. - -## Contribuindo -O LVGL é um projeto aberto e sua contribuição é muito bem-vinda. Há muitas maneiras de contribuir, desde simplesmente -falando sobre seu projeto, escrevendo exemplos, melhorando a documentação, corrigindo bugs até hospedar seu próprio -projeto sob a organização LVGL. - -Para obter uma descrição detalhada das oportunidades de contribuição, visite a seção de [contribuição](https://docs.lvgl.io/master/CONTRIBUTING.html) da documentação. diff --git a/lib/libesp32_lvgl/lvgl/README_zh.md b/lib/libesp32_lvgl/lvgl/README_zh.md deleted file mode 100644 index cac080d4e..000000000 --- a/lib/libesp32_lvgl/lvgl/README_zh.md +++ /dev/null @@ -1,193 +0,0 @@ -

LVGL - Light and Versatile Graphics Library

-

LVGL - 轻量级通用型图形库

- - - -

- -

-

-LVGL是一个高度可裁剪、低资源占用、界面美观且易用的嵌入式系统图形库 -

- - -

-官网 · -文档 · -论坛 · -服务 · -例程 -

- - -[English](./README.md) | **中文** | [Português do Brasil](./README_pt_BR.md) - - ---- - -#### 目录 -- [概况与总览](#概况与总览) -- [如何入门](#如何入门) -- [例程](#例程) -- [服务](#服务) -- [如何向社区贡献](#如何向社区贡献) - -## 概况与总览 -### 特性 -* 丰富且强大的模块化[图形组件](https://docs.lvgl.io/master/widgets/index.html):按钮 (buttons)、图表 (charts)、列表 (lists)、滑动条 (sliders)、图片 (images) 等 -* 高级的图形引擎:动画、抗锯齿、透明度、平滑滚动、图层混合等效果 -* 支持多种[输入设备](https://docs.lvgl.io/master/overview/indev.html):触摸屏、 键盘、编码器、按键等 -* 支持[多显示设备](https://docs.lvgl.io/master/overview/display.html) -* 不依赖特定的硬件平台,可以在任何显示屏上运行 -* 配置可裁剪(最低资源占用:64 kB Flash,16 kB RAM) -* 基于UTF-8的多语种支持,例如中文、日文、韩文、阿拉伯文等 -* 可以通过[类CSS](https://docs.lvgl.io/master/overview/style.html)的方式来设计、布局图形界面(例如:[Flexbox](https://docs.lvgl.io/master/layouts/flex.html)、[Grid](https://docs.lvgl.io/master/layouts/grid.html)) -* 支持操作系统、外置内存、以及硬件加速(LVGL已内建支持STM32 DMA2D、SWM341 DMA2D、NXP PXP和VGLite) -* 即便仅有[单缓冲区(frame buffer)](https://docs.lvgl.io/master/porting/display.html)的情况下,也可保证渲染如丝般顺滑 -* 全部由C编写完成,并支持C++调用 -* 支持Micropython编程,参见:[LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings) -* 支持[模拟器](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html)仿真,可以无硬件依托进行开发 -* 丰富详实的[例程](https://github.com/lvgl/lvgl/tree/master/examples) -* 详尽的[文档](http://docs.lvgl.io/)以及API参考手册,可线上查阅或可下载为PDF格式 - -### 硬件要求 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
要求 最低要求建议要求
架构16、32、64位微控制器或微处理器
时钟 > 16 MHz > 48 MHz
Flash/ROM > 64 kB > 180 kB
Static RAM > 16 kB > 48 kB
Draw buffer > 1 × hor. res. pixels > 1/10屏幕大小
编译器 C99或更新
- -*注意:资源占用情况与具体硬件平台、编译器等因素有关,上表中仅给出参考值* - -### 已经支持的平台 -LVGL本身并不依赖特定的硬件平台,任何满足LVGL硬件配置要求的微控制器均可运行LVGL。 -如下仅列举其中一部分: - -- NXP: Kinetis, LPC, iMX, iMX RT -- STM32F1, STM32F3, STM32F4, STM32F7, STM32L4, STM32L5, STM32H7 -- Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ -- [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb) -- [Raspberry Pi](http://www.vk3erw.com/index.php/16-software/63-raspberry-pi-official-7-touchscreen-and-littlevgl) -- [Espressif ESP32](https://github.com/lvgl/lv_port_esp32) -- [Infineon Aurix](https://github.com/lvgl/lv_port_aurix) -- Nordic NRF52 Bluetooth modules -- Quectel modems -- [SYNWIT SWM341](https://www.synwit.cn/) - -LVGL也支持: -- [Arduino library](https://docs.lvgl.io/master/get-started/platforms/arduino.html) -- [PlatformIO package](https://platformio.org/lib/show/12440/lvgl) -- [Zephyr library](https://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_LVGL.html) -- [ESP32 component](https://docs.lvgl.io/master/get-started/platforms/espressif.html) -- [NXP MCUXpresso component](https://www.nxp.com/design/software/embedded-software/lvgl-open-source-graphics-library:LITTLEVGL-OPEN-SOURCE-GRAPHICS-LIBRARY) -- [NuttX library](https://docs.lvgl.io/master/get-started/os/nuttx.html) -- [RT-Thread RTOS](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/packages-manual/lvgl-docs/introduction) - - -## 如何入门 -请按照如下顺序来学习LVGL: -1. 使用[网页在线例程](https://lvgl.io/demos)来体验LVGL(3分钟) -2. 阅读文档[简介](https://docs.lvgl.io/master/intro/index.html)章节来初步了解LVGL(5分钟) -3. 再来阅读一下文档快速[快速概览](https://docs.lvgl.io/master/get-started/quick-overview.html)章节来了解LVGL的基本知识(15分钟) -4. 学习如何使用[模拟器](https://docs.lvgl.io/master/get-started/platforms/pc-simulator.html)来在电脑上仿真LVGL(10分钟) -5. 试着动手实践一些[例程](https://github.com/lvgl/lvgl/tree/master/examples) -6. 参考[移植指南](https://docs.lvgl.io/master/porting/index.html)尝试将LVGL移植到一块开发板上,LVGL也已经提供了一些移植好的[工程](https://github.com/lvgl?q=lv_port_) -7. 仔细阅读文档[总览](https://docs.lvgl.io/master/overview/index.html)章节来更加深入的了解和熟悉LVGL(2-3小时) -8. 浏览文档[组件(Widgets)](https://docs.lvgl.io/master/widgets/index.html)章节来了解如何使用它们 -9. 如果你有问题可以到LVGL[论坛](http://forum.lvgl.io/)提问 -10. 阅读文档[如何向社区贡献](https://docs.lvgl.io/master/CONTRIBUTING.html)章节来看看你能帮LVGL社区做些什么,以促进LVGL软件质量的不断提高(15分钟) - -## 例程 - -更多例程请参见 [examples](https://github.com/lvgl/lvgl/tree/master/examples) 文件夹。 - -![LVGL button with label example](https://github.com/lvgl/lvgl/raw/master/docs/misc/btn_example.png) - -### C -```c -lv_obj_t * btn = lv_btn_create(lv_scr_act()); /*Add a button to the current screen*/ -lv_obj_set_pos(btn, 10, 10); /*Set its position*/ -lv_obj_set_size(btn, 100, 50); /*Set its size*/ -lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL); /*Assign a callback to the button*/ - -lv_obj_t * label = lv_label_create(btn); /*Add a label to the button*/ -lv_label_set_text(label, "Button"); /*Set the labels text*/ -lv_obj_center(label); /*Align the label to the center*/ -... - -void btn_event_cb(lv_event_t * e) -{ - printf("Clicked\n"); -} -``` -### Micropython -更多信息请到 [Micropython官网](https://docs.lvgl.io/master/get-started/bindings/micropython.html) 查询. -```python -def btn_event_cb(e): - print("Clicked") - -# Create a Button and a Label -btn = lv.btn(lv.scr_act()) -btn.set_pos(10, 10) -btn.set_size(100, 50) -btn.add_event_cb(btn_event_cb, lv.EVENT.CLICKED, None) - -label = lv.label(btn) -label.set_text("Button") -label.center() -``` - -## 服务 -LVGL 责任有限公司成立的目的是为了给用户使用LVGL图形库提供额外的技术支持,我们致力于提供以下服务: - -- 图形设计 -- UI设计 -- 技术咨询以及技术支持 - -更多信息请参见 https://lvgl.io/services ,如果有任何问题请随时联系我们。 - - -## 如何向社区贡献 -LVGL是一个开源项目,非常欢迎您参与到社区贡献当中。您有很多种方式来为提高LVGL贡献您的一份力量,包括但不限于: - -- 介绍你基于LVGL设计的作品或项目 -- 写一些例程 -- 修改以及完善文档 -- 修复bug - -请参见文档[如何向社区贡献](https://docs.lvgl.io/master/CONTRIBUTING.html)章节来获取更多信息。 diff --git a/lib/libesp32_lvgl/lvgl/library.json b/lib/libesp32_lvgl/lvgl/library.json index 068fc5c47..beb14edd3 100644 --- a/lib/libesp32_lvgl/lvgl/library.json +++ b/lib/libesp32_lvgl/lvgl/library.json @@ -1,6 +1,6 @@ { "name": "lvgl", - "version": "8.3.11", + "version": "9.0.0", "keywords": "graphics, gui, embedded, tft, lvgl", "description": "Graphics library to create embedded GUI with easy-to-use graphical elements, beautiful visual effects and low memory footprint. It offers anti-aliasing, opacity, and animations using only one frame buffer.", "repository": { diff --git a/lib/libesp32_lvgl/lvgl/library.properties b/lib/libesp32_lvgl/lvgl/library.properties index bc7411552..11cacf03d 100644 --- a/lib/libesp32_lvgl/lvgl/library.properties +++ b/lib/libesp32_lvgl/lvgl/library.properties @@ -1,5 +1,5 @@ name=lvgl -version=8.3.11 +version=9.0.0 author=kisvegabor maintainer=kisvegabor,embeddedt,pete-pjb sentence=Full-featured Graphics Library for Embedded Systems diff --git a/lib/libesp32_lvgl/lvgl/lv_conf_template.h b/lib/libesp32_lvgl/lvgl/lv_conf_template.h index bed77fb8f..742d95cb0 100644 --- a/lib/libesp32_lvgl/lvgl/lv_conf_template.h +++ b/lib/libesp32_lvgl/lvgl/lv_conf_template.h @@ -1,6 +1,6 @@ /** * @file lv_conf.h - * Configuration file for v8.3.11 + * Configuration file for v9.0.0 */ /* @@ -17,39 +17,35 @@ #ifndef LV_CONF_H #define LV_CONF_H -#include - /*==================== COLOR SETTINGS *====================*/ -/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/ +/*Color depth: 8 (A8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/ #define LV_COLOR_DEPTH 16 -/*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/ -#define LV_COLOR_16_SWAP 0 - -/*Enable features to draw on transparent background. - *It's required if opa, and transform_* style properties are used. - *Can be also used if the UI is above another layer, e.g. an OSD menu or video player.*/ -#define LV_COLOR_SCREEN_TRANSP 0 - -/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. - * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */ -#define LV_COLOR_MIX_ROUND_OFS 0 - -/*Images pixels with this color will not be drawn if they are chroma keyed)*/ -#define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/ - /*========================= - MEMORY SETTINGS + STDLIB WRAPPER SETTINGS *=========================*/ -/*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/ -#define LV_MEM_CUSTOM 0 -#if LV_MEM_CUSTOM == 0 - /*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/ - #define LV_MEM_SIZE (48U * 1024U) /*[bytes]*/ +/* Possible values + * - LV_STDLIB_BUILTIN: LVGL's built in implementation + * - LV_STDLIB_CLIB: Standard C functions, like malloc, strlen, etc + * - LV_STDLIB_MICROPYTHON: MicroPython implementation + * - LV_STDLIB_RTTHREAD: RT-Thread implementation + * - LV_STDLIB_CUSTOM: Implement the functions externally + */ +#define LV_USE_STDLIB_MALLOC LV_STDLIB_BUILTIN +#define LV_USE_STDLIB_STRING LV_STDLIB_BUILTIN +#define LV_USE_STDLIB_SPRINTF LV_STDLIB_BUILTIN + + +#if LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN + /*Size of the memory available for `lv_malloc()` in bytes (>= 2kB)*/ + #define LV_MEM_SIZE (64 * 1024U) /*[bytes]*/ + + /*Size of the memory expand for `lv_malloc()` in bytes*/ + #define LV_MEM_POOL_EXPAND_SIZE 0 /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/ #define LV_MEM_ADR 0 /*0: unused*/ @@ -58,173 +54,134 @@ #undef LV_MEM_POOL_INCLUDE #undef LV_MEM_POOL_ALLOC #endif - -#else /*LV_MEM_CUSTOM*/ - #define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ - #define LV_MEM_CUSTOM_ALLOC malloc - #define LV_MEM_CUSTOM_FREE free - #define LV_MEM_CUSTOM_REALLOC realloc -#endif /*LV_MEM_CUSTOM*/ - -/*Number of the intermediate memory buffer used during rendering and other internal processing mechanisms. - *You will see an error log message if there wasn't enough buffers. */ -#define LV_MEM_BUF_MAX_NUM 16 - -/*Use the standard `memcpy` and `memset` instead of LVGL's own functions. (Might or might not be faster).*/ -#define LV_MEMCPY_MEMSET_STD 0 +#endif /*LV_USE_MALLOC == LV_STDLIB_BUILTIN*/ /*==================== HAL SETTINGS *====================*/ -/*Default display refresh period. LVG will redraw changed areas with this period time*/ -#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ - -/*Input device read period in milliseconds*/ -#define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/ - -/*Use a custom tick source that tells the elapsed time in milliseconds. - *It removes the need to manually update the tick with `lv_tick_inc()`)*/ -#define LV_TICK_CUSTOM 0 -#if LV_TICK_CUSTOM - #define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ - #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ - /*If using lvgl as ESP32 component*/ - // #define LV_TICK_CUSTOM_INCLUDE "esp_timer.h" - // #define LV_TICK_CUSTOM_SYS_TIME_EXPR ((esp_timer_get_time() / 1000LL)) -#endif /*LV_TICK_CUSTOM*/ +/*Default display refresh, input device read and animation step period.*/ +#define LV_DEF_REFR_PERIOD 33 /*[ms]*/ /*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings. *(Not so important, you can adjust it to modify default sizes and spaces)*/ #define LV_DPI_DEF 130 /*[px/inch]*/ +/*================= + * OPERATING SYSTEM + *=================*/ +/*Select an operating system to use. Possible options: + * - LV_OS_NONE + * - LV_OS_PTHREAD + * - LV_OS_FREERTOS + * - LV_OS_CMSIS_RTOS2 + * - LV_OS_RTTHREAD + * - LV_OS_WINDOWS + * - LV_OS_CUSTOM */ +#define LV_USE_OS LV_OS_NONE + +#if LV_USE_OS == LV_OS_CUSTOM + #define LV_OS_CUSTOM_INCLUDE +#endif + +/*======================== + * RENDERING CONFIGURATION + *========================*/ + +/*Align the stride of all layers and images to this bytes*/ +#define LV_DRAW_BUF_STRIDE_ALIGN 1 + +/*Align the start address of draw_buf addresses to this bytes*/ +#define LV_DRAW_BUF_ALIGN 4 + +#define LV_USE_DRAW_SW 1 +#if LV_USE_DRAW_SW == 1 + /* Set the number of draw unit. + * > 1 requires an operating system enabled in `LV_USE_OS` + * > 1 means multiply threads will render the screen in parallel */ + #define LV_DRAW_SW_DRAW_UNIT_CNT 1 + + /* Use Arm-2D to accelerate the sw render */ + #define LV_USE_DRAW_ARM2D_SYNC 0 + + /* If a widget has `style_opa < 255` (not `bg_opa`, `text_opa` etc) or not NORMAL blend mode + * it is buffered into a "simple" layer before rendering. The widget can be buffered in smaller chunks. + * "Transformed layers" (if `transform_angle/zoom` are set) use larger buffers + * and can't be drawn in chunks. */ + + /*The target buffer size for simple layer chunks.*/ + #define LV_DRAW_SW_LAYER_SIMPLE_BUF_SIZE (24 * 1024) /*[bytes]*/ + + /* 0: use a simple renderer capable of drawing only simple rectangles with gradient, images, texts, and straight lines only + * 1: use a complex renderer capable of drawing rounded corners, shadow, skew lines, and arcs too */ + #define LV_DRAW_SW_COMPLEX 1 + + #if LV_DRAW_SW_COMPLEX == 1 + /*Allow buffering some shadow calculation. + *LV_DRAW_SW_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius` + *Caching has LV_DRAW_SW_SHADOW_CACHE_SIZE^2 RAM cost*/ + #define LV_DRAW_SW_SHADOW_CACHE_SIZE 0 + + /* Set number of maximally cached circle data. + * The circumference of 1/4 circle are saved for anti-aliasing + * radius * 4 bytes are used per circle (the most often used radiuses are saved) + * 0: to disable caching */ + #define LV_DRAW_SW_CIRCLE_CACHE_SIZE 4 + #endif + + #define LV_USE_DRAW_SW_ASM LV_DRAW_SW_ASM_NONE + + #if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_CUSTOM + #define LV_DRAW_SW_ASM_CUSTOM_INCLUDE "" + #endif +#endif + +/* Use NXP's VG-Lite GPU on iMX RTxxx platforms. */ +#define LV_USE_DRAW_VGLITE 0 + +#if LV_USE_DRAW_VGLITE + /* Enable blit quality degradation workaround recommended for screen's dimension > 352 pixels. */ + #define LV_USE_VGLITE_BLIT_SPLIT 0 + + #if LV_USE_OS + /* Enable VGLite draw async. Queue multiple tasks and flash them once to the GPU. */ + #define LV_USE_VGLITE_DRAW_ASYNC 1 + #endif + + /* Enable VGLite asserts. */ + #define LV_USE_VGLITE_ASSERT 0 +#endif + +/* Use NXP's PXP on iMX RTxxx platforms. */ +#define LV_USE_DRAW_PXP 0 + +#if LV_USE_DRAW_PXP + /* Enable PXP asserts. */ + #define LV_USE_PXP_ASSERT 0 +#endif + +/* Use Renesas Dave2D on RA platforms. */ +#define LV_USE_DRAW_DAVE2D 0 + +/* Draw using cached SDL textures*/ +#define LV_USE_DRAW_SDL 0 + +/* Use VG-Lite GPU. */ +#define LV_USE_DRAW_VG_LITE 0 + +#if LV_USE_DRAW_VG_LITE +/* Enable VG-Lite custom external 'gpu_init()' function */ +#define LV_VG_LITE_USE_GPU_INIT 0 + +/* Enable VG-Lite assert. */ +#define LV_VG_LITE_USE_ASSERT 0 + +#endif + /*======================= * FEATURE CONFIGURATION *=======================*/ -/*------------- - * Drawing - *-----------*/ - -/*Enable complex draw engine. - *Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/ -#define LV_DRAW_COMPLEX 1 -#if LV_DRAW_COMPLEX != 0 - - /*Allow buffering some shadow calculation. - *LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius` - *Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/ - #define LV_SHADOW_CACHE_SIZE 0 - - /* Set number of maximally cached circle data. - * The circumference of 1/4 circle are saved for anti-aliasing - * radius * 4 bytes are used per circle (the most often used radiuses are saved) - * 0: to disable caching */ - #define LV_CIRCLE_CACHE_SIZE 4 -#endif /*LV_DRAW_COMPLEX*/ - -/** - * "Simple layers" are used when a widget has `style_opa < 255` to buffer the widget into a layer - * and blend it as an image with the given opacity. - * Note that `bg_opa`, `text_opa` etc don't require buffering into layer) - * The widget can be buffered in smaller chunks to avoid using large buffers. - * - * - LV_LAYER_SIMPLE_BUF_SIZE: [bytes] the optimal target buffer size. LVGL will try to allocate it - * - LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE: [bytes] used if `LV_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated. - * - * Both buffer sizes are in bytes. - * "Transformed layers" (where transform_angle/zoom properties are used) use larger buffers - * and can't be drawn in chunks. So these settings affects only widgets with opacity. - */ -#define LV_LAYER_SIMPLE_BUF_SIZE (24 * 1024) -#define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE (3 * 1024) - -/*Default image cache size. Image caching keeps the images opened. - *If only the built-in image formats are used there is no real advantage of caching. (I.e. if no new image decoder is added) - *With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. - *However the opened images might consume additional RAM. - *0: to disable caching*/ -#define LV_IMG_CACHE_DEF_SIZE 0 - -/*Number of stops allowed per gradient. Increase this to allow more stops. - *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ -#define LV_GRADIENT_MAX_STOPS 2 - -/*Default gradient buffer size. - *When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again. - *LV_GRAD_CACHE_DEF_SIZE sets the size of this cache in bytes. - *If the cache is too small the map will be allocated only while it's required for the drawing. - *0 mean no caching.*/ -#define LV_GRAD_CACHE_DEF_SIZE 0 - -/*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display) - *LV_DITHER_GRADIENT implies allocating one or two more lines of the object's rendering surface - *The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion */ -#define LV_DITHER_GRADIENT 0 -#if LV_DITHER_GRADIENT - /*Add support for error diffusion dithering. - *Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing. - *The increase in memory consumption is (24 bits * object's width)*/ - #define LV_DITHER_ERROR_DIFFUSION 0 -#endif - -/*Maximum buffer size to allocate for rotation. - *Only used if software rotation is enabled in the display driver.*/ -#define LV_DISP_ROT_MAX_BUF (10*1024) - -/*------------- - * GPU - *-----------*/ - -/*Use Arm's 2D acceleration library Arm-2D */ -#define LV_USE_GPU_ARM2D 0 - -/*Use STM32's DMA2D (aka Chrom Art) GPU*/ -#define LV_USE_GPU_STM32_DMA2D 0 -#if LV_USE_GPU_STM32_DMA2D - /*Must be defined to include path of CMSIS header of target processor - e.g. "stm32f7xx.h" or "stm32f4xx.h"*/ - #define LV_GPU_DMA2D_CMSIS_INCLUDE -#endif - -/*Enable RA6M3 G2D GPU*/ -#define LV_USE_GPU_RA6M3_G2D 0 -#if LV_USE_GPU_RA6M3_G2D - /*include path of target processor - e.g. "hal_data.h"*/ - #define LV_GPU_RA6M3_G2D_INCLUDE "hal_data.h" -#endif - -/*Use SWM341's DMA2D GPU*/ -#define LV_USE_GPU_SWM341_DMA2D 0 -#if LV_USE_GPU_SWM341_DMA2D - #define LV_GPU_SWM341_DMA2D_INCLUDE "SWM341.h" -#endif - -/*Use NXP's PXP GPU iMX RTxxx platforms*/ -#define LV_USE_GPU_NXP_PXP 0 -#if LV_USE_GPU_NXP_PXP - /*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c) - * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS - * has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected. - *0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init() - */ - #define LV_USE_GPU_NXP_PXP_AUTO_INIT 0 -#endif - -/*Use NXP's VG-Lite GPU iMX RTxxx platforms*/ -#define LV_USE_GPU_NXP_VG_LITE 0 - -/*Use SDL renderer API*/ -#define LV_USE_GPU_SDL 0 -#if LV_USE_GPU_SDL - #define LV_GPU_SDL_INCLUDE_PATH - /*Texture cache size, 8MB by default*/ - #define LV_GPU_SDL_LRU_SIZE (1024 * 1024 * 8) - /*Custom blend mode for mask drawing, disable if you need to link with older SDL2 lib*/ - #define LV_GPU_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6)) -#endif - /*------------- * Logging *-----------*/ @@ -246,6 +203,14 @@ *0: User need to register a callback with `lv_log_register_print_cb()`*/ #define LV_LOG_PRINTF 0 + /*1: Enable print timestamp; + *0: Disable print timestamp*/ + #define LV_LOG_USE_TIMESTAMP 1 + + /*1: Print file and line number of the log; + *0: Do not print file and line number of the log*/ + #define LV_LOG_USE_FILE_LINE 1 + /*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/ #define LV_LOG_TRACE_MEM 1 #define LV_LOG_TRACE_TIMER 1 @@ -255,6 +220,7 @@ #define LV_LOG_TRACE_OBJ_CREATE 1 #define LV_LOG_TRACE_LAYOUT 1 #define LV_LOG_TRACE_ANIM 1 + #define LV_LOG_TRACE_CACHE 1 #endif /*LV_USE_LOG*/ @@ -275,43 +241,79 @@ #define LV_ASSERT_HANDLER while(1); /*Halt by default*/ /*------------- - * Others + * Debug *-----------*/ -/*1: Show CPU usage and FPS count*/ -#define LV_USE_PERF_MONITOR 0 -#if LV_USE_PERF_MONITOR - #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT -#endif - -/*1: Show the used memory and the memory fragmentation - * Requires LV_MEM_CUSTOM = 0*/ -#define LV_USE_MEM_MONITOR 0 -#if LV_USE_MEM_MONITOR - #define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT -#endif - /*1: Draw random colored rectangles over the redrawn areas*/ #define LV_USE_REFR_DEBUG 0 -/*Change the built in (v)snprintf functions*/ -#define LV_SPRINTF_CUSTOM 0 -#if LV_SPRINTF_CUSTOM - #define LV_SPRINTF_INCLUDE - #define lv_snprintf snprintf - #define lv_vsnprintf vsnprintf -#else /*LV_SPRINTF_CUSTOM*/ - #define LV_SPRINTF_USE_FLOAT 0 -#endif /*LV_SPRINTF_CUSTOM*/ +/*1: Draw a red overlay for ARGB layers and a green overlay for RGB layers*/ +#define LV_USE_LAYER_DEBUG 0 -#define LV_USE_USER_DATA 1 +/*1: Draw overlays with different colors for each draw_unit's tasks. + *Also add the index number of the draw unit on white background. + *For layers add the index number of the draw unit on black background.*/ +#define LV_USE_PARALLEL_DRAW_DEBUG 0 -/*Garbage Collector settings - *Used if lvgl is bound to higher level language and the memory is managed by that language*/ -#define LV_ENABLE_GC 0 -#if LV_ENABLE_GC != 0 - #define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ -#endif /*LV_ENABLE_GC*/ +/*------------- + * Others + *-----------*/ + +#define LV_ENABLE_GLOBAL_CUSTOM 0 +#if LV_ENABLE_GLOBAL_CUSTOM + /*Header to include for the custom 'lv_global' function"*/ + #define LV_GLOBAL_CUSTOM_INCLUDE +#endif + +/*Default cache size in bytes. + *Used by image decoders such as `lv_lodepng` to keep the decoded image in the memory. + *If size is not set to 0, the decoder will fail to decode when the cache is full. + *If size is 0, the cache function is not enabled and the decoded mem will be released immediately after use.*/ +#define LV_CACHE_DEF_SIZE 0 + +/*Default number of image header cache entries. The cache is used to store the headers of images + *The main logic is like `LV_CACHE_DEF_SIZE` but for image headers.*/ +#define LV_IMAGE_HEADER_CACHE_DEF_CNT 0 + +/*Number of stops allowed per gradient. Increase this to allow more stops. + *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ +#define LV_GRADIENT_MAX_STOPS 2 + +/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. + * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */ +#define LV_COLOR_MIX_ROUND_OFS 0 + +/* Add 2 x 32 bit variables to each lv_obj_t to speed up getting style properties */ +#define LV_OBJ_STYLE_CACHE 0 + +/* Add `id` field to `lv_obj_t` */ +#define LV_USE_OBJ_ID 0 + +/* Use lvgl builtin method for obj ID */ +#define LV_USE_OBJ_ID_BUILTIN 0 + +/*Use obj property set/get API*/ +#define LV_USE_OBJ_PROPERTY 0 + +/* VG-Lite Simulator */ +/*Requires: LV_USE_THORVG_INTERNAL or LV_USE_THORVG_EXTERNAL */ +#define LV_USE_VG_LITE_THORVG 0 + +#if LV_USE_VG_LITE_THORVG + + /*Enable LVGL's blend mode support*/ + #define LV_VG_LITE_THORVG_LVGL_BLEND_SUPPORT 0 + + /*Enable YUV color format support*/ + #define LV_VG_LITE_THORVG_YUV_SUPPORT 0 + + /*Enable 16 pixels alignment*/ + #define LV_VG_LITE_THORVG_16PIXELS_ALIGN 1 + + /*Enable multi-thread render*/ + #define LV_VG_LITE_THORVG_THREAD_RENDER 0 + +#endif /*===================== * COMPILER SETTINGS @@ -326,7 +328,7 @@ /*Define a custom attribute to `lv_timer_handler` function*/ #define LV_ATTRIBUTE_TIMER_HANDLER -/*Define a custom attribute to `lv_disp_flush_ready` function*/ +/*Define a custom attribute to `lv_display_flush_ready` function*/ #define LV_ATTRIBUTE_FLUSH_READY /*Required alignment size for buffers*/ @@ -345,15 +347,15 @@ /*Place performance critical functions into a faster memory (e.g RAM)*/ #define LV_ATTRIBUTE_FAST_MEM -/*Prefix variables that are used in GPU accelerated operations, often these need to be placed in RAM sections that are DMA accessible*/ -#define LV_ATTRIBUTE_DMA - /*Export integer constant to binding. This macro is used with constants in the form of LV_ that *should also appear on LVGL binding API such as Micropython.*/ #define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/ -/*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/ -#define LV_USE_LARGE_COORD 0 +/*Prefix all global extern data with this*/ +#define LV_ATTRIBUTE_EXTERN_DATA + +/* Use `float` as `lv_value_precise_t` */ +#define LV_USE_FLOAT 0 /*================== * FONT USAGE @@ -384,7 +386,6 @@ #define LV_FONT_MONTSERRAT_48 0 /*Demonstrate special features*/ -#define LV_FONT_MONTSERRAT_12_SUBPX 0 #define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/ #define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, Persian letters and all their forms*/ #define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/ @@ -409,13 +410,6 @@ /*Enables/disables support for compressed fonts.*/ #define LV_USE_FONT_COMPRESSED 0 -/*Enable subpixel rendering*/ -#define LV_USE_FONT_SUBPX 0 -#if LV_USE_FONT_SUBPX - /*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/ - #define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/ -#endif - /*Enable drawing placeholders when glyph dsc is not found*/ #define LV_USE_FONT_PLACEHOLDER 1 @@ -432,7 +426,7 @@ #define LV_TXT_ENC LV_TXT_ENC_UTF8 /*Can break (wrap) texts on these chars*/ -#define LV_TXT_BREAK_CHARS " ,.;:-_" +#define LV_TXT_BREAK_CHARS " ,.;:-_)]}" /*If a word is at least this long, will break wherever "prettiest" *To disable, set to a value <= 0*/ @@ -446,9 +440,6 @@ *Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/ #define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3 -/*The control character to use for signalling text recoloring.*/ -#define LV_TXT_COLOR_CMD "#" - /*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts. *The direction will be processed according to the Unicode Bidirectional Algorithm: *https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ @@ -466,59 +457,22 @@ #define LV_USE_ARABIC_PERSIAN_CHARS 0 /*================== - * WIDGET USAGE + * WIDGETS *================*/ /*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/ +#define LV_WIDGETS_HAS_DEFAULT_VALUE 1 + +#define LV_USE_ANIMIMG 1 + #define LV_USE_ARC 1 #define LV_USE_BAR 1 -#define LV_USE_BTN 1 +#define LV_USE_BUTTON 1 -#define LV_USE_BTNMATRIX 1 - -#define LV_USE_CANVAS 1 - -#define LV_USE_CHECKBOX 1 - -#define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ - -#define LV_USE_IMG 1 /*Requires: lv_label*/ - -#define LV_USE_LABEL 1 -#if LV_USE_LABEL - #define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ - #define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ -#endif - -#define LV_USE_LINE 1 - -#define LV_USE_ROLLER 1 /*Requires: lv_label*/ -#if LV_USE_ROLLER - #define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/ -#endif - -#define LV_USE_SLIDER 1 /*Requires: lv_bar*/ - -#define LV_USE_SWITCH 1 - -#define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ -#if LV_USE_TEXTAREA != 0 - #define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ -#endif - -#define LV_USE_TABLE 1 - -/*================== - * EXTRA COMPONENTS - *==================*/ - -/*----------- - * Widgets - *----------*/ -#define LV_USE_ANIMIMG 1 +#define LV_USE_BUTTONMATRIX 1 #define LV_USE_CALENDAR 1 #if LV_USE_CALENDAR @@ -534,24 +488,43 @@ #define LV_USE_CALENDAR_HEADER_DROPDOWN 1 #endif /*LV_USE_CALENDAR*/ +#define LV_USE_CANVAS 1 + #define LV_USE_CHART 1 -#define LV_USE_COLORWHEEL 1 +#define LV_USE_CHECKBOX 1 -#define LV_USE_IMGBTN 1 +#define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ + +#define LV_USE_IMAGE 1 /*Requires: lv_label*/ + +#define LV_USE_IMAGEBUTTON 1 #define LV_USE_KEYBOARD 1 +#define LV_USE_LABEL 1 +#if LV_USE_LABEL + #define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ + #define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ + #define LV_LABEL_WAIT_CHAR_COUNT 3 /*The count of wait chart*/ +#endif + #define LV_USE_LED 1 +#define LV_USE_LINE 1 + #define LV_USE_LIST 1 #define LV_USE_MENU 1 -#define LV_USE_METER 1 - #define LV_USE_MSGBOX 1 +#define LV_USE_ROLLER 1 /*Requires: lv_label*/ + +#define LV_USE_SCALE 1 + +#define LV_USE_SLIDER 1 /*Requires: lv_bar*/ + #define LV_USE_SPAN 1 #if LV_USE_SPAN /*A line text can contain maximum num of span descriptor */ @@ -562,15 +535,24 @@ #define LV_USE_SPINNER 1 +#define LV_USE_SWITCH 1 + +#define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ +#if LV_USE_TEXTAREA != 0 + #define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ +#endif + +#define LV_USE_TABLE 1 + #define LV_USE_TABVIEW 1 #define LV_USE_TILEVIEW 1 #define LV_USE_WIN 1 -/*----------- - * Themes - *----------*/ +/*================== + * THEMES + *==================*/ /*A simple, impressive and very complete theme*/ #define LV_USE_THEME_DEFAULT 1 @@ -587,14 +569,14 @@ #endif /*LV_USE_THEME_DEFAULT*/ /*A very simple theme that is a good starting point for a custom theme*/ -#define LV_USE_THEME_BASIC 1 +#define LV_USE_THEME_SIMPLE 1 /*A theme designed for monochrome displays*/ #define LV_USE_THEME_MONO 1 -/*----------- - * Layouts - *----------*/ +/*================== + * LAYOUTS + *==================*/ /*A layout similar to Flexbox in CSS.*/ #define LV_USE_FLEX 1 @@ -602,9 +584,9 @@ /*A layout similar to Grid in CSS.*/ #define LV_USE_GRID 1 -/*--------------------- - * 3rd party libraries - *--------------------*/ +/*==================== + * 3RD PARTS LIBRARIES + *====================*/ /*File system interfaces for common APIs */ @@ -639,56 +621,93 @@ #define LV_FS_FATFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ #endif -/*API for LittleFS (library needs to be added separately). Uses lfs_file_open, lfs_file_read, etc*/ -#define LV_USE_FS_LITTLEFS 0 -#if LV_USE_FS_LITTLEFS - #define LV_FS_LITTLEFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ - #define LV_FS_LITTLEFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ +/*API for memory-mapped file access. */ +#define LV_USE_FS_MEMFS 0 +#if LV_USE_FS_MEMFS + #define LV_FS_MEMFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ #endif -/*PNG decoder library*/ -#define LV_USE_PNG 0 +/*LODEPNG decoder library*/ +#define LV_USE_LODEPNG 0 + +/*PNG decoder(libpng) library*/ +#define LV_USE_LIBPNG 0 /*BMP decoder library*/ #define LV_USE_BMP 0 /* JPG + split JPG decoder library. * Split JPG is a custom format optimized for embedded systems. */ -#define LV_USE_SJPG 0 +#define LV_USE_TJPGD 0 + +/* libjpeg-turbo decoder library. + * Supports complete JPEG specifications and high-performance JPEG decoding. */ +#define LV_USE_LIBJPEG_TURBO 0 /*GIF decoder library*/ #define LV_USE_GIF 0 +#if LV_USE_GIF +/*GIF decoder accelerate*/ +#define LV_GIF_CACHE_DECODE_DATA 0 +#endif + + +/*Decode bin images to RAM*/ +#define LV_BIN_DECODER_RAM_LOAD 0 + +/*RLE decompress library*/ +#define LV_USE_RLE 0 /*QR code library*/ #define LV_USE_QRCODE 0 +/*Barcode code library*/ +#define LV_USE_BARCODE 0 + /*FreeType library*/ #define LV_USE_FREETYPE 0 #if LV_USE_FREETYPE - /*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/ - #define LV_FREETYPE_CACHE_SIZE (16 * 1024) - #if LV_FREETYPE_CACHE_SIZE >= 0 - /* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */ - /* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */ - /* if font size >= 256, must be configured as image cache */ - #define LV_FREETYPE_SBIT_CACHE 0 - /* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */ - /* (0:use system defaults) */ - #define LV_FREETYPE_CACHE_FT_FACES 0 - #define LV_FREETYPE_CACHE_FT_SIZES 0 - #endif + /*Memory used by FreeType to cache characters in kilobytes*/ + #define LV_FREETYPE_CACHE_SIZE 768 + + /*Let FreeType to use LVGL memory and file porting*/ + #define LV_FREETYPE_USE_LVGL_PORT 0 + + /* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */ + /* (0:use system defaults) */ + #define LV_FREETYPE_CACHE_FT_FACES 8 + #define LV_FREETYPE_CACHE_FT_SIZES 8 + #define LV_FREETYPE_CACHE_FT_GLYPH_CNT 256 #endif -/*Tiny TTF library*/ +/* Built-in TTF decoder */ #define LV_USE_TINY_TTF 0 #if LV_USE_TINY_TTF - /*Load TTF data from files*/ + /* Enable loading TTF data from files */ #define LV_TINY_TTF_FILE_SUPPORT 0 #endif /*Rlottie library*/ #define LV_USE_RLOTTIE 0 +/*Enable Vector Graphic APIs*/ +#define LV_USE_VECTOR_GRAPHIC 0 + +/* Enable ThorVG (vector graphics library) from the src/libs folder */ +#define LV_USE_THORVG_INTERNAL 0 + +/* Enable ThorVG by assuming that its installed and linked to the project */ +#define LV_USE_THORVG_EXTERNAL 0 + +/*Enable LZ4 compress/decompress lib*/ +#define LV_USE_LZ4 0 + +/*Use lvgl built-in LZ4 lib*/ +#define LV_USE_LZ4_INTERNAL 0 + +/*Use external LZ4 library*/ +#define LV_USE_LZ4_EXTERNAL 0 + /*FFmpeg library for image decoding and playing videos *Supports all major image formats so do not enable other image decoder with it*/ #define LV_USE_FFMPEG 0 @@ -697,13 +716,65 @@ #define LV_FFMPEG_DUMP_FORMAT 0 #endif -/*----------- - * Others - *----------*/ +/*================== + * OTHERS + *==================*/ /*1: Enable API to take snapshot for object*/ #define LV_USE_SNAPSHOT 0 +/*1: Enable system monitor component*/ +#define LV_USE_SYSMON 0 +#if LV_USE_SYSMON + /*Get the idle percentage. E.g. uint32_t my_get_idle(void);*/ + #define LV_SYSMON_GET_IDLE lv_timer_get_idle + + /*1: Show CPU usage and FPS count + * Requires `LV_USE_SYSMON = 1`*/ + #define LV_USE_PERF_MONITOR 0 + #if LV_USE_PERF_MONITOR + #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT + + /*0: Displays performance data on the screen, 1: Prints performance data using log.*/ + #define LV_USE_PERF_MONITOR_LOG_MODE 0 + #endif + + /*1: Show the used memory and the memory fragmentation + * Requires `LV_USE_BUILTIN_MALLOC = 1` + * Requires `LV_USE_SYSMON = 1`*/ + #define LV_USE_MEM_MONITOR 0 + #if LV_USE_MEM_MONITOR + #define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT + #endif + +#endif /*LV_USE_SYSMON*/ + +/*1: Enable the runtime performance profiler*/ +#define LV_USE_PROFILER 0 +#if LV_USE_PROFILER + /*1: Enable the built-in profiler*/ + #define LV_USE_PROFILER_BUILTIN 1 + #if LV_USE_PROFILER_BUILTIN + /*Default profiler trace buffer size*/ + #define LV_PROFILER_BUILTIN_BUF_SIZE (16 * 1024) /*[bytes]*/ + #endif + + /*Header to include for the profiler*/ + #define LV_PROFILER_INCLUDE "lvgl/src/misc/lv_profiler_builtin.h" + + /*Profiler start point function*/ + #define LV_PROFILER_BEGIN LV_PROFILER_BUILTIN_BEGIN + + /*Profiler end point function*/ + #define LV_PROFILER_END LV_PROFILER_BUILTIN_END + + /*Profiler start point function with custom tag*/ + #define LV_PROFILER_BEGIN_TAG LV_PROFILER_BUILTIN_BEGIN_TAG + + /*Profiler end point function with custom tag*/ + #define LV_PROFILER_END_TAG LV_PROFILER_BUILTIN_END_TAG +#endif + /*1: Enable Monkey test*/ #define LV_USE_MONKEY 0 @@ -716,8 +787,8 @@ /*1: Support using images as font in label or span widgets */ #define LV_USE_IMGFONT 0 -/*1: Enable a published subscriber based messaging system */ -#define LV_USE_MSG 0 +/*1: Enable an observer pattern implementation*/ +#define LV_USE_OBSERVER 1 /*1: Enable Pinyin input method*/ /*Requires: lv_keyboard*/ @@ -734,9 +805,95 @@ #define LV_IME_PINYIN_USE_K9_MODE 1 #if LV_IME_PINYIN_USE_K9_MODE == 1 #define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3 - #endif // LV_IME_PINYIN_USE_K9_MODE + #endif /*LV_IME_PINYIN_USE_K9_MODE*/ #endif +/*1: Enable file explorer*/ +/*Requires: lv_table*/ +#define LV_USE_FILE_EXPLORER 0 +#if LV_USE_FILE_EXPLORER + /*Maximum length of path*/ + #define LV_FILE_EXPLORER_PATH_MAX_LEN (128) + /*Quick access bar, 1:use, 0:not use*/ + /*Requires: lv_list*/ + #define LV_FILE_EXPLORER_QUICK_ACCESS 1 +#endif + +/*================== + * DEVICES + *==================*/ + +/*Use SDL to open window on PC and handle mouse and keyboard*/ +#define LV_USE_SDL 0 +#if LV_USE_SDL + #define LV_SDL_INCLUDE_PATH + #define LV_SDL_RENDER_MODE LV_DISPLAY_RENDER_MODE_DIRECT /*LV_DISPLAY_RENDER_MODE_DIRECT is recommended for best performance*/ + #define LV_SDL_BUF_COUNT 1 /*1 or 2*/ + #define LV_SDL_FULLSCREEN 0 /*1: Make the window full screen by default*/ + #define LV_SDL_DIRECT_EXIT 1 /*1: Exit the application when all SDL windows are closed*/ +#endif + +/*Use X11 to open window on Linux desktop and handle mouse and keyboard*/ +#define LV_USE_X11 0 +#if LV_USE_X11 + #define LV_X11_DIRECT_EXIT 1 /*Exit the application when all X11 windows have been closed*/ + #define LV_X11_DOUBLE_BUFFER 1 /*Use double buffers for endering*/ + /*select only 1 of the following render modes (LV_X11_RENDER_MODE_PARTIAL preferred!)*/ + #define LV_X11_RENDER_MODE_PARTIAL 1 /*Partial render mode (preferred)*/ + #define LV_X11_RENDER_MODE_DIRECT 0 /*direct render mode*/ + #define LV_X11_RENDER_MODE_FULL 0 /*Full render mode*/ +#endif + +/*Driver for /dev/fb*/ +#define LV_USE_LINUX_FBDEV 0 +#if LV_USE_LINUX_FBDEV + #define LV_LINUX_FBDEV_BSD 0 + #define LV_LINUX_FBDEV_RENDER_MODE LV_DISPLAY_RENDER_MODE_PARTIAL + #define LV_LINUX_FBDEV_BUFFER_COUNT 0 + #define LV_LINUX_FBDEV_BUFFER_SIZE 60 +#endif + +/*Use Nuttx to open window and handle touchscreen*/ +#define LV_USE_NUTTX 0 + +#if LV_USE_NUTTX + #define LV_USE_NUTTX_LIBUV 0 + + /*Use Nuttx custom init API to open window and handle touchscreen*/ + #define LV_USE_NUTTX_CUSTOM_INIT 0 + + /*Driver for /dev/lcd*/ + #define LV_USE_NUTTX_LCD 0 + #if LV_USE_NUTTX_LCD + #define LV_NUTTX_LCD_BUFFER_COUNT 0 + #define LV_NUTTX_LCD_BUFFER_SIZE 60 + #endif + + /*Driver for /dev/input*/ + #define LV_USE_NUTTX_TOUCHSCREEN 0 + +#endif + +/*Driver for /dev/dri/card*/ +#define LV_USE_LINUX_DRM 0 + +/*Interface for TFT_eSPI*/ +#define LV_USE_TFT_ESPI 0 + +/*Driver for evdev input devices*/ +#define LV_USE_EVDEV 0 + +/*Drivers for LCD devices connected via SPI/parallel port*/ +#define LV_USE_ST7735 0 +#define LV_USE_ST7789 0 +#define LV_USE_ST7796 0 +#define LV_USE_ILI9341 0 + +#define LV_USE_GENERIC_MIPI (LV_USE_ST7735 | LV_USE_ST7789 | LV_USE_ST7796 | LV_USE_ILI9341) + +/* LVGL Windows backend */ +#define LV_USE_WINDOWS 0 + /*================== * EXAMPLES *==================*/ @@ -751,7 +908,7 @@ /*Show some widget. It might be required to increase `LV_MEM_SIZE` */ #define LV_USE_DEMO_WIDGETS 0 #if LV_USE_DEMO_WIDGETS -#define LV_DEMO_WIDGETS_SLIDESHOW 0 + #define LV_DEMO_WIDGETS_SLIDESHOW 0 #endif /*Demonstrate the usage of encoder and keyboard*/ @@ -759,10 +916,9 @@ /*Benchmark your system*/ #define LV_USE_DEMO_BENCHMARK 0 -#if LV_USE_DEMO_BENCHMARK -/*Use RGB565A8 images with 16 bit color depth instead of ARGB8565*/ -#define LV_DEMO_BENCHMARK_RGB565A8 0 -#endif + +/*Render test for each primitives. Requires at least 480x272 display*/ +#define LV_USE_DEMO_RENDER 0 /*Stress test for LVGL*/ #define LV_USE_DEMO_STRESS 0 @@ -777,6 +933,20 @@ #define LV_DEMO_MUSIC_AUTO_PLAY 0 #endif +/*Flex layout demo*/ +#define LV_USE_DEMO_FLEX_LAYOUT 0 + +/*Smart-phone like multi-language demo*/ +#define LV_USE_DEMO_MULTILANG 0 + +/*Widget transformation demo*/ +#define LV_USE_DEMO_TRANSFORM 0 + +/*Demonstrate scroll settings*/ +#define LV_USE_DEMO_SCROLL 0 + +/*Vector graphic demo*/ +#define LV_USE_DEMO_VECTOR_GRAPHIC 0 /*--END OF LV_CONF_H--*/ #endif /*LV_CONF_H*/ diff --git a/lib/libesp32_lvgl/lvgl/lvgl.h b/lib/libesp32_lvgl/lvgl/lvgl.h index 47700d4e6..76314d729 100644 --- a/lib/libesp32_lvgl/lvgl/lvgl.h +++ b/lib/libesp32_lvgl/lvgl/lvgl.h @@ -13,61 +13,111 @@ extern "C" { /*************************** * CURRENT VERSION OF LVGL ***************************/ -#define LVGL_VERSION_MAJOR 8 -#define LVGL_VERSION_MINOR 3 -#define LVGL_VERSION_PATCH 11 -#define LVGL_VERSION_INFO "" +#define LVGL_VERSION_MAJOR 9 +#define LVGL_VERSION_MINOR 0 +#define LVGL_VERSION_PATCH 0 +#define LVGL_VERSION_INFO "" /********************* * INCLUDES *********************/ +#include "src/lv_init.h" + +#include "src/stdlib/lv_mem.h" +#include "src/stdlib/lv_string.h" +#include "src/stdlib/lv_sprintf.h" #include "src/misc/lv_log.h" #include "src/misc/lv_timer.h" #include "src/misc/lv_math.h" -#include "src/misc/lv_mem.h" +#include "src/misc/lv_array.h" #include "src/misc/lv_async.h" #include "src/misc/lv_anim_timeline.h" -#include "src/misc/lv_printf.h" +#include "src/misc/lv_profiler_builtin.h" +#include "src/misc/lv_rb.h" -#include "src/hal/lv_hal.h" +#include "src/tick/lv_tick.h" #include "src/core/lv_obj.h" #include "src/core/lv_group.h" -#include "src/core/lv_indev.h" +#include "src/indev/lv_indev.h" #include "src/core/lv_refr.h" -#include "src/core/lv_disp.h" -#include "src/core/lv_theme.h" +#include "src/display/lv_display.h" #include "src/font/lv_font.h" -#include "src/font/lv_font_loader.h" +#include "src/font/lv_binfont_loader.h" #include "src/font/lv_font_fmt_txt.h" -#include "src/widgets/lv_arc.h" -#include "src/widgets/lv_btn.h" -#include "src/widgets/lv_img.h" -#include "src/widgets/lv_label.h" -#include "src/widgets/lv_line.h" -#include "src/widgets/lv_table.h" -#include "src/widgets/lv_checkbox.h" -#include "src/widgets/lv_bar.h" -#include "src/widgets/lv_slider.h" -#include "src/widgets/lv_btnmatrix.h" -#include "src/widgets/lv_dropdown.h" -#include "src/widgets/lv_roller.h" -#include "src/widgets/lv_textarea.h" -#include "src/widgets/lv_canvas.h" -#include "src/widgets/lv_switch.h" +#include "src/widgets/animimage/lv_animimage.h" +#include "src/widgets/arc/lv_arc.h" +#include "src/widgets/bar/lv_bar.h" +#include "src/widgets/button/lv_button.h" +#include "src/widgets/buttonmatrix/lv_buttonmatrix.h" +#include "src/widgets/calendar/lv_calendar.h" +#include "src/widgets/canvas/lv_canvas.h" +#include "src/widgets/chart/lv_chart.h" +#include "src/widgets/checkbox/lv_checkbox.h" +#include "src/widgets/dropdown/lv_dropdown.h" +#include "src/widgets/image/lv_image.h" +#include "src/widgets/imagebutton/lv_imagebutton.h" +#include "src/widgets/keyboard/lv_keyboard.h" +#include "src/widgets/label/lv_label.h" +#include "src/widgets/led/lv_led.h" +#include "src/widgets/line/lv_line.h" +#include "src/widgets/list/lv_list.h" +#include "src/widgets/menu/lv_menu.h" +#include "src/widgets/msgbox/lv_msgbox.h" +#include "src/widgets/roller/lv_roller.h" +#include "src/widgets/scale/lv_scale.h" +#include "src/widgets/slider/lv_slider.h" +#include "src/widgets/span/lv_span.h" +#include "src/widgets/spinbox/lv_spinbox.h" +#include "src/widgets/spinner/lv_spinner.h" +#include "src/widgets/switch/lv_switch.h" +#include "src/widgets/table/lv_table.h" +#include "src/widgets/tabview/lv_tabview.h" +#include "src/widgets/textarea/lv_textarea.h" +#include "src/widgets/tileview/lv_tileview.h" +#include "src/widgets/win/lv_win.h" + +#include "src/others/snapshot/lv_snapshot.h" +#include "src/others/sysmon/lv_sysmon.h" +#include "src/others/monkey/lv_monkey.h" +#include "src/others/gridnav/lv_gridnav.h" +#include "src/others/fragment/lv_fragment.h" +#include "src/others/imgfont/lv_imgfont.h" +#include "src/others/observer/lv_observer.h" +#include "src/others/ime/lv_ime_pinyin.h" +#include "src/others/file_explorer/lv_file_explorer.h" + +#include "src/libs/barcode/lv_barcode.h" +#include "src/libs/bin_decoder/lv_bin_decoder.h" +#include "src/libs/bmp/lv_bmp.h" +#include "src/libs/rle/lv_rle.h" +#include "src/libs/fsdrv/lv_fsdrv.h" +#include "src/libs/lodepng/lv_lodepng.h" +#include "src/libs/libpng/lv_libpng.h" +#include "src/libs/gif/lv_gif.h" +#include "src/libs/qrcode/lv_qrcode.h" +#include "src/libs/tjpgd/lv_tjpgd.h" +#include "src/libs/libjpeg_turbo/lv_libjpeg_turbo.h" +#include "src/libs/freetype/lv_freetype.h" +#include "src/libs/rlottie/lv_rlottie.h" +#include "src/libs/ffmpeg/lv_ffmpeg.h" +#include "src/libs/tiny_ttf/lv_tiny_ttf.h" + +#include "src/layouts/lv_layout.h" #include "src/draw/lv_draw.h" +#include "src/draw/lv_draw_vector.h" + +#include "src/themes/lv_theme.h" + +#include "src/drivers/lv_drivers.h" #include "src/lv_api_map.h" -/*----------------- - * EXTRAS - *----------------*/ -#include "src/extra/lv_extra.h" - +#include "src/core/lv_global.h" /********************* * DEFINES *********************/ @@ -126,7 +176,7 @@ static inline int lv_version_patch(void) return LVGL_VERSION_PATCH; } -static inline const char *lv_version_info(void) +static inline const char * lv_version_info(void) { return LVGL_VERSION_INFO; } diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_core.mk b/lib/libesp32_lvgl/lvgl/src/core/lv_core.mk deleted file mode 100644 index 677a9f6b4..000000000 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_core.mk +++ /dev/null @@ -1,20 +0,0 @@ -CSRCS += lv_disp.c -CSRCS += lv_group.c -CSRCS += lv_indev.c -CSRCS += lv_indev_scroll.c -CSRCS += lv_obj.c -CSRCS += lv_obj_class.c -CSRCS += lv_obj_draw.c -CSRCS += lv_obj_pos.c -CSRCS += lv_obj_scroll.c -CSRCS += lv_obj_style.c -CSRCS += lv_obj_style_gen.c -CSRCS += lv_obj_tree.c -CSRCS += lv_event.c -CSRCS += lv_refr.c -CSRCS += lv_theme.c - -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core" diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_disp.c b/lib/libesp32_lvgl/lvgl/src/core/lv_disp.c deleted file mode 100644 index cacade51d..000000000 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_disp.c +++ /dev/null @@ -1,539 +0,0 @@ -/** - * @file lv_disp.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_disp.h" -#include "../misc/lv_math.h" -#include "../core/lv_refr.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void scr_load_internal(lv_obj_t * scr); -static void scr_load_anim_start(lv_anim_t * a); -static void opa_scale_anim(void * obj, int32_t v); -static void set_x_anim(void * obj, int32_t v); -static void set_y_anim(void * obj, int32_t v); -static void scr_anim_ready(lv_anim_t * a); -static bool is_out_anim(lv_scr_load_anim_t a); - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Return with a pointer to the active screen - * @param disp pointer to display which active screen should be get. (NULL to use the default - * screen) - * @return pointer to the active screen object (loaded by 'lv_scr_load()') - */ -lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp) -{ - if(!disp) disp = lv_disp_get_default(); - if(!disp) { - LV_LOG_WARN("no display registered to get its active screen"); - return NULL; - } - - return disp->act_scr; -} - -/** - * Return with a pointer to the previous screen. Only used during screen transitions. - * @param disp pointer to display which previous screen should be get. (NULL to use the default - * screen) - * @return pointer to the previous screen object or NULL if not used now - */ -lv_obj_t * lv_disp_get_scr_prev(lv_disp_t * disp) -{ - if(!disp) disp = lv_disp_get_default(); - if(!disp) { - LV_LOG_WARN("no display registered to get its previous screen"); - return NULL; - } - - return disp->prev_scr; -} - -/** - * Make a screen active - * @param scr pointer to a screen - */ -void lv_disp_load_scr(lv_obj_t * scr) -{ - lv_scr_load_anim(scr, LV_SCR_LOAD_ANIM_NONE, 0, 0, false); -} - -/** - * Return with the top layer. (Same on every screen and it is above the normal screen layer) - * @param disp pointer to display which top layer should be get. (NULL to use the default screen) - * @return pointer to the top layer object (transparent screen sized lv_obj) - */ -lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp) -{ - if(!disp) disp = lv_disp_get_default(); - if(!disp) { - LV_LOG_WARN("lv_layer_top: no display registered to get its top layer"); - return NULL; - } - - return disp->top_layer; -} - -/** - * Return with the sys. layer. (Same on every screen and it is above the normal screen and the top - * layer) - * @param disp pointer to display which sys. layer should be retrieved. (NULL to use the default screen) - * @return pointer to the sys layer object (transparent screen sized lv_obj) - */ -lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp) -{ - if(!disp) disp = lv_disp_get_default(); - if(!disp) { - LV_LOG_WARN("lv_layer_sys: no display registered to get its sys. layer"); - return NULL; - } - - return disp->sys_layer; -} - -/** - * Set the theme of a display - * @param disp pointer to a display - */ -void lv_disp_set_theme(lv_disp_t * disp, lv_theme_t * th) -{ - if(!disp) disp = lv_disp_get_default(); - if(!disp) { - LV_LOG_WARN("no display registered"); - return; - } - - disp->theme = th; - - if(disp->screen_cnt == 3 && - lv_obj_get_child_cnt(disp->screens[0]) == 0 && - lv_obj_get_child_cnt(disp->screens[1]) == 0 && - lv_obj_get_child_cnt(disp->screens[2]) == 0) { - lv_theme_apply(disp->screens[0]); - } -} -/** - * Get the theme of a display - * @param disp pointer to a display - * @return the display's theme (can be NULL) - */ -lv_theme_t * lv_disp_get_theme(lv_disp_t * disp) -{ - if(disp == NULL) disp = lv_disp_get_default(); - return disp->theme; -} - -/** - * Set the background color of a display - * @param disp pointer to a display - * @param color color of the background - */ -void lv_disp_set_bg_color(lv_disp_t * disp, lv_color_t color) -{ - if(!disp) disp = lv_disp_get_default(); - if(!disp) { - LV_LOG_WARN("no display registered"); - return; - } - - disp->bg_color = color; - - lv_area_t a; - lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1); - _lv_inv_area(disp, &a); - -} - -/** - * Set the background image of a display - * @param disp pointer to a display - * @param img_src path to file or pointer to an `lv_img_dsc_t` variable - */ -void lv_disp_set_bg_image(lv_disp_t * disp, const void * img_src) -{ - if(!disp) disp = lv_disp_get_default(); - if(!disp) { - LV_LOG_WARN("no display registered"); - return; - } - - disp->bg_img = img_src; - - lv_area_t a; - lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1); - _lv_inv_area(disp, &a); -} - -/** - * Set opacity of the background - * @param disp pointer to a display - * @param opa opacity (0..255) - */ -void lv_disp_set_bg_opa(lv_disp_t * disp, lv_opa_t opa) -{ - if(!disp) disp = lv_disp_get_default(); - if(!disp) { - LV_LOG_WARN("no display registered"); - return; - } - - disp->bg_opa = opa; - - lv_area_t a; - lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1); - _lv_inv_area(disp, &a); -} - -/** - * Switch screen with animation - * @param scr pointer to the new screen to load - * @param anim_type type of the animation from `lv_scr_load_anim_t`, e.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT` - * @param time time of the animation - * @param delay delay before the transition - * @param auto_del true: automatically delete the old screen - */ -void lv_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del) -{ - - lv_disp_t * d = lv_obj_get_disp(new_scr); - lv_obj_t * act_scr = lv_scr_act(); - - if(act_scr == new_scr || d->scr_to_load == new_scr) { - return; - } - - /*If an other screen load animation is in progress - *make target screen loaded immediately. */ - if(d->scr_to_load) { - scr_load_internal(d->scr_to_load); - lv_anim_del(d->scr_to_load, NULL); - lv_obj_set_pos(d->scr_to_load, 0, 0); - lv_obj_remove_local_style_prop(d->scr_to_load, LV_STYLE_OPA, 0); - - if(d->del_prev) { - lv_obj_del(act_scr); - } - act_scr = d->scr_to_load; - } - - d->scr_to_load = new_scr; - - if(d->prev_scr && d->del_prev) { - lv_obj_del(d->prev_scr); - d->prev_scr = NULL; - } - - d->draw_prev_over_act = is_out_anim(anim_type); - d->del_prev = auto_del; - - /*Be sure there is no other animation on the screens*/ - lv_anim_del(new_scr, NULL); - lv_anim_del(lv_scr_act(), NULL); - - /*Be sure both screens are in a normal position*/ - lv_obj_set_pos(new_scr, 0, 0); - lv_obj_set_pos(lv_scr_act(), 0, 0); - lv_obj_remove_local_style_prop(new_scr, LV_STYLE_OPA, 0); - lv_obj_remove_local_style_prop(lv_scr_act(), LV_STYLE_OPA, 0); - - /*Shortcut for immediate load*/ - if(time == 0 && delay == 0) { - scr_load_internal(new_scr); - if(auto_del) lv_obj_del(act_scr); - return; - } - - lv_anim_t a_new; - lv_anim_init(&a_new); - lv_anim_set_var(&a_new, new_scr); - lv_anim_set_start_cb(&a_new, scr_load_anim_start); - lv_anim_set_ready_cb(&a_new, scr_anim_ready); - lv_anim_set_time(&a_new, time); - lv_anim_set_delay(&a_new, delay); - - lv_anim_t a_old; - lv_anim_init(&a_old); - lv_anim_set_var(&a_old, d->act_scr); - lv_anim_set_time(&a_old, time); - lv_anim_set_delay(&a_old, delay); - - switch(anim_type) { - case LV_SCR_LOAD_ANIM_NONE: - /*Create a dummy animation to apply the delay*/ - lv_anim_set_exec_cb(&a_new, set_x_anim); - lv_anim_set_values(&a_new, 0, 0); - break; - case LV_SCR_LOAD_ANIM_OVER_LEFT: - lv_anim_set_exec_cb(&a_new, set_x_anim); - lv_anim_set_values(&a_new, lv_disp_get_hor_res(d), 0); - break; - case LV_SCR_LOAD_ANIM_OVER_RIGHT: - lv_anim_set_exec_cb(&a_new, set_x_anim); - lv_anim_set_values(&a_new, -lv_disp_get_hor_res(d), 0); - break; - case LV_SCR_LOAD_ANIM_OVER_TOP: - lv_anim_set_exec_cb(&a_new, set_y_anim); - lv_anim_set_values(&a_new, lv_disp_get_ver_res(d), 0); - break; - case LV_SCR_LOAD_ANIM_OVER_BOTTOM: - lv_anim_set_exec_cb(&a_new, set_y_anim); - lv_anim_set_values(&a_new, -lv_disp_get_ver_res(d), 0); - break; - case LV_SCR_LOAD_ANIM_MOVE_LEFT: - lv_anim_set_exec_cb(&a_new, set_x_anim); - lv_anim_set_values(&a_new, lv_disp_get_hor_res(d), 0); - - lv_anim_set_exec_cb(&a_old, set_x_anim); - lv_anim_set_values(&a_old, 0, -lv_disp_get_hor_res(d)); - break; - case LV_SCR_LOAD_ANIM_MOVE_RIGHT: - lv_anim_set_exec_cb(&a_new, set_x_anim); - lv_anim_set_values(&a_new, -lv_disp_get_hor_res(d), 0); - - lv_anim_set_exec_cb(&a_old, set_x_anim); - lv_anim_set_values(&a_old, 0, lv_disp_get_hor_res(d)); - break; - case LV_SCR_LOAD_ANIM_MOVE_TOP: - lv_anim_set_exec_cb(&a_new, set_y_anim); - lv_anim_set_values(&a_new, lv_disp_get_ver_res(d), 0); - - lv_anim_set_exec_cb(&a_old, set_y_anim); - lv_anim_set_values(&a_old, 0, -lv_disp_get_ver_res(d)); - break; - case LV_SCR_LOAD_ANIM_MOVE_BOTTOM: - lv_anim_set_exec_cb(&a_new, set_y_anim); - lv_anim_set_values(&a_new, -lv_disp_get_ver_res(d), 0); - - lv_anim_set_exec_cb(&a_old, set_y_anim); - lv_anim_set_values(&a_old, 0, lv_disp_get_ver_res(d)); - break; - case LV_SCR_LOAD_ANIM_FADE_IN: - lv_anim_set_exec_cb(&a_new, opa_scale_anim); - lv_anim_set_values(&a_new, LV_OPA_TRANSP, LV_OPA_COVER); - break; - case LV_SCR_LOAD_ANIM_FADE_OUT: - lv_anim_set_exec_cb(&a_old, opa_scale_anim); - lv_anim_set_values(&a_old, LV_OPA_COVER, LV_OPA_TRANSP); - break; - case LV_SCR_LOAD_ANIM_OUT_LEFT: - lv_anim_set_exec_cb(&a_old, set_x_anim); - lv_anim_set_values(&a_old, 0, -lv_disp_get_hor_res(d)); - break; - case LV_SCR_LOAD_ANIM_OUT_RIGHT: - lv_anim_set_exec_cb(&a_old, set_x_anim); - lv_anim_set_values(&a_old, 0, lv_disp_get_hor_res(d)); - break; - case LV_SCR_LOAD_ANIM_OUT_TOP: - lv_anim_set_exec_cb(&a_old, set_y_anim); - lv_anim_set_values(&a_old, 0, -lv_disp_get_ver_res(d)); - break; - case LV_SCR_LOAD_ANIM_OUT_BOTTOM: - lv_anim_set_exec_cb(&a_old, set_y_anim); - lv_anim_set_values(&a_old, 0, lv_disp_get_ver_res(d)); - break; - } - - lv_event_send(act_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL); - - lv_anim_start(&a_new); - lv_anim_start(&a_old); -} - -/** - * Get elapsed time since last user activity on a display (e.g. click) - * @param disp pointer to a display (NULL to get the overall smallest inactivity) - * @return elapsed ticks (milliseconds) since the last activity - */ -uint32_t lv_disp_get_inactive_time(const lv_disp_t * disp) -{ - if(disp) return lv_tick_elaps(disp->last_activity_time); - - lv_disp_t * d; - uint32_t t = UINT32_MAX; - d = lv_disp_get_next(NULL); - while(d) { - uint32_t elaps = lv_tick_elaps(d->last_activity_time); - t = LV_MIN(t, elaps); - d = lv_disp_get_next(d); - } - - return t; -} - -/** - * Manually trigger an activity on a display - * @param disp pointer to a display (NULL to use the default display) - */ -void lv_disp_trig_activity(lv_disp_t * disp) -{ - if(!disp) disp = lv_disp_get_default(); - if(!disp) { - LV_LOG_WARN("lv_disp_trig_activity: no display registered"); - return; - } - - disp->last_activity_time = lv_tick_get(); -} - -/** - * Clean any CPU cache that is related to the display. - * @param disp pointer to a display (NULL to use the default display) - */ -void lv_disp_clean_dcache(lv_disp_t * disp) -{ - if(!disp) disp = lv_disp_get_default(); - if(!disp) { - LV_LOG_WARN("lv_disp_clean_dcache: no display registered"); - return; - } - - if(disp->driver->clean_dcache_cb) - disp->driver->clean_dcache_cb(disp->driver); -} - -/** - * Temporarily enable and disable the invalidation of the display. - * @param disp pointer to a display (NULL to use the default display) - * @param en true: enable invalidation; false: invalidation - */ -void lv_disp_enable_invalidation(lv_disp_t * disp, bool en) -{ - if(!disp) disp = lv_disp_get_default(); - if(!disp) { - LV_LOG_WARN("no display registered"); - return; - } - - disp->inv_en_cnt += en ? 1 : -1; -} - -/** - * Get display invalidation is enabled. - * @param disp pointer to a display (NULL to use the default display) - * @return return true if invalidation is enabled - */ -bool lv_disp_is_invalidation_enabled(lv_disp_t * disp) -{ - if(!disp) disp = lv_disp_get_default(); - if(!disp) { - LV_LOG_WARN("no display registered"); - return false; - } - - return (disp->inv_en_cnt > 0); -} - -/** - * Get a pointer to the screen refresher timer to - * modify its parameters with `lv_timer_...` functions. - * @param disp pointer to a display - * @return pointer to the display refresher timer. (NULL on error) - */ -lv_timer_t * _lv_disp_get_refr_timer(lv_disp_t * disp) -{ - if(!disp) disp = lv_disp_get_default(); - if(!disp) { - LV_LOG_WARN("lv_disp_get_refr_timer: no display registered"); - return NULL; - } - - return disp->refr_timer; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void scr_load_internal(lv_obj_t * scr) -{ - lv_disp_t * d = lv_obj_get_disp(scr); - if(!d) return; /*Shouldn't happen, just to be sure*/ - - lv_obj_t * old_scr = d->act_scr; - - if(d->act_scr) lv_event_send(old_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL); - if(d->act_scr) lv_event_send(scr, LV_EVENT_SCREEN_LOAD_START, NULL); - - d->act_scr = scr; - d->scr_to_load = NULL; - - if(d->act_scr) lv_event_send(scr, LV_EVENT_SCREEN_LOADED, NULL); - if(d->act_scr) lv_event_send(old_scr, LV_EVENT_SCREEN_UNLOADED, NULL); - - lv_obj_invalidate(scr); -} - -static void scr_load_anim_start(lv_anim_t * a) -{ - lv_disp_t * d = lv_obj_get_disp(a->var); - - d->prev_scr = lv_scr_act(); - d->act_scr = a->var; - - lv_event_send(d->act_scr, LV_EVENT_SCREEN_LOAD_START, NULL); -} - -static void opa_scale_anim(void * obj, int32_t v) -{ - lv_obj_set_style_opa(obj, v, 0); -} - -static void set_x_anim(void * obj, int32_t v) -{ - lv_obj_set_x(obj, v); -} - -static void set_y_anim(void * obj, int32_t v) -{ - lv_obj_set_y(obj, v); -} - -static void scr_anim_ready(lv_anim_t * a) -{ - lv_disp_t * d = lv_obj_get_disp(a->var); - - lv_event_send(d->act_scr, LV_EVENT_SCREEN_LOADED, NULL); - lv_event_send(d->prev_scr, LV_EVENT_SCREEN_UNLOADED, NULL); - - if(d->prev_scr && d->del_prev) lv_obj_del(d->prev_scr); - d->prev_scr = NULL; - d->draw_prev_over_act = false; - d->scr_to_load = NULL; - lv_obj_remove_local_style_prop(a->var, LV_STYLE_OPA, 0); - lv_obj_invalidate(d->act_scr); -} - -static bool is_out_anim(lv_scr_load_anim_t anim_type) -{ - return anim_type == LV_SCR_LOAD_ANIM_FADE_OUT || - anim_type == LV_SCR_LOAD_ANIM_OUT_LEFT || - anim_type == LV_SCR_LOAD_ANIM_OUT_RIGHT || - anim_type == LV_SCR_LOAD_ANIM_OUT_TOP || - anim_type == LV_SCR_LOAD_ANIM_OUT_BOTTOM; -} diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_disp.h b/lib/libesp32_lvgl/lvgl/src/core/lv_disp.h deleted file mode 100644 index 7854cb7f2..000000000 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_disp.h +++ /dev/null @@ -1,264 +0,0 @@ -/** - * @file lv_disp.h - * - */ - -#ifndef LV_DISP_H -#define LV_DISP_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../hal/lv_hal.h" -#include "lv_obj.h" -#include "lv_theme.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef enum { - LV_SCR_LOAD_ANIM_NONE, - LV_SCR_LOAD_ANIM_OVER_LEFT, - LV_SCR_LOAD_ANIM_OVER_RIGHT, - LV_SCR_LOAD_ANIM_OVER_TOP, - LV_SCR_LOAD_ANIM_OVER_BOTTOM, - LV_SCR_LOAD_ANIM_MOVE_LEFT, - LV_SCR_LOAD_ANIM_MOVE_RIGHT, - LV_SCR_LOAD_ANIM_MOVE_TOP, - LV_SCR_LOAD_ANIM_MOVE_BOTTOM, - LV_SCR_LOAD_ANIM_FADE_IN, - LV_SCR_LOAD_ANIM_FADE_ON = LV_SCR_LOAD_ANIM_FADE_IN, /*For backward compatibility*/ - LV_SCR_LOAD_ANIM_FADE_OUT, - LV_SCR_LOAD_ANIM_OUT_LEFT, - LV_SCR_LOAD_ANIM_OUT_RIGHT, - LV_SCR_LOAD_ANIM_OUT_TOP, - LV_SCR_LOAD_ANIM_OUT_BOTTOM, -} lv_scr_load_anim_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Return with a pointer to the active screen - * @param disp pointer to display which active screen should be get. (NULL to use the default - * screen) - * @return pointer to the active screen object (loaded by 'lv_scr_load()') - */ -lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp); - -/** - * Return with a pointer to the previous screen. Only used during screen transitions. - * @param disp pointer to display which previous screen should be get. (NULL to use the default - * screen) - * @return pointer to the previous screen object or NULL if not used now - */ -lv_obj_t * lv_disp_get_scr_prev(lv_disp_t * disp); - -/** - * Make a screen active - * @param scr pointer to a screen - */ -void lv_disp_load_scr(lv_obj_t * scr); - -/** - * Return with the top layer. (Same on every screen and it is above the normal screen layer) - * @param disp pointer to display which top layer should be get. (NULL to use the default screen) - * @return pointer to the top layer object (transparent screen sized lv_obj) - */ -lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp); - -/** - * Return with the sys. layer. (Same on every screen and it is above the normal screen and the top - * layer) - * @param disp pointer to display which sys. layer should be retrieved. (NULL to use the default screen) - * @return pointer to the sys layer object (transparent screen sized lv_obj) - */ -lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp); - -/** - * Set the theme of a display - * @param disp pointer to a display - */ -void lv_disp_set_theme(lv_disp_t * disp, lv_theme_t * th); - -/** - * Get the theme of a display - * @param disp pointer to a display - * @return the display's theme (can be NULL) - */ -lv_theme_t * lv_disp_get_theme(lv_disp_t * disp); - -/** - * Set the background color of a display - * @param disp pointer to a display - * @param color color of the background - */ -void lv_disp_set_bg_color(lv_disp_t * disp, lv_color_t color); - -/** - * Set the background image of a display - * @param disp pointer to a display - * @param img_src path to file or pointer to an `lv_img_dsc_t` variable - */ -void lv_disp_set_bg_image(lv_disp_t * disp, const void * img_src); - -/** - * Set opacity of the background - * @param disp pointer to a display - * @param opa opacity (0..255) - */ -void lv_disp_set_bg_opa(lv_disp_t * disp, lv_opa_t opa); - -/** - * Switch screen with animation - * @param scr pointer to the new screen to load - * @param anim_type type of the animation from `lv_scr_load_anim_t`, e.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT` - * @param time time of the animation - * @param delay delay before the transition - * @param auto_del true: automatically delete the old screen - */ -void lv_scr_load_anim(lv_obj_t * scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del); - -/** - * Get elapsed time since last user activity on a display (e.g. click) - * @param disp pointer to a display (NULL to get the overall smallest inactivity) - * @return elapsed ticks (milliseconds) since the last activity - */ -uint32_t lv_disp_get_inactive_time(const lv_disp_t * disp); - -/** - * Manually trigger an activity on a display - * @param disp pointer to a display (NULL to use the default display) - */ -void lv_disp_trig_activity(lv_disp_t * disp); - -/** - * Clean any CPU cache that is related to the display. - * @param disp pointer to a display (NULL to use the default display) - */ -void lv_disp_clean_dcache(lv_disp_t * disp); - -/** - * Temporarily enable and disable the invalidation of the display. - * @param disp pointer to a display (NULL to use the default display) - * @param en true: enable invalidation; false: invalidation - */ -void lv_disp_enable_invalidation(lv_disp_t * disp, bool en); - -/** - * Get display invalidation is enabled. - * @param disp pointer to a display (NULL to use the default display) - * @return return true if invalidation is enabled - */ -bool lv_disp_is_invalidation_enabled(lv_disp_t * disp); - -/** - * Get a pointer to the screen refresher timer to - * modify its parameters with `lv_timer_...` functions. - * @param disp pointer to a display - * @return pointer to the display refresher timer. (NULL on error) - */ -lv_timer_t * _lv_disp_get_refr_timer(lv_disp_t * disp); - -/*------------------------------------------------ - * To improve backward compatibility - * Recommended only if you have one display - *------------------------------------------------*/ - -/** - * Get the active screen of the default display - * @return pointer to the active screen - */ -static inline lv_obj_t * lv_scr_act(void) -{ - return lv_disp_get_scr_act(lv_disp_get_default()); -} - -/** - * Get the top layer of the default display - * @return pointer to the top layer - */ -static inline lv_obj_t * lv_layer_top(void) -{ - return lv_disp_get_layer_top(lv_disp_get_default()); -} - -/** - * Get the active screen of the default display - * @return pointer to the sys layer - */ -static inline lv_obj_t * lv_layer_sys(void) -{ - return lv_disp_get_layer_sys(lv_disp_get_default()); -} - -static inline void lv_scr_load(lv_obj_t * scr) -{ - lv_disp_load_scr(scr); -} - -/********************** - * MACROS - **********************/ - -/*------------------------------------------------ - * To improve backward compatibility - * Recommended only if you have one display - *------------------------------------------------*/ - -#ifndef LV_HOR_RES -/** - * The horizontal resolution of the currently active display. - */ -#define LV_HOR_RES lv_disp_get_hor_res(lv_disp_get_default()) -#endif - -#ifndef LV_VER_RES -/** - * The vertical resolution of the currently active display. - */ -#define LV_VER_RES lv_disp_get_ver_res(lv_disp_get_default()) -#endif - -/** - * Scale the given number of pixels (a distance or size) relative to a 160 DPI display - * considering the DPI of the default display. - * It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the - * DPI of the display. - * @param n the number of pixels to scale - * @return `n x current_dpi/160` - */ -static inline lv_coord_t lv_dpx(lv_coord_t n) -{ - return LV_DPX(n); -} - -/** - * Scale the given number of pixels (a distance or size) relative to a 160 DPI display - * considering the DPI of the given display. - * It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the - * DPI of the display. - * @param obj a display whose dpi should be considered - * @param n the number of pixels to scale - * @return `n x current_dpi/160` - */ -static inline lv_coord_t lv_disp_dpx(const lv_disp_t * disp, lv_coord_t n) -{ - return _LV_DPX_CALC(lv_disp_get_dpi(disp), n); -} - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DISP_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_event.c b/lib/libesp32_lvgl/lvgl/src/core/lv_event.c deleted file mode 100644 index f53ceac1d..000000000 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_event.c +++ /dev/null @@ -1,527 +0,0 @@ -/** - * @file lv_event.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_obj.h" -#include "lv_indev.h" - -/********************* - * DEFINES - *********************/ -#define MY_CLASS &lv_obj_class - -/********************** - * TYPEDEFS - **********************/ -typedef struct _lv_event_dsc_t { - lv_event_cb_t cb; - void * user_data; - lv_event_code_t filter : 8; -} lv_event_dsc_t; - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id); -static lv_res_t event_send_core(lv_event_t * e); -static bool event_is_bubbled(lv_event_t * e); - - -/********************** - * STATIC VARIABLES - **********************/ -static lv_event_t * event_head; - -/********************** - * MACROS - **********************/ -#if LV_LOG_TRACE_EVENT - #define EVENT_TRACE(...) LV_LOG_TRACE(__VA_ARGS__) -#else - #define EVENT_TRACE(...) -#endif - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_res_t lv_event_send(lv_obj_t * obj, lv_event_code_t event_code, void * param) -{ - if(obj == NULL) return LV_RES_OK; - - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_event_t e; - e.target = obj; - e.current_target = obj; - e.code = event_code; - e.user_data = NULL; - e.param = param; - e.deleted = 0; - e.stop_bubbling = 0; - e.stop_processing = 0; - - /*Build a simple linked list from the objects used in the events - *It's important to know if this object was deleted by a nested event - *called from this `event_cb`.*/ - e.prev = event_head; - event_head = &e; - - /*Send the event*/ - lv_res_t res = event_send_core(&e); - - /*Remove this element from the list*/ - event_head = e.prev; - - return res; -} - - -lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e) -{ - const lv_obj_class_t * base; - if(class_p == NULL) base = e->current_target->class_p; - else base = class_p->base_class; - - /*Find a base in which call the ancestor's event handler_cb if set*/ - while(base && base->event_cb == NULL) base = base->base_class; - - if(base == NULL) return LV_RES_OK; - if(base->event_cb == NULL) return LV_RES_OK; - - /*Call the actual event callback*/ - e->user_data = NULL; - base->event_cb(base, e); - - lv_res_t res = LV_RES_OK; - /*Stop if the object is deleted*/ - if(e->deleted) res = LV_RES_INV; - - return res; -} - - -lv_obj_t * lv_event_get_target(lv_event_t * e) -{ - return e->target; -} - -lv_obj_t * lv_event_get_current_target(lv_event_t * e) -{ - return e->current_target; -} - -lv_event_code_t lv_event_get_code(lv_event_t * e) -{ - return e->code & ~LV_EVENT_PREPROCESS; -} - -void * lv_event_get_param(lv_event_t * e) -{ - return e->param; -} - -void * lv_event_get_user_data(lv_event_t * e) -{ - return e->user_data; -} - -void lv_event_stop_bubbling(lv_event_t * e) -{ - e->stop_bubbling = 1; -} - -void lv_event_stop_processing(lv_event_t * e) -{ - e->stop_processing = 1; -} - - -uint32_t lv_event_register_id(void) -{ - static uint32_t last_id = _LV_EVENT_LAST; - last_id ++; - return last_id; -} - -void _lv_event_mark_deleted(lv_obj_t * obj) -{ - lv_event_t * e = event_head; - - while(e) { - if(e->current_target == obj || e->target == obj) e->deleted = 1; - e = e->prev; - } -} - - -struct _lv_event_dsc_t * lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, - void * user_data) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_obj_allocate_spec_attr(obj); - - obj->spec_attr->event_dsc_cnt++; - obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, - obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); - LV_ASSERT_MALLOC(obj->spec_attr->event_dsc); - - obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].cb = event_cb; - obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].filter = filter; - obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].user_data = user_data; - - return &obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1]; -} - -bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - if(obj->spec_attr == NULL) return false; - - int32_t i = 0; - for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) { - if(event_cb == NULL || obj->spec_attr->event_dsc[i].cb == event_cb) { - /*Shift the remaining event handlers forward*/ - for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) { - obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1]; - } - obj->spec_attr->event_dsc_cnt--; - obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, - obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); - LV_ASSERT_MALLOC(obj->spec_attr->event_dsc); - return true; - } - } - - /*No event handler found*/ - return false; -} - -bool lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj, lv_event_cb_t event_cb, const void * user_data) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - if(obj->spec_attr == NULL) return false; - - int32_t i = 0; - for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) { - if((event_cb == NULL || obj->spec_attr->event_dsc[i].cb == event_cb) && - obj->spec_attr->event_dsc[i].user_data == user_data) { - /*Shift the remaining event handlers forward*/ - for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) { - obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1]; - } - obj->spec_attr->event_dsc_cnt--; - obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, - obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); - LV_ASSERT_MALLOC(obj->spec_attr->event_dsc); - return true; - } - } - - /*No event handler found*/ - return false; -} - - -bool lv_obj_remove_event_dsc(lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - if(obj->spec_attr == NULL) return false; - - int32_t i = 0; - for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) { - if(&obj->spec_attr->event_dsc[i] == event_dsc) { - /*Shift the remaining event handlers forward*/ - for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) { - obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1]; - } - obj->spec_attr->event_dsc_cnt--; - obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc, - obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t)); - LV_ASSERT_MALLOC(obj->spec_attr->event_dsc); - return true; - } - } - - /*No event handler found*/ - return false; -} - -void * lv_obj_get_event_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - if(obj->spec_attr == NULL) return NULL; - - int32_t i = 0; - for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) { - if(event_cb == obj->spec_attr->event_dsc[i].cb) return obj->spec_attr->event_dsc[i].user_data; - } - return NULL; -} - -lv_indev_t * lv_event_get_indev(lv_event_t * e) -{ - - if(e->code == LV_EVENT_PRESSED || - e->code == LV_EVENT_PRESSING || - e->code == LV_EVENT_PRESS_LOST || - e->code == LV_EVENT_SHORT_CLICKED || - e->code == LV_EVENT_LONG_PRESSED || - e->code == LV_EVENT_LONG_PRESSED_REPEAT || - e->code == LV_EVENT_CLICKED || - e->code == LV_EVENT_RELEASED || - e->code == LV_EVENT_SCROLL_BEGIN || - e->code == LV_EVENT_SCROLL_END || - e->code == LV_EVENT_SCROLL || - e->code == LV_EVENT_GESTURE || - e->code == LV_EVENT_KEY || - e->code == LV_EVENT_FOCUSED || - e->code == LV_EVENT_DEFOCUSED || - e->code == LV_EVENT_LEAVE) { - return lv_event_get_param(e); - } - else { - LV_LOG_WARN("Not interpreted with this event code"); - return NULL; - } -} - -lv_obj_draw_part_dsc_t * lv_event_get_draw_part_dsc(lv_event_t * e) -{ - if(e->code == LV_EVENT_DRAW_PART_BEGIN || - e->code == LV_EVENT_DRAW_PART_END) { - return lv_event_get_param(e); - } - else { - LV_LOG_WARN("Not interpreted with this event code"); - return NULL; - } -} - -lv_draw_ctx_t * lv_event_get_draw_ctx(lv_event_t * e) -{ - if(e->code == LV_EVENT_DRAW_MAIN || - e->code == LV_EVENT_DRAW_MAIN_BEGIN || - e->code == LV_EVENT_DRAW_MAIN_END || - e->code == LV_EVENT_DRAW_POST || - e->code == LV_EVENT_DRAW_POST_BEGIN || - e->code == LV_EVENT_DRAW_POST_END) { - return lv_event_get_param(e); - } - else { - LV_LOG_WARN("Not interpreted with this event code"); - return NULL; - } -} - -const lv_area_t * lv_event_get_old_size(lv_event_t * e) -{ - if(e->code == LV_EVENT_SIZE_CHANGED) { - return lv_event_get_param(e); - } - else { - LV_LOG_WARN("Not interpreted with this event code"); - return NULL; - } -} - -uint32_t lv_event_get_key(lv_event_t * e) -{ - if(e->code == LV_EVENT_KEY) { - uint32_t * k = lv_event_get_param(e); - if(k) return *k; - else return 0; - } - else { - LV_LOG_WARN("Not interpreted with this event code"); - return 0; - } -} - -lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e) -{ - if(e->code == LV_EVENT_SCROLL_BEGIN) { - return lv_event_get_param(e); - } - else { - LV_LOG_WARN("Not interpreted with this event code"); - return 0; - } -} - -void lv_event_set_ext_draw_size(lv_event_t * e, lv_coord_t size) -{ - if(e->code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - lv_coord_t * cur_size = lv_event_get_param(e); - *cur_size = LV_MAX(*cur_size, size); - } - else { - LV_LOG_WARN("Not interpreted with this event code"); - } -} - -lv_point_t * lv_event_get_self_size_info(lv_event_t * e) -{ - if(e->code == LV_EVENT_GET_SELF_SIZE) { - return lv_event_get_param(e); - } - else { - LV_LOG_WARN("Not interpreted with this event code"); - return 0; - } -} - -lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e) -{ - if(e->code == LV_EVENT_HIT_TEST) { - return lv_event_get_param(e); - } - else { - LV_LOG_WARN("Not interpreted with this event code"); - return 0; - } -} - -const lv_area_t * lv_event_get_cover_area(lv_event_t * e) -{ - if(e->code == LV_EVENT_COVER_CHECK) { - lv_cover_check_info_t * p = lv_event_get_param(e); - return p->area; - } - else { - LV_LOG_WARN("Not interpreted with this event code"); - return NULL; - } -} - -void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res) -{ - if(e->code == LV_EVENT_COVER_CHECK) { - lv_cover_check_info_t * p = lv_event_get_param(e); - if(res > p->res) p->res = res; /*Save only "stronger" results*/ - } - else { - LV_LOG_WARN("Not interpreted with this event code"); - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - if(!obj->spec_attr) return NULL; - if(id >= obj->spec_attr->event_dsc_cnt) return NULL; - - return &obj->spec_attr->event_dsc[id]; -} - -static lv_res_t event_send_core(lv_event_t * e) -{ - EVENT_TRACE("Sending event %d to %p with %p param", e->code, (void *)e->current_target, e->param); - - /*Call the input device's feedback callback if set*/ - lv_indev_t * indev_act = lv_indev_get_act(); - if(indev_act) { - if(indev_act->driver->feedback_cb) indev_act->driver->feedback_cb(indev_act->driver, e->code); - if(e->stop_processing) return LV_RES_OK; - if(e->deleted) return LV_RES_INV; - } - - lv_res_t res = LV_RES_OK; - lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(e->current_target, 0); - - uint32_t i = 0; - while(event_dsc && res == LV_RES_OK) { - if(event_dsc->cb && ((event_dsc->filter & LV_EVENT_PREPROCESS) == LV_EVENT_PREPROCESS) - && (event_dsc->filter == (LV_EVENT_ALL | LV_EVENT_PREPROCESS) || - (event_dsc->filter & ~LV_EVENT_PREPROCESS) == e->code)) { - e->user_data = event_dsc->user_data; - event_dsc->cb(e); - - if(e->stop_processing) return LV_RES_OK; - /*Stop if the object is deleted*/ - if(e->deleted) return LV_RES_INV; - } - - i++; - event_dsc = lv_obj_get_event_dsc(e->current_target, i); - } - - res = lv_obj_event_base(NULL, e); - - event_dsc = res == LV_RES_INV ? NULL : lv_obj_get_event_dsc(e->current_target, 0); - - i = 0; - while(event_dsc && res == LV_RES_OK) { - if(event_dsc->cb && ((event_dsc->filter & LV_EVENT_PREPROCESS) == 0) - && (event_dsc->filter == LV_EVENT_ALL || event_dsc->filter == e->code)) { - e->user_data = event_dsc->user_data; - event_dsc->cb(e); - - if(e->stop_processing) return LV_RES_OK; - /*Stop if the object is deleted*/ - if(e->deleted) return LV_RES_INV; - } - - i++; - event_dsc = lv_obj_get_event_dsc(e->current_target, i); - } - - if(res == LV_RES_OK && e->current_target->parent && event_is_bubbled(e)) { - e->current_target = e->current_target->parent; - res = event_send_core(e); - if(res != LV_RES_OK) return LV_RES_INV; - } - - return res; -} - -static bool event_is_bubbled(lv_event_t * e) -{ - if(e->stop_bubbling) return false; - - /*Event codes that always bubble*/ - switch(e->code) { - case LV_EVENT_CHILD_CREATED: - case LV_EVENT_CHILD_DELETED: - return true; - default: - break; - } - - /*Check other codes only if bubbling is enabled*/ - if(lv_obj_has_flag(e->current_target, LV_OBJ_FLAG_EVENT_BUBBLE) == false) return false; - - switch(e->code) { - case LV_EVENT_HIT_TEST: - case LV_EVENT_COVER_CHECK: - case LV_EVENT_REFR_EXT_DRAW_SIZE: - case LV_EVENT_DRAW_MAIN_BEGIN: - case LV_EVENT_DRAW_MAIN: - case LV_EVENT_DRAW_MAIN_END: - case LV_EVENT_DRAW_POST_BEGIN: - case LV_EVENT_DRAW_POST: - case LV_EVENT_DRAW_POST_END: - case LV_EVENT_DRAW_PART_BEGIN: - case LV_EVENT_DRAW_PART_END: - case LV_EVENT_REFRESH: - case LV_EVENT_DELETE: - case LV_EVENT_CHILD_CREATED: - case LV_EVENT_CHILD_DELETED: - case LV_EVENT_CHILD_CHANGED: - case LV_EVENT_SIZE_CHANGED: - case LV_EVENT_STYLE_CHANGED: - case LV_EVENT_GET_SELF_SIZE: - return false; - default: - return true; - } -} diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_event.h b/lib/libesp32_lvgl/lvgl/src/core/lv_event.h deleted file mode 100644 index d5a9eb6ba..000000000 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_event.h +++ /dev/null @@ -1,363 +0,0 @@ -/** - * @file lv_event.h - * - */ - -#ifndef LV_EVENT_H -#define LV_EVENT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -struct _lv_obj_t; -struct _lv_event_dsc_t; - -/** - * Type of event being sent to the object. - */ -typedef enum { - LV_EVENT_ALL = 0, - - /** Input device events*/ - LV_EVENT_PRESSED, /**< The object has been pressed*/ - LV_EVENT_PRESSING, /**< The object is being pressed (called continuously while pressing)*/ - LV_EVENT_PRESS_LOST, /**< The object is still being pressed but slid cursor/finger off of the object */ - LV_EVENT_SHORT_CLICKED, /**< The object was pressed for a short period of time, then released it. Not called if scrolled.*/ - LV_EVENT_LONG_PRESSED, /**< Object has been pressed for at least `long_press_time`. Not called if scrolled.*/ - LV_EVENT_LONG_PRESSED_REPEAT, /**< Called after `long_press_time` in every `long_press_repeat_time` ms. Not called if scrolled.*/ - LV_EVENT_CLICKED, /**< Called on release if not scrolled (regardless to long press)*/ - LV_EVENT_RELEASED, /**< Called in every cases when the object has been released*/ - LV_EVENT_SCROLL_BEGIN, /**< Scrolling begins. The event parameter is a pointer to the animation of the scroll. Can be modified*/ - LV_EVENT_SCROLL_END, /**< Scrolling ends*/ - LV_EVENT_SCROLL, /**< Scrolling*/ - LV_EVENT_GESTURE, /**< A gesture is detected. Get the gesture with `lv_indev_get_gesture_dir(lv_indev_get_act());` */ - LV_EVENT_KEY, /**< A key is sent to the object. Get the key with `lv_indev_get_key(lv_indev_get_act());`*/ - LV_EVENT_FOCUSED, /**< The object is focused*/ - LV_EVENT_DEFOCUSED, /**< The object is defocused*/ - LV_EVENT_LEAVE, /**< The object is defocused but still selected*/ - LV_EVENT_HIT_TEST, /**< Perform advanced hit-testing*/ - - /** Drawing events*/ - LV_EVENT_COVER_CHECK, /**< Check if the object fully covers an area. The event parameter is `lv_cover_check_info_t *`.*/ - LV_EVENT_REFR_EXT_DRAW_SIZE, /**< Get the required extra draw area around the object (e.g. for shadow). The event parameter is `lv_coord_t *` to store the size.*/ - LV_EVENT_DRAW_MAIN_BEGIN, /**< Starting the main drawing phase*/ - LV_EVENT_DRAW_MAIN, /**< Perform the main drawing*/ - LV_EVENT_DRAW_MAIN_END, /**< Finishing the main drawing phase*/ - LV_EVENT_DRAW_POST_BEGIN, /**< Starting the post draw phase (when all children are drawn)*/ - LV_EVENT_DRAW_POST, /**< Perform the post draw phase (when all children are drawn)*/ - LV_EVENT_DRAW_POST_END, /**< Finishing the post draw phase (when all children are drawn)*/ - LV_EVENT_DRAW_PART_BEGIN, /**< Starting to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. */ - LV_EVENT_DRAW_PART_END, /**< Finishing to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. */ - - /** Special events*/ - LV_EVENT_VALUE_CHANGED, /**< The object's value has changed (i.e. slider moved)*/ - LV_EVENT_INSERT, /**< A text is inserted to the object. The event data is `char *` being inserted.*/ - LV_EVENT_REFRESH, /**< Notify the object to refresh something on it (for the user)*/ - LV_EVENT_READY, /**< A process has finished*/ - LV_EVENT_CANCEL, /**< A process has been cancelled */ - - /** Other events*/ - LV_EVENT_DELETE, /**< Object is being deleted*/ - LV_EVENT_CHILD_CHANGED, /**< Child was removed, added, or its size, position were changed */ - LV_EVENT_CHILD_CREATED, /**< Child was created, always bubbles up to all parents*/ - LV_EVENT_CHILD_DELETED, /**< Child was deleted, always bubbles up to all parents*/ - LV_EVENT_SCREEN_UNLOAD_START, /**< A screen unload started, fired immediately when scr_load is called*/ - LV_EVENT_SCREEN_LOAD_START, /**< A screen load started, fired when the screen change delay is expired*/ - LV_EVENT_SCREEN_LOADED, /**< A screen was loaded*/ - LV_EVENT_SCREEN_UNLOADED, /**< A screen was unloaded*/ - LV_EVENT_SIZE_CHANGED, /**< Object coordinates/size have changed*/ - LV_EVENT_STYLE_CHANGED, /**< Object's style has changed*/ - LV_EVENT_LAYOUT_CHANGED, /**< The children position has changed due to a layout recalculation*/ - LV_EVENT_GET_SELF_SIZE, /**< Get the internal size of a widget*/ - - _LV_EVENT_LAST, /** Number of default events*/ - - - LV_EVENT_PREPROCESS = 0x80, /** This is a flag that can be set with an event so it's processed - before the class default event processing */ -} lv_event_code_t; - -typedef struct _lv_event_t { - struct _lv_obj_t * target; - struct _lv_obj_t * current_target; - lv_event_code_t code; - void * user_data; - void * param; - struct _lv_event_t * prev; - uint8_t deleted : 1; - uint8_t stop_processing : 1; - uint8_t stop_bubbling : 1; -} lv_event_t; - -/** - * @brief Event callback. - * Events are used to notify the user of some action being taken on the object. - * For details, see ::lv_event_t. - */ -typedef void (*lv_event_cb_t)(lv_event_t * e); - -/** - * Used as the event parameter of ::LV_EVENT_HIT_TEST to check if an `point` can click the object or not. - * `res` should be set like this: - * - If already set to `false` an other event wants that point non clickable. If you want to respect it leave it as `false` or set `true` to overwrite it. - * - If already set `true` and `point` shouldn't be clickable set to `false` - * - If already set to `true` you agree that `point` can click the object leave it as `true` - */ -typedef struct { - const lv_point_t * point; /**< A point relative to screen to check if it can click the object or not*/ - bool res; /**< true: `point` can click the object; false: it cannot*/ -} lv_hit_test_info_t; - -/** - * Used as the event parameter of ::LV_EVENT_COVER_CHECK to check if an area is covered by the object or not. - * In the event use `const lv_area_t * area = lv_event_get_cover_area(e)` to get the area to check - * and `lv_event_set_cover_res(e, res)` to set the result. - */ -typedef struct { - lv_cover_res_t res; - const lv_area_t * area; -} lv_cover_check_info_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Send an event to the object - * @param obj pointer to an object - * @param event_code the type of the event from `lv_event_t` - * @param param arbitrary data depending on the widget type and the event. (Usually `NULL`) - * @return LV_RES_OK: `obj` was not deleted in the event; LV_RES_INV: `obj` was deleted in the event_code - */ -lv_res_t lv_event_send(struct _lv_obj_t * obj, lv_event_code_t event_code, void * param); - -/** - * Used by the widgets internally to call the ancestor widget types's event handler - * @param class_p pointer to the class of the widget (NOT the ancestor class) - * @param e pointer to the event descriptor - * @return LV_RES_OK: the target object was not deleted in the event; LV_RES_INV: it was deleted in the event_code - */ -lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e); - -/** - * Get the object originally targeted by the event. It's the same even if the event is bubbled. - * @param e pointer to the event descriptor - * @return the target of the event_code - */ -struct _lv_obj_t * lv_event_get_target(lv_event_t * e); - -/** - * Get the current target of the event. It's the object which event handler being called. - * If the event is not bubbled it's the same as "normal" target. - * @param e pointer to the event descriptor - * @return pointer to the current target of the event_code - */ -struct _lv_obj_t * lv_event_get_current_target(lv_event_t * e); - -/** - * Get the event code of an event - * @param e pointer to the event descriptor - * @return the event code. (E.g. `LV_EVENT_CLICKED`, `LV_EVENT_FOCUSED`, etc) - */ -lv_event_code_t lv_event_get_code(lv_event_t * e); - -/** - * Get the parameter passed when the event was sent - * @param e pointer to the event descriptor - * @return pointer to the parameter - */ -void * lv_event_get_param(lv_event_t * e); - -/** - * Get the user_data passed when the event was registered on the object - * @param e pointer to the event descriptor - * @return pointer to the user_data - */ -void * lv_event_get_user_data(lv_event_t * e); - -/** - * Stop the event from bubbling. - * This is only valid when called in the middle of an event processing chain. - * @param e pointer to the event descriptor - */ -void lv_event_stop_bubbling(lv_event_t * e); - -/** - * Stop processing this event. - * This is only valid when called in the middle of an event processing chain. - * @param e pointer to the event descriptor - */ -void lv_event_stop_processing(lv_event_t * e); - -/** - * Register a new, custom event ID. - * It can be used the same way as e.g. `LV_EVENT_CLICKED` to send custom events - * @return the new event id - * @example - * uint32_t LV_EVENT_MINE = 0; - * ... - * e = lv_event_register_id(); - * ... - * lv_event_send(obj, LV_EVENT_MINE, &some_data); - */ -uint32_t lv_event_register_id(void); - -/** - * Nested events can be called and one of them might belong to an object that is being deleted. - * Mark this object's `event_temp_data` deleted to know that its `lv_event_send` should return `LV_RES_INV` - * @param obj pointer to an object to mark as deleted - */ -void _lv_event_mark_deleted(struct _lv_obj_t * obj); - - -/** - * Add an event handler function for an object. - * Used by the user to react on event which happens with the object. - * An object can have multiple event handler. They will be called in the same order as they were added. - * @param obj pointer to an object - * @param filter and event code (e.g. `LV_EVENT_CLICKED`) on which the event should be called. `LV_EVENT_ALL` can be sued the receive all the events. - * @param event_cb the new event function - * @param user_data custom data data will be available in `event_cb` - * @return a pointer the event descriptor. Can be used in ::lv_obj_remove_event_dsc - */ -struct _lv_event_dsc_t * lv_obj_add_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, - void * user_data); - -/** - * Remove an event handler function for an object. - * @param obj pointer to an object - * @param event_cb the event function to remove, or `NULL` to remove the firstly added event callback - * @return true if any event handlers were removed - */ -bool lv_obj_remove_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb); - -/** - * Remove an event handler function with a specific user_data from an object. - * @param obj pointer to an object - * @param event_cb the event function to remove, or `NULL` only `user_data` matters. - * @param event_user_data the user_data specified in ::lv_obj_add_event_cb - * @return true if any event handlers were removed - */ -bool lv_obj_remove_event_cb_with_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb, - const void * event_user_data); - -/** - * DEPRECATED because doesn't work if multiple event handlers are added to an object. - * Remove an event handler function for an object. - * @param obj pointer to an object - * @param event_dsc pointer to an event descriptor to remove (returned by ::lv_obj_add_event_cb) - * @return true if any event handlers were removed - */ -bool lv_obj_remove_event_dsc(struct _lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc); - -/** - * The user data of an event object event callback. Always the first match with `event_cb` will be returned. - * @param obj pointer to an object - * @param event_cb the event function - * @return the user_data - */ -void * lv_obj_get_event_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb); - -/** - * Get the input device passed as parameter to indev related events. - * @param e pointer to an event - * @return the indev that triggered the event or NULL if called on a not indev related event - */ -lv_indev_t * lv_event_get_indev(lv_event_t * e); - -/** - * Get the part draw descriptor passed as parameter to `LV_EVENT_DRAW_PART_BEGIN/END`. - * @param e pointer to an event - * @return the part draw descriptor to hook the drawing or NULL if called on an unrelated event - */ -lv_obj_draw_part_dsc_t * lv_event_get_draw_part_dsc(lv_event_t * e); - -/** - * Get the draw context which should be the first parameter of the draw functions. - * Namely: `LV_EVENT_DRAW_MAIN/POST`, `LV_EVENT_DRAW_MAIN/POST_BEGIN`, `LV_EVENT_DRAW_MAIN/POST_END` - * @param e pointer to an event - * @return pointer to a draw context or NULL if called on an unrelated event - */ -lv_draw_ctx_t * lv_event_get_draw_ctx(lv_event_t * e); - -/** - * Get the old area of the object before its size was changed. Can be used in `LV_EVENT_SIZE_CHANGED` - * @param e pointer to an event - * @return the old absolute area of the object or NULL if called on an unrelated event - */ -const lv_area_t * lv_event_get_old_size(lv_event_t * e); - -/** - * Get the key passed as parameter to an event. Can be used in `LV_EVENT_KEY` - * @param e pointer to an event - * @return the triggering key or NULL if called on an unrelated event - */ -uint32_t lv_event_get_key(lv_event_t * e); - -/** - * Get the animation descriptor of a scrolling. Can be used in `LV_EVENT_SCROLL_BEGIN` - * @param e pointer to an event - * @return the animation that will scroll the object. (can be modified as required) - */ -lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e); - -/** - * Set the new extra draw size. Can be used in `LV_EVENT_REFR_EXT_DRAW_SIZE` - * @param e pointer to an event - * @param size The new extra draw size - */ -void lv_event_set_ext_draw_size(lv_event_t * e, lv_coord_t size); - -/** - * Get a pointer to an `lv_point_t` variable in which the self size should be saved (width in `point->x` and height `point->y`). - * Can be used in `LV_EVENT_GET_SELF_SIZE` - * @param e pointer to an event - * @return pointer to `lv_point_t` or NULL if called on an unrelated event - */ -lv_point_t * lv_event_get_self_size_info(lv_event_t * e); - -/** - * Get a pointer to an `lv_hit_test_info_t` variable in which the hit test result should be saved. Can be used in `LV_EVENT_HIT_TEST` - * @param e pointer to an event - * @return pointer to `lv_hit_test_info_t` or NULL if called on an unrelated event - */ -lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e); - -/** - * Get a pointer to an area which should be examined whether the object fully covers it or not. - * Can be used in `LV_EVENT_HIT_TEST` - * @param e pointer to an event - * @return an area with absolute coordinates to check - */ -const lv_area_t * lv_event_get_cover_area(lv_event_t * e); - -/** - * Set the result of cover checking. Can be used in `LV_EVENT_COVER_CHECK` - * @param e pointer to an event - * @param res an element of ::lv_cover_check_info_t - */ -void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res); - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_EVENT_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_global.h b/lib/libesp32_lvgl/lvgl/src/core/lv_global.h new file mode 100644 index 000000000..ed006224c --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_global.h @@ -0,0 +1,229 @@ +/** + * @file lv_global.h + * + */ + +#ifndef LV_GLOBAL_H +#define LV_GLOBAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include + +#include "../misc/lv_types.h" +#include "../draw/lv_draw.h" +#if LV_USE_DRAW_SW +#include "../draw/sw/lv_draw_sw.h" +#endif +#include "../misc/lv_anim.h" +#include "../misc/lv_area.h" +#include "../misc/lv_color_op.h" +#include "../misc/lv_ll.h" +#include "../misc/lv_log.h" +#include "../misc/lv_profiler_builtin.h" +#include "../misc/lv_style.h" +#include "../misc/lv_timer.h" +#include "../others/sysmon/lv_sysmon.h" +#include "../stdlib/builtin/lv_tlsf.h" + +#if LV_USE_FONT_COMPRESSED +#include "../font/lv_font_fmt_txt.h" +#endif + +#include "../tick/lv_tick.h" +#include "../layouts/lv_layout.h" + +/********************* + * DEFINES + *********************/ +#define ZERO_MEM_SENTINEL 0xa1b2c3d4 + +/********************** + * TYPEDEFS + **********************/ + +#if LV_USE_SPAN != 0 +struct _snippet_stack; +#endif + +#if LV_USE_FREETYPE +struct _lv_freetype_context_t; +#endif + +typedef struct _lv_global_t { + bool inited; + bool deinit_in_progress; /**< Can be used e.g. in the LV_EVENT_DELETE to deinit the drivers too */ + + lv_ll_t disp_ll; + lv_display_t * disp_refresh; + lv_display_t * disp_default; + + lv_ll_t style_trans_ll; + bool style_refresh; + uint32_t style_custom_table_size; + uint32_t style_last_custom_prop_id; + uint8_t * style_custom_prop_flag_lookup_table; + + lv_ll_t group_ll; + lv_group_t * group_default; + + lv_ll_t indev_ll; + lv_indev_t * indev_active; + lv_obj_t * indev_obj_active; + + uint32_t layout_count; + lv_layout_dsc_t * layout_list; + bool layout_update_mutex; + + uint32_t memory_zero; + uint32_t math_rand_seed; + lv_area_transform_cache_t area_trans_cache; + + lv_event_t * event_header; + uint32_t event_last_register_id; + + lv_timer_state_t timer_state; + lv_anim_state_t anim_state; + lv_tick_state_t tick_state; + + lv_draw_buf_handlers_t draw_buf_handlers; + + lv_ll_t img_decoder_ll; + +#if LV_CACHE_DEF_SIZE > 0 + lv_cache_t * img_cache; +#endif + +#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 + lv_cache_t * img_header_cache; +#endif + + lv_draw_global_info_t draw_info; +#if defined(LV_DRAW_SW_SHADOW_CACHE_SIZE) && LV_DRAW_SW_SHADOW_CACHE_SIZE > 0 + lv_draw_sw_shadow_cache_t sw_shadow_cache; +#endif +#if LV_DRAW_SW_COMPLEX + _lv_draw_sw_mask_radius_circle_dsc_arr_t sw_circle_cache; +#endif + +#if LV_USE_LOG + lv_log_print_g_cb_t custom_log_print_cb; +#endif + +#if LV_USE_LOG && LV_LOG_USE_TIMESTAMP + uint32_t log_last_log_time; +#endif + +#if LV_USE_THEME_SIMPLE + void * theme_simple; +#endif + +#if LV_USE_THEME_DEFAULT + void * theme_default; +#endif + +#if LV_USE_THEME_MONO + void * theme_mono; +#endif + +#if LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN + lv_tlsf_state_t tlsf_state; +#endif + + lv_ll_t fsdrv_ll; +#if LV_USE_FS_STDIO != '\0' + lv_fs_drv_t stdio_fs_drv; +#endif +#if LV_USE_FS_POSIX + lv_fs_drv_t posix_fs_drv; +#endif + +#if LV_USE_FS_FATFS + lv_fs_drv_t fatfs_fs_drv; +#endif + +#if LV_USE_FS_WIN32 != '\0' + lv_fs_drv_t win32_fs_drv; +#endif + +#if LV_USE_FREETYPE + struct _lv_freetype_context_t * ft_context; +#endif + +#if LV_USE_TINY_TTF + lv_cache_t * tiny_ttf_cache; +#endif + +#if LV_USE_FONT_COMPRESSED + lv_font_fmt_rle_t font_fmt_rle; +#endif + +#if LV_USE_SPAN != 0 + struct _snippet_stack * span_snippet_stack; +#endif + +#if LV_USE_PROFILER && LV_USE_PROFILER_BUILTIN + lv_profiler_builtin_ctx_t profiler_context; +#endif + +#if LV_USE_FILE_EXPLORER != 0 + lv_style_t fe_list_button_style; +#endif + +#if LV_USE_SYSMON && LV_USE_PERF_MONITOR + lv_sysmon_backend_data_t sysmon_perf; +#endif + +#if LV_USE_SYSMON && LV_USE_MEM_MONITOR + lv_sysmon_backend_data_t sysmon_mem; +#endif + +#if LV_USE_IME_PINYIN != 0 + size_t ime_cand_len; +#endif + +#if LV_USE_OBJ_ID_BUILTIN + void * objid_array; + uint32_t objid_count; +#endif + void * user_data; +} lv_global_t; + +/********************** + * MACROS + **********************/ + +#if LV_ENABLE_GLOBAL_CUSTOM +#include LV_GLOBAL_CUSTOM_INCLUDE + +#ifndef LV_GLOBAL_CUSTOM +#define LV_GLOBAL_CUSTOM() lv_global_default() +#endif +#define LV_GLOBAL_DEFAULT() LV_GLOBAL_CUSTOM() +#else +LV_ATTRIBUTE_EXTERN_DATA extern lv_global_t lv_global; +#define LV_GLOBAL_DEFAULT() (&lv_global) +#endif + +/********************** + * GLOBAL PROTOTYPES + **********************/ +#if LV_ENABLE_GLOBAL_CUSTOM +/** + * Get the default global object for current thread + * @return pointer to the default global object + */ +lv_global_t * lv_global_default(void); +#endif +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GLOBAL_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_group.c b/lib/libesp32_lvgl/lvgl/src/core/lv_group.c index 63fde71a0..f7a7cbb14 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_group.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_group.c @@ -9,13 +9,15 @@ #include #include "lv_group.h" -#include "../misc/lv_gc.h" #include "../core/lv_obj.h" -#include "../core/lv_indev.h" +#include "../core/lv_global.h" +#include "../indev/lv_indev.h" /********************* * DEFINES *********************/ +#define default_group LV_GLOBAL_DEFAULT()->group_default +#define group_ll_p &(LV_GLOBAL_DEFAULT()->group_ll) /********************** * TYPEDEFS @@ -32,7 +34,6 @@ static lv_indev_t * get_indev(const lv_group_t * g); /********************** * STATIC VARIABLES **********************/ -static lv_group_t * default_group; /********************** * MACROS @@ -44,12 +45,17 @@ static lv_group_t * default_group; void _lv_group_init(void) { - _lv_ll_init(&LV_GC_ROOT(_lv_group_ll), sizeof(lv_group_t)); + _lv_ll_init(group_ll_p, sizeof(lv_group_t)); +} + +void _lv_group_deinit(void) +{ + _lv_ll_clear(group_ll_p); } lv_group_t * lv_group_create(void) { - lv_group_t * group = _lv_ll_ins_head(&LV_GC_ROOT(_lv_group_ll)); + lv_group_t * group = _lv_ll_ins_head(group_ll_p); LV_ASSERT_MALLOC(group); if(group == NULL) return NULL; _lv_ll_init(&group->obj_ll, sizeof(lv_obj_t *)); @@ -61,19 +67,16 @@ lv_group_t * lv_group_create(void) group->editing = 0; group->refocus_policy = LV_GROUP_REFOCUS_POLICY_PREV; group->wrap = 1; - -#if LV_USE_USER_DATA - group->user_data = NULL; -#endif + group->user_data = NULL; return group; } -void lv_group_del(lv_group_t * group) +void lv_group_delete(lv_group_t * group) { /*Defocus the currently focused object*/ if(group->obj_focus != NULL) { - lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group)); + lv_obj_send_event(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group)); lv_obj_invalidate(*group->obj_focus); } @@ -86,16 +89,18 @@ void lv_group_del(lv_group_t * group) /*Remove the group from any indev devices */ lv_indev_t * indev = lv_indev_get_next(NULL); while(indev) { - if(indev->group == group) { + if(lv_indev_get_group(indev) == group) { lv_indev_set_group(indev, NULL); } indev = lv_indev_get_next(indev); } - if(default_group == group) default_group = NULL; + /*If the group is the default group, set the default group as NULL*/ + if(group == lv_group_get_default()) lv_group_set_default(NULL); + _lv_ll_clear(&(group->obj_ll)); - _lv_ll_remove(&LV_GC_ROOT(_lv_group_ll), group); - lv_mem_free(group); + _lv_ll_remove(group_ll_p, group); + lv_free(group); } void lv_group_set_default(lv_group_t * group) @@ -185,7 +190,7 @@ void lv_group_remove_obj(lv_obj_t * obj) /*If this is the only object in the group then focus to nothing.*/ if(_lv_ll_get_head(&g->obj_ll) == g->obj_focus && _lv_ll_get_tail(&g->obj_ll) == g->obj_focus) { - lv_event_send(*g->obj_focus, LV_EVENT_DEFOCUSED, get_indev(g)); + lv_obj_send_event(*g->obj_focus, LV_EVENT_DEFOCUSED, get_indev(g)); } /*If there more objects in the group then focus to the next/prev object*/ else { @@ -205,7 +210,7 @@ void lv_group_remove_obj(lv_obj_t * obj) _LV_LL_READ(&g->obj_ll, i) { if(*i == obj) { _lv_ll_remove(&g->obj_ll, i); - lv_mem_free(i); + lv_free(i); if(obj->spec_attr) obj->spec_attr->group_p = NULL; break; } @@ -217,7 +222,7 @@ void lv_group_remove_all_objs(lv_group_t * group) { /*Defocus the currently focused object*/ if(group->obj_focus != NULL) { - lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group)); + lv_obj_send_event(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group)); lv_obj_invalidate(*group->obj_focus); group->obj_focus = NULL; } @@ -246,8 +251,8 @@ void lv_group_focus_obj(lv_obj_t * obj) _LV_LL_READ(&g->obj_ll, i) { if(*i == obj) { if(g->obj_focus != NULL && obj != *g->obj_focus) { /*Do not defocus if the same object needs to be focused again*/ - lv_res_t res = lv_event_send(*g->obj_focus, LV_EVENT_DEFOCUSED, get_indev(g)); - if(res != LV_RES_OK) return; + lv_result_t res = lv_obj_send_event(*g->obj_focus, LV_EVENT_DEFOCUSED, get_indev(g)); + if(res != LV_RESULT_OK) return; lv_obj_invalidate(*g->obj_focus); } @@ -255,8 +260,8 @@ void lv_group_focus_obj(lv_obj_t * obj) if(g->obj_focus != NULL) { if(g->focus_cb) g->focus_cb(g); - lv_res_t res = lv_event_send(*g->obj_focus, LV_EVENT_FOCUSED, get_indev(g)); - if(res != LV_RES_OK) return; + lv_result_t res = lv_obj_send_event(*g->obj_focus, LV_EVENT_FOCUSED, get_indev(g)); + if(res != LV_RESULT_OK) return; lv_obj_invalidate(*g->obj_focus); } break; @@ -288,14 +293,14 @@ void lv_group_focus_freeze(lv_group_t * group, bool en) else group->frozen = 1; } -lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c) +lv_result_t lv_group_send_data(lv_group_t * group, uint32_t c) { lv_obj_t * act = lv_group_get_focused(group); - if(act == NULL) return LV_RES_OK; + if(act == NULL) return LV_RESULT_OK; - if(lv_obj_has_state(act, LV_STATE_DISABLED)) return LV_RES_OK; + if(lv_obj_has_state(act, LV_STATE_DISABLED)) return LV_RESULT_OK; - return lv_event_send(act, LV_EVENT_KEY, &c); + return lv_obj_send_event(act, LV_EVENT_KEY, &c); } void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb) @@ -319,8 +324,8 @@ void lv_group_set_editing(lv_group_t * group, bool edit) lv_obj_t * focused = lv_group_get_focused(group); if(focused) { - lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_FOCUSED, get_indev(group)); - if(res != LV_RES_OK) return; + lv_result_t res = lv_obj_send_event(*group->obj_focus, LV_EVENT_FOCUSED, get_indev(group)); + if(res != LV_RESULT_OK) return; lv_obj_invalidate(focused); } @@ -359,19 +364,39 @@ lv_group_edge_cb_t lv_group_get_edge_cb(const lv_group_t * group) bool lv_group_get_editing(const lv_group_t * group) { if(!group) return false; - return group->editing ? true : false; + return group->editing; } bool lv_group_get_wrap(lv_group_t * group) { if(!group) return false; - return group->wrap ? true : false; + return group->wrap; } uint32_t lv_group_get_obj_count(lv_group_t * group) { return _lv_ll_get_len(&group->obj_ll); } + +uint32_t lv_group_get_count(void) +{ + return _lv_ll_get_len(group_ll_p); +} + +lv_group_t * lv_group_by_index(uint32_t index) +{ + uint32_t len = 0; + void * node; + + for(node = _lv_ll_get_tail(group_ll_p); node != NULL; node = _lv_ll_get_prev(group_ll_p, node)) { + if(len == index) { + return (lv_group_t *) node; + } + len++; + } + + return NULL; +} /********************** * STATIC FUNCTIONS **********************/ @@ -449,15 +474,15 @@ static bool focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *) if(obj_next == group->obj_focus) return focus_changed; /*There's only one visible object and it's already focused*/ if(group->obj_focus) { - lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group)); - if(res != LV_RES_OK) return focus_changed; + lv_result_t res = lv_obj_send_event(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group)); + if(res != LV_RESULT_OK) return focus_changed; lv_obj_invalidate(*group->obj_focus); } group->obj_focus = obj_next; - lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_FOCUSED, get_indev(group)); - if(res != LV_RES_OK) return focus_changed; + lv_result_t res = lv_obj_send_event(*group->obj_focus, LV_EVENT_FOCUSED, get_indev(group)); + if(res != LV_RESULT_OK) return focus_changed; lv_obj_invalidate(*group->obj_focus); @@ -467,7 +492,7 @@ static bool focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *) } /** - * Find an indev preferably with KEYPAD or ENCOEDR type that uses the given group. + * Find an indev preferably with POINTER type (because it's the most generic) that uses the given group. * In other words, find an indev, that is related to the given group. * In the worst case simply return the latest indev * @param g a group the find in the indevs @@ -475,24 +500,18 @@ static bool focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *) */ static lv_indev_t * get_indev(const lv_group_t * g) { - lv_indev_t * indev_encoder = NULL; - lv_indev_t * indev_group = NULL; + lv_indev_t * indev_guess = NULL; lv_indev_t * indev = lv_indev_get_next(NULL); + while(indev) { lv_indev_type_t indev_type = lv_indev_get_type(indev); - if(indev->group == g) { - /*Prefer KEYPAD*/ - if(indev_type == LV_INDEV_TYPE_KEYPAD) return indev; - if(indev_type == LV_INDEV_TYPE_ENCODER) indev_encoder = indev; - indev_group = indev; + /*Prefer POINTER*/ + if(indev_type == LV_INDEV_TYPE_POINTER) return indev; + if(lv_indev_get_group(indev) == g) { + indev_guess = indev; } indev = lv_indev_get_next(indev); } - if(indev_encoder) return indev_encoder; - if(indev_group) return indev_group; - - /*In lack of a better option use the first input device. (It can be NULL if there is no input device)*/ - return lv_indev_get_next(NULL); + return indev_guess; } - diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_group.h b/lib/libesp32_lvgl/lvgl/src/core/lv_group.h index 091059730..ca60edb12 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_group.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_group.h @@ -18,15 +18,14 @@ extern "C" { #include #include -#include "../misc/lv_ll.h" #include "../misc/lv_types.h" +#include "../misc/lv_ll.h" /********************* * DEFINES *********************/ /*Predefined keys to control the focused object via lv_group_send(group, c)*/ - -enum { +enum _lv_key_t { LV_KEY_UP = 17, /*0x11*/ LV_KEY_DOWN = 18, /*0x12*/ LV_KEY_RIGHT = 19, /*0x13*/ @@ -40,34 +39,28 @@ enum { LV_KEY_HOME = 2, /*0x02, STX*/ LV_KEY_END = 3, /*0x03, ETX*/ }; -typedef uint8_t lv_key_t; /********************** * TYPEDEFS **********************/ -struct _lv_obj_t; -struct _lv_group_t; - -typedef void (*lv_group_focus_cb_t)(struct _lv_group_t *); -typedef void (*lv_group_edge_cb_t)(struct _lv_group_t *, bool); +typedef void (*lv_group_focus_cb_t)(lv_group_t *); +typedef void (*lv_group_edge_cb_t)(lv_group_t *, bool); /** * Groups can be used to logically hold objects so that they can be individually focused. * They are NOT for laying out objects on a screen (try layouts for that). */ -typedef struct _lv_group_t { +struct _lv_group_t { lv_ll_t obj_ll; /**< Linked list to store the objects in the group*/ - struct _lv_obj_t ** obj_focus; /**< The object in focus*/ + lv_obj_t ** obj_focus; /**< The object in focus*/ lv_group_focus_cb_t focus_cb; /**< A function to call when a new object is focused (optional)*/ lv_group_edge_cb_t edge_cb; /**< A function to call when an edge is reached, no more focus targets are available in this direction (to allow edge feedback like a sound or a scroll bounce) */ -#if LV_USE_USER_DATA void * user_data; -#endif uint8_t frozen : 1; /**< 1: can't focus to new object*/ uint8_t editing : 1; /**< 1: Edit mode, 0: Navigate mode*/ @@ -75,8 +68,7 @@ typedef struct _lv_group_t { deletion.*/ uint8_t wrap : 1; /**< 1: Focus next/prev can wrap at end of list. 0: Focus next/prev stops at end of list.*/ -} lv_group_t; - +}; typedef enum { LV_GROUP_REFOCUS_POLICY_NEXT = 0, @@ -88,11 +80,17 @@ typedef enum { **********************/ /** - * Init. the group module + * Init the group module * @remarks Internal function, do not call directly. */ void _lv_group_init(void); +/** + * Deinit the group module + * @remarks Internal function, do not call directly. + */ +void _lv_group_deinit(void); + /** * Create a new object group * @return pointer to the new object group @@ -103,7 +101,7 @@ lv_group_t * lv_group_create(void); * Delete a group object * @param group pointer to a group */ -void lv_group_del(lv_group_t * group); +void lv_group_delete(lv_group_t * group); /** * Set a default group. New object are added to this group if it's enabled in their class with `add_to_def_group = true` @@ -122,20 +120,20 @@ lv_group_t * lv_group_get_default(void); * @param group pointer to a group * @param obj pointer to an object to add */ -void lv_group_add_obj(lv_group_t * group, struct _lv_obj_t * obj); +void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj); /** * Swap 2 object in a group. The object must be in the same group * @param obj1 pointer to an object * @param obj2 pointer to an other object */ -void lv_group_swap_obj(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2); +void lv_group_swap_obj(lv_obj_t * obj1, lv_obj_t * obj2); /** * Remove an object from its group * @param obj pointer to an object to remove */ -void lv_group_remove_obj(struct _lv_obj_t * obj); +void lv_group_remove_obj(lv_obj_t * obj); /** * Remove all objects from a group @@ -147,7 +145,7 @@ void lv_group_remove_all_objs(lv_group_t * group); * Focus on an object (defocus the current) * @param obj pointer to an object to focus on */ -void lv_group_focus_obj(struct _lv_obj_t * obj); +void lv_group_focus_obj(lv_obj_t * obj); /** * Focus the next object in a group (defocus the current) @@ -174,7 +172,7 @@ void lv_group_focus_freeze(lv_group_t * group, bool en); * @param c a character (use LV_KEY_.. to navigate) * @return result of focused object in group. */ -lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c); +lv_result_t lv_group_send_data(lv_group_t * group, uint32_t c); /** * Set a function for a group which will be called when a new object is focused @@ -190,7 +188,6 @@ void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb); */ void lv_group_set_edge_cb(lv_group_t * group, lv_group_edge_cb_t edge_cb); - /** * Set whether the next or previous item in a group is focused if the currently focused obj is * deleted. @@ -218,7 +215,7 @@ void lv_group_set_wrap(lv_group_t * group, bool en); * @param group pointer to a group * @return pointer to the focused object */ -struct _lv_obj_t * lv_group_get_focused(const lv_group_t * group); +lv_obj_t * lv_group_get_focused(const lv_group_t * group); /** * Get the focus callback function of a group @@ -255,6 +252,18 @@ bool lv_group_get_wrap(lv_group_t * group); */ uint32_t lv_group_get_obj_count(lv_group_t * group); +/** + * Get the number of groups + * @return number of groups + */ +uint32_t lv_group_get_count(void); + +/** + * Get a group by its index + * @return pointer to the group + */ +lv_group_t * lv_group_by_index(uint32_t index); + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_indev.c b/lib/libesp32_lvgl/lvgl/src/core/lv_indev.c deleted file mode 100644 index 9192f8473..000000000 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_indev.c +++ /dev/null @@ -1,1180 +0,0 @@ -/** - * @file lv_indev.c - * - */ - -/********************* - * INCLUDES - ********************/ -#include "lv_indev.h" -#include "lv_disp.h" -#include "lv_obj.h" -#include "lv_indev_scroll.h" -#include "lv_group.h" -#include "lv_refr.h" - -#include "../hal/lv_hal_tick.h" -#include "../misc/lv_timer.h" -#include "../misc/lv_math.h" - -/********************* - * DEFINES - *********************/ -#if LV_INDEV_DEF_SCROLL_THROW <= 0 - #warning "LV_INDEV_DRAG_THROW must be greater than 0" -#endif - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data); -static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data); -static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data); -static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data); -static void indev_proc_press(_lv_indev_proc_t * proc); -static void indev_proc_release(_lv_indev_proc_t * proc); -static void indev_proc_reset_query_handler(lv_indev_t * indev); -static void indev_click_focus(_lv_indev_proc_t * proc); -static void indev_gesture(_lv_indev_proc_t * proc); -static bool indev_reset_check(_lv_indev_proc_t * proc); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_indev_t * indev_act; -static lv_obj_t * indev_obj_act = NULL; - -/********************** - * MACROS - **********************/ -#if LV_LOG_TRACE_INDEV - #define INDEV_TRACE(...) LV_LOG_TRACE(__VA_ARGS__) -#else - #define INDEV_TRACE(...) -#endif - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void lv_indev_read_timer_cb(lv_timer_t * timer) -{ - INDEV_TRACE("begin"); - - lv_indev_data_t data; - - indev_act = timer->user_data; - - /*Read and process all indevs*/ - if(indev_act->driver->disp == NULL) return; /*Not assigned to any displays*/ - - /*Handle reset query before processing the point*/ - indev_proc_reset_query_handler(indev_act); - - if(indev_act->proc.disabled || - indev_act->driver->disp->prev_scr != NULL) return; /*Input disabled or screen animation active*/ - bool continue_reading; - do { - /*Read the data*/ - _lv_indev_read(indev_act, &data); - continue_reading = data.continue_reading; - - /*The active object might be deleted even in the read function*/ - indev_proc_reset_query_handler(indev_act); - indev_obj_act = NULL; - - indev_act->proc.state = data.state; - - /*Save the last activity time*/ - if(indev_act->proc.state == LV_INDEV_STATE_PRESSED) { - indev_act->driver->disp->last_activity_time = lv_tick_get(); - } - else if(indev_act->driver->type == LV_INDEV_TYPE_ENCODER && data.enc_diff) { - indev_act->driver->disp->last_activity_time = lv_tick_get(); - } - - if(indev_act->driver->type == LV_INDEV_TYPE_POINTER) { - indev_pointer_proc(indev_act, &data); - } - else if(indev_act->driver->type == LV_INDEV_TYPE_KEYPAD) { - indev_keypad_proc(indev_act, &data); - } - else if(indev_act->driver->type == LV_INDEV_TYPE_ENCODER) { - indev_encoder_proc(indev_act, &data); - } - else if(indev_act->driver->type == LV_INDEV_TYPE_BUTTON) { - indev_button_proc(indev_act, &data); - } - /*Handle reset query if it happened in during processing*/ - indev_proc_reset_query_handler(indev_act); - } while(continue_reading); - - /*End of indev processing, so no act indev*/ - indev_act = NULL; - indev_obj_act = NULL; - - INDEV_TRACE("finished"); -} - -void lv_indev_enable(lv_indev_t * indev, bool en) -{ - uint8_t enable = en ? 0 : 1; - - if(indev) { - indev->proc.disabled = enable; - } - else { - lv_indev_t * i = lv_indev_get_next(NULL); - while(i) { - i->proc.disabled = enable; - i = lv_indev_get_next(i); - } - } -} - -lv_indev_t * lv_indev_get_act(void) -{ - return indev_act; -} - -lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev) -{ - if(indev == NULL) return LV_INDEV_TYPE_NONE; - - return indev->driver->type; -} - -void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj) -{ - if(indev) { - indev->proc.reset_query = 1; - if(indev_act == indev) indev_obj_act = NULL; - if(indev->driver->type == LV_INDEV_TYPE_POINTER || indev->driver->type == LV_INDEV_TYPE_KEYPAD) { - if(obj == NULL || indev->proc.types.pointer.last_pressed == obj) { - indev->proc.types.pointer.last_pressed = NULL; - } - if(obj == NULL || indev->proc.types.pointer.act_obj == obj) { - indev->proc.types.pointer.act_obj = NULL; - } - if(obj == NULL || indev->proc.types.pointer.last_obj == obj) { - indev->proc.types.pointer.last_obj = NULL; - } - } - } - else { - lv_indev_t * i = lv_indev_get_next(NULL); - while(i) { - i->proc.reset_query = 1; - if(i->driver->type == LV_INDEV_TYPE_POINTER || i->driver->type == LV_INDEV_TYPE_KEYPAD) { - if(obj == NULL || i->proc.types.pointer.last_pressed == obj) { - i->proc.types.pointer.last_pressed = NULL; - } - if(obj == NULL || i->proc.types.pointer.act_obj == obj) { - i->proc.types.pointer.act_obj = NULL; - } - if(obj == NULL || i->proc.types.pointer.last_obj == obj) { - i->proc.types.pointer.last_obj = NULL; - } - } - i = lv_indev_get_next(i); - } - indev_obj_act = NULL; - } -} - -void lv_indev_reset_long_press(lv_indev_t * indev) -{ - indev->proc.long_pr_sent = 0; - indev->proc.longpr_rep_timestamp = lv_tick_get(); - indev->proc.pr_timestamp = lv_tick_get(); -} - -void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj) -{ - if(indev->driver->type != LV_INDEV_TYPE_POINTER) return; - - indev->cursor = cur_obj; - lv_obj_set_parent(indev->cursor, lv_disp_get_layer_sys(indev->driver->disp)); - lv_obj_set_pos(indev->cursor, indev->proc.types.pointer.act_point.x, indev->proc.types.pointer.act_point.y); - lv_obj_clear_flag(indev->cursor, LV_OBJ_FLAG_CLICKABLE); - lv_obj_add_flag(indev->cursor, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_FLOATING); -} - -void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group) -{ - if(indev->driver->type == LV_INDEV_TYPE_KEYPAD || indev->driver->type == LV_INDEV_TYPE_ENCODER) { - indev->group = group; - } -} - -void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[]) -{ - if(indev->driver->type == LV_INDEV_TYPE_BUTTON) { - indev->btn_points = points; - } -} - -void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point) -{ - if(indev == NULL) { - point->x = 0; - point->y = 0; - return; - } - if(indev->driver->type != LV_INDEV_TYPE_POINTER && indev->driver->type != LV_INDEV_TYPE_BUTTON) { - point->x = -1; - point->y = -1; - } - else { - point->x = indev->proc.types.pointer.act_point.x; - point->y = indev->proc.types.pointer.act_point.y; - } -} - -lv_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev) -{ - return indev->proc.types.pointer.gesture_dir; -} - -uint32_t lv_indev_get_key(const lv_indev_t * indev) -{ - if(indev->driver->type != LV_INDEV_TYPE_KEYPAD) - return 0; - else - return indev->proc.types.keypad.last_key; -} - -lv_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev) -{ - if(indev == NULL) return false; - if(indev->driver->type != LV_INDEV_TYPE_POINTER && indev->driver->type != LV_INDEV_TYPE_BUTTON) return false; - return indev->proc.types.pointer.scroll_dir; -} - -lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev) -{ - if(indev == NULL) return NULL; - if(indev->driver->type != LV_INDEV_TYPE_POINTER && indev->driver->type != LV_INDEV_TYPE_BUTTON) return NULL; - return indev->proc.types.pointer.scroll_obj; -} - -void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point) -{ - point->x = 0; - point->y = 0; - - if(indev == NULL) return; - - if(indev->driver->type == LV_INDEV_TYPE_POINTER || indev->driver->type == LV_INDEV_TYPE_BUTTON) { - point->x = indev->proc.types.pointer.vect.x; - point->y = indev->proc.types.pointer.vect.y; - } -} - -void lv_indev_wait_release(lv_indev_t * indev) -{ - if(indev == NULL)return; - indev->proc.wait_until_release = 1; -} - -lv_obj_t * lv_indev_get_obj_act(void) -{ - return indev_obj_act; -} - -lv_timer_t * lv_indev_get_read_timer(lv_disp_t * indev) -{ - if(!indev) { - LV_LOG_WARN("lv_indev_get_read_timer: indev was NULL"); - return NULL; - } - - return indev->refr_timer; -} - - -lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point) -{ - lv_obj_t * found_p = NULL; - - /*If this obj is hidden the children are hidden too so return immediately*/ - if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return NULL; - - lv_point_t p_trans = *point; - lv_obj_transform_point(obj, &p_trans, false, true); - - bool hit_test_ok = lv_obj_hit_test(obj, &p_trans); - - /*If the point is on this object or has overflow visible check its children too*/ - if(_lv_area_is_point_on(&obj->coords, &p_trans, 0) || lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) { - int32_t i; - uint32_t child_cnt = lv_obj_get_child_cnt(obj); - - /*If a child matches use it*/ - for(i = child_cnt - 1; i >= 0; i--) { - lv_obj_t * child = obj->spec_attr->children[i]; - found_p = lv_indev_search_obj(child, &p_trans); - if(found_p) return found_p; - } - } - - /*If not return earlier for a clicked child and this obj's hittest was ok use it - *else return NULL*/ - if(hit_test_ok) return obj; - else return NULL; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Process a new point from LV_INDEV_TYPE_POINTER input device - * @param i pointer to an input device - * @param data pointer to the data read from the input device - */ -static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data) -{ - lv_disp_t * disp = i->driver->disp; - /*Save the raw points so they can be used again in _lv_indev_read*/ - i->proc.types.pointer.last_raw_point.x = data->point.x; - i->proc.types.pointer.last_raw_point.y = data->point.y; - - if(disp->driver->rotated == LV_DISP_ROT_180 || disp->driver->rotated == LV_DISP_ROT_270) { - data->point.x = disp->driver->hor_res - data->point.x - 1; - data->point.y = disp->driver->ver_res - data->point.y - 1; - } - if(disp->driver->rotated == LV_DISP_ROT_90 || disp->driver->rotated == LV_DISP_ROT_270) { - lv_coord_t tmp = data->point.y; - data->point.y = data->point.x; - data->point.x = disp->driver->ver_res - tmp - 1; - } - - /*Simple sanity check*/ - if(data->point.x < 0) { - LV_LOG_WARN("X is %d which is smaller than zero", (int)data->point.x); - } - if(data->point.x >= lv_disp_get_hor_res(i->driver->disp)) { - LV_LOG_WARN("X is %d which is greater than hor. res", (int)data->point.x); - } - if(data->point.y < 0) { - LV_LOG_WARN("Y is %d which is smaller than zero", (int)data->point.y); - } - if(data->point.y >= lv_disp_get_ver_res(i->driver->disp)) { - LV_LOG_WARN("Y is %d which is greater than ver. res", (int)data->point.y); - } - - /*Move the cursor if set and moved*/ - if(i->cursor != NULL && - (i->proc.types.pointer.last_point.x != data->point.x || i->proc.types.pointer.last_point.y != data->point.y)) { - lv_obj_set_pos(i->cursor, data->point.x, data->point.y); - } - - i->proc.types.pointer.act_point.x = data->point.x; - i->proc.types.pointer.act_point.y = data->point.y; - - if(i->proc.state == LV_INDEV_STATE_PRESSED) { - indev_proc_press(&i->proc); - } - else { - indev_proc_release(&i->proc); - } - - i->proc.types.pointer.last_point.x = i->proc.types.pointer.act_point.x; - i->proc.types.pointer.last_point.y = i->proc.types.pointer.act_point.y; -} - -/** - * Process a new point from LV_INDEV_TYPE_KEYPAD input device - * @param i pointer to an input device - * @param data pointer to the data read from the input device - */ -static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data) -{ - if(data->state == LV_INDEV_STATE_PRESSED && i->proc.wait_until_release) return; - - if(i->proc.wait_until_release) { - i->proc.wait_until_release = 0; - i->proc.pr_timestamp = 0; - i->proc.long_pr_sent = 0; - i->proc.types.keypad.last_state = LV_INDEV_STATE_RELEASED; /*To skip the processing of release*/ - } - - lv_group_t * g = i->group; - if(g == NULL) return; - - indev_obj_act = lv_group_get_focused(g); - if(indev_obj_act == NULL) return; - - bool dis = lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED); - - /*Save the last key to compare it with the current latter on RELEASE*/ - uint32_t prev_key = i->proc.types.keypad.last_key; - - /*Save the last key. - *It must be done here else `lv_indev_get_key` will return the last key in events*/ - i->proc.types.keypad.last_key = data->key; - - /*Save the previous state so we can detect state changes below and also set the last state now - *so if any event handler on the way returns `LV_RES_INV` the last state is remembered - *for the next time*/ - uint32_t prev_state = i->proc.types.keypad.last_state; - i->proc.types.keypad.last_state = data->state; - - /*Key press happened*/ - if(data->state == LV_INDEV_STATE_PRESSED && prev_state == LV_INDEV_STATE_RELEASED) { - LV_LOG_INFO("%" LV_PRIu32 " key is pressed", data->key); - i->proc.pr_timestamp = lv_tick_get(); - - /*Move the focus on NEXT*/ - if(data->key == LV_KEY_NEXT) { - lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/ - lv_group_focus_next(g); - if(indev_reset_check(&i->proc)) return; - } - /*Move the focus on PREV*/ - else if(data->key == LV_KEY_PREV) { - lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/ - lv_group_focus_prev(g); - if(indev_reset_check(&i->proc)) return; - } - else if(!dis) { - /*Simulate a press on the object if ENTER was pressed*/ - if(data->key == LV_KEY_ENTER) { - /*Send the ENTER as a normal KEY*/ - lv_group_send_data(g, LV_KEY_ENTER); - if(indev_reset_check(&i->proc)) return; - - if(!dis) lv_event_send(indev_obj_act, LV_EVENT_PRESSED, indev_act); - if(indev_reset_check(&i->proc)) return; - } - else if(data->key == LV_KEY_ESC) { - /*Send the ESC as a normal KEY*/ - lv_group_send_data(g, LV_KEY_ESC); - if(indev_reset_check(&i->proc)) return; - - lv_event_send(indev_obj_act, LV_EVENT_CANCEL, indev_act); - if(indev_reset_check(&i->proc)) return; - } - /*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/ - else { - lv_group_send_data(g, data->key); - if(indev_reset_check(&i->proc)) return; - } - } - } - /*Pressing*/ - else if(!dis && data->state == LV_INDEV_STATE_PRESSED && prev_state == LV_INDEV_STATE_PRESSED) { - - if(data->key == LV_KEY_ENTER) { - lv_event_send(indev_obj_act, LV_EVENT_PRESSING, indev_act); - if(indev_reset_check(&i->proc)) return; - } - - /*Long press time has elapsed?*/ - if(i->proc.long_pr_sent == 0 && lv_tick_elaps(i->proc.pr_timestamp) > i->driver->long_press_time) { - i->proc.long_pr_sent = 1; - if(data->key == LV_KEY_ENTER) { - i->proc.longpr_rep_timestamp = lv_tick_get(); - lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, indev_act); - if(indev_reset_check(&i->proc)) return; - } - } - /*Long press repeated time has elapsed?*/ - else if(i->proc.long_pr_sent != 0 && - lv_tick_elaps(i->proc.longpr_rep_timestamp) > i->driver->long_press_repeat_time) { - - i->proc.longpr_rep_timestamp = lv_tick_get(); - - /*Send LONG_PRESS_REP on ENTER*/ - if(data->key == LV_KEY_ENTER) { - lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED_REPEAT, indev_act); - if(indev_reset_check(&i->proc)) return; - } - /*Move the focus on NEXT again*/ - else if(data->key == LV_KEY_NEXT) { - lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/ - lv_group_focus_next(g); - if(indev_reset_check(&i->proc)) return; - } - /*Move the focus on PREV again*/ - else if(data->key == LV_KEY_PREV) { - lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/ - lv_group_focus_prev(g); - if(indev_reset_check(&i->proc)) return; - } - /*Just send other keys again to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT)*/ - else { - lv_group_send_data(g, data->key); - if(indev_reset_check(&i->proc)) return; - } - } - } - /*Release happened*/ - else if(!dis && data->state == LV_INDEV_STATE_RELEASED && prev_state == LV_INDEV_STATE_PRESSED) { - LV_LOG_INFO("%" LV_PRIu32 " key is released", data->key); - /*The user might clear the key when it was released. Always release the pressed key*/ - data->key = prev_key; - if(data->key == LV_KEY_ENTER) { - - lv_event_send(indev_obj_act, LV_EVENT_RELEASED, indev_act); - if(indev_reset_check(&i->proc)) return; - - if(i->proc.long_pr_sent == 0) { - lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, indev_act); - if(indev_reset_check(&i->proc)) return; - } - - lv_event_send(indev_obj_act, LV_EVENT_CLICKED, indev_act); - if(indev_reset_check(&i->proc)) return; - - } - i->proc.pr_timestamp = 0; - i->proc.long_pr_sent = 0; - } - indev_obj_act = NULL; -} - -/** - * Process a new point from LV_INDEV_TYPE_ENCODER input device - * @param i pointer to an input device - * @param data pointer to the data read from the input device - */ -static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) -{ - if(data->state == LV_INDEV_STATE_PRESSED && i->proc.wait_until_release) return; - - if(i->proc.wait_until_release) { - i->proc.wait_until_release = 0; - i->proc.pr_timestamp = 0; - i->proc.long_pr_sent = 0; - i->proc.types.keypad.last_state = LV_INDEV_STATE_RELEASED; /*To skip the processing of release*/ - } - - /*Save the last keys before anything else. - *They need to be already saved if the function returns for any reason*/ - lv_indev_state_t last_state = i->proc.types.keypad.last_state; - i->proc.types.keypad.last_state = data->state; - i->proc.types.keypad.last_key = data->key; - - lv_group_t * g = i->group; - if(g == NULL) return; - - indev_obj_act = lv_group_get_focused(g); - if(indev_obj_act == NULL) return; - - /*Process the steps they are valid only with released button*/ - if(data->state != LV_INDEV_STATE_RELEASED) { - data->enc_diff = 0; - } - - /*Refresh the focused object. It might change due to lv_group_focus_prev/next*/ - indev_obj_act = lv_group_get_focused(g); - if(indev_obj_act == NULL) return; - - /*Button press happened*/ - if(data->state == LV_INDEV_STATE_PRESSED && last_state == LV_INDEV_STATE_RELEASED) { - LV_LOG_INFO("pressed"); - - i->proc.pr_timestamp = lv_tick_get(); - - if(data->key == LV_KEY_ENTER) { - bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) || - lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE); - if(lv_group_get_editing(g) == true || editable_or_scrollable == false) { - lv_event_send(indev_obj_act, LV_EVENT_PRESSED, indev_act); - if(indev_reset_check(&i->proc)) return; - } - } - else if(data->key == LV_KEY_LEFT) { - /*emulate encoder left*/ - data->enc_diff--; - } - else if(data->key == LV_KEY_RIGHT) { - /*emulate encoder right*/ - data->enc_diff++; - } - else if(data->key == LV_KEY_ESC) { - /*Send the ESC as a normal KEY*/ - lv_group_send_data(g, LV_KEY_ESC); - if(indev_reset_check(&i->proc)) return; - - lv_event_send(indev_obj_act, LV_EVENT_CANCEL, indev_act); - if(indev_reset_check(&i->proc)) return; - } - /*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/ - else { - lv_group_send_data(g, data->key); - if(indev_reset_check(&i->proc)) return; - } - } - /*Pressing*/ - else if(data->state == LV_INDEV_STATE_PRESSED && last_state == LV_INDEV_STATE_PRESSED) { - /*Long press*/ - if(i->proc.long_pr_sent == 0 && lv_tick_elaps(i->proc.pr_timestamp) > i->driver->long_press_time) { - - i->proc.long_pr_sent = 1; - i->proc.longpr_rep_timestamp = lv_tick_get(); - - if(data->key == LV_KEY_ENTER) { - bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) || - lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE); - - /*On enter long press toggle edit mode.*/ - if(editable_or_scrollable) { - /*Don't leave edit mode if there is only one object (nowhere to navigate)*/ - if(lv_group_get_obj_count(g) > 1) { - LV_LOG_INFO("toggling edit mode"); - lv_group_set_editing(g, lv_group_get_editing(g) ? false : true); /*Toggle edit mode on long press*/ - lv_obj_clear_state(indev_obj_act, LV_STATE_PRESSED); /*Remove the pressed state manually*/ - } - } - /*If not editable then just send a long press Call the ancestor's event handler*/ - else { - lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, indev_act); - if(indev_reset_check(&i->proc)) return; - } - } - - i->proc.long_pr_sent = 1; - } - /*Long press repeated time has elapsed?*/ - else if(i->proc.long_pr_sent != 0 && lv_tick_elaps(i->proc.longpr_rep_timestamp) > i->driver->long_press_repeat_time) { - - i->proc.longpr_rep_timestamp = lv_tick_get(); - - if(data->key == LV_KEY_ENTER) { - lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED_REPEAT, indev_act); - if(indev_reset_check(&i->proc)) return; - } - else if(data->key == LV_KEY_LEFT) { - /*emulate encoder left*/ - data->enc_diff--; - } - else if(data->key == LV_KEY_RIGHT) { - /*emulate encoder right*/ - data->enc_diff++; - } - else { - lv_group_send_data(g, data->key); - if(indev_reset_check(&i->proc)) return; - } - - } - - } - /*Release happened*/ - else if(data->state == LV_INDEV_STATE_RELEASED && last_state == LV_INDEV_STATE_PRESSED) { - LV_LOG_INFO("released"); - - if(data->key == LV_KEY_ENTER) { - bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) || - lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE); - - /*The button was released on a non-editable object. Just send enter*/ - if(editable_or_scrollable == false) { - lv_event_send(indev_obj_act, LV_EVENT_RELEASED, indev_act); - if(indev_reset_check(&i->proc)) return; - - if(i->proc.long_pr_sent == 0) lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, indev_act); - if(indev_reset_check(&i->proc)) return; - - lv_event_send(indev_obj_act, LV_EVENT_CLICKED, indev_act); - if(indev_reset_check(&i->proc)) return; - - } - /*An object is being edited and the button is released.*/ - else if(lv_group_get_editing(g)) { - /*Ignore long pressed enter release because it comes from mode switch*/ - if(!i->proc.long_pr_sent || lv_group_get_obj_count(g) <= 1) { - lv_event_send(indev_obj_act, LV_EVENT_RELEASED, indev_act); - if(indev_reset_check(&i->proc)) return; - - lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, indev_act); - if(indev_reset_check(&i->proc)) return; - - lv_event_send(indev_obj_act, LV_EVENT_CLICKED, indev_act); - if(indev_reset_check(&i->proc)) return; - - lv_group_send_data(g, LV_KEY_ENTER); - if(indev_reset_check(&i->proc)) return; - } - else { - lv_obj_clear_state(indev_obj_act, LV_STATE_PRESSED); /*Remove the pressed state manually*/ - } - } - /*If the focused object is editable and now in navigate mode then on enter switch edit - mode*/ - else if(!i->proc.long_pr_sent) { - LV_LOG_INFO("entering edit mode"); - lv_group_set_editing(g, true); /*Set edit mode*/ - } - } - - i->proc.pr_timestamp = 0; - i->proc.long_pr_sent = 0; - } - indev_obj_act = NULL; - - /*if encoder steps or simulated steps via left/right keys*/ - if(data->enc_diff != 0) { - /*In edit mode send LEFT/RIGHT keys*/ - if(lv_group_get_editing(g)) { - LV_LOG_INFO("rotated by %+d (edit)", data->enc_diff); - int32_t s; - if(data->enc_diff < 0) { - for(s = 0; s < -data->enc_diff; s++) { - lv_group_send_data(g, LV_KEY_LEFT); - if(indev_reset_check(&i->proc)) return; - } - } - else if(data->enc_diff > 0) { - for(s = 0; s < data->enc_diff; s++) { - lv_group_send_data(g, LV_KEY_RIGHT); - if(indev_reset_check(&i->proc)) return; - } - } - } - /*In navigate mode focus on the next/prev objects*/ - else { - LV_LOG_INFO("rotated by %+d (nav)", data->enc_diff); - int32_t s; - if(data->enc_diff < 0) { - for(s = 0; s < -data->enc_diff; s++) { - lv_group_focus_prev(g); - if(indev_reset_check(&i->proc)) return; - } - } - else if(data->enc_diff > 0) { - for(s = 0; s < data->enc_diff; s++) { - lv_group_focus_next(g); - if(indev_reset_check(&i->proc)) return; - } - } - } - } -} - -/** - * Process new points from an input device. indev->state.pressed has to be set - * @param indev pointer to an input device state - * @param x x coordinate of the next point - * @param y y coordinate of the next point - */ -static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data) -{ - /*Die gracefully if i->btn_points is NULL*/ - if(i->btn_points == NULL) { - LV_LOG_WARN("btn_points is NULL"); - return; - } - - lv_coord_t x = i->btn_points[data->btn_id].x; - lv_coord_t y = i->btn_points[data->btn_id].y; - - static lv_indev_state_t prev_state = LV_INDEV_STATE_RELEASED; - if(prev_state != data->state) { - if(data->state == LV_INDEV_STATE_PRESSED) { - LV_LOG_INFO("button %" LV_PRIu32 " is pressed (x:%d y:%d)", data->btn_id, x, y); - } - else { - LV_LOG_INFO("button %" LV_PRIu32 " is released (x:%d y:%d)", data->btn_id, x, y); - } - } - - /*If a new point comes always make a release*/ - if(data->state == LV_INDEV_STATE_PRESSED) { - if(i->proc.types.pointer.last_point.x != x || - i->proc.types.pointer.last_point.y != y) { - indev_proc_release(&i->proc); - } - } - - if(indev_reset_check(&i->proc)) return; - - /*Save the new points*/ - i->proc.types.pointer.act_point.x = x; - i->proc.types.pointer.act_point.y = y; - - if(data->state == LV_INDEV_STATE_PRESSED) indev_proc_press(&i->proc); - else indev_proc_release(&i->proc); - - if(indev_reset_check(&i->proc)) return; - - i->proc.types.pointer.last_point.x = i->proc.types.pointer.act_point.x; - i->proc.types.pointer.last_point.y = i->proc.types.pointer.act_point.y; -} - -/** - * Process the pressed state of LV_INDEV_TYPE_POINTER input devices - * @param indev pointer to an input device 'proc' - * @return LV_RES_OK: no indev reset required; LV_RES_INV: indev reset is required - */ -static void indev_proc_press(_lv_indev_proc_t * proc) -{ - LV_LOG_INFO("pressed at x:%d y:%d", proc->types.pointer.act_point.x, proc->types.pointer.act_point.y); - indev_obj_act = proc->types.pointer.act_obj; - - if(proc->wait_until_release != 0) return; - - lv_disp_t * disp = indev_act->driver->disp; - bool new_obj_searched = false; - - /*If there is no last object then search*/ - if(indev_obj_act == NULL) { - indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point); - if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp), - &proc->types.pointer.act_point); - if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp), - &proc->types.pointer.act_point); - new_obj_searched = true; - } - /*If there is last object but it is not scrolled and not protected also search*/ - else if(proc->types.pointer.scroll_obj == NULL && - lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_PRESS_LOCK) == false) { - indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point); - if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp), - &proc->types.pointer.act_point); - if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp), - &proc->types.pointer.act_point); - new_obj_searched = true; - } - - /*The last object might have scroll throw. Stop it manually*/ - if(new_obj_searched && proc->types.pointer.last_obj) { - proc->types.pointer.scroll_throw_vect.x = 0; - proc->types.pointer.scroll_throw_vect.y = 0; - _lv_indev_scroll_throw_handler(proc); - if(indev_reset_check(proc)) return; - } - - /*If a new object was found reset some variables and send a pressed event handler*/ - if(indev_obj_act != proc->types.pointer.act_obj) { - proc->types.pointer.last_point.x = proc->types.pointer.act_point.x; - proc->types.pointer.last_point.y = proc->types.pointer.act_point.y; - - /*If a new object found the previous was lost, so send a Call the ancestor's event handler*/ - if(proc->types.pointer.act_obj != NULL) { - /*Save the obj because in special cases `act_obj` can change in the Call the ancestor's event handler function*/ - lv_obj_t * last_obj = proc->types.pointer.act_obj; - - lv_event_send(last_obj, LV_EVENT_PRESS_LOST, indev_act); - if(indev_reset_check(proc)) return; - } - - proc->types.pointer.act_obj = indev_obj_act; /*Save the pressed object*/ - proc->types.pointer.last_obj = indev_obj_act; - - if(indev_obj_act != NULL) { - /*Save the time when the obj pressed to count long press time.*/ - proc->pr_timestamp = lv_tick_get(); - proc->long_pr_sent = 0; - proc->types.pointer.scroll_sum.x = 0; - proc->types.pointer.scroll_sum.y = 0; - proc->types.pointer.scroll_dir = LV_DIR_NONE; - proc->types.pointer.gesture_dir = LV_DIR_NONE; - proc->types.pointer.gesture_sent = 0; - proc->types.pointer.gesture_sum.x = 0; - proc->types.pointer.gesture_sum.y = 0; - proc->types.pointer.vect.x = 0; - proc->types.pointer.vect.y = 0; - - /*Call the ancestor's event handler about the press*/ - lv_event_send(indev_obj_act, LV_EVENT_PRESSED, indev_act); - if(indev_reset_check(proc)) return; - - if(indev_act->proc.wait_until_release) return; - - /*Handle focus*/ - indev_click_focus(&indev_act->proc); - if(indev_reset_check(proc)) return; - - } - } - - /*Calculate the vector and apply a low pass filter: new value = 0.5 * old_value + 0.5 * new_value*/ - proc->types.pointer.vect.x = proc->types.pointer.act_point.x - proc->types.pointer.last_point.x; - proc->types.pointer.vect.y = proc->types.pointer.act_point.y - proc->types.pointer.last_point.y; - - proc->types.pointer.scroll_throw_vect.x = (proc->types.pointer.scroll_throw_vect.x + proc->types.pointer.vect.x) / 2; - proc->types.pointer.scroll_throw_vect.y = (proc->types.pointer.scroll_throw_vect.y + proc->types.pointer.vect.y) / 2; - - proc->types.pointer.scroll_throw_vect_ori = proc->types.pointer.scroll_throw_vect; - - if(indev_obj_act) { - lv_event_send(indev_obj_act, LV_EVENT_PRESSING, indev_act); - if(indev_reset_check(proc)) return; - - if(indev_act->proc.wait_until_release) return; - - _lv_indev_scroll_handler(proc); - if(indev_reset_check(proc)) return; - indev_gesture(proc); - if(indev_reset_check(proc)) return; - - /*If there is no scrolling then check for long press time*/ - if(proc->types.pointer.scroll_obj == NULL && proc->long_pr_sent == 0) { - /*Call the ancestor's event handler about the long press if enough time elapsed*/ - if(lv_tick_elaps(proc->pr_timestamp) > indev_act->driver->long_press_time) { - lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, indev_act); - if(indev_reset_check(proc)) return; - - /*Mark the Call the ancestor's event handler sending to do not send it again*/ - proc->long_pr_sent = 1; - - /*Save the long press time stamp for the long press repeat handler*/ - proc->longpr_rep_timestamp = lv_tick_get(); - } - } - - /*Send long press repeated Call the ancestor's event handler*/ - if(proc->types.pointer.scroll_obj == NULL && proc->long_pr_sent == 1) { - /*Call the ancestor's event handler about the long press repeat if enough time elapsed*/ - if(lv_tick_elaps(proc->longpr_rep_timestamp) > indev_act->driver->long_press_repeat_time) { - lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED_REPEAT, indev_act); - if(indev_reset_check(proc)) return; - proc->longpr_rep_timestamp = lv_tick_get(); - } - } - } -} - -/** - * Process the released state of LV_INDEV_TYPE_POINTER input devices - * @param proc pointer to an input device 'proc' - */ -static void indev_proc_release(_lv_indev_proc_t * proc) -{ - if(proc->wait_until_release != 0) { - lv_event_send(proc->types.pointer.act_obj, LV_EVENT_PRESS_LOST, indev_act); - if(indev_reset_check(proc)) return; - - proc->types.pointer.act_obj = NULL; - proc->types.pointer.last_obj = NULL; - proc->pr_timestamp = 0; - proc->longpr_rep_timestamp = 0; - proc->wait_until_release = 0; - } - indev_obj_act = proc->types.pointer.act_obj; - lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj; - - /*Forget the act obj and send a released Call the ancestor's event handler*/ - if(indev_obj_act) { - LV_LOG_INFO("released"); - - /*Send RELEASE Call the ancestor's event handler and event*/ - lv_event_send(indev_obj_act, LV_EVENT_RELEASED, indev_act); - if(indev_reset_check(proc)) return; - - /*Send CLICK if no scrolling*/ - if(scroll_obj == NULL) { - if(proc->long_pr_sent == 0) { - lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, indev_act); - if(indev_reset_check(proc)) return; - } - - lv_event_send(indev_obj_act, LV_EVENT_CLICKED, indev_act); - if(indev_reset_check(proc)) return; - } - - proc->types.pointer.act_obj = NULL; - proc->pr_timestamp = 0; - proc->longpr_rep_timestamp = 0; - - - /*Get the transformed vector with this object*/ - if(scroll_obj) { - int16_t angle = 0; - int16_t zoom = 256; - lv_point_t pivot = { 0, 0 }; - lv_obj_t * parent = scroll_obj; - while(parent) { - angle += lv_obj_get_style_transform_angle(parent, 0); - zoom *= (lv_obj_get_style_transform_zoom(parent, 0) / 256); - parent = lv_obj_get_parent(parent); - } - - if(angle != 0 || zoom != LV_IMG_ZOOM_NONE) { - angle = -angle; - zoom = (256 * 256) / zoom; - lv_point_transform(&proc->types.pointer.scroll_throw_vect, angle, zoom, &pivot); - lv_point_transform(&proc->types.pointer.scroll_throw_vect_ori, angle, zoom, &pivot); - } - } - - } - - /*The reset can be set in the Call the ancestor's event handler function. - * In case of reset query ignore the remaining parts.*/ - if(scroll_obj) { - _lv_indev_scroll_throw_handler(proc); - if(indev_reset_check(proc)) return; - } -} - -/** - * Process a new point from LV_INDEV_TYPE_BUTTON input device - * @param i pointer to an input device - * @param data pointer to the data read from the input device - * Reset input device if a reset query has been sent to it - * @param indev pointer to an input device - */ -static void indev_proc_reset_query_handler(lv_indev_t * indev) -{ - if(indev->proc.reset_query) { - indev->proc.types.pointer.act_obj = NULL; - indev->proc.types.pointer.last_obj = NULL; - indev->proc.types.pointer.scroll_obj = NULL; - indev->proc.long_pr_sent = 0; - indev->proc.pr_timestamp = 0; - indev->proc.longpr_rep_timestamp = 0; - indev->proc.types.pointer.scroll_sum.x = 0; - indev->proc.types.pointer.scroll_sum.y = 0; - indev->proc.types.pointer.scroll_dir = LV_DIR_NONE; - indev->proc.types.pointer.scroll_throw_vect.x = 0; - indev->proc.types.pointer.scroll_throw_vect.y = 0; - indev->proc.types.pointer.gesture_sum.x = 0; - indev->proc.types.pointer.gesture_sum.y = 0; - indev->proc.reset_query = 0; - indev_obj_act = NULL; - } -} - -/** - * Handle focus/defocus on click for POINTER input devices - * @param proc pointer to the state of the indev - */ -static void indev_click_focus(_lv_indev_proc_t * proc) -{ - /*Handle click focus*/ - if(lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_CLICK_FOCUSABLE) == false || - proc->types.pointer.last_pressed == indev_obj_act) { - return; - } - - lv_group_t * g_act = lv_obj_get_group(indev_obj_act); - lv_group_t * g_prev = proc->types.pointer.last_pressed ? lv_obj_get_group(proc->types.pointer.last_pressed) : NULL; - - /*If both the last and act. obj. are in the same group (or have no group)*/ - if(g_act == g_prev) { - /*The objects are in a group*/ - if(g_act) { - lv_group_focus_obj(indev_obj_act); - if(indev_reset_check(proc)) return; - } - /*The object are not in group*/ - else { - if(proc->types.pointer.last_pressed) { - lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act); - if(indev_reset_check(proc)) return; - } - - lv_event_send(indev_obj_act, LV_EVENT_FOCUSED, indev_act); - if(indev_reset_check(proc)) return; - } - } - /*The object are not in the same group (in different groups or one has no group)*/ - else { - /*If the prev. obj. is not in a group then defocus it.*/ - if(g_prev == NULL && proc->types.pointer.last_pressed) { - lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act); - if(indev_reset_check(proc)) return; - } - /*Focus on a non-group object*/ - else { - if(proc->types.pointer.last_pressed) { - /*If the prev. object also wasn't in a group defocus it*/ - if(g_prev == NULL) { - lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act); - if(indev_reset_check(proc)) return; - } - /*If the prev. object also was in a group at least "LEAVE" it instead of defocus*/ - else { - lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_LEAVE, indev_act); - if(indev_reset_check(proc)) return; - } - } - } - - /*Focus to the act. in its group*/ - if(g_act) { - lv_group_focus_obj(indev_obj_act); - if(indev_reset_check(proc)) return; - } - else { - lv_event_send(indev_obj_act, LV_EVENT_FOCUSED, indev_act); - if(indev_reset_check(proc)) return; - } - } - proc->types.pointer.last_pressed = indev_obj_act; -} - -/** -* Handle the gesture of indev_proc_p->types.pointer.act_obj -* @param indev pointer to an input device state -*/ -void indev_gesture(_lv_indev_proc_t * proc) -{ - - if(proc->types.pointer.scroll_obj) return; - if(proc->types.pointer.gesture_sent) return; - - lv_obj_t * gesture_obj = proc->types.pointer.act_obj; - - /*If gesture parent is active check recursively the gesture attribute*/ - while(gesture_obj && lv_obj_has_flag(gesture_obj, LV_OBJ_FLAG_GESTURE_BUBBLE)) { - gesture_obj = lv_obj_get_parent(gesture_obj); - } - - if(gesture_obj == NULL) return; - - if((LV_ABS(proc->types.pointer.vect.x) < indev_act->driver->gesture_min_velocity) && - (LV_ABS(proc->types.pointer.vect.y) < indev_act->driver->gesture_min_velocity)) { - proc->types.pointer.gesture_sum.x = 0; - proc->types.pointer.gesture_sum.y = 0; - } - - /*Count the movement by gesture*/ - proc->types.pointer.gesture_sum.x += proc->types.pointer.vect.x; - proc->types.pointer.gesture_sum.y += proc->types.pointer.vect.y; - - if((LV_ABS(proc->types.pointer.gesture_sum.x) > indev_act->driver->gesture_limit) || - (LV_ABS(proc->types.pointer.gesture_sum.y) > indev_act->driver->gesture_limit)) { - - proc->types.pointer.gesture_sent = 1; - - if(LV_ABS(proc->types.pointer.gesture_sum.x) > LV_ABS(proc->types.pointer.gesture_sum.y)) { - if(proc->types.pointer.gesture_sum.x > 0) - proc->types.pointer.gesture_dir = LV_DIR_RIGHT; - else - proc->types.pointer.gesture_dir = LV_DIR_LEFT; - } - else { - if(proc->types.pointer.gesture_sum.y > 0) - proc->types.pointer.gesture_dir = LV_DIR_BOTTOM; - else - proc->types.pointer.gesture_dir = LV_DIR_TOP; - } - - lv_event_send(gesture_obj, LV_EVENT_GESTURE, indev_act); - if(indev_reset_check(proc)) return; - } -} - -/** - * Checks if the reset_query flag has been set. If so, perform necessary global indev cleanup actions - * @param proc pointer to an input device 'proc' - * @return true if indev query should be immediately truncated. - */ -static bool indev_reset_check(_lv_indev_proc_t * proc) -{ - if(proc->reset_query) { - indev_obj_act = NULL; - } - - return proc->reset_query ? true : false; -} diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_indev.h b/lib/libesp32_lvgl/lvgl/src/core/lv_indev.h deleted file mode 100644 index a98df86ef..000000000 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_indev.h +++ /dev/null @@ -1,176 +0,0 @@ -/** - * @file lv_indev.h - * - */ - -#ifndef LV_INDEV_H -#define LV_INDEV_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "lv_obj.h" -#include "../hal/lv_hal_indev.h" -#include "lv_group.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Called periodically to read the input devices - * @param timer pointer to a timer to read - */ -void lv_indev_read_timer_cb(lv_timer_t * timer); - -/** - * Enable or disable one or all input devices (default enabled) - * @param indev pointer to an input device or NULL to enable/disable all of them - * @param en true to enable, false to disable - */ -void lv_indev_enable(lv_indev_t * indev, bool en); - -/** - * Get the currently processed input device. Can be used in action functions too. - * @return pointer to the currently processed input device or NULL if no input device processing - * right now - */ -lv_indev_t * lv_indev_get_act(void); - -/** - * Get the type of an input device - * @param indev pointer to an input device - * @return the type of the input device from `lv_hal_indev_type_t` (`LV_INDEV_TYPE_...`) - */ -lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev); - -/** - * Reset one or all input devices - * @param indev pointer to an input device to reset or NULL to reset all of them - * @param obj pointer to an object which triggers the reset. - */ -void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj); - -/** - * Reset the long press state of an input device - * @param indev pointer to an input device - */ -void lv_indev_reset_long_press(lv_indev_t * indev); - -/** - * Set a cursor for a pointer input device (for LV_INPUT_TYPE_POINTER and LV_INPUT_TYPE_BUTTON) - * @param indev pointer to an input device - * @param cur_obj pointer to an object to be used as cursor - */ -void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj); - -/** - * Set a destination group for a keypad input device (for LV_INDEV_TYPE_KEYPAD) - * @param indev pointer to an input device - * @param group point to a group - */ -void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group); - -/** - * Set the an array of points for LV_INDEV_TYPE_BUTTON. - * These points will be assigned to the buttons to press a specific point on the screen - * @param indev pointer to an input device - * @param group point to a group - */ -void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[]); - -/** - * Get the last point of an input device (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON) - * @param indev pointer to an input device - * @param point pointer to a point to store the result - */ -void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point); - -/** -* Get the current gesture direct -* @param indev pointer to an input device -* @return current gesture direct -*/ -lv_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev); - -/** - * Get the last pressed key of an input device (for LV_INDEV_TYPE_KEYPAD) - * @param indev pointer to an input device - * @return the last pressed key (0 on error) - */ -uint32_t lv_indev_get_key(const lv_indev_t * indev); - -/** - * Check the current scroll direction of an input device (for LV_INDEV_TYPE_POINTER and - * LV_INDEV_TYPE_BUTTON) - * @param indev pointer to an input device - * @return LV_DIR_NONE: no scrolling now - * LV_DIR_HOR/VER - */ -lv_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev); - -/** - * Get the currently scrolled object (for LV_INDEV_TYPE_POINTER and - * LV_INDEV_TYPE_BUTTON) - * @param indev pointer to an input device - * @return pointer to the currently scrolled object or NULL if no scrolling by this indev - */ -lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev); - -/** - * Get the movement vector of an input device (for LV_INDEV_TYPE_POINTER and - * LV_INDEV_TYPE_BUTTON) - * @param indev pointer to an input device - * @param point pointer to a point to store the types.pointer.vector - */ -void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point); - -/** - * Do nothing until the next release - * @param indev pointer to an input device - */ -void lv_indev_wait_release(lv_indev_t * indev); - -/** - * Gets a pointer to the currently active object in the currently processed input device. - * @return pointer to currently active object or NULL if no active object - */ -lv_obj_t * lv_indev_get_obj_act(void); - -/** - * Get a pointer to the indev read timer to - * modify its parameters with `lv_timer_...` functions. - * @param indev pointer to an input device - * @return pointer to the indev read refresher timer. (NULL on error) - */ -lv_timer_t * lv_indev_get_read_timer(lv_disp_t * indev); - -/** - * Search the most top, clickable object by a point - * @param obj pointer to a start object, typically the screen - * @param point pointer to a point for searching the most top child - * @return pointer to the found object or NULL if there was no suitable object - */ -lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point); - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_INDEV_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj.c index f0f4d5500..29708ea1f 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj.c @@ -7,41 +7,21 @@ * INCLUDES *********************/ #include "lv_obj.h" -#include "lv_indev.h" +#include "../indev/lv_indev.h" +#include "../indev/lv_indev_private.h" #include "lv_refr.h" #include "lv_group.h" -#include "lv_disp.h" -#include "lv_theme.h" +#include "../display/lv_display.h" +#include "../display/lv_display_private.h" +#include "../themes/lv_theme.h" #include "../misc/lv_assert.h" -#include "../draw/lv_draw.h" -#include "../misc/lv_anim.h" -#include "../misc/lv_timer.h" -#include "../misc/lv_async.h" -#include "../misc/lv_fs.h" -#include "../misc/lv_gc.h" #include "../misc/lv_math.h" #include "../misc/lv_log.h" -#include "../hal/lv_hal.h" -#include "../extra/lv_extra.h" +#include "../tick/lv_tick.h" +#include "../stdlib/lv_string.h" #include #include -#if LV_USE_GPU_STM32_DMA2D - #include "../draw/stm32_dma2d/lv_gpu_stm32_dma2d.h" -#endif - -#if LV_USE_GPU_RA6M3_G2D - #include "../draw/renesas/lv_gpu_d2_ra6m3.h" -#endif - -#if LV_USE_GPU_SWM341_DMA2D - #include "../draw/swm341_dma2d/lv_gpu_swm341_dma2d.h" -#endif - -#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT - #include "../draw/nxp/pxp/lv_gpu_nxp_pxp.h" -#endif - /********************* * DEFINES *********************/ @@ -61,15 +41,33 @@ static void lv_obj_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void lv_obj_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void lv_obj_draw(lv_event_t * e); static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e); -static void draw_scrollbar(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx); -static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc); +static void draw_scrollbar(lv_obj_t * obj, lv_layer_t * layer); +static lv_result_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc); static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find); -static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state); +static void update_obj_state(lv_obj_t * obj, lv_state_t new_state); +#if LV_USE_OBJ_PROPERTY + static lv_result_t lv_obj_set_any(lv_obj_t *, lv_prop_id_t, const lv_property_t *); + static lv_result_t lv_obj_get_any(const lv_obj_t *, lv_prop_id_t, lv_property_t *); +#endif /********************** * STATIC VARIABLES **********************/ -static bool lv_initialized = false; +#if LV_USE_OBJ_PROPERTY +static const lv_property_ops_t properties[] = { + { + .id = LV_PROPERTY_OBJ_PARENT, + .setter = lv_obj_set_parent, + .getter = lv_obj_get_parent, + }, + { + .id = LV_PROPERTY_ID_ANY, + .setter = lv_obj_set_any, + .getter = lv_obj_get_any, + } +}; +#endif + const lv_obj_class_t lv_obj_class = { .constructor_cb = lv_obj_constructor, .destructor_cb = lv_obj_destructor, @@ -80,6 +78,13 @@ const lv_obj_class_t lv_obj_class = { .group_def = LV_OBJ_CLASS_GROUP_DEF_FALSE, .instance_size = (sizeof(lv_obj_t)), .base_class = NULL, + .name = "obj", +#if LV_USE_OBJ_PROPERTY + .prop_index_start = LV_PROPERTY_OBJ_START, + .prop_index_end = LV_PROPERTY_OBJ_END, + .properties = properties, + .properties_count = sizeof(properties) / sizeof(properties[0]), +#endif }; /********************** @@ -90,126 +95,6 @@ const lv_obj_class_t lv_obj_class = { * GLOBAL FUNCTIONS **********************/ -bool lv_is_initialized(void) -{ - return lv_initialized; -} - -void lv_init(void) -{ - /*Do nothing if already initialized*/ - if(lv_initialized) { - LV_LOG_WARN("lv_init: already inited"); - return; - } - - LV_LOG_INFO("begin"); - - /*Initialize the misc modules*/ - lv_mem_init(); - - _lv_timer_core_init(); - - _lv_fs_init(); - - _lv_anim_core_init(); - - _lv_group_init(); - - lv_draw_init(); - -#if LV_USE_GPU_STM32_DMA2D - /*Initialize DMA2D GPU*/ - lv_draw_stm32_dma2d_init(); -#endif - -#if LV_USE_GPU_RA6M3_G2D - /*Initialize G2D GPU*/ - lv_draw_ra6m3_g2d_init(); -#endif - -#if LV_USE_GPU_SWM341_DMA2D - /*Initialize DMA2D GPU*/ - lv_draw_swm341_dma2d_init(); -#endif - -#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT - PXP_COND_STOP(!lv_gpu_nxp_pxp_init(), "PXP init failed."); -#endif - - _lv_obj_style_init(); - _lv_ll_init(&LV_GC_ROOT(_lv_disp_ll), sizeof(lv_disp_t)); - _lv_ll_init(&LV_GC_ROOT(_lv_indev_ll), sizeof(lv_indev_t)); - - /*Initialize the screen refresh system*/ - _lv_refr_init(); - - _lv_img_decoder_init(); -#if LV_IMG_CACHE_DEF_SIZE - lv_img_cache_set_size(LV_IMG_CACHE_DEF_SIZE); -#endif - /*Test if the IDE has UTF-8 encoding*/ - const char * txt = "Á"; - - const uint8_t * txt_u8 = (uint8_t *)txt; - if(txt_u8[0] != 0xc3 || txt_u8[1] != 0x81 || txt_u8[2] != 0x00) { - LV_LOG_WARN("The strings have no UTF-8 encoding. Non-ASCII characters won't be displayed."); - } - - uint32_t endianess_test = 0x11223344; - uint8_t * endianess_test_p = (uint8_t *) &endianess_test; - bool big_endian = endianess_test_p[0] == 0x11 ? true : false; - - if(big_endian) { - LV_ASSERT_MSG(LV_BIG_ENDIAN_SYSTEM == 1, - "It's a big endian system but LV_BIG_ENDIAN_SYSTEM is not enabled in lv_conf.h"); - } - else { - LV_ASSERT_MSG(LV_BIG_ENDIAN_SYSTEM == 0, - "It's a little endian system but LV_BIG_ENDIAN_SYSTEM is enabled in lv_conf.h"); - } - -#if LV_USE_ASSERT_MEM_INTEGRITY - LV_LOG_WARN("Memory integrity checks are enabled via LV_USE_ASSERT_MEM_INTEGRITY which makes LVGL much slower"); -#endif - -#if LV_USE_ASSERT_OBJ - LV_LOG_WARN("Object sanity checks are enabled via LV_USE_ASSERT_OBJ which makes LVGL much slower"); -#endif - -#if LV_USE_ASSERT_STYLE - LV_LOG_WARN("Style sanity checks are enabled that uses more RAM"); -#endif - -#if LV_LOG_LEVEL == LV_LOG_LEVEL_TRACE - LV_LOG_WARN("Log level is set to 'Trace' which makes LVGL much slower"); -#endif - - lv_extra_init(); - - lv_initialized = true; - - LV_LOG_TRACE("finished"); -} - -#if LV_ENABLE_GC || !LV_MEM_CUSTOM - -void lv_deinit(void) -{ - _lv_gc_clear_roots(); - - lv_disp_set_default(NULL); - lv_mem_deinit(); - lv_initialized = false; - - LV_LOG_INFO("lv_deinit done"); - -#if LV_USE_LOG - lv_log_register_print_cb(NULL); -#endif -} -#endif - lv_obj_t * lv_obj_create(lv_obj_t * parent) { LV_LOG_INFO("begin"); @@ -263,7 +148,7 @@ void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f) } } -void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f) +void lv_obj_remove_flag(lv_obj_t * obj, lv_obj_flag_t f) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -291,26 +176,43 @@ void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f) } +void lv_obj_update_flag(lv_obj_t * obj, lv_obj_flag_t f, bool v) +{ + if(v) lv_obj_add_flag(obj, f); + else lv_obj_remove_flag(obj, f); +} + void lv_obj_add_state(lv_obj_t * obj, lv_state_t state) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_state_t new_state = obj->state | state; if(obj->state != new_state) { - lv_obj_set_state(obj, new_state); + + if(new_state & LV_STATE_DISABLED) { + lv_indev_reset(NULL, obj); + } + + update_obj_state(obj, new_state); } } -void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state) +void lv_obj_remove_state(lv_obj_t * obj, lv_state_t state) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_state_t new_state = obj->state & (~state); if(obj->state != new_state) { - lv_obj_set_state(obj, new_state); + update_obj_state(obj, new_state); } } +void lv_obj_set_state(lv_obj_t * obj, lv_state_t state, bool v) +{ + if(v) lv_obj_add_state(obj, state); + else lv_obj_remove_state(obj, state); +} + /*======================= * Getter functions *======================*/ @@ -319,14 +221,14 @@ bool lv_obj_has_flag(const lv_obj_t * obj, lv_obj_flag_t f) { LV_ASSERT_OBJ(obj, MY_CLASS); - return (obj->flags & f) == f ? true : false; + return (obj->flags & f) == f; } bool lv_obj_has_flag_any(const lv_obj_t * obj, lv_obj_flag_t f) { LV_ASSERT_OBJ(obj, MY_CLASS); - return (obj->flags & f) ? true : false; + return !!(obj->flags & f); } lv_state_t lv_obj_get_state(const lv_obj_t * obj) @@ -340,10 +242,10 @@ bool lv_obj_has_state(const lv_obj_t * obj, lv_state_t state) { LV_ASSERT_OBJ(obj, MY_CLASS); - return obj->state & state ? true : false; + return !!(obj->state & state); } -void * lv_obj_get_group(const lv_obj_t * obj) +lv_group_t * lv_obj_get_group(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -360,14 +262,10 @@ void lv_obj_allocate_spec_attr(lv_obj_t * obj) LV_ASSERT_OBJ(obj, MY_CLASS); if(obj->spec_attr == NULL) { - static uint32_t x = 0; - x++; - obj->spec_attr = lv_mem_alloc(sizeof(_lv_obj_spec_attr_t)); + obj->spec_attr = lv_malloc_zeroed(sizeof(_lv_obj_spec_attr_t)); LV_ASSERT_MALLOC(obj->spec_attr); if(obj->spec_attr == NULL) return; - lv_memset_00(obj->spec_attr, sizeof(_lv_obj_spec_attr_t)); - obj->spec_attr->scroll_dir = LV_DIR_ALL; obj->spec_attr->scrollbar_mode = LV_SCROLLBAR_MODE_AUTO; } @@ -376,7 +274,7 @@ void lv_obj_allocate_spec_attr(lv_obj_t * obj) bool lv_obj_check_type(const lv_obj_t * obj, const lv_obj_class_t * class_p) { if(obj == NULL) return false; - return obj->class_p == class_p ? true : false; + return obj->class_p == class_p; } bool lv_obj_has_class(const lv_obj_t * obj, const lv_obj_class_t * class_p) @@ -397,7 +295,7 @@ const lv_obj_class_t * lv_obj_get_class(const lv_obj_t * obj) bool lv_obj_is_valid(const lv_obj_t * obj) { - lv_disp_t * disp = lv_disp_get_next(NULL); + lv_display_t * disp = lv_display_get_next(NULL); while(disp) { uint32_t i; for(i = 0; i < disp->screen_cnt; i++) { @@ -406,7 +304,7 @@ bool lv_obj_is_valid(const lv_obj_t * obj) if(found) return true; } - disp = lv_disp_get_next(disp); + disp = lv_display_get_next(disp); } return false; @@ -423,8 +321,8 @@ static void lv_obj_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) lv_obj_t * parent = obj->parent; if(parent) { - lv_coord_t sl = lv_obj_get_scroll_left(parent); - lv_coord_t st = lv_obj_get_scroll_top(parent); + int32_t sl = lv_obj_get_scroll_left(parent); + int32_t st = lv_obj_get_scroll_top(parent); obj->coords.y1 = parent->coords.y1 + lv_obj_get_style_pad_top(parent, LV_PART_MAIN) - st; obj->coords.y2 = obj->coords.y1 - 1; @@ -444,6 +342,10 @@ static void lv_obj_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) obj->flags |= LV_OBJ_FLAG_SCROLL_WITH_ARROW; if(parent) obj->flags |= LV_OBJ_FLAG_GESTURE_BUBBLE; +#if LV_USE_OBJ_ID + lv_obj_assign_id(class_p, obj); +#endif + LV_TRACE_OBJ_CREATE("finished"); } @@ -459,7 +361,7 @@ static void lv_obj_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) lv_obj_enable_style_refresh(true); /*Remove the animations from this object*/ - lv_anim_del(obj, NULL); + lv_anim_delete(obj, NULL); /*Delete from the group*/ lv_group_t * group = lv_obj_get_group(obj); @@ -467,23 +369,25 @@ static void lv_obj_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) if(obj->spec_attr) { if(obj->spec_attr->children) { - lv_mem_free(obj->spec_attr->children); + lv_free(obj->spec_attr->children); obj->spec_attr->children = NULL; } - if(obj->spec_attr->event_dsc) { - lv_mem_free(obj->spec_attr->event_dsc); - obj->spec_attr->event_dsc = NULL; - } - lv_mem_free(obj->spec_attr); + lv_event_remove_all(&obj->spec_attr->event_list); + + lv_free(obj->spec_attr); obj->spec_attr = NULL; } + +#if LV_USE_OBJ_ID + lv_obj_free_id(obj); +#endif } static void lv_obj_draw(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); if(code == LV_EVENT_COVER_CHECK) { lv_cover_check_info_t * info = lv_event_get_param(e); if(info->res == LV_COVER_RES_MASKED) return; @@ -493,15 +397,12 @@ static void lv_obj_draw(lv_event_t * e) } /*Most trivial test. Is the mask fully IN the object? If no it surely doesn't cover it*/ - lv_coord_t r = lv_obj_get_style_radius(obj, LV_PART_MAIN); - lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN); - lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN); + int32_t r = lv_obj_get_style_radius(obj, LV_PART_MAIN); + int32_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN); + int32_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN); lv_area_t coords; lv_area_copy(&coords, &obj->coords); - coords.x1 -= w; - coords.x2 += w; - coords.y1 -= h; - coords.y2 += h; + lv_area_increase(&coords, w, h); if(_lv_area_is_in(info->area, &coords, r) == false) { info->res = LV_COVER_RES_NOT_COVER; @@ -518,118 +419,70 @@ static void lv_obj_draw(lv_event_t * e) return; } + if(lv_obj_get_style_bg_grad_dir(obj, 0) != LV_GRAD_DIR_NONE) { + if(lv_obj_get_style_bg_grad_opa(obj, 0) < LV_OPA_MAX) { + info->res = LV_COVER_RES_NOT_COVER; + return; + } + const lv_grad_dsc_t * grad_dsc = lv_obj_get_style_bg_grad(obj, 0); + if(grad_dsc) { + uint32_t i; + for(i = 0; i < grad_dsc->stops_count; i++) { + if(grad_dsc->stops[i].opa < LV_OPA_MAX) { + info->res = LV_COVER_RES_NOT_COVER; + return; + } + } + } + } info->res = LV_COVER_RES_COVER; } else if(code == LV_EVENT_DRAW_MAIN) { - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); lv_draw_rect_dsc_t draw_dsc; lv_draw_rect_dsc_init(&draw_dsc); + + lv_obj_init_draw_rect_dsc(obj, LV_PART_MAIN, &draw_dsc); /*If the border is drawn later disable loading its properties*/ if(lv_obj_get_style_border_post(obj, LV_PART_MAIN)) { draw_dsc.border_post = 1; } - lv_obj_init_draw_rect_dsc(obj, LV_PART_MAIN, &draw_dsc); - lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN); - lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN); + int32_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN); + int32_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN); lv_area_t coords; lv_area_copy(&coords, &obj->coords); - coords.x1 -= w; - coords.x2 += w; - coords.y1 -= h; - coords.y2 += h; + lv_area_increase(&coords, w, h); - lv_obj_draw_part_dsc_t part_dsc; - lv_obj_draw_dsc_init(&part_dsc, draw_ctx); - part_dsc.class_p = MY_CLASS; - part_dsc.type = LV_OBJ_DRAW_PART_RECTANGLE; - part_dsc.rect_dsc = &draw_dsc; - part_dsc.draw_area = &coords; - part_dsc.part = LV_PART_MAIN; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc); - -#if LV_DRAW_COMPLEX - /*With clip corner enabled draw the bg img separately to make it clipped*/ - bool clip_corner = (lv_obj_get_style_clip_corner(obj, LV_PART_MAIN) && draw_dsc.radius != 0) ? true : false; - const void * bg_img_src = draw_dsc.bg_img_src; - if(clip_corner) { - draw_dsc.bg_img_src = NULL; - } -#endif - - lv_draw_rect(draw_ctx, &draw_dsc, &coords); - - -#if LV_DRAW_COMPLEX - if(clip_corner) { - lv_draw_mask_radius_param_t * mp = lv_mem_buf_get(sizeof(lv_draw_mask_radius_param_t)); - lv_draw_mask_radius_init(mp, &obj->coords, draw_dsc.radius, false); - /*Add the mask and use `obj+8` as custom id. Don't use `obj` directly because it might be used by the user*/ - lv_draw_mask_add(mp, obj + 8); - - if(bg_img_src) { - draw_dsc.bg_opa = LV_OPA_TRANSP; - draw_dsc.border_opa = LV_OPA_TRANSP; - draw_dsc.outline_opa = LV_OPA_TRANSP; - draw_dsc.shadow_opa = LV_OPA_TRANSP; - draw_dsc.bg_img_src = bg_img_src; - lv_draw_rect(draw_ctx, &draw_dsc, &coords); - } - - } -#endif - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc); + lv_draw_rect(layer, &draw_dsc, &coords); } else if(code == LV_EVENT_DRAW_POST) { - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); - draw_scrollbar(obj, draw_ctx); - -#if LV_DRAW_COMPLEX - if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) { - lv_draw_mask_radius_param_t * param = lv_draw_mask_remove_custom(obj + 8); - if(param) { - lv_draw_mask_free_param(param); - lv_mem_buf_release(param); - } - } -#endif + lv_layer_t * layer = lv_event_get_layer(e); + draw_scrollbar(obj, layer); /*If the border is drawn later disable loading other properties*/ if(lv_obj_get_style_border_post(obj, LV_PART_MAIN)) { lv_draw_rect_dsc_t draw_dsc; lv_draw_rect_dsc_init(&draw_dsc); draw_dsc.bg_opa = LV_OPA_TRANSP; - draw_dsc.bg_img_opa = LV_OPA_TRANSP; + draw_dsc.bg_image_opa = LV_OPA_TRANSP; draw_dsc.outline_opa = LV_OPA_TRANSP; draw_dsc.shadow_opa = LV_OPA_TRANSP; lv_obj_init_draw_rect_dsc(obj, LV_PART_MAIN, &draw_dsc); - lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN); - lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN); + int32_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN); + int32_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN); lv_area_t coords; lv_area_copy(&coords, &obj->coords); - coords.x1 -= w; - coords.x2 += w; - coords.y1 -= h; - coords.y2 += h; + lv_area_increase(&coords, w, h); - lv_obj_draw_part_dsc_t part_dsc; - lv_obj_draw_dsc_init(&part_dsc, draw_ctx); - part_dsc.class_p = MY_CLASS; - part_dsc.type = LV_OBJ_DRAW_PART_BORDER_POST; - part_dsc.rect_dsc = &draw_dsc; - part_dsc.draw_area = &coords; - part_dsc.part = LV_PART_MAIN; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc); - - lv_draw_rect(draw_ctx, &draw_dsc, &coords); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc); + lv_draw_rect(layer, &draw_dsc, &coords); } } } -static void draw_scrollbar(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) +static void draw_scrollbar(lv_obj_t * obj, lv_layer_t * layer) { lv_area_t hor_area; @@ -639,28 +492,16 @@ static void draw_scrollbar(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) if(lv_area_get_size(&hor_area) <= 0 && lv_area_get_size(&ver_area) <= 0) return; lv_draw_rect_dsc_t draw_dsc; - lv_res_t sb_res = scrollbar_init_draw_dsc(obj, &draw_dsc); - if(sb_res != LV_RES_OK) return; - - lv_obj_draw_part_dsc_t part_dsc; - lv_obj_draw_dsc_init(&part_dsc, draw_ctx); - part_dsc.class_p = MY_CLASS; - part_dsc.type = LV_OBJ_DRAW_PART_SCROLLBAR; - part_dsc.rect_dsc = &draw_dsc; - part_dsc.part = LV_PART_SCROLLBAR; + lv_result_t sb_res = scrollbar_init_draw_dsc(obj, &draw_dsc); + if(sb_res != LV_RESULT_OK) return; if(lv_area_get_size(&hor_area) > 0) { - part_dsc.draw_area = &hor_area; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc); - lv_draw_rect(draw_ctx, &draw_dsc, &hor_area); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc); + draw_dsc.base.id1 = 0; + lv_draw_rect(layer, &draw_dsc, &hor_area); } if(lv_area_get_size(&ver_area) > 0) { - part_dsc.draw_area = &ver_area; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc); - part_dsc.draw_area = &ver_area; - lv_draw_rect(draw_ctx, &draw_dsc, &ver_area); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc); + draw_dsc.base.id1 = 1; + lv_draw_rect(layer, &draw_dsc, &ver_area); } } @@ -668,9 +509,9 @@ static void draw_scrollbar(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) * Initialize the draw descriptor for the scrollbar * @param obj pointer to an object * @param dsc the draw descriptor to initialize - * @return LV_RES_OK: the scrollbar is visible; LV_RES_INV: the scrollbar is not visible + * @return LV_RESULT_OK: the scrollbar is visible; LV_RESULT_INVALID: the scrollbar is not visible */ -static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc) +static lv_result_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc) { lv_draw_rect_dsc_init(dsc); dsc->bg_opa = lv_obj_get_style_bg_opa(obj, LV_PART_SCROLLBAR); @@ -689,7 +530,6 @@ static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc } } -#if LV_DRAW_COMPLEX dsc->shadow_opa = lv_obj_get_style_shadow_opa(obj, LV_PART_SCROLLBAR); if(dsc->shadow_opa > LV_OPA_MIN) { dsc->shadow_width = lv_obj_get_style_shadow_width(obj, LV_PART_SCROLLBAR); @@ -704,22 +544,19 @@ static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc lv_opa_t opa = lv_obj_get_style_opa_recursive(obj, LV_PART_SCROLLBAR); if(opa < LV_OPA_MAX) { - dsc->bg_opa = (dsc->bg_opa * opa) >> 8; - dsc->border_opa = (dsc->bg_opa * opa) >> 8; - dsc->shadow_opa = (dsc->bg_opa * opa) >> 8; + lv_opa_t v = LV_OPA_MIX2(dsc->bg_opa, opa); + dsc->bg_opa = v; + dsc->border_opa = v; + dsc->shadow_opa = v; } if(dsc->bg_opa != LV_OPA_TRANSP || dsc->border_opa != LV_OPA_TRANSP || dsc->shadow_opa != LV_OPA_TRANSP) { dsc->radius = lv_obj_get_style_radius(obj, LV_PART_SCROLLBAR); - return LV_RES_OK; + return LV_RESULT_OK; } else { - return LV_RES_INV; + return LV_RESULT_INVALID; } -#else - if(dsc->bg_opa != LV_OPA_TRANSP || dsc->border_opa != LV_OPA_TRANSP) return LV_RES_OK; - else return LV_RES_INV; -#endif } static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e) @@ -732,22 +569,22 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_obj_add_state(obj, LV_STATE_PRESSED); } else if(code == LV_EVENT_RELEASED) { - lv_obj_clear_state(obj, LV_STATE_PRESSED); - lv_indev_t * indev = lv_event_get_indev(e); + lv_obj_remove_state(obj, LV_STATE_PRESSED); + void * param = lv_event_get_param(e); /*Go the checked state if enabled*/ - if(lv_indev_get_scroll_obj(indev) == NULL && lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE)) { + if(lv_indev_get_scroll_obj(param) == NULL && lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE)) { if(!(lv_obj_get_state(obj) & LV_STATE_CHECKED)) lv_obj_add_state(obj, LV_STATE_CHECKED); - else lv_obj_clear_state(obj, LV_STATE_CHECKED); + else lv_obj_remove_state(obj, LV_STATE_CHECKED); - lv_res_t res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; + lv_result_t res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RESULT_OK) return; } } else if(code == LV_EVENT_PRESS_LOST) { - lv_obj_clear_state(obj, LV_STATE_PRESSED); + lv_obj_remove_state(obj, LV_STATE_PRESSED); } else if(code == LV_EVENT_STYLE_CHANGED) { - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); for(uint32_t i = 0; i < child_cnt; i++) { lv_obj_t * child = obj->spec_attr->children[i]; lv_obj_mark_layout_as_dirty(child); @@ -755,26 +592,26 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e) } else if(code == LV_EVENT_KEY) { if(lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE)) { - char c = *((char *)lv_event_get_param(e)); + uint32_t c = lv_event_get_key(e); if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { lv_obj_add_state(obj, LV_STATE_CHECKED); } else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { - lv_obj_clear_state(obj, LV_STATE_CHECKED); + lv_obj_remove_state(obj, LV_STATE_CHECKED); } /*With Enter LV_EVENT_RELEASED will send VALUE_CHANGE event*/ if(c != LV_KEY_ENTER) { - lv_res_t res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; + lv_result_t res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RESULT_OK) return; } } else if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_WITH_ARROW) && !lv_obj_is_editable(obj)) { /*scroll by keypad or encoder*/ lv_anim_enable_t anim_enable = LV_ANIM_OFF; - lv_coord_t sl = lv_obj_get_scroll_left(obj); - lv_coord_t sr = lv_obj_get_scroll_right(obj); - char c = *((char *)lv_event_get_param(e)); + int32_t sl = lv_obj_get_scroll_left(obj); + int32_t sr = lv_obj_get_scroll_right(obj); + uint32_t c = lv_event_get_key(e); if(c == LV_KEY_DOWN) { /*use scroll_to_x/y functions to enforce scroll limits*/ lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) + lv_obj_get_height(obj) / 4, anim_enable); @@ -810,7 +647,7 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e) /* Use the indev for then indev handler. * But if the obj was focused manually it returns NULL so try to * use the indev from the event*/ - lv_indev_t * indev = lv_indev_get_act(); + lv_indev_t * indev = lv_indev_active(); if(indev == NULL) indev = lv_event_get_indev(e); lv_indev_type_t indev_type = lv_indev_get_type(indev); @@ -821,14 +658,14 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e) } else { lv_obj_add_state(obj, state); - lv_obj_clear_state(obj, LV_STATE_EDITED); + lv_obj_remove_state(obj, LV_STATE_EDITED); } } else if(code == LV_EVENT_SCROLL_BEGIN) { lv_obj_add_state(obj, LV_STATE_SCROLLED); } else if(code == LV_EVENT_SCROLL_END) { - lv_obj_clear_state(obj, LV_STATE_SCROLLED); + lv_obj_remove_state(obj, LV_STATE_SCROLLED); if(lv_obj_get_scrollbar_mode(obj) == LV_SCROLLBAR_MODE_ACTIVE) { lv_area_t hor_area, ver_area; lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area); @@ -837,26 +674,26 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e) } } else if(code == LV_EVENT_DEFOCUSED) { - lv_obj_clear_state(obj, LV_STATE_FOCUSED | LV_STATE_EDITED | LV_STATE_FOCUS_KEY); + lv_obj_remove_state(obj, LV_STATE_FOCUSED | LV_STATE_EDITED | LV_STATE_FOCUS_KEY); } else if(code == LV_EVENT_SIZE_CHANGED) { - lv_coord_t align = lv_obj_get_style_align(obj, LV_PART_MAIN); + int32_t align = lv_obj_get_style_align(obj, LV_PART_MAIN); uint16_t layout = lv_obj_get_style_layout(obj, LV_PART_MAIN); if(layout || align) { lv_obj_mark_layout_as_dirty(obj); } uint32_t i; - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); for(i = 0; i < child_cnt; i++) { lv_obj_t * child = obj->spec_attr->children[i]; lv_obj_mark_layout_as_dirty(child); } } else if(code == LV_EVENT_CHILD_CHANGED) { - lv_coord_t w = lv_obj_get_style_width(obj, LV_PART_MAIN); - lv_coord_t h = lv_obj_get_style_height(obj, LV_PART_MAIN); - lv_coord_t align = lv_obj_get_style_align(obj, LV_PART_MAIN); + int32_t w = lv_obj_get_style_width(obj, LV_PART_MAIN); + int32_t h = lv_obj_get_style_height(obj, LV_PART_MAIN); + int32_t align = lv_obj_get_style_align(obj, LV_PART_MAIN); uint16_t layout = lv_obj_get_style_layout(obj, LV_PART_MAIN); if(layout || align || w == LV_SIZE_CONTENT || h == LV_SIZE_CONTENT) { lv_obj_mark_layout_as_dirty(obj); @@ -867,12 +704,16 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_obj_mark_layout_as_dirty(obj); } else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - lv_coord_t d = lv_obj_calculate_ext_draw_size(obj, LV_PART_MAIN); + int32_t d = lv_obj_calculate_ext_draw_size(obj, LV_PART_MAIN); lv_event_set_ext_draw_size(e, d); } else if(code == LV_EVENT_DRAW_MAIN || code == LV_EVENT_DRAW_POST || code == LV_EVENT_COVER_CHECK) { lv_obj_draw(e); } + else if(code == LV_EVENT_INDEV_RESET) { + lv_obj_remove_state(obj, LV_STATE_PRESSED); + lv_obj_remove_state(obj, LV_STATE_SCROLLED); + } } /** @@ -881,21 +722,27 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e) * @param obj pointer to an object * @param state the new state */ -static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state) +static void update_obj_state(lv_obj_t * obj, lv_state_t new_state) { if(obj->state == new_state) return; LV_ASSERT_OBJ(obj, MY_CLASS); lv_state_t prev_state = obj->state; - obj->state = new_state; _lv_style_state_cmp_t cmp_res = _lv_obj_style_state_compare(obj, prev_state, new_state); /*If there is no difference in styles there is nothing else to do*/ - if(cmp_res == _LV_STYLE_STATE_CMP_SAME) return; + if(cmp_res == _LV_STYLE_STATE_CMP_SAME) { + obj->state = new_state; + return; + } - _lv_obj_style_transition_dsc_t * ts = lv_mem_buf_get(sizeof(_lv_obj_style_transition_dsc_t) * STYLE_TRANSITION_MAX); - lv_memset_00(ts, sizeof(_lv_obj_style_transition_dsc_t) * STYLE_TRANSITION_MAX); + /*Invalidate the object in their current state*/ + lv_obj_invalidate(obj); + + obj->state = new_state; + + _lv_obj_style_transition_dsc_t * ts = lv_malloc_zeroed(sizeof(_lv_obj_style_transition_dsc_t) * STYLE_TRANSITION_MAX); uint32_t tsi = 0; uint32_t i; for(i = 0; i < obj->style_cnt && tsi < STYLE_TRANSITION_MAX; i++) { @@ -926,9 +773,7 @@ static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state) ts[tsi].delay = tr->delay; ts[tsi].path_cb = tr->path_xcb; ts[tsi].prop = tr->props[j]; -#if LV_USE_USER_DATA ts[tsi].user_data = tr->user_data; -#endif ts[tsi].selector = obj_style->selector; tsi++; } @@ -940,10 +785,11 @@ static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state) _lv_obj_style_create_transition(obj, part_act, prev_state, new_state, &ts[i]); } - lv_mem_buf_release(ts); + lv_free(ts); if(cmp_res == _LV_STYLE_STATE_CMP_DIFF_REDRAW) { - lv_obj_invalidate(obj); + /*Invalidation is not enough, e.g. layer type needs to be updated too*/ + lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY); } else if(cmp_res == _LV_STYLE_STATE_CMP_DIFF_LAYOUT) { lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY); @@ -974,3 +820,55 @@ static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_fin } return false; } + +#if LV_USE_OBJ_PROPERTY +static lv_result_t lv_obj_set_any(lv_obj_t * obj, lv_prop_id_t id, const lv_property_t * prop) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + if(id >= LV_PROPERTY_OBJ_FLAG_START && id <= LV_PROPERTY_OBJ_FLAG_END) { + lv_obj_flag_t flag = 1L << (id - LV_PROPERTY_OBJ_FLAG_START); + if(prop->num) lv_obj_add_flag(obj, flag); + else lv_obj_remove_flag(obj, flag); + return LV_RESULT_OK; + } + else if(id >= LV_PROPERTY_OBJ_STATE_START && id <= LV_PROPERTY_OBJ_STATE_END) { + lv_state_t state = 1L << (id - LV_PROPERTY_OBJ_STATE_START); + if(id == LV_PROPERTY_OBJ_STATE_ANY) { + state = LV_STATE_ANY; + } + + if(prop->num) lv_obj_add_state(obj, state); + else lv_obj_remove_state(obj, state); + return LV_RESULT_OK; + } + else { + return LV_RESULT_INVALID; + } +} + +static lv_result_t lv_obj_get_any(const lv_obj_t * obj, lv_prop_id_t id, lv_property_t * prop) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + if(id >= LV_PROPERTY_OBJ_FLAG_START && id <= LV_PROPERTY_OBJ_FLAG_END) { + lv_obj_flag_t flag = 1L << (id - LV_PROPERTY_OBJ_FLAG_START); + prop->id = id; + prop->num = obj->flags & flag; + return LV_RESULT_OK; + } + else if(id >= LV_PROPERTY_OBJ_STATE_START && id <= LV_PROPERTY_OBJ_STATE_END) { + prop->id = id; + if(id == LV_PROPERTY_OBJ_STATE_ANY) { + prop->num = obj->state; + } + else { + lv_obj_flag_t flag = 1L << (id - LV_PROPERTY_OBJ_STATE_START); + prop->num = obj->state & flag; + } + return LV_RESULT_OK; + } + else { + return LV_RESULT_INVALID; + } +} +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj.h index 830d122e4..b67684f32 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj.h @@ -17,12 +17,21 @@ extern "C" { #include #include -#include "../misc/lv_style.h" #include "../misc/lv_types.h" +#include "../misc/lv_style.h" #include "../misc/lv_area.h" #include "../misc/lv_color.h" #include "../misc/lv_assert.h" -#include "../hal/lv_hal.h" + +#include "lv_obj_tree.h" +#include "lv_obj_pos.h" +#include "lv_obj_scroll.h" +#include "lv_obj_style.h" +#include "lv_obj_draw.h" +#include "lv_obj_class.h" +#include "lv_obj_event.h" +#include "lv_obj_property.h" +#include "lv_group.h" /********************* * DEFINES @@ -32,13 +41,11 @@ extern "C" { * TYPEDEFS **********************/ -struct _lv_obj_t; - /** * Possible states of a widget. * OR-ed values are possible */ -enum { +enum _lv_state_t { LV_STATE_DEFAULT = 0x0000, LV_STATE_CHECKED = 0x0001, LV_STATE_FOCUSED = 0x0002, @@ -48,7 +55,6 @@ enum { LV_STATE_PRESSED = 0x0020, LV_STATE_SCROLLED = 0x0040, LV_STATE_DISABLED = 0x0080, - LV_STATE_USER_1 = 0x1000, LV_STATE_USER_2 = 0x2000, LV_STATE_USER_3 = 0x4000, @@ -57,36 +63,35 @@ enum { LV_STATE_ANY = 0xFFFF, /**< Special value can be used in some functions to target all states*/ }; -typedef uint16_t lv_state_t; - /** * The possible parts of widgets. * The parts can be considered as the internal building block of the widgets. * E.g. slider = background + indicator + knob * Not all parts are used by every widget */ -enum { + +enum _lv_part_t { LV_PART_MAIN = 0x000000, /**< A background like rectangle*/ LV_PART_SCROLLBAR = 0x010000, /**< The scrollbar(s)*/ LV_PART_INDICATOR = 0x020000, /**< Indicator, e.g. for slider, bar, switch, or the tick box of the checkbox*/ LV_PART_KNOB = 0x030000, /**< Like handle to grab to adjust the value*/ LV_PART_SELECTED = 0x040000, /**< Indicate the currently selected option or section*/ LV_PART_ITEMS = 0x050000, /**< Used if the widget has multiple similar elements (e.g. table cells)*/ - LV_PART_TICKS = 0x060000, /**< Ticks on scale e.g. for a chart or meter*/ - LV_PART_CURSOR = 0x070000, /**< Mark a specific place e.g. for text area's cursor or on a chart*/ + LV_PART_CURSOR = 0x060000, /**< Mark a specific place e.g. for text area's cursor or on a chart*/ LV_PART_CUSTOM_FIRST = 0x080000, /**< Extension point for custom widgets*/ LV_PART_ANY = 0x0F0000, /**< Special value can be used in some functions to target all parts*/ }; -typedef uint32_t lv_part_t; - /** * On/Off features controlling the object's behavior. * OR-ed values are possible + * + * Note: update obj flags corresponding properties below + * whenever add/remove flags or change bit definition of flags. */ -enum { +typedef enum { LV_OBJ_FLAG_HIDDEN = (1L << 0), /**< Make the object hidden. (Like it wasn't there at all)*/ LV_OBJ_FLAG_CLICKABLE = (1L << 1), /**< Make the object clickable by the input devices*/ LV_OBJ_FLAG_CLICK_FOCUSABLE = (1L << 2), /**< Add focused state to the object when clicked*/ @@ -107,7 +112,11 @@ enum { LV_OBJ_FLAG_ADV_HITTEST = (1L << 16), /**< Allow performing more accurate hit (click) test. E.g. consider rounded corners.*/ LV_OBJ_FLAG_IGNORE_LAYOUT = (1L << 17), /**< Make the object position-able by the layouts*/ LV_OBJ_FLAG_FLOATING = (1L << 18), /**< Do not scroll the object when the parent scrolls and ignore layout*/ - LV_OBJ_FLAG_OVERFLOW_VISIBLE = (1L << 19), /**< Do not clip the children's content to the parent's boundary*/ + LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS = (1L << 19), /**< Send `LV_EVENT_DRAW_TASK_ADDED` events*/ + LV_OBJ_FLAG_OVERFLOW_VISIBLE = (1L << 20),/**< Do not clip the children to the parent's ext draw size*/ +#if LV_USE_FLEX + LV_OBJ_FLAG_FLEX_IN_NEW_TRACK = (1L << 21), /**< Start a new flex track on this item*/ +#endif LV_OBJ_FLAG_LAYOUT_1 = (1L << 23), /**< Custom flag, free to use by layouts*/ LV_OBJ_FLAG_LAYOUT_2 = (1L << 24), /**< Custom flag, free to use by layouts*/ @@ -118,66 +127,107 @@ enum { LV_OBJ_FLAG_USER_2 = (1L << 28), /**< Custom flag, free to use by user*/ LV_OBJ_FLAG_USER_3 = (1L << 29), /**< Custom flag, free to use by user*/ LV_OBJ_FLAG_USER_4 = (1L << 30), /**< Custom flag, free to use by user*/ +} _lv_obj_flag_t; +#if LV_USE_OBJ_PROPERTY +enum { + /*OBJ flag properties */ + LV_PROPERTY_ID(OBJ, FLAG_START, LV_PROPERTY_TYPE_INT, 0), + LV_PROPERTY_ID(OBJ, FLAG_HIDDEN, LV_PROPERTY_TYPE_INT, 0), + LV_PROPERTY_ID(OBJ, FLAG_CLICKABLE, LV_PROPERTY_TYPE_INT, 1), + LV_PROPERTY_ID(OBJ, FLAG_CLICK_FOCUSABLE, LV_PROPERTY_TYPE_INT, 2), + LV_PROPERTY_ID(OBJ, FLAG_CHECKABLE, LV_PROPERTY_TYPE_INT, 3), + LV_PROPERTY_ID(OBJ, FLAG_SCROLLABLE, LV_PROPERTY_TYPE_INT, 4), + LV_PROPERTY_ID(OBJ, FLAG_SCROLL_ELASTIC, LV_PROPERTY_TYPE_INT, 5), + LV_PROPERTY_ID(OBJ, FLAG_SCROLL_MOMENTUM, LV_PROPERTY_TYPE_INT, 6), + LV_PROPERTY_ID(OBJ, FLAG_SCROLL_ONE, LV_PROPERTY_TYPE_INT, 7), + LV_PROPERTY_ID(OBJ, FLAG_SCROLL_CHAIN_HOR, LV_PROPERTY_TYPE_INT, 8), + LV_PROPERTY_ID(OBJ, FLAG_SCROLL_CHAIN_VER, LV_PROPERTY_TYPE_INT, 9), + LV_PROPERTY_ID(OBJ, FLAG_SCROLL_ON_FOCUS, LV_PROPERTY_TYPE_INT, 10), + LV_PROPERTY_ID(OBJ, FLAG_SCROLL_WITH_ARROW, LV_PROPERTY_TYPE_INT, 11), + LV_PROPERTY_ID(OBJ, FLAG_SNAPPABLE, LV_PROPERTY_TYPE_INT, 12), + LV_PROPERTY_ID(OBJ, FLAG_PRESS_LOCK, LV_PROPERTY_TYPE_INT, 13), + LV_PROPERTY_ID(OBJ, FLAG_EVENT_BUBBLE, LV_PROPERTY_TYPE_INT, 14), + LV_PROPERTY_ID(OBJ, FLAG_GESTURE_BUBBLE, LV_PROPERTY_TYPE_INT, 15), + LV_PROPERTY_ID(OBJ, FLAG_ADV_HITTEST, LV_PROPERTY_TYPE_INT, 16), + LV_PROPERTY_ID(OBJ, FLAG_IGNORE_LAYOUT, LV_PROPERTY_TYPE_INT, 17), + LV_PROPERTY_ID(OBJ, FLAG_FLOATING, LV_PROPERTY_TYPE_INT, 18), + LV_PROPERTY_ID(OBJ, FLAG_SEND_DRAW_TASK_EVENTS, LV_PROPERTY_TYPE_INT, 19), + LV_PROPERTY_ID(OBJ, FLAG_OVERFLOW_VISIBLE, LV_PROPERTY_TYPE_INT, 20), + LV_PROPERTY_ID(OBJ, FLAG_FLEX_IN_NEW_TRACK, LV_PROPERTY_TYPE_INT, 21), + LV_PROPERTY_ID(OBJ, FLAG_LAYOUT_1, LV_PROPERTY_TYPE_INT, 23), + LV_PROPERTY_ID(OBJ, FLAG_LAYOUT_2, LV_PROPERTY_TYPE_INT, 24), + LV_PROPERTY_ID(OBJ, FLAG_WIDGET_1, LV_PROPERTY_TYPE_INT, 25), + LV_PROPERTY_ID(OBJ, FLAG_WIDGET_2, LV_PROPERTY_TYPE_INT, 26), + LV_PROPERTY_ID(OBJ, FLAG_USER_1, LV_PROPERTY_TYPE_INT, 27), + LV_PROPERTY_ID(OBJ, FLAG_USER_2, LV_PROPERTY_TYPE_INT, 28), + LV_PROPERTY_ID(OBJ, FLAG_USER_3, LV_PROPERTY_TYPE_INT, 29), + LV_PROPERTY_ID(OBJ, FLAG_USER_4, LV_PROPERTY_TYPE_INT, 30), + LV_PROPERTY_ID(OBJ, FLAG_END, LV_PROPERTY_TYPE_INT, 30), + + LV_PROPERTY_ID(OBJ, STATE_START, LV_PROPERTY_TYPE_INT, 31), + LV_PROPERTY_ID(OBJ, STATE_CHECKED, LV_PROPERTY_TYPE_INT, 31), + LV_PROPERTY_ID(OBJ, STATE_FOCUSED, LV_PROPERTY_TYPE_INT, 32), + LV_PROPERTY_ID(OBJ, STATE_FOCUS_KEY, LV_PROPERTY_TYPE_INT, 33), + LV_PROPERTY_ID(OBJ, STATE_EDITED, LV_PROPERTY_TYPE_INT, 34), + LV_PROPERTY_ID(OBJ, STATE_HOVERED, LV_PROPERTY_TYPE_INT, 35), + LV_PROPERTY_ID(OBJ, STATE_PRESSED, LV_PROPERTY_TYPE_INT, 36), + LV_PROPERTY_ID(OBJ, STATE_SCROLLED, LV_PROPERTY_TYPE_INT, 37), + LV_PROPERTY_ID(OBJ, STATE_DISABLED, LV_PROPERTY_TYPE_INT, 38), + /*not used bit8-bit11*/ + LV_PROPERTY_ID(OBJ, STATE_USER_1, LV_PROPERTY_TYPE_INT, 43), + LV_PROPERTY_ID(OBJ, STATE_USER_2, LV_PROPERTY_TYPE_INT, 44), + LV_PROPERTY_ID(OBJ, STATE_USER_3, LV_PROPERTY_TYPE_INT, 45), + LV_PROPERTY_ID(OBJ, STATE_USER_4, LV_PROPERTY_TYPE_INT, 46), + LV_PROPERTY_ID(OBJ, STATE_ANY, LV_PROPERTY_TYPE_INT, 47), + LV_PROPERTY_ID(OBJ, STATE_END, LV_PROPERTY_TYPE_INT, 47), + + /*OBJ normal properties*/ + LV_PROPERTY_ID(OBJ, PARENT, LV_PROPERTY_TYPE_POINTER, 31), + + LV_PROPERTY_OBJ_END, }; - - -typedef uint32_t lv_obj_flag_t; - -/** - * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_obj_class` - * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` - */ -typedef enum { - LV_OBJ_DRAW_PART_RECTANGLE, /**< The main rectangle*/ - LV_OBJ_DRAW_PART_BORDER_POST,/**< The border if style_border_post = true*/ - LV_OBJ_DRAW_PART_SCROLLBAR, /**< The scrollbar*/ -} lv_obj_draw_part_type_t; - -#include "lv_obj_tree.h" -#include "lv_obj_pos.h" -#include "lv_obj_scroll.h" -#include "lv_obj_style.h" -#include "lv_obj_draw.h" -#include "lv_obj_class.h" -#include "lv_event.h" -#include "lv_group.h" +#endif /** * Make the base object's class publicly available. */ -extern const lv_obj_class_t lv_obj_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_obj_class; /** * Special, rarely used attributes. * They are allocated automatically if any elements is set. */ typedef struct { - struct _lv_obj_t ** children; /**< Store the pointer of the children in an array.*/ - uint32_t child_cnt; /**< Number of children*/ + lv_obj_t ** children; /**< Store the pointer of the children in an array.*/ lv_group_t * group_p; + lv_event_list_t event_list; - struct _lv_event_dsc_t * event_dsc; /**< Dynamically allocated event callback and user data array*/ - lv_point_t scroll; /**< The current X/Y scroll offset*/ + lv_point_t scroll; /**< The current X/Y scroll offset*/ - lv_coord_t ext_click_pad; /**< Extra click padding in all direction*/ - lv_coord_t ext_draw_size; /**< EXTend the size in every direction for drawing.*/ + int32_t ext_click_pad; /**< Extra click padding in all direction*/ + int32_t ext_draw_size; /**< EXTend the size in every direction for drawing.*/ - lv_scrollbar_mode_t scrollbar_mode : 2; /**< How to display scrollbars*/ - lv_scroll_snap_t scroll_snap_x : 2; /**< Where to align the snappable children horizontally*/ - lv_scroll_snap_t scroll_snap_y : 2; /**< Where to align the snappable children vertically*/ - lv_dir_t scroll_dir : 4; /**< The allowed scroll direction(s)*/ - uint8_t event_dsc_cnt : 6; /**< Number of event callbacks stored in `event_dsc` array*/ - uint8_t layer_type : 2; /**< Cache the layer type here. Element of @lv_intermediate_layer_type_t */ + uint16_t child_cnt; /**< Number of children*/ + uint16_t scrollbar_mode : 2; /**< How to display scrollbars, see `lv_scrollbar_mode_t`*/ + uint16_t scroll_snap_x : 2; /**< Where to align the snappable children horizontally, see `lv_scroll_snap_t`*/ + uint16_t scroll_snap_y : 2; /**< Where to align the snappable children vertically*/ + uint16_t scroll_dir : 4; /**< The allowed scroll direction(s), see `lv_dir_t`*/ + uint16_t layer_type : 2; /**< Cache the layer type here. Element of @lv_intermediate_layer_type_t */ } _lv_obj_spec_attr_t; -typedef struct _lv_obj_t { +struct _lv_obj_t { const lv_obj_class_t * class_p; - struct _lv_obj_t * parent; + lv_obj_t * parent; _lv_obj_spec_attr_t * spec_attr; _lv_obj_style_t * styles; -#if LV_USE_USER_DATA +#if LV_OBJ_STYLE_CACHE + uint32_t style_main_prop_is_set; + uint32_t style_other_prop_is_set; +#endif void * user_data; +#if LV_USE_OBJ_ID + void * id; #endif lv_area_t coords; lv_obj_flag_t flags; @@ -189,35 +239,13 @@ typedef struct _lv_obj_t { uint16_t style_cnt : 6; uint16_t h_layout : 1; uint16_t w_layout : 1; - uint16_t being_deleted : 1; -} lv_obj_t; - + uint16_t is_deleting : 1; +}; /********************** * GLOBAL PROTOTYPES **********************/ -/** - * Initialize LVGL library. - * Should be called before any other LVGL related function. - */ -void lv_init(void); - -#if LV_ENABLE_GC || !LV_MEM_CUSTOM - -/** - * Deinit the 'lv' library - * Currently only implemented when not using custom allocators, or GC is enabled. - */ -void lv_deinit(void); - -#endif - -/** - * Returns whether the 'lv' library is currently initialized - */ -bool lv_is_initialized(void); - /** * Create a base object (a rectangle) * @param parent pointer to a parent object. If NULL then a screen will be created. @@ -225,7 +253,6 @@ bool lv_is_initialized(void); */ lv_obj_t * lv_obj_create(lv_obj_t * parent); - /*===================== * Setter functions *====================*/ @@ -238,12 +265,19 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent); void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f); /** - * Clear one or more flags + * Remove one or more flags * @param obj pointer to an object * @param f OR-ed values from `lv_obj_flag_t` to set. */ -void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f); +void lv_obj_remove_flag(lv_obj_t * obj, lv_obj_flag_t f); +/** + * Set add or remove one or more flags. + * @param obj pointer to an object + * @param f OR-ed values from `lv_obj_flag_t` to update. + * @param v true: add the flags; false: remove the flags + */ +void lv_obj_update_flag(lv_obj_t * obj, lv_obj_flag_t f, bool v); /** * Add one or more states to the object. The other state bits will remain unchanged. @@ -259,19 +293,25 @@ void lv_obj_add_state(lv_obj_t * obj, lv_state_t state); * @param obj pointer to an object * @param state the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED` */ -void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state); +void lv_obj_remove_state(lv_obj_t * obj, lv_state_t state); + +/** + * Add or remove one or more states to the object. The other state bits will remain unchanged. + * @param obj pointer to an object + * @param state the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED` + * @param v true: add the states; false: remove the states + */ +void lv_obj_set_state(lv_obj_t * obj, lv_state_t state, bool v); /** * Set the user_data field of the object * @param obj pointer to an object * @param user_data pointer to the new user_data. */ -#if LV_USE_USER_DATA static inline void lv_obj_set_user_data(lv_obj_t * obj, void * user_data) { obj->user_data = user_data; } -#endif /*======================= * Getter functions @@ -313,19 +353,17 @@ bool lv_obj_has_state(const lv_obj_t * obj, lv_state_t state); * @param obj pointer to an object * @return the pointer to group of the object */ -void * lv_obj_get_group(const lv_obj_t * obj); +lv_group_t * lv_obj_get_group(const lv_obj_t * obj); /** * Get the user_data field of the object * @param obj pointer to an object * @return the pointer to the user_data of the object */ -#if LV_USE_USER_DATA static inline void * lv_obj_get_user_data(lv_obj_t * obj) { return obj->user_data; } -#endif /*======================= * Other functions @@ -368,19 +406,41 @@ const lv_obj_class_t * lv_obj_get_class(const lv_obj_t * obj); */ bool lv_obj_is_valid(const lv_obj_t * obj); +#if LV_USE_OBJ_ID + /** - * Scale the given number of pixels (a distance or size) relative to a 160 DPI display - * considering the DPI of the `obj`'s display. - * It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the - * DPI of the display. - * @param obj an object whose display's dpi should be considered - * @param n the number of pixels to scale - * @return `n x current_dpi/160` + * Assign an id to an object if not previously assigned + * Set `LV_USE_OBJ_ID_BUILTIN` to 1 to use builtin method to generate object ID. + * Otherwise, these functions including `lv_obj_[assign|free|stringify]_id` should be implemented externally. + * + * @param class_p the class this obj belongs to. Note obj->class_p is the class currently being constructed. + * @param obj pointer to an object */ -static inline lv_coord_t lv_obj_dpx(const lv_obj_t * obj, lv_coord_t n) -{ - return _LV_DPX_CALC(lv_disp_get_dpi(lv_obj_get_disp(obj)), n); -} +void lv_obj_assign_id(const lv_obj_class_t * class_p, lv_obj_t * obj); + +/** + * Free resources allocated by `lv_obj_assign_id` + * @param obj pointer to an object + */ +void lv_obj_free_id(lv_obj_t * obj); + +/** + * Format an object's id into a string. + * @param obj pointer to an object + * @param buf buffer to write the string into + * @param len length of the buffer + */ +const char * lv_obj_stringify_id(lv_obj_t * obj, char * buf, uint32_t len); + +#if LV_USE_OBJ_ID_BUILTIN +/** + * Free resources used by builtin ID generator. + */ +void lv_objid_builtin_destroy(void); + +#endif + +#endif /*LV_USE_OBJ_ID*/ /********************** * MACROS @@ -403,7 +463,6 @@ static inline lv_coord_t lv_obj_dpx(const lv_obj_t * obj, lv_coord_t n) # define LV_TRACE_OBJ_CREATE(...) #endif - #ifdef __cplusplus } /*extern "C"*/ #endif diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.c index fe2044824..fd483ee05 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.c @@ -7,7 +7,10 @@ * INCLUDES *********************/ #include "lv_obj.h" -#include "lv_theme.h" +#include "../themes/lv_theme.h" +#include "../display/lv_display.h" +#include "../display/lv_display_private.h" +#include "../stdlib/lv_string.h" /********************* * DEFINES @@ -25,7 +28,7 @@ /********************** * STATIC PROTOTYPES **********************/ -static void lv_obj_construct(lv_obj_t * obj); +static void lv_obj_construct(const lv_obj_class_t * class_p, lv_obj_t * obj); static uint32_t get_instance_size(const lv_obj_class_t * class_p); /********************** @@ -44,38 +47,34 @@ lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * pa { LV_TRACE_OBJ_CREATE("Creating object with %p class on %p parent", (void *)class_p, (void *)parent); uint32_t s = get_instance_size(class_p); - lv_obj_t * obj = lv_mem_alloc(s); + lv_obj_t * obj = lv_malloc_zeroed(s); if(obj == NULL) return NULL; - lv_memset_00(obj, s); obj->class_p = class_p; obj->parent = parent; /*Create a screen*/ if(parent == NULL) { LV_TRACE_OBJ_CREATE("creating a screen"); - lv_disp_t * disp = lv_disp_get_default(); + lv_display_t * disp = lv_display_get_default(); if(!disp) { LV_LOG_WARN("No display created yet. No place to assign the new screen"); - lv_mem_free(obj); + lv_free(obj); return NULL; } if(disp->screens == NULL) { - disp->screens = lv_mem_alloc(sizeof(lv_obj_t *)); - disp->screens[0] = obj; - disp->screen_cnt = 1; - } - else { - disp->screen_cnt++; - disp->screens = lv_mem_realloc(disp->screens, sizeof(lv_obj_t *) * disp->screen_cnt); - disp->screens[disp->screen_cnt - 1] = obj; + disp->screen_cnt = 0; } + disp->screen_cnt++; + disp->screens = lv_realloc(disp->screens, sizeof(lv_obj_t *) * disp->screen_cnt); + disp->screens[disp->screen_cnt - 1] = obj; + /*Set coordinates to full screen size*/ obj->coords.x1 = 0; obj->coords.y1 = 0; - obj->coords.x2 = lv_disp_get_hor_res(NULL) - 1; - obj->coords.y2 = lv_disp_get_ver_res(NULL) - 1; + obj->coords.x2 = lv_display_get_horizontal_resolution(NULL) - 1; + obj->coords.y2 = lv_display_get_vertical_resolution(NULL) - 1; } /*Create a normal object*/ else { @@ -85,17 +84,10 @@ lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * pa lv_obj_allocate_spec_attr(parent); } - if(parent->spec_attr->children == NULL) { - parent->spec_attr->children = lv_mem_alloc(sizeof(lv_obj_t *)); - parent->spec_attr->children[0] = obj; - parent->spec_attr->child_cnt = 1; - } - else { - parent->spec_attr->child_cnt++; - parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children, - sizeof(lv_obj_t *) * parent->spec_attr->child_cnt); - parent->spec_attr->children[parent->spec_attr->child_cnt - 1] = obj; - } + parent->spec_attr->child_cnt++; + parent->spec_attr->children = lv_realloc(parent->spec_attr->children, + sizeof(lv_obj_t *) * parent->spec_attr->child_cnt); + parent->spec_attr->children[parent->spec_attr->child_cnt - 1] = obj; } return obj; @@ -107,7 +99,7 @@ void lv_obj_class_init_obj(lv_obj_t * obj) lv_obj_enable_style_refresh(false); lv_theme_apply(obj); - lv_obj_construct(obj); + lv_obj_construct(obj->class_p, obj); lv_obj_enable_style_refresh(true); lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY); @@ -123,8 +115,8 @@ void lv_obj_class_init_obj(lv_obj_t * obj) if(parent) { /*Call the ancestor's event handler to the parent to notify it about the new child. *Also triggers layout update*/ - lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj); - lv_event_send(parent, LV_EVENT_CHILD_CREATED, obj); + lv_obj_send_event(parent, LV_EVENT_CHILD_CHANGED, obj); + lv_obj_send_event(parent, LV_EVENT_CHILD_CREATED, obj); /*Invalidate the area if not screen created*/ lv_obj_invalidate(obj); @@ -153,7 +145,7 @@ bool lv_obj_is_editable(lv_obj_t * obj) if(class_p == NULL) return false; - return class_p->editable == LV_OBJ_CLASS_EDITABLE_TRUE ? true : false; + return class_p->editable == LV_OBJ_CLASS_EDITABLE_TRUE; } bool lv_obj_is_group_def(lv_obj_t * obj) @@ -165,29 +157,29 @@ bool lv_obj_is_group_def(lv_obj_t * obj) if(class_p == NULL) return false; - return class_p->group_def == LV_OBJ_CLASS_GROUP_DEF_TRUE ? true : false; + return class_p->group_def == LV_OBJ_CLASS_GROUP_DEF_TRUE; } /********************** * STATIC FUNCTIONS **********************/ -static void lv_obj_construct(lv_obj_t * obj) +static void lv_obj_construct(const lv_obj_class_t * class_p, lv_obj_t * obj) { - const lv_obj_class_t * original_class_p = obj->class_p; - if(obj->class_p->base_class) { + const lv_obj_class_t * original_class_p = obj->class_p; + /*Don't let the descendant methods run during constructing the ancestor type*/ obj->class_p = obj->class_p->base_class; /*Construct the base first*/ - lv_obj_construct(obj); + lv_obj_construct(class_p, obj); + + /*Restore the original class*/ + obj->class_p = original_class_p; } - /*Restore the original class*/ - obj->class_p = original_class_p; - - if(obj->class_p->constructor_cb) obj->class_p->constructor_cb(obj->class_p, obj); + if(obj->class_p->constructor_cb) obj->class_p->constructor_cb(class_p, obj); } static uint32_t get_instance_size(const lv_obj_class_t * class_p) diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.h index 01a7248ba..729229224 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_class.h @@ -15,20 +15,18 @@ extern "C" { *********************/ #include #include +#include "../misc/lv_types.h" +#include "../misc/lv_area.h" +#include "lv_obj_property.h" /********************* * DEFINES *********************/ - /********************** * TYPEDEFS **********************/ -struct _lv_obj_t; -struct _lv_obj_class_t; -struct _lv_event_t; - typedef enum { LV_OBJ_CLASS_EDITABLE_INHERIT, /**< Check the base class. Must have 0 value to let zero initialized class inherit*/ LV_OBJ_CLASS_EDITABLE_TRUE, @@ -41,26 +39,41 @@ typedef enum { LV_OBJ_CLASS_GROUP_DEF_FALSE, } lv_obj_class_group_def_t; -typedef void (*lv_obj_class_event_cb_t)(struct _lv_obj_class_t * class_p, struct _lv_event_t * e); +typedef enum { + LV_OBJ_CLASS_THEME_INHERITABLE_FALSE, /**< Do not inherit theme from base class. */ + LV_OBJ_CLASS_THEME_INHERITABLE_TRUE, +} lv_obj_class_theme_inheritable_t; + +typedef void (*lv_obj_class_event_cb_t)(lv_obj_class_t * class_p, lv_event_t * e); /** * Describe the common methods of every object. * Similar to a C++ class. */ -typedef struct _lv_obj_class_t { - const struct _lv_obj_class_t * base_class; - void (*constructor_cb)(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * obj); - void (*destructor_cb)(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * obj); -#if LV_USE_USER_DATA - void * user_data; +struct _lv_obj_class_t { + const lv_obj_class_t * base_class; + /*class_p is the final class while obj->class_p is the class currently being [de]constructed.*/ + void (*constructor_cb)(const lv_obj_class_t * class_p, lv_obj_t * obj); + void (*destructor_cb)(const lv_obj_class_t * class_p, lv_obj_t * obj); + + /*class_p is the class in which event is being processed.*/ + void (*event_cb)(const lv_obj_class_t * class_p, lv_event_t * e); /**< Widget type specific event function*/ + +#if LV_USE_OBJ_PROPERTY + uint32_t prop_index_start; + uint32_t prop_index_end; + const lv_property_ops_t * properties; + uint32_t properties_count; #endif - void (*event_cb)(const struct _lv_obj_class_t * class_p, - struct _lv_event_t * e); /**< Widget type specific event function*/ - lv_coord_t width_def; - lv_coord_t height_def; + + void * user_data; + const char * name; + int32_t width_def; + int32_t height_def; uint32_t editable : 2; /**< Value from ::lv_obj_class_editable_t*/ uint32_t group_def : 2; /**< Value from ::lv_obj_class_group_def_t*/ uint32_t instance_size : 16; -} lv_obj_class_t; + uint32_t theme_inheritable : 1; /**< Value from ::lv_obj_class_theme_inheritable_t*/ +}; /********************** * GLOBAL PROTOTYPES @@ -72,21 +85,20 @@ typedef struct _lv_obj_class_t { * @param parent pointer to an object where the new object should be created * @return pointer to the created object */ -struct _lv_obj_t * lv_obj_class_create_obj(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * parent); +lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * parent); -void lv_obj_class_init_obj(struct _lv_obj_t * obj); +void lv_obj_class_init_obj(lv_obj_t * obj); -void _lv_obj_destruct(struct _lv_obj_t * obj); +void _lv_obj_destruct(lv_obj_t * obj); -bool lv_obj_is_editable(struct _lv_obj_t * obj); +bool lv_obj_is_editable(lv_obj_t * obj); -bool lv_obj_is_group_def(struct _lv_obj_t * obj); +bool lv_obj_is_group_def(lv_obj_t * obj); /********************** * MACROS **********************/ - #ifdef __cplusplus } /*extern "C"*/ #endif diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.c index d906126c3..2f4632515 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.c @@ -8,8 +8,9 @@ *********************/ #include "lv_obj_draw.h" #include "lv_obj.h" -#include "lv_disp.h" -#include "lv_indev.h" +#include "../display/lv_display.h" +#include "../indev/lv_indev.h" +#include "../stdlib/lv_string.h" /********************* * DEFINES @@ -38,11 +39,14 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t * draw_dsc) { + draw_dsc->base.obj = obj; + draw_dsc->base.part = part; + lv_opa_t opa = lv_obj_get_style_opa_recursive(obj, part); if(part != LV_PART_MAIN) { if(opa <= LV_OPA_MIN) { draw_dsc->bg_opa = LV_OPA_TRANSP; - draw_dsc->bg_img_opa = LV_OPA_TRANSP; + draw_dsc->bg_image_opa = LV_OPA_TRANSP; draw_dsc->border_opa = LV_OPA_TRANSP; draw_dsc->outline_opa = LV_OPA_TRANSP; draw_dsc->shadow_opa = LV_OPA_TRANSP; @@ -50,9 +54,6 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t } } -#if LV_DRAW_COMPLEX - if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); - draw_dsc->radius = lv_obj_get_style_radius(obj, part); if(draw_dsc->bg_opa != LV_OPA_TRANSP) { @@ -70,15 +71,16 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t draw_dsc->bg_grad.stops[1].color = lv_obj_get_style_bg_grad_color_filtered(obj, part); draw_dsc->bg_grad.stops[0].frac = lv_obj_get_style_bg_main_stop(obj, part); draw_dsc->bg_grad.stops[1].frac = lv_obj_get_style_bg_grad_stop(obj, part); + draw_dsc->bg_grad.stops[0].opa = lv_obj_get_style_bg_main_opa(obj, part); + draw_dsc->bg_grad.stops[1].opa = lv_obj_get_style_bg_grad_opa(obj, part); } - draw_dsc->bg_grad.dither = lv_obj_get_style_bg_dither_mode(obj, part); } } } - draw_dsc->border_width = lv_obj_get_style_border_width(obj, part); - if(draw_dsc->border_width) { - if(draw_dsc->border_opa != LV_OPA_TRANSP) { + if(draw_dsc->border_opa != LV_OPA_TRANSP) { + draw_dsc->border_width = lv_obj_get_style_border_width(obj, part); + if(draw_dsc->border_width) { draw_dsc->border_opa = lv_obj_get_style_border_opa(obj, part); if(draw_dsc->border_opa > LV_OPA_MIN) { draw_dsc->border_side = lv_obj_get_style_border_side(obj, part); @@ -87,9 +89,9 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t } } - draw_dsc->outline_width = lv_obj_get_style_outline_width(obj, part); - if(draw_dsc->outline_width) { - if(draw_dsc->outline_opa != LV_OPA_TRANSP) { + if(draw_dsc->outline_opa != LV_OPA_TRANSP) { + draw_dsc->outline_width = lv_obj_get_style_outline_width(obj, part); + if(draw_dsc->outline_width) { draw_dsc->outline_opa = lv_obj_get_style_outline_opa(obj, part); if(draw_dsc->outline_opa > LV_OPA_MIN) { draw_dsc->outline_pad = lv_obj_get_style_outline_pad(obj, part); @@ -98,19 +100,19 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t } } - if(draw_dsc->bg_img_opa != LV_OPA_TRANSP) { - draw_dsc->bg_img_src = lv_obj_get_style_bg_img_src(obj, part); - if(draw_dsc->bg_img_src) { - draw_dsc->bg_img_opa = lv_obj_get_style_bg_img_opa(obj, part); - if(draw_dsc->bg_img_opa > LV_OPA_MIN) { - if(lv_img_src_get_type(draw_dsc->bg_img_src) == LV_IMG_SRC_SYMBOL) { - draw_dsc->bg_img_symbol_font = lv_obj_get_style_text_font(obj, part); - draw_dsc->bg_img_recolor = lv_obj_get_style_text_color_filtered(obj, part); + if(draw_dsc->bg_image_opa != LV_OPA_TRANSP) { + draw_dsc->bg_image_src = lv_obj_get_style_bg_image_src(obj, part); + if(draw_dsc->bg_image_src) { + draw_dsc->bg_image_opa = lv_obj_get_style_bg_image_opa(obj, part); + if(draw_dsc->bg_image_opa > LV_OPA_MIN) { + if(lv_image_src_get_type(draw_dsc->bg_image_src) == LV_IMAGE_SRC_SYMBOL) { + draw_dsc->bg_image_symbol_font = lv_obj_get_style_text_font(obj, part); + draw_dsc->bg_image_recolor = lv_obj_get_style_text_color_filtered(obj, part); } else { - draw_dsc->bg_img_recolor = lv_obj_get_style_bg_img_recolor_filtered(obj, part); - draw_dsc->bg_img_recolor_opa = lv_obj_get_style_bg_img_recolor_opa(obj, part); - draw_dsc->bg_img_tiled = lv_obj_get_style_bg_img_tiled(obj, part); + draw_dsc->bg_image_recolor = lv_obj_get_style_bg_image_recolor_filtered(obj, part); + draw_dsc->bg_image_recolor_opa = lv_obj_get_style_bg_image_recolor_opa(obj, part); + draw_dsc->bg_image_tiled = lv_obj_get_style_bg_image_tiled(obj, part); } } } @@ -122,8 +124,8 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t if(draw_dsc->shadow_opa > LV_OPA_MIN) { draw_dsc->shadow_opa = lv_obj_get_style_shadow_opa(obj, part); if(draw_dsc->shadow_opa > LV_OPA_MIN) { - draw_dsc->shadow_ofs_x = lv_obj_get_style_shadow_ofs_x(obj, part); - draw_dsc->shadow_ofs_y = lv_obj_get_style_shadow_ofs_y(obj, part); + draw_dsc->shadow_offset_x = lv_obj_get_style_shadow_offset_x(obj, part); + draw_dsc->shadow_offset_y = lv_obj_get_style_shadow_offset_y(obj, part); draw_dsc->shadow_spread = lv_obj_get_style_shadow_spread(obj, part); draw_dsc->shadow_color = lv_obj_get_style_shadow_color_filtered(obj, part); } @@ -131,75 +133,26 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t } } -#else /*LV_DRAW_COMPLEX*/ - if(draw_dsc->bg_opa != LV_OPA_TRANSP) { - draw_dsc->bg_opa = lv_obj_get_style_bg_opa(obj, part); - if(draw_dsc->bg_opa > LV_OPA_MIN) { - draw_dsc->bg_color = lv_obj_get_style_bg_color_filtered(obj, part); - } - } - - draw_dsc->border_width = lv_obj_get_style_border_width(obj, part); - if(draw_dsc->border_width) { - if(draw_dsc->border_opa != LV_OPA_TRANSP) { - draw_dsc->border_opa = lv_obj_get_style_border_opa(obj, part); - if(draw_dsc->border_opa > LV_OPA_MIN) { - draw_dsc->border_color = lv_obj_get_style_border_color_filtered(obj, part); - draw_dsc->border_side = lv_obj_get_style_border_side(obj, part); - } - } - } - - draw_dsc->outline_width = lv_obj_get_style_outline_width(obj, part); - if(draw_dsc->outline_width) { - if(draw_dsc->outline_opa != LV_OPA_TRANSP) { - draw_dsc->outline_opa = lv_obj_get_style_outline_opa(obj, part); - if(draw_dsc->outline_opa > LV_OPA_MIN) { - draw_dsc->outline_pad = lv_obj_get_style_outline_pad(obj, part); - draw_dsc->outline_color = lv_obj_get_style_outline_color_filtered(obj, part); - } - } - } - - if(draw_dsc->bg_img_opa != LV_OPA_TRANSP) { - draw_dsc->bg_img_src = lv_obj_get_style_bg_img_src(obj, part); - if(draw_dsc->bg_img_src) { - draw_dsc->bg_img_opa = lv_obj_get_style_bg_img_opa(obj, part); - if(draw_dsc->bg_img_opa > LV_OPA_MIN) { - if(lv_img_src_get_type(draw_dsc->bg_img_src) == LV_IMG_SRC_SYMBOL) { - draw_dsc->bg_img_symbol_font = lv_obj_get_style_text_font(obj, part); - draw_dsc->bg_img_recolor = lv_obj_get_style_text_color_filtered(obj, part); - } - else { - draw_dsc->bg_img_recolor = lv_obj_get_style_bg_img_recolor_filtered(obj, part); - draw_dsc->bg_img_recolor_opa = lv_obj_get_style_bg_img_recolor_opa(obj, part); - draw_dsc->bg_img_tiled = lv_obj_get_style_bg_img_tiled(obj, part); - } - } - } - } -#endif if(opa < LV_OPA_MAX) { - draw_dsc->bg_opa = (opa * draw_dsc->bg_opa) >> 8; - draw_dsc->bg_img_opa = (opa * draw_dsc->bg_img_opa) >> 8; - draw_dsc->border_opa = (opa * draw_dsc->border_opa) >> 8; - draw_dsc->outline_opa = (opa * draw_dsc->outline_opa) >> 8; - draw_dsc->shadow_opa = (opa * draw_dsc->shadow_opa) >> 8; + draw_dsc->bg_opa = LV_OPA_MIX2(draw_dsc->bg_opa, opa); + draw_dsc->bg_image_opa = LV_OPA_MIX2(draw_dsc->bg_image_opa, opa); + draw_dsc->border_opa = LV_OPA_MIX2(draw_dsc->border_opa, opa); + draw_dsc->shadow_opa = LV_OPA_MIX2(draw_dsc->shadow_opa, opa); + draw_dsc->outline_opa = LV_OPA_MIX2(draw_dsc->outline_opa, opa); } } void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc) { + draw_dsc->base.obj = obj; + draw_dsc->base.part = part; + draw_dsc->opa = lv_obj_get_style_text_opa(obj, part); if(draw_dsc->opa <= LV_OPA_MIN) return; lv_opa_t opa = lv_obj_get_style_opa_recursive(obj, part); - if(opa <= LV_OPA_MIN) { - draw_dsc->opa = LV_OPA_TRANSP; - return; - } if(opa < LV_OPA_MAX) { - draw_dsc->opa = (opa * draw_dsc->opa) >> 8; + draw_dsc->opa = LV_OPA_MIX2(draw_dsc->opa, opa); } if(draw_dsc->opa <= LV_OPA_MIN) return; @@ -207,9 +160,7 @@ void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint32_t part, lv_draw_label_dsc draw_dsc->letter_space = lv_obj_get_style_text_letter_space(obj, part); draw_dsc->line_space = lv_obj_get_style_text_line_space(obj, part); draw_dsc->decor = lv_obj_get_style_text_decor(obj, part); -#if LV_DRAW_COMPLEX if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); -#endif draw_dsc->font = lv_obj_get_style_text_font(obj, part); @@ -220,47 +171,43 @@ void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint32_t part, lv_draw_label_dsc draw_dsc->align = lv_obj_get_style_text_align(obj, part); } -void lv_obj_init_draw_img_dsc(lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc) +void lv_obj_init_draw_image_dsc(lv_obj_t * obj, uint32_t part, lv_draw_image_dsc_t * draw_dsc) { - draw_dsc->opa = lv_obj_get_style_img_opa(obj, part); + draw_dsc->base.obj = obj; + draw_dsc->base.part = part; + + draw_dsc->opa = lv_obj_get_style_image_opa(obj, part); if(draw_dsc->opa <= LV_OPA_MIN) return; lv_opa_t opa = lv_obj_get_style_opa_recursive(obj, part); - if(opa <= LV_OPA_MIN) { - draw_dsc->opa = LV_OPA_TRANSP; - return; - } if(opa < LV_OPA_MAX) { - draw_dsc->opa = (opa * draw_dsc->opa) >> 8; + draw_dsc->opa = LV_OPA_MIX2(draw_dsc->opa, opa); } if(draw_dsc->opa <= LV_OPA_MIN) return; - draw_dsc->angle = 0; - draw_dsc->zoom = LV_IMG_ZOOM_NONE; + draw_dsc->rotation = 0; + draw_dsc->scale_x = LV_SCALE_NONE; + draw_dsc->scale_y = LV_SCALE_NONE; draw_dsc->pivot.x = lv_area_get_width(&obj->coords) / 2; draw_dsc->pivot.y = lv_area_get_height(&obj->coords) / 2; - draw_dsc->recolor_opa = lv_obj_get_style_img_recolor_opa(obj, part); - if(draw_dsc->recolor_opa > 0) { - draw_dsc->recolor = lv_obj_get_style_img_recolor_filtered(obj, part); - } -#if LV_DRAW_COMPLEX + draw_dsc->recolor_opa = lv_obj_get_style_image_recolor_opa(obj, part); + draw_dsc->recolor = lv_obj_get_style_image_recolor_filtered(obj, part); + if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); -#endif } void lv_obj_init_draw_line_dsc(lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc) { + draw_dsc->base.obj = obj; + draw_dsc->base.part = part; + draw_dsc->opa = lv_obj_get_style_line_opa(obj, part); if(draw_dsc->opa <= LV_OPA_MIN) return; lv_opa_t opa = lv_obj_get_style_opa_recursive(obj, part); - if(opa <= LV_OPA_MIN) { - draw_dsc->opa = LV_OPA_TRANSP; - return; - } if(opa < LV_OPA_MAX) { - draw_dsc->opa = (opa * draw_dsc->opa) >> 8; + draw_dsc->opa = LV_OPA_MIX2(draw_dsc->opa, opa); } if(draw_dsc->opa <= LV_OPA_MIN) return; @@ -277,13 +224,14 @@ void lv_obj_init_draw_line_dsc(lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t draw_dsc->round_start = lv_obj_get_style_line_rounded(obj, part); draw_dsc->round_end = draw_dsc->round_start; -#if LV_DRAW_COMPLEX if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); -#endif } void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc) { + draw_dsc->base.obj = obj; + draw_dsc->base.part = part; + draw_dsc->width = lv_obj_get_style_arc_width(obj, part); if(draw_dsc->width == 0) return; @@ -291,78 +239,58 @@ void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * if(draw_dsc->opa <= LV_OPA_MIN) return; lv_opa_t opa = lv_obj_get_style_opa_recursive(obj, part); - if(opa <= LV_OPA_MIN) { - draw_dsc->opa = LV_OPA_TRANSP; - return; - } if(opa < LV_OPA_MAX) { - draw_dsc->opa = (opa * draw_dsc->opa) >> 8; + draw_dsc->opa = LV_OPA_MIX2(draw_dsc->opa, opa); } if(draw_dsc->opa <= LV_OPA_MIN) return; draw_dsc->color = lv_obj_get_style_arc_color_filtered(obj, part); - draw_dsc->img_src = lv_obj_get_style_arc_img_src(obj, part); + draw_dsc->img_src = lv_obj_get_style_arc_image_src(obj, part); draw_dsc->rounded = lv_obj_get_style_arc_rounded(obj, part); - -#if LV_DRAW_COMPLEX - if(part != LV_PART_MAIN) draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part); -#endif } -lv_coord_t lv_obj_calculate_ext_draw_size(lv_obj_t * obj, uint32_t part) +int32_t lv_obj_calculate_ext_draw_size(lv_obj_t * obj, uint32_t part) { - lv_coord_t s = 0; + int32_t s = 0; - lv_coord_t sh_width = lv_obj_get_style_shadow_width(obj, part); + int32_t sh_width = lv_obj_get_style_shadow_width(obj, part); if(sh_width) { lv_opa_t sh_opa = lv_obj_get_style_shadow_opa(obj, part); if(sh_opa > LV_OPA_MIN) { sh_width = sh_width / 2 + 1; /*The blur adds only half width*/ sh_width += lv_obj_get_style_shadow_spread(obj, part); - lv_coord_t sh_ofs_x = lv_obj_get_style_shadow_ofs_x(obj, part); - lv_coord_t sh_ofs_y = lv_obj_get_style_shadow_ofs_y(obj, part); + int32_t sh_ofs_x = lv_obj_get_style_shadow_offset_x(obj, part); + int32_t sh_ofs_y = lv_obj_get_style_shadow_offset_y(obj, part); sh_width += LV_MAX(LV_ABS(sh_ofs_x), LV_ABS(sh_ofs_y)); s = LV_MAX(s, sh_width); } } - lv_coord_t outline_width = lv_obj_get_style_outline_width(obj, part); + int32_t outline_width = lv_obj_get_style_outline_width(obj, part); if(outline_width) { lv_opa_t outline_opa = lv_obj_get_style_outline_opa(obj, part); if(outline_opa > LV_OPA_MIN) { - lv_coord_t outline_pad = lv_obj_get_style_outline_pad(obj, part); + int32_t outline_pad = lv_obj_get_style_outline_pad(obj, part); s = LV_MAX(s, outline_pad + outline_width); } } - lv_coord_t w = lv_obj_get_style_transform_width(obj, part); - lv_coord_t h = lv_obj_get_style_transform_height(obj, part); - lv_coord_t wh = LV_MAX(w, h); + int32_t w = lv_obj_get_style_transform_width(obj, part); + int32_t h = lv_obj_get_style_transform_height(obj, part); + int32_t wh = LV_MAX(w, h); if(wh > 0) s += wh; return s; } -void lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc, lv_draw_ctx_t * draw_ctx) -{ - lv_memset_00(dsc, sizeof(lv_obj_draw_part_dsc_t)); - dsc->draw_ctx = draw_ctx; -} - -bool lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc, const lv_obj_class_t * class_p, uint32_t type) -{ - if(dsc->class_p == class_p && dsc->type == type) return true; - else return false; -} - void lv_obj_refresh_ext_draw_size(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_coord_t s_old = _lv_obj_get_ext_draw_size(obj); - lv_coord_t s_new = 0; - lv_event_send(obj, LV_EVENT_REFR_EXT_DRAW_SIZE, &s_new); + int32_t s_old = _lv_obj_get_ext_draw_size(obj); + int32_t s_new = 0; + lv_obj_send_event(obj, LV_EVENT_REFR_EXT_DRAW_SIZE, &s_new); if(s_new != s_old) lv_obj_invalidate(obj); @@ -380,7 +308,7 @@ void lv_obj_refresh_ext_draw_size(lv_obj_t * obj) if(s_new != s_old) lv_obj_invalidate(obj); } -lv_coord_t _lv_obj_get_ext_draw_size(const lv_obj_t * obj) +int32_t _lv_obj_get_ext_draw_size(const lv_obj_t * obj) { if(obj->spec_attr) return obj->spec_attr->ext_draw_size; else return 0; @@ -389,7 +317,7 @@ lv_coord_t _lv_obj_get_ext_draw_size(const lv_obj_t * obj) lv_layer_type_t _lv_obj_get_layer_type(const lv_obj_t * obj) { - if(obj->spec_attr) return obj->spec_attr->layer_type; + if(obj->spec_attr) return (lv_layer_type_t)obj->spec_attr->layer_type; else return LV_LAYER_TYPE_NONE; } diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.h index 3f9d0f30f..ad4f08721 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.h @@ -13,6 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ +#include "../misc/lv_types.h" #include "../draw/lv_draw.h" /********************* @@ -23,49 +24,12 @@ extern "C" { * TYPEDEFS **********************/ -struct _lv_obj_t; -struct _lv_obj_class_t; - -/** Cover check results.*/ -typedef enum { - LV_COVER_RES_COVER = 0, - LV_COVER_RES_NOT_COVER = 1, - LV_COVER_RES_MASKED = 2, -} lv_cover_res_t; - typedef enum { LV_LAYER_TYPE_NONE, LV_LAYER_TYPE_SIMPLE, LV_LAYER_TYPE_TRANSFORM, } lv_layer_type_t; -typedef struct { - lv_draw_ctx_t * draw_ctx; /**< Draw context*/ - const struct _lv_obj_class_t * class_p; /**< The class that sent the event */ - uint32_t type; /**< The type if part being draw. Element of `lv__draw_part_type_t` */ - lv_area_t * draw_area; /**< The area of the part being drawn*/ - lv_draw_rect_dsc_t * - rect_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for rectangle-like parts*/ - lv_draw_label_dsc_t * - label_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for text-like parts*/ - lv_draw_line_dsc_t * - line_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for line-like parts*/ - lv_draw_img_dsc_t * - img_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for image-like parts*/ - lv_draw_arc_dsc_t * - arc_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for arc-like parts*/ - const lv_point_t * - p1; /**< A point calculated during drawing. E.g. a point of chart or the center of an arc.*/ - const lv_point_t * p2; /**< A point calculated during drawing. E.g. a point of chart.*/ - char * text; /**< A text calculated during drawing. Can be modified. E.g. tick labels on a chart axis.*/ - uint32_t text_length; /**< Size of the text buffer containing null-terminated text string calculated during drawing.*/ - uint32_t part; /**< The current part for which the event is sent*/ - uint32_t id; /**< The index of the part. E.g. a button's index on button matrix or table cell index.*/ - lv_coord_t radius; /**< E.g. the radius of an arc (not the corner radius).*/ - int32_t value; /**< A value calculated during drawing. E.g. Chart's tick line value.*/ - const void * sub_part_ptr; /**< A pointer the identifies something in the part. E.g. chart series. */ -} lv_obj_draw_part_dsc_t; - /********************** * GLOBAL PROTOTYPES **********************/ @@ -80,7 +44,7 @@ typedef struct { * @note Only the relevant fields will be set. * E.g. if `border width == 0` the other border properties won't be evaluated. */ -void lv_obj_init_draw_rect_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t * draw_dsc); +void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t * draw_dsc); /** * Initialize a label draw descriptor from an object's styles in its current state @@ -90,7 +54,7 @@ void lv_obj_init_draw_rect_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_re * If the `opa` field is set to or the property is equal to `LV_OPA_TRANSP` the rest won't be initialized. * Should be initialized with `lv_draw_label_dsc_init(draw_dsc)`. */ -void lv_obj_init_draw_label_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc); +void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc); /** * Initialize an image draw descriptor from an object's styles in its current state @@ -99,8 +63,7 @@ void lv_obj_init_draw_label_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_l * @param draw_dsc the descriptor to initialize. * Should be initialized with `lv_draw_image_dsc_init(draw_dsc)`. */ -void lv_obj_init_draw_img_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc); - +void lv_obj_init_draw_image_dsc(lv_obj_t * obj, uint32_t part, lv_draw_image_dsc_t * draw_dsc); /** * Initialize a line draw descriptor from an object's styles in its current state @@ -109,7 +72,7 @@ void lv_obj_init_draw_img_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_img * @param draw_dsc the descriptor to initialize. * Should be initialized with `lv_draw_line_dsc_init(draw_dsc)`. */ -void lv_obj_init_draw_line_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc); +void lv_obj_init_draw_line_dsc(lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc); /** * Initialize an arc draw descriptor from an object's styles in its current state @@ -118,7 +81,7 @@ void lv_obj_init_draw_line_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_li * @param draw_dsc the descriptor to initialize. * Should be initialized with `lv_draw_arc_dsc_init(draw_dsc)`. */ -void lv_obj_init_draw_arc_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc); +void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc); /** * Get the required extra size (around the object's part) to draw shadow, outline, value etc. @@ -126,40 +89,23 @@ void lv_obj_init_draw_arc_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_arc * @param part part of the object * @return the extra size required around the object */ -lv_coord_t lv_obj_calculate_ext_draw_size(struct _lv_obj_t * obj, uint32_t part); - -/** - * Initialize a draw descriptor used in events. - * @param dsc pointer to a descriptor. Later it should be passed as parameter to an `LV_EVENT_DRAW_PART_BEGIN/END` event. - * @param draw the current draw context. (usually returned by `lv_event_get_draw_ctx(e)`) - */ -void lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc, lv_draw_ctx_t * draw_ctx); - -/** - * Check the type obj a part draw descriptor - * @param dsc the descriptor (normally the event parameter) - * @param class_p pointer to class to which `type` is related - * @param type element of `lv__draw_part_type_t` - * @return true if ::dsc is related to ::class_p and ::type - */ -bool lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc, const struct _lv_obj_class_t * class_p, uint32_t type); +int32_t lv_obj_calculate_ext_draw_size(lv_obj_t * obj, uint32_t part); /** * Send a 'LV_EVENT_REFR_EXT_DRAW_SIZE' Call the ancestor's event handler to the object to refresh the value of the extended draw size. * The result will be saved in `obj`. * @param obj pointer to an object */ -void lv_obj_refresh_ext_draw_size(struct _lv_obj_t * obj); +void lv_obj_refresh_ext_draw_size(lv_obj_t * obj); /** * Get the extended draw area of an object. * @param obj pointer to an object * @return the size extended draw area around the real coordinates */ -lv_coord_t _lv_obj_get_ext_draw_size(const struct _lv_obj_t * obj); +int32_t _lv_obj_get_ext_draw_size(const lv_obj_t * obj); - -lv_layer_type_t _lv_obj_get_layer_type(const struct _lv_obj_t * obj); +lv_layer_type_t _lv_obj_get_layer_type(const lv_obj_t * obj); /********************** * MACROS diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_event.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_event.c new file mode 100644 index 000000000..bafcdcf3c --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_event.c @@ -0,0 +1,394 @@ +/** + * @file lv_obj_event.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_obj.h" +#include "../indev/lv_indev.h" +#include "../indev/lv_indev_private.h" + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_obj_class + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static lv_result_t event_send_core(lv_event_t * e); +static bool event_is_bubbled(lv_event_t * e); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ +#if LV_USE_LOG && LV_LOG_TRACE_EVENT + #define LV_TRACE_EVENT(...) LV_LOG_TRACE(__VA_ARGS__) +#else + #define LV_TRACE_EVENT(...) +#endif + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_result_t lv_obj_send_event(lv_obj_t * obj, lv_event_code_t event_code, void * param) +{ + if(obj == NULL) return LV_RESULT_OK; + + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_event_t e; + e.current_target = obj; + e.original_target = obj; + e.code = event_code; + e.user_data = NULL; + e.param = param; + e.deleted = 0; + e.stop_bubbling = 0; + e.stop_processing = 0; + + _lv_event_push(&e); + + /*Send the event*/ + lv_result_t res = event_send_core(&e); + + /*Remove this element from the list*/ + _lv_event_pop(&e); + + return res; +} + +lv_result_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e) +{ + const lv_obj_class_t * base; + if(class_p == NULL) base = ((lv_obj_t *)e->current_target)->class_p; + else base = class_p->base_class; + + /*Find a base in which call the ancestor's event handler_cb if set*/ + while(base && base->event_cb == NULL) base = base->base_class; + + if(base == NULL) return LV_RESULT_OK; + if(base->event_cb == NULL) return LV_RESULT_OK; + + /*Call the actual event callback*/ + e->user_data = NULL; + base->event_cb(base, e); + + lv_result_t res = LV_RESULT_OK; + /*Stop if the object is deleted*/ + if(e->deleted) res = LV_RESULT_INVALID; + + return res; +} + +void lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, + void * user_data) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_obj_allocate_spec_attr(obj); + + lv_event_add(&obj->spec_attr->event_list, event_cb, filter, user_data); +} + +uint32_t lv_obj_get_event_count(lv_obj_t * obj) +{ + LV_ASSERT_NULL(obj); + if(obj->spec_attr == NULL) return 0; + return lv_event_get_count(&obj->spec_attr->event_list); +} + +lv_event_dsc_t * lv_obj_get_event_dsc(lv_obj_t * obj, uint32_t index) +{ + LV_ASSERT_NULL(obj); + if(obj->spec_attr == NULL) return NULL; + return lv_event_get_dsc(&obj->spec_attr->event_list, index); +} + +bool lv_obj_remove_event(lv_obj_t * obj, uint32_t index) +{ + LV_ASSERT_NULL(obj); + if(obj->spec_attr == NULL) return false; + return lv_event_remove(&obj->spec_attr->event_list, index); +} + +bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb) +{ + LV_ASSERT_NULL(obj); + + uint32_t event_cnt = lv_obj_get_event_count(obj); + uint32_t i; + for(i = 0; i < event_cnt; i++) { + lv_event_dsc_t * dsc = lv_obj_get_event_dsc(obj, i); + if(dsc->cb == event_cb) { + lv_obj_remove_event(obj, i); + return true; + } + } + + return false; +} + +uint32_t lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj, lv_event_cb_t event_cb, void * user_data) +{ + LV_ASSERT_NULL(obj); + + uint32_t event_cnt = lv_obj_get_event_count(obj); + uint32_t removed_count = 0; + int32_t i; + + for(i = event_cnt - 1; i >= 0; i--) { + lv_event_dsc_t * dsc = lv_obj_get_event_dsc(obj, i); + if(dsc && dsc->cb == event_cb && dsc->user_data == user_data) { + lv_obj_remove_event(obj, i); + removed_count ++; + } + } + + return removed_count; +} + +lv_obj_t * lv_event_get_current_target_obj(lv_event_t * e) +{ + return lv_event_get_current_target(e); +} + +lv_obj_t * lv_event_get_target_obj(lv_event_t * e) +{ + return lv_event_get_target(e); +} + +lv_indev_t * lv_event_get_indev(lv_event_t * e) +{ + + if(e->code == LV_EVENT_PRESSED || + e->code == LV_EVENT_PRESSING || + e->code == LV_EVENT_PRESS_LOST || + e->code == LV_EVENT_SHORT_CLICKED || + e->code == LV_EVENT_LONG_PRESSED || + e->code == LV_EVENT_LONG_PRESSED_REPEAT || + e->code == LV_EVENT_CLICKED || + e->code == LV_EVENT_RELEASED || + e->code == LV_EVENT_SCROLL_BEGIN || + e->code == LV_EVENT_SCROLL_END || + e->code == LV_EVENT_SCROLL || + e->code == LV_EVENT_GESTURE || + e->code == LV_EVENT_KEY || + e->code == LV_EVENT_FOCUSED || + e->code == LV_EVENT_DEFOCUSED || + e->code == LV_EVENT_LEAVE) { + return lv_event_get_param(e); + } + else { + LV_LOG_WARN("Not interpreted with this event code"); + return NULL; + } +} + +lv_layer_t * lv_event_get_layer(lv_event_t * e) +{ + if(e->code == LV_EVENT_DRAW_MAIN || + e->code == LV_EVENT_DRAW_MAIN_BEGIN || + e->code == LV_EVENT_DRAW_MAIN_END || + e->code == LV_EVENT_DRAW_POST || + e->code == LV_EVENT_DRAW_POST_BEGIN || + e->code == LV_EVENT_DRAW_POST_END) { + return lv_event_get_param(e); + } + else { + LV_LOG_WARN("Not interpreted with this event code"); + return NULL; + } +} + +const lv_area_t * lv_event_get_old_size(lv_event_t * e) +{ + if(e->code == LV_EVENT_SIZE_CHANGED) { + return lv_event_get_param(e); + } + else { + LV_LOG_WARN("Not interpreted with this event code"); + return NULL; + } +} + +uint32_t lv_event_get_key(lv_event_t * e) +{ + if(e->code == LV_EVENT_KEY) { + uint32_t * k = lv_event_get_param(e); + if(k) return *k; + else return 0; + } + else { + LV_LOG_WARN("Not interpreted with this event code"); + return 0; + } +} + +lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e) +{ + if(e->code == LV_EVENT_SCROLL_BEGIN) { + return lv_event_get_param(e); + } + else { + LV_LOG_WARN("Not interpreted with this event code"); + return NULL; + } +} + +void lv_event_set_ext_draw_size(lv_event_t * e, int32_t size) +{ + if(e->code == LV_EVENT_REFR_EXT_DRAW_SIZE) { + int32_t * cur_size = lv_event_get_param(e); + *cur_size = LV_MAX(*cur_size, size); + } + else { + LV_LOG_WARN("Not interpreted with this event code"); + } +} + +lv_point_t * lv_event_get_self_size_info(lv_event_t * e) +{ + if(e->code == LV_EVENT_GET_SELF_SIZE) { + return lv_event_get_param(e); + } + else { + LV_LOG_WARN("Not interpreted with this event code"); + return 0; + } +} + +lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e) +{ + if(e->code == LV_EVENT_HIT_TEST) { + return lv_event_get_param(e); + } + else { + LV_LOG_WARN("Not interpreted with this event code"); + return 0; + } +} + +const lv_area_t * lv_event_get_cover_area(lv_event_t * e) +{ + if(e->code == LV_EVENT_COVER_CHECK) { + lv_cover_check_info_t * p = lv_event_get_param(e); + return p->area; + } + else { + LV_LOG_WARN("Not interpreted with this event code"); + return NULL; + } +} + +void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res) +{ + if(e->code == LV_EVENT_COVER_CHECK) { + lv_cover_check_info_t * p = lv_event_get_param(e); + if(res > p->res) p->res = res; /*Save only "stronger" results*/ + } + else { + LV_LOG_WARN("Not interpreted with this event code"); + } +} + +lv_draw_task_t * lv_event_get_draw_task(lv_event_t * e) +{ + if(e->code == LV_EVENT_DRAW_TASK_ADDED) { + return lv_event_get_param(e); + } + else { + LV_LOG_WARN("Not interpreted with this event code"); + return NULL; + } + +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static lv_result_t event_send_core(lv_event_t * e) +{ + LV_TRACE_EVENT("Sending event %d to %p with %p param", e->code, (void *)e->original_target, e->param); + + /*Call the input device's feedback callback if set*/ + lv_indev_t * indev_act = lv_indev_active(); + if(indev_act) { + if(e->stop_processing) return LV_RESULT_OK; + if(e->deleted) return LV_RESULT_INVALID; + } + + lv_obj_t * target = e->current_target; + lv_result_t res = LV_RESULT_OK; + lv_event_list_t * list = target->spec_attr ? &target->spec_attr->event_list : NULL; + + res = lv_event_send(list, e, true); + if(res != LV_RESULT_OK) return res; + + res = lv_obj_event_base(NULL, e); + if(res != LV_RESULT_OK) return res; + + res = lv_event_send(list, e, false); + if(res != LV_RESULT_OK) return res; + + lv_obj_t * parent = lv_obj_get_parent(e->current_target); + if(parent && event_is_bubbled(e)) { + e->current_target = parent; + res = event_send_core(e); + if(res != LV_RESULT_OK) return res; + } + + return res; +} + +static bool event_is_bubbled(lv_event_t * e) +{ + if(e->stop_bubbling) return false; + + /*Event codes that always bubble*/ + switch(e->code) { + case LV_EVENT_CHILD_CREATED: + case LV_EVENT_CHILD_DELETED: + return true; + default: + break; + } + + /*Check other codes only if bubbling is enabled*/ + if(lv_obj_has_flag(e->current_target, LV_OBJ_FLAG_EVENT_BUBBLE) == false) return false; + + switch(e->code) { + case LV_EVENT_HIT_TEST: + case LV_EVENT_COVER_CHECK: + case LV_EVENT_REFR_EXT_DRAW_SIZE: + case LV_EVENT_DRAW_MAIN_BEGIN: + case LV_EVENT_DRAW_MAIN: + case LV_EVENT_DRAW_MAIN_END: + case LV_EVENT_DRAW_POST_BEGIN: + case LV_EVENT_DRAW_POST: + case LV_EVENT_DRAW_POST_END: + case LV_EVENT_DRAW_TASK_ADDED: + case LV_EVENT_REFRESH: + case LV_EVENT_DELETE: + case LV_EVENT_CHILD_CREATED: + case LV_EVENT_CHILD_DELETED: + case LV_EVENT_CHILD_CHANGED: + case LV_EVENT_SIZE_CHANGED: + case LV_EVENT_STYLE_CHANGED: + case LV_EVENT_GET_SELF_SIZE: + return false; + default: + return true; + } +} diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_event.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_event.h new file mode 100644 index 000000000..580692e61 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_event.h @@ -0,0 +1,212 @@ +/** + * @file lv_obj_event.h + * + */ + +#ifndef LV_OBJ_EVENT_H +#define LV_OBJ_EVENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include "../misc/lv_types.h" +#include "../misc/lv_event.h" +#include "../indev/lv_indev.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** + * Used as the event parameter of ::LV_EVENT_HIT_TEST to check if an `point` can click the object or not. + * `res` should be set like this: + * - If already set to `false` an other event wants that point non clickable. If you want to respect it leave it as `false` or set `true` to overwrite it. + * - If already set `true` and `point` shouldn't be clickable set to `false` + * - If already set to `true` you agree that `point` can click the object leave it as `true` + */ +typedef struct { + const lv_point_t * point; /**< A point relative to screen to check if it can click the object or not*/ + bool res; /**< true: `point` can click the object; false: it cannot*/ +} lv_hit_test_info_t; + +/** Cover check results.*/ +typedef enum { + LV_COVER_RES_COVER = 0, + LV_COVER_RES_NOT_COVER = 1, + LV_COVER_RES_MASKED = 2, +} lv_cover_res_t; + +/** + * Used as the event parameter of ::LV_EVENT_COVER_CHECK to check if an area is covered by the object or not. + * In the event use `const lv_area_t * area = lv_event_get_cover_area(e)` to get the area to check + * and `lv_event_set_cover_res(e, res)` to set the result. + */ +typedef struct { + lv_cover_res_t res; + const lv_area_t * area; +} lv_cover_check_info_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Send an event to the object + * @param obj pointer to an object + * @param event_code the type of the event from `lv_event_t` + * @param param arbitrary data depending on the widget type and the event. (Usually `NULL`) + * @return LV_RESULT_OK: `obj` was not deleted in the event; LV_RESULT_INVALID: `obj` was deleted in the event_code + */ +lv_result_t lv_obj_send_event(lv_obj_t * obj, lv_event_code_t event_code, void * param); + +/** + * Used by the widgets internally to call the ancestor widget types's event handler + * @param class_p pointer to the class of the widget (NOT the ancestor class) + * @param e pointer to the event descriptor + * @return LV_RESULT_OK: the target object was not deleted in the event; LV_RESULT_INVALID: it was deleted in the event_code + */ +lv_result_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e); + +/** + * Get the current target of the event. It's the object which event handler being called. + * If the event is not bubbled it's the same as "original" target. + * @param e pointer to the event descriptor + * @return the target of the event_code + */ +lv_obj_t * lv_event_get_current_target_obj(lv_event_t * e); + +/** + * Get the object originally targeted by the event. It's the same even if the event is bubbled. + * @param e pointer to the event descriptor + * @return pointer to the original target of the event_code + */ +lv_obj_t * lv_event_get_target_obj(lv_event_t * e); + +/** + * Add an event handler function for an object. + * Used by the user to react on event which happens with the object. + * An object can have multiple event handler. They will be called in the same order as they were added. + * @param obj pointer to an object + * @param filter an event code (e.g. `LV_EVENT_CLICKED`) on which the event should be called. `LV_EVENT_ALL` can be used to receive all the events. + * @param event_cb the new event function + * @param user_data custom data data will be available in `event_cb` + */ +void lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter, + void * user_data); + +uint32_t lv_obj_get_event_count(lv_obj_t * obj); + +lv_event_dsc_t * lv_obj_get_event_dsc(lv_obj_t * obj, uint32_t index); + +bool lv_obj_remove_event(lv_obj_t * obj, uint32_t index); + +bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb); + +/** + * Remove an event_cb with user_data + * @param obj pointer to a obj + * @param event_cb the event_cb of the event to remove + * @param user_data user_data + * @return the count of the event removed + */ +uint32_t lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj, lv_event_cb_t event_cb, void * user_data); + +/** + * Get the input device passed as parameter to indev related events. + * @param e pointer to an event + * @return the indev that triggered the event or NULL if called on a not indev related event + */ +lv_indev_t * lv_event_get_indev(lv_event_t * e); + +/** + * Get the draw context which should be the first parameter of the draw functions. + * Namely: `LV_EVENT_DRAW_MAIN/POST`, `LV_EVENT_DRAW_MAIN/POST_BEGIN`, `LV_EVENT_DRAW_MAIN/POST_END` + * @param e pointer to an event + * @return pointer to a draw context or NULL if called on an unrelated event + */ +lv_layer_t * lv_event_get_layer(lv_event_t * e); + +/** + * Get the old area of the object before its size was changed. Can be used in `LV_EVENT_SIZE_CHANGED` + * @param e pointer to an event + * @return the old absolute area of the object or NULL if called on an unrelated event + */ +const lv_area_t * lv_event_get_old_size(lv_event_t * e); + +/** + * Get the key passed as parameter to an event. Can be used in `LV_EVENT_KEY` + * @param e pointer to an event + * @return the triggering key or NULL if called on an unrelated event + */ +uint32_t lv_event_get_key(lv_event_t * e); + +/** + * Get the animation descriptor of a scrolling. Can be used in `LV_EVENT_SCROLL_BEGIN` + * @param e pointer to an event + * @return the animation that will scroll the object. (can be modified as required) + */ +lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e); + +/** + * Set the new extra draw size. Can be used in `LV_EVENT_REFR_EXT_DRAW_SIZE` + * @param e pointer to an event + * @param size The new extra draw size + */ +void lv_event_set_ext_draw_size(lv_event_t * e, int32_t size); + +/** + * Get a pointer to an `lv_point_t` variable in which the self size should be saved (width in `point->x` and height `point->y`). + * Can be used in `LV_EVENT_GET_SELF_SIZE` + * @param e pointer to an event + * @return pointer to `lv_point_t` or NULL if called on an unrelated event + */ +lv_point_t * lv_event_get_self_size_info(lv_event_t * e); + +/** + * Get a pointer to an `lv_hit_test_info_t` variable in which the hit test result should be saved. Can be used in `LV_EVENT_HIT_TEST` + * @param e pointer to an event + * @return pointer to `lv_hit_test_info_t` or NULL if called on an unrelated event + */ +lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e); + +/** + * Get a pointer to an area which should be examined whether the object fully covers it or not. + * Can be used in `LV_EVENT_HIT_TEST` + * @param e pointer to an event + * @return an area with absolute coordinates to check + */ +const lv_area_t * lv_event_get_cover_area(lv_event_t * e); + +/** + * Set the result of cover checking. Can be used in `LV_EVENT_COVER_CHECK` + * @param e pointer to an event + * @param res an element of ::lv_cover_check_info_t + */ +void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res); + +/** + * Get the draw task which was just added. + * Can be used in `LV_EVENT_DRAW_TASK_ADDED event` + * @param e pointer to an event + * @return the added draw task + */ +lv_draw_task_t * lv_event_get_draw_task(lv_event_t * e); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_OBJ_EVENT_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_id_builtin.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_id_builtin.c new file mode 100644 index 000000000..4e1976bce --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_id_builtin.c @@ -0,0 +1,108 @@ +/** + * @file lv_obj_id.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_obj.h" +#include "lv_global.h" +#include "../osal/lv_os.h" +#include "../stdlib/lv_sprintf.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +typedef struct _class_info_t { + const lv_obj_class_t * class_p; + uint32_t obj_count; +} class_info_t; + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +#if LV_USE_OBJ_ID_BUILTIN + +void lv_obj_assign_id(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_ASSERT(obj && class_p); + + uint32_t i; + uint32_t id = 0; + lv_global_t * global = LV_GLOBAL_DEFAULT(); + class_info_t * info = NULL; + + if(obj == NULL || class_p == NULL) return; + if(global == NULL) return; + + obj->id = NULL; + + for(i = 0; i < global->objid_count; i ++) { + info = ((class_info_t *)global->objid_array) + i; + if(class_p == info->class_p) break; + } + + /*Resize array*/ + if(i == global->objid_count) { + void * array = lv_realloc(global->objid_array, sizeof(class_info_t) * (global->objid_count + 1)); + LV_ASSERT_MALLOC(array); + if(array == NULL) return; + global->objid_array = array; + global->objid_count ++; + info = ((class_info_t *)global->objid_array) + i; + info->obj_count = 0; + info->class_p = class_p; + } + + id = ++info->obj_count; + + obj->id = (void *)(lv_uintptr_t)id; +} + +void lv_obj_free_id(lv_obj_t * obj) +{ + LV_UNUSED(obj); +} + +const char * lv_obj_stringify_id(lv_obj_t * obj, char * buf, uint32_t len) +{ + const char * name; + if(obj == NULL || obj->class_p == NULL) return NULL; + if(buf == NULL) return NULL; + + name = obj->class_p->name; + if(name == NULL) name = "nameless"; + + lv_snprintf(buf, len, "%s%" LV_PRId32 "", name, (uint32_t)(lv_uintptr_t)obj->id); + return buf; +} + +void lv_objid_builtin_destroy(void) +{ + lv_global_t * global = LV_GLOBAL_DEFAULT(); + if(global == NULL) return; + + lv_free(global->objid_array); + global->objid_count = 0; +} + +#endif /*LV_USE_OBJ_ID_BUILTIN*/ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.c index c50ea3a3c..d79af8b44 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.c @@ -7,14 +7,16 @@ * INCLUDES *********************/ #include "lv_obj.h" -#include "lv_disp.h" +#include "../display/lv_display.h" +#include "../display/lv_display_private.h" #include "lv_refr.h" -#include "../misc/lv_gc.h" +#include "../core/lv_global.h" /********************* * DEFINES *********************/ #define MY_CLASS &lv_obj_class +#define update_layout_mutex LV_GLOBAL_DEFAULT()->layout_update_mutex /********************** * TYPEDEFS @@ -23,15 +25,14 @@ /********************** * STATIC PROTOTYPES **********************/ -static lv_coord_t calc_content_width(lv_obj_t * obj); -static lv_coord_t calc_content_height(lv_obj_t * obj); +static int32_t calc_content_width(lv_obj_t * obj); +static int32_t calc_content_height(lv_obj_t * obj); static void layout_update_core(lv_obj_t * obj); static void transform_point(const lv_obj_t * obj, lv_point_t * p, bool inv); /********************** * STATIC VARIABLES **********************/ -static uint32_t layout_cnt; /********************** * MACROS @@ -41,7 +42,7 @@ static uint32_t layout_cnt; * GLOBAL FUNCTIONS **********************/ -void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) +void lv_obj_set_pos(lv_obj_t * obj, int32_t x, int32_t y) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -49,30 +50,30 @@ void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) lv_obj_set_y(obj, y); } -void lv_obj_set_x(lv_obj_t * obj, lv_coord_t x) +void lv_obj_set_x(lv_obj_t * obj, int32_t x) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_res_t res_x; + lv_result_t res_x; lv_style_value_t v_x; res_x = lv_obj_get_local_style_prop(obj, LV_STYLE_X, &v_x, 0); - if((res_x == LV_RES_OK && v_x.num != x) || res_x == LV_RES_INV) { + if((res_x == LV_RESULT_OK && v_x.num != x) || res_x == LV_RESULT_INVALID) { lv_obj_set_style_x(obj, x, 0); } } -void lv_obj_set_y(lv_obj_t * obj, lv_coord_t y) +void lv_obj_set_y(lv_obj_t * obj, int32_t y) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_res_t res_y; + lv_result_t res_y; lv_style_value_t v_y; res_y = lv_obj_get_local_style_prop(obj, LV_STYLE_Y, &v_y, 0); - if((res_y == LV_RES_OK && v_y.num != y) || res_y == LV_RES_INV) { + if((res_y == LV_RESULT_OK && v_y.num != y) || res_y == LV_RESULT_INVALID) { lv_obj_set_style_y(obj, y, 0); } } @@ -87,19 +88,18 @@ bool lv_obj_refr_size(lv_obj_t * obj) lv_obj_t * parent = lv_obj_get_parent(obj); if(parent == NULL) return false; - lv_coord_t sl_ori = lv_obj_get_scroll_left(obj); bool w_is_content = false; bool w_is_pct = false; - lv_coord_t w; + int32_t w; if(obj->w_layout) { w = lv_obj_get_width(obj); } else { w = lv_obj_get_style_width(obj, LV_PART_MAIN); - w_is_content = w == LV_SIZE_CONTENT ? true : false; - w_is_pct = LV_COORD_IS_PCT(w) ? true : false; - lv_coord_t parent_w = lv_obj_get_content_width(parent); + w_is_content = w == LV_SIZE_CONTENT; + w_is_pct = LV_COORD_IS_PCT(w); + int32_t parent_w = lv_obj_get_content_width(parent); if(w_is_content) { w = calc_content_width(obj); @@ -108,22 +108,20 @@ bool lv_obj_refr_size(lv_obj_t * obj) /*If parent has content size and the child has pct size *a circular dependency will occur. To solve it keep child size at zero */ if(parent->w_layout == 0 && lv_obj_get_style_width(parent, 0) == LV_SIZE_CONTENT) { - lv_coord_t border_w = lv_obj_get_style_border_width(obj, 0); - w = lv_obj_get_style_pad_left(obj, 0) + border_w; - w += lv_obj_get_style_pad_right(obj, 0) + border_w; + w = lv_obj_get_style_space_left(obj, 0) + lv_obj_get_style_space_right(obj, 0); } else { w = (LV_COORD_GET_PCT(w) * parent_w) / 100; + w -= lv_obj_get_style_margin_left(obj, LV_PART_MAIN) + lv_obj_get_style_margin_right(obj, LV_PART_MAIN); } } - lv_coord_t minw = lv_obj_get_style_min_width(obj, LV_PART_MAIN); - lv_coord_t maxw = lv_obj_get_style_max_width(obj, LV_PART_MAIN); + int32_t minw = lv_obj_get_style_min_width(obj, LV_PART_MAIN); + int32_t maxw = lv_obj_get_style_max_width(obj, LV_PART_MAIN); w = lv_clamp_width(w, minw, maxw, parent_w); } - lv_coord_t st_ori = lv_obj_get_scroll_top(obj); - lv_coord_t h; + int32_t h; bool h_is_content = false; bool h_is_pct = false; if(obj->h_layout) { @@ -131,9 +129,9 @@ bool lv_obj_refr_size(lv_obj_t * obj) } else { h = lv_obj_get_style_height(obj, LV_PART_MAIN); - h_is_content = h == LV_SIZE_CONTENT ? true : false; - h_is_pct = LV_COORD_IS_PCT(h) ? true : false; - lv_coord_t parent_h = lv_obj_get_content_height(parent); + h_is_content = h == LV_SIZE_CONTENT; + h_is_pct = LV_COORD_IS_PCT(h); + int32_t parent_h = lv_obj_get_content_height(parent); if(h_is_content) { h = calc_content_height(obj); @@ -142,25 +140,19 @@ bool lv_obj_refr_size(lv_obj_t * obj) /*If parent has content size and the child has pct size *a circular dependency will occur. To solve it keep child size at zero */ if(parent->h_layout == 0 && lv_obj_get_style_height(parent, 0) == LV_SIZE_CONTENT) { - lv_coord_t border_w = lv_obj_get_style_border_width(obj, 0); - h = lv_obj_get_style_pad_top(obj, 0) + border_w; - h += lv_obj_get_style_pad_bottom(obj, 0) + border_w; + h = lv_obj_get_style_space_top(obj, 0) + lv_obj_get_style_space_bottom(obj, 0); } else { h = (LV_COORD_GET_PCT(h) * parent_h) / 100; + h -= lv_obj_get_style_margin_top(obj, LV_PART_MAIN) + lv_obj_get_style_margin_bottom(obj, LV_PART_MAIN); } } - lv_coord_t minh = lv_obj_get_style_min_height(obj, LV_PART_MAIN); - lv_coord_t maxh = lv_obj_get_style_max_height(obj, LV_PART_MAIN); + int32_t minh = lv_obj_get_style_min_height(obj, LV_PART_MAIN); + int32_t maxh = lv_obj_get_style_max_height(obj, LV_PART_MAIN); h = lv_clamp_height(h, minh, maxh, parent_h); } - /*calc_auto_size set the scroll x/y to 0 so revert the original value*/ - if(w_is_content || h_is_content) { - lv_obj_scroll_to(obj, sl_ori, st_ori, LV_ANIM_OFF); - } - /*Do nothing if the size is not changed*/ /*It is very important else recursive resizing can occur without size change*/ if(lv_obj_get_width(obj) == w && lv_obj_get_height(obj) == h) return false; @@ -192,10 +184,10 @@ bool lv_obj_refr_size(lv_obj_t * obj) } /*Call the ancestor's event handler to the object with its new coordinates*/ - lv_event_send(obj, LV_EVENT_SIZE_CHANGED, &ori); + lv_obj_send_event(obj, LV_EVENT_SIZE_CHANGED, &ori); /*Call the ancestor's event handler to the parent too*/ - lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj); + lv_obj_send_event(parent, LV_EVENT_CHILD_CHANGED, obj); /*Invalidate the new area*/ lv_obj_invalidate(obj); @@ -212,7 +204,7 @@ bool lv_obj_refr_size(lv_obj_t * obj) return true; } -void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) +void lv_obj_set_size(lv_obj_t * obj, int32_t w, int32_t h) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -220,48 +212,44 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) lv_obj_set_height(obj, h); } -void lv_obj_set_width(lv_obj_t * obj, lv_coord_t w) +void lv_obj_set_width(lv_obj_t * obj, int32_t w) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_res_t res_w; + lv_result_t res_w; lv_style_value_t v_w; res_w = lv_obj_get_local_style_prop(obj, LV_STYLE_WIDTH, &v_w, 0); - if((res_w == LV_RES_OK && v_w.num != w) || res_w == LV_RES_INV) { + if((res_w == LV_RESULT_OK && v_w.num != w) || res_w == LV_RESULT_INVALID) { lv_obj_set_style_width(obj, w, 0); } } -void lv_obj_set_height(lv_obj_t * obj, lv_coord_t h) +void lv_obj_set_height(lv_obj_t * obj, int32_t h) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_res_t res_h; + lv_result_t res_h; lv_style_value_t v_h; res_h = lv_obj_get_local_style_prop(obj, LV_STYLE_HEIGHT, &v_h, 0); - if((res_h == LV_RES_OK && v_h.num != h) || res_h == LV_RES_INV) { + if((res_h == LV_RESULT_OK && v_h.num != h) || res_h == LV_RESULT_INVALID) { lv_obj_set_style_height(obj, h, 0); } } -void lv_obj_set_content_width(lv_obj_t * obj, lv_coord_t w) +void lv_obj_set_content_width(lv_obj_t * obj, int32_t w) { - lv_coord_t pleft = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t pright = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - - lv_obj_set_width(obj, w + pleft + pright + 2 * border_width); + int32_t left = lv_obj_get_style_space_left(obj, LV_PART_MAIN); + int32_t right = lv_obj_get_style_space_right(obj, LV_PART_MAIN); + lv_obj_set_width(obj, w + left + right); } -void lv_obj_set_content_height(lv_obj_t * obj, lv_coord_t h) +void lv_obj_set_content_height(lv_obj_t * obj, int32_t h) { - lv_coord_t ptop = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t pbottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - - lv_obj_set_height(obj, h + ptop + pbottom + 2 * border_width); + int32_t top = lv_obj_get_style_space_top(obj, LV_PART_MAIN); + int32_t bottom = lv_obj_get_style_space_bottom(obj, LV_PART_MAIN); + lv_obj_set_height(obj, h + top + bottom); } void lv_obj_set_layout(lv_obj_t * obj, uint32_t layout) @@ -294,41 +282,30 @@ void lv_obj_mark_layout_as_dirty(lv_obj_t * obj) scr->scr_layout_inv = 1; /*Make the display refreshing*/ - lv_disp_t * disp = lv_obj_get_disp(scr); - if(disp->refr_timer) lv_timer_resume(disp->refr_timer); + lv_display_t * disp = lv_obj_get_display(scr); + lv_display_send_event(disp, LV_EVENT_REFR_REQUEST, NULL); } void lv_obj_update_layout(const lv_obj_t * obj) { - static bool mutex = false; - if(mutex) { + if(update_layout_mutex) { LV_LOG_TRACE("Already running, returning"); return; } - mutex = true; + LV_PROFILER_BEGIN; + update_layout_mutex = true; lv_obj_t * scr = lv_obj_get_screen(obj); - - /*Repeat until there where layout invalidations*/ + /*Repeat until there are no more layout invalidations*/ while(scr->scr_layout_inv) { - LV_LOG_INFO("Layout update begin"); + LV_LOG_TRACE("Layout update begin"); scr->scr_layout_inv = 0; layout_update_core(scr); LV_LOG_TRACE("Layout update end"); } - mutex = false; -} - -uint32_t lv_layout_register(lv_layout_update_cb_t cb, void * user_data) -{ - layout_cnt++; - LV_GC_ROOT(_lv_layout_list) = lv_mem_realloc(LV_GC_ROOT(_lv_layout_list), layout_cnt * sizeof(lv_layout_dsc_t)); - LV_ASSERT_MALLOC(LV_GC_ROOT(_lv_layout_list)); - - LV_GC_ROOT(_lv_layout_list)[layout_cnt - 1].cb = cb; - LV_GC_ROOT(_lv_layout_list)[layout_cnt - 1].user_data = user_data; - return layout_cnt; /*No -1 to skip 0th index*/ + update_layout_mutex = false; + LV_PROFILER_END; } void lv_obj_set_align(lv_obj_t * obj, lv_align_t align) @@ -336,13 +313,13 @@ void lv_obj_set_align(lv_obj_t * obj, lv_align_t align) lv_obj_set_style_align(obj, align, 0); } -void lv_obj_align(lv_obj_t * obj, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs) +void lv_obj_align(lv_obj_t * obj, lv_align_t align, int32_t x_ofs, int32_t y_ofs) { lv_obj_set_style_align(obj, align, 0); lv_obj_set_pos(obj, x_ofs, y_ofs); } -void lv_obj_align_to(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs) +void lv_obj_align_to(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, int32_t x_ofs, int32_t y_ofs) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -351,17 +328,18 @@ void lv_obj_align_to(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv LV_ASSERT_OBJ(base, MY_CLASS); - lv_coord_t x = 0; - lv_coord_t y = 0; + int32_t x = 0; + int32_t y = 0; lv_obj_t * parent = lv_obj_get_parent(obj); - lv_coord_t pborder = lv_obj_get_style_border_width(parent, LV_PART_MAIN); - lv_coord_t pleft = lv_obj_get_style_pad_left(parent, LV_PART_MAIN) + pborder; - lv_coord_t ptop = lv_obj_get_style_pad_top(parent, LV_PART_MAIN) + pborder; - lv_coord_t bborder = lv_obj_get_style_border_width(base, LV_PART_MAIN); - lv_coord_t bleft = lv_obj_get_style_pad_left(base, LV_PART_MAIN) + bborder; - lv_coord_t btop = lv_obj_get_style_pad_top(base, LV_PART_MAIN) + bborder; + LV_ASSERT_OBJ(parent, MY_CLASS); + + int32_t pleft = lv_obj_get_style_space_left(parent, LV_PART_MAIN); + int32_t ptop = lv_obj_get_style_space_top(parent, LV_PART_MAIN); + + int32_t bleft = lv_obj_get_style_space_left(base, LV_PART_MAIN); + int32_t btop = lv_obj_get_style_space_top(base, LV_PART_MAIN); if(align == LV_ALIGN_DEFAULT) { if(lv_obj_get_style_base_dir(base, LV_PART_MAIN) == LV_BASE_DIR_RTL) align = LV_ALIGN_TOP_RIGHT; @@ -373,10 +351,12 @@ void lv_obj_align_to(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv x = lv_obj_get_content_width(base) / 2 - lv_obj_get_width(obj) / 2 + bleft; y = lv_obj_get_content_height(base) / 2 - lv_obj_get_height(obj) / 2 + btop; break; + case LV_ALIGN_TOP_LEFT: x = bleft; y = btop; break; + case LV_ALIGN_TOP_MID: x = lv_obj_get_content_width(base) / 2 - lv_obj_get_width(obj) / 2 + bleft; y = btop; @@ -472,6 +452,8 @@ void lv_obj_align_to(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv break; } + if(LV_COORD_IS_PCT(x_ofs)) x_ofs = (lv_obj_get_width(base) * LV_COORD_GET_PCT(x_ofs)) / 100; + if(LV_COORD_IS_PCT(y_ofs)) y_ofs = (lv_obj_get_height(base) * LV_COORD_GET_PCT(y_ofs)) / 100; if(lv_obj_get_style_base_dir(parent, LV_PART_MAIN) == LV_BASE_DIR_RTL) { x += x_ofs + base->coords.x1 - parent->coords.x1 + lv_obj_get_scroll_right(parent) - pleft; } @@ -491,17 +473,16 @@ void lv_obj_get_coords(const lv_obj_t * obj, lv_area_t * coords) lv_area_copy(coords, &obj->coords); } -lv_coord_t lv_obj_get_x(const lv_obj_t * obj) +int32_t lv_obj_get_x(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_coord_t rel_x; + int32_t rel_x; lv_obj_t * parent = lv_obj_get_parent(obj); if(parent) { rel_x = obj->coords.x1 - parent->coords.x1; rel_x += lv_obj_get_scroll_x(parent); - rel_x -= lv_obj_get_style_pad_left(parent, LV_PART_MAIN); - rel_x -= lv_obj_get_style_border_width(parent, LV_PART_MAIN); + rel_x -= lv_obj_get_style_space_left(parent, LV_PART_MAIN); } else { rel_x = obj->coords.x1; @@ -509,24 +490,23 @@ lv_coord_t lv_obj_get_x(const lv_obj_t * obj) return rel_x; } -lv_coord_t lv_obj_get_x2(const lv_obj_t * obj) +int32_t lv_obj_get_x2(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); return lv_obj_get_x(obj) + lv_obj_get_width(obj); } -lv_coord_t lv_obj_get_y(const lv_obj_t * obj) +int32_t lv_obj_get_y(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_coord_t rel_y; + int32_t rel_y; lv_obj_t * parent = lv_obj_get_parent(obj); if(parent) { rel_y = obj->coords.y1 - parent->coords.y1; rel_y += lv_obj_get_scroll_y(parent); - rel_y -= lv_obj_get_style_pad_top(parent, LV_PART_MAIN); - rel_y -= lv_obj_get_style_border_width(parent, LV_PART_MAIN); + rel_y -= lv_obj_get_style_space_top(parent, LV_PART_MAIN); } else { rel_y = obj->coords.y1; @@ -534,92 +514,87 @@ lv_coord_t lv_obj_get_y(const lv_obj_t * obj) return rel_y; } -lv_coord_t lv_obj_get_y2(const lv_obj_t * obj) +int32_t lv_obj_get_y2(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); return lv_obj_get_y(obj) + lv_obj_get_height(obj); } -lv_coord_t lv_obj_get_x_aligned(const lv_obj_t * obj) +int32_t lv_obj_get_x_aligned(const lv_obj_t * obj) { return lv_obj_get_style_x(obj, LV_PART_MAIN); } -lv_coord_t lv_obj_get_y_aligned(const lv_obj_t * obj) +int32_t lv_obj_get_y_aligned(const lv_obj_t * obj) { return lv_obj_get_style_y(obj, LV_PART_MAIN); } - -lv_coord_t lv_obj_get_width(const lv_obj_t * obj) +int32_t lv_obj_get_width(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); return lv_area_get_width(&obj->coords); } -lv_coord_t lv_obj_get_height(const lv_obj_t * obj) +int32_t lv_obj_get_height(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); return lv_area_get_height(&obj->coords); } -lv_coord_t lv_obj_get_content_width(const lv_obj_t * obj) +int32_t lv_obj_get_content_width(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t left = lv_obj_get_style_space_left(obj, LV_PART_MAIN); + int32_t right = lv_obj_get_style_space_right(obj, LV_PART_MAIN); - return lv_obj_get_width(obj) - left - right - 2 * border_width; + return lv_obj_get_width(obj) - left - right; } -lv_coord_t lv_obj_get_content_height(const lv_obj_t * obj) +int32_t lv_obj_get_content_height(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t top = lv_obj_get_style_space_top(obj, LV_PART_MAIN); + int32_t bottom = lv_obj_get_style_space_bottom(obj, LV_PART_MAIN); - return lv_obj_get_height(obj) - top - bottom - 2 * border_width; + return lv_obj_get_height(obj) - top - bottom; } void lv_obj_get_content_coords(const lv_obj_t * obj, lv_area_t * area) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); lv_obj_get_coords(obj, area); - lv_area_increase(area, -border_width, -border_width); - area->x1 += lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - area->x2 -= lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - area->y1 += lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - area->y2 -= lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + area->x1 += lv_obj_get_style_space_left(obj, LV_PART_MAIN); + area->x2 -= lv_obj_get_style_space_right(obj, LV_PART_MAIN); + area->y1 += lv_obj_get_style_space_top(obj, LV_PART_MAIN); + area->y2 -= lv_obj_get_style_space_bottom(obj, LV_PART_MAIN); } -lv_coord_t lv_obj_get_self_width(const lv_obj_t * obj) +int32_t lv_obj_get_self_width(const lv_obj_t * obj) { lv_point_t p = {0, LV_COORD_MIN}; - lv_event_send((lv_obj_t *)obj, LV_EVENT_GET_SELF_SIZE, &p); + lv_obj_send_event((lv_obj_t *)obj, LV_EVENT_GET_SELF_SIZE, &p); return p.x; } -lv_coord_t lv_obj_get_self_height(const lv_obj_t * obj) +int32_t lv_obj_get_self_height(const lv_obj_t * obj) { lv_point_t p = {LV_COORD_MIN, 0}; - lv_event_send((lv_obj_t *)obj, LV_EVENT_GET_SELF_SIZE, &p); + lv_obj_send_event((lv_obj_t *)obj, LV_EVENT_GET_SELF_SIZE, &p); return p.y; } bool lv_obj_refresh_self_size(lv_obj_t * obj) { - lv_coord_t w_set = lv_obj_get_style_width(obj, LV_PART_MAIN); - lv_coord_t h_set = lv_obj_get_style_height(obj, LV_PART_MAIN); + int32_t w_set = lv_obj_get_style_width(obj, LV_PART_MAIN); + int32_t h_set = lv_obj_get_style_height(obj, LV_PART_MAIN); if(w_set != LV_SIZE_CONTENT && h_set != LV_SIZE_CONTENT) return false; lv_obj_mark_layout_as_dirty(obj); @@ -630,10 +605,9 @@ void lv_obj_refr_pos(lv_obj_t * obj) { if(lv_obj_is_layout_positioned(obj)) return; - lv_obj_t * parent = lv_obj_get_parent(obj); - lv_coord_t x = lv_obj_get_style_x(obj, LV_PART_MAIN); - lv_coord_t y = lv_obj_get_style_y(obj, LV_PART_MAIN); + int32_t x = lv_obj_get_style_x(obj, LV_PART_MAIN); + int32_t y = lv_obj_get_style_y(obj, LV_PART_MAIN); if(parent == NULL) { lv_obj_move_to(obj, x, y); @@ -641,16 +615,16 @@ void lv_obj_refr_pos(lv_obj_t * obj) } /*Handle percentage value*/ - lv_coord_t pw = lv_obj_get_content_width(parent); - lv_coord_t ph = lv_obj_get_content_height(parent); + int32_t pw = lv_obj_get_content_width(parent); + int32_t ph = lv_obj_get_content_height(parent); if(LV_COORD_IS_PCT(x)) x = (pw * LV_COORD_GET_PCT(x)) / 100; if(LV_COORD_IS_PCT(y)) y = (ph * LV_COORD_GET_PCT(y)) / 100; /*Handle percentage value of translate*/ - lv_coord_t tr_x = lv_obj_get_style_translate_x(obj, LV_PART_MAIN); - lv_coord_t tr_y = lv_obj_get_style_translate_y(obj, LV_PART_MAIN); - lv_coord_t w = lv_obj_get_width(obj); - lv_coord_t h = lv_obj_get_height(obj); + int32_t tr_x = lv_obj_get_style_translate_x(obj, LV_PART_MAIN); + int32_t tr_y = lv_obj_get_style_translate_y(obj, LV_PART_MAIN); + int32_t w = lv_obj_get_width(obj); + int32_t h = lv_obj_get_height(obj); if(LV_COORD_IS_PCT(tr_x)) tr_x = (w * LV_COORD_GET_PCT(tr_x)) / 100; if(LV_COORD_IS_PCT(tr_y)) tr_y = (h * LV_COORD_GET_PCT(tr_y)) / 100; @@ -665,68 +639,61 @@ void lv_obj_refr_pos(lv_obj_t * obj) else align = LV_ALIGN_TOP_LEFT; } - if(align == LV_ALIGN_TOP_LEFT) { - lv_obj_move_to(obj, x, y); + switch(align) { + case LV_ALIGN_TOP_LEFT: + break; + case LV_ALIGN_TOP_MID: + x += pw / 2 - w / 2; + break; + case LV_ALIGN_TOP_RIGHT: + x += pw - w; + break; + case LV_ALIGN_LEFT_MID: + y += ph / 2 - h / 2; + break; + case LV_ALIGN_BOTTOM_LEFT: + y += ph - h; + break; + case LV_ALIGN_BOTTOM_MID: + x += pw / 2 - w / 2; + y += ph - h; + break; + case LV_ALIGN_BOTTOM_RIGHT: + x += pw - w; + y += ph - h; + break; + case LV_ALIGN_RIGHT_MID: + x += pw - w; + y += ph / 2 - h / 2; + break; + case LV_ALIGN_CENTER: + x += pw / 2 - w / 2; + y += ph / 2 - h / 2; + break; + default: + break; } - else { - switch(align) { - case LV_ALIGN_TOP_MID: - x += pw / 2 - w / 2; - break; - case LV_ALIGN_TOP_RIGHT: - x += pw - w; - break; - case LV_ALIGN_LEFT_MID: - y += ph / 2 - h / 2; - break; - case LV_ALIGN_BOTTOM_LEFT: - y += ph - h; - break; - case LV_ALIGN_BOTTOM_MID: - x += pw / 2 - w / 2; - y += ph - h; - break; - case LV_ALIGN_BOTTOM_RIGHT: - x += pw - w; - y += ph - h; - break; - case LV_ALIGN_RIGHT_MID: - x += pw - w; - y += ph / 2 - h / 2; - break; - case LV_ALIGN_CENTER: - x += pw / 2 - w / 2; - y += ph / 2 - h / 2; - break; - default: - break; - } - lv_obj_move_to(obj, x, y); - } + lv_obj_move_to(obj, x, y); } -void lv_obj_move_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) +void lv_obj_move_to(lv_obj_t * obj, int32_t x, int32_t y) { /*Convert x and y to absolute coordinates*/ lv_obj_t * parent = obj->parent; if(parent) { - lv_coord_t pad_left = lv_obj_get_style_pad_left(parent, LV_PART_MAIN); - lv_coord_t pad_top = lv_obj_get_style_pad_top(parent, LV_PART_MAIN); - if(lv_obj_has_flag(obj, LV_OBJ_FLAG_FLOATING)) { - x += pad_left + parent->coords.x1; - y += pad_top + parent->coords.y1; + x += parent->coords.x1; + y += parent->coords.y1; } else { - x += pad_left + parent->coords.x1 - lv_obj_get_scroll_x(parent); - y += pad_top + parent->coords.y1 - lv_obj_get_scroll_y(parent); + x += parent->coords.x1 - lv_obj_get_scroll_x(parent); + y += parent->coords.y1 - lv_obj_get_scroll_y(parent); } - lv_coord_t border_width = lv_obj_get_style_border_width(parent, LV_PART_MAIN); - x += border_width; - y += border_width; + x += lv_obj_get_style_space_left(parent, LV_PART_MAIN); + y += lv_obj_get_style_space_top(parent, LV_PART_MAIN); } /*Calculate and set the movement*/ @@ -766,23 +733,23 @@ void lv_obj_move_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) lv_obj_move_children_by(obj, diff.x, diff.y, false); /*Call the ancestor's event handler to the parent too*/ - if(parent) lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj); + if(parent) lv_obj_send_event(parent, LV_EVENT_CHILD_CHANGED, obj); /*Invalidate the new area*/ lv_obj_invalidate(obj); /*If the object was out of the parent invalidate the new scrollbar area too. - *If it wasn't out of the parent but out now, also invalidate the srollbars*/ + *If it wasn't out of the parent but out now, also invalidate the scrollbars*/ if(parent) { bool on2 = _lv_area_is_in(&obj->coords, &parent_fit_area, 0); if(on1 || (!on1 && on2)) lv_obj_scrollbar_invalidate(parent); } } -void lv_obj_move_children_by(lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_diff, bool ignore_floating) +void lv_obj_move_children_by(lv_obj_t * obj, int32_t x_diff, int32_t y_diff, bool ignore_floating) { uint32_t i; - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); for(i = 0; i < child_cnt; i++) { lv_obj_t * child = obj->spec_attr->children[i]; if(ignore_floating && lv_obj_has_flag(child, LV_OBJ_FLAG_FLOATING)) continue; @@ -830,22 +797,20 @@ void lv_obj_get_transformed_area(const lv_obj_t * obj, lv_area_t * area, bool re area->x2 = LV_MAX4(p[0].x, p[1].x, p[2].x, p[3].x); area->y1 = LV_MIN4(p[0].y, p[1].y, p[2].y, p[3].y); area->y2 = LV_MAX4(p[0].y, p[1].y, p[2].y, p[3].y); - lv_area_increase(area, 5, 5); } - void lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_disp_t * disp = lv_obj_get_disp(obj); - if(!lv_disp_is_invalidation_enabled(disp)) return; + lv_display_t * disp = lv_obj_get_display(obj); + if(!lv_display_is_invalidation_enabled(disp)) return; lv_area_t area_tmp; lv_area_copy(&area_tmp, area); if(!lv_obj_area_is_visible(obj, &area_tmp)) return; - _lv_inv_area(lv_obj_get_disp(obj), &area_tmp); + _lv_inv_area(lv_obj_get_display(obj), &area_tmp); } void lv_obj_invalidate(const lv_obj_t * obj) @@ -854,7 +819,7 @@ void lv_obj_invalidate(const lv_obj_t * obj) /*Truncate the area to the object*/ lv_area_t obj_coords; - lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj); + int32_t ext_size = _lv_obj_get_ext_draw_size(obj); lv_area_copy(&obj_coords, &obj->coords); obj_coords.x1 -= ext_size; obj_coords.y1 -= ext_size; @@ -862,7 +827,6 @@ void lv_obj_invalidate(const lv_obj_t * obj) obj_coords.y2 += ext_size; lv_obj_invalidate_area(obj, &obj_coords); - } bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area) @@ -871,45 +835,43 @@ bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area) /*Invalidate the object only if it belongs to the current or previous or one of the layers'*/ lv_obj_t * obj_scr = lv_obj_get_screen(obj); - lv_disp_t * disp = lv_obj_get_disp(obj_scr); - if(obj_scr != lv_disp_get_scr_act(disp) && - obj_scr != lv_disp_get_scr_prev(disp) && - obj_scr != lv_disp_get_layer_top(disp) && - obj_scr != lv_disp_get_layer_sys(disp)) { + lv_display_t * disp = lv_obj_get_display(obj_scr); + if(obj_scr != lv_display_get_screen_active(disp) && + obj_scr != lv_display_get_screen_prev(disp) && + obj_scr != lv_display_get_layer_bottom(disp) && + obj_scr != lv_display_get_layer_top(disp) && + obj_scr != lv_display_get_layer_sys(disp)) { return false; } /*Truncate the area to the object*/ - if(!lv_obj_has_flag_any(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) { - lv_area_t obj_coords; - lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj); - lv_area_copy(&obj_coords, &obj->coords); - obj_coords.x1 -= ext_size; - obj_coords.y1 -= ext_size; - obj_coords.x2 += ext_size; - obj_coords.y2 += ext_size; + lv_area_t obj_coords; + int32_t ext_size = _lv_obj_get_ext_draw_size(obj); + lv_area_copy(&obj_coords, &obj->coords); + lv_area_increase(&obj_coords, ext_size, ext_size); - /*The area is not on the object*/ - if(!_lv_area_intersect(area, area, &obj_coords)) return false; - } + /*The area is not on the object*/ + if(!_lv_area_intersect(area, area, &obj_coords)) return false; lv_obj_get_transformed_area(obj, area, true, false); - /*Truncate recursively to the parents*/ - lv_obj_t * par = lv_obj_get_parent(obj); - while(par != NULL) { + lv_obj_t * parent = lv_obj_get_parent(obj); + while(parent != NULL) { /*If the parent is hidden then the child is hidden and won't be drawn*/ - if(lv_obj_has_flag(par, LV_OBJ_FLAG_HIDDEN)) return false; + if(lv_obj_has_flag(parent, LV_OBJ_FLAG_HIDDEN)) return false; /*Truncate to the parent and if no common parts break*/ - if(!lv_obj_has_flag_any(par, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) { - lv_area_t par_area = par->coords; - lv_obj_get_transformed_area(par, &par_area, true, false); - if(!_lv_area_intersect(area, area, &par_area)) return false; + lv_area_t parent_coords = parent->coords; + if(lv_obj_has_flag(parent, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) { + int32_t parent_ext_size = _lv_obj_get_ext_draw_size(parent); + lv_area_increase(&parent_coords, parent_ext_size, parent_ext_size); } - par = lv_obj_get_parent(par); + lv_obj_get_transformed_area(parent, &parent_coords, true, false); + if(!_lv_area_intersect(area, area, &parent_coords)) return false; + + parent = lv_obj_get_parent(parent); } return true; @@ -920,7 +882,7 @@ bool lv_obj_is_visible(const lv_obj_t * obj) LV_ASSERT_OBJ(obj, MY_CLASS); lv_area_t obj_coords; - lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj); + int32_t ext_size = _lv_obj_get_ext_draw_size(obj); lv_area_copy(&obj_coords, &obj->coords); obj_coords.x1 -= ext_size; obj_coords.y1 -= ext_size; @@ -928,10 +890,9 @@ bool lv_obj_is_visible(const lv_obj_t * obj) obj_coords.y2 += ext_size; return lv_obj_area_is_visible(obj, &obj_coords); - } -void lv_obj_set_ext_click_area(lv_obj_t * obj, lv_coord_t size) +void lv_obj_set_ext_click_area(lv_obj_t * obj, int32_t size) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -943,17 +904,13 @@ void lv_obj_get_click_area(const lv_obj_t * obj, lv_area_t * area) { lv_area_copy(area, &obj->coords); if(obj->spec_attr) { - area->x1 -= obj->spec_attr->ext_click_pad; - area->x2 += obj->spec_attr->ext_click_pad; - area->y1 -= obj->spec_attr->ext_click_pad; - area->y2 += obj->spec_attr->ext_click_pad; + lv_area_increase(area, obj->spec_attr->ext_click_pad, obj->spec_attr->ext_click_pad); } } bool lv_obj_hit_test(lv_obj_t * obj, const lv_point_t * point) { if(!lv_obj_has_flag(obj, LV_OBJ_FLAG_CLICKABLE)) return false; - if(lv_obj_has_state(obj, LV_STATE_DISABLED)) return false; lv_area_t a; lv_obj_get_click_area(obj, &a); @@ -964,50 +921,49 @@ bool lv_obj_hit_test(lv_obj_t * obj, const lv_point_t * point) lv_hit_test_info_t hit_info; hit_info.point = point; hit_info.res = true; - lv_event_send(obj, LV_EVENT_HIT_TEST, &hit_info); + lv_obj_send_event(obj, LV_EVENT_HIT_TEST, &hit_info); return hit_info.res; } return res; } -lv_coord_t lv_clamp_width(lv_coord_t width, lv_coord_t min_width, lv_coord_t max_width, lv_coord_t ref_width) +int32_t lv_clamp_width(int32_t width, int32_t min_width, int32_t max_width, int32_t ref_width) { if(LV_COORD_IS_PCT(min_width)) min_width = (ref_width * LV_COORD_GET_PCT(min_width)) / 100; if(LV_COORD_IS_PCT(max_width)) max_width = (ref_width * LV_COORD_GET_PCT(max_width)) / 100; return LV_CLAMP(min_width, width, max_width); } -lv_coord_t lv_clamp_height(lv_coord_t height, lv_coord_t min_height, lv_coord_t max_height, lv_coord_t ref_height) +int32_t lv_clamp_height(int32_t height, int32_t min_height, int32_t max_height, int32_t ref_height) { if(LV_COORD_IS_PCT(min_height)) min_height = (ref_height * LV_COORD_GET_PCT(min_height)) / 100; if(LV_COORD_IS_PCT(max_height)) max_height = (ref_height * LV_COORD_GET_PCT(max_height)) / 100; return LV_CLAMP(min_height, height, max_height); } - - /********************** * STATIC FUNCTIONS **********************/ -static lv_coord_t calc_content_width(lv_obj_t * obj) +static int32_t calc_content_width(lv_obj_t * obj) { - lv_obj_scroll_to_x(obj, 0, LV_ANIM_OFF); + int32_t scroll_x_tmp = lv_obj_get_scroll_x(obj); + if(obj->spec_attr) obj->spec_attr->scroll.x = 0; - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN) + border_width; - lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; + int32_t space_right = lv_obj_get_style_space_right(obj, LV_PART_MAIN); + int32_t space_left = lv_obj_get_style_space_left(obj, LV_PART_MAIN); - lv_coord_t self_w; - self_w = lv_obj_get_self_width(obj) + pad_left + pad_right; + int32_t self_w; + self_w = lv_obj_get_self_width(obj) + space_left + space_right; - lv_coord_t child_res = LV_COORD_MIN; + int32_t child_res = LV_COORD_MIN; uint32_t i; - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); /*With RTL find the left most coordinate*/ if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) { for(i = 0; i < child_cnt; i++) { + int32_t child_res_tmp = LV_COORD_MIN; lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; @@ -1019,27 +975,31 @@ static lv_coord_t calc_content_width(lv_obj_t * obj) case LV_ALIGN_BOTTOM_RIGHT: case LV_ALIGN_RIGHT_MID: /*Normal right aligns. Other are ignored due to possible circular dependencies*/ - child_res = LV_MAX(child_res, obj->coords.x2 - child->coords.x1 + 1); + child_res_tmp = obj->coords.x2 - child->coords.x1 + 1; break; default: /* Consider other cases only if x=0 and use the width of the object. * With x!=0 circular dependency could occur. */ if(lv_obj_get_style_x(child, 0) == 0) { - child_res = LV_MAX(child_res, lv_area_get_width(&child->coords) + pad_right); + child_res_tmp = lv_area_get_width(&child->coords) + space_right; + child_res_tmp += lv_obj_get_style_margin_left(child, LV_PART_MAIN); } + break; } } else { - child_res = LV_MAX(child_res, obj->coords.x2 - child->coords.x1 + 1); + child_res_tmp = obj->coords.x2 - child->coords.x1 + 1; } + child_res = LV_MAX(child_res, child_res_tmp + lv_obj_get_style_margin_left(child, LV_PART_MAIN)); } if(child_res != LV_COORD_MIN) { - child_res += pad_left; + child_res += space_left; } } /*Else find the right most coordinate*/ else { for(i = 0; i < child_cnt; i++) { + int32_t child_res_tmp = LV_COORD_MIN; lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; @@ -1051,49 +1011,55 @@ static lv_coord_t calc_content_width(lv_obj_t * obj) case LV_ALIGN_BOTTOM_LEFT: case LV_ALIGN_LEFT_MID: /*Normal left aligns.*/ - child_res = LV_MAX(child_res, child->coords.x2 - obj->coords.x1 + 1); + child_res_tmp = child->coords.x2 - obj->coords.x1 + 1; break; default: /* Consider other cases only if x=0 and use the width of the object. * With x!=0 circular dependency could occur. */ if(lv_obj_get_style_y(child, 0) == 0) { - child_res = LV_MAX(child_res, lv_area_get_width(&child->coords) + pad_left); + child_res_tmp = lv_area_get_width(&child->coords) + space_left; + child_res_tmp += lv_obj_get_style_margin_right(child, LV_PART_MAIN); } + break; } } else { - child_res = LV_MAX(child_res, child->coords.x2 - obj->coords.x1 + 1); + child_res_tmp = child->coords.x2 - obj->coords.x1 + 1; } + + child_res = LV_MAX(child_res, child_res_tmp + lv_obj_get_style_margin_right(child, LV_PART_MAIN)); } if(child_res != LV_COORD_MIN) { - child_res += pad_right; + child_res += space_right; } } + if(obj->spec_attr) obj->spec_attr->scroll.x = -scroll_x_tmp; + if(child_res == LV_COORD_MIN) return self_w; - else return LV_MAX(child_res, self_w); + return LV_MAX(child_res, self_w); } -static lv_coord_t calc_content_height(lv_obj_t * obj) +static int32_t calc_content_height(lv_obj_t * obj) { - lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF); + int32_t scroll_y_tmp = lv_obj_get_scroll_y(obj); + if(obj->spec_attr) obj->spec_attr->scroll.y = 0; - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; - lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN) + border_width; + int32_t space_top = lv_obj_get_style_space_top(obj, LV_PART_MAIN); + int32_t space_bottom = lv_obj_get_style_space_bottom(obj, LV_PART_MAIN); - lv_coord_t self_h; - self_h = lv_obj_get_self_height(obj) + pad_top + pad_bottom; + int32_t self_h; + self_h = lv_obj_get_self_height(obj) + space_top + space_bottom; - lv_coord_t child_res = LV_COORD_MIN; + int32_t child_res = LV_COORD_MIN; uint32_t i; - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); for(i = 0; i < child_cnt; i++) { + int32_t child_res_tmp = LV_COORD_MIN; lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; - if(!lv_obj_is_layout_positioned(child)) { lv_align_t align = lv_obj_get_style_align(child, 0); switch(align) { @@ -1102,36 +1068,35 @@ static lv_coord_t calc_content_height(lv_obj_t * obj) case LV_ALIGN_TOP_MID: case LV_ALIGN_TOP_LEFT: /*Normal top aligns. */ - child_res = LV_MAX(child_res, child->coords.y2 - obj->coords.y1 + 1); + child_res_tmp = child->coords.y2 - obj->coords.y1 + 1; break; default: /* Consider other cases only if y=0 and use the height of the object. * With y!=0 circular dependency could occur. */ if(lv_obj_get_style_y(child, 0) == 0) { - child_res = LV_MAX(child_res, lv_area_get_height(&child->coords) + pad_top); + child_res_tmp = lv_area_get_height(&child->coords) + space_top; + child_res_tmp += lv_obj_get_style_margin_top(child, LV_PART_MAIN); } break; } } else { - child_res = LV_MAX(child_res, child->coords.y2 - obj->coords.y1 + 1); + child_res_tmp = child->coords.y2 - obj->coords.y1 + 1; } + + child_res = LV_MAX(child_res, child_res_tmp + lv_obj_get_style_margin_bottom(child, LV_PART_MAIN)); } - if(child_res != LV_COORD_MIN) { - child_res += pad_bottom; - return LV_MAX(child_res, self_h); - } - else { - return self_h; - } + if(obj->spec_attr) obj->spec_attr->scroll.y = -scroll_y_tmp; + if(child_res == LV_COORD_MIN) return self_h; + return LV_MAX(self_h, child_res + space_bottom); } static void layout_update_core(lv_obj_t * obj) { uint32_t i; - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); for(i = 0; i < child_cnt; i++) { lv_obj_t * child = obj->spec_attr->children[i]; layout_update_core(child); @@ -1143,11 +1108,7 @@ static void layout_update_core(lv_obj_t * obj) lv_obj_refr_pos(obj); if(child_cnt > 0) { - uint32_t layout_id = lv_obj_get_style_layout(obj, LV_PART_MAIN); - if(layout_id > 0 && layout_id <= layout_cnt) { - void * user_data = LV_GC_ROOT(_lv_layout_list)[layout_id - 1].user_data; - LV_GC_ROOT(_lv_layout_list)[layout_id - 1].cb(obj, user_data); - } + _lv_layout_apply(obj); } } @@ -1159,10 +1120,11 @@ static void layout_update_core(lv_obj_t * obj) static void transform_point(const lv_obj_t * obj, lv_point_t * p, bool inv) { - int16_t angle = lv_obj_get_style_transform_angle(obj, 0); - int16_t zoom = lv_obj_get_style_transform_zoom(obj, 0); + int32_t angle = lv_obj_get_style_transform_rotation(obj, 0); + int32_t scale_x = lv_obj_get_style_transform_scale_x_safe(obj, 0); + int32_t scale_y = lv_obj_get_style_transform_scale_y_safe(obj, 0); - if(angle == 0 && zoom == LV_IMG_ZOOM_NONE) return; + if(angle == 0 && scale_x == LV_SCALE_NONE && scale_y == LV_SCALE_NONE) return; lv_point_t pivot = { .x = lv_obj_get_style_transform_pivot_x(obj, 0), @@ -1181,8 +1143,9 @@ static void transform_point(const lv_obj_t * obj, lv_point_t * p, bool inv) if(inv) { angle = -angle; - zoom = (256 * 256) / zoom; + scale_x = (256 * 256) / scale_x; + scale_y = (256 * 256) / scale_y; } - lv_point_transform(p, angle, zoom, &pivot); + lv_point_transform(p, angle, scale_x, scale_y, &pivot, !inv); } diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.h index d20ee9656..823355e43 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.h @@ -22,13 +22,6 @@ extern "C" { /********************** * TYPEDEFS **********************/ -struct _lv_obj_t; - -typedef void (*lv_layout_update_cb_t)(struct _lv_obj_t *, void * user_data); -typedef struct { - lv_layout_update_cb_t cb; - void * user_data; -} lv_layout_dsc_t; /********************** * GLOBAL PROTOTYPES @@ -44,7 +37,7 @@ typedef struct { * @note The position is interpreted on the content area of the parent * @note The values can be set in pixel or in percentage of parent size with `lv_pct(v)` */ -void lv_obj_set_pos(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y); +void lv_obj_set_pos(lv_obj_t * obj, int32_t x, int32_t y); /** * Set the x coordinate of an object @@ -55,7 +48,7 @@ void lv_obj_set_pos(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y); * @note The position is interpreted on the content area of the parent * @note The values can be set in pixel or in percentage of parent size with `lv_pct(v)` */ -void lv_obj_set_x(struct _lv_obj_t * obj, lv_coord_t x); +void lv_obj_set_x(lv_obj_t * obj, int32_t x); /** * Set the y coordinate of an object @@ -66,7 +59,7 @@ void lv_obj_set_x(struct _lv_obj_t * obj, lv_coord_t x); * @note The position is interpreted on the content area of the parent * @note The values can be set in pixel or in percentage of parent size with `lv_pct(v)` */ -void lv_obj_set_y(struct _lv_obj_t * obj, lv_coord_t y); +void lv_obj_set_y(lv_obj_t * obj, int32_t y); /** * Set the size of an object. @@ -76,17 +69,17 @@ void lv_obj_set_y(struct _lv_obj_t * obj, lv_coord_t y); * @note possible values are: * pixel simple set the size accordingly * LV_SIZE_CONTENT set the size to involve all children in the given direction - * LV_SIZE_PCT(x) to set size in percentage of the parent's content area size (the size without paddings). + * lv_pct(x) to set size in percentage of the parent's content area size (the size without paddings). * x should be in [0..1000]% range */ -void lv_obj_set_size(struct _lv_obj_t * obj, lv_coord_t w, lv_coord_t h); +void lv_obj_set_size(lv_obj_t * obj, int32_t w, int32_t h); /** * Recalculate the size of the object * @param obj pointer to an object * @return true: the size has been changed */ -bool lv_obj_refr_size(struct _lv_obj_t * obj); +bool lv_obj_refr_size(lv_obj_t * obj); /** * Set the width of an object @@ -98,7 +91,7 @@ bool lv_obj_refr_size(struct _lv_obj_t * obj); * lv_pct(x) to set size in percentage of the parent's content area size (the size without paddings). * x should be in [0..1000]% range */ -void lv_obj_set_width(struct _lv_obj_t * obj, lv_coord_t w); +void lv_obj_set_width(lv_obj_t * obj, int32_t w); /** * Set the height of an object @@ -110,62 +103,54 @@ void lv_obj_set_width(struct _lv_obj_t * obj, lv_coord_t w); * lv_pct(x) to set size in percentage of the parent's content area size (the size without paddings). * x should be in [0..1000]% range */ -void lv_obj_set_height(struct _lv_obj_t * obj, lv_coord_t h); +void lv_obj_set_height(lv_obj_t * obj, int32_t h); /** * Set the width reduced by the left and right padding and the border width. * @param obj pointer to an object * @param w the width without paddings in pixels */ -void lv_obj_set_content_width(struct _lv_obj_t * obj, lv_coord_t w); +void lv_obj_set_content_width(lv_obj_t * obj, int32_t w); /** * Set the height reduced by the top and bottom padding and the border width. * @param obj pointer to an object * @param h the height without paddings in pixels */ -void lv_obj_set_content_height(struct _lv_obj_t * obj, lv_coord_t h); +void lv_obj_set_content_height(lv_obj_t * obj, int32_t h); /** * Set a layout for an object * @param obj pointer to an object * @param layout pointer to a layout descriptor to set */ -void lv_obj_set_layout(struct _lv_obj_t * obj, uint32_t layout); +void lv_obj_set_layout(lv_obj_t * obj, uint32_t layout); /** * Test whether the and object is positioned by a layout or not * @param obj pointer to an object to test * @return true: positioned by a layout; false: not positioned by a layout */ -bool lv_obj_is_layout_positioned(const struct _lv_obj_t * obj); +bool lv_obj_is_layout_positioned(const lv_obj_t * obj); /** * Mark the object for layout update. * @param obj pointer to an object whose children needs to be updated */ -void lv_obj_mark_layout_as_dirty(struct _lv_obj_t * obj); +void lv_obj_mark_layout_as_dirty(lv_obj_t * obj); /** * Update the layout of an object. * @param obj pointer to an object whose children needs to be updated */ -void lv_obj_update_layout(const struct _lv_obj_t * obj); - -/** - * Register a new layout - * @param cb the layout update callback - * @param user_data custom data that will be passed to `cb` - * @return the ID of the new layout - */ -uint32_t lv_layout_register(lv_layout_update_cb_t cb, void * user_data); +void lv_obj_update_layout(const lv_obj_t * obj); /** * Change the alignment of an object. * @param obj pointer to an object to align * @param align type of alignment (see 'lv_align_t' enum) `LV_ALIGN_OUT_...` can't be used. */ -void lv_obj_set_align(struct _lv_obj_t * obj, lv_align_t align); +void lv_obj_set_align(lv_obj_t * obj, lv_align_t align); /** * Change the alignment of an object and set new coordinates. @@ -177,7 +162,7 @@ void lv_obj_set_align(struct _lv_obj_t * obj, lv_align_t align); * @param x_ofs x coordinate offset after alignment * @param y_ofs y coordinate offset after alignment */ -void lv_obj_align(struct _lv_obj_t * obj, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs); +void lv_obj_align(lv_obj_t * obj, lv_align_t align, int32_t x_ofs, int32_t y_ofs); /** * Align an object to an other object. @@ -188,26 +173,25 @@ void lv_obj_align(struct _lv_obj_t * obj, lv_align_t align, lv_coord_t x_ofs, lv * @param y_ofs y coordinate offset after alignment * @note if the position or size of `base` changes `obj` needs to be aligned manually again */ -void lv_obj_align_to(struct _lv_obj_t * obj, const struct _lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, - lv_coord_t y_ofs); +void lv_obj_align_to(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, int32_t x_ofs, + int32_t y_ofs); /** * Align an object to the center on its parent. * @param obj pointer to an object to align * @note if the parent size changes `obj` needs to be aligned manually again */ -static inline void lv_obj_center(struct _lv_obj_t * obj) +static inline void lv_obj_center(lv_obj_t * obj) { lv_obj_align(obj, LV_ALIGN_CENTER, 0, 0); } - /** * Copy the coordinates of an object to an area * @param obj pointer to an object * @param coords pointer to an area to store the coordinates */ -void lv_obj_get_coords(const struct _lv_obj_t * obj, lv_area_t * coords); +void lv_obj_get_coords(const lv_obj_t * obj, lv_area_t * coords); /** * Get the x coordinate of object. @@ -219,7 +203,7 @@ void lv_obj_get_coords(const struct _lv_obj_t * obj, lv_area_t * coords); * @note Scrolling of the parent doesn't change the returned value. * @note The returned value is always the distance from the parent even if `obj` is positioned by a layout. */ -lv_coord_t lv_obj_get_x(const struct _lv_obj_t * obj); +int32_t lv_obj_get_x(const lv_obj_t * obj); /** * Get the x2 coordinate of object. @@ -231,7 +215,7 @@ lv_coord_t lv_obj_get_x(const struct _lv_obj_t * obj); * @note Scrolling of the parent doesn't change the returned value. * @note The returned value is always the distance from the parent even if `obj` is positioned by a layout. */ -lv_coord_t lv_obj_get_x2(const struct _lv_obj_t * obj); +int32_t lv_obj_get_x2(const lv_obj_t * obj); /** * Get the y coordinate of object. @@ -243,7 +227,7 @@ lv_coord_t lv_obj_get_x2(const struct _lv_obj_t * obj); * @note Scrolling of the parent doesn't change the returned value. * @note The returned value is always the distance from the parent even if `obj` is positioned by a layout. */ -lv_coord_t lv_obj_get_y(const struct _lv_obj_t * obj); +int32_t lv_obj_get_y(const lv_obj_t * obj); /** * Get the y2 coordinate of object. @@ -255,21 +239,21 @@ lv_coord_t lv_obj_get_y(const struct _lv_obj_t * obj); * @note Scrolling of the parent doesn't change the returned value. * @note The returned value is always the distance from the parent even if `obj` is positioned by a layout. */ -lv_coord_t lv_obj_get_y2(const struct _lv_obj_t * obj); +int32_t lv_obj_get_y2(const lv_obj_t * obj); /** * Get the actually set x coordinate of object, i.e. the offset form the set alignment * @param obj pointer to an object * @return the set x coordinate */ -lv_coord_t lv_obj_get_x_aligned(const struct _lv_obj_t * obj); +int32_t lv_obj_get_x_aligned(const lv_obj_t * obj); /** * Get the actually set y coordinate of object, i.e. the offset form the set alignment * @param obj pointer to an object * @return the set y coordinate */ -lv_coord_t lv_obj_get_y_aligned(const struct _lv_obj_t * obj); +int32_t lv_obj_get_y_aligned(const lv_obj_t * obj); /** * Get the width of an object @@ -278,7 +262,7 @@ lv_coord_t lv_obj_get_y_aligned(const struct _lv_obj_t * obj); * call `lv_obj_update_layout(obj)`. * @return the width in pixels */ -lv_coord_t lv_obj_get_width(const struct _lv_obj_t * obj); +int32_t lv_obj_get_width(const lv_obj_t * obj); /** * Get the height of an object @@ -287,7 +271,7 @@ lv_coord_t lv_obj_get_width(const struct _lv_obj_t * obj); * call `lv_obj_update_layout(obj)`. * @return the height in pixels */ -lv_coord_t lv_obj_get_height(const struct _lv_obj_t * obj); +int32_t lv_obj_get_height(const lv_obj_t * obj); /** * Get the width reduced by the left and right padding and the border width. @@ -296,7 +280,7 @@ lv_coord_t lv_obj_get_height(const struct _lv_obj_t * obj); * call `lv_obj_update_layout(obj)`. * @return the width which still fits into its parent without causing overflow (making the parent scrollable) */ -lv_coord_t lv_obj_get_content_width(const struct _lv_obj_t * obj); +int32_t lv_obj_get_content_width(const lv_obj_t * obj); /** * Get the height reduced by the top and bottom padding and the border width. @@ -305,7 +289,7 @@ lv_coord_t lv_obj_get_content_width(const struct _lv_obj_t * obj); * call `lv_obj_update_layout(obj)`. * @return the height which still fits into the parent without causing overflow (making the parent scrollable) */ -lv_coord_t lv_obj_get_content_height(const struct _lv_obj_t * obj); +int32_t lv_obj_get_content_height(const lv_obj_t * obj); /** * Get the area reduced by the paddings and the border width. @@ -314,7 +298,7 @@ lv_coord_t lv_obj_get_content_height(const struct _lv_obj_t * obj); * call `lv_obj_update_layout(obj)`. * @param area the area which still fits into the parent without causing overflow (making the parent scrollable) */ -void lv_obj_get_content_coords(const struct _lv_obj_t * obj, lv_area_t * area); +void lv_obj_get_content_coords(const lv_obj_t * obj, lv_area_t * area); /** * Get the width occupied by the "parts" of the widget. E.g. the width of all columns of a table. @@ -323,7 +307,7 @@ void lv_obj_get_content_coords(const struct _lv_obj_t * obj, lv_area_t * area); * @note This size independent from the real size of the widget. * It just tells how large the internal ("virtual") content is. */ -lv_coord_t lv_obj_get_self_width(const struct _lv_obj_t * obj); +int32_t lv_obj_get_self_width(const lv_obj_t * obj); /** * Get the height occupied by the "parts" of the widget. E.g. the height of all rows of a table. @@ -332,21 +316,20 @@ lv_coord_t lv_obj_get_self_width(const struct _lv_obj_t * obj); * @note This size independent from the real size of the widget. * It just tells how large the internal ("virtual") content is. */ -lv_coord_t lv_obj_get_self_height(const struct _lv_obj_t * obj); +int32_t lv_obj_get_self_height(const lv_obj_t * obj); /** * Handle if the size of the internal ("virtual") content of an object has changed. * @param obj pointer to an object * @return false: nothing happened; true: refresh happened */ -bool lv_obj_refresh_self_size(struct _lv_obj_t * obj); +bool lv_obj_refresh_self_size(lv_obj_t * obj); -void lv_obj_refr_pos(struct _lv_obj_t * obj); +void lv_obj_refr_pos(lv_obj_t * obj); -void lv_obj_move_to(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y); +void lv_obj_move_to(lv_obj_t * obj, int32_t x, int32_t y); - -void lv_obj_move_children_by(struct _lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_diff, bool ignore_floating); +void lv_obj_move_children_by(lv_obj_t * obj, int32_t x_diff, int32_t y_diff, bool ignore_floating); /** * Transform a point using the angle and zoom style properties of an object @@ -355,7 +338,7 @@ void lv_obj_move_children_by(struct _lv_obj_t * obj, lv_coord_t x_diff, lv_coord * @param recursive consider the transformation properties of the parents too * @param inv do the inverse of the transformation (-angle and 1/zoom) */ -void lv_obj_transform_point(const struct _lv_obj_t * obj, lv_point_t * p, bool recursive, bool inv); +void lv_obj_transform_point(const lv_obj_t * obj, lv_point_t * p, bool recursive, bool inv); /** * Transform an area using the angle and zoom style properties of an object @@ -364,7 +347,7 @@ void lv_obj_transform_point(const struct _lv_obj_t * obj, lv_point_t * p, bool r * @param recursive consider the transformation properties of the parents too * @param inv do the inverse of the transformation (-angle and 1/zoom) */ -void lv_obj_get_transformed_area(const struct _lv_obj_t * obj, lv_area_t * area, bool recursive, bool inv); +void lv_obj_get_transformed_area(const lv_obj_t * obj, lv_area_t * area, bool recursive, bool inv); /** * Mark an area of an object as invalid. @@ -372,13 +355,13 @@ void lv_obj_get_transformed_area(const struct _lv_obj_t * obj, lv_area_t * area, * @param obj pointer to an object * @param area the area to redraw */ -void lv_obj_invalidate_area(const struct _lv_obj_t * obj, const lv_area_t * area); +void lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area); /** * Mark the object as invalid to redrawn its area * @param obj pointer to an object */ -void lv_obj_invalidate(const struct _lv_obj_t * obj); +void lv_obj_invalidate(const lv_obj_t * obj); /** * Tell whether an area of an object is visible (even partially) now or not @@ -386,21 +369,21 @@ void lv_obj_invalidate(const struct _lv_obj_t * obj); * @param area the are to check. The visible part of the area will be written back here. * @return true visible; false not visible (hidden, out of parent, on other screen, etc) */ -bool lv_obj_area_is_visible(const struct _lv_obj_t * obj, lv_area_t * area); +bool lv_obj_area_is_visible(const lv_obj_t * obj, lv_area_t * area); /** * Tell whether an object is visible (even partially) now or not * @param obj pointer to an object * @return true: visible; false not visible (hidden, out of parent, on other screen, etc) */ -bool lv_obj_is_visible(const struct _lv_obj_t * obj); +bool lv_obj_is_visible(const lv_obj_t * obj); /** * Set the size of an extended clickable area * @param obj pointer to an object * @param size extended clickable area in all 4 directions [px] */ -void lv_obj_set_ext_click_area(struct _lv_obj_t * obj, lv_coord_t size); +void lv_obj_set_ext_click_area(lv_obj_t * obj, int32_t size); /** * Get the an area where to object can be clicked. @@ -408,7 +391,7 @@ void lv_obj_set_ext_click_area(struct _lv_obj_t * obj, lv_coord_t size); * @param obj pointer to an object * @param area store the result area here */ -void lv_obj_get_click_area(const struct _lv_obj_t * obj, lv_area_t * area); +void lv_obj_get_click_area(const lv_obj_t * obj, lv_area_t * area); /** * Hit-test an object given a particular point in screen space. @@ -416,7 +399,7 @@ void lv_obj_get_click_area(const struct _lv_obj_t * obj, lv_area_t * area); * @param point screen-space point (absolute coordinate) * @return true: if the object is considered under the point */ -bool lv_obj_hit_test(struct _lv_obj_t * obj, const lv_point_t * point); +bool lv_obj_hit_test(lv_obj_t * obj, const lv_point_t * point); /** * Clamp a width between min and max width. If the min/max width is in percentage value use the ref_width @@ -426,7 +409,7 @@ bool lv_obj_hit_test(struct _lv_obj_t * obj, const lv_point_t * point); * @param ref_width the reference width used when min/max width is in percentage * @return the clamped width */ -lv_coord_t lv_clamp_width(lv_coord_t width, lv_coord_t min_width, lv_coord_t max_width, lv_coord_t ref_width); +int32_t lv_clamp_width(int32_t width, int32_t min_width, int32_t max_width, int32_t ref_width); /** * Clamp a height between min and max height. If the min/max height is in percentage value use the ref_height @@ -436,7 +419,7 @@ lv_coord_t lv_clamp_width(lv_coord_t width, lv_coord_t min_width, lv_coord_t max * @param ref_height the reference height used when min/max height is in percentage * @return the clamped height */ -lv_coord_t lv_clamp_height(lv_coord_t height, lv_coord_t min_height, lv_coord_t max_height, lv_coord_t ref_height); +int32_t lv_clamp_height(int32_t height, int32_t min_height, int32_t max_height, int32_t ref_height); /********************** * MACROS diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_property.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_property.c new file mode 100644 index 000000000..20a2d25c1 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_property.c @@ -0,0 +1,179 @@ +/** + * @file lv_obj_id.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../core/lv_obj.h" +#include "../stdlib/lv_string.h" +#include "lv_obj_property.h" + +#if LV_USE_OBJ_PROPERTY + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef void (*lv_property_set_int_t)(lv_obj_t *, int32_t); +typedef void (*lv_property_set_pointer_t)(lv_obj_t *, const void *); +typedef void (*lv_property_set_color_t)(lv_obj_t *, lv_color_t); +typedef lv_result_t (*lv_property_setter_t)(lv_obj_t *, lv_prop_id_t, const lv_property_t *); + +typedef int32_t (*lv_property_get_int_t)(const lv_obj_t *); +typedef void * (*lv_property_get_pointer_t)(const lv_obj_t *); +typedef lv_color_t (*lv_property_get_color_t)(const lv_obj_t *); +typedef lv_result_t (*lv_property_getter_t)(const lv_obj_t *, lv_prop_id_t, lv_property_t *); + +/********************** + * STATIC PROTOTYPES + **********************/ + +static lv_result_t obj_property(lv_obj_t * obj, lv_prop_id_t id, lv_property_t * value, bool set); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_result_t lv_obj_set_property(lv_obj_t * obj, const lv_property_t * value) +{ + LV_ASSERT(obj && value); + + if(value->id == LV_PROPERTY_ID_INVALID) { + LV_LOG_WARN("invalid property id set to %p\n", obj); + return LV_RESULT_INVALID; + } + + if(value->id < LV_PROPERTY_ID_START) { + lv_obj_set_local_style_prop(obj, value->id, value->_style, 0); + return LV_RESULT_OK; + } + + return obj_property(obj, value->id, (lv_property_t *)value, true); +} + +lv_result_t lv_obj_set_properties(lv_obj_t * obj, const lv_property_t * value, uint32_t count) +{ + for(uint32_t i = 0; i < count; i++) { + lv_result_t result = lv_obj_set_property(obj, &value[i]); + if(result != LV_RESULT_OK) { + return result; + } + } + + return LV_RESULT_OK; +} + +lv_property_t lv_obj_get_property(lv_obj_t * obj, lv_prop_id_t id) +{ + lv_result_t result; + lv_property_t value; + + if(id == LV_PROPERTY_ID_INVALID) { + LV_LOG_WARN("invalid property id to get from %p\n", obj); + value.id = 0; + value.num = 0; + return value; + } + + if(id < LV_PROPERTY_ID_START) { + lv_obj_get_local_style_prop(obj, id, &value._style, 0); + value.id = id; + return value; + } + + result = obj_property(obj, id, &value, false); + if(result != LV_RESULT_OK) + value.id = 0; + + return value; +} + +static lv_result_t obj_property(lv_obj_t * obj, lv_prop_id_t id, lv_property_t * value, bool set) +{ + const lv_property_ops_t * properties; + const lv_property_ops_t * prop; + + const lv_obj_class_t * clz; + uint32_t index = LV_PROPERTY_ID_INDEX(id); + + for(clz = obj->class_p ; clz; clz = clz->base_class) { + properties = clz->properties; + if(properties == NULL) { + /* try base class*/ + continue; + } + + if(id != LV_PROPERTY_ID_ANY && (index < clz->prop_index_start || index > clz->prop_index_end)) { + /* try base class*/ + continue; + } + + /*Check if there's setter available for this class*/ + for(uint32_t i = 0; i < clz->properties_count; i++) { + prop = &properties[i]; + + /*pass id and value directly to widget's property method*/ + if(prop->id == LV_PROPERTY_ID_ANY) { + value->id = prop->id; + if(set) return ((lv_property_setter_t)prop->setter)(obj, id, value); + else return ((lv_property_getter_t)prop->getter)(obj, id, value); + } + + /*Not this id, check next*/ + if(prop->id != id) + continue; + + /*id matched but we got null pointer to functions*/ + if(set ? prop->setter == NULL : prop->getter == NULL) { + LV_LOG_WARN("null %s provided, id: %d\n", set ? "setter" : "getter", id); + return LV_RESULT_INVALID; + } + + /*Update value id if it's a read*/ + if(!set) value->id = prop->id; + + switch(LV_PROPERTY_ID_TYPE(prop->id)) { + case LV_PROPERTY_TYPE_INT: + if(set)((lv_property_set_int_t)(prop->setter))(obj, value->num); + else value->num = ((lv_property_get_int_t)(prop->getter))(obj); + break; + case LV_PROPERTY_TYPE_POINTER: + case LV_PROPERTY_TYPE_IMGSRC: + if(set)((lv_property_set_pointer_t)(prop->setter))(obj, value->ptr); + else value->ptr = ((lv_property_get_pointer_t)(prop->getter))(obj); + break; + case LV_PROPERTY_TYPE_COLOR: + if(set)((lv_property_set_color_t)prop->setter)(obj, value->color); + else value->color = ((lv_property_get_color_t)(prop->getter))(obj); + break; + default: + LV_LOG_WARN("unknown property id: 0x%08x\n", prop->id); + return LV_RESULT_INVALID; + break; + } + + return LV_RESULT_OK; + } + + /*If no setter found, try base class then*/ + } + + LV_LOG_WARN("unknown property id: 0x%08x\n", id); + return LV_RESULT_INVALID; +} + +#endif /*LV_USE_OBJ_PROPERTY*/ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_property.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_property.h new file mode 100644 index 000000000..ca3754ab3 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_property.h @@ -0,0 +1,128 @@ +/** + * @file lv_obj_property.h + * + */ + +#ifndef LV_OBJ_PROPERTY_H +#define LV_OBJ_PROPERTY_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../misc/lv_types.h" +#include "../misc/lv_style.h" + +#if LV_USE_OBJ_PROPERTY + +/********************* + * DEFINES + *********************/ + +/*All possible property value types*/ +#define LV_PROPERTY_TYPE_INVALID 0 /*Use default 0 as invalid to detect program outliers*/ +#define LV_PROPERTY_TYPE_INT 1 /*int32_t type*/ +#define LV_PROPERTY_TYPE_PRECISE 2 /*lv_value_precise_t, int32_t or float depending on LV_USE_FLOAT*/ +#define LV_PROPERTY_TYPE_COLOR 3 /*ARGB8888 type*/ +#define LV_PROPERTY_TYPE_POINTER 4 /*void * pointer*/ +#define LV_PROPERTY_TYPE_IMGSRC 5 /*Special pointer for image*/ + +/********************** + * TYPEDEFS + **********************/ + +#define LV_PROPERTY_ID(clz, name, type, index) LV_PROPERTY_## clz ##_##name = (LV_PROPERTY_## clz ##_START + (index)) | ((type) << 28) + +#define LV_PROPERTY_ID_TYPE(id) ((id) >> 28) +#define LV_PROPERTY_ID_INDEX(id) ((id) & 0xfffffff) + +/*Set properties from an array of lv_property_t*/ +#define LV_OBJ_SET_PROPERTY_ARRAY(obj, array) lv_obj_set_properties(obj, array, sizeof(array)/sizeof(array[0])) + +/** + * Group of predefined widget ID start value. + */ +enum { + LV_PROPERTY_ID_INVALID = 0, + + /*ID 0 to 0xff are style ID, check lv_style_prop_t*/ + LV_PROPERTY_ID_START = 0x100, /*ID little than 0xff is style ID*/ + + /* lv_obj.c */ + LV_PROPERTY_OBJ_START = 1000, + + /* lv_image.c */ + LV_PROPERTY_IMAGE_START = 1100, + + /*Special ID*/ + LV_PROPERTY_ID_BUILTIN_LAST, /*Use it to extend ID and make sure it's unique and compile time determinant*/ + + LV_PROPERTY_ID_ANY = 0x7ffffffe, /*Special ID used by lvgl to intercept all setter/getter call.*/ +}; + +typedef uint32_t lv_prop_id_t; + +typedef struct { + lv_prop_id_t id; + union { + int32_t num; /**< Number integer number (opacity, enums, booleans or "normal" numbers)*/ + const void * ptr; /**< Constant pointers (font, cone text, etc)*/ + lv_color_t color; /**< Colors*/ + lv_value_precise_t precise; /**< float or int for precise value*/ + lv_style_value_t _style; /**< A place holder for style value which is same as property value.*/ + }; +} lv_property_t; + +typedef struct { + lv_prop_id_t id; + + void * setter; + void * getter; +} lv_property_ops_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/*===================== + * Setter functions + *====================*/ + +/** + * Set widget property value. + * @param obj pointer to an object + * @param id ID of which property + * @param value The property value to set + * @return return LV_RESULT_OK if success + */ +lv_result_t lv_obj_set_property(lv_obj_t * obj, const lv_property_t * value); + +lv_result_t lv_obj_set_properties(lv_obj_t * obj, const lv_property_t * value, uint32_t count); + +/*===================== + * Getter functions + *====================*/ + +/** + * Read property value from object + * @param obj pointer to an object + * @param id ID of which property + * @param value pointer to a buffer to store the value + * @return ? to be discussed, LV_RESULT_OK or LV_RESULT_INVALID + */ +lv_property_t lv_obj_get_property(lv_obj_t * obj, lv_prop_id_t id); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_OBJ_PROPERTY*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_OBJ_PROPERTY_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.c index 02b982614..f21ebc513 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.c @@ -8,9 +8,9 @@ *********************/ #include "lv_obj_scroll.h" #include "lv_obj.h" -#include "lv_indev.h" -#include "lv_disp.h" -#include "lv_indev_scroll.h" +#include "../indev/lv_indev.h" +#include "../indev/lv_indev_scroll.h" +#include "../display/lv_display.h" /********************* * DEFINES @@ -33,7 +33,7 @@ **********************/ static void scroll_x_anim(void * obj, int32_t v); static void scroll_y_anim(void * obj, int32_t v); -static void scroll_anim_ready_cb(lv_anim_t * a); +static void scroll_completed_completed_cb(lv_anim_t * a); static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_point_t * scroll_value, lv_anim_enable_t anim_en); @@ -113,52 +113,53 @@ lv_scroll_snap_t lv_obj_get_scroll_snap_y(const lv_obj_t * obj) else return LV_SCROLL_SNAP_NONE; } -lv_coord_t lv_obj_get_scroll_x(const lv_obj_t * obj) +int32_t lv_obj_get_scroll_x(const lv_obj_t * obj) { if(obj->spec_attr == NULL) return 0; return -obj->spec_attr->scroll.x; } -lv_coord_t lv_obj_get_scroll_y(const lv_obj_t * obj) +int32_t lv_obj_get_scroll_y(const lv_obj_t * obj) { if(obj->spec_attr == NULL) return 0; return -obj->spec_attr->scroll.y; } -lv_coord_t lv_obj_get_scroll_top(lv_obj_t * obj) +int32_t lv_obj_get_scroll_top(lv_obj_t * obj) { if(obj->spec_attr == NULL) return 0; return -obj->spec_attr->scroll.y; } -lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj) +int32_t lv_obj_get_scroll_bottom(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_coord_t child_res = LV_COORD_MIN; + int32_t child_res = LV_COORD_MIN; uint32_t i; - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); for(i = 0; i < child_cnt; i++) { lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; - child_res = LV_MAX(child_res, child->coords.y2); + + int32_t tmp_y = child->coords.y2 + lv_obj_get_style_margin_bottom(child, LV_PART_MAIN); + child_res = LV_MAX(child_res, tmp_y); } - lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t space_top = lv_obj_get_style_space_top(obj, LV_PART_MAIN); + int32_t space_bottom = lv_obj_get_style_space_bottom(obj, LV_PART_MAIN); if(child_res != LV_COORD_MIN) { - child_res -= (obj->coords.y2 - pad_bottom - border_width); + child_res -= (obj->coords.y2 - space_bottom); } - lv_coord_t self_h = lv_obj_get_self_height(obj); - self_h = self_h - (lv_obj_get_height(obj) - pad_top - pad_bottom - 2 * border_width); + int32_t self_h = lv_obj_get_self_height(obj); + self_h = self_h - (lv_obj_get_height(obj) - space_top - space_bottom); self_h -= lv_obj_get_scroll_y(obj); return LV_MAX(child_res, self_h); } -lv_coord_t lv_obj_get_scroll_left(lv_obj_t * obj) +int32_t lv_obj_get_scroll_left(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -170,38 +171,38 @@ lv_coord_t lv_obj_get_scroll_left(lv_obj_t * obj) } /*With RTL base direction scrolling the left is normal so find the left most coordinate*/ - lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t space_right = lv_obj_get_style_space_right(obj, LV_PART_MAIN); + int32_t space_left = lv_obj_get_style_space_left(obj, LV_PART_MAIN); - lv_coord_t child_res = 0; + int32_t child_res = 0; uint32_t i; - lv_coord_t x1 = LV_COORD_MAX; - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + int32_t x1 = LV_COORD_MAX; + uint32_t child_cnt = lv_obj_get_child_count(obj); for(i = 0; i < child_cnt; i++) { lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; - x1 = LV_MIN(x1, child->coords.x1); + int32_t tmp_x = child->coords.x1 - lv_obj_get_style_margin_left(child, LV_PART_MAIN); + x1 = LV_MIN(x1, tmp_x); } if(x1 != LV_COORD_MAX) { child_res = x1; - child_res = (obj->coords.x1 + pad_left + border_width) - child_res; + child_res = (obj->coords.x1 + space_left) - child_res; } else { child_res = LV_COORD_MIN; } - lv_coord_t self_w = lv_obj_get_self_width(obj); - self_w = self_w - (lv_obj_get_width(obj) - pad_right - pad_left - 2 * border_width); + int32_t self_w = lv_obj_get_self_width(obj); + self_w = self_w - (lv_obj_get_width(obj) - space_right - space_left); self_w += lv_obj_get_scroll_x(obj); return LV_MAX(child_res, self_w); } -lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj) +int32_t lv_obj_get_scroll_right(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -213,31 +214,32 @@ lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj) } /*With other base direction (LTR) scrolling to the right is normal so find the right most coordinate*/ - lv_coord_t child_res = LV_COORD_MIN; + int32_t child_res = LV_COORD_MIN; uint32_t i; - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); for(i = 0; i < child_cnt; i++) { lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; - child_res = LV_MAX(child_res, child->coords.x2); + + int32_t tmp_x = child->coords.x2 + lv_obj_get_style_margin_right(child, LV_PART_MAIN); + child_res = LV_MAX(child_res, tmp_x); } - lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t space_right = lv_obj_get_style_space_right(obj, LV_PART_MAIN); + int32_t space_left = lv_obj_get_style_space_left(obj, LV_PART_MAIN); if(child_res != LV_COORD_MIN) { - child_res -= (obj->coords.x2 - pad_right - border_width); + child_res -= (obj->coords.x2 - space_right); } - lv_coord_t self_w; + int32_t self_w; self_w = lv_obj_get_self_width(obj); - self_w = self_w - (lv_obj_get_width(obj) - pad_right - pad_left - 2 * border_width); + self_w = self_w - (lv_obj_get_width(obj) - space_right - space_left); self_w -= lv_obj_get_scroll_x(obj); return LV_MAX(child_res, self_w); } -void lv_obj_get_scroll_end(struct _lv_obj_t * obj, lv_point_t * end) +void lv_obj_get_scroll_end(lv_obj_t * obj, lv_point_t * end) { lv_anim_t * a; a = lv_anim_get(obj, scroll_x_anim); @@ -251,21 +253,21 @@ void lv_obj_get_scroll_end(struct _lv_obj_t * obj, lv_point_t * end) * Other functions *====================*/ -void lv_obj_scroll_by_bounded(lv_obj_t * obj, lv_coord_t dx, lv_coord_t dy, lv_anim_enable_t anim_en) +void lv_obj_scroll_by_bounded(lv_obj_t * obj, int32_t dx, int32_t dy, lv_anim_enable_t anim_en) { if(dx == 0 && dy == 0) return; /*We need to know the final sizes for bound check*/ lv_obj_update_layout(obj); - /*Don't let scroll more then naturally possible by the size of the content*/ - lv_coord_t x_current = -lv_obj_get_scroll_x(obj); - lv_coord_t x_bounded = x_current + dx; + /*Don't let scroll more than naturally possible by the size of the content*/ + int32_t x_current = -lv_obj_get_scroll_x(obj); + int32_t x_bounded = x_current + dx; if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) { if(x_bounded > 0) x_bounded = 0; if(x_bounded < 0) { - lv_coord_t scroll_max = lv_obj_get_scroll_left(obj) + lv_obj_get_scroll_right(obj); + int32_t scroll_max = lv_obj_get_scroll_left(obj) + lv_obj_get_scroll_right(obj); if(scroll_max < 0) scroll_max = 0; if(x_bounded < -scroll_max) x_bounded = -scroll_max; @@ -274,20 +276,20 @@ void lv_obj_scroll_by_bounded(lv_obj_t * obj, lv_coord_t dx, lv_coord_t dy, lv_a else { if(x_bounded < 0) x_bounded = 0; if(x_bounded > 0) { - lv_coord_t scroll_max = lv_obj_get_scroll_left(obj) + lv_obj_get_scroll_right(obj); + int32_t scroll_max = lv_obj_get_scroll_left(obj) + lv_obj_get_scroll_right(obj); if(scroll_max < 0) scroll_max = 0; if(x_bounded > scroll_max) x_bounded = scroll_max; } } - /*Don't let scroll more then naturally possible by the size of the content*/ - lv_coord_t y_current = -lv_obj_get_scroll_y(obj); - lv_coord_t y_bounded = y_current + dy; + /*Don't let scroll more than naturally possible by the size of the content*/ + int32_t y_current = -lv_obj_get_scroll_y(obj); + int32_t y_bounded = y_current + dy; if(y_bounded > 0) y_bounded = 0; if(y_bounded < 0) { - lv_coord_t scroll_max = lv_obj_get_scroll_top(obj) + lv_obj_get_scroll_bottom(obj); + int32_t scroll_max = lv_obj_get_scroll_top(obj) + lv_obj_get_scroll_bottom(obj); if(scroll_max < 0) scroll_max = 0; if(y_bounded < -scroll_max) y_bounded = -scroll_max; } @@ -299,88 +301,85 @@ void lv_obj_scroll_by_bounded(lv_obj_t * obj, lv_coord_t dx, lv_coord_t dy, lv_a } } - -void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t dx, lv_coord_t dy, lv_anim_enable_t anim_en) +void lv_obj_scroll_by(lv_obj_t * obj, int32_t dx, int32_t dy, lv_anim_enable_t anim_en) { if(dx == 0 && dy == 0) return; if(anim_en == LV_ANIM_ON) { - lv_disp_t * d = lv_obj_get_disp(obj); + lv_display_t * d = lv_obj_get_display(obj); lv_anim_t a; lv_anim_init(&a); lv_anim_set_var(&a, obj); - lv_anim_set_ready_cb(&a, scroll_anim_ready_cb); + lv_anim_set_completed_cb(&a, scroll_completed_completed_cb); if(dx) { - uint32_t t = lv_anim_speed_to_time((lv_disp_get_hor_res(d) * 2) >> 2, 0, dx); - if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN; - if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX; - lv_anim_set_time(&a, t); - lv_coord_t sx = lv_obj_get_scroll_x(obj); + uint32_t t = lv_anim_speed_clamped((lv_display_get_horizontal_resolution(d)) >> 1, SCROLL_ANIM_TIME_MIN, + SCROLL_ANIM_TIME_MAX); + lv_anim_set_duration(&a, t); + int32_t sx = lv_obj_get_scroll_x(obj); lv_anim_set_values(&a, -sx, -sx + dx); lv_anim_set_exec_cb(&a, scroll_x_anim); lv_anim_set_path_cb(&a, lv_anim_path_ease_out); - lv_res_t res; - res = lv_event_send(obj, LV_EVENT_SCROLL_BEGIN, &a); - if(res != LV_RES_OK) return; + lv_result_t res; + res = lv_obj_send_event(obj, LV_EVENT_SCROLL_BEGIN, &a); + if(res != LV_RESULT_OK) return; lv_anim_start(&a); } if(dy) { - uint32_t t = lv_anim_speed_to_time((lv_disp_get_ver_res(d) * 2) >> 2, 0, dy); - if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN; - if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX; - lv_anim_set_time(&a, t); - lv_coord_t sy = lv_obj_get_scroll_y(obj); + uint32_t t = lv_anim_speed_clamped((lv_display_get_vertical_resolution(d)) >> 1, SCROLL_ANIM_TIME_MIN, + SCROLL_ANIM_TIME_MAX); + lv_anim_set_duration(&a, t); + int32_t sy = lv_obj_get_scroll_y(obj); lv_anim_set_values(&a, -sy, -sy + dy); lv_anim_set_exec_cb(&a, scroll_y_anim); lv_anim_set_path_cb(&a, lv_anim_path_ease_out); - lv_res_t res; - res = lv_event_send(obj, LV_EVENT_SCROLL_BEGIN, &a); - if(res != LV_RES_OK) return; + lv_result_t res; + res = lv_obj_send_event(obj, LV_EVENT_SCROLL_BEGIN, &a); + if(res != LV_RESULT_OK) return; lv_anim_start(&a); } } else { /*Remove pending animations*/ - lv_anim_del(obj, scroll_y_anim); - lv_anim_del(obj, scroll_x_anim); + lv_anim_delete(obj, scroll_y_anim); + lv_anim_delete(obj, scroll_x_anim); - lv_res_t res; - res = lv_event_send(obj, LV_EVENT_SCROLL_BEGIN, NULL); - if(res != LV_RES_OK) return; + lv_result_t res; + res = lv_obj_send_event(obj, LV_EVENT_SCROLL_BEGIN, NULL); + if(res != LV_RESULT_OK) return; res = _lv_obj_scroll_by_raw(obj, dx, dy); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; - res = lv_event_send(obj, LV_EVENT_SCROLL_END, NULL); - if(res != LV_RES_OK) return; + res = lv_obj_send_event(obj, LV_EVENT_SCROLL_END, NULL); + if(res != LV_RESULT_OK) return; } } -void lv_obj_scroll_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en) +void lv_obj_scroll_to(lv_obj_t * obj, int32_t x, int32_t y, lv_anim_enable_t anim_en) { lv_obj_scroll_to_x(obj, x, anim_en); lv_obj_scroll_to_y(obj, y, anim_en); } -void lv_obj_scroll_to_x(lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t anim_en) +void lv_obj_scroll_to_x(lv_obj_t * obj, int32_t x, lv_anim_enable_t anim_en) { - lv_anim_del(obj, scroll_x_anim); + lv_anim_delete(obj, scroll_x_anim); - lv_coord_t scroll_x = lv_obj_get_scroll_x(obj); - lv_coord_t diff = -x + scroll_x; + int32_t scroll_x = lv_obj_get_scroll_x(obj); + int32_t diff = -x + scroll_x; lv_obj_scroll_by_bounded(obj, diff, 0, anim_en); } -void lv_obj_scroll_to_y(lv_obj_t * obj, lv_coord_t y, lv_anim_enable_t anim_en) +void lv_obj_scroll_to_y(lv_obj_t * obj, int32_t y, lv_anim_enable_t anim_en) { - lv_anim_del(obj, scroll_y_anim); + lv_anim_delete(obj, scroll_y_anim); - lv_coord_t scroll_y = lv_obj_get_scroll_y(obj); - lv_coord_t diff = -y + scroll_y; + int32_t scroll_y = lv_obj_get_scroll_y(obj); + int32_t diff = -y + scroll_y; lv_obj_scroll_by_bounded(obj, 0, diff, anim_en); } @@ -409,9 +408,9 @@ void lv_obj_scroll_to_view_recursive(lv_obj_t * obj, lv_anim_enable_t anim_en) } } -lv_res_t _lv_obj_scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) +lv_result_t _lv_obj_scroll_by_raw(lv_obj_t * obj, int32_t x, int32_t y) { - if(x == 0 && y == 0) return LV_RES_OK; + if(x == 0 && y == 0) return LV_RESULT_OK; lv_obj_allocate_spec_attr(obj); @@ -419,13 +418,12 @@ lv_res_t _lv_obj_scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) obj->spec_attr->scroll.y += y; lv_obj_move_children_by(obj, x, y, true); - lv_res_t res = lv_event_send(obj, LV_EVENT_SCROLL, NULL); - if(res != LV_RES_OK) return res; + lv_result_t res = lv_obj_send_event(obj, LV_EVENT_SCROLL, NULL); + if(res != LV_RESULT_OK) return res; lv_obj_invalidate(obj); - return LV_RES_OK; + return LV_RESULT_OK; } - bool lv_obj_is_scrolling(const lv_obj_t * obj) { lv_indev_t * indev = lv_indev_get_next(NULL); @@ -465,10 +463,10 @@ void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * if(indev == NULL) return; } - lv_coord_t st = lv_obj_get_scroll_top(obj); - lv_coord_t sb = lv_obj_get_scroll_bottom(obj); - lv_coord_t sl = lv_obj_get_scroll_left(obj); - lv_coord_t sr = lv_obj_get_scroll_right(obj); + int32_t st = lv_obj_get_scroll_top(obj); + int32_t sb = lv_obj_get_scroll_bottom(obj); + int32_t sl = lv_obj_get_scroll_left(obj); + int32_t sr = lv_obj_get_scroll_right(obj); lv_dir_t dir = lv_obj_get_scroll_dir(obj); @@ -480,7 +478,6 @@ void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * ver_draw = true; } - bool hor_draw = false; if((dir & LV_DIR_HOR) && ((sm == LV_SCROLLBAR_MODE_ON) || @@ -491,21 +488,21 @@ void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * if(!hor_draw && !ver_draw) return; - bool rtl = lv_obj_get_style_base_dir(obj, LV_PART_SCROLLBAR) == LV_BASE_DIR_RTL ? true : false; + bool rtl = lv_obj_get_style_base_dir(obj, LV_PART_SCROLLBAR) == LV_BASE_DIR_RTL; - lv_coord_t top_space = lv_obj_get_style_pad_top(obj, LV_PART_SCROLLBAR); - lv_coord_t bottom_space = lv_obj_get_style_pad_bottom(obj, LV_PART_SCROLLBAR); - lv_coord_t left_space = lv_obj_get_style_pad_left(obj, LV_PART_SCROLLBAR); - lv_coord_t right_space = lv_obj_get_style_pad_right(obj, LV_PART_SCROLLBAR); - lv_coord_t tickness = lv_obj_get_style_width(obj, LV_PART_SCROLLBAR); + int32_t top_space = lv_obj_get_style_pad_top(obj, LV_PART_SCROLLBAR); + int32_t bottom_space = lv_obj_get_style_pad_bottom(obj, LV_PART_SCROLLBAR); + int32_t left_space = lv_obj_get_style_pad_left(obj, LV_PART_SCROLLBAR); + int32_t right_space = lv_obj_get_style_pad_right(obj, LV_PART_SCROLLBAR); + int32_t thickness = lv_obj_get_style_width(obj, LV_PART_SCROLLBAR); - lv_coord_t obj_h = lv_obj_get_height(obj); - lv_coord_t obj_w = lv_obj_get_width(obj); + int32_t obj_h = lv_obj_get_height(obj); + int32_t obj_w = lv_obj_get_width(obj); /*Space required for the vertical and horizontal scrollbars*/ - lv_coord_t ver_reg_space = ver_draw ? tickness : 0; - lv_coord_t hor_req_space = hor_draw ? tickness : 0; - lv_coord_t rem; + int32_t ver_reg_space = ver_draw ? thickness : 0; + int32_t hor_req_space = hor_draw ? thickness : 0; + int32_t rem; if(lv_obj_get_style_bg_opa(obj, LV_PART_SCROLLBAR) < LV_OPA_MIN && lv_obj_get_style_border_opa(obj, LV_PART_SCROLLBAR) < LV_OPA_MIN) { @@ -513,30 +510,30 @@ void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * } /*Draw vertical scrollbar if the mode is ON or can be scrolled in this direction*/ - lv_coord_t content_h = obj_h + st + sb; + int32_t content_h = obj_h + st + sb; if(ver_draw && content_h) { ver_area->y1 = obj->coords.y1; ver_area->y2 = obj->coords.y2; if(rtl) { ver_area->x1 = obj->coords.x1 + left_space; - ver_area->x2 = ver_area->x1 + tickness - 1; + ver_area->x2 = ver_area->x1 + thickness - 1; } else { ver_area->x2 = obj->coords.x2 - right_space; - ver_area->x1 = ver_area->x2 - tickness + 1; + ver_area->x1 = ver_area->x2 - thickness + 1; } - lv_coord_t sb_h = ((obj_h - top_space - bottom_space - hor_req_space) * obj_h) / content_h; + int32_t sb_h = ((obj_h - top_space - bottom_space - hor_req_space) * obj_h) / content_h; sb_h = LV_MAX(sb_h, SCROLLBAR_MIN_SIZE); rem = (obj_h - top_space - bottom_space - hor_req_space) - sb_h; /*Remaining size from the scrollbar track that is not the scrollbar itself*/ - lv_coord_t scroll_h = content_h - obj_h; /*The size of the content which can be really scrolled*/ + int32_t scroll_h = content_h - obj_h; /*The size of the content which can be really scrolled*/ if(scroll_h <= 0) { ver_area->y1 = obj->coords.y1 + top_space; ver_area->y2 = obj->coords.y2 - bottom_space - hor_req_space - 1; } else { - lv_coord_t sb_y = (rem * sb) / scroll_h; + int32_t sb_y = (rem * sb) / scroll_h; sb_y = rem - sb_y; ver_area->y1 = obj->coords.y1 + sb_y + top_space; @@ -557,18 +554,18 @@ void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * } /*Draw horizontal scrollbar if the mode is ON or can be scrolled in this direction*/ - lv_coord_t content_w = obj_w + sl + sr; + int32_t content_w = obj_w + sl + sr; if(hor_draw && content_w) { hor_area->y2 = obj->coords.y2 - bottom_space; - hor_area->y1 = hor_area->y2 - tickness + 1; + hor_area->y1 = hor_area->y2 - thickness + 1; hor_area->x1 = obj->coords.x1; hor_area->x2 = obj->coords.x2; - lv_coord_t sb_w = ((obj_w - left_space - right_space - ver_reg_space) * obj_w) / content_w; + int32_t sb_w = ((obj_w - left_space - right_space - ver_reg_space) * obj_w) / content_w; sb_w = LV_MAX(sb_w, SCROLLBAR_MIN_SIZE); rem = (obj_w - left_space - right_space - ver_reg_space) - sb_w; /*Remaining size from the scrollbar track that is not the scrollbar itself*/ - lv_coord_t scroll_w = content_w - obj_w; /*The size of the content which can be really scrolled*/ + int32_t scroll_w = content_w - obj_w; /*The size of the content which can be really scrolled*/ if(scroll_w <= 0) { if(rtl) { hor_area->x1 = obj->coords.x1 + left_space + ver_reg_space - 1; @@ -580,7 +577,7 @@ void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * } } else { - lv_coord_t sb_x = (rem * sr) / scroll_w; + int32_t sb_x = (rem * sr) / scroll_w; sb_x = rem - sb_x; if(rtl) { @@ -636,8 +633,8 @@ void lv_obj_readjust_scroll(lv_obj_t * obj, lv_anim_enable_t anim_en) /*Be sure the bottom side is not remains scrolled in*/ /*With snapping the content can't be scrolled in*/ if(lv_obj_get_scroll_snap_y(obj) == LV_SCROLL_SNAP_NONE) { - lv_coord_t st = lv_obj_get_scroll_top(obj); - lv_coord_t sb = lv_obj_get_scroll_bottom(obj); + int32_t st = lv_obj_get_scroll_top(obj); + int32_t sb = lv_obj_get_scroll_bottom(obj); if(sb < 0 && st > 0) { sb = LV_MIN(st, -sb); lv_obj_scroll_by(obj, 0, sb, anim_en); @@ -645,8 +642,8 @@ void lv_obj_readjust_scroll(lv_obj_t * obj, lv_anim_enable_t anim_en) } if(lv_obj_get_scroll_snap_x(obj) == LV_SCROLL_SNAP_NONE) { - lv_coord_t sl = lv_obj_get_scroll_left(obj); - lv_coord_t sr = lv_obj_get_scroll_right(obj); + int32_t sl = lv_obj_get_scroll_left(obj); + int32_t sr = lv_obj_get_scroll_right(obj); if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) { /*Be sure the left side is not remains scrolled in*/ if(sr < 0 && sl > 0) { @@ -668,7 +665,6 @@ void lv_obj_readjust_scroll(lv_obj_t * obj, lv_anim_enable_t anim_en) * STATIC FUNCTIONS **********************/ - static void scroll_x_anim(void * obj, int32_t v) { _lv_obj_scroll_by_raw(obj, v + lv_obj_get_scroll_x(obj), 0); @@ -679,9 +675,9 @@ static void scroll_y_anim(void * obj, int32_t v) _lv_obj_scroll_by_raw(obj, 0, v + lv_obj_get_scroll_y(obj)); } -static void scroll_anim_ready_cb(lv_anim_t * a) +static void scroll_completed_completed_cb(lv_anim_t * a) { - lv_event_send(a->var, LV_EVENT_SCROLL_END, NULL); + lv_obj_send_event(a->var, LV_EVENT_SCROLL_END, NULL); } static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_point_t * scroll_value, @@ -691,102 +687,101 @@ static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_p if(!lv_obj_has_flag(parent, LV_OBJ_FLAG_SCROLLABLE)) return; lv_dir_t scroll_dir = lv_obj_get_scroll_dir(parent); - lv_coord_t snap_goal = 0; - lv_coord_t act = 0; + int32_t snap_goal = 0; + int32_t act = 0; const lv_area_t * area_tmp; - lv_coord_t y_scroll = 0; + int32_t y_scroll = 0; lv_scroll_snap_t snap_y = lv_obj_get_scroll_snap_y(parent); if(snap_y != LV_SCROLL_SNAP_NONE) area_tmp = &child->coords; else area_tmp = area; - lv_coord_t border_width = lv_obj_get_style_border_width(parent, LV_PART_MAIN); - lv_coord_t ptop = lv_obj_get_style_pad_top(parent, LV_PART_MAIN) + border_width; - lv_coord_t pbottom = lv_obj_get_style_pad_bottom(parent, LV_PART_MAIN) + border_width; - lv_coord_t top_diff = parent->coords.y1 + ptop - area_tmp->y1 - scroll_value->y; - lv_coord_t bottom_diff = -(parent->coords.y2 - pbottom - area_tmp->y2 - scroll_value->y); - lv_coord_t parent_h = lv_obj_get_height(parent) - ptop - pbottom; + int32_t stop = lv_obj_get_style_space_top(parent, LV_PART_MAIN); + int32_t sbottom = lv_obj_get_style_space_bottom(parent, LV_PART_MAIN); + int32_t top_diff = parent->coords.y1 + stop - area_tmp->y1 - scroll_value->y; + int32_t bottom_diff = -(parent->coords.y2 - sbottom - area_tmp->y2 - scroll_value->y); + int32_t parent_h = lv_obj_get_height(parent) - stop - sbottom; if((top_diff >= 0 && bottom_diff >= 0)) y_scroll = 0; else if(top_diff > 0) { y_scroll = top_diff; /*Do not let scrolling in*/ - lv_coord_t st = lv_obj_get_scroll_top(parent); + int32_t st = lv_obj_get_scroll_top(parent); if(st - y_scroll < 0) y_scroll = 0; } else if(bottom_diff > 0) { y_scroll = -bottom_diff; /*Do not let scrolling in*/ - lv_coord_t sb = lv_obj_get_scroll_bottom(parent); + int32_t sb = lv_obj_get_scroll_bottom(parent); if(sb + y_scroll < 0) y_scroll = 0; } switch(snap_y) { case LV_SCROLL_SNAP_START: - snap_goal = parent->coords.y1 + ptop; + snap_goal = parent->coords.y1 + stop; act = area_tmp->y1 + y_scroll; y_scroll += snap_goal - act; break; case LV_SCROLL_SNAP_END: - snap_goal = parent->coords.y2 - pbottom; + snap_goal = parent->coords.y2 - sbottom; act = area_tmp->y2 + y_scroll; y_scroll += snap_goal - act; break; case LV_SCROLL_SNAP_CENTER: - snap_goal = parent->coords.y1 + ptop + parent_h / 2; + snap_goal = parent->coords.y1 + stop + parent_h / 2; act = lv_area_get_height(area_tmp) / 2 + area_tmp->y1 + y_scroll; y_scroll += snap_goal - act; break; } - lv_coord_t x_scroll = 0; + int32_t x_scroll = 0; lv_scroll_snap_t snap_x = lv_obj_get_scroll_snap_x(parent); if(snap_x != LV_SCROLL_SNAP_NONE) area_tmp = &child->coords; else area_tmp = area; - lv_coord_t pleft = lv_obj_get_style_pad_left(parent, LV_PART_MAIN) + border_width; - lv_coord_t pright = lv_obj_get_style_pad_right(parent, LV_PART_MAIN) + border_width; - lv_coord_t left_diff = parent->coords.x1 + pleft - area_tmp->x1 - scroll_value->x; - lv_coord_t right_diff = -(parent->coords.x2 - pright - area_tmp->x2 - scroll_value->x); + int32_t sleft = lv_obj_get_style_space_left(parent, LV_PART_MAIN); + int32_t sright = lv_obj_get_style_space_right(parent, LV_PART_MAIN); + int32_t left_diff = parent->coords.x1 + sleft - area_tmp->x1 - scroll_value->x; + int32_t right_diff = -(parent->coords.x2 - sright - area_tmp->x2 - scroll_value->x); if((left_diff >= 0 && right_diff >= 0)) x_scroll = 0; else if(left_diff > 0) { x_scroll = left_diff; /*Do not let scrolling in*/ - lv_coord_t sl = lv_obj_get_scroll_left(parent); + int32_t sl = lv_obj_get_scroll_left(parent); if(sl - x_scroll < 0) x_scroll = 0; } else if(right_diff > 0) { x_scroll = -right_diff; /*Do not let scrolling in*/ - lv_coord_t sr = lv_obj_get_scroll_right(parent); + int32_t sr = lv_obj_get_scroll_right(parent); if(sr + x_scroll < 0) x_scroll = 0; } - lv_coord_t parent_w = lv_obj_get_width(parent) - pleft - pright; + int32_t parent_w = lv_obj_get_width(parent) - sleft - sright; switch(snap_x) { case LV_SCROLL_SNAP_START: - snap_goal = parent->coords.x1 + pleft; + snap_goal = parent->coords.x1 + sleft; act = area_tmp->x1 + x_scroll; x_scroll += snap_goal - act; break; case LV_SCROLL_SNAP_END: - snap_goal = parent->coords.x2 - pright; + snap_goal = parent->coords.x2 - sright; act = area_tmp->x2 + x_scroll; x_scroll += snap_goal - act; break; case LV_SCROLL_SNAP_CENTER: - snap_goal = parent->coords.x1 + pleft + parent_w / 2; + snap_goal = parent->coords.x1 + sleft + parent_w / 2; act = lv_area_get_width(area_tmp) / 2 + area_tmp->x1 + x_scroll; x_scroll += snap_goal - act; break; } /*Remove any pending scroll animations.*/ - bool y_del = lv_anim_del(parent, scroll_y_anim); - bool x_del = lv_anim_del(parent, scroll_x_anim); + bool y_del = lv_anim_delete(parent, scroll_y_anim); + bool x_del = lv_anim_delete(parent, scroll_x_anim); if(y_del || x_del) { - lv_res_t res; - res = lv_event_send(parent, LV_EVENT_SCROLL_END, NULL); - if(res != LV_RES_OK) return; + lv_result_t res; + res = lv_obj_send_event(parent, LV_EVENT_SCROLL_END, NULL); + if(res != LV_RESULT_OK) return; } if((scroll_dir & LV_DIR_LEFT) == 0 && x_scroll < 0) x_scroll = 0; diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.h index 459389e3f..0114a3b65 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_scroll.h @@ -26,26 +26,34 @@ extern "C" { **********************/ /*Can't include lv_obj.h because it includes this header file*/ -struct _lv_obj_t; /** Scrollbar modes: shows when should the scrollbars be visible*/ -enum { +enum _lv_scrollbar_mode_t { LV_SCROLLBAR_MODE_OFF, /**< Never show scrollbars*/ LV_SCROLLBAR_MODE_ON, /**< Always show scrollbars*/ LV_SCROLLBAR_MODE_ACTIVE, /**< Show scroll bars when object is being scrolled*/ LV_SCROLLBAR_MODE_AUTO, /**< Show scroll bars when the content is large enough to be scrolled*/ }; -typedef uint8_t lv_scrollbar_mode_t; +#ifdef DOXYGEN +typedef _lv_scrollbar_mode_t lv_scrollbar_mode_t; +#else +typedef uint8_t lv_scrollbar_mode_t; +#endif /*DOXYGEN*/ /** Scroll span align options. Tells where to align the snappable children when scroll stops.*/ -enum { +enum _lv_scroll_snap_t { LV_SCROLL_SNAP_NONE, /**< Do not align, leave where it is*/ LV_SCROLL_SNAP_START, /**< Align to the left/top*/ LV_SCROLL_SNAP_END, /**< Align to the right/bottom*/ LV_SCROLL_SNAP_CENTER /**< Align to the center*/ }; + +#ifdef DOXYGEN +typedef _lv_scroll_snap_t lv_scroll_snap_t; +#else typedef uint8_t lv_scroll_snap_t; +#endif /*DOXYGEN*/ /********************** * GLOBAL PROTOTYPES @@ -60,28 +68,28 @@ typedef uint8_t lv_scroll_snap_t; * @param obj pointer to an object * @param mode LV_SCROLL_MODE_ON/OFF/AUTO/ACTIVE */ -void lv_obj_set_scrollbar_mode(struct _lv_obj_t * obj, lv_scrollbar_mode_t mode); +void lv_obj_set_scrollbar_mode(lv_obj_t * obj, lv_scrollbar_mode_t mode); /** * Set the object in which directions can be scrolled * @param obj pointer to an object * @param dir the allow scroll directions. An element or OR-ed values of `lv_dir_t` */ -void lv_obj_set_scroll_dir(struct _lv_obj_t * obj, lv_dir_t dir); +void lv_obj_set_scroll_dir(lv_obj_t * obj, lv_dir_t dir); /** * Set where to snap the children when scrolling ends horizontally * @param obj pointer to an object * @param align the snap align to set from `lv_scroll_snap_t` */ -void lv_obj_set_scroll_snap_x(struct _lv_obj_t * obj, lv_scroll_snap_t align); +void lv_obj_set_scroll_snap_x(lv_obj_t * obj, lv_scroll_snap_t align); /** * Set where to snap the children when scrolling ends vertically * @param obj pointer to an object * @param align the snap align to set from `lv_scroll_snap_t` */ -void lv_obj_set_scroll_snap_y(struct _lv_obj_t * obj, lv_scroll_snap_t align); +void lv_obj_set_scroll_snap_y(lv_obj_t * obj, lv_scroll_snap_t align); /*===================== * Getter functions @@ -92,28 +100,28 @@ void lv_obj_set_scroll_snap_y(struct _lv_obj_t * obj, lv_scroll_snap_t align); * @param obj pointer to an object * @return the current scroll mode from `lv_scrollbar_mode_t` */ -lv_scrollbar_mode_t lv_obj_get_scrollbar_mode(const struct _lv_obj_t * obj); +lv_scrollbar_mode_t lv_obj_get_scrollbar_mode(const lv_obj_t * obj); /** * Get the object in which directions can be scrolled * @param obj pointer to an object * @param dir the allow scroll directions. An element or OR-ed values of `lv_dir_t` */ -lv_dir_t lv_obj_get_scroll_dir(const struct _lv_obj_t * obj); +lv_dir_t lv_obj_get_scroll_dir(const lv_obj_t * obj); /** * Get where to snap the children when scrolling ends horizontally * @param obj pointer to an object * @return the current snap align from `lv_scroll_snap_t` */ -lv_scroll_snap_t lv_obj_get_scroll_snap_x(const struct _lv_obj_t * obj); +lv_scroll_snap_t lv_obj_get_scroll_snap_x(const lv_obj_t * obj); /** * Get where to snap the children when scrolling ends vertically * @param obj pointer to an object * @return the current snap align from `lv_scroll_snap_t` */ -lv_scroll_snap_t lv_obj_get_scroll_snap_y(const struct _lv_obj_t * obj); +lv_scroll_snap_t lv_obj_get_scroll_snap_y(const lv_obj_t * obj); /** * Get current X scroll position. @@ -123,7 +131,7 @@ lv_scroll_snap_t lv_obj_get_scroll_snap_y(const struct _lv_obj_t * obj); * If scrolled return > 0 * If scrolled in (elastic scroll) return < 0 */ -lv_coord_t lv_obj_get_scroll_x(const struct _lv_obj_t * obj); +int32_t lv_obj_get_scroll_x(const lv_obj_t * obj); /** * Get current Y scroll position. @@ -133,7 +141,7 @@ lv_coord_t lv_obj_get_scroll_x(const struct _lv_obj_t * obj); * If scrolled return > 0 * If scrolled inside return < 0 */ -lv_coord_t lv_obj_get_scroll_y(const struct _lv_obj_t * obj); +int32_t lv_obj_get_scroll_y(const lv_obj_t * obj); /** * Return the height of the area above the object. @@ -142,7 +150,7 @@ lv_coord_t lv_obj_get_scroll_y(const struct _lv_obj_t * obj); * @param obj pointer to an object * @return the scrollable area above the object in pixels */ -lv_coord_t lv_obj_get_scroll_top(struct _lv_obj_t * obj); +int32_t lv_obj_get_scroll_top(lv_obj_t * obj); /** * Return the height of the area below the object. @@ -151,7 +159,7 @@ lv_coord_t lv_obj_get_scroll_top(struct _lv_obj_t * obj); * @param obj pointer to an object * @return the scrollable area below the object in pixels */ -lv_coord_t lv_obj_get_scroll_bottom(struct _lv_obj_t * obj); +int32_t lv_obj_get_scroll_bottom(lv_obj_t * obj); /** * Return the width of the area on the left the object. @@ -160,7 +168,7 @@ lv_coord_t lv_obj_get_scroll_bottom(struct _lv_obj_t * obj); * @param obj pointer to an object * @return the scrollable area on the left the object in pixels */ -lv_coord_t lv_obj_get_scroll_left(struct _lv_obj_t * obj); +int32_t lv_obj_get_scroll_left(lv_obj_t * obj); /** * Return the width of the area on the right the object. @@ -169,7 +177,7 @@ lv_coord_t lv_obj_get_scroll_left(struct _lv_obj_t * obj); * @param obj pointer to an object * @return the scrollable area on the right the object in pixels */ -lv_coord_t lv_obj_get_scroll_right(struct _lv_obj_t * obj); +int32_t lv_obj_get_scroll_right(lv_obj_t * obj); /** * Get the X and Y coordinates where the scrolling will end for this object if a scrolling animation is in progress. @@ -177,7 +185,7 @@ lv_coord_t lv_obj_get_scroll_right(struct _lv_obj_t * obj); * @param obj pointer to an object * @param end pointer to store the result */ -void lv_obj_get_scroll_end(struct _lv_obj_t * obj, lv_point_t * end); +void lv_obj_get_scroll_end(lv_obj_t * obj, lv_point_t * end); /*===================== * Other functions @@ -186,13 +194,13 @@ void lv_obj_get_scroll_end(struct _lv_obj_t * obj, lv_point_t * end); /** * Scroll by a given amount of pixels * @param obj pointer to an object to scroll - * @param dx pixels to scroll horizontally - * @param dy pixels to scroll vertically + * @param x pixels to scroll horizontally + * @param y pixels to scroll vertically * @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately * @note > 0 value means scroll right/bottom (show the more content on the right/bottom) * @note e.g. dy = -20 means scroll down 20 px */ -void lv_obj_scroll_by(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en); +void lv_obj_scroll_by(lv_obj_t * obj, int32_t x, int32_t y, lv_anim_enable_t anim_en); /** * Scroll by a given amount of pixels. @@ -203,7 +211,7 @@ void lv_obj_scroll_by(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_ani * @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately * @note e.g. dy = -20 means scroll down 20 px */ -void lv_obj_scroll_by_bounded(struct _lv_obj_t * obj, lv_coord_t dx, lv_coord_t dy, lv_anim_enable_t anim_en); +void lv_obj_scroll_by_bounded(lv_obj_t * obj, int32_t dx, int32_t dy, lv_anim_enable_t anim_en); /** * Scroll to a given coordinate on an object. @@ -213,7 +221,7 @@ void lv_obj_scroll_by_bounded(struct _lv_obj_t * obj, lv_coord_t dx, lv_coord_t * @param y pixels to scroll vertically * @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately */ -void lv_obj_scroll_to(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en); +void lv_obj_scroll_to(lv_obj_t * obj, int32_t x, int32_t y, lv_anim_enable_t anim_en); /** * Scroll to a given X coordinate on an object. @@ -222,7 +230,7 @@ void lv_obj_scroll_to(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_ani * @param x pixels to scroll horizontally * @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately */ -void lv_obj_scroll_to_x(struct _lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t anim_en); +void lv_obj_scroll_to_x(lv_obj_t * obj, int32_t x, lv_anim_enable_t anim_en); /** * Scroll to a given Y coordinate on an object @@ -231,14 +239,14 @@ void lv_obj_scroll_to_x(struct _lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t a * @param y pixels to scroll vertically * @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately */ -void lv_obj_scroll_to_y(struct _lv_obj_t * obj, lv_coord_t y, lv_anim_enable_t anim_en); +void lv_obj_scroll_to_y(lv_obj_t * obj, int32_t y, lv_anim_enable_t anim_en); /** * Scroll to an object until it becomes visible on its parent * @param obj pointer to an object to scroll into view * @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately */ -void lv_obj_scroll_to_view(struct _lv_obj_t * obj, lv_anim_enable_t anim_en); +void lv_obj_scroll_to_view(lv_obj_t * obj, lv_anim_enable_t anim_en); /** * Scroll to an object until it becomes visible on its parent. @@ -247,8 +255,7 @@ void lv_obj_scroll_to_view(struct _lv_obj_t * obj, lv_anim_enable_t anim_en); * @param obj pointer to an object to scroll into view * @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately */ -void lv_obj_scroll_to_view_recursive(struct _lv_obj_t * obj, lv_anim_enable_t anim_en); - +void lv_obj_scroll_to_view_recursive(lv_obj_t * obj, lv_anim_enable_t anim_en); /** * Low level function to scroll by given x and y coordinates. @@ -256,24 +263,24 @@ void lv_obj_scroll_to_view_recursive(struct _lv_obj_t * obj, lv_anim_enable_t an * @param obj pointer to an object to scroll * @param x pixels to scroll horizontally * @param y pixels to scroll vertically - * @return `LV_RES_INV`: to object was deleted in `LV_EVENT_SCROLL`; - * `LV_RES_OK`: if the object is still valid + * @return `LV_RESULT_INVALID`: to object was deleted in `LV_EVENT_SCROLL`; + * `LV_RESULT_OK`: if the object is still valid */ -lv_res_t _lv_obj_scroll_by_raw(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y); +lv_result_t _lv_obj_scroll_by_raw(lv_obj_t * obj, int32_t x, int32_t y); /** * Tell whether an object is being scrolled or not at this moment * @param obj pointer to an object * @return true: `obj` is being scrolled */ -bool lv_obj_is_scrolling(const struct _lv_obj_t * obj); +bool lv_obj_is_scrolling(const lv_obj_t * obj); /** * Check the children of `obj` and scroll `obj` to fulfill the scroll_snap settings * @param obj an object whose children needs to checked and snapped * @param anim_en LV_ANIM_ON/OFF */ -void lv_obj_update_snap(struct _lv_obj_t * obj, lv_anim_enable_t anim_en); +void lv_obj_update_snap(lv_obj_t * obj, lv_anim_enable_t anim_en); /** * Get the area of the scrollbars @@ -281,20 +288,20 @@ void lv_obj_update_snap(struct _lv_obj_t * obj, lv_anim_enable_t anim_en); * @param hor pointer to store the area of the horizontal scrollbar * @param ver pointer to store the area of the vertical scrollbar */ -void lv_obj_get_scrollbar_area(struct _lv_obj_t * obj, lv_area_t * hor, lv_area_t * ver); +void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor, lv_area_t * ver); /** * Invalidate the area of the scrollbars * @param obj pointer to an object */ -void lv_obj_scrollbar_invalidate(struct _lv_obj_t * obj); +void lv_obj_scrollbar_invalidate(lv_obj_t * obj); /** * Checks if the content is scrolled "in" and adjusts it to a normal position. * @param obj pointer to an object * @param anim_en LV_ANIM_ON/OFF */ -void lv_obj_readjust_scroll(struct _lv_obj_t * obj, lv_anim_enable_t anim_en); +void lv_obj_readjust_scroll(lv_obj_t * obj, lv_anim_enable_t anim_en); /********************** * MACROS diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.c index ecffca921..4bc708c18 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.c @@ -7,13 +7,19 @@ * INCLUDES *********************/ #include "lv_obj.h" -#include "lv_disp.h" -#include "../misc/lv_gc.h" - +#include "../display/lv_display.h" +#include "../display/lv_display_private.h" +#include "../misc/lv_color.h" +#include "../stdlib/lv_string.h" +#include "../core/lv_global.h" /********************* * DEFINES *********************/ #define MY_CLASS &lv_obj_class +#define style_refr LV_GLOBAL_DEFAULT()->style_refresh +#define style_trans_ll_p &(LV_GLOBAL_DEFAULT()->style_trans_ll) +#define _style_custom_prop_flag_lookup_table LV_GLOBAL_DEFAULT()->style_custom_prop_flag_lookup_table +#define STYLE_PROP_SHIFTED(prop) ((uint32_t)1 << ((prop) >> 3)) /********************** * TYPEDEFS @@ -44,21 +50,25 @@ typedef enum { **********************/ static lv_style_t * get_local_style(lv_obj_t * obj, lv_style_selector_t selector); static _lv_obj_style_t * get_trans_style(lv_obj_t * obj, uint32_t part); -static lv_style_res_t get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v); +static lv_style_res_t get_prop_core(const lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop, + lv_style_value_t * v); static void report_style_change_core(void * style, lv_obj_t * obj); static void refresh_children_style(lv_obj_t * obj); -static bool trans_del(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, trans_t * tr_limit); +static bool trans_delete(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, trans_t * tr_limit); static void trans_anim_cb(void * _tr, int32_t v); static void trans_anim_start_cb(lv_anim_t * a); -static void trans_anim_ready_cb(lv_anim_t * a); +static void trans_anim_completed_cb(lv_anim_t * a); static lv_layer_type_t calculate_layer_type(lv_obj_t * obj); +static void full_cache_refresh(lv_obj_t * obj, lv_part_t part); static void fade_anim_cb(void * obj, int32_t v); -static void fade_in_anim_ready(lv_anim_t * a); +static void fade_in_anim_completed(lv_anim_t * a); +static bool style_has_flag(const lv_style_t * style, uint32_t flag); +static lv_style_res_t get_selector_style_prop(const lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop, + lv_style_value_t * value_act); /********************** * STATIC VARIABLES **********************/ -static bool style_refr = true; /********************** * MACROS @@ -70,12 +80,32 @@ static bool style_refr = true; void _lv_obj_style_init(void) { - _lv_ll_init(&LV_GC_ROOT(_lv_obj_style_trans_ll), sizeof(trans_t)); + _lv_ll_init(style_trans_ll_p, sizeof(trans_t)); } -void lv_obj_add_style(lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector) +void _lv_obj_style_deinit(void) { - trans_del(obj, selector, LV_STYLE_PROP_ANY, NULL); + _lv_ll_clear(style_trans_ll_p); + if(_style_custom_prop_flag_lookup_table != NULL) { + lv_free(_style_custom_prop_flag_lookup_table); + _style_custom_prop_flag_lookup_table = NULL; + } +} + +void lv_obj_add_style(lv_obj_t * obj, const lv_style_t * style, lv_style_selector_t selector) +{ + LV_ASSERT(obj->style_cnt < 63); + + trans_delete(obj, selector, LV_STYLE_PROP_ANY, NULL); + + lv_part_t part = lv_obj_style_get_selector_part(selector); + + if(style && part == LV_PART_MAIN && style_has_flag(style, LV_STYLE_PROP_FLAG_TRANSFORM)) { + lv_obj_invalidate(obj); + } + + /*Try removing the style first to be sure it won't be added twice*/ + lv_obj_remove_style(obj, style, selector); uint32_t i; /*Go after the transition and local styles*/ @@ -89,27 +119,95 @@ void lv_obj_add_style(lv_obj_t * obj, lv_style_t * style, lv_style_selector_t se /*Allocate space for the new style and shift the rest of the style to the end*/ obj->style_cnt++; - obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t)); + LV_ASSERT(obj->style_cnt != 0); + obj->styles = lv_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t)); + LV_ASSERT_MALLOC(obj->styles); uint32_t j; for(j = obj->style_cnt - 1; j > i ; j--) { obj->styles[j] = obj->styles[j - 1]; } - lv_memset_00(&obj->styles[i], sizeof(_lv_obj_style_t)); + lv_memzero(&obj->styles[i], sizeof(_lv_obj_style_t)); obj->styles[i].style = style; obj->styles[i].selector = selector; +#if LV_OBJ_STYLE_CACHE + uint32_t * prop_is_set = part == LV_PART_MAIN ? &obj->style_main_prop_is_set : &obj->style_other_prop_is_set; + if(lv_style_is_const(style)) { + lv_style_const_prop_t * props = style->values_and_props; + for(i = 0; props[i].prop_ptr; i++) { + (*prop_is_set) |= STYLE_PROP_SHIFTED(*props[i].prop_ptr); + } + } + else { + lv_style_prop_t * props = (lv_style_prop_t *)style->values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + for(i = 0; i < style->prop_cnt; i++) { + (*prop_is_set) |= STYLE_PROP_SHIFTED(props[i]); + } + } +#endif + lv_obj_refresh_style(obj, selector, LV_STYLE_PROP_ANY); } -void lv_obj_remove_style(lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector) +bool lv_obj_replace_style(lv_obj_t * obj, const lv_style_t * old_style, const lv_style_t * new_style, + lv_style_selector_t selector) +{ + lv_state_t state = lv_obj_style_get_selector_state(selector); + lv_part_t part = lv_obj_style_get_selector_part(selector); + + /*All objects must exist*/ + if(!obj || !old_style || !new_style || (old_style == new_style)) { + return false; + } + + /*Similar to lv_obj_add_style, delete transition*/ + trans_delete(obj, selector, LV_STYLE_PROP_ANY, NULL); + + bool replaced = false; + uint32_t i; + for(i = 0; i < obj->style_cnt; i++) { + lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector); + lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector); + + /*Skip local styles and transitions*/ + if(obj->styles[i].is_local || obj->styles[i].is_trans) { + continue; + } + + /*Skip non-matching styles*/ + if((state != LV_STATE_ANY && state_act != state) || + (part != LV_PART_ANY && part_act != part) || + (old_style != obj->styles[i].style)) { + continue; + } + + lv_memzero(&obj->styles[i], sizeof(_lv_obj_style_t)); + obj->styles[i].style = new_style; + obj->styles[i].selector = selector; + + replaced = true; + /*Don't break and continue replacing other occurrences*/ + } + if(replaced) { + full_cache_refresh(obj, part); + lv_obj_refresh_style(obj, part, LV_STYLE_PROP_ANY); + } + return replaced; +} + +void lv_obj_remove_style(lv_obj_t * obj, const lv_style_t * style, lv_style_selector_t selector) { lv_state_t state = lv_obj_style_get_selector_state(selector); lv_part_t part = lv_obj_style_get_selector_part(selector); lv_style_prop_t prop = LV_STYLE_PROP_ANY; if(style && style->prop_cnt == 0) prop = LV_STYLE_PROP_INV; + if(style && part == LV_PART_MAIN && style_has_flag(style, LV_STYLE_PROP_FLAG_TRANSFORM)) { + lv_obj_invalidate(obj); + } + uint32_t i = 0; bool deleted = false; while(i < obj->style_cnt) { @@ -123,12 +221,12 @@ void lv_obj_remove_style(lv_obj_t * obj, lv_style_t * style, lv_style_selector_t } if(obj->styles[i].is_trans) { - trans_del(obj, part, LV_STYLE_PROP_ANY, NULL); + trans_delete(obj, part, LV_STYLE_PROP_ANY, NULL); } if(obj->styles[i].is_local || obj->styles[i].is_trans) { - lv_style_reset(obj->styles[i].style); - lv_mem_free(obj->styles[i].style); + if(obj->styles[i].style) lv_style_reset((lv_style_t *)obj->styles[i].style); + lv_free((lv_style_t *)obj->styles[i].style); obj->styles[i].style = NULL; } @@ -139,28 +237,35 @@ void lv_obj_remove_style(lv_obj_t * obj, lv_style_t * style, lv_style_selector_t } obj->style_cnt--; - obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t)); + obj->styles = lv_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t)); deleted = true; /*The style from the current `i` index is removed, so `i` points to the next style. *Therefore it doesn't needs to be incremented*/ } + if(deleted && prop != LV_STYLE_PROP_INV) { + full_cache_refresh(obj, part); lv_obj_refresh_style(obj, part, prop); } } +void lv_obj_remove_style_all(lv_obj_t * obj) +{ + lv_obj_remove_style(obj, NULL, LV_PART_ANY | LV_STATE_ANY); +} + void lv_obj_report_style_change(lv_style_t * style) { if(!style_refr) return; - lv_disp_t * d = lv_disp_get_next(NULL); + lv_display_t * d = lv_display_get_next(NULL); while(d) { uint32_t i; for(i = 0; i < d->screen_cnt; i++) { report_style_change_core(style, d->screens[i]); } - d = lv_disp_get_next(d); + d = lv_display_get_next(d); } } @@ -174,17 +279,17 @@ void lv_obj_refresh_style(lv_obj_t * obj, lv_style_selector_t selector, lv_style lv_part_t part = lv_obj_style_get_selector_part(selector); - bool is_layout_refr = lv_style_prop_has_flag(prop, LV_STYLE_PROP_LAYOUT_REFR); - bool is_ext_draw = lv_style_prop_has_flag(prop, LV_STYLE_PROP_EXT_DRAW); - bool is_inheritable = lv_style_prop_has_flag(prop, LV_STYLE_PROP_INHERIT); - bool is_layer_refr = lv_style_prop_has_flag(prop, LV_STYLE_PROP_LAYER_REFR); + bool is_layout_refr = lv_style_prop_has_flag(prop, LV_STYLE_PROP_FLAG_LAYOUT_UPDATE); + bool is_ext_draw = lv_style_prop_has_flag(prop, LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE); + bool is_inheritable = lv_style_prop_has_flag(prop, LV_STYLE_PROP_FLAG_INHERITABLE); + bool is_layer_refr = lv_style_prop_has_flag(prop, LV_STYLE_PROP_FLAG_LAYER_UPDATE); if(is_layout_refr) { if(part == LV_PART_ANY || part == LV_PART_MAIN || lv_obj_get_style_height(obj, 0) == LV_SIZE_CONTENT || lv_obj_get_style_width(obj, 0) == LV_SIZE_CONTENT) { - lv_event_send(obj, LV_EVENT_STYLE_CHANGED, NULL); + lv_obj_send_event(obj, LV_EVENT_STYLE_CHANGED, NULL); lv_obj_mark_layout_as_dirty(obj); } } @@ -220,70 +325,120 @@ void lv_obj_enable_style_refresh(bool en) style_refr = en; } +static inline lv_style_value_t lv_style_prop_get_default_inlined(lv_style_prop_t prop) +{ + const lv_color_t black = LV_COLOR_MAKE(0x00, 0x00, 0x00); + const lv_color_t white = LV_COLOR_MAKE(0xff, 0xff, 0xff); + switch(prop) { + case LV_STYLE_TRANSFORM_SCALE_X: + case LV_STYLE_TRANSFORM_SCALE_Y: + return (lv_style_value_t) { + .num = LV_SCALE_NONE + }; + case LV_STYLE_BG_COLOR: + return (lv_style_value_t) { + .color = black + }; + case LV_STYLE_BG_GRAD_COLOR: + case LV_STYLE_BORDER_COLOR: + case LV_STYLE_SHADOW_COLOR: + case LV_STYLE_OUTLINE_COLOR: + case LV_STYLE_ARC_COLOR: + case LV_STYLE_LINE_COLOR: + case LV_STYLE_TEXT_COLOR: + case LV_STYLE_IMAGE_RECOLOR: + return (lv_style_value_t) { + .color = white + }; + case LV_STYLE_OPA: + case LV_STYLE_OPA_LAYERED: + case LV_STYLE_BORDER_OPA: + case LV_STYLE_TEXT_OPA: + case LV_STYLE_IMAGE_OPA: + case LV_STYLE_BG_GRAD_OPA: + case LV_STYLE_BG_MAIN_OPA: + case LV_STYLE_BG_IMAGE_OPA: + case LV_STYLE_OUTLINE_OPA: + case LV_STYLE_SHADOW_OPA: + case LV_STYLE_LINE_OPA: + case LV_STYLE_ARC_OPA: + return (lv_style_value_t) { + .num = LV_OPA_COVER + }; + case LV_STYLE_BG_GRAD_STOP: + return (lv_style_value_t) { + .num = 255 + }; + case LV_STYLE_BORDER_SIDE: + return (lv_style_value_t) { + .num = LV_BORDER_SIDE_FULL + }; + case LV_STYLE_TEXT_FONT: + return (lv_style_value_t) { + .ptr = LV_FONT_DEFAULT + }; + case LV_STYLE_MAX_WIDTH: + case LV_STYLE_MAX_HEIGHT: + return (lv_style_value_t) { + .num = LV_COORD_MAX + }; + default: + return (lv_style_value_t) { + .ptr = 0 + }; + } +} + lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop) { - lv_style_value_t value_act; - bool inheritable = lv_style_prop_has_flag(prop, LV_STYLE_PROP_INHERIT); - lv_style_res_t found = LV_STYLE_RES_NOT_FOUND; - while(obj) { - found = get_prop_core(obj, part, prop, &value_act); - if(found == LV_STYLE_RES_FOUND) break; - if(!inheritable) break; + LV_ASSERT_NULL(obj) - /*If not found, check the `MAIN` style first*/ - if(found != LV_STYLE_RES_INHERIT && part != LV_PART_MAIN) { - part = LV_PART_MAIN; - continue; - } + lv_style_selector_t selector = part | obj->state; + lv_style_value_t value_act = { .ptr = NULL }; + lv_style_res_t found; - /*Check the parent too.*/ - obj = lv_obj_get_parent(obj); - } + found = get_selector_style_prop(obj, selector, prop, &value_act); + if(found == LV_STYLE_RES_FOUND) return value_act; - if(found != LV_STYLE_RES_FOUND) { - if(part == LV_PART_MAIN && (prop == LV_STYLE_WIDTH || prop == LV_STYLE_HEIGHT)) { - const lv_obj_class_t * cls = obj->class_p; - while(cls) { - if(prop == LV_STYLE_WIDTH) { - if(cls->width_def != 0) break; - } - else { - if(cls->height_def != 0) break; - } - cls = cls->base_class; - } + return lv_style_prop_get_default_inlined(prop); +} - if(cls) { - value_act.num = prop == LV_STYLE_WIDTH ? cls->width_def : cls->height_def; - } - else { - value_act.num = 0; - } - } - else { - value_act = lv_style_prop_get_default(prop); - } - } - return value_act; +bool lv_obj_has_style_prop(const lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop) +{ + LV_ASSERT_NULL(obj) + + lv_style_value_t value_act = { .ptr = NULL }; + lv_style_res_t found; + + found = get_selector_style_prop(obj, selector, prop, &value_act); + if(found == LV_STYLE_RES_FOUND) return true; + + return false; } void lv_obj_set_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value, lv_style_selector_t selector) { lv_style_t * style = get_local_style(obj, selector); + if(selector == LV_PART_MAIN && lv_style_prop_has_flag(prop, LV_STYLE_PROP_FLAG_TRANSFORM)) { + lv_obj_invalidate(obj); + } + lv_style_set_prop(style, prop, value); + +#if LV_OBJ_STYLE_CACHE + uint32_t prop_shifted = STYLE_PROP_SHIFTED(prop); + if(lv_obj_style_get_selector_part(selector) == LV_PART_MAIN) { + obj->style_main_prop_is_set |= prop_shifted; + } + else { + obj->style_other_prop_is_set |= prop_shifted; + } +#endif + lv_obj_refresh_style(obj, selector, prop); } -void lv_obj_set_local_style_prop_meta(lv_obj_t * obj, lv_style_prop_t prop, uint16_t meta, - lv_style_selector_t selector) -{ - lv_style_t * style = get_local_style(obj, selector); - lv_style_set_prop_meta(style, prop, meta); - lv_obj_refresh_style(obj, selector, prop); -} - - lv_style_res_t lv_obj_get_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, lv_style_selector_t selector) { @@ -314,8 +469,9 @@ bool lv_obj_remove_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_sty /*The style is not found*/ if(i == obj->style_cnt) return false; - lv_res_t res = lv_style_remove_prop(obj->styles[i].style, prop); - if(res == LV_RES_OK) { + lv_result_t res = lv_style_remove_prop((lv_style_t *)obj->styles[i].style, prop); + if(res == LV_RESULT_OK) { + full_cache_refresh(obj, lv_obj_style_get_selector_part(selector)); lv_obj_refresh_style(obj, selector, prop); } @@ -335,24 +491,24 @@ void _lv_obj_style_create_transition(lv_obj_t * obj, lv_part_t part, lv_state_t lv_style_value_t v2 = lv_obj_get_style_prop(obj, part, tr_dsc->prop); obj->skip_trans = 0; - if(v1.ptr == v2.ptr && v1.num == v2.num && v1.color.full == v2.color.full) return; + if(v1.ptr == v2.ptr && v1.num == v2.num && lv_color_eq(v1.color, v2.color)) return; obj->state = prev_state; v1 = lv_obj_get_style_prop(obj, part, tr_dsc->prop); obj->state = new_state; _lv_obj_style_t * style_trans = get_trans_style(obj, part); - lv_style_set_prop(style_trans->style, tr_dsc->prop, v1); /*Be sure `trans_style` has a valid value*/ + lv_style_set_prop((lv_style_t *)style_trans->style, tr_dsc->prop, v1); /*Be sure `trans_style` has a valid value*/ if(tr_dsc->prop == LV_STYLE_RADIUS) { if(v1.num == LV_RADIUS_CIRCLE || v2.num == LV_RADIUS_CIRCLE) { - lv_coord_t whalf = lv_obj_get_width(obj) / 2; - lv_coord_t hhalf = lv_obj_get_height(obj) / 2; + int32_t whalf = lv_obj_get_width(obj) / 2; + int32_t hhalf = lv_obj_get_height(obj) / 2; if(v1.num == LV_RADIUS_CIRCLE) v1.num = LV_MIN(whalf + 1, hhalf + 1); if(v2.num == LV_RADIUS_CIRCLE) v2.num = LV_MIN(whalf + 1, hhalf + 1); } } - tr = _lv_ll_ins_head(&LV_GC_ROOT(_lv_obj_style_trans_ll)); + tr = _lv_ll_ins_head(style_trans_ll_p); LV_ASSERT_MALLOC(tr); if(tr == NULL) return; tr->start_value = v1; @@ -366,19 +522,16 @@ void _lv_obj_style_create_transition(lv_obj_t * obj, lv_part_t part, lv_state_t lv_anim_set_var(&a, tr); lv_anim_set_exec_cb(&a, trans_anim_cb); lv_anim_set_start_cb(&a, trans_anim_start_cb); - lv_anim_set_ready_cb(&a, trans_anim_ready_cb); + lv_anim_set_completed_cb(&a, trans_anim_completed_cb); lv_anim_set_values(&a, 0x00, 0xFF); - lv_anim_set_time(&a, tr_dsc->time); + lv_anim_set_duration(&a, tr_dsc->time); lv_anim_set_delay(&a, tr_dsc->delay); lv_anim_set_path_cb(&a, tr_dsc->path_cb); lv_anim_set_early_apply(&a, false); -#if LV_USE_USER_DATA - a.user_data = tr_dsc->user_data; -#endif + lv_anim_set_user_data(&a, tr_dsc->user_data); lv_anim_start(&a); } - lv_style_value_t _lv_obj_style_apply_color_filter(const lv_obj_t * obj, uint32_t part, lv_style_value_t v) { if(obj == NULL) return v; @@ -404,7 +557,7 @@ _lv_style_state_cmp_t _lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t sta bool valid1 = state_act & (~state1) ? false : true; bool valid2 = state_act & (~state2) ? false : true; if(valid1 != valid2) { - lv_style_t * style = obj->styles[i].style; + const lv_style_t * style = obj->styles[i].style; lv_style_value_t v; /*If there is layout difference on the main part, return immediately. There is no more serious difference*/ bool layout_diff = false; @@ -424,8 +577,6 @@ _lv_style_state_cmp_t _lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t sta else if(lv_style_get_prop(style, LV_STYLE_MIN_HEIGHT, &v)) layout_diff = true; else if(lv_style_get_prop(style, LV_STYLE_MAX_HEIGHT, &v)) layout_diff = true; else if(lv_style_get_prop(style, LV_STYLE_BORDER_WIDTH, &v)) layout_diff = true; - else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ANGLE, &v)) layout_diff = true; - else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ZOOM, &v)) layout_diff = true; if(layout_diff) { return _LV_STYLE_STATE_CMP_DIFF_LAYOUT; @@ -434,15 +585,16 @@ _lv_style_state_cmp_t _lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t sta /*Check for draw pad changes*/ if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_HEIGHT, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; - else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ANGLE, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; - else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ZOOM, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; + else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ROTATION, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; + else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_SCALE_X, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; + else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_SCALE_Y, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; else if(lv_style_get_prop(style, LV_STYLE_OUTLINE_OPA, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; else if(lv_style_get_prop(style, LV_STYLE_OUTLINE_PAD, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; else if(lv_style_get_prop(style, LV_STYLE_OUTLINE_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; else if(lv_style_get_prop(style, LV_STYLE_SHADOW_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; else if(lv_style_get_prop(style, LV_STYLE_SHADOW_OPA, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; - else if(lv_style_get_prop(style, LV_STYLE_SHADOW_OFS_X, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; - else if(lv_style_get_prop(style, LV_STYLE_SHADOW_OFS_Y, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; + else if(lv_style_get_prop(style, LV_STYLE_SHADOW_OFFSET_X, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; + else if(lv_style_get_prop(style, LV_STYLE_SHADOW_OFFSET_Y, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; else if(lv_style_get_prop(style, LV_STYLE_SHADOW_SPREAD, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; else if(lv_style_get_prop(style, LV_STYLE_LINE_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD; else if(res == _LV_STYLE_STATE_CMP_SAME) res = _LV_STYLE_STATE_CMP_DIFF_REDRAW; @@ -459,8 +611,8 @@ void lv_obj_fade_in(lv_obj_t * obj, uint32_t time, uint32_t delay) lv_anim_set_var(&a, obj); lv_anim_set_values(&a, 0, LV_OPA_COVER); lv_anim_set_exec_cb(&a, fade_anim_cb); - lv_anim_set_ready_cb(&a, fade_in_anim_ready); - lv_anim_set_time(&a, time); + lv_anim_set_completed_cb(&a, fade_in_anim_completed); + lv_anim_set_duration(&a, time); lv_anim_set_delay(&a, delay); lv_anim_start(&a); } @@ -472,23 +624,12 @@ void lv_obj_fade_out(lv_obj_t * obj, uint32_t time, uint32_t delay) lv_anim_set_var(&a, obj); lv_anim_set_values(&a, lv_obj_get_style_opa(obj, 0), LV_OPA_TRANSP); lv_anim_set_exec_cb(&a, fade_anim_cb); - lv_anim_set_time(&a, time); + lv_anim_set_duration(&a, time); lv_anim_set_delay(&a, delay); lv_anim_start(&a); } -lv_state_t lv_obj_style_get_selector_state(lv_style_selector_t selector) -{ - return selector & 0xFFFF; -} - -lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector) -{ - return selector & 0xFF0000; -} - - -lv_text_align_t lv_obj_calculate_style_text_align(const struct _lv_obj_t * obj, lv_part_t part, const char * txt) +lv_text_align_t lv_obj_calculate_style_text_align(const lv_obj_t * obj, lv_part_t part, const char * txt) { lv_text_align_t align = lv_obj_get_style_text_align(obj, part); lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, part); @@ -504,7 +645,7 @@ lv_opa_t lv_obj_get_style_opa_recursive(const lv_obj_t * obj, lv_part_t part) lv_opa_t opa_final = LV_OPA_COVER; if(opa_obj < LV_OPA_MAX) { - opa_final = ((uint32_t)opa_final * opa_obj) >> 8; + opa_final = LV_OPA_MIX2(opa_final, opa_obj); } if(part != LV_PART_MAIN) { @@ -518,7 +659,7 @@ lv_opa_t lv_obj_get_style_opa_recursive(const lv_obj_t * obj, lv_part_t part) opa_obj = lv_obj_get_style_opa(obj, part); if(opa_obj <= LV_OPA_MIN) return LV_OPA_TRANSP; if(opa_obj < LV_OPA_MAX) { - opa_final = ((uint32_t)opa_final * opa_obj) >> 8; + opa_final = LV_OPA_MIX2(opa_final, opa_obj); } obj = lv_obj_get_parent(obj); @@ -529,7 +670,6 @@ lv_opa_t lv_obj_get_style_opa_recursive(const lv_obj_t * obj, lv_part_t part) return opa_final; } - /********************** * STATIC FUNCTIONS **********************/ @@ -547,12 +687,13 @@ static lv_style_t * get_local_style(lv_obj_t * obj, lv_style_selector_t selector for(i = 0; i < obj->style_cnt; i++) { if(obj->styles[i].is_local && obj->styles[i].selector == selector) { - return obj->styles[i].style; + return (lv_style_t *)obj->styles[i].style; } } obj->style_cnt++; - obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t)); + LV_ASSERT(obj->style_cnt != 0); + obj->styles = lv_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t)); LV_ASSERT_MALLOC(obj->styles); for(i = obj->style_cnt - 1; i > 0 ; i--) { @@ -562,12 +703,13 @@ static lv_style_t * get_local_style(lv_obj_t * obj, lv_style_selector_t selector obj->styles[i] = obj->styles[i - 1]; } - lv_memset_00(&obj->styles[i], sizeof(_lv_obj_style_t)); - obj->styles[i].style = lv_mem_alloc(sizeof(lv_style_t)); - lv_style_init(obj->styles[i].style); + lv_memzero(&obj->styles[i], sizeof(_lv_obj_style_t)); + obj->styles[i].style = lv_malloc(sizeof(lv_style_t)); + lv_style_init((lv_style_t *)obj->styles[i].style); + obj->styles[i].is_local = 1; obj->styles[i].selector = selector; - return obj->styles[i].style; + return (lv_style_t *)obj->styles[i].style; } /** @@ -588,31 +730,34 @@ static _lv_obj_style_t * get_trans_style(lv_obj_t * obj, lv_style_selector_t se if(i != obj->style_cnt) return &obj->styles[i]; obj->style_cnt++; - obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t)); + LV_ASSERT(obj->style_cnt != 0); + obj->styles = lv_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t)); for(i = obj->style_cnt - 1; i > 0 ; i--) { obj->styles[i] = obj->styles[i - 1]; } - lv_memset_00(&obj->styles[0], sizeof(_lv_obj_style_t)); - obj->styles[0].style = lv_mem_alloc(sizeof(lv_style_t)); - lv_style_init(obj->styles[0].style); + lv_memzero(&obj->styles[0], sizeof(_lv_obj_style_t)); + obj->styles[0].style = lv_malloc(sizeof(lv_style_t)); + lv_style_init((lv_style_t *)obj->styles[0].style); + obj->styles[0].is_trans = 1; obj->styles[0].selector = selector; return &obj->styles[0]; } - -static lv_style_res_t get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v) +static lv_style_res_t get_prop_core(const lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop, + lv_style_value_t * v) { - uint8_t group = 1 << _lv_style_get_prop_group(prop); + + const uint32_t group = (uint32_t)1 << _lv_style_get_prop_group(prop); + const lv_part_t part = lv_obj_style_get_selector_part(selector); + const lv_state_t state = lv_obj_style_get_selector_state(selector); + const lv_state_t state_inv = ~state; + const bool skip_trans = obj->skip_trans; int32_t weight = -1; - lv_state_t state = obj->state; - lv_state_t state_inv = ~state; - lv_style_value_t value_tmp; - bool skip_trans = obj->skip_trans; - uint32_t i; lv_style_res_t found; + uint32_t i; for(i = 0; i < obj->style_cnt; i++) { _lv_obj_style_t * obj_style = &obj->styles[i]; if(obj_style->is_trans == false) break; @@ -622,51 +767,36 @@ static lv_style_res_t get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_sty if(part_act != part) continue; if((obj_style->style->has_group & group) == 0) continue; - found = lv_style_get_prop(obj_style->style, prop, &value_tmp); + found = lv_style_get_prop_inlined(obj_style->style, prop, v); if(found == LV_STYLE_RES_FOUND) { - *v = value_tmp; return LV_STYLE_RES_FOUND; } - else if(found == LV_STYLE_RES_INHERIT) { - return LV_STYLE_RES_INHERIT; - } } for(; i < obj->style_cnt; i++) { if((obj->styles[i].style->has_group & group) == 0) continue; _lv_obj_style_t * obj_style = &obj->styles[i]; lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector); - lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector); if(part_act != part) continue; /*Be sure the style not specifies other state than the requested. *E.g. For HOVER+PRESS object state, HOVER style only is OK, but HOVER+FOCUS style is not*/ + lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector); if((state_act & state_inv)) continue; /*Check only better candidates*/ if(state_act <= weight) continue; - found = lv_style_get_prop(obj_style->style, prop, &value_tmp); - + found = lv_style_get_prop_inlined(obj_style->style, prop, v); if(found == LV_STYLE_RES_FOUND) { if(state_act == state) { - *v = value_tmp; return LV_STYLE_RES_FOUND; } - if(weight < state_act) { - weight = state_act; - *v = value_tmp; - } - } - else if(found == LV_STYLE_RES_INHERIT) { - return LV_STYLE_RES_INHERIT; + weight = state_act; } } - if(weight >= 0) { - *v = value_tmp; - return LV_STYLE_RES_FOUND; - } + if(weight >= 0) return LV_STYLE_RES_FOUND; else return LV_STYLE_RES_NOT_FOUND; } @@ -680,12 +810,13 @@ static void report_style_change_core(void * style, lv_obj_t * obj) uint32_t i; for(i = 0; i < obj->style_cnt; i++) { if(style == NULL || obj->styles[i].style == style) { + full_cache_refresh(obj, lv_obj_style_get_selector_part(obj->styles[i].selector)); lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY); break; } } - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); for(i = 0; i < child_cnt; i++) { report_style_change_core(style, obj->spec_attr->children[i]); } @@ -699,11 +830,11 @@ static void report_style_change_core(void * style, lv_obj_t * obj) static void refresh_children_style(lv_obj_t * obj) { uint32_t i; - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); for(i = 0; i < child_cnt; i++) { lv_obj_t * child = obj->spec_attr->children[i]; lv_obj_invalidate(child); - lv_event_send(child, LV_EVENT_STYLE_CHANGED, NULL); + lv_obj_send_event(child, LV_EVENT_STYLE_CHANGED, NULL); lv_obj_invalidate(child); refresh_children_style(child); /*Check children too*/ @@ -719,17 +850,17 @@ static void refresh_children_style(lv_obj_t * obj) * @param prop a property or 0xFF to remove all properties * @param tr_limit delete transitions only "older" than this. `NULL` if not used */ -static bool trans_del(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, trans_t * tr_limit) +static bool trans_delete(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, trans_t * tr_limit) { trans_t * tr; trans_t * tr_prev; bool removed = false; - tr = _lv_ll_get_tail(&LV_GC_ROOT(_lv_obj_style_trans_ll)); + tr = _lv_ll_get_tail(style_trans_ll_p); while(tr != NULL) { if(tr == tr_limit) break; /*'tr' might be deleted, so get the next object while 'tr' is valid*/ - tr_prev = _lv_ll_get_prev(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr); + tr_prev = _lv_ll_get_prev(style_trans_ll_p, tr); if(tr->obj == obj && (part == tr->selector || part == LV_PART_ANY) && (prop == tr->prop || prop == LV_STYLE_PROP_ANY)) { /*Remove any transitioned properties from the trans. style @@ -737,14 +868,14 @@ static bool trans_del(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, tran uint32_t i; for(i = 0; i < obj->style_cnt; i++) { if(obj->styles[i].is_trans && (part == LV_PART_ANY || obj->styles[i].selector == part)) { - lv_style_remove_prop(obj->styles[i].style, tr->prop); + lv_style_remove_prop((lv_style_t *)obj->styles[i].style, tr->prop); } } /*Free the transition descriptor too*/ - lv_anim_del(tr, NULL); - _lv_ll_remove(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr); - lv_mem_free(tr); + lv_anim_delete(tr, NULL); + _lv_ll_remove(style_trans_ll_p, tr); + lv_free(tr); removed = true; } @@ -762,7 +893,7 @@ static void trans_anim_cb(void * _tr, int32_t v) for(i = 0; i < obj->style_cnt; i++) { if(obj->styles[i].is_trans == 0 || obj->styles[i].selector != tr->selector) continue; - lv_style_value_t value_final; + lv_style_value_t value_final = {0}; switch(tr->prop) { case LV_STYLE_BORDER_SIDE: @@ -788,7 +919,7 @@ static void trans_anim_cb(void * _tr, int32_t v) case LV_STYLE_TEXT_COLOR: case LV_STYLE_SHADOW_COLOR: case LV_STYLE_OUTLINE_COLOR: - case LV_STYLE_IMG_RECOLOR: + case LV_STYLE_IMAGE_RECOLOR: if(v <= 0) value_final.color = tr->start_value.color; else if(v >= 255) value_final.color = tr->end_value.color; else value_final.color = lv_color_mix(tr->end_value.color, tr->start_value.color, v); @@ -804,12 +935,12 @@ static void trans_anim_cb(void * _tr, int32_t v) lv_style_value_t old_value; bool refr = true; if(lv_style_get_prop(obj->styles[i].style, tr->prop, &old_value)) { - if(value_final.ptr == old_value.ptr && value_final.color.full == old_value.color.full && + if(value_final.ptr == old_value.ptr && lv_color_eq(value_final.color, old_value.color) && value_final.num == old_value.num) { refr = false; } } - lv_style_set_prop(obj->styles[i].style, tr->prop, value_final); + lv_style_set_prop((lv_style_t *)obj->styles[i].style, tr->prop, value_final); if(refr) lv_obj_refresh_style(tr->obj, tr->selector, tr->prop); break; @@ -829,16 +960,17 @@ static void trans_anim_start_cb(lv_anim_t * a) tr->prop = LV_STYLE_PROP_INV; /*Delete the related transitions if any*/ - trans_del(tr->obj, part, prop_tmp, tr); + trans_delete(tr->obj, part, prop_tmp, tr); tr->prop = prop_tmp; _lv_obj_style_t * style_trans = get_trans_style(tr->obj, tr->selector); - lv_style_set_prop(style_trans->style, tr->prop, tr->start_value); /*Be sure `trans_style` has a valid value*/ + lv_style_set_prop((lv_style_t *)style_trans->style, tr->prop, + tr->start_value); /*Be sure `trans_style` has a valid value*/ } -static void trans_anim_ready_cb(lv_anim_t * a) +static void trans_anim_completed_cb(lv_anim_t * a) { trans_t * tr = a->var; lv_obj_t * obj = tr->obj; @@ -849,7 +981,7 @@ static void trans_anim_ready_cb(lv_anim_t * a) *It allows changing it by normal styles*/ bool running = false; trans_t * tr_i; - _LV_LL_READ(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr_i) { + _LV_LL_READ(style_trans_ll_p, tr_i) { if(tr_i != tr && tr_i->obj == tr->obj && tr_i->selector == tr->selector && tr_i->prop == tr->prop) { running = true; break; @@ -860,14 +992,14 @@ static void trans_anim_ready_cb(lv_anim_t * a) uint32_t i; for(i = 0; i < obj->style_cnt; i++) { if(obj->styles[i].is_trans && obj->styles[i].selector == tr->selector) { - _lv_ll_remove(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr); - lv_mem_free(tr); + _lv_ll_remove(style_trans_ll_p, tr); + lv_free(tr); _lv_obj_style_t * obj_style = &obj->styles[i]; - lv_style_remove_prop(obj_style->style, prop); + lv_style_remove_prop((lv_style_t *)obj_style->style, prop); if(lv_style_is_empty(obj->styles[i].style)) { - lv_obj_remove_style(obj, obj_style->style, obj_style->selector); + lv_obj_remove_style(obj, (lv_style_t *)obj_style->style, obj_style->selector); } break; @@ -878,23 +1010,167 @@ static void trans_anim_ready_cb(lv_anim_t * a) static lv_layer_type_t calculate_layer_type(lv_obj_t * obj) { - if(lv_obj_get_style_transform_angle(obj, 0) != 0) return LV_LAYER_TYPE_TRANSFORM; - if(lv_obj_get_style_transform_zoom(obj, 0) != 256) return LV_LAYER_TYPE_TRANSFORM; + if(lv_obj_get_style_transform_rotation(obj, 0) != 0) return LV_LAYER_TYPE_TRANSFORM; + if(lv_obj_get_style_transform_scale_x(obj, 0) != 256) return LV_LAYER_TYPE_TRANSFORM; + if(lv_obj_get_style_transform_scale_y(obj, 0) != 256) return LV_LAYER_TYPE_TRANSFORM; + if(lv_obj_get_style_transform_skew_x(obj, 0) != 0) return LV_LAYER_TYPE_TRANSFORM; + if(lv_obj_get_style_transform_skew_y(obj, 0) != 0) return LV_LAYER_TYPE_TRANSFORM; if(lv_obj_get_style_opa_layered(obj, 0) != LV_OPA_COVER) return LV_LAYER_TYPE_SIMPLE; -#if LV_DRAW_COMPLEX if(lv_obj_get_style_blend_mode(obj, 0) != LV_BLEND_MODE_NORMAL) return LV_LAYER_TYPE_SIMPLE; -#endif return LV_LAYER_TYPE_NONE; } +static void full_cache_refresh(lv_obj_t * obj, lv_part_t part) +{ +#if LV_OBJ_STYLE_CACHE + uint32_t i; + if(part == LV_PART_MAIN || part == LV_PART_ANY) { + obj->style_main_prop_is_set = 0; + for(i = 0; i < obj->style_cnt; i++) { + if(lv_obj_style_get_selector_part(obj->styles[i].selector) != LV_PART_MAIN) continue; + lv_style_t * style = (lv_style_t *)obj->styles[i].style; + uint32_t j; + if(lv_style_is_const(style)) { + lv_style_const_prop_t * props = style->values_and_props; + for(j = 0; props[j].prop_ptr; j++) { + obj->style_main_prop_is_set |= STYLE_PROP_SHIFTED(*props[j].prop_ptr); + } + } + else { + lv_style_prop_t * props = (lv_style_prop_t *)style->values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + for(j = 0; j < style->prop_cnt; j++) { + obj->style_main_prop_is_set |= STYLE_PROP_SHIFTED(props[j]); + } + } + } + } + if(part != LV_PART_MAIN || part == LV_PART_ANY) { + obj->style_other_prop_is_set = 0; + for(i = 0; i < obj->style_cnt; i++) { + if(lv_obj_style_get_selector_part(obj->styles[i].selector) == LV_PART_MAIN) continue; + lv_style_t * style = (lv_style_t *)obj->styles[i].style; + uint32_t j; + if(lv_style_is_const(style)) { + lv_style_const_prop_t * props = style->values_and_props; + for(j = 0; props[j].prop_ptr; j++) { + obj->style_other_prop_is_set |= STYLE_PROP_SHIFTED(*props[j].prop_ptr); + } + } + else { + lv_style_prop_t * props = (lv_style_prop_t *)style->values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + for(j = 0; j < style->prop_cnt; j++) { + obj->style_other_prop_is_set |= STYLE_PROP_SHIFTED(props[j]); + } + } + } + } +#else + LV_UNUSED(obj); + LV_UNUSED(part); +#endif +} + static void fade_anim_cb(void * obj, int32_t v) { lv_obj_set_style_opa(obj, v, 0); } -static void fade_in_anim_ready(lv_anim_t * a) +static void fade_in_anim_completed(lv_anim_t * a) { lv_obj_remove_local_style_prop(a->var, LV_STYLE_OPA, 0); } +static bool style_has_flag(const lv_style_t * style, uint32_t flag) +{ + if(lv_style_is_const(style)) { + lv_style_const_prop_t * props = style->values_and_props; + uint32_t i; + for(i = 0; props[i].prop_ptr; i++) { + if(lv_style_prop_has_flag(*props[i].prop_ptr, flag)) { + return true; + } + } + } + else { + lv_style_prop_t * props = (lv_style_prop_t *)style->values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + uint32_t i; + for(i = 0; i < style->prop_cnt; i++) { + if(lv_style_prop_has_flag(props[i], flag)) { + return true; + } + } + } + return false; +} +static lv_style_res_t get_selector_style_prop(const lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop, + lv_style_value_t * value_act) +{ + lv_style_res_t found; + lv_part_t part = lv_obj_style_get_selector_part(selector); + + /*The happy path*/ +#if LV_OBJ_STYLE_CACHE + const uint32_t prop_shifted = STYLE_PROP_SHIFTED(prop); + if((part == LV_PART_MAIN ? obj->style_main_prop_is_set : obj->style_other_prop_is_set) & prop_shifted) +#endif + { + found = get_prop_core(obj, selector, prop, value_act); + if(found == LV_STYLE_RES_FOUND) return LV_STYLE_RES_FOUND; + } + + extern const uint8_t _lv_style_builtin_prop_flag_lookup_table[]; + bool inheritable = false; + if(prop < _LV_STYLE_NUM_BUILT_IN_PROPS) { + inheritable = _lv_style_builtin_prop_flag_lookup_table[prop] & LV_STYLE_PROP_FLAG_INHERITABLE; + } + else { + if(_style_custom_prop_flag_lookup_table != NULL) { + inheritable = _style_custom_prop_flag_lookup_table[prop - _LV_STYLE_NUM_BUILT_IN_PROPS] & + LV_STYLE_PROP_FLAG_INHERITABLE; + } + } + + if(inheritable) { + /*If not found, check the `MAIN` style first, if already on the MAIN part go to the parent*/ + if(part != LV_PART_MAIN) part = LV_PART_MAIN; + else obj = obj->parent; + + while(obj) { +#if LV_OBJ_STYLE_CACHE + if(obj->style_main_prop_is_set & prop_shifted) +#endif + { + selector = part | obj->state; + found = get_prop_core(obj, selector, prop, value_act); + if(found == LV_STYLE_RES_FOUND) return LV_STYLE_RES_FOUND; + } + /*Check the parent too.*/ + obj = obj->parent; + } + } + else { + /*Get the width and height from the class. + * WIDTH and HEIGHT are not inherited so add them in the `else` to skip checking them for inherited properties */ + if(part == LV_PART_MAIN && (prop == LV_STYLE_WIDTH || prop == LV_STYLE_HEIGHT)) { + const lv_obj_class_t * cls = obj->class_p; + while(cls) { + if(prop == LV_STYLE_WIDTH) { + if(cls->width_def != 0) { + value_act->num = cls->width_def; + return LV_STYLE_RES_FOUND; + } + } + else { + if(cls->height_def != 0) { + value_act->num = cls->height_def; + return LV_STYLE_RES_FOUND; + } + } + cls = cls->base_class; + } + } + } + + return LV_STYLE_RES_NOT_FOUND; +} diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.h index ecc24db7e..3b52d8a38 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style.h @@ -16,6 +16,7 @@ extern "C" { #include #include #include "../misc/lv_bidi.h" +#include "../misc/lv_style.h" /********************* * DEFINES @@ -25,7 +26,17 @@ extern "C" { * TYPEDEFS **********************/ /*Can't include lv_obj.h because it includes this header file*/ -struct _lv_obj_t; + +#ifndef LV_OBJ_H +/// @cond +/** + * Tells Doxygen to ignore a duplicate declaration + */ +typedef uint32_t lv_part_t; +typedef uint16_t lv_state_t; +/// @endcond + +#endif typedef enum { _LV_STYLE_STATE_CMP_SAME, /*The style properties in the 2 states are identical*/ @@ -37,7 +48,7 @@ typedef enum { typedef uint32_t lv_style_selector_t; typedef struct { - lv_style_t * style; + const lv_style_t * style; uint32_t selector : 24; uint32_t is_local : 1; uint32_t is_trans : 1; @@ -49,9 +60,7 @@ typedef struct { lv_style_selector_t selector; lv_style_prop_t prop; lv_anim_path_cb_t path_cb; -#if LV_USE_USER_DATA void * user_data; -#endif } _lv_obj_style_transition_dsc_t; /********************** @@ -64,6 +73,12 @@ typedef struct { */ void _lv_obj_style_init(void); +/** + * Deinitialize the object related style manager module. + * Called by LVGL in `lv_deinit()` + */ +void _lv_obj_style_deinit(void); + /** * Add a style to an object. * @param obj pointer to an object @@ -72,10 +87,22 @@ void _lv_obj_style_init(void); * @example lv_obj_add_style(btn, &style_btn, 0); //Default button style * @example lv_obj_add_style(btn, &btn_red, LV_STATE_PRESSED); //Overwrite only some colors to red when pressed */ -void lv_obj_add_style(struct _lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector); +void lv_obj_add_style(lv_obj_t * obj, const lv_style_t * style, lv_style_selector_t selector); /** - * Add a style to an object. + * Replaces a style of an object, preserving the order of the style stack (local styles and transitions are ignored). + * @param obj pointer to an object + * @param old_style pointer to a style to replace. + * @param new_style pointer to a style to replace the old style with. + * @param selector OR-ed values of states and a part to replace only styles with matching selectors. LV_STATE_ANY and LV_PART_ANY can be used + * @example lv_obj_replace_style(obj, &yellow_style, &blue_style, LV_PART_ANY | LV_STATE_ANY); //Replace a specific style + * @example lv_obj_replace_style(obj, &yellow_style, &blue_style, LV_PART_MAIN | LV_STATE_PRESSED); //Replace a specific style assigned to the main part when it is pressed + */ +bool lv_obj_replace_style(lv_obj_t * obj, const lv_style_t * old_style, const lv_style_t * new_style, + lv_style_selector_t selector); + +/** + * Remove a style from an object. * @param obj pointer to an object * @param style pointer to a style to remove. Can be NULL to check only the selector * @param selector OR-ed values of states and a part to remove only styles with matching selectors. LV_STATE_ANY and LV_PART_ANY can be used @@ -83,16 +110,13 @@ void lv_obj_add_style(struct _lv_obj_t * obj, lv_style_t * style, lv_style_selec * @example lv_obj_remove_style(obj, NULL, LV_PART_MAIN | LV_STATE_ANY); //Remove all styles from the main part * @example lv_obj_remove_style(obj, NULL, LV_PART_ANY | LV_STATE_ANY); //Remove all styles */ -void lv_obj_remove_style(struct _lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector); +void lv_obj_remove_style(lv_obj_t * obj, const lv_style_t * style, lv_style_selector_t selector); /** * Remove all styles from an object * @param obj pointer to an object */ -static inline void lv_obj_remove_style_all(struct _lv_obj_t * obj) -{ - lv_obj_remove_style(obj, NULL, LV_PART_ANY | LV_STATE_ANY); -} +void lv_obj_remove_style_all(lv_obj_t * obj); /** * Notify all object if a style is modified @@ -109,7 +133,7 @@ void lv_obj_report_style_change(lv_style_t * style); * It is used to optimize what needs to be refreshed. * `LV_STYLE_PROP_INV` to perform only a style cache update */ -void lv_obj_refresh_style(struct _lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop); +void lv_obj_refresh_style(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop); /** * Enable or disable automatic style refreshing when a new style is added/removed to/from an object @@ -128,7 +152,16 @@ void lv_obj_enable_style_refresh(bool en); * @return the value of the property. * Should be read from the correct field of the `lv_style_value_t` according to the type of the property. */ -lv_style_value_t lv_obj_get_style_prop(const struct _lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop); +lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop); + +/** + * Check if an object has a specified style property for a given style selector. + * @param obj pointer to an object + * @param selector the style selector to be checked, defining the scope of the style to be examined. + * @param prop the property to be checked. + * @return true if the object has the specified selector and property, false otherwise. + */ +bool lv_obj_has_style_prop(const lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop); /** * Set local style property on an object's part and state. @@ -137,13 +170,10 @@ lv_style_value_t lv_obj_get_style_prop(const struct _lv_obj_t * obj, lv_part_t p * @param value value of the property. The correct element should be set according to the type of the property * @param selector OR-ed value of parts and state for which the style should be set */ -void lv_obj_set_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value, +void lv_obj_set_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value, lv_style_selector_t selector); -void lv_obj_set_local_style_prop_meta(struct _lv_obj_t * obj, lv_style_prop_t prop, uint16_t meta, - lv_style_selector_t selector); - -lv_style_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, +lv_style_res_t lv_obj_get_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value, lv_style_selector_t selector); /** @@ -153,12 +183,12 @@ lv_style_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop * @param selector OR-ed value of parts and state for which the style should be removed * @return true the property was found and removed; false: the property was not found */ -bool lv_obj_remove_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector); +bool lv_obj_remove_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector); /** * Used internally for color filtering */ -lv_style_value_t _lv_obj_style_apply_color_filter(const struct _lv_obj_t * obj, uint32_t part, lv_style_value_t v); +lv_style_value_t _lv_obj_style_apply_color_filter(const lv_obj_t * obj, uint32_t part, lv_style_value_t v); /** * Used internally to create a style transition @@ -168,7 +198,7 @@ lv_style_value_t _lv_obj_style_apply_color_filter(const struct _lv_obj_t * obj, * @param new_state * @param tr */ -void _lv_obj_style_create_transition(struct _lv_obj_t * obj, lv_part_t part, lv_state_t prev_state, +void _lv_obj_style_create_transition(lv_obj_t * obj, lv_part_t part, lv_state_t prev_state, lv_state_t new_state, const _lv_obj_style_transition_dsc_t * tr); /** @@ -178,7 +208,7 @@ void _lv_obj_style_create_transition(struct _lv_obj_t * obj, lv_part_t part, lv_ * @param state2 * @return */ -_lv_style_state_cmp_t _lv_obj_style_state_compare(struct _lv_obj_t * obj, lv_state_t state1, lv_state_t state2); +_lv_style_state_cmp_t _lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t state1, lv_state_t state2); /** * Fade in an an object and all its children. @@ -186,7 +216,7 @@ _lv_style_state_cmp_t _lv_obj_style_state_compare(struct _lv_obj_t * obj, lv_sta * @param time time of fade * @param delay delay to start the animation */ -void lv_obj_fade_in(struct _lv_obj_t * obj, uint32_t time, uint32_t delay); +void lv_obj_fade_in(lv_obj_t * obj, uint32_t time, uint32_t delay); /** * Fade out an an object and all its children. @@ -194,15 +224,21 @@ void lv_obj_fade_in(struct _lv_obj_t * obj, uint32_t time, uint32_t delay); * @param time time of fade * @param delay delay to start the animation */ -void lv_obj_fade_out(struct _lv_obj_t * obj, uint32_t time, uint32_t delay); +void lv_obj_fade_out(lv_obj_t * obj, uint32_t time, uint32_t delay); -lv_state_t lv_obj_style_get_selector_state(lv_style_selector_t selector); +static inline lv_state_t lv_obj_style_get_selector_state(lv_style_selector_t selector) +{ + return selector & 0xFFFF; +} -lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector); +static inline lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector) +{ + return selector & 0xFF0000; +} #include "lv_obj_style_gen.h" -static inline void lv_obj_set_style_pad_all(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +static inline void lv_obj_set_style_pad_all(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_obj_set_style_pad_left(obj, value, selector); lv_obj_set_style_pad_right(obj, value, selector); @@ -210,47 +246,111 @@ static inline void lv_obj_set_style_pad_all(struct _lv_obj_t * obj, lv_coord_t v lv_obj_set_style_pad_bottom(obj, value, selector); } -static inline void lv_obj_set_style_pad_hor(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +static inline void lv_obj_set_style_pad_hor(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_obj_set_style_pad_left(obj, value, selector); lv_obj_set_style_pad_right(obj, value, selector); } -static inline void lv_obj_set_style_pad_ver(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +static inline void lv_obj_set_style_pad_ver(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_obj_set_style_pad_top(obj, value, selector); lv_obj_set_style_pad_bottom(obj, value, selector); } -static inline void lv_obj_set_style_pad_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +static inline void lv_obj_set_style_margin_all(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +{ + lv_obj_set_style_margin_left(obj, value, selector); + lv_obj_set_style_margin_right(obj, value, selector); + lv_obj_set_style_margin_top(obj, value, selector); + lv_obj_set_style_margin_bottom(obj, value, selector); +} + +static inline void lv_obj_set_style_margin_hor(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +{ + lv_obj_set_style_margin_left(obj, value, selector); + lv_obj_set_style_margin_right(obj, value, selector); +} + +static inline void lv_obj_set_style_margin_ver(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +{ + lv_obj_set_style_margin_top(obj, value, selector); + lv_obj_set_style_margin_bottom(obj, value, selector); +} + +static inline void lv_obj_set_style_pad_gap(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_obj_set_style_pad_row(obj, value, selector); lv_obj_set_style_pad_column(obj, value, selector); } -static inline void lv_obj_set_style_size(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +static inline void lv_obj_set_style_size(lv_obj_t * obj, int32_t width, int32_t height, + lv_style_selector_t selector) { - lv_obj_set_style_width(obj, value, selector); - lv_obj_set_style_height(obj, value, selector); + lv_obj_set_style_width(obj, width, selector); + lv_obj_set_style_height(obj, height, selector); } -lv_text_align_t lv_obj_calculate_style_text_align(const struct _lv_obj_t * obj, lv_part_t part, const char * txt); - -static inline lv_coord_t lv_obj_get_style_transform_zoom_safe(const struct _lv_obj_t * obj, uint32_t part) +static inline void lv_obj_set_style_transform_scale(lv_obj_t * obj, int32_t value, + lv_style_selector_t selector) { - int16_t zoom = lv_obj_get_style_transform_zoom(obj, part); + lv_obj_set_style_transform_scale_x(obj, value, selector); + lv_obj_set_style_transform_scale_y(obj, value, selector); +} + +static inline int32_t lv_obj_get_style_space_left(const lv_obj_t * obj, uint32_t part) +{ + int32_t padding = lv_obj_get_style_pad_left(obj, part); + int32_t border_width = lv_obj_get_style_border_width(obj, part); + lv_border_side_t border_side = lv_obj_get_style_border_side(obj, part); + return (border_side & LV_BORDER_SIDE_LEFT) ? padding + border_width : padding; +} + +static inline int32_t lv_obj_get_style_space_right(const lv_obj_t * obj, uint32_t part) +{ + int32_t padding = lv_obj_get_style_pad_right(obj, part); + int32_t border_width = lv_obj_get_style_border_width(obj, part); + lv_border_side_t border_side = lv_obj_get_style_border_side(obj, part); + return (border_side & LV_BORDER_SIDE_RIGHT) ? padding + border_width : padding; +} + +static inline int32_t lv_obj_get_style_space_top(const lv_obj_t * obj, uint32_t part) +{ + int32_t padding = lv_obj_get_style_pad_top(obj, part); + int32_t border_width = lv_obj_get_style_border_width(obj, part); + lv_border_side_t border_side = lv_obj_get_style_border_side(obj, part); + return (border_side & LV_BORDER_SIDE_TOP) ? padding + border_width : padding; +} + +static inline int32_t lv_obj_get_style_space_bottom(const lv_obj_t * obj, uint32_t part) +{ + int32_t padding = lv_obj_get_style_pad_bottom(obj, part); + int32_t border_width = lv_obj_get_style_border_width(obj, part); + lv_border_side_t border_side = lv_obj_get_style_border_side(obj, part); + return (border_side & LV_BORDER_SIDE_BOTTOM) ? padding + border_width : padding; +} + +lv_text_align_t lv_obj_calculate_style_text_align(const lv_obj_t * obj, lv_part_t part, const char * txt); + +static inline int32_t lv_obj_get_style_transform_scale_x_safe(const lv_obj_t * obj, uint32_t part) +{ + int16_t zoom = lv_obj_get_style_transform_scale_x(obj, part); return zoom != 0 ? zoom : 1; } +static inline int32_t lv_obj_get_style_transform_scale_y_safe(const lv_obj_t * obj, uint32_t part) +{ + int16_t zoom = lv_obj_get_style_transform_scale_y(obj, part); + return zoom != 0 ? zoom : 1; +} /** * Get the `opa` style property from all parents and multiply and `>> 8` them. * @param obj the object whose opacity should be get - * @param part the part whose opacity should be get. Non-MAIN parts will consider the `opa` of teh MAIN part too + * @param part the part whose opacity should be get. Non-MAIN parts will consider the `opa` of the MAIN part too * @return the final opacity considering the parents' opacity too */ -lv_opa_t lv_obj_get_style_opa_recursive(const struct _lv_obj_t * obj, lv_part_t part); - +lv_opa_t lv_obj_get_style_opa_recursive(const lv_obj_t * obj, lv_part_t part); /********************** * MACROS diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.c index 81358ab9e..489962205 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.c @@ -1,6 +1,16 @@ + +/* + ********************************************************************** + * DO NOT EDIT + * This file is automatically generated by "style_api_gen.py" + ********************************************************************** + */ + + #include "lv_obj.h" -void lv_obj_set_style_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) + +void lv_obj_set_style_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -8,7 +18,7 @@ void lv_obj_set_style_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_s lv_obj_set_local_style_prop(obj, LV_STYLE_WIDTH, v, selector); } -void lv_obj_set_style_min_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_min_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -16,7 +26,7 @@ void lv_obj_set_style_min_width(struct _lv_obj_t * obj, lv_coord_t value, lv_sty lv_obj_set_local_style_prop(obj, LV_STYLE_MIN_WIDTH, v, selector); } -void lv_obj_set_style_max_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_max_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -24,7 +34,7 @@ void lv_obj_set_style_max_width(struct _lv_obj_t * obj, lv_coord_t value, lv_sty lv_obj_set_local_style_prop(obj, LV_STYLE_MAX_WIDTH, v, selector); } -void lv_obj_set_style_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -32,7 +42,7 @@ void lv_obj_set_style_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_ lv_obj_set_local_style_prop(obj, LV_STYLE_HEIGHT, v, selector); } -void lv_obj_set_style_min_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_min_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -40,7 +50,7 @@ void lv_obj_set_style_min_height(struct _lv_obj_t * obj, lv_coord_t value, lv_st lv_obj_set_local_style_prop(obj, LV_STYLE_MIN_HEIGHT, v, selector); } -void lv_obj_set_style_max_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_max_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -48,7 +58,15 @@ void lv_obj_set_style_max_height(struct _lv_obj_t * obj, lv_coord_t value, lv_st lv_obj_set_local_style_prop(obj, LV_STYLE_MAX_HEIGHT, v, selector); } -void lv_obj_set_style_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_length(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_LENGTH, v, selector); +} + +void lv_obj_set_style_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -56,7 +74,7 @@ void lv_obj_set_style_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selec lv_obj_set_local_style_prop(obj, LV_STYLE_X, v, selector); } -void lv_obj_set_style_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -64,7 +82,7 @@ void lv_obj_set_style_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selec lv_obj_set_local_style_prop(obj, LV_STYLE_Y, v, selector); } -void lv_obj_set_style_align(struct _lv_obj_t * obj, lv_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_align(lv_obj_t * obj, lv_align_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -72,7 +90,7 @@ void lv_obj_set_style_align(struct _lv_obj_t * obj, lv_align_t value, lv_style_s lv_obj_set_local_style_prop(obj, LV_STYLE_ALIGN, v, selector); } -void lv_obj_set_style_transform_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -80,7 +98,7 @@ void lv_obj_set_style_transform_width(struct _lv_obj_t * obj, lv_coord_t value, lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_WIDTH, v, selector); } -void lv_obj_set_style_transform_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -88,7 +106,7 @@ void lv_obj_set_style_transform_height(struct _lv_obj_t * obj, lv_coord_t value, lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_HEIGHT, v, selector); } -void lv_obj_set_style_translate_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_translate_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -96,7 +114,7 @@ void lv_obj_set_style_translate_x(struct _lv_obj_t * obj, lv_coord_t value, lv_s lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSLATE_X, v, selector); } -void lv_obj_set_style_translate_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_translate_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -104,23 +122,31 @@ void lv_obj_set_style_translate_y(struct _lv_obj_t * obj, lv_coord_t value, lv_s lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSLATE_Y, v, selector); } -void lv_obj_set_style_transform_zoom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_scale_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value }; - lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_ZOOM, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_SCALE_X, v, selector); } -void lv_obj_set_style_transform_angle(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_scale_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value }; - lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_ANGLE, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_SCALE_Y, v, selector); } -void lv_obj_set_style_transform_pivot_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_rotation(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_ROTATION, v, selector); +} + +void lv_obj_set_style_transform_pivot_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -128,7 +154,7 @@ void lv_obj_set_style_transform_pivot_x(struct _lv_obj_t * obj, lv_coord_t value lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_PIVOT_X, v, selector); } -void lv_obj_set_style_transform_pivot_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_pivot_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -136,7 +162,23 @@ void lv_obj_set_style_transform_pivot_y(struct _lv_obj_t * obj, lv_coord_t value lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_PIVOT_Y, v, selector); } -void lv_obj_set_style_pad_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_transform_skew_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_SKEW_X, v, selector); +} + +void lv_obj_set_style_transform_skew_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_SKEW_Y, v, selector); +} + +void lv_obj_set_style_pad_top(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -144,7 +186,7 @@ void lv_obj_set_style_pad_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_TOP, v, selector); } -void lv_obj_set_style_pad_bottom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_pad_bottom(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -152,7 +194,7 @@ void lv_obj_set_style_pad_bottom(struct _lv_obj_t * obj, lv_coord_t value, lv_st lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_BOTTOM, v, selector); } -void lv_obj_set_style_pad_left(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_pad_left(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -160,7 +202,7 @@ void lv_obj_set_style_pad_left(struct _lv_obj_t * obj, lv_coord_t value, lv_styl lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_LEFT, v, selector); } -void lv_obj_set_style_pad_right(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_pad_right(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -168,7 +210,7 @@ void lv_obj_set_style_pad_right(struct _lv_obj_t * obj, lv_coord_t value, lv_sty lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_RIGHT, v, selector); } -void lv_obj_set_style_pad_row(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_pad_row(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -176,7 +218,7 @@ void lv_obj_set_style_pad_row(struct _lv_obj_t * obj, lv_coord_t value, lv_style lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_ROW, v, selector); } -void lv_obj_set_style_pad_column(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_pad_column(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -184,7 +226,39 @@ void lv_obj_set_style_pad_column(struct _lv_obj_t * obj, lv_coord_t value, lv_st lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_COLUMN, v, selector); } -void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_margin_top(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_MARGIN_TOP, v, selector); +} + +void lv_obj_set_style_margin_bottom(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_MARGIN_BOTTOM, v, selector); +} + +void lv_obj_set_style_margin_left(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_MARGIN_LEFT, v, selector); +} + +void lv_obj_set_style_margin_right(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_MARGIN_RIGHT, v, selector); +} + +void lv_obj_set_style_bg_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) { lv_style_value_t v = { .color = value @@ -192,7 +266,7 @@ void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_styl lv_obj_set_local_style_prop(obj, LV_STYLE_BG_COLOR, v, selector); } -void lv_obj_set_style_bg_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -200,7 +274,7 @@ void lv_obj_set_style_bg_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_se lv_obj_set_local_style_prop(obj, LV_STYLE_BG_OPA, v, selector); } -void lv_obj_set_style_bg_grad_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_grad_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) { lv_style_value_t v = { .color = value @@ -208,7 +282,7 @@ void lv_obj_set_style_bg_grad_color(struct _lv_obj_t * obj, lv_color_t value, lv lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_COLOR, v, selector); } -void lv_obj_set_style_bg_grad_dir(struct _lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_grad_dir(lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -216,7 +290,7 @@ void lv_obj_set_style_bg_grad_dir(struct _lv_obj_t * obj, lv_grad_dir_t value, l lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_DIR, v, selector); } -void lv_obj_set_style_bg_main_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_main_stop(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -224,7 +298,7 @@ void lv_obj_set_style_bg_main_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_ lv_obj_set_local_style_prop(obj, LV_STYLE_BG_MAIN_STOP, v, selector); } -void lv_obj_set_style_bg_grad_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_grad_stop(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -232,7 +306,23 @@ void lv_obj_set_style_bg_grad_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_ lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_STOP, v, selector); } -void lv_obj_set_style_bg_grad(struct _lv_obj_t * obj, const lv_grad_dsc_t * value, lv_style_selector_t selector) +void lv_obj_set_style_bg_main_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_BG_MAIN_OPA, v, selector); +} + +void lv_obj_set_style_bg_grad_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_OPA, v, selector); +} + +void lv_obj_set_style_bg_grad(lv_obj_t * obj, const lv_grad_dsc_t * value, lv_style_selector_t selector) { lv_style_value_t v = { .ptr = value @@ -240,55 +330,47 @@ void lv_obj_set_style_bg_grad(struct _lv_obj_t * obj, const lv_grad_dsc_t * valu lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD, v, selector); } -void lv_obj_set_style_bg_dither_mode(struct _lv_obj_t * obj, lv_dither_mode_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .num = (int32_t)value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_BG_DITHER_MODE, v, selector); -} - -void lv_obj_set_style_bg_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector) +void lv_obj_set_style_bg_image_src(lv_obj_t * obj, const void * value, lv_style_selector_t selector) { lv_style_value_t v = { .ptr = value }; - lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_SRC, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMAGE_SRC, v, selector); } -void lv_obj_set_style_bg_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_image_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value }; - lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_OPA, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMAGE_OPA, v, selector); } -void lv_obj_set_style_bg_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_image_recolor(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) { lv_style_value_t v = { .color = value }; - lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_RECOLOR, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMAGE_RECOLOR, v, selector); } -void lv_obj_set_style_bg_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_bg_image_recolor_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value }; - lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_RECOLOR_OPA, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMAGE_RECOLOR_OPA, v, selector); } -void lv_obj_set_style_bg_img_tiled(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) +void lv_obj_set_style_bg_image_tiled(lv_obj_t * obj, bool value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value }; - lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_TILED, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMAGE_TILED, v, selector); } -void lv_obj_set_style_border_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_border_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) { lv_style_value_t v = { .color = value @@ -296,7 +378,7 @@ void lv_obj_set_style_border_color(struct _lv_obj_t * obj, lv_color_t value, lv_ lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_COLOR, v, selector); } -void lv_obj_set_style_border_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_border_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -304,7 +386,7 @@ void lv_obj_set_style_border_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_styl lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_OPA, v, selector); } -void lv_obj_set_style_border_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_border_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -312,7 +394,7 @@ void lv_obj_set_style_border_width(struct _lv_obj_t * obj, lv_coord_t value, lv_ lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_WIDTH, v, selector); } -void lv_obj_set_style_border_side(struct _lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector) +void lv_obj_set_style_border_side(lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -320,7 +402,7 @@ void lv_obj_set_style_border_side(struct _lv_obj_t * obj, lv_border_side_t value lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_SIDE, v, selector); } -void lv_obj_set_style_border_post(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) +void lv_obj_set_style_border_post(lv_obj_t * obj, bool value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -328,7 +410,7 @@ void lv_obj_set_style_border_post(struct _lv_obj_t * obj, bool value, lv_style_s lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_POST, v, selector); } -void lv_obj_set_style_outline_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_outline_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -336,7 +418,7 @@ void lv_obj_set_style_outline_width(struct _lv_obj_t * obj, lv_coord_t value, lv lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_WIDTH, v, selector); } -void lv_obj_set_style_outline_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_outline_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) { lv_style_value_t v = { .color = value @@ -344,7 +426,7 @@ void lv_obj_set_style_outline_color(struct _lv_obj_t * obj, lv_color_t value, lv lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_COLOR, v, selector); } -void lv_obj_set_style_outline_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_outline_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -352,7 +434,7 @@ void lv_obj_set_style_outline_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_sty lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_OPA, v, selector); } -void lv_obj_set_style_outline_pad(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_outline_pad(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -360,7 +442,7 @@ void lv_obj_set_style_outline_pad(struct _lv_obj_t * obj, lv_coord_t value, lv_s lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_PAD, v, selector); } -void lv_obj_set_style_shadow_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_shadow_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -368,23 +450,23 @@ void lv_obj_set_style_shadow_width(struct _lv_obj_t * obj, lv_coord_t value, lv_ lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_WIDTH, v, selector); } -void lv_obj_set_style_shadow_ofs_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_shadow_offset_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value }; - lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OFS_X, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OFFSET_X, v, selector); } -void lv_obj_set_style_shadow_ofs_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_shadow_offset_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value }; - lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OFS_Y, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OFFSET_Y, v, selector); } -void lv_obj_set_style_shadow_spread(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_shadow_spread(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -392,7 +474,7 @@ void lv_obj_set_style_shadow_spread(struct _lv_obj_t * obj, lv_coord_t value, lv lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_SPREAD, v, selector); } -void lv_obj_set_style_shadow_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_shadow_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) { lv_style_value_t v = { .color = value @@ -400,7 +482,7 @@ void lv_obj_set_style_shadow_color(struct _lv_obj_t * obj, lv_color_t value, lv_ lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_COLOR, v, selector); } -void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_shadow_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -408,31 +490,31 @@ void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_styl lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OPA, v, selector); } -void lv_obj_set_style_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_image_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value }; - lv_obj_set_local_style_prop(obj, LV_STYLE_IMG_OPA, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_IMAGE_OPA, v, selector); } -void lv_obj_set_style_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_image_recolor(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) { lv_style_value_t v = { .color = value }; - lv_obj_set_local_style_prop(obj, LV_STYLE_IMG_RECOLOR, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_IMAGE_RECOLOR, v, selector); } -void lv_obj_set_style_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_image_recolor_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value }; - lv_obj_set_local_style_prop(obj, LV_STYLE_IMG_RECOLOR_OPA, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_IMAGE_RECOLOR_OPA, v, selector); } -void lv_obj_set_style_line_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_line_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -440,7 +522,7 @@ void lv_obj_set_style_line_width(struct _lv_obj_t * obj, lv_coord_t value, lv_st lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_WIDTH, v, selector); } -void lv_obj_set_style_line_dash_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_line_dash_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -448,7 +530,7 @@ void lv_obj_set_style_line_dash_width(struct _lv_obj_t * obj, lv_coord_t value, lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_DASH_WIDTH, v, selector); } -void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_line_dash_gap(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -456,7 +538,7 @@ void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_DASH_GAP, v, selector); } -void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) +void lv_obj_set_style_line_rounded(lv_obj_t * obj, bool value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -464,7 +546,7 @@ void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, bool value, lv_style_ lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_ROUNDED, v, selector); } -void lv_obj_set_style_line_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_line_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) { lv_style_value_t v = { .color = value @@ -472,7 +554,7 @@ void lv_obj_set_style_line_color(struct _lv_obj_t * obj, lv_color_t value, lv_st lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_COLOR, v, selector); } -void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_line_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -480,7 +562,7 @@ void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_ lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_OPA, v, selector); } -void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_arc_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -488,7 +570,7 @@ void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_sty lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_WIDTH, v, selector); } -void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) +void lv_obj_set_style_arc_rounded(lv_obj_t * obj, bool value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -496,7 +578,7 @@ void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, bool value, lv_style_s lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_ROUNDED, v, selector); } -void lv_obj_set_style_arc_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_arc_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) { lv_style_value_t v = { .color = value @@ -504,7 +586,7 @@ void lv_obj_set_style_arc_color(struct _lv_obj_t * obj, lv_color_t value, lv_sty lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_COLOR, v, selector); } -void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_arc_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -512,15 +594,15 @@ void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_s lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_OPA, v, selector); } -void lv_obj_set_style_arc_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector) +void lv_obj_set_style_arc_image_src(lv_obj_t * obj, const void * value, lv_style_selector_t selector) { lv_style_value_t v = { .ptr = value }; - lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_IMG_SRC, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_IMAGE_SRC, v, selector); } -void lv_obj_set_style_text_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) +void lv_obj_set_style_text_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector) { lv_style_value_t v = { .color = value @@ -528,7 +610,7 @@ void lv_obj_set_style_text_color(struct _lv_obj_t * obj, lv_color_t value, lv_st lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_COLOR, v, selector); } -void lv_obj_set_style_text_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_text_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -536,7 +618,7 @@ void lv_obj_set_style_text_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_ lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_OPA, v, selector); } -void lv_obj_set_style_text_font(struct _lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector) +void lv_obj_set_style_text_font(lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector) { lv_style_value_t v = { .ptr = value @@ -544,7 +626,7 @@ void lv_obj_set_style_text_font(struct _lv_obj_t * obj, const lv_font_t * value, lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_FONT, v, selector); } -void lv_obj_set_style_text_letter_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_text_letter_space(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -552,7 +634,7 @@ void lv_obj_set_style_text_letter_space(struct _lv_obj_t * obj, lv_coord_t value lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_LETTER_SPACE, v, selector); } -void lv_obj_set_style_text_line_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_text_line_space(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -560,7 +642,7 @@ void lv_obj_set_style_text_line_space(struct _lv_obj_t * obj, lv_coord_t value, lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_LINE_SPACE, v, selector); } -void lv_obj_set_style_text_decor(struct _lv_obj_t * obj, lv_text_decor_t value, lv_style_selector_t selector) +void lv_obj_set_style_text_decor(lv_obj_t * obj, lv_text_decor_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -568,7 +650,7 @@ void lv_obj_set_style_text_decor(struct _lv_obj_t * obj, lv_text_decor_t value, lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_DECOR, v, selector); } -void lv_obj_set_style_text_align(struct _lv_obj_t * obj, lv_text_align_t value, lv_style_selector_t selector) +void lv_obj_set_style_text_align(lv_obj_t * obj, lv_text_align_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -576,7 +658,7 @@ void lv_obj_set_style_text_align(struct _lv_obj_t * obj, lv_text_align_t value, lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_ALIGN, v, selector); } -void lv_obj_set_style_radius(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) +void lv_obj_set_style_radius(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -584,7 +666,7 @@ void lv_obj_set_style_radius(struct _lv_obj_t * obj, lv_coord_t value, lv_style_ lv_obj_set_local_style_prop(obj, LV_STYLE_RADIUS, v, selector); } -void lv_obj_set_style_clip_corner(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector) +void lv_obj_set_style_clip_corner(lv_obj_t * obj, bool value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -592,7 +674,7 @@ void lv_obj_set_style_clip_corner(struct _lv_obj_t * obj, bool value, lv_style_s lv_obj_set_local_style_prop(obj, LV_STYLE_CLIP_CORNER, v, selector); } -void lv_obj_set_style_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -600,7 +682,7 @@ void lv_obj_set_style_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selec lv_obj_set_local_style_prop(obj, LV_STYLE_OPA, v, selector); } -void lv_obj_set_style_opa_layered(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_opa_layered(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -608,7 +690,8 @@ void lv_obj_set_style_opa_layered(struct _lv_obj_t * obj, lv_opa_t value, lv_sty lv_obj_set_local_style_prop(obj, LV_STYLE_OPA_LAYERED, v, selector); } -void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector) +void lv_obj_set_style_color_filter_dsc(lv_obj_t * obj, const lv_color_filter_dsc_t * value, + lv_style_selector_t selector) { lv_style_value_t v = { .ptr = value @@ -616,7 +699,7 @@ void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_fi lv_obj_set_local_style_prop(obj, LV_STYLE_COLOR_FILTER_DSC, v, selector); } -void lv_obj_set_style_color_filter_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) +void lv_obj_set_style_color_filter_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -624,7 +707,7 @@ void lv_obj_set_style_color_filter_opa(struct _lv_obj_t * obj, lv_opa_t value, l lv_obj_set_local_style_prop(obj, LV_STYLE_COLOR_FILTER_OPA, v, selector); } -void lv_obj_set_style_anim(struct _lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector) +void lv_obj_set_style_anim(lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector) { lv_style_value_t v = { .ptr = value @@ -632,23 +715,15 @@ void lv_obj_set_style_anim(struct _lv_obj_t * obj, const lv_anim_t * value, lv_s lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM, v, selector); } -void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector) +void lv_obj_set_style_anim_duration(lv_obj_t * obj, uint32_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value }; - lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM_TIME, v, selector); + lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM_DURATION, v, selector); } -void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .num = (int32_t)value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM_SPEED, v, selector); -} - -void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector) +void lv_obj_set_style_transition(lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector) { lv_style_value_t v = { .ptr = value @@ -656,7 +731,7 @@ void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transiti lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSITION, v, selector); } -void lv_obj_set_style_blend_mode(struct _lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector) +void lv_obj_set_style_blend_mode(lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -664,7 +739,7 @@ void lv_obj_set_style_blend_mode(struct _lv_obj_t * obj, lv_blend_mode_t value, lv_obj_set_local_style_prop(obj, LV_STYLE_BLEND_MODE, v, selector); } -void lv_obj_set_style_layout(struct _lv_obj_t * obj, uint16_t value, lv_style_selector_t selector) +void lv_obj_set_style_layout(lv_obj_t * obj, uint16_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value @@ -672,10 +747,138 @@ void lv_obj_set_style_layout(struct _lv_obj_t * obj, uint16_t value, lv_style_se lv_obj_set_local_style_prop(obj, LV_STYLE_LAYOUT, v, selector); } -void lv_obj_set_style_base_dir(struct _lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector) +void lv_obj_set_style_base_dir(lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector) { lv_style_value_t v = { .num = (int32_t)value }; lv_obj_set_local_style_prop(obj, LV_STYLE_BASE_DIR, v, selector); } +#if LV_USE_FLEX + + +void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_FLOW, v, selector); +} + +void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_MAIN_PLACE, v, selector); +} + +void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_CROSS_PLACE, v, selector); +} + +void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_TRACK_PLACE, v, selector); +} + +void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_GROW, v, selector); +} +#endif /*LV_USE_FLEX*/ + +#if LV_USE_GRID + + +void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const int32_t * value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .ptr = value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_COLUMN_DSC_ARRAY, v, selector); +} + +void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_COLUMN_ALIGN, v, selector); +} + +void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const int32_t * value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .ptr = value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_ROW_DSC_ARRAY, v, selector); +} + +void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_ROW_ALIGN, v, selector); +} + +void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_POS, v, selector); +} + +void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_X_ALIGN, v, selector); +} + +void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_SPAN, v, selector); +} + +void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_ROW_POS, v, selector); +} + +void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_Y_ALIGN, v, selector); +} + +void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, int32_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_ROW_SPAN, v, selector); +} +#endif /*LV_USE_GRID*/ + diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.h index 4a135be09..a8d67e837 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_style_gen.h @@ -1,655 +1,855 @@ -static inline lv_coord_t lv_obj_get_style_width(const struct _lv_obj_t * obj, uint32_t part) + +/* + ********************************************************************** + * DO NOT EDIT + * This file is automatically generated by "style_api_gen.py" + ********************************************************************** + */ + +#ifndef LV_OBJ_STYLE_GEN_H +#define LV_OBJ_STYLE_GEN_H + +#include "../misc/lv_area.h" +#include "../misc/lv_style.h" +#include "../core/lv_obj_style.h" + +static inline int32_t lv_obj_get_style_width(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_WIDTH); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_min_width(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_min_width(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MIN_WIDTH); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_max_width(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_max_width(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MAX_WIDTH); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_height(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_height(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_HEIGHT); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_min_height(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_min_height(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MIN_HEIGHT); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_max_height(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_max_height(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MAX_HEIGHT); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_x(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_length(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LENGTH); + return (int32_t)v.num; +} + +static inline int32_t lv_obj_get_style_x(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_X); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_y(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_y(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_Y); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_align_t lv_obj_get_style_align(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_align_t lv_obj_get_style_align(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ALIGN); return (lv_align_t)v.num; } -static inline lv_coord_t lv_obj_get_style_transform_width(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_width(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_WIDTH); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_transform_height(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_height(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_HEIGHT); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_translate_x(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_translate_x(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSLATE_X); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_translate_y(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_translate_y(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSLATE_Y); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_transform_zoom(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_scale_x(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_ZOOM); - return (lv_coord_t)v.num; + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_SCALE_X); + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_transform_angle(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_scale_y(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_ANGLE); - return (lv_coord_t)v.num; + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_SCALE_Y); + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_transform_pivot_x(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_rotation(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_ROTATION); + return (int32_t)v.num; +} + +static inline int32_t lv_obj_get_style_transform_pivot_x(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_PIVOT_X); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_transform_pivot_y(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_pivot_y(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_PIVOT_Y); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_pad_top(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_transform_skew_x(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_SKEW_X); + return (int32_t)v.num; +} + +static inline int32_t lv_obj_get_style_transform_skew_y(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_SKEW_Y); + return (int32_t)v.num; +} + +static inline int32_t lv_obj_get_style_pad_top(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_TOP); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_pad_bottom(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_pad_bottom(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_BOTTOM); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_pad_left(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_pad_left(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_LEFT); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_pad_right(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_pad_right(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_RIGHT); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_pad_row(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_pad_row(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_ROW); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_pad_column(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_pad_column(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_COLUMN); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_color_t lv_obj_get_style_bg_color(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_margin_top(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MARGIN_TOP); + return (int32_t)v.num; +} + +static inline int32_t lv_obj_get_style_margin_bottom(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MARGIN_BOTTOM); + return (int32_t)v.num; +} + +static inline int32_t lv_obj_get_style_margin_left(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MARGIN_LEFT); + return (int32_t)v.num; +} + +static inline int32_t lv_obj_get_style_margin_right(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MARGIN_RIGHT); + return (int32_t)v.num; +} + +static inline lv_color_t lv_obj_get_style_bg_color(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_COLOR); return v.color; } -static inline lv_color_t lv_obj_get_style_bg_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_bg_color_filtered(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_COLOR)); return v.color; } -static inline lv_opa_t lv_obj_get_style_bg_opa(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_bg_opa(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_OPA); return (lv_opa_t)v.num; } -static inline lv_color_t lv_obj_get_style_bg_grad_color(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_bg_grad_color(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR); return v.color; } -static inline lv_color_t lv_obj_get_style_bg_grad_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_bg_grad_color_filtered(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR)); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, + LV_STYLE_BG_GRAD_COLOR)); return v.color; } -static inline lv_grad_dir_t lv_obj_get_style_bg_grad_dir(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_grad_dir_t lv_obj_get_style_bg_grad_dir(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_DIR); return (lv_grad_dir_t)v.num; } -static inline lv_coord_t lv_obj_get_style_bg_main_stop(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_bg_main_stop(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_MAIN_STOP); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_bg_grad_stop(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_bg_grad_stop(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_STOP); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline const lv_grad_dsc_t * lv_obj_get_style_bg_grad(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_bg_main_opa(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_MAIN_OPA); + return (lv_opa_t)v.num; +} + +static inline lv_opa_t lv_obj_get_style_bg_grad_opa(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_OPA); + return (lv_opa_t)v.num; +} + +static inline const lv_grad_dsc_t * lv_obj_get_style_bg_grad(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD); return (const lv_grad_dsc_t *)v.ptr; } -static inline lv_dither_mode_t lv_obj_get_style_bg_dither_mode(const struct _lv_obj_t * obj, uint32_t part) +static inline const void * lv_obj_get_style_bg_image_src(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_DITHER_MODE); - return (lv_dither_mode_t)v.num; -} - -static inline const void * lv_obj_get_style_bg_img_src(const struct _lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_SRC); + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMAGE_SRC); return (const void *)v.ptr; } -static inline lv_opa_t lv_obj_get_style_bg_img_opa(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_bg_image_opa(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_OPA); + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMAGE_OPA); return (lv_opa_t)v.num; } -static inline lv_color_t lv_obj_get_style_bg_img_recolor(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_bg_image_recolor(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR); + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMAGE_RECOLOR); return v.color; } -static inline lv_color_t lv_obj_get_style_bg_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_bg_image_recolor_filtered(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR)); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, + LV_STYLE_BG_IMAGE_RECOLOR)); return v.color; } -static inline lv_opa_t lv_obj_get_style_bg_img_recolor_opa(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_bg_image_recolor_opa(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR_OPA); + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMAGE_RECOLOR_OPA); return (lv_opa_t)v.num; } -static inline bool lv_obj_get_style_bg_img_tiled(const struct _lv_obj_t * obj, uint32_t part) +static inline bool lv_obj_get_style_bg_image_tiled(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_TILED); + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMAGE_TILED); return (bool)v.num; } -static inline lv_color_t lv_obj_get_style_border_color(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_border_color(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR); return v.color; } -static inline lv_color_t lv_obj_get_style_border_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_border_color_filtered(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR)); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, + LV_STYLE_BORDER_COLOR)); return v.color; } -static inline lv_opa_t lv_obj_get_style_border_opa(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_border_opa(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_OPA); return (lv_opa_t)v.num; } -static inline lv_coord_t lv_obj_get_style_border_width(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_border_width(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_WIDTH); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_border_side_t lv_obj_get_style_border_side(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_border_side_t lv_obj_get_style_border_side(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_SIDE); return (lv_border_side_t)v.num; } -static inline bool lv_obj_get_style_border_post(const struct _lv_obj_t * obj, uint32_t part) +static inline bool lv_obj_get_style_border_post(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_POST); return (bool)v.num; } -static inline lv_coord_t lv_obj_get_style_outline_width(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_outline_width(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_WIDTH); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_color_t lv_obj_get_style_outline_color(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_outline_color(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR); return v.color; } -static inline lv_color_t lv_obj_get_style_outline_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_outline_color_filtered(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR)); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, + LV_STYLE_OUTLINE_COLOR)); return v.color; } -static inline lv_opa_t lv_obj_get_style_outline_opa(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_outline_opa(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_OPA); return (lv_opa_t)v.num; } -static inline lv_coord_t lv_obj_get_style_outline_pad(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_outline_pad(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_PAD); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_shadow_width(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_shadow_width(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_WIDTH); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_shadow_ofs_x(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_shadow_offset_x(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OFS_X); - return (lv_coord_t)v.num; + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OFFSET_X); + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_shadow_ofs_y(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_shadow_offset_y(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OFS_Y); - return (lv_coord_t)v.num; + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OFFSET_Y); + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_shadow_spread(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_shadow_spread(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_SPREAD); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_color_t lv_obj_get_style_shadow_color(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_shadow_color(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR); return v.color; } -static inline lv_color_t lv_obj_get_style_shadow_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_shadow_color_filtered(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR)); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, + LV_STYLE_SHADOW_COLOR)); return v.color; } -static inline lv_opa_t lv_obj_get_style_shadow_opa(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_shadow_opa(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OPA); return (lv_opa_t)v.num; } -static inline lv_opa_t lv_obj_get_style_img_opa(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_image_opa(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_OPA); + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMAGE_OPA); return (lv_opa_t)v.num; } -static inline lv_color_t lv_obj_get_style_img_recolor(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_image_recolor(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR); + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMAGE_RECOLOR); return v.color; } -static inline lv_color_t lv_obj_get_style_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_image_recolor_filtered(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR)); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, + LV_STYLE_IMAGE_RECOLOR)); return v.color; } -static inline lv_opa_t lv_obj_get_style_img_recolor_opa(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_image_recolor_opa(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR_OPA); + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMAGE_RECOLOR_OPA); return (lv_opa_t)v.num; } -static inline lv_coord_t lv_obj_get_style_line_width(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_line_width(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_WIDTH); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_line_dash_width(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_line_dash_width(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_DASH_WIDTH); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_line_dash_gap(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_line_dash_gap(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_DASH_GAP); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline bool lv_obj_get_style_line_rounded(const struct _lv_obj_t * obj, uint32_t part) +static inline bool lv_obj_get_style_line_rounded(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_ROUNDED); return (bool)v.num; } -static inline lv_color_t lv_obj_get_style_line_color(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_line_color(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_COLOR); return v.color; } -static inline lv_color_t lv_obj_get_style_line_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_line_color_filtered(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_COLOR)); return v.color; } -static inline lv_opa_t lv_obj_get_style_line_opa(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_line_opa(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_OPA); return (lv_opa_t)v.num; } -static inline lv_coord_t lv_obj_get_style_arc_width(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_arc_width(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_WIDTH); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline bool lv_obj_get_style_arc_rounded(const struct _lv_obj_t * obj, uint32_t part) +static inline bool lv_obj_get_style_arc_rounded(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_ROUNDED); return (bool)v.num; } -static inline lv_color_t lv_obj_get_style_arc_color(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_arc_color(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_COLOR); return v.color; } -static inline lv_color_t lv_obj_get_style_arc_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_arc_color_filtered(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_COLOR)); return v.color; } -static inline lv_opa_t lv_obj_get_style_arc_opa(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_arc_opa(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_OPA); return (lv_opa_t)v.num; } -static inline const void * lv_obj_get_style_arc_img_src(const struct _lv_obj_t * obj, uint32_t part) +static inline const void * lv_obj_get_style_arc_image_src(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_IMG_SRC); + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_IMAGE_SRC); return (const void *)v.ptr; } -static inline lv_color_t lv_obj_get_style_text_color(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_text_color(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_COLOR); return v.color; } -static inline lv_color_t lv_obj_get_style_text_color_filtered(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_color_t lv_obj_get_style_text_color_filtered(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_COLOR)); return v.color; } -static inline lv_opa_t lv_obj_get_style_text_opa(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_text_opa(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_OPA); return (lv_opa_t)v.num; } -static inline const lv_font_t * lv_obj_get_style_text_font(const struct _lv_obj_t * obj, uint32_t part) +static inline const lv_font_t * lv_obj_get_style_text_font(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_FONT); return (const lv_font_t *)v.ptr; } -static inline lv_coord_t lv_obj_get_style_text_letter_space(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_text_letter_space(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_LETTER_SPACE); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_coord_t lv_obj_get_style_text_line_space(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_text_line_space(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_LINE_SPACE); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline lv_text_decor_t lv_obj_get_style_text_decor(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_text_decor_t lv_obj_get_style_text_decor(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_DECOR); return (lv_text_decor_t)v.num; } -static inline lv_text_align_t lv_obj_get_style_text_align(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_text_align_t lv_obj_get_style_text_align(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_ALIGN); return (lv_text_align_t)v.num; } -static inline lv_coord_t lv_obj_get_style_radius(const struct _lv_obj_t * obj, uint32_t part) +static inline int32_t lv_obj_get_style_radius(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_RADIUS); - return (lv_coord_t)v.num; + return (int32_t)v.num; } -static inline bool lv_obj_get_style_clip_corner(const struct _lv_obj_t * obj, uint32_t part) +static inline bool lv_obj_get_style_clip_corner(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_CLIP_CORNER); return (bool)v.num; } -static inline lv_opa_t lv_obj_get_style_opa(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_opa(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OPA); return (lv_opa_t)v.num; } -static inline lv_opa_t lv_obj_get_style_opa_layered(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_opa_layered(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OPA_LAYERED); return (lv_opa_t)v.num; } -static inline const lv_color_filter_dsc_t * lv_obj_get_style_color_filter_dsc(const struct _lv_obj_t * obj, uint32_t part) +static inline const lv_color_filter_dsc_t * lv_obj_get_style_color_filter_dsc(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_COLOR_FILTER_DSC); return (const lv_color_filter_dsc_t *)v.ptr; } -static inline lv_opa_t lv_obj_get_style_color_filter_opa(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_opa_t lv_obj_get_style_color_filter_opa(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_COLOR_FILTER_OPA); return (lv_opa_t)v.num; } -static inline const lv_anim_t * lv_obj_get_style_anim(const struct _lv_obj_t * obj, uint32_t part) +static inline const lv_anim_t * lv_obj_get_style_anim(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM); return (const lv_anim_t *)v.ptr; } -static inline uint32_t lv_obj_get_style_anim_time(const struct _lv_obj_t * obj, uint32_t part) +static inline uint32_t lv_obj_get_style_anim_duration(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM_TIME); + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM_DURATION); return (uint32_t)v.num; } -static inline uint32_t lv_obj_get_style_anim_speed(const struct _lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM_SPEED); - return (uint32_t)v.num; -} - -static inline const lv_style_transition_dsc_t * lv_obj_get_style_transition(const struct _lv_obj_t * obj, uint32_t part) +static inline const lv_style_transition_dsc_t * lv_obj_get_style_transition(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSITION); return (const lv_style_transition_dsc_t *)v.ptr; } -static inline lv_blend_mode_t lv_obj_get_style_blend_mode(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_blend_mode_t lv_obj_get_style_blend_mode(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BLEND_MODE); return (lv_blend_mode_t)v.num; } -static inline uint16_t lv_obj_get_style_layout(const struct _lv_obj_t * obj, uint32_t part) +static inline uint16_t lv_obj_get_style_layout(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LAYOUT); return (uint16_t)v.num; } -static inline lv_base_dir_t lv_obj_get_style_base_dir(const struct _lv_obj_t * obj, uint32_t part) +static inline lv_base_dir_t lv_obj_get_style_base_dir(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BASE_DIR); return (lv_base_dir_t)v.num; } -void lv_obj_set_style_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_min_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_max_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_min_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_max_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_align(struct _lv_obj_t * obj, lv_align_t value, lv_style_selector_t selector); -void lv_obj_set_style_transform_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_transform_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_translate_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_translate_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_transform_zoom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_transform_angle(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_transform_pivot_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_transform_pivot_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_pad_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_pad_bottom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_pad_left(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_pad_right(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_pad_row(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_pad_column(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_bg_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_bg_grad_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_bg_grad_dir(struct _lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector); -void lv_obj_set_style_bg_main_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_bg_grad_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_bg_grad(struct _lv_obj_t * obj, const lv_grad_dsc_t * value, lv_style_selector_t selector); -void lv_obj_set_style_bg_dither_mode(struct _lv_obj_t * obj, lv_dither_mode_t value, lv_style_selector_t selector); -void lv_obj_set_style_bg_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector); -void lv_obj_set_style_bg_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_bg_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_bg_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_bg_img_tiled(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); -void lv_obj_set_style_border_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_border_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_border_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_border_side(struct _lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector); -void lv_obj_set_style_border_post(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); -void lv_obj_set_style_outline_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_outline_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_outline_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_outline_pad(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_shadow_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_shadow_ofs_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_shadow_ofs_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_shadow_spread(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_shadow_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_line_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_line_dash_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); -void lv_obj_set_style_line_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); -void lv_obj_set_style_arc_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_arc_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector); -void lv_obj_set_style_text_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); -void lv_obj_set_style_text_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_text_font(struct _lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector); -void lv_obj_set_style_text_letter_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_text_line_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_text_decor(struct _lv_obj_t * obj, lv_text_decor_t value, lv_style_selector_t selector); -void lv_obj_set_style_text_align(struct _lv_obj_t * obj, lv_text_align_t value, lv_style_selector_t selector); -void lv_obj_set_style_radius(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_clip_corner(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector); -void lv_obj_set_style_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_opa_layered(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector); -void lv_obj_set_style_color_filter_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_anim(struct _lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector); -void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector); -void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector); -void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector); -void lv_obj_set_style_blend_mode(struct _lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector); -void lv_obj_set_style_layout(struct _lv_obj_t * obj, uint16_t value, lv_style_selector_t selector); -void lv_obj_set_style_base_dir(struct _lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector); +#if LV_USE_FLEX + +static inline lv_flex_flow_t lv_obj_get_style_flex_flow(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_FLOW); + return (lv_flex_flow_t)v.num; +} + +static inline lv_flex_align_t lv_obj_get_style_flex_main_place(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_MAIN_PLACE); + return (lv_flex_align_t)v.num; +} + +static inline lv_flex_align_t lv_obj_get_style_flex_cross_place(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_CROSS_PLACE); + return (lv_flex_align_t)v.num; +} + +static inline lv_flex_align_t lv_obj_get_style_flex_track_place(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_TRACK_PLACE); + return (lv_flex_align_t)v.num; +} + +static inline uint8_t lv_obj_get_style_flex_grow(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_GROW); + return (uint8_t)v.num; +} + +#endif /*LV_USE_FLEX*/ + +#if LV_USE_GRID + +static inline const int32_t * lv_obj_get_style_grid_column_dsc_array(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_COLUMN_DSC_ARRAY); + return (const int32_t *)v.ptr; +} + +static inline lv_grid_align_t lv_obj_get_style_grid_column_align(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_COLUMN_ALIGN); + return (lv_grid_align_t)v.num; +} + +static inline const int32_t * lv_obj_get_style_grid_row_dsc_array(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_ROW_DSC_ARRAY); + return (const int32_t *)v.ptr; +} + +static inline lv_grid_align_t lv_obj_get_style_grid_row_align(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_ROW_ALIGN); + return (lv_grid_align_t)v.num; +} + +static inline int32_t lv_obj_get_style_grid_cell_column_pos(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_COLUMN_POS); + return (int32_t)v.num; +} + +static inline lv_grid_align_t lv_obj_get_style_grid_cell_x_align(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_X_ALIGN); + return (lv_grid_align_t)v.num; +} + +static inline int32_t lv_obj_get_style_grid_cell_column_span(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_COLUMN_SPAN); + return (int32_t)v.num; +} + +static inline int32_t lv_obj_get_style_grid_cell_row_pos(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_ROW_POS); + return (int32_t)v.num; +} + +static inline lv_grid_align_t lv_obj_get_style_grid_cell_y_align(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_Y_ALIGN); + return (lv_grid_align_t)v.num; +} + +static inline int32_t lv_obj_get_style_grid_cell_row_span(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_ROW_SPAN); + return (int32_t)v.num; +} + +#endif /*LV_USE_GRID*/ + +void lv_obj_set_style_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_min_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_max_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_min_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_max_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_length(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_align(lv_obj_t * obj, lv_align_t value, lv_style_selector_t selector); +void lv_obj_set_style_transform_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_transform_height(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_translate_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_translate_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_transform_scale_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_transform_scale_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_transform_rotation(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_transform_pivot_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_transform_pivot_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_transform_skew_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_transform_skew_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_pad_top(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_pad_bottom(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_pad_left(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_pad_right(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_pad_row(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_pad_column(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_margin_top(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_margin_bottom(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_margin_left(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_margin_right(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_grad_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_grad_dir(lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_main_stop(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_grad_stop(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_main_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_grad_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_grad(lv_obj_t * obj, const lv_grad_dsc_t * value, lv_style_selector_t selector); +void lv_obj_set_style_bg_image_src(lv_obj_t * obj, const void * value, lv_style_selector_t selector); +void lv_obj_set_style_bg_image_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_image_recolor(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_image_recolor_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_bg_image_tiled(lv_obj_t * obj, bool value, lv_style_selector_t selector); +void lv_obj_set_style_border_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_border_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_border_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_border_side(lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector); +void lv_obj_set_style_border_post(lv_obj_t * obj, bool value, lv_style_selector_t selector); +void lv_obj_set_style_outline_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_outline_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_outline_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_outline_pad(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_shadow_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_shadow_offset_x(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_shadow_offset_y(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_shadow_spread(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_shadow_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_shadow_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_image_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_image_recolor(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_image_recolor_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_line_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_line_dash_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_line_dash_gap(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_line_rounded(lv_obj_t * obj, bool value, lv_style_selector_t selector); +void lv_obj_set_style_line_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_line_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_arc_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_arc_rounded(lv_obj_t * obj, bool value, lv_style_selector_t selector); +void lv_obj_set_style_arc_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_arc_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_arc_image_src(lv_obj_t * obj, const void * value, lv_style_selector_t selector); +void lv_obj_set_style_text_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector); +void lv_obj_set_style_text_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_text_font(lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector); +void lv_obj_set_style_text_letter_space(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_text_line_space(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_text_decor(lv_obj_t * obj, lv_text_decor_t value, lv_style_selector_t selector); +void lv_obj_set_style_text_align(lv_obj_t * obj, lv_text_align_t value, lv_style_selector_t selector); +void lv_obj_set_style_radius(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +void lv_obj_set_style_clip_corner(lv_obj_t * obj, bool value, lv_style_selector_t selector); +void lv_obj_set_style_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_opa_layered(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_color_filter_dsc(lv_obj_t * obj, const lv_color_filter_dsc_t * value, + lv_style_selector_t selector); +void lv_obj_set_style_color_filter_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); +void lv_obj_set_style_anim(lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector); +void lv_obj_set_style_anim_duration(lv_obj_t * obj, uint32_t value, lv_style_selector_t selector); +void lv_obj_set_style_transition(lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector); +void lv_obj_set_style_blend_mode(lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector); +void lv_obj_set_style_layout(lv_obj_t * obj, uint16_t value, lv_style_selector_t selector); +void lv_obj_set_style_base_dir(lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector); +#if LV_USE_FLEX + + void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector); + void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector); + void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector); + void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector); + void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector); +#endif /*LV_USE_FLEX*/ + +#if LV_USE_GRID + + void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const int32_t * value, lv_style_selector_t selector); + void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector); + void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const int32_t * value, lv_style_selector_t selector); + void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector); + void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); + void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector); + void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); + void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); + void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector); + void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, int32_t value, lv_style_selector_t selector); +#endif /*LV_USE_GRID*/ + +#endif /* LV_OBJ_STYLE_GEN_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.c b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.c index 5ae629e75..2aa07d8d9 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.c @@ -9,15 +9,21 @@ #include #include "lv_obj.h" -#include "lv_indev.h" +#include "../indev/lv_indev.h" +#include "../indev/lv_indev_private.h" +#include "../display/lv_display.h" +#include "../display/lv_display_private.h" #include "../misc/lv_anim.h" -#include "../misc/lv_gc.h" #include "../misc/lv_async.h" +#include "../core/lv_global.h" /********************* * DEFINES *********************/ #define MY_CLASS &lv_obj_class +#define disp_ll_p &(LV_GLOBAL_DEFAULT()->disp_ll) + +#define OBJ_DUMP_STRING_LEN 128 /********************** * TYPEDEFS @@ -26,9 +32,11 @@ /********************** * STATIC PROTOTYPES **********************/ -static void lv_obj_del_async_cb(void * obj); -static void obj_del_core(lv_obj_t * obj); +static void lv_obj_delete_async_cb(void * obj); +static void obj_delete_core(lv_obj_t * obj); static lv_obj_tree_walk_res_t walk_core(lv_obj_t * obj, lv_obj_tree_walk_cb_t cb, void * user_data); +static lv_obj_tree_walk_res_t dump_tree_core(lv_obj_t * obj, int32_t depth); +static lv_obj_t * lv_obj_get_first_not_deleting_child(lv_obj_t * obj); /********************** * STATIC VARIABLES @@ -42,33 +50,36 @@ static lv_obj_tree_walk_res_t walk_core(lv_obj_t * obj, lv_obj_tree_walk_cb_t cb * GLOBAL FUNCTIONS **********************/ -void lv_obj_del(lv_obj_t * obj) +void lv_obj_delete(lv_obj_t * obj) { + if(obj->is_deleting) + return; + LV_LOG_TRACE("begin (delete %p)", (void *)obj); LV_ASSERT_OBJ(obj, MY_CLASS); lv_obj_invalidate(obj); lv_obj_t * par = lv_obj_get_parent(obj); - lv_disp_t * disp = NULL; - bool act_scr_del = false; + lv_display_t * disp = NULL; + bool act_screen_del = false; if(par == NULL) { - disp = lv_obj_get_disp(obj); + disp = lv_obj_get_display(obj); if(!disp) return; /*Shouldn't happen*/ - if(disp->act_scr == obj) act_scr_del = true; + if(disp->act_scr == obj) act_screen_del = true; } - obj_del_core(obj); + obj_delete_core(obj); /*Call the ancestor's event handler to the parent to notify it about the child delete*/ - if(par) { + if(par && !par->is_deleting) { lv_obj_scrollbar_invalidate(par); - lv_event_send(par, LV_EVENT_CHILD_CHANGED, NULL); - lv_event_send(par, LV_EVENT_CHILD_DELETED, NULL); + lv_obj_send_event(par, LV_EVENT_CHILD_CHANGED, NULL); + lv_obj_send_event(par, LV_EVENT_CHILD_DELETED, NULL); } /*Handle if the active screen was deleted*/ - if(act_scr_del) { + if(act_screen_del) { LV_LOG_WARN("the active screen was deleted"); disp->act_scr = NULL; } @@ -79,15 +90,16 @@ void lv_obj_del(lv_obj_t * obj) void lv_obj_clean(lv_obj_t * obj) { - LV_LOG_TRACE("begin (delete %p)", (void *)obj); + LV_LOG_TRACE("begin (clean %p)", (void *)obj); LV_ASSERT_OBJ(obj, MY_CLASS); lv_obj_invalidate(obj); - lv_obj_t * child = lv_obj_get_child(obj, 0); + uint32_t cnt = lv_obj_get_child_count(obj); + lv_obj_t * child = lv_obj_get_first_not_deleting_child(obj); while(child) { - obj_del_core(child); - child = lv_obj_get_child(obj, 0); + obj_delete_core(child); + child = lv_obj_get_first_not_deleting_child(obj); } /*Just to remove scroll animations if any*/ lv_obj_scroll_to(obj, 0, 0, LV_ANIM_OFF); @@ -96,32 +108,37 @@ void lv_obj_clean(lv_obj_t * obj) obj->spec_attr->scroll.y = 0; } + if(lv_obj_get_child_count(obj) < cnt) { + lv_obj_send_event(obj, LV_EVENT_CHILD_CHANGED, NULL); + lv_obj_send_event(obj, LV_EVENT_CHILD_DELETED, NULL); + } + LV_ASSERT_MEM_INTEGRITY(); - LV_LOG_TRACE("finished (delete %p)", (void *)obj); + LV_LOG_TRACE("finished (clean %p)", (void *)obj); } -void lv_obj_del_delayed(lv_obj_t * obj, uint32_t delay_ms) +void lv_obj_delete_delayed(lv_obj_t * obj, uint32_t delay_ms) { lv_anim_t a; lv_anim_init(&a); lv_anim_set_var(&a, obj); lv_anim_set_exec_cb(&a, NULL); - lv_anim_set_time(&a, 1); + lv_anim_set_duration(&a, 1); lv_anim_set_delay(&a, delay_ms); - lv_anim_set_ready_cb(&a, lv_obj_del_anim_ready_cb); + lv_anim_set_completed_cb(&a, lv_obj_delete_anim_completed_cb); lv_anim_start(&a); } -void lv_obj_del_anim_ready_cb(lv_anim_t * a) +void lv_obj_delete_anim_completed_cb(lv_anim_t * a) { - lv_obj_del(a->var); + lv_obj_delete(a->var); } -void lv_obj_del_async(lv_obj_t * obj) +void lv_obj_delete_async(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_async_call(lv_obj_del_async_cb, obj); + lv_async_call(lv_obj_delete_async_cb, obj); } void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent) @@ -146,35 +163,35 @@ void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent) lv_obj_t * old_parent = obj->parent; /*Remove the object from the old parent's child list*/ int32_t i; - for(i = lv_obj_get_index(obj); i <= (int32_t)lv_obj_get_child_cnt(old_parent) - 2; i++) { + for(i = lv_obj_get_index(obj); i <= (int32_t)lv_obj_get_child_count(old_parent) - 2; i++) { old_parent->spec_attr->children[i] = old_parent->spec_attr->children[i + 1]; } old_parent->spec_attr->child_cnt--; if(old_parent->spec_attr->child_cnt) { - old_parent->spec_attr->children = lv_mem_realloc(old_parent->spec_attr->children, - old_parent->spec_attr->child_cnt * (sizeof(lv_obj_t *))); + old_parent->spec_attr->children = lv_realloc(old_parent->spec_attr->children, + old_parent->spec_attr->child_cnt * (sizeof(lv_obj_t *))); } else { - lv_mem_free(old_parent->spec_attr->children); + lv_free(old_parent->spec_attr->children); old_parent->spec_attr->children = NULL; } /*Add the child to the new parent as the last (newest child)*/ parent->spec_attr->child_cnt++; - parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children, - parent->spec_attr->child_cnt * (sizeof(lv_obj_t *))); - parent->spec_attr->children[lv_obj_get_child_cnt(parent) - 1] = obj; + parent->spec_attr->children = lv_realloc(parent->spec_attr->children, + parent->spec_attr->child_cnt * (sizeof(lv_obj_t *))); + parent->spec_attr->children[lv_obj_get_child_count(parent) - 1] = obj; obj->parent = parent; /*Notify the original parent because one of its children is lost*/ lv_obj_scrollbar_invalidate(old_parent); - lv_event_send(old_parent, LV_EVENT_CHILD_CHANGED, obj); - lv_event_send(old_parent, LV_EVENT_CHILD_DELETED, NULL); + lv_obj_send_event(old_parent, LV_EVENT_CHILD_CHANGED, obj); + lv_obj_send_event(old_parent, LV_EVENT_CHILD_DELETED, NULL); /*Notify the new parent about the child*/ - lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj); - lv_event_send(parent, LV_EVENT_CHILD_CREATED, NULL); + lv_obj_send_event(parent, LV_EVENT_CHILD_CHANGED, obj); + lv_obj_send_event(parent, LV_EVENT_CHILD_CREATED, NULL); lv_obj_mark_layout_as_dirty(obj); @@ -185,17 +202,31 @@ void lv_obj_move_to_index(lv_obj_t * obj, int32_t index) { LV_ASSERT_OBJ(obj, MY_CLASS); - if(index < 0) { - index = lv_obj_get_child_cnt(lv_obj_get_parent(obj)) + index; + /* Check parent validity */ + lv_obj_t * parent = lv_obj_get_parent(obj); + if(!parent) { + LV_LOG_WARN("parent is NULL"); + return; } + const uint32_t parent_child_count = lv_obj_get_child_count(parent); + /* old_index only can be 0 or greater, this point can not be reached if the parent is not null */ const int32_t old_index = lv_obj_get_index(obj); + LV_ASSERT(0 <= old_index); - lv_obj_t * parent = lv_obj_get_parent(obj); + if(index < 0) { + index += parent_child_count; + } - if(index < 0) return; - if(index >= (int32_t) lv_obj_get_child_cnt(parent)) return; - if(index == old_index) return; + /* Index was negative and the absolute value is greater than parent child count */ + if((index < 0) + /* Index is same or bigger than parent child count */ + || (index >= (int32_t) parent_child_count) + /* If both previous and new index are the same */ + || (index == old_index)) { + + return; + } int32_t i = old_index; if(index < old_index) { @@ -212,7 +243,7 @@ void lv_obj_move_to_index(lv_obj_t * obj, int32_t index) } parent->spec_attr->children[index] = obj; - lv_event_send(parent, LV_EVENT_CHILD_CHANGED, NULL); + lv_obj_send_event(parent, LV_EVENT_CHILD_CHANGED, NULL); lv_obj_invalidate(parent); } @@ -227,16 +258,19 @@ void lv_obj_swap(lv_obj_t * obj1, lv_obj_t * obj2) uint_fast32_t index1 = lv_obj_get_index(obj1); uint_fast32_t index2 = lv_obj_get_index(obj2); - lv_event_send(parent2, LV_EVENT_CHILD_DELETED, obj2); - lv_event_send(parent, LV_EVENT_CHILD_DELETED, obj1); + lv_obj_send_event(parent2, LV_EVENT_CHILD_DELETED, obj2); + lv_obj_send_event(parent, LV_EVENT_CHILD_DELETED, obj1); parent->spec_attr->children[index1] = obj2; - parent2->spec_attr->children[index2] = obj1; + obj2->parent = parent; - lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj2); - lv_event_send(parent, LV_EVENT_CHILD_CREATED, obj2); - lv_event_send(parent2, LV_EVENT_CHILD_CHANGED, obj1); - lv_event_send(parent2, LV_EVENT_CHILD_CREATED, obj1); + parent2->spec_attr->children[index2] = obj1; + obj1->parent = parent2; + + lv_obj_send_event(parent, LV_EVENT_CHILD_CHANGED, obj2); + lv_obj_send_event(parent, LV_EVENT_CHILD_CREATED, obj2); + lv_obj_send_event(parent2, LV_EVENT_CHILD_CHANGED, obj1); + lv_obj_send_event(parent2, LV_EVENT_CHILD_CREATED, obj1); lv_obj_invalidate(parent); @@ -261,7 +295,7 @@ lv_obj_t * lv_obj_get_screen(const lv_obj_t * obj) return (lv_obj_t *)act_par; } -lv_disp_t * lv_obj_get_disp(const lv_obj_t * obj) +lv_display_t * lv_obj_get_display(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -270,8 +304,9 @@ lv_disp_t * lv_obj_get_disp(const lv_obj_t * obj) if(obj->parent == NULL) scr = obj; /*`obj` is a screen*/ else scr = lv_obj_get_screen(obj); /*get the screen of `obj`*/ - lv_disp_t * d; - _LV_LL_READ(&LV_GC_ROOT(_lv_disp_ll), d) { + lv_display_t * d; + lv_ll_t * disp_head = disp_ll_p; + _LV_LL_READ(disp_head, d) { uint32_t i; for(i = 0; i < d->screen_cnt; i++) { if(d->screens[i] == scr) return d; @@ -290,46 +325,130 @@ lv_obj_t * lv_obj_get_parent(const lv_obj_t * obj) return obj->parent; } -lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, int32_t id) +lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, int32_t idx) { LV_ASSERT_OBJ(obj, MY_CLASS); if(obj->spec_attr == NULL) return NULL; uint32_t idu; - if(id < 0) { - id = obj->spec_attr->child_cnt + id; - if(id < 0) return NULL; - idu = (uint32_t) id; + if(idx < 0) { + idx = obj->spec_attr->child_cnt + idx; + if(idx < 0) return NULL; + idu = (uint32_t) idx; } else { - idu = id; + idu = idx; } if(idu >= obj->spec_attr->child_cnt) return NULL; - else return obj->spec_attr->children[id]; + else return obj->spec_attr->children[idx]; } -uint32_t lv_obj_get_child_cnt(const lv_obj_t * obj) +lv_obj_t * lv_obj_get_child_by_type(const lv_obj_t * obj, int32_t idx, const lv_obj_class_t * class_p) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + if(obj->spec_attr == NULL) return NULL; + + int32_t i; + int32_t cnt = (int32_t)obj->spec_attr->child_cnt; + if(idx >= 0) { + for(i = 0; i < cnt; i++) { + if(obj->spec_attr->children[i]->class_p == class_p) { + if(idx == 0) return obj->spec_attr->children[i]; + else idx--; + } + } + } + else { + idx++; /*-1 means the first child*/ + for(i = cnt - 1; i >= 0; i--) { + if(obj->spec_attr->children[i]->class_p == class_p) { + if(idx == 0) return obj->spec_attr->children[i]; + else idx++; + } + } + } + return NULL; +} + +lv_obj_t * lv_obj_get_sibling(const lv_obj_t * obj, int32_t idx) +{ + lv_obj_t * parent = lv_obj_get_parent(obj); + int32_t sibling_idx = (int32_t)lv_obj_get_index(obj) + idx; + if(sibling_idx < 0) return NULL; + + return lv_obj_get_child(parent, sibling_idx); +} + +lv_obj_t * lv_obj_get_sibling_by_type(const lv_obj_t * obj, int32_t idx, const lv_obj_class_t * class_p) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_obj_t * parent = lv_obj_get_parent(obj); + int32_t sibling_idx = (int32_t)lv_obj_get_index_by_type(obj, class_p) + idx; + if(sibling_idx < 0) return NULL; + + return lv_obj_get_child(parent, sibling_idx); +} + +uint32_t lv_obj_get_child_count(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); if(obj->spec_attr == NULL) return 0; return obj->spec_attr->child_cnt; } -uint32_t lv_obj_get_index(const lv_obj_t * obj) +uint32_t lv_obj_get_child_count_by_type(const lv_obj_t * obj, const lv_obj_class_t * class_p) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + if(obj->spec_attr == NULL) return 0; + + uint32_t i; + uint32_t cnt = 0; + for(i = 0; i < obj->spec_attr->child_cnt; i++) { + if(obj->spec_attr->children[i]->class_p == class_p) cnt++; + } + return cnt; +} + +int32_t lv_obj_get_index(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_obj_t * parent = lv_obj_get_parent(obj); - if(parent == NULL) return 0; + if(parent == NULL) return -1; - uint32_t i = 0; - for(i = 0; i < lv_obj_get_child_cnt(parent); i++) { - if(lv_obj_get_child(parent, i) == obj) return i; + int32_t i = 0; + for(i = 0; i < parent->spec_attr->child_cnt; i++) { + if(parent->spec_attr->children[i] == obj) return i; } - return 0xFFFFFFFF; /*Shouldn't happen*/ + /*Shouldn't reach this point*/ + LV_ASSERT(0); + return -1; +} + +int32_t lv_obj_get_index_by_type(const lv_obj_t * obj, const lv_obj_class_t * class_p) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_obj_t * parent = lv_obj_get_parent(obj); + if(parent == NULL) return 0xFFFFFFFF; + + uint32_t i = 0; + uint32_t idx = 0; + for(i = 0; i < parent->spec_attr->child_cnt; i++) { + lv_obj_t * child = parent->spec_attr->children[i]; + if(child->class_p == class_p) { + if(child == obj) return idx; + idx++; + } + } + + /*Can happen if there was no children with the given type*/ + return -1; } void lv_obj_tree_walk(lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data) @@ -337,29 +456,55 @@ void lv_obj_tree_walk(lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * use walk_core(start_obj, cb, user_data); } +void lv_obj_dump_tree(lv_obj_t * start_obj) +{ + if(start_obj == NULL) { + lv_display_t * disp = lv_display_get_next(NULL); + while(disp) { + uint32_t i; + for(i = 0; i < disp->screen_cnt; i++) { + dump_tree_core(disp->screens[i], 0); + } + disp = lv_display_get_next(disp); + } + } + else { + dump_tree_core(start_obj, 0); + } +} + /********************** * STATIC FUNCTIONS **********************/ -static void lv_obj_del_async_cb(void * obj) +static void lv_obj_delete_async_cb(void * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_obj_del(obj); + lv_obj_delete(obj); } -static void obj_del_core(lv_obj_t * obj) +static void obj_delete_core(lv_obj_t * obj) { - /*Let the user free the resources used in `LV_EVENT_DELETE`*/ - lv_res_t res = lv_event_send(obj, LV_EVENT_DELETE, NULL); - if(res == LV_RES_INV) return; + if(obj->is_deleting) + return; - obj->being_deleted = 1; + obj->is_deleting = true; + + /*Let the user free the resources used in `LV_EVENT_DELETE`*/ + lv_result_t res = lv_obj_send_event(obj, LV_EVENT_DELETE, NULL); + if(res == LV_RESULT_INVALID) { + obj->is_deleting = false; + return; + } + + /*Clean registered event_cb*/ + if(obj->spec_attr) lv_event_remove_all(&(obj->spec_attr->event_list)); /*Recursively delete the children*/ lv_obj_t * child = lv_obj_get_child(obj, 0); while(child) { - obj_del_core(child); + obj_delete_core(child); child = lv_obj_get_child(obj, 0); } @@ -368,25 +513,34 @@ static void obj_del_core(lv_obj_t * obj) /*Reset all input devices if the object to delete is used*/ lv_indev_t * indev = lv_indev_get_next(NULL); while(indev) { - if(indev->proc.types.pointer.act_obj == obj || indev->proc.types.pointer.last_obj == obj) { - lv_indev_reset(indev, obj); - } - if(indev->proc.types.pointer.last_pressed == obj) { - indev->proc.types.pointer.last_pressed = NULL; + lv_indev_type_t indev_type = lv_indev_get_type(indev); + if(indev_type == LV_INDEV_TYPE_POINTER || indev_type == LV_INDEV_TYPE_BUTTON) { + if(indev->pointer.act_obj == obj || indev->pointer.last_obj == obj || indev->pointer.scroll_obj == obj) { + lv_indev_reset(indev, obj); + } + if(indev->pointer.last_pressed == obj) { + indev->pointer.last_pressed = NULL; + } } - if(indev->group == group && obj == lv_indev_get_obj_act()) { + if(indev->group == group && obj == lv_indev_get_active_obj()) { lv_indev_reset(indev, obj); } indev = lv_indev_get_next(indev); } + /*Delete all pending async del-s*/ + lv_result_t async_cancel_res = LV_RESULT_OK; + while(async_cancel_res == LV_RESULT_OK) { + async_cancel_res = lv_async_call_cancel(lv_obj_delete_async_cb, obj); + } + /*All children deleted. Now clean up the object specific data*/ _lv_obj_destruct(obj); /*Remove the screen for the screen list*/ if(obj->parent == NULL) { - lv_disp_t * disp = lv_obj_get_disp(obj); + lv_display_t * disp = lv_obj_get_display(obj); uint32_t i; /*Find the screen in the list*/ for(i = 0; i < disp->screen_cnt; i++) { @@ -398,37 +552,36 @@ static void obj_del_core(lv_obj_t * obj) disp->screens[i] = disp->screens[i + 1]; } disp->screen_cnt--; - disp->screens = lv_mem_realloc(disp->screens, disp->screen_cnt * sizeof(lv_obj_t *)); + disp->screens = lv_realloc(disp->screens, disp->screen_cnt * sizeof(lv_obj_t *)); } /*Remove the object from the child list of its parent*/ else { - uint32_t id = lv_obj_get_index(obj); - uint32_t i; + int32_t id = lv_obj_get_index(obj); + uint16_t i; for(i = id; i < obj->parent->spec_attr->child_cnt - 1; i++) { obj->parent->spec_attr->children[i] = obj->parent->spec_attr->children[i + 1]; } obj->parent->spec_attr->child_cnt--; - obj->parent->spec_attr->children = lv_mem_realloc(obj->parent->spec_attr->children, - obj->parent->spec_attr->child_cnt * sizeof(lv_obj_t *)); + obj->parent->spec_attr->children = lv_realloc(obj->parent->spec_attr->children, + obj->parent->spec_attr->child_cnt * sizeof(lv_obj_t *)); } /*Free the object itself*/ - lv_mem_free(obj); + lv_free(obj); } - static lv_obj_tree_walk_res_t walk_core(lv_obj_t * obj, lv_obj_tree_walk_cb_t cb, void * user_data) { lv_obj_tree_walk_res_t res = LV_OBJ_TREE_WALK_NEXT; if(obj == NULL) { - lv_disp_t * disp = lv_disp_get_next(NULL); + lv_display_t * disp = lv_display_get_next(NULL); while(disp) { uint32_t i; for(i = 0; i < disp->screen_cnt; i++) { walk_core(disp->screens[i], cb, user_data); } - disp = lv_disp_get_next(disp); + disp = lv_display_get_next(disp); } return LV_OBJ_TREE_WALK_END; /*The value doesn't matter as it wasn't called recursively*/ } @@ -439,10 +592,59 @@ static lv_obj_tree_walk_res_t walk_core(lv_obj_t * obj, lv_obj_tree_walk_cb_t cb if(res != LV_OBJ_TREE_WALK_SKIP_CHILDREN) { uint32_t i; - for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + for(i = 0; i < lv_obj_get_child_count(obj); i++) { res = walk_core(lv_obj_get_child(obj, i), cb, user_data); if(res == LV_OBJ_TREE_WALK_END) return LV_OBJ_TREE_WALK_END; } } return LV_OBJ_TREE_WALK_NEXT; } + +static lv_obj_tree_walk_res_t dump_tree_core(lv_obj_t * obj, int32_t depth) +{ + lv_obj_tree_walk_res_t res; + +#if LV_USE_LOG + const char * id; + +#if LV_USE_OBJ_ID + char buf[OBJ_DUMP_STRING_LEN]; + id = lv_obj_stringify_id(obj, buf, sizeof(buf)); + if(id == NULL) id = "obj0"; +#else + id = "obj0"; +#endif + + /*id of `obj0` is an invalid id for builtin id*/ + LV_LOG_USER("parent:%p, obj:%p, id:%s;", (void *)(obj ? obj->parent : NULL), (void *)obj, id); +#endif /*LV_USE_LOG*/ + + if(obj && obj->spec_attr && obj->spec_attr->child_cnt) { + for(uint32_t i = 0; i < obj->spec_attr->child_cnt; i++) { + res = dump_tree_core(lv_obj_get_child(obj, i), depth + 1); + if(res == LV_OBJ_TREE_WALK_END) + break; + } + return LV_OBJ_TREE_WALK_NEXT; + } + else { + return LV_OBJ_TREE_WALK_END; + } +} + +static lv_obj_t * lv_obj_get_first_not_deleting_child(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + if(obj->spec_attr == NULL) return NULL; + + int32_t i; + int32_t cnt = (int32_t)obj->spec_attr->child_cnt; + for(i = 0; i < cnt; i++) { + if(!obj->spec_attr->children[i]->is_deleting) { + return obj->spec_attr->children[i]; + } + } + + return NULL; +} diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.h b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.h index bee9e1604..c500c7956 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.h @@ -15,26 +15,25 @@ extern "C" { *********************/ #include #include +#include "../misc/lv_types.h" +#include "../misc/lv_anim.h" +#include "../display/lv_display.h" /********************* * DEFINES *********************/ - /********************** * TYPEDEFS **********************/ -struct _lv_obj_t; -struct _lv_obj_class_t; - typedef enum { LV_OBJ_TREE_WALK_NEXT, LV_OBJ_TREE_WALK_SKIP_CHILDREN, LV_OBJ_TREE_WALK_END, } lv_obj_tree_walk_res_t; -typedef lv_obj_tree_walk_res_t (*lv_obj_tree_walk_cb_t)(struct _lv_obj_t *, void *); +typedef lv_obj_tree_walk_res_t (*lv_obj_tree_walk_cb_t)(lv_obj_t *, void *); /********************** * GLOBAL PROTOTYPES @@ -46,7 +45,7 @@ typedef lv_obj_tree_walk_res_t (*lv_obj_tree_walk_cb_t)(struct _lv_obj_t *, void * Send `LV_EVENT_DELETED` to deleted objects. * @param obj pointer to an object */ -void lv_obj_del(struct _lv_obj_t * obj); +void lv_obj_delete(lv_obj_t * obj); /** * Delete all children of an object. @@ -54,20 +53,20 @@ void lv_obj_del(struct _lv_obj_t * obj); * Send `LV_EVENT_DELETED` to deleted objects. * @param obj pointer to an object */ -void lv_obj_clean(struct _lv_obj_t * obj); +void lv_obj_clean(lv_obj_t * obj); /** * Delete an object after some delay * @param obj pointer to an object * @param delay_ms time to wait before delete in milliseconds */ -void lv_obj_del_delayed(struct _lv_obj_t * obj, uint32_t delay_ms); +void lv_obj_delete_delayed(lv_obj_t * obj, uint32_t delay_ms); /** * A function to be easily used in animation ready callback to delete an object when the animation is ready * @param a pointer to the animation */ -void lv_obj_del_anim_ready_cb(lv_anim_t * a); +void lv_obj_delete_anim_completed_cb(lv_anim_t * a); /** * Helper function for asynchronously deleting objects. @@ -75,7 +74,7 @@ void lv_obj_del_anim_ready_cb(lv_anim_t * a); * @param obj object to delete * @see lv_async_call */ -void lv_obj_del_async(struct _lv_obj_t * obj); +void lv_obj_delete_async(lv_obj_t * obj); /** * Move the parent of an object. The relative coordinates will be kept. @@ -83,7 +82,7 @@ void lv_obj_del_async(struct _lv_obj_t * obj); * @param obj pointer to an object whose parent needs to be changed * @param parent pointer to the new parent */ -void lv_obj_set_parent(struct _lv_obj_t * obj, struct _lv_obj_t * parent); +void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent); /** * Swap the positions of two objects. @@ -91,7 +90,7 @@ void lv_obj_set_parent(struct _lv_obj_t * obj, struct _lv_obj_t * parent); * @param obj1 pointer to the first object * @param obj2 pointer to the second object */ -void lv_obj_swap(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2); +void lv_obj_swap(lv_obj_t * obj1, lv_obj_t * obj2); /** * moves the object to the given index in its parent. @@ -101,33 +100,33 @@ void lv_obj_swap(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2); * @note to move to the background: lv_obj_move_to_index(obj, 0) * @note to move forward (up): lv_obj_move_to_index(obj, lv_obj_get_index(obj) - 1) */ -void lv_obj_move_to_index(struct _lv_obj_t * obj, int32_t index); +void lv_obj_move_to_index(lv_obj_t * obj, int32_t index); /** * Get the screen of an object * @param obj pointer to an object * @return pointer to the object's screen */ -struct _lv_obj_t * lv_obj_get_screen(const struct _lv_obj_t * obj); +lv_obj_t * lv_obj_get_screen(const lv_obj_t * obj); /** * Get the display of the object * @param obj pointer to an object * @return pointer to the object's display */ -lv_disp_t * lv_obj_get_disp(const struct _lv_obj_t * obj); +lv_display_t * lv_obj_get_display(const lv_obj_t * obj); /** * Get the parent of an object * @param obj pointer to an object * @return the parent of the object. (NULL if `obj` was a screen) */ -struct _lv_obj_t * lv_obj_get_parent(const struct _lv_obj_t * obj); +lv_obj_t * lv_obj_get_parent(const lv_obj_t * obj); /** * Get the child of an object by the child's index. * @param obj pointer to an object whose child should be get - * @param id the index of the child. + * @param idx the index of the child. * 0: the oldest (firstly created) child * 1: the second oldest * child count-1: the youngest @@ -135,22 +134,85 @@ struct _lv_obj_t * lv_obj_get_parent(const struct _lv_obj_t * obj); * -2: the second youngest * @return pointer to the child or NULL if the index was invalid */ -struct _lv_obj_t * lv_obj_get_child(const struct _lv_obj_t * obj, int32_t id); +lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, int32_t idx); + +/** + * Get the child of an object by the child's index. Consider the children only with a given type. + * @param obj pointer to an object whose child should be get + * @param idx the index of the child. + * 0: the oldest (firstly created) child + * 1: the second oldest + * child count-1: the youngest + * -1: the youngest + * -2: the second youngest + * @param class_p the type of the children to check + * @return pointer to the child or NULL if the index was invalid + */ +lv_obj_t * lv_obj_get_child_by_type(const lv_obj_t * obj, int32_t idx, + const lv_obj_class_t * class_p); + +/** + * Return a sibling of an object + * @param obj pointer to an object whose sibling should be get + * @param idx 0: `obj` itself + * -1: the first older sibling + * -2: the next older sibling + * 1: the first younger sibling + * 2: the next younger sibling + * etc + * @return pointer to the requested sibling or NULL if there is no such sibling + */ +lv_obj_t * lv_obj_get_sibling(const lv_obj_t * obj, int32_t idx); + +/** + * Return a sibling of an object. Consider the siblings only with a given type. + * @param obj pointer to an object whose sibling should be get + * @param idx 0: `obj` itself + * -1: the first older sibling + * -2: the next older sibling + * 1: the first younger sibling + * 2: the next younger sibling + * etc + * @param class_p the type of the children to check + * @return pointer to the requested sibling or NULL if there is no such sibling + */ +lv_obj_t * lv_obj_get_sibling_by_type(const lv_obj_t * obj, int32_t idx, + const lv_obj_class_t * class_p); /** * Get the number of children * @param obj pointer to an object * @return the number of children */ -uint32_t lv_obj_get_child_cnt(const struct _lv_obj_t * obj); +uint32_t lv_obj_get_child_count(const lv_obj_t * obj); + +/** + * Get the number of children having a given type. + * @param obj pointer to an object + * @param class_p the type of the children to check + * @return the number of children + */ + +uint32_t lv_obj_get_child_count_by_type(const lv_obj_t * obj, const lv_obj_class_t * class_p); /** * Get the index of a child. * @param obj pointer to an object * @return the child index of the object. - * E.g. 0: the oldest (firstly created child) + * E.g. 0: the oldest (firstly created child). + * (-1 if child could not be found or no parent exists) */ -uint32_t lv_obj_get_index(const struct _lv_obj_t * obj); +int32_t lv_obj_get_index(const lv_obj_t * obj); + +/** + * Get the index of a child. Consider the children only with a given type. + * @param obj pointer to an object + * @param class_p the type of the children to check + * @return the child index of the object. + * E.g. 0: the oldest (firstly created child with the given class). + * (-1 if child could not be found or no parent exists) + */ +int32_t lv_obj_get_index_by_type(const lv_obj_t * obj, const lv_obj_class_t * class_p); /** * Iterate through all children of any object. @@ -158,13 +220,18 @@ uint32_t lv_obj_get_index(const struct _lv_obj_t * obj); * @param cb call this callback on the objects * @param user_data pointer to any user related data (will be passed to `cb`) */ -void lv_obj_tree_walk(struct _lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data); +void lv_obj_tree_walk(lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data); + +/** + * Iterate through all children of any object and print their ID. + * @param start_obj start integrating from this object + */ +void lv_obj_dump_tree(lv_obj_t * start_ob); /********************** * MACROS **********************/ - #ifdef __cplusplus } /*extern "C"*/ #endif diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_refr.c b/lib/libesp32_lvgl/lvgl/src/core/lv_refr.c index bfd27487a..5bedd063b 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_refr.c +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_refr.c @@ -8,45 +8,27 @@ *********************/ #include #include "lv_refr.h" -#include "lv_disp.h" -#include "../hal/lv_hal_tick.h" -#include "../hal/lv_hal_disp.h" +#include "../display/lv_display.h" +#include "../display/lv_display_private.h" +#include "../tick/lv_tick.h" #include "../misc/lv_timer.h" -#include "../misc/lv_mem.h" #include "../misc/lv_math.h" -#include "../misc/lv_gc.h" +#include "../misc/lv_profiler.h" #include "../draw/lv_draw.h" #include "../font/lv_font_fmt_txt.h" -#include "../extra/others/snapshot/lv_snapshot.h" - -#if LV_USE_PERF_MONITOR || LV_USE_MEM_MONITOR - #include "../widgets/lv_label.h" -#endif +#include "../stdlib/lv_string.h" +#include "lv_global.h" /********************* * DEFINES *********************/ +/*Display being refreshed*/ +#define disp_refr LV_GLOBAL_DEFAULT()->disp_refresh + /********************** * TYPEDEFS **********************/ -typedef struct { - uint32_t perf_last_time; - uint32_t elaps_sum; - uint32_t frame_cnt; - uint32_t fps_sum_cnt; - uint32_t fps_sum_all; -#if LV_USE_LABEL - lv_obj_t * perf_label; -#endif -} perf_monitor_t; - -typedef struct { - uint32_t mem_last_time; -#if LV_USE_LABEL - lv_obj_t * mem_label; -#endif -} mem_monitor_t; /********************** * STATIC PROTOTYPES @@ -55,42 +37,26 @@ static void lv_refr_join_area(void); static void refr_invalid_areas(void); static void refr_sync_areas(void); static void refr_area(const lv_area_t * area_p); -static void refr_area_part(lv_draw_ctx_t * draw_ctx); +static void refr_area_part(lv_layer_t * layer); static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj); -static void refr_obj_and_children(lv_draw_ctx_t * draw_ctx, lv_obj_t * top_obj); -static void refr_obj(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj); -static uint32_t get_max_row(lv_disp_t * disp, lv_coord_t area_w, lv_coord_t area_h); -static void draw_buf_flush(lv_disp_t * disp); -static void call_flush_cb(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p); - -#if LV_USE_PERF_MONITOR - static void perf_monitor_init(perf_monitor_t * perf_monitor); -#endif -#if LV_USE_MEM_MONITOR - static void mem_monitor_init(mem_monitor_t * mem_monitor); -#endif +static void refr_obj_and_children(lv_layer_t * layer, lv_obj_t * top_obj); +static void refr_obj(lv_layer_t * layer, lv_obj_t * obj); +static uint32_t get_max_row(lv_display_t * disp, int32_t area_w, int32_t area_h); +static void draw_buf_flush(lv_display_t * disp); +static void call_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map); +static void wait_for_flushing(lv_display_t * disp); /********************** * STATIC VARIABLES **********************/ -static uint32_t px_num; -static lv_disp_t * disp_refr; /*Display being refreshed*/ - -#if LV_USE_PERF_MONITOR - static perf_monitor_t perf_monitor; -#endif - -#if LV_USE_MEM_MONITOR - static mem_monitor_t mem_monitor; -#endif /********************** * MACROS **********************/ -#if LV_LOG_TRACE_DISP_REFR - #define REFR_TRACE(...) LV_LOG_TRACE(__VA_ARGS__) +#if LV_USE_LOG && LV_LOG_TRACE_DISP_REFR + #define LV_TRACE_REFR(...) LV_LOG_TRACE(__VA_ARGS__) #else - #define REFR_TRACE(...) + #define LV_TRACE_REFR(...) #endif /********************** @@ -102,117 +68,193 @@ static lv_disp_t * disp_refr; /*Display being refreshed*/ */ void _lv_refr_init(void) { -#if LV_USE_PERF_MONITOR - perf_monitor_init(&perf_monitor); -#endif -#if LV_USE_MEM_MONITOR - mem_monitor_init(&mem_monitor); -#endif } -void lv_refr_now(lv_disp_t * disp) +void _lv_refr_deinit(void) +{ +} + +void lv_refr_now(lv_display_t * disp) { lv_anim_refr_now(); if(disp) { - if(disp->refr_timer) _lv_disp_refr_timer(disp->refr_timer); + if(disp->refr_timer) _lv_display_refr_timer(disp->refr_timer); } else { - lv_disp_t * d; - d = lv_disp_get_next(NULL); + lv_display_t * d; + d = lv_display_get_next(NULL); while(d) { - if(d->refr_timer) _lv_disp_refr_timer(d->refr_timer); - d = lv_disp_get_next(d); + if(d->refr_timer) _lv_display_refr_timer(d->refr_timer); + d = lv_display_get_next(d); } } } -void lv_obj_redraw(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj) +void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj) { - const lv_area_t * clip_area_ori = draw_ctx->clip_area; + lv_area_t clip_area_ori = layer->_clip_area; lv_area_t clip_coords_for_obj; /*Truncate the clip area to `obj size + ext size` area*/ lv_area_t obj_coords_ext; lv_obj_get_coords(obj, &obj_coords_ext); - lv_coord_t ext_draw_size = _lv_obj_get_ext_draw_size(obj); + int32_t ext_draw_size = _lv_obj_get_ext_draw_size(obj); lv_area_increase(&obj_coords_ext, ext_draw_size, ext_draw_size); - bool com_clip_res = _lv_area_intersect(&clip_coords_for_obj, clip_area_ori, &obj_coords_ext); - /*If the object is visible on the current clip area OR has overflow visible draw it. - *With overflow visible drawing should happen to apply the masks which might affect children */ - bool should_draw = com_clip_res || lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE); - if(should_draw) { - draw_ctx->clip_area = &clip_coords_for_obj; - lv_event_send(obj, LV_EVENT_DRAW_MAIN_BEGIN, draw_ctx); - lv_event_send(obj, LV_EVENT_DRAW_MAIN, draw_ctx); - lv_event_send(obj, LV_EVENT_DRAW_MAIN_END, draw_ctx); + if(!_lv_area_intersect(&clip_coords_for_obj, &clip_area_ori, &obj_coords_ext)) return; + /*If the object is visible on the current clip area*/ + layer->_clip_area = clip_coords_for_obj; + + lv_obj_send_event(obj, LV_EVENT_DRAW_MAIN_BEGIN, layer); + lv_obj_send_event(obj, LV_EVENT_DRAW_MAIN, layer); + lv_obj_send_event(obj, LV_EVENT_DRAW_MAIN_END, layer); #if LV_USE_REFR_DEBUG - lv_color_t debug_color = lv_color_make(lv_rand(0, 0xFF), lv_rand(0, 0xFF), lv_rand(0, 0xFF)); - lv_draw_rect_dsc_t draw_dsc; - lv_draw_rect_dsc_init(&draw_dsc); - draw_dsc.bg_color.full = debug_color.full; - draw_dsc.bg_opa = LV_OPA_20; - draw_dsc.border_width = 1; - draw_dsc.border_opa = LV_OPA_30; - draw_dsc.border_color = debug_color; - lv_draw_rect(draw_ctx, &draw_dsc, &obj_coords_ext); + lv_color_t debug_color = lv_color_make(lv_rand(0, 0xFF), lv_rand(0, 0xFF), lv_rand(0, 0xFF)); + lv_draw_rect_dsc_t draw_dsc; + lv_draw_rect_dsc_init(&draw_dsc); + draw_dsc.bg_color = debug_color; + draw_dsc.bg_opa = LV_OPA_20; + draw_dsc.border_width = 1; + draw_dsc.border_opa = LV_OPA_30; + draw_dsc.border_color = debug_color; + lv_draw_rect(layer, &draw_dsc, &obj_coords_ext); #endif - } - /*With overflow visible keep the previous clip area to let the children visible out of this object too - *With not overflow visible limit the clip are to the object's coordinates to clip the children*/ - lv_area_t clip_coords_for_children; - bool refr_children = true; + const lv_area_t * obj_coords; if(lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) { - clip_coords_for_children = *clip_area_ori; + obj_coords = &obj_coords_ext; } else { - if(!_lv_area_intersect(&clip_coords_for_children, clip_area_ori, &obj->coords)) { - refr_children = false; - } + obj_coords = &obj->coords; + } + lv_area_t clip_coords_for_children; + bool refr_children = true; + if(!_lv_area_intersect(&clip_coords_for_children, &clip_area_ori, obj_coords)) { + refr_children = false; } if(refr_children) { - draw_ctx->clip_area = &clip_coords_for_children; uint32_t i; - uint32_t child_cnt = lv_obj_get_child_cnt(obj); - for(i = 0; i < child_cnt; i++) { - lv_obj_t * child = obj->spec_attr->children[i]; - refr_obj(draw_ctx, child); + uint32_t child_cnt = lv_obj_get_child_count(obj); + if(child_cnt == 0) { + /*If the object was visible on the clip area call the post draw events too*/ + layer->_clip_area = clip_coords_for_obj; + /*If all the children are redrawn make 'post draw' draw*/ + lv_obj_send_event(obj, LV_EVENT_DRAW_POST_BEGIN, layer); + lv_obj_send_event(obj, LV_EVENT_DRAW_POST, layer); + lv_obj_send_event(obj, LV_EVENT_DRAW_POST_END, layer); + } + else { + layer->_clip_area = clip_coords_for_children; + bool clip_corner = lv_obj_get_style_clip_corner(obj, LV_PART_MAIN); + + int32_t radius = 0; + if(clip_corner) { + radius = lv_obj_get_style_radius(obj, LV_PART_MAIN); + if(radius == 0) clip_corner = false; + } + + if(clip_corner == false) { + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; + refr_obj(layer, child); + } + + /*If the object was visible on the clip area call the post draw events too*/ + layer->_clip_area = clip_coords_for_obj; + /*If all the children are redrawn make 'post draw' draw*/ + lv_obj_send_event(obj, LV_EVENT_DRAW_POST_BEGIN, layer); + lv_obj_send_event(obj, LV_EVENT_DRAW_POST, layer); + lv_obj_send_event(obj, LV_EVENT_DRAW_POST_END, layer); + } + else { + lv_layer_t * layer_children; + lv_draw_mask_rect_dsc_t mask_draw_dsc; + lv_draw_mask_rect_dsc_init(&mask_draw_dsc); + mask_draw_dsc.radius = radius; + mask_draw_dsc.area = obj->coords; + + lv_draw_image_dsc_t img_draw_dsc; + lv_draw_image_dsc_init(&img_draw_dsc); + + int32_t short_side = LV_MIN(lv_area_get_width(&obj->coords), lv_area_get_height(&obj->coords)); + int32_t rout = LV_MIN(radius, short_side >> 1); + + lv_area_t bottom = obj->coords; + bottom.y1 = bottom.y2 - rout + 1; + if(_lv_area_intersect(&bottom, &bottom, &clip_area_ori)) { + layer_children = lv_draw_layer_create(layer, LV_COLOR_FORMAT_ARGB8888, &bottom); + + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; + refr_obj(layer_children, child); + } + + /*If all the children are redrawn send 'post draw' draw*/ + lv_obj_send_event(obj, LV_EVENT_DRAW_POST_BEGIN, layer_children); + lv_obj_send_event(obj, LV_EVENT_DRAW_POST, layer_children); + lv_obj_send_event(obj, LV_EVENT_DRAW_POST_END, layer_children); + + lv_draw_mask_rect(layer_children, &mask_draw_dsc); + + img_draw_dsc.src = layer_children; + lv_draw_layer(layer, &img_draw_dsc, &bottom); + } + + lv_area_t top = obj->coords; + top.y2 = top.y1 + rout - 1; + if(_lv_area_intersect(&top, &top, &clip_area_ori)) { + layer_children = lv_draw_layer_create(layer, LV_COLOR_FORMAT_ARGB8888, &top); + + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; + refr_obj(layer_children, child); + } + + /*If all the children are redrawn send 'post draw' draw*/ + lv_obj_send_event(obj, LV_EVENT_DRAW_POST_BEGIN, layer_children); + lv_obj_send_event(obj, LV_EVENT_DRAW_POST, layer_children); + lv_obj_send_event(obj, LV_EVENT_DRAW_POST_END, layer_children); + + lv_draw_mask_rect(layer_children, &mask_draw_dsc); + + img_draw_dsc.src = layer_children; + lv_draw_layer(layer, &img_draw_dsc, &top); + + } + + lv_area_t mid = obj->coords; + mid.y1 += rout; + mid.y2 -= rout; + if(_lv_area_intersect(&mid, &mid, &clip_area_ori)) { + layer->_clip_area = mid; + for(i = 0; i < child_cnt; i++) { + lv_obj_t * child = obj->spec_attr->children[i]; + refr_obj(layer, child); + } + + /*If all the children are redrawn make 'post draw' draw*/ + lv_obj_send_event(obj, LV_EVENT_DRAW_POST_BEGIN, layer); + lv_obj_send_event(obj, LV_EVENT_DRAW_POST, layer); + lv_obj_send_event(obj, LV_EVENT_DRAW_POST_END, layer); + + } + + } } } - /*If the object was visible on the clip area call the post draw events too*/ - if(should_draw) { - draw_ctx->clip_area = &clip_coords_for_obj; - - /*If all the children are redrawn make 'post draw' draw*/ - lv_event_send(obj, LV_EVENT_DRAW_POST_BEGIN, draw_ctx); - lv_event_send(obj, LV_EVENT_DRAW_POST, draw_ctx); - lv_event_send(obj, LV_EVENT_DRAW_POST_END, draw_ctx); - } - - draw_ctx->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } - -/** - * Invalidate an area on display to redraw it - * @param area_p pointer to area which should be invalidated (NULL: delete the invalidated areas) - * @param disp pointer to display where the area should be invalidated (NULL can be used if there is - * only one display) - */ -void _lv_inv_area(lv_disp_t * disp, const lv_area_t * area_p) +void _lv_inv_area(lv_display_t * disp, const lv_area_t * area_p) { - if(!disp) disp = lv_disp_get_default(); + if(!disp) disp = lv_display_get_default(); if(!disp) return; - if(!lv_disp_is_invalidation_enabled(disp)) return; + if(!lv_display_is_invalidation_enabled(disp)) return; - if(disp->rendering_in_progress) { - LV_LOG_ERROR("detected modifying dirty areas in render"); - return; - } + LV_ASSERT_MSG(!disp->rendering_in_progress, "Invalidate area is not allowed during rendering."); /*Clear the invalidate buffer if the parameter is NULL*/ if(area_p == NULL) { @@ -223,8 +265,8 @@ void _lv_inv_area(lv_disp_t * disp, const lv_area_t * area_p) lv_area_t scr_area; scr_area.x1 = 0; scr_area.y1 = 0; - scr_area.x2 = lv_disp_get_hor_res(disp) - 1; - scr_area.y2 = lv_disp_get_ver_res(disp) - 1; + scr_area.x2 = lv_display_get_horizontal_resolution(disp) - 1; + scr_area.y2 = lv_display_get_vertical_resolution(disp) - 1; lv_area_t com_area; bool suc; @@ -233,14 +275,15 @@ void _lv_inv_area(lv_disp_t * disp, const lv_area_t * area_p) if(suc == false) return; /*Out of the screen*/ /*If there were at least 1 invalid area in full refresh mode, redraw the whole screen*/ - if(disp->driver->full_refresh) { + if(disp->render_mode == LV_DISPLAY_RENDER_MODE_FULL) { disp->inv_areas[0] = scr_area; disp->inv_p = 1; - if(disp->refr_timer) lv_timer_resume(disp->refr_timer); + lv_display_send_event(disp, LV_EVENT_REFR_REQUEST, NULL); return; } - if(disp->driver->rounder_cb) disp->driver->rounder_cb(disp->driver, &com_area); + lv_result_t res = lv_display_send_event(disp, LV_EVENT_INVALIDATE_AREA, &com_area); + if(res != LV_RESULT_OK) return; /*Save only if this area is not in one of the saved areas*/ uint16_t i; @@ -249,225 +292,125 @@ void _lv_inv_area(lv_disp_t * disp, const lv_area_t * area_p) } /*Save the area*/ - if(disp->inv_p < LV_INV_BUF_SIZE) { - lv_area_copy(&disp->inv_areas[disp->inv_p], &com_area); - } - else { /*If no place for the area add the screen*/ + lv_area_t * tmp_area_p = &com_area; + if(disp->inv_p >= LV_INV_BUF_SIZE) { /*If no place for the area add the screen*/ disp->inv_p = 0; - lv_area_copy(&disp->inv_areas[disp->inv_p], &scr_area); + tmp_area_p = &scr_area; } + lv_area_copy(&disp->inv_areas[disp->inv_p], tmp_area_p); disp->inv_p++; - if(disp->refr_timer) lv_timer_resume(disp->refr_timer); + + lv_display_send_event(disp, LV_EVENT_REFR_REQUEST, NULL); } /** * Get the display which is being refreshed * @return the display being refreshed */ -lv_disp_t * _lv_refr_get_disp_refreshing(void) +lv_display_t * _lv_refr_get_disp_refreshing(void) { return disp_refr; } /** - * Set the display which is being refreshed. - * It shouldn't be used directly by the user. - * It can be used to trick the drawing functions about there is an active display. - * @param the display being refreshed + * Get the display which is being refreshed + * @return the display being refreshed */ -void _lv_refr_set_disp_refreshing(lv_disp_t * disp) +void _lv_refr_set_disp_refreshing(lv_display_t * disp) { disp_refr = disp; } -/** - * Called periodically to handle the refreshing - * @param tmr pointer to the timer itself - */ -void _lv_disp_refr_timer(lv_timer_t * tmr) +void _lv_display_refr_timer(lv_timer_t * tmr) { - REFR_TRACE("begin"); - - uint32_t start = lv_tick_get(); - volatile uint32_t elaps = 0; + LV_PROFILER_BEGIN; + LV_TRACE_REFR("begin"); if(tmr) { disp_refr = tmr->user_data; -#if LV_USE_PERF_MONITOR == 0 && LV_USE_MEM_MONITOR == 0 - /** - * Ensure the timer does not run again automatically. + /* Ensure the timer does not run again automatically. * This is done before refreshing in case refreshing invalidates something else. - */ + * However if the performance monitor is enabled keep the timer running to count the FPS.*/ +#if !(defined(LV_USE_PERF_MONITOR) && LV_USE_PERF_MONITOR) lv_timer_pause(tmr); #endif } else { - disp_refr = lv_disp_get_default(); + disp_refr = lv_display_get_default(); } + if(disp_refr == NULL) { + LV_LOG_WARN("No display registered"); + return; + } + + lv_draw_buf_t * buf_act = disp_refr->buf_act; + if(!(buf_act && buf_act->data && buf_act->data_size)) { + LV_LOG_WARN("No draw buffer"); + return; + } + + lv_display_send_event(disp_refr, LV_EVENT_REFR_START, NULL); + /*Refresh the screen's layout if required*/ + LV_PROFILER_BEGIN_TAG("layout"); lv_obj_update_layout(disp_refr->act_scr); if(disp_refr->prev_scr) lv_obj_update_layout(disp_refr->prev_scr); + lv_obj_update_layout(disp_refr->bottom_layer); lv_obj_update_layout(disp_refr->top_layer); lv_obj_update_layout(disp_refr->sys_layer); + LV_PROFILER_END_TAG("layout"); /*Do nothing if there is no active screen*/ if(disp_refr->act_scr == NULL) { disp_refr->inv_p = 0; LV_LOG_WARN("there is no active screen"); - REFR_TRACE("finished"); - return; + goto refr_finish; } lv_refr_join_area(); refr_sync_areas(); refr_invalid_areas(); + if(disp_refr->inv_p == 0) goto refr_finish; + /*If refresh happened ...*/ - if(disp_refr->inv_p != 0) { + lv_display_send_event(disp_refr, LV_EVENT_RENDER_READY, NULL); - /*Copy invalid areas for sync next refresh in double buffered direct mode*/ - if(disp_refr->driver->direct_mode && disp_refr->driver->draw_buf->buf2) { + if(!lv_display_is_double_buffered(disp_refr) || + disp_refr->render_mode != LV_DISPLAY_RENDER_MODE_DIRECT) goto refr_clean_up; - uint16_t i; - for(i = 0; i < disp_refr->inv_p; i++) { - if(disp_refr->inv_area_joined[i]) - continue; + /*With double buffered direct mode synchronize the rendered areas to the other buffer*/ + /*We need to wait for ready here to not mess up the active screen*/ + wait_for_flushing(disp_refr); - lv_area_t * sync_area = _lv_ll_ins_tail(&disp_refr->sync_areas); - *sync_area = disp_refr->inv_areas[i]; - } - } + uint32_t i; + for(i = 0; i < disp_refr->inv_p; i++) { + if(disp_refr->inv_area_joined[i]) + continue; - /*Clean up*/ - lv_memset_00(disp_refr->inv_areas, sizeof(disp_refr->inv_areas)); - lv_memset_00(disp_refr->inv_area_joined, sizeof(disp_refr->inv_area_joined)); - disp_refr->inv_p = 0; - - elaps = lv_tick_elaps(start); - - /*Call monitor cb if present*/ - if(disp_refr->driver->monitor_cb) { - disp_refr->driver->monitor_cb(disp_refr->driver, elaps, px_num); - } + lv_area_t * sync_area = _lv_ll_ins_tail(&disp_refr->sync_areas); + *sync_area = disp_refr->inv_areas[i]; } - lv_mem_buf_free_all(); - _lv_font_clean_up_fmt_txt(); +refr_clean_up: + lv_memzero(disp_refr->inv_areas, sizeof(disp_refr->inv_areas)); + lv_memzero(disp_refr->inv_area_joined, sizeof(disp_refr->inv_area_joined)); + disp_refr->inv_p = 0; -#if LV_DRAW_COMPLEX - _lv_draw_mask_cleanup(); +refr_finish: + +#if LV_DRAW_SW_COMPLEX == 1 + _lv_draw_sw_mask_cleanup(); #endif -#if LV_USE_PERF_MONITOR && LV_USE_LABEL - lv_obj_t * perf_label = perf_monitor.perf_label; - if(perf_label == NULL) { - perf_label = lv_label_create(lv_layer_sys()); - lv_obj_set_style_bg_opa(perf_label, LV_OPA_50, 0); - lv_obj_set_style_bg_color(perf_label, lv_color_black(), 0); - lv_obj_set_style_text_color(perf_label, lv_color_white(), 0); - lv_obj_set_style_pad_top(perf_label, 3, 0); - lv_obj_set_style_pad_bottom(perf_label, 3, 0); - lv_obj_set_style_pad_left(perf_label, 3, 0); - lv_obj_set_style_pad_right(perf_label, 3, 0); - lv_obj_set_style_text_align(perf_label, LV_TEXT_ALIGN_RIGHT, 0); - lv_label_set_text(perf_label, "?"); - lv_obj_align(perf_label, LV_USE_PERF_MONITOR_POS, 0, 0); - perf_monitor.perf_label = perf_label; - } + lv_display_send_event(disp_refr, LV_EVENT_REFR_READY, NULL); - if(lv_tick_elaps(perf_monitor.perf_last_time) < 300) { - if(px_num > 5000) { - perf_monitor.elaps_sum += elaps; - perf_monitor.frame_cnt ++; - } - } - else { - perf_monitor.perf_last_time = lv_tick_get(); - uint32_t fps_limit; - uint32_t fps; - - if(disp_refr->refr_timer) { - fps_limit = 1000 / disp_refr->refr_timer->period; - } - else { - fps_limit = 1000 / LV_DISP_DEF_REFR_PERIOD; - } - - if(perf_monitor.elaps_sum == 0) { - perf_monitor.elaps_sum = 1; - } - if(perf_monitor.frame_cnt == 0) { - fps = fps_limit; - } - else { - fps = (1000 * perf_monitor.frame_cnt) / perf_monitor.elaps_sum; - } - perf_monitor.elaps_sum = 0; - perf_monitor.frame_cnt = 0; - if(fps > fps_limit) { - fps = fps_limit; - } - - perf_monitor.fps_sum_all += fps; - perf_monitor.fps_sum_cnt ++; - uint32_t cpu = 100 - lv_timer_get_idle(); - lv_label_set_text_fmt(perf_label, "%"LV_PRIu32" FPS\n%"LV_PRIu32"%% CPU", fps, cpu); - } -#endif - -#if LV_USE_MEM_MONITOR && LV_MEM_CUSTOM == 0 && LV_USE_LABEL - lv_obj_t * mem_label = mem_monitor.mem_label; - if(mem_label == NULL) { - mem_label = lv_label_create(lv_layer_sys()); - lv_obj_set_style_bg_opa(mem_label, LV_OPA_50, 0); - lv_obj_set_style_bg_color(mem_label, lv_color_black(), 0); - lv_obj_set_style_text_color(mem_label, lv_color_white(), 0); - lv_obj_set_style_pad_top(mem_label, 3, 0); - lv_obj_set_style_pad_bottom(mem_label, 3, 0); - lv_obj_set_style_pad_left(mem_label, 3, 0); - lv_obj_set_style_pad_right(mem_label, 3, 0); - lv_label_set_text(mem_label, "?"); - lv_obj_align(mem_label, LV_USE_MEM_MONITOR_POS, 0, 0); - mem_monitor.mem_label = mem_label; - } - - if(lv_tick_elaps(mem_monitor.mem_last_time) > 300) { - mem_monitor.mem_last_time = lv_tick_get(); - lv_mem_monitor_t mon; - lv_mem_monitor(&mon); - uint32_t used_size = mon.total_size - mon.free_size;; - uint32_t used_kb = used_size / 1024; - uint32_t used_kb_tenth = (used_size - (used_kb * 1024)) / 102; - lv_label_set_text_fmt(mem_label, - "%"LV_PRIu32 ".%"LV_PRIu32 " kB used (%d %%)\n" - "%d%% frag.", - used_kb, used_kb_tenth, mon.used_pct, - mon.frag_pct); - } -#endif - - REFR_TRACE("finished"); + LV_TRACE_REFR("finished"); + LV_PROFILER_END; } -#if LV_USE_PERF_MONITOR -void lv_refr_reset_fps_counter(void) -{ - perf_monitor.fps_sum_all = 0; - perf_monitor.fps_sum_cnt = 0; -} - -uint32_t lv_refr_get_fps_avg(void) -{ - if(perf_monitor.fps_sum_cnt == 0) { - return 0; - } - return perf_monitor.fps_sum_all / perf_monitor.fps_sum_cnt; -} -#endif - - /********************** * STATIC FUNCTIONS **********************/ @@ -477,6 +420,7 @@ uint32_t lv_refr_get_fps_avg(void) */ static void lv_refr_join_area(void) { + LV_PROFILER_BEGIN; uint32_t join_from; uint32_t join_in; lv_area_t joined_area; @@ -507,6 +451,7 @@ static void lv_refr_join_area(void) } } } + LV_PROFILER_END; } /** @@ -514,30 +459,34 @@ static void lv_refr_join_area(void) */ static void refr_sync_areas(void) { - /*Do not sync if not direct mode*/ - if(!disp_refr->driver->direct_mode) return; + /*Do not sync if not direct or double buffered*/ + if(disp_refr->render_mode != LV_DISPLAY_RENDER_MODE_DIRECT) return; /*Do not sync if not double buffered*/ - if(disp_refr->driver->draw_buf->buf2 == NULL) return; + if(!lv_display_is_double_buffered(disp_refr)) return; /*Do not sync if no sync areas*/ if(_lv_ll_is_empty(&disp_refr->sync_areas)) return; + LV_PROFILER_BEGIN; + /*With double buffered direct mode synchronize the rendered areas to the other buffer*/ + /*We need to wait for ready here to not mess up the active screen*/ + wait_for_flushing(disp_refr); + /*The buffers are already swapped. *So the active buffer is the off screen buffer where LVGL will render*/ - void * buf_off_screen = disp_refr->driver->draw_buf->buf_act; - void * buf_on_screen = disp_refr->driver->draw_buf->buf_act == disp_refr->driver->draw_buf->buf1 - ? disp_refr->driver->draw_buf->buf2 - : disp_refr->driver->draw_buf->buf1; + lv_draw_buf_t * off_screen = disp_refr->buf_act; + lv_draw_buf_t * on_screen = disp_refr->buf_act == disp_refr->buf_1 ? disp_refr->buf_2 : disp_refr->buf_1; - /*Get stride for buffer copy*/ - lv_coord_t stride = lv_disp_get_hor_res(disp_refr); + uint32_t hor_res = lv_display_get_horizontal_resolution(disp_refr); + uint32_t ver_res = lv_display_get_vertical_resolution(disp_refr); /*Iterate through invalidated areas to see if sync area should be copied*/ + uint16_t i; + int8_t j; lv_area_t res[4] = {0}; - int8_t res_c, j; - uint32_t i; - lv_area_t * sync_area, *new_area, *next_area; + int8_t res_c; + lv_area_t * sync_area, * new_area, * next_area; for(i = 0; i < disp_refr->inv_p; i++) { /*Skip joined areas*/ if(disp_refr->inv_area_joined[i]) continue; @@ -559,7 +508,7 @@ static void refr_sync_areas(void) *new_area = res[j]; } _lv_ll_remove(&disp_refr->sync_areas, sync_area); - lv_mem_free(sync_area); + lv_free(sync_area); } /*Move on to next sync area*/ @@ -567,18 +516,20 @@ static void refr_sync_areas(void) } } + lv_area_t disp_area = {0, 0, (int32_t)hor_res - 1, (int32_t)ver_res - 1}; /*Copy sync areas (if any remaining)*/ for(sync_area = _lv_ll_get_head(&disp_refr->sync_areas); sync_area != NULL; sync_area = _lv_ll_get_next(&disp_refr->sync_areas, sync_area)) { - disp_refr->driver->draw_ctx->buffer_copy( - disp_refr->driver->draw_ctx, - buf_off_screen, stride, sync_area, - buf_on_screen, stride, sync_area - ); + /** + * @todo Resize SDL window will trigger crash because of sync_area is larger than disp_area + */ + _lv_area_intersect(sync_area, sync_area, &disp_area); + lv_draw_buf_copy(off_screen, sync_area, on_screen, sync_area); } /*Clear sync areas*/ _lv_ll_clear(&disp_refr->sync_areas); + LV_PROFILER_END; } /** @@ -586,9 +537,8 @@ static void refr_sync_areas(void) */ static void refr_invalid_areas(void) { - px_num = 0; - if(disp_refr->inv_p == 0) return; + LV_PROFILER_BEGIN; /*Find the last area which will be drawn*/ int32_t i; @@ -601,27 +551,39 @@ static void refr_invalid_areas(void) } /*Notify the display driven rendering has started*/ - if(disp_refr->driver->render_start_cb) { - disp_refr->driver->render_start_cb(disp_refr->driver); - } + lv_display_send_event(disp_refr, LV_EVENT_RENDER_START, NULL); - disp_refr->driver->draw_buf->last_area = 0; - disp_refr->driver->draw_buf->last_part = 0; + disp_refr->last_area = 0; + disp_refr->last_part = 0; disp_refr->rendering_in_progress = true; - for(i = 0; i < disp_refr->inv_p; i++) { + for(i = 0; i < (int32_t)disp_refr->inv_p; i++) { /*Refresh the unjoined areas*/ if(disp_refr->inv_area_joined[i] == 0) { - if(i == last_i) disp_refr->driver->draw_buf->last_area = 1; - disp_refr->driver->draw_buf->last_part = 0; + if(i == last_i) disp_refr->last_area = 1; + disp_refr->last_part = 0; refr_area(&disp_refr->inv_areas[i]); - - px_num += lv_area_get_size(&disp_refr->inv_areas[i]); } } disp_refr->rendering_in_progress = false; + LV_PROFILER_END; +} + +/** + * Reshape the draw buffer if required + * @param layer pointer to a layer which will be drawn + */ +static void layer_reshape_draw_buf(lv_layer_t * layer) +{ + LV_ASSERT(lv_draw_buf_reshape( + layer->draw_buf, + layer->color_format, + lv_area_get_width(&layer->buf_area), + lv_area_get_height(&layer->buf_area), + 0) + != NULL); } /** @@ -630,40 +592,47 @@ static void refr_invalid_areas(void) */ static void refr_area(const lv_area_t * area_p) { - lv_draw_ctx_t * draw_ctx = disp_refr->driver->draw_ctx; - draw_ctx->buf = disp_refr->driver->draw_buf->buf_act; + LV_PROFILER_BEGIN; + lv_layer_t * layer = disp_refr->layer_head; + layer->draw_buf = disp_refr->buf_act; /*With full refresh just redraw directly into the buffer*/ /*In direct mode draw directly on the absolute coordinates of the buffer*/ - if(disp_refr->driver->full_refresh || disp_refr->driver->direct_mode) { + if(disp_refr->render_mode != LV_DISPLAY_RENDER_MODE_PARTIAL) { + layer->buf_area.x1 = 0; + layer->buf_area.y1 = 0; + layer->buf_area.x2 = lv_display_get_horizontal_resolution(disp_refr) - 1; + layer->buf_area.y2 = lv_display_get_vertical_resolution(disp_refr) - 1; + layer_reshape_draw_buf(layer); lv_area_t disp_area; - lv_area_set(&disp_area, 0, 0, lv_disp_get_hor_res(disp_refr) - 1, lv_disp_get_ver_res(disp_refr) - 1); - draw_ctx->buf_area = &disp_area; + lv_area_set(&disp_area, 0, 0, lv_display_get_horizontal_resolution(disp_refr) - 1, + lv_display_get_vertical_resolution(disp_refr) - 1); - if(disp_refr->driver->full_refresh) { - disp_refr->driver->draw_buf->last_part = 1; - draw_ctx->clip_area = &disp_area; - refr_area_part(draw_ctx); + if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_FULL) { + disp_refr->last_part = 1; + layer->_clip_area = disp_area; + refr_area_part(layer); } - else { - disp_refr->driver->draw_buf->last_part = disp_refr->driver->draw_buf->last_area; - draw_ctx->clip_area = area_p; - refr_area_part(draw_ctx); + else if(disp_refr->render_mode == LV_DISPLAY_RENDER_MODE_DIRECT) { + disp_refr->last_part = disp_refr->last_area; + layer->_clip_area = *area_p; + refr_area_part(layer); } + LV_PROFILER_END; return; } /*Normal refresh: draw the area in parts*/ /*Calculate the max row num*/ - lv_coord_t w = lv_area_get_width(area_p); - lv_coord_t h = lv_area_get_height(area_p); - lv_coord_t y2 = area_p->y2 >= lv_disp_get_ver_res(disp_refr) ? - lv_disp_get_ver_res(disp_refr) - 1 : area_p->y2; + int32_t w = lv_area_get_width(area_p); + int32_t h = lv_area_get_height(area_p); + int32_t y2 = area_p->y2 >= lv_display_get_vertical_resolution(disp_refr) ? + lv_display_get_vertical_resolution(disp_refr) - 1 : area_p->y2; int32_t max_row = get_max_row(disp_refr, w, h); - lv_coord_t row; - lv_coord_t row_last = 0; + int32_t row; + int32_t row_last = 0; lv_area_t sub_area; for(row = area_p->y1; row + max_row - 1 <= y2; row += max_row) { /*Calc. the next y coordinates of draw_buf*/ @@ -671,13 +640,14 @@ static void refr_area(const lv_area_t * area_p) sub_area.x2 = area_p->x2; sub_area.y1 = row; sub_area.y2 = row + max_row - 1; - draw_ctx->buf_area = &sub_area; - draw_ctx->clip_area = &sub_area; - draw_ctx->buf = disp_refr->driver->draw_buf->buf_act; + layer->draw_buf = disp_refr->buf_act; + layer->buf_area = sub_area; + layer->_clip_area = sub_area; + layer_reshape_draw_buf(layer); if(sub_area.y2 > y2) sub_area.y2 = y2; row_last = sub_area.y2; - if(y2 == row_last) disp_refr->driver->draw_buf->last_part = 1; - refr_area_part(draw_ctx); + if(y2 == row_last) disp_refr->last_part = 1; + refr_area_part(layer); } /*If the last y coordinates are not handled yet ...*/ @@ -687,115 +657,72 @@ static void refr_area(const lv_area_t * area_p) sub_area.x2 = area_p->x2; sub_area.y1 = row; sub_area.y2 = y2; - draw_ctx->buf_area = &sub_area; - draw_ctx->clip_area = &sub_area; - draw_ctx->buf = disp_refr->driver->draw_buf->buf_act; - disp_refr->driver->draw_buf->last_part = 1; - refr_area_part(draw_ctx); + layer->draw_buf = disp_refr->buf_act; + layer->buf_area = sub_area; + layer->_clip_area = sub_area; + layer_reshape_draw_buf(layer); + disp_refr->last_part = 1; + refr_area_part(layer); } + LV_PROFILER_END; } -static void refr_area_part(lv_draw_ctx_t * draw_ctx) +static void refr_area_part(lv_layer_t * layer) { - lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr); + LV_PROFILER_BEGIN; + disp_refr->refreshed_area = layer->_clip_area; - if(draw_ctx->init_buf) - draw_ctx->init_buf(draw_ctx); - - /* Below the `area_p` area will be redrawn into the draw buffer. - * In single buffered mode wait here until the buffer is freed. - * In full double buffered mode wait here while the buffers are swapped and a buffer becomes available*/ - bool full_sized = draw_buf->size == (uint32_t)disp_refr->driver->hor_res * disp_refr->driver->ver_res; - if((draw_buf->buf1 && !draw_buf->buf2) || - (draw_buf->buf1 && draw_buf->buf2 && full_sized)) { - while(draw_buf->flushing) { - if(disp_refr->driver->wait_cb) disp_refr->driver->wait_cb(disp_refr->driver); - } - - /*If the screen is transparent initialize it when the flushing is ready*/ -#if LV_COLOR_SCREEN_TRANSP - if(disp_refr->driver->screen_transp) { - if(disp_refr->driver->clear_cb) { - disp_refr->driver->clear_cb(disp_refr->driver, disp_refr->driver->draw_buf->buf_act, disp_refr->driver->draw_buf->size); - } - else { - lv_memset_00(disp_refr->driver->draw_buf->buf_act, disp_refr->driver->draw_buf->size * LV_IMG_PX_SIZE_ALPHA_BYTE); - } - } -#endif + /* In single buffered mode wait here until the buffer is freed. + * Else we would draw into the buffer while it's still being transferred to the display*/ + if(!lv_display_is_double_buffered(disp_refr)) { + wait_for_flushing(disp_refr); + } + /*If the screen is transparent initialize it when the flushing is ready*/ + if(lv_color_format_has_alpha(disp_refr->color_format)) { + lv_draw_buf_clear(layer->draw_buf, &disp_refr->refreshed_area); } lv_obj_t * top_act_scr = NULL; lv_obj_t * top_prev_scr = NULL; /*Get the most top object which is not covered by others*/ - top_act_scr = lv_refr_get_top_obj(draw_ctx->buf_area, lv_disp_get_scr_act(disp_refr)); + top_act_scr = lv_refr_get_top_obj(&layer->_clip_area, lv_display_get_screen_active(disp_refr)); if(disp_refr->prev_scr) { - top_prev_scr = lv_refr_get_top_obj(draw_ctx->buf_area, disp_refr->prev_scr); + top_prev_scr = lv_refr_get_top_obj(&layer->_clip_area, disp_refr->prev_scr); } - /*Draw a display background if there is no top object*/ + /*Draw a bottom layer background if there is no top object*/ if(top_act_scr == NULL && top_prev_scr == NULL) { - lv_area_t a; - lv_area_set(&a, 0, 0, - lv_disp_get_hor_res(disp_refr) - 1, lv_disp_get_ver_res(disp_refr) - 1); - if(draw_ctx->draw_bg) { - lv_draw_rect_dsc_t dsc; - lv_draw_rect_dsc_init(&dsc); - dsc.bg_img_src = disp_refr->bg_img; - dsc.bg_img_opa = disp_refr->bg_opa; - dsc.bg_color = disp_refr->bg_color; - dsc.bg_opa = disp_refr->bg_opa; - draw_ctx->draw_bg(draw_ctx, &dsc, &a); - } - else if(disp_refr->bg_img) { - lv_img_header_t header; - lv_res_t res = lv_img_decoder_get_info(disp_refr->bg_img, &header); - if(res == LV_RES_OK) { - lv_draw_img_dsc_t dsc; - lv_draw_img_dsc_init(&dsc); - dsc.opa = disp_refr->bg_opa; - lv_draw_img(draw_ctx, &dsc, &a, disp_refr->bg_img); - } - else { - LV_LOG_WARN("Can't draw the background image"); - } - } - else { - lv_draw_rect_dsc_t dsc; - lv_draw_rect_dsc_init(&dsc); - dsc.bg_color = disp_refr->bg_color; - dsc.bg_opa = disp_refr->bg_opa; - lv_draw_rect(draw_ctx, &dsc, draw_ctx->buf_area); - } + refr_obj_and_children(layer, lv_display_get_layer_bottom(disp_refr)); } if(disp_refr->draw_prev_over_act) { if(top_act_scr == NULL) top_act_scr = disp_refr->act_scr; - refr_obj_and_children(draw_ctx, top_act_scr); + refr_obj_and_children(layer, top_act_scr); /*Refresh the previous screen if any*/ if(disp_refr->prev_scr) { if(top_prev_scr == NULL) top_prev_scr = disp_refr->prev_scr; - refr_obj_and_children(draw_ctx, top_prev_scr); + refr_obj_and_children(layer, top_prev_scr); } } else { /*Refresh the previous screen if any*/ if(disp_refr->prev_scr) { if(top_prev_scr == NULL) top_prev_scr = disp_refr->prev_scr; - refr_obj_and_children(draw_ctx, top_prev_scr); + refr_obj_and_children(layer, top_prev_scr); } if(top_act_scr == NULL) top_act_scr = disp_refr->act_scr; - refr_obj_and_children(draw_ctx, top_act_scr); + refr_obj_and_children(layer, top_act_scr); } /*Also refresh top and sys layer unconditionally*/ - refr_obj_and_children(draw_ctx, lv_disp_get_layer_top(disp_refr)); - refr_obj_and_children(draw_ctx, lv_disp_get_layer_sys(disp_refr)); + refr_obj_and_children(layer, lv_display_get_layer_top(disp_refr)); + refr_obj_and_children(layer, lv_display_get_layer_sys(disp_refr)); draw_buf_flush(disp_refr); + LV_PROFILER_END; } /** @@ -816,11 +743,11 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj) lv_cover_check_info_t info; info.res = LV_COVER_RES_COVER; info.area = area_p; - lv_event_send(obj, LV_EVENT_COVER_CHECK, &info); + lv_obj_send_event(obj, LV_EVENT_COVER_CHECK, &info); if(info.res == LV_COVER_RES_MASKED) return NULL; int32_t i; - int32_t child_cnt = lv_obj_get_child_cnt(obj); + int32_t child_cnt = lv_obj_get_child_count(obj); for(i = child_cnt - 1; i >= 0; i--) { lv_obj_t * child = obj->spec_attr->children[i]; found_p = lv_refr_get_top_obj(area_p, child); @@ -844,16 +771,17 @@ static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj) * @param top_p pointer to an objects. Start the drawing from it. * @param mask_p pointer to an area, the objects will be drawn only here */ -static void refr_obj_and_children(lv_draw_ctx_t * draw_ctx, lv_obj_t * top_obj) +static void refr_obj_and_children(lv_layer_t * layer, lv_obj_t * top_obj) { /*Normally always will be a top_obj (at least the screen) *but in special cases (e.g. if the screen has alpha) it won't. *In this case use the screen directly*/ - if(top_obj == NULL) top_obj = lv_disp_get_scr_act(disp_refr); + if(top_obj == NULL) top_obj = lv_display_get_screen_active(disp_refr); if(top_obj == NULL) return; /*Shouldn't happen*/ + LV_PROFILER_BEGIN; /*Refresh the top object and its children*/ - refr_obj(draw_ctx, top_obj); + refr_obj(layer, top_obj); /*Draw the 'younger' sibling objects because they can be on top_obj*/ lv_obj_t * parent; @@ -865,7 +793,7 @@ static void refr_obj_and_children(lv_draw_ctx_t * draw_ctx, lv_obj_t * top_obj) while(parent != NULL) { bool go = false; uint32_t i; - uint32_t child_cnt = lv_obj_get_child_cnt(parent); + uint32_t child_cnt = lv_obj_get_child_count(parent); for(i = 0; i < child_cnt; i++) { lv_obj_t * child = parent->spec_attr->children[i]; if(!go) { @@ -873,14 +801,14 @@ static void refr_obj_and_children(lv_draw_ctx_t * draw_ctx, lv_obj_t * top_obj) } else { /*Refresh the objects*/ - refr_obj(draw_ctx, child); + refr_obj(layer, child); } } /*Call the post draw draw function of the parents of the to object*/ - lv_event_send(parent, LV_EVENT_DRAW_POST_BEGIN, (void *)draw_ctx); - lv_event_send(parent, LV_EVENT_DRAW_POST, (void *)draw_ctx); - lv_event_send(parent, LV_EVENT_DRAW_POST_END, (void *)draw_ctx); + lv_obj_send_event(parent, LV_EVENT_DRAW_POST_BEGIN, (void *)layer); + lv_obj_send_event(parent, LV_EVENT_DRAW_POST, (void *)layer); + lv_obj_send_event(parent, LV_EVENT_DRAW_POST_END, (void *)layer); /*The new border will be the last parents, *so the 'younger' brothers of parent will be refreshed*/ @@ -888,13 +816,13 @@ static void refr_obj_and_children(lv_draw_ctx_t * draw_ctx, lv_obj_t * top_obj) /*Go a level deeper*/ parent = lv_obj_get_parent(parent); } + LV_PROFILER_END; } - -static lv_res_t layer_get_area(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj, lv_layer_type_t layer_type, - lv_area_t * layer_area_out) +static lv_result_t layer_get_area(lv_layer_t * layer, lv_obj_t * obj, lv_layer_type_t layer_type, + lv_area_t * layer_area_out) { - lv_coord_t ext_draw_size = _lv_obj_get_ext_draw_size(obj); + int32_t ext_draw_size = _lv_obj_get_ext_draw_size(obj); lv_area_t obj_coords_ext; lv_obj_get_coords(obj, &obj_coords_ext); lv_area_increase(&obj_coords_ext, ext_draw_size, ext_draw_size); @@ -905,8 +833,8 @@ static lv_res_t layer_get_area(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj, lv_laye lv_area_t clip_coords_for_obj; lv_area_t tranf_coords = obj_coords_ext; lv_obj_get_transformed_area(obj, &tranf_coords, false, false); - if(!_lv_area_intersect(&clip_coords_for_obj, draw_ctx->clip_area, &tranf_coords)) { - return LV_RES_INV; + if(!_lv_area_intersect(&clip_coords_for_obj, &layer->_clip_area, &tranf_coords)) { + return LV_RESULT_INVALID; } /*Transform back (inverse) the transformed area. @@ -915,437 +843,226 @@ static lv_res_t layer_get_area(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj, lv_laye lv_area_t inverse_clip_coords_for_obj = clip_coords_for_obj; lv_obj_get_transformed_area(obj, &inverse_clip_coords_for_obj, false, true); if(!_lv_area_intersect(&inverse_clip_coords_for_obj, &inverse_clip_coords_for_obj, &obj_coords_ext)) { - return LV_RES_INV; + return LV_RESULT_INVALID; } *layer_area_out = inverse_clip_coords_for_obj; + lv_area_increase(layer_area_out, 5, 5); /*To avoid rounding error*/ } else if(layer_type == LV_LAYER_TYPE_SIMPLE) { lv_area_t clip_coords_for_obj; - if(!_lv_area_intersect(&clip_coords_for_obj, draw_ctx->clip_area, &obj_coords_ext)) { - return LV_RES_INV; + if(!_lv_area_intersect(&clip_coords_for_obj, &layer->_clip_area, &obj_coords_ext)) { + return LV_RESULT_INVALID; } *layer_area_out = clip_coords_for_obj; } else { - LV_LOG_WARN("Unhandled intermediate layer type"); - return LV_RES_INV; + LV_LOG_WARN("Unhandled layer type"); + return LV_RESULT_INVALID; } - return LV_RES_OK; + return LV_RESULT_OK; } -static void layer_alpha_test(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx, - lv_draw_layer_flags_t flags) +static bool alpha_test_area_on_obj(lv_obj_t * obj, const lv_area_t * area) { - bool has_alpha; - /*If globally the layer has alpha maybe this smaller section has not (e.g. not on a rounded corner) - *If turns out that this section has no alpha renderer can choose faster algorithms*/ - if(flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA) { - /*Test for alpha by assuming there is no alpha. If it fails, fall back to rendering with alpha*/ - has_alpha = true; - if(_lv_area_is_in(&layer_ctx->area_act, &obj->coords, 0)) { - lv_cover_check_info_t info; - info.res = LV_COVER_RES_COVER; - info.area = &layer_ctx->area_act; - lv_event_send(obj, LV_EVENT_COVER_CHECK, &info); - if(info.res == LV_COVER_RES_COVER) has_alpha = false; - } + /*Test for alpha by assuming there is no alpha. If it fails, fall back to rendering with alpha*/ + /*If the layer area is not fully on the object, it can't fully cover it*/ + if(!_lv_area_is_on(area, &obj->coords)) return true; - if(has_alpha) { - layer_ctx->area_act.y2 = layer_ctx->area_act.y1 + layer_ctx->max_row_with_alpha - 1; - } - } - else { - has_alpha = false; - } - - if(layer_ctx->area_act.y2 > layer_ctx->area_full.y2) layer_ctx->area_act.y2 = layer_ctx->area_full.y2; - lv_draw_layer_adjust(draw_ctx, layer_ctx, has_alpha ? LV_DRAW_LAYER_FLAG_HAS_ALPHA : LV_DRAW_LAYER_FLAG_NONE); + lv_cover_check_info_t info; + info.res = LV_COVER_RES_COVER; + info.area = area; + lv_obj_send_event(obj, LV_EVENT_COVER_CHECK, &info); + if(info.res == LV_COVER_RES_COVER) return false; + else return true; } - -void refr_obj(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj) +void refr_obj(lv_layer_t * layer, lv_obj_t * obj) { - /*Do not refresh hidden objects*/ if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return; + lv_layer_type_t layer_type = _lv_obj_get_layer_type(obj); if(layer_type == LV_LAYER_TYPE_NONE) { - lv_obj_redraw(draw_ctx, obj); + lv_obj_redraw(layer, obj); } else { lv_opa_t opa = lv_obj_get_style_opa_layered(obj, 0); if(opa < LV_OPA_MIN) return; lv_area_t layer_area_full; - lv_res_t res = layer_get_area(draw_ctx, obj, layer_type, &layer_area_full); - if(res != LV_RES_OK) return; + lv_result_t res = layer_get_area(layer, obj, layer_type, &layer_area_full); + if(res != LV_RESULT_OK) return; - lv_draw_layer_flags_t flags = LV_DRAW_LAYER_FLAG_HAS_ALPHA; - - if(_lv_area_is_in(&layer_area_full, &obj->coords, 0)) { - lv_cover_check_info_t info; - info.res = LV_COVER_RES_COVER; - info.area = &layer_area_full; - lv_event_send(obj, LV_EVENT_COVER_CHECK, &info); - if(info.res == LV_COVER_RES_COVER) flags &= ~LV_DRAW_LAYER_FLAG_HAS_ALPHA; + /*Simple layers can be subdivied into smaller layers*/ + uint32_t max_rgb_row_height = lv_area_get_height(&layer_area_full); + uint32_t max_argb_row_height = lv_area_get_height(&layer_area_full); + if(layer_type == LV_LAYER_TYPE_SIMPLE) { + int32_t w = lv_area_get_width(&layer_area_full); + uint8_t px_size = lv_color_format_get_size(disp_refr->color_format); + max_rgb_row_height = LV_DRAW_SW_LAYER_SIMPLE_BUF_SIZE / w / px_size; + max_argb_row_height = LV_DRAW_SW_LAYER_SIMPLE_BUF_SIZE / w / sizeof(lv_color32_t); } - if(layer_type == LV_LAYER_TYPE_SIMPLE) flags |= LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE; + lv_area_t layer_area_act; + layer_area_act.x1 = layer_area_full.x1; + layer_area_act.x2 = layer_area_full.x2; + layer_area_act.y1 = layer_area_full.y1; + layer_area_act.y2 = layer_area_full.y1; - lv_draw_layer_ctx_t * layer_ctx = lv_draw_layer_create(draw_ctx, &layer_area_full, flags); - if(layer_ctx == NULL) { - LV_LOG_WARN("Couldn't create a new layer context"); - return; - } - lv_point_t pivot = { - .x = lv_obj_get_style_transform_pivot_x(obj, 0), - .y = lv_obj_get_style_transform_pivot_y(obj, 0) - }; - - if(LV_COORD_IS_PCT(pivot.x)) { - pivot.x = (LV_COORD_GET_PCT(pivot.x) * lv_area_get_width(&obj->coords)) / 100; - } - if(LV_COORD_IS_PCT(pivot.y)) { - pivot.y = (LV_COORD_GET_PCT(pivot.y) * lv_area_get_height(&obj->coords)) / 100; - } - - lv_draw_img_dsc_t draw_dsc; - lv_draw_img_dsc_init(&draw_dsc); - draw_dsc.opa = opa; - draw_dsc.angle = lv_obj_get_style_transform_angle(obj, 0); - if(draw_dsc.angle > 3600) draw_dsc.angle -= 3600; - else if(draw_dsc.angle < 0) draw_dsc.angle += 3600; - - draw_dsc.zoom = lv_obj_get_style_transform_zoom(obj, 0); - draw_dsc.blend_mode = lv_obj_get_style_blend_mode(obj, 0); - draw_dsc.antialias = disp_refr->driver->antialiasing; - - if(flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) { - layer_ctx->area_act = layer_ctx->area_full; - layer_ctx->area_act.y2 = layer_ctx->area_act.y1 + layer_ctx->max_row_with_no_alpha - 1; - if(layer_ctx->area_act.y2 > layer_ctx->area_full.y2) layer_ctx->area_act.y2 = layer_ctx->area_full.y2; - } - - while(layer_ctx->area_act.y1 <= layer_area_full.y2) { - if(flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) { - layer_alpha_test(obj, draw_ctx, layer_ctx, flags); + while(layer_area_act.y2 < layer_area_full.y2) { + /* Test with an RGB layer size (which is larger than the ARGB layer size) + * If it really doesn't need alpha use it. Else switch to the ARGB size*/ + layer_area_act.y2 = layer_area_act.y1 + max_rgb_row_height - 1; + if(layer_area_act.y2 > layer_area_full.y2) layer_area_act.y2 = layer_area_full.y2; + bool area_need_alpha = alpha_test_area_on_obj(obj, &layer_area_act); + if(area_need_alpha) { + layer_area_act.y2 = layer_area_act.y1 + max_argb_row_height - 1; + if(layer_area_act.y2 > layer_area_full.y2) layer_area_act.y2 = layer_area_full.y2; } - lv_obj_redraw(draw_ctx, obj); + lv_layer_t * new_layer = lv_draw_layer_create(layer, + area_need_alpha ? LV_COLOR_FORMAT_ARGB8888 : LV_COLOR_FORMAT_NATIVE, &layer_area_act); + lv_obj_redraw(new_layer, obj); - draw_dsc.pivot.x = obj->coords.x1 + pivot.x - draw_ctx->buf_area->x1; - draw_dsc.pivot.y = obj->coords.y1 + pivot.y - draw_ctx->buf_area->y1; + lv_draw_image_dsc_t layer_draw_dsc; + lv_draw_image_dsc_init(&layer_draw_dsc); + layer_draw_dsc.pivot.x = obj->coords.x1 + lv_obj_get_style_transform_pivot_x(obj, 0) - new_layer->buf_area.x1; + layer_draw_dsc.pivot.y = obj->coords.y1 + lv_obj_get_style_transform_pivot_y(obj, 0) - new_layer->buf_area.y1; - /*With LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE it should also go the next chunk*/ - lv_draw_layer_blend(draw_ctx, layer_ctx, &draw_dsc); + layer_draw_dsc.opa = opa; + layer_draw_dsc.rotation = lv_obj_get_style_transform_rotation(obj, 0); + while(layer_draw_dsc.rotation > 3600) layer_draw_dsc.rotation -= 3600; + while(layer_draw_dsc.rotation < 0) layer_draw_dsc.rotation += 3600; + layer_draw_dsc.scale_x = lv_obj_get_style_transform_scale_x(obj, 0); + layer_draw_dsc.scale_y = lv_obj_get_style_transform_scale_y(obj, 0); + layer_draw_dsc.skew_x = lv_obj_get_style_transform_skew_x(obj, 0); + layer_draw_dsc.skew_y = lv_obj_get_style_transform_skew_y(obj, 0); + layer_draw_dsc.blend_mode = lv_obj_get_style_blend_mode(obj, 0); + layer_draw_dsc.antialias = disp_refr->antialiasing; + layer_draw_dsc.src = new_layer; - if((flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) == 0) break; + lv_draw_layer(layer, &layer_draw_dsc, &layer_area_act); - layer_ctx->area_act.y1 = layer_ctx->area_act.y2 + 1; - layer_ctx->area_act.y2 = layer_ctx->area_act.y1 + layer_ctx->max_row_with_no_alpha - 1; + layer_area_act.y1 = layer_area_act.y2 + 1; } - - lv_draw_layer_destroy(draw_ctx, layer_ctx); } } - -static uint32_t get_max_row(lv_disp_t * disp, lv_coord_t area_w, lv_coord_t area_h) +static uint32_t get_max_row(lv_display_t * disp, int32_t area_w, int32_t area_h) { - int32_t max_row = (uint32_t)disp->driver->draw_buf->size / area_w; + bool has_alpha = lv_color_format_has_alpha(disp->color_format); + uint32_t px_size_disp = lv_color_format_get_size(disp->color_format); + uint8_t px_size_render = has_alpha ? sizeof(lv_color32_t) : px_size_disp; + int32_t max_row = (uint32_t)disp->buf_act->data_size / LV_MAX(px_size_render, px_size_disp) / area_w; if(max_row > area_h) max_row = area_h; /*Round down the lines of draw_buf if rounding is added*/ - if(disp_refr->driver->rounder_cb) { - lv_area_t tmp; - tmp.x1 = 0; - tmp.x2 = 0; - tmp.y1 = 0; + lv_area_t tmp; + tmp.x1 = 0; + tmp.x2 = 0; + tmp.y1 = 0; - lv_coord_t h_tmp = max_row; - do { - tmp.y2 = h_tmp - 1; - disp_refr->driver->rounder_cb(disp_refr->driver, &tmp); + int32_t h_tmp = max_row; + do { + tmp.y2 = h_tmp - 1; + lv_display_send_event(disp_refr, LV_EVENT_INVALIDATE_AREA, &tmp); - /*If this height fits into `max_row` then fine*/ - if(lv_area_get_height(&tmp) <= max_row) break; + /*If this height fits into `max_row` then fine*/ + if(lv_area_get_height(&tmp) <= max_row) break; - /*Decrement the height of the area until it fits into `max_row` after rounding*/ - h_tmp--; - } while(h_tmp > 0); + /*Decrement the height of the area until it fits into `max_row` after rounding*/ + h_tmp--; + } while(h_tmp > 0); - if(h_tmp <= 0) { - LV_LOG_WARN("Can't set draw_buf height using the round function. (Wrong round_cb or to " - "small draw_buf)"); - return 0; - } - else { - max_row = tmp.y2 + 1; - } + if(h_tmp <= 0) { + LV_LOG_WARN("Can't set draw_buf height using the round function. (Wrong round_cb or too " + "small draw_buf)"); + return 0; + } + else { + max_row = tmp.y2 + 1; } return max_row; } -static void draw_buf_rotate_180(lv_disp_drv_t * drv, lv_area_t * area, lv_color_t * color_p) -{ - lv_coord_t area_w = lv_area_get_width(area); - lv_coord_t area_h = lv_area_get_height(area); - uint32_t total = area_w * area_h; - /*Swap the beginning and end values*/ - lv_color_t tmp; - uint32_t i = total - 1, j = 0; - while(i > j) { - tmp = color_p[i]; - color_p[i] = color_p[j]; - color_p[j] = tmp; - i--; - j++; - } - lv_coord_t tmp_coord; - tmp_coord = area->y2; - area->y2 = drv->ver_res - area->y1 - 1; - area->y1 = drv->ver_res - tmp_coord - 1; - tmp_coord = area->x2; - area->x2 = drv->hor_res - area->x1 - 1; - area->x1 = drv->hor_res - tmp_coord - 1; -} - -static void LV_ATTRIBUTE_FAST_MEM draw_buf_rotate_90(bool invert_i, lv_coord_t area_w, lv_coord_t area_h, - lv_color_t * orig_color_p, lv_color_t * rot_buf) -{ - - uint32_t invert = (area_w * area_h) - 1; - uint32_t initial_i = ((area_w - 1) * area_h); - for(lv_coord_t y = 0; y < area_h; y++) { - uint32_t i = initial_i + y; - if(invert_i) - i = invert - i; - for(lv_coord_t x = 0; x < area_w; x++) { - rot_buf[i] = *(orig_color_p++); - if(invert_i) - i += area_h; - else - i -= area_h; - } - } -} - -/** - * Helper function for draw_buf_rotate_90_sqr. Given a list of four numbers, rotate the entire list to the left. - */ -static inline void draw_buf_rotate4(lv_color_t * a, lv_color_t * b, lv_color_t * c, lv_color_t * d) -{ - lv_color_t tmp; - tmp = *a; - *a = *b; - *b = *c; - *c = *d; - *d = tmp; -} - -/** - * Rotate a square image 90/270 degrees in place. - * @note inspired by https://stackoverflow.com/a/43694906 - */ -static void draw_buf_rotate_90_sqr(bool is_270, lv_coord_t w, lv_color_t * color_p) -{ - for(lv_coord_t i = 0; i < w / 2; i++) { - for(lv_coord_t j = 0; j < (w + 1) / 2; j++) { - lv_coord_t inv_i = (w - 1) - i; - lv_coord_t inv_j = (w - 1) - j; - if(is_270) { - draw_buf_rotate4( - &color_p[i * w + j], - &color_p[inv_j * w + i], - &color_p[inv_i * w + inv_j], - &color_p[j * w + inv_i] - ); - } - else { - draw_buf_rotate4( - &color_p[i * w + j], - &color_p[j * w + inv_i], - &color_p[inv_i * w + inv_j], - &color_p[inv_j * w + i] - ); - } - - } - } -} - -/** - * Rotate the draw_buf to the display's native orientation. - */ -static void draw_buf_rotate(lv_area_t * area, lv_color_t * color_p) -{ - lv_disp_drv_t * drv = disp_refr->driver; - if(disp_refr->driver->full_refresh && drv->sw_rotate) { - LV_LOG_ERROR("cannot rotate a full refreshed display!"); - return; - } - if(drv->rotated == LV_DISP_ROT_180) { - draw_buf_rotate_180(drv, area, color_p); - call_flush_cb(drv, area, color_p); - } - else if(drv->rotated == LV_DISP_ROT_90 || drv->rotated == LV_DISP_ROT_270) { - /*Allocate a temporary buffer to store rotated image*/ - lv_color_t * rot_buf = NULL; - lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr); - lv_coord_t area_w = lv_area_get_width(area); - lv_coord_t area_h = lv_area_get_height(area); - /*Determine the maximum number of rows that can be rotated at a time*/ - lv_coord_t max_row = LV_MIN((lv_coord_t)((LV_DISP_ROT_MAX_BUF / sizeof(lv_color_t)) / area_w), area_h); - lv_coord_t init_y_off; - init_y_off = area->y1; - if(drv->rotated == LV_DISP_ROT_90) { - area->y2 = drv->ver_res - area->x1 - 1; - area->y1 = area->y2 - area_w + 1; - } - else { - area->y1 = area->x1; - area->y2 = area->y1 + area_w - 1; - } - - /*Rotate the screen in chunks, flushing after each one*/ - lv_coord_t row = 0; - while(row < area_h) { - lv_coord_t height = LV_MIN(max_row, area_h - row); - draw_buf->flushing = 1; - if((row == 0) && (area_h >= area_w)) { - /*Rotate the initial area as a square*/ - height = area_w; - draw_buf_rotate_90_sqr(drv->rotated == LV_DISP_ROT_270, area_w, color_p); - if(drv->rotated == LV_DISP_ROT_90) { - area->x1 = init_y_off; - area->x2 = init_y_off + area_w - 1; - } - else { - area->x2 = drv->hor_res - 1 - init_y_off; - area->x1 = area->x2 - area_w + 1; - } - } - else { - /*Rotate other areas using a maximum buffer size*/ - if(rot_buf == NULL) rot_buf = lv_mem_buf_get(LV_DISP_ROT_MAX_BUF); - draw_buf_rotate_90(drv->rotated == LV_DISP_ROT_270, area_w, height, color_p, rot_buf); - - if(drv->rotated == LV_DISP_ROT_90) { - area->x1 = init_y_off + row; - area->x2 = init_y_off + row + height - 1; - } - else { - area->x2 = drv->hor_res - 1 - init_y_off - row; - area->x1 = area->x2 - height + 1; - } - } - - /* The original part (chunk of the current area) were split into more parts here. - * Set the original last_part flag on the last part of rotation. */ - if(row + height >= area_h && draw_buf->last_area && draw_buf->last_part) { - draw_buf->flushing_last = 1; - } - else { - draw_buf->flushing_last = 0; - } - - /*Flush the completed area to the display*/ - call_flush_cb(drv, area, rot_buf == NULL ? color_p : rot_buf); - /*FIXME: Rotation forces legacy behavior where rendering and flushing are done serially*/ - while(draw_buf->flushing) { - if(drv->wait_cb) drv->wait_cb(drv); - } - color_p += area_w * height; - row += height; - } - /*Free the allocated buffer at the end if necessary*/ - if(rot_buf != NULL) lv_mem_buf_release(rot_buf); - } -} - /** * Flush the content of the draw buffer */ -static void draw_buf_flush(lv_disp_t * disp) +static void draw_buf_flush(lv_display_t * disp) { - lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr); - /*Flush the rendered content to the display*/ - lv_draw_ctx_t * draw_ctx = disp->driver->draw_ctx; - if(draw_ctx->wait_for_finish) draw_ctx->wait_for_finish(draw_ctx); + lv_layer_t * layer = disp->layer_head; - /* In partial double buffered mode wait until the other buffer is freed - * and driver is ready to receive the new buffer */ - bool full_sized = draw_buf->size == (uint32_t)disp_refr->driver->hor_res * disp_refr->driver->ver_res; - if(draw_buf->buf1 && draw_buf->buf2 && !full_sized) { - while(draw_buf->flushing) { - if(disp_refr->driver->wait_cb) disp_refr->driver->wait_cb(disp_refr->driver); - } + while(layer->draw_task_head) { + lv_draw_dispatch_wait_for_request(); + lv_draw_dispatch(); } - draw_buf->flushing = 1; + /* In double buffered mode wait until the other buffer is freed + * and driver is ready to receive the new buffer. + * If we need to wait here it means that the content of one buffer is being sent to display + * and other buffer already contains the new rendered image. */ + if(lv_display_is_double_buffered(disp)) { + wait_for_flushing(disp_refr); + } - if(disp_refr->driver->draw_buf->last_area && disp_refr->driver->draw_buf->last_part) draw_buf->flushing_last = 1; - else draw_buf->flushing_last = 0; + disp->flushing = 1; - bool flushing_last = draw_buf->flushing_last; + if(disp->last_area && disp->last_part) disp->flushing_last = 1; + else disp->flushing_last = 0; - if(disp->driver->flush_cb) { - /*Rotate the buffer to the display's native orientation if necessary*/ - if(disp->driver->rotated != LV_DISP_ROT_NONE && disp->driver->sw_rotate) { - draw_buf_rotate(draw_ctx->buf_area, draw_ctx->buf); + bool flushing_last = disp->flushing_last; + + if(disp->flush_cb) { + call_flush_cb(disp, &disp->refreshed_area, layer->draw_buf->data); + } + /*If there are 2 buffers swap them. With direct mode swap only on the last area*/ + if(lv_display_is_double_buffered(disp) && (disp->render_mode != LV_DISPLAY_RENDER_MODE_DIRECT || flushing_last)) { + if(disp->buf_act == disp->buf_1) { + disp->buf_act = disp->buf_2; } else { - call_flush_cb(disp->driver, draw_ctx->buf_area, draw_ctx->buf); + disp->buf_act = disp->buf_1; } } - - /*If there are 2 buffers swap them. With direct mode swap only on the last area*/ - if(draw_buf->buf1 && draw_buf->buf2 && (!disp->driver->direct_mode || flushing_last)) { - if(draw_buf->buf_act == draw_buf->buf1) - draw_buf->buf_act = draw_buf->buf2; - else - draw_buf->buf_act = draw_buf->buf1; - } } -static void call_flush_cb(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p) +static void call_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map) { - REFR_TRACE("Calling flush_cb on (%d;%d)(%d;%d) area with %p image pointer", area->x1, area->y1, area->x2, area->y2, - (void *)color_p); + LV_PROFILER_BEGIN; + LV_TRACE_REFR("Calling flush_cb on (%d;%d)(%d;%d) area with %p image pointer", + (int)area->x1, (int)area->y1, (int)area->x2, (int)area->y2, (void *)px_map); lv_area_t offset_area = { - .x1 = area->x1 + drv->offset_x, - .y1 = area->y1 + drv->offset_y, - .x2 = area->x2 + drv->offset_x, - .y2 = area->y2 + drv->offset_y + .x1 = area->x1 + disp->offset_x, + .y1 = area->y1 + disp->offset_y, + .x2 = area->x2 + disp->offset_x, + .y2 = area->y2 + disp->offset_y }; - drv->flush_cb(drv, &offset_area, color_p); + lv_display_send_event(disp, LV_EVENT_FLUSH_START, &offset_area); + disp->flush_cb(disp, &offset_area, px_map); + lv_display_send_event(disp, LV_EVENT_FLUSH_FINISH, &offset_area); + + LV_PROFILER_END; } -#if LV_USE_PERF_MONITOR -static void perf_monitor_init(perf_monitor_t * _perf_monitor) +static void wait_for_flushing(lv_display_t * disp) { - LV_ASSERT_NULL(_perf_monitor); - _perf_monitor->elaps_sum = 0; - _perf_monitor->fps_sum_all = 0; - _perf_monitor->fps_sum_cnt = 0; - _perf_monitor->frame_cnt = 0; - _perf_monitor->perf_last_time = 0; - _perf_monitor->perf_label = NULL; -} -#endif + LV_PROFILER_BEGIN; + LV_LOG_TRACE("begin"); -#if LV_USE_MEM_MONITOR -static void mem_monitor_init(mem_monitor_t * _mem_monitor) -{ - LV_ASSERT_NULL(_mem_monitor); - _mem_monitor->mem_last_time = 0; - _mem_monitor->mem_label = NULL; -} -#endif + if(disp->flush_wait_cb) { + disp->flush_wait_cb(disp); + } + else { + while(disp->flushing); + } + disp->flushing_last = 0; + LV_LOG_TRACE("end"); + LV_PROFILER_END; +} diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_refr.h b/lib/libesp32_lvgl/lvgl/src/core/lv_refr.h index 72e8d6c39..e92732edd 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_refr.h +++ b/lib/libesp32_lvgl/lvgl/src/core/lv_refr.h @@ -14,14 +14,13 @@ extern "C" { * INCLUDES *********************/ #include "lv_obj.h" +#include "../display/lv_display.h" #include /********************* * DEFINES *********************/ -#define LV_REFR_TASK_PRIO LV_TASK_PRIO_MID - /********************** * TYPEDEFS **********************/ @@ -47,6 +46,11 @@ extern "C" { */ void _lv_refr_init(void); +/** + * Deinitialize the screen refresh subsystem + */ +void _lv_refr_deinit(void); + /** * Redraw the invalidated areas now. * Normally the redrawing is periodically executed in `lv_timer_handler` but a long blocking process @@ -54,14 +58,14 @@ void _lv_refr_init(void); * (e.g. progress bar) this function can be called when the screen should be updated. * @param disp pointer to display to refresh. NULL to refresh all displays. */ -void lv_refr_now(lv_disp_t * disp); +void lv_refr_now(lv_display_t * disp); /** * Redrawn on object an all its children using the passed draw context - * @param draw pointer to an initialized draw context + * @param layer pointer to a layer where to draw. * @param obj the start object from the redraw should start */ -void lv_obj_redraw(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj); +void lv_obj_redraw(lv_layer_t * layer, lv_obj_t * obj); /** * Invalidate an area on display to redraw it @@ -69,40 +73,25 @@ void lv_obj_redraw(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj); * @param disp pointer to display where the area should be invalidated (NULL can be used if there is * only one display) */ -void _lv_inv_area(lv_disp_t * disp, const lv_area_t * area_p); +void _lv_inv_area(lv_display_t * disp, const lv_area_t * area_p); /** * Get the display which is being refreshed * @return the display being refreshed */ -lv_disp_t * _lv_refr_get_disp_refreshing(void); +lv_display_t * _lv_refr_get_disp_refreshing(void); /** - * Set the display which is being refreshed. - * It shouldn't be used directly by the user. - * It can be used to trick the drawing functions about there is an active display. - * @param the display being refreshed + * Set the display which is being refreshed + * @param disp the display being refreshed */ -void _lv_refr_set_disp_refreshing(lv_disp_t * disp); - -#if LV_USE_PERF_MONITOR -/** - * Reset FPS counter - */ -void lv_refr_reset_fps_counter(void); - -/** - * Get the average FPS - * @return the average FPS - */ -uint32_t lv_refr_get_fps_avg(void); -#endif +void _lv_refr_set_disp_refreshing(lv_display_t * disp); /** * Called periodically to handle the refreshing * @param timer pointer to the timer itself */ -void _lv_disp_refr_timer(lv_timer_t * timer); +void _lv_display_refr_timer(lv_timer_t * timer); /********************** * STATIC FUNCTIONS diff --git a/lib/libesp32_lvgl/lvgl/src/display/lv_display.c b/lib/libesp32_lvgl/lvgl/src/display/lv_display.c new file mode 100644 index 000000000..d67a9a44b --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/display/lv_display.c @@ -0,0 +1,1050 @@ +/** + * @file lv_disp.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_display.h" +#include "../misc/lv_math.h" +#include "../core/lv_refr.h" +#include "../display/lv_display_private.h" +#include "../stdlib/lv_string.h" +#include "../themes/lv_theme.h" +#include "../core/lv_global.h" + +#if LV_USE_DRAW_SW + #include "../draw/sw/lv_draw_sw.h" +#endif + +/********************* + * DEFINES + *********************/ +#define disp_def LV_GLOBAL_DEFAULT()->disp_default +#define disp_ll_p &(LV_GLOBAL_DEFAULT()->disp_ll) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static lv_obj_tree_walk_res_t invalidate_layout_cb(lv_obj_t * obj, void * user_data); +static void update_resolution(lv_display_t * disp); +static void scr_load_internal(lv_obj_t * scr); +static void scr_load_anim_start(lv_anim_t * a); +static void opa_scale_anim(void * obj, int32_t v); +static void set_x_anim(void * obj, int32_t v); +static void set_y_anim(void * obj, int32_t v); +static void scr_anim_completed(lv_anim_t * a); +static bool is_out_anim(lv_screen_load_anim_t a); +static void disp_event_cb(lv_event_t * e); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_display_t * lv_display_create(int32_t hor_res, int32_t ver_res) +{ + lv_display_t * disp = _lv_ll_ins_head(disp_ll_p); + LV_ASSERT_MALLOC(disp); + if(!disp) return NULL; + + lv_memzero(disp, sizeof(lv_display_t)); + + disp->hor_res = hor_res; + disp->ver_res = ver_res; + disp->physical_hor_res = -1; + disp->physical_ver_res = -1; + disp->offset_x = 0; + disp->offset_y = 0; + disp->antialiasing = LV_COLOR_DEPTH > 8 ? 1 : 0; + disp->dpi = LV_DPI_DEF; + disp->color_format = LV_COLOR_FORMAT_NATIVE; + + disp->layer_head = lv_malloc_zeroed(sizeof(lv_layer_t)); + LV_ASSERT_MALLOC(disp->layer_head); + if(disp->layer_head == NULL) return NULL; + + if(disp->layer_init) disp->layer_init(disp, disp->layer_head); + disp->layer_head->buf_area.x1 = 0; + disp->layer_head->buf_area.y1 = 0; + disp->layer_head->buf_area.x2 = hor_res - 1; + disp->layer_head->buf_area.y2 = ver_res - 1; + disp->layer_head->color_format = disp->color_format; + + disp->inv_en_cnt = 1; + + _lv_ll_init(&disp->sync_areas, sizeof(lv_area_t)); + + lv_display_t * disp_def_tmp = disp_def; + disp_def = disp; /*Temporarily change the default screen to create the default screens on the + new display*/ + /*Create a refresh timer*/ + disp->refr_timer = lv_timer_create(_lv_display_refr_timer, LV_DEF_REFR_PERIOD, disp); + LV_ASSERT_MALLOC(disp->refr_timer); + if(disp->refr_timer == NULL) { + lv_free(disp); + return NULL; + } + +#if LV_USE_THEME_DEFAULT + if(lv_theme_default_is_inited() == false) { + disp->theme = lv_theme_default_init(disp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), + LV_THEME_DEFAULT_DARK, LV_FONT_DEFAULT); + } + else { + disp->theme = lv_theme_default_get(); + } +#elif LV_USE_THEME_SIMPLE + if(lv_theme_simple_is_inited() == false) { + disp->theme = lv_theme_simple_init(disp); + } + else { + disp->theme = lv_theme_simple_get(); + } +#endif + + disp->bottom_layer = lv_obj_create(NULL); /*Create bottom layer on the display*/ + disp->act_scr = lv_obj_create(NULL); /*Create a default screen on the display*/ + disp->top_layer = lv_obj_create(NULL); /*Create top layer on the display*/ + disp->sys_layer = lv_obj_create(NULL); /*Create sys layer on the display*/ + lv_obj_remove_style_all(disp->bottom_layer); + lv_obj_remove_style_all(disp->top_layer); + lv_obj_remove_style_all(disp->sys_layer); + lv_obj_remove_flag(disp->top_layer, LV_OBJ_FLAG_CLICKABLE); + lv_obj_remove_flag(disp->sys_layer, LV_OBJ_FLAG_CLICKABLE); + + lv_obj_set_scrollbar_mode(disp->bottom_layer, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_scrollbar_mode(disp->top_layer, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_scrollbar_mode(disp->sys_layer, LV_SCROLLBAR_MODE_OFF); + + lv_obj_invalidate(disp->act_scr); + + disp_def = disp_def_tmp; /*Revert the default display*/ + if(disp_def == NULL) disp_def = disp; /*Initialize the default display*/ + + lv_display_add_event_cb(disp, disp_event_cb, LV_EVENT_REFR_REQUEST, NULL); + + lv_timer_ready(disp->refr_timer); /*Be sure the screen will be refreshed immediately on start up*/ + + return disp; +} + +void lv_display_delete(lv_display_t * disp) +{ + bool was_default = false; + if(disp == lv_display_get_default()) was_default = true; + + lv_display_send_event(disp, LV_EVENT_DELETE, NULL); + lv_event_remove_all(&(disp->event_list)); + + /*Detach the input devices*/ + lv_indev_t * indev; + indev = lv_indev_get_next(NULL); + while(indev) { + if(lv_indev_get_display(indev) == disp) { + lv_indev_set_display(indev, NULL); + } + indev = lv_indev_get_next(indev); + } + + /* Delete screen and other obj */ + if(disp->sys_layer) { + lv_obj_delete(disp->sys_layer); + disp->sys_layer = NULL; + } + if(disp->top_layer) { + lv_obj_delete(disp->top_layer); + disp->top_layer = NULL; + } + + if(disp->bottom_layer) { + lv_obj_delete(disp->bottom_layer); + disp->bottom_layer = NULL; + } + + disp->act_scr = NULL; + + while(disp->screen_cnt != 0) { + /*Delete the screenst*/ + lv_obj_delete(disp->screens[0]); + } + + _lv_ll_clear(&disp->sync_areas); + _lv_ll_remove(disp_ll_p, disp); + if(disp->refr_timer) lv_timer_delete(disp->refr_timer); + + if(disp->layer_deinit) disp->layer_deinit(disp, disp->layer_head); + lv_free(disp->layer_head); + + lv_free(disp); + + if(was_default) lv_display_set_default(_lv_ll_get_head(disp_ll_p)); +} + +void lv_display_set_default(lv_display_t * disp) +{ + disp_def = disp; +} + +lv_display_t * lv_display_get_default(void) +{ + return disp_def; +} + +lv_display_t * lv_display_get_next(lv_display_t * disp) +{ + if(disp == NULL) + return _lv_ll_get_head(disp_ll_p); + else + return _lv_ll_get_next(disp_ll_p, disp); +} + +/*--------------------- + * RESOLUTION + *--------------------*/ + +void lv_display_set_resolution(lv_display_t * disp, int32_t hor_res, int32_t ver_res) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return; + + if(disp->hor_res == hor_res && disp->ver_res == ver_res) return; + + disp->hor_res = hor_res; + disp->ver_res = ver_res; + + update_resolution(disp); +} + +void lv_display_set_physical_resolution(lv_display_t * disp, int32_t hor_res, int32_t ver_res) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return; + + disp->physical_hor_res = hor_res; + disp->physical_ver_res = ver_res; + + lv_obj_invalidate(disp->sys_layer); + +} + +void lv_display_set_offset(lv_display_t * disp, int32_t x, int32_t y) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return; + + disp->offset_x = x; + disp->offset_y = y; + + lv_obj_invalidate(disp->sys_layer); + +} + +void lv_display_set_dpi(lv_display_t * disp, int32_t dpi) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return; + + disp->dpi = dpi; +} + +int32_t lv_display_get_horizontal_resolution(const lv_display_t * disp) +{ + if(disp == NULL) disp = lv_display_get_default(); + + if(disp == NULL) { + return 0; + } + else { + switch(disp->rotation) { + case LV_DISPLAY_ROTATION_90: + case LV_DISPLAY_ROTATION_270: + return disp->ver_res; + default: + return disp->hor_res; + } + } +} + +int32_t lv_display_get_vertical_resolution(const lv_display_t * disp) +{ + if(disp == NULL) disp = lv_display_get_default(); + + if(disp == NULL) { + return 0; + } + else { + switch(disp->rotation) { + case LV_DISPLAY_ROTATION_90: + case LV_DISPLAY_ROTATION_270: + return disp->hor_res; + default: + return disp->ver_res; + } + } +} + +int32_t lv_display_get_physical_horizontal_resolution(const lv_display_t * disp) +{ + if(disp == NULL) disp = lv_display_get_default(); + + if(disp == NULL) { + return 0; + } + else { + switch(disp->rotation) { + case LV_DISPLAY_ROTATION_90: + case LV_DISPLAY_ROTATION_270: + return disp->physical_ver_res > 0 ? disp->physical_ver_res : disp->ver_res; + default: + return disp->physical_hor_res > 0 ? disp->physical_hor_res : disp->hor_res; + } + } +} + +int32_t lv_display_get_physical_vertical_resolution(const lv_display_t * disp) +{ + if(disp == NULL) disp = lv_display_get_default(); + + if(disp == NULL) { + return 0; + } + else { + switch(disp->rotation) { + case LV_DISPLAY_ROTATION_90: + case LV_DISPLAY_ROTATION_270: + return disp->physical_hor_res > 0 ? disp->physical_hor_res : disp->hor_res; + default: + return disp->physical_ver_res > 0 ? disp->physical_ver_res : disp->ver_res; + } + } +} + +int32_t lv_display_get_offset_x(const lv_display_t * disp) +{ + if(disp == NULL) disp = lv_display_get_default(); + + if(disp == NULL) { + return 0; + } + else { + switch(disp->rotation) { + case LV_DISPLAY_ROTATION_90: + return disp->offset_y; + case LV_DISPLAY_ROTATION_180: + return lv_display_get_physical_horizontal_resolution(disp) - disp->offset_x; + case LV_DISPLAY_ROTATION_270: + return lv_display_get_physical_horizontal_resolution(disp) - disp->offset_y; + default: + return disp->offset_x; + } + } +} + +int32_t lv_display_get_offset_y(const lv_display_t * disp) +{ + if(disp == NULL) disp = lv_display_get_default(); + + if(disp == NULL) { + return 0; + } + else { + switch(disp->rotation) { + case LV_DISPLAY_ROTATION_90: + return disp->offset_x; + case LV_DISPLAY_ROTATION_180: + return lv_display_get_physical_vertical_resolution(disp) - disp->offset_y; + case LV_DISPLAY_ROTATION_270: + return lv_display_get_physical_vertical_resolution(disp) - disp->offset_x; + default: + return disp->offset_y; + } + } +} + +int32_t lv_display_get_dpi(const lv_display_t * disp) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return LV_DPI_DEF; /*Do not return 0 because it might be a divider*/ + return disp->dpi; +} + +/*--------------------- + * BUFFERING + *--------------------*/ + +void lv_display_set_draw_buffers(lv_display_t * disp, lv_draw_buf_t * buf1, lv_draw_buf_t * buf2) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return; + + disp->buf_1 = buf1; + disp->buf_2 = buf2; + disp->buf_act = disp->buf_1; +} + +void lv_display_set_buffers(lv_display_t * disp, void * buf1, void * buf2, uint32_t buf_size, + lv_display_render_mode_t render_mode) +{ + LV_ASSERT_MSG(buf1 != NULL, "Null buffer"); + lv_color_format_t cf = lv_display_get_color_format(disp); + uint32_t w = lv_display_get_horizontal_resolution(disp); + uint32_t h = lv_display_get_vertical_resolution(disp); + + LV_ASSERT_MSG(w != 0 && h != 0, "display resolution is 0"); + + /* buf1 or buf2 is not aligned according to LV_DRAW_BUF_ALIGN */ + LV_ASSERT_MSG(buf1 == lv_draw_buf_align(buf1, cf), "buf1 is not aligned: %p", buf1); + LV_ASSERT_MSG(buf2 == NULL || buf2 == lv_draw_buf_align(buf2, cf), "buf2 is not aligned: %p", buf2); + + uint32_t stride = lv_draw_buf_width_to_stride(w, cf); + if(render_mode == LV_DISPLAY_RENDER_MODE_PARTIAL) { + /* for partial mode, we calculate the height based on the buf_size and stride */ + h = buf_size / stride; + LV_ASSERT_MSG(h != 0, "the buffer is too small"); + } + else { + LV_ASSERT_MSG(stride * h <= buf_size, "%s mode requires screen sized buffer(s)", + render_mode == LV_DISPLAY_RENDER_MODE_FULL ? "FULL" : "DIRECT"); + } + + lv_draw_buf_init(&disp->_static_buf1, w, h, cf, stride, buf1, buf_size); + lv_draw_buf_init(&disp->_static_buf2, w, h, cf, stride, buf2, buf_size); + lv_display_set_draw_buffers(disp, &disp->_static_buf1, buf2 ? &disp->_static_buf2 : NULL); + lv_display_set_render_mode(disp, render_mode); +} + +void lv_display_set_render_mode(lv_display_t * disp, lv_display_render_mode_t render_mode) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return; + disp->render_mode = render_mode; +} + +void lv_display_set_flush_cb(lv_display_t * disp, lv_display_flush_cb_t flush_cb) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return; + + disp->flush_cb = flush_cb; +} + +void lv_display_set_flush_wait_cb(lv_display_t * disp, lv_display_flush_wait_cb_t wait_cb) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return; + + disp->flush_wait_cb = wait_cb; +} + +void lv_display_set_color_format(lv_display_t * disp, lv_color_format_t color_format) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return; + + disp->color_format = color_format; + disp->layer_head->color_format = color_format; + + lv_display_send_event(disp, LV_EVENT_COLOR_FORMAT_CHANGED, NULL); +} + +lv_color_format_t lv_display_get_color_format(lv_display_t * disp) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return LV_COLOR_FORMAT_UNKNOWN; + + return disp->color_format; +} + +void lv_display_set_antialiasing(lv_display_t * disp, bool en) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return; + + disp->antialiasing = en; +} + +bool lv_display_get_antialiasing(lv_display_t * disp) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return false; + + return disp->antialiasing; +} + +LV_ATTRIBUTE_FLUSH_READY void lv_display_flush_ready(lv_display_t * disp) +{ + disp->flushing = 0; +} + +LV_ATTRIBUTE_FLUSH_READY bool lv_display_flush_is_last(lv_display_t * disp) +{ + return disp->flushing_last; +} + +bool lv_display_is_double_buffered(lv_display_t * disp) +{ + return disp->buf_2 != NULL; +} + +/*--------------------- + * SCREENS + *--------------------*/ + +lv_obj_t * lv_display_get_screen_active(lv_display_t * disp) +{ + if(!disp) disp = lv_display_get_default(); + if(!disp) { + LV_LOG_WARN("no display registered to get its active screen"); + return NULL; + } + + return disp->act_scr; +} + +lv_obj_t * lv_display_get_screen_prev(lv_display_t * disp) +{ + if(!disp) disp = lv_display_get_default(); + if(!disp) { + LV_LOG_WARN("no display registered to get its previous screen"); + return NULL; + } + + return disp->prev_scr; +} + +lv_obj_t * lv_display_get_layer_top(lv_display_t * disp) +{ + if(!disp) disp = lv_display_get_default(); + if(!disp) { + LV_LOG_WARN("lv_layer_top: no display registered to get its top layer"); + return NULL; + } + + return disp->top_layer; +} + +lv_obj_t * lv_display_get_layer_sys(lv_display_t * disp) +{ + if(!disp) disp = lv_display_get_default(); + if(!disp) { + LV_LOG_WARN("lv_layer_sys: no display registered to get its sys. layer"); + return NULL; + } + + return disp->sys_layer; +} + +lv_obj_t * lv_display_get_layer_bottom(lv_display_t * disp) +{ + if(!disp) disp = lv_display_get_default(); + if(!disp) { + LV_LOG_WARN("lv_layer_bottom: no display registered to get its bottom layer"); + return NULL; + } + + return disp->bottom_layer; +} + +void lv_screen_load(struct _lv_obj_t * scr) +{ + lv_screen_load_anim(scr, LV_SCR_LOAD_ANIM_NONE, 0, 0, false); +} + +void lv_screen_load_anim(lv_obj_t * new_scr, lv_screen_load_anim_t anim_type, uint32_t time, uint32_t delay, + bool auto_del) +{ + lv_display_t * d = lv_obj_get_display(new_scr); + lv_obj_t * act_scr = lv_screen_active(); + + if(act_scr == new_scr || d->scr_to_load == new_scr) { + return; + } + + /*If another screen load animation is in progress + *make target screen loaded immediately. */ + if(d->scr_to_load && act_scr != d->scr_to_load) { + lv_anim_delete(d->scr_to_load, NULL); + lv_obj_set_pos(d->scr_to_load, 0, 0); + lv_obj_remove_local_style_prop(d->scr_to_load, LV_STYLE_OPA, 0); + + if(d->del_prev) { + lv_obj_delete(act_scr); + } + act_scr = lv_screen_active(); /*Active screen changed.*/ + + scr_load_internal(d->scr_to_load); + } + + d->scr_to_load = new_scr; + + if(d->prev_scr && d->del_prev) { + lv_obj_delete(d->prev_scr); + d->prev_scr = NULL; + } + + d->draw_prev_over_act = is_out_anim(anim_type); + d->del_prev = auto_del; + + /*Be sure there is no other animation on the screens*/ + lv_anim_delete(new_scr, NULL); + if(act_scr) lv_anim_delete(act_scr, NULL); + + /*Be sure both screens are in a normal position*/ + lv_obj_set_pos(new_scr, 0, 0); + if(act_scr) lv_obj_set_pos(act_scr, 0, 0); + lv_obj_remove_local_style_prop(new_scr, LV_STYLE_OPA, 0); + if(act_scr) lv_obj_remove_local_style_prop(act_scr, LV_STYLE_OPA, 0); + + /*Shortcut for immediate load*/ + if(time == 0 && delay == 0) { + scr_load_internal(new_scr); + if(auto_del && act_scr) lv_obj_delete(act_scr); + return; + } + + lv_anim_t a_new; + lv_anim_init(&a_new); + lv_anim_set_var(&a_new, new_scr); + lv_anim_set_start_cb(&a_new, scr_load_anim_start); + lv_anim_set_completed_cb(&a_new, scr_anim_completed); + lv_anim_set_duration(&a_new, time); + lv_anim_set_delay(&a_new, delay); + + lv_anim_t a_old; + lv_anim_init(&a_old); + lv_anim_set_var(&a_old, act_scr); + lv_anim_set_duration(&a_old, time); + lv_anim_set_delay(&a_old, delay); + + switch(anim_type) { + case LV_SCR_LOAD_ANIM_NONE: + /*Create a dummy animation to apply the delay*/ + lv_anim_set_exec_cb(&a_new, set_x_anim); + lv_anim_set_values(&a_new, 0, 0); + break; + case LV_SCR_LOAD_ANIM_OVER_LEFT: + lv_anim_set_exec_cb(&a_new, set_x_anim); + lv_anim_set_values(&a_new, lv_display_get_horizontal_resolution(d), 0); + break; + case LV_SCR_LOAD_ANIM_OVER_RIGHT: + lv_anim_set_exec_cb(&a_new, set_x_anim); + lv_anim_set_values(&a_new, -lv_display_get_horizontal_resolution(d), 0); + break; + case LV_SCR_LOAD_ANIM_OVER_TOP: + lv_anim_set_exec_cb(&a_new, set_y_anim); + lv_anim_set_values(&a_new, lv_display_get_vertical_resolution(d), 0); + break; + case LV_SCR_LOAD_ANIM_OVER_BOTTOM: + lv_anim_set_exec_cb(&a_new, set_y_anim); + lv_anim_set_values(&a_new, -lv_display_get_vertical_resolution(d), 0); + break; + case LV_SCR_LOAD_ANIM_MOVE_LEFT: + lv_anim_set_exec_cb(&a_new, set_x_anim); + lv_anim_set_values(&a_new, lv_display_get_horizontal_resolution(d), 0); + + lv_anim_set_exec_cb(&a_old, set_x_anim); + lv_anim_set_values(&a_old, 0, -lv_display_get_horizontal_resolution(d)); + break; + case LV_SCR_LOAD_ANIM_MOVE_RIGHT: + lv_anim_set_exec_cb(&a_new, set_x_anim); + lv_anim_set_values(&a_new, -lv_display_get_horizontal_resolution(d), 0); + + lv_anim_set_exec_cb(&a_old, set_x_anim); + lv_anim_set_values(&a_old, 0, lv_display_get_horizontal_resolution(d)); + break; + case LV_SCR_LOAD_ANIM_MOVE_TOP: + lv_anim_set_exec_cb(&a_new, set_y_anim); + lv_anim_set_values(&a_new, lv_display_get_vertical_resolution(d), 0); + + lv_anim_set_exec_cb(&a_old, set_y_anim); + lv_anim_set_values(&a_old, 0, -lv_display_get_vertical_resolution(d)); + break; + case LV_SCR_LOAD_ANIM_MOVE_BOTTOM: + lv_anim_set_exec_cb(&a_new, set_y_anim); + lv_anim_set_values(&a_new, -lv_display_get_vertical_resolution(d), 0); + + lv_anim_set_exec_cb(&a_old, set_y_anim); + lv_anim_set_values(&a_old, 0, lv_display_get_vertical_resolution(d)); + break; + case LV_SCR_LOAD_ANIM_FADE_IN: + lv_anim_set_exec_cb(&a_new, opa_scale_anim); + lv_anim_set_values(&a_new, LV_OPA_TRANSP, LV_OPA_COVER); + break; + case LV_SCR_LOAD_ANIM_FADE_OUT: + lv_anim_set_exec_cb(&a_old, opa_scale_anim); + lv_anim_set_values(&a_old, LV_OPA_COVER, LV_OPA_TRANSP); + break; + case LV_SCR_LOAD_ANIM_OUT_LEFT: + lv_anim_set_exec_cb(&a_old, set_x_anim); + lv_anim_set_values(&a_old, 0, -lv_display_get_horizontal_resolution(d)); + break; + case LV_SCR_LOAD_ANIM_OUT_RIGHT: + lv_anim_set_exec_cb(&a_old, set_x_anim); + lv_anim_set_values(&a_old, 0, lv_display_get_horizontal_resolution(d)); + break; + case LV_SCR_LOAD_ANIM_OUT_TOP: + lv_anim_set_exec_cb(&a_old, set_y_anim); + lv_anim_set_values(&a_old, 0, -lv_display_get_vertical_resolution(d)); + break; + case LV_SCR_LOAD_ANIM_OUT_BOTTOM: + lv_anim_set_exec_cb(&a_old, set_y_anim); + lv_anim_set_values(&a_old, 0, lv_display_get_vertical_resolution(d)); + break; + } + + if(act_scr) lv_obj_send_event(act_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL); + + lv_anim_start(&a_new); + if(act_scr) lv_anim_start(&a_old); +} + +/*--------------------- + * OTHERS + *--------------------*/ + +void lv_display_add_event_cb(lv_display_t * disp, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data) +{ + LV_ASSERT_NULL(disp); + + lv_event_add(&disp->event_list, event_cb, filter, user_data); +} + +uint32_t lv_display_get_event_count(lv_display_t * disp) +{ + LV_ASSERT_NULL(disp); + return lv_event_get_count(&disp->event_list); +} + +lv_event_dsc_t * lv_display_get_event_dsc(lv_display_t * disp, uint32_t index) +{ + LV_ASSERT_NULL(disp); + return lv_event_get_dsc(&disp->event_list, index); + +} + +bool lv_display_delete_event(lv_display_t * disp, uint32_t index) +{ + LV_ASSERT_NULL(disp); + + return lv_event_remove(&disp->event_list, index); +} + +uint32_t lv_display_remove_event_cb_with_user_data(lv_display_t * disp, lv_event_cb_t event_cb, void * user_data) +{ + LV_ASSERT_NULL(disp); + + uint32_t event_cnt = lv_display_get_event_count(disp); + uint32_t removed_count = 0; + int32_t i; + + for(i = event_cnt - 1; i >= 0; i--) { + lv_event_dsc_t * dsc = lv_display_get_event_dsc(disp, i); + if(dsc && dsc->cb == event_cb && dsc->user_data == user_data) { + lv_display_delete_event(disp, i); + removed_count ++; + } + } + + return removed_count; +} + +lv_result_t lv_display_send_event(lv_display_t * disp, lv_event_code_t code, void * param) +{ + + lv_event_t e; + lv_memzero(&e, sizeof(e)); + e.code = code; + e.current_target = disp; + e.original_target = disp; + e.param = param; + lv_result_t res; + res = lv_event_send(&disp->event_list, &e, true); + if(res != LV_RESULT_OK) return res; + + res = lv_event_send(&disp->event_list, &e, false); + if(res != LV_RESULT_OK) return res; + + return res; +} + +void lv_display_set_rotation(lv_display_t * disp, lv_display_rotation_t rotation) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return; + + disp->rotation = rotation; + update_resolution(disp); +} + +lv_display_rotation_t lv_display_get_rotation(lv_display_t * disp) +{ + if(disp == NULL) disp = lv_display_get_default(); + if(disp == NULL) return LV_DISPLAY_ROTATION_0; + return disp->rotation; +} + +void lv_display_set_theme(lv_display_t * disp, lv_theme_t * th) +{ + if(!disp) disp = lv_display_get_default(); + if(!disp) { + LV_LOG_WARN("no display registered"); + return; + } + + disp->theme = th; + + if(disp->screen_cnt == 4 && + lv_obj_get_child_count(disp->screens[0]) == 0 && + lv_obj_get_child_count(disp->screens[1]) == 0 && + lv_obj_get_child_count(disp->screens[2]) == 0) { + lv_theme_apply(disp->screens[0]); + } +} + +lv_theme_t * lv_display_get_theme(lv_display_t * disp) +{ + if(disp == NULL) disp = lv_display_get_default(); + return disp->theme; +} + +uint32_t lv_display_get_inactive_time(const lv_display_t * disp) +{ + if(disp) return lv_tick_elaps(disp->last_activity_time); + + lv_display_t * d; + uint32_t t = UINT32_MAX; + d = lv_display_get_next(NULL); + while(d) { + uint32_t elaps = lv_tick_elaps(d->last_activity_time); + t = LV_MIN(t, elaps); + d = lv_display_get_next(d); + } + + return t; +} + +void lv_display_trigger_activity(lv_display_t * disp) +{ + if(!disp) disp = lv_display_get_default(); + if(!disp) { + LV_LOG_WARN("lv_display_trigger_activity: no display registered"); + return; + } + + disp->last_activity_time = lv_tick_get(); +} + +void lv_display_enable_invalidation(lv_display_t * disp, bool en) +{ + if(!disp) disp = lv_display_get_default(); + if(!disp) { + LV_LOG_WARN("no display registered"); + return; + } + + disp->inv_en_cnt += en ? 1 : -1; +} + +bool lv_display_is_invalidation_enabled(lv_display_t * disp) +{ + if(!disp) disp = lv_display_get_default(); + if(!disp) { + LV_LOG_WARN("no display registered"); + return false; + } + + return (disp->inv_en_cnt > 0); +} + +lv_timer_t * lv_display_get_refr_timer(lv_display_t * disp) +{ + if(!disp) disp = lv_display_get_default(); + if(!disp) return NULL; + + return disp->refr_timer; +} + +void lv_display_delete_refr_timer(lv_display_t * disp) +{ + if(!disp) disp = lv_display_get_default(); + if(!disp || !disp->refr_timer) return; + + lv_timer_delete(disp->refr_timer); + disp->refr_timer = NULL; +} + +void lv_display_set_user_data(lv_display_t * disp, void * user_data) +{ + if(!disp) disp = lv_display_get_default(); + if(!disp) return; + disp->user_data = user_data; +} + +void lv_display_set_driver_data(lv_display_t * disp, void * driver_data) +{ + if(!disp) disp = lv_display_get_default(); + if(!disp) return; + + disp->driver_data = driver_data; +} + +void * lv_display_get_user_data(lv_display_t * disp) +{ + if(!disp) disp = lv_display_get_default(); + if(!disp) return NULL; + return disp->user_data; +} + +void * lv_display_get_driver_data(lv_display_t * disp) +{ + if(!disp) disp = lv_display_get_default(); + if(!disp) return NULL; + + return disp->driver_data; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void update_resolution(lv_display_t * disp) +{ + int32_t hor_res = lv_display_get_horizontal_resolution(disp); + int32_t ver_res = lv_display_get_vertical_resolution(disp); + + lv_area_t prev_coords; + lv_obj_get_coords(disp->sys_layer, &prev_coords); + uint32_t i; + for(i = 0; i < disp->screen_cnt; i++) { + lv_area_set_width(&disp->screens[i]->coords, hor_res); + lv_area_set_height(&disp->screens[i]->coords, ver_res); + lv_obj_send_event(disp->screens[i], LV_EVENT_SIZE_CHANGED, &prev_coords); + } + + lv_area_set_width(&disp->top_layer->coords, hor_res); + lv_area_set_height(&disp->top_layer->coords, ver_res); + lv_obj_send_event(disp->top_layer, LV_EVENT_SIZE_CHANGED, &prev_coords); + + lv_area_set_width(&disp->sys_layer->coords, hor_res); + lv_area_set_height(&disp->sys_layer->coords, ver_res); + lv_obj_send_event(disp->sys_layer, LV_EVENT_SIZE_CHANGED, &prev_coords); + + lv_area_set_width(&disp->bottom_layer->coords, hor_res); + lv_area_set_height(&disp->bottom_layer->coords, ver_res); + lv_obj_send_event(disp->bottom_layer, LV_EVENT_SIZE_CHANGED, &prev_coords); + + lv_memzero(disp->inv_areas, sizeof(disp->inv_areas)); + lv_memzero(disp->inv_area_joined, sizeof(disp->inv_area_joined)); + disp->inv_p = 0; + lv_obj_invalidate(disp->sys_layer); + + lv_obj_tree_walk(NULL, invalidate_layout_cb, NULL); + + lv_display_send_event(disp, LV_EVENT_RESOLUTION_CHANGED, NULL); +} + +static lv_obj_tree_walk_res_t invalidate_layout_cb(lv_obj_t * obj, void * user_data) +{ + LV_UNUSED(user_data); + lv_obj_mark_layout_as_dirty(obj); + return LV_OBJ_TREE_WALK_NEXT; +} + +static void scr_load_internal(lv_obj_t * scr) +{ + /*scr must not be NULL, but d->act_scr might be*/ + LV_ASSERT_NULL(scr); + if(scr == NULL) return; + + lv_display_t * d = lv_obj_get_display(scr); + if(!d) return; /*Shouldn't happen, just to be sure*/ + + lv_obj_t * old_scr = d->act_scr; + + if(old_scr) lv_obj_send_event(old_scr, LV_EVENT_SCREEN_UNLOAD_START, NULL); + lv_obj_send_event(scr, LV_EVENT_SCREEN_LOAD_START, NULL); + + d->act_scr = scr; + d->scr_to_load = NULL; + + lv_obj_send_event(scr, LV_EVENT_SCREEN_LOADED, NULL); + if(old_scr) lv_obj_send_event(old_scr, LV_EVENT_SCREEN_UNLOADED, NULL); + + lv_obj_invalidate(scr); +} + +static void scr_load_anim_start(lv_anim_t * a) +{ + lv_display_t * d = lv_obj_get_display(a->var); + + d->prev_scr = lv_screen_active(); + d->act_scr = a->var; + + lv_obj_send_event(d->act_scr, LV_EVENT_SCREEN_LOAD_START, NULL); +} + +static void opa_scale_anim(void * obj, int32_t v) +{ + lv_obj_set_style_opa(obj, v, 0); +} + +static void set_x_anim(void * obj, int32_t v) +{ + lv_obj_set_x(obj, v); +} + +static void set_y_anim(void * obj, int32_t v) +{ + lv_obj_set_y(obj, v); +} + +static void scr_anim_completed(lv_anim_t * a) +{ + lv_display_t * d = lv_obj_get_display(a->var); + + lv_obj_send_event(d->act_scr, LV_EVENT_SCREEN_LOADED, NULL); + lv_obj_send_event(d->prev_scr, LV_EVENT_SCREEN_UNLOADED, NULL); + + if(d->prev_scr && d->del_prev) lv_obj_delete(d->prev_scr); + d->prev_scr = NULL; + d->draw_prev_over_act = false; + d->scr_to_load = NULL; + lv_obj_remove_local_style_prop(a->var, LV_STYLE_OPA, 0); + lv_obj_invalidate(d->act_scr); +} + +static bool is_out_anim(lv_screen_load_anim_t anim_type) +{ + return anim_type == LV_SCR_LOAD_ANIM_FADE_OUT || + anim_type == LV_SCR_LOAD_ANIM_OUT_LEFT || + anim_type == LV_SCR_LOAD_ANIM_OUT_RIGHT || + anim_type == LV_SCR_LOAD_ANIM_OUT_TOP || + anim_type == LV_SCR_LOAD_ANIM_OUT_BOTTOM; +} + +static void disp_event_cb(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_display_t * disp = lv_event_get_target(e); + switch(code) { + case LV_EVENT_REFR_REQUEST: + if(disp->refr_timer) lv_timer_resume(disp->refr_timer); + break; + + default: + break; + } +} diff --git a/lib/libesp32_lvgl/lvgl/src/display/lv_display.h b/lib/libesp32_lvgl/lvgl/src/display/lv_display.h new file mode 100644 index 000000000..da0c38f7d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/display/lv_display.h @@ -0,0 +1,601 @@ +/** + * @file lv_disp.h + * + */ + +#ifndef LV_DISPLAY_H +#define LV_DISPLAY_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../misc/lv_types.h" +#include "../misc/lv_timer.h" +#include "../misc/lv_event.h" +#include "../misc/lv_color.h" +#include "../draw/lv_draw.h" + +/********************* + * DEFINES + *********************/ + +#ifndef LV_ATTRIBUTE_FLUSH_READY +#define LV_ATTRIBUTE_FLUSH_READY +#endif + +/********************** + * TYPEDEFS + **********************/ + +typedef enum { + LV_DISPLAY_ROTATION_0 = 0, + LV_DISPLAY_ROTATION_90, + LV_DISPLAY_ROTATION_180, + LV_DISPLAY_ROTATION_270 +} lv_display_rotation_t; + +typedef enum { + /** + * Use the buffer(s) to render the screen is smaller parts. + * This way the buffers can be smaller then the display to save RAM. At least 1/10 screen size buffer(s) are recommended. + */ + LV_DISPLAY_RENDER_MODE_PARTIAL, + + /** + * The buffer(s) has to be screen sized and LVGL will render into the correct location of the buffer. + * This way the buffer always contain the whole image. Only the changed ares will be updated. + * With 2 buffers the buffers' content are kept in sync automatically and in flush_cb only address change is required. + */ + LV_DISPLAY_RENDER_MODE_DIRECT, + + /** + * Always redraw the whole screen even if only one pixel has been changed. + * With 2 buffers in flush_cb only and address change is required. + */ + LV_DISPLAY_RENDER_MODE_FULL, +} lv_display_render_mode_t; + +typedef enum { + LV_SCR_LOAD_ANIM_NONE, + LV_SCR_LOAD_ANIM_OVER_LEFT, + LV_SCR_LOAD_ANIM_OVER_RIGHT, + LV_SCR_LOAD_ANIM_OVER_TOP, + LV_SCR_LOAD_ANIM_OVER_BOTTOM, + LV_SCR_LOAD_ANIM_MOVE_LEFT, + LV_SCR_LOAD_ANIM_MOVE_RIGHT, + LV_SCR_LOAD_ANIM_MOVE_TOP, + LV_SCR_LOAD_ANIM_MOVE_BOTTOM, + LV_SCR_LOAD_ANIM_FADE_IN, + LV_SCR_LOAD_ANIM_FADE_ON = LV_SCR_LOAD_ANIM_FADE_IN, /*For backward compatibility*/ + LV_SCR_LOAD_ANIM_FADE_OUT, + LV_SCR_LOAD_ANIM_OUT_LEFT, + LV_SCR_LOAD_ANIM_OUT_RIGHT, + LV_SCR_LOAD_ANIM_OUT_TOP, + LV_SCR_LOAD_ANIM_OUT_BOTTOM, +} lv_screen_load_anim_t; + +typedef void (*lv_display_flush_cb_t)(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map); +typedef void (*lv_display_flush_wait_cb_t)(lv_display_t * disp); + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a new display with the given resolution + * @param hor_res horizontal resolution in pixels + * @param ver_res vertical resolution in pixels + * @return pointer to a display object or `NULL` on error + */ +lv_display_t * lv_display_create(int32_t hor_res, int32_t ver_res); + +/** + * Remove a display + * @param disp pointer to display + */ +void lv_display_delete(lv_display_t * disp); + +/** + * Set a default display. The new screens will be created on it by default. + * @param disp pointer to a display + */ +void lv_display_set_default(lv_display_t * disp); + +/** + * Get the default display + * @return pointer to the default display + */ +lv_display_t * lv_display_get_default(void); + +/** + * Get the next display. + * @param disp pointer to the current display. NULL to initialize. + * @return the next display or NULL if no more. Gives the first display when the parameter is NULL. + */ +lv_display_t * lv_display_get_next(lv_display_t * disp); + +/*--------------------- + * RESOLUTION + *--------------------*/ + +/** + * Sets the resolution of a display. `LV_EVENT_RESOLUTION_CHANGED` event will be sent. + * Here the native resolution of the device should be set. If the display will be rotated later with + * `lv_display_set_rotation` LVGL will swap the hor. and ver. resolution automatically. + * @param disp pointer to a display + * @param hor_res the new horizontal resolution + * @param ver_res the new vertical resolution + */ +void lv_display_set_resolution(lv_display_t * disp, int32_t hor_res, int32_t ver_res); + +/** + * It's not mandatory to use the whole display for LVGL, however in some cases physical resolution is important. + * For example the touchpad still sees whole resolution and the values needs to be converted + * to the active LVGL display area. + * @param disp pointer to a display + * @param hor_res the new physical horizontal resolution, or -1 to assume it's the same as the normal hor. res. + * @param ver_res the new physical vertical resolution, or -1 to assume it's the same as the normal hor. res. + */ +void lv_display_set_physical_resolution(lv_display_t * disp, int32_t hor_res, int32_t ver_res); + +/** + * If physical resolution is not the same as the normal resolution + * the offset of the active display area can be set here. + * @param disp pointer to a display + * @param x X offset + * @param y Y offset + */ +void lv_display_set_offset(lv_display_t * disp, int32_t x, int32_t y); + +/** + * Set the rotation of this display. LVGL will swap the horizontal and vertical resolutions internally. + * @param disp pointer to a display (NULL to use the default display) + * @param rotation `LV_DISPLAY_ROTATION_0/90/180/270` + */ +void lv_display_set_rotation(lv_display_t * disp, lv_display_rotation_t rotation); + +/** + * Set the DPI (dot per inch) of the display. + * dpi = sqrt(hor_res^2 + ver_res^2) / diagonal" + * @param disp pointer to a display + * @param dpi the new DPI + */ +void lv_display_set_dpi(lv_display_t * disp, int32_t dpi); + +/** + * Get the horizontal resolution of a display. + * @param disp pointer to a display (NULL to use the default display) + * @return the horizontal resolution of the display. + */ +int32_t lv_display_get_horizontal_resolution(const lv_display_t * disp); + +/** + * Get the vertical resolution of a display + * @param disp pointer to a display (NULL to use the default display) + * @return the vertical resolution of the display + */ +int32_t lv_display_get_vertical_resolution(const lv_display_t * disp); + +/** + * Get the physical horizontal resolution of a display + * @param disp pointer to a display (NULL to use the default display) + * @return the physical horizontal resolution of the display + */ +int32_t lv_display_get_physical_horizontal_resolution(const lv_display_t * disp); + +/** + * Get the physical vertical resolution of a display + * @param disp pointer to a display (NULL to use the default display) + * @return the physical vertical resolution of the display + */ +int32_t lv_display_get_physical_vertical_resolution(const lv_display_t * disp); + +/** + * Get the horizontal offset from the full / physical display + * @param disp pointer to a display (NULL to use the default display) + * @return the horizontal offset from the physical display + */ +int32_t lv_display_get_offset_x(const lv_display_t * disp); + +/** + * Get the vertical offset from the full / physical display + * @param disp pointer to a display (NULL to use the default display) + * @return the horizontal offset from the physical display + */ +int32_t lv_display_get_offset_y(const lv_display_t * disp); + +/** + * Get the current rotation of this display. + * @param disp pointer to a display (NULL to use the default display) + * @return the current rotation + */ +lv_display_rotation_t lv_display_get_rotation(lv_display_t * disp); + +/** + * Get the DPI of the display + * @param disp pointer to a display (NULL to use the default display) + * @return dpi of the display + */ +int32_t lv_display_get_dpi(const lv_display_t * disp); + +/*--------------------- + * BUFFERING + *--------------------*/ + +/** + * Set the buffers for a display, similarly to `lv_display_set_draw_buffers`, but accept the raw buffer pointers. + * @param disp pointer to a display + * @param buf1 first buffer + * @param buf2 second buffer (can be `NULL`) + * @param buf_size buffer size in byte + * @param render_mode LV_DISPLAY_RENDER_MODE_PARTIAL/DIRECT/FULL + */ +void lv_display_set_buffers(lv_display_t * disp, void * buf1, void * buf2, uint32_t buf_size, + lv_display_render_mode_t render_mode); + +/** + * Set the buffers for a display, accept a draw buffer pointer. + * Normally use `lv_display_set_buffers` is enough for most cases. + * Use this function when an existing lv_draw_buf_t is available. + * @param disp pointer to a display + * @param buf1 first buffer + * @param buf2 second buffer (can be `NULL`) + */ +void lv_display_set_draw_buffers(lv_display_t * disp, lv_draw_buf_t * buf1, lv_draw_buf_t * buf2); + +/** + * Set display render mode + * @param disp pointer to a display + * @param render_mode LV_DISPLAY_RENDER_MODE_PARTIAL/DIRECT/FULL + */ +void lv_display_set_render_mode(lv_display_t * disp, lv_display_render_mode_t render_mode); + +/** + * Set the flush callback which will be called to copy the rendered image to the display. + * @param disp pointer to a display + * @param flush_cb the flush callback (`px_map` contains the rendered image as raw pixel map and it should be copied to `area` on the display) + */ +void lv_display_set_flush_cb(lv_display_t * disp, lv_display_flush_cb_t flush_cb); + +/** + * Set a callback to be used while LVGL is waiting flushing to be finished. + * It can do any complex logic to wait, including semaphores, mutexes, polling flags, etc. + * If not set the `disp->flushing` flag is used which can be cleared with `lv_display_flush_ready()` + * @param disp pointer to a display + * @param wait_cb a callback to call while LVGL is waiting for flush ready. + * If NULL `lv_display_flush_ready()` can be used to signal that flushing is ready. + */ +void lv_display_set_flush_wait_cb(lv_display_t * disp, lv_display_flush_wait_cb_t wait_cb); + +/** + * Set the color format of the display. + * @param disp pointer to a display + * @param color_format Possible values are + * - LV_COLOR_FORMAT_RGB565 + * - LV_COLOR_FORMAT_RGB888 + * - LV_COLOR_FORMAT_XRGB888 + * - LV_COLOR_FORMAT_ARGB888 + *@note To change the endianness of the rendered image in case of RGB565 format + * (i.e. swap the 2 bytes) call `lv_draw_sw_rgb565_swap` in the flush_cb + */ +void lv_display_set_color_format(lv_display_t * disp, lv_color_format_t color_format); + +/** + * Get the color format of the display + * @param disp pointer to a display + * @return the color format + */ +lv_color_format_t lv_display_get_color_format(lv_display_t * disp); + +/** + * Enable anti-aliasing for the render engine + * @param disp pointer to a display + * @param en true/false + */ +void lv_display_set_antialiasing(lv_display_t * disp, bool en); + +/** + * Get if anti-aliasing is enabled for a display or not + * @param disp pointer to a display (NULL to use the default display) + * @return true/false + */ +bool lv_display_get_antialiasing(lv_display_t * disp); + +//! @cond Doxygen_Suppress + +/** + * Call from the display driver when the flushing is finished + * @param disp pointer to display whose `flush_cb` was called + */ +LV_ATTRIBUTE_FLUSH_READY void lv_display_flush_ready(lv_display_t * disp); + +/** + * Tell if it's the last area of the refreshing process. + * Can be called from `flush_cb` to execute some special display refreshing if needed when all areas area flushed. + * @param disp pointer to display + * @return true: it's the last area to flush; + * false: there are other areas too which will be refreshed soon + */ +LV_ATTRIBUTE_FLUSH_READY bool lv_display_flush_is_last(lv_display_t * disp); + +//! @endcond + +bool lv_display_is_double_buffered(lv_display_t * disp); + +/*--------------------- + * SCREENS + *--------------------*/ + +/** + * Return a pointer to the active screen on a display + * @param disp pointer to display which active screen should be get. + * (NULL to use the default screen) + * @return pointer to the active screen object (loaded by 'lv_screen_load()') + */ +lv_obj_t * lv_display_get_screen_active(lv_display_t * disp); + +/** + * Return with a pointer to the previous screen. Only used during screen transitions. + * @param disp pointer to display which previous screen should be get. + * (NULL to use the default screen) + * @return pointer to the previous screen object or NULL if not used now + */ +lv_obj_t * lv_display_get_screen_prev(lv_display_t * disp); + +/** + * Return the top layer. The top layer is the same on all screens and it is above the normal screen layer. + * @param disp pointer to display which top layer should be get. (NULL to use the default screen) + * @return pointer to the top layer object + */ +lv_obj_t * lv_display_get_layer_top(lv_display_t * disp); + +/** + * Return the sys. layer. The system layer is the same on all screen and it is above the normal screen and the top layer. + * @param disp pointer to display which sys. layer should be retrieved. (NULL to use the default screen) + * @return pointer to the sys layer object + */ +lv_obj_t * lv_display_get_layer_sys(lv_display_t * disp); + +/** + * Return the bottom layer. The bottom layer is the same on all screen and it is under the normal screen layer. + * It's visible only if the the screen is transparent. + * @param disp pointer to display (NULL to use the default screen) + * @return pointer to the bottom layer object + */ +lv_obj_t * lv_display_get_layer_bottom(lv_display_t * disp); + +/** + * Load a screen on the default display + * @param scr pointer to a screen + */ +void lv_screen_load(struct _lv_obj_t * scr); + +/** + * Switch screen with animation + * @param scr pointer to the new screen to load + * @param anim_type type of the animation from `lv_screen_load_anim_t`, e.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT` + * @param time time of the animation + * @param delay delay before the transition + * @param auto_del true: automatically delete the old screen + */ +void lv_screen_load_anim(lv_obj_t * scr, lv_screen_load_anim_t anim_type, uint32_t time, uint32_t delay, + bool auto_del); + +/** + * Get the active screen of the default display + * @return pointer to the active screen + */ +static inline lv_obj_t * lv_screen_active(void) +{ + return lv_display_get_screen_active(lv_display_get_default()); +} + +/** + * Get the top layer of the default display + * @return pointer to the top layer + */ +static inline lv_obj_t * lv_layer_top(void) +{ + return lv_display_get_layer_top(lv_display_get_default()); +} + +/** + * Get the system layer of the default display + * @return pointer to the sys layer + */ +static inline lv_obj_t * lv_layer_sys(void) +{ + return lv_display_get_layer_sys(lv_display_get_default()); +} + +/** + * Get the bottom layer of the default display + * @return pointer to the bottom layer + */ +static inline lv_obj_t * lv_layer_bottom(void) +{ + return lv_display_get_layer_bottom(lv_display_get_default()); +} + +/*--------------------- + * OTHERS + *--------------------*/ + +/** + * Add an event handler to the display + * @param disp pointer to a display + * @param event_cb an event callback + * @param filter event code to react or `LV_EVENT_ALL` + * @param user_data optional user_data + */ +void lv_display_add_event_cb(lv_display_t * disp, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data); + +/** + * Get the number of event attached to a display + * @param disp pointer to a display + * @return number of events + */ +uint32_t lv_display_get_event_count(lv_display_t * disp); + +/** + * Get an event descriptor for an event + * @param disp pointer to a display + * @param index the index of the event + * @return the event descriptor + */ +lv_event_dsc_t * lv_display_get_event_dsc(lv_display_t * disp, uint32_t index); + +/** + * Remove an event + * @param disp pointer to a display + * @param index the index of the event to remove + * @return true: and event was removed; false: no event was removed + */ +bool lv_display_delete_event(lv_display_t * disp, uint32_t index); + +/** + * Remove an event_cb with user_data + * @param disp pointer to a display + * @param event_cb the event_cb of the event to remove + * @param user_data user_data + * @return the count of the event removed + */ +uint32_t lv_display_remove_event_cb_with_user_data(lv_display_t * disp, lv_event_cb_t event_cb, void * user_data); + +/** + * Send an event to a display + * @param disp pointer to a display + * @param code an event code. LV_EVENT_... + * @param param optional param + * @return LV_RESULT_OK: disp wasn't deleted in the event. + */ +lv_result_t lv_display_send_event(lv_display_t * disp, lv_event_code_t code, void * param); + +/** + * Set the theme of a display. If there are no user created widgets yet the screens' theme will be updated + * @param disp pointer to a display + * @param th pointer to a theme + */ +void lv_display_set_theme(lv_display_t * disp, lv_theme_t * th); + +/** + * Get the theme of a display + * @param disp pointer to a display + * @return the display's theme (can be NULL) + */ +lv_theme_t * lv_display_get_theme(lv_display_t * disp); + +/** + * Get elapsed time since last user activity on a display (e.g. click) + * @param disp pointer to a display (NULL to get the overall smallest inactivity) + * @return elapsed ticks (milliseconds) since the last activity + */ +uint32_t lv_display_get_inactive_time(const lv_display_t * disp); + +/** + * Manually trigger an activity on a display + * @param disp pointer to a display (NULL to use the default display) + */ +void lv_display_trigger_activity(lv_display_t * disp); + +/** + * Temporarily enable and disable the invalidation of the display. + * @param disp pointer to a display (NULL to use the default display) + * @param en true: enable invalidation; false: invalidation + */ +void lv_display_enable_invalidation(lv_display_t * disp, bool en); + +/** + * Get display invalidation is enabled. + * @param disp pointer to a display (NULL to use the default display) + * @return return true if invalidation is enabled + */ +bool lv_display_is_invalidation_enabled(lv_display_t * disp); + +/** + * Get a pointer to the screen refresher timer to + * modify its parameters with `lv_timer_...` functions. + * @param disp pointer to a display + * @return pointer to the display refresher timer. (NULL on error) + */ +lv_timer_t * lv_display_get_refr_timer(lv_display_t * disp); + +/** + * Delete screen refresher timer + * @param disp pointer to a display + */ +void lv_display_delete_refr_timer(lv_display_t * disp); + +void lv_display_set_user_data(lv_display_t * disp, void * user_data); +void lv_display_set_driver_data(lv_display_t * disp, void * driver_data); +void * lv_display_get_user_data(lv_display_t * disp); +void * lv_display_get_driver_data(lv_display_t * disp); + +/********************** + * MACROS + **********************/ + +/*------------------------------------------------ + * To improve backward compatibility + * Recommended only if you have one display + *------------------------------------------------*/ + +#ifndef LV_HOR_RES +/** + * The horizontal resolution of the currently active display. + */ +#define LV_HOR_RES lv_display_get_horizontal_resolution(lv_display_get_default()) +#endif + +#ifndef LV_VER_RES +/** + * The vertical resolution of the currently active display. + */ +#define LV_VER_RES lv_display_get_vertical_resolution(lv_display_get_default()) +#endif + +/** + * Same as Android's DIP. (Different name is chosen to avoid mistype between LV_DPI and LV_DIP) + * 1 dip is 1 px on a 160 DPI screen + * 1 dip is 2 px on a 320 DPI screen + * https://stackoverflow.com/questions/2025282/what-is-the-difference-between-px-dip-dp-and-sp + */ +#define _LV_DPX_CALC(dpi, n) ((n) == 0 ? 0 :LV_MAX((( (dpi) * (n) + 80) / 160), 1)) /*+80 for rounding*/ +#define LV_DPX(n) _LV_DPX_CALC(lv_display_get_dpi(NULL), n) + +/** + * Scale the given number of pixels (a distance or size) relative to a 160 DPI display + * considering the DPI of the default display. + * It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the + * DPI of the display. + * @param n the number of pixels to scale + * @return `n x current_dpi/160` + */ +static inline int32_t lv_dpx(int32_t n) +{ + return LV_DPX(n); +} + +/** + * Scale the given number of pixels (a distance or size) relative to a 160 DPI display + * considering the DPI of the given display. + * It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the + * DPI of the display. + * @param disp a display whose dpi should be considered + * @param n the number of pixels to scale + * @return `n x current_dpi/160` + */ +static inline int32_t lv_display_dpx(const lv_display_t * disp, int32_t n) +{ + return _LV_DPX_CALC(lv_display_get_dpi(disp), n); +} + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DISPLAY_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/display/lv_display_private.h b/lib/libesp32_lvgl/lvgl/src/display/lv_display_private.h new file mode 100644 index 000000000..c7d2569cf --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/display/lv_display_private.h @@ -0,0 +1,165 @@ +/** + * @file lv_display_private.h + * + */ + +#ifndef LV_DISPLAY_PRIVATE_H +#define LV_DISPLAY_PRIVATE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../misc/lv_types.h" +#include "../core/lv_obj.h" +#include "../draw/lv_draw.h" +#include "lv_display.h" + +/********************* + * DEFINES + *********************/ +#ifndef LV_INV_BUF_SIZE +#define LV_INV_BUF_SIZE 32 /*Buffer size for invalid areas*/ +#endif + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_display_t { + + /*--------------------- + * Resolution + *--------------------*/ + + /** Horizontal resolution.*/ + int32_t hor_res; + + /** Vertical resolution.*/ + int32_t ver_res; + + /** Horizontal resolution of the full / physical display. Set to -1 for fullscreen mode.*/ + int32_t physical_hor_res; + + /** Vertical resolution of the full / physical display. Set to -1 for fullscreen mode.*/ + int32_t physical_ver_res; + + /** Horizontal offset from the full / physical display. Set to 0 for fullscreen mode.*/ + int32_t offset_x; + + /** Vertical offset from the full / physical display. Set to 0 for fullscreen mode.*/ + int32_t offset_y; + + uint32_t dpi; /** DPI (dot per inch) of the display. Default value is `LV_DPI_DEF`.*/ + + /*--------------------- + * Buffering + *--------------------*/ + lv_draw_buf_t * buf_1; + lv_draw_buf_t * buf_2; + + /** Internal, used by the library*/ + lv_draw_buf_t * buf_act; + + /** MANDATORY: Write the internal buffer (draw_buf) to the display. 'lv_display_flush_ready()' has to be + * called when finished*/ + lv_display_flush_cb_t flush_cb; + + /** + * Used to wait while flushing is ready. + * It can do any complex logic to wait, including semaphores, mutexes, polling flags, etc. + * If not set `flushing` flag is used which can be cleared with `lv_display_flush_ready()`*/ + lv_display_flush_wait_cb_t flush_wait_cb; + + /*1: flushing is in progress. (It can't be a bit field because when it's cleared from IRQ Read-Modify-Write issue might occur)*/ + volatile int flushing; + + /*1: It was the last chunk to flush. (It can't be a bit field because when it's cleared from IRQ Read-Modify-Write issue might occur)*/ + volatile int flushing_last; + volatile uint32_t last_area : 1; /*1: the last area is being rendered*/ + volatile uint32_t last_part : 1; /*1: the last part of the current area is being rendered*/ + + lv_display_render_mode_t render_mode; + uint32_t antialiasing : 1; /**< 1: anti-aliasing is enabled on this display.*/ + + /** 1: The current screen rendering is in progress*/ + uint32_t rendering_in_progress : 1; + + lv_color_format_t color_format; + + /** Invalidated (marked to redraw) areas*/ + lv_area_t inv_areas[LV_INV_BUF_SIZE]; + uint8_t inv_area_joined[LV_INV_BUF_SIZE]; + uint32_t inv_p; + int32_t inv_en_cnt; + + /** Double buffer sync areas (redrawn during last refresh) */ + lv_ll_t sync_areas; + + lv_draw_buf_t _static_buf1; /*Used when user pass in a raw buffer as display draw buffer*/ + lv_draw_buf_t _static_buf2; + /*--------------------- + * Layer + *--------------------*/ + lv_layer_t * layer_head; + void (*layer_init)(lv_display_t * disp, lv_layer_t * layer); + void (*layer_deinit)(lv_display_t * disp, lv_layer_t * layer); + + /*--------------------- + * Screens + *--------------------*/ + + /** Screens of the display*/ + lv_obj_t ** screens; /**< Array of screen objects.*/ + lv_obj_t * act_scr; /**< Currently active screen on this display*/ + lv_obj_t * prev_scr; /**< Previous screen. Used during screen animations*/ + lv_obj_t * scr_to_load; /**< The screen prepared to load in lv_screen_load_anim*/ + lv_obj_t * bottom_layer; /**< @see lv_display_get_layer_bottom*/ + lv_obj_t * top_layer; /**< @see lv_display_get_layer_top*/ + lv_obj_t * sys_layer; /**< @see lv_display_get_layer_sys*/ + uint32_t screen_cnt; + uint8_t draw_prev_over_act : 1;/** 1: Draw previous screen over active screen*/ + uint8_t del_prev : 1; /** 1: Automatically delete the previous screen when the screen load animation is ready*/ + + /*--------------------- + * Others + *--------------------*/ + + void * driver_data; /**< Custom user data*/ + + void * user_data; /**< Custom user data*/ + + lv_event_list_t event_list; + + uint32_t sw_rotate : 1; /**< 1: use software rotation (slower)*/ + uint32_t rotation : 2; /**< Element of @lv_display_rotation_t*/ + + /**< The theme assigned to the screen*/ + lv_theme_t * theme; + + /** A timer which periodically checks the dirty areas and refreshes them*/ + lv_timer_t * refr_timer; + + /*Miscellaneous data*/ + uint32_t last_activity_time; /**< Last time when there was activity on this display*/ + + /** The area being refreshed*/ + lv_area_t refreshed_area; +}; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DISPLAY_PRIVATE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_draw_arm2d.mk b/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_draw_arm2d.mk deleted file mode 100644 index 17219b07e..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_draw_arm2d.mk +++ /dev/null @@ -1,6 +0,0 @@ -CSRCS += lv_gpu_arm2d.c - -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d" diff --git a/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_gpu_arm2d.c b/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_gpu_arm2d.c deleted file mode 100644 index cc1ef6083..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_gpu_arm2d.c +++ /dev/null @@ -1,1574 +0,0 @@ -/** - * @file lv_gpu_arm2d.c - * - */ - -/* - * Copyright (C) 2010-2023 Arm Limited or its affiliates. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/********************* - * INCLUDES - *********************/ -#if defined(__clang__) - #pragma clang diagnostic ignored "-Wunknown-warning-option" - #pragma clang diagnostic ignored "-Wreserved-identifier" - #pragma clang diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers" - #pragma clang diagnostic ignored "-Wmissing-variable-declarations" - #pragma clang diagnostic ignored "-Wcast-qual" - #pragma clang diagnostic ignored "-Wcast-align" - #pragma clang diagnostic ignored "-Wextra-semi-stmt" - #pragma clang diagnostic ignored "-Wsign-conversion" - #pragma clang diagnostic ignored "-Wunused-function" - #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" - #pragma clang diagnostic ignored "-Wdouble-promotion" - #pragma clang diagnostic ignored "-Wunused-parameter" - #pragma clang diagnostic ignored "-Wimplicit-float-conversion" - #pragma clang diagnostic ignored "-Wimplicit-int-conversion" - #pragma clang diagnostic ignored "-Wtautological-pointer-compare" - #pragma clang diagnostic ignored "-Wsign-compare" - #pragma clang diagnostic ignored "-Wfloat-conversion" - #pragma clang diagnostic ignored "-Wmissing-prototypes" - #pragma clang diagnostic ignored "-Wpadded" - #pragma clang diagnostic ignored "-Wundef" - #pragma clang diagnostic ignored "-Wdeclaration-after-statement" - #pragma clang diagnostic ignored "-Wdisabled-macro-expansion" - #pragma clang diagnostic ignored "-Wunused-variable" - #pragma clang diagnostic ignored "-Wunused-but-set-variable" - #pragma clang diagnostic ignored "-Wint-conversion" -#endif - - -#include "lv_gpu_arm2d.h" -#include "../../core/lv_refr.h" - -#if LV_USE_GPU_ARM2D -#define __ARM_2D_IMPL__ -#include "arm_2d.h" -#include "__arm_2d_impl.h" - - -#if defined(__IS_COMPILER_ARM_COMPILER_5__) - #pragma diag_suppress 174,177,188,68,513,144,1296 -#elif defined(__IS_COMPILER_IAR__) - #pragma diag_suppress=Pa093 -#elif defined(__IS_COMPILER_GCC__) - #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" -#endif - -/********************* - * DEFINES - *********************/ -#if ( !defined(__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) \ - || !__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) \ -&& LV_COLOR_DEPTH == 32 \ -&& !defined(__ARM_2D_LVGL_CFG_NO_WARNING__) -#warning Please set macro __ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__ to 1 to get more acceleration opportunities. Or you can define macro __ARM_2D_LVGL_CFG_NO_WARNING__ to suppress this warning. -#endif - -#define MAX_BUF_SIZE (uint32_t) lv_disp_get_hor_res(_lv_refr_get_disp_refreshing()) - -#if LV_COLOR_DEPTH == 16 -#define arm_2d_fill_colour arm_2d_rgb16_fill_colour -#define arm_2d_fill_colour_with_alpha arm_2d_rgb565_fill_colour_with_alpha -#define arm_2d_fill_colour_with_mask arm_2d_rgb565_fill_colour_with_mask -#define arm_2d_fill_colour_with_mask_and_opacity \ - arm_2d_rgb565_fill_colour_with_mask_and_opacity -#define arm_2d_tile_copy arm_2d_rgb16_tile_copy -#define arm_2d_alpha_blending arm_2d_rgb565_alpha_blending -#define arm_2d_tile_copy_with_src_mask arm_2d_rgb565_tile_copy_with_src_mask -#define arm_2d_color_t arm_2d_color_rgb565_t - -/* arm-2d direct mode apis */ -#define __arm_2d_impl_colour_filling __arm_2d_impl_rgb16_colour_filling -#define __arm_2d_impl_colour_filling_with_opacity \ - __arm_2d_impl_rgb565_colour_filling_with_opacity -#define __arm_2d_impl_colour_filling_mask \ - __arm_2d_impl_rgb565_colour_filling_mask -#define __arm_2d_impl_colour_filling_mask_opacity \ - __arm_2d_impl_rgb565_colour_filling_mask_opacity -#define __arm_2d_impl_copy __arm_2d_impl_rgb16_copy -#define __arm_2d_impl_alpha_blending __arm_2d_impl_rgb565_alpha_blending -#define __arm_2d_impl_src_msk_copy __arm_2d_impl_rgb565_src_msk_copy -#define __arm_2d_impl_src_chn_msk_copy __arm_2d_impl_rgb565_src_chn_msk_copy -#define __arm_2d_impl_cl_key_copy __arm_2d_impl_rgb16_cl_key_copy -#define __arm_2d_impl_alpha_blending_colour_keying \ - __arm_2d_impl_rgb565_alpha_blending_colour_keying -#define arm_2d_tile_transform_with_src_mask_and_opacity_prepare \ - arm_2dp_rgb565_tile_transform_with_src_mask_and_opacity_prepare -#define arm_2d_tile_transform_with_opacity_prepare \ - arm_2dp_rgb565_tile_transform_with_opacity_prepare -#define arm_2d_tile_transform_only_with_opacity_prepare \ - arm_2dp_rgb565_tile_transform_only_with_opacity_prepare -#define arm_2d_tile_transform_prepare \ - arm_2dp_rgb565_tile_transform_prepare - -#define __ARM_2D_PIXEL_BLENDING_OPA __ARM_2D_PIXEL_BLENDING_OPA_RGB565 - -#define color_int uint16_t - -#elif LV_COLOR_DEPTH == 32 -#define arm_2d_fill_colour arm_2d_rgb32_fill_colour -#define arm_2d_fill_colour_with_alpha arm_2d_cccn888_fill_colour_with_alpha -#define arm_2d_fill_colour_with_mask arm_2d_cccn888_fill_colour_with_mask -#define arm_2d_fill_colour_with_mask_and_opacity \ - arm_2d_cccn888_fill_colour_with_mask_and_opacity -#define arm_2d_tile_copy arm_2d_rgb32_tile_copy -#define arm_2d_alpha_blending arm_2d_cccn888_alpha_blending -#define arm_2d_tile_copy_with_src_mask arm_2d_cccn888_tile_copy_with_src_mask -#define arm_2d_color_t arm_2d_color_cccn888_t - -/* arm-2d direct mode apis */ -#define __arm_2d_impl_colour_filling __arm_2d_impl_rgb32_colour_filling -#define __arm_2d_impl_colour_filling_with_opacity \ - __arm_2d_impl_cccn888_colour_filling_with_opacity -#define __arm_2d_impl_colour_filling_mask \ - __arm_2d_impl_cccn888_colour_filling_mask -#define __arm_2d_impl_colour_filling_mask_opacity \ - __arm_2d_impl_cccn888_colour_filling_mask_opacity -#define __arm_2d_impl_copy __arm_2d_impl_rgb32_copy -#define __arm_2d_impl_alpha_blending __arm_2d_impl_cccn888_alpha_blending -#define __arm_2d_impl_src_msk_copy __arm_2d_impl_cccn888_src_msk_copy -#define __arm_2d_impl_src_chn_msk_copy __arm_2d_impl_cccn888_src_chn_msk_copy -#define __arm_2d_impl_cl_key_copy __arm_2d_impl_rgb32_cl_key_copy -#define __arm_2d_impl_alpha_blending_colour_keying \ - __arm_2d_impl_cccn888_alpha_blending_colour_keying -#define arm_2d_tile_transform_with_src_mask_and_opacity_prepare \ - arm_2dp_cccn888_tile_transform_with_src_mask_and_opacity_prepare -#define arm_2d_tile_transform_with_opacity_prepare \ - arm_2dp_cccn888_tile_transform_with_opacity_prepare -#define arm_2d_tile_transform_only_with_opacity_prepare \ - arm_2dp_cccn888_tile_transform_only_with_opacity_prepare -#define arm_2d_tile_transform_prepare \ - arm_2dp_cccn888_tile_transform_prepare - -#define __ARM_2D_PIXEL_BLENDING_OPA __ARM_2D_PIXEL_BLENDING_OPA_CCCN888 - -#define color_int uint32_t - -#else -#error The specified LV_COLOR_DEPTH is not supported by this version of lv_gpu_arm2d.c. -#endif - -/* *INDENT-OFF* */ -#define __PREPARE_LL_ACCELERATION__() \ - int32_t src_stride = lv_area_get_width(coords); \ - \ - uint8_t px_size_byte = cf == LV_IMG_CF_TRUE_COLOR_ALPHA \ - ? LV_IMG_PX_SIZE_ALPHA_BYTE \ - : sizeof(lv_color_t); \ - \ - const uint8_t * src_buf_tmp = src_buf; \ - src_buf_tmp += src_stride \ - * (draw_area.y1 - coords->y1) \ - * px_size_byte; \ - src_buf_tmp += (draw_area.x1 - coords->x1) * px_size_byte; \ - \ - lv_area_t blend_area2; \ - if(!_lv_area_intersect(&blend_area2, \ - &draw_area, \ - draw_ctx->clip_area)) return; \ - \ - int32_t w = lv_area_get_width(&blend_area2); \ - int32_t h = lv_area_get_height(&blend_area2); \ - \ - lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); \ - \ - lv_color_t * dest_buf = draw_ctx->buf; \ - dest_buf += dest_stride * (blend_area2.y1 - draw_ctx->buf_area->y1) \ - + (blend_area2.x1 - draw_ctx->buf_area->x1); \ - \ - arm_2d_size_t copy_size = { \ - .iWidth = lv_area_get_width(&blend_area2), \ - .iHeight = lv_area_get_height(&blend_area2), \ - } - -#define __PREPARE_TARGET_TILE__(__blend_area) \ - static arm_2d_tile_t target_tile; \ - static arm_2d_region_t target_region; \ - \ - lv_color_t * dest_buf = draw_ctx->buf; \ - \ - target_tile = (arm_2d_tile_t) { \ - .tRegion = { \ - .tSize = { \ - .iWidth = lv_area_get_width(draw_ctx->buf_area), \ - .iHeight = lv_area_get_height(draw_ctx->buf_area), \ - }, \ - }, \ - .tInfo.bIsRoot = true, \ - .phwBuffer = (uint16_t *)draw_ctx->buf, \ - }; \ - \ - target_region = (arm_2d_region_t) { \ - .tLocation = { \ - .iX = (__blend_area).x1 - draw_ctx->buf_area->x1, \ - .iY = (__blend_area).y1 - draw_ctx->buf_area->y1, \ - }, \ - .tSize = { \ - .iWidth = lv_area_get_width(&(__blend_area)), \ - .iHeight = lv_area_get_height(&(__blend_area)), \ - }, \ - } - -#define __PREPARE_SOURCE_TILE__(__dsc, __blend_area) \ - static arm_2d_tile_t source_tile_orig; \ - static arm_2d_tile_t source_tile; \ - const lv_color_t * src_buf = (__dsc)->src_buf; \ - if (src_buf) { \ - source_tile_orig = (arm_2d_tile_t) { \ - .tRegion = { \ - .tSize = { \ - .iWidth = lv_area_get_width((__dsc)->blend_area), \ - .iHeight = lv_area_get_height((__dsc)->blend_area), \ - }, \ - }, \ - .tInfo.bIsRoot = true, \ - .phwBuffer = (uint16_t *)src_buf, \ - }; \ - \ - arm_2d_tile_generate_child( \ - &source_tile_orig, \ - (arm_2d_region_t []) { \ - { \ - .tLocation = { \ - .iX = (__blend_area).x1 - (__dsc)->blend_area->x1, \ - .iY = (__blend_area).y1 - (__dsc)->blend_area->y1, \ - }, \ - .tSize = source_tile_orig.tRegion.tSize, \ - } \ - }, \ - &source_tile, \ - false); \ - source_tile.tInfo.bDerivedResource = true; \ - } - -#define __PREPARE_MASK_TILE__(__dsc, __blend_area, __mask, __is_chn) \ - static arm_2d_tile_t mask_tile_orig; \ - static arm_2d_tile_t mask_tile; \ - if(NULL != (__mask)) { \ - mask_tile_orig = (arm_2d_tile_t) { \ - .tRegion = { \ - .tSize = { \ - .iWidth = lv_area_get_width((__dsc)->mask_area), \ - .iHeight = lv_area_get_height((__dsc)->mask_area), \ - }, \ - }, \ - .tInfo = { \ - .bIsRoot = true, \ - .bHasEnforcedColour = true, \ - .tColourInfo = { \ - .chScheme = (__is_chn) ? ARM_2D_CHANNEL_8in32 \ - : ARM_2D_COLOUR_8BIT, \ - }, \ - }, \ - .pchBuffer = ((uint8_t *)(__mask)) + (__is_chn) ? 3 : 0, \ - }; \ - \ - arm_2d_tile_generate_child( \ - &mask_tile_orig, \ - (arm_2d_region_t []) { \ - { \ - .tLocation = { \ - .iX = (__dsc)->mask_area->x1 - (__blend_area).x1, \ - .iY = (__dsc)->mask_area->y1 - (__blend_area).y1, \ - }, \ - .tSize = mask_tile_orig.tRegion.tSize, \ - } \ - }, \ - &mask_tile, \ - false); \ - mask_tile.tInfo.bDerivedResource = true; \ - } -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -#define __RECOLOUR_WRAPPER(...) \ - do { \ - lv_color_t *rgb_tmp_buf = NULL; \ - if(draw_dsc->recolor_opa > LV_OPA_MIN) { \ - rgb_tmp_buf \ - = lv_mem_buf_get(src_w * src_h * sizeof(lv_color_t)); \ - if (NULL == rgb_tmp_buf) { \ - LV_LOG_WARN( \ - "Failed to allocate memory for accelerating recolour, " \ - "use normal route instead."); \ - break; \ - } \ - lv_memcpy(rgb_tmp_buf, src_buf, src_w * src_h * sizeof(lv_color_t));\ - arm_2d_size_t copy_size = { \ - .iWidth = src_w, \ - .iHeight = src_h, \ - }; \ - /* apply re-colour */ \ - __arm_2d_impl_colour_filling_with_opacity( \ - (color_int *)rgb_tmp_buf, \ - src_w, \ - ©_size, \ - (color_int)draw_dsc->recolor.full, \ - draw_dsc->recolor_opa); \ - \ - /* replace src_buf for the following operation */ \ - src_buf = (const uint8_t *)rgb_tmp_buf; \ - } \ - do { \ - __VA_ARGS__ \ - } while(0); \ - if (NULL != rgb_tmp_buf) { \ - lv_mem_buf_release(rgb_tmp_buf); \ - } \ - } while(0); \ - src_buf = src_buf_org; - -#define __RECOLOUR_BEGIN() \ - do { \ - lv_color_t *rgb_tmp_buf = NULL; \ - if(draw_dsc->recolor_opa > LV_OPA_MIN) { \ - rgb_tmp_buf \ - = lv_mem_buf_get(src_w * src_h * sizeof(lv_color_t)); \ - if (NULL == rgb_tmp_buf) { \ - LV_LOG_WARN( \ - "Failed to allocate memory for accelerating recolour, " \ - "use normal route instead."); \ - break; \ - } \ - lv_memcpy(rgb_tmp_buf, src_buf, src_w * src_h * sizeof(lv_color_t));\ - arm_2d_size_t copy_size = { \ - .iWidth = src_w, \ - .iHeight = src_h, \ - }; \ - /* apply re-colour */ \ - __arm_2d_impl_colour_filling_with_opacity( \ - (color_int *)rgb_tmp_buf, \ - src_w, \ - ©_size, \ - (color_int)draw_dsc->recolor.full, \ - draw_dsc->recolor_opa); \ - \ - /* replace src_buf for the following operation */ \ - src_buf = (const uint8_t *)rgb_tmp_buf; \ - } \ - do { - -#define __RECOLOUR_END() \ - } while(0); \ - if (NULL != rgb_tmp_buf) { \ - lv_mem_buf_release(rgb_tmp_buf); \ - } \ - } while(0); \ - src_buf = src_buf_org; - -#define __ARM_2D_PREPARE_TRANS_AND_TARGET_REGION(__TRANS_PREPARE, ...) \ - do { \ - __TRANS_PREPARE( \ - NULL, \ - __VA_ARGS__); \ - \ - target_region = (arm_2d_region_t) { \ - .tLocation = { \ - .iX = coords->x1 - draw_ctx->clip_area->x1, \ - .iY = coords->y1 - draw_ctx->clip_area->y1, \ - }, \ - .tSize = { \ - .iWidth = lv_area_get_width(coords), \ - .iHeight = lv_area_get_height(coords), \ - }, \ - }; \ - \ - arm_2d_size_t tTransSize \ - = ARM_2D_CTRL.DefaultOP \ - .tTransform.Source.ptTile->tRegion.tSize; \ - \ - if (target_region.tSize.iWidth < tTransSize.iWidth) { \ - int16_t iDelta = tTransSize.iWidth - target_region.tSize.iWidth;\ - target_region.tLocation.iX -= iDelta / 2; \ - target_region.tSize.iWidth = tTransSize.iWidth; \ - } \ - \ - if (target_region.tSize.iHeight < tTransSize.iHeight) { \ - int16_t iDelta \ - = tTransSize.iHeight - target_region.tSize.iHeight; \ - target_region.tLocation.iY -= iDelta / 2; \ - target_region.tSize.iHeight = tTransSize.iHeight; \ - } \ - } while(0) - -/* *INDENT-ON* */ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -#if __ARM_2D_HAS_HW_ACC__ -static bool /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_arm2d_fill_colour(const arm_2d_tile_t * target_tile, - const arm_2d_region_t * region, - lv_color_t color, - lv_opa_t opa, - const arm_2d_tile_t * mask_tile); - -static bool /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_arm2d_tile_copy(const arm_2d_tile_t * target_tile, - const arm_2d_region_t * region, - arm_2d_tile_t * source_tile, - lv_opa_t opa, - arm_2d_tile_t * mask_tile); -#else - -static void convert_cb(const lv_area_t * dest_area, - const void * src_buf, - lv_coord_t src_w, - lv_coord_t src_h, - lv_coord_t src_stride, - const lv_draw_img_dsc_t * draw_dsc, - lv_img_cf_t cf, - lv_color_t * cbuf, - lv_opa_t * abuf); - -static bool /* LV_ATTRIBUTE_FAST_MEM */ arm_2d_fill_normal(lv_color_t * dest_buf, - const lv_area_t * dest_area, - lv_coord_t dest_stride, - lv_color_t color, - lv_opa_t opa, - const lv_opa_t * mask, - lv_coord_t mask_stride); - -static bool /* LV_ATTRIBUTE_FAST_MEM */ arm_2d_copy_normal(lv_color_t * dest_buf, - const lv_area_t * dest_area, - lv_coord_t dest_stride, - const lv_color_t * src_buf, - lv_coord_t src_stride, - lv_opa_t opa, - const lv_opa_t * mask, - lv_coord_t mask_stride); -#endif - -static void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx, - const lv_draw_sw_blend_dsc_t * dsc); -static void /* LV_ATTRIBUTE_FAST_MEM */ lv_gpu_arm2d_wait_cb(lv_draw_ctx_t * draw_ctx); -static void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx, - const lv_draw_img_dsc_t * draw_dsc, - const lv_area_t * coords, - const uint8_t * src_buf, - lv_img_cf_t cf); - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void lv_draw_arm2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) -{ - arm_2d_init(); - - lv_draw_sw_init_ctx(drv, draw_ctx); - - lv_draw_arm2d_ctx_t * arm2d_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx; - - arm2d_draw_ctx->blend = lv_draw_arm2d_blend; - arm2d_draw_ctx->base_draw.wait_for_finish = lv_gpu_arm2d_wait_cb; - -#if !__ARM_2D_HAS_HW_ACC__ - arm2d_draw_ctx->base_draw.draw_img_decoded = lv_draw_arm2d_img_decoded; -#endif - -} - -void lv_draw_arm2d_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) -{ - LV_UNUSED(drv); - LV_UNUSED(draw_ctx); -} - -extern void test_flush(lv_color_t * color_p); - -#if __ARM_2D_HAS_HW_ACC__ -static void LV_ATTRIBUTE_FAST_MEM lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx, - const lv_draw_sw_blend_dsc_t * dsc) -{ - const lv_opa_t * mask; - if(dsc->mask_buf == NULL) mask = NULL; - if(dsc->mask_buf && dsc->mask_res == LV_DRAW_MASK_RES_TRANSP) return; - else if(dsc->mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask = NULL; - else mask = dsc->mask_buf; - - - lv_area_t blend_area; - if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) { - return; - } - - bool is_accelerated = false; - - if(dsc->blend_mode == LV_BLEND_MODE_NORMAL - && lv_area_get_size(&blend_area) > 100) { - - __PREPARE_TARGET_TILE__(blend_area); - __PREPARE_SOURCE_TILE__(dsc, blend_area); - __PREPARE_MASK_TILE__(dsc, blend_area, mask, false); - - if(src_buf) { - is_accelerated = lv_draw_arm2d_tile_copy( - &target_tile, - &target_region, - &source_tile, - dsc->opa, - (NULL == mask) ? NULL : &mask_tile); - } - else { - is_accelerated = lv_draw_arm2d_fill_colour( - &target_tile, - &target_region, - dsc->color, - dsc->opa, - (NULL == mask) ? NULL : &mask_tile); - } - } - - if(!is_accelerated) { - lv_draw_sw_blend_basic(draw_ctx, dsc); - } -} - - -static bool LV_ATTRIBUTE_FAST_MEM lv_draw_arm2d_fill_colour(const arm_2d_tile_t * target_tile, - const arm_2d_region_t * region, - lv_color_t color, - lv_opa_t opa, - const arm_2d_tile_t * mask_tile) -{ - arm_fsm_rt_t result = (arm_fsm_rt_t)ARM_2D_ERR_NONE; - - if(NULL == mask_tile) { - if(opa >= LV_OPA_MAX) { - result = arm_2d_fill_colour(target_tile, region, color.full); - } - else { -#if LV_COLOR_SCREEN_TRANSP - return false; -#else - result = arm_2d_fill_colour_with_alpha( - target_tile, - region, - (arm_2d_color_t) { - color.full - }, - opa); -#endif - } - } - else { - - if(opa >= LV_OPA_MAX) { - result = arm_2d_fill_colour_with_mask( - target_tile, - region, - mask_tile, - (arm_2d_color_t) { - color.full - }); - } - else { -#if LV_COLOR_SCREEN_TRANSP - return false; -#else - result = arm_2d_fill_colour_with_mask_and_opacity( - target_tile, - region, - mask_tile, - (arm_2d_color_t) { - color.full - }, - opa); -#endif - } - } - - if(result < 0) { - /* error detected */ - return false; - } - - return true; - -} - -static bool LV_ATTRIBUTE_FAST_MEM lv_draw_arm2d_tile_copy(const arm_2d_tile_t * target_tile, - const arm_2d_region_t * region, - arm_2d_tile_t * source_tile, - lv_opa_t opa, - arm_2d_tile_t * mask_tile) -{ - arm_fsm_rt_t result = (arm_fsm_rt_t)ARM_2D_ERR_NONE; - - if(NULL == mask_tile) { - if(opa >= LV_OPA_MAX) { - result = arm_2d_tile_copy(source_tile, - target_tile, - region, - ARM_2D_CP_MODE_COPY); - } -#if LV_COLOR_SCREEN_TRANSP - else { - return false; /* not supported */ - } -#else - else { - result = arm_2d_alpha_blending(source_tile, - target_tile, - region, - opa); - } -#endif - } - else { -#if LV_COLOR_SCREEN_TRANSP - return false; /* not support */ -#else - - if(opa >= LV_OPA_MAX) { - result = arm_2d_tile_copy_with_src_mask(source_tile, - mask_tile, - target_tile, - region, - ARM_2D_CP_MODE_COPY); - } - else { - return false; - } -#endif - } - - if(result < 0) { - /* error detected */ - return false; - } - - return true; -} - -static void lv_gpu_arm2d_wait_cb(lv_draw_ctx_t * draw_ctx) -{ - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - - arm_2d_op_wait_async(NULL); - if(disp->driver && disp->driver->wait_cb) { - disp->driver->wait_cb(disp->driver); - } - lv_draw_sw_wait_for_finish(draw_ctx); -} -#else - - -static void LV_ATTRIBUTE_FAST_MEM lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx, - const lv_draw_sw_blend_dsc_t * dsc) -{ - const lv_opa_t * mask; - if(dsc->mask_buf == NULL) mask = NULL; - if(dsc->mask_buf && dsc->mask_res == LV_DRAW_MASK_RES_TRANSP) return; - else if(dsc->mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask = NULL; - else mask = dsc->mask_buf; - - lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); - - lv_area_t blend_area; - if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return; - - //lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - - bool is_accelerated = false; - do { - - /* target buffer */ - lv_color_t * dest_buf = draw_ctx->buf; - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - if(disp->driver->screen_transp == 0) { - dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + (blend_area.x1 - draw_ctx->buf_area->x1); - } - else { - /*With LV_COLOR_DEPTH 16 it means ARGB8565 (3 bytes format)*/ - uint8_t * dest_buf8 = (uint8_t *) dest_buf; - dest_buf8 += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) * LV_IMG_PX_SIZE_ALPHA_BYTE; - dest_buf8 += (blend_area.x1 - draw_ctx->buf_area->x1) * LV_IMG_PX_SIZE_ALPHA_BYTE; - dest_buf = (lv_color_t *)dest_buf8; - } - - /* source buffer */ - const lv_color_t * src_buf = dsc->src_buf; - lv_coord_t src_stride; - if(src_buf) { - src_stride = lv_area_get_width(dsc->blend_area); - src_buf += src_stride * (blend_area.y1 - dsc->blend_area->y1) + (blend_area.x1 - dsc->blend_area->x1); - } - else { - src_stride = 0; - } - - lv_coord_t mask_stride; - if(mask) { - mask_stride = lv_area_get_width(dsc->mask_area); - mask += mask_stride * (blend_area.y1 - dsc->mask_area->y1) + (blend_area.x1 - dsc->mask_area->x1); - } - else { - mask_stride = 0; - } - - lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - - if(disp->driver->screen_transp) { - break; - } - if(dsc->src_buf == NULL) { - if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { - is_accelerated = arm_2d_fill_normal(dest_buf, - &blend_area, - dest_stride, - dsc->color, - dsc->opa, - mask, - mask_stride); - } - } - else { - if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { - is_accelerated = arm_2d_copy_normal(dest_buf, - &blend_area, - dest_stride, - src_buf, - src_stride, - dsc->opa, - mask, - mask_stride); - } - } - } while(0); - - if(!is_accelerated) lv_draw_sw_blend_basic(draw_ctx, dsc); -} - -static bool LV_ATTRIBUTE_FAST_MEM arm_2d_fill_normal(lv_color_t * dest_buf, - const lv_area_t * dest_area, - lv_coord_t dest_stride, - lv_color_t color, - lv_opa_t opa, - const lv_opa_t * mask, - lv_coord_t mask_stride) -{ - arm_2d_size_t target_size = { - .iWidth = lv_area_get_width(dest_area), - .iHeight = lv_area_get_height(dest_area), - }; - - /*No mask*/ - if(mask == NULL) { - if(opa >= LV_OPA_MAX) { - __arm_2d_impl_colour_filling((color_int *)dest_buf, - dest_stride, - &target_size, - color.full); - } - /*Has opacity*/ - else { - __arm_2d_impl_colour_filling_with_opacity((color_int *)dest_buf, - dest_stride, - &target_size, - color.full, - opa); - } - } - /*Masked*/ - else { - /*Only the mask matters*/ - if(opa >= LV_OPA_MAX) { - __arm_2d_impl_colour_filling_mask((color_int *)dest_buf, - dest_stride, - (uint8_t *)mask, - mask_stride, - &target_size, - color.full); - } - /*With opacity*/ - else { - __arm_2d_impl_colour_filling_mask_opacity((color_int *)dest_buf, - dest_stride, - (uint8_t *)mask, - mask_stride, - &target_size, - color.full, - opa); - } - } - - return true; -} - - -static bool LV_ATTRIBUTE_FAST_MEM arm_2d_copy_normal(lv_color_t * dest_buf, - const lv_area_t * dest_area, - lv_coord_t dest_stride, - const lv_color_t * src_buf, - lv_coord_t src_stride, - lv_opa_t opa, - const lv_opa_t * mask, - lv_coord_t mask_stride) - -{ - int32_t w = lv_area_get_width(dest_area); - int32_t h = lv_area_get_height(dest_area); - - arm_2d_size_t copy_size = { - .iWidth = lv_area_get_width(dest_area), - .iHeight = lv_area_get_height(dest_area), - }; - - /*Simple fill (maybe with opacity), no masking*/ - if(mask == NULL) { - if(opa >= LV_OPA_MAX) { - __arm_2d_impl_copy((color_int *)src_buf, - src_stride, - (color_int *)dest_buf, - dest_stride, - ©_size); - } - else { - __arm_2d_impl_alpha_blending((color_int *)src_buf, - src_stride, - (color_int *)dest_buf, - dest_stride, - ©_size, - opa); - } - } - /*Masked*/ - else { - /*Only the mask matters*/ - if(opa > LV_OPA_MAX) { - __arm_2d_impl_src_msk_copy((color_int *)src_buf, - src_stride, - (uint8_t *)mask, - mask_stride, - ©_size, - (color_int *)dest_buf, - dest_stride, - ©_size); - } - /*Handle opa and mask values too*/ - else { - __arm_2d_impl_gray8_alpha_blending((uint8_t *)mask, - mask_stride, - (uint8_t *)mask, - mask_stride, - ©_size, - opa); - - __arm_2d_impl_src_msk_copy((color_int *)src_buf, - src_stride, - (uint8_t *)mask, - mask_stride, - ©_size, - (color_int *)dest_buf, - dest_stride, - ©_size); - } - } - - return true; -} - -static void LV_ATTRIBUTE_FAST_MEM lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx, - const lv_draw_img_dsc_t * draw_dsc, - const lv_area_t * coords, - const uint8_t * src_buf, - lv_img_cf_t cf) -{ - /*Use the clip area as draw area*/ - lv_area_t draw_area; - lv_area_copy(&draw_area, draw_ctx->clip_area); - const uint8_t * src_buf_org = src_buf; - - bool mask_any = lv_draw_mask_is_any(&draw_area); - bool transform = draw_dsc->angle != 0 || draw_dsc->zoom != LV_IMG_ZOOM_NONE ? true : false; - - lv_area_t blend_area; - lv_draw_sw_blend_dsc_t blend_dsc; - - lv_memset_00(&blend_dsc, sizeof(lv_draw_sw_blend_dsc_t)); - blend_dsc.opa = draw_dsc->opa; - blend_dsc.blend_mode = draw_dsc->blend_mode; - blend_dsc.blend_area = &blend_area; - - if(lv_img_cf_is_chroma_keyed(cf)) cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED; - else if(cf == LV_IMG_CF_ALPHA_8BIT) {} - else if(cf == LV_IMG_CF_RGB565A8) {} - else if(lv_img_cf_has_alpha(cf)) cf = LV_IMG_CF_TRUE_COLOR_ALPHA; - else cf = LV_IMG_CF_TRUE_COLOR; - - - /*The simplest case just copy the pixels into the draw_buf*/ - if(!mask_any && !transform && cf == LV_IMG_CF_TRUE_COLOR && draw_dsc->recolor_opa == LV_OPA_TRANSP) { - blend_dsc.src_buf = (const lv_color_t *)src_buf; - - blend_dsc.blend_area = coords; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - else if(!mask_any && !transform && cf == LV_IMG_CF_ALPHA_8BIT) { - lv_area_t clipped_coords; - if(!_lv_area_intersect(&clipped_coords, coords, draw_ctx->clip_area)) return; - - blend_dsc.mask_buf = (lv_opa_t *)src_buf; - blend_dsc.mask_area = coords; - blend_dsc.src_buf = NULL; - blend_dsc.color = draw_dsc->recolor; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - - blend_dsc.blend_area = coords; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } -#if LV_COLOR_DEPTH == 16 - else if(!mask_any && !transform && cf == LV_IMG_CF_RGB565A8 && draw_dsc->recolor_opa == LV_OPA_TRANSP && - blend_dsc.opa >= LV_OPA_MAX) { - lv_coord_t src_w = lv_area_get_width(coords); - lv_coord_t src_h = lv_area_get_height(coords); - blend_dsc.src_buf = (const lv_color_t *)src_buf; - blend_dsc.mask_buf = (lv_opa_t *)src_buf; - blend_dsc.mask_buf += sizeof(lv_color_t) * src_w * src_h; - blend_dsc.blend_area = coords; - blend_dsc.mask_area = coords; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } -#endif - /*In the other cases every pixel need to be checked one-by-one*/ - else { - blend_area.x1 = draw_ctx->clip_area->x1; - blend_area.x2 = draw_ctx->clip_area->x2; - blend_area.y1 = draw_ctx->clip_area->y1; - blend_area.y2 = draw_ctx->clip_area->y2; - - lv_coord_t src_w = lv_area_get_width(coords); - lv_coord_t src_h = lv_area_get_height(coords); - lv_coord_t blend_h = lv_area_get_height(&blend_area); - lv_coord_t blend_w = lv_area_get_width(&blend_area); - - uint32_t max_buf_size = MAX_BUF_SIZE; - uint32_t blend_size = lv_area_get_size(&blend_area); - uint32_t buf_h; - uint32_t buf_w = blend_w; - if(blend_size <= max_buf_size) { - buf_h = blend_h; - } - else { - /*Round to full lines*/ - buf_h = max_buf_size / blend_w; - } - - /*Create buffers and masks*/ - uint32_t buf_size = buf_w * buf_h; - - lv_color_t * rgb_buf = lv_mem_buf_get(buf_size * sizeof(lv_color_t)); - lv_opa_t * mask_buf = lv_mem_buf_get(buf_size); - blend_dsc.mask_buf = mask_buf; - blend_dsc.mask_area = &blend_area; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - blend_dsc.src_buf = rgb_buf; - lv_coord_t y_last = blend_area.y2; - blend_area.y2 = blend_area.y1 + buf_h - 1; - - lv_draw_mask_res_t mask_res_def = (cf != LV_IMG_CF_TRUE_COLOR || draw_dsc->angle || - draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? - LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; - blend_dsc.mask_res = mask_res_def; - - if(cf == LV_IMG_CF_ALPHA_8BIT) { - /* original code: - lv_color_fill(rgb_buf, draw_dsc->recolor, buf_size); - */ - arm_2d_size_t copy_size = { - .iWidth = buf_w, - .iHeight = buf_h, - }; - - /* apply re-colour */ - __arm_2d_impl_colour_filling( - (color_int *)rgb_buf, - buf_w, - ©_size, - (color_int)draw_dsc->recolor.full); - } - - bool is_accelerated = false; - - if(!transform) { - if(LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf) { - /* copy with colour keying */ - - /* *INDENT-OFF* */ - __RECOLOUR_WRAPPER( - - lv_color_t chrome_key = LV_COLOR_CHROMA_KEY; - /* calculate new chrome-key colour */ - if(draw_dsc->recolor_opa > LV_OPA_MIN) { - __ARM_2D_PIXEL_BLENDING_OPA( - (color_int *) & (draw_dsc->recolor.full), - (color_int *) & (chrome_key.full), - draw_dsc->recolor_opa - ); - } - - __PREPARE_LL_ACCELERATION__(); - - if(blend_dsc.opa >= LV_OPA_MAX) { - __arm_2d_impl_cl_key_copy( - (color_int *)src_buf_tmp, - src_stride, - (color_int *)dest_buf, - dest_stride, - ©_size, - (color_int)chrome_key.full); - } - else { - __arm_2d_impl_alpha_blending_colour_keying( - (color_int *)src_buf_tmp, - src_stride, - (color_int *)dest_buf, - dest_stride, - ©_size, - blend_dsc.opa, - (color_int)chrome_key.full); - } - is_accelerated = true; - ) - /* *INDENT-ON* */ - } - else if((LV_COLOR_DEPTH == 32) - && !mask_any - && (LV_IMG_CF_TRUE_COLOR_ALPHA == cf)) { - /* accelerate copy-with-source-masks-and-opacity */ - - /* *INDENT-OFF* */ - __RECOLOUR_WRAPPER( - __PREPARE_LL_ACCELERATION__(); - - uint8_t * mask_temp_buf = NULL; - if(blend_dsc.opa < LV_OPA_MAX) { - mask_temp_buf = lv_mem_buf_get(copy_size.iHeight * copy_size.iWidth); - if(NULL == mask_temp_buf) { - LV_LOG_WARN( - "Failed to allocate memory for alpha mask," - " use normal route instead."); - break; - } - lv_memset_00(mask_temp_buf, copy_size.iHeight * copy_size.iWidth); - - __arm_2d_impl_gray8_colour_filling_channel_mask_opacity( - mask_temp_buf, - src_stride, - (uint32_t *) - ((uintptr_t)src_buf_tmp + LV_IMG_PX_SIZE_ALPHA_BYTE - 1), - src_stride, - ©_size, - 0xFF, - blend_dsc.opa); - - __arm_2d_impl_src_msk_copy( - (color_int *)src_buf_tmp, - src_stride, - mask_temp_buf, - src_stride, - ©_size, - (color_int *)dest_buf, - dest_stride, - ©_size); - - lv_mem_buf_release(mask_temp_buf); - } - else { - __arm_2d_impl_src_chn_msk_copy( - (color_int *)src_buf_tmp, - src_stride, - (uint32_t *) - ((uintptr_t)src_buf_tmp + LV_IMG_PX_SIZE_ALPHA_BYTE - 1), - src_stride, - ©_size, - (color_int *)dest_buf, - dest_stride, - ©_size); - } - - is_accelerated = true; - ) - /* *INDENT-ON* */ - } - else if(!mask_any - && (LV_IMG_CF_RGB565A8 == cf)) { - /* accelerate copy-with-source-masks-and-opacity */ - - uint8_t * mask_after_rgb = src_buf + sizeof(lv_color_t) * src_w * src_h; - /* *INDENT-OFF* */ - __RECOLOUR_WRAPPER( - __PREPARE_LL_ACCELERATION__(); - - uint8_t * mask_temp_buf = NULL; - if(blend_dsc.opa < LV_OPA_MAX) { - mask_temp_buf = lv_mem_buf_get(copy_size.iHeight * copy_size.iWidth); - if(NULL == mask_temp_buf) { - LV_LOG_WARN( - "Failed to allocate memory for alpha mask," - " use normal route instead."); - break; - } - lv_memset_00(mask_temp_buf, copy_size.iHeight * copy_size.iWidth); - - __arm_2d_impl_gray8_colour_filling_mask_opacity( - mask_temp_buf, - src_stride, - mask_after_rgb, - src_stride, - ©_size, - 0xFF, - blend_dsc.opa); - - __arm_2d_impl_src_msk_copy( - (color_int *)src_buf_tmp, - src_stride, - mask_temp_buf, - src_stride, - ©_size, - (color_int *)dest_buf, - dest_stride, - ©_size); - - lv_mem_buf_release(mask_temp_buf); - } - else { - __arm_2d_impl_src_msk_copy( - (color_int *)src_buf_tmp, - src_stride, - mask_after_rgb, - src_stride, - ©_size, - (color_int *)dest_buf, - dest_stride, - ©_size); - } - - is_accelerated = true; - ) - /* *INDENT-ON* */ - } - else if(!mask_any && (cf == LV_IMG_CF_TRUE_COLOR)) { - /* accelerate copy-with-source-masks-and-opacity */ - - /* *INDENT-OFF* */ - __RECOLOUR_WRAPPER( - __PREPARE_LL_ACCELERATION__(); - - if(blend_dsc.opa >= LV_OPA_MAX) { - __arm_2d_impl_copy( - (color_int *)src_buf_tmp, - src_stride, - (color_int *)dest_buf, - dest_stride, - ©_size); - } - else { - __arm_2d_impl_alpha_blending( - (color_int *)src_buf_tmp, - src_stride, - (color_int *)dest_buf, - dest_stride, - ©_size, - blend_dsc.opa); - } - is_accelerated = true; - ) - /* *INDENT-ON* */ - } - } - else if(!mask_any -#if defined(__ARM_2D_HAS_ANTI_ALIAS_TRANSFORM__) && __ARM_2D_HAS_ANTI_ALIAS_TRANSFORM__ - && (draw_dsc->antialias == 1) -#else - && (draw_dsc->antialias == 0) -#endif - && (draw_dsc->recolor_opa == LV_OPA_TRANSP) - && (((LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf) - || (LV_IMG_CF_TRUE_COLOR == cf)) - || (LV_IMG_CF_RGB565A8 == cf) -#if defined(__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) && __ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__ - || ((LV_IMG_CF_TRUE_COLOR_ALPHA == cf) - && (LV_COLOR_DEPTH == 32)) -#endif - ) - ) { - - uint8_t * mask_after_rgb = src_buf + sizeof(lv_color_t) * src_w * src_h; - /* *INDENT-OFF* */ - __RECOLOUR_WRAPPER( - /* accelerate transform without re-color */ - - static arm_2d_tile_t target_tile_origin; - static arm_2d_tile_t target_tile; - arm_2d_region_t clip_region; - static arm_2d_region_t target_region; - - lv_color_t * dest_buf = draw_ctx->buf; - - target_tile_origin = (arm_2d_tile_t) { - .tRegion = { - .tSize = { - .iWidth = lv_area_get_width(draw_ctx->buf_area), - .iHeight = lv_area_get_height(draw_ctx->buf_area), - }, - }, - .tInfo.bIsRoot = true, - .phwBuffer = (uint16_t *)draw_ctx->buf, - }; - - clip_region = (arm_2d_region_t) { - .tLocation = { - .iX = draw_ctx->clip_area->x1 - draw_ctx->buf_area->x1, - .iY = draw_ctx->clip_area->y1 - draw_ctx->buf_area->y1, - }, - .tSize = { - .iWidth = lv_area_get_width(draw_ctx->clip_area), - .iHeight = lv_area_get_height(draw_ctx->clip_area), - }, - }; - - arm_2d_tile_generate_child(&target_tile_origin, - &clip_region, - &target_tile, - false); - - static arm_2d_tile_t source_tile; - - source_tile = (arm_2d_tile_t) { - .tRegion = { - .tSize = { - .iWidth = src_w, - .iHeight = src_h, - }, - }, - .tInfo.bIsRoot = true, - .pchBuffer = (uint8_t *)src_buf, - }; - - static arm_2d_location_t source_center, target_center; - source_center.iX = draw_dsc->pivot.x; - source_center.iY = draw_dsc->pivot.y; - - if(LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf) { - - __ARM_2D_PREPARE_TRANS_AND_TARGET_REGION( - arm_2d_tile_transform_with_opacity_prepare, - &source_tile, - source_center, - ARM_2D_ANGLE((draw_dsc->angle / 10.0f)), - draw_dsc->zoom / 256.0f, - (color_int)LV_COLOR_CHROMA_KEY.full, - blend_dsc.opa); - - arm_2d_tile_transform( - &target_tile, - &target_region, - NULL - ); - is_accelerated = true; - } - #if ARM_2D_VERISON >= 10103 - else if (LV_IMG_CF_TRUE_COLOR == cf) { - __ARM_2D_PREPARE_TRANS_AND_TARGET_REGION( - arm_2d_tile_transform_only_with_opacity_prepare, - &source_tile, - source_center, - ARM_2D_ANGLE((draw_dsc->angle / 10.0f)), - draw_dsc->zoom / 256.0f, - blend_dsc.opa); - - arm_2d_tile_transform( - &target_tile, - &target_region, - NULL - ); - is_accelerated = true; - } - #endif - else if (LV_IMG_CF_RGB565A8 == cf) { - static arm_2d_tile_t mask_tile; - mask_tile = source_tile; - - mask_tile.tInfo.bHasEnforcedColour = true; - mask_tile.tInfo.tColourInfo.chScheme = ARM_2D_COLOUR_GRAY8; - mask_tile.pchBuffer = mask_after_rgb; - - __ARM_2D_PREPARE_TRANS_AND_TARGET_REGION( - arm_2d_tile_transform_with_src_mask_and_opacity_prepare, - &source_tile, - &mask_tile, - source_center, - ARM_2D_ANGLE((draw_dsc->angle / 10.0f)), - draw_dsc->zoom / 256.0f, - blend_dsc.opa - ); - - arm_2d_tile_transform( - &target_tile, - &target_region, - NULL - ); - - is_accelerated = true; - } - #if defined(__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) \ - && __ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__ - else if((LV_IMG_CF_TRUE_COLOR_ALPHA == cf) && - (LV_COLOR_DEPTH == 32)) { - static arm_2d_tile_t mask_tile; - mask_tile = source_tile; - - mask_tile.tInfo.bHasEnforcedColour = true; - mask_tile.tInfo.tColourInfo.chScheme = ARM_2D_CHANNEL_8in32; - mask_tile.pchBuffer += 3; - - __ARM_2D_PREPARE_TRANS_AND_TARGET_REGION( - arm_2d_tile_transform_with_src_mask_and_opacity_prepare, - &source_tile, - &mask_tile, - source_center, - ARM_2D_ANGLE((draw_dsc->angle / 10.0f)), - draw_dsc->zoom / 256.0f, - blend_dsc.opa - ); - - arm_2d_tile_transform( - &target_tile, - &target_region, - NULL - ); - - is_accelerated = true; - } - #endif - ) - /* *INDENT-ON* */ - } - - /* *INDENT-OFF* */ - if(!is_accelerated) while(blend_area.y1 <= y_last) { - /*Apply transformations if any or separate the channels*/ - lv_area_t transform_area; - lv_area_copy(&transform_area, &blend_area); - lv_area_move(&transform_area, -coords->x1, -coords->y1); - if(transform) { - lv_draw_transform(draw_ctx, &transform_area, src_buf, src_w, src_h, src_w, - draw_dsc, cf, rgb_buf, mask_buf); - } - else { - convert_cb(&transform_area, src_buf, src_w, src_h, src_w, draw_dsc, cf, rgb_buf, mask_buf); - } - - /*Apply recolor*/ - if(draw_dsc->recolor_opa > LV_OPA_MIN) { - arm_2d_size_t copy_size = { - .iWidth = buf_w, - .iHeight = buf_h, - }; - - /* apply re-colour */ - __arm_2d_impl_colour_filling_with_opacity( - (color_int *)rgb_buf, - buf_w, - ©_size, - (color_int)draw_dsc->recolor.full, - draw_dsc->recolor_opa); - } -#if LV_USE_DRAW_MASKS - /*Apply the masks if any*/ - if(mask_any) { - lv_coord_t y; - lv_opa_t * mask_buf_tmp = mask_buf; - for(y = blend_area.y1; y <= blend_area.y2; y++) { - lv_draw_mask_res_t mask_res_line; - mask_res_line = lv_draw_mask_apply(mask_buf_tmp, blend_area.x1, y, blend_w); - - if(mask_res_line == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(mask_buf_tmp, blend_w); - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - } - else if(mask_res_line == LV_DRAW_MASK_RES_CHANGED) { - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - } - mask_buf_tmp += blend_w; - } - } -#endif - - /*Blend*/ - lv_draw_sw_blend(draw_ctx, &blend_dsc); - - /*Go the the next lines*/ - blend_area.y1 = blend_area.y2 + 1; - blend_area.y2 = blend_area.y1 + buf_h - 1; - if(blend_area.y2 > y_last) blend_area.y2 = y_last; - } - - lv_mem_buf_release(mask_buf); - lv_mem_buf_release(rgb_buf); - } -} - -static void lv_gpu_arm2d_wait_cb(lv_draw_ctx_t * draw_ctx) -{ - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - - arm_2d_op_wait_async(NULL); - if(disp->driver && disp->driver->wait_cb) { - disp->driver->wait_cb(disp->driver); - } - lv_draw_sw_wait_for_finish(draw_ctx); -} - - -#endif - - -/********************** - * STATIC FUNCTIONS - **********************/ -/* Separate the image channels to RGB and Alpha to match LV_COLOR_DEPTH settings*/ -static void convert_cb(const lv_area_t * dest_area, const void * src_buf, lv_coord_t src_w, lv_coord_t src_h, - lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf) -{ - LV_UNUSED(draw_dsc); - LV_UNUSED(src_h); - LV_UNUSED(src_w); - - const uint8_t * src_tmp8 = (const uint8_t *)src_buf; - lv_coord_t y; - lv_coord_t x; - - if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { - uint32_t px_cnt = lv_area_get_size(dest_area); - lv_memset(abuf, 0xff, px_cnt); - - src_tmp8 += (src_stride * dest_area->y1 * sizeof(lv_color_t)) + dest_area->x1 * sizeof(lv_color_t); - uint32_t dest_w = lv_area_get_width(dest_area); - uint32_t dest_w_byte = dest_w * sizeof(lv_color_t); - - lv_coord_t src_stride_byte = src_stride * sizeof(lv_color_t); - lv_color_t * cbuf_tmp = cbuf; - for(y = dest_area->y1; y <= dest_area->y2; y++) { - lv_memcpy(cbuf_tmp, src_tmp8, dest_w_byte); - src_tmp8 += src_stride_byte; - cbuf_tmp += dest_w; - } - - /*Make "holes" for with Chroma keying*/ - if(cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { - uint32_t i; - lv_color_t chk = LV_COLOR_CHROMA_KEY; -#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 - uint8_t * cbuf_uint = (uint8_t *)cbuf; - uint8_t chk_v = chk.full; -#elif LV_COLOR_DEPTH == 16 - uint16_t * cbuf_uint = (uint16_t *)cbuf; - uint16_t chk_v = chk.full; -#elif LV_COLOR_DEPTH == 32 - uint32_t * cbuf_uint = (uint32_t *)cbuf; - uint32_t chk_v = chk.full; -#endif - for(i = 0; i < px_cnt; i++) { - if(chk_v == cbuf_uint[i]) abuf[i] = 0x00; - } - } - } - else if(cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { - src_tmp8 += (src_stride * dest_area->y1 * LV_IMG_PX_SIZE_ALPHA_BYTE) + dest_area->x1 * LV_IMG_PX_SIZE_ALPHA_BYTE; - - lv_coord_t src_new_line_step_px = (src_stride - lv_area_get_width(dest_area)); - lv_coord_t src_new_line_step_byte = src_new_line_step_px * LV_IMG_PX_SIZE_ALPHA_BYTE; - - lv_coord_t dest_h = lv_area_get_height(dest_area); - lv_coord_t dest_w = lv_area_get_width(dest_area); - for(y = 0; y < dest_h; y++) { - for(x = 0; x < dest_w; x++) { - abuf[x] = src_tmp8[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; -#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 - cbuf[x].full = *src_tmp8; -#elif LV_COLOR_DEPTH == 16 - cbuf[x].full = *src_tmp8 + ((*(src_tmp8 + 1)) << 8); -#elif LV_COLOR_DEPTH == 32 - cbuf[x] = *((lv_color_t *) src_tmp8); - cbuf[x].ch.alpha = 0xff; -#endif - src_tmp8 += LV_IMG_PX_SIZE_ALPHA_BYTE; - - } - cbuf += dest_w; - abuf += dest_w; - src_tmp8 += src_new_line_step_byte; - } - } - else if(cf == LV_IMG_CF_RGB565A8) { - src_tmp8 += (src_stride * dest_area->y1 * sizeof(lv_color_t)) + dest_area->x1 * sizeof(lv_color_t); - - lv_coord_t src_stride_byte = src_stride * sizeof(lv_color_t); - - lv_coord_t dest_h = lv_area_get_height(dest_area); - lv_coord_t dest_w = lv_area_get_width(dest_area); - for(y = 0; y < dest_h; y++) { - lv_memcpy(cbuf, src_tmp8, dest_w * sizeof(lv_color_t)); - cbuf += dest_w; - src_tmp8 += src_stride_byte; - } - - src_tmp8 = (const uint8_t *)src_buf; - src_tmp8 += sizeof(lv_color_t) * src_w * src_h; - src_tmp8 += src_stride * dest_area->y1 + dest_area->x1; - for(y = 0; y < dest_h; y++) { - lv_memcpy(abuf, src_tmp8, dest_w); - abuf += dest_w; - src_tmp8 += src_stride; - } - } -} - -#if 0 -static void invalidate_cache(void) -{ - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - if(disp->driver->clean_dcache_cb) disp->driver->clean_dcache_cb(disp->driver); - else { -#if __CORTEX_M >= 0x07 - if((SCB->CCR) & (uint32_t)SCB_CCR_DC_Msk) - SCB_CleanInvalidateDCache(); -#endif - } -} -#endif - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_gpu_arm2d.h b/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_gpu_arm2d.h deleted file mode 100644 index 50fa5a891..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/arm2d/lv_gpu_arm2d.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @file lv_gpu_arm2d.h - * - */ - -#ifndef LV_GPU_ARM2D_H -#define LV_GPU_ARM2D_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../misc/lv_color.h" -#include "../../hal/lv_hal_disp.h" -#include "../sw/lv_draw_sw.h" - -#if LV_USE_GPU_ARM2D - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ -typedef lv_draw_sw_ctx_t lv_draw_arm2d_ctx_t; - -struct _lv_disp_drv_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -void lv_draw_arm2d_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); - -void lv_draw_arm2d_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_GPU_ARM2D*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_GPU_ARM2D_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.c index 823f70768..b4c9b4abd 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.c @@ -8,10 +8,15 @@ *********************/ #include "lv_draw.h" #include "sw/lv_draw_sw.h" +#include "../display/lv_display_private.h" +#include "../core/lv_global.h" +#include "../core/lv_refr.h" +#include "../stdlib/lv_string.h" /********************* * DEFINES *********************/ +#define _draw_info LV_GLOBAL_DEFAULT()->draw_info /********************** * TYPEDEFS @@ -20,7 +25,12 @@ /********************** * STATIC PROTOTYPES **********************/ +static bool is_independent(lv_layer_t * layer, lv_draw_task_t * t_check); +static inline uint32_t get_layer_size_kb(uint32_t size_byte) +{ + return size_byte < 1024 ? 1 : size_byte >> 10; +} /********************** * STATIC VARIABLES **********************/ @@ -39,15 +49,379 @@ void lv_draw_init(void) { - /*Nothing to init now*/ +#if LV_USE_OS + lv_thread_sync_init(&_draw_info.sync); +#endif } -void lv_draw_wait_for_finish(lv_draw_ctx_t * draw_ctx) +void lv_draw_deinit(void) { - if(draw_ctx->wait_for_finish) draw_ctx->wait_for_finish(draw_ctx); +#if LV_USE_OS + lv_thread_sync_delete(&_draw_info.sync); +#endif + + lv_draw_unit_t * u = _draw_info.unit_head; + while(u) { + lv_draw_unit_t * cur_unit = u; + u = u->next; + + if(cur_unit->delete_cb) cur_unit->delete_cb(cur_unit); + lv_free(cur_unit); + } + _draw_info.unit_head = NULL; +} + +void * lv_draw_create_unit(size_t size) +{ + lv_draw_unit_t * new_unit = lv_malloc_zeroed(size); + + new_unit->next = _draw_info.unit_head; + _draw_info.unit_head = new_unit; + + return new_unit; +} + +lv_draw_task_t * lv_draw_add_task(lv_layer_t * layer, const lv_area_t * coords) +{ + LV_PROFILER_BEGIN; + lv_draw_task_t * new_task = lv_malloc_zeroed(sizeof(lv_draw_task_t)); + + new_task->area = *coords; + new_task->_real_area = *coords; + new_task->clip_area = layer->_clip_area; + new_task->state = LV_DRAW_TASK_STATE_QUEUED; + + /*Find the tail*/ + if(layer->draw_task_head == NULL) { + layer->draw_task_head = new_task; + } + else { + lv_draw_task_t * tail = layer->draw_task_head; + while(tail->next) tail = tail->next; + + tail->next = new_task; + } + + LV_PROFILER_END; + return new_task; +} + +void lv_draw_finalize_task_creation(lv_layer_t * layer, lv_draw_task_t * t) +{ + LV_PROFILER_BEGIN; + lv_draw_dsc_base_t * base_dsc = t->draw_dsc; + base_dsc->layer = layer; + + lv_draw_global_info_t * info = &_draw_info; + + /*Send LV_EVENT_DRAW_TASK_ADDED and dispatch only on the "main" draw_task + *and not on the draw tasks added in the event. + *Sending LV_EVENT_DRAW_TASK_ADDED events might cause recursive event sends and besides + *dispatching might remove the "main" draw task while it's still being used in the event*/ + + if(info->task_running == false) { + if(base_dsc->obj && lv_obj_has_flag(base_dsc->obj, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS)) { + info->task_running = true; + lv_obj_send_event(base_dsc->obj, LV_EVENT_DRAW_TASK_ADDED, t); + info->task_running = false; + } + + /*Let the draw units set their preference score*/ + t->preference_score = 100; + t->preferred_draw_unit_id = 0; + lv_draw_unit_t * u = info->unit_head; + while(u) { + if(u->evaluate_cb) u->evaluate_cb(u, t); + u = u->next; + } + + lv_draw_dispatch(); + } + else { + /*Let the draw units set their preference score*/ + t->preference_score = 100; + t->preferred_draw_unit_id = 0; + lv_draw_unit_t * u = info->unit_head; + while(u) { + if(u->evaluate_cb) u->evaluate_cb(u, t); + u = u->next; + } + } + LV_PROFILER_END; +} + +void lv_draw_dispatch(void) +{ + LV_PROFILER_BEGIN; + bool render_running = false; + lv_display_t * disp = lv_display_get_next(NULL); + while(disp) { + lv_layer_t * layer = disp->layer_head; + while(layer) { + if(lv_draw_dispatch_layer(disp, layer)) + render_running = true; + layer = layer->next; + } + if(!render_running) { + lv_draw_dispatch_request(); + } + disp = lv_display_get_next(disp); + } + LV_PROFILER_END; +} + +bool lv_draw_dispatch_layer(lv_display_t * disp, lv_layer_t * layer) +{ + LV_PROFILER_BEGIN; + /*Remove the finished tasks first*/ + lv_draw_task_t * t_prev = NULL; + lv_draw_task_t * t = layer->draw_task_head; + while(t) { + lv_draw_task_t * t_next = t->next; + if(t->state == LV_DRAW_TASK_STATE_READY) { + if(t_prev) t_prev->next = t->next; /*Remove by it by assigning the next task to the previous*/ + else layer->draw_task_head = t_next; /*If it was the head, set the next as head*/ + + /*If it was layer drawing free the layer too*/ + if(t->type == LV_DRAW_TASK_TYPE_LAYER) { + lv_draw_image_dsc_t * draw_image_dsc = t->draw_dsc; + lv_layer_t * layer_drawn = (lv_layer_t *)draw_image_dsc->src; + + if(layer_drawn->draw_buf) { + int32_t h = lv_area_get_height(&layer_drawn->buf_area); + int32_t w = lv_area_get_width(&layer_drawn->buf_area); + uint32_t layer_size_byte = h * lv_draw_buf_width_to_stride(w, layer_drawn->color_format); + + _draw_info.used_memory_for_layers_kb -= get_layer_size_kb(layer_size_byte); + LV_LOG_INFO("Layer memory used: %" LV_PRIu32 " kB\n", _draw_info.used_memory_for_layers_kb); + lv_draw_buf_destroy(layer_drawn->draw_buf); + layer_drawn->draw_buf = NULL; + } + + /*Remove the layer from the display's*/ + if(disp) { + lv_layer_t * l2 = disp->layer_head; + while(l2) { + if(l2->next == layer_drawn) { + l2->next = layer_drawn->next; + break; + } + l2 = l2->next; + } + + if(disp->layer_deinit) disp->layer_deinit(disp, layer_drawn); + lv_free(layer_drawn); + } + } + if(t->type == LV_DRAW_TASK_TYPE_LABEL) { + lv_draw_label_dsc_t * draw_label_dsc = t->draw_dsc; + if(draw_label_dsc->text_local) { + lv_free((void *)draw_label_dsc->text); + draw_label_dsc->text = NULL; + } + } + + lv_free(t->draw_dsc); + lv_free(t); + } + else { + t_prev = t; + } + t = t_next; + } + + bool render_running = false; + + /*This layer is ready, enable blending its buffer*/ + if(layer->parent && layer->all_tasks_added && layer->draw_task_head == NULL) { + /*Find a draw task with TYPE_LAYER in the layer where the src is this layer*/ + lv_draw_task_t * t_src = layer->parent->draw_task_head; + while(t_src) { + if(t_src->type == LV_DRAW_TASK_TYPE_LAYER && t_src->state == LV_DRAW_TASK_STATE_WAITING) { + lv_draw_image_dsc_t * draw_dsc = t_src->draw_dsc; + if(draw_dsc->src == layer) { + t_src->state = LV_DRAW_TASK_STATE_QUEUED; + lv_draw_dispatch_request(); + break; + } + } + t_src = t_src->next; + } + } + /*Assign draw tasks to the draw_units*/ + else { + /*Find a draw unit which is not busy and can take at least one task*/ + /*Let all draw units to pick draw tasks*/ + lv_draw_unit_t * u = _draw_info.unit_head; + while(u) { + int32_t taken_cnt = u->dispatch_cb(u, layer); + if(taken_cnt >= 0) render_running = true; + u = u->next; + } + } + + LV_PROFILER_END; + return render_running; +} + +void lv_draw_dispatch_wait_for_request(void) +{ +#if LV_USE_OS + lv_thread_sync_wait(&_draw_info.sync); +#else + while(!_draw_info.dispatch_req); + _draw_info.dispatch_req = 0; +#endif +} + +void lv_draw_dispatch_request(void) +{ +#if LV_USE_OS + lv_thread_sync_signal(&_draw_info.sync); +#else + _draw_info.dispatch_req = 1; +#endif +} + +lv_draw_task_t * lv_draw_get_next_available_task(lv_layer_t * layer, lv_draw_task_t * t_prev, uint8_t draw_unit_id) +{ + LV_PROFILER_BEGIN; + /*If the first task is screen sized, there cannot be independent areas*/ + if(layer->draw_task_head) { + int32_t hor_res = lv_display_get_horizontal_resolution(_lv_refr_get_disp_refreshing()); + int32_t ver_res = lv_display_get_vertical_resolution(_lv_refr_get_disp_refreshing()); + lv_draw_task_t * t = layer->draw_task_head; + if(t->state != LV_DRAW_TASK_STATE_QUEUED && + t->area.x1 <= 0 && t->area.x2 >= hor_res - 1 && + t->area.y1 <= 0 && t->area.y2 >= ver_res - 1) { + LV_PROFILER_END; + return NULL; + } + } + + lv_draw_task_t * t = t_prev ? t_prev->next : layer->draw_task_head; + while(t) { + /*Find a queued and independent task*/ + if(t->state == LV_DRAW_TASK_STATE_QUEUED && + (t->preferred_draw_unit_id == LV_DRAW_UNIT_ID_ANY || t->preferred_draw_unit_id == draw_unit_id) && + is_independent(layer, t)) { + LV_PROFILER_END; + return t; + } + t = t->next; + } + + LV_PROFILER_END; + return NULL; +} + +uint32_t lv_draw_get_dependent_count(lv_draw_task_t * t_check) +{ + if(t_check == NULL) return 0; + if(t_check->next == NULL) return 0; + + LV_PROFILER_BEGIN; + uint32_t cnt = 0; + + lv_draw_task_t * t = t_check->next; + while(t) { + if((t->state == LV_DRAW_TASK_STATE_QUEUED || t->state == LV_DRAW_TASK_STATE_WAITING) && + _lv_area_is_on(&t_check->area, &t->area)) { + cnt++; + } + + t = t->next; + } + LV_PROFILER_END; + return cnt; +} + +lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t color_format, const lv_area_t * area) +{ + lv_display_t * disp = _lv_refr_get_disp_refreshing(); + lv_layer_t * new_layer = lv_malloc_zeroed(sizeof(lv_layer_t)); + LV_ASSERT_MALLOC(new_layer); + if(new_layer == NULL) return NULL; + + new_layer->parent = parent_layer; + new_layer->_clip_area = *area; + new_layer->buf_area = *area; + new_layer->color_format = color_format; + + if(disp->layer_head) { + lv_layer_t * tail = disp->layer_head; + while(tail->next) tail = tail->next; + tail->next = new_layer; + } + else { + disp->layer_head = new_layer; + } + + return new_layer; +} + +void * lv_draw_layer_alloc_buf(lv_layer_t * layer) +{ + /*If the buffer of the layer is already allocated return it*/ + if(layer->draw_buf != NULL) { + return layer->draw_buf->data; + } + + /*If the buffer of the layer is not allocated yet, allocate it now*/ + int32_t w = lv_area_get_width(&layer->buf_area); + int32_t h = lv_area_get_height(&layer->buf_area); + + layer->draw_buf = lv_draw_buf_create(w, h, layer->color_format, 0); + + if(layer->draw_buf == NULL) { + LV_LOG_WARN("Allocating layer buffer failed. Try later"); + return NULL; + } + + if(lv_color_format_has_alpha(layer->color_format)) { + lv_area_t a; + a.x1 = 0; + a.y1 = 0; + a.x2 = w - 1; + a.y2 = h - 1; + lv_draw_buf_clear(layer->draw_buf, &a); + } + + return layer->draw_buf->data; +} + +void * lv_draw_layer_go_to_xy(lv_layer_t * layer, int32_t x, int32_t y) +{ + return lv_draw_buf_goto_xy(layer->draw_buf, x, y); } /********************** * STATIC FUNCTIONS **********************/ +/** + * Check if there are older draw task overlapping the area of `t_check` + * @param layer the draw ctx to search in + * @param t_check check this task if it overlaps with the older ones + * @return true: `t_check` is not overlapping with older tasks so it's independent + */ +static bool is_independent(lv_layer_t * layer, lv_draw_task_t * t_check) +{ + LV_PROFILER_BEGIN; + lv_draw_task_t * t = layer->draw_task_head; + + /*If t_check is outside of the older tasks then it's independent*/ + while(t && t != t_check) { + if(t->state != LV_DRAW_TASK_STATE_READY) { + lv_area_t a; + if(_lv_area_intersect(&a, &t->_real_area, &t_check->_real_area)) { + LV_PROFILER_END; + return false; + } + } + t = t->next; + } + LV_PROFILER_END; + + return true; +} diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.h index ffe1d4e27..0672bc55d 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.h @@ -15,190 +15,294 @@ extern "C" { *********************/ #include "../lv_conf_internal.h" +#include "../misc/lv_types.h" #include "../misc/lv_style.h" -#include "../misc/lv_txt.h" -#include "lv_img_decoder.h" -#include "lv_img_cache.h" - -#include "lv_draw_rect.h" -#include "lv_draw_label.h" -#include "lv_draw_img.h" -#include "lv_draw_line.h" -#include "lv_draw_triangle.h" -#include "lv_draw_arc.h" -#include "lv_draw_mask.h" -#include "lv_draw_transform.h" -#include "lv_draw_layer.h" +#include "../misc/lv_text.h" +#include "../misc/lv_profiler.h" +#include "lv_image_decoder.h" +#include "../osal/lv_os.h" +#include "lv_draw_buf.h" /********************* * DEFINES *********************/ +#define LV_DRAW_UNIT_ID_ANY 0 /********************** * TYPEDEFS **********************/ +typedef enum { + LV_DRAW_TASK_TYPE_FILL, + LV_DRAW_TASK_TYPE_BORDER, + LV_DRAW_TASK_TYPE_BOX_SHADOW, + LV_DRAW_TASK_TYPE_LABEL, + LV_DRAW_TASK_TYPE_IMAGE, + LV_DRAW_TASK_TYPE_LAYER, + LV_DRAW_TASK_TYPE_LINE, + LV_DRAW_TASK_TYPE_ARC, + LV_DRAW_TASK_TYPE_TRIANGLE, + LV_DRAW_TASK_TYPE_MASK_RECTANGLE, + LV_DRAW_TASK_TYPE_MASK_BITMAP, + LV_DRAW_TASK_TYPE_VECTOR, +} lv_draw_task_type_t; + +typedef enum { + LV_DRAW_TASK_STATE_WAITING, /*Waiting for something to be finished. E.g. rendering a layer*/ + LV_DRAW_TASK_STATE_QUEUED, + LV_DRAW_TASK_STATE_IN_PROGRESS, + LV_DRAW_TASK_STATE_READY, +} lv_draw_task_state_t; + +struct _lv_draw_task_t { + lv_draw_task_t * next; + + lv_draw_task_type_t type; + + /** + * The area where to draw + */ + lv_area_t area; + + /** + * The real draw area. E.g. for shadow, outline, or transformed images it's different from `area` + */ + lv_area_t _real_area; + + /** The original area which is updated*/ + lv_area_t clip_area_original; + + /** + * The clip area of the layer is saved here when the draw task is created. + * As the clip area of the layer can be changed as new draw tasks are added its current value needs to be saved. + * Therefore during drawing the layer's clip area shouldn't be used as it might be already changed for other draw tasks. + */ + lv_area_t clip_area; + + volatile int state; /*int instead of lv_draw_task_state_t to be sure its atomic*/ + + void * draw_dsc; + + /** + * The ID of the draw_unit which should take this task + */ + uint8_t preferred_draw_unit_id; + + /** + * Set to which extent `preferred_draw_unit_id` is good at this task. + * 80: means 20% better (faster) than software rendering + * 100: the default value + * 110: means 10% worse (slower) than software rendering + */ + uint8_t preference_score; + +}; + typedef struct { void * user_data; } lv_draw_mask_t; -typedef struct _lv_draw_layer_ctx_t { - lv_area_t area_full; - lv_area_t area_act; - lv_coord_t max_row_with_alpha; - lv_coord_t max_row_with_no_alpha; - void * buf; - struct { - const lv_area_t * clip_area; - lv_area_t * buf_area; - void * buf; - bool screen_transp; - } original; -} lv_draw_layer_ctx_t; - -typedef struct _lv_draw_ctx_t { - /** - * Pointer to a buffer to draw into - */ - void * buf; +struct _lv_draw_unit_t { + lv_draw_unit_t * next; /** - * The position and size of `buf` (absolute coordinates) + * The target_layer on which drawing should happen */ - lv_area_t * buf_area; + lv_layer_t * target_layer; - /** - * The current clip area with absolute coordinates, always the same or smaller than `buf_area` - */ const lv_area_t * clip_area; - void (*init_buf)(struct _lv_draw_ctx_t * draw_ctx); - - void (*draw_rect)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); - - void (*draw_arc)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, - uint16_t radius, uint16_t start_angle, uint16_t end_angle); - - void (*draw_img_decoded)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, - const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format); - - lv_res_t (*draw_img)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc, - const lv_area_t * coords, const void * src); - - void (*draw_letter)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p, - uint32_t letter); - - - void (*draw_line)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1, - const lv_point_t * point2); - - - void (*draw_polygon)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, - const lv_point_t * points, uint16_t point_cnt); - - /** - * Get an area of a transformed image (zoomed and/or rotated) - * @param draw_ctx pointer to a draw context - * @param dest_area get this area of the result image. It assumes that the original image is placed to the 0;0 position. - * @param src_buf the source image - * @param src_w width of the source image in [px] - * @param src_h height of the source image in [px] - * @param src_stride the stride in [px]. - * @param draw_dsc an `lv_draw_img_dsc_t` descriptor containing the transformation parameters - * @param cf the color format of `src_buf` - * @param cbuf place the colors of the pixels on `dest_area` here in RGB format - * @param abuf place the opacity of the pixels on `dest_area` here + * Called to try to assign a draw task to itself. + * `lv_draw_get_next_available_task` can be used to get an independent draw task. + * A draw task should be assign only if the draw unit can draw it too + * @param draw_unit pointer to the draw unit + * @param layer pointer to a layer on which the draw task should be drawn + * @return >=0: The number of taken draw task: + * 0 means the task has not yet been completed. + * 1 means a new task has been accepted. + * -1: The draw unit wanted to work on a task but couldn't do that + * due to some errors (e.g. out of memory). + * It signals that LVGL should call the dispatcher later again + * to let draw unit try to start the rendering again. */ - void (*draw_transform)(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf, - lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, - const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf); + int32_t (*dispatch_cb)(lv_draw_unit_t * draw_unit, lv_layer_t * layer); /** - * Replace the buffer with a rect without decoration like radius or borders - */ - void (*draw_bg)(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_area_t * coords); - - /** - * Wait until all background operations are finished. (E.g. GPU operations) - */ - void (*wait_for_finish)(struct _lv_draw_ctx_t * draw_ctx); - - /** - * Copy an area from buffer to an other - * @param draw_ctx pointer to a draw context - * @param dest_buf copy the buffer into this buffer - * @param dest_stride the width of the dest_buf in pixels - * @param dest_area the destination area - * @param src_buf copy from this buffer - * @param src_stride the width of src_buf in pixels - * @param src_area the source area. * - * @note dest_area and src_area must have the same width and height - * but can have different x and y position. - * @note dest_area and src_area must be clipped to the real dimensions of the buffers + * @param draw_unit + * @param task + * @return */ - void (*buffer_copy)(struct _lv_draw_ctx_t * draw_ctx, void * dest_buf, lv_coord_t dest_stride, - const lv_area_t * dest_area, - void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area); + int32_t (*evaluate_cb)(lv_draw_unit_t * draw_unit, lv_draw_task_t * task); /** - * Initialize a new layer context. - * The original buffer and area data are already saved from `draw_ctx` to `layer_ctx` - * @param draw_ctx pointer to the current draw context - * @param layer_area the coordinates of the layer - * @param flags OR-ed flags from @lv_draw_layer_flags_t - * @return pointer to the layer context, or NULL on error + * Called to delete draw unit. + * @param draw_unit + * @return */ - struct _lv_draw_layer_ctx_t * (*layer_init)(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, - lv_draw_layer_flags_t flags); + int32_t (*delete_cb)(lv_draw_unit_t * draw_unit); +}; + +struct _lv_layer_t { + + /** Target draw buffer of the layer*/ + lv_draw_buf_t * draw_buf; + + /** The absolute coordinates of the buffer */ + lv_area_t buf_area; + + /** The color format of the layer. LV_COLOR_FORMAT_... */ + lv_color_format_t color_format; /** - * Adjust the layer_ctx and/or draw_ctx based on the `layer_ctx->area_act`. - * It's called only if flags has `LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE` - * @param draw_ctx pointer to the current draw context - * @param layer_ctx pointer to a layer context - * @param flags OR-ed flags from @lv_draw_layer_flags_t + * NEVER USE IT DRAW UNITS. USED INTERNALLY DURING DRAW TASK CREATION. + * The current clip area with absolute coordinates, always the same or smaller than `buf_area` + * Can be set before new draw tasks are added to indicate the clip area of the draw tasks. + * Therefore `lv_draw_add_task()` always saves it in the new draw task to know the clip area when the draw task was added. + * During drawing the draw units also sees the saved clip_area and should use it during drawing. + * During drawing the layer's clip area shouldn't be used as it might be already changed for other draw tasks. */ - void (*layer_adjust)(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, - lv_draw_layer_flags_t flags); + lv_area_t _clip_area; - /** - * Blend a rendered layer to `layer_ctx->area_act` - * @param draw_ctx pointer to the current draw context - * @param layer_ctx pointer to a layer context - * @param draw_dsc pointer to an image draw descriptor - */ - void (*layer_blend)(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, - const lv_draw_img_dsc_t * draw_dsc); + /** Linked list of draw tasks */ + lv_draw_task_t * draw_task_head; - /** - * Destroy a layer context. The original buffer and area data of the `draw_ctx` will be restored - * and the `layer_ctx` itself will be freed automatically. - * @param draw_ctx pointer to the current draw context - * @param layer_ctx pointer to a layer context - */ - void (*layer_destroy)(struct _lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx); - - /** - * Size of a layer context in bytes. - */ - size_t layer_instance_size; - -#if LV_USE_USER_DATA + lv_layer_t * parent; + lv_layer_t * next; + bool all_tasks_added; void * user_data; -#endif +}; -} lv_draw_ctx_t; +typedef struct { + lv_obj_t * obj; + uint32_t part; + uint32_t id1; + uint32_t id2; + lv_layer_t * layer; + size_t dsc_size; + void * user_data; +} lv_draw_dsc_base_t; + +typedef struct { + lv_draw_unit_t * unit_head; + uint32_t used_memory_for_layers_kb; +#if LV_USE_OS + lv_thread_sync_t sync; +#else + int dispatch_req; +#endif + lv_mutex_t circle_cache_mutex; + bool task_running; +} lv_draw_global_info_t; /********************** * GLOBAL PROTOTYPES **********************/ +/** + * Used internally to initialize the drawing module + */ void lv_draw_init(void); +/** + * Deinitialize the drawing module + */ +void lv_draw_deinit(void); -void lv_draw_wait_for_finish(lv_draw_ctx_t * draw_ctx); +/** + * Allocate a new draw unit with the given size and appends it to the list of draw units + * @param size the size to allocate. E.g. `sizeof(my_draw_unit_t)`, + * where the first element of `my_draw_unit_t` is `lv_draw_unit_t`. + */ +void * lv_draw_create_unit(size_t size); + +/** + * Add an empty draw task to the draw task list of a layer. + * @param layer pointer to a layer + * @param coords the coordinates of the draw task + * @return the created draw task which needs to be + * further configured e.g. by added a draw descriptor + */ +lv_draw_task_t * lv_draw_add_task(lv_layer_t * layer, const lv_area_t * coords); + +/** + * Needs to be called when a draw task is created and configured. + * It will send an event about the new draw task to the widget + * and assign it to a draw unit. + * @param layer pointer to a layer + * @param t poinr to a draw task + */ +void lv_draw_finalize_task_creation(lv_layer_t * layer, lv_draw_task_t * t); + +/** + * Try dispatching draw tasks to draw units + */ +void lv_draw_dispatch(void); + +/** + * Used internally to try dispatching draw tasks of a specific layer + * @param disp pointer to a display on which the dispatching was requested + * @param layer pointer to a layer + * @return at least one draw task is being rendered (maybe it was taken earlier) + */ +bool lv_draw_dispatch_layer(lv_display_t * disp, lv_layer_t * layer); + +/** + * Wait for a new dispatch request. + * It's blocking if `LV_USE_OS == 0` else it yields + */ +void lv_draw_dispatch_wait_for_request(void); + +/** + * When a draw unit finished a draw task it needs to request dispatching + * to let LVGL assign a new draw task to it + */ +void lv_draw_dispatch_request(void); + +/** + * Find and available draw task + * @param layer the draw ctx to search in + * @param t_prev continue searching from this task + * @param draw_unit_id check the task where `preferred_draw_unit_id` equals this value or `LV_DRAW_UNIT_ID_ANY` + * @return tan available draw task or NULL if there is no any + */ +lv_draw_task_t * lv_draw_get_next_available_task(lv_layer_t * layer, lv_draw_task_t * t_prev, uint8_t draw_unit_id); + +/** + * Tell how many draw task are waiting to be drawn on the area of `t_check`. + * It can be used to determine if a GPU shall combine many draw tasks in to one or not. + * If a lot of tasks are waiting for the current ones it makes sense to draw them one-by-one + * to not block the dependent tasks' rendering + * @param t_check the task whose dependent tasks shall be counted + * @return number of tasks depending on `t_check` + */ +uint32_t lv_draw_get_dependent_count(lv_draw_task_t * t_check); + +/** + * Create a new layer on a parent layer + * @param parent_layer the parent layer to which the layer will be merged when it's rendered + * @param color_format the color format of the layer + * @param area the areas of the layer (absolute coordinates) + * @return the new target_layer or NULL on error + */ +lv_layer_t * lv_draw_layer_create(lv_layer_t * parent_layer, lv_color_format_t color_format, const lv_area_t * area); + +/** + * Try to allocate a buffer for the layer. + * @param layer pointer to a layer + * @return pointer to the allocated aligned buffer or NULL on failure + */ +void * lv_draw_layer_alloc_buf(lv_layer_t * layer); + +/** + * Got to a pixel at X and Y coordinate on a layer + * @param layer pointer to a layer + * @param x the target X coordinate + * @param y the target X coordinate + * @return `buf` offset to point to the given X and Y coordinate + */ +void * lv_draw_layer_go_to_xy(lv_layer_t * layer, int32_t x, int32_t y); /********************** * GLOBAL VARIABLES @@ -211,6 +315,13 @@ void lv_draw_wait_for_finish(lv_draw_ctx_t * draw_ctx); /********************** * POST INCLUDES *********************/ +#include "lv_draw_rect.h" +#include "lv_draw_label.h" +#include "lv_draw_image.h" +#include "lv_draw_arc.h" +#include "lv_draw_line.h" +#include "lv_draw_triangle.h" +#include "lv_draw_mask.h" #ifdef __cplusplus } /*extern "C"*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.mk b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.mk deleted file mode 100644 index f48f48fe0..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw.mk +++ /dev/null @@ -1,25 +0,0 @@ -CSRCS += lv_draw_arc.c -CSRCS += lv_draw.c -CSRCS += lv_draw_img.c -CSRCS += lv_draw_label.c -CSRCS += lv_draw_line.c -CSRCS += lv_draw_mask.c -CSRCS += lv_draw_rect.c -CSRCS += lv_draw_transform.c -CSRCS += lv_draw_layer.c -CSRCS += lv_draw_triangle.c -CSRCS += lv_img_buf.c -CSRCS += lv_img_cache.c -CSRCS += lv_img_decoder.c - -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw" - -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/arm2d/lv_draw_arm2d.mk -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/lv_draw_nxp.mk -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl/lv_draw_sdl.mk -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d/lv_draw_stm32_dma2d.mk -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw/lv_draw_sw.mk -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/swm341_dma2d/lv_draw_swm341_dma2d.mk diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.c index b806a002e..9f8a8b0f9 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.c @@ -6,8 +6,10 @@ /********************* * INCLUDES *********************/ -#include "lv_draw.h" +#include "../core/lv_obj.h" #include "lv_draw_arc.h" +#include "../core/lv_obj_event.h" +#include "../stdlib/lv_string.h" /********************* * DEFINES @@ -35,32 +37,45 @@ void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc) { - lv_memset_00(dsc, sizeof(lv_draw_arc_dsc_t)); + lv_memzero(dsc, sizeof(lv_draw_arc_dsc_t)); dsc->width = 1; dsc->opa = LV_OPA_COVER; dsc->color = lv_color_black(); } -void lv_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, uint16_t radius, - uint16_t start_angle, uint16_t end_angle) +void lv_draw_arc(lv_layer_t * layer, const lv_draw_arc_dsc_t * dsc) { if(dsc->opa <= LV_OPA_MIN) return; if(dsc->width == 0) return; - if(start_angle == end_angle) return; + if(dsc->start_angle == dsc->end_angle) return; - draw_ctx->draw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle); + LV_PROFILER_BEGIN; + lv_area_t a; + a.x1 = dsc->center.x - dsc->radius; + a.y1 = dsc->center.y - dsc->radius; + a.x2 = dsc->center.x + dsc->radius - 1; + a.y2 = dsc->center.y + dsc->radius - 1; + lv_draw_task_t * t = lv_draw_add_task(layer, &a); - // const lv_draw_backend_t * backend = lv_draw_backend_get(); - // backend->draw_arc(center_x, center_y, radius, start_angle, end_angle, clip_area, dsc); + t->draw_dsc = lv_malloc(sizeof(*dsc)); + lv_memcpy(t->draw_dsc, dsc, sizeof(*dsc)); + t->type = LV_DRAW_TASK_TYPE_ARC; + + lv_draw_finalize_task_creation(layer, t); + + LV_PROFILER_END; } -void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle, - lv_coord_t w, bool rounded, lv_area_t * area) +void lv_draw_arc_get_area(int32_t x, int32_t y, uint16_t radius, lv_value_precise_t start_angle, + lv_value_precise_t end_angle, + int32_t w, bool rounded, lv_area_t * area) { - lv_coord_t rout = radius; + int32_t rout = radius; + int32_t start_angle_int = (int32_t) start_angle; + int32_t end_angle_int = (int32_t) end_angle; /*Special case: full arc invalidation */ - if(end_angle == start_angle + 360) { + if(end_angle_int == start_angle_int + 360) { area->x1 = x - rout; area->y1 = y - rout; area->x2 = x + rout; @@ -68,75 +83,75 @@ void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t return; } - if(start_angle > 360) start_angle -= 360; - if(end_angle > 360) end_angle -= 360; + if(start_angle_int > 360) start_angle_int -= 360; + if(end_angle_int > 360) end_angle_int -= 360; - lv_coord_t rin = radius - w; - lv_coord_t extra_area = rounded ? w / 2 + 1 : 0; - uint8_t start_quarter = start_angle / 90; - uint8_t end_quarter = end_angle / 90; + int32_t rin = radius - w; + int32_t extra_area = rounded ? w / 2 + 1 : 0; + uint8_t start_quarter = start_angle_int / 90; + uint8_t end_quarter = end_angle_int / 90; /*360 deg still counts as quarter 3 (360 / 90 would be 4)*/ if(start_quarter == 4) start_quarter = 3; if(end_quarter == 4) end_quarter = 3; - if(start_quarter == end_quarter && start_angle <= end_angle) { + if(start_quarter == end_quarter && start_angle_int <= end_angle_int) { if(start_quarter == 0) { - area->y1 = y + ((lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) - extra_area; - area->x2 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area; + area->y1 = y + ((lv_trigo_sin(start_angle_int) * rin) >> LV_TRIGO_SHIFT) - extra_area; + area->x2 = x + ((lv_trigo_sin(start_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area; - area->y2 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area; - area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area; + area->y2 = y + ((lv_trigo_sin(end_angle_int) * rout) >> LV_TRIGO_SHIFT) + extra_area; + area->x1 = x + ((lv_trigo_sin(end_angle_int + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area; } else if(start_quarter == 1) { - area->y2 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area; - area->x2 = x + ((lv_trigo_sin(start_angle + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area; + area->y2 = y + ((lv_trigo_sin(start_angle_int) * rout) >> LV_TRIGO_SHIFT) + extra_area; + area->x2 = x + ((lv_trigo_sin(start_angle_int + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area; - area->y1 = y + ((lv_trigo_sin(end_angle) * rin) >> LV_TRIGO_SHIFT) - extra_area; - area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area; + area->y1 = y + ((lv_trigo_sin(end_angle_int) * rin) >> LV_TRIGO_SHIFT) - extra_area; + area->x1 = x + ((lv_trigo_sin(end_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area; } else if(start_quarter == 2) { - area->x1 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area; - area->y2 = y + ((lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area; + area->x1 = x + ((lv_trigo_sin(start_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area; + area->y2 = y + ((lv_trigo_sin(start_angle_int) * rin) >> LV_TRIGO_SHIFT) + extra_area; - area->y1 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area; - area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area; + area->y1 = y + ((lv_trigo_sin(end_angle_int) * rout) >> LV_TRIGO_SHIFT) - extra_area; + area->x2 = x + ((lv_trigo_sin(end_angle_int + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area; } else if(start_quarter == 3) { - area->x1 = x + ((lv_trigo_sin(start_angle + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area; - area->y1 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area; + area->x1 = x + ((lv_trigo_sin(start_angle_int + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area; + area->y1 = y + ((lv_trigo_sin(start_angle_int) * rout) >> LV_TRIGO_SHIFT) - extra_area; - area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area; - area->y2 = y + ((lv_trigo_sin(end_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area; + area->x2 = x + ((lv_trigo_sin(end_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area; + area->y2 = y + ((lv_trigo_sin(end_angle_int) * rin) >> LV_TRIGO_SHIFT) + extra_area; } } else if(start_quarter == 0 && end_quarter == 1) { - area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area; - area->y1 = y + ((LV_MIN(lv_trigo_sin(end_angle), - lv_trigo_sin(start_angle)) * rin) >> LV_TRIGO_SHIFT) - extra_area; - area->x2 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area; + area->x1 = x + ((lv_trigo_sin(end_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area; + area->y1 = y + ((LV_MIN(lv_trigo_sin(end_angle_int), + lv_trigo_sin(start_angle_int)) * rin) >> LV_TRIGO_SHIFT) - extra_area; + area->x2 = x + ((lv_trigo_sin(start_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area; area->y2 = y + rout + extra_area; } else if(start_quarter == 1 && end_quarter == 2) { area->x1 = x - rout - extra_area; - area->y1 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area; - area->x2 = x + ((LV_MAX(lv_trigo_sin(start_angle + 90), - lv_trigo_sin(end_angle + 90)) * rin) >> LV_TRIGO_SHIFT) + extra_area; - area->y2 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area; + area->y1 = y + ((lv_trigo_sin(end_angle_int) * rout) >> LV_TRIGO_SHIFT) - extra_area; + area->x2 = x + ((LV_MAX(lv_trigo_sin(start_angle_int + 90), + lv_trigo_sin(end_angle_int + 90)) * rin) >> LV_TRIGO_SHIFT) + extra_area; + area->y2 = y + ((lv_trigo_sin(start_angle_int) * rout) >> LV_TRIGO_SHIFT) + extra_area; } else if(start_quarter == 2 && end_quarter == 3) { - area->x1 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area; + area->x1 = x + ((lv_trigo_sin(start_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area; area->y1 = y - rout - extra_area; - area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area; - area->y2 = y + (LV_MAX(lv_trigo_sin(end_angle) * rin, - lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area; + area->x2 = x + ((lv_trigo_sin(end_angle_int + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area; + area->y2 = y + (LV_MAX(lv_trigo_sin(end_angle_int) * rin, + lv_trigo_sin(start_angle_int) * rin) >> LV_TRIGO_SHIFT) + extra_area; } else if(start_quarter == 3 && end_quarter == 0) { - area->x1 = x + ((LV_MIN(lv_trigo_sin(end_angle + 90), - lv_trigo_sin(start_angle + 90)) * rin) >> LV_TRIGO_SHIFT) - extra_area; - area->y1 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area; + area->x1 = x + ((LV_MIN(lv_trigo_sin(end_angle_int + 90), + lv_trigo_sin(start_angle_int + 90)) * rin) >> LV_TRIGO_SHIFT) - extra_area; + area->y1 = y + ((lv_trigo_sin(start_angle_int) * rout) >> LV_TRIGO_SHIFT) - extra_area; area->x2 = x + rout + extra_area; - area->y2 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area; + area->y2 = y + ((lv_trigo_sin(end_angle_int) * rout) >> LV_TRIGO_SHIFT) + extra_area; } else { diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.h index 8783f131b..e4e09987f 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.h @@ -25,38 +25,37 @@ extern "C" { /********************** * TYPEDEFS **********************/ + typedef struct { + lv_draw_dsc_base_t base; + lv_color_t color; - lv_coord_t width; - uint16_t start_angle; - uint16_t end_angle; + int32_t width; + lv_value_precise_t start_angle; + lv_value_precise_t end_angle; + lv_point_t center; + uint16_t radius; const void * img_src; lv_opa_t opa; - lv_blend_mode_t blend_mode : 2; uint8_t rounded : 1; } lv_draw_arc_dsc_t; -struct _lv_draw_ctx_t; - /********************** * GLOBAL PROTOTYPES **********************/ +/** + * Initialize an arc draw descriptor. + * @param dsc pointer to a draw descriptor + */ void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc); /** - * Draw an arc. (Can draw pie too with great thickness.) - * @param center_x the x coordinate of the center of the arc - * @param center_y the y coordinate of the center of the arc - * @param radius the radius of the arc - * @param mask the arc will be drawn only in this mask - * @param start_angle the start angle of the arc (0 deg on the bottom, 90 deg on the right) - * @param end_angle the end angle of the arc - * @param clip_area the arc will be drawn only in this area - * @param dsc pointer to an initialized `lv_draw_line_dsc_t` variable + * Create an arc draw task. + * @param layer pointer to a layer + * @param dsc pointer to an initialized draw descriptor variable */ -void lv_draw_arc(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, - uint16_t radius, uint16_t start_angle, uint16_t end_angle); +void lv_draw_arc(lv_layer_t * layer, const lv_draw_arc_dsc_t * dsc); /** * Get an area the should be invalidated when the arcs angle changed between start_angle and end_ange @@ -69,8 +68,9 @@ void lv_draw_arc(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc * @param rounded true: the arc is rounded * @param area store the area to invalidate here */ -void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle, - lv_coord_t w, bool rounded, lv_area_t * area); +void lv_draw_arc_get_area(int32_t x, int32_t y, uint16_t radius, lv_value_precise_t start_angle, + lv_value_precise_t end_angle, + int32_t w, bool rounded, lv_area_t * area); /********************** * MACROS diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_buf.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_buf.c new file mode 100644 index 000000000..fba6a4d1d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_buf.c @@ -0,0 +1,441 @@ +/** + * @file lv_draw_buf.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../misc/lv_types.h" +#include "lv_draw_buf.h" +#include "../stdlib/lv_string.h" +#include "../core/lv_global.h" + +/********************* + * DEFINES + *********************/ +#define handlers LV_GLOBAL_DEFAULT()->draw_buf_handlers + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void * buf_malloc(size_t size, lv_color_format_t color_format); +static void buf_free(void * buf); +static void * buf_align(void * buf, lv_color_format_t color_format); +static void * draw_buf_malloc(size_t size_bytes, lv_color_format_t color_format); +static void draw_buf_free(void * buf); +static uint32_t width_to_stride(uint32_t w, lv_color_format_t color_format); +static uint32_t _calculate_draw_buf_size(uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void _lv_draw_buf_init_handlers(void) +{ + lv_memzero(&handlers, sizeof(lv_draw_buf_handlers_t)); + handlers.buf_malloc_cb = buf_malloc; + handlers.buf_free_cb = buf_free; + handlers.align_pointer_cb = buf_align; + handlers.invalidate_cache_cb = NULL; + handlers.width_to_stride_cb = width_to_stride; +} + +lv_draw_buf_handlers_t * lv_draw_buf_get_handlers(void) +{ + return &handlers; +} + +uint32_t lv_draw_buf_width_to_stride(uint32_t w, lv_color_format_t color_format) +{ + if(handlers.width_to_stride_cb) return handlers.width_to_stride_cb(w, color_format); + else return 0; +} + +void * lv_draw_buf_align(void * data, lv_color_format_t color_format) +{ + if(handlers.align_pointer_cb) return handlers.align_pointer_cb(data, color_format); + else return NULL; +} + +void lv_draw_buf_invalidate_cache(void * buf, uint32_t stride, lv_color_format_t color_format, const lv_area_t * area) +{ + if(handlers.invalidate_cache_cb) handlers.invalidate_cache_cb(buf, stride, color_format, area); +} + +void lv_draw_buf_clear(lv_draw_buf_t * draw_buf, const lv_area_t * a) +{ + LV_ASSERT_NULL(draw_buf); + if(a && lv_area_get_width(a) < 0) return; + if(a && lv_area_get_height(a) < 0) return; + + const lv_image_header_t * header = &draw_buf->header; + uint32_t stride = header->stride; + + if(a == NULL) { + lv_memzero(draw_buf->data, header->h * stride); + } + else { + uint8_t * bufc; + uint32_t line_length; + int32_t start_y, end_y; + uint8_t px_size = lv_color_format_get_size(header->cf); + bufc = lv_draw_buf_goto_xy(draw_buf, a->x1, a->y1); + line_length = lv_area_get_width(a) * px_size; + start_y = a->y1; + end_y = a->y2; + for(; start_y <= end_y; start_y++) { + lv_memzero(bufc, line_length); + bufc += stride; + } + } +} + +void lv_draw_buf_copy(lv_draw_buf_t * dest, const lv_area_t * dest_area, + const lv_draw_buf_t * src, const lv_area_t * src_area) +{ + uint8_t * dest_bufc; + uint8_t * src_bufc; + int32_t line_width; + + if(dest_area == NULL) line_width = dest->header.w; + else line_width = lv_area_get_width(dest_area); + + /*Check source and dest area have same width*/ + if((src_area == NULL && line_width != src->header.w) || \ + (src_area != NULL && line_width != lv_area_get_width(src_area))) { + LV_ASSERT_MSG(0, "Source and destination areas have different width"); + return; + } + + if(src_area) src_bufc = lv_draw_buf_goto_xy(src, src_area->x1, src_area->y1); + else src_bufc = src->data; + + if(dest_area) dest_bufc = lv_draw_buf_goto_xy(dest, dest_area->x1, dest_area->y1); + else dest_bufc = dest->data; + + int32_t start_y, end_y; + if(dest_area) { + start_y = dest_area->y1; + end_y = dest_area->y2; + } + else { + start_y = 0; + end_y = dest->header.h - 1; + } + + uint32_t dest_stride = dest->header.stride; + uint32_t src_stride = src->header.stride; + line_width *= lv_color_format_get_size(dest->header.cf); /*Pixel to bytes*/ + + for(; start_y <= end_y; start_y++) { + lv_memcpy(dest_bufc, src_bufc, line_width); + dest_bufc += dest_stride; + src_bufc += src_stride; + } +} + +lv_result_t lv_draw_buf_init(lv_draw_buf_t * draw_buf, uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride, + void * data, uint32_t data_size) +{ + LV_ASSERT_NULL(draw_buf); + if(draw_buf == NULL) return LV_RESULT_INVALID; + + lv_memzero(draw_buf, sizeof(lv_draw_buf_t)); + if(stride == 0) stride = lv_draw_buf_width_to_stride(w, cf); + if(stride * h > data_size) { + LV_LOG_WARN("Data size too small, required: %" LV_PRId32 ", provided: %" LV_PRId32, stride * h, + data_size); + return LV_RESULT_INVALID; + } + + lv_image_header_init(&draw_buf->header, w, h, cf, stride, 0); + draw_buf->data = lv_draw_buf_align(data, cf); + draw_buf->unaligned_data = data; + draw_buf->data_size = data_size; + if(draw_buf->data != draw_buf->unaligned_data) { + LV_LOG_WARN("Data is not aligned, ignored"); + } + return LV_RESULT_OK; +} + +lv_draw_buf_t * lv_draw_buf_create(uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride) +{ + lv_draw_buf_t * draw_buf = lv_malloc_zeroed(sizeof(lv_draw_buf_t)); + LV_ASSERT_MALLOC(draw_buf); + if(draw_buf == NULL) return NULL; + if(stride == 0) stride = lv_draw_buf_width_to_stride(w, cf); + + uint32_t size = _calculate_draw_buf_size(w, h, cf, stride); + + void * buf = draw_buf_malloc(size, cf); + /*Do not assert here as LVGL or the app might just want to try creating a draw_buf*/ + if(buf == NULL) { + LV_LOG_WARN("No memory: %"LV_PRIu32"x%"LV_PRIu32", cf: %d, stride: %"LV_PRIu32", %"LV_PRIu32"Byte, ", + w, h, cf, stride, size); + lv_free(draw_buf); + return NULL; + } + + draw_buf->header.w = w; + draw_buf->header.h = h; + draw_buf->header.cf = cf; + draw_buf->header.flags = LV_IMAGE_FLAGS_MODIFIABLE | LV_IMAGE_FLAGS_ALLOCATED; + draw_buf->header.stride = stride; + draw_buf->header.magic = LV_IMAGE_HEADER_MAGIC; + draw_buf->data = lv_draw_buf_align(buf, cf); + draw_buf->unaligned_data = buf; + draw_buf->data_size = size; + return draw_buf; +} + +lv_draw_buf_t * lv_draw_buf_dup(const lv_draw_buf_t * draw_buf) +{ + const lv_image_header_t * header = &draw_buf->header; + lv_draw_buf_t * new_buf = lv_draw_buf_create(header->w, header->h, header->cf, header->stride); + if(new_buf == NULL) return NULL; + + new_buf->header.flags = draw_buf->header.flags; + new_buf->header.flags |= LV_IMAGE_FLAGS_MODIFIABLE | LV_IMAGE_FLAGS_ALLOCATED; + + /*Choose the smaller size to copy*/ + uint32_t size = LV_MIN(draw_buf->data_size, new_buf->data_size); + + /*Copy image data*/ + lv_memcpy(new_buf->data, draw_buf->data, size); + return new_buf; +} + +lv_draw_buf_t * lv_draw_buf_reshape(lv_draw_buf_t * draw_buf, lv_color_format_t cf, uint32_t w, uint32_t h, + uint32_t stride) +{ + if(draw_buf == NULL) return NULL; + + /*If color format is unknown, keep using the original color format.*/ + if(cf == LV_COLOR_FORMAT_UNKNOWN) cf = draw_buf->header.cf; + if(stride == 0) stride = lv_draw_buf_width_to_stride(w, cf); + + uint32_t size = _calculate_draw_buf_size(w, h, cf, stride); + + if(size > draw_buf->data_size) { + LV_LOG_INFO("Draw buf too small for new shape"); + return NULL; + } + + draw_buf->header.cf = cf; + draw_buf->header.w = w; + draw_buf->header.h = h; + draw_buf->header.stride = stride; + + return draw_buf; +} + +void lv_draw_buf_destroy(lv_draw_buf_t * buf) +{ + LV_ASSERT_NULL(buf); + if(buf == NULL) return; + + if(buf->header.flags & LV_IMAGE_FLAGS_ALLOCATED) { + draw_buf_free(buf->unaligned_data); + lv_free(buf); + } + else { + LV_LOG_ERROR("draw buffer is not allocated, ignored"); + } +} + +void * lv_draw_buf_goto_xy(const lv_draw_buf_t * buf, uint32_t x, uint32_t y) +{ + LV_ASSERT_NULL(buf); + if(buf == NULL) return NULL; + + uint8_t * data = buf->data; + data += buf->header.stride * y; + + if(x == 0) + return data; + + return data + x * lv_color_format_get_size(buf->header.cf); +} + +lv_draw_buf_t * lv_draw_buf_adjust_stride(const lv_draw_buf_t * src, uint32_t stride) +{ + LV_ASSERT_NULL(src); + LV_ASSERT_NULL(src->data); + if(src == NULL) return NULL; + if(src->data == NULL) return NULL; + + const lv_image_header_t * header = &src->header; + + /*Use global stride*/ + if(stride == 0) stride = lv_draw_buf_width_to_stride(header->w, header->cf); + + /*Check if stride already match*/ + if(header->stride == stride) return NULL; + + /*Calculate the minimal stride allowed from bpp*/ + uint32_t bpp = lv_color_format_get_bpp(header->cf); + uint32_t min_stride = (header->w * bpp + 7) >> 3; + if(stride < min_stride) { + LV_LOG_WARN("New stride is too small. min: %" LV_PRId32, min_stride); + return NULL; + } + + lv_draw_buf_t * dst = lv_draw_buf_create(header->w, header->h, header->cf, stride); + if(dst == NULL) return NULL; + + uint8_t * dst_data = dst->data; + const uint8_t * src_data = src->data; + for(int32_t y = 0; y < src->header.h; y++) { + lv_memcpy(dst_data, src_data, min_stride); + src_data += src->header.stride; + dst_data += dst->header.stride; + } + + return dst; +} + +lv_result_t lv_draw_buf_premultiply(lv_draw_buf_t * draw_buf) +{ + LV_ASSERT_NULL(draw_buf); + if(draw_buf == NULL) return LV_RESULT_INVALID; + + if(draw_buf->header.flags & LV_IMAGE_FLAGS_PREMULTIPLIED) return LV_RESULT_INVALID; + if((draw_buf->header.flags & LV_IMAGE_FLAGS_MODIFIABLE) == 0) { + LV_LOG_WARN("draw buf is not modifiable: 0x%04x", draw_buf->header.flags); + return LV_RESULT_INVALID; + } + + /*Premultiply color with alpha, do case by case by judging color format*/ + lv_color_format_t cf = draw_buf->header.cf; + if(LV_COLOR_FORMAT_IS_INDEXED(cf)) { + int size = LV_COLOR_INDEXED_PALETTE_SIZE(cf); + lv_color32_t * palette = (lv_color32_t *)draw_buf->data; + for(int i = 0; i < size; i++) { + lv_color_premultiply(&palette[i]); + } + } + else if(cf == LV_COLOR_FORMAT_ARGB8888) { + uint32_t h = draw_buf->header.h; + uint32_t w = draw_buf->header.w; + uint32_t stride = draw_buf->header.stride; + uint8_t * line = (uint8_t *)draw_buf->data; + for(uint32_t y = 0; y < h; y++) { + lv_color32_t * pixel = (lv_color32_t *)line; + for(uint32_t x = 0; x < w; x++) { + lv_color_premultiply(pixel); + pixel++; + } + line += stride; + } + } + else if(cf == LV_COLOR_FORMAT_RGB565A8) { + uint32_t h = draw_buf->header.h; + uint32_t w = draw_buf->header.w; + uint32_t stride = draw_buf->header.stride; + uint32_t alpha_stride = stride / 2; + uint8_t * line = (uint8_t *)draw_buf->data; + lv_opa_t * alpha = (lv_opa_t *)(line + stride * h); + for(uint32_t y = 0; y < h; y++) { + lv_color16_t * pixel = (lv_color16_t *)line; + for(uint32_t x = 0; x < w; x++) { + lv_color16_premultiply(pixel, alpha[x]); + pixel++; + } + line += stride; + alpha += alpha_stride; + } + } + else if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf)) { + /*Pass*/ + } + else { + LV_LOG_WARN("draw buf has no alpha, cf: %d", cf); + } + + draw_buf->header.flags |= LV_IMAGE_FLAGS_PREMULTIPLIED; + + return LV_RESULT_OK; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void * buf_malloc(size_t size_bytes, lv_color_format_t color_format) +{ + LV_UNUSED(color_format); + + /*Allocate larger memory to be sure it can be aligned as needed*/ + size_bytes += LV_DRAW_BUF_ALIGN - 1; + return lv_malloc(size_bytes); +} + +static void buf_free(void * buf) +{ + lv_free(buf); +} + +static void * buf_align(void * buf, lv_color_format_t color_format) +{ + LV_UNUSED(color_format); + + uint8_t * buf_u8 = buf; + if(buf_u8) { + buf_u8 += LV_DRAW_BUF_ALIGN - 1; + buf_u8 = (uint8_t *)((lv_uintptr_t) buf_u8 & ~(LV_DRAW_BUF_ALIGN - 1)); + } + return buf_u8; +} + +static uint32_t width_to_stride(uint32_t w, lv_color_format_t color_format) +{ + uint32_t width_byte; + width_byte = w * lv_color_format_get_bpp(color_format); + width_byte = (width_byte + 7) >> 3; /*Round up*/ + return (width_byte + LV_DRAW_BUF_STRIDE_ALIGN - 1) & ~(LV_DRAW_BUF_STRIDE_ALIGN - 1); +} + +static void * draw_buf_malloc(size_t size_bytes, lv_color_format_t color_format) +{ + if(handlers.buf_malloc_cb) return handlers.buf_malloc_cb(size_bytes, color_format); + else return NULL; +} + +static void draw_buf_free(void * buf) +{ + if(handlers.buf_free_cb) handlers.buf_free_cb(buf); +} + +/** + * For given width, height, color format, and stride, calculate the size needed for a new draw buffer. + */ +static uint32_t _calculate_draw_buf_size(uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride) +{ + uint32_t size; + + if(stride == 0) stride = lv_draw_buf_width_to_stride(w, cf); + + size = stride * h; + if(cf == LV_COLOR_FORMAT_RGB565A8) { + size += (stride / 2) * h; /*A8 mask*/ + } + else if(LV_COLOR_FORMAT_IS_INDEXED(cf)) { + /*@todo we have to include palette right before image data*/ + size += LV_COLOR_INDEXED_PALETTE_SIZE(cf) * 4; + } + + return size; +} diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_buf.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_buf.h new file mode 100644 index 000000000..4b14262cf --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_buf.h @@ -0,0 +1,251 @@ +/** + * @file lv_draw_buf.h + * + */ + +#ifndef LV_DRAW_BUF_H +#define LV_DRAW_BUF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../misc/lv_area.h" +#include "../misc/lv_color.h" +#include "lv_image_buf.h" + +/********************* + * DEFINES + *********************/ + +/*Use this value to let LVGL calculate stride automatically*/ +#define LV_STRIDE_AUTO 0 +LV_EXPORT_CONST_INT(LV_STRIDE_AUTO); + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_image_header_t header; + uint32_t data_size; /*Total buf size in bytes*/ + void * data; + void * unaligned_data; /*Unaligned address of `data`, used internally by lvgl*/ +} lv_draw_buf_t; + +/** + * Stride alignment for draw buffers. + * It may vary between different color formats and hardware. + * Refine it to suit your needs. + */ + +#define _LV_DRAW_BUF_STRIDE(w, cf) \ + ((((w) * LV_COLOR_FORMAT_GET_BPP(cf) + 7) / 8 + (LV_DRAW_BUF_STRIDE_ALIGN) - 1) & ~((LV_DRAW_BUF_STRIDE_ALIGN) - 1)) + +#define _LV_DRAW_BUF_SIZE(w, h, cf) \ + (_LV_DRAW_BUF_STRIDE(w, cf) * (h)) + +/** + * Define a static draw buffer with the given width, height, and color format. + * Stride alignment is set to LV_DRAW_BUF_STRIDE_ALIGN. + */ +#define LV_DRAW_BUF_DEFINE(name, _w, _h, _cf) \ + static uint8_t buf_##name[_LV_DRAW_BUF_SIZE(_w, _h, _cf)]; \ + static lv_draw_buf_t name = { \ + .header = { \ + .w = (_w), \ + .h = (_h), \ + .cf = (_cf), \ + .flags = LV_IMAGE_FLAGS_MODIFIABLE, \ + .stride = _LV_DRAW_BUF_STRIDE(_w, _cf), \ + }, \ + .data_size = sizeof(buf_##name), \ + .data = buf_##name, \ + .unaligned_data = buf_##name, \ + } + +typedef void * (*lv_draw_buf_malloc_cb)(size_t size, lv_color_format_t color_format); + +typedef void (*lv_draw_buf_free_cb)(void * draw_buf); + +typedef void * (*lv_draw_buf_align_cb)(void * buf, lv_color_format_t color_format); + +typedef void (*lv_draw_buf_invalidate_cache_cb)(void * buf, uint32_t stride, lv_color_format_t color_format, + const lv_area_t * area); + +typedef uint32_t (*lv_draw_buf_width_to_stride_cb)(uint32_t w, lv_color_format_t color_format); + +typedef struct { + lv_draw_buf_malloc_cb buf_malloc_cb; + lv_draw_buf_free_cb buf_free_cb; + lv_draw_buf_align_cb align_pointer_cb; + lv_draw_buf_invalidate_cache_cb invalidate_cache_cb; + lv_draw_buf_width_to_stride_cb width_to_stride_cb; +} lv_draw_buf_handlers_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Called internally to initialize the draw_buf_handlers in lv_global + */ +void _lv_draw_buf_init_handlers(void); + +/** + * Get the struct which holds the callbacks for draw buf management. + * Custom callback can be set on the returned value + * @return pointer to the struct of handlers + */ +lv_draw_buf_handlers_t * lv_draw_buf_get_handlers(void); + +/** + * Align the address of a buffer. The buffer needs to be large enough for the real data after alignment + * @param buf the data to align + * @param color_format the color format of the buffer + * @return the aligned buffer + */ +void * lv_draw_buf_align(void * buf, lv_color_format_t color_format); + +/** + * Invalidate the cache of the buffer + * @param buf a memory address to invalidate + * @param stride stride of the buffer + * @param color_format color format of the buffer + * @param area the area to invalidate in the buffer + */ +void lv_draw_buf_invalidate_cache(void * buf, uint32_t stride, lv_color_format_t color_format, const lv_area_t * area); + +/** + * Calculate the stride in bytes based on a width and color format + * @param w the width in pixels + * @param color_format the color format + * @return the stride in bytes + */ +uint32_t lv_draw_buf_width_to_stride(uint32_t w, lv_color_format_t color_format); + +/** + * Clear an area on the buffer + * @param draw_buf pointer to draw buffer + * @param a the area to clear, or NULL to clear the whole buffer + */ +void lv_draw_buf_clear(lv_draw_buf_t * draw_buf, const lv_area_t * a); + +/** + * Copy an area from a buffer to an other + * @param dest pointer to the destination draw buffer + * @param dest_area the area to copy from the destination buffer, if NULL, use the whole buffer + * @param src pointer to the source draw buffer + * @param src_area the area to copy from the destination buffer, if NULL, use the whole buffer + * @note `dest_area` and `src_area` should have the same width and height + * @note `dest` and `src` should have same color format. Color converting is not supported fow now. + */ +void lv_draw_buf_copy(lv_draw_buf_t * dest, const lv_area_t * dest_area, + const lv_draw_buf_t * src, const lv_area_t * src_area); + +/** + * Note: Eventually, lv_draw_buf_malloc/free will be kept as private. + * For now, we use `create` to distinguish with malloc. + * + * Create an draw buf by allocating struct for `lv_draw_buf_t` and allocating a buffer for it + * that meets specified requirements. + * + * @param w the buffer width in pixels + * @param h the buffer height in pixels + * @param cf the color format for image + * @param stride the stride in bytes for image. Use 0 for automatic calculation based on + * w, cf, and global stride alignment configuration. + */ +lv_draw_buf_t * lv_draw_buf_create(uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride); + +/** + * Initialize a draw buf with the given buffer and parameters. + * @param draw_buf the draw buf to initialize + * @param w the buffer width in pixels + * @param h the buffer height in pixels + * @param cf the color format + * @param stride the stride in bytes. Use 0 for automatic calculation + * @param data the buffer used for drawing. Unaligned `data` will be aligned internally + * @param data_size the size of the buffer in bytes + * @return return LV_RESULT_OK on success, LV_RESULT_INVALID otherwise + */ +lv_result_t lv_draw_buf_init(lv_draw_buf_t * draw_buf, uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride, + void * data, uint32_t data_size); + +/** + * Duplicate a draw buf with same image size, stride and color format. Copy the image data too. + * @param draw_buf the draw buf to duplicate + * @return the duplicated draw buf on success, NULL if failed + */ +lv_draw_buf_t * lv_draw_buf_dup(const lv_draw_buf_t * draw_buf); + +/** + * Keep using the existing memory, reshape the draw buffer to the given width and height. + * Return NULL if data_size is smaller than the required size. + * @param draw_buf pointer to a draw buffer + * @param cf the new color format, use 0 or LV_COLOR_FORMAT_UNKNOWN to keep using the original color format. + * @param w the new width in pixels + * @param h the new height in pixels + * @param stride the stride in bytes for image. Use 0 for automatic calculation. + */ +lv_draw_buf_t * lv_draw_buf_reshape(lv_draw_buf_t * draw_buf, lv_color_format_t cf, uint32_t w, uint32_t h, + uint32_t stride); + +/** + * Destroy a draw buf by free the actual buffer if it's marked as LV_IMAGE_FLAGS_MODIFIABLE in header. + * Then free the lv_draw_buf_t struct. + */ +void lv_draw_buf_destroy(lv_draw_buf_t * buf); + +/** + * Return pointer to the buffer at the given coordinates + */ +void * lv_draw_buf_goto_xy(const lv_draw_buf_t * buf, uint32_t x, uint32_t y); + +/** + * Adjust the stride of a draw buf. + */ +lv_draw_buf_t * lv_draw_buf_adjust_stride(const lv_draw_buf_t * src, uint32_t stride); + +/** + * Premultiply draw buffer color with alpha channel. + * If it's already premultiplied, return directly. + * Only color formats with alpha channel will be processed. + * + * @return LV_RESULT_OK: premultiply success + */ +lv_result_t lv_draw_buf_premultiply(lv_draw_buf_t * draw_buf); + +static inline bool lv_draw_buf_has_flag(lv_draw_buf_t * draw_buf, lv_image_flags_t flag) +{ + return draw_buf->header.flags & flag; +} + +/** + * As of now, draw buf share same definition as `lv_image_dsc_t`. + * And is interchangeable with `lv_image_dsc_t`. + */ + +static inline void lv_draw_buf_from_image(lv_draw_buf_t * buf, const lv_image_dsc_t * img) +{ + lv_memcpy(buf, img, sizeof(lv_image_dsc_t)); + buf->unaligned_data = buf->data; +} + +static inline void lv_draw_buf_to_image(const lv_draw_buf_t * buf, lv_image_dsc_t * img) +{ + lv_memcpy(img, buf, sizeof(lv_image_dsc_t)); +} + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_BUF_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_image.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_image.c new file mode 100644 index 000000000..cb89fbda2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_image.c @@ -0,0 +1,262 @@ +/** + * @file lv_draw_img.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_image.h" +#include "../display/lv_display.h" +#include "../misc/lv_log.h" +#include "../misc/lv_math.h" +#include "../core/lv_refr.h" +#include "../stdlib/lv_mem.h" +#include "../stdlib/lv_string.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void img_decode_and_draw(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + lv_image_decoder_dsc_t * decoder_dsc, lv_area_t * relative_decoded_area, + const lv_area_t * img_area, const lv_area_t * clipped_img_area, + lv_draw_image_core_cb draw_core_cb); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_image_dsc_init(lv_draw_image_dsc_t * dsc) +{ + lv_memzero(dsc, sizeof(lv_draw_image_dsc_t)); + dsc->recolor = lv_color_black(); + dsc->opa = LV_OPA_COVER; + dsc->scale_x = LV_SCALE_NONE; + dsc->scale_y = LV_SCALE_NONE; + dsc->antialias = LV_COLOR_DEPTH > 8 ? 1 : 0; + dsc->base.dsc_size = sizeof(lv_draw_image_dsc_t); +} + +void lv_draw_layer(lv_layer_t * layer, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords) +{ + lv_draw_task_t * t = lv_draw_add_task(layer, coords); + + t->draw_dsc = lv_malloc(sizeof(*dsc)); + lv_memcpy(t->draw_dsc, dsc, sizeof(*dsc)); + t->type = LV_DRAW_TASK_TYPE_LAYER; + t->state = LV_DRAW_TASK_STATE_WAITING; + + _lv_image_buf_get_transformed_area(&t->_real_area, lv_area_get_width(coords), lv_area_get_height(coords), + dsc->rotation, dsc->scale_x, dsc->scale_y, &dsc->pivot); + lv_area_move(&t->_real_area, coords->x1, coords->y1); + + lv_layer_t * layer_to_draw = (lv_layer_t *)dsc->src; + layer_to_draw->all_tasks_added = true; + + lv_draw_finalize_task_creation(layer, t); +} + +void lv_draw_image(lv_layer_t * layer, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords) +{ + if(dsc->src == NULL) { + LV_LOG_WARN("Image draw: src is NULL"); + return; + } + if(dsc->opa <= LV_OPA_MIN) return; + + LV_PROFILER_BEGIN; + + lv_draw_image_dsc_t * new_image_dsc = lv_malloc(sizeof(*dsc)); + lv_memcpy(new_image_dsc, dsc, sizeof(*dsc)); + lv_result_t res = lv_image_decoder_get_info(new_image_dsc->src, &new_image_dsc->header); + if(res != LV_RESULT_OK) { + LV_LOG_WARN("Couldn't get info about the image"); + lv_free(new_image_dsc); + return; + } + + lv_draw_task_t * t = lv_draw_add_task(layer, coords); + t->draw_dsc = new_image_dsc; + t->type = LV_DRAW_TASK_TYPE_IMAGE; + + _lv_image_buf_get_transformed_area(&t->_real_area, lv_area_get_width(coords), lv_area_get_height(coords), + dsc->rotation, dsc->scale_x, dsc->scale_y, &dsc->pivot); + lv_area_move(&t->_real_area, coords->x1, coords->y1); + + lv_draw_finalize_task_creation(layer, t); + LV_PROFILER_END; +} + +lv_image_src_t lv_image_src_get_type(const void * src) +{ + if(src == NULL) return LV_IMAGE_SRC_UNKNOWN; + const uint8_t * u8_p = src; + + /*The first byte shows the type of the image source*/ + if(u8_p[0] >= 0x20 && u8_p[0] <= 0x7F) { + return LV_IMAGE_SRC_FILE; /*If it's an ASCII character then it's file name*/ + } + else if(u8_p[0] >= 0x80) { + return LV_IMAGE_SRC_SYMBOL; /*Symbols begins after 0x7F*/ + } + else { + return LV_IMAGE_SRC_VARIABLE; /*`lv_image_dsc_t` is draw to the first byte < 0x20*/ + } +} + +void _lv_draw_image_normal_helper(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords, lv_draw_image_core_cb draw_core_cb) +{ + if(draw_core_cb == NULL) { + LV_LOG_WARN("draw_core_cb is NULL"); + return; + } + + lv_area_t draw_area; + lv_area_copy(&draw_area, coords); + if(draw_dsc->rotation || draw_dsc->scale_x != LV_SCALE_NONE || draw_dsc->scale_y != LV_SCALE_NONE) { + int32_t w = lv_area_get_width(coords); + int32_t h = lv_area_get_height(coords); + + _lv_image_buf_get_transformed_area(&draw_area, w, h, draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, + &draw_dsc->pivot); + + draw_area.x1 += coords->x1; + draw_area.y1 += coords->y1; + draw_area.x2 += coords->x1; + draw_area.y2 += coords->y1; + } + + lv_area_t clipped_img_area; + if(!_lv_area_intersect(&clipped_img_area, &draw_area, draw_unit->clip_area)) { + return; + } + + lv_image_decoder_dsc_t decoder_dsc; + lv_result_t res = lv_image_decoder_open(&decoder_dsc, draw_dsc->src, NULL); + if(res != LV_RESULT_OK) { + LV_LOG_ERROR("Failed to open image"); + return; + } + + img_decode_and_draw(draw_unit, draw_dsc, &decoder_dsc, NULL, coords, &clipped_img_area, draw_core_cb); + + lv_image_decoder_close(&decoder_dsc); +} + +void _lv_draw_image_tiled_helper(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords, lv_draw_image_core_cb draw_core_cb) +{ + if(draw_core_cb == NULL) { + LV_LOG_WARN("draw_core_cb is NULL"); + return; + } + + lv_image_decoder_dsc_t decoder_dsc; + lv_result_t res = lv_image_decoder_open(&decoder_dsc, draw_dsc->src, NULL); + if(res != LV_RESULT_OK) { + LV_LOG_ERROR("Failed to open image"); + return; + } + + int32_t img_w = draw_dsc->header.w; + int32_t img_h = draw_dsc->header.h; + + lv_area_t tile_area = *coords; + lv_area_set_width(&tile_area, img_w); + lv_area_set_height(&tile_area, img_h); + + int32_t tile_x_start = tile_area.x1; + + lv_area_t relative_decoded_area = { + .x1 = LV_COORD_MIN, + .y1 = LV_COORD_MIN, + .x2 = LV_COORD_MIN, + .y2 = LV_COORD_MIN, + }; + + while(tile_area.y1 <= draw_unit->clip_area->y2) { + while(tile_area.x1 <= draw_unit->clip_area->x2) { + + lv_area_t clipped_img_area; + if(_lv_area_intersect(&clipped_img_area, &tile_area, draw_unit->clip_area)) { + img_decode_and_draw(draw_unit, draw_dsc, &decoder_dsc, &relative_decoded_area, &tile_area, &clipped_img_area, + draw_core_cb); + } + + tile_area.x1 += img_w; + tile_area.x2 += img_w; + } + + tile_area.y1 += img_h; + tile_area.y2 += img_h; + tile_area.x1 = tile_x_start; + tile_area.x2 = tile_x_start + img_w - 1; + } + + lv_image_decoder_close(&decoder_dsc); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void img_decode_and_draw(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + lv_image_decoder_dsc_t * decoder_dsc, lv_area_t * relative_decoded_area, + const lv_area_t * img_area, const lv_area_t * clipped_img_area, + lv_draw_image_core_cb draw_core_cb) +{ + lv_draw_image_sup_t sup; + sup.alpha_color = draw_dsc->recolor; + sup.palette = decoder_dsc->palette; + sup.palette_size = decoder_dsc->palette_size; + + /*The whole image is available, just draw it*/ + if(decoder_dsc->decoded && (relative_decoded_area == NULL || relative_decoded_area->x1 == LV_COORD_MIN)) { + draw_core_cb(draw_unit, draw_dsc, decoder_dsc, &sup, img_area, clipped_img_area); + } + /*Draw in smaller pieces*/ + else { + lv_area_t relative_full_area_to_decode = *clipped_img_area; + lv_area_move(&relative_full_area_to_decode, -img_area->x1, -img_area->y1); + lv_area_t tmp; + if(relative_decoded_area == NULL) relative_decoded_area = &tmp; + relative_decoded_area->x1 = LV_COORD_MIN; + relative_decoded_area->y1 = LV_COORD_MIN; + relative_decoded_area->x2 = LV_COORD_MIN; + relative_decoded_area->y2 = LV_COORD_MIN; + lv_result_t res = LV_RESULT_OK; + + while(res == LV_RESULT_OK) { + res = lv_image_decoder_get_area(decoder_dsc, &relative_full_area_to_decode, relative_decoded_area); + + lv_area_t absolute_decoded_area = *relative_decoded_area; + lv_area_move(&absolute_decoded_area, img_area->x1, img_area->y1); + if(res == LV_RESULT_OK) { + /*Limit draw area to the current decoded area and draw the image*/ + lv_area_t clipped_img_area_sub; + if(_lv_area_intersect(&clipped_img_area_sub, clipped_img_area, &absolute_decoded_area)) { + draw_core_cb(draw_unit, draw_dsc, decoder_dsc, &sup, + &absolute_decoded_area, &clipped_img_area_sub); + } + } + } + } +} diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_image.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_image.h new file mode 100644 index 000000000..4965c773e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_image.h @@ -0,0 +1,138 @@ +/** + * @file lv_draw_img.h + * + */ + +#ifndef LV_DRAW_IMAGE_H +#define LV_DRAW_IMAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_draw.h" +#include "lv_image_decoder.h" +#include "lv_image_buf.h" +#include "../misc/lv_style.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_color_t alpha_color; + const lv_color32_t * palette; + uint32_t palette_size : 9; +} lv_draw_image_sup_t; + +typedef struct _lv_draw_image_dsc_t { + lv_draw_dsc_base_t base; + + const void * src; + lv_image_header_t header; + + int32_t rotation; + int32_t scale_x; + int32_t scale_y; + int32_t skew_x; + int32_t skew_y; + lv_point_t pivot; + + lv_color_t recolor; + lv_opa_t recolor_opa; + + lv_opa_t opa; + lv_blend_mode_t blend_mode : 4; + + uint16_t antialias : 1; + uint16_t tile : 1; + lv_draw_image_sup_t * sup; +} lv_draw_image_dsc_t; + +/** + * PErform the actual rendering of a decoded image + * @param draw_unit pointer to a draw unit + * @param draw_dsc the draw descriptor of the image + * @param decoder_dsc pointer to the decoded image's descriptor + * @param sup supplementary data + * @param img_coords the absolute coordinates of the image + * @param clipped_img_area the absolute clip coordinates + */ +typedef void (*lv_draw_image_core_cb)(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup, + const lv_area_t * img_coords, const lv_area_t * clipped_img_area); + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize an image draw descriptor. + * @param dsc pointer to a draw descriptor + */ +void lv_draw_image_dsc_init(lv_draw_image_dsc_t * dsc); + +/** + * Create an image draw task + * @param layer pointer to a layer + * @param dsc pointer to an initialized draw descriptor + * @param coords the coordinates of the image + */ +void lv_draw_image(lv_layer_t * layer, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords); + +/** + * Create a draw task to blend a layer to an other layer + * @param layer pointer to a layer + * @param dsc pointer to an initialized draw descriptor + * @param coords the coordinates of the layer + */ +void lv_draw_layer(lv_layer_t * layer, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords); + +/** + * Get the type of an image source + * @param src pointer to an image source: + * - pointer to an 'lv_image_t' variable (image stored internally and compiled into the code) + * - a path to a file (e.g. "S:/folder/image.bin") + * - or a symbol (e.g. LV_SYMBOL_CLOSE) + * @return type of the image source LV_IMAGE_SRC_VARIABLE/FILE/SYMBOL/UNKNOWN + */ +lv_image_src_t lv_image_src_get_type(const void * src); + +/** + * Can be used by draw units to handle the decoding and + * prepare everything for the actual image rendering + * @param draw_unit pointer to a draw unit + * @param draw_dsc the draw descriptor of the image + * @param coords the absolute coordinates of the image + * @param draw_core_cb a callback to perform the actual rendering + */ +void _lv_draw_image_normal_helper(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords, lv_draw_image_core_cb draw_core_cb); + +/** + * Can be used by draw units for TILED images to handle the decoding and + * prepare everything for the actual image rendering + * @param draw_unit pointer to a draw unit + * @param draw_dsc the draw descriptor of the image + * @param coords the absolute coordinates of the image + * @param draw_core_cb a callback to perform the actual rendering + */ +void _lv_draw_image_tiled_helper(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords, lv_draw_image_core_cb draw_core_cb); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_IMAGE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.c deleted file mode 100644 index 5e67f8885..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.c +++ /dev/null @@ -1,375 +0,0 @@ -/** - * @file lv_draw_img.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_draw_img.h" -#include "lv_img_cache.h" -#include "../hal/lv_hal_disp.h" -#include "../misc/lv_log.h" -#include "../core/lv_refr.h" -#include "../misc/lv_mem.h" -#include "../misc/lv_math.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_res_t /* LV_ATTRIBUTE_FAST_MEM */ decode_and_draw(lv_draw_ctx_t * draw_ctx, - const lv_draw_img_dsc_t * draw_dsc, - const lv_area_t * coords, const void * src); - -static void show_error(lv_draw_ctx_t * draw_ctx, const lv_area_t * coords, const char * msg); -static void draw_cleanup(_lv_img_cache_entry_t * cache); - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void lv_draw_img_dsc_init(lv_draw_img_dsc_t * dsc) -{ - lv_memset_00(dsc, sizeof(lv_draw_img_dsc_t)); - dsc->recolor = lv_color_black(); - dsc->opa = LV_OPA_COVER; - dsc->zoom = LV_IMG_ZOOM_NONE; - dsc->antialias = LV_COLOR_DEPTH > 8 ? 1 : 0; -} - -/** - * Draw an image - * @param coords the coordinates of the image - * @param mask the image will be drawn only in this area - * @param src pointer to a lv_color_t array which contains the pixels of the image - * @param dsc pointer to an initialized `lv_draw_img_dsc_t` variable - */ -void lv_draw_img(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, const lv_area_t * coords, const void * src) -{ - if(src == NULL) { - LV_LOG_WARN("Image draw: src is NULL"); - show_error(draw_ctx, coords, "No\ndata"); - return; - } - - if(dsc->opa <= LV_OPA_MIN) return; - - lv_res_t res = LV_RES_INV; - - if(draw_ctx->draw_img) { - res = draw_ctx->draw_img(draw_ctx, dsc, coords, src); - } - - if(res != LV_RES_OK) { - res = decode_and_draw(draw_ctx, dsc, coords, src); - } - - if(res != LV_RES_OK) { - LV_LOG_WARN("Image draw error"); - show_error(draw_ctx, coords, "No\ndata"); - } -} - -/** - * Get the pixel size of a color format in bits - * @param cf a color format (`LV_IMG_CF_...`) - * @return the pixel size in bits - */ -uint8_t lv_img_cf_get_px_size(lv_img_cf_t cf) -{ - uint8_t px_size = 0; - - switch(cf) { - case LV_IMG_CF_UNKNOWN: - case LV_IMG_CF_RAW: - px_size = 0; - break; - case LV_IMG_CF_TRUE_COLOR: - case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED: - px_size = LV_COLOR_SIZE; - break; - case LV_IMG_CF_TRUE_COLOR_ALPHA: - px_size = LV_IMG_PX_SIZE_ALPHA_BYTE << 3; - break; - case LV_IMG_CF_INDEXED_1BIT: - case LV_IMG_CF_ALPHA_1BIT: - px_size = 1; - break; - case LV_IMG_CF_INDEXED_2BIT: - case LV_IMG_CF_ALPHA_2BIT: - px_size = 2; - break; - case LV_IMG_CF_INDEXED_4BIT: - case LV_IMG_CF_ALPHA_4BIT: - px_size = 4; - break; - case LV_IMG_CF_INDEXED_8BIT: - case LV_IMG_CF_ALPHA_8BIT: - px_size = 8; - break; - default: - px_size = 0; - break; - } - - return px_size; -} - -/** - * Check if a color format is chroma keyed or not - * @param cf a color format (`LV_IMG_CF_...`) - * @return true: chroma keyed; false: not chroma keyed - */ -bool lv_img_cf_is_chroma_keyed(lv_img_cf_t cf) -{ - bool is_chroma_keyed = false; - - switch(cf) { - case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED: - case LV_IMG_CF_RAW_CHROMA_KEYED: - is_chroma_keyed = true; - break; - - default: - is_chroma_keyed = false; - break; - } - - return is_chroma_keyed; -} - -/** - * Check if a color format has alpha channel or not - * @param cf a color format (`LV_IMG_CF_...`) - * @return true: has alpha channel; false: doesn't have alpha channel - */ -bool lv_img_cf_has_alpha(lv_img_cf_t cf) -{ - bool has_alpha = false; - - switch(cf) { - case LV_IMG_CF_TRUE_COLOR_ALPHA: - case LV_IMG_CF_RAW_ALPHA: - case LV_IMG_CF_INDEXED_1BIT: - case LV_IMG_CF_INDEXED_2BIT: - case LV_IMG_CF_INDEXED_4BIT: - case LV_IMG_CF_INDEXED_8BIT: - case LV_IMG_CF_ALPHA_1BIT: - case LV_IMG_CF_ALPHA_2BIT: - case LV_IMG_CF_ALPHA_4BIT: - case LV_IMG_CF_ALPHA_8BIT: - has_alpha = true; - break; - default: - has_alpha = false; - break; - } - - return has_alpha; -} - -/** - * Get the type of an image source - * @param src pointer to an image source: - * - pointer to an 'lv_img_t' variable (image stored internally and compiled into the code) - * - a path to a file (e.g. "S:/folder/image.bin") - * - or a symbol (e.g. LV_SYMBOL_CLOSE) - * @return type of the image source LV_IMG_SRC_VARIABLE/FILE/SYMBOL/UNKNOWN - */ -lv_img_src_t lv_img_src_get_type(const void * src) -{ - lv_img_src_t img_src_type = LV_IMG_SRC_UNKNOWN; - - if(src == NULL) return img_src_type; - const uint8_t * u8_p = src; - - /*The first or fourth byte depending on platform endianess shows the type of the image source*/ -#if LV_BIG_ENDIAN_SYSTEM - if(u8_p[3] >= 0x20 && u8_p[3] <= 0x7F) { -#else - if(u8_p[0] >= 0x20 && u8_p[0] <= 0x7F) { -#endif - img_src_type = LV_IMG_SRC_FILE; /*If it's an ASCII character then it's file name*/ - } -#if LV_BIG_ENDIAN_SYSTEM - else if(u8_p[3] >= 0x80) { -#else - else if(u8_p[0] >= 0x80) { -#endif - img_src_type = LV_IMG_SRC_SYMBOL; /*Symbols begins after 0x7F*/ - } - else { - img_src_type = LV_IMG_SRC_VARIABLE; /*`lv_img_dsc_t` is draw to the first byte < 0x20*/ - } - - if(LV_IMG_SRC_UNKNOWN == img_src_type) { - LV_LOG_WARN("lv_img_src_get_type: unknown image type"); - } - - return img_src_type; -} - -void lv_draw_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, - const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format) -{ - if(draw_ctx->draw_img_decoded == NULL) return; - - draw_ctx->draw_img_decoded(draw_ctx, dsc, coords, map_p, color_format); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static lv_res_t LV_ATTRIBUTE_FAST_MEM decode_and_draw(lv_draw_ctx_t * draw_ctx, - const lv_draw_img_dsc_t * draw_dsc, - const lv_area_t * coords, const void * src) -{ - if(draw_dsc->opa <= LV_OPA_MIN) return LV_RES_OK; - - _lv_img_cache_entry_t * cdsc = _lv_img_cache_open(src, draw_dsc->recolor, draw_dsc->frame_id); - - if(cdsc == NULL) return LV_RES_INV; - - lv_img_cf_t cf; - if(lv_img_cf_is_chroma_keyed(cdsc->dec_dsc.header.cf)) cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED; - else if(LV_IMG_CF_ALPHA_8BIT == cdsc->dec_dsc.header.cf) cf = LV_IMG_CF_ALPHA_8BIT; - else if(LV_IMG_CF_RGB565A8 == cdsc->dec_dsc.header.cf) cf = LV_IMG_CF_RGB565A8; - else if(lv_img_cf_has_alpha(cdsc->dec_dsc.header.cf)) cf = LV_IMG_CF_TRUE_COLOR_ALPHA; - else cf = LV_IMG_CF_TRUE_COLOR; - - if(cf == LV_IMG_CF_ALPHA_8BIT) { - if(draw_dsc->angle || draw_dsc->zoom != LV_IMG_ZOOM_NONE) { - /* resume normal method */ - cf = LV_IMG_CF_TRUE_COLOR_ALPHA; - cdsc->dec_dsc.img_data = NULL; - } - } - - if(cdsc->dec_dsc.error_msg != NULL) { - LV_LOG_WARN("Image draw error"); - - show_error(draw_ctx, coords, cdsc->dec_dsc.error_msg); - } - /*The decoder could open the image and gave the entire uncompressed image. - *Just draw it!*/ - else if(cdsc->dec_dsc.img_data) { - lv_area_t map_area_rot; - lv_area_copy(&map_area_rot, coords); - if(draw_dsc->angle || draw_dsc->zoom != LV_IMG_ZOOM_NONE) { - int32_t w = lv_area_get_width(coords); - int32_t h = lv_area_get_height(coords); - - _lv_img_buf_get_transformed_area(&map_area_rot, w, h, draw_dsc->angle, draw_dsc->zoom, &draw_dsc->pivot); - - map_area_rot.x1 += coords->x1; - map_area_rot.y1 += coords->y1; - map_area_rot.x2 += coords->x1; - map_area_rot.y2 += coords->y1; - } - - lv_area_t clip_com; /*Common area of mask and coords*/ - bool union_ok; - union_ok = _lv_area_intersect(&clip_com, draw_ctx->clip_area, &map_area_rot); - /*Out of mask. There is nothing to draw so the image is drawn successfully.*/ - if(union_ok == false) { - draw_cleanup(cdsc); - return LV_RES_OK; - } - - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &clip_com; - lv_draw_img_decoded(draw_ctx, draw_dsc, coords, cdsc->dec_dsc.img_data, cf); - draw_ctx->clip_area = clip_area_ori; - } - /*The whole uncompressed image is not available. Try to read it line-by-line*/ - else { - lv_area_t mask_com; /*Common area of mask and coords*/ - bool union_ok; - union_ok = _lv_area_intersect(&mask_com, draw_ctx->clip_area, coords); - /*Out of mask. There is nothing to draw so the image is drawn successfully.*/ - if(union_ok == false) { - draw_cleanup(cdsc); - return LV_RES_OK; - } - - int32_t width = lv_area_get_width(&mask_com); - - uint8_t * buf = lv_mem_buf_get(lv_area_get_width(&mask_com) * - LV_IMG_PX_SIZE_ALPHA_BYTE); /*+1 because of the possible alpha byte*/ - - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - lv_area_t line; - lv_area_copy(&line, &mask_com); - lv_area_set_height(&line, 1); - int32_t x = mask_com.x1 - coords->x1; - int32_t y = mask_com.y1 - coords->y1; - int32_t row; - lv_res_t read_res; - for(row = mask_com.y1; row <= mask_com.y2; row++) { - lv_area_t mask_line; - union_ok = _lv_area_intersect(&mask_line, clip_area_ori, &line); - if(union_ok == false) continue; - - read_res = lv_img_decoder_read_line(&cdsc->dec_dsc, x, y, width, buf); - if(read_res != LV_RES_OK) { - lv_img_decoder_close(&cdsc->dec_dsc); - LV_LOG_WARN("Image draw can't read the line"); - lv_mem_buf_release(buf); - draw_cleanup(cdsc); - draw_ctx->clip_area = clip_area_ori; - return LV_RES_INV; - } - - draw_ctx->clip_area = &mask_line; - lv_draw_img_decoded(draw_ctx, draw_dsc, &line, buf, cf); - line.y1++; - line.y2++; - y++; - } - draw_ctx->clip_area = clip_area_ori; - lv_mem_buf_release(buf); - } - - draw_cleanup(cdsc); - return LV_RES_OK; -} - - -static void show_error(lv_draw_ctx_t * draw_ctx, const lv_area_t * coords, const char * msg) -{ - lv_draw_rect_dsc_t rect_dsc; - lv_draw_rect_dsc_init(&rect_dsc); - rect_dsc.bg_color = lv_color_white(); - lv_draw_rect(draw_ctx, &rect_dsc, coords); - - lv_draw_label_dsc_t label_dsc; - lv_draw_label_dsc_init(&label_dsc); - lv_draw_label(draw_ctx, &label_dsc, coords, msg, NULL); -} - -static void draw_cleanup(_lv_img_cache_entry_t * cache) -{ - /*Automatically close images with no caching*/ -#if LV_IMG_CACHE_DEF_SIZE == 0 - lv_img_decoder_close(&cache->dec_dsc); -#else - LV_UNUSED(cache); -#endif -} diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.h deleted file mode 100644 index a88a33caf..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.h +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @file lv_draw_img.h - * - */ - -#ifndef LV_DRAW_IMG_H -#define LV_DRAW_IMG_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "lv_img_decoder.h" -#include "lv_img_buf.h" -#include "../misc/lv_style.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - - int16_t angle; - uint16_t zoom; - lv_point_t pivot; - - lv_color_t recolor; - lv_opa_t recolor_opa; - - lv_opa_t opa; - lv_blend_mode_t blend_mode : 4; - - int32_t frame_id; - uint8_t antialias : 1; -} lv_draw_img_dsc_t; - -struct _lv_draw_ctx_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -void lv_draw_img_dsc_init(lv_draw_img_dsc_t * dsc); -/** - * Draw an image - * @param coords the coordinates of the image - * @param mask the image will be drawn only in this area - * @param src pointer to a lv_color_t array which contains the pixels of the image - * @param dsc pointer to an initialized `lv_draw_img_dsc_t` variable - */ -void lv_draw_img(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, const lv_area_t * coords, - const void * src); - - -void lv_draw_img_decoded(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, - const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format); - -/** - * Get the type of an image source - * @param src pointer to an image source: - * - pointer to an 'lv_img_t' variable (image stored internally and compiled into the code) - * - a path to a file (e.g. "S:/folder/image.bin") - * - or a symbol (e.g. LV_SYMBOL_CLOSE) - * @return type of the image source LV_IMG_SRC_VARIABLE/FILE/SYMBOL/UNKNOWN - */ -lv_img_src_t lv_img_src_get_type(const void * src); - -/** - * Get the pixel size of a color format in bits - * @param cf a color format (`LV_IMG_CF_...`) - * @return the pixel size in bits - */ -uint8_t lv_img_cf_get_px_size(lv_img_cf_t cf); - -/** - * Check if a color format is chroma keyed or not - * @param cf a color format (`LV_IMG_CF_...`) - * @return true: chroma keyed; false: not chroma keyed - */ -bool lv_img_cf_is_chroma_keyed(lv_img_cf_t cf); - -/** - * Check if a color format has alpha channel or not - * @param cf a color format (`LV_IMG_CF_...`) - * @return true: has alpha channel; false: doesn't have alpha channel - */ -bool lv_img_cf_has_alpha(lv_img_cf_t cf); - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_IMG_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.c index daf44743f..81a11e87b 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.c @@ -6,13 +6,14 @@ /********************* * INCLUDES *********************/ -#include "lv_draw.h" +#include "../core/lv_obj.h" #include "lv_draw_label.h" #include "../misc/lv_math.h" -#include "../hal/lv_hal_disp.h" -#include "../core/lv_refr.h" +#include "../core/lv_obj_event.h" #include "../misc/lv_bidi.h" #include "../misc/lv_assert.h" +#include "../stdlib/lv_mem.h" +#include "../stdlib/lv_string.h" /********************* * DEFINES @@ -23,18 +24,12 @@ /********************** * TYPEDEFS **********************/ -enum { - CMD_STATE_WAIT, - CMD_STATE_PAR, - CMD_STATE_IN, -}; -typedef uint8_t cmd_state_t; /********************** * STATIC PROTOTYPES **********************/ - -static uint8_t hex_char_to_num(char hex); +static void draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc, const lv_point_t * pos, + const lv_font_t * font, uint32_t letter, lv_draw_glyph_cb_t cb); /********************** * STATIC VARIABLES @@ -52,9 +47,9 @@ static uint8_t hex_char_to_num(char hex); * GLOBAL FUNCTIONS **********************/ -void LV_ATTRIBUTE_FAST_MEM lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc) +void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc) { - lv_memset_00(dsc, sizeof(lv_draw_label_dsc_t)); + lv_memzero(dsc, sizeof(lv_draw_label_dsc_t)); dsc->opa = LV_OPA_COVER; dsc->color = lv_color_black(); dsc->font = LV_FONT_DEFAULT; @@ -63,19 +58,43 @@ void LV_ATTRIBUTE_FAST_MEM lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc) dsc->sel_color = lv_color_black(); dsc->sel_bg_color = lv_palette_main(LV_PALETTE_BLUE); dsc->bidi_dir = LV_BASE_DIR_LTR; + dsc->base.dsc_size = sizeof(lv_draw_label_dsc_t); } -/** - * Write a text - * @param coords coordinates of the label - * @param mask the label will be drawn only in this area - * @param dsc pointer to draw descriptor - * @param txt `\0` terminated text to write - * @param hint pointer to a `lv_draw_label_hint_t` variable. - * It is managed by the draw to speed up the drawing of very long texts (thousands of lines). - */ -void LV_ATTRIBUTE_FAST_MEM lv_draw_label(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, - const lv_area_t * coords, const char * txt, lv_draw_label_hint_t * hint) +void lv_draw_glyph_dsc_init(lv_draw_glyph_dsc_t * dsc) +{ + lv_memzero(dsc, sizeof(lv_draw_glyph_dsc_t)); +} + +LV_ATTRIBUTE_FAST_MEM void lv_draw_label(lv_layer_t * layer, const lv_draw_label_dsc_t * dsc, + const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) return; + if(dsc->text == NULL || dsc->text[0] == '\0') return; + if(dsc->font == NULL) { + LV_LOG_WARN("dsc->font == NULL"); + return; + } + + LV_PROFILER_BEGIN; + lv_draw_task_t * t = lv_draw_add_task(layer, coords); + + t->draw_dsc = lv_malloc(sizeof(*dsc)); + lv_memcpy(t->draw_dsc, dsc, sizeof(*dsc)); + t->type = LV_DRAW_TASK_TYPE_LABEL; + + /*The text is stored in a local variable so malloc memory for it*/ + if(dsc->text_local) { + lv_draw_label_dsc_t * new_dsc = t->draw_dsc; + new_dsc->text = lv_strdup(dsc->text); + } + + lv_draw_finalize_task_creation(layer, t); + LV_PROFILER_END; +} + +LV_ATTRIBUTE_FAST_MEM void lv_draw_character(lv_layer_t * layer, lv_draw_label_dsc_t * dsc, + const lv_point_t * point, uint32_t unicode_letter) { if(dsc->opa <= LV_OPA_MIN) return; if(dsc->font == NULL) { @@ -83,28 +102,52 @@ void LV_ATTRIBUTE_FAST_MEM lv_draw_label(lv_draw_ctx_t * draw_ctx, const lv_draw return; } - if(draw_ctx->draw_letter == NULL) { - LV_LOG_WARN("draw->draw_letter == NULL (there is no function to draw letters)"); - return; - } + if(_lv_text_is_marker(unicode_letter)) return; - lv_draw_label_dsc_t dsc_mod = *dsc; + LV_PROFILER_BEGIN; + lv_font_glyph_dsc_t g; + lv_font_get_glyph_dsc(dsc->font, &g, unicode_letter, 0); + + lv_area_t a; + a.x1 = point->x; + a.y1 = point->y; + a.x2 = a.x1 + g.adv_w; + a.y2 = a.y1 + lv_font_get_line_height(g.resolved_font ? g.resolved_font : dsc->font); + + /*lv_draw_label needs UTF8 text so convert the Unicode character to an UTF8 string */ + uint32_t letter_buf[2]; + letter_buf[0] = _lv_text_unicode_to_encoded(unicode_letter); + letter_buf[1] = '\0'; + + const char * letter_buf_char = (const char *)letter_buf; + +#if LV_BIG_ENDIAN_SYSTEM + while(*letter_buf_char == 0) ++letter_buf_char; +#endif + + dsc->text = letter_buf_char; + dsc->text_local = 1; + + lv_draw_label(layer, dsc, &a); + LV_PROFILER_END; +} + +void lv_draw_label_iterate_characters(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, + const lv_area_t * coords, + lv_draw_glyph_cb_t cb) +{ const lv_font_t * font = dsc->font; int32_t w; - /*No need to waste processor time if string is empty*/ - if(txt == NULL || txt[0] == '\0') - return; - lv_area_t clipped_area; - bool clip_ok = _lv_area_intersect(&clipped_area, coords, draw_ctx->clip_area); + bool clip_ok = _lv_area_intersect(&clipped_area, coords, draw_unit->clip_area); if(!clip_ok) return; lv_text_align_t align = dsc->align; lv_base_dir_t base_dir = dsc->bidi_dir; - lv_bidi_calculate_align(&align, &base_dir, txt); + lv_bidi_calculate_align(&align, &base_dir, dsc->text); if((dsc->flag & LV_TEXT_FLAG_EXPAND) == 0) { /*Normally use the label's width as width*/ @@ -113,8 +156,8 @@ void LV_ATTRIBUTE_FAST_MEM lv_draw_label(lv_draw_ctx_t * draw_ctx, const lv_draw else { /*If EXPAND is enabled then not limit the text's width to the object's width*/ lv_point_t p; - lv_txt_get_size(&p, txt, dsc->font, dsc->letter_space, dsc->line_space, LV_COORD_MAX, - dsc->flag); + lv_text_get_size(&p, dsc->text, dsc->font, dsc->letter_space, dsc->line_space, LV_COORD_MAX, + dsc->flag); w = p.x; } @@ -124,8 +167,7 @@ void LV_ATTRIBUTE_FAST_MEM lv_draw_label(lv_draw_ctx_t * draw_ctx, const lv_draw /*Init variables for the first line*/ int32_t line_width = 0; lv_point_t pos; - pos.x = coords->x1; - pos.y = coords->y1; + lv_point_set(&pos, coords->x1, coords->y1); int32_t x_ofs = 0; int32_t y_ofs = 0; @@ -137,51 +179,53 @@ void LV_ATTRIBUTE_FAST_MEM lv_draw_label(lv_draw_ctx_t * draw_ctx, const lv_draw int32_t last_line_start = -1; /*Check the hint to use the cached info*/ - if(hint && y_ofs == 0 && coords->y1 < 0) { + if(dsc->hint && y_ofs == 0 && coords->y1 < 0) { /*If the label changed too much recalculate the hint.*/ - if(LV_ABS(hint->coord_y - coords->y1) > LV_LABEL_HINT_UPDATE_TH - 2 * line_height) { - hint->line_start = -1; + if(LV_ABS(dsc->hint->coord_y - coords->y1) > LV_LABEL_HINT_UPDATE_TH - 2 * line_height) { + dsc->hint->line_start = -1; } - last_line_start = hint->line_start; + last_line_start = dsc->hint->line_start; } /*Use the hint if it's valid*/ - if(hint && last_line_start >= 0) { + if(dsc->hint && last_line_start >= 0) { line_start = last_line_start; - pos.y += hint->y; + pos.y += dsc->hint->y; } - uint32_t line_end = line_start + _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, NULL, dsc->flag); + uint32_t line_end = line_start + _lv_text_get_next_line(&dsc->text[line_start], font, dsc->letter_space, w, NULL, + dsc->flag); /*Go the first visible line*/ - while(pos.y + line_height_font < draw_ctx->clip_area->y1) { + while(pos.y + line_height_font < draw_unit->clip_area->y1) { /*Go to next line*/ line_start = line_end; - line_end += _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, NULL, dsc->flag); + line_end += _lv_text_get_next_line(&dsc->text[line_start], font, dsc->letter_space, w, NULL, dsc->flag); pos.y += line_height; /*Save at the threshold coordinate*/ - if(hint && pos.y >= -LV_LABEL_HINT_UPDATE_TH && hint->line_start < 0) { - hint->line_start = line_start; - hint->y = pos.y - coords->y1; - hint->coord_y = coords->y1; + if(dsc->hint && pos.y >= -LV_LABEL_HINT_UPDATE_TH && dsc->hint->line_start < 0) { + dsc->hint->line_start = line_start; + dsc->hint->y = pos.y - coords->y1; + dsc->hint->coord_y = coords->y1; } - if(txt[line_start] == '\0') return; + if(dsc->text[line_start] == '\0') return; } /*Align to middle*/ if(align == LV_TEXT_ALIGN_CENTER) { - line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag); + line_width = lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space); pos.x += (lv_area_get_width(coords) - line_width) / 2; } /*Align to the right*/ else if(align == LV_TEXT_ALIGN_RIGHT) { - line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag); + line_width = lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space); pos.x += lv_area_get_width(coords) - line_width; } + uint32_t sel_start = dsc->sel_start; uint32_t sel_end = dsc->sel_end; if(sel_start > sel_end) { @@ -189,229 +233,213 @@ void LV_ATTRIBUTE_FAST_MEM lv_draw_label(lv_draw_ctx_t * draw_ctx, const lv_draw sel_start = sel_end; sel_end = tmp; } - lv_draw_line_dsc_t line_dsc; - if((dsc->decor & LV_TEXT_DECOR_UNDERLINE) || (dsc->decor & LV_TEXT_DECOR_STRIKETHROUGH)) { - lv_draw_line_dsc_init(&line_dsc); - line_dsc.color = dsc->color; - line_dsc.width = font->underline_thickness ? font->underline_thickness : 1; - line_dsc.opa = dsc->opa; - line_dsc.blend_mode = dsc->blend_mode; - } + lv_area_t bg_coords; + lv_draw_glyph_dsc_t draw_letter_dsc; + lv_draw_glyph_dsc_init(&draw_letter_dsc); + draw_letter_dsc.opa = dsc->opa; + draw_letter_dsc.bg_coords = &bg_coords; + draw_letter_dsc.color = dsc->color; - cmd_state_t cmd_state = CMD_STATE_WAIT; + lv_draw_fill_dsc_t fill_dsc; + lv_draw_fill_dsc_init(&fill_dsc); + fill_dsc.opa = dsc->opa; + int32_t underline_width = font->underline_thickness ? font->underline_thickness : 1; + int32_t line_start_x; uint32_t i; - uint32_t par_start = 0; - lv_color_t recolor = lv_color_black(); - lv_color_t color = lv_color_black(); int32_t letter_w; - lv_draw_rect_dsc_t draw_dsc_sel; - lv_draw_rect_dsc_init(&draw_dsc_sel); - draw_dsc_sel.bg_color = dsc->sel_bg_color; - - int32_t pos_x_start = pos.x; /*Write out all lines*/ - while(txt[line_start] != '\0') { + while(dsc->text[line_start] != '\0') { pos.x += x_ofs; + line_start_x = pos.x; /*Write all letter of a line*/ - cmd_state = CMD_STATE_WAIT; - i = 0; + i = 0; #if LV_USE_BIDI - char * bidi_txt = lv_mem_buf_get(line_end - line_start + 1); - _lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, base_dir, NULL, 0); + char * bidi_txt = lv_malloc(line_end - line_start + 1); + LV_ASSERT_MALLOC(bidi_txt); + _lv_bidi_process_paragraph(dsc->text + line_start, bidi_txt, line_end - line_start, base_dir, NULL, 0); #else - const char * bidi_txt = txt + line_start; + const char * bidi_txt = dsc->text + line_start; #endif while(i < line_end - line_start) { uint32_t logical_char_pos = 0; if(sel_start != 0xFFFF && sel_end != 0xFFFF) { #if LV_USE_BIDI - logical_char_pos = _lv_txt_encoded_get_char_id(txt, line_start); - uint32_t t = _lv_txt_encoded_get_char_id(bidi_txt, i); + logical_char_pos = _lv_text_encoded_get_char_id(dsc->text, line_start); + uint32_t t = _lv_text_encoded_get_char_id(bidi_txt, i); logical_char_pos += _lv_bidi_get_logical_pos(bidi_txt, NULL, line_end - line_start, base_dir, t, NULL); #else - logical_char_pos = _lv_txt_encoded_get_char_id(txt, line_start + i); + logical_char_pos = _lv_text_encoded_get_char_id(dsc->text, line_start + i); #endif } uint32_t letter; uint32_t letter_next; - _lv_txt_encoded_letter_next_2(bidi_txt, &letter, &letter_next, &i); - /*Handle the re-color command*/ - if((dsc->flag & LV_TEXT_FLAG_RECOLOR) != 0) { - if(letter == (uint32_t)LV_TXT_COLOR_CMD[0]) { - if(cmd_state == CMD_STATE_WAIT) { /*Start char*/ - par_start = i; - cmd_state = CMD_STATE_PAR; - continue; - } - else if(cmd_state == CMD_STATE_PAR) { /*Other start char in parameter escaped cmd. char*/ - cmd_state = CMD_STATE_WAIT; - } - else if(cmd_state == CMD_STATE_IN) { /*Command end*/ - cmd_state = CMD_STATE_WAIT; - continue; - } - } - - /*Skip the color parameter and wait the space after it*/ - if(cmd_state == CMD_STATE_PAR) { - if(letter == ' ') { - /*Get the parameter*/ - if(i - par_start == LABEL_RECOLOR_PAR_LENGTH + 1) { - char buf[LABEL_RECOLOR_PAR_LENGTH + 1]; - lv_memcpy_small(buf, &bidi_txt[par_start], LABEL_RECOLOR_PAR_LENGTH); - buf[LABEL_RECOLOR_PAR_LENGTH] = '\0'; - int r, g, b; - r = (hex_char_to_num(buf[0]) << 4) + hex_char_to_num(buf[1]); - g = (hex_char_to_num(buf[2]) << 4) + hex_char_to_num(buf[3]); - b = (hex_char_to_num(buf[4]) << 4) + hex_char_to_num(buf[5]); - recolor = lv_color_make(r, g, b); - } - else { - recolor.full = dsc->color.full; - } - cmd_state = CMD_STATE_IN; /*After the parameter the text is in the command*/ - } - continue; - } - } - - color = dsc->color; - - if(cmd_state == CMD_STATE_IN) color = recolor; + _lv_text_encoded_letter_next_2(bidi_txt, &letter, &letter_next, &i); letter_w = lv_font_get_glyph_width(font, letter, letter_next); - if(sel_start != 0xFFFF && sel_end != 0xFFFF) { - if(logical_char_pos >= sel_start && logical_char_pos < sel_end) { - lv_area_t sel_coords; - sel_coords.x1 = pos.x; - sel_coords.y1 = pos.y; - sel_coords.x2 = pos.x + letter_w + dsc->letter_space - 1; - sel_coords.y2 = pos.y + line_height - 1; - lv_draw_rect(draw_ctx, &draw_dsc_sel, &sel_coords); - color = dsc->sel_color; + /*Always set the bg_coordinates for placeholder drawing*/ + bg_coords.x1 = pos.x; + bg_coords.y1 = pos.y; + bg_coords.x2 = pos.x + letter_w - 1; + bg_coords.y2 = pos.y + line_height - 1; + + if(i >= line_end - line_start) { + if(dsc->decor & LV_TEXT_DECOR_UNDERLINE) { + lv_area_t fill_area; + fill_area.x1 = line_start_x; + fill_area.x2 = pos.x + letter_w - 1; + fill_area.y1 = pos.y + font->line_height - font->base_line - font->underline_position; + fill_area.y2 = fill_area.y1 + underline_width - 1; + + fill_dsc.color = dsc->color; + cb(draw_unit, NULL, &fill_dsc, &fill_area); + } + if(dsc->decor & LV_TEXT_DECOR_STRIKETHROUGH) { + lv_area_t fill_area; + fill_area.x1 = line_start_x; + fill_area.x2 = pos.x + letter_w - 1; + fill_area.y1 = pos.y + (font->line_height - font->base_line) * 2 / 3 + font->underline_thickness / 2; + fill_area.y2 = fill_area.y1 + underline_width - 1; + + fill_dsc.color = dsc->color; + cb(draw_unit, NULL, &fill_dsc, &fill_area); } } - dsc_mod.color = color; - lv_draw_letter(draw_ctx, &dsc_mod, &pos, letter); + if(sel_start != 0xFFFF && sel_end != 0xFFFF && logical_char_pos >= sel_start && logical_char_pos < sel_end) { + draw_letter_dsc.color = dsc->sel_color; + fill_dsc.color = dsc->sel_bg_color; + cb(draw_unit, NULL, &fill_dsc, &bg_coords); + } + else { + draw_letter_dsc.color = dsc->color; + } + + draw_letter(draw_unit, &draw_letter_dsc, &pos, font, letter, cb); if(letter_w > 0) { pos.x += letter_w + dsc->letter_space; } } - if(dsc->decor & LV_TEXT_DECOR_STRIKETHROUGH) { - lv_point_t p1; - lv_point_t p2; - p1.x = pos_x_start; - p1.y = pos.y + (dsc->font->line_height / 2) + line_dsc.width / 2; - p2.x = pos.x; - p2.y = p1.y; - line_dsc.color = color; - lv_draw_line(draw_ctx, &line_dsc, &p1, &p2); - } - - if(dsc->decor & LV_TEXT_DECOR_UNDERLINE) { - lv_point_t p1; - lv_point_t p2; - p1.x = pos_x_start; - p1.y = pos.y + dsc->font->line_height - dsc->font->base_line - font->underline_position; - p2.x = pos.x; - p2.y = p1.y; - line_dsc.color = color; - lv_draw_line(draw_ctx, &line_dsc, &p1, &p2); - } - #if LV_USE_BIDI - lv_mem_buf_release(bidi_txt); + lv_free(bidi_txt); bidi_txt = NULL; #endif /*Go to next line*/ line_start = line_end; - line_end += _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, NULL, dsc->flag); + line_end += _lv_text_get_next_line(&dsc->text[line_start], font, dsc->letter_space, w, NULL, dsc->flag); pos.x = coords->x1; /*Align to middle*/ if(align == LV_TEXT_ALIGN_CENTER) { line_width = - lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag); + lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space); pos.x += (lv_area_get_width(coords) - line_width) / 2; - } /*Align to the right*/ else if(align == LV_TEXT_ALIGN_RIGHT) { line_width = - lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag); + lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space); pos.x += lv_area_get_width(coords) - line_width; } /*Go the next line position*/ pos.y += line_height; - if(pos.y > draw_ctx->clip_area->y2) return; + if(pos.y > draw_unit->clip_area->y2) break; } + if(draw_letter_dsc._draw_buf) lv_draw_buf_destroy(draw_letter_dsc._draw_buf); + LV_ASSERT_MEM_INTEGRITY(); } -void lv_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p, - uint32_t letter) -{ - draw_ctx->draw_letter(draw_ctx, dsc, pos_p, letter); -} - - /********************** * STATIC FUNCTIONS **********************/ -/** - * Convert a hexadecimal characters to a number (0..15) - * @param hex Pointer to a hexadecimal character (0..9, A..F) - * @return the numerical value of `hex` or 0 on error - */ -static uint8_t hex_char_to_num(char hex) +static void draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc, const lv_point_t * pos, + const lv_font_t * font, uint32_t letter, lv_draw_glyph_cb_t cb) { - uint8_t result = 0; + lv_font_glyph_dsc_t g; - if(hex >= '0' && hex <= '9') { - result = hex - '0'; + if(_lv_text_is_marker(letter)) /*Markers are valid letters but should not be rendered.*/ + return; + + LV_PROFILER_BEGIN; + bool g_ret = lv_font_get_glyph_dsc(font, &g, letter, '\0'); + if(g_ret == false) { + /*Add warning if the dsc is not found*/ + LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%" LV_PRIX32, letter); } - else { - if(hex >= 'a') hex -= 'a' - 'A'; /*Convert to upper case*/ - switch(hex) { - case 'A': - result = 10; - break; - case 'B': - result = 11; - break; - case 'C': - result = 12; - break; - case 'D': - result = 13; - break; - case 'E': - result = 14; - break; - case 'F': - result = 15; - break; - default: - result = 0; - break; + /*Don't draw anything if the character is empty. E.g. space*/ + if((g.box_h == 0) || (g.box_w == 0)) { + LV_PROFILER_END; + return; + } + + lv_area_t letter_coords; + letter_coords.x1 = pos->x + g.ofs_x; + letter_coords.x2 = letter_coords.x1 + g.box_w - 1; + letter_coords.y1 = pos->y + (font->line_height - font->base_line) - g.box_h - g.ofs_y; + letter_coords.y2 = letter_coords.y1 + g.box_h - 1; + + /*If the letter is completely out of mask don't draw it*/ + if(_lv_area_is_out(&letter_coords, draw_unit->clip_area, 0) && + _lv_area_is_out(dsc->bg_coords, draw_unit->clip_area, 0)) { + LV_PROFILER_END; + return; + } + + if(g.resolved_font) { + lv_draw_buf_t * draw_buf = NULL; + if(g.bpp < LV_IMGFONT_BPP) { + /*Only check draw buf for bitmap glyph*/ + draw_buf = lv_draw_buf_reshape(dsc->_draw_buf, 0, g.box_w, g.box_h, LV_STRIDE_AUTO); + if(draw_buf == NULL) { + if(dsc->_draw_buf) lv_draw_buf_destroy(dsc->_draw_buf); + + uint32_t h = g.box_h; + if(h * g.box_w < 64) h *= 2; /*Alloc a slightly larger buffer*/ + draw_buf = lv_draw_buf_create(g.box_w, h, LV_COLOR_FORMAT_A8, LV_STRIDE_AUTO); + LV_ASSERT_MALLOC(draw_buf); + draw_buf->header.h = g.box_h; + dsc->_draw_buf = draw_buf; + } + } + + dsc->glyph_data = (void *)lv_font_get_glyph_bitmap(&g, letter, draw_buf); + if(dsc->glyph_data == NULL) { + dsc->format = LV_DRAW_LETTER_BITMAP_FORMAT_INVALID; + } + else if(g.bpp == LV_IMGFONT_BPP) { + dsc->format = LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE; + } + else if(g.bpp == LV_VECFONT_BPP) { + dsc->format = LV_DRAW_LETTER_VECTOR_FORMAT; + } + else { + dsc->format = LV_DRAW_LETTER_BITMAP_FORMAT_A8; } } + else { + dsc->format = LV_DRAW_LETTER_BITMAP_FORMAT_INVALID; + } - return result; + dsc->letter_coords = &letter_coords; + dsc->g = &g; + cb(draw_unit, dsc, NULL, NULL); + + if(g.resolved_font && font->release_glyph) { + font->release_glyph(font, &g); + } + LV_PROFILER_END; } - diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.h index b28436af8..05df99192 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_label.h @@ -13,8 +13,9 @@ extern "C" { /********************* * INCLUDES *********************/ +#include "lv_draw.h" #include "../misc/lv_bidi.h" -#include "../misc/lv_txt.h" +#include "../misc/lv_text.h" #include "../misc/lv_color.h" #include "../misc/lv_style.h" @@ -27,25 +28,6 @@ extern "C" { * TYPEDEFS **********************/ -typedef struct { - const lv_font_t * font; - uint32_t sel_start; - uint32_t sel_end; - lv_color_t color; - lv_color_t sel_color; - lv_color_t sel_bg_color; - lv_coord_t line_space; - lv_coord_t letter_space; - lv_coord_t ofs_x; - lv_coord_t ofs_y; - lv_opa_t opa; - lv_base_dir_t bidi_dir; - lv_text_align_t align; - lv_text_flag_t flag; - lv_text_decor_t decor : 3; - lv_blend_mode_t blend_mode: 3; -} lv_draw_label_dsc_t; - /** Store some info to speed up drawing of very large texts * It takes a lot of time to get the first visible character because * all the previous characters needs to be checked to calculate the positions. @@ -63,27 +45,112 @@ typedef struct _lv_draw_label_hint_t { int32_t coord_y; } lv_draw_label_hint_t; -struct _lv_draw_ctx_t; +typedef struct { + lv_draw_dsc_base_t base; + + const char * text; + const lv_font_t * font; + uint32_t sel_start; + uint32_t sel_end; + lv_color_t color; + lv_color_t sel_color; + lv_color_t sel_bg_color; + int32_t line_space; + int32_t letter_space; + int32_t ofs_x; + int32_t ofs_y; + lv_opa_t opa; + lv_base_dir_t bidi_dir; + lv_text_align_t align; + lv_text_flag_t flag; + lv_text_decor_t decor : 3; + lv_blend_mode_t blend_mode : 3; + /** + * < 1: malloc buffer and copy `text` there. + * 0: `text` is const and it's pointer will be valid during rendering.*/ + uint8_t text_local : 1; + lv_draw_label_hint_t * hint; +} lv_draw_label_dsc_t; + +typedef enum { + LV_DRAW_LETTER_BITMAP_FORMAT_INVALID, + LV_DRAW_LETTER_BITMAP_FORMAT_A8, + LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE, + LV_DRAW_LETTER_VECTOR_FORMAT, +} lv_draw_glyph_bitmap_format_t; + +typedef struct { + void * glyph_data; /*Depends on `format` field, it could be image source or draw buf of bitmap or vector data.*/ + lv_draw_glyph_bitmap_format_t format; + const lv_area_t * letter_coords; + const lv_area_t * bg_coords; + const lv_font_glyph_dsc_t * g; + lv_color_t color; + lv_opa_t opa; + lv_draw_buf_t * _draw_buf; /*a shared draw buf for get_bitmap, do not use it directly, use glyph_data instead*/ +} lv_draw_glyph_dsc_t; + +/** + * Passed as a parameter to `lv_draw_label_iterate_characters` to + * draw the characters one by one + * @param draw_unit pointer to a draw unit + * @param dsc pointer to `lv_draw_glyph_dsc_t` to describe the character to draw + * if NULL don't draw character + * @param fill_dsc pointer to a fill descriptor to draw a background for the character or + * underline or strike through + * if NULL do not fill anything + * @param fill_area the area to fill + * if NULL do not fill anything + */ +typedef void(*lv_draw_glyph_cb_t)(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc, lv_draw_fill_dsc_t * fill_dsc, + const lv_area_t * fill_area); + /********************** * GLOBAL PROTOTYPES **********************/ -void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc); +/** + * Initialize a label draw descriptor + * @param dsc pointer to a draw descriptor + */ +LV_ATTRIBUTE_FAST_MEM void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc); /** - * Write a text - * @param coords coordinates of the label - * @param mask the label will be drawn only in this area - * @param dsc pointer to draw descriptor - * @param txt `\0` terminated text to write - * @param hint pointer to a `lv_draw_label_hint_t` variable. - * It is managed by the draw to speed up the drawing of very long texts (thousands of lines). + * Initialize a glyph draw descriptor. + * Used internally. + * @param dsc pointer to a draw descriptor */ -void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_label(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, - const lv_area_t * coords, const char * txt, lv_draw_label_hint_t * hint); +void lv_draw_glyph_dsc_init(lv_draw_glyph_dsc_t * dsc); -void lv_draw_letter(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p, - uint32_t letter); +/** + * Crate a draw task to render a text + * @param layer pointer to a layer + * @param dsc pointer to draw descriptor + * @param coords coordinates of the character + */ +LV_ATTRIBUTE_FAST_MEM void lv_draw_label(lv_layer_t * layer, const lv_draw_label_dsc_t * dsc, + const lv_area_t * coords); + +/** + * Crate a draw task to render a single character + * @param layer pointer to a layer + * @param dsc pointer to draw descriptor + * @param point position of the label + * @param unicode_letter the letter to draw + */ +LV_ATTRIBUTE_FAST_MEM void lv_draw_character(lv_layer_t * layer, lv_draw_label_dsc_t * dsc, + const lv_point_t * point, uint32_t unicode_letter); + +/** + * Should be used during rendering the characters to get the position and other + * parameters of the characters + * @param draw_unit pointer to a draw unit + * @param dsc pointer to draw descriptor + * @param coords coordinates of the label + * @param cb a callback to call to draw each glyphs one by one + */ +void lv_draw_label_iterate_characters(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, + const lv_area_t * coords, lv_draw_glyph_cb_t cb); /*********************** * GLOBAL VARIABLES diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_layer.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_layer.c deleted file mode 100644 index da35682d1..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_layer.c +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @file lv_draw_layer.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_draw.h" -#include "lv_draw_arc.h" -#include "../core/lv_refr.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_draw_layer_ctx_t * lv_draw_layer_create(lv_draw_ctx_t * draw_ctx, const lv_area_t * layer_area, - lv_draw_layer_flags_t flags) -{ - if(draw_ctx->layer_init == NULL) return NULL; - - lv_draw_layer_ctx_t * layer_ctx = lv_mem_alloc(draw_ctx->layer_instance_size); - LV_ASSERT_MALLOC(layer_ctx); - if(layer_ctx == NULL) { - LV_LOG_WARN("Couldn't allocate a new layer context"); - return NULL; - } - - lv_memset_00(layer_ctx, draw_ctx->layer_instance_size); - - lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing(); - layer_ctx->original.buf = draw_ctx->buf; - layer_ctx->original.buf_area = draw_ctx->buf_area; - layer_ctx->original.clip_area = draw_ctx->clip_area; - layer_ctx->original.screen_transp = disp_refr->driver->screen_transp; - layer_ctx->area_full = *layer_area; - - lv_draw_layer_ctx_t * init_layer_ctx = draw_ctx->layer_init(draw_ctx, layer_ctx, flags); - if(NULL == init_layer_ctx) { - lv_mem_free(layer_ctx); - } - return init_layer_ctx; -} - -void lv_draw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, - lv_draw_layer_flags_t flags) -{ - if(draw_ctx->layer_adjust) draw_ctx->layer_adjust(draw_ctx, layer_ctx, flags); -} - -void lv_draw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, - lv_draw_img_dsc_t * draw_dsc) -{ - if(draw_ctx->layer_blend) draw_ctx->layer_blend(draw_ctx, layer_ctx, draw_dsc); -} - -void lv_draw_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx) -{ - - lv_draw_wait_for_finish(draw_ctx); - draw_ctx->buf = layer_ctx->original.buf; - draw_ctx->buf_area = layer_ctx->original.buf_area; - draw_ctx->clip_area = layer_ctx->original.clip_area; - lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing(); - disp_refr->driver->screen_transp = layer_ctx->original.screen_transp; - - if(draw_ctx->layer_destroy) draw_ctx->layer_destroy(draw_ctx, layer_ctx); - lv_mem_free(layer_ctx); -} - -/********************** - * STATIC FUNCTIONS - **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_layer.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_layer.h deleted file mode 100644 index cd64149c4..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_layer.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @file lv_draw_layer.h - * - */ - -#ifndef LV_DRAW_LAYER_H -#define LV_DRAW_LAYER_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ -struct _lv_draw_ctx_t; -struct _lv_draw_layer_ctx_t; - -typedef enum { - LV_DRAW_LAYER_FLAG_NONE, - LV_DRAW_LAYER_FLAG_HAS_ALPHA, - LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE, -} lv_draw_layer_flags_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a new layer context. It is used to start and independent rendering session - * with the current draw_ctx - * @param draw_ctx pointer to the current draw context - * @param layer_area the coordinates of the layer - * @param flags OR-ed flags from @lv_draw_layer_flags_t - * @return pointer to the layer context, or NULL on error - */ -struct _lv_draw_layer_ctx_t * lv_draw_layer_create(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * layer_area, - lv_draw_layer_flags_t flags); - -/** - * Adjust the layer_ctx and/or draw_ctx based on the `layer_ctx->area_act`. - * It's called only if flags has `LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE` - * @param draw_ctx pointer to the current draw context - * @param layer_ctx pointer to a layer context - * @param flags OR-ed flags from @lv_draw_layer_flags_t - */ -void lv_draw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, - lv_draw_layer_flags_t flags); - -/** - * Blend a rendered layer to `layer_ctx->area_act` - * @param draw_ctx pointer to the current draw context - * @param layer_ctx pointer to a layer context - * @param draw_dsc pointer to an image draw descriptor - */ -void lv_draw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, - lv_draw_img_dsc_t * draw_dsc); - -/** - * Destroy a layer context. - * @param draw_ctx pointer to the current draw context - * @param layer_ctx pointer to a layer context - */ -void lv_draw_layer_destroy(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx); - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_LAYER_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_line.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_line.c index d0c432763..759f9808d 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_line.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_line.c @@ -9,6 +9,7 @@ #include #include "../core/lv_refr.h" #include "../misc/lv_math.h" +#include "../stdlib/lv_string.h" /********************* * DEFINES @@ -34,21 +35,31 @@ * GLOBAL FUNCTIONS **********************/ -void LV_ATTRIBUTE_FAST_MEM lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc) +LV_ATTRIBUTE_FAST_MEM void lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc) { - lv_memset_00(dsc, sizeof(lv_draw_line_dsc_t)); + lv_memzero(dsc, sizeof(lv_draw_line_dsc_t)); dsc->width = 1; dsc->opa = LV_OPA_COVER; dsc->color = lv_color_black(); } -void LV_ATTRIBUTE_FAST_MEM lv_draw_line(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, - const lv_point_t * point1, const lv_point_t * point2) +LV_ATTRIBUTE_FAST_MEM void lv_draw_line(lv_layer_t * layer, const lv_draw_line_dsc_t * dsc) { - if(dsc->width == 0) return; - if(dsc->opa <= LV_OPA_MIN) return; + LV_PROFILER_BEGIN; + lv_area_t a; + a.x1 = (int32_t)LV_MIN(dsc->p1.x, dsc->p2.x) - dsc->width; + a.x2 = (int32_t)LV_MAX(dsc->p1.x, dsc->p2.x) + dsc->width; + a.y1 = (int32_t)LV_MIN(dsc->p1.y, dsc->p2.y) - dsc->width; + a.y2 = (int32_t)LV_MAX(dsc->p1.y, dsc->p2.y) + dsc->width; - draw_ctx->draw_line(draw_ctx, dsc, point1, point2); + lv_draw_task_t * t = lv_draw_add_task(layer, &a); + + t->draw_dsc = lv_malloc(sizeof(*dsc)); + lv_memcpy(t->draw_dsc, dsc, sizeof(*dsc)); + t->type = LV_DRAW_TASK_TYPE_LINE; + + lv_draw_finalize_task_creation(layer, t); + LV_PROFILER_END; } /********************** diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_line.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_line.h index b476ce4ca..f7a95ea14 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_line.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_line.h @@ -26,10 +26,14 @@ extern "C" { * TYPEDEFS **********************/ typedef struct { + lv_draw_dsc_base_t base; + + lv_point_precise_t p1; + lv_point_precise_t p2; lv_color_t color; - lv_coord_t width; - lv_coord_t dash_width; - lv_coord_t dash_gap; + int32_t width; + int32_t dash_width; + int32_t dash_gap; lv_opa_t opa; lv_blend_mode_t blend_mode : 2; uint8_t round_start : 1; @@ -37,24 +41,22 @@ typedef struct { uint8_t raw_end : 1; /*Do not bother with perpendicular line ending if it's not visible for any reason*/ } lv_draw_line_dsc_t; -struct _lv_draw_ctx_t; - /********************** * GLOBAL PROTOTYPES **********************/ -void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc); +/** + * Initialize a line draw descriptor + * @param dsc pointer to a draw descriptor + */ +void lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc); /** - * Draw a line - * @param point1 first point of the line - * @param point2 second point of the line - * @param clip the line will be drawn only in this area - * @param dsc pointer to an initialized `lv_draw_line_dsc_t` variable + * Create a line draw task + * @param layer pointer to a layer + * @param dsc pointer to an initialized `lv_draw_line_dsc_t` variable */ -void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_line(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, - const lv_point_t * point1, const lv_point_t * point2); - +void lv_draw_line(lv_layer_t * layer, const lv_draw_line_dsc_t * dsc); /********************** * MACROS diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.c index 872ca9a98..d470aeaff 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.c @@ -1,23 +1,20 @@ /** - * @file lv_mask.c + * @file lv_draw_mask.c * */ /********************* * INCLUDES *********************/ -#include "lv_draw.h" -#if LV_DRAW_COMPLEX +#include +#include "lv_draw_mask.h" +#include "../core/lv_refr.h" #include "../misc/lv_math.h" -#include "../misc/lv_log.h" -#include "../misc/lv_assert.h" -#include "../misc/lv_gc.h" +#include "../stdlib/lv_string.h" /********************* * DEFINES *********************/ -#define CIRCLE_CACHE_LIFE_MAX 1000 -#define CIRCLE_CACHE_AGING(life, r) life = LV_MIN(life + (r < 16 ? 1 : (r >> 4)), 1000) /********************** * TYPEDEFS @@ -26,39 +23,6 @@ /********************** * STATIC PROTOTYPES **********************/ -static lv_draw_mask_res_t /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - lv_draw_mask_line_param_t * param); -static lv_draw_mask_res_t /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - lv_draw_mask_radius_param_t * param); -static lv_draw_mask_res_t /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - lv_draw_mask_angle_param_t * param); -static lv_draw_mask_res_t /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_mask_fade(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - lv_draw_mask_fade_param_t * param); -static lv_draw_mask_res_t /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_mask_map(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - lv_draw_mask_map_param_t * param); -static lv_draw_mask_res_t /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_mask_polygon(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - lv_draw_mask_polygon_param_t * param); - -static lv_draw_mask_res_t /* LV_ATTRIBUTE_FAST_MEM */ line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - lv_draw_mask_line_param_t * p); -static lv_draw_mask_res_t /* LV_ATTRIBUTE_FAST_MEM */ line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - lv_draw_mask_line_param_t * p); - -static void circ_init(lv_point_t * c, lv_coord_t * tmp, lv_coord_t radius); -static bool circ_cont(lv_point_t * c); -static void circ_next(lv_point_t * c, lv_coord_t * tmp); -static void circ_calc_aa4(_lv_draw_mask_radius_circle_dsc_t * c, lv_coord_t radius); -static lv_opa_t * get_next_line(_lv_draw_mask_radius_circle_dsc_t * c, lv_coord_t y, lv_coord_t * len, - lv_coord_t * x_start); -static inline lv_opa_t /* LV_ATTRIBUTE_FAST_MEM */ mask_mix(lv_opa_t mask_act, lv_opa_t mask_new); /********************** * STATIC VARIABLES @@ -72,1460 +36,40 @@ static inline lv_opa_t /* LV_ATTRIBUTE_FAST_MEM */ mask_mix(lv_opa_t mask_act, l * GLOBAL FUNCTIONS **********************/ -/** - * Add a draw mask. Everything drawn after it (until removing the mask) will be affected by the mask. - * @param param an initialized mask parameter. Only the pointer is saved. - * @param custom_id a custom pointer to identify the mask. Used in `lv_draw_mask_remove_custom`. - * @return the an integer, the ID of the mask. Can be used in `lv_draw_mask_remove_id`. - */ -int16_t lv_draw_mask_add(void * param, void * custom_id) +LV_ATTRIBUTE_FAST_MEM void lv_draw_mask_rect_dsc_init(lv_draw_mask_rect_dsc_t * dsc) { - /*Look for a free entry*/ - uint8_t i; - for(i = 0; i < _LV_MASK_MAX_NUM; i++) { - if(LV_GC_ROOT(_lv_draw_mask_list[i]).param == NULL) break; - } - - if(i >= _LV_MASK_MAX_NUM) { - LV_LOG_WARN("lv_mask_add: no place to add the mask"); - return LV_MASK_ID_INV; - } - - LV_GC_ROOT(_lv_draw_mask_list[i]).param = param; - LV_GC_ROOT(_lv_draw_mask_list[i]).custom_id = custom_id; - - return i; + lv_memzero(dsc, sizeof(lv_draw_mask_rect_dsc_t)); } -/** - * Apply the added buffers on a line. Used internally by the library's drawing routines. - * @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`. - * @param abs_x absolute X coordinate where the line to calculate start - * @param abs_y absolute Y coordinate where the line to calculate start - * @param len length of the line to calculate (in pixel count) - * @return One of these values: - * - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero - * - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged - * - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line - */ -lv_draw_mask_res_t LV_ATTRIBUTE_FAST_MEM lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len) +LV_ATTRIBUTE_FAST_MEM void lv_draw_mask_rect(lv_layer_t * layer, const lv_draw_mask_rect_dsc_t * dsc) { - bool changed = false; - _lv_draw_mask_common_dsc_t * dsc; - - _lv_draw_mask_saved_t * m = LV_GC_ROOT(_lv_draw_mask_list); - - while(m->param) { - dsc = m->param; - lv_draw_mask_res_t res = LV_DRAW_MASK_RES_FULL_COVER; - res = dsc->cb(mask_buf, abs_x, abs_y, len, (void *)m->param); - if(res == LV_DRAW_MASK_RES_TRANSP) return LV_DRAW_MASK_RES_TRANSP; - else if(res == LV_DRAW_MASK_RES_CHANGED) changed = true; - - m++; - } - - return changed ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; -} - -/** - * Apply the specified buffers on a line. Used internally by the library's drawing routines. - * @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`. - * @param abs_x absolute X coordinate where the line to calculate start - * @param abs_y absolute Y coordinate where the line to calculate start - * @param len length of the line to calculate (in pixel count) - * @param ids ID array of added buffers - * @param ids_count number of ID array - * @return One of these values: - * - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero - * - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged - * - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line - */ -lv_draw_mask_res_t LV_ATTRIBUTE_FAST_MEM lv_draw_mask_apply_ids(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - const int16_t * ids, int16_t ids_count) -{ - bool changed = false; - _lv_draw_mask_common_dsc_t * dsc; - - for(int i = 0; i < ids_count; i++) { - int16_t id = ids[i]; - if(id == LV_MASK_ID_INV) continue; - dsc = LV_GC_ROOT(_lv_draw_mask_list[id]).param; - if(!dsc) continue; - lv_draw_mask_res_t res = LV_DRAW_MASK_RES_FULL_COVER; - res = dsc->cb(mask_buf, abs_x, abs_y, len, dsc); - if(res == LV_DRAW_MASK_RES_TRANSP) return LV_DRAW_MASK_RES_TRANSP; - else if(res == LV_DRAW_MASK_RES_CHANGED) changed = true; - } - - return changed ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; -} - -/** - * Remove a mask with a given ID - * @param id the ID of the mask. Returned by `lv_draw_mask_add` - * @return the parameter of the removed mask. - * If more masks have `custom_id` ID then the last mask's parameter will be returned - */ -void * lv_draw_mask_remove_id(int16_t id) -{ - _lv_draw_mask_common_dsc_t * p = NULL; - - if(id != LV_MASK_ID_INV) { - p = LV_GC_ROOT(_lv_draw_mask_list[id]).param; - LV_GC_ROOT(_lv_draw_mask_list[id]).param = NULL; - LV_GC_ROOT(_lv_draw_mask_list[id]).custom_id = NULL; - } - - return p; -} - -/** - * Remove all mask with a given custom ID - * @param custom_id a pointer used in `lv_draw_mask_add` - * @return return the parameter of the removed mask. - * If more masks have `custom_id` ID then the last mask's parameter will be returned - */ -void * lv_draw_mask_remove_custom(void * custom_id) -{ - _lv_draw_mask_common_dsc_t * p = NULL; - uint8_t i; - for(i = 0; i < _LV_MASK_MAX_NUM; i++) { - if(LV_GC_ROOT(_lv_draw_mask_list[i]).custom_id == custom_id) { - p = LV_GC_ROOT(_lv_draw_mask_list[i]).param; - lv_draw_mask_remove_id(i); - } - } - return p; -} - -/** - * Free the data from the parameter. - * It's called inside `lv_draw_mask_remove_id` and `lv_draw_mask_remove_custom` - * Needs to be called only in special cases when the mask is not added by `lv_draw_mask_add` - * and not removed by `lv_draw_mask_remove_id` or `lv_draw_mask_remove_custom` - * @param p pointer to a mask parameter - */ -void lv_draw_mask_free_param(void * p) -{ - _lv_draw_mask_common_dsc_t * pdsc = p; - if(pdsc->type == LV_DRAW_MASK_TYPE_RADIUS) { - lv_draw_mask_radius_param_t * radius_p = (lv_draw_mask_radius_param_t *) p; - if(radius_p->circle) { - if(radius_p->circle->life < 0) { - lv_mem_free(radius_p->circle->cir_opa); - lv_mem_free(radius_p->circle); - } - else { - radius_p->circle->used_cnt--; - } - } - } - else if(pdsc->type == LV_DRAW_MASK_TYPE_POLYGON) { - lv_draw_mask_polygon_param_t * poly_p = (lv_draw_mask_polygon_param_t *) p; - lv_mem_free(poly_p->cfg.points); - } -} - -void _lv_draw_mask_cleanup(void) -{ - uint8_t i; - for(i = 0; i < LV_CIRCLE_CACHE_SIZE; i++) { - if(LV_GC_ROOT(_lv_circle_cache[i]).buf) { - lv_mem_free(LV_GC_ROOT(_lv_circle_cache[i]).buf); - } - lv_memset_00(&LV_GC_ROOT(_lv_circle_cache[i]), sizeof(LV_GC_ROOT(_lv_circle_cache[i]))); - } -} - -/** - * Count the currently added masks - * @return number of active masks - */ -uint8_t LV_ATTRIBUTE_FAST_MEM lv_draw_mask_get_cnt(void) -{ - uint8_t cnt = 0; - uint8_t i; - for(i = 0; i < _LV_MASK_MAX_NUM; i++) { - if(LV_GC_ROOT(_lv_draw_mask_list[i]).param) cnt++; - } - return cnt; -} - -bool lv_draw_mask_is_any(const lv_area_t * a) -{ - if(a == NULL) return LV_GC_ROOT(_lv_draw_mask_list[0]).param ? true : false; - - uint8_t i; - for(i = 0; i < _LV_MASK_MAX_NUM; i++) { - _lv_draw_mask_common_dsc_t * comm_param = LV_GC_ROOT(_lv_draw_mask_list[i]).param; - if(comm_param == NULL) continue; - if(comm_param->type == LV_DRAW_MASK_TYPE_RADIUS) { - lv_draw_mask_radius_param_t * radius_param = LV_GC_ROOT(_lv_draw_mask_list[i]).param; - if(radius_param->cfg.outer) { - if(!_lv_area_is_out(a, &radius_param->cfg.rect, radius_param->cfg.radius)) return true; - } - else { - if(!_lv_area_is_in(a, &radius_param->cfg.rect, radius_param->cfg.radius)) return true; - } - } - else { - return true; - } - } - - return false; - -} - -/** - *Initialize a line mask from two points. - * @param param pointer to a `lv_draw_mask_param_t` to initialize - * @param p1x X coordinate of the first point of the line - * @param p1y Y coordinate of the first point of the line - * @param p2x X coordinate of the second point of the line - * @param p2y y coordinate of the second point of the line - * @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep. - * With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept - * With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept - */ -void lv_draw_mask_line_points_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x, - lv_coord_t p2y, lv_draw_mask_line_side_t side) -{ - lv_memset_00(param, sizeof(lv_draw_mask_line_param_t)); - - if(p1y == p2y && side == LV_DRAW_MASK_LINE_SIDE_BOTTOM) { - p1y--; - p2y--; - } - - if(p1y > p2y) { - lv_coord_t t; - t = p2x; - p2x = p1x; - p1x = t; - - t = p2y; - p2y = p1y; - p1y = t; - } - - param->cfg.p1.x = p1x; - param->cfg.p1.y = p1y; - param->cfg.p2.x = p2x; - param->cfg.p2.y = p2y; - param->cfg.side = side; - - param->origo.x = p1x; - param->origo.y = p1y; - param->flat = (LV_ABS(p2x - p1x) > LV_ABS(p2y - p1y)) ? 1 : 0; - param->yx_steep = 0; - param->xy_steep = 0; - param->dsc.cb = (lv_draw_mask_xcb_t)lv_draw_mask_line; - param->dsc.type = LV_DRAW_MASK_TYPE_LINE; - - int32_t dx = p2x - p1x; - int32_t dy = p2y - p1y; - - if(param->flat) { - /*Normalize the steep. Delta x should be relative to delta x = 1024*/ - int32_t m; - - if(dx) { - m = (1L << 20) / dx; /*m is multiplier to normalize y (upscaled by 1024)*/ - param->yx_steep = (m * dy) >> 10; - } - - if(dy) { - m = (1L << 20) / dy; /*m is multiplier to normalize x (upscaled by 1024)*/ - param->xy_steep = (m * dx) >> 10; - } - param->steep = param->yx_steep; - } - else { - /*Normalize the steep. Delta y should be relative to delta x = 1024*/ - int32_t m; - - if(dy) { - m = (1L << 20) / dy; /*m is multiplier to normalize x (upscaled by 1024)*/ - param->xy_steep = (m * dx) >> 10; - } - - if(dx) { - m = (1L << 20) / dx; /*m is multiplier to normalize x (upscaled by 1024)*/ - param->yx_steep = (m * dy) >> 10; - } - param->steep = param->xy_steep; - } - - if(param->cfg.side == LV_DRAW_MASK_LINE_SIDE_LEFT) param->inv = 0; - else if(param->cfg.side == LV_DRAW_MASK_LINE_SIDE_RIGHT) param->inv = 1; - else if(param->cfg.side == LV_DRAW_MASK_LINE_SIDE_TOP) { - if(param->steep > 0) param->inv = 1; - else param->inv = 0; - } - else if(param->cfg.side == LV_DRAW_MASK_LINE_SIDE_BOTTOM) { - if(param->steep > 0) param->inv = 0; - else param->inv = 1; - } - - param->spx = param->steep >> 2; - if(param->steep < 0) param->spx = -param->spx; -} - -/** - *Initialize a line mask from a point and an angle. - * @param param pointer to a `lv_draw_mask_param_t` to initialize - * @param px X coordinate of a point of the line - * @param py X coordinate of a point of the line - * @param angle right 0 deg, bottom: 90 - * @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep. - * With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept - * With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept - */ -void lv_draw_mask_line_angle_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t py, int16_t angle, - lv_draw_mask_line_side_t side) -{ - /*Find an optimal degree. - *lv_mask_line_points_init will swap the points to keep the smaller y in p1 - *Theoretically a line with `angle` or `angle+180` is the same only the points are swapped - *Find the degree which keeps the origo in place*/ - if(angle > 180) angle -= 180; /*> 180 will swap the origo*/ - - int32_t p2x; - int32_t p2y; - - p2x = (lv_trigo_sin(angle + 90) >> 5) + p1x; - p2y = (lv_trigo_sin(angle) >> 5) + py; - - lv_draw_mask_line_points_init(param, p1x, py, p2x, p2y, side); -} - -/** - * Initialize an angle mask. - * @param param pointer to a `lv_draw_mask_param_t` to initialize - * @param vertex_x X coordinate of the angle vertex (absolute coordinates) - * @param vertex_y Y coordinate of the angle vertex (absolute coordinates) - * @param start_angle start angle in degrees. 0 deg on the right, 90 deg, on the bottom - * @param end_angle end angle - */ -void lv_draw_mask_angle_init(lv_draw_mask_angle_param_t * param, lv_coord_t vertex_x, lv_coord_t vertex_y, - lv_coord_t start_angle, lv_coord_t end_angle) -{ - lv_draw_mask_line_side_t start_side; - lv_draw_mask_line_side_t end_side; - - /*Constrain the input angles*/ - if(start_angle < 0) - start_angle = 0; - else if(start_angle > 359) - start_angle = 359; - - if(end_angle < 0) - end_angle = 0; - else if(end_angle > 359) - end_angle = 359; - - if(end_angle < start_angle) { - param->delta_deg = 360 - start_angle + end_angle; - } - else { - param->delta_deg = LV_ABS(end_angle - start_angle); - } - - param->cfg.start_angle = start_angle; - param->cfg.end_angle = end_angle; - param->cfg.vertex_p.x = vertex_x; - param->cfg.vertex_p.y = vertex_y; - param->dsc.cb = (lv_draw_mask_xcb_t)lv_draw_mask_angle; - param->dsc.type = LV_DRAW_MASK_TYPE_ANGLE; - - LV_ASSERT_MSG(start_angle >= 0 && start_angle <= 360, "Unexpected start angle"); - - if(start_angle >= 0 && start_angle < 180) { - start_side = LV_DRAW_MASK_LINE_SIDE_LEFT; - } - else - start_side = LV_DRAW_MASK_LINE_SIDE_RIGHT; /*silence compiler*/ - - LV_ASSERT_MSG(end_angle >= 0 && start_angle <= 360, "Unexpected end angle"); - - if(end_angle >= 0 && end_angle < 180) { - end_side = LV_DRAW_MASK_LINE_SIDE_RIGHT; - } - else if(end_angle >= 180 && end_angle < 360) { - end_side = LV_DRAW_MASK_LINE_SIDE_LEFT; - } - else - end_side = LV_DRAW_MASK_LINE_SIDE_RIGHT; /*silence compiler*/ - - lv_draw_mask_line_angle_init(¶m->start_line, vertex_x, vertex_y, start_angle, start_side); - lv_draw_mask_line_angle_init(¶m->end_line, vertex_x, vertex_y, end_angle, end_side); -} - -/** - * Initialize a fade mask. - * @param param pointer to an `lv_draw_mask_radius_param_t` to initialize - * @param rect coordinates of the rectangle to affect (absolute coordinates) - * @param radius radius of the rectangle - * @param inv true: keep the pixels inside the rectangle; keep the pixels outside of the rectangle - */ -void lv_draw_mask_radius_init(lv_draw_mask_radius_param_t * param, const lv_area_t * rect, lv_coord_t radius, bool inv) -{ - lv_coord_t w = lv_area_get_width(rect); - lv_coord_t h = lv_area_get_height(rect); - int32_t short_side = LV_MIN(w, h); - if(radius > short_side >> 1) radius = short_side >> 1; - if(radius < 0) radius = 0; - - lv_area_copy(¶m->cfg.rect, rect); - param->cfg.radius = radius; - param->cfg.outer = inv ? 1 : 0; - param->dsc.cb = (lv_draw_mask_xcb_t)lv_draw_mask_radius; - param->dsc.type = LV_DRAW_MASK_TYPE_RADIUS; - - if(radius == 0) { - param->circle = NULL; + if(!lv_color_format_has_alpha(layer->color_format)) { + LV_LOG_WARN("Only layers with alpha channel can be masked"); return; } + LV_PROFILER_BEGIN; - uint32_t i; + lv_draw_task_t * t = lv_draw_add_task(layer, &layer->buf_area); - /*Try to reuse a circle cache entry*/ - for(i = 0; i < LV_CIRCLE_CACHE_SIZE; i++) { - if(LV_GC_ROOT(_lv_circle_cache[i]).radius == radius) { - LV_GC_ROOT(_lv_circle_cache[i]).used_cnt++; - CIRCLE_CACHE_AGING(LV_GC_ROOT(_lv_circle_cache[i]).life, radius); - param->circle = &LV_GC_ROOT(_lv_circle_cache[i]); - return; - } + t->draw_dsc = lv_malloc(sizeof(*dsc)); + lv_memcpy(t->draw_dsc, dsc, sizeof(*dsc)); + t->type = LV_DRAW_TASK_TYPE_MASK_RECTANGLE; + + lv_draw_dsc_base_t * base_dsc = t->draw_dsc; + base_dsc->layer = layer; + + if(base_dsc->obj && lv_obj_has_flag(base_dsc->obj, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS)) { + /*Disable sending LV_EVENT_DRAW_TASK_ADDED first to avoid triggering recursive + *event calls due draw task adds in the event*/ + lv_obj_remove_flag(base_dsc->obj, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS); + lv_obj_send_event(dsc->base.obj, LV_EVENT_DRAW_TASK_ADDED, t); + lv_obj_add_flag(base_dsc->obj, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS); } - /*If not found find a free entry with lowest life*/ - _lv_draw_mask_radius_circle_dsc_t * entry = NULL; - for(i = 0; i < LV_CIRCLE_CACHE_SIZE; i++) { - if(LV_GC_ROOT(_lv_circle_cache[i]).used_cnt == 0) { - if(!entry) entry = &LV_GC_ROOT(_lv_circle_cache[i]); - else if(LV_GC_ROOT(_lv_circle_cache[i]).life < entry->life) entry = &LV_GC_ROOT(_lv_circle_cache[i]); - } - } - - if(!entry) { - entry = lv_mem_alloc(sizeof(_lv_draw_mask_radius_circle_dsc_t)); - LV_ASSERT_MALLOC(entry); - lv_memset_00(entry, sizeof(_lv_draw_mask_radius_circle_dsc_t)); - entry->life = -1; - } - else { - entry->used_cnt++; - entry->life = 0; - CIRCLE_CACHE_AGING(entry->life, radius); - } - - param->circle = entry; - - circ_calc_aa4(param->circle, radius); -} - -/** - * Initialize a fade mask. - * @param param pointer to a `lv_draw_mask_param_t` to initialize - * @param coords coordinates of the area to affect (absolute coordinates) - * @param opa_top opacity on the top - * @param y_top at which coordinate start to change to opacity to `opa_bottom` - * @param opa_bottom opacity at the bottom - * @param y_bottom at which coordinate reach `opa_bottom`. - */ -void lv_draw_mask_fade_init(lv_draw_mask_fade_param_t * param, const lv_area_t * coords, lv_opa_t opa_top, - lv_coord_t y_top, - lv_opa_t opa_bottom, lv_coord_t y_bottom) -{ - lv_area_copy(¶m->cfg.coords, coords); - param->cfg.opa_top = opa_top; - param->cfg.opa_bottom = opa_bottom; - param->cfg.y_top = y_top; - param->cfg.y_bottom = y_bottom; - param->dsc.cb = (lv_draw_mask_xcb_t)lv_draw_mask_fade; - param->dsc.type = LV_DRAW_MASK_TYPE_FADE; -} - -/** - * Initialize a map mask. - * @param param pointer to a `lv_draw_mask_param_t` to initialize - * @param coords coordinates of the map (absolute coordinates) - * @param map array of bytes with the mask values - */ -void lv_draw_mask_map_init(lv_draw_mask_map_param_t * param, const lv_area_t * coords, const lv_opa_t * map) -{ - lv_area_copy(¶m->cfg.coords, coords); - param->cfg.map = map; - param->dsc.cb = (lv_draw_mask_xcb_t)lv_draw_mask_map; - param->dsc.type = LV_DRAW_MASK_TYPE_MAP; -} - -void lv_draw_mask_polygon_init(lv_draw_mask_polygon_param_t * param, const lv_point_t * points, uint16_t point_cnt) -{ - /*Join adjacent points if they are on the same coordinate*/ - lv_point_t * p = lv_mem_alloc(point_cnt * sizeof(lv_point_t)); - if(p == NULL) return; - uint16_t i; - uint16_t pcnt = 0; - p[0] = points[0]; - for(i = 0; i < point_cnt - 1; i++) { - if(points[i].x != points[i + 1].x || points[i].y != points[i + 1].y) { - p[pcnt] = points[i]; - pcnt++; - } - } - /*The first and the last points are also adjacent*/ - if(points[0].x != points[point_cnt - 1].x || points[0].y != points[point_cnt - 1].y) { - p[pcnt] = points[point_cnt - 1]; - pcnt++; - } - param->cfg.points = p; - param->cfg.point_cnt = pcnt; - param->dsc.cb = (lv_draw_mask_xcb_t)lv_draw_mask_polygon; - param->dsc.type = LV_DRAW_MASK_TYPE_POLYGON; + lv_draw_finalize_task_creation(layer, t); + LV_PROFILER_END; } /********************** * STATIC FUNCTIONS **********************/ - -static lv_draw_mask_res_t LV_ATTRIBUTE_FAST_MEM lv_draw_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - lv_draw_mask_line_param_t * p) -{ - /*Make to points relative to the vertex*/ - abs_y -= p->origo.y; - abs_x -= p->origo.x; - - /*Handle special cases*/ - if(p->steep == 0) { - /*Horizontal*/ - if(p->flat) { - /*Non sense: Can't be on the right/left of a horizontal line*/ - if(p->cfg.side == LV_DRAW_MASK_LINE_SIDE_LEFT || - p->cfg.side == LV_DRAW_MASK_LINE_SIDE_RIGHT) return LV_DRAW_MASK_RES_FULL_COVER; - else if(p->cfg.side == LV_DRAW_MASK_LINE_SIDE_TOP && abs_y + 1 < 0) return LV_DRAW_MASK_RES_FULL_COVER; - else if(p->cfg.side == LV_DRAW_MASK_LINE_SIDE_BOTTOM && abs_y > 0) return LV_DRAW_MASK_RES_FULL_COVER; - else { - return LV_DRAW_MASK_RES_TRANSP; - } - } - /*Vertical*/ - else { - /*Non sense: Can't be on the top/bottom of a vertical line*/ - if(p->cfg.side == LV_DRAW_MASK_LINE_SIDE_TOP || - p->cfg.side == LV_DRAW_MASK_LINE_SIDE_BOTTOM) return LV_DRAW_MASK_RES_FULL_COVER; - else if(p->cfg.side == LV_DRAW_MASK_LINE_SIDE_RIGHT && abs_x > 0) return LV_DRAW_MASK_RES_FULL_COVER; - else if(p->cfg.side == LV_DRAW_MASK_LINE_SIDE_LEFT) { - if(abs_x + len < 0) return LV_DRAW_MASK_RES_FULL_COVER; - else { - int32_t k = - abs_x; - if(k < 0) return LV_DRAW_MASK_RES_TRANSP; - if(k >= 0 && k < len) lv_memset_00(&mask_buf[k], len - k); - return LV_DRAW_MASK_RES_CHANGED; - } - } - else { - if(abs_x + len < 0) return LV_DRAW_MASK_RES_TRANSP; - else { - int32_t k = - abs_x; - if(k < 0) k = 0; - if(k >= len) return LV_DRAW_MASK_RES_TRANSP; - else if(k >= 0 && k < len) lv_memset_00(&mask_buf[0], k); - return LV_DRAW_MASK_RES_CHANGED; - } - } - } - } - - lv_draw_mask_res_t res; - if(p->flat) { - res = line_mask_flat(mask_buf, abs_x, abs_y, len, p); - } - else { - res = line_mask_steep(mask_buf, abs_x, abs_y, len, p); - } - - return res; -} - -static lv_draw_mask_res_t LV_ATTRIBUTE_FAST_MEM line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, - lv_coord_t len, - lv_draw_mask_line_param_t * p) -{ - - int32_t y_at_x; - y_at_x = (int32_t)((int32_t)p->yx_steep * abs_x) >> 10; - - if(p->yx_steep > 0) { - if(y_at_x > abs_y) { - if(p->inv) { - return LV_DRAW_MASK_RES_FULL_COVER; - } - else { - return LV_DRAW_MASK_RES_TRANSP; - } - } - } - else { - if(y_at_x < abs_y) { - if(p->inv) { - return LV_DRAW_MASK_RES_FULL_COVER; - } - else { - return LV_DRAW_MASK_RES_TRANSP; - } - } - } - - /*At the end of the mask if the limit line is smaller than the mask's y. - *Then the mask is in the "good" area*/ - y_at_x = (int32_t)((int32_t)p->yx_steep * (abs_x + len)) >> 10; - if(p->yx_steep > 0) { - if(y_at_x < abs_y) { - if(p->inv) { - return LV_DRAW_MASK_RES_TRANSP; - } - else { - return LV_DRAW_MASK_RES_FULL_COVER; - } - } - } - else { - if(y_at_x > abs_y) { - if(p->inv) { - return LV_DRAW_MASK_RES_TRANSP; - } - else { - return LV_DRAW_MASK_RES_FULL_COVER; - } - } - } - - int32_t xe; - if(p->yx_steep > 0) xe = ((abs_y * 256) * p->xy_steep) >> 10; - else xe = (((abs_y + 1) * 256) * p->xy_steep) >> 10; - - int32_t xei = xe >> 8; - int32_t xef = xe & 0xFF; - - int32_t px_h; - if(xef == 0) px_h = 255; - else px_h = 255 - (((255 - xef) * p->spx) >> 8); - int32_t k = xei - abs_x; - lv_opa_t m; - - if(xef) { - if(k >= 0 && k < len) { - m = 255 - (((255 - xef) * (255 - px_h)) >> 9); - if(p->inv) m = 255 - m; - mask_buf[k] = mask_mix(mask_buf[k], m); - } - k++; - } - - while(px_h > p->spx) { - if(k >= 0 && k < len) { - m = px_h - (p->spx >> 1); - if(p->inv) m = 255 - m; - mask_buf[k] = mask_mix(mask_buf[k], m); - } - px_h -= p->spx; - k++; - if(k >= len) break; - } - - if(k < len && k >= 0) { - int32_t x_inters = (px_h * p->xy_steep) >> 10; - m = (x_inters * px_h) >> 9; - if(p->yx_steep < 0) m = 255 - m; - if(p->inv) m = 255 - m; - mask_buf[k] = mask_mix(mask_buf[k], m); - } - - if(p->inv) { - k = xei - abs_x; - if(k > len) { - return LV_DRAW_MASK_RES_TRANSP; - } - if(k >= 0) { - lv_memset_00(&mask_buf[0], k); - } - } - else { - k++; - if(k < 0) { - return LV_DRAW_MASK_RES_TRANSP; - } - if(k <= len) { - lv_memset_00(&mask_buf[k], len - k); - } - } - - return LV_DRAW_MASK_RES_CHANGED; -} - -static lv_draw_mask_res_t LV_ATTRIBUTE_FAST_MEM line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, - lv_coord_t len, - lv_draw_mask_line_param_t * p) -{ - int32_t k; - int32_t x_at_y; - /*At the beginning of the mask if the limit line is greater than the mask's y. - *Then the mask is in the "wrong" area*/ - x_at_y = (int32_t)((int32_t)p->xy_steep * abs_y) >> 10; - if(p->xy_steep > 0) x_at_y++; - if(x_at_y < abs_x) { - if(p->inv) { - return LV_DRAW_MASK_RES_FULL_COVER; - } - else { - return LV_DRAW_MASK_RES_TRANSP; - } - } - - /*At the end of the mask if the limit line is smaller than the mask's y. - *Then the mask is in the "good" area*/ - x_at_y = (int32_t)((int32_t)p->xy_steep * (abs_y)) >> 10; - if(x_at_y > abs_x + len) { - if(p->inv) { - return LV_DRAW_MASK_RES_TRANSP; - } - else { - return LV_DRAW_MASK_RES_FULL_COVER; - } - } - - /*X start*/ - int32_t xs = ((abs_y * 256) * p->xy_steep) >> 10; - int32_t xsi = xs >> 8; - int32_t xsf = xs & 0xFF; - - /*X end*/ - int32_t xe = (((abs_y + 1) * 256) * p->xy_steep) >> 10; - int32_t xei = xe >> 8; - int32_t xef = xe & 0xFF; - - lv_opa_t m; - - k = xsi - abs_x; - if(xsi != xei && (p->xy_steep < 0 && xsf == 0)) { - xsf = 0xFF; - xsi = xei; - k--; - } - - if(xsi == xei) { - if(k >= 0 && k < len) { - m = (xsf + xef) >> 1; - if(p->inv) m = 255 - m; - mask_buf[k] = mask_mix(mask_buf[k], m); - } - k++; - - if(p->inv) { - k = xsi - abs_x; - if(k >= len) { - return LV_DRAW_MASK_RES_TRANSP; - } - if(k >= 0) lv_memset_00(&mask_buf[0], k); - - } - else { - if(k > len) k = len; - if(k == 0) return LV_DRAW_MASK_RES_TRANSP; - else if(k > 0) lv_memset_00(&mask_buf[k], len - k); - } - - } - else { - int32_t y_inters; - if(p->xy_steep < 0) { - y_inters = (xsf * (-p->yx_steep)) >> 10; - if(k >= 0 && k < len) { - m = (y_inters * xsf) >> 9; - if(p->inv) m = 255 - m; - mask_buf[k] = mask_mix(mask_buf[k], m); - } - k--; - - int32_t x_inters = ((255 - y_inters) * (-p->xy_steep)) >> 10; - - if(k >= 0 && k < len) { - m = 255 - (((255 - y_inters) * x_inters) >> 9); - if(p->inv) m = 255 - m; - mask_buf[k] = mask_mix(mask_buf[k], m); - } - - k += 2; - - if(p->inv) { - k = xsi - abs_x - 1; - - if(k > len) k = len; - else if(k > 0) lv_memset_00(&mask_buf[0], k); - - } - else { - if(k > len) return LV_DRAW_MASK_RES_FULL_COVER; - if(k >= 0) lv_memset_00(&mask_buf[k], len - k); - } - - } - else { - y_inters = ((255 - xsf) * p->yx_steep) >> 10; - if(k >= 0 && k < len) { - m = 255 - ((y_inters * (255 - xsf)) >> 9); - if(p->inv) m = 255 - m; - mask_buf[k] = mask_mix(mask_buf[k], m); - } - - k++; - - int32_t x_inters = ((255 - y_inters) * p->xy_steep) >> 10; - if(k >= 0 && k < len) { - m = ((255 - y_inters) * x_inters) >> 9; - if(p->inv) m = 255 - m; - mask_buf[k] = mask_mix(mask_buf[k], m); - } - k++; - - if(p->inv) { - k = xsi - abs_x; - if(k > len) return LV_DRAW_MASK_RES_TRANSP; - if(k >= 0) lv_memset_00(&mask_buf[0], k); - - } - else { - if(k > len) k = len; - if(k == 0) return LV_DRAW_MASK_RES_TRANSP; - else if(k > 0) lv_memset_00(&mask_buf[k], len - k); - } - } - } - - return LV_DRAW_MASK_RES_CHANGED; -} - -static lv_draw_mask_res_t LV_ATTRIBUTE_FAST_MEM lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - lv_draw_mask_angle_param_t * p) -{ - int32_t rel_y = abs_y - p->cfg.vertex_p.y; - int32_t rel_x = abs_x - p->cfg.vertex_p.x; - - if(p->cfg.start_angle < 180 && p->cfg.end_angle < 180 && - p->cfg.start_angle != 0 && p->cfg.end_angle != 0 && - p->cfg.start_angle > p->cfg.end_angle) { - - if(abs_y < p->cfg.vertex_p.y) { - return LV_DRAW_MASK_RES_FULL_COVER; - } - - /*Start angle mask can work only from the end of end angle mask*/ - int32_t end_angle_first = (rel_y * p->end_line.xy_steep) >> 10; - int32_t start_angle_last = ((rel_y + 1) * p->start_line.xy_steep) >> 10; - - /*Do not let the line end cross the vertex else it will affect the opposite part*/ - if(p->cfg.start_angle > 270 && p->cfg.start_angle <= 359 && start_angle_last < 0) start_angle_last = 0; - else if(p->cfg.start_angle > 0 && p->cfg.start_angle <= 90 && start_angle_last < 0) start_angle_last = 0; - else if(p->cfg.start_angle > 90 && p->cfg.start_angle < 270 && start_angle_last > 0) start_angle_last = 0; - - if(p->cfg.end_angle > 270 && p->cfg.end_angle <= 359 && start_angle_last < 0) start_angle_last = 0; - else if(p->cfg.end_angle > 0 && p->cfg.end_angle <= 90 && start_angle_last < 0) start_angle_last = 0; - else if(p->cfg.end_angle > 90 && p->cfg.end_angle < 270 && start_angle_last > 0) start_angle_last = 0; - - int32_t dist = (end_angle_first - start_angle_last) >> 1; - - lv_draw_mask_res_t res1 = LV_DRAW_MASK_RES_FULL_COVER; - lv_draw_mask_res_t res2 = LV_DRAW_MASK_RES_FULL_COVER; - - int32_t tmp = start_angle_last + dist - rel_x; - if(tmp > len) tmp = len; - if(tmp > 0) { - res1 = lv_draw_mask_line(&mask_buf[0], abs_x, abs_y, tmp, &p->start_line); - if(res1 == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(&mask_buf[0], tmp); - } - } - - if(tmp > len) tmp = len; - if(tmp < 0) tmp = 0; - res2 = lv_draw_mask_line(&mask_buf[tmp], abs_x + tmp, abs_y, len - tmp, &p->end_line); - if(res2 == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(&mask_buf[tmp], len - tmp); - } - if(res1 == res2) return res1; - else return LV_DRAW_MASK_RES_CHANGED; - } - else if(p->cfg.start_angle > 180 && p->cfg.end_angle > 180 && p->cfg.start_angle > p->cfg.end_angle) { - - if(abs_y > p->cfg.vertex_p.y) { - return LV_DRAW_MASK_RES_FULL_COVER; - } - - /*Start angle mask can work only from the end of end angle mask*/ - int32_t end_angle_first = (rel_y * p->end_line.xy_steep) >> 10; - int32_t start_angle_last = ((rel_y + 1) * p->start_line.xy_steep) >> 10; - - /*Do not let the line end cross the vertex else it will affect the opposite part*/ - if(p->cfg.start_angle > 270 && p->cfg.start_angle <= 359 && start_angle_last < 0) start_angle_last = 0; - else if(p->cfg.start_angle > 0 && p->cfg.start_angle <= 90 && start_angle_last < 0) start_angle_last = 0; - else if(p->cfg.start_angle > 90 && p->cfg.start_angle < 270 && start_angle_last > 0) start_angle_last = 0; - - if(p->cfg.end_angle > 270 && p->cfg.end_angle <= 359 && start_angle_last < 0) start_angle_last = 0; - else if(p->cfg.end_angle > 0 && p->cfg.end_angle <= 90 && start_angle_last < 0) start_angle_last = 0; - else if(p->cfg.end_angle > 90 && p->cfg.end_angle < 270 && start_angle_last > 0) start_angle_last = 0; - - int32_t dist = (end_angle_first - start_angle_last) >> 1; - - lv_draw_mask_res_t res1 = LV_DRAW_MASK_RES_FULL_COVER; - lv_draw_mask_res_t res2 = LV_DRAW_MASK_RES_FULL_COVER; - - int32_t tmp = start_angle_last + dist - rel_x; - if(tmp > len) tmp = len; - if(tmp > 0) { - res1 = lv_draw_mask_line(&mask_buf[0], abs_x, abs_y, tmp, (lv_draw_mask_line_param_t *)&p->end_line); - if(res1 == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(&mask_buf[0], tmp); - } - } - - if(tmp > len) tmp = len; - if(tmp < 0) tmp = 0; - res2 = lv_draw_mask_line(&mask_buf[tmp], abs_x + tmp, abs_y, len - tmp, (lv_draw_mask_line_param_t *)&p->start_line); - if(res2 == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(&mask_buf[tmp], len - tmp); - } - if(res1 == res2) return res1; - else return LV_DRAW_MASK_RES_CHANGED; - } - else { - - lv_draw_mask_res_t res1 = LV_DRAW_MASK_RES_FULL_COVER; - lv_draw_mask_res_t res2 = LV_DRAW_MASK_RES_FULL_COVER; - - if(p->cfg.start_angle == 180) { - if(abs_y < p->cfg.vertex_p.y) res1 = LV_DRAW_MASK_RES_FULL_COVER; - else res1 = LV_DRAW_MASK_RES_UNKNOWN; - } - else if(p->cfg.start_angle == 0) { - if(abs_y < p->cfg.vertex_p.y) res1 = LV_DRAW_MASK_RES_UNKNOWN; - else res1 = LV_DRAW_MASK_RES_FULL_COVER; - } - else if((p->cfg.start_angle < 180 && abs_y < p->cfg.vertex_p.y) || - (p->cfg.start_angle > 180 && abs_y >= p->cfg.vertex_p.y)) { - res1 = LV_DRAW_MASK_RES_UNKNOWN; - } - else { - res1 = lv_draw_mask_line(mask_buf, abs_x, abs_y, len, &p->start_line); - } - - if(p->cfg.end_angle == 180) { - if(abs_y < p->cfg.vertex_p.y) res2 = LV_DRAW_MASK_RES_UNKNOWN; - else res2 = LV_DRAW_MASK_RES_FULL_COVER; - } - else if(p->cfg.end_angle == 0) { - if(abs_y < p->cfg.vertex_p.y) res2 = LV_DRAW_MASK_RES_FULL_COVER; - else res2 = LV_DRAW_MASK_RES_UNKNOWN; - } - else if((p->cfg.end_angle < 180 && abs_y < p->cfg.vertex_p.y) || - (p->cfg.end_angle > 180 && abs_y >= p->cfg.vertex_p.y)) { - res2 = LV_DRAW_MASK_RES_UNKNOWN; - } - else { - res2 = lv_draw_mask_line(mask_buf, abs_x, abs_y, len, &p->end_line); - } - - if(res1 == LV_DRAW_MASK_RES_TRANSP || res2 == LV_DRAW_MASK_RES_TRANSP) return LV_DRAW_MASK_RES_TRANSP; - else if(res1 == LV_DRAW_MASK_RES_UNKNOWN && res2 == LV_DRAW_MASK_RES_UNKNOWN) return LV_DRAW_MASK_RES_TRANSP; - else if(res1 == LV_DRAW_MASK_RES_FULL_COVER && res2 == LV_DRAW_MASK_RES_FULL_COVER) return LV_DRAW_MASK_RES_FULL_COVER; - else return LV_DRAW_MASK_RES_CHANGED; - } -} - - - -static lv_draw_mask_res_t LV_ATTRIBUTE_FAST_MEM lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - lv_draw_mask_radius_param_t * p) -{ - bool outer = p->cfg.outer; - int32_t radius = p->cfg.radius; - lv_area_t rect; - lv_area_copy(&rect, &p->cfg.rect); - - if(outer == false) { - if((abs_y < rect.y1 || abs_y > rect.y2)) { - return LV_DRAW_MASK_RES_TRANSP; - } - } - else { - if(abs_y < rect.y1 || abs_y > rect.y2) { - return LV_DRAW_MASK_RES_FULL_COVER; - } - } - - if((abs_x >= rect.x1 + radius && abs_x + len <= rect.x2 - radius) || - (abs_y >= rect.y1 + radius && abs_y <= rect.y2 - radius)) { - if(outer == false) { - /*Remove the edges*/ - int32_t last = rect.x1 - abs_x; - if(last > len) return LV_DRAW_MASK_RES_TRANSP; - if(last >= 0) { - lv_memset_00(&mask_buf[0], last); - } - - int32_t first = rect.x2 - abs_x + 1; - if(first <= 0) return LV_DRAW_MASK_RES_TRANSP; - else if(first < len) { - lv_memset_00(&mask_buf[first], len - first); - } - if(last == 0 && first == len) return LV_DRAW_MASK_RES_FULL_COVER; - else return LV_DRAW_MASK_RES_CHANGED; - } - else { - int32_t first = rect.x1 - abs_x; - if(first < 0) first = 0; - if(first <= len) { - int32_t last = rect.x2 - abs_x - first + 1; - if(first + last > len) last = len - first; - if(last >= 0) { - lv_memset_00(&mask_buf[first], last); - } - } - } - return LV_DRAW_MASK_RES_CHANGED; - } - // printf("exec: x:%d.. %d, y:%d: r:%d, %s\n", abs_x, abs_x + len - 1, abs_y, p->cfg.radius, p->cfg.outer ? "inv" : "norm"); - - - // if( abs_x == 276 && abs_x + len - 1 == 479 && abs_y == 63 && p->cfg.radius == 5 && p->cfg.outer == 1) { - // char x = 0; - // } - //exec: x:276.. 479, y:63: r:5, inv) - - int32_t k = rect.x1 - abs_x; /*First relevant coordinate on the of the mask*/ - int32_t w = lv_area_get_width(&rect); - int32_t h = lv_area_get_height(&rect); - abs_x -= rect.x1; - abs_y -= rect.y1; - - lv_coord_t aa_len; - lv_coord_t x_start; - lv_coord_t cir_y; - if(abs_y < radius) { - cir_y = radius - abs_y - 1; - } - else { - cir_y = abs_y - (h - radius); - } - lv_opa_t * aa_opa = get_next_line(p->circle, cir_y, &aa_len, &x_start); - lv_coord_t cir_x_right = k + w - radius + x_start; - lv_coord_t cir_x_left = k + radius - x_start - 1; - lv_coord_t i; - - if(outer == false) { - for(i = 0; i < aa_len; i++) { - lv_opa_t opa = aa_opa[aa_len - i - 1]; - if(cir_x_right + i >= 0 && cir_x_right + i < len) { - mask_buf[cir_x_right + i] = mask_mix(opa, mask_buf[cir_x_right + i]); - } - if(cir_x_left - i >= 0 && cir_x_left - i < len) { - mask_buf[cir_x_left - i] = mask_mix(opa, mask_buf[cir_x_left - i]); - } - } - - /*Clean the right side*/ - cir_x_right = LV_CLAMP(0, cir_x_right + i, len); - lv_memset_00(&mask_buf[cir_x_right], len - cir_x_right); - - /*Clean the left side*/ - cir_x_left = LV_CLAMP(0, cir_x_left - aa_len + 1, len); - lv_memset_00(&mask_buf[0], cir_x_left); - } - else { - for(i = 0; i < aa_len; i++) { - lv_opa_t opa = 255 - (aa_opa[aa_len - 1 - i]); - if(cir_x_right + i >= 0 && cir_x_right + i < len) { - mask_buf[cir_x_right + i] = mask_mix(opa, mask_buf[cir_x_right + i]); - } - if(cir_x_left - i >= 0 && cir_x_left - i < len) { - mask_buf[cir_x_left - i] = mask_mix(opa, mask_buf[cir_x_left - i]); - } - } - - lv_coord_t clr_start = LV_CLAMP(0, cir_x_left + 1, len); - lv_coord_t clr_len = LV_CLAMP(0, cir_x_right - clr_start, len - clr_start); - lv_memset_00(&mask_buf[clr_start], clr_len); - } - - return LV_DRAW_MASK_RES_CHANGED; -} - -static lv_draw_mask_res_t LV_ATTRIBUTE_FAST_MEM lv_draw_mask_fade(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - lv_draw_mask_fade_param_t * p) -{ - if(abs_y < p->cfg.coords.y1) return LV_DRAW_MASK_RES_FULL_COVER; - if(abs_y > p->cfg.coords.y2) return LV_DRAW_MASK_RES_FULL_COVER; - if(abs_x + len < p->cfg.coords.x1) return LV_DRAW_MASK_RES_FULL_COVER; - if(abs_x > p->cfg.coords.x2) return LV_DRAW_MASK_RES_FULL_COVER; - - if(abs_x + len > p->cfg.coords.x2) len -= abs_x + len - p->cfg.coords.x2 - 1; - - if(abs_x < p->cfg.coords.x1) { - int32_t x_ofs = 0; - x_ofs = p->cfg.coords.x1 - abs_x; - len -= x_ofs; - mask_buf += x_ofs; - } - - int32_t i; - - if(abs_y <= p->cfg.y_top) { - for(i = 0; i < len; i++) { - mask_buf[i] = mask_mix(mask_buf[i], p->cfg.opa_top); - } - return LV_DRAW_MASK_RES_CHANGED; - } - else if(abs_y >= p->cfg.y_bottom) { - for(i = 0; i < len; i++) { - mask_buf[i] = mask_mix(mask_buf[i], p->cfg.opa_bottom); - } - return LV_DRAW_MASK_RES_CHANGED; - } - else { - /*Calculate the opa proportionally*/ - int16_t opa_diff = p->cfg.opa_bottom - p->cfg.opa_top; - int32_t y_diff = p->cfg.y_bottom - p->cfg.y_top + 1; - lv_opa_t opa_act = (int32_t)((int32_t)(abs_y - p->cfg.y_top) * opa_diff) / y_diff; - opa_act += p->cfg.opa_top; - - for(i = 0; i < len; i++) { - mask_buf[i] = mask_mix(mask_buf[i], opa_act); - } - return LV_DRAW_MASK_RES_CHANGED; - } -} - -static lv_draw_mask_res_t LV_ATTRIBUTE_FAST_MEM lv_draw_mask_map(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - lv_draw_mask_map_param_t * p) -{ - /*Handle out of the mask cases*/ - if(abs_y < p->cfg.coords.y1) return LV_DRAW_MASK_RES_FULL_COVER; - if(abs_y > p->cfg.coords.y2) return LV_DRAW_MASK_RES_FULL_COVER; - if(abs_x + len < p->cfg.coords.x1) return LV_DRAW_MASK_RES_FULL_COVER; - if(abs_x > p->cfg.coords.x2) return LV_DRAW_MASK_RES_FULL_COVER; - - /*Got to the current row in the map*/ - const lv_opa_t * map_tmp = p->cfg.map; - map_tmp += (abs_y - p->cfg.coords.y1) * lv_area_get_width(&p->cfg.coords); - - if(abs_x + len > p->cfg.coords.x2) len -= abs_x + len - p->cfg.coords.x2 - 1; - - if(abs_x < p->cfg.coords.x1) { - int32_t x_ofs = 0; - x_ofs = p->cfg.coords.x1 - abs_x; - len -= x_ofs; - mask_buf += x_ofs; - } - else { - map_tmp += (abs_x - p->cfg.coords.x1); - } - - int32_t i; - for(i = 0; i < len; i++) { - mask_buf[i] = mask_mix(mask_buf[i], map_tmp[i]); - } - - return LV_DRAW_MASK_RES_CHANGED; -} - -static lv_draw_mask_res_t LV_ATTRIBUTE_FAST_MEM lv_draw_mask_polygon(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - lv_draw_mask_polygon_param_t * param) -{ - uint16_t i; - struct { - lv_point_t p1; - lv_point_t p2; - } lines[2], tmp; - uint16_t line_cnt = 0; - lv_memset_00(&lines, sizeof(lines)); - int psign_prev = 0; - for(i = 0; i < param->cfg.point_cnt; i++) { - lv_point_t p1 = param->cfg.points[i]; - lv_point_t p2 = param->cfg.points[i + 1 < param->cfg.point_cnt ? i + 1 : 0]; - int pdiff = p1.y - p2.y, psign = pdiff / LV_ABS(pdiff); - if(pdiff > 0) { - if(abs_y > p1.y || abs_y < p2.y) continue; - lines[line_cnt].p1 = p2; - lines[line_cnt].p2 = p1; - } - else { - if(abs_y < p1.y || abs_y > p2.y) continue; - lines[line_cnt].p1 = p1; - lines[line_cnt].p2 = p2; - } - if(psign_prev && psign_prev == psign) continue; - psign_prev = psign; - line_cnt++; - if(line_cnt == 2) break; - } - if(line_cnt != 2) return LV_DRAW_MASK_RES_TRANSP; - if(lines[0].p1.x > lines[1].p1.x || lines[0].p2.x > lines[1].p2.x) { - tmp = lines[0]; - lines[0] = lines[1]; - lines[1] = tmp; - } - lv_draw_mask_line_param_t line_p; - lv_draw_mask_line_points_init(&line_p, lines[0].p1.x, lines[0].p1.y, lines[0].p2.x, lines[0].p2.y, - LV_DRAW_MASK_LINE_SIDE_RIGHT); - if(line_p.steep == 0 && line_p.flat) { - lv_coord_t x1 = LV_MIN(lines[0].p1.x, lines[0].p2.x); - lv_coord_t x2 = LV_MAX(lines[0].p1.x, lines[0].p2.x); - for(i = 0; i < len; i++) { - mask_buf[i] = mask_mix(mask_buf[i], (abs_x + i >= x1 && abs_x + i <= x2) * 0xFF); - } - lv_draw_mask_free_param(&line_p); - return LV_DRAW_MASK_RES_CHANGED; - } - lv_draw_mask_res_t res1 = lv_draw_mask_line(mask_buf, abs_x, abs_y, len, &line_p); - lv_draw_mask_free_param(&line_p); - if(res1 == LV_DRAW_MASK_RES_TRANSP) { - return LV_DRAW_MASK_RES_TRANSP; - } - lv_draw_mask_line_points_init(&line_p, lines[1].p1.x, lines[1].p1.y, lines[1].p2.x, lines[1].p2.y, - LV_DRAW_MASK_LINE_SIDE_LEFT); - if(line_p.steep == 0 && line_p.flat) { - lv_coord_t x1 = LV_MIN(lines[1].p1.x, lines[1].p2.x); - lv_coord_t x2 = LV_MAX(lines[1].p1.x, lines[1].p2.x); - for(i = 0; i < len; i++) { - mask_buf[i] = mask_mix(mask_buf[i], (abs_x + i >= x1 && abs_x + i <= x2) * 0xFF); - } - lv_draw_mask_free_param(&line_p); - return LV_DRAW_MASK_RES_CHANGED; - } - lv_draw_mask_res_t res2 = lv_draw_mask_line(mask_buf, abs_x, abs_y, len, &line_p); - lv_draw_mask_free_param(&line_p); - if(res2 == LV_DRAW_MASK_RES_TRANSP) { - return LV_DRAW_MASK_RES_TRANSP; - } - if(res1 == LV_DRAW_MASK_RES_CHANGED || res2 == LV_DRAW_MASK_RES_CHANGED) return LV_DRAW_MASK_RES_CHANGED; - return res1; -} -/** - * Initialize the circle drawing - * @param c pointer to a point. The coordinates will be calculated here - * @param tmp point to a variable. It will store temporary data - * @param radius radius of the circle - */ -static void circ_init(lv_point_t * c, lv_coord_t * tmp, lv_coord_t radius) -{ - c->x = radius; - c->y = 0; - *tmp = 1 - radius; -} - -/** - * Test the circle drawing is ready or not - * @param c same as in circ_init - * @return true if the circle is not ready yet - */ -static bool circ_cont(lv_point_t * c) -{ - return c->y <= c->x ? true : false; -} - -/** - * Get the next point from the circle - * @param c same as in circ_init. The next point stored here. - * @param tmp same as in circ_init. - */ -static void circ_next(lv_point_t * c, lv_coord_t * tmp) -{ - - if(*tmp <= 0) { - (*tmp) += 2 * c->y + 3; /*Change in decision criterion for y -> y+1*/ - } - else { - (*tmp) += 2 * (c->y - c->x) + 5; /*Change for y -> y+1, x -> x-1*/ - c->x--; - } - c->y++; -} - -static void circ_calc_aa4(_lv_draw_mask_radius_circle_dsc_t * c, lv_coord_t radius) -{ - if(radius == 0) return; - c->radius = radius; - - /*Allocate buffers*/ - if(c->buf) lv_mem_free(c->buf); - - c->buf = lv_mem_alloc(radius * 6 + 6); /*Use uint16_t for opa_start_on_y and x_start_on_y*/ - LV_ASSERT_MALLOC(c->buf); - c->cir_opa = c->buf; - c->opa_start_on_y = (uint16_t *)(c->buf + 2 * radius + 2); - c->x_start_on_y = (uint16_t *)(c->buf + 4 * radius + 4); - - /*Special case, handle manually*/ - if(radius == 1) { - c->cir_opa[0] = 180; - c->opa_start_on_y[0] = 0; - c->opa_start_on_y[1] = 1; - c->x_start_on_y[0] = 0; - return; - } - - lv_coord_t * cir_x = lv_mem_buf_get((radius + 1) * 2 * 2 * sizeof(lv_coord_t)); - lv_coord_t * cir_y = &cir_x[(radius + 1) * 2]; - - uint32_t y_8th_cnt = 0; - lv_point_t cp; - lv_coord_t tmp; - circ_init(&cp, &tmp, radius * 4); /*Upscale by 4*/ - int32_t i; - - uint32_t x_int[4]; - uint32_t x_fract[4]; - lv_coord_t cir_size = 0; - x_int[0] = cp.x >> 2; - x_fract[0] = 0; - - /*Calculate an 1/8 circle*/ - while(circ_cont(&cp)) { - /*Calculate 4 point of the circle */ - for(i = 0; i < 4; i++) { - circ_next(&cp, &tmp); - if(circ_cont(&cp) == false) break; - x_int[i] = cp.x >> 2; - x_fract[i] = cp.x & 0x3; - } - if(i != 4) break; - - /*All lines on the same x when downscaled*/ - if(x_int[0] == x_int[3]) { - cir_x[cir_size] = x_int[0]; - cir_y[cir_size] = y_8th_cnt; - c->cir_opa[cir_size] = x_fract[0] + x_fract[1] + x_fract[2] + x_fract[3]; - c->cir_opa[cir_size] *= 16; - cir_size++; - } - /*Second line on new x when downscaled*/ - else if(x_int[0] != x_int[1]) { - cir_x[cir_size] = x_int[0]; - cir_y[cir_size] = y_8th_cnt; - c->cir_opa[cir_size] = x_fract[0]; - c->cir_opa[cir_size] *= 16; - cir_size++; - - cir_x[cir_size] = x_int[0] - 1; - cir_y[cir_size] = y_8th_cnt; - c->cir_opa[cir_size] = 1 * 4 + x_fract[1] + x_fract[2] + x_fract[3];; - c->cir_opa[cir_size] *= 16; - cir_size++; - } - /*Third line on new x when downscaled*/ - else if(x_int[0] != x_int[2]) { - cir_x[cir_size] = x_int[0]; - cir_y[cir_size] = y_8th_cnt; - c->cir_opa[cir_size] = x_fract[0] + x_fract[1]; - c->cir_opa[cir_size] *= 16; - cir_size++; - - cir_x[cir_size] = x_int[0] - 1; - cir_y[cir_size] = y_8th_cnt; - c->cir_opa[cir_size] = 2 * 4 + x_fract[2] + x_fract[3];; - c->cir_opa[cir_size] *= 16; - cir_size++; - } - /*Forth line on new x when downscaled*/ - else { - cir_x[cir_size] = x_int[0]; - cir_y[cir_size] = y_8th_cnt; - c->cir_opa[cir_size] = x_fract[0] + x_fract[1] + x_fract[2]; - c->cir_opa[cir_size] *= 16; - cir_size++; - - cir_x[cir_size] = x_int[0] - 1; - cir_y[cir_size] = y_8th_cnt; - c->cir_opa[cir_size] = 3 * 4 + x_fract[3];; - c->cir_opa[cir_size] *= 16; - cir_size++; - } - - y_8th_cnt++; - } - - /*The point on the 1/8 circle is special, calculate it manually*/ - int32_t mid = radius * 723; - int32_t mid_int = mid >> 10; - if(cir_x[cir_size - 1] != mid_int || cir_y[cir_size - 1] != mid_int) { - int32_t tmp_val = mid - (mid_int << 10); - if(tmp_val <= 512) { - tmp_val = tmp_val * tmp_val * 2; - tmp_val = tmp_val >> (10 + 6); - } - else { - tmp_val = 1024 - tmp_val; - tmp_val = tmp_val * tmp_val * 2; - tmp_val = tmp_val >> (10 + 6); - tmp_val = 15 - tmp_val; - } - - cir_x[cir_size] = mid_int; - cir_y[cir_size] = mid_int; - c->cir_opa[cir_size] = tmp_val; - c->cir_opa[cir_size] *= 16; - cir_size++; - } - - /*Build the second octet by mirroring the first*/ - for(i = cir_size - 2; i >= 0; i--, cir_size++) { - cir_x[cir_size] = cir_y[i]; - cir_y[cir_size] = cir_x[i]; - c->cir_opa[cir_size] = c->cir_opa[i]; - } - - lv_coord_t y = 0; - i = 0; - c->opa_start_on_y[0] = 0; - while(i < cir_size) { - c->opa_start_on_y[y] = i; - c->x_start_on_y[y] = cir_x[i]; - for(; cir_y[i] == y && i < (int32_t)cir_size; i++) { - c->x_start_on_y[y] = LV_MIN(c->x_start_on_y[y], cir_x[i]); - } - y++; - } - - lv_mem_buf_release(cir_x); -} - -static lv_opa_t * get_next_line(_lv_draw_mask_radius_circle_dsc_t * c, lv_coord_t y, lv_coord_t * len, - lv_coord_t * x_start) -{ - *len = c->opa_start_on_y[y + 1] - c->opa_start_on_y[y]; - *x_start = c->x_start_on_y[y]; - return &c->cir_opa[c->opa_start_on_y[y]]; -} - - -static inline lv_opa_t LV_ATTRIBUTE_FAST_MEM mask_mix(lv_opa_t mask_act, lv_opa_t mask_new) -{ - if(mask_new >= LV_OPA_MAX) return mask_act; - if(mask_new <= LV_OPA_MIN) return 0; - - return LV_UDIV255(mask_act * mask_new);// >> 8); -} - - -#endif /*LV_DRAW_COMPLEX*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.h index 908be6b88..9c8af1b9b 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_mask.h @@ -1,388 +1,53 @@ /** - * @file lv_draw_mask.h + * @file lv_draw_mask_rect.h * */ -#ifndef LV_DRAW_MASK_H -#define LV_DRAW_MASK_H +#ifndef LV_DRAW_MASK_RECT_H +#define LV_DRAW_MASK_RECT_H #ifdef __cplusplus extern "C" { #endif - /********************* * INCLUDES *********************/ -#include -#include "../misc/lv_area.h" +#include "lv_draw.h" #include "../misc/lv_color.h" -#include "../misc/lv_math.h" +#include "../misc/lv_area.h" +#include "../misc/lv_style.h" /********************* * DEFINES *********************/ -#define LV_MASK_ID_INV (-1) -#if LV_DRAW_COMPLEX -# define _LV_MASK_MAX_NUM 16 -#else -# define _LV_MASK_MAX_NUM 1 -#endif /********************** * TYPEDEFS **********************/ - -enum { - LV_DRAW_MASK_RES_TRANSP, - LV_DRAW_MASK_RES_FULL_COVER, - LV_DRAW_MASK_RES_CHANGED, - LV_DRAW_MASK_RES_UNKNOWN -}; - -typedef uint8_t lv_draw_mask_res_t; - typedef struct { - void * param; - void * custom_id; -} _lv_draw_mask_saved_t; - -typedef _lv_draw_mask_saved_t _lv_draw_mask_saved_arr_t[_LV_MASK_MAX_NUM]; - - - -#if LV_DRAW_COMPLEX == 0 -static inline uint8_t lv_draw_mask_get_cnt(void) -{ - return 0; -} - -static inline bool lv_draw_mask_is_any(const lv_area_t * a) -{ - LV_UNUSED(a); - return false; -} - -#endif - -#if LV_DRAW_COMPLEX - -enum { - LV_DRAW_MASK_TYPE_LINE, - LV_DRAW_MASK_TYPE_ANGLE, - LV_DRAW_MASK_TYPE_RADIUS, - LV_DRAW_MASK_TYPE_FADE, - LV_DRAW_MASK_TYPE_MAP, - LV_DRAW_MASK_TYPE_POLYGON, -}; - -typedef uint8_t lv_draw_mask_type_t; - -enum { - LV_DRAW_MASK_LINE_SIDE_LEFT = 0, - LV_DRAW_MASK_LINE_SIDE_RIGHT, - LV_DRAW_MASK_LINE_SIDE_TOP, - LV_DRAW_MASK_LINE_SIDE_BOTTOM, -}; - -/** - * A common callback type for every mask type. - * Used internally by the library. - */ -typedef lv_draw_mask_res_t (*lv_draw_mask_xcb_t)(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, - lv_coord_t len, - void * p); - -typedef uint8_t lv_draw_mask_line_side_t; - -typedef struct { - lv_draw_mask_xcb_t cb; - lv_draw_mask_type_t type; -} _lv_draw_mask_common_dsc_t; - -typedef struct { - /*The first element must be the common descriptor*/ - _lv_draw_mask_common_dsc_t dsc; - - struct { - /*First point*/ - lv_point_t p1; - - /*Second point*/ - lv_point_t p2; - - /*Which side to keep?*/ - lv_draw_mask_line_side_t side : 2; - } cfg; - - /*A point of the line*/ - lv_point_t origo; - - /*X / (1024*Y) steepness (X is 0..1023 range). What is the change of X in 1024 Y?*/ - int32_t xy_steep; - - /*Y / (1024*X) steepness (Y is 0..1023 range). What is the change of Y in 1024 X?*/ - int32_t yx_steep; - - /*Helper which stores yx_steep for flat lines and xy_steep for steep (non flat) lines*/ - int32_t steep; - - /*Steepness in 1 px in 0..255 range. Used only by flat lines.*/ - int32_t spx; - - /*1: It's a flat line? (Near to horizontal)*/ - uint8_t flat : 1; - - /*Invert the mask. The default is: Keep the left part. - *It is used to select left/right/top/bottom*/ - uint8_t inv: 1; -} lv_draw_mask_line_param_t; - -typedef struct { - /*The first element must be the common descriptor*/ - _lv_draw_mask_common_dsc_t dsc; - - struct { - lv_point_t vertex_p; - lv_coord_t start_angle; - lv_coord_t end_angle; - } cfg; - - lv_draw_mask_line_param_t start_line; - lv_draw_mask_line_param_t end_line; - uint16_t delta_deg; -} lv_draw_mask_angle_param_t; - -typedef struct { - uint8_t * buf; - lv_opa_t * cir_opa; /*Opacity of values on the circumference of an 1/4 circle*/ - uint16_t * x_start_on_y; /*The x coordinate of the circle for each y value*/ - uint16_t * opa_start_on_y; /*The index of `cir_opa` for each y value*/ - int32_t life; /*How many times the entry way used*/ - uint32_t used_cnt; /*Like a semaphore to count the referencing masks*/ - lv_coord_t radius; /*The radius of the entry*/ -} _lv_draw_mask_radius_circle_dsc_t; - -typedef _lv_draw_mask_radius_circle_dsc_t _lv_draw_mask_radius_circle_dsc_arr_t[LV_CIRCLE_CACHE_SIZE]; - -typedef struct { - /*The first element must be the common descriptor*/ - _lv_draw_mask_common_dsc_t dsc; - - struct { - lv_area_t rect; - lv_coord_t radius; - /*Invert the mask. 0: Keep the pixels inside.*/ - uint8_t outer: 1; - } cfg; - - _lv_draw_mask_radius_circle_dsc_t * circle; -} lv_draw_mask_radius_param_t; - - -typedef struct { - /*The first element must be the common descriptor*/ - _lv_draw_mask_common_dsc_t dsc; - - struct { - lv_area_t coords; - lv_coord_t y_top; - lv_coord_t y_bottom; - lv_opa_t opa_top; - lv_opa_t opa_bottom; - } cfg; - -} lv_draw_mask_fade_param_t; - - -typedef struct _lv_draw_mask_map_param_t { - /*The first element must be the common descriptor*/ - _lv_draw_mask_common_dsc_t dsc; - - struct { - lv_area_t coords; - const lv_opa_t * map; - } cfg; -} lv_draw_mask_map_param_t; - -typedef struct { - /*The first element must be the common descriptor*/ - _lv_draw_mask_common_dsc_t dsc; - - struct { - lv_point_t * points; - uint16_t point_cnt; - } cfg; -} lv_draw_mask_polygon_param_t; + lv_draw_dsc_base_t base; + lv_area_t area; + int32_t radius; +} lv_draw_mask_rect_dsc_t; /********************** * GLOBAL PROTOTYPES **********************/ /** - * Add a draw mask. Everything drawn after it (until removing the mask) will be affected by the mask. - * @param param an initialized mask parameter. Only the pointer is saved. - * @param custom_id a custom pointer to identify the mask. Used in `lv_draw_mask_remove_custom`. - * @return the an integer, the ID of the mask. Can be used in `lv_draw_mask_remove_id`. + * Initialize a rectangle mask draw descriptor. + * @param dsc pointer to a draw descriptor */ -int16_t lv_draw_mask_add(void * param, void * custom_id); - -//! @cond Doxygen_Suppress +LV_ATTRIBUTE_FAST_MEM void lv_draw_mask_rect_dsc_init(lv_draw_mask_rect_dsc_t * dsc); /** - * Apply the added buffers on a line. Used internally by the library's drawing routines. - * @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`. - * @param abs_x absolute X coordinate where the line to calculate start - * @param abs_y absolute Y coordinate where the line to calculate start - * @param len length of the line to calculate (in pixel count) - * @return One of these values: - * - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero - * - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged - * - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line + * Create a draw task to mask a rectangle from the buffer + * @param layer pointer to a layer + * @param dsc pointer to a draw descriptor */ -lv_draw_mask_res_t /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len); - -/** - * Apply the specified buffers on a line. Used internally by the library's drawing routines. - * @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`. - * @param abs_x absolute X coordinate where the line to calculate start - * @param abs_y absolute Y coordinate where the line to calculate start - * @param len length of the line to calculate (in pixel count) - * @param ids ID array of added buffers - * @param ids_count number of ID array - * @return One of these values: - * - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero - * - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged - * - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line - */ -lv_draw_mask_res_t /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_mask_apply_ids(lv_opa_t * mask_buf, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t len, - const int16_t * ids, int16_t ids_count); - -//! @endcond - -/** - * Remove a mask with a given ID - * @param id the ID of the mask. Returned by `lv_draw_mask_add` - * @return the parameter of the removed mask. - * If more masks have `custom_id` ID then the last mask's parameter will be returned - */ -void * lv_draw_mask_remove_id(int16_t id); - -/** - * Remove all mask with a given custom ID - * @param custom_id a pointer used in `lv_draw_mask_add` - * @return return the parameter of the removed mask. - * If more masks have `custom_id` ID then the last mask's parameter will be returned - */ -void * lv_draw_mask_remove_custom(void * custom_id); - -/** - * Free the data from the parameter. - * It's called inside `lv_draw_mask_remove_id` and `lv_draw_mask_remove_custom` - * Needs to be called only in special cases when the mask is not added by `lv_draw_mask_add` - * and not removed by `lv_draw_mask_remove_id` or `lv_draw_mask_remove_custom` - * @param p pointer to a mask parameter - */ -void lv_draw_mask_free_param(void * p); - -/** - * Called by LVGL the rendering of a screen is ready to clean up - * the temporal (cache) data of the masks - */ -void _lv_draw_mask_cleanup(void); - -//! @cond Doxygen_Suppress - -/** - * Count the currently added masks - * @return number of active masks - */ -uint8_t /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_mask_get_cnt(void); - - -/** - * Check if there is any added draw mask - * @param a an area to test for affecting masks. - * @return true: there is t least 1 draw mask; false: there are no draw masks - */ -bool lv_draw_mask_is_any(const lv_area_t * a); - -//! @endcond - -/** - *Initialize a line mask from two points. - * @param param pointer to a `lv_draw_mask_param_t` to initialize - * @param p1x X coordinate of the first point of the line - * @param p1y Y coordinate of the first point of the line - * @param p2x X coordinate of the second point of the line - * @param p2y y coordinate of the second point of the line - * @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep. - * With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept - * With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept - */ -void lv_draw_mask_line_points_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x, - lv_coord_t p2y, lv_draw_mask_line_side_t side); - -/** - *Initialize a line mask from a point and an angle. - * @param param pointer to a `lv_draw_mask_param_t` to initialize - * @param px X coordinate of a point of the line - * @param py X coordinate of a point of the line - * @param angle right 0 deg, bottom: 90 - * @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep. - * With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept - * With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept - */ -void lv_draw_mask_line_angle_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t py, int16_t angle, - lv_draw_mask_line_side_t side); - -/** - * Initialize an angle mask. - * @param param pointer to a `lv_draw_mask_param_t` to initialize - * @param vertex_x X coordinate of the angle vertex (absolute coordinates) - * @param vertex_y Y coordinate of the angle vertex (absolute coordinates) - * @param start_angle start angle in degrees. 0 deg on the right, 90 deg, on the bottom - * @param end_angle end angle - */ -void lv_draw_mask_angle_init(lv_draw_mask_angle_param_t * param, lv_coord_t vertex_x, lv_coord_t vertex_y, - lv_coord_t start_angle, lv_coord_t end_angle); - -/** - * Initialize a fade mask. - * @param param pointer to an `lv_draw_mask_radius_param_t` to initialize - * @param rect coordinates of the rectangle to affect (absolute coordinates) - * @param radius radius of the rectangle - * @param inv true: keep the pixels inside the rectangle; keep the pixels outside of the rectangle - */ -void lv_draw_mask_radius_init(lv_draw_mask_radius_param_t * param, const lv_area_t * rect, lv_coord_t radius, bool inv); - -/** - * Initialize a fade mask. - * @param param pointer to a `lv_draw_mask_param_t` to initialize - * @param coords coordinates of the area to affect (absolute coordinates) - * @param opa_top opacity on the top - * @param y_top at which coordinate start to change to opacity to `opa_bottom` - * @param opa_bottom opacity at the bottom - * @param y_bottom at which coordinate reach `opa_bottom`. - */ -void lv_draw_mask_fade_init(lv_draw_mask_fade_param_t * param, const lv_area_t * coords, lv_opa_t opa_top, - lv_coord_t y_top, - lv_opa_t opa_bottom, lv_coord_t y_bottom); - -/** - * Initialize a map mask. - * @param param pointer to a `lv_draw_mask_param_t` to initialize - * @param coords coordinates of the map (absolute coordinates) - * @param map array of bytes with the mask values - */ -void lv_draw_mask_map_init(lv_draw_mask_map_param_t * param, const lv_area_t * coords, const lv_opa_t * map); - -void lv_draw_mask_polygon_init(lv_draw_mask_polygon_param_t * param, const lv_point_t * points, uint16_t point_cnt); - -#endif /*LV_DRAW_COMPLEX*/ +void lv_draw_mask_rect(lv_layer_t * layer, const lv_draw_mask_rect_dsc_t * dsc); /********************** * MACROS @@ -392,4 +57,4 @@ void lv_draw_mask_polygon_init(lv_draw_mask_polygon_param_t * param, const lv_po } /*extern "C"*/ #endif -#endif /*LV_DRAW_MASK_H*/ +#endif /*LV_DRAW_MASK_RECT_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.c index ae81f3880..a20c81c22 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.c @@ -6,9 +6,11 @@ /********************* * INCLUDES *********************/ -#include "lv_draw.h" +#include "../core/lv_obj.h" #include "lv_draw_rect.h" #include "../misc/lv_assert.h" +#include "../core/lv_obj_event.h" +#include "../stdlib/lv_string.h" /********************* * DEFINES @@ -34,9 +36,9 @@ * GLOBAL FUNCTIONS **********************/ -void LV_ATTRIBUTE_FAST_MEM lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc) +LV_ATTRIBUTE_FAST_MEM void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc) { - lv_memset_00(dsc, sizeof(lv_draw_rect_dsc_t)); + lv_memzero(dsc, sizeof(lv_draw_rect_dsc_t)); dsc->bg_color = lv_color_white(); dsc->bg_grad.stops[0].color = lv_color_white(); dsc->bg_grad.stops[1].color = lv_color_black(); @@ -44,28 +46,235 @@ void LV_ATTRIBUTE_FAST_MEM lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc) dsc->bg_grad.stops_count = 2; dsc->border_color = lv_color_black(); dsc->shadow_color = lv_color_black(); - dsc->bg_img_symbol_font = LV_FONT_DEFAULT; + dsc->bg_image_symbol_font = LV_FONT_DEFAULT; dsc->bg_opa = LV_OPA_COVER; - dsc->bg_img_opa = LV_OPA_COVER; + dsc->bg_image_opa = LV_OPA_COVER; dsc->outline_opa = LV_OPA_COVER; dsc->border_opa = LV_OPA_COVER; dsc->shadow_opa = LV_OPA_COVER; dsc->border_side = LV_BORDER_SIDE_FULL; } -/** - * Draw a rectangle - * @param coords the coordinates of the rectangle - * @param mask the rectangle will be drawn only in this mask - * @param dsc pointer to an initialized `lv_draw_rect_dsc_t` variable - */ -void lv_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) +void lv_draw_fill_dsc_init(lv_draw_fill_dsc_t * dsc) { - if(lv_area_get_height(coords) < 1 || lv_area_get_width(coords) < 1) return; + lv_memzero(dsc, sizeof(*dsc)); + dsc->opa = LV_OPA_COVER; + dsc->base.dsc_size = sizeof(lv_draw_fill_dsc_t); +} - draw_ctx->draw_rect(draw_ctx, dsc, coords); +void lv_draw_border_dsc_init(lv_draw_border_dsc_t * dsc) +{ + lv_memzero(dsc, sizeof(*dsc)); + dsc->opa = LV_OPA_COVER; + dsc->side = LV_BORDER_SIDE_FULL; + dsc->base.dsc_size = sizeof(lv_draw_border_dsc_t); +} + +void lv_draw_box_shadow_dsc_init(lv_draw_box_shadow_dsc_t * dsc) +{ + lv_memzero(dsc, sizeof(*dsc)); + dsc->opa = LV_OPA_COVER; + dsc->base.dsc_size = sizeof(lv_draw_box_shadow_dsc_t); +} + +void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) +{ + + LV_PROFILER_BEGIN; + bool has_shadow; + bool has_fill; + bool has_border; + bool has_outline; + bool has_bg_img; + + if(dsc->shadow_width == 0 || + dsc->shadow_opa <= LV_OPA_MIN || + (dsc->shadow_width == 1 && dsc->shadow_spread <= 0 && + dsc->shadow_offset_x == 0 && dsc->shadow_offset_y == 0)) { + has_shadow = false; + } + else { + has_shadow = true; + } + + if(dsc->bg_opa <= LV_OPA_MIN) has_fill = false; + else has_fill = true; + + if(dsc->bg_image_opa <= LV_OPA_MIN || dsc->bg_image_src == NULL) has_bg_img = false; + else has_bg_img = true; + + if(dsc->border_opa <= LV_OPA_MIN || dsc->border_width == 0 || dsc->border_post == true) has_border = false; + else has_border = true; + + if(dsc->outline_opa <= LV_OPA_MIN || dsc->outline_width == 0) has_outline = false; + else has_outline = true; + + bool bg_cover = true; + if(dsc->bg_opa < LV_OPA_COVER) bg_cover = false; + else if(dsc->bg_grad.dir != LV_GRAD_DIR_NONE) { + uint32_t s; + for(s = 0; s < dsc->bg_grad.stops_count; s++) { + if(dsc->bg_grad.stops[s].opa != LV_OPA_COVER) { + bg_cover = false; + break; + } + } + } + + lv_draw_task_t * t; + + /*Shadow*/ + if(has_shadow) { + /*Check whether the shadow is visible*/ + t = lv_draw_add_task(layer, coords); + lv_draw_box_shadow_dsc_t * shadow_dsc = lv_malloc(sizeof(lv_draw_box_shadow_dsc_t)); + t->draw_dsc = shadow_dsc; + lv_area_increase(&t->_real_area, dsc->shadow_spread, dsc->shadow_spread); + lv_area_increase(&t->_real_area, dsc->shadow_width, dsc->shadow_width); + lv_area_move(&t->_real_area, dsc->shadow_offset_x, dsc->shadow_offset_y); + shadow_dsc->base = dsc->base; + shadow_dsc->base.dsc_size = sizeof(lv_draw_box_shadow_dsc_t); + shadow_dsc->radius = dsc->radius; + shadow_dsc->color = dsc->shadow_color; + shadow_dsc->width = dsc->shadow_width; + shadow_dsc->spread = dsc->shadow_spread; + shadow_dsc->opa = dsc->shadow_opa; + shadow_dsc->ofs_x = dsc->shadow_offset_x; + shadow_dsc->ofs_y = dsc->shadow_offset_y; + shadow_dsc->bg_cover = bg_cover; + t->type = LV_DRAW_TASK_TYPE_BOX_SHADOW; + lv_draw_finalize_task_creation(layer, t); + } + + /*Background*/ + if(has_fill) { + lv_area_t bg_coords = *coords; + /*If the border fully covers make the bg area 1px smaller to avoid artifacts on the corners*/ + if(dsc->border_width > 1 && dsc->border_opa >= LV_OPA_MAX && dsc->radius != 0) { + bg_coords.x1 += (dsc->border_side & LV_BORDER_SIDE_LEFT) ? 1 : 0; + bg_coords.y1 += (dsc->border_side & LV_BORDER_SIDE_TOP) ? 1 : 0; + bg_coords.x2 -= (dsc->border_side & LV_BORDER_SIDE_RIGHT) ? 1 : 0; + bg_coords.y2 -= (dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? 1 : 0; + } + + t = lv_draw_add_task(layer, &bg_coords); + lv_draw_fill_dsc_t * bg_dsc = lv_malloc(sizeof(lv_draw_fill_dsc_t)); + lv_draw_fill_dsc_init(bg_dsc); + t->draw_dsc = bg_dsc; + bg_dsc->base = dsc->base; + bg_dsc->base.dsc_size = sizeof(lv_draw_fill_dsc_t); + bg_dsc->radius = dsc->radius; + bg_dsc->color = dsc->bg_color; + bg_dsc->grad = dsc->bg_grad; + bg_dsc->opa = dsc->bg_opa; + t->type = LV_DRAW_TASK_TYPE_FILL; + + lv_draw_finalize_task_creation(layer, t); + } + + /*Background image*/ + if(has_bg_img) { + lv_image_src_t src_type = lv_image_src_get_type(dsc->bg_image_src); + lv_result_t res = LV_RESULT_OK; + lv_image_header_t header; + if(src_type == LV_IMAGE_SRC_VARIABLE || src_type == LV_IMAGE_SRC_FILE) { + res = lv_image_decoder_get_info(dsc->bg_image_src, &header); + } + else if(src_type == LV_IMAGE_SRC_UNKNOWN) { + res = LV_RESULT_INVALID; + } + else { + lv_memzero(&header, sizeof(header)); + } + + if(res == LV_RESULT_OK) { + if(src_type == LV_IMAGE_SRC_VARIABLE || src_type == LV_IMAGE_SRC_FILE) { + + if(dsc->bg_image_tiled) { + t = lv_draw_add_task(layer, coords); + } + else { + lv_area_t a = {0, 0, header.w - 1, header.h - 1}; + lv_area_align(coords, &a, LV_ALIGN_CENTER, 0, 0); + t = lv_draw_add_task(layer, &a); + } + + lv_draw_image_dsc_t * bg_image_dsc = lv_malloc(sizeof(lv_draw_image_dsc_t)); + lv_draw_image_dsc_init(bg_image_dsc); + t->draw_dsc = bg_image_dsc; + bg_image_dsc->base = dsc->base; + bg_image_dsc->base.dsc_size = sizeof(lv_draw_image_dsc_t); + bg_image_dsc->src = dsc->bg_image_src; + bg_image_dsc->opa = dsc->bg_image_opa; + bg_image_dsc->recolor = dsc->bg_image_recolor; + bg_image_dsc->recolor_opa = dsc->bg_image_recolor_opa; + bg_image_dsc->tile = dsc->bg_image_tiled; + bg_image_dsc->header = header; + t->type = LV_DRAW_TASK_TYPE_IMAGE; + lv_draw_finalize_task_creation(layer, t); + } + else { + lv_point_t s; + lv_text_get_size(&s, dsc->bg_image_src, dsc->bg_image_symbol_font, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + + lv_area_t a = {0, 0, s.x - 1, s.y - 1}; + lv_area_align(coords, &a, LV_ALIGN_CENTER, 0, 0); + t = lv_draw_add_task(layer, &a); + + lv_draw_label_dsc_t * bg_label_dsc = lv_malloc(sizeof(lv_draw_label_dsc_t)); + lv_draw_label_dsc_init(bg_label_dsc); + t->draw_dsc = bg_label_dsc; + bg_label_dsc->base = dsc->base; + bg_label_dsc->base.dsc_size = sizeof(lv_draw_label_dsc_t); + bg_label_dsc->color = dsc->bg_image_recolor; + bg_label_dsc->font = dsc->bg_image_symbol_font; + bg_label_dsc->text = dsc->bg_image_src; + t->type = LV_DRAW_TASK_TYPE_LABEL; + lv_draw_finalize_task_creation(layer, t); + } + } + } + + /*Border*/ + if(has_border) { + t = lv_draw_add_task(layer, coords); + lv_draw_border_dsc_t * border_dsc = lv_malloc(sizeof(lv_draw_border_dsc_t)); + t->draw_dsc = border_dsc; + border_dsc->base = dsc->base; + border_dsc->base.dsc_size = sizeof(lv_draw_border_dsc_t); + border_dsc->radius = dsc->radius; + border_dsc->color = dsc->border_color; + border_dsc->opa = dsc->border_opa; + border_dsc->width = dsc->border_width; + border_dsc->side = dsc->border_side; + t->type = LV_DRAW_TASK_TYPE_BORDER; + lv_draw_finalize_task_creation(layer, t); + } + + /*Outline*/ + if(has_outline) { + lv_area_t outline_coords = *coords; + lv_area_increase(&outline_coords, dsc->outline_width + dsc->outline_pad, dsc->outline_width + dsc->outline_pad); + t = lv_draw_add_task(layer, &outline_coords); + lv_draw_border_dsc_t * outline_dsc = lv_malloc(sizeof(lv_draw_border_dsc_t)); + t->draw_dsc = outline_dsc; + lv_area_increase(&t->_real_area, dsc->outline_width, dsc->outline_width); + lv_area_increase(&t->_real_area, dsc->outline_pad, dsc->outline_pad); + outline_dsc->base = dsc->base; + outline_dsc->base.dsc_size = sizeof(lv_draw_border_dsc_t); + outline_dsc->radius = dsc->radius == LV_RADIUS_CIRCLE ? LV_RADIUS_CIRCLE : dsc->radius + dsc->outline_width + + dsc->outline_pad; + outline_dsc->color = dsc->outline_color; + outline_dsc->opa = dsc->outline_opa; + outline_dsc->width = dsc->outline_width; + outline_dsc->side = LV_BORDER_SIDE_FULL; + t->type = LV_DRAW_TASK_TYPE_BORDER; + lv_draw_finalize_task_creation(layer, t); + } LV_ASSERT_MEM_INTEGRITY(); + + LV_PROFILER_END; } /********************** diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.h index 46a58a493..bc1439f34 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_rect.h @@ -13,7 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../lv_conf_internal.h" +#include "lv_draw.h" #include "../misc/lv_color.h" #include "../misc/lv_area.h" #include "../misc/lv_style.h" @@ -30,8 +30,9 @@ LV_EXPORT_CONST_INT(LV_RADIUS_CIRCLE); **********************/ typedef struct { - lv_coord_t radius; - lv_blend_mode_t blend_mode; + lv_draw_dsc_base_t base; + + int32_t radius; /*Background*/ lv_opa_t bg_opa; @@ -39,51 +40,107 @@ typedef struct { lv_grad_dsc_t bg_grad; /*Background img*/ - const void * bg_img_src; - const void * bg_img_symbol_font; - lv_color_t bg_img_recolor; - lv_opa_t bg_img_opa; - lv_opa_t bg_img_recolor_opa; - uint8_t bg_img_tiled; + const void * bg_image_src; + const void * bg_image_symbol_font; + lv_color_t bg_image_recolor; + lv_opa_t bg_image_opa; + lv_opa_t bg_image_recolor_opa; + uint8_t bg_image_tiled; /*Border*/ lv_color_t border_color; - lv_coord_t border_width; + int32_t border_width; lv_opa_t border_opa; - uint8_t border_post : 1; /*There is a border it will be drawn later.*/ lv_border_side_t border_side : 5; + uint8_t border_post : 1; /*The border will be drawn later*/ /*Outline*/ lv_color_t outline_color; - lv_coord_t outline_width; - lv_coord_t outline_pad; + int32_t outline_width; + int32_t outline_pad; lv_opa_t outline_opa; /*Shadow*/ lv_color_t shadow_color; - lv_coord_t shadow_width; - lv_coord_t shadow_ofs_x; - lv_coord_t shadow_ofs_y; - lv_coord_t shadow_spread; + int32_t shadow_width; + int32_t shadow_offset_x; + int32_t shadow_offset_y; + int32_t shadow_spread; lv_opa_t shadow_opa; } lv_draw_rect_dsc_t; -struct _lv_draw_ctx_t; +typedef struct { + lv_draw_dsc_base_t base; + + int32_t radius; + + lv_opa_t opa; + lv_color_t color; + lv_grad_dsc_t grad; +} lv_draw_fill_dsc_t; + +typedef struct { + lv_draw_dsc_base_t base; + + int32_t radius; + + lv_color_t color; + int32_t width; + lv_opa_t opa; + lv_border_side_t side : 5; + +} lv_draw_border_dsc_t; + +typedef struct { + lv_draw_dsc_base_t base; + + int32_t radius; + + lv_color_t color; + int32_t width; + int32_t spread; + int32_t ofs_x; + int32_t ofs_y; + lv_opa_t opa; + uint8_t bg_cover : 1; +} lv_draw_box_shadow_dsc_t; /********************** * GLOBAL PROTOTYPES **********************/ -void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc); - +/** + * Initialize a rectangle draw descriptor. + * @param dsc pointer to a draw descriptor + */ +LV_ATTRIBUTE_FAST_MEM void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc); /** - * Draw a rectangle - * @param coords the coordinates of the rectangle - * @param clip the rectangle will be drawn only in this area - * @param dsc pointer to an initialized `lv_draw_rect_dsc_t` variable + * Initialize a fill draw descriptor. + * @param dsc pointer to a draw descriptor */ -void lv_draw_rect(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); +void lv_draw_fill_dsc_init(lv_draw_fill_dsc_t * dsc); + +/** + * Initialize a border draw descriptor. + * @param dsc pointer to a draw descriptor + */ +void lv_draw_border_dsc_init(lv_draw_border_dsc_t * dsc); + +/** + * Initialize a box shadow draw descriptor. + * @param dsc pointer to a draw descriptor + */ +void lv_draw_box_shadow_dsc_init(lv_draw_box_shadow_dsc_t * dsc); + +/** + * The rectangle is a wrapper for fill, border, bg. image and box shadow. + * Internally fill, border, image and box shadow draw tasks will be created. + * @param layer pointer to a layer + * @param dsc pointer to an initialized draw descriptor variable + * @param coords the coordinates of the rectangle + */ +void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); /********************** * MACROS diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_transform.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_transform.c deleted file mode 100644 index 580351d6d..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_transform.c +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @file lv_draw_transform.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_draw.h" -#include "lv_draw_transform.h" -#include "../misc/lv_assert.h" -#include "../misc/lv_area.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ -void lv_draw_transform(lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf, lv_coord_t src_w, - lv_coord_t src_h, - lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf) -{ - LV_ASSERT_NULL(draw_ctx); - if(draw_ctx->draw_transform == NULL) { - LV_LOG_WARN("draw_ctx->draw_transform == NULL"); - return; - } - - draw_ctx->draw_transform(draw_ctx, dest_area, src_buf, src_w, src_h, src_stride, draw_dsc, cf, cbuf, abuf); - -} - - -/********************** - * STATIC FUNCTIONS - **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_transform.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_transform.h deleted file mode 100644 index 1926c2fc2..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_transform.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @file lv_draw_transform.h - * - */ - -#ifndef LV_DRAW_TRANSFORM_H -#define LV_DRAW_TRANSFORM_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" -#include "../misc/lv_area.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ -struct _lv_draw_ctx_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -void lv_draw_transform(struct _lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf, - lv_coord_t src_w, lv_coord_t src_h, - lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf); - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_TRANSFORM_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_triangle.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_triangle.c index 42b4d7799..86d236321 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_triangle.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_triangle.c @@ -6,10 +6,11 @@ /********************* * INCLUDES *********************/ -#include "lv_draw.h" +#include "../core/lv_obj.h" #include "lv_draw_triangle.h" #include "../misc/lv_math.h" -#include "../misc/lv_mem.h" +#include "../stdlib/lv_mem.h" +#include "../stdlib/lv_string.h" /********************* * DEFINES @@ -35,16 +36,36 @@ * GLOBAL FUNCTIONS **********************/ -void lv_draw_polygon(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[], - uint16_t point_cnt) +void lv_draw_triangle_dsc_init(lv_draw_triangle_dsc_t * dsc) { - draw_ctx->draw_polygon(draw_ctx, draw_dsc, points, point_cnt); + LV_PROFILER_BEGIN; + lv_memzero(dsc, sizeof(lv_draw_triangle_dsc_t)); + dsc->bg_color = lv_color_white(); + dsc->bg_grad.stops[0].color = lv_color_white(); + dsc->bg_grad.stops[1].color = lv_color_black(); + dsc->bg_grad.stops[1].frac = 0xFF; + dsc->bg_grad.stops_count = 2; + dsc->bg_opa = LV_OPA_COVER; + LV_PROFILER_END; } -void lv_draw_triangle(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[]) +void lv_draw_triangle(lv_layer_t * layer, const lv_draw_triangle_dsc_t * dsc) { + LV_PROFILER_BEGIN; + lv_area_t a; + a.x1 = (int32_t)LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + a.y1 = (int32_t)LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); + a.x2 = (int32_t)LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + a.y2 = (int32_t)LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); - draw_ctx->draw_polygon(draw_ctx, draw_dsc, points, 3); + lv_draw_task_t * t = lv_draw_add_task(layer, &a); + + t->draw_dsc = lv_malloc(sizeof(*dsc)); + lv_memcpy(t->draw_dsc, dsc, sizeof(*dsc)); + t->type = LV_DRAW_TASK_TYPE_TRIANGLE; + + lv_draw_finalize_task_creation(layer, t); + LV_PROFILER_END; } /********************** diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_triangle.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_triangle.h index e8d857502..618908d4a 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_triangle.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_triangle.h @@ -22,15 +22,33 @@ extern "C" { /********************** * TYPEDEFS **********************/ +typedef struct { + lv_draw_dsc_base_t base; + + lv_opa_t bg_opa; + lv_color_t bg_color; + lv_grad_dsc_t bg_grad; + + lv_point_precise_t p[3]; +} lv_draw_triangle_dsc_t; /********************** * GLOBAL PROTOTYPES **********************/ -void lv_draw_polygon(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[], - uint16_t point_cnt); +/** + * Initialize a triangle draw descriptor + * @param dsc pointer to a draw descriptor + */ +void lv_draw_triangle_dsc_init(lv_draw_triangle_dsc_t * draw_dsc); + +/** + * Create a triangle draw task + * @param layer pointer to a layer + * @param dsc pointer to an initialized `lv_draw_triangle_dsc_t` variable + */ +void lv_draw_triangle(lv_layer_t * layer, const lv_draw_triangle_dsc_t * draw_dsc); -void lv_draw_triangle(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[]); /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_vector.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_vector.c new file mode 100644 index 000000000..6873f25d7 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_vector.c @@ -0,0 +1,753 @@ +/** +* @file lv_draw_vector.c + * + */ + +/********************* +* INCLUDES + *********************/ +#include "lv_draw_vector.h" + +#if LV_USE_VECTOR_GRAPHIC + +#include "../misc/lv_ll.h" +#include "../stdlib/lv_string.h" +#include +#include + +/********************* +* DEFINES + *********************/ + +#ifndef M_PI + #define M_PI 3.1415926f +#endif + +#define CHECK_AND_RESIZE_PATH_CONTAINER(P, N) \ + do { \ + if ((lv_array_size(&(P)->ops) + (N)) > lv_array_capacity(&(P)->ops)) { \ + lv_array_resize(&(P)->ops, ((P)->ops.capacity << 1)); \ + } \ + if ((lv_array_size(&(P)->points) + (N)) > lv_array_capacity(&(P)->points)) { \ + lv_array_resize(&(P)->points, ((P)->points.capacity << 1)); \ + } \ + } while(0) + +/********************** +* TYPEDEFS + **********************/ + +typedef struct { + lv_vector_path_t * path; + lv_vector_draw_dsc_t dsc; +} _lv_vector_draw_task; + +/********************** +* STATIC PROTOTYPES + **********************/ + +static bool _is_identity_or_translation(const lv_matrix_t * matrix) +{ + return (matrix->m[0][0] == 1.0f && + matrix->m[0][1] == 0.0f && + matrix->m[1][0] == 0.0f && + matrix->m[1][1] == 1.0f && + matrix->m[2][0] == 0.0f && + matrix->m[2][1] == 0.0f && + matrix->m[2][2] == 1.0f); +} + +static void _multiply_matrix(lv_matrix_t * matrix, const lv_matrix_t * mul) +{ + /*TODO: use NEON to optimize this function on ARM architecture.*/ + lv_matrix_t tmp; + + for(int y = 0; y < 3; y++) { + for(int x = 0; x < 3; x++) { + tmp.m[y][x] = (matrix->m[y][0] * mul->m[0][x]) + + (matrix->m[y][1] * mul->m[1][x]) + + (matrix->m[y][2] * mul->m[2][x]); + } + } + + lv_memcpy(matrix, &tmp, sizeof(lv_matrix_t)); +} + +static void _copy_draw_dsc(lv_vector_draw_dsc_t * dst, const lv_vector_draw_dsc_t * src) +{ + dst->fill_dsc.style = src->fill_dsc.style; + dst->fill_dsc.color = src->fill_dsc.color; + dst->fill_dsc.opa = src->fill_dsc.opa; + dst->fill_dsc.fill_rule = src->fill_dsc.fill_rule; + dst->fill_dsc.gradient.style = src->fill_dsc.gradient.style; + dst->fill_dsc.gradient.cx = src->fill_dsc.gradient.cx; + dst->fill_dsc.gradient.cy = src->fill_dsc.gradient.cy; + dst->fill_dsc.gradient.cr = src->fill_dsc.gradient.cr; + dst->fill_dsc.gradient.spread = src->fill_dsc.gradient.spread; + lv_memcpy(&(dst->fill_dsc.gradient.grad), &(src->fill_dsc.gradient.grad), sizeof(lv_grad_dsc_t)); + lv_memcpy(&(dst->fill_dsc.img_dsc), &(src->fill_dsc.img_dsc), sizeof(lv_draw_image_dsc_t)); + lv_memcpy(&(dst->fill_dsc.matrix), &(src->fill_dsc.matrix), sizeof(lv_matrix_t)); + + dst->stroke_dsc.style = src->stroke_dsc.style; + dst->stroke_dsc.color = src->stroke_dsc.color; + dst->stroke_dsc.opa = src->stroke_dsc.opa; + dst->stroke_dsc.width = src->stroke_dsc.width; + dst->stroke_dsc.cap = src->stroke_dsc.cap; + dst->stroke_dsc.join = src->stroke_dsc.join; + dst->stroke_dsc.miter_limit = src->stroke_dsc.miter_limit; + lv_array_copy(&(dst->stroke_dsc.dash_pattern), &(src->stroke_dsc.dash_pattern)); + dst->stroke_dsc.gradient.style = src->stroke_dsc.gradient.style; + dst->stroke_dsc.gradient.cx = src->stroke_dsc.gradient.cx; + dst->stroke_dsc.gradient.cy = src->stroke_dsc.gradient.cy; + dst->stroke_dsc.gradient.cr = src->stroke_dsc.gradient.cr; + dst->stroke_dsc.gradient.spread = src->fill_dsc.gradient.spread; + lv_memcpy(&(dst->stroke_dsc.gradient.grad), &(src->stroke_dsc.gradient.grad), sizeof(lv_grad_dsc_t)); + lv_memcpy(&(dst->stroke_dsc.matrix), &(src->stroke_dsc.matrix), sizeof(lv_matrix_t)); + + dst->blend_mode = src->blend_mode; + lv_memcpy(&(dst->matrix), &(src->matrix), sizeof(lv_matrix_t)); + lv_area_copy(&(dst->scissor_area), &(src->scissor_area)); +} +/********************** +* GLOBAL FUNCTIONS + **********************/ + +/* matrix functions */ +void lv_matrix_identity(lv_matrix_t * matrix) +{ + matrix->m[0][0] = 1.0f; + matrix->m[0][1] = 0.0f; + matrix->m[0][2] = 0.0f; + matrix->m[1][0] = 0.0f; + matrix->m[1][1] = 1.0f; + matrix->m[1][2] = 0.0f; + matrix->m[2][0] = 0.0f; + matrix->m[2][1] = 0.0f; + matrix->m[2][2] = 1.0f; +} + +void lv_matrix_translate(lv_matrix_t * matrix, float dx, float dy) +{ + if(_is_identity_or_translation(matrix)) { + /*optimization for matrix translation.*/ + matrix->m[0][2] += dx; + matrix->m[1][2] += dy; + return; + } + + lv_matrix_t tlm = {{ + {1.0f, 0.0f, dx}, + {0.0f, 1.0f, dy}, + {0.0f, 0.0f, 1.0f}, + } + }; + + _multiply_matrix(matrix, &tlm); +} + +void lv_matrix_scale(lv_matrix_t * matrix, float scale_x, float scale_y) +{ + lv_matrix_t scm = {{ + {scale_x, 0.0f, 0.0f}, + {0.0f, scale_y, 0.0f}, + {0.0f, 0.0f, 1.0f}, + } + }; + + _multiply_matrix(matrix, &scm); +} + +void lv_matrix_rotate(lv_matrix_t * matrix, float degree) +{ + float radian = degree / 180.0f * (float)M_PI; + float cos_r = cosf(radian); + float sin_r = sinf(radian); + + lv_matrix_t rtm = {{ + {cos_r, -sin_r, 0.0f}, + {sin_r, cos_r, 0.0f}, + {0.0f, 0.0f, 1.0f}, + } + }; + + _multiply_matrix(matrix, &rtm); +} + +void lv_matrix_skew(lv_matrix_t * matrix, float skew_x, float skew_y) +{ + float rskew_x = skew_x / 180.0f * (float)M_PI; + float rskew_y = skew_y / 180.0f * (float)M_PI; + float tan_x = tanf(rskew_x); + float tan_y = tanf(rskew_y); + + lv_matrix_t skm = {{ + {1.0f, tan_x, 0.0f}, + {tan_y, 1.0f, 0.0f}, + {0.0f, 0.0f, 1.0f}, + } + }; + + _multiply_matrix(matrix, &skm); +} + +void lv_matrix_multiply(lv_matrix_t * matrix, const lv_matrix_t * m) +{ + _multiply_matrix(matrix, m); +} + +/* path functions */ +lv_vector_path_t * lv_vector_path_create(lv_vector_path_quality_t quality) +{ + lv_vector_path_t * path = lv_malloc(sizeof(lv_vector_path_t)); + LV_ASSERT_MALLOC(path); + lv_memzero(path, sizeof(lv_vector_path_t)); + path->quality = quality; + lv_array_init(&path->ops, 8, sizeof(uint8_t)); + lv_array_init(&path->points, 8, sizeof(lv_fpoint_t)); + return path; +} + +void lv_vector_path_copy(lv_vector_path_t * target_path, const lv_vector_path_t * path) +{ + target_path->quality = path->quality; + lv_array_copy(&target_path->ops, &path->ops); + lv_array_copy(&target_path->points, &path->points); +} + +void lv_vector_path_clear(lv_vector_path_t * path) +{ + lv_array_clear(&path->ops); + lv_array_clear(&path->points); +} + +void lv_vector_path_delete(lv_vector_path_t * path) +{ + lv_array_deinit(&path->ops); + lv_array_deinit(&path->points); + lv_free(path); +} + +void lv_vector_path_move_to(lv_vector_path_t * path, const lv_fpoint_t * p) +{ + CHECK_AND_RESIZE_PATH_CONTAINER(path, 1); + + uint8_t op = LV_VECTOR_PATH_OP_MOVE_TO; + lv_array_push_back(&path->ops, &op); + lv_array_push_back(&path->points, p); +} + +void lv_vector_path_line_to(lv_vector_path_t * path, const lv_fpoint_t * p) +{ + if(lv_array_is_empty(&path->ops)) { + /*first op must be move_to*/ + return; + } + + CHECK_AND_RESIZE_PATH_CONTAINER(path, 1); + + uint8_t op = LV_VECTOR_PATH_OP_LINE_TO; + lv_array_push_back(&path->ops, &op); + lv_array_push_back(&path->points, p); +} + +void lv_vector_path_quad_to(lv_vector_path_t * path, const lv_fpoint_t * p1, const lv_fpoint_t * p2) +{ + if(lv_array_is_empty(&path->ops)) { + /*first op must be move_to*/ + return; + } + + CHECK_AND_RESIZE_PATH_CONTAINER(path, 2); + + uint8_t op = LV_VECTOR_PATH_OP_QUAD_TO; + lv_array_push_back(&path->ops, &op); + lv_array_push_back(&path->points, p1); + lv_array_push_back(&path->points, p2); +} + +void lv_vector_path_cubic_to(lv_vector_path_t * path, const lv_fpoint_t * p1, const lv_fpoint_t * p2, + const lv_fpoint_t * p3) +{ + if(lv_array_is_empty(&path->ops)) { + /*first op must be move_to*/ + return; + } + + CHECK_AND_RESIZE_PATH_CONTAINER(path, 3); + + uint8_t op = LV_VECTOR_PATH_OP_CUBIC_TO; + lv_array_push_back(&path->ops, &op); + lv_array_push_back(&path->points, p1); + lv_array_push_back(&path->points, p2); + lv_array_push_back(&path->points, p3); +} + +void lv_vector_path_close(lv_vector_path_t * path) +{ + if(lv_array_is_empty(&path->ops)) { + /*first op must be move_to*/ + return; + } + + CHECK_AND_RESIZE_PATH_CONTAINER(path, 1); + + uint8_t op = LV_VECTOR_PATH_OP_CLOSE; + lv_array_push_back(&path->ops, &op); +} + +void lv_vector_path_append_rect(lv_vector_path_t * path, const lv_area_t * rect, float rx, float ry) +{ + float x = rect->x1; + float y = rect->y1; + float w = (float)lv_area_get_width(rect); + float h = (float)lv_area_get_height(rect); + + float hw = w * 0.5f; + float hh = h * 0.5f; + + if(rx > hw) rx = hw; + if(ry > hh) ry = hh; + + if(rx == 0 && ry == 0) { + lv_fpoint_t pt = {x, y}; + lv_vector_path_move_to(path, &pt); + pt.x += w; + lv_vector_path_line_to(path, &pt); + pt.y += h; + lv_vector_path_line_to(path, &pt); + pt.x -= w; + lv_vector_path_line_to(path, &pt); + lv_vector_path_close(path); + } + else if(rx == hw && ry == hh) { + lv_fpoint_t pt = {x + w * 0.5f, y + h * 0.5f}; + lv_vector_path_append_circle(path, &pt, rx, ry); + } + else { + float hrx = rx * 0.5f; + float hry = ry * 0.5f; + lv_fpoint_t pt, pt2, pt3; + + pt.x = x + rx; + pt.y = y; + lv_vector_path_move_to(path, &pt); + + pt.x = x + w - rx; + pt.y = y; + lv_vector_path_line_to(path, &pt); + + pt.x = x + w - rx + hrx; + pt.y = y; + pt2.x = x + w; + pt2.y = y + ry - hry; + pt3.x = x + w; + pt3.y = y + ry; + lv_vector_path_cubic_to(path, &pt, &pt2, &pt3); + + pt.x = x + w; + pt.y = y + h - ry; + lv_vector_path_line_to(path, &pt); + + pt.x = x + w; + pt.y = y + h - ry + hry; + pt2.x = x + w - rx + hrx; + pt2.y = y + h; + pt3.x = x + w - rx; + pt3.y = y + h; + lv_vector_path_cubic_to(path, &pt, &pt2, &pt3); + + pt.x = x + rx; + pt.y = y + h; + lv_vector_path_line_to(path, &pt); + + pt.x = x + rx - hrx; + pt.y = y + h; + pt2.x = x; + pt2.y = y + h - ry + hry; + pt3.x = x; + pt3.y = y + h - ry; + lv_vector_path_cubic_to(path, &pt, &pt2, &pt3); + + pt.x = x; + pt.y = y + ry; + lv_vector_path_line_to(path, &pt); + + pt.x = x; + pt.y = y + ry - hry; + pt2.x = x + rx - hrx; + pt2.y = y; + pt3.x = x + rx; + pt3.y = y; + lv_vector_path_cubic_to(path, &pt, &pt2, &pt3); + lv_vector_path_close(path); + } +} + +void lv_vector_path_append_circle(lv_vector_path_t * path, const lv_fpoint_t * c, float rx, float ry) +{ + float krx = rx * 0.552284f; + float kry = ry * 0.552284f; + float cx = c->x; + float cy = c->y; + + lv_fpoint_t pt, pt2, pt3; + pt.x = cx; + pt.y = cy - ry; + lv_vector_path_move_to(path, &pt); + + pt.x = cx + krx; + pt.y = cy - ry; + pt2.x = cx + rx; + pt2.y = cy - kry; + pt3.x = cx + rx; + pt3.y = cy; + lv_vector_path_cubic_to(path, &pt, &pt2, &pt3); + + pt.x = cx + rx; + pt.y = cy + kry; + pt2.x = cx + krx; + pt2.y = cy + ry; + pt3.x = cx; + pt3.y = cy + ry; + lv_vector_path_cubic_to(path, &pt, &pt2, &pt3); + + pt.x = cx - krx; + pt.y = cy + ry; + pt2.x = cx - rx; + pt2.y = cy + kry; + pt3.x = cx - rx; + pt3.y = cy; + lv_vector_path_cubic_to(path, &pt, &pt2, &pt3); + + pt.x = cx - rx; + pt.y = cy - kry; + pt2.x = cx - krx; + pt2.y = cy - ry; + pt3.x = cx; + pt3.y = cy - ry; + lv_vector_path_cubic_to(path, &pt, &pt2, &pt3); + + lv_vector_path_close(path); +} + +void lv_vector_path_append_path(lv_vector_path_t * path, const lv_vector_path_t * subpath) +{ + uint32_t ops_size = lv_array_size(&path->ops); + uint32_t nops_size = lv_array_size(&subpath->ops); + uint32_t point_size = lv_array_size(&path->points); + uint32_t npoint_size = lv_array_size(&subpath->points); + + lv_array_concat(&path->ops, &subpath->ops); + path->ops.size = ops_size + nops_size; + + lv_array_concat(&path->points, &subpath->points); + path->points.size = point_size + npoint_size; +} + +/* draw dsc functions */ + +lv_vector_dsc_t * lv_vector_dsc_create(lv_layer_t * layer) +{ + lv_vector_dsc_t * dsc = lv_malloc(sizeof(lv_vector_dsc_t)); + LV_ASSERT_MALLOC(dsc); + lv_memzero(dsc, sizeof(lv_vector_dsc_t)); + + dsc->layer = layer; + + lv_vector_fill_dsc_t * fill_dsc = &(dsc->current_dsc.fill_dsc); + fill_dsc->style = LV_VECTOR_DRAW_STYLE_SOLID; + fill_dsc->color = lv_color_to_32(lv_color_black(), 0xFF); + fill_dsc->opa = LV_OPA_COVER; + fill_dsc->fill_rule = LV_VECTOR_FILL_NONZERO; + lv_matrix_identity(&(fill_dsc->matrix)); /*identity matrix*/ + + lv_vector_stroke_dsc_t * stroke_dsc = &(dsc->current_dsc.stroke_dsc); + stroke_dsc->style = LV_VECTOR_DRAW_STYLE_SOLID; + stroke_dsc->color = lv_color_to_32(lv_color_black(), 0xFF); + stroke_dsc->opa = LV_OPA_0; /*default no stroke*/ + stroke_dsc->width = 1.0f; + stroke_dsc->cap = LV_VECTOR_STROKE_CAP_BUTT; + stroke_dsc->join = LV_VECTOR_STROKE_JOIN_MITER; + stroke_dsc->miter_limit = 4.0f; + lv_matrix_identity(&(stroke_dsc->matrix)); /*identity matrix*/ + + dsc->current_dsc.blend_mode = LV_VECTOR_BLEND_SRC_OVER; + dsc->current_dsc.scissor_area = layer->_clip_area; + lv_matrix_identity(&(dsc->current_dsc.matrix)); /*identity matrix*/ + dsc->tasks.task_list = NULL; + return dsc; +} + +void lv_vector_dsc_delete(lv_vector_dsc_t * dsc) +{ + if(dsc->tasks.task_list) { + lv_ll_t * task_list = dsc->tasks.task_list; + _lv_vector_for_each_destroy_tasks(task_list, NULL, NULL); + dsc->tasks.task_list = NULL; + } + lv_array_deinit(&(dsc->current_dsc.stroke_dsc.dash_pattern)); + lv_free(dsc); +} + +void lv_vector_dsc_set_blend_mode(lv_vector_dsc_t * dsc, lv_vector_blend_t blend) +{ + dsc->current_dsc.blend_mode = blend; +} + +void lv_vector_dsc_set_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix) +{ + lv_memcpy(&(dsc->current_dsc.matrix), matrix, sizeof(lv_matrix_t)); +} + +void lv_vector_dsc_set_fill_color(lv_vector_dsc_t * dsc, lv_color_t color) +{ + dsc->current_dsc.fill_dsc.style = LV_VECTOR_DRAW_STYLE_SOLID; + dsc->current_dsc.fill_dsc.color = lv_color_to_32(color, 0xFF); +} + +void lv_vector_dsc_set_fill_color32(lv_vector_dsc_t * dsc, lv_color32_t color) +{ + dsc->current_dsc.fill_dsc.style = LV_VECTOR_DRAW_STYLE_SOLID; + dsc->current_dsc.fill_dsc.color = color; +} + +void lv_vector_dsc_set_fill_opa(lv_vector_dsc_t * dsc, lv_opa_t opa) +{ + dsc->current_dsc.fill_dsc.opa = opa; +} + +void lv_vector_dsc_set_fill_rule(lv_vector_dsc_t * dsc, lv_vector_fill_t rule) +{ + dsc->current_dsc.fill_dsc.fill_rule = rule; +} + +void lv_vector_dsc_set_fill_image(lv_vector_dsc_t * dsc, const lv_draw_image_dsc_t * img_dsc) +{ + dsc->current_dsc.fill_dsc.style = LV_VECTOR_DRAW_STYLE_PATTERN; + lv_memcpy(&(dsc->current_dsc.fill_dsc.img_dsc), img_dsc, sizeof(lv_draw_image_dsc_t)); +} + +void lv_vector_dsc_set_fill_linear_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, + lv_vector_gradient_spread_t spread) +{ + dsc->current_dsc.fill_dsc.style = LV_VECTOR_DRAW_STYLE_GRADIENT; + dsc->current_dsc.fill_dsc.gradient.style = LV_VECTOR_GRADIENT_STYLE_LINEAR; + dsc->current_dsc.fill_dsc.gradient.spread = spread; + lv_memcpy(&(dsc->current_dsc.fill_dsc.gradient.grad), grad, sizeof(lv_grad_dsc_t)); +} + +void lv_vector_dsc_set_fill_radial_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, float cx, float cy, + float radius, lv_vector_gradient_spread_t spread) +{ + dsc->current_dsc.fill_dsc.style = LV_VECTOR_DRAW_STYLE_GRADIENT; + dsc->current_dsc.fill_dsc.gradient.style = LV_VECTOR_GRADIENT_STYLE_RADIAL; + dsc->current_dsc.fill_dsc.gradient.cx = cx; + dsc->current_dsc.fill_dsc.gradient.cy = cy; + dsc->current_dsc.fill_dsc.gradient.cr = radius; + dsc->current_dsc.fill_dsc.gradient.spread = spread; + lv_memcpy(&(dsc->current_dsc.fill_dsc.gradient.grad), grad, sizeof(lv_grad_dsc_t)); +} + +void lv_vector_dsc_set_fill_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix) +{ + lv_memcpy(&(dsc->current_dsc.fill_dsc.matrix), matrix, sizeof(lv_matrix_t)); +} + +void lv_vector_dsc_set_stroke_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix) +{ + lv_memcpy(&(dsc->current_dsc.stroke_dsc.matrix), matrix, sizeof(lv_matrix_t)); +} + +void lv_vector_dsc_set_stroke_color32(lv_vector_dsc_t * dsc, lv_color32_t color) +{ + dsc->current_dsc.stroke_dsc.style = LV_VECTOR_DRAW_STYLE_SOLID; + dsc->current_dsc.stroke_dsc.color = color; +} + +void lv_vector_dsc_set_stroke_color(lv_vector_dsc_t * dsc, lv_color_t color) +{ + dsc->current_dsc.stroke_dsc.style = LV_VECTOR_DRAW_STYLE_SOLID; + dsc->current_dsc.stroke_dsc.color = lv_color_to_32(color, 0xFF); +} + +void lv_vector_dsc_set_stroke_opa(lv_vector_dsc_t * dsc, lv_opa_t opa) +{ + dsc->current_dsc.stroke_dsc.opa = opa; +} + +void lv_vector_dsc_set_stroke_width(lv_vector_dsc_t * dsc, float width) +{ + dsc->current_dsc.stroke_dsc.width = width; +} + +void lv_vector_dsc_set_stroke_dash(lv_vector_dsc_t * dsc, float * dash_pattern, uint16_t dash_count) +{ + lv_array_t * dash_array = &(dsc->current_dsc.stroke_dsc.dash_pattern); + if(dash_pattern) { + lv_array_clear(dash_array); + if(lv_array_capacity(dash_array) == 0) { + lv_array_init(dash_array, dash_count, sizeof(float)); + } + else { + lv_array_resize(dash_array, dash_count); + } + for(uint16_t i = 0; i < dash_count; i++) { + lv_array_push_back(dash_array, &dash_pattern[i]); + } + } + else { /*clear dash*/ + lv_array_clear(dash_array); + } +} + +void lv_vector_dsc_set_stroke_cap(lv_vector_dsc_t * dsc, lv_vector_stroke_cap_t cap) +{ + dsc->current_dsc.stroke_dsc.cap = cap; +} + +void lv_vector_dsc_set_stroke_join(lv_vector_dsc_t * dsc, lv_vector_stroke_join_t join) +{ + dsc->current_dsc.stroke_dsc.join = join; +} + +void lv_vector_dsc_set_stroke_miter_limit(lv_vector_dsc_t * dsc, uint16_t miter_limit) +{ + dsc->current_dsc.stroke_dsc.miter_limit = miter_limit; +} + +void lv_vector_dsc_set_stroke_linear_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, + lv_vector_gradient_spread_t spread) +{ + dsc->current_dsc.stroke_dsc.style = LV_VECTOR_DRAW_STYLE_GRADIENT; + dsc->current_dsc.stroke_dsc.gradient.style = LV_VECTOR_GRADIENT_STYLE_LINEAR; + dsc->current_dsc.stroke_dsc.gradient.spread = spread; + lv_memcpy(&(dsc->current_dsc.stroke_dsc.gradient.grad), grad, sizeof(lv_grad_dsc_t)); +} + +void lv_vector_dsc_set_stroke_radial_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, float cx, float cy, + float radius, lv_vector_gradient_spread_t spread) +{ + dsc->current_dsc.stroke_dsc.style = LV_VECTOR_DRAW_STYLE_GRADIENT; + dsc->current_dsc.stroke_dsc.gradient.style = LV_VECTOR_GRADIENT_STYLE_RADIAL; + dsc->current_dsc.stroke_dsc.gradient.cx = cx; + dsc->current_dsc.stroke_dsc.gradient.cy = cy; + dsc->current_dsc.stroke_dsc.gradient.cr = radius; + dsc->current_dsc.stroke_dsc.gradient.spread = spread; + lv_memcpy(&(dsc->current_dsc.stroke_dsc.gradient.grad), grad, sizeof(lv_grad_dsc_t)); +} + +/* draw functions */ +void lv_vector_dsc_add_path(lv_vector_dsc_t * dsc, const lv_vector_path_t * path) +{ + lv_area_t rect; + if(!_lv_area_intersect(&rect, &(dsc->layer->_clip_area), &(dsc->current_dsc.scissor_area))) { + return; + } + + if(dsc->current_dsc.fill_dsc.opa == 0 + && dsc->current_dsc.stroke_dsc.opa == 0) { + return; + } + + if(!dsc->tasks.task_list) { + dsc->tasks.task_list = lv_malloc(sizeof(lv_ll_t)); + LV_ASSERT_MALLOC(dsc->tasks.task_list); + _lv_ll_init(dsc->tasks.task_list, sizeof(_lv_vector_draw_task)); + } + + _lv_vector_draw_task * new_task = (_lv_vector_draw_task *)_lv_ll_ins_tail(dsc->tasks.task_list); + lv_memset(new_task, 0, sizeof(_lv_vector_draw_task)); + + new_task->path = lv_vector_path_create(0); + + _copy_draw_dsc(&(new_task->dsc), &(dsc->current_dsc)); + lv_vector_path_copy(new_task->path, path); + new_task->dsc.scissor_area = rect; +} + +void lv_vector_clear_area(lv_vector_dsc_t * dsc, const lv_area_t * rect) +{ + lv_area_t r; + if(!_lv_area_intersect(&r, &(dsc->layer->_clip_area), &(dsc->current_dsc.scissor_area))) { + return; + } + + if(!dsc->tasks.task_list) { + dsc->tasks.task_list = lv_malloc(sizeof(lv_ll_t)); + LV_ASSERT_MALLOC(dsc->tasks.task_list); + _lv_ll_init(dsc->tasks.task_list, sizeof(_lv_vector_draw_task)); + } + + _lv_vector_draw_task * new_task = (_lv_vector_draw_task *)_lv_ll_ins_tail(dsc->tasks.task_list); + lv_memset(new_task, 0, sizeof(_lv_vector_draw_task)); + + new_task->dsc.fill_dsc.color = dsc->current_dsc.fill_dsc.color; + lv_area_copy(&(new_task->dsc.scissor_area), rect); +} + +void lv_draw_vector(lv_vector_dsc_t * dsc) +{ + if(!dsc->tasks.task_list) { + return; + } + + lv_layer_t * layer = dsc->layer; + + lv_draw_task_t * t = lv_draw_add_task(layer, &(layer->_clip_area)); + t->type = LV_DRAW_TASK_TYPE_VECTOR; + t->draw_dsc = lv_malloc(sizeof(lv_draw_vector_task_dsc_t)); + lv_memcpy(t->draw_dsc, &(dsc->tasks), sizeof(lv_draw_vector_task_dsc_t)); + lv_draw_finalize_task_creation(layer, t); + dsc->tasks.task_list = NULL; +} + +/* draw dsc transform */ +void lv_vector_dsc_identity(lv_vector_dsc_t * dsc) +{ + lv_matrix_identity(&(dsc->current_dsc.matrix)); /*identity matrix*/ +} + +void lv_vector_dsc_scale(lv_vector_dsc_t * dsc, float scale_x, float scale_y) +{ + lv_matrix_scale(&(dsc->current_dsc.matrix), scale_x, scale_y); +} + +void lv_vector_dsc_rotate(lv_vector_dsc_t * dsc, float degree) +{ + lv_matrix_rotate(&(dsc->current_dsc.matrix), degree); +} + +void lv_vector_dsc_translate(lv_vector_dsc_t * dsc, float tx, float ty) +{ + lv_matrix_translate(&(dsc->current_dsc.matrix), tx, ty); +} + +void lv_vector_dsc_skew(lv_vector_dsc_t * dsc, float skew_x, float skew_y) +{ + lv_matrix_skew(&(dsc->current_dsc.matrix), skew_x, skew_y); +} + +void _lv_vector_for_each_destroy_tasks(lv_ll_t * task_list, vector_draw_task_cb cb, void * data) +{ + _lv_vector_draw_task * task = _lv_ll_get_head(task_list); + _lv_vector_draw_task * next_task = NULL; + + while(task != NULL) { + next_task = _lv_ll_get_next(task_list, task); + _lv_ll_remove(task_list, task); + + if(cb) { + cb(data, task->path, &(task->dsc)); + } + + if(task->path) { + lv_vector_path_delete(task->path); + } + lv_array_deinit(&(task->dsc.stroke_dsc.dash_pattern)); + + lv_free(task); + task = next_task; + } + lv_free(task_list); +} +#endif /* LV_USE_VECTOR_GRAPHIC */ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_vector.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_vector.h new file mode 100644 index 000000000..a296c5a5c --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_draw_vector.h @@ -0,0 +1,538 @@ +/** + * @file lv_draw_vector.h + * + */ + +#ifndef LV_DRAW_VECTOR_H +#define LV_DRAW_VECTOR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_draw.h" +#include "../misc/lv_array.h" + +#if LV_USE_VECTOR_GRAPHIC + +/********************** + * TYPEDEFS + **********************/ +enum { + LV_VECTOR_FILL_NONZERO = 0, + LV_VECTOR_FILL_EVENODD, +}; +typedef uint8_t lv_vector_fill_t; + +enum { + LV_VECTOR_STROKE_CAP_BUTT = 0, + LV_VECTOR_STROKE_CAP_SQUARE, + LV_VECTOR_STROKE_CAP_ROUND, +}; +typedef uint8_t lv_vector_stroke_cap_t; + +enum { + LV_VECTOR_STROKE_JOIN_MITER = 0, + LV_VECTOR_STROKE_JOIN_BEVEL, + LV_VECTOR_STROKE_JOIN_ROUND, +}; +typedef uint8_t lv_vector_stroke_join_t; + +enum { + LV_VECTOR_PATH_QUALITY_MEDIUM = 0, /* default*/ + LV_VECTOR_PATH_QUALITY_HIGH, + LV_VECTOR_PATH_QUALITY_LOW, +}; +typedef uint8_t lv_vector_path_quality_t; + +enum { + LV_VECTOR_BLEND_SRC_OVER = 0, + LV_VECTOR_BLEND_SRC_IN, + LV_VECTOR_BLEND_DST_OVER, + LV_VECTOR_BLEND_DST_IN, + LV_VECTOR_BLEND_SCREEN, + LV_VECTOR_BLEND_MULTIPLY, + LV_VECTOR_BLEND_NONE, + LV_VECTOR_BLEND_ADDITIVE, + LV_VECTOR_BLEND_SUBTRACTIVE, +}; +typedef uint8_t lv_vector_blend_t; + +enum { + LV_VECTOR_PATH_OP_MOVE_TO = 0, + LV_VECTOR_PATH_OP_LINE_TO, + LV_VECTOR_PATH_OP_QUAD_TO, + LV_VECTOR_PATH_OP_CUBIC_TO, + LV_VECTOR_PATH_OP_CLOSE, +}; +typedef uint8_t lv_vector_path_op_t; + +enum { + LV_VECTOR_DRAW_STYLE_SOLID = 0, + LV_VECTOR_DRAW_STYLE_PATTERN, + LV_VECTOR_DRAW_STYLE_GRADIENT, +}; +typedef uint8_t lv_vector_draw_style_t; + +enum { + LV_VECTOR_GRADIENT_SPREAD_PAD = 0, + LV_VECTOR_GRADIENT_SPREAD_REPEAT, + LV_VECTOR_GRADIENT_SPREAD_REFLECT, +}; +typedef uint8_t lv_vector_gradient_spread_t; + +enum { + LV_VECTOR_GRADIENT_STYLE_LINEAR = 0, + LV_VECTOR_GRADIENT_STYLE_RADIAL, +}; +typedef uint8_t lv_vector_gradient_style_t; + +typedef struct { + float x; + float y; +} lv_fpoint_t; + +typedef struct { + float m[3][3]; +} lv_matrix_t; + +typedef struct { + lv_vector_path_quality_t quality; + lv_array_t ops; + lv_array_t points; +} lv_vector_path_t; + +typedef struct { + lv_vector_gradient_style_t style; + lv_grad_dsc_t grad; + float cx; + float cy; + float cr; + lv_vector_gradient_spread_t spread; +} lv_vector_gradient_t; + +typedef struct { + lv_vector_draw_style_t style; + lv_color32_t color; + lv_opa_t opa; + lv_vector_fill_t fill_rule; + lv_draw_image_dsc_t img_dsc; + lv_vector_gradient_t gradient; + lv_matrix_t matrix; +} lv_vector_fill_dsc_t; + +typedef struct { + lv_vector_draw_style_t style; + lv_color32_t color; + lv_opa_t opa; + float width; + lv_array_t dash_pattern; + lv_vector_stroke_cap_t cap; + lv_vector_stroke_join_t join; + uint16_t miter_limit; + lv_vector_gradient_t gradient; + lv_matrix_t matrix; +} lv_vector_stroke_dsc_t; + +typedef struct { + lv_vector_fill_dsc_t fill_dsc; + lv_vector_stroke_dsc_t stroke_dsc; + lv_matrix_t matrix; + lv_vector_blend_t blend_mode; + lv_area_t scissor_area; +} lv_vector_draw_dsc_t; + +typedef struct { + lv_draw_dsc_base_t base; + lv_ll_t * task_list; /*draw task list.*/ +} lv_draw_vector_task_dsc_t; + +typedef struct { + lv_layer_t * layer; + lv_vector_draw_dsc_t current_dsc; + /* private data */ + lv_draw_vector_task_dsc_t tasks; +} lv_vector_dsc_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Set matrix to identity matrix + * @param matrix pointer to a matrix + */ +void lv_matrix_identity(lv_matrix_t * matrix); + +/** + * Translate the matrix to new position + * @param matrix pointer to a matrix + * @param tx the amount of translate in x direction + * @param tx the amount of translate in y direction + */ +void lv_matrix_translate(lv_matrix_t * matrix, float tx, float ty); + +/** + * Change the scale factor of the matrix + * @param matrix pointer to a matrix + * @param scale_x the scale factor for the X direction + * @param scale_y the scale factor for the Y direction + */ +void lv_matrix_scale(lv_matrix_t * matrix, float scale_x, float scale_y); + +/** + * Rotate the matrix with origin + * @param matrix pointer to a matrix + * @param degree angle to rotate + */ +void lv_matrix_rotate(lv_matrix_t * matrix, float degree); + +/** + * Change the skew factor of the matrix + * @param matrix pointer to a matrix + * @param skew_x the skew factor for x direction + * @param skew_y the skew factor for y direction + */ +void lv_matrix_skew(lv_matrix_t * matrix, float skew_x, float skew_y); + +/** + * Multiply two matrix and store the result to the first one + * @param matrix pointer to a matrix + * @param matrix2 pointer to another matrix + */ +void lv_matrix_multiply(lv_matrix_t * matrix, const lv_matrix_t * matrix2); + +/** + * Create a vector graphic path object + * @param quality the quality hint of path + * @return pointer to the created path object + */ +lv_vector_path_t * lv_vector_path_create(lv_vector_path_quality_t quality); + +/** + * Copy a path data to another + * @param target_path pointer to a path + * @param path pointer to source path + */ +void lv_vector_path_copy(lv_vector_path_t * target_path, const lv_vector_path_t * path); + +/** + * Clear path data + * @param path pointer to a path + */ +void lv_vector_path_clear(lv_vector_path_t * path); + +/** + * Delete the graphic path object + * @param path pointer to a path + */ +void lv_vector_path_delete(lv_vector_path_t * path); + +/** + * Begin a new sub path and set a point to path + * @param path pointer to a path + * @param p pointer to a `lv_fpoint_t` variable + */ +void lv_vector_path_move_to(lv_vector_path_t * path, const lv_fpoint_t * p); + +/** + * Add a line to the path from last point to the point + * @param path pointer to a path + * @param p pointer to a `lv_fpoint_t` variable + */ +void lv_vector_path_line_to(lv_vector_path_t * path, const lv_fpoint_t * p); + +/** + * Add a quadratic bezier line to the path from last point to the point + * @param path pointer to a path + * @param p1 pointer to a `lv_fpoint_t` variable for control point + * @param p2 pointer to a `lv_fpoint_t` variable for end point + */ +void lv_vector_path_quad_to(lv_vector_path_t * path, const lv_fpoint_t * p1, const lv_fpoint_t * p2); + +/** + * Add a cubic bezier line to the path from last point to the point + * @param path pointer to a path + * @param p1 pointer to a `lv_fpoint_t` variable for first control point + * @param p2 pointer to a `lv_fpoint_t` variable for second control point + * @param p3 pointer to a `lv_fpoint_t` variable for end point + */ +void lv_vector_path_cubic_to(lv_vector_path_t * path, const lv_fpoint_t * p1, const lv_fpoint_t * p2, + const lv_fpoint_t * p3); + +/** + * Close the sub path + * @param path pointer to a path + */ +void lv_vector_path_close(lv_vector_path_t * path); + +/** + * Add a rectangle to the path + * @param path pointer to a path + * @param rect pointer to a `lv_area_t` variable + * @param rx the horizontal radius for rounded rectangle + * @param ry the vertical radius for rounded rectangle + */ +void lv_vector_path_append_rect(lv_vector_path_t * path, const lv_area_t * rect, float rx, float ry); + +/** + * Add a circle to the path + * @param path pointer to a path + * @param c pointer to a `lv_fpoint_t` variable for center of the circle + * @param rx the horizontal radius for circle + * @param ry the vertical radius for circle + */ +void lv_vector_path_append_circle(lv_vector_path_t * path, const lv_fpoint_t * c, float rx, float ry); + +/** + * Add an sub path to the path + * @param path pointer to a path + * @param subpath pointer to another path which will be added + */ +void lv_vector_path_append_path(lv_vector_path_t * path, const lv_vector_path_t * subpath); + +/** + * Create a vector graphic descriptor + * @param layer pointer to a layer + * @return pointer to the created descriptor + */ +lv_vector_dsc_t * lv_vector_dsc_create(lv_layer_t * layer); + +/** + * Delete the vector graphic descriptor + * @param dsc pointer to a vector graphic descriptor + */ +void lv_vector_dsc_delete(lv_vector_dsc_t * dsc); + +/** + * Set a matrix to current transformation matrix + * @param dsc pointer to a vector graphic descriptor + * @param matrix pointer to a matrix + */ +void lv_vector_dsc_set_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix); + +/** + * Set blend mode for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param blend the blend mode to be set in `lv_vector_blend_t` + */ +void lv_vector_dsc_set_blend_mode(lv_vector_dsc_t * dsc, lv_vector_blend_t blend); + +/** + * Set fill color for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param color the color to be set in lv_color32_t format + */ +void lv_vector_dsc_set_fill_color32(lv_vector_dsc_t * dsc, lv_color32_t color); + +/** + * Set fill color for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param color the color to be set in lv_color_t format + */ +void lv_vector_dsc_set_fill_color(lv_vector_dsc_t * dsc, lv_color_t color); + +/** + * Set fill opacity for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param opa the opacity to be set in lv_opa_t format + */ +void lv_vector_dsc_set_fill_opa(lv_vector_dsc_t * dsc, lv_opa_t opa); + +/** + * Set fill rule for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param rule the fill rule to be set in lv_vector_fill_t format + */ +void lv_vector_dsc_set_fill_rule(lv_vector_dsc_t * dsc, lv_vector_fill_t rule); + +/** + * Set fill image for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param img_dsc pointer to a `lv_draw_image_dsc_t` variable + */ +void lv_vector_dsc_set_fill_image(lv_vector_dsc_t * dsc, const lv_draw_image_dsc_t * img_dsc); + +/** + * Set fill linear gradient for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param grad pointer to a `lv_grad_dsc_t` variable + * @param spread the gradient spread to be set in lv_vector_gradient_spread_t format + */ +void lv_vector_dsc_set_fill_linear_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, + lv_vector_gradient_spread_t spread); + +/** + * Set fill radial gradient for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param grad pointer to a `lv_grad_dsc_t` variable + * @param cx the x for center of the circle + * @param cy the y for center of the circle + * @param radius the radius for circle + * @param spread the gradient spread to be set in lv_vector_gradient_spread_t format + */ +void lv_vector_dsc_set_fill_radial_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, float cx, float cy, + float radius, lv_vector_gradient_spread_t spread); + +/** + * Set a matrix to current fill transformation matrix + * @param dsc pointer to a vector graphic descriptor + * @param matrix pointer to a matrix + */ +void lv_vector_dsc_set_fill_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix); + +/** + * Set stroke color for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param color the color to be set in lv_color32_t format + */ +void lv_vector_dsc_set_stroke_color32(lv_vector_dsc_t * dsc, lv_color32_t color); + +/** + * Set stroke color for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param color the color to be set in lv_color_t format + */ +void lv_vector_dsc_set_stroke_color(lv_vector_dsc_t * dsc, lv_color_t color); + +/** + * Set stroke opacity for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param opa the opacity to be set in lv_opa_t format + */ +void lv_vector_dsc_set_stroke_opa(lv_vector_dsc_t * dsc, lv_opa_t opa); + +/** + * Set stroke line width for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param width the stroke line width + */ +void lv_vector_dsc_set_stroke_width(lv_vector_dsc_t * dsc, float width); + +/** + * Set stroke line dash pattern for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param dash_pattern an array of values that specify the segments of dash line + * @param dash_count the length of dash pattern array + */ +void lv_vector_dsc_set_stroke_dash(lv_vector_dsc_t * dsc, float * dash_pattern, uint16_t dash_count); + +/** + * Set stroke line cap style for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param cap the line cap to be set in lv_vector_stroke_cap_t format + */ +void lv_vector_dsc_set_stroke_cap(lv_vector_dsc_t * dsc, lv_vector_stroke_cap_t cap); + +/** + * Set stroke line join style for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param join the line join to be set in lv_vector_stroke_join_t format + */ +void lv_vector_dsc_set_stroke_join(lv_vector_dsc_t * dsc, lv_vector_stroke_join_t join); + +/** + * Set stroke miter limit for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param miter_limit the stroke miter_limit + */ +void lv_vector_dsc_set_stroke_miter_limit(lv_vector_dsc_t * dsc, uint16_t miter_limit); + +/** + * Set stroke linear gradient for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param grad pointer to a `lv_grad_dsc_t` variable + * @param spread the gradient spread to be set in lv_vector_gradient_spread_t format + */ +void lv_vector_dsc_set_stroke_linear_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, + lv_vector_gradient_spread_t spread); +/** + * Set stroke radial gradient for descriptor + * @param dsc pointer to a vector graphic descriptor + * @param grad pointer to a `lv_grad_dsc_t` variable + * @param cx the x for center of the circle + * @param cy the y for center of the circle + * @param radius the radius for circle + * @param spread the gradient spread to be set in lv_vector_gradient_spread_t format + */ +void lv_vector_dsc_set_stroke_radial_gradient(lv_vector_dsc_t * dsc, const lv_grad_dsc_t * grad, float cx, float cy, + float radius, lv_vector_gradient_spread_t spread); +/** + * Set a matrix to current stroke transformation matrix + * @param dsc pointer to a vector graphic descriptor + * @param matrix pointer to a matrix + */ +void lv_vector_dsc_set_stroke_transform(lv_vector_dsc_t * dsc, const lv_matrix_t * matrix); + +/** + * Set current transformation matrix to identity matrix + * @param dsc pointer to a vector graphic descriptor + */ +void lv_vector_dsc_identity(lv_vector_dsc_t * dsc); + +/** + * Change the scale factor of current transformation matrix + * @param dsc pointer to a vector graphic descriptor + * @param scale_x the scale factor for the X direction + * @param scale_y the scale factor for the Y direction + */ +void lv_vector_dsc_scale(lv_vector_dsc_t * dsc, float scale_x, float scale_y); + +/** + * Rotate current transformation matrix with origin + * @param dsc pointer to a vector graphic descriptor + * @param degree angle to rotate + */ +void lv_vector_dsc_rotate(lv_vector_dsc_t * dsc, float degree); + +/** + * Translate current transformation matrix to new position + * @param dsc pointer to a vector graphic descriptor + * @param tx the amount of translate in x direction + * @param tx the amount of translate in y direction + */ +void lv_vector_dsc_translate(lv_vector_dsc_t * dsc, float tx, float ty); + +/** + * Change the skew factor of current transformation matrix + * @param dsc pointer to a vector graphic descriptor + * @param skew_x the skew factor for x direction + * @param skew_y the skew factor for y direction + */ +void lv_vector_dsc_skew(lv_vector_dsc_t * dsc, float skew_x, float skew_y); + +/** + * Add a graphic path to the draw list + * @param dsc pointer to a vector graphic descriptor + * @param path pointer to a path + */ +void lv_vector_dsc_add_path(lv_vector_dsc_t * dsc, const lv_vector_path_t * path); + +/** + * Clear a rectangle area use current fill color + * @param dsc pointer to a vector graphic descriptor + * @param rect the area to clear in the buffer + */ +void lv_vector_clear_area(lv_vector_dsc_t * dsc, const lv_area_t * rect); + +/** + * Draw all the vector graphic paths + * @param dsc pointer to a vector graphic descriptor + */ +void lv_draw_vector(lv_vector_dsc_t * dsc); + +/* Traverser for task list */ +typedef void (*vector_draw_task_cb)(void * ctx, const lv_vector_path_t * path, const lv_vector_draw_dsc_t * dsc); + +void _lv_vector_for_each_destroy_tasks(lv_ll_t * task_list, vector_draw_task_cb cb, void * data); + +#endif /* LV_USE_VECTOR_GRAPHIC */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV_DRAW_VECTOR_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_image_buf.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_image_buf.c new file mode 100644 index 000000000..551c15db2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_image_buf.c @@ -0,0 +1,92 @@ +/** + * @file lv_image_buf.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include +#include +#include "lv_image_buf.h" +#include "lv_draw_image.h" +#include "../misc/lv_math.h" +#include "../misc/lv_log.h" +#include "../stdlib/lv_mem.h" +#include "../stdlib/lv_string.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_image_buf_set_palette(lv_image_dsc_t * dsc, uint8_t id, lv_color32_t c) +{ + if(dsc->header.cf < LV_COLOR_FORMAT_I1 || dsc->header.cf > LV_COLOR_FORMAT_I8) { + LV_LOG_WARN("Not indexed color format"); + return; + } + uint8_t * buf = (uint8_t *)dsc->data; + lv_memcpy(&buf[id * sizeof(c)], &c, sizeof(c)); +} + +void lv_image_buf_free(lv_image_dsc_t * dsc) +{ + if(dsc != NULL) { + if(dsc->data != NULL) + lv_free((void *)dsc->data); + + lv_free(dsc); + } +} + +void _lv_image_buf_get_transformed_area(lv_area_t * res, int32_t w, int32_t h, int32_t angle, uint16_t scale_x, + uint16_t scale_y, + const lv_point_t * pivot) +{ + if(angle == 0 && scale_x == LV_SCALE_NONE && scale_y == LV_SCALE_NONE) { + res->x1 = 0; + res->y1 = 0; + res->x2 = w - 1; + res->y2 = h - 1; + return; + } + + lv_point_t p[4] = { + {0, 0}, + {w, 0}, + {0, h}, + {w, h}, + }; + lv_point_transform(&p[0], angle, scale_x, scale_y, pivot, true); + lv_point_transform(&p[1], angle, scale_x, scale_y, pivot, true); + lv_point_transform(&p[2], angle, scale_x, scale_y, pivot, true); + lv_point_transform(&p[3], angle, scale_x, scale_y, pivot, true); + res->x1 = LV_MIN4(p[0].x, p[1].x, p[2].x, p[3].x); + res->x2 = LV_MAX4(p[0].x, p[1].x, p[2].x, p[3].x) - 1; + res->y1 = LV_MIN4(p[0].y, p[1].y, p[2].y, p[3].y); + res->y2 = LV_MAX4(p[0].y, p[1].y, p[2].y, p[3].y) - 1; +} + +/********************** + * STATIC FUNCTIONS + **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_image_buf.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_image_buf.h new file mode 100644 index 000000000..4c74ceef4 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_image_buf.h @@ -0,0 +1,195 @@ +/** + * @file lv_image_buf.h + * + */ + +#ifndef LV_IMAGE_BUF_H +#define LV_IMAGE_BUF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include "../misc/lv_color.h" +#include "../misc/lv_area.h" +#include "../stdlib/lv_string.h" + +/********************* + * DEFINES + *********************/ + +#define _LV_ZOOM_INV_UPSCALE 5 + +/** Magic number for lvgl image, 9 means lvgl version 9 + * It must not be a valid ASCII character nor larger than 0x80. See `lv_image_src_get_type`. + */ +#define LV_IMAGE_HEADER_MAGIC (0x19) + +/********************** + * TYPEDEFS + **********************/ + +typedef enum _lv_image_flags_t { + /** + * For RGB map of the image data, mark if it's pre-multiplied with alpha. + * For indexed image, this bit indicated palette data is pre-multiplied with alpha. + */ + LV_IMAGE_FLAGS_PREMULTIPLIED = (1 << 0), + + /** + * If the image data is malloced and can be processed in place. + * In image decoder post processing, this flag means we modify it in-place. + */ + LV_IMAGE_FLAGS_MODIFIABLE = (1 << 1), + + /** + * Indicating it's a vector image instead of default raster image. + * Some of the flags are not usable for vector image, like PREMULTIPLIED. + */ + LV_IMAGE_FLAGS_VECTORS = (1 << 2), + + /** + * The image data is compressed, so decoder needs to decode image firstly. + * If this flag is set, the whole image will be decompressed upon decode, and + * `get_area_cb` won't be necessary. + */ + LV_IMAGE_FLAGS_COMPRESSED = (1 << 3), + + /** + * The image is allocated from heap, thus should be freed after use. + */ + LV_IMAGE_FLAGS_ALLOCATED = (1 << 4), + + /** + * Flags reserved for user, lvgl won't use these bits. + */ + LV_IMAGE_FLAGS_USER1 = 0x1000, + LV_IMAGE_FLAGS_USER2 = 0x2000, + LV_IMAGE_FLAGS_USER3 = 0x4000, + LV_IMAGE_FLAGS_USER4 = 0x8000, + LV_IMAGE_FLAGS_USER5 = 0x0100, + LV_IMAGE_FLAGS_USER6 = 0x0200, + LV_IMAGE_FLAGS_USER7 = 0x0400, + LV_IMAGE_FLAGS_USER8 = 0x0800, +} lv_image_flags_t; + +typedef enum { + LV_IMAGE_COMPRESS_NONE = 0, + LV_IMAGE_COMPRESS_RLE, /*LVGL custom RLE compression*/ + LV_IMAGE_COMPRESS_LZ4, +} lv_image_compress_t; + +#if LV_BIG_ENDIAN_SYSTEM +typedef struct { + uint32_t reserved_2: 16; /*Reserved to be used later*/ + uint32_t stride: 16; /*Number of bytes in a row*/ + uint32_t h: 16; + uint32_t w: 16; + uint32_t flags: 16; /*Image flags, see `lv_image_flags_t`*/ + uint32_t cf : 8; /*Color format: See `lv_color_format_t`*/ + uint32_t magic: 8; /*Magic number. Must be LV_IMAGE_HEADER_MAGIC*/ +} lv_image_header_t; +#else +typedef struct { + uint32_t magic: 8; /*Magic number. Must be LV_IMAGE_HEADER_MAGIC*/ + uint32_t cf : 8; /*Color format: See `lv_color_format_t`*/ + uint32_t flags: 16; /*Image flags, see `lv_image_flags_t`*/ + + uint32_t w: 16; + uint32_t h: 16; + uint32_t stride: 16; /*Number of bytes in a row*/ + uint32_t reserved_2: 16; /*Reserved to be used later*/ +} lv_image_header_t; +#endif + +typedef struct { + void * buf; + uint32_t stride; /*Number of bytes in a row*/ +} lv_yuv_plane_t; + +typedef union { + lv_yuv_plane_t yuv; /*packed format*/ + struct { + lv_yuv_plane_t y; + lv_yuv_plane_t u; + lv_yuv_plane_t v; + } planar; /*planar format with 3 plane*/ + struct { + lv_yuv_plane_t y; + lv_yuv_plane_t uv; + } semi_planar; /*planar format with 2 plane*/ +} lv_yuv_buf_t; + +/** + * Struct to describe an image. Both decoded and raw image can share + * the same struct. + * + * Image is also identical to lv_draw_buf_t for now. + * Ideally, decoded image should be lv_draw_buf_t. + */ +typedef struct { + lv_image_header_t header; /**< A header describing the basics of the image*/ + uint32_t data_size; /**< Size of the image in bytes*/ + const uint8_t * data; /**< Pointer to the data of the image*/ +} lv_image_dsc_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Set the palette color of an indexed image. Valid only for `LV_COLOR_FORMAT_I1/2/4/8` + * @param dsc pointer to an image descriptor + * @param id the palette color to set: + * - for `LV_COLOR_FORMAT_I1`: 0..1 + * - for `LV_COLOR_FORMAT_I2`: 0..3 + * - for `LV_COLOR_FORMAT_I4`: 0..15 + * - for `LV_COLOR_FORMAT_I8`: 0..255 + * @param c the color to set in lv_color32_t format + */ +void lv_image_buf_set_palette(lv_image_dsc_t * dsc, uint8_t id, lv_color32_t c); + +/** + * Free an allocated image buffer + * @param dsc image buffer to free + */ +void lv_image_buf_free(lv_image_dsc_t * dsc); + +/** + * Get the area of a rectangle if its rotated and scaled + * @param res store the coordinates here + * @param w width of the rectangle to transform + * @param h height of the rectangle to transform + * @param angle angle of rotation + * @param scale_x zoom in x direction, (256 no zoom) + * @param scale_y zoom in y direction, (256 no zoom) + * @param pivot x,y pivot coordinates of rotation + */ +void _lv_image_buf_get_transformed_area(lv_area_t * res, int32_t w, int32_t h, int32_t angle, uint16_t scale_x, + uint16_t scale_y, + const lv_point_t * pivot); + +static inline void lv_image_header_init(lv_image_header_t * header, uint32_t w, uint32_t h, lv_color_format_t cf, + uint32_t stride, lv_image_flags_t flags) +{ + LV_ASSERT(header); + lv_memzero(header, sizeof(*header)); + header->w = w; + header->h = h; + header->cf = cf; + header->stride = stride; + header->flags = flags; +} +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_IMAGE_BUF_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_image_decoder.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_image_decoder.c new file mode 100644 index 000000000..204edf994 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_image_decoder.c @@ -0,0 +1,451 @@ +/** + * @file lv_image_decoder.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_image_decoder.h" +#include "../misc/lv_assert.h" +#include "../draw/lv_draw_image.h" +#include "../misc/lv_ll.h" +#include "../stdlib/lv_string.h" +#include "../core/lv_global.h" + +/********************* + * DEFINES + *********************/ +#define img_decoder_ll_p &(LV_GLOBAL_DEFAULT()->img_decoder_ll) +#define img_cache_p (LV_GLOBAL_DEFAULT()->img_cache) +#define img_header_cache_p (LV_GLOBAL_DEFAULT()->img_header_cache) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static uint32_t img_width_to_stride(lv_image_header_t * header); + +/** + * Get the header info of an image source, and return the a pointer to the decoder that can open it. + * @param src The image source (e.g. a filename or a pointer to a C array) + * @param header The header of the image + * @return The decoder that can open the image source or NULL if not found (or can't open it). + */ +static lv_image_decoder_t * image_decoder_get_info(const void * src, lv_image_header_t * header); + +#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 +static lv_cache_compare_res_t image_decoder_header_cache_compare_cb(const lv_image_header_cache_data_t * lhs, + const lv_image_header_cache_data_t * rhs); +static void image_decoder_header_cache_free_cb(lv_image_header_cache_data_t * entry, void * user_data); +#endif + +#if LV_CACHE_DEF_SIZE > 0 +static lv_cache_compare_res_t image_decoder_cache_compare_cb(const lv_image_cache_data_t * lhs, + const lv_image_cache_data_t * rhs); +static void image_decoder_cache_free_cb(lv_image_cache_data_t * entry, void * user_data); + +static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc); +#endif +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Initialize the image decoder module + */ +void _lv_image_decoder_init(void) +{ + _lv_ll_init(img_decoder_ll_p, sizeof(lv_image_decoder_t)); + +#if LV_CACHE_DEF_SIZE > 0 + img_cache_p = lv_cache_create(&lv_cache_class_lru_rb_size, + sizeof(lv_image_cache_data_t), LV_CACHE_DEF_SIZE, (lv_cache_ops_t) { + .compare_cb = (lv_cache_compare_cb_t)image_decoder_cache_compare_cb, + .create_cb = NULL, + .free_cb = (lv_cache_free_cb_t)image_decoder_cache_free_cb, + }); + +#endif + +#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 + img_header_cache_p = lv_cache_create(&lv_cache_class_lru_rb_count, + sizeof(lv_image_header_cache_data_t), LV_IMAGE_HEADER_CACHE_DEF_CNT, (lv_cache_ops_t) { + .compare_cb = (lv_cache_compare_cb_t)image_decoder_header_cache_compare_cb, + .create_cb = NULL, + .free_cb = (lv_cache_free_cb_t)image_decoder_header_cache_free_cb + }); +#endif +} + +/** + * Deinitialize the image decoder module + */ +void _lv_image_decoder_deinit(void) +{ +#if LV_CACHE_DEF_SIZE > 0 + lv_cache_destroy(img_cache_p, NULL); +#endif + +#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 + lv_cache_destroy(img_header_cache_p, NULL); +#endif + _lv_ll_clear(img_decoder_ll_p); +} + +lv_result_t lv_image_decoder_get_info(const void * src, lv_image_header_t * header) +{ + lv_image_decoder_t * decoder = image_decoder_get_info(src, header); + if(decoder == NULL) return LV_RESULT_INVALID; + + return LV_RESULT_OK; +} + +lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src, const lv_image_decoder_args_t * args) +{ + lv_memzero(dsc, sizeof(lv_image_decoder_dsc_t)); + + if(src == NULL) return LV_RESULT_INVALID; + dsc->src = src; + dsc->src_type = lv_image_src_get_type(src); + +#if LV_CACHE_DEF_SIZE > 0 + dsc->cache = img_cache_p; + /* + * Check the cache first + * If the image is found in the cache, just return it.*/ + if(try_cache(dsc) == LV_RESULT_OK) return LV_RESULT_OK; +#endif + + /*Find the decoder that can open the image source, and get the header info in the same time.*/ + dsc->decoder = image_decoder_get_info(src, &dsc->header); + if(dsc->decoder == NULL) return LV_RESULT_INVALID; + + /*Duplicate the source if it's a file*/ + if(dsc->src_type == LV_IMAGE_SRC_FILE) dsc->src = lv_strdup(dsc->src); + + /*Make a copy of args*/ + dsc->args = args ? *args : (lv_image_decoder_args_t) { + .stride_align = LV_DRAW_BUF_STRIDE_ALIGN != 1, + .premultiply = false, + .no_cache = false, + .use_indexed = false, + }; + + /* + * We assume that if a decoder can get the info, it can open the image. + * If decoder open failed, free the source and return error. + * If decoder open succeed, add the image to cache if enabled. + * */ + lv_result_t res = dsc->decoder->open_cb(dsc->decoder, dsc); + + return res; +} + +lv_result_t lv_image_decoder_get_area(lv_image_decoder_dsc_t * dsc, const lv_area_t * full_area, + lv_area_t * decoded_area) +{ + lv_result_t res = LV_RESULT_INVALID; + if(dsc->decoder->get_area_cb) res = dsc->decoder->get_area_cb(dsc->decoder, dsc, full_area, decoded_area); + + return res; +} + +void lv_image_decoder_close(lv_image_decoder_dsc_t * dsc) +{ + if(dsc->decoder) { + if(dsc->decoder->close_cb) dsc->decoder->close_cb(dsc->decoder, dsc); + + if(dsc->src_type == LV_IMAGE_SRC_FILE) { + lv_free((void *)dsc->src); + dsc->src = NULL; + } + } +} + +/** + * Create a new image decoder + * @return pointer to the new image decoder + */ +lv_image_decoder_t * lv_image_decoder_create(void) +{ + lv_image_decoder_t * decoder; + decoder = _lv_ll_ins_head(img_decoder_ll_p); + LV_ASSERT_MALLOC(decoder); + if(decoder == NULL) return NULL; + + lv_memzero(decoder, sizeof(lv_image_decoder_t)); + + return decoder; +} + +void lv_image_decoder_delete(lv_image_decoder_t * decoder) +{ + _lv_ll_remove(img_decoder_ll_p, decoder); + lv_free(decoder); +} + +lv_image_decoder_t * lv_image_decoder_get_next(lv_image_decoder_t * decoder) +{ + if(decoder == NULL) + return _lv_ll_get_head(img_decoder_ll_p); + else + return _lv_ll_get_next(img_decoder_ll_p, decoder); +} + +void lv_image_decoder_set_info_cb(lv_image_decoder_t * decoder, lv_image_decoder_info_f_t info_cb) +{ + decoder->info_cb = info_cb; +} + +void lv_image_decoder_set_open_cb(lv_image_decoder_t * decoder, lv_image_decoder_open_f_t open_cb) +{ + decoder->open_cb = open_cb; +} + +void lv_image_decoder_set_get_area_cb(lv_image_decoder_t * decoder, lv_image_decoder_get_area_cb_t get_area_cb) +{ + decoder->get_area_cb = get_area_cb; +} + +void lv_image_decoder_set_close_cb(lv_image_decoder_t * decoder, lv_image_decoder_close_f_t close_cb) +{ + decoder->close_cb = close_cb; +} + +void lv_image_decoder_set_cache_free_cb(lv_image_decoder_t * decoder, lv_cache_free_cb_t cache_free_cb) +{ + decoder->cache_free_cb = cache_free_cb; +} + +#if LV_CACHE_DEF_SIZE > 0 +lv_cache_entry_t * lv_image_decoder_add_to_cache(lv_image_decoder_t * decoder, + lv_image_cache_data_t * search_key, + const lv_draw_buf_t * decoded, void * user_data) +{ + lv_cache_entry_t * cache_entry = lv_cache_add(img_cache_p, search_key, NULL); + if(cache_entry == NULL) { + return NULL; + } + + lv_image_cache_data_t * cached_data; + cached_data = lv_cache_entry_get_data(cache_entry); + + /*Set the cache entry to decoder data*/ + cached_data->decoded = decoded; + if(cached_data->src_type == LV_IMAGE_SRC_FILE) { + cached_data->src = lv_strdup(cached_data->src); + } + cached_data->user_data = user_data; /*Need to free data on cache invalidate instead of decoder_close*/ + cached_data->decoder = decoder; + + return cache_entry; +} +#endif + +lv_draw_buf_t * lv_image_decoder_post_process(lv_image_decoder_dsc_t * dsc, lv_draw_buf_t * decoded) +{ + if(decoded == NULL) return NULL; /*No need to adjust*/ + + lv_image_decoder_args_t * args = &dsc->args; + if(args->stride_align && decoded->header.cf != LV_COLOR_FORMAT_RGB565A8) { + uint32_t stride_expect = lv_draw_buf_width_to_stride(decoded->header.w, decoded->header.cf); + if(decoded->header.stride != stride_expect) { + LV_LOG_TRACE("Stride mismatch"); + lv_draw_buf_t * aligned = lv_draw_buf_adjust_stride(decoded, stride_expect); + if(aligned == NULL) { + LV_LOG_ERROR("No memory for Stride adjust."); + return NULL; + } + + decoded = aligned; + } + } + + /*Premultiply alpha channel*/ + if(args->premultiply + && !LV_COLOR_FORMAT_IS_ALPHA_ONLY(decoded->header.cf) + && lv_color_format_has_alpha(decoded->header.cf) + && !lv_draw_buf_has_flag(decoded, LV_IMAGE_FLAGS_PREMULTIPLIED) /*Hasn't done yet*/ + ) { + LV_LOG_TRACE("Alpha premultiply."); + if(lv_draw_buf_has_flag(decoded, LV_IMAGE_FLAGS_MODIFIABLE)) { + /*Do it directly*/ + lv_draw_buf_premultiply(decoded); + } + else { + decoded = lv_draw_buf_dup(decoded); + if(decoded == NULL) { + LV_LOG_ERROR("No memory for premulitplying."); + return NULL; + } + + lv_draw_buf_premultiply(decoded); + } + } + + return decoded; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static lv_image_decoder_t * image_decoder_get_info(const void * src, lv_image_header_t * header) +{ + lv_memzero(header, sizeof(lv_image_header_t)); + + if(src == NULL) return NULL; + + lv_image_src_t src_type = lv_image_src_get_type(src); + if(src_type == LV_IMAGE_SRC_VARIABLE) { + const lv_image_dsc_t * img_dsc = src; + if(img_dsc->data == NULL) return NULL; + } + + lv_image_decoder_t * decoder; + +#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 + lv_image_header_cache_data_t search_key; + search_key.src_type = src_type; + search_key.src = src; + + lv_cache_entry_t * entry = lv_cache_acquire(img_header_cache_p, &search_key, NULL); + + if(entry) { + lv_image_header_cache_data_t * cached_data = lv_cache_entry_get_data(entry); + *header = cached_data->header; + decoder = cached_data->decoder; + lv_cache_release(img_header_cache_p, entry, NULL); + return decoder; + } +#endif + + _LV_LL_READ(img_decoder_ll_p, decoder) { + /*Info and Open callbacks are required*/ + if(decoder->info_cb && decoder->open_cb) { + lv_result_t res = decoder->info_cb(decoder, src, header); + if(res == LV_RESULT_OK) { + if(header->stride == 0) header->stride = img_width_to_stride(header); + break; + } + } + } + +#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 + if(decoder) { + if(src_type == LV_IMAGE_SRC_FILE) search_key.src = lv_strdup(src); + search_key.decoder = decoder; + search_key.header = *header; + entry = lv_cache_add(img_header_cache_p, &search_key, NULL); + + if(entry == NULL) { + if(src_type == LV_IMAGE_SRC_FILE) lv_free((void *)search_key.src); + return NULL; + } + + lv_cache_release(img_header_cache_p, entry, NULL); + } +#endif + + return decoder; +} + +static uint32_t img_width_to_stride(lv_image_header_t * header) +{ + if(header->cf == LV_COLOR_FORMAT_RGB565A8) { + return header->w * 2; + } + else { + return ((uint32_t)header->w * lv_color_format_get_bpp(header->cf) + 7) >> 3; + } +} + +#if LV_CACHE_DEF_SIZE > 0 || LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 +inline static lv_cache_compare_res_t image_decoder_common_compare(const void * lhs_src, lv_image_src_t lhs_src_type, + const void * rhs_src, lv_image_src_t rhs_src_type) +{ + if(lhs_src_type == rhs_src_type) { + if(lhs_src_type == LV_IMAGE_SRC_FILE) { + int32_t cmp_res = lv_strcmp(lhs_src, rhs_src); + if(cmp_res != 0) { + return cmp_res > 0 ? 1 : -1; + } + } + else if(lhs_src_type == LV_IMAGE_SRC_VARIABLE) { + if(lhs_src != rhs_src) { + return lhs_src > rhs_src ? 1 : -1; + } + } + return 0; + } + return lhs_src_type > rhs_src_type ? 1 : -1; +} +#endif + +#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 +static lv_cache_compare_res_t image_decoder_header_cache_compare_cb( + const lv_image_header_cache_data_t * lhs, + const lv_image_header_cache_data_t * rhs) +{ + return image_decoder_common_compare(lhs->src, lhs->src_type, rhs->src, rhs->src_type); +} + +static void image_decoder_header_cache_free_cb(lv_image_header_cache_data_t * entry, void * user_data) +{ + LV_UNUSED(user_data); /*Unused*/ + + if(entry->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)entry->src); +} +#endif + +#if LV_CACHE_DEF_SIZE > 0 +static lv_cache_compare_res_t image_decoder_cache_compare_cb( + const lv_image_cache_data_t * lhs, + const lv_image_cache_data_t * rhs) +{ + return image_decoder_common_compare(lhs->src, lhs->src_type, rhs->src, rhs->src_type); +} + +static void image_decoder_cache_free_cb(lv_image_cache_data_t * entry, void * user_data) +{ + LV_UNUSED(user_data); /*Unused*/ + + const lv_image_decoder_t * decoder = entry->decoder; + if(decoder && decoder->cache_free_cb) { + decoder->cache_free_cb(entry, user_data); + } +} + +static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc) +{ + lv_cache_t * cache = dsc->cache; + + lv_image_cache_data_t search_key; + search_key.src_type = dsc->src_type; + search_key.src = dsc->src; + + lv_cache_entry_t * entry = lv_cache_acquire(cache, &search_key, NULL); + + if(entry) { + lv_image_cache_data_t * cached_data = lv_cache_entry_get_data(entry); + dsc->decoded = cached_data->decoded; + dsc->cache_entry = entry; /*Save the cache to release it in decoder_close*/ + return LV_RESULT_OK; + } + + return LV_RESULT_INVALID; +} +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_image_decoder.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_image_decoder.h new file mode 100644 index 000000000..2979f08fc --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/lv_image_decoder.h @@ -0,0 +1,306 @@ +/** + * @file lv_image_decoder.h + * + */ + +#ifndef LV_IMAGE_DECODER_H +#define LV_IMAGE_DECODER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include +#include "lv_draw_buf.h" +#include "../misc/lv_fs.h" +#include "../misc/lv_types.h" +#include "../misc/lv_area.h" +#include "../misc/cache/lv_cache.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** + * Source of image.*/ +enum _lv_image_src_t { + LV_IMAGE_SRC_VARIABLE, /** Binary/C variable*/ + LV_IMAGE_SRC_FILE, /** File in filesystem*/ + LV_IMAGE_SRC_SYMBOL, /** Symbol (@ref lv_symbol_def.h)*/ + LV_IMAGE_SRC_UNKNOWN, /** Unknown source*/ +}; + +#ifdef DOXYGEN +typedef _lv_image_src_t lv_image_src_t; +#else +typedef uint8_t lv_image_src_t; +#endif /*DOXYGEN*/ + +/*Decoder function definitions*/ +struct _lv_image_decoder_dsc_t; +typedef struct _lv_image_decoder_dsc_t lv_image_decoder_dsc_t; + +/** + * Image decoder args. + * It determines how to decoder an image, e.g. whether to premultiply the alpha or not. + * It should be passed to lv_img_decoder_open() function. If NULL is provided, default + * args are used. + * + * Default args: + * all field are zero or false. + */ +typedef struct _lv_image_decoder_args_t { + bool stride_align; /*Whether stride should be aligned*/ + bool premultiply; /*Whether image should be premultiplied or not after decoding*/ + bool no_cache; /*Whether this image should be kept out of cache*/ + bool use_indexed; /*Decoded indexed image as is. Convert to ARGB8888 if false.*/ +} lv_image_decoder_args_t; + +/** + * Get info from an image and store in the `header` + * @param src the image source. Can be a pointer to a C array or a file name (Use + * `lv_image_src_get_type` to determine the type) + * @param header store the info here + * @return LV_RESULT_OK: info written correctly; LV_RESULT_INVALID: failed + */ +typedef lv_result_t (*lv_image_decoder_info_f_t)(lv_image_decoder_t * decoder, const void * src, + lv_image_header_t * header); + +/** + * Open an image for decoding. Prepare it as it is required to read it later + * @param decoder pointer to the decoder the function associated with + * @param dsc pointer to decoder descriptor. `src`, `color` are already initialized in it. + */ +typedef lv_result_t (*lv_image_decoder_open_f_t)(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); + +/** + * Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`. + * Required only if the "open" function can't return with the whole decoded pixel array. + * @param decoder pointer to the decoder the function associated with + * @param dsc pointer to decoder descriptor + * @param x start x coordinate + * @param y start y coordinate + * @param len number of pixels to decode + * @param buf a buffer to store the decoded pixels + * @return LV_RESULT_OK: ok; LV_RESULT_INVALID: failed + */ +typedef lv_result_t (*lv_image_decoder_get_area_cb_t)(lv_image_decoder_t * decoder, + lv_image_decoder_dsc_t * dsc, + const lv_area_t * full_area, lv_area_t * decoded_area); + +/** + * Close the pending decoding. Free resources etc. + * @param decoder pointer to the decoder the function associated with + * @param dsc pointer to decoder descriptor + */ +typedef void (*lv_image_decoder_close_f_t)(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); + +struct _lv_image_decoder_t { + lv_image_decoder_info_f_t info_cb; + lv_image_decoder_open_f_t open_cb; + lv_image_decoder_get_area_cb_t get_area_cb; + lv_image_decoder_close_f_t close_cb; + + lv_cache_free_cb_t cache_free_cb; + void * user_data; +}; + +typedef struct _lv_image_decoder_cache_data_t { + lv_cache_slot_size_t slot; + + const void * src; + lv_image_src_t src_type; + + const lv_draw_buf_t * decoded; + const lv_image_decoder_t * decoder; + void * user_data; +} lv_image_cache_data_t; + +typedef struct _lv_image_decoder_header_cache_data_t { + const void * src; + lv_image_src_t src_type; + + lv_image_header_t header; + lv_image_decoder_t * decoder; +} lv_image_header_cache_data_t; + +/**Describe an image decoding session. Stores data about the decoding*/ +struct _lv_image_decoder_dsc_t { + /**The decoder which was able to open the image source*/ + lv_image_decoder_t * decoder; + + /*A copy of parameters of how this image is decoded*/ + lv_image_decoder_args_t args; + + /**The image source. A file path like "S:my_img.png" or pointer to an `lv_image_dsc_t` variable*/ + const void * src; + + /**Type of the source: file or variable. Can be set in `open` function if required*/ + lv_image_src_t src_type; + + /**Info about the opened image: color format, size, etc. MUST be set in `open` function*/ + lv_image_header_t header; + + /** Pointer to a draw buffer where the image's data (pixels) are stored in a decoded, plain format. + * MUST be set in `open` or `get_area_cb`function*/ + const lv_draw_buf_t * decoded; /*A draw buffer to described decoded image.*/ + + const lv_color32_t * palette; + uint32_t palette_size; + + /** How much time did it take to open the image. [ms] + * If not set `lv_image_cache` will measure and set the time to open*/ + uint32_t time_to_open; + + /**A text to display instead of the image when the image can't be opened. + * Can be set in `open` function or set NULL.*/ + const char * error_msg; + + lv_cache_t * cache; + + /**Point to cache entry information*/ + lv_cache_entry_t * cache_entry; + + /**Store any custom data here is required*/ + void * user_data; +}; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the image decoder module + */ +void _lv_image_decoder_init(void); + +/** + * Deinitialize the image decoder module + */ +void _lv_image_decoder_deinit(void); + +/** + * Get information about an image. + * Try the created image decoder one by one. Once one is able to get info that info will be used. + * @param src the image source. Can be + * 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_drv_register()`) + * 2) Variable: Pointer to an `lv_image_dsc_t` variable + * 3) Symbol: E.g. `LV_SYMBOL_OK` + * @param header the image info will be stored here + * @return LV_RESULT_OK: success; LV_RESULT_INVALID: wasn't able to get info about the image + */ +lv_result_t lv_image_decoder_get_info(const void * src, lv_image_header_t * header); + +/** + * Open an image. + * Try the created image decoders one by one. Once one is able to open the image that decoder is saved in `dsc` + * @param dsc describes a decoding session. Simply a pointer to an `lv_image_decoder_dsc_t` variable. + * @param src the image source. Can be + * 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_drv_register())`) + * 2) Variable: Pointer to an `lv_image_dsc_t` variable + * 3) Symbol: E.g. `LV_SYMBOL_OK` + * @param color The color of the image with `LV_COLOR_FORMAT_ALPHA_...` + * @param args args about how the image should be opened. + * @return LV_RESULT_OK: opened the image. `dsc->decoded` and `dsc->header` are set. + * LV_RESULT_INVALID: none of the registered image decoders were able to open the image. + */ +lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src, const lv_image_decoder_args_t * args); + +/** + * Decode an area of the opened image + * @param dsc image decoder descriptor + * @param full_area start X coordinate (from left) + * @param decoded_area start Y coordinate (from top) + * @return LV_RESULT_OK: success; LV_RESULT_INVALID: an error occurred + */ +lv_result_t lv_image_decoder_get_area(lv_image_decoder_dsc_t * dsc, const lv_area_t * full_area, + lv_area_t * decoded_area); + +/** + * Close a decoding session + * @param dsc pointer to `lv_image_decoder_dsc_t` used in `lv_image_decoder_open` + */ +void lv_image_decoder_close(lv_image_decoder_dsc_t * dsc); + +/** + * Create a new image decoder + * @return pointer to the new image decoder + */ +lv_image_decoder_t * lv_image_decoder_create(void); + +/** + * Delete an image decoder + * @param decoder pointer to an image decoder + */ +void lv_image_decoder_delete(lv_image_decoder_t * decoder); + +/** + * Get the next image decoder in the linked list of image decoders + * @param decoder pointer to an image decoder or NULL to get the first one + * @return the next image decoder or NULL if no more image decoder exists + */ +lv_image_decoder_t * lv_image_decoder_get_next(lv_image_decoder_t * decoder); + +/** + * Set a callback to get information about the image + * @param decoder pointer to an image decoder + * @param info_cb a function to collect info about an image (fill an `lv_image_header_t` struct) + */ +void lv_image_decoder_set_info_cb(lv_image_decoder_t * decoder, lv_image_decoder_info_f_t info_cb); + +/** + * Set a callback to open an image + * @param decoder pointer to an image decoder + * @param open_cb a function to open an image + */ +void lv_image_decoder_set_open_cb(lv_image_decoder_t * decoder, lv_image_decoder_open_f_t open_cb); + +/** + * Set a callback to a decoded line of an image + * @param decoder pointer to an image decoder + * @param read_line_cb a function to read a line of an image + */ +void lv_image_decoder_set_get_area_cb(lv_image_decoder_t * decoder, lv_image_decoder_get_area_cb_t read_line_cb); + +/** + * Set a callback to close a decoding session. E.g. close files and free other resources. + * @param decoder pointer to an image decoder + * @param close_cb a function to close a decoding session + */ +void lv_image_decoder_set_close_cb(lv_image_decoder_t * decoder, lv_image_decoder_close_f_t close_cb); + +void lv_image_decoder_set_cache_free_cb(lv_image_decoder_t * decoder, lv_cache_free_cb_t cache_free_cb); + +#if LV_CACHE_DEF_SIZE > 0 +lv_cache_entry_t * lv_image_decoder_add_to_cache(lv_image_decoder_t * decoder, + lv_image_cache_data_t * search_key, + const lv_draw_buf_t * decoded, void * user_data); +#endif + +/** + * Check the decoded image, make any modification if decoder `args` requires. + * @note A new draw buf will be allocated if provided `decoded` is not modifiable or stride mismatch etc. + * @param dsc pointer to a decoder descriptor + * @param decoded pointer to a decoded image to post process to meet dsc->args requirement. + * @return post processed draw buffer, when it differs with `decoded`, it's newly allocated. + */ +lv_draw_buf_t * lv_image_decoder_post_process(lv_image_decoder_dsc_t * dsc, lv_draw_buf_t * decoded); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_IMAGE_DECODER_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.c deleted file mode 100644 index 5ac1eadf5..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.c +++ /dev/null @@ -1,392 +0,0 @@ -/** - * @file lv_img_buf.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include -#include -#include "lv_img_buf.h" -#include "lv_draw_img.h" -#include "../misc/lv_math.h" -#include "../misc/lv_log.h" -#include "../misc/lv_mem.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_color_t lv_img_buf_get_px_color(const lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color) -{ - lv_color_t p_color = lv_color_black(); - uint8_t * buf_u8 = (uint8_t *)dsc->data; - - if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED || - dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA || dsc->header.cf == LV_IMG_CF_RGB565A8) { - uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3; - uint32_t px = dsc->header.w * y * px_size + x * px_size; - lv_memcpy_small(&p_color, &buf_u8[px], sizeof(lv_color_t)); -#if LV_COLOR_SIZE == 32 - p_color.ch.alpha = 0xFF; /*Only the color should be get so use a default alpha value*/ -#endif - } - else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) { - buf_u8 += 4 * 2; - uint8_t bit = x & 0x7; - x = x >> 3; - - /*Get the current pixel. - *dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned - *so the possible real width are 8, 16, 24 ...*/ - uint32_t px = ((dsc->header.w + 7) >> 3) * y + x; - p_color.full = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit); - } - else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) { - buf_u8 += 4 * 4; - uint8_t bit = (x & 0x3) * 2; - x = x >> 2; - - /*Get the current pixel. - *dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned - *so the possible real width are 4, 8, 12 ...*/ - uint32_t px = ((dsc->header.w + 3) >> 2) * y + x; - p_color.full = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit); - } - else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) { - buf_u8 += 4 * 16; - uint8_t bit = (x & 0x1) * 4; - x = x >> 1; - - /*Get the current pixel. - *dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned - *so the possible real width are 2, 4, 6 ...*/ - uint32_t px = ((dsc->header.w + 1) >> 1) * y + x; - p_color.full = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit); - } - else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) { - buf_u8 += 4 * 256; - uint32_t px = dsc->header.w * y + x; - p_color.full = buf_u8[px]; - } - else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT || - dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) { - p_color = color; - } - return p_color; -} - -lv_opa_t lv_img_buf_get_px_alpha(const lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y) -{ - uint8_t * buf_u8 = (uint8_t *)dsc->data; - - if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { - uint32_t px = dsc->header.w * y * LV_IMG_PX_SIZE_ALPHA_BYTE + x * LV_IMG_PX_SIZE_ALPHA_BYTE; - return buf_u8[px + LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; - } - else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) { - uint8_t bit = x & 0x7; - x = x >> 3; - - /*Get the current pixel. - *dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned - *so the possible real width are 8 ,16, 24 ...*/ - uint32_t px = ((dsc->header.w + 7) >> 3) * y + x; - uint8_t px_opa = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit); - return px_opa ? LV_OPA_TRANSP : LV_OPA_COVER; - } - else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) { - const uint8_t opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/ - - uint8_t bit = (x & 0x3) * 2; - x = x >> 2; - - /*Get the current pixel. - *dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned - *so the possible real width are 4 ,8, 12 ...*/ - uint32_t px = ((dsc->header.w + 3) >> 2) * y + x; - uint8_t px_opa = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit); - return opa_table[px_opa]; - } - else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) { - const uint8_t opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/ - 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255 - }; - - uint8_t bit = (x & 0x1) * 4; - x = x >> 1; - - /*Get the current pixel. - *dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned - *so the possible real width are 2 ,4, 6 ...*/ - uint32_t px = ((dsc->header.w + 1) >> 1) * y + x; - uint8_t px_opa = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit); - return opa_table[px_opa]; - } - else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) { - uint32_t px = dsc->header.w * y + x; - return buf_u8[px]; - } - - return LV_OPA_COVER; -} - -void lv_img_buf_set_px_alpha(const lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa) -{ - uint8_t * buf_u8 = (uint8_t *)dsc->data; - - if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { - uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3; - uint32_t px = dsc->header.w * y * px_size + x * px_size; - buf_u8[px + px_size - 1] = opa; - } - else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) { - opa = opa >> 7; /*opa -> [0,1]*/ - uint8_t bit = x & 0x7; - x = x >> 3; - - /*Get the current pixel. - *dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned - *so the possible real width are 8 ,16, 24 ...*/ - uint32_t px = ((dsc->header.w + 7) >> 3) * y + x; - buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit)); - buf_u8[px] = buf_u8[px] | ((opa & 0x1) << (7 - bit)); - } - else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) { - opa = opa >> 6; /*opa -> [0,3]*/ - uint8_t bit = (x & 0x3) * 2; - x = x >> 2; - - /*Get the current pixel. - *dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned - *so the possible real width are 4 ,8, 12 ...*/ - uint32_t px = ((dsc->header.w + 3) >> 2) * y + x; - buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit)); - buf_u8[px] = buf_u8[px] | ((opa & 0x3) << (6 - bit)); - } - else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) { - opa = opa >> 4; /*opa -> [0,15]*/ - uint8_t bit = (x & 0x1) * 4; - x = x >> 1; - - /*Get the current pixel. - *dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned - *so the possible real width are 2 ,4, 6 ...*/ - uint32_t px = ((dsc->header.w + 1) >> 1) * y + x; - buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit)); - buf_u8[px] = buf_u8[px] | ((opa & 0xF) << (4 - bit)); - } - else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) { - uint32_t px = dsc->header.w * y + x; - buf_u8[px] = opa; - } -} - -void lv_img_buf_set_px_color(const lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c) -{ - uint8_t * buf_u8 = (uint8_t *)dsc->data; - - if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { - uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3; - uint32_t px = dsc->header.w * y * px_size + x * px_size; - lv_memcpy_small(&buf_u8[px], &c, px_size); - } - else if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { - uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3; - uint32_t px = dsc->header.w * y * px_size + x * px_size; - lv_memcpy_small(&buf_u8[px], &c, px_size - 1); /*-1 to not overwrite the alpha value*/ - } - else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) { - buf_u8 += sizeof(lv_color32_t) * 2; /*Skip the palette*/ - - uint8_t bit = x & 0x7; - x = x >> 3; - - /*Get the current pixel. - *dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned - *so the possible real width are 8 ,16, 24 ...*/ - uint32_t px = ((dsc->header.w + 7) >> 3) * y + x; - buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit)); - buf_u8[px] = buf_u8[px] | ((c.full & 0x1) << (7 - bit)); - } - else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) { - buf_u8 += sizeof(lv_color32_t) * 4; /*Skip the palette*/ - uint8_t bit = (x & 0x3) * 2; - x = x >> 2; - - /*Get the current pixel. - *dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned - *so the possible real width are 4, 8 ,12 ...*/ - uint32_t px = ((dsc->header.w + 3) >> 2) * y + x; - - buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit)); - buf_u8[px] = buf_u8[px] | ((c.full & 0x3) << (6 - bit)); - } - else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) { - buf_u8 += sizeof(lv_color32_t) * 16; /*Skip the palette*/ - uint8_t bit = (x & 0x1) * 4; - x = x >> 1; - - /*Get the current pixel. - *dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned - *so the possible real width are 2 ,4, 6 ...*/ - uint32_t px = ((dsc->header.w + 1) >> 1) * y + x; - buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit)); - buf_u8[px] = buf_u8[px] | ((c.full & 0xF) << (4 - bit)); - } - else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) { - buf_u8 += sizeof(lv_color32_t) * 256; /*Skip the palette*/ - uint32_t px = dsc->header.w * y + x; - buf_u8[px] = c.full; - } -} - -void lv_img_buf_set_palette(const lv_img_dsc_t * dsc, uint8_t id, lv_color_t c) -{ - if((dsc->header.cf == LV_IMG_CF_ALPHA_1BIT && id > 1) || (dsc->header.cf == LV_IMG_CF_ALPHA_2BIT && id > 3) || - (dsc->header.cf == LV_IMG_CF_ALPHA_4BIT && id > 15) || (dsc->header.cf == LV_IMG_CF_ALPHA_8BIT)) { - LV_LOG_WARN("lv_img_buf_set_px_alpha: invalid 'id'"); - return; - } - - lv_color32_t c32; - c32.full = lv_color_to32(c); - uint8_t * buf = (uint8_t *)dsc->data; - lv_memcpy_small(&buf[id * sizeof(c32)], &c32, sizeof(c32)); -} - -lv_img_dsc_t * lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf) -{ - /*Allocate image descriptor*/ - lv_img_dsc_t * dsc = lv_mem_alloc(sizeof(lv_img_dsc_t)); - if(dsc == NULL) - return NULL; - - lv_memset_00(dsc, sizeof(lv_img_dsc_t)); - - /*Get image data size*/ - dsc->data_size = lv_img_buf_get_img_size(w, h, cf); - if(dsc->data_size == 0) { - lv_mem_free(dsc); - return NULL; - } - - /*Allocate raw buffer*/ - dsc->data = lv_mem_alloc(dsc->data_size); - if(dsc->data == NULL) { - lv_mem_free(dsc); - return NULL; - } - lv_memset_00((uint8_t *)dsc->data, dsc->data_size); - - /*Fill in header*/ - dsc->header.always_zero = 0; - dsc->header.w = w; - dsc->header.h = h; - dsc->header.cf = cf; - return dsc; -} - -void lv_img_buf_free(lv_img_dsc_t * dsc) -{ - if(dsc != NULL) { - if(dsc->data != NULL) - lv_mem_free((void *)dsc->data); - - lv_mem_free(dsc); - } -} - -uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf) -{ - switch(cf) { - case LV_IMG_CF_TRUE_COLOR: - return LV_IMG_BUF_SIZE_TRUE_COLOR(w, h); - case LV_IMG_CF_TRUE_COLOR_ALPHA: - case LV_IMG_CF_RGB565A8: - return LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h); - case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED: - return LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h); - case LV_IMG_CF_ALPHA_1BIT: - return LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h); - case LV_IMG_CF_ALPHA_2BIT: - return LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h); - case LV_IMG_CF_ALPHA_4BIT: - return LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h); - case LV_IMG_CF_ALPHA_8BIT: - return LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h); - case LV_IMG_CF_INDEXED_1BIT: - return LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h); - case LV_IMG_CF_INDEXED_2BIT: - return LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h); - case LV_IMG_CF_INDEXED_4BIT: - return LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h); - case LV_IMG_CF_INDEXED_8BIT: - return LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h); - default: - return 0; - } -} - -void _lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t h, int16_t angle, uint16_t zoom, - const lv_point_t * pivot) -{ -#if LV_DRAW_COMPLEX - if(angle == 0 && zoom == LV_IMG_ZOOM_NONE) { - res->x1 = 0; - res->y1 = 0; - res->x2 = w - 1; - res->y2 = h - 1; - return; - } - - lv_point_t p[4] = { - {0, 0}, - {w, 0}, - {0, h}, - {w, h}, - }; - lv_point_transform(&p[0], angle, zoom, pivot); - lv_point_transform(&p[1], angle, zoom, pivot); - lv_point_transform(&p[2], angle, zoom, pivot); - lv_point_transform(&p[3], angle, zoom, pivot); - res->x1 = LV_MIN4(p[0].x, p[1].x, p[2].x, p[3].x) - 2; - res->x2 = LV_MAX4(p[0].x, p[1].x, p[2].x, p[3].x) + 2; - res->y1 = LV_MIN4(p[0].y, p[1].y, p[2].y, p[3].y) - 2; - res->y2 = LV_MAX4(p[0].y, p[1].y, p[2].y, p[3].y) + 2; - -#else - LV_UNUSED(angle); - LV_UNUSED(zoom); - LV_UNUSED(pivot); - res->x1 = 0; - res->y1 = 0; - res->x2 = w - 1; - res->y2 = h - 1; -#endif -} - -/********************** - * STATIC FUNCTIONS - **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.h deleted file mode 100644 index 71c3bd0b2..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.h +++ /dev/null @@ -1,249 +0,0 @@ -/** - * @file lv_img_buf.h - * - */ - -#ifndef LV_IMG_BUF_H -#define LV_IMG_BUF_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include -#include "../misc/lv_color.h" -#include "../misc/lv_area.h" - -/********************* - * DEFINES - *********************/ -/*If image pixels contains alpha we need to know how much byte is a pixel*/ -#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8 -#define LV_IMG_PX_SIZE_ALPHA_BYTE 2 -#elif LV_COLOR_DEPTH == 16 -#define LV_IMG_PX_SIZE_ALPHA_BYTE 3 -#elif LV_COLOR_DEPTH == 32 -#define LV_IMG_PX_SIZE_ALPHA_BYTE 4 -#endif - -#define LV_IMG_BUF_SIZE_TRUE_COLOR(w, h) ((LV_COLOR_SIZE / 8) * w * h) -#define LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h) ((LV_COLOR_SIZE / 8) * w * h) -#define LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h) (LV_IMG_PX_SIZE_ALPHA_BYTE * w * h) - -/*+ 1: to be sure no fractional row*/ -#define LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) ((((w / 8) + 1) * h)) -#define LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) ((((w / 4) + 1) * h)) -#define LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) ((((w / 2) + 1) * h)) -#define LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) ((w * h)) - -/*4 * X: for palette*/ -#define LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) + 4 * 2) -#define LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) + 4 * 4) -#define LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) + 4 * 16) -#define LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) + 4 * 256) - -#define _LV_ZOOM_INV_UPSCALE 5 - -/********************** - * TYPEDEFS - **********************/ - -/*Image color format*/ -enum { - LV_IMG_CF_UNKNOWN = 0, - - LV_IMG_CF_RAW, /**< Contains the file as it is. Needs custom decoder function*/ - LV_IMG_CF_RAW_ALPHA, /**< Contains the file as it is. The image has alpha. Needs custom decoder - function*/ - LV_IMG_CF_RAW_CHROMA_KEYED, /**< Contains the file as it is. The image is chroma keyed. Needs - custom decoder function*/ - - LV_IMG_CF_TRUE_COLOR, /**< Color format and depth should match with LV_COLOR settings*/ - LV_IMG_CF_TRUE_COLOR_ALPHA, /**< Same as `LV_IMG_CF_TRUE_COLOR` but every pixel has an alpha byte*/ - LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED, /**< Same as `LV_IMG_CF_TRUE_COLOR` but LV_COLOR_TRANSP pixels - will be transparent*/ - - LV_IMG_CF_INDEXED_1BIT, /**< Can have 2 different colors in a palette (can't be chroma keyed)*/ - LV_IMG_CF_INDEXED_2BIT, /**< Can have 4 different colors in a palette (can't be chroma keyed)*/ - LV_IMG_CF_INDEXED_4BIT, /**< Can have 16 different colors in a palette (can't be chroma keyed)*/ - LV_IMG_CF_INDEXED_8BIT, /**< Can have 256 different colors in a palette (can't be chroma keyed)*/ - - LV_IMG_CF_ALPHA_1BIT, /**< Can have one color and it can be drawn or not*/ - LV_IMG_CF_ALPHA_2BIT, /**< Can have one color but 4 different alpha value*/ - LV_IMG_CF_ALPHA_4BIT, /**< Can have one color but 16 different alpha value*/ - LV_IMG_CF_ALPHA_8BIT, /**< Can have one color but 256 different alpha value*/ - - LV_IMG_CF_RGB888, - LV_IMG_CF_RGBA8888, - LV_IMG_CF_RGBX8888, - LV_IMG_CF_RGB565, - LV_IMG_CF_RGBA5658, - LV_IMG_CF_RGB565A8, - - LV_IMG_CF_RESERVED_15, /**< Reserved for further use.*/ - LV_IMG_CF_RESERVED_16, /**< Reserved for further use.*/ - LV_IMG_CF_RESERVED_17, /**< Reserved for further use.*/ - LV_IMG_CF_RESERVED_18, /**< Reserved for further use.*/ - LV_IMG_CF_RESERVED_19, /**< Reserved for further use.*/ - LV_IMG_CF_RESERVED_20, /**< Reserved for further use.*/ - LV_IMG_CF_RESERVED_21, /**< Reserved for further use.*/ - LV_IMG_CF_RESERVED_22, /**< Reserved for further use.*/ - LV_IMG_CF_RESERVED_23, /**< Reserved for further use.*/ - - LV_IMG_CF_USER_ENCODED_0, /**< User holder encoding format.*/ - LV_IMG_CF_USER_ENCODED_1, /**< User holder encoding format.*/ - LV_IMG_CF_USER_ENCODED_2, /**< User holder encoding format.*/ - LV_IMG_CF_USER_ENCODED_3, /**< User holder encoding format.*/ - LV_IMG_CF_USER_ENCODED_4, /**< User holder encoding format.*/ - LV_IMG_CF_USER_ENCODED_5, /**< User holder encoding format.*/ - LV_IMG_CF_USER_ENCODED_6, /**< User holder encoding format.*/ - LV_IMG_CF_USER_ENCODED_7, /**< User holder encoding format.*/ -}; -typedef uint8_t lv_img_cf_t; - - -/** - * The first 8 bit is very important to distinguish the different source types. - * For more info see `lv_img_get_src_type()` in lv_img.c - * On big endian systems the order is reversed so cf and always_zero must be at - * the end of the struct. - */ -#if LV_BIG_ENDIAN_SYSTEM -typedef struct { - - uint32_t h : 11; /*Height of the image map*/ - uint32_t w : 11; /*Width of the image map*/ - uint32_t reserved : 2; /*Reserved to be used later*/ - uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a - non-printable character*/ - uint32_t cf : 5; /*Color format: See `lv_img_color_format_t`*/ - -} lv_img_header_t; -#else -typedef struct { - - uint32_t cf : 5; /*Color format: See `lv_img_color_format_t`*/ - uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a - non-printable character*/ - - uint32_t reserved : 2; /*Reserved to be used later*/ - - uint32_t w : 11; /*Width of the image map*/ - uint32_t h : 11; /*Height of the image map*/ -} lv_img_header_t; -#endif - -/** Image header it is compatible with - * the result from image converter utility*/ -typedef struct { - lv_img_header_t header; /**< A header describing the basics of the image*/ - uint32_t data_size; /**< Size of the image in bytes*/ - const uint8_t * data; /**< Pointer to the data of the image*/ -} lv_img_dsc_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Allocate an image buffer in RAM - * @param w width of image - * @param h height of image - * @param cf a color format (`LV_IMG_CF_...`) - * @return an allocated image, or NULL on failure - */ -lv_img_dsc_t * lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf); - -/** - * Get the color of an image's pixel - * @param dsc an image descriptor - * @param x x coordinate of the point to get - * @param y x coordinate of the point to get - * @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used. - * Not used in other cases. - * @param safe true: check out of bounds - * @return color of the point - */ -lv_color_t lv_img_buf_get_px_color(const lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color); - -/** - * Get the alpha value of an image's pixel - * @param dsc pointer to an image descriptor - * @param x x coordinate of the point to set - * @param y x coordinate of the point to set - * @param safe true: check out of bounds - * @return alpha value of the point - */ -lv_opa_t lv_img_buf_get_px_alpha(const lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y); - -/** - * Set the color of a pixel of an image. The alpha channel won't be affected. - * @param dsc pointer to an image descriptor - * @param x x coordinate of the point to set - * @param y x coordinate of the point to set - * @param c color of the point - * @param safe true: check out of bounds - */ -void lv_img_buf_set_px_color(const lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c); - -/** - * Set the alpha value of a pixel of an image. The color won't be affected - * @param dsc pointer to an image descriptor - * @param x x coordinate of the point to set - * @param y x coordinate of the point to set - * @param opa the desired opacity - * @param safe true: check out of bounds - */ -void lv_img_buf_set_px_alpha(const lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa); - -/** - * Set the palette color of an indexed image. Valid only for `LV_IMG_CF_INDEXED1/2/4/8` - * @param dsc pointer to an image descriptor - * @param id the palette color to set: - * - for `LV_IMG_CF_INDEXED1`: 0..1 - * - for `LV_IMG_CF_INDEXED2`: 0..3 - * - for `LV_IMG_CF_INDEXED4`: 0..15 - * - for `LV_IMG_CF_INDEXED8`: 0..255 - * @param c the color to set - */ -void lv_img_buf_set_palette(const lv_img_dsc_t * dsc, uint8_t id, lv_color_t c); - -/** - * Free an allocated image buffer - * @param dsc image buffer to free - */ -void lv_img_buf_free(lv_img_dsc_t * dsc); - -/** - * Get the memory consumption of a raw bitmap, given color format and dimensions. - * @param w width - * @param h height - * @param cf color format - * @return size in bytes - */ -uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf); - -/** - * Get the area of a rectangle if its rotated and scaled - * @param res store the coordinates here - * @param w width of the rectangle to transform - * @param h height of the rectangle to transform - * @param angle angle of rotation - * @param zoom zoom, (256 no zoom) - * @param pivot x,y pivot coordinates of rotation - */ -void _lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t h, int16_t angle, uint16_t zoom, - const lv_point_t * pivot); - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_IMG_BUF_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_cache.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_cache.c deleted file mode 100644 index 2caf51217..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_cache.c +++ /dev/null @@ -1,215 +0,0 @@ -/** - * @file lv_img_cache.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../misc/lv_assert.h" -#include "lv_img_cache.h" -#include "lv_img_decoder.h" -#include "lv_draw_img.h" -#include "../hal/lv_hal_tick.h" -#include "../misc/lv_gc.h" - -/********************* - * DEFINES - *********************/ -/*Decrement life with this value on every open*/ -#define LV_IMG_CACHE_AGING 1 - -/*Boost life by this factor (multiply time_to_open with this value)*/ -#define LV_IMG_CACHE_LIFE_GAIN 1 - -/*Don't let life to be greater than this limit because it would require a lot of time to - * "die" from very high values*/ -#define LV_IMG_CACHE_LIFE_LIMIT 1000 - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -#if LV_IMG_CACHE_DEF_SIZE - static bool lv_img_cache_match(const void * src1, const void * src2); -#endif - -/********************** - * STATIC VARIABLES - **********************/ -#if LV_IMG_CACHE_DEF_SIZE - static uint16_t entry_cnt; -#endif - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Open an image using the image decoder interface and cache it. - * The image will be left open meaning if the image decoder open callback allocated memory then it will remain. - * The image is closed if a new image is opened and the new image takes its place in the cache. - * @param src source of the image. Path to file or pointer to an `lv_img_dsc_t` variable - * @param color color The color of the image with `LV_IMG_CF_ALPHA_...` - * @return pointer to the cache entry or NULL if can open the image - */ -_lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color, int32_t frame_id) -{ - /*Is the image cached?*/ - _lv_img_cache_entry_t * cached_src = NULL; - -#if LV_IMG_CACHE_DEF_SIZE - if(entry_cnt == 0) { - LV_LOG_WARN("lv_img_cache_open: the cache size is 0"); - return NULL; - } - - _lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array); - - /*Decrement all lifes. Make the entries older*/ - uint16_t i; - for(i = 0; i < entry_cnt; i++) { - if(cache[i].life > INT32_MIN + LV_IMG_CACHE_AGING) { - cache[i].life -= LV_IMG_CACHE_AGING; - } - } - - for(i = 0; i < entry_cnt; i++) { - if(color.full == cache[i].dec_dsc.color.full && - frame_id == cache[i].dec_dsc.frame_id && - lv_img_cache_match(src, cache[i].dec_dsc.src)) { - /*If opened increment its life. - *Image difficult to open should live longer to keep avoid frequent their recaching. - *Therefore increase `life` with `time_to_open`*/ - cached_src = &cache[i]; - cached_src->life += cached_src->dec_dsc.time_to_open * LV_IMG_CACHE_LIFE_GAIN; - if(cached_src->life > LV_IMG_CACHE_LIFE_LIMIT) cached_src->life = LV_IMG_CACHE_LIFE_LIMIT; - LV_LOG_TRACE("image source found in the cache"); - break; - } - } - - /*The image is not cached then cache it now*/ - if(cached_src) return cached_src; - - /*Find an entry to reuse. Select the entry with the least life*/ - cached_src = &cache[0]; - for(i = 1; i < entry_cnt; i++) { - if(cache[i].life < cached_src->life) { - cached_src = &cache[i]; - } - } - - /*Close the decoder to reuse if it was opened (has a valid source)*/ - if(cached_src->dec_dsc.src) { - lv_img_decoder_close(&cached_src->dec_dsc); - LV_LOG_INFO("image draw: cache miss, close and reuse an entry"); - } - else { - LV_LOG_INFO("image draw: cache miss, cached to an empty entry"); - } -#else - cached_src = &LV_GC_ROOT(_lv_img_cache_single); -#endif - /*Open the image and measure the time to open*/ - uint32_t t_start = lv_tick_get(); - lv_res_t open_res = lv_img_decoder_open(&cached_src->dec_dsc, src, color, frame_id); - if(open_res == LV_RES_INV) { - LV_LOG_WARN("Image draw cannot open the image resource"); - lv_memset_00(cached_src, sizeof(_lv_img_cache_entry_t)); - cached_src->life = INT32_MIN; /*Make the empty entry very "weak" to force its us*/ - return NULL; - } - - cached_src->life = 0; - - /*If `time_to_open` was not set in the open function set it here*/ - if(cached_src->dec_dsc.time_to_open == 0) { - cached_src->dec_dsc.time_to_open = lv_tick_elaps(t_start); - } - - if(cached_src->dec_dsc.time_to_open == 0) cached_src->dec_dsc.time_to_open = 1; - - return cached_src; -} - -/** - * Set the number of images to be cached. - * More cached images mean more opened image at same time which might mean more memory usage. - * E.g. if 20 PNG or JPG images are open in the RAM they consume memory while opened in the cache. - * @param new_entry_cnt number of image to cache - */ -void lv_img_cache_set_size(uint16_t new_entry_cnt) -{ -#if LV_IMG_CACHE_DEF_SIZE == 0 - LV_UNUSED(new_entry_cnt); - LV_LOG_WARN("Can't change cache size because it's disabled by LV_IMG_CACHE_DEF_SIZE = 0"); -#else - if(LV_GC_ROOT(_lv_img_cache_array) != NULL) { - /*Clean the cache before free it*/ - lv_img_cache_invalidate_src(NULL); - lv_mem_free(LV_GC_ROOT(_lv_img_cache_array)); - } - - /*Reallocate the cache*/ - LV_GC_ROOT(_lv_img_cache_array) = lv_mem_alloc(sizeof(_lv_img_cache_entry_t) * new_entry_cnt); - LV_ASSERT_MALLOC(LV_GC_ROOT(_lv_img_cache_array)); - if(LV_GC_ROOT(_lv_img_cache_array) == NULL) { - entry_cnt = 0; - return; - } - entry_cnt = new_entry_cnt; - - /*Clean the cache*/ - lv_memset_00(LV_GC_ROOT(_lv_img_cache_array), entry_cnt * sizeof(_lv_img_cache_entry_t)); -#endif -} - -/** - * Invalidate an image source in the cache. - * Useful if the image source is updated therefore it needs to be cached again. - * @param src an image source path to a file or pointer to an `lv_img_dsc_t` variable. - */ -void lv_img_cache_invalidate_src(const void * src) -{ - LV_UNUSED(src); -#if LV_IMG_CACHE_DEF_SIZE - _lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array); - - uint16_t i; - for(i = 0; i < entry_cnt; i++) { - if(src == NULL || lv_img_cache_match(src, cache[i].dec_dsc.src)) { - if(cache[i].dec_dsc.src != NULL) { - lv_img_decoder_close(&cache[i].dec_dsc); - } - - lv_memset_00(&cache[i], sizeof(_lv_img_cache_entry_t)); - } - } -#endif -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -#if LV_IMG_CACHE_DEF_SIZE -static bool lv_img_cache_match(const void * src1, const void * src2) -{ - lv_img_src_t src_type = lv_img_src_get_type(src1); - if(src_type == LV_IMG_SRC_VARIABLE) - return src1 == src2; - if(src_type != LV_IMG_SRC_FILE) - return false; - if(lv_img_src_get_type(src2) != LV_IMG_SRC_FILE) - return false; - return strcmp(src1, src2) == 0; -} -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_cache.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_cache.h deleted file mode 100644 index dc0c5d98c..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_cache.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file lv_img_cache.h - * - */ - -#ifndef LV_IMG_CACHE_H -#define LV_IMG_CACHE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "lv_img_decoder.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/** - * When loading images from the network it can take a long time to download and decode the image. - * - * To avoid repeating this heavy load images can be cached. - */ -typedef struct { - lv_img_decoder_dsc_t dec_dsc; /**< Image information*/ - - /** Count the cache entries's life. Add `time_to_open` to `life` when the entry is used. - * Decrement all lifes by one every in every ::lv_img_cache_open. - * If life == 0 the entry can be reused*/ - int32_t life; -} _lv_img_cache_entry_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Open an image using the image decoder interface and cache it. - * The image will be left open meaning if the image decoder open callback allocated memory then it will remain. - * The image is closed if a new image is opened and the new image takes its place in the cache. - * @param src source of the image. Path to file or pointer to an `lv_img_dsc_t` variable - * @param color The color of the image with `LV_IMG_CF_ALPHA_...` - * @param frame_id the index of the frame. Used only with animated images, set 0 for normal images - * @return pointer to the cache entry or NULL if can open the image - */ -_lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color, int32_t frame_id); - -/** - * Set the number of images to be cached. - * More cached images mean more opened image at same time which might mean more memory usage. - * E.g. if 20 PNG or JPG images are open in the RAM they consume memory while opened in the cache. - * @param new_entry_cnt number of image to cache - */ -void lv_img_cache_set_size(uint16_t new_slot_num); - -/** - * Invalidate an image source in the cache. - * Useful if the image source is updated therefore it needs to be cached again. - * @param src an image source path to a file or pointer to an `lv_img_dsc_t` variable. - */ -void lv_img_cache_invalidate_src(const void * src); - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_IMG_CACHE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.c b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.c deleted file mode 100644 index 76aff5ec7..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.c +++ /dev/null @@ -1,730 +0,0 @@ -/** - * @file lv_img_decoder.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_img_decoder.h" -#include "../misc/lv_assert.h" -#include "../draw/lv_draw_img.h" -#include "../misc/lv_ll.h" -#include "../misc/lv_gc.h" - -/********************* - * DEFINES - *********************/ -#define CF_BUILT_IN_FIRST LV_IMG_CF_TRUE_COLOR -#define CF_BUILT_IN_LAST LV_IMG_CF_RGB565A8 - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - lv_fs_file_t f; - lv_color_t * palette; - lv_opa_t * opa; -} lv_img_decoder_built_in_data_t; - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_res_t lv_img_decoder_built_in_line_true_color(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, - lv_coord_t len, uint8_t * buf); -static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, - lv_coord_t len, uint8_t * buf); -static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, - lv_coord_t len, uint8_t * buf); - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Initialize the image decoder module - */ -void _lv_img_decoder_init(void) -{ - _lv_ll_init(&LV_GC_ROOT(_lv_img_decoder_ll), sizeof(lv_img_decoder_t)); - - lv_img_decoder_t * decoder; - - /*Create a decoder for the built in color format*/ - decoder = lv_img_decoder_create(); - LV_ASSERT_MALLOC(decoder); - if(decoder == NULL) { - LV_LOG_WARN("lv_img_decoder_init: out of memory"); - return; - } - - lv_img_decoder_set_info_cb(decoder, lv_img_decoder_built_in_info); - lv_img_decoder_set_open_cb(decoder, lv_img_decoder_built_in_open); - lv_img_decoder_set_read_line_cb(decoder, lv_img_decoder_built_in_read_line); - lv_img_decoder_set_close_cb(decoder, lv_img_decoder_built_in_close); -} - -/** - * Get information about an image. - * Try the created image decoder one by one. Once one is able to get info that info will be used. - * @param src the image source. E.g. file name or variable. - * @param header the image info will be stored here - * @return LV_RES_OK: success; LV_RES_INV: wasn't able to get info about the image - */ -lv_res_t lv_img_decoder_get_info(const void * src, lv_img_header_t * header) -{ - lv_memset_00(header, sizeof(lv_img_header_t)); - - if(src == NULL) return LV_RES_INV; - - lv_img_src_t src_type = lv_img_src_get_type(src); - if(src_type == LV_IMG_SRC_VARIABLE) { - const lv_img_dsc_t * img_dsc = src; - if(img_dsc->data == NULL) return LV_RES_INV; - } - - lv_res_t res = LV_RES_INV; - lv_img_decoder_t * d; - _LV_LL_READ(&LV_GC_ROOT(_lv_img_decoder_ll), d) { - if(d->info_cb) { - res = d->info_cb(d, src, header); - if(res == LV_RES_OK) break; - } - } - - return res; -} - -lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, lv_color_t color, int32_t frame_id) -{ - lv_memset_00(dsc, sizeof(lv_img_decoder_dsc_t)); - - if(src == NULL) return LV_RES_INV; - lv_img_src_t src_type = lv_img_src_get_type(src); - if(src_type == LV_IMG_SRC_VARIABLE) { - const lv_img_dsc_t * img_dsc = src; - if(img_dsc->data == NULL) return LV_RES_INV; - } - - dsc->color = color; - dsc->src_type = src_type; - dsc->frame_id = frame_id; - - if(dsc->src_type == LV_IMG_SRC_FILE) { - size_t fnlen = strlen(src); - dsc->src = lv_mem_alloc(fnlen + 1); - LV_ASSERT_MALLOC(dsc->src); - if(dsc->src == NULL) { - LV_LOG_WARN("lv_img_decoder_open: out of memory"); - return LV_RES_INV; - } - strcpy((char *)dsc->src, src); - } - else { - dsc->src = src; - } - - lv_res_t res = LV_RES_INV; - - lv_img_decoder_t * decoder; - _LV_LL_READ(&LV_GC_ROOT(_lv_img_decoder_ll), decoder) { - /*Info and Open callbacks are required*/ - if(decoder->info_cb == NULL || decoder->open_cb == NULL) continue; - - res = decoder->info_cb(decoder, src, &dsc->header); - if(res != LV_RES_OK) continue; - - dsc->decoder = decoder; - res = decoder->open_cb(decoder, dsc); - - /*Opened successfully. It is a good decoder for this image source*/ - if(res == LV_RES_OK) return res; - - /*Prepare for the next loop*/ - lv_memset_00(&dsc->header, sizeof(lv_img_header_t)); - - dsc->error_msg = NULL; - dsc->img_data = NULL; - dsc->user_data = NULL; - dsc->time_to_open = 0; - } - - if(dsc->src_type == LV_IMG_SRC_FILE) - lv_mem_free((void *)dsc->src); - - return res; -} - -/** - * Read a line from an opened image - * @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open` - * @param x start X coordinate (from left) - * @param y start Y coordinate (from top) - * @param len number of pixels to read - * @param buf store the data here - * @return LV_RES_OK: success; LV_RES_INV: an error occurred - */ -lv_res_t lv_img_decoder_read_line(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf) -{ - lv_res_t res = LV_RES_INV; - if(dsc->decoder->read_line_cb) res = dsc->decoder->read_line_cb(dsc->decoder, dsc, x, y, len, buf); - - return res; -} - -/** - * Close a decoding session - * @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open` - */ -void lv_img_decoder_close(lv_img_decoder_dsc_t * dsc) -{ - if(dsc->decoder) { - if(dsc->decoder->close_cb) dsc->decoder->close_cb(dsc->decoder, dsc); - - if(dsc->src_type == LV_IMG_SRC_FILE) { - lv_mem_free((void *)dsc->src); - dsc->src = NULL; - } - } -} - -/** - * Create a new image decoder - * @return pointer to the new image decoder - */ -lv_img_decoder_t * lv_img_decoder_create(void) -{ - lv_img_decoder_t * decoder; - decoder = _lv_ll_ins_head(&LV_GC_ROOT(_lv_img_decoder_ll)); - LV_ASSERT_MALLOC(decoder); - if(decoder == NULL) return NULL; - - lv_memset_00(decoder, sizeof(lv_img_decoder_t)); - - return decoder; -} - -/** - * Delete an image decoder - * @param decoder pointer to an image decoder - */ -void lv_img_decoder_delete(lv_img_decoder_t * decoder) -{ - _lv_ll_remove(&LV_GC_ROOT(_lv_img_decoder_ll), decoder); - lv_mem_free(decoder); -} - -/** - * Set a callback to get information about the image - * @param decoder pointer to an image decoder - * @param info_cb a function to collect info about an image (fill an `lv_img_header_t` struct) - */ -void lv_img_decoder_set_info_cb(lv_img_decoder_t * decoder, lv_img_decoder_info_f_t info_cb) -{ - decoder->info_cb = info_cb; -} - -/** - * Set a callback to open an image - * @param decoder pointer to an image decoder - * @param open_cb a function to open an image - */ -void lv_img_decoder_set_open_cb(lv_img_decoder_t * decoder, lv_img_decoder_open_f_t open_cb) -{ - decoder->open_cb = open_cb; -} - -/** - * Set a callback to a decoded line of an image - * @param decoder pointer to an image decoder - * @param read_line_cb a function to read a line of an image - */ -void lv_img_decoder_set_read_line_cb(lv_img_decoder_t * decoder, lv_img_decoder_read_line_f_t read_line_cb) -{ - decoder->read_line_cb = read_line_cb; -} - -/** - * Set a callback to close a decoding session. E.g. close files and free other resources. - * @param decoder pointer to an image decoder - * @param close_cb a function to close a decoding session - */ -void lv_img_decoder_set_close_cb(lv_img_decoder_t * decoder, lv_img_decoder_close_f_t close_cb) -{ - decoder->close_cb = close_cb; -} - -/** - * Get info about a built-in image - * @param decoder the decoder where this function belongs - * @param src the image source: pointer to an `lv_img_dsc_t` variable, a file path or a symbol - * @param header store the image data here - * @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error. - */ -lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header) -{ - LV_UNUSED(decoder); /*Unused*/ - - lv_img_src_t src_type = lv_img_src_get_type(src); - if(src_type == LV_IMG_SRC_VARIABLE) { - lv_img_cf_t cf = ((lv_img_dsc_t *)src)->header.cf; - if(cf < CF_BUILT_IN_FIRST || cf > CF_BUILT_IN_LAST) return LV_RES_INV; - - header->w = ((lv_img_dsc_t *)src)->header.w; - header->h = ((lv_img_dsc_t *)src)->header.h; - header->cf = ((lv_img_dsc_t *)src)->header.cf; - } - else if(src_type == LV_IMG_SRC_FILE) { - /*Support only "*.bin" files*/ - if(strcmp(lv_fs_get_ext(src), "bin")) return LV_RES_INV; - - lv_fs_file_t f; - lv_fs_res_t res = lv_fs_open(&f, src, LV_FS_MODE_RD); - if(res == LV_FS_RES_OK) { - uint32_t rn; - res = lv_fs_read(&f, header, sizeof(lv_img_header_t), &rn); - lv_fs_close(&f); - if(res != LV_FS_RES_OK || rn != sizeof(lv_img_header_t)) { - LV_LOG_WARN("Image get info get read file header"); - return LV_RES_INV; - } - } - - if(header->cf < CF_BUILT_IN_FIRST || header->cf > CF_BUILT_IN_LAST) return LV_RES_INV; - } - else if(src_type == LV_IMG_SRC_SYMBOL) { - /*The size depend on the font but it is unknown here. It should be handled outside of the - *function*/ - header->w = 1; - header->h = 1; - /*Symbols always have transparent parts. Important because of cover check in the draw - *function. The actual value doesn't matter because lv_draw_label will draw it*/ - header->cf = LV_IMG_CF_ALPHA_1BIT; - } - else { - LV_LOG_WARN("Image get info found unknown src type"); - return LV_RES_INV; - } - return LV_RES_OK; -} - -/** - * Open a built in image - * @param decoder the decoder where this function belongs - * @param dsc pointer to decoder descriptor. `src`, `color` are already initialized in it. - * @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error. - */ -lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) -{ - /*Open the file if it's a file*/ - if(dsc->src_type == LV_IMG_SRC_FILE) { - /*Support only "*.bin" files*/ - if(strcmp(lv_fs_get_ext(dsc->src), "bin")) return LV_RES_INV; - - lv_fs_file_t f; - lv_fs_res_t res = lv_fs_open(&f, dsc->src, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) { - LV_LOG_WARN("Built-in image decoder can't open the file"); - return LV_RES_INV; - } - - /*If the file was open successfully save the file descriptor*/ - if(dsc->user_data == NULL) { - dsc->user_data = lv_mem_alloc(sizeof(lv_img_decoder_built_in_data_t)); - LV_ASSERT_MALLOC(dsc->user_data); - if(dsc->user_data == NULL) { - LV_LOG_ERROR("img_decoder_built_in_open: out of memory"); - lv_fs_close(&f); - return LV_RES_INV; - } - lv_memset_00(dsc->user_data, sizeof(lv_img_decoder_built_in_data_t)); - } - - lv_img_decoder_built_in_data_t * user_data = dsc->user_data; - lv_memcpy_small(&user_data->f, &f, sizeof(f)); - } - else if(dsc->src_type == LV_IMG_SRC_VARIABLE) { - /*The variables should have valid data*/ - if(((lv_img_dsc_t *)dsc->src)->data == NULL) { - return LV_RES_INV; - } - } - - lv_img_cf_t cf = dsc->header.cf; - /*Process A8, RGB565A8, need load file to ram after https://github.com/lvgl/lvgl/pull/3337*/ - if(cf == LV_IMG_CF_ALPHA_8BIT || cf == LV_IMG_CF_RGB565A8) { - if(dsc->src_type == LV_IMG_SRC_VARIABLE) { - /*In case of uncompressed formats the image stored in the ROM/RAM. - *So simply give its pointer*/ - dsc->img_data = ((lv_img_dsc_t *)dsc->src)->data; - return LV_RES_OK; - } - else { - /*If it's a file, read all to memory*/ - uint32_t len = dsc->header.w * dsc->header.h; - len *= cf == LV_IMG_CF_RGB565A8 ? 3 : 1; - uint8_t * fs_buf = lv_mem_alloc(len); - if(fs_buf == NULL) return LV_RES_INV; - - lv_img_decoder_built_in_data_t * user_data = dsc->user_data; - lv_fs_seek(&user_data->f, 4, LV_FS_SEEK_SET); /*+4 to skip the header*/ - lv_fs_res_t res = lv_fs_read(&user_data->f, fs_buf, len, NULL); - if(res != LV_FS_RES_OK) { - lv_mem_free(fs_buf); - return LV_RES_INV; - } - dsc->img_data = fs_buf; - return LV_RES_OK; - } - } - /*Process true color formats*/ - else if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_ALPHA || - cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { - if(dsc->src_type == LV_IMG_SRC_VARIABLE) { - /*In case of uncompressed formats the image stored in the ROM/RAM. - *So simply give its pointer*/ - dsc->img_data = ((lv_img_dsc_t *)dsc->src)->data; - return LV_RES_OK; - } - else { - /*If it's a file it need to be read line by line later*/ - return LV_RES_OK; - } - } - /*Process indexed images. Build a palette*/ - else if(cf == LV_IMG_CF_INDEXED_1BIT || cf == LV_IMG_CF_INDEXED_2BIT || cf == LV_IMG_CF_INDEXED_4BIT || - cf == LV_IMG_CF_INDEXED_8BIT) { - uint8_t px_size = lv_img_cf_get_px_size(cf); - uint32_t palette_size = 1 << px_size; - - /*Allocate the palette*/ - if(dsc->user_data == NULL) { - dsc->user_data = lv_mem_alloc(sizeof(lv_img_decoder_built_in_data_t)); - LV_ASSERT_MALLOC(dsc->user_data); - if(dsc->user_data == NULL) { - LV_LOG_ERROR("img_decoder_built_in_open: out of memory"); - return LV_RES_INV; - } - lv_memset_00(dsc->user_data, sizeof(lv_img_decoder_built_in_data_t)); - } - - lv_img_decoder_built_in_data_t * user_data = dsc->user_data; - user_data->palette = lv_mem_alloc(palette_size * sizeof(lv_color_t)); - LV_ASSERT_MALLOC(user_data->palette); - user_data->opa = lv_mem_alloc(palette_size * sizeof(lv_opa_t)); - LV_ASSERT_MALLOC(user_data->opa); - if(user_data->palette == NULL || user_data->opa == NULL) { - LV_LOG_ERROR("img_decoder_built_in_open: out of memory"); - lv_img_decoder_built_in_close(decoder, dsc); - return LV_RES_INV; - } - - if(dsc->src_type == LV_IMG_SRC_FILE) { - /*Read the palette from file*/ - lv_fs_seek(&user_data->f, 4, LV_FS_SEEK_SET); /*Skip the header*/ - lv_color32_t cur_color; - uint32_t i; - for(i = 0; i < palette_size; i++) { - lv_fs_read(&user_data->f, &cur_color, sizeof(lv_color32_t), NULL); - user_data->palette[i] = lv_color_make(cur_color.ch.red, cur_color.ch.green, cur_color.ch.blue); - user_data->opa[i] = cur_color.ch.alpha; - } - } - else { - /*The palette begins in the beginning of the image data. Just point to it.*/ - lv_color32_t * palette_p = (lv_color32_t *)((lv_img_dsc_t *)dsc->src)->data; - - uint32_t i; - for(i = 0; i < palette_size; i++) { - user_data->palette[i] = lv_color_make(palette_p[i].ch.red, palette_p[i].ch.green, palette_p[i].ch.blue); - user_data->opa[i] = palette_p[i].ch.alpha; - } - } - - return LV_RES_OK; - } - /*Alpha indexed images.*/ - else if(cf == LV_IMG_CF_ALPHA_1BIT || cf == LV_IMG_CF_ALPHA_2BIT || cf == LV_IMG_CF_ALPHA_4BIT) { - return LV_RES_OK; /*Nothing to process*/ - } - /*Unknown format. Can't decode it.*/ - else { - /*Free the potentially allocated memories*/ - lv_img_decoder_built_in_close(decoder, dsc); - - LV_LOG_WARN("Image decoder open: unknown color format"); - return LV_RES_INV; - } -} - -/** - * Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`. - * Required only if the "open" function can't return with the whole decoded pixel array. - * @param decoder pointer to the decoder the function associated with - * @param dsc pointer to decoder descriptor - * @param x start x coordinate - * @param y start y coordinate - * @param len number of pixels to decode - * @param buf a buffer to store the decoded pixels - * @return LV_RES_OK: ok; LV_RES_INV: failed - */ -lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x, - lv_coord_t y, lv_coord_t len, uint8_t * buf) -{ - LV_UNUSED(decoder); /*Unused*/ - - lv_res_t res = LV_RES_INV; - - if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA || - dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { - /*For TRUE_COLOR images read line required only for files. - *For variables the image data was returned in `open`*/ - if(dsc->src_type == LV_IMG_SRC_FILE) { - res = lv_img_decoder_built_in_line_true_color(dsc, x, y, len, buf); - } - } - else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT || - dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) { - res = lv_img_decoder_built_in_line_alpha(dsc, x, y, len, buf); - } - else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT || dsc->header.cf == LV_IMG_CF_INDEXED_2BIT || - dsc->header.cf == LV_IMG_CF_INDEXED_4BIT || dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) { - res = lv_img_decoder_built_in_line_indexed(dsc, x, y, len, buf); - } - else { - LV_LOG_WARN("Built-in image decoder read not supports the color format"); - return LV_RES_INV; - } - - return res; -} - -/** - * Close the pending decoding. Free resources etc. - * @param decoder pointer to the decoder the function associated with - * @param dsc pointer to decoder descriptor - */ -void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) -{ - LV_UNUSED(decoder); /*Unused*/ - - lv_img_decoder_built_in_data_t * user_data = dsc->user_data; - if(user_data) { - if(dsc->src_type == LV_IMG_SRC_FILE) { - lv_fs_close(&user_data->f); - } - if(user_data->palette) lv_mem_free(user_data->palette); - if(user_data->opa) lv_mem_free(user_data->opa); - - lv_mem_free(user_data); - dsc->user_data = NULL; - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static lv_res_t lv_img_decoder_built_in_line_true_color(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, - lv_coord_t len, uint8_t * buf) -{ - lv_img_decoder_built_in_data_t * user_data = dsc->user_data; - lv_fs_res_t res; - uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf); - - uint32_t pos = ((y * dsc->header.w + x) * px_size) >> 3; - pos += 4; /*Skip the header*/ - res = lv_fs_seek(&user_data->f, pos, LV_FS_SEEK_SET); - if(res != LV_FS_RES_OK) { - LV_LOG_WARN("Built-in image decoder seek failed"); - return LV_RES_INV; - } - uint32_t btr = len * (px_size >> 3); - uint32_t br = 0; - res = lv_fs_read(&user_data->f, buf, btr, &br); - if(res != LV_FS_RES_OK || btr != br) { - LV_LOG_WARN("Built-in image decoder read failed"); - return LV_RES_INV; - } - - return LV_RES_OK; -} - -static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, - lv_coord_t len, uint8_t * buf) -{ - const lv_opa_t alpha1_opa_table[2] = {0, 255}; /*Opacity mapping with bpp = 1 (Just for compatibility)*/ - const lv_opa_t alpha2_opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/ - const lv_opa_t alpha4_opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/ - 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255 - }; - - /*Simply fill the buffer with the color. Later only the alpha value will be modified.*/ - lv_color_t bg_color = dsc->color; - lv_coord_t i; - for(i = 0; i < len; i++) { -#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 - buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = bg_color.full; -#elif LV_COLOR_DEPTH == 16 - /*Because of Alpha byte 16 bit color can start on odd address which can cause crash*/ - buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = bg_color.full & 0xFF; - buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + 1] = (bg_color.full >> 8) & 0xFF; -#elif LV_COLOR_DEPTH == 32 - *((uint32_t *)&buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE]) = bg_color.full; -#else -#error "Invalid LV_COLOR_DEPTH. Check it in lv_conf.h" -#endif - } - - const lv_opa_t * opa_table = NULL; - uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf); - uint16_t mask = (1 << px_size) - 1; /*E.g. px_size = 2; mask = 0x03*/ - - lv_coord_t w = 0; - uint32_t ofs = 0; - int8_t pos = 0; - switch(dsc->header.cf) { - case LV_IMG_CF_ALPHA_1BIT: - w = (dsc->header.w + 7) >> 3; /*E.g. w = 20 -> w = 2 + 1*/ - ofs += w * y + (x >> 3); /*First pixel*/ - pos = 7 - (x & 0x7); - opa_table = alpha1_opa_table; - break; - case LV_IMG_CF_ALPHA_2BIT: - w = (dsc->header.w + 3) >> 2; /*E.g. w = 13 -> w = 3 + 1 (bytes)*/ - ofs += w * y + (x >> 2); /*First pixel*/ - pos = 6 - (x & 0x3) * 2; - opa_table = alpha2_opa_table; - break; - case LV_IMG_CF_ALPHA_4BIT: - w = (dsc->header.w + 1) >> 1; /*E.g. w = 13 -> w = 6 + 1 (bytes)*/ - ofs += w * y + (x >> 1); /*First pixel*/ - pos = 4 - (x & 0x1) * 4; - opa_table = alpha4_opa_table; - break; - case LV_IMG_CF_ALPHA_8BIT: - w = dsc->header.w; /*E.g. x = 7 -> w = 7 (bytes)*/ - ofs += w * y + x; /*First pixel*/ - pos = 0; - break; - } - - lv_img_decoder_built_in_data_t * user_data = dsc->user_data; - uint8_t * fs_buf = lv_mem_buf_get(w); - if(fs_buf == NULL) return LV_RES_INV; - - const uint8_t * data_tmp = NULL; - if(dsc->src_type == LV_IMG_SRC_VARIABLE) { - const lv_img_dsc_t * img_dsc = dsc->src; - - data_tmp = img_dsc->data + ofs; - } - else { - lv_fs_seek(&user_data->f, ofs + 4, LV_FS_SEEK_SET); /*+4 to skip the header*/ - lv_fs_read(&user_data->f, fs_buf, w, NULL); - data_tmp = fs_buf; - } - - for(i = 0; i < len; i++) { - uint8_t val_act = (*data_tmp >> pos) & mask; - - buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + LV_IMG_PX_SIZE_ALPHA_BYTE - 1] = - dsc->header.cf == LV_IMG_CF_ALPHA_8BIT ? val_act : opa_table[val_act]; - - pos -= px_size; - if(pos < 0) { - pos = 8 - px_size; - data_tmp++; - } - } - lv_mem_buf_release(fs_buf); - return LV_RES_OK; -} - -static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, - lv_coord_t len, uint8_t * buf) -{ - uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf); - uint16_t mask = (1 << px_size) - 1; /*E.g. px_size = 2; mask = 0x03*/ - - lv_coord_t w = 0; - int8_t pos = 0; - uint32_t ofs = 0; - switch(dsc->header.cf) { - case LV_IMG_CF_INDEXED_1BIT: - w = (dsc->header.w + 7) >> 3; /*E.g. w = 20 -> w = 2 + 1*/ - ofs += w * y + (x >> 3); /*First pixel*/ - ofs += 8; /*Skip the palette*/ - pos = 7 - (x & 0x7); - break; - case LV_IMG_CF_INDEXED_2BIT: - w = (dsc->header.w + 3) >> 2; /*E.g. w = 13 -> w = 3 + 1 (bytes)*/ - ofs += w * y + (x >> 2); /*First pixel*/ - ofs += 16; /*Skip the palette*/ - pos = 6 - (x & 0x3) * 2; - break; - case LV_IMG_CF_INDEXED_4BIT: - w = (dsc->header.w + 1) >> 1; /*E.g. w = 13 -> w = 6 + 1 (bytes)*/ - ofs += w * y + (x >> 1); /*First pixel*/ - ofs += 64; /*Skip the palette*/ - pos = 4 - (x & 0x1) * 4; - break; - case LV_IMG_CF_INDEXED_8BIT: - w = dsc->header.w; /*E.g. x = 7 -> w = 7 (bytes)*/ - ofs += w * y + x; /*First pixel*/ - ofs += 1024; /*Skip the palette*/ - pos = 0; - break; - } - - lv_img_decoder_built_in_data_t * user_data = dsc->user_data; - - uint8_t * fs_buf = lv_mem_buf_get(w); - if(fs_buf == NULL) return LV_RES_INV; - const uint8_t * data_tmp = NULL; - if(dsc->src_type == LV_IMG_SRC_VARIABLE) { - const lv_img_dsc_t * img_dsc = dsc->src; - data_tmp = img_dsc->data + ofs; - } - else { - lv_fs_seek(&user_data->f, ofs + 4, LV_FS_SEEK_SET); /*+4 to skip the header*/ - lv_fs_read(&user_data->f, fs_buf, w, NULL); - data_tmp = fs_buf; - } - - lv_coord_t i; - for(i = 0; i < len; i++) { - uint8_t val_act = (*data_tmp >> pos) & mask; - - lv_color_t color = user_data->palette[val_act]; -#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 - buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = color.full; -#elif LV_COLOR_DEPTH == 16 - /*Because of Alpha byte 16 bit color can start on odd address which can cause crash*/ - buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = color.full & 0xFF; - buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + 1] = (color.full >> 8) & 0xFF; -#elif LV_COLOR_DEPTH == 32 - *((uint32_t *)&buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE]) = color.full; -#else -#error "Invalid LV_COLOR_DEPTH. Check it in lv_conf.h" -#endif - buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + LV_IMG_PX_SIZE_ALPHA_BYTE - 1] = user_data->opa[val_act]; - - pos -= px_size; - if(pos < 0) { - pos = 8 - px_size; - data_tmp++; - } - } - lv_mem_buf_release(fs_buf); - return LV_RES_OK; -} diff --git a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.h b/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.h deleted file mode 100644 index 9dc84dd56..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/lv_img_decoder.h +++ /dev/null @@ -1,274 +0,0 @@ -/** - * @file lv_img_decoder.h - * - */ - -#ifndef LV_IMG_DECODER_H -#define LV_IMG_DECODER_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#include -#include "lv_img_buf.h" -#include "../misc/lv_fs.h" -#include "../misc/lv_types.h" -#include "../misc/lv_area.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/** - * Source of image.*/ -enum { - LV_IMG_SRC_VARIABLE, /** Binary/C variable*/ - LV_IMG_SRC_FILE, /** File in filesystem*/ - LV_IMG_SRC_SYMBOL, /** Symbol (@ref lv_symbol_def.h)*/ - LV_IMG_SRC_UNKNOWN, /** Unknown source*/ -}; - -typedef uint8_t lv_img_src_t; - -/*Decoder function definitions*/ -struct _lv_img_decoder_dsc_t; -struct _lv_img_decoder_t; - -/** - * Get info from an image and store in the `header` - * @param src the image source. Can be a pointer to a C array or a file name (Use - * `lv_img_src_get_type` to determine the type) - * @param header store the info here - * @return LV_RES_OK: info written correctly; LV_RES_INV: failed - */ -typedef lv_res_t (*lv_img_decoder_info_f_t)(struct _lv_img_decoder_t * decoder, const void * src, - lv_img_header_t * header); - -/** - * Open an image for decoding. Prepare it as it is required to read it later - * @param decoder pointer to the decoder the function associated with - * @param dsc pointer to decoder descriptor. `src`, `color` are already initialized in it. - */ -typedef lv_res_t (*lv_img_decoder_open_f_t)(struct _lv_img_decoder_t * decoder, struct _lv_img_decoder_dsc_t * dsc); - -/** - * Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`. - * Required only if the "open" function can't return with the whole decoded pixel array. - * @param decoder pointer to the decoder the function associated with - * @param dsc pointer to decoder descriptor - * @param x start x coordinate - * @param y start y coordinate - * @param len number of pixels to decode - * @param buf a buffer to store the decoded pixels - * @return LV_RES_OK: ok; LV_RES_INV: failed - */ -typedef lv_res_t (*lv_img_decoder_read_line_f_t)(struct _lv_img_decoder_t * decoder, struct _lv_img_decoder_dsc_t * dsc, - lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf); - -/** - * Close the pending decoding. Free resources etc. - * @param decoder pointer to the decoder the function associated with - * @param dsc pointer to decoder descriptor - */ -typedef void (*lv_img_decoder_close_f_t)(struct _lv_img_decoder_t * decoder, struct _lv_img_decoder_dsc_t * dsc); - - -typedef struct _lv_img_decoder_t { - lv_img_decoder_info_f_t info_cb; - lv_img_decoder_open_f_t open_cb; - lv_img_decoder_read_line_f_t read_line_cb; - lv_img_decoder_close_f_t close_cb; - -#if LV_USE_USER_DATA - void * user_data; -#endif -} lv_img_decoder_t; - - -/**Describe an image decoding session. Stores data about the decoding*/ -typedef struct _lv_img_decoder_dsc_t { - /**The decoder which was able to open the image source*/ - lv_img_decoder_t * decoder; - - /**The image source. A file path like "S:my_img.png" or pointer to an `lv_img_dsc_t` variable*/ - const void * src; - - /**Color to draw the image. USed when the image has alpha channel only*/ - lv_color_t color; - - /**Frame of the image, using with animated images*/ - int32_t frame_id; - - /**Type of the source: file or variable. Can be set in `open` function if required*/ - lv_img_src_t src_type; - - /**Info about the opened image: color format, size, etc. MUST be set in `open` function*/ - lv_img_header_t header; - - /** Pointer to a buffer where the image's data (pixels) are stored in a decoded, plain format. - * MUST be set in `open` function*/ - const uint8_t * img_data; - - /** How much time did it take to open the image. [ms] - * If not set `lv_img_cache` will measure and set the time to open*/ - uint32_t time_to_open; - - /**A text to display instead of the image when the image can't be opened. - * Can be set in `open` function or set NULL.*/ - const char * error_msg; - - /**Store any custom data here is required*/ - void * user_data; -} lv_img_decoder_dsc_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Initialize the image decoder module - */ -void _lv_img_decoder_init(void); - -/** - * Get information about an image. - * Try the created image decoder one by one. Once one is able to get info that info will be used. - * @param src the image source. Can be - * 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_drv_register()`) - * 2) Variable: Pointer to an `lv_img_dsc_t` variable - * 3) Symbol: E.g. `LV_SYMBOL_OK` - * @param header the image info will be stored here - * @return LV_RES_OK: success; LV_RES_INV: wasn't able to get info about the image - */ -lv_res_t lv_img_decoder_get_info(const void * src, lv_img_header_t * header); - -/** - * Open an image. - * Try the created image decoders one by one. Once one is able to open the image that decoder is saved in `dsc` - * @param dsc describes a decoding session. Simply a pointer to an `lv_img_decoder_dsc_t` variable. - * @param src the image source. Can be - * 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_drv_register())`) - * 2) Variable: Pointer to an `lv_img_dsc_t` variable - * 3) Symbol: E.g. `LV_SYMBOL_OK` - * @param color The color of the image with `LV_IMG_CF_ALPHA_...` - * @param frame_id the index of the frame. Used only with animated images, set 0 for normal images - * @return LV_RES_OK: opened the image. `dsc->img_data` and `dsc->header` are set. - * LV_RES_INV: none of the registered image decoders were able to open the image. - */ -lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, lv_color_t color, int32_t frame_id); - -/** - * Read a line from an opened image - * @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open` - * @param x start X coordinate (from left) - * @param y start Y coordinate (from top) - * @param len number of pixels to read - * @param buf store the data here - * @return LV_RES_OK: success; LV_RES_INV: an error occurred - */ -lv_res_t lv_img_decoder_read_line(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_coord_t len, - uint8_t * buf); - -/** - * Close a decoding session - * @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open` - */ -void lv_img_decoder_close(lv_img_decoder_dsc_t * dsc); - -/** - * Create a new image decoder - * @return pointer to the new image decoder - */ -lv_img_decoder_t * lv_img_decoder_create(void); - -/** - * Delete an image decoder - * @param decoder pointer to an image decoder - */ -void lv_img_decoder_delete(lv_img_decoder_t * decoder); - -/** - * Set a callback to get information about the image - * @param decoder pointer to an image decoder - * @param info_cb a function to collect info about an image (fill an `lv_img_header_t` struct) - */ -void lv_img_decoder_set_info_cb(lv_img_decoder_t * decoder, lv_img_decoder_info_f_t info_cb); - -/** - * Set a callback to open an image - * @param decoder pointer to an image decoder - * @param open_cb a function to open an image - */ -void lv_img_decoder_set_open_cb(lv_img_decoder_t * decoder, lv_img_decoder_open_f_t open_cb); - -/** - * Set a callback to a decoded line of an image - * @param decoder pointer to an image decoder - * @param read_line_cb a function to read a line of an image - */ -void lv_img_decoder_set_read_line_cb(lv_img_decoder_t * decoder, lv_img_decoder_read_line_f_t read_line_cb); - -/** - * Set a callback to close a decoding session. E.g. close files and free other resources. - * @param decoder pointer to an image decoder - * @param close_cb a function to close a decoding session - */ -void lv_img_decoder_set_close_cb(lv_img_decoder_t * decoder, lv_img_decoder_close_f_t close_cb); - -/** - * Get info about a built-in image - * @param decoder the decoder where this function belongs - * @param src the image source: pointer to an `lv_img_dsc_t` variable, a file path or a symbol - * @param header store the image data here - * @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error. - */ -lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header); - -/** - * Open a built in image - * @param decoder the decoder where this function belongs - * @param dsc pointer to decoder descriptor. `src`, `style` are already initialized in it. - * @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error. - */ -lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc); - -/** - * Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`. - * Required only if the "open" function can't return with the whole decoded pixel array. - * @param decoder pointer to the decoder the function associated with - * @param dsc pointer to decoder descriptor - * @param x start x coordinate - * @param y start y coordinate - * @param len number of pixels to decode - * @param buf a buffer to store the decoded pixels - * @return LV_RES_OK: ok; LV_RES_INV: failed - */ -lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x, - lv_coord_t y, lv_coord_t len, uint8_t * buf); - -/** - * Close the pending decoding. Free resources etc. - * @param decoder pointer to the decoder the function associated with - * @param dsc pointer to decoder descriptor - */ -void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc); - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_IMG_DECODER_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/lv_draw_nxp.mk b/lib/libesp32_lvgl/lvgl/src/draw/nxp/lv_draw_nxp.mk deleted file mode 100644 index 18a751eab..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/lv_draw_nxp.mk +++ /dev/null @@ -1,7 +0,0 @@ -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp" - -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp/lv_draw_nxp_pxp.mk -include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite/lv_draw_nxp_vglite.mk diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_buf_pxp.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_buf_pxp.c new file mode 100644 index 000000000..7ba894e12 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_buf_pxp.c @@ -0,0 +1,106 @@ +/** + * @file lv_draw_buf_pxp.c + * + */ + +/** + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_pxp.h" + +#if LV_USE_DRAW_PXP +#include "lv_pxp_cfg.h" +#include "lv_pxp_utils.h" + +#include "lvgl_support.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void _invalidate_cache(void * buf, uint32_t stride, lv_color_format_t cf, const lv_area_t * area); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_buf_pxp_init_handlers(void) +{ + lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers(); + + handlers->invalidate_cache_cb = _invalidate_cache; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void _invalidate_cache(void * buf, uint32_t stride, lv_color_format_t cf, const lv_area_t * area) +{ + if(area->y1 == 0) { + uint16_t size = stride * lv_area_get_height(area); + + /* Invalidate full buffer. */ + DEMO_CleanInvalidateCacheByAddr((void *)buf, size); + return; + } + + const uint8_t * buf_u8 = buf; + /* ARM require a 32 byte aligned address. */ + uint8_t align_bytes = 32; + uint8_t bits_per_pixel = lv_color_format_get_bpp(cf); + + uint16_t align_pixels = align_bytes * 8 / bits_per_pixel; + uint16_t offset_x = 0; + + if(area->x1 >= (int32_t)(area->x1 % align_pixels)) { + uint16_t shift_x = area->x1 - (area->x1 % align_pixels); + + offset_x = area->x1 - shift_x; + buf_u8 += (shift_x * bits_per_pixel) / 8; + } + + if(area->y1) { + uint16_t shift_y = area->y1; + + buf_u8 += shift_y * stride; + } + + /* Area to clear can start from a different offset in buffer. + * Invalidate the area line by line. + */ + uint16_t line_pixels = offset_x + lv_area_get_width(area); + uint16_t line_size = (line_pixels * bits_per_pixel) / 8; + uint16_t area_height = lv_area_get_height(area); + + for(uint16_t y = 0; y < area_height; y++) { + const void * line_addr = buf_u8 + y * stride; + + DEMO_CleanInvalidateCacheByAddr((void *)line_addr, line_size); + } +} + +#endif /*LV_USE_DRAW_PXP*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_nxp_pxp.mk b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_nxp_pxp.mk deleted file mode 100644 index 5c684bcd5..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_nxp_pxp.mk +++ /dev/null @@ -1,9 +0,0 @@ -CSRCS += lv_draw_pxp.c -CSRCS += lv_draw_pxp_blend.c -CSRCS += lv_gpu_nxp_pxp_osa.c -CSRCS += lv_gpu_nxp_pxp.c - -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/pxp" diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp.c index cd70f48b2..3bd0c8ba4 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp.c @@ -4,27 +4,9 @@ */ /** - * MIT License - * - * Copyright 2022, 2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * Copyright 2022-2024 NXP * + * SPDX-License-Identifier: MIT */ /********************* @@ -33,21 +15,19 @@ #include "lv_draw_pxp.h" -#if LV_USE_GPU_NXP_PXP -#include "lv_draw_pxp_blend.h" +#if LV_USE_DRAW_PXP +#include "lv_pxp_cfg.h" +#include "lv_pxp_utils.h" -#if LV_COLOR_DEPTH != 32 - #include "../../../core/lv_refr.h" +#if LV_USE_PARALLEL_DRAW_DEBUG + #include "../../../core/lv_global.h" #endif /********************* * DEFINES *********************/ -/* Minimum area (in pixels) for PXP blit/fill processing. */ -#ifndef LV_GPU_NXP_PXP_SIZE_LIMIT - #define LV_GPU_NXP_PXP_SIZE_LIMIT 5000 -#endif +#define DRAW_UNIT_ID_PXP 3 /********************** * TYPEDEFS @@ -57,21 +37,41 @@ * STATIC PROTOTYPES **********************/ -static void lv_draw_pxp_wait_for_finish(lv_draw_ctx_t * draw_ctx); +/* + * Evaluate a task and set the score and preferred PXP unit. + * Return 1 if task is preferred, 0 otherwise (task is not supported). + */ +static int32_t _pxp_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task); -static void lv_draw_pxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); +/* + * Dispatch a task to the PXP unit. + * Return 1 if task was dispatched, 0 otherwise (task not supported). + */ +static int32_t _pxp_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer); -static void lv_draw_pxp_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, - const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf); +/* + * Delete the PXP draw unit. + */ +static int32_t _pxp_delete(lv_draw_unit_t * draw_unit); -static void lv_draw_pxp_buffer_copy(lv_draw_ctx_t * draw_ctx, - void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area, - void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area); +#if LV_USE_OS + static void _pxp_render_thread_cb(void * ptr); +#endif + +static void _pxp_execute_drawing(lv_draw_pxp_unit_t * u); + +/********************** + * STATIC PROTOTYPES + **********************/ /********************** * STATIC VARIABLES **********************/ +#if LV_USE_PARALLEL_DRAW_DEBUG + #define _draw_info LV_GLOBAL_DEFAULT()->draw_info +#endif + /********************** * MACROS **********************/ @@ -80,196 +80,406 @@ static void lv_draw_pxp_buffer_copy(lv_draw_ctx_t * draw_ctx, * GLOBAL FUNCTIONS **********************/ -void lv_draw_pxp_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) +void lv_draw_pxp_init(void) { - lv_draw_sw_init_ctx(drv, draw_ctx); + lv_draw_buf_pxp_init_handlers(); - lv_draw_pxp_ctx_t * pxp_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx; - pxp_draw_ctx->base_draw.draw_img_decoded = lv_draw_pxp_img_decoded; - pxp_draw_ctx->blend = lv_draw_pxp_blend; - pxp_draw_ctx->base_draw.wait_for_finish = lv_draw_pxp_wait_for_finish; - pxp_draw_ctx->base_draw.buffer_copy = lv_draw_pxp_buffer_copy; + lv_draw_pxp_unit_t * draw_pxp_unit = lv_draw_create_unit(sizeof(lv_draw_pxp_unit_t)); + draw_pxp_unit->base_unit.evaluate_cb = _pxp_evaluate; + draw_pxp_unit->base_unit.dispatch_cb = _pxp_dispatch; + draw_pxp_unit->base_unit.delete_cb = _pxp_delete; + + lv_pxp_init(); + +#if LV_USE_OS + lv_thread_init(&draw_pxp_unit->thread, LV_THREAD_PRIO_HIGH, _pxp_render_thread_cb, 2 * 1024, draw_pxp_unit); +#endif } -void lv_draw_pxp_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) +void lv_draw_pxp_deinit(void) { - lv_draw_sw_deinit_ctx(drv, draw_ctx); + lv_pxp_deinit(); +} + +void lv_draw_pxp_rotate(const void * src_buf, void * dest_buf, int32_t src_width, int32_t src_height, + int32_t src_stride, int32_t dest_stride, lv_display_rotation_t rotation, + lv_color_format_t cf) +{ + lv_pxp_reset(); + + /* convert rotation angle */ + pxp_rotate_degree_t pxp_rotation; + switch(rotation) { + case LV_DISPLAY_ROTATION_0: + pxp_rotation = kPXP_Rotate0; + break; + case LV_DISPLAY_ROTATION_90: + pxp_rotation = kPXP_Rotate90; + break; + case LV_DISPLAY_ROTATION_180: + pxp_rotation = kPXP_Rotate180; + break; + case LV_DISPLAY_ROTATION_270: + pxp_rotation = kPXP_Rotate270; + break; + default: + pxp_rotation = kPXP_Rotate0; + break; + } + PXP_SetRotateConfig(PXP_ID, kPXP_RotateOutputBuffer, pxp_rotation, kPXP_FlipDisable); + + /*Simple blit, no effect - Disable PS buffer*/ + PXP_SetProcessSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); + + /*AS buffer - source image*/ + pxp_as_buffer_config_t asBufferConfig = { + .pixelFormat = pxp_get_as_px_format(cf), + .bufferAddr = (uint32_t)src_buf, + .pitchBytes = src_stride + }; + PXP_SetAlphaSurfaceBufferConfig(PXP_ID, &asBufferConfig); + PXP_SetAlphaSurfacePosition(PXP_ID, 0U, 0U, src_width - 1U, src_height - 1U); + PXP_EnableAlphaSurfaceOverlayColorKey(PXP_ID, false); + + /*Output buffer.*/ + pxp_output_buffer_config_t outputBufferConfig = { + .pixelFormat = pxp_get_out_px_format(cf), + .interlacedMode = kPXP_OutputProgressive, + .buffer0Addr = (uint32_t)dest_buf, + .buffer1Addr = (uint32_t)0U, + .pitchBytes = dest_stride, + .width = src_width, + .height = src_height + }; + PXP_SetOutputBufferConfig(PXP_ID, &outputBufferConfig); + + lv_pxp_run(); } /********************** * STATIC FUNCTIONS **********************/ -/** - * During rendering, LVGL might initializes new draw_ctxs and start drawing into - * a separate buffer (called layer). If the content to be rendered has "holes", - * e.g. rounded corner, LVGL temporarily sets the disp_drv.screen_transp flag. - * It means the renderers should draw into an ARGB buffer. - * With 32 bit color depth it's not a big problem but with 16 bit color depth - * the target pixel format is ARGB8565 which is not supported by the GPU. - * In this case, the PXP callbacks should fallback to SW rendering. - */ -static inline bool need_argb8565_support() +static inline bool _pxp_src_cf_supported(lv_color_format_t cf) { -#if LV_COLOR_DEPTH != 32 - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + bool is_cf_supported = false; - if(disp->driver->screen_transp == 1) - return true; + switch(cf) { + case LV_COLOR_FORMAT_RGB565: + case LV_COLOR_FORMAT_ARGB8888: + case LV_COLOR_FORMAT_XRGB8888: + is_cf_supported = true; + break; + default: + break; + } + + return is_cf_supported; +} + +static inline bool _pxp_dest_cf_supported(lv_color_format_t cf) +{ + bool is_cf_supported = false; + + switch(cf) { + case LV_COLOR_FORMAT_RGB565: + case LV_COLOR_FORMAT_RGB888: + case LV_COLOR_FORMAT_ARGB8888: + case LV_COLOR_FORMAT_XRGB8888: + is_cf_supported = true; + break; + default: + break; + } + + return is_cf_supported; +} + +static bool _pxp_draw_img_supported(const lv_draw_image_dsc_t * draw_dsc) +{ + const lv_image_dsc_t * img_dsc = draw_dsc->src; + + bool has_recolor = (draw_dsc->recolor_opa > LV_OPA_MIN); + bool has_transform = (draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE || + draw_dsc->scale_y != LV_SCALE_NONE); + + /* Recolor and transformation are not supported at the same time. */ + if(has_recolor && has_transform) + return false; + + bool has_opa = (draw_dsc->opa < (lv_opa_t)LV_OPA_MAX); + bool src_has_alpha = (img_dsc->header.cf == LV_COLOR_FORMAT_ARGB8888); + + /* + * Recolor or transformation for images w/ opa or alpha channel can't + * be obtained in a single PXP configuration. Two steps are required. + */ + if((has_recolor || has_transform) && (has_opa || src_has_alpha)) + return false; + + /* PXP can only rotate at 90x angles. */ + if(draw_dsc->rotation % 900) + return false; + + /* + * PXP is set to process 16x16 blocks to optimize the system for memory + * bandwidth and image processing time. + * The output engine essentially truncates any output pixels after the + * desired number of pixels has been written. + * When rotating a source image and the output is not divisible by the block + * size, the incorrect pixels could be truncated and the final output image + * can look shifted. + * + * No combination of rotate with flip, scaling or decimation is possible + * if buffer is unaligned. + */ + if(has_transform && (img_dsc->header.w % 16 || img_dsc->header.h % 16)) + return false; + + return true; +} + +static int32_t _pxp_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t) +{ + LV_UNUSED(u); + + const lv_draw_dsc_base_t * draw_dsc_base = (lv_draw_dsc_base_t *) t->draw_dsc; + + if(!_pxp_dest_cf_supported(draw_dsc_base->layer->color_format)) + return 0; + + switch(t->type) { + case LV_DRAW_TASK_TYPE_FILL: { + const lv_draw_fill_dsc_t * draw_dsc = (lv_draw_fill_dsc_t *) t->draw_dsc; + + /* Most simple case: just a plain rectangle (no radius, no gradient). */ + if((draw_dsc->radius != 0) || (draw_dsc->grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE)) + return 0; + + if(t->preference_score > 70) { + t->preference_score = 70; + t->preferred_draw_unit_id = DRAW_UNIT_ID_PXP; + } + return 1; + } + + case LV_DRAW_TASK_TYPE_LAYER: { + const lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc; + lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src; + + if(!_pxp_src_cf_supported(layer_to_draw->color_format)) + return 0; + + if(!_pxp_draw_img_supported(draw_dsc)) + return 0; + + if(t->preference_score > 70) { + t->preference_score = 70; + t->preferred_draw_unit_id = DRAW_UNIT_ID_PXP; + } + return 1; + } + + case LV_DRAW_TASK_TYPE_IMAGE: { + lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc; + const lv_image_dsc_t * img_dsc = draw_dsc->src; + + if((!_pxp_src_cf_supported(img_dsc->header.cf)) || + (!pxp_buf_aligned(img_dsc->data, img_dsc->header.stride))) + return 0; + + if(!_pxp_draw_img_supported(draw_dsc)) + return 0; + + if(t->preference_score > 70) { + t->preference_score = 70; + t->preferred_draw_unit_id = DRAW_UNIT_ID_PXP; + } + return 1; + } + default: + return 0; + } + + return 0; +} + +static int32_t _pxp_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer) +{ + lv_draw_pxp_unit_t * draw_pxp_unit = (lv_draw_pxp_unit_t *) draw_unit; + + /* Return immediately if it's busy with draw task. */ + if(draw_pxp_unit->task_act) + return 0; + + /* Try to get an ready to draw. */ + lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_PXP); + + if(t == NULL || t->preferred_draw_unit_id != DRAW_UNIT_ID_PXP) + return -1; + + void * buf = lv_draw_layer_alloc_buf(layer); + if(buf == NULL) + return -1; + + t->state = LV_DRAW_TASK_STATE_IN_PROGRESS; + draw_pxp_unit->base_unit.target_layer = layer; + draw_pxp_unit->base_unit.clip_area = &t->clip_area; + draw_pxp_unit->task_act = t; + +#if LV_USE_OS + /* Let the render thread work. */ + if(draw_pxp_unit->inited) + lv_thread_sync_signal(&draw_pxp_unit->sync); +#else + _pxp_execute_drawing(draw_pxp_unit); + + draw_pxp_unit->task_act->state = LV_DRAW_TASK_STATE_READY; + draw_pxp_unit->task_act = NULL; + + /* The draw unit is free now. Request a new dispatching as it can get a new task. */ + lv_draw_dispatch_request(); #endif - return false; + return 1; } -static void lv_draw_pxp_wait_for_finish(lv_draw_ctx_t * draw_ctx) +static int32_t _pxp_delete(lv_draw_unit_t * draw_unit) { - lv_gpu_nxp_pxp_wait(); +#if LV_USE_OS + lv_draw_pxp_unit_t * draw_pxp_unit = (lv_draw_pxp_unit_t *) draw_unit; - lv_draw_sw_wait_for_finish(draw_ctx); -} + LV_LOG_INFO("Cancel PXP draw thread."); + draw_pxp_unit->exit_status = true; -static void lv_draw_pxp_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc) -{ - if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) - return; + if(draw_pxp_unit->inited) + lv_thread_sync_signal(&draw_pxp_unit->sync); - if(need_argb8565_support()) { - lv_draw_sw_blend_basic(draw_ctx, dsc); - return; - } + lv_result_t res = lv_thread_delete(&draw_pxp_unit->thread); - lv_area_t blend_area; - /*Let's get the blend area which is the intersection of the area to draw and the clip area*/ - if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) - return; /*Fully clipped, nothing to do*/ + return res; +#else + LV_UNUSED(draw_unit); - /*Make the blend area relative to the buffer*/ - lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - if(dsc->mask_buf != NULL || dsc->blend_mode != LV_BLEND_MODE_NORMAL || - lv_area_get_size(&blend_area) < LV_GPU_NXP_PXP_SIZE_LIMIT) { - lv_draw_sw_blend_basic(draw_ctx, dsc); - return; - } - - /*Fill/Blend only non masked, normal blended*/ - lv_color_t * dest_buf = draw_ctx->buf; - lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); - const lv_color_t * src_buf = dsc->src_buf; - - if(src_buf == NULL) { - lv_gpu_nxp_pxp_fill(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa); - } - else { - lv_area_t src_area; - src_area.x1 = blend_area.x1 - (dsc->blend_area->x1 - draw_ctx->buf_area->x1); - src_area.y1 = blend_area.y1 - (dsc->blend_area->y1 - draw_ctx->buf_area->y1); - src_area.x2 = src_area.x1 + lv_area_get_width(dsc->blend_area) - 1; - src_area.y2 = src_area.y1 + lv_area_get_height(dsc->blend_area) - 1; - lv_coord_t src_stride = lv_area_get_width(dsc->blend_area); - - lv_gpu_nxp_pxp_blit(dest_buf, &blend_area, dest_stride, src_buf, &src_area, src_stride, - dsc->opa, LV_DISP_ROT_NONE); - } -} - -static void lv_draw_pxp_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, - const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf) -{ - if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) - return; - - if(need_argb8565_support()) { - lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf); - return; - } - - const lv_color_t * src_buf = (const lv_color_t *)map_p; - if(!src_buf) { - lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf); - return; - } - - lv_area_t rel_coords; - lv_area_copy(&rel_coords, coords); - lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - - lv_area_t rel_clip_area; - lv_area_copy(&rel_clip_area, draw_ctx->clip_area); - lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - - bool has_scale = (dsc->zoom != LV_IMG_ZOOM_NONE); - bool has_rotation = (dsc->angle != 0); - bool unsup_rotation = false; - - lv_area_t blend_area; - if(has_rotation) - lv_area_copy(&blend_area, &rel_coords); - else if(!_lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area)) - return; /*Fully clipped, nothing to do*/ - - bool has_mask = lv_draw_mask_is_any(&blend_area); - lv_coord_t src_width = lv_area_get_width(coords); - lv_coord_t src_height = lv_area_get_height(coords); - - if(has_rotation) { - /* - * PXP can only rotate at 90x angles. - */ - if(dsc->angle % 900) { - PXP_LOG_TRACE("Rotation angle %d is not supported. PXP can rotate only 90x angle.", dsc->angle); - unsup_rotation = true; - } - - /* - * PXP is set to process 16x16 blocks to optimize the system for memory - * bandwidth and image processing time. - * The output engine essentially truncates any output pixels after the - * desired number of pixels has been written. - * When rotating a source image and the output is not divisible by the block - * size, the incorrect pixels could be truncated and the final output image - * can look shifted. - */ - if(src_width % 16 || src_height % 16) { - PXP_LOG_TRACE("Rotation is not supported for image w/o alignment to block size 16x16."); - unsup_rotation = true; - } - } - - if(has_mask || has_scale || unsup_rotation || lv_area_get_size(&blend_area) < LV_GPU_NXP_PXP_SIZE_LIMIT -#if LV_COLOR_DEPTH != 32 - || lv_img_cf_has_alpha(cf) + return 0; #endif - ) { - lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf); - return; - } - - lv_color_t * dest_buf = draw_ctx->buf; - lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); - - lv_area_t src_area; - src_area.x1 = blend_area.x1 - (coords->x1 - draw_ctx->buf_area->x1); - src_area.y1 = blend_area.y1 - (coords->y1 - draw_ctx->buf_area->y1); - src_area.x2 = src_area.x1 + src_width - 1; - src_area.y2 = src_area.y1 + src_height - 1; - lv_coord_t src_stride = lv_area_get_width(coords); - - lv_gpu_nxp_pxp_blit_transform(dest_buf, &blend_area, dest_stride, src_buf, &src_area, src_stride, - dsc, cf); } -static void lv_draw_pxp_buffer_copy(lv_draw_ctx_t * draw_ctx, - void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area, - void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area) +static void _pxp_execute_drawing(lv_draw_pxp_unit_t * u) { - LV_UNUSED(draw_ctx); + lv_draw_task_t * t = u->task_act; + lv_draw_unit_t * draw_unit = (lv_draw_unit_t *)u; + lv_layer_t * layer = draw_unit->target_layer; + lv_draw_buf_t * draw_buf = layer->draw_buf; - if(lv_area_get_size(dest_area) < LV_GPU_NXP_PXP_SIZE_LIMIT) { - lv_draw_sw_buffer_copy(draw_ctx, dest_buf, dest_stride, dest_area, src_buf, src_stride, src_area); - return; + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, &t->area, draw_unit->clip_area)) + return; /*Fully clipped, nothing to do*/ + + /* Make area relative to the buffer */ + lv_area_move(&draw_area, -layer->buf_area.x1, -layer->buf_area.y1); + + /* Invalidate only the drawing area */ + lv_draw_buf_invalidate_cache(draw_buf->data, draw_buf->header.stride, draw_buf->header.cf, &draw_area); + + switch(t->type) { + case LV_DRAW_TASK_TYPE_FILL: + lv_draw_pxp_fill(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_IMAGE: + lv_draw_pxp_img(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_LAYER: + lv_draw_pxp_layer(draw_unit, t->draw_dsc, &t->area); + break; + default: + break; } - lv_gpu_nxp_pxp_buffer_copy(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride); +#if LV_USE_PARALLEL_DRAW_DEBUG + /*Layers manage it for themselves*/ + if(t->type != LV_DRAW_TASK_TYPE_LAYER) { + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, &t->area, u->base_unit.clip_area)) + return; + + int32_t idx = 0; + lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head; + while(draw_unit_tmp != (lv_draw_unit_t *)u) { + draw_unit_tmp = draw_unit_tmp->next; + idx++; + } + lv_draw_rect_dsc_t rect_dsc; + lv_draw_rect_dsc_init(&rect_dsc); + rect_dsc.bg_color = lv_palette_main(idx % _LV_PALETTE_LAST); + rect_dsc.border_color = rect_dsc.bg_color; + rect_dsc.bg_opa = LV_OPA_10; + rect_dsc.border_opa = LV_OPA_80; + rect_dsc.border_width = 1; + lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &draw_area); + + lv_point_t txt_size; + lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE); + + lv_area_t txt_area; + txt_area.x1 = draw_area.x1; + txt_area.y1 = draw_area.y1; + txt_area.x2 = draw_area.x1 + txt_size.x - 1; + txt_area.y2 = draw_area.y1 + txt_size.y - 1; + + lv_draw_rect_dsc_init(&rect_dsc); + rect_dsc.bg_color = lv_color_white(); + lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &txt_area); + + char buf[8]; + lv_snprintf(buf, sizeof(buf), "%d", idx); + lv_draw_label_dsc_t label_dsc; + lv_draw_label_dsc_init(&label_dsc); + label_dsc.color = lv_color_black(); + label_dsc.text = buf; + lv_draw_sw_label((lv_draw_unit_t *)u, &label_dsc, &txt_area); + } +#endif } -#endif /*LV_USE_GPU_NXP_PXP*/ +#if LV_USE_OS +static void _pxp_render_thread_cb(void * ptr) +{ + lv_draw_pxp_unit_t * u = ptr; + + lv_thread_sync_init(&u->sync); + u->inited = true; + + while(1) { + /* Wait for sync if there is no task set. */ + while(u->task_act == NULL) { + if(u->exit_status) + break; + + lv_thread_sync_wait(&u->sync); + } + + if(u->exit_status) { + LV_LOG_INFO("Ready to exit PXP draw thread."); + break; + } + + _pxp_execute_drawing(u); + + /* Signal the ready state to dispatcher. */ + u->task_act->state = LV_DRAW_TASK_STATE_READY; + + /* Cleanup. */ + u->task_act = NULL; + + /* The draw unit is free now. Request a new dispatching as it can get a new task. */ + lv_draw_dispatch_request(); + } + + u->inited = false; + lv_thread_sync_delete(&u->sync); + LV_LOG_INFO("Exit PXP draw thread."); +} +#endif + +#endif /*LV_USE_DRAW_PXP*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp.h index 1ace3bca4..d5e98d791 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp.h @@ -4,27 +4,9 @@ */ /** - * MIT License - * - * Copyright 2022, 2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * Copyright 2022-2024 NXP * + * SPDX-License-Identifier: MIT */ #ifndef LV_DRAW_PXP_H @@ -40,7 +22,7 @@ extern "C" { #include "../../../lv_conf_internal.h" -#if LV_USE_GPU_NXP_PXP +#if LV_USE_DRAW_PXP #include "../../sw/lv_draw_sw.h" /********************* @@ -50,20 +32,36 @@ extern "C" { /********************** * TYPEDEFS **********************/ -typedef lv_draw_sw_ctx_t lv_draw_pxp_ctx_t; + +typedef lv_draw_sw_unit_t lv_draw_pxp_unit_t; /********************** * GLOBAL PROTOTYPES **********************/ -void lv_draw_pxp_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); +void lv_draw_buf_pxp_init_handlers(void); -void lv_draw_pxp_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); +void lv_draw_pxp_init(void); + +void lv_draw_pxp_deinit(void); + +void lv_draw_pxp_rotate(const void * src_buf, void * dest_buf, int32_t src_width, int32_t src_height, + int32_t src_stride, int32_t dest_stride, lv_display_rotation_t rotation, + lv_color_format_t cf); + +void lv_draw_pxp_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_pxp_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_pxp_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords); /********************** * MACROS **********************/ -#endif /*LV_USE_GPU_NXP_PXP*/ +#endif /*LV_USE_DRAW_PXP*/ #ifdef __cplusplus } /*extern "C"*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.c deleted file mode 100644 index 82925769a..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.c +++ /dev/null @@ -1,573 +0,0 @@ -/** - * @file lv_draw_pxp_blend.c - * - */ - -/** - * MIT License - * - * Copyright 2020-2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "lv_draw_pxp_blend.h" - -#if LV_USE_GPU_NXP_PXP -#include "lvgl_support.h" - -/********************* - * DEFINES - *********************/ - -#if LV_COLOR_16_SWAP - #error Color swap not implemented. Disable LV_COLOR_16_SWAP feature. -#endif - -#if LV_COLOR_DEPTH == 16 - #define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatRGB565 - #define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatRGB565 - #define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB565 - #define PXP_TEMP_BUF_SIZE LCD_WIDTH * LCD_HEIGHT * 2U -#elif LV_COLOR_DEPTH == 32 - #define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatARGB8888 - #define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatARGB8888 - #if (!(defined(FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT) && FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT)) && \ - (!(defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3)) - #define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatARGB8888 - #else - #define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB888 - #endif - #define PXP_TEMP_BUF_SIZE LCD_WIDTH * LCD_HEIGHT * 4U -#elif - #error Only 16bit and 32bit color depth are supported. Set LV_COLOR_DEPTH to 16 or 32. -#endif - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -static LV_ATTRIBUTE_MEM_ALIGN uint8_t temp_buf[PXP_TEMP_BUF_SIZE]; - -/** - * BLock Image Transfer - copy rectangular image from src buffer to dst buffer - * with combination of transformation (rotation, scale, recolor) and opacity, alpha channel - * or color keying. This requires two steps. First step is used for transformation into - * a temporary buffer and the second one will handle the color format or opacity. - * - * @param[in/out] dest_buf Destination buffer - * @param[in] dest_area Area with relative coordinates of destination buffer - * @param[in] dest_stride Stride of destination buffer in pixels - * @param[in] src_buf Source buffer - * @param[in] src_area Area with relative coordinates of source buffer - * @param[in] src_stride Stride of source buffer in pixels - * @param[in] dsc Image descriptor - * @param[in] cf Color format - */ -static void lv_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, - const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf); - -/** - * BLock Image Transfer - copy rectangular image from src buffer to dst buffer - * with transformation and full opacity. - * - * @param[in/out] dest_buf Destination buffer - * @param[in] dest_area Area with relative coordinates of destination buffer - * @param[in] dest_stride Stride of destination buffer in pixels - * @param[in] src_buf Source buffer - * @param[in] src_area Area with relative coordinates of source buffer - * @param[in] src_stride Stride of source buffer in pixels - * @param[in] dsc Image descriptor - * @param[in] cf Color format - */ -static void lv_pxp_blit_cover(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, - const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf); - -/** - * BLock Image Transfer - copy rectangular image from src buffer to dst buffer - * without transformation but handling color format or opacity. - * - * @param[in/out] dest_buf Destination buffer - * @param[in] dest_area Area with relative coordinates of destination buffer - * @param[in] dest_stride Stride of destination buffer in pixels - * @param[in] src_buf Source buffer - * @param[in] src_area Area with relative coordinates of source buffer - * @param[in] src_stride Stride of source buffer in pixels - * @param[in] dsc Image descriptor - * @param[in] cf Color format - */ -static void lv_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, - const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf); - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - lv_color_t color, lv_opa_t opa) -{ - lv_coord_t dest_w = lv_area_get_width(dest_area); - lv_coord_t dest_h = lv_area_get_height(dest_area); - - lv_gpu_nxp_pxp_reset(); - - /*OUT buffer configure*/ - pxp_output_buffer_config_t outputConfig = { - .pixelFormat = PXP_OUT_PIXEL_FORMAT, - .interlacedMode = kPXP_OutputProgressive, - .buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1), - .buffer1Addr = (uint32_t)NULL, - .pitchBytes = dest_stride * sizeof(lv_color_t), - .width = dest_w, - .height = dest_h - }; - - PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputConfig); - - if(opa >= (lv_opa_t)LV_OPA_MAX) { - /*Simple color fill without opacity - AS disabled*/ - PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); - - } - else { - /*Fill with opacity - AS used as source (same as OUT)*/ - pxp_as_buffer_config_t asBufferConfig = { - .pixelFormat = PXP_AS_PIXEL_FORMAT, - .bufferAddr = (uint32_t)outputConfig.buffer0Addr, - .pitchBytes = outputConfig.pitchBytes - }; - - PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig); - PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U); - } - - /*Disable PS, use as color generator*/ - PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); - PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(color)); - - /** - * Configure Porter-Duff blending - src settings are unused for fill without opacity (opa = 0xff). - * - * Note: srcFactorMode and dstFactorMode are inverted in fsl_pxp.h: - * srcFactorMode is actually applied on PS alpha value - * dstFactorMode is actually applied on AS alpha value - */ - pxp_porter_duff_config_t pdConfig = { - .enable = 1, - .dstColorMode = kPXP_PorterDuffColorNoAlpha, - .srcColorMode = kPXP_PorterDuffColorNoAlpha, - .dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha, - .srcGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha, - .dstFactorMode = kPXP_PorterDuffFactorStraight, - .srcFactorMode = (opa >= (lv_opa_t)LV_OPA_MAX) ? kPXP_PorterDuffFactorStraight : kPXP_PorterDuffFactorInversed, - .dstGlobalAlpha = opa, - .srcGlobalAlpha = opa, - .dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/ - .srcAlphaMode = kPXP_PorterDuffAlphaStraight /*don't care*/ - }; - - PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig); - - lv_gpu_nxp_pxp_run(); -} - -void lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, - lv_opa_t opa, lv_disp_rot_t angle) -{ - lv_coord_t dest_w = lv_area_get_width(dest_area); - lv_coord_t dest_h = lv_area_get_height(dest_area); - lv_coord_t src_w = lv_area_get_width(src_area); - lv_coord_t src_h = lv_area_get_height(src_area); - - lv_gpu_nxp_pxp_reset(); - - /* convert rotation angle */ - pxp_rotate_degree_t pxp_rot; - switch(angle) { - case LV_DISP_ROT_NONE: - pxp_rot = kPXP_Rotate0; - break; - case LV_DISP_ROT_90: - pxp_rot = kPXP_Rotate90; - break; - case LV_DISP_ROT_180: - pxp_rot = kPXP_Rotate180; - break; - case LV_DISP_ROT_270: - pxp_rot = kPXP_Rotate270; - break; - default: - pxp_rot = kPXP_Rotate0; - break; - } - PXP_SetRotateConfig(LV_GPU_NXP_PXP_ID, kPXP_RotateOutputBuffer, pxp_rot, kPXP_FlipDisable); - - pxp_as_blend_config_t asBlendConfig = { - .alpha = opa, - .invertAlpha = false, - .alphaMode = kPXP_AlphaRop, - .ropMode = kPXP_RopMergeAs - }; - - if(opa >= (lv_opa_t)LV_OPA_MAX) { - /*Simple blit, no effect - Disable PS buffer*/ - PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); - } - else { - pxp_ps_buffer_config_t psBufferConfig = { - .pixelFormat = PXP_PS_PIXEL_FORMAT, - .swapByte = false, - .bufferAddr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1), - .bufferAddrU = 0U, - .bufferAddrV = 0U, - .pitchBytes = dest_stride * sizeof(lv_color_t) - }; - - asBlendConfig.alphaMode = kPXP_AlphaOverride; - - PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig); - PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U); - } - - /*AS buffer - source image*/ - pxp_as_buffer_config_t asBufferConfig = { - .pixelFormat = PXP_AS_PIXEL_FORMAT, - .bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_area->x1), - .pitchBytes = src_stride * sizeof(lv_color_t) - }; - PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig); - PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U); - PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig); - PXP_EnableAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, false); - - /*Output buffer.*/ - pxp_output_buffer_config_t outputBufferConfig = { - .pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT, - .interlacedMode = kPXP_OutputProgressive, - .buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1), - .buffer1Addr = (uint32_t)0U, - .pitchBytes = dest_stride * sizeof(lv_color_t), - .width = dest_w, - .height = dest_h - }; - PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig); - - lv_gpu_nxp_pxp_run(); -} - -void lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, - const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf) -{ - bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP); - bool has_rotation = (dsc->angle != 0); - - if(has_recolor || has_rotation) { - if(dsc->opa >= (lv_opa_t)LV_OPA_MAX && !lv_img_cf_has_alpha(cf) && !lv_img_cf_is_chroma_keyed(cf)) { - lv_pxp_blit_cover(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, dsc, cf); - return; - } - else { - /*Recolor and/or rotation with alpha or opacity is done in two steps.*/ - lv_pxp_blit_opa(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, dsc, cf); - return; - } - } - - lv_pxp_blit_cf(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, dsc, cf); -} - -void lv_gpu_nxp_pxp_buffer_copy(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride) -{ - lv_coord_t src_width = lv_area_get_width(src_area); - lv_coord_t src_height = lv_area_get_height(src_area); - - lv_gpu_nxp_pxp_reset(); - - const pxp_pic_copy_config_t picCopyConfig = { - .srcPicBaseAddr = (uint32_t)src_buf, - .srcPitchBytes = src_stride * sizeof(lv_color_t), - .srcOffsetX = src_area->x1, - .srcOffsetY = src_area->y1, - .destPicBaseAddr = (uint32_t)dest_buf, - .destPitchBytes = dest_stride * sizeof(lv_color_t), - .destOffsetX = dest_area->x1, - .destOffsetY = dest_area->y1, - .width = src_width, - .height = src_height, - .pixelFormat = PXP_AS_PIXEL_FORMAT - }; - - PXP_StartPictureCopy(LV_GPU_NXP_PXP_ID, &picCopyConfig); - - lv_gpu_nxp_pxp_wait(); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void lv_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, - const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf) -{ - lv_area_t temp_area; - lv_area_copy(&temp_area, dest_area); - lv_coord_t temp_stride = dest_stride; - lv_coord_t temp_w = lv_area_get_width(&temp_area); - lv_coord_t temp_h = lv_area_get_height(&temp_area); - - /*Step 1: Transform with full opacity to temporary buffer*/ - lv_pxp_blit_cover((lv_color_t *)temp_buf, &temp_area, temp_stride, src_buf, src_area, src_stride, dsc, cf); - - /*Switch width and height if angle requires it*/ - if(dsc->angle == 900 || dsc->angle == 2700) { - temp_area.x2 = temp_area.x1 + temp_h - 1; - temp_area.y2 = temp_area.y1 + temp_w - 1; - } - - /*Step 2: Blit temporary result with required opacity to output*/ - lv_pxp_blit_cf(dest_buf, &temp_area, dest_stride, (lv_color_t *)temp_buf, &temp_area, temp_stride, dsc, cf); -} -static void lv_pxp_blit_cover(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, - const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf) -{ - lv_coord_t dest_w = lv_area_get_width(dest_area); - lv_coord_t dest_h = lv_area_get_height(dest_area); - lv_coord_t src_w = lv_area_get_width(src_area); - lv_coord_t src_h = lv_area_get_height(src_area); - - bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP); - bool has_rotation = (dsc->angle != 0); - - lv_point_t pivot = dsc->pivot; - lv_coord_t piv_offset_x; - lv_coord_t piv_offset_y; - - lv_gpu_nxp_pxp_reset(); - - if(has_rotation) { - /*Convert rotation angle and calculate offsets caused by pivot*/ - pxp_rotate_degree_t pxp_angle; - switch(dsc->angle) { - case 0: - pxp_angle = kPXP_Rotate0; - piv_offset_x = 0; - piv_offset_y = 0; - break; - case 900: - piv_offset_x = pivot.x + pivot.y - dest_h; - piv_offset_y = pivot.y - pivot.x; - pxp_angle = kPXP_Rotate90; - break; - case 1800: - piv_offset_x = 2 * pivot.x - dest_w; - piv_offset_y = 2 * pivot.y - dest_h; - pxp_angle = kPXP_Rotate180; - break; - case 2700: - piv_offset_x = pivot.x - pivot.y; - piv_offset_y = pivot.x + pivot.y - dest_w; - pxp_angle = kPXP_Rotate270; - break; - default: - piv_offset_x = 0; - piv_offset_y = 0; - pxp_angle = kPXP_Rotate0; - } - PXP_SetRotateConfig(LV_GPU_NXP_PXP_ID, kPXP_RotateOutputBuffer, pxp_angle, kPXP_FlipDisable); - lv_area_move(dest_area, piv_offset_x, piv_offset_y); - } - - /*AS buffer - source image*/ - pxp_as_buffer_config_t asBufferConfig = { - .pixelFormat = PXP_AS_PIXEL_FORMAT, - .bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_area->x1), - .pitchBytes = src_stride * sizeof(lv_color_t) - }; - PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig); - PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U); - - /*Disable PS buffer*/ - PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); - if(has_recolor) - /*Use as color generator*/ - PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(dsc->recolor)); - - /*Output buffer*/ - pxp_output_buffer_config_t outputBufferConfig = { - .pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT, - .interlacedMode = kPXP_OutputProgressive, - .buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1), - .buffer1Addr = (uint32_t)0U, - .pitchBytes = dest_stride * sizeof(lv_color_t), - .width = dest_w, - .height = dest_h - }; - PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig); - - if(has_recolor || lv_img_cf_has_alpha(cf)) { - /** - * Configure Porter-Duff blending. - * - * Note: srcFactorMode and dstFactorMode are inverted in fsl_pxp.h: - * srcFactorMode is actually applied on PS alpha value - * dstFactorMode is actually applied on AS alpha value - */ - pxp_porter_duff_config_t pdConfig = { - .enable = 1, - .dstColorMode = kPXP_PorterDuffColorWithAlpha, - .srcColorMode = kPXP_PorterDuffColorNoAlpha, - .dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha, - .srcGlobalAlphaMode = lv_img_cf_has_alpha(cf) ? kPXP_PorterDuffLocalAlpha : kPXP_PorterDuffGlobalAlpha, - .dstFactorMode = kPXP_PorterDuffFactorStraight, - .srcFactorMode = kPXP_PorterDuffFactorInversed, - .dstGlobalAlpha = has_recolor ? dsc->recolor_opa : 0x00, - .srcGlobalAlpha = 0xff, - .dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/ - .srcAlphaMode = kPXP_PorterDuffAlphaStraight - }; - PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig); - } - - lv_gpu_nxp_pxp_run(); -} - -static void lv_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, - const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf) -{ - lv_coord_t dest_w = lv_area_get_width(dest_area); - lv_coord_t dest_h = lv_area_get_height(dest_area); - lv_coord_t src_w = lv_area_get_width(src_area); - lv_coord_t src_h = lv_area_get_height(src_area); - - lv_gpu_nxp_pxp_reset(); - - pxp_as_blend_config_t asBlendConfig = { - .alpha = dsc->opa, - .invertAlpha = false, - .alphaMode = kPXP_AlphaRop, - .ropMode = kPXP_RopMergeAs - }; - - if(dsc->opa >= (lv_opa_t)LV_OPA_MAX && !lv_img_cf_is_chroma_keyed(cf) && !lv_img_cf_has_alpha(cf)) { - /*Simple blit, no effect - Disable PS buffer*/ - PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); - } - else { - /*PS must be enabled to fetch background pixels. - PS and OUT buffers are the same, blend will be done in-place*/ - pxp_ps_buffer_config_t psBufferConfig = { - .pixelFormat = PXP_PS_PIXEL_FORMAT, - .swapByte = false, - .bufferAddr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1), - .bufferAddrU = 0U, - .bufferAddrV = 0U, - .pitchBytes = dest_stride * sizeof(lv_color_t) - }; - if(dsc->opa >= (lv_opa_t)LV_OPA_MAX) { - asBlendConfig.alphaMode = lv_img_cf_has_alpha(cf) ? kPXP_AlphaEmbedded : kPXP_AlphaOverride; - } - else { - asBlendConfig.alphaMode = lv_img_cf_has_alpha(cf) ? kPXP_AlphaMultiply : kPXP_AlphaOverride; - } - PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig); - PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U); - } - - /*AS buffer - source image*/ - pxp_as_buffer_config_t asBufferConfig = { - .pixelFormat = PXP_AS_PIXEL_FORMAT, - .bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_area->x1), - .pitchBytes = src_stride * sizeof(lv_color_t) - }; - PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig); - PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U); - PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig); - - if(lv_img_cf_is_chroma_keyed(cf)) { - lv_color_t colorKeyLow = LV_COLOR_CHROMA_KEY; - lv_color_t colorKeyHigh = LV_COLOR_CHROMA_KEY; - - bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP); - - if(has_recolor) { - /* New color key after recoloring */ - lv_color_t colorKey = lv_color_mix(dsc->recolor, LV_COLOR_CHROMA_KEY, dsc->recolor_opa); - - LV_COLOR_SET_R(colorKeyLow, colorKey.ch.red != 0 ? colorKey.ch.red - 1 : 0); - LV_COLOR_SET_G(colorKeyLow, colorKey.ch.green != 0 ? colorKey.ch.green - 1 : 0); - LV_COLOR_SET_B(colorKeyLow, colorKey.ch.blue != 0 ? colorKey.ch.blue - 1 : 0); - -#if LV_COLOR_DEPTH == 16 - LV_COLOR_SET_R(colorKeyHigh, colorKey.ch.red != 0x1f ? colorKey.ch.red + 1 : 0x1f); - LV_COLOR_SET_G(colorKeyHigh, colorKey.ch.green != 0x3f ? colorKey.ch.green + 1 : 0x3f); - LV_COLOR_SET_B(colorKeyHigh, colorKey.ch.blue != 0x1f ? colorKey.ch.blue + 1 : 0x1f); -#else /*LV_COLOR_DEPTH == 32*/ - LV_COLOR_SET_R(colorKeyHigh, colorKey.ch.red != 0xff ? colorKey.ch.red + 1 : 0xff); - LV_COLOR_SET_G(colorKeyHigh, colorKey.ch.green != 0xff ? colorKey.ch.green + 1 : 0xff); - LV_COLOR_SET_B(colorKeyHigh, colorKey.ch.blue != 0xff ? colorKey.ch.blue + 1 : 0xff); -#endif - } - - PXP_SetAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, lv_color_to32(colorKeyLow), - lv_color_to32(colorKeyHigh)); - } - - PXP_EnableAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, lv_img_cf_is_chroma_keyed(cf)); - - /*Output buffer.*/ - pxp_output_buffer_config_t outputBufferConfig = { - .pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT, - .interlacedMode = kPXP_OutputProgressive, - .buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1), - .buffer1Addr = (uint32_t)0U, - .pitchBytes = dest_stride * sizeof(lv_color_t), - .width = dest_w, - .height = dest_h - }; - PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig); - - lv_gpu_nxp_pxp_run(); -} - -#endif /*LV_USE_GPU_NXP_PXP*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.h deleted file mode 100644 index 961566726..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.h +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @file lv_draw_pxp_blend.h - * - */ - -/** - * MIT License - * - * Copyright 2020-2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef LV_DRAW_PXP_BLEND_H -#define LV_DRAW_PXP_BLEND_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ - -#include "../../../lv_conf_internal.h" - -#if LV_USE_GPU_NXP_PXP -#include "lv_gpu_nxp_pxp.h" -#include "../../sw/lv_draw_sw.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Fill area, with optional opacity. - * - * @param[in/out] dest_buf Destination buffer - * @param[in] dest_area Area with relative coordinates of destination buffer - * @param[in] dest_stride Stride of destination buffer in pixels - * @param[in] color Color - * @param[in] opa Opacity - */ -void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - lv_color_t color, lv_opa_t opa); - -/** - * BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects. - * By default, image is copied directly, with optional opacity. This function can also - * rotate the display output buffer to a specified angle (90x step). - * - * @param[in/out] dest_buf Destination buffer - * @param[in] dest_area Area with relative coordinates of destination buffer - * @param[in] dest_stride Stride of destination buffer in pixels - * @param[in] src_buf Source buffer - * @param[in] src_area Source area with relative coordinates of source buffer - * @param[in] src_stride Stride of source buffer in pixels - * @param[in] opa Opacity - * @param[in] angle Display rotation angle (90x) - */ -void lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, - lv_opa_t opa, lv_disp_rot_t angle); - -/** - * BLock Image Transfer - copy rectangular image from src_buf to dst_buf with transformation. - * - * - * @param[in/out] dest_buf Destination buffer - * @param[in] dest_area Area with relative coordinates of destination buffer - * @param[in] dest_stride Stride of destination buffer in pixels - * @param[in] src_buf Source buffer - * @param[in] src_area Area with relative coordinates of source buffer - * @param[in] src_stride Stride of source buffer in pixels - * @param[in] dsc Image descriptor - * @param[in] cf Color format - */ -void lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, - const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf); - -/** - * BLock Image Transfer - copy rectangular image from src_buf to dst_buf, no transformation or blending. - * - * - * @param[in/out] dest_buf Destination buffer - * @param[in] dest_area Area with relative coordinates of destination buffer - * @param[in] dest_stride Stride of destination buffer in pixels - * @param[in] src_buf Source buffer - * @param[in] src_area Area with relative coordinates of source buffer - * @param[in] src_stride Stride of source buffer in pixels - */ -void lv_gpu_nxp_pxp_buffer_copy(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_GPU_NXP_PXP*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_PXP_BLEND_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_fill.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_fill.c new file mode 100644 index 000000000..60873ede0 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_fill.c @@ -0,0 +1,147 @@ +/** + * @file lv_draw_pxp_fill.c + * + */ + +/** + * Copyright 2020-2024 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_pxp.h" + +#if LV_USE_DRAW_PXP +#include "lv_pxp_cfg.h" +#include "lv_pxp_utils.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void _pxp_fill(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride, + lv_color_format_t dest_cf, const lv_draw_fill_dsc_t * dsc); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_pxp_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, + const lv_area_t * coords) +{ + if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) + return; + + lv_layer_t * layer = draw_unit->target_layer; + lv_draw_buf_t * draw_buf = layer->draw_buf; + + lv_area_t rel_coords; + lv_area_copy(&rel_coords, coords); + lv_area_move(&rel_coords, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t rel_clip_area; + lv_area_copy(&rel_clip_area, draw_unit->clip_area); + lv_area_move(&rel_clip_area, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t blend_area; + if(!_lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area)) + return; /*Fully clipped, nothing to do*/ + + _pxp_fill(draw_buf->data, &blend_area, draw_buf->header.stride, draw_buf->header.cf, dsc); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void _pxp_fill(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride, + lv_color_format_t dest_cf, const lv_draw_fill_dsc_t * dsc) +{ + int32_t dest_w = lv_area_get_width(dest_area); + int32_t dest_h = lv_area_get_height(dest_area); + + lv_pxp_reset(); + + uint8_t px_size = lv_color_format_get_size(dest_cf); + + /*OUT buffer configure*/ + pxp_output_buffer_config_t outputConfig = { + .pixelFormat = pxp_get_out_px_format(dest_cf), + .interlacedMode = kPXP_OutputProgressive, + .buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + px_size * dest_area->x1), + .buffer1Addr = (uint32_t)NULL, + .pitchBytes = dest_stride, + .width = dest_w, + .height = dest_h + }; + + PXP_SetOutputBufferConfig(PXP_ID, &outputConfig); + + if(dsc->opa >= (lv_opa_t)LV_OPA_MAX) { + /*Simple color fill without opacity - AS disabled*/ + PXP_SetAlphaSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); + + } + else { + /*Fill with opacity - AS used as source (same as OUT)*/ + pxp_as_buffer_config_t asBufferConfig = { + .pixelFormat = pxp_get_as_px_format(dest_cf), + .bufferAddr = outputConfig.buffer0Addr, + .pitchBytes = outputConfig.pitchBytes + }; + + PXP_SetAlphaSurfaceBufferConfig(PXP_ID, &asBufferConfig); + PXP_SetAlphaSurfacePosition(PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U); + } + + /*Disable PS, use as color generator*/ + PXP_SetProcessSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); + PXP_SetProcessSurfaceBackGroundColor(PXP_ID, lv_color_to_u32(dsc->color)); + + /** + * Configure Porter-Duff blending - src settings are unused for fill without opacity (opa = 0xff). + * + * Note: srcFactorMode and dstFactorMode are inverted in fsl_pxp.h: + * srcFactorMode is actually applied on PS alpha value + * dstFactorMode is actually applied on AS alpha value + */ + pxp_porter_duff_config_t pdConfig = { + .enable = 1, + .dstColorMode = kPXP_PorterDuffColorNoAlpha, + .srcColorMode = kPXP_PorterDuffColorNoAlpha, + .dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha, + .srcGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha, + .dstFactorMode = kPXP_PorterDuffFactorStraight, + .srcFactorMode = (dsc->opa >= (lv_opa_t)LV_OPA_MAX) ? kPXP_PorterDuffFactorStraight : kPXP_PorterDuffFactorInversed, + .dstGlobalAlpha = dsc->opa, + .srcGlobalAlpha = dsc->opa, + .dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/ + .srcAlphaMode = kPXP_PorterDuffAlphaStraight /*don't care*/ + }; + + PXP_SetPorterDuffConfig(PXP_ID, &pdConfig); + + lv_pxp_run(); +} + +#endif /*LV_USE_DRAW_PXP*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_img.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_img.c new file mode 100644 index 000000000..9e5205667 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_img.c @@ -0,0 +1,365 @@ +/** + * @file lv_draw_pxp_img.c + * + */ + +/** + * Copyright 2020-2024 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_pxp.h" + +#if LV_USE_DRAW_PXP +#include "lv_pxp_cfg.h" +#include "lv_pxp_utils.h" + +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/* Blit w/ recolor for images w/o opa and alpha channel */ +static void _pxp_blit_recolor(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride, + lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area, + int32_t src_stride, lv_color_format_t src_cf, const lv_draw_image_dsc_t * dsc); + +/* Blit w/ transformation for images w/o opa and alpha channel */ +static void _pxp_blit_transform(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride, + lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area, + int32_t src_stride, lv_color_format_t src_cf, const lv_draw_image_dsc_t * dsc); + +/* Blit simple w/ opa and alpha channel */ +static void _pxp_blit(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride, + lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area, + int32_t src_stride, lv_color_format_t src_cf, lv_opa_t opa); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_pxp_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc, + const lv_area_t * coords) +{ + if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) + return; + + lv_layer_t * layer = draw_unit->target_layer; + lv_draw_buf_t * draw_buf = layer->draw_buf; + const lv_image_dsc_t * img_dsc = dsc->src; + + lv_area_t rel_coords; + lv_area_copy(&rel_coords, coords); + lv_area_move(&rel_coords, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t rel_clip_area; + lv_area_copy(&rel_clip_area, draw_unit->clip_area); + lv_area_move(&rel_clip_area, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t blend_area; + bool has_transform = (dsc->rotation != 0 || dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE); + if(has_transform) + lv_area_copy(&blend_area, &rel_coords); + else if(!_lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area)) + return; /*Fully clipped, nothing to do*/ + + const uint8_t * src_buf = img_dsc->data; + + lv_area_t src_area; + src_area.x1 = blend_area.x1 - (coords->x1 - layer->buf_area.x1); + src_area.y1 = blend_area.y1 - (coords->y1 - layer->buf_area.y1); + src_area.x2 = src_area.x1 + lv_area_get_width(coords) - 1; + src_area.y2 = src_area.y1 + lv_area_get_height(coords) - 1; + int32_t src_stride = img_dsc->header.stride; + lv_color_format_t src_cf = img_dsc->header.cf; + + uint8_t * dest_buf = draw_buf->data; + int32_t dest_stride = draw_buf->header.stride; + lv_color_format_t dest_cf = draw_buf->header.cf; + bool has_recolor = (dsc->recolor_opa > LV_OPA_MIN); + + if(has_recolor && !has_transform) + _pxp_blit_recolor(dest_buf, &blend_area, dest_stride, dest_cf, + src_buf, &src_area, src_stride, src_cf, dsc); + else if(has_transform) + _pxp_blit_transform(dest_buf, &blend_area, dest_stride, dest_cf, + src_buf, &src_area, src_stride, src_cf, dsc); + else + _pxp_blit(dest_buf, &blend_area, dest_stride, dest_cf, + src_buf, &src_area, src_stride, src_cf, dsc->opa); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void _pxp_blit_recolor(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride, + lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area, + int32_t src_stride, lv_color_format_t src_cf, const lv_draw_image_dsc_t * dsc) +{ + + int32_t dest_w = lv_area_get_width(dest_area); + int32_t dest_h = lv_area_get_height(dest_area); + int32_t src_w = lv_area_get_width(src_area); + int32_t src_h = lv_area_get_height(src_area); + + bool src_has_alpha = (src_cf == LV_COLOR_FORMAT_ARGB8888); + uint8_t src_px_size = lv_color_format_get_size(src_cf); + uint8_t dest_px_size = lv_color_format_get_size(dest_cf); + + lv_pxp_reset(); + + /*AS buffer - source image*/ + pxp_as_buffer_config_t asBufferConfig = { + .pixelFormat = pxp_get_as_px_format(src_cf), + .bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_px_size * src_area->x1), + .pitchBytes = src_stride + }; + PXP_SetAlphaSurfaceBufferConfig(PXP_ID, &asBufferConfig); + PXP_SetAlphaSurfacePosition(PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U); + + /*Disable PS, use as color generator*/ + PXP_SetProcessSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); + PXP_SetProcessSurfaceBackGroundColor(PXP_ID, lv_color_to_u32(dsc->recolor)); + + /*Output buffer*/ + pxp_output_buffer_config_t outputBufferConfig = { + .pixelFormat = pxp_get_out_px_format(dest_cf), + .interlacedMode = kPXP_OutputProgressive, + .buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_px_size * dest_area->x1), + .buffer1Addr = (uint32_t)0U, + .pitchBytes = dest_stride, + .width = dest_w, + .height = dest_h + }; + PXP_SetOutputBufferConfig(PXP_ID, &outputBufferConfig); + + /** + * Configure Porter-Duff blending. + * + * Note: srcFactorMode and dstFactorMode are inverted in fsl_pxp.h: + * srcFactorMode is actually applied on PS alpha value + * dstFactorMode is actually applied on AS alpha value + */ + pxp_porter_duff_config_t pdConfig = { + .enable = 1, + .dstColorMode = kPXP_PorterDuffColorWithAlpha, + .srcColorMode = kPXP_PorterDuffColorWithAlpha, + .dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha, + .srcGlobalAlphaMode = src_has_alpha ? kPXP_PorterDuffLocalAlpha : kPXP_PorterDuffGlobalAlpha, + .dstFactorMode = kPXP_PorterDuffFactorStraight, + .srcFactorMode = kPXP_PorterDuffFactorInversed, + .dstGlobalAlpha = dsc->recolor_opa, + .srcGlobalAlpha = 0xff, + .dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/ + .srcAlphaMode = kPXP_PorterDuffAlphaStraight + }; + PXP_SetPorterDuffConfig(PXP_ID, &pdConfig); + + lv_pxp_run(); +} + +static void _pxp_blit_transform(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride, + lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area, + int32_t src_stride, lv_color_format_t src_cf, const lv_draw_image_dsc_t * dsc) +{ + int32_t src_w = lv_area_get_width(src_area); + int32_t src_h = lv_area_get_height(src_area); + int32_t dest_w = lv_area_get_width(dest_area); + int32_t dest_h = lv_area_get_height(dest_area); + + lv_point_t pivot = dsc->pivot; + /*The offsets are now relative to the transformation result with pivot ULC*/ + int32_t piv_offset_x = 0; + int32_t piv_offset_y = 0; + + int32_t trim_x = 0; + int32_t trim_y = 0; + + bool has_rotation = (dsc->rotation != 0); + bool has_scale = (dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE); + uint8_t src_px_size = lv_color_format_get_size(src_cf); + uint8_t dest_px_size = lv_color_format_get_size(dest_cf); + + lv_pxp_reset(); + + if(has_rotation) { + /*Convert rotation angle and calculate offsets caused by pivot*/ + pxp_rotate_degree_t pxp_angle; + switch(dsc->rotation) { + case 0: + pxp_angle = kPXP_Rotate0; + piv_offset_x = 0; + piv_offset_y = 0; + break; + case 900: + pxp_angle = kPXP_Rotate90; + piv_offset_x = pivot.x + pivot.y - src_h; + piv_offset_y = pivot.y - pivot.x; + break; + case 1800: + pxp_angle = kPXP_Rotate180; + piv_offset_x = 2 * pivot.x - src_w; + piv_offset_y = 2 * pivot.y - src_h; + break; + case 2700: + pxp_angle = kPXP_Rotate270; + piv_offset_x = pivot.x - pivot.y; + piv_offset_y = pivot.x + pivot.y - src_w; + break; + default: + pxp_angle = kPXP_Rotate0; + piv_offset_x = 0; + piv_offset_y = 0; + } + /*PS buffer rotation and decimation does not function at the same time*/ + PXP_SetRotateConfig(PXP_ID, kPXP_RotateOutputBuffer, pxp_angle, kPXP_FlipDisable); + } + + if(has_scale) { + float fp_scale_x = (float)dsc->scale_x / LV_SCALE_NONE; + float fp_scale_y = (float)dsc->scale_y / LV_SCALE_NONE; + int32_t int_scale_x = (int32_t)fp_scale_x; + int32_t int_scale_y = (int32_t)fp_scale_y; + + /*Any scale_factor in (k, k + 1] will result in a trim equal to k*/ + trim_x = (fp_scale_x == int_scale_x) ? int_scale_x - 1 : int_scale_x; + trim_y = (fp_scale_y == int_scale_y) ? int_scale_y - 1 : int_scale_y; + + dest_w = src_w * fp_scale_x + trim_x; + dest_h = src_h * fp_scale_y + trim_y; + + /*Final pivot offset = scale_factor * rotation_pivot_offset + scaling_pivot_offset*/ + piv_offset_x = floor(fp_scale_x * piv_offset_x) - floor((fp_scale_x - 1) * pivot.x); + piv_offset_y = floor(fp_scale_y * piv_offset_y) - floor((fp_scale_y - 1) * pivot.y); + } + + /*PS buffer - source image*/ + pxp_ps_buffer_config_t psBufferConfig = { + .pixelFormat = pxp_get_ps_px_format(src_cf), + .swapByte = false, + .bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_px_size * src_area->x1), + .bufferAddrU = 0, + .bufferAddrV = 0, + .pitchBytes = src_stride + }; + PXP_SetProcessSurfaceBufferConfig(PXP_ID, &psBufferConfig); + PXP_SetProcessSurfacePosition(PXP_ID, 0U, 0U, dest_w - trim_x - 1U, dest_h - trim_y - 1U); + + if(has_scale) + PXP_SetProcessSurfaceScaler(PXP_ID, src_w, src_h, dest_w, dest_h); + + /*AS disabled */ + PXP_SetAlphaSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); + + /*Output buffer*/ + pxp_output_buffer_config_t outputBufferConfig = { + .pixelFormat = pxp_get_out_px_format(dest_cf), + .interlacedMode = kPXP_OutputProgressive, + .buffer0Addr = (uint32_t)(dest_buf + dest_stride * (dest_area->y1 + piv_offset_y) + dest_px_size * (dest_area->x1 + piv_offset_x)), + .buffer1Addr = (uint32_t)0U, + .pitchBytes = dest_stride, + .width = dest_w - trim_x, + .height = dest_h - trim_y + }; + PXP_SetOutputBufferConfig(PXP_ID, &outputBufferConfig); + + lv_pxp_run(); +} + +static void _pxp_blit(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride, + lv_color_format_t dest_cf, const uint8_t * src_buf, const lv_area_t * src_area, + int32_t src_stride, lv_color_format_t src_cf, lv_opa_t opa) +{ + int32_t dest_w = lv_area_get_width(dest_area); + int32_t dest_h = lv_area_get_height(dest_area); + int32_t src_w = lv_area_get_width(src_area); + int32_t src_h = lv_area_get_height(src_area); + + bool src_has_alpha = (src_cf == LV_COLOR_FORMAT_ARGB8888); + uint8_t src_px_size = lv_color_format_get_size(src_cf); + uint8_t dest_px_size = lv_color_format_get_size(dest_cf); + + lv_pxp_reset(); + + pxp_as_blend_config_t asBlendConfig = { + .alpha = opa, + .invertAlpha = false, + .alphaMode = kPXP_AlphaRop, + .ropMode = kPXP_RopMergeAs + }; + + if(opa >= (lv_opa_t)LV_OPA_MAX && !src_has_alpha) { + /*Simple blit, no effect - Disable PS buffer*/ + PXP_SetProcessSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); + } + else { + /*PS must be enabled to fetch background pixels. + PS and OUT buffers are the same, blend will be done in-place*/ + pxp_ps_buffer_config_t psBufferConfig = { + .pixelFormat = pxp_get_ps_px_format(dest_cf), + .swapByte = false, + .bufferAddr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_px_size * dest_area->x1), + .bufferAddrU = 0U, + .bufferAddrV = 0U, + .pitchBytes = dest_stride + }; + + if(opa >= (lv_opa_t)LV_OPA_MAX) + asBlendConfig.alphaMode = src_has_alpha ? kPXP_AlphaEmbedded : kPXP_AlphaOverride; + else + asBlendConfig.alphaMode = src_has_alpha ? kPXP_AlphaMultiply : kPXP_AlphaOverride; + + PXP_SetProcessSurfaceBufferConfig(PXP_ID, &psBufferConfig); + PXP_SetProcessSurfacePosition(PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U); + } + + /*AS buffer - source image*/ + pxp_as_buffer_config_t asBufferConfig = { + .pixelFormat = pxp_get_as_px_format(src_cf), + .bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_px_size * src_area->x1), + .pitchBytes = src_stride + }; + PXP_SetAlphaSurfaceBufferConfig(PXP_ID, &asBufferConfig); + PXP_SetAlphaSurfacePosition(PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U); + PXP_SetAlphaSurfaceBlendConfig(PXP_ID, &asBlendConfig); + PXP_EnableAlphaSurfaceOverlayColorKey(PXP_ID, false); + + /*Output buffer.*/ + pxp_output_buffer_config_t outputBufferConfig = { + .pixelFormat = pxp_get_out_px_format(dest_cf), + .interlacedMode = kPXP_OutputProgressive, + .buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_px_size * dest_area->x1), + .buffer1Addr = (uint32_t)0U, + .pitchBytes = dest_stride, + .width = dest_w, + .height = dest_h + }; + PXP_SetOutputBufferConfig(PXP_ID, &outputBufferConfig); + + lv_pxp_run(); +} + +#endif /*LV_USE_DRAW_PXP*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_layer.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_layer.c new file mode 100644 index 000000000..ee474d721 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_draw_pxp_layer.c @@ -0,0 +1,156 @@ +/** + * @file lv_draw_pxp_layer.c + * + */ + +/** + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_pxp.h" + +#if LV_USE_DRAW_PXP + +#include "../../../stdlib/lv_string.h" +#if LV_USE_PARALLEL_DRAW_DEBUG + #include "../../../core/lv_global.h" +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +#if LV_USE_PARALLEL_DRAW_DEBUG + #define _draw_info LV_GLOBAL_DEFAULT()->draw_info +#endif + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_pxp_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords) +{ + lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src; + const lv_draw_buf_t * draw_buf = layer_to_draw->draw_buf; + + /* It can happen that nothing was draw on a layer and therefore its buffer is not allocated. + * In this case just return. + */ + if(draw_buf == NULL) + return; + + const lv_area_t area_to_draw = { + .x1 = 0, + .y1 = 0, + .x2 = draw_buf->header.w - 1, + .y2 = draw_buf->header.h - 1 + }; + lv_draw_buf_invalidate_cache(draw_buf->data, draw_buf->header.stride, draw_buf->header.cf, &area_to_draw); + + lv_draw_image_dsc_t new_draw_dsc = *draw_dsc; + new_draw_dsc.src = draw_buf; + lv_draw_pxp_img(draw_unit, &new_draw_dsc, coords); + +#if LV_USE_LAYER_DEBUG || LV_USE_PARALLEL_DRAW_DEBUG + lv_area_t area_rot; + lv_area_copy(&area_rot, coords); + if(draw_dsc->rotation || draw_dsc->scale_x != LV_SCALE_NONE || draw_dsc->scale_y != LV_SCALE_NONE) { + int32_t w = lv_area_get_width(coords); + int32_t h = lv_area_get_height(coords); + + _lv_image_buf_get_transformed_area(&area_rot, w, h, draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, + &draw_dsc->pivot); + + area_rot.x1 += coords->x1; + area_rot.y1 += coords->y1; + area_rot.x2 += coords->x1; + area_rot.y2 += coords->y1; + } + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, &area_rot, draw_unit->clip_area)) return; +#endif + +#if LV_USE_LAYER_DEBUG + lv_draw_fill_dsc_t fill_dsc; + lv_draw_fill_dsc_init(&fill_dsc); + fill_dsc.color = lv_color_hex(layer_to_draw->color_format == LV_COLOR_FORMAT_ARGB8888 ? 0xff0000 : 0x00ff00); + fill_dsc.opa = LV_OPA_20; + lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot); + + lv_draw_border_dsc_t border_dsc; + lv_draw_border_dsc_init(&border_dsc); + border_dsc.color = fill_dsc.color; + border_dsc.opa = LV_OPA_60; + border_dsc.width = 2; + lv_draw_sw_border(draw_unit, &border_dsc, &area_rot); + +#endif + +#if LV_USE_PARALLEL_DRAW_DEBUG + uint32_t idx = 0; + lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head; + while(draw_unit_tmp != draw_unit) { + draw_unit_tmp = draw_unit_tmp->next; + idx++; + } + + lv_draw_fill_dsc_t fill_dsc; + lv_draw_rect_dsc_init(&fill_dsc); + fill_dsc.color = lv_palette_main(idx % _LV_PALETTE_LAST); + fill_dsc.opa = LV_OPA_10; + lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot); + + lv_draw_border_dsc_t border_dsc; + lv_draw_border_dsc_init(&border_dsc); + border_dsc.color = lv_palette_main(idx % _LV_PALETTE_LAST); + border_dsc.opa = LV_OPA_100; + border_dsc.width = 2; + lv_draw_sw_border(draw_unit, &border_dsc, &area_rot); + + lv_point_t txt_size; + lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE); + + lv_area_t txt_area; + txt_area.x1 = draw_area.x1; + txt_area.x2 = draw_area.x1 + txt_size.x - 1; + txt_area.y2 = draw_area.y2; + txt_area.y1 = draw_area.y2 - txt_size.y + 1; + + lv_draw_fill_dsc_init(&fill_dsc); + fill_dsc.color = lv_color_black(); + lv_draw_sw_fill(draw_unit, &fill_dsc, &txt_area); + + char buf[8]; + lv_snprintf(buf, sizeof(buf), "%d", idx); + lv_draw_label_dsc_t label_dsc; + lv_draw_label_dsc_init(&label_dsc); + label_dsc.color = lv_color_white(); + label_dsc.text = buf; + lv_draw_sw_label(draw_unit, &label_dsc, &txt_area); +#endif +} + +#endif /*LV_USE_DRAW_PXP*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.c deleted file mode 100644 index 164216f44..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.c +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @file lv_gpu_nxp_pxp.c - * - */ - -/** - * MIT License - * - * Copyright 2020-2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "lv_gpu_nxp_pxp.h" - -#if LV_USE_GPU_NXP_PXP -#include "lv_gpu_nxp_pxp_osa.h" -#include "../../../core/lv_refr.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/** - * Clean and invalidate cache. - */ -static inline void invalidate_cache(void); - -/********************** - * STATIC VARIABLES - **********************/ - -static lv_nxp_pxp_cfg_t * pxp_cfg; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_res_t lv_gpu_nxp_pxp_init(void) -{ -#if LV_USE_GPU_NXP_PXP_AUTO_INIT - pxp_cfg = lv_gpu_nxp_pxp_get_cfg(); -#endif - - if(!pxp_cfg || !pxp_cfg->pxp_interrupt_deinit || !pxp_cfg->pxp_interrupt_init || - !pxp_cfg->pxp_run || !pxp_cfg->pxp_wait) - PXP_RETURN_INV("PXP configuration error."); - - PXP_Init(LV_GPU_NXP_PXP_ID); - - PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/ - PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/ - - PXP_EnableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable); - - if(pxp_cfg->pxp_interrupt_init() != LV_RES_OK) { - PXP_DisableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable); - PXP_Deinit(LV_GPU_NXP_PXP_ID); - PXP_RETURN_INV("PXP interrupt init failed."); - } - - return LV_RES_OK; -} - -void lv_gpu_nxp_pxp_deinit(void) -{ - pxp_cfg->pxp_interrupt_deinit(); - PXP_DisableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable); - PXP_Deinit(LV_GPU_NXP_PXP_ID); -} - -void lv_gpu_nxp_pxp_reset(void) -{ - /* Wait for previous command to complete before resetting the registers. */ - lv_gpu_nxp_pxp_wait(); - - PXP_ResetControl(LV_GPU_NXP_PXP_ID); - - PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false); /*Disable CSC1, it is enabled by default.*/ - PXP_SetProcessBlockSize(LV_GPU_NXP_PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/ -} - -void lv_gpu_nxp_pxp_run(void) -{ - invalidate_cache(); - - pxp_cfg->pxp_run(); -} - -void lv_gpu_nxp_pxp_wait(void) -{ - pxp_cfg->pxp_wait(); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static inline void invalidate_cache(void) -{ - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - if(disp->driver->clean_dcache_cb) - disp->driver->clean_dcache_cb(disp->driver); -} - -#endif /*LV_USE_GPU_NXP_PXP*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.h deleted file mode 100644 index 46f4a0ba1..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.h +++ /dev/null @@ -1,166 +0,0 @@ -/** - * @file lv_gpu_nxp_pxp.h - * - */ - -/** - * MIT License - * - * Copyright 2020-2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef LV_GPU_NXP_PXP_H -#define LV_GPU_NXP_PXP_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ - -#include "../../../lv_conf_internal.h" - -#if LV_USE_GPU_NXP_PXP -#include "fsl_cache.h" -#include "fsl_pxp.h" - -#include "../../../misc/lv_log.h" - -/********************* - * DEFINES - *********************/ - -/** PXP module instance to use*/ -#define LV_GPU_NXP_PXP_ID PXP - -/** PXP interrupt line ID*/ -#define LV_GPU_NXP_PXP_IRQ_ID PXP_IRQn - -#ifndef LV_GPU_NXP_PXP_LOG_ERRORS -/** Enable logging of PXP errors (\see LV_LOG_ERROR)*/ -#define LV_GPU_NXP_PXP_LOG_ERRORS 1 -#endif - -#ifndef LV_GPU_NXP_PXP_LOG_TRACES -/** Enable logging of PXP errors (\see LV_LOG_ERROR)*/ -#define LV_GPU_NXP_PXP_LOG_TRACES 0 -#endif - -/********************** - * TYPEDEFS - **********************/ - -/** - * NXP PXP device configuration - call-backs used for - * interrupt init/wait/deinit. - */ -typedef struct { - /** Callback for PXP interrupt initialization*/ - lv_res_t (*pxp_interrupt_init)(void); - - /** Callback for PXP interrupt de-initialization*/ - void (*pxp_interrupt_deinit)(void); - - /** Callback for PXP start*/ - void (*pxp_run)(void); - - /** Callback for waiting of PXP completion*/ - void (*pxp_wait)(void); -} lv_nxp_pxp_cfg_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Reset and initialize PXP device. This function should be called as a part - * of display init sequence. - * - * @retval LV_RES_OK PXP init completed - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_PXP_LOG_ERRORS) - */ -lv_res_t lv_gpu_nxp_pxp_init(void); - -/** - * Disable PXP device. Should be called during display deinit sequence. - */ -void lv_gpu_nxp_pxp_deinit(void); - -/** - * Reset PXP device. - */ -void lv_gpu_nxp_pxp_reset(void); - -/** - * Clear cache and start PXP. - */ -void lv_gpu_nxp_pxp_run(void); - -/** - * Wait for PXP completion. - */ -void lv_gpu_nxp_pxp_wait(void); - -/********************** - * MACROS - **********************/ - -#define PXP_COND_STOP(cond, txt) \ - do { \ - if (cond) { \ - LV_LOG_ERROR("%s. STOP!", txt); \ - for ( ; ; ); \ - } \ - } while(0) - -#if LV_GPU_NXP_PXP_LOG_ERRORS -#define PXP_RETURN_INV(fmt, ...) \ - do { \ - LV_LOG_ERROR(fmt, ##__VA_ARGS__); \ - return LV_RES_INV; \ - } while (0) -#else -#define PXP_RETURN_INV(fmt, ...) \ - do { \ - return LV_RES_INV; \ - }while(0) -#endif /*LV_GPU_NXP_PXP_LOG_ERRORS*/ - -#if LV_GPU_NXP_PXP_LOG_TRACES -#define PXP_LOG_TRACE(fmt, ...) \ - do { \ - LV_LOG(fmt, ##__VA_ARGS__); \ - } while (0) -#else -#define PXP_LOG_TRACE(fmt, ...) \ - do { \ - } while (0) -#endif /*LV_GPU_NXP_PXP_LOG_TRACES*/ - -#endif /*LV_USE_GPU_NXP_PXP*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_GPU_NXP_PXP_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.c deleted file mode 100644 index 8e1884036..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.c +++ /dev/null @@ -1,180 +0,0 @@ -/** - * @file lv_gpu_nxp_pxp_osa.c - * - */ - -/** - * MIT License - * - * Copyright 2020, 2022, 2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "lv_gpu_nxp_pxp_osa.h" - -#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT -#include "../../../misc/lv_log.h" -#include "fsl_pxp.h" - -#if defined(SDK_OS_FREE_RTOS) - #include "FreeRTOS.h" - #include "semphr.h" -#endif - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/** - * PXP interrupt initialization. - */ -static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void); - -/** - * PXP interrupt de-initialization. - */ -static void _lv_gpu_nxp_pxp_interrupt_deinit(void); - -/** - * Start the PXP job. - */ -static void _lv_gpu_nxp_pxp_run(void); - -/** - * Wait for PXP completion. - */ -static void _lv_gpu_nxp_pxp_wait(void); - -/********************** - * STATIC VARIABLES - **********************/ - -#if defined(SDK_OS_FREE_RTOS) - static SemaphoreHandle_t s_pxpIdleSem; -#endif -static volatile bool s_pxpIdle; - -static lv_nxp_pxp_cfg_t pxp_default_cfg = { - .pxp_interrupt_init = _lv_gpu_nxp_pxp_interrupt_init, - .pxp_interrupt_deinit = _lv_gpu_nxp_pxp_interrupt_deinit, - .pxp_run = _lv_gpu_nxp_pxp_run, - .pxp_wait = _lv_gpu_nxp_pxp_wait, -}; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void PXP_IRQHandler(void) -{ -#if defined(SDK_OS_FREE_RTOS) - BaseType_t taskAwake = pdFALSE; -#endif - - if(kPXP_CompleteFlag & PXP_GetStatusFlags(LV_GPU_NXP_PXP_ID)) { - PXP_ClearStatusFlags(LV_GPU_NXP_PXP_ID, kPXP_CompleteFlag); -#if defined(SDK_OS_FREE_RTOS) - xSemaphoreGiveFromISR(s_pxpIdleSem, &taskAwake); - portYIELD_FROM_ISR(taskAwake); -#else - s_pxpIdle = true; -#endif - } -} - -lv_nxp_pxp_cfg_t * lv_gpu_nxp_pxp_get_cfg(void) -{ - return &pxp_default_cfg; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static lv_res_t _lv_gpu_nxp_pxp_interrupt_init(void) -{ -#if defined(SDK_OS_FREE_RTOS) - s_pxpIdleSem = xSemaphoreCreateBinary(); - if(s_pxpIdleSem == NULL) - return LV_RES_INV; - - NVIC_SetPriority(LV_GPU_NXP_PXP_IRQ_ID, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1); -#endif - s_pxpIdle = true; - - NVIC_EnableIRQ(LV_GPU_NXP_PXP_IRQ_ID); - - return LV_RES_OK; -} - -static void _lv_gpu_nxp_pxp_interrupt_deinit(void) -{ - NVIC_DisableIRQ(LV_GPU_NXP_PXP_IRQ_ID); -#if defined(SDK_OS_FREE_RTOS) - vSemaphoreDelete(s_pxpIdleSem); -#endif -} - -/** - * Function to start PXP job. - */ -static void _lv_gpu_nxp_pxp_run(void) -{ - s_pxpIdle = false; - - PXP_EnableInterrupts(LV_GPU_NXP_PXP_ID, kPXP_CompleteInterruptEnable); - PXP_Start(LV_GPU_NXP_PXP_ID); -} - -/** - * Function to wait for PXP completion. - */ -static void _lv_gpu_nxp_pxp_wait(void) -{ -#if defined(SDK_OS_FREE_RTOS) - /* Return if PXP was never started, otherwise the semaphore will lock forever. */ - if(s_pxpIdle == true) - return; - - if(xSemaphoreTake(s_pxpIdleSem, portMAX_DELAY) == pdTRUE) - s_pxpIdle = true; -#else - while(s_pxpIdle == false) { - } -#endif -} - -#endif /*LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.h deleted file mode 100644 index 5c87824ab..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file lv_gpu_nxp_pxp_osa.h - * - */ - -/** - * MIT License - * - * Copyright 2020, 2022 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef LV_GPU_NXP_PXP_OSA_H -#define LV_GPU_NXP_PXP_OSA_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ - -#include "../../../lv_conf_internal.h" - -#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT -#include "lv_gpu_nxp_pxp.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * PXP device interrupt handler. Used to check PXP task completion status. - */ -void PXP_IRQHandler(void); - -/** - * Helper function to get the PXP default configuration. - */ -lv_nxp_pxp_cfg_t * lv_gpu_nxp_pxp_get_cfg(void); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_GPU_NXP_PXP_OSA_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_cfg.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_cfg.c new file mode 100644 index 000000000..f1d796293 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_cfg.c @@ -0,0 +1,91 @@ +/** + * @file lv_pxp_cfg.c + * + */ + +/** + * Copyright 2020-2023 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_pxp_cfg.h" + +#if LV_USE_DRAW_PXP +#include "lv_pxp_osa.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +static pxp_cfg_t * _pxp_cfg; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_pxp_init(void) +{ + _pxp_cfg = pxp_get_default_cfg(); + + PXP_Init(PXP_ID); + + PXP_EnableCsc1(PXP_ID, false); /*Disable CSC1, it is enabled by default.*/ + PXP_SetProcessBlockSize(PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/ + + PXP_EnableInterrupts(PXP_ID, kPXP_CompleteInterruptEnable); + + _pxp_cfg->pxp_interrupt_init(); +} + +void lv_pxp_deinit(void) +{ + _pxp_cfg->pxp_interrupt_deinit(); + PXP_DisableInterrupts(PXP_ID, kPXP_CompleteInterruptEnable); + PXP_Deinit(PXP_ID); +} + +void lv_pxp_reset(void) +{ + PXP_ResetControl(PXP_ID); + + PXP_EnableCsc1(PXP_ID, false); /*Disable CSC1, it is enabled by default.*/ + PXP_SetProcessBlockSize(PXP_ID, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/ +} + +void lv_pxp_run(void) +{ + _pxp_cfg->pxp_run(); + _pxp_cfg->pxp_wait(); +} + +void lv_pxp_wait(void) +{ + _pxp_cfg->pxp_wait(); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_PXP*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_cfg.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_cfg.h new file mode 100644 index 000000000..b487e7ff9 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_cfg.h @@ -0,0 +1,102 @@ +/** + * @file lv_pxp_cfg.h + * + */ + +/** + * Copyright 2020-2023 NXP + * + * SPDX-License-Identifier: MIT + */ + +#ifndef LV_PXP_CFG_H +#define LV_PXP_CFG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../../lv_conf_internal.h" + +#if LV_USE_DRAW_PXP +#include "fsl_cache.h" +#include "fsl_pxp.h" + +#include "../../../misc/lv_log.h" + +/********************* + * DEFINES + *********************/ + +/** PXP module instance to use*/ +#define PXP_ID PXP + +/** PXP interrupt line ID*/ +#define PXP_IRQ_ID PXP_IRQn + +/********************** + * TYPEDEFS + **********************/ + +/** + * NXP PXP device configuration. + */ +typedef struct { + /** Callback for PXP interrupt initialization*/ + void (*pxp_interrupt_init)(void); + + /** Callback for PXP interrupt de-initialization*/ + void (*pxp_interrupt_deinit)(void); + + /** Callback for PXP start*/ + void (*pxp_run)(void); + + /** Callback for waiting of PXP completion*/ + void (*pxp_wait)(void); +} pxp_cfg_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Reset and initialize PXP device. This function should be called as a part + * of display init sequence. + */ +void lv_pxp_init(void); + +/** + * Disable PXP device. Should be called during display deinit sequence. + */ +void lv_pxp_deinit(void); + +/** + * Reset PXP device. + */ +void lv_pxp_reset(void); + +/** + * Clear cache and start PXP. + */ +void lv_pxp_run(void); + +/** + * Wait for PXP completion. + */ +void lv_pxp_wait(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DRAW_PXP*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_PXP_CFG_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_osa.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_osa.c new file mode 100644 index 000000000..539cefe50 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_osa.c @@ -0,0 +1,165 @@ +/** + * @file lv_pxp_osa.c + * + */ + +/** + * Copyright 2020, 2022-2023 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_pxp_osa.h" + +#if LV_USE_DRAW_PXP +#include "lv_pxp_utils.h" +#include "../../../misc/lv_log.h" +#include "fsl_pxp.h" + +#if defined(SDK_OS_FREE_RTOS) + #include "FreeRTOS.h" + #include "semphr.h" +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/** + * PXP interrupt initialization. + */ +static void _pxp_interrupt_init(void); + +/** + * PXP interrupt de-initialization. + */ +static void _pxp_interrupt_deinit(void); + +/** + * Start the PXP job. + */ +static void _pxp_run(void); + +/** + * Wait for PXP completion. + */ +static void _pxp_wait(void); + +/********************** + * STATIC VARIABLES + **********************/ + +#if defined(SDK_OS_FREE_RTOS) + static SemaphoreHandle_t xPXPIdleSemaphore; +#endif +static volatile bool ucPXPIdle; + +static pxp_cfg_t _pxp_default_cfg = { + .pxp_interrupt_init = _pxp_interrupt_init, + .pxp_interrupt_deinit = _pxp_interrupt_deinit, + .pxp_run = _pxp_run, + .pxp_wait = _pxp_wait, +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void PXP_IRQHandler(void) +{ +#if defined(SDK_OS_FREE_RTOS) + BaseType_t xHigherPriorityTaskWoken = pdFALSE; +#endif + + if(kPXP_CompleteFlag & PXP_GetStatusFlags(PXP_ID)) { + PXP_ClearStatusFlags(PXP_ID, kPXP_CompleteFlag); +#if defined(SDK_OS_FREE_RTOS) + xSemaphoreGiveFromISR(xPXPIdleSemaphore, &xHigherPriorityTaskWoken); + + /* If xHigherPriorityTaskWoken is now set to pdTRUE then a context switch + should be performed to ensure the interrupt returns directly to the highest + priority task. The macro used for this purpose is dependent on the port in + use and may be called portEND_SWITCHING_ISR(). */ + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +#else + ucPXPIdle = true; +#endif + } +} + +pxp_cfg_t * pxp_get_default_cfg(void) +{ + return &_pxp_default_cfg; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void _pxp_interrupt_init(void) +{ +#if defined(SDK_OS_FREE_RTOS) + xPXPIdleSemaphore = xSemaphoreCreateBinary(); + PXP_ASSERT_MSG(xPXPIdleSemaphore, "xSemaphoreCreateBinary failed!"); + + NVIC_SetPriority(PXP_IRQ_ID, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1); +#endif + ucPXPIdle = true; + + NVIC_EnableIRQ(PXP_IRQ_ID); +} + +static void _pxp_interrupt_deinit(void) +{ + NVIC_DisableIRQ(PXP_IRQ_ID); +#if defined(SDK_OS_FREE_RTOS) + vSemaphoreDelete(xPXPIdleSemaphore); +#endif +} + +/** + * Function to start PXP job. + */ +static void _pxp_run(void) +{ + ucPXPIdle = false; + + PXP_EnableInterrupts(PXP_ID, kPXP_CompleteInterruptEnable); + PXP_Start(PXP_ID); +} + +/** + * Function to wait for PXP completion. + */ +static void _pxp_wait(void) +{ +#if defined(SDK_OS_FREE_RTOS) + /* Return if PXP was never started, otherwise the semaphore will lock forever. */ + if(ucPXPIdle == true) + return; + + if(xSemaphoreTake(xPXPIdleSemaphore, portMAX_DELAY) == pdTRUE) + ucPXPIdle = true; +#else + while(ucPXPIdle == false) { + } +#endif +} + +#endif /*LV_USE_DRAW_PXP*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_osa.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_osa.h new file mode 100644 index 000000000..371429049 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_osa.h @@ -0,0 +1,60 @@ +/** + * @file lv_pxp_osa.h + * + */ + +/** + * Copyright 2020, 2022-2023 NXP + * + * SPDX-License-Identifier: MIT + */ + +#ifndef LV_PXP_OSA_H +#define LV_PXP_OSA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../../lv_conf_internal.h" + +#if LV_USE_DRAW_PXP +#include "lv_pxp_cfg.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * PXP device interrupt handler. Used to check PXP task completion status. + */ +void PXP_IRQHandler(void); + +/** + * Get the PXP default configuration. + */ +pxp_cfg_t * pxp_get_default_cfg(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DRAW_PXP*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_PXP_OSA_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_utils.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_utils.c new file mode 100644 index 000000000..3940a68b5 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_utils.c @@ -0,0 +1,145 @@ +/** + * @file lv_pxp_utils.c + * + */ + +/** + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_pxp_utils.h" + +#if LV_USE_DRAW_PXP + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +pxp_output_pixel_format_t pxp_get_out_px_format(lv_color_format_t cf) +{ + pxp_output_pixel_format_t out_px_format = kPXP_OutputPixelFormatRGB565; + + switch(cf) { + case LV_COLOR_FORMAT_RGB565: + out_px_format = kPXP_OutputPixelFormatRGB565; + break; + case LV_COLOR_FORMAT_RGB888: + out_px_format = kPXP_OutputPixelFormatRGB888P; + break; + case LV_COLOR_FORMAT_ARGB8888: + out_px_format = kPXP_OutputPixelFormatARGB8888; + break; + case LV_COLOR_FORMAT_XRGB8888: + out_px_format = kPXP_OutputPixelFormatRGB888; + break; + + default: + PXP_ASSERT_MSG(false, "Unsupported color format."); + break; + } + + return out_px_format; +} + +pxp_as_pixel_format_t pxp_get_as_px_format(lv_color_format_t cf) +{ + pxp_as_pixel_format_t as_px_format = kPXP_AsPixelFormatRGB565; + + switch(cf) { + case LV_COLOR_FORMAT_RGB565: + as_px_format = kPXP_AsPixelFormatRGB565; + break; + case LV_COLOR_FORMAT_RGB888: + PXP_ASSERT_MSG(false, "Unsupported color format."); + break; + case LV_COLOR_FORMAT_ARGB8888: + as_px_format = kPXP_AsPixelFormatARGB8888; + break; + case LV_COLOR_FORMAT_XRGB8888: + as_px_format = kPXP_AsPixelFormatRGB888; + break; + + default: + PXP_ASSERT_MSG(false, "Unsupported color format."); + break; + } + + return as_px_format; +} + +pxp_ps_pixel_format_t pxp_get_ps_px_format(lv_color_format_t cf) +{ + pxp_ps_pixel_format_t ps_px_format = kPXP_PsPixelFormatRGB565; + + switch(cf) { + case LV_COLOR_FORMAT_RGB565: + ps_px_format = kPXP_PsPixelFormatRGB565; + break; + case LV_COLOR_FORMAT_RGB888: + PXP_ASSERT_MSG(false, "Unsupported color format."); + break; + case LV_COLOR_FORMAT_ARGB8888: +#if (!(defined(FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT) && FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT)) && \ + (!(defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3)) + ps_px_format = kPXP_PsPixelFormatARGB8888; +#else + PXP_ASSERT_MSG(false, "Unsupported color format."); +#endif + break; + case LV_COLOR_FORMAT_XRGB8888: +#if (!(defined(FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT) && FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT)) && \ + (!(defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3)) + ps_px_format = kPXP_PsPixelFormatARGB8888; +#else + ps_px_format = kPXP_PsPixelFormatRGB888; +#endif + break; + + default: + PXP_ASSERT_MSG(false, "Unsupported color format."); + break; + } + + return ps_px_format; +} + +bool pxp_buf_aligned(const void * buf, uint32_t stride) +{ + /* Test for pointer alignment */ + if((uintptr_t)buf % 64) + return false; + + /* Test for invalid stride (no stride alignment required) */ + if(stride == 0) + return false; + + return true; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_PXP*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_utils.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_utils.h new file mode 100644 index 000000000..a1f0a16c4 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/pxp/lv_pxp_utils.h @@ -0,0 +1,80 @@ +/** + * @file lv_pxp_utils.h + * + */ + +/** + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: MIT + */ + +#ifndef LV_PXP_UTILS_H +#define LV_PXP_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lv_conf_internal.h" + +#if LV_USE_DRAW_PXP +#include "fsl_pxp.h" +#include "../../../misc/lv_color.h" + +/********************* + * DEFINES + *********************/ + +#if LV_USE_PXP_ASSERT +#define PXP_ASSERT(expr) LV_ASSERT(expr) +#else +#define PXP_ASSERT(expr) +#endif + +#define PXP_ASSERT_MSG(expr, msg) \ + do { \ + if(!(expr)) { \ + LV_LOG_ERROR(msg); \ + PXP_ASSERT(false); \ + } \ + } while(0) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +pxp_output_pixel_format_t pxp_get_out_px_format(lv_color_format_t cf); + +pxp_as_pixel_format_t pxp_get_as_px_format(lv_color_format_t cf); + +pxp_ps_pixel_format_t pxp_get_ps_px_format(lv_color_format_t cf); + +bool pxp_buf_aligned(const void * buf, uint32_t stride); + +/********************** + * MACROS + **********************/ + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_PXP*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_PXP_UTILS_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_buf_vglite.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_buf_vglite.c new file mode 100644 index 000000000..393c9a6b2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_buf_vglite.c @@ -0,0 +1,148 @@ +/** + * @file lv_draw_buf_vglite.c + * + */ + +/** + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vglite.h" + +#if LV_USE_DRAW_VGLITE +#include "lv_vglite_buf.h" +#include "lv_vglite_utils.h" + +#include "lvgl_support.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void * _buf_malloc(size_t size_bytes, lv_color_format_t cf); + +static void * _buf_align(void * buf, lv_color_format_t cf); + +static void _invalidate_cache(void * buf, uint32_t stride, lv_color_format_t cf, const lv_area_t * area); + +static uint32_t _width_to_stride(uint32_t w, lv_color_format_t cf); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_buf_vglite_init_handlers(void) +{ + lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers(); + + handlers->buf_malloc_cb = _buf_malloc; + handlers->align_pointer_cb = _buf_align; + handlers->invalidate_cache_cb = _invalidate_cache; + handlers->width_to_stride_cb = _width_to_stride; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void * _buf_malloc(size_t size_bytes, lv_color_format_t cf) +{ + uint8_t align_bytes = vglite_get_alignment(cf); + + /*Allocate larger memory to be sure it can be aligned as needed*/ + size_bytes += align_bytes - 1; + + return lv_malloc(size_bytes); +} + +static void * _buf_align(void * buf, lv_color_format_t cf) +{ + uint8_t align_bytes = vglite_get_alignment(cf); + + uint8_t * buf_u8 = buf; + if(buf_u8) { + buf_u8 += align_bytes - 1; + buf_u8 = (uint8_t *)((lv_uintptr_t)buf_u8 & ~(align_bytes - 1)); + } + + return buf_u8; +} + +static void _invalidate_cache(void * buf, uint32_t stride, lv_color_format_t cf, const lv_area_t * area) +{ + if(area->y1 == 0) { + uint16_t size = stride * lv_area_get_height(area); + + /* Invalidate full buffer. */ + DEMO_CleanInvalidateCacheByAddr((void *)buf, size); + return; + } + + const uint8_t * buf_u8 = buf; + /* ARM require a 32 byte aligned address. */ + uint8_t align_bytes = 32; + uint8_t bits_per_pixel = lv_color_format_get_bpp(cf); + + uint16_t align_pixels = align_bytes * 8 / bits_per_pixel; + uint16_t offset_x = 0; + + if(area->x1 >= (int32_t)(area->x1 % align_pixels)) { + uint16_t shift_x = area->x1 - (area->x1 % align_pixels); + + offset_x = area->x1 - shift_x; + buf_u8 += (shift_x * bits_per_pixel) / 8; + } + + if(area->y1) { + uint16_t shift_y = area->y1; + + buf_u8 += shift_y * stride; + } + + /* Area to clear can start from a different offset in buffer. + * Invalidate the area line by line. + */ + uint16_t line_pixels = offset_x + lv_area_get_width(area); + uint16_t line_size = (line_pixels * bits_per_pixel) / 8; + uint16_t area_height = lv_area_get_height(area); + + for(uint16_t y = 0; y < area_height; y++) { + const void * line_addr = buf_u8 + y * stride; + + DEMO_CleanInvalidateCacheByAddr((void *)line_addr, line_size); + } +} + +static uint32_t _width_to_stride(uint32_t w, lv_color_format_t cf) +{ + uint8_t bits_per_pixel = lv_color_format_get_bpp(cf); + uint32_t width_bits = (w * bits_per_pixel + 7) & ~7; + uint32_t width_bytes = width_bits / 8; + uint8_t align_bytes = vglite_get_alignment(cf); + + return (width_bytes + align_bytes - 1) & ~(align_bytes - 1); +} + +#endif /*LV_USE_DRAW_VGLITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_nxp_vglite.mk b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_nxp_vglite.mk deleted file mode 100644 index c9473cc10..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_nxp_vglite.mk +++ /dev/null @@ -1,12 +0,0 @@ -CSRCS += lv_draw_vglite.c -CSRCS += lv_draw_vglite_arc.c -CSRCS += lv_draw_vglite_blend.c -CSRCS += lv_draw_vglite_line.c -CSRCS += lv_draw_vglite_rect.c -CSRCS += lv_vglite_buf.c -CSRCS += lv_vglite_utils.c - -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/nxp/vglite" diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite.c index 031f57e4e..f701f6800 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite.c @@ -4,27 +4,9 @@ */ /** - * MIT License - * - * Copyright 2022, 2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * Copyright 2023-2024 NXP * + * SPDX-License-Identifier: MIT */ /********************* @@ -33,68 +15,84 @@ #include "lv_draw_vglite.h" -#if LV_USE_GPU_NXP_VG_LITE -#include -#include "lv_draw_vglite_blend.h" -#include "lv_draw_vglite_line.h" -#include "lv_draw_vglite_rect.h" -#include "lv_draw_vglite_arc.h" +#if LV_USE_DRAW_VGLITE #include "lv_vglite_buf.h" +#include "lv_vglite_utils.h" -#if LV_COLOR_DEPTH != 32 - #include "../../../core/lv_refr.h" +#if LV_USE_PARALLEL_DRAW_DEBUG + #include "../../../core/lv_global.h" #endif /********************* * DEFINES *********************/ -/* Minimum area (in pixels) for VG-Lite blit/fill processing. */ -#ifndef LV_GPU_NXP_VG_LITE_SIZE_LIMIT - #define LV_GPU_NXP_VG_LITE_SIZE_LIMIT 5000 +#define DRAW_UNIT_ID_VGLITE 2 + +#if LV_USE_VGLITE_DRAW_ASYNC + #define VGLITE_TASK_BUF_SIZE 10 #endif /********************** * TYPEDEFS **********************/ +#if LV_USE_VGLITE_DRAW_ASYNC +/** + * Structure of pending vglite draw task + */ +typedef struct _vglite_draw_task_t { + lv_draw_task_t * task; + bool flushed; +} vglite_draw_tasks_t; +#endif + /********************** * STATIC PROTOTYPES **********************/ -static void lv_draw_vglite_init_buf(lv_draw_ctx_t * draw_ctx); +/* + * Evaluate a task and set the score and preferred VGLite draw unit. + * Return 1 if task is preferred, 0 otherwise (task is not supported). + */ +static int32_t _vglite_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task); -static void lv_draw_vglite_wait_for_finish(lv_draw_ctx_t * draw_ctx); +/* + * Dispatch (assign) a task to VGLite draw unit (itself). + * Return 1 if task was dispatched, 0 otherwise (task not supported). + */ +static int32_t _vglite_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer); -static void lv_draw_vglite_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, - const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf); +/* + * Delete the VGLite draw unit. + */ +static int32_t _vglite_delete(lv_draw_unit_t * draw_unit); -static void lv_draw_vglite_buffer_copy(lv_draw_ctx_t * draw_ctx, - void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area, - void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area); +#if LV_USE_OS + static void _vglite_render_thread_cb(void * ptr); +#endif -static void lv_draw_vglite_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); - -static void lv_draw_vglite_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1, - const lv_point_t * point2); - -static void lv_draw_vglite_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); - -static lv_res_t lv_draw_vglite_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); - -static lv_res_t lv_draw_vglite_border(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, - const lv_area_t * coords); - -static lv_res_t lv_draw_vglite_outline(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, - const lv_area_t * coords); - -static void lv_draw_vglite_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, - uint16_t radius, uint16_t start_angle, uint16_t end_angle); +static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u); /********************** * STATIC VARIABLES **********************/ +#if LV_USE_PARALLEL_DRAW_DEBUG + #define _draw_info LV_GLOBAL_DEFAULT()->draw_info +#endif + +#if LV_USE_VGLITE_DRAW_ASYNC + /* + * Circular buffer to hold the queued and the flushed tasks. + * Two indexes, _head and _tail, are used to signal the beginning + * and the end of the valid tasks that are pending. + */ + static vglite_draw_tasks_t _draw_task_buf[VGLITE_TASK_BUF_SIZE]; + static volatile int _head = 0; + static volatile int _tail = 0; +#endif + /********************** * MACROS **********************/ @@ -103,455 +101,437 @@ static void lv_draw_vglite_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * GLOBAL FUNCTIONS **********************/ -void lv_draw_vglite_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) +void lv_draw_vglite_init(void) { - lv_draw_sw_init_ctx(drv, draw_ctx); + lv_draw_buf_vglite_init_handlers(); - lv_draw_vglite_ctx_t * vglite_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx; - vglite_draw_ctx->base_draw.init_buf = lv_draw_vglite_init_buf; - vglite_draw_ctx->base_draw.draw_line = lv_draw_vglite_line; - vglite_draw_ctx->base_draw.draw_arc = lv_draw_vglite_arc; - vglite_draw_ctx->base_draw.draw_rect = lv_draw_vglite_rect; - vglite_draw_ctx->base_draw.draw_img_decoded = lv_draw_vglite_img_decoded; - vglite_draw_ctx->blend = lv_draw_vglite_blend; - vglite_draw_ctx->base_draw.wait_for_finish = lv_draw_vglite_wait_for_finish; - vglite_draw_ctx->base_draw.buffer_copy = lv_draw_vglite_buffer_copy; + lv_draw_vglite_unit_t * draw_vglite_unit = lv_draw_create_unit(sizeof(lv_draw_vglite_unit_t)); + draw_vglite_unit->base_unit.evaluate_cb = _vglite_evaluate; + draw_vglite_unit->base_unit.dispatch_cb = _vglite_dispatch; + draw_vglite_unit->base_unit.delete_cb = _vglite_delete; + +#if LV_USE_OS + lv_thread_init(&draw_vglite_unit->thread, LV_THREAD_PRIO_HIGH, _vglite_render_thread_cb, 2 * 1024, draw_vglite_unit); +#endif } -void lv_draw_vglite_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) +void lv_draw_vglite_deinit(void) { - lv_draw_sw_deinit_ctx(drv, draw_ctx); } /********************** * STATIC FUNCTIONS **********************/ -/** - * During rendering, LVGL might initializes new draw_ctxs and start drawing into - * a separate buffer (called layer). If the content to be rendered has "holes", - * e.g. rounded corner, LVGL temporarily sets the disp_drv.screen_transp flag. - * It means the renderers should draw into an ARGB buffer. - * With 32 bit color depth it's not a big problem but with 16 bit color depth - * the target pixel format is ARGB8565 which is not supported by the GPU. - * In this case, the VG-Lite callbacks should fallback to SW rendering. - */ -static inline bool need_argb8565_support() +static inline bool _vglite_src_cf_supported(lv_color_format_t cf) { -#if LV_COLOR_DEPTH != 32 - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); + bool is_cf_supported = false; - if(disp->driver->screen_transp == 1) - return true; + switch(cf) { +#if CHIPID == 0x255 || CHIPID == 0x555 + case LV_COLOR_FORMAT_I1: + case LV_COLOR_FORMAT_I2: + case LV_COLOR_FORMAT_I4: + case LV_COLOR_FORMAT_I8: #endif - - return false; -} - -static void lv_draw_vglite_init_buf(lv_draw_ctx_t * draw_ctx) -{ - lv_gpu_nxp_vglite_init_buf(draw_ctx->buf, draw_ctx->buf_area, lv_area_get_width(draw_ctx->buf_area)); -} - -static void lv_draw_vglite_wait_for_finish(lv_draw_ctx_t * draw_ctx) -{ - vg_lite_finish(); - - lv_draw_sw_wait_for_finish(draw_ctx); -} - -static void lv_draw_vglite_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc) -{ - if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) - return; - - if(need_argb8565_support()) { - lv_draw_sw_blend_basic(draw_ctx, dsc); - return; + case LV_COLOR_FORMAT_A4: + case LV_COLOR_FORMAT_A8: + case LV_COLOR_FORMAT_L8: + case LV_COLOR_FORMAT_RGB565: +#if CHIPID == 0x555 + case LV_COLOR_FORMAT_RGB565A8: + case LV_COLOR_FORMAT_RGB888: +#endif + case LV_COLOR_FORMAT_ARGB8888: + case LV_COLOR_FORMAT_XRGB8888: + is_cf_supported = true; + break; + default: + break; } - lv_area_t blend_area; - if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) + return is_cf_supported; +} + +static inline bool _vglite_dest_cf_supported(lv_color_format_t cf) +{ + bool is_cf_supported = false; + + switch(cf) { + case LV_COLOR_FORMAT_A8: +#if CHIPID == 0x255 || CHIPID == 0x555 + case LV_COLOR_FORMAT_L8: +#endif + case LV_COLOR_FORMAT_RGB565: +#if CHIPTID == 0x555 + case LV_COLOR_FORMAT_RGB565A8: + case LV_COLOR_FORMAT_RGB888: +#endif + case LV_COLOR_FORMAT_ARGB8888: + case LV_COLOR_FORMAT_XRGB8888: + is_cf_supported = true; + break; + default: + break; + } + + return is_cf_supported; +} + +static int32_t _vglite_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t) +{ + LV_UNUSED(u); + + const lv_draw_dsc_base_t * draw_dsc_base = (lv_draw_dsc_base_t *) t->draw_dsc; + + if(!_vglite_dest_cf_supported(draw_dsc_base->layer->color_format)) + return 0; + + switch(t->type) { + case LV_DRAW_TASK_TYPE_FILL: + if(t->preference_score > 80) { + t->preference_score = 80; + t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE; + } + return 1; + + case LV_DRAW_TASK_TYPE_LINE: + case LV_DRAW_TASK_TYPE_ARC: + case LV_DRAW_TASK_TYPE_TRIANGLE: + if(t->preference_score > 90) { + t->preference_score = 90; + t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE; + } + return 1; + + case LV_DRAW_TASK_TYPE_LABEL: + if(t->preference_score > 95) { + t->preference_score = 95; + t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE; + } + return 1; + + case LV_DRAW_TASK_TYPE_BORDER: { + const lv_draw_border_dsc_t * draw_dsc = (lv_draw_border_dsc_t *) t->draw_dsc; + + if(draw_dsc->side != (lv_border_side_t)LV_BORDER_SIDE_FULL) + return 0; + + if(t->preference_score > 90) { + t->preference_score = 90; + t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE; + } + return 1; + } + + case LV_DRAW_TASK_TYPE_LAYER: { + const lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc; + lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src; + + if(!_vglite_src_cf_supported(layer_to_draw->color_format)) + return 0; + + if(t->preference_score > 80) { + t->preference_score = 80; + t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE; + } + return 1; + } + + case LV_DRAW_TASK_TYPE_IMAGE: { + lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc; + const lv_image_dsc_t * img_dsc = draw_dsc->src; + +#if LV_USE_VGLITE_BLIT_SPLIT + bool has_transform = (draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE || + draw_dsc->scale_y != LV_SCALE_NONE); +#endif + + if((!_vglite_src_cf_supported(img_dsc->header.cf)) +#if LV_USE_VGLITE_BLIT_SPLIT + || has_transform +#endif + || (!vglite_buf_aligned(img_dsc->data, img_dsc->header.stride, img_dsc->header.cf)) + ) + return 0; + + if(t->preference_score > 80) { + t->preference_score = 80; + t->preferred_draw_unit_id = DRAW_UNIT_ID_VGLITE; + } + return 1; + } + default: + return 0; + } + + return 0; +} + +static int32_t _vglite_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer) +{ + lv_draw_vglite_unit_t * draw_vglite_unit = (lv_draw_vglite_unit_t *) draw_unit; + + /* Return immediately if it's busy with draw task. */ + if(draw_vglite_unit->task_act) + return 0; + + /* Try to get an ready to draw. */ + lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_VGLITE); + + if(t == NULL || t->preferred_draw_unit_id != DRAW_UNIT_ID_VGLITE) + return -1; + + void * buf = lv_draw_layer_alloc_buf(layer); + if(buf == NULL) + return -1; + + t->state = LV_DRAW_TASK_STATE_IN_PROGRESS; + draw_vglite_unit->base_unit.target_layer = layer; + draw_vglite_unit->base_unit.clip_area = &t->clip_area; + draw_vglite_unit->task_act = t; + +#if LV_USE_OS + /* Let the render thread work. */ + if(draw_vglite_unit->inited) + lv_thread_sync_signal(&draw_vglite_unit->sync); +#else + _vglite_execute_drawing(draw_vglite_unit); + + draw_vglite_unit->task_act->state = LV_DRAW_TASK_STATE_READY; + draw_vglite_unit->task_act = NULL; + + /* The draw unit is free now. Request a new dispatching as it can get a new task. */ + lv_draw_dispatch_request(); +#endif + + return 1; +} + +static int32_t _vglite_delete(lv_draw_unit_t * draw_unit) +{ +#if LV_USE_OS + lv_draw_vglite_unit_t * draw_vglite_unit = (lv_draw_vglite_unit_t *) draw_unit; + + LV_LOG_INFO("Cancel VGLite draw thread."); + draw_vglite_unit->exit_status = true; + + if(draw_vglite_unit->inited) + lv_thread_sync_signal(&draw_vglite_unit->sync); + + lv_result_t res = lv_thread_delete(&draw_vglite_unit->thread); + + return res; +#else + LV_UNUSED(draw_unit); + + return 0; +#endif +} + +static void _vglite_execute_drawing(lv_draw_vglite_unit_t * u) +{ + lv_draw_task_t * t = u->task_act; + lv_draw_unit_t * draw_unit = (lv_draw_unit_t *)u; + lv_layer_t * layer = draw_unit->target_layer; + lv_draw_buf_t * draw_buf = layer->draw_buf; + + /* Set target buffer */ + vglite_set_dest_buf(draw_buf->data, draw_buf->header.w, draw_buf->header.h, draw_buf->header.stride, + draw_buf->header.cf); + + lv_area_t clip_area; + lv_area_copy(&clip_area, draw_unit->clip_area); + lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t draw_area; + lv_area_copy(&draw_area, &t->area); + lv_area_move(&draw_area, -layer->buf_area.x1, -layer->buf_area.y1); + + if(!_lv_area_intersect(&draw_area, &draw_area, &clip_area)) return; /*Fully clipped, nothing to do*/ - lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); + /* Invalidate the drawing area */ + lv_draw_buf_invalidate_cache(draw_buf->data, draw_buf->header.stride, draw_buf->header.cf, &draw_area); - bool done = false; - /*Fill/Blend only non masked, normal blended*/ - if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL && - lv_area_get_size(&blend_area) >= LV_GPU_NXP_VG_LITE_SIZE_LIMIT) { - const lv_color_t * src_buf = dsc->src_buf; + /* Set scissor area */ + vglite_set_scissor(&clip_area); - if(src_buf == NULL) { - done = (lv_gpu_nxp_vglite_fill(&blend_area, dsc->color, dsc->opa) == LV_RES_OK); - if(!done) - VG_LITE_LOG_TRACE("VG-Lite fill failed. Fallback."); + switch(t->type) { + case LV_DRAW_TASK_TYPE_LABEL: + lv_draw_vglite_label(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_FILL: + lv_draw_vglite_fill(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_BORDER: + lv_draw_vglite_border(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_IMAGE: + lv_draw_vglite_img(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_ARC: + lv_draw_vglite_arc(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_LINE: + lv_draw_vglite_line(draw_unit, t->draw_dsc); + break; + case LV_DRAW_TASK_TYPE_LAYER: + lv_draw_vglite_layer(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_TRIANGLE: + lv_draw_vglite_triangle(draw_unit, t->draw_dsc); + break; + default: + break; + } + + /* Disable scissor */ + vglite_set_scissor(&layer->buf_area); + +#if LV_USE_PARALLEL_DRAW_DEBUG + /*Layers manage it for themselves*/ + if(t->type != LV_DRAW_TASK_TYPE_LAYER) { + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, &t->area, u->base_unit.clip_area)) + return; + + int32_t idx = 0; + lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head; + while(draw_unit_tmp != (lv_draw_unit_t *)u) { + draw_unit_tmp = draw_unit_tmp->next; + idx++; } + lv_draw_rect_dsc_t rect_dsc; + lv_draw_rect_dsc_init(&rect_dsc); + rect_dsc.bg_color = lv_palette_main(idx % _LV_PALETTE_LAST); + rect_dsc.border_color = rect_dsc.bg_color; + rect_dsc.bg_opa = LV_OPA_10; + rect_dsc.border_opa = LV_OPA_80; + rect_dsc.border_width = 1; + lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &draw_area); + + lv_point_t txt_size; + lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE); + + lv_area_t txt_area; + txt_area.x1 = draw_area.x1; + txt_area.y1 = draw_area.y1; + txt_area.x2 = draw_area.x1 + txt_size.x - 1; + txt_area.y2 = draw_area.y1 + txt_size.y - 1; + + lv_draw_rect_dsc_init(&rect_dsc); + rect_dsc.bg_color = lv_color_white(); + lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &txt_area); + + char buf[8]; + lv_snprintf(buf, sizeof(buf), "%d", idx); + lv_draw_label_dsc_t label_dsc; + lv_draw_label_dsc_init(&label_dsc); + label_dsc.color = lv_color_black(); + label_dsc.text = buf; + lv_draw_sw_label((lv_draw_unit_t *)u, &label_dsc, &txt_area); + } +#endif +} + +#if LV_USE_VGLITE_DRAW_ASYNC +static inline void _vglite_queue_task(lv_draw_task_t * task_act) +{ + _draw_task_buf[_tail].task = task_act; + _draw_task_buf[_tail].flushed = false; + _tail = (_tail + 1) % VGLITE_TASK_BUF_SIZE; +} + +static inline void _vglite_signal_task_ready(lv_draw_task_t * task_act) +{ + if(vglite_cmd_buf_is_flushed()) { + int end = (_head < _tail) ? _tail : _tail + VGLITE_TASK_BUF_SIZE; + + for(int i = _head; i < end; i++) { + /* Previous flushed tasks are ready now. */ + if(_draw_task_buf[i % VGLITE_TASK_BUF_SIZE].flushed) { + lv_draw_task_t * task = _draw_task_buf[i % VGLITE_TASK_BUF_SIZE].task; + + /* Signal the ready state to dispatcher. */ + task->state = LV_DRAW_TASK_STATE_READY; + _head = (_head + 1) % VGLITE_TASK_BUF_SIZE; + /* No need to cleanup the tasks in buffer as we advance with the _head. */ + } + else { + /* Those tasks have been flushed now. */ + _draw_task_buf[i % VGLITE_TASK_BUF_SIZE].flushed = true; + } + } + } + + if(task_act) + VGLITE_ASSERT_MSG(_tail != _head, "VGLite task buffer full."); +} +#endif + +#if LV_USE_OS +static void _vglite_render_thread_cb(void * ptr) +{ + lv_draw_vglite_unit_t * u = ptr; + + lv_thread_sync_init(&u->sync); + u->inited = true; + + while(1) { + /* Wait for sync if there is no task set. */ + while(u->task_act == NULL +#if LV_USE_VGLITE_DRAW_ASYNC + /* + * Wait for sync if _draw_task_buf is empty. + * The thread will have to run as much as there are pending tasks. + */ + && _head == _tail +#endif + ) { + if(u->exit_status) + break; + + lv_thread_sync_wait(&u->sync); + } + + if(u->exit_status) { + LV_LOG_INFO("Ready to exit VGLite draw thread."); + break; + } + + if(u->task_act) { +#if LV_USE_VGLITE_DRAW_ASYNC + _vglite_queue_task((void *)u->task_act); +#endif + _vglite_execute_drawing(u); + } +#if LV_USE_VGLITE_DRAW_ASYNC else { - lv_area_t src_area; - src_area.x1 = blend_area.x1 - (dsc->blend_area->x1 - draw_ctx->buf_area->x1); - src_area.y1 = blend_area.y1 - (dsc->blend_area->y1 - draw_ctx->buf_area->y1); - src_area.x2 = src_area.x1 + lv_area_get_width(dsc->blend_area) - 1; - src_area.y2 = src_area.y1 + lv_area_get_height(dsc->blend_area) - 1; - lv_coord_t src_stride = lv_area_get_width(dsc->blend_area); - -#if VG_LITE_BLIT_SPLIT_ENABLED - lv_color_t * dest_buf = draw_ctx->buf; - lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); - - done = (lv_gpu_nxp_vglite_blit_split(dest_buf, &blend_area, dest_stride, - src_buf, &src_area, src_stride, dsc->opa) == LV_RES_OK); -#else - done = (lv_gpu_nxp_vglite_blit(&blend_area, src_buf, &src_area, src_stride, dsc->opa) == LV_RES_OK); -#endif - - if(!done) - VG_LITE_LOG_TRACE("VG-Lite blit failed. Fallback."); + /* + * Update the flush status for last pending tasks. + * vg_lite_flush() will early return if there is nothing to submit. + */ + vglite_run(); } - } - - if(!done) - lv_draw_sw_blend_basic(draw_ctx, dsc); -} - -static void lv_draw_vglite_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, - const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t cf) -{ - if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) - return; - - if(need_argb8565_support()) { - lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf); - return; - } - - const lv_color_t * src_buf = (const lv_color_t *)map_p; - if(!src_buf) { - lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf); - return; - } - - lv_area_t rel_coords; - lv_area_copy(&rel_coords, coords); - lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - - lv_area_t rel_clip_area; - lv_area_copy(&rel_clip_area, draw_ctx->clip_area); - lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - - lv_area_t blend_area; - bool has_transform = dsc->angle != 0 || dsc->zoom != LV_IMG_ZOOM_NONE; - - if(has_transform) - lv_area_copy(&blend_area, &rel_coords); - else if(!_lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area)) - return; /*Fully clipped, nothing to do*/ - - bool has_mask = lv_draw_mask_is_any(&blend_area); - bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP); - - bool done = false; - if(!has_mask && !has_recolor && !lv_img_cf_is_chroma_keyed(cf) && - lv_area_get_size(&blend_area) >= LV_GPU_NXP_VG_LITE_SIZE_LIMIT -#if LV_COLOR_DEPTH != 32 - && !lv_img_cf_has_alpha(cf) #endif - ) { - lv_area_t src_area; - src_area.x1 = blend_area.x1 - (coords->x1 - draw_ctx->buf_area->x1); - src_area.y1 = blend_area.y1 - (coords->y1 - draw_ctx->buf_area->y1); - src_area.x2 = src_area.x1 + lv_area_get_width(coords) - 1; - src_area.y2 = src_area.y1 + lv_area_get_height(coords) - 1; - lv_coord_t src_stride = lv_area_get_width(coords); - -#if VG_LITE_BLIT_SPLIT_ENABLED - lv_color_t * dest_buf = draw_ctx->buf; - lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); - - if(has_transform) - /* VG-Lite blit split with transformation is not supported! */ - done = false; - else - done = (lv_gpu_nxp_vglite_blit_split(dest_buf, &blend_area, dest_stride, - src_buf, &src_area, src_stride, dsc->opa) == LV_RES_OK); +#if LV_USE_VGLITE_DRAW_ASYNC + _vglite_signal_task_ready((void *)u->task_act); #else - if(has_transform) - done = (lv_gpu_nxp_vglite_blit_transform(&blend_area, &rel_clip_area, - src_buf, &src_area, src_stride, dsc) == LV_RES_OK); - else - done = (lv_gpu_nxp_vglite_blit(&blend_area, src_buf, &src_area, src_stride, dsc->opa) == LV_RES_OK); + /* Signal the ready state to dispatcher. */ + u->task_act->state = LV_DRAW_TASK_STATE_READY; +#endif + /* Cleanup. */ + u->task_act = NULL; + + /* The draw unit is free now. Request a new dispatching as it can get a new task. */ + lv_draw_dispatch_request(); + } + + u->inited = false; + lv_thread_sync_delete(&u->sync); + LV_LOG_INFO("Exit VGLite draw thread."); +} #endif - if(!done) - VG_LITE_LOG_TRACE("VG-Lite blit %sfailed. Fallback.", has_transform ? "transform " : ""); - } - - if(!done) - lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, cf); -} - -static void lv_draw_vglite_buffer_copy(lv_draw_ctx_t * draw_ctx, - void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area, - void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area) -{ - bool done = false; - - if(lv_area_get_size(dest_area) >= LV_GPU_NXP_VG_LITE_SIZE_LIMIT) { - done = lv_gpu_nxp_vglite_buffer_copy(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride); - if(!done) - VG_LITE_LOG_TRACE("VG-Lite buffer copy failed. Fallback."); - } - - if(!done) - lv_draw_sw_buffer_copy(draw_ctx, dest_buf, dest_stride, dest_area, src_buf, src_stride, src_area); -} - -static void lv_draw_vglite_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1, - const lv_point_t * point2) -{ - if(dsc->width == 0) - return; - if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) - return; - if(point1->x == point2->x && point1->y == point2->y) - return; - - if(need_argb8565_support()) { - lv_draw_sw_line(draw_ctx, dsc, point1, point2); - return; - } - - lv_area_t rel_clip_area; - rel_clip_area.x1 = LV_MIN(point1->x, point2->x) - dsc->width / 2; - rel_clip_area.x2 = LV_MAX(point1->x, point2->x) + dsc->width / 2; - rel_clip_area.y1 = LV_MIN(point1->y, point2->y) - dsc->width / 2; - rel_clip_area.y2 = LV_MAX(point1->y, point2->y) + dsc->width / 2; - - lv_area_t clipped_coords; - if(!_lv_area_intersect(&clipped_coords, &rel_clip_area, draw_ctx->clip_area)) - return; /*Fully clipped, nothing to do*/ - - lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - - lv_point_t rel_point1 = { point1->x - draw_ctx->buf_area->x1, point1->y - draw_ctx->buf_area->y1 }; - lv_point_t rel_point2 = { point2->x - draw_ctx->buf_area->x1, point2->y - draw_ctx->buf_area->y1 }; - - bool done = false; - bool has_mask = lv_draw_mask_is_any(&rel_clip_area); - - if(!has_mask) { - done = (lv_gpu_nxp_vglite_draw_line(&rel_point1, &rel_point2, &rel_clip_area, dsc) == LV_RES_OK); - if(!done) - VG_LITE_LOG_TRACE("VG-Lite draw line failed. Fallback."); - } - - if(!done) - lv_draw_sw_line(draw_ctx, dsc, point1, point2); -} - -static void lv_draw_vglite_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) -{ - if(need_argb8565_support()) { - lv_draw_sw_rect(draw_ctx, dsc, coords); - return; - } - - lv_draw_rect_dsc_t vglite_dsc; - - lv_memcpy(&vglite_dsc, dsc, sizeof(vglite_dsc)); - vglite_dsc.bg_opa = 0; - vglite_dsc.bg_img_opa = 0; - vglite_dsc.border_opa = 0; - vglite_dsc.outline_opa = 0; -#if LV_DRAW_COMPLEX - /* Draw the shadow with CPU */ - lv_draw_sw_rect(draw_ctx, &vglite_dsc, coords); - vglite_dsc.shadow_opa = 0; -#endif /*LV_DRAW_COMPLEX*/ - - /* Draw the background */ - vglite_dsc.bg_opa = dsc->bg_opa; - if(lv_draw_vglite_bg(draw_ctx, &vglite_dsc, coords) != LV_RES_OK) - lv_draw_sw_rect(draw_ctx, &vglite_dsc, coords); - vglite_dsc.bg_opa = 0; - - /* Draw the background image - * It will be done once draw_ctx->draw_img_decoded() - * callback gets called from lv_draw_sw_rect(). - */ - vglite_dsc.bg_img_opa = dsc->bg_img_opa; - lv_draw_sw_rect(draw_ctx, &vglite_dsc, coords); - vglite_dsc.bg_img_opa = 0; - - /* Draw the border */ - vglite_dsc.border_opa = dsc->border_opa; - if(lv_draw_vglite_border(draw_ctx, &vglite_dsc, coords) != LV_RES_OK) - lv_draw_sw_rect(draw_ctx, &vglite_dsc, coords); - vglite_dsc.border_opa = 0; - - /* Draw the outline */ - vglite_dsc.outline_opa = dsc->outline_opa; - if(lv_draw_vglite_outline(draw_ctx, &vglite_dsc, coords) != LV_RES_OK) - lv_draw_sw_rect(draw_ctx, &vglite_dsc, coords); -} - -static lv_res_t lv_draw_vglite_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) -{ - if(dsc->bg_opa <= (lv_opa_t)LV_OPA_MIN) - return LV_RES_INV; - - lv_area_t rel_coords; - lv_area_copy(&rel_coords, coords); - - /*If the border fully covers make the bg area 1px smaller to avoid artifacts on the corners*/ - if(dsc->border_width > 1 && dsc->border_opa >= (lv_opa_t)LV_OPA_MAX && dsc->radius != 0) { - rel_coords.x1 += (dsc->border_side & LV_BORDER_SIDE_LEFT) ? 1 : 0; - rel_coords.y1 += (dsc->border_side & LV_BORDER_SIDE_TOP) ? 1 : 0; - rel_coords.x2 -= (dsc->border_side & LV_BORDER_SIDE_RIGHT) ? 1 : 0; - rel_coords.y2 -= (dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? 1 : 0; - } - lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - - lv_area_t rel_clip_area; - lv_area_copy(&rel_clip_area, draw_ctx->clip_area); - lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - - lv_area_t clipped_coords; - if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area)) - return LV_RES_OK; /*Fully clipped, nothing to do*/ - - bool has_mask = lv_draw_mask_is_any(&rel_coords); - lv_grad_dir_t grad_dir = dsc->bg_grad.dir; - lv_color_t bg_color = (grad_dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE) ? - dsc->bg_color : dsc->bg_grad.stops[0].color; - if(bg_color.full == dsc->bg_grad.stops[1].color.full) - grad_dir = LV_GRAD_DIR_NONE; - - /* - * Most simple case: just a plain rectangle (no mask, no radius, no gradient) - * shall be handled by draw_ctx->blend(). - * - * Complex case: gradient or radius but no mask. - */ - if(!has_mask && ((dsc->radius != 0) || (grad_dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE))) { - lv_res_t res = lv_gpu_nxp_vglite_draw_bg(&rel_coords, &rel_clip_area, dsc); - if(res != LV_RES_OK) - VG_LITE_LOG_TRACE("VG-Lite draw bg failed. Fallback."); - - return res; - } - - return LV_RES_INV; -} - -static lv_res_t lv_draw_vglite_border(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, - const lv_area_t * coords) -{ - if(dsc->border_opa <= (lv_opa_t)LV_OPA_MIN) - return LV_RES_INV; - if(dsc->border_width == 0) - return LV_RES_INV; - if(dsc->border_post) - return LV_RES_INV; - if(dsc->border_side != (lv_border_side_t)LV_BORDER_SIDE_FULL) - return LV_RES_INV; - - lv_area_t rel_coords; - lv_coord_t border_width = dsc->border_width; - - /* Move border inwards to align with software rendered border */ - rel_coords.x1 = coords->x1 + ceil(border_width / 2.0f); - rel_coords.x2 = coords->x2 - floor(border_width / 2.0f); - rel_coords.y1 = coords->y1 + ceil(border_width / 2.0f); - rel_coords.y2 = coords->y2 - floor(border_width / 2.0f); - - lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - - lv_area_t rel_clip_area; - lv_area_copy(&rel_clip_area, draw_ctx->clip_area); - lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - - lv_area_t clipped_coords; - if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area)) - return LV_RES_OK; /*Fully clipped, nothing to do*/ - - lv_res_t res = lv_gpu_nxp_vglite_draw_border_generic(&rel_coords, &rel_clip_area, dsc, true); - if(res != LV_RES_OK) - VG_LITE_LOG_TRACE("VG-Lite draw border failed. Fallback."); - - return res; -} - -static lv_res_t lv_draw_vglite_outline(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, - const lv_area_t * coords) -{ - if(dsc->outline_opa <= (lv_opa_t)LV_OPA_MIN) - return LV_RES_INV; - if(dsc->outline_width == 0) - return LV_RES_INV; - - /* Move outline outwards to align with software rendered outline */ - lv_coord_t outline_pad = dsc->outline_pad - 1; - lv_area_t rel_coords; - rel_coords.x1 = coords->x1 - outline_pad - floor(dsc->outline_width / 2.0f); - rel_coords.x2 = coords->x2 + outline_pad + ceil(dsc->outline_width / 2.0f); - rel_coords.y1 = coords->y1 - outline_pad - floor(dsc->outline_width / 2.0f); - rel_coords.y2 = coords->y2 + outline_pad + ceil(dsc->outline_width / 2.0f); - - lv_area_move(&rel_coords, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - - lv_area_t rel_clip_area; - lv_area_copy(&rel_clip_area, draw_ctx->clip_area); - lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - - lv_area_t clipped_coords; - if(!_lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area)) - return LV_RES_OK; /*Fully clipped, nothing to do*/ - - lv_res_t res = lv_gpu_nxp_vglite_draw_border_generic(&rel_coords, &rel_clip_area, dsc, false); - if(res != LV_RES_OK) - VG_LITE_LOG_TRACE("VG-Lite draw outline failed. Fallback."); - - return res; -} - -static void lv_draw_vglite_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, - uint16_t radius, uint16_t start_angle, uint16_t end_angle) -{ - bool done = false; - -#if LV_DRAW_COMPLEX - if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) - return; - if(dsc->width == 0) - return; - if(start_angle == end_angle) - return; - - if(need_argb8565_support()) { - lv_draw_sw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle); - return; - } - - lv_point_t rel_center = {center->x - draw_ctx->buf_area->x1, center->y - draw_ctx->buf_area->y1}; - - lv_area_t rel_clip_area; - lv_area_copy(&rel_clip_area, draw_ctx->clip_area); - lv_area_move(&rel_clip_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - - bool has_mask = lv_draw_mask_is_any(&rel_clip_area); - - if(!has_mask) { - done = (lv_gpu_nxp_vglite_draw_arc(&rel_center, (int32_t)radius, (int32_t)start_angle, (int32_t)end_angle, - &rel_clip_area, dsc) == LV_RES_OK); - if(!done) - VG_LITE_LOG_TRACE("VG-Lite draw arc failed. Fallback."); - } - -#endif/*LV_DRAW_COMPLEX*/ - - if(!done) - lv_draw_sw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle); -} - -#endif /*LV_USE_GPU_NXP_VG_LITE*/ +#endif /*LV_USE_DRAW_VGLITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite.h index c44cb8fc7..fe3cdfbc2 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite.h @@ -4,27 +4,9 @@ */ /** - * MIT License - * - * Copyright 2022, 2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * Copyright 2023-2024 NXP * + * SPDX-License-Identifier: MIT */ #ifndef LV_DRAW_VGLITE_H @@ -40,7 +22,7 @@ extern "C" { #include "../../../lv_conf_internal.h" -#if LV_USE_GPU_NXP_VG_LITE +#if LV_USE_DRAW_VGLITE #include "../../sw/lv_draw_sw.h" /********************* @@ -50,20 +32,45 @@ extern "C" { /********************** * TYPEDEFS **********************/ -typedef lv_draw_sw_ctx_t lv_draw_vglite_ctx_t; + +typedef lv_draw_sw_unit_t lv_draw_vglite_unit_t; /********************** * GLOBAL PROTOTYPES **********************/ -void lv_draw_vglite_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); +void lv_draw_buf_vglite_init_handlers(void); -void lv_draw_vglite_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); +void lv_draw_vglite_init(void); + +void lv_draw_vglite_deinit(void); + +void lv_draw_vglite_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_vglite_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_vglite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_vglite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_vglite_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_vglite_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords); + +void lv_draw_vglite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc); + +void lv_draw_vglite_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc); /********************** * MACROS **********************/ -#endif /*LV_USE_GPU_NXP_VG_LITE*/ +#endif /*LV_USE_DRAW_VGLITE*/ #ifdef __cplusplus } /*extern "C"*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.c index ef6d25a42..b35d2c74a 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.c @@ -4,37 +4,23 @@ */ /** - * MIT License - * - * Copyright 2021-2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * Copyright 2021-2024 NXP * + * SPDX-License-Identifier: MIT */ /********************* * INCLUDES *********************/ -#include "lv_draw_vglite_arc.h" +#include "lv_draw_vglite.h" -#if LV_USE_GPU_NXP_VG_LITE +#if LV_USE_DRAW_VGLITE #include "lv_vglite_buf.h" +#include "lv_vglite_path.h" +#include "lv_vglite_utils.h" + +#include "../../../stdlib/lv_string.h" #include /********************* @@ -87,9 +73,16 @@ typedef struct _cubic_cont_pt { * STATIC PROTOTYPES **********************/ -static void rotate_point(int32_t angle, int32_t * x, int32_t * y); -static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius, - int32_t start_angle, int32_t end_angle, const lv_point_t * center, bool cw); +/** + * Draw arc shape with effects + * + * @param[in] center Arc center with relative coordinates + * @param[in] clip_area Clip area with relative coordinates to dest buff + * @param[in] dsc Arc description structure (width, rounded ending, opacity) + * + */ +static void _vglite_draw_arc(const lv_point_t * center, const lv_area_t * clip_area, + const lv_draw_arc_dsc_t * dsc); /********************** * STATIC VARIABLES @@ -103,141 +96,33 @@ static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius, * GLOBAL FUNCTIONS **********************/ -lv_res_t lv_gpu_nxp_vglite_draw_arc(const lv_point_t * center, int32_t radius, int32_t start_angle, int32_t end_angle, - const lv_area_t * clip_area, const lv_draw_arc_dsc_t * dsc) +void lv_draw_vglite_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, + const lv_area_t * coords) { - vg_lite_error_t err = VG_LITE_SUCCESS; - lv_color32_t col32 = {.full = lv_color_to32(dsc->color)}; /*Convert color to RGBA8888*/ - vg_lite_path_t path; - vg_lite_color_t vgcol; /* vglite takes ABGR */ - bool donut = ((end_angle - start_angle) % 360 == 0) ? true : false; - vg_lite_buffer_t * vgbuf = lv_vglite_get_dest_buf(); + LV_UNUSED(coords); - /* path: max size = 16 cubic bezier (7 words each) */ - int32_t arc_path[16 * 7]; - lv_memset_00(arc_path, sizeof(arc_path)); + if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) + return; + if(dsc->width == 0) + return; + if(dsc->start_angle == dsc->end_angle) + return; - /*** Init path ***/ - lv_coord_t width = dsc->width; /* inner arc radius = outer arc radius - width */ - if(width > (lv_coord_t)radius) - width = radius; + lv_layer_t * layer = draw_unit->target_layer; + lv_point_t center = {dsc->center.x - layer->buf_area.x1, dsc->center.y - layer->buf_area.y1}; - int pidx = 0; - int32_t cp_x, cp_y; /* control point coords */ + lv_area_t clip_area; + lv_area_copy(&clip_area, draw_unit->clip_area); + lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1); - /* first control point of curve */ - cp_x = radius; - cp_y = 0; - rotate_point(start_angle, &cp_x, &cp_y); - arc_path[pidx++] = VLC_OP_MOVE; - arc_path[pidx++] = center->x + cp_x; - arc_path[pidx++] = center->y + cp_y; - - /* draw 1-5 outer quarters */ - add_arc_path(arc_path, &pidx, radius, start_angle, end_angle, center, true); - - if(donut) { - /* close outer circle */ - cp_x = radius; - cp_y = 0; - rotate_point(start_angle, &cp_x, &cp_y); - arc_path[pidx++] = VLC_OP_LINE; - arc_path[pidx++] = center->x + cp_x; - arc_path[pidx++] = center->y + cp_y; - /* start inner circle */ - cp_x = radius - width; - cp_y = 0; - rotate_point(start_angle, &cp_x, &cp_y); - arc_path[pidx++] = VLC_OP_MOVE; - arc_path[pidx++] = center->x + cp_x; - arc_path[pidx++] = center->y + cp_y; - - } - else if(dsc->rounded != 0U) { /* 1st rounded arc ending */ - cp_x = radius - width / 2; - cp_y = 0; - rotate_point(end_angle, &cp_x, &cp_y); - lv_point_t round_center = {center->x + cp_x, center->y + cp_y}; - add_arc_path(arc_path, &pidx, width / 2, end_angle, (end_angle + 180), - &round_center, true); - - } - else { /* 1st flat ending */ - cp_x = radius - width; - cp_y = 0; - rotate_point(end_angle, &cp_x, &cp_y); - arc_path[pidx++] = VLC_OP_LINE; - arc_path[pidx++] = center->x + cp_x; - arc_path[pidx++] = center->y + cp_y; - } - - /* draw 1-5 inner quarters */ - add_arc_path(arc_path, &pidx, radius - width, start_angle, end_angle, center, false); - - /* last control point of curve */ - if(donut) { /* close the loop */ - cp_x = radius - width; - cp_y = 0; - rotate_point(start_angle, &cp_x, &cp_y); - arc_path[pidx++] = VLC_OP_LINE; - arc_path[pidx++] = center->x + cp_x; - arc_path[pidx++] = center->y + cp_y; - - } - else if(dsc->rounded != 0U) { /* 2nd rounded arc ending */ - cp_x = radius - width / 2; - cp_y = 0; - rotate_point(start_angle, &cp_x, &cp_y); - lv_point_t round_center = {center->x + cp_x, center->y + cp_y}; - add_arc_path(arc_path, &pidx, width / 2, (start_angle + 180), (start_angle + 360), - &round_center, true); - - } - else { /* 2nd flat ending */ - cp_x = radius; - cp_y = 0; - rotate_point(start_angle, &cp_x, &cp_y); - arc_path[pidx++] = VLC_OP_LINE; - arc_path[pidx++] = center->x + cp_x; - arc_path[pidx++] = center->y + cp_y; - } - - arc_path[pidx++] = VLC_OP_END; - - err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, (uint32_t)pidx * sizeof(int32_t), arc_path, - (vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1, - ((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f); - VG_LITE_ERR_RETURN_INV(err, "Init path failed."); - - vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_BGRA8888 : VG_LITE_ABGR8888; - if(lv_vglite_premult_and_swizzle(&vgcol, col32, dsc->opa, color_format) != LV_RES_OK) - VG_LITE_RETURN_INV("Premultiplication and swizzle failed."); - - vg_lite_matrix_t matrix; - vg_lite_identity(&matrix); - - lv_vglite_set_scissor(clip_area); - - /*** Draw arc ***/ - err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol); - VG_LITE_ERR_RETURN_INV(err, "Draw arc failed."); - - if(lv_vglite_run() != LV_RES_OK) - VG_LITE_RETURN_INV("Run failed."); - - lv_vglite_disable_scissor(); - - err = vg_lite_clear_path(&path); - VG_LITE_ERR_RETURN_INV(err, "Clear path failed."); - - return LV_RES_OK; + _vglite_draw_arc(¢er, &clip_area, dsc); } /********************** * STATIC FUNCTIONS **********************/ -static void copy_arc(vg_arc * dst, vg_arc * src) +static void _copy_arc(vg_arc * dst, vg_arc * src) { dst->quarter = src->quarter; dst->rad = src->rad; @@ -255,7 +140,7 @@ static void copy_arc(vg_arc * dst, vg_arc * src) /** * Rotate the point according given rotation angle rotation center is 0,0 */ -static void rotate_point(int32_t angle, int32_t * x, int32_t * y) +static void _rotate_point(int32_t angle, int32_t * x, int32_t * y) { int32_t ori_x = *x; int32_t ori_y = *y; @@ -272,9 +157,9 @@ static void rotate_point(int32_t angle, int32_t * x, int32_t * y) * ---+--- * Q1 | Q0 */ -static void set_full_arc(vg_arc * fullarc) +static void _set_full_arc(vg_arc * fullarc) { - /* the tangent lenght for the bezier circle approx */ + /* the tangent length for the bezier circle approx */ float tang = ((float)fullarc->rad) * BEZIER_OPTIM_CIRCLE; switch(fullarc->quarter) { case 0: @@ -322,7 +207,7 @@ static void set_full_arc(vg_arc * fullarc) fullarc->p3y = 0; break; default: - LV_LOG_ERROR("Invalid arc quarter value."); + VGLITE_ASSERT_MSG(false, "Invalid arc quarter."); break; } } @@ -331,7 +216,7 @@ static void set_full_arc(vg_arc * fullarc) * Linear interpolation between two points 'a' and 'b' * 't' parameter is the proportion ratio expressed in range [0 ; T_FRACTION ] */ -static inline float lerp(float coord_a, float coord_b, uint16_t t) +static inline float _lerp(float coord_a, float coord_b, uint16_t t) { float tf = (float)t; return ((T_FRACTION - tf) * coord_a + tf * coord_b) / T_FRACTION; @@ -340,7 +225,7 @@ static inline float lerp(float coord_a, float coord_b, uint16_t t) /** * Computes a point of bezier curve given 't' param */ -static inline float comp_bezier_point(float t, cubic_cont_pt cp) +static inline float _comp_bezier_point(float t, cubic_cont_pt cp) { float t_sq = t * t; float inv_t_sq = (1.0f - t) * (1.0f - t); @@ -356,7 +241,7 @@ static inline float comp_bezier_point(float t, cubic_cont_pt cp) * bezier curve is defined by control points [p0 p1 p2 p3] * 'dec' tells if curve is decreasing (true) or increasing (false) */ -static uint16_t get_bez_t_from_pos(float pt, cubic_cont_pt cp, bool dec) +static uint16_t _get_bez_t_from_pos(float pt, cubic_cont_pt cp, bool dec) { /* initialize dichotomy with boundary 't' values */ float t_low = 0.0f; @@ -365,7 +250,7 @@ static uint16_t get_bez_t_from_pos(float pt, cubic_cont_pt cp, bool dec) float a_pt; /* dichotomy loop */ for(int i = 0; i < DICHOTO_ITER; i++) { - a_pt = comp_bezier_point(t_mid, cp); + a_pt = _comp_bezier_point(t_mid, cp); /* check mid-point position on bezier curve versus targeted point */ if((a_pt > pt) != dec) { t_hig = t_mid; @@ -384,17 +269,17 @@ static uint16_t get_bez_t_from_pos(float pt, cubic_cont_pt cp, bool dec) * Gives relative coords of the control points * for the sub-arc starting at angle with given angle span */ -static void get_subarc_control_points(vg_arc * arc, int32_t span) +static void _get_subarc_control_points(vg_arc * arc, int32_t span) { - vg_arc fullarc; + vg_arc fullarc = {0}; fullarc.angle = arc->angle; fullarc.quarter = arc->quarter; fullarc.rad = arc->rad; - set_full_arc(&fullarc); + _set_full_arc(&fullarc); /* special case of full arc */ if(arc->angle == 90) { - copy_arc(arc, &fullarc); + _copy_arc(arc, &fullarc); return; } @@ -402,67 +287,67 @@ static void get_subarc_control_points(vg_arc * arc, int32_t span) uint16_t t2 = TperDegree[arc->angle + span]; /* lerp for A */ - float a2x = lerp((float)fullarc.p0x, (float)fullarc.p1x, t2); - float a2y = lerp((float)fullarc.p0y, (float)fullarc.p1y, t2); + float a2x = _lerp((float)fullarc.p0x, (float)fullarc.p1x, t2); + float a2y = _lerp((float)fullarc.p0y, (float)fullarc.p1y, t2); /* lerp for B */ - float b2x = lerp((float)fullarc.p1x, (float)fullarc.p2x, t2); - float b2y = lerp((float)fullarc.p1y, (float)fullarc.p2y, t2); + float b2x = _lerp((float)fullarc.p1x, (float)fullarc.p2x, t2); + float b2y = _lerp((float)fullarc.p1y, (float)fullarc.p2y, t2); /* lerp for C */ - float c2x = lerp((float)fullarc.p2x, (float)fullarc.p3x, t2); - float c2y = lerp((float)fullarc.p2y, (float)fullarc.p3y, t2); + float c2x = _lerp((float)fullarc.p2x, (float)fullarc.p3x, t2); + float c2y = _lerp((float)fullarc.p2y, (float)fullarc.p3y, t2); /* lerp for D */ - float d2x = lerp(a2x, b2x, t2); - float d2y = lerp(a2y, b2y, t2); + float d2x = _lerp(a2x, b2x, t2); + float d2y = _lerp(a2y, b2y, t2); /* lerp for E */ - float e2x = lerp(b2x, c2x, t2); - float e2y = lerp(b2y, c2y, t2); + float e2x = _lerp(b2x, c2x, t2); + float e2y = _lerp(b2y, c2y, t2); - float pt2x = lerp(d2x, e2x, t2); - float pt2y = lerp(d2y, e2y, t2); + float pt2x = _lerp(d2x, e2x, t2); + float pt2y = _lerp(d2y, e2y, t2); /* compute sub-arc using the geometric construction of curve */ uint16_t t1 = TperDegree[arc->angle]; /* lerp for A */ - float a1x = lerp((float)fullarc.p0x, (float)fullarc.p1x, t1); - float a1y = lerp((float)fullarc.p0y, (float)fullarc.p1y, t1); + float a1x = _lerp((float)fullarc.p0x, (float)fullarc.p1x, t1); + float a1y = _lerp((float)fullarc.p0y, (float)fullarc.p1y, t1); /* lerp for B */ - float b1x = lerp((float)fullarc.p1x, (float)fullarc.p2x, t1); - float b1y = lerp((float)fullarc.p1y, (float)fullarc.p2y, t1); + float b1x = _lerp((float)fullarc.p1x, (float)fullarc.p2x, t1); + float b1y = _lerp((float)fullarc.p1y, (float)fullarc.p2y, t1); /* lerp for C */ - float c1x = lerp((float)fullarc.p2x, (float)fullarc.p3x, t1); - float c1y = lerp((float)fullarc.p2y, (float)fullarc.p3y, t1); + float c1x = _lerp((float)fullarc.p2x, (float)fullarc.p3x, t1); + float c1y = _lerp((float)fullarc.p2y, (float)fullarc.p3y, t1); /* lerp for D */ - float d1x = lerp(a1x, b1x, t1); - float d1y = lerp(a1y, b1y, t1); + float d1x = _lerp(a1x, b1x, t1); + float d1y = _lerp(a1y, b1y, t1); /* lerp for E */ - float e1x = lerp(b1x, c1x, t1); - float e1y = lerp(b1y, c1y, t1); + float e1x = _lerp(b1x, c1x, t1); + float e1y = _lerp(b1y, c1y, t1); - float pt1x = lerp(d1x, e1x, t1); - float pt1y = lerp(d1y, e1y, t1); + float pt1x = _lerp(d1x, e1x, t1); + float pt1y = _lerp(d1y, e1y, t1); /* find the 't3' parameter for point P(t1) on the sub-arc [P0 A2 D2 P(t2)] using dichotomy * use position of x axis only */ uint16_t t3; - t3 = get_bez_t_from_pos(pt1x, + t3 = _get_bez_t_from_pos(pt1x, (cubic_cont_pt) { .p0 = ((float)fullarc.p0x), .p1 = a2x, .p2 = d2x, .p3 = pt2x }, (bool)(pt2x < (float)fullarc.p0x)); /* lerp for B */ - float b3x = lerp(a2x, d2x, t3); - float b3y = lerp(a2y, d2y, t3); + float b3x = _lerp(a2x, d2x, t3); + float b3y = _lerp(a2y, d2y, t3); /* lerp for C */ - float c3x = lerp(d2x, pt2x, t3); - float c3y = lerp(d2y, pt2y, t3); + float c3x = _lerp(d2x, pt2x, t3); + float c3y = _lerp(d2y, pt2y, t3); /* lerp for E */ - float e3x = lerp(b3x, c3x, t3); - float e3y = lerp(b3y, c3y, t3); + float e3x = _lerp(b3x, c3x, t3); + float e3y = _lerp(b3y, c3y, t3); arc->p0x = (int32_t)floorf(0.5f + pt1x); arc->p0y = (int32_t)floorf(0.5f + pt1y); @@ -477,43 +362,43 @@ static void get_subarc_control_points(vg_arc * arc, int32_t span) /** * Gives relative coords of the control points */ -static void get_arc_control_points(vg_arc * arc, bool start) +static void _get_arc_control_points(vg_arc * arc, bool start) { - vg_arc fullarc; + vg_arc fullarc = {0}; fullarc.angle = arc->angle; fullarc.quarter = arc->quarter; fullarc.rad = arc->rad; - set_full_arc(&fullarc); + _set_full_arc(&fullarc); /* special case of full arc */ if(arc->angle == 90) { - copy_arc(arc, &fullarc); + _copy_arc(arc, &fullarc); return; } /* compute sub-arc using the geometric construction of curve */ uint16_t t = TperDegree[arc->angle]; /* lerp for A */ - float ax = lerp((float)fullarc.p0x, (float)fullarc.p1x, t); - float ay = lerp((float)fullarc.p0y, (float)fullarc.p1y, t); + float ax = _lerp((float)fullarc.p0x, (float)fullarc.p1x, t); + float ay = _lerp((float)fullarc.p0y, (float)fullarc.p1y, t); /* lerp for B */ - float bx = lerp((float)fullarc.p1x, (float)fullarc.p2x, t); - float by = lerp((float)fullarc.p1y, (float)fullarc.p2y, t); + float bx = _lerp((float)fullarc.p1x, (float)fullarc.p2x, t); + float by = _lerp((float)fullarc.p1y, (float)fullarc.p2y, t); /* lerp for C */ - float cx = lerp((float)fullarc.p2x, (float)fullarc.p3x, t); - float cy = lerp((float)fullarc.p2y, (float)fullarc.p3y, t); + float cx = _lerp((float)fullarc.p2x, (float)fullarc.p3x, t); + float cy = _lerp((float)fullarc.p2y, (float)fullarc.p3y, t); /* lerp for D */ - float dx = lerp(ax, bx, t); - float dy = lerp(ay, by, t); + float dx = _lerp(ax, bx, t); + float dy = _lerp(ay, by, t); /* lerp for E */ - float ex = lerp(bx, cx, t); - float ey = lerp(by, cy, t); + float ex = _lerp(bx, cx, t); + float ey = _lerp(by, cy, t); /* sub-arc's control points are tangents of DeCasteljau's algorithm */ if(start) { - arc->p0x = (int32_t)floorf(0.5f + lerp(dx, ex, t)); - arc->p0y = (int32_t)floorf(0.5f + lerp(dy, ey, t)); + arc->p0x = (int32_t)floorf(0.5f + _lerp(dx, ex, t)); + arc->p0y = (int32_t)floorf(0.5f + _lerp(dy, ey, t)); arc->p1x = (int32_t)floorf(0.5f + ex); arc->p1y = (int32_t)floorf(0.5f + ey); arc->p2x = (int32_t)floorf(0.5f + cx); @@ -528,8 +413,8 @@ static void get_arc_control_points(vg_arc * arc, bool start) arc->p1y = (int32_t)floorf(0.5f + ay); arc->p2x = (int32_t)floorf(0.5f + dx); arc->p2y = (int32_t)floorf(0.5f + dy); - arc->p3x = (int32_t)floorf(0.5f + lerp(dx, ex, t)); - arc->p3y = (int32_t)floorf(0.5f + lerp(dy, ey, t)); + arc->p3x = (int32_t)floorf(0.5f + _lerp(dx, ex, t)); + arc->p3y = (int32_t)floorf(0.5f + _lerp(dy, ey, t)); } } @@ -542,7 +427,7 @@ static void get_arc_control_points(vg_arc * arc, bool start) * center: (in) the center of the circle in draw coordinates * cw: (in) true if arc is clockwise */ -static void add_split_arc_path(int32_t * arc_path, int * pidx, vg_arc * q_arc, const lv_point_t * center, bool cw) +static void _add_split_arc_path(int32_t * arc_path, int * pidx, vg_arc * q_arc, const lv_point_t * center, bool cw) { /* assumes first control point already in array arc_path[] */ int idx = *pidx; @@ -592,11 +477,9 @@ static void add_split_arc_path(int32_t * arc_path, int * pidx, vg_arc * q_arc, c *pidx = idx; } -static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius, - int32_t start_angle, int32_t end_angle, const lv_point_t * center, bool cw) +static void _add_arc_path(int32_t * arc_path, int * pidx, int32_t radius, + int32_t start_angle, int32_t end_angle, const lv_point_t * center, bool cw) { - if(end_angle < start_angle) end_angle += 360; - /* set number of arcs to draw */ vg_arc q_arc; int32_t start_arc_angle = start_angle % 90; @@ -609,8 +492,8 @@ static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius, if(((start_angle / 90) == (end_angle / 90)) && (nbarc <= 0)) { q_arc.quarter = (start_angle / 90) % 4; q_arc.angle = start_arc_angle; - get_subarc_control_points(&q_arc, end_arc_angle - start_arc_angle); - add_split_arc_path(arc_path, pidx, &q_arc, center, cw); + _get_subarc_control_points(&q_arc, end_arc_angle - start_arc_angle); + _add_split_arc_path(arc_path, pidx, &q_arc, center, cw); return; } @@ -620,27 +503,27 @@ static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius, q_arc.quarter = (start_angle / 90) % 4; q_arc.angle = start_arc_angle; /* get cubic points relative to center */ - get_arc_control_points(&q_arc, true); + _get_arc_control_points(&q_arc, true); /* put cubic points in arc_path */ - add_split_arc_path(arc_path, pidx, &q_arc, center, cw); + _add_split_arc_path(arc_path, pidx, &q_arc, center, cw); } /* full arcs */ for(int32_t q = 0; q < nbarc ; q++) { q_arc.quarter = (q + ((start_angle + 89) / 90)) % 4; q_arc.angle = 90; /* get cubic points relative to center */ - get_arc_control_points(&q_arc, true); /* 2nd parameter 'start' ignored */ + _get_arc_control_points(&q_arc, true); /* 2nd parameter 'start' ignored */ /* put cubic points in arc_path */ - add_split_arc_path(arc_path, pidx, &q_arc, center, cw); + _add_split_arc_path(arc_path, pidx, &q_arc, center, cw); } /* partial ending arc */ if(end_arc_angle > 0) { q_arc.quarter = (end_angle / 90) % 4; q_arc.angle = end_arc_angle; /* get cubic points relative to center */ - get_arc_control_points(&q_arc, false); + _get_arc_control_points(&q_arc, false); /* put cubic points in arc_path */ - add_split_arc_path(arc_path, pidx, &q_arc, center, cw); + _add_split_arc_path(arc_path, pidx, &q_arc, center, cw); } } @@ -651,29 +534,154 @@ static void add_arc_path(int32_t * arc_path, int * pidx, int32_t radius, q_arc.quarter = (end_angle / 90) % 4; q_arc.angle = end_arc_angle; /* get cubic points relative to center */ - get_arc_control_points(&q_arc, false); + _get_arc_control_points(&q_arc, false); /* put cubic points in arc_path */ - add_split_arc_path(arc_path, pidx, &q_arc, center, cw); + _add_split_arc_path(arc_path, pidx, &q_arc, center, cw); } /* full arcs */ for(int32_t q = nbarc - 1; q >= 0; q--) { q_arc.quarter = (q + ((start_angle + 89) / 90)) % 4; q_arc.angle = 90; /* get cubic points relative to center */ - get_arc_control_points(&q_arc, true); /* 2nd parameter 'start' ignored */ + _get_arc_control_points(&q_arc, true); /* 2nd parameter 'start' ignored */ /* put cubic points in arc_path */ - add_split_arc_path(arc_path, pidx, &q_arc, center, cw); + _add_split_arc_path(arc_path, pidx, &q_arc, center, cw); } /* partial starting arc */ if(start_arc_angle > 0) { q_arc.quarter = (start_angle / 90) % 4; q_arc.angle = start_arc_angle; /* get cubic points relative to center */ - get_arc_control_points(&q_arc, true); + _get_arc_control_points(&q_arc, true); /* put cubic points in arc_path */ - add_split_arc_path(arc_path, pidx, &q_arc, center, cw); + _add_split_arc_path(arc_path, pidx, &q_arc, center, cw); } } } -#endif /*LV_USE_GPU_NXP_VG_LITE*/ +static void _vglite_draw_arc(const lv_point_t * center, const lv_area_t * clip_area, + const lv_draw_arc_dsc_t * dsc) +{ + vg_lite_path_t path; + uint16_t start_angle = dsc->start_angle; + uint16_t end_angle = dsc->end_angle; + + /* be sure end_angle > start_angle */ + if(end_angle < start_angle) + end_angle += 360; + + bool donut = ((end_angle - start_angle) % 360 == 0) ? true : false; + vg_lite_buffer_t * vgbuf = vglite_get_dest_buf(); + + /* path: max size = 16 cubic bezier (7 words each) */ + int32_t arc_path[16 * 7]; + lv_memzero(arc_path, sizeof(arc_path)); + + /*** Init path ***/ + int32_t width = dsc->width; /* inner arc radius = outer arc radius - width */ + uint16_t radius = dsc->radius; + + if(width > radius) + width = radius; + + int pidx = 0; + int32_t cp_x, cp_y; /* control point coords */ + + /* first control point of curve */ + cp_x = radius; + cp_y = 0; + _rotate_point(start_angle, &cp_x, &cp_y); + arc_path[pidx++] = VLC_OP_MOVE; + arc_path[pidx++] = center->x + cp_x; + arc_path[pidx++] = center->y + cp_y; + + /* draw 1-5 outer quarters */ + _add_arc_path(arc_path, &pidx, radius, start_angle, end_angle, center, true); + + if(donut) { + /* close outer circle */ + cp_x = radius; + cp_y = 0; + _rotate_point(start_angle, &cp_x, &cp_y); + arc_path[pidx++] = VLC_OP_LINE; + arc_path[pidx++] = center->x + cp_x; + arc_path[pidx++] = center->y + cp_y; + /* start inner circle */ + cp_x = radius - width; + cp_y = 0; + _rotate_point(start_angle, &cp_x, &cp_y); + arc_path[pidx++] = VLC_OP_MOVE; + arc_path[pidx++] = center->x + cp_x; + arc_path[pidx++] = center->y + cp_y; + + } + else if(dsc->rounded != 0U) { /* 1st rounded arc ending */ + cp_x = radius - width / 2; + cp_y = 0; + _rotate_point(end_angle, &cp_x, &cp_y); + lv_point_t round_center = {center->x + cp_x, center->y + cp_y}; + _add_arc_path(arc_path, &pidx, width / 2, end_angle, (end_angle + 180), + &round_center, true); + + } + else { /* 1st flat ending */ + cp_x = radius - width; + cp_y = 0; + _rotate_point(end_angle, &cp_x, &cp_y); + arc_path[pidx++] = VLC_OP_LINE; + arc_path[pidx++] = center->x + cp_x; + arc_path[pidx++] = center->y + cp_y; + } + + /* draw 1-5 inner quarters */ + _add_arc_path(arc_path, &pidx, radius - width, start_angle, end_angle, center, false); + + /* last control point of curve */ + if(donut) { /* close the loop */ + cp_x = radius - width; + cp_y = 0; + _rotate_point(start_angle, &cp_x, &cp_y); + arc_path[pidx++] = VLC_OP_LINE; + arc_path[pidx++] = center->x + cp_x; + arc_path[pidx++] = center->y + cp_y; + + } + else if(dsc->rounded != 0U) { /* 2nd rounded arc ending */ + cp_x = radius - width / 2; + cp_y = 0; + _rotate_point(start_angle, &cp_x, &cp_y); + lv_point_t round_center = {center->x + cp_x, center->y + cp_y}; + _add_arc_path(arc_path, &pidx, width / 2, (start_angle + 180), (start_angle + 360), + &round_center, true); + + } + else { /* 2nd flat ending */ + cp_x = radius; + cp_y = 0; + _rotate_point(start_angle, &cp_x, &cp_y); + arc_path[pidx++] = VLC_OP_LINE; + arc_path[pidx++] = center->x + cp_x; + arc_path[pidx++] = center->y + cp_y; + } + + arc_path[pidx++] = VLC_OP_END; + + VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, (uint32_t)pidx * sizeof(int32_t), arc_path, + (vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1, + ((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f)); + + lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa); + vg_lite_color_t vgcol = vglite_get_color(col32, false); + + vg_lite_matrix_t matrix; + vg_lite_identity(&matrix); + + /*** Draw arc ***/ + VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol)); + + vglite_run(); + + VGLITE_CHECK_ERROR(vg_lite_clear_path(&path)); +} + +#endif /*LV_USE_DRAW_VGLITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.h deleted file mode 100644 index 0fbff3d92..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @file lv_draw_vglite_arc.h - * - */ - -/** - * MIT License - * - * Copyright 2021-2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef LV_DRAW_VGLITE_ARC_H -#define LV_DRAW_VGLITE_ARC_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../../lv_conf_internal.h" - -#if LV_USE_GPU_NXP_VG_LITE -#include "lv_vglite_utils.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Draw arc shape with effects - * - * @param[in] center Arc center with relative coordinates - * @param[in] radius Radius of external arc - * @param[in] start_angle Starting angle in degrees - * @param[in] end_angle Ending angle in degrees - * @param[in] clip_area Clipping area with relative coordinates to dest buff - * @param[in] dsc Arc description structure (width, rounded ending, opacity) - * - * @retval LV_RES_OK Draw completed - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) - */ -lv_res_t lv_gpu_nxp_vglite_draw_arc(const lv_point_t * center, int32_t radius, int32_t start_angle, int32_t end_angle, - const lv_area_t * clip_area, const lv_draw_arc_dsc_t * dsc); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_GPU_NXP_VG_LITE*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_VGLITE_ARC_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.c deleted file mode 100644 index 4a15fd55c..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.c +++ /dev/null @@ -1,635 +0,0 @@ -/** - * @file lv_draw_vglite_blend.c - * - */ - -/** - * MIT License - * - * Copyright 2020-2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "lv_draw_vglite_blend.h" - -#if LV_USE_GPU_NXP_VG_LITE -#include "lv_vglite_buf.h" -#include "lv_vglite_utils.h" - -/********************* - * DEFINES - *********************/ - -/** Stride in px required by VG-Lite HW*/ -#define LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX 16U - -#if VG_LITE_BLIT_SPLIT_ENABLED - /** - * BLIT split threshold - BLITs with width or height higher than this value will be done - * in multiple steps. Value must be 16-aligned. Don't change. - */ - #define LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR 352 -#endif - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/** - * Blit image, with optional opacity. - * - * @param[in] src_area Source area with relative coordinates of source buffer - * @param[in] opa Opacity - * - * @retval LV_RES_OK Transfer complete - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) - */ -static lv_res_t lv_vglite_blit(const lv_area_t * src_area, lv_opa_t opa); - -/** - * Check source memory and stride alignment. - * - * @param[in] src_buf Source buffer - * @param[in] src_stride Stride of source buffer in pixels - * - * @retval LV_RES_OK Alignment OK - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) - */ -static lv_res_t check_src_alignment(const lv_color_t * src_buf, lv_coord_t src_stride); - -/** - * Creates matrix that translates to origin of given destination area. - * - * @param[in] dest_area Area with relative coordinates of destination buffer - */ -static inline void lv_vglite_set_translation_matrix(const lv_area_t * dest_area); - -/** - * Creates matrix that translates to origin of given destination area with transformation (scale or rotate). - * - * @param[in] dest_area Area with relative coordinates of destination buffer - * @param[in] dsc Image descriptor - */ -static inline void lv_vglite_set_transformation_matrix(const lv_area_t * dest_area, const lv_draw_img_dsc_t * dsc); - -#if VG_LITE_BLIT_SPLIT_ENABLED -/** - * Move buffer pointer as close as possible to area, but with respect to alignment requirements. X-axis only. - * - * @param[in/out] area Area to be updated - * @param[in/out] buf Pointer to be updated - */ -static void align_x(lv_area_t * area, lv_color_t ** buf); - -/** - * Move buffer pointer to the area start and update variables, Y-axis only. - * - * @param[in/out] area Area to be updated - * @param[in/out] buf Pointer to be updated - * @param[in] stride Buffer stride in pixels - */ -static void align_y(lv_area_t * area, lv_color_t ** buf, lv_coord_t stride); - -/** - * Blit image split in tiles, with optional opacity. - * - * @param[in/out] dest_buf Destination buffer - * @param[in] dest_area Area with relative coordinates of destination buffer - * @param[in] dest_stride Stride of destination buffer in pixels - * @param[in] src_buf Source buffer - * @param[in] src_area Source area with relative coordinates of source buffer - * @param[in] src_stride Stride of source buffer in pixels - * @param[in] opa Opacity - * - * @retval LV_RES_OK Transfer complete - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) - */ -static lv_res_t lv_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride, - lv_opa_t opa); -#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/ - -/********************** - * STATIC VARIABLES - **********************/ - -static vg_lite_matrix_t vgmatrix; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_res_t lv_gpu_nxp_vglite_fill(const lv_area_t * dest_area, lv_color_t color, lv_opa_t opa) -{ - vg_lite_error_t err = VG_LITE_SUCCESS; - lv_color32_t col32 = {.full = lv_color_to32(color)}; /*Convert color to RGBA8888*/ - vg_lite_color_t vgcol; /* vglite takes ABGR */ - vg_lite_buffer_t * vgbuf = lv_vglite_get_dest_buf(); - - vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_BGRA8888 : VG_LITE_ABGR8888; - if(lv_vglite_premult_and_swizzle(&vgcol, col32, opa, color_format) != LV_RES_OK) - VG_LITE_RETURN_INV("Premultiplication and swizzle failed."); - - if(opa >= (lv_opa_t)LV_OPA_MAX) { /*Opaque fill*/ - vg_lite_rectangle_t rect = { - .x = dest_area->x1, - .y = dest_area->y1, - .width = lv_area_get_width(dest_area), - .height = lv_area_get_height(dest_area) - }; - - err = vg_lite_clear(vgbuf, &rect, vgcol); - VG_LITE_ERR_RETURN_INV(err, "Clear failed."); - - if(lv_vglite_run() != LV_RES_OK) - VG_LITE_RETURN_INV("Run failed."); - } - else { /*fill with transparency*/ - - vg_lite_path_t path; - int32_t path_data[] = { /*VG rectangular path*/ - VLC_OP_MOVE, dest_area->x1, dest_area->y1, - VLC_OP_LINE, dest_area->x2 + 1, dest_area->y1, - VLC_OP_LINE, dest_area->x2 + 1, dest_area->y2 + 1, - VLC_OP_LINE, dest_area->x1, dest_area->y2 + 1, - VLC_OP_LINE, dest_area->x1, dest_area->y1, - VLC_OP_END - }; - - err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_LOW, sizeof(path_data), path_data, - (vg_lite_float_t) dest_area->x1, (vg_lite_float_t) dest_area->y1, - ((vg_lite_float_t) dest_area->x2) + 1.0f, ((vg_lite_float_t) dest_area->y2) + 1.0f); - VG_LITE_ERR_RETURN_INV(err, "Init path failed."); - - vg_lite_matrix_t matrix; - vg_lite_identity(&matrix); - - /*Draw rectangle*/ - err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol); - VG_LITE_ERR_RETURN_INV(err, "Draw rectangle failed."); - - if(lv_vglite_run() != LV_RES_OK) - VG_LITE_RETURN_INV("Run failed."); - - err = vg_lite_clear_path(&path); - VG_LITE_ERR_RETURN_INV(err, "Clear path failed."); - } - - return LV_RES_OK; -} - -#if VG_LITE_BLIT_SPLIT_ENABLED -lv_res_t lv_gpu_nxp_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride, - lv_opa_t opa) -{ - /* Set src_vgbuf structure. */ - lv_vglite_set_src_buf(src_buf, src_area, src_stride); - - lv_color_t * orig_dest_buf = dest_buf; - - lv_res_t rv = lv_vglite_blit_split(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, opa); - - /* Restore the original dest_vgbuf memory address. */ - lv_vglite_set_dest_buf_ptr(orig_dest_buf); - - return rv; -} -#else -lv_res_t lv_gpu_nxp_vglite_blit(const lv_area_t * dest_area, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, - lv_opa_t opa) -{ - if(check_src_alignment(src_buf, src_stride) != LV_RES_OK) - VG_LITE_RETURN_INV("Check src alignment failed."); - - /* Set src_vgbuf structure. */ - lv_vglite_set_src_buf(src_buf, src_area, src_stride); - - /* Set scissor. */ - lv_vglite_set_scissor(dest_area); - - /* Set vgmatrix. */ - lv_vglite_set_translation_matrix(dest_area); - - /* Start blit. */ - lv_res_t rv = lv_vglite_blit(src_area, opa); - - /* Disable scissor. */ - lv_vglite_disable_scissor(); - - return rv; -} - -lv_res_t lv_gpu_nxp_vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * clip_area, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, - const lv_draw_img_dsc_t * dsc) -{ - lv_res_t rv = LV_RES_INV; - - if(check_src_alignment(src_buf, src_stride) != LV_RES_OK) - VG_LITE_RETURN_INV("Check src alignment failed."); - - /* Set src_vgbuf structure. */ - lv_vglite_set_src_buf(src_buf, src_area, src_stride); - - /* Set scissor */ - lv_vglite_set_scissor(clip_area); - - /* Set vgmatrix. */ - lv_vglite_set_transformation_matrix(dest_area, dsc); - - /* Start blit. */ - rv = lv_vglite_blit(src_area, dsc->opa); - - /* Disable scissor. */ - lv_vglite_disable_scissor(); - - return rv; -} -#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/ - -lv_res_t lv_gpu_nxp_vglite_buffer_copy(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride) -{ - vg_lite_error_t err = VG_LITE_SUCCESS; - - if(check_src_alignment(src_buf, src_stride) != LV_RES_OK) - VG_LITE_RETURN_INV("Check src alignment failed."); - - vg_lite_buffer_t src_vgbuf; - /* Set src_vgbuf structure. */ - lv_vglite_set_buf(&src_vgbuf, src_buf, src_area, src_stride); - - vg_lite_buffer_t dest_vgbuf; - /* Set dest_vgbuf structure. */ - lv_vglite_set_buf(&dest_vgbuf, dest_buf, dest_area, dest_stride); - - uint32_t rect[] = { - (uint32_t)src_area->x1, /* start x */ - (uint32_t)src_area->y1, /* start y */ - (uint32_t)lv_area_get_width(src_area), /* width */ - (uint32_t)lv_area_get_height(src_area) /* height */ - }; - - /* Set scissor. */ - lv_vglite_set_scissor(dest_area); - - /* Set vgmatrix. */ - lv_vglite_set_translation_matrix(dest_area); - - err = vg_lite_blit_rect(&dest_vgbuf, &src_vgbuf, rect, &vgmatrix, - VG_LITE_BLEND_NONE, 0xFFFFFFFFU, VG_LITE_FILTER_POINT); - if(err != VG_LITE_SUCCESS) { - LV_LOG_ERROR("Blit rectangle failed."); - /* Disable scissor. */ - lv_vglite_disable_scissor(); - - return LV_RES_INV; - } - - if(lv_vglite_run() != LV_RES_OK) { - LV_LOG_ERROR("Run failed."); - /* Disable scissor. */ - lv_vglite_disable_scissor(); - - return LV_RES_INV; - } - - /* Disable scissor. */ - lv_vglite_disable_scissor(); - - return LV_RES_OK; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -#if VG_LITE_BLIT_SPLIT_ENABLED -static lv_res_t lv_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride, - lv_opa_t opa) -{ - lv_res_t rv = LV_RES_INV; - - VG_LITE_LOG_TRACE("Blit " - "Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | " - "Size: ([%dx%d] -> [%dx%d]) | " - "Addr: (0x%x -> 0x%x)", - src_area->x1, src_area->y1, src_area->x2, src_area->y2, - dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2, - lv_area_get_width(src_area), lv_area_get_height(src_area), - lv_area_get_width(dest_area), lv_area_get_height(dest_area), - (uintptr_t)src_buf, (uintptr_t)dest_buf); - - /* Stage 1: Move starting pointers as close as possible to [x1, y1], so coordinates are as small as possible. */ - align_x(src_area, (lv_color_t **)&src_buf); - align_y(src_area, (lv_color_t **)&src_buf, src_stride); - align_x(dest_area, (lv_color_t **)&dest_buf); - align_y(dest_area, (lv_color_t **)&dest_buf, dest_stride); - - /* Stage 2: If we're in limit, do a single BLIT */ - if((src_area->x2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) && - (src_area->y2 < LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR)) { - if(check_src_alignment(src_buf, src_stride) != LV_RES_OK) - VG_LITE_RETURN_INV("Check src alignment failed."); - - /* Set new dest_vgbuf and src_vgbuf memory addresses. */ - lv_vglite_set_dest_buf_ptr(dest_buf); - lv_vglite_set_src_buf_ptr(src_buf); - - /* Set scissor */ - lv_vglite_set_scissor(dest_area); - - /* Set vgmatrix. */ - lv_vglite_set_translation_matrix(dest_area); - - /* Start blit. */ - rv = lv_vglite_blit(src_area, opa); - - /* Disable scissor. */ - lv_vglite_disable_scissor(); - - VG_LITE_LOG_TRACE("Single " - "Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | " - "Size: ([%dx%d] -> [%dx%d]) | " - "Addr: (0x%x -> 0x%x) %s", - src_area->x1, src_area->y1, src_area->x2, src_area->y2, - dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2, - lv_area_get_width(src_area), lv_area_get_height(src_area), - lv_area_get_width(dest_area), lv_area_get_height(dest_area), - (uintptr_t)src_buf, (uintptr_t)dest_buf, - rv == LV_RES_OK ? "OK!" : "FAILED!"); - - return rv; - }; - - /* Stage 3: Split the BLIT into multiple tiles */ - VG_LITE_LOG_TRACE("Split " - "Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | " - "Size: ([%dx%d] -> [%dx%d]) | " - "Addr: (0x%x -> 0x%x)", - src_area->x1, src_area->y1, src_area->x2, src_area->y2, - dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2, - lv_area_get_width(src_area), lv_area_get_height(src_area), - lv_area_get_width(dest_area), lv_area_get_height(dest_area), - (uintptr_t)src_buf, (uintptr_t)dest_buf); - - - lv_coord_t width = lv_area_get_width(src_area); - lv_coord_t height = lv_area_get_height(src_area); - - /* Number of tiles needed */ - int total_tiles_x = (src_area->x1 + width + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) / - LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; - int total_tiles_y = (src_area->y1 + height + LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1) / - LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; - - /* src and dst buffer shift against each other. Src buffer real data [0,0] may start actually at [3,0] in buffer, as - * the buffer pointer has to be aligned, while dst buffer real data [0,0] may start at [1,0] in buffer. alignment may be - * different */ - int shift_src_x = (src_area->x1 > dest_area->x1) ? (src_area->x1 - dest_area->x1) : 0; - int shift_dest_x = (src_area->x1 < dest_area->x1) ? (dest_area->x1 - src_area->x1) : 0; - - VG_LITE_LOG_TRACE("X shift: src: %d, dst: %d", shift_src_x, shift_dest_x); - - lv_color_t * tile_dest_buf; - lv_area_t tile_dest_area; - const lv_color_t * tile_src_buf; - lv_area_t tile_src_area; - - for(int y = 0; y < total_tiles_y; y++) { - - tile_src_area.y1 = 0; /* no vertical alignment, always start from 0 */ - tile_src_area.y2 = height - y * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; - if(tile_src_area.y2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) { - tile_src_area.y2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; /* Should never happen */ - } - tile_src_buf = src_buf + y * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * src_stride; - - tile_dest_area.y1 = tile_src_area.y1; /* y has no alignment, always in sync with src */ - tile_dest_area.y2 = tile_src_area.y2; - - tile_dest_buf = dest_buf + y * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR * dest_stride; - - for(int x = 0; x < total_tiles_x; x++) { - - if(x == 0) { - /* 1st tile is special - there may be a gap between buffer start pointer - * and area.x1 value, as the pointer has to be aligned. - * tile_src_buf pointer - keep init value from Y-loop. - * Also, 1st tile start is not shifted! shift is applied from 2nd tile */ - tile_src_area.x1 = src_area->x1; - tile_dest_area.x1 = dest_area->x1; - } - else { - /* subsequent tiles always starts from 0, but shifted*/ - tile_src_area.x1 = 0 + shift_src_x; - tile_dest_area.x1 = 0 + shift_dest_x; - /* and advance start pointer + 1 tile size */ - tile_src_buf += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; - tile_dest_buf += LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR; - } - - /* Clip tile end coordinates */ - tile_src_area.x2 = width + src_area->x1 - x * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; - if(tile_src_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) { - tile_src_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; - } - - tile_dest_area.x2 = width + dest_area->x1 - x * LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; - if(tile_dest_area.x2 >= LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR) { - tile_dest_area.x2 = LV_GPU_NXP_VG_LITE_BLIT_SPLIT_THR - 1; - } - - if(x < (total_tiles_x - 1)) { - /* And adjust end coords if shifted, but not for last tile! */ - tile_src_area.x2 += shift_src_x; - tile_dest_area.x2 += shift_dest_x; - } - - if(check_src_alignment(tile_src_buf, src_stride) != LV_RES_OK) - VG_LITE_RETURN_INV("Check src alignment failed."); - - /* Set new dest_vgbuf and src_vgbuf memory addresses. */ - lv_vglite_set_dest_buf_ptr(tile_dest_buf); - lv_vglite_set_src_buf_ptr(tile_src_buf); - - /* Set scissor */ - lv_vglite_set_scissor(&tile_dest_area); - - /* Set vgmatrix. */ - lv_vglite_set_translation_matrix(&tile_dest_area); - - /* Start blit. */ - rv = lv_vglite_blit(&tile_src_area, opa); - - /* Disable scissor. */ - lv_vglite_disable_scissor(); - - VG_LITE_LOG_TRACE("Tile [%d, %d] " - "Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | " - "Size: ([%dx%d] -> [%dx%d]) | " - "Addr: (0x%x -> 0x%x) %s", - x, y, - tile_src_area.x1, tile_src_area.y1, tile_src_area.x2, tile_src_area.y2, - tile_dest_area.x1, tile_dest_area.y1, tile_dest_area.x2, tile_dest_area.y2, - lv_area_get_width(&tile_src_area), lv_area_get_height(&tile_src_area), - lv_area_get_width(&tile_dest_area), lv_area_get_height(&tile_dest_area), - (uintptr_t)tile_src_buf, (uintptr_t)tile_dest_buf, - rv == LV_RES_OK ? "OK!" : "FAILED!"); - - if(rv != LV_RES_OK) { - return rv; - } - } - } - - return rv; -} -#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/ - -static lv_res_t lv_vglite_blit(const lv_area_t * src_area, lv_opa_t opa) -{ - vg_lite_error_t err = VG_LITE_SUCCESS; - vg_lite_buffer_t * dst_vgbuf = lv_vglite_get_dest_buf(); - vg_lite_buffer_t * src_vgbuf = lv_vglite_get_src_buf(); - - uint32_t rect[] = { - (uint32_t)src_area->x1, /* start x */ - (uint32_t)src_area->y1, /* start y */ - (uint32_t)lv_area_get_width(src_area), /* width */ - (uint32_t)lv_area_get_height(src_area) /* height */ - }; - - uint32_t color; - vg_lite_blend_t blend; - if(opa >= (lv_opa_t)LV_OPA_MAX) { - color = 0xFFFFFFFFU; - blend = VG_LITE_BLEND_SRC_OVER; - src_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT; - } - else { - if(vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) { - color = (opa << 24) | 0x00FFFFFFU; - } - else { - color = (opa << 24) | (opa << 16) | (opa << 8) | opa; - } - blend = VG_LITE_BLEND_SRC_OVER; - src_vgbuf->image_mode = VG_LITE_MULTIPLY_IMAGE_MODE; - src_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT; - } - - err = vg_lite_blit_rect(dst_vgbuf, src_vgbuf, rect, &vgmatrix, blend, color, VG_LITE_FILTER_POINT); - VG_LITE_ERR_RETURN_INV(err, "Blit rectangle failed."); - - if(lv_vglite_run() != LV_RES_OK) - VG_LITE_RETURN_INV("Run failed."); - - return LV_RES_OK; -} - -static lv_res_t check_src_alignment(const lv_color_t * src_buf, lv_coord_t src_stride) -{ - /* No alignment requirement for destination pixel buffer when using mode VG_LITE_LINEAR */ - - /* Test for pointer alignment */ - if((((uintptr_t)src_buf) % (uintptr_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE) != (uintptr_t)0x0U) - VG_LITE_RETURN_INV("Src buffer ptr (0x%x) not aligned to 0x%x bytes.", - (size_t)src_buf, LV_ATTRIBUTE_MEM_ALIGN_SIZE); - - /* Test for stride alignment */ - if((src_stride % (lv_coord_t)LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX) != 0x0U) - VG_LITE_RETURN_INV("Src buffer stride (%d px) not aligned to %d px.", - src_stride, LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX); - return LV_RES_OK; -} - -static inline void lv_vglite_set_translation_matrix(const lv_area_t * dest_area) -{ - vg_lite_identity(&vgmatrix); - vg_lite_translate((vg_lite_float_t)dest_area->x1, (vg_lite_float_t)dest_area->y1, &vgmatrix); -} - -static inline void lv_vglite_set_transformation_matrix(const lv_area_t * dest_area, const lv_draw_img_dsc_t * dsc) -{ - lv_vglite_set_translation_matrix(dest_area); - - bool has_scale = (dsc->zoom != LV_IMG_ZOOM_NONE); - bool has_rotation = (dsc->angle != 0); - - vg_lite_translate(dsc->pivot.x, dsc->pivot.y, &vgmatrix); - if(has_rotation) - vg_lite_rotate(dsc->angle / 10.0f, &vgmatrix); /* angle is 1/10 degree */ - if(has_scale) { - vg_lite_float_t scale = 1.0f * dsc->zoom / LV_IMG_ZOOM_NONE; - vg_lite_scale(scale, scale, &vgmatrix); - } - vg_lite_translate(0.0f - dsc->pivot.x, 0.0f - dsc->pivot.y, &vgmatrix); -} - -#if VG_LITE_BLIT_SPLIT_ENABLED -static void align_x(lv_area_t * area, lv_color_t ** buf) -{ - int alignedAreaStartPx = area->x1 - (area->x1 % (LV_ATTRIBUTE_MEM_ALIGN_SIZE / sizeof(lv_color_t))); - VG_LITE_COND_STOP(alignedAreaStartPx < 0, "Negative X alignment."); - - area->x1 -= alignedAreaStartPx; - area->x2 -= alignedAreaStartPx; - *buf += alignedAreaStartPx; -} - -static void align_y(lv_area_t * area, lv_color_t ** buf, lv_coord_t stride) -{ - int LineToAlignMem; - int alignedAreaStartPy; - /* find how many lines of pixels will respect memory alignment requirement */ - if((stride % (lv_coord_t)LV_ATTRIBUTE_MEM_ALIGN_SIZE) == 0x0U) { - alignedAreaStartPy = area->y1; - } - else { - LineToAlignMem = LV_ATTRIBUTE_MEM_ALIGN_SIZE / (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t)); - VG_LITE_COND_STOP(LV_ATTRIBUTE_MEM_ALIGN_SIZE % (LV_GPU_NXP_VG_LITE_STRIDE_ALIGN_PX * sizeof(lv_color_t)), - "Complex case: need gcd function."); - alignedAreaStartPy = area->y1 - (area->y1 % LineToAlignMem); - VG_LITE_COND_STOP(alignedAreaStartPy < 0, "Negative Y alignment."); - } - - area->y1 -= alignedAreaStartPy; - area->y2 -= alignedAreaStartPy; - *buf += (uint32_t)(alignedAreaStartPy * stride); -} -#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/ - -#endif /*LV_USE_GPU_NXP_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.h deleted file mode 100644 index 1aae34bd9..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.h +++ /dev/null @@ -1,168 +0,0 @@ -/** - * @file lv_draw_vglite_blend.h - * - */ - -/** - * MIT License - * - * Copyright 2020-2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef LV_DRAW_VGLITE_BLEND_H -#define LV_DRAW_VGLITE_BLEND_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ - -#include "../../../lv_conf_internal.h" - -#if LV_USE_GPU_NXP_VG_LITE -#include "lv_vglite_utils.h" - -/********************* - * DEFINES - *********************/ - -/** - * Enable BLIT quality degradation workaround for RT595, - * recommended for screen's dimension > 352 pixels. - */ -#define RT595_BLIT_WRKRND_ENABLED 1 - -/* Internal compound symbol */ -#if (defined(CPU_MIMXRT595SFFOB) || defined(CPU_MIMXRT595SFFOB_cm33) || \ - defined(CPU_MIMXRT595SFFOC) || defined(CPU_MIMXRT595SFFOC_cm33)) && \ - RT595_BLIT_WRKRND_ENABLED -#define VG_LITE_BLIT_SPLIT_ENABLED 1 -#else -#define VG_LITE_BLIT_SPLIT_ENABLED 0 -#endif - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Fill area, with optional opacity. - * - * @param[in] dest_area Area with relative coordinates of destination buffer - * @param[in] color Color - * @param[in] opa Opacity (255 = full, 128 = 50% background/50% color, 0 = no fill) - * - * @retval LV_RES_OK Fill completed - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) - */ -lv_res_t lv_gpu_nxp_vglite_fill(const lv_area_t * dest_area, lv_color_t color, lv_opa_t opa); - -#if VG_LITE_BLIT_SPLIT_ENABLED -/** - * BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects. - * By default, image is copied directly, with optional opacity. - * - * @param[in/out] dest_buf Destination buffer - * @param[in] dest_area Area with relative coordinates of destination buffer - * @param[in] dest_stride Stride of destination buffer in pixels - * @param[in] src_buf Source buffer - * @param[in] src_area Source area with relative coordinates of source buffer - * @param[in] src_stride Stride of source buffer in pixels - * @param[in] opa Opacity - * - * @retval LV_RES_OK Transfer complete - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) - */ -lv_res_t lv_gpu_nxp_vglite_blit_split(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, lv_area_t * src_area, lv_coord_t src_stride, - lv_opa_t opa); -#else -/** - * BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects. - * By default, image is copied directly, with optional opacity. - * - * @param[in] dest_stride Stride of destination buffer in pixels - * @param[in] src_buf Source buffer - * @param[in] src_area Source area with relative coordinates of source buffer - * @param[in] src_stride Stride of source buffer in pixels - * @param[in] opa Opacity - * - * @retval LV_RES_OK Transfer complete - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) - */ -lv_res_t lv_gpu_nxp_vglite_blit(const lv_area_t * dest_area, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, - lv_opa_t opa); - -/** - * BLock Image Transfer - copy rectangular image from src_buf to dst_buf with transformation. - * By default, image is copied directly, with optional opacity. - * - * @param[in] dest_area Area with relative coordinates of destination buffer - * @param[in] clip_area Clip area with relative coordinates of destination buffer - * @param[in] src_buf Source buffer - * @param[in] src_area Source area with relative coordinates of source buffer - * @param[in] src_stride Stride of source buffer in pixels - * @param[in] dsc Image descriptor - * - * @retval LV_RES_OK Transfer complete - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) - */ -lv_res_t lv_gpu_nxp_vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * clip_area, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride, - const lv_draw_img_dsc_t * dsc); - -#endif /*VG_LITE_BLIT_SPLIT_ENABLED*/ - -/** - * BLock Image Transfer - simple copy of rectangular image from source to destination. - * - * @param[in] dest_buf Destination buffer - * @param[in] dest_area Area with relative coordinates of destination buffer - * @param[in] dest_stride Stride of destination buffer in pixels - * @param[in] src_buf Source buffer - * @param[in] src_area Source area with relative coordinates of source buffer - * @param[in] src_stride Stride of source buffer in pixels - * - * @retval LV_RES_OK Transfer complete - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) - */ -lv_res_t lv_gpu_nxp_vglite_buffer_copy(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_GPU_NXP_VG_LITE*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_VGLITE_BLEND_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_border.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_border.c new file mode 100644 index 000000000..eb8c93bae --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_border.c @@ -0,0 +1,150 @@ +/** + * @file lv_draw_vglite_border.c + * + */ + +/** + * Copyright 2022-2024 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vglite.h" + +#if LV_USE_DRAW_VGLITE +#include "lv_vglite_buf.h" +#include "lv_vglite_path.h" +#include "lv_vglite_utils.h" + +#include + +/********************* + * DEFINES + *********************/ + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/** + * Draw rectangle border/outline shape with effects (rounded corners, opacity) + * + * @param[in] coords Coordinates of the rectangle border/outline (relative to dest buff) + * @param[in] clip_area Clip area with relative coordinates to dest buff + * @param[in] dsc Description of the rectangle border/outline + * + */ +static void _vglite_draw_border(const lv_area_t * coords, const lv_area_t * clip_area, + const lv_draw_border_dsc_t * dsc); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vglite_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, + const lv_area_t * coords) +{ + if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) + return; + if(dsc->width == 0) + return; + if(dsc->side == (lv_border_side_t)LV_BORDER_SIDE_NONE) + return; + + lv_layer_t * layer = draw_unit->target_layer; + lv_area_t inward_coords; + int32_t width = dsc->width; + + /* Move border inwards to align with software rendered border */ + inward_coords.x1 = coords->x1 + ceil(width / 2.0f); + inward_coords.x2 = coords->x2 - floor(width / 2.0f); + inward_coords.y1 = coords->y1 + ceil(width / 2.0f); + inward_coords.y2 = coords->y2 - floor(width / 2.0f); + + lv_area_move(&inward_coords, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t clip_area; + lv_area_copy(&clip_area, draw_unit->clip_area); + lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t clipped_coords; + if(!_lv_area_intersect(&clipped_coords, &inward_coords, &clip_area)) + return; /*Fully clipped, nothing to do*/ + + _vglite_draw_border(&inward_coords, &clip_area, dsc); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void _vglite_draw_border(const lv_area_t * coords, const lv_area_t * clip_area, + const lv_draw_border_dsc_t * dsc) +{ + int32_t radius = dsc->radius; + vg_lite_buffer_t * vgbuf = vglite_get_dest_buf(); + + if(radius < 0) + return; + + int32_t border_half = (int32_t)floor(dsc->width / 2.0f); + if(radius > border_half) + radius = radius - border_half; + + vg_lite_cap_style_t cap_style = (radius) ? VG_LITE_CAP_ROUND : VG_LITE_CAP_BUTT; + vg_lite_join_style_t join_style = (radius) ? VG_LITE_JOIN_ROUND : VG_LITE_JOIN_MITER; + + /*** Init path ***/ + int32_t path_data[RECT_PATH_DATA_MAX_SIZE]; + uint32_t path_data_size; + vglite_create_rect_path_data(path_data, &path_data_size, radius, coords); + vg_lite_quality_t path_quality = radius > 0 ? VG_LITE_HIGH : VG_LITE_MEDIUM; + + vg_lite_path_t path; + VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data, + (vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1, + ((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f)); + + lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa); + vg_lite_color_t vgcol = vglite_get_color(col32, false); + + vg_lite_matrix_t matrix; + vg_lite_identity(&matrix); + + int32_t line_width = dsc->width; + + /*** Draw border ***/ + VGLITE_CHECK_ERROR(vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH)); + + VGLITE_CHECK_ERROR(vg_lite_set_stroke(&path, cap_style, join_style, line_width, 8, NULL, 0, 0, vgcol)); + + VGLITE_CHECK_ERROR(vg_lite_update_stroke(&path)); + + VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol)); + + vglite_run(); + + VGLITE_CHECK_ERROR(vg_lite_clear_path(&path)); +} + +#endif /*LV_USE_DRAW_VGLITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_fill.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_fill.c new file mode 100644 index 000000000..bf066859e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_fill.c @@ -0,0 +1,237 @@ +/** + * @file lv_draw_vglite_fill.c + * + */ + +/** + * Copyright 2020-2024 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vglite.h" + +#if LV_USE_DRAW_VGLITE +#include "lv_vglite_buf.h" +#include "lv_vglite_path.h" +#include "lv_vglite_utils.h" + +#include "../../../stdlib/lv_string.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/** + * Fill area, with optional opacity. + * + * @param[in] dest_area Area with relative coordinates of destination buffer + * @param[in] dsc Description of the area to fill (color, opa) + * + */ +static void _vglite_fill(const lv_area_t * dest_area, const lv_draw_fill_dsc_t * dsc); + +/** + * Draw rectangle background with effects (rounded corners, gradient) + * + * @param[in] coords Coordinates of the rectangle background (relative to dest buff) + * @param[in] clip_area Clip area with relative coordinates to dest buff + * @param[in] dsc Description of the rectangle background + * + */ +static void _vglite_draw_rect(const lv_area_t * coords, const lv_area_t * clip_area, + const lv_draw_fill_dsc_t * dsc); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vglite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, + const lv_area_t * coords) +{ + if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) + return; + + lv_layer_t * layer = draw_unit->target_layer; + lv_area_t relative_coords; + lv_area_copy(&relative_coords, coords); + lv_area_move(&relative_coords, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t clip_area; + lv_area_copy(&clip_area, draw_unit->clip_area); + lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t clipped_coords; + if(!_lv_area_intersect(&clipped_coords, &relative_coords, &clip_area)) + return; /*Fully clipped, nothing to do*/ + + /* + * Most simple case: just a plain rectangle (no radius, no gradient) + */ + if((dsc->radius == 0) && (dsc->grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE)) + _vglite_fill(&clipped_coords, dsc); + else + _vglite_draw_rect(&relative_coords, &clip_area, dsc); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void _vglite_fill(const lv_area_t * dest_area, const lv_draw_fill_dsc_t * dsc) +{ + vg_lite_buffer_t * vgbuf = vglite_get_dest_buf(); + + lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa); + vg_lite_color_t vgcol = vglite_get_color(col32, false); + + if(dsc->opa >= (lv_opa_t)LV_OPA_MAX) { /*Opaque fill*/ + vg_lite_rectangle_t rect = { + .x = dest_area->x1, + .y = dest_area->y1, + .width = lv_area_get_width(dest_area), + .height = lv_area_get_height(dest_area) + }; + + VGLITE_CHECK_ERROR(vg_lite_clear(vgbuf, &rect, vgcol)); + + vglite_run(); + } + else { /*fill with transparency*/ + + vg_lite_path_t path; + int32_t path_data[] = { /*VG rectangular path*/ + VLC_OP_MOVE, dest_area->x1, dest_area->y1, + VLC_OP_LINE, dest_area->x2 + 1, dest_area->y1, + VLC_OP_LINE, dest_area->x2 + 1, dest_area->y2 + 1, + VLC_OP_LINE, dest_area->x1, dest_area->y2 + 1, + VLC_OP_LINE, dest_area->x1, dest_area->y1, + VLC_OP_END + }; + + VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_MEDIUM, sizeof(path_data), path_data, + (vg_lite_float_t) dest_area->x1, (vg_lite_float_t) dest_area->y1, + ((vg_lite_float_t) dest_area->x2) + 1.0f, ((vg_lite_float_t) dest_area->y2) + 1.0f)); + + vg_lite_matrix_t matrix; + vg_lite_identity(&matrix); + + /*Draw rectangle*/ + VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol)); + + vglite_run(); + + VGLITE_CHECK_ERROR(vg_lite_clear_path(&path)); + } +} + +static void _vglite_draw_rect(const lv_area_t * coords, const lv_area_t * clip_area, + const lv_draw_fill_dsc_t * dsc) +{ + int32_t width = lv_area_get_width(coords); + int32_t height = lv_area_get_height(coords); + int32_t radius = dsc->radius; + lv_opa_t opa = dsc->opa; + vg_lite_buffer_t * vgbuf = vglite_get_dest_buf(); + + if(dsc->radius < 0) + return; + + /*** Init path ***/ + int32_t path_data[RECT_PATH_DATA_MAX_SIZE]; + uint32_t path_data_size; + vglite_create_rect_path_data(path_data, &path_data_size, radius, coords); + vg_lite_quality_t path_quality = dsc->radius > 0 ? VG_LITE_HIGH : VG_LITE_MEDIUM; + + vg_lite_path_t path; + VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data, + (vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1, + ((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f)); + + vg_lite_matrix_t matrix; + vg_lite_identity(&matrix); + + /*** Init Color ***/ + lv_color32_t col32 = lv_color_to_32(dsc->color, opa); + vg_lite_color_t vgcol = vglite_get_color(col32, false); + + vg_lite_linear_gradient_t gradient; + bool has_gradient = (dsc->grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE); + + /*** Init Gradient ***/ + if(has_gradient) { + vg_lite_matrix_t * grad_matrix; + + vg_lite_uint32_t colors[LV_GRADIENT_MAX_STOPS]; + vg_lite_uint32_t stops[LV_GRADIENT_MAX_STOPS]; + lv_color32_t col32[LV_GRADIENT_MAX_STOPS]; + + /* Gradient setup */ + vg_lite_uint32_t cnt = LV_MAX(dsc->grad.stops_count, LV_GRADIENT_MAX_STOPS); + lv_opa_t opa; + + for(uint8_t i = 0; i < cnt; i++) { + stops[i] = dsc->grad.stops[i].frac; + + opa = LV_OPA_MIX2(dsc->grad.stops[i].opa, dsc->opa); + + col32[i] = lv_color_to_32(dsc->grad.stops[i].color, opa); + colors[i] = vglite_get_color(col32[i], true); + } + + lv_memzero(&gradient, sizeof(vg_lite_linear_gradient_t)); + + VGLITE_CHECK_ERROR(vg_lite_init_grad(&gradient)); + + VGLITE_CHECK_ERROR(vg_lite_set_grad(&gradient, cnt, colors, stops)); + + VGLITE_CHECK_ERROR(vg_lite_update_grad(&gradient)); + + grad_matrix = vg_lite_get_grad_matrix(&gradient); + vg_lite_identity(grad_matrix); + vg_lite_translate((float)coords->x1, (float)coords->y1, grad_matrix); + + if(dsc->grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_VER) { + vg_lite_scale(1.0f, (float)height / 256.0f, grad_matrix); + vg_lite_rotate(90.0f, grad_matrix); + } + else { /*LV_GRAD_DIR_HOR*/ + vg_lite_scale((float)width / 256.0f, 1.0f, grad_matrix); + } + + VGLITE_CHECK_ERROR(vg_lite_draw_gradient(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient, + VG_LITE_BLEND_SRC_OVER)); + } + else { + VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol)); + } + + vglite_run(); + + VGLITE_CHECK_ERROR(vg_lite_clear_path(&path)); + + if(has_gradient) + VGLITE_CHECK_ERROR(vg_lite_clear_grad(&gradient)); +} + +#endif /*LV_USE_DRAW_VGLITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_img.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_img.c new file mode 100644 index 000000000..6dacad88b --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_img.c @@ -0,0 +1,401 @@ +/** + * @file lv_draw_vglite_blend.c + * + */ + +/** + * Copyright 2020-2024 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vglite.h" + +#if LV_USE_DRAW_VGLITE +#include "lv_vglite_buf.h" +#include "lv_vglite_matrix.h" +#include "lv_vglite_utils.h" + +#include "../../../misc/lv_log.h" + +/********************* + * DEFINES + *********************/ + +#if LV_USE_VGLITE_BLIT_SPLIT +/** +* BLIT split threshold - BLITs with width or height higher than this value will +* be done in multiple steps. Value must be multiple of stride alignment in px. +* For most color formats the alignment is 16px (except the index formats). +*/ +#define VGLITE_BLIT_SPLIT_THR 352 + +/* Enable for logging debug traces. */ +#define VGLITE_LOG_TRACE 0 + +#if VGLITE_LOG_TRACE +#define VGLITE_TRACE(fmt, ...) \ + do { \ + LV_LOG(fmt, ##__VA_ARGS__); \ + } while (0) +#else +#define VGLITE_TRACE(fmt, ...) \ + do { \ + } while (0) +#endif +#endif /*LV_USE_VGLITE_BLIT_SPLIT*/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/** + * BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects. + * By default, image is copied directly, with optional opacity. + * + * @param[in] dest_area Destination area with relative coordinates to dest buffer + * @param[in] src_area Source area with relative coordinates to src buffer + * @param[in] dsc Image descriptor + * + */ +static void _vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area, + const lv_draw_image_dsc_t * dsc); + +#if LV_USE_VGLITE_BLIT_SPLIT +/** + * Move buffer pointer as close as possible to area, but with respect to alignment requirements. + * + * @param[in] buf Buffer address pointer + * @param[in] area Area with relative coordinates to the buffer + * @param[in] stride Stride of buffer in bytes + * @param[in] cf Color format of buffer + */ +static void _move_buf_close_to_area(void ** buf, lv_area_t * area, uint32_t stride, lv_color_format_t cf); + +/** + * BLock Image Transfer - copy rectangular image from src_buf to dst_buf with effects. + * By default, image is copied directly, with optional opacity. + * + * @param dest_buf Destination buffer + * @param[in] dest_area Destination area with relative coordinates to dest buffer + * @param[in] dest_stride Stride of destination buffer in bytes + * @param[in] dest_cf Color format of destination buffer + * @param[in] src_buf Source buffer + * @param[in] src_area Source area with relative coordinates to src buffer + * @param[in] src_stride Stride of source buffer in bytes + * @param[in] src_cf Color format of source buffer + * @param[in] dsc Image descriptor + * + */ +static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t dest_stride, lv_color_format_t dest_cf, + const void * src_buf, lv_area_t * src_area, uint32_t src_stride, lv_color_format_t src_cf, + const lv_draw_image_dsc_t * dsc); +#else +/** + * BLock Image Transfer - copy rectangular image from src_buf to dst_buf with transformation. + * By default, image is copied directly, with optional opacity. + * + * @param[in] dest_area Area with relative coordinates to dest buffer + * @param[in] src_area Source area with relative coordinates to src buffer + * @param[in] dsc Image descriptor + * + */ +static void _vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * src_area, + const lv_draw_image_dsc_t * dsc); +#endif /*LV_USE_VGLITE_BLIT_SPLIT*/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vglite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc, + const lv_area_t * coords) +{ + if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) + return; + + lv_layer_t * layer = draw_unit->target_layer; + const lv_image_dsc_t * img_dsc = dsc->src; + + lv_area_t relative_coords; + lv_area_copy(&relative_coords, coords); + lv_area_move(&relative_coords, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t clip_area; + lv_area_copy(&clip_area, draw_unit->clip_area); + lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t blend_area; + bool has_transform = (dsc->rotation != 0 || dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE); + if(has_transform) + lv_area_copy(&blend_area, &relative_coords); + else if(!_lv_area_intersect(&blend_area, &relative_coords, &clip_area)) + return; /*Fully clipped, nothing to do*/ + + const void * src_buf = img_dsc->data; + + lv_area_t src_area; + src_area.x1 = blend_area.x1 - (coords->x1 - layer->buf_area.x1); + src_area.y1 = blend_area.y1 - (coords->y1 - layer->buf_area.y1); + src_area.x2 = img_dsc->header.w - 1; + src_area.y2 = img_dsc->header.h - 1; + + lv_color_format_t src_cf = img_dsc->header.cf; + uint32_t src_stride = img_dsc->header.stride; + + /* Set src_vgbuf structure. */ + vglite_set_src_buf(src_buf, lv_area_get_width(&src_area), lv_area_get_height(&src_area), src_stride, src_cf); + +#if LV_USE_VGLITE_BLIT_SPLIT + void * dest_buf = layer->draw_buf->data; + uint32_t dest_stride = layer->draw_buf->header.stride; + lv_color_format_t dest_cf = layer->draw_buf->header.cf; + + if(!has_transform) + _vglite_blit_split(dest_buf, &blend_area, dest_stride, dest_cf, + src_buf, &src_area, src_stride, src_cf, dsc); +#else + if(has_transform) + _vglite_blit_transform(&blend_area, &src_area, dsc); + else + _vglite_blit_single(&blend_area, &src_area, dsc); +#endif /*LV_USE_VGLITE_BLIT_SPLIT*/ +} + +/********************** + * STATIC FUNCTIONS + **********************/ +static void _vglite_blit(const lv_area_t * src_area, const lv_draw_image_dsc_t * dsc) +{ + vg_lite_buffer_t * dst_vgbuf = vglite_get_dest_buf(); + vg_lite_buffer_t * src_vgbuf = vglite_get_src_buf(); + + vg_lite_rectangle_t rect = { + .x = (vg_lite_int32_t)src_area->x1, + .y = (vg_lite_int32_t)src_area->y1, + .width = (vg_lite_int32_t)lv_area_get_width(src_area), + .height = (vg_lite_int32_t)lv_area_get_height(src_area) + }; + + src_vgbuf->image_mode = VG_LITE_MULTIPLY_IMAGE_MODE; + src_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT; + + lv_color_t color; + lv_opa_t opa; + + bool has_recolor = (dsc->recolor_opa > LV_OPA_MIN); + if(has_recolor) { + color = dsc->recolor; + opa = LV_OPA_MIX2(dsc->recolor_opa, dsc->opa); + } + else { + color.red = 0xFF; + color.green = 0xFF; + color.blue = 0xFF; + opa = dsc->opa; + } + + lv_color32_t col32 = lv_color_to_32(color, opa); + vg_lite_color_t vgcol = vglite_get_color(col32, false); + + vg_lite_matrix_t * vgmatrix = vglite_get_matrix(); + vg_lite_blend_t vgblend = vglite_get_blend_mode(dsc->blend_mode); + + VGLITE_CHECK_ERROR(vg_lite_blit_rect(dst_vgbuf, src_vgbuf, &rect, vgmatrix, vgblend, vgcol, VG_LITE_FILTER_POINT)); + + vglite_run(); +} + +static void _vglite_blit_single(const lv_area_t * dest_area, const lv_area_t * src_area, + const lv_draw_image_dsc_t * dsc) +{ + /* Set vgmatrix. */ + vglite_set_translation_matrix(dest_area); + + /* Start blit. */ + _vglite_blit(src_area, dsc); +} + +#if LV_USE_VGLITE_BLIT_SPLIT +static void _move_buf_close_to_area(void ** buf, lv_area_t * area, uint32_t stride, lv_color_format_t cf) +{ + uint8_t ** buf_u8 = (uint8_t **)buf; + uint8_t align_bytes = vglite_get_alignment(cf); + uint8_t bits_per_pixel = lv_color_format_get_bpp(cf); + + uint16_t align_pixels = align_bytes * 8 / bits_per_pixel; + + if(area->x1 >= (int32_t)(area->x1 % align_pixels)) { + uint16_t shift_x = area->x1 - (area->x1 % align_pixels); + + area->x1 -= shift_x; + area->x2 -= shift_x; + *buf_u8 += (shift_x * bits_per_pixel) / 8; + } + + if(area->y1) { + uint16_t shift_y = area->y1; + + area->y1 -= shift_y; + area->y2 -= shift_y; + *buf_u8 += shift_y * stride; + } +} + +static void _vglite_blit_split(void * dest_buf, lv_area_t * dest_area, uint32_t dest_stride, lv_color_format_t dest_cf, + const void * src_buf, lv_area_t * src_area, uint32_t src_stride, lv_color_format_t src_cf, + const lv_draw_image_dsc_t * dsc) +{ + VGLITE_TRACE("Blit " + "Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | " + "Size: ([%dx%d] -> [%dx%d]) | " + "Addr: (0x%x -> 0x%x)", + src_area->x1, src_area->y1, src_area->x2, src_area->y2, + dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2, + lv_area_get_width(src_area), lv_area_get_height(src_area), + lv_area_get_width(dest_area), lv_area_get_height(dest_area), + (uintptr_t)src_buf, (uintptr_t)dest_buf); + + /* Move starting pointers as close as possible to [x1, y1], so coordinates are as small as possible */ + _move_buf_close_to_area((void **)&src_buf, src_area, src_stride, src_cf); + _move_buf_close_to_area(&dest_buf, dest_area, dest_stride, dest_cf); + + /* If we're in limit, do a single BLIT */ + if((src_area->x2 < VGLITE_BLIT_SPLIT_THR) && + (src_area->y2 < VGLITE_BLIT_SPLIT_THR)) { + + /* Set new dest_vgbuf and src_vgbuf memory addresses */ + vglite_set_dest_buf_ptr(dest_buf); + vglite_set_src_buf_ptr(src_buf); + + _vglite_blit_single(dest_area, src_area, dsc); + + VGLITE_TRACE("Single " + "Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | " + "Size: ([%dx%d] -> [%dx%d]) | " + "Addr: (0x%x -> 0x%x)", + src_area->x1, src_area->y1, src_area->x2, src_area->y2, + dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2, + lv_area_get_width(src_area), lv_area_get_height(src_area), + lv_area_get_width(dest_area), lv_area_get_height(dest_area), + (uintptr_t)src_buf, (uintptr_t)dest_buf); + }; + + /* Split the BLIT into multiple tiles */ + VGLITE_TRACE("Split " + "Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | " + "Size: ([%dx%d] -> [%dx%d]) | " + "Addr: (0x%x -> 0x%x)", + src_area->x1, src_area->y1, src_area->x2, src_area->y2, + dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2, + lv_area_get_width(src_area), lv_area_get_height(src_area), + lv_area_get_width(dest_area), lv_area_get_height(dest_area), + (uintptr_t)src_buf, (uintptr_t)dest_buf); + + int32_t width = LV_MIN(lv_area_get_width(src_area), lv_area_get_width(dest_area)); + int32_t height = LV_MIN(lv_area_get_height(src_area), lv_area_get_height(dest_area)); + + /* Number of tiles needed */ + uint8_t total_tiles_x = (src_area->x1 + width + VGLITE_BLIT_SPLIT_THR - 1) / + VGLITE_BLIT_SPLIT_THR; + uint8_t total_tiles_y = (src_area->y1 + height + VGLITE_BLIT_SPLIT_THR - 1) / + VGLITE_BLIT_SPLIT_THR; + + uint16_t shift_src_x = src_area->x1; + uint16_t shift_dest_x = dest_area->x1; + + VGLITE_TRACE("X shift: src: %d, dst: %d", shift_src_x, shift_dest_x); + + uint8_t * tile_dest_buf; + lv_area_t tile_dest_area; + const uint8_t * tile_src_buf; + lv_area_t tile_src_area; + + for(uint8_t y = 0; y < total_tiles_y; y++) { + /* y1 always start from 0 */ + tile_src_area.y1 = 0; + + /* Calculate y2 coordinates */ + if(y < total_tiles_y - 1) + tile_src_area.y2 = VGLITE_BLIT_SPLIT_THR - 1; + else + tile_src_area.y2 = height - y * VGLITE_BLIT_SPLIT_THR - 1; + + /* No vertical shift, dest y is always in sync with src y */ + tile_dest_area.y1 = tile_src_area.y1; + tile_dest_area.y2 = tile_src_area.y2; + + /* Advance start pointer for every tile, except the first column (y = 0) */ + tile_src_buf = (uint8_t *)src_buf + y * VGLITE_BLIT_SPLIT_THR * src_stride; + tile_dest_buf = (uint8_t *)dest_buf + y * VGLITE_BLIT_SPLIT_THR * dest_stride; + + for(uint8_t x = 0; x < total_tiles_x; x++) { + /* x1 always start from the same shift */ + tile_src_area.x1 = shift_src_x; + tile_dest_area.x1 = shift_dest_x; + if(x > 0) { + /* Advance start pointer for every tile, except the first raw (x = 0) */ + tile_src_buf += VGLITE_BLIT_SPLIT_THR * lv_color_format_get_bpp(src_cf) / 8; + tile_dest_buf += VGLITE_BLIT_SPLIT_THR * lv_color_format_get_bpp(dest_cf) / 8; + } + + /* Calculate x2 coordinates */ + if(x < total_tiles_x - 1) + tile_src_area.x2 = VGLITE_BLIT_SPLIT_THR - 1; + else + tile_src_area.x2 = width - x * VGLITE_BLIT_SPLIT_THR - 1; + + tile_dest_area.x2 = tile_src_area.x2; + + /* Shift x2 coordinates */ + tile_src_area.x2 += shift_src_x; + tile_dest_area.x2 += shift_dest_x; + + /* Set new dest_vgbuf and src_vgbuf memory addresses */ + vglite_set_dest_buf_ptr(tile_dest_buf); + vglite_set_src_buf_ptr(tile_src_buf); + + _vglite_blit_single(&tile_dest_area, &tile_src_area, dsc); + + VGLITE_TRACE("Tile [%d, %d] " + "Area: ([%d,%d], [%d,%d]) -> ([%d,%d], [%d,%d]) | " + "Size: ([%dx%d] -> [%dx%d]) | " + "Addr: (0x%x -> 0x%x)", + x, y, + tile_src_area.x1, tile_src_area.y1, tile_src_area.x2, tile_src_area.y2, + tile_dest_area.x1, tile_dest_area.y1, tile_dest_area.x2, tile_dest_area.y2, + lv_area_get_width(&tile_src_area), lv_area_get_height(&tile_src_area), + lv_area_get_width(&tile_dest_area), lv_area_get_height(&tile_dest_area), + (uintptr_t)tile_src_buf, (uintptr_t)tile_dest_buf); + } + } +} +#else +static void _vglite_blit_transform(const lv_area_t * dest_area, const lv_area_t * src_area, + const lv_draw_image_dsc_t * dsc) +{ + /* Set vgmatrix. */ + vglite_set_transformation_matrix(dest_area, dsc); + + /* Start blit. */ + _vglite_blit(src_area, dsc); +} +#endif /*LV_USE_VGLITE_BLIT_SPLIT*/ + +#endif /*LV_USE_DRAW_VGLITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_label.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_label.c new file mode 100644 index 000000000..587f55f79 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_label.c @@ -0,0 +1,184 @@ +/** + * @file lv_draw_vglite_label.c + * + */ + +/** + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vglite.h" + +#if LV_USE_DRAW_VGLITE +#include "lv_vglite_buf.h" +#include "lv_vglite_matrix.h" +#include "lv_vglite_utils.h" + +#include "../../../stdlib/lv_string.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void _draw_vglite_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc, + lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area); + +/** + * Draw letter (character bitmap blend) with optional color and opacity + * + * @param[in] mask_area Mask area with relative coordinates of source buffer + * @param[in] color Color + * @param[in] opa Opacity + * + */ +static void _vglite_draw_letter(const lv_area_t * mask_area, lv_color_t color, lv_opa_t opa); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * GLOBAL VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vglite_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, + const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) return; + + lv_draw_label_iterate_characters(draw_unit, dsc, coords, _draw_vglite_letter); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void _draw_vglite_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc, + lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area) +{ + if(glyph_draw_dsc) { + if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_INVALID) { +#if LV_USE_FONT_PLACEHOLDER + /* Draw a placeholder rectangle*/ + lv_draw_border_dsc_t border_draw_dsc; + lv_draw_border_dsc_init(&border_draw_dsc); + border_draw_dsc.opa = glyph_draw_dsc->opa; + border_draw_dsc.color = glyph_draw_dsc->color; + border_draw_dsc.width = 1; + lv_draw_vglite_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords); +#endif + } + else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_A8) { + /*Do not draw transparent things*/ + if(glyph_draw_dsc->opa <= LV_OPA_MIN) + return; + + lv_layer_t * layer = draw_unit->target_layer; + + lv_area_t blend_area; + if(!_lv_area_intersect(&blend_area, glyph_draw_dsc->letter_coords, draw_unit->clip_area)) + return; + lv_area_move(&blend_area, -layer->buf_area.x1, -layer->buf_area.y1); + + const lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data; + const void * mask_buf = draw_buf->data; + + uint32_t mask_width = lv_area_get_width(glyph_draw_dsc->letter_coords); + uint32_t mask_height = lv_area_get_height(glyph_draw_dsc->letter_coords); + uint32_t mask_stride = draw_buf->header.stride; + + lv_area_t mask_area; + mask_area.x1 = blend_area.x1 - (glyph_draw_dsc->letter_coords->x1 - layer->buf_area.x1); + mask_area.y1 = blend_area.y1 - (glyph_draw_dsc->letter_coords->y1 - layer->buf_area.y1); + mask_area.x2 = mask_width - 1; + mask_area.y2 = mask_height - 1; + + if(!vglite_buf_aligned(mask_buf, mask_stride, LV_COLOR_FORMAT_A8)) { + /* Draw a placeholder rectangle*/ + lv_draw_border_dsc_t border_draw_dsc; + lv_draw_border_dsc_init(&border_draw_dsc); + border_draw_dsc.opa = glyph_draw_dsc->opa; + border_draw_dsc.color = glyph_draw_dsc->color; + border_draw_dsc.width = 1; + lv_draw_vglite_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords); + } + else { + /* Set src_vgbuf structure. */ + vglite_set_src_buf(mask_buf, mask_width, mask_height, mask_stride, LV_COLOR_FORMAT_A8); + + /* Set vgmatrix. */ + vglite_set_translation_matrix(&blend_area); + + lv_draw_buf_invalidate_cache((void *)mask_buf, mask_stride, LV_COLOR_FORMAT_A8, &mask_area); + + _vglite_draw_letter(&mask_area, glyph_draw_dsc->color, glyph_draw_dsc->opa); + } + } + else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE) { +#if LV_USE_IMGFONT + lv_draw_img_dsc_t img_dsc; + lv_draw_img_dsc_init(&img_dsc); + img_dsc.angle = 0; + img_dsc.zoom = LV_ZOOM_NONE; + img_dsc.opa = glyph_draw_dsc->opa; + img_dsc.src = glyph_draw_dsc->glyph_data; + lv_draw_vglite_img(draw_unit, &img_dsc, glyph_draw_dsc->letter_coords); +#endif + } + } + + if(fill_draw_dsc && fill_area) { + lv_draw_vglite_fill(draw_unit, fill_draw_dsc, fill_area); + } +} + +static void _vglite_draw_letter(const lv_area_t * mask_area, lv_color_t color, lv_opa_t opa) +{ + vg_lite_buffer_t * dst_vgbuf = vglite_get_dest_buf(); + vg_lite_buffer_t * mask_vgbuf = vglite_get_src_buf(); + + mask_vgbuf->image_mode = VG_LITE_MULTIPLY_IMAGE_MODE; + mask_vgbuf->transparency_mode = VG_LITE_IMAGE_TRANSPARENT; + + vg_lite_rectangle_t rect = { + .x = (vg_lite_int32_t)mask_area->x1, + .y = (vg_lite_int32_t)mask_area->y1, + .width = (vg_lite_int32_t)lv_area_get_width(mask_area), + .height = (vg_lite_int32_t)lv_area_get_height(mask_area) + }; + + lv_color32_t col32 = lv_color_to_32(color, opa); + vg_lite_color_t vgcol = vglite_get_color(col32, false); + + vg_lite_matrix_t * vgmatrix = vglite_get_matrix(); + + /*Blit with font color as paint color*/ + VGLITE_CHECK_ERROR(vg_lite_blit_rect(dst_vgbuf, mask_vgbuf, &rect, vgmatrix, VG_LITE_BLEND_SRC_OVER, vgcol, + VG_LITE_FILTER_POINT)); + + vglite_run(); +} + +#endif /*LV_USE_DRAW_VGLITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_layer.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_layer.c new file mode 100644 index 000000000..3a46a142c --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_layer.c @@ -0,0 +1,159 @@ +/** + * @file lv_draw_vglite_layer.c + * + */ + +/** + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vglite.h" + +#if LV_USE_DRAW_VGLITE + +#include "../../../stdlib/lv_string.h" +#if LV_USE_PARALLEL_DRAW_DEBUG + #include "../../../core/lv_global.h" +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +#if LV_USE_PARALLEL_DRAW_DEBUG + #define _draw_info LV_GLOBAL_DEFAULT()->draw_info +#endif + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vglite_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords) +{ + lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src; + const lv_draw_buf_t * draw_buf = layer_to_draw->draw_buf; + + /* It can happen that nothing was draw on a layer and therefore its buffer is not allocated. + * In this case just return. + */ + if(draw_buf == NULL) + return; + + const lv_area_t area_to_draw = { + .x1 = 0, + .y1 = 0, + .x2 = draw_buf->header.w - 1, + .y2 = draw_buf->header.h - 1 + }; + lv_draw_buf_invalidate_cache(draw_buf->data, draw_buf->header.stride, draw_buf->header.cf, &area_to_draw); + + lv_draw_image_dsc_t new_draw_dsc = *draw_dsc; + new_draw_dsc.src = draw_buf; + lv_draw_vglite_img(draw_unit, &new_draw_dsc, coords); + +#if LV_USE_LAYER_DEBUG || LV_USE_PARALLEL_DRAW_DEBUG + lv_area_t area_rot; + lv_area_copy(&area_rot, coords); + bool has_transform = (draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE || + draw_dsc->scale_y != LV_SCALE_NONE); + + if(has_transform) { + int32_t w = lv_area_get_width(coords); + int32_t h = lv_area_get_height(coords); + + _lv_image_buf_get_transformed_area(&area_rot, w, h, draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, + &draw_dsc->pivot); + + area_rot.x1 += coords->x1; + area_rot.y1 += coords->y1; + area_rot.x2 += coords->x1; + area_rot.y2 += coords->y1; + } + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, &area_rot, draw_unit->clip_area)) return; +#endif + +#if LV_USE_LAYER_DEBUG + lv_draw_fill_dsc_t fill_dsc; + lv_draw_fill_dsc_init(&fill_dsc); + fill_dsc.color = lv_color_hex(layer_to_draw->color_format == LV_COLOR_FORMAT_ARGB8888 ? 0xff0000 : 0x00ff00); + fill_dsc.opa = LV_OPA_20; + lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot); + + lv_draw_border_dsc_t border_dsc; + lv_draw_border_dsc_init(&border_dsc); + border_dsc.color = fill_dsc.color; + border_dsc.opa = LV_OPA_60; + border_dsc.width = 2; + lv_draw_sw_border(draw_unit, &border_dsc, &area_rot); + +#endif + +#if LV_USE_PARALLEL_DRAW_DEBUG + uint32_t idx = 0; + lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head; + while(draw_unit_tmp != draw_unit) { + draw_unit_tmp = draw_unit_tmp->next; + idx++; + } + + lv_draw_fill_dsc_t fill_dsc; + lv_draw_rect_dsc_init(&fill_dsc); + fill_dsc.color = lv_palette_main(idx % _LV_PALETTE_LAST); + fill_dsc.opa = LV_OPA_10; + lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot); + + lv_draw_border_dsc_t border_dsc; + lv_draw_border_dsc_init(&border_dsc); + border_dsc.color = lv_palette_main(idx % _LV_PALETTE_LAST); + border_dsc.opa = LV_OPA_100; + border_dsc.width = 2; + lv_draw_sw_border(draw_unit, &border_dsc, &area_rot); + + lv_point_t txt_size; + lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE); + + lv_area_t txt_area; + txt_area.x1 = draw_area.x1; + txt_area.x2 = draw_area.x1 + txt_size.x - 1; + txt_area.y2 = draw_area.y2; + txt_area.y1 = draw_area.y2 - txt_size.y + 1; + + lv_draw_fill_dsc_init(&fill_dsc); + fill_dsc.color = lv_color_black(); + lv_draw_sw_fill(draw_unit, &fill_dsc, &txt_area); + + char buf[8]; + lv_snprintf(buf, sizeof(buf), "%d", idx); + lv_draw_label_dsc_t label_dsc; + lv_draw_label_dsc_init(&label_dsc); + label_dsc.color = lv_color_white(); + label_dsc.text = buf; + lv_draw_sw_label(draw_unit, &label_dsc, &txt_area); +#endif +} + +#endif /*LV_USE_DRAW_VGLITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_line.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_line.c index bf7bee11a..d458375c5 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_line.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_line.c @@ -4,38 +4,20 @@ */ /** - * MIT License - * - * Copyright 2022, 2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * Copyright 2022-2024 NXP * + * SPDX-License-Identifier: MIT */ /********************* * INCLUDES *********************/ -#include "lv_draw_vglite_line.h" +#include "lv_draw_vglite.h" -#if LV_USE_GPU_NXP_VG_LITE +#if LV_USE_DRAW_VGLITE #include "lv_vglite_buf.h" -#include +#include "lv_vglite_utils.h" /********************* * DEFINES @@ -49,6 +31,18 @@ * STATIC PROTOTYPES **********************/ +/** + * Draw line shape with effects + * + * @param[in] point1 Starting point with relative coordinates + * @param[in] point2 Ending point with relative coordinates + * @param[in] clip_area Clip area with relative coordinates to dest buff + * @param[in] dsc Line description structure (width, rounded ending, opacity, ...) + * + */ +static void _vglite_draw_line(const lv_point_t * point1, const lv_point_t * point2, + const lv_area_t * clip_area, const lv_draw_line_dsc_t * dsc); + /********************** * STATIC VARIABLES **********************/ @@ -61,13 +55,42 @@ * GLOBAL FUNCTIONS **********************/ -lv_res_t lv_gpu_nxp_vglite_draw_line(const lv_point_t * point1, const lv_point_t * point2, - const lv_area_t * clip_area, const lv_draw_line_dsc_t * dsc) +void lv_draw_vglite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc) +{ + if(dsc->width == 0) + return; + if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) + return; + if(dsc->p1.x == dsc->p2.x && dsc->p1.y == dsc->p2.y) + return; + + lv_layer_t * layer = draw_unit->target_layer; + lv_area_t clip_area; + clip_area.x1 = LV_MIN(dsc->p1.x, dsc->p2.x) - dsc->width / 2; + clip_area.x2 = LV_MAX(dsc->p1.x, dsc->p2.x) + dsc->width / 2; + clip_area.y1 = LV_MIN(dsc->p1.y, dsc->p2.y) - dsc->width / 2; + clip_area.y2 = LV_MAX(dsc->p1.y, dsc->p2.y) + dsc->width / 2; + + if(!_lv_area_intersect(&clip_area, &clip_area, draw_unit->clip_area)) + return; /*Fully clipped, nothing to do*/ + + lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_point_t point1 = {dsc->p1.x - layer->buf_area.x1, dsc->p1.y - layer->buf_area.y1}; + lv_point_t point2 = {dsc->p2.x - layer->buf_area.x1, dsc->p2.y - layer->buf_area.y1}; + + _vglite_draw_line(&point1, &point2, &clip_area, dsc); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void _vglite_draw_line(const lv_point_t * point1, const lv_point_t * point2, + const lv_area_t * clip_area, const lv_draw_line_dsc_t * dsc) { - vg_lite_error_t err = VG_LITE_SUCCESS; vg_lite_path_t path; - vg_lite_color_t vgcol; /* vglite takes ABGR */ - vg_lite_buffer_t * vgbuf = lv_vglite_get_dest_buf(); + vg_lite_buffer_t * vgbuf = vglite_get_dest_buf(); vg_lite_cap_style_t cap_style = (dsc->round_start || dsc->round_end) ? VG_LITE_CAP_ROUND : VG_LITE_CAP_BUTT; vg_lite_join_style_t join_style = (dsc->round_start || dsc->round_end) ? VG_LITE_JOIN_ROUND : VG_LITE_JOIN_MITER; @@ -83,11 +106,10 @@ lv_res_t lv_gpu_nxp_vglite_draw_line(const lv_point_t * point1, const lv_point_t stroke_dash_phase = (vg_lite_float_t)dsc->dash_width / 2; } - /* Choose vglite blend mode based on given lvgl blend mode */ - vg_lite_blend_t vglite_blend_mode = lv_vglite_get_blend_mode(dsc->blend_mode); + vg_lite_blend_t vgblend = vglite_get_blend_mode(dsc->blend_mode); /*** Init path ***/ - lv_coord_t width = dsc->width; + int32_t width = dsc->width; int32_t line_path[] = { /*VG line path*/ VLC_OP_MOVE, point1->x, point1->y, @@ -95,48 +117,29 @@ lv_res_t lv_gpu_nxp_vglite_draw_line(const lv_point_t * point1, const lv_point_t VLC_OP_END }; - err = vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(line_path), line_path, - (vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1, - ((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f); - VG_LITE_ERR_RETURN_INV(err, "Init path failed."); + VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(line_path), line_path, + (vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1, + ((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f)); + + lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa); + vg_lite_color_t vgcol = vglite_get_color(col32, false); vg_lite_matrix_t matrix; vg_lite_identity(&matrix); - lv_color32_t col32 = { .full = lv_color_to32(dsc->color) }; /*Convert color to RGBA8888*/ - vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_BGRA8888 : VG_LITE_ABGR8888; - if(lv_vglite_premult_and_swizzle(&vgcol, col32, dsc->opa, color_format) != LV_RES_OK) - VG_LITE_RETURN_INV("Premultiplication and swizzle failed."); - /*** Draw line ***/ - err = vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH); - VG_LITE_ERR_RETURN_INV(err, "Set draw path type failed."); + VGLITE_CHECK_ERROR(vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH)); - err = vg_lite_set_stroke(&path, cap_style, join_style, width, 8, stroke_dash_pattern, stroke_dash_count, - stroke_dash_phase, vgcol); - VG_LITE_ERR_RETURN_INV(err, "Set stroke failed."); + VGLITE_CHECK_ERROR(vg_lite_set_stroke(&path, cap_style, join_style, width, 8, stroke_dash_pattern, stroke_dash_count, + stroke_dash_phase, vgcol)); - err = vg_lite_update_stroke(&path); - VG_LITE_ERR_RETURN_INV(err, "Update stroke failed."); + VGLITE_CHECK_ERROR(vg_lite_update_stroke(&path)); - lv_vglite_set_scissor(clip_area); + VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, vgblend, vgcol)); - err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, vglite_blend_mode, vgcol); - VG_LITE_ERR_RETURN_INV(err, "Draw line failed."); + vglite_run(); - if(lv_vglite_run() != LV_RES_OK) - VG_LITE_RETURN_INV("Run failed."); - - lv_vglite_disable_scissor(); - - err = vg_lite_clear_path(&path); - VG_LITE_ERR_RETURN_INV(err, "Clear path failed."); - - return LV_RES_OK; + VGLITE_CHECK_ERROR(vg_lite_clear_path(&path)); } -/********************** - * STATIC FUNCTIONS - **********************/ - -#endif /*LV_USE_GPU_NXP_VG_LITE*/ +#endif /*LV_USE_DRAW_VGLITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_line.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_line.h deleted file mode 100644 index cbd4b95ec..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_line.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @file lv_draw_vglite_line.h - * - */ - -/** - * MIT License - * - * Copyright 2022, 2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef LV_DRAW_VGLITE_LINE_H -#define LV_DRAW_VGLITE_LINE_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../../lv_conf_internal.h" - -#if LV_USE_GPU_NXP_VG_LITE -#include "lv_vglite_utils.h" -#include "../../lv_draw_line.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Draw line shape with effects - * - * @param[in] point1 Starting point with relative coordinates - * @param[in] point2 Ending point with relative coordinates - * @param[in] clip_area Clipping area with relative coordinates to dest buff - * @param[in] dsc Line description structure (width, rounded ending, opacity, ...) - * - * @retval LV_RES_OK Draw completed - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) - */ -lv_res_t lv_gpu_nxp_vglite_draw_line(const lv_point_t * point1, const lv_point_t * point2, - const lv_area_t * clip_area, const lv_draw_line_dsc_t * dsc); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_GPU_NXP_VG_LITE*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_VGLITE_RECT_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.c deleted file mode 100644 index e9db57da9..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.c +++ /dev/null @@ -1,459 +0,0 @@ -/** - * @file lv_draw_vglite_rect.c - * - */ - -/** - * MIT License - * - * Copyright 2021-2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "lv_draw_vglite_rect.h" - -#if LV_USE_GPU_NXP_VG_LITE -#include "lv_vglite_buf.h" -#include - -/********************* - * DEFINES - *********************/ -/********************* - * DEFINES - *********************/ - -/* Path data sizes for different elements */ -#define CUBIC_PATH_DATA_SIZE 7 /* 1 opcode, 6 arguments */ -#define LINE_PATH_DATA_SIZE 3 /* 1 opcode, 2 arguments */ -#define MOVE_PATH_DATA_SIZE 3 /* 1 opcode, 2 arguments */ -#define END_PATH_DATA_SIZE 1 /* 1 opcode, 0 arguments */ -/* Maximum possible rectangle path size - * is in the rounded rectangle case: - * - 1 move for the path start - * - 4 cubics for the corners - * - 4 lines for the sides - * - 1 end for the path end */ -#define RECT_PATH_DATA_MAX_SIZE 1 * MOVE_PATH_DATA_SIZE + 4 * CUBIC_PATH_DATA_SIZE + 4 * LINE_PATH_DATA_SIZE + 1 * END_PATH_DATA_SIZE - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/** - * Generates path data for rectangle drawing. - * - * @param[in/out] path The path data to initialize - * @param[in/out] path_size The resulting size of the created path data - * @param[in] dsc The style descriptor for the rectangle to be drawn - * @param[in] coords The coordinates of the rectangle to be drawn - */ -static void lv_vglite_create_rect_path_data(int32_t * path_data, uint32_t * path_data_size, - lv_coord_t radius, - const lv_area_t * coords); - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_res_t lv_gpu_nxp_vglite_draw_bg(const lv_area_t * coords, const lv_area_t * clip_area, - const lv_draw_rect_dsc_t * dsc) -{ - vg_lite_error_t err = VG_LITE_SUCCESS; - lv_coord_t width = lv_area_get_width(coords); - lv_coord_t height = lv_area_get_height(coords); - vg_lite_color_t vgcol; - lv_coord_t radius = dsc->radius; - vg_lite_buffer_t * vgbuf = lv_vglite_get_dest_buf(); - - if(dsc->radius < 0) - return LV_RES_INV; - - /*** Init path ***/ - int32_t path_data[RECT_PATH_DATA_MAX_SIZE]; - uint32_t path_data_size; - lv_vglite_create_rect_path_data(path_data, &path_data_size, radius, coords); - vg_lite_quality_t path_quality = dsc->radius > 0 ? VG_LITE_HIGH : VG_LITE_LOW; - - vg_lite_path_t path; - err = vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data, - (vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1, - ((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f); - VG_LITE_ERR_RETURN_INV(err, "Init path failed."); - - vg_lite_matrix_t matrix; - vg_lite_identity(&matrix); - - vg_lite_matrix_t * grad_matrix; - vg_lite_linear_gradient_t gradient; - - /*** Init Color/Gradient ***/ - if(dsc->bg_grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE) { - uint32_t colors[2]; - uint32_t stops[2]; - lv_color32_t col32[2]; - - /* Gradient setup */ - uint8_t cnt = LV_MAX(dsc->bg_grad.stops_count, 2); - for(uint8_t i = 0; i < cnt; i++) { - col32[i].full = lv_color_to32(dsc->bg_grad.stops[i].color); /*Convert color to RGBA8888*/ - stops[i] = dsc->bg_grad.stops[i].frac; - - vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_ABGR8888 : VG_LITE_ARGB8888; - if(lv_vglite_premult_and_swizzle(&colors[i], col32[i], dsc->bg_opa, color_format) != LV_RES_OK) - VG_LITE_RETURN_INV("Premultiplication and swizzle failed."); - } - - lv_memset_00(&gradient, sizeof(vg_lite_linear_gradient_t)); - - err = vg_lite_init_grad(&gradient); - VG_LITE_ERR_RETURN_INV(err, "Init gradient failed"); - - err = vg_lite_set_grad(&gradient, cnt, colors, stops); - VG_LITE_ERR_RETURN_INV(err, "Set gradient failed."); - - err = vg_lite_update_grad(&gradient); - VG_LITE_ERR_RETURN_INV(err, "Update gradient failed."); - - grad_matrix = vg_lite_get_grad_matrix(&gradient); - vg_lite_identity(grad_matrix); - vg_lite_translate((float)coords->x1, (float)coords->y1, grad_matrix); - - if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_VER) { - vg_lite_scale(1.0f, (float)height / 256.0f, grad_matrix); - vg_lite_rotate(90.0f, grad_matrix); - } - else { /*LV_GRAD_DIR_HOR*/ - vg_lite_scale((float)width / 256.0f, 1.0f, grad_matrix); - } - } - - lv_color32_t bg_col32 = {.full = lv_color_to32(dsc->bg_color)}; /*Convert color to RGBA8888*/ - vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_BGRA8888 : VG_LITE_ABGR8888; - if(lv_vglite_premult_and_swizzle(&vgcol, bg_col32, dsc->bg_opa, color_format) != LV_RES_OK) - VG_LITE_RETURN_INV("Premultiplication and swizzle failed."); - - lv_vglite_set_scissor(clip_area); - - /*** Draw rectangle ***/ - if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE) { - err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol); - } - else { - err = vg_lite_draw_gradient(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient, VG_LITE_BLEND_SRC_OVER); - } - VG_LITE_ERR_RETURN_INV(err, "Draw gradient failed."); - - if(lv_vglite_run() != LV_RES_OK) - VG_LITE_RETURN_INV("Run failed."); - - lv_vglite_disable_scissor(); - - err = vg_lite_clear_path(&path); - VG_LITE_ERR_RETURN_INV(err, "Clear path failed."); - - if(dsc->bg_grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE) { - err = vg_lite_clear_grad(&gradient); - VG_LITE_ERR_RETURN_INV(err, "Clear gradient failed."); - } - - return LV_RES_OK; -} - -lv_res_t lv_gpu_nxp_vglite_draw_border_generic(const lv_area_t * coords, const lv_area_t * clip_area, - const lv_draw_rect_dsc_t * dsc, bool border) -{ - vg_lite_error_t err = VG_LITE_SUCCESS; - vg_lite_color_t vgcol; /* vglite takes ABGR */ - lv_coord_t radius = dsc->radius; - vg_lite_buffer_t * vgbuf = lv_vglite_get_dest_buf(); - - if(radius < 0) - return LV_RES_INV; - - if(border) { - /* Draw border - only has radius if object has radius*/ - lv_coord_t border_half = (lv_coord_t)floor(dsc->border_width / 2.0f); - if(radius > border_half) - radius = radius - border_half; - } - else { - /* Draw outline - always has radius, leave the same radius in the circle case */ - lv_coord_t outline_half = (lv_coord_t)ceil(dsc->outline_width / 2.0f); - if(radius < (lv_coord_t)LV_RADIUS_CIRCLE - outline_half) - radius = radius + outline_half; - } - - vg_lite_cap_style_t cap_style = (radius) ? VG_LITE_CAP_ROUND : VG_LITE_CAP_BUTT; - vg_lite_join_style_t join_style = (radius) ? VG_LITE_JOIN_ROUND : VG_LITE_JOIN_MITER; - - /* Choose vglite blend mode based on given lvgl blend mode */ - vg_lite_blend_t vglite_blend_mode = lv_vglite_get_blend_mode(dsc->blend_mode); - - /*** Init path ***/ - int32_t path_data[RECT_PATH_DATA_MAX_SIZE]; - uint32_t path_data_size; - lv_vglite_create_rect_path_data(path_data, &path_data_size, radius, coords); - vg_lite_quality_t path_quality = dsc->radius > 0 ? VG_LITE_HIGH : VG_LITE_LOW; - - vg_lite_path_t path; - err = vg_lite_init_path(&path, VG_LITE_S32, path_quality, path_data_size, path_data, - (vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1, - ((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f); - VG_LITE_ERR_RETURN_INV(err, "Init path failed."); - - vg_lite_matrix_t matrix; - vg_lite_identity(&matrix); - - lv_opa_t opa; - lv_color32_t col32; - lv_coord_t line_width; - - if(border) { - opa = dsc->border_opa; - col32.full = lv_color_to32(dsc->border_color); /*Convert color to RGBA8888*/ - line_width = dsc->border_width; - } - else { - opa = dsc->outline_opa; - col32.full = lv_color_to32(dsc->outline_color); /*Convert color to RGBA8888*/ - line_width = dsc->outline_width; - } - - vg_lite_buffer_format_t color_format = LV_COLOR_DEPTH == 16 ? VG_LITE_BGRA8888 : VG_LITE_ABGR8888; - if(lv_vglite_premult_and_swizzle(&vgcol, col32, opa, color_format) != LV_RES_OK) - VG_LITE_RETURN_INV("Premultiplication and swizzle failed."); - - /*** Draw border ***/ - err = vg_lite_set_draw_path_type(&path, VG_LITE_DRAW_STROKE_PATH); - VG_LITE_ERR_RETURN_INV(err, "Set draw path type failed."); - - err = vg_lite_set_stroke(&path, cap_style, join_style, line_width, 8, NULL, 0, 0, vgcol); - VG_LITE_ERR_RETURN_INV(err, "Set stroke failed."); - - err = vg_lite_update_stroke(&path); - VG_LITE_ERR_RETURN_INV(err, "Update stroke failed."); - - lv_vglite_set_scissor(clip_area); - - err = vg_lite_draw(vgbuf, &path, VG_LITE_FILL_NON_ZERO, &matrix, vglite_blend_mode, vgcol); - VG_LITE_ERR_RETURN_INV(err, "Draw border failed."); - - if(lv_vglite_run() != LV_RES_OK) - VG_LITE_RETURN_INV("Run failed."); - - lv_vglite_disable_scissor(); - - err = vg_lite_clear_path(&path); - VG_LITE_ERR_RETURN_INV(err, "Clear path failed."); - - return LV_RES_OK; - -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void lv_vglite_create_rect_path_data(int32_t * path_data, uint32_t * path_data_size, - lv_coord_t radius, - const lv_area_t * coords) -{ - lv_coord_t rect_width = lv_area_get_width(coords); - lv_coord_t rect_height = lv_area_get_height(coords); - - /* Get the final radius. Can't be larger than the half of the shortest side */ - int32_t shortest_side = LV_MIN(rect_width, rect_height); - int32_t final_radius = LV_MIN(radius, shortest_side / 2); - - /* Path data element index */ - uint8_t pidx = 0; - - if((radius == (lv_coord_t)LV_RADIUS_CIRCLE) && (rect_width == rect_height)) { - - /* Get the control point offset for rounded cases */ - int32_t cpoff = (int32_t)((float)final_radius * BEZIER_OPTIM_CIRCLE); - - /* Circle case */ - /* Starting point */ - path_data[pidx++] = VLC_OP_MOVE; - path_data[pidx++] = coords->x1 + final_radius; - path_data[pidx++] = coords->y1; - - /* Top-right arc */ - path_data[pidx++] = VLC_OP_CUBIC_REL; - path_data[pidx++] = cpoff; - path_data[pidx++] = 0; - path_data[pidx++] = final_radius; - path_data[pidx++] = final_radius - cpoff; - path_data[pidx++] = final_radius; - path_data[pidx++] = final_radius; - - /* Bottom-right arc*/ - path_data[pidx++] = VLC_OP_CUBIC_REL; - path_data[pidx++] = 0; - path_data[pidx++] = cpoff; - path_data[pidx++] = cpoff - final_radius; - path_data[pidx++] = final_radius; - path_data[pidx++] = 0 - final_radius; - path_data[pidx++] = final_radius; - - /* Bottom-left arc */ - path_data[pidx++] = VLC_OP_CUBIC_REL; - path_data[pidx++] = 0 - cpoff; - path_data[pidx++] = 0; - path_data[pidx++] = 0 - final_radius; - path_data[pidx++] = cpoff - final_radius; - path_data[pidx++] = 0 - final_radius; - path_data[pidx++] = 0 - final_radius; - - /* Top-left arc*/ - path_data[pidx++] = VLC_OP_CUBIC_REL; - path_data[pidx++] = 0; - path_data[pidx++] = 0 - cpoff; - path_data[pidx++] = final_radius - cpoff; - path_data[pidx++] = 0 - final_radius; - path_data[pidx++] = final_radius; - path_data[pidx++] = 0 - final_radius; - - /* Ending point */ - path_data[pidx++] = VLC_OP_END; - } - else if(radius > 0) { - /* Get the control point offset for rounded cases */ - int32_t cpoff = (int32_t)((float)final_radius * BEZIER_OPTIM_CIRCLE); - - /* Rounded rectangle case */ - /* Starting point */ - path_data[pidx++] = VLC_OP_MOVE; - path_data[pidx++] = coords->x1 + final_radius; - path_data[pidx++] = coords->y1; - - /* Top side */ - path_data[pidx++] = VLC_OP_LINE; - path_data[pidx++] = coords->x2 - final_radius + 1; // Extended for VGLite - path_data[pidx++] = coords->y1; - - /* Top-right corner */ - path_data[pidx++] = VLC_OP_CUBIC_REL; - path_data[pidx++] = cpoff; - path_data[pidx++] = 0; - path_data[pidx++] = final_radius; - path_data[pidx++] = final_radius - cpoff; - path_data[pidx++] = final_radius; - path_data[pidx++] = final_radius; - - /* Right side */ - path_data[pidx++] = VLC_OP_LINE; - path_data[pidx++] = coords->x2 + 1; // Extended for VGLite - path_data[pidx++] = coords->y2 - final_radius + 1; // Extended for VGLite - - /* Bottom-right corner*/ - path_data[pidx++] = VLC_OP_CUBIC_REL; - path_data[pidx++] = 0; - path_data[pidx++] = cpoff; - path_data[pidx++] = cpoff - final_radius; - path_data[pidx++] = final_radius; - path_data[pidx++] = 0 - final_radius; - path_data[pidx++] = final_radius; - - /* Bottom side */ - path_data[pidx++] = VLC_OP_LINE; - path_data[pidx++] = coords->x1 + final_radius; - path_data[pidx++] = coords->y2 + 1; // Extended for VGLite - - /* Bottom-left corner */ - path_data[pidx++] = VLC_OP_CUBIC_REL; - path_data[pidx++] = 0 - cpoff; - path_data[pidx++] = 0; - path_data[pidx++] = 0 - final_radius; - path_data[pidx++] = cpoff - final_radius; - path_data[pidx++] = 0 - final_radius; - path_data[pidx++] = 0 - final_radius; - - /* Left side*/ - path_data[pidx++] = VLC_OP_LINE; - path_data[pidx++] = coords->x1; - path_data[pidx++] = coords->y1 + final_radius; - - /* Top-left corner */ - path_data[pidx++] = VLC_OP_CUBIC_REL; - path_data[pidx++] = 0; - path_data[pidx++] = 0 - cpoff; - path_data[pidx++] = final_radius - cpoff; - path_data[pidx++] = 0 - final_radius; - path_data[pidx++] = final_radius; - path_data[pidx++] = 0 - final_radius; - - /* Ending point */ - path_data[pidx++] = VLC_OP_END; - } - else { - /* Non-rounded rectangle case */ - /* Starting point */ - path_data[pidx++] = VLC_OP_MOVE; - path_data[pidx++] = coords->x1; - path_data[pidx++] = coords->y1; - - /* Top side */ - path_data[pidx++] = VLC_OP_LINE; - path_data[pidx++] = coords->x2 + 1; // Extended for VGLite - path_data[pidx++] = coords->y1; - - /* Right side */ - path_data[pidx++] = VLC_OP_LINE; - path_data[pidx++] = coords->x2 + 1; // Extended for VGLite - path_data[pidx++] = coords->y2 + 1; // Extended for VGLite - - /* Bottom side */ - path_data[pidx++] = VLC_OP_LINE; - path_data[pidx++] = coords->x1; - path_data[pidx++] = coords->y2 + 1; // Extended for VGLite - - /* Left side*/ - path_data[pidx++] = VLC_OP_LINE; - path_data[pidx++] = coords->x1; - path_data[pidx++] = coords->y1; - - /* Ending point */ - path_data[pidx++] = VLC_OP_END; - } - - /* Resulting path size */ - *path_data_size = pidx * sizeof(int32_t); -} - -#endif /*LV_USE_GPU_NXP_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.h deleted file mode 100644 index 795822746..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @file lv_draw_vglite_rect.h - * - */ - -/** - * MIT License - * - * Copyright 2021-2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef LV_DRAW_VGLITE_RECT_H -#define LV_DRAW_VGLITE_RECT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../../lv_conf_internal.h" - -#if LV_USE_GPU_NXP_VG_LITE -#include "lv_vglite_utils.h" -#include "../../lv_draw_rect.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Draw rectangle background with effects (rounded corners, gradient) - * - * @param[in] coords Coordinates of the rectangle background (relative to dest buff) - * @param[in] clip_area Clipping area with relative coordinates to dest buff - * @param[in] dsc Description of the rectangle background - * - * @retval LV_RES_OK Draw completed - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) - * - */ -lv_res_t lv_gpu_nxp_vglite_draw_bg(const lv_area_t * coords, const lv_area_t * clip_area, - const lv_draw_rect_dsc_t * dsc); - -/** - * Draw rectangle border/outline shape with effects (rounded corners, opacity) - * - * @param[in] coords Coordinates of the rectangle border/outline (relative to dest buff) - * @param[in] clip_area Clipping area with relative coordinates to dest buff - * @param[in] dsc Description of the rectangle border/outline - * @param[in] border True for border, False for outline - * - * @retval LV_RES_OK Draw completed - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) - * - */ -lv_res_t lv_gpu_nxp_vglite_draw_border_generic(const lv_area_t * coords, const lv_area_t * clip_area, - const lv_draw_rect_dsc_t * dsc, bool border); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_GPU_NXP_VG_LITE*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_VGLITE_RECT_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_triangle.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_triangle.c new file mode 100644 index 000000000..0de169dc0 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_draw_vglite_triangle.c @@ -0,0 +1,179 @@ +/** + * @file lv_draw_vglite_triangle.c + * + */ + +/** + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vglite.h" + +#if LV_USE_DRAW_VGLITE +#include "lv_vglite_buf.h" +#include "lv_vglite_path.h" +#include "lv_vglite_utils.h" + +#include "../../../stdlib/lv_string.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/** + * Draw triangle shape with effects (opacity, gradient) + * + * @param[in] coords Coordinates of the triangle (relative to dest buff) + * @param[in] clip_area Clipping area with relative coordinates to dest buff + * @param[in] dsc Description of the triangle + * + */ +static void _vglite_draw_triangle(const lv_area_t * coords, const lv_area_t * clip_area, + const lv_draw_triangle_dsc_t * dsc); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vglite_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc) +{ + if(dsc->bg_opa <= (lv_opa_t)LV_OPA_MIN) + return; + + lv_layer_t * layer = draw_unit->target_layer; + lv_area_t clip_area; + lv_area_copy(&clip_area, draw_unit->clip_area); + lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t coords; + coords.x1 = (int32_t)LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + coords.y1 = (int32_t)LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); + coords.x2 = (int32_t)LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + coords.y2 = (int32_t)LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); + + lv_area_move(&coords, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t clipped_coords; + if(!_lv_area_intersect(&clipped_coords, &coords, &clip_area)) + return; /* Fully clipped, nothing to do */ + + _vglite_draw_triangle(&coords, &clip_area, dsc); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void _vglite_draw_triangle(const lv_area_t * coords, const lv_area_t * clip_area, + const lv_draw_triangle_dsc_t * dsc) +{ + vg_lite_buffer_t * vgbuf = vglite_get_dest_buf(); + + lv_area_t tri_area; + tri_area.x1 = (int32_t)LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + tri_area.y1 = (int32_t)LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); + tri_area.x2 = (int32_t)LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + tri_area.y2 = (int32_t)LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); + + uint32_t width = tri_area.x2 - tri_area.x1; + uint32_t height = tri_area.y2 - tri_area.y1; + + /* Init path */ + int32_t triangle_path[] = { /*VG line path*/ + VLC_OP_MOVE, dsc->p[0].x, dsc->p[0].y, + VLC_OP_LINE, dsc->p[1].x, dsc->p[1].y, + VLC_OP_LINE, dsc->p[2].x, dsc->p[2].y, + VLC_OP_LINE, dsc->p[0].x, dsc->p[0].y, + VLC_OP_END + }; + + vg_lite_path_t path; + VGLITE_CHECK_ERROR(vg_lite_init_path(&path, VG_LITE_S32, VG_LITE_HIGH, sizeof(triangle_path), triangle_path, + (vg_lite_float_t)clip_area->x1, (vg_lite_float_t)clip_area->y1, + ((vg_lite_float_t)clip_area->x2) + 1.0f, ((vg_lite_float_t)clip_area->y2) + 1.0f)); + + vg_lite_matrix_t matrix; + vg_lite_identity(&matrix); + + /* Init Color */ + lv_color32_t col32 = lv_color_to_32(dsc->bg_color, dsc->bg_opa); + vg_lite_color_t vgcol = vglite_get_color(col32, false); + + vg_lite_linear_gradient_t gradient; + bool has_gradient = (dsc->bg_grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE); + + /* Init Gradient*/ + if(has_gradient) { + vg_lite_matrix_t * grad_matrix; + + vg_lite_uint32_t colors[LV_GRADIENT_MAX_STOPS]; + vg_lite_uint32_t stops[LV_GRADIENT_MAX_STOPS]; + lv_color32_t col32[LV_GRADIENT_MAX_STOPS]; + + /* Gradient Setup */ + vg_lite_uint32_t cnt = LV_MAX(dsc->bg_grad.stops_count, LV_GRADIENT_MAX_STOPS); + for(uint8_t i = 0; i < cnt; i++) { + stops[i] = dsc->bg_grad.stops[i].frac; + + col32[i] = lv_color_to_32(dsc->bg_grad.stops[i].color, dsc->bg_grad.stops[i].opa); + colors[i] = vglite_get_color(col32[i], true); + } + + lv_memzero(&gradient, sizeof(vg_lite_linear_gradient_t)); + + VGLITE_CHECK_ERROR(vg_lite_init_grad(&gradient)); + + VGLITE_CHECK_ERROR(vg_lite_set_grad(&gradient, cnt, colors, stops)); + + VGLITE_CHECK_ERROR(vg_lite_update_grad(&gradient)); + + grad_matrix = vg_lite_get_grad_matrix(&gradient); + vg_lite_identity(grad_matrix); + vg_lite_translate((float)coords->x1, (float)coords->y1, grad_matrix); + + if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_VER) { + vg_lite_scale(1.0f, (float)height / 256.0f, grad_matrix); + vg_lite_rotate(90.0f, grad_matrix); + } + else { /*LV_GRAD_DIR_HOR*/ + vg_lite_scale((float)width / 256.0f, 1.0f, grad_matrix); + } + + VGLITE_CHECK_ERROR(vg_lite_draw_gradient(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, &gradient, + VG_LITE_BLEND_SRC_OVER)); + } + else { + VGLITE_CHECK_ERROR(vg_lite_draw(vgbuf, &path, VG_LITE_FILL_EVEN_ODD, &matrix, VG_LITE_BLEND_SRC_OVER, vgcol)); + } + + vglite_run(); + + VGLITE_CHECK_ERROR(vg_lite_clear_path(&path)); + + if(has_gradient) + VGLITE_CHECK_ERROR(vg_lite_clear_grad(&gradient)); +} + +#endif /*LV_USE_DRAW_VGLITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_buf.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_buf.c index e1ff6a297..a72c8e554 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_buf.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_buf.c @@ -4,27 +4,9 @@ */ /** - * MIT License - * * Copyright 2023 NXP * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * + * SPDX-License-Identifier: MIT */ /********************* @@ -33,20 +15,15 @@ #include "lv_vglite_buf.h" -#if LV_USE_GPU_NXP_VG_LITE +#if LV_USE_DRAW_VGLITE +#include "lv_vglite_utils.h" + +#include "../../../stdlib/lv_string.h" /********************* * DEFINES *********************/ -#if LV_COLOR_DEPTH == 16 - #define VG_LITE_PX_FMT VG_LITE_RGB565 -#elif LV_COLOR_DEPTH == 32 - #define VG_LITE_PX_FMT VG_LITE_BGRA8888 -#else - #error Only 16bit and 32bit color depth are supported. Set LV_COLOR_DEPTH to 16 or 32. -#endif - /********************** * TYPEDEFS **********************/ @@ -55,15 +32,14 @@ * STATIC PROTOTYPES **********************/ -static inline void lv_vglite_set_dest_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride); -static inline void lv_vglite_set_buf_ptr(vg_lite_buffer_t * vgbuf, const lv_color_t * buf); +static inline void _set_vgbuf_ptr(vg_lite_buffer_t * vgbuf, void * buf); /********************** * STATIC VARIABLES **********************/ -static vg_lite_buffer_t dest_vgbuf; -static vg_lite_buffer_t src_vgbuf; +static vg_lite_buffer_t _dest_vgbuf; +static vg_lite_buffer_t _src_vgbuf; /********************** * MACROS @@ -73,52 +49,56 @@ static vg_lite_buffer_t src_vgbuf; * GLOBAL FUNCTIONS **********************/ -void lv_gpu_nxp_vglite_init_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride) +vg_lite_buffer_t * vglite_get_dest_buf(void) { - lv_vglite_set_dest_buf(buf, area, stride); + return &_dest_vgbuf; } -vg_lite_buffer_t * lv_vglite_get_dest_buf(void) +vg_lite_buffer_t * vglite_get_src_buf(void) { - return &dest_vgbuf; + return &_src_vgbuf; } -vg_lite_buffer_t * lv_vglite_get_src_buf(void) +void vglite_set_dest_buf_ptr(void * buf) { - return &src_vgbuf; + _set_vgbuf_ptr(&_dest_vgbuf, buf); } -void lv_vglite_set_dest_buf_ptr(const lv_color_t * buf) +void vglite_set_src_buf_ptr(const void * buf) { - lv_vglite_set_buf_ptr(&dest_vgbuf, buf); + _set_vgbuf_ptr(&_src_vgbuf, (void *)buf); } -void lv_vglite_set_src_buf_ptr(const lv_color_t * buf) +void vglite_set_dest_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride, + lv_color_format_t cf) { - lv_vglite_set_buf_ptr(&src_vgbuf, buf); + vglite_set_buf(&_dest_vgbuf, (void *)buf, width, height, stride, cf); } -void lv_vglite_set_src_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride) +void vglite_set_src_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride, + lv_color_format_t cf) { - if(src_vgbuf.memory != (void *)buf) - lv_vglite_set_buf(&src_vgbuf, buf, area, stride); + vglite_set_buf(&_src_vgbuf, (void *)buf, width, height, stride, cf); } -void lv_vglite_set_buf(vg_lite_buffer_t * vgbuf, const lv_color_t * buf, - const lv_area_t * area, lv_coord_t stride) +void vglite_set_buf(vg_lite_buffer_t * vgbuf, void * buf, + uint32_t width, uint32_t height, uint32_t stride, + lv_color_format_t cf) { - vgbuf->format = VG_LITE_PX_FMT; + vg_lite_buffer_format_t vgformat = vglite_get_buf_format(cf); + + vgbuf->format = vgformat; vgbuf->tiled = VG_LITE_LINEAR; vgbuf->image_mode = VG_LITE_NORMAL_IMAGE_MODE; vgbuf->transparency_mode = VG_LITE_IMAGE_OPAQUE; - vgbuf->width = (int32_t)lv_area_get_width(area); - vgbuf->height = (int32_t)lv_area_get_height(area); - vgbuf->stride = (int32_t)(stride) * sizeof(lv_color_t); + vgbuf->width = (int32_t)width; + vgbuf->height = (int32_t)height; + vgbuf->stride = (int32_t)stride; - lv_memset_00(&vgbuf->yuv, sizeof(vgbuf->yuv)); + lv_memzero(&vgbuf->yuv, sizeof(vgbuf->yuv)); - vgbuf->memory = (void *)buf; + vgbuf->memory = buf; vgbuf->address = (uint32_t)vgbuf->memory; vgbuf->handle = NULL; } @@ -127,15 +107,10 @@ void lv_vglite_set_buf(vg_lite_buffer_t * vgbuf, const lv_color_t * buf, * STATIC FUNCTIONS **********************/ -static inline void lv_vglite_set_dest_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride) +static inline void _set_vgbuf_ptr(vg_lite_buffer_t * vgbuf, void * buf) { - lv_vglite_set_buf(&dest_vgbuf, buf, area, stride); -} - -static inline void lv_vglite_set_buf_ptr(vg_lite_buffer_t * vgbuf, const lv_color_t * buf) -{ - vgbuf->memory = (void *)buf; + vgbuf->memory = buf; vgbuf->address = (uint32_t)vgbuf->memory; } -#endif /*LV_USE_GPU_NXP_VG_LITE*/ +#endif /*LV_USE_DRAW_VGLITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_buf.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_buf.h index e89af1c87..3ef434748 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_buf.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_buf.h @@ -4,27 +4,9 @@ */ /** - * MIT License - * * Copyright 2023 NXP * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * + * SPDX-License-Identifier: MIT */ #ifndef LV_VGLITE_BUF_H @@ -39,10 +21,11 @@ extern "C" { *********************/ #include "../../../lv_conf_internal.h" -#if LV_USE_GPU_NXP_VG_LITE -#include "vg_lite.h" +#if LV_USE_DRAW_VGLITE #include "../../sw/lv_draw_sw.h" +#include "vg_lite.h" + /********************* * DEFINES *********************/ @@ -54,68 +37,85 @@ extern "C" { /********************** * GLOBAL PROTOTYPES **********************/ -/** - * Init vglite destination buffer. It will be done once per frame. - * - * @param[in] buf Destination buffer address (does not require alignment for VG_LITE_LINEAR mode) - * @param[in] area Destination buffer area (for width and height) - * @param[in] stride Stride of destination buffer - */ -void lv_gpu_nxp_vglite_init_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride); /** * Get vglite destination buffer pointer. * * @retval The vglite destination buffer + * */ -vg_lite_buffer_t * lv_vglite_get_dest_buf(void); +vg_lite_buffer_t * vglite_get_dest_buf(void); /** * Get vglite source buffer pointer. * * @retval The vglite source buffer + * */ -vg_lite_buffer_t * lv_vglite_get_src_buf(void); +vg_lite_buffer_t * vglite_get_src_buf(void); /** * Set vglite destination buffer address only. * * @param[in] buf Destination buffer address (does not require alignment for VG_LITE_LINEAR mode) + * */ -void lv_vglite_set_dest_buf_ptr(const lv_color_t * buf); +void vglite_set_dest_buf_ptr(void * buf); /** * Set vglite source buffer address only. * * @param[in] buf Source buffer address + * */ -void lv_vglite_set_src_buf_ptr(const lv_color_t * buf); +void vglite_set_src_buf_ptr(const void * buf); /** - * Set vglite source buffer. It will be done only if buffer addreess is different. + * Set vglite destination buffer. + * + * @param[in] buf Destination buffer address + * @param[in] width Destination buffer width + * @param[in] height Destination buffer height + * @param[in] stride Destination buffer stride in bytes + * @param[in] cf Destination buffer color format + * + */ +void vglite_set_dest_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride, + lv_color_format_t cf); + +/** + * Set vglite source buffer. * * @param[in] buf Source buffer address - * @param[in] area Source buffer area (for width and height) - * @param[in] stride Stride of source buffer + * @param[in] width Source buffer width + * @param[in] height Source buffer height + * @param[in] stride Source buffer stride in bytes + * @param[in] cf Source buffer color format + * */ -void lv_vglite_set_src_buf(const lv_color_t * buf, const lv_area_t * area, lv_coord_t stride); +void vglite_set_src_buf(const void * buf, uint32_t width, uint32_t height, uint32_t stride, + lv_color_format_t cf); /** * Set vglite buffer. * * @param[in] vgbuf Address of the VGLite buffer object * @param[in] buf Address of the memory for the VGLite buffer - * @param[in] area buffer area (for width and height) - * @param[in] stride buffer stride + * @param[in] width Buffer width + * @param[in] height Buffer height + * @param[in] stride Buffer stride in bytes + * @param[in] cf Buffer color format + * */ -void lv_vglite_set_buf(vg_lite_buffer_t * vgbuf, const lv_color_t * buf, - const lv_area_t * area, lv_coord_t stride); +void vglite_set_buf(vg_lite_buffer_t * vgbuf, void * buf, + uint32_t width, uint32_t height, uint32_t stride, + lv_color_format_t cf); /********************** * MACROS **********************/ -#endif /*LV_USE_GPU_NXP_VG_LITE*/ +#endif /*LV_USE_DRAW_VGLITE*/ #ifdef __cplusplus } /*extern "C"*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_matrix.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_matrix.c new file mode 100644 index 000000000..3076c6c91 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_matrix.c @@ -0,0 +1,79 @@ +/** + * @file lv_vglite_matrix.c + * + */ + +/** + * Copyright 2023 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_vglite_matrix.h" + +#if LV_USE_DRAW_VGLITE + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +static vg_lite_matrix_t _vgmatrix; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +vg_lite_matrix_t * vglite_get_matrix(void) +{ + return &_vgmatrix; +} + +void vglite_set_translation_matrix(const lv_area_t * dest_area) +{ + vg_lite_identity(&_vgmatrix); + vg_lite_translate((vg_lite_float_t)dest_area->x1, (vg_lite_float_t)dest_area->y1, &_vgmatrix); +} + +void vglite_set_transformation_matrix(const lv_area_t * dest_area, const lv_draw_image_dsc_t * dsc) +{ + vglite_set_translation_matrix(dest_area); + + bool has_scale = (dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE); + bool has_rotation = (dsc->rotation != 0); + + vg_lite_translate(dsc->pivot.x, dsc->pivot.y, &_vgmatrix); + if(has_rotation) + vg_lite_rotate(dsc->rotation / 10.0f, &_vgmatrix); /* angle is 1/10 degree */ + if(has_scale) { + vg_lite_float_t scale_x = 1.0f * dsc->scale_x / LV_SCALE_NONE; + vg_lite_float_t scale_y = 1.0f * dsc->scale_y / LV_SCALE_NONE; + vg_lite_scale(scale_x, scale_y, &_vgmatrix); + } + vg_lite_translate(0.0f - dsc->pivot.x, 0.0f - dsc->pivot.y, &_vgmatrix); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_VGLITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_matrix.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_matrix.h new file mode 100644 index 000000000..832cd86bb --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_matrix.h @@ -0,0 +1,78 @@ +/** + * @file lv_vglite_matrix.h + * + */ + +/** + * Copyright 2023 NXP + * + * SPDX-License-Identifier: MIT + */ + +#ifndef LV_VGLITE_MATRIX_H +#define LV_VGLITE_MATRIX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lv_conf_internal.h" + +#if LV_USE_DRAW_VGLITE +#include "../../sw/lv_draw_sw.h" + +#include "vg_lite.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +vg_lite_matrix_t * vglite_get_matrix(void); + +/** + * Creates matrix that translates to origin of given destination area. + * + * @param[in] dest_area Area with relative coordinates of destination buffer + * + */ +void vglite_set_translation_matrix(const lv_area_t * dest_area); + +/** + * Creates matrix that translates to origin of given destination area with transformation (scale or rotate). + * + * @param[in] dest_area Area with relative coordinates of destination buffer + * @param[in] dsc Image descriptor + * + */ +void vglite_set_transformation_matrix(const lv_area_t * dest_area, const lv_draw_image_dsc_t * dsc); + +/********************** + * MACROS + **********************/ + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_VGLITE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_VGLITE_MATRIX_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_path.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_path.c new file mode 100644 index 000000000..6f8b759c8 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_path.c @@ -0,0 +1,217 @@ +/** + * @file lv_vglite_path.c + * + */ + +/** + * Copyright 2023 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_vglite_path.h" + +#if LV_USE_DRAW_VGLITE +#include "vg_lite.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void vglite_create_rect_path_data(int32_t * path_data, uint32_t * path_data_size, + int32_t radius, + const lv_area_t * coords) +{ + int32_t rect_width = lv_area_get_width(coords); + int32_t rect_height = lv_area_get_height(coords); + + /* Get the final radius. Can't be larger than the half of the shortest side */ + int32_t shortest_side = LV_MIN(rect_width, rect_height); + int32_t final_radius = LV_MIN(radius, shortest_side / 2); + + /* Path data element index */ + uint8_t pidx = 0; + + if((radius == (int32_t)LV_RADIUS_CIRCLE) && (rect_width == rect_height)) { + + /* Get the control point offset for rounded cases */ + int32_t cpoff = (int32_t)((float)final_radius * BEZIER_OPTIM_CIRCLE); + + /* Circle case */ + /* Starting point */ + path_data[pidx++] = VLC_OP_MOVE; + path_data[pidx++] = coords->x1 + final_radius; + path_data[pidx++] = coords->y1; + + /* Top-right arc */ + path_data[pidx++] = VLC_OP_CUBIC_REL; + path_data[pidx++] = cpoff; + path_data[pidx++] = 0; + path_data[pidx++] = final_radius; + path_data[pidx++] = final_radius - cpoff; + path_data[pidx++] = final_radius; + path_data[pidx++] = final_radius; + + /* Bottom-right arc*/ + path_data[pidx++] = VLC_OP_CUBIC_REL; + path_data[pidx++] = 0; + path_data[pidx++] = cpoff; + path_data[pidx++] = cpoff - final_radius; + path_data[pidx++] = final_radius; + path_data[pidx++] = 0 - final_radius; + path_data[pidx++] = final_radius; + + /* Bottom-left arc */ + path_data[pidx++] = VLC_OP_CUBIC_REL; + path_data[pidx++] = 0 - cpoff; + path_data[pidx++] = 0; + path_data[pidx++] = 0 - final_radius; + path_data[pidx++] = cpoff - final_radius; + path_data[pidx++] = 0 - final_radius; + path_data[pidx++] = 0 - final_radius; + + /* Top-left arc*/ + path_data[pidx++] = VLC_OP_CUBIC_REL; + path_data[pidx++] = 0; + path_data[pidx++] = 0 - cpoff; + path_data[pidx++] = final_radius - cpoff; + path_data[pidx++] = 0 - final_radius; + path_data[pidx++] = final_radius; + path_data[pidx++] = 0 - final_radius; + + /* Ending point */ + path_data[pidx++] = VLC_OP_END; + } + else if(radius > 0) { + /* Get the control point offset for rounded cases */ + int32_t cpoff = (int32_t)((float)final_radius * BEZIER_OPTIM_CIRCLE); + + /* Rounded rectangle case */ + /* Starting point */ + path_data[pidx++] = VLC_OP_MOVE; + path_data[pidx++] = coords->x1 + final_radius; + path_data[pidx++] = coords->y1; + + /* Top side */ + path_data[pidx++] = VLC_OP_LINE; + path_data[pidx++] = coords->x2 - final_radius + 1; /*Extended for VGLite*/ + path_data[pidx++] = coords->y1; + + /* Top-right corner */ + path_data[pidx++] = VLC_OP_CUBIC_REL; + path_data[pidx++] = cpoff; + path_data[pidx++] = 0; + path_data[pidx++] = final_radius; + path_data[pidx++] = final_radius - cpoff; + path_data[pidx++] = final_radius; + path_data[pidx++] = final_radius; + + /* Right side */ + path_data[pidx++] = VLC_OP_LINE; + path_data[pidx++] = coords->x2 + 1; /*Extended for VGLite*/ + path_data[pidx++] = coords->y2 - final_radius + 1; /*Extended for VGLite*/ + + /* Bottom-right corner*/ + path_data[pidx++] = VLC_OP_CUBIC_REL; + path_data[pidx++] = 0; + path_data[pidx++] = cpoff; + path_data[pidx++] = cpoff - final_radius; + path_data[pidx++] = final_radius; + path_data[pidx++] = 0 - final_radius; + path_data[pidx++] = final_radius; + + /* Bottom side */ + path_data[pidx++] = VLC_OP_LINE; + path_data[pidx++] = coords->x1 + final_radius; + path_data[pidx++] = coords->y2 + 1; /*Extended for VGLite*/ + + /* Bottom-left corner */ + path_data[pidx++] = VLC_OP_CUBIC_REL; + path_data[pidx++] = 0 - cpoff; + path_data[pidx++] = 0; + path_data[pidx++] = 0 - final_radius; + path_data[pidx++] = cpoff - final_radius; + path_data[pidx++] = 0 - final_radius; + path_data[pidx++] = 0 - final_radius; + + /* Left side*/ + path_data[pidx++] = VLC_OP_LINE; + path_data[pidx++] = coords->x1; + path_data[pidx++] = coords->y1 + final_radius; + + /* Top-left corner */ + path_data[pidx++] = VLC_OP_CUBIC_REL; + path_data[pidx++] = 0; + path_data[pidx++] = 0 - cpoff; + path_data[pidx++] = final_radius - cpoff; + path_data[pidx++] = 0 - final_radius; + path_data[pidx++] = final_radius; + path_data[pidx++] = 0 - final_radius; + + /* Ending point */ + path_data[pidx++] = VLC_OP_END; + } + else { + /* Non-rounded rectangle case */ + /* Starting point */ + path_data[pidx++] = VLC_OP_MOVE; + path_data[pidx++] = coords->x1; + path_data[pidx++] = coords->y1; + + /* Top side */ + path_data[pidx++] = VLC_OP_LINE; + path_data[pidx++] = coords->x2 + 1; /*Extended for VGLite*/ + path_data[pidx++] = coords->y1; + + /* Right side */ + path_data[pidx++] = VLC_OP_LINE; + path_data[pidx++] = coords->x2 + 1; /*Extended for VGLite*/ + path_data[pidx++] = coords->y2 + 1; /*Extended for VGLite*/ + + /* Bottom side */ + path_data[pidx++] = VLC_OP_LINE; + path_data[pidx++] = coords->x1; + path_data[pidx++] = coords->y2 + 1; /*Extended for VGLite*/ + + /* Left side*/ + path_data[pidx++] = VLC_OP_LINE; + path_data[pidx++] = coords->x1; + path_data[pidx++] = coords->y1; + + /* Ending point */ + path_data[pidx++] = VLC_OP_END; + } + + /* Resulting path size */ + *path_data_size = pidx * sizeof(int32_t); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_VGLITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_path.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_path.h new file mode 100644 index 000000000..6c92e50e6 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_path.h @@ -0,0 +1,91 @@ +/** + * @file lv_vglite_path.h + * + */ + +/** + * Copyright 2023 NXP + * + * SPDX-License-Identifier: MIT + */ + +#ifndef LV_VGLITE_PATH_H +#define LV_VGLITE_PATH_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lv_conf_internal.h" + +#if LV_USE_DRAW_VGLITE +#include "../../sw/lv_draw_sw.h" + +/********************* + * DEFINES + *********************/ + +/* The optimal Bezier control point offset for radial unit + * see: https://spencermortensen.com/articles/bezier-circle/ + **/ +#define BEZIER_OPTIM_CIRCLE 0.551915024494f + +/* Draw lines for control points of Bezier curves */ +#define BEZIER_DBG_CONTROL_POINTS 0 + +/* Path data sizes for different elements */ +#define CUBIC_PATH_DATA_SIZE 7 /* 1 opcode, 6 arguments */ +#define LINE_PATH_DATA_SIZE 3 /* 1 opcode, 2 arguments */ +#define MOVE_PATH_DATA_SIZE 3 /* 1 opcode, 2 arguments */ +#define END_PATH_DATA_SIZE 1 /* 1 opcode, 0 arguments */ +/* Maximum possible rectangle path size + * is in the rounded rectangle case: + * - 1 move for the path start + * - 4 cubics for the corners + * - 4 lines for the sides + * - 1 end for the path end */ +#define RECT_PATH_DATA_MAX_SIZE 1 * MOVE_PATH_DATA_SIZE + 4 * CUBIC_PATH_DATA_SIZE + 4 * LINE_PATH_DATA_SIZE + 1 * END_PATH_DATA_SIZE + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Generates path data for rectangle drawing. + * + * @param[in/out] path The path data to initialize + * @param[in/out] path_size The resulting size of the created path data + * @param[in] dsc The style descriptor for the rectangle to be drawn + * @param[in] coords The coordinates of the rectangle to be drawn + * + */ +void vglite_create_rect_path_data(int32_t * path_data, uint32_t * path_data_size, + int32_t radius, + const lv_area_t * coords); + +/********************** + * MACROS + **********************/ + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_VGLITE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_VGLITE_PATH_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_utils.c b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_utils.c index adc9f7712..7e923cefc 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_utils.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_utils.c @@ -4,27 +4,9 @@ */ /** - * MIT License - * - * Copyright 2022, 2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * Copyright 2022-2024 NXP * + * SPDX-License-Identifier: MIT */ /********************* @@ -33,7 +15,9 @@ #include "lv_vglite_utils.h" -#if LV_USE_GPU_NXP_VG_LITE +#if LV_USE_DRAW_VGLITE +#include "lv_vglite_buf.h" + #include "../../../core/lv_refr.h" /********************* @@ -48,15 +32,14 @@ * STATIC PROTOTYPES **********************/ -/** - * Clean and invalidate cache. - */ -static inline void invalidate_cache(void); - /********************** * STATIC VARIABLES **********************/ +#if LV_USE_VGLITE_DRAW_ASYNC + static volatile bool _cmd_buf_flushed = false; +#endif + /********************** * MACROS **********************/ @@ -65,85 +48,238 @@ static inline void invalidate_cache(void); * GLOBAL FUNCTIONS **********************/ -lv_res_t lv_vglite_run(void) +const char * vglite_error_to_string(vg_lite_error_t error) { - invalidate_cache(); + switch(error) { + ENUM_TO_STRING(VG_LITE_SUCCESS); + ENUM_TO_STRING(VG_LITE_INVALID_ARGUMENT); + ENUM_TO_STRING(VG_LITE_OUT_OF_MEMORY); + ENUM_TO_STRING(VG_LITE_NO_CONTEXT); + ENUM_TO_STRING(VG_LITE_TIMEOUT); + ENUM_TO_STRING(VG_LITE_OUT_OF_RESOURCES); + ENUM_TO_STRING(VG_LITE_GENERIC_IO); + ENUM_TO_STRING(VG_LITE_NOT_SUPPORT); + ENUM_TO_STRING(VG_LITE_ALREADY_EXISTS); + ENUM_TO_STRING(VG_LITE_NOT_ALIGNED); + ENUM_TO_STRING(VG_LITE_FLEXA_TIME_OUT); + ENUM_TO_STRING(VG_LITE_FLEXA_HANDSHAKE_FAIL); + default: + break; + } - VG_LITE_ERR_RETURN_INV(vg_lite_flush(), "Flush failed."); - - return LV_RES_OK; + return "VG_LITE_UKNOWN_ERROR"; } -lv_res_t lv_vglite_premult_and_swizzle(vg_lite_color_t * vg_col32, lv_color32_t lv_col32, lv_opa_t opa, - vg_lite_buffer_format_t vg_col_format) +#if LV_USE_VGLITE_DRAW_ASYNC +bool vglite_cmd_buf_is_flushed(void) { + return _cmd_buf_flushed; +} +#endif - lv_color32_t lv_col32_premul = lv_col32; - if(opa <= (lv_opa_t)LV_OPA_MAX) { - /* Only pre-multiply color if hardware pre-multiplication is not present */ - if(!vg_lite_query_feature(gcFEATURE_BIT_VG_PE_PREMULTIPLY)) { - lv_col32_premul.ch.red = (uint8_t)(((uint16_t)lv_col32.ch.red * opa) >> 8); - lv_col32_premul.ch.green = (uint8_t)(((uint16_t)lv_col32.ch.green * opa) >> 8); - lv_col32_premul.ch.blue = (uint8_t)(((uint16_t)lv_col32.ch.blue * opa) >> 8); +void vglite_run(void) +{ +#if LV_USE_VGLITE_DRAW_ASYNC + vg_lite_uint32_t gpu_idle = 0; + + VGLITE_CHECK_ERROR(vg_lite_get_parameter(VG_LITE_GPU_IDLE_STATE, 1, (vg_lite_pointer)&gpu_idle)); + + if(!gpu_idle) { + _cmd_buf_flushed = false; + + return; + } +#endif + + /* + * If LV_USE_VGLITE_DRAW_ASYNC is enabled, simply flush the command buffer and the + * vglite draw thread will signal asynchronous the dispatcher for completed tasks. + * Without draw async, process the tasks and signal them as complete one by one. + */ +#if LV_USE_VGLITE_DRAW_ASYNC + VGLITE_CHECK_ERROR(vg_lite_flush()); + _cmd_buf_flushed = true; +#else + VGLITE_CHECK_ERROR(vg_lite_finish()); +#endif +} + +vg_lite_color_t vglite_get_color(lv_color32_t lv_col32, bool gradient) +{ + vg_lite_color_t vg_col32; + + /* Pre-multiply alpha */ + lv_col32.red = LV_UDIV255(lv_col32.red * lv_col32.alpha); + lv_col32.green = LV_UDIV255(lv_col32.green * lv_col32.alpha); + lv_col32.blue = LV_UDIV255(lv_col32.blue * lv_col32.alpha); + + if(!gradient) + /* The color is in ABGR8888 format with red channel in the lower 8 bits. */ + vg_col32 = ((vg_lite_color_t)lv_col32.alpha << 24) | ((vg_lite_color_t)lv_col32.blue << 16) | + ((vg_lite_color_t)lv_col32.green << 8) | (vg_lite_color_t)lv_col32.red; + else + /* The gradient color is in ARGB8888 format with blue channel in the lower 8 bits. */ + vg_col32 = ((vg_lite_color_t)lv_col32.alpha << 24) | ((vg_lite_color_t)lv_col32.red << 16) | + ((vg_lite_color_t)lv_col32.green << 8) | (vg_lite_color_t)lv_col32.blue; + + return vg_col32; +} + +vg_lite_blend_t vglite_get_blend_mode(lv_blend_mode_t lv_blend_mode) +{ + vg_lite_blend_t vg_blend_mode = VG_LITE_BLEND_NONE; + + if(vg_lite_query_feature(gcFEATURE_BIT_VG_LVGL_SUPPORT)) { + switch(lv_blend_mode) { + case LV_BLEND_MODE_NORMAL: + vg_blend_mode = VG_LITE_BLEND_NORMAL_LVGL; + break; + case LV_BLEND_MODE_ADDITIVE: + vg_blend_mode = VG_LITE_BLEND_ADDITIVE_LVGL; + break; + case LV_BLEND_MODE_SUBTRACTIVE: + vg_blend_mode = VG_LITE_BLEND_SUBTRACT_LVGL; + break; + case LV_BLEND_MODE_MULTIPLY: + vg_blend_mode = VG_LITE_BLEND_MULTIPLY_LVGL; + break; + default: + VGLITE_ASSERT_MSG(false, "Unsupported blend mode."); + break; + } + } + else { + switch(lv_blend_mode) { + case LV_BLEND_MODE_NORMAL: + vg_blend_mode = VG_LITE_BLEND_SRC_OVER; + break; + case LV_BLEND_MODE_ADDITIVE: + vg_blend_mode = VG_LITE_BLEND_ADDITIVE; + break; + case LV_BLEND_MODE_SUBTRACTIVE: + vg_blend_mode = VG_LITE_BLEND_SUBTRACT; + break; + case LV_BLEND_MODE_MULTIPLY: + vg_blend_mode = VG_LITE_BLEND_MULTIPLY; + break; + default: + VGLITE_ASSERT_MSG(false, "Unsupported blend mode."); + break; } - lv_col32_premul.ch.alpha = opa; } - switch(vg_col_format) { - case VG_LITE_BGRA8888: - *vg_col32 = lv_col32_premul.full; - break; - case VG_LITE_RGBA8888: - *vg_col32 = ((uint32_t)lv_col32_premul.ch.red << 24) | ((uint32_t)lv_col32_premul.ch.green << 16) | - ((uint32_t)lv_col32_premul.ch.blue << 8) | (uint32_t)lv_col32_premul.ch.alpha; - break; - case VG_LITE_ABGR8888: - *vg_col32 = ((uint32_t)lv_col32_premul.ch.alpha << 24) | ((uint32_t)lv_col32_premul.ch.blue << 16) | - ((uint32_t)lv_col32_premul.ch.green << 8) | (uint32_t)lv_col32_premul.ch.red; - break; - case VG_LITE_ARGB8888: - *vg_col32 = ((uint32_t)lv_col32_premul.ch.alpha << 24) | ((uint32_t)lv_col32_premul.ch.red << 16) | - ((uint32_t)lv_col32_premul.ch.green << 8) | (uint32_t)lv_col32_premul.ch.blue; - break; - default: - return LV_RES_INV; - } - - return LV_RES_OK; + return vg_blend_mode; } -vg_lite_blend_t lv_vglite_get_blend_mode(lv_blend_mode_t lv_blend_mode) +vg_lite_buffer_format_t vglite_get_buf_format(lv_color_format_t cf) { - vg_lite_blend_t vg_blend_mode; - switch(lv_blend_mode) { - case LV_BLEND_MODE_ADDITIVE: - vg_blend_mode = VG_LITE_BLEND_ADDITIVE; + vg_lite_buffer_format_t vg_buffer_format = VG_LITE_BGR565; + + switch(cf) { + case LV_COLOR_FORMAT_L8: + vg_buffer_format = VG_LITE_L8; break; - case LV_BLEND_MODE_SUBTRACTIVE: - vg_blend_mode = VG_LITE_BLEND_SUBTRACT; + case LV_COLOR_FORMAT_A8: + vg_buffer_format = VG_LITE_A8; break; - case LV_BLEND_MODE_MULTIPLY: - vg_blend_mode = VG_LITE_BLEND_MULTIPLY; + case LV_COLOR_FORMAT_I1: + vg_buffer_format = VG_LITE_INDEX_1; break; - case LV_BLEND_MODE_REPLACE: - vg_blend_mode = VG_LITE_BLEND_NONE; + case LV_COLOR_FORMAT_I2: + vg_buffer_format = VG_LITE_INDEX_2; break; + case LV_COLOR_FORMAT_I4: + vg_buffer_format = VG_LITE_INDEX_4; + break; + case LV_COLOR_FORMAT_I8: + vg_buffer_format = VG_LITE_INDEX_8; + break; + case LV_COLOR_FORMAT_RGB565: + vg_buffer_format = VG_LITE_BGR565; + break; + case LV_COLOR_FORMAT_RGB565A8: + vg_buffer_format = VG_LITE_ABGR8565; + break; + case LV_COLOR_FORMAT_RGB888: + vg_buffer_format = VG_LITE_BGR888; + break; + case LV_COLOR_FORMAT_ARGB8888: + vg_buffer_format = VG_LITE_BGRA8888; + break; + case LV_COLOR_FORMAT_XRGB8888: + vg_buffer_format = VG_LITE_BGRX8888; + break; + default: - vg_blend_mode = VG_LITE_BLEND_SRC_OVER; + VGLITE_ASSERT_MSG(false, "Unsupported color format."); break; } - return vg_blend_mode; + + return vg_buffer_format; +} + +uint8_t vglite_get_alignment(lv_color_format_t cf) +{ + uint8_t align_bytes = LV_COLOR_DEPTH / 8 * 16; /*16 pixels*/ + + switch(cf) { + case LV_COLOR_FORMAT_I1: + case LV_COLOR_FORMAT_I2: + case LV_COLOR_FORMAT_I4: + /* + * VGLite alignment require 8 bytes. + * But ARM clean and invalidate cache needs 32 bytes address alignment. + */ + align_bytes = 32; + break; + case LV_COLOR_FORMAT_I8: + case LV_COLOR_FORMAT_A8: + case LV_COLOR_FORMAT_L8: + /* + * VGLite alignment require 16 bytes. + * But ARM clean and invalidate cache needs 32 bytes address alignment. + */ + align_bytes = 32; + break; + case LV_COLOR_FORMAT_RGB565: + align_bytes = 32; + break; + case LV_COLOR_FORMAT_RGB565A8: + case LV_COLOR_FORMAT_RGB888: + align_bytes = 48; + break; + case LV_COLOR_FORMAT_ARGB8888: + case LV_COLOR_FORMAT_XRGB8888: + align_bytes = 64; + break; + + default: + VGLITE_ASSERT_MSG(false, "Unsupported buffer format."); + break; + } + + return align_bytes; +} + +bool vglite_buf_aligned(const void * buf, uint32_t stride, lv_color_format_t cf) +{ + uint8_t align_bytes = vglite_get_alignment(cf); + + /* No alignment requirement for destination buffer when using mode VG_LITE_LINEAR */ + + /* Test for pointer alignment */ + if((uintptr_t)buf % align_bytes) + return false; + + /* Test for stride alignment */ + if(stride == 0 || stride % align_bytes) + return false; + + return true; } /********************** * STATIC FUNCTIONS **********************/ -static inline void invalidate_cache(void) -{ - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - if(disp->driver->clean_dcache_cb) - disp->driver->clean_dcache_cb(disp->driver); -} - -#endif /*LV_USE_GPU_NXP_VG_LITE*/ +#endif /*LV_USE_DRAW_VGLITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_utils.h b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_utils.h index 219396b10..814276223 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_utils.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/nxp/vglite/lv_vglite_utils.h @@ -4,27 +4,9 @@ */ /** - * MIT License - * - * Copyright 2022, 2023 NXP - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next paragraph) - * shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * Copyright 2022-2024 NXP * + * SPDX-License-Identifier: MIT */ #ifndef LV_VGLITE_UTILS_H @@ -39,33 +21,43 @@ extern "C" { *********************/ #include "../../../lv_conf_internal.h" -#if LV_USE_GPU_NXP_VG_LITE -#include "vg_lite.h" +#if LV_USE_DRAW_VGLITE #include "../../sw/lv_draw_sw.h" -#include "../../../misc/lv_log.h" + +#include "vg_lite.h" +#include "vg_lite_options.h" /********************* * DEFINES *********************/ -#ifndef LV_GPU_NXP_VG_LITE_LOG_ERRORS -/** Enable logging of VG-Lite errors (\see LV_LOG_ERROR)*/ -#define LV_GPU_NXP_VG_LITE_LOG_ERRORS 1 +#define ENUM_TO_STRING(e) \ + case (e): \ + return #e + +#if LV_USE_VGLITE_ASSERT +#define VGLITE_ASSERT(expr) LV_ASSERT(expr) +#else +#define VGLITE_ASSERT(expr) #endif -#ifndef LV_GPU_NXP_VG_LITE_LOG_TRACES -/** Enable logging of VG-Lite traces (\see LV_LOG_ERROR)*/ -#define LV_GPU_NXP_VG_LITE_LOG_TRACES 0 -#endif +#define VGLITE_ASSERT_MSG(expr, msg) \ + do { \ + if(!(expr)) { \ + LV_LOG_ERROR(msg); \ + VGLITE_ASSERT(false); \ + } \ + } while(0) - -/* The optimal Bezier control point offset for radial unit - * see: https://spencermortensen.com/articles/bezier-circle/ - **/ -#define BEZIER_OPTIM_CIRCLE 0.551915024494f - -/* Draw lines for control points of Bezier curves */ -#define BEZIER_DBG_CONTROL_POINTS 0 +#define VGLITE_CHECK_ERROR(function) \ + do { \ + vg_lite_error_t error = function; \ + if(error != VG_LITE_SUCCESS) { \ + LV_LOG_ERROR("Execute '" #function "' error(%d): %s", \ + (int)error, vglite_error_to_string(error)); \ + VGLITE_ASSERT(false); \ + } \ + } while (0) /********************** * TYPEDEFS @@ -76,35 +68,44 @@ extern "C" { **********************/ /** - * Enable scissor and set the clipping box. + * Set the clipping box. * * @param[in] clip_area Clip area with relative coordinates of destination buffer + * */ -static inline void lv_vglite_set_scissor(const lv_area_t * clip_area); - -/** - * Disable scissor. - */ -static inline void lv_vglite_disable_scissor(void); - +static inline void vglite_set_scissor(const lv_area_t * clip_area); /********************** * GLOBAL PROTOTYPES **********************/ +const char * vglite_error_to_string(vg_lite_error_t error); + +#if LV_USE_VGLITE_DRAW_ASYNC /** - * Premultiplies and swizzles given LVGL 32bit color to obtain vglite color. + * Get VG-Lite command buffer flushed status. * - * @param[in/out] vg_col32 The obtained vglite color - * @param[in] lv_col32 The initial LVGL 32bit color - * @param[in] opa The opacity to premultiply with - * @param[in] vg_col_format The format of the resulting vglite color - * - * @retval LV_RES_OK Operation completed - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) */ -lv_res_t lv_vglite_premult_and_swizzle(vg_lite_color_t * vg_col32, lv_color32_t lv_col32, lv_opa_t opa, - vg_lite_buffer_format_t vg_col_format); +bool vglite_cmd_buf_is_flushed(void); +#endif + +/** + * Flush command to VG-Lite. + * + */ +void vglite_run(void); + +/** + * Get vglite color. Premultiplies (if not hw already) and swizzles the given + * LVGL 32bit color to obtain vglite color. + * + * @param[in] lv_col32 The initial LVGL 32bit color + * @param[in] gradient True for gradient color + * + * @retval The vglite 32-bit color value: + * + */ +vg_lite_color_t vglite_get_color(lv_color32_t lv_col32, bool gradient); /** * Get vglite blend mode. @@ -112,86 +113,56 @@ lv_res_t lv_vglite_premult_and_swizzle(vg_lite_color_t * vg_col32, lv_color32_t * @param[in] lv_blend_mode The LVGL blend mode * * @retval The vglite blend mode + * */ -vg_lite_blend_t lv_vglite_get_blend_mode(lv_blend_mode_t lv_blend_mode); +vg_lite_blend_t vglite_get_blend_mode(lv_blend_mode_t lv_blend_mode); /** - * Clear cache and flush command to VG-Lite. + * Get vglite buffer format. + * + * @param[in] cf Color format + * + * @retval The vglite buffer format * - * @retval LV_RES_OK Run completed - * @retval LV_RES_INV Error occurred (\see LV_GPU_NXP_VG_LITE_LOG_ERRORS) */ -lv_res_t lv_vglite_run(void); +vg_lite_buffer_format_t vglite_get_buf_format(lv_color_format_t cf); + +/** + * Get vglite buffer alignment. + * + * @param[in] cf Color format + * + * @retval Alignment requirement in bytes + * + */ +uint8_t vglite_get_alignment(lv_color_format_t cf); + +/** + * Check memory and stride alignment. + * + * @param[in] buf Buffer address + * @param[in] stride Stride of buffer in bytes + * @param[in] cf Color format - to calculate the expected alignment + * + * @retval true Alignment OK + * + */ +bool vglite_buf_aligned(const void * buf, uint32_t stride, lv_color_format_t cf); /********************** * MACROS **********************/ -#define VG_LITE_COND_STOP(cond, txt) \ - do { \ - if (cond) { \ - LV_LOG_ERROR("%s. STOP!", txt); \ - for ( ; ; ); \ - } \ - } while(0) - -#if LV_GPU_NXP_VG_LITE_LOG_ERRORS -#define VG_LITE_ERR_RETURN_INV(err, fmt, ...) \ - do { \ - if(err != VG_LITE_SUCCESS) { \ - LV_LOG_ERROR(fmt" (err = %d)", \ - err, ##__VA_ARGS__); \ - return LV_RES_INV; \ - } \ - } while (0) -#else -#define VG_LITE_ERR_RETURN_INV(err, fmt, ...) \ - do { \ - if(err != VG_LITE_SUCCESS) { \ - return LV_RES_INV; \ - } \ - }while(0) -#endif /*LV_GPU_NXP_VG_LITE_LOG_ERRORS*/ - -#if LV_GPU_NXP_VG_LITE_LOG_TRACES -#define VG_LITE_LOG_TRACE(fmt, ...) \ - do { \ - LV_LOG(fmt, ##__VA_ARGS__); \ - } while (0) - -#define VG_LITE_RETURN_INV(fmt, ...) \ - do { \ - LV_LOG_ERROR(fmt, ##__VA_ARGS__); \ - return LV_RES_INV; \ - } while (0) -#else -#define VG_LITE_LOG_TRACE(fmt, ...) \ - do { \ - } while (0) -#define VG_LITE_RETURN_INV(fmt, ...) \ - do { \ - return LV_RES_INV; \ - }while(0) -#endif /*LV_GPU_NXP_VG_LITE_LOG_TRACES*/ - /********************** * STATIC FUNCTIONS **********************/ -static inline void lv_vglite_set_scissor(const lv_area_t * clip_area) +static inline void vglite_set_scissor(const lv_area_t * clip_area) { - vg_lite_enable_scissor(); - vg_lite_set_scissor((int32_t)clip_area->x1, (int32_t)clip_area->y1, - (int32_t)lv_area_get_width(clip_area), - (int32_t)lv_area_get_height(clip_area)); + vg_lite_set_scissor(clip_area->x1, clip_area->y1, clip_area->x2 + 1, clip_area->y2 + 1); } -static inline void lv_vglite_disable_scissor(void) -{ - vg_lite_disable_scissor(); -} - -#endif /*LV_USE_GPU_NXP_VG_LITE*/ +#endif /*LV_USE_DRAW_VGLITE*/ #ifdef __cplusplus } /*extern "C"*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d.c b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d.c new file mode 100644 index 000000000..029a1b5a2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d.c @@ -0,0 +1,633 @@ +/** + * @file lv_draw_dave2d.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + +/********************* + * DEFINES + *********************/ +#define DRAW_UNIT_ID_DAVE2D 4 + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +#if LV_USE_OS + static void _dave2d_render_thread_cb(void * ptr); +#endif + +static void execute_drawing(lv_draw_dave2d_unit_t * u); + +#if defined(RENESAS_CORTEX_M85) +#if (BSP_CFG_DCACHE_ENABLED) +static void _dave2d_buf_invalidate_cache_cb(void * buf, uint32_t stride, lv_color_format_t color_format, + const lv_area_t * area); +#endif +#endif + +static int32_t _dave2d_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task); + +static int32_t lv_draw_dave2d_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer); + +static d2_s32 lv_dave2d_init(void); + +static void lv_draw_buf_dave2d_init_handlers(void); + +void dave2d_execute_dlist_and_flush(void); + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +d2_device * _d2_handle; +d2_renderbuffer * _renderbuffer; +d2_renderbuffer * _blit_renderbuffer; + +lv_ll_t _ll_Dave2D_Tasks; + +#if LV_USE_OS + lv_mutex_t xd2Semaphore; +#endif + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_dave2d_init(void) +{ + d2_s32 result = D2_OK; + + lv_draw_buf_dave2d_init_handlers(); + + lv_draw_dave2d_unit_t * draw_dave2d_unit = lv_draw_create_unit(sizeof(lv_draw_dave2d_unit_t)); + draw_dave2d_unit->base_unit.dispatch_cb = lv_draw_dave2d_dispatch; + draw_dave2d_unit->base_unit.evaluate_cb = _dave2d_evaluate; + draw_dave2d_unit->idx = DRAW_UNIT_ID_DAVE2D; + + result = lv_dave2d_init(); + if(D2_OK != result) { + __BKPT(0); + } + +#if LV_USE_OS + lv_result_t res; + res = lv_mutex_init(&xd2Semaphore); + if(LV_RESULT_OK != res) { + __BKPT(0); + } + + draw_dave2d_unit->pd2Mutex = &xd2Semaphore; +#endif + + draw_dave2d_unit->d2_handle = _d2_handle; + draw_dave2d_unit->renderbuffer = _renderbuffer; + _lv_ll_init(&_ll_Dave2D_Tasks, 4); + +#if LV_USE_OS + lv_thread_init(&draw_dave2d_unit->thread, LV_THREAD_PRIO_HIGH, _dave2d_render_thread_cb, 8 * 1024, draw_dave2d_unit); +#endif + +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_draw_buf_dave2d_init_handlers(void) +{ + lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers(); + +#if defined(RENESAS_CORTEX_M85) +#if (BSP_CFG_DCACHE_ENABLED) + handlers->invalidate_cache_cb = _dave2d_buf_invalidate_cache_cb; +#endif +#endif +} + +#if defined(RENESAS_CORTEX_M85) +#if (BSP_CFG_DCACHE_ENABLED) +static void _dave2d_buf_invalidate_cache_cb(void * buf, uint32_t stride, lv_color_format_t color_format, + const lv_area_t * area) +{ + uint8_t * address = buf; + int32_t i = 0; + uint32_t bytes_per_pixel = lv_color_format_get_size(color_format); + int32_t width = lv_area_get_width(area); + int32_t lines = lv_area_get_height(area); + int32_t bytes_to_flush_per_line = (int32_t)width * (int32_t)bytes_per_pixel; + + /* Stride is in bytes, not pixels */ + address = address + (area->x1 * (int32_t)bytes_per_pixel) + (stride * (uint32_t)area->y1); + + for(i = 0; i < lines; i++) { + SCB_CleanInvalidateDCache_by_Addr(address, bytes_to_flush_per_line); + address += stride; + } +} +#endif +#endif + +/** + * @todo + * LVGL needs to use hardware acceleration for buf_copy and do not affect GPU rendering. + */ +#if 0 +static void _dave2d_buf_copy(void * dest_buf, uint32_t dest_w, uint32_t dest_h, const lv_area_t * dest_area, + void * src_buf, uint32_t src_w, uint32_t src_h, const lv_area_t * src_area, lv_color_format_t color_format) +{ + d2_s32 result; + +#if LV_USE_OS + lv_result_t status; + + status = lv_mutex_lock(&xd2Semaphore); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + d2_u32 src_blend_mode = d2_getblendmodesrc(_d2_handle); + d2_u32 dst_blend_mode = d2_getblendmodedst(_d2_handle); + + result = d2_selectrenderbuffer(_d2_handle, _blit_renderbuffer); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_setblendmode(_d2_handle, d2_bm_one, d2_bm_zero); + if(D2_OK != result) { + __BKPT(0); + } + + // Generate render operations + result = d2_framebuffer(_d2_handle, (uint16_t *)dest_buf, DISPLAY_HSIZE_INPUT0, DISPLAY_BUFFER_STRIDE_PIXELS_INPUT0, + DISPLAY_VSIZE_INPUT0, lv_draw_dave2d_cf_fb_get()); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_cliprect(_d2_handle, (d2_border)dest_area->x1, (d2_border)dest_area->y1, (d2_border)dest_area->x2, + (d2_border)dest_area->y2); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_setblitsrc(_d2_handle, (void *) src_buf, (d2_s32)src_w, (d2_s32)src_w, (d2_s32)src_h, + lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(color_format)); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_blitcopy(_d2_handle, (d2_s32)src_w, (d2_s32)src_h, (d2_blitpos)src_area->x1, (d2_blitpos)src_area->y1, + D2_FIX4(dest_w), D2_FIX4(dest_h), + D2_FIX4(dest_area->x1), D2_FIX4(dest_area->y1), 0); + if(D2_OK != result) { + __BKPT(0); + } + + // Execute render operations + result = d2_executerenderbuffer(_d2_handle, _blit_renderbuffer, 0); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_flushframe(_d2_handle); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_selectrenderbuffer(_d2_handle, _renderbuffer); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_setblendmode(_d2_handle, src_blend_mode, dst_blend_mode); + if(D2_OK != result) { + __BKPT(0); + } + +#if LV_USE_OS + status = lv_mutex_unlock(&xd2Semaphore); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + +} +#endif + +#define USE_D2 (1) + +static int32_t _dave2d_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t) +{ + LV_UNUSED(u); + int32_t ret = 0; + + switch(t->type) { + case LV_DRAW_TASK_TYPE_FILL: { +#if USE_D2 + lv_draw_fill_dsc_t * dsc = t->draw_dsc; + if(dsc->grad.dir == LV_GRAD_DIR_NONE + || ((dsc->grad.dir != LV_GRAD_DIR_NONE) + && ((dsc->grad.stops[0].color.blue == dsc->grad.stops[dsc->grad.stops_count - 1].color.blue) + && (dsc->grad.stops[0].color.red == dsc->grad.stops[dsc->grad.stops_count - 1].color.red) + && (dsc->grad.stops[0].color.green == dsc->grad.stops[dsc->grad.stops_count - 1].color.green)))) { + + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; + + } + else +#endif + { + __NOP(); + } + ret = 0; + break; + } + case LV_DRAW_TASK_TYPE_LAYER: { + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_IMAGE: { +#if USE_D2 + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; +#endif + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_BORDER: { +#if USE_D2 + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; +#endif + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_BOX_SHADOW: { + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_LABEL: { +#if USE_D2 + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; +#endif + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_LINE: { +#if USE_D2 + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; +#endif + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_ARC: { +#if USE_D2 + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; +#endif + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_TRIANGLE: { +#if USE_D2 + lv_draw_fill_dsc_t * dsc = t->draw_dsc; + if(dsc->grad.dir == LV_GRAD_DIR_NONE + || ((dsc->grad.dir != LV_GRAD_DIR_NONE) + && ((dsc->grad.stops[0].color.blue == dsc->grad.stops[dsc->grad.stops_count - 1].color.blue) + && (dsc->grad.stops[0].color.red == dsc->grad.stops[dsc->grad.stops_count - 1].color.red) + && (dsc->grad.stops[0].color.green == dsc->grad.stops[dsc->grad.stops_count - 1].color.green)))) { + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; + } + else { + } +#endif + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_MASK_RECTANGLE: { +#if 0//USE_D2 + t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D; + t->preference_score = 0; +#endif + ret = 0; + break; + } + + case LV_DRAW_TASK_TYPE_MASK_BITMAP: { + ret = 0; + break; + } + + default: + ret = 0; + break; + } + + return ret; +} + +#define DAVE2D_REFERRING_WATERMARK 10 + +static int32_t lv_draw_dave2d_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer) +{ + lv_draw_dave2d_unit_t * draw_dave2d_unit = (lv_draw_dave2d_unit_t *) draw_unit; +#if (0 == D2_RENDER_EACH_OPERATION) + static uint32_t ref_count = 0; +#endif + + /*Return immediately if it's busy with draw task*/ + if(draw_dave2d_unit->task_act) return 0; + + lv_draw_task_t * t = NULL; + t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_DAVE2D); + + /* Return 0 is no selection, some tasks can be supported by other units. */ + if(t == NULL) { +#if (0 == D2_RENDER_EACH_OPERATION) + if(false == _lv_ll_is_empty(&_ll_Dave2D_Tasks)) { + ref_count = 0; + dave2d_execute_dlist_and_flush(); + } +#endif + return 0; + } + + if(t->preferred_draw_unit_id != DRAW_UNIT_ID_DAVE2D) { + return 0; + } + + void * buf = lv_draw_layer_alloc_buf(layer); + if(buf == NULL) { + return -1; + } + +#if (0 == D2_RENDER_EACH_OPERATION) + ref_count += lv_draw_get_dependent_count(t); + + if(DAVE2D_REFERRING_WATERMARK < ref_count) { + ref_count = 0; + dave2d_execute_dlist_and_flush(); + } + + lv_draw_task_t ** p_new_list_entry; + p_new_list_entry = _lv_ll_ins_tail(&_ll_Dave2D_Tasks); + *p_new_list_entry = t; +#endif + + t->state = LV_DRAW_TASK_STATE_IN_PROGRESS; + draw_dave2d_unit->base_unit.target_layer = layer; + draw_dave2d_unit->base_unit.clip_area = &t->clip_area; + draw_dave2d_unit->task_act = t; + +#if LV_USE_OS + /*Let the render thread work*/ + lv_thread_sync_signal(&draw_dave2d_unit->sync); +#else + execute_drawing(draw_dave2d_unit); +#if (D2_RENDER_EACH_OPERATION) + draw_dave2d_unit->task_act->state = LV_DRAW_TASK_STATE_READY; +#endif + draw_dave2d_unit->task_act = NULL; + + /*The draw unit is free now. Request a new dispatching as it can get a new task*/ + lv_draw_dispatch_request(); + +#endif + return 1; +} + +#if LV_USE_OS +static void _dave2d_render_thread_cb(void * ptr) +{ + lv_draw_dave2d_unit_t * u = ptr; + + lv_thread_sync_init(&u->sync); + + while(1) { + while(u->task_act == NULL) { + lv_thread_sync_wait(&u->sync); + } + + execute_drawing(u); + + /*Cleanup*/ +#if (D2_RENDER_EACH_OPERATION) + u->task_act->state = LV_DRAW_TASK_STATE_READY; +#endif + u->task_act = NULL; + + /*The draw unit is free now. Request a new dispatching as it can get a new task*/ + lv_draw_dispatch_request(); + } +} +#endif + +static void execute_drawing(lv_draw_dave2d_unit_t * u) +{ + /*Render the draw task*/ + lv_draw_task_t * t = u->task_act; + lv_layer_t * layer = u->base_unit.target_layer; + +#if defined(RENESAS_CORTEX_M85) +#if (BSP_CFG_DCACHE_ENABLED) + lv_area_t clipped_area; + int32_t x; + int32_t y; + + _lv_area_intersect(&clipped_area, &t->area, u->base_unit.clip_area); + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + lv_area_move(&clipped_area, x, y); + + /* Invalidate cache */ + lv_draw_buf_invalidate_cache(layer->draw_buf->data, layer->draw_buf->header.stride, layer->color_format, &clipped_area); +#endif +#endif + + switch(t->type) { + case LV_DRAW_TASK_TYPE_FILL: + lv_draw_dave2d_fill(u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_BORDER: + lv_draw_dave2d_border(u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_BOX_SHADOW: + //lv_draw_dave2d_box_shadow(u, t->draw_dsc, &t->area); + break; +#if 0 + case LV_DRAW_TASK_TYPE_BG_IMG: + //lv_draw_dave2d_bg_image(u, t->draw_dsc, &t->area); + break; +#endif + case LV_DRAW_TASK_TYPE_LABEL: + lv_draw_dave2d_label(u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_IMAGE: + lv_draw_dave2d_image(u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_LINE: + lv_draw_dave2d_line(u, t->draw_dsc); + break; + case LV_DRAW_TASK_TYPE_ARC: + lv_draw_dave2d_arc(u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_TRIANGLE: + lv_draw_dave2d_triangle(u, t->draw_dsc); + break; + case LV_DRAW_TASK_TYPE_LAYER: + //lv_draw_dave2d_layer(u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_MASK_RECTANGLE: + //lv_draw_dave2d_mask_rect(u, t->draw_dsc, &t->area); + break; + default: + break; + } + +} + +static d2_s32 lv_dave2d_init(void) +{ + d2_s32 result = D2_OK; + + if(_d2_handle != NULL) { + return D2_NOMEMORY; + } + + _d2_handle = d2_opendevice(0); + if(_d2_handle == NULL) { + return D2_NOMEMORY; + } + + /* bind the hardware */ + result = d2_inithw(_d2_handle, 0); + if(result != D2_OK) { + LV_LOG_ERROR("Could NOT d2_inithw\n"); + d2_closedevice(_d2_handle); + return result; + } + + // + // Set various D2 parameters + // + result = d2_setblendmode(_d2_handle, d2_bm_alpha, d2_bm_one_minus_alpha); + result = d2_setalphamode(_d2_handle, d2_am_constant); + result = d2_setalpha(_d2_handle, UINT8_MAX); + result = d2_setantialiasing(_d2_handle, 1); + result = d2_setlinecap(_d2_handle, d2_lc_butt); + result = d2_setlinejoin(_d2_handle, d2_lj_miter); + + /* set blocksize for default displaylist */ + result = d2_setdlistblocksize(_d2_handle, 25); + if(D2_OK != result) { + LV_LOG_ERROR("Could NOT d2_setdlistblocksize\n"); + d2_closedevice(_d2_handle); + return result; + } + + _blit_renderbuffer = d2_newrenderbuffer(_d2_handle, 20, 20); + if(!_blit_renderbuffer) { + LV_LOG_ERROR("NO renderbuffer\n"); + d2_closedevice(_d2_handle); + + return D2_NOMEMORY; + } + + _renderbuffer = d2_newrenderbuffer(_d2_handle, 20, 20); + if(!_renderbuffer) { + LV_LOG_ERROR("NO renderbuffer\n"); + d2_closedevice(_d2_handle); + + return D2_NOMEMORY; + } + + result = d2_selectrenderbuffer(_d2_handle, _renderbuffer); + if(D2_OK != result) { + LV_LOG_ERROR("Could NOT d2_selectrenderbuffer\n"); + d2_closedevice(_d2_handle); + } + + return result; +} + +void dave2d_execute_dlist_and_flush(void) +{ +#if LV_USE_OS + lv_result_t status; + + status = lv_mutex_lock(&xd2Semaphore); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + d2_s32 result; + lv_draw_task_t ** p_list_entry; + lv_draw_task_t * p_list_entry1; + + // Execute render operations + result = d2_executerenderbuffer(_d2_handle, _renderbuffer, 0); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_flushframe(_d2_handle); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_selectrenderbuffer(_d2_handle, _renderbuffer); + if(D2_OK != result) { + __BKPT(0); + } + + while(false == _lv_ll_is_empty(&_ll_Dave2D_Tasks)) { + p_list_entry = _lv_ll_get_tail(&_ll_Dave2D_Tasks); + p_list_entry1 = *p_list_entry; + p_list_entry1->state = LV_DRAW_TASK_STATE_READY; + _lv_ll_remove(&_ll_Dave2D_Tasks, p_list_entry); + lv_free(p_list_entry); + } + +#if LV_USE_OS + status = lv_mutex_unlock(&xd2Semaphore); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif +} + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d.h b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d.h new file mode 100644 index 000000000..0058518d4 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d.h @@ -0,0 +1,91 @@ +#ifndef LV_DRAW_DAVE2D_H +#define LV_DRAW_DAVE2D_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lv_conf_internal.h" +#if LV_USE_DRAW_DAVE2D +#include "../../lv_draw.h" +#include "hal_data.h" +#include "lv_draw_dave2d_utils.h" + +/********************* + * DEFINES + *********************/ + +#define D2_RENDER_EACH_OPERATION (1) + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_draw_unit_t base_unit; + lv_draw_task_t * task_act; +#if LV_USE_OS + lv_thread_sync_t sync; + lv_thread_t thread; +#endif + uint32_t idx; + d2_device * d2_handle; + d2_renderbuffer * renderbuffer; +#if LV_USE_OS + lv_mutex_t * pd2Mutex; +#endif +} lv_draw_dave2d_unit_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_dave2d_init(void); + +void lv_draw_dave2d_image(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords); + +void lv_draw_dave2d_fill(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords); + +void lv_draw_dave2d_border(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_dave2d_box_shadow(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_box_shadow_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_dave2d_label(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords); + +void lv_draw_dave2d_arc(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords); + +void lv_draw_dave2d_line(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc); + +void lv_draw_dave2d_layer(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords); + +void lv_draw_dave2d_triangle(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc); + +void lv_draw_dave2d_mask_rect(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_mask_rect_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_dave2d_transform(lv_draw_dave2d_unit_t * draw_unit, const lv_area_t * dest_area, const void * src_buf, + int32_t src_w, int32_t src_h, int32_t src_stride, + const lv_draw_image_dsc_t * draw_dsc, const lv_draw_image_sup_t * sup, lv_color_format_t cf, void * dest_buf); + +/*********************** + * GLOBAL VARIABLES + ***********************/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DRAW_DAVE2D*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_arc.c b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_arc.c new file mode 100644 index 000000000..c703bbe61 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_arc.c @@ -0,0 +1,194 @@ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + +void lv_draw_dave2d_arc(lv_draw_dave2d_unit_t * u, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords) +{ + + uint32_t flags = 0; + int32_t sin_start; + int32_t cos_start; + int32_t sin_end; + int32_t cos_end; + d2_s32 result; + lv_area_t clipped_area; + lv_area_t buffer_area; + lv_point_t arc_centre; + int32_t x; + int32_t y; + + if(!_lv_area_intersect(&clipped_area, coords, u->base_unit.clip_area)) return; + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + buffer_area = u->base_unit.target_layer->buf_area; + + arc_centre = dsc->center; + arc_centre.x = arc_centre.x - buffer_area.x1; + arc_centre.y = arc_centre.y - buffer_area.y1; + + lv_area_move(&clipped_area, x, y); + lv_area_move(&buffer_area, x, y); + + // + // If both angles are equal (e.g. 0 and 0 or 180 and 180) nothing has to be done + // + if(dsc->start_angle == dsc->end_angle) { + return; // Nothing to do, no angle - no arc + } + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + + // + // Generate render operations + // + d2_framebuffer_from_layer(u->d2_handle, u->base_unit.target_layer); + + d2_setalpha(u->d2_handle, dsc->opa); + + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(dsc->color)); + + result = d2_cliprect(u->d2_handle, (d2_border)clipped_area.x1, (d2_border)clipped_area.y1, (d2_border)clipped_area.x2, + (d2_border)clipped_area.y2); + if(D2_OK != result) { + __BKPT(0); + } + + if(360 <= LV_ABS(dsc->start_angle - dsc->end_angle)) { + d2_rendercircle(u->d2_handle, + (d2_point)D2_FIX4(arc_centre.x), + (d2_point) D2_FIX4(arc_centre.y), + (d2_width) D2_FIX4(dsc->radius - dsc->width / 2), + (d2_width) D2_FIX4(dsc->width)); + } + else { //An ARC, not a full circle + // + // If the difference between both is larger than 180 degrees we must use the concave flag + // + /** Set d2_wf_concave flag if the pie object to draw is concave shape. */ + if((LV_ABS(dsc->start_angle - dsc->end_angle) > 180) || ((dsc->end_angle < dsc->start_angle) && + (LV_ABS(dsc->start_angle - (dsc->end_angle + 360)) > 180))) { + flags = d2_wf_concave; + } + else { + flags = 0; + } + + sin_start = lv_trigo_sin((int16_t)dsc->start_angle); + cos_start = lv_trigo_cos((int16_t)dsc->start_angle); + + sin_end = lv_trigo_sin((int16_t)dsc->end_angle); + cos_end = lv_trigo_cos((int16_t)dsc->end_angle); + + bool draw_arc; + lv_area_t arc_area; + lv_area_t clip_arc; + lv_point_t start_point; + lv_point_t end_point; + + start_point.x = arc_centre.x + (int16_t)(((dsc->radius) * cos_start) >> LV_TRIGO_SHIFT); + start_point.y = arc_centre.y + (int16_t)(((dsc->radius) * sin_start) >> LV_TRIGO_SHIFT); + + end_point.x = arc_centre.x + (int16_t)(((dsc->radius) * cos_end) >> LV_TRIGO_SHIFT); + end_point.y = arc_centre.y + (int16_t)(((dsc->radius) * sin_end) >> LV_TRIGO_SHIFT); + + arc_area.x1 = LV_MIN3(start_point.x, end_point.x, arc_centre.x); + arc_area.y1 = LV_MIN3(start_point.y, end_point.y, arc_centre.y); + + arc_area.x2 = LV_MAX3(start_point.x, end_point.x, arc_centre.x); + arc_area.y2 = LV_MAX3(start_point.y, end_point.y, arc_centre.y); + + /* 0 degrees */ + if((dsc->end_angle < dsc->start_angle) || ((dsc->start_angle < 360) && (dsc->end_angle > 360))) { + arc_area.x2 = arc_centre.x + dsc->radius; + } + + /* 90 degrees */ + if(((dsc->end_angle > 90) && (dsc->start_angle < 90)) || ((dsc->start_angle < 90) && + (dsc->end_angle < dsc->start_angle))) { + arc_area.y2 = arc_centre.y + dsc->radius; + } + + /* 180 degrees */ + if(((dsc->end_angle > 180) && (dsc->start_angle < 180)) || ((dsc->start_angle < 180) && + (dsc->end_angle < dsc->start_angle))) { + arc_area.x1 = arc_centre.x - dsc->radius; + } + + /* 270 degrees */ + if(((dsc->end_angle > 270) && (dsc->start_angle < 270)) || ((dsc->start_angle < 270) && + (dsc->end_angle < dsc->start_angle))) { + arc_area.y1 = arc_centre.y - dsc->radius; + } + + draw_arc = _lv_area_intersect(&clip_arc, &arc_area, &clipped_area); + + if(draw_arc) { + + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(arc_centre.x), + (d2_point) D2_FIX4(arc_centre.y), + (d2_width) D2_FIX4(dsc->radius - dsc->width / 2), + (d2_width) D2_FIX4(dsc->width), + -(d2_s32)(sin_start << 1), + (d2_s32)(cos_start << 1), + (d2_s32)(sin_end << 1), + -(d2_s32)(cos_end << 1), + flags); + if(D2_OK != result) { + __BKPT(0); + } + + if(dsc->rounded) { + lv_point_t start_coord; + lv_point_t end_coord; + + start_coord.x = arc_centre.x + (int16_t)(((dsc->radius - dsc->width / 2) * cos_start) >> LV_TRIGO_SHIFT); + start_coord.y = arc_centre.y + (int16_t)(((dsc->radius - dsc->width / 2) * sin_start) >> LV_TRIGO_SHIFT); + + /** Render a circle. */ + d2_rendercircle(u->d2_handle, + (d2_point) D2_FIX4((uint16_t)(start_coord.x)), + (d2_point) D2_FIX4((uint16_t)(start_coord.y)), + (d2_width) D2_FIX4(dsc->width / 2), 0); + + end_coord.x = arc_centre.x + (int16_t)(((dsc->radius - dsc->width / 2) * cos_end) >> LV_TRIGO_SHIFT); + end_coord.y = arc_centre.y + (int16_t)(((dsc->radius - dsc->width / 2) * sin_end) >> LV_TRIGO_SHIFT); + + /** Render a circle. */ + d2_rendercircle(u->d2_handle, + (d2_point) D2_FIX4((uint16_t)(end_coord.x)), + (d2_point) D2_FIX4((uint16_t)(end_coord.y)), + (d2_width) D2_FIX4(dsc->width / 2), 0); + } + } + } + + // + // Execute render operations + // + +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif +} + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_border.c b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_border.c new file mode 100644 index 000000000..70763332e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_border.c @@ -0,0 +1,433 @@ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + +static void dave2d_draw_border_complex(lv_draw_dave2d_unit_t * draw_unit, const lv_area_t * outer_area, + const lv_area_t * inner_area, + int32_t rout, int32_t rin, lv_color_t color, lv_opa_t opa); + +static void dave2d_draw_border_simple(lv_draw_dave2d_unit_t * draw_unit, const lv_area_t * outer_area, + const lv_area_t * inner_area, + lv_color_t color, lv_opa_t opa); + +void lv_draw_dave2d_border(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, + const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) return; + if(dsc->width == 0) return; + if(dsc->side == LV_BORDER_SIDE_NONE) return; + + int32_t coords_w = lv_area_get_width(coords); + int32_t coords_h = lv_area_get_height(coords); + int32_t rout = dsc->radius; + int32_t short_side = LV_MIN(coords_w, coords_h); + if(rout > short_side >> 1) rout = short_side >> 1; + + /*Get the inner area*/ + lv_area_t area_inner; + lv_area_copy(&area_inner, coords); + area_inner.x1 += ((dsc->side & LV_BORDER_SIDE_LEFT) ? dsc->width : - (dsc->width + rout)); + area_inner.x2 -= ((dsc->side & LV_BORDER_SIDE_RIGHT) ? dsc->width : - (dsc->width + rout)); + area_inner.y1 += ((dsc->side & LV_BORDER_SIDE_TOP) ? dsc->width : - (dsc->width + rout)); + area_inner.y2 -= ((dsc->side & LV_BORDER_SIDE_BOTTOM) ? dsc->width : - (dsc->width + rout)); + + int32_t rin = rout - dsc->width; + if(rin < 0) rin = 0; + + if(rout == 0 && rin == 0) { + dave2d_draw_border_simple(draw_unit, coords, &area_inner, dsc->color, dsc->opa); + } + else { + dave2d_draw_border_complex(draw_unit, coords, &area_inner, rout, rin, dsc->color, dsc->opa); + } + +} + +static void dave2d_draw_border_simple(lv_draw_dave2d_unit_t * u, const lv_area_t * outer_area, + const lv_area_t * inner_area, + lv_color_t color, lv_opa_t opa) + +{ + + lv_area_t clip_area; + lv_area_t local_outer_area; + lv_area_t local_inner_area; + int32_t x; + int32_t y; + bool is_common; + + is_common = _lv_area_intersect(&clip_area, outer_area, u->base_unit.clip_area); + if(!is_common) return; + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + local_outer_area = *outer_area; + local_inner_area = *inner_area; + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + lv_area_move(&clip_area, x, y); + lv_area_move(&local_outer_area, x, y); + lv_area_move(&local_inner_area, x, y); + +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + // + // Generate render operations + // + + d2_framebuffer_from_layer(u->d2_handle, u->base_unit.target_layer); + + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(color)); + d2_setalpha(u->d2_handle, opa); + d2_cliprect(u->d2_handle, (d2_border)clip_area.x1, (d2_border)clip_area.y1, (d2_border)clip_area.x2, + (d2_border)clip_area.y2); + + lv_area_t a; + + bool top_side = local_outer_area.y1 <= local_inner_area.y1; + bool bottom_side = local_outer_area.y2 >= local_inner_area.y2; + bool left_side = local_outer_area.x1 <= local_inner_area.x1; + bool right_side = local_outer_area.x2 >= local_inner_area.x2; + + /*Top*/ + a.x1 = local_outer_area.x1; + a.x2 = local_outer_area.x2; + a.y1 = local_outer_area.y1; + a.y2 = local_inner_area.y1 - 1; + if(top_side) { + d2_renderbox(u->d2_handle, (d2_point)D2_FIX4(a.x1), + (d2_point)D2_FIX4(a.y1), + (d2_point)D2_FIX4(lv_area_get_width(&a)), + (d2_point)D2_FIX4(lv_area_get_height(&a))); + } + + /*Bottom*/ + a.y1 = local_inner_area.y2 + 1; + a.y2 = local_outer_area.y2; + if(bottom_side) { + d2_renderbox(u->d2_handle, (d2_point)D2_FIX4(a.x1), + (d2_point)D2_FIX4(a.y1), + (d2_point)D2_FIX4(lv_area_get_width(&a)), + (d2_point)D2_FIX4(lv_area_get_height(&a))); + } + + /*Left*/ + a.x1 = local_outer_area.x1; + a.x2 = local_inner_area.x1 - 1; + a.y1 = (top_side) ? local_inner_area.y1 : local_outer_area.y1; + a.y2 = (bottom_side) ? local_inner_area.y2 : local_outer_area.y2; + if(left_side) { + d2_renderbox(u->d2_handle, (d2_point)D2_FIX4(a.x1), + (d2_point)D2_FIX4(a.y1), + (d2_point)D2_FIX4(lv_area_get_width(&a)), + (d2_point)D2_FIX4(lv_area_get_height(&a))); + } + + /*Right*/ + a.x1 = local_inner_area.x2 + 1; + a.x2 = local_outer_area.x2; + if(right_side) { + d2_renderbox(u->d2_handle, (d2_point)D2_FIX4(a.x1), + (d2_point)D2_FIX4(a.y1), + (d2_point)D2_FIX4(lv_area_get_width(&a)), + (d2_point)D2_FIX4(lv_area_get_height(&a))); + } + + // + // Execute render operations + // +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif +} + +static void dave2d_draw_border_complex(lv_draw_dave2d_unit_t * u, const lv_area_t * orig_outer_area, + const lv_area_t * orig_inner_area, + int32_t rout, int32_t rin, lv_color_t color, lv_opa_t opa) +{ +#if LV_DRAW_SW_COMPLEX + /*Get clipped draw area which is the real draw area. + *It is always the same or inside `coords`*/ + lv_area_t draw_area; + lv_area_t outer_area; + lv_area_t inner_area; + int32_t x; + int32_t y; + d2_s32 result; + d2_u32 flags = 0; + + outer_area = *orig_outer_area; + inner_area = *orig_inner_area; + + if(!_lv_area_intersect(&draw_area, &outer_area, u->base_unit.clip_area)) return; + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + lv_area_move(&draw_area, x, y); + lv_area_move(&outer_area, x, y); + lv_area_move(&inner_area, x, y); + +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + // + // Generate render operations + // + + d2_framebuffer_from_layer(u->d2_handle, u->base_unit.target_layer); + + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(color)); + d2_setalpha(u->d2_handle, opa); + d2_cliprect(u->d2_handle, (d2_border)draw_area.x1, (d2_border)draw_area.y1, (d2_border)draw_area.x2, + (d2_border)draw_area.y2); + + lv_area_t blend_area; + /*Calculate the x and y coordinates where the straight parts area are */ + lv_area_t core_area; + core_area.x1 = LV_MAX(outer_area.x1 + rout, inner_area.x1); + core_area.x2 = LV_MIN(outer_area.x2 - rout, inner_area.x2); + core_area.y1 = LV_MAX(outer_area.y1 + rout, inner_area.y1); + core_area.y2 = LV_MIN(outer_area.y2 - rout, inner_area.y2); + + bool top_side = outer_area.y1 <= inner_area.y1; + bool bottom_side = outer_area.y2 >= inner_area.y2; + + /*No masks*/ + bool left_side = outer_area.x1 <= inner_area.x1; + bool right_side = outer_area.x2 >= inner_area.x2; + + /*Draw the straight lines first */ + if(top_side) { + blend_area.x1 = core_area.x1; + blend_area.x2 = core_area.x2; + blend_area.y1 = outer_area.y1; + blend_area.y2 = inner_area.y1 - 1; + d2_renderbox(u->d2_handle, + (d2_point)D2_FIX4(blend_area.x1), + (d2_point)D2_FIX4(blend_area.y1), + (d2_point)D2_FIX4(lv_area_get_width(&blend_area)), + (d2_point)D2_FIX4(lv_area_get_height(&blend_area))); + } + + if(bottom_side) { + blend_area.x1 = core_area.x1; + blend_area.x2 = core_area.x2; + blend_area.y1 = inner_area.y2 + 1; + blend_area.y2 = outer_area.y2; + d2_renderbox(u->d2_handle, + (d2_point)D2_FIX4(blend_area.x1), + (d2_point)D2_FIX4(blend_area.y1), + (d2_point)D2_FIX4(lv_area_get_width(&blend_area)), + (d2_point)D2_FIX4(lv_area_get_height(&blend_area))); + } + + if(left_side) { + blend_area.x1 = outer_area.x1; + blend_area.x2 = inner_area.x1 - 1; + blend_area.y1 = core_area.y1; + blend_area.y2 = core_area.y2; + d2_renderbox(u->d2_handle, + (d2_point)D2_FIX4(blend_area.x1), + (d2_point)D2_FIX4(blend_area.y1), + (d2_point)D2_FIX4(lv_area_get_width(&blend_area)), + (d2_point)D2_FIX4(lv_area_get_height(&blend_area))); + } + + if(right_side) { + blend_area.x1 = inner_area.x2 + 1; + blend_area.x2 = outer_area.x2; + blend_area.y1 = core_area.y1; + blend_area.y2 = core_area.y2; + d2_renderbox(u->d2_handle, + (d2_point)D2_FIX4(blend_area.x1), + (d2_point)D2_FIX4(blend_area.y1), + (d2_point)D2_FIX4(lv_area_get_width(&blend_area)), + (d2_point)D2_FIX4(lv_area_get_height(&blend_area))); + } + + /*Draw the corners*/ + int32_t blend_w; + /*Left corners*/ + blend_area.x1 = draw_area.x1; + blend_area.x2 = LV_MIN(draw_area.x2, core_area.x1 - 1); + + blend_w = lv_area_get_width(&blend_area); + + if(blend_w > 0) { + d2_s32 aa; + aa = d2_getantialiasing(u->d2_handle); + d2_setantialiasing(u->d2_handle, 0); //Don't blend with the background according to coverage value + + if(left_side || top_side) { + lv_area_t arc_area; + lv_area_t clip_arc; + + arc_area.x1 = core_area.x1 - rout; + arc_area.y1 = core_area.y1 - rout; + arc_area.x2 = core_area.x1; + arc_area.y2 = core_area.y1; + + if(_lv_area_intersect(&clip_arc, &arc_area, &draw_area)) { + d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2, + (d2_border)clip_arc.y2); + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(core_area.x1), + (d2_point) D2_FIX4(core_area.y1), + (d2_width) D2_FIX4(rout), + (d2_width) D2_FIX4((rout - rin)), + (d2_s32) D2_FIX16(0), // 180 Degrees + (d2_s32) D2_FIX16((int16_t) -1), + (d2_s32) D2_FIX16((int16_t) -1),//( 270 Degrees + (d2_s32) D2_FIX16(0), + flags); + if(D2_OK != result) { + __BKPT(0); + } + } + + } + + if(left_side || bottom_side) { + lv_area_t arc_area; + lv_area_t clip_arc; + + arc_area.x1 = core_area.x1 - rout; + arc_area.y1 = core_area.y2; + arc_area.x2 = core_area.x1; + arc_area.y2 = core_area.y2 + rout; + + if(_lv_area_intersect(&clip_arc, &arc_area, &draw_area)) { + + d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2, + (d2_border)clip_arc.y2); + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(core_area.x1), + (d2_point) D2_FIX4(core_area.y2), + (d2_width) D2_FIX4(rout), + (d2_width) D2_FIX4((rout - rin)), + (d2_s32) D2_FIX16((int16_t) -1), //90 degrees + (d2_s32) D2_FIX16(0), + (d2_s32) D2_FIX16(0), //180 degrees + (d2_s32) D2_FIX16(1), + flags); + if(D2_OK != result) { + __BKPT(0); + } + } + } + + /*Right corners*/ + blend_area.x1 = LV_MAX(draw_area.x1, blend_area.x2 + 1); /*To not overlap with the left side*/ + blend_area.x1 = LV_MAX(draw_area.x1, core_area.x2 + 1); + + blend_area.x2 = draw_area.x2; + blend_w = lv_area_get_width(&blend_area); + + if(blend_w > 0) { + if(right_side || top_side) { + + lv_area_t arc_area; + lv_area_t clip_arc; + + arc_area.x1 = core_area.x2; + arc_area.y1 = core_area.y1 - rout; + arc_area.x2 = core_area.x2 + rout; + arc_area.y2 = core_area.y1; + + if(_lv_area_intersect(&clip_arc, &arc_area, &draw_area)) { + + d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2, + (d2_border)clip_arc.y2); + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(core_area.x2), + (d2_point) D2_FIX4(core_area.y1), + (d2_width) D2_FIX4(rout), + (d2_width) D2_FIX4((rout - rin)), + (d2_s32) D2_FIX16((int16_t)1), // 270 Degrees + (d2_s32) D2_FIX16(0), + (d2_s32) D2_FIX16(0),// 0 degrees + (d2_s32) D2_FIX16(-1), + flags); + if(D2_OK != result) { + __BKPT(0); + } + } + + } + + if(right_side || bottom_side) { + lv_area_t arc_area; + lv_area_t clip_arc; + + arc_area.x1 = core_area.x2; + arc_area.y1 = core_area.y2; + arc_area.x2 = core_area.x2 + rout; + arc_area.y2 = core_area.y2 + rout; + + if(_lv_area_intersect(&clip_arc, &arc_area, &draw_area)) { + + d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2, + (d2_border)clip_arc.y2); + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(core_area.x2), + (d2_point) D2_FIX4(core_area.y2), + (d2_width) D2_FIX4(rout), + (d2_width) D2_FIX4((rout - rin)), + (d2_s32) D2_FIX16(0),// 0 degrees + (d2_s32) D2_FIX16(1), + (d2_s32) D2_FIX16(1),// 90 degrees + (d2_s32) D2_FIX16(0), + flags); + if(D2_OK != result) { + __BKPT(0); + } + } + } + } + d2_setantialiasing(u->d2_handle, aa); //restore original setting + } + + // + // Execute render operations + // +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + +#endif /*LV_DRAW_SW_COMPLEX*/ +} + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_fill.c b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_fill.c new file mode 100644 index 000000000..3f9599165 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_fill.c @@ -0,0 +1,328 @@ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + +void lv_draw_dave2d_fill(lv_draw_dave2d_unit_t * u, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords) +{ + lv_area_t draw_area; + lv_area_t coordinates; + bool is_common; + int32_t x; + int32_t y; + d2_u8 current_alpha_mode = 0; + d2_s32 result; + d2_u32 flags = 0; + + lv_point_t arc_centre; + + is_common = _lv_area_intersect(&draw_area, coords, u->base_unit.clip_area); + if(!is_common) return; + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + lv_area_copy(&coordinates, coords); + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + lv_area_move(&draw_area, x, y); + lv_area_move(&coordinates, x, y); + + // + // Generate render operations + // +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + + d2_framebuffer_from_layer(u->d2_handle, u->base_unit.target_layer); + + if(LV_GRAD_DIR_NONE != dsc->grad.dir) { + float a1; + float a2; + + float y1; + float y2; + + float y3; + float y0; + int16_t y0_i ; + int16_t y3_i ; + + if(LV_GRAD_DIR_VER == dsc->grad.dir) { + a1 = dsc->grad.stops[0].opa; + a2 = dsc->grad.stops[dsc->grad.stops_count - 1].opa; + + y1 = (float)LV_MIN(coordinates.y1, coordinates.y2); + y2 = (float)LV_MAX(coordinates.y1, coordinates.y2); + + if(a1 < a2) { + /* TODO */ + __BKPT(0); + y0 = 0.0f;//silence the compiler warning + y3 = 0.0f; + + } + else { + y0 = y2 - ((y2 - y1) / (a2 - a1) * (a2)); //point where alpha is 0 + y3 = y1 + ((y2 - y1) / (a2 - a1) * (255 - a1)); //point where alpha is 255 + } + + y0_i = (int16_t)y0; + y3_i = (int16_t)y3; + + d2_setalphagradient(u->d2_handle, 0, (d2_point)D2_FIX4(0), (d2_point)D2_FIX4(y0_i), (d2_point)D2_FIX4(0), + (d2_point)D2_FIX4((y3_i - y0_i))); + } + else if(LV_GRAD_DIR_HOR == dsc->grad.dir) { + /* TODO */ + __BKPT(0); + + float x1; + float x2; + + float x3; + float x0; + int16_t x0_i ; + int16_t x3_i ; + + a1 = dsc->grad.stops[0].opa; + a2 = dsc->grad.stops[dsc->grad.stops_count - 1].opa; + + x1 = (float)LV_MIN(coordinates.x1, coordinates.x2); + x2 = (float)LV_MAX(coordinates.x1, coordinates.x2); + + if(a1 < a2) { + /* TODO */ + __BKPT(0); + x0 = 0.0f;//silence the compiler warning + x3 = 0.0f; + + } + else { + x0 = x2 - ((x2 - x1) / (a2 - a1) * (a2)); //point where alpha is 0 + x3 = x1 + ((x2 - x1) / (a2 - a1) * (255 - a1)); //point where alpha is 255 + } + + x0_i = (int16_t)x0; + x3_i = (int16_t)x3; + + d2_setalphagradient(u->d2_handle, 0, (d2_point)D2_FIX4(x0_i), (d2_point)D2_FIX4(0), (d2_point)D2_FIX4(x3_i - x0_i), + (d2_point)D2_FIX4((0))); + } + + current_alpha_mode = d2_getalphamode(u->d2_handle); + d2_setfillmode(u->d2_handle, d2_fm_color); + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(dsc->grad.stops[0].color)); + d2_setalphamode(u->d2_handle, d2_am_gradient1); + } + else { + d2_setfillmode(u->d2_handle, d2_fm_color); //default + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(dsc->color)); + d2_setalpha(u->d2_handle, dsc->opa); + } + + d2_cliprect(u->d2_handle, (d2_border)draw_area.x1, (d2_border)draw_area.y1, (d2_border)draw_area.x2, + (d2_border)draw_area.y2); + + if(dsc->radius == 0) { + + d2_renderbox(u->d2_handle, (d2_point)D2_FIX4(coordinates.x1), + (d2_point)D2_FIX4(coordinates.y1), + (d2_point)D2_FIX4(lv_area_get_width(&coordinates)), + (d2_point)D2_FIX4(lv_area_get_height(&coordinates))); + } + else { + /*Get the real radius. Can't be larger than the half of the shortest side */ + int32_t coords_bg_w = lv_area_get_width(&coordinates); + int32_t coords_bg_h = lv_area_get_height(&coordinates); + int32_t short_side = LV_MIN(coords_bg_w, coords_bg_h); + int32_t radius = LV_MIN(dsc->radius, short_side >> 1); + + arc_centre.x = coordinates.x1 + radius; + arc_centre.y = coordinates.y1 + radius; + + if(((2 * radius) == coords_bg_w) && ((2 * radius) == coords_bg_h)) { + result = d2_rendercircle(u->d2_handle, + (d2_point)D2_FIX4(arc_centre.x), + (d2_point) D2_FIX4(arc_centre.y), + (d2_width) D2_FIX4(radius), + (d2_width) D2_FIX4(0)); + if(D2_OK != result) { + __BKPT(0); + } + } + else { + + lv_area_t arc_area; + lv_area_t clip_arc; + arc_centre.x = coordinates.x1 + radius; + arc_centre.y = coordinates.y1 + radius; + + arc_area.x1 = coordinates.x1; + arc_area.y1 = coordinates.y1; + arc_area.x2 = coordinates.x1 + radius; + arc_area.y2 = coordinates.y1 + radius; + + if(_lv_area_intersect(&clip_arc, &arc_area, &draw_area)) { + + d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2, + (d2_border)clip_arc.y2); + + // d2_renderwedge internally changes the clip rectangle, only draw it if it is in side the current clip rectangle + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(arc_centre.x), + (d2_point) D2_FIX4(arc_centre.y), + (d2_width) D2_FIX4(radius), + (d2_width) D2_FIX4(0), + (d2_s32) D2_FIX16(0), // 180 Degrees + (d2_s32) D2_FIX16((int16_t) -1), + (d2_s32) D2_FIX16((int16_t) -1),//( 270 Degrees + (d2_s32) D2_FIX16(0), + flags); + if(D2_OK != result) { + __BKPT(0); + } + } + + arc_centre.x = coordinates.x2 - radius; + arc_centre.y = coordinates.y1 + radius; + + arc_area.x1 = coordinates.x2 - radius; + arc_area.y1 = coordinates.y1; + arc_area.x2 = coordinates.x2; + arc_area.y2 = coordinates.y1 + radius; + + if(_lv_area_intersect(&clip_arc, &arc_area, &draw_area)) { + d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2, + (d2_border)clip_arc.y2); + + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(arc_centre.x), + (d2_point) D2_FIX4(arc_centre.y), + (d2_width) D2_FIX4(radius), + (d2_width) D2_FIX4(0), + (d2_s32) D2_FIX16((int16_t)1), // 270 Degrees + (d2_s32) D2_FIX16(0), + (d2_s32) D2_FIX16(0),// 0 degrees + (d2_s32) D2_FIX16(-1), + flags); + if(D2_OK != result) { + __BKPT(0); + } + } + + arc_centre.x = coordinates.x2 - radius; + arc_centre.y = coordinates.y2 - radius; + + arc_area.x1 = coordinates.x2 - radius; + arc_area.y1 = coordinates.y2 - radius; + arc_area.x2 = coordinates.x2; + arc_area.y2 = coordinates.y2; + + if(_lv_area_intersect(&clip_arc, &arc_area, &draw_area)) { + d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2, + (d2_border)clip_arc.y2); + + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(arc_centre.x), + (d2_point) D2_FIX4(arc_centre.y), + (d2_width) D2_FIX4(radius), + (d2_width) D2_FIX4(0), + (d2_s32) D2_FIX16(0),// 0 degrees + (d2_s32) D2_FIX16(1), + (d2_s32) D2_FIX16(1),// 90 degrees + (d2_s32) D2_FIX16(0), + flags); + if(D2_OK != result) { + __BKPT(0); + } + } + + arc_centre.x = coordinates.x1 + radius; + arc_centre.y = coordinates.y2 - radius; + + arc_area.x1 = coordinates.x1; + arc_area.y1 = coordinates.y2 - radius; + arc_area.x2 = coordinates.x1 + radius; + arc_area.y2 = coordinates.y2; + + if(_lv_area_intersect(&clip_arc, &arc_area, &draw_area)) { + d2_cliprect(u->d2_handle, (d2_border)clip_arc.x1, (d2_border)clip_arc.y1, (d2_border)clip_arc.x2, + (d2_border)clip_arc.y2); + + result = d2_renderwedge(u->d2_handle, + (d2_point)D2_FIX4(arc_centre.x), + (d2_point) D2_FIX4(arc_centre.y), + (d2_width) D2_FIX4(radius), + (d2_width) D2_FIX4(0), + (d2_s32) D2_FIX16((int16_t) -1), //90 degrees + (d2_s32) D2_FIX16(0), + (d2_s32) D2_FIX16(0), //180 degrees + (d2_s32) D2_FIX16(1), + flags); + if(D2_OK != result) { + __BKPT(0); + } + } + + /* reset the clip rectangle */ + d2_cliprect(u->d2_handle, (d2_border)draw_area.x1, (d2_border)draw_area.y1, (d2_border)draw_area.x2, + (d2_border)draw_area.y2); + + result = d2_renderbox(u->d2_handle, + (d2_width)D2_FIX4(coordinates.x1 + radius), + (d2_width)D2_FIX4(coordinates.y1), + (d2_width)D2_FIX4(lv_area_get_width(&coordinates) - (2 * radius)), + (d2_width)D2_FIX4(lv_area_get_height(&coordinates))); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_renderbox(u->d2_handle, + (d2_width)D2_FIX4(coordinates.x1), + (d2_width)D2_FIX4(coordinates.y1 + radius), + (d2_width)D2_FIX4(radius), + (d2_width)D2_FIX4(lv_area_get_height(&coordinates) - (2 * radius))); + if(D2_OK != result) { + __BKPT(0); + } + + result = d2_renderbox(u->d2_handle, + (d2_width)D2_FIX4(coordinates.x2 - radius), + (d2_width)D2_FIX4(coordinates.y1 + radius), + (d2_width)D2_FIX4(radius), + (d2_width)D2_FIX4(lv_area_get_height(&coordinates) - (2 * radius))); + if(D2_OK != result) { + __BKPT(0); + } + } + } + + // + // Execute render operations + // +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + + if(LV_GRAD_DIR_NONE != dsc->grad.dir) { + d2_setalphamode(u->d2_handle, current_alpha_mode); + d2_setfillmode(u->d2_handle, d2_fm_color); //default + } + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif +} + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_image.c b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_image.c new file mode 100644 index 000000000..7c55b6d3d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_image.c @@ -0,0 +1,331 @@ +/** + * @file lv_draw_dave2d_image.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void img_draw_core(lv_draw_unit_t * u_base, const lv_draw_image_dsc_t * draw_dsc, + const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup, + const lv_area_t * img_coords, const lv_area_t * clipped_img_area); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_dave2d_image(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords) +{ + if(!draw_dsc->tile) { + _lv_draw_image_normal_helper((lv_draw_unit_t *)draw_unit, draw_dsc, coords, img_draw_core); + } + else { + _lv_draw_image_tiled_helper((lv_draw_unit_t *)draw_unit, draw_dsc, coords, img_draw_core); + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void img_draw_core(lv_draw_unit_t * u_base, const lv_draw_image_dsc_t * draw_dsc, + const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup, + const lv_area_t * img_coords, const lv_area_t * clipped_img_area) +{ + + lv_draw_dave2d_unit_t * u = (lv_draw_dave2d_unit_t *)u_base; + + (void)sup; //remove warning about unused parameter + + bool transformed = draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE || + draw_dsc->scale_y != LV_SCALE_NONE ? true : false; + + const lv_draw_buf_t * decoded = decoder_dsc->decoded; + const uint8_t * src_buf = decoded->data; + const lv_image_header_t * header = &decoded->header; + uint32_t img_stride = decoded->header.stride; + lv_color_format_t cf = decoded->header.cf; + lv_area_t buffer_area; + lv_area_t draw_area; + lv_area_t clipped_area; + int32_t x; + int32_t y; + d2_u8 a_texture_op = d2_to_one; + d2_u8 r_texture_op = d2_to_copy; + d2_u8 g_texture_op = d2_to_copy; + d2_u8 b_texture_op = d2_to_copy; + d2_u8 current_fill_mode; + d2_u32 src_blend_mode; + d2_u32 dst_blend_mode; + void * p_intermediate_buf = NULL; + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + buffer_area = u->base_unit.target_layer->buf_area; + draw_area = *img_coords; + clipped_area = *clipped_img_area; + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + lv_area_move(&draw_area, x, y); + lv_area_move(&buffer_area, x, y); + lv_area_move(&clipped_area, x, y); + + /* Generate render operations*/ +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + + current_fill_mode = d2_getfillmode(u->d2_handle); + a_texture_op = d2_gettextureoperationa(u->d2_handle); + r_texture_op = d2_gettextureoperationr(u->d2_handle); + g_texture_op = d2_gettextureoperationg(u->d2_handle); + b_texture_op = d2_gettextureoperationb(u->d2_handle); + src_blend_mode = d2_getblendmodesrc(u->d2_handle); + dst_blend_mode = d2_getblendmodedst(u->d2_handle); + +#if defined(RENESAS_CORTEX_M85) +#if (BSP_CFG_DCACHE_ENABLED) + d1_cacheblockflush(u->d2_handle, 0, src_buf, + img_stride * header->h); //Stride is in bytes, not pixels/texels +#endif +#endif + + if(LV_COLOR_FORMAT_RGB565A8 == cf) { + + lv_point_t p1[4] = { //Points in clockwise order + {0, 0}, + {header->w - 1, 0}, + {header->w - 1, header->h - 1}, + {0, header->h - 1}, + }; + + d2_s32 dxu1 = D2_FIX16(1); + d2_s32 dxv1 = D2_FIX16(0); + d2_s32 dyu1 = D2_FIX16(0); + d2_s32 dyv1 = D2_FIX16(1); + + uint32_t size = header->h * (header->w * lv_color_format_get_size(LV_COLOR_FORMAT_ARGB8888)); + p_intermediate_buf = lv_malloc(size); + + d2_framebuffer(u->d2_handle, + p_intermediate_buf, + (d2_s32)header->w, + (d2_u32)header->w, + (d2_u32)header->h, + lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(LV_COLOR_FORMAT_ARGB8888)); + + d2_cliprect(u->d2_handle, (d2_border)0, (d2_border)0, (d2_border)header->w - 1, + (d2_border)header->h - 1); + + d2_settexopparam(u->d2_handle, d2_cc_alpha, draw_dsc->opa, 0); + + d2_settextureoperation(u->d2_handle, d2_to_replace, d2_to_copy, d2_to_copy, d2_to_copy); + + d2_settexturemapping(u->d2_handle, D2_FIX4(p1[0].x), D2_FIX4(p1[0].y), D2_FIX16(0), D2_FIX16(0), dxu1, dxv1, dyu1, + dyv1); + d2_settexturemode(u->d2_handle, d2_tm_filter); + d2_setfillmode(u->d2_handle, d2_fm_texture); + + d2_settexture(u->d2_handle, (void *)src_buf, + (d2_s32)(img_stride / lv_color_format_get_size(LV_COLOR_FORMAT_RGB565)), + header->w, header->h, lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(LV_COLOR_FORMAT_RGB565)); + + d2_setblendmode(u->d2_handle, d2_bm_one, d2_bm_zero); + + d2_renderquad(u->d2_handle, + (d2_point)D2_FIX4(p1[0].x), + (d2_point)D2_FIX4(p1[0].y), + (d2_point)D2_FIX4(p1[1].x), + (d2_point)D2_FIX4(p1[1].y), + (d2_point)D2_FIX4(p1[2].x), + (d2_point)D2_FIX4(p1[2].y), + (d2_point)D2_FIX4(p1[3].x), + (d2_point)D2_FIX4(p1[3].y), + 0); + + d2_setblendmode(u->d2_handle, d2_bm_zero, d2_bm_one); //Keep the RGB data in the intermediate buffer + + d2_setalphablendmode(u->d2_handle, d2_bm_one, d2_bm_zero); //Write SRC alpha, i.e. A8 data + + d2_settextureoperation(u->d2_handle, d2_to_copy, d2_to_copy, d2_to_copy, d2_to_copy); + + d2_settexture(u->d2_handle, (void *)(src_buf + header->h * (header->w * lv_color_format_get_size( + LV_COLOR_FORMAT_RGB565))), + (d2_s32)(img_stride / lv_color_format_get_size(LV_COLOR_FORMAT_RGB565)), + header->w, header->h, lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(LV_COLOR_FORMAT_A8)); + + d2_renderquad(u->d2_handle, + (d2_point)D2_FIX4(p1[0].x), + (d2_point)D2_FIX4(p1[0].y), + (d2_point)D2_FIX4(p1[1].x), + (d2_point)D2_FIX4(p1[1].y), + (d2_point)D2_FIX4(p1[2].x), + (d2_point)D2_FIX4(p1[2].y), + (d2_point)D2_FIX4(p1[3].x), + (d2_point)D2_FIX4(p1[3].y), + 0); + + cf = LV_COLOR_FORMAT_ARGB8888; + src_buf = p_intermediate_buf; + img_stride = header->w * lv_color_format_get_size(cf); + + } + + d2_framebuffer_from_layer(u->d2_handle, u->base_unit.target_layer); + + d2_cliprect(u->d2_handle, (d2_border)clipped_area.x1, (d2_border)clipped_area.y1, (d2_border)clipped_area.x2, + (d2_border)clipped_area.y2); + + d2_settexopparam(u->d2_handle, d2_cc_alpha, draw_dsc->opa, 0); + + if(LV_COLOR_FORMAT_RGB565 == cf) { + d2_settextureoperation(u->d2_handle, d2_to_replace, d2_to_copy, d2_to_copy, d2_to_copy); + } + else { //Formats with an alpha channel, + d2_settextureoperation(u->d2_handle, d2_to_copy, d2_to_copy, d2_to_copy, d2_to_copy); + } + + if(LV_BLEND_MODE_NORMAL == draw_dsc->blend_mode) { /**< Simply mix according to the opacity value*/ + d2_setblendmode(u->d2_handle, d2_bm_alpha, d2_bm_one_minus_alpha); //direct linear blend + } + else if(LV_BLEND_MODE_ADDITIVE == draw_dsc->blend_mode) { /**< Add the respective color channels*/ + /* TODO */ + d2_setblendmode(u->d2_handle, d2_bm_alpha, d2_bm_one); //Additive blending + } + else if(LV_BLEND_MODE_SUBTRACTIVE == draw_dsc->blend_mode) { /**< Subtract the foreground from the background*/ + /* TODO */ + __NOP(); + } + else { //LV_BLEND_MODE_MULTIPLY, /**< Multiply the foreground and background*/ + /* TODO */ + __NOP(); + } + + lv_point_t p[4] = { //Points in clockwise order + {0, 0}, + {header->w - 1, 0}, + {header->w - 1, header->h - 1}, + {0, header->h - 1}, + }; + + d2_settexture(u->d2_handle, (void *)src_buf, + (d2_s32)(img_stride / lv_color_format_get_size(cf)), + header->w, header->h, lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(cf)); + + d2_settexturemode(u->d2_handle, d2_tm_filter); + d2_setfillmode(u->d2_handle, d2_fm_texture); + + d2_s32 dxu = D2_FIX16(1); + d2_s32 dxv = D2_FIX16(0); + d2_s32 dyu = D2_FIX16(0); + d2_s32 dyv = D2_FIX16(1); + + if(transformed) { + lv_point_transform(&p[0], draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, &draw_dsc->pivot, true); + lv_point_transform(&p[1], draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, &draw_dsc->pivot, true); + lv_point_transform(&p[2], draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, &draw_dsc->pivot, true); + lv_point_transform(&p[3], draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, &draw_dsc->pivot, true); + + int32_t angle_limited = draw_dsc->rotation; + if(angle_limited > 3600) angle_limited -= 3600; + if(angle_limited < 0) angle_limited += 3600; + + int32_t angle_low = angle_limited / 10; + + if(0 != angle_low) { + /* LV_TRIGO_SHIFT is 15, so only need to shift by 1 to get 16:16 fixed point */ + dxv = (d2_s32)((1 << 1) * lv_trigo_sin((int16_t)angle_low)); + dxu = (d2_s32)((1 << 1) * lv_trigo_cos((int16_t)angle_low)); + dyv = (d2_s32)((1 << 1) * lv_trigo_sin((int16_t)angle_low + 90)); + dyu = (d2_s32)((1 << 1) * lv_trigo_cos((int16_t)angle_low + 90)); + } + + if(LV_SCALE_NONE != draw_dsc->scale_x) { + dxu = (dxu * LV_SCALE_NONE) / draw_dsc->scale_x; + dxv = (dxv * LV_SCALE_NONE) / draw_dsc->scale_x; + } + if(LV_SCALE_NONE != draw_dsc->scale_y) { + dyu = (dyu * LV_SCALE_NONE) / draw_dsc->scale_y; + dyv = (dyv * LV_SCALE_NONE) / draw_dsc->scale_y; + } + } + + p[0].x += draw_area.x1; + p[0].y += draw_area.y1; + p[1].x += draw_area.x1; + p[1].y += draw_area.y1; + p[2].x += draw_area.x1; + p[2].y += draw_area.y1; + p[3].x += draw_area.x1; + p[3].y += draw_area.y1; + + d2_settexturemapping(u->d2_handle, D2_FIX4(p[0].x), D2_FIX4(p[0].y), D2_FIX16(0), D2_FIX16(0), dxu, dxv, dyu, dyv); + + d2_renderquad(u->d2_handle, + (d2_point)D2_FIX4(p[0].x), + (d2_point)D2_FIX4(p[0].y), + (d2_point)D2_FIX4(p[1].x), + (d2_point)D2_FIX4(p[1].y), + (d2_point)D2_FIX4(p[2].x), + (d2_point)D2_FIX4(p[2].y), + (d2_point)D2_FIX4(p[3].x), + (d2_point)D2_FIX4(p[3].y), + 0); + + // + // Execute render operations + // +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + + d2_setfillmode(u->d2_handle, current_fill_mode); + d2_settextureoperation(u->d2_handle, a_texture_op, r_texture_op, g_texture_op, b_texture_op); + d2_setblendmode(u->d2_handle, src_blend_mode, dst_blend_mode); + + if(NULL != p_intermediate_buf) { + lv_free(p_intermediate_buf); + } + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + +} + +#endif //LV_USE_DRAW_DAVE2D diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_label.c b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_label.c new file mode 100644 index 000000000..cc85f5e63 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_label.c @@ -0,0 +1,157 @@ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + +static void lv_draw_dave2d_draw_letter_cb(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc, + lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area); + +static lv_draw_dave2d_unit_t * unit = NULL; + +void lv_draw_dave2d_label(lv_draw_dave2d_unit_t * u, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) return; + + unit = u; + + lv_draw_label_iterate_characters(&u->base_unit, dsc, coords, lv_draw_dave2d_draw_letter_cb); + +} + +static void lv_draw_dave2d_draw_letter_cb(lv_draw_unit_t * u, lv_draw_glyph_dsc_t * glyph_draw_dsc, + lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area) +{ + + d2_u8 current_fillmode; + lv_area_t clip_area; + lv_area_t letter_coords; + + int32_t x; + int32_t y; + + letter_coords = *glyph_draw_dsc->letter_coords; + + bool is_common; + is_common = _lv_area_intersect(&clip_area, glyph_draw_dsc->letter_coords, u->clip_area); + if(!is_common) return; + + x = 0 - unit->base_unit.target_layer->buf_area.x1; + y = 0 - unit->base_unit.target_layer->buf_area.y1; + + lv_area_move(&clip_area, x, y); + lv_area_move(&letter_coords, x, y); + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(unit->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(unit->d2_handle, unit->renderbuffer); +#endif + + // + // Generate render operations + // + + d2_framebuffer_from_layer(unit->d2_handle, unit->base_unit.target_layer); + + current_fillmode = d2_getfillmode(unit->d2_handle); + + d2_cliprect(unit->d2_handle, (d2_border)clip_area.x1, (d2_border)clip_area.y1, (d2_border)clip_area.x2, + (d2_border)clip_area.y2); + + if(glyph_draw_dsc) { + if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_INVALID) { +#if LV_USE_FONT_PLACEHOLDER + /* Draw a placeholder rectangle*/ + lv_draw_border_dsc_t border_draw_dsc; + lv_draw_border_dsc_init(&border_draw_dsc); + border_draw_dsc.opa = glyph_draw_dsc->opa; + border_draw_dsc.color = glyph_draw_dsc->color; + border_draw_dsc.width = 1; + //lv_draw_sw_border(u, &border_draw_dsc, glyph_draw_dsc->bg_coords); + lv_draw_dave2d_border(unit, &border_draw_dsc, glyph_draw_dsc->bg_coords); +#endif + } + else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_A8) { + lv_area_t mask_area = letter_coords; + mask_area.x2 = mask_area.x1 + lv_draw_buf_width_to_stride(lv_area_get_width(&mask_area), LV_COLOR_FORMAT_A8) - 1; + // lv_draw_sw_blend_dsc_t blend_dsc; + // lv_memzero(&blend_dsc, sizeof(blend_dsc)); + // blend_dsc.color = glyph_draw_dsc->color; + // blend_dsc.opa = glyph_draw_dsc->opa; + // blend_dsc.mask_buf = glyph_draw_dsc->glyph_data; + // blend_dsc.mask_area = &mask_area; + // blend_dsc.blend_area = glyph_draw_dsc->letter_coords; + // blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + //lv_draw_sw_blend(u, &blend_dsc); + + lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data; + +#if defined(RENESAS_CORTEX_M85) +#if (BSP_CFG_DCACHE_ENABLED) + d1_cacheblockflush(unit->d2_handle, 0, draw_buf->data, draw_buf->data_size); +#endif +#endif + d2_settexture(unit->d2_handle, (void *)draw_buf->data, + (d2_s32)lv_draw_buf_width_to_stride((uint32_t)lv_area_get_width(&letter_coords), LV_COLOR_FORMAT_A8), + lv_area_get_width(&letter_coords), lv_area_get_height(&letter_coords), d2_mode_alpha8); + d2_settexopparam(unit->d2_handle, d2_cc_red, glyph_draw_dsc->color.red, 0); + d2_settexopparam(unit->d2_handle, d2_cc_green, glyph_draw_dsc->color.green, 0); + d2_settexopparam(unit->d2_handle, d2_cc_blue, glyph_draw_dsc->color.blue, 0); + d2_settexopparam(unit->d2_handle, d2_cc_alpha, glyph_draw_dsc->opa, 0); + + d2_settextureoperation(unit->d2_handle, d2_to_multiply, d2_to_multiply, d2_to_multiply, d2_to_multiply); + + d2_settexturemapping(unit->d2_handle, D2_FIX4(letter_coords.x1), D2_FIX4(letter_coords.y1), D2_FIX16(0), D2_FIX16(0), + D2_FIX16(1), D2_FIX16(0), D2_FIX16(0), D2_FIX16(1)); + + d2_settexturemode(unit->d2_handle, d2_tm_filter); + + d2_setfillmode(unit->d2_handle, d2_fm_texture); + + d2_renderbox(unit->d2_handle, (d2_point)D2_FIX4(letter_coords.x1), + (d2_point)D2_FIX4(letter_coords.y1), + (d2_point)D2_FIX4(lv_area_get_width(&letter_coords)), + (d2_point)D2_FIX4(lv_area_get_height(&letter_coords))); + + d2_setfillmode(unit->d2_handle, current_fillmode); + } + else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE) { +#if LV_USE_IMGFONT + lv_draw_image_dsc_t img_dsc; + lv_draw_image_dsc_init(&img_dsc); + img_dsc.rotation = 0; + img_dsc.scale_x = LV_SCALE_NONE; + img_dsc.scale_y = LV_SCALE_NONE; + img_dsc.opa = glyph_draw_dsc->opa; + img_dsc.src = glyph_draw_dsc->glyph_data; + //lv_draw_sw_image(draw_unit, &img_dsc, glyph_draw_dsc->letter_coords); +#endif + } + } + + // + // Execute render operations + // +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(unit->d2_handle, unit->renderbuffer, 0); + d2_flushframe(unit->d2_handle); +#endif + + if(fill_draw_dsc && fill_area) { + //lv_draw_sw_fill(u, fill_draw_dsc, fill_area); + lv_draw_dave2d_fill(unit, fill_draw_dsc, fill_area); + } + +#if LV_USE_OS + status = lv_mutex_unlock(unit->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif +} + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_line.c b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_line.c new file mode 100644 index 000000000..b23aa8b98 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_line.c @@ -0,0 +1,97 @@ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + +void lv_draw_dave2d_line(lv_draw_dave2d_unit_t * u, const lv_draw_line_dsc_t * dsc) +{ + + lv_area_t clip_line; + d2_u32 mode; + d2_s32 result; + lv_area_t buffer_area; + uint32_t res; + lv_value_precise_t p1_x; + lv_value_precise_t p1_y; + lv_value_precise_t p2_x; + lv_value_precise_t p2_y; + int32_t x; + int32_t y; + + clip_line.x1 = LV_MIN(dsc->p1.x, dsc->p2.x) - dsc->width / 2; + clip_line.x2 = LV_MAX(dsc->p1.x, dsc->p2.x) + dsc->width / 2; + clip_line.y1 = LV_MIN(dsc->p1.y, dsc->p2.y) - dsc->width / 2; + clip_line.y2 = LV_MAX(dsc->p1.y, dsc->p2.y) + dsc->width / 2; + + bool is_common; + is_common = _lv_area_intersect(&clip_line, &clip_line, u->base_unit.clip_area); + if(!is_common) return; + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + buffer_area = u->base_unit.target_layer->buf_area; + p1_x = dsc->p1.x - buffer_area.x1; + p1_y = dsc->p1.y - buffer_area.y1; + p2_x = dsc->p2.x - buffer_area.x1; + p2_y = dsc->p2.y - buffer_area.y1; + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + lv_area_move(&clip_line, x, y); + lv_area_move(&buffer_area, x, y); + + bool dashed = dsc->dash_gap && dsc->dash_width; + + if(dashed) { + /* TODO */ + __BKPT(0); + } + +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + // + // Generate render operations + // + d2_framebuffer_from_layer(u->d2_handle, u->base_unit.target_layer); + + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(dsc->color)); + + d2_setalpha(u->d2_handle, dsc->opa); + + d2_cliprect(u->d2_handle, clip_line.x1, clip_line.y1, clip_line.x2, clip_line.y2); + + if((dsc->round_end == 1) || (dsc->round_start == 1)) { + mode = d2_lc_round; + } + else { + mode = d2_lc_butt; // lines end directly at endpoints + } + + d2_setlinecap(u->d2_handle, mode); + + d2_renderline(u->d2_handle, D2_FIX4(p1_x), D2_FIX4(p1_y), D2_FIX4(p2_x), + D2_FIX4(p2_y), D2_FIX4(dsc->width), d2_le_exclude_none); + + // + // Execute render operations + // +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif +} + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_mask_rectangle.c b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_mask_rectangle.c new file mode 100644 index 000000000..928da567d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_mask_rectangle.c @@ -0,0 +1,59 @@ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + +void lv_draw_dave2d_mask_rect(lv_draw_dave2d_unit_t * u, const lv_draw_mask_rect_dsc_t * dsc, const lv_area_t * coords) +{ + lv_area_t clipped_area; + lv_area_t coordinates; + int32_t x; + int32_t y; + + if(!_lv_area_intersect(&clipped_area, coords, u->base_unit.clip_area)) return; + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + coordinates = *coords; + + lv_area_move(&clipped_area, x, y); + lv_area_move(&coordinates, x, y); + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + +#ifdef D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + + d2_framebuffer_from_layer(u->d2_handle, u->base_unit.target_layer); + + d2_cliprect(u->d2_handle, (d2_border)clipped_area.x1, (d2_border)clipped_area.y1, (d2_border)clipped_area.x2, + (d2_border)clipped_area.y2); + + d2_renderbox(u->d2_handle, + (d2_point) D2_FIX4(coordinates.x1), + (d2_point) D2_FIX4(coordinates.y1), + (d2_width) D2_FIX4(lv_area_get_width(&coordinates)), + (d2_width) D2_FIX4(lv_area_get_height(&coordinates))); + + // + // Execute render operations + // +#ifdef D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif +} +#endif //LV_USE_DRAW_DAVE2D diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_triangle.c b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_triangle.c new file mode 100644 index 000000000..ad21b9c2a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_triangle.c @@ -0,0 +1,179 @@ +#include "lv_draw_dave2d.h" +#if LV_USE_DRAW_DAVE2D + +void lv_draw_dave2d_triangle(lv_draw_dave2d_unit_t * u, const lv_draw_triangle_dsc_t * dsc) +{ + lv_area_t clipped_area; + d2_u32 flags = 0; + d2_u8 current_alpha_mode = 0; + int32_t x; + int32_t y; + + lv_area_t tri_area; + tri_area.x1 = LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + tri_area.y1 = LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); + tri_area.x2 = LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + tri_area.y2 = LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); + + if(!_lv_area_intersect(&clipped_area, &tri_area, u->base_unit.clip_area)) return; + +#if LV_USE_OS + lv_result_t status; + status = lv_mutex_lock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } +#endif + + x = 0 - u->base_unit.target_layer->buf_area.x1; + y = 0 - u->base_unit.target_layer->buf_area.y1; + + lv_area_move(&clipped_area, x, y); + +#if D2_RENDER_EACH_OPERATION + d2_selectrenderbuffer(u->d2_handle, u->renderbuffer); +#endif + + lv_point_precise_t p[3]; + p[0] = dsc->p[0]; + p[1] = dsc->p[1]; + p[2] = dsc->p[2]; + + /*Order the points like this: + * [0]: top + * [1]: right bottom + * [2]: left bottom */ + + if(dsc->p[0].y <= dsc->p[1].y && dsc->p[0].y <= dsc->p[2].y) { + p[0] = dsc->p[0]; + if(dsc->p[1].x < dsc->p[2].x) { + p[2] = dsc->p[1]; + p[1] = dsc->p[2]; + } + else { + p[2] = dsc->p[2]; + p[1] = dsc->p[1]; + } + } + else if(dsc->p[1].y <= dsc->p[0].y && dsc->p[1].y <= dsc->p[2].y) { + p[0] = dsc->p[1]; + if(dsc->p[0].x < dsc->p[2].x) { + p[2] = dsc->p[0]; + p[1] = dsc->p[2]; + } + else { + p[2] = dsc->p[2]; + p[1] = dsc->p[0]; + } + } + else { + p[0] = dsc->p[2]; + if(dsc->p[0].x < dsc->p[1].x) { + p[2] = dsc->p[0]; + p[1] = dsc->p[1]; + } + else { + p[2] = dsc->p[1]; + p[1] = dsc->p[0]; + } + } + + p[0].x -= u->base_unit.target_layer->buf_area.x1; + p[1].x -= u->base_unit.target_layer->buf_area.x1; + p[2].x -= u->base_unit.target_layer->buf_area.x1; + + p[0].y -= u->base_unit.target_layer->buf_area.y1; + p[1].y -= u->base_unit.target_layer->buf_area.y1; + p[2].y -= u->base_unit.target_layer->buf_area.y1; + + p[1].y -= 1; + p[2].y -= 1; + + current_alpha_mode = d2_getalphamode(u->d2_handle); + + if(LV_GRAD_DIR_NONE != dsc->bg_grad.dir) { + float a1; + float a2; + + float y1; + float y2; + + float y3; + float y0; + int32_t y0_i ; + int32_t y3_i ; + + if(LV_GRAD_DIR_VER == dsc->bg_grad.dir) { + a1 = dsc->bg_grad.stops[0].opa; + a2 = dsc->bg_grad.stops[dsc->bg_grad.stops_count - 1].opa; + + y1 = LV_MIN3(p[0].y, p[1].y, p[2].y); + y2 = LV_MAX3(p[0].y, p[1].y, p[2].y); + + if(a1 < a2) { + /* TODO */ + __BKPT(0); + y0 = 0.0f;//silence the compiler warning + y3 = 0.0f; + + } + else { + y0 = y2 - ((y2 - y1) / (a2 - a1) * (a2)); //point where alpha is 0 + y3 = y1 + ((y2 - y1) / (a2 - a1) * (255 - a1)); //point where alpha is 255 + } + + y0_i = (int16_t)y0; + y3_i = (int16_t)y3; + + d2_setalphagradient(u->d2_handle, 0, D2_FIX4(0), D2_FIX4(y0_i), D2_FIX4(0), D2_FIX4((y3_i - y0_i))); + } + else if(LV_GRAD_DIR_HOR == dsc->bg_grad.dir) { + /* TODO */ + __BKPT(0); + } + + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(dsc->bg_grad.stops[0].color)); + d2_setalphamode(u->d2_handle, d2_am_gradient1); + } + else { + d2_setalpha(u->d2_handle, dsc->bg_opa); + d2_setalphamode(u->d2_handle, d2_am_constant); + d2_setcolor(u->d2_handle, 0, lv_draw_dave2d_lv_colour_to_d2_colour(dsc->bg_color)); + + } + + d2_framebuffer_from_layer(u->d2_handle, u->base_unit.target_layer); + + d2_cliprect(u->d2_handle, (d2_border)clipped_area.x1, (d2_border)clipped_area.y1, (d2_border)clipped_area.x2, + (d2_border)clipped_area.y2); + + d2_rendertri(u->d2_handle, + (d2_point) D2_FIX4(p[0].x), + (d2_point) D2_FIX4(p[0].y), + (d2_point) D2_FIX4(p[1].x), + (d2_point) D2_FIX4(p[1].y), + (d2_point) D2_FIX4(p[2].x), + (d2_point) D2_FIX4(p[2].y), + flags); + + // + // Execute render operations + // +#if D2_RENDER_EACH_OPERATION + d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0); + d2_flushframe(u->d2_handle); +#endif + + d2_setalphamode(u->d2_handle, current_alpha_mode); + +#if LV_USE_OS + status = lv_mutex_unlock(u->pd2Mutex); + if(LV_RESULT_OK != status) { + __BKPT(0); + } + +#endif + +} + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_utils.c b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_utils.c new file mode 100644 index 000000000..c62a19439 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_utils.c @@ -0,0 +1,140 @@ +/** + * @file lv_draw_dave2d_utils.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_dave2d.h" + +#if LV_USE_DRAW_DAVE2D + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +d2_color lv_draw_dave2d_lv_colour_to_d2_colour(lv_color_t color) +{ + uint8_t alpha, red, green, blue; + + alpha = 0x00; + red = color.red ; + green = color.green ; + blue = color.blue; + /*Color depth: 8 (A8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/ + switch(LV_COLOR_DEPTH) { + case(8): + __BKPT(0); + break; + case(16): + break; + case(24): + break; + case(32): + break; + + default: + break; + } + + return (alpha) << 24UL + | (red) << 16UL + | (green) << 8UL + | (blue) << 0UL; +} + +d2_s32 lv_draw_dave2d_cf_fb_get(void) +{ + d2_s32 d2_fb_mode = 0; + switch(g_display0_cfg.input->format) { + case DISPLAY_IN_FORMAT_16BITS_RGB565: ///< RGB565, 16 bits + d2_fb_mode = d2_mode_rgb565; + break; + case DISPLAY_IN_FORMAT_32BITS_ARGB8888: ///< ARGB8888, 32 bits + d2_fb_mode = d2_mode_argb8888; + break; + case DISPLAY_IN_FORMAT_32BITS_RGB888: ///< RGB888, 32 bits + d2_fb_mode = d2_mode_rgb888; + break; + case DISPLAY_IN_FORMAT_16BITS_ARGB4444: ///< ARGB4444, 16 bits + d2_fb_mode = d2_mode_argb4444; + break; + case DISPLAY_IN_FORMAT_16BITS_ARGB1555: ///< ARGB1555, 16 bits + case DISPLAY_IN_FORMAT_CLUT8 : ///< CLUT8 + case DISPLAY_IN_FORMAT_CLUT4 : ///< CLUT4 + case DISPLAY_IN_FORMAT_CLUT1 : ///< CLUT1 + //Not supported as a FB format by Dave2D + break; + + default: + break; + } + + return d2_fb_mode; +} + +d2_u32 lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(lv_color_format_t colour_format) +{ + d2_u32 d2_lvgl_mode = 0; + + switch(colour_format) { + case(LV_COLOR_FORMAT_A8): + d2_lvgl_mode = d2_mode_alpha8; //? + break; + case(LV_COLOR_FORMAT_RGB565): + d2_lvgl_mode = d2_mode_rgb565; + break; + case(LV_COLOR_FORMAT_RGB888): + d2_lvgl_mode = d2_mode_argb8888; //? + break; + case(LV_COLOR_FORMAT_ARGB8888): + d2_lvgl_mode = d2_mode_argb8888; + break; + + default: + __BKPT(0); + break; + + } + return d2_lvgl_mode; +} + +void d2_framebuffer_from_layer(d2_device * handle, lv_layer_t * layer) +{ + lv_draw_buf_t * draw_buf = layer->draw_buf; + lv_area_t buffer_area = layer->buf_area; + lv_area_move(&buffer_area, -layer->buf_area.x1, -layer->buf_area.y1); + + d2_framebuffer(handle, draw_buf->data, + (d2_s32) draw_buf->header.stride / lv_color_format_get_size(layer->color_format), + (d2_u32)lv_area_get_width(&buffer_area), + (d2_u32)lv_area_get_height(&buffer_area), + lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(layer->color_format)); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_DAVE2D*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_utils.h b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_utils.h new file mode 100644 index 000000000..67c510267 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/renesas/dave2d/lv_draw_dave2d_utils.h @@ -0,0 +1,45 @@ +/** + * @file lv_draw_dave2d_utils.h + * + */ + +#ifndef LV_DRAW_DAVE2D_UTILS_H +#define LV_DRAW_DAVE2D_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +d2_color lv_draw_dave2d_lv_colour_to_d2_colour(lv_color_t color); + +d2_s32 lv_draw_dave2d_cf_fb_get(void); + +d2_u32 lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(lv_color_format_t colour_format); + +void d2_framebuffer_from_layer(d2_device * handle, lv_layer_t * layer); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_DAVE2D_UTILS_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_draw_renesas.mk b/lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_draw_renesas.mk deleted file mode 100644 index b5e3ad100..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_draw_renesas.mk +++ /dev/null @@ -1,7 +0,0 @@ -CSRCS += lv_gpu_d2_ra6m3.c -CSRCS += lv_gpu_d2_draw_label.c - -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/renesas -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/renesas - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/renesas" diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_gpu_d2_draw_label.c b/lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_gpu_d2_draw_label.c deleted file mode 100644 index e92ebf190..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_gpu_d2_draw_label.c +++ /dev/null @@ -1,292 +0,0 @@ -/** - * @file lv_gpu_d2_draw_label.c - * - * @description HAL layer for display driver - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../../draw/lv_draw_label.h" -#include "../../misc/lv_assert.h" -#include "../../core/lv_refr.h" -#include "lv_gpu_d2_ra6m3.h" - -#if LV_USE_GPU_RA6M3_G2D -#include LV_GPU_RA6M3_G2D_INCLUDE - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * GLOBAL VARIABLES - **********************/ -extern const uint8_t _lv_bpp1_opa_table[2]; -extern const uint8_t _lv_bpp2_opa_table[4]; -extern const uint8_t _lv_bpp4_opa_table[16]; -extern const uint8_t _lv_bpp8_opa_table[256]; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void LV_ATTRIBUTE_FAST_MEM draw_letter_normal(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, - const lv_point_t * pos, lv_font_glyph_dsc_t * g, const uint8_t * map_p) -{ - - const uint8_t * bpp_opa_table_p; - uint32_t bitmask_init; - uint32_t bitmask; - uint32_t bpp = g->bpp; - lv_opa_t opa = dsc->opa; - uint32_t shades; - if(bpp == 3) bpp = 4; - -#if LV_USE_IMGFONT - if(bpp == LV_IMGFONT_BPP) { //is imgfont - lv_area_t fill_area; - fill_area.x1 = pos->x; - fill_area.y1 = pos->y; - fill_area.x2 = pos->x + g->box_w - 1; - fill_area.y2 = pos->y + g->box_h - 1; - lv_draw_img_dsc_t img_dsc; - lv_draw_img_dsc_init(&img_dsc); - img_dsc.angle = 0; - img_dsc.zoom = LV_IMG_ZOOM_NONE; - img_dsc.opa = dsc->opa; - img_dsc.blend_mode = dsc->blend_mode; - lv_draw_img(draw_ctx, &img_dsc, &fill_area, map_p); - return; - } -#endif - - switch(bpp) { - case 1: - bpp_opa_table_p = _lv_bpp1_opa_table; - bitmask_init = 0x80; - shades = 2; - break; - case 2: - bpp_opa_table_p = _lv_bpp2_opa_table; - bitmask_init = 0xC0; - shades = 4; - break; - case 4: - bpp_opa_table_p = _lv_bpp4_opa_table; - bitmask_init = 0xF0; - shades = 16; - break; - case 8: - bpp_opa_table_p = _lv_bpp8_opa_table; - bitmask_init = 0xFF; - shades = 256; - break; /*No opa table, pixel value will be used directly*/ - default: - LV_LOG_WARN("lv_draw_letter: invalid bpp"); - return; /*Invalid bpp. Can't render the letter*/ - } - - static lv_opa_t opa_table[256]; - static lv_opa_t prev_opa = LV_OPA_TRANSP; - static uint32_t prev_bpp = 0; - if(opa < LV_OPA_MAX) { - if(prev_opa != opa || prev_bpp != bpp) { - uint32_t i; - for(i = 0; i < shades; i++) { - opa_table[i] = bpp_opa_table_p[i] == LV_OPA_COVER ? opa : ((bpp_opa_table_p[i] * opa) >> 8); - } - } - bpp_opa_table_p = opa_table; - prev_opa = opa; - prev_bpp = bpp; - } - - int32_t col, row; - int32_t box_w = g->box_w; - int32_t box_h = g->box_h; - int32_t width_bit = box_w * bpp; /*Letter width in bits*/ - - /*Calculate the col/row start/end on the map*/ - int32_t col_start = pos->x >= draw_ctx->clip_area->x1 ? 0 : draw_ctx->clip_area->x1 - pos->x; - int32_t col_end = pos->x + box_w <= draw_ctx->clip_area->x2 ? box_w : draw_ctx->clip_area->x2 - pos->x + 1; - int32_t row_start = pos->y >= draw_ctx->clip_area->y1 ? 0 : draw_ctx->clip_area->y1 - pos->y; - int32_t row_end = pos->y + box_h <= draw_ctx->clip_area->y2 ? box_h : draw_ctx->clip_area->y2 - pos->y + 1; - - /*Move on the map too*/ - uint32_t bit_ofs = (row_start * width_bit) + (col_start * bpp); - map_p += bit_ofs >> 3; - - uint8_t letter_px; - uint32_t col_bit; - col_bit = bit_ofs & 0x7; /*"& 0x7" equals to "% 8" just faster*/ - - lv_draw_sw_blend_dsc_t blend_dsc; - lv_memset_00(&blend_dsc, sizeof(blend_dsc)); - blend_dsc.color = dsc->color; - blend_dsc.opa = LV_OPA_COVER; - blend_dsc.blend_mode = dsc->blend_mode; - - lv_coord_t hor_res = lv_disp_get_hor_res(_lv_refr_get_disp_refreshing()); - uint32_t mask_buf_size = box_w * box_h > hor_res ? hor_res : box_w * box_h; - lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); - blend_dsc.mask_buf = mask_buf; - int32_t mask_p = 0; - - lv_area_t fill_area; - fill_area.x1 = col_start + pos->x; - fill_area.x2 = col_end + pos->x - 1; - fill_area.y1 = row_start + pos->y; - fill_area.y2 = fill_area.y1; -#if LV_DRAW_COMPLEX - lv_coord_t fill_w = lv_area_get_width(&fill_area); - lv_area_t mask_area; - lv_area_copy(&mask_area, &fill_area); - mask_area.y2 = mask_area.y1 + row_end; - bool mask_any = lv_draw_mask_is_any(&mask_area); -#endif - blend_dsc.blend_area = &fill_area; - blend_dsc.mask_area = &fill_area; - - uint32_t col_bit_max = 8 - bpp; - uint32_t col_bit_row_ofs = (box_w + col_start - col_end) * bpp; - - for(row = row_start ; row < row_end; row++) { -#if LV_DRAW_COMPLEX - int32_t mask_p_start = mask_p; -#endif - bitmask = bitmask_init >> col_bit; - for(col = col_start; col < col_end; col++) { - /*Load the pixel's opacity into the mask*/ - letter_px = (*map_p & bitmask) >> (col_bit_max - col_bit); - if(letter_px) { - mask_buf[mask_p] = bpp_opa_table_p[letter_px]; - } - else { - mask_buf[mask_p] = 0; - } - - /*Go to the next column*/ - if(col_bit < col_bit_max) { - col_bit += bpp; - bitmask = bitmask >> bpp; - } - else { - col_bit = 0; - bitmask = bitmask_init; - map_p++; - } - - /*Next mask byte*/ - mask_p++; - } - -#if LV_DRAW_COMPLEX - /*Apply masks if any*/ - if(mask_any) { - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, fill_area.x1, fill_area.y2, - fill_w); - if(blend_dsc.mask_res == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(mask_buf + mask_p_start, fill_w); - } - } -#endif - - if((uint32_t) mask_p + (col_end - col_start) < mask_buf_size) { - fill_area.y2 ++; - } - else { - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - lv_draw_ra6m3_2d_blend(draw_ctx, &blend_dsc); - - fill_area.y1 = fill_area.y2 + 1; - fill_area.y2 = fill_area.y1; - mask_p = 0; - } - - col_bit += col_bit_row_ofs; - map_p += (col_bit >> 3); - col_bit = col_bit & 0x7; - } - - /*Flush the last part*/ - if(fill_area.y1 != fill_area.y2) { - fill_area.y2--; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - lv_draw_ra6m3_2d_blend(draw_ctx, &blend_dsc); - mask_p = 0; - } - - lv_mem_buf_release(mask_buf); -} - -void lv_draw_gpu_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p, - uint32_t letter) -{ - const lv_font_t * font_p = dsc->font; - - lv_opa_t opa = dsc->opa; - if(opa < LV_OPA_MIN) return; - if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; - - if(font_p == NULL) { - LV_LOG_WARN("lv_draw_letter: font is NULL"); - return; - } - - lv_font_glyph_dsc_t g; - bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0'); - if(g_ret == false) { - /*Add warning if the dsc is not found - *but do not print warning for non printable ASCII chars (e.g. '\n')*/ - if(letter >= 0x20 && - letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/ - letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/ - LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%X", letter); - } - return; - } - - /*Don't draw anything if the character is empty. E.g. space*/ - if((g.box_h == 0) || (g.box_w == 0)) return; - - lv_point_t gpos; - gpos.x = pos_p->x + g.ofs_x; - gpos.y = pos_p->y + (dsc->font->line_height - dsc->font->base_line) - g.box_h - g.ofs_y; - - /*If the letter is completely out of mask don't draw it*/ - if(gpos.x + g.box_w < draw_ctx->clip_area->x1 || - gpos.x > draw_ctx->clip_area->x2 || - gpos.y + g.box_h < draw_ctx->clip_area->y1 || - gpos.y > draw_ctx->clip_area->y2) { - return; - } - - const uint8_t * map_p = lv_font_get_glyph_bitmap(font_p, letter); - if(map_p == NULL) { - LV_LOG_WARN("lv_draw_letter: character's bitmap not found"); - return; - } - - if(font_p->subpx) { -#if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX - draw_letter_subpx(pos_x, pos_y, &g, clip_area, map_p, color, opa, blend_mode); -#else - LV_LOG_WARN("Can't draw sub-pixel rendered letter because LV_USE_FONT_SUBPX == 0 in lv_conf.h"); -#endif - } - else { - draw_letter_normal(draw_ctx, dsc, &gpos, &g, map_p); - } -} - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_gpu_d2_ra6m3.c b/lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_gpu_d2_ra6m3.c deleted file mode 100644 index ba4c08425..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_gpu_d2_ra6m3.c +++ /dev/null @@ -1,742 +0,0 @@ -/** - * @file lv_gpu_d2_ra6m3.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_gpu_d2_ra6m3.h" -#include "../../core/lv_refr.h" -#include - -#if LV_USE_GPU_RA6M3_G2D - -#include LV_GPU_RA6M3_G2D_INCLUDE - -/********************* - * DEFINES - *********************/ -#define LOG_ERRORS -#ifdef LOG_ERRORS - #define STRINGIFY(x) #x - #define TOSTRING(x) STRINGIFY(x) - - #define ERROR_LIST_SIZE (4) - #define D2_EXEC(a) lv_port_gpu_log_error(a, __func__, __LINE__) -#else - /* here is error logging not enabled */ - #define D2_EXEC(a) a; -#endif - -/********************** - * TYPEDEFS - **********************/ -typedef struct { - d2_s32 error; - const char * func; - int line; -} log_error_entry; - -/********************** - * STATIC PROTOTYPES - **********************/ -#ifdef LOG_ERRORS - static void lv_port_gpu_log_error(d2_s32 status, const char * func, int line); -#endif -static void invalidate_cache(void); - -void lv_draw_gpu_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p, - uint32_t letter); - -/********************** - * STATIC VARIABLES - **********************/ -#ifdef LOG_ERRORS - static log_error_entry log_error_list[ERROR_LIST_SIZE]; - static int error_list_index; - static int error_count; -#endif - -static d2_device * _d2_handle; -static d2_renderbuffer * renderbuffer; - -static d2_s32 src_cf_val, dst_cf_val; -static lv_draw_img_dsc_t img_dsc; -static bool color_key_enabled, alpha_enabled, blend_enabled, colorize_enabled; - -/********************** - * STATIC FUNCTIONS - **********************/ -static d2_s32 lv_port_gpu_cf_lv_to_d2(lv_img_cf_t cf) -{ - d2_s32 d2_cf; - -#if (DLG_LVGL_CF == 1) - switch(cf & ~(1 << 5)) { -#else - switch(cf) { -#endif /* (DLG_LVGL_CF == 1) */ - case LV_IMG_CF_TRUE_COLOR: - d2_cf = d2_mode_rgb565; - break; - case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED: - d2_cf = d2_mode_rgb565; - break; - case LV_IMG_CF_ALPHA_1BIT: - d2_cf = d2_mode_alpha1; - break; - case LV_IMG_CF_ALPHA_2BIT: - d2_cf = d2_mode_alpha2; - break; - case LV_IMG_CF_ALPHA_4BIT: - d2_cf = d2_mode_alpha4; - break; - case LV_IMG_CF_ALPHA_8BIT: - d2_cf = d2_mode_alpha8; - break; - case LV_IMG_CF_INDEXED_1BIT: - d2_cf = d2_mode_i1 | d2_mode_clut; - break; - case LV_IMG_CF_INDEXED_2BIT: - d2_cf = d2_mode_i2 | d2_mode_clut; - break; - case LV_IMG_CF_INDEXED_4BIT: - d2_cf = d2_mode_i4 | d2_mode_clut; - break; - case LV_IMG_CF_INDEXED_8BIT: - d2_cf = d2_mode_i8 | d2_mode_clut; - break; -#if (DLG_LVGL_CF == 1) - case LV_IMG_CF_RGB565: - d2_cf = d2_mode_rgb565; - break; - case LV_IMG_CF_RGB888: - d2_cf = d2_mode_rgb888; - break; - case LV_IMG_CF_RGBA8888: - d2_cf = d2_mode_rgba8888; - break; -#endif /* DLG_LVGL_CF */ - default: - return -1; - } - -#if (DLG_LVGL_CF == 1) - return d2_cf | (cf & (1 << 5) ? d2_mode_rle : 0); -#else - return d2_cf; -#endif /* (DLG_LVGL_CF == 1) */ -} - -static bool lv_port_gpu_cf_fb_valid(d2_s32 cf) -{ - if((cf & (d2_mode_rle | d2_mode_clut)) || cf < 0) { - return false; - } - - switch(cf) { - case d2_mode_alpha8: - case d2_mode_rgb565: - case d2_mode_argb8888: - case d2_mode_argb4444: - case d2_mode_rgba8888: - case d2_mode_rgba4444: - return true; - default: - return false; - } -} - -static bool lv_port_gpu_cf_has_alpha(d2_s32 cf) -{ - switch(cf & ~(d2_mode_clut | d2_mode_rle)) { - case d2_mode_argb8888: - case d2_mode_rgba8888: - case d2_mode_argb4444: - case d2_mode_rgba4444: - case d2_mode_argb1555: - case d2_mode_rgba5551: - case d2_mode_ai44: - case d2_mode_i8: - case d2_mode_i4: - case d2_mode_i2: - case d2_mode_i1: - case d2_mode_alpha8: - case d2_mode_alpha4: - case d2_mode_alpha2: - case d2_mode_alpha1: - return true; - default: - return false; - } -} - -static bool lv_port_gpu_cf_is_alpha(d2_s32 cf) -{ - switch(cf & ~d2_mode_rle) { - case d2_mode_alpha8: - case d2_mode_alpha4: - case d2_mode_alpha2: - case d2_mode_alpha1: - return true; - default: - return false; - } -} - -static d2_color lv_port_gpu_color_lv_to_d2(lv_color_t color) -{ - uint8_t alpha, red, green, blue; - - alpha = 0xFF; - red = color.ch.red << 3 | color.ch.red >> 2; - green = color.ch.green << 2 | color.ch.green >> 4; - blue = color.ch.blue << 3 | color.ch.blue >> 2; - - return (alpha) << 24UL - | (red) << 16UL - | (green) << 8UL - | (blue) << 0UL; -} - -static void lv_port_gpu_get_recolor_consts(d2_color * cl, d2_color * ch) -{ - d2_color c = lv_port_gpu_color_lv_to_d2(img_dsc.recolor); - d2_alpha r, g, b, opa = img_dsc.recolor_opa > LV_OPA_MAX ? LV_OPA_COVER : img_dsc.recolor_opa; - - r = ((uint32_t)((uint8_t)(c >> 16UL)) * opa) / 255; - g = ((uint32_t)((uint8_t)(c >> 8UL)) * opa) / 255; - b = ((uint32_t)((uint8_t)(c >> 0UL)) * opa) / 255; - *cl = r << 16UL | g << 8UL | b << 0UL; - - r += 255 - opa; - g += 255 - opa; - b += 255 - opa; - *ch = r << 16UL | g << 8UL | b << 0UL; -} - -static int lv_port_gpu_handle_indexed_color(const lv_color_t ** src, const d2_color ** clut, d2_s32 cf) -{ - int clut_len = 0; - - if(cf & d2_mode_clut) { - /* Calculate CLUT length in entries */ - switch(cf & ~(d2_mode_clut | d2_mode_rle)) { - case d2_mode_i1: - clut_len = 2; - break; - case d2_mode_i2: - clut_len = 4; - break; - case d2_mode_i4: - clut_len = 16; - break; - case d2_mode_i8: - clut_len = 256; - break; - case d2_mode_ai44: - clut_len = 16; - break; - default: - return 0; - } - - *clut = (const d2_color *)*src; - *src = (const lv_color_t *)((const uint32_t *)*src + clut_len); - } - return clut_len; -} - -static int lv_port_gpu_cf_bpp(d2_s32 cf) -{ - switch(cf & ~(d2_mode_clut | d2_mode_rle)) { - case d2_mode_argb8888: - return 32; - case d2_mode_rgba8888: - return 32; - case d2_mode_rgb888: - return 32; - case d2_mode_argb4444: - return 16; - case d2_mode_rgba4444: - return 16; - case d2_mode_argb1555: - return 16; - case d2_mode_rgba5551: - return 16; - case d2_mode_rgb565: - return 16; - case d2_mode_ai44: - return 8; - case d2_mode_i8: - return 8; - case d2_mode_i4: - return 4; - case d2_mode_i2: - return 2; - case d2_mode_i1: - return 1; - case d2_mode_alpha8: - return 8; - case d2_mode_alpha4: - return 4; - case d2_mode_alpha2: - return 2; - case d2_mode_alpha1: - return 1; - default: - return 0; - } -} - -static d2_s32 lv_port_gpu_cf_get_default(void) -{ - return d2_mode_rgb565; -} - -static void lv_port_gpu_config_blit_clear(void) -{ - alpha_enabled = false; - color_key_enabled = false; - blend_enabled = true; - colorize_enabled = false; - - lv_draw_img_dsc_init(&img_dsc); - - src_cf_val = lv_port_gpu_cf_get_default(); - dst_cf_val = lv_port_gpu_cf_get_default(); -} - -void lv_port_gpu_init(void) -{ - lv_port_gpu_config_blit_clear(); -} - -static void lv_port_gpu_rotate_point(int * x, int * y, float cos_angle, float sin_angle, int pivot_x, int pivot_y) -{ - float fx, fy; - - *x -= pivot_x; - *y -= pivot_y; - - fx = ((float) * x) / 16.0f; - fy = ((float) * y) / 16.0f; - - *x = (int)(((fx * cos_angle) - (fy * sin_angle)) * 16.0f); - *y = (int)(((fx * sin_angle) + (fy * cos_angle)) * 16.0f); - - *x += pivot_x; - *y += pivot_y; -} - -void lv_draw_ra6m3_g2d_init(void) -{ - if(_d2_handle != NULL) { - return; - } - - _d2_handle = d2_opendevice(0); - - if(_d2_handle == NULL) - return; - - /* set blocksize for default displaylist */ - if(d2_setdlistblocksize(_d2_handle, 25) != D2_OK) { - LV_LOG_ERROR("Could NOT d2_setdlistblocksize\n"); - d2_closedevice(_d2_handle); - - return; - } - - /* bind the hardware */ - if(d2_inithw(_d2_handle, 0) != D2_OK) { - LV_LOG_ERROR("Could NOT d2_inithw\n"); - d2_closedevice(_d2_handle); - - return; - } - - renderbuffer = d2_newrenderbuffer(_d2_handle, 20, 20); - if(!renderbuffer) { - LV_LOG_ERROR("NO renderbuffer\n"); - d2_closedevice(_d2_handle); - - return; - } -} - -static void lv_port_gpu_hw_deinit(void) -{ - if(_d2_handle == NULL) - return; - - D2_EXEC(d2_freerenderbuffer(_d2_handle, renderbuffer)); - D2_EXEC(d2_closedevice(_d2_handle)); - - renderbuffer = NULL; - _d2_handle = NULL; -} - -void lv_port_gpu_flush(void) -{ - lv_port_gpu_hw_deinit(); -} - -static void lv_port_gpu_start_render(void) -{ - D2_EXEC(d2_selectrenderbuffer(_d2_handle, renderbuffer)); -} - -static void lv_port_gpu_complete_render(void) -{ - D2_EXEC(d2_flushframe(_d2_handle)); -} - -void lv_port_gpu_wait(lv_draw_ctx_t * draw_ctx) -{ - lv_port_gpu_complete_render(); - - lv_draw_sw_wait_for_finish(draw_ctx); -} - -static void lv_port_gpu_execute_render(void) -{ - if(_d2_handle) { - D2_EXEC(d2_executerenderbuffer(_d2_handle, renderbuffer, 0)); - } -} - -void lv_port_gpu_blit(int32_t x, int32_t y, lv_color_t * dst, const lv_area_t * fill_area) -{ - uint32_t ModeSrc; - - ModeSrc = d2_mode_rgb565; - - lv_coord_t dst_width, dst_hight; - dst_width = lv_area_get_width(fill_area); - dst_hight = lv_area_get_height(fill_area); - - d2_selectrenderbuffer(_d2_handle, renderbuffer); - - // Generate render operations - d2_framebuffer(_d2_handle, (uint16_t *)&fb_background[0], LV_HOR_RES_MAX, LV_HOR_RES_MAX, - MAX(fill_area->y2 + 1, 2), lv_port_gpu_cf_get_default()); - - d2_cliprect(_d2_handle, 0, 0, LV_HOR_RES_MAX - 1, fill_area->y2); - d2_setblitsrc(_d2_handle, (void *) dst, dst_width, dst_width, dst_hight, ModeSrc); - d2_blitcopy(_d2_handle, dst_width, dst_hight, 0, 0, D2_FIX4(dst_width), D2_FIX4(dst_hight), - D2_FIX4(fill_area->x1), D2_FIX4(fill_area->y1), 0); - - // Execute render operations - d2_executerenderbuffer(_d2_handle, renderbuffer, 0); -} - -void lv_port_gpu_fill(lv_color_t * dest_buf, const lv_area_t * fill_area, lv_coord_t dst_width, - lv_color_t color, lv_opa_t opa) -{ - invalidate_cache(); - - lv_port_gpu_start_render(); - - D2_EXEC(d2_framebuffer(_d2_handle, d1_maptovidmem(_d2_handle, dest_buf), MAX(dst_width, 2), MAX(dst_width, 2), - MAX(fill_area->y2 + 1, 2), lv_port_gpu_cf_get_default())); - - D2_EXEC(d2_cliprect(_d2_handle, 0, 0, dst_width - 1, fill_area->y2)); - D2_EXEC(d2_setalpha(_d2_handle, opa > LV_OPA_MAX ? 0xFF : opa)); - D2_EXEC(d2_setcolor(_d2_handle, 0, lv_port_gpu_color_lv_to_d2(color))); - D2_EXEC(d2_renderbox(_d2_handle, D2_FIX4(fill_area->x1), D2_FIX4(fill_area->y1), - D2_FIX4(lv_area_get_width(fill_area)), D2_FIX4(lv_area_get_height(fill_area)))); - - lv_port_gpu_execute_render(); -} - -bool lv_port_gpu_config_blit(const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t dst_cf, - lv_img_cf_t src_cf, bool alpha_en, bool color_key_en, bool blend_en, bool colorize_en) -{ - d2_s32 d2_src_cf, d2_dst_cf; - - if(blend_en && draw_dsc->blend_mode != LV_BLEND_MODE_NORMAL - && draw_dsc->blend_mode != LV_BLEND_MODE_ADDITIVE) { - return false; - } - - d2_src_cf = lv_port_gpu_cf_lv_to_d2(src_cf); - d2_dst_cf = lv_port_gpu_cf_lv_to_d2(dst_cf); - if(d2_src_cf < 0 || !lv_port_gpu_cf_fb_valid(d2_dst_cf)) { - return false; - } - src_cf_val = d2_src_cf; - dst_cf_val = d2_dst_cf; - - img_dsc = *draw_dsc; - - /* Disable alpha if alpha channel does not exist */ - alpha_enabled = lv_port_gpu_cf_has_alpha(src_cf_val) ? alpha_en : 0; - color_key_enabled = color_key_en; - blend_enabled = blend_en; - colorize_enabled = colorize_en | lv_port_gpu_cf_is_alpha(src_cf_val); - - return true; -} - -static void lv_port_gpu_blit_internal(const lv_area_t * dest_area, const lv_color_t * src_buf, - const lv_area_t * src_area, d2_u32 flags) -{ - const lv_area_t * img_area = src_area; - lv_area_t img_area_scaled; - lv_coord_t w, h, img_w, img_h; - d2_s32 pitch; - int bpp = lv_port_gpu_cf_bpp(src_cf_val); - - D2_EXEC(d2_cliprect(_d2_handle, dest_area->x1, dest_area->y1, dest_area->x2, dest_area->y2)); - - pitch = w = lv_area_get_width(src_area); - h = lv_area_get_height(src_area); - - if(img_dsc.zoom != LV_IMG_ZOOM_NONE) { - img_area_scaled.x1 = src_area->x1 + ((((int32_t)0 - img_dsc.pivot.x) * img_dsc.zoom) >> 8) + img_dsc.pivot.x; - img_area_scaled.x2 = src_area->x1 + ((((int32_t)w - img_dsc.pivot.x) * img_dsc.zoom) >> 8) + img_dsc.pivot.x; - img_area_scaled.y1 = src_area->y1 + ((((int32_t)0 - img_dsc.pivot.y) * img_dsc.zoom) >> 8) + img_dsc.pivot.y; - img_area_scaled.y2 = src_area->y1 + ((((int32_t)h - img_dsc.pivot.y) * img_dsc.zoom) >> 8) + img_dsc.pivot.y; - img_area = &img_area_scaled; - } - - img_w = lv_area_get_width(img_area); - img_h = lv_area_get_height(img_area); - - if(0 < bpp && bpp < 8) { - pitch = (w + (8 - bpp)) & (~(8 - bpp)); - } - - if(img_dsc.angle == 0) { - D2_EXEC(d2_setblitsrc(_d2_handle, (void *) src_buf, pitch, w, h, src_cf_val)); - - D2_EXEC(d2_blitcopy(_d2_handle, w, h, 0, 0, - D2_FIX4(img_w), D2_FIX4(img_h), D2_FIX4(img_area->x1), D2_FIX4(img_area->y1), flags)); - } - else { - int x, y, x1, y1, x2, y2, x3, y3, x4, y4, dxu, dxv, dyu, dyv, xx, xy, yx, yy; - int pivot_scaled_x, pivot_scaled_y; - int tex_offset = (flags & d2_bf_filter) ? -32767 : 0; - d2_u8 amode, cmode = d2_to_copy; - float angle = ((float)img_dsc.angle / 10) * M_PI / 180; - float cos_angle = cosf(angle); - float sin_angle = sinf(angle); - d2_u8 fillmode_backup; - - /* setup texture params */ - fillmode_backup = d2_getfillmode(_d2_handle); - D2_EXEC(d2_setfillmode(_d2_handle, d2_fm_texture)); - D2_EXEC(d2_settexture(_d2_handle, (void *) src_buf, pitch, w, h, src_cf_val)); - D2_EXEC(d2_settexturemode(_d2_handle, flags & (d2_bf_filter | d2_bf_wrap))); - amode = flags & d2_bf_usealpha ? d2_to_copy : d2_to_one; - cmode = flags & d2_bf_colorize2 ? d2_to_blend : d2_to_copy; - D2_EXEC(d2_settextureoperation(_d2_handle, amode, cmode, cmode, cmode)); - if(flags & d2_bf_colorize2) { - d2_color cl = d2_getcolor(_d2_handle, 0), ch = d2_getcolor(_d2_handle, 1); - D2_EXEC(d2_settexopparam(_d2_handle, d2_cc_red, (uint8_t)(cl >> 16UL), - (uint8_t)(ch >> 16UL))); - D2_EXEC(d2_settexopparam(_d2_handle, d2_cc_green, (uint8_t)(cl >> 8UL), - (uint8_t)(ch >> 8UL))); - D2_EXEC(d2_settexopparam(_d2_handle, d2_cc_blue, (uint8_t)(cl >> 0UL), - (uint8_t)(ch >> 0UL))); - } - - x = D2_FIX4(img_area->x1); - y = D2_FIX4(img_area->y1); - - /* define quad points */ - x1 = D2_FIX4(0); - y1 = D2_FIX4(0); - x2 = D2_FIX4(img_w); - y2 = D2_FIX4(0); - x3 = D2_FIX4(img_w); - y3 = D2_FIX4(img_h); - x4 = D2_FIX4(0); - y4 = D2_FIX4(img_h); - - /* rotate points for quad */ - pivot_scaled_x = (img_dsc.pivot.x * img_dsc.zoom) >> 4; - pivot_scaled_y = (img_dsc.pivot.y * img_dsc.zoom) >> 4; - - lv_port_gpu_rotate_point(&x1, &y1, cos_angle, sin_angle, pivot_scaled_x, pivot_scaled_y); - lv_port_gpu_rotate_point(&x2, &y2, cos_angle, sin_angle, pivot_scaled_x, pivot_scaled_y); - lv_port_gpu_rotate_point(&x3, &y3, cos_angle, sin_angle, pivot_scaled_x, pivot_scaled_y); - lv_port_gpu_rotate_point(&x4, &y4, cos_angle, sin_angle, pivot_scaled_x, pivot_scaled_y); - - /* compute texture increments */ - xx = (int)(cos_angle * 65536.0f); - xy = (int)(sin_angle * 65536.0f); - yx = (int)(-sin_angle * 65536.0f); - yy = (int)(cos_angle * 65536.0f); - dxu = ((D2_FIX16(w) / D2_FIX4(img_w)) * xx) >> 12; - dxv = ((D2_FIX16(w) / D2_FIX4(img_w)) * xy) >> 12; - dyu = ((D2_FIX16(h) / D2_FIX4(img_h)) * yx) >> 12; - dyv = ((D2_FIX16(h) / D2_FIX4(img_h)) * yy) >> 12; - - /* map texture exactly to rotated quad, so texel center is always (0/0) top-left */ - D2_EXEC(d2_settexelcenter(_d2_handle, 0, 0)); - D2_EXEC(d2_settexturemapping(_d2_handle, (d2_point)(x + x1), (d2_point)(y + y1), - tex_offset, tex_offset, dxu, dxv, dyu, dyv)); - - int minx = MAX(dest_area->x1, D2_INT4(x + MIN(x1, MIN(x2, MIN(x3, x4))))); - int maxx = MIN(dest_area->x2, D2_INT4(x + MAX(x1, MAX(x2, MAX(x3, x4))))); - int slice = (flags & d2_bf_filter) ? 6 : 8; - - /* Perform render operation in slices to acheive better performance */ - for(int posx = minx; posx < maxx; posx += slice) { - D2_EXEC(d2_cliprect(_d2_handle, posx, dest_area->y1, MIN(posx + slice - 1, maxx), dest_area->y2)); - D2_EXEC(d2_renderquad(_d2_handle, (d2_point)(x + x1), (d2_point)(y + y1), - (d2_point)(x + x2), (d2_point)(y + y2), - (d2_point)(x + x3), (d2_point)(y + y3), - (d2_point)(x + x4), (d2_point)(y + y4), 0)); - } - D2_EXEC(d2_setfillmode(_d2_handle, fillmode_backup)); - } -} - -void lv_port_ra_gpu_blit(lv_color_t * dst, const lv_area_t * dst_area, lv_coord_t dest_stride, - const lv_color_t * src, const lv_area_t * src_area, lv_opa_t opa) -{ - d2_u32 flags = 0; - const d2_color * clut = NULL; - int clut_len = 0; - - invalidate_cache(); - - clut_len = lv_port_gpu_handle_indexed_color(&src, &clut, src_cf_val); - - lv_port_gpu_start_render(); - - D2_EXEC(d2_framebuffer(_d2_handle, d1_maptovidmem(_d2_handle, dst), MAX(dest_stride, 2), - MAX(dst_area->x2 + 1, 2), MAX(dst_area->y2 + 1, 2), dst_cf_val)); - - flags |= alpha_enabled ? d2_bf_usealpha : 0; - - D2_EXEC(d2_setalpha(_d2_handle, opa > LV_OPA_MAX ? LV_OPA_COVER : opa)); - - if(clut) { - D2_EXEC(d2_writetexclut_direct(_d2_handle, clut, 0, clut_len)); - } - - flags |= color_key_enabled ? d2_bf_usealpha : 0; - flags |= (colorize_enabled || img_dsc.recolor_opa != LV_OPA_TRANSP) ? d2_bf_colorize2 : 0; - if(colorize_enabled) { - D2_EXEC(d2_setcolor(_d2_handle, 0, lv_port_gpu_color_lv_to_d2(img_dsc.recolor))); - D2_EXEC(d2_setcolor(_d2_handle, 1, lv_port_gpu_color_lv_to_d2(img_dsc.recolor))); - } - else if(img_dsc.recolor_opa != LV_OPA_TRANSP) { - d2_color cl = 0, ch = 0; - lv_port_gpu_get_recolor_consts(&cl, &ch); - D2_EXEC(d2_setcolor(_d2_handle, 0, cl)); - D2_EXEC(d2_setcolor(_d2_handle, 1, ch)); - } - - flags |= ((img_dsc.angle || img_dsc.zoom != LV_IMG_ZOOM_NONE) && img_dsc.antialias) ? d2_bf_filter : 0; - - if(blend_enabled) { - D2_EXEC(d2_setblendmode(_d2_handle, d2_bm_alpha, - img_dsc.blend_mode != LV_BLEND_MODE_NORMAL ? d2_bm_one : d2_bm_one_minus_alpha)); - D2_EXEC(d2_setalphablendmode(_d2_handle, d2_bm_one, d2_bm_one_minus_alpha)); - } - else { - D2_EXEC(d2_setblendmode(_d2_handle, d2_bm_one, d2_bm_zero)); - D2_EXEC(d2_setalphablendmode(_d2_handle, d2_bm_one, d2_bm_zero)); - } - - lv_port_gpu_blit_internal(dst_area, src, src_area, flags); - - lv_port_gpu_execute_render(); -} - -void lv_draw_ra6m3_2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc) -{ - lv_area_t blend_area; - if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return; - - bool done = false; - - if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL && lv_area_get_size(&blend_area) > 100) { - lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); - - lv_color_t * dest_buf = draw_ctx->buf; - - const lv_color_t * src_buf = dsc->src_buf; - if(src_buf) { - lv_draw_sw_blend_basic(draw_ctx, dsc); - - lv_area_t src_area; - src_area.x1 = blend_area.x1 - (dsc->blend_area->x1 - draw_ctx->buf_area->x1); - src_area.y1 = blend_area.y1 - (dsc->blend_area->y1 - draw_ctx->buf_area->y1); - src_area.x2 = src_area.x1 + lv_area_get_width(dsc->blend_area) - 1; - src_area.y2 = src_area.y1 + lv_area_get_height(dsc->blend_area) - 1; - - lv_port_ra_gpu_blit(dest_buf, &blend_area, dest_stride, src_buf, &src_area, dsc->opa); - done = true; - } - else if(dsc->opa >= LV_OPA_MAX) { - lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - lv_port_gpu_fill(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa); - done = true; - } - } - - if(!done) lv_draw_sw_blend_basic(draw_ctx, dsc); -} - -static void lv_port_gpu_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, - const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format) -{ - /*TODO basic ARGB8888 image can be handles here*/ - - lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, color_format); -} - -void lv_draw_ra6m3_2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) -{ - lv_draw_sw_init_ctx(drv, draw_ctx); - - lv_draw_ra6m3_dma2d_ctx_t * ra_2d_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx; - - ra_2d_draw_ctx->blend = lv_draw_ra6m3_2d_blend; - ra_2d_draw_ctx->base_draw.draw_img_decoded = lv_port_gpu_img_decoded; - ra_2d_draw_ctx->base_draw.wait_for_finish = lv_port_gpu_wait; - ra_2d_draw_ctx->base_draw.draw_letter = lv_draw_gpu_letter; - //ra_2d_draw_ctx->base_draw.buffer_copy = lv_draw_ra6m3_2d_buffer_copy; -} - -void lv_draw_stm32_dma2d_ctx_deinit(lv_disp_t * disp, lv_draw_ctx_t * draw_ctx) -{ - LV_UNUSED(disp); - LV_UNUSED(draw_ctx); -} - -static void invalidate_cache(void) -{ - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - if(disp->driver->clean_dcache_cb) disp->driver->clean_dcache_cb(disp->driver); -} - -#ifdef LOG_ERRORS -static void lv_port_gpu_log_error(d2_s32 status, const char * func, int line) -{ - if(status) { - log_error_list[error_list_index].error = status; - log_error_list[error_list_index].func = func; - log_error_list[error_list_index].line = line; - LV_LOG_ERROR("%s\r\n", d2_geterrorstring(_d2_handle)); - LV_LOG_ERROR("%d:\t%d - %s : %d\r\n", error_count, - log_error_list[error_list_index].error, - log_error_list[error_list_index].func, - log_error_list[error_list_index].line); - - error_count++; - error_list_index++; - if(error_list_index >= ERROR_LIST_SIZE) { - error_list_index = 0; - } - } -} -#endif -#endif /* LV_USE_GPU_RA6M3_G2D */ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_gpu_d2_ra6m3.h b/lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_gpu_d2_ra6m3.h deleted file mode 100644 index 5d37ce45e..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/renesas/lv_gpu_d2_ra6m3.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @file lv_gpu_d2_ra6m3.h - * - */ -#ifndef LV_GPU_D2_RA6M3_H -#define LV_GPU_D2_RA6M3_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../misc/lv_color.h" - -#if LV_USE_GPU_RA6M3_G2D -#include "../../core/lv_disp.h" -#include "../sw/lv_draw_sw.h" - -/********************** - * DEFINE - **********************/ -#define MIN(A, B) ((A) < (B) ? (A) : (B)) -#define MAX(A, B) ((A) > (B) ? (A) : (B)) -#define M_PI 3.1415926 - -/********************** - * TYPEDEFS - **********************/ -typedef lv_draw_sw_ctx_t lv_draw_ra6m3_dma2d_ctx_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ -void lv_draw_ra6m3_g2d_init(void); - -void lv_port_gpu_init(void); - -void lv_port_gpu_flush(void); - -void lv_port_gpu_blit(int32_t x, int32_t y, lv_color_t * dst, const lv_area_t * fill_area); - -void lv_draw_ra6m3_2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); - -void lv_draw_ra6m3_2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); - -void lv_draw_ra6m3_2d_ctx_deinit(lv_disp_drv_t * disp, lv_draw_ctx_t * draw_ctx); - -#endif /*LV_USE_GPU_GD32_IPA*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/README.md b/lib/libesp32_lvgl/lvgl/src/draw/sdl/README.md deleted file mode 100644 index 4415ffac8..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# SDL_Renderer Based Drawing Functions - -In LVGL, drawing was performed by CPU. To improve drawing performance on platforms with GPU, -we should perform drawing operations on GPU if possible. - -This implementation has moved most bitmap blending and drawing procedures to utilize SDL_Renderer, -which takes advantages of hardware acceleration APIs like DirectX or OpenGL. - -This implementation can be also considered as a reference implementation, for contributors wants to -develop accelerated drawing functions with other APIs such as OpenGL/OpenGL ES. - -## Caveats -`lv_draw_arc`, `lv_draw_line` is not enabled, due to incomplete implementation. So lines and arcs will -have significant impact to drawing performances. - -Performance of this implementation still has room to improve. Or we should use more powerful APIs -such as OpenGL. - -## Notices for files - -### `lv_draw_sdl_stack_blur.c` - -Contains modified code from [android-stackblur](https://github.com/kikoso/android-stackblur) project. -Apache License 2.0 - -### `lv_draw_sdl_lru.c`/`lv_draw_sdl_lru.h` - -Contains modified code from [C-LRU-Cache](https://github.com/willcannings/C-LRU-Cache) project. No license defined. \ No newline at end of file diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.c index e3cdf577a..7ce1935df 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.c @@ -6,50 +6,51 @@ /********************* * INCLUDES *********************/ - - -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL +#include "../lv_draw.h" +#if LV_USE_DRAW_SDL +#include LV_SDL_INCLUDE_PATH +#include #include "lv_draw_sdl.h" -#include "lv_draw_sdl_utils.h" -#include "lv_draw_sdl_texture_cache.h" -#include "lv_draw_sdl_layer.h" +#include "../../core/lv_refr.h" +#include "../../display/lv_display_private.h" +#include "../../stdlib/lv_string.h" +#include "../../drivers/sdl/lv_sdl_window.h" /********************* * DEFINES *********************/ -void lv_draw_sdl_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); - -lv_res_t lv_draw_sdl_img_core(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc, - const lv_area_t * coords, const void * src); - -void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p, - uint32_t letter); - -void lv_draw_sdl_draw_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1, - const lv_point_t * point2); - -void lv_draw_sdl_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, - uint16_t radius, uint16_t start_angle, uint16_t end_angle); - -void lv_draw_sdl_polygon(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t * points, - uint16_t point_cnt); - -void lv_draw_sdl_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); +#define DRAW_UNIT_ID_SDL 100 /********************** * TYPEDEFS **********************/ +typedef struct { + lv_draw_dsc_base_t * draw_dsc; + int32_t w; + int32_t h; + SDL_Texture * texture; +} cache_data_t; /********************** * STATIC PROTOTYPES **********************/ +static void execute_drawing(lv_draw_sdl_unit_t * u); + +static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer); + +static int32_t evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task); +static bool draw_to_texture(lv_draw_sdl_unit_t * u, cache_data_t * data); + +/********************** + * GLOBAL PROTOTYPES + **********************/ +static uint8_t sdl_render_buf[2048 * 1024 * 4]; /********************** * STATIC VARIABLES **********************/ +static SDL_Texture * layer_get_texture(lv_layer_t * layer); /********************** * MACROS @@ -58,46 +59,342 @@ void lv_draw_sdl_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * ds /********************** * GLOBAL FUNCTIONS **********************/ - -void lv_draw_sdl_init_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx) +static bool sdl_texture_cache_create_cb(cache_data_t * cached_data, void * user_data) { - _lv_draw_sdl_utils_init(); - lv_memset_00(draw_ctx, sizeof(lv_draw_sdl_ctx_t)); - draw_ctx->draw_rect = lv_draw_sdl_draw_rect; - draw_ctx->draw_img = lv_draw_sdl_img_core; - draw_ctx->draw_letter = lv_draw_sdl_draw_letter; - draw_ctx->draw_line = lv_draw_sdl_draw_line; - draw_ctx->draw_arc = lv_draw_sdl_draw_arc; - draw_ctx->draw_polygon = lv_draw_sdl_polygon; - draw_ctx->draw_bg = lv_draw_sdl_draw_bg; - draw_ctx->layer_init = lv_draw_sdl_layer_init; - draw_ctx->layer_blend = lv_draw_sdl_layer_blend; - draw_ctx->layer_destroy = lv_draw_sdl_layer_destroy; - draw_ctx->layer_instance_size = sizeof(lv_draw_sdl_layer_ctx_t); - lv_draw_sdl_ctx_t * draw_ctx_sdl = (lv_draw_sdl_ctx_t *) draw_ctx; - draw_ctx_sdl->renderer = ((lv_draw_sdl_drv_param_t *) disp_drv->user_data)->renderer; - draw_ctx_sdl->internals = lv_mem_alloc(sizeof(lv_draw_sdl_context_internals_t)); - lv_memset_00(draw_ctx_sdl->internals, sizeof(lv_draw_sdl_context_internals_t)); - lv_draw_sdl_texture_cache_init(draw_ctx_sdl); + return draw_to_texture((lv_draw_sdl_unit_t *)user_data, cached_data); } -void lv_draw_sdl_deinit_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx) +static void sdl_texture_cache_free_cb(cache_data_t * cached_data, void * user_data) { - lv_draw_sdl_ctx_t * draw_ctx_sdl = (lv_draw_sdl_ctx_t *) draw_ctx; - lv_draw_sdl_texture_cache_deinit(draw_ctx_sdl); - lv_mem_free(draw_ctx_sdl->internals); - _lv_draw_sdl_utils_deinit(); + LV_UNUSED(user_data); + + lv_free(cached_data->draw_dsc); + SDL_DestroyTexture(cached_data->texture); + cached_data->draw_dsc = NULL; + cached_data->texture = NULL; } -SDL_Texture * lv_draw_sdl_create_screen_texture(SDL_Renderer * renderer, lv_coord_t hor, lv_coord_t ver) +static lv_cache_compare_res_t sdl_texture_cache_compare_cb(const cache_data_t * lhs, const cache_data_t * rhs) { - SDL_Texture * texture = SDL_CreateTexture(renderer, LV_DRAW_SDL_TEXTURE_FORMAT, SDL_TEXTUREACCESS_TARGET, hor, ver); - SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); - return texture; + if(lhs == rhs) return 0; + + if(lhs->w != rhs->w) { + return lhs->w > rhs->w ? 1 : -1; + } + if(lhs->h != rhs->h) { + return lhs->h > rhs->h ? 1 : -1; + } + + uint32_t lhs_dsc_size = lhs->draw_dsc->dsc_size; + uint32_t rhs_dsc_size = rhs->draw_dsc->dsc_size; + + if(lhs_dsc_size != rhs_dsc_size) { + return lhs_dsc_size > rhs_dsc_size ? 1 : -1; + } + + int cmp_res = memcmp(lhs->draw_dsc, rhs->draw_dsc, lhs->draw_dsc->dsc_size); + + if(cmp_res != 0) { + return cmp_res > 0 ? 1 : -1; + } + + return 0; +} + +void lv_draw_sdl_init(void) +{ + lv_draw_sdl_unit_t * draw_sdl_unit = lv_draw_create_unit(sizeof(lv_draw_sdl_unit_t)); + draw_sdl_unit->base_unit.dispatch_cb = dispatch; + draw_sdl_unit->base_unit.evaluate_cb = evaluate; + draw_sdl_unit->texture_cache = lv_cache_create(&lv_cache_class_lru_rb_count, + sizeof(cache_data_t), 128, (lv_cache_ops_t) { + .compare_cb = (lv_cache_compare_cb_t)sdl_texture_cache_compare_cb, + .create_cb = (lv_cache_create_cb_t)sdl_texture_cache_create_cb, + .free_cb = (lv_cache_free_cb_t)sdl_texture_cache_free_cb, + }); } /********************** * STATIC FUNCTIONS **********************/ -#endif /*LV_USE_GPU_SDL*/ +static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer) +{ + lv_draw_sdl_unit_t * draw_sdl_unit = (lv_draw_sdl_unit_t *) draw_unit; + + /*Return immediately if it's busy with a draw task*/ + if(draw_sdl_unit->task_act) return 0; + + lv_draw_task_t * t = NULL; + t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_SDL); + if(t == NULL) return -1; + + lv_display_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Texture * texture = layer_get_texture(layer); + if(layer != disp->layer_head && texture == NULL) { + void * buf = lv_draw_layer_alloc_buf(layer); + if(buf == NULL) return -1; + + SDL_Renderer * renderer = lv_sdl_window_get_renderer(disp); + int32_t w = lv_area_get_width(&layer->buf_area); + int32_t h = lv_area_get_height(&layer->buf_area); + layer->user_data = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_TARGET, w, h); + } + + t->state = LV_DRAW_TASK_STATE_IN_PROGRESS; + draw_sdl_unit->base_unit.target_layer = layer; + draw_sdl_unit->base_unit.clip_area = &t->clip_area; + draw_sdl_unit->task_act = t; + + execute_drawing(draw_sdl_unit); + + draw_sdl_unit->task_act->state = LV_DRAW_TASK_STATE_READY; + draw_sdl_unit->task_act = NULL; + + /*The draw unit is free now. Request a new dispatching as it can get a new task*/ + lv_draw_dispatch_request(); + return 1; +} + +static int32_t evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task) +{ + LV_UNUSED(draw_unit); + + if(((lv_draw_dsc_base_t *)task->draw_dsc)->user_data == NULL) { + task->preference_score = 0; + task->preferred_draw_unit_id = DRAW_UNIT_ID_SDL; + } + return 0; +} + +static bool draw_to_texture(lv_draw_sdl_unit_t * u, cache_data_t * data) +{ + lv_draw_task_t * task = u->task_act; + + lv_layer_t dest_layer; + lv_memzero(&dest_layer, sizeof(dest_layer)); + dest_layer.buf = lv_draw_buf_align(sdl_render_buf, LV_COLOR_FORMAT_ARGB8888); + dest_layer.color_format = LV_COLOR_FORMAT_ARGB8888; + + lv_area_t a; + _lv_area_intersect(&a, u->base_unit.clip_area, &task->area); + dest_layer.buf_area = task->area; + dest_layer._clip_area = task->area; + lv_memzero(sdl_render_buf, lv_area_get_size(&dest_layer.buf_area) * 4 + 100); + + lv_display_t * disp = _lv_refr_get_disp_refreshing(); + + SDL_Texture * texture = NULL; + switch(task->type) { + case LV_DRAW_TASK_TYPE_FILL: { + lv_draw_fill_dsc_t * fill_dsc = task->draw_dsc; + lv_draw_rect_dsc_t rect_dsc; + lv_draw_rect_dsc_init(&rect_dsc); + rect_dsc.base.user_data = lv_sdl_window_get_renderer(disp); + rect_dsc.bg_color = fill_dsc->color; + rect_dsc.bg_grad = fill_dsc->grad; + rect_dsc.radius = fill_dsc->radius; + rect_dsc.bg_opa = fill_dsc->opa; + + lv_draw_rect(&dest_layer, &rect_dsc, &task->area); + } + break; + case LV_DRAW_TASK_TYPE_BORDER: { + lv_draw_border_dsc_t * border_dsc = task->draw_dsc;; + lv_draw_rect_dsc_t rect_dsc; + lv_draw_rect_dsc_init(&rect_dsc); + rect_dsc.base.user_data = lv_sdl_window_get_renderer(disp); + rect_dsc.bg_opa = LV_OPA_TRANSP; + rect_dsc.radius = border_dsc->radius; + rect_dsc.border_color = border_dsc->color; + rect_dsc.border_opa = border_dsc->opa; + rect_dsc.border_side = border_dsc->side; + rect_dsc.border_width = border_dsc->width; + lv_draw_rect(&dest_layer, &rect_dsc, &task->area); + break; + } + case LV_DRAW_TASK_TYPE_LABEL: { + lv_draw_label_dsc_t label_dsc; + lv_draw_label_dsc_init(&label_dsc); + lv_memcpy(&label_dsc, task->draw_dsc, sizeof(label_dsc)); + label_dsc.base.user_data = lv_sdl_window_get_renderer(disp); + lv_draw_label(&dest_layer, &label_dsc, &task->area); + } + break; + case LV_DRAW_TASK_TYPE_IMAGE: { + lv_draw_image_dsc_t * image_dsc = task->draw_dsc; + // SDL_Surface* loadImage(std::string path) { + const char * path = image_dsc->src; + SDL_Surface * surface = IMG_Load(&path[2]); + if(surface == NULL) { + fprintf(stderr, "could not load image: %s\n", IMG_GetError()); + return false; + } + + SDL_Renderer * renderer = lv_sdl_window_get_renderer(disp); + texture = SDL_CreateTextureFromSurface(renderer, surface); + break; + } + default: + return false; + } + + while(dest_layer.draw_task_head) { + lv_draw_dispatch_layer(disp, &dest_layer); + if(dest_layer.draw_task_head) { + lv_draw_dispatch_wait_for_request(); + } + } + + SDL_Rect rect; + rect.x = dest_layer.buf_area.x1; + rect.y = dest_layer.buf_area.y1; + rect.w = lv_area_get_width(&dest_layer.buf_area); + rect.h = lv_area_get_height(&dest_layer.buf_area); + + if(texture == NULL) { + texture = SDL_CreateTexture(lv_sdl_window_get_renderer(disp), SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STATIC, rect.w, rect.h); + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + SDL_UpdateTexture(texture, NULL, sdl_render_buf, rect.w * 4); + } + else { + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + } + + lv_draw_dsc_base_t * base_dsc = task->draw_dsc; + + data->draw_dsc = lv_malloc(base_dsc->dsc_size); + lv_memcpy((void *)data->draw_dsc, base_dsc, base_dsc->dsc_size); + data->w = lv_area_get_width(&task->area); + data->h = lv_area_get_height(&task->area); + data->texture = texture; + + return true; +} + +static void blend_texture_layer(lv_draw_sdl_unit_t * u) +{ + lv_display_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Renderer * renderer = lv_sdl_window_get_renderer(disp); + + SDL_Rect clip_rect; + clip_rect.x = u->base_unit.clip_area->x1; + clip_rect.y = u->base_unit.clip_area->y1; + clip_rect.w = lv_area_get_width(u->base_unit.clip_area); + clip_rect.h = lv_area_get_height(u->base_unit.clip_area); + + lv_draw_task_t * t = u->task_act; + SDL_Rect rect; + rect.x = t->area.x1; + rect.y = t->area.y1; + rect.w = lv_area_get_width(&t->area); + rect.h = lv_area_get_height(&t->area); + + lv_draw_image_dsc_t * draw_dsc = t->draw_dsc; + lv_layer_t * src_layer = (lv_layer_t *)draw_dsc->src; + SDL_Texture * src_texture = layer_get_texture(src_layer); + + SDL_SetTextureAlphaMod(src_texture, draw_dsc->opa); + SDL_SetTextureBlendMode(src_texture, SDL_BLENDMODE_BLEND); + SDL_SetRenderTarget(renderer, layer_get_texture(u->base_unit.target_layer)); + SDL_RenderSetClipRect(renderer, &clip_rect); + SDL_RenderCopy(renderer, src_texture, NULL, &rect); + SDL_DestroyTexture(src_texture); + SDL_RenderSetClipRect(renderer, NULL); +} + +static void draw_from_cached_texture(lv_draw_sdl_unit_t * u) +{ + lv_draw_task_t * t = u->task_act; + + cache_data_t data_to_find; + data_to_find.draw_dsc = (lv_draw_dsc_base_t *)t->draw_dsc; + + data_to_find.w = lv_area_get_width(&t->area); + data_to_find.h = lv_area_get_height(&t->area); + data_to_find.texture = NULL; + + /*user_data stores the renderer to differentiate it from SW rendered tasks. + *However the cached texture is independent from the renderer so use NULL user_data*/ + void * user_data_saved = data_to_find.draw_dsc->user_data; + data_to_find.draw_dsc->user_data = NULL; + + lv_cache_entry_t * entry_cached = lv_cache_acquire_or_create(u->texture_cache, &data_to_find, u); + if(!entry_cached) { + return; + } + + data_to_find.draw_dsc->user_data = user_data_saved; + + cache_data_t * data_cached = lv_cache_entry_get_data(entry_cached); + SDL_Texture * texture = data_cached->texture; + lv_display_t * disp = _lv_refr_get_disp_refreshing(); + SDL_Renderer * renderer = lv_sdl_window_get_renderer(disp); + + lv_layer_t * dest_layer = u->base_unit.target_layer; + SDL_Rect clip_rect; + clip_rect.x = u->base_unit.clip_area->x1 - dest_layer->buf_area.x1; + clip_rect.y = u->base_unit.clip_area->y1 - dest_layer->buf_area.y1; + clip_rect.w = lv_area_get_width(u->base_unit.clip_area); + clip_rect.h = lv_area_get_height(u->base_unit.clip_area); + + SDL_Rect rect; + + SDL_SetRenderTarget(renderer, layer_get_texture(dest_layer)); + + if(t->type == LV_DRAW_TASK_TYPE_IMAGE) { + lv_draw_image_dsc_t * draw_dsc = t->draw_dsc; + lv_area_t image_area; + image_area.x1 = 0; + image_area.y1 = 0; + image_area.x2 = draw_dsc->header.w - 1; + image_area.y2 = draw_dsc->header.h - 1; + + lv_area_move(&image_area, t->area.x1 - dest_layer->buf_area.x1, t->area.y1 - dest_layer->buf_area.y1); + rect.x = image_area.x1; + rect.y = image_area.y1; + rect.w = lv_area_get_width(&image_area); + rect.h = lv_area_get_height(&image_area); + + SDL_RenderSetClipRect(renderer, &clip_rect); + SDL_RenderCopy(renderer, texture, NULL, &rect); + } + else { + rect.x = t->area.x1 - dest_layer->buf_area.x1; + rect.y = t->area.y1 - dest_layer->buf_area.y1; + rect.w = lv_area_get_width(&t->area); + rect.h = lv_area_get_height(&t->area); + + SDL_RenderSetClipRect(renderer, &clip_rect); + SDL_RenderCopy(renderer, texture, NULL, &rect); + } + + SDL_RenderSetClipRect(renderer, NULL); + + lv_cache_release(u->texture_cache, entry_cached, u); +} + +static void execute_drawing(lv_draw_sdl_unit_t * u) +{ + lv_draw_task_t * t = u->task_act; + + if(t->type == LV_DRAW_TASK_TYPE_BOX_SHADOW) return; + if(t->type == LV_DRAW_TASK_TYPE_LINE) return; + if(t->type == LV_DRAW_TASK_TYPE_TRIANGLE) return; + + if(t->type == LV_DRAW_TASK_TYPE_LAYER) { + blend_texture_layer(u); + } + else { + draw_from_cached_texture(u); + } +} + +static SDL_Texture * layer_get_texture(lv_layer_t * layer) +{ + return layer->user_data; +} + +#endif /*LV_USE_DRAW_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.h b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.h index 9b44a7b2f..8f75ef473 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.h @@ -6,7 +6,6 @@ #ifndef LV_DRAW_SDL_H #define LV_DRAW_SDL_H - #ifdef __cplusplus extern "C" { #endif @@ -14,80 +13,75 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include LV_GPU_SDL_INCLUDE_PATH - #include "../lv_draw.h" -#include "../../core/lv_disp.h" + +#if LV_USE_DRAW_SDL + +#include +#include "../../misc/lv_area.h" +#include "../../misc/lv_color.h" +#include "../../display/lv_display.h" +#include "../../osal/lv_os.h" /********************* * DEFINES *********************/ -#if SDL_BYTEORDER == SDL_BIG_ENDIAN -#define LV_DRAW_SDL_TEXTURE_FORMAT SDL_PIXELFORMAT_ARGB8888 -#else -#define LV_DRAW_SDL_TEXTURE_FORMAT SDL_PIXELFORMAT_RGBA8888 -#endif - /********************** * TYPEDEFS **********************/ -struct lv_draw_sdl_context_internals_t; - typedef struct { - /** - * Render for display driver - */ - SDL_Renderer * renderer; - void * user_data; -} lv_draw_sdl_drv_param_t; + lv_draw_unit_t base_unit; + lv_draw_task_t * task_act; + uint32_t texture_cache_data_type; + lv_cache_t * texture_cache; +} lv_draw_sdl_unit_t; +#if LV_DRAW_SW_SHADOW_CACHE_SIZE typedef struct { - lv_draw_ctx_t base_draw; - SDL_Renderer * renderer; - struct lv_draw_sdl_context_internals_t * internals; -} lv_draw_sdl_ctx_t; + uint8_t cache[LV_DRAW_SW_SHADOW_CACHE_SIZE * LV_DRAW_SW_SHADOW_CACHE_SIZE]; + int32_t cache_size; + int32_t cache_r; +} lv_draw_sw_shadow_cache_t; +#endif /********************** * GLOBAL PROTOTYPES **********************/ -void lv_draw_sdl_init_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx); +void lv_draw_sdl_init(void); -/** - * @brief Free caches - * - */ -void lv_draw_sdl_deinit_ctx(lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx); +LV_ATTRIBUTE_FAST_MEM void lv_draw_sdl_image(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords); -SDL_Texture * lv_draw_sdl_create_screen_texture(SDL_Renderer * renderer, lv_coord_t hor, lv_coord_t ver); +void lv_draw_sdl_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords); -/*====================== - * Add/remove functions - *=====================*/ +void lv_draw_sdl_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, const lv_area_t * coords); -/*===================== - * Setter functions - *====================*/ +void lv_draw_sdl_box_shadow(lv_draw_unit_t * draw_unit, const lv_draw_box_shadow_dsc_t * dsc, const lv_area_t * coords); -/*===================== - * Getter functions - *====================*/ +void lv_draw_sdl_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords); -/*===================== - * Other functions - *====================*/ +void lv_draw_sdl_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords); + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sdl_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc); + +void lv_draw_sdl_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, const lv_area_t * coords); + +void lv_draw_sdl_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc); + +void lv_draw_sdl_mask_rect(lv_draw_unit_t * draw_unit, const lv_draw_mask_rect_dsc_t * dsc, const lv_area_t * coords); + +/*********************** + * GLOBAL VARIABLES + ***********************/ /********************** * MACROS **********************/ -#endif /*LV_USE_GPU_SDL*/ +#endif /*LV_USE_DRAW_SDL*/ #ifdef __cplusplus } /*extern "C"*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.mk b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.mk deleted file mode 100644 index c5c28b66b..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.mk +++ /dev/null @@ -1,19 +0,0 @@ -CSRCS += lv_draw_sdl.c -CSRCS += lv_draw_sdl_arc.c -CSRCS += lv_draw_sdl_bg.c -CSRCS += lv_draw_sdl_composite.c -CSRCS += lv_draw_sdl_img.c -CSRCS += lv_draw_sdl_label.c -CSRCS += lv_draw_sdl_line.c -CSRCS += lv_draw_sdl_mask.c -CSRCS += lv_draw_sdl_polygon.c -CSRCS += lv_draw_sdl_rect.c -CSRCS += lv_draw_sdl_stack_blur.c -CSRCS += lv_draw_sdl_texture_cache.c -CSRCS += lv_draw_sdl_utils.c -CSRCS += lv_draw_sdl_layer.c - -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sdl" diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_arc.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_arc.c deleted file mode 100644 index f43fef641..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_arc.c +++ /dev/null @@ -1,245 +0,0 @@ -/** - * @file lv_draw_sdl_arc.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include "lv_draw_sdl.h" -#include "lv_draw_sdl_utils.h" -#include "lv_draw_sdl_texture_cache.h" -#include "lv_draw_sdl_composite.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -static void dump_masks(SDL_Texture * texture, const lv_area_t * coords, const int16_t * ids, int16_t ids_count, - const int16_t * caps); - -static void get_cap_area(int16_t angle, lv_coord_t thickness, uint16_t radius, const lv_point_t * center, - lv_area_t * out); - -/********************** - * GLOBAL FUNCTIONS - **********************/ -void lv_draw_sdl_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, - uint16_t radius, uint16_t start_angle, uint16_t end_angle) -{ - lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx; - - lv_area_t area_out; - area_out.x1 = center->x - radius; - area_out.y1 = center->y - radius; - area_out.x2 = center->x + radius - 1; /*-1 because the center already belongs to the left/bottom part*/ - area_out.y2 = center->y + radius - 1; - - lv_area_t draw_area; - if(!_lv_area_intersect(&draw_area, &area_out, draw_ctx->clip_area)) { - return; - } - - lv_area_t area_in; - lv_area_copy(&area_in, &area_out); - area_in.x1 += dsc->width; - area_in.y1 += dsc->width; - area_in.x2 -= dsc->width; - area_in.y2 -= dsc->width; - - - while(start_angle >= 360) start_angle -= 360; - while(end_angle >= 360) end_angle -= 360; - - int16_t mask_ids[3] = {LV_MASK_ID_INV, LV_MASK_ID_INV, LV_MASK_ID_INV}, mask_ids_count = 1; - int16_t cap_ids[2] = {LV_MASK_ID_INV, LV_MASK_ID_INV}; - - lv_draw_mask_radius_param_t mask_out_param; - lv_draw_mask_radius_init(&mask_out_param, &area_out, LV_RADIUS_CIRCLE, false); - mask_ids[0] = lv_draw_mask_add(&mask_out_param, NULL); - - lv_draw_mask_radius_param_t mask_in_param; - if(lv_area_get_width(&area_in) > 0 && lv_area_get_height(&area_in) > 0) { - lv_draw_mask_radius_init(&mask_in_param, &area_in, LV_RADIUS_CIRCLE, true); - mask_ids[1] = lv_draw_mask_add(&mask_in_param, NULL); - mask_ids_count++; - } - - lv_draw_mask_angle_param_t mask_angle_param; - if((start_angle - end_angle) % 360) { - lv_draw_mask_angle_init(&mask_angle_param, center->x, center->y, start_angle, end_angle); - mask_ids[2] = lv_draw_mask_add(&mask_angle_param, NULL); - mask_ids_count++; - } - - lv_draw_mask_radius_param_t cap_start_param, cap_end_param; - if(mask_ids_count == 3 && dsc->rounded) { - lv_area_t start_area, end_area; - get_cap_area((int16_t) start_angle, dsc->width, radius, center, &start_area); - get_cap_area((int16_t) end_angle, dsc->width, radius, center, &end_area); - lv_draw_mask_radius_init(&cap_start_param, &start_area, dsc->width / 2, false); - cap_ids[0] = lv_draw_mask_add(&cap_start_param, NULL); - lv_draw_mask_radius_init(&cap_end_param, &end_area, dsc->width / 2, false); - cap_ids[1] = lv_draw_mask_add(&cap_end_param, NULL); - } - - lv_coord_t w = lv_area_get_width(&draw_area), h = lv_area_get_height(&draw_area); - bool texture_cached = false; - SDL_Texture * texture = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, w, h, - &texture_cached); - SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); - dump_masks(texture, &draw_area, mask_ids, mask_ids_count, cap_ids[0] != LV_MASK_ID_INV ? cap_ids : NULL); - - lv_draw_mask_remove_id(mask_ids[0]); - lv_draw_mask_free_param(&mask_out_param); - - if(mask_ids_count > 1) { - lv_draw_mask_remove_id(mask_ids[1]); - lv_draw_mask_free_param(&mask_in_param); - } - - if(mask_ids_count > 2) { - lv_draw_mask_remove_id(mask_ids[2]); - lv_draw_mask_free_param(&mask_angle_param); - } - - if(cap_ids[0] != LV_MASK_ID_INV) { - lv_draw_mask_remove_id(cap_ids[0]); - lv_draw_mask_remove_id(cap_ids[1]); - lv_draw_mask_free_param(&cap_start_param); - lv_draw_mask_free_param(&cap_end_param); - } - - SDL_Rect srcrect = {0, 0, w, h}, dstrect; - lv_area_to_sdl_rect(&draw_area, &dstrect); - SDL_Color color; - lv_color_to_sdl_color(&dsc->color, &color); - SDL_SetTextureColorMod(texture, color.r, color.g, color.b); - SDL_SetTextureAlphaMod(texture, dsc->opa); - SDL_RenderCopy(ctx->renderer, texture, &srcrect, &dstrect); - - if(!texture_cached) { - LV_LOG_WARN("Texture is not cached, this will impact performance."); - SDL_DestroyTexture(texture); - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void dump_masks(SDL_Texture * texture, const lv_area_t * coords, const int16_t * ids, int16_t ids_count, - const int16_t * caps) -{ - lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords); - SDL_assert(w > 0 && h > 0); - SDL_Rect rect = {0, 0, w, h}; - uint8_t * pixels; - int pitch; - if(SDL_LockTexture(texture, &rect, (void **) &pixels, &pitch) != 0) return; - - lv_opa_t * line_buf = lv_mem_buf_get(rect.w); - for(lv_coord_t y = 0; y < rect.h; y++) { - lv_memset_ff(line_buf, rect.w); - lv_coord_t abs_x = (lv_coord_t) coords->x1, abs_y = (lv_coord_t)(y + coords->y1), len = (lv_coord_t) rect.w; - lv_draw_mask_res_t res; - res = lv_draw_mask_apply_ids(line_buf, abs_x, abs_y, len, ids, ids_count); - if(res == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(&pixels[y * pitch], 4 * rect.w); - } - else if(res == LV_DRAW_MASK_RES_FULL_COVER) { - lv_memset_ff(&pixels[y * pitch], 4 * rect.w); - } - else { - for(int x = 0; x < rect.w; x++) { - uint8_t * pixel = &pixels[y * pitch + x * 4]; - *pixel = line_buf[x]; - pixel[1] = pixel[2] = pixel[3] = 0xFF; - } - } - if(caps) { - for(int i = 0; i < 2; i++) { - lv_memset_ff(line_buf, rect.w); - res = lv_draw_mask_apply_ids(line_buf, abs_x, abs_y, len, &caps[i], 1); - if(res == LV_DRAW_MASK_RES_TRANSP) { - /* Ignore */ - } - else if(res == LV_DRAW_MASK_RES_FULL_COVER) { - lv_memset_ff(&pixels[y * pitch], 4 * rect.w); - } - else { - for(int x = 0; x < rect.w; x++) { - uint8_t * pixel = &pixels[y * pitch + x * 4]; - uint16_t old_opa = line_buf[x] + *pixel; - *pixel = LV_MIN(old_opa, 0xFF); - pixel[1] = pixel[2] = pixel[3] = 0xFF; - } - } - } - } - } - lv_mem_buf_release(line_buf); - SDL_UnlockTexture(texture); -} - -static void get_cap_area(int16_t angle, lv_coord_t thickness, uint16_t radius, const lv_point_t * center, - lv_area_t * out) -{ - const uint8_t ps = 8; - const uint8_t pa = 127; - - int32_t thick_half = thickness / 2; - uint8_t thick_corr = (thickness & 0x01) ? 0 : 1; - - int32_t cir_x; - int32_t cir_y; - - cir_x = ((radius - thick_half) * lv_trigo_sin((int16_t)(90 - angle))) >> (LV_TRIGO_SHIFT - ps); - cir_y = ((radius - thick_half) * lv_trigo_sin(angle)) >> (LV_TRIGO_SHIFT - ps); - - /*Actually the center of the pixel need to be calculated so apply 1/2 px offset*/ - if(cir_x > 0) { - cir_x = (cir_x - pa) >> ps; - out->x1 = cir_x - thick_half + thick_corr; - out->x2 = cir_x + thick_half; - } - else { - cir_x = (cir_x + pa) >> ps; - out->x1 = cir_x - thick_half; - out->x2 = cir_x + thick_half - thick_corr; - } - - if(cir_y > 0) { - cir_y = (cir_y - pa) >> ps; - out->y1 = cir_y - thick_half + thick_corr; - out->y2 = cir_y + thick_half; - } - else { - cir_y = (cir_y + pa) >> ps; - out->y1 = cir_y - thick_half; - out->y2 = cir_y + thick_half - thick_corr; - } - lv_area_move(out, center->x, center->y); -} - -#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_bg.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_bg.c deleted file mode 100644 index 48e0f6b19..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_bg.c +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @file lv_draw_sdl_bg.c - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include "../lv_draw_rect.h" -#include "../lv_draw_img.h" -#include "../lv_draw_label.h" -#include "../lv_draw_mask.h" -#include "../../core/lv_refr.h" -#include "lv_draw_sdl_utils.h" -#include "lv_draw_sdl_texture_cache.h" -#include "lv_draw_sdl_composite.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area, - const lv_draw_rect_dsc_t * dsc); - -static void draw_bg_img(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area, - const lv_draw_rect_dsc_t * dsc); - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void lv_draw_sdl_draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) -{ - const lv_area_t * clip = draw_ctx->clip_area; - lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx; - /* Coords will be translated so coords will start at (0,0) */ - lv_area_t t_area; - bool has_content = _lv_area_intersect(&t_area, coords, clip); - - /* Shadows and outlines will also draw in extended area */ - if(has_content) { - if(dsc->bg_img_src) { - draw_bg_img(ctx, coords, &t_area, dsc); - } - else { - draw_bg_color(ctx, coords, &t_area, dsc); - } - } - -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area, - const lv_draw_rect_dsc_t * dsc) -{ - SDL_Color bg_color; - lv_color_to_sdl_color(&dsc->bg_color, &bg_color); - SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE); - SDL_SetRenderDrawColor(ctx->renderer, bg_color.r, bg_color.g, bg_color.b, dsc->bg_opa); - - SDL_Rect rect; - lv_area_to_sdl_rect(draw_area, &rect); - SDL_RenderFillRect(ctx->renderer, &rect); - - SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND); -} - -static void draw_bg_img(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area, - const lv_draw_rect_dsc_t * dsc) -{ - SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE); - SDL_SetRenderDrawColor(ctx->renderer, 0, 0, 0, 0); - - SDL_Rect rect; - lv_area_to_sdl_rect(draw_area, &rect); - SDL_RenderFillRect(ctx->renderer, &rect); - - SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND); - lv_draw_rect((lv_draw_ctx_t *) ctx, dsc, coords); -} - -#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.c deleted file mode 100644 index 9bf6385e5..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.c +++ /dev/null @@ -1,279 +0,0 @@ -/** - * @file lv_draw_sdl_composite.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include "../../misc/lv_gc.h" -#include "../../core/lv_refr.h" -#include "lv_draw_sdl_composite.h" -#include "lv_draw_sdl_utils.h" -#include "lv_draw_sdl_priv.h" -#include "lv_draw_sdl_texture_cache.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - lv_sdl_cache_key_magic_t magic; - lv_draw_sdl_composite_texture_id_t type; -} composite_key_t; - -/********************** - * STATIC PROTOTYPES - **********************/ - -static composite_key_t mask_key_create(lv_draw_sdl_composite_texture_id_t type); - -static lv_coord_t next_pow_of_2(lv_coord_t num); - -static void dump_masks(SDL_Texture * texture, const lv_area_t * coords); -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -bool lv_draw_sdl_composite_begin(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords_in, const lv_area_t * clip_in, - const lv_area_t * extension, lv_blend_mode_t blend_mode, lv_area_t * coords_out, - lv_area_t * clip_out, lv_area_t * apply_area) -{ - lv_area_t full_coords = *coords_in; - - /* Normalize full_coords */ - if(full_coords.x1 > full_coords.x2) { - lv_coord_t x2 = full_coords.x2; - full_coords.x2 = full_coords.x1; - full_coords.x1 = x2; - } - if(full_coords.y1 > full_coords.y2) { - lv_coord_t y2 = full_coords.y2; - full_coords.y2 = full_coords.y1; - full_coords.y1 = y2; - } - - if(extension) { - full_coords.x1 -= extension->x1; - full_coords.x2 += extension->x2; - full_coords.y1 -= extension->y1; - full_coords.y2 += extension->y2; - } - - if(!_lv_area_intersect(apply_area, &full_coords, clip_in)) return false; - bool has_mask = lv_draw_mask_is_any(apply_area); - - const bool draw_mask = has_mask && LV_GPU_SDL_CUSTOM_BLEND_MODE; - const bool draw_blend = blend_mode != LV_BLEND_MODE_NORMAL; - if(draw_mask || draw_blend) { - lv_draw_sdl_context_internals_t * internals = ctx->internals; - LV_ASSERT(internals->mask == NULL && internals->composition == NULL && internals->target_backup == NULL); - - lv_coord_t w = lv_area_get_width(apply_area), h = lv_area_get_height(apply_area); - internals->composition = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0, w, h, - &internals->composition_cached); - /* Don't need to worry about integral overflow */ - lv_coord_t ofs_x = (lv_coord_t) - apply_area->x1, ofs_y = (lv_coord_t) - apply_area->y1; - /* Offset draw area to start with (0,0) of coords */ - lv_area_move(coords_out, ofs_x, ofs_y); - lv_area_move(clip_out, ofs_x, ofs_y); - internals->target_backup = SDL_GetRenderTarget(ctx->renderer); - SDL_SetRenderTarget(ctx->renderer, internals->composition); - SDL_SetRenderDrawColor(ctx->renderer, 255, 255, 255, 0); - /* SDL_RenderClear is not working properly, so we overwrite the target with solid color */ - SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE); - SDL_RenderFillRect(ctx->renderer, NULL); - SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND); -#if LV_GPU_SDL_CUSTOM_BLEND_MODE - internals->mask = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM0, w, h, - &internals->composition_cached); - dump_masks(internals->mask, apply_area); -#endif - } - else if(has_mask) { - /* Fallback mask handling. This will at least make bars looks less bad */ - for(uint8_t i = 0; i < _LV_MASK_MAX_NUM; i++) { - _lv_draw_mask_common_dsc_t * comm_param = LV_GC_ROOT(_lv_draw_mask_list[i]).param; - if(comm_param == NULL) continue; - switch(comm_param->type) { - case LV_DRAW_MASK_TYPE_RADIUS: { - const lv_draw_mask_radius_param_t * param = (const lv_draw_mask_radius_param_t *) comm_param; - if(param->cfg.outer) break; - _lv_area_intersect(clip_out, apply_area, ¶m->cfg.rect); - break; - } - default: - break; - } - } - } - return has_mask; -} - -void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_area, lv_blend_mode_t blend_mode) -{ - lv_draw_sdl_context_internals_t * internals = ctx->internals; - SDL_Rect src_rect = {0, 0, lv_area_get_width(apply_area), lv_area_get_height(apply_area)}; -#if LV_GPU_SDL_CUSTOM_BLEND_MODE - if(internals->mask) { - SDL_BlendMode mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, - SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_ZERO, - SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDOPERATION_ADD); - SDL_SetTextureBlendMode(internals->mask, mode); - SDL_RenderCopy(ctx->renderer, internals->mask, &src_rect, &src_rect); - } -#endif - - /* Shapes are drawn on composite layer when mask or blend mode is present */ - if(internals->composition) { - SDL_Rect dst_rect; - lv_area_to_sdl_rect(apply_area, &dst_rect); - - SDL_SetRenderTarget(ctx->renderer, internals->target_backup); - switch(blend_mode) { - case LV_BLEND_MODE_NORMAL: - SDL_SetTextureBlendMode(internals->composition, SDL_BLENDMODE_BLEND); - break; - case LV_BLEND_MODE_ADDITIVE: - SDL_SetTextureBlendMode(internals->composition, SDL_BLENDMODE_ADD); - break; -#if LV_GPU_SDL_CUSTOM_BLEND_MODE - case LV_BLEND_MODE_SUBTRACTIVE: { - SDL_BlendMode mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE, - SDL_BLENDOPERATION_SUBTRACT, SDL_BLENDFACTOR_ONE, - SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT); - SDL_SetTextureBlendMode(internals->composition, mode); - break; - } - case LV_BLEND_MODE_MULTIPLY: { - SDL_BlendMode mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_SRC_COLOR, - SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_ZERO, - SDL_BLENDFACTOR_DST_ALPHA, SDL_BLENDOPERATION_ADD); - SDL_SetTextureBlendMode(internals->composition, mode); - break; - } -#endif - default: - LV_LOG_WARN("Doesn't support blend mode %d", blend_mode); - SDL_SetTextureBlendMode(internals->composition, SDL_BLENDMODE_BLEND); - /* Unsupported yet */ - break; - } - SDL_RenderCopy(ctx->renderer, internals->composition, &src_rect, &dst_rect); - if(!internals->composition_cached) { - LV_LOG_WARN("Texture is not cached, this will impact performance."); - SDL_DestroyTexture(internals->composition); - } - } - - internals->mask = internals->composition = internals->target_backup = NULL; -} - -SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_composite_texture_id_t id, - lv_coord_t w, lv_coord_t h, bool * texture_in_cache) -{ - lv_point_t * tex_size = NULL; - composite_key_t mask_key = mask_key_create(id); - SDL_Texture * result = lv_draw_sdl_texture_cache_get_with_userdata(ctx, &mask_key, sizeof(composite_key_t), NULL, - (void **) &tex_size); - if(result == NULL || tex_size->x < w || tex_size->y < h) { - lv_coord_t size = next_pow_of_2(LV_MAX(w, h)); - int access = SDL_TEXTUREACCESS_STREAMING; - if(id >= LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0) { - access = SDL_TEXTUREACCESS_TARGET; - } - else if(id >= LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0) { - access = SDL_TEXTUREACCESS_TARGET; - } - result = SDL_CreateTexture(ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, access, size, size); - tex_size = lv_mem_alloc(sizeof(lv_point_t)); - tex_size->x = tex_size->y = size; - bool in_cache = lv_draw_sdl_texture_cache_put_advanced(ctx, &mask_key, sizeof(composite_key_t), result, - tex_size, lv_mem_free, 0); - if(!in_cache) { - lv_mem_free(tex_size); - } - if(texture_in_cache != NULL) { - *texture_in_cache = in_cache; - } - } - else if(texture_in_cache != NULL) { - *texture_in_cache = true; - } - - return result; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static composite_key_t mask_key_create(lv_draw_sdl_composite_texture_id_t type) -{ - composite_key_t key; - /* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */ - SDL_memset(&key, 0, sizeof(key)); - key.magic = LV_GPU_CACHE_KEY_MAGIC_MASK; - key.type = type; - return key; -} - -static lv_coord_t next_pow_of_2(lv_coord_t num) -{ - lv_coord_t n = 128; - while(n < num && n < 16384) { - n = n << 1; - } - return n; -} - -static void dump_masks(SDL_Texture * texture, const lv_area_t * coords) -{ - lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords); - SDL_assert(w > 0 && h > 0); - SDL_Rect rect = {0, 0, w, h}; - uint8_t * pixels; - int pitch; - if(SDL_LockTexture(texture, &rect, (void **) &pixels, &pitch) != 0) return; - - lv_opa_t * line_buf = lv_mem_buf_get(rect.w); - for(lv_coord_t y = 0; y < rect.h; y++) { - lv_memset_ff(line_buf, rect.w); - lv_coord_t abs_x = (lv_coord_t) coords->x1, abs_y = (lv_coord_t)(y + coords->y1), len = (lv_coord_t) rect.w; - lv_draw_mask_res_t res; - res = lv_draw_mask_apply(line_buf, abs_x, abs_y, len); - if(res == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(&pixels[y * pitch], 4 * rect.w); - } - else if(res == LV_DRAW_MASK_RES_FULL_COVER) { - lv_memset_ff(&pixels[y * pitch], 4 * rect.w); - } - else { - for(int x = 0; x < rect.w; x++) { - const size_t idx = y * pitch + x * 4; - pixels[idx] = line_buf[x]; - pixels[idx + 1] = pixels[idx + 2] = pixels[idx + 3] = 0xFF; - } - } - } - lv_mem_buf_release(line_buf); - SDL_UnlockTexture(texture); -} - -#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.h b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.h deleted file mode 100644 index 57191bbce..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.h +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @file lv_draw_sdl_composite.h - * - */ - -#ifndef LV_DRAW_SDL_COMPOSITE_H -#define LV_DRAW_SDL_COMPOSITE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ - -#include "../../lv_conf_internal.h" - -#include LV_GPU_SDL_INCLUDE_PATH - -#include "lv_draw_sdl.h" -#include "../../misc/lv_area.h" -#include "../../misc/lv_color.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef enum lv_draw_sdl_composite_texture_id_t { - LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM0, - LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, - LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET0, - LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TARGET1, - LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0, -} lv_draw_sdl_composite_texture_id_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Begin drawing with mask. Render target will be switched to a temporary texture, - * and drawing coordinates may get clipped or translated - * @param ctx Drawing context - * @param coords_in Original coordinates - * @param clip_in Original clip area - * @param extension Useful for shadows or outlines, can be NULL - * @param coords_out Translated coords - * @param clip_out Translated clip area - * @param apply_area Area of actual composited texture will be drawn - * @return true if there are any mask needs to be drawn, false otherwise - */ -bool lv_draw_sdl_composite_begin(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords_in, const lv_area_t * clip_in, - const lv_area_t * extension, lv_blend_mode_t blend_mode, lv_area_t * coords_out, - lv_area_t * clip_out, lv_area_t * apply_area); - -void lv_draw_sdl_composite_end(lv_draw_sdl_ctx_t * ctx, const lv_area_t * apply_area, lv_blend_mode_t blend_mode); - -/** - * - * @param ctx Drawing context - * @param id Texture ID - * @param w Maximum width needed - * @param h Maximum height needed - * @param texture_in_cache output to query if the texture is in cache. If it's not in cache, you'll need to destroy it - * by yourself - * @return Obtained texture - */ -SDL_Texture * lv_draw_sdl_composite_texture_obtain(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_composite_texture_id_t id, - lv_coord_t w, lv_coord_t h, bool * texture_in_cache); - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_SDL_COMPOSITE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_img.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_img.c deleted file mode 100644 index 4dddc8c60..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_img.c +++ /dev/null @@ -1,499 +0,0 @@ -/** - * @file lv_draw_sdl_img.c - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include "../lv_draw_img.h" -#include "../lv_img_cache.h" -#include "../lv_draw_mask.h" -#include "../../misc/lv_lru.h" -#include "../../misc/lv_gc.h" - -#include "lv_draw_sdl_img.h" -#include "lv_draw_sdl_utils.h" -#include "lv_draw_sdl_texture_cache.h" -#include "lv_draw_sdl_composite.h" -#include "lv_draw_sdl_rect.h" -#include "lv_draw_sdl_layer.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - lv_sdl_cache_key_magic_t magic; - const SDL_Texture * texture; - lv_coord_t w, h, radius; -} lv_draw_img_rounded_key_t; - -enum { - ROUNDED_IMG_PART_LEFT = 0, - ROUNDED_IMG_PART_HCENTER = 1, - ROUNDED_IMG_PART_RIGHT = 2, - ROUNDED_IMG_PART_TOP = 3, - ROUNDED_IMG_PART_VCENTER = 4, - ROUNDED_IMG_PART_BOTTOM = 5, -}; - -enum { - ROUNDED_IMG_CORNER_TOP_LEFT = 0, - ROUNDED_IMG_CORNER_TOP_RIGHT = 1, - ROUNDED_IMG_CORNER_BOTTOM_RIGHT = 2, - ROUNDED_IMG_CORNER_BOTTOM_LEFT = 3, -}; - -/********************** - * STATIC PROTOTYPES - **********************/ - -static SDL_Texture * upload_img_texture(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc); - -static SDL_Texture * upload_img_texture_fallback(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc); - -static bool check_mask_simple_radius(const lv_area_t * coords, lv_coord_t * radius); - -static void draw_img_simple(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header, - const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip); - -static void draw_img_rounded(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header, - const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip, - lv_coord_t radius); - -static SDL_Texture * img_rounded_frag_obtain(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, - const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius, - bool * in_cache); - -static lv_draw_img_rounded_key_t rounded_key_create(const SDL_Texture * texture, lv_coord_t w, lv_coord_t h, - lv_coord_t radius); - -static void calc_draw_part(SDL_Texture * texture, const lv_draw_sdl_img_header_t * header, const lv_area_t * coords, - const lv_area_t * clip, SDL_Rect * clipped_src, SDL_Rect * clipped_dst); -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - - -static void apply_recolor_opa(SDL_Texture * texture, const lv_draw_img_dsc_t * draw_dsc); - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_res_t lv_draw_sdl_img_core(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc, - const lv_area_t * coords, const void * src) -{ - const lv_area_t * clip = draw_ctx->clip_area; - lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx; - - size_t key_size; - lv_draw_sdl_cache_key_head_img_t * key = lv_draw_sdl_texture_img_key_create(src, draw_dsc->frame_id, &key_size); - bool texture_found = false; - lv_draw_sdl_img_header_t * header = NULL; - SDL_Texture * texture = lv_draw_sdl_texture_cache_get_with_userdata(ctx, key, key_size, &texture_found, - (void **) &header); - bool texture_in_cache = false; - if(!texture_found) { - lv_draw_sdl_img_load_texture(ctx, key, key_size, src, draw_dsc->frame_id, &texture, &header, - &texture_in_cache); - } - else { - texture_in_cache = true; - } - SDL_free(key); - if(!texture || !header) { - return LV_RES_INV; - } - - lv_area_t zoomed_cords; - _lv_img_buf_get_transformed_area(&zoomed_cords, lv_area_get_width(coords), lv_area_get_height(coords), 0, - draw_dsc->zoom, &draw_dsc->pivot); - lv_area_move(&zoomed_cords, coords->x1, coords->y1); - - /* When in > 0, draw simple radius */ - lv_coord_t radius = 0; - /* Coords will be translated so coords will start at (0,0) */ - lv_area_t t_coords = zoomed_cords, t_clip = *clip, apply_area; - - bool has_composite = false; - - if(!check_mask_simple_radius(&t_coords, &radius)) { - has_composite = lv_draw_sdl_composite_begin(ctx, &zoomed_cords, clip, NULL, draw_dsc->blend_mode, - &t_coords, &t_clip, &apply_area); - } - - lv_draw_sdl_transform_areas_offset(ctx, has_composite, &apply_area, &t_coords, &t_clip); - - SDL_Rect clip_rect, coords_rect; - lv_area_to_sdl_rect(&t_clip, &clip_rect); - lv_area_to_sdl_rect(&t_coords, &coords_rect); - - SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); - - if(radius > 0) { - draw_img_rounded(ctx, texture, header, draw_dsc, &t_coords, &t_clip, radius); - } - else { - draw_img_simple(ctx, texture, header, draw_dsc, &t_coords, &t_clip); - } - - lv_draw_sdl_composite_end(ctx, &apply_area, draw_dsc->blend_mode); - - if(!texture_in_cache) { - LV_LOG_WARN("Texture is not cached, this will impact performance."); - if(!header->managed) { - SDL_DestroyTexture(texture); - } - lv_mem_free(header); - } - - return LV_RES_OK; -} - -static void calc_draw_part(SDL_Texture * texture, const lv_draw_sdl_img_header_t * header, const lv_area_t * coords, - const lv_area_t * clip, SDL_Rect * clipped_src, SDL_Rect * clipped_dst) -{ - double x = 0, y = 0, w, h; - if(SDL_RectEmpty(&header->rect)) { - Uint32 format = 0; - int access = 0, tw, th; - SDL_QueryTexture(texture, &format, &access, &tw, &th); - w = tw; - h = th; - } - else { - x = header->rect.x; - y = header->rect.y; - w = header->rect.w; - h = header->rect.h; - } - if(clip) { - lv_area_t clipped_area; - _lv_area_intersect(&clipped_area, coords, clip); - lv_area_to_sdl_rect(&clipped_area, clipped_dst); - } - else { - lv_area_to_sdl_rect(coords, clipped_dst); - } - lv_coord_t coords_w = lv_area_get_width(coords), coords_h = lv_area_get_height(coords); - clipped_src->x = (int)(x + (clipped_dst->x - coords->x1) * w / coords_w); - clipped_src->y = (int)(y + (clipped_dst->y - coords->y1) * h / coords_h); - clipped_src->w = (int)(w - (coords_w - clipped_dst->w) * w / coords_w); - clipped_src->h = (int)(h - (coords_h - clipped_dst->h) * h / coords_h); -} - -bool lv_draw_sdl_img_load_texture(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_cache_key_head_img_t * key, size_t key_size, - const void * src, int32_t frame_id, SDL_Texture ** texture, - lv_draw_sdl_img_header_t ** header, bool * texture_in_cache) -{ - _lv_img_cache_entry_t * cdsc = _lv_img_cache_open(src, lv_color_white(), frame_id); - lv_draw_sdl_cache_flag_t tex_flags = 0; - SDL_Rect rect; - SDL_memset(&rect, 0, sizeof(SDL_Rect)); - if(cdsc) { - lv_img_decoder_dsc_t * dsc = &cdsc->dec_dsc; - if(dsc->user_data && SDL_memcmp(dsc->user_data, LV_DRAW_SDL_DEC_DSC_TEXTURE_HEAD, 8) == 0) { - lv_draw_sdl_dec_dsc_userdata_t * ptr = (lv_draw_sdl_dec_dsc_userdata_t *) dsc->user_data; - *texture = ptr->texture; - rect = ptr->rect; - if(ptr->texture_managed) { - tex_flags |= LV_DRAW_SDL_CACHE_FLAG_MANAGED; - } - ptr->texture_referenced = true; - } - else { - *texture = upload_img_texture(ctx->renderer, dsc); - } -#if LV_IMG_CACHE_DEF_SIZE == 0 - lv_img_decoder_close(dsc); -#endif - } - if(texture && cdsc) { - *header = lv_mem_alloc(sizeof(lv_draw_sdl_img_header_t)); - SDL_memcpy(&(*header)->base, &cdsc->dec_dsc.header, sizeof(lv_img_header_t)); - (*header)->rect = rect; - (*header)->managed = (tex_flags & LV_DRAW_SDL_CACHE_FLAG_MANAGED) != 0; - *texture_in_cache = lv_draw_sdl_texture_cache_put_advanced(ctx, key, key_size, *texture, *header, SDL_free, - tex_flags); - return true; - } - else { - *texture_in_cache = lv_draw_sdl_texture_cache_put(ctx, key, key_size, NULL); - return false; - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static SDL_Texture * upload_img_texture(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc) -{ - if(!dsc->img_data) { - return upload_img_texture_fallback(renderer, dsc); - } - bool chroma_keyed = dsc->header.cf == (uint32_t) LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED; - int h = (int) dsc->header.h; - int w = (int) dsc->header.w; - void * data = (void *) dsc->img_data; - Uint32 rmask = 0x00FF0000; - Uint32 gmask = 0x0000FF00; - Uint32 bmask = 0x000000FF; - Uint32 amask = 0xFF000000; - if(chroma_keyed) { - amask = 0x00; - } - SDL_Surface * surface = SDL_CreateRGBSurfaceFrom(data, w, h, LV_COLOR_DEPTH, w * LV_COLOR_DEPTH / 8, - rmask, gmask, bmask, amask); - SDL_SetColorKey(surface, chroma_keyed, lv_color_to32(LV_COLOR_CHROMA_KEY)); - SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface); - SDL_FreeSurface(surface); - return texture; -} - -static SDL_Texture * upload_img_texture_fallback(SDL_Renderer * renderer, lv_img_decoder_dsc_t * dsc) -{ - lv_coord_t h = (lv_coord_t) dsc->header.h; - lv_coord_t w = (lv_coord_t) dsc->header.w; - uint8_t * data = lv_mem_buf_get(w * h * sizeof(lv_color_t)); - for(lv_coord_t y = 0; y < h; y++) { - lv_img_decoder_read_line(dsc, 0, y, w, &data[y * w * sizeof(lv_color_t)]); - } - Uint32 rmask = 0x00FF0000; - Uint32 gmask = 0x0000FF00; - Uint32 bmask = 0x000000FF; - Uint32 amask = 0xFF000000; - SDL_Surface * surface = SDL_CreateRGBSurfaceFrom(data, w, h, LV_COLOR_DEPTH, w * LV_COLOR_DEPTH / 8, - rmask, gmask, bmask, amask); - SDL_SetColorKey(surface, SDL_TRUE, lv_color_to32(LV_COLOR_CHROMA_KEY)); - SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface); - SDL_FreeSurface(surface); - lv_mem_buf_release(data); - return texture; -} - -/** - * Check if there is only one radius mask - * @param radius Set to radius value if the only mask is a radius mask - * @return true if the only mask is a radius mask - */ -static bool check_mask_simple_radius(const lv_area_t * coords, lv_coord_t * radius) -{ - if(lv_draw_mask_get_cnt() != 1) return false; - for(uint8_t i = 0; i < _LV_MASK_MAX_NUM; i++) { - _lv_draw_mask_common_dsc_t * param = LV_GC_ROOT(_lv_draw_mask_list[i]).param; - if(param->type == LV_DRAW_MASK_TYPE_RADIUS) { - lv_draw_mask_radius_param_t * rparam = (lv_draw_mask_radius_param_t *) param; - if(rparam->cfg.outer) return false; - if(!_lv_area_is_equal(&rparam->cfg.rect, coords)) return false; - *radius = rparam->cfg.radius; - return true; - } - } - return false; -} - -static void draw_img_simple(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header, - const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip) -{ - apply_recolor_opa(texture, draw_dsc); - SDL_Point pivot = {.x = draw_dsc->pivot.x, .y = draw_dsc->pivot.y}; - - /*Image needs to be rotated, so we have to use clip rect which is slower*/ - if(draw_dsc->angle != 0) { - /* No radius, set clip here */ - SDL_Rect clip_rect; - lv_area_to_sdl_rect(clip, &clip_rect); - SDL_RenderSetClipRect(ctx->renderer, &clip_rect); - } - SDL_Rect src_rect, dst_rect; - calc_draw_part(texture, header, coords, clip, &src_rect, &dst_rect); - SDL_RenderCopyEx(ctx->renderer, texture, &src_rect, &dst_rect, draw_dsc->angle, &pivot, SDL_FLIP_NONE); - if(draw_dsc->angle != 0) { - SDL_RenderSetClipRect(ctx->renderer, NULL); - } -} - - -static void draw_img_rounded(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, const lv_draw_sdl_img_header_t * header, - const lv_draw_img_dsc_t * draw_dsc, const lv_area_t * coords, const lv_area_t * clip, - lv_coord_t radius) -{ - const int w = lv_area_get_width(coords), h = lv_area_get_height(coords); - lv_coord_t real_radius = LV_MIN3(radius, w, h); - bool frag_in_cache = false; - SDL_Texture * frag = img_rounded_frag_obtain(ctx, texture, header, w, h, real_radius, &frag_in_cache); - apply_recolor_opa(frag, draw_dsc); - lv_draw_sdl_rect_bg_frag_draw_corners(ctx, frag, real_radius, coords, clip, true); - - apply_recolor_opa(texture, draw_dsc); - - SDL_Rect src_rect, dst_rect; - /* Draw 3 parts */ - lv_area_t clip_tmp, part; - calc_draw_part(texture, header, coords, NULL, &src_rect, &dst_rect); - for(int i = w > h ? ROUNDED_IMG_PART_LEFT : ROUNDED_IMG_PART_TOP, j = i + 3; i <= j; i++) { - switch(i) { - case ROUNDED_IMG_PART_LEFT: - lv_area_set(&part, coords->x1, coords->y1 + radius, coords->x1 + radius - 1, coords->y2 - radius); - break; - case ROUNDED_IMG_PART_HCENTER: - lv_area_set(&part, coords->x1 + radius, coords->y1, coords->x2 - radius, coords->y2); - break; - case ROUNDED_IMG_PART_RIGHT: - lv_area_set(&part, coords->x2 - radius + 1, coords->y1 + radius, coords->x2, coords->y2 - radius); - break; - case ROUNDED_IMG_PART_TOP: - lv_area_set(&part, coords->x1 + radius, coords->y1, coords->x2 - radius, coords->y1 + radius - 1); - break; - case ROUNDED_IMG_PART_VCENTER: - lv_area_set(&part, coords->x1 + radius, coords->y2 - radius + 1, coords->x2 - radius, coords->y2); - break; - case ROUNDED_IMG_PART_BOTTOM: - lv_area_set(&part, coords->x1, coords->y1 + radius, coords->x2, coords->y2 - radius); - break; - default: - break; - } - if(!_lv_area_intersect(&clip_tmp, &part, clip)) continue; - SDL_Rect clip_rect; - lv_area_to_sdl_rect(&clip_tmp, &clip_rect); - SDL_RenderSetClipRect(ctx->renderer, &clip_rect); - SDL_RenderCopy(ctx->renderer, texture, &src_rect, &dst_rect); - } - SDL_RenderSetClipRect(ctx->renderer, NULL); - - if(!frag_in_cache) { - LV_LOG_WARN("Texture is not cached, this will impact performance."); - SDL_DestroyTexture(frag); - } -} - -static void apply_recolor_opa(SDL_Texture * texture, const lv_draw_img_dsc_t * draw_dsc) -{ - if(draw_dsc->recolor_opa > LV_OPA_TRANSP) { - /* Draw with mixed recolor */ - lv_color_t recolor = lv_color_mix(draw_dsc->recolor, lv_color_white(), draw_dsc->recolor_opa); - SDL_SetTextureColorMod(texture, recolor.ch.red, recolor.ch.green, recolor.ch.blue); - } - else { - /* Draw with no recolor */ - SDL_SetTextureColorMod(texture, 0xFF, 0xFF, 0xFF); - } - SDL_SetTextureAlphaMod(texture, draw_dsc->opa); -} - -static SDL_Texture * img_rounded_frag_obtain(lv_draw_sdl_ctx_t * ctx, SDL_Texture * texture, - const lv_draw_sdl_img_header_t * header, int w, int h, lv_coord_t radius, - bool * in_cache) -{ - lv_draw_img_rounded_key_t key = rounded_key_create(texture, w, h, radius); - bool mask_frag_in_cache = false; - SDL_Texture * mask_frag = lv_draw_sdl_rect_bg_frag_obtain(ctx, radius, &mask_frag_in_cache); - SDL_Texture * img_frag = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL); - if(img_frag == NULL) { - const lv_coord_t full_frag_size = radius * 2 + 3; - img_frag = SDL_CreateTexture(ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, SDL_TEXTUREACCESS_TARGET, - full_frag_size, full_frag_size); - SDL_assert(img_frag); - SDL_SetTextureBlendMode(img_frag, SDL_BLENDMODE_BLEND); - SDL_Texture * old_target = SDL_GetRenderTarget(ctx->renderer); - SDL_SetRenderTarget(ctx->renderer, img_frag); - SDL_SetRenderDrawColor(ctx->renderer, 0, 0, 0, 0); - /* SDL_RenderClear is not working properly, so we overwrite the target with solid color */ - SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_NONE); - SDL_RenderFillRect(ctx->renderer, NULL); - SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND); - - lv_area_t coords = {0, 0, w - 1, h - 1}; - lv_area_t frag_coords = {0, 0, full_frag_size - 1, full_frag_size - 1}; - lv_draw_sdl_rect_bg_frag_draw_corners(ctx, mask_frag, radius, &frag_coords, NULL, false); - - SDL_SetTextureAlphaMod(texture, 0xFF); - SDL_SetTextureColorMod(texture, 0xFF, 0xFF, 0xFF); -#if LV_GPU_SDL_CUSTOM_BLEND_MODE - SDL_BlendMode blend_mode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ZERO, - SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_DST_ALPHA, - SDL_BLENDFACTOR_ZERO, SDL_BLENDOPERATION_ADD); - SDL_SetTextureBlendMode(texture, blend_mode); -#else - SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_MOD); -#endif - SDL_Rect srcrect, cliprect, dstrect = {0, 0, radius, radius}; - - cliprect.w = cliprect.h = radius; - for(int i = 0; i <= ROUNDED_IMG_CORNER_BOTTOM_LEFT; i++) { - switch(i) { - case ROUNDED_IMG_CORNER_TOP_LEFT: - cliprect.x = 0; - cliprect.y = 0; - lv_area_align(&frag_coords, &coords, LV_ALIGN_TOP_LEFT, 0, 0); - break; - case ROUNDED_IMG_CORNER_TOP_RIGHT: - cliprect.x = full_frag_size - radius; - cliprect.y = 0; - lv_area_align(&frag_coords, &coords, LV_ALIGN_TOP_RIGHT, 0, 0); - break; - case ROUNDED_IMG_CORNER_BOTTOM_RIGHT: - cliprect.x = full_frag_size - radius; - cliprect.y = full_frag_size - radius; - lv_area_align(&frag_coords, &coords, LV_ALIGN_BOTTOM_RIGHT, 0, 0); - break; - case ROUNDED_IMG_CORNER_BOTTOM_LEFT: - cliprect.x = 0; - cliprect.y = full_frag_size - radius; - lv_area_align(&frag_coords, &coords, LV_ALIGN_BOTTOM_LEFT, 0, 0); - break; - default: - break; - } - calc_draw_part(texture, header, &coords, NULL, &srcrect, &dstrect); - SDL_RenderSetClipRect(ctx->renderer, &cliprect); - SDL_RenderCopy(ctx->renderer, texture, &srcrect, &dstrect); - } - SDL_RenderSetClipRect(ctx->renderer, NULL); - - SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); - - SDL_SetRenderTarget(ctx->renderer, old_target); - *in_cache = lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), img_frag); - } - else { - *in_cache = true; - } - if(!mask_frag_in_cache) { - LV_LOG_WARN("Texture is not cached, this will impact performance."); - SDL_DestroyTexture(mask_frag); - } - return img_frag; -} - -static lv_draw_img_rounded_key_t rounded_key_create(const SDL_Texture * texture, lv_coord_t w, lv_coord_t h, - lv_coord_t radius) -{ - lv_draw_img_rounded_key_t key; - SDL_memset(&key, 0, sizeof(key)); - key.magic = LV_GPU_CACHE_KEY_MAGIC_IMG_ROUNDED_CORNERS; - key.texture = texture; - key.w = w; - key.h = h; - key.radius = radius; - return key; -} - -#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_img.h b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_img.h deleted file mode 100644 index 6233913d8..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_img.h +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @file lv_draw_sdl_img.h - * - */ - -#ifndef LV_DRAW_SDL_IMG_H -#define LV_DRAW_SDL_IMG_H - - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include LV_GPU_SDL_INCLUDE_PATH - -#include "../lv_draw.h" - -#include "lv_draw_sdl_texture_cache.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct lv_draw_sdl_img_header_t { - lv_img_header_t base; - SDL_Rect rect; - bool managed; -} lv_draw_sdl_img_header_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/*====================== - * Add/remove functions - *=====================*/ - -/*===================== - * Setter functions - *====================*/ - -/*===================== - * Getter functions - *====================*/ - -/*===================== - * Other functions - *====================*/ -/** - * - * @param ctx Drawing context - * @param key Texture cache key - * @param key_size Size of texture cache key - * @param src Image source pointer - * @param frame_id Frame ID for animated image - * @param texture Texture for render - * @param header Header also holds sdl image info - * @param texture_in_cache Whether the texture has been put in the cache. Please note for managed texture, - * this will be false too. So you'll need to check header.managed too. - * @return Whether the image has been loaded successfully - */ -bool lv_draw_sdl_img_load_texture(lv_draw_sdl_ctx_t * ctx, lv_draw_sdl_cache_key_head_img_t * key, size_t key_size, - const void * src, int32_t frame_id, SDL_Texture ** texture, - lv_draw_sdl_img_header_t ** header, bool * texture_in_cache); -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_GPU_SDL*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_SDL_IMG_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_label.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_label.c deleted file mode 100644 index d043c510b..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_label.c +++ /dev/null @@ -1,189 +0,0 @@ -/** - * @file lv_draw_sdl_label.c - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include LV_GPU_SDL_INCLUDE_PATH - -#include "../lv_draw_label.h" -#include "../../misc/lv_utils.h" - -#include "lv_draw_sdl_utils.h" -#include "lv_draw_sdl_texture_cache.h" -#include "lv_draw_sdl_composite.h" -#include "lv_draw_sdl_layer.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - lv_sdl_cache_key_magic_t magic; - const lv_font_t * font_p; - uint32_t letter; -} lv_font_glyph_key_t; - -/********************** - * STATIC PROTOTYPES - **********************/ - -static lv_font_glyph_key_t font_key_glyph_create(const lv_font_t * font_p, uint32_t letter); - - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void lv_draw_sdl_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p, - uint32_t letter) -{ - const lv_area_t * clip_area = draw_ctx->clip_area; - const lv_font_t * font_p = dsc->font; - lv_opa_t opa = dsc->opa; - lv_color_t color = dsc->color; - if(opa < LV_OPA_MIN) return; - if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; - - if(font_p == NULL) { - LV_LOG_WARN("lv_draw_letter: font is NULL"); - return; - } - - lv_font_glyph_dsc_t g; - bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0'); - if(g_ret == false) { - /*Add warning if the dsc is not found - *but do not print warning for non printable ASCII chars (e.g. '\n')*/ - if(letter >= 0x20 && - letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/ - letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/ - LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%X", letter); - - /* draw placeholder */ - lv_area_t glyph_coords; - lv_draw_rect_dsc_t glyph_dsc; - lv_coord_t begin_x = pos_p->x + g.ofs_x; - lv_coord_t begin_y = pos_p->y + g.ofs_y; - lv_area_set(&glyph_coords, begin_x, begin_y, begin_x + g.box_w, begin_y + g.box_h); - lv_draw_rect_dsc_init(&glyph_dsc); - glyph_dsc.bg_opa = LV_OPA_MIN; - glyph_dsc.outline_opa = LV_OPA_MIN; - glyph_dsc.shadow_opa = LV_OPA_MIN; - glyph_dsc.bg_img_opa = LV_OPA_MIN; - glyph_dsc.border_color = dsc->color; - glyph_dsc.border_width = 1; - draw_ctx->draw_rect(draw_ctx, &glyph_dsc, &glyph_coords); - } - return; - } - - /*Don't draw anything if the character is empty. E.g. space*/ - if((g.box_h == 0) || (g.box_w == 0)) return; - - int32_t pos_x = pos_p->x + g.ofs_x; - int32_t pos_y = pos_p->y + (font_p->line_height - font_p->base_line) - g.box_h - g.ofs_y; - - const lv_area_t letter_area = {pos_x, pos_y, pos_x + g.box_w - 1, pos_y + g.box_h - 1}; - lv_area_t draw_area; - - /*If the letter is completely out of mask don't draw it*/ - if(!_lv_area_intersect(&draw_area, &letter_area, clip_area)) { - return; - } - - lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx; - SDL_Renderer * renderer = ctx->renderer; - - lv_font_glyph_key_t glyph_key = font_key_glyph_create(font_p, letter); - bool glyph_found = false; - SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &glyph_key, sizeof(glyph_key), &glyph_found); - bool in_cache = false; - if(!glyph_found) { - if(g.resolved_font) { - font_p = g.resolved_font; - } - const uint8_t * bmp = lv_font_get_glyph_bitmap(font_p, letter); - uint8_t * buf = lv_mem_alloc(g.box_w * g.box_h); - lv_sdl_to_8bpp(buf, bmp, g.box_w, g.box_h, g.box_w, g.bpp); - SDL_Surface * mask = lv_sdl_create_opa_surface(buf, g.box_w, g.box_h, g.box_w); - texture = SDL_CreateTextureFromSurface(renderer, mask); - SDL_FreeSurface(mask); - lv_mem_free(buf); - in_cache = lv_draw_sdl_texture_cache_put(ctx, &glyph_key, sizeof(glyph_key), texture); - } - else { - in_cache = true; - } - if(!texture) { - return; - } - - lv_area_t t_letter = letter_area, t_clip = *clip_area, apply_area; - bool has_composite = lv_draw_sdl_composite_begin(ctx, &letter_area, clip_area, NULL, dsc->blend_mode, &t_letter, - &t_clip, &apply_area); - - lv_draw_sdl_transform_areas_offset(ctx, has_composite, &apply_area, &t_letter, &t_clip); - - /*If the letter is completely out of mask don't draw it*/ - if(!_lv_area_intersect(&draw_area, &t_letter, &t_clip)) { - if(!in_cache) { - LV_LOG_WARN("Texture is not cached, this will impact performance."); - SDL_DestroyTexture(texture); - } - return; - } - SDL_Rect srcrect, dstrect; - lv_area_to_sdl_rect(&draw_area, &dstrect); - srcrect.x = draw_area.x1 - t_letter.x1; - srcrect.y = draw_area.y1 - t_letter.y1; - srcrect.w = dstrect.w; - srcrect.h = dstrect.h; - SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); - SDL_SetTextureAlphaMod(texture, opa); - SDL_SetTextureColorMod(texture, color.ch.red, color.ch.green, color.ch.blue); - SDL_RenderCopy(renderer, texture, &srcrect, &dstrect); - - lv_draw_sdl_composite_end(ctx, &apply_area, dsc->blend_mode); - - if(!in_cache) { - LV_LOG_WARN("Texture is not cached, this will impact performance."); - SDL_DestroyTexture(texture); - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static lv_font_glyph_key_t font_key_glyph_create(const lv_font_t * font_p, uint32_t letter) -{ - lv_font_glyph_key_t key; - /* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */ - SDL_memset(&key, 0, sizeof(key)); - key.magic = LV_GPU_CACHE_KEY_MAGIC_FONT_GLYPH; - key.font_p = font_p; - key.letter = letter; - return key; -} - -#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_layer.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_layer.c deleted file mode 100644 index d517636d9..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_layer.c +++ /dev/null @@ -1,147 +0,0 @@ -/** - * @file lv_draw_sdl_refr.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include "../../core/lv_refr.h" - -#include "lv_draw_sdl.h" -#include "lv_draw_sdl_priv.h" -#include "lv_draw_sdl_composite.h" -#include "lv_draw_sdl_utils.h" -#include "lv_draw_sdl_layer.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_draw_layer_ctx_t * lv_draw_sdl_layer_init(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx, - lv_draw_layer_flags_t flags) -{ - lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx; - SDL_Renderer * renderer = ctx->renderer; - - lv_draw_sdl_layer_ctx_t * transform_ctx = (lv_draw_sdl_layer_ctx_t *) layer_ctx; - - transform_ctx->flags = flags; - transform_ctx->orig_target = SDL_GetRenderTarget(renderer); - - lv_coord_t target_w = lv_area_get_width(&layer_ctx->area_full); - lv_coord_t target_h = lv_area_get_height(&layer_ctx->area_full); - - enum lv_draw_sdl_composite_texture_id_t texture_id = LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_TRANSFORM0 + - ctx->internals->transform_count; - transform_ctx->target = lv_draw_sdl_composite_texture_obtain(ctx, texture_id, target_w, target_h, - &transform_ctx->target_in_cache); - transform_ctx->target_rect.x = 0; - transform_ctx->target_rect.y = 0; - transform_ctx->target_rect.w = target_w; - transform_ctx->target_rect.h = target_h; - - layer_ctx->max_row_with_alpha = target_h; - layer_ctx->max_row_with_no_alpha = target_h; - - SDL_SetTextureBlendMode(transform_ctx->target, SDL_BLENDMODE_BLEND); - SDL_SetRenderTarget(renderer, transform_ctx->target); - - /* SDL_RenderClear is not working properly, so we overwrite the target with solid color */ - SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE); - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); - SDL_RenderFillRect(renderer, NULL); - SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); - - /* Set proper drawing context for transform layer */ - ctx->internals->transform_count += 1; - draw_ctx->buf_area = &layer_ctx->area_full; - draw_ctx->clip_area = &layer_ctx->area_full; - - return layer_ctx; -} - -void lv_draw_sdl_layer_blend(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx, - const lv_draw_img_dsc_t * draw_dsc) -{ - lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx; - lv_draw_sdl_layer_ctx_t * transform_ctx = (lv_draw_sdl_layer_ctx_t *) layer_ctx; - - SDL_Renderer * renderer = ctx->renderer; - - SDL_Rect trans_rect; - - if(transform_ctx->flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) { - lv_area_zoom_to_sdl_rect(&layer_ctx->area_act, &trans_rect, draw_dsc->zoom, &draw_dsc->pivot); - } - else { - lv_area_zoom_to_sdl_rect(&layer_ctx->area_full, &trans_rect, draw_dsc->zoom, &draw_dsc->pivot); - } - - SDL_SetRenderTarget(renderer, transform_ctx->orig_target); - - /*Render off-screen texture, transformed*/ - SDL_Rect clip_rect; - lv_area_to_sdl_rect(layer_ctx->original.clip_area, &clip_rect); - SDL_Point center = {.x = draw_dsc->pivot.x, .y = draw_dsc->pivot.y}; - SDL_RenderSetClipRect(renderer, &clip_rect); - SDL_SetTextureAlphaMod(transform_ctx->target, draw_dsc->opa); - SDL_RenderCopyEx(renderer, transform_ctx->target, &transform_ctx->target_rect, &trans_rect, - draw_dsc->angle, ¢er, SDL_FLIP_NONE); - SDL_RenderSetClipRect(renderer, NULL); -} - -void lv_draw_sdl_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx) -{ - lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx; - lv_draw_sdl_layer_ctx_t * transform_ctx = (lv_draw_sdl_layer_ctx_t *) layer_ctx; - if(!transform_ctx->target_in_cache && transform_ctx->target != NULL) { - LV_LOG_WARN("Texture is not cached, this will impact performance."); - SDL_DestroyTexture(transform_ctx->target); - } - ctx->internals->transform_count -= 1; -} - -void lv_draw_sdl_transform_areas_offset(lv_draw_sdl_ctx_t * ctx, bool has_composite, lv_area_t * apply_area, - lv_area_t * coords, lv_area_t * clip) -{ - if(ctx->internals->transform_count == 0) { - return; - } - lv_area_t * area = ctx->base_draw.buf_area; - lv_area_move(coords, -area->x1, -area->y1); - lv_area_move(clip, -area->x1, -area->y1); - if(has_composite) { - lv_area_move(apply_area, -area->x1, -area->y1); - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_layer.h b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_layer.h deleted file mode 100644 index f6aa66867..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_layer.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @file lv_draw_sdl_refr.h - * - */ - -#ifndef LV_TEMPL_H -#define LV_TEMPL_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "lv_draw_sdl.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ -typedef struct _lv_draw_sdl_layer_ctx_t { - lv_draw_layer_ctx_t base; - - SDL_Texture * orig_target; - SDL_Texture * target; - SDL_Rect target_rect; - bool target_in_cache; - lv_draw_layer_flags_t flags; -} lv_draw_sdl_layer_ctx_t; -/********************** - * GLOBAL PROTOTYPES - **********************/ - -lv_draw_layer_ctx_t * lv_draw_sdl_layer_init(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx, - lv_draw_layer_flags_t flags); - -void lv_draw_sdl_layer_blend(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * transform_ctx, - const lv_draw_img_dsc_t * draw_dsc); - -void lv_draw_sdl_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx); - -void lv_draw_sdl_transform_areas_offset(lv_draw_sdl_ctx_t * ctx, bool has_composite, lv_area_t * apply_area, - lv_area_t * coords, lv_area_t * clip); -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_TEMPL_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_line.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_line.c deleted file mode 100644 index 204e1a3d8..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_line.c +++ /dev/null @@ -1,157 +0,0 @@ -/** - * @file lv_draw_sdl_line.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include "lv_draw_sdl.h" -#include "lv_draw_sdl_utils.h" -#include "lv_draw_sdl_texture_cache.h" -#include "lv_draw_sdl_composite.h" -#include "lv_draw_sdl_mask.h" - -/********************* - * DEFINES - *********************/ -#define ROUND_START 0x01 -#define ROUND_END 0x02 -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - lv_sdl_cache_key_magic_t magic; - lv_coord_t length; - lv_coord_t width; - uint8_t round; -} lv_draw_line_key_t; - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -static lv_draw_line_key_t line_key_create(const lv_draw_line_dsc_t * dsc, lv_coord_t length); - -static SDL_Texture * line_texture_create(lv_draw_sdl_ctx_t * sdl_ctx, const lv_draw_line_dsc_t * dsc, - lv_coord_t length); - -/********************** - * GLOBAL FUNCTIONS - **********************/ -void lv_draw_sdl_draw_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1, - const lv_point_t * point2, bool * in_cache) -{ - lv_draw_sdl_ctx_t * sdl_ctx = (lv_draw_sdl_ctx_t *) draw_ctx; - SDL_Renderer * renderer = sdl_ctx->renderer; - lv_coord_t x1 = point1->x, x2 = point2->x, y1 = point1->y, y2 = point2->y; - double length = SDL_sqrt(SDL_pow(x2 - x1, 2) + SDL_pow(y2 - y1, 2)); - if(length - (long) length > 0.5) { - length = (long) length + 1; - } - - double angle = SDL_atan2(y2 - y1, x2 - x1) * 180 / M_PI; - lv_draw_line_key_t key = line_key_create(dsc, (lv_coord_t) length); - SDL_Texture * texture = lv_draw_sdl_texture_cache_get(sdl_ctx, &key, sizeof(key), NULL); - if(!texture) { - texture = line_texture_create(sdl_ctx, dsc, (lv_coord_t) length); - *in_cache = lv_draw_sdl_texture_cache_put(sdl_ctx, &key, sizeof(key), texture); - } - - lv_area_t coords = {x1, y1, x2, y2}; - const lv_area_t * clip = draw_ctx->clip_area; - - SDL_Rect coords_r, clip_r; - lv_area_to_sdl_rect(&coords, &coords_r); - lv_area_to_sdl_rect(clip, &clip_r); - - lv_area_t t_coords = coords, t_clip = *clip, apply_area; - lv_area_t extension = {dsc->width / 2, dsc->width / 2, dsc->width / 2, dsc->width / 2}; - lv_draw_sdl_composite_begin(sdl_ctx, &coords, clip, &extension, dsc->blend_mode, &t_coords, &t_clip, - &apply_area); - - SDL_Color color; - lv_color_to_sdl_color(&dsc->color, &color); - - SDL_SetTextureColorMod(texture, color.r, color.g, color.b); - SDL_SetTextureAlphaMod(texture, dsc->opa); - SDL_Rect srcrect = {0, 0, (int) length + dsc->width + 2, dsc->width + 2}, - dstrect = {t_coords.x1 - 1 - dsc->width / 2, t_coords.y1 - 1, srcrect.w, srcrect.h}; - SDL_Point center = {1 + dsc->width / 2, 1 + dsc->width / 2}; - - SDL_Rect clip_rect; - lv_area_to_sdl_rect(&t_clip, &clip_rect); - if(!SDL_RectEquals(&clip_rect, &dstrect) || angle != 0) { - SDL_RenderSetClipRect(renderer, &clip_rect); - } - SDL_RenderCopyEx(renderer, texture, &srcrect, &dstrect, angle, ¢er, 0); - SDL_RenderSetClipRect(renderer, NULL); - - lv_draw_sdl_composite_end(sdl_ctx, &apply_area, dsc->blend_mode); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static lv_draw_line_key_t line_key_create(const lv_draw_line_dsc_t * dsc, lv_coord_t length) -{ - lv_draw_line_key_t key; - lv_memset_00(&key, sizeof(lv_draw_line_key_t)); - key.magic = LV_GPU_CACHE_KEY_MAGIC_LINE; - key.length = length; - key.width = dsc->width; - key.round = (dsc->round_start ? ROUND_START : 0) | (dsc->round_end ? ROUND_END : 0); - return key; -} - -static SDL_Texture * line_texture_create(lv_draw_sdl_ctx_t * sdl_ctx, const lv_draw_line_dsc_t * dsc, lv_coord_t length) -{ - SDL_Texture * texture = SDL_CreateTexture(sdl_ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, SDL_TEXTUREACCESS_TARGET, - length + dsc->width + 2, dsc->width + 2); - SDL_Texture * target = SDL_GetRenderTarget(sdl_ctx->renderer); - SDL_SetRenderTarget(sdl_ctx->renderer, texture); - SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); - SDL_SetRenderDrawColor(sdl_ctx->renderer, 0xFF, 0xFF, 0xFF, 0x0); - /* SDL_RenderClear is not working properly, so we overwrite the target with solid color */ - SDL_SetRenderDrawBlendMode(sdl_ctx->renderer, SDL_BLENDMODE_NONE); - SDL_RenderFillRect(sdl_ctx->renderer, NULL); - SDL_SetRenderDrawBlendMode(sdl_ctx->renderer, SDL_BLENDMODE_BLEND); - SDL_SetRenderDrawColor(sdl_ctx->renderer, 0xFF, 0xFF, 0xFF, 0xFF); - SDL_Rect line_rect = {1 + dsc->width / 2, 1, length, dsc->width}; - SDL_RenderFillRect(sdl_ctx->renderer, &line_rect); - if(dsc->round_start || dsc->round_end) { - lv_draw_mask_radius_param_t param; - lv_area_t round_area = {0, 0, dsc->width - 1, dsc->width - 1}; - lv_draw_mask_radius_init(¶m, &round_area, LV_RADIUS_CIRCLE, false); - - int16_t mask_id = lv_draw_mask_add(¶m, NULL); - SDL_Texture * round_texture = lv_draw_sdl_mask_dump_texture(sdl_ctx->renderer, &round_area, &mask_id, 1); - lv_draw_mask_remove_id(mask_id); - - SDL_Rect round_src = {0, 0, dsc->width, dsc->width}; - SDL_Rect round_dst = {line_rect.x - dsc->width / 2, 1, dsc->width, dsc->width}; - SDL_RenderCopy(sdl_ctx->renderer, round_texture, &round_src, &round_dst); - round_dst.x = line_rect.w + dsc->width / 2; - SDL_RenderCopy(sdl_ctx->renderer, round_texture, &round_src, &round_dst); - SDL_DestroyTexture(round_texture); - } - - SDL_SetRenderTarget(sdl_ctx->renderer, target); - return texture; -} - -#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_mask.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_mask.c deleted file mode 100644 index 7bb5bbb3b..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_mask.c +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @file lv_draw_sdl_mask.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include "../../misc/lv_gc.h" -#include "lv_draw_sdl_mask.h" -#include "lv_draw_sdl_utils.h" - -/********************* - * DEFINES - *********************/ -#ifndef HAVE_SDL_CUSTOM_BLEND_MODE - #define HAVE_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6)) -#endif - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_opa_t * lv_draw_sdl_mask_dump_opa(const lv_area_t * coords, const int16_t * ids, int16_t ids_count) -{ - SDL_assert(coords->x2 >= coords->x1); - SDL_assert(coords->y2 >= coords->y1); - lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords); - lv_opa_t * mask_buf = lv_mem_buf_get(w * h); - for(lv_coord_t y = 0; y < h; y++) { - lv_opa_t * line_buf = &mask_buf[y * w]; - lv_memset_ff(line_buf, w); - lv_coord_t abs_x = (lv_coord_t) coords->x1, abs_y = (lv_coord_t)(y + coords->y1), len = (lv_coord_t) w; - lv_draw_mask_res_t res; - if(ids) { - res = lv_draw_mask_apply_ids(line_buf, abs_x, abs_y, len, ids, ids_count); - } - else { - res = lv_draw_mask_apply(line_buf, abs_x, abs_y, len); - } - if(res == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(line_buf, w); - } - } - return mask_buf; -} - -SDL_Texture * lv_draw_sdl_mask_dump_texture(SDL_Renderer * renderer, const lv_area_t * coords, const int16_t * ids, - int16_t ids_count) -{ - lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords); - lv_opa_t * mask_buf = lv_draw_sdl_mask_dump_opa(coords, ids, ids_count); - SDL_Surface * surface = lv_sdl_create_opa_surface(mask_buf, w, h, w); - lv_mem_buf_release(mask_buf); - SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface); - SDL_FreeSurface(surface); - return texture; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_mask.h b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_mask.h deleted file mode 100644 index a562d73d7..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_mask.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @file lv_draw_sdl_mask.h - * - */ - -#ifndef LV_DRAW_SDL_MASK_H -#define LV_DRAW_SDL_MASK_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ - -#include "../../lv_conf_internal.h" - -#include LV_GPU_SDL_INCLUDE_PATH - -#include "lv_draw_sdl.h" -#include "../../misc/lv_area.h" -#include "../../misc/lv_color.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -lv_opa_t * lv_draw_sdl_mask_dump_opa(const lv_area_t * coords, const int16_t * ids, int16_t ids_count); - -SDL_Texture * lv_draw_sdl_mask_dump_texture(SDL_Renderer * renderer, const lv_area_t * coords, const int16_t * ids, - int16_t ids_count); - - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_SDL_MASK_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_polygon.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_polygon.c deleted file mode 100644 index 68305c7c8..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_polygon.c +++ /dev/null @@ -1,139 +0,0 @@ -/** - * @file lv_draw_sdl_polygon.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include "lv_draw_sdl.h" -#include "lv_draw_sdl_utils.h" -#include "lv_draw_sdl_texture_cache.h" -#include "lv_draw_sdl_composite.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -static void dump_masks(SDL_Texture * texture, const lv_area_t * coords); - -/********************** - * GLOBAL FUNCTIONS - **********************/ -void lv_draw_sdl_polygon(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t * points, - uint16_t point_cnt) -{ - if(point_cnt < 3) return; - if(points == NULL) return; - - lv_draw_mask_polygon_param_t polygon_param; - lv_draw_mask_polygon_init(&polygon_param, points, point_cnt); - - if(polygon_param.cfg.point_cnt < 3) { - lv_draw_mask_free_param(&polygon_param); - return; - } - - lv_area_t poly_coords = {.x1 = LV_COORD_MAX, .y1 = LV_COORD_MAX, .x2 = LV_COORD_MIN, .y2 = LV_COORD_MIN}; - - uint16_t i; - for(i = 0; i < point_cnt; i++) { - poly_coords.x1 = LV_MIN(poly_coords.x1, polygon_param.cfg.points[i].x); - poly_coords.y1 = LV_MIN(poly_coords.y1, polygon_param.cfg.points[i].y); - poly_coords.x2 = LV_MAX(poly_coords.x2, polygon_param.cfg.points[i].x); - poly_coords.y2 = LV_MAX(poly_coords.y2, polygon_param.cfg.points[i].y); - } - - bool is_common; - lv_area_t draw_area; - is_common = _lv_area_intersect(&draw_area, &poly_coords, draw_ctx->clip_area); - if(!is_common) { - lv_draw_mask_free_param(&polygon_param); - return; - } - - lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx; - - int16_t mask_id = lv_draw_mask_add(&polygon_param, NULL); - - lv_coord_t w = lv_area_get_width(&draw_area), h = lv_area_get_height(&draw_area); - bool texture_in_cache = false; - SDL_Texture * texture = lv_draw_sdl_composite_texture_obtain(ctx, LV_DRAW_SDL_COMPOSITE_TEXTURE_ID_STREAM1, w, h, - &texture_in_cache); - SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); - dump_masks(texture, &draw_area); - - lv_draw_mask_remove_id(mask_id); - lv_draw_mask_free_param(&polygon_param); - - SDL_Rect srcrect = {0, 0, w, h}, dstrect; - lv_area_to_sdl_rect(&draw_area, &dstrect); - SDL_Color color; - lv_color_to_sdl_color(&draw_dsc->bg_color, &color); - SDL_SetTextureColorMod(texture, color.r, color.g, color.b); - SDL_SetTextureAlphaMod(texture, draw_dsc->bg_opa); - SDL_RenderCopy(ctx->renderer, texture, &srcrect, &dstrect); - if(!texture_in_cache) { - LV_LOG_WARN("Texture is not cached, this will impact performance."); - SDL_DestroyTexture(texture); - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void dump_masks(SDL_Texture * texture, const lv_area_t * coords) -{ - lv_coord_t w = lv_area_get_width(coords), h = lv_area_get_height(coords); - SDL_assert(w > 0 && h > 0); - SDL_Rect rect = {0, 0, w, h}; - uint8_t * pixels; - int pitch; - if(SDL_LockTexture(texture, &rect, (void **) &pixels, &pitch) != 0) return; - - lv_opa_t * line_buf = lv_mem_buf_get(rect.w); - for(lv_coord_t y = 0; y < rect.h; y++) { - lv_memset_ff(line_buf, rect.w); - lv_coord_t abs_x = (lv_coord_t) coords->x1, abs_y = (lv_coord_t)(y + coords->y1), len = (lv_coord_t) rect.w; - lv_draw_mask_res_t res; - res = lv_draw_mask_apply(line_buf, abs_x, abs_y, len); - if(res == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(&pixels[y * pitch], 4 * rect.w); - } - else if(res == LV_DRAW_MASK_RES_FULL_COVER) { - lv_memset_ff(&pixels[y * pitch], 4 * rect.w); - } - else { - for(int x = 0; x < rect.w; x++) { - uint8_t * pixel = &pixels[y * pitch + x * 4]; - *pixel = line_buf[x]; - pixel[1] = pixel[2] = pixel[3] = 0xFF; - } - } - } - lv_mem_buf_release(line_buf); - SDL_UnlockTexture(texture); -} - -#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_priv.h b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_priv.h deleted file mode 100644 index ffc191b0a..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_priv.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @file lv_draw_sdl_priv.h - * - */ - -#ifndef LV_DRAW_SDL_PRIV_H -#define LV_DRAW_SDL_PRIV_H - - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include LV_GPU_SDL_INCLUDE_PATH - -#include "../lv_draw.h" -#include "../../misc/lv_lru.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct lv_draw_sdl_context_internals_t { - lv_lru_t * texture_cache; - SDL_Texture * mask; - SDL_Texture * composition; - bool composition_cached; - SDL_Texture * target_backup; - uint8_t transform_count; -} lv_draw_sdl_context_internals_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/*====================== - * Add/remove functions - *=====================*/ - -/*===================== - * Setter functions - *====================*/ - -/*===================== - * Getter functions - *====================*/ - -/*===================== - * Other functions - *====================*/ - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_GPU_SDL*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_SDL_PRIV_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_rect.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_rect.c deleted file mode 100644 index 149dcbf67..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_rect.c +++ /dev/null @@ -1,1013 +0,0 @@ -/** - * @file lv_draw_sdl_rect.c - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include "../lv_draw_rect.h" -#include "../lv_draw_img.h" -#include "../lv_draw_label.h" -#include "../lv_draw_mask.h" -#include "../../core/lv_refr.h" -#include "lv_draw_sdl_utils.h" -#include "lv_draw_sdl_texture_cache.h" -#include "lv_draw_sdl_composite.h" -#include "lv_draw_sdl_mask.h" -#include "lv_draw_sdl_stack_blur.h" -#include "lv_draw_sdl_layer.h" - -/********************* - * DEFINES - *********************/ - -#define FRAG_SPACING 3 - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - lv_sdl_cache_key_magic_t magic; - lv_coord_t radius; - lv_coord_t size; -} lv_draw_rect_bg_key_t; - -typedef struct { - lv_sdl_cache_key_magic_t magic; - lv_gradient_stop_t stops[LV_GRADIENT_MAX_STOPS]; - uint8_t stops_count; - lv_grad_dir_t dir; -} lv_draw_rect_grad_strip_key_t; - -typedef struct { - lv_sdl_cache_key_magic_t magic; - lv_gradient_stop_t stops[LV_GRADIENT_MAX_STOPS]; - uint8_t stops_count; - lv_grad_dir_t dir; - lv_coord_t w; - lv_coord_t h; - lv_coord_t radius; -} lv_draw_rect_grad_frag_key_t; - -typedef struct { - lv_sdl_cache_key_magic_t magic; - lv_coord_t radius; - lv_coord_t size; - lv_coord_t blur; -} lv_draw_rect_shadow_key_t; - -typedef struct { - lv_sdl_cache_key_magic_t magic; - lv_coord_t rout, rin; - lv_area_t offsets; -} lv_draw_rect_border_key_t; - -/********************** - * STATIC PROTOTYPES - **********************/ - -static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area, - const lv_draw_rect_dsc_t * dsc); - -static void draw_bg_grad_simple(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area, - const lv_grad_dsc_t * grad, bool blend_mod); - -static void draw_bg_grad_radius(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area, - const lv_draw_rect_dsc_t * dsc); - -static void draw_bg_img(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area, - const lv_draw_rect_dsc_t * dsc); - -static void draw_border(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area, - const lv_draw_rect_dsc_t * dsc); - -static void draw_shadow(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * clip, - const lv_draw_rect_dsc_t * dsc); - -static void draw_outline(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * clip, - const lv_draw_rect_dsc_t * dsc); - -static void draw_border_generic(lv_draw_sdl_ctx_t * ctx, const lv_area_t * outer_area, const lv_area_t * inner_area, - const lv_area_t * clip, lv_coord_t rout, lv_coord_t rin, lv_color_t color, lv_opa_t opa, - lv_blend_mode_t blend_mode); - -static void frag_render_borders(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size, - const lv_area_t * coords, const lv_area_t * clipped, bool full); - -static void frag_render_center(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size, - const lv_area_t * coords, const lv_area_t * clipped, bool full); - -static lv_draw_rect_bg_key_t rect_bg_key_create(lv_coord_t radius, lv_coord_t size); - -static lv_draw_rect_grad_frag_key_t rect_grad_frag_key_create(const lv_grad_dsc_t * grad, lv_coord_t w, lv_coord_t h, - lv_coord_t radius); - -static lv_draw_rect_grad_strip_key_t rect_grad_strip_key_create(const lv_grad_dsc_t * grad); - -static lv_draw_rect_shadow_key_t rect_shadow_key_create(lv_coord_t radius, lv_coord_t size, lv_coord_t blur); - -static lv_draw_rect_border_key_t rect_border_key_create(lv_coord_t rout, lv_coord_t rin, const lv_area_t * outer_area, - const lv_area_t * inner_area); - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ -#define SKIP_BORDER(dsc) ((dsc)->border_opa <= LV_OPA_MIN || (dsc)->border_width == 0 || (dsc)->border_side == LV_BORDER_SIDE_NONE || (dsc)->border_post) -#define SKIP_SHADOW(dsc) ((dsc)->shadow_width == 0 || (dsc)->shadow_opa <= LV_OPA_MIN || ((dsc)->shadow_width == 1 && (dsc)->shadow_spread <= 0 && (dsc)->shadow_ofs_x == 0 && (dsc)->shadow_ofs_y == 0)) -#define SKIP_IMAGE(dsc) ((dsc)->bg_img_src == NULL || (dsc)->bg_img_opa <= LV_OPA_MIN) -#define SKIP_OUTLINE(dsc) ((dsc)->outline_opa <= LV_OPA_MIN || (dsc)->outline_width == 0) - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void lv_draw_sdl_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) -{ - const lv_area_t * clip = draw_ctx->clip_area; - lv_draw_sdl_ctx_t * ctx = (lv_draw_sdl_ctx_t *) draw_ctx; - - lv_area_t extension = {0, 0, 0, 0}; - if(!SKIP_SHADOW(dsc)) { - lv_coord_t ext = (lv_coord_t)(dsc->shadow_spread - dsc->shadow_width / 2 + 1); - extension.x1 = LV_MAX(extension.x1, -dsc->shadow_ofs_x + ext); - extension.x2 = LV_MAX(extension.x2, dsc->shadow_ofs_x + ext); - extension.y1 = LV_MAX(extension.y1, -dsc->shadow_ofs_y + ext); - extension.y2 = LV_MAX(extension.y2, dsc->shadow_ofs_y + ext); - } - if(!SKIP_OUTLINE(dsc)) { - lv_coord_t ext = (lv_coord_t)(dsc->outline_pad - 1 + dsc->outline_width); - extension.x1 = LV_MAX(extension.x1, ext); - extension.x2 = LV_MAX(extension.x2, ext); - extension.y1 = LV_MAX(extension.y1, ext); - extension.y2 = LV_MAX(extension.y2, ext); - } - /* Coords will be translated so coords will start at (0,0) */ - lv_area_t t_coords = *coords, t_clip = *clip, apply_area, t_area; - bool has_composite = lv_draw_sdl_composite_begin(ctx, coords, clip, &extension, dsc->blend_mode, &t_coords, &t_clip, - &apply_area); - - lv_draw_sdl_transform_areas_offset(ctx, has_composite, &apply_area, &t_coords, &t_clip); - - bool has_content = _lv_area_intersect(&t_area, &t_coords, &t_clip); - - SDL_Rect clip_rect; - lv_area_to_sdl_rect(&t_clip, &clip_rect); - draw_shadow(ctx, &t_coords, &t_clip, dsc); - /* Shadows and outlines will also draw in extended area */ - if(has_content) { - draw_bg_color(ctx, &t_coords, &t_area, dsc); - draw_bg_img(ctx, &t_coords, &t_area, dsc); - draw_border(ctx, &t_coords, &t_area, dsc); - } - draw_outline(ctx, &t_coords, &t_clip, dsc); - - lv_draw_sdl_composite_end(ctx, &apply_area, dsc->blend_mode); -} - -SDL_Texture * lv_draw_sdl_rect_bg_frag_obtain(lv_draw_sdl_ctx_t * ctx, lv_coord_t radius, bool * in_cache) -{ - lv_draw_rect_bg_key_t key = rect_bg_key_create(radius, radius); - SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL); - if(texture == NULL) { - lv_area_t coords = {0, 0, radius * 2 - 1, radius * 2 - 1}; - lv_area_t coords_frag = {0, 0, radius - 1, radius - 1}; - lv_draw_mask_radius_param_t mask_rout_param; - lv_draw_mask_radius_init(&mask_rout_param, &coords, radius, false); - int16_t mask_id = lv_draw_mask_add(&mask_rout_param, NULL); - texture = lv_draw_sdl_mask_dump_texture(ctx->renderer, &coords_frag, &mask_id, 1); - SDL_assert(texture != NULL); - lv_draw_mask_remove_id(mask_id); - *in_cache = lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture); - } - else { - *in_cache = true; - } - return texture; -} - -SDL_Texture * lv_draw_sdl_rect_grad_frag_obtain(lv_draw_sdl_ctx_t * ctx, const lv_grad_dsc_t * grad, lv_coord_t w, - lv_coord_t h, lv_coord_t radius, bool * in_cache) -{ - lv_draw_rect_grad_frag_key_t key = rect_grad_frag_key_create(grad, w, h, radius); - SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL); - if(texture == NULL) { - lv_area_t coords = {0, 0, radius * 2 + FRAG_SPACING - 1, radius * 2 + FRAG_SPACING - 1}; - texture = SDL_CreateTexture(ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, SDL_TEXTUREACCESS_TARGET, - lv_area_get_width(&coords), lv_area_get_height(&coords)); - SDL_assert(texture != NULL); - - lv_draw_mask_radius_param_t mask_rout_param; - lv_draw_mask_radius_init(&mask_rout_param, &coords, radius, false); - int16_t mask_id = lv_draw_mask_add(&mask_rout_param, NULL); - SDL_Texture * mask = lv_draw_sdl_mask_dump_texture(ctx->renderer, &coords, &mask_id, 1); - SDL_assert(mask != NULL); - SDL_SetTextureBlendMode(mask, SDL_BLENDMODE_NONE); - lv_draw_mask_remove_id(mask_id); - - SDL_Texture * target_backup = SDL_GetRenderTarget(ctx->renderer); - SDL_SetRenderTarget(ctx->renderer, texture); - SDL_RenderCopy(ctx->renderer, mask, NULL, NULL); - SDL_DestroyTexture(mask); - - lv_area_t blend_coords = {.x1 = 0, .y1 = 0, .x2 = w - 1, .y2 = h - 1}; - lv_area_t draw_area = {.x1 = 0, .y1 = 0, .x2 = radius - 1, .y2 = radius - 1}; - /* Align to top left */ - lv_area_align(&coords, &draw_area, LV_ALIGN_TOP_LEFT, 0, 0); - lv_area_align(&coords, &blend_coords, LV_ALIGN_TOP_LEFT, 0, 0); - draw_bg_grad_simple(ctx, &blend_coords, &draw_area, grad, true); - - /* Align to top right */ - lv_area_align(&coords, &draw_area, LV_ALIGN_TOP_RIGHT, 0, 0); - lv_area_align(&coords, &blend_coords, LV_ALIGN_TOP_RIGHT, 0, 0); - draw_bg_grad_simple(ctx, &blend_coords, &draw_area, grad, true); - - /* Align to bottom right */ - lv_area_align(&coords, &draw_area, LV_ALIGN_BOTTOM_RIGHT, 0, 0); - lv_area_align(&coords, &blend_coords, LV_ALIGN_BOTTOM_RIGHT, 0, 0); - draw_bg_grad_simple(ctx, &blend_coords, &draw_area, grad, true); - - /* Align to bottom left */ - lv_area_align(&coords, &draw_area, LV_ALIGN_BOTTOM_LEFT, 0, 0); - lv_area_align(&coords, &blend_coords, LV_ALIGN_BOTTOM_LEFT, 0, 0); - draw_bg_grad_simple(ctx, &blend_coords, &draw_area, grad, true); - - SDL_SetRenderTarget(ctx->renderer, target_backup); - *in_cache = lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture); - } - else { - *in_cache = true; - } - return texture; -} - -SDL_Texture * lv_draw_sdl_rect_grad_strip_obtain(lv_draw_sdl_ctx_t * ctx, const lv_grad_dsc_t * grad, bool * in_cache) -{ - lv_draw_rect_grad_strip_key_t key = rect_grad_strip_key_create(grad); - SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL); - if(texture == NULL) { - Uint32 amask = 0xFF000000; - Uint32 rmask = 0x00FF0000; - Uint32 gmask = 0x0000FF00; - Uint32 bmask = 0x000000FF; - lv_color_t pixels[256]; - for(int i = 0; i < 256; i++) { - pixels[i] = lv_gradient_calculate(grad, 256, i); - } - int width = grad->dir == LV_GRAD_DIR_VER ? 1 : 256; - int height = grad->dir == LV_GRAD_DIR_VER ? 256 : 1; - SDL_Surface * surface = SDL_CreateRGBSurfaceFrom(pixels, width, height, LV_COLOR_DEPTH, width * LV_COLOR_DEPTH / 8, - rmask, gmask, bmask, amask); - texture = SDL_CreateTextureFromSurface(ctx->renderer, surface); - SDL_assert(texture != NULL); - SDL_FreeSurface(surface); - *in_cache = lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture); - } - else { - *in_cache = true; - } - return texture; -} - -void lv_draw_sdl_rect_bg_frag_draw_corners(lv_draw_sdl_ctx_t * ctx, SDL_Texture * frag, lv_coord_t frag_size, - const lv_area_t * coords, const lv_area_t * clip, bool full) -{ - if(!clip) clip = coords; - lv_area_t corner_area, dst_area; - /* Upper left */ - corner_area.x1 = coords->x1; - corner_area.y1 = coords->y1; - corner_area.x2 = coords->x1 + frag_size - 1; - corner_area.y2 = coords->y1 + frag_size - 1; - if(_lv_area_intersect(&dst_area, &corner_area, clip)) { - SDL_Rect dst_rect; - lv_area_to_sdl_rect(&dst_area, &dst_rect); - - lv_coord_t dw = lv_area_get_width(&dst_area), dh = lv_area_get_height(&dst_area); - lv_coord_t sx = (lv_coord_t)(dst_area.x1 - corner_area.x1), sy = (lv_coord_t)(dst_area.y1 - corner_area.y1); - SDL_Rect src_rect = {sx, sy, dw, dh}; - SDL_RenderCopy(ctx->renderer, frag, &src_rect, &dst_rect); - } - /* Upper right, clip right edge if too big */ - corner_area.x1 = LV_MAX(coords->x2 - frag_size + 1, coords->x1 + frag_size); - corner_area.x2 = coords->x2; - if(_lv_area_intersect(&dst_area, &corner_area, clip)) { - SDL_Rect dst_rect; - lv_area_to_sdl_rect(&dst_area, &dst_rect); - - lv_coord_t dw = lv_area_get_width(&dst_area), dh = lv_area_get_height(&dst_area); - if(full) { - lv_coord_t sx = (lv_coord_t)(dst_area.x1 - corner_area.x1), - sy = (lv_coord_t)(dst_area.y1 - corner_area.y1); - SDL_Rect src_rect = {frag_size + FRAG_SPACING + sx, sy, dw, dh}; - SDL_RenderCopy(ctx->renderer, frag, &src_rect, &dst_rect); - } - else { - SDL_Rect src_rect = {corner_area.x2 - dst_area.x2, dst_area.y1 - corner_area.y1, dw, dh}; - SDL_RenderCopyEx(ctx->renderer, frag, &src_rect, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL); - } - } - /* Lower right, clip bottom edge if too big */ - corner_area.y1 = LV_MAX(coords->y2 - frag_size + 1, coords->y1 + frag_size); - corner_area.y2 = coords->y2; - if(_lv_area_intersect(&dst_area, &corner_area, clip)) { - SDL_Rect dst_rect; - lv_area_to_sdl_rect(&dst_area, &dst_rect); - - lv_coord_t dw = lv_area_get_width(&dst_area), dh = lv_area_get_height(&dst_area); - if(full) { - lv_coord_t sx = (lv_coord_t)(dst_area.x1 - corner_area.x1), - sy = (lv_coord_t)(dst_area.y1 - corner_area.y1); - SDL_Rect src_rect = {frag_size + FRAG_SPACING + sx, frag_size + FRAG_SPACING + sy, dw, dh}; - SDL_RenderCopy(ctx->renderer, frag, &src_rect, &dst_rect); - } - else { - SDL_Rect src_rect = {corner_area.x2 - dst_area.x2, corner_area.y2 - dst_area.y2, dw, dh}; - SDL_RenderCopyEx(ctx->renderer, frag, &src_rect, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL | SDL_FLIP_VERTICAL); - } - } - /* Lower left, right edge should not be clipped */ - corner_area.x1 = coords->x1; - corner_area.x2 = coords->x1 + frag_size - 1; - if(_lv_area_intersect(&dst_area, &corner_area, clip)) { - SDL_Rect dst_rect; - lv_area_to_sdl_rect(&dst_area, &dst_rect); - - lv_coord_t dw = lv_area_get_width(&dst_area), dh = lv_area_get_height(&dst_area); - if(full) { - lv_coord_t sx = (lv_coord_t)(dst_area.x1 - corner_area.x1), - sy = (lv_coord_t)(dst_area.y1 - corner_area.y1); - SDL_Rect src_rect = {sx, frag_size + FRAG_SPACING + sy, dw, dh}; - SDL_RenderCopy(ctx->renderer, frag, &src_rect, &dst_rect); - } - else { - SDL_Rect src_rect = {dst_area.x1 - corner_area.x1, corner_area.y2 - dst_area.y2, dw, dh}; - SDL_RenderCopyEx(ctx->renderer, frag, &src_rect, &dst_rect, 0, NULL, SDL_FLIP_VERTICAL); - } - } -} - - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void draw_bg_color(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area, - const lv_draw_rect_dsc_t * dsc) -{ - if(dsc->bg_opa == 0) { - return; - } - lv_coord_t radius = dsc->radius; - SDL_Color bg_color; - if(dsc->bg_grad.dir == LV_GRAD_DIR_NONE) { - lv_color_to_sdl_color(&dsc->bg_color, &bg_color); - } - else if(dsc->bg_grad.stops_count == 1) { - lv_color_to_sdl_color(&dsc->bg_grad.stops[0].color, &bg_color); - } - else { - if(radius <= 0) { - draw_bg_grad_simple(ctx, coords, draw_area, &dsc->bg_grad, false); - } - else { - draw_bg_grad_radius(ctx, coords, draw_area, dsc); - } - return; - } - if(radius <= 0) { - SDL_Rect rect; - lv_area_to_sdl_rect(draw_area, &rect); - SDL_SetRenderDrawColor(ctx->renderer, bg_color.r, bg_color.g, bg_color.b, dsc->bg_opa); - SDL_SetRenderDrawBlendMode(ctx->renderer, SDL_BLENDMODE_BLEND); - SDL_RenderFillRect(ctx->renderer, &rect); - return; - } - - /*A small texture with a quarter of the rect is enough*/ - lv_coord_t bg_w = lv_area_get_width(coords), bg_h = lv_area_get_height(coords); - lv_coord_t real_radius = LV_MIN3(bg_w / 2, bg_h / 2, radius); - bool texture_in_cache = false; - SDL_Texture * texture = lv_draw_sdl_rect_bg_frag_obtain(ctx, real_radius, &texture_in_cache); - - SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); - SDL_SetTextureAlphaMod(texture, dsc->bg_opa); - SDL_SetTextureColorMod(texture, bg_color.r, bg_color.g, bg_color.b); - lv_draw_sdl_rect_bg_frag_draw_corners(ctx, texture, real_radius, coords, draw_area, false); - frag_render_borders(ctx->renderer, texture, real_radius, coords, draw_area, false); - frag_render_center(ctx->renderer, texture, real_radius, coords, draw_area, false); - - if(!texture_in_cache) { - LV_LOG_WARN("Texture is not cached, this will impact performance."); - SDL_DestroyTexture(texture); - } -} - -static void draw_bg_grad_simple(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area, - const lv_grad_dsc_t * grad, bool blend_mod) -{ - SDL_Rect dstrect; - lv_area_to_sdl_rect(draw_area, &dstrect); - SDL_Rect srcrect; - if(grad->dir == LV_GRAD_DIR_VER) { - lv_coord_t coords_h = lv_area_get_height(coords); - srcrect.x = 0; - srcrect.y = (draw_area->y1 - coords->y1) * 255 / coords_h; - srcrect.w = 1; - srcrect.h = dstrect.h * 256 / coords_h; - - if(srcrect.y < 0 || srcrect.y > 255) { - return; - } - } - else { - lv_coord_t coords_w = lv_area_get_width(coords); - srcrect.x = (draw_area->x1 - coords->x1) * 255 / coords_w; - srcrect.y = 0; - srcrect.w = dstrect.w * 256 / coords_w; - srcrect.h = 1; - - if(srcrect.x < 0 || srcrect.x > 255) { - return; - } - } - - bool grad_texture_in_cache = false; - SDL_Texture * grad_texture = lv_draw_sdl_rect_grad_strip_obtain(ctx, grad, &grad_texture_in_cache); - if(blend_mod) { - SDL_SetTextureBlendMode(grad_texture, SDL_BLENDMODE_MOD); - } - else { - SDL_SetTextureBlendMode(grad_texture, SDL_BLENDMODE_BLEND); - } - - SDL_RenderCopy(ctx->renderer, grad_texture, &srcrect, &dstrect); - - if(!grad_texture_in_cache) { - LV_LOG_WARN("Texture is not cached, this will impact performance."); - SDL_DestroyTexture(grad_texture); - } -} - -static void draw_bg_grad_radius(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area, - const lv_draw_rect_dsc_t * dsc) -{ - lv_coord_t radius = dsc->radius; - /*A small texture with a quarter of the rect is enough*/ - lv_coord_t bg_w = lv_area_get_width(coords), bg_h = lv_area_get_height(coords); - lv_coord_t real_radius = LV_MIN3(bg_w / 2, bg_h / 2, radius); - bool grad_texture_in_cache = false; - SDL_Texture * grad_texture = lv_draw_sdl_rect_grad_frag_obtain(ctx, &dsc->bg_grad, bg_w, bg_h, radius, - &grad_texture_in_cache); - SDL_SetTextureBlendMode(grad_texture, SDL_BLENDMODE_BLEND); - - lv_draw_sdl_rect_bg_frag_draw_corners(ctx, grad_texture, real_radius, coords, draw_area, true); - lv_area_t part_coords; - lv_area_t part_area; - if(bg_w > radius * 2) { - /*Draw left, middle, right*/ - part_coords.x1 = 0; - part_coords.x2 = radius - 1; - part_coords.y1 = radius; - part_coords.y2 = bg_h - radius - 1; - - lv_area_align(coords, &part_coords, LV_ALIGN_LEFT_MID, 0, 0); - _lv_area_intersect(&part_area, &part_coords, draw_area); - draw_bg_grad_simple(ctx, coords, &part_area, &dsc->bg_grad, false); - - lv_area_align(coords, &part_coords, LV_ALIGN_RIGHT_MID, 0, 0); - _lv_area_intersect(&part_area, &part_coords, draw_area); - draw_bg_grad_simple(ctx, coords, &part_area, &dsc->bg_grad, false); - - part_coords.x1 = radius; - part_coords.x2 = bg_w - radius - 1; - part_coords.y1 = 0; - part_coords.y2 = bg_h - 1; - lv_area_align(coords, &part_coords, LV_ALIGN_CENTER, 0, 0); - _lv_area_intersect(&part_area, &part_coords, draw_area); - draw_bg_grad_simple(ctx, coords, &part_area, &dsc->bg_grad, false); - } - else if(bg_h > radius * 2) { - /*Draw top, middle, bottom*/ - part_coords.x1 = radius; - part_coords.x2 = bg_w - radius - 1; - part_coords.y1 = 0; - part_coords.y2 = radius - 1; - - lv_area_align(coords, &part_coords, LV_ALIGN_TOP_MID, 0, 0); - _lv_area_intersect(&part_area, &part_coords, draw_area); - draw_bg_grad_simple(ctx, coords, &part_area, &dsc->bg_grad, false); - - lv_area_align(coords, &part_coords, LV_ALIGN_BOTTOM_MID, 0, 0); - _lv_area_intersect(&part_area, &part_coords, draw_area); - draw_bg_grad_simple(ctx, coords, &part_area, &dsc->bg_grad, false); - - part_coords.x1 = 0; - part_coords.x2 = bg_w - 1; - part_coords.y1 = radius; - part_coords.y2 = bg_h - radius - 1; - lv_area_align(coords, &part_coords, LV_ALIGN_CENTER, 0, 0); - _lv_area_intersect(&part_area, &part_coords, draw_area); - draw_bg_grad_simple(ctx, coords, &part_area, &dsc->bg_grad, false); - } - - if(!grad_texture_in_cache) { - LV_LOG_WARN("Texture is not cached, this will impact performance."); - SDL_DestroyTexture(grad_texture); - } -} - -static void draw_bg_img(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area, - const lv_draw_rect_dsc_t * dsc) -{ - LV_UNUSED(draw_area); - if(SKIP_IMAGE(dsc)) return; - - lv_img_src_t src_type = lv_img_src_get_type(dsc->bg_img_src); - if(src_type == LV_IMG_SRC_SYMBOL) { - lv_point_t size; - lv_txt_get_size(&size, dsc->bg_img_src, dsc->bg_img_symbol_font, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); - lv_area_t a; - a.x1 = coords->x1 + lv_area_get_width(coords) / 2 - size.x / 2; - a.x2 = a.x1 + size.x - 1; - a.y1 = coords->y1 + lv_area_get_height(coords) / 2 - size.y / 2; - a.y2 = a.y1 + size.y - 1; - - lv_draw_label_dsc_t label_draw_dsc; - lv_draw_label_dsc_init(&label_draw_dsc); - label_draw_dsc.font = dsc->bg_img_symbol_font; - label_draw_dsc.color = dsc->bg_img_recolor; - label_draw_dsc.opa = dsc->bg_img_opa; - lv_draw_label((lv_draw_ctx_t *) ctx, &label_draw_dsc, &a, dsc->bg_img_src, NULL); - } - else { - lv_img_header_t header; - size_t key_size; - lv_draw_sdl_cache_key_head_img_t * key = lv_draw_sdl_texture_img_key_create(dsc->bg_img_src, 0, &key_size); - bool key_found; - lv_img_header_t * cache_header = NULL; - SDL_Texture * texture = lv_draw_sdl_texture_cache_get_with_userdata(ctx, key, key_size, &key_found, - (void **) &cache_header); - SDL_free(key); - if(texture) { - header = *cache_header; - } - else if(key_found || lv_img_decoder_get_info(dsc->bg_img_src, &header) != LV_RES_OK) { - /* When cache hit but with negative result, use default decoder. If still fail, return.*/ - LV_LOG_WARN("Couldn't read the background image"); - return; - } - - lv_draw_img_dsc_t img_dsc; - lv_draw_img_dsc_init(&img_dsc); - img_dsc.blend_mode = dsc->blend_mode; - img_dsc.recolor = dsc->bg_img_recolor; - img_dsc.recolor_opa = dsc->bg_img_recolor_opa; - img_dsc.opa = dsc->bg_img_opa; - img_dsc.frame_id = 0; - - int16_t radius_mask_id = LV_MASK_ID_INV; - lv_draw_mask_radius_param_t radius_param; - if(dsc->radius > 0) { - lv_draw_mask_radius_init(&radius_param, coords, dsc->radius, false); - radius_mask_id = lv_draw_mask_add(&radius_param, NULL); - } - - /*Center align*/ - if(dsc->bg_img_tiled == false) { - lv_area_t area; - area.x1 = coords->x1 + lv_area_get_width(coords) / 2 - header.w / 2; - area.y1 = coords->y1 + lv_area_get_height(coords) / 2 - header.h / 2; - area.x2 = area.x1 + header.w - 1; - area.y2 = area.y1 + header.h - 1; - - lv_draw_img((lv_draw_ctx_t *) ctx, &img_dsc, &area, dsc->bg_img_src); - } - else { - lv_area_t area; - area.y1 = coords->y1; - area.y2 = area.y1 + header.h - 1; - - for(; area.y1 <= coords->y2; area.y1 += header.h, area.y2 += header.h) { - - area.x1 = coords->x1; - area.x2 = area.x1 + header.w - 1; - for(; area.x1 <= coords->x2; area.x1 += header.w, area.x2 += header.w) { - lv_draw_img((lv_draw_ctx_t *) ctx, &img_dsc, &area, dsc->bg_img_src); - } - } - } - - if(radius_mask_id != LV_MASK_ID_INV) { - lv_draw_mask_remove_id(radius_mask_id); - lv_draw_mask_free_param(&radius_param); - } - } -} - -static void draw_shadow(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * clip, - const lv_draw_rect_dsc_t * dsc) -{ - /*Check whether the shadow is visible*/ - if(SKIP_SHADOW(dsc)) return; - - lv_coord_t sw = dsc->shadow_width; - - lv_area_t core_area; - core_area.x1 = coords->x1 + dsc->shadow_ofs_x - dsc->shadow_spread; - core_area.x2 = coords->x2 + dsc->shadow_ofs_x + dsc->shadow_spread; - core_area.y1 = coords->y1 + dsc->shadow_ofs_y - dsc->shadow_spread; - core_area.y2 = coords->y2 + dsc->shadow_ofs_y + dsc->shadow_spread; - - lv_area_t shadow_area; - shadow_area.x1 = core_area.x1 - sw / 2 - 1; - shadow_area.x2 = core_area.x2 + sw / 2 + 1; - shadow_area.y1 = core_area.y1 - sw / 2 - 1; - shadow_area.y2 = core_area.y2 + sw / 2 + 1; - - lv_opa_t opa = dsc->shadow_opa; - - if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; - - /*Get clipped draw area which is the real draw area. - *It is always the same or inside `shadow_area`*/ - lv_area_t draw_area; - if(!_lv_area_intersect(&draw_area, &shadow_area, clip)) return; - - SDL_Rect core_area_rect; - lv_area_to_sdl_rect(&shadow_area, &core_area_rect); - - lv_coord_t radius = dsc->radius; - /* No matter how big the shadow is, what we need is just a corner */ - lv_coord_t frag_size = LV_MIN3(lv_area_get_width(&core_area) / 2, lv_area_get_height(&core_area) / 2, - LV_MAX(sw / 2, radius)); - - /* This is how big the corner is after blurring */ - lv_coord_t blur_growth = (lv_coord_t)(sw / 2 + 1); - - lv_coord_t blur_frag_size = (lv_coord_t)(frag_size + blur_growth); - - lv_draw_rect_shadow_key_t key = rect_shadow_key_create(radius, frag_size, sw); - - SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL); - bool texture_in_cache = false; - if(texture == NULL) { - lv_area_t mask_area = {blur_growth, blur_growth}, mask_area_blurred = {0, 0}; - lv_area_set_width(&mask_area, frag_size * 2); - lv_area_set_height(&mask_area, frag_size * 2); - lv_area_set_width(&mask_area_blurred, blur_frag_size * 2); - lv_area_set_height(&mask_area_blurred, blur_frag_size * 2); - - lv_draw_mask_radius_param_t mask_rout_param; - lv_draw_mask_radius_init(&mask_rout_param, &mask_area, radius, false); - int16_t mask_id = lv_draw_mask_add(&mask_rout_param, NULL); - lv_opa_t * mask_buf = lv_draw_sdl_mask_dump_opa(&mask_area_blurred, &mask_id, 1); - lv_stack_blur_grayscale(mask_buf, lv_area_get_width(&mask_area_blurred), lv_area_get_height(&mask_area_blurred), - sw / 2 + sw % 2); - texture = lv_sdl_create_opa_texture(ctx->renderer, mask_buf, blur_frag_size, blur_frag_size, - lv_area_get_width(&mask_area_blurred)); - lv_mem_buf_release(mask_buf); - lv_draw_mask_remove_id(mask_id); - SDL_assert(texture); - texture_in_cache = lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture); - } - else { - texture_in_cache = true; - } - - SDL_Color shadow_color; - lv_color_to_sdl_color(&dsc->shadow_color, &shadow_color); - SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); - SDL_SetTextureAlphaMod(texture, opa); - SDL_SetTextureColorMod(texture, shadow_color.r, shadow_color.g, shadow_color.b); - - lv_draw_sdl_rect_bg_frag_draw_corners(ctx, texture, blur_frag_size, &shadow_area, clip, false); - frag_render_borders(ctx->renderer, texture, blur_frag_size, &shadow_area, clip, false); - frag_render_center(ctx->renderer, texture, blur_frag_size, &shadow_area, clip, false); - - if(!texture_in_cache) { - LV_LOG_WARN("Texture is not cached, this will impact performance."); - SDL_DestroyTexture(texture); - } -} - - -static void draw_border(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * draw_area, - const lv_draw_rect_dsc_t * dsc) -{ - if(SKIP_BORDER(dsc)) return; - - SDL_Color border_color; - lv_color_to_sdl_color(&dsc->border_color, &border_color); - - lv_coord_t coords_w = lv_area_get_width(coords), coords_h = lv_area_get_height(coords); - lv_coord_t short_side = LV_MIN(coords_w, coords_h); - lv_coord_t rout = LV_MIN(dsc->radius, short_side / 2);/*Get the inner area*/ - lv_area_t area_inner; - lv_area_copy(&area_inner, coords);// lv_area_increase(&area_inner, 1, 1); - area_inner.x1 += ((dsc->border_side & LV_BORDER_SIDE_LEFT) ? dsc->border_width : -(dsc->border_width + rout)); - area_inner.x2 -= ((dsc->border_side & LV_BORDER_SIDE_RIGHT) ? dsc->border_width : -(dsc->border_width + rout)); - area_inner.y1 += ((dsc->border_side & LV_BORDER_SIDE_TOP) ? dsc->border_width : -(dsc->border_width + rout)); - area_inner.y2 -= ((dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? dsc->border_width : -(dsc->border_width + rout)); - lv_coord_t rin = LV_MAX(rout - dsc->border_width, 0); - draw_border_generic(ctx, coords, &area_inner, draw_area, rout, rin, dsc->border_color, dsc->border_opa, - dsc->blend_mode); -} - -static void draw_outline(lv_draw_sdl_ctx_t * ctx, const lv_area_t * coords, const lv_area_t * clip, - const lv_draw_rect_dsc_t * dsc) -{ - if(SKIP_OUTLINE(dsc)) return; - - lv_opa_t opa = dsc->outline_opa; - - if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; - - /*Get the inner radius*/ - lv_area_t area_inner; - lv_area_copy(&area_inner, coords); - - /*Bring the outline closer to make sure there is no color bleeding with pad=0*/ - lv_coord_t pad = dsc->outline_pad - 1; - area_inner.x1 -= pad; - area_inner.y1 -= pad; - area_inner.x2 += pad; - area_inner.y2 += pad; - - lv_area_t area_outer; - lv_area_copy(&area_outer, &area_inner); - - area_outer.x1 -= dsc->outline_width; - area_outer.x2 += dsc->outline_width; - area_outer.y1 -= dsc->outline_width; - area_outer.y2 += dsc->outline_width; - - lv_area_t draw_area; - if(!_lv_area_intersect(&draw_area, &area_outer, clip)) return; - - int32_t inner_w = lv_area_get_width(&area_inner); - int32_t inner_h = lv_area_get_height(&area_inner); - lv_coord_t rin = dsc->radius; - int32_t short_side = LV_MIN(inner_w, inner_h); - if(rin > short_side >> 1) rin = short_side >> 1; - - lv_coord_t rout = rin + dsc->outline_width; - - draw_border_generic(ctx, &area_outer, &area_inner, clip, rout, rin, dsc->outline_color, dsc->outline_opa, - dsc->blend_mode); -} - -static void draw_border_generic(lv_draw_sdl_ctx_t * ctx, const lv_area_t * outer_area, const lv_area_t * inner_area, - const lv_area_t * clip, lv_coord_t rout, lv_coord_t rin, lv_color_t color, lv_opa_t opa, - lv_blend_mode_t blend_mode) -{ - opa = opa >= LV_OPA_COVER ? LV_OPA_COVER : opa; - - SDL_Renderer * renderer = ctx->renderer; - - lv_draw_rect_border_key_t key = rect_border_key_create(rout, rin, outer_area, inner_area); - lv_coord_t radius = LV_MIN3(rout, lv_area_get_width(outer_area) / 2, lv_area_get_height(outer_area) / 2); - lv_coord_t max_side = LV_MAX4(key.offsets.x1, key.offsets.y1, -key.offsets.x2, -key.offsets.y2); - lv_coord_t frag_size = LV_MAX(radius, max_side); - SDL_Texture * texture = lv_draw_sdl_texture_cache_get(ctx, &key, sizeof(key), NULL); - bool texture_in_cache; - if(texture == NULL) { - /* Create a mask texture with size of (frag_size * 2 + FRAG_SPACING) */ - const lv_area_t frag_area = {0, 0, frag_size * 2 + FRAG_SPACING - 1, frag_size * 2 + FRAG_SPACING - 1}; - - /*Create mask for the outer area*/ - int16_t mask_ids[2] = {LV_MASK_ID_INV, LV_MASK_ID_INV}; - lv_draw_mask_radius_param_t mask_rout_param; - if(rout > 0) { - lv_draw_mask_radius_init(&mask_rout_param, &frag_area, rout, false); - mask_ids[0] = lv_draw_mask_add(&mask_rout_param, NULL); - } - - /*Create mask for the inner mask*/ - if(rin < 0) rin = 0; - const lv_area_t frag_inner_area = {frag_area.x1 + key.offsets.x1, frag_area.y1 + key.offsets.y1, - frag_area.x2 + key.offsets.x2, frag_area.y2 + key.offsets.y2 - }; - lv_draw_mask_radius_param_t mask_rin_param; - lv_draw_mask_radius_init(&mask_rin_param, &frag_inner_area, rin, true); - mask_ids[1] = lv_draw_mask_add(&mask_rin_param, NULL); - - texture = lv_draw_sdl_mask_dump_texture(renderer, &frag_area, mask_ids, 2); - - lv_draw_mask_remove_id(mask_ids[1]); - lv_draw_mask_remove_id(mask_ids[0]); - SDL_assert(texture); - texture_in_cache = lv_draw_sdl_texture_cache_put(ctx, &key, sizeof(key), texture); - } - else { - texture_in_cache = true; - } - - SDL_Rect outer_rect; - lv_area_to_sdl_rect(outer_area, &outer_rect); - SDL_Color color_sdl; - lv_color_to_sdl_color(&color, &color_sdl); - - SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); - SDL_SetTextureAlphaMod(texture, opa); - SDL_SetTextureColorMod(texture, color_sdl.r, color_sdl.g, color_sdl.b); - - lv_draw_sdl_rect_bg_frag_draw_corners(ctx, texture, frag_size, outer_area, clip, true); - frag_render_borders(renderer, texture, frag_size, outer_area, clip, true); - - if(!texture_in_cache) { - LV_LOG_WARN("Texture is not cached, this will impact performance."); - SDL_DestroyTexture(texture); - } -} - -static void frag_render_borders(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size, - const lv_area_t * coords, const lv_area_t * clipped, bool full) -{ - lv_area_t border_area, dst_area; - /* Top border */ - border_area.x1 = coords->x1 + frag_size; - border_area.y1 = coords->y1; - border_area.x2 = coords->x2 - frag_size; - border_area.y2 = coords->y1 + frag_size - 1; - if(_lv_area_intersect(&dst_area, &border_area, clipped)) { - SDL_Rect dst_rect; - lv_area_to_sdl_rect(&dst_area, &dst_rect); - - lv_coord_t sy = (lv_coord_t)(dst_area.y1 - border_area.y1); - if(full) { - SDL_Rect src_rect = {frag_size + 1, sy, 1, lv_area_get_height(&dst_area)}; - SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect); - } - else { - SDL_Rect src_rect = {frag_size - 1, sy, 1, lv_area_get_height(&dst_area)}; - SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect); - } - } - /* Bottom border */ - border_area.y1 = LV_MAX(coords->y2 - frag_size + 1, coords->y1 + frag_size); - border_area.y2 = coords->y2; - if(_lv_area_intersect(&dst_area, &border_area, clipped)) { - SDL_Rect dst_rect; - lv_area_to_sdl_rect(&dst_area, &dst_rect); - - lv_coord_t dh = lv_area_get_height(&dst_area); - if(full) { - lv_coord_t sy = (lv_coord_t)(dst_area.y1 - border_area.y1); - SDL_Rect src_rect = {frag_size + 1, frag_size + FRAG_SPACING + sy, 1, dh}; - SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect); - } - else { - lv_coord_t sy = (lv_coord_t)(border_area.y2 - dst_area.y2); - SDL_Rect src_rect = {frag_size - 1, sy, 1, dh}; - SDL_RenderCopyEx(renderer, frag, &src_rect, &dst_rect, 0, NULL, SDL_FLIP_VERTICAL); - } - } - /* Left border */ - border_area.x1 = coords->x1; - border_area.y1 = coords->y1 + frag_size; - border_area.x2 = coords->x1 + frag_size - 1; - border_area.y2 = coords->y2 - frag_size; - if(_lv_area_intersect(&dst_area, &border_area, clipped)) { - SDL_Rect dst_rect; - lv_area_to_sdl_rect(&dst_area, &dst_rect); - - lv_coord_t dw = lv_area_get_width(&dst_area); - lv_coord_t sx = (lv_coord_t)(dst_area.x1 - border_area.x1); - if(full) { - SDL_Rect src_rect = {sx, frag_size + 1, dw, 1}; - SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect); - } - else { - SDL_Rect src_rect = {sx, frag_size - 1, dw, 1}; - SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect); - } - } - /* Right border */ - border_area.x1 = LV_MAX(coords->x2 - frag_size + 1, coords->x1 + frag_size); - border_area.x2 = coords->x2; - if(_lv_area_intersect(&dst_area, &border_area, clipped)) { - SDL_Rect dst_rect; - lv_area_to_sdl_rect(&dst_area, &dst_rect); - - lv_coord_t dw = lv_area_get_width(&dst_area); - if(full) { - lv_coord_t sx = (lv_coord_t)(dst_area.x1 - border_area.x1); - SDL_Rect src_rect = {frag_size + FRAG_SPACING + sx, frag_size + 1, dw, 1}; - SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect); - } - else { - lv_coord_t sx = (lv_coord_t)(border_area.x2 - dst_area.x2); - SDL_Rect src_rect = {sx, frag_size - 1, dw, 1}; - SDL_RenderCopyEx(renderer, frag, &src_rect, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL); - } - } -} - -static void frag_render_center(SDL_Renderer * renderer, SDL_Texture * frag, lv_coord_t frag_size, - const lv_area_t * coords, - const lv_area_t * clipped, bool full) -{ - lv_area_t center_area = { - coords->x1 + frag_size, - coords->y1 + frag_size, - coords->x2 - frag_size, - coords->y2 - frag_size, - }; - if(center_area.x2 < center_area.x1 || center_area.y2 < center_area.y1) return; - lv_area_t draw_area; - if(!_lv_area_intersect(&draw_area, ¢er_area, clipped)) { - return; - } - SDL_Rect dst_rect; - lv_area_to_sdl_rect(&draw_area, &dst_rect); - if(full) { - SDL_Rect src_rect = {frag_size, frag_size, 1, 1}; - SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect); - } - else { - SDL_Rect src_rect = {frag_size - 1, frag_size - 1, 1, 1}; - SDL_RenderCopy(renderer, frag, &src_rect, &dst_rect); - } -} - -static lv_draw_rect_bg_key_t rect_bg_key_create(lv_coord_t radius, lv_coord_t size) -{ - lv_draw_rect_bg_key_t key; - SDL_memset(&key, 0, sizeof(key)); - key.magic = LV_GPU_CACHE_KEY_MAGIC_RECT_BG; - key.radius = radius; - key.size = size; - return key; -} - -static lv_draw_rect_grad_frag_key_t rect_grad_frag_key_create(const lv_grad_dsc_t * grad, lv_coord_t w, lv_coord_t h, - lv_coord_t radius) -{ - lv_draw_rect_grad_frag_key_t key; - SDL_memset(&key, 0, sizeof(key)); - key.magic = LV_GPU_CACHE_KEY_MAGIC_RECT_GRAD; - key.stops_count = grad->stops_count; - key.dir = grad->dir; - for(uint8_t i = 0; i < grad->stops_count; i++) { - key.stops[i].frac = grad->stops[i].frac; - key.stops[i].color = grad->stops[i].color; - } - key.w = w; - key.h = h; - key.radius = radius; - return key; -} - -static lv_draw_rect_grad_strip_key_t rect_grad_strip_key_create(const lv_grad_dsc_t * grad) -{ - lv_draw_rect_grad_strip_key_t key; - SDL_memset(&key, 0, sizeof(key)); - key.magic = LV_GPU_CACHE_KEY_MAGIC_RECT_GRAD; - key.stops_count = grad->stops_count; - key.dir = grad->dir; - for(uint8_t i = 0; i < grad->stops_count; i++) { - key.stops[i].frac = grad->stops[i].frac; - key.stops[i].color = grad->stops[i].color; - } - return key; -} - -static lv_draw_rect_shadow_key_t rect_shadow_key_create(lv_coord_t radius, lv_coord_t size, lv_coord_t blur) -{ - lv_draw_rect_shadow_key_t key; - SDL_memset(&key, 0, sizeof(key)); - key.magic = LV_GPU_CACHE_KEY_MAGIC_RECT_SHADOW; - key.radius = radius; - key.size = size; - key.blur = blur; - return key; -} - -static lv_draw_rect_border_key_t rect_border_key_create(lv_coord_t rout, lv_coord_t rin, const lv_area_t * outer_area, - const lv_area_t * inner_area) -{ - lv_draw_rect_border_key_t key; - /* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */ - SDL_memset(&key, 0, sizeof(key)); - key.magic = LV_GPU_CACHE_KEY_MAGIC_RECT_BORDER; - key.rout = rout; - key.rin = rin; - key.offsets.x1 = inner_area->x1 - outer_area->x1; - key.offsets.x2 = inner_area->x2 - outer_area->x2; - key.offsets.y1 = inner_area->y1 - outer_area->y1; - key.offsets.y2 = inner_area->y2 - outer_area->y2; - return key; -} - -#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_rect.h b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_rect.h deleted file mode 100644 index c3262d5f1..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_rect.h +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @file lv_draw_sdl_rect.h - * - */ - -#ifndef LV_DRAW_SDL_RECT_H -#define LV_DRAW_SDL_RECT_H - - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include LV_GPU_SDL_INCLUDE_PATH - -#include "../lv_draw.h" - -#include "lv_draw_sdl_texture_cache.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct lv_draw_sdl_rect_header_t { - lv_img_header_t base; - SDL_Rect rect; -} lv_draw_sdl_rect_header_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/*====================== - * Add/remove functions - *=====================*/ - -/*===================== - * Setter functions - *====================*/ - -/*===================== - * Getter functions - *====================*/ - -/*===================== - * Other functions - *====================*/ - -/** - * - * @param ctx Drawing context - * @param radius Corner radius of the rectangle - * @param in_cache Whether the texture has been put in the cache - * @return Background fragment texture - */ -SDL_Texture * lv_draw_sdl_rect_bg_frag_obtain(lv_draw_sdl_ctx_t * ctx, lv_coord_t radius, bool * in_cache); - -/** - * - * @param ctx Drawing context - * @param grad Gradient info - * @param w Width of the rectangle - * @param h Height of the rectangle - * @param radius Corner radius of the rectangle - * @param in_cache Whether the texture has been put in the cache - * @return Gradient fragment texture - */ -SDL_Texture * lv_draw_sdl_rect_grad_frag_obtain(lv_draw_sdl_ctx_t * ctx, const lv_grad_dsc_t * grad, lv_coord_t w, - lv_coord_t h, lv_coord_t radius, bool * in_cache); - -/** - * - * @param ctx Drawing context - * @param grad Gradient info - * @param in_cache Whether the texture has been put in the cache - * @return Gradient strip texture - */ -SDL_Texture * lv_draw_sdl_rect_grad_strip_obtain(lv_draw_sdl_ctx_t * ctx, const lv_grad_dsc_t * grad, bool * in_cache); - -void lv_draw_sdl_rect_bg_frag_draw_corners(lv_draw_sdl_ctx_t * ctx, SDL_Texture * frag, lv_coord_t frag_size, - const lv_area_t * coords, const lv_area_t * clip, bool full); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_GPU_SDL*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_SDL_RECT_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.c deleted file mode 100644 index 1c411b0ee..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.c +++ /dev/null @@ -1,249 +0,0 @@ -/** - * @file lv_draw_sdl_stack_blur.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_draw_sdl_stack_blur.h" - -#if LV_USE_GPU_SDL -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -static void -stack_blur_job(lv_opa_t * src, unsigned int w, unsigned int h, unsigned int radius, int cores, int core, int step); - -/********************** - * STATIC VARIABLES - **********************/ - -// Based heavily on http://vitiy.info/Code/stackblur.cpp -// See http://vitiy.info/stackblur-algorithm-multi-threaded-blur-for-cpp/ -// Stack Blur Algorithm by Mario Klingemann - -static unsigned short const stackblur_mul[255] = { - 512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, - 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, - 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, - 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, - 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, - 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, - 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, - 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, - 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, - 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, - 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, - 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, - 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, - 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, - 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, - 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259 -}; - -static unsigned char const stackblur_shr[255] = { - 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, - 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 -}; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void lv_stack_blur_grayscale(lv_opa_t * buf, uint16_t w, uint16_t h, uint16_t r) -{ - stack_blur_job(buf, w, h, r, 1, 0, 1); - stack_blur_job(buf, w, h, r, 1, 0, 2); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void stack_blur_job(lv_opa_t * src, unsigned int w, unsigned int h, unsigned int radius, int cores, int core, - int step) -{ - if(radius < 2 || radius > 254) { - /* Silently ignore bad radius */ - return; - } - - unsigned int x, y, xp, yp, i; - unsigned int sp; - unsigned int stack_start; - unsigned char * stack_ptr; - - lv_opa_t * src_ptr; - lv_opa_t * dst_ptr; - - unsigned long sum_r; - unsigned long sum_in_r; - unsigned long sum_out_r; - - unsigned int wm = w - 1; - unsigned int hm = h - 1; - unsigned int stride = w; - unsigned int div = (radius * 2) + 1; - unsigned int mul_sum = stackblur_mul[radius]; - unsigned char shr_sum = stackblur_shr[radius]; - unsigned char stack[254 * 2 + 1]; - - if(step == 1) { - unsigned int minY = core * h / cores; - unsigned int maxY = (core + 1) * h / cores; - - for(y = minY; y < maxY; y++) { - sum_r = - sum_in_r = - sum_out_r = 0; - - src_ptr = src + stride * y; // start of line (0,y) - - for(i = 0; i <= radius; i++) { - stack_ptr = &stack[i]; - stack_ptr[0] = src_ptr[0]; - sum_r += src_ptr[0] * (i + 1); - sum_out_r += src_ptr[0]; - } - - - for(i = 1; i <= radius; i++) { - if(i <= wm) src_ptr += 1; - stack_ptr = &stack[i + radius]; - stack_ptr[0] = src_ptr[0]; - sum_r += src_ptr[0] * (radius + 1 - i); - sum_in_r += src_ptr[0]; - } - - - sp = radius; - xp = radius; - if(xp > wm) xp = wm; - src_ptr = src + (xp + y * w); // img.pix_ptr(xp, y); - dst_ptr = src + y * stride; // img.pix_ptr(0, y); - for(x = 0; x < w; x++) { - dst_ptr[0] = LV_CLAMP((sum_r * mul_sum) >> shr_sum, 0, 255); - dst_ptr += 1; - - sum_r -= sum_out_r; - - stack_start = sp + div - radius; - if(stack_start >= div) stack_start -= div; - stack_ptr = &stack[stack_start]; - - sum_out_r -= stack_ptr[0]; - - if(xp < wm) { - src_ptr += 1; - ++xp; - } - - stack_ptr[0] = src_ptr[0]; - - sum_in_r += src_ptr[0]; - sum_r += sum_in_r; - - ++sp; - if(sp >= div) sp = 0; - stack_ptr = &stack[sp]; - - sum_out_r += stack_ptr[0]; - sum_in_r -= stack_ptr[0]; - } - - } - } - - // step 2 - if(step == 2) { - unsigned int minX = core * w / cores; - unsigned int maxX = (core + 1) * w / cores; - - for(x = minX; x < maxX; x++) { - sum_r = - sum_in_r = - sum_out_r = 0; - - src_ptr = src + x; // x,0 - for(i = 0; i <= radius; i++) { - stack_ptr = &stack[i]; - stack_ptr[0] = src_ptr[0]; - sum_r += src_ptr[0] * (i + 1); - sum_out_r += src_ptr[0]; - } - for(i = 1; i <= radius; i++) { - if(i <= hm) src_ptr += stride; // +stride - - stack_ptr = &stack[i + radius]; - stack_ptr[0] = src_ptr[0]; - sum_r += src_ptr[0] * (radius + 1 - i); - sum_in_r += src_ptr[0]; - } - - sp = radius; - yp = radius; - if(yp > hm) yp = hm; - src_ptr = src + (x + yp * w); // img.pix_ptr(x, yp); - dst_ptr = src + x; // img.pix_ptr(x, 0); - for(y = 0; y < h; y++) { - dst_ptr[0] = LV_CLAMP((sum_r * mul_sum) >> shr_sum, 0, 255); - dst_ptr += stride; - - sum_r -= sum_out_r; - - stack_start = sp + div - radius; - if(stack_start >= div) stack_start -= div; - stack_ptr = &stack[stack_start]; - - sum_out_r -= stack_ptr[0]; - - if(yp < hm) { - src_ptr += stride; // stride - ++yp; - } - - stack_ptr[0] = src_ptr[0]; - - sum_in_r += src_ptr[0]; - sum_r += sum_in_r; - - ++sp; - if(sp >= div) sp = 0; - stack_ptr = &stack[sp]; - - sum_out_r += stack_ptr[0]; - sum_in_r -= stack_ptr[0]; - } - } - } -} - -#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.c deleted file mode 100644 index 406741783..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.c +++ /dev/null @@ -1,176 +0,0 @@ -/** - * @file lv_draw_sdl_texture_cache.c - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include "lv_draw_sdl_texture_cache.h" - -#include "lv_draw_sdl_utils.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - SDL_Texture * texture; - void * userdata; - lv_lru_free_t * userdata_free; - lv_draw_sdl_cache_flag_t flags; -} draw_cache_value_t; - -typedef struct { - lv_sdl_cache_key_magic_t magic; -} temp_texture_key_t; - -typedef struct { - lv_coord_t width, height; -} temp_texture_userdata_t; - -static void draw_cache_free_value(draw_cache_value_t *); - -static draw_cache_value_t * draw_cache_get_entry(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, - bool * found); -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void lv_draw_sdl_texture_cache_init(lv_draw_sdl_ctx_t * ctx) -{ - ctx->internals->texture_cache = lv_lru_create(LV_GPU_SDL_LRU_SIZE, 65536, - (lv_lru_free_t *) draw_cache_free_value, NULL); -} - -void lv_draw_sdl_texture_cache_deinit(lv_draw_sdl_ctx_t * ctx) -{ - lv_lru_del(ctx->internals->texture_cache); -} - -SDL_Texture * lv_draw_sdl_texture_cache_get(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, bool * found) -{ - return lv_draw_sdl_texture_cache_get_with_userdata(ctx, key, key_length, found, NULL); -} - -SDL_Texture * lv_draw_sdl_texture_cache_get_with_userdata(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, - bool * found, void ** userdata) -{ - draw_cache_value_t * value = draw_cache_get_entry(ctx, key, key_length, found); - if(!value) return NULL; - if(userdata) { - *userdata = value->userdata; - } - return value->texture; -} - -bool lv_draw_sdl_texture_cache_put(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, SDL_Texture * texture) -{ - return lv_draw_sdl_texture_cache_put_advanced(ctx, key, key_length, texture, NULL, NULL, 0); -} - -bool lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, - SDL_Texture * texture, void * userdata, void userdata_free(void *), - lv_draw_sdl_cache_flag_t flags) -{ - lv_lru_t * lru = ctx->internals->texture_cache; - draw_cache_value_t * value = SDL_malloc(sizeof(draw_cache_value_t)); - value->texture = texture; - value->userdata = userdata; - value->userdata_free = userdata_free; - value->flags = flags; - if(!texture) { - return lv_lru_set(lru, key, key_length, value, 1) == LV_LRU_OK; - } - if(flags & LV_DRAW_SDL_CACHE_FLAG_MANAGED) { - /* Managed texture doesn't count into cache size */ - LV_LOG_INFO("cache texture %p", texture); - return lv_lru_set(lru, key, key_length, value, 1) == LV_LRU_OK; - } - Uint32 format; - int access, width, height; - if(SDL_QueryTexture(texture, &format, &access, &width, &height) != 0) { - return false; - } - LV_LOG_INFO("cache texture %p, %d*%d@%dbpp", texture, width, height, SDL_BITSPERPIXEL(format)); - return lv_lru_set(lru, key, key_length, value, width * height * SDL_BITSPERPIXEL(format) / 8) == LV_LRU_OK; -} - -lv_draw_sdl_cache_key_head_img_t * lv_draw_sdl_texture_img_key_create(const void * src, int32_t frame_id, size_t * size) -{ - lv_draw_sdl_cache_key_head_img_t header; - /* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */ - SDL_memset(&header, 0, sizeof(header)); - header.magic = LV_GPU_CACHE_KEY_MAGIC_IMG; - header.type = lv_img_src_get_type(src); - header.frame_id = frame_id; - void * key; - size_t key_size; - if(header.type == LV_IMG_SRC_FILE || header.type == LV_IMG_SRC_SYMBOL) { - size_t srclen = SDL_strlen(src); - key_size = sizeof(header) + srclen; - key = SDL_malloc(key_size); - SDL_memcpy(key, &header, sizeof(header)); - /*Copy string content as key value*/ - SDL_memcpy(key + sizeof(header), src, srclen); - } - else { - key_size = sizeof(header) + sizeof(void *); - key = SDL_malloc(key_size); - SDL_memcpy(key, &header, sizeof(header)); - /*Copy address number as key value*/ - SDL_memcpy(key + sizeof(header), &src, sizeof(void *)); - } - *size = key_size; - return (lv_draw_sdl_cache_key_head_img_t *) key; -} - -static void draw_cache_free_value(draw_cache_value_t * value) -{ - if(value->texture && !(value->flags & LV_DRAW_SDL_CACHE_FLAG_MANAGED)) { - LV_LOG_INFO("destroy texture %p", value->texture); - SDL_DestroyTexture(value->texture); - } - if(value->userdata_free) { - value->userdata_free(value->userdata); - } - SDL_free(value); -} - -static draw_cache_value_t * draw_cache_get_entry(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, - bool * found) -{ - lv_lru_t * lru = ctx->internals->texture_cache; - draw_cache_value_t * value = NULL; - lv_lru_get(lru, key, key_length, (void **) &value); - if(!value) { - if(found) { - *found = false; - } - return NULL; - } - if(found) { - *found = true; - } - return value; -} - -#endif /*LV_USE_GPU_SDL*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.h b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.h deleted file mode 100644 index 3a799f58b..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - * @file lv_draw_sdl_texture_cache.h - * - */ - -#ifndef LV_DRAW_SDL_TEXTURE_CACHE_H -#define LV_DRAW_SDL_TEXTURE_CACHE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ - -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include LV_GPU_SDL_INCLUDE_PATH -#include "lv_draw_sdl.h" -#include "lv_draw_sdl_priv.h" -#include "../../draw/lv_img_decoder.h" -#include "../../misc/lv_area.h" - -/********************* - * DEFINES - *********************/ - -#define LV_DRAW_SDL_DEC_DSC_TEXTURE_HEAD "@LVSDLTex" - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - char head[8]; - SDL_Texture * texture; - SDL_Rect rect; - bool texture_managed; - bool texture_referenced; -} lv_draw_sdl_dec_dsc_userdata_t; - -typedef enum { - LV_GPU_CACHE_KEY_MAGIC_ARC = 0x01, - LV_GPU_CACHE_KEY_MAGIC_IMG = 0x11, - LV_GPU_CACHE_KEY_MAGIC_IMG_ROUNDED_CORNERS = 0x12, - LV_GPU_CACHE_KEY_MAGIC_LINE = 0x21, - LV_GPU_CACHE_KEY_MAGIC_RECT_BG = 0x31, - LV_GPU_CACHE_KEY_MAGIC_RECT_SHADOW = 0x32, - LV_GPU_CACHE_KEY_MAGIC_RECT_BORDER = 0x33, - LV_GPU_CACHE_KEY_MAGIC_RECT_GRAD = 0x34, - LV_GPU_CACHE_KEY_MAGIC_FONT_GLYPH = 0x41, - LV_GPU_CACHE_KEY_MAGIC_MASK = 0x51, -} lv_sdl_cache_key_magic_t; - -typedef enum { - LV_DRAW_SDL_CACHE_FLAG_NONE = 0, - LV_DRAW_SDL_CACHE_FLAG_MANAGED = 1, -} lv_draw_sdl_cache_flag_t; - -typedef struct { - lv_sdl_cache_key_magic_t magic; - lv_img_src_t type; - int32_t frame_id; -} lv_draw_sdl_cache_key_head_img_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -void lv_draw_sdl_texture_cache_init(lv_draw_sdl_ctx_t * ctx); - -void lv_draw_sdl_texture_cache_deinit(lv_draw_sdl_ctx_t * ctx); - -/** - * Find cached texture by key. The texture can be destroyed during usage. - */ -SDL_Texture * lv_draw_sdl_texture_cache_get(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, bool * found); - -SDL_Texture * lv_draw_sdl_texture_cache_get_with_userdata(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, - bool * found, void ** userdata); - -/** - * @return Whether the texture has been put in the cache - */ -bool lv_draw_sdl_texture_cache_put(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, SDL_Texture * texture); - -/** - * @return Whether the texture has been put in the cache - */ -bool lv_draw_sdl_texture_cache_put_advanced(lv_draw_sdl_ctx_t * ctx, const void * key, size_t key_length, - SDL_Texture * texture, void * userdata, void userdata_free(void *), - lv_draw_sdl_cache_flag_t flags); - -lv_draw_sdl_cache_key_head_img_t * lv_draw_sdl_texture_img_key_create(const void * src, int32_t frame_id, - size_t * size); - -/********************** - * MACROS - **********************/ -#endif /*LV_USE_GPU_SDL*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_SDL_TEXTURE_CACHE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_utils.c b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_utils.c deleted file mode 100644 index 3ca0fad45..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_utils.c +++ /dev/null @@ -1,183 +0,0 @@ -/** - * @file lv_draw_sdl_utils.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include "lv_draw_sdl_utils.h" - -#include "../lv_draw.h" -#include "../lv_draw_label.h" -#include "../../core/lv_refr.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -/********************** - * STATIC VARIABLES - **********************/ -extern const uint8_t _lv_bpp1_opa_table[2]; -extern const uint8_t _lv_bpp2_opa_table[4]; -extern const uint8_t _lv_bpp4_opa_table[16]; -extern const uint8_t _lv_bpp8_opa_table[256]; - -static int utils_init_count = 0; -static SDL_Palette * lv_sdl_palette_grayscale8 = NULL; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void _lv_draw_sdl_utils_init() -{ - utils_init_count++; - if(utils_init_count > 1) { - return; - } - lv_sdl_palette_grayscale8 = lv_sdl_alloc_palette_for_bpp(_lv_bpp8_opa_table, 8); -} - -void _lv_draw_sdl_utils_deinit() -{ - if(utils_init_count == 0) { - return; - } - utils_init_count--; - if(utils_init_count == 0) { - SDL_FreePalette(lv_sdl_palette_grayscale8); - lv_sdl_palette_grayscale8 = NULL; - } -} - -void lv_area_to_sdl_rect(const lv_area_t * in, SDL_Rect * out) -{ - out->x = in->x1; - out->y = in->y1; - out->w = in->x2 - in->x1 + 1; - out->h = in->y2 - in->y1 + 1; -} - -void lv_color_to_sdl_color(const lv_color_t * in, SDL_Color * out) -{ -#if LV_COLOR_DEPTH == 32 - out->a = in->ch.alpha; - out->r = in->ch.red; - out->g = in->ch.green; - out->b = in->ch.blue; -#else - uint32_t color32 = lv_color_to32(*in); - lv_color32_t * color32_t = (lv_color32_t *) &color32; - out->a = color32_t->ch.alpha; - out->r = color32_t->ch.red; - out->g = color32_t->ch.green; - out->b = color32_t->ch.blue; -#endif -} - -void lv_area_zoom_to_sdl_rect(const lv_area_t * in, SDL_Rect * out, uint16_t zoom, const lv_point_t * pivot) -{ - if(zoom == LV_IMG_ZOOM_NONE) { - lv_area_to_sdl_rect(in, out); - return; - } - lv_area_t tmp; - _lv_img_buf_get_transformed_area(&tmp, lv_area_get_width(in), lv_area_get_height(in), 0, zoom, pivot); - lv_area_move(&tmp, in->x1, in->y1); - lv_area_to_sdl_rect(&tmp, out); -} - -SDL_Palette * lv_sdl_alloc_palette_for_bpp(const uint8_t * mapping, uint8_t bpp) -{ - SDL_assert(bpp >= 1 && bpp <= 8); - int color_cnt = 1 << bpp; - SDL_Palette * result = SDL_AllocPalette(color_cnt); - SDL_Color palette[256]; - for(int i = 0; i < color_cnt; i++) { - palette[i].r = palette[i].g = palette[i].b = 0xFF; - palette[i].a = mapping ? mapping[i] : i; - } - SDL_SetPaletteColors(result, palette, 0, color_cnt); - return result; -} - -SDL_Surface * lv_sdl_create_opa_surface(lv_opa_t * opa, lv_coord_t width, lv_coord_t height, lv_coord_t stride) -{ - SDL_Surface * indexed = SDL_CreateRGBSurfaceFrom(opa, width, height, 8, stride, 0, 0, 0, 0); - SDL_SetSurfacePalette(indexed, lv_sdl_palette_grayscale8); - SDL_Surface * converted = SDL_ConvertSurfaceFormat(indexed, LV_DRAW_SDL_TEXTURE_FORMAT, 0); - SDL_FreeSurface(indexed); - return converted; -} - -SDL_Texture * lv_sdl_create_opa_texture(SDL_Renderer * renderer, lv_opa_t * pixels, lv_coord_t width, - lv_coord_t height, lv_coord_t stride) -{ - SDL_Surface * indexed = lv_sdl_create_opa_surface(pixels, width, height, stride); - SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, indexed); - SDL_FreeSurface(indexed); - return texture; -} - -void lv_sdl_to_8bpp(uint8_t * dest, const uint8_t * src, int width, int height, int stride, uint8_t bpp) -{ - int src_len = width * height; - int cur = 0; - int curbit; - uint8_t opa_mask; - const uint8_t * opa_table; - switch(bpp) { - case 1: - opa_mask = 0x1; - opa_table = _lv_bpp1_opa_table; - break; - case 2: - opa_mask = 0x4; - opa_table = _lv_bpp2_opa_table; - break; - case 4: - opa_mask = 0xF; - opa_table = _lv_bpp4_opa_table; - break; - case 8: - opa_mask = 0xFF; - opa_table = _lv_bpp8_opa_table; - break; - default: - return; - } - /* Does this work well on big endian systems? */ - while(cur < src_len) { - curbit = 8 - bpp; - uint8_t src_byte = src[cur * bpp / 8]; - while(curbit >= 0 && cur < src_len) { - uint8_t src_bits = opa_mask & (src_byte >> curbit); - dest[(cur / width * stride) + (cur % width)] = opa_table[src_bits]; - curbit -= bpp; - cur++; - } - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -#endif /*LV_USE_GPU_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_utils.h b/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_utils.h deleted file mode 100644 index 9afae6879..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_utils.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @file lv_draw_sdl_utils.h - * - */ -#ifndef LV_DRAW_SDL_UTILS_H -#define LV_DRAW_SDL_UTILS_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ - -#include "../../lv_conf_internal.h" -#if LV_USE_GPU_SDL - -#include "lv_draw_sdl.h" -#include "../../misc/lv_color.h" -#include "../../misc/lv_area.h" - -#include LV_GPU_SDL_INCLUDE_PATH - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -void _lv_draw_sdl_utils_init(); - -void _lv_draw_sdl_utils_deinit(); - -void lv_area_to_sdl_rect(const lv_area_t * in, SDL_Rect * out); - -void lv_color_to_sdl_color(const lv_color_t * in, SDL_Color * out); - -void lv_area_zoom_to_sdl_rect(const lv_area_t * in, SDL_Rect * out, uint16_t zoom, const lv_point_t * pivot); - -SDL_Palette * lv_sdl_alloc_palette_for_bpp(const uint8_t * mapping, uint8_t bpp); - -SDL_Surface * lv_sdl_create_opa_surface(lv_opa_t * opa, lv_coord_t width, lv_coord_t height, lv_coord_t stride); - -SDL_Texture * lv_sdl_create_opa_texture(SDL_Renderer * renderer, lv_opa_t * pixels, lv_coord_t width, - lv_coord_t height, lv_coord_t stride); - -void lv_sdl_to_8bpp(uint8_t * dest, const uint8_t * src, int width, int height, int stride, uint8_t bpp); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_GPU_SDL*/ -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_SDL_UTILS_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_draw_stm32_dma2d.mk b/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_draw_stm32_dma2d.mk deleted file mode 100644 index 8ed00b015..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_draw_stm32_dma2d.mk +++ /dev/null @@ -1,6 +0,0 @@ -CSRCS += lv_gpu_stm32_dma2d.c - -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/stm32_dma2d" diff --git a/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c b/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c deleted file mode 100644 index 84da4b69c..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c +++ /dev/null @@ -1,796 +0,0 @@ -/** - * @file lv_gpu_stm32_dma2d.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_gpu_stm32_dma2d.h" -#include "../../core/lv_refr.h" - -#if LV_USE_GPU_STM32_DMA2D - -/********************* - * DEFINES - *********************/ -#if LV_COLOR_16_SWAP - // Note: DMA2D red/blue swap (RBS) works for all color modes - #define RBS_BIT 1U -#else - #define RBS_BIT 0U -#endif - -#define CACHE_ROW_SIZE 32U // cache row size in Bytes - -// For code/implementation discussion refer to https://github.com/lvgl/lvgl/issues/3714#issuecomment-1365187036 -// astyle --options=lvgl/scripts/code-format.cfg --ignore-exclude-errors lvgl/src/draw/stm32_dma2d/*.c lvgl/src/draw/stm32_dma2d/*.h - -#if LV_COLOR_DEPTH == 16 - const dma2d_color_format_t LvglColorFormat = RGB565; -#elif LV_COLOR_DEPTH == 32 - const dma2d_color_format_t LvglColorFormat = ARGB8888; -#else - #error "Cannot use DMA2D with LV_COLOR_DEPTH other than 16 or 32" -#endif - -#if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) - #define LV_STM32_DMA2D_USE_M7_CACHE -#endif - -#if defined (LV_STM32_DMA2D_USE_M7_CACHE) - // Cortex-M7 DCache present - #define __lv_gpu_stm32_dma2d_clean_cache(address, offset, width, height, pixel_size) _lv_gpu_stm32_dma2d_clean_cache(address, offset, width, height, pixel_size) - #define __lv_gpu_stm32_dma2d_invalidate_cache(address, offset, width, height, pixel_size) _lv_gpu_stm32_dma2d_invalidate_cache(address, offset, width, height, pixel_size) -#else - #define __lv_gpu_stm32_dma2d_clean_cache(address, offset, width, height, pixel_size) - #define __lv_gpu_stm32_dma2d_invalidate_cache(address, offset, width, height, pixel_size) -#endif - -/********************** - * STATIC PROTOTYPES - **********************/ -static void lv_draw_stm32_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); -static void lv_draw_stm32_dma2d_buffer_copy(lv_draw_ctx_t * draw_ctx, - void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area, - void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area); -static void lv_draw_stm32_dma2d_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * img_dsc, - const lv_area_t * coords, const uint8_t * src_buf, lv_img_cf_t color_format); -static dma2d_color_format_t lv_color_format_to_dma2d_color_format(lv_img_cf_t color_format); -static lv_point_t lv_area_get_offset(const lv_area_t * area1, const lv_area_t * area2); - -LV_STM32_DMA2D_STATIC void lv_gpu_stm32_dma2d_wait_cb(lv_draw_ctx_t * draw_ctx); -LV_STM32_DMA2D_STATIC lv_res_t lv_draw_stm32_dma2d_img(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * img_dsc, - const lv_area_t * src_area, const void * src); -LV_STM32_DMA2D_STATIC void _lv_draw_stm32_dma2d_blend_fill(const lv_color_t * dst_buf, lv_coord_t dst_stride, - const lv_area_t * draw_area, lv_color_t color, lv_opa_t opa); -LV_STM32_DMA2D_STATIC void _lv_draw_stm32_dma2d_blend_map(const lv_color_t * dest_buf, lv_coord_t dest_stride, - const lv_area_t * draw_area, const void * src_buf, lv_coord_t src_stride, const lv_point_t * src_offset, lv_opa_t opa, - dma2d_color_format_t src_color_format, bool ignore_src_alpha); -LV_STM32_DMA2D_STATIC void _lv_draw_stm32_dma2d_blend_paint(const lv_color_t * dst_buf, lv_coord_t dst_stride, - const lv_area_t * draw_area, const lv_opa_t * mask_buf, lv_coord_t mask_stride, const lv_point_t * mask_offset, - lv_color_t color, lv_opa_t opa); -LV_STM32_DMA2D_STATIC void _lv_draw_stm32_dma2d_copy_buffer(const lv_color_t * dest_buf, lv_coord_t dest_stride, - const lv_area_t * draw_area, const lv_color_t * src_buf, lv_coord_t src_stride, const lv_point_t * src_offset); -LV_STM32_DMA2D_STATIC void _lv_gpu_stm32_dma2d_await_dma_transfer_finish(lv_disp_drv_t * disp_drv); -LV_STM32_DMA2D_STATIC void _lv_gpu_stm32_dma2d_start_dma_transfer(void); - -#if defined (LV_STM32_DMA2D_USE_M7_CACHE) -LV_STM32_DMA2D_STATIC void _lv_gpu_stm32_dma2d_invalidate_cache(uint32_t address, lv_coord_t offset, - lv_coord_t width, lv_coord_t height, uint8_t pixel_size); -LV_STM32_DMA2D_STATIC void _lv_gpu_stm32_dma2d_clean_cache(uint32_t address, lv_coord_t offset, lv_coord_t width, - lv_coord_t height, uint8_t pixel_size); -#endif - -#if defined(LV_STM32_DMA2D_TEST) - LV_STM32_DMA2D_STATIC bool _lv_gpu_stm32_dwt_init(void); - LV_STM32_DMA2D_STATIC void _lv_gpu_stm32_dwt_reset(void); - LV_STM32_DMA2D_STATIC uint32_t _lv_gpu_stm32_dwt_get_us(void); -#endif - -static bool isDma2dInProgess = false; // indicates whether DMA2D transfer *initiated here* is in progress - -/** - * Turn on the peripheral and set output color mode, this only needs to be done once - */ -void lv_draw_stm32_dma2d_init(void) -{ - // Enable DMA2D clock -#if defined(STM32F4) || defined(STM32F7) || defined(STM32U5) - RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN; // enable DMA2D - // wait for hardware access to complete - __asm volatile("DSB\n"); - volatile uint32_t temp = RCC->AHB1ENR; - LV_UNUSED(temp); -#elif defined(STM32H7) - RCC->AHB3ENR |= RCC_AHB3ENR_DMA2DEN; - // wait for hardware access to complete - __asm volatile("DSB\n"); - volatile uint32_t temp = RCC->AHB3ENR; - LV_UNUSED(temp); -#else -# warning "LVGL can't enable the clock of DMA2D" -#endif - // AHB master timer configuration - DMA2D->AMTCR = 0; // AHB bus guaranteed dead time disabled -#if defined(LV_STM32_DMA2D_TEST) - _lv_gpu_stm32_dwt_init(); // init µs timer -#endif -} - -void lv_draw_stm32_dma2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) -{ - lv_draw_sw_init_ctx(drv, draw_ctx); - - lv_draw_stm32_dma2d_ctx_t * dma2d_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx; - - dma2d_draw_ctx->blend = lv_draw_stm32_dma2d_blend; - dma2d_draw_ctx->base_draw.draw_img_decoded = lv_draw_stm32_dma2d_img_decoded; - //dma2d_draw_ctx->base_draw.draw_img = lv_draw_stm32_dma2d_img; - // Note: currently it does not make sense use lv_gpu_stm32_dma2d_wait_cb() since waiting starts right after the dma2d transfer - //dma2d_draw_ctx->base_draw.wait_for_finish = lv_gpu_stm32_dma2d_wait_cb; - dma2d_draw_ctx->base_draw.buffer_copy = lv_draw_stm32_dma2d_buffer_copy; -} - -void lv_draw_stm32_dma2d_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) -{ - LV_UNUSED(drv); - LV_UNUSED(draw_ctx); -} - -static void lv_draw_stm32_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc) -{ - if(dsc->blend_mode != LV_BLEND_MODE_NORMAL) { - lv_draw_sw_blend_basic(draw_ctx, dsc); - return; - } - // Note: x1 must be zero. Otherwise, there is no way to correctly calculate dest_stride. - //LV_ASSERT_MSG(draw_ctx->buf_area->x1 == 0); // critical? - // Both draw buffer start address and buffer size *must* be 32-byte aligned since draw buffer cache is being invalidated. - //uint32_t drawBufferLength = lv_area_get_size(draw_ctx->buf_area) * sizeof(lv_color_t); - //LV_ASSERT_MSG(drawBufferLength % CACHE_ROW_SIZE == 0); // critical, but this is not the way to test it - //LV_ASSERT_MSG((uint32_t)draw_ctx->buf % CACHE_ROW_SIZE == 0, "draw_ctx.buf is not 32B aligned"); // critical? - - if(dsc->src_buf) { - // For performance reasons, both source buffer start address and buffer size *should* be 32-byte aligned since source buffer cache is being cleaned. - //uint32_t srcBufferLength = lv_area_get_size(dsc->blend_area) * sizeof(lv_color_t); - //LV_ASSERT_MSG(srcBufferLength % CACHE_ROW_SIZE == 0); // FIXME: assert fails (performance, non-critical) - //LV_ASSERT_MSG((uint32_t)dsc->src_buf % CACHE_ROW_SIZE == 0); // FIXME: assert fails (performance, non-critical) - } - - lv_area_t draw_area; - if(!_lv_area_intersect(&draw_area, dsc->blend_area, draw_ctx->clip_area)) return; - // + draw_ctx->buf_area has the entire draw buffer location - // + draw_ctx->clip_area has the current draw buffer location - // + dsc->blend_area has the location of the area intended to be painted - image etc. - // + draw_area has the area actually being painted - // All coordinates are relative to the screen. - - const lv_opa_t * mask = dsc->mask_buf; - - if(dsc->mask_buf && dsc->mask_res == LV_DRAW_MASK_RES_TRANSP) return; - else if(dsc->mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask = NULL; - - lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); - if(mask != NULL) { - // For performance reasons, both mask buffer start address and buffer size *should* be 32-byte aligned since mask buffer cache is being cleaned. - //uint32_t srcBufferLength = lv_area_get_size(dsc->mask_area) * sizeof(lv_opa_t); - //LV_ASSERT_MSG(srcBufferLength % CACHE_ROW_SIZE == 0); // FIXME: assert fails (performance, non-critical) - //LV_ASSERT_MSG((uint32_t)mask % CACHE_ROW_SIZE == 0); // FIXME: assert fails (performance, non-critical) - - lv_coord_t mask_stride = lv_area_get_width(dsc->mask_area); - lv_point_t mask_offset = lv_area_get_offset(dsc->mask_area, &draw_area); // mask offset in relation to draw_area - - if(dsc->src_buf == NULL) { // 93.5% - lv_area_move(&draw_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - _lv_draw_stm32_dma2d_blend_paint(draw_ctx->buf, dest_stride, &draw_area, mask, mask_stride, &mask_offset, dsc->color, - dsc->opa); - } - else { // 0.2% - // note: (x)RGB dsc->src_buf does not carry alpha channel bytes, - // alpha channel bytes are carried in dsc->mask_buf -#if LV_COLOR_DEPTH == 32 - lv_coord_t src_stride = lv_area_get_width(dsc->blend_area); - lv_point_t src_offset = lv_area_get_offset(dsc->blend_area, &draw_area); // source image offset in relation to draw_area - lv_coord_t draw_width = lv_area_get_width(&draw_area); - lv_coord_t draw_height = lv_area_get_height(&draw_area); - - // merge mask alpha bytes with src RGB bytes - // TODO: optimize by reading 4 or 8 mask bytes at a time - mask += (mask_stride * mask_offset.y) + mask_offset.x; - lv_color_t * src_buf = (lv_color_t *)dsc->src_buf; - src_buf += (src_stride * src_offset.y) + src_offset.x; - uint16_t mask_buffer_offset = mask_stride - draw_width; - uint16_t src_buffer_offset = src_stride - draw_width; - while(draw_height > 0) { - draw_height--; - for(uint16_t x = 0; x < draw_width; x++) { - (*src_buf).ch.alpha = *mask; - src_buf++; - mask++; - } - mask += mask_buffer_offset; - src_buf += src_buffer_offset; - } - - lv_area_move(&draw_area, -draw_ctx->buf_area->x1, - -draw_ctx->buf_area->y1); // translate the screen draw area to the origin of the buffer area - _lv_draw_stm32_dma2d_blend_map(draw_ctx->buf, dest_stride, &draw_area, dsc->src_buf, src_stride, &src_offset, dsc->opa, - ARGB8888, false); -#else - // Note: 16-bit bitmap hardware blending with mask and background is possible, but requires a temp 24 or 32-bit buffer to combine bitmap with mask first. - - lv_draw_sw_blend_basic(draw_ctx, dsc); // (e.g. Shop Items) - // clean cache after software drawing - this does not help since this is not the only place where buffer is written without dma2d - // lv_coord_t draw_width = lv_area_get_width(&draw_area); - // lv_coord_t draw_height = lv_area_get_height(&draw_area); - // uint32_t dest_address = (uint32_t)(draw_ctx->buf + (dest_stride * draw_area.y1) + draw_area.x1); - // __lv_gpu_stm32_dma2d_clean_cache(dest_address, dest_stride - draw_width, draw_width, draw_height, sizeof(lv_color_t)); -#endif - } - } - else { - if(dsc->src_buf == NULL) { // 6.1% - lv_area_move(&draw_area, -draw_ctx->buf_area->x1, - -draw_ctx->buf_area->y1); // translate the screen draw area to the origin of the buffer area - _lv_draw_stm32_dma2d_blend_fill(draw_ctx->buf, dest_stride, &draw_area, dsc->color, dsc->opa); - } - else { // 0.2% - lv_coord_t src_stride = lv_area_get_width(dsc->blend_area); - lv_point_t src_offset = lv_area_get_offset(dsc->blend_area, &draw_area); // source image offset in relation to draw_area - lv_area_move(&draw_area, -draw_ctx->buf_area->x1, - -draw_ctx->buf_area->y1); // translate the screen draw area to the origin of the buffer area - _lv_draw_stm32_dma2d_blend_map(draw_ctx->buf, dest_stride, &draw_area, dsc->src_buf, src_stride, &src_offset, dsc->opa, - LvglColorFormat, true); - } - } -} - -// Does dest_area = intersect(draw_ctx->clip_area, src_area) ? -// See: https://github.com/lvgl/lvgl/issues/3714#issuecomment-1331710788 -static void lv_draw_stm32_dma2d_buffer_copy(lv_draw_ctx_t * draw_ctx, void * dest_buf, lv_coord_t dest_stride, - const lv_area_t * dest_area, void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area) -{ - // Both draw buffer start address and buffer size *must* be 32-byte aligned since draw buffer cache is being invalidated. - //uint32_t drawBufferLength = lv_area_get_size(draw_ctx->buf_area) * sizeof(lv_color_t); - //LV_ASSERT_MSG(drawBufferLength % CACHE_ROW_SIZE == 0); // critical, but this is not the way to test it - //LV_ASSERT_MSG((uint32_t)draw_ctx->buf % CACHE_ROW_SIZE == 0, "draw_ctx.buf is not 32B aligned"); // critical? - // FIXME: - // 1. Both src_buf and dest_buf pixel size *must* be known to use DMA2D. - // 2. Verify both buffers start addresses and lengths are 32-byte (cache row size) aligned. - LV_UNUSED(draw_ctx); - lv_point_t src_offset = lv_area_get_offset(src_area, dest_area); - // FIXME: use lv_area_move(dest_area, -dest_area->x1, -dest_area->y1) here ? - // TODO: It is assumed that dest_buf and src_buf buffers are of lv_color_t type. Verify it, this assumption may be incorrect. - _lv_draw_stm32_dma2d_blend_map((const lv_color_t *)dest_buf, dest_stride, dest_area, (const lv_color_t *)src_buf, - src_stride, &src_offset, 0xff, LvglColorFormat, true); - // TODO: Investigate if output buffer cache needs to be invalidated. It depends on what the destination buffer is and how it is used next - by dma2d or not. - _lv_gpu_stm32_dma2d_await_dma_transfer_finish(NULL); // TODO: is this line needed here? -} - -static void lv_draw_stm32_dma2d_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * img_dsc, - const lv_area_t * coords, const uint8_t * src_buf, lv_img_cf_t color_format) -{ - if(draw_ctx->draw_img_decoded == NULL) return; - lv_area_t draw_area; - lv_area_copy(&draw_area, draw_ctx->clip_area); - - bool mask_any = lv_draw_mask_is_any(&draw_area); - bool transform = img_dsc->angle != 0 || img_dsc->zoom != LV_IMG_ZOOM_NONE; - const dma2d_color_format_t bitmapColorFormat = lv_color_format_to_dma2d_color_format(color_format); - const bool ignoreBitmapAlpha = (color_format == LV_IMG_CF_RGBX8888); - - if(!mask_any && !transform && bitmapColorFormat != UNSUPPORTED && img_dsc->recolor_opa == LV_OPA_TRANSP) { - // simple bitmap blending, optionally with supported color format conversion - handle directly by dma2d - lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); - lv_coord_t src_stride = lv_area_get_width(coords); - lv_point_t src_offset = lv_area_get_offset(coords, &draw_area); // source image offset in relation to draw_area - lv_area_move(&draw_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - _lv_draw_stm32_dma2d_blend_map(draw_ctx->buf, dest_stride, &draw_area, src_buf, src_stride, &src_offset, - img_dsc->opa, bitmapColorFormat, ignoreBitmapAlpha); - } - else { - // all more complex cases which require additional image transformations - lv_draw_sw_img_decoded(draw_ctx, img_dsc, coords, src_buf, color_format); - - } -} - -static lv_point_t lv_area_get_offset(const lv_area_t * area1, const lv_area_t * area2) -{ - lv_point_t offset = {x: area2->x1 - area1->x1, y: area2->y1 - area1->y1}; - return offset; -} - -static dma2d_color_format_t lv_color_format_to_dma2d_color_format(lv_img_cf_t color_format) -{ - switch(color_format) { - case LV_IMG_CF_RGBA8888: - // note: LV_IMG_CF_RGBA8888 is actually ARGB8888 - return ARGB8888; - case LV_IMG_CF_RGBX8888: - // note: LV_IMG_CF_RGBX8888 is actually XRGB8888 - return ARGB8888; - case LV_IMG_CF_RGB565: - return RGB565; - case LV_IMG_CF_TRUE_COLOR: - return LvglColorFormat; - case LV_IMG_CF_TRUE_COLOR_ALPHA: -#if LV_COLOR_DEPTH == 16 - // bitmap color format is 24b ARGB8565 - dma2d unsupported - return UNSUPPORTED; -#elif LV_COLOR_DEPTH == 32 - return ARGB8888; -#else - // unknown bitmap color format - return UNSUPPORTED; -#endif - default: - return UNSUPPORTED; - } -} - -LV_STM32_DMA2D_STATIC lv_res_t lv_draw_stm32_dma2d_img(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * img_dsc, - const lv_area_t * src_area, const void * src) -{ - //if(lv_img_src_get_type(src) != LV_IMG_SRC_VARIABLE) return LV_RES_INV; - return LV_RES_INV; - if(img_dsc->opa <= LV_OPA_MIN) return LV_RES_OK; - const lv_img_dsc_t * img = src; - const dma2d_color_format_t bitmapColorFormat = lv_color_format_to_dma2d_color_format(img->header.cf); - const bool ignoreBitmapAlpha = (img->header.cf == LV_IMG_CF_RGBX8888); - - if(bitmapColorFormat == UNSUPPORTED || img_dsc->angle != 0 || img_dsc->zoom != LV_IMG_ZOOM_NONE) { - return LV_RES_INV; // sorry, dma2d can handle this - } - - // FIXME: handle dsc.pivot, dsc.recolor, dsc.blend_mode - // FIXME: src pixel size *must* be known to use DMA2D - // FIXME: If image is drawn by SW, then output cache needs to be cleaned next. Currently it is not possible. - // Both draw buffer start address and buffer size *must* be 32-byte aligned since draw buffer cache is being invalidated. - //uint32_t drawBufferLength = lv_area_get_size(draw_ctx->buf_area) * sizeof(lv_color_t); - //LV_ASSERT_MSG(drawBufferLength % CACHE_ROW_SIZE == 0); // critical, but this is not the way to test it - //LV_ASSERT_MSG((uint32_t)draw_ctx->buf % CACHE_ROW_SIZE == 0, "draw_ctx.buf is not 32B aligned"); // critical? - - // For performance reasons, both source buffer start address and buffer size *should* be 32-byte aligned since source buffer cache is being cleaned. - //uint32_t srcBufferLength = lv_area_get_size(src_area) * sizeof(lv_color_t); // TODO: verify src pixel size = sizeof(lv_color_t) - //LV_ASSERT_MSG(srcBufferLength % CACHE_ROW_SIZE == 0); // FIXME: assert fails (performance, non-critical) - //LV_ASSERT_MSG((uint32_t)src % CACHE_ROW_SIZE == 0); // FIXME: assert fails (performance, non-critical) - - lv_area_t draw_area; - if(!_lv_area_intersect(&draw_area, src_area, draw_ctx->clip_area)) return LV_RES_OK; - - lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); - lv_point_t src_offset = lv_area_get_offset(src_area, &draw_area); // source image offset in relation to draw_area - lv_area_move(&draw_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - _lv_draw_stm32_dma2d_blend_map(draw_ctx->buf, dest_stride, &draw_area, img->data, img->header.w, - &src_offset, img_dsc->opa, bitmapColorFormat, ignoreBitmapAlpha); - return LV_RES_OK; -} - -LV_STM32_DMA2D_STATIC void lv_gpu_stm32_dma2d_wait_cb(lv_draw_ctx_t * draw_ctx) -{ - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - _lv_gpu_stm32_dma2d_await_dma_transfer_finish(disp->driver); - lv_draw_sw_wait_for_finish(draw_ctx); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * @brief Fills draw_area with specified color. - * @param color color to be painted, note: alpha is ignored - */ -LV_STM32_DMA2D_STATIC void _lv_draw_stm32_dma2d_blend_fill(const lv_color_t * dest_buf, lv_coord_t dest_stride, - const lv_area_t * draw_area, lv_color_t color, lv_opa_t opa) -{ - LV_ASSERT_MSG(!isDma2dInProgess, "dma2d transfer has not finished"); // critical - lv_coord_t draw_width = lv_area_get_width(draw_area); - lv_coord_t draw_height = lv_area_get_height(draw_area); - - _lv_gpu_stm32_dma2d_await_dma_transfer_finish(NULL); - - if(opa >= LV_OPA_MAX) { - DMA2D->CR = 0x3UL << DMA2D_CR_MODE_Pos; // Register-to-memory (no FG nor BG, only output stage active) - - DMA2D->OPFCCR = LvglColorFormat; -#if defined(DMA2D_OPFCCR_RBS_Pos) - DMA2D->OPFCCR |= (RBS_BIT << DMA2D_OPFCCR_RBS_Pos); -#endif - DMA2D->OMAR = (uint32_t)(dest_buf + (dest_stride * draw_area->y1) + draw_area->x1); - DMA2D->OOR = dest_stride - draw_width; // out buffer offset - // Note: unlike FGCOLR and BGCOLR, OCOLR bits must match DMA2D_OUTPUT_COLOR, alpha can be specified -#if RBS_BIT - // swap red/blue bits - DMA2D->OCOLR = (color.ch.blue << 11) | (color.ch.green_l << 5 | color.ch.green_h << 8) | (color.ch.red); -#else - DMA2D->OCOLR = color.full; -#endif - } - else { - DMA2D->CR = 0x2UL << DMA2D_CR_MODE_Pos; // Memory-to-memory with blending (FG and BG fetch with PFC and blending) - - DMA2D->FGPFCCR = A8; - DMA2D->FGPFCCR |= (opa << DMA2D_FGPFCCR_ALPHA_Pos); - // Alpha Mode 1: Replace original foreground image alpha channel value by FGPFCCR.ALPHA - DMA2D->FGPFCCR |= (0x1UL << DMA2D_FGPFCCR_AM_Pos); - //DMA2D->FGPFCCR |= (RBS_BIT << DMA2D_FGPFCCR_RBS_Pos); - - // Note: in Alpha Mode 1 FGMAR and FGOR are not used to supply foreground A8 bytes, - // those bytes are replaced by constant ALPHA defined in FGPFCCR - DMA2D->FGMAR = (uint32_t)dest_buf; - DMA2D->FGOR = dest_stride; - DMA2D->FGCOLR = lv_color_to32(color) & 0x00ffffff; // swap FGCOLR R/B bits if FGPFCCR.RBS (RBS_BIT) bit is set - - DMA2D->BGPFCCR = LvglColorFormat; -#if defined(DMA2D_BGPFCCR_RBS_Pos) - DMA2D->BGPFCCR |= (RBS_BIT << DMA2D_BGPFCCR_RBS_Pos); -#endif - DMA2D->BGMAR = (uint32_t)(dest_buf + (dest_stride * draw_area->y1) + draw_area->x1); - DMA2D->BGOR = dest_stride - draw_width; - DMA2D->BGCOLR = 0; // used in A4 and A8 modes only - __lv_gpu_stm32_dma2d_clean_cache(DMA2D->BGMAR, DMA2D->BGOR, draw_width, draw_height, sizeof(lv_color_t)); - - DMA2D->OPFCCR = LvglColorFormat; -#if defined(DMA2D_OPFCCR_RBS_Pos) - DMA2D->OPFCCR |= (RBS_BIT << DMA2D_OPFCCR_RBS_Pos); -#endif - DMA2D->OMAR = DMA2D->BGMAR; - DMA2D->OOR = DMA2D->BGOR; - DMA2D->OCOLR = 0; - } - // PL - pixel per lines (14 bit), NL - number of lines (16 bit) - DMA2D->NLR = (draw_width << DMA2D_NLR_PL_Pos) | (draw_height << DMA2D_NLR_NL_Pos); - - _lv_gpu_stm32_dma2d_start_dma_transfer(); -} - -/** - * @brief Draws src (foreground) map on dst (background) map. - * @param src_offset src offset in relation to dst, useful when src is larger than draw_area - * @param opa constant opacity to be applied - * @param bitmapColorCode bitmap color type - * @param ignoreAlpha if TRUE, bitmap src alpha channel is ignored - */ -LV_STM32_DMA2D_STATIC void _lv_draw_stm32_dma2d_blend_map(const lv_color_t * dest_buf, lv_coord_t dest_stride, - const lv_area_t * draw_area, const void * src_buf, lv_coord_t src_stride, const lv_point_t * src_offset, lv_opa_t opa, - dma2d_color_format_t src_color_format, bool ignore_src_alpha) -{ - LV_ASSERT_MSG(!isDma2dInProgess, "dma2d transfer has not finished"); // critical - if(opa <= LV_OPA_MIN || src_color_format == UNSUPPORTED) return; - lv_coord_t draw_width = lv_area_get_width(draw_area); - lv_coord_t draw_height = lv_area_get_height(draw_area); - bool bitmapHasOpacity = !ignore_src_alpha && (src_color_format == ARGB8888 || src_color_format == ARGB1555 || - src_color_format == ARGB4444); - - if(opa >= LV_OPA_MAX) opa = 0xff; - - uint8_t srcBpp; // source bytes per pixel - switch(src_color_format) { - case ARGB8888: - srcBpp = 4; - break; - case RGB888: - srcBpp = 3; - break; - case RGB565: - case ARGB1555: - case ARGB4444: - srcBpp = 2; - break; - default: - LV_LOG_ERROR("unsupported color format"); - return; - } - - _lv_gpu_stm32_dma2d_await_dma_transfer_finish(NULL); - - DMA2D->FGPFCCR = src_color_format; - - if(opa == 0xff && !bitmapHasOpacity) { - // no need to blend - if(src_color_format == LvglColorFormat) { - // no need to convert pixel format (PFC) either - DMA2D->CR = 0x0UL; - } - else { - DMA2D->CR = 0x1UL << DMA2D_CR_MODE_Pos; // Memory-to-memory with PFC (FG fetch only with FG PFC active) - } - // Alpha Mode 0: No modification of the foreground image alpha channel value - } - else { - // blend - DMA2D->CR = 0x2UL << DMA2D_CR_MODE_Pos; // Memory-to-memory with blending (FG and BG fetch with PFC and blending) - DMA2D->FGPFCCR |= (opa << DMA2D_FGPFCCR_ALPHA_Pos); - if(bitmapHasOpacity) { - // Alpha Mode 2: Replace original foreground image alpha channel value by FGPFCCR.ALPHA multiplied with original alpha channel value - DMA2D->FGPFCCR |= (0x2UL << DMA2D_FGPFCCR_AM_Pos); - } - else { - // Alpha Mode 1: Replace original foreground image alpha channel value by FGPFCCR.ALPHA - DMA2D->FGPFCCR |= (0x1UL << DMA2D_FGPFCCR_AM_Pos); - } - } -#if defined(DMA2D_FGPFCCR_RBS_Pos) - DMA2D->FGPFCCR |= (RBS_BIT << DMA2D_FGPFCCR_RBS_Pos); -#endif - DMA2D->FGMAR = ((uint32_t)src_buf) + srcBpp * ((src_stride * src_offset->y) + src_offset->x); - DMA2D->FGOR = src_stride - draw_width; - DMA2D->FGCOLR = 0; // used in A4 and A8 modes only - __lv_gpu_stm32_dma2d_clean_cache(DMA2D->FGMAR, DMA2D->FGOR, draw_width, draw_height, srcBpp); - - DMA2D->OPFCCR = LvglColorFormat; -#if defined(DMA2D_OPFCCR_RBS_Pos) - DMA2D->OPFCCR |= (RBS_BIT << DMA2D_OPFCCR_RBS_Pos); -#endif - DMA2D->OMAR = (uint32_t)(dest_buf + (dest_stride * draw_area->y1) + draw_area->x1); - DMA2D->OOR = dest_stride - draw_width; - DMA2D->OCOLR = 0; - - if(opa != 0xff || bitmapHasOpacity) { - // use background (BG*) registers - DMA2D->BGPFCCR = LvglColorFormat; -#if defined(DMA2D_BGPFCCR_RBS_Pos) - DMA2D->BGPFCCR |= (RBS_BIT << DMA2D_BGPFCCR_RBS_Pos); -#endif - DMA2D->BGMAR = DMA2D->OMAR; - DMA2D->BGOR = DMA2D->OOR; - DMA2D->BGCOLR = 0; // used in A4 and A8 modes only - __lv_gpu_stm32_dma2d_clean_cache(DMA2D->BGMAR, DMA2D->BGOR, draw_width, draw_height, sizeof(lv_color_t)); - } - - // PL - pixel per lines (14 bit), NL - number of lines (16 bit) - DMA2D->NLR = (draw_width << DMA2D_NLR_PL_Pos) | (draw_height << DMA2D_NLR_NL_Pos); - - _lv_gpu_stm32_dma2d_start_dma_transfer(); -} - -/** - * @brief Paints solid color with alpha mask with additional constant opacity. Useful e.g. for painting anti-aliased fonts. - * @param src_offset src offset in relation to dst, useful when src (alpha mask) is larger than draw_area - * @param color color to paint, note: alpha is ignored - * @param opa constant opacity to be applied - */ -LV_STM32_DMA2D_STATIC void _lv_draw_stm32_dma2d_blend_paint(const lv_color_t * dest_buf, lv_coord_t dest_stride, - const lv_area_t * draw_area, const lv_opa_t * mask_buf, lv_coord_t mask_stride, const lv_point_t * mask_offset, - lv_color_t color, lv_opa_t opa) -{ - LV_ASSERT_MSG(!isDma2dInProgess, "dma2d transfer has not finished"); // critical - lv_coord_t draw_width = lv_area_get_width(draw_area); - lv_coord_t draw_height = lv_area_get_height(draw_area); - - _lv_gpu_stm32_dma2d_await_dma_transfer_finish(NULL); - - DMA2D->CR = 0x2UL << DMA2D_CR_MODE_Pos; // Memory-to-memory with blending (FG and BG fetch with PFC and blending) - - DMA2D->FGPFCCR = A8; - if(opa < LV_OPA_MAX) { - DMA2D->FGPFCCR |= (opa << DMA2D_FGPFCCR_ALPHA_Pos); - DMA2D->FGPFCCR |= (0x2UL << - DMA2D_FGPFCCR_AM_Pos); // Alpha Mode: Replace original foreground image alpha channel value by FGPFCCR.ALPHA multiplied with original alpha channel value - } - //DMA2D->FGPFCCR |= (RBS_BIT << DMA2D_FGPFCCR_RBS_Pos); - DMA2D->FGMAR = (uint32_t)(mask_buf + (mask_stride * mask_offset->y) + mask_offset->x); - DMA2D->FGOR = mask_stride - draw_width; - DMA2D->FGCOLR = lv_color_to32(color) & 0x00ffffff; // swap FGCOLR R/B bits if FGPFCCR.RBS (RBS_BIT) bit is set - __lv_gpu_stm32_dma2d_clean_cache(DMA2D->FGMAR, DMA2D->FGOR, draw_width, draw_height, sizeof(lv_opa_t)); - - DMA2D->BGPFCCR = LvglColorFormat; -#if defined(DMA2D_BGPFCCR_RBS_Pos) - DMA2D->BGPFCCR |= (RBS_BIT << DMA2D_BGPFCCR_RBS_Pos); -#endif - DMA2D->BGMAR = (uint32_t)(dest_buf + (dest_stride * draw_area->y1) + draw_area->x1); - DMA2D->BGOR = dest_stride - draw_width; - DMA2D->BGCOLR = 0; // used in A4 and A8 modes only - __lv_gpu_stm32_dma2d_clean_cache(DMA2D->BGMAR, DMA2D->BGOR, draw_width, draw_height, sizeof(lv_color_t)); - - DMA2D->OPFCCR = LvglColorFormat; -#if defined(DMA2D_OPFCCR_RBS_Pos) - DMA2D->OPFCCR |= (RBS_BIT << DMA2D_OPFCCR_RBS_Pos); -#endif - DMA2D->OMAR = DMA2D->BGMAR; - DMA2D->OOR = DMA2D->BGOR; - DMA2D->OCOLR = 0; - // PL - pixel per lines (14 bit), NL - number of lines (16 bit) - DMA2D->NLR = (draw_width << DMA2D_NLR_PL_Pos) | (draw_height << DMA2D_NLR_NL_Pos); - - _lv_gpu_stm32_dma2d_start_dma_transfer(); -} - -/** - * @brief Copies src (foreground) map to the dst (background) map. - * @param src_offset src offset in relation to dst, useful when src is larger than draw_area - */ -LV_STM32_DMA2D_STATIC void _lv_draw_stm32_dma2d_copy_buffer(const lv_color_t * dest_buf, lv_coord_t dest_stride, - const lv_area_t * draw_area, const lv_color_t * src_buf, lv_coord_t src_stride, const lv_point_t * src_offset) -{ - LV_ASSERT_MSG(!isDma2dInProgess, "dma2d transfer has not finished"); // critical - lv_coord_t draw_width = lv_area_get_width(draw_area); - lv_coord_t draw_height = lv_area_get_height(draw_area); - - _lv_gpu_stm32_dma2d_await_dma_transfer_finish(NULL); - - DMA2D->CR = 0x0UL; // Memory-to-memory (FG fetch only) - - DMA2D->FGPFCCR = LvglColorFormat; -#if defined(DMA2D_FGPFCCR_RBS_Pos) - DMA2D->FGPFCCR |= (RBS_BIT << DMA2D_FGPFCCR_RBS_Pos); -#endif - DMA2D->FGMAR = (uint32_t)(src_buf + (src_stride * src_offset->y) + src_offset->x); - DMA2D->FGOR = src_stride - draw_width; - DMA2D->FGCOLR = 0; // used in A4 and A8 modes only - __lv_gpu_stm32_dma2d_clean_cache(DMA2D->FGMAR, DMA2D->FGOR, draw_width, draw_height, sizeof(lv_color_t)); - - // Note BG* registers do not need to be set up since BG is not used - - DMA2D->OPFCCR = LvglColorFormat; -#if defined(DMA2D_OPFCCR_RBS_Pos) - DMA2D->OPFCCR |= (RBS_BIT << DMA2D_OPFCCR_RBS_Pos); -#endif - DMA2D->OMAR = (uint32_t)(dest_buf + (dest_stride * draw_area->y1) + draw_area->x1); - DMA2D->OOR = dest_stride - draw_width; - DMA2D->OCOLR = 0; - - // PL - pixel per lines (14 bit), NL - number of lines (16 bit) - DMA2D->NLR = (draw_width << DMA2D_NLR_PL_Pos) | (draw_height << DMA2D_NLR_NL_Pos); - - _lv_gpu_stm32_dma2d_start_dma_transfer(); -} - -LV_STM32_DMA2D_STATIC void _lv_gpu_stm32_dma2d_start_dma_transfer(void) -{ - LV_ASSERT_MSG(!isDma2dInProgess, "dma2d transfer has not finished"); - isDma2dInProgess = true; - DMA2D->IFCR = 0x3FU; // trigger ISR flags reset - // Note: cleaning output buffer cache is needed only when buffer may be misaligned or adjacent area may have been drawn in sw-fashion, e.g. using lv_draw_sw_blend_basic() -#if LV_COLOR_DEPTH == 16 - __lv_gpu_stm32_dma2d_clean_cache(DMA2D->OMAR, DMA2D->OOR, (DMA2D->NLR & DMA2D_NLR_PL_Msk) >> DMA2D_NLR_PL_Pos, - (DMA2D->NLR & DMA2D_NLR_NL_Msk) >> DMA2D_NLR_NL_Pos, sizeof(lv_color_t)); -#endif - DMA2D->CR |= DMA2D_CR_START; - // Note: for some reason mask buffer gets damaged during transfer if waiting is postponed - _lv_gpu_stm32_dma2d_await_dma_transfer_finish(NULL); // FIXME: this line should not be needed here, but it is -} - -LV_STM32_DMA2D_STATIC void _lv_gpu_stm32_dma2d_await_dma_transfer_finish(lv_disp_drv_t * disp_drv) -{ - if(disp_drv && disp_drv->wait_cb) { - while((DMA2D->CR & DMA2D_CR_START) != 0U) { - disp_drv->wait_cb(disp_drv); - } - } - else { - while((DMA2D->CR & DMA2D_CR_START) != 0U); - } - - __IO uint32_t isrFlags = DMA2D->ISR; - - if(isrFlags & DMA2D_ISR_CEIF) { - LV_LOG_ERROR("DMA2D config error"); - } - - if(isrFlags & DMA2D_ISR_TEIF) { - LV_LOG_ERROR("DMA2D transfer error"); - } - - DMA2D->IFCR = 0x3FU; // trigger ISR flags reset - - if(isDma2dInProgess) { - // invalidate output buffer cached memory ONLY after DMA2D transfer - //__lv_gpu_stm32_dma2d_invalidate_cache(DMA2D->OMAR, DMA2D->OOR, (DMA2D->NLR & DMA2D_NLR_PL_Msk) >> DMA2D_NLR_PL_Pos, (DMA2D->NLR & DMA2D_NLR_NL_Msk) >> DMA2D_NLR_NL_Pos, sizeof(lv_color_t)); - isDma2dInProgess = false; - } -} - -#if defined (LV_STM32_DMA2D_USE_M7_CACHE) -// Cortex-M7 DCache present -LV_STM32_DMA2D_STATIC void _lv_gpu_stm32_dma2d_invalidate_cache(uint32_t address, lv_coord_t offset, lv_coord_t width, - lv_coord_t height, uint8_t pixel_size) -{ - if(((SCB->CCR) & SCB_CCR_DC_Msk) == 0) return; // L1 data cache is disabled - uint16_t stride = pixel_size * (width + offset); // in bytes - uint16_t ll = pixel_size * width; // line length in bytes - uint32_t n = 0; // address of the next cache row after the last invalidated row - lv_coord_t h = 0; - - __DSB(); - - while(h < height) { - uint32_t a = address + (h * stride); - uint32_t e = a + ll; // end address, address of the first byte after the current line - a &= ~(CACHE_ROW_SIZE - 1U); - if(a < n) a = n; // prevent the previous last cache row from being invalidated again - - while(a < e) { - SCB->DCIMVAC = a; - a += CACHE_ROW_SIZE; - } - - n = a; - h++; - }; - - __DSB(); - __ISB(); -} - -LV_STM32_DMA2D_STATIC void _lv_gpu_stm32_dma2d_clean_cache(uint32_t address, lv_coord_t offset, lv_coord_t width, - lv_coord_t height, uint8_t pixel_size) -{ - if(((SCB->CCR) & SCB_CCR_DC_Msk) == 0) return; // L1 data cache is disabled - uint16_t stride = pixel_size * (width + offset); // in bytes - uint16_t ll = pixel_size * width; // line length in bytes - uint32_t n = 0; // address of the next cache row after the last cleaned row - lv_coord_t h = 0; - __DSB(); - - while(h < height) { - uint32_t a = address + (h * stride); - uint32_t e = a + ll; // end address, address of the first byte after the current line - a &= ~(CACHE_ROW_SIZE - 1U); - if(a < n) a = n; // prevent the previous last cache row from being cleaned again - - while(a < e) { - SCB->DCCMVAC = a; - a += CACHE_ROW_SIZE; - } - - n = a; - h++; - }; - - __DSB(); - __ISB(); -} -#endif // LV_STM32_DMA2D_USE_M7_CACHE - -#if defined(LV_STM32_DMA2D_TEST) -// initialize µs timer -LV_STM32_DMA2D_STATIC bool _lv_gpu_stm32_dwt_init(void) -{ - // disable TRC - CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk; - // enable TRC - CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; - -#if defined(__CORTEX_M) && (__CORTEX_M == 7U) - DWT->LAR = 0xC5ACCE55; -#endif - // disable clock cycle counter - DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; - // enable clock cycle counter - DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; - - // reset the clock cycle counter value - DWT->CYCCNT = 0; - - // 3 NO OPERATION instructions - __ASM volatile("NOP"); - __ASM volatile("NOP"); - __ASM volatile("NOP"); - - // check if clock cycle counter has started - if(DWT->CYCCNT) { - return true; // clock cycle counter started - } - else { - return false; // clock cycle counter not started - } -} - -// get elapsed µs since reset -LV_STM32_DMA2D_STATIC uint32_t _lv_gpu_stm32_dwt_get_us(void) -{ - uint32_t us = (DWT->CYCCNT * 1000000) / HAL_RCC_GetHCLKFreq(); - return us; -} - -// reset µs timer -LV_STM32_DMA2D_STATIC void _lv_gpu_stm32_dwt_reset(void) -{ - DWT->CYCCNT = 0; -} -#endif // LV_STM32_DMA2D_TEST -#endif // LV_USE_GPU_STM32_DMA2D \ No newline at end of file diff --git a/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h b/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h deleted file mode 100644 index 0a970426d..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @file lv_gpu_stm32_dma2d.h - * - */ - -#ifndef LV_GPU_STM32_DMA2D_H -#define LV_GPU_STM32_DMA2D_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "../../misc/lv_color.h" -#include "../../hal/lv_hal_disp.h" -#include "../sw/lv_draw_sw.h" - -#if LV_USE_GPU_STM32_DMA2D - -/********************* - * INCLUDES - *********************/ -#include LV_GPU_DMA2D_CMSIS_INCLUDE - -/********************* - * DEFINES - *********************/ -#if defined(LV_STM32_DMA2D_TEST) -// removes "static" modifier for some internal methods in order to test them -#define LV_STM32_DMA2D_STATIC -#else -#define LV_STM32_DMA2D_STATIC static -#endif - -/********************** - * TYPEDEFS - **********************/ -enum dma2d_color_format { - ARGB8888 = 0x0, - RGB888 = 0x01, - RGB565 = 0x02, - ARGB1555 = 0x03, - ARGB4444 = 0x04, - A8 = 0x09, - UNSUPPORTED = 0xff, -}; -typedef enum dma2d_color_format dma2d_color_format_t; -typedef lv_draw_sw_ctx_t lv_draw_stm32_dma2d_ctx_t; -struct _lv_disp_drv_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ -void lv_draw_stm32_dma2d_init(void); -void lv_draw_stm32_dma2d_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); -void lv_draw_stm32_dma2d_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_GPU_STM32_DMA2D*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_GPU_STM32_DMA2D_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/arm2d/lv_draw_sw_arm2d.h b/lib/libesp32_lvgl/lvgl/src/draw/sw/arm2d/lv_draw_sw_arm2d.h new file mode 100644 index 000000000..62445ee22 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/arm2d/lv_draw_sw_arm2d.h @@ -0,0 +1,564 @@ +/** + * @file lv_draw_sw_arm2d.h + * + */ + +#ifndef LV_DRAW_SW_ARM2D_H +#define LV_DRAW_SW_ARM2D_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* *INDENT-OFF* */ + +/********************* + * INCLUDES + *********************/ + +#include "../../../lv_conf_internal.h" + +#if LV_USE_DRAW_ARM2D_SYNC + +#define __ARM_2D_IMPL__ +#include "arm_2d.h" +#include "__arm_2d_impl.h" + +#if defined(__IS_COMPILER_ARM_COMPILER_5__) +#pragma diag_suppress 174,177,188,68,513,144,1296 +#elif defined(__IS_COMPILER_IAR__) +#pragma diag_suppress=Pa093 +#elif defined(__IS_COMPILER_GCC__) +#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" +#endif + +/********************* + * DEFINES + *********************/ +#ifndef LV_DRAW_SW_RGB565_SWAP + #define LV_DRAW_SW_RGB565_SWAP(__buf_ptr, __buf_size_px) \ + _lv_draw_sw_rgb565_swap_helium((__buf_ptr), (__buf_size_px)) +#endif + +#ifndef LV_DRAW_SW_IMAGE + #define LV_DRAW_SW_IMAGE(__transformed, \ + __cf, \ + __src_buf, \ + __img_coords, \ + __src_stride, \ + __blend_area, \ + __draw_unit, \ + __draw_dsc) \ + _lv_draw_sw_image_helium( (__transformed), \ + (__cf), \ + (uint8_t *)(__src_buf), \ + (__img_coords), \ + (__src_stride), \ + (__blend_area), \ + (__draw_unit), \ + (__draw_dsc)) +#endif + +#ifndef LV_DRAW_SW_RGB565_RECOLOR + #define LV_DRAW_SW_RGB565_RECOLOR(__src_buf, __blend_area, __color, __opa) \ + _lv_draw_sw_image_recolor_rgb565( (__src_buf), \ + &(__blend_area), \ + (__color), \ + (__opa)) +#endif + +#ifndef LV_DRAW_SW_RGB888_RECOLOR + #define LV_DRAW_SW_RGB888_RECOLOR( __src_buf, \ + __blend_area, \ + __color, \ + __opa, \ + __cf) \ + _lv_draw_sw_image_recolor_rgb888( (__src_buf), \ + &(__blend_area), \ + (__color), \ + (__opa), \ + (__cf)) +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +extern void arm_2d_helper_swap_rgb16(uint16_t * phwBuffer, uint32_t wCount); + +/********************** + * MACROS + **********************/ + +#define __RECOLOUR_BEGIN() \ + do { \ + lv_color_t *rgb_tmp_buf = NULL; \ + if(draw_dsc->recolor_opa > LV_OPA_MIN) { \ + if(LV_COLOR_FORMAT_RGB565 == des_cf) { \ + rgb_tmp_buf \ + = lv_malloc(src_w * src_h * sizeof(uint16_t)); \ + if (NULL == rgb_tmp_buf) { \ + LV_LOG_WARN( \ + "Failed to allocate memory for accelerating recolor, " \ + "use normal route instead."); \ + break; \ + } \ + lv_memcpy( rgb_tmp_buf, \ + src_buf, \ + src_w * src_h * sizeof(uint16_t)); \ + arm_2d_size_t copy_size = { \ + .iWidth = src_w, \ + .iHeight = src_h, \ + }; \ + /* apply re-color */ \ + __arm_2d_impl_rgb565_colour_filling_with_opacity( \ + (uint16_t *)rgb_tmp_buf, \ + src_w, \ + ©_size, \ + lv_color_to_u16(draw_dsc->recolor), \ + draw_dsc->recolor_opa); \ + \ + /* replace src_buf for the following operation */ \ + src_buf = (const uint8_t *)rgb_tmp_buf; \ + } \ + else if(LV_COLOR_FORMAT_XRGB8888 == des_cf) { \ + rgb_tmp_buf \ + = lv_malloc(src_w * src_h * sizeof(uint32_t)); \ + if (NULL == rgb_tmp_buf) { \ + LV_LOG_WARN( \ + "Failed to allocate memory for accelerating recolor, " \ + "use normal route instead."); \ + break; \ + } \ + lv_memcpy( rgb_tmp_buf, \ + src_buf, \ + src_w * src_h * sizeof(uint32_t)); \ + arm_2d_size_t copy_size = { \ + .iWidth = src_w, \ + .iHeight = src_h, \ + }; \ + /* apply re-color */ \ + __arm_2d_impl_cccn888_colour_filling_with_opacity( \ + (uint32_t *)rgb_tmp_buf, \ + src_w, \ + ©_size, \ + lv_color_to_u32(draw_dsc->recolor), \ + draw_dsc->recolor_opa); \ + \ + /* replace src_buf for the following operation */ \ + src_buf = (const uint8_t *)rgb_tmp_buf; \ + } \ + } \ + do { + +#define __RECOLOUR_END() \ + } while(0); \ + if (NULL != rgb_tmp_buf) { \ + lv_free(rgb_tmp_buf); \ + } \ + } while(0); + +static inline lv_result_t _lv_draw_sw_rgb565_swap_helium(void * buf, uint32_t buf_size_px) +{ + arm_2d_helper_swap_rgb16((uint16_t *)buf, buf_size_px); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_draw_sw_image_helium( + bool is_transform, + lv_color_format_t src_cf, + const uint8_t *src_buf, + const lv_area_t * coords, + int32_t src_stride, + const lv_area_t * des_area, + lv_draw_unit_t * draw_unit, + const lv_draw_image_dsc_t * draw_dsc) +{ + lv_result_t result = LV_RESULT_INVALID; + lv_layer_t * layer = draw_unit->target_layer; + lv_color_format_t des_cf = layer->color_format; + static bool arm_2d_initialized = false; + + if (!arm_2d_initialized) { + arm_2d_initialized = true; + arm_2d_init(); + } + + do { + if (!is_transform) { + break; + } + if(draw_dsc->scale_x != draw_dsc->scale_y) { + break; + } + /* filter the unsupported colour format combination */ + if((LV_COLOR_FORMAT_RGB565 == des_cf) + && !( (LV_COLOR_FORMAT_RGB565 == src_cf) + || (LV_COLOR_FORMAT_RGB565A8 == src_cf))) { + break; + } + if((LV_COLOR_FORMAT_XRGB8888 == des_cf) + && !( (LV_COLOR_FORMAT_ARGB8888 == src_cf) + || (LV_COLOR_FORMAT_XRGB8888 == src_cf))) { + break; + } + + /* ------------- prepare parameters for arm-2d APIs - BEGIN --------- */ + + lv_area_t blend_area; + if(!_lv_area_intersect(&blend_area, des_area, draw_unit->clip_area)) { + break; + } + + int32_t src_w = lv_area_get_width(coords); + int32_t src_h = lv_area_get_height(coords); + + arm_2d_size_t src_size = { + .iWidth = (int16_t)src_w, + .iHeight = (int16_t)src_h, + }; + +// arm_2d_size_t des_size; + +// do{ +// int32_t des_w = lv_area_get_width(&blend_area); +// int32_t des_h = lv_area_get_height(&blend_area); + +// LV_ASSERT(des_w <= INT16_MAX); +// LV_ASSERT(des_h <= INT16_MAX); + +// des_size.iWidth = (int16_t)des_w; +// des_size.iHeight = (int16_t)des_h; +// } while(0); +// +// arm_2d_size_t copy_size = { +// .iWidth = MIN(des_size.iWidth, src_size.iWidth), +// .iHeight = MIN(des_size.iHeight, src_size.iHeight), +// }; +// +// int32_t des_stride = lv_draw_buf_width_to_stride( +// lv_area_get_width(&layer->buf_area), +// des_cf); +// uint8_t *des_buf_moved = (uint8_t *)lv_draw_layer_go_to_xy( +// layer, +// blend_area.x1 - layer->buf_area.x1, +// blend_area.y1 - layer->buf_area.y1); + uint8_t *des_buf = (uint8_t *)lv_draw_layer_go_to_xy(layer, 0, 0); + uint8_t opa = draw_dsc->opa; + + /* ------------- prepare parameters for arm-2d APIs - END ----------- */ + __RECOLOUR_BEGIN() + + static arm_2d_tile_t target_tile_origin; + static arm_2d_tile_t target_tile; + arm_2d_region_t clip_region; + static arm_2d_region_t target_region; + + target_region = (arm_2d_region_t) { + .tLocation = { + .iX = (int16_t)(coords->x1 - draw_unit->clip_area->x1), + .iY = (int16_t)(coords->y1 - draw_unit->clip_area->y1), + }, + .tSize = src_size, + }; + + target_tile_origin = (arm_2d_tile_t) { + .tRegion = { + .tSize = { + .iWidth = (int16_t)lv_area_get_width(&layer->buf_area), + .iHeight = (int16_t)lv_area_get_height(&layer->buf_area), + }, + }, + .tInfo = { + .bIsRoot = true, + }, + .phwBuffer = (uint16_t *)des_buf, + }; + + clip_region = (arm_2d_region_t) { + .tLocation = { + .iX = (int16_t)(draw_unit->clip_area->x1 - layer->buf_area.x1), + .iY = (int16_t)(draw_unit->clip_area->y1 - layer->buf_area.y1), + }, + .tSize = { + .iWidth = (int16_t)lv_area_get_width(draw_unit->clip_area), + .iHeight = (int16_t)lv_area_get_height(draw_unit->clip_area), + }, + }; + + arm_2d_tile_generate_child(&target_tile_origin, + &clip_region, + &target_tile, + false); + + static arm_2d_tile_t source_tile; + + source_tile = (arm_2d_tile_t) { + .tRegion = { + .tSize = { + .iWidth = (int16_t)src_w, + .iHeight = (int16_t)src_h, + }, + }, + .tInfo = { + .bIsRoot = true, + }, + .pchBuffer = (uint8_t *)src_buf, + }; + + static arm_2d_location_t source_center, target_center; + source_center.iX = draw_dsc->pivot.x; + source_center.iY = draw_dsc->pivot.y; + target_center = target_region.tLocation; + target_center.iX += draw_dsc->pivot.x; + target_center.iY += draw_dsc->pivot.y; + + if(LV_COLOR_FORMAT_A8 == src_cf) { + + source_tile.tInfo.bHasEnforcedColour = true; + source_tile.tInfo.tColourInfo.chScheme = ARM_2D_COLOUR_GRAY8; + + if(LV_COLOR_FORMAT_RGB565 == des_cf) { + + arm_2d_rgb565_fill_colour_with_mask_opacity_and_transform( + &source_tile, + &target_tile, + NULL, + source_center, + ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)), + draw_dsc->scale_x / 256.0f, + lv_color_to_u16(draw_dsc->recolor), + opa, + &target_center + ); + + } + else if(LV_COLOR_FORMAT_XRGB8888 == des_cf) { + arm_2d_cccn888_fill_colour_with_mask_opacity_and_transform( + &source_tile, + &target_tile, + NULL, + source_center, + ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)), + draw_dsc->scale_x / 256.0f, + lv_color_to_int(draw_dsc->recolor), + opa, + &target_center + ); + } + else { + break; + } + + } + else if(LV_COLOR_FORMAT_RGB565A8 == src_cf) { + LV_ASSERT(LV_COLOR_FORMAT_RGB565 == des_cf); + + /* mask_buf = src_buf + src_stride * src_w / header->w * src_h; */ + const uint8_t *mask_buf = src_buf + src_stride * src_h; + int32_t mask_stride = src_stride / 2; + + static arm_2d_tile_t mask_tile; + mask_tile = source_tile; + + mask_tile.tInfo.bHasEnforcedColour = true; + mask_tile.tInfo.tColourInfo.chScheme = ARM_2D_COLOUR_GRAY8; + mask_tile.pchBuffer = (uint8_t *)mask_buf; + + if(opa >= LV_OPA_MAX) { + arm_2d_rgb565_tile_transform_with_src_mask( + &source_tile, + &mask_tile, + &target_tile, + NULL, + source_center, + ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)), + draw_dsc->scale_x / 256.0f, + &target_center + ); + } + else { + arm_2d_rgb565_tile_transform_with_src_mask_and_opacity( + &source_tile, + &mask_tile, + &target_tile, + NULL, + source_center, + ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)), + draw_dsc->scale_x / 256.0f, + opa, + &target_center + ); + } + + } + else if(LV_COLOR_FORMAT_RGB565 == src_cf) { + LV_ASSERT(LV_COLOR_FORMAT_RGB565 == des_cf); + + if(opa >= LV_OPA_MAX) { + arm_2d_rgb565_tile_transform_only( + &source_tile, + &target_tile, + NULL, + source_center, + ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)), + draw_dsc->scale_x / 256.0f, + &target_center + ); + } + else { + arm_2d_rgb565_tile_transform_only_with_opacity( + &source_tile, + &target_tile, + NULL, + source_center, + ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)), + draw_dsc->scale_x / 256.0f, + opa, + &target_center + ); + } + + } + else if(LV_COLOR_FORMAT_ARGB8888 == src_cf) { + LV_ASSERT(LV_COLOR_FORMAT_XRGB8888 == des_cf); + + static arm_2d_tile_t mask_tile; + mask_tile = source_tile; + + mask_tile.tInfo.bHasEnforcedColour = true; + mask_tile.tInfo.tColourInfo.chScheme = ARM_2D_CHANNEL_8in32; + mask_tile.pchBuffer = (uint8_t *)src_buf + 3; + + if(opa >= LV_OPA_MAX) { + arm_2d_cccn888_tile_transform_with_src_mask( + &source_tile, + &mask_tile, + &target_tile, + NULL, + source_center, + ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)), + draw_dsc->scale_x / 256.0f, + &target_center + ); + } + else { + arm_2d_cccn888_tile_transform_with_src_mask_and_opacity( + &source_tile, + &mask_tile, + &target_tile, + NULL, + source_center, + ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)), + draw_dsc->scale_x / 256.0f, + opa, + &target_center + ); + } + + } + else if(LV_COLOR_FORMAT_XRGB8888 == src_cf) { + LV_ASSERT(LV_COLOR_FORMAT_XRGB8888 == des_cf); + + if(opa >= LV_OPA_MAX) { + arm_2d_cccn888_tile_transform_only( + &source_tile, + &target_tile, + NULL, + source_center, + ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)), + draw_dsc->scale_x / 256.0f, + &target_center + ); + } + else { + arm_2d_cccn888_tile_transform_only_with_opacity( + &source_tile, + &target_tile, + NULL, + source_center, + ARM_2D_ANGLE((draw_dsc->rotation / 10.0f)), + draw_dsc->scale_x / 256.0f, + opa, + &target_center + ); + } + + } + else { + break; + } + + result = LV_RESULT_OK; + + __RECOLOUR_END() + } while(0); + + return result; +} + +static inline lv_result_t _lv_draw_sw_image_recolor_rgb565( + const uint8_t *src_buf, + const lv_area_t * blend_area, + lv_color_t color, + lv_opa_t opa) +{ + int32_t src_w = lv_area_get_width(blend_area); + int32_t src_h = lv_area_get_height(blend_area); + + arm_2d_size_t copy_size = { + .iWidth = (int16_t)src_w, + .iHeight = (int16_t)src_h, + }; + + __arm_2d_impl_rgb565_colour_filling_with_opacity( + (uint16_t *)src_buf, + src_w, + ©_size, + lv_color_to_u16(color), + opa); + + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_draw_sw_image_recolor_rgb888( + const uint8_t *src_buf, + const lv_area_t * blend_area, + lv_color_t color, + lv_opa_t opa, + lv_color_format_t src_cf) +{ + if(LV_COLOR_FORMAT_XRGB8888 != src_cf) { + return LV_RESULT_INVALID; + } + + int32_t src_w = lv_area_get_width(blend_area); + int32_t src_h = lv_area_get_height(blend_area); + + arm_2d_size_t copy_size = { + .iWidth = (int16_t)src_w, + .iHeight = (int16_t)src_h, + }; + + __arm_2d_impl_cccn888_colour_filling_with_opacity( + (uint32_t *)src_buf, + src_w, + ©_size, + lv_color_to_u32(color), + opa); + + return LV_RESULT_OK; +} + +#endif /* LV_USE_DRAW_ARM2D_SYNC */ + +/* *INDENT-ON* */ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SW_ARM2D_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/arm2d/lv_draw_sw_helium.h b/lib/libesp32_lvgl/lvgl/src/draw/sw/arm2d/lv_draw_sw_helium.h new file mode 100644 index 000000000..c35a06eb6 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/arm2d/lv_draw_sw_helium.h @@ -0,0 +1,60 @@ +/** + * @file lv_draw_sw_helium.h + * + */ + +#ifndef LV_DRAW_SW_HELIUM_H +#define LV_DRAW_SW_HELIUM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* *INDENT-OFF* */ + +/********************* + * INCLUDES + *********************/ + +#include "../../../lv_conf_internal.h" + +/* detect whether helium is available based on arm compilers' standard */ +#if defined(__ARM_FEATURE_MVE) && __ARM_FEATURE_MVE + +#ifdef LV_DRAW_SW_HELIUM_CUSTOM_INCLUDE +#include LV_DRAW_SW_HELIUM_CUSTOM_INCLUDE +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************* + * POST INCLUDES + *********************/ +/* use arm-2d as the default helium acceleration */ +#include "lv_draw_sw_arm2d.h" + +#endif /* defined(__ARM_FEATURE_MVE) && __ARM_FEATURE_MVE */ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SW_HELIUM_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/arm2d/lv_blend_arm2d.h b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/arm2d/lv_blend_arm2d.h new file mode 100644 index 000000000..669b3a2d4 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/arm2d/lv_blend_arm2d.h @@ -0,0 +1,1441 @@ +/** + * @file lv_blend_arm2d.h + * + */ + +#ifndef LV_BLEND_ARM2D_H +#define LV_BLEND_ARM2D_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../../../lv_conf_internal.h" + +#if LV_USE_DRAW_ARM2D_SYNC + +#define __ARM_2D_IMPL__ +#include "arm_2d.h" +#include "__arm_2d_impl.h" + +#if defined(__IS_COMPILER_ARM_COMPILER_5__) +#pragma diag_suppress 174,177,188,68,513,144,1296 +#elif defined(__IS_COMPILER_IAR__) +#pragma diag_suppress=Pa093 +#elif defined(__IS_COMPILER_GCC__) +#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" +#endif +/********************* + * DEFINES + *********************/ + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565 +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565(dsc) \ + _lv_color_blend_to_rgb565_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_OPA +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_OPA(dsc) \ + _lv_color_blend_to_rgb565_with_opa_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_MASK +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_MASK(dsc) \ + _lv_color_blend_to_rgb565_with_mask_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565_MIX_MASK_OPA +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565_MIX_MASK_OPA(dsc) \ + _lv_color_blend_to_rgb565_mix_mask_opa_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565 +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565(dsc) \ + _lv_rgb565_blend_normal_to_rgb565_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_OPA +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_OPA(dsc) \ + _lv_rgb565_blend_normal_to_rgb565_with_opa_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_MASK +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_MASK(dsc) \ + _lv_rgb565_blend_normal_to_rgb565_with_mask_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(dsc) \ + _lv_rgb565_blend_normal_to_rgb565_mix_mask_opa_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565 +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb565_helium(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_OPA +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_OPA(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb565_with_opa_helium(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_MASK +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_MASK(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb565_with_mask_helium(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb565_mix_mask_opa_helium(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565 +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565(dsc) \ + _lv_argb8888_blend_normal_to_rgb565_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_OPA +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_OPA(dsc) \ + _lv_argb8888_blend_normal_to_rgb565_with_opa_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_MASK +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_MASK(dsc) \ + _lv_argb8888_blend_normal_to_rgb565_with_mask_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(dsc) \ + _lv_argb8888_blend_normal_to_rgb565_mix_mask_opa_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB888 +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB888(dsc, dst_px_size) \ + _lv_color_blend_to_rgb888_helium(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_OPA +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_OPA(dsc, dst_px_size) \ + _lv_color_blend_to_rgb888_with_opa_helium(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_MASK +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_MASK(dsc, dst_px_size) \ + _lv_color_blend_to_rgb888_with_mask_helium(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB888_MIX_MASK_OPA +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB888_MIX_MASK_OPA(dsc, dst_px_size) \ + _lv_color_blend_to_rgb888_mix_mask_opa_helium(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888 +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888(dsc, dst_px_size) \ + _lv_rgb565_blend_normal_to_rgb888_helium(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_OPA +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_OPA(dsc, dst_px_size) \ + _lv_rgb565_blend_normal_to_rgb888_with_opa_helium(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_MASK +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_MASK(dsc, dst_px_size) \ + _lv_rgb565_blend_normal_to_rgb888_with_mask_helium(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA(dsc, dst_px_size) \ + _lv_rgb565_blend_normal_to_rgb888_mix_mask_opa_helium(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888 +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888(dsc, dst_px_size, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb888_helium(dsc, dst_px_size, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_OPA +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_OPA(dsc, dst_px_size, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb888_with_opa_helium(dsc, dst_px_size, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_MASK +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_MASK(dsc, dst_px_size, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb888_with_mask_helium(dsc, dst_px_size, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA(dsc, dst_px_size, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb888_mix_mask_opa_helium(dsc, dst_px_size, src_px_size) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888 +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888(dsc, dst_px_size) \ + _lv_argb8888_blend_normal_to_rgb888_helium(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_OPA +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_OPA(dsc, dst_px_size) \ + _lv_argb8888_blend_normal_to_rgb888_with_opa_helium(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_MASK +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_MASK(dsc, dst_px_size) \ + _lv_argb8888_blend_normal_to_rgb888_with_mask_helium(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA(dsc, dst_px_size) \ + _lv_argb8888_blend_normal_to_rgb888_mix_mask_opa_helium(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888 +#define LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888(dsc) \ + _lv_color_blend_to_argb8888_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_WITH_OPA +#define LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_WITH_OPA(dsc) \ + _lv_color_blend_to_argb8888_with_opa_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_WITH_MASK +#define LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_WITH_MASK(dsc) \ + _lv_color_blend_to_argb8888_with_mask_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_MIX_MASK_OPA +#define LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_MIX_MASK_OPA(dsc) \ + _lv_color_blend_to_argb8888_mix_mask_opa_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888 +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888(dsc) \ + _lv_rgb565_blend_normal_to_argb8888_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_WITH_OPA +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_WITH_OPA(dsc) \ + _lv_rgb565_blend_normal_to_argb8888_with_opa_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_WITH_MASK +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_WITH_MASK(dsc) \ + _lv_rgb565_blend_normal_to_argb8888_with_mask_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA(dsc) \ + _lv_rgb565_blend_normal_to_argb8888_mix_mask_opa_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888 +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_argb8888_helium(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_WITH_OPA +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_WITH_OPA(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_argb8888_with_opa_helium(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_WITH_MASK +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_WITH_MASK(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_argb8888_with_mask_helium(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_argb8888_mix_mask_opa_helium(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888 +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888(dsc) \ + _lv_argb8888_blend_normal_to_argb8888_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_WITH_OPA +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_WITH_OPA(dsc) \ + _lv_argb8888_blend_normal_to_argb8888_with_opa_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_WITH_MASK +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_WITH_MASK(dsc) \ + _lv_argb8888_blend_normal_to_argb8888_with_mask_helium(dsc) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA(dsc) \ + _lv_argb8888_blend_normal_to_argb8888_mix_mask_opa_helium(dsc) +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +static inline lv_result_t _lv_color_blend_to_rgb565_helium(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t stride = (dsc->dest_stride) / sizeof(uint16_t); + __arm_2d_impl_rgb16_colour_filling((uint16_t *)dsc->dest_buf, + stride, + &draw_size, + lv_color_to_u16(dsc->color)); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_color_blend_to_rgb565_with_opa_helium(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t stride = (dsc->dest_stride) / sizeof(uint16_t); + __arm_2d_impl_rgb565_colour_filling_with_opacity((uint16_t *)dsc->dest_buf, + stride, + &draw_size, + lv_color_to_u16(dsc->color), + dsc->opa); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_color_blend_to_rgb565_with_mask_helium(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t stride = (dsc->dest_stride) / sizeof(uint16_t); + __arm_2d_impl_rgb565_colour_filling_mask((uint16_t *)dsc->dest_buf, + stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + lv_color_to_u16(dsc->color)); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_color_blend_to_rgb565_mix_mask_opa_helium(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t stride = (dsc->dest_stride) / sizeof(uint16_t); + __arm_2d_impl_rgb565_colour_filling_mask_opacity((uint16_t *)dsc->dest_buf, + stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + lv_color_to_u16(dsc->color), + dsc->opa); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb565_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint16_t); + int16_t src_stride = dsc->src_stride / sizeof(uint16_t); + __arm_2d_impl_rgb16_copy((uint16_t *)dsc->src_buf, + src_stride, + (uint16_t *)dsc->dest_buf, + des_stride, + &draw_size); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb565_with_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint16_t); + int16_t src_stride = dsc->src_stride / sizeof(uint16_t); + __arm_2d_impl_rgb565_tile_copy_opacity((uint16_t *)dsc->src_buf, + src_stride, + (uint16_t *)dsc->dest_buf, + des_stride, + &draw_size, + dsc->opa); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb565_with_mask_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint16_t); + int16_t src_stride = dsc->src_stride / sizeof(uint16_t); + __arm_2d_impl_rgb565_src_msk_copy((uint16_t *)dsc->src_buf, + src_stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + (uint16_t *)dsc->dest_buf, + des_stride, + &draw_size); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb565_mix_mask_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint16_t); + int16_t src_stride = dsc->src_stride / sizeof(uint16_t); + + __arm_2d_impl_gray8_colour_filling_with_opacity((uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + 0x00, + 255 - dsc->opa); + + __arm_2d_impl_rgb565_src_msk_copy((uint16_t *)dsc->src_buf, + src_stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + (uint16_t *)dsc->dest_buf, + des_stride, + &draw_size); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb565_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ + if(src_px_size == 3) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint16_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + __arm_2d_impl_cccn888_to_rgb565((uint32_t *)dsc->src_buf, + src_stride, + (uint16_t *)dsc->dest_buf, + des_stride, + &draw_size); + + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb565_with_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ + if(src_px_size == 3) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint16_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + uint16_t * tmp_buf = (uint16_t *)lv_malloc(dsc->dest_stride * dsc->dest_h); + if(NULL == tmp_buf) { + return LV_RESULT_INVALID; + } + + __arm_2d_impl_cccn888_to_rgb565((uint32_t *)dsc->src_buf, + src_stride, + (uint16_t *)tmp_buf, + des_stride, + &draw_size); + + __arm_2d_impl_rgb565_tile_copy_opacity(tmp_buf, + des_stride, + (uint16_t *)dsc->dest_buf, + des_stride, + &draw_size, + dsc->opa); + + lv_free(tmp_buf); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb565_with_mask_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ + if(src_px_size == 3) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint16_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + uint16_t * tmp_buf = (uint16_t *)lv_malloc(dsc->dest_stride * dsc->dest_h); + if(NULL == tmp_buf) { + return LV_RESULT_INVALID; + } + + __arm_2d_impl_cccn888_to_rgb565((uint32_t *)dsc->src_buf, + src_stride, + (uint16_t *)tmp_buf, + des_stride, + &draw_size); + + __arm_2d_impl_rgb565_src_msk_copy(tmp_buf, + des_stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + (uint16_t *)dsc->dest_buf, + des_stride, + &draw_size); + + lv_free(tmp_buf); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb565_mix_mask_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ + if(src_px_size == 3) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint16_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + uint16_t * tmp_buf = (uint16_t *)lv_malloc(dsc->dest_stride * dsc->dest_h); + if(NULL == tmp_buf) { + return LV_RESULT_INVALID; + } + + __arm_2d_impl_cccn888_to_rgb565((uint32_t *)dsc->src_buf, + src_stride, + (uint16_t *)tmp_buf, + des_stride, + &draw_size); + + __arm_2d_impl_gray8_colour_filling_with_opacity((uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + 0x00, + 255 - dsc->opa); + + __arm_2d_impl_rgb565_src_msk_copy(tmp_buf, + des_stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + (uint16_t *)dsc->dest_buf, + des_stride, + &draw_size); + + lv_free(tmp_buf); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb565_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint16_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + uint16_t * tmp_buf = (uint16_t *)lv_malloc(dsc->dest_stride * dsc->dest_h); + if(NULL == tmp_buf) { + return LV_RESULT_INVALID; + } + + __arm_2d_impl_cccn888_to_rgb565((uint32_t *)dsc->src_buf, + src_stride, + (uint16_t *)tmp_buf, + des_stride, + &draw_size); + + __arm_2d_impl_rgb565_src_chn_msk_copy(tmp_buf, + des_stride, + (uint32_t *)((uintptr_t)(dsc->src_buf) + 3), + src_stride, + &draw_size, + (uint16_t *)dsc->dest_buf, + des_stride, + &draw_size); + + lv_free(tmp_buf); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb565_with_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint16_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + uint16_t * tmp_buf = (uint16_t *)lv_malloc(dsc->dest_stride * dsc->dest_h); + if(NULL == tmp_buf) { + return LV_RESULT_INVALID; + } + uint8_t * tmp_msk = (uint8_t *)lv_malloc(des_stride * dsc->dest_h); + if(NULL == tmp_msk) { + lv_free(tmp_buf); + return LV_RESULT_INVALID; + } + + /* get rgb565 */ + __arm_2d_impl_cccn888_to_rgb565((uint32_t *)dsc->src_buf, + src_stride, + (uint16_t *)tmp_buf, + des_stride, + &draw_size); + + lv_memzero(tmp_msk, des_stride * dsc->dest_h); + + /* get mask */ + __arm_2d_impl_gray8_colour_filling_channel_mask_opacity(tmp_msk, + des_stride, + (uint32_t *)((uintptr_t)(dsc->src_buf) + 3), + src_stride, + &draw_size, + 0xFF, + dsc->opa); + + __arm_2d_impl_rgb565_src_msk_copy(tmp_buf, + des_stride, + tmp_msk, + des_stride, + &draw_size, + (uint16_t *)dsc->dest_buf, + des_stride, + &draw_size); + + lv_free(tmp_msk); + lv_free(tmp_buf); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb565_with_mask_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint16_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + uint16_t * tmp_buf = (uint16_t *)lv_malloc(dsc->dest_stride * dsc->dest_h); + if(NULL == tmp_buf) { + return LV_RESULT_INVALID; + } + uint8_t * tmp_msk = (uint8_t *)lv_malloc(des_stride * dsc->dest_h); + if(NULL == tmp_msk) { + lv_free(tmp_buf); + return LV_RESULT_INVALID; + } + + /* get rgb565 */ + __arm_2d_impl_cccn888_to_rgb565((uint32_t *)dsc->src_buf, + src_stride, + (uint16_t *)tmp_buf, + des_stride, + &draw_size); + + lv_memzero(tmp_msk, des_stride * dsc->dest_h); + + /* get mask */ + __arm_2d_impl_gray8_colour_filling_channel_mask(tmp_msk, + des_stride, + (uint32_t *)((uintptr_t)(dsc->src_buf) + 3), + src_stride, + &draw_size, + 0xFF); + + __arm_2d_impl_rgb565_masks_copy(tmp_buf, + des_stride, + tmp_msk, + des_stride, + &draw_size, + (uint16_t *)dsc->dest_buf, + des_stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + &draw_size); + + lv_free(tmp_msk); + lv_free(tmp_buf); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb565_mix_mask_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint16_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + uint16_t * tmp_buf = (uint16_t *)lv_malloc(dsc->dest_stride * dsc->dest_h); + if(NULL == tmp_buf) { + return LV_RESULT_INVALID; + } + uint8_t * tmp_msk = (uint8_t *)lv_malloc(des_stride * dsc->dest_h); + if(NULL == tmp_msk) { + lv_free(tmp_buf); + return LV_RESULT_INVALID; + } + + /* get rgb565 */ + __arm_2d_impl_cccn888_to_rgb565((uint32_t *)dsc->src_buf, + src_stride, + (uint16_t *)tmp_buf, + des_stride, + &draw_size); + + lv_memzero(tmp_msk, des_stride * dsc->dest_h); + + /* get mask */ + __arm_2d_impl_gray8_colour_filling_channel_mask_opacity(tmp_msk, + des_stride, + (uint32_t *)((uintptr_t)(dsc->src_buf) + 3), + src_stride, + &draw_size, + 0xFF, + dsc->opa); + + __arm_2d_impl_rgb565_masks_copy(tmp_buf, + des_stride, + tmp_msk, + des_stride, + &draw_size, + (uint16_t *)dsc->dest_buf, + des_stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + &draw_size); + + lv_free(tmp_msk); + lv_free(tmp_buf); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_color_blend_to_rgb888_helium(_lv_draw_sw_blend_fill_dsc_t * dsc, uint32_t dst_px_size) +{ + if(dst_px_size == 3) { + return LV_RESULT_INVALID; + } + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t stride = (dsc->dest_stride) / sizeof(uint32_t); + __arm_2d_impl_rgb32_colour_filling((uint32_t *)dsc->dest_buf, + stride, + &draw_size, + lv_color_to_u32(dsc->color)); + return LV_RESULT_OK; + +} + +static inline lv_result_t _lv_color_blend_to_rgb888_with_opa_helium(_lv_draw_sw_blend_fill_dsc_t * dsc, + uint32_t dst_px_size) +{ + if(dst_px_size == 3) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t stride = (dsc->dest_stride) / sizeof(uint32_t); + __arm_2d_impl_cccn888_colour_filling_with_opacity((uint32_t *)dsc->dest_buf, + stride, + &draw_size, + lv_color_to_u32(dsc->color), + dsc->opa); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_color_blend_to_rgb888_with_mask_helium(_lv_draw_sw_blend_fill_dsc_t * dsc, + uint32_t dst_px_size) +{ + + if(dst_px_size == 3) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t stride = (dsc->dest_stride) / sizeof(uint32_t); + __arm_2d_impl_cccn888_colour_filling_mask((uint32_t *)dsc->dest_buf, + stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + lv_color_to_u32(dsc->color)); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_color_blend_to_rgb888_mix_mask_opa_helium(_lv_draw_sw_blend_fill_dsc_t * dsc, + uint32_t dst_px_size) +{ + + if(dst_px_size == 3) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t stride = (dsc->dest_stride) / sizeof(uint32_t); + __arm_2d_impl_cccn888_colour_filling_mask_opacity((uint32_t *)dsc->dest_buf, + stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + lv_color_to_u32(dsc->color), + dsc->opa); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb888_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + + if(dst_px_size == 3) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint32_t); + int16_t src_stride = dsc->src_stride / sizeof(uint16_t); + + __arm_2d_impl_rgb565_to_cccn888((uint16_t *)dsc->src_buf, + src_stride, + (uint32_t *)dsc->dest_buf, + des_stride, + &draw_size); + + return LV_RESULT_OK; + +} + +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb888_with_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + + if(dst_px_size == 3) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint32_t); + int16_t src_stride = dsc->src_stride / sizeof(uint16_t); + + uint32_t * tmp_buf = (uint32_t *)lv_malloc(dsc->dest_stride * dsc->dest_h); + if(NULL == tmp_buf) { + return LV_RESULT_INVALID; + } + + /* get rgb565 */ + __arm_2d_impl_rgb565_to_cccn888((uint16_t *)dsc->src_buf, + src_stride, + (uint32_t *)tmp_buf, + des_stride, + &draw_size); + + __arm_2d_impl_cccn888_tile_copy_opacity(tmp_buf, + des_stride, + (uint32_t *)dsc->dest_buf, + des_stride, + &draw_size, + dsc->opa); + + lv_free(tmp_buf); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb888_with_mask_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + + if(dst_px_size == 3) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint32_t); + int16_t src_stride = dsc->src_stride / sizeof(uint16_t); + + uint32_t * tmp_buf = (uint32_t *)lv_malloc(dsc->dest_stride * dsc->dest_h); + if(NULL == tmp_buf) { + return LV_RESULT_INVALID; + } + + __arm_2d_impl_rgb565_to_cccn888((uint16_t *)dsc->src_buf, + src_stride, + (uint32_t *)tmp_buf, + des_stride, + &draw_size); + + __arm_2d_impl_cccn888_src_msk_copy(tmp_buf, + des_stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + (uint32_t *)dsc->dest_buf, + des_stride, + &draw_size); + + lv_free(tmp_buf); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb888_mix_mask_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + + if(dst_px_size == 3) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint32_t); + int16_t src_stride = dsc->src_stride / sizeof(uint16_t); + + uint32_t * tmp_buf = (uint32_t *)lv_malloc(dsc->dest_stride * dsc->dest_h); + if(NULL == tmp_buf) { + return LV_RESULT_INVALID; + } + + __arm_2d_impl_rgb565_to_cccn888((uint16_t *)dsc->src_buf, + src_stride, + (uint32_t *)tmp_buf, + des_stride, + &draw_size); + + __arm_2d_impl_gray8_colour_filling_with_opacity((uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + 0x00, + 255 - dsc->opa); + + __arm_2d_impl_cccn888_src_msk_copy(tmp_buf, + des_stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + (uint32_t *)dsc->dest_buf, + des_stride, + &draw_size); + + lv_free(tmp_buf); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb888_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size, + uint32_t src_px_size) +{ + if((dst_px_size == 3) || (src_px_size == 3)) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint32_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + __arm_2d_impl_rgb32_copy((uint32_t *)dsc->src_buf, + src_stride, + (uint32_t *)dsc->dest_buf, + des_stride, + &draw_size); + + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb888_with_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size, uint32_t src_px_size) +{ + if((dst_px_size == 3) || (src_px_size == 3)) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint32_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + __arm_2d_impl_cccn888_tile_copy_opacity((uint32_t *)dsc->src_buf, + src_stride, + (uint32_t *)dsc->dest_buf, + des_stride, + &draw_size, + dsc->opa); + + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb888_with_mask_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size, uint32_t src_px_size) +{ + if((dst_px_size == 3) || (src_px_size == 3)) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint32_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + __arm_2d_impl_cccn888_src_msk_copy((uint32_t *)dsc->src_buf, + src_stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + (uint32_t *)dsc->dest_buf, + des_stride, + &draw_size); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb888_mix_mask_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size, uint32_t src_px_size) +{ + if((dst_px_size == 3) || (src_px_size == 3)) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint32_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + __arm_2d_impl_gray8_colour_filling_with_opacity((uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + 0x00, + 255 - dsc->opa); + + __arm_2d_impl_cccn888_src_msk_copy((uint32_t *)dsc->src_buf, + src_stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + (uint32_t *)dsc->dest_buf, + des_stride, + &draw_size); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb888_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + + if(dst_px_size == 3) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint32_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + __arm_2d_impl_cccn888_src_chn_msk_copy((uint32_t *)dsc->src_buf, + src_stride, + (uint32_t *)((uintptr_t)(dsc->src_buf) + 3), + src_stride, + &draw_size, + (uint32_t *)dsc->dest_buf, + des_stride, + &draw_size); + + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb888_with_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + if(dst_px_size == 3) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint32_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + uint8_t * tmp_msk = (uint8_t *)lv_malloc(des_stride * dsc->dest_h); + if(NULL == tmp_msk) { + return LV_RESULT_INVALID; + } + + lv_memzero(tmp_msk, des_stride * dsc->dest_h); + + /* get mask */ + __arm_2d_impl_gray8_colour_filling_channel_mask_opacity(tmp_msk, + des_stride, + (uint32_t *)((uintptr_t)(dsc->src_buf) + 3), + src_stride, + &draw_size, + 0xFF, + dsc->opa); + + __arm_2d_impl_cccn888_src_msk_copy((uint32_t *)dsc->src_buf, + src_stride, + tmp_msk, + des_stride, + &draw_size, + (uint32_t *)dsc->dest_buf, + des_stride, + &draw_size); + + lv_free(tmp_msk); + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb888_with_mask_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + + if(dst_px_size == 3) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint32_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + __arm_2d_impl_cccn888_src_chn_msk_des_msk_copy((uint32_t *)dsc->src_buf, + src_stride, + (uint32_t *)((uintptr_t)(dsc->src_buf) + 3), + src_stride, + &draw_size, + (uint32_t *)dsc->dest_buf, + des_stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + &draw_size); + + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb888_mix_mask_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + if(dst_px_size == 3) { + return LV_RESULT_INVALID; + } + + arm_2d_size_t draw_size = {dsc->dest_w, dsc->dest_h}; + int16_t des_stride = dsc->dest_stride / sizeof(uint32_t); + int16_t src_stride = dsc->src_stride / sizeof(uint32_t); + + __arm_2d_impl_gray8_colour_filling_with_opacity((uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + 0x00, + 255 - dsc->opa); + + __arm_2d_impl_cccn888_src_chn_msk_des_msk_copy((uint32_t *)dsc->src_buf, + src_stride, + (uint32_t *)((uintptr_t)(dsc->src_buf) + 3), + src_stride, + &draw_size, + (uint32_t *)dsc->dest_buf, + des_stride, + (uint8_t *)dsc->mask_buf, + dsc->mask_stride, + &draw_size, + &draw_size); + + return LV_RESULT_OK; +} + +static inline lv_result_t _lv_color_blend_to_argb8888_helium(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ +#if 0 + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color + }; + + lv_color_blend_to_argb8888_helium(&asm_dsc); +#endif + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_color_blend_to_argb8888_with_opa_helium(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ +#if 0 + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color + }; + lv_color_blend_to_argb8888_with_opa_helium(&asm_dsc); +#endif + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_color_blend_to_argb8888_with_mask_helium(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ +#if 0 + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_color_blend_to_argb8888_with_mask_helium(&asm_dsc); +#endif + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_color_blend_to_argb8888_mix_mask_opa_helium(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ +#if 0 + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_color_blend_to_argb8888_mix_mask_opa_helium(&asm_dsc); +#endif + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_rgb565_blend_normal_to_argb8888_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ +#if 0 + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + lv_rgb565_blend_normal_to_argb8888_helium(&asm_dsc); +#endif + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_rgb565_blend_normal_to_argb8888_with_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ +#if 0 + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + lv_rgb565_blend_normal_to_argb8888_with_opa_helium(&asm_dsc); +#endif + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_rgb565_blend_normal_to_argb8888_with_mask_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ +#if 0 + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_rgb565_blend_normal_to_argb8888_with_mask_helium(&asm_dsc); +#endif + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_rgb565_blend_normal_to_argb8888_mix_mask_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ +#if 0 + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_rgb565_blend_normal_to_argb8888_mix_mask_opa_helium(&asm_dsc); +#endif + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_argb8888_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ +#if 0 + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_argb8888_helium(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_argb8888_helium(&asm_dsc); + } +#endif + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_argb8888_with_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ +#if 0 + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_argb8888_with_opa_helium(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_argb8888_with_opa_helium(&asm_dsc); + } +#endif + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_argb8888_with_mask_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ +#if 0 + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_argb8888_with_mask_helium(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_argb8888_with_mask_helium(&asm_dsc); + } +#endif + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_argb8888_mix_mask_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ +#if 0 + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_argb8888_mix_mask_opa_helium(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_argb8888_mix_mask_opa_helium(&asm_dsc); + } +#endif + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_argb8888_blend_normal_to_argb8888_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ +#if 0 + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + lv_argb8888_blend_normal_to_argb8888_helium(&asm_dsc); +#endif + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_argb8888_blend_normal_to_argb8888_with_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ +#if 0 + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + lv_argb8888_blend_normal_to_argb8888_with_opa_helium(&asm_dsc); +#endif + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_argb8888_blend_normal_to_argb8888_with_mask_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ +#if 0 + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_argb8888_blend_normal_to_argb8888_with_mask_helium(&asm_dsc); +#endif + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_argb8888_blend_normal_to_argb8888_mix_mask_opa_helium(_lv_draw_sw_blend_image_dsc_t * dsc) +{ +#if 0 + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_argb8888_blend_normal_to_argb8888_mix_mask_opa_helium(&asm_dsc); +#endif + return LV_RESULT_INVALID; +} + +/********************** + * MACROS + **********************/ + +#endif /* LV_USE_DRAW_ARM2D_SYNC */ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_BLEND_ARM2D_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/arm2d/lv_blend_helium.h b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/arm2d/lv_blend_helium.h new file mode 100644 index 000000000..03caed11f --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/arm2d/lv_blend_helium.h @@ -0,0 +1,58 @@ +/** + * @file lv_blend_arm2d.h + * + */ + +#ifndef LV_BLEND_HELIUM_H +#define LV_BLEND_HELIUM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../../../lv_conf_internal.h" + +/* detect whether helium is available based on arm compilers' standard */ +#if defined(__ARM_FEATURE_MVE) && __ARM_FEATURE_MVE + +#ifdef LV_DRAW_SW_HELIUM_CUSTOM_INCLUDE +#include LV_DRAW_SW_HELIUM_CUSTOM_INCLUDE +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************* + * POST INCLUDES + *********************/ +/* use arm-2d as the default helium acceleration */ +#include "lv_blend_arm2d.h" + +#endif /* defined(__ARM_FEATURE_MVE) && __ARM_FEATURE_MVE */ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_BLEND_HELIUM_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend.c new file mode 100644 index 000000000..0cdbca5a2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend.c @@ -0,0 +1,151 @@ +/** + * @file lv_draw_sw_blend.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../lv_draw_sw.h" +#include "lv_draw_sw_blend_to_rgb565.h" +#include "lv_draw_sw_blend_to_argb8888.h" +#include "lv_draw_sw_blend_to_rgb888.h" + +#if LV_USE_DRAW_SW + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_sw_blend(lv_draw_unit_t * draw_unit, const lv_draw_sw_blend_dsc_t * blend_dsc) +{ + /*Do not draw transparent things*/ + if(blend_dsc->opa <= LV_OPA_MIN) return; + if(blend_dsc->mask_buf && blend_dsc->mask_res == LV_DRAW_SW_MASK_RES_TRANSP) return; + + lv_area_t blend_area; + if(!_lv_area_intersect(&blend_area, blend_dsc->blend_area, draw_unit->clip_area)) return; + + LV_PROFILER_BEGIN; + lv_layer_t * layer = draw_unit->target_layer; + uint32_t layer_stride_byte = lv_draw_buf_width_to_stride(lv_area_get_width(&layer->buf_area), layer->color_format); + + if(blend_dsc->src_buf == NULL) { + _lv_draw_sw_blend_fill_dsc_t fill_dsc; + fill_dsc.dest_w = lv_area_get_width(&blend_area); + fill_dsc.dest_h = lv_area_get_height(&blend_area); + fill_dsc.dest_stride = layer_stride_byte; + fill_dsc.opa = blend_dsc->opa; + fill_dsc.color = blend_dsc->color; + + if(blend_dsc->mask_buf == NULL) fill_dsc.mask_buf = NULL; + else if(blend_dsc->mask_res == LV_DRAW_SW_MASK_RES_FULL_COVER) fill_dsc.mask_buf = NULL; + else fill_dsc.mask_buf = blend_dsc->mask_buf; + + fill_dsc.dest_buf = lv_draw_layer_go_to_xy(layer, blend_area.x1 - layer->buf_area.x1, + blend_area.y1 - layer->buf_area.y1); + + if(fill_dsc.mask_buf) { + fill_dsc.mask_stride = blend_dsc->mask_stride == 0 ? lv_area_get_width(blend_dsc->mask_area) : blend_dsc->mask_stride; + fill_dsc.mask_buf += fill_dsc.mask_stride * (blend_area.y1 - blend_dsc->mask_area->y1) + + (blend_area.x1 - blend_dsc->mask_area->x1); + } + + switch(layer->color_format) { + case LV_COLOR_FORMAT_RGB565: + lv_draw_sw_blend_color_to_rgb565(&fill_dsc); + break; + case LV_COLOR_FORMAT_ARGB8888: + lv_draw_sw_blend_color_to_argb8888(&fill_dsc); + break; + case LV_COLOR_FORMAT_RGB888: + lv_draw_sw_blend_color_to_rgb888(&fill_dsc, 3); + break; + case LV_COLOR_FORMAT_XRGB8888: + lv_draw_sw_blend_color_to_rgb888(&fill_dsc, 4); + break; + default: + break; + } + } + else { + if(!_lv_area_intersect(&blend_area, &blend_area, blend_dsc->src_area)) { + LV_PROFILER_END; + return; + } + + _lv_draw_sw_blend_image_dsc_t image_dsc; + image_dsc.dest_w = lv_area_get_width(&blend_area); + image_dsc.dest_h = lv_area_get_height(&blend_area); + image_dsc.dest_stride = layer_stride_byte; + + image_dsc.opa = blend_dsc->opa; + image_dsc.blend_mode = blend_dsc->blend_mode; + image_dsc.src_stride = blend_dsc->src_stride; + image_dsc.src_color_format = blend_dsc->src_color_format; + + const uint8_t * src_buf = blend_dsc->src_buf; + uint32_t src_px_size = lv_color_format_get_size(blend_dsc->src_color_format); + src_buf += image_dsc.src_stride * (blend_area.y1 - blend_dsc->src_area->y1); + src_buf += (blend_area.x1 - blend_dsc->src_area->x1) * src_px_size; + image_dsc.src_buf = src_buf; + + if(blend_dsc->mask_buf == NULL) image_dsc.mask_buf = NULL; + else if(blend_dsc->mask_res == LV_DRAW_SW_MASK_RES_FULL_COVER) image_dsc.mask_buf = NULL; + else image_dsc.mask_buf = blend_dsc->mask_buf; + + if(image_dsc.mask_buf) { + image_dsc.mask_buf = blend_dsc->mask_buf; + image_dsc.mask_stride = blend_dsc->mask_stride ? blend_dsc->mask_stride : lv_area_get_width(blend_dsc->mask_area); + image_dsc.mask_buf += image_dsc.mask_stride * (blend_area.y1 - blend_dsc->mask_area->y1) + + (blend_area.x1 - blend_dsc->mask_area->x1); + } + + image_dsc.dest_buf = lv_draw_layer_go_to_xy(layer, blend_area.x1 - layer->buf_area.x1, + blend_area.y1 - layer->buf_area.y1); + + switch(layer->color_format) { + case LV_COLOR_FORMAT_RGB565: + case LV_COLOR_FORMAT_RGB565A8: + lv_draw_sw_blend_image_to_rgb565(&image_dsc); + break; + case LV_COLOR_FORMAT_ARGB8888: + lv_draw_sw_blend_image_to_argb8888(&image_dsc); + break; + case LV_COLOR_FORMAT_RGB888: + lv_draw_sw_blend_image_to_rgb888(&image_dsc, 3); + break; + case LV_COLOR_FORMAT_XRGB8888: + lv_draw_sw_blend_image_to_rgb888(&image_dsc, 4); + break; + default: + break; + } + } + LV_PROFILER_END; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend.h b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend.h new file mode 100644 index 000000000..c1b1edca0 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend.h @@ -0,0 +1,93 @@ +/** + * @file lv_draw_sw_blend.h + * + */ + +#ifndef LV_DRAW_SW_BLEND_H +#define LV_DRAW_SW_BLEND_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_draw_sw_mask.h" +#if LV_USE_DRAW_SW + +#include "../../../misc/lv_color.h" +#include "../../../misc/lv_area.h" +#include "../../../misc/lv_style.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + const lv_area_t * blend_area; /**< The area with absolute coordinates to draw on `layer->buf` + * will be clipped to `layer->clip_area` */ + const void * src_buf; /**< Pointer to an image to blend. If set `fill_color` is ignored */ + uint32_t src_stride; + lv_color_format_t src_color_format; + const lv_area_t * src_area; + lv_opa_t opa; /**< The overall opacity*/ + lv_color_t color; /**< Fill color*/ + const lv_opa_t * mask_buf; /**< NULL if ignored, or an alpha mask to apply on `blend_area`*/ + lv_draw_sw_mask_res_t mask_res; /**< The result of the previous mask operation */ + const lv_area_t * mask_area; /**< The area of `mask_buf` with absolute coordinates*/ + int32_t mask_stride; + lv_blend_mode_t blend_mode; /**< E.g. LV_BLEND_MODE_ADDITIVE*/ +} lv_draw_sw_blend_dsc_t; + +typedef struct { + void * dest_buf; + int32_t dest_w; + int32_t dest_h; + int32_t dest_stride; + const lv_opa_t * mask_buf; + int32_t mask_stride; + lv_color_t color; + lv_opa_t opa; +} _lv_draw_sw_blend_fill_dsc_t; + +typedef struct { + void * dest_buf; + int32_t dest_w; + int32_t dest_h; + int32_t dest_stride; + const lv_opa_t * mask_buf; + int32_t mask_stride; + const void * src_buf; + int32_t src_stride; + lv_color_format_t src_color_format; + lv_opa_t opa; + lv_blend_mode_t blend_mode; +} _lv_draw_sw_blend_image_dsc_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Call the blend function of the `layer`. + * @param draw_unit pointer to a draw unit + * @param dsc pointer to an initialized blend descriptor + */ +void lv_draw_sw_blend(lv_draw_unit_t * draw_unit, const lv_draw_sw_blend_dsc_t * dsc); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DRAW_SW*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SW_BLEND_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_argb8888.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_argb8888.c new file mode 100644 index 000000000..79a7accd5 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_argb8888.c @@ -0,0 +1,655 @@ +/** + * @file lv_draw_sw_blend.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_sw_blend_to_argb8888.h" +#if LV_USE_DRAW_SW + +#include "lv_draw_sw_blend.h" +#include "../../../misc/lv_math.h" +#include "../../../display/lv_display.h" +#include "../../../core/lv_refr.h" +#include "../../../misc/lv_color.h" +#include "../../../stdlib/lv_string.h" + +#if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_NEON + #include "neon/lv_blend_neon.h" +#elif LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_HELIUM + #include "arm2d/lv_blend_helium.h" +#elif LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_CUSTOM + #include LV_DRAW_SW_ASM_CUSTOM_INCLUDE +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_color32_t fg_saved; + lv_color32_t bg_saved; + lv_color32_t res_saved; + lv_opa_t res_alpha_saved; + lv_opa_t ratio_saved; +} lv_color_mix_alpha_cache_t; + +/********************** + * STATIC PROTOTYPES + **********************/ + +LV_ATTRIBUTE_FAST_MEM static void rgb565_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc); + +LV_ATTRIBUTE_FAST_MEM static void rgb888_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc, const uint8_t src_px_size); + +LV_ATTRIBUTE_FAST_MEM static void argb8888_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc); + +LV_ATTRIBUTE_FAST_MEM static inline lv_color32_t lv_color_32_32_mix(lv_color32_t fg, lv_color32_t bg, + lv_color_mix_alpha_cache_t * cache); + +static void lv_color_mix_with_alpha_cache_init(lv_color_mix_alpha_cache_t * cache); + +LV_ATTRIBUTE_FAST_MEM static inline void blend_non_normal_pixel(lv_color32_t * dest, lv_color32_t src, + lv_blend_mode_t mode, lv_color_mix_alpha_cache_t * cache); +LV_ATTRIBUTE_FAST_MEM static inline void * drawbuf_next_row(const void * buf, uint32_t stride); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888 + #define LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_WITH_OPA + #define LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_WITH_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_WITH_MASK + #define LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_WITH_MASK(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_MIX_MASK_OPA + #define LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_MIX_MASK_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888 + #define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_WITH_OPA + #define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_WITH_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_WITH_MASK + #define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_WITH_MASK(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA + #define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888 + #define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_WITH_OPA + #define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_WITH_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_WITH_MASK + #define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_WITH_MASK(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA + #define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888 + #define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_WITH_OPA + #define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_WITH_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_WITH_MASK + #define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_WITH_MASK(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA + #define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA(...) LV_RESULT_INVALID +#endif + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_color_to_argb8888(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ + int32_t w = dsc->dest_w; + int32_t h = dsc->dest_h; + lv_opa_t opa = dsc->opa; + const lv_opa_t * mask = dsc->mask_buf; + int32_t mask_stride = dsc->mask_stride; + int32_t dest_stride = dsc->dest_stride; + + lv_color_mix_alpha_cache_t cache; + lv_color_mix_with_alpha_cache_init(&cache); + + int32_t x; + int32_t y; + + LV_UNUSED(w); + LV_UNUSED(h); + LV_UNUSED(x); + LV_UNUSED(y); + LV_UNUSED(opa); + LV_UNUSED(mask); + LV_UNUSED(mask_stride); + LV_UNUSED(dest_stride); + + /*Simple fill*/ + if(mask == NULL && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888(dsc)) { + uint32_t color32 = lv_color_to_u32(dsc->color); + uint32_t * dest_buf = dsc->dest_buf; + for(y = 0; y < h; y++) { + for(x = 0; x < w - 16; x += 16) { + dest_buf[x + 0] = color32; + dest_buf[x + 1] = color32; + dest_buf[x + 2] = color32; + dest_buf[x + 3] = color32; + + dest_buf[x + 4] = color32; + dest_buf[x + 5] = color32; + dest_buf[x + 6] = color32; + dest_buf[x + 7] = color32; + + dest_buf[x + 8] = color32; + dest_buf[x + 9] = color32; + dest_buf[x + 10] = color32; + dest_buf[x + 11] = color32; + + dest_buf[x + 12] = color32; + dest_buf[x + 13] = color32; + dest_buf[x + 14] = color32; + dest_buf[x + 15] = color32; + } + for(; x < w; x ++) { + dest_buf[x] = color32; + } + + dest_buf = drawbuf_next_row(dest_buf, dest_stride); + } + } + + } + /*Opacity only*/ + else if(mask == NULL && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_WITH_OPA(dsc)) { + lv_color32_t color_argb = lv_color_to_32(dsc->color, opa); + lv_color32_t * dest_buf = dsc->dest_buf; + + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + dest_buf[x] = lv_color_32_32_mix(color_argb, dest_buf[x], &cache); + } + dest_buf = drawbuf_next_row(dest_buf, dest_stride); + } + } + + } + /*Masked with full opacity*/ + else if(mask && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_WITH_MASK(dsc)) { + lv_color32_t color_argb = lv_color_to_32(dsc->color, 0xff); + lv_color32_t * dest_buf = dsc->dest_buf; + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + color_argb.alpha = mask[x]; + dest_buf[x] = lv_color_32_32_mix(color_argb, dest_buf[x], &cache); + } + + dest_buf = drawbuf_next_row(dest_buf, dest_stride); + mask += mask_stride; + } + } + + } + /*Masked with opacity*/ + else { + if(LV_RESULT_INVALID == LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_MIX_MASK_OPA(dsc)) { + lv_color32_t color_argb = lv_color_to_32(dsc->color, opa); + lv_color32_t * dest_buf = dsc->dest_buf; + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + color_argb.alpha = LV_OPA_MIX2(mask[x], opa); + dest_buf[x] = lv_color_32_32_mix(color_argb, dest_buf[x], &cache); + } + dest_buf = drawbuf_next_row(dest_buf, dest_stride); + mask += mask_stride; + } + } + } +} + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_image_to_argb8888(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + switch(dsc->src_color_format) { + case LV_COLOR_FORMAT_RGB565: + rgb565_image_blend(dsc); + break; + case LV_COLOR_FORMAT_RGB888: + rgb888_image_blend(dsc, 3); + break; + case LV_COLOR_FORMAT_XRGB8888: + rgb888_image_blend(dsc, 4); + break; + case LV_COLOR_FORMAT_ARGB8888: + argb8888_image_blend(dsc); + break; + default: + LV_LOG_WARN("Not supported source color format"); + break; + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +LV_ATTRIBUTE_FAST_MEM static void rgb565_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + int32_t w = dsc->dest_w; + int32_t h = dsc->dest_h; + lv_opa_t opa = dsc->opa; + lv_color32_t * dest_buf_c32 = dsc->dest_buf; + int32_t dest_stride = dsc->dest_stride; + const lv_color16_t * src_buf_c16 = (const lv_color16_t *) dsc->src_buf; + int32_t src_stride = dsc->src_stride; + const lv_opa_t * mask_buf = dsc->mask_buf; + int32_t mask_stride = dsc->mask_stride; + + lv_color32_t color_argb; + lv_color_mix_alpha_cache_t cache; + lv_color_mix_with_alpha_cache_init(&cache); + + int32_t x; + int32_t y; + + LV_UNUSED(color_argb); + + if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { + if(mask_buf == NULL) { + lv_result_t accelerated; + if(opa >= LV_OPA_MAX) { + accelerated = LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888(dsc); + } + else { + accelerated = LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_WITH_OPA(dsc); + } + if(LV_RESULT_INVALID == accelerated) { + color_argb.alpha = opa; + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + color_argb.red = (src_buf_c16[x].red * 2106) >> 8; /*To make it rounded*/ + color_argb.green = (src_buf_c16[x].green * 1037) >> 8; + color_argb.blue = (src_buf_c16[x].blue * 2106) >> 8; + dest_buf_c32[x] = lv_color_32_32_mix(color_argb, dest_buf_c32[x], &cache); + } + dest_buf_c32 = drawbuf_next_row(dest_buf_c32, dest_stride); + src_buf_c16 = drawbuf_next_row(src_buf_c16, src_stride); + } + } + } + else if(mask_buf && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_WITH_MASK(dsc)) { + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + color_argb.alpha = mask_buf[x]; + color_argb.red = (src_buf_c16[x].red * 2106) >> 8; /*To make it rounded*/ + color_argb.green = (src_buf_c16[x].green * 1037) >> 8; + color_argb.blue = (src_buf_c16[x].blue * 2106) >> 8; + dest_buf_c32[x] = lv_color_32_32_mix(color_argb, dest_buf_c32[x], &cache); + } + dest_buf_c32 = drawbuf_next_row(dest_buf_c32, dest_stride); + src_buf_c16 = drawbuf_next_row(src_buf_c16, src_stride); + mask_buf += mask_stride; + } + } + } + else { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA(dsc)) { + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + color_argb.alpha = LV_OPA_MIX2(mask_buf[x], opa); + color_argb.red = (src_buf_c16[x].red * 2106) >> 8; /*To make it rounded*/ + color_argb.green = (src_buf_c16[x].green * 1037) >> 8; + color_argb.blue = (src_buf_c16[x].blue * 2106) >> 8; + dest_buf_c32[x] = lv_color_32_32_mix(color_argb, dest_buf_c32[x], &cache); + } + dest_buf_c32 = drawbuf_next_row(dest_buf_c32, dest_stride); + src_buf_c16 = drawbuf_next_row(src_buf_c16, src_stride); + mask_buf += mask_stride; + } + } + } + } + else { + lv_color32_t src_argb; + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + src_argb.red = (src_buf_c16[x].red * 2106) >> 8; + src_argb.green = (src_buf_c16[x].green * 1037) >> 8; + src_argb.blue = (src_buf_c16[x].blue * 2106) >> 8; + if(mask_buf == NULL) src_argb.alpha = opa; + else src_argb.alpha = LV_OPA_MIX2(mask_buf[x], opa); + blend_non_normal_pixel(&dest_buf_c32[x], src_argb, dsc->blend_mode, &cache); + } + if(mask_buf) mask_buf += mask_stride; + dest_buf_c32 = drawbuf_next_row(dest_buf_c32, dest_stride); + src_buf_c16 = drawbuf_next_row(src_buf_c16, src_stride); + } + } +} + +LV_ATTRIBUTE_FAST_MEM static void rgb888_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc, const uint8_t src_px_size) +{ + + int32_t w = dsc->dest_w; + int32_t h = dsc->dest_h; + lv_opa_t opa = dsc->opa; + lv_color32_t * dest_buf_c32 = dsc->dest_buf; + int32_t dest_stride = dsc->dest_stride; + const uint8_t * src_buf = dsc->src_buf; + int32_t src_stride = dsc->src_stride; + const lv_opa_t * mask_buf = dsc->mask_buf; + int32_t mask_stride = dsc->mask_stride; + + lv_color32_t color_argb; + lv_color_mix_alpha_cache_t cache; + lv_color_mix_with_alpha_cache_init(&cache); + + int32_t dest_x; + int32_t src_x; + int32_t y; + + LV_UNUSED(color_argb); + + if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { + /*Special case*/ + if(mask_buf == NULL && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888(dsc, src_px_size)) { + if(src_px_size == 4) { + uint32_t line_in_bytes = w * 4; + for(y = 0; y < h; y++) { + lv_memcpy(dest_buf_c32, src_buf, line_in_bytes); + dest_buf_c32 = drawbuf_next_row(dest_buf_c32, dest_stride); + src_buf = drawbuf_next_row(src_buf, src_stride); + } + } + else if(src_px_size == 3) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += 3) { + dest_buf_c32[dest_x].red = src_buf[src_x + 2]; + dest_buf_c32[dest_x].green = src_buf[src_x + 1]; + dest_buf_c32[dest_x].blue = src_buf[src_x + 0]; + dest_buf_c32[dest_x].alpha = 0xff; + } + dest_buf_c32 = drawbuf_next_row(dest_buf_c32, dest_stride); + src_buf = drawbuf_next_row(src_buf, src_stride); + } + } + } + + } + if(mask_buf == NULL && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_WITH_OPA(dsc, src_px_size)) { + color_argb.alpha = opa; + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += src_px_size) { + color_argb.red = src_buf[src_x + 2]; + color_argb.green = src_buf[src_x + 1]; + color_argb.blue = src_buf[src_x + 0]; + dest_buf_c32[dest_x] = lv_color_32_32_mix(color_argb, dest_buf_c32[dest_x], &cache); + } + dest_buf_c32 = drawbuf_next_row(dest_buf_c32, dest_stride); + src_buf = drawbuf_next_row(src_buf, src_stride); + } + } + + } + if(mask_buf && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_WITH_MASK(dsc, src_px_size)) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += src_px_size) { + color_argb.alpha = mask_buf[dest_x]; + color_argb.red = src_buf[src_x + 2]; + color_argb.green = src_buf[src_x + 1]; + color_argb.blue = src_buf[src_x + 0]; + dest_buf_c32[dest_x] = lv_color_32_32_mix(color_argb, dest_buf_c32[dest_x], &cache); + } + dest_buf_c32 = drawbuf_next_row(dest_buf_c32, dest_stride); + src_buf = drawbuf_next_row(src_buf, src_stride); + mask_buf += mask_stride; + } + } + } + if(mask_buf && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA(dsc, src_px_size)) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += src_px_size) { + color_argb.alpha = (opa * mask_buf[dest_x]) >> 8; + color_argb.red = src_buf[src_x + 2]; + color_argb.green = src_buf[src_x + 1]; + color_argb.blue = src_buf[src_x + 0]; + dest_buf_c32[dest_x] = lv_color_32_32_mix(color_argb, dest_buf_c32[dest_x], &cache); + } + dest_buf_c32 = drawbuf_next_row(dest_buf_c32, dest_stride); + src_buf = drawbuf_next_row(src_buf, src_stride); + mask_buf += mask_stride; + } + } + } + } + else { + lv_color32_t src_argb; + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += src_px_size) { + src_argb.red = src_buf[src_x + 2]; + src_argb.green = src_buf[src_x + 1]; + src_argb.blue = src_buf[src_x + 0]; + if(mask_buf == NULL) src_argb.alpha = opa; + else src_argb.alpha = LV_OPA_MIX2(mask_buf[dest_x], opa); + + blend_non_normal_pixel(&dest_buf_c32[dest_x], src_argb, dsc->blend_mode, &cache); + } + if(mask_buf) mask_buf += mask_stride; + dest_buf_c32 = drawbuf_next_row(dest_buf_c32, dest_stride); + src_buf = drawbuf_next_row(src_buf, src_stride); + } + } +} + +LV_ATTRIBUTE_FAST_MEM static void argb8888_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + int32_t w = dsc->dest_w; + int32_t h = dsc->dest_h; + lv_opa_t opa = dsc->opa; + lv_color32_t * dest_buf_c32 = dsc->dest_buf; + int32_t dest_stride = dsc->dest_stride; + const lv_color32_t * src_buf_c32 = dsc->src_buf; + int32_t src_stride = dsc->src_stride; + const lv_opa_t * mask_buf = dsc->mask_buf; + int32_t mask_stride = dsc->mask_stride; + + lv_color32_t color_argb; + lv_color_mix_alpha_cache_t cache; + lv_color_mix_with_alpha_cache_init(&cache); + + int32_t x; + int32_t y; + + if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { + if(mask_buf == NULL && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888(dsc)) { + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + dest_buf_c32[x] = lv_color_32_32_mix(src_buf_c32[x], dest_buf_c32[x], &cache); + } + dest_buf_c32 = drawbuf_next_row(dest_buf_c32, dest_stride); + src_buf_c32 = drawbuf_next_row(src_buf_c32, src_stride); + } + } + } + else if(mask_buf == NULL && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_WITH_OPA(dsc)) { + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + color_argb = src_buf_c32[x]; + color_argb.alpha = LV_OPA_MIX2(color_argb.alpha, opa); + dest_buf_c32[x] = lv_color_32_32_mix(color_argb, dest_buf_c32[x], &cache); + } + dest_buf_c32 = drawbuf_next_row(dest_buf_c32, dest_stride); + src_buf_c32 = drawbuf_next_row(src_buf_c32, src_stride); + } + } + } + else if(mask_buf && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_WITH_MASK(dsc)) { + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + color_argb = src_buf_c32[x]; + color_argb.alpha = LV_OPA_MIX2(color_argb.alpha, mask_buf[x]); + dest_buf_c32[x] = lv_color_32_32_mix(color_argb, dest_buf_c32[x], &cache); + } + dest_buf_c32 = drawbuf_next_row(dest_buf_c32, dest_stride); + src_buf_c32 = drawbuf_next_row(src_buf_c32, src_stride); + mask_buf += mask_stride; + } + } + } + else if(mask_buf && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA(dsc)) { + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + color_argb = src_buf_c32[x]; + color_argb.alpha = LV_OPA_MIX3(color_argb.alpha, opa, mask_buf[x]); + dest_buf_c32[x] = lv_color_32_32_mix(color_argb, dest_buf_c32[x], &cache); + } + dest_buf_c32 = drawbuf_next_row(dest_buf_c32, dest_stride); + src_buf_c32 = drawbuf_next_row(src_buf_c32, src_stride); + mask_buf += mask_stride; + } + } + } + } + else { + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + color_argb = src_buf_c32[x]; + if(mask_buf == NULL) color_argb.alpha = LV_OPA_MIX2(color_argb.alpha, opa); + else color_argb.alpha = LV_OPA_MIX3(color_argb.alpha, mask_buf[x], opa); + blend_non_normal_pixel(&dest_buf_c32[x], color_argb, dsc->blend_mode, &cache); + } + if(mask_buf) mask_buf += mask_stride; + dest_buf_c32 = drawbuf_next_row(dest_buf_c32, dest_stride); + src_buf_c32 = drawbuf_next_row(src_buf_c32, src_stride); + } + } +} + +LV_ATTRIBUTE_FAST_MEM static inline lv_color32_t lv_color_32_32_mix(lv_color32_t fg, lv_color32_t bg, + lv_color_mix_alpha_cache_t * cache) +{ + /*Pick the foreground if it's fully opaque or the Background is fully transparent*/ + if(fg.alpha >= LV_OPA_MAX || bg.alpha <= LV_OPA_MIN) { + return fg; + } + /*Transparent foreground: use the Background*/ + else if(fg.alpha <= LV_OPA_MIN) { + return bg; + } + /*Opaque background: use simple mix*/ + else if(bg.alpha == 255) { + return lv_color_mix32(fg, bg); + } + /*Both colors have alpha. Expensive calculation need to be applied*/ + else { + /*Save the parameters and the result. If they will be asked again don't compute again*/ + + /*Update the ratio and the result alpha value if the input alpha values change*/ + if(bg.alpha != cache->bg_saved.alpha || fg.alpha != cache->fg_saved.alpha) { + /*Info: + * https://en.wikipedia.org/wiki/Alpha_compositing#Analytical_derivation_of_the_over_operator*/ + cache->res_alpha_saved = 255 - LV_OPA_MIX2(255 - fg.alpha, 255 - bg.alpha); + LV_ASSERT(cache->ratio_saved != 0); + cache->ratio_saved = (uint32_t)((uint32_t)fg.alpha * 255) / cache->res_alpha_saved; + } + + if(!lv_color32_eq(bg, cache->bg_saved) || !lv_color32_eq(fg, cache->fg_saved)) { + cache->fg_saved = fg; + cache->bg_saved = bg; + fg.alpha = cache->ratio_saved; + cache->res_saved = lv_color_mix32(fg, bg); + cache->res_saved.alpha = cache->res_alpha_saved; + } + + return cache->res_saved; + } +} + +void lv_color_mix_with_alpha_cache_init(lv_color_mix_alpha_cache_t * cache) +{ + lv_memzero(&cache->fg_saved, sizeof(lv_color32_t)); + lv_memzero(&cache->bg_saved, sizeof(lv_color32_t)); + lv_memzero(&cache->res_saved, sizeof(lv_color32_t)); + cache->res_alpha_saved = 255; + cache->ratio_saved = 255; +} + +LV_ATTRIBUTE_FAST_MEM static inline void blend_non_normal_pixel(lv_color32_t * dest, lv_color32_t src, + lv_blend_mode_t mode, lv_color_mix_alpha_cache_t * cache) +{ + lv_color32_t res; + switch(mode) { + case LV_BLEND_MODE_ADDITIVE: + res.red = LV_MIN(dest->red + src.red, 255); + res.green = LV_MIN(dest->green + src.green, 255); + res.blue = LV_MIN(dest->blue + src.blue, 255); + break; + case LV_BLEND_MODE_SUBTRACTIVE: + res.red = LV_MAX(dest->red - src.red, 0); + res.green = LV_MAX(dest->green - src.green, 0); + res.blue = LV_MAX(dest->blue - src.blue, 0); + break; + case LV_BLEND_MODE_MULTIPLY: + res.red = (dest->red * src.red) >> 8; + res.green = (dest->green * src.green) >> 8; + res.blue = (dest->blue * src.blue) >> 8; + break; + default: + LV_LOG_WARN("Not supported blend mode: %d", mode); + return; + } + res.alpha = src.alpha; + *dest = lv_color_32_32_mix(res, *dest, cache); +} + +LV_ATTRIBUTE_FAST_MEM static inline void * drawbuf_next_row(const void * buf, uint32_t stride) +{ + return (void *)((uint8_t *)buf + stride); +} + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_argb8888.h b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_argb8888.h new file mode 100644 index 000000000..66299f4e2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_argb8888.h @@ -0,0 +1,45 @@ +/** + * @file lv_draw_sw_blend_argb8888.h + * + */ + +#ifndef LV_DRAW_SW_BLEND_ARGB8888_H +#define LV_DRAW_SW_BLEND_ARGB8888_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_draw_sw.h" +#if LV_USE_DRAW_SW + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_color_to_argb8888(_lv_draw_sw_blend_fill_dsc_t * dsc); + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_image_to_argb8888(_lv_draw_sw_blend_image_dsc_t * dsc); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DRAW_SW*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SW_BLEND_ARGB8888_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb565.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb565.c new file mode 100644 index 000000000..634ed7b46 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb565.c @@ -0,0 +1,675 @@ +/** + * @file lv_draw_sw_blend_to_rgb565.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_sw_blend_to_rgb565.h" +#if LV_USE_DRAW_SW + +#include "lv_draw_sw_blend.h" +#include "../../../misc/lv_math.h" +#include "../../../display/lv_display.h" +#include "../../../core/lv_refr.h" +#include "../../../misc/lv_color.h" +#include "../../../stdlib/lv_string.h" + +#if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_NEON + #include "neon/lv_blend_neon.h" +#elif LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_HELIUM + #include "arm2d/lv_blend_helium.h" +#elif LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_CUSTOM + #include LV_DRAW_SW_ASM_CUSTOM_INCLUDE +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +LV_ATTRIBUTE_FAST_MEM static void rgb565_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc); + +LV_ATTRIBUTE_FAST_MEM static void rgb888_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc, const uint8_t src_px_size); + +LV_ATTRIBUTE_FAST_MEM static void argb8888_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc); + +LV_ATTRIBUTE_FAST_MEM static inline uint16_t lv_color_24_16_mix(const uint8_t * c1, uint16_t c2, uint8_t mix); + +LV_ATTRIBUTE_FAST_MEM static inline void * drawbuf_next_row(const void * buf, uint32_t stride); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565 + #define LV_DRAW_SW_COLOR_BLEND_TO_RGB565(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_OPA + #define LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_MASK + #define LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_MASK(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565_MIX_MASK_OPA + #define LV_DRAW_SW_COLOR_BLEND_TO_RGB565_MIX_MASK_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565 + #define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_OPA + #define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_MASK + #define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_MASK(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA + #define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565 + #define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_OPA + #define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_MASK + #define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_MASK(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA + #define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565 + #define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_OPA + #define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_MASK + #define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_MASK(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA + #define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(...) LV_RESULT_INVALID +#endif + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Fill an area with a color. + * Supports normal fill, fill with opacity, fill with mask, and fill with mask and opacity. + * dest_buf and color have native color depth. (RGB565, RGB888, XRGB8888) + * The background (dest_buf) cannot have alpha channel + * @param dest_buf + * @param dest_area + * @param dest_stride + * @param color + * @param opa + * @param mask + * @param mask_stride + */ +LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_color_to_rgb565(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ + int32_t w = dsc->dest_w; + int32_t h = dsc->dest_h; + uint16_t color16 = lv_color_to_u16(dsc->color); + lv_opa_t opa = dsc->opa; + const lv_opa_t * mask = dsc->mask_buf; + int32_t mask_stride = dsc->mask_stride; + uint16_t * dest_buf_u16 = dsc->dest_buf; + int32_t dest_stride = dsc->dest_stride; + + int32_t x; + int32_t y; + + LV_UNUSED(w); + LV_UNUSED(h); + LV_UNUSED(x); + LV_UNUSED(y); + LV_UNUSED(opa); + LV_UNUSED(mask); + LV_UNUSED(color16); + LV_UNUSED(mask_stride); + LV_UNUSED(dest_stride); + LV_UNUSED(dest_buf_u16); + + /*Simple fill*/ + if(mask == NULL && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_COLOR_BLEND_TO_RGB565(dsc)) { + for(y = 0; y < h; y++) { + uint16_t * dest_end_final = dest_buf_u16 + w; + uint32_t * dest_end_mid = (uint32_t *)((uint16_t *) dest_buf_u16 + ((w - 1) & ~(0xF))); + if((lv_uintptr_t)&dest_buf_u16[0] & 0x3) { + dest_buf_u16[0] = color16; + dest_buf_u16++; + } + + uint32_t c32 = (uint32_t)color16 + ((uint32_t)color16 << 16); + uint32_t * dest32 = (uint32_t *)dest_buf_u16; + while(dest32 < dest_end_mid) { + dest32[0] = c32; + dest32[1] = c32; + dest32[2] = c32; + dest32[3] = c32; + dest32[4] = c32; + dest32[5] = c32; + dest32[6] = c32; + dest32[7] = c32; + dest32 += 8; + } + + dest_buf_u16 = (uint16_t *)dest32; + + while(dest_buf_u16 < dest_end_final) { + *dest_buf_u16 = color16; + dest_buf_u16++; + } + + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + dest_buf_u16 -= w; + } + } + + } + /*Opacity only*/ + else if(mask == NULL && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_OPA(dsc)) { + uint32_t last_dest32_color = dest_buf_u16[0] + 1; /*Set to value which is not equal to the first pixel*/ + uint32_t last_res32_color = 0; + + for(y = 0; y < h; y++) { + x = 0; + if((lv_uintptr_t)&dest_buf_u16[0] & 0x3) { + dest_buf_u16[0] = lv_color_16_16_mix(color16, dest_buf_u16[0], opa); + x = 1; + } + + for(; x < w - 2; x += 2) { + if(dest_buf_u16[x] != dest_buf_u16[x + 1]) { + dest_buf_u16[x + 0] = lv_color_16_16_mix(color16, dest_buf_u16[x + 0], opa); + dest_buf_u16[x + 1] = lv_color_16_16_mix(color16, dest_buf_u16[x + 1], opa); + } + else { + volatile uint32_t * dest32 = (uint32_t *)&dest_buf_u16[x]; + if(last_dest32_color == *dest32) { + *dest32 = last_res32_color; + } + else { + last_dest32_color = *dest32; + + dest_buf_u16[x] = lv_color_16_16_mix(color16, dest_buf_u16[x + 0], opa); + dest_buf_u16[x + 1] = dest_buf_u16[x]; + + last_res32_color = *dest32; + } + } + } + + for(; x < w ; x++) { + dest_buf_u16[x] = lv_color_16_16_mix(color16, dest_buf_u16[x], opa); + } + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + } + } + + } + + /*Masked with full opacity*/ + else if(mask && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_MASK(dsc)) { + uint32_t c32 = color16 + ((uint32_t)color16 << 16); + for(y = 0; y < h; y++) { + for(x = 0; x < w && ((lv_uintptr_t)(mask) & 0x3); x++) { + dest_buf_u16[x] = lv_color_16_16_mix(color16, dest_buf_u16[x], mask[x]); + } + + for(; x <= w - 4; x += 4) { + uint32_t mask32 = *((uint32_t *)&mask[x]); + if(mask32 == 0xFFFFFFFF) { + if((lv_uintptr_t)&dest_buf_u16[x] & 0x3) { + dest_buf_u16[x] = color16; + uint32_t * d32 = (uint32_t *)(&dest_buf_u16[x + 1]); + *d32 = c32; + dest_buf_u16[x + 3] = color16; + } + else { + uint32_t * dest32 = (uint32_t *)&dest_buf_u16[x]; + dest32[0] = c32; + dest32[1] = c32; + } + } + else if(mask32) { + dest_buf_u16[x + 0] = lv_color_16_16_mix(color16, dest_buf_u16[x + 0], mask[x + 0]); + dest_buf_u16[x + 1] = lv_color_16_16_mix(color16, dest_buf_u16[x + 1], mask[x + 1]); + dest_buf_u16[x + 2] = lv_color_16_16_mix(color16, dest_buf_u16[x + 2], mask[x + 2]); + dest_buf_u16[x + 3] = lv_color_16_16_mix(color16, dest_buf_u16[x + 3], mask[x + 3]); + } + } + + for(; x < w ; x++) { + dest_buf_u16[x] = lv_color_16_16_mix(color16, dest_buf_u16[x], mask[x]); + } + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + mask += mask_stride; + } + } + + } + /*Masked with opacity*/ + else if(mask && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_COLOR_BLEND_TO_RGB565_MIX_MASK_OPA(dsc)) { + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + dest_buf_u16[x] = lv_color_16_16_mix(color16, dest_buf_u16[x], LV_OPA_MIX2(mask[x], opa)); + } + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + mask += mask_stride; + } + } + } +} + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_image_to_rgb565(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + switch(dsc->src_color_format) { + case LV_COLOR_FORMAT_RGB565: + rgb565_image_blend(dsc); + break; + case LV_COLOR_FORMAT_RGB888: + rgb888_image_blend(dsc, 3); + break; + case LV_COLOR_FORMAT_XRGB8888: + rgb888_image_blend(dsc, 4); + break; + case LV_COLOR_FORMAT_ARGB8888: + argb8888_image_blend(dsc); + break; + default: + LV_LOG_WARN("Not supported source color format"); + break; + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +LV_ATTRIBUTE_FAST_MEM static void rgb565_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + int32_t w = dsc->dest_w; + int32_t h = dsc->dest_h; + lv_opa_t opa = dsc->opa; + uint16_t * dest_buf_u16 = dsc->dest_buf; + int32_t dest_stride = dsc->dest_stride; + const uint16_t * src_buf_u16 = dsc->src_buf; + int32_t src_stride = dsc->src_stride; + const lv_opa_t * mask_buf = dsc->mask_buf; + int32_t mask_stride = dsc->mask_stride; + + int32_t x; + int32_t y; + + if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { + if(mask_buf == NULL && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565(dsc)) { + uint32_t line_in_bytes = w * 2; + for(y = 0; y < h; y++) { + lv_memcpy(dest_buf_u16, src_buf_u16, line_in_bytes); + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + src_buf_u16 = drawbuf_next_row(src_buf_u16, src_stride); + } + } + } + else if(mask_buf == NULL && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_OPA(dsc)) { + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + dest_buf_u16[x] = lv_color_16_16_mix(src_buf_u16[x], dest_buf_u16[x], opa); + } + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + src_buf_u16 = drawbuf_next_row(src_buf_u16, src_stride); + } + } + } + else if(mask_buf && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_MASK(dsc)) { + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + dest_buf_u16[x] = lv_color_16_16_mix(src_buf_u16[x], dest_buf_u16[x], mask_buf[x]); + } + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + src_buf_u16 = drawbuf_next_row(src_buf_u16, src_stride); + mask_buf += mask_stride; + } + } + } + else { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(dsc)) { + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + dest_buf_u16[x] = lv_color_16_16_mix(src_buf_u16[x], dest_buf_u16[x], LV_OPA_MIX2(mask_buf[x], opa)); + } + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + src_buf_u16 = drawbuf_next_row(src_buf_u16, src_stride); + mask_buf += mask_stride; + } + } + } + } + else { + uint16_t res = 0; + for(y = 0; y < h; y++) { + lv_color16_t * dest_buf_c16 = (lv_color16_t *) dest_buf_u16; + lv_color16_t * src_buf_c16 = (lv_color16_t *) src_buf_u16; + for(x = 0; x < w; x++) { + switch(dsc->blend_mode) { + case LV_BLEND_MODE_ADDITIVE: + if(src_buf_u16[x] == 0x0000) continue; /*Do not add pure black*/ + res = (LV_MIN(dest_buf_c16[x].red + src_buf_c16[x].red, 31)) << 11; + res += (LV_MIN(dest_buf_c16[x].green + src_buf_c16[x].green, 63)) << 5; + res += LV_MIN(dest_buf_c16[x].blue + src_buf_c16[x].blue, 31); + break; + case LV_BLEND_MODE_SUBTRACTIVE: + if(src_buf_u16[x] == 0x0000) continue; /*Do not subtract pure black*/ + res = (LV_MAX(dest_buf_c16[x].red - src_buf_c16[x].red, 0)) << 11; + res += (LV_MAX(dest_buf_c16[x].green - src_buf_c16[x].green, 0)) << 5; + res += LV_MAX(dest_buf_c16[x].blue - src_buf_c16[x].blue, 0); + break; + case LV_BLEND_MODE_MULTIPLY: + if(src_buf_u16[x] == 0xffff) continue; /*Do not multiply with pure white (considered as 1)*/ + res = ((dest_buf_c16[x].red * src_buf_c16[x].red) >> 5) << 11; + res += ((dest_buf_c16[x].green * src_buf_c16[x].green) >> 6) << 5; + res += (dest_buf_c16[x].blue * src_buf_c16[x].blue) >> 5; + break; + default: + LV_LOG_WARN("Not supported blend mode: %d", dsc->blend_mode); + return; + } + + if(mask_buf == NULL) { + dest_buf_u16[x] = lv_color_16_16_mix(res, dest_buf_u16[x], opa); + } + else { + if(opa >= LV_OPA_MAX) dest_buf_u16[x] = lv_color_16_16_mix(res, dest_buf_u16[x], mask_buf[x]); + else dest_buf_u16[x] = lv_color_16_16_mix(res, dest_buf_u16[x], LV_OPA_MIX2(mask_buf[x], opa)); + } + } + + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + src_buf_u16 = drawbuf_next_row(src_buf_u16, src_stride); + if(mask_buf) mask_buf += mask_stride; + } + } +} + +LV_ATTRIBUTE_FAST_MEM static void rgb888_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc, const uint8_t src_px_size) +{ + int32_t w = dsc->dest_w; + int32_t h = dsc->dest_h; + lv_opa_t opa = dsc->opa; + uint16_t * dest_buf_u16 = dsc->dest_buf; + int32_t dest_stride = dsc->dest_stride; + const uint8_t * src_buf_u8 = dsc->src_buf; + int32_t src_stride = dsc->src_stride; + const lv_opa_t * mask_buf = dsc->mask_buf; + int32_t mask_stride = dsc->mask_stride; + + int32_t dest_x; + int32_t src_x; + int32_t y; + + if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { + if(mask_buf == NULL && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565(dsc, src_px_size)) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += src_px_size) { + dest_buf_u16[dest_x] = ((src_buf_u8[src_x + 2] & 0xF8) << 8) + + ((src_buf_u8[src_x + 1] & 0xFC) << 3) + + ((src_buf_u8[src_x + 0] & 0xF8) >> 3); + } + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + src_buf_u8 += src_stride; + } + } + } + else if(mask_buf == NULL && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_OPA(dsc, src_px_size)) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += src_px_size) { + dest_buf_u16[dest_x] = lv_color_24_16_mix(&src_buf_u8[src_x], dest_buf_u16[dest_x], opa); + } + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + src_buf_u8 += src_stride; + } + } + } + if(mask_buf && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_MASK(dsc, src_px_size)) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += src_px_size) { + dest_buf_u16[dest_x] = lv_color_24_16_mix(&src_buf_u8[src_x], dest_buf_u16[dest_x], mask_buf[dest_x]); + } + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + src_buf_u8 += src_stride; + mask_buf += mask_stride; + } + } + } + if(mask_buf && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(dsc, src_px_size)) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += src_px_size) { + dest_buf_u16[dest_x] = lv_color_24_16_mix(&src_buf_u8[src_x], dest_buf_u16[dest_x], LV_OPA_MIX2(mask_buf[dest_x], opa)); + } + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + src_buf_u8 += src_stride; + mask_buf += mask_stride; + } + } + } + } + else { + uint16_t res = 0; + for(y = 0; y < h; y++) { + lv_color16_t * dest_buf_c16 = (lv_color16_t *) dest_buf_u16; + for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += src_px_size) { + switch(dsc->blend_mode) { + case LV_BLEND_MODE_ADDITIVE: + res = (LV_MIN(dest_buf_c16[dest_x].red + (src_buf_u8[src_x + 2] >> 3), 31)) << 11; + res += (LV_MIN(dest_buf_c16[dest_x].green + (src_buf_u8[src_x + 1] >> 2), 63)) << 5; + res += LV_MIN(dest_buf_c16[dest_x].blue + (src_buf_u8[src_x + 0] >> 3), 31); + break; + case LV_BLEND_MODE_SUBTRACTIVE: + res = (LV_MAX(dest_buf_c16[dest_x].red - (src_buf_u8[src_x + 2] >> 3), 0)) << 11; + res += (LV_MAX(dest_buf_c16[dest_x].green - (src_buf_u8[src_x + 1] >> 2), 0)) << 5; + res += LV_MAX(dest_buf_c16[dest_x].blue - (src_buf_u8[src_x + 0] >> 3), 0); + break; + case LV_BLEND_MODE_MULTIPLY: + res = ((dest_buf_c16[dest_x].red * (src_buf_u8[src_x + 2] >> 3)) >> 5) << 11; + res += ((dest_buf_c16[dest_x].green * (src_buf_u8[src_x + 1] >> 2)) >> 6) << 5; + res += (dest_buf_c16[dest_x].blue * (src_buf_u8[src_x + 1] >> 3)) >> 5; + break; + default: + LV_LOG_WARN("Not supported blend mode: %d", dsc->blend_mode); + return; + } + + if(mask_buf == NULL) { + dest_buf_u16[dest_x] = lv_color_16_16_mix(res, dest_buf_u16[dest_x], opa); + } + else { + if(opa >= LV_OPA_MAX) dest_buf_u16[dest_x] = lv_color_16_16_mix(res, dest_buf_u16[dest_x], mask_buf[dest_x]); + else dest_buf_u16[dest_x] = lv_color_16_16_mix(res, dest_buf_u16[dest_x], LV_OPA_MIX2(mask_buf[dest_x], opa)); + } + } + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + src_buf_u8 += src_stride; + if(mask_buf) mask_buf += mask_stride; + } + + } +} + +LV_ATTRIBUTE_FAST_MEM static void argb8888_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + int32_t w = dsc->dest_w; + int32_t h = dsc->dest_h; + lv_opa_t opa = dsc->opa; + uint16_t * dest_buf_u16 = dsc->dest_buf; + int32_t dest_stride = dsc->dest_stride; + const uint8_t * src_buf_u8 = dsc->src_buf; + int32_t src_stride = dsc->src_stride; + const lv_opa_t * mask_buf = dsc->mask_buf; + int32_t mask_stride = dsc->mask_stride; + + int32_t dest_x; + int32_t src_x; + int32_t y; + + if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { + if(mask_buf == NULL && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565(dsc)) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += 4) { + dest_buf_u16[dest_x] = lv_color_24_16_mix(&src_buf_u8[src_x], dest_buf_u16[dest_x], src_buf_u8[src_x + 3]); + } + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + src_buf_u8 += src_stride; + } + } + } + else if(mask_buf == NULL && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_OPA(dsc)) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += 4) { + dest_buf_u16[dest_x] = lv_color_24_16_mix(&src_buf_u8[src_x], dest_buf_u16[dest_x], LV_OPA_MIX2(src_buf_u8[src_x + 3], + opa)); + } + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + src_buf_u8 += src_stride; + } + } + } + else if(mask_buf && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_MASK(dsc)) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += 4) { + dest_buf_u16[dest_x] = lv_color_24_16_mix(&src_buf_u8[src_x], dest_buf_u16[dest_x], + LV_OPA_MIX2(src_buf_u8[src_x + 3], mask_buf[dest_x])); + } + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + src_buf_u8 += src_stride; + mask_buf += mask_stride; + } + } + } + else if(mask_buf && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(dsc)) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += 4) { + dest_buf_u16[dest_x] = lv_color_24_16_mix(&src_buf_u8[src_x], dest_buf_u16[dest_x], + LV_OPA_MIX3(src_buf_u8[src_x + 3], mask_buf[dest_x], opa)); + } + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + src_buf_u8 += src_stride; + mask_buf += mask_stride; + } + } + } + } + else { + uint16_t res = 0; + for(y = 0; y < h; y++) { + lv_color16_t * dest_buf_c16 = (lv_color16_t *) dest_buf_u16; + for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += 4) { + switch(dsc->blend_mode) { + case LV_BLEND_MODE_ADDITIVE: + res = (LV_MIN(dest_buf_c16[dest_x].red + (src_buf_u8[src_x + 2] >> 3), 31)) << 11; + res += (LV_MIN(dest_buf_c16[dest_x].green + (src_buf_u8[src_x + 1] >> 2), 63)) << 5; + res += LV_MIN(dest_buf_c16[dest_x].blue + (src_buf_u8[src_x + 0] >> 3), 31); + break; + case LV_BLEND_MODE_SUBTRACTIVE: + res = (LV_MAX(dest_buf_c16[dest_x].red - (src_buf_u8[src_x + 2] >> 3), 0)) << 11; + res += (LV_MAX(dest_buf_c16[dest_x].green - (src_buf_u8[src_x + 1] >> 2), 0)) << 5; + res += LV_MAX(dest_buf_c16[dest_x].blue - (src_buf_u8[src_x + 0] >> 3), 0); + break; + case LV_BLEND_MODE_MULTIPLY: + res = ((dest_buf_c16[dest_x].red * (src_buf_u8[src_x + 2] >> 3)) >> 5) << 11; + res += ((dest_buf_c16[dest_x].green * (src_buf_u8[src_x + 1] >> 2)) >> 6) << 5; + res += (dest_buf_c16[dest_x].blue * (src_buf_u8[src_x + 0] >> 3)) >> 5; + break; + default: + LV_LOG_WARN("Not supported blend mode: %d", dsc->blend_mode); + return; + } + + if(mask_buf == NULL && opa >= LV_OPA_MAX) { + dest_buf_u16[dest_x] = lv_color_16_16_mix(res, dest_buf_u16[dest_x], src_buf_u8[src_x + 3]); + } + else if(mask_buf == NULL && opa < LV_OPA_MAX) { + dest_buf_u16[dest_x] = lv_color_16_16_mix(res, dest_buf_u16[dest_x], LV_OPA_MIX2(opa, src_buf_u8[src_x + 3])); + } + else { + if(opa >= LV_OPA_MAX) dest_buf_u16[dest_x] = lv_color_16_16_mix(res, dest_buf_u16[dest_x], mask_buf[dest_x]); + else dest_buf_u16[dest_x] = lv_color_16_16_mix(res, dest_buf_u16[dest_x], LV_OPA_MIX3(mask_buf[dest_x], opa, + src_buf_u8[src_x + 3])); + } + } + + dest_buf_u16 = drawbuf_next_row(dest_buf_u16, dest_stride); + src_buf_u8 += src_stride; + if(mask_buf) mask_buf += mask_stride; + } + } +} + +LV_ATTRIBUTE_FAST_MEM static inline uint16_t lv_color_24_16_mix(const uint8_t * c1, uint16_t c2, uint8_t mix) +{ + if(mix == 0) { + return c2; + } + else if(mix == 255) { + return ((c1[2] & 0xF8) << 8) + ((c1[1] & 0xFC) << 3) + ((c1[0] & 0xF8) >> 3); + } + else { + lv_opa_t mix_inv = 255 - mix; + + return ((((c1[2] >> 3) * mix + ((c2 >> 11) & 0x1F) * mix_inv) << 3) & 0xF800) + + ((((c1[1] >> 2) * mix + ((c2 >> 5) & 0x3F) * mix_inv) >> 3) & 0x07E0) + + (((c1[0] >> 3) * mix + (c2 & 0x1F) * mix_inv) >> 8); + } +} + +LV_ATTRIBUTE_FAST_MEM static inline void * drawbuf_next_row(const void * buf, uint32_t stride) +{ + return (void *)((uint8_t *)buf + stride); +} + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb565.h b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb565.h new file mode 100644 index 000000000..b87611ee2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb565.h @@ -0,0 +1,45 @@ +/** + * @file lv_draw_sw_blend_rgb565.h + * + */ + +#ifndef LV_DRAW_SW_BLEND_RGB565_H +#define LV_DRAW_SW_BLEND_RGB565_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_draw_sw.h" +#if LV_USE_DRAW_SW + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_color_to_rgb565(_lv_draw_sw_blend_fill_dsc_t * dsc); + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_image_to_rgb565(_lv_draw_sw_blend_image_dsc_t * dsc); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DRAW_SW*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SW_BLEND_RGB565_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb888.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb888.c new file mode 100644 index 000000000..17860a257 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb888.c @@ -0,0 +1,606 @@ +/** + * @file lv_draw_sw_blend_to_rgb888.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_sw_blend_to_rgb888.h" +#if LV_USE_DRAW_SW + +#include "lv_draw_sw_blend.h" +#include "../../../misc/lv_math.h" +#include "../../../display/lv_display.h" +#include "../../../core/lv_refr.h" +#include "../../../misc/lv_color.h" +#include "../../../stdlib/lv_string.h" + +#if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_NEON + #include "neon/lv_blend_neon.h" +#elif LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_HELIUM + #include "arm2d/lv_blend_helium.h" +#elif LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_CUSTOM + #include LV_DRAW_SW_ASM_CUSTOM_INCLUDE +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +LV_ATTRIBUTE_FAST_MEM static void rgb565_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc, uint32_t dest_px_size); + +LV_ATTRIBUTE_FAST_MEM static void rgb888_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc, const uint8_t dest_px_size, + uint32_t src_px_size); + +LV_ATTRIBUTE_FAST_MEM static void argb8888_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc, uint32_t dest_px_size); + +LV_ATTRIBUTE_FAST_MEM static inline void lv_color_24_24_mix(const uint8_t * src, uint8_t * dest, uint8_t mix); + +LV_ATTRIBUTE_FAST_MEM static inline void blend_non_normal_pixel(uint8_t * dest, lv_color32_t src, lv_blend_mode_t mode); +LV_ATTRIBUTE_FAST_MEM static inline void * drawbuf_next_row(const void * buf, uint32_t stride); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB888 + #define LV_DRAW_SW_COLOR_BLEND_TO_RGB888(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_OPA + #define LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_MASK + #define LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_MASK(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB888_MIX_MASK_OPA + #define LV_DRAW_SW_COLOR_BLEND_TO_RGB888_MIX_MASK_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888 + #define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_OPA + #define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_MASK + #define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_MASK(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA + #define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888 + #define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_OPA + #define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_MASK + #define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_MASK(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA + #define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888 + #define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_OPA + #define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_OPA(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_MASK + #define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_MASK(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA + #define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA(...) LV_RESULT_INVALID +#endif + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_color_to_rgb888(_lv_draw_sw_blend_fill_dsc_t * dsc, uint32_t dest_px_size) +{ + int32_t w = dsc->dest_w; + int32_t h = dsc->dest_h; + lv_opa_t opa = dsc->opa; + const lv_opa_t * mask = dsc->mask_buf; + int32_t mask_stride = dsc->mask_stride; + int32_t dest_stride = dsc->dest_stride; + + int32_t x; + int32_t y; + + LV_UNUSED(w); + LV_UNUSED(h); + LV_UNUSED(x); + LV_UNUSED(y); + LV_UNUSED(opa); + LV_UNUSED(mask); + LV_UNUSED(mask_stride); + LV_UNUSED(dest_stride); + + /*Simple fill*/ + if(mask == NULL && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_COLOR_BLEND_TO_RGB888(dsc, dest_px_size)) { + if(dest_px_size == 3) { + uint8_t * dest_buf_u8 = dsc->dest_buf; + uint8_t * dest_buf_ori = dsc->dest_buf; + w *= dest_px_size; + + for(x = 0; x < w; x += 3) { + dest_buf_u8[x + 0] = dsc->color.blue; + dest_buf_u8[x + 1] = dsc->color.green; + dest_buf_u8[x + 2] = dsc->color.red; + } + + dest_buf_u8 += dest_stride; + + for(y = 1; y < h; y++) { + lv_memcpy(dest_buf_u8, dest_buf_ori, w); + dest_buf_u8 += dest_stride; + } + } + if(dest_px_size == 4) { + uint32_t color32 = lv_color_to_u32(dsc->color); + uint32_t * dest_buf_u32 = dsc->dest_buf; + for(y = 0; y < h; y++) { + for(x = 0; x <= w - 16; x += 16) { + dest_buf_u32[x + 0] = color32; + dest_buf_u32[x + 1] = color32; + dest_buf_u32[x + 2] = color32; + dest_buf_u32[x + 3] = color32; + + dest_buf_u32[x + 4] = color32; + dest_buf_u32[x + 5] = color32; + dest_buf_u32[x + 6] = color32; + dest_buf_u32[x + 7] = color32; + + dest_buf_u32[x + 8] = color32; + dest_buf_u32[x + 9] = color32; + dest_buf_u32[x + 10] = color32; + dest_buf_u32[x + 11] = color32; + + dest_buf_u32[x + 12] = color32; + dest_buf_u32[x + 13] = color32; + dest_buf_u32[x + 14] = color32; + dest_buf_u32[x + 15] = color32; + } + for(; x < w; x ++) { + dest_buf_u32[x] = color32; + } + + dest_buf_u32 = drawbuf_next_row(dest_buf_u32, dest_stride); + } + } + } + } + /*Opacity only*/ + else if(mask == NULL && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_OPA(dsc, dest_px_size)) { + uint32_t color32 = lv_color_to_u32(dsc->color); + uint8_t * dest_buf = dsc->dest_buf; + w *= dest_px_size; + for(y = 0; y < h; y++) { + for(x = 0; x < w; x += dest_px_size) { + lv_color_24_24_mix((const uint8_t *)&color32, &dest_buf[x], opa); + } + + dest_buf = drawbuf_next_row(dest_buf, dest_stride); + } + } + } + /*Masked with full opacity*/ + else if(mask && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_MASK(dsc, dest_px_size)) { + uint32_t color32 = lv_color_to_u32(dsc->color); + uint8_t * dest_buf = dsc->dest_buf; + w *= dest_px_size; + + for(y = 0; y < h; y++) { + uint32_t mask_x; + for(x = 0, mask_x = 0; x < w; x += dest_px_size, mask_x++) { + lv_color_24_24_mix((const uint8_t *)&color32, &dest_buf[x], mask[mask_x]); + } + dest_buf += dest_stride; + mask += mask_stride; + } + } + } + /*Masked with opacity*/ + else { + if(LV_RESULT_INVALID == LV_DRAW_SW_COLOR_BLEND_TO_RGB888_MIX_MASK_OPA(dsc, dest_px_size)) { + uint32_t color32 = lv_color_to_u32(dsc->color); + uint8_t * dest_buf = dsc->dest_buf; + w *= dest_px_size; + + for(y = 0; y < h; y++) { + uint32_t mask_x; + for(x = 0, mask_x = 0; x < w; x += dest_px_size, mask_x++) { + lv_color_24_24_mix((const uint8_t *) &color32, &dest_buf[x], LV_OPA_MIX2(opa, mask[mask_x])); + } + dest_buf += dest_stride; + mask += mask_stride; + } + } + } +} + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_image_to_rgb888(_lv_draw_sw_blend_image_dsc_t * dsc, uint32_t dest_px_size) +{ + + switch(dsc->src_color_format) { + case LV_COLOR_FORMAT_RGB565: + rgb565_image_blend(dsc, dest_px_size); + break; + case LV_COLOR_FORMAT_RGB888: + rgb888_image_blend(dsc, dest_px_size, 3); + break; + case LV_COLOR_FORMAT_XRGB8888: + rgb888_image_blend(dsc, dest_px_size, 4); + break; + case LV_COLOR_FORMAT_ARGB8888: + argb8888_image_blend(dsc, dest_px_size); + break; + default: + LV_LOG_WARN("Not supported source color format"); + break; + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +LV_ATTRIBUTE_FAST_MEM static void rgb565_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc, uint32_t dest_px_size) +{ + int32_t w = dsc->dest_w; + int32_t h = dsc->dest_h; + lv_opa_t opa = dsc->opa; + uint8_t * dest_buf_u8 = dsc->dest_buf; + int32_t dest_stride = dsc->dest_stride; + const lv_color16_t * src_buf_c16 = (const lv_color16_t *) dsc->src_buf; + int32_t src_stride = dsc->src_stride; + const lv_opa_t * mask_buf = dsc->mask_buf; + int32_t mask_stride = dsc->mask_stride; + + int32_t src_x; + int32_t dest_x; + int32_t y; + + if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { + if(mask_buf == NULL && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888(dsc, dest_px_size)) { + for(y = 0; y < h; y++) { + for(src_x = 0, dest_x = 0; src_x < w; dest_x += dest_px_size, src_x++) { + dest_buf_u8[dest_x + 2] = (src_buf_c16[src_x].red * 2106) >> 8; /*To make it rounded*/ + dest_buf_u8[dest_x + 1] = (src_buf_c16[src_x].green * 1037) >> 8; + dest_buf_u8[dest_x + 0] = (src_buf_c16[src_x].blue * 2106) >> 8; + } + dest_buf_u8 += dest_stride; + src_buf_c16 = drawbuf_next_row(src_buf_c16, src_stride); + } + } + } + else if(mask_buf == NULL && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_OPA(dsc, dest_px_size)) { + uint8_t res[3]; + for(y = 0; y < h; y++) { + for(src_x = 0, dest_x = 0; src_x < w; dest_x += dest_px_size, src_x++) { + res[2] = (src_buf_c16[src_x].red * 2106) >> 8; /*To make it rounded*/ + res[1] = (src_buf_c16[src_x].green * 1037) >> 8; + res[0] = (src_buf_c16[src_x].blue * 2106) >> 8; + lv_color_24_24_mix(res, &dest_buf_u8[dest_x], opa); + } + dest_buf_u8 += dest_stride; + src_buf_c16 = drawbuf_next_row(src_buf_c16, src_stride); + } + } + } + else if(mask_buf && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_MASK(dsc, dest_px_size)) { + uint8_t res[3]; + for(y = 0; y < h; y++) { + for(src_x = 0, dest_x = 0; src_x < w; dest_x += dest_px_size, src_x++) { + res[2] = (src_buf_c16[src_x].red * 2106) >> 8; /*To make it rounded*/ + res[1] = (src_buf_c16[src_x].green * 1037) >> 8; + res[0] = (src_buf_c16[src_x].blue * 2106) >> 8; + lv_color_24_24_mix(res, &dest_buf_u8[dest_x], mask_buf[src_x]); + } + dest_buf_u8 += dest_stride; + src_buf_c16 = drawbuf_next_row(src_buf_c16, src_stride); + mask_buf += mask_stride; + } + } + } + else { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA(dsc, dest_px_size)) { + uint8_t res[3]; + for(y = 0; y < h; y++) { + for(src_x = 0, dest_x = 0; src_x < w; dest_x += dest_px_size, src_x++) { + res[2] = (src_buf_c16[src_x].red * 2106) >> 8; /*To make it rounded*/ + res[1] = (src_buf_c16[src_x].green * 1037) >> 8; + res[0] = (src_buf_c16[src_x].blue * 2106) >> 8; + lv_color_24_24_mix(res, &dest_buf_u8[dest_x], LV_OPA_MIX2(opa, mask_buf[src_x])); + } + dest_buf_u8 += dest_stride; + src_buf_c16 = drawbuf_next_row(src_buf_c16, src_stride); + mask_buf += mask_stride; + } + } + } + } + else { + lv_color32_t src_argb; + for(y = 0; y < h; y++) { + for(src_x = 0, dest_x = 0; src_x < w; src_x++, dest_x += dest_px_size) { + src_argb.red = (src_buf_c16[src_x].red * 2106) >> 8; + src_argb.green = (src_buf_c16[src_x].green * 1037) >> 8; + src_argb.blue = (src_buf_c16[src_x].blue * 2106) >> 8; + if(mask_buf == NULL) src_argb.alpha = opa; + else src_argb.alpha = LV_OPA_MIX2(mask_buf[src_x], opa); + blend_non_normal_pixel(&dest_buf_u8[dest_x], src_argb, dsc->blend_mode); + } + if(mask_buf) mask_buf += mask_stride; + dest_buf_u8 += dest_stride; + src_buf_c16 = drawbuf_next_row(src_buf_c16, src_stride); + } + } +} + +LV_ATTRIBUTE_FAST_MEM static void rgb888_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc, const uint8_t dest_px_size, + uint32_t src_px_size) +{ + int32_t w = dsc->dest_w * dest_px_size; + int32_t h = dsc->dest_h; + lv_opa_t opa = dsc->opa; + uint8_t * dest_buf = dsc->dest_buf; + int32_t dest_stride = dsc->dest_stride; + const uint8_t * src_buf = dsc->src_buf; + int32_t src_stride = dsc->src_stride; + const lv_opa_t * mask_buf = dsc->mask_buf; + int32_t mask_stride = dsc->mask_stride; + + int32_t dest_x; + int32_t src_x; + int32_t y; + + if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { + /*Special case*/ + if(mask_buf == NULL && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888(dsc, dest_px_size, src_px_size)) { + if(src_px_size == dest_px_size) { + for(y = 0; y < h; y++) { + lv_memcpy(dest_buf, src_buf, w); + dest_buf += dest_stride; + src_buf += src_stride; + } + } + else { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x += dest_px_size, src_x += src_px_size) { + dest_buf[dest_x + 0] = src_buf[src_x + 0]; + dest_buf[dest_x + 1] = src_buf[src_x + 1]; + dest_buf[dest_x + 2] = src_buf[src_x + 2]; + } + dest_buf += dest_stride; + src_buf += src_stride; + } + } + } + } + if(mask_buf == NULL && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_OPA(dsc, dest_px_size, src_px_size)) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x += dest_px_size, src_x += src_px_size) { + lv_color_24_24_mix(&src_buf[src_x], &dest_buf[dest_x], opa); + } + dest_buf += dest_stride; + src_buf += src_stride; + } + } + } + if(mask_buf && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_MASK(dsc, dest_px_size, src_px_size)) { + uint32_t mask_x; + for(y = 0; y < h; y++) { + for(mask_x = 0, dest_x = 0, src_x = 0; dest_x < w; mask_x++, dest_x += dest_px_size, src_x += src_px_size) { + lv_color_24_24_mix(&src_buf[src_x], &dest_buf[dest_x], mask_buf[mask_x]); + } + dest_buf += dest_stride; + src_buf += src_stride; + mask_buf += mask_stride; + } + } + } + if(mask_buf && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA(dsc, dest_px_size, src_px_size)) { + uint32_t mask_x; + for(y = 0; y < h; y++) { + for(mask_x = 0, dest_x = 0, src_x = 0; dest_x < w; mask_x++, dest_x += dest_px_size, src_x += src_px_size) { + lv_color_24_24_mix(&src_buf[src_x], &dest_buf[dest_x], LV_OPA_MIX2(opa, mask_buf[mask_x])); + } + dest_buf += dest_stride; + src_buf += src_stride; + mask_buf += mask_stride; + } + } + } + } + else { + lv_color32_t src_argb; + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; dest_x < w; dest_x += dest_px_size, src_x += src_px_size) { + src_argb.red = src_buf[src_x + 2]; + src_argb.green = src_buf[src_x + 1]; + src_argb.blue = src_buf[src_x + 0]; + if(mask_buf == NULL) src_argb.alpha = opa; + else src_argb.alpha = LV_OPA_MIX2(mask_buf[dest_x], opa); + + blend_non_normal_pixel(&dest_buf[dest_x], src_argb, dsc->blend_mode); + } + if(mask_buf) mask_buf += mask_stride; + dest_buf += dest_stride; + src_buf += src_stride; + } + } +} + +LV_ATTRIBUTE_FAST_MEM static void argb8888_image_blend(_lv_draw_sw_blend_image_dsc_t * dsc, uint32_t dest_px_size) +{ + int32_t w = dsc->dest_w; + int32_t h = dsc->dest_h; + lv_opa_t opa = dsc->opa; + uint8_t * dest_buf = dsc->dest_buf; + int32_t dest_stride = dsc->dest_stride; + const lv_color32_t * src_buf_c32 = dsc->src_buf; + int32_t src_stride = dsc->src_stride; + const lv_opa_t * mask_buf = dsc->mask_buf; + int32_t mask_stride = dsc->mask_stride; + + int32_t dest_x; + int32_t src_x; + int32_t y; + + if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { + if(mask_buf == NULL && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888(dsc, dest_px_size)) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; src_x < w; dest_x += dest_px_size, src_x++) { + lv_color_24_24_mix((const uint8_t *)&src_buf_c32[src_x], &dest_buf[dest_x], src_buf_c32[src_x].alpha); + } + dest_buf += dest_stride; + src_buf_c32 = drawbuf_next_row(src_buf_c32, src_stride); + } + } + } + else if(mask_buf == NULL && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_OPA(dsc, dest_px_size)) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; src_x < w; dest_x += dest_px_size, src_x++) { + lv_color_24_24_mix((const uint8_t *)&src_buf_c32[src_x], &dest_buf[dest_x], LV_OPA_MIX2(src_buf_c32[src_x].alpha, opa)); + } + dest_buf += dest_stride; + src_buf_c32 = drawbuf_next_row(src_buf_c32, src_stride); + } + } + } + else if(mask_buf && opa >= LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_MASK(dsc, dest_px_size)) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; src_x < w; dest_x += dest_px_size, src_x++) { + lv_color_24_24_mix((const uint8_t *)&src_buf_c32[src_x], &dest_buf[dest_x], + LV_OPA_MIX2(src_buf_c32[src_x].alpha, mask_buf[src_x])); + } + dest_buf += dest_stride; + src_buf_c32 = drawbuf_next_row(src_buf_c32, src_stride); + mask_buf += mask_stride; + } + } + } + else if(mask_buf && opa < LV_OPA_MAX) { + if(LV_RESULT_INVALID == LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA(dsc, dest_px_size)) { + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; src_x < w; dest_x += dest_px_size, src_x++) { + lv_color_24_24_mix((const uint8_t *)&src_buf_c32[src_x], &dest_buf[dest_x], + LV_OPA_MIX3(src_buf_c32[src_x].alpha, mask_buf[src_x], opa)); + } + dest_buf += dest_stride; + src_buf_c32 = drawbuf_next_row(src_buf_c32, src_stride); + mask_buf += mask_stride; + } + } + } + } + else { + lv_color32_t src_argb; + for(y = 0; y < h; y++) { + for(dest_x = 0, src_x = 0; src_x < w; dest_x += dest_px_size, src_x ++) { + src_argb = src_buf_c32[src_x]; + if(mask_buf == NULL) src_argb.alpha = LV_OPA_MIX2(src_argb.alpha, opa); + else src_argb.alpha = LV_OPA_MIX3(src_argb.alpha, mask_buf[dest_x], opa); + + blend_non_normal_pixel(&dest_buf[dest_x], src_argb, dsc->blend_mode); + } + if(mask_buf) mask_buf += mask_stride; + dest_buf += dest_stride; + src_buf_c32 = drawbuf_next_row(src_buf_c32, src_stride); + } + } +} + +LV_ATTRIBUTE_FAST_MEM static inline void blend_non_normal_pixel(uint8_t * dest, lv_color32_t src, lv_blend_mode_t mode) +{ + uint8_t res[3] = {0, 0, 0}; + switch(mode) { + case LV_BLEND_MODE_ADDITIVE: + res[0] = LV_MIN(dest[0] + src.blue, 255); + res[1] = LV_MIN(dest[1] + src.green, 255); + res[2] = LV_MIN(dest[2] + src.red, 255); + break; + case LV_BLEND_MODE_SUBTRACTIVE: + res[0] = LV_MAX(dest[0] - src.blue, 0); + res[1] = LV_MAX(dest[1] - src.green, 0); + res[2] = LV_MAX(dest[2] - src.red, 0); + break; + case LV_BLEND_MODE_MULTIPLY: + res[0] = (dest[0] * src.blue) >> 8; + res[1] = (dest[1] * src.green) >> 8; + res[2] = (dest[2] * src.red) >> 8; + break; + default: + LV_LOG_WARN("Not supported blend mode: %d", mode); + return; + } + lv_color_24_24_mix(res, dest, src.alpha); +} + +LV_ATTRIBUTE_FAST_MEM static inline void lv_color_24_24_mix(const uint8_t * src, uint8_t * dest, uint8_t mix) +{ + + if(mix == 0) return; + + if(mix >= LV_OPA_MAX) { + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + } + else { + lv_opa_t mix_inv = 255 - mix; + dest[0] = (uint32_t)((uint32_t)src[0] * mix + dest[0] * mix_inv) >> 8; + dest[1] = (uint32_t)((uint32_t)src[1] * mix + dest[1] * mix_inv) >> 8; + dest[2] = (uint32_t)((uint32_t)src[2] * mix + dest[2] * mix_inv) >> 8; + } +} + +LV_ATTRIBUTE_FAST_MEM static inline void * drawbuf_next_row(const void * buf, uint32_t stride) +{ + return (void *)((uint8_t *)buf + stride); +} + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb888.h b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb888.h new file mode 100644 index 000000000..9e46ef210 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/lv_draw_sw_blend_to_rgb888.h @@ -0,0 +1,45 @@ +/** + * @file lv_draw_sw_blend_rgb888.h + * + */ + +#ifndef LV_DRAW_SW_BLEND_RGB888_H +#define LV_DRAW_SW_BLEND_RGB888_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_draw_sw.h" +#if LV_USE_DRAW_SW + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_color_to_rgb888(_lv_draw_sw_blend_fill_dsc_t * dsc, uint32_t dest_px_size); + +LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_image_to_rgb888(_lv_draw_sw_blend_image_dsc_t * dsc, uint32_t dest_px_size); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DRAW_SW*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SW_BLEND_RGB888_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/neon/lv_blend_neon.S b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/neon/lv_blend_neon.S new file mode 100644 index 000000000..ff3cc113f --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/neon/lv_blend_neon.S @@ -0,0 +1,684 @@ +/** + * @file lv_blend_to_neon.S + * + */ + +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#endif + +#include "lv_blend_neon.h" + +#if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_NEON + +.text +.fpu neon +.arch armv7a +.syntax unified +.altmacro +.p2align 2 + +@ d0 ~ d3 : src B,G,R,A +@ d4 ~ d7 : dst B,G,R,A +@ q8 : src RGB565 raw +@ q9 : dst RGB565 raw +@ q10 ~ q12: pre-multiplied src +@ d26~29 : temp +@ d30 : mask +@ d31 : opa + +FG_MASK .req r0 +BG_MASK .req r1 +DST_ADDR .req r2 +DST_W .req r3 +DST_H .req r4 +DST_STRIDE .req r5 +SRC_ADDR .req r6 +SRC_STRIDE .req r7 +MASK_ADDR .req r8 +MASK_STRIDE .req r9 +W .req r10 +H .req r11 +S_8888_L .qn q0 +S_8888_H .qn q1 +D_8888_L .qn q2 +D_8888_H .qn q3 + S_B .dn d0 + S_G .dn d1 + S_R .dn d2 + S_A .dn d3 + D_B .dn d4 + D_G .dn d5 + D_R .dn d6 + D_A .dn d7 +S_565 .qn q8 +D_565 .qn q9 + S_565_L .dn d16 + S_565_H .dn d17 + D_565_L .dn d18 + D_565_H .dn d19 +PREMULT_B .qn q10 +PREMULT_G .qn q11 +PREMULT_R .qn q12 +TMP_Q0 .qn q13 + TMP_D0 .dn d26 + TMP_D1 .dn d27 +TMP_Q1 .qn q14 + TMP_D2 .dn d28 + TMP_D3 .dn d29 + M_A .dn d30 + OPA .dn d31 + +.macro convert reg, bpp, intlv +.if bpp >= 31 + .if intlv + vzip.8 reg&_B, reg&_R @ BRBRBRBR GGGGGGGG BRBRBRBR AAAAAAAA + vzip.8 reg&_G, reg&_A @ BRBRBRBR GAGAGAGA BRBRBRBR GAGAGAGA + vzip.8 reg&_R, reg&_A @ BRBRBRBR GAGAGAGA BGRABGRA BGRABGRA + vzip.8 reg&_B, reg&_G @ BGRABGRA BGRABGRA BGRABGRA BGRABGRA + .else + vuzp.8 reg&_B, reg&_G @ BRBRBRBR GAGAGAGA BGRABGRA BGRABGRA + vuzp.8 reg&_R, reg&_A @ BRBRBRBR GAGAGAGA BRBRBRBR GAGAGAGA + vuzp.8 reg&_G, reg&_A @ BRBRBRBR GGGGGGGG BRBRBRBR AAAAAAAA + vuzp.8 reg&_B, reg&_R @ BBBBBBBB GGGGGGGG RRRRRRRR AAAAAAAA + .endif +.elseif bpp == 24 + .if intlv @ for init only (same B,G,R for all channel) + vzip.8 reg&_B, reg&_G @ BGBGBGBG BGBGBGBG RRRRRRRR + vzip.16 reg&_B, reg&_R @ BGRRBGRR BGBGBGBG BGRRBGRR + vsli.64 reg&_8888_L, reg&_8888_L, #24 @ BGRBGRRB BGBBGBGB + vsli.64 reg&_B, reg&_G, #48 @ BGRBGRBG + vsri.64 reg&_R, reg&_B, #8 @ GRBGRBGR + vsri.64 reg&_G, reg&_R, #8 @ RBGRBGRB + .endif +.elseif bpp == 16 + .if intlv + vshll.u8 reg&_565, reg&_R, #8 @ RRRrrRRR 00000000 + vshll.u8 TMP_Q0, reg&_G, #8 @ GGGgggGG 00000000 + vshll.u8 TMP_Q1, reg&_B, #8 @ BBBbbBBB 00000000 + vsri.16 reg&_565, TMP_Q0, #5 @ RRRrrGGG gggGG000 + vsri.16 reg&_565, TMP_Q1, #11 @ RRRrrGGG gggBBBbb + .else + vshr.u8 TMP_Q0, reg&_565, #3 @ 000RRRrr 000gggBB + vshrn.i16 reg&_G, reg&_565, #5 @ rrGGGggg + vshrn.i16 reg&_R, TMP_Q0, #5 @ RRRrr000 + vshl.i8 reg&_G, reg&_G, #2 @ GGGggg00 + vshl.i16 TMP_Q1, reg&_565, #3 @ rrGGGggg BBBbb000 + vsri.8 reg&_R, reg&_R, #5 @ RRRrrRRR + vmovn.i16 reg&_B, TMP_Q1 @ BBBbb000 + vsri.8 reg&_G, reg&_G, #6 @ GGGgggGG + vsri.8 reg&_B, reg&_B, #5 @ BBBbbBBB + .endif +.endif +.endm + +.macro ldst op, bpp, len, mem, reg, cvt, wb +.if bpp >= 31 + .if len == 8 + .if cvt + v&op&4.8 {reg&_B, reg&_G, reg&_R, reg&_A}, [mem&_ADDR]&wb + .else + v&op&1.32 {reg&_8888_L, reg&_8888_H}, [mem&_ADDR]&wb + .endif + .else + .if (op == st) && cvt + convert reg, bpp, 1 + .endif + .if len == 7 + v&op&1.32 {reg&_8888_L}, [mem&_ADDR]! + v&op&1.32 {reg&_R}, [mem&_ADDR]! + v&op&1.32 {reg&_A[0]}, [mem&_ADDR]! + .elseif len == 6 + v&op&1.32 {reg&_8888_L}, [mem&_ADDR]! + v&op&1.32 {reg&_R}, [mem&_ADDR]! + .elseif len == 5 + v&op&1.32 {reg&_8888_L}, [mem&_ADDR]! + v&op&1.32 {reg&_R[0]}, [mem&_ADDR]! + .elseif len == 4 + v&op&1.32 {reg&_8888_L}, [mem&_ADDR]&wb + .elseif len == 3 + v&op&1.32 {reg&_B}, [mem&_ADDR]! + v&op&1.32 {reg&_G[0]}, [mem&_ADDR]! + .elseif len == 2 + v&op&1.32 {reg&_B}, [mem&_ADDR]&wb + .elseif len == 1 + v&op&1.32 {reg&_B[0]}, [mem&_ADDR]&wb + .else + .error "[32bpp]len should be 1~8" + .endif + .if (op == ld) && cvt + convert reg, bpp, 0 + .endif + .if (wb&1) && (len != 4) && (len != 2) && (len != 1) + sub mem&_ADDR, #4*len + .endif + .endif +.elseif bpp == 24 + .if len == 8 + .if cvt + v&op&3.8 {reg&_B, reg&_G, reg&_R}, [mem&_ADDR]&wb + .else + v&op&1.8 {reg&_B, reg&_G, reg&_R}, [mem&_ADDR]&wb + .endif + .elseif (len < 8) && (len > 0) + .if cvt + v&op&3.8 {reg&_B[0], reg&_G[0], reg&_R[0]}, [mem&_ADDR]! + .if len > 1 + v&op&3.8 {reg&_B[1], reg&_G[1], reg&_R[1]}, [mem&_ADDR]! + .endif + .if len > 2 + v&op&3.8 {reg&_B[2], reg&_G[2], reg&_R[2]}, [mem&_ADDR]! + .endif + .if len > 3 + v&op&3.8 {reg&_B[3], reg&_G[3], reg&_R[3]}, [mem&_ADDR]! + .endif + .if len > 4 + v&op&3.8 {reg&_B[4], reg&_G[4], reg&_R[4]}, [mem&_ADDR]! + .endif + .if len > 5 + v&op&3.8 {reg&_B[5], reg&_G[5], reg&_R[5]}, [mem&_ADDR]! + .endif + .if len > 6 + v&op&3.8 {reg&_B[6], reg&_G[6], reg&_R[6]}, [mem&_ADDR]! + .endif + .if wb&1 + sub mem&_ADDR, #3*len + .endif + .else + .if len == 7 + v&op&1.32 {reg&_8888_L}, [mem&_ADDR]! + v&op&1.32 {reg&_R[0]}, [mem&_ADDR]! + v&op&1.8 {reg&_R[4]}, [mem&_ADDR]! + .elseif len == 6 + v&op&1.32 {reg&_8888_L}, [mem&_ADDR]! + v&op&1.16 {reg&_R[0]}, [mem&_ADDR]! + .elseif len == 5 + v&op&1.32 {reg&_B}, [mem&_ADDR]! + v&op&1.32 {reg&_G[0]}, [mem&_ADDR]! + v&op&1.16 {reg&_G[2]}, [mem&_ADDR]! + v&op&1.8 {reg&_G[6]}, [mem&_ADDR]! + .elseif len == 4 + v&op&1.32 {reg&_B}, [mem&_ADDR]! + v&op&1.32 {reg&_G[0]}, [mem&_ADDR]! + .elseif len == 3 + v&op&1.32 {reg&_B}, [mem&_ADDR]! + v&op&1.8 {reg&_G[0]}, [mem&_ADDR]! + .elseif len == 2 + v&op&1.32 {reg&_B[0]}, [mem&_ADDR]! + v&op&1.16 {reg&_B[2]}, [mem&_ADDR]! + .elseif len == 1 + v&op&1.16 {reg&_B[0]}, [mem&_ADDR]! + v&op&1.8 {reg&_B[2]}, [mem&_ADDR]! + .endif + .if wb&1 + sub mem&_ADDR, #3*len + .endif + .endif + .else + .error "[24bpp]len should be 1~8" + .endif +.elseif bpp == 16 + .if (op == st) && cvt + convert reg, bpp, 1 + .endif + .if len == 8 + v&op&1.16 {reg&_565}, [mem&_ADDR]&wb + .elseif len == 7 + v&op&1.16 {reg&_565_L}, [mem&_ADDR]! + v&op&1.32 {reg&_565_H[0]}, [mem&_ADDR]! + v&op&1.16 {reg&_565_H[2]}, [mem&_ADDR]! + .if wb&1 + sub mem&_ADDR, #14 + .endif + .elseif len == 6 + v&op&1.16 {reg&_565_L}, [mem&_ADDR]! + v&op&1.32 {reg&_565_H[0]}, [mem&_ADDR]! + .if wb&1 + sub mem&_ADDR, #12 + .endif + .elseif len == 5 + v&op&1.16 {reg&_565_L}, [mem&_ADDR]! + v&op&1.16 {reg&_565_H[0]}, [mem&_ADDR]! + .if wb&1 + sub mem&_ADDR, #10 + .endif + .elseif len == 4 + v&op&1.16 {reg&_565_L}, [mem&_ADDR]&wb + .elseif len == 3 + v&op&1.32 {reg&_565_L[0]}, [mem&_ADDR]! + v&op&1.16 {reg&_565_L[2]}, [mem&_ADDR]! + .if wb&1 + sub mem&_ADDR, #6 + .endif + .elseif len == 2 + v&op&1.32 {reg&_565_L[0]}, [mem&_ADDR]&wb + .elseif len == 1 + v&op&1.16 {reg&_565_L[0]}, [mem&_ADDR]&wb + .else + .error "[16bpp]len should be 1~8" + .endif + .if (op == ld) && cvt + convert reg, bpp, 0 + .endif +.elseif bpp == 8 + .if len == 8 + v&op&1.8 {reg&_A}, [mem&_ADDR]&wb + .elseif len == 7 + v&op&1.32 {reg&_A[0]}, [mem&_ADDR]! + v&op&1.16 {reg&_A[2]}, [mem&_ADDR]! + v&op&1.8 {reg&_A[6]}, [mem&_ADDR]! + .if wb&1 + sub mem&_ADDR, #7 + .endif + .elseif len == 6 + v&op&1.32 {reg&_A[0]}, [mem&_ADDR]! + v&op&1.16 {reg&_A[2]}, [mem&_ADDR]! + .if wb&1 + sub mem&_ADDR, #6 + .endif + .elseif len == 5 + v&op&1.32 {reg&_A[0]}, [mem&_ADDR]! + v&op&1.8 {reg&_A[4]}, [mem&_ADDR]! + .if wb&1 + sub mem&_ADDR, #5 + .endif + .elseif len == 4 + v&op&1.32 {reg&_A[0]}, [mem&_ADDR]&wb + .elseif len == 3 + v&op&1.16 {reg&_A[0]}, [mem&_ADDR]! + v&op&1.8 {reg&_A[2]}, [mem&_ADDR]! + .if wb&1 + sub mem&_ADDR, #3 + .endif + .elseif len == 2 + v&op&1.16 {reg&_A[0]}, [mem&_ADDR]&wb + .elseif len == 1 + v&op&1.8 {reg&_A[0]}, [mem&_ADDR]&wb + .else + .error "[8bpp]len should be 1~8" + .endif +.elseif (bpp == 0) && wb&1 + .if len == 8 + v&op&3.8 {reg&_B[], reg&_G[], reg&_R[]}, [mem&_ADDR] + .else + .error "[color]len should be 8" + .endif +.endif +.if (op == ld) && cvt && (bpp > 8) && (bpp < 32) + vmov.u8 reg&_A, #0xFF +.endif +.endm + +.macro premult alpha + vmull.u8 PREMULT_B, S_B, alpha + vmull.u8 PREMULT_G, S_G, alpha + vmull.u8 PREMULT_R, S_R, alpha +.endm + +.macro init src_bpp, dst_bpp, mask, opa + ldr DST_ADDR, [r0, #4] + ldr DST_W, [r0, #8] + ldr DST_H, [r0, #12] + ldr DST_STRIDE, [r0, #16] + ldr SRC_ADDR, [r0, #20] +.if src_bpp > 0 + ldr SRC_STRIDE, [r0, #24] +.endif +.if mask + ldr MASK_ADDR, [r0, #28] + ldr MASK_STRIDE, [r0, #32] + sub MASK_STRIDE, MASK_STRIDE, DST_W +.endif +.if opa + vld1.8 {OPA[]}, [r0] +.else + vmov.u8 OPA, #0xFF +.endif + + sub DST_STRIDE, DST_STRIDE, DST_W + vmvn D_A, OPA +.if dst_bpp == 16 + lsl DST_STRIDE, DST_STRIDE, #1 +.elseif dst_bpp == 24 + add DST_STRIDE, DST_STRIDE, DST_STRIDE, lsl #1 +.elseif dst_bpp >= 31 + lsl DST_STRIDE, DST_STRIDE, #2 +.endif +.if src_bpp == 0 + .if mask || opa + ldst ld, src_bpp, 8, SRC, S, 1 + vmov.u8 S_A, #0xFF + premult OPA + .else + ldst ld, src_bpp, 8, SRC, D, 1 + vmov.u8 D_A, #0xFF + convert D, dst_bpp, 1 + .endif +.else + sub SRC_STRIDE, SRC_STRIDE, DST_W + .if src_bpp == 16 + lsl SRC_STRIDE, SRC_STRIDE, #1 + .elseif src_bpp == 24 + add SRC_STRIDE, SRC_STRIDE, SRC_STRIDE, lsl #1 + .elseif src_bpp >= 31 + lsl SRC_STRIDE, SRC_STRIDE, #2 + .endif +.endif + mvn FG_MASK, #0 + mvn BG_MASK, #0 +.endm + +@ input: M_A = 255 - fg.alpha +.macro calc_alpha len + vmov.u8 TMP_D0, #0xFD + vmvn D_A, D_A + vcge.u8 TMP_D1, S_A, TMP_D0 @ if (fg.alpha >= LV_OPA_MAX + vcge.u8 TMP_D2, D_A, TMP_D0 @ || bg.alpha <= LV_OPA_MIN) + vorr TMP_D2, TMP_D1 + vcge.u8 TMP_D3, M_A, TMP_D0 @ elseif (fg.alpha <= LV_OPA_MIN) + vmvn TMP_Q1, TMP_Q1 + vshrn.i16 TMP_D0, TMP_Q1, #4 + vmov FG_MASK, BG_MASK, TMP_D0 + cbz FG_MASK, 99f @ return fg; + vmull.u8 TMP_Q0, M_A, D_A @ D_A = 255 - LV_OPA_MIX2(255 - fg.alpha, 255 - bg.alpha) + vqrshrn.u16 M_A, TMP_Q0, #8 + vbif M_A, D_A, TMP_D3 @ insert original D_A when fg.alpha <= LV_OPA_MIN + vmvn D_A, M_A + cbz BG_MASK, 99f @ return bg; + vmov.u8 TMP_D2, #0xFF + vmovl.u8 TMP_Q0, D_A + .if len > 4 + vmovl.u16 S_565, TMP_D1 + .endif + vmovl.u16 TMP_Q0, TMP_D0 + vmull.u8 TMP_Q1, S_A, TMP_D2 + vcvt.f32.u32 TMP_Q0, TMP_Q0 + .if len > 4 + vmovl.u16 D_565, TMP_D3 + vcvt.f32.u32 S_565, S_565 + .endif + vmovl.u16 TMP_Q1, TMP_D2 + vrecpe.f32 TMP_Q0, TMP_Q0 + vcvt.f32.u32 TMP_Q1, TMP_Q1 + .if len > 4 + vcvt.f32.u32 D_565, D_565 + vrecpe.f32 S_565, S_565 + .endif + vmul.f32 TMP_Q0, TMP_Q0, TMP_Q1 + .if len > 4 + vmul.f32 S_565, S_565, D_565 + .endif + vcvt.u32.f32 TMP_Q0, TMP_Q0 + .if len > 4 + vcvt.u32.f32 S_565, S_565 + .endif + vmovn.u32 TMP_D0, TMP_Q0 + .if len > 4 + vmovn.u32 TMP_D1, S_565 + .endif + vmovn.u16 TMP_D0, TMP_Q0 + premult TMP_D0 + vmvn M_A, TMP_D0 +99: +.endm + +.macro blend mode, dst_bpp +.if dst_bpp == 32 + vmov TMP_D0, FG_MASK, BG_MASK + vmovl.s8 TMP_Q0, TMP_D0 + vsli.8 TMP_Q0, TMP_Q0, #4 + cbz FG_MASK, 98f +.endif +.if mode == normal +.if dst_bpp == 32 + cbz BG_MASK, 97f + mvns BG_MASK, BG_MASK + beq 96f + vmov S_565_L, D_B + vmov S_565_H, D_G + vmov D_565_L, D_R +.endif +96: + vmlal.u8 PREMULT_B, D_B, M_A + vmlal.u8 PREMULT_G, D_G, M_A + vmlal.u8 PREMULT_R, D_R, M_A + vqrshrn.u16 D_B, PREMULT_B, #8 + vqrshrn.u16 D_G, PREMULT_G, #8 + vqrshrn.u16 D_R, PREMULT_R, #8 +.if dst_bpp == 32 + beq 97f + vbif D_B, S_565_L, TMP_D1 + vbif D_G, S_565_H, TMP_D1 + vbif D_R, D_565_L, TMP_D1 +97: + mvns FG_MASK, FG_MASK + beq 99f +.endif +.else + .error "blend mode is unsupported" +.endif +.if dst_bpp == 32 +98: + vbif D_B, S_B, TMP_D0 + vbif D_G, S_G, TMP_D0 + vbif D_R, S_R, TMP_D0 + vbif D_A, S_A, TMP_D0 +99: +.endif +.endm + +.macro process len, src_bpp, dst_bpp, mask, opa, mode +.if (src_bpp < 32) && (mask == 0) && (opa == 0) +@ no blend + .if src_bpp == 0 || src_bpp == dst_bpp + ldst ld, src_bpp, len, SRC, D, 0, ! + ldst st, dst_bpp, len, DST, D, 0, ! + .else + ldst ld, src_bpp, len, SRC, D, 1, ! + ldst st, dst_bpp, len, DST, D, 1, ! + .endif +.elseif src_bpp < 32 +@ no src_a + .if src_bpp > 0 + ldst ld, src_bpp, len, SRC, S, 1, ! + .endif + ldst ld, dst_bpp, len, DST, D, 1 + .if mask + ldst ld, 8, len, MASK, S, 1, ! + .if opa + vmull.u8 TMP_Q0, S_A, OPA + vqrshrn.u16 S_A, TMP_Q0, #8 + .endif + vmvn M_A, S_A + .if dst_bpp < 32 + premult S_A + .else + calc_alpha len + .endif + .else + vmvn M_A, OPA + .if dst_bpp < 32 + premult OPA + .else + vmov S_A, OPA + calc_alpha len + .endif + .endif + blend mode, dst_bpp + ldst st, dst_bpp, len, DST, D, 1, ! +.else +@ src_a (+mask) (+opa) + ldst ld, src_bpp, len, SRC, S, 1, ! + ldst ld, dst_bpp, len, DST, D, 1 + .if mask == 0 + .if opa + vmull.u8 TMP_Q0, S_A, OPA + vqrshrn.u16 S_A, TMP_Q0, #8 + .endif + .else + ldst ld, 8, len, MASK, M, 1, ! + vmull.u8 TMP_Q0, S_A, M_A + vqrshrn.u16 S_A, TMP_Q0, #8 + .if opa + vmull.u8 TMP_Q0, S_A, OPA + vqrshrn.u16 S_A, TMP_Q0, #8 + .endif + .endif + vmvn M_A, S_A + .if dst_bpp < 32 + premult S_A + .else + calc_alpha len + .endif + blend mode, dst_bpp + ldst st, dst_bpp, len, DST, D, 1, ! +.endif +.endm + +.macro tail src_bpp, dst_bpp, mask, opa, mode + tst DST_W, #4 + beq 3f + tst DST_W, #2 + beq 5f + tst DST_W, #1 + beq 6f + process 7, src_bpp, dst_bpp, mask, opa, mode + b 0f +6: + process 6, src_bpp, dst_bpp, mask, opa, mode + b 0f +5: + tst DST_W, #1 + beq 4f + process 5, src_bpp, dst_bpp, mask, opa, mode + b 0f +4: + process 4, src_bpp, dst_bpp, mask, opa, mode + b 0f +3: + tst DST_W, #2 + beq 1f + tst DST_W, #1 + beq 2f + process 3, src_bpp, dst_bpp, mask, opa, mode + b 0f +2: + process 2, src_bpp, dst_bpp, mask, opa, mode + b 0f +1: + process 1, src_bpp, dst_bpp, mask, opa, mode +0: +.endm + +.macro next src_bpp, mask + add DST_ADDR, DST_ADDR, DST_STRIDE +.if src_bpp + add SRC_ADDR, SRC_ADDR, SRC_STRIDE +.endif +.if mask + add MASK_ADDR, MASK_ADDR, MASK_STRIDE +.endif +.endm + +.macro enter + push {r4-r11, lr} +.endm + +.macro exit + pop {r4-r11, pc} +.endm + +.macro preload mem, bpp +.if bpp >= 31 + pld [mem&_ADDR, DST_W, lsl #2] +.elseif bpp == 24 + add W, DST_W, DST_W, lsl #1 + pld [mem&_ADDR, W] +.elseif bpp == 16 + pld [mem&_ADDR, DST_W, lsl #1] +.elseif bpp == 8 + pld [mem&_ADDR, DST_W] +.endif +.endm + +.macro blender src_bpp, dst_bpp, mask, opa, mode + enter + init src_bpp, dst_bpp, mask, opa + movs H, DST_H + beq 0f + preload SRC, src_bpp +.if mask || opa || (src_bpp == 32) + preload DST, dst_bpp +.endif + subs W, DST_W, #8 + blt 7f +9: + process 8, src_bpp, dst_bpp, mask, opa, mode + subs W, W, #8 + bge 9b + tst DST_W, #7 + beq 8f + tail src_bpp, dst_bpp, mask, opa, mode +8: + next src_bpp, mask + preload SRC, src_bpp +.if mask || opa || (src_bpp == 32) + preload DST, dst_bpp +.endif + sub W, DST_W, #8 + subs H, H, #1 + bgt 9b + exit +7: + tail src_bpp, dst_bpp, mask, opa, mode + next src_bpp, mask + subs H, H, #1 + bgt 7b + exit +.endm + +.macro export name, src_bpp, dst_bpp, mask, opa, mode +.thumb_func +.func name +.global name +name&: + blender src_bpp, dst_bpp, mask, opa, mode +.endfunc +.endm + +.macro export_set src, dst, src_bpp, dst_bpp, mode +.if src == color + export lv_&src&_blend_to_&dst&_neon, src_bpp, dst_bpp, 0, 0, mode + export lv_&src&_blend_to_&dst&_with_opa_neon, src_bpp, dst_bpp, 0, 1, mode + export lv_&src&_blend_to_&dst&_with_mask_neon, src_bpp, dst_bpp, 1, 0, mode + export lv_&src&_blend_to_&dst&_mix_mask_opa_neon, src_bpp, dst_bpp, 1, 1, mode +.else + export lv_&src&_blend_&mode&_to_&dst&_neon, src_bpp, dst_bpp, 0, 0, mode + export lv_&src&_blend_&mode&_to_&dst&_with_opa_neon, src_bpp, dst_bpp, 0, 1, mode + export lv_&src&_blend_&mode&_to_&dst&_with_mask_neon, src_bpp, dst_bpp, 1, 0, mode + export lv_&src&_blend_&mode&_to_&dst&_mix_mask_opa_neon, src_bpp, dst_bpp, 1, 1, mode +.endif +.endm + +export_set color, rgb565, 0, 16, normal +export_set rgb565, rgb565, 16, 16, normal +export_set rgb888, rgb565, 24, 16, normal +export_set xrgb8888, rgb565, 31, 16, normal +export_set argb8888, rgb565, 32, 16, normal +export_set color, rgb888, 0, 24, normal +export_set rgb565, rgb888, 16, 24, normal +export_set rgb888, rgb888, 24, 24, normal +export_set xrgb8888, rgb888, 31, 24, normal +export_set argb8888, rgb888, 32, 24, normal +export_set color, xrgb8888, 0, 31, normal +export_set rgb565, xrgb8888, 16, 31, normal +export_set rgb888, xrgb8888, 24, 31, normal +export_set xrgb8888, xrgb8888, 31, 31, normal +export_set argb8888, xrgb8888, 32, 31, normal +export_set color, argb8888, 0, 32, normal +export_set rgb565, argb8888, 16, 32, normal +export_set rgb888, argb8888, 24, 32, normal +export_set xrgb8888, argb8888, 31, 32, normal +export_set argb8888, argb8888, 32, 32, normal + +#endif /*LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_NEON*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/neon/lv_blend_neon.h b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/neon/lv_blend_neon.h new file mode 100644 index 000000000..fe284ee4a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/blend/neon/lv_blend_neon.h @@ -0,0 +1,1295 @@ +/** + * @file lv_blend_to_neon.h + * + */ + +#ifndef LV_BLEND_TO_NEON_H +#define LV_BLEND_TO_NEON_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../../../lv_conf_internal.h" + +#ifdef LV_DRAW_SW_NEON_CUSTOM_INCLUDE +#include LV_DRAW_SW_NEON_CUSTOM_INCLUDE +#endif + +/********************* + * DEFINES + *********************/ +#if !defined(__ASSEMBLY__) + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565 +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565(dsc) \ + _lv_color_blend_to_rgb565_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_OPA +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_OPA(dsc) \ + _lv_color_blend_to_rgb565_with_opa_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_MASK +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_MASK(dsc) \ + _lv_color_blend_to_rgb565_with_mask_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565_MIX_MASK_OPA +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565_MIX_MASK_OPA(dsc) \ + _lv_color_blend_to_rgb565_mix_mask_opa_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565 +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565(dsc) \ + _lv_rgb565_blend_normal_to_rgb565_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_OPA +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_OPA(dsc) \ + _lv_rgb565_blend_normal_to_rgb565_with_opa_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_MASK +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_MASK(dsc) \ + _lv_rgb565_blend_normal_to_rgb565_with_mask_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(dsc) \ + _lv_rgb565_blend_normal_to_rgb565_mix_mask_opa_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565 +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb565_neon(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_OPA +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_OPA(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb565_with_opa_neon(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_MASK +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_MASK(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb565_with_mask_neon(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb565_mix_mask_opa_neon(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565 +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565(dsc) \ + _lv_argb8888_blend_normal_to_rgb565_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_OPA +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_OPA(dsc) \ + _lv_argb8888_blend_normal_to_rgb565_with_opa_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_MASK +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_MASK(dsc) \ + _lv_argb8888_blend_normal_to_rgb565_with_mask_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(dsc) \ + _lv_argb8888_blend_normal_to_rgb565_mix_mask_opa_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB888 +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB888(dsc, dst_px_size) \ + _lv_color_blend_to_rgb888_neon(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_OPA +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_OPA(dsc, dst_px_size) \ + _lv_color_blend_to_rgb888_with_opa_neon(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_MASK +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_MASK(dsc, dst_px_size) \ + _lv_color_blend_to_rgb888_with_mask_neon(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB888_MIX_MASK_OPA +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB888_MIX_MASK_OPA(dsc, dst_px_size) \ + _lv_color_blend_to_rgb888_mix_mask_opa_neon(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888 +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888(dsc, dst_px_size) \ + _lv_rgb565_blend_normal_to_rgb888_neon(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_OPA +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_OPA(dsc, dst_px_size) \ + _lv_rgb565_blend_normal_to_rgb888_with_opa_neon(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_MASK +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_MASK(dsc, dst_px_size) \ + _lv_rgb565_blend_normal_to_rgb888_with_mask_neon(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA(dsc, dst_px_size) \ + _lv_rgb565_blend_normal_to_rgb888_mix_mask_opa_neon(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888 +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888(dsc, dst_px_size, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb888_neon(dsc, dst_px_size, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_OPA +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_OPA(dsc, dst_px_size, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb888_with_opa_neon(dsc, dst_px_size, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_MASK +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_MASK(dsc, dst_px_size, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb888_with_mask_neon(dsc, dst_px_size, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA(dsc, dst_px_size, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb888_mix_mask_opa_neon(dsc, dst_px_size, src_px_size) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888 +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888(dsc, dst_px_size) \ + _lv_argb8888_blend_normal_to_rgb888_neon(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_OPA +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_OPA(dsc, dst_px_size) \ + _lv_argb8888_blend_normal_to_rgb888_with_opa_neon(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_MASK +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_MASK(dsc, dst_px_size) \ + _lv_argb8888_blend_normal_to_rgb888_with_mask_neon(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_MIX_MASK_OPA(dsc, dst_px_size) \ + _lv_argb8888_blend_normal_to_rgb888_mix_mask_opa_neon(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888 +#define LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888(dsc) \ + _lv_color_blend_to_argb8888_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_WITH_OPA +#define LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_WITH_OPA(dsc) \ + _lv_color_blend_to_argb8888_with_opa_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_WITH_MASK +#define LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_WITH_MASK(dsc) \ + _lv_color_blend_to_argb8888_with_mask_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_MIX_MASK_OPA +#define LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888_MIX_MASK_OPA(dsc) \ + _lv_color_blend_to_argb8888_mix_mask_opa_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888 +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888(dsc) \ + _lv_rgb565_blend_normal_to_argb8888_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_WITH_OPA +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_WITH_OPA(dsc) \ + _lv_rgb565_blend_normal_to_argb8888_with_opa_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_WITH_MASK +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_WITH_MASK(dsc) \ + _lv_rgb565_blend_normal_to_argb8888_with_mask_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA(dsc) \ + _lv_rgb565_blend_normal_to_argb8888_mix_mask_opa_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888 +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_argb8888_neon(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_WITH_OPA +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_WITH_OPA(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_argb8888_with_opa_neon(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_WITH_MASK +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_WITH_MASK(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_argb8888_with_mask_neon(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA(dsc, src_px_size) \ + _lv_rgb888_blend_normal_to_argb8888_mix_mask_opa_neon(dsc, src_px_size) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888 +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888(dsc) \ + _lv_argb8888_blend_normal_to_argb8888_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_WITH_OPA +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_WITH_OPA(dsc) \ + _lv_argb8888_blend_normal_to_argb8888_with_opa_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_WITH_MASK +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_WITH_MASK(dsc) \ + _lv_argb8888_blend_normal_to_argb8888_with_mask_neon(dsc) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_ARGB8888_MIX_MASK_OPA(dsc) \ + _lv_argb8888_blend_normal_to_argb8888_mix_mask_opa_neon(dsc) +#endif + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + uint32_t opa; + void * dst_buf; + uint32_t dst_w; + uint32_t dst_h; + uint32_t dst_stride; + const void * src_buf; + uint32_t src_stride; + const lv_opa_t * mask_buf; + uint32_t mask_stride; +} asm_dsc_t; +/********************** + * GLOBAL PROTOTYPES + **********************/ + +extern void lv_color_blend_to_rgb565_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_color_blend_to_rgb565_neon(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color + }; + + lv_color_blend_to_rgb565_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_color_blend_to_rgb565_with_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_color_blend_to_rgb565_with_opa_neon(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color + }; + lv_color_blend_to_rgb565_with_opa_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_color_blend_to_rgb565_with_mask_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_color_blend_to_rgb565_with_mask_neon(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_color_blend_to_rgb565_with_mask_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_color_blend_to_rgb565_mix_mask_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_color_blend_to_rgb565_mix_mask_opa_neon(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_color_blend_to_rgb565_mix_mask_opa_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_rgb565_blend_normal_to_rgb565_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb565_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + lv_rgb565_blend_normal_to_rgb565_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_rgb565_blend_normal_to_rgb565_with_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb565_with_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + lv_rgb565_blend_normal_to_rgb565_with_opa_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_rgb565_blend_normal_to_rgb565_with_mask_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb565_with_mask_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_rgb565_blend_normal_to_rgb565_with_mask_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_rgb565_blend_normal_to_rgb565_mix_mask_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb565_mix_mask_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_rgb565_blend_normal_to_rgb565_mix_mask_opa_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_rgb888_blend_normal_to_rgb565_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_rgb565_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb565_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_rgb565_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_rgb565_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_rgb888_blend_normal_to_rgb565_with_opa_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_rgb565_with_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb565_with_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_rgb565_with_opa_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_rgb565_with_opa_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_rgb888_blend_normal_to_rgb565_with_mask_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_rgb565_with_mask_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb565_with_mask_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_rgb565_with_mask_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_rgb565_with_mask_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_rgb888_blend_normal_to_rgb565_mix_mask_opa_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_rgb565_mix_mask_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb565_mix_mask_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_rgb565_mix_mask_opa_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_rgb565_mix_mask_opa_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_argb8888_blend_normal_to_rgb565_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb565_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + lv_argb8888_blend_normal_to_rgb565_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_argb8888_blend_normal_to_rgb565_with_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb565_with_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + lv_argb8888_blend_normal_to_rgb565_with_opa_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_argb8888_blend_normal_to_rgb565_with_mask_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb565_with_mask_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_argb8888_blend_normal_to_rgb565_with_mask_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_argb8888_blend_normal_to_rgb565_mix_mask_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb565_mix_mask_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_argb8888_blend_normal_to_rgb565_mix_mask_opa_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_color_blend_to_rgb888_neon(asm_dsc_t * dsc); +extern void lv_color_blend_to_xrgb8888_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_color_blend_to_rgb888_neon(_lv_draw_sw_blend_fill_dsc_t * dsc, uint32_t dst_px_size) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color + }; + if(dst_px_size == 3) { + lv_color_blend_to_rgb888_neon(&asm_dsc); + } + else { + lv_color_blend_to_xrgb8888_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_color_blend_to_rgb888_with_opa_neon(asm_dsc_t * dsc); +extern void lv_color_blend_to_xrgb8888_with_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_color_blend_to_rgb888_with_opa_neon(_lv_draw_sw_blend_fill_dsc_t * dsc, + uint32_t dst_px_size) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color + }; + if(dst_px_size == 3) { + lv_color_blend_to_rgb888_with_opa_neon(&asm_dsc); + } + else { + lv_color_blend_to_xrgb8888_with_opa_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_color_blend_to_rgb888_with_mask_neon(asm_dsc_t * dsc); +extern void lv_color_blend_to_xrgb8888_with_mask_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_color_blend_to_rgb888_with_mask_neon(_lv_draw_sw_blend_fill_dsc_t * dsc, + uint32_t dst_px_size) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + if(dst_px_size == 3) { + lv_color_blend_to_rgb888_with_mask_neon(&asm_dsc); + } + else { + lv_color_blend_to_xrgb8888_with_mask_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_color_blend_to_rgb888_mix_mask_opa_neon(asm_dsc_t * dsc); +extern void lv_color_blend_to_xrgb8888_mix_mask_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_color_blend_to_rgb888_mix_mask_opa_neon(_lv_draw_sw_blend_fill_dsc_t * dsc, + uint32_t dst_px_size) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + if(dst_px_size == 3) { + lv_color_blend_to_rgb888_mix_mask_opa_neon(&asm_dsc); + } + else { + lv_color_blend_to_xrgb8888_mix_mask_opa_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_rgb565_blend_normal_to_rgb888_neon(asm_dsc_t * dsc); +extern void lv_rgb565_blend_normal_to_xrgb8888_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb888_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + if(dst_px_size == 3) { + lv_rgb565_blend_normal_to_rgb888_neon(&asm_dsc); + } + else { + lv_rgb565_blend_normal_to_xrgb8888_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_rgb565_blend_normal_to_rgb888_with_opa_neon(asm_dsc_t * dsc); +extern void lv_rgb565_blend_normal_to_xrgb8888_with_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb888_with_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + if(dst_px_size == 3) { + lv_rgb565_blend_normal_to_rgb888_with_opa_neon(&asm_dsc); + } + else { + lv_rgb565_blend_normal_to_xrgb8888_with_opa_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_rgb565_blend_normal_to_rgb888_with_mask_neon(asm_dsc_t * dsc); +extern void lv_rgb565_blend_normal_to_xrgb8888_with_mask_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb888_with_mask_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + if(dst_px_size == 3) { + lv_rgb565_blend_normal_to_rgb888_with_mask_neon(&asm_dsc); + } + else { + lv_rgb565_blend_normal_to_xrgb8888_with_mask_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_rgb565_blend_normal_to_rgb888_mix_mask_opa_neon(asm_dsc_t * dsc); +extern void lv_rgb565_blend_normal_to_xrgb8888_mix_mask_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb888_mix_mask_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + if(dst_px_size == 3) { + lv_rgb565_blend_normal_to_rgb888_mix_mask_opa_neon(&asm_dsc); + } + else { + lv_rgb565_blend_normal_to_xrgb8888_mix_mask_opa_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_rgb888_blend_normal_to_rgb888_neon(asm_dsc_t * dsc); +extern void lv_rgb888_blend_normal_to_xrgb8888_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_rgb888_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_xrgb8888_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb888_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size, + uint32_t src_px_size) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + if(dst_px_size == 3) { + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_rgb888_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_rgb888_neon(&asm_dsc); + } + } + else { + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_xrgb8888_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_xrgb8888_neon(&asm_dsc); + } + } + return LV_RESULT_OK; +} + +extern void lv_rgb888_blend_normal_to_rgb888_with_opa_neon(asm_dsc_t * dsc); +extern void lv_rgb888_blend_normal_to_xrgb8888_with_opa_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_rgb888_with_opa_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_xrgb8888_with_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb888_with_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size, uint32_t src_px_size) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + if(dst_px_size == 3) { + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_rgb888_with_opa_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_rgb888_with_opa_neon(&asm_dsc); + } + } + else { + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_xrgb8888_with_opa_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_xrgb8888_with_opa_neon(&asm_dsc); + } + } + return LV_RESULT_OK; +} + +extern void lv_rgb888_blend_normal_to_rgb888_with_mask_neon(asm_dsc_t * dsc); +extern void lv_rgb888_blend_normal_to_xrgb8888_with_mask_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_rgb888_with_mask_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_xrgb8888_with_mask_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb888_with_mask_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size, uint32_t src_px_size) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + if(dst_px_size == 3) { + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_rgb888_with_mask_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_rgb888_with_mask_neon(&asm_dsc); + } + } + else { + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_xrgb8888_with_mask_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_xrgb8888_with_mask_neon(&asm_dsc); + } + } + return LV_RESULT_OK; +} + +extern void lv_rgb888_blend_normal_to_rgb888_mix_mask_opa_neon(asm_dsc_t * dsc); +extern void lv_rgb888_blend_normal_to_xrgb8888_mix_mask_opa_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_rgb888_mix_mask_opa_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_xrgb8888_mix_mask_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb888_mix_mask_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size, uint32_t src_px_size) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + if(dst_px_size == 3) { + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_rgb888_mix_mask_opa_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_rgb888_mix_mask_opa_neon(&asm_dsc); + } + } + else { + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_xrgb8888_mix_mask_opa_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_xrgb8888_mix_mask_opa_neon(&asm_dsc); + } + } + return LV_RESULT_OK; +} + +extern void lv_argb8888_blend_normal_to_rgb888_neon(asm_dsc_t * dsc); +extern void lv_argb8888_blend_normal_to_xrgb8888_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb888_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + if(dst_px_size == 3) { + lv_argb8888_blend_normal_to_rgb888_neon(&asm_dsc); + } + else { + lv_argb8888_blend_normal_to_xrgb8888_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_argb8888_blend_normal_to_rgb888_with_opa_neon(asm_dsc_t * dsc); +extern void lv_argb8888_blend_normal_to_xrgb8888_with_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb888_with_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + if(dst_px_size == 3) { + lv_argb8888_blend_normal_to_rgb888_with_opa_neon(&asm_dsc); + } + else { + lv_argb8888_blend_normal_to_xrgb8888_with_opa_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_argb8888_blend_normal_to_rgb888_with_mask_neon(asm_dsc_t * dsc); +extern void lv_argb8888_blend_normal_to_xrgb8888_with_mask_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb888_with_mask_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + if(dst_px_size == 3) { + lv_argb8888_blend_normal_to_rgb888_with_mask_neon(&asm_dsc); + } + else { + lv_argb8888_blend_normal_to_xrgb8888_with_mask_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_argb8888_blend_normal_to_rgb888_mix_mask_opa_neon(asm_dsc_t * dsc); +extern void lv_argb8888_blend_normal_to_xrgb8888_mix_mask_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb888_mix_mask_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t dst_px_size) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + if(dst_px_size == 3) { + lv_argb8888_blend_normal_to_rgb888_mix_mask_opa_neon(&asm_dsc); + } + else { + lv_argb8888_blend_normal_to_xrgb8888_mix_mask_opa_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_color_blend_to_argb8888_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_color_blend_to_argb8888_neon(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color + }; + + lv_color_blend_to_argb8888_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_color_blend_to_argb8888_with_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_color_blend_to_argb8888_with_opa_neon(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color + }; + lv_color_blend_to_argb8888_with_opa_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_color_blend_to_argb8888_with_mask_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_color_blend_to_argb8888_with_mask_neon(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_color_blend_to_argb8888_with_mask_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_color_blend_to_argb8888_mix_mask_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_color_blend_to_argb8888_mix_mask_opa_neon(_lv_draw_sw_blend_fill_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = &dsc->color, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_color_blend_to_argb8888_mix_mask_opa_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_rgb565_blend_normal_to_argb8888_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb565_blend_normal_to_argb8888_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + lv_rgb565_blend_normal_to_argb8888_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_rgb565_blend_normal_to_argb8888_with_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb565_blend_normal_to_argb8888_with_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + lv_rgb565_blend_normal_to_argb8888_with_opa_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_rgb565_blend_normal_to_argb8888_with_mask_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb565_blend_normal_to_argb8888_with_mask_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_rgb565_blend_normal_to_argb8888_with_mask_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_rgb565_blend_normal_to_argb8888_mix_mask_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb565_blend_normal_to_argb8888_mix_mask_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_rgb565_blend_normal_to_argb8888_mix_mask_opa_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_rgb888_blend_normal_to_argb8888_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_argb8888_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb888_blend_normal_to_argb8888_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_argb8888_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_argb8888_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_rgb888_blend_normal_to_argb8888_with_opa_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_argb8888_with_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb888_blend_normal_to_argb8888_with_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_argb8888_with_opa_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_argb8888_with_opa_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_rgb888_blend_normal_to_argb8888_with_mask_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_argb8888_with_mask_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb888_blend_normal_to_argb8888_with_mask_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_argb8888_with_mask_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_argb8888_with_mask_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_rgb888_blend_normal_to_argb8888_mix_mask_opa_neon(asm_dsc_t * dsc); +extern void lv_xrgb8888_blend_normal_to_argb8888_mix_mask_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_rgb888_blend_normal_to_argb8888_mix_mask_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc, + uint32_t src_px_size) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + if(src_px_size == 3) { + lv_rgb888_blend_normal_to_argb8888_mix_mask_opa_neon(&asm_dsc); + } + else { + lv_xrgb8888_blend_normal_to_argb8888_mix_mask_opa_neon(&asm_dsc); + } + return LV_RESULT_OK; +} + +extern void lv_argb8888_blend_normal_to_argb8888_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_argb8888_blend_normal_to_argb8888_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + lv_argb8888_blend_normal_to_argb8888_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_argb8888_blend_normal_to_argb8888_with_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_argb8888_blend_normal_to_argb8888_with_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride + }; + lv_argb8888_blend_normal_to_argb8888_with_opa_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_argb8888_blend_normal_to_argb8888_with_mask_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_argb8888_blend_normal_to_argb8888_with_mask_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_argb8888_blend_normal_to_argb8888_with_mask_neon(&asm_dsc); + return LV_RESULT_OK; +} + +extern void lv_argb8888_blend_normal_to_argb8888_mix_mask_opa_neon(asm_dsc_t * dsc); +static inline lv_result_t _lv_argb8888_blend_normal_to_argb8888_mix_mask_opa_neon(_lv_draw_sw_blend_image_dsc_t * dsc) +{ + asm_dsc_t asm_dsc = { + .opa = dsc->opa, + .dst_buf = dsc->dest_buf, + .dst_w = dsc->dest_w, + .dst_h = dsc->dest_h, + .dst_stride = dsc->dest_stride, + .src_buf = dsc->src_buf, + .src_stride = dsc->src_stride, + .mask_buf = dsc->mask_buf, + .mask_stride = dsc->mask_stride + }; + lv_argb8888_blend_normal_to_argb8888_mix_mask_opa_neon(&asm_dsc); + return LV_RESULT_OK; +} + +#endif /* !defined(__ASSEMBLY__) */ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_BLEND_TO_NEON_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.c index 1c0c6d4a2..fb1fd8d5d 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.c @@ -7,11 +7,72 @@ * INCLUDES *********************/ #include "../lv_draw.h" +#if LV_USE_DRAW_SW + +#include "../../core/lv_refr.h" #include "lv_draw_sw.h" +#include "../../display/lv_display_private.h" +#include "../../stdlib/lv_string.h" +#include "../../core/lv_global.h" + +#if LV_USE_VECTOR_GRAPHIC && (LV_USE_THORVG_EXTERNAL || LV_USE_THORVG_INTERNAL) + #if LV_USE_THORVG_EXTERNAL + #include + #else + #include "../../libs/thorvg/thorvg_capi.h" + #endif +#endif + +#if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_HELIUM + #include "arm2d/lv_draw_sw_helium.h" +#elif LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_CUSTOM + #include LV_DRAW_SW_ASM_CUSTOM_INCLUDE +#endif /********************* * DEFINES *********************/ +#define DRAW_UNIT_ID_SW 1 + +#ifndef LV_DRAW_SW_RGB565_SWAP + #define LV_DRAW_SW_RGB565_SWAP(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ROTATE90_ARGB8888 + #define LV_DRAW_SW_ROTATE90_ARGB8888(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ROTATE180_ARGB8888 + #define LV_DRAW_SW_ROTATE180_ARGB8888(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ROTATE270_ARGB8888 + #define LV_DRAW_SW_ROTATE270_ARGB8888(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ROTATE90_RGB888 + #define LV_DRAW_SW_ROTATE90_RGB888(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ROTATE180_RGB888 + #define LV_DRAW_SW_ROTATE180_RGB888(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ROTATE270_RGB888 + #define LV_DRAW_SW_ROTATE270_RGB888(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ROTATE90_RGB565 + #define LV_DRAW_SW_ROTATE90_RGB565(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ROTATE180_RGB565 + #define LV_DRAW_SW_ROTATE180_RGB565(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_ROTATE270_RGB565 + #define LV_DRAW_SW_ROTATE270_RGB565(...) LV_RESULT_INVALID +#endif /********************** * TYPEDEFS @@ -20,14 +81,43 @@ /********************** * STATIC PROTOTYPES **********************/ +#if LV_USE_OS + static void render_thread_cb(void * ptr); +#endif -/********************** - * GLOBAL PROTOTYPES - **********************/ +static void execute_drawing(lv_draw_sw_unit_t * u); + +static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer); +static int32_t evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task); +static int32_t lv_draw_sw_delete(lv_draw_unit_t * draw_unit); + +static void rotate90_argb8888(const uint32_t * src, uint32_t * dst, int32_t srcWidth, int32_t srcHeight, + int32_t srcStride, + int32_t dstStride); +static void rotate180_argb8888(const uint32_t * src, uint32_t * dst, int32_t width, int32_t height, int32_t src_stride, + int32_t dest_stride); +static void rotate270_argb8888(const uint32_t * src, uint32_t * dst, int32_t srcWidth, int32_t srcHeight, + int32_t srcStride, + int32_t dstStride); +static void rotate90_rgb888(const uint8_t * src, uint8_t * dst, int32_t srcWidth, int32_t srcHeight, int32_t srcStride, + int32_t dstStride); +static void rotate180_rgb888(const uint8_t * src, uint8_t * dst, int32_t width, int32_t height, int32_t src_stride, + int32_t dest_stride); +static void rotate270_rgb888(const uint8_t * src, uint8_t * dst, int32_t width, int32_t height, int32_t srcStride, + int32_t dstStride); +static void rotate90_rgb565(const uint16_t * src, uint16_t * dst, int32_t srcWidth, int32_t srcHeight, + int32_t srcStride, + int32_t dstStride); +static void rotate180_rgb565(const uint16_t * src, uint16_t * dst, int32_t width, int32_t height, int32_t src_stride, + int32_t dest_stride); +static void rotate270_rgb565(const uint16_t * src, uint16_t * dst, int32_t srcWidth, int32_t srcHeight, + int32_t srcStride, + int32_t dstStride); /********************** * STATIC VARIABLES **********************/ +#define _draw_info LV_GLOBAL_DEFAULT()->draw_info /********************** * MACROS @@ -37,72 +127,491 @@ * GLOBAL FUNCTIONS **********************/ -void lv_draw_sw_init_ctx(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) +void lv_draw_sw_init(void) { - LV_UNUSED(drv); - lv_draw_sw_ctx_t * draw_sw_ctx = (lv_draw_sw_ctx_t *) draw_ctx; - lv_memset_00(draw_sw_ctx, sizeof(lv_draw_sw_ctx_t)); - - draw_sw_ctx->base_draw.draw_arc = lv_draw_sw_arc; - draw_sw_ctx->base_draw.draw_rect = lv_draw_sw_rect; - draw_sw_ctx->base_draw.draw_bg = lv_draw_sw_bg; - draw_sw_ctx->base_draw.draw_letter = lv_draw_sw_letter; - draw_sw_ctx->base_draw.draw_img_decoded = lv_draw_sw_img_decoded; - draw_sw_ctx->base_draw.draw_line = lv_draw_sw_line; - draw_sw_ctx->base_draw.draw_polygon = lv_draw_sw_polygon; -#if LV_DRAW_COMPLEX - draw_sw_ctx->base_draw.draw_transform = lv_draw_sw_transform; +#if LV_DRAW_SW_COMPLEX == 1 + lv_draw_sw_mask_init(); +#endif + + uint32_t i; + for(i = 0; i < LV_DRAW_SW_DRAW_UNIT_CNT; i++) { + lv_draw_sw_unit_t * draw_sw_unit = lv_draw_create_unit(sizeof(lv_draw_sw_unit_t)); + draw_sw_unit->base_unit.dispatch_cb = dispatch; + draw_sw_unit->base_unit.evaluate_cb = evaluate; + draw_sw_unit->idx = i; + draw_sw_unit->base_unit.delete_cb = LV_USE_OS ? lv_draw_sw_delete : NULL; + +#if LV_USE_OS + lv_thread_init(&draw_sw_unit->thread, LV_THREAD_PRIO_HIGH, render_thread_cb, 8 * 1024, draw_sw_unit); +#endif + } + +#if LV_USE_VECTOR_GRAPHIC && (LV_USE_THORVG_EXTERNAL || LV_USE_THORVG_INTERNAL) + tvg_engine_init(TVG_ENGINE_SW, 0); #endif - draw_sw_ctx->base_draw.wait_for_finish = lv_draw_sw_wait_for_finish; - draw_sw_ctx->base_draw.buffer_copy = lv_draw_sw_buffer_copy; - draw_sw_ctx->base_draw.layer_init = lv_draw_sw_layer_create; - draw_sw_ctx->base_draw.layer_adjust = lv_draw_sw_layer_adjust; - draw_sw_ctx->base_draw.layer_blend = lv_draw_sw_layer_blend; - draw_sw_ctx->base_draw.layer_destroy = lv_draw_sw_layer_destroy; - draw_sw_ctx->blend = lv_draw_sw_blend_basic; - draw_ctx->layer_instance_size = sizeof(lv_draw_sw_layer_ctx_t); } -void lv_draw_sw_deinit_ctx(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) +void lv_draw_sw_deinit(void) { - LV_UNUSED(drv); +#if LV_USE_VECTOR_GRAPHIC && (LV_USE_THORVG_EXTERNAL || LV_USE_THORVG_INTERNAL) + tvg_engine_term(TVG_ENGINE_SW); +#endif - lv_draw_sw_ctx_t * draw_sw_ctx = (lv_draw_sw_ctx_t *) draw_ctx; - lv_memset_00(draw_sw_ctx, sizeof(lv_draw_sw_ctx_t)); +#if LV_DRAW_SW_COMPLEX == 1 + lv_draw_sw_mask_deinit(); +#endif } -void lv_draw_sw_wait_for_finish(lv_draw_ctx_t * draw_ctx) +static int32_t lv_draw_sw_delete(lv_draw_unit_t * draw_unit) { - LV_UNUSED(draw_ctx); - /*Nothing to wait for*/ +#if LV_USE_OS + lv_draw_sw_unit_t * draw_sw_unit = (lv_draw_sw_unit_t *) draw_unit; + + LV_LOG_INFO("cancel software rendering thread"); + draw_sw_unit->exit_status = true; + + if(draw_sw_unit->inited) { + lv_thread_sync_signal(&draw_sw_unit->sync); + } + + return lv_thread_delete(&draw_sw_unit->thread); +#else + LV_UNUSED(draw_unit); + return 0; +#endif } -void lv_draw_sw_buffer_copy(lv_draw_ctx_t * draw_ctx, - void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area, - void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area) +void lv_draw_sw_rgb565_swap(void * buf, uint32_t buf_size_px) { - LV_UNUSED(draw_ctx); + if(LV_DRAW_SW_RGB565_SWAP(buf, buf_size_px) == LV_RESULT_OK) return; - lv_color_t * dest_bufc = dest_buf; - lv_color_t * src_bufc = src_buf; + uint32_t u32_cnt = buf_size_px / 2; + uint16_t * buf16 = buf; + uint32_t * buf32 = buf; - /*Got the first pixel of each buffer*/ - dest_bufc += dest_stride * dest_area->y1; - dest_bufc += dest_area->x1; + while(u32_cnt >= 8) { + buf32[0] = ((buf32[0] & 0xff00ff00) >> 8) | ((buf32[0] & 0x00ff00ff) << 8); + buf32[1] = ((buf32[1] & 0xff00ff00) >> 8) | ((buf32[1] & 0x00ff00ff) << 8); + buf32[2] = ((buf32[2] & 0xff00ff00) >> 8) | ((buf32[2] & 0x00ff00ff) << 8); + buf32[3] = ((buf32[3] & 0xff00ff00) >> 8) | ((buf32[3] & 0x00ff00ff) << 8); + buf32[4] = ((buf32[4] & 0xff00ff00) >> 8) | ((buf32[4] & 0x00ff00ff) << 8); + buf32[5] = ((buf32[5] & 0xff00ff00) >> 8) | ((buf32[5] & 0x00ff00ff) << 8); + buf32[6] = ((buf32[6] & 0xff00ff00) >> 8) | ((buf32[6] & 0x00ff00ff) << 8); + buf32[7] = ((buf32[7] & 0xff00ff00) >> 8) | ((buf32[7] & 0x00ff00ff) << 8); + buf32 += 8; + u32_cnt -= 8; + } - src_bufc += src_stride * src_area->y1; - src_bufc += src_area->x1; + while(u32_cnt) { + *buf32 = ((*buf32 & 0xff00ff00) >> 8) | ((*buf32 & 0x00ff00ff) << 8); + buf32++; + u32_cnt--; + } - uint32_t line_length = lv_area_get_width(dest_area) * sizeof(lv_color_t); - lv_coord_t y; - for(y = dest_area->y1; y <= dest_area->y2; y++) { - lv_memcpy(dest_bufc, src_bufc, line_length); - dest_bufc += dest_stride; - src_bufc += src_stride; + if(buf_size_px & 0x1) { + uint32_t e = buf_size_px - 1; + buf16[e] = ((buf16[e] & 0xff00) >> 8) | ((buf16[e] & 0x00ff) << 8); + } + +} + +void lv_draw_sw_rotate(const void * src, void * dest, int32_t src_width, int32_t src_height, int32_t src_sride, + int32_t dest_stride, lv_display_rotation_t rotation, lv_color_format_t color_format) +{ + uint32_t px_bpp = lv_color_format_get_bpp(color_format); + if(rotation == LV_DISPLAY_ROTATION_90) { + if(px_bpp == 16) rotate90_rgb565(src, dest, src_width, src_height, src_sride, dest_stride); + if(px_bpp == 24) rotate90_rgb888(src, dest, src_width, src_height, src_sride, dest_stride); + if(px_bpp == 32) rotate90_argb8888(src, dest, src_width, src_height, src_sride, dest_stride); + } + else if(rotation == LV_DISPLAY_ROTATION_180) { + if(px_bpp == 16) rotate180_rgb565(src, dest, src_width, src_height, src_sride, dest_stride); + if(px_bpp == 24) rotate180_rgb888(src, dest, src_width, src_height, src_sride, dest_stride); + if(px_bpp == 32) rotate180_argb8888(src, dest, src_width, src_height, src_sride, dest_stride); + } + else if(rotation == LV_DISPLAY_ROTATION_270) { + if(px_bpp == 16) rotate270_rgb565(src, dest, src_width, src_height, src_sride, dest_stride); + if(px_bpp == 24) rotate270_rgb888(src, dest, src_width, src_height, src_sride, dest_stride); + if(px_bpp == 32) rotate270_argb8888(src, dest, src_width, src_height, src_sride, dest_stride); } } /********************** * STATIC FUNCTIONS **********************/ +static inline void execute_drawing_unit(lv_draw_sw_unit_t * u) +{ + execute_drawing(u); + + u->task_act->state = LV_DRAW_TASK_STATE_READY; + u->task_act = NULL; + + /*The draw unit is free now. Request a new dispatching as it can get a new task*/ + lv_draw_dispatch_request(); +} + +static int32_t evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task) +{ + LV_UNUSED(draw_unit); + + switch(task->type) { + case LV_DRAW_TASK_TYPE_IMAGE: + case LV_DRAW_TASK_TYPE_LAYER: { + lv_draw_image_dsc_t * draw_dsc = task->draw_dsc; + + /* not support skew */ + if(draw_dsc->skew_x != 0 || draw_dsc->skew_y != 0) { + return 0; + } + } + break; + default: + break; + } + + if(task->preference_score >= 100) { + task->preference_score = 100; + task->preferred_draw_unit_id = DRAW_UNIT_ID_SW; + } + + return 0; +} + +static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer) +{ + LV_PROFILER_BEGIN; + lv_draw_sw_unit_t * draw_sw_unit = (lv_draw_sw_unit_t *) draw_unit; + + /*Return immediately if it's busy with draw task*/ + if(draw_sw_unit->task_act) { + LV_PROFILER_END; + return 0; + } + + lv_draw_task_t * t = NULL; + t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_SW); + if(t == NULL) { + LV_PROFILER_END; + return -1; + } + + void * buf = lv_draw_layer_alloc_buf(layer); + if(buf == NULL) { + LV_PROFILER_END; + return -1; + } + + t->state = LV_DRAW_TASK_STATE_IN_PROGRESS; + draw_sw_unit->base_unit.target_layer = layer; + draw_sw_unit->base_unit.clip_area = &t->clip_area; + draw_sw_unit->task_act = t; + +#if LV_USE_OS + /*Let the render thread work*/ + if(draw_sw_unit->inited) lv_thread_sync_signal(&draw_sw_unit->sync); +#else + execute_drawing_unit(draw_sw_unit); +#endif + LV_PROFILER_END; + return 1; +} + +#if LV_USE_OS +static void render_thread_cb(void * ptr) +{ + lv_draw_sw_unit_t * u = ptr; + + lv_thread_sync_init(&u->sync); + u->inited = true; + + while(1) { + while(u->task_act == NULL) { + if(u->exit_status) { + break; + } + lv_thread_sync_wait(&u->sync); + } + + if(u->exit_status) { + LV_LOG_INFO("ready to exit software rendering thread"); + break; + } + + execute_drawing_unit(u); + } + + u->inited = false; + lv_thread_sync_delete(&u->sync); + LV_LOG_INFO("exit software rendering thread"); +} +#endif + +static void execute_drawing(lv_draw_sw_unit_t * u) +{ + LV_PROFILER_BEGIN; + /*Render the draw task*/ + lv_draw_task_t * t = u->task_act; + switch(t->type) { + case LV_DRAW_TASK_TYPE_FILL: + lv_draw_sw_fill((lv_draw_unit_t *)u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_BORDER: + lv_draw_sw_border((lv_draw_unit_t *)u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_BOX_SHADOW: + lv_draw_sw_box_shadow((lv_draw_unit_t *)u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_LABEL: + lv_draw_sw_label((lv_draw_unit_t *)u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_IMAGE: + lv_draw_sw_image((lv_draw_unit_t *)u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_ARC: + lv_draw_sw_arc((lv_draw_unit_t *)u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_LINE: + lv_draw_sw_line((lv_draw_unit_t *)u, t->draw_dsc); + break; + case LV_DRAW_TASK_TYPE_TRIANGLE: + lv_draw_sw_triangle((lv_draw_unit_t *)u, t->draw_dsc); + break; + case LV_DRAW_TASK_TYPE_LAYER: + lv_draw_sw_layer((lv_draw_unit_t *)u, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_MASK_RECTANGLE: + lv_draw_sw_mask_rect((lv_draw_unit_t *)u, t->draw_dsc, &t->area); + break; +#if LV_USE_VECTOR_GRAPHIC && (LV_USE_THORVG_EXTERNAL || LV_USE_THORVG_INTERNAL) + case LV_DRAW_TASK_TYPE_VECTOR: + lv_draw_sw_vector((lv_draw_unit_t *)u, t->draw_dsc); + break; +#endif + default: + break; + } + +#if LV_USE_PARALLEL_DRAW_DEBUG + /*Layers manage it for themselves*/ + if(t->type != LV_DRAW_TASK_TYPE_LAYER) { + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, &t->area, u->base_unit.clip_area)) return; + + int32_t idx = 0; + lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head; + while(draw_unit_tmp != (lv_draw_unit_t *)u) { + draw_unit_tmp = draw_unit_tmp->next; + idx++; + } + lv_draw_rect_dsc_t rect_dsc; + lv_draw_rect_dsc_init(&rect_dsc); + rect_dsc.bg_color = lv_palette_main(idx % _LV_PALETTE_LAST); + rect_dsc.border_color = rect_dsc.bg_color; + rect_dsc.bg_opa = LV_OPA_10; + rect_dsc.border_opa = LV_OPA_80; + rect_dsc.border_width = 1; + lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &draw_area); + + lv_point_t txt_size; + lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE); + + lv_area_t txt_area; + txt_area.x1 = draw_area.x1; + txt_area.y1 = draw_area.y1; + txt_area.x2 = draw_area.x1 + txt_size.x - 1; + txt_area.y2 = draw_area.y1 + txt_size.y - 1; + + lv_draw_rect_dsc_init(&rect_dsc); + rect_dsc.bg_color = lv_color_white(); + lv_draw_sw_fill((lv_draw_unit_t *)u, &rect_dsc, &txt_area); + + char buf[8]; + lv_snprintf(buf, sizeof(buf), "%d", idx); + lv_draw_label_dsc_t label_dsc; + lv_draw_label_dsc_init(&label_dsc); + label_dsc.color = lv_color_black(); + label_dsc.text = buf; + lv_draw_sw_label((lv_draw_unit_t *)u, &label_dsc, &txt_area); + } +#endif + LV_PROFILER_END; +} + +static void rotate90_argb8888(const uint32_t * src, uint32_t * dst, int32_t srcWidth, int32_t srcHeight, + int32_t srcStride, + int32_t dstStride) +{ + if(LV_RESULT_OK == LV_DRAW_SW_ROTATE90_ARGB8888(src, dst, srcWidth, srcHeight, srcStride, dstStride)) { + return ; + } + + srcStride /= sizeof(uint32_t); + dstStride /= sizeof(uint32_t); + + for(int32_t x = 0; x < srcWidth; ++x) { + int32_t dstIndex = x * dstStride; + int32_t srcIndex = x; + for(int32_t y = 0; y < srcHeight; ++y) { + dst[dstIndex + (srcHeight - y - 1)] = src[srcIndex]; + srcIndex += srcStride; + } + } +} + +static void rotate180_argb8888(const uint32_t * src, uint32_t * dst, int32_t width, int32_t height, int32_t src_stride, + int32_t dest_stride) +{ + if(LV_RESULT_OK == LV_DRAW_SW_ROTATE180_ARGB8888(src, dst, srcWidth, srcHeight, srcStride, dstStride)) { + return ; + } + + src_stride /= sizeof(uint32_t); + dest_stride /= sizeof(uint32_t); + + for(int32_t y = 0; y < height; ++y) { + int32_t dstIndex = (height - y - 1) * src_stride; + int32_t srcIndex = y * src_stride; + for(int32_t x = 0; x < width; ++x) { + dst[dstIndex + width - x - 1] = src[srcIndex + x]; + } + } +} + +static void rotate270_argb8888(const uint32_t * src, uint32_t * dst, int32_t srcWidth, int32_t srcHeight, + int32_t srcStride, + int32_t dstStride) +{ + if(LV_RESULT_OK == LV_DRAW_SW_ROTATE270_ARGB8888(src, dst, srcWidth, srcHeight, srcStride, dstStride)) { + return ; + } + + srcStride /= sizeof(uint32_t); + dstStride /= sizeof(uint32_t); + + for(int32_t x = 0; x < srcWidth; ++x) { + int32_t dstIndex = (srcWidth - x - 1); + int32_t srcIndex = x; + for(int32_t y = 0; y < srcHeight; ++y) { + dst[dstIndex * dstStride + y] = src[srcIndex]; + srcIndex += srcStride; + } + } +} + +static void rotate90_rgb888(const uint8_t * src, uint8_t * dst, int32_t srcWidth, int32_t srcHeight, int32_t srcStride, + int32_t dstStride) +{ + if(LV_RESULT_OK == LV_DRAW_SW_ROTATE90_RGB888(src, dst, srcWidth, srcHeight, srcStride, dstStride)) { + return ; + } + + for(int32_t x = 0; x < srcWidth; ++x) { + for(int32_t y = 0; y < srcHeight; ++y) { + int32_t srcIndex = y * srcStride + x * 3; + int32_t dstIndex = (srcWidth - x - 1) * dstStride + y * 3; + dst[dstIndex] = src[srcIndex]; /*Red*/ + dst[dstIndex + 1] = src[srcIndex + 1]; /*Green*/ + dst[dstIndex + 2] = src[srcIndex + 2]; /*Blue*/ + } + } +} + +static void rotate180_rgb888(const uint8_t * src, uint8_t * dst, int32_t width, int32_t height, int32_t src_stride, + int32_t dest_stride) +{ + if(LV_RESULT_OK == LV_DRAW_SW_ROTATE180_RGB888(src, dst, srcWidth, srcHeight, srcStride, dstStride)) { + return ; + } + + for(int32_t y = 0; y < height; ++y) { + for(int32_t x = 0; x < width; ++x) { + int32_t srcIndex = y * src_stride + x * 3; + int32_t dstIndex = (height - y - 1) * dest_stride + (width - x - 1) * 3; + dst[dstIndex] = src[srcIndex]; + dst[dstIndex + 1] = src[srcIndex + 1]; + dst[dstIndex + 2] = src[srcIndex + 2]; + } + } +} + +static void rotate270_rgb888(const uint8_t * src, uint8_t * dst, int32_t width, int32_t height, int32_t srcStride, + int32_t dstStride) +{ + if(LV_RESULT_OK == LV_DRAW_SW_ROTATE270_RGB888(src, dst, srcWidth, srcHeight, srcStride, dstStride)) { + return ; + } + + for(int32_t x = 0; x < width; ++x) { + for(int32_t y = 0; y < height; ++y) { + int32_t srcIndex = y * srcStride + x * 3; + int32_t dstIndex = x * dstStride + (height - y - 1) * 3; + dst[dstIndex] = src[srcIndex]; /*Red*/ + dst[dstIndex + 1] = src[srcIndex + 1]; /*Green*/ + dst[dstIndex + 2] = src[srcIndex + 2]; /*Blue*/ + } + } +} + +static void rotate90_rgb565(const uint16_t * src, uint16_t * dst, int32_t srcWidth, int32_t srcHeight, + int32_t srcStride, + int32_t dstStride) +{ + if(LV_RESULT_OK == LV_DRAW_SW_ROTATE90_RGB565(src, dst, srcWidth, srcHeight, srcStride, dstStride)) { + return ; + } + + srcStride /= sizeof(uint16_t); + dstStride /= sizeof(uint16_t); + + for(int32_t x = 0; x < srcWidth; ++x) { + int32_t dstIndex = x * dstStride; + int32_t srcIndex = x; + for(int32_t y = 0; y < srcHeight; ++y) { + dst[dstIndex + (srcHeight - y - 1)] = src[srcIndex]; + srcIndex += srcStride; + } + } +} + +static void rotate180_rgb565(const uint16_t * src, uint16_t * dst, int32_t width, int32_t height, int32_t src_stride, + int32_t dest_stride) +{ + if(LV_RESULT_OK == LV_DRAW_SW_ROTATE180_RGB565(src, dst, srcWidth, srcHeight, srcStride, dstStride)) { + return ; + } + + src_stride /= sizeof(uint16_t); + dest_stride /= sizeof(uint16_t); + + for(int32_t y = 0; y < height; ++y) { + int32_t dstIndex = (height - y - 1) * dest_stride; + int32_t srcIndex = y * src_stride; + for(int32_t x = 0; x < width; ++x) { + dst[dstIndex + width - x - 1] = src[srcIndex + x]; + } + } +} + +static void rotate270_rgb565(const uint16_t * src, uint16_t * dst, int32_t srcWidth, int32_t srcHeight, + int32_t srcStride, + int32_t dstStride) +{ + if(LV_RESULT_OK == LV_DRAW_SW_ROTATE270_RGB565(src, dst, srcWidth, srcHeight, srcStride, dstStride)) { + return ; + } + + srcStride /= sizeof(uint16_t); + dstStride /= sizeof(uint16_t); + + for(int32_t x = 0; x < srcWidth; ++x) { + int32_t dstIndex = (srcWidth - x - 1); + int32_t srcIndex = x; + for(int32_t y = 0; y < srcHeight; ++y) { + dst[dstIndex * dstStride + y] = src[srcIndex]; + srcIndex += srcStride; + } + } +} + +#endif /*LV_USE_DRAW_SW*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.h b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.h index 0f6d46b90..bc0e39937 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.h @@ -13,11 +13,15 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "lv_draw_sw_blend.h" #include "../lv_draw.h" +#if LV_USE_DRAW_SW + #include "../../misc/lv_area.h" #include "../../misc/lv_color.h" -#include "../../hal/lv_hal_disp.h" +#include "../../display/lv_display.h" +#include "../../osal/lv_os.h" + +#include "../../draw/lv_draw_vector.h" /********************* * DEFINES @@ -27,69 +31,167 @@ extern "C" { * TYPEDEFS **********************/ -struct _lv_disp_drv_t; - typedef struct { - lv_draw_ctx_t base_draw; - - /** Fill an area of the destination buffer with a color*/ - void (*blend)(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); -} lv_draw_sw_ctx_t; + lv_draw_unit_t base_unit; + lv_draw_task_t * task_act; +#if LV_USE_OS + lv_thread_sync_t sync; + lv_thread_t thread; + volatile bool inited; + volatile bool exit_status; +#endif + uint32_t idx; +} lv_draw_sw_unit_t; +#if LV_DRAW_SW_SHADOW_CACHE_SIZE typedef struct { - lv_draw_layer_ctx_t base_draw; - - uint32_t buf_size_bytes: 31; - uint32_t has_alpha : 1; -} lv_draw_sw_layer_ctx_t; + uint8_t cache[LV_DRAW_SW_SHADOW_CACHE_SIZE * LV_DRAW_SW_SHADOW_CACHE_SIZE]; + int32_t cache_size; + int32_t cache_r; +} lv_draw_sw_shadow_cache_t; +#endif /********************** * GLOBAL PROTOTYPES **********************/ -void lv_draw_sw_init_ctx(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); -void lv_draw_sw_deinit_ctx(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); +/** + * Initialize the SW renderer. Called in internally. + * It creates as many SW renderers as defined in LV_DRAW_SW_DRAW_UNIT_CNT + */ +void lv_draw_sw_init(void); -void lv_draw_sw_wait_for_finish(lv_draw_ctx_t * draw_ctx); +/** + * Deinitialize the SW renderers + */ +void lv_draw_sw_deinit(void); -void lv_draw_sw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, uint16_t radius, - uint16_t start_angle, uint16_t end_angle); +/** + * Fill an area using SW render. Handle gradient and radius. + * @param draw_unit pointer to a draw unit + * @param dsc the draw descriptor + * @param coords the coordinates of the rectangle + */ +void lv_draw_sw_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords); -void lv_draw_sw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); +/** + * Draw border with SW render. + * @param draw_unit pointer to a draw unit + * @param dsc the draw descriptor + * @param coords the coordinates of the rectangle + */ +void lv_draw_sw_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, const lv_area_t * coords); -void lv_draw_sw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); -void lv_draw_sw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p, - uint32_t letter); +/** + * Draw box shadow with SW render. + * @param draw_unit pointer to a draw unit + * @param dsc the draw descriptor + * @param coords the coordinates of the rectangle for which the box shadow should be drawn + */ +void lv_draw_sw_box_shadow(lv_draw_unit_t * draw_unit, const lv_draw_box_shadow_dsc_t * dsc, const lv_area_t * coords); -void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_sw_img_decoded(struct _lv_draw_ctx_t * draw_ctx, - const lv_draw_img_dsc_t * draw_dsc, - const lv_area_t * coords, const uint8_t * src_buf, - lv_img_cf_t cf); +/** + * Draw an image with SW render. It handles image decoding, tiling, transformations, and recoloring. + * @param draw_unit pointer to a draw unit + * @param dsc the draw descriptor + * @param coords the coordinates of the image + */ +void lv_draw_sw_image(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords); -void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_sw_line(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, - const lv_point_t * point1, const lv_point_t * point2); +/** + * Draw a label with SW render. + * @param draw_unit pointer to a draw unit + * @param dsc the draw descriptor + * @param coords the coordinates of the label + */ +void lv_draw_sw_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords); -void lv_draw_sw_polygon(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, - const lv_point_t * points, uint16_t point_cnt); +/** + * Draw an arc with SW render. + * @param draw_unit pointer to a draw unit + * @param dsc the draw descriptor + * @param coords the coordinates of the arc + */ +void lv_draw_sw_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords); -void lv_draw_sw_buffer_copy(lv_draw_ctx_t * draw_ctx, - void * dest_buf, lv_coord_t dest_stride, const lv_area_t * dest_area, - void * src_buf, lv_coord_t src_stride, const lv_area_t * src_area); +/** + * Draw a line with SW render. + * @param draw_unit pointer to a draw unit + * @param dsc the draw descriptor + */ +void lv_draw_sw_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc); -void lv_draw_sw_transform(lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf, - lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, - const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf); +/** + * Blend a layer with SW render + * @param draw_unit pointer to a draw unit + * @param dsc the draw descriptor + * @param coords the coordinates of the layer + */ +void lv_draw_sw_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, const lv_area_t * coords); -struct _lv_draw_layer_ctx_t * lv_draw_sw_layer_create(struct _lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx, - lv_draw_layer_flags_t flags); +/** + * Draw a triangle with SW render. + * @param draw_unit pointer to a draw unit + * @param dsc the draw descriptor + */ +void lv_draw_sw_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc); -void lv_draw_sw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, - lv_draw_layer_flags_t flags); +/** + * Mask out a rectangle with radius from a current layer + * @param draw_unit pointer to a draw unit + * @param dsc the draw descriptor + * @param coords the coordinates of the mask + */ +void lv_draw_sw_mask_rect(lv_draw_unit_t * draw_unit, const lv_draw_mask_rect_dsc_t * dsc, const lv_area_t * coords); -void lv_draw_sw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, - const lv_draw_img_dsc_t * draw_dsc); +/** + * Used internally to get a transformed are of an image + * @param draw_unit pointer to a draw unit + * @param dest_area the area to calculate, i.e. get this area from the transformed image + * @param src_buf the source buffer + * @param src_w source buffer width in pixels + * @param src_h source buffer height in pixels + * @param src_stride source buffer stride in bytes + * @param dsc the draw descriptor + * @param sup supplementary data + * @param cf color format of the source buffer + * @param dest_buf the destination buffer + */ +void lv_draw_sw_transform(lv_draw_unit_t * draw_unit, const lv_area_t * dest_area, const void * src_buf, + int32_t src_w, int32_t src_h, int32_t src_stride, + const lv_draw_image_dsc_t * draw_dsc, const lv_draw_image_sup_t * sup, lv_color_format_t cf, void * dest_buf); -void lv_draw_sw_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx); +#if LV_USE_VECTOR_GRAPHIC && (LV_USE_THORVG_EXTERNAL || LV_USE_THORVG_INTERNAL) +/** + * Draw vector graphics with SW render. + * @param draw_unit pointer to a draw unit + * @param dsc the draw descriptor + */ +void lv_draw_sw_vector(lv_draw_unit_t * draw_unit, const lv_draw_vector_task_dsc_t * dsc); +#endif + +/** + * Swap the upper and lower byte of an RGB565 buffer. + * Might be required if a 8bit parallel port or an SPI port send the bytes in the wrong order. + * The bytes will be swapped in place. + * @param buf_size_px number of pixels in the buffer + */ +void lv_draw_sw_rgb565_swap(void * buf, uint32_t buf_size_px); + +/** + * Rotate a buffer into an other buffer + * @param src the source buffer + * @param dest the destination buffer + * @param src_width source width in pixels + * @param src_height source height in pixels + * @param src_sride source stride in bytes (number of bytes in a row) + * @param dest_stride destination stride in bytes (number of bytes in a row) + * @param rotation LV_DISPLAY_ROTATION_0/90/180/270 + * @param color_format LV_COLOR_FORMAT_RGB565/RGB888/XRGB8888/ARGB8888 + */ +void lv_draw_sw_rotate(const void * src, void * dest, int32_t src_width, int32_t src_height, int32_t src_sride, + int32_t dest_stride, lv_display_rotation_t rotation, lv_color_format_t color_format); /*********************** * GLOBAL VARIABLES @@ -99,6 +201,10 @@ void lv_draw_sw_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * la * MACROS **********************/ +#include "blend/lv_draw_sw_blend.h" + +#endif /*LV_USE_DRAW_SW*/ + #ifdef __cplusplus } /*extern "C"*/ #endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.mk b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.mk deleted file mode 100644 index 4625cbcfc..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.mk +++ /dev/null @@ -1,17 +0,0 @@ -CSRCS += lv_draw_sw.c -CSRCS += lv_draw_sw_arc.c -CSRCS += lv_draw_sw_blend.c -CSRCS += lv_draw_sw_dither.c -CSRCS += lv_draw_sw_gradient.c -CSRCS += lv_draw_sw_img.c -CSRCS += lv_draw_sw_letter.c -CSRCS += lv_draw_sw_line.c -CSRCS += lv_draw_sw_polygon.c -CSRCS += lv_draw_sw_rect.c -CSRCS += lv_draw_sw_transform.c -CSRCS += lv_draw_sw_layer.c - -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/sw" diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_arc.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_arc.c index 3ed62b6ef..e1093b5f5 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_arc.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_arc.c @@ -1,5 +1,5 @@ /** - * @file lv_draw_arc.c + * @file lv_draw_sw_arc.c * */ @@ -7,11 +7,19 @@ * INCLUDES *********************/ #include "lv_draw_sw.h" +#if LV_USE_DRAW_SW +#if LV_DRAW_SW_COMPLEX + #include "../../misc/lv_math.h" #include "../../misc/lv_log.h" -#include "../../misc/lv_mem.h" +#include "../../stdlib/lv_mem.h" +#include "../../stdlib/lv_string.h" #include "../lv_draw.h" +static void add_circle(const lv_opa_t * circle_mask, const lv_area_t * blend_area, const lv_area_t * circle_area, + lv_opa_t * mask_buf, int32_t width); +static void get_rounded_area(int16_t angle, int32_t radius, uint8_t thickness, lv_area_t * res_area); + /********************* * DEFINES *********************/ @@ -21,29 +29,10 @@ /********************** * TYPEDEFS **********************/ -typedef struct { - const lv_point_t * center; - lv_coord_t radius; - uint16_t start_angle; - uint16_t end_angle; - uint16_t start_quarter; - uint16_t end_quarter; - lv_coord_t width; - lv_draw_rect_dsc_t * draw_dsc; - const lv_area_t * draw_area; - lv_draw_ctx_t * draw_ctx; -} quarter_draw_dsc_t; /********************** * STATIC PROTOTYPES **********************/ -#if LV_DRAW_COMPLEX - static void draw_quarter_0(quarter_draw_dsc_t * q); - static void draw_quarter_1(quarter_draw_dsc_t * q); - static void draw_quarter_2(quarter_draw_dsc_t * q); - static void draw_quarter_3(quarter_draw_dsc_t * q); - static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t thickness, lv_area_t * res_area); -#endif /*LV_DRAW_COMPLEX*/ /********************** * STATIC VARIABLES @@ -57,35 +46,33 @@ typedef struct { * GLOBAL FUNCTIONS **********************/ -void lv_draw_sw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const lv_point_t * center, uint16_t radius, - uint16_t start_angle, uint16_t end_angle) +void lv_draw_sw_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords) { -#if LV_DRAW_COMPLEX +#if LV_DRAW_SW_COMPLEX if(dsc->opa <= LV_OPA_MIN) return; if(dsc->width == 0) return; - if(start_angle == end_angle) return; + if(dsc->start_angle == dsc->end_angle) return; - lv_coord_t width = dsc->width; - if(width > radius) width = radius; + int32_t width = dsc->width; + if(width > dsc->radius) width = dsc->radius; - lv_draw_rect_dsc_t cir_dsc; - lv_draw_rect_dsc_init(&cir_dsc); - cir_dsc.blend_mode = dsc->blend_mode; - if(dsc->img_src) { - cir_dsc.bg_opa = LV_OPA_TRANSP; - cir_dsc.bg_img_src = dsc->img_src; - cir_dsc.bg_img_opa = dsc->opa; + lv_area_t area_out = *coords; + lv_area_t clipped_area; + if(!_lv_area_intersect(&clipped_area, &area_out, draw_unit->clip_area)) return; + + /*Draw a full ring*/ + if(dsc->img_src == NULL && + (dsc->start_angle + 360 == dsc->end_angle || dsc->start_angle == dsc->end_angle + 360)) { + lv_draw_border_dsc_t cir_dsc; + lv_draw_border_dsc_init(&cir_dsc); + cir_dsc.opa = dsc->opa; + cir_dsc.color = dsc->color; + cir_dsc.width = width; + cir_dsc.radius = LV_RADIUS_CIRCLE; + cir_dsc.side = LV_BORDER_SIDE_FULL; + lv_draw_sw_border(draw_unit, &cir_dsc, &area_out); + return; } - else { - cir_dsc.bg_opa = dsc->opa; - cir_dsc.bg_color = dsc->color; - } - - lv_area_t area_out; - area_out.x1 = center->x - radius; - area_out.y1 = center->y - radius; - area_out.x2 = center->x + radius - 1; /*-1 because the center already belongs to the left/bottom part*/ - area_out.y2 = center->y + radius - 1; lv_area_t area_in; lv_area_copy(&area_in, &area_out); @@ -94,444 +81,194 @@ void lv_draw_sw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, con area_in.x2 -= dsc->width; area_in.y2 -= dsc->width; - /*Create inner the mask*/ - int16_t mask_in_id = LV_MASK_ID_INV; - lv_draw_mask_radius_param_t mask_in_param; - bool mask_in_param_valid = false; - if(lv_area_get_width(&area_in) > 0 && lv_area_get_height(&area_in) > 0) { - lv_draw_mask_radius_init(&mask_in_param, &area_in, LV_RADIUS_CIRCLE, true); - mask_in_param_valid = true; - mask_in_id = lv_draw_mask_add(&mask_in_param, NULL); - } - - lv_draw_mask_radius_param_t mask_out_param; - lv_draw_mask_radius_init(&mask_out_param, &area_out, LV_RADIUS_CIRCLE, false); - int16_t mask_out_id = lv_draw_mask_add(&mask_out_param, NULL); - - /*Draw a full ring*/ - if(start_angle + 360 == end_angle || start_angle == end_angle + 360) { - cir_dsc.radius = LV_RADIUS_CIRCLE; - lv_draw_rect(draw_ctx, &cir_dsc, &area_out); - - lv_draw_mask_remove_id(mask_out_id); - if(mask_in_id != LV_MASK_ID_INV) lv_draw_mask_remove_id(mask_in_id); - - lv_draw_mask_free_param(&mask_out_param); - if(mask_in_param_valid) { - lv_draw_mask_free_param(&mask_in_param); - } - - return; - } - + int32_t start_angle = (int32_t)dsc->start_angle; + int32_t end_angle = (int32_t)dsc->end_angle; while(start_angle >= 360) start_angle -= 360; while(end_angle >= 360) end_angle -= 360; - lv_draw_mask_angle_param_t mask_angle_param; - lv_draw_mask_angle_init(&mask_angle_param, center->x, center->y, start_angle, end_angle); - int16_t mask_angle_id = lv_draw_mask_add(&mask_angle_param, NULL); + void * mask_list[4] = {0}; + /*Create an angle mask*/ + lv_draw_sw_mask_angle_param_t mask_angle_param; + lv_draw_sw_mask_angle_init(&mask_angle_param, dsc->center.x, dsc->center.y, start_angle, end_angle); + mask_list[0] = &mask_angle_param; - int32_t angle_gap; - if(end_angle > start_angle) { - angle_gap = 360 - (end_angle - start_angle); + /*Create an outer mask*/ + lv_draw_sw_mask_radius_param_t mask_out_param; + lv_draw_sw_mask_radius_init(&mask_out_param, &area_out, LV_RADIUS_CIRCLE, false); + mask_list[1] = &mask_out_param; + + /*Create inner the mask*/ + lv_draw_sw_mask_radius_param_t mask_in_param; + bool mask_in_param_valid = false; + if(lv_area_get_width(&area_in) > 0 && lv_area_get_height(&area_in) > 0) { + lv_draw_sw_mask_radius_init(&mask_in_param, &area_in, LV_RADIUS_CIRCLE, true); + mask_list[2] = &mask_in_param; + mask_in_param_valid = true; + } + + int32_t blend_h = lv_area_get_height(&clipped_area); + int32_t blend_w = lv_area_get_width(&clipped_area); + int32_t h; + lv_opa_t * mask_buf = lv_malloc(blend_w); + + lv_area_t blend_area = clipped_area; + lv_area_t img_area; + lv_draw_sw_blend_dsc_t blend_dsc = {0}; + blend_dsc.mask_buf = mask_buf; + blend_dsc.opa = dsc->opa; + blend_dsc.blend_area = &blend_area; + blend_dsc.mask_area = &blend_area; + lv_image_decoder_dsc_t decoder_dsc; + if(dsc->img_src == NULL) { + blend_dsc.color = dsc->color; } else { - angle_gap = start_angle - end_angle; + lv_image_decoder_open(&decoder_dsc, dsc->img_src, NULL); + img_area.x1 = 0; + img_area.y1 = 0; + img_area.x2 = decoder_dsc.decoded->header.w - 1; + img_area.y2 = decoder_dsc.decoded->header.h - 1; + int32_t ofs = decoder_dsc.decoded->header.w / 2; + lv_area_move(&img_area, dsc->center.x - ofs, dsc->center.y - ofs); + blend_dsc.src_area = &img_area; + blend_dsc.src_buf = decoder_dsc.decoded->data; + blend_dsc.src_color_format = decoder_dsc.decoded->header.cf; + blend_dsc.src_stride = decoder_dsc.decoded->header.stride; } - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - - if(angle_gap > SPLIT_ANGLE_GAP_LIMIT && radius > SPLIT_RADIUS_LIMIT) { - /*Handle each quarter individually and skip which is empty*/ - quarter_draw_dsc_t q_dsc; - q_dsc.center = center; - q_dsc.radius = radius; - q_dsc.start_angle = start_angle; - q_dsc.end_angle = end_angle; - q_dsc.start_quarter = (start_angle / 90) & 0x3; - q_dsc.end_quarter = (end_angle / 90) & 0x3; - q_dsc.width = width; - q_dsc.draw_dsc = &cir_dsc; - q_dsc.draw_area = &area_out; - q_dsc.draw_ctx = draw_ctx; - - draw_quarter_0(&q_dsc); - draw_quarter_1(&q_dsc); - draw_quarter_2(&q_dsc); - draw_quarter_3(&q_dsc); - } - else { - lv_draw_rect(draw_ctx, &cir_dsc, &area_out); - } - - lv_draw_mask_free_param(&mask_angle_param); - lv_draw_mask_free_param(&mask_out_param); - if(mask_in_param_valid) { - lv_draw_mask_free_param(&mask_in_param); - } - - lv_draw_mask_remove_id(mask_angle_id); - lv_draw_mask_remove_id(mask_out_id); - if(mask_in_id != LV_MASK_ID_INV) lv_draw_mask_remove_id(mask_in_id); - + lv_opa_t * circle_mask = NULL; + lv_area_t round_area_1; + lv_area_t round_area_2; if(dsc->rounded) { + circle_mask = lv_malloc(width * width); + lv_memset(circle_mask, 0xff, width * width); + lv_area_t circle_area = {0, 0, width - 1, width - 1}; + lv_draw_sw_mask_radius_param_t circle_mask_param; + lv_draw_sw_mask_radius_init(&circle_mask_param, &circle_area, width / 2, false); + void * circle_mask_list[2] = {&circle_mask_param, NULL}; - lv_draw_mask_radius_param_t mask_end_param; + lv_opa_t * circle_mask_tmp = circle_mask; + for(h = 0; h < width; h++) { + lv_draw_sw_mask_res_t res = lv_draw_sw_mask_apply(circle_mask_list, circle_mask_tmp, 0, h, width); + if(res == LV_DRAW_SW_MASK_RES_TRANSP) { + lv_memzero(circle_mask_tmp, width); + } - lv_area_t round_area; - get_rounded_area(start_angle, radius, width, &round_area); - round_area.x1 += center->x; - round_area.x2 += center->x; - round_area.y1 += center->y; - round_area.y2 += center->y; - lv_area_t clip_area2; - if(_lv_area_intersect(&clip_area2, clip_area_ori, &round_area)) { - lv_draw_mask_radius_init(&mask_end_param, &round_area, LV_RADIUS_CIRCLE, false); - int16_t mask_end_id = lv_draw_mask_add(&mask_end_param, NULL); - - draw_ctx->clip_area = &clip_area2; - lv_draw_rect(draw_ctx, &cir_dsc, &area_out); - lv_draw_mask_remove_id(mask_end_id); - lv_draw_mask_free_param(&mask_end_param); + circle_mask_tmp += width; } + get_rounded_area(start_angle, dsc->radius, width, &round_area_1); + lv_area_move(&round_area_1, dsc->center.x, dsc->center.y); + get_rounded_area(end_angle, dsc->radius, width, &round_area_2); + lv_area_move(&round_area_2, dsc->center.x, dsc->center.y); - get_rounded_area(end_angle, radius, width, &round_area); - round_area.x1 += center->x; - round_area.x2 += center->x; - round_area.y1 += center->y; - round_area.y2 += center->y; - if(_lv_area_intersect(&clip_area2, clip_area_ori, &round_area)) { - lv_draw_mask_radius_init(&mask_end_param, &round_area, LV_RADIUS_CIRCLE, false); - int16_t mask_end_id = lv_draw_mask_add(&mask_end_param, NULL); - - draw_ctx->clip_area = &clip_area2; - lv_draw_rect(draw_ctx, &cir_dsc, &area_out); - lv_draw_mask_remove_id(mask_end_id); - lv_draw_mask_free_param(&mask_end_param); - } - draw_ctx->clip_area = clip_area_ori; } + + blend_area.y2 = blend_area.y1; + for(h = 0; h < blend_h; h++) { + lv_memset(mask_buf, 0xff, blend_w); + blend_dsc.mask_res = lv_draw_sw_mask_apply(mask_list, mask_buf, blend_area.x1, blend_area.y1, blend_w); + + if(dsc->rounded) { + if(blend_area.y1 >= round_area_1.y1 && blend_area.y1 <= round_area_1.y2) { + if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_TRANSP) { + lv_memzero(mask_buf, blend_w); + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + } + add_circle(circle_mask, &blend_area, &round_area_1, mask_buf, width); + } + if(blend_area.y1 >= round_area_2.y1 && blend_area.y1 <= round_area_2.y2) { + if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_TRANSP) { + lv_memzero(mask_buf, blend_w); + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + } + add_circle(circle_mask, &blend_area, &round_area_2, mask_buf, width); + } + } + + lv_draw_sw_blend(draw_unit, &blend_dsc); + + blend_area.y1 ++; + blend_area.y2 ++; + } + + lv_draw_sw_mask_free_param(&mask_angle_param); + lv_draw_sw_mask_free_param(&mask_out_param); + if(mask_in_param_valid) { + lv_draw_sw_mask_free_param(&mask_in_param); + } + + lv_free(mask_buf); + if(dsc->img_src) lv_image_decoder_close(&decoder_dsc); + if(circle_mask) lv_free(circle_mask); #else - LV_LOG_WARN("Can't draw arc with LV_DRAW_COMPLEX == 0"); + LV_LOG_WARN("Can't draw arc with LV_DRAW_SW_COMPLEX == 0"); LV_UNUSED(center); LV_UNUSED(radius); LV_UNUSED(start_angle); LV_UNUSED(end_angle); - LV_UNUSED(draw_ctx); + LV_UNUSED(layer); LV_UNUSED(dsc); -#endif /*LV_DRAW_COMPLEX*/ +#endif /*LV_DRAW_SW_COMPLEX*/ } /********************** * STATIC FUNCTIONS **********************/ -#if LV_DRAW_COMPLEX -static void draw_quarter_0(quarter_draw_dsc_t * q) +static void add_circle(const lv_opa_t * circle_mask, const lv_area_t * blend_area, const lv_area_t * circle_area, + lv_opa_t * mask_buf, int32_t width) { - const lv_area_t * clip_area_ori = q->draw_ctx->clip_area; - lv_area_t quarter_area; + lv_area_t circle_common_area; + if(_lv_area_intersect(&circle_common_area, circle_area, blend_area)) { + const lv_opa_t * circle_mask_tmp = circle_mask + width * (circle_common_area.y1 - circle_area->y1); + circle_mask_tmp += circle_common_area.x1 - circle_area->x1; - if(q->start_quarter == 0 && q->end_quarter == 0 && q->start_angle < q->end_angle) { - /*Small arc here*/ - quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT); + lv_opa_t * mask_buf_tmp = mask_buf + circle_common_area.x1 - blend_area->x1; - quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * q->radius) >> LV_TRIGO_SHIFT); - quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); + uint32_t x; + uint32_t w = lv_area_get_width(&circle_common_area); + for(x = 0; x < w; x++) { + uint32_t res = mask_buf_tmp[x] + circle_mask_tmp[x]; + mask_buf_tmp[x] = res > 255 ? 255 : res; } } - else if(q->start_quarter == 0 || q->end_quarter == 0) { - /*Start and/or end arcs here*/ - if(q->start_quarter == 0) { - quarter_area.x1 = q->center->x; - quarter_area.y2 = q->center->y + q->radius; - quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT); - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); - } - } - if(q->end_quarter == 0) { - quarter_area.x2 = q->center->x + q->radius; - quarter_area.y1 = q->center->y; - - quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * q->radius) >> LV_TRIGO_SHIFT); - quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); - } - } - } - else if((q->start_quarter == q->end_quarter && q->start_quarter != 0 && q->end_angle < q->start_angle) || - (q->start_quarter == 2 && q->end_quarter == 1) || - (q->start_quarter == 3 && q->end_quarter == 2) || - (q->start_quarter == 3 && q->end_quarter == 1)) { - /*Arc crosses here*/ - quarter_area.x1 = q->center->x; - quarter_area.y1 = q->center->y; - quarter_area.x2 = q->center->x + q->radius; - quarter_area.y2 = q->center->y + q->radius; - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); - } - } - q->draw_ctx->clip_area = clip_area_ori; } -static void draw_quarter_1(quarter_draw_dsc_t * q) +static void get_rounded_area(int16_t angle, int32_t radius, uint8_t thickness, lv_area_t * res_area) { - const lv_area_t * clip_area_ori = q->draw_ctx->clip_area; - lv_area_t quarter_area; - - if(q->start_quarter == 1 && q->end_quarter == 1 && q->start_angle < q->end_angle) { - /*Small arc here*/ - quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT); - quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - - quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT); - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); - } - } - else if(q->start_quarter == 1 || q->end_quarter == 1) { - /*Start and/or end arcs here*/ - if(q->start_quarter == 1) { - quarter_area.x1 = q->center->x - q->radius; - quarter_area.y1 = q->center->y; - - quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT); - quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); - } - } - if(q->end_quarter == 1) { - quarter_area.x2 = q->center->x - 1; - quarter_area.y2 = q->center->y + q->radius; - - quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT); - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); - } - } - } - else if((q->start_quarter == q->end_quarter && q->start_quarter != 1 && q->end_angle < q->start_angle) || - (q->start_quarter == 0 && q->end_quarter == 2) || - (q->start_quarter == 0 && q->end_quarter == 3) || - (q->start_quarter == 3 && q->end_quarter == 2)) { - /*Arc crosses here*/ - quarter_area.x1 = q->center->x - q->radius; - quarter_area.y1 = q->center->y; - quarter_area.x2 = q->center->x - 1; - quarter_area.y2 = q->center->y + q->radius; - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); - } - } - q->draw_ctx->clip_area = clip_area_ori; -} - -static void draw_quarter_2(quarter_draw_dsc_t * q) -{ - const lv_area_t * clip_area_ori = q->draw_ctx->clip_area; - lv_area_t quarter_area; - - if(q->start_quarter == 2 && q->end_quarter == 2 && q->start_angle < q->end_angle) { - /*Small arc here*/ - quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT); - quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - - quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * q->radius) >> LV_TRIGO_SHIFT); - quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); - } - } - else if(q->start_quarter == 2 || q->end_quarter == 2) { - /*Start and/or end arcs here*/ - if(q->start_quarter == 2) { - quarter_area.x2 = q->center->x - 1; - quarter_area.y1 = q->center->y - q->radius; - - quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT); - quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); - } - } - if(q->end_quarter == 2) { - quarter_area.x1 = q->center->x - q->radius; - quarter_area.y2 = q->center->y - 1; - - quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius)) >> LV_TRIGO_SHIFT); - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); - } - } - } - else if((q->start_quarter == q->end_quarter && q->start_quarter != 2 && q->end_angle < q->start_angle) || - (q->start_quarter == 0 && q->end_quarter == 3) || - (q->start_quarter == 1 && q->end_quarter == 3) || - (q->start_quarter == 1 && q->end_quarter == 0)) { - /*Arc crosses here*/ - quarter_area.x1 = q->center->x - q->radius; - quarter_area.y1 = q->center->y - q->radius; - quarter_area.x2 = q->center->x - 1; - quarter_area.y2 = q->center->y - 1; - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); - } - } - q->draw_ctx->clip_area = clip_area_ori; -} - -static void draw_quarter_3(quarter_draw_dsc_t * q) -{ - const lv_area_t * clip_area_ori = q->draw_ctx->clip_area; - lv_area_t quarter_area; - - if(q->start_quarter == 3 && q->end_quarter == 3 && q->start_angle < q->end_angle) { - /*Small arc here*/ - quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT); - - quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT); - quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); - } - } - else if(q->start_quarter == 3 || q->end_quarter == 3) { - /*Start and/or end arcs here*/ - if(q->start_quarter == 3) { - quarter_area.x2 = q->center->x + q->radius; - quarter_area.y2 = q->center->y - 1; - - quarter_area.x1 = q->center->x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - quarter_area.y1 = q->center->y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT); - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); - } - } - if(q->end_quarter == 3) { - quarter_area.x1 = q->center->x; - quarter_area.y1 = q->center->y - q->radius; - - quarter_area.x2 = q->center->x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT); - quarter_area.y2 = q->center->y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT); - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); - } - } - } - else if((q->start_quarter == q->end_quarter && q->start_quarter != 3 && q->end_angle < q->start_angle) || - (q->start_quarter == 2 && q->end_quarter == 0) || - (q->start_quarter == 1 && q->end_quarter == 0) || - (q->start_quarter == 2 && q->end_quarter == 1)) { - /*Arc crosses here*/ - quarter_area.x1 = q->center->x; - quarter_area.y1 = q->center->y - q->radius; - quarter_area.x2 = q->center->x + q->radius; - quarter_area.y2 = q->center->y - 1; - - bool ok = _lv_area_intersect(&quarter_area, &quarter_area, clip_area_ori); - if(ok) { - q->draw_ctx->clip_area = &quarter_area; - lv_draw_rect(q->draw_ctx, q->draw_dsc, q->draw_area); - } - } - - q->draw_ctx->clip_area = clip_area_ori; -} - -static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t thickness, lv_area_t * res_area) -{ - const uint8_t ps = 8; - const uint8_t pa = 127; - int32_t thick_half = thickness / 2; uint8_t thick_corr = (thickness & 0x01) ? 0 : 1; int32_t cir_x; int32_t cir_y; - cir_x = ((radius - thick_half) * lv_trigo_sin(90 - angle)) >> (LV_TRIGO_SHIFT - ps); - cir_y = ((radius - thick_half) * lv_trigo_sin(angle)) >> (LV_TRIGO_SHIFT - ps); + cir_x = ((radius - thick_half) * lv_trigo_cos(angle)) >> (LV_TRIGO_SHIFT - 8); + cir_y = ((radius - thick_half) * lv_trigo_sin(angle)) >> (LV_TRIGO_SHIFT - 8); - /*Actually the center of the pixel need to be calculated so apply 1/2 px offset*/ + /*The center of the pixel need to be calculated so apply 1/2 px offset*/ if(cir_x > 0) { - cir_x = (cir_x - pa) >> ps; + cir_x = (cir_x - 128) >> 8; res_area->x1 = cir_x - thick_half + thick_corr; res_area->x2 = cir_x + thick_half; } else { - cir_x = (cir_x + pa) >> ps; + cir_x = (cir_x + 128) >> 8; res_area->x1 = cir_x - thick_half; res_area->x2 = cir_x + thick_half - thick_corr; } if(cir_y > 0) { - cir_y = (cir_y - pa) >> ps; + cir_y = (cir_y - 128) >> 8; res_area->y1 = cir_y - thick_half + thick_corr; res_area->y2 = cir_y + thick_half; } else { - cir_y = (cir_y + pa) >> ps; + cir_y = (cir_y + 128) >> 8; res_area->y1 = cir_y - thick_half; res_area->y2 = cir_y + thick_half - thick_corr; } } -#endif /*LV_DRAW_COMPLEX*/ +#endif /*LV_DRAW_SW_COMPLEX*/ +#endif /*LV_USE_DRAW_SW*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_blend.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_blend.c deleted file mode 100644 index a7c431370..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_blend.c +++ /dev/null @@ -1,1061 +0,0 @@ -/** - * @file lv_draw_sw_blend.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_draw_sw.h" -#include "../../misc/lv_math.h" -#include "../../hal/lv_hal_disp.h" -#include "../../core/lv_refr.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -static void fill_set_px(lv_color_t * dest_buf, const lv_area_t * blend_area, lv_coord_t dest_stride, - lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stide); - -static void /* LV_ATTRIBUTE_FAST_MEM */ fill_normal(lv_color_t * dest_buf, const lv_area_t * dest_area, - lv_coord_t dest_stride, lv_color_t color, lv_opa_t opa, - const lv_opa_t * mask, lv_coord_t mask_stride); - - -#if LV_COLOR_SCREEN_TRANSP -static void /* LV_ATTRIBUTE_FAST_MEM */ fill_argb(lv_color_t * dest_buf, const lv_area_t * dest_area, - lv_coord_t dest_stride, lv_color_t color, lv_opa_t opa, - const lv_opa_t * mask, lv_coord_t mask_stride); -#endif /*LV_COLOR_SCREEN_TRANSP*/ - -#if LV_DRAW_COMPLEX -static void fill_blended(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, lv_color_t color, - lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride, lv_blend_mode_t blend_mode); -#endif /*LV_DRAW_COMPLEX*/ - -static void map_set_px(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa, - const lv_opa_t * mask, lv_coord_t mask_stride); - -static void /* LV_ATTRIBUTE_FAST_MEM */ map_normal(lv_color_t * dest_buf, const lv_area_t * dest_area, - lv_coord_t dest_stride, const lv_color_t * src_buf, - lv_coord_t src_stride, lv_opa_t opa, const lv_opa_t * mask, - lv_coord_t mask_stride); - -#if LV_COLOR_SCREEN_TRANSP -static void /* LV_ATTRIBUTE_FAST_MEM */ map_argb(lv_color_t * dest_buf, const lv_area_t * dest_area, - lv_coord_t dest_stride, const lv_color_t * src_buf, - lv_coord_t src_stride, lv_opa_t opa, const lv_opa_t * mask, - lv_coord_t mask_stride, lv_blend_mode_t blend_mode); - -#endif /*LV_COLOR_SCREEN_TRANSP*/ - -#if LV_DRAW_COMPLEX -static void map_blended(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa, - const lv_opa_t * mask, lv_coord_t mask_stride, lv_blend_mode_t blend_mode); - -static inline lv_color_t color_blend_true_color_additive(lv_color_t fg, lv_color_t bg, lv_opa_t opa); -static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_color_t bg, lv_opa_t opa); -static inline lv_color_t color_blend_true_color_multiply(lv_color_t fg, lv_color_t bg, lv_opa_t opa); -#endif /*LV_DRAW_COMPLEX*/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ -#define FILL_NORMAL_MASK_PX(color) \ - if(*mask == LV_OPA_COVER) *dest_buf = color; \ - else *dest_buf = lv_color_mix(color, *dest_buf, *mask); \ - mask++; \ - dest_buf++; - -#define MAP_NORMAL_MASK_PX(x) \ - if(*mask_tmp_x) { \ - if(*mask_tmp_x == LV_OPA_COVER) dest_buf[x] = src_buf[x]; \ - else dest_buf[x] = lv_color_mix(src_buf[x], dest_buf[x], *mask_tmp_x); \ - } \ - mask_tmp_x++; - - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void lv_draw_sw_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc) -{ - /*Do not draw transparent things*/ - if(dsc->opa <= LV_OPA_MIN) return; - - lv_area_t blend_area; - if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return; - - if(draw_ctx->wait_for_finish) draw_ctx->wait_for_finish(draw_ctx); - - ((lv_draw_sw_ctx_t *)draw_ctx)->blend(draw_ctx, dsc); -} - -void LV_ATTRIBUTE_FAST_MEM lv_draw_sw_blend_basic(lv_draw_ctx_t * draw_ctx, - const lv_draw_sw_blend_dsc_t * dsc) -{ - lv_opa_t * mask; - if(dsc->mask_buf == NULL) mask = NULL; - if(dsc->mask_buf && dsc->mask_res == LV_DRAW_MASK_RES_TRANSP) return; - else if(dsc->mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask = NULL; - else mask = dsc->mask_buf; - - lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); - - lv_area_t blend_area; - if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return; - - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - lv_color_t * dest_buf = draw_ctx->buf; - if(disp->driver->set_px_cb == NULL) { - if(disp->driver->screen_transp == 0) { - dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + (blend_area.x1 - draw_ctx->buf_area->x1); - } - else { - /*With LV_COLOR_DEPTH 16 it means ARGB8565 (3 bytes format)*/ - uint8_t * dest_buf8 = (uint8_t *) dest_buf; - dest_buf8 += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) * LV_IMG_PX_SIZE_ALPHA_BYTE; - dest_buf8 += (blend_area.x1 - draw_ctx->buf_area->x1) * LV_IMG_PX_SIZE_ALPHA_BYTE; - dest_buf = (lv_color_t *)dest_buf8; - } - } - - const lv_color_t * src_buf = dsc->src_buf; - lv_coord_t src_stride; - if(src_buf) { - src_stride = lv_area_get_width(dsc->blend_area); - src_buf += src_stride * (blend_area.y1 - dsc->blend_area->y1) + (blend_area.x1 - dsc->blend_area->x1); - } - else { - src_stride = 0; - } - - lv_coord_t mask_stride; - if(mask) { - /*Round the values in the mask if anti-aliasing is disabled*/ - if(disp->driver->antialiasing == 0) { - int32_t mask_size = lv_area_get_size(dsc->mask_area); - int32_t i; - for(i = 0; i < mask_size; i++) { - mask[i] = mask[i] > 128 ? LV_OPA_COVER : LV_OPA_TRANSP; - } - } - - mask_stride = lv_area_get_width(dsc->mask_area); - mask += mask_stride * (blend_area.y1 - dsc->mask_area->y1) + (blend_area.x1 - dsc->mask_area->x1); - - } - else { - mask_stride = 0; - } - - lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - - - if(disp->driver->set_px_cb) { - if(dsc->src_buf == NULL) { - fill_set_px(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa, mask, mask_stride); - } - else { - map_set_px(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa, mask, mask_stride); - } - } -#if LV_COLOR_SCREEN_TRANSP - else if(disp->driver->screen_transp) { - if(dsc->src_buf == NULL) { - fill_argb(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa, mask, mask_stride); - } - else { - map_argb(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa, mask, mask_stride, dsc->blend_mode); - } - } -#endif - else if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { - if(dsc->src_buf == NULL) { - fill_normal(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa, mask, mask_stride); - } - else { - map_normal(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa, mask, mask_stride); - } - } - else { -#if LV_DRAW_COMPLEX - if(dsc->src_buf == NULL) { - fill_blended(dest_buf, &blend_area, dest_stride, dsc->color, dsc->opa, mask, mask_stride, dsc->blend_mode); - } - else { - map_blended(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa, mask, mask_stride, dsc->blend_mode); - } -#endif - } -} - - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void fill_set_px(lv_color_t * dest_buf, const lv_area_t * blend_area, lv_coord_t dest_stride, - lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stide) -{ - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - - int32_t x; - int32_t y; - - if(mask == NULL) { - for(y = blend_area->y1; y <= blend_area->y2; y++) { - for(x = blend_area->x1; x <= blend_area->x2; x++) { - disp->driver->set_px_cb(disp->driver, (void *)dest_buf, dest_stride, x, y, color, opa); - } - } - } - else { - int32_t w = lv_area_get_width(blend_area); - int32_t h = lv_area_get_height(blend_area); - - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - if(mask[x]) { - - - disp->driver->set_px_cb(disp->driver, (void *)dest_buf, dest_stride, blend_area->x1 + x, blend_area->y1 + y, color, - (uint32_t)((uint32_t)opa * mask[x]) >> 8); - } - } - mask += mask_stide; - } - } -} - -static LV_ATTRIBUTE_FAST_MEM void fill_normal(lv_color_t * dest_buf, const lv_area_t * dest_area, - lv_coord_t dest_stride, lv_color_t color, lv_opa_t opa, - const lv_opa_t * mask, lv_coord_t mask_stride) -{ - int32_t w = lv_area_get_width(dest_area); - int32_t h = lv_area_get_height(dest_area); - - int32_t x; - int32_t y; - - /*No mask*/ - if(mask == NULL) { - if(opa >= LV_OPA_MAX) { - for(y = 0; y < h; y++) { - lv_color_fill(dest_buf, color, w); - dest_buf += dest_stride; - } - } - /*Has opacity*/ - else { - lv_color_t last_dest_color = lv_color_black(); - lv_color_t last_res_color = lv_color_mix(color, last_dest_color, opa); - -#if LV_COLOR_MIX_ROUND_OFS == 0 && LV_COLOR_DEPTH == 16 - /*lv_color_mix work with an optimized algorithm with 16 bit color depth. - *However, it introduces some rounded error on opa. - *Introduce the same error here too to make lv_color_premult produces the same result */ - opa = (uint32_t)((uint32_t)opa + 4) >> 3; - opa = opa << 3; -#endif - - uint16_t color_premult[3]; - lv_color_premult(color, opa, color_premult); - lv_opa_t opa_inv = 255 - opa; - - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - if(last_dest_color.full != dest_buf[x].full) { - last_dest_color = dest_buf[x]; - last_res_color = lv_color_mix_premult(color_premult, dest_buf[x], opa_inv); - } - dest_buf[x] = last_res_color; - } - dest_buf += dest_stride; - } - } - } - /*Masked*/ - else { -#if LV_COLOR_DEPTH == 16 - uint32_t c32 = color.full + ((uint32_t)color.full << 16); -#endif - /*Only the mask matters*/ - if(opa >= LV_OPA_MAX) { - int32_t x_end4 = w - 4; - for(y = 0; y < h; y++) { - for(x = 0; x < w && ((lv_uintptr_t)(mask) & 0x3); x++) { - FILL_NORMAL_MASK_PX(color) - } - - for(; x <= x_end4; x += 4) { - uint32_t mask32 = *((uint32_t *)mask); - if(mask32 == 0xFFFFFFFF) { -#if LV_COLOR_DEPTH == 16 - if((lv_uintptr_t)dest_buf & 0x3) { - *(dest_buf + 0) = color; - uint32_t * d = (uint32_t *)(dest_buf + 1); - *d = c32; - *(dest_buf + 3) = color; - } - else { - uint32_t * d = (uint32_t *)dest_buf; - *d = c32; - *(d + 1) = c32; - } -#else - dest_buf[0] = color; - dest_buf[1] = color; - dest_buf[2] = color; - dest_buf[3] = color; -#endif - dest_buf += 4; - mask += 4; - } - else if(mask32) { - FILL_NORMAL_MASK_PX(color) - FILL_NORMAL_MASK_PX(color) - FILL_NORMAL_MASK_PX(color) - FILL_NORMAL_MASK_PX(color) - } - else { - mask += 4; - dest_buf += 4; - } - } - - for(; x < w ; x++) { - FILL_NORMAL_MASK_PX(color) - } - dest_buf += (dest_stride - w); - mask += (mask_stride - w); - } - } - /*With opacity*/ - else { - /*Buffer the result color to avoid recalculating the same color*/ - lv_color_t last_dest_color; - lv_color_t last_res_color; - lv_opa_t last_mask = LV_OPA_TRANSP; - last_dest_color.full = dest_buf[0].full; - last_res_color.full = dest_buf[0].full; - lv_opa_t opa_tmp = LV_OPA_TRANSP; - - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - if(*mask) { - if(*mask != last_mask) opa_tmp = *mask == LV_OPA_COVER ? opa : - (uint32_t)((uint32_t)(*mask) * opa) >> 8; - if(*mask != last_mask || last_dest_color.full != dest_buf[x].full) { - if(opa_tmp == LV_OPA_COVER) last_res_color = color; - else last_res_color = lv_color_mix(color, dest_buf[x], opa_tmp); - last_mask = *mask; - last_dest_color.full = dest_buf[x].full; - } - dest_buf[x] = last_res_color; - } - mask++; - } - dest_buf += dest_stride; - mask += (mask_stride - w); - } - } - } -} - -#if LV_COLOR_SCREEN_TRANSP -static inline void set_px_argb(uint8_t * buf, lv_color_t color, lv_opa_t opa) -{ - lv_color_t bg_color; - lv_color_t res_color; - lv_opa_t bg_opa = buf[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; -#if LV_COLOR_DEPTH == 8 - bg_color.full = buf[0]; - lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &buf[1]); - if(buf[1] <= LV_OPA_MIN) return; - buf[0] = res_color.full; -#elif LV_COLOR_DEPTH == 16 - bg_color.full = buf[0] + (buf[1] << 8); - lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &buf[2]); - if(buf[2] <= LV_OPA_MIN) return; - buf[0] = res_color.full & 0xff; - buf[1] = res_color.full >> 8; -#elif LV_COLOR_DEPTH == 32 - bg_color = *((lv_color_t *)buf); - lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &buf[3]); - if(buf[3] <= LV_OPA_MIN) return; - buf[0] = res_color.ch.blue; - buf[1] = res_color.ch.green; - buf[2] = res_color.ch.red; -#endif -} - -static inline void set_px_argb_blend(uint8_t * buf, lv_color_t color, lv_opa_t opa, lv_color_t (*blend_fp)(lv_color_t, - lv_color_t, lv_opa_t)) -{ - static lv_color_t last_dest_color; - static lv_color_t last_src_color; - static lv_color_t last_res_color; - static uint32_t last_opa = 0xffff; /*Set to an invalid value for first*/ - - lv_color_t bg_color; - - /*Get the BG color*/ -#if LV_COLOR_DEPTH == 8 - if(buf[1] <= LV_OPA_MIN) return; - bg_color.full = buf[0]; -#elif LV_COLOR_DEPTH == 16 - if(buf[2] <= LV_OPA_MIN) return; - bg_color.full = buf[0] + (buf[1] << 8); -#elif LV_COLOR_DEPTH == 32 - if(buf[3] <= LV_OPA_MIN) return; - bg_color = *((lv_color_t *)buf); -#endif - - /*Get the result color*/ - if(last_dest_color.full != bg_color.full || last_src_color.full != color.full || last_opa != opa) { - last_dest_color = bg_color; - last_src_color = color; - last_opa = opa; - last_res_color = blend_fp(last_src_color, last_dest_color, last_opa); - } - - /*Set the result color*/ -#if LV_COLOR_DEPTH == 8 - buf[0] = last_res_color.full; -#elif LV_COLOR_DEPTH == 16 - buf[0] = last_res_color.full & 0xff; - buf[1] = last_res_color.full >> 8; -#elif LV_COLOR_DEPTH == 32 - buf[0] = last_res_color.ch.blue; - buf[1] = last_res_color.ch.green; - buf[2] = last_res_color.ch.red; -#endif - -} - -static void LV_ATTRIBUTE_FAST_MEM fill_argb(lv_color_t * dest_buf, const lv_area_t * dest_area, - lv_coord_t dest_stride, lv_color_t color, lv_opa_t opa, - const lv_opa_t * mask, lv_coord_t mask_stride) -{ - uint8_t * dest_buf8 = (uint8_t *) dest_buf; - int32_t w = lv_area_get_width(dest_area); - int32_t h = lv_area_get_height(dest_area); - - int32_t x; - int32_t y; - - uint8_t ctmp[LV_IMG_PX_SIZE_ALPHA_BYTE]; - lv_memcpy(ctmp, &color, sizeof(lv_color_t)); - ctmp[LV_IMG_PX_SIZE_ALPHA_BYTE - 1] = opa; - - /*No mask*/ - if(mask == NULL) { - if(opa >= LV_OPA_MAX) { - for(x = 0; x < w; x++) { - lv_memcpy(dest_buf8, ctmp, LV_IMG_PX_SIZE_ALPHA_BYTE); - dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; - } - - dest_buf8 += (dest_stride - w) * LV_IMG_PX_SIZE_ALPHA_BYTE; - - for(y = 1; y < h; y++) { - lv_memcpy(dest_buf8, (uint8_t *) dest_buf, w * LV_IMG_PX_SIZE_ALPHA_BYTE); - dest_buf8 += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; - } - } - /*Has opacity*/ - else { - uint8_t * dest_buf8_row = dest_buf8; - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - set_px_argb(dest_buf8, color, opa); - dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; - } - dest_buf8_row += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; - dest_buf8 = dest_buf8_row; - } - } - } - /*Masked*/ - else { - /*Only the mask matters*/ - if(opa >= LV_OPA_MAX) { - uint8_t * dest_buf8_row = dest_buf8; - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - set_px_argb(dest_buf8, color, *mask); - mask++; - dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; - } - dest_buf8_row += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; - dest_buf8 = dest_buf8_row; - } - } - /*With opacity*/ - else { - /*Buffer the result color to avoid recalculating the same color*/ - lv_opa_t last_mask = LV_OPA_TRANSP; - lv_opa_t opa_tmp = LV_OPA_TRANSP; - - uint8_t * dest_buf8_row = dest_buf8; - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - if(*mask) { - if(*mask != last_mask) opa_tmp = *mask == LV_OPA_COVER ? opa : - (uint32_t)((uint32_t)(*mask) * opa) >> 8; - - set_px_argb(dest_buf8, color, opa_tmp); - } - dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; - mask++; - } - dest_buf8_row += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; - dest_buf8 = dest_buf8_row; - mask += (mask_stride - w); - } - } - } -} -#endif - -#if LV_DRAW_COMPLEX -static void fill_blended(lv_color_t * dest_buf, const lv_area_t * dest_area, - lv_coord_t dest_stride, lv_color_t color, lv_opa_t opa, const lv_opa_t * mask, lv_coord_t mask_stride, - lv_blend_mode_t blend_mode) -{ - - int32_t w = lv_area_get_width(dest_area); - int32_t h = lv_area_get_height(dest_area); - - int32_t x; - int32_t y; - - lv_color_t (*blend_fp)(lv_color_t, lv_color_t, lv_opa_t); - switch(blend_mode) { - case LV_BLEND_MODE_ADDITIVE: - blend_fp = color_blend_true_color_additive; - break; - case LV_BLEND_MODE_SUBTRACTIVE: - blend_fp = color_blend_true_color_subtractive; - break; - case LV_BLEND_MODE_MULTIPLY: - blend_fp = color_blend_true_color_multiply; - break; - default: - LV_LOG_WARN("fill_blended: unsupported blend mode"); - return; - } - - /*Simple fill (maybe with opacity), no masking*/ - if(mask == NULL) { - lv_color_t last_dest_color = dest_buf[0]; - lv_color_t last_res_color = blend_fp(color, dest_buf[0], opa); - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - if(last_dest_color.full != dest_buf[x].full) { - last_dest_color = dest_buf[x]; - last_res_color = blend_fp(color, dest_buf[x], opa); - } - dest_buf[x] = last_res_color; - } - dest_buf += dest_stride; - } - } - /*Masked*/ - else { - /*Buffer the result color to avoid recalculating the same color*/ - lv_color_t last_dest_color; - lv_color_t last_res_color; - lv_opa_t last_mask = LV_OPA_TRANSP; - last_dest_color = dest_buf[0]; - lv_opa_t opa_tmp = mask[0] >= LV_OPA_MAX ? opa : (uint32_t)((uint32_t)mask[0] * opa) >> 8; - last_res_color = blend_fp(color, last_dest_color, opa_tmp); - - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - if(mask[x] == 0) continue; - if(mask[x] != last_mask || last_dest_color.full != dest_buf[x].full) { - opa_tmp = mask[x] >= LV_OPA_MAX ? opa : (uint32_t)((uint32_t)mask[x] * opa) >> 8; - - last_res_color = blend_fp(color, dest_buf[x], opa_tmp); - last_mask = mask[x]; - last_dest_color.full = dest_buf[x].full; - } - dest_buf[x] = last_res_color; - } - dest_buf += dest_stride; - mask += mask_stride; - } - } -} -#endif - -static void map_set_px(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa, - const lv_opa_t * mask, lv_coord_t mask_stride) - -{ - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - - int32_t w = lv_area_get_width(dest_area); - int32_t h = lv_area_get_height(dest_area); - - int32_t x; - int32_t y; - - if(mask == NULL) { - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - disp->driver->set_px_cb(disp->driver, (void *)dest_buf, dest_stride, dest_area->x1 + x, dest_area->y1 + y, src_buf[x], - opa); - } - src_buf += src_stride; - } - } - else { - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - if(mask[x]) { - disp->driver->set_px_cb(disp->driver, (void *)dest_buf, dest_stride, dest_area->x1 + x, dest_area->y1 + y, src_buf[x], - (uint32_t)((uint32_t)opa * mask[x]) >> 8); - } - } - mask += mask_stride; - src_buf += src_stride; - } - } -} - -static void LV_ATTRIBUTE_FAST_MEM map_normal(lv_color_t * dest_buf, const lv_area_t * dest_area, - lv_coord_t dest_stride, const lv_color_t * src_buf, - lv_coord_t src_stride, lv_opa_t opa, const lv_opa_t * mask, - lv_coord_t mask_stride) - -{ - int32_t w = lv_area_get_width(dest_area); - int32_t h = lv_area_get_height(dest_area); - - int32_t x; - int32_t y; - - /*Simple fill (maybe with opacity), no masking*/ - if(mask == NULL) { - if(opa >= LV_OPA_MAX) { - for(y = 0; y < h; y++) { - lv_memcpy(dest_buf, src_buf, w * sizeof(lv_color_t)); - dest_buf += dest_stride; - src_buf += src_stride; - } - } - else { - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - dest_buf[x] = lv_color_mix(src_buf[x], dest_buf[x], opa); - } - dest_buf += dest_stride; - src_buf += src_stride; - } - } - } - /*Masked*/ - else { - /*Only the mask matters*/ - if(opa > LV_OPA_MAX) { - int32_t x_end4 = w - 4; - - for(y = 0; y < h; y++) { - const lv_opa_t * mask_tmp_x = mask; -#if 0 - for(x = 0; x < w; x++) { - MAP_NORMAL_MASK_PX(x); - } -#else - for(x = 0; x < w && ((lv_uintptr_t)mask_tmp_x & 0x3); x++) { - MAP_NORMAL_MASK_PX(x) - } - - uint32_t * mask32 = (uint32_t *)mask_tmp_x; - for(; x < x_end4; x += 4) { - if(*mask32) { - if((*mask32) == 0xFFFFFFFF) { - dest_buf[x] = src_buf[x]; - dest_buf[x + 1] = src_buf[x + 1]; - dest_buf[x + 2] = src_buf[x + 2]; - dest_buf[x + 3] = src_buf[x + 3]; - } - else { - mask_tmp_x = (const lv_opa_t *)mask32; - MAP_NORMAL_MASK_PX(x) - MAP_NORMAL_MASK_PX(x + 1) - MAP_NORMAL_MASK_PX(x + 2) - MAP_NORMAL_MASK_PX(x + 3) - } - } - mask32++; - } - - mask_tmp_x = (const lv_opa_t *)mask32; - for(; x < w ; x++) { - MAP_NORMAL_MASK_PX(x) - } -#endif - dest_buf += dest_stride; - src_buf += src_stride; - mask += mask_stride; - } - } - /*Handle opa and mask values too*/ - else { - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - if(mask[x]) { - lv_opa_t opa_tmp = mask[x] >= LV_OPA_MAX ? opa : ((opa * mask[x]) >> 8); - dest_buf[x] = lv_color_mix(src_buf[x], dest_buf[x], opa_tmp); - } - } - dest_buf += dest_stride; - src_buf += src_stride; - mask += mask_stride; - } - } - } -} - - - -#if LV_COLOR_SCREEN_TRANSP -static void LV_ATTRIBUTE_FAST_MEM map_argb(lv_color_t * dest_buf, const lv_area_t * dest_area, - lv_coord_t dest_stride, const lv_color_t * src_buf, - lv_coord_t src_stride, lv_opa_t opa, const lv_opa_t * mask, - lv_coord_t mask_stride, lv_blend_mode_t blend_mode) - -{ - uint8_t * dest_buf8 = (uint8_t *) dest_buf; - - int32_t w = lv_area_get_width(dest_area); - int32_t h = lv_area_get_height(dest_area); - - int32_t x; - int32_t y; - - lv_color_t (*blend_fp)(lv_color_t, lv_color_t, lv_opa_t); - switch(blend_mode) { - case LV_BLEND_MODE_ADDITIVE: - blend_fp = color_blend_true_color_additive; - break; - case LV_BLEND_MODE_SUBTRACTIVE: - blend_fp = color_blend_true_color_subtractive; - break; - case LV_BLEND_MODE_MULTIPLY: - blend_fp = color_blend_true_color_multiply; - break; - default: - blend_fp = NULL; - } - - /*Simple fill (maybe with opacity), no masking*/ - if(mask == NULL) { - if(opa >= LV_OPA_MAX) { - if(blend_fp == NULL && LV_COLOR_DEPTH == 32) { - for(y = 0; y < h; y++) { - lv_memcpy(dest_buf, src_buf, w * sizeof(lv_color_t)); - dest_buf += dest_stride; - src_buf += src_stride; - } - } - else { - uint8_t * dest_buf8_row = dest_buf8; - for(y = 0; y < h; y++) { - if(blend_fp == NULL) { - for(x = 0; x < w; x++) { - set_px_argb(dest_buf8, src_buf[x], LV_OPA_COVER); - dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; - } - } - else { - for(x = 0; x < w; x++) { - set_px_argb_blend(dest_buf8, src_buf[x], LV_OPA_COVER, blend_fp); - dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; - } - } - - dest_buf8_row += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; - dest_buf8 = dest_buf8_row; - src_buf += src_stride; - } - } - } - /*No mask but opacity*/ - else { - uint8_t * dest_buf8_row = dest_buf8; - for(y = 0; y < h; y++) { - if(blend_fp == NULL) { - for(x = 0; x < w; x++) { - set_px_argb(dest_buf8, src_buf[x], opa); - dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; - } - } - else { - for(x = 0; x < w; x++) { - set_px_argb_blend(dest_buf8, src_buf[x], opa, blend_fp); - dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; - } - } - - dest_buf8_row += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; - dest_buf8 = dest_buf8_row; - src_buf += src_stride; - } - } - } - /*Masked*/ - else { - /*Only the mask matters*/ - if(opa > LV_OPA_MAX) { - uint8_t * dest_buf8_row = dest_buf8; - for(y = 0; y < h; y++) { - if(blend_fp == NULL) { - for(x = 0; x < w; x++) { - set_px_argb(dest_buf8, src_buf[x], mask[x]); - dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; - } - } - else { - for(x = 0; x < w; x++) { - set_px_argb_blend(dest_buf8, src_buf[x], mask[x], blend_fp); - dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; - } - } - dest_buf8_row += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; - dest_buf8 = dest_buf8_row; - src_buf += src_stride; - mask += mask_stride; - } - } - /*Handle opa and mask values too*/ - else { - uint8_t * dest_buf8_row = dest_buf8; - for(y = 0; y < h; y++) { - if(blend_fp == NULL) { - for(x = 0; x < w; x++) { - if(mask[x]) { - lv_opa_t opa_tmp = mask[x] >= LV_OPA_MAX ? opa : ((opa * mask[x]) >> 8); - set_px_argb(dest_buf8, src_buf[x], opa_tmp); - } - dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; - } - } - else { - for(x = 0; x < w; x++) { - if(mask[x]) { - lv_opa_t opa_tmp = mask[x] >= LV_OPA_MAX ? opa : ((opa * mask[x]) >> 8); - set_px_argb_blend(dest_buf8, src_buf[x], opa_tmp, blend_fp); - } - dest_buf8 += LV_IMG_PX_SIZE_ALPHA_BYTE; - } - } - dest_buf8_row += dest_stride * LV_IMG_PX_SIZE_ALPHA_BYTE; - dest_buf8 = dest_buf8_row; - src_buf += src_stride; - mask += mask_stride; - } - } - } -} -#endif - - -#if LV_DRAW_COMPLEX -static void map_blended(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa, - const lv_opa_t * mask, lv_coord_t mask_stride, lv_blend_mode_t blend_mode) -{ - - int32_t w = lv_area_get_width(dest_area); - int32_t h = lv_area_get_height(dest_area); - - int32_t x; - int32_t y; - - lv_color_t (*blend_fp)(lv_color_t, lv_color_t, lv_opa_t); - switch(blend_mode) { - case LV_BLEND_MODE_ADDITIVE: - blend_fp = color_blend_true_color_additive; - break; - case LV_BLEND_MODE_SUBTRACTIVE: - blend_fp = color_blend_true_color_subtractive; - break; - case LV_BLEND_MODE_MULTIPLY: - blend_fp = color_blend_true_color_multiply; - break; - default: - LV_LOG_WARN("fill_blended: unsupported blend mode"); - return; - } - - lv_color_t last_dest_color; - lv_color_t last_src_color; - /*Simple fill (maybe with opacity), no masking*/ - if(mask == NULL) { - last_dest_color = dest_buf[0]; - last_src_color = src_buf[0]; - lv_color_t last_res_color = blend_fp(last_src_color, last_dest_color, opa); - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - if(last_src_color.full != src_buf[x].full || last_dest_color.full != dest_buf[x].full) { - last_dest_color = dest_buf[x]; - last_src_color = src_buf[x]; - last_res_color = blend_fp(last_src_color, last_dest_color, opa); - } - dest_buf[x] = last_res_color; - } - dest_buf += dest_stride; - src_buf += src_stride; - } - } - /*Masked*/ - else { - last_dest_color = dest_buf[0]; - last_src_color = src_buf[0]; - lv_opa_t last_opa = mask[0] >= LV_OPA_MAX ? opa : ((opa * mask[0]) >> 8); - lv_color_t last_res_color = blend_fp(last_src_color, last_dest_color, last_opa); - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - if(mask[x] == 0) continue; - lv_opa_t opa_tmp = mask[x] >= LV_OPA_MAX ? opa : ((opa * mask[x]) >> 8); - if(last_src_color.full != src_buf[x].full || last_dest_color.full != dest_buf[x].full || last_opa != opa_tmp) { - last_dest_color = dest_buf[x]; - last_src_color = src_buf[x]; - last_opa = opa_tmp; - last_res_color = blend_fp(last_src_color, last_dest_color, last_opa); - } - dest_buf[x] = last_res_color; - } - dest_buf += dest_stride; - src_buf += src_stride; - mask += mask_stride; - } - } -} - -static inline lv_color_t color_blend_true_color_additive(lv_color_t fg, lv_color_t bg, lv_opa_t opa) -{ - - if(opa <= LV_OPA_MIN) return bg; - - uint32_t tmp; -#if LV_COLOR_DEPTH == 1 - tmp = bg.full + fg.full; - fg.full = LV_MIN(tmp, 1); -#else - tmp = bg.ch.red + fg.ch.red; -#if LV_COLOR_DEPTH == 8 - fg.ch.red = LV_MIN(tmp, 7); -#elif LV_COLOR_DEPTH == 16 - fg.ch.red = LV_MIN(tmp, 31); -#elif LV_COLOR_DEPTH == 32 - fg.ch.red = LV_MIN(tmp, 255); -#endif - -#if LV_COLOR_DEPTH == 8 - tmp = bg.ch.green + fg.ch.green; - fg.ch.green = LV_MIN(tmp, 7); -#elif LV_COLOR_DEPTH == 16 -#if LV_COLOR_16_SWAP == 0 - tmp = bg.ch.green + fg.ch.green; - fg.ch.green = LV_MIN(tmp, 63); -#else - tmp = (bg.ch.green_h << 3) + bg.ch.green_l + (fg.ch.green_h << 3) + fg.ch.green_l; - tmp = LV_MIN(tmp, 63); - fg.ch.green_h = tmp >> 3; - fg.ch.green_l = tmp & 0x7; -#endif - -#elif LV_COLOR_DEPTH == 32 - tmp = bg.ch.green + fg.ch.green; - fg.ch.green = LV_MIN(tmp, 255); -#endif - - tmp = bg.ch.blue + fg.ch.blue; -#if LV_COLOR_DEPTH == 8 - fg.ch.blue = LV_MIN(tmp, 4); -#elif LV_COLOR_DEPTH == 16 - fg.ch.blue = LV_MIN(tmp, 31); -#elif LV_COLOR_DEPTH == 32 - fg.ch.blue = LV_MIN(tmp, 255); -#endif -#endif - - if(opa == LV_OPA_COVER) return fg; - - return lv_color_mix(fg, bg, opa); -} - -static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_color_t bg, lv_opa_t opa) -{ - if(opa <= LV_OPA_MIN) return bg; - - int32_t tmp; - tmp = bg.ch.red - fg.ch.red; - fg.ch.red = LV_MAX(tmp, 0); - -#if LV_COLOR_16_SWAP == 0 - tmp = bg.ch.green - fg.ch.green; - fg.ch.green = LV_MAX(tmp, 0); -#else - tmp = (bg.ch.green_h << 3) + bg.ch.green_l + (fg.ch.green_h << 3) + fg.ch.green_l; - tmp = LV_MAX(tmp, 0); - fg.ch.green_h = tmp >> 3; - fg.ch.green_l = tmp & 0x7; -#endif - - tmp = bg.ch.blue - fg.ch.blue; - fg.ch.blue = LV_MAX(tmp, 0); - - if(opa == LV_OPA_COVER) return fg; - - return lv_color_mix(fg, bg, opa); -} - -static inline lv_color_t color_blend_true_color_multiply(lv_color_t fg, lv_color_t bg, lv_opa_t opa) -{ - if(opa <= LV_OPA_MIN) return bg; - -#if LV_COLOR_DEPTH == 32 - fg.ch.red = (fg.ch.red * bg.ch.red) >> 8; - fg.ch.green = (fg.ch.green * bg.ch.green) >> 8; - fg.ch.blue = (fg.ch.blue * bg.ch.blue) >> 8; -#elif LV_COLOR_DEPTH == 16 - fg.ch.red = (fg.ch.red * bg.ch.red) >> 5; - fg.ch.blue = (fg.ch.blue * bg.ch.blue) >> 5; - LV_COLOR_SET_G(fg, (LV_COLOR_GET_G(fg) * LV_COLOR_GET_G(bg)) >> 6); -#elif LV_COLOR_DEPTH == 8 - fg.ch.red = (fg.ch.red * bg.ch.red) >> 3; - fg.ch.green = (fg.ch.green * bg.ch.green) >> 3; - fg.ch.blue = (fg.ch.blue * bg.ch.blue) >> 2; -#endif - - if(opa == LV_OPA_COVER) return fg; - - return lv_color_mix(fg, bg, opa); -} - -#endif - diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_blend.h b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_blend.h deleted file mode 100644 index 3158d985c..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_blend.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @file lv_draw_sw_blend.h - * - */ - -#ifndef LV_DRAW_SW_BLEND_H -#define LV_DRAW_SW_BLEND_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../misc/lv_color.h" -#include "../../misc/lv_area.h" -#include "../../misc/lv_style.h" -#include "../lv_draw_mask.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - const lv_area_t * blend_area; /**< The area with absolute coordinates to draw on `draw_ctx->buf` - * will be clipped to `draw_ctx->clip_area` */ - const lv_color_t * src_buf; /**< Pointer to an image to blend. If set `fill_color` is ignored */ - lv_color_t color; /**< Fill color*/ - lv_opa_t * mask_buf; /**< NULL if ignored, or an alpha mask to apply on `blend_area`*/ - lv_draw_mask_res_t mask_res; /**< The result of the previous mask operation */ - const lv_area_t * mask_area; /**< The area of `mask_buf` with absolute coordinates*/ - lv_opa_t opa; /**< The overall opacity*/ - lv_blend_mode_t blend_mode; /**< E.g. LV_BLEND_MODE_ADDITIVE*/ -} lv_draw_sw_blend_dsc_t; - -struct _lv_draw_ctx_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Call the blend function of the `draw_ctx`. - * @param draw_ctx pointer to a draw context - * @param dsc pointer to an initialized blend descriptor - */ -void lv_draw_sw_blend(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); - -/** - * The basic blend function used with software rendering. - * @param draw_ctx pointer to a draw context - * @param dsc pointer to an initialized blend descriptor - */ -void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_sw_blend_basic(struct _lv_draw_ctx_t * draw_ctx, - const lv_draw_sw_blend_dsc_t * dsc); - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_DRAW_SW_BLEND_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_border.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_border.c new file mode 100644 index 000000000..c7f11919d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_border.c @@ -0,0 +1,332 @@ +/** + * @file lv_draw_sw_border.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_sw.h" +#if LV_USE_DRAW_SW + +#include "blend/lv_draw_sw_blend.h" +#include "../../misc/lv_math.h" +#include "../../misc/lv_text_ap.h" +#include "../../core/lv_refr.h" +#include "../../misc/lv_assert.h" +#include "../../stdlib/lv_string.h" +#include "../lv_draw_mask.h" + +/********************* + * DEFINES + *********************/ +#define SPLIT_LIMIT 50 + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void draw_border_complex(lv_draw_unit_t * draw_unit, const lv_area_t * outer_area, const lv_area_t * inner_area, + int32_t rout, int32_t rin, lv_color_t color, lv_opa_t opa); + +static void draw_border_simple(lv_draw_unit_t * draw_unit, const lv_area_t * outer_area, const lv_area_t * inner_area, + lv_color_t color, lv_opa_t opa); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_sw_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) return; + if(dsc->width == 0) return; + if(dsc->side == LV_BORDER_SIDE_NONE) return; + + int32_t coords_w = lv_area_get_width(coords); + int32_t coords_h = lv_area_get_height(coords); + int32_t rout = dsc->radius; + int32_t short_side = LV_MIN(coords_w, coords_h); + if(rout > short_side >> 1) rout = short_side >> 1; + + /*Get the inner area*/ + lv_area_t area_inner; + lv_area_copy(&area_inner, coords); + area_inner.x1 += ((dsc->side & LV_BORDER_SIDE_LEFT) ? dsc->width : - (dsc->width + rout)); + area_inner.x2 -= ((dsc->side & LV_BORDER_SIDE_RIGHT) ? dsc->width : - (dsc->width + rout)); + area_inner.y1 += ((dsc->side & LV_BORDER_SIDE_TOP) ? dsc->width : - (dsc->width + rout)); + area_inner.y2 -= ((dsc->side & LV_BORDER_SIDE_BOTTOM) ? dsc->width : - (dsc->width + rout)); + + int32_t rin = rout - dsc->width; + if(rin < 0) rin = 0; + + if(rout == 0 && rin == 0) { + draw_border_simple(draw_unit, coords, &area_inner, dsc->color, dsc->opa); + } + else { + draw_border_complex(draw_unit, coords, &area_inner, rout, rin, dsc->color, dsc->opa); + } + +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +void draw_border_complex(lv_draw_unit_t * draw_unit, const lv_area_t * outer_area, const lv_area_t * inner_area, + int32_t rout, int32_t rin, lv_color_t color, lv_opa_t opa) +{ +#if LV_DRAW_SW_COMPLEX + /*Get clipped draw area which is the real draw area. + *It is always the same or inside `coords`*/ + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, outer_area, draw_unit->clip_area)) return; + int32_t draw_area_w = lv_area_get_width(&draw_area); + + lv_draw_sw_blend_dsc_t blend_dsc; + lv_memzero(&blend_dsc, sizeof(blend_dsc)); + lv_opa_t * mask_buf = lv_malloc(draw_area_w); + blend_dsc.mask_buf = mask_buf; + + void * mask_list[3] = {0}; + + /*Create mask for the inner mask*/ + lv_draw_sw_mask_radius_param_t mask_rin_param; + lv_draw_sw_mask_radius_init(&mask_rin_param, inner_area, rin, true); + mask_list[0] = &mask_rin_param; + + /*Create mask for the outer area*/ + lv_draw_sw_mask_radius_param_t mask_rout_param; + if(rout > 0) { + lv_draw_sw_mask_radius_init(&mask_rout_param, outer_area, rout, false); + mask_list[1] = &mask_rout_param; + } + + int32_t h; + lv_area_t blend_area; + blend_dsc.blend_area = &blend_area; + blend_dsc.mask_area = &blend_area; + blend_dsc.color = color; + blend_dsc.opa = opa; + + /*Calculate the x and y coordinates where the straight parts area is*/ + lv_area_t core_area; + core_area.x1 = LV_MAX(outer_area->x1 + rout, inner_area->x1); + core_area.x2 = LV_MIN(outer_area->x2 - rout, inner_area->x2); + core_area.y1 = LV_MAX(outer_area->y1 + rout, inner_area->y1); + core_area.y2 = LV_MIN(outer_area->y2 - rout, inner_area->y2); + int32_t core_w = lv_area_get_width(&core_area); + + bool top_side = outer_area->y1 <= inner_area->y1; + bool bottom_side = outer_area->y2 >= inner_area->y2; + + /*No masks*/ + bool left_side = outer_area->x1 <= inner_area->x1; + bool right_side = outer_area->x2 >= inner_area->x2; + + bool split_hor = true; + if(left_side && right_side && top_side && bottom_side && + core_w < SPLIT_LIMIT) { + split_hor = false; + } + + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_FULL_COVER; + /*Draw the straight lines first if they are long enough*/ + if(top_side && split_hor) { + blend_area.x1 = core_area.x1; + blend_area.x2 = core_area.x2; + blend_area.y1 = outer_area->y1; + blend_area.y2 = inner_area->y1 - 1; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + + if(bottom_side && split_hor) { + blend_area.x1 = core_area.x1; + blend_area.x2 = core_area.x2; + blend_area.y1 = inner_area->y2 + 1; + blend_area.y2 = outer_area->y2; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + + /*If the border is very thick and the vertical sides overlap horizontally draw a single rectangle*/ + if(inner_area->x1 >= inner_area->x2 && left_side && right_side) { + blend_area.x1 = outer_area->x1; + blend_area.x2 = outer_area->x2; + blend_area.y1 = core_area.y1; + blend_area.y2 = core_area.y2; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + else { + if(left_side) { + blend_area.x1 = outer_area->x1; + blend_area.x2 = inner_area->x1 - 1; + blend_area.y1 = core_area.y1; + blend_area.y2 = core_area.y2; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + + if(right_side) { + blend_area.x1 = inner_area->x2 + 1; + blend_area.x2 = outer_area->x2; + blend_area.y1 = core_area.y1; + blend_area.y2 = core_area.y2; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + } + + /*Draw the corners*/ + int32_t blend_w; + + /*Left and right corner together if they are close to each other*/ + if(!split_hor) { + /*Calculate the top corner and mirror it to the bottom*/ + blend_area.x1 = draw_area.x1; + blend_area.x2 = draw_area.x2; + int32_t max_h = LV_MAX(rout, inner_area->y1 - outer_area->y1); + for(h = 0; h < max_h; h++) { + int32_t top_y = outer_area->y1 + h; + int32_t bottom_y = outer_area->y2 - h; + if(top_y < draw_area.y1 && bottom_y > draw_area.y2) continue; /*This line is clipped now*/ + + lv_memset(mask_buf, 0xff, draw_area_w); + blend_dsc.mask_res = lv_draw_sw_mask_apply(mask_list, mask_buf, blend_area.x1, top_y, draw_area_w); + + if(top_y >= draw_area.y1) { + blend_area.y1 = top_y; + blend_area.y2 = top_y; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + + if(bottom_y <= draw_area.y2) { + blend_area.y1 = bottom_y; + blend_area.y2 = bottom_y; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + } + } + else { + /*Left corners*/ + blend_area.x1 = draw_area.x1; + blend_area.x2 = LV_MIN(draw_area.x2, core_area.x1 - 1); + blend_w = lv_area_get_width(&blend_area); + if(blend_w > 0) { + if(left_side || top_side) { + for(h = draw_area.y1; h < core_area.y1; h++) { + blend_area.y1 = h; + blend_area.y2 = h; + + lv_memset(mask_buf, 0xff, blend_w); + blend_dsc.mask_res = lv_draw_sw_mask_apply(mask_list, mask_buf, blend_area.x1, h, blend_w); + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + } + + if(left_side || bottom_side) { + for(h = core_area.y2 + 1; h <= draw_area.y2; h++) { + blend_area.y1 = h; + blend_area.y2 = h; + + lv_memset(mask_buf, 0xff, blend_w); + blend_dsc.mask_res = lv_draw_sw_mask_apply(mask_list, mask_buf, blend_area.x1, h, blend_w); + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + } + } + + /*Right corners*/ + blend_area.x1 = LV_MAX(draw_area.x1, blend_area.x2 + 1); /*To not overlap with the left side*/ + blend_area.x1 = LV_MAX(draw_area.x1, core_area.x2 + 1); + + blend_area.x2 = draw_area.x2; + blend_w = lv_area_get_width(&blend_area); + + if(blend_w > 0) { + if(right_side || top_side) { + for(h = draw_area.y1; h < core_area.y1; h++) { + blend_area.y1 = h; + blend_area.y2 = h; + + lv_memset(mask_buf, 0xff, blend_w); + blend_dsc.mask_res = lv_draw_sw_mask_apply(mask_list, mask_buf, blend_area.x1, h, blend_w); + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + } + + if(right_side || bottom_side) { + for(h = core_area.y2 + 1; h <= draw_area.y2; h++) { + blend_area.y1 = h; + blend_area.y2 = h; + + lv_memset(mask_buf, 0xff, blend_w); + blend_dsc.mask_res = lv_draw_sw_mask_apply(mask_list, mask_buf, blend_area.x1, h, blend_w); + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + } + } + } + + lv_draw_sw_mask_free_param(&mask_rin_param); + if(rout > 0) lv_draw_sw_mask_free_param(&mask_rout_param); + lv_free(mask_buf); + +#endif /*LV_DRAW_SW_COMPLEX*/ +} +static void draw_border_simple(lv_draw_unit_t * draw_unit, const lv_area_t * outer_area, const lv_area_t * inner_area, + lv_color_t color, lv_opa_t opa) +{ + lv_area_t a; + lv_draw_sw_blend_dsc_t blend_dsc; + lv_memzero(&blend_dsc, sizeof(lv_draw_sw_blend_dsc_t)); + blend_dsc.blend_area = &a; + blend_dsc.color = color; + blend_dsc.opa = opa; + + bool top_side = outer_area->y1 <= inner_area->y1; + bool bottom_side = outer_area->y2 >= inner_area->y2; + bool left_side = outer_area->x1 <= inner_area->x1; + bool right_side = outer_area->x2 >= inner_area->x2; + + /*Top*/ + a.x1 = outer_area->x1; + a.x2 = outer_area->x2; + a.y1 = outer_area->y1; + a.y2 = inner_area->y1 - 1; + if(top_side) { + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + + /*Bottom*/ + a.y1 = inner_area->y2 + 1; + a.y2 = outer_area->y2; + if(bottom_side) { + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + + /*Left*/ + a.x1 = outer_area->x1; + a.x2 = inner_area->x1 - 1; + a.y1 = (top_side) ? inner_area->y1 : outer_area->y1; + a.y2 = (bottom_side) ? inner_area->y2 : outer_area->y2; + if(left_side) { + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + + /*Right*/ + a.x1 = inner_area->x2 + 1; + a.x2 = outer_area->x2; + if(right_side) { + lv_draw_sw_blend(draw_unit, &blend_dsc); + } +} + +#endif /*LV_USE_DRAW_SW*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_box_shadow.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_box_shadow.c new file mode 100644 index 000000000..f5ea57010 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_box_shadow.c @@ -0,0 +1,729 @@ +/** + * @file lv_draw_sw_box_shadow.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_sw.h" +#if LV_USE_DRAW_SW + +#include "blend/lv_draw_sw_blend.h" +#include "../../core/lv_global.h" +#include "../../misc/lv_math.h" +#include "../../core/lv_refr.h" +#include "../../misc/lv_assert.h" +#include "../../stdlib/lv_string.h" +#include "../lv_draw_mask.h" + +/********************* + * DEFINES + *********************/ +#define SHADOW_UPSCALE_SHIFT 6 +#define SHADOW_ENHANCE 1 + +#if defined(LV_DRAW_SW_SHADOW_CACHE_SIZE) && LV_DRAW_SW_SHADOW_CACHE_SIZE > 0 + #define shadow_cache LV_GLOBAL_DEFAULT()->sw_shadow_cache +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +#if LV_DRAW_SW_COMPLEX +LV_ATTRIBUTE_FAST_MEM static void shadow_draw_corner_buf(const lv_area_t * coords, uint16_t * sh_buf, int32_t s, + int32_t r); +LV_ATTRIBUTE_FAST_MEM static void shadow_blur_corner(int32_t size, int32_t sw, uint16_t * sh_ups_buf); +#endif /*LV_DRAW_SW_COMPLEX*/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_sw_box_shadow(lv_draw_unit_t * draw_unit, const lv_draw_box_shadow_dsc_t * dsc, const lv_area_t * coords) +{ + /*Calculate the rectangle which is blurred to get the shadow in `shadow_area`*/ + lv_area_t core_area; + core_area.x1 = coords->x1 + dsc->ofs_x - dsc->spread; + core_area.x2 = coords->x2 + dsc->ofs_x + dsc->spread; + core_area.y1 = coords->y1 + dsc->ofs_y - dsc->spread; + core_area.y2 = coords->y2 + dsc->ofs_y + dsc->spread; + + /*Calculate the bounding box of the shadow*/ + lv_area_t shadow_area; + shadow_area.x1 = core_area.x1 - dsc->width / 2 - 1; + shadow_area.x2 = core_area.x2 + dsc->width / 2 + 1; + shadow_area.y1 = core_area.y1 - dsc->width / 2 - 1; + shadow_area.y2 = core_area.y2 + dsc->width / 2 + 1; + + lv_opa_t opa = dsc->opa; + if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; + + /*Get clipped draw area which is the real draw area. + *It is always the same or inside `shadow_area`*/ + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, &shadow_area, draw_unit->clip_area)) return; + + /*Consider 1 px smaller bg to be sure the edge will be covered by the shadow*/ + lv_area_t bg_area; + lv_area_copy(&bg_area, coords); + lv_area_increase(&bg_area, -1, -1); + + /*Get the clamped radius*/ + int32_t r_bg = dsc->radius; + int32_t short_side = LV_MIN(lv_area_get_width(&bg_area), lv_area_get_height(&bg_area)); + if(r_bg > short_side >> 1) r_bg = short_side >> 1; + + /*Get the clamped radius*/ + int32_t r_sh = dsc->radius; + short_side = LV_MIN(lv_area_get_width(&core_area), lv_area_get_height(&core_area)); + if(r_sh > short_side >> 1) r_sh = short_side >> 1; + + /*Get how many pixels are affected by the blur on the corners*/ + int32_t corner_size = dsc->width + r_sh; + + lv_opa_t * sh_buf; + +#if LV_DRAW_SW_SHADOW_CACHE_SIZE + lv_draw_sw_shadow_cache_t * cache = &shadow_cache; + if(cache->cache_size == corner_size && cache->cache_r == r_sh) { + /*Use the cache if available*/ + sh_buf = lv_malloc(corner_size * corner_size); + lv_memcpy(sh_buf, cache->cache, corner_size * corner_size); + } + else { + /*A larger buffer is required for calculation*/ + sh_buf = lv_malloc(corner_size * corner_size * sizeof(uint16_t)); + shadow_draw_corner_buf(&core_area, (uint16_t *)sh_buf, dsc->width, r_sh); + + /*Cache the corner if it fits into the cache size*/ + if((uint32_t)corner_size * corner_size < sizeof(cache->cache)) { + lv_memcpy(cache->cache, sh_buf, corner_size * corner_size); + cache->cache_size = corner_size; + cache->cache_r = r_sh; + } + } +#else + sh_buf = lv_malloc(corner_size * corner_size * sizeof(uint16_t)); + shadow_draw_corner_buf(&core_area, (uint16_t *)sh_buf, dsc->width, r_sh); +#endif /*LV_DRAW_SW_SHADOW_CACHE_SIZE*/ + + /*Skip a lot of masking if the background will cover the shadow that would be masked out*/ + bool simple = dsc->bg_cover; + + /*Create a radius mask to clip remove shadow on the bg area*/ + + lv_draw_sw_mask_radius_param_t mask_rout_param; + void * masks[2] = {0}; + if(!simple) { + lv_draw_sw_mask_radius_init(&mask_rout_param, &bg_area, r_bg, true); + masks[0] = &mask_rout_param; + } + + lv_opa_t * mask_buf = lv_malloc(lv_area_get_width(&shadow_area)); + lv_area_t blend_area; + lv_area_t clip_area_sub; + lv_opa_t * sh_buf_tmp; + int32_t y; + bool simple_sub; + + lv_draw_sw_blend_dsc_t blend_dsc; + lv_memzero(&blend_dsc, sizeof(blend_dsc)); + blend_dsc.blend_area = &blend_area; + blend_dsc.mask_area = &blend_area; + blend_dsc.mask_buf = mask_buf; + blend_dsc.color = dsc->color; + blend_dsc.opa = dsc->opa; + + int32_t w_half = shadow_area.x1 + lv_area_get_width(&shadow_area) / 2; + int32_t h_half = shadow_area.y1 + lv_area_get_height(&shadow_area) / 2; + + /*Draw the corners if they are on the current clip area and not fully covered by the bg*/ + + /*Top right corner*/ + blend_area.x2 = shadow_area.x2; + blend_area.x1 = shadow_area.x2 - corner_size + 1; + blend_area.y1 = shadow_area.y1; + blend_area.y2 = shadow_area.y1 + corner_size - 1; + /*Do not overdraw the other top corners*/ + blend_area.x1 = LV_MAX(blend_area.x1, w_half); + blend_area.y2 = LV_MIN(blend_area.y2, h_half); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_unit->clip_area) && + !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + int32_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (clip_area_sub.y1 - shadow_area.y1) * corner_size; + sh_buf_tmp += clip_area_sub.x1 - (shadow_area.x2 - corner_size + 1); + + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + if(w > 0) { + blend_dsc.mask_buf = mask_buf; + blend_area.x1 = clip_area_sub.x1; + blend_area.x2 = clip_area_sub.x2; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ + for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { + blend_area.y1 = y; + blend_area.y2 = y; + + if(!simple_sub) { + lv_memcpy(mask_buf, sh_buf_tmp, corner_size); + blend_dsc.mask_res = lv_draw_sw_mask_apply(masks, mask_buf, clip_area_sub.x1, y, w); + if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + } + else { + blend_dsc.mask_buf = sh_buf_tmp; + } + lv_draw_sw_blend(draw_unit, &blend_dsc); + sh_buf_tmp += corner_size; + } + } + } + + /*Bottom right corner. + *Almost the same as top right just read the lines of `sh_buf` from then end*/ + blend_area.x2 = shadow_area.x2; + blend_area.x1 = shadow_area.x2 - corner_size + 1; + blend_area.y1 = shadow_area.y2 - corner_size + 1; + blend_area.y2 = shadow_area.y2; + /*Do not overdraw the other corners*/ + blend_area.x1 = LV_MAX(blend_area.x1, w_half); + blend_area.y1 = LV_MAX(blend_area.y1, h_half + 1); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_unit->clip_area) && + !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + int32_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (blend_area.y2 - clip_area_sub.y2) * corner_size; + sh_buf_tmp += clip_area_sub.x1 - (shadow_area.x2 - corner_size + 1); + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + + if(w > 0) { + blend_dsc.mask_buf = mask_buf; + blend_area.x1 = clip_area_sub.x1; + blend_area.x2 = clip_area_sub.x2; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ + for(y = clip_area_sub.y2; y >= clip_area_sub.y1; y--) { + blend_area.y1 = y; + blend_area.y2 = y; + + if(!simple_sub) { + lv_memcpy(mask_buf, sh_buf_tmp, corner_size); + blend_dsc.mask_res = lv_draw_sw_mask_apply(masks, mask_buf, clip_area_sub.x1, y, w); + if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + } + else { + blend_dsc.mask_buf = sh_buf_tmp; + } + lv_draw_sw_blend(draw_unit, &blend_dsc); + sh_buf_tmp += corner_size; + } + } + } + + /*Top side*/ + blend_area.x1 = shadow_area.x1 + corner_size; + blend_area.x2 = shadow_area.x2 - corner_size; + blend_area.y1 = shadow_area.y1; + blend_area.y2 = shadow_area.y1 + corner_size - 1; + blend_area.y2 = LV_MIN(blend_area.y2, h_half); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_unit->clip_area) && + !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + int32_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (clip_area_sub.y1 - blend_area.y1) * corner_size; + + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + + if(w > 0) { + if(!simple_sub) { + blend_dsc.mask_buf = mask_buf; + } + else { + blend_dsc.mask_buf = NULL; + } + blend_area.x1 = clip_area_sub.x1; + blend_area.x2 = clip_area_sub.x2; + + for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { + blend_area.y1 = y; + blend_area.y2 = y; + + if(!simple_sub) { + lv_memset(mask_buf, sh_buf_tmp[0], w); + blend_dsc.mask_res = lv_draw_sw_mask_apply(masks, mask_buf, clip_area_sub.x1, y, w); + if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + else { + blend_dsc.opa = opa == LV_OPA_COVER ? sh_buf_tmp[0] : LV_OPA_MIX2(sh_buf_tmp[0], dsc->opa); + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + sh_buf_tmp += corner_size; + } + } + } + blend_dsc.opa = dsc->opa; /*Restore*/ + + /*Bottom side*/ + blend_area.x1 = shadow_area.x1 + corner_size; + blend_area.x2 = shadow_area.x2 - corner_size; + blend_area.y1 = shadow_area.y2 - corner_size + 1; + blend_area.y2 = shadow_area.y2; + blend_area.y1 = LV_MAX(blend_area.y1, h_half + 1); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_unit->clip_area) && + !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + int32_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (blend_area.y2 - clip_area_sub.y2) * corner_size; + if(w > 0) { + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + + if(!simple_sub) { + blend_dsc.mask_buf = mask_buf; + } + else { + blend_dsc.mask_buf = NULL; + } + blend_area.x1 = clip_area_sub.x1; + blend_area.x2 = clip_area_sub.x2; + + for(y = clip_area_sub.y2; y >= clip_area_sub.y1; y--) { + blend_area.y1 = y; + blend_area.y2 = y; + + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + + if(!simple_sub) { + lv_memset(mask_buf, sh_buf_tmp[0], w); + blend_dsc.mask_res = lv_draw_sw_mask_apply(masks, mask_buf, clip_area_sub.x1, y, w); + if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + else { + blend_dsc.opa = opa == LV_OPA_COVER ? sh_buf_tmp[0] : (sh_buf_tmp[0] * dsc->opa) >> 8; + lv_draw_sw_blend(draw_unit, &blend_dsc); + + } + sh_buf_tmp += corner_size; + } + } + } + + blend_dsc.opa = dsc->opa; /*Restore*/ + + /*Right side*/ + blend_area.x1 = shadow_area.x2 - corner_size + 1; + blend_area.x2 = shadow_area.x2; + blend_area.y1 = shadow_area.y1 + corner_size; + blend_area.y2 = shadow_area.y2 - corner_size; + /*Do not overdraw the other corners*/ + blend_area.y1 = LV_MIN(blend_area.y1, h_half + 1); + blend_area.y2 = LV_MAX(blend_area.y2, h_half); + blend_area.x1 = LV_MAX(blend_area.x1, w_half); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_unit->clip_area) && + !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + int32_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (corner_size - 1) * corner_size; + sh_buf_tmp += clip_area_sub.x1 - (shadow_area.x2 - corner_size + 1); + + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + blend_dsc.mask_buf = simple_sub ? sh_buf_tmp : mask_buf; + + if(w > 0) { + blend_area.x1 = clip_area_sub.x1; + blend_area.x2 = clip_area_sub.x2; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ + for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { + blend_area.y1 = y; + blend_area.y2 = y; + + if(!simple_sub) { + lv_memcpy(mask_buf, sh_buf_tmp, w); + blend_dsc.mask_res = lv_draw_sw_mask_apply(masks, mask_buf, clip_area_sub.x1, y, w); + if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + } + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + } + } + + /*Mirror the shadow corner buffer horizontally*/ + sh_buf_tmp = sh_buf ; + for(y = 0; y < corner_size; y++) { + int32_t x; + lv_opa_t * start = sh_buf_tmp; + lv_opa_t * end = sh_buf_tmp + corner_size - 1; + for(x = 0; x < corner_size / 2; x++) { + lv_opa_t tmp = *start; + *start = *end; + *end = tmp; + + start++; + end--; + } + sh_buf_tmp += corner_size; + } + + /*Left side*/ + blend_area.x1 = shadow_area.x1; + blend_area.x2 = shadow_area.x1 + corner_size - 1; + blend_area.y1 = shadow_area.y1 + corner_size; + blend_area.y2 = shadow_area.y2 - corner_size; + /*Do not overdraw the other corners*/ + blend_area.y1 = LV_MIN(blend_area.y1, h_half + 1); + blend_area.y2 = LV_MAX(blend_area.y2, h_half); + blend_area.x2 = LV_MIN(blend_area.x2, w_half - 1); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_unit->clip_area) && + !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + int32_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (corner_size - 1) * corner_size; + sh_buf_tmp += clip_area_sub.x1 - blend_area.x1; + + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + blend_dsc.mask_buf = simple_sub ? sh_buf_tmp : mask_buf; + if(w > 0) { + blend_area.x1 = clip_area_sub.x1; + blend_area.x2 = clip_area_sub.x2; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ + for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { + blend_area.y1 = y; + blend_area.y2 = y; + + if(!simple_sub) { + lv_memcpy(mask_buf, sh_buf_tmp, w); + blend_dsc.mask_res = lv_draw_sw_mask_apply(masks, mask_buf, clip_area_sub.x1, y, w); + if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + } + + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + } + } + + /*Top left corner*/ + blend_area.x1 = shadow_area.x1; + blend_area.x2 = shadow_area.x1 + corner_size - 1; + blend_area.y1 = shadow_area.y1; + blend_area.y2 = shadow_area.y1 + corner_size - 1; + /*Do not overdraw the other corners*/ + blend_area.x2 = LV_MIN(blend_area.x2, w_half - 1); + blend_area.y2 = LV_MIN(blend_area.y2, h_half); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_unit->clip_area) && + !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + int32_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (clip_area_sub.y1 - blend_area.y1) * corner_size; + sh_buf_tmp += clip_area_sub.x1 - blend_area.x1; + + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + blend_dsc.mask_buf = mask_buf; + + if(w > 0) { + blend_area.x1 = clip_area_sub.x1; + blend_area.x2 = clip_area_sub.x2; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ + for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { + blend_area.y1 = y; + blend_area.y2 = y; + + if(!simple_sub) { + lv_memcpy(mask_buf, sh_buf_tmp, corner_size); + blend_dsc.mask_res = lv_draw_sw_mask_apply(masks, mask_buf, clip_area_sub.x1, y, w); + if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + } + else { + blend_dsc.mask_buf = sh_buf_tmp; + } + + lv_draw_sw_blend(draw_unit, &blend_dsc); + sh_buf_tmp += corner_size; + } + } + } + + /*Bottom left corner. + *Almost the same as bottom right just read the lines of `sh_buf` from then end*/ + blend_area.x1 = shadow_area.x1 ; + blend_area.x2 = shadow_area.x1 + corner_size - 1; + blend_area.y1 = shadow_area.y2 - corner_size + 1; + blend_area.y2 = shadow_area.y2; + /*Do not overdraw the other corners*/ + blend_area.y1 = LV_MAX(blend_area.y1, h_half + 1); + blend_area.x2 = LV_MIN(blend_area.x2, w_half - 1); + + if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_unit->clip_area) && + !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + int32_t w = lv_area_get_width(&clip_area_sub); + sh_buf_tmp = sh_buf; + sh_buf_tmp += (blend_area.y2 - clip_area_sub.y2) * corner_size; + sh_buf_tmp += clip_area_sub.x1 - blend_area.x1; + + /*Do not mask if out of the bg*/ + if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; + else simple_sub = simple; + blend_dsc.mask_buf = mask_buf; + if(w > 0) { + blend_area.x1 = clip_area_sub.x1; + blend_area.x2 = clip_area_sub.x2; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ + for(y = clip_area_sub.y2; y >= clip_area_sub.y1; y--) { + blend_area.y1 = y; + blend_area.y2 = y; + + if(!simple_sub) { + lv_memcpy(mask_buf, sh_buf_tmp, corner_size); + blend_dsc.mask_res = lv_draw_sw_mask_apply(masks, mask_buf, clip_area_sub.x1, y, w); + if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + } + else { + blend_dsc.mask_buf = sh_buf_tmp; + } + lv_draw_sw_blend(draw_unit, &blend_dsc); + sh_buf_tmp += corner_size; + } + } + } + + /*Draw the center rectangle.*/ + blend_area.x1 = shadow_area.x1 + corner_size ; + blend_area.x2 = shadow_area.x2 - corner_size; + blend_area.y1 = shadow_area.y1 + corner_size; + blend_area.y2 = shadow_area.y2 - corner_size; + blend_area.y1 = LV_MIN(blend_area.y1, h_half + 1); + blend_area.y2 = LV_MAX(blend_area.y2, h_half); + blend_dsc.mask_buf = mask_buf; + + if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_unit->clip_area) && + !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { + int32_t w = lv_area_get_width(&clip_area_sub); + if(w > 0) { + blend_area.x1 = clip_area_sub.x1; + blend_area.x2 = clip_area_sub.x2; + for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { + blend_area.y1 = y; + blend_area.y2 = y; + + lv_memset(mask_buf, 0xff, w); + blend_dsc.mask_res = lv_draw_sw_mask_apply(masks, mask_buf, clip_area_sub.x1, y, w); + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + } + } + + if(!simple) { + lv_draw_sw_mask_free_param(&mask_rout_param); + } + lv_free(sh_buf); + lv_free(mask_buf); +} +#endif /*LV_USE_DRAW_SW*/ + +/********************** + * STATIC FUNCTIONS + **********************/ + +#if LV_DRAW_SW_COMPLEX + +/** + * Calculate a blurred corner + * @param coords Coordinates of the shadow + * @param sh_buf a buffer to store the result. Its size should be `(sw + r)^2 * 2` + * @param sw shadow width + * @param r radius + */ +LV_ATTRIBUTE_FAST_MEM static void shadow_draw_corner_buf(const lv_area_t * coords, uint16_t * sh_buf, int32_t sw, + int32_t r) +{ + int32_t sw_ori = sw; + int32_t size = sw_ori + r; + + lv_area_t sh_area; + lv_area_copy(&sh_area, coords); + sh_area.x2 = sw / 2 + r - 1 - ((sw & 1) ? 0 : 1); + sh_area.y1 = sw / 2 + 1; + + sh_area.x1 = sh_area.x2 - lv_area_get_width(coords); + sh_area.y2 = sh_area.y1 + lv_area_get_height(coords); + + lv_draw_sw_mask_radius_param_t mask_param; + lv_draw_sw_mask_radius_init(&mask_param, &sh_area, r, false); + +#if SHADOW_ENHANCE + /*Set half shadow width width because blur will be repeated*/ + if(sw_ori == 1) sw = 1; + else sw = sw_ori >> 1; +#endif /*SHADOW_ENHANCE*/ + + int32_t y; + lv_opa_t * mask_line = lv_malloc(size); + uint16_t * sh_ups_tmp_buf = (uint16_t *)sh_buf; + for(y = 0; y < size; y++) { + lv_memset(mask_line, 0xff, size); + lv_draw_sw_mask_res_t mask_res = mask_param.dsc.cb(mask_line, 0, y, size, &mask_param); + if(mask_res == LV_DRAW_SW_MASK_RES_TRANSP) { + lv_memzero(sh_ups_tmp_buf, size * sizeof(sh_ups_tmp_buf[0])); + } + else { + int32_t i; + sh_ups_tmp_buf[0] = (mask_line[0] << SHADOW_UPSCALE_SHIFT) / sw; + for(i = 1; i < size; i++) { + if(mask_line[i] == mask_line[i - 1]) sh_ups_tmp_buf[i] = sh_ups_tmp_buf[i - 1]; + else sh_ups_tmp_buf[i] = (mask_line[i] << SHADOW_UPSCALE_SHIFT) / sw; + } + } + + sh_ups_tmp_buf += size; + } + lv_free(mask_line); + + lv_draw_sw_mask_free_param(&mask_param); + + if(sw == 1) { + int32_t i; + lv_opa_t * res_buf = (lv_opa_t *)sh_buf; + for(i = 0; i < size * size; i++) { + res_buf[i] = (sh_buf[i] >> SHADOW_UPSCALE_SHIFT); + } + return; + } + + shadow_blur_corner(size, sw, sh_buf); + +#if SHADOW_ENHANCE == 0 + /*The result is required in lv_opa_t not uint16_t*/ + uint32_t x; + lv_opa_t * res_buf = (lv_opa_t *)sh_buf; + for(x = 0; x < size * size; x++) { + res_buf[x] = sh_buf[x]; + } +#else + sw += sw_ori & 1; + if(sw > 1) { + uint32_t i; + uint32_t max_v_div = (LV_OPA_COVER << SHADOW_UPSCALE_SHIFT) / sw; + for(i = 0; i < (uint32_t)size * size; i++) { + if(sh_buf[i] == 0) continue; + else if(sh_buf[i] == LV_OPA_COVER) sh_buf[i] = max_v_div; + else sh_buf[i] = (sh_buf[i] << SHADOW_UPSCALE_SHIFT) / sw; + } + + shadow_blur_corner(size, sw, sh_buf); + } + int32_t x; + lv_opa_t * res_buf = (lv_opa_t *)sh_buf; + for(x = 0; x < size * size; x++) { + res_buf[x] = sh_buf[x]; + } +#endif + +} + +LV_ATTRIBUTE_FAST_MEM static void shadow_blur_corner(int32_t size, int32_t sw, uint16_t * sh_ups_buf) +{ + int32_t s_left = sw >> 1; + int32_t s_right = (sw >> 1); + if((sw & 1) == 0) s_left--; + + /*Horizontal blur*/ + uint16_t * sh_ups_blur_buf = lv_malloc(size * sizeof(uint16_t)); + + int32_t x; + int32_t y; + + uint16_t * sh_ups_tmp_buf = sh_ups_buf; + + for(y = 0; y < size; y++) { + int32_t v = sh_ups_tmp_buf[size - 1] * sw; + for(x = size - 1; x >= 0; x--) { + sh_ups_blur_buf[x] = v; + + /*Forget the right pixel*/ + uint32_t right_val = 0; + if(x + s_right < size) right_val = sh_ups_tmp_buf[x + s_right]; + v -= right_val; + + /*Add the left pixel*/ + uint32_t left_val; + if(x - s_left - 1 < 0) left_val = sh_ups_tmp_buf[0]; + else left_val = sh_ups_tmp_buf[x - s_left - 1]; + v += left_val; + } + lv_memcpy(sh_ups_tmp_buf, sh_ups_blur_buf, size * sizeof(uint16_t)); + sh_ups_tmp_buf += size; + } + + /*Vertical blur*/ + uint32_t i; + uint32_t max_v = LV_OPA_COVER << SHADOW_UPSCALE_SHIFT; + uint32_t max_v_div = max_v / sw; + for(i = 0; i < (uint32_t)size * size; i++) { + if(sh_ups_buf[i] == 0) continue; + else if(sh_ups_buf[i] == max_v) sh_ups_buf[i] = max_v_div; + else sh_ups_buf[i] = sh_ups_buf[i] / sw; + } + + for(x = 0; x < size; x++) { + sh_ups_tmp_buf = &sh_ups_buf[x]; + int32_t v = sh_ups_tmp_buf[0] * sw; + for(y = 0; y < size ; y++, sh_ups_tmp_buf += size) { + sh_ups_blur_buf[y] = v < 0 ? 0 : (v >> SHADOW_UPSCALE_SHIFT); + + /*Forget the top pixel*/ + uint32_t top_val; + if(y - s_right <= 0) top_val = sh_ups_tmp_buf[0]; + else top_val = sh_ups_buf[(y - s_right) * size + x]; + v -= top_val; + + /*Add the bottom pixel*/ + uint32_t bottom_val; + if(y + s_left + 1 < size) bottom_val = sh_ups_buf[(y + s_left + 1) * size + x]; + else bottom_val = sh_ups_buf[(size - 1) * size + x]; + v += bottom_val; + } + + /*Write back the result into `sh_ups_buf`*/ + sh_ups_tmp_buf = &sh_ups_buf[x]; + for(y = 0; y < size; y++, sh_ups_tmp_buf += size) { + (*sh_ups_tmp_buf) = sh_ups_blur_buf[y]; + } + } + + lv_free(sh_ups_blur_buf); +} +#endif /*LV_DRAW_SW_COMPLEX*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_dither.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_dither.c deleted file mode 100644 index 68fd2db6e..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_dither.c +++ /dev/null @@ -1,213 +0,0 @@ -/** - * @file lv_draw_sw_dither.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_draw_sw_dither.h" -#include "lv_draw_sw_gradient.h" -#include "../../misc/lv_color.h" - -/********************** - * STATIC FUNCTIONS - **********************/ - - -#if _DITHER_GRADIENT - -void LV_ATTRIBUTE_FAST_MEM lv_dither_none(lv_grad_t * grad, lv_coord_t x, lv_coord_t y, lv_coord_t w) -{ - LV_UNUSED(x); - LV_UNUSED(y); - if(grad == NULL || grad->filled) return; - for(lv_coord_t i = 0; i < w; i++) { - grad->map[i] = lv_color_hex(grad->hmap[i].full); - } - grad->filled = 1; -} - -static const uint8_t dither_ordered_threshold_matrix[8 * 8] = { - 0, 48, 12, 60, 3, 51, 15, 63, - 32, 16, 44, 28, 35, 19, 47, 31, - 8, 56, 4, 52, 11, 59, 7, 55, - 40, 24, 36, 20, 43, 27, 39, 23, - 2, 50, 14, 62, 1, 49, 13, 61, - 34, 18, 46, 30, 33, 17, 45, 29, - 10, 58, 6, 54, 9, 57, 5, 53, - 42, 26, 38, 22, 41, 25, 37, 21 -}; /* Shift by 6 to normalize */ - - -void LV_ATTRIBUTE_FAST_MEM lv_dither_ordered_hor(lv_grad_t * grad, lv_coord_t x, lv_coord_t y, lv_coord_t w) -{ - LV_UNUSED(x); - /* For vertical dithering, the error is spread on the next column (and not next line). - Since the renderer is scanline based, it's not obvious what could be used to perform the rendering efficiently. - The algorithm below is based on few assumptions: - 1. An error diffusion algorithm (like Floyd Steinberg) here would be hard to implement since it means that a pixel on column n depends on the pixel on row n - 2. Instead an ordered dithering algorithm shift the value a bit, but the influence only spread from the matrix size (used 8x8 here) - 3. It means that a pixel i,j only depends on the value of a pixel i-7, j-7 to i,j and no other one. - Then we compute a complete row of ordered dither and store it in out. */ - - /*The apply the algorithm for this patch*/ - for(lv_coord_t j = 0; j < w; j++) { - int8_t factor = dither_ordered_threshold_matrix[(y & 7) * 8 + ((j) & 7)] - 32; - lv_color32_t tmp = grad->hmap[LV_CLAMP(0, j - 4, grad->size)]; - lv_color32_t t; - t.ch.red = LV_CLAMP(0, tmp.ch.red + factor, 255); - t.ch.green = LV_CLAMP(0, tmp.ch.green + factor, 255); - t.ch.blue = LV_CLAMP(0, tmp.ch.blue + factor, 255); - - grad->map[j] = lv_color_hex(t.full); - } -} - -void LV_ATTRIBUTE_FAST_MEM lv_dither_ordered_ver(lv_grad_t * grad, lv_coord_t x, lv_coord_t y, lv_coord_t w) -{ - /* For vertical dithering, the error is spread on the next column (and not next line). - Since the renderer is scanline based, it's not obvious what could be used to perform the rendering efficiently. - The algorithm below is based on few assumptions: - 1. An error diffusion algorithm (like Floyd Steinberg) here would be hard to implement since it means that a pixel on column n depends on the pixel on row n - 2. Instead an ordered dithering algorithm shift the value a bit, but the influence only spread from the matrix size (used 8x8 here) - 3. It means that a pixel i,j only depends on the value of a pixel i-7, j-7 to i,j and no other one. - Then we compute a complete row of ordered dither and store it in out. */ - - /*Extract patch for working with, selected pseudo randomly*/ - lv_color32_t tmp = grad->hmap[LV_CLAMP(0, y - 4, grad->size)]; - - /*The apply the algorithm for this patch*/ - for(lv_coord_t j = 0; j < 8; j++) { - int8_t factor = dither_ordered_threshold_matrix[(y & 7) * 8 + ((j + x) & 7)] - 32; - lv_color32_t t; - t.ch.red = LV_CLAMP(0, tmp.ch.red + factor, 255); - t.ch.green = LV_CLAMP(0, tmp.ch.green + factor, 255); - t.ch.blue = LV_CLAMP(0, tmp.ch.blue + factor, 255); - - grad->map[j] = lv_color_hex(t.full); - } - /*Finally fill the line*/ - lv_coord_t j = 8; - for(; j < w - 8; j += 8) { - lv_memcpy(grad->map + j, grad->map, 8 * sizeof(*grad->map)); - } - /* Prevent overwriting */ - for(; j < w; j++) { - grad->map[j] = grad->map[j & 7]; - } -} - -#if LV_DITHER_ERROR_DIFFUSION == 1 -void LV_ATTRIBUTE_FAST_MEM lv_dither_err_diff_hor(lv_grad_t * grad, lv_coord_t xs, lv_coord_t y, lv_coord_t w) -{ - LV_UNUSED(xs); - LV_UNUSED(y); - LV_UNUSED(w); - - /* Implement Floyd Steinberg algorithm, see https://surma.dev/things/ditherpunk/ - Coefs are: x 7 - 3 5 1 - / 16 - Can be implemented as: x (x<<3 - x) - (x<<2 - x) (x<<2+x) x - */ - int coef[4] = {0, 0, 0, 0}; -#define FS_COMPUTE_ERROR(e) { coef[0] = (e<<3) - e; coef[1] = (e<<2) - e; coef[2] = (e<<2) + e; coef[3] = e; } -#define FS_COMPONENTS(A, OP, B, C) A.ch.red = LV_CLAMP(0, A.ch.red OP B.r OP C.r, 255); A.ch.green = LV_CLAMP(0, A.ch.green OP B.g OP C.g, 255); A.ch.blue = LV_CLAMP(0, A.ch.blue OP B.b OP C.b, 255); -#define FS_QUANT_ERROR(e, t, q) { lv_color32_t u; u.full = lv_color_to32(q); e.r = (int8_t)(t.ch.red - u.ch.red); e.g = (int8_t)(t.ch.green - u.ch.green); e.b = (int8_t)(t.ch.blue - u.ch.blue); } - lv_scolor24_t next_px_err = {0}, next_l = {0}, error; - /*First last pixel are not dithered */ - grad->map[0] = lv_color_hex(grad->hmap[0].full); - for(lv_coord_t x = 1; x < grad->size - 1; x++) { - lv_color32_t t = grad->hmap[x]; - lv_color_t q; - /*Add error term*/ - FS_COMPONENTS(t, +, next_px_err, next_l); - next_l = grad->error_acc[x + 1]; - /*Quantify*/ - q = lv_color_hex(t.full); - /*Then compute error*/ - FS_QUANT_ERROR(error, t, q); - /*Dither the error*/ - FS_COMPUTE_ERROR(error.r); - next_px_err.r = coef[0] >> 4; - grad->error_acc[x - 1].r += coef[1] >> 4; - grad->error_acc[x].r += coef[2] >> 4; - grad->error_acc[x + 1].r = coef[3] >> 4; - - FS_COMPUTE_ERROR(error.g); - next_px_err.g = coef[0] >> 4; - grad->error_acc[x - 1].g += coef[1] >> 4; - grad->error_acc[x].g += coef[2] >> 4; - grad->error_acc[x + 1].g = coef[3] >> 4; - - FS_COMPUTE_ERROR(error.b); - next_px_err.b = coef[0] >> 4; - grad->error_acc[x - 1].b += coef[1] >> 4; - grad->error_acc[x].b += coef[2] >> 4; - grad->error_acc[x + 1].b = coef[3] >> 4; - - grad->map[x] = q; - } - grad->map[grad->size - 1] = lv_color_hex(grad->hmap[grad->size - 1].full); -} - -void LV_ATTRIBUTE_FAST_MEM lv_dither_err_diff_ver(lv_grad_t * grad, lv_coord_t xs, lv_coord_t y, lv_coord_t w) -{ - /* Try to implement error diffusion on a vertical gradient and an horizontal map using those tricks: - Since the given hi-resolution gradient (in src) is vertical, the Floyd Steinberg algorithm pass need to be rotated, - so we'll get this instead (from top to bottom): - - A B C - 1 [ ][ ][ ] - 2 [ ][ ][ ] Pixel A2 will spread its error on pixel A3 with coefficient 7, - 3 [ ][ ][ ] Pixel A2 will spread its error on pixel B1 with coefficient 3, B2 with coef 5 and B3 with coef 1 - - When taking into account an arbitrary pixel P(i,j), its added error diffusion term is: - e(i,j) = 1/16 * [ e(i-1,j) * 5 + e(i-1,j+1) * 3 + e(i-1,j-1) * 1 + e(i,j-1) * 7] - - This means that the error term depends on pixel W, NW, N and SW. - If we consider that we are generating the error diffused gradient map from top to bottom, we can remember the previous - line (N, NW) in the term above. Also, we remember the (W) term too since we are computing the gradient map from left to right. - However, the SW term is painful for us, we can't support it (since to get it, we need its own SW term and so on). - Let's remove it and re-dispatch the error factor accordingly so they stays normalized: - e(i,j) ~= 1/16 * [ e(i-1,j) * 6 + e(i-1,j-1) * 1 + e(i,j-1) * 9] - - That's the idea of this pseudo Floyd Steinberg dithering */ -#define FS_APPLY(d, s, c) d.r = (int8_t)(s.r * c) >> 4; d.g = (int8_t)(s.g * c) >> 4; d.b = (int8_t)(s.b * c) >> 4; -#define FS_COMPONENTS3(A, OP, B, b, C, c, D, d) \ - A.ch.red = LV_CLAMP(0, A.ch.red OP ((B.r * b OP C.r * c OP D.r * d) >> 4), 255); \ - A.ch.green = LV_CLAMP(0, A.ch.green OP ((B.r * b OP C.r * c OP D.r * d) >> 4), 255); \ - A.ch.blue = LV_CLAMP(0, A.ch.blue OP ((B.r * b OP C.r * c OP D.r * d) >> 4), 255); - - lv_scolor24_t next_px_err, prev_l = grad->error_acc[0]; - /*Compute the error term for the current pixel (first pixel is never dithered)*/ - if(xs == 0) { - grad->map[0] = lv_color_hex(grad->hmap[y].full); - FS_QUANT_ERROR(next_px_err, grad->hmap[y], grad->map[0]); - } - else { - lv_color_t tmp = lv_color_hex(grad->hmap[y].full); - lv_color32_t t = grad->hmap[y]; - FS_QUANT_ERROR(next_px_err, grad->hmap[y], tmp); - FS_COMPONENTS3(t, +, next_px_err, 6, prev_l, 1, grad->error_acc[0], 9); - grad->map[0] = lv_color_hex(t.full); - } - - for(lv_coord_t x = 1; x < w; x++) { - lv_color32_t t = grad->hmap[y]; - lv_color_t q; - /*Add the current error term*/ - FS_COMPONENTS3(t, +, next_px_err, 6, prev_l, 1, grad->error_acc[x], 9); - prev_l = grad->error_acc[x]; - /*Quantize and compute error term*/ - q = lv_color_hex(t.full); - FS_QUANT_ERROR(next_px_err, t, q); - /*Store error for next line computation*/ - grad->error_acc[x] = next_px_err; - grad->map[x] = q; - } -} -#endif -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_dither.h b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_dither.h deleted file mode 100644 index 17f98f90b..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_dither.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @file lv_draw_sw_dither.h - * - */ - -#ifndef LV_DRAW_SW_DITHER_H -#define LV_DRAW_SW_DITHER_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../core/lv_obj_pos.h" - - -/********************* - * DEFINES - *********************/ -#if LV_COLOR_DEPTH < 32 && LV_DITHER_GRADIENT == 1 -#define _DITHER_GRADIENT 1 -#else -#define _DITHER_GRADIENT 0 -#endif - -/********************** - * TYPEDEFS - **********************/ -#if _DITHER_GRADIENT -/*A signed error color component*/ -typedef struct { - int8_t r, g, b; -} lv_scolor24_t; - -struct _lv_gradient_cache_t; -typedef void (*lv_dither_func_t)(struct _lv_gradient_cache_t * grad, lv_coord_t x, lv_coord_t y, lv_coord_t w); - -#endif - - -/********************** - * PROTOTYPES - **********************/ -#if LV_DRAW_COMPLEX -#if _DITHER_GRADIENT -void /* LV_ATTRIBUTE_FAST_MEM */ lv_dither_none(struct _lv_gradient_cache_t * grad, lv_coord_t x, lv_coord_t y, - lv_coord_t w); - -void /* LV_ATTRIBUTE_FAST_MEM */ lv_dither_ordered_hor(struct _lv_gradient_cache_t * grad, const lv_coord_t xs, - const lv_coord_t y, const lv_coord_t w); -void /* LV_ATTRIBUTE_FAST_MEM */ lv_dither_ordered_ver(struct _lv_gradient_cache_t * grad, const lv_coord_t xs, - const lv_coord_t y, const lv_coord_t w); - -#if LV_DITHER_ERROR_DIFFUSION == 1 -void /* LV_ATTRIBUTE_FAST_MEM */ lv_dither_err_diff_hor(struct _lv_gradient_cache_t * grad, const lv_coord_t xs, - const lv_coord_t y, const lv_coord_t w); -void /* LV_ATTRIBUTE_FAST_MEM */ lv_dither_err_diff_ver(struct _lv_gradient_cache_t * grad, const lv_coord_t xs, - const lv_coord_t y, const lv_coord_t w); -#endif /* LV_DITHER_ERROR_DIFFUSION */ - -#endif /* _DITHER_GRADIENT */ -#endif - - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_fill.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_fill.c new file mode 100644 index 000000000..027f3048d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_fill.c @@ -0,0 +1,224 @@ +/** + * @file lv_draw_sw_fill.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_sw.h" +#if LV_USE_DRAW_SW + +#include "blend/lv_draw_sw_blend.h" +#include "lv_draw_sw_gradient.h" +#include "../../misc/lv_math.h" +#include "../../misc/lv_text_ap.h" +#include "../../core/lv_refr.h" +#include "../../misc/lv_assert.h" +#include "../../stdlib/lv_string.h" +#include "../lv_draw_mask.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_sw_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) return; + + lv_area_t bg_coords; + lv_area_copy(&bg_coords, coords); + + lv_area_t clipped_coords; + if(!_lv_area_intersect(&clipped_coords, &bg_coords, draw_unit->clip_area)) return; + + lv_grad_dir_t grad_dir = dsc->grad.dir; + lv_color_t bg_color = grad_dir == LV_GRAD_DIR_NONE ? dsc->color : dsc->grad.stops[0].color; + + lv_draw_sw_blend_dsc_t blend_dsc = {0}; + blend_dsc.color = bg_color; + + /*Most simple case: just a plain rectangle*/ + if(dsc->radius == 0 && (grad_dir == LV_GRAD_DIR_NONE)) { + blend_dsc.blend_area = &bg_coords; + blend_dsc.opa = dsc->opa; + lv_draw_sw_blend(draw_unit, &blend_dsc); + return; + } + + /*Complex case: there is gradient, mask, or radius*/ +#if LV_DRAW_SW_COMPLEX == 0 + LV_LOG_WARN("Can't draw complex rectangle because LV_DRAW_SW_COMPLEX = 0"); +#else + lv_opa_t opa = dsc->opa >= LV_OPA_MAX ? LV_OPA_COVER : dsc->opa; + + /*Get the real radius. Can't be larger than the half of the shortest side */ + int32_t coords_bg_w = lv_area_get_width(&bg_coords); + int32_t coords_bg_h = lv_area_get_height(&bg_coords); + int32_t short_side = LV_MIN(coords_bg_w, coords_bg_h); + int32_t rout = LV_MIN(dsc->radius, short_side >> 1); + + /*Add a radius mask if there is a radius*/ + int32_t clipped_w = lv_area_get_width(&clipped_coords); + lv_opa_t * mask_buf = NULL; + lv_draw_sw_mask_radius_param_t mask_rout_param; + void * mask_list[2] = {NULL, NULL}; + if(rout > 0) { + mask_buf = lv_malloc(clipped_w); + lv_draw_sw_mask_radius_init(&mask_rout_param, &bg_coords, rout, false); + mask_list[0] = &mask_rout_param; + } + + int32_t h; + + lv_area_t blend_area; + blend_area.x1 = clipped_coords.x1; + blend_area.x2 = clipped_coords.x2; + + blend_dsc.mask_buf = mask_buf; + blend_dsc.blend_area = &blend_area; + blend_dsc.mask_area = &blend_area; + blend_dsc.opa = LV_OPA_COVER; + + /*Get gradient if appropriate*/ + lv_grad_t * grad = lv_gradient_get(&dsc->grad, coords_bg_w, coords_bg_h); + lv_opa_t * grad_opa_map = NULL; + if(grad && grad_dir == LV_GRAD_DIR_HOR) { + blend_dsc.src_area = &blend_area; + blend_dsc.src_buf = grad->color_map + clipped_coords.x1 - bg_coords.x1; + bool transp = false; + uint32_t s; + for(s = 0; s < dsc->grad.stops_count; s++) { + if(dsc->grad.stops[s].opa != LV_OPA_COVER) { + transp = true; + break; + } + } + + if(transp) grad_opa_map = grad->opa_map + clipped_coords.x1 - bg_coords.x1; + + blend_dsc.src_color_format = LV_COLOR_FORMAT_RGB888; + } + + /* Draw the top of the rectangle line by line and mirror it to the bottom. */ + for(h = 0; h < rout; h++) { + int32_t top_y = bg_coords.y1 + h; + int32_t bottom_y = bg_coords.y2 - h; + if(top_y < clipped_coords.y1 && bottom_y > clipped_coords.y2) continue; /*This line is clipped now*/ + + /* Initialize the mask to opa instead of 0xFF and blend with LV_OPA_COVER. + * It saves calculating the final opa in lv_draw_sw_blend*/ + lv_memset(mask_buf, opa, clipped_w); + blend_dsc.mask_res = lv_draw_sw_mask_apply(mask_list, mask_buf, blend_area.x1, top_y, clipped_w); + if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + + bool hor_grad_processed = false; + if(top_y >= clipped_coords.y1) { + blend_area.y1 = top_y; + blend_area.y2 = top_y; + + if(grad_dir == LV_GRAD_DIR_VER) { + blend_dsc.color = grad->color_map[top_y - bg_coords.y1]; + blend_dsc.opa = grad->opa_map[top_y - bg_coords.y1]; + } + else if(grad_dir == LV_GRAD_DIR_HOR) { + hor_grad_processed = true; + if(grad_opa_map) { + int32_t i; + for(i = 0; i < clipped_w; i++) { + if(grad_opa_map[i] < LV_OPA_MAX) mask_buf[i] = (mask_buf[i] * grad_opa_map[i]) >> 8; + } + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + } + } + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + + if(bottom_y <= clipped_coords.y2) { + blend_area.y1 = bottom_y; + blend_area.y2 = bottom_y; + + if(grad_dir == LV_GRAD_DIR_VER) { + blend_dsc.color = grad->color_map[bottom_y - bg_coords.y1]; + blend_dsc.opa = grad->opa_map[bottom_y - bg_coords.y1]; + } + else if(hor_grad_processed == false && grad_dir == LV_GRAD_DIR_HOR) { + if(grad_opa_map) { + int32_t i; + for(i = 0; i < clipped_w; i++) { + if(grad_opa_map[i] < LV_OPA_MAX) mask_buf[i] = (mask_buf[i] * grad_opa_map[i]) >> 8; + } + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + } + } + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + } + + /* Draw the center of the rectangle.*/ + + /*If no gradient, the center is a simple rectangle*/ + if(grad_dir == LV_GRAD_DIR_NONE) { + blend_area.y1 = bg_coords.y1 + rout; + blend_area.y2 = bg_coords.y2 - rout; + blend_dsc.opa = opa; + blend_dsc.mask_buf = NULL; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + /*With gradient draw line by line*/ + else { + blend_dsc.opa = opa; + if(grad_dir == LV_GRAD_DIR_VER) { + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_FULL_COVER; + } + else if(grad_dir == LV_GRAD_DIR_HOR) { + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + blend_dsc.mask_buf = grad_opa_map; + } + + int32_t h_end = bg_coords.y2 - rout; + for(h = bg_coords.y1 + rout; h <= h_end; h++) { + blend_area.y1 = h; + blend_area.y2 = h; + + if(grad_dir == LV_GRAD_DIR_VER) { + blend_dsc.color = grad->color_map[h - bg_coords.y1]; + if(opa >= LV_OPA_MAX) blend_dsc.opa = grad->opa_map[h - bg_coords.y1]; + else blend_dsc.opa = LV_OPA_MIX2(grad->opa_map[h - bg_coords.y1], opa); + } + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + } + + if(mask_buf) { + lv_free(mask_buf); + lv_draw_sw_mask_free_param(&mask_rout_param); + } + if(grad) { + lv_gradient_cleanup(grad); + } + +#endif +} + +#endif /*LV_USE_DRAW_SW*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_gradient.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_gradient.c index efa158ca7..0759d943c 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_gradient.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_gradient.c @@ -7,19 +7,16 @@ * INCLUDES *********************/ #include "lv_draw_sw_gradient.h" -#include "../../misc/lv_gc.h" +#if LV_USE_DRAW_SW + #include "../../misc/lv_types.h" +#include "../../osal/lv_os.h" /********************* * DEFINES *********************/ -#if _DITHER_GRADIENT - #define GRAD_CM(r,g,b) LV_COLOR_MAKE32(r,g,b) - #define GRAD_CONV(t, x) t.full = lv_color_to32(x) -#else - #define GRAD_CM(r,g,b) LV_COLOR_MAKE(r,g,b) - #define GRAD_CONV(t, x) t = x -#endif +#define GRAD_CM(r,g,b) lv_color_make(r,g,b) +#define GRAD_CONV(t, x) t = x #undef ALIGN #if defined(LV_ARCH_64) @@ -28,319 +25,116 @@ #define ALIGN(X) (((X) + 3) & ~3) #endif -#if LV_GRAD_CACHE_DEF_SIZE != 0 && LV_GRAD_CACHE_DEF_SIZE < 256 - #error "LV_GRAD_CACHE_DEF_SIZE is too small" -#endif - /********************** * STATIC PROTOTYPES **********************/ -static lv_grad_t * next_in_cache(lv_grad_t * item); - -typedef lv_res_t (*op_cache_t)(lv_grad_t * c, void * ctx); -static lv_res_t iterate_cache(op_cache_t func, void * ctx, lv_grad_t ** out); -static size_t get_cache_item_size(lv_grad_t * c); -static lv_grad_t * allocate_item(const lv_grad_dsc_t * g, lv_coord_t w, lv_coord_t h); -static lv_res_t find_oldest_item_life(lv_grad_t * c, void * ctx); -static lv_res_t kill_oldest_item(lv_grad_t * c, void * ctx); -static lv_res_t find_item(lv_grad_t * c, void * ctx); -static void free_item(lv_grad_t * c); -static uint32_t compute_key(const lv_grad_dsc_t * g, lv_coord_t w, lv_coord_t h); - +typedef lv_result_t (*op_cache_t)(lv_grad_t * c, void * ctx); +static lv_grad_t * allocate_item(const lv_grad_dsc_t * g, int32_t w, int32_t h); /********************** * STATIC VARIABLE **********************/ -static size_t grad_cache_size = 0; -static uint8_t * grad_cache_end = 0; /********************** * STATIC FUNCTIONS **********************/ -union void_cast { - const void * ptr; - const uint32_t value; -}; -static uint32_t compute_key(const lv_grad_dsc_t * g, lv_coord_t size, lv_coord_t w) +static lv_grad_t * allocate_item(const lv_grad_dsc_t * g, int32_t w, int32_t h) { - union void_cast v; - v.ptr = g; - return (v.value ^ size ^ (w >> 1)); /*Yes, this is correct, it's like a hash that changes if the width changes*/ -} + int32_t size = g->dir == LV_GRAD_DIR_HOR ? w : h; -static size_t get_cache_item_size(lv_grad_t * c) -{ - size_t s = ALIGN(sizeof(*c)) + ALIGN(c->alloc_size * sizeof(lv_color_t)); -#if _DITHER_GRADIENT - s += ALIGN(c->size * sizeof(lv_color32_t)); -#if LV_DITHER_ERROR_DIFFUSION == 1 - s += ALIGN(c->w * sizeof(lv_scolor24_t)); -#endif -#endif - return s; -} + size_t req_size = ALIGN(sizeof(lv_grad_t)) + ALIGN(size * sizeof(lv_color_t)) + ALIGN(size * sizeof(lv_opa_t)); + lv_grad_t * item = lv_malloc(req_size); + LV_ASSERT_MALLOC(item); + if(item == NULL) return NULL; -static lv_grad_t * next_in_cache(lv_grad_t * item) -{ - if(grad_cache_size == 0) return NULL; - - if(item == NULL) - return (lv_grad_t *)LV_GC_ROOT(_lv_grad_cache_mem); - - size_t s = get_cache_item_size(item); - /*Compute the size for this cache item*/ - if((uint8_t *)item + s >= grad_cache_end) return NULL; - else return (lv_grad_t *)((uint8_t *)item + s); -} - -static lv_res_t iterate_cache(op_cache_t func, void * ctx, lv_grad_t ** out) -{ - lv_grad_t * first = next_in_cache(NULL); - while(first != NULL && first->life) { - if((*func)(first, ctx) == LV_RES_OK) { - if(out != NULL) *out = first; - return LV_RES_OK; - } - first = next_in_cache(first); - } - return LV_RES_INV; -} - -static lv_res_t find_oldest_item_life(lv_grad_t * c, void * ctx) -{ - uint32_t * min_life = (uint32_t *)ctx; - if(c->life < *min_life) *min_life = c->life; - return LV_RES_INV; -} - -static void free_item(lv_grad_t * c) -{ - size_t size = get_cache_item_size(c); - size_t next_items_size = (size_t)(grad_cache_end - (uint8_t *)c) - size; - grad_cache_end -= size; - if(next_items_size) { - uint8_t * old = (uint8_t *)c; - lv_memcpy(c, ((uint8_t *)c) + size, next_items_size); - /* Then need to fix all internal pointers too */ - while((uint8_t *)c != grad_cache_end) { - c->map = (lv_color_t *)(((uint8_t *)c->map) - size); -#if _DITHER_GRADIENT - c->hmap = (lv_color32_t *)(((uint8_t *)c->hmap) - size); -#if LV_DITHER_ERROR_DIFFUSION == 1 - c->error_acc = (lv_scolor24_t *)(((uint8_t *)c->error_acc) - size); -#endif -#endif - c = (lv_grad_t *)(((uint8_t *)c) + get_cache_item_size(c)); - } - lv_memset_00(old + next_items_size, size); - } -} - -static lv_res_t kill_oldest_item(lv_grad_t * c, void * ctx) -{ - uint32_t * min_life = (uint32_t *)ctx; - if(c->life == *min_life) { - /*Found, let's kill it*/ - free_item(c); - return LV_RES_OK; - } - return LV_RES_INV; -} - -static lv_res_t find_item(lv_grad_t * c, void * ctx) -{ - uint32_t * k = (uint32_t *)ctx; - if(c->key == *k) return LV_RES_OK; - return LV_RES_INV; -} - -static lv_grad_t * allocate_item(const lv_grad_dsc_t * g, lv_coord_t w, lv_coord_t h) -{ - lv_coord_t size = g->dir == LV_GRAD_DIR_HOR ? w : h; - lv_coord_t map_size = LV_MAX(w, h); /* The map is being used horizontally (width) unless - no dithering is selected where it's used vertically */ - - size_t req_size = ALIGN(sizeof(lv_grad_t)) + ALIGN(map_size * sizeof(lv_color_t)); -#if _DITHER_GRADIENT - req_size += ALIGN(size * sizeof(lv_color32_t)); -#if LV_DITHER_ERROR_DIFFUSION == 1 - req_size += ALIGN(w * sizeof(lv_scolor24_t)); -#endif -#endif - - size_t act_size = (size_t)(grad_cache_end - LV_GC_ROOT(_lv_grad_cache_mem)); - lv_grad_t * item = NULL; - if(req_size + act_size < grad_cache_size) { - item = (lv_grad_t *)grad_cache_end; - item->not_cached = 0; - } - else { - /*Need to evict items from cache until we find enough space to allocate this one */ - if(req_size <= grad_cache_size) { - while(act_size + req_size > grad_cache_size) { - uint32_t oldest_life = UINT32_MAX; - iterate_cache(&find_oldest_item_life, &oldest_life, NULL); - iterate_cache(&kill_oldest_item, &oldest_life, NULL); - act_size = (size_t)(grad_cache_end - LV_GC_ROOT(_lv_grad_cache_mem)); - } - item = (lv_grad_t *)grad_cache_end; - item->not_cached = 0; - } - else { - /*The cache is too small. Allocate the item manually and free it later.*/ - item = lv_mem_alloc(req_size); - LV_ASSERT_MALLOC(item); - if(item == NULL) return NULL; - item->not_cached = 1; - } - } - - item->key = compute_key(g, size, w); - item->life = 1; - item->filled = 0; - item->alloc_size = map_size; + uint8_t * p = (uint8_t *)item; + item->color_map = (lv_color_t *)(p + ALIGN(sizeof(*item))); + item->opa_map = (lv_opa_t *)(p + ALIGN(sizeof(*item)) + ALIGN(size * sizeof(lv_color_t))); item->size = size; - if(item->not_cached) { - uint8_t * p = (uint8_t *)item; - item->map = (lv_color_t *)(p + ALIGN(sizeof(*item))); -#if _DITHER_GRADIENT - item->hmap = (lv_color32_t *)(p + ALIGN(sizeof(*item)) + ALIGN(map_size * sizeof(lv_color_t))); -#if LV_DITHER_ERROR_DIFFUSION == 1 - item->error_acc = (lv_scolor24_t *)(p + ALIGN(sizeof(*item)) + ALIGN(size * sizeof(lv_grad_color_t)) + - ALIGN(map_size * sizeof(lv_color_t))); - item->w = w; -#endif -#endif - } - else { - item->map = (lv_color_t *)(grad_cache_end + ALIGN(sizeof(*item))); -#if _DITHER_GRADIENT - item->hmap = (lv_color32_t *)(grad_cache_end + ALIGN(sizeof(*item)) + ALIGN(map_size * sizeof(lv_color_t))); -#if LV_DITHER_ERROR_DIFFUSION == 1 - item->error_acc = (lv_scolor24_t *)(grad_cache_end + ALIGN(sizeof(*item)) + ALIGN(size * sizeof(lv_grad_color_t)) + - ALIGN(map_size * sizeof(lv_color_t))); - item->w = w; -#endif -#endif - grad_cache_end += req_size; - } return item; } - /********************** * FUNCTIONS **********************/ -void lv_gradient_free_cache(void) -{ - lv_mem_free(LV_GC_ROOT(_lv_grad_cache_mem)); - LV_GC_ROOT(_lv_grad_cache_mem) = grad_cache_end = NULL; - grad_cache_size = 0; -} -void lv_gradient_set_cache_size(size_t max_bytes) -{ - lv_mem_free(LV_GC_ROOT(_lv_grad_cache_mem)); - grad_cache_end = LV_GC_ROOT(_lv_grad_cache_mem) = lv_mem_alloc(max_bytes); - LV_ASSERT_MALLOC(LV_GC_ROOT(_lv_grad_cache_mem)); - lv_memset_00(LV_GC_ROOT(_lv_grad_cache_mem), max_bytes); - grad_cache_size = max_bytes; -} - -lv_grad_t * lv_gradient_get(const lv_grad_dsc_t * g, lv_coord_t w, lv_coord_t h) +lv_grad_t * lv_gradient_get(const lv_grad_dsc_t * g, int32_t w, int32_t h) { /* No gradient, no cache */ if(g->dir == LV_GRAD_DIR_NONE) return NULL; - /* Step 0: Check if the cache exist (else create it) */ - static bool inited = false; - if(!inited) { - lv_gradient_set_cache_size(LV_GRAD_CACHE_DEF_SIZE); - inited = true; - } - /* Step 1: Search cache for the given key */ - lv_coord_t size = g->dir == LV_GRAD_DIR_HOR ? w : h; - uint32_t key = compute_key(g, size, w); - lv_grad_t * item = NULL; - if(iterate_cache(&find_item, &key, &item) == LV_RES_OK) { - item->life++; /* Don't forget to bump the counter */ - return item; - } - - /* Step 2: Need to allocate an item for it */ - item = allocate_item(g, w, h); + lv_grad_t * item = allocate_item(g, w, h); if(item == NULL) { - LV_LOG_WARN("Faild to allcoate item for teh gradient"); + LV_LOG_WARN("Failed to allocate item for the gradient"); return item; } /* Step 3: Fill it with the gradient, as expected */ -#if _DITHER_GRADIENT - for(lv_coord_t i = 0; i < item->size; i++) { - item->hmap[i] = lv_gradient_calculate(g, item->size, i); + uint32_t i; + for(i = 0; i < item->size; i++) { + lv_gradient_color_calculate(g, item->size, i, &item->color_map[i], &item->opa_map[i]); } -#if LV_DITHER_ERROR_DIFFUSION == 1 - lv_memset_00(item->error_acc, w * sizeof(lv_scolor24_t)); -#endif -#else - for(lv_coord_t i = 0; i < item->size; i++) { - item->map[i] = lv_gradient_calculate(g, item->size, i); - } -#endif - return item; } -lv_grad_color_t LV_ATTRIBUTE_FAST_MEM lv_gradient_calculate(const lv_grad_dsc_t * dsc, lv_coord_t range, - lv_coord_t frac) +LV_ATTRIBUTE_FAST_MEM void lv_gradient_color_calculate(const lv_grad_dsc_t * dsc, int32_t range, + int32_t frac, lv_grad_color_t * color_out, lv_opa_t * opa_out) { lv_grad_color_t tmp; - lv_color32_t one, two; /*Clip out-of-bounds first*/ int32_t min = (dsc->stops[0].frac * range) >> 8; if(frac <= min) { GRAD_CONV(tmp, dsc->stops[0].color); - return tmp; + *color_out = tmp; + *opa_out = dsc->stops[0].opa; + return; } int32_t max = (dsc->stops[dsc->stops_count - 1].frac * range) >> 8; if(frac >= max) { GRAD_CONV(tmp, dsc->stops[dsc->stops_count - 1].color); - return tmp; + *color_out = tmp; + *opa_out = dsc->stops[dsc->stops_count - 1].opa; + return; } /*Find the 2 closest stop now*/ int32_t d = 0; + int32_t found_i = 0; for(uint8_t i = 1; i < dsc->stops_count; i++) { int32_t cur = (dsc->stops[i].frac * range) >> 8; if(frac <= cur) { - one.full = lv_color_to32(dsc->stops[i - 1].color); - two.full = lv_color_to32(dsc->stops[i].color); - min = (dsc->stops[i - 1].frac * range) >> 8; - max = (dsc->stops[i].frac * range) >> 8; - d = max - min; + found_i = i; break; } } - LV_ASSERT(d != 0); + LV_ASSERT(found_i != 0); + + lv_color_t one, two; + one = dsc->stops[found_i - 1].color; + two = dsc->stops[found_i].color; + min = (dsc->stops[found_i - 1].frac * range) >> 8; + max = (dsc->stops[found_i].frac * range) >> 8; + d = max - min; /*Then interpolate*/ frac -= min; lv_opa_t mix = (frac * 255) / d; lv_opa_t imix = 255 - mix; - lv_grad_color_t r = GRAD_CM(LV_UDIV255(two.ch.red * mix + one.ch.red * imix), - LV_UDIV255(two.ch.green * mix + one.ch.green * imix), - LV_UDIV255(two.ch.blue * mix + one.ch.blue * imix)); - return r; + *color_out = GRAD_CM(LV_UDIV255(two.red * mix + one.red * imix), + LV_UDIV255(two.green * mix + one.green * imix), + LV_UDIV255(two.blue * mix + one.blue * imix)); + + *opa_out = LV_UDIV255(dsc->stops[found_i].opa * mix + dsc->stops[found_i - 1].opa * imix); } void lv_gradient_cleanup(lv_grad_t * grad) { - if(grad->not_cached) { - lv_mem_free(grad); - } + lv_free(grad); } + +#endif /*LV_USE_DRAW_SW*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_gradient.h b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_gradient.h index 95a3c4e4e..19fa697b3 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_gradient.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_gradient.h @@ -15,7 +15,8 @@ extern "C" { *********************/ #include "../../misc/lv_color.h" #include "../../misc/lv_style.h" -#include "lv_draw_sw_dither.h" + +#if LV_USE_DRAW_SW /********************* * DEFINES @@ -24,42 +25,17 @@ extern "C" { #error LVGL needs at least 2 stops for gradients. Please increase the LV_GRADIENT_MAX_STOPS #endif - /********************** * TYPEDEFS **********************/ -#if _DITHER_GRADIENT -typedef lv_color32_t lv_grad_color_t; -#else typedef lv_color_t lv_grad_color_t; -#endif -/** To avoid recomputing gradient for each draw operation, - * it's possible to cache the computation in this structure instance. - * Whenever possible, this structure is reused instead of recomputing the gradient map */ typedef struct _lv_gradient_cache_t { - uint32_t key; /**< A discriminating key that's built from the drawing operation. - * If the key does not match, the cache item is not used */ - uint32_t life : 30; /**< A life counter that's incremented on usage. Higher counter is - * less likely to be evicted from the cache */ - uint32_t filled : 1; /**< Used to skip dithering in it if already done */ - uint32_t not_cached: 1; /**< The cache was too small so this item is not managed by the cache*/ - lv_color_t * map; /**< The computed gradient low bitdepth color map, points into the - * cache's buffer, no free needed */ - lv_coord_t alloc_size; /**< The map allocated size in colors */ - lv_coord_t size; /**< The computed gradient color map size, in colors */ -#if _DITHER_GRADIENT - lv_color32_t * hmap; /**< If dithering, we need to store the current, high bitdepth gradient - * map too, points to the cache's buffer, no free needed */ -#if LV_DITHER_ERROR_DIFFUSION == 1 - lv_scolor24_t * error_acc; /**< Error diffusion dithering algorithm requires storing the last error - * drawn, points to the cache's buffer, no free needed */ - lv_coord_t w; /**< The error array width in pixels */ -#endif -#endif + lv_color_t * color_map; + lv_opa_t * opa_map; + uint32_t size; } lv_grad_t; - /********************** * PROTOTYPES **********************/ @@ -69,20 +45,12 @@ typedef struct _lv_gradient_cache_t { * @param range The range to use in computation. * @param frac The current part used in the range. frac is in [0; range] */ -lv_grad_color_t /* LV_ATTRIBUTE_FAST_MEM */ lv_gradient_calculate(const lv_grad_dsc_t * dsc, lv_coord_t range, - lv_coord_t frac); -/** - * Set the gradient cache size - * @param max_bytes Max cahce size - */ -void lv_gradient_set_cache_size(size_t max_bytes); - -/** Free the gradient cache */ -void lv_gradient_free_cache(void); +LV_ATTRIBUTE_FAST_MEM void lv_gradient_color_calculate(const lv_grad_dsc_t * dsc, int32_t range, + int32_t frac, lv_grad_color_t * color_out, lv_opa_t * opa_out); /** Get a gradient cache from the given parameters */ -lv_grad_t * lv_gradient_get(const lv_grad_dsc_t * gradient, lv_coord_t w, lv_coord_t h); +lv_grad_t * lv_gradient_get(const lv_grad_dsc_t * gradient, int32_t w, int32_t h); /** * Clean up the gradient item after it was get with `lv_grad_get_from_cache`. @@ -90,6 +58,8 @@ lv_grad_t * lv_gradient_get(const lv_grad_dsc_t * gradient, lv_coord_t w, lv_coo */ void lv_gradient_cleanup(lv_grad_t * grad); +#endif /*LV_USE_DRAW_SW*/ + #ifdef __cplusplus } /*extern "C"*/ #endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_img.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_img.c index 7181c15ff..c5518e88c 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_img.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_img.c @@ -1,5 +1,5 @@ /** - * @file lv_draw_img.c + * @file lv_draw_sw_img.c * */ @@ -7,17 +7,40 @@ * INCLUDES *********************/ #include "lv_draw_sw.h" -#include "../lv_img_cache.h" -#include "../../hal/lv_hal_disp.h" +#if LV_USE_DRAW_SW + +#include "../../display/lv_display.h" +#include "../../display/lv_display_private.h" #include "../../misc/lv_log.h" #include "../../core/lv_refr.h" -#include "../../misc/lv_mem.h" +#include "../../stdlib/lv_mem.h" #include "../../misc/lv_math.h" +#include "../../misc/lv_color.h" +#include "../../stdlib/lv_string.h" +#include "../../core/lv_global.h" + +#if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_HELIUM + #include "arm2d/lv_draw_sw_helium.h" +#elif LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_CUSTOM + #include LV_DRAW_SW_ASM_CUSTOM_INCLUDE +#endif /********************* * DEFINES *********************/ -#define MAX_BUF_SIZE (uint32_t) lv_disp_get_hor_res(_lv_refr_get_disp_refreshing()) +#define MAX_BUF_SIZE (uint32_t) (4 * lv_display_get_horizontal_resolution(_lv_refr_get_disp_refreshing()) * lv_color_format_get_size(lv_display_get_color_format(_lv_refr_get_disp_refreshing()))) + +#ifndef LV_DRAW_SW_IMAGE + #define LV_DRAW_SW_IMAGE(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB565_RECOLOR + #define LV_DRAW_SW_RGB565_RECOLOR(...) LV_RESULT_INVALID +#endif + +#ifndef LV_DRAW_SW_RGB888_RECOLOR + #define LV_DRAW_SW_RGB888_RECOLOR(...) LV_RESULT_INVALID +#endif /********************** * TYPEDEFS @@ -26,12 +49,15 @@ /********************** * STATIC PROTOTYPES **********************/ -static void convert_cb(const lv_area_t * dest_area, const void * src_buf, lv_coord_t src_w, lv_coord_t src_h, - lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf); + +static void img_draw_core(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup, + const lv_area_t * img_coords, const lv_area_t * clipped_img_area); /********************** * STATIC VARIABLES **********************/ +#define _draw_info LV_GLOBAL_DEFAULT()->draw_info /********************** * MACROS @@ -41,158 +67,104 @@ static void convert_cb(const lv_area_t * dest_area, const void * src_buf, lv_coo * GLOBAL FUNCTIONS **********************/ - -void LV_ATTRIBUTE_FAST_MEM lv_draw_sw_img_decoded(struct _lv_draw_ctx_t * draw_ctx, - const lv_draw_img_dsc_t * draw_dsc, - const lv_area_t * coords, const uint8_t * src_buf, - lv_img_cf_t cf) +void lv_draw_sw_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, const lv_area_t * coords) { - /*Use the clip area as draw area*/ + lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src; + + /*It can happen that nothing was draw on a layer and therefore its buffer is not allocated. + *In this case just return. */ + if(layer_to_draw->draw_buf == NULL) return; + + lv_draw_image_dsc_t new_draw_dsc = *draw_dsc; + new_draw_dsc.src = layer_to_draw->draw_buf; + lv_draw_sw_image(draw_unit, &new_draw_dsc, coords); +#if LV_USE_LAYER_DEBUG || LV_USE_PARALLEL_DRAW_DEBUG + lv_area_t area_rot; + lv_area_copy(&area_rot, coords); + if(draw_dsc->rotation || draw_dsc->scale_x != LV_SCALE_NONE || draw_dsc->scale_y != LV_SCALE_NONE) { + int32_t w = lv_area_get_width(coords); + int32_t h = lv_area_get_height(coords); + + _lv_image_buf_get_transformed_area(&area_rot, w, h, draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, + &draw_dsc->pivot); + + area_rot.x1 += coords->x1; + area_rot.y1 += coords->y1; + area_rot.x2 += coords->x1; + area_rot.y2 += coords->y1; + } lv_area_t draw_area; - lv_area_copy(&draw_area, draw_ctx->clip_area); - - bool mask_any = lv_draw_mask_is_any(&draw_area); - bool transform = draw_dsc->angle != 0 || draw_dsc->zoom != LV_IMG_ZOOM_NONE ? true : false; - - lv_area_t blend_area; - lv_draw_sw_blend_dsc_t blend_dsc; - - lv_memset_00(&blend_dsc, sizeof(lv_draw_sw_blend_dsc_t)); - blend_dsc.opa = draw_dsc->opa; - blend_dsc.blend_mode = draw_dsc->blend_mode; - blend_dsc.blend_area = &blend_area; - - /*The simplest case just copy the pixels into the draw_buf*/ - if(!mask_any && !transform && cf == LV_IMG_CF_TRUE_COLOR && draw_dsc->recolor_opa == LV_OPA_TRANSP) { - blend_dsc.src_buf = (const lv_color_t *)src_buf; - - blend_dsc.blend_area = coords; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - else if(!mask_any && !transform && cf == LV_IMG_CF_ALPHA_8BIT) { - lv_area_t clipped_coords; - if(!_lv_area_intersect(&clipped_coords, coords, draw_ctx->clip_area)) return; - - blend_dsc.mask_buf = (lv_opa_t *)src_buf; - blend_dsc.mask_area = coords; - blend_dsc.src_buf = NULL; - blend_dsc.color = draw_dsc->recolor; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - - blend_dsc.blend_area = coords; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } -#if LV_COLOR_DEPTH == 16 - else if(!mask_any && !transform && cf == LV_IMG_CF_RGB565A8 && draw_dsc->recolor_opa == LV_OPA_TRANSP) { - lv_coord_t src_w = lv_area_get_width(coords); - lv_coord_t src_h = lv_area_get_height(coords); - blend_dsc.src_buf = (const lv_color_t *)src_buf; - blend_dsc.mask_buf = (lv_opa_t *)src_buf; - blend_dsc.mask_buf += sizeof(lv_color_t) * src_w * src_h; - blend_dsc.blend_area = coords; - blend_dsc.mask_area = coords; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } + if(!_lv_area_intersect(&draw_area, &area_rot, draw_unit->clip_area)) return; #endif - /*In the other cases every pixel need to be checked one-by-one*/ + +#if LV_USE_LAYER_DEBUG + lv_draw_fill_dsc_t fill_dsc; + lv_draw_fill_dsc_init(&fill_dsc); + fill_dsc.color = lv_color_hex(layer_to_draw->color_format == LV_COLOR_FORMAT_ARGB8888 ? 0xff0000 : 0x00ff00); + fill_dsc.opa = LV_OPA_20; + lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot); + + lv_draw_border_dsc_t border_dsc; + lv_draw_border_dsc_init(&border_dsc); + border_dsc.color = fill_dsc.color; + border_dsc.opa = LV_OPA_60; + border_dsc.width = 2; + lv_draw_sw_border(draw_unit, &border_dsc, &area_rot); + +#endif + +#if LV_USE_PARALLEL_DRAW_DEBUG + uint32_t idx = 0; + lv_draw_unit_t * draw_unit_tmp = _draw_info.unit_head; + while(draw_unit_tmp != draw_unit) { + draw_unit_tmp = draw_unit_tmp->next; + idx++; + } + + lv_draw_fill_dsc_t fill_dsc; + lv_draw_rect_dsc_init(&fill_dsc); + fill_dsc.color = lv_palette_main(idx % _LV_PALETTE_LAST); + fill_dsc.opa = LV_OPA_10; + lv_draw_sw_fill(draw_unit, &fill_dsc, &area_rot); + + lv_draw_border_dsc_t border_dsc; + lv_draw_border_dsc_init(&border_dsc); + border_dsc.color = lv_palette_main(idx % _LV_PALETTE_LAST); + border_dsc.opa = LV_OPA_100; + border_dsc.width = 2; + lv_draw_sw_border(draw_unit, &border_dsc, &area_rot); + + lv_point_t txt_size; + lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE); + + lv_area_t txt_area; + txt_area.x1 = draw_area.x1; + txt_area.x2 = draw_area.x1 + txt_size.x - 1; + txt_area.y2 = draw_area.y2; + txt_area.y1 = draw_area.y2 - txt_size.y + 1; + + lv_draw_fill_dsc_init(&fill_dsc); + fill_dsc.color = lv_color_black(); + lv_draw_sw_fill(draw_unit, &fill_dsc, &txt_area); + + char buf[8]; + lv_snprintf(buf, sizeof(buf), "%d", idx); + lv_draw_label_dsc_t label_dsc; + lv_draw_label_dsc_init(&label_dsc); + label_dsc.color = lv_color_white(); + label_dsc.text = buf; + lv_draw_sw_label(draw_unit, &label_dsc, &txt_area); +#endif +} + +void lv_draw_sw_image(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords) +{ + if(!draw_dsc->tile) { + _lv_draw_image_normal_helper(draw_unit, draw_dsc, coords, img_draw_core); + } else { - blend_area.x1 = draw_ctx->clip_area->x1; - blend_area.x2 = draw_ctx->clip_area->x2; - blend_area.y1 = draw_ctx->clip_area->y1; - blend_area.y2 = draw_ctx->clip_area->y2; - - lv_coord_t src_w = lv_area_get_width(coords); - lv_coord_t src_h = lv_area_get_height(coords); - lv_coord_t blend_h = lv_area_get_height(&blend_area); - lv_coord_t blend_w = lv_area_get_width(&blend_area); - - uint32_t max_buf_size = MAX_BUF_SIZE; - uint32_t blend_size = lv_area_get_size(&blend_area); - uint32_t buf_h; - uint32_t buf_w = blend_w; - if(blend_size <= max_buf_size) { - buf_h = blend_h; - } - else { - /*Round to full lines*/ - buf_h = max_buf_size / blend_w; - } - - /*Create buffers and masks*/ - uint32_t buf_size = buf_w * buf_h; - - lv_color_t * rgb_buf = lv_mem_buf_get(buf_size * sizeof(lv_color_t)); - lv_opa_t * mask_buf = lv_mem_buf_get(buf_size); - blend_dsc.mask_buf = mask_buf; - blend_dsc.mask_area = &blend_area; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - blend_dsc.src_buf = rgb_buf; - lv_coord_t y_last = blend_area.y2; - blend_area.y2 = blend_area.y1 + buf_h - 1; - - lv_draw_mask_res_t mask_res_def = (cf != LV_IMG_CF_TRUE_COLOR || draw_dsc->angle || - draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? - LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; - blend_dsc.mask_res = mask_res_def; - - while(blend_area.y1 <= y_last) { - /*Apply transformations if any or separate the channels*/ - lv_area_t transform_area; - lv_area_copy(&transform_area, &blend_area); - lv_area_move(&transform_area, -coords->x1, -coords->y1); - if(transform) { - lv_draw_transform(draw_ctx, &transform_area, src_buf, src_w, src_h, src_w, - draw_dsc, cf, rgb_buf, mask_buf); - } - else { - convert_cb(&transform_area, src_buf, src_w, src_h, src_w, draw_dsc, cf, rgb_buf, mask_buf); - } - - /*Apply recolor*/ - if(draw_dsc->recolor_opa > LV_OPA_MIN) { - uint16_t premult_v[3]; - lv_opa_t recolor_opa = draw_dsc->recolor_opa; - lv_color_t recolor = draw_dsc->recolor; - lv_color_premult(recolor, recolor_opa, premult_v); - recolor_opa = 255 - recolor_opa; - uint32_t i; - for(i = 0; i < buf_size; i++) { - rgb_buf[i] = lv_color_mix_premult(premult_v, rgb_buf[i], recolor_opa); - } - } -#if LV_DRAW_COMPLEX - /*Apply the masks if any*/ - if(mask_any) { - lv_coord_t y; - lv_opa_t * mask_buf_tmp = mask_buf; - for(y = blend_area.y1; y <= blend_area.y2; y++) { - lv_draw_mask_res_t mask_res_line; - mask_res_line = lv_draw_mask_apply(mask_buf_tmp, blend_area.x1, y, blend_w); - - if(mask_res_line == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(mask_buf_tmp, blend_w); - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - } - else if(mask_res_line == LV_DRAW_MASK_RES_CHANGED) { - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - } - mask_buf_tmp += blend_w; - } - } -#endif - - /*Blend*/ - lv_draw_sw_blend(draw_ctx, &blend_dsc); - - /*Go the the next lines*/ - blend_area.y1 = blend_area.y2 + 1; - blend_area.y2 = blend_area.y1 + buf_h - 1; - if(blend_area.y2 > y_last) blend_area.y2 = y_last; - } - - lv_mem_buf_release(mask_buf); - lv_mem_buf_release(rgb_buf); + _lv_draw_image_tiled_helper(draw_unit, draw_dsc, coords, img_draw_core); } } @@ -200,100 +172,231 @@ void LV_ATTRIBUTE_FAST_MEM lv_draw_sw_img_decoded(struct _lv_draw_ctx_t * draw_c * STATIC FUNCTIONS **********************/ -/* Separate the image channels to RGB and Alpha to match LV_COLOR_DEPTH settings*/ -static void convert_cb(const lv_area_t * dest_area, const void * src_buf, lv_coord_t src_w, lv_coord_t src_h, - lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf) +static void img_draw_core(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup, + const lv_area_t * img_coords, const lv_area_t * clipped_img_area) { - LV_UNUSED(draw_dsc); - LV_UNUSED(src_h); - LV_UNUSED(src_w); + bool transformed = draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE || + draw_dsc->scale_y != LV_SCALE_NONE ? true : false; - const uint8_t * src_tmp8 = (const uint8_t *)src_buf; - lv_coord_t y; - lv_coord_t x; + lv_draw_sw_blend_dsc_t blend_dsc; + const lv_draw_buf_t * decoded = decoder_dsc->decoded; + const uint8_t * src_buf = decoded->data; + const lv_image_header_t * header = &decoded->header; + uint32_t img_stride = decoded->header.stride; + lv_color_format_t cf = decoded->header.cf; - if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { - uint32_t px_cnt = lv_area_get_size(dest_area); - lv_memset_ff(abuf, px_cnt); + lv_memzero(&blend_dsc, sizeof(lv_draw_sw_blend_dsc_t)); + blend_dsc.opa = draw_dsc->opa; + blend_dsc.blend_mode = draw_dsc->blend_mode; + blend_dsc.src_stride = img_stride; - src_tmp8 += (src_stride * dest_area->y1 * sizeof(lv_color_t)) + dest_area->x1 * sizeof(lv_color_t); - uint32_t dest_w = lv_area_get_width(dest_area); - uint32_t dest_w_byte = dest_w * sizeof(lv_color_t); + if(!transformed && cf == LV_COLOR_FORMAT_A8) { + lv_area_t clipped_coords; + if(!_lv_area_intersect(&clipped_coords, img_coords, draw_unit->clip_area)) return; - lv_coord_t src_stride_byte = src_stride * sizeof(lv_color_t); - lv_color_t * cbuf_tmp = cbuf; - for(y = dest_area->y1; y <= dest_area->y2; y++) { - lv_memcpy(cbuf_tmp, src_tmp8, dest_w_byte); - src_tmp8 += src_stride_byte; - cbuf_tmp += dest_w; + blend_dsc.mask_buf = (lv_opa_t *)src_buf; + blend_dsc.mask_area = img_coords; + blend_dsc.mask_stride = img_stride; + blend_dsc.src_buf = NULL; + blend_dsc.color = draw_dsc->recolor; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + + blend_dsc.blend_area = img_coords; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + else if(!transformed && cf == LV_COLOR_FORMAT_RGB565A8 && draw_dsc->recolor_opa <= LV_OPA_MIN) { + int32_t src_h = lv_area_get_height(img_coords); + int32_t src_w = lv_area_get_width(img_coords); + blend_dsc.src_area = img_coords; + blend_dsc.src_buf = src_buf; + blend_dsc.mask_buf = (lv_opa_t *)src_buf; + blend_dsc.mask_buf += img_stride * src_w / header->w * src_h; + /** + * Note, for RGB565A8, lacking of stride parameter, we always use + * always half of RGB map stride as alpha map stride. The image should + * be generated in this way too. + */ + blend_dsc.mask_stride = img_stride / 2; + blend_dsc.blend_area = img_coords; + blend_dsc.mask_area = img_coords; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + blend_dsc.src_color_format = LV_COLOR_FORMAT_RGB565; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + /*The simplest case just copy the pixels into the draw_buf. Blending will convert the colors if needed*/ + else if(!transformed && draw_dsc->recolor_opa <= LV_OPA_MIN) { + blend_dsc.src_area = img_coords; + blend_dsc.src_buf = src_buf; + blend_dsc.blend_area = img_coords; + blend_dsc.src_color_format = cf; + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + /* check whethr it is possible to accelerate the operation in synchronouse mode */ + else if(LV_RESULT_INVALID == LV_DRAW_SW_IMAGE(transformed, /* whether require transform */ + cf, /* image format */ + src_buf, /* image buffer */ + img_coords, /* src_h, src_w, src_x1, src_y1 */ + img_stride, /* image stride */ + clipped_img_area, /* blend area */ + draw_unit, /* target buffer, buffer width, buffer height, buffer stride */ + draw_dsc)) { /* opa, recolour_opa and colour */ + /*In the other cases every pixel need to be checked one-by-one*/ + + lv_area_t blend_area = *clipped_img_area; + blend_dsc.blend_area = &blend_area; + + int32_t src_w = lv_area_get_width(img_coords); + int32_t src_h = lv_area_get_height(img_coords); + int32_t blend_w = lv_area_get_width(&blend_area); + int32_t blend_h = lv_area_get_height(&blend_area); + + lv_color_format_t cf_final = cf; + if(transformed) { + if(cf == LV_COLOR_FORMAT_RGB888 || cf == LV_COLOR_FORMAT_XRGB8888) cf_final = LV_COLOR_FORMAT_ARGB8888; + else if(cf == LV_COLOR_FORMAT_RGB565) cf_final = LV_COLOR_FORMAT_RGB565A8; } - /*Make "holes" for with Chroma keying*/ - if(cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { - uint32_t i; - lv_color_t chk = LV_COLOR_CHROMA_KEY; -#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 - uint8_t * cbuf_uint = (uint8_t *)cbuf; - uint8_t chk_v = chk.full; -#elif LV_COLOR_DEPTH == 16 - uint16_t * cbuf_uint = (uint16_t *)cbuf; - uint16_t chk_v = chk.full; -#elif LV_COLOR_DEPTH == 32 - uint32_t * cbuf_uint = (uint32_t *)cbuf; - uint32_t chk_v = chk.full; -#endif - for(i = 0; i < px_cnt; i++) { - if(chk_v == cbuf_uint[i]) abuf[i] = 0x00; + uint8_t * tmp_buf; + uint32_t px_size = lv_color_format_get_size(cf_final); + int32_t buf_h; + if(cf_final == LV_COLOR_FORMAT_RGB565A8) { + uint32_t buf_stride = blend_w * 3; + buf_h = MAX_BUF_SIZE / buf_stride; + if(buf_h > blend_h) buf_h = blend_h; + tmp_buf = lv_malloc(buf_stride * buf_h); + } + else { + uint32_t buf_stride = blend_w * lv_color_format_get_size(cf_final); + buf_h = MAX_BUF_SIZE / buf_stride; + if(buf_h > blend_h) buf_h = blend_h; + tmp_buf = lv_malloc(buf_stride * buf_h); + } + LV_ASSERT_MALLOC(tmp_buf); + + blend_dsc.src_buf = tmp_buf; + blend_dsc.src_color_format = cf_final; + int32_t y_last = blend_area.y2; + blend_area.y2 = blend_area.y1 + buf_h - 1; + + blend_dsc.src_area = &blend_area; + if(cf_final == LV_COLOR_FORMAT_RGB565A8) { + /*RGB565A8 images will blended as RGB565 + mask + *Therefore the stride can be different. */ + blend_dsc.src_stride = blend_w * 2; + blend_dsc.mask_buf = tmp_buf + blend_w * 2 * buf_h; + blend_dsc.mask_stride = blend_w; + blend_dsc.mask_area = &blend_area; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + blend_dsc.src_color_format = LV_COLOR_FORMAT_RGB565; + } + else if(cf_final == LV_COLOR_FORMAT_A8) { + blend_dsc.mask_buf = blend_dsc.src_buf; + blend_dsc.mask_stride = blend_w; + blend_dsc.mask_area = &blend_area; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + blend_dsc.color = draw_dsc->recolor; + blend_dsc.src_buf = NULL; + } + else { + blend_dsc.src_stride = blend_w * lv_color_format_get_size(cf_final); + } + + while(blend_area.y1 <= y_last) { + /*Apply transformations if any or separate the channels*/ + lv_area_t relative_area; + lv_area_copy(&relative_area, &blend_area); + lv_area_move(&relative_area, -img_coords->x1, -img_coords->y1); + if(transformed) { + lv_draw_sw_transform(draw_unit, &relative_area, src_buf, src_w, src_h, img_stride, + draw_dsc, sup, cf, tmp_buf); + } + else if(draw_dsc->recolor_opa >= LV_OPA_MIN) { + int32_t h = lv_area_get_height(&relative_area); + if(cf_final == LV_COLOR_FORMAT_RGB565A8) { + uint32_t stride_px = img_stride / 2; + const uint8_t * rgb_src_buf = src_buf + stride_px * 2 * relative_area.y1 + relative_area.x1 * 2; + const uint8_t * a_src_buf = src_buf + stride_px * 2 * src_h + stride_px * relative_area.y1 + + relative_area.x1; + uint8_t * rgb_dest_buf = tmp_buf; + uint8_t * a_dest_buf = (uint8_t *)blend_dsc.mask_buf; + int32_t i; + for(i = 0; i < h; i++) { + lv_memcpy(rgb_dest_buf, rgb_src_buf, blend_w * 2); + lv_memcpy(a_dest_buf, a_src_buf, blend_w); + rgb_src_buf += stride_px * 2; + a_src_buf += stride_px; + rgb_dest_buf += blend_w * 2; + a_dest_buf += blend_w; + } + } + else if(cf_final != LV_COLOR_FORMAT_A8) { + const uint8_t * src_buf_tmp = src_buf + img_stride * relative_area.y1 + relative_area.x1 * px_size; + uint8_t * dest_buf_tmp = tmp_buf; + int32_t i; + for(i = 0; i < h; i++) { + lv_memcpy(dest_buf_tmp, src_buf_tmp, blend_w * px_size); + dest_buf_tmp += blend_w * px_size; + src_buf_tmp += img_stride; + } + } + } + + /*Apply recolor*/ + if(draw_dsc->recolor_opa > LV_OPA_MIN) { + lv_color_t color = draw_dsc->recolor; + lv_opa_t mix = draw_dsc->recolor_opa; + lv_opa_t mix_inv = 255 - mix; + if(cf_final == LV_COLOR_FORMAT_RGB565A8 || cf_final == LV_COLOR_FORMAT_RGB565) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_RECOLOR(tmp_buf, blend_area, color, mix)) { + uint16_t c_mult[3]; + c_mult[0] = (color.blue >> 3) * mix; + c_mult[1] = (color.green >> 2) * mix; + c_mult[2] = (color.red >> 3) * mix; + uint16_t * buf16 = (uint16_t *)tmp_buf; + int32_t i; + int32_t size = lv_area_get_size(&blend_area); + for(i = 0; i < size; i++) { + buf16[i] = (((c_mult[2] + ((buf16[i] >> 11) & 0x1F) * mix_inv) << 3) & 0xF800) + + (((c_mult[1] + ((buf16[i] >> 5) & 0x3F) * mix_inv) >> 3) & 0x07E0) + + ((c_mult[0] + (buf16[i] & 0x1F) * mix_inv) >> 8); + } + } + } + else if(cf_final != LV_COLOR_FORMAT_A8) { + if(LV_RESULT_INVALID == LV_DRAW_SW_RGB888_RECOLOR(tmp_buf, blend_area, color, mix, cf_final)) { + uint32_t size = lv_area_get_size(&blend_area); + uint32_t i; + uint16_t c_mult[3]; + c_mult[0] = color.blue * mix; + c_mult[1] = color.green * mix; + c_mult[2] = color.red * mix; + uint8_t * tmp_buf_2 = tmp_buf; + for(i = 0; i < size * px_size; i += px_size) { + tmp_buf_2[i + 0] = (c_mult[0] + (tmp_buf_2[i + 0] * mix_inv)) >> 8; + tmp_buf_2[i + 1] = (c_mult[1] + (tmp_buf_2[i + 1] * mix_inv)) >> 8; + tmp_buf_2[i + 2] = (c_mult[2] + (tmp_buf_2[i + 2] * mix_inv)) >> 8; + } + } + } + } + + /*Blend*/ + lv_draw_sw_blend(draw_unit, &blend_dsc); + + /*Go to the next area*/ + blend_area.y1 = blend_area.y2 + 1; + blend_area.y2 = blend_area.y1 + buf_h - 1; + if(blend_area.y2 > y_last) { + blend_area.y2 = y_last; + if(cf_final == LV_COLOR_FORMAT_RGB565A8) { + blend_dsc.mask_buf = tmp_buf + blend_w * 2 * lv_area_get_height(&blend_area); + } } } - } - else if(cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { - src_tmp8 += (src_stride * dest_area->y1 * LV_IMG_PX_SIZE_ALPHA_BYTE) + dest_area->x1 * LV_IMG_PX_SIZE_ALPHA_BYTE; - lv_coord_t src_new_line_step_px = (src_stride - lv_area_get_width(dest_area)); - lv_coord_t src_new_line_step_byte = src_new_line_step_px * LV_IMG_PX_SIZE_ALPHA_BYTE; - - lv_coord_t dest_h = lv_area_get_height(dest_area); - lv_coord_t dest_w = lv_area_get_width(dest_area); - for(y = 0; y < dest_h; y++) { - for(x = 0; x < dest_w; x++) { - abuf[x] = src_tmp8[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; -#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 - cbuf[x].full = *src_tmp8; -#elif LV_COLOR_DEPTH == 16 - cbuf[x].full = *src_tmp8 + ((*(src_tmp8 + 1)) << 8); -#elif LV_COLOR_DEPTH == 32 - cbuf[x] = *((lv_color_t *) src_tmp8); - cbuf[x].ch.alpha = 0xff; -#endif - src_tmp8 += LV_IMG_PX_SIZE_ALPHA_BYTE; - - } - cbuf += dest_w; - abuf += dest_w; - src_tmp8 += src_new_line_step_byte; - } - } - else if(cf == LV_IMG_CF_RGB565A8) { - src_tmp8 += (src_stride * dest_area->y1 * sizeof(lv_color_t)) + dest_area->x1 * sizeof(lv_color_t); - - lv_coord_t src_stride_byte = src_stride * sizeof(lv_color_t); - - lv_coord_t dest_h = lv_area_get_height(dest_area); - lv_coord_t dest_w = lv_area_get_width(dest_area); - for(y = 0; y < dest_h; y++) { - lv_memcpy(cbuf, src_tmp8, dest_w * sizeof(lv_color_t)); - cbuf += dest_w; - src_tmp8 += src_stride_byte; - } - - src_tmp8 = (const uint8_t *)src_buf; - src_tmp8 += sizeof(lv_color_t) * src_w * src_h; - src_tmp8 += src_stride * dest_area->y1 + dest_area->x1; - for(y = 0; y < dest_h; y++) { - lv_memcpy(abuf, src_tmp8, dest_w); - abuf += dest_w; - src_tmp8 += src_stride; - } + lv_free(tmp_buf); } } + +#endif /*LV_USE_DRAW_SW*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_layer.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_layer.c deleted file mode 100644 index b53c662e2..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_layer.c +++ /dev/null @@ -1,150 +0,0 @@ -/** - * @file lv_draw_sw_layer.h - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_draw_sw.h" -#include "../../hal/lv_hal_disp.h" -#include "../../misc/lv_area.h" -#include "../../core/lv_refr.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * GLOBAL VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - - -struct _lv_draw_layer_ctx_t * lv_draw_sw_layer_create(struct _lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx, - lv_draw_layer_flags_t flags) -{ - if(LV_COLOR_SCREEN_TRANSP == 0 && (flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA)) { - LV_LOG_WARN("Rendering this widget needs LV_COLOR_SCREEN_TRANSP 1"); - return NULL; - } - - lv_draw_sw_layer_ctx_t * layer_sw_ctx = (lv_draw_sw_layer_ctx_t *) layer_ctx; - uint32_t px_size = flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA ? LV_IMG_PX_SIZE_ALPHA_BYTE : sizeof(lv_color_t); - if(flags & LV_DRAW_LAYER_FLAG_CAN_SUBDIVIDE) { - layer_sw_ctx->buf_size_bytes = LV_LAYER_SIMPLE_BUF_SIZE; - uint32_t full_size = lv_area_get_size(&layer_sw_ctx->base_draw.area_full) * px_size; - if(layer_sw_ctx->buf_size_bytes > full_size) layer_sw_ctx->buf_size_bytes = full_size; - layer_sw_ctx->base_draw.buf = lv_mem_alloc(layer_sw_ctx->buf_size_bytes); - if(layer_sw_ctx->base_draw.buf == NULL) { - LV_LOG_WARN("Cannot allocate %"LV_PRIu32" bytes for layer buffer. Allocating %"LV_PRIu32" bytes instead. (Reduced performance)", - (uint32_t)layer_sw_ctx->buf_size_bytes, (uint32_t)LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE * px_size); - layer_sw_ctx->buf_size_bytes = LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE; - layer_sw_ctx->base_draw.buf = lv_mem_alloc(layer_sw_ctx->buf_size_bytes); - if(layer_sw_ctx->base_draw.buf == NULL) { - return NULL; - } - } - layer_sw_ctx->base_draw.area_act = layer_sw_ctx->base_draw.area_full; - layer_sw_ctx->base_draw.area_act.y2 = layer_sw_ctx->base_draw.area_full.y1; - lv_coord_t w = lv_area_get_width(&layer_sw_ctx->base_draw.area_act); - layer_sw_ctx->base_draw.max_row_with_alpha = layer_sw_ctx->buf_size_bytes / w / LV_IMG_PX_SIZE_ALPHA_BYTE; - layer_sw_ctx->base_draw.max_row_with_no_alpha = layer_sw_ctx->buf_size_bytes / w / sizeof(lv_color_t); - } - else { - layer_sw_ctx->base_draw.area_act = layer_sw_ctx->base_draw.area_full; - layer_sw_ctx->buf_size_bytes = lv_area_get_size(&layer_sw_ctx->base_draw.area_full) * px_size; - layer_sw_ctx->base_draw.buf = lv_mem_alloc(layer_sw_ctx->buf_size_bytes); - lv_memset_00(layer_sw_ctx->base_draw.buf, layer_sw_ctx->buf_size_bytes); - layer_sw_ctx->has_alpha = flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA ? 1 : 0; - if(layer_sw_ctx->base_draw.buf == NULL) { - return NULL; - } - - draw_ctx->buf = layer_sw_ctx->base_draw.buf; - draw_ctx->buf_area = &layer_sw_ctx->base_draw.area_act; - draw_ctx->clip_area = &layer_sw_ctx->base_draw.area_act; - - lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing(); - disp_refr->driver->screen_transp = flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA ? 1 : 0; - } - - return layer_ctx; -} - -void lv_draw_sw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, - lv_draw_layer_flags_t flags) -{ - - lv_draw_sw_layer_ctx_t * layer_sw_ctx = (lv_draw_sw_layer_ctx_t *) layer_ctx; - lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing(); - if(flags & LV_DRAW_LAYER_FLAG_HAS_ALPHA) { - lv_memset_00(layer_ctx->buf, layer_sw_ctx->buf_size_bytes); - layer_sw_ctx->has_alpha = 1; - disp_refr->driver->screen_transp = 1; - } - else { - layer_sw_ctx->has_alpha = 0; - disp_refr->driver->screen_transp = 0; - } - - draw_ctx->buf = layer_ctx->buf; - draw_ctx->buf_area = &layer_ctx->area_act; - draw_ctx->clip_area = &layer_ctx->area_act; -} - -void lv_draw_sw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, - const lv_draw_img_dsc_t * draw_dsc) -{ - lv_draw_sw_layer_ctx_t * layer_sw_ctx = (lv_draw_sw_layer_ctx_t *) layer_ctx; - - lv_img_dsc_t img; - img.data = draw_ctx->buf; - img.header.always_zero = 0; - img.header.w = lv_area_get_width(draw_ctx->buf_area); - img.header.h = lv_area_get_height(draw_ctx->buf_area); - img.header.cf = layer_sw_ctx->has_alpha ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR; - - /*Restore the original draw_ctx*/ - draw_ctx->buf = layer_ctx->original.buf; - draw_ctx->buf_area = layer_ctx->original.buf_area; - draw_ctx->clip_area = layer_ctx->original.clip_area; - lv_disp_t * disp_refr = _lv_refr_get_disp_refreshing(); - disp_refr->driver->screen_transp = layer_ctx->original.screen_transp; - - /*Blend the layer*/ - lv_draw_img(draw_ctx, draw_dsc, &layer_ctx->area_act, &img); - lv_draw_wait_for_finish(draw_ctx); - lv_img_cache_invalidate_src(&img); -} - -void lv_draw_sw_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx) -{ - LV_UNUSED(draw_ctx); - - lv_mem_free(layer_ctx->buf); -} - - -/********************** - * STATIC FUNCTIONS - **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_letter.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_letter.c index ee27bc61b..10cd35c6f 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_letter.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_letter.c @@ -7,13 +7,16 @@ * INCLUDES *********************/ #include "lv_draw_sw.h" -#include "../../hal/lv_hal_disp.h" +#if LV_USE_DRAW_SW + +#include "../../display/lv_display.h" #include "../../misc/lv_math.h" #include "../../misc/lv_assert.h" #include "../../misc/lv_area.h" #include "../../misc/lv_style.h" #include "../../font/lv_font.h" #include "../../core/lv_refr.h" +#include "../../stdlib/lv_string.h" /********************* * DEFINES @@ -27,14 +30,8 @@ * STATIC PROTOTYPES **********************/ -static void /* LV_ATTRIBUTE_FAST_MEM */ draw_letter_normal(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, - const lv_point_t * pos, lv_font_glyph_dsc_t * g, const uint8_t * map_p); - - -#if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX -static void draw_letter_subpx(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos, - lv_font_glyph_dsc_t * g, const uint8_t * map_p); -#endif /*LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX*/ +LV_ATTRIBUTE_FAST_MEM static void draw_letter_cb(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc, + lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area); /********************** * STATIC VARIABLES @@ -44,37 +41,6 @@ static void draw_letter_subpx(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_ * GLOBAL VARIABLES **********************/ -const uint8_t _lv_bpp1_opa_table[2] = {0, 255}; /*Opacity mapping with bpp = 1 (Just for compatibility)*/ -const uint8_t _lv_bpp2_opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/ - -const uint8_t _lv_bpp3_opa_table[8] = {0, 36, 73, 109, /*Opacity mapping with bpp = 3*/ - 146, 182, 219, 255 - }; - -const uint8_t _lv_bpp4_opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/ - 68, 85, 102, 119, - 136, 153, 170, 187, - 204, 221, 238, 255 - }; - -const uint8_t _lv_bpp8_opa_table[256] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 - }; - /********************** * MACROS **********************/ @@ -83,491 +49,67 @@ const uint8_t _lv_bpp8_opa_table[256] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1 * GLOBAL FUNCTIONS **********************/ -/** - * Draw a letter in the Virtual Display Buffer - * @param pos_p left-top coordinate of the latter - * @param mask_p the letter will be drawn only on this area (truncated to draw_buf area) - * @param font_p pointer to font - * @param letter a letter to draw - * @param color color of letter - * @param opa opacity of letter (0..255) - */ -void lv_draw_sw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p, - uint32_t letter) +void lv_draw_sw_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords) { - lv_font_glyph_dsc_t g; - bool g_ret = lv_font_get_glyph_dsc(dsc->font, &g, letter, '\0'); - if(g_ret == false) { - /*Add warning if the dsc is not found - *but do not print warning for non printable ASCII chars (e.g. '\n')*/ - if(letter >= 0x20 && - letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/ - letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/ - LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%" LV_PRIX32, letter); + if(dsc->opa <= LV_OPA_MIN) return; -#if LV_USE_FONT_PLACEHOLDER - /* draw placeholder */ - lv_area_t glyph_coords; - lv_draw_rect_dsc_t glyph_dsc; - lv_coord_t begin_x = pos_p->x + g.ofs_x; - lv_coord_t begin_y = pos_p->y + g.ofs_y; - lv_area_set(&glyph_coords, begin_x, begin_y, begin_x + g.box_w, begin_y + g.box_h); - lv_draw_rect_dsc_init(&glyph_dsc); - glyph_dsc.bg_opa = LV_OPA_MIN; - glyph_dsc.outline_opa = LV_OPA_MIN; - glyph_dsc.shadow_opa = LV_OPA_MIN; - glyph_dsc.bg_img_opa = LV_OPA_MIN; - glyph_dsc.border_color = dsc->color; - glyph_dsc.border_width = 1; - draw_ctx->draw_rect(draw_ctx, &glyph_dsc, &glyph_coords); -#endif - } - return; - } - - /*Don't draw anything if the character is empty. E.g. space*/ - if((g.box_h == 0) || (g.box_w == 0)) return; - - lv_point_t gpos; - gpos.x = pos_p->x + g.ofs_x; - gpos.y = pos_p->y + (dsc->font->line_height - dsc->font->base_line) - g.box_h - g.ofs_y; - - /*If the letter is completely out of mask don't draw it*/ - if(gpos.x + g.box_w < draw_ctx->clip_area->x1 || - gpos.x > draw_ctx->clip_area->x2 || - gpos.y + g.box_h < draw_ctx->clip_area->y1 || - gpos.y > draw_ctx->clip_area->y2) { - return; - } - - const uint8_t * map_p = lv_font_get_glyph_bitmap(g.resolved_font, letter); - if(map_p == NULL) { - LV_LOG_WARN("lv_draw_letter: character's bitmap not found"); - return; - } - - if(g.resolved_font->subpx) { -#if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX - draw_letter_subpx(draw_ctx, dsc, &gpos, &g, map_p); -#else - LV_LOG_WARN("Can't draw sub-pixel rendered letter because LV_USE_FONT_SUBPX == 0 in lv_conf.h"); -#endif - } - else { - draw_letter_normal(draw_ctx, dsc, &gpos, &g, map_p); - } + LV_PROFILER_BEGIN; + lv_draw_label_iterate_characters(draw_unit, dsc, coords, draw_letter_cb); + LV_PROFILER_END; } /********************** * STATIC FUNCTIONS **********************/ -static void LV_ATTRIBUTE_FAST_MEM draw_letter_normal(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, - const lv_point_t * pos, lv_font_glyph_dsc_t * g, const uint8_t * map_p) +LV_ATTRIBUTE_FAST_MEM static void draw_letter_cb(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc, + lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area) { + if(glyph_draw_dsc) { + if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_INVALID) { +#if LV_USE_FONT_PLACEHOLDER + /* Draw a placeholder rectangle*/ + lv_draw_border_dsc_t border_draw_dsc; + lv_draw_border_dsc_init(&border_draw_dsc); + border_draw_dsc.opa = glyph_draw_dsc->opa; + border_draw_dsc.color = glyph_draw_dsc->color; + border_draw_dsc.width = 1; + lv_draw_sw_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords); +#endif + } + else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_A8) { + lv_area_t mask_area = *glyph_draw_dsc->letter_coords; + mask_area.x2 = mask_area.x1 + lv_draw_buf_width_to_stride(lv_area_get_width(&mask_area), LV_COLOR_FORMAT_A8) - 1; + lv_draw_sw_blend_dsc_t blend_dsc; + lv_memzero(&blend_dsc, sizeof(blend_dsc)); + blend_dsc.color = glyph_draw_dsc->color; + blend_dsc.opa = glyph_draw_dsc->opa; + lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data; + blend_dsc.mask_buf = draw_buf->data; + blend_dsc.mask_area = &mask_area; + blend_dsc.mask_stride = draw_buf->header.stride; + blend_dsc.blend_area = glyph_draw_dsc->letter_coords; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; - const uint8_t * bpp_opa_table_p; - uint32_t bitmask_init; - uint32_t bitmask; - uint32_t bpp = g->bpp; - lv_opa_t opa = dsc->opa; - uint32_t shades; - if(bpp == 3) bpp = 4; - + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE) { #if LV_USE_IMGFONT - if(bpp == LV_IMGFONT_BPP) { //is imgfont - lv_area_t fill_area; - fill_area.x1 = pos->x; - fill_area.y1 = pos->y; - fill_area.x2 = pos->x + g->box_w - 1; - fill_area.y2 = pos->y + g->box_h - 1; - lv_draw_img_dsc_t img_dsc; - lv_draw_img_dsc_init(&img_dsc); - img_dsc.angle = 0; - img_dsc.zoom = LV_IMG_ZOOM_NONE; - img_dsc.opa = dsc->opa; - img_dsc.blend_mode = dsc->blend_mode; - lv_draw_img(draw_ctx, &img_dsc, &fill_area, map_p); - return; - } + lv_draw_image_dsc_t img_dsc; + lv_draw_image_dsc_init(&img_dsc); + img_dsc.rotation = 0; + img_dsc.scale_x = LV_SCALE_NONE; + img_dsc.scale_y = LV_SCALE_NONE; + img_dsc.opa = glyph_draw_dsc->opa; + img_dsc.src = glyph_draw_dsc->glyph_data; + lv_draw_sw_image(draw_unit, &img_dsc, glyph_draw_dsc->letter_coords); #endif - - switch(bpp) { - case 1: - bpp_opa_table_p = _lv_bpp1_opa_table; - bitmask_init = 0x80; - shades = 2; - break; - case 2: - bpp_opa_table_p = _lv_bpp2_opa_table; - bitmask_init = 0xC0; - shades = 4; - break; - case 4: - bpp_opa_table_p = _lv_bpp4_opa_table; - bitmask_init = 0xF0; - shades = 16; - break; - case 8: - bpp_opa_table_p = _lv_bpp8_opa_table; - bitmask_init = 0xFF; - shades = 256; - break; /*No opa table, pixel value will be used directly*/ - default: - LV_LOG_WARN("lv_draw_letter: invalid bpp"); - return; /*Invalid bpp. Can't render the letter*/ + } } - static lv_opa_t opa_table[256]; - static lv_opa_t prev_opa = LV_OPA_TRANSP; - static uint32_t prev_bpp = 0; - if(opa < LV_OPA_MAX) { - if(prev_opa != opa || prev_bpp != bpp) { - uint32_t i; - for(i = 0; i < shades; i++) { - opa_table[i] = bpp_opa_table_p[i] == LV_OPA_COVER ? opa : ((bpp_opa_table_p[i] * opa) >> 8); - } - } - bpp_opa_table_p = opa_table; - prev_opa = opa; - prev_bpp = bpp; + if(fill_draw_dsc && fill_area) { + lv_draw_sw_fill(draw_unit, fill_draw_dsc, fill_area); } - - int32_t col, row; - int32_t box_w = g->box_w; - int32_t box_h = g->box_h; - int32_t width_bit = box_w * bpp; /*Letter width in bits*/ - - /*Calculate the col/row start/end on the map*/ - int32_t col_start = pos->x >= draw_ctx->clip_area->x1 ? 0 : draw_ctx->clip_area->x1 - pos->x; - int32_t col_end = pos->x + box_w <= draw_ctx->clip_area->x2 ? box_w : draw_ctx->clip_area->x2 - pos->x + 1; - int32_t row_start = pos->y >= draw_ctx->clip_area->y1 ? 0 : draw_ctx->clip_area->y1 - pos->y; - int32_t row_end = pos->y + box_h <= draw_ctx->clip_area->y2 ? box_h : draw_ctx->clip_area->y2 - pos->y + 1; - - /*Move on the map too*/ - uint32_t bit_ofs = (row_start * width_bit) + (col_start * bpp); - map_p += bit_ofs >> 3; - - uint8_t letter_px; - uint32_t col_bit; - col_bit = bit_ofs & 0x7; /*"& 0x7" equals to "% 8" just faster*/ - - lv_draw_sw_blend_dsc_t blend_dsc; - lv_memset_00(&blend_dsc, sizeof(blend_dsc)); - blend_dsc.color = dsc->color; - blend_dsc.opa = dsc->opa; - blend_dsc.blend_mode = dsc->blend_mode; - - lv_coord_t hor_res = lv_disp_get_hor_res(_lv_refr_get_disp_refreshing()); - uint32_t mask_buf_size = box_w * box_h > hor_res ? hor_res : box_w * box_h; - lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); - blend_dsc.mask_buf = mask_buf; - int32_t mask_p = 0; - - lv_area_t fill_area; - fill_area.x1 = col_start + pos->x; - fill_area.x2 = col_end + pos->x - 1; - fill_area.y1 = row_start + pos->y; - fill_area.y2 = fill_area.y1; -#if LV_DRAW_COMPLEX - lv_coord_t fill_w = lv_area_get_width(&fill_area); - lv_area_t mask_area; - lv_area_copy(&mask_area, &fill_area); - mask_area.y2 = mask_area.y1 + row_end; - bool mask_any = lv_draw_mask_is_any(&mask_area); -#endif - blend_dsc.blend_area = &fill_area; - blend_dsc.mask_area = &fill_area; - - uint32_t col_bit_max = 8 - bpp; - uint32_t col_bit_row_ofs = (box_w + col_start - col_end) * bpp; - - for(row = row_start ; row < row_end; row++) { -#if LV_DRAW_COMPLEX - int32_t mask_p_start = mask_p; -#endif - bitmask = bitmask_init >> col_bit; - for(col = col_start; col < col_end; col++) { - /*Load the pixel's opacity into the mask*/ - letter_px = (*map_p & bitmask) >> (col_bit_max - col_bit); - if(letter_px) { - mask_buf[mask_p] = bpp_opa_table_p[letter_px]; - } - else { - mask_buf[mask_p] = 0; - } - - /*Go to the next column*/ - if(col_bit < col_bit_max) { - col_bit += bpp; - bitmask = bitmask >> bpp; - } - else { - col_bit = 0; - bitmask = bitmask_init; - map_p++; - } - - /*Next mask byte*/ - mask_p++; - } - -#if LV_DRAW_COMPLEX - /*Apply masks if any*/ - if(mask_any) { - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, fill_area.x1, fill_area.y2, - fill_w); - if(blend_dsc.mask_res == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(mask_buf + mask_p_start, fill_w); - } - } -#endif - - if((uint32_t) mask_p + (col_end - col_start) < mask_buf_size) { - fill_area.y2 ++; - } - else { - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - - fill_area.y1 = fill_area.y2 + 1; - fill_area.y2 = fill_area.y1; - mask_p = 0; - } - - col_bit += col_bit_row_ofs; - map_p += (col_bit >> 3); - col_bit = col_bit & 0x7; - } - - /*Flush the last part*/ - if(fill_area.y1 != fill_area.y2) { - fill_area.y2--; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - mask_p = 0; - } - - lv_mem_buf_release(mask_buf); } -#if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX -static void draw_letter_subpx(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos, - lv_font_glyph_dsc_t * g, const uint8_t * map_p) -{ - const uint8_t * bpp_opa_table; - uint32_t bitmask_init; - uint32_t bitmask; - uint32_t bpp = g->bpp; - lv_opa_t opa = dsc->opa; - if(bpp == 3) bpp = 4; - - switch(bpp) { - case 1: - bpp_opa_table = _lv_bpp1_opa_table; - bitmask_init = 0x80; - break; - case 2: - bpp_opa_table = _lv_bpp2_opa_table; - bitmask_init = 0xC0; - break; - case 4: - bpp_opa_table = _lv_bpp4_opa_table; - bitmask_init = 0xF0; - break; - case 8: - bpp_opa_table = _lv_bpp8_opa_table; - bitmask_init = 0xFF; - break; /*No opa table, pixel value will be used directly*/ - default: - LV_LOG_WARN("lv_draw_letter: invalid bpp not found"); - return; /*Invalid bpp. Can't render the letter*/ - } - - int32_t col, row; - - int32_t box_w = g->box_w; - int32_t box_h = g->box_h; - int32_t width_bit = box_w * bpp; /*Letter width in bits*/ - - /*Calculate the col/row start/end on the map*/ - int32_t col_start = pos->x >= draw_ctx->clip_area->x1 ? 0 : (draw_ctx->clip_area->x1 - pos->x) * 3; - int32_t col_end = pos->x + box_w / 3 <= draw_ctx->clip_area->x2 ? box_w : (draw_ctx->clip_area->x2 - pos->x + 1) * 3; - int32_t row_start = pos->y >= draw_ctx->clip_area->y1 ? 0 : draw_ctx->clip_area->y1 - pos->y; - int32_t row_end = pos->y + box_h <= draw_ctx->clip_area->y2 ? box_h : draw_ctx->clip_area->y2 - pos->y + 1; - - /*Move on the map too*/ - int32_t bit_ofs = (row_start * width_bit) + (col_start * bpp); - map_p += bit_ofs >> 3; - - uint8_t letter_px; - lv_opa_t px_opa; - int32_t col_bit; - col_bit = bit_ofs & 0x7; /*"& 0x7" equals to "% 8" just faster*/ - - lv_area_t map_area; - map_area.x1 = col_start / 3 + pos->x; - map_area.x2 = col_end / 3 + pos->x - 1; - map_area.y1 = row_start + pos->y; - map_area.y2 = map_area.y1; - - if(map_area.x2 <= map_area.x1) return; - - lv_coord_t hor_res = lv_disp_get_hor_res(_lv_refr_get_disp_refreshing()); - int32_t mask_buf_size = box_w * box_h > hor_res ? hor_res : g->box_w * g->box_h; - lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); - int32_t mask_p = 0; - - lv_color_t * color_buf = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t)); - - int32_t dest_buf_stride = lv_area_get_width(draw_ctx->buf_area); - lv_color_t * dest_buf_tmp = draw_ctx->buf; - - /*Set a pointer on draw_buf to the first pixel of the letter*/ - dest_buf_tmp += ((pos->y - draw_ctx->buf_area->y1) * dest_buf_stride) + pos->x - draw_ctx->buf_area->x1; - - /*If the letter is partially out of mask the move there on draw_buf*/ - dest_buf_tmp += (row_start * dest_buf_stride) + col_start / 3; - - lv_area_t mask_area; - lv_area_copy(&mask_area, &map_area); - mask_area.y2 = mask_area.y1 + row_end; - bool mask_any = lv_draw_mask_is_any(&map_area); - uint8_t font_rgb[3]; - - lv_color_t color = dsc->color; -#if LV_COLOR_16_SWAP == 0 - uint8_t txt_rgb[3] = {color.ch.red, color.ch.green, color.ch.blue}; -#else - uint8_t txt_rgb[3] = {color.ch.red, (color.ch.green_h << 3) + color.ch.green_l, color.ch.blue}; -#endif - - lv_draw_sw_blend_dsc_t blend_dsc; - lv_memset_00(&blend_dsc, sizeof(blend_dsc)); - blend_dsc.blend_area = &map_area; - blend_dsc.mask_area = &map_area; - blend_dsc.src_buf = color_buf; - blend_dsc.mask_buf = mask_buf; - blend_dsc.opa = opa; - blend_dsc.blend_mode = dsc->blend_mode; - - for(row = row_start ; row < row_end; row++) { - uint32_t subpx_cnt = 0; - bitmask = bitmask_init >> col_bit; - int32_t mask_p_start = mask_p; - - for(col = col_start; col < col_end; col++) { - /*Load the pixel's opacity into the mask*/ - letter_px = (*map_p & bitmask) >> (8 - col_bit - bpp); - if(letter_px != 0) { - if(opa >= LV_OPA_MAX) { - px_opa = bpp == 8 ? letter_px : bpp_opa_table[letter_px]; - } - else { - px_opa = bpp == 8 ? (uint32_t)((uint32_t)letter_px * opa) >> 8 - : (uint32_t)((uint32_t)bpp_opa_table[letter_px] * opa) >> 8; - } - } - else { - px_opa = 0; - } - - font_rgb[subpx_cnt] = px_opa; - - subpx_cnt ++; - if(subpx_cnt == 3) { - subpx_cnt = 0; - - lv_color_t res_color; -#if LV_COLOR_16_SWAP == 0 - uint8_t bg_rgb[3] = {dest_buf_tmp->ch.red, dest_buf_tmp->ch.green, dest_buf_tmp->ch.blue}; -#else - uint8_t bg_rgb[3] = {dest_buf_tmp->ch.red, - (dest_buf_tmp->ch.green_h << 3) + dest_buf_tmp->ch.green_l, - dest_buf_tmp->ch.blue - }; -#endif - -#if LV_FONT_SUBPX_BGR - res_color.ch.red = (uint32_t)((uint16_t)txt_rgb[0] * font_rgb[2] + (bg_rgb[0] * (255 - font_rgb[2]))) >> 8; - res_color.ch.blue = (uint32_t)((uint16_t)txt_rgb[2] * font_rgb[0] + (bg_rgb[2] * (255 - font_rgb[0]))) >> 8; -#else - res_color.ch.red = (uint32_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8; - res_color.ch.blue = (uint32_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8; -#endif - -#if LV_COLOR_16_SWAP == 0 - res_color.ch.green = (uint32_t)((uint32_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8; -#else - uint8_t green = (uint32_t)((uint32_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8; - res_color.ch.green_h = green >> 3; - res_color.ch.green_l = green & 0x7; -#endif - -#if LV_COLOR_DEPTH == 32 - res_color.ch.alpha = 0xff; -#endif - - if(font_rgb[0] == 0 && font_rgb[1] == 0 && font_rgb[2] == 0) mask_buf[mask_p] = LV_OPA_TRANSP; - else mask_buf[mask_p] = LV_OPA_COVER; - color_buf[mask_p] = res_color; - - /*Next mask byte*/ - mask_p++; - dest_buf_tmp++; - } - - /*Go to the next column*/ - if(col_bit < (int32_t)(8 - bpp)) { - col_bit += bpp; - bitmask = bitmask >> bpp; - } - else { - col_bit = 0; - bitmask = bitmask_init; - map_p++; - } - } - - /*Apply masks if any*/ - if(mask_any) { - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, map_area.x1, map_area.y2, - lv_area_get_width(&map_area)); - if(blend_dsc.mask_res == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(mask_buf + mask_p_start, lv_area_get_width(&map_area)); - } - } - - if((int32_t) mask_p + (col_end - col_start) < mask_buf_size) { - map_area.y2 ++; - } - else { - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - - map_area.y1 = map_area.y2 + 1; - map_area.y2 = map_area.y1; - mask_p = 0; - } - - col_bit += ((box_w - col_end) + col_start) * bpp; - - map_p += (col_bit >> 3); - col_bit = col_bit & 0x7; - - /*Next row in draw_buf*/ - dest_buf_tmp += dest_buf_stride - (col_end - col_start) / 3; - } - - /*Flush the last part*/ - if(map_area.y1 != map_area.y2) { - map_area.y2--; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - - lv_mem_buf_release(mask_buf); - lv_mem_buf_release(color_buf); -} -#endif /*LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX*/ - +#endif /*LV_USE_DRAW_SW*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_line.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_line.c index c666891c5..26011f036 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_line.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_line.c @@ -1,5 +1,5 @@ /** - * @file lv_draw_line.c + * @file lv_draw_sw_line.c * */ @@ -8,8 +8,11 @@ *********************/ #include #include "lv_draw_sw.h" +#if LV_USE_DRAW_SW + #include "../../misc/lv_math.h" #include "../../core/lv_refr.h" +#include "../../stdlib/lv_string.h" /********************* * DEFINES @@ -23,12 +26,9 @@ * STATIC PROTOTYPES **********************/ -static void /* LV_ATTRIBUTE_FAST_MEM */ draw_line_skew(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, - const lv_point_t * point1, const lv_point_t * point2); -static void /* LV_ATTRIBUTE_FAST_MEM */ draw_line_hor(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, - const lv_point_t * point1, const lv_point_t * point2); -static void /* LV_ATTRIBUTE_FAST_MEM */ draw_line_ver(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, - const lv_point_t * point1, const lv_point_t * point2); +LV_ATTRIBUTE_FAST_MEM static void draw_line_skew(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc); +LV_ATTRIBUTE_FAST_MEM static void draw_line_hor(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc); +LV_ATTRIBUTE_FAST_MEM static void draw_line_ver(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc); /********************** * STATIC VARIABLES @@ -42,262 +42,225 @@ static void /* LV_ATTRIBUTE_FAST_MEM */ draw_line_ver(struct _lv_draw_ctx_t * dr * GLOBAL FUNCTIONS **********************/ -/** - * Draw a line - * @param point1 first point of the line - * @param point2 second point of the line - * @param clip the line will be drawn only in this area - * @param dsc pointer to an initialized `lv_draw_line_dsc_t` variable - */ -void LV_ATTRIBUTE_FAST_MEM lv_draw_sw_line(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, - const lv_point_t * point1, const lv_point_t * point2) +void lv_draw_sw_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc) { if(dsc->width == 0) return; if(dsc->opa <= LV_OPA_MIN) return; - if(point1->x == point2->x && point1->y == point2->y) return; + if(dsc->p1.x == dsc->p2.x && dsc->p1.y == dsc->p2.y) return; lv_area_t clip_line; - clip_line.x1 = LV_MIN(point1->x, point2->x) - dsc->width / 2; - clip_line.x2 = LV_MAX(point1->x, point2->x) + dsc->width / 2; - clip_line.y1 = LV_MIN(point1->y, point2->y) - dsc->width / 2; - clip_line.y2 = LV_MAX(point1->y, point2->y) + dsc->width / 2; + clip_line.x1 = (int32_t)LV_MIN(dsc->p1.x, dsc->p2.x) - dsc->width / 2; + clip_line.x2 = (int32_t)LV_MAX(dsc->p1.x, dsc->p2.x) + dsc->width / 2; + clip_line.y1 = (int32_t)LV_MIN(dsc->p1.y, dsc->p2.y) - dsc->width / 2; + clip_line.y2 = (int32_t)LV_MAX(dsc->p1.y, dsc->p2.y) + dsc->width / 2; bool is_common; - is_common = _lv_area_intersect(&clip_line, &clip_line, draw_ctx->clip_area); + is_common = _lv_area_intersect(&clip_line, &clip_line, draw_unit->clip_area); if(!is_common) return; - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &clip_line; - if(point1->y == point2->y) draw_line_hor(draw_ctx, dsc, point1, point2); - else if(point1->x == point2->x) draw_line_ver(draw_ctx, dsc, point1, point2); - else draw_line_skew(draw_ctx, dsc, point1, point2); + LV_PROFILER_BEGIN; + if(dsc->p1.y == dsc->p2.y) draw_line_hor(draw_unit, dsc); + else if(dsc->p1.x == dsc->p2.x) draw_line_ver(draw_unit, dsc); + else draw_line_skew(draw_unit, dsc); if(dsc->round_end || dsc->round_start) { - lv_draw_rect_dsc_t cir_dsc; - lv_draw_rect_dsc_init(&cir_dsc); - cir_dsc.bg_color = dsc->color; + lv_draw_fill_dsc_t cir_dsc; + lv_draw_fill_dsc_init(&cir_dsc); + cir_dsc.color = dsc->color; cir_dsc.radius = LV_RADIUS_CIRCLE; - cir_dsc.bg_opa = dsc->opa; + cir_dsc.opa = dsc->opa; int32_t r = (dsc->width >> 1); int32_t r_corr = (dsc->width & 1) ? 0 : 1; lv_area_t cir_area; if(dsc->round_start) { - cir_area.x1 = point1->x - r; - cir_area.y1 = point1->y - r; - cir_area.x2 = point1->x + r - r_corr; - cir_area.y2 = point1->y + r - r_corr ; - lv_draw_rect(draw_ctx, &cir_dsc, &cir_area); + cir_area.x1 = (int32_t)dsc->p1.x - r; + cir_area.y1 = (int32_t)dsc->p1.y - r; + cir_area.x2 = (int32_t)dsc->p1.x + r - r_corr; + cir_area.y2 = (int32_t)dsc->p1.y + r - r_corr ; + lv_draw_sw_fill(draw_unit, &cir_dsc, &cir_area); } if(dsc->round_end) { - cir_area.x1 = point2->x - r; - cir_area.y1 = point2->y - r; - cir_area.x2 = point2->x + r - r_corr; - cir_area.y2 = point2->y + r - r_corr ; - lv_draw_rect(draw_ctx, &cir_dsc, &cir_area); + cir_area.x1 = (int32_t)dsc->p2.x - r; + cir_area.y1 = (int32_t)dsc->p2.y - r; + cir_area.x2 = (int32_t)dsc->p2.x + r - r_corr; + cir_area.y2 = (int32_t)dsc->p2.y + r - r_corr ; + lv_draw_sw_fill(draw_unit, &cir_dsc, &cir_area); } } - - draw_ctx->clip_area = clip_area_ori; + LV_PROFILER_END; } /********************** * STATIC FUNCTIONS **********************/ - - -static void LV_ATTRIBUTE_FAST_MEM draw_line_hor(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, - const lv_point_t * point1, const lv_point_t * point2) +LV_ATTRIBUTE_FAST_MEM static void draw_line_hor(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc) { int32_t w = dsc->width - 1; int32_t w_half0 = w >> 1; int32_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/ lv_area_t blend_area; - blend_area.x1 = LV_MIN(point1->x, point2->x); - blend_area.x2 = LV_MAX(point1->x, point2->x) - 1; - blend_area.y1 = point1->y - w_half1; - blend_area.y2 = point1->y + w_half0; + blend_area.x1 = (int32_t)LV_MIN(dsc->p1.x, dsc->p2.x); + blend_area.x2 = (int32_t)LV_MAX(dsc->p1.x, dsc->p2.x) - 1; + blend_area.y1 = (int32_t)dsc->p1.y - w_half1; + blend_area.y2 = (int32_t)dsc->p1.y + w_half0; bool is_common; - is_common = _lv_area_intersect(&blend_area, &blend_area, draw_ctx->clip_area); + is_common = _lv_area_intersect(&blend_area, &blend_area, draw_unit->clip_area); if(!is_common) return; - bool dashed = dsc->dash_gap && dsc->dash_width ? true : false; - bool simple_mode = true; - if(lv_draw_mask_is_any(&blend_area)) simple_mode = false; - else if(dashed) simple_mode = false; + bool dashed = dsc->dash_gap && dsc->dash_width; lv_draw_sw_blend_dsc_t blend_dsc; - lv_memset_00(&blend_dsc, sizeof(blend_dsc)); + lv_memzero(&blend_dsc, sizeof(blend_dsc)); blend_dsc.blend_area = &blend_area; blend_dsc.color = dsc->color; blend_dsc.opa = dsc->opa; /*If there is no mask then simply draw a rectangle*/ - if(simple_mode) { - lv_draw_sw_blend(draw_ctx, &blend_dsc); + if(!dashed) { + lv_draw_sw_blend(draw_unit, &blend_dsc); } -#if LV_DRAW_COMPLEX +#if LV_DRAW_SW_COMPLEX /*If there other mask apply it*/ else { int32_t blend_area_w = lv_area_get_width(&blend_area); - lv_coord_t y2 = blend_area.y2; + int32_t y2 = blend_area.y2; blend_area.y2 = blend_area.y1; - lv_coord_t dash_start = 0; - if(dashed) { - dash_start = (blend_area.x1) % (dsc->dash_gap + dsc->dash_width); - } + int32_t dash_start = blend_area.x1 % (dsc->dash_gap + dsc->dash_width); - lv_opa_t * mask_buf = lv_mem_buf_get(blend_area_w); + lv_opa_t * mask_buf = lv_malloc(blend_area_w); blend_dsc.mask_buf = mask_buf; blend_dsc.mask_area = &blend_area; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; int32_t h; for(h = blend_area.y1; h <= y2; h++) { - lv_memset_ff(mask_buf, blend_area_w); - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf, blend_area.x1, h, blend_area_w); + lv_memset(mask_buf, 0xff, blend_area_w); - if(dashed) { - if(blend_dsc.mask_res != LV_DRAW_MASK_RES_TRANSP) { - lv_coord_t dash_cnt = dash_start; - lv_coord_t i; - for(i = 0; i < blend_area_w; i++, dash_cnt++) { - if(dash_cnt <= dsc->dash_width) { - int16_t diff = dsc->dash_width - dash_cnt; - i += diff; - dash_cnt += diff; - } - else if(dash_cnt >= dsc->dash_gap + dsc->dash_width) { - dash_cnt = 0; - } - else { - mask_buf[i] = 0x00; - } - } - - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; + int32_t dash_cnt = dash_start; + int32_t i; + for(i = 0; i < blend_area_w; i++, dash_cnt++) { + if(dash_cnt <= dsc->dash_width) { + int16_t diff = dsc->dash_width - dash_cnt; + i += diff; + dash_cnt += diff; } + else if(dash_cnt >= dsc->dash_gap + dsc->dash_width) { + dash_cnt = 0; + } + else { + mask_buf[i] = 0x00; + } + + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; } - lv_draw_sw_blend(draw_ctx, &blend_dsc); + lv_draw_sw_blend(draw_unit, &blend_dsc); blend_area.y1++; blend_area.y2++; } - lv_mem_buf_release(mask_buf); + lv_free(mask_buf); } -#endif /*LV_DRAW_COMPLEX*/ +#endif /*LV_DRAW_SW_COMPLEX*/ } -static void LV_ATTRIBUTE_FAST_MEM draw_line_ver(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, - const lv_point_t * point1, const lv_point_t * point2) +LV_ATTRIBUTE_FAST_MEM static void draw_line_ver(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc) { int32_t w = dsc->width - 1; int32_t w_half0 = w >> 1; int32_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/ lv_area_t blend_area; - blend_area.x1 = point1->x - w_half1; - blend_area.x2 = point1->x + w_half0; - blend_area.y1 = LV_MIN(point1->y, point2->y); - blend_area.y2 = LV_MAX(point1->y, point2->y) - 1; + blend_area.x1 = (int32_t)dsc->p1.x - w_half1; + blend_area.x2 = (int32_t)dsc->p1.x + w_half0; + blend_area.y1 = (int32_t)LV_MIN(dsc->p1.y, dsc->p2.y); + blend_area.y2 = (int32_t)LV_MAX(dsc->p1.y, dsc->p2.y) - 1; bool is_common; - is_common = _lv_area_intersect(&blend_area, &blend_area, draw_ctx->clip_area); + is_common = _lv_area_intersect(&blend_area, &blend_area, draw_unit->clip_area); if(!is_common) return; - bool dashed = dsc->dash_gap && dsc->dash_width ? true : false; - bool simple_mode = true; - if(lv_draw_mask_is_any(&blend_area)) simple_mode = false; - else if(dashed) simple_mode = false; + bool dashed = dsc->dash_gap && dsc->dash_width; lv_draw_sw_blend_dsc_t blend_dsc; - lv_memset_00(&blend_dsc, sizeof(blend_dsc)); + lv_memzero(&blend_dsc, sizeof(blend_dsc)); blend_dsc.blend_area = &blend_area; blend_dsc.color = dsc->color; blend_dsc.opa = dsc->opa; /*If there is no mask then simply draw a rectangle*/ - if(simple_mode) { - lv_draw_sw_blend(draw_ctx, &blend_dsc); + if(!dashed) { + lv_draw_sw_blend(draw_unit, &blend_dsc); } -#if LV_DRAW_COMPLEX +#if LV_DRAW_SW_COMPLEX /*If there other mask apply it*/ else { int32_t draw_area_w = lv_area_get_width(&blend_area); - lv_coord_t y2 = blend_area.y2; + int32_t y2 = blend_area.y2; blend_area.y2 = blend_area.y1; - lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w); + lv_opa_t * mask_buf = lv_malloc(draw_area_w); blend_dsc.mask_buf = mask_buf; blend_dsc.mask_area = &blend_area; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + int32_t dash_start = (blend_area.y1) % (dsc->dash_gap + dsc->dash_width); - lv_coord_t dash_start = 0; - if(dashed) { - dash_start = (blend_area.y1) % (dsc->dash_gap + dsc->dash_width); - } - - lv_coord_t dash_cnt = dash_start; + int32_t dash_cnt = dash_start; int32_t h; for(h = blend_area.y1; h <= y2; h++) { - lv_memset_ff(mask_buf, draw_area_w); - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf, blend_area.x1, h, draw_area_w); + lv_memset(mask_buf, 0xff, draw_area_w); - if(dashed) { - if(blend_dsc.mask_res != LV_DRAW_MASK_RES_TRANSP) { - if(dash_cnt > dsc->dash_width) { - blend_dsc.mask_res = LV_DRAW_MASK_RES_TRANSP; - } - - if(dash_cnt >= dsc->dash_gap + dsc->dash_width) { - dash_cnt = 0; - } - } - dash_cnt ++; + if(dash_cnt > dsc->dash_width) { + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_TRANSP; + } + else { + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_FULL_COVER; } - lv_draw_sw_blend(draw_ctx, &blend_dsc); + if(dash_cnt >= dsc->dash_gap + dsc->dash_width) { + dash_cnt = 0; + } + dash_cnt ++; + + lv_draw_sw_blend(draw_unit, &blend_dsc); blend_area.y1++; blend_area.y2++; } - lv_mem_buf_release(mask_buf); + lv_free(mask_buf); } -#endif /*LV_DRAW_COMPLEX*/ +#endif /*LV_DRAW_SW_COMPLEX*/ } -static void LV_ATTRIBUTE_FAST_MEM draw_line_skew(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, - const lv_point_t * point1, const lv_point_t * point2) +LV_ATTRIBUTE_FAST_MEM static void draw_line_skew(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc) { -#if LV_DRAW_COMPLEX +#if LV_DRAW_SW_COMPLEX /*Keep the great y in p1*/ lv_point_t p1; lv_point_t p2; - if(point1->y < point2->y) { - p1.y = point1->y; - p2.y = point2->y; - p1.x = point1->x; - p2.x = point2->x; + if(dsc->p1.y < dsc->p2.y) { + p1 = lv_point_from_precise(&dsc->p1); + p2 = lv_point_from_precise(&dsc->p2); } else { - p1.y = point2->y; - p2.y = point1->y; - p1.x = point2->x; - p2.x = point1->x; + p1 = lv_point_from_precise(&dsc->p2); + p2 = lv_point_from_precise(&dsc->p1); } int32_t xdiff = p2.x - p1.x; int32_t ydiff = p2.y - p1.y; - bool flat = LV_ABS(xdiff) > LV_ABS(ydiff) ? true : false; + bool flat = LV_ABS(xdiff) > LV_ABS(ydiff); static const uint8_t wcorr[] = { 128, 128, 128, 129, 129, 130, 130, 131, @@ -325,47 +288,47 @@ static void LV_ATTRIBUTE_FAST_MEM draw_line_skew(struct _lv_draw_ctx_t * draw_ct /*Get the union of `coords` and `clip`*/ /*`clip` is already truncated to the `draw_buf` size *in 'lv_refr_area' function*/ - bool is_common = _lv_area_intersect(&blend_area, &blend_area, draw_ctx->clip_area); + bool is_common = _lv_area_intersect(&blend_area, &blend_area, draw_unit->clip_area); if(is_common == false) return; - lv_draw_mask_line_param_t mask_left_param; - lv_draw_mask_line_param_t mask_right_param; - lv_draw_mask_line_param_t mask_top_param; - lv_draw_mask_line_param_t mask_bottom_param; + lv_draw_sw_mask_line_param_t mask_left_param; + lv_draw_sw_mask_line_param_t mask_right_param; + lv_draw_sw_mask_line_param_t mask_top_param; + lv_draw_sw_mask_line_param_t mask_bottom_param; + + void * masks[5] = {&mask_left_param, & mask_right_param, NULL, NULL, NULL}; if(flat) { if(xdiff > 0) { - lv_draw_mask_line_points_init(&mask_left_param, p1.x, p1.y - w_half0, p2.x, p2.y - w_half0, - LV_DRAW_MASK_LINE_SIDE_LEFT); - lv_draw_mask_line_points_init(&mask_right_param, p1.x, p1.y + w_half1, p2.x, p2.y + w_half1, - LV_DRAW_MASK_LINE_SIDE_RIGHT); + lv_draw_sw_mask_line_points_init(&mask_left_param, p1.x, p1.y - w_half0, p2.x, p2.y - w_half0, + LV_DRAW_SW_MASK_LINE_SIDE_LEFT); + lv_draw_sw_mask_line_points_init(&mask_right_param, p1.x, p1.y + w_half1, p2.x, p2.y + w_half1, + LV_DRAW_SW_MASK_LINE_SIDE_RIGHT); } else { - lv_draw_mask_line_points_init(&mask_left_param, p1.x, p1.y + w_half1, p2.x, p2.y + w_half1, - LV_DRAW_MASK_LINE_SIDE_LEFT); - lv_draw_mask_line_points_init(&mask_right_param, p1.x, p1.y - w_half0, p2.x, p2.y - w_half0, - LV_DRAW_MASK_LINE_SIDE_RIGHT); + lv_draw_sw_mask_line_points_init(&mask_left_param, p1.x, p1.y + w_half1, p2.x, p2.y + w_half1, + LV_DRAW_SW_MASK_LINE_SIDE_LEFT); + lv_draw_sw_mask_line_points_init(&mask_right_param, p1.x, p1.y - w_half0, p2.x, p2.y - w_half0, + LV_DRAW_SW_MASK_LINE_SIDE_RIGHT); } } else { - lv_draw_mask_line_points_init(&mask_left_param, p1.x + w_half1, p1.y, p2.x + w_half1, p2.y, - LV_DRAW_MASK_LINE_SIDE_LEFT); - lv_draw_mask_line_points_init(&mask_right_param, p1.x - w_half0, p1.y, p2.x - w_half0, p2.y, - LV_DRAW_MASK_LINE_SIDE_RIGHT); + lv_draw_sw_mask_line_points_init(&mask_left_param, p1.x + w_half1, p1.y, p2.x + w_half1, p2.y, + LV_DRAW_SW_MASK_LINE_SIDE_LEFT); + lv_draw_sw_mask_line_points_init(&mask_right_param, p1.x - w_half0, p1.y, p2.x - w_half0, p2.y, + LV_DRAW_SW_MASK_LINE_SIDE_RIGHT); + } /*Use the normal vector for the endings*/ - int16_t mask_left_id = lv_draw_mask_add(&mask_left_param, NULL); - int16_t mask_right_id = lv_draw_mask_add(&mask_right_param, NULL); - int16_t mask_top_id = LV_MASK_ID_INV; - int16_t mask_bottom_id = LV_MASK_ID_INV; - if(!dsc->raw_end) { - lv_draw_mask_line_points_init(&mask_top_param, p1.x, p1.y, p1.x - ydiff, p1.y + xdiff, LV_DRAW_MASK_LINE_SIDE_BOTTOM); - lv_draw_mask_line_points_init(&mask_bottom_param, p2.x, p2.y, p2.x - ydiff, p2.y + xdiff, LV_DRAW_MASK_LINE_SIDE_TOP); - mask_top_id = lv_draw_mask_add(&mask_top_param, NULL); - mask_bottom_id = lv_draw_mask_add(&mask_bottom_param, NULL); + lv_draw_sw_mask_line_points_init(&mask_top_param, p1.x, p1.y, p1.x - ydiff, p1.y + xdiff, + LV_DRAW_SW_MASK_LINE_SIDE_BOTTOM); + lv_draw_sw_mask_line_points_init(&mask_bottom_param, p2.x, p2.y, p2.x - ydiff, p2.y + xdiff, + LV_DRAW_SW_MASK_LINE_SIDE_TOP); + masks[2] = &mask_top_param; + masks[3] = &mask_bottom_param; } /*The real draw area is around the line. @@ -375,18 +338,18 @@ static void LV_ATTRIBUTE_FAST_MEM draw_line_skew(struct _lv_draw_ctx_t * draw_ct /*Draw the background line by line*/ int32_t h; - uint32_t hor_res = (uint32_t)lv_disp_get_hor_res(_lv_refr_get_disp_refreshing()); + uint32_t hor_res = (uint32_t)lv_display_get_horizontal_resolution(_lv_refr_get_disp_refreshing()); size_t mask_buf_size = LV_MIN(lv_area_get_size(&blend_area), hor_res); - lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); + lv_opa_t * mask_buf = lv_malloc(mask_buf_size); - lv_coord_t y2 = blend_area.y2; + int32_t y2 = blend_area.y2; blend_area.y2 = blend_area.y1; uint32_t mask_p = 0; - lv_memset_ff(mask_buf, mask_buf_size); + lv_memset(mask_buf, 0xff, mask_buf_size); lv_draw_sw_blend_dsc_t blend_dsc; - lv_memset_00(&blend_dsc, sizeof(blend_dsc)); + lv_memzero(&blend_dsc, sizeof(blend_dsc)); blend_dsc.blend_area = &blend_area; blend_dsc.color = dsc->color; blend_dsc.opa = dsc->opa; @@ -395,9 +358,9 @@ static void LV_ATTRIBUTE_FAST_MEM draw_line_skew(struct _lv_draw_ctx_t * draw_ct /*Fill the first row with 'color'*/ for(h = blend_area.y1; h <= y2; h++) { - blend_dsc.mask_res = lv_draw_mask_apply(&mask_buf[mask_p], blend_area.x1, h, draw_area_w); - if(blend_dsc.mask_res == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(&mask_buf[mask_p], draw_area_w); + blend_dsc.mask_res = lv_draw_sw_mask_apply(masks, &mask_buf[mask_p], blend_area.x1, h, draw_area_w); + if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_TRANSP) { + lv_memzero(&mask_buf[mask_p], draw_area_w); } mask_p += draw_area_w; @@ -405,39 +368,36 @@ static void LV_ATTRIBUTE_FAST_MEM draw_line_skew(struct _lv_draw_ctx_t * draw_ct blend_area.y2 ++; } else { - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - lv_draw_sw_blend(draw_ctx, &blend_dsc); + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + lv_draw_sw_blend(draw_unit, &blend_dsc); blend_area.y1 = blend_area.y2 + 1; blend_area.y2 = blend_area.y1; mask_p = 0; - lv_memset_ff(mask_buf, mask_buf_size); + lv_memset(mask_buf, 0xff, mask_buf_size); } } /*Flush the last part*/ if(blend_area.y1 != blend_area.y2) { blend_area.y2--; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - lv_draw_sw_blend(draw_ctx, &blend_dsc); + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + lv_draw_sw_blend(draw_unit, &blend_dsc); } - lv_mem_buf_release(mask_buf); + lv_free(mask_buf); - lv_draw_mask_free_param(&mask_left_param); - lv_draw_mask_free_param(&mask_right_param); - if(mask_top_id != LV_MASK_ID_INV) lv_draw_mask_free_param(&mask_top_param); - if(mask_bottom_id != LV_MASK_ID_INV) lv_draw_mask_free_param(&mask_bottom_param); - lv_draw_mask_remove_id(mask_left_id); - lv_draw_mask_remove_id(mask_right_id); - lv_draw_mask_remove_id(mask_top_id); - lv_draw_mask_remove_id(mask_bottom_id); + lv_draw_sw_mask_free_param(&mask_left_param); + lv_draw_sw_mask_free_param(&mask_right_param); + if(!dsc->raw_end) { + lv_draw_sw_mask_free_param(&mask_top_param); + lv_draw_sw_mask_free_param(&mask_bottom_param); + } #else - LV_UNUSED(point1); - LV_UNUSED(point2); - LV_UNUSED(draw_ctx); + LV_UNUSED(draw_unit); LV_UNUSED(dsc); - LV_LOG_WARN("Can't draw skewed line with LV_DRAW_COMPLEX == 0"); -#endif /*LV_DRAW_COMPLEX*/ + LV_LOG_WARN("Can't draw skewed line with LV_DRAW_SW_COMPLEX == 0"); +#endif /*LV_DRAW_SW_COMPLEX*/ } +#endif /*LV_USE_DRAW_SW*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_mask.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_mask.c new file mode 100644 index 000000000..5790f6742 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_mask.c @@ -0,0 +1,1235 @@ +/** + * @file lv_draw_sw_mask.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../lv_draw.h" + +#if LV_DRAW_SW_COMPLEX +#include "lv_draw_sw_mask.h" +#include "../../core/lv_global.h" +#include "../../misc/lv_math.h" +#include "../../misc/lv_log.h" +#include "../../misc/lv_assert.h" +#include "../../osal/lv_os.h" +#include "../../stdlib/lv_string.h" + +/********************* + * DEFINES + *********************/ +#define CIRCLE_CACHE_LIFE_MAX 1000 +#define CIRCLE_CACHE_AGING(life, r) life = LV_MIN(life + (r < 16 ? 1 : (r >> 4)), 1000) +#define circle_cache_mutex LV_GLOBAL_DEFAULT()->draw_info.circle_cache_mutex +#define _circle_cache LV_GLOBAL_DEFAULT()->sw_circle_cache + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +LV_ATTRIBUTE_FAST_MEM static lv_draw_sw_mask_res_t lv_draw_mask_line(lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, int32_t len, + lv_draw_sw_mask_line_param_t * param); +LV_ATTRIBUTE_FAST_MEM static lv_draw_sw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, int32_t len, + lv_draw_sw_mask_radius_param_t * param); +LV_ATTRIBUTE_FAST_MEM static lv_draw_sw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, int32_t len, + lv_draw_sw_mask_angle_param_t * param); +LV_ATTRIBUTE_FAST_MEM static lv_draw_sw_mask_res_t lv_draw_mask_fade(lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, int32_t len, + lv_draw_sw_mask_fade_param_t * param); +LV_ATTRIBUTE_FAST_MEM static lv_draw_sw_mask_res_t lv_draw_mask_map(lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, int32_t len, + lv_draw_sw_mask_map_param_t * param); + +LV_ATTRIBUTE_FAST_MEM static lv_draw_sw_mask_res_t line_mask_flat(lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, + int32_t len, + lv_draw_sw_mask_line_param_t * p); +LV_ATTRIBUTE_FAST_MEM static lv_draw_sw_mask_res_t line_mask_steep(lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, + int32_t len, + lv_draw_sw_mask_line_param_t * p); + +static void circ_init(lv_point_t * c, int32_t * tmp, int32_t radius); +static bool circ_cont(lv_point_t * c); +static void circ_next(lv_point_t * c, int32_t * tmp); +static void circ_calc_aa4(_lv_draw_sw_mask_radius_circle_dsc_t * c, int32_t radius); +static lv_opa_t * get_next_line(_lv_draw_sw_mask_radius_circle_dsc_t * c, int32_t y, int32_t * len, + int32_t * x_start); +LV_ATTRIBUTE_FAST_MEM static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_sw_mask_init(void) +{ + lv_mutex_init(&circle_cache_mutex); +} + +void lv_draw_sw_mask_deinit(void) +{ + lv_mutex_delete(&circle_cache_mutex); +} + +LV_ATTRIBUTE_FAST_MEM lv_draw_sw_mask_res_t lv_draw_sw_mask_apply(void * masks[], lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, + int32_t len) +{ + bool changed = false; + _lv_draw_sw_mask_common_dsc_t * dsc; + + uint32_t i; + for(i = 0; masks[i]; i++) { + dsc = masks[i]; + lv_draw_sw_mask_res_t res = LV_DRAW_SW_MASK_RES_FULL_COVER; + res = dsc->cb(mask_buf, abs_x, abs_y, len, masks[i]); + if(res == LV_DRAW_SW_MASK_RES_TRANSP) return LV_DRAW_SW_MASK_RES_TRANSP; + else if(res == LV_DRAW_SW_MASK_RES_CHANGED) changed = true; + } + + return changed ? LV_DRAW_SW_MASK_RES_CHANGED : LV_DRAW_SW_MASK_RES_FULL_COVER; +} + +void lv_draw_sw_mask_free_param(void * p) +{ + lv_mutex_lock(&circle_cache_mutex); + _lv_draw_sw_mask_common_dsc_t * pdsc = p; + if(pdsc->type == LV_DRAW_SW_MASK_TYPE_RADIUS) { + lv_draw_sw_mask_radius_param_t * radius_p = (lv_draw_sw_mask_radius_param_t *) p; + if(radius_p->circle) { + if(radius_p->circle->life < 0) { + lv_free(radius_p->circle->cir_opa); + lv_free(radius_p->circle); + } + else { + radius_p->circle->used_cnt--; + } + } + } + + lv_mutex_unlock(&circle_cache_mutex); +} + +void _lv_draw_sw_mask_cleanup(void) +{ + uint8_t i; + for(i = 0; i < LV_DRAW_SW_CIRCLE_CACHE_SIZE; i++) { + if(_circle_cache[i].buf) { + lv_free(_circle_cache[i].buf); + } + lv_memzero(&(_circle_cache[i]), sizeof(_circle_cache[i])); + } +} + +void lv_draw_sw_mask_line_points_init(lv_draw_sw_mask_line_param_t * param, int32_t p1x, int32_t p1y, + int32_t p2x, + int32_t p2y, lv_draw_sw_mask_line_side_t side) +{ + lv_memzero(param, sizeof(lv_draw_sw_mask_line_param_t)); + + if(p1y == p2y && side == LV_DRAW_SW_MASK_LINE_SIDE_BOTTOM) { + p1y--; + p2y--; + } + + if(p1y > p2y) { + int32_t t; + t = p2x; + p2x = p1x; + p1x = t; + + t = p2y; + p2y = p1y; + p1y = t; + } + + lv_point_set(¶m->cfg.p1, p1x, p1y); + lv_point_set(¶m->cfg.p2, p2x, p2y); + param->cfg.side = side; + + lv_point_set(¶m->origo, p1x, p1y); + param->flat = (LV_ABS(p2x - p1x) > LV_ABS(p2y - p1y)) ? 1 : 0; + param->yx_steep = 0; + param->xy_steep = 0; + param->dsc.cb = (lv_draw_sw_mask_xcb_t)lv_draw_mask_line; + param->dsc.type = LV_DRAW_SW_MASK_TYPE_LINE; + + int32_t dx = p2x - p1x; + int32_t dy = p2y - p1y; + + if(param->flat) { + /*Normalize the steep. Delta x should be relative to delta x = 1024*/ + int32_t m; + + if(dx) { + m = (1L << 20) / dx; /*m is multiplier to normalize y (upscaled by 1024)*/ + param->yx_steep = (m * dy) >> 10; + } + + if(dy) { + m = (1L << 20) / dy; /*m is multiplier to normalize x (upscaled by 1024)*/ + param->xy_steep = (m * dx) >> 10; + } + param->steep = param->yx_steep; + } + else { + /*Normalize the steep. Delta y should be relative to delta x = 1024*/ + int32_t m; + + if(dy) { + m = (1L << 20) / dy; /*m is multiplier to normalize x (upscaled by 1024)*/ + param->xy_steep = (m * dx) >> 10; + } + + if(dx) { + m = (1L << 20) / dx; /*m is multiplier to normalize x (upscaled by 1024)*/ + param->yx_steep = (m * dy) >> 10; + } + param->steep = param->xy_steep; + } + + if(param->cfg.side == LV_DRAW_SW_MASK_LINE_SIDE_LEFT) param->inv = 0; + else if(param->cfg.side == LV_DRAW_SW_MASK_LINE_SIDE_RIGHT) param->inv = 1; + else if(param->cfg.side == LV_DRAW_SW_MASK_LINE_SIDE_TOP) { + if(param->steep > 0) param->inv = 1; + else param->inv = 0; + } + else if(param->cfg.side == LV_DRAW_SW_MASK_LINE_SIDE_BOTTOM) { + if(param->steep > 0) param->inv = 0; + else param->inv = 1; + } + + param->spx = param->steep >> 2; + if(param->steep < 0) param->spx = -param->spx; +} + +void lv_draw_sw_mask_line_angle_init(lv_draw_sw_mask_line_param_t * param, int32_t p1x, int32_t py, int16_t angle, + lv_draw_sw_mask_line_side_t side) +{ + /*Find an optimal degree. + *lv_mask_line_points_init will swap the points to keep the smaller y in p1 + *Theoretically a line with `angle` or `angle+180` is the same only the points are swapped + *Find the degree which keeps the origo in place*/ + if(angle > 180) angle -= 180; /*> 180 will swap the origo*/ + + int32_t p2x; + int32_t p2y; + + p2x = (lv_trigo_sin(angle + 90) >> 5) + p1x; + p2y = (lv_trigo_sin(angle) >> 5) + py; + + lv_draw_sw_mask_line_points_init(param, p1x, py, p2x, p2y, side); +} + +void lv_draw_sw_mask_angle_init(lv_draw_sw_mask_angle_param_t * param, int32_t vertex_x, int32_t vertex_y, + int32_t start_angle, int32_t end_angle) +{ + lv_draw_sw_mask_line_side_t start_side; + lv_draw_sw_mask_line_side_t end_side; + + /*Constrain the input angles*/ + if(start_angle < 0) + start_angle = 0; + else if(start_angle > 359) + start_angle = 359; + + if(end_angle < 0) + end_angle = 0; + else if(end_angle > 359) + end_angle = 359; + + if(end_angle < start_angle) { + param->delta_deg = 360 - start_angle + end_angle; + } + else { + param->delta_deg = LV_ABS(end_angle - start_angle); + } + + param->cfg.start_angle = start_angle; + param->cfg.end_angle = end_angle; + lv_point_set(¶m->cfg.vertex_p, vertex_x, vertex_y); + param->dsc.cb = (lv_draw_sw_mask_xcb_t)lv_draw_mask_angle; + param->dsc.type = LV_DRAW_SW_MASK_TYPE_ANGLE; + + LV_ASSERT_MSG(start_angle >= 0 && start_angle <= 360, "Unexpected start angle"); + + if(start_angle >= 0 && start_angle < 180) { + start_side = LV_DRAW_SW_MASK_LINE_SIDE_LEFT; + } + else + start_side = LV_DRAW_SW_MASK_LINE_SIDE_RIGHT; /*silence compiler*/ + + LV_ASSERT_MSG(end_angle >= 0 && start_angle <= 360, "Unexpected end angle"); + + if(end_angle >= 0 && end_angle < 180) { + end_side = LV_DRAW_SW_MASK_LINE_SIDE_RIGHT; + } + else if(end_angle >= 180 && end_angle < 360) { + end_side = LV_DRAW_SW_MASK_LINE_SIDE_LEFT; + } + else + end_side = LV_DRAW_SW_MASK_LINE_SIDE_RIGHT; /*silence compiler*/ + + lv_draw_sw_mask_line_angle_init(¶m->start_line, vertex_x, vertex_y, start_angle, start_side); + lv_draw_sw_mask_line_angle_init(¶m->end_line, vertex_x, vertex_y, end_angle, end_side); +} + +void lv_draw_sw_mask_radius_init(lv_draw_sw_mask_radius_param_t * param, const lv_area_t * rect, int32_t radius, + bool inv) +{ + int32_t w = lv_area_get_width(rect); + int32_t h = lv_area_get_height(rect); + int32_t short_side = LV_MIN(w, h); + if(radius > short_side >> 1) radius = short_side >> 1; + if(radius < 0) radius = 0; + + lv_area_copy(¶m->cfg.rect, rect); + param->cfg.radius = radius; + param->cfg.outer = inv ? 1 : 0; + param->dsc.cb = (lv_draw_sw_mask_xcb_t)lv_draw_mask_radius; + param->dsc.type = LV_DRAW_SW_MASK_TYPE_RADIUS; + + if(radius == 0) { + param->circle = NULL; + return; + } + + lv_mutex_lock(&circle_cache_mutex); + + uint32_t i; + + /*Try to reuse a circle cache entry*/ + for(i = 0; i < LV_DRAW_SW_CIRCLE_CACHE_SIZE; i++) { + if(_circle_cache[i].radius == radius) { + _circle_cache[i].used_cnt++; + CIRCLE_CACHE_AGING(_circle_cache[i].life, radius); + param->circle = &(_circle_cache[i]); + lv_mutex_unlock(&circle_cache_mutex); + return; + } + } + + /*If not cached use the free entry with lowest life*/ + _lv_draw_sw_mask_radius_circle_dsc_t * entry = NULL; + for(i = 0; i < LV_DRAW_SW_CIRCLE_CACHE_SIZE; i++) { + if(_circle_cache[i].used_cnt == 0) { + if(!entry) entry = &(_circle_cache[i]); + else if(_circle_cache[i].life < entry->life) entry = &(_circle_cache[i]); + } + } + + /*There is no unused entry. Allocate one temporarily*/ + if(!entry) { + entry = lv_malloc_zeroed(sizeof(_lv_draw_sw_mask_radius_circle_dsc_t)); + LV_ASSERT_MALLOC(entry); + entry->life = -1; + } + else { + entry->used_cnt++; + entry->life = 0; + CIRCLE_CACHE_AGING(entry->life, radius); + } + + param->circle = entry; + + circ_calc_aa4(param->circle, radius); + lv_mutex_unlock(&circle_cache_mutex); + +} + +void lv_draw_sw_mask_fade_init(lv_draw_sw_mask_fade_param_t * param, const lv_area_t * coords, lv_opa_t opa_top, + int32_t y_top, + lv_opa_t opa_bottom, int32_t y_bottom) +{ + lv_area_copy(¶m->cfg.coords, coords); + param->cfg.opa_top = opa_top; + param->cfg.opa_bottom = opa_bottom; + param->cfg.y_top = y_top; + param->cfg.y_bottom = y_bottom; + param->dsc.cb = (lv_draw_sw_mask_xcb_t)lv_draw_mask_fade; + param->dsc.type = LV_DRAW_SW_MASK_TYPE_FADE; +} + +void lv_draw_sw_mask_map_init(lv_draw_sw_mask_map_param_t * param, const lv_area_t * coords, const lv_opa_t * map) +{ + lv_area_copy(¶m->cfg.coords, coords); + param->cfg.map = map; + param->dsc.cb = (lv_draw_sw_mask_xcb_t)lv_draw_mask_map; + param->dsc.type = LV_DRAW_SW_MASK_TYPE_MAP; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +LV_ATTRIBUTE_FAST_MEM static lv_draw_sw_mask_res_t lv_draw_mask_line(lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, int32_t len, + lv_draw_sw_mask_line_param_t * p) +{ + /*Make to points relative to the vertex*/ + abs_y -= p->origo.y; + abs_x -= p->origo.x; + + /*Handle special cases*/ + if(p->steep == 0) { + /*Horizontal*/ + if(p->flat) { + /*Non sense: Can't be on the right/left of a horizontal line*/ + if(p->cfg.side == LV_DRAW_SW_MASK_LINE_SIDE_LEFT || + p->cfg.side == LV_DRAW_SW_MASK_LINE_SIDE_RIGHT) return LV_DRAW_SW_MASK_RES_FULL_COVER; + else if(p->cfg.side == LV_DRAW_SW_MASK_LINE_SIDE_TOP && abs_y < 0) return LV_DRAW_SW_MASK_RES_FULL_COVER; + else if(p->cfg.side == LV_DRAW_SW_MASK_LINE_SIDE_BOTTOM && abs_y > 0) return LV_DRAW_SW_MASK_RES_FULL_COVER; + else { + return LV_DRAW_SW_MASK_RES_TRANSP; + } + } + /*Vertical*/ + else { + /*Non sense: Can't be on the top/bottom of a vertical line*/ + if(p->cfg.side == LV_DRAW_SW_MASK_LINE_SIDE_TOP || + p->cfg.side == LV_DRAW_SW_MASK_LINE_SIDE_BOTTOM) return LV_DRAW_SW_MASK_RES_FULL_COVER; + else if(p->cfg.side == LV_DRAW_SW_MASK_LINE_SIDE_RIGHT && abs_x > 0) return LV_DRAW_SW_MASK_RES_FULL_COVER; + else if(p->cfg.side == LV_DRAW_SW_MASK_LINE_SIDE_LEFT) { + if(abs_x + len < 0) return LV_DRAW_SW_MASK_RES_FULL_COVER; + else { + int32_t k = - abs_x; + if(k < 0) return LV_DRAW_SW_MASK_RES_TRANSP; + if(k >= 0 && k < len) lv_memzero(&mask_buf[k], len - k); + return LV_DRAW_SW_MASK_RES_CHANGED; + } + } + else { + if(abs_x + len < 0) return LV_DRAW_SW_MASK_RES_TRANSP; + else { + int32_t k = - abs_x; + if(k < 0) k = 0; + if(k >= len) return LV_DRAW_SW_MASK_RES_TRANSP; + else if(k >= 0 && k < len) lv_memzero(&mask_buf[0], k); + return LV_DRAW_SW_MASK_RES_CHANGED; + } + } + } + } + + lv_draw_sw_mask_res_t res; + if(p->flat) { + res = line_mask_flat(mask_buf, abs_x, abs_y, len, p); + } + else { + res = line_mask_steep(mask_buf, abs_x, abs_y, len, p); + } + + return res; +} + +LV_ATTRIBUTE_FAST_MEM static lv_draw_sw_mask_res_t line_mask_flat(lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, + int32_t len, + lv_draw_sw_mask_line_param_t * p) +{ + + int32_t y_at_x; + y_at_x = (int32_t)((int32_t)p->yx_steep * abs_x) >> 10; + + if(p->yx_steep > 0) { + if(y_at_x > abs_y) { + if(p->inv) { + return LV_DRAW_SW_MASK_RES_FULL_COVER; + } + else { + return LV_DRAW_SW_MASK_RES_TRANSP; + } + } + } + else { + if(y_at_x < abs_y) { + if(p->inv) { + return LV_DRAW_SW_MASK_RES_FULL_COVER; + } + else { + return LV_DRAW_SW_MASK_RES_TRANSP; + } + } + } + + /*At the end of the mask if the limit line is smaller than the mask's y. + *Then the mask is in the "good" area*/ + y_at_x = (int32_t)((int32_t)p->yx_steep * (abs_x + len)) >> 10; + if(p->yx_steep > 0) { + if(y_at_x < abs_y) { + if(p->inv) { + return LV_DRAW_SW_MASK_RES_TRANSP; + } + else { + return LV_DRAW_SW_MASK_RES_FULL_COVER; + } + } + } + else { + if(y_at_x > abs_y) { + if(p->inv) { + return LV_DRAW_SW_MASK_RES_TRANSP; + } + else { + return LV_DRAW_SW_MASK_RES_FULL_COVER; + } + } + } + + int32_t xe; + if(p->yx_steep > 0) xe = ((abs_y * 256) * p->xy_steep) >> 10; + else xe = (((abs_y + 1) * 256) * p->xy_steep) >> 10; + + int32_t xei = xe >> 8; + int32_t xef = xe & 0xFF; + + int32_t px_h; + if(xef == 0) px_h = 255; + else px_h = 255 - (((255 - xef) * p->spx) >> 8); + int32_t k = xei - abs_x; + lv_opa_t m; + + if(xef) { + if(k >= 0 && k < len) { + m = 255 - (((255 - xef) * (255 - px_h)) >> 9); + if(p->inv) m = 255 - m; + mask_buf[k] = mask_mix(mask_buf[k], m); + } + k++; + } + + while(px_h > p->spx) { + if(k >= 0 && k < len) { + m = px_h - (p->spx >> 1); + if(p->inv) m = 255 - m; + mask_buf[k] = mask_mix(mask_buf[k], m); + } + px_h -= p->spx; + k++; + if(k >= len) break; + } + + if(k < len && k >= 0) { + int32_t x_inters = (px_h * p->xy_steep) >> 10; + m = (x_inters * px_h) >> 9; + if(p->yx_steep < 0) m = 255 - m; + if(p->inv) m = 255 - m; + mask_buf[k] = mask_mix(mask_buf[k], m); + } + + if(p->inv) { + k = xei - abs_x; + if(k > len) { + return LV_DRAW_SW_MASK_RES_TRANSP; + } + if(k >= 0) { + lv_memzero(&mask_buf[0], k); + } + } + else { + k++; + if(k < 0) { + return LV_DRAW_SW_MASK_RES_TRANSP; + } + if(k <= len) { + lv_memzero(&mask_buf[k], len - k); + } + } + + return LV_DRAW_SW_MASK_RES_CHANGED; +} + +LV_ATTRIBUTE_FAST_MEM static lv_draw_sw_mask_res_t line_mask_steep(lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, + int32_t len, + lv_draw_sw_mask_line_param_t * p) +{ + int32_t k; + int32_t x_at_y; + /*At the beginning of the mask if the limit line is greater than the mask's y. + *Then the mask is in the "wrong" area*/ + x_at_y = (int32_t)((int32_t)p->xy_steep * abs_y) >> 10; + if(p->xy_steep > 0) x_at_y++; + if(x_at_y < abs_x) { + if(p->inv) { + return LV_DRAW_SW_MASK_RES_FULL_COVER; + } + else { + return LV_DRAW_SW_MASK_RES_TRANSP; + } + } + + /*At the end of the mask if the limit line is smaller than the mask's y. + *Then the mask is in the "good" area*/ + x_at_y = (int32_t)((int32_t)p->xy_steep * (abs_y)) >> 10; + if(x_at_y > abs_x + len) { + if(p->inv) { + return LV_DRAW_SW_MASK_RES_TRANSP; + } + else { + return LV_DRAW_SW_MASK_RES_FULL_COVER; + } + } + + /*X start*/ + int32_t xs = ((abs_y * 256) * p->xy_steep) >> 10; + int32_t xsi = xs >> 8; + int32_t xsf = xs & 0xFF; + + /*X end*/ + int32_t xe = (((abs_y + 1) * 256) * p->xy_steep) >> 10; + int32_t xei = xe >> 8; + int32_t xef = xe & 0xFF; + + lv_opa_t m; + + k = xsi - abs_x; + if(xsi != xei && (p->xy_steep < 0 && xsf == 0)) { + xsf = 0xFF; + xsi = xei; + k--; + } + + if(xsi == xei) { + if(k >= 0 && k < len) { + m = (xsf + xef) >> 1; + if(p->inv) m = 255 - m; + mask_buf[k] = mask_mix(mask_buf[k], m); + } + k++; + + if(p->inv) { + k = xsi - abs_x; + if(k >= len) { + return LV_DRAW_SW_MASK_RES_TRANSP; + } + if(k >= 0) lv_memzero(&mask_buf[0], k); + + } + else { + if(k > len) k = len; + if(k == 0) return LV_DRAW_SW_MASK_RES_TRANSP; + else if(k > 0) lv_memzero(&mask_buf[k], len - k); + } + + } + else { + int32_t y_inters; + if(p->xy_steep < 0) { + y_inters = (xsf * (-p->yx_steep)) >> 10; + if(k >= 0 && k < len) { + m = (y_inters * xsf) >> 9; + if(p->inv) m = 255 - m; + mask_buf[k] = mask_mix(mask_buf[k], m); + } + k--; + + int32_t x_inters = ((255 - y_inters) * (-p->xy_steep)) >> 10; + + if(k >= 0 && k < len) { + m = 255 - (((255 - y_inters) * x_inters) >> 9); + if(p->inv) m = 255 - m; + mask_buf[k] = mask_mix(mask_buf[k], m); + } + + k += 2; + + if(p->inv) { + k = xsi - abs_x - 1; + + if(k > len) k = len; + else if(k > 0) lv_memzero(&mask_buf[0], k); + + } + else { + if(k > len) return LV_DRAW_SW_MASK_RES_FULL_COVER; + if(k >= 0) lv_memzero(&mask_buf[k], len - k); + } + + } + else { + y_inters = ((255 - xsf) * p->yx_steep) >> 10; + if(k >= 0 && k < len) { + m = 255 - ((y_inters * (255 - xsf)) >> 9); + if(p->inv) m = 255 - m; + mask_buf[k] = mask_mix(mask_buf[k], m); + } + + k++; + + int32_t x_inters = ((255 - y_inters) * p->xy_steep) >> 10; + if(k >= 0 && k < len) { + m = ((255 - y_inters) * x_inters) >> 9; + if(p->inv) m = 255 - m; + mask_buf[k] = mask_mix(mask_buf[k], m); + } + k++; + + if(p->inv) { + k = xsi - abs_x; + if(k > len) return LV_DRAW_SW_MASK_RES_TRANSP; + if(k >= 0) lv_memzero(&mask_buf[0], k); + + } + else { + if(k > len) k = len; + if(k == 0) return LV_DRAW_SW_MASK_RES_TRANSP; + else if(k > 0) lv_memzero(&mask_buf[k], len - k); + } + } + } + + return LV_DRAW_SW_MASK_RES_CHANGED; +} + +LV_ATTRIBUTE_FAST_MEM static lv_draw_sw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, int32_t len, + lv_draw_sw_mask_angle_param_t * p) +{ + int32_t rel_y = abs_y - p->cfg.vertex_p.y; + int32_t rel_x = abs_x - p->cfg.vertex_p.x; + + if(p->cfg.start_angle < 180 && p->cfg.end_angle < 180 && + p->cfg.start_angle != 0 && p->cfg.end_angle != 0 && + p->cfg.start_angle > p->cfg.end_angle) { + + if(abs_y < p->cfg.vertex_p.y) { + return LV_DRAW_SW_MASK_RES_FULL_COVER; + } + + /*Start angle mask can work only from the end of end angle mask*/ + int32_t end_angle_first = (rel_y * p->end_line.xy_steep) >> 10; + int32_t start_angle_last = ((rel_y + 1) * p->start_line.xy_steep) >> 10; + + /*Do not let the line end cross the vertex else it will affect the opposite part*/ + if(p->cfg.start_angle > 270 && p->cfg.start_angle <= 359 && start_angle_last < 0) start_angle_last = 0; + else if(p->cfg.start_angle > 0 && p->cfg.start_angle <= 90 && start_angle_last < 0) start_angle_last = 0; + else if(p->cfg.start_angle > 90 && p->cfg.start_angle < 270 && start_angle_last > 0) start_angle_last = 0; + + if(p->cfg.end_angle > 270 && p->cfg.end_angle <= 359 && start_angle_last < 0) start_angle_last = 0; + else if(p->cfg.end_angle > 0 && p->cfg.end_angle <= 90 && start_angle_last < 0) start_angle_last = 0; + else if(p->cfg.end_angle > 90 && p->cfg.end_angle < 270 && start_angle_last > 0) start_angle_last = 0; + + int32_t dist = (end_angle_first - start_angle_last) >> 1; + + lv_draw_sw_mask_res_t res1 = LV_DRAW_SW_MASK_RES_FULL_COVER; + lv_draw_sw_mask_res_t res2 = LV_DRAW_SW_MASK_RES_FULL_COVER; + + int32_t tmp = start_angle_last + dist - rel_x; + if(tmp > len) tmp = len; + if(tmp > 0) { + res1 = lv_draw_mask_line(&mask_buf[0], abs_x, abs_y, tmp, &p->start_line); + if(res1 == LV_DRAW_SW_MASK_RES_TRANSP) { + lv_memzero(&mask_buf[0], tmp); + } + } + + if(tmp > len) tmp = len; + if(tmp < 0) tmp = 0; + res2 = lv_draw_mask_line(&mask_buf[tmp], abs_x + tmp, abs_y, len - tmp, &p->end_line); + if(res2 == LV_DRAW_SW_MASK_RES_TRANSP) { + lv_memzero(&mask_buf[tmp], len - tmp); + } + if(res1 == res2) return res1; + else return LV_DRAW_SW_MASK_RES_CHANGED; + } + else if(p->cfg.start_angle > 180 && p->cfg.end_angle > 180 && p->cfg.start_angle > p->cfg.end_angle) { + + if(abs_y > p->cfg.vertex_p.y) { + return LV_DRAW_SW_MASK_RES_FULL_COVER; + } + + /*Start angle mask can work only from the end of end angle mask*/ + int32_t end_angle_first = (rel_y * p->end_line.xy_steep) >> 10; + int32_t start_angle_last = ((rel_y + 1) * p->start_line.xy_steep) >> 10; + + /*Do not let the line end cross the vertex else it will affect the opposite part*/ + if(p->cfg.start_angle > 270 && p->cfg.start_angle <= 359 && start_angle_last < 0) start_angle_last = 0; + else if(p->cfg.start_angle > 0 && p->cfg.start_angle <= 90 && start_angle_last < 0) start_angle_last = 0; + else if(p->cfg.start_angle > 90 && p->cfg.start_angle < 270 && start_angle_last > 0) start_angle_last = 0; + + if(p->cfg.end_angle > 270 && p->cfg.end_angle <= 359 && start_angle_last < 0) start_angle_last = 0; + else if(p->cfg.end_angle > 0 && p->cfg.end_angle <= 90 && start_angle_last < 0) start_angle_last = 0; + else if(p->cfg.end_angle > 90 && p->cfg.end_angle < 270 && start_angle_last > 0) start_angle_last = 0; + + int32_t dist = (end_angle_first - start_angle_last) >> 1; + + lv_draw_sw_mask_res_t res1 = LV_DRAW_SW_MASK_RES_FULL_COVER; + lv_draw_sw_mask_res_t res2 = LV_DRAW_SW_MASK_RES_FULL_COVER; + + int32_t tmp = start_angle_last + dist - rel_x; + if(tmp > len) tmp = len; + if(tmp > 0) { + res1 = lv_draw_mask_line(&mask_buf[0], abs_x, abs_y, tmp, (lv_draw_sw_mask_line_param_t *)&p->end_line); + if(res1 == LV_DRAW_SW_MASK_RES_TRANSP) { + lv_memzero(&mask_buf[0], tmp); + } + } + + if(tmp > len) tmp = len; + if(tmp < 0) tmp = 0; + res2 = lv_draw_mask_line(&mask_buf[tmp], abs_x + tmp, abs_y, len - tmp, (lv_draw_sw_mask_line_param_t *)&p->start_line); + if(res2 == LV_DRAW_SW_MASK_RES_TRANSP) { + lv_memzero(&mask_buf[tmp], len - tmp); + } + if(res1 == res2) return res1; + else return LV_DRAW_SW_MASK_RES_CHANGED; + } + else { + + lv_draw_sw_mask_res_t res1 = LV_DRAW_SW_MASK_RES_FULL_COVER; + lv_draw_sw_mask_res_t res2 = LV_DRAW_SW_MASK_RES_FULL_COVER; + + if(p->cfg.start_angle == 180) { + if(abs_y < p->cfg.vertex_p.y) res1 = LV_DRAW_SW_MASK_RES_FULL_COVER; + else res1 = LV_DRAW_SW_MASK_RES_UNKNOWN; + } + else if(p->cfg.start_angle == 0) { + if(abs_y < p->cfg.vertex_p.y) res1 = LV_DRAW_SW_MASK_RES_UNKNOWN; + else res1 = LV_DRAW_SW_MASK_RES_FULL_COVER; + } + else if((p->cfg.start_angle < 180 && abs_y < p->cfg.vertex_p.y) || + (p->cfg.start_angle > 180 && abs_y >= p->cfg.vertex_p.y)) { + res1 = LV_DRAW_SW_MASK_RES_UNKNOWN; + } + else { + res1 = lv_draw_mask_line(mask_buf, abs_x, abs_y, len, &p->start_line); + } + + if(p->cfg.end_angle == 180) { + if(abs_y < p->cfg.vertex_p.y) res2 = LV_DRAW_SW_MASK_RES_UNKNOWN; + else res2 = LV_DRAW_SW_MASK_RES_FULL_COVER; + } + else if(p->cfg.end_angle == 0) { + if(abs_y < p->cfg.vertex_p.y) res2 = LV_DRAW_SW_MASK_RES_FULL_COVER; + else res2 = LV_DRAW_SW_MASK_RES_UNKNOWN; + } + else if((p->cfg.end_angle < 180 && abs_y < p->cfg.vertex_p.y) || + (p->cfg.end_angle > 180 && abs_y >= p->cfg.vertex_p.y)) { + res2 = LV_DRAW_SW_MASK_RES_UNKNOWN; + } + else { + res2 = lv_draw_mask_line(mask_buf, abs_x, abs_y, len, &p->end_line); + } + + if(res1 == LV_DRAW_SW_MASK_RES_TRANSP || res2 == LV_DRAW_SW_MASK_RES_TRANSP) return LV_DRAW_SW_MASK_RES_TRANSP; + else if(res1 == LV_DRAW_SW_MASK_RES_UNKNOWN && res2 == LV_DRAW_SW_MASK_RES_UNKNOWN) return LV_DRAW_SW_MASK_RES_TRANSP; + else if(res1 == LV_DRAW_SW_MASK_RES_FULL_COVER && + res2 == LV_DRAW_SW_MASK_RES_FULL_COVER) return LV_DRAW_SW_MASK_RES_FULL_COVER; + else return LV_DRAW_SW_MASK_RES_CHANGED; + } +} + +LV_ATTRIBUTE_FAST_MEM static lv_draw_sw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, int32_t len, + lv_draw_sw_mask_radius_param_t * p) +{ + bool outer = p->cfg.outer; + int32_t radius = p->cfg.radius; + lv_area_t rect; + lv_area_copy(&rect, &p->cfg.rect); + + if(outer == false) { + if((abs_y < rect.y1 || abs_y > rect.y2)) { + return LV_DRAW_SW_MASK_RES_TRANSP; + } + } + else { + if(abs_y < rect.y1 || abs_y > rect.y2) { + return LV_DRAW_SW_MASK_RES_FULL_COVER; + } + } + + if((abs_x >= rect.x1 + radius && abs_x + len <= rect.x2 - radius) || + (abs_y >= rect.y1 + radius && abs_y <= rect.y2 - radius)) { + if(outer == false) { + /*Remove the edges*/ + int32_t last = rect.x1 - abs_x; + if(last > len) return LV_DRAW_SW_MASK_RES_TRANSP; + if(last >= 0) { + lv_memzero(&mask_buf[0], last); + } + + int32_t first = rect.x2 - abs_x + 1; + if(first <= 0) return LV_DRAW_SW_MASK_RES_TRANSP; + else if(first < len) { + lv_memzero(&mask_buf[first], len - first); + } + if(last == 0 && first == len) return LV_DRAW_SW_MASK_RES_FULL_COVER; + else return LV_DRAW_SW_MASK_RES_CHANGED; + } + else { + int32_t first = rect.x1 - abs_x; + if(first < 0) first = 0; + if(first <= len) { + int32_t last = rect.x2 - abs_x - first + 1; + if(first + last > len) last = len - first; + if(last >= 0) { + lv_memzero(&mask_buf[first], last); + } + } + } + return LV_DRAW_SW_MASK_RES_CHANGED; + } + + int32_t k = rect.x1 - abs_x; /*First relevant coordinate on the of the mask*/ + int32_t w = lv_area_get_width(&rect); + int32_t h = lv_area_get_height(&rect); + abs_x -= rect.x1; + abs_y -= rect.y1; + + int32_t aa_len; + int32_t x_start; + int32_t cir_y; + if(abs_y < radius) { + cir_y = radius - abs_y - 1; + } + else { + cir_y = abs_y - (h - radius); + } + lv_opa_t * aa_opa = get_next_line(p->circle, cir_y, &aa_len, &x_start); + int32_t cir_x_right = k + w - radius + x_start; + int32_t cir_x_left = k + radius - x_start - 1; + int32_t i; + + if(outer == false) { + for(i = 0; i < aa_len; i++) { + lv_opa_t opa = aa_opa[aa_len - i - 1]; + if(cir_x_right + i >= 0 && cir_x_right + i < len) { + mask_buf[cir_x_right + i] = mask_mix(opa, mask_buf[cir_x_right + i]); + } + if(cir_x_left - i >= 0 && cir_x_left - i < len) { + mask_buf[cir_x_left - i] = mask_mix(opa, mask_buf[cir_x_left - i]); + } + } + + /*Clean the right side*/ + cir_x_right = LV_CLAMP(0, cir_x_right + i, len); + lv_memzero(&mask_buf[cir_x_right], len - cir_x_right); + + /*Clean the left side*/ + cir_x_left = LV_CLAMP(0, cir_x_left - aa_len + 1, len); + lv_memzero(&mask_buf[0], cir_x_left); + } + else { + for(i = 0; i < aa_len; i++) { + lv_opa_t opa = 255 - (aa_opa[aa_len - 1 - i]); + if(cir_x_right + i >= 0 && cir_x_right + i < len) { + mask_buf[cir_x_right + i] = mask_mix(opa, mask_buf[cir_x_right + i]); + } + if(cir_x_left - i >= 0 && cir_x_left - i < len) { + mask_buf[cir_x_left - i] = mask_mix(opa, mask_buf[cir_x_left - i]); + } + } + + int32_t clr_start = LV_CLAMP(0, cir_x_left + 1, len); + int32_t clr_len = LV_CLAMP(0, cir_x_right - clr_start, len - clr_start); + lv_memzero(&mask_buf[clr_start], clr_len); + } + + return LV_DRAW_SW_MASK_RES_CHANGED; +} + +LV_ATTRIBUTE_FAST_MEM static lv_draw_sw_mask_res_t lv_draw_mask_fade(lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, int32_t len, + lv_draw_sw_mask_fade_param_t * p) +{ + if(abs_y < p->cfg.coords.y1) return LV_DRAW_SW_MASK_RES_FULL_COVER; + if(abs_y > p->cfg.coords.y2) return LV_DRAW_SW_MASK_RES_FULL_COVER; + if(abs_x + len < p->cfg.coords.x1) return LV_DRAW_SW_MASK_RES_FULL_COVER; + if(abs_x > p->cfg.coords.x2) return LV_DRAW_SW_MASK_RES_FULL_COVER; + + if(abs_x + len > p->cfg.coords.x2) len -= abs_x + len - p->cfg.coords.x2 - 1; + + if(abs_x < p->cfg.coords.x1) { + int32_t x_ofs = 0; + x_ofs = p->cfg.coords.x1 - abs_x; + len -= x_ofs; + mask_buf += x_ofs; + } + + int32_t i; + + if(abs_y <= p->cfg.y_top) { + for(i = 0; i < len; i++) { + mask_buf[i] = mask_mix(mask_buf[i], p->cfg.opa_top); + } + return LV_DRAW_SW_MASK_RES_CHANGED; + } + else if(abs_y >= p->cfg.y_bottom) { + for(i = 0; i < len; i++) { + mask_buf[i] = mask_mix(mask_buf[i], p->cfg.opa_bottom); + } + return LV_DRAW_SW_MASK_RES_CHANGED; + } + else { + /*Calculate the opa proportionally*/ + int16_t opa_diff = p->cfg.opa_bottom - p->cfg.opa_top; + int32_t y_diff = p->cfg.y_bottom - p->cfg.y_top + 1; + lv_opa_t opa_act = LV_OPA_MIX2(abs_y - p->cfg.y_top, opa_diff) / y_diff; + opa_act += p->cfg.opa_top; + + for(i = 0; i < len; i++) { + mask_buf[i] = mask_mix(mask_buf[i], opa_act); + } + return LV_DRAW_SW_MASK_RES_CHANGED; + } +} + +LV_ATTRIBUTE_FAST_MEM static lv_draw_sw_mask_res_t lv_draw_mask_map(lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, int32_t len, + lv_draw_sw_mask_map_param_t * p) +{ + /*Handle out of the mask cases*/ + if(abs_y < p->cfg.coords.y1) return LV_DRAW_SW_MASK_RES_FULL_COVER; + if(abs_y > p->cfg.coords.y2) return LV_DRAW_SW_MASK_RES_FULL_COVER; + if(abs_x + len < p->cfg.coords.x1) return LV_DRAW_SW_MASK_RES_FULL_COVER; + if(abs_x > p->cfg.coords.x2) return LV_DRAW_SW_MASK_RES_FULL_COVER; + + /*Got to the current row in the map*/ + const lv_opa_t * map_tmp = p->cfg.map; + map_tmp += (abs_y - p->cfg.coords.y1) * lv_area_get_width(&p->cfg.coords); + + if(abs_x + len > p->cfg.coords.x2) len -= abs_x + len - p->cfg.coords.x2 - 1; + + if(abs_x < p->cfg.coords.x1) { + int32_t x_ofs = 0; + x_ofs = p->cfg.coords.x1 - abs_x; + len -= x_ofs; + mask_buf += x_ofs; + } + else { + map_tmp += (abs_x - p->cfg.coords.x1); + } + + int32_t i; + for(i = 0; i < len; i++) { + mask_buf[i] = mask_mix(mask_buf[i], map_tmp[i]); + } + + return LV_DRAW_SW_MASK_RES_CHANGED; +} + +/** + * Initialize the circle drawing + * @param c pointer to a point. The coordinates will be calculated here + * @param tmp point to a variable. It will store temporary data + * @param radius radius of the circle + */ +static void circ_init(lv_point_t * c, int32_t * tmp, int32_t radius) +{ + c->x = radius; + c->y = 0; + *tmp = 1 - radius; +} + +/** + * Test the circle drawing is ready or not + * @param c same as in circ_init + * @return true if the circle is not ready yet + */ +static bool circ_cont(lv_point_t * c) +{ + return c->y <= c->x; +} + +/** + * Get the next point from the circle + * @param c same as in circ_init. The next point stored here. + * @param tmp same as in circ_init. + */ +static void circ_next(lv_point_t * c, int32_t * tmp) +{ + + if(*tmp <= 0) { + (*tmp) += 2 * c->y + 3; /*Change in decision criterion for y -> y+1*/ + } + else { + (*tmp) += 2 * (c->y - c->x) + 5; /*Change for y -> y+1, x -> x-1*/ + c->x--; + } + c->y++; +} + +static void circ_calc_aa4(_lv_draw_sw_mask_radius_circle_dsc_t * c, int32_t radius) +{ + if(radius == 0) return; + c->radius = radius; + + /*Allocate buffers*/ + if(c->buf) lv_free(c->buf); + + c->buf = lv_malloc(radius * 6 + 6); /*Use uint16_t for opa_start_on_y and x_start_on_y*/ + LV_ASSERT_MALLOC(c->buf); + c->cir_opa = c->buf; + c->opa_start_on_y = (uint16_t *)(c->buf + 2 * radius + 2); + c->x_start_on_y = (uint16_t *)(c->buf + 4 * radius + 4); + + /*Special case, handle manually*/ + if(radius == 1) { + c->cir_opa[0] = 180; + c->opa_start_on_y[0] = 0; + c->opa_start_on_y[1] = 1; + c->x_start_on_y[0] = 0; + return; + } + + const size_t cir_xy_size = (radius + 1) * 2 * 2 * sizeof(int32_t); + int32_t * cir_x = lv_malloc_zeroed(cir_xy_size); + int32_t * cir_y = &cir_x[(radius + 1) * 2]; + + uint32_t y_8th_cnt = 0; + lv_point_t cp; + int32_t tmp; + circ_init(&cp, &tmp, radius * 4); /*Upscale by 4*/ + int32_t i; + + uint32_t x_int[4]; + uint32_t x_fract[4]; + int32_t cir_size = 0; + x_int[0] = cp.x >> 2; + x_fract[0] = 0; + + /*Calculate an 1/8 circle*/ + while(circ_cont(&cp)) { + /*Calculate 4 point of the circle */ + for(i = 0; i < 4; i++) { + circ_next(&cp, &tmp); + if(circ_cont(&cp) == false) break; + x_int[i] = cp.x >> 2; + x_fract[i] = cp.x & 0x3; + } + if(i != 4) break; + + /*All lines on the same x when downscaled*/ + if(x_int[0] == x_int[3]) { + cir_x[cir_size] = x_int[0]; + cir_y[cir_size] = y_8th_cnt; + c->cir_opa[cir_size] = x_fract[0] + x_fract[1] + x_fract[2] + x_fract[3]; + c->cir_opa[cir_size] *= 16; + cir_size++; + } + /*Second line on new x when downscaled*/ + else if(x_int[0] != x_int[1]) { + cir_x[cir_size] = x_int[0]; + cir_y[cir_size] = y_8th_cnt; + c->cir_opa[cir_size] = x_fract[0]; + c->cir_opa[cir_size] *= 16; + cir_size++; + + cir_x[cir_size] = x_int[0] - 1; + cir_y[cir_size] = y_8th_cnt; + c->cir_opa[cir_size] = 1 * 4 + x_fract[1] + x_fract[2] + x_fract[3];; + c->cir_opa[cir_size] *= 16; + cir_size++; + } + /*Third line on new x when downscaled*/ + else if(x_int[0] != x_int[2]) { + cir_x[cir_size] = x_int[0]; + cir_y[cir_size] = y_8th_cnt; + c->cir_opa[cir_size] = x_fract[0] + x_fract[1]; + c->cir_opa[cir_size] *= 16; + cir_size++; + + cir_x[cir_size] = x_int[0] - 1; + cir_y[cir_size] = y_8th_cnt; + c->cir_opa[cir_size] = 2 * 4 + x_fract[2] + x_fract[3];; + c->cir_opa[cir_size] *= 16; + cir_size++; + } + /*Forth line on new x when downscaled*/ + else { + cir_x[cir_size] = x_int[0]; + cir_y[cir_size] = y_8th_cnt; + c->cir_opa[cir_size] = x_fract[0] + x_fract[1] + x_fract[2]; + c->cir_opa[cir_size] *= 16; + cir_size++; + + cir_x[cir_size] = x_int[0] - 1; + cir_y[cir_size] = y_8th_cnt; + c->cir_opa[cir_size] = 3 * 4 + x_fract[3];; + c->cir_opa[cir_size] *= 16; + cir_size++; + } + + y_8th_cnt++; + } + + /*The point on the 1/8 circle is special, calculate it manually*/ + int32_t mid = radius * 723; + int32_t mid_int = mid >> 10; + if(cir_x[cir_size - 1] != mid_int || cir_y[cir_size - 1] != mid_int) { + int32_t tmp_val = mid - (mid_int << 10); + if(tmp_val <= 512) { + tmp_val = tmp_val * tmp_val * 2; + tmp_val = tmp_val >> (10 + 6); + } + else { + tmp_val = 1024 - tmp_val; + tmp_val = tmp_val * tmp_val * 2; + tmp_val = tmp_val >> (10 + 6); + tmp_val = 15 - tmp_val; + } + + cir_x[cir_size] = mid_int; + cir_y[cir_size] = mid_int; + c->cir_opa[cir_size] = tmp_val; + c->cir_opa[cir_size] *= 16; + cir_size++; + } + + /*Build the second octet by mirroring the first*/ + for(i = cir_size - 2; i >= 0; i--, cir_size++) { + cir_x[cir_size] = cir_y[i]; + cir_y[cir_size] = cir_x[i]; + c->cir_opa[cir_size] = c->cir_opa[i]; + } + + int32_t y = 0; + i = 0; + c->opa_start_on_y[0] = 0; + while(i < cir_size) { + c->opa_start_on_y[y] = i; + c->x_start_on_y[y] = cir_x[i]; + for(; cir_y[i] == y && i < (int32_t)cir_size; i++) { + c->x_start_on_y[y] = LV_MIN(c->x_start_on_y[y], cir_x[i]); + } + y++; + } + + lv_free(cir_x); +} + +static lv_opa_t * get_next_line(_lv_draw_sw_mask_radius_circle_dsc_t * c, int32_t y, int32_t * len, + int32_t * x_start) +{ + *len = c->opa_start_on_y[y + 1] - c->opa_start_on_y[y]; + *x_start = c->x_start_on_y[y]; + return &c->cir_opa[c->opa_start_on_y[y]]; +} + +LV_ATTRIBUTE_FAST_MEM static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new) +{ + if(mask_new >= LV_OPA_MAX) return mask_act; + if(mask_new <= LV_OPA_MIN) return 0; + + return LV_UDIV255(mask_act * mask_new); +} + +#endif /*LV_DRAW_SW_COMPLEX*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_mask.h b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_mask.h new file mode 100644 index 000000000..9cde01683 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_mask.h @@ -0,0 +1,304 @@ +/** + * @file lv_draw_sw_mask.h + * + */ + +#ifndef LV_DRAW_SW_MASK_H +#define LV_DRAW_SW_MASK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include "../../misc/lv_area.h" +#include "../../misc/lv_color.h" +#include "../../misc/lv_math.h" + +/********************* + * DEFINES + *********************/ +#define LV_MASK_ID_INV (-1) +#if LV_DRAW_SW_COMPLEX +# define _LV_MASK_MAX_NUM 16 +#else +# define _LV_MASK_MAX_NUM 1 +#endif + +/********************** + * TYPEDEFS + **********************/ + +enum { + LV_DRAW_SW_MASK_RES_TRANSP, + LV_DRAW_SW_MASK_RES_FULL_COVER, + LV_DRAW_SW_MASK_RES_CHANGED, + LV_DRAW_SW_MASK_RES_UNKNOWN +}; + +typedef uint8_t lv_draw_sw_mask_res_t; + +#if LV_DRAW_SW_COMPLEX + +enum { + LV_DRAW_SW_MASK_TYPE_LINE, + LV_DRAW_SW_MASK_TYPE_ANGLE, + LV_DRAW_SW_MASK_TYPE_RADIUS, + LV_DRAW_SW_MASK_TYPE_FADE, + LV_DRAW_SW_MASK_TYPE_MAP, +}; + +typedef uint8_t lv_draw_sw_mask_type_t; + +enum { + LV_DRAW_SW_MASK_LINE_SIDE_LEFT = 0, + LV_DRAW_SW_MASK_LINE_SIDE_RIGHT, + LV_DRAW_SW_MASK_LINE_SIDE_TOP, + LV_DRAW_SW_MASK_LINE_SIDE_BOTTOM, +}; + +/** + * A common callback type for every mask type. + * Used internally by the library. + */ +typedef lv_draw_sw_mask_res_t (*lv_draw_sw_mask_xcb_t)(lv_opa_t * mask_buf, int32_t abs_x, int32_t abs_y, + int32_t len, + void * p); + +typedef uint8_t lv_draw_sw_mask_line_side_t; + +typedef struct { + lv_draw_sw_mask_xcb_t cb; + lv_draw_sw_mask_type_t type; +} _lv_draw_sw_mask_common_dsc_t; + +typedef struct { + /*The first element must be the common descriptor*/ + _lv_draw_sw_mask_common_dsc_t dsc; + + struct { + /*First point*/ + lv_point_t p1; + + /*Second point*/ + lv_point_t p2; + + /*Which side to keep?*/ + lv_draw_sw_mask_line_side_t side : 2; + } cfg; + + /*A point of the line*/ + lv_point_t origo; + + /*X / (1024*Y) steepness (X is 0..1023 range). What is the change of X in 1024 Y?*/ + int32_t xy_steep; + + /*Y / (1024*X) steepness (Y is 0..1023 range). What is the change of Y in 1024 X?*/ + int32_t yx_steep; + + /*Helper which stores yx_steep for flat lines and xy_steep for steep (non flat) lines*/ + int32_t steep; + + /*Steepness in 1 px in 0..255 range. Used only by flat lines.*/ + int32_t spx; + + /*1: It's a flat line? (Near to horizontal)*/ + uint8_t flat : 1; + + /*Invert the mask. The default is: Keep the left part. + *It is used to select left/right/top/bottom*/ + uint8_t inv: 1; +} lv_draw_sw_mask_line_param_t; + +typedef struct { + /*The first element must be the common descriptor*/ + _lv_draw_sw_mask_common_dsc_t dsc; + + struct { + lv_point_t vertex_p; + int32_t start_angle; + int32_t end_angle; + } cfg; + + lv_draw_sw_mask_line_param_t start_line; + lv_draw_sw_mask_line_param_t end_line; + uint16_t delta_deg; +} lv_draw_sw_mask_angle_param_t; + +typedef struct { + uint8_t * buf; + lv_opa_t * cir_opa; /*Opacity of values on the circumference of an 1/4 circle*/ + uint16_t * x_start_on_y; /*The x coordinate of the circle for each y value*/ + uint16_t * opa_start_on_y; /*The index of `cir_opa` for each y value*/ + int32_t life; /*How many times the entry way used*/ + uint32_t used_cnt; /*Like a semaphore to count the referencing masks*/ + int32_t radius; /*The radius of the entry*/ +} _lv_draw_sw_mask_radius_circle_dsc_t; + +typedef _lv_draw_sw_mask_radius_circle_dsc_t _lv_draw_sw_mask_radius_circle_dsc_arr_t[LV_DRAW_SW_CIRCLE_CACHE_SIZE]; + +typedef struct { + /*The first element must be the common descriptor*/ + _lv_draw_sw_mask_common_dsc_t dsc; + + struct { + lv_area_t rect; + int32_t radius; + /*Invert the mask. 0: Keep the pixels inside.*/ + uint8_t outer: 1; + } cfg; + + _lv_draw_sw_mask_radius_circle_dsc_t * circle; +} lv_draw_sw_mask_radius_param_t; + +typedef struct { + /*The first element must be the common descriptor*/ + _lv_draw_sw_mask_common_dsc_t dsc; + + struct { + lv_area_t coords; + int32_t y_top; + int32_t y_bottom; + lv_opa_t opa_top; + lv_opa_t opa_bottom; + } cfg; + +} lv_draw_sw_mask_fade_param_t; + +typedef struct _lv_draw_sw_mask_map_param_t { + /*The first element must be the common descriptor*/ + _lv_draw_sw_mask_common_dsc_t dsc; + + struct { + lv_area_t coords; + const lv_opa_t * map; + } cfg; +} lv_draw_sw_mask_map_param_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_sw_mask_init(void); + +void lv_draw_sw_mask_deinit(void); + +//! @cond Doxygen_Suppress + +/** + * Apply the added buffers on a line. Used internally by the library's drawing routines. + * @param masks the masks list to apply, must be ended with NULL pointer in array. + * @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`. + * @param abs_x absolute X coordinate where the line to calculate start + * @param abs_y absolute Y coordinate where the line to calculate start + * @param len length of the line to calculate (in pixel count) + * @return One of these values: + * - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero + * - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged + * - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line + */ +LV_ATTRIBUTE_FAST_MEM lv_draw_sw_mask_res_t lv_draw_sw_mask_apply(void * masks[], lv_opa_t * mask_buf, int32_t abs_x, + int32_t abs_y, + int32_t len); + +//! @endcond + +/** + * Free the data from the parameter. + * It's called inside `lv_draw_sw_mask_remove_id` and `lv_draw_sw_mask_remove_custom` + * Needs to be called only in special cases when the mask is not added by `lv_draw_mask_add` + * and not removed by `lv_draw_mask_remove_id` or `lv_draw_mask_remove_custom` + * @param p pointer to a mask parameter + */ +void lv_draw_sw_mask_free_param(void * p); + +/** + * Called by LVGL the rendering of a screen is ready to clean up + * the temporal (cache) data of the masks + */ +void _lv_draw_sw_mask_cleanup(void); + +/** + *Initialize a line mask from two points. + * @param param pointer to a `lv_draw_mask_param_t` to initialize + * @param p1x X coordinate of the first point of the line + * @param p1y Y coordinate of the first point of the line + * @param p2x X coordinate of the second point of the line + * @param p2y y coordinate of the second point of the line + * @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep. + * With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept + * With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept + */ +void lv_draw_sw_mask_line_points_init(lv_draw_sw_mask_line_param_t * param, int32_t p1x, int32_t p1y, + int32_t p2x, + int32_t p2y, lv_draw_sw_mask_line_side_t side); + +/** + *Initialize a line mask from a point and an angle. + * @param param pointer to a `lv_draw_mask_param_t` to initialize + * @param px X coordinate of a point of the line + * @param py X coordinate of a point of the line + * @param angle right 0 deg, bottom: 90 + * @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep. + * With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept + * With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept + */ +void lv_draw_sw_mask_line_angle_init(lv_draw_sw_mask_line_param_t * param, int32_t p1x, int32_t py, int16_t angle, + lv_draw_sw_mask_line_side_t side); + +/** + * Initialize an angle mask. + * @param param pointer to a `lv_draw_mask_param_t` to initialize + * @param vertex_x X coordinate of the angle vertex (absolute coordinates) + * @param vertex_y Y coordinate of the angle vertex (absolute coordinates) + * @param start_angle start angle in degrees. 0 deg on the right, 90 deg, on the bottom + * @param end_angle end angle + */ +void lv_draw_sw_mask_angle_init(lv_draw_sw_mask_angle_param_t * param, int32_t vertex_x, int32_t vertex_y, + int32_t start_angle, int32_t end_angle); + +/** + * Initialize a fade mask. + * @param param pointer to an `lv_draw_mask_radius_param_t` to initialize + * @param rect coordinates of the rectangle to affect (absolute coordinates) + * @param radius radius of the rectangle + * @param inv true: keep the pixels inside the rectangle; keep the pixels outside of the rectangle + */ +void lv_draw_sw_mask_radius_init(lv_draw_sw_mask_radius_param_t * param, const lv_area_t * rect, int32_t radius, + bool inv); + +/** + * Initialize a fade mask. + * @param param pointer to a `lv_draw_mask_param_t` to initialize + * @param coords coordinates of the area to affect (absolute coordinates) + * @param opa_top opacity on the top + * @param y_top at which coordinate start to change to opacity to `opa_bottom` + * @param opa_bottom opacity at the bottom + * @param y_bottom at which coordinate reach `opa_bottom`. + */ +void lv_draw_sw_mask_fade_init(lv_draw_sw_mask_fade_param_t * param, const lv_area_t * coords, lv_opa_t opa_top, + int32_t y_top, + lv_opa_t opa_bottom, int32_t y_bottom); + +/** + * Initialize a map mask. + * @param param pointer to a `lv_draw_mask_param_t` to initialize + * @param coords coordinates of the map (absolute coordinates) + * @param map array of bytes with the mask values + */ +void lv_draw_sw_mask_map_init(lv_draw_sw_mask_map_param_t * param, const lv_area_t * coords, const lv_opa_t * map); + +#endif /*LV_DRAW_SW_COMPLEX*/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_SW_MASK_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_mask_rect.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_mask_rect.c new file mode 100644 index 000000000..1f800a6d5 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_mask_rect.c @@ -0,0 +1,121 @@ +/** + * @file lv_draw_sw_mask_rect.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../lv_draw.h" +#if LV_USE_DRAW_SW +#if LV_DRAW_SW_COMPLEX + +#include "../../misc/lv_math.h" +#include "../../misc/lv_log.h" +#include "../../stdlib/lv_mem.h" +#include "../../stdlib/lv_string.h" +#include "lv_draw_sw.h" +#include "lv_draw_sw_mask.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_sw_mask_rect(lv_draw_unit_t * draw_unit, const lv_draw_mask_rect_dsc_t * dsc, const lv_area_t * coords) +{ + LV_UNUSED(coords); + + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, &dsc->area, draw_unit->clip_area)) { + return; + } + + lv_layer_t * target_layer = draw_unit->target_layer; + lv_area_t * buf_area = &target_layer->buf_area; + lv_area_t clear_area; + + void * draw_buf = target_layer->draw_buf; + + /*Clear the top part*/ + lv_area_set(&clear_area, draw_unit->clip_area->x1, draw_unit->clip_area->y1, draw_unit->clip_area->x2, + dsc->area.y1 - 1); + lv_area_move(&clear_area, -buf_area->x1, -buf_area->y1); + lv_draw_buf_clear(draw_buf, &clear_area); + + /*Clear the bottom part*/ + lv_area_set(&clear_area, draw_unit->clip_area->x1, dsc->area.y2 + 1, draw_unit->clip_area->x2, + draw_unit->clip_area->y2); + lv_area_move(&clear_area, -buf_area->x1, -buf_area->y1); + lv_draw_buf_clear(draw_buf, &clear_area); + + /*Clear the left part*/ + lv_area_set(&clear_area, draw_unit->clip_area->x1, dsc->area.y1, dsc->area.x1 - 1, dsc->area.y2); + lv_area_move(&clear_area, -buf_area->x1, -buf_area->y1); + lv_draw_buf_clear(draw_buf, &clear_area); + + /*Clear the right part*/ + lv_area_set(&clear_area, dsc->area.x2 + 1, dsc->area.y1, draw_unit->clip_area->x2, dsc->area.y2); + lv_area_move(&clear_area, -buf_area->x1, -buf_area->y1); + lv_draw_buf_clear(draw_buf, &clear_area); + + lv_draw_sw_mask_radius_param_t param; + lv_draw_sw_mask_radius_init(¶m, &dsc->area, dsc->radius, false); + + void * masks[2] = {0}; + masks[0] = ¶m; + + uint32_t area_w = lv_area_get_width(&draw_area); + lv_opa_t * mask_buf = lv_malloc(area_w); + + int32_t y; + for(y = draw_area.y1; y <= draw_area.y2; y++) { + lv_memset(mask_buf, 0xff, area_w); + lv_draw_sw_mask_res_t res = lv_draw_sw_mask_apply(masks, mask_buf, draw_area.x1, y, area_w); + if(res == LV_DRAW_SW_MASK_RES_FULL_COVER) continue; + + lv_color32_t * c32_buf = lv_draw_layer_go_to_xy(target_layer, draw_area.x1 - buf_area->x1, + y - buf_area->y1); + + if(res == LV_DRAW_SW_MASK_RES_TRANSP) { + lv_memzero(c32_buf, area_w * sizeof(lv_color32_t)); + } + else { + uint32_t i; + for(i = 0; i < area_w; i++) { + if(mask_buf[i] != LV_OPA_COVER) { + c32_buf[i].alpha = LV_OPA_MIX2(c32_buf[i].alpha, mask_buf[i]); + } + } + } + } + + lv_free(mask_buf); + lv_draw_sw_mask_free_param(¶m); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_DRAW_SW_COMPLEX*/ +#endif /*LV_USE_DRAW_SW*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_polygon.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_polygon.c deleted file mode 100644 index a05b4713e..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_polygon.c +++ /dev/null @@ -1,207 +0,0 @@ -/** - * @file lv_draw_sw_polygon.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_draw_sw.h" -#include "../../misc/lv_math.h" -#include "../../misc/lv_mem.h" -#include "../../misc/lv_area.h" -#include "../../misc/lv_color.h" -#include "../lv_draw_rect.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Draw a polygon. Only convex polygons are supported - * @param points an array of points - * @param point_cnt number of points - * @param clip_area polygon will be drawn only in this area - * @param draw_dsc pointer to an initialized `lv_draw_rect_dsc_t` variable - */ -void lv_draw_sw_polygon(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t * points, - uint16_t point_cnt) -{ -#if LV_DRAW_COMPLEX - if(point_cnt < 3) return; - if(points == NULL) return; - - /*Join adjacent points if they are on the same coordinate*/ - lv_point_t * p = lv_mem_buf_get(point_cnt * sizeof(lv_point_t)); - if(p == NULL) return; - uint16_t i; - uint16_t pcnt = 0; - p[0] = points[0]; - for(i = 0; i < point_cnt - 1; i++) { - if(points[i].x != points[i + 1].x || points[i].y != points[i + 1].y) { - p[pcnt] = points[i]; - pcnt++; - } - } - /*The first and the last points are also adjacent*/ - if(points[0].x != points[point_cnt - 1].x || points[0].y != points[point_cnt - 1].y) { - p[pcnt] = points[point_cnt - 1]; - pcnt++; - } - - point_cnt = pcnt; - if(point_cnt < 3) { - lv_mem_buf_release(p); - return; - } - - lv_area_t poly_coords = {.x1 = LV_COORD_MAX, .y1 = LV_COORD_MAX, .x2 = LV_COORD_MIN, .y2 = LV_COORD_MIN}; - - for(i = 0; i < point_cnt; i++) { - poly_coords.x1 = LV_MIN(poly_coords.x1, p[i].x); - poly_coords.y1 = LV_MIN(poly_coords.y1, p[i].y); - poly_coords.x2 = LV_MAX(poly_coords.x2, p[i].x); - poly_coords.y2 = LV_MAX(poly_coords.y2, p[i].y); - } - - bool is_common; - lv_area_t clip_area; - is_common = _lv_area_intersect(&clip_area, &poly_coords, draw_ctx->clip_area); - if(!is_common) { - lv_mem_buf_release(p); - return; - } - - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &clip_area; - - /*Find the lowest point*/ - lv_coord_t y_min = p[0].y; - int16_t y_min_i = 0; - - for(i = 1; i < point_cnt; i++) { - if(p[i].y < y_min) { - y_min = p[i].y; - y_min_i = i; - } - } - - lv_draw_mask_line_param_t * mp = lv_mem_buf_get(sizeof(lv_draw_mask_line_param_t) * point_cnt); - lv_draw_mask_line_param_t * mp_next = mp; - - int32_t i_prev_left = y_min_i; - int32_t i_prev_right = y_min_i; - int32_t i_next_left; - int32_t i_next_right; - uint32_t mask_cnt = 0; - - /*Get the index of the left and right points*/ - i_next_left = y_min_i - 1; - if(i_next_left < 0) i_next_left = point_cnt + i_next_left; - - i_next_right = y_min_i + 1; - if(i_next_right > point_cnt - 1) i_next_right = 0; - - /** - * Check if the order of points is inverted or not. - * The normal case is when the left point is on `y_min_i - 1` - * Explanation: - * if angle(p_left) < angle(p_right) -> inverted - * dy_left/dx_left < dy_right/dx_right - * dy_left * dx_right < dy_right * dx_left - */ - lv_coord_t dxl = p[i_next_left].x - p[y_min_i].x; - lv_coord_t dxr = p[i_next_right].x - p[y_min_i].x; - lv_coord_t dyl = p[i_next_left].y - p[y_min_i].y; - lv_coord_t dyr = p[i_next_right].y - p[y_min_i].y; - - bool inv = false; - if(dyl * dxr < dyr * dxl) inv = true; - - do { - if(!inv) { - i_next_left = i_prev_left - 1; - if(i_next_left < 0) i_next_left = point_cnt + i_next_left; - - i_next_right = i_prev_right + 1; - if(i_next_right > point_cnt - 1) i_next_right = 0; - } - else { - i_next_left = i_prev_left + 1; - if(i_next_left > point_cnt - 1) i_next_left = 0; - - i_next_right = i_prev_right - 1; - if(i_next_right < 0) i_next_right = point_cnt + i_next_right; - } - - if(p[i_next_left].y >= p[i_prev_left].y) { - if(p[i_next_left].y != p[i_prev_left].y && - p[i_next_left].x != p[i_prev_left].x) { - lv_draw_mask_line_points_init(mp_next, p[i_prev_left].x, p[i_prev_left].y, - p[i_next_left].x, p[i_next_left].y, - LV_DRAW_MASK_LINE_SIDE_RIGHT); - lv_draw_mask_add(mp_next, mp); - mp_next++; - } - mask_cnt++; - i_prev_left = i_next_left; - } - - if(mask_cnt == point_cnt) break; - - if(p[i_next_right].y >= p[i_prev_right].y) { - if(p[i_next_right].y != p[i_prev_right].y && - p[i_next_right].x != p[i_prev_right].x) { - - lv_draw_mask_line_points_init(mp_next, p[i_prev_right].x, p[i_prev_right].y, - p[i_next_right].x, p[i_next_right].y, - LV_DRAW_MASK_LINE_SIDE_LEFT); - lv_draw_mask_add(mp_next, mp); - mp_next++; - } - mask_cnt++; - i_prev_right = i_next_right; - } - - } while(mask_cnt < point_cnt); - - lv_draw_rect(draw_ctx, draw_dsc, &poly_coords); - - lv_draw_mask_remove_custom(mp); - - lv_mem_buf_release(mp); - lv_mem_buf_release(p); - - draw_ctx->clip_area = clip_area_ori; -#else - LV_UNUSED(points); - LV_UNUSED(point_cnt); - LV_UNUSED(draw_ctx); - LV_UNUSED(draw_dsc); - LV_LOG_WARN("Can't draw polygon with LV_DRAW_COMPLEX == 0"); -#endif /*LV_DRAW_COMPLEX*/ -} - -/********************** - * STATIC FUNCTIONS - **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_rect.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_rect.c deleted file mode 100644 index a1e620b3c..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_rect.c +++ /dev/null @@ -1,1436 +0,0 @@ -/** - * @file lv_draw_rect.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_draw_sw.h" -#include "../../misc/lv_math.h" -#include "../../misc/lv_txt_ap.h" -#include "../../core/lv_refr.h" -#include "../../misc/lv_assert.h" -#include "lv_draw_sw_dither.h" - -/********************* - * DEFINES - *********************/ -#define SHADOW_UPSCALE_SHIFT 6 -#define SHADOW_ENHANCE 1 -#define SPLIT_LIMIT 50 - - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); -static void draw_bg_img(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); -static void draw_border(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); - -static void draw_outline(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords); - -#if LV_DRAW_COMPLEX -static void /* LV_ATTRIBUTE_FAST_MEM */ draw_shadow(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, - const lv_area_t * coords); -static void /* LV_ATTRIBUTE_FAST_MEM */ shadow_draw_corner_buf(const lv_area_t * coords, uint16_t * sh_buf, - lv_coord_t s, lv_coord_t r); -static void /* LV_ATTRIBUTE_FAST_MEM */ shadow_blur_corner(lv_coord_t size, lv_coord_t sw, uint16_t * sh_ups_buf); -#endif - -void draw_border_generic(lv_draw_ctx_t * draw_ctx, const lv_area_t * outer_area, const lv_area_t * inner_area, - lv_coord_t rout, lv_coord_t rin, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode); - -static void draw_border_simple(lv_draw_ctx_t * draw_ctx, const lv_area_t * outer_area, const lv_area_t * inner_area, - lv_color_t color, lv_opa_t opa); - - -/********************** - * STATIC VARIABLES - **********************/ -#if defined(LV_SHADOW_CACHE_SIZE) && LV_SHADOW_CACHE_SIZE > 0 - static uint8_t sh_cache[LV_SHADOW_CACHE_SIZE * LV_SHADOW_CACHE_SIZE]; - static int32_t sh_cache_size = -1; - static int32_t sh_cache_r = -1; -#endif - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void lv_draw_sw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) -{ -#if LV_DRAW_COMPLEX - draw_shadow(draw_ctx, dsc, coords); -#endif - - draw_bg(draw_ctx, dsc, coords); - draw_bg_img(draw_ctx, dsc, coords); - - draw_border(draw_ctx, dsc, coords); - - draw_outline(draw_ctx, dsc, coords); - - LV_ASSERT_MEM_INTEGRITY(); -} - -void lv_draw_sw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) -{ -#if LV_COLOR_SCREEN_TRANSP && LV_COLOR_DEPTH == 32 - lv_memset_00(draw_ctx->buf, lv_area_get_size(draw_ctx->buf_area) * sizeof(lv_color_t)); -#endif - - draw_bg(draw_ctx, dsc, coords); - draw_bg_img(draw_ctx, dsc, coords); -} - - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void draw_bg(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) -{ - if(dsc->bg_opa <= LV_OPA_MIN) return; - - lv_area_t bg_coords; - lv_area_copy(&bg_coords, coords); - - /*If the border fully covers make the bg area 1px smaller to avoid artifacts on the corners*/ - if(dsc->border_width > 1 && dsc->border_opa >= LV_OPA_MAX && dsc->radius != 0) { - bg_coords.x1 += (dsc->border_side & LV_BORDER_SIDE_LEFT) ? 1 : 0; - bg_coords.y1 += (dsc->border_side & LV_BORDER_SIDE_TOP) ? 1 : 0; - bg_coords.x2 -= (dsc->border_side & LV_BORDER_SIDE_RIGHT) ? 1 : 0; - bg_coords.y2 -= (dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? 1 : 0; - } - - lv_area_t clipped_coords; - if(!_lv_area_intersect(&clipped_coords, &bg_coords, draw_ctx->clip_area)) return; - - lv_grad_dir_t grad_dir = dsc->bg_grad.dir; - lv_color_t bg_color = grad_dir == LV_GRAD_DIR_NONE ? dsc->bg_color : dsc->bg_grad.stops[0].color; - if(bg_color.full == dsc->bg_grad.stops[1].color.full) grad_dir = LV_GRAD_DIR_NONE; - - bool mask_any = lv_draw_mask_is_any(&bg_coords); - lv_draw_sw_blend_dsc_t blend_dsc = {0}; - blend_dsc.blend_mode = dsc->blend_mode; - blend_dsc.color = bg_color; - - /*Most simple case: just a plain rectangle*/ - if(!mask_any && dsc->radius == 0 && (grad_dir == LV_GRAD_DIR_NONE)) { - blend_dsc.blend_area = &bg_coords; - blend_dsc.opa = dsc->bg_opa; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - return; - } - - /*Complex case: there is gradient, mask, or radius*/ -#if LV_DRAW_COMPLEX == 0 - LV_LOG_WARN("Can't draw complex rectangle because LV_DRAW_COMPLEX = 0"); -#else - lv_opa_t opa = dsc->bg_opa >= LV_OPA_MAX ? LV_OPA_COVER : dsc->bg_opa; - - /*Get the real radius. Can't be larger than the half of the shortest side */ - lv_coord_t coords_bg_w = lv_area_get_width(&bg_coords); - lv_coord_t coords_bg_h = lv_area_get_height(&bg_coords); - int32_t short_side = LV_MIN(coords_bg_w, coords_bg_h); - int32_t rout = LV_MIN(dsc->radius, short_side >> 1); - - /*Add a radius mask if there is radius*/ - int32_t clipped_w = lv_area_get_width(&clipped_coords); - int16_t mask_rout_id = LV_MASK_ID_INV; - lv_opa_t * mask_buf = NULL; - lv_draw_mask_radius_param_t mask_rout_param; - if(rout > 0 || mask_any) { - mask_buf = lv_mem_buf_get(clipped_w); - lv_draw_mask_radius_init(&mask_rout_param, &bg_coords, rout, false); - mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); - } - - int32_t h; - - lv_area_t blend_area; - blend_area.x1 = clipped_coords.x1; - blend_area.x2 = clipped_coords.x2; - - blend_dsc.mask_buf = mask_buf; - blend_dsc.blend_area = &blend_area; - blend_dsc.mask_area = &blend_area; - blend_dsc.opa = LV_OPA_COVER; - - - /*Get gradient if appropriate*/ - lv_grad_t * grad = lv_gradient_get(&dsc->bg_grad, coords_bg_w, coords_bg_h); - if(grad && grad_dir == LV_GRAD_DIR_HOR) { - blend_dsc.src_buf = grad->map + clipped_coords.x1 - bg_coords.x1; - } - -#if _DITHER_GRADIENT - lv_dither_mode_t dither_mode = dsc->bg_grad.dither; - lv_dither_func_t dither_func = &lv_dither_none; - lv_coord_t grad_size = coords_bg_w; - if(grad_dir == LV_GRAD_DIR_VER && dither_mode != LV_DITHER_NONE) { - /* When dithering, we are still using a map that's changing from line to line*/ - blend_dsc.src_buf = grad->map; - } - - if(grad && dither_mode == LV_DITHER_NONE) { - grad->filled = 0; /*Should we force refilling it each draw call ?*/ - if(grad_dir == LV_GRAD_DIR_VER) - grad_size = coords_bg_h; - } - else -#if LV_DITHER_ERROR_DIFFUSION - if(dither_mode == LV_DITHER_ORDERED) -#endif - switch(grad_dir) { - case LV_GRAD_DIR_HOR: - dither_func = lv_dither_ordered_hor; - break; - case LV_GRAD_DIR_VER: - dither_func = lv_dither_ordered_ver; - break; - default: - dither_func = NULL; - } - -#if LV_DITHER_ERROR_DIFFUSION - else if(dither_mode == LV_DITHER_ERR_DIFF) - switch(grad_dir) { - case LV_GRAD_DIR_HOR: - dither_func = lv_dither_err_diff_hor; - break; - case LV_GRAD_DIR_VER: - dither_func = lv_dither_err_diff_ver; - break; - default: - dither_func = NULL; - } -#endif -#endif - - /*There is another mask too. Draw line by line. */ - if(mask_any) { - for(h = clipped_coords.y1; h <= clipped_coords.y2; h++) { - blend_area.y1 = h; - blend_area.y2 = h; - - /* Initialize the mask to opa instead of 0xFF and blend with LV_OPA_COVER. - * It saves calculating the final opa in lv_draw_sw_blend*/ - lv_memset(mask_buf, opa, clipped_w); - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf, clipped_coords.x1, h, clipped_w); - if(blend_dsc.mask_res == LV_DRAW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - -#if _DITHER_GRADIENT - if(dither_func) dither_func(grad, blend_area.x1, h - bg_coords.y1, grad_size); -#endif - if(grad_dir == LV_GRAD_DIR_VER) blend_dsc.color = grad->map[h - bg_coords.y1]; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - goto bg_clean_up; - } - - - /* Draw the top of the rectangle line by line and mirror it to the bottom. */ - for(h = 0; h < rout; h++) { - lv_coord_t top_y = bg_coords.y1 + h; - lv_coord_t bottom_y = bg_coords.y2 - h; - if(top_y < clipped_coords.y1 && bottom_y > clipped_coords.y2) continue; /*This line is clipped now*/ - - /* Initialize the mask to opa instead of 0xFF and blend with LV_OPA_COVER. - * It saves calculating the final opa in lv_draw_sw_blend*/ - lv_memset(mask_buf, opa, clipped_w); - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf, blend_area.x1, top_y, clipped_w); - if(blend_dsc.mask_res == LV_DRAW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - - if(top_y >= clipped_coords.y1) { - blend_area.y1 = top_y; - blend_area.y2 = top_y; - -#if _DITHER_GRADIENT - if(dither_func) dither_func(grad, blend_area.x1, top_y - bg_coords.y1, grad_size); -#endif - if(grad_dir == LV_GRAD_DIR_VER) blend_dsc.color = grad->map[top_y - bg_coords.y1]; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - - if(bottom_y <= clipped_coords.y2) { - blend_area.y1 = bottom_y; - blend_area.y2 = bottom_y; - -#if _DITHER_GRADIENT - if(dither_func) dither_func(grad, blend_area.x1, bottom_y - bg_coords.y1, grad_size); -#endif - if(grad_dir == LV_GRAD_DIR_VER) blend_dsc.color = grad->map[bottom_y - bg_coords.y1]; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - } - - /* Draw the center of the rectangle.*/ - - /*If no other masks and no gradient, the center is a simple rectangle*/ - lv_area_t center_coords; - center_coords.x1 = bg_coords.x1; - center_coords.x2 = bg_coords.x2; - center_coords.y1 = bg_coords.y1 + rout; - center_coords.y2 = bg_coords.y2 - rout; - bool mask_any_center = lv_draw_mask_is_any(¢er_coords); - if(!mask_any_center && grad_dir == LV_GRAD_DIR_NONE) { - blend_area.y1 = bg_coords.y1 + rout; - blend_area.y2 = bg_coords.y2 - rout; - blend_dsc.opa = opa; - blend_dsc.mask_buf = NULL; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - /*With gradient and/or mask draw line by line*/ - else { - blend_dsc.opa = opa; - blend_dsc.mask_res = LV_DRAW_MASK_RES_FULL_COVER; - int32_t h_end = bg_coords.y2 - rout; - for(h = bg_coords.y1 + rout; h <= h_end; h++) { - /*If there is no other mask do not apply mask as in the center there is no radius to mask*/ - if(mask_any_center) { - lv_memset(mask_buf, opa, clipped_w); - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf, clipped_coords.x1, h, clipped_w); - } - - blend_area.y1 = h; - blend_area.y2 = h; - -#if _DITHER_GRADIENT - if(dither_func) dither_func(grad, blend_area.x1, h - bg_coords.y1, grad_size); -#endif - if(grad_dir == LV_GRAD_DIR_VER) blend_dsc.color = grad->map[h - bg_coords.y1]; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - } - - -bg_clean_up: - if(mask_buf) lv_mem_buf_release(mask_buf); - if(mask_rout_id != LV_MASK_ID_INV) { - lv_draw_mask_remove_id(mask_rout_id); - lv_draw_mask_free_param(&mask_rout_param); - } - if(grad) { - lv_gradient_cleanup(grad); - } - -#endif -} - -static void draw_bg_img(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) -{ - if(dsc->bg_img_src == NULL) return; - if(dsc->bg_img_opa <= LV_OPA_MIN) return; - - lv_area_t clip_area; - if(!_lv_area_intersect(&clip_area, coords, draw_ctx->clip_area)) { - return; - } - - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &clip_area; - - lv_img_src_t src_type = lv_img_src_get_type(dsc->bg_img_src); - if(src_type == LV_IMG_SRC_SYMBOL) { - lv_point_t size; - lv_txt_get_size(&size, dsc->bg_img_src, dsc->bg_img_symbol_font, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); - lv_area_t a; - a.x1 = coords->x1 + lv_area_get_width(coords) / 2 - size.x / 2; - a.x2 = a.x1 + size.x - 1; - a.y1 = coords->y1 + lv_area_get_height(coords) / 2 - size.y / 2; - a.y2 = a.y1 + size.y - 1; - - lv_draw_label_dsc_t label_draw_dsc; - lv_draw_label_dsc_init(&label_draw_dsc); - label_draw_dsc.font = dsc->bg_img_symbol_font; - label_draw_dsc.color = dsc->bg_img_recolor; - label_draw_dsc.opa = dsc->bg_img_opa; - lv_draw_label(draw_ctx, &label_draw_dsc, &a, dsc->bg_img_src, NULL); - } - else { - lv_img_header_t header; - lv_res_t res = lv_img_decoder_get_info(dsc->bg_img_src, &header); - if(res == LV_RES_OK) { - lv_draw_img_dsc_t img_dsc; - lv_draw_img_dsc_init(&img_dsc); - img_dsc.blend_mode = dsc->blend_mode; - img_dsc.recolor = dsc->bg_img_recolor; - img_dsc.recolor_opa = dsc->bg_img_recolor_opa; - img_dsc.opa = dsc->bg_img_opa; - - /*Center align*/ - if(dsc->bg_img_tiled == false) { - lv_area_t area; - area.x1 = coords->x1 + lv_area_get_width(coords) / 2 - header.w / 2; - area.y1 = coords->y1 + lv_area_get_height(coords) / 2 - header.h / 2; - area.x2 = area.x1 + header.w - 1; - area.y2 = area.y1 + header.h - 1; - - lv_draw_img(draw_ctx, &img_dsc, &area, dsc->bg_img_src); - } - else { - lv_area_t area; - area.y1 = coords->y1; - area.y2 = area.y1 + header.h - 1; - - for(; area.y1 <= coords->y2; area.y1 += header.h, area.y2 += header.h) { - - area.x1 = coords->x1; - area.x2 = area.x1 + header.w - 1; - for(; area.x1 <= coords->x2; area.x1 += header.w, area.x2 += header.w) { - lv_draw_img(draw_ctx, &img_dsc, &area, dsc->bg_img_src); - } - } - } - } - else { - LV_LOG_WARN("Couldn't read the background image"); - } - } - - draw_ctx->clip_area = clip_area_ori; -} - -static void draw_border(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) -{ - if(dsc->border_opa <= LV_OPA_MIN) return; - if(dsc->border_width == 0) return; - if(dsc->border_side == LV_BORDER_SIDE_NONE) return; - if(dsc->border_post) return; - - int32_t coords_w = lv_area_get_width(coords); - int32_t coords_h = lv_area_get_height(coords); - int32_t rout = dsc->radius; - int32_t short_side = LV_MIN(coords_w, coords_h); - if(rout > short_side >> 1) rout = short_side >> 1; - - /*Get the inner area*/ - lv_area_t area_inner; - lv_area_copy(&area_inner, coords); - area_inner.x1 += ((dsc->border_side & LV_BORDER_SIDE_LEFT) ? dsc->border_width : - (dsc->border_width + rout)); - area_inner.x2 -= ((dsc->border_side & LV_BORDER_SIDE_RIGHT) ? dsc->border_width : - (dsc->border_width + rout)); - area_inner.y1 += ((dsc->border_side & LV_BORDER_SIDE_TOP) ? dsc->border_width : - (dsc->border_width + rout)); - area_inner.y2 -= ((dsc->border_side & LV_BORDER_SIDE_BOTTOM) ? dsc->border_width : - (dsc->border_width + rout)); - - lv_coord_t rin = rout - dsc->border_width; - if(rin < 0) rin = 0; - - draw_border_generic(draw_ctx, coords, &area_inner, rout, rin, dsc->border_color, dsc->border_opa, dsc->blend_mode); - -} - -#if LV_DRAW_COMPLEX -static void LV_ATTRIBUTE_FAST_MEM draw_shadow(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, - const lv_area_t * coords) -{ - /*Check whether the shadow is visible*/ - if(dsc->shadow_width == 0) return; - if(dsc->shadow_opa <= LV_OPA_MIN) return; - - if(dsc->shadow_width == 1 && dsc->shadow_spread <= 0 && - dsc->shadow_ofs_x == 0 && dsc->shadow_ofs_y == 0) { - return; - } - - /*Calculate the rectangle which is blurred to get the shadow in `shadow_area`*/ - lv_area_t core_area; - core_area.x1 = coords->x1 + dsc->shadow_ofs_x - dsc->shadow_spread; - core_area.x2 = coords->x2 + dsc->shadow_ofs_x + dsc->shadow_spread; - core_area.y1 = coords->y1 + dsc->shadow_ofs_y - dsc->shadow_spread; - core_area.y2 = coords->y2 + dsc->shadow_ofs_y + dsc->shadow_spread; - - /*Calculate the bounding box of the shadow*/ - lv_area_t shadow_area; - shadow_area.x1 = core_area.x1 - dsc->shadow_width / 2 - 1; - shadow_area.x2 = core_area.x2 + dsc->shadow_width / 2 + 1; - shadow_area.y1 = core_area.y1 - dsc->shadow_width / 2 - 1; - shadow_area.y2 = core_area.y2 + dsc->shadow_width / 2 + 1; - - lv_opa_t opa = dsc->shadow_opa; - if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; - - /*Get clipped draw area which is the real draw area. - *It is always the same or inside `shadow_area`*/ - lv_area_t draw_area; - if(!_lv_area_intersect(&draw_area, &shadow_area, draw_ctx->clip_area)) return; - - /*Consider 1 px smaller bg to be sure the edge will be covered by the shadow*/ - lv_area_t bg_area; - lv_area_copy(&bg_area, coords); - lv_area_increase(&bg_area, -1, -1); - - /*Get the clamped radius*/ - int32_t r_bg = dsc->radius; - lv_coord_t short_side = LV_MIN(lv_area_get_width(&bg_area), lv_area_get_height(&bg_area)); - if(r_bg > short_side >> 1) r_bg = short_side >> 1; - - /*Get the clamped radius*/ - int32_t r_sh = dsc->radius; - short_side = LV_MIN(lv_area_get_width(&core_area), lv_area_get_height(&core_area)); - if(r_sh > short_side >> 1) r_sh = short_side >> 1; - - - /*Get how many pixels are affected by the blur on the corners*/ - int32_t corner_size = dsc->shadow_width + r_sh; - - lv_opa_t * sh_buf; - -#if LV_SHADOW_CACHE_SIZE - if(sh_cache_size == corner_size && sh_cache_r == r_sh) { - /*Use the cache if available*/ - sh_buf = lv_mem_buf_get(corner_size * corner_size); - lv_memcpy(sh_buf, sh_cache, corner_size * corner_size); - } - else { - /*A larger buffer is required for calculation*/ - sh_buf = lv_mem_buf_get(corner_size * corner_size * sizeof(uint16_t)); - shadow_draw_corner_buf(&core_area, (uint16_t *)sh_buf, dsc->shadow_width, r_sh); - - /*Cache the corner if it fits into the cache size*/ - if((uint32_t)corner_size * corner_size < sizeof(sh_cache)) { - lv_memcpy(sh_cache, sh_buf, corner_size * corner_size); - sh_cache_size = corner_size; - sh_cache_r = r_sh; - } - } -#else - sh_buf = lv_mem_buf_get(corner_size * corner_size * sizeof(uint16_t)); - shadow_draw_corner_buf(&core_area, (uint16_t *)sh_buf, dsc->shadow_width, r_sh); -#endif - - /*Skip a lot of masking if the background will cover the shadow that would be masked out*/ - bool mask_any = lv_draw_mask_is_any(&shadow_area); - bool simple = true; - if(mask_any || dsc->bg_opa < LV_OPA_COVER || dsc->blend_mode != LV_BLEND_MODE_NORMAL) simple = false; - - /*Create a radius mask to clip remove shadow on the bg area*/ - - lv_draw_mask_radius_param_t mask_rout_param; - int16_t mask_rout_id = LV_MASK_ID_INV; - if(!simple) { - lv_draw_mask_radius_init(&mask_rout_param, &bg_area, r_bg, true); - mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); - } - lv_opa_t * mask_buf = lv_mem_buf_get(lv_area_get_width(&shadow_area)); - lv_area_t blend_area; - lv_area_t clip_area_sub; - lv_opa_t * sh_buf_tmp; - lv_coord_t y; - bool simple_sub; - - lv_draw_sw_blend_dsc_t blend_dsc; - lv_memset_00(&blend_dsc, sizeof(blend_dsc)); - blend_dsc.blend_area = &blend_area; - blend_dsc.mask_area = &blend_area; - blend_dsc.mask_buf = mask_buf; - blend_dsc.color = dsc->shadow_color; - blend_dsc.opa = dsc->shadow_opa; - blend_dsc.blend_mode = dsc->blend_mode; - - lv_coord_t w_half = shadow_area.x1 + lv_area_get_width(&shadow_area) / 2; - lv_coord_t h_half = shadow_area.y1 + lv_area_get_height(&shadow_area) / 2; - - /*Draw the corners if they are on the current clip area and not fully covered by the bg*/ - - /*Top right corner*/ - blend_area.x2 = shadow_area.x2; - blend_area.x1 = shadow_area.x2 - corner_size + 1; - blend_area.y1 = shadow_area.y1; - blend_area.y2 = shadow_area.y1 + corner_size - 1; - /*Do not overdraw the other top corners*/ - blend_area.x1 = LV_MAX(blend_area.x1, w_half); - blend_area.y2 = LV_MIN(blend_area.y2, h_half); - - if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_ctx->clip_area) && - !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { - lv_coord_t w = lv_area_get_width(&clip_area_sub); - sh_buf_tmp = sh_buf; - sh_buf_tmp += (clip_area_sub.y1 - shadow_area.y1) * corner_size; - sh_buf_tmp += clip_area_sub.x1 - (shadow_area.x2 - corner_size + 1); - - /*Do not mask if out of the bg*/ - if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; - else simple_sub = simple; - if(w > 0) { - blend_dsc.mask_buf = mask_buf; - blend_area.x1 = clip_area_sub.x1; - blend_area.x2 = clip_area_sub.x2; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ - for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { - blend_area.y1 = y; - blend_area.y2 = y; - - if(!simple_sub) { - lv_memcpy(mask_buf, sh_buf_tmp, corner_size); - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); - if(blend_dsc.mask_res == LV_DRAW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - } - else { - blend_dsc.mask_buf = sh_buf_tmp; - } - lv_draw_sw_blend(draw_ctx, &blend_dsc); - sh_buf_tmp += corner_size; - } - } - } - - /*Bottom right corner. - *Almost the same as top right just read the lines of `sh_buf` from then end*/ - blend_area.x2 = shadow_area.x2; - blend_area.x1 = shadow_area.x2 - corner_size + 1; - blend_area.y1 = shadow_area.y2 - corner_size + 1; - blend_area.y2 = shadow_area.y2; - /*Do not overdraw the other corners*/ - blend_area.x1 = LV_MAX(blend_area.x1, w_half); - blend_area.y1 = LV_MAX(blend_area.y1, h_half + 1); - - if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_ctx->clip_area) && - !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { - lv_coord_t w = lv_area_get_width(&clip_area_sub); - sh_buf_tmp = sh_buf; - sh_buf_tmp += (blend_area.y2 - clip_area_sub.y2) * corner_size; - sh_buf_tmp += clip_area_sub.x1 - (shadow_area.x2 - corner_size + 1); - /*Do not mask if out of the bg*/ - if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; - else simple_sub = simple; - - if(w > 0) { - blend_dsc.mask_buf = mask_buf; - blend_area.x1 = clip_area_sub.x1; - blend_area.x2 = clip_area_sub.x2; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ - for(y = clip_area_sub.y2; y >= clip_area_sub.y1; y--) { - blend_area.y1 = y; - blend_area.y2 = y; - - if(!simple_sub) { - lv_memcpy(mask_buf, sh_buf_tmp, corner_size); - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); - if(blend_dsc.mask_res == LV_DRAW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - } - else { - blend_dsc.mask_buf = sh_buf_tmp; - } - lv_draw_sw_blend(draw_ctx, &blend_dsc); - sh_buf_tmp += corner_size; - } - } - } - - /*Top side*/ - blend_area.x1 = shadow_area.x1 + corner_size; - blend_area.x2 = shadow_area.x2 - corner_size; - blend_area.y1 = shadow_area.y1; - blend_area.y2 = shadow_area.y1 + corner_size - 1; - blend_area.y2 = LV_MIN(blend_area.y2, h_half); - - if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_ctx->clip_area) && - !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { - lv_coord_t w = lv_area_get_width(&clip_area_sub); - sh_buf_tmp = sh_buf; - sh_buf_tmp += (clip_area_sub.y1 - blend_area.y1) * corner_size; - - /*Do not mask if out of the bg*/ - if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; - else simple_sub = simple; - - if(w > 0) { - if(!simple_sub) { - blend_dsc.mask_buf = mask_buf; - } - else { - blend_dsc.mask_buf = NULL; - } - blend_area.x1 = clip_area_sub.x1; - blend_area.x2 = clip_area_sub.x2; - - for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { - blend_area.y1 = y; - blend_area.y2 = y; - - if(!simple_sub) { - lv_memset(mask_buf, sh_buf_tmp[0], w); - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); - if(blend_dsc.mask_res == LV_DRAW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - else { - blend_dsc.opa = opa == LV_OPA_COVER ? sh_buf_tmp[0] : (sh_buf_tmp[0] * dsc->shadow_opa) >> 8; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - sh_buf_tmp += corner_size; - } - } - } - blend_dsc.opa = dsc->shadow_opa; /*Restore*/ - - /*Bottom side*/ - blend_area.x1 = shadow_area.x1 + corner_size; - blend_area.x2 = shadow_area.x2 - corner_size; - blend_area.y1 = shadow_area.y2 - corner_size + 1; - blend_area.y2 = shadow_area.y2; - blend_area.y1 = LV_MAX(blend_area.y1, h_half + 1); - - - if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_ctx->clip_area) && - !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { - lv_coord_t w = lv_area_get_width(&clip_area_sub); - sh_buf_tmp = sh_buf; - sh_buf_tmp += (blend_area.y2 - clip_area_sub.y2) * corner_size; - if(w > 0) { - /*Do not mask if out of the bg*/ - if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; - else simple_sub = simple; - - if(!simple_sub) { - blend_dsc.mask_buf = mask_buf; - } - else { - blend_dsc.mask_buf = NULL; - } - blend_area.x1 = clip_area_sub.x1; - blend_area.x2 = clip_area_sub.x2; - - for(y = clip_area_sub.y2; y >= clip_area_sub.y1; y--) { - blend_area.y1 = y; - blend_area.y2 = y; - - /*Do not mask if out of the bg*/ - if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; - else simple_sub = simple; - - if(!simple_sub) { - lv_memset(mask_buf, sh_buf_tmp[0], w); - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); - if(blend_dsc.mask_res == LV_DRAW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - else { - blend_dsc.opa = opa == LV_OPA_COVER ? sh_buf_tmp[0] : (sh_buf_tmp[0] * dsc->shadow_opa) >> 8; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - - } - sh_buf_tmp += corner_size; - } - } - } - - blend_dsc.opa = dsc->shadow_opa; /*Restore*/ - - /*Right side*/ - blend_area.x1 = shadow_area.x2 - corner_size + 1; - blend_area.x2 = shadow_area.x2; - blend_area.y1 = shadow_area.y1 + corner_size; - blend_area.y2 = shadow_area.y2 - corner_size; - /*Do not overdraw the other corners*/ - blend_area.y1 = LV_MIN(blend_area.y1, h_half + 1); - blend_area.y2 = LV_MAX(blend_area.y2, h_half); - blend_area.x1 = LV_MAX(blend_area.x1, w_half); - - if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_ctx->clip_area) && - !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { - lv_coord_t w = lv_area_get_width(&clip_area_sub); - sh_buf_tmp = sh_buf; - sh_buf_tmp += (corner_size - 1) * corner_size; - sh_buf_tmp += clip_area_sub.x1 - (shadow_area.x2 - corner_size + 1); - - /*Do not mask if out of the bg*/ - if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; - else simple_sub = simple; - blend_dsc.mask_buf = simple_sub ? sh_buf_tmp : mask_buf; - - if(w > 0) { - blend_area.x1 = clip_area_sub.x1; - blend_area.x2 = clip_area_sub.x2; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ - for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { - blend_area.y1 = y; - blend_area.y2 = y; - - if(!simple_sub) { - lv_memcpy(mask_buf, sh_buf_tmp, w); - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); - if(blend_dsc.mask_res == LV_DRAW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - } - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - } - } - - /*Mirror the shadow corner buffer horizontally*/ - sh_buf_tmp = sh_buf ; - for(y = 0; y < corner_size; y++) { - int32_t x; - lv_opa_t * start = sh_buf_tmp; - lv_opa_t * end = sh_buf_tmp + corner_size - 1; - for(x = 0; x < corner_size / 2; x++) { - lv_opa_t tmp = *start; - *start = *end; - *end = tmp; - - start++; - end--; - } - sh_buf_tmp += corner_size; - } - - /*Left side*/ - blend_area.x1 = shadow_area.x1; - blend_area.x2 = shadow_area.x1 + corner_size - 1; - blend_area.y1 = shadow_area.y1 + corner_size; - blend_area.y2 = shadow_area.y2 - corner_size; - /*Do not overdraw the other corners*/ - blend_area.y1 = LV_MIN(blend_area.y1, h_half + 1); - blend_area.y2 = LV_MAX(blend_area.y2, h_half); - blend_area.x2 = LV_MIN(blend_area.x2, w_half - 1); - - if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_ctx->clip_area) && - !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { - lv_coord_t w = lv_area_get_width(&clip_area_sub); - sh_buf_tmp = sh_buf; - sh_buf_tmp += (corner_size - 1) * corner_size; - sh_buf_tmp += clip_area_sub.x1 - blend_area.x1; - - /*Do not mask if out of the bg*/ - if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; - else simple_sub = simple; - blend_dsc.mask_buf = simple_sub ? sh_buf_tmp : mask_buf; - if(w > 0) { - blend_area.x1 = clip_area_sub.x1; - blend_area.x2 = clip_area_sub.x2; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ - for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { - blend_area.y1 = y; - blend_area.y2 = y; - - if(!simple_sub) { - lv_memcpy(mask_buf, sh_buf_tmp, w); - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); - if(blend_dsc.mask_res == LV_DRAW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - } - - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - } - } - - /*Top left corner*/ - blend_area.x1 = shadow_area.x1; - blend_area.x2 = shadow_area.x1 + corner_size - 1; - blend_area.y1 = shadow_area.y1; - blend_area.y2 = shadow_area.y1 + corner_size - 1; - /*Do not overdraw the other corners*/ - blend_area.x2 = LV_MIN(blend_area.x2, w_half - 1); - blend_area.y2 = LV_MIN(blend_area.y2, h_half); - - if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_ctx->clip_area) && - !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { - lv_coord_t w = lv_area_get_width(&clip_area_sub); - sh_buf_tmp = sh_buf; - sh_buf_tmp += (clip_area_sub.y1 - blend_area.y1) * corner_size; - sh_buf_tmp += clip_area_sub.x1 - blend_area.x1; - - /*Do not mask if out of the bg*/ - if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; - else simple_sub = simple; - blend_dsc.mask_buf = mask_buf; - - if(w > 0) { - blend_area.x1 = clip_area_sub.x1; - blend_area.x2 = clip_area_sub.x2; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ - for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { - blend_area.y1 = y; - blend_area.y2 = y; - - if(!simple_sub) { - lv_memcpy(mask_buf, sh_buf_tmp, corner_size); - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); - if(blend_dsc.mask_res == LV_DRAW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - } - else { - blend_dsc.mask_buf = sh_buf_tmp; - } - - lv_draw_sw_blend(draw_ctx, &blend_dsc); - sh_buf_tmp += corner_size; - } - } - } - - /*Bottom left corner. - *Almost the same as bottom right just read the lines of `sh_buf` from then end*/ - blend_area.x1 = shadow_area.x1 ; - blend_area.x2 = shadow_area.x1 + corner_size - 1; - blend_area.y1 = shadow_area.y2 - corner_size + 1; - blend_area.y2 = shadow_area.y2; - /*Do not overdraw the other corners*/ - blend_area.y1 = LV_MAX(blend_area.y1, h_half + 1); - blend_area.x2 = LV_MIN(blend_area.x2, w_half - 1); - - if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_ctx->clip_area) && - !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { - lv_coord_t w = lv_area_get_width(&clip_area_sub); - sh_buf_tmp = sh_buf; - sh_buf_tmp += (blend_area.y2 - clip_area_sub.y2) * corner_size; - sh_buf_tmp += clip_area_sub.x1 - blend_area.x1; - - /*Do not mask if out of the bg*/ - if(simple && _lv_area_is_out(&clip_area_sub, &bg_area, r_bg)) simple_sub = true; - else simple_sub = simple; - blend_dsc.mask_buf = mask_buf; - if(w > 0) { - blend_area.x1 = clip_area_sub.x1; - blend_area.x2 = clip_area_sub.x2; - blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; /*In simple mode it won't be overwritten*/ - for(y = clip_area_sub.y2; y >= clip_area_sub.y1; y--) { - blend_area.y1 = y; - blend_area.y2 = y; - - if(!simple_sub) { - lv_memcpy(mask_buf, sh_buf_tmp, corner_size); - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); - if(blend_dsc.mask_res == LV_DRAW_MASK_RES_FULL_COVER) blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; - } - else { - blend_dsc.mask_buf = sh_buf_tmp; - } - lv_draw_sw_blend(draw_ctx, &blend_dsc); - sh_buf_tmp += corner_size; - } - } - } - - /*Draw the center rectangle.*/ - blend_area.x1 = shadow_area.x1 + corner_size ; - blend_area.x2 = shadow_area.x2 - corner_size; - blend_area.y1 = shadow_area.y1 + corner_size; - blend_area.y2 = shadow_area.y2 - corner_size; - blend_dsc.mask_buf = mask_buf; - - if(_lv_area_intersect(&clip_area_sub, &blend_area, draw_ctx->clip_area) && - !_lv_area_is_in(&clip_area_sub, &bg_area, r_bg)) { - lv_coord_t w = lv_area_get_width(&clip_area_sub); - if(w > 0) { - blend_area.x1 = clip_area_sub.x1; - blend_area.x2 = clip_area_sub.x2; - for(y = clip_area_sub.y1; y <= clip_area_sub.y2; y++) { - blend_area.y1 = y; - blend_area.y2 = y; - - lv_memset_ff(mask_buf, w); - blend_dsc.mask_res = lv_draw_mask_apply(mask_buf, clip_area_sub.x1, y, w); - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - } - } - - if(!simple) { - lv_draw_mask_free_param(&mask_rout_param); - lv_draw_mask_remove_id(mask_rout_id); - } - lv_mem_buf_release(sh_buf); - lv_mem_buf_release(mask_buf); -} - -/** - * Calculate a blurred corner - * @param coords Coordinates of the shadow - * @param sh_buf a buffer to store the result. Its size should be `(sw + r)^2 * 2` - * @param sw shadow width - * @param r radius - */ -static void LV_ATTRIBUTE_FAST_MEM shadow_draw_corner_buf(const lv_area_t * coords, uint16_t * sh_buf, - lv_coord_t sw, lv_coord_t r) -{ - int32_t sw_ori = sw; - int32_t size = sw_ori + r; - - lv_area_t sh_area; - lv_area_copy(&sh_area, coords); - sh_area.x2 = sw / 2 + r - 1 - ((sw & 1) ? 0 : 1); - sh_area.y1 = sw / 2 + 1; - - sh_area.x1 = sh_area.x2 - lv_area_get_width(coords); - sh_area.y2 = sh_area.y1 + lv_area_get_height(coords); - - lv_draw_mask_radius_param_t mask_param; - lv_draw_mask_radius_init(&mask_param, &sh_area, r, false); - -#if SHADOW_ENHANCE - /*Set half shadow width width because blur will be repeated*/ - if(sw_ori == 1) sw = 1; - else sw = sw_ori >> 1; -#endif - - int32_t y; - lv_opa_t * mask_line = lv_mem_buf_get(size); - uint16_t * sh_ups_tmp_buf = (uint16_t *)sh_buf; - for(y = 0; y < size; y++) { - lv_memset_ff(mask_line, size); - lv_draw_mask_res_t mask_res = mask_param.dsc.cb(mask_line, 0, y, size, &mask_param); - if(mask_res == LV_DRAW_MASK_RES_TRANSP) { - lv_memset_00(sh_ups_tmp_buf, size * sizeof(sh_ups_tmp_buf[0])); - } - else { - int32_t i; - sh_ups_tmp_buf[0] = (mask_line[0] << SHADOW_UPSCALE_SHIFT) / sw; - for(i = 1; i < size; i++) { - if(mask_line[i] == mask_line[i - 1]) sh_ups_tmp_buf[i] = sh_ups_tmp_buf[i - 1]; - else sh_ups_tmp_buf[i] = (mask_line[i] << SHADOW_UPSCALE_SHIFT) / sw; - } - } - - sh_ups_tmp_buf += size; - } - lv_mem_buf_release(mask_line); - - lv_draw_mask_free_param(&mask_param); - - if(sw == 1) { - int32_t i; - lv_opa_t * res_buf = (lv_opa_t *)sh_buf; - for(i = 0; i < size * size; i++) { - res_buf[i] = (sh_buf[i] >> SHADOW_UPSCALE_SHIFT); - } - return; - } - - shadow_blur_corner(size, sw, sh_buf); - -#if SHADOW_ENHANCE == 0 - /*The result is required in lv_opa_t not uint16_t*/ - uint32_t x; - lv_opa_t * res_buf = (lv_opa_t *)sh_buf; - for(x = 0; x < size * size; x++) { - res_buf[x] = sh_buf[x]; - } -#else - sw += sw_ori & 1; - if(sw > 1) { - uint32_t i; - uint32_t max_v_div = (LV_OPA_COVER << SHADOW_UPSCALE_SHIFT) / sw; - for(i = 0; i < (uint32_t)size * size; i++) { - if(sh_buf[i] == 0) continue; - else if(sh_buf[i] == LV_OPA_COVER) sh_buf[i] = max_v_div; - else sh_buf[i] = (sh_buf[i] << SHADOW_UPSCALE_SHIFT) / sw; - } - - shadow_blur_corner(size, sw, sh_buf); - } - int32_t x; - lv_opa_t * res_buf = (lv_opa_t *)sh_buf; - for(x = 0; x < size * size; x++) { - res_buf[x] = sh_buf[x]; - } -#endif - -} - -static void LV_ATTRIBUTE_FAST_MEM shadow_blur_corner(lv_coord_t size, lv_coord_t sw, uint16_t * sh_ups_buf) -{ - int32_t s_left = sw >> 1; - int32_t s_right = (sw >> 1); - if((sw & 1) == 0) s_left--; - - /*Horizontal blur*/ - uint16_t * sh_ups_blur_buf = lv_mem_buf_get(size * sizeof(uint16_t)); - - int32_t x; - int32_t y; - - uint16_t * sh_ups_tmp_buf = sh_ups_buf; - - for(y = 0; y < size; y++) { - int32_t v = sh_ups_tmp_buf[size - 1] * sw; - for(x = size - 1; x >= 0; x--) { - sh_ups_blur_buf[x] = v; - - /*Forget the right pixel*/ - uint32_t right_val = 0; - if(x + s_right < size) right_val = sh_ups_tmp_buf[x + s_right]; - v -= right_val; - - /*Add the left pixel*/ - uint32_t left_val; - if(x - s_left - 1 < 0) left_val = sh_ups_tmp_buf[0]; - else left_val = sh_ups_tmp_buf[x - s_left - 1]; - v += left_val; - } - lv_memcpy(sh_ups_tmp_buf, sh_ups_blur_buf, size * sizeof(uint16_t)); - sh_ups_tmp_buf += size; - } - - /*Vertical blur*/ - uint32_t i; - uint32_t max_v = LV_OPA_COVER << SHADOW_UPSCALE_SHIFT; - uint32_t max_v_div = max_v / sw; - for(i = 0; i < (uint32_t)size * size; i++) { - if(sh_ups_buf[i] == 0) continue; - else if(sh_ups_buf[i] == max_v) sh_ups_buf[i] = max_v_div; - else sh_ups_buf[i] = sh_ups_buf[i] / sw; - } - - for(x = 0; x < size; x++) { - sh_ups_tmp_buf = &sh_ups_buf[x]; - int32_t v = sh_ups_tmp_buf[0] * sw; - for(y = 0; y < size ; y++, sh_ups_tmp_buf += size) { - sh_ups_blur_buf[y] = v < 0 ? 0 : (v >> SHADOW_UPSCALE_SHIFT); - - /*Forget the top pixel*/ - uint32_t top_val; - if(y - s_right <= 0) top_val = sh_ups_tmp_buf[0]; - else top_val = sh_ups_buf[(y - s_right) * size + x]; - v -= top_val; - - /*Add the bottom pixel*/ - uint32_t bottom_val; - if(y + s_left + 1 < size) bottom_val = sh_ups_buf[(y + s_left + 1) * size + x]; - else bottom_val = sh_ups_buf[(size - 1) * size + x]; - v += bottom_val; - } - - /*Write back the result into `sh_ups_buf`*/ - sh_ups_tmp_buf = &sh_ups_buf[x]; - for(y = 0; y < size; y++, sh_ups_tmp_buf += size) { - (*sh_ups_tmp_buf) = sh_ups_blur_buf[y]; - } - } - - lv_mem_buf_release(sh_ups_blur_buf); -} -#endif - -static void draw_outline(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) -{ - if(dsc->outline_opa <= LV_OPA_MIN) return; - if(dsc->outline_width == 0) return; - - lv_opa_t opa = dsc->outline_opa; - - if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; - - /*Get the inner radius*/ - lv_area_t area_inner; - lv_area_copy(&area_inner, coords); - - /*Bring the outline closer to make sure there is no color bleeding with pad=0*/ - lv_coord_t pad = dsc->outline_pad - 1; - area_inner.x1 -= pad; - area_inner.y1 -= pad; - area_inner.x2 += pad; - area_inner.y2 += pad; - - lv_area_t area_outer; - lv_area_copy(&area_outer, &area_inner); - - area_outer.x1 -= dsc->outline_width; - area_outer.x2 += dsc->outline_width; - area_outer.y1 -= dsc->outline_width; - area_outer.y2 += dsc->outline_width; - - - int32_t inner_w = lv_area_get_width(&area_inner); - int32_t inner_h = lv_area_get_height(&area_inner); - int32_t rin = dsc->radius; - int32_t short_side = LV_MIN(inner_w, inner_h); - if(rin > short_side >> 1) rin = short_side >> 1; - - lv_coord_t rout = rin + dsc->outline_width; - - draw_border_generic(draw_ctx, &area_outer, &area_inner, rout, rin, dsc->outline_color, dsc->outline_opa, - dsc->blend_mode); -} - -void draw_border_generic(lv_draw_ctx_t * draw_ctx, const lv_area_t * outer_area, const lv_area_t * inner_area, - lv_coord_t rout, lv_coord_t rin, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode) -{ - opa = opa >= LV_OPA_COVER ? LV_OPA_COVER : opa; - - bool mask_any = lv_draw_mask_is_any(outer_area); - -#if LV_DRAW_COMPLEX - - if(!mask_any && rout == 0 && rin == 0) { - draw_border_simple(draw_ctx, outer_area, inner_area, color, opa); - return; - } - - /*Get clipped draw area which is the real draw area. - *It is always the same or inside `coords`*/ - lv_area_t draw_area; - if(!_lv_area_intersect(&draw_area, outer_area, draw_ctx->clip_area)) return; - int32_t draw_area_w = lv_area_get_width(&draw_area); - - lv_draw_sw_blend_dsc_t blend_dsc; - lv_memset_00(&blend_dsc, sizeof(blend_dsc)); - blend_dsc.mask_buf = lv_mem_buf_get(draw_area_w);; - - - /*Create mask for the outer area*/ - int16_t mask_rout_id = LV_MASK_ID_INV; - lv_draw_mask_radius_param_t mask_rout_param; - if(rout > 0) { - lv_draw_mask_radius_init(&mask_rout_param, outer_area, rout, false); - mask_rout_id = lv_draw_mask_add(&mask_rout_param, NULL); - } - - /*Create mask for the inner mask*/ - lv_draw_mask_radius_param_t mask_rin_param; - lv_draw_mask_radius_init(&mask_rin_param, inner_area, rin, true); - int16_t mask_rin_id = lv_draw_mask_add(&mask_rin_param, NULL); - - int32_t h; - lv_area_t blend_area; - blend_dsc.blend_area = &blend_area; - blend_dsc.mask_area = &blend_area; - blend_dsc.color = color; - blend_dsc.opa = opa; - blend_dsc.blend_mode = blend_mode; - - /*Calculate the x and y coordinates where the straight parts area*/ - lv_area_t core_area; - core_area.x1 = LV_MAX(outer_area->x1 + rout, inner_area->x1); - core_area.x2 = LV_MIN(outer_area->x2 - rout, inner_area->x2); - core_area.y1 = LV_MAX(outer_area->y1 + rout, inner_area->y1); - core_area.y2 = LV_MIN(outer_area->y2 - rout, inner_area->y2); - lv_coord_t core_w = lv_area_get_width(&core_area); - - bool top_side = outer_area->y1 <= inner_area->y1 ? true : false; - bool bottom_side = outer_area->y2 >= inner_area->y2 ? true : false; - - /*If there is other masks, need to draw line by line*/ - if(mask_any) { - blend_area.x1 = draw_area.x1; - blend_area.x2 = draw_area.x2; - for(h = draw_area.y1; h <= draw_area.y2; h++) { - if(!top_side && h < core_area.y1) continue; - if(!bottom_side && h > core_area.y2) break; - - blend_area.y1 = h; - blend_area.y2 = h; - - lv_memset_ff(blend_dsc.mask_buf, draw_area_w); - blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask_buf, draw_area.x1, h, draw_area_w); - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - - lv_draw_mask_free_param(&mask_rin_param); - lv_draw_mask_remove_id(mask_rin_id); - if(mask_rout_id != LV_MASK_ID_INV) { - lv_draw_mask_free_param(&mask_rout_param); - lv_draw_mask_remove_id(mask_rout_id); - } - lv_mem_buf_release(blend_dsc.mask_buf); - return; - } - - /*No masks*/ - bool left_side = outer_area->x1 <= inner_area->x1 ? true : false; - bool right_side = outer_area->x2 >= inner_area->x2 ? true : false; - - bool split_hor = true; - if(left_side && right_side && top_side && bottom_side && - core_w < SPLIT_LIMIT) { - split_hor = false; - } - - blend_dsc.mask_res = LV_DRAW_MASK_RES_FULL_COVER; - /*Draw the straight lines first if they are long enough*/ - if(top_side && split_hor) { - blend_area.x1 = core_area.x1; - blend_area.x2 = core_area.x2; - blend_area.y1 = outer_area->y1; - blend_area.y2 = inner_area->y1 - 1; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - - if(bottom_side && split_hor) { - blend_area.x1 = core_area.x1; - blend_area.x2 = core_area.x2; - blend_area.y1 = inner_area->y2 + 1; - blend_area.y2 = outer_area->y2; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - - if(left_side) { - blend_area.x1 = outer_area->x1; - blend_area.x2 = inner_area->x1 - 1; - blend_area.y1 = core_area.y1; - blend_area.y2 = core_area.y2; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - - if(right_side) { - blend_area.x1 = inner_area->x2 + 1; - blend_area.x2 = outer_area->x2; - blend_area.y1 = core_area.y1; - blend_area.y2 = core_area.y2; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - - /*Draw the corners*/ - lv_coord_t blend_w; - - /*Left and right corner together if they are close to each other*/ - if(!split_hor) { - /*Calculate the top corner and mirror it to the bottom*/ - blend_area.x1 = draw_area.x1; - blend_area.x2 = draw_area.x2; - lv_coord_t max_h = LV_MAX(rout, inner_area->y1 - outer_area->y1); - for(h = 0; h < max_h; h++) { - lv_coord_t top_y = outer_area->y1 + h; - lv_coord_t bottom_y = outer_area->y2 - h; - if(top_y < draw_area.y1 && bottom_y > draw_area.y2) continue; /*This line is clipped now*/ - - lv_memset_ff(blend_dsc.mask_buf, draw_area_w); - blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask_buf, blend_area.x1, top_y, draw_area_w); - - if(top_y >= draw_area.y1) { - blend_area.y1 = top_y; - blend_area.y2 = top_y; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - - if(bottom_y <= draw_area.y2) { - blend_area.y1 = bottom_y; - blend_area.y2 = bottom_y; - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - } - } - else { - /*Left corners*/ - blend_area.x1 = draw_area.x1; - blend_area.x2 = LV_MIN(draw_area.x2, core_area.x1 - 1); - blend_w = lv_area_get_width(&blend_area); - if(blend_w > 0) { - if(left_side || top_side) { - for(h = draw_area.y1; h < core_area.y1; h++) { - blend_area.y1 = h; - blend_area.y2 = h; - - lv_memset_ff(blend_dsc.mask_buf, blend_w); - blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask_buf, blend_area.x1, h, blend_w); - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - } - - if(left_side || bottom_side) { - for(h = core_area.y2 + 1; h <= draw_area.y2; h++) { - blend_area.y1 = h; - blend_area.y2 = h; - - lv_memset_ff(blend_dsc.mask_buf, blend_w); - blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask_buf, blend_area.x1, h, blend_w); - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - } - } - - /*Right corners*/ - blend_area.x1 = LV_MAX(draw_area.x1, core_area.x2 + 1); - blend_area.x2 = draw_area.x2; - blend_w = lv_area_get_width(&blend_area); - - if(blend_w > 0) { - if(right_side || top_side) { - for(h = draw_area.y1; h < core_area.y1; h++) { - blend_area.y1 = h; - blend_area.y2 = h; - - lv_memset_ff(blend_dsc.mask_buf, blend_w); - blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask_buf, blend_area.x1, h, blend_w); - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - } - - if(right_side || bottom_side) { - for(h = core_area.y2 + 1; h <= draw_area.y2; h++) { - blend_area.y1 = h; - blend_area.y2 = h; - - lv_memset_ff(blend_dsc.mask_buf, blend_w); - blend_dsc.mask_res = lv_draw_mask_apply(blend_dsc.mask_buf, blend_area.x1, h, blend_w); - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - } - } - } - - lv_draw_mask_free_param(&mask_rin_param); - lv_draw_mask_remove_id(mask_rin_id); - lv_draw_mask_free_param(&mask_rout_param); - lv_draw_mask_remove_id(mask_rout_id); - lv_mem_buf_release(blend_dsc.mask_buf); - -#else /*LV_DRAW_COMPLEX*/ - LV_UNUSED(blend_mode); - LV_UNUSED(rout); - LV_UNUSED(rin); - if(!mask_any) { - draw_border_simple(draw_ctx, outer_area, inner_area, color, opa); - return; - } - -#endif /*LV_DRAW_COMPLEX*/ -} -static void draw_border_simple(lv_draw_ctx_t * draw_ctx, const lv_area_t * outer_area, const lv_area_t * inner_area, - lv_color_t color, lv_opa_t opa) -{ - lv_area_t a; - lv_draw_sw_blend_dsc_t blend_dsc; - lv_memset_00(&blend_dsc, sizeof(lv_draw_sw_blend_dsc_t)); - blend_dsc.blend_area = &a; - blend_dsc.color = color; - blend_dsc.opa = opa; - - bool top_side = outer_area->y1 <= inner_area->y1 ? true : false; - bool bottom_side = outer_area->y2 >= inner_area->y2 ? true : false; - bool left_side = outer_area->x1 <= inner_area->x1 ? true : false; - bool right_side = outer_area->x2 >= inner_area->x2 ? true : false; - - - /*Top*/ - a.x1 = outer_area->x1; - a.x2 = outer_area->x2; - a.y1 = outer_area->y1; - a.y2 = inner_area->y1 - 1; - if(top_side) { - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - - /*Bottom*/ - a.y1 = inner_area->y2 + 1; - a.y2 = outer_area->y2; - if(bottom_side) { - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - - /*Left*/ - a.x1 = outer_area->x1; - a.x2 = inner_area->x1 - 1; - a.y1 = (top_side) ? inner_area->y1 : outer_area->y1; - a.y2 = (bottom_side) ? inner_area->y2 : outer_area->y2; - if(left_side) { - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } - - /*Right*/ - a.x1 = inner_area->x2 + 1; - a.x2 = outer_area->x2; - if(right_side) { - lv_draw_sw_blend(draw_ctx, &blend_dsc); - } -} - diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_transform.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_transform.c index 9ead7b95c..d835f58e1 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_transform.c +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_transform.c @@ -1,5 +1,5 @@ /** - * @file lv_draw_sw_tranform.c + * @file lv_draw_sw_transform.c * */ @@ -7,11 +7,14 @@ * INCLUDES *********************/ #include "lv_draw_sw.h" +#if LV_USE_DRAW_SW + #include "../../misc/lv_assert.h" #include "../../misc/lv_area.h" #include "../../core/lv_refr.h" +#include "../../misc/lv_color.h" +#include "../../stdlib/lv_string.h" -#if LV_DRAW_COMPLEX /********************* * DEFINES *********************/ @@ -26,7 +29,8 @@ typedef struct { int32_t y_out; int32_t sinma; int32_t cosma; - int32_t zoom; + int32_t scale_x; + int32_t scale_y; int32_t angle; int32_t pivot_x_256; int32_t pivot_y_256; @@ -47,23 +51,21 @@ typedef struct { static void transform_point_upscaled(point_transform_dsc_t * t, int32_t xin, int32_t yin, int32_t * xout, int32_t * yout); -static void argb_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, - int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, - int32_t x_end, lv_color_t * cbuf, uint8_t * abuf); +static void transform_rgb888(const uint8_t * src, int32_t src_w, int32_t src_h, int32_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, uint8_t * dest_buf, bool aa, uint32_t px_size); -static void rgb_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, - int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, - int32_t x_end, lv_color_t * cbuf, uint8_t * abuf, lv_img_cf_t cf); +static void transform_argb8888(const uint8_t * src, int32_t src_w, int32_t src_h, int32_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, uint8_t * dest_buf, bool aa); -#if LV_COLOR_DEPTH == 16 -static void rgb565a8_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, - int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, - int32_t x_end, lv_color_t * cbuf, uint8_t * abuf); -#endif +static void transform_rgb565a8(const uint8_t * src, int32_t src_w, int32_t src_h, int32_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, uint16_t * cbuf, uint8_t * abuf, bool src_has_a8, bool aa); -static void argb_and_rgb_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, - int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, - int32_t x_end, lv_color_t * cbuf, uint8_t * abuf, lv_img_cf_t cf); +static void transform_a8(const uint8_t * src, int32_t src_w, int32_t src_h, int32_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, uint8_t * abuf, bool aa); /********************** * STATIC VARIABLES @@ -77,15 +79,17 @@ static void argb_and_rgb_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t sr * GLOBAL FUNCTIONS **********************/ -void lv_draw_sw_transform(lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, const void * src_buf, - lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, - const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf) +void lv_draw_sw_transform(lv_draw_unit_t * draw_unit, const lv_area_t * dest_area, const void * src_buf, + int32_t src_w, int32_t src_h, int32_t src_stride, + const lv_draw_image_dsc_t * draw_dsc, const lv_draw_image_sup_t * sup, lv_color_format_t src_cf, void * dest_buf) { - LV_UNUSED(draw_ctx); + LV_UNUSED(draw_unit); + LV_UNUSED(sup); point_transform_dsc_t tr_dsc; - tr_dsc.angle = -draw_dsc->angle; - tr_dsc.zoom = (256 * 256) / draw_dsc->zoom; + tr_dsc.angle = -draw_dsc->rotation; + tr_dsc.scale_x = (256 * 256) / draw_dsc->scale_x; + tr_dsc.scale_y = (256 * 256) / draw_dsc->scale_y; tr_dsc.pivot = draw_dsc->pivot; int32_t angle_low = tr_dsc.angle / 10; @@ -105,51 +109,131 @@ void lv_draw_sw_transform(lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, tr_dsc.pivot_x_256 = tr_dsc.pivot.x * 256; tr_dsc.pivot_y_256 = tr_dsc.pivot.y * 256; - lv_coord_t dest_w = lv_area_get_width(dest_area); - lv_coord_t dest_h = lv_area_get_height(dest_area); - lv_coord_t y; - for(y = 0; y < dest_h; y++) { + int32_t dest_w = lv_area_get_width(dest_area); + int32_t dest_h = lv_area_get_height(dest_area); + + int32_t dest_stride_a8 = dest_w; + int32_t dest_stride; + if(src_cf == LV_COLOR_FORMAT_RGB888) { + dest_stride = dest_w * lv_color_format_get_size(LV_COLOR_FORMAT_ARGB8888); + } + else if(src_cf == LV_COLOR_FORMAT_RGB565A8) { + dest_stride = dest_w * 2; + } + else { + dest_stride = dest_w * lv_color_format_get_size(src_cf); + } + + uint8_t * alpha_buf; + if(src_cf == LV_COLOR_FORMAT_RGB565 || src_cf == LV_COLOR_FORMAT_RGB565A8) { + alpha_buf = dest_buf; + alpha_buf += dest_stride * dest_h; + } + else { + alpha_buf = NULL; + } + + bool aa = draw_dsc->antialias; + bool is_rotated = draw_dsc->rotation; + + int32_t xs_ups = 0, ys_ups = 0, ys_ups_start = 0, ys_step_256_original = 0; + int32_t xs_step_256 = 0, ys_step_256 = 0; + + /*If scaled only make some simplification to avoid rounding errors. + *For example if there is a 100x100 image zoomed to 300% + *The destination area in X will be x1=0; x2=299 + *When the step is calculated below it will think that stepping + *1/3 pixels on the original image will result in 300% zoom. + *However this way the last pixel will be on the 99.67 coordinate. + *As it's larger than 99.5 LVGL will start to mix the next coordinate + *which is out of the image, so will make the pixel more transparent. + *To avoid it in case of scale only limit the coordinates to the 0..297 range, + *that is to 0..(src_w-1)*zoom */ + if(is_rotated == false) { int32_t xs1_ups, ys1_ups, xs2_ups, ys2_ups; - transform_point_upscaled(&tr_dsc, dest_area->x1, dest_area->y1 + y, &xs1_ups, &ys1_ups); - transform_point_upscaled(&tr_dsc, dest_area->x2, dest_area->y1 + y, &xs2_ups, &ys2_ups); + int32_t x_max = (((src_w - 1 - draw_dsc->pivot.x) * draw_dsc->scale_x) >> 8) + draw_dsc->pivot.x; + int32_t y_max = (((src_h - 1 - draw_dsc->pivot.y) * draw_dsc->scale_y) >> 8) + draw_dsc->pivot.y; + + lv_area_t dest_area_limited; + dest_area_limited.x1 = dest_area->x1 > x_max ? x_max : dest_area->x1; + dest_area_limited.x2 = dest_area->x2 > x_max ? x_max : dest_area->x2; + dest_area_limited.y1 = dest_area->y1 > y_max ? y_max : dest_area->y1; + dest_area_limited.y2 = dest_area->y2 > y_max ? y_max : dest_area->y2; + + transform_point_upscaled(&tr_dsc, dest_area_limited.x1, dest_area_limited.y1, &xs1_ups, &ys1_ups); + transform_point_upscaled(&tr_dsc, dest_area_limited.x2, dest_area_limited.y2, &xs2_ups, &ys2_ups); int32_t xs_diff = xs2_ups - xs1_ups; int32_t ys_diff = ys2_ups - ys1_ups; - int32_t xs_step_256 = 0; - int32_t ys_step_256 = 0; + xs_step_256 = 0; + ys_step_256_original = 0; if(dest_w > 1) { xs_step_256 = (256 * xs_diff) / (dest_w - 1); - ys_step_256 = (256 * ys_diff) / (dest_w - 1); } - int32_t xs_ups = xs1_ups + 0x80; - int32_t ys_ups = ys1_ups + 0x80; + if(dest_h > 1) { + ys_step_256_original = (256 * ys_diff) / (dest_h - 1); + } - if(draw_dsc->antialias == 0) { - switch(cf) { - case LV_IMG_CF_TRUE_COLOR_ALPHA: - argb_no_aa(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, cbuf, abuf); - break; - case LV_IMG_CF_TRUE_COLOR: - case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED: - rgb_no_aa(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, cbuf, abuf, cf); - break; + xs_ups = xs1_ups + 0x80; + ys_ups_start = ys1_ups + 0x80; + } -#if LV_COLOR_DEPTH == 16 - case LV_IMG_CF_RGB565A8: - rgb565a8_no_aa(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, cbuf, abuf); - break; -#endif - default: - break; - } + int32_t y; + for(y = 0; y < dest_h; y++) { + if(is_rotated == false) { + ys_ups = ys_ups_start + ((ys_step_256_original * y) >> 8); + ys_step_256 = 0; } else { - argb_and_rgb_aa(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, cbuf, abuf, cf); + int32_t xs1_ups, ys1_ups, xs2_ups, ys2_ups; + transform_point_upscaled(&tr_dsc, dest_area->x1, dest_area->y1 + y, &xs1_ups, &ys1_ups); + transform_point_upscaled(&tr_dsc, dest_area->x2, dest_area->y1 + y, &xs2_ups, &ys2_ups); + + int32_t xs_diff = xs2_ups - xs1_ups; + int32_t ys_diff = ys2_ups - ys1_ups; + xs_step_256 = 0; + ys_step_256 = 0; + if(dest_w > 1) { + xs_step_256 = (256 * xs_diff) / (dest_w - 1); + ys_step_256 = (256 * ys_diff) / (dest_w - 1); + } + + xs_ups = xs1_ups + 0x80; + ys_ups = ys1_ups + 0x80; } - cbuf += dest_w; - abuf += dest_w; + switch(src_cf) { + case LV_COLOR_FORMAT_XRGB8888: + transform_rgb888(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, dest_buf, aa, + 4); + break; + case LV_COLOR_FORMAT_RGB888: + transform_rgb888(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, dest_buf, aa, + 3); + break; + case LV_COLOR_FORMAT_A8: + transform_a8(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, dest_buf, aa); + break; + case LV_COLOR_FORMAT_ARGB8888: + transform_argb8888(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, dest_buf, + aa); + break; + case LV_COLOR_FORMAT_RGB565: + transform_rgb565a8(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, dest_buf, + alpha_buf, false, aa); + break; + case LV_COLOR_FORMAT_RGB565A8: + transform_rgb565a8(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, + (uint16_t *)dest_buf, + alpha_buf, true, aa); + break; + default: + break; + } + + dest_buf = (uint8_t *)dest_buf + dest_stride; + if(alpha_buf) alpha_buf += dest_stride_a8; } } @@ -157,150 +241,311 @@ void lv_draw_sw_transform(lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, * STATIC FUNCTIONS **********************/ -static void rgb_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, - int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, - int32_t x_end, lv_color_t * cbuf, uint8_t * abuf, lv_img_cf_t cf) +static void transform_rgb888(const uint8_t * src, int32_t src_w, int32_t src_h, int32_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, uint8_t * dest_buf, bool aa, uint32_t px_size) { int32_t xs_ups_start = xs_ups; int32_t ys_ups_start = ys_ups; - lv_disp_t * d = _lv_refr_get_disp_refreshing(); - lv_color_t ck = d->driver->color_chroma_key; + lv_color32_t * dest_c32 = (lv_color32_t *) dest_buf; - lv_memset_ff(abuf, x_end); - - lv_coord_t x; + int32_t x; for(x = 0; x < x_end; x++) { xs_ups = xs_ups_start + ((xs_step * x) >> 8); ys_ups = ys_ups_start + ((ys_step * x) >> 8); int32_t xs_int = xs_ups >> 8; int32_t ys_int = ys_ups >> 8; + + /*Fully out of the image*/ if(xs_int < 0 || xs_int >= src_w || ys_int < 0 || ys_int >= src_h) { - abuf[x] = 0x00; + dest_c32[x].alpha = 0x00; + continue; + } + + /*Get the direction the hor and ver neighbor + *`fract` will be in range of 0x00..0xFF and `next` (+/-1) indicates the direction*/ + int32_t xs_fract = xs_ups & 0xFF; + int32_t ys_fract = ys_ups & 0xFF; + + int32_t x_next; + int32_t y_next; + if(xs_fract < 0x80) { + x_next = -1; + xs_fract = 0x7F - xs_fract; } else { - -#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8 - const uint8_t * src_tmp = src; - src_tmp += ys_int * src_stride + xs_int; - cbuf[x].full = src_tmp[0]; -#elif LV_COLOR_DEPTH == 16 - const lv_color_t * src_tmp = (const lv_color_t *)src; - src_tmp += ys_int * src_stride + xs_int; - cbuf[x] = *src_tmp; -#elif LV_COLOR_DEPTH == 32 - const uint8_t * src_tmp = src; - src_tmp += (ys_int * src_stride * sizeof(lv_color_t)) + xs_int * sizeof(lv_color_t); - cbuf[x].full = *((uint32_t *)src_tmp); -#endif + x_next = 1; + xs_fract = xs_fract - 0x80; } - if(cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED && cbuf[x].full == ck.full) { - abuf[x] = 0x00; - } - } -} - -static void argb_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, - int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, - int32_t x_end, lv_color_t * cbuf, uint8_t * abuf) -{ - int32_t xs_ups_start = xs_ups; - int32_t ys_ups_start = ys_ups; - - lv_coord_t x; - for(x = 0; x < x_end; x++) { - xs_ups = xs_ups_start + ((xs_step * x) >> 8); - ys_ups = ys_ups_start + ((ys_step * x) >> 8); - - int32_t xs_int = xs_ups >> 8; - int32_t ys_int = ys_ups >> 8; - if(xs_int < 0 || xs_int >= src_w || ys_int < 0 || ys_int >= src_h) { - abuf[x] = 0; + if(ys_fract < 0x80) { + y_next = -1; + ys_fract = 0x7F - ys_fract; } else { - const uint8_t * src_tmp = src; - src_tmp += (ys_int * src_stride * LV_IMG_PX_SIZE_ALPHA_BYTE) + xs_int * LV_IMG_PX_SIZE_ALPHA_BYTE; - -#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8 - cbuf[x].full = src_tmp[0]; -#elif LV_COLOR_DEPTH == 16 - cbuf[x].full = src_tmp[0] + (src_tmp[1] << 8); -#elif LV_COLOR_DEPTH == 32 - cbuf[x].full = *((uint32_t *)src_tmp); -#endif - abuf[x] = src_tmp[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; + y_next = 1; + ys_fract = ys_fract - 0x80; } - } -} -#if LV_COLOR_DEPTH == 16 -static void rgb565a8_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, - int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, - int32_t x_end, lv_color_t * cbuf, uint8_t * abuf) -{ - int32_t xs_ups_start = xs_ups; - int32_t ys_ups_start = ys_ups; + const uint8_t * src_u8 = &src[ys_int * src_stride + xs_int * px_size]; - lv_coord_t x; - for(x = 0; x < x_end; x++) { - xs_ups = xs_ups_start + ((xs_step * x) >> 8); - ys_ups = ys_ups_start + ((ys_step * x) >> 8); + dest_c32[x].red = src_u8[2]; + dest_c32[x].green = src_u8[1]; + dest_c32[x].blue = src_u8[0]; + dest_c32[x].alpha = 0xff; - int32_t xs_int = xs_ups >> 8; - int32_t ys_int = ys_ups >> 8; - if(xs_int < 0 || xs_int >= src_w || ys_int < 0 || ys_int >= src_h) { - abuf[x] = 0; - } - else { - const lv_color_t * src_tmp = (const lv_color_t *)src; - src_tmp += ys_int * src_stride + xs_int; - cbuf[x] = *src_tmp; + if(aa && + xs_int + x_next >= 0 && + xs_int + x_next <= src_w - 1 && + ys_int + y_next >= 0 && + ys_int + y_next <= src_h - 1) { + const uint8_t * px_hor_u8 = src_u8 + (int32_t)(x_next * px_size); + lv_color32_t px_hor; + px_hor.red = px_hor_u8[2]; + px_hor.green = px_hor_u8[1]; + px_hor.blue = px_hor_u8[0]; + px_hor.alpha = 0xff; - const lv_opa_t * a_tmp = src + src_stride * src_h * sizeof(lv_color_t); - a_tmp += ys_int * src_stride + xs_int; - abuf[x] = *a_tmp; - } - } -} -#endif + const uint8_t * px_ver_u8 = src_u8 + (int32_t)(y_next * src_stride); + lv_color32_t px_ver; + px_ver.red = px_ver_u8[2]; + px_ver.green = px_ver_u8[1]; + px_ver.blue = px_ver_u8[0]; + px_ver.alpha = 0xff; - -static void argb_and_rgb_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, - int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, - int32_t x_end, lv_color_t * cbuf, uint8_t * abuf, lv_img_cf_t cf) -{ - int32_t xs_ups_start = xs_ups; - int32_t ys_ups_start = ys_ups; - bool has_alpha; - int32_t px_size; - lv_color_t ck = _LV_COLOR_ZERO_INITIALIZER; - switch(cf) { - case LV_IMG_CF_TRUE_COLOR: - has_alpha = false; - px_size = sizeof(lv_color_t); - break; - case LV_IMG_CF_TRUE_COLOR_ALPHA: - has_alpha = true; - px_size = LV_IMG_PX_SIZE_ALPHA_BYTE; - break; - case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED: { - has_alpha = true; - px_size = sizeof(lv_color_t); - lv_disp_t * d = _lv_refr_get_disp_refreshing(); - ck = d->driver->color_chroma_key; - break; + if(!lv_color32_eq(dest_c32[x], px_ver)) { + px_ver.alpha = ys_fract; + dest_c32[x] = lv_color_mix32(px_ver, dest_c32[x]); } -#if LV_COLOR_DEPTH == 16 - case LV_IMG_CF_RGB565A8: - has_alpha = true; - px_size = sizeof(lv_color_t); - break; -#endif - default: - return; - } - lv_coord_t x; + if(!lv_color32_eq(dest_c32[x], px_hor)) { + px_hor.alpha = xs_fract; + dest_c32[x] = lv_color_mix32(px_hor, dest_c32[x]); + } + } + /*Partially out of the image*/ + else { + lv_opa_t a = 0xff; + + if((xs_int == 0 && x_next < 0) || (xs_int == src_w - 1 && x_next > 0)) { + dest_c32[x].alpha = (a * (0xFF - xs_fract)) >> 8; + } + else if((ys_int == 0 && y_next < 0) || (ys_int == src_h - 1 && y_next > 0)) { + dest_c32[x].alpha = (a * (0xFF - ys_fract)) >> 8; + } + } + } +} + +static void transform_argb8888(const uint8_t * src, int32_t src_w, int32_t src_h, int32_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, uint8_t * dest_buf, bool aa) +{ + // lv_memzero(dest_buf, x_end * 4); + int32_t xs_ups_start = xs_ups; + int32_t ys_ups_start = ys_ups; + lv_color32_t * dest_c32 = (lv_color32_t *) dest_buf; + + int32_t x; + for(x = 0; x < x_end; x++) { + xs_ups = xs_ups_start + ((xs_step * x) >> 8); + ys_ups = ys_ups_start + ((ys_step * x) >> 8); + + int32_t xs_int = xs_ups >> 8; + int32_t ys_int = ys_ups >> 8; + + /*Fully out of the image*/ + if(xs_int < 0 || xs_int >= src_w || ys_int < 0 || ys_int >= src_h) { + ((uint32_t *)dest_buf)[x] = 0x00000000; + continue; + } + + /*Get the direction the hor and ver neighbor + *`fract` will be in range of 0x00..0xFF and `next` (+/-1) indicates the direction*/ + int32_t xs_fract = xs_ups & 0xFF; + int32_t ys_fract = ys_ups & 0xFF; + + int32_t x_next; + int32_t y_next; + if(xs_fract < 0x80) { + x_next = -1; + xs_fract = 0x7F - xs_fract; + } + else { + x_next = 1; + xs_fract = xs_fract - 0x80; + } + if(ys_fract < 0x80) { + y_next = -1; + ys_fract = 0x7F - ys_fract; + } + else { + y_next = 1; + ys_fract = ys_fract - 0x80; + } + + const lv_color32_t * src_c32 = (const lv_color32_t *)src; + src_c32 += (ys_int * src_stride) + xs_int; + + src_c32 = (const lv_color32_t *)(src + ys_int * src_stride + xs_int * 4); + + dest_c32[x] = src_c32[0]; + + if(aa && + xs_int + x_next >= 0 && + xs_int + x_next <= src_w - 1 && + ys_int + y_next >= 0 && + ys_int + y_next <= src_h - 1) { + + lv_color32_t px_hor = src_c32[x_next]; + lv_color32_t px_ver = *(const lv_color32_t *)((uint8_t *)src_c32 + y_next * src_stride); + + if(px_ver.alpha == 0) { + dest_c32[x].alpha = (dest_c32[x].alpha * (0xFF - ys_fract)) >> 8; + } + else if(!lv_color32_eq(dest_c32[x], px_ver)) { + dest_c32[x].alpha = ((px_ver.alpha * ys_fract) + (dest_c32[x].alpha * (0xFF - ys_fract))) >> 8; + px_ver.alpha = ys_fract; + dest_c32[x] = lv_color_mix32(px_ver, dest_c32[x]); + } + + if(px_hor.alpha == 0) { + dest_c32[x].alpha = (dest_c32[x].alpha * (0xFF - xs_fract)) >> 8; + } + else if(!lv_color32_eq(dest_c32[x], px_hor)) { + dest_c32[x].alpha = ((px_hor.alpha * xs_fract) + (dest_c32[x].alpha * (0xFF - xs_fract))) >> 8; + px_hor.alpha = xs_fract; + dest_c32[x] = lv_color_mix32(px_hor, dest_c32[x]); + } + } + /*Partially out of the image*/ + else { + if((xs_int == 0 && x_next < 0) || (xs_int == src_w - 1 && x_next > 0)) { + dest_c32[x].alpha = (dest_c32[x].alpha * (0x7F - xs_fract)) >> 7; + } + else if((ys_int == 0 && y_next < 0) || (ys_int == src_h - 1 && y_next > 0)) { + dest_c32[x].alpha = (dest_c32[x].alpha * (0x7F - ys_fract)) >> 7; + } + } + } +} + +static void transform_rgb565a8(const uint8_t * src, int32_t src_w, int32_t src_h, int32_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, uint16_t * cbuf, uint8_t * abuf, bool src_has_a8, bool aa) +{ + int32_t xs_ups_start = xs_ups; + int32_t ys_ups_start = ys_ups; + + const lv_opa_t * src_alpha = src + src_stride * src_h; + + /*Must be signed type, because we would use negative array index calculated from stride*/ + int32_t alpha_stride = src_stride / 2; /*alpha map stride is always half of RGB map stride*/ + + int32_t x; + for(x = 0; x < x_end; x++) { + xs_ups = xs_ups_start + ((xs_step * x) >> 8); + ys_ups = ys_ups_start + ((ys_step * x) >> 8); + + int32_t xs_int = xs_ups >> 8; + int32_t ys_int = ys_ups >> 8; + + /*Fully out of the image*/ + if(xs_int < 0 || xs_int >= src_w || ys_int < 0 || ys_int >= src_h) { + abuf[x] = 0x00; + continue; + } + + /*Get the direction the hor and ver neighbor + *`fract` will be in range of 0x00..0xFF and `next` (+/-1) indicates the direction*/ + int32_t xs_fract = xs_ups & 0xFF; + int32_t ys_fract = ys_ups & 0xFF; + + int32_t x_next; + int32_t y_next; + if(xs_fract < 0x80) { + x_next = -1; + xs_fract = (0x7F - xs_fract) * 2; + } + else { + x_next = 1; + xs_fract = (xs_fract - 0x80) * 2; + } + if(ys_fract < 0x80) { + y_next = -1; + ys_fract = (0x7F - ys_fract) * 2; + } + else { + y_next = 1; + ys_fract = (ys_fract - 0x80) * 2; + } + + const uint16_t * src_tmp_u16 = (const uint16_t *)(src + (ys_int * src_stride) + xs_int * 2); + cbuf[x] = src_tmp_u16[0]; + + if(aa && + xs_int + x_next >= 0 && + xs_int + x_next <= src_w - 1 && + ys_int + y_next >= 0 && + ys_int + y_next <= src_h - 1) { + + uint16_t px_hor = src_tmp_u16[x_next]; + uint16_t px_ver = *(const uint16_t *)((uint8_t *)src_tmp_u16 + (y_next * src_stride)); + + if(src_has_a8) { + const lv_opa_t * src_alpha_tmp = src_alpha; + src_alpha_tmp += (ys_int * alpha_stride) + xs_int; + abuf[x] = src_alpha_tmp[0]; + + lv_opa_t a_hor = src_alpha_tmp[x_next]; + lv_opa_t a_ver = src_alpha_tmp[y_next * alpha_stride]; + + if(a_ver != abuf[x]) a_ver = ((a_ver * ys_fract) + (abuf[x] * (0x100 - ys_fract))) >> 8; + if(a_hor != abuf[x]) a_hor = ((a_hor * xs_fract) + (abuf[x] * (0x100 - xs_fract))) >> 8; + abuf[x] = (a_ver + a_hor) >> 1; + + if(abuf[x] == 0x00) continue; + } + else { + abuf[x] = 0xff; + } + + if(cbuf[x] != px_ver || cbuf[x] != px_hor) { + uint16_t v = lv_color_16_16_mix(px_ver, cbuf[x], ys_fract); + uint16_t h = lv_color_16_16_mix(px_hor, cbuf[x], xs_fract); + cbuf[x] = lv_color_16_16_mix(h, v, LV_OPA_50); + } + } + /*Partially out of the image*/ + else { + lv_opa_t a; + if(src_has_a8) { + const lv_opa_t * src_alpha_tmp = src_alpha; + src_alpha_tmp += (ys_int * alpha_stride) + xs_int; + a = src_alpha_tmp[0]; + } + else { + a = 0xff; + } + + if((xs_int == 0 && x_next < 0) || (xs_int == src_w - 1 && x_next > 0)) { + abuf[x] = (a * (0xFF - xs_fract)) >> 8; + } + else if((ys_int == 0 && y_next < 0) || (ys_int == src_h - 1 && y_next > 0)) { + abuf[x] = (a * (0xFF - ys_fract)) >> 8; + } + } + } +} + +static void transform_a8(const uint8_t * src, int32_t src_w, int32_t src_h, int32_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, uint8_t * abuf, bool aa) +{ + int32_t xs_ups_start = xs_ups; + int32_t ys_ups_start = ys_ups; + + int32_t x; for(x = 0; x < x_end; x++) { xs_ups = xs_ups_start + ((xs_step * x) >> 8); ys_ups = ys_ups_start + ((ys_step * x) >> 8); @@ -339,128 +584,29 @@ static void argb_and_rgb_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t sr } const uint8_t * src_tmp = src; - src_tmp += (ys_int * src_stride * px_size) + xs_int * px_size; + src_tmp += ys_int * src_stride + xs_int; + abuf[x] = src_tmp[0]; - - if(xs_int + x_next >= 0 && + if(aa && + xs_int + x_next >= 0 && xs_int + x_next <= src_w - 1 && ys_int + y_next >= 0 && ys_int + y_next <= src_h - 1) { - const uint8_t * px_base = src_tmp; - const uint8_t * px_hor = src_tmp + x_next * px_size; - const uint8_t * px_ver = src_tmp + y_next * src_stride * px_size; - lv_color_t c_base; - lv_color_t c_ver; - lv_color_t c_hor; + lv_opa_t a_ver = src_tmp[x_next]; + lv_opa_t a_hor = src_tmp[y_next * src_stride]; - if(has_alpha) { - lv_opa_t a_base; - lv_opa_t a_ver; - lv_opa_t a_hor; - if(cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { - a_base = px_base[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; - a_ver = px_ver[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; - a_hor = px_hor[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; - } -#if LV_COLOR_DEPTH == 16 - else if(cf == LV_IMG_CF_RGB565A8) { - const lv_opa_t * a_tmp = src + src_stride * src_h * sizeof(lv_color_t); - a_base = *(a_tmp + (ys_int * src_stride) + xs_int); - a_hor = *(a_tmp + (ys_int * src_stride) + xs_int + x_next); - a_ver = *(a_tmp + ((ys_int + y_next) * src_stride) + xs_int); - } -#endif - else if(cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { - if(((lv_color_t *)px_base)->full == ck.full || - ((lv_color_t *)px_ver)->full == ck.full || - ((lv_color_t *)px_hor)->full == ck.full) { - abuf[x] = 0x00; - continue; - } - else { - a_base = 0xff; - a_ver = 0xff; - a_hor = 0xff; - } - } - else { - a_base = 0xff; - a_ver = 0xff; - a_hor = 0xff; - } - - if(a_ver != a_base) a_ver = ((a_ver * ys_fract) + (a_base * (0x100 - ys_fract))) >> 8; - if(a_hor != a_base) a_hor = ((a_hor * xs_fract) + (a_base * (0x100 - xs_fract))) >> 8; - abuf[x] = (a_ver + a_hor) >> 1; - - if(abuf[x] == 0x00) continue; - -#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8 - c_base.full = px_base[0]; - c_ver.full = px_ver[0]; - c_hor.full = px_hor[0]; -#elif LV_COLOR_DEPTH == 16 - c_base.full = px_base[0] + (px_base[1] << 8); - c_ver.full = px_ver[0] + (px_ver[1] << 8); - c_hor.full = px_hor[0] + (px_hor[1] << 8); -#elif LV_COLOR_DEPTH == 32 - c_base.full = *((uint32_t *)px_base); - c_ver.full = *((uint32_t *)px_ver); - c_hor.full = *((uint32_t *)px_hor); -#endif - } - /*No alpha channel -> RGB*/ - else { - c_base = *((const lv_color_t *) px_base); - c_hor = *((const lv_color_t *) px_hor); - c_ver = *((const lv_color_t *) px_ver); - abuf[x] = 0xff; - } - - if(c_base.full == c_ver.full && c_base.full == c_hor.full) { - cbuf[x] = c_base; - } - else { - c_ver = lv_color_mix(c_ver, c_base, ys_fract); - c_hor = lv_color_mix(c_hor, c_base, xs_fract); - cbuf[x] = lv_color_mix(c_hor, c_ver, LV_OPA_50); - } + if(a_ver != abuf[x]) a_ver = ((a_ver * ys_fract) + (abuf[x] * (0x100 - ys_fract))) >> 8; + if(a_hor != abuf[x]) a_hor = ((a_hor * xs_fract) + (abuf[x] * (0x100 - xs_fract))) >> 8; + abuf[x] = (a_ver + a_hor) >> 1; } - /*Partially out of the image*/ else { -#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8 - cbuf[x].full = src_tmp[0]; -#elif LV_COLOR_DEPTH == 16 - cbuf[x].full = src_tmp[0] + (src_tmp[1] << 8); -#elif LV_COLOR_DEPTH == 32 - cbuf[x].full = *((uint32_t *)src_tmp); -#endif - lv_opa_t a; - switch(cf) { - case LV_IMG_CF_TRUE_COLOR_ALPHA: - a = src_tmp[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; - break; - case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED: - a = cbuf[x].full == ck.full ? 0x00 : 0xff; - break; -#if LV_COLOR_DEPTH == 16 - case LV_IMG_CF_RGB565A8: - a = *(src + src_stride * src_h * sizeof(lv_color_t) + (ys_int * src_stride) + xs_int); - break; -#endif - default: - a = 0xff; - } - + /*Partially out of the image*/ if((xs_int == 0 && x_next < 0) || (xs_int == src_w - 1 && x_next > 0)) { - abuf[x] = (a * (0xFF - xs_fract)) >> 8; + abuf[x] = (src_tmp[0] * (0xFF - xs_fract)) >> 8; } else if((ys_int == 0 && y_next < 0) || (ys_int == src_h - 1 && y_next > 0)) { - abuf[x] = (a * (0xFF - ys_fract)) >> 8; - } - else { - abuf[x] = 0x00; + abuf[x] = (src_tmp[0] * (0xFF - ys_fract)) >> 8; } } } @@ -469,7 +615,7 @@ static void argb_and_rgb_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t sr static void transform_point_upscaled(point_transform_dsc_t * t, int32_t xin, int32_t yin, int32_t * xout, int32_t * yout) { - if(t->angle == 0 && t->zoom == LV_IMG_ZOOM_NONE) { + if(t->angle == 0 && t->scale_x == LV_SCALE_NONE && t->scale_y == LV_SCALE_NONE) { *xout = xin * 256; *yout = yin * 256; return; @@ -479,18 +625,17 @@ static void transform_point_upscaled(point_transform_dsc_t * t, int32_t xin, int yin -= t->pivot.y; if(t->angle == 0) { - *xout = ((int32_t)(xin * t->zoom)) + (t->pivot_x_256); - *yout = ((int32_t)(yin * t->zoom)) + (t->pivot_y_256); + *xout = ((int32_t)(xin * t->scale_x)) + (t->pivot_x_256); + *yout = ((int32_t)(yin * t->scale_y)) + (t->pivot_y_256); } - else if(t->zoom == LV_IMG_ZOOM_NONE) { + else if(t->scale_x == LV_SCALE_NONE && t->scale_y == LV_SCALE_NONE) { *xout = ((t->cosma * xin - t->sinma * yin) >> 2) + (t->pivot_x_256); *yout = ((t->sinma * xin + t->cosma * yin) >> 2) + (t->pivot_y_256); } else { - *xout = (((t->cosma * xin - t->sinma * yin) * t->zoom) >> 10) + (t->pivot_x_256); - *yout = (((t->sinma * xin + t->cosma * yin) * t->zoom) >> 10) + (t->pivot_y_256); + *xout = (((t->cosma * xin - t->sinma * yin) * t->scale_x) >> 10) + (t->pivot_x_256); + *yout = (((t->sinma * xin + t->cosma * yin) * t->scale_y) >> 10) + (t->pivot_y_256); } } -#endif - +#endif /*LV_USE_DRAW_SW*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_triangle.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_triangle.c new file mode 100644 index 000000000..311325b3d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_triangle.c @@ -0,0 +1,197 @@ +/** + * @file lv_draw_sw_triangle.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_sw.h" +#if LV_USE_DRAW_SW + +#include "../../misc/lv_math.h" +#include "../../stdlib/lv_mem.h" +#include "../../misc/lv_area.h" +#include "../../misc/lv_color.h" +#include "../../stdlib/lv_string.h" +#include "../lv_draw_triangle.h" +#include "lv_draw_sw_gradient.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_sw_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc) +{ +#if LV_DRAW_SW_COMPLEX + lv_area_t tri_area; + tri_area.x1 = (int32_t)LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + tri_area.y1 = (int32_t)LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); + tri_area.x2 = (int32_t)LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + tri_area.y2 = (int32_t)LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); + + bool is_common; + lv_area_t draw_area; + is_common = _lv_area_intersect(&draw_area, &tri_area, draw_unit->clip_area); + if(!is_common) return; + + lv_point_t p[3]; + /*If there is a vertical side use it as p[0] and p[1]*/ + if(dsc->p[0].x == dsc->p[1].x) { + p[0] = lv_point_from_precise(&dsc->p[0]); + p[1] = lv_point_from_precise(&dsc->p[1]); + p[2] = lv_point_from_precise(&dsc->p[2]); + } + else if(dsc->p[0].x == dsc->p[2].x) { + p[0] = lv_point_from_precise(&dsc->p[0]); + p[1] = lv_point_from_precise(&dsc->p[2]); + p[2] = lv_point_from_precise(&dsc->p[1]); + } + else if(dsc->p[1].x == dsc->p[2].x) { + p[0] = lv_point_from_precise(&dsc->p[1]); + p[1] = lv_point_from_precise(&dsc->p[2]); + p[2] = lv_point_from_precise(&dsc->p[0]); + } + else { + p[0] = lv_point_from_precise(&dsc->p[0]); + p[1] = lv_point_from_precise(&dsc->p[1]); + p[2] = lv_point_from_precise(&dsc->p[2]); + + /*Set the smallest y as p[0]*/ + if(p[0].y > p[1].y) lv_point_swap(&p[0], &p[1]); + if(p[0].y > p[2].y) lv_point_swap(&p[0], &p[2]); + + /*Set the greatest y as p[1]*/ + if(p[1].y < p[2].y) lv_point_swap(&p[1], &p[2]); + } + + /*Be sure p[0] is on the top*/ + if(p[0].y > p[1].y) lv_point_swap(&p[0], &p[1]); + + /*If right == true p[2] is on the right side of the p[0] p[1] line*/ + bool right = ((p[1].x - p[0].x) * (p[2].y - p[0].y) - (p[1].y - p[0].y) * (p[2].x - p[0].x)) < 0; + + void * masks[4] = {0}; + lv_draw_sw_mask_line_param_t mask_left; + lv_draw_sw_mask_line_param_t mask_right; + lv_draw_sw_mask_line_param_t mask_bottom; + + lv_draw_sw_mask_line_points_init(&mask_left, p[0].x, p[0].y, + p[1].x, p[1].y, + right ? LV_DRAW_SW_MASK_LINE_SIDE_RIGHT : LV_DRAW_SW_MASK_LINE_SIDE_LEFT); + + lv_draw_sw_mask_line_points_init(&mask_right, p[0].x, p[0].y, + p[2].x, p[2].y, + right ? LV_DRAW_SW_MASK_LINE_SIDE_LEFT : LV_DRAW_SW_MASK_LINE_SIDE_RIGHT); + + if(p[1].y == p[2].y) { + lv_draw_sw_mask_line_points_init(&mask_bottom, p[1].x, p[1].y, + p[2].x, p[2].y, LV_DRAW_SW_MASK_LINE_SIDE_TOP); + } + else { + lv_draw_sw_mask_line_points_init(&mask_bottom, p[1].x, p[1].y, + p[2].x, p[2].y, + right ? LV_DRAW_SW_MASK_LINE_SIDE_LEFT : LV_DRAW_SW_MASK_LINE_SIDE_RIGHT); + } + + masks[0] = &mask_left; + masks[1] = &mask_right; + masks[2] = &mask_bottom; + int32_t area_w = lv_area_get_width(&draw_area); + lv_opa_t * mask_buf = lv_malloc(area_w); + + lv_area_t blend_area = draw_area; + blend_area.y2 = blend_area.y1; + lv_draw_sw_blend_dsc_t blend_dsc; + blend_dsc.color = dsc->bg_color; + blend_dsc.opa = dsc->bg_opa; + blend_dsc.mask_buf = mask_buf; + blend_dsc.blend_area = &blend_area; + blend_dsc.mask_area = &blend_area; + blend_dsc.blend_mode = LV_BLEND_MODE_NORMAL; + blend_dsc.src_buf = NULL; + + lv_grad_dir_t grad_dir = dsc->bg_grad.dir; + + lv_grad_t * grad = lv_gradient_get(&dsc->bg_grad, lv_area_get_width(&tri_area), lv_area_get_height(&tri_area)); + lv_opa_t * grad_opa_map = NULL; + if(grad && grad_dir == LV_GRAD_DIR_HOR) { + blend_dsc.src_area = &blend_area; + blend_dsc.src_buf = grad->color_map + draw_area.x1 - tri_area.x1; + grad_opa_map = grad->opa_map + draw_area.x1 - tri_area.x1; + blend_dsc.src_color_format = LV_COLOR_FORMAT_RGB888; + } + + int32_t y; + for(y = draw_area.y1; y <= draw_area.y2; y++) { + blend_area.y1 = y; + blend_area.y2 = y; + lv_memset(mask_buf, 0xff, area_w); + blend_dsc.mask_res = lv_draw_sw_mask_apply(masks, mask_buf, draw_area.x1, y, area_w); + if(grad_dir == LV_GRAD_DIR_VER) { + blend_dsc.color = grad->color_map[y - tri_area.y1]; + blend_dsc.opa = grad->opa_map[y - tri_area.y1]; + if(dsc->bg_opa < LV_OPA_MAX) blend_dsc.opa = LV_OPA_MIX2(blend_dsc.opa, dsc->bg_opa); + } + else if(grad_dir == LV_GRAD_DIR_HOR) { + if(grad_opa_map) { + int32_t i; + if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_CHANGED) { + blend_dsc.mask_buf = mask_buf; + for(i = 0; i < area_w; i++) { + if(grad_opa_map[i] < LV_OPA_MAX) mask_buf[i] = LV_OPA_MIX2(mask_buf[i], grad_opa_map[i]); + } + } + else if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_FULL_COVER) { + blend_dsc.mask_buf = grad_opa_map; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + } + else if(blend_dsc.mask_res == LV_DRAW_SW_MASK_RES_TRANSP) { + continue; + } + } + } + lv_draw_sw_blend(draw_unit, &blend_dsc); + } + + lv_free(mask_buf); + lv_draw_sw_mask_free_param(&mask_bottom); + lv_draw_sw_mask_free_param(&mask_left); + lv_draw_sw_mask_free_param(&mask_right); + + if(grad) { + lv_gradient_cleanup(grad); + } + +#else + LV_UNUSED(draw_unit); + LV_UNUSED(dsc); + LV_LOG_WARN("Can't draw triangles with LV_DRAW_SW_COMPLEX == 0"); +#endif /*LV_DRAW_SW_COMPLEX*/ +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_SW*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_vector.c b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_vector.c new file mode 100644 index 000000000..bd20df39c --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_vector.c @@ -0,0 +1,464 @@ +/** + * @file lv_draw_img.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_sw.h" + +#if LV_USE_VECTOR_GRAPHIC && (LV_USE_THORVG_EXTERNAL || LV_USE_THORVG_INTERNAL) +#if LV_USE_THORVG_EXTERNAL + #include +#else + #include "../../libs/thorvg/thorvg_capi.h" +#endif +#include "../../stdlib/lv_string.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + float x; + float y; + float w; + float h; +} _tvg_rect; + +typedef struct { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; +} _tvg_color; + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +static void _lv_area_to_tvg(_tvg_rect * rect, const lv_area_t * area) +{ + rect->x = area->x1; + rect->y = area->y1; + rect->w = lv_area_get_width(area); + rect->h = lv_area_get_height(area); +} + +static void _lv_color_to_tvg(_tvg_color * color, const lv_color32_t * c, lv_opa_t opa) +{ + color->r = c->red; + color->g = c->green; + color->b = c->blue; + color->a = LV_OPA_MIX2(c->alpha, opa); +} + +static void _lv_matrix_to_tvg(Tvg_Matrix * tm, const lv_matrix_t * m) +{ + tm->e11 = m->m[0][0]; + tm->e12 = m->m[0][1]; + tm->e13 = m->m[0][2]; + tm->e21 = m->m[1][0]; + tm->e22 = m->m[1][1]; + tm->e23 = m->m[1][2]; + tm->e31 = m->m[2][0]; + tm->e32 = m->m[2][1]; + tm->e33 = m->m[2][2]; +} + +static void _set_paint_matrix(Tvg_Paint * obj, const Tvg_Matrix * m) +{ + tvg_paint_set_transform(obj, m); +} + +static void _set_paint_shape(Tvg_Paint * obj, const lv_vector_path_t * p) +{ + uint32_t pidx = 0; + for(uint32_t i = 0; i < p->ops.size; i++) { + lv_vector_path_op_t * op = lv_array_at(&p->ops, i); + switch(*op) { + case LV_VECTOR_PATH_OP_MOVE_TO: { + lv_fpoint_t * pt = lv_array_at(&p->points, pidx); + tvg_shape_move_to(obj, pt->x, pt->y); + pidx += 1; + } + break; + case LV_VECTOR_PATH_OP_LINE_TO: { + lv_fpoint_t * pt = lv_array_at(&p->points, pidx); + tvg_shape_line_to(obj, pt->x, pt->y); + pidx += 1; + } + break; + case LV_VECTOR_PATH_OP_QUAD_TO: { + lv_fpoint_t * pt1 = lv_array_at(&p->points, pidx); + lv_fpoint_t * pt2 = lv_array_at(&p->points, pidx + 1); + + lv_fpoint_t * last_pt = lv_array_at(&p->points, pidx - 1); + + lv_fpoint_t cp[2]; + cp[0].x = (last_pt->x + 2 * pt1->x) * (1.0f / 3.0f); + cp[0].y = (last_pt->y + 2 * pt1->y) * (1.0f / 3.0f); + cp[1].x = (pt2->x + 2 * pt1->x) * (1.0f / 3.0f); + cp[1].y = (pt2->y + 2 * pt1->y) * (1.0f / 3.0f); + + tvg_shape_cubic_to(obj, cp[0].x, cp[0].y, cp[1].x, cp[1].y, pt2->x, pt2->y); + pidx += 2; + } + break; + case LV_VECTOR_PATH_OP_CUBIC_TO: { + lv_fpoint_t * pt1 = lv_array_at(&p->points, pidx); + lv_fpoint_t * pt2 = lv_array_at(&p->points, pidx + 1); + lv_fpoint_t * pt3 = lv_array_at(&p->points, pidx + 2); + + tvg_shape_cubic_to(obj, pt1->x, pt1->y, pt2->x, pt2->y, pt3->x, pt3->y); + pidx += 3; + } + break; + case LV_VECTOR_PATH_OP_CLOSE: { + tvg_shape_close(obj); + } + break; + } + } +} + +static Tvg_Stroke_Cap _lv_stroke_cap_to_tvg(lv_vector_stroke_cap_t cap) +{ + switch(cap) { + case LV_VECTOR_STROKE_CAP_SQUARE: + return TVG_STROKE_CAP_SQUARE; + case LV_VECTOR_STROKE_CAP_ROUND: + return TVG_STROKE_CAP_ROUND; + case LV_VECTOR_STROKE_CAP_BUTT: + return TVG_STROKE_CAP_BUTT; + default: + return TVG_STROKE_CAP_SQUARE; + } +} + +static Tvg_Stroke_Join _lv_stroke_join_to_tvg(lv_vector_stroke_join_t join) +{ + switch(join) { + case LV_VECTOR_STROKE_JOIN_BEVEL: + return TVG_STROKE_JOIN_BEVEL; + case LV_VECTOR_STROKE_JOIN_ROUND: + return TVG_STROKE_JOIN_ROUND; + case LV_VECTOR_STROKE_JOIN_MITER: + return TVG_STROKE_JOIN_MITER; + default: + return TVG_STROKE_JOIN_BEVEL; + } +} + +static Tvg_Stroke_Fill _lv_spread_to_tvg(lv_vector_gradient_spread_t sp) +{ + switch(sp) { + case LV_VECTOR_GRADIENT_SPREAD_PAD: + return TVG_STROKE_FILL_PAD; + case LV_VECTOR_GRADIENT_SPREAD_REPEAT: + return TVG_STROKE_FILL_REPEAT; + case LV_VECTOR_GRADIENT_SPREAD_REFLECT: + return TVG_STROKE_FILL_REFLECT; + default: + return TVG_STROKE_FILL_PAD; + } +} + +static void _setup_gradient(Tvg_Gradient * gradient, const lv_vector_gradient_t * grad, + const lv_matrix_t * matrix) +{ + const lv_grad_dsc_t * g = &grad->grad; + Tvg_Color_Stop * stops = (Tvg_Color_Stop *)lv_malloc(sizeof(Tvg_Color_Stop) * g->stops_count); + for(uint8_t i = 0; i < g->stops_count; i++) { + const lv_gradient_stop_t * s = &(g->stops[i]); + + stops[i].offset = s->frac / 255.0f; + stops[i].r = s->color.red; + stops[i].g = s->color.green; + stops[i].b = s->color.blue; + stops[i].a = s->opa; + } + + tvg_gradient_set_color_stops(gradient, stops, g->stops_count); + tvg_gradient_set_spread(gradient, _lv_spread_to_tvg(grad->spread)); + Tvg_Matrix mtx; + _lv_matrix_to_tvg(&mtx, matrix); + tvg_gradient_set_transform(gradient, &mtx); + lv_free(stops); +} + +static void _set_paint_stroke_gradient(Tvg_Paint * obj, const lv_vector_gradient_t * g, const lv_matrix_t * m) +{ + float x, y, w, h; + tvg_paint_get_bounds(obj, &x, &y, &w, &h, false); + + Tvg_Gradient * grad = NULL; + if(g->style == LV_VECTOR_GRADIENT_STYLE_RADIAL) { + grad = tvg_radial_gradient_new(); + tvg_radial_gradient_set(grad, g->cx + x, g->cy + y, g->cr); + _setup_gradient(grad, g, m); + tvg_shape_set_stroke_radial_gradient(obj, grad); + } + else { + grad = tvg_linear_gradient_new(); + + if(g->grad.dir == LV_GRAD_DIR_VER) { + tvg_linear_gradient_set(grad, x, y, x, y + h); + } + else { + tvg_linear_gradient_set(grad, x, y, x + w, y); + } + + _setup_gradient(grad, g, m); + tvg_shape_set_stroke_linear_gradient(obj, grad); + } +} + +static void _set_paint_stroke(Tvg_Paint * obj, const lv_vector_stroke_dsc_t * dsc) +{ + if(dsc->style == LV_VECTOR_DRAW_STYLE_SOLID) { + _tvg_color c; + _lv_color_to_tvg(&c, &dsc->color, dsc->opa); + tvg_shape_set_stroke_color(obj, c.r, c.g, c.b, c.a); + } + else { /*gradient*/ + _set_paint_stroke_gradient(obj, &dsc->gradient, &dsc->matrix); + } + + tvg_shape_set_stroke_width(obj, dsc->width); + tvg_shape_set_stroke_miterlimit(obj, dsc->miter_limit); + tvg_shape_set_stroke_cap(obj, _lv_stroke_cap_to_tvg(dsc->cap)); + tvg_shape_set_stroke_join(obj, _lv_stroke_join_to_tvg(dsc->join)); + + if(!lv_array_is_empty(&dsc->dash_pattern)) { + float * dash_array = lv_array_at(&dsc->dash_pattern, 0); + tvg_shape_set_stroke_dash(obj, dash_array, dsc->dash_pattern.size); + } +} + +static Tvg_Fill_Rule _lv_fill_rule_to_tvg(lv_vector_fill_t rule) +{ + switch(rule) { + case LV_VECTOR_FILL_NONZERO: + return TVG_FILL_RULE_WINDING; + case LV_VECTOR_FILL_EVENODD: + return TVG_FILL_RULE_EVEN_ODD; + default: + return TVG_FILL_RULE_WINDING; + } +} + +static void _set_paint_fill_gradient(Tvg_Paint * obj, const lv_vector_gradient_t * g, const lv_matrix_t * m) +{ + float x, y, w, h; + tvg_paint_get_bounds(obj, &x, &y, &w, &h, false); + + Tvg_Gradient * grad = NULL; + if(g->style == LV_VECTOR_GRADIENT_STYLE_RADIAL) { + grad = tvg_radial_gradient_new(); + tvg_radial_gradient_set(grad, g->cx + x, g->cy + y, g->cr); + _setup_gradient(grad, g, m); + tvg_shape_set_radial_gradient(obj, grad); + } + else { + grad = tvg_linear_gradient_new(); + + if(g->grad.dir == LV_GRAD_DIR_VER) { + tvg_linear_gradient_set(grad, x, y, x, y + h); + } + else { + tvg_linear_gradient_set(grad, x, y, x + w, y); + } + + _setup_gradient(grad, g, m); + tvg_shape_set_linear_gradient(obj, grad); + } +} + +static void _set_paint_fill_pattern(Tvg_Paint * obj, Tvg_Canvas * canvas, const lv_draw_image_dsc_t * p, + const lv_matrix_t * m) +{ + lv_image_decoder_dsc_t decoder_dsc; + lv_image_decoder_args_t args = { 0 }; + lv_result_t res = lv_image_decoder_open(&decoder_dsc, p->src, &args); + if(res != LV_RESULT_OK) { + LV_LOG_ERROR("Failed to open image"); + return; + } + + if(!decoder_dsc.decoded) { + lv_image_decoder_close(&decoder_dsc); + LV_LOG_ERROR("Image not ready"); + return; + } + + const uint8_t * src_buf = decoder_dsc.decoded->data; + const lv_image_header_t * header = &decoder_dsc.decoded->header; + lv_color_format_t cf = header->cf; + + if(cf != LV_COLOR_FORMAT_ARGB8888) { + lv_image_decoder_close(&decoder_dsc); + LV_LOG_ERROR("Not support image format"); + return; + } + + Tvg_Paint * img = tvg_picture_new(); + tvg_picture_load_raw(img, (uint32_t *)src_buf, header->w, header->h, true); + Tvg_Paint * clip_path = tvg_paint_duplicate(obj); + tvg_paint_set_composite_method(img, clip_path, TVG_COMPOSITE_METHOD_CLIP_PATH); + tvg_paint_set_opacity(img, p->opa); + + Tvg_Matrix mtx; + _lv_matrix_to_tvg(&mtx, m); + tvg_paint_set_transform(img, &mtx); + tvg_canvas_push(canvas, img); + lv_image_decoder_close(&decoder_dsc); +} + +static void _set_paint_fill(Tvg_Paint * obj, Tvg_Canvas * canvas, const lv_vector_fill_dsc_t * dsc, + const lv_matrix_t * matrix) +{ + tvg_shape_set_fill_rule(obj, _lv_fill_rule_to_tvg(dsc->fill_rule)); + + if(dsc->style == LV_VECTOR_DRAW_STYLE_SOLID) { + _tvg_color c; + _lv_color_to_tvg(&c, &dsc->color, dsc->opa); + tvg_shape_set_fill_color(obj, c.r, c.g, c.b, c.a); + } + else if(dsc->style == LV_VECTOR_DRAW_STYLE_PATTERN) { + float x, y, w, h; + tvg_paint_get_bounds(obj, &x, &y, &w, &h, false); + + lv_matrix_t imx; + lv_memcpy(&imx, matrix, sizeof(lv_matrix_t)); + lv_matrix_translate(&imx, x, y); + lv_matrix_multiply(&imx, &dsc->matrix); + _set_paint_fill_pattern(obj, canvas, &dsc->img_dsc, &imx); + } + else if(dsc->style == LV_VECTOR_DRAW_STYLE_GRADIENT) { + _set_paint_fill_gradient(obj, &dsc->gradient, &dsc->matrix); + } +} + +static Tvg_Blend_Method _lv_blend_to_tvg(lv_vector_blend_t blend) +{ + switch(blend) { + case LV_VECTOR_BLEND_SRC_OVER: + return TVG_BLEND_METHOD_NORMAL; + case LV_VECTOR_BLEND_SCREEN: + return TVG_BLEND_METHOD_SCREEN; + case LV_VECTOR_BLEND_MULTIPLY: + return TVG_BLEND_METHOD_MULTIPLY; + case LV_VECTOR_BLEND_NONE: + return TVG_BLEND_METHOD_SRCOVER; + case LV_VECTOR_BLEND_ADDITIVE: + return TVG_BLEND_METHOD_ADD; + case LV_VECTOR_BLEND_SRC_IN: + case LV_VECTOR_BLEND_DST_OVER: + case LV_VECTOR_BLEND_DST_IN: + case LV_VECTOR_BLEND_SUBTRACTIVE: + /*not support yet.*/ + default: + return TVG_BLEND_METHOD_NORMAL; + } +} + +static void _set_paint_blend_mode(Tvg_Paint * obj, lv_vector_blend_t blend) +{ + tvg_paint_set_blend_method(obj, _lv_blend_to_tvg(blend)); +} + +static void _task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vector_draw_dsc_t * dsc) +{ + Tvg_Canvas * canvas = (Tvg_Canvas *)ctx; + + Tvg_Paint * obj = tvg_shape_new(); + + if(!path) { /*clear*/ + _tvg_rect rc; + _lv_area_to_tvg(&rc, &dsc->scissor_area); + + _tvg_color c; + _lv_color_to_tvg(&c, &dsc->fill_dsc.color, LV_OPA_COVER); + + Tvg_Matrix mtx = { + 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f, + }; + _set_paint_matrix(obj, &mtx); + tvg_shape_append_rect(obj, rc.x, rc.y, rc.w, rc.h, 0, 0); + tvg_shape_set_fill_color(obj, c.r, c.g, c.b, c.a); + } + else { + Tvg_Matrix mtx; + _lv_matrix_to_tvg(&mtx, &dsc->matrix); + _set_paint_matrix(obj, &mtx); + + _set_paint_shape(obj, path); + + _set_paint_fill(obj, canvas, &dsc->fill_dsc, &dsc->matrix); + _set_paint_stroke(obj, &dsc->stroke_dsc); + _set_paint_blend_mode(obj, dsc->blend_mode); + } + + tvg_canvas_push(canvas, obj); +} + +/********************** + * GLOBAL FUNCTIONS + **********************/ +void lv_draw_sw_vector(lv_draw_unit_t * draw_unit, const lv_draw_vector_task_dsc_t * dsc) +{ + LV_UNUSED(draw_unit); + + if(dsc->task_list == NULL) + return; + + lv_layer_t * layer = dsc->base.layer; + lv_draw_buf_t * draw_buf = layer->draw_buf; + if(draw_buf == NULL) + return; + + lv_color_format_t cf = draw_buf->header.cf; + + if(cf != LV_COLOR_FORMAT_ARGB8888 && \ + cf != LV_COLOR_FORMAT_XRGB8888) { + LV_LOG_ERROR("unsupported layer color: %d", cf); + return; + } + + void * buf = draw_buf->data; + int32_t width = lv_area_get_width(&layer->buf_area); + int32_t height = lv_area_get_height(&layer->buf_area); + uint32_t stride = draw_buf->header.stride; + Tvg_Canvas * canvas = tvg_swcanvas_create(); + tvg_swcanvas_set_target(canvas, buf, stride / 4, width, height, TVG_COLORSPACE_ARGB8888); + + lv_ll_t * task_list = dsc->task_list; + _lv_vector_for_each_destroy_tasks(task_list, _task_draw_cb, canvas); + + if(tvg_canvas_draw(canvas) == TVG_RESULT_SUCCESS) { + tvg_canvas_sync(canvas); + } + + tvg_canvas_destroy(canvas); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_SW*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_draw_swm341_dma2d.mk b/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_draw_swm341_dma2d.mk deleted file mode 100644 index bc19e3802..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_draw_swm341_dma2d.mk +++ /dev/null @@ -1,6 +0,0 @@ -CSRCS += lv_gpu_swm341_dma2d.c - -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/swm341_dma2d -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/swm341_dma2d - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw/swm341_dma2d" diff --git a/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.c b/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.c deleted file mode 100644 index 74a539467..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.c +++ /dev/null @@ -1,241 +0,0 @@ -/** - * @file lv_gpu_swm341_dma2d.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_gpu_swm341_dma2d.h" -#include "../../core/lv_refr.h" - -#if LV_USE_GPU_SWM341_DMA2D - -#include LV_GPU_SWM341_DMA2D_INCLUDE - -/********************* - * DEFINES - *********************/ - -#if LV_COLOR_16_SWAP - #error "Can't use DMA2D with LV_COLOR_16_SWAP 1" -#endif - -#if LV_COLOR_DEPTH == 8 - #error "Can't use DMA2D with LV_COLOR_DEPTH == 8" -#endif - -#if LV_COLOR_DEPTH == 16 - #define LV_DMA2D_COLOR_FORMAT LV_SWM341_DMA2D_RGB565 -#elif LV_COLOR_DEPTH == 32 - #define LV_DMA2D_COLOR_FORMAT LV_SWM341_DMA2D_ARGB8888 -#else - /*Can't use GPU with other formats*/ -#endif - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -static void lv_draw_swm341_dma2d_blend_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area, - lv_color_t color); - -static void lv_draw_swm341_dma2d_blend_map(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa); - -static void lv_draw_swm341_dma2d_img_decoded(lv_draw_ctx_t * draw, const lv_draw_img_dsc_t * dsc, - const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format); - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Turn on the peripheral and set output color mode, this only needs to be done once - */ -void lv_draw_swm341_dma2d_init(void) -{ - /*Enable DMA2D clock*/ - SYS->CLKEN0 |= (1 << SYS_CLKEN0_DMA2D_Pos); - - DMA2D->CR &= ~DMA2D_CR_WAIT_Msk; - DMA2D->CR |= (CyclesPerUs << DMA2D_CR_WAIT_Pos); - - DMA2D->IF = 0xFF; - DMA2D->IE = (0 << DMA2D_IE_DONE_Pos); - - /*set output colour mode*/ - DMA2D->L[DMA2D_LAYER_OUT].PFCCR = (LV_DMA2D_COLOR_FORMAT << DMA2D_PFCCR_CFMT_Pos); -} - -void lv_draw_swm341_dma2d_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) -{ - - lv_draw_sw_init_ctx(drv, draw_ctx); - - lv_draw_swm341_dma2d_ctx_t * dma2d_draw_ctx = (lv_draw_sw_ctx_t *)draw_ctx; - - dma2d_draw_ctx->blend = lv_draw_swm341_dma2d_blend; - // dma2d_draw_ctx->base_draw.draw_img_decoded = lv_draw_swm341_dma2d_img_decoded; - dma2d_draw_ctx->base_draw.wait_for_finish = lv_gpu_swm341_dma2d_wait_cb; -} - -void lv_draw_swm341_dma2d_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) -{ - LV_UNUSED(drv); - LV_UNUSED(draw_ctx); -} - -void lv_draw_swm341_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc) -{ - lv_area_t blend_area; - if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) - return; - - bool done = false; - - if(dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL && lv_area_get_size(&blend_area) > 100) { - lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); - - lv_color_t * dest_buf = draw_ctx->buf; - dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + (blend_area.x1 - draw_ctx->buf_area->x1); - - const lv_color_t * src_buf = dsc->src_buf; - if(src_buf) { - lv_draw_sw_blend_basic(draw_ctx, dsc); - lv_coord_t src_stride; - src_stride = lv_area_get_width(dsc->blend_area); - src_buf += src_stride * (blend_area.y1 - dsc->blend_area->y1) + (blend_area.x1 - dsc->blend_area->x1); - lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - lv_draw_swm341_dma2d_blend_map(dest_buf, &blend_area, dest_stride, src_buf, src_stride, dsc->opa); - done = true; - } - else if(dsc->opa >= LV_OPA_MAX) { - lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); - lv_draw_swm341_dma2d_blend_fill(dest_buf, dest_stride, &blend_area, dsc->color); - done = true; - } - } - - if(!done) lv_draw_sw_blend_basic(draw_ctx, dsc); -} - -static void lv_draw_swm341_dma2d_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, - const lv_area_t * coords, const uint8_t * map_p, lv_img_cf_t color_format) -{ - /*TODO basic ARGB8888 image can be handles here*/ - - lv_draw_sw_img_decoded(draw_ctx, dsc, coords, map_p, color_format); -} - -static void lv_draw_swm341_dma2d_blend_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area, - lv_color_t color) -{ - /*Simply fill an area*/ - int32_t area_w = lv_area_get_width(fill_area); - int32_t area_h = lv_area_get_height(fill_area); - -#if 1 - DMA2D->L[DMA2D_LAYER_OUT].COLOR = color.full; - - DMA2D->L[DMA2D_LAYER_OUT].MAR = (uint32_t)dest_buf; - DMA2D->L[DMA2D_LAYER_OUT].OR = dest_stride - area_w; - DMA2D->NLR = ((area_w - 1) << DMA2D_NLR_NPIXEL_Pos) | ((area_h - 1) << DMA2D_NLR_NLINE_Pos); - - /*start transfer*/ - DMA2D->CR &= ~DMA2D_CR_MODE_Msk; - DMA2D->CR |= (3 << DMA2D_CR_MODE_Pos) | - (1 << DMA2D_CR_START_Pos); -#else - for(uint32_t y = 0; y < area_h; y++) { - for(uint32_t x = 0; x < area_w; x++) { - dest_buf[y * dest_stride + x] = color; - } - } -#endif -} - -static void lv_draw_swm341_dma2d_blend_map(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride, - const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa) -{ - - /*Simple copy*/ - int32_t dest_w = lv_area_get_width(dest_area); - int32_t dest_h = lv_area_get_height(dest_area); - - if(opa >= LV_OPA_MAX) { -#if 1 - /*copy output colour mode, this register controls both input and output colour format*/ - DMA2D->L[DMA2D_LAYER_FG].MAR = (uint32_t)src_buf; - DMA2D->L[DMA2D_LAYER_FG].OR = src_stride - dest_w; - DMA2D->L[DMA2D_LAYER_FG].PFCCR = (LV_DMA2D_COLOR_FORMAT << DMA2D_PFCCR_CFMT_Pos); - - DMA2D->L[DMA2D_LAYER_OUT].MAR = (uint32_t)dest_buf; - DMA2D->L[DMA2D_LAYER_OUT].OR = dest_stride - dest_w; - - DMA2D->NLR = ((dest_w - 1) << DMA2D_NLR_NPIXEL_Pos) | ((dest_h - 1) << DMA2D_NLR_NLINE_Pos); - - /*start transfer*/ - DMA2D->CR &= ~DMA2D_CR_MODE_Msk; - DMA2D->CR |= (0 << DMA2D_CR_MODE_Pos) | - (1 << DMA2D_CR_START_Pos); -#else - lv_color_t temp_buf[1024]; - for(uint32_t y = 0; y < dest_h; y++) { - memcpy(temp_buf, &src_buf[y * src_stride], dest_w * sizeof(lv_color_t)); - memcpy(&dest_buf[y * dest_stride], temp_buf, dest_w * sizeof(lv_color_t)); - } -#endif - } - else { - DMA2D->L[DMA2D_LAYER_FG].MAR = (uint32_t)src_buf; - DMA2D->L[DMA2D_LAYER_FG].OR = src_stride - dest_w; - DMA2D->L[DMA2D_LAYER_FG].PFCCR = (LV_DMA2D_COLOR_FORMAT << DMA2D_PFCCR_CFMT_Pos) - /*alpha mode 2, replace with foreground * alpha value*/ - | (2 << DAM2D_PFCCR_AMODE_Pos) - /*alpha value*/ - | (opa << DMA2D_PFCCR_ALPHA_Pos); - - DMA2D->L[DMA2D_LAYER_BG].MAR = (uint32_t)dest_buf; - DMA2D->L[DMA2D_LAYER_BG].OR = dest_stride - dest_w; - DMA2D->L[DMA2D_LAYER_BG].PFCCR = (LV_DMA2D_COLOR_FORMAT << DMA2D_PFCCR_CFMT_Pos); - - DMA2D->L[DMA2D_LAYER_OUT].MAR = (uint32_t)dest_buf; - DMA2D->L[DMA2D_LAYER_OUT].OR = dest_stride - dest_w; - - DMA2D->NLR = ((dest_w - 1) << DMA2D_NLR_NPIXEL_Pos) | ((dest_h - 1) << DMA2D_NLR_NLINE_Pos); - - /*start transfer*/ - DMA2D->CR &= ~DMA2D_CR_MODE_Msk; - DMA2D->CR |= (2 << DMA2D_CR_MODE_Pos) | - (1 << DMA2D_CR_START_Pos); - } -} - -void lv_gpu_swm341_dma2d_wait_cb(lv_draw_ctx_t * draw_ctx) -{ - lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - if(disp->driver && disp->driver->wait_cb) { - while(DMA2D->CR & DMA2D_CR_START_Msk) { - disp->driver->wait_cb(disp->driver); - } - } - else { - while(DMA2D->CR & DMA2D_CR_START_Msk); - } - lv_draw_sw_wait_for_finish(draw_ctx); -} - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.h b/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.h deleted file mode 100644 index 20b892260..000000000 --- a/lib/libesp32_lvgl/lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @file lv_gpu_swm341_dma2d.h - * - */ - -#ifndef LV_GPU_SWM341_DMA2D_H -#define LV_GPU_SWM341_DMA2D_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../misc/lv_color.h" -#include "../../hal/lv_hal_disp.h" -#include "../sw/lv_draw_sw.h" - -#if LV_USE_GPU_SWM341_DMA2D - -/********************* - * DEFINES - *********************/ - -#define LV_SWM341_DMA2D_ARGB8888 0 -#define LV_SWM341_DMA2D_RGB888 1 -#define LV_SWM341_DMA2D_RGB565 2 - -/********************** - * TYPEDEFS - **********************/ -typedef lv_draw_sw_ctx_t lv_draw_swm341_dma2d_ctx_t; - -struct _lv_disp_drv_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Turn on the peripheral and set output color mode, this only needs to be done once - */ -void lv_draw_swm341_dma2d_init(void); - -void lv_draw_swm341_dma2d_ctx_init(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); - -void lv_draw_swm341_dma2d_ctx_deinit(struct _lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx); - -void lv_draw_swm341_dma2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); - -void lv_gpu_swm341_dma2d_wait_cb(lv_draw_ctx_t * draw_ctx); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_GPU_SWM341_DMA2D*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_GPU_SWM341_DMA2D_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_buf_vg_lite.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_buf_vg_lite.c new file mode 100644 index 000000000..65b085ca0 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_buf_vg_lite.c @@ -0,0 +1,57 @@ +/** + * @file lv_draw_buf_vg_lite.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vg_lite.h" + +#if LV_USE_DRAW_VG_LITE + +#include "lv_vg_lite_utils.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static uint32_t width_to_stride(uint32_t w, lv_color_format_t color_format); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_buf_vg_lite_init_handlers(void) +{ + lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers(); + handlers->width_to_stride_cb = width_to_stride; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static uint32_t width_to_stride(uint32_t w, lv_color_format_t color_format) +{ + return lv_vg_lite_width_to_stride(w, lv_vg_lite_vg_fmt(color_format)); +} + +#endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite.c new file mode 100644 index 000000000..ad49c4a52 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite.c @@ -0,0 +1,225 @@ +/** + * @file lv_vg_lite_draw.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vg_lite.h" + +#if LV_USE_DRAW_VG_LITE + +#include "../lv_draw.h" +#include "lv_draw_vg_lite_type.h" +#include "lv_vg_lite_path.h" +#include "lv_vg_lite_utils.h" +#include "lv_vg_lite_decoder.h" + +/********************* + * DEFINES + *********************/ + +#define VG_LITE_DRAW_UNIT_ID 2 + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static int32_t draw_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer); + +static int32_t draw_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task); + +static int32_t draw_delete(lv_draw_unit_t * draw_unit); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vg_lite_init(void) +{ +#if LV_VG_LITE_USE_GPU_INIT + extern void gpu_init(void); + static bool inited = false; + if(!inited) { + gpu_init(); + inited = true; + } +#endif + + lv_vg_lite_dump_info(); + + lv_draw_buf_vg_lite_init_handlers(); + + lv_draw_vg_lite_unit_t * unit = lv_draw_create_unit(sizeof(lv_draw_vg_lite_unit_t)); + unit->base_unit.dispatch_cb = draw_dispatch; + unit->base_unit.evaluate_cb = draw_evaluate; + unit->base_unit.delete_cb = draw_delete; + + lv_vg_lite_path_init(unit); + + lv_vg_lite_decoder_init(); +} + +void lv_draw_vg_lite_deinit(void) +{ +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void draw_execute(lv_draw_vg_lite_unit_t * u) +{ + lv_draw_task_t * t = u->task_act; + lv_draw_unit_t * draw_unit = (lv_draw_unit_t *)u; + + lv_layer_t * layer = u->base_unit.target_layer; + + lv_vg_lite_buffer_from_draw_buf(&u->target_buffer, layer->draw_buf); + + vg_lite_identity(&u->global_matrix); + vg_lite_translate(-layer->buf_area.x1, -layer->buf_area.y1, &u->global_matrix); + + switch(t->type) { + case LV_DRAW_TASK_TYPE_LABEL: + lv_draw_vg_lite_label(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_FILL: + lv_draw_vg_lite_fill(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_BORDER: + lv_draw_vg_lite_border(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_BOX_SHADOW: + lv_draw_vg_lite_box_shadow(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_IMAGE: + lv_draw_vg_lite_img(draw_unit, t->draw_dsc, &t->area, false); + break; + case LV_DRAW_TASK_TYPE_ARC: + lv_draw_vg_lite_arc(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_LINE: + lv_draw_vg_lite_line(draw_unit, t->draw_dsc); + break; + case LV_DRAW_TASK_TYPE_LAYER: + lv_draw_vg_lite_layer(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_TRIANGLE: + lv_draw_vg_lite_triangle(draw_unit, t->draw_dsc); + break; + case LV_DRAW_TASK_TYPE_MASK_RECTANGLE: + lv_draw_vg_lite_mask_rect(draw_unit, t->draw_dsc, &t->area); + break; +#if LV_USE_VECTOR_GRAPHIC + case LV_DRAW_TASK_TYPE_VECTOR: + lv_draw_vg_lite_vector(draw_unit, t->draw_dsc); + break; +#endif + default: + break; + } + +#if LV_USE_PARALLEL_DRAW_DEBUG + /* Layers manage it for themselves. */ + if(t->type != LV_DRAW_TASK_TYPE_LAYER) { + } +#endif + + LV_VG_LITE_CHECK_ERROR(vg_lite_finish()); +} + +static int32_t draw_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer) +{ + lv_draw_vg_lite_unit_t * draw_vg_lite_unit = (lv_draw_vg_lite_unit_t *)draw_unit; + + /* Return immediately if it's busy with draw task. */ + if(draw_vg_lite_unit->task_act) { + return 0; + } + + /* Try to get an ready to draw. */ + lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, VG_LITE_DRAW_UNIT_ID); + + /* Return 0 is no selection, some tasks can be supported by other units. */ + if(!t || t->preferred_draw_unit_id != VG_LITE_DRAW_UNIT_ID) { + return -1; + } + + void * buf = lv_draw_layer_alloc_buf(layer); + if(!buf) { + return -1; + } + + /* Return if target buffer format is not supported. */ + if(!lv_vg_lite_is_dest_cf_supported(layer->draw_buf->header.cf)) { + return -1; + } + + t->state = LV_DRAW_TASK_STATE_IN_PROGRESS; + draw_vg_lite_unit->base_unit.target_layer = layer; + draw_vg_lite_unit->base_unit.clip_area = &t->clip_area; + draw_vg_lite_unit->task_act = t; + + draw_execute(draw_vg_lite_unit); + + draw_vg_lite_unit->task_act->state = LV_DRAW_TASK_STATE_READY; + draw_vg_lite_unit->task_act = NULL; + + /* The draw unit is free now. Request a new dispatching as it can get a new task. */ + lv_draw_dispatch_request(); + + return 1; +} + +static int32_t draw_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task) +{ + LV_UNUSED(draw_unit); + + switch(task->type) { + case LV_DRAW_TASK_TYPE_LABEL: + case LV_DRAW_TASK_TYPE_FILL: + case LV_DRAW_TASK_TYPE_BORDER: + case LV_DRAW_TASK_TYPE_BOX_SHADOW: + case LV_DRAW_TASK_TYPE_IMAGE: + case LV_DRAW_TASK_TYPE_LAYER: + case LV_DRAW_TASK_TYPE_LINE: + case LV_DRAW_TASK_TYPE_ARC: + case LV_DRAW_TASK_TYPE_TRIANGLE: + case LV_DRAW_TASK_TYPE_MASK_RECTANGLE: + // case LV_DRAW_TASK_TYPE_MASK_BITMAP: +#if LV_USE_VECTOR_GRAPHIC + case LV_DRAW_TASK_TYPE_VECTOR: +#endif + task->preference_score = 80; + task->preferred_draw_unit_id = VG_LITE_DRAW_UNIT_ID; + return 1; + default: + break; + } + return 0; +} + +static int32_t draw_delete(lv_draw_unit_t * draw_unit) +{ + lv_draw_vg_lite_unit_t * unit = (lv_draw_vg_lite_unit_t *)draw_unit; + lv_vg_lite_path_deinit(unit); + lv_vg_lite_decoder_deinit(); + return 1; +} + +#endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite.h b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite.h new file mode 100644 index 000000000..8b5cb3b46 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite.h @@ -0,0 +1,84 @@ +/** + * @file lv_vg_lite_draw.h + * + */ + +#ifndef LV_VG_LITE_DRAW_H +#define LV_VG_LITE_DRAW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_DRAW_VG_LITE + +#include "../lv_draw.h" +#include "../../draw/lv_draw_vector.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_buf_vg_lite_init_handlers(void); + +void lv_draw_vg_lite_init(void); + +void lv_draw_vg_lite_deinit(void); + +void lv_draw_vg_lite_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_vg_lite_box_shadow(lv_draw_unit_t * draw_unit, const lv_draw_box_shadow_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_vg_lite_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_vg_lite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_vg_lite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc, + const lv_area_t * coords, bool no_cache); + +void lv_draw_vg_lite_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_vg_lite_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords); + +void lv_draw_vg_lite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc); + +void lv_draw_vg_lite_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc); + +void lv_draw_vg_lite_mask_rect(lv_draw_unit_t * draw_unit, const lv_draw_mask_rect_dsc_t * dsc, + const lv_area_t * coords); + +#if LV_USE_VECTOR_GRAPHIC +void lv_draw_vg_lite_vector(lv_draw_unit_t * draw_unit, const lv_draw_vector_task_dsc_t * dsc); +#endif + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_VG_LITE_DRAW_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_arc.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_arc.c new file mode 100644 index 000000000..a253b6148 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_arc.c @@ -0,0 +1,200 @@ +/** + * @file lv_draw_vg_lite_arc.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vg_lite.h" + +#if LV_USE_DRAW_VG_LITE + +#include "lv_draw_vg_lite_type.h" +#include "lv_vg_lite_math.h" +#include "lv_vg_lite_path.h" +#include "lv_vg_lite_utils.h" +#include + +/********************* + * DEFINES + *********************/ + +#define PI 3.1415926535897932384626433832795f +#define TWO_PI 6.283185307179586476925286766559f +#define DEG_TO_RAD 0.017453292519943295769236907684886f +#define RAD_TO_DEG 57.295779513082320876798154814105f +#define radians(deg) ((deg) * DEG_TO_RAD) +#define degrees(rad) ((rad) * RAD_TO_DEG) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vg_lite_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, + const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) + return; + if(dsc->width <= 0) + return; + if(dsc->start_angle == dsc->end_angle) + return; + + lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit; + + lv_area_t clip_area; + if(!_lv_area_intersect(&clip_area, coords, draw_unit->clip_area)) { + /*Fully clipped, nothing to do*/ + return; + } + + float start_angle = dsc->start_angle; + float end_angle = dsc->end_angle; + float sweep_angle = end_angle - start_angle; + + while(sweep_angle < 0) { + sweep_angle += 360; + } + + while(sweep_angle > 360) { + sweep_angle -= 360; + } + + /*If the angles are the same then there is nothing to draw*/ + if(math_zero(sweep_angle)) { + return; + } + + lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_FP32); + lv_vg_lite_path_set_quality(path, VG_LITE_HIGH); + lv_vg_lite_path_set_bonding_box_area(path, &clip_area); + + float radius_out = dsc->radius; + float radius_in = dsc->radius - dsc->width; + float half_width = dsc->width * 0.5f; + float radius_center = radius_out - half_width; + float cx = dsc->center.x; + float cy = dsc->center.y; + + vg_lite_fill_t fill = VG_LITE_FILL_NON_ZERO; + + if(math_equal(sweep_angle, 360)) { + lv_vg_lite_path_append_circle(path, cx, cy, radius_out, radius_out); + lv_vg_lite_path_append_circle(path, cx, cy, radius_in, radius_in); + fill = VG_LITE_FILL_EVEN_ODD; + } + else { + /* radius_out start point */ + float start_angle_rad = MATH_RADIANS(start_angle); + float start_x = radius_out * MATH_COSF(start_angle_rad) + cx; + float start_y = radius_out * MATH_SINF(start_angle_rad) + cy; + + /* radius_in start point */ + float end_angle_rad = MATH_RADIANS(end_angle); + float end_x = radius_in * MATH_COSF(end_angle_rad) + cx; + float end_y = radius_in * MATH_SINF(end_angle_rad) + cy; + + /* radius_out arc */ + lv_vg_lite_path_append_arc(path, + cx, cy, + radius_out, + start_angle, + sweep_angle, + false); + + /* line to radius_in */ + lv_vg_lite_path_line_to(path, end_x, end_y); + + /* radius_in arc */ + lv_vg_lite_path_append_arc(path, + cx, cy, + radius_in, + end_angle, + -sweep_angle, + false); + + /* close arc */ + lv_vg_lite_path_line_to(path, start_x, start_y); + lv_vg_lite_path_close(path); + + /* draw round */ + if(dsc->rounded && half_width > 0) { + float rcx1 = cx + radius_center * MATH_COSF(end_angle_rad); + float rcy1 = cy + radius_center * MATH_SINF(end_angle_rad); + lv_vg_lite_path_append_circle(path, rcx1, rcy1, half_width, half_width); + + float rcx2 = cx + radius_center * MATH_COSF(start_angle_rad); + float rcy2 = cy + radius_center * MATH_SINF(start_angle_rad); + lv_vg_lite_path_append_circle(path, rcx2, rcy2, half_width, half_width); + } + } + + lv_vg_lite_path_end(path); + + vg_lite_matrix_t matrix; + vg_lite_identity(&matrix); + lv_vg_lite_matrix_multiply(&matrix, &u->global_matrix); + + vg_lite_color_t color = lv_vg_lite_color(dsc->color, dsc->opa, true); + + vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path); + + LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer); + LV_VG_LITE_ASSERT_PATH(vg_lite_path); + + LV_VG_LITE_CHECK_ERROR(vg_lite_draw( + &u->target_buffer, + vg_lite_path, + fill, + &matrix, + VG_LITE_BLEND_SRC_OVER, + color)); + + if(dsc->img_src) { + vg_lite_buffer_t src_buf; + lv_image_decoder_dsc_t decoder_dsc; + if(lv_vg_lite_buffer_open_image(&src_buf, &decoder_dsc, dsc->img_src, false)) { + vg_lite_matrix_t path_matrix; + vg_lite_identity(&path_matrix); + LV_VG_LITE_CHECK_ERROR(vg_lite_draw_pattern( + &u->target_buffer, + vg_lite_path, + fill, + &path_matrix, + &src_buf, + &matrix, + VG_LITE_BLEND_SRC_OVER, + VG_LITE_PATTERN_COLOR, + 0, + color, + VG_LITE_FILTER_BI_LINEAR)); + lv_image_decoder_close(&decoder_dsc); + } + } + + lv_vg_lite_path_drop(u, path); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_border.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_border.c new file mode 100644 index 000000000..757e2ea22 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_border.c @@ -0,0 +1,115 @@ +/** + * @file lv_draw_vg_lite_border.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vg_lite.h" + +#if LV_USE_DRAW_VG_LITE + +#include "lv_draw_vg_lite_type.h" +#include "lv_vg_lite_utils.h" +#include "lv_vg_lite_path.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vg_lite_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, + const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) + return; + if(dsc->width == 0) + return; + if(dsc->side == LV_BORDER_SIDE_NONE) + return; + + lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit; + + lv_area_t clip_area; + if(!_lv_area_intersect(&clip_area, coords, draw_unit->clip_area)) { + /*Fully clipped, nothing to do*/ + return; + } + + int32_t w = lv_area_get_width(coords); + int32_t h = lv_area_get_height(coords); + int32_t r_out = dsc->radius; + if(r_out) { + int32_t r_short = LV_MIN(w, h) / 2; + r_out = LV_MIN(r_out, r_short); + } + + int32_t border_w = dsc->width; + int32_t r_in = LV_MAX(0, r_out - border_w); + + lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_S16); + lv_vg_lite_path_set_quality(path, dsc->radius == 0 ? VG_LITE_LOW : VG_LITE_HIGH); + lv_vg_lite_path_set_bonding_box_area(path, &clip_area); + + /* outer rect */ + lv_vg_lite_path_append_rect(path, + coords->x1, coords->y1, + w, h, + r_out, r_out); + + /* inner rect */ + lv_vg_lite_path_append_rect(path, + coords->x1 + border_w, coords->y1 + border_w, + w - border_w * 2, h - border_w * 2, + r_in, r_in); + + lv_vg_lite_path_end(path); + + vg_lite_matrix_t matrix; + vg_lite_identity(&matrix); + lv_vg_lite_matrix_multiply(&matrix, &u->global_matrix); + + vg_lite_color_t color = lv_vg_lite_color(dsc->color, dsc->opa, true); + + vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path); + + LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer); + LV_VG_LITE_ASSERT_PATH(vg_lite_path); + + LV_VG_LITE_CHECK_ERROR(vg_lite_draw( + &u->target_buffer, + vg_lite_path, + VG_LITE_FILL_EVEN_ODD, + &matrix, + VG_LITE_BLEND_SRC_OVER, + color)); + + lv_vg_lite_path_drop(u, path); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_box_shadow.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_box_shadow.c new file mode 100644 index 000000000..c9e00c4d3 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_box_shadow.c @@ -0,0 +1,97 @@ +/** + * @file lv_draw_vg_lite_box_shadow.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vg_lite.h" + +#if LV_USE_DRAW_VG_LITE + +#include "lv_draw_vg_lite_type.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vg_lite_box_shadow(lv_draw_unit_t * draw_unit, const lv_draw_box_shadow_dsc_t * dsc, + const lv_area_t * coords) +{ + /*Calculate the rectangle which is blurred to get the shadow in `shadow_area`*/ + lv_area_t core_area; + core_area.x1 = coords->x1 + dsc->ofs_x - dsc->spread; + core_area.x2 = coords->x2 + dsc->ofs_x + dsc->spread; + core_area.y1 = coords->y1 + dsc->ofs_y - dsc->spread; + core_area.y2 = coords->y2 + dsc->ofs_y + dsc->spread; + + /*Calculate the bounding box of the shadow*/ + lv_area_t shadow_area; + shadow_area.x1 = core_area.x1 - dsc->width / 2 - 1; + shadow_area.x2 = core_area.x2 + dsc->width / 2 + 1; + shadow_area.y1 = core_area.y1 - dsc->width / 2 - 1; + shadow_area.y2 = core_area.y2 + dsc->width / 2 + 1; + + lv_opa_t opa = dsc->opa; + if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; + + /*Get clipped draw area which is the real draw area. + *It is always the same or inside `shadow_area`*/ + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, &shadow_area, draw_unit->clip_area)) return; + + lv_draw_border_dsc_t border_dsc; + lv_draw_border_dsc_init(&border_dsc); + border_dsc.width = 3; + border_dsc.color = dsc->color; + border_dsc.radius = dsc->radius; + + lv_area_move(&draw_area, dsc->ofs_x, dsc->ofs_y); + draw_area = core_area; + int32_t half_w = dsc->width / 2; + + for(int32_t w = 0; w < half_w; w++) { + border_dsc.opa = lv_map(w, 0, half_w, dsc->opa / 4, LV_OPA_0); + border_dsc.radius++; + lv_area_increase(&draw_area, 1, 1); + lv_draw_vg_lite_border(draw_unit, &border_dsc, &draw_area); + + /* fill center */ + if(dsc->ofs_x || dsc->ofs_y) { + lv_draw_fill_dsc_t fill_dsc; + lv_draw_fill_dsc_init(&fill_dsc); + fill_dsc.radius = dsc->radius; + fill_dsc.opa = dsc->opa; + fill_dsc.color = dsc->color; + lv_draw_vg_lite_fill(draw_unit, &fill_dsc, &core_area); + } + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_fill.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_fill.c new file mode 100644 index 000000000..459fd47fb --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_fill.c @@ -0,0 +1,111 @@ +/** + * @file lv_draw_vg_lite_fill.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vg_lite.h" + +#if LV_USE_DRAW_VG_LITE + +#include "lv_draw_vg_lite_type.h" +#include "lv_vg_lite_path.h" +#include "lv_vg_lite_utils.h" + +/********************* + * DEFINES + *********************/ + +#if LV_GRADIENT_MAX_STOPS > VLC_MAX_GRADIENT_STOPS + #error "LV_GRADIENT_MAX_STOPS must be equal or less than VLC_MAX_GRADIENT_STOPS" +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vg_lite_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) { + return; + } + + lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit; + + lv_area_t clip_area; + if(!_lv_area_intersect(&clip_area, coords, draw_unit->clip_area)) { + /*Fully clipped, nothing to do*/ + return; + } + + vg_lite_matrix_t matrix; + vg_lite_identity(&matrix); + lv_vg_lite_matrix_multiply(&matrix, &u->global_matrix); + + int32_t w = lv_area_get_width(coords); + int32_t h = lv_area_get_height(coords); + int32_t r = dsc->radius; + if(r) { + int32_t r_short = LV_MIN(w, h) / 2; + r = LV_MIN(r, r_short); + } + + lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_S16); + lv_vg_lite_path_set_quality(path, dsc->radius == 0 ? VG_LITE_LOW : VG_LITE_HIGH); + lv_vg_lite_path_set_bonding_box_area(path, &clip_area); + lv_vg_lite_path_append_rect(path, coords->x1, coords->y1, w, h, r, r); + lv_vg_lite_path_end(path); + + vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path); + + LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer); + LV_VG_LITE_ASSERT_PATH(vg_lite_path); + + if(dsc->grad.dir != LV_GRAD_DIR_NONE) { + lv_vg_lite_draw_linear_grad( + &u->target_buffer, + vg_lite_path, + coords, + &dsc->grad, + &matrix, + VG_LITE_FILL_EVEN_ODD, + VG_LITE_BLEND_SRC_OVER); + } + else { /* normal fill */ + vg_lite_color_t color = lv_vg_lite_color(dsc->color, dsc->opa, true); + LV_VG_LITE_CHECK_ERROR(vg_lite_draw( + &u->target_buffer, + vg_lite_path, + VG_LITE_FILL_EVEN_ODD, + &matrix, + VG_LITE_BLEND_SRC_OVER, + color)); + } + + lv_vg_lite_path_drop(u, path); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_img.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_img.c new file mode 100644 index 000000000..05c8debd0 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_img.c @@ -0,0 +1,158 @@ +/** + * @file lv_draw_vg_lite_img.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vg_lite.h" + +#if LV_USE_DRAW_VG_LITE + +#include "lv_draw_vg_lite_type.h" +#include "lv_vg_lite_decoder.h" +#include "lv_vg_lite_path.h" +#include "lv_vg_lite_utils.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vg_lite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc, + const lv_area_t * coords, bool no_cache) +{ + if(dsc->opa <= LV_OPA_MIN) { + return; + } + + lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit; + + /* The coordinates passed in by coords are not transformed, + * so the transformed area needs to be calculated once. + */ + lv_area_t image_tf_area; + _lv_image_buf_get_transformed_area( + &image_tf_area, + lv_area_get_width(coords), + lv_area_get_height(coords), + dsc->rotation, + dsc->scale_x, + dsc->scale_y, + &dsc->pivot); + lv_area_move(&image_tf_area, coords->x1, coords->y1); + + lv_area_t clip_area; + if(!_lv_area_intersect(&clip_area, &image_tf_area, draw_unit->clip_area)) { + /*Fully clipped, nothing to do*/ + return; + } + + vg_lite_buffer_t src_buf; + lv_image_decoder_dsc_t decoder_dsc; + if(!lv_vg_lite_buffer_open_image(&src_buf, &decoder_dsc, dsc->src, no_cache)) { + return; + } + + vg_lite_color_t color = 0; + if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(decoder_dsc.decoded->header.cf) || dsc->recolor_opa > LV_OPA_MIN) { + /* alpha image and image recolor */ + src_buf.image_mode = VG_LITE_MULTIPLY_IMAGE_MODE; + color = lv_vg_lite_color(dsc->recolor, LV_OPA_MIX2(dsc->opa, dsc->recolor_opa), true); + } + else if(dsc->opa < LV_OPA_MAX) { + /* normal image opa */ + src_buf.image_mode = VG_LITE_MULTIPLY_IMAGE_MODE; + lv_memset(&color, dsc->opa, sizeof(color)); + } + + bool has_trasform = (dsc->rotation != 0 || dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE); + vg_lite_filter_t filter = has_trasform ? VG_LITE_FILTER_BI_LINEAR : VG_LITE_FILTER_POINT; + + vg_lite_matrix_t matrix; + vg_lite_identity(&matrix); + lv_vg_lite_matrix_multiply(&matrix, &u->global_matrix); + lv_vg_lite_image_matrix(&matrix, coords->x1, coords->y1, dsc); + + LV_VG_LITE_ASSERT_SRC_BUFFER(&src_buf); + LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer); + + /* If clipping is not required, blit directly */ + if(_lv_area_is_in(&image_tf_area, draw_unit->clip_area, false)) { + /* The image area is the coordinates relative to the image itself */ + lv_area_t src_area = *coords; + lv_area_move(&src_area, -coords->x1, -coords->y1); + + /* rect is used to crop the pixel-aligned padding area */ + vg_lite_rectangle_t rect; + lv_vg_lite_rect(&rect, &src_area); + LV_VG_LITE_CHECK_ERROR(vg_lite_blit_rect( + &u->target_buffer, + &src_buf, + &rect, + &matrix, + lv_vg_lite_blend_mode(dsc->blend_mode), + color, + filter)); + } + else { + lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_S16); + lv_vg_lite_path_append_rect( + path, + clip_area.x1, clip_area.y1, + lv_area_get_width(&clip_area), lv_area_get_height(&clip_area), + 0, 0); + lv_vg_lite_path_set_bonding_box_area(path, &clip_area); + lv_vg_lite_path_end(path); + + vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path); + LV_VG_LITE_ASSERT_PATH(vg_lite_path); + + vg_lite_matrix_t path_matrix; + vg_lite_identity(&path_matrix); + + LV_VG_LITE_CHECK_ERROR(vg_lite_draw_pattern( + &u->target_buffer, + vg_lite_path, + VG_LITE_FILL_EVEN_ODD, + &path_matrix, + &src_buf, + &matrix, + lv_vg_lite_blend_mode(dsc->blend_mode), + VG_LITE_PATTERN_COLOR, + 0, + color, + filter)); + + lv_vg_lite_path_drop(u, path); + } + + lv_image_decoder_close(&decoder_dsc); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_label.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_label.c new file mode 100644 index 000000000..91bcf2e2d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_label.c @@ -0,0 +1,331 @@ +/** + * @file lv_draw_vg_lite_label.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vg_lite.h" + +#include "../../libs/freetype/lv_freetype.h" + +#if LV_USE_DRAW_VG_LITE + +#include "lv_vg_lite_utils.h" +#include "lv_vg_lite_path.h" +#include "lv_draw_vg_lite_type.h" + +/********************* + * DEFINES + *********************/ + +#define PATH_QUALITY VG_LITE_MEDIUM +#define PATH_DATA_COORD_FORMAT VG_LITE_S16 +#define FT_F26DOT6_SHIFT 6 + +/** After converting the font reference size, it is also necessary to scale the 26dot6 data + * in the path to the real physical size + */ +#define FT_F26DOT6_TO_PATH_SCALE(x) (LV_FREETYPE_F26DOT6_TO_FLOAT(x) / (1 << FT_F26DOT6_SHIFT)) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void draw_letter_cb(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc, + lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area); + +static void draw_letter_bitmap(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_dsc_t * dsc); + +#if LV_USE_FREETYPE + static void freetype_outline_event_cb(lv_event_t * e); + static void draw_letter_outline(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_dsc_t * dsc); +#endif /* LV_USE_FREETYPE */ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vg_lite_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, + const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) return; + +#if LV_USE_FREETYPE + static bool is_init = false; + if(!is_init) { + lv_freetype_outline_add_event(freetype_outline_event_cb, LV_EVENT_ALL, draw_unit); + is_init = true; + } +#endif /* LV_USE_FREETYPE */ + + lv_draw_label_iterate_characters(draw_unit, dsc, coords, draw_letter_cb); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void draw_letter_cb(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc, + lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area) +{ + lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit; + if(glyph_draw_dsc) { + + switch(glyph_draw_dsc->format) { + case LV_DRAW_LETTER_BITMAP_FORMAT_A8: { + draw_letter_bitmap(u, glyph_draw_dsc); + } + break; + +#if LV_USE_FREETYPE + case LV_DRAW_LETTER_VECTOR_FORMAT: { + if(lv_freetype_is_outline_font(glyph_draw_dsc->g->resolved_font)) { + draw_letter_outline(u, glyph_draw_dsc); + } + } + break; +#endif /* LV_USE_FREETYPE */ + + case LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE: { + lv_draw_image_dsc_t img_dsc; + lv_draw_image_dsc_init(&img_dsc); + img_dsc.opa = glyph_draw_dsc->opa; + img_dsc.src = glyph_draw_dsc->glyph_data; + lv_draw_vg_lite_img(draw_unit, &img_dsc, glyph_draw_dsc->letter_coords, false); + } + break; + +#if LV_USE_FONT_PLACEHOLDER + case LV_DRAW_LETTER_BITMAP_FORMAT_INVALID: { + /* Draw a placeholder rectangle*/ + lv_draw_border_dsc_t border_draw_dsc; + lv_draw_border_dsc_init(&border_draw_dsc); + border_draw_dsc.opa = glyph_draw_dsc->opa; + border_draw_dsc.color = glyph_draw_dsc->color; + border_draw_dsc.width = 1; + lv_draw_vg_lite_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords); + } + break; +#endif /* LV_USE_FONT_PLACEHOLDER */ + + default: + break; + } + } + + if(fill_draw_dsc && fill_area) { + lv_draw_vg_lite_fill(draw_unit, fill_draw_dsc, fill_area); + } +} + +static void draw_letter_bitmap(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_dsc_t * dsc) +{ + lv_area_t clip_area; + if(!_lv_area_intersect(&clip_area, u->base_unit.clip_area, dsc->letter_coords)) { + return; + } + + lv_area_t image_area = *dsc->letter_coords; + + vg_lite_matrix_t matrix; + vg_lite_identity(&matrix); + lv_vg_lite_matrix_multiply(&matrix, &u->global_matrix); + vg_lite_translate(image_area.x1, image_area.y1, &matrix); + + vg_lite_buffer_t src_buf; + lv_draw_buf_t * draw_buf = dsc->glyph_data; + lv_vg_lite_buffer_from_draw_buf(&src_buf, draw_buf); + + vg_lite_color_t color; + color = lv_vg_lite_color(dsc->color, dsc->opa, true); + + LV_VG_LITE_ASSERT_SRC_BUFFER(&src_buf); + LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer); + + /* If clipping is not required, blit directly */ + if(_lv_area_is_in(&image_area, u->base_unit.clip_area, false)) { + /* The image area is the coordinates relative to the image itself */ + lv_area_t src_area = image_area; + lv_area_move(&src_area, -image_area.x1, -image_area.y1); + + /* rect is used to crop the pixel-aligned padding area */ + vg_lite_rectangle_t rect; + lv_vg_lite_rect(&rect, &src_area); + LV_VG_LITE_CHECK_ERROR(vg_lite_blit_rect( + &u->target_buffer, + &src_buf, + &rect, + &matrix, + VG_LITE_BLEND_SRC_OVER, + color, + VG_LITE_FILTER_LINEAR)); + } + else { + lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_S16); + lv_vg_lite_path_append_rect( + path, + clip_area.x1, clip_area.y1, + lv_area_get_width(&clip_area), lv_area_get_height(&clip_area), + 0, 0); + lv_vg_lite_path_set_bonding_box_area(path, &clip_area); + lv_vg_lite_path_end(path); + + vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path); + LV_VG_LITE_ASSERT_PATH(vg_lite_path); + + vg_lite_matrix_t path_matrix; + vg_lite_identity(&path_matrix); + + LV_VG_LITE_CHECK_ERROR(vg_lite_draw_pattern( + &u->target_buffer, + vg_lite_path, + VG_LITE_FILL_EVEN_ODD, + &path_matrix, + &src_buf, + &matrix, + VG_LITE_BLEND_SRC_OVER, + VG_LITE_PATTERN_COLOR, + color, + color, + VG_LITE_FILTER_LINEAR)); + + lv_vg_lite_path_drop(u, path); + } + + /* TODO: The temporary buffer of the built-in font is reused. + * You need to wait for the GPU to finish using the buffer before releasing it. + * Later, use the font cache for management to improve efficiency. + */ + LV_VG_LITE_CHECK_ERROR(vg_lite_finish()); +} + +#if LV_USE_FREETYPE + +static void draw_letter_outline(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_dsc_t * dsc) +{ + /* get clip area */ + lv_area_t path_clip_area; + if(!_lv_area_intersect(&path_clip_area, u->base_unit.clip_area, dsc->letter_coords)) { + return; + } + + /* vg-lite bounding_box will crop the pixels on the edge, so +1px is needed here */ + path_clip_area.x2++; + path_clip_area.y2++; + + lv_vg_lite_path_t * outline = (lv_vg_lite_path_t *)dsc->glyph_data; + lv_point_t pos = {dsc->letter_coords->x1, dsc->letter_coords->y1}; + + /* calc convert matrix */ + float scale = FT_F26DOT6_TO_PATH_SCALE(lv_freetype_outline_get_scale(dsc->g->resolved_font)); + vg_lite_matrix_t matrix; + vg_lite_identity(&matrix); + + /* convert to vg-lite coordinate */ + vg_lite_translate(pos.x - dsc->g->ofs_x, pos.y + dsc->g->box_h + dsc->g->ofs_y, &matrix); + + /* scale size */ + vg_lite_scale(scale, scale, &matrix); + + /* Cartesian coordinates to LCD coordinates */ + lv_vg_lite_matrix_flip_y(&matrix); + + /* calc inverse matrix */ + vg_lite_matrix_t result; + if(!lv_vg_lite_matrix_inverse(&result, &matrix)) { + LV_LOG_ERROR("no inverse matrix"); + return; + } + + lv_point_precise_t p1 = { path_clip_area.x1, path_clip_area.y1 }; + lv_point_precise_t p1_res = lv_vg_lite_matrix_transform_point(&result, &p1); + + lv_point_precise_t p2 = { path_clip_area.x2, path_clip_area.y2 }; + lv_point_precise_t p2_res = lv_vg_lite_matrix_transform_point(&result, &p2); + + /* Since the font uses Cartesian coordinates, the y coordinates need to be reversed */ + lv_vg_lite_path_set_bonding_box(outline, p1_res.x, p2_res.y, p2_res.x, p1_res.y); + + /* Move to the position relative to the first address of the buffer */ + lv_layer_t * layer = u->base_unit.target_layer; + vg_lite_translate(-layer->buf_area.x1 / scale, layer->buf_area.y1 / scale, &matrix); + + vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(outline); + + LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer); + LV_VG_LITE_ASSERT_PATH(vg_lite_path); + LV_VG_LITE_CHECK_ERROR(vg_lite_draw( + &u->target_buffer, vg_lite_path, VG_LITE_FILL_NON_ZERO, + &matrix, VG_LITE_BLEND_SRC_OVER, lv_vg_lite_color(dsc->color, dsc->opa, true))); +} + +static void vg_lite_outline_push(const lv_freetype_outline_event_param_t * param) +{ + lv_vg_lite_path_t * outline = param->outline; + LV_ASSERT_NULL(outline); + + lv_freetype_outline_type_t type = param->type; + switch(type) { + case LV_FREETYPE_OUTLINE_END: + lv_vg_lite_path_end(outline); + break; + case LV_FREETYPE_OUTLINE_MOVE_TO: + lv_vg_lite_path_move_to(outline, param->to.x, param->to.y); + break; + case LV_FREETYPE_OUTLINE_LINE_TO: + lv_vg_lite_path_line_to(outline, param->to.x, param->to.y); + break; + case LV_FREETYPE_OUTLINE_CUBIC_TO: + lv_vg_lite_path_cubic_to(outline, param->control1.x, param->control1.y, + param->control2.x, param->control2.y, + param->to.x, param->to.y); + break; + case LV_FREETYPE_OUTLINE_CONIC_TO: + lv_vg_lite_path_quad_to(outline, param->control1.x, param->control1.y, + param->to.x, param->to.y); + break; + default: + LV_LOG_ERROR("unknown point type: %d", type); + LV_ASSERT(false); + break; + } +} + +static void freetype_outline_event_cb(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_freetype_outline_event_param_t * param = lv_event_get_param(e); + switch(code) { + case LV_EVENT_CREATE: + param->outline = lv_vg_lite_path_create(PATH_DATA_COORD_FORMAT); + break; + case LV_EVENT_DELETE: + lv_vg_lite_path_destroy(param->outline); + break; + case LV_EVENT_INSERT: + vg_lite_outline_push(param); + break; + default: + LV_LOG_WARN("unknown event code: %d", code); + break; + } +} + +#endif /* LV_USE_FREETYPE */ + +#endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_layer.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_layer.c new file mode 100644 index 000000000..9476c6c02 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_layer.c @@ -0,0 +1,63 @@ +/** + * @file lv_draw_vg_lite_layer.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vg_lite.h" + +#if LV_USE_DRAW_VG_LITE + +#include "lv_vg_lite_utils.h" +#include "lv_draw_vg_lite_type.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vg_lite_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords) +{ + lv_layer_t * layer = (lv_layer_t *)draw_dsc->src; + + /*It can happen that nothing was draw on a layer and therefore its buffer is not allocated. + *In this case just return. */ + if(layer->draw_buf == NULL) + return; + + /* The GPU output should already be premultiplied RGB */ + layer->draw_buf->header.flags |= LV_IMAGE_FLAGS_PREMULTIPLIED; + + lv_draw_image_dsc_t new_draw_dsc = *draw_dsc; + new_draw_dsc.src = layer->draw_buf; + lv_draw_vg_lite_img(draw_unit, &new_draw_dsc, coords, true); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_line.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_line.c new file mode 100644 index 000000000..26d9d9f4a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_line.c @@ -0,0 +1,211 @@ +/** + * @file lv_draw_vg_lite_line.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vg_lite.h" + +#if LV_USE_DRAW_VG_LITE + +#include "lv_draw_vg_lite_type.h" +#include "lv_vg_lite_math.h" +#include "lv_vg_lite_path.h" +#include "lv_vg_lite_utils.h" + +/********************* + * DEFINES + *********************/ + +#define SQ(x) ((x) * (x)) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vg_lite_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc) +{ + if(dsc->opa <= LV_OPA_MIN) + return; + if(dsc->width == 0) + return; + + float p1_x = dsc->p1.x; + float p1_y = dsc->p1.y; + float p2_x = dsc->p2.x; + float p2_y = dsc->p2.y; + + if(p1_x == p2_x && p1_y == p2_y) + return; + + float half_w = dsc->width * 0.5f; + + lv_area_t rel_clip_area; + rel_clip_area.x1 = (int32_t)(LV_MIN(p1_x, p2_x) - half_w); + rel_clip_area.x2 = (int32_t)(LV_MAX(p1_x, p2_x) + half_w); + rel_clip_area.y1 = (int32_t)(LV_MIN(p1_y, p2_y) - half_w); + rel_clip_area.y2 = (int32_t)(LV_MAX(p1_y, p2_y) + half_w); + + if(!_lv_area_intersect(&rel_clip_area, &rel_clip_area, draw_unit->clip_area)) { + return; /*Fully clipped, nothing to do*/ + } + + lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit; + + int32_t dash_width = dsc->dash_width; + int32_t dash_gap = dsc->dash_gap; + int32_t dash_l = dash_width + dash_gap; + + float dx = p2_x - p1_x; + float dy = p2_y - p1_y; + float inv_dl = math_fast_inv_sqrtf(SQ(dx) + SQ(dy)); + float w_dx = dsc->width * dy * inv_dl; + float w_dy = dsc->width * dx * inv_dl; + float w2_dx = w_dx / 2; + float w2_dy = w_dy / 2; + + int32_t ndash = 0; + if(dash_width && dash_l * inv_dl < 1.0f) { + ndash = (int32_t)((1.0f / inv_dl + dash_l - 1) / dash_l); + } + + lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_FP32); + lv_vg_lite_path_set_quality(path, VG_LITE_MEDIUM); + lv_vg_lite_path_set_bonding_box_area(path, &rel_clip_area); + + /* head point */ + float head_start_x = p1_x + w2_dx; + float head_start_y = p1_y - w2_dy; + float head_end_x = p1_x - w2_dx; + float head_end_y = p1_y + w2_dy; + + /* tali point */ + float tali_start_x = p2_x - w2_dx; + float tali_start_y = p2_y + w2_dy; + float tali_end_x = p2_x + w2_dx; + float tali_end_y = p2_y - w2_dy; + + /* + head_start tali_end + *-----------------* + /| |\ + / | | \ + arc_c *( *p1 p2* )* arc_c + \ | | / + \| |/ + *-----------------* + head_end tali_start + */ + + /* move to start point */ + lv_vg_lite_path_move_to(path, head_start_x, head_start_y); + + /* draw line head */ + if(dsc->round_start) { + float arc_cx = p1_x - w2_dy; + float arc_cy = p1_y - w2_dx; + + /* start 90deg arc */ + lv_vg_lite_path_append_arc_right_angle(path, + head_start_x, head_start_y, + p1_x, p1_y, + arc_cx, arc_cy); + + /* end 90deg arc */ + lv_vg_lite_path_append_arc_right_angle(path, + arc_cx, arc_cy, + p1_x, p1_y, + head_end_x, head_end_y); + } + else { + lv_vg_lite_path_line_to(path, head_end_x, head_end_y); + } + + /* draw line body */ + lv_vg_lite_path_line_to(path, tali_start_x, tali_start_y); + + /* draw line tail */ + if(dsc->round_end) { + float arc_cx = p2_x + w2_dy; + float arc_cy = p2_y + w2_dx; + lv_vg_lite_path_append_arc_right_angle(path, + tali_start_x, tali_start_y, + p2_x, p2_y, + arc_cx, arc_cy); + lv_vg_lite_path_append_arc_right_angle(path, + arc_cx, arc_cy, + p2_x, p2_y, + tali_end_x, tali_end_y); + } + else { + lv_vg_lite_path_line_to(path, tali_end_x, tali_end_y); + } + + /* close draw line body */ + lv_vg_lite_path_line_to(path, head_start_x, head_start_y); + + for(int32_t i = 0; i < ndash; i++) { + float start_x = p1_x - w2_dx + dx * (i * dash_l + dash_width) * inv_dl; + float start_y = p1_y + w2_dy + dy * (i * dash_l + dash_width) * inv_dl; + + lv_vg_lite_path_move_to(path, start_x, start_y); + lv_vg_lite_path_line_to(path, + p1_x + w2_dx + dx * (i * dash_l + dash_width) * inv_dl, + p1_y - w2_dy + dy * (i * dash_l + dash_width) * inv_dl); + lv_vg_lite_path_line_to(path, + p1_x + w2_dx + dx * (i + 1) * dash_l * inv_dl, + p1_y - w2_dy + dy * (i + 1) * dash_l * inv_dl); + lv_vg_lite_path_line_to(path, + p1_x - w2_dx + dx * (i + 1) * dash_l * inv_dl, + p1_y + w2_dy + dy * (i + 1) * dash_l * inv_dl); + lv_vg_lite_path_line_to(path, start_x, start_y); + } + + lv_vg_lite_path_end(path); + + vg_lite_matrix_t matrix; + vg_lite_identity(&matrix); + lv_vg_lite_matrix_multiply(&matrix, &u->global_matrix); + + vg_lite_color_t color = lv_vg_lite_color(dsc->color, dsc->opa, true); + + vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path); + + LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer); + LV_VG_LITE_ASSERT_PATH(vg_lite_path); + + LV_VG_LITE_CHECK_ERROR(vg_lite_draw( + &u->target_buffer, + vg_lite_path, + VG_LITE_FILL_EVEN_ODD, + &matrix, + VG_LITE_BLEND_SRC_OVER, + color)); + + lv_vg_lite_path_drop(u, path); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_mask_rect.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_mask_rect.c new file mode 100644 index 000000000..ef9b7658a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_mask_rect.c @@ -0,0 +1,94 @@ +/** + * @file lv_draw_vg_lite_rect.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vg_lite.h" + +#if LV_USE_DRAW_VG_LITE + +#include "lv_vg_lite_utils.h" +#include "lv_draw_vg_lite_type.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vg_lite_mask_rect(lv_draw_unit_t * draw_unit, const lv_draw_mask_rect_dsc_t * dsc, + const lv_area_t * coords) +{ + LV_UNUSED(coords); + + lv_area_t draw_area; + if(!_lv_area_intersect(&draw_area, &dsc->area, draw_unit->clip_area)) { + return; + } + + lv_draw_sw_mask_radius_param_t param; + lv_draw_sw_mask_radius_init(¶m, &dsc->area, dsc->radius, false); + + void * masks[2] = {0}; + masks[0] = ¶m; + + uint32_t area_w = lv_area_get_width(&draw_area); + lv_opa_t * mask_buf = lv_malloc(area_w); + + int32_t y; + for(y = draw_area.y1; y <= draw_area.y2; y++) { + lv_memset(mask_buf, 0xff, area_w); + lv_draw_sw_mask_res_t res = lv_draw_sw_mask_apply(masks, mask_buf, draw_area.x1, y, area_w); + if(res == LV_DRAW_SW_MASK_RES_FULL_COVER) continue; + + lv_layer_t * target_layer = draw_unit->target_layer; + lv_color32_t * c32_buf = lv_draw_layer_go_to_xy(target_layer, draw_area.x1 - target_layer->buf_area.x1, + y - target_layer->buf_area.y1); + + if(res == LV_DRAW_SW_MASK_RES_TRANSP) { + lv_memzero(c32_buf, area_w * sizeof(lv_color32_t)); + } + else { + uint32_t i; + for(i = 0; i < area_w; i++) { + if(mask_buf[i] != LV_OPA_COVER) { + c32_buf[i].alpha = LV_OPA_MIX2(c32_buf[i].alpha, mask_buf[i]); + } + + /*Pre-multiply the alpha*/ + lv_color_premultiply(&c32_buf[i]); + } + } + } + + lv_free(mask_buf); + lv_draw_sw_mask_free_param(¶m); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_triangle.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_triangle.c new file mode 100644 index 000000000..6dd90d7c4 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_triangle.c @@ -0,0 +1,104 @@ +/** + * @file lv_draw_vg_lite_triangle.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vg_lite.h" + +#if LV_USE_DRAW_VG_LITE + +#include "lv_vg_lite_utils.h" +#include "lv_vg_lite_path.h" +#include "lv_draw_vg_lite_type.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vg_lite_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc) +{ + if(dsc->bg_opa <= LV_OPA_MIN) return; + + lv_area_t tri_area; + tri_area.x1 = (int32_t)LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + tri_area.y1 = (int32_t)LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); + tri_area.x2 = (int32_t)LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + tri_area.y2 = (int32_t)LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); + + bool is_common; + lv_area_t clip_area; + is_common = _lv_area_intersect(&clip_area, &tri_area, draw_unit->clip_area); + if(!is_common) return; + + lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit; + + lv_vg_lite_path_t * path = lv_vg_lite_path_get(u, VG_LITE_FP32); + lv_vg_lite_path_set_bonding_box_area(path, &clip_area); + lv_vg_lite_path_move_to(path, dsc->p[0].x, dsc->p[0].y); + lv_vg_lite_path_line_to(path, dsc->p[1].x, dsc->p[1].y); + lv_vg_lite_path_line_to(path, dsc->p[2].x, dsc->p[2].y); + lv_vg_lite_path_close(path); + lv_vg_lite_path_end(path); + + vg_lite_path_t * vg_lite_path = lv_vg_lite_path_get_path(path); + + LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer); + LV_VG_LITE_ASSERT_PATH(vg_lite_path); + + vg_lite_matrix_t matrix; + vg_lite_identity(&matrix); + lv_vg_lite_matrix_multiply(&matrix, &u->global_matrix); + + if(dsc->bg_grad.dir != LV_GRAD_DIR_NONE) { + lv_vg_lite_draw_linear_grad( + &u->target_buffer, + vg_lite_path, + &tri_area, + &dsc->bg_grad, + &matrix, + VG_LITE_FILL_EVEN_ODD, + VG_LITE_BLEND_SRC_OVER); + } + else { /* normal fill */ + vg_lite_color_t color = lv_vg_lite_color(dsc->bg_color, dsc->bg_opa, true); + LV_VG_LITE_CHECK_ERROR(vg_lite_draw( + &u->target_buffer, + vg_lite_path, + VG_LITE_FILL_EVEN_ODD, + &matrix, + VG_LITE_BLEND_SRC_OVER, + color)); + } + + lv_vg_lite_path_drop(u, path); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_type.h b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_type.h new file mode 100644 index 000000000..59da4122b --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_type.h @@ -0,0 +1,60 @@ +/** + * @file lv_draw_vg_lite_type.h + * + */ + +#ifndef LV_DRAW_VG_LITE_TYPE_H +#define LV_DRAW_VG_LITE_TYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_DRAW_VG_LITE + +#include "../lv_draw.h" + +#if LV_USE_VG_LITE_THORVG +#include "../../others/vg_lite_tvg/vg_lite.h" +#else +#include +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_draw_vg_lite_unit_t { + lv_draw_unit_t base_unit; + lv_draw_task_t * task_act; + vg_lite_buffer_t target_buffer; + vg_lite_matrix_t global_matrix; + struct _lv_vg_lite_path_t * global_path; + bool path_in_use; +}; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_VG_LITE_DRAW_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_vector.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_vector.c new file mode 100644 index 000000000..1326588c6 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_draw_vg_lite_vector.c @@ -0,0 +1,338 @@ +/** + * @file lv_draw_vg_lite_vector.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_draw_vg_lite.h" + +#if LV_USE_DRAW_VG_LITE && LV_USE_VECTOR_GRAPHIC + +#include "lv_draw_vg_lite_type.h" +#include "lv_vg_lite_path.h" +#include "lv_vg_lite_utils.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vector_draw_dsc_t * dsc); +static void lv_matrix_to_vg(vg_lite_matrix_t * desy, const lv_matrix_t * src); +static void lv_path_to_vg(lv_vg_lite_path_t * dest, const lv_vector_path_t * src); +static vg_lite_blend_t lv_blend_to_vg(lv_vector_blend_t blend); +static vg_lite_fill_t lv_fill_to_vg(lv_vector_fill_t fill_rule); +static vg_lite_gradient_spreadmode_t lv_spread_to_vg(lv_vector_gradient_spread_t spread); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_vg_lite_vector(lv_draw_unit_t * draw_unit, const lv_draw_vector_task_dsc_t * dsc) +{ + if(dsc->task_list == NULL) + return; + + lv_layer_t * layer = dsc->base.layer; + if(layer->draw_buf == NULL) + return; + + _lv_vector_for_each_destroy_tasks(dsc->task_list, task_draw_cb, draw_unit); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static vg_lite_color_t lv_color32_to_vg(lv_color32_t color, lv_opa_t opa) +{ + uint8_t a = LV_OPA_MIX2(color.alpha, opa); + if(a < LV_OPA_MAX) { + color.red = LV_UDIV255(color.red * opa); + color.green = LV_UDIV255(color.green * opa); + color.blue = LV_UDIV255(color.blue * opa); + } + return (uint32_t)a << 24 | (uint32_t)color.blue << 16 | (uint32_t)color.green << 8 | color.red; +} + +static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vector_draw_dsc_t * dsc) +{ + lv_draw_vg_lite_unit_t * u = ctx; + LV_VG_LITE_ASSERT_DEST_BUFFER(&u->target_buffer); + + /* clear area */ + if(!path) { + /* clear color needs to ignore fill_dsc.opa */ + vg_lite_color_t c = lv_color32_to_vg(dsc->fill_dsc.color, LV_OPA_COVER); + vg_lite_rectangle_t rect; + lv_vg_lite_rect(&rect, &dsc->scissor_area); + LV_VG_LITE_CHECK_ERROR(vg_lite_clear(&u->target_buffer, &rect, c)); + return; + } + + /* set scissor area */ + lv_vg_lite_set_scissor_area(&dsc->scissor_area); + + /* convert color */ + vg_lite_color_t vg_color = lv_color32_to_vg(dsc->fill_dsc.color, dsc->fill_dsc.opa); + + /* transform matrix */ + vg_lite_matrix_t matrix; + lv_matrix_to_vg(&matrix, &dsc->matrix); + + /* convert path */ + lv_vg_lite_path_t * lv_vg_path = lv_vg_lite_path_get(u, VG_LITE_FP32); + lv_path_to_vg(lv_vg_path, path); + vg_lite_path_t * vg_path = lv_vg_lite_path_get_path(lv_vg_path); + LV_VG_LITE_ASSERT_PATH(vg_path); + + /* convert blend mode and fill rule */ + vg_lite_blend_t blend = lv_blend_to_vg(dsc->blend_mode); + vg_lite_fill_t fill = lv_fill_to_vg(dsc->fill_dsc.fill_rule); + + /* get path bounds */ + float min_x, min_y, max_x, max_y; + lv_vg_lite_path_get_bonding_box(lv_vg_path, &min_x, &min_y, &max_x, &max_y); + + switch(dsc->fill_dsc.style) { + case LV_VECTOR_DRAW_STYLE_SOLID: { + /* normal draw shape */ + LV_VG_LITE_CHECK_ERROR(vg_lite_draw( + &u->target_buffer, + vg_path, + fill, + &matrix, + blend, + vg_color)); + } + break; + case LV_VECTOR_DRAW_STYLE_PATTERN: { + /* draw image */ + vg_lite_buffer_t image_buffer; + lv_image_decoder_dsc_t decoder_dsc; + if(lv_vg_lite_buffer_open_image(&image_buffer, &decoder_dsc, dsc->fill_dsc.img_dsc.src, false)) { + lv_matrix_t m = dsc->matrix; + lv_matrix_translate(&m, min_x, min_y); + lv_matrix_multiply(&m, &dsc->fill_dsc.matrix); + + vg_lite_matrix_t src_matrix; + lv_matrix_to_vg(&src_matrix, &m); + + vg_lite_matrix_t path_matrix; + vg_lite_identity(&path_matrix); + + vg_lite_color_t recolor = lv_vg_lite_color(dsc->fill_dsc.img_dsc.recolor, dsc->fill_dsc.img_dsc.recolor_opa, true); + + LV_VG_LITE_CHECK_ERROR(vg_lite_draw_pattern( + &u->target_buffer, + vg_path, + fill, + &path_matrix, + &image_buffer, + &src_matrix, + blend, + VG_LITE_PATTERN_COLOR, + recolor, + vg_color, + VG_LITE_FILTER_BI_LINEAR)); + lv_image_decoder_close(&decoder_dsc); + } + } + break; + case LV_VECTOR_DRAW_STYLE_GRADIENT: { + /* draw gradient */ + lv_area_t grad_area; + lv_area_set(&grad_area, (int32_t)min_x, (int32_t)min_y, (int32_t)max_x, (int32_t)max_y); + lv_vector_gradient_style_t style = dsc->fill_dsc.gradient.style; + vg_lite_gradient_spreadmode_t spreadmode = lv_spread_to_vg(dsc->fill_dsc.gradient.spread); + LV_UNUSED(spreadmode); + + if(style == LV_VECTOR_GRADIENT_STYLE_LINEAR) { + lv_vg_lite_draw_linear_grad( + &u->target_buffer, + vg_path, + &grad_area, + &dsc->fill_dsc.gradient.grad, + &matrix, + fill, + blend); + } + else if(style == LV_VECTOR_GRADIENT_STYLE_RADIAL) { + if(vg_lite_query_feature(gcFEATURE_BIT_VG_RADIAL_GRADIENT)) { + /* TODO: radial gradient */ + } + else { + LV_LOG_WARN("radial gradient is not supported"); + } + } + } + break; + default: + LV_LOG_WARN("unknown style: %d", dsc->fill_dsc.style); + break; + } + + /* drop path */ + lv_vg_lite_path_drop(u, lv_vg_path); + + /* disable scissor */ + lv_vg_lite_disable_scissor(); +} + +static void lv_matrix_to_vg(vg_lite_matrix_t * dest, const lv_matrix_t * src) +{ + lv_memcpy(dest, src, sizeof(lv_matrix_t)); +} + +static vg_lite_quality_t lv_quality_to_vg(lv_vector_path_quality_t quality) +{ + switch(quality) { + case LV_VECTOR_PATH_QUALITY_LOW: + return VG_LITE_LOW; + case LV_VECTOR_PATH_QUALITY_MEDIUM: + return VG_LITE_MEDIUM; + case LV_VECTOR_PATH_QUALITY_HIGH: + return VG_LITE_HIGH; + default: + return VG_LITE_MEDIUM; + } +} + +static void lv_path_to_vg(lv_vg_lite_path_t * dest, const lv_vector_path_t * src) +{ + lv_vg_lite_path_set_quality(dest, lv_quality_to_vg(src->quality)); + + /* init bounds */ + float min_x = __FLT_MAX__; + float min_y = __FLT_MAX__; + float max_x = __FLT_MIN__; + float max_y = __FLT_MIN__; + +#define CMP_BOUNDS(point) \ + do { \ + if((point)->x < min_x) min_x = (point)->x; \ + if((point)->y < min_y) min_y = (point)->y; \ + if((point)->x > max_x) max_x = (point)->x; \ + if((point)->y > max_y) max_y = (point)->y; \ + } while(0) + + uint32_t pidx = 0; + for(uint32_t i = 0; i < src->ops.size; i++) { + lv_vector_path_op_t * op = lv_array_at(&src->ops, i); + switch(*op) { + case LV_VECTOR_PATH_OP_MOVE_TO: { + const lv_fpoint_t * pt = lv_array_at(&src->points, pidx); + CMP_BOUNDS(pt); + lv_vg_lite_path_move_to(dest, pt->x, pt->y); + pidx += 1; + } + break; + case LV_VECTOR_PATH_OP_LINE_TO: { + const lv_fpoint_t * pt = lv_array_at(&src->points, pidx); + CMP_BOUNDS(pt); + lv_vg_lite_path_line_to(dest, pt->x, pt->y); + pidx += 1; + } + break; + case LV_VECTOR_PATH_OP_QUAD_TO: { + const lv_fpoint_t * pt1 = lv_array_at(&src->points, pidx); + const lv_fpoint_t * pt2 = lv_array_at(&src->points, pidx + 1); + CMP_BOUNDS(pt1); + CMP_BOUNDS(pt2); + lv_vg_lite_path_quad_to(dest, pt1->x, pt1->y, pt2->x, pt2->y); + pidx += 2; + } + break; + case LV_VECTOR_PATH_OP_CUBIC_TO: { + const lv_fpoint_t * pt1 = lv_array_at(&src->points, pidx); + const lv_fpoint_t * pt2 = lv_array_at(&src->points, pidx + 1); + const lv_fpoint_t * pt3 = lv_array_at(&src->points, pidx + 2); + CMP_BOUNDS(pt1); + CMP_BOUNDS(pt2); + CMP_BOUNDS(pt3); + lv_vg_lite_path_cubic_to(dest, pt1->x, pt1->y, pt2->x, pt2->y, pt3->x, pt3->y); + pidx += 3; + } + break; + case LV_VECTOR_PATH_OP_CLOSE: { + lv_vg_lite_path_close(dest); + } + break; + } + } + + lv_vg_lite_path_end(dest); + lv_vg_lite_path_set_bonding_box(dest, min_x, min_y, max_x, max_y); +} + +static vg_lite_blend_t lv_blend_to_vg(lv_vector_blend_t blend) +{ + switch(blend) { + case LV_VECTOR_BLEND_SRC_OVER: + return VG_LITE_BLEND_SRC_OVER; + case LV_VECTOR_BLEND_SCREEN: + return VG_LITE_BLEND_SCREEN; + case LV_VECTOR_BLEND_MULTIPLY: + return VG_LITE_BLEND_MULTIPLY; + case LV_VECTOR_BLEND_NONE: + return VG_LITE_BLEND_NONE; + case LV_VECTOR_BLEND_ADDITIVE: + return VG_LITE_BLEND_ADDITIVE; + case LV_VECTOR_BLEND_SRC_IN: + return VG_LITE_BLEND_SRC_IN; + case LV_VECTOR_BLEND_DST_OVER: + return VG_LITE_BLEND_DST_OVER; + case LV_VECTOR_BLEND_DST_IN: + return VG_LITE_BLEND_DST_IN; + case LV_VECTOR_BLEND_SUBTRACTIVE: + return VG_LITE_BLEND_SUBTRACT; + default: + return VG_LITE_BLEND_SRC_OVER; + } +} + +static vg_lite_fill_t lv_fill_to_vg(lv_vector_fill_t fill_rule) +{ + switch(fill_rule) { + case LV_VECTOR_FILL_NONZERO: + return VG_LITE_FILL_NON_ZERO; + case LV_VECTOR_FILL_EVENODD: + return VG_LITE_FILL_EVEN_ODD; + default: + return VG_LITE_FILL_NON_ZERO; + } +} + +static vg_lite_gradient_spreadmode_t lv_spread_to_vg(lv_vector_gradient_spread_t spread) +{ + switch(spread) { + case LV_VECTOR_GRADIENT_SPREAD_PAD: + return VG_LITE_GRADIENT_SPREAD_PAD; + case LV_VECTOR_GRADIENT_SPREAD_REPEAT: + return VG_LITE_GRADIENT_SPREAD_REPEAT; + case LV_VECTOR_GRADIENT_SPREAD_REFLECT: + return VG_LITE_GRADIENT_SPREAD_REFLECT; + default: + return VG_LITE_GRADIENT_SPREAD_FILL; + } +} + +#endif /*LV_USE_DRAW_VG_LITE && LV_USE_VECTOR_GRAPHIC*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_decoder.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_decoder.c new file mode 100644 index 000000000..59dc6f754 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_decoder.c @@ -0,0 +1,443 @@ +/** + * @file lv_vg_lite_decoder.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_vg_lite_decoder.h" + +#if LV_USE_DRAW_VG_LITE + +#include "lv_vg_lite_utils.h" + +/********************* + * DEFINES + *********************/ + +#define LV_VG_LITE_IMAGE_NO_CACHE LV_IMAGE_FLAGS_USER1 + +/********************** + * TYPEDEFS + **********************/ + +#pragma pack(1) + +typedef struct { + lv_color16_t c; + uint8_t alpha; +} lv_color16_alpha_t; + +#pragma pack() + +/********************** + * STATIC PROTOTYPES + **********************/ + +static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); +static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); +static void decoder_cache_free(lv_image_cache_data_t * cached_data, void * user_data); +static void image_try_self_pre_mul(lv_image_decoder_dsc_t * dsc); +static void image_color32_pre_mul(lv_color32_t * img_data, uint32_t px_size); +static void image_color16_pre_mul(lv_color16_alpha_t * img_data, uint32_t px_size); +static void image_copy(uint8_t * dest, const uint8_t * src, + size_t dest_stride, size_t src_stride, + uint32_t height); +static void image_invalidate_cache(void * buf, uint32_t stride, + uint32_t width, uint32_t height, + lv_color_format_t cf); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_vg_lite_decoder_init(void) +{ + lv_image_decoder_t * decoder = lv_image_decoder_create(); + lv_image_decoder_set_info_cb(decoder, decoder_info); + lv_image_decoder_set_open_cb(decoder, decoder_open); + lv_image_decoder_set_close_cb(decoder, decoder_close); + lv_image_decoder_set_cache_free_cb(decoder, (lv_cache_free_cb_t)decoder_cache_free); +} + +void lv_vg_lite_decoder_deinit(void) +{ + lv_image_decoder_t * dec = NULL; + while((dec = lv_image_decoder_get_next(dec)) != NULL) { + if(dec->info_cb == decoder_info) { + lv_image_decoder_delete(dec); + break; + } + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void image_color32_pre_mul(lv_color32_t * img_data, uint32_t px_size) +{ + while(px_size--) { + img_data->red = LV_UDIV255(img_data->red * img_data->alpha); + img_data->green = LV_UDIV255(img_data->green * img_data->alpha); + img_data->blue = LV_UDIV255(img_data->blue * img_data->alpha); + img_data++; + } +} + +static void image_color16_pre_mul(lv_color16_alpha_t * img_data, uint32_t px_size) +{ + while(px_size--) { + img_data->c.red = LV_UDIV255(img_data->c.red * img_data->alpha); + img_data->c.green = LV_UDIV255(img_data->c.green * img_data->alpha); + img_data->c.blue = LV_UDIV255(img_data->c.blue * img_data->alpha); + img_data++; + } +} + +static void image_try_self_pre_mul(lv_image_decoder_dsc_t * dsc) +{ + /* !!! WARNING !!! + * self-premultiplied images + * should be width-aligned and in modifiable RAM + */ + if(lv_vg_lite_support_blend_normal()) { + return; + } + + if(dsc->header.flags & LV_IMAGE_FLAGS_PREMULTIPLIED) { + return; + } + + lv_color_format_t cf = dsc->header.cf; + if(!lv_color_format_has_alpha(cf)) { + return; + } + + int32_t image_w = dsc->header.w; + int32_t image_h = dsc->header.h; + uint32_t stride = lv_draw_buf_width_to_stride(image_w, cf); + uint32_t aligned_w = lv_vg_lite_width_align(image_w); + size_t px_size = aligned_w * image_h; + void * image_data = dsc->decoded->data; + + if(cf == LV_COLOR_FORMAT_ARGB8888) { + image_color32_pre_mul(image_data, px_size); + } + else if(cf == LV_COLOR_FORMAT_RGB565A8) { + image_color16_pre_mul(image_data, px_size); + } + else if(LV_COLOR_FORMAT_IS_INDEXED(cf)) { + lv_color32_t * palette = (lv_color32_t *)image_data; + uint32_t palette_size = LV_COLOR_INDEXED_PALETTE_SIZE(cf); + image_color32_pre_mul(palette, palette_size); + } + else if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf)) { + /* do nothing */ + } + else { + LV_LOG_WARN("unsupported cf: %d", cf); + } + + image_invalidate_cache(image_data, stride, image_w, image_h, cf); + + dsc->header.flags |= LV_IMAGE_FLAGS_PREMULTIPLIED; +} + +static void image_copy(uint8_t * dest, const uint8_t * src, + size_t dest_stride, size_t src_stride, + uint32_t height) +{ + for(uint32_t y = 0; y < height; y++) { + lv_memcpy(dest, src, src_stride); + src += src_stride; + dest += dest_stride; + } +} + +static void image_invalidate_cache(void * buf, uint32_t stride, + uint32_t width, uint32_t height, + lv_color_format_t cf) +{ + width = lv_vg_lite_width_align(width); + lv_area_t image_area; + lv_area_set(&image_area, 0, 0, width - 1, height - 1); + lv_draw_buf_invalidate_cache(buf, stride, cf, &image_area); +} + +static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) +{ + return lv_bin_decoder_info(decoder, src, header); +} + +static lv_result_t decoder_open_variable(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); /*Unused*/ + + lv_color_format_t cf = dsc->header.cf; + int32_t width = dsc->header.w; + int32_t height = dsc->header.h; + + /* native stride */ + uint32_t width_byte; + width_byte = width * lv_color_format_get_bpp(cf); + width_byte = (width_byte + 7) >> 3; /*Round up*/ + + bool support_blend_normal = lv_vg_lite_support_blend_normal(); + + /*In case of uncompressed formats the image stored in the ROM/RAM. + *So simply give its pointer*/ + const uint8_t * image_data = ((lv_image_dsc_t *)dsc->src)->data; + uint32_t image_data_size = ((lv_image_dsc_t *)dsc->src)->data_size; + + bool has_alpha = lv_color_format_has_alpha(cf); + bool is_indexed = LV_COLOR_FORMAT_IS_INDEXED(cf); + bool is_yuv = LV_COLOR_FORMAT_IS_YUV(cf); + bool is_addr_aligned = (image_data == lv_draw_buf_align((void *)image_data, cf)) ? true : false; + + uint32_t stride = lv_draw_buf_width_to_stride(width, cf); + bool is_stride_aligned = (stride == width_byte) ? true : false; + + /* When the following conditions are met, + * there is no need to copy image resource preprocessing. + */ + if((is_addr_aligned + && is_stride_aligned + && !is_indexed + && (!has_alpha || (has_alpha && support_blend_normal))) || is_yuv) { + + lv_draw_buf_t * draw_buf = lv_malloc_zeroed(sizeof(lv_draw_buf_t)); + LV_ASSERT_MALLOC(draw_buf); + lv_draw_buf_init(draw_buf, width, height, cf, stride, (void *)image_data, image_data_size); + dsc->decoded = draw_buf; + return LV_RESULT_OK; + } + + uint32_t palette_size = LV_COLOR_INDEXED_PALETTE_SIZE(cf); + uint32_t palette_size_bytes = palette_size * sizeof(lv_color32_t); + + /* Since the palette and index image are next to each other, + * the palette size needs to be aligned to ensure that the image is aligned. + */ + uint32_t palette_size_bytes_aligned = LV_VG_LITE_ALIGN(palette_size_bytes, LV_DRAW_BUF_ALIGN); + + lv_draw_buf_t * draw_buf = lv_draw_buf_create(width, height, cf, stride); + if(draw_buf == NULL) { + LV_LOG_ERROR("create draw buf failed, cf = %d", cf); + return LV_RESULT_INVALID; + } + + dsc->decoded = draw_buf; + + const uint8_t * src = image_data; + uint8_t * dest = draw_buf->data; + + /* copy palette */ + if(palette_size_bytes) { + lv_memcpy(dest, src, palette_size_bytes); + src += palette_size_bytes; + + /* move to align size */ + dest += palette_size_bytes_aligned; + } + + image_copy(dest, src, stride, width_byte, height); + + /* premul alpha */ + image_try_self_pre_mul(dsc); + + /* invalidate D-Cache */ + image_invalidate_cache(draw_buf->data, stride, width, height, cf); + + LV_LOG_INFO("image %p (W%" LV_PRId32 " x H%" LV_PRId32 ", buffer: %p, cf: %d) decode finish", + image_data, width, height, draw_buf->data, cf); + return LV_RESULT_OK; +} + +static lv_result_t decoder_open_file(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); /*Unused*/ + + lv_color_format_t cf = dsc->header.cf; + uint32_t width = dsc->header.w; + uint32_t height = dsc->header.h; + const char * path = dsc->src; + + lv_fs_file_t file; + lv_fs_res_t res = lv_fs_open(&file, path, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) { + LV_LOG_ERROR("open %s failed", path); + return LV_RESULT_INVALID; + } + + /* skip image header bytes */ + res = lv_fs_seek(&file, sizeof(lv_image_header_t), LV_FS_SEEK_SET); + if(res != LV_FS_RES_OK) { + LV_LOG_ERROR("seek %s lv_image_header_t failed", path); + lv_fs_close(&file); + return LV_RESULT_INVALID; + } + + /* native stride */ + uint32_t width_byte; + width_byte = width * lv_color_format_get_bpp(cf); + width_byte = (width_byte + 7) >> 3; /*Round up*/ + + bool support_blend_normal = lv_vg_lite_support_blend_normal(); + + uint32_t stride = lv_draw_buf_width_to_stride(width, cf); + + uint32_t palette_size = LV_COLOR_INDEXED_PALETTE_SIZE(cf); + uint32_t palette_size_bytes = palette_size * sizeof(lv_color32_t); + + /* Since the palette and index image are next to each other, + * the palette size needs to be aligned to ensure that the image is aligned. + */ + uint32_t palette_size_bytes_aligned = LV_VG_LITE_ALIGN(palette_size_bytes, LV_DRAW_BUF_ALIGN); + + lv_draw_buf_t * draw_buf = lv_draw_buf_create(width, height, cf, stride); + if(draw_buf == NULL) { + LV_LOG_ERROR("create draw buf failed, cf = %d", cf); + return LV_RESULT_INVALID; + } + + dsc->decoded = draw_buf; + uint8_t * dest = draw_buf->data; + + /* copy palette */ + if(palette_size_bytes) { + uint32_t br; + /* read palette */ + res = lv_fs_read(&file, dest, palette_size_bytes, &br); + if(res != LV_FS_RES_OK || br != palette_size_bytes) { + LV_LOG_ERROR("read %s (palette: %" LV_PRIu32 ", br: %" LV_PRIu32 ") failed", + path, palette_size_bytes, br); + goto failed; + } + + if(!support_blend_normal) { + image_color32_pre_mul((lv_color32_t *)dest, palette_size); + } + + /* move to index image map */ + dest += palette_size_bytes_aligned; + } + + for(uint32_t y = 0; y < height; y++) { + uint32_t br; + res = lv_fs_read(&file, dest, width_byte, &br); + if(res != LV_FS_RES_OK || br != width_byte) { + LV_LOG_ERROR("read %s (y: %" LV_PRIu32 ", width_byte: %" LV_PRIu32 ", br: %" LV_PRIu32 ") failed", + path, y, width_byte, br); + goto failed; + } + + dest += stride; + } + + lv_fs_close(&file); + + /* premul alpha */ + image_try_self_pre_mul(dsc); + + /* invalidate D-Cache */ + image_invalidate_cache(draw_buf->data, stride, width, height, cf); + + LV_LOG_INFO("image %s (W%" LV_PRId32 " x H%" LV_PRId32 ", buffer: %p cf: %d) decode finish", + path, width, height, draw_buf->data, cf); + return LV_RESULT_OK; + +failed: + lv_fs_close(&file); + lv_draw_buf_destroy(draw_buf); + dsc->decoded = NULL; + + return LV_RESULT_INVALID; +} + +/** + * Decode an image using the vg_lite gpu. + * @param decoder pointer to the decoder + * @param dsc pointer to the decoder descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image + */ +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + + lv_result_t res = LV_RESULT_INVALID; + + switch(dsc->src_type) { + case LV_IMAGE_SRC_VARIABLE: + res = decoder_open_variable(decoder, dsc); + break; + case LV_IMAGE_SRC_FILE: + res = decoder_open_file(decoder, dsc); + break; + default: + break; + } + + if(dsc->args.no_cache) return LV_RES_OK; + +#if LV_CACHE_DEF_SIZE > 0 + if(res == LV_RESULT_OK) { + lv_image_cache_data_t search_key; + search_key.src_type = dsc->src_type; + search_key.src = dsc->src; + search_key.slot.size = dsc->decoded->data_size; + + lv_cache_entry_t * entry = lv_image_decoder_add_to_cache(decoder, &search_key, dsc->decoded, NULL); + + if(entry == NULL) { + lv_draw_buf_destroy((lv_draw_buf_t *)dsc->decoded); + dsc->decoded = NULL; + return LV_RESULT_INVALID; + } + dsc->cache_entry = entry; + } +#endif + + return res; +} + +static void decoder_draw_buf_free(lv_draw_buf_t * draw_buf) +{ + if(draw_buf->header.flags & LV_VG_LITE_IMAGE_NO_CACHE) { + lv_free(draw_buf); + } + else { + lv_draw_buf_destroy(draw_buf); + } +} + +static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); /*Unused*/ + + if(dsc->args.no_cache || LV_CACHE_DEF_SIZE == 0) + lv_draw_buf_destroy((lv_draw_buf_t *)dsc->decoded); + else + lv_cache_release(dsc->cache, dsc->cache_entry, NULL); +} + +static void decoder_cache_free(lv_image_cache_data_t * cached_data, void * user_data) +{ + LV_UNUSED(user_data); + + if(cached_data->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)cached_data->src); + + decoder_draw_buf_free((lv_draw_buf_t *)cached_data->decoded); +} + +#endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.h b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_decoder.h similarity index 59% rename from lib/libesp32_lvgl/lvgl/src/extra/lv_extra.h rename to lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_decoder.h index c0306a980..9bab540c6 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.h +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_decoder.h @@ -1,10 +1,10 @@ /** - * @file lv_extra.h + * @file lv_vg_lite_decoder.h * */ -#ifndef LV_EXTRA_H -#define LV_EXTRA_H +#ifndef LV_VG_LITE_DECODER_H +#define LV_VG_LITE_DECODER_H #ifdef __cplusplus extern "C" { @@ -14,11 +14,9 @@ extern "C" { * INCLUDES *********************/ -#include "layouts/lv_layouts.h" -#include "libs/lv_libs.h" -#include "others/lv_others.h" -#include "themes/lv_themes.h" -#include "widgets/lv_widgets.h" +#include "../lv_image_decoder.h" + +#if LV_USE_DRAW_VG_LITE /********************* * DEFINES @@ -32,17 +30,18 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ -/** - * Initialize the extra components - */ -void lv_extra_init(void); +void lv_vg_lite_decoder_init(void); + +void lv_vg_lite_decoder_deinit(void); /********************** * MACROS **********************/ +#endif /*LV_USE_DRAW_VG_LITE*/ + #ifdef __cplusplus } /*extern "C"*/ #endif -#endif /*LV_EXTRA_H*/ +#endif /*LV_VG_LITE_DECODER_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_math.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_math.c new file mode 100644 index 000000000..08b180bf8 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_math.c @@ -0,0 +1,60 @@ +/** + * @file lv_vg_lite_math.h + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_vg_lite_math.h" + +#if LV_USE_DRAW_VG_LITE + +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +float math_fast_inv_sqrtf(float number) +{ + int32_t i; + float x2, y; + const float threehalfs = 1.5f; + + x2 = number * 0.5f; + y = number; + i = *(int32_t *)&y; /* evil floating point bit level hacking */ + i = 0x5f3759df - (i >> 1); /* what the fuck? */ + y = *(float *)&i; + y = y * (threehalfs - (x2 * y * y)); /* 1st iteration */ + + return y; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_math.h b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_math.h new file mode 100644 index 000000000..5607333b4 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_math.h @@ -0,0 +1,75 @@ +/** + * @file lv_vg_lite_math.h + * + */ + +#ifndef LV_VG_LITE_MATH_H +#define LV_VG_LITE_MATH_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_DRAW_VG_LITE + +#include +#include +#include + +/********************* + * DEFINES + *********************/ + +#define MATH_PI 3.14159265358979323846f +#define MATH_HALF_PI 1.57079632679489661923f +#define MATH_TWO_PI 6.28318530717958647692f +#define DEG_TO_RAD 0.017453292519943295769236907684886f +#define RAD_TO_DEG 57.295779513082320876798154814105f + +#define MATH_TANF(x) tanf(x) +#define MATH_SINF(x) sinf(x) +#define MATH_COSF(x) cosf(x) +#define MATH_ASINF(x) asinf(x) +#define MATH_FABSF(x) fabsf(x) +#define MATH_SQRTF(x) sqrtf(x) + +#define MATH_RADIANS(deg) ((deg) * DEG_TO_RAD) +#define MATH_DEGRESS(rad) ((rad) * RAD_TO_DEG) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +static inline bool math_zero(float a) +{ + return (MATH_FABSF(a) < FLT_EPSILON); +} + +static inline bool math_equal(float a, float b) +{ + return math_zero(a - b); +} + +float math_fast_inv_sqrtf(float number); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_VG_LITE_MATH_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_path.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_path.c new file mode 100644 index 000000000..40be97b4e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_path.c @@ -0,0 +1,573 @@ +/** + * @file lv_vg_lite_path.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_vg_lite_path.h" + +#if LV_USE_DRAW_VG_LITE + +#include "lv_draw_vg_lite_type.h" +#include "lv_vg_lite_math.h" +#include + +/********************* + * DEFINES + *********************/ + +#define PATH_KAPPA 0.552284f + +/* Magic number from https://spencermortensen.com/articles/bezier-circle/ */ +#define PATH_ARC_MAGIC 0.55191502449351f + +#define SIGN(x) (math_zero(x) ? 0 : ((x) > 0 ? 1 : -1)) + +#define VLC_OP_ARG_LEN(OP, LEN) \ + case VLC_OP_##OP: \ + return (LEN) + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_vg_lite_path_t { + vg_lite_path_t base; + size_t mem_size; + uint8_t format_len; +}; + +typedef struct { + float min_x; + float min_y; + float max_x; + float max_y; +} lv_vg_lite_path_bounds_t; + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_vg_lite_path_init(struct _lv_draw_vg_lite_unit_t * unit) +{ + LV_ASSERT_NULL(unit); + unit->global_path = lv_vg_lite_path_create(VG_LITE_FP32); + unit->path_in_use = false; +} + +void lv_vg_lite_path_deinit(struct _lv_draw_vg_lite_unit_t * unit) +{ + LV_ASSERT_NULL(unit); + LV_ASSERT(!unit->path_in_use); + lv_vg_lite_path_destroy(unit->global_path); + unit->global_path = NULL; +} + +lv_vg_lite_path_t * lv_vg_lite_path_create(vg_lite_format_t data_format) +{ + lv_vg_lite_path_t * path = lv_malloc_zeroed(sizeof(lv_vg_lite_path_t)); + LV_ASSERT_MALLOC(path); + path->format_len = lv_vg_lite_path_format_len(data_format); + LV_ASSERT(vg_lite_init_path( + &path->base, + data_format, + VG_LITE_MEDIUM, + 0, + NULL, + 0, 0, 0, 0) + == VG_LITE_SUCCESS); + return path; +} + +void lv_vg_lite_path_destroy(lv_vg_lite_path_t * path) +{ + LV_ASSERT_NULL(path); + if(path->base.path != NULL) { + lv_free(path->base.path); + path->base.path = NULL; + } + lv_free(path); +} + +lv_vg_lite_path_t * lv_vg_lite_path_get(struct _lv_draw_vg_lite_unit_t * unit, vg_lite_format_t data_format) +{ + LV_ASSERT_NULL(unit); + LV_ASSERT_NULL(unit->global_path); + LV_ASSERT(!unit->path_in_use); + lv_vg_lite_path_reset(unit->global_path, data_format); + unit->path_in_use = true; + return unit->global_path; +} + +void lv_vg_lite_path_drop(struct _lv_draw_vg_lite_unit_t * unit, lv_vg_lite_path_t * path) +{ + LV_ASSERT_NULL(unit); + LV_ASSERT_NULL(path); + LV_ASSERT(unit->global_path == path); + LV_ASSERT(unit->path_in_use); + unit->path_in_use = false; +} + +void lv_vg_lite_path_reset(lv_vg_lite_path_t * path, vg_lite_format_t data_format) +{ + LV_ASSERT_NULL(path); + path->base.path_length = 0; + path->base.format = data_format; + path->base.quality = VG_LITE_MEDIUM; + path->format_len = lv_vg_lite_path_format_len(data_format); +} + +vg_lite_path_t * lv_vg_lite_path_get_path(lv_vg_lite_path_t * path) +{ + LV_ASSERT_NULL(path); + return &path->base; +} + +void lv_vg_lite_path_set_bonding_box(lv_vg_lite_path_t * path, + float min_x, float min_y, + float max_x, float max_y) +{ + LV_ASSERT_NULL(path); + path->base.bounding_box[0] = min_x; + path->base.bounding_box[1] = min_y; + path->base.bounding_box[2] = max_x; + path->base.bounding_box[3] = max_y; +} + +void lv_vg_lite_path_set_bonding_box_area(lv_vg_lite_path_t * path, const lv_area_t * area) +{ + LV_ASSERT_NULL(path); + LV_ASSERT_NULL(area); + lv_vg_lite_path_set_bonding_box(path, area->x1, area->y1, area->x2 + 1, area->y2 + 1); +} + +void lv_vg_lite_path_get_bonding_box(lv_vg_lite_path_t * path, + float * min_x, float * min_y, + float * max_x, float * max_y) +{ + LV_ASSERT_NULL(path); + if(min_x) *min_x = path->base.bounding_box[0]; + if(min_y) *min_y = path->base.bounding_box[1]; + if(max_x) *max_x = path->base.bounding_box[2]; + if(max_y) *max_y = path->base.bounding_box[3]; +} + +static void path_bounds_iter_cb(void * user_data, uint8_t op_code, const float * data, uint32_t len) +{ + LV_UNUSED(op_code); + + if(len == 0) { + return; + } + + typedef struct { + float x; + float y; + } point_t; + + const int pt_len = sizeof(point_t) / sizeof(float); + + LV_ASSERT(len % pt_len == 0); + + const point_t * pt = (point_t *)data; + len /= pt_len; + + lv_vg_lite_path_bounds_t * bounds = user_data; + + for(uint32_t i = 0; i < len; i++) { + if(pt[i].x < bounds->min_x) bounds->min_x = pt[i].x; + if(pt[i].y < bounds->min_y) bounds->min_y = pt[i].y; + if(pt[i].x > bounds->max_x) bounds->max_x = pt[i].x; + if(pt[i].y > bounds->max_y) bounds->max_y = pt[i].y; + } +} + +bool lv_vg_lite_path_update_bonding_box(lv_vg_lite_path_t * path) +{ + LV_ASSERT_NULL(path); + + if(!path->format_len) { + return false; + } + + lv_vg_lite_path_bounds_t bounds; + + /* init bounds */ + bounds.min_x = __FLT_MAX__; + bounds.min_y = __FLT_MAX__; + bounds.max_x = __FLT_MIN__; + bounds.max_y = __FLT_MIN__; + + /* calc bounds */ + lv_vg_lite_path_for_each_data(lv_vg_lite_path_get_path(path), path_bounds_iter_cb, &bounds); + + /* set bounds */ + lv_vg_lite_path_set_bonding_box(path, bounds.min_x, bounds.min_y, bounds.max_x, bounds.max_y); + + return true; +} + +void lv_vg_lite_path_set_quality(lv_vg_lite_path_t * path, vg_lite_quality_t quality) +{ + LV_ASSERT_NULL(path); + path->base.quality = quality; +} + +static void lv_vg_lite_path_append_data(lv_vg_lite_path_t * path, const void * data, size_t len) +{ + LV_ASSERT_NULL(path); + LV_ASSERT_NULL(data); + + if(path->base.path_length + len > path->mem_size) { + if(path->mem_size == 0) { + path->mem_size = len; + } + else { + path->mem_size *= 2; + } + path->base.path = lv_realloc(path->base.path, path->mem_size); + LV_ASSERT_MALLOC(path->base.path); + } + + lv_memcpy((uint8_t *)path->base.path + path->base.path_length, data, len); + path->base.path_length += len; +} + +static void lv_vg_lite_path_append_op(lv_vg_lite_path_t * path, uint32_t op) +{ + lv_vg_lite_path_append_data(path, &op, path->format_len); +} + +static void lv_vg_lite_path_append_point(lv_vg_lite_path_t * path, float x, float y) +{ + if(path->base.format == VG_LITE_FP32) { + lv_vg_lite_path_append_data(path, &x, sizeof(x)); + lv_vg_lite_path_append_data(path, &y, sizeof(y)); + return; + } + + int32_t ix = (int32_t)(x); + int32_t iy = (int32_t)(y); + lv_vg_lite_path_append_data(path, &ix, path->format_len); + lv_vg_lite_path_append_data(path, &iy, path->format_len); +} + +void lv_vg_lite_path_move_to(lv_vg_lite_path_t * path, + float x, float y) +{ + LV_ASSERT_NULL(path); + lv_vg_lite_path_append_op(path, VLC_OP_MOVE); + lv_vg_lite_path_append_point(path, x, y); +} + +void lv_vg_lite_path_line_to(lv_vg_lite_path_t * path, + float x, float y) +{ + LV_ASSERT_NULL(path); + lv_vg_lite_path_append_op(path, VLC_OP_LINE); + lv_vg_lite_path_append_point(path, x, y); +} + +void lv_vg_lite_path_quad_to(lv_vg_lite_path_t * path, + float cx, float cy, + float x, float y) +{ + LV_ASSERT_NULL(path); + lv_vg_lite_path_append_op(path, VLC_OP_QUAD); + lv_vg_lite_path_append_point(path, cx, cy); + lv_vg_lite_path_append_point(path, x, y); +} + +void lv_vg_lite_path_cubic_to(lv_vg_lite_path_t * path, + float cx1, float cy1, + float cx2, float cy2, + float x, float y) +{ + LV_ASSERT_NULL(path); + lv_vg_lite_path_append_op(path, VLC_OP_CUBIC); + lv_vg_lite_path_append_point(path, cx1, cy1); + lv_vg_lite_path_append_point(path, cx2, cy2); + lv_vg_lite_path_append_point(path, x, y); +} + +void lv_vg_lite_path_close(lv_vg_lite_path_t * path) +{ + LV_ASSERT_NULL(path); + lv_vg_lite_path_append_op(path, VLC_OP_CLOSE); +} + +void lv_vg_lite_path_end(lv_vg_lite_path_t * path) +{ + LV_ASSERT_NULL(path); + lv_vg_lite_path_append_op(path, VLC_OP_END); +} + +void lv_vg_lite_path_append_rect( + lv_vg_lite_path_t * path, + float x, float y, + float w, float h, + float rx, float ry) +{ + const float half_w = w * 0.5f; + const float half_h = h * 0.5f; + + /*clamping cornerRadius by minimum size*/ + if(rx > half_w) + rx = half_w; + if(ry > half_h) + ry = half_h; + + /*rectangle*/ + if(rx == 0 && ry == 0) { + lv_vg_lite_path_move_to(path, x, y); + lv_vg_lite_path_line_to(path, x + w, y); + lv_vg_lite_path_line_to(path, x + w, y + h); + lv_vg_lite_path_line_to(path, x, y + h); + lv_vg_lite_path_close(path); + return; + } + + /*circle*/ + if(math_equal(rx, half_w) && math_equal(ry, half_h)) { + return lv_vg_lite_path_append_circle(path, x + (w * 0.5f), y + (h * 0.5f), rx, ry); + } + + /*rounded rectangle*/ + float hrx = rx * 0.5f; + float hry = ry * 0.5f; + lv_vg_lite_path_move_to(path, x + rx, y); + lv_vg_lite_path_line_to(path, x + w - rx, y); + lv_vg_lite_path_cubic_to(path, x + w - rx + hrx, y, x + w, y + ry - hry, x + w, y + ry); + lv_vg_lite_path_line_to(path, x + w, y + h - ry); + lv_vg_lite_path_cubic_to(path, x + w, y + h - ry + hry, x + w - rx + hrx, y + h, x + w - rx, y + h); + lv_vg_lite_path_line_to(path, x + rx, y + h); + lv_vg_lite_path_cubic_to(path, x + rx - hrx, y + h, x, y + h - ry + hry, x, y + h - ry); + lv_vg_lite_path_line_to(path, x, y + ry); + lv_vg_lite_path_cubic_to(path, x, y + ry - hry, x + rx - hrx, y, x + rx, y); + lv_vg_lite_path_close(path); +} + +void lv_vg_lite_path_append_circle( + lv_vg_lite_path_t * path, + float cx, float cy, + float rx, float ry) +{ + /* https://learn.microsoft.com/zh-cn/xamarin/xamarin-forms/user-interface/graphics/skiasharp/curves/beziers */ + float rx_kappa = rx * PATH_KAPPA; + float ry_kappa = ry * PATH_KAPPA; + + lv_vg_lite_path_move_to(path, cx, cy - ry); + lv_vg_lite_path_cubic_to(path, cx + rx_kappa, cy - ry, cx + rx, cy - ry_kappa, cx + rx, cy); + lv_vg_lite_path_cubic_to(path, cx + rx, cy + ry_kappa, cx + rx_kappa, cy + ry, cx, cy + ry); + lv_vg_lite_path_cubic_to(path, cx - rx_kappa, cy + ry, cx - rx, cy + ry_kappa, cx - rx, cy); + lv_vg_lite_path_cubic_to(path, cx - rx, cy - ry_kappa, cx - rx_kappa, cy - ry, cx, cy - ry); + lv_vg_lite_path_close(path); +} + +void lv_vg_lite_path_append_arc_right_angle(lv_vg_lite_path_t * path, + float start_x, float start_y, + float center_x, float center_y, + float end_x, float end_y) +{ + float dx1 = center_x - start_x; + float dy1 = center_y - start_y; + float dx2 = end_x - center_x; + float dy2 = end_y - center_y; + + float c = SIGN(dx1 * dy2 - dx2 * dy1) * PATH_ARC_MAGIC; + + lv_vg_lite_path_cubic_to(path, + start_x - c * dy1, start_y + c * dx1, + end_x - c * dy2, end_y + c * dx2, + end_x, end_y); +} + +void lv_vg_lite_path_append_arc(lv_vg_lite_path_t * path, + float cx, float cy, + float radius, + float start_angle, + float sweep, + bool pie) +{ + /* just circle */ + if(sweep >= 360.0f || sweep <= -360.0f) { + return lv_vg_lite_path_append_circle(path, cx, cy, radius, radius); + } + + start_angle = MATH_RADIANS(start_angle); + sweep = MATH_RADIANS(sweep); + + int n_curves = (int)ceil(MATH_FABSF(sweep / MATH_HALF_PI)); + int sweep_sign = (sweep < 0 ? -1 : 1); + float fract = fmodf(sweep, MATH_HALF_PI); + fract = (math_zero(fract)) ? MATH_HALF_PI * sweep_sign : fract; + + /* Start from here */ + float start_x = radius * MATH_COSF(start_angle); + float start_y = radius * MATH_SINF(start_angle); + + if(pie) { + lv_vg_lite_path_move_to(path, cx, cy); + lv_vg_lite_path_line_to(path, start_x + cx, start_y + cy); + } + else { + lv_vg_lite_path_move_to(path, start_x + cx, start_y + cy); + } + + for(int i = 0; i < n_curves; ++i) { + float end_angle = start_angle + ((i != n_curves - 1) ? MATH_HALF_PI * sweep_sign : fract); + float end_x = radius * MATH_COSF(end_angle); + float end_y = radius * MATH_SINF(end_angle); + + /* variables needed to calculate bezier control points */ + + /** get bezier control points using article: + * (http://itc.ktu.lt/index.php/ITC/article/view/11812/6479) + */ + float ax = start_x; + float ay = start_y; + float bx = end_x; + float by = end_y; + float q1 = ax * ax + ay * ay; + float q2 = ax * bx + ay * by + q1; + float k2 = (4.0f / 3.0f) * ((MATH_SQRTF(2 * q1 * q2) - q2) / (ax * by - ay * bx)); + + /* Next start point is the current end point */ + start_x = end_x; + start_y = end_y; + + end_x += cx; + end_y += cy; + + float ctrl1_x = ax - k2 * ay + cx; + float ctrl1_y = ay + k2 * ax + cy; + float ctrl2_x = bx + k2 * by + cx; + float ctrl2_y = by - k2 * bx + cy; + + lv_vg_lite_path_cubic_to(path, ctrl1_x, ctrl1_y, ctrl2_x, ctrl2_y, end_x, end_y); + start_angle = end_angle; + } + + if(pie) { + lv_vg_lite_path_close(path); + } +} + +uint8_t lv_vg_lite_vlc_op_arg_len(uint8_t vlc_op) +{ + switch(vlc_op) { + VLC_OP_ARG_LEN(END, 0); + VLC_OP_ARG_LEN(CLOSE, 0); + VLC_OP_ARG_LEN(MOVE, 2); + VLC_OP_ARG_LEN(MOVE_REL, 2); + VLC_OP_ARG_LEN(LINE, 2); + VLC_OP_ARG_LEN(LINE_REL, 2); + VLC_OP_ARG_LEN(QUAD, 4); + VLC_OP_ARG_LEN(QUAD_REL, 4); + VLC_OP_ARG_LEN(CUBIC, 6); + VLC_OP_ARG_LEN(CUBIC_REL, 6); + VLC_OP_ARG_LEN(SCCWARC, 5); + VLC_OP_ARG_LEN(SCCWARC_REL, 5); + VLC_OP_ARG_LEN(SCWARC, 5); + VLC_OP_ARG_LEN(SCWARC_REL, 5); + VLC_OP_ARG_LEN(LCCWARC, 5); + VLC_OP_ARG_LEN(LCCWARC_REL, 5); + VLC_OP_ARG_LEN(LCWARC, 5); + VLC_OP_ARG_LEN(LCWARC_REL, 5); + default: + break; + } + + LV_LOG_ERROR("UNKNOW_VLC_OP: 0x%x", vlc_op); + LV_ASSERT(false); + return 0; +} + +uint8_t lv_vg_lite_path_format_len(vg_lite_format_t format) +{ + switch(format) { + case VG_LITE_S8: + return 1; + case VG_LITE_S16: + return 2; + case VG_LITE_S32: + return 4; + case VG_LITE_FP32: + return 4; + default: + break; + } + + LV_LOG_ERROR("UNKNOW_FORMAT: %d", format); + LV_ASSERT(false); + return 0; +} + +void lv_vg_lite_path_for_each_data(const vg_lite_path_t * path, lv_vg_lite_path_iter_cb_t cb, void * user_data) +{ + LV_ASSERT_NULL(path); + LV_ASSERT_NULL(cb); + + uint8_t fmt_len = lv_vg_lite_path_format_len(path->format); + uint8_t * cur = path->path; + uint8_t * end = cur + path->path_length; + float tmp_data[8]; + + while(cur < end) { + /* get op code */ + uint8_t op_code = VLC_GET_OP_CODE(cur); + + /* get arguments length */ + uint8_t arg_len = lv_vg_lite_vlc_op_arg_len(op_code); + + /* skip op code */ + cur += fmt_len; + + /* print arguments */ + for(uint8_t i = 0; i < arg_len; i++) { + switch(path->format) { + case VG_LITE_S8: + tmp_data[i] = *((int8_t *)cur); + break; + case VG_LITE_S16: + tmp_data[i] = *((int16_t *)cur); + break; + case VG_LITE_S32: + tmp_data[i] = *((int32_t *)cur); + break; + case VG_LITE_FP32: + tmp_data[i] = *((float *)cur); + break; + default: + LV_LOG_ERROR("UNKNOW_FORMAT(%d)", path->format); + LV_ASSERT(false); + break; + } + + cur += fmt_len; + } + + cb(user_data, op_code, tmp_data, arg_len); + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_path.h b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_path.h new file mode 100644 index 000000000..c7172e6fe --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_path.h @@ -0,0 +1,124 @@ +/** + * @file lv_vg_lite_path.h + * + */ + +#ifndef LV_VG_LITE_PATH_H +#define LV_VG_LITE_PATH_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "lv_vg_lite_utils.h" + +#if LV_USE_DRAW_VG_LITE + +/********************* + * DEFINES + *********************/ + +typedef struct _lv_vg_lite_path_t lv_vg_lite_path_t; +typedef struct _lv_draw_vg_lite_unit_t lv_draw_vg_lite_unit_t; + +typedef void (*lv_vg_lite_path_iter_cb_t)(void * user_data, uint8_t op_code, const float * data, uint32_t len); + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_vg_lite_path_init(lv_draw_vg_lite_unit_t * unit); + +void lv_vg_lite_path_deinit(lv_draw_vg_lite_unit_t * unit); + +lv_vg_lite_path_t * lv_vg_lite_path_create(vg_lite_format_t data_format); + +void lv_vg_lite_path_destroy(lv_vg_lite_path_t * path); + +lv_vg_lite_path_t * lv_vg_lite_path_get(lv_draw_vg_lite_unit_t * unit, vg_lite_format_t data_format); + +void lv_vg_lite_path_drop(lv_draw_vg_lite_unit_t * unit, lv_vg_lite_path_t * path); + +void lv_vg_lite_path_reset(lv_vg_lite_path_t * path, vg_lite_format_t data_format); + +void lv_vg_lite_path_set_bonding_box_area(lv_vg_lite_path_t * path, const lv_area_t * area); + +void lv_vg_lite_path_set_bonding_box(lv_vg_lite_path_t * path, + float min_x, float min_y, + float max_x, float max_y); + +void lv_vg_lite_path_get_bonding_box(lv_vg_lite_path_t * path, + float * min_x, float * min_y, + float * max_x, float * max_y); + +bool lv_vg_lite_path_update_bonding_box(lv_vg_lite_path_t * path); + +void lv_vg_lite_path_set_quality(lv_vg_lite_path_t * path, vg_lite_quality_t quality); + +vg_lite_path_t * lv_vg_lite_path_get_path(lv_vg_lite_path_t * path); + +void lv_vg_lite_path_move_to(lv_vg_lite_path_t * path, + float x, float y); + +void lv_vg_lite_path_line_to(lv_vg_lite_path_t * path, + float x, float y); + +void lv_vg_lite_path_quad_to(lv_vg_lite_path_t * path, + float cx, float cy, + float x, float y); + +void lv_vg_lite_path_cubic_to(lv_vg_lite_path_t * path, + float cx1, float cy1, + float cx2, float cy2, + float x, float y); + +void lv_vg_lite_path_close(lv_vg_lite_path_t * path); + +void lv_vg_lite_path_end(lv_vg_lite_path_t * path); + +void lv_vg_lite_path_append_rect(lv_vg_lite_path_t * path, + float x, float y, + float w, float h, + float rx, float ry); + +void lv_vg_lite_path_append_circle(lv_vg_lite_path_t * path, + float cx, float cy, + float rx, float ry); + +void lv_vg_lite_path_append_arc_right_angle(lv_vg_lite_path_t * path, + float start_x, float start_y, + float center_x, float center_y, + float end_x, float end_y); + +void lv_vg_lite_path_append_arc(lv_vg_lite_path_t * path, + float cx, float cy, + float radius, + float start_angle, + float sweep, + bool pie); + +uint8_t lv_vg_lite_vlc_op_arg_len(uint8_t vlc_op); + +uint8_t lv_vg_lite_path_format_len(vg_lite_format_t format); + +void lv_vg_lite_path_for_each_data(const vg_lite_path_t * path, lv_vg_lite_path_iter_cb_t cb, void * user_data); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_VG_LITE_PATH_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_utils.c b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_utils.c new file mode 100644 index 000000000..c8bf9f859 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_utils.c @@ -0,0 +1,1029 @@ +/** + * @file vg_lite_utils.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_vg_lite_utils.h" + +#if LV_USE_DRAW_VG_LITE + +#include "lv_vg_lite_decoder.h" +#include "lv_vg_lite_path.h" +#include + +/********************* + * DEFINES + *********************/ + +#define ENUM_TO_STRING(e) \ + case (e): \ + return #e + +#define VG_LITE_ENUM_TO_STRING(e) \ + case (VG_LITE_##e): \ + return #e + +#define VLC_OP_ENUM_TO_STRING(e) \ + case (VLC_OP_##e): \ + return #e + +#define FEATURE_ENUM_TO_STRING(e) \ + case (gcFEATURE_BIT_VG_##e): \ + return #e + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_vg_lite_dump_info(void) +{ + char name[64]; + vg_lite_uint32_t chip_id; + vg_lite_uint32_t chip_rev; + vg_lite_uint32_t cid; + vg_lite_get_product_info(name, &chip_id, &chip_rev); + vg_lite_get_register(0x30, &cid); + LV_LOG_USER("Product Info: %s" + " | Chip ID: 0x%" LV_PRIx32 + " | Revision: 0x%" LV_PRIx32 + " | CID: 0x%" LV_PRIx32, + name, (uint32_t)chip_id, (uint32_t)chip_rev, (uint32_t)cid); + + vg_lite_info_t info; + vg_lite_get_info(&info); + LV_LOG_USER("VGLite API version: 0x%" LV_PRIx32, (uint32_t)info.api_version); + LV_LOG_USER("VGLite API header version: 0x%" LV_PRIx32, (uint32_t)info.header_version); + LV_LOG_USER("VGLite release version: 0x%" LV_PRIx32, (uint32_t)info.release_version); + + for(int feature = 0; feature < gcFEATURE_COUNT; feature++) { + vg_lite_uint32_t ret = vg_lite_query_feature((vg_lite_feature_t)feature); + LV_UNUSED(ret); + LV_LOG_USER("Feature-%d: %s\t - %s", + feature, lv_vg_lite_feature_string((vg_lite_feature_t)feature), + ret ? "YES" : "NO"); + } + + vg_lite_uint32_t mem_avail = 0; + vg_lite_get_mem_size(&mem_avail); + LV_LOG_USER("Memory Avaliable: %" LV_PRId32 " Bytes", (uint32_t)mem_avail); +} + +const char * lv_vg_lite_error_string(vg_lite_error_t error) +{ + switch(error) { + VG_LITE_ENUM_TO_STRING(SUCCESS); + VG_LITE_ENUM_TO_STRING(INVALID_ARGUMENT); + VG_LITE_ENUM_TO_STRING(OUT_OF_MEMORY); + VG_LITE_ENUM_TO_STRING(NO_CONTEXT); + VG_LITE_ENUM_TO_STRING(TIMEOUT); + VG_LITE_ENUM_TO_STRING(OUT_OF_RESOURCES); + VG_LITE_ENUM_TO_STRING(GENERIC_IO); + VG_LITE_ENUM_TO_STRING(NOT_SUPPORT); + VG_LITE_ENUM_TO_STRING(ALREADY_EXISTS); + VG_LITE_ENUM_TO_STRING(NOT_ALIGNED); + VG_LITE_ENUM_TO_STRING(FLEXA_TIME_OUT); + VG_LITE_ENUM_TO_STRING(FLEXA_HANDSHAKE_FAIL); + default: + break; + } + return "UNKNOW_ERROR"; +} + +const char * lv_vg_lite_feature_string(vg_lite_feature_t feature) +{ + switch(feature) { + FEATURE_ENUM_TO_STRING(IM_INDEX_FORMAT); + FEATURE_ENUM_TO_STRING(SCISSOR); + FEATURE_ENUM_TO_STRING(BORDER_CULLING); + FEATURE_ENUM_TO_STRING(RGBA2_FORMAT); + FEATURE_ENUM_TO_STRING(QUALITY_8X); + FEATURE_ENUM_TO_STRING(IM_FASTCLAER); + FEATURE_ENUM_TO_STRING(RADIAL_GRADIENT); + FEATURE_ENUM_TO_STRING(GLOBAL_ALPHA); + FEATURE_ENUM_TO_STRING(RGBA8_ETC2_EAC); + FEATURE_ENUM_TO_STRING(COLOR_KEY); + FEATURE_ENUM_TO_STRING(DOUBLE_IMAGE); + FEATURE_ENUM_TO_STRING(YUV_OUTPUT); + FEATURE_ENUM_TO_STRING(FLEXA); + FEATURE_ENUM_TO_STRING(24BIT); + FEATURE_ENUM_TO_STRING(DITHER); + FEATURE_ENUM_TO_STRING(USE_DST); + FEATURE_ENUM_TO_STRING(PE_CLEAR); + FEATURE_ENUM_TO_STRING(IM_INPUT); + FEATURE_ENUM_TO_STRING(DEC_COMPRESS); + FEATURE_ENUM_TO_STRING(LINEAR_GRADIENT_EXT); + FEATURE_ENUM_TO_STRING(MASK); + FEATURE_ENUM_TO_STRING(MIRROR); + FEATURE_ENUM_TO_STRING(GAMMA); + FEATURE_ENUM_TO_STRING(NEW_BLEND_MODE); + FEATURE_ENUM_TO_STRING(STENCIL); + FEATURE_ENUM_TO_STRING(SRC_PREMULTIPLIED); /*! Valid only if FEATURE_ENUM_TO_STRING(HW_PREMULTIPLY is 0 */ + FEATURE_ENUM_TO_STRING(HW_PREMULTIPLY); /*! HW multiplier can accept either premultiplied or not */ + FEATURE_ENUM_TO_STRING(COLOR_TRANSFORMATION); + FEATURE_ENUM_TO_STRING(LVGL_SUPPORT); + FEATURE_ENUM_TO_STRING(INDEX_ENDIAN); + FEATURE_ENUM_TO_STRING(24BIT_PLANAR); + FEATURE_ENUM_TO_STRING(PIXEL_MATRIX); + FEATURE_ENUM_TO_STRING(NEW_IMAGE_INDEX); + FEATURE_ENUM_TO_STRING(PARALLEL_PATHS); + FEATURE_ENUM_TO_STRING(STRIPE_MODE); + FEATURE_ENUM_TO_STRING(IM_DEC_INPUT); + FEATURE_ENUM_TO_STRING(GAUSSIAN_BLUR); + FEATURE_ENUM_TO_STRING(RECTANGLE_TILED_OUT); + FEATURE_ENUM_TO_STRING(TESSELLATION_TILED_OUT); + FEATURE_ENUM_TO_STRING(IM_REPEAT_REFLECT); + FEATURE_ENUM_TO_STRING(YUY2_INPUT); + FEATURE_ENUM_TO_STRING(YUV_INPUT); + FEATURE_ENUM_TO_STRING(YUV_TILED_INPUT); + FEATURE_ENUM_TO_STRING(AYUV_INPUT); + FEATURE_ENUM_TO_STRING(16PIXELS_ALIGN); + default: + break; + } + return "UNKNOW_FEATURE"; +} + +const char * lv_vg_lite_buffer_format_string(vg_lite_buffer_format_t format) +{ + switch(format) { + VG_LITE_ENUM_TO_STRING(RGBA8888); + VG_LITE_ENUM_TO_STRING(BGRA8888); + VG_LITE_ENUM_TO_STRING(RGBX8888); + VG_LITE_ENUM_TO_STRING(BGRX8888); + VG_LITE_ENUM_TO_STRING(RGB565); + VG_LITE_ENUM_TO_STRING(BGR565); + VG_LITE_ENUM_TO_STRING(RGBA4444); + VG_LITE_ENUM_TO_STRING(BGRA4444); + VG_LITE_ENUM_TO_STRING(BGRA5551); + VG_LITE_ENUM_TO_STRING(A4); + VG_LITE_ENUM_TO_STRING(A8); + VG_LITE_ENUM_TO_STRING(L8); + VG_LITE_ENUM_TO_STRING(YUYV); + VG_LITE_ENUM_TO_STRING(YUY2); + VG_LITE_ENUM_TO_STRING(NV12); + VG_LITE_ENUM_TO_STRING(ANV12); + VG_LITE_ENUM_TO_STRING(AYUY2); + VG_LITE_ENUM_TO_STRING(YV12); + VG_LITE_ENUM_TO_STRING(YV24); + VG_LITE_ENUM_TO_STRING(YV16); + VG_LITE_ENUM_TO_STRING(NV16); + VG_LITE_ENUM_TO_STRING(YUY2_TILED); + VG_LITE_ENUM_TO_STRING(NV12_TILED); + VG_LITE_ENUM_TO_STRING(ANV12_TILED); + VG_LITE_ENUM_TO_STRING(AYUY2_TILED); + VG_LITE_ENUM_TO_STRING(INDEX_1); + VG_LITE_ENUM_TO_STRING(INDEX_2); + VG_LITE_ENUM_TO_STRING(INDEX_4); + VG_LITE_ENUM_TO_STRING(INDEX_8); + VG_LITE_ENUM_TO_STRING(RGBA2222); + VG_LITE_ENUM_TO_STRING(BGRA2222); + VG_LITE_ENUM_TO_STRING(ABGR2222); + VG_LITE_ENUM_TO_STRING(ARGB2222); + VG_LITE_ENUM_TO_STRING(ABGR4444); + VG_LITE_ENUM_TO_STRING(ARGB4444); + VG_LITE_ENUM_TO_STRING(ABGR8888); + VG_LITE_ENUM_TO_STRING(ARGB8888); + VG_LITE_ENUM_TO_STRING(ABGR1555); + VG_LITE_ENUM_TO_STRING(RGBA5551); + VG_LITE_ENUM_TO_STRING(ARGB1555); + VG_LITE_ENUM_TO_STRING(XBGR8888); + VG_LITE_ENUM_TO_STRING(XRGB8888); + VG_LITE_ENUM_TO_STRING(RGBA8888_ETC2_EAC); + VG_LITE_ENUM_TO_STRING(RGB888); + VG_LITE_ENUM_TO_STRING(BGR888); + VG_LITE_ENUM_TO_STRING(ABGR8565); + VG_LITE_ENUM_TO_STRING(BGRA5658); + VG_LITE_ENUM_TO_STRING(ARGB8565); + VG_LITE_ENUM_TO_STRING(RGBA5658); + default: + break; + } + return "UNKNOW_BUFFER_FORMAT"; +} + +const char * lv_vg_lite_vlc_op_string(uint8_t vlc_op) +{ + switch(vlc_op) { + VLC_OP_ENUM_TO_STRING(END); + VLC_OP_ENUM_TO_STRING(CLOSE); + VLC_OP_ENUM_TO_STRING(MOVE); + VLC_OP_ENUM_TO_STRING(MOVE_REL); + VLC_OP_ENUM_TO_STRING(LINE); + VLC_OP_ENUM_TO_STRING(LINE_REL); + VLC_OP_ENUM_TO_STRING(QUAD); + VLC_OP_ENUM_TO_STRING(QUAD_REL); + VLC_OP_ENUM_TO_STRING(CUBIC); + VLC_OP_ENUM_TO_STRING(CUBIC_REL); + + VLC_OP_ENUM_TO_STRING(SCCWARC); + VLC_OP_ENUM_TO_STRING(SCCWARC_REL); + VLC_OP_ENUM_TO_STRING(SCWARC); + VLC_OP_ENUM_TO_STRING(SCWARC_REL); + VLC_OP_ENUM_TO_STRING(LCCWARC); + VLC_OP_ENUM_TO_STRING(LCCWARC_REL); + VLC_OP_ENUM_TO_STRING(LCWARC); + VLC_OP_ENUM_TO_STRING(LCWARC_REL); + default: + break; + } + return "UNKNOW_VLC_OP"; +} + +static void path_data_print_cb(void * user_data, uint8_t op_code, const float * data, uint32_t len) +{ + LV_UNUSED(user_data); + + LV_LOG("%s, ", lv_vg_lite_vlc_op_string(op_code)); + for(uint32_t i = 0; i < len; i++) { + LV_LOG("%0.2f, ", data[i]); + } + LV_LOG("\n"); +} + +void lv_vg_lite_path_dump_info(const vg_lite_path_t * path) +{ + LV_ASSERT(path != NULL); + LV_ASSERT(path->path != NULL); + uint8_t fmt_len = lv_vg_lite_path_format_len(path->format); + size_t len = path->path_length / fmt_len; + + LV_ASSERT(len > 0); + + LV_LOG_USER("address: %p", path->path); + LV_LOG_USER("length: %d", (int)len); + LV_LOG_USER("bonding box: (%0.2f, %0.2f) - (%0.2f, %0.2f)", + path->bounding_box[0], path->bounding_box[1], + path->bounding_box[2], path->bounding_box[3]); + LV_LOG_USER("format: %d", (int)path->format); + LV_LOG_USER("quality: %d", (int)path->quality); + + lv_vg_lite_path_for_each_data(path, path_data_print_cb, NULL); +} + +void lv_vg_lite_buffer_dump_info(const vg_lite_buffer_t * buffer) +{ + LV_LOG_USER("memory: %p", (buffer)->memory); + LV_LOG_USER("address: 0x%08x", (int)(buffer)->address); + LV_LOG_USER("size: W%d x H%d", (int)((buffer)->width), (int)((buffer)->height)); + LV_LOG_USER("stride: %d", (int)((buffer)->stride)); + LV_LOG_USER("format: %d (%s)", + (int)((buffer)->format), + lv_vg_lite_buffer_format_string((buffer)->format)); + LV_LOG_USER("tiled: %d", (int)((buffer)->tiled)); +} + +void lv_vg_lite_matrix_dump_info(const vg_lite_matrix_t * matrix) +{ + for(int i = 0; i < 3; i++) { + LV_LOG_USER("| %0.2f, %0.2f, %0.2f |", + (matrix)->m[i][0], (matrix)->m[i][1], (matrix)->m[i][2]); + } +} + +bool lv_vg_lite_is_dest_cf_supported(lv_color_format_t cf) +{ + switch(cf) { + case LV_COLOR_FORMAT_RGB565: + case LV_COLOR_FORMAT_RGB565A8: + case LV_COLOR_FORMAT_RGB888: + case LV_COLOR_FORMAT_ARGB8888: + case LV_COLOR_FORMAT_XRGB8888: + return true; + default: + break; + } + return false; +} + +bool lv_vg_lite_is_src_cf_supported(lv_color_format_t cf) +{ + switch(cf) { + case LV_COLOR_FORMAT_A4: + case LV_COLOR_FORMAT_A8: + case LV_COLOR_FORMAT_I8: + case LV_COLOR_FORMAT_RGB565: + case LV_COLOR_FORMAT_RGB565A8: + case LV_COLOR_FORMAT_RGB888: + case LV_COLOR_FORMAT_ARGB8888: + case LV_COLOR_FORMAT_XRGB8888: + case LV_COLOR_FORMAT_NV12: + return true; + default: + break; + } + return false; +} + +vg_lite_buffer_format_t lv_vg_lite_vg_fmt(lv_color_format_t cf) +{ + switch(cf) { + case LV_COLOR_FORMAT_A4: + return VG_LITE_A4; + + case LV_COLOR_FORMAT_A8: + return VG_LITE_A8; + + case LV_COLOR_FORMAT_L8: + return VG_LITE_L8; + + case LV_COLOR_FORMAT_I1: + return VG_LITE_INDEX_1; + + case LV_COLOR_FORMAT_I2: + return VG_LITE_INDEX_2; + + case LV_COLOR_FORMAT_I4: + return VG_LITE_INDEX_4; + + case LV_COLOR_FORMAT_I8: + return VG_LITE_INDEX_8; + + case LV_COLOR_FORMAT_RGB565: + return VG_LITE_BGR565; + + case LV_COLOR_FORMAT_RGB565A8: + return VG_LITE_BGRA5658; + + case LV_COLOR_FORMAT_RGB888: + return VG_LITE_BGR888; + + case LV_COLOR_FORMAT_ARGB8888: + return VG_LITE_BGRA8888; + + case LV_COLOR_FORMAT_XRGB8888: + return VG_LITE_BGRX8888; + + case LV_COLOR_FORMAT_NV12: + return VG_LITE_NV12; + + default: + LV_LOG_ERROR("unsupport color format: %d", cf); + break; + } + + LV_ASSERT(false); + return 0; +} + +void lv_vg_lite_buffer_format_bytes( + vg_lite_buffer_format_t format, + uint32_t * mul, + uint32_t * div, + uint32_t * bytes_align) +{ + /* Get the bpp information of a color format. */ + *mul = *div = 1; + *bytes_align = 4; + switch(format) { + case VG_LITE_L8: + case VG_LITE_A8: + case VG_LITE_RGBA8888_ETC2_EAC: + break; + case VG_LITE_A4: + *div = 2; + break; + case VG_LITE_ABGR1555: + case VG_LITE_ARGB1555: + case VG_LITE_BGRA5551: + case VG_LITE_RGBA5551: + case VG_LITE_RGBA4444: + case VG_LITE_BGRA4444: + case VG_LITE_ABGR4444: + case VG_LITE_ARGB4444: + case VG_LITE_RGB565: + case VG_LITE_BGR565: + case VG_LITE_YUYV: + case VG_LITE_YUY2: + case VG_LITE_YUY2_TILED: + /* AYUY2 buffer memory = YUY2 + alpha. */ + case VG_LITE_AYUY2: + case VG_LITE_AYUY2_TILED: + *mul = 2; + break; + case VG_LITE_RGBA8888: + case VG_LITE_BGRA8888: + case VG_LITE_ABGR8888: + case VG_LITE_ARGB8888: + case VG_LITE_RGBX8888: + case VG_LITE_BGRX8888: + case VG_LITE_XBGR8888: + case VG_LITE_XRGB8888: + *mul = 4; + break; + case VG_LITE_NV12: + case VG_LITE_NV12_TILED: + *mul = 1; + break; + case VG_LITE_ANV12: + case VG_LITE_ANV12_TILED: + *mul = 4; + break; + case VG_LITE_INDEX_1: + *div = 8; + *bytes_align = 8; + break; + case VG_LITE_INDEX_2: + *div = 4; + *bytes_align = 8; + break; + case VG_LITE_INDEX_4: + *div = 2; + *bytes_align = 8; + break; + case VG_LITE_INDEX_8: + *bytes_align = 1; + break; + case VG_LITE_RGBA2222: + case VG_LITE_BGRA2222: + case VG_LITE_ABGR2222: + case VG_LITE_ARGB2222: + *mul = 1; + break; + case VG_LITE_RGB888: + case VG_LITE_BGR888: + case VG_LITE_ABGR8565: + case VG_LITE_BGRA5658: + case VG_LITE_ARGB8565: + case VG_LITE_RGBA5658: + *mul = 3; + break; + default: + LV_LOG_ERROR("unsupport color format: 0x%" PRIx32, (uint32_t)format); + LV_ASSERT(false); + break; + } +} + +uint32_t lv_vg_lite_width_to_stride(uint32_t w, vg_lite_buffer_format_t color_format) +{ + w = lv_vg_lite_width_align(w); + + uint32_t mul, div, align; + lv_vg_lite_buffer_format_bytes(color_format, &mul, &div, &align); + return LV_VG_LITE_ALIGN((w * mul / div), align); +} + +uint32_t lv_vg_lite_width_align(uint32_t w) +{ + if(lv_vg_lite_16px_align()) { + w = LV_VG_LITE_ALIGN(w, 16); + } + + return w; +} + +void lv_vg_lite_buffer_init( + vg_lite_buffer_t * buffer, + const void * ptr, + int32_t width, + int32_t height, + vg_lite_buffer_format_t format, + bool tiled) +{ + uint32_t mul; + uint32_t div; + uint32_t align; + LV_ASSERT_NULL(buffer); + LV_ASSERT_NULL(ptr); + + lv_memzero(buffer, sizeof(vg_lite_buffer_t)); + + buffer->format = format; + if(tiled || format == VG_LITE_RGBA8888_ETC2_EAC) { + buffer->tiled = VG_LITE_TILED; + } + else { + buffer->tiled = VG_LITE_LINEAR; + } + buffer->image_mode = VG_LITE_NORMAL_IMAGE_MODE; + buffer->transparency_mode = VG_LITE_IMAGE_OPAQUE; + buffer->width = width; + buffer->height = height; + lv_vg_lite_buffer_format_bytes(buffer->format, &mul, &div, &align); + buffer->stride = LV_VG_LITE_ALIGN((buffer->width * mul / div), align); + + if(format == VG_LITE_NV12) { + lv_yuv_buf_t * frame_p = (lv_yuv_buf_t *)ptr; + buffer->memory = (void *)frame_p->semi_planar.y.buf; + buffer->address = (uintptr_t)frame_p->semi_planar.y.buf; + buffer->yuv.swizzle = VG_LITE_SWIZZLE_UV; + buffer->yuv.alpha_stride = buffer->stride; + buffer->yuv.uv_height = buffer->height / 2; + buffer->yuv.uv_memory = (void *)frame_p->semi_planar.uv.buf; + buffer->yuv.uv_planar = (uint32_t)(uintptr_t)frame_p->semi_planar.uv.buf; + buffer->yuv.uv_stride = frame_p->semi_planar.uv.stride; + } + else { + buffer->memory = (void *)ptr; + buffer->address = (uintptr_t)ptr; + } +} + +void lv_vg_lite_buffer_from_draw_buf(vg_lite_buffer_t * buffer, const lv_draw_buf_t * draw_buf) +{ + LV_ASSERT_NULL(buffer); + LV_ASSERT_NULL(draw_buf); + + const uint8_t * ptr = draw_buf->data; + int32_t width = draw_buf->header.w; + int32_t height = draw_buf->header.h; + vg_lite_buffer_format_t format = lv_vg_lite_vg_fmt(draw_buf->header.cf); + + if(LV_COLOR_FORMAT_IS_INDEXED(draw_buf->header.cf)) + ptr += LV_COLOR_INDEXED_PALETTE_SIZE(draw_buf->header.cf) * 4; + + width = lv_vg_lite_width_align(width); + + lv_vg_lite_buffer_init(buffer, ptr, width, height, format, false); + + /* Alpha image need to be multiplied by color */ + if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(draw_buf->header.cf)) { + buffer->image_mode = VG_LITE_MULTIPLY_IMAGE_MODE; + } +} + +void lv_vg_lite_image_matrix(vg_lite_matrix_t * matrix, int32_t x, int32_t y, const lv_draw_image_dsc_t * dsc) +{ + LV_ASSERT_NULL(matrix); + LV_ASSERT_NULL(dsc); + + int32_t rotation = dsc->rotation; + int32_t scale_x = dsc->scale_x; + int32_t scale_y = dsc->scale_y; + + vg_lite_translate(x, y, matrix); + + if(rotation != 0 || scale_x != LV_SCALE_NONE || scale_y != LV_SCALE_NONE) { + lv_point_t pivot = dsc->pivot; + vg_lite_translate(pivot.x, pivot.y, matrix); + + if(rotation != 0) { + vg_lite_rotate(rotation * 0.1f, matrix); + } + + if(scale_x != LV_SCALE_NONE || scale_y != LV_SCALE_NONE) { + vg_lite_scale( + (vg_lite_float_t)scale_x / LV_SCALE_NONE, + (vg_lite_float_t)scale_y / LV_SCALE_NONE, + matrix); + } + + vg_lite_translate(-pivot.x, -pivot.y, matrix); + } +} + +bool lv_vg_lite_buffer_open_image(vg_lite_buffer_t * buffer, lv_image_decoder_dsc_t * decoder_dsc, const void * src, + bool no_cache) +{ + LV_ASSERT_NULL(buffer); + LV_ASSERT_NULL(decoder_dsc); + LV_ASSERT_NULL(src); + + lv_image_decoder_args_t args; + lv_memzero(&args, sizeof(lv_image_decoder_args_t)); + args.premultiply = !lv_vg_lite_support_blend_normal(); + args.stride_align = true; + args.use_indexed = true; + args.no_cache = no_cache; + + lv_result_t res = lv_image_decoder_open(decoder_dsc, src, &args); + if(res != LV_RESULT_OK) { + LV_LOG_ERROR("Failed to open image"); + return false; + } + + const lv_draw_buf_t * decoded = decoder_dsc->decoded; + if(decoded == NULL || decoded->data == NULL) { + lv_image_decoder_close(decoder_dsc); + LV_LOG_ERROR("image data is NULL"); + return false; + } + + if(!lv_vg_lite_is_src_cf_supported(decoded->header.cf)) { + LV_LOG_ERROR("unsupported color format: %d", decoded->header.cf); + lv_image_decoder_close(decoder_dsc); + return false; + } + + if(LV_COLOR_FORMAT_IS_INDEXED(decoded->header.cf)) { + uint32_t palette_size = LV_COLOR_INDEXED_PALETTE_SIZE(decoded->header.cf); + LV_VG_LITE_CHECK_ERROR(vg_lite_set_CLUT(palette_size, (vg_lite_uint32_t *)decoded->data)); + } + + lv_vg_lite_buffer_from_draw_buf(buffer, decoded); + return true; +} + +void lv_vg_lite_rect(vg_lite_rectangle_t * rect, const lv_area_t * area) +{ + rect->x = area->x1; + rect->y = area->y1; + rect->width = lv_area_get_width(area); + rect->height = lv_area_get_height(area); +} + +uint32_t lv_vg_lite_get_palette_size(vg_lite_buffer_format_t format) +{ + uint32_t size = 0; + switch(format) { + case VG_LITE_INDEX_1: + size = 1 << 1; + break; + case VG_LITE_INDEX_2: + size = 1 << 2; + break; + case VG_LITE_INDEX_4: + size = 1 << 4; + break; + case VG_LITE_INDEX_8: + size = 1 << 8; + break; + default: + break; + } + return size; +} + +vg_lite_color_t lv_vg_lite_color(lv_color_t color, lv_opa_t opa, bool pre_mul) +{ + if(pre_mul && opa < LV_OPA_MAX) { + color.red = LV_UDIV255(color.red * opa); + color.green = LV_UDIV255(color.green * opa); + color.blue = LV_UDIV255(color.blue * opa); + } + return (uint32_t)opa << 24 | (uint32_t)color.blue << 16 | (uint32_t)color.green << 8 | color.red; +} + +vg_lite_blend_t lv_vg_lite_blend_mode(lv_blend_mode_t blend_mode) +{ + if(lv_vg_lite_support_blend_normal()) { + switch(blend_mode) { + case LV_BLEND_MODE_NORMAL: /**< Simply mix according to the opacity value*/ + return VG_LITE_BLEND_NORMAL_LVGL; + + case LV_BLEND_MODE_ADDITIVE: /**< Add the respective color channels*/ + return VG_LITE_BLEND_ADDITIVE_LVGL; + + case LV_BLEND_MODE_SUBTRACTIVE: /**< Subtract the foreground from the background*/ + return VG_LITE_BLEND_SUBTRACT_LVGL; + + case LV_BLEND_MODE_MULTIPLY: /**< Multiply the foreground and background*/ + return VG_LITE_BLEND_MULTIPLY_LVGL; + + default: + return VG_LITE_BLEND_NONE; + } + } + + switch(blend_mode) { + case LV_BLEND_MODE_NORMAL: /**< Simply mix according to the opacity value*/ + return VG_LITE_BLEND_SRC_OVER; + + case LV_BLEND_MODE_ADDITIVE: /**< Add the respective color channels*/ + return VG_LITE_BLEND_ADDITIVE; + + case LV_BLEND_MODE_SUBTRACTIVE: /**< Subtract the foreground from the background*/ + return VG_LITE_BLEND_SUBTRACT; + + case LV_BLEND_MODE_MULTIPLY: /**< Multiply the foreground and background*/ + return VG_LITE_BLEND_MULTIPLY; + + default: + return VG_LITE_BLEND_NONE; + } +} + +bool lv_vg_lite_buffer_check(const vg_lite_buffer_t * buffer, bool is_src) +{ + uint32_t mul; + uint32_t div; + uint32_t align; + int32_t stride; + + if(!buffer) { + LV_LOG_ERROR("buffer is NULL"); + return false; + } + + if(buffer->width < 1) { + LV_LOG_ERROR("buffer width(%d) < 1", (int)buffer->width); + return false; + } + + if(buffer->height < 1) { + LV_LOG_ERROR("buffer height(%d) < 1", (int)buffer->height); + return false; + } + + if(buffer->stride < 1) { + LV_LOG_ERROR("buffer stride(%d) < 1", (int)buffer->stride); + return false; + } + + if(!(buffer->tiled == VG_LITE_LINEAR || buffer->tiled == VG_LITE_TILED)) { + LV_LOG_ERROR("buffer tiled(%d) is invalid", (int)buffer->tiled); + return false; + } + + if(buffer->memory == NULL) { + LV_LOG_ERROR("buffer memory is NULL"); + return false; + } + + if((uint32_t)(uintptr_t)buffer->memory != buffer->address) { + LV_LOG_ERROR("buffer memory(%p) != address(%p)", + buffer->memory, (void *)(uintptr_t)buffer->address); + return false; + } + + if(is_src && buffer->width != (vg_lite_int32_t)lv_vg_lite_width_align(buffer->width)) { + LV_LOG_ERROR("buffer width(%d) is not aligned", (int)buffer->width); + return false; + } + + if(!LV_VG_LITE_IS_ALIGNED(buffer->memory, LV_DRAW_BUF_ALIGN)) { + LV_LOG_ERROR("buffer address(%p) is not aligned to %d", buffer->memory, LV_DRAW_BUF_ALIGN); + return false; + } + + lv_vg_lite_buffer_format_bytes(buffer->format, &mul, &div, &align); + stride = LV_VG_LITE_ALIGN((buffer->width * mul / div), align); + + if(buffer->stride != stride) { + LV_LOG_ERROR("buffer stride(%d) != %d", (int)buffer->stride, (int)stride); + return false; + } + + if(!(buffer->image_mode == VG_LITE_NORMAL_IMAGE_MODE + || buffer->image_mode == VG_LITE_NONE_IMAGE_MODE + || buffer->image_mode == VG_LITE_MULTIPLY_IMAGE_MODE)) { + LV_LOG_ERROR("buffer image_mode(%d) is invalid", (int)buffer->image_mode); + return false; + } + + if(!(buffer->transparency_mode == VG_LITE_IMAGE_OPAQUE + || buffer->transparency_mode == VG_LITE_IMAGE_TRANSPARENT)) { + LV_LOG_ERROR("buffer transparency_mode(%d) is invalid", + (int)buffer->transparency_mode); + return false; + } + + return true; +} + +bool lv_vg_lite_path_check(const vg_lite_path_t * path) +{ + if(path == NULL) { + LV_LOG_ERROR("path is NULL"); + return false; + } + + if(path->path == NULL) { + LV_LOG_ERROR("path->path is NULL"); + return false; + } + + uint8_t fmt_len = lv_vg_lite_path_format_len(path->format); + if(!fmt_len) { + LV_LOG_ERROR("path format(%d) is invalid", (int)path->format); + return false; + } + + size_t len = path->path_length / fmt_len; + + if(len < 1) { + LV_LOG_ERROR("path length(%d) error", (int)path->path_length); + return false; + } + + const uint8_t * cur = path->path; + const uint8_t * end = cur + path->path_length; + + while(cur < end) { + /* get op code */ + uint8_t op_code = VLC_GET_OP_CODE(cur); + + /* get arguments length */ + uint8_t arg_len = lv_vg_lite_vlc_op_arg_len(op_code); + + /* get next op code */ + cur += (fmt_len * (1 + arg_len)) ; + + /* break if end */ + if(op_code == VLC_OP_END) { + break; + } + } + + if(cur != end) { + LV_LOG_ERROR("path length(%d) error", (int)path->path_length); + return false; + } + + uint8_t end_op_code = VLC_GET_OP_CODE(end - fmt_len); + if(end_op_code != VLC_OP_END) { + LV_LOG_ERROR("%d (%s) -> is NOT VLC_OP_END", end_op_code, lv_vg_lite_vlc_op_string(end_op_code)); + return false; + } + + return true; +} + +bool lv_vg_lite_support_blend_normal(void) +{ + return vg_lite_query_feature(gcFEATURE_BIT_VG_LVGL_SUPPORT); +} + +bool lv_vg_lite_16px_align(void) +{ + return vg_lite_query_feature(gcFEATURE_BIT_VG_16PIXELS_ALIGN); +} + +void lv_vg_lite_draw_linear_grad( + vg_lite_buffer_t * buffer, + vg_lite_path_t * path, + const lv_area_t * area, + const lv_grad_dsc_t * grad, + const vg_lite_matrix_t * matrix, + vg_lite_fill_t fill, + vg_lite_blend_t blend) +{ + LV_ASSERT_NULL(buffer); + LV_ASSERT_NULL(path); + LV_ASSERT_NULL(area); + LV_ASSERT_NULL(grad); + + LV_ASSERT(grad->dir != LV_GRAD_DIR_NONE); + + vg_lite_uint32_t colors[VLC_MAX_GRADIENT_STOPS]; + vg_lite_uint32_t stops[VLC_MAX_GRADIENT_STOPS]; + + /* Gradient setup */ + uint8_t cnt = grad->stops_count; + LV_ASSERT(cnt < VLC_MAX_GRADIENT_STOPS); + for(uint8_t i = 0; i < cnt; i++) { + stops[i] = grad->stops[i].frac; + const lv_color_t * c = &grad->stops[i].color; + lv_opa_t opa = grad->stops[i].opa; + + /* lvgl color -> gradient color */ + lv_color_t grad_color = lv_color_make(c->blue, c->green, c->red); + colors[i] = lv_vg_lite_color(grad_color, opa, true); + } + + vg_lite_linear_gradient_t gradient; + lv_memzero(&gradient, sizeof(gradient)); + + LV_VG_LITE_CHECK_ERROR(vg_lite_init_grad(&gradient)); + LV_VG_LITE_CHECK_ERROR(vg_lite_set_grad(&gradient, cnt, colors, stops)); + LV_VG_LITE_CHECK_ERROR(vg_lite_update_grad(&gradient)); + + vg_lite_matrix_t * grad_matrix = vg_lite_get_grad_matrix(&gradient); + vg_lite_identity(grad_matrix); + vg_lite_translate(area->x1, area->y1, grad_matrix); + + if(grad->dir == LV_GRAD_DIR_VER) { + vg_lite_scale(1, lv_area_get_height(area) / 256.0f, grad_matrix); + vg_lite_rotate(90, grad_matrix); + } + else { /*LV_GRAD_DIR_HOR*/ + vg_lite_scale(lv_area_get_width(area) / 256.0f, 1, grad_matrix); + } + + LV_VG_LITE_CHECK_ERROR(vg_lite_draw_grad( + buffer, + path, + fill, + (vg_lite_matrix_t *)matrix, + &gradient, + blend)); + + LV_VG_LITE_CHECK_ERROR(vg_lite_clear_grad(&gradient)); +} + +void lv_vg_lite_matrix_multiply(vg_lite_matrix_t * matrix, const vg_lite_matrix_t * mult) +{ + vg_lite_matrix_t temp; + int row, column; + + /* Process all rows. */ + for(row = 0; row < 3; row++) { + /* Process all columns. */ + for(column = 0; column < 3; column++) { + /* Compute matrix entry. */ + temp.m[row][column] = (matrix->m[row][0] * mult->m[0][column]) + + (matrix->m[row][1] * mult->m[1][column]) + + (matrix->m[row][2] * mult->m[2][column]); + } + } + + /* Copy temporary matrix into result. */ + lv_memcpy(matrix, &temp, sizeof(temp)); +} + +void lv_vg_lite_matrix_flip_y(vg_lite_matrix_t * matrix) +{ + matrix->m[1][1] = -matrix->m[1][1]; +} + +bool lv_vg_lite_matrix_inverse(vg_lite_matrix_t * result, const vg_lite_matrix_t * matrix) +{ + vg_lite_float_t det00, det01, det02; + vg_lite_float_t d; + bool is_affine; + + /* Test for identity matrix. */ + if(matrix == NULL) { + result->m[0][0] = 1.0f; + result->m[0][1] = 0.0f; + result->m[0][2] = 0.0f; + result->m[1][0] = 0.0f; + result->m[1][1] = 1.0f; + result->m[1][2] = 0.0f; + result->m[2][0] = 0.0f; + result->m[2][1] = 0.0f; + result->m[2][2] = 1.0f; + + /* Success. */ + return true; + } + + det00 = (matrix->m[1][1] * matrix->m[2][2]) - (matrix->m[2][1] * matrix->m[1][2]); + det01 = (matrix->m[2][0] * matrix->m[1][2]) - (matrix->m[1][0] * matrix->m[2][2]); + det02 = (matrix->m[1][0] * matrix->m[2][1]) - (matrix->m[2][0] * matrix->m[1][1]); + + /* Compute determinant. */ + d = (matrix->m[0][0] * det00) + (matrix->m[0][1] * det01) + (matrix->m[0][2] * det02); + + /* Return 0 if there is no inverse matrix. */ + if(d == 0.0f) + return false; + + /* Compute reciprocal. */ + d = 1.0f / d; + + /* Determine if the matrix is affine. */ + is_affine = (matrix->m[2][0] == 0.0f) && (matrix->m[2][1] == 0.0f) && (matrix->m[2][2] == 1.0f); + + result->m[0][0] = d * det00; + result->m[0][1] = d * ((matrix->m[2][1] * matrix->m[0][2]) - (matrix->m[0][1] * matrix->m[2][2])); + result->m[0][2] = d * ((matrix->m[0][1] * matrix->m[1][2]) - (matrix->m[1][1] * matrix->m[0][2])); + result->m[1][0] = d * det01; + result->m[1][1] = d * ((matrix->m[0][0] * matrix->m[2][2]) - (matrix->m[2][0] * matrix->m[0][2])); + result->m[1][2] = d * ((matrix->m[1][0] * matrix->m[0][2]) - (matrix->m[0][0] * matrix->m[1][2])); + result->m[2][0] = is_affine ? 0.0f : d * det02; + result->m[2][1] = is_affine ? 0.0f : d * ((matrix->m[2][0] * matrix->m[0][1]) - (matrix->m[0][0] * matrix->m[2][1])); + result->m[2][2] = is_affine ? 1.0f : d * ((matrix->m[0][0] * matrix->m[1][1]) - (matrix->m[1][0] * matrix->m[0][1])); + + /* Success. */ + return true; +} + +lv_point_precise_t lv_vg_lite_matrix_transform_point(const vg_lite_matrix_t * matrix, const lv_point_precise_t * point) +{ + lv_point_precise_t p; + p.x = (lv_value_precise_t)(point->x * matrix->m[0][0] + point->y * matrix->m[0][1] + matrix->m[0][2]); + p.y = (lv_value_precise_t)(point->x * matrix->m[1][0] + point->y * matrix->m[1][1] + matrix->m[1][2]); + return p; +} + +void lv_vg_lite_set_scissor_area(const lv_area_t * area) +{ + vg_lite_enable_scissor(); + vg_lite_set_scissor( + area->x1, + area->y1, + lv_area_get_width(area), + lv_area_get_height(area)); +} + +void lv_vg_lite_disable_scissor(void) +{ + vg_lite_disable_scissor(); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_utils.h b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_utils.h new file mode 100644 index 000000000..a0edc735c --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/draw/vg_lite/lv_vg_lite_utils.h @@ -0,0 +1,181 @@ +/** + * @file lv_vg_lite_utils.h + * + */ + +#ifndef LV_VG_LITE_UTILS_H +#define LV_VG_LITE_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lvgl.h" + +#if LV_USE_DRAW_VG_LITE + +#include +#if LV_USE_VG_LITE_THORVG +#include "../../others/vg_lite_tvg/vg_lite.h" +#else +#include +#endif + +/********************* + * DEFINES + *********************/ + +#if LV_DRAW_BUF_ALIGN != 64 +#error "LV_DRAW_BUF_ALIGN must be 64" +#endif + +#define LV_VG_LITE_IS_ERROR(err) (err > 0) + +#define VLC_GET_OP_CODE(ptr) (*((uint8_t*)ptr)) + +#if LV_VG_LITE_USE_ASSERT +#define LV_VG_LITE_ASSERT(expr) LV_ASSERT(expr) +#else +#define LV_VG_LITE_ASSERT(expr) +#endif + +#define LV_VG_LITE_CHECK_ERROR(expr) \ + do { \ + vg_lite_error_t error = expr; \ + if (LV_VG_LITE_IS_ERROR(error)) { \ + LV_LOG_ERROR("Execute '" #expr "' error(%d): %s", \ + (int)error, lv_vg_lite_error_string(error)); \ + LV_VG_LITE_ASSERT(false); \ + } \ + } while (0) + +#define LV_VG_LITE_ASSERT_PATH(path) LV_VG_LITE_ASSERT(lv_vg_lite_path_check(path)) +#define LV_VG_LITE_ASSERT_SRC_BUFFER(buffer) LV_VG_LITE_ASSERT(lv_vg_lite_buffer_check(buffer, true)) +#define LV_VG_LITE_ASSERT_DEST_BUFFER(buffer) LV_VG_LITE_ASSERT(lv_vg_lite_buffer_check(buffer, false)) + +#define LV_VG_LITE_ALIGN(number, align_bytes) \ + (((number) + ((align_bytes)-1)) & ~((align_bytes)-1)) + +#define LV_VG_LITE_IS_ALIGNED(num, align) (((uintptr_t)(num) & ((align)-1)) == 0) + +#define LV_VG_LITE_IS_INDEX_FMT(fmt) \ + ((fmt) == VG_LITE_INDEX_1 \ + || (fmt) == VG_LITE_INDEX_2 \ + || (fmt) == VG_LITE_INDEX_4 \ + || (fmt) == VG_LITE_INDEX_8) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/* Print info */ + +void lv_vg_lite_dump_info(void); + +const char * lv_vg_lite_error_string(vg_lite_error_t error); + +const char * lv_vg_lite_feature_string(vg_lite_feature_t feature); + +const char * lv_vg_lite_buffer_format_string(vg_lite_buffer_format_t format); + +const char * lv_vg_lite_vlc_op_string(uint8_t vlc_op); + +void lv_vg_lite_path_dump_info(const vg_lite_path_t * path); + +void lv_vg_lite_buffer_dump_info(const vg_lite_buffer_t * buffer); + +void lv_vg_lite_matrix_dump_info(const vg_lite_matrix_t * matrix); + +bool lv_vg_lite_is_dest_cf_supported(lv_color_format_t cf); + +bool lv_vg_lite_is_src_cf_supported(lv_color_format_t cf); + +/* Converter */ + +vg_lite_buffer_format_t lv_vg_lite_vg_fmt(lv_color_format_t cf); + +void lv_vg_lite_buffer_format_bytes( + vg_lite_buffer_format_t format, + uint32_t * mul, + uint32_t * div, + uint32_t * bytes_align); + +uint32_t lv_vg_lite_width_to_stride(uint32_t w, vg_lite_buffer_format_t color_format); + +uint32_t lv_vg_lite_width_align(uint32_t w); + +void lv_vg_lite_buffer_init( + vg_lite_buffer_t * buffer, + const void * ptr, + int32_t width, + int32_t height, + vg_lite_buffer_format_t format, + bool tiled); + +void lv_vg_lite_buffer_from_draw_buf(vg_lite_buffer_t * buffer, const lv_draw_buf_t * draw_buf); + +void lv_vg_lite_image_matrix(vg_lite_matrix_t * matrix, int32_t x, int32_t y, const lv_draw_image_dsc_t * dsc); + +bool lv_vg_lite_buffer_open_image(vg_lite_buffer_t * buffer, lv_image_decoder_dsc_t * decoder_dsc, const void * src, + bool no_cache); + +vg_lite_blend_t lv_vg_lite_blend_mode(lv_blend_mode_t blend_mode); + +uint32_t lv_vg_lite_get_palette_size(vg_lite_buffer_format_t format); + +vg_lite_color_t lv_vg_lite_color(lv_color_t color, lv_opa_t opa, bool pre_mul); + +void lv_vg_lite_rect(vg_lite_rectangle_t * rect, const lv_area_t * area); + +/* Param checker */ + +bool lv_vg_lite_buffer_check(const vg_lite_buffer_t * buffer, bool is_src); + +bool lv_vg_lite_path_check(const vg_lite_path_t * path); + +/* Wrapper */ + +bool lv_vg_lite_support_blend_normal(void); + +bool lv_vg_lite_16px_align(void); + +void lv_vg_lite_draw_linear_grad( + vg_lite_buffer_t * buffer, + vg_lite_path_t * path, + const lv_area_t * area, + const lv_grad_dsc_t * grad, + const vg_lite_matrix_t * matrix, + vg_lite_fill_t fill, + vg_lite_blend_t blend); + +void lv_vg_lite_matrix_multiply(vg_lite_matrix_t * matrix, const vg_lite_matrix_t * mult); + +void lv_vg_lite_matrix_flip_y(vg_lite_matrix_t * matrix); + +bool lv_vg_lite_matrix_inverse(vg_lite_matrix_t * result, const vg_lite_matrix_t * matrix); + +lv_point_precise_t lv_vg_lite_matrix_transform_point(const vg_lite_matrix_t * matrix, const lv_point_precise_t * point); + +void lv_vg_lite_set_scissor_area(const lv_area_t * area); + +void lv_vg_lite_disable_scissor(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_DRAW_VG_LITE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*VG_LITE_UTILS_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/README.md b/lib/libesp32_lvgl/lvgl/src/drivers/README.md new file mode 100644 index 000000000..f755a3abe --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/README.md @@ -0,0 +1 @@ +High level drivers for display controllers, frame buffers, etc \ No newline at end of file diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/drm/lv_linux_drm.c b/lib/libesp32_lvgl/lvgl/src/drivers/display/drm/lv_linux_drm.c new file mode 100644 index 000000000..0f847344a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/drm/lv_linux_drm.c @@ -0,0 +1,837 @@ +/** + * @file lv_linux_drm.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_linux_drm.h" +#if LV_USE_LINUX_DRM + +#include "../../../lv_api_map.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/********************* + * DEFINES + *********************/ +#if LV_COLOR_DEPTH == 32 + #define DRM_FOURCC DRM_FORMAT_ARGB8888 +#elif LV_COLOR_DEPTH == 16 + #define DRM_FOURCC DRM_FORMAT_RGB565 +#else + #error LV_COLOR_DEPTH not supported +#endif + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + uint32_t handle; + uint32_t pitch; + uint32_t offset; + unsigned long int size; + uint8_t * map; + uint32_t fb_handle; +} drm_buffer_t; + +typedef struct { + int fd; + uint32_t conn_id, enc_id, crtc_id, plane_id, crtc_idx; + uint32_t width, height; + uint32_t mmWidth, mmHeight; + uint32_t fourcc; + drmModeModeInfo mode; + uint32_t blob_id; + drmModeCrtc * saved_crtc; + drmModeAtomicReq * req; + drmEventContext drm_event_ctx; + drmModePlane * plane; + drmModeCrtc * crtc; + drmModeConnector * conn; + uint32_t count_plane_props; + uint32_t count_crtc_props; + uint32_t count_conn_props; + drmModePropertyPtr plane_props[128]; + drmModePropertyPtr crtc_props[128]; + drmModePropertyPtr conn_props[128]; + drm_buffer_t drm_bufs[2]; /*DUMB buffers*/ +} drm_dev_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static uint32_t get_plane_property_id(drm_dev_t * drm_dev, const char * name); +static uint32_t get_crtc_property_id(drm_dev_t * drm_dev, const char * name); +static uint32_t get_conn_property_id(drm_dev_t * drm_dev, const char * name); +static void page_flip_handler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, + void * user_data); +static int drm_get_plane_props(drm_dev_t * drm_dev); +static int drm_get_crtc_props(drm_dev_t * drm_dev); +static int drm_get_conn_props(drm_dev_t * drm_dev); +static int drm_add_plane_property(drm_dev_t * drm_dev, const char * name, uint64_t value); +static int drm_add_crtc_property(drm_dev_t * drm_dev, const char * name, uint64_t value); +static int drm_add_conn_property(drm_dev_t * drm_dev, const char * name, uint64_t value); +static int drm_dmabuf_set_plane(drm_dev_t * drm_dev, drm_buffer_t * buf); +static int find_plane(drm_dev_t * drm_dev, unsigned int fourcc, uint32_t * plane_id, uint32_t crtc_id, + uint32_t crtc_idx); +static int drm_find_connector(drm_dev_t * drm_dev, int64_t connector_id); +static int drm_open(const char * path); +static int drm_setup(drm_dev_t * drm_dev, const char * device_path, int64_t connector_id, unsigned int fourcc); +static int drm_allocate_dumb(drm_dev_t * drm_dev, drm_buffer_t * buf); +static int drm_setup_buffers(drm_dev_t * drm_dev); +static void drm_flush_wait(lv_display_t * drm_dev); +static void drm_flush(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ +#ifndef DIV_ROUND_UP + #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) +#endif + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_display_t * lv_linux_drm_create(void) +{ + drm_dev_t * drm_dev = lv_malloc_zeroed(sizeof(drm_dev_t)); + LV_ASSERT_MALLOC(drm_dev); + if(drm_dev == NULL) return NULL; + + lv_display_t * disp = lv_display_create(800, 480); + if(disp == NULL) { + lv_free(drm_dev); + return NULL; + } + drm_dev->fd = -1; + lv_display_set_driver_data(disp, drm_dev); + lv_display_set_flush_wait_cb(disp, drm_flush_wait); + lv_display_set_flush_cb(disp, drm_flush); + + return disp; +} + +void lv_linux_drm_set_file(lv_display_t * disp, const char * file, int64_t connector_id) +{ + drm_dev_t * drm_dev = lv_display_get_driver_data(disp); + int ret; + + ret = drm_setup(drm_dev, file, connector_id, DRM_FOURCC); + if(ret) { + close(drm_dev->fd); + drm_dev->fd = -1; + return; + } + + ret = drm_setup_buffers(drm_dev); + if(ret) { + LV_LOG_ERROR("DRM buffer allocation failed"); + close(drm_dev->fd); + drm_dev->fd = -1; + return; + } + + LV_LOG_INFO("DRM subsystem and buffer mapped successfully"); + + int32_t hor_res = drm_dev->width; + int32_t ver_res = drm_dev->height; + int32_t width = drm_dev->mmWidth; + + size_t buf_size = LV_MIN(drm_dev->drm_bufs[1].size, drm_dev->drm_bufs[0].size); + lv_display_set_buffers(disp, drm_dev->drm_bufs[1].map, drm_dev->drm_bufs[0].map, buf_size, + LV_DISPLAY_RENDER_MODE_DIRECT); + lv_display_set_resolution(disp, hor_res, ver_res); + + if(width) { + lv_display_set_dpi(disp, DIV_ROUND_UP(hor_res * 25400, width * 1000)); + } + + LV_LOG_INFO("Resolution is set to %" LV_PRId32 "x%" LV_PRId32 " at %" LV_PRId32 "dpi", + hor_res, ver_res, lv_display_get_dpi(disp)); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static uint32_t get_plane_property_id(drm_dev_t * drm_dev, const char * name) +{ + uint32_t i; + + LV_LOG_TRACE("Find plane property: %s", name); + + for(i = 0; i < drm_dev->count_plane_props; ++i) + if(!lv_strcmp(drm_dev->plane_props[i]->name, name)) + return drm_dev->plane_props[i]->prop_id; + + LV_LOG_TRACE("Unknown plane property: %s", name); + + return 0; +} + +static uint32_t get_crtc_property_id(drm_dev_t * drm_dev, const char * name) +{ + uint32_t i; + + LV_LOG_TRACE("Find crtc property: %s", name); + + for(i = 0; i < drm_dev->count_crtc_props; ++i) + if(!lv_strcmp(drm_dev->crtc_props[i]->name, name)) + return drm_dev->crtc_props[i]->prop_id; + + LV_LOG_TRACE("Unknown crtc property: %s", name); + + return 0; +} + +static uint32_t get_conn_property_id(drm_dev_t * drm_dev, const char * name) +{ + uint32_t i; + + LV_LOG_TRACE("Find conn property: %s", name); + + for(i = 0; i < drm_dev->count_conn_props; ++i) + if(!lv_strcmp(drm_dev->conn_props[i]->name, name)) + return drm_dev->conn_props[i]->prop_id; + + LV_LOG_TRACE("Unknown conn property: %s", name); + + return 0; +} + +static void page_flip_handler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, + void * user_data) +{ + LV_UNUSED(fd); + LV_UNUSED(sequence); + LV_UNUSED(tv_sec); + LV_UNUSED(tv_usec); + LV_LOG_TRACE("flip"); + drm_dev_t * drm_dev = user_data; + if(drm_dev->req) { + drmModeAtomicFree(drm_dev->req); + drm_dev->req = NULL; + } +} + +static int drm_get_plane_props(drm_dev_t * drm_dev) +{ + uint32_t i; + + drmModeObjectPropertiesPtr props = drmModeObjectGetProperties(drm_dev->fd, drm_dev->plane_id, + DRM_MODE_OBJECT_PLANE); + if(!props) { + LV_LOG_ERROR("drmModeObjectGetProperties failed"); + return -1; + } + LV_LOG_TRACE("Found %u plane props", props->count_props); + drm_dev->count_plane_props = props->count_props; + for(i = 0; i < props->count_props; i++) { + drm_dev->plane_props[i] = drmModeGetProperty(drm_dev->fd, props->props[i]); + LV_LOG_TRACE("Added plane prop %u:%s", drm_dev->plane_props[i]->prop_id, drm_dev->plane_props[i]->name); + } + drmModeFreeObjectProperties(props); + + return 0; +} + +static int drm_get_crtc_props(drm_dev_t * drm_dev) +{ + uint32_t i; + + drmModeObjectPropertiesPtr props = drmModeObjectGetProperties(drm_dev->fd, drm_dev->crtc_id, + DRM_MODE_OBJECT_CRTC); + if(!props) { + LV_LOG_ERROR("drmModeObjectGetProperties failed"); + return -1; + } + LV_LOG_TRACE("Found %u crtc props", props->count_props); + drm_dev->count_crtc_props = props->count_props; + for(i = 0; i < props->count_props; i++) { + drm_dev->crtc_props[i] = drmModeGetProperty(drm_dev->fd, props->props[i]); + LV_LOG_TRACE("Added crtc prop %u:%s", drm_dev->crtc_props[i]->prop_id, drm_dev->crtc_props[i]->name); + } + drmModeFreeObjectProperties(props); + + return 0; +} + +static int drm_get_conn_props(drm_dev_t * drm_dev) +{ + uint32_t i; + + drmModeObjectPropertiesPtr props = drmModeObjectGetProperties(drm_dev->fd, drm_dev->conn_id, + DRM_MODE_OBJECT_CONNECTOR); + if(!props) { + LV_LOG_ERROR("drmModeObjectGetProperties failed"); + return -1; + } + LV_LOG_TRACE("Found %u connector props", props->count_props); + drm_dev->count_conn_props = props->count_props; + for(i = 0; i < props->count_props; i++) { + drm_dev->conn_props[i] = drmModeGetProperty(drm_dev->fd, props->props[i]); + LV_LOG_TRACE("Added connector prop %u:%s", drm_dev->conn_props[i]->prop_id, drm_dev->conn_props[i]->name); + } + drmModeFreeObjectProperties(props); + + return 0; +} + +static int drm_add_plane_property(drm_dev_t * drm_dev, const char * name, uint64_t value) +{ + int ret; + uint32_t prop_id = get_plane_property_id(drm_dev, name); + + if(!prop_id) { + LV_LOG_ERROR("Couldn't find plane prop %s", name); + return -1; + } + + ret = drmModeAtomicAddProperty(drm_dev->req, drm_dev->plane_id, get_plane_property_id(drm_dev, name), value); + if(ret < 0) { + LV_LOG_ERROR("drmModeAtomicAddProperty (%s:%" PRIu64 ") failed: %d", name, value, ret); + return ret; + } + + return 0; +} + +static int drm_add_crtc_property(drm_dev_t * drm_dev, const char * name, uint64_t value) +{ + int ret; + uint32_t prop_id = get_crtc_property_id(drm_dev, name); + + if(!prop_id) { + LV_LOG_ERROR("Couldn't find crtc prop %s", name); + return -1; + } + + ret = drmModeAtomicAddProperty(drm_dev->req, drm_dev->crtc_id, get_crtc_property_id(drm_dev, name), value); + if(ret < 0) { + LV_LOG_ERROR("drmModeAtomicAddProperty (%s:%" PRIu64 ") failed: %d", name, value, ret); + return ret; + } + + return 0; +} + +static int drm_add_conn_property(drm_dev_t * drm_dev, const char * name, uint64_t value) +{ + int ret; + uint32_t prop_id = get_conn_property_id(drm_dev, name); + + if(!prop_id) { + LV_LOG_ERROR("Couldn't find conn prop %s", name); + return -1; + } + + ret = drmModeAtomicAddProperty(drm_dev->req, drm_dev->conn_id, get_conn_property_id(drm_dev, name), value); + if(ret < 0) { + LV_LOG_ERROR("drmModeAtomicAddProperty (%s:%" PRIu64 ") failed: %d", name, value, ret); + return ret; + } + + return 0; +} + +static int drm_dmabuf_set_plane(drm_dev_t * drm_dev, drm_buffer_t * buf) +{ + int ret; + static int first = 1; + uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK; + + drm_dev->req = drmModeAtomicAlloc(); + + /* On first Atomic commit, do a modeset */ + if(first) { + drm_add_conn_property(drm_dev, "CRTC_ID", drm_dev->crtc_id); + + drm_add_crtc_property(drm_dev, "MODE_ID", drm_dev->blob_id); + drm_add_crtc_property(drm_dev, "ACTIVE", 1); + + flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; + + first = 0; + } + + drm_add_plane_property(drm_dev, "FB_ID", buf->fb_handle); + drm_add_plane_property(drm_dev, "CRTC_ID", drm_dev->crtc_id); + drm_add_plane_property(drm_dev, "SRC_X", 0); + drm_add_plane_property(drm_dev, "SRC_Y", 0); + drm_add_plane_property(drm_dev, "SRC_W", drm_dev->width << 16); + drm_add_plane_property(drm_dev, "SRC_H", drm_dev->height << 16); + drm_add_plane_property(drm_dev, "CRTC_X", 0); + drm_add_plane_property(drm_dev, "CRTC_Y", 0); + drm_add_plane_property(drm_dev, "CRTC_W", drm_dev->width); + drm_add_plane_property(drm_dev, "CRTC_H", drm_dev->height); + + ret = drmModeAtomicCommit(drm_dev->fd, drm_dev->req, flags, drm_dev); + if(ret) { + LV_LOG_ERROR("drmModeAtomicCommit failed: %s (%d)", strerror(errno), errno); + drmModeAtomicFree(drm_dev->req); + return ret; + } + + return 0; +} + +static int find_plane(drm_dev_t * drm_dev, unsigned int fourcc, uint32_t * plane_id, uint32_t crtc_id, + uint32_t crtc_idx) +{ + LV_UNUSED(crtc_id); + drmModePlaneResPtr planes; + drmModePlanePtr plane; + unsigned int i; + unsigned int j; + int ret = 0; + unsigned int format = fourcc; + + planes = drmModeGetPlaneResources(drm_dev->fd); + if(!planes) { + LV_LOG_ERROR("drmModeGetPlaneResources failed"); + return -1; + } + + LV_LOG_TRACE("drm: found planes %u", planes->count_planes); + + for(i = 0; i < planes->count_planes; ++i) { + plane = drmModeGetPlane(drm_dev->fd, planes->planes[i]); + if(!plane) { + LV_LOG_ERROR("drmModeGetPlane failed: %s", strerror(errno)); + break; + } + + if(!(plane->possible_crtcs & (1 << crtc_idx))) { + drmModeFreePlane(plane); + continue; + } + + for(j = 0; j < plane->count_formats; ++j) { + if(plane->formats[j] == format) + break; + } + + if(j == plane->count_formats) { + drmModeFreePlane(plane); + continue; + } + + *plane_id = plane->plane_id; + drmModeFreePlane(plane); + + LV_LOG_TRACE("found plane %d", *plane_id); + + break; + } + + if(i == planes->count_planes) + ret = -1; + + drmModeFreePlaneResources(planes); + + return ret; +} + +static int drm_find_connector(drm_dev_t * drm_dev, int64_t connector_id) +{ + drmModeConnector * conn = NULL; + drmModeEncoder * enc = NULL; + drmModeRes * res; + int i; + + if((res = drmModeGetResources(drm_dev->fd)) == NULL) { + LV_LOG_ERROR("drmModeGetResources() failed"); + return -1; + } + + if(res->count_crtcs <= 0) { + LV_LOG_ERROR("no Crtcs"); + goto free_res; + } + + /* find all available connectors */ + for(i = 0; i < res->count_connectors; i++) { + conn = drmModeGetConnector(drm_dev->fd, res->connectors[i]); + if(!conn) + continue; + + if(connector_id >= 0 && conn->connector_id != connector_id) { + drmModeFreeConnector(conn); + continue; + } + + if(conn->connection == DRM_MODE_CONNECTED) { + LV_LOG_TRACE("drm: connector %d: connected", conn->connector_id); + } + else if(conn->connection == DRM_MODE_DISCONNECTED) { + LV_LOG_TRACE("drm: connector %d: disconnected", conn->connector_id); + } + else if(conn->connection == DRM_MODE_UNKNOWNCONNECTION) { + LV_LOG_TRACE("drm: connector %d: unknownconnection", conn->connector_id); + } + else { + LV_LOG_TRACE("drm: connector %d: unknown", conn->connector_id); + } + + if(conn->connection == DRM_MODE_CONNECTED && conn->count_modes > 0) + break; + + drmModeFreeConnector(conn); + conn = NULL; + }; + + if(!conn) { + LV_LOG_ERROR("suitable connector not found"); + goto free_res; + } + + drm_dev->conn_id = conn->connector_id; + LV_LOG_TRACE("conn_id: %d", drm_dev->conn_id); + drm_dev->mmWidth = conn->mmWidth; + drm_dev->mmHeight = conn->mmHeight; + + lv_memcpy(&drm_dev->mode, &conn->modes[0], sizeof(drmModeModeInfo)); + + if(drmModeCreatePropertyBlob(drm_dev->fd, &drm_dev->mode, sizeof(drm_dev->mode), + &drm_dev->blob_id)) { + LV_LOG_ERROR("error creating mode blob"); + goto free_res; + } + + drm_dev->width = conn->modes[0].hdisplay; + drm_dev->height = conn->modes[0].vdisplay; + + for(i = 0 ; i < res->count_encoders; i++) { + enc = drmModeGetEncoder(drm_dev->fd, res->encoders[i]); + if(!enc) + continue; + + LV_LOG_TRACE("enc%d enc_id %d conn enc_id %d", i, enc->encoder_id, conn->encoder_id); + + if(enc->encoder_id == conn->encoder_id) + break; + + drmModeFreeEncoder(enc); + enc = NULL; + } + + if(enc) { + drm_dev->enc_id = enc->encoder_id; + LV_LOG_TRACE("enc_id: %d", drm_dev->enc_id); + drm_dev->crtc_id = enc->crtc_id; + LV_LOG_TRACE("crtc_id: %d", drm_dev->crtc_id); + drmModeFreeEncoder(enc); + } + else { + /* Encoder hasn't been associated yet, look it up */ + for(i = 0; i < conn->count_encoders; i++) { + int crtc, crtc_id = -1; + + enc = drmModeGetEncoder(drm_dev->fd, conn->encoders[i]); + if(!enc) + continue; + + for(crtc = 0 ; crtc < res->count_crtcs; crtc++) { + uint32_t crtc_mask = 1 << crtc; + + crtc_id = res->crtcs[crtc]; + + LV_LOG_TRACE("enc_id %d crtc%d id %d mask %x possible %x", enc->encoder_id, crtc, crtc_id, crtc_mask, + enc->possible_crtcs); + + if(enc->possible_crtcs & crtc_mask) + break; + } + + if(crtc_id > 0) { + drm_dev->enc_id = enc->encoder_id; + LV_LOG_TRACE("enc_id: %d", drm_dev->enc_id); + drm_dev->crtc_id = crtc_id; + LV_LOG_TRACE("crtc_id: %d", drm_dev->crtc_id); + break; + } + + drmModeFreeEncoder(enc); + enc = NULL; + } + + if(!enc) { + LV_LOG_ERROR("suitable encoder not found"); + goto free_res; + } + + drmModeFreeEncoder(enc); + } + + drm_dev->crtc_idx = UINT32_MAX; + + for(i = 0; i < res->count_crtcs; ++i) { + if(drm_dev->crtc_id == res->crtcs[i]) { + drm_dev->crtc_idx = i; + break; + } + } + + if(drm_dev->crtc_idx == UINT32_MAX) { + LV_LOG_ERROR("drm: CRTC not found"); + goto free_res; + } + + LV_LOG_TRACE("crtc_idx: %d", drm_dev->crtc_idx); + + return 0; + +free_res: + drmModeFreeResources(res); + + return -1; +} + +static int drm_open(const char * path) +{ + int fd, flags; + uint64_t has_dumb; + int ret; + + fd = open(path, O_RDWR); + if(fd < 0) { + LV_LOG_ERROR("cannot open \"%s\"", path); + return -1; + } + + /* set FD_CLOEXEC flag */ + if((flags = fcntl(fd, F_GETFD)) < 0 || + fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { + LV_LOG_ERROR("fcntl FD_CLOEXEC failed"); + goto err; + } + + /* check capability */ + ret = drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb); + if(ret < 0 || has_dumb == 0) { + LV_LOG_ERROR("drmGetCap DRM_CAP_DUMB_BUFFER failed or \"%s\" doesn't have dumb " + "buffer", path); + goto err; + } + + return fd; +err: + close(fd); + return -1; +} + +static int drm_setup(drm_dev_t * drm_dev, const char * device_path, int64_t connector_id, unsigned int fourcc) +{ + int ret; + + drm_dev->fd = drm_open(device_path); + if(drm_dev->fd < 0) + return -1; + + ret = drmSetClientCap(drm_dev->fd, DRM_CLIENT_CAP_ATOMIC, 1); + if(ret) { + LV_LOG_ERROR("No atomic modesetting support: %s", strerror(errno)); + goto err; + } + + ret = drm_find_connector(drm_dev, connector_id); + if(ret) { + LV_LOG_ERROR("available drm devices not found"); + goto err; + } + + ret = find_plane(drm_dev, fourcc, &drm_dev->plane_id, drm_dev->crtc_id, drm_dev->crtc_idx); + if(ret) { + LV_LOG_ERROR("Cannot find plane"); + goto err; + } + + drm_dev->plane = drmModeGetPlane(drm_dev->fd, drm_dev->plane_id); + if(!drm_dev->plane) { + LV_LOG_ERROR("Cannot get plane"); + goto err; + } + + drm_dev->crtc = drmModeGetCrtc(drm_dev->fd, drm_dev->crtc_id); + if(!drm_dev->crtc) { + LV_LOG_ERROR("Cannot get crtc"); + goto err; + } + + drm_dev->conn = drmModeGetConnector(drm_dev->fd, drm_dev->conn_id); + if(!drm_dev->conn) { + LV_LOG_ERROR("Cannot get connector"); + goto err; + } + + ret = drm_get_plane_props(drm_dev); + if(ret) { + LV_LOG_ERROR("Cannot get plane props"); + goto err; + } + + ret = drm_get_crtc_props(drm_dev); + if(ret) { + LV_LOG_ERROR("Cannot get crtc props"); + goto err; + } + + ret = drm_get_conn_props(drm_dev); + if(ret) { + LV_LOG_ERROR("Cannot get connector props"); + goto err; + } + + drm_dev->drm_event_ctx.version = DRM_EVENT_CONTEXT_VERSION; + drm_dev->drm_event_ctx.page_flip_handler = page_flip_handler; + drm_dev->fourcc = fourcc; + + LV_LOG_INFO("drm: Found plane_id: %u connector_id: %d crtc_id: %d", + drm_dev->plane_id, drm_dev->conn_id, drm_dev->crtc_id); + + LV_LOG_INFO("drm: %dx%d (%dmm X% dmm) pixel format %c%c%c%c", + drm_dev->width, drm_dev->height, drm_dev->mmWidth, drm_dev->mmHeight, + (fourcc >> 0) & 0xff, (fourcc >> 8) & 0xff, (fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff); + + return 0; + +err: + close(drm_dev->fd); + return -1; +} + +static int drm_allocate_dumb(drm_dev_t * drm_dev, drm_buffer_t * buf) +{ + struct drm_mode_create_dumb creq; + struct drm_mode_map_dumb mreq; + uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0}; + int ret; + + /* create dumb buffer */ + lv_memzero(&creq, sizeof(creq)); + creq.width = drm_dev->width; + creq.height = drm_dev->height; + creq.bpp = LV_COLOR_DEPTH; + ret = drmIoctl(drm_dev->fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq); + if(ret < 0) { + LV_LOG_ERROR("DRM_IOCTL_MODE_CREATE_DUMB fail"); + return -1; + } + + buf->handle = creq.handle; + buf->pitch = creq.pitch; + buf->size = creq.size; + + /* prepare buffer for memory mapping */ + lv_memzero(&mreq, sizeof(mreq)); + mreq.handle = creq.handle; + ret = drmIoctl(drm_dev->fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq); + if(ret) { + LV_LOG_ERROR("DRM_IOCTL_MODE_MAP_DUMB fail"); + return -1; + } + + buf->offset = mreq.offset; + LV_LOG_INFO("size %lu pitch %u offset %u", buf->size, buf->pitch, buf->offset); + + /* perform actual memory mapping */ + buf->map = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm_dev->fd, mreq.offset); + if(buf->map == MAP_FAILED) { + LV_LOG_ERROR("mmap fail"); + return -1; + } + + /* clear the framebuffer to 0 (= full transparency in ARGB8888) */ + lv_memzero(buf->map, creq.size); + + /* create framebuffer object for the dumb-buffer */ + handles[0] = creq.handle; + pitches[0] = creq.pitch; + offsets[0] = 0; + ret = drmModeAddFB2(drm_dev->fd, drm_dev->width, drm_dev->height, drm_dev->fourcc, + handles, pitches, offsets, &buf->fb_handle, 0); + if(ret) { + LV_LOG_ERROR("drmModeAddFB fail"); + return -1; + } + + return 0; +} + +static int drm_setup_buffers(drm_dev_t * drm_dev) +{ + int ret; + + /*Allocate DUMB buffers*/ + ret = drm_allocate_dumb(drm_dev, &drm_dev->drm_bufs[0]); + if(ret) + return ret; + + ret = drm_allocate_dumb(drm_dev, &drm_dev->drm_bufs[1]); + if(ret) + return ret; + + return 0; +} + +static void drm_flush_wait(lv_display_t * disp) +{ + drm_dev_t * drm_dev = lv_display_get_driver_data(disp); + + struct pollfd pfd; + pfd.fd = drm_dev->fd; + pfd.events = POLLIN; + + while(drm_dev->req) { + int ret; + do { + ret = poll(&pfd, 1, -1); + } while(ret == -1 && errno == EINTR); + + if(ret > 0) + drmHandleEvent(drm_dev->fd, &drm_dev->drm_event_ctx); + else { + LV_LOG_ERROR("poll failed: %s", strerror(errno)); + return; + } + } +} + +static void drm_flush(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map) +{ + if(!lv_display_flush_is_last(disp)) return; + + LV_UNUSED(area); + LV_UNUSED(px_map); + drm_dev_t * drm_dev = lv_display_get_driver_data(disp); + + for(int idx = 0; idx < 2; idx++) { + if(drm_dev->drm_bufs[idx].map == px_map) { + /*Request buffer swap*/ + if(drm_dmabuf_set_plane(drm_dev, &drm_dev->drm_bufs[idx])) { + LV_LOG_ERROR("Flush fail"); + return; + } + else + LV_LOG_TRACE("Flush done"); + } + } +} + +#endif /*LV_USE_LINUX_DRM*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/drm/lv_linux_drm.h b/lib/libesp32_lvgl/lvgl/src/drivers/display/drm/lv_linux_drm.h new file mode 100644 index 000000000..a75d19586 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/drm/lv_linux_drm.h @@ -0,0 +1,46 @@ +/** + * @file lv_linux_drm_h + * + */ + +#ifndef LV_LINUX_DRM_H +#define LV_LINUX_DRM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../../display/lv_display.h" + +#if LV_USE_LINUX_DRM + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +lv_display_t * lv_linux_drm_create(void); + +void lv_linux_drm_set_file(lv_display_t * disp, const char * file, int64_t connector_id); + +/********************** + * MACROS + **********************/ + +#endif /* LV_USE_LINUX_DRM */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV_LINUX_DRM_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/fb/lv_linux_fbdev.c b/lib/libesp32_lvgl/lvgl/src/drivers/display/fb/lv_linux_fbdev.c new file mode 100644 index 000000000..c835efa80 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/fb/lv_linux_fbdev.c @@ -0,0 +1,290 @@ +/** + * @file lv_linux_fbdev.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_linux_fbdev.h" +#if LV_USE_LINUX_FBDEV + +#include +#include +#include +#include +#include +#include +#include +#include + +#if LV_LINUX_FBDEV_BSD + #include + #include + #include +#else + #include +#endif /* LV_LINUX_FBDEV_BSD */ + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +struct bsd_fb_var_info { + uint32_t xoffset; + uint32_t yoffset; + uint32_t xres; + uint32_t yres; + int bits_per_pixel; +}; + +struct bsd_fb_fix_info { + long int line_length; + long int smem_len; +}; + +typedef struct { + const char * devname; + lv_color_format_t color_format; +#if LV_LINUX_FBDEV_BSD + struct bsd_fb_var_info vinfo; + struct bsd_fb_fix_info finfo; +#else + struct fb_var_screeninfo vinfo; + struct fb_fix_screeninfo finfo; +#endif /* LV_LINUX_FBDEV_BSD */ + char * fbp; + long int screensize; + int fbfd; +} lv_linux_fb_t; + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p); +static uint32_t tick_get_cb(void); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +#if LV_LINUX_FBDEV_BSD + #define FBIOBLANK FBIO_BLANK +#endif /* LV_LINUX_FBDEV_BSD */ + +#ifndef DIV_ROUND_UP + #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) +#endif + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_display_t * lv_linux_fbdev_create(void) +{ + static bool inited = false; + if(!inited) { + lv_tick_set_cb(tick_get_cb), + inited = true; + } + + lv_linux_fb_t * dsc = lv_malloc_zeroed(sizeof(lv_linux_fb_t)); + LV_ASSERT_MALLOC(dsc); + if(dsc == NULL) return NULL; + + lv_display_t * disp = lv_display_create(800, 480); + if(disp == NULL) { + lv_free(dsc); + return NULL; + } + dsc->fbfd = -1; + lv_display_set_driver_data(disp, dsc); + lv_display_set_flush_cb(disp, flush_cb); + + return disp; +} + +void lv_linux_fbdev_set_file(lv_display_t * disp, const char * file) +{ + char * devname = lv_malloc(lv_strlen(file) + 1); + LV_ASSERT_MALLOC(devname); + if(devname == NULL) return; + lv_strcpy(devname, file); + + lv_linux_fb_t * dsc = lv_display_get_driver_data(disp); + dsc->devname = devname; + + if(dsc->fbfd > 0) close(dsc->fbfd); + + /* Open the file for reading and writing*/ + dsc->fbfd = open(dsc->devname, O_RDWR); + if(dsc->fbfd == -1) { + perror("Error: cannot open framebuffer device"); + return; + } + LV_LOG_INFO("The framebuffer device was opened successfully"); + + /* Make sure that the display is on.*/ + if(ioctl(dsc->fbfd, FBIOBLANK, FB_BLANK_UNBLANK) != 0) { + perror("ioctl(FBIOBLANK)"); + /* Don't return. Some framebuffer drivers like efifb or simplefb don't implement FBIOBLANK.*/ + } + +#if LV_LINUX_FBDEV_BSD + struct fbtype fb; + unsigned line_length; + + /*Get fb type*/ + if(ioctl(dsc->fbfd, FBIOGTYPE, &fb) != 0) { + perror("ioctl(FBIOGTYPE)"); + return; + } + + /*Get screen width*/ + if(ioctl(dsc->fbfd, FBIO_GETLINEWIDTH, &line_length) != 0) { + perror("ioctl(FBIO_GETLINEWIDTH)"); + return; + } + + dsc->vinfo.xres = (unsigned) fb.fb_width; + dsc->vinfo.yres = (unsigned) fb.fb_height; + dsc->vinfo.bits_per_pixel = fb.fb_depth; + dsc->vinfo.xoffset = 0; + dsc->vinfo.yoffset = 0; + dsc->finfo.line_length = line_length; + dsc->finfo.smem_len = dsc->finfo.line_length * dsc->vinfo.yres; +#else /* LV_LINUX_FBDEV_BSD */ + + /* Get fixed screen information*/ + if(ioctl(dsc->fbfd, FBIOGET_FSCREENINFO, &dsc->finfo) == -1) { + perror("Error reading fixed information"); + return; + } + + /* Get variable screen information*/ + if(ioctl(dsc->fbfd, FBIOGET_VSCREENINFO, &dsc->vinfo) == -1) { + perror("Error reading variable information"); + return; + } +#endif /* LV_LINUX_FBDEV_BSD */ + + LV_LOG_INFO("%dx%d, %dbpp", dsc->vinfo.xres, dsc->vinfo.yres, dsc->vinfo.bits_per_pixel); + + /* Figure out the size of the screen in bytes*/ + dsc->screensize = dsc->finfo.smem_len;/*finfo.line_length * vinfo.yres;*/ + + /* Map the device to memory*/ + dsc->fbp = (char *)mmap(0, dsc->screensize, PROT_READ | PROT_WRITE, MAP_SHARED, dsc->fbfd, 0); + if((intptr_t)dsc->fbp == -1) { + perror("Error: failed to map framebuffer device to memory"); + return; + } + + /* Don't initialise the memory to retain what's currently displayed / avoid clearing the screen. + * This is important for applications that only draw to a subsection of the full framebuffer.*/ + + LV_LOG_INFO("The framebuffer device was mapped to memory successfully"); + + switch(dsc->vinfo.bits_per_pixel) { + case 16: + lv_display_set_color_format(disp, LV_COLOR_FORMAT_RGB565); + break; + case 24: + lv_display_set_color_format(disp, LV_COLOR_FORMAT_RGB888); + break; + case 32: + lv_display_set_color_format(disp, LV_COLOR_FORMAT_XRGB8888); + break; + default: + LV_LOG_WARN("Not supported color format (%d bits)", dsc->vinfo.bits_per_pixel); + return; + } + + int32_t hor_res = dsc->vinfo.xres; + int32_t ver_res = dsc->vinfo.yres; + int32_t width = dsc->vinfo.width; + uint32_t draw_buf_size = hor_res * (dsc->vinfo.bits_per_pixel >> 3); + if(LV_LINUX_FBDEV_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL) { + draw_buf_size *= LV_LINUX_FBDEV_BUFFER_SIZE; + } + else { + draw_buf_size *= ver_res; + } + + uint8_t * draw_buf = NULL; + uint8_t * draw_buf_2 = NULL; + draw_buf = malloc(draw_buf_size); + + if(LV_LINUX_FBDEV_BUFFER_COUNT == 2) { + draw_buf_2 = malloc(draw_buf_size); + } + + lv_display_set_buffers(disp, draw_buf, draw_buf_2, draw_buf_size, LV_LINUX_FBDEV_RENDER_MODE); + lv_display_set_resolution(disp, hor_res, ver_res); + + if(width) { + lv_display_set_dpi(disp, DIV_ROUND_UP(hor_res * 254, width * 10)); + } + + LV_LOG_INFO("Resolution is set to %" LV_PRId32 "x%" LV_PRId32 " at %" LV_PRId32 "dpi", + hor_res, ver_res, lv_display_get_dpi(disp)); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p) +{ + lv_linux_fb_t * dsc = lv_display_get_driver_data(disp); + + if(dsc->fbp == NULL || + area->x2 < 0 || area->y2 < 0 || + area->x1 > (int32_t)dsc->vinfo.xres - 1 || area->y1 > (int32_t)dsc->vinfo.yres - 1) { + lv_display_flush_ready(disp); + return; + } + + int32_t w = lv_area_get_width(area); + uint32_t px_size = lv_color_format_get_size(lv_display_get_color_format(disp)); + uint32_t color_pos = (area->x1 + dsc->vinfo.xoffset) * px_size + area->y1 * dsc->finfo.line_length; + uint32_t fb_pos = color_pos + dsc->vinfo.yoffset * dsc->finfo.line_length; + + uint8_t * fbp = (uint8_t *)dsc->fbp; + int32_t y; + if(LV_LINUX_FBDEV_RENDER_MODE == LV_DISPLAY_RENDER_MODE_DIRECT) { + for(y = area->y1; y <= area->y2; y++) { + lv_memcpy(&fbp[fb_pos], &color_p[color_pos], w * px_size); + fb_pos += dsc->finfo.line_length; + color_pos += dsc->finfo.line_length; + } + } + else { + for(y = area->y1; y <= area->y2; y++) { + lv_memcpy(&fbp[fb_pos], color_p, w * px_size); + fb_pos += dsc->finfo.line_length; + color_p += w * px_size; + } + } + + lv_display_flush_ready(disp); +} + +static uint32_t tick_get_cb(void) +{ + struct timeval tv_now; + gettimeofday(&tv_now, NULL); + uint64_t time_ms; + time_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000; + return time_ms; +} + +#endif /*LV_USE_LINUX_FBDEV*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/fb/lv_linux_fbdev.h b/lib/libesp32_lvgl/lvgl/src/drivers/display/fb/lv_linux_fbdev.h new file mode 100644 index 000000000..b94723c9f --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/fb/lv_linux_fbdev.h @@ -0,0 +1,46 @@ +/** + * @file lv_linux_fb_dev_h + * + */ + +#ifndef LV_LINUX_FB_DEV_H +#define LV_LINUX_FB_DEV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../../display/lv_display.h" + +#if LV_USE_LINUX_FBDEV + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +lv_display_t * lv_linux_fbdev_create(void); + +void lv_linux_fbdev_set_file(lv_display_t * disp, const char * file); + +/********************** + * MACROS + **********************/ + +#endif /* LV_USE_LINUX_FBDEV */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV_LINUX_FB_DEV_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/ili9341/lv_ili9341.c b/lib/libesp32_lvgl/lvgl/src/drivers/display/ili9341/lv_ili9341.c new file mode 100644 index 000000000..a6b2acf7e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/ili9341/lv_ili9341.c @@ -0,0 +1,117 @@ +/** + * @file lv_ili9341.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_ili9341.h" + +#if LV_USE_ILI9341 + +/********************* + * DEFINES + *********************/ + +#define CMD_FRMCTR1 0xB1 /* Frame Rate Control (In Normal Mode/Full Colors) */ +#define CMD_FRMCTR2 0xB2 /* Frame Rate Control (In Idle Mode/8 colors) */ +#define CMD_FRMCTR3 0xB3 /* Frame Rate control (In Partial Mode/Full Colors) */ +#define CMD_INVCTR 0xB4 /* Display Inversion Control */ +#define CMD_DFUNCTR 0xB6 /* Display Function Control */ +#define CMD_PWCTR1 0xC0 /* Power Control 1 */ +#define CMD_PWCTR2 0xC1 /* Power Control 2 */ +#define CMD_VMCTR1 0xC5 /* VCOM Control 1 */ +#define CMD_VMCTR2 0xC7 /* VCOM Control 2 */ +#define CMD_PWCTRA 0xCB /* Power Control A */ +#define CMD_PWCTRB 0xCF /* Power Control B */ +#define CMD_GMCTRP1 0xE0 /* Positive Gamma Correction */ +#define CMD_GMCTRN1 0xE1 /* Negative Gamma Correction */ +#define CMD_DTCTRA 0xE8 /* Driver timing control A */ +#define CMD_DTCTRB 0xEA /* Driver timing control B */ +#define CMD_PONSEQ 0xED /* Power On Sequence */ +#define CMD_RDINDEX 0xD9 /* ili9341 */ +#define CMD_IDXRD 0xDD /* ILI9341 only, indexed control register read */ +#define CMD_ENA3G 0xF2 /* Enable 3 Gamma control */ +#define CMD_IFCTR 0xF6 /* Interface Control */ +#define CMD_PRCTR 0xF7 /* Pump ratio control */ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC CONSTANTS + **********************/ + +/* init commands based on LovyanGFX ILI9341 driver */ +static const uint8_t init_cmd_list[] = { + CMD_PWCTRB, 3, 0x00, 0xC1, 0x30, + CMD_PONSEQ, 4, 0x64, 0x03, 0x12, 0x81, + CMD_DTCTRA, 3, 0x85, 0x00, 0x78, + CMD_PWCTRA, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, + CMD_PRCTR, 1, 0x20, + CMD_DTCTRB, 2, 0x00, 0x00, + CMD_PWCTR1, 1, 0x23, + CMD_PWCTR2, 1, 0x10, + CMD_VMCTR1, 2, 0x3e, 0x28, + CMD_VMCTR2, 1, 0x86, + CMD_FRMCTR1, 2, 0x00, 0x13, + CMD_DFUNCTR, 2, 0x0A, 0xA2, + CMD_IFCTR, 3, 0x09, 0x30, 0x00, + CMD_ENA3G, 1, 0x00, + LV_LCD_CMD_SET_GAMMA_CURVE, 1, 0x01, + CMD_GMCTRP1, 15, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00, + CMD_GMCTRN1, 15, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, + LV_LCD_CMD_DELAY_MS, LV_LCD_CMD_EOF +}; + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_display_t * lv_ili9341_create(uint32_t hor_res, uint32_t ver_res, lv_lcd_flag_t flags, + lv_ili9341_send_cmd_cb_t send_cmd_cb, lv_ili9341_send_color_cb_t send_color_cb) +{ + lv_display_t * disp = lv_lcd_generic_mipi_create(hor_res, ver_res, flags, send_cmd_cb, send_color_cb); + lv_lcd_generic_mipi_send_cmd_list(disp, init_cmd_list); + return disp; +} + +void lv_ili9341_set_gap(lv_display_t * disp, uint16_t x, uint16_t y) +{ + lv_lcd_generic_mipi_set_gap(disp, x, y); +} + +void lv_ili9341_set_invert(lv_display_t * disp, bool invert) +{ + lv_lcd_generic_mipi_set_invert(disp, invert); +} + +void lv_ili9341_set_gamma_curve(lv_display_t * disp, uint8_t gamma) +{ + lv_lcd_generic_mipi_set_gamma_curve(disp, gamma); +} + +void lv_ili9341_send_cmd_list(lv_display_t * disp, const uint8_t * cmd_list) +{ + lv_lcd_generic_mipi_send_cmd_list(disp, cmd_list); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_ILI9341*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/ili9341/lv_ili9341.h b/lib/libesp32_lvgl/lvgl/src/drivers/display/ili9341/lv_ili9341.h new file mode 100644 index 000000000..c93fcba03 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/ili9341/lv_ili9341.h @@ -0,0 +1,93 @@ +/* + * lv_ili9341.h + * + * This driver is just a wrapper around the generic MIPI compatible LCD controller driver + * + */ + +#ifndef LV_ILI9341_H +#define LV_ILI9341_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../lcd/lv_lcd_generic_mipi.h" + +#if LV_USE_ILI9341 + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef lv_lcd_send_cmd_cb_t lv_ili9341_send_cmd_cb_t; +typedef lv_lcd_send_color_cb_t lv_ili9341_send_color_cb_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an LCD display with ILI9341 driver + * @param hor_res horizontal resolution + * @param ver_res vertical resolution + * @param flags default configuration settings (mirror, RGB ordering, etc.) + * @param send_cmd platform-dependent function to send a command to the LCD controller (usually uses polling transfer) + * @param send_color platform-dependent function to send pixel data to the LCD controller (usually uses DMA transfer: must implement a 'ready' callback) + * @return pointer to the created display + */ +lv_display_t * lv_ili9341_create(uint32_t hor_res, uint32_t ver_res, lv_lcd_flag_t flags, + lv_ili9341_send_cmd_cb_t send_cmd_cb, lv_ili9341_send_color_cb_t send_color_cb); + +/** + * Set gap, i.e., the offset of the (0,0) pixel in the VRAM + * @param disp display object + * @param x x offset + * @param y y offset + */ +void lv_ili9341_set_gap(lv_display_t * disp, uint16_t x, uint16_t y); + +/** + * Set color inversion + * @param disp display object + * @param invert false: normal, true: invert + */ +void lv_ili9341_set_invert(lv_display_t * disp, bool invert); + +/** + * Set gamma curve + * @param disp display object + * @param gamma gamma curve + */ +void lv_ili9341_set_gamma_curve(lv_display_t * disp, uint8_t gamma); + +/** + * Send list of commands. + * @param disp display object + * @param cmd_list controller and panel-specific commands + */ +void lv_ili9341_send_cmd_list(lv_display_t * disp, const uint8_t * cmd_list); + +/********************** + * OTHERS + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_USE_ILI9341*/ + +#endif /* LV_ILI9341_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/lcd/lv_lcd_generic_mipi.c b/lib/libesp32_lvgl/lvgl/src/drivers/display/lcd/lv_lcd_generic_mipi.c new file mode 100644 index 000000000..46bcf1b5a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/lcd/lv_lcd_generic_mipi.c @@ -0,0 +1,340 @@ +/** + * @file lv_lcd_generic_mipi.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_lcd_generic_mipi.h" + +#if LV_USE_GENERIC_MIPI + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void send_cmd(lv_lcd_generic_mipi_driver_t * drv, uint8_t cmd, uint8_t * param, size_t param_size); +static void send_color(lv_lcd_generic_mipi_driver_t * drv, uint8_t cmd, uint8_t * param, size_t param_size); +static void init(lv_lcd_generic_mipi_driver_t * drv, lv_lcd_flag_t flags); +static void set_mirror(lv_lcd_generic_mipi_driver_t * drv, bool mirror_x, bool mirror_y); +static void set_swap_xy(lv_lcd_generic_mipi_driver_t * drv, bool swap); +static void set_rotation(lv_lcd_generic_mipi_driver_t * drv, lv_display_rotation_t rot); +static void res_chg_event_cb(lv_event_t * e); +static lv_lcd_generic_mipi_driver_t * get_driver(lv_display_t * disp); +static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_display_t * lv_lcd_generic_mipi_create(uint32_t hor_res, uint32_t ver_res, lv_lcd_flag_t flags, + lv_lcd_send_cmd_cb_t send_cmd_cb, lv_lcd_send_color_cb_t send_color_cb) +{ + lv_display_t * disp = lv_display_create(hor_res, ver_res); + if(disp == NULL) { + return NULL; + } + + lv_lcd_generic_mipi_driver_t * drv = (lv_lcd_generic_mipi_driver_t *)lv_malloc(sizeof(lv_lcd_generic_mipi_driver_t)); + if(drv == NULL) { + lv_display_delete(disp); + return NULL; + } + + /* init driver struct */ + drv->disp = disp; + drv->send_cmd = send_cmd_cb; + drv->send_color = send_color_cb; + lv_display_set_driver_data(disp, (void *)drv); + + /* init controller */ + init(drv, flags); + + /* register resolution change callback (NOTE: this handles screen rotation as well) */ + lv_display_add_event_cb(disp, res_chg_event_cb, LV_EVENT_RESOLUTION_CHANGED, NULL); + + /* register flush callback */ + lv_display_set_flush_cb(disp, flush_cb); + + return disp; +} + +void lv_lcd_generic_mipi_set_gap(lv_display_t * disp, uint16_t x, uint16_t y) +{ + lv_lcd_generic_mipi_driver_t * drv = get_driver(disp); + drv->x_gap = x; + drv->y_gap = y; +} + +void lv_lcd_generic_mipi_set_invert(lv_display_t * disp, bool invert) +{ + lv_lcd_generic_mipi_driver_t * drv = get_driver(disp); + send_cmd(drv, invert ? LV_LCD_CMD_ENTER_INVERT_MODE : LV_LCD_CMD_EXIT_INVERT_MODE, NULL, 0); +} + +void lv_lcd_generic_mipi_set_address_mode(lv_display_t * disp, bool mirror_x, bool mirror_y, bool swap_xy, bool bgr) +{ + lv_lcd_generic_mipi_driver_t * drv = get_driver(disp); + uint8_t mad = drv->madctl_reg & ~(LV_LCD_MASK_RGB_ORDER); + if(bgr) { + mad |= LV_LCD_BIT_RGB_ORDER__BGR; + } + drv->madctl_reg = mad; + drv->mirror_x = mirror_x; + drv->mirror_y = mirror_y; + drv->swap_xy = swap_xy; + set_rotation(drv, lv_display_get_rotation(disp)); /* update screen */ +} + +void lv_lcd_generic_mipi_set_gamma_curve(lv_display_t * disp, uint8_t gamma) +{ + lv_lcd_generic_mipi_driver_t * drv = get_driver(disp); + send_cmd(drv, LV_LCD_CMD_SET_GAMMA_CURVE, (uint8_t[]) { + gamma, + }, 1); +} + +void lv_lcd_generic_mipi_send_cmd_list(lv_display_t * disp, const uint8_t * cmd_list) +{ + lv_lcd_generic_mipi_driver_t * drv = get_driver(disp); + while(1) { + uint8_t cmd = *cmd_list++; + uint8_t num = *cmd_list++; + if(cmd == LV_LCD_CMD_DELAY_MS) { + if(num == LV_LCD_CMD_EOF) /* end of list */ + break; + else { /* delay in 10 ms units*/ + lv_delay_ms((uint32_t)(num) * 10); + } + } + else { + drv->send_cmd(drv->disp, &cmd, 1, cmd_list, num); + cmd_list += num; + } + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Helper function to call the user-supplied 'send_cmd' function + * @param drv LCD driver object + * @param cmd command byte + * @param param parameter buffer + * @param param_size number of bytes of the parameters + */ +static void send_cmd(lv_lcd_generic_mipi_driver_t * drv, uint8_t cmd, uint8_t * param, size_t param_size) +{ + uint8_t cmdbuf = cmd; /* MIPI uses 8 bit commands */ + drv->send_cmd(drv->disp, &cmdbuf, 1, param, param_size); +} + +/** + * Helper function to call the user-supplied 'send_color' function + * @param drv LCD driver object + * @param cmd command byte + * @param param parameter buffer + * @param param_size number of bytes of the parameters + */ +static void send_color(lv_lcd_generic_mipi_driver_t * drv, uint8_t cmd, uint8_t * param, size_t param_size) +{ + uint8_t cmdbuf = cmd; /* MIPI uses 8 bit commands */ + drv->send_color(drv->disp, &cmdbuf, 1, param, param_size); +} + +/** + * Initialize LCD driver after a hard reset + * @param drv LCD driver object + */ +static void init(lv_lcd_generic_mipi_driver_t * drv, lv_lcd_flag_t flags) +{ + drv->x_gap = 0; + drv->y_gap = 0; + + /* init color mode and RGB order */ + drv->madctl_reg = flags & LV_LCD_FLAG_BGR ? LV_LCD_BIT_RGB_ORDER__BGR : LV_LCD_BIT_RGB_ORDER__RGB; + drv->colmod_reg = flags & LV_LCD_FLAG_RGB666 ? LV_LCD_PIXEL_FORMAT_RGB666 : LV_LCD_PIXEL_FORMAT_RGB565; + + /* init orientation */ + drv->mirror_x = flags & LV_LCD_FLAG_MIRROR_X; + drv->mirror_y = flags & LV_LCD_FLAG_MIRROR_Y; + drv->swap_xy = false; + /* update madctl_reg */ + set_swap_xy(drv, drv->swap_xy); + set_mirror(drv, drv->mirror_x, drv->mirror_y); + + /* enter sleep mode first */ + send_cmd(drv, LV_LCD_CMD_ENTER_SLEEP_MODE, NULL, 0); + lv_delay_ms(10); + + /* perform software reset */ + send_cmd(drv, LV_LCD_CMD_SOFT_RESET, NULL, 0); + lv_delay_ms(200); + + /* LCD goes into sleep mode and display will be turned off after power on reset, exit sleep mode first */ + send_cmd(drv, LV_LCD_CMD_EXIT_SLEEP_MODE, NULL, 0); + lv_delay_ms(300); + + send_cmd(drv, LV_LCD_CMD_ENTER_NORMAL_MODE, NULL, 0); + + send_cmd(drv, LV_LCD_CMD_SET_ADDRESS_MODE, (uint8_t[]) { + drv->madctl_reg, + }, 1); + send_cmd(drv, LV_LCD_CMD_SET_PIXEL_FORMAT, (uint8_t[]) { + drv->colmod_reg, + }, 1); + send_cmd(drv, LV_LCD_CMD_SET_DISPLAY_ON, NULL, 0); +} + +/** + * Set readout directions (used for rotating the display) + * @param drv LCD driver object + * @param mirror_x false: normal, true: mirrored + * @param mirror_y false: normal, true: mirrored + */ +static void set_mirror(lv_lcd_generic_mipi_driver_t * drv, bool mirror_x, bool mirror_y) +{ + uint8_t mad = drv->madctl_reg & ~(LV_LCD_MASK_COLUMN_ADDRESS_ORDER | LV_LCD_MASK_PAGE_ADDRESS_ORDER); + if(mirror_x) { + mad |= LV_LCD_BIT_COLUMN_ADDRESS_ORDER__RTOL; + } + if(mirror_y) { + mad |= LV_LCD_BIT_PAGE_ADDRESS_ORDER__BTOT; + } + drv->madctl_reg = mad; +} + +/** + * Swap horizontal and vertical readout (used for rotating the display) + * @param drv LCD driver object + * @param swap false: normal, true: swapped + */ +static void set_swap_xy(lv_lcd_generic_mipi_driver_t * drv, bool swap) +{ + uint8_t mad = drv->madctl_reg & ~(LV_LCD_MASK_PAGE_COLUMN_ORDER); + if(swap) { + mad |= LV_LCD_BIT_PAGE_COLUMN_ORDER__REVERSE; + } + drv->madctl_reg = mad; +} + +/** + * Flush display buffer to the LCD + * @param disp display object + * @param hor_res horizontal resolution + * @param area area stored in the buffer + * @param px_map buffer containing pixel data + * @note transfers pixel data to the LCD controller using the callbacks 'send_cmd' and 'send_color', which were + * passed to the 'lv_st7789_create()' function + */ +static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map) +{ + lv_lcd_generic_mipi_driver_t * drv = get_driver(disp); + + int32_t x_start = area->x1; + int32_t x_end = area->x2 + 1; + int32_t y_start = area->y1; + int32_t y_end = area->y2 + 1; + + LV_ASSERT((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position"); + + x_start += drv->x_gap; + x_end += drv->x_gap; + y_start += drv->y_gap; + y_end += drv->y_gap; + + /* define an area of frame memory where MCU can access */ + send_cmd(drv, LV_LCD_CMD_SET_COLUMN_ADDRESS, (uint8_t[]) { + (x_start >> 8) & 0xFF, + x_start & 0xFF, + ((x_end - 1) >> 8) & 0xFF, + (x_end - 1) & 0xFF, + }, 4); + send_cmd(drv, LV_LCD_CMD_SET_PAGE_ADDRESS, (uint8_t[]) { + (y_start >> 8) & 0xFF, + y_start & 0xFF, + ((y_end - 1) >> 8) & 0xFF, + (y_end - 1) & 0xFF, + }, 4); + /* transfer frame buffer */ + size_t len = (x_end - x_start) * (y_end - y_start) * lv_color_format_get_size(lv_display_get_color_format(disp)); + send_color(drv, LV_LCD_CMD_WRITE_MEMORY_START, px_map, len); +} + +/** + * Set rotation taking into account the current mirror and swap settings + * @param drv LCD driver object + * @param rot rotation + */ +static void set_rotation(lv_lcd_generic_mipi_driver_t * drv, lv_display_rotation_t rot) +{ + switch(rot) { + case LV_DISPLAY_ROTATION_0: + set_swap_xy(drv, drv->swap_xy); + set_mirror(drv, drv->mirror_x, drv->mirror_y); + break; + case LV_DISPLAY_ROTATION_90: + set_swap_xy(drv, !drv->swap_xy); + set_mirror(drv, !drv->mirror_x, drv->mirror_y); + break; + case LV_DISPLAY_ROTATION_180: + set_swap_xy(drv, drv->swap_xy); + set_mirror(drv, !drv->mirror_x, !drv->mirror_y); + break; + case LV_DISPLAY_ROTATION_270: + set_swap_xy(drv, !drv->swap_xy); + set_mirror(drv, drv->mirror_x, !drv->mirror_y); + break; + } + send_cmd(drv, LV_LCD_CMD_SET_ADDRESS_MODE, (uint8_t[]) { + drv->madctl_reg + }, 1); +} + +/** + * Handle LV_EVENT_RESOLUTION_CHANGED event (handles both resolution and rotation change) + * @param e LV_EVENT_RESOLUTION_CHANGED event + */ +static void res_chg_event_cb(lv_event_t * e) +{ + lv_display_t * disp = lv_event_get_current_target(e); + lv_lcd_generic_mipi_driver_t * drv = get_driver(disp); + + uint16_t hor_res = lv_display_get_horizontal_resolution(disp); + uint16_t ver_res = lv_display_get_vertical_resolution(disp); + lv_display_rotation_t rot = lv_display_get_rotation(disp); + + /* TODO: implement resolution change */ + LV_UNUSED(hor_res); + LV_UNUSED(ver_res); + + /* handle rotation */ + set_rotation(drv, rot); +} + +static lv_lcd_generic_mipi_driver_t * get_driver(lv_display_t * disp) +{ + return (lv_lcd_generic_mipi_driver_t *)lv_display_get_driver_data(disp); +} + +#endif /*LV_USE_GENERIC_MIPI*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/lcd/lv_lcd_generic_mipi.h b/lib/libesp32_lvgl/lvgl/src/drivers/display/lcd/lv_lcd_generic_mipi.h new file mode 100644 index 000000000..ae5c0ef14 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/lcd/lv_lcd_generic_mipi.h @@ -0,0 +1,241 @@ +/* + * lv_lcd_generic_mipi.h + * + * Generic driver for controllers adhering to the MIPI DBI/DCS specification + * + * Works with: + * + * ST7735 + * ST7789 + * ST7796 + * ILI9341 + * ILI9488 (NOTE: in SPI mode ILI9488 only supports RGB666 mode, which is currently not supported) + * + * any probably many more + * + */ + +#ifndef LV_LCD_GENERIC_MIPI_H +#define LV_LCD_GENERIC_MIPI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../../display/lv_display.h" + +#if LV_USE_GENERIC_MIPI + +/********************* + * DEFINES + *********************/ + +/* MIPI DCS (Display Command Set) v1.02.00 User Command Set */ +#define LV_LCD_CMD_NOP 0x00 /* No Operation */ +#define LV_LCD_CMD_SOFT_RESET 0x01 /* Software Reset */ +#define LV_LCD_CMD_GET_POWER_MODE 0x0A /* Get the current power mode */ +#define LV_LCD_CMD_GET_ADDRESS_MODE 0x0B /* Get the data order for transfers from the Host to the display module and from the frame memory to the display device */ +#define LV_LCD_CMD_GET_PIXEL_FORMAT 0x0C /* Get the current pixel format */ +#define LV_LCD_CMD_GET_DISPLAY_MODE 0x0D /* Get the current display mode from the peripheral */ +#define LV_LCD_CMD_GET_SIGNAL_MODE 0x0E /* Get display module signaling mode */ +#define LV_LCD_CMD_GET_DIAGNOSTIC_RESULT 0x0F /* Get Peripheral Self-Diagnostic Result */ +#define LV_LCD_CMD_ENTER_SLEEP_MODE 0x10 /* Power for the display panel is off */ +#define LV_LCD_CMD_EXIT_SLEEP_MODE 0x11 /* Power for the display panel is on */ +#define LV_LCD_CMD_ENTER_PARTIAL_MODE 0x12 /* Part of the display area is used for image display */ +#define LV_LCD_CMD_ENTER_NORMAL_MODE 0x13 /* The whole display area is used for image display */ +#define LV_LCD_CMD_EXIT_INVERT_MODE 0x20 /* Displayed image colors are not inverted */ +#define LV_LCD_CMD_ENTER_INVERT_MODE 0x21 /* Displayed image colors are inverted */ +#define LV_LCD_CMD_SET_GAMMA_CURVE 0x26 /* Selects the gamma curve used by the display device */ +#define LV_LCD_CMD_SET_DISPLAY_OFF 0x28 /* Blanks the display device */ +#define LV_LCD_CMD_SET_DISPLAY_ON 0x29 /* Show the image on the display device */ +#define LV_LCD_CMD_SET_COLUMN_ADDRESS 0x2A /* Set the column extent */ +#define LV_LCD_CMD_SET_PAGE_ADDRESS 0x2B /* Set the page extent */ +#define LV_LCD_CMD_WRITE_MEMORY_START 0x2C /* Transfer image data from the Host Processor to the peripheral starting at the location provided by set_column_address and set_page_address */ +#define LV_LCD_CMD_READ_MEMORY_START 0x2E /* Transfer image data from the peripheral to the Host Processor interface starting at the location provided by set_column_address and set_page_address */ +#define LV_LCD_CMD_SET_PARTIAL_ROWS 0x30 /* Defines the number of rows in the partial display area on the display device */ +#define LV_LCD_CMD_SET_PARTIAL_COLUMNS 0x31 /* Defines the number of columns in the partial display area on the display device */ +#define LV_LCD_CMD_SET_SCROLL_AREA 0x33 /* Defines the vertical scrolling and fixed area on display device */ +#define LV_LCD_CMD_SET_TEAR_OFF 0x34 /* Synchronization information is not sent from the display module to the host processor */ +#define LV_LCD_CMD_SET_TEAR_ON 0x35 /* Synchronization information is sent from the display module to the host processor at the start of VFP */ +#define LV_LCD_CMD_SET_ADDRESS_MODE 0x36 /* Set the data order for transfers from the Host to the display module and from the frame memory to the display device */ +#define LV_LCD_CMD_SET_SCROLL_START 0x37 /* Defines the vertical scrolling starting point */ +#define LV_LCD_CMD_EXIT_IDLE_MODE 0x38 /* Full color depth is used on the display panel */ +#define LV_LCD_CMD_ENTER_IDLE_MODE 0x39 /* Reduced color depth is used on the display panel */ +#define LV_LCD_CMD_SET_PIXEL_FORMAT 0x3A /* Defines how many bits per pixel are used in the interface */ +#define LV_LCD_CMD_WRITE_MEMORY_CONTINUE 0x3C /* Transfer image information from the Host Processor interface to the peripheral from the last written location */ +#define LV_LCD_CMD_READ_MEMORY_CONTINUE 0x3E /* Read image data from the peripheral continuing after the last read_memory_continue or read_memory_start */ +#define LV_LCD_CMD_SET_TEAR_SCANLINE 0x44 /* Synchronization information is sent from the display module to the host processor when the display device refresh reaches the provided scanline */ +#define LV_LCD_CMD_GET_SCANLINE 0x45 /* Get the current scanline */ +#define LV_LCD_CMD_READ_DDB_CONTINUE 0xA8 /* Continue reading the DDB from the last read location */ +#define LV_LCD_CMD_READ_DDB_START 0xA1 /* Read the DDB from the provided location */ + +/* address mode flag masks */ +#define LV_LCD_MASK_FLIP_VERTICAL (1 << 0) /* This bit flips the image shown on the display device top to bottom. No change is made to the frame memory */ +#define LV_LCD_MASK_FLIP_HORIZONTAL (1 << 1) /* This bit flips the image shown on the display device left to right. No change is made to the frame memory */ +#define LV_LCD_MASK_DATA_LATCH_DATA_ORDER (1 << 2) /* Display Data Latch Order */ +#define LV_LCD_MASK_RGB_ORDER (1 << 3) /* RGB/BGR Order */ +#define LV_LCD_MASK_LINE_ADDRESS_ORDER (1 << 4) /* Line Address Order */ +#define LV_LCD_MASK_PAGE_COLUMN_ORDER (1 << 5) /* Page/Column Order */ +#define LV_LCD_MASK_COLUMN_ADDRESS_ORDER (1 << 6) /* Column Address Order */ +#define LV_LCD_MASK_PAGE_ADDRESS_ORDER (1 << 7) /* Page Address Order */ + +#define LV_LCD_BIT_FLIP_VERTICAL__NOT_FLIPPED 0 +#define LV_LCD_BIT_FLIP_VERTICAL__FLIPPED LV_LCD_MASK_FLIP_VERTICAL /* This bit flips the image shown on the display device top to bottom. No change is made to the frame memory */ +#define LV_LCD_BIT_FLIP_HORIZONTAL__NOT_FLIPPED 0 +#define LV_LCD_BIT_FLIP_HORIZONTAL__FLIPPED LV_LCD_MASK_FLIP_HORIZONTAL /* This bit flips the image shown on the display device left to right. No change is made to the frame memory */ +#define LV_LCD_BIT_DATA_LATCH_DATA_ORDER__LTOR 0 /* Display Data Latch Order: LCD Refresh Left to Right */ +#define LV_LCD_BIT_DATA_LATCH_DATA_ORDER__RTOL LV_LCD_MASK_DATA_LATCH_DATA_ORDER /* Display Data Latch Order: LCD Refresh Right to Left */ +#define LV_LCD_BIT_RGB_ORDER__RGB 0 /* RGB/BGR Order: RGB */ +#define LV_LCD_BIT_RGB_ORDER__BGR LV_LCD_MASK_RGB_ORDER /* RGB/BGR Order: BGR */ +#define LV_LCD_BIT_LINE_ADDRESS_ORDER__TTOB 0 /* Line Address Order: LCD Refresh Top to Bottom */ +#define LV_LCD_BIT_LINE_ADDRESS_ORDER__BTOT LV_LCD_MASK_LINE_ADDRESS_ORDER /* Line Address Order: LCD Refresh Bottom to Top */ +#define LV_LCD_BIT_PAGE_COLUMN_ORDER__NORMAL 0 /* Page/Column Order: Normal Mode */ +#define LV_LCD_BIT_PAGE_COLUMN_ORDER__REVERSE LV_LCD_MASK_PAGE_COLUMN_ORDER /* Page/Column Order: Reverse Mode */ +#define LV_LCD_BIT_COLUMN_ADDRESS_ORDER__LTOR 0 /* Column Address Order: Left to Right */ +#define LV_LCD_BIT_COLUMN_ADDRESS_ORDER__RTOL LV_LCD_MASK_COLUMN_ADDRESS_ORDER /* Column Address Order: Right to Left */ +#define LV_LCD_BIT_PAGE_ADDRESS_ORDER__TTOB 0 /* Page Address Order: Top to Bottom */ +#define LV_LCD_BIT_PAGE_ADDRESS_ORDER__BTOT LV_LCD_MASK_PAGE_ADDRESS_ORDER /* Page Address Order: Bottom to Top */ + +/* predefined gamma curves */ +#define LV_LCD_GAMMA_2_2 0x01 /* 2.2 */ +#define LV_LCD_GAMMA_1_8 0x02 /* 1.8 */ +#define LV_LCD_GAMMA_2_5 0x04 /* 2.5 */ +#define LV_LCD_GAMMA_1_0 0x08 /* 1.0 */ + +/* common pixel formats */ +#define LV_LCD_PIXEL_FORMAT_RGB565 0x55 /* bus: 16 bits, pixel: 16 bits */ +#define LV_LCD_PIXEL_FORMAT_RGB666 0x66 /* bus: 18 bits, pixel: 18 bits */ + +/* flags for lv_lcd_xxx_create() */ +#define LV_LCD_FLAG_NONE 0x00000000UL +#define LV_LCD_FLAG_MIRROR_X 0x00000001UL +#define LV_LCD_FLAG_MIRROR_Y 0x00000002UL +#define LV_LCD_FLAG_BGR 0x00000008UL +#define LV_LCD_FLAG_RGB666 0x00000010UL + +/* command list */ +#define LV_LCD_CMD_DELAY_MS 0xff +#define LV_LCD_CMD_EOF 0xff + +/********************** + * TYPEDEFS + **********************/ + +/** + * Configuration flags for lv_lcd_xxx_create() + * + */ +typedef uint32_t lv_lcd_flag_t; + +/** + * Prototype of a platform-dependent callback to transfer commands and data to the LCD controller. + * @param disp display object + * @param cmd command buffer (can handle 16 bit commands as well) + * @param cmd_size number of bytes of the command + * @param param parameter buffer + * @param param_size number of bytes of the parameters + */ +typedef void (*lv_lcd_send_cmd_cb_t)(lv_display_t * disp, const uint8_t * cmd, size_t cmd_size, const uint8_t * param, + size_t param_size); + +/** + * Prototype of a platform-dependent callback to transfer pixel data to the LCD controller. + * @param disp display object + * @param cmd command buffer (can handle 16 bit commands as well) + * @param cmd_size number of bytes of the command + * @param param parameter buffer + * @param param_size number of bytes of the parameters + */ +typedef void (*lv_lcd_send_color_cb_t)(lv_display_t * disp, const uint8_t * cmd, size_t cmd_size, uint8_t * param, + size_t param_size); + +/** + * Generic MIPI compatible LCD driver + */ +typedef struct { + lv_display_t * disp; /* the associated LVGL display object */ + lv_lcd_send_cmd_cb_t send_cmd; /* platform-specific implementation to send a command to the LCD controller */ + lv_lcd_send_color_cb_t send_color; /* platform-specific implementation to send pixel data to the LCD controller */ + uint16_t x_gap; /* x offset of the (0,0) pixel in VRAM */ + uint16_t y_gap; /* y offset of the (0,0) pixel in VRAM */ + uint8_t madctl_reg; /* current value of MADCTL register */ + uint8_t colmod_reg; /* current value of COLMOD register */ + bool mirror_x; + bool mirror_y; + bool swap_xy; +} lv_lcd_generic_mipi_driver_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a MIPI DCS compatible LCD display + * @param hor_res horizontal resolution + * @param ver_res vertical resolution + * @param flags default configuration settings (mirror, RGB ordering, etc.) + * @param send_cmd platform-dependent function to send a command to the LCD controller (usually uses polling transfer) + * @param send_color platform-dependent function to send pixel data to the LCD controller (usually uses DMA transfer: must implement a 'ready' callback) + * @return pointer to the created display + */ +lv_display_t * lv_lcd_generic_mipi_create(uint32_t hor_res, uint32_t ver_res, lv_lcd_flag_t flags, + lv_lcd_send_cmd_cb_t send_cmd_cb, lv_lcd_send_color_cb_t send_color_cb); + +/** + * Set gap, i.e., the offset of the (0,0) pixel in the VRAM + * @param disp display object + * @param x x offset + * @param y y offset + */ +void lv_lcd_generic_mipi_set_gap(lv_display_t * disp, uint16_t x, uint16_t y); + +/** + * Set color inversion + * @param disp display object + * @param invert false: normal, true: invert + */ +void lv_lcd_generic_mipi_set_invert(lv_display_t * disp, bool invert); + +/** + * Set address mode + * @param disp display object + * @param mirror_x horizontal mirror (false: normal, true: mirrored) + * @param mirror_y vertical mirror (false: normal, true: mirrored) + * @param swap_xy swap axes (false: normal, true: swap) + * @param bgr RGB/BGR order (false: RGB, true: BGR) + */ +void lv_lcd_generic_mipi_set_address_mode(lv_display_t * disp, bool mirror_x, bool mirror_y, bool swap_xy, bool bgr); + +/** + * Set gamma curve + * @param disp display object + * @param gamma gamma curve + */ +void lv_lcd_generic_mipi_set_gamma_curve(lv_display_t * disp, uint8_t gamma); + +/** + * Send list of commands. + * @param disp display object + * @param cmd_list controller and panel-specific commands + */ +void lv_lcd_generic_mipi_send_cmd_list(lv_display_t * disp, const uint8_t * cmd_list); + +/********************** + * OTHERS + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_USE_GENERIC_MIPI*/ + +#endif /* LV_LCD_GENERIC_MIPI_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/st7735/lv_st7735.c b/lib/libesp32_lvgl/lvgl/src/drivers/display/st7735/lv_st7735.c new file mode 100644 index 000000000..6b5e62dcb --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/st7735/lv_st7735.c @@ -0,0 +1,113 @@ +/** + * @file lv_st7735.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_st7735.h" + +#if LV_USE_ST7735 + +/********************* + * DEFINES + *********************/ + +#define CMD_GAMSET 0x26 + +#define CMD_FRMCTR1 0xB1 +#define CMD_FRMCTR2 0xB2 +#define CMD_FRMCTR3 0xB3 +#define CMD_INVCTR 0xB4 +#define CMD_DISSET5 0xB6 + +#define CMD_PWCTR1 0xC0 +#define CMD_PWCTR2 0xC1 +#define CMD_PWCTR3 0xC2 +#define CMD_PWCTR4 0xC3 +#define CMD_PWCTR5 0xC4 +#define CMD_VMCTR1 0xC5 +#define CMD_VMOFCTR 0xC7 + +#define CMD_NVFCTR1 0xD9 + +#define CMD_GMCTRP1 0xE0 +#define CMD_GMCTRN1 0xE1 + +#define CMD_PWCTR6 0xFC + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC CONSTANTS + **********************/ + +/* init commands for buydisplay.com ER-TFTM018-3 */ +static const uint8_t init_cmd_list[] = { + 0xB1, 3, 0x05, 0x3C, 0x3C, + 0xB2, 3, 0x05, 0x3C, 0x3C, + 0xB3, 6, 0x05, 0x3C, 0x3C, 0x05, 0x3C, 0x3C, + 0xB4, 1, 0x03, + 0xC0, 3, 0x28, 0x08, 0x04, + 0xC1, 1, 0XC0, + 0xC2, 2, 0x0D, 0x00, + 0xC3, 2, 0x8D, 0x2A, + 0xC4, 2, 0x8D, 0xEE, + 0xC5, 1, 0x10, + 0xE0, 16, 0x04, 0x22, 0x07, 0x0A, 0x2E, 0x30, 0x25, 0x2A, 0x28, 0x26, 0x2E, 0x3A, 0x00, 0x01, 0x03, 0x13, + 0xE1, 16, 0x04, 0x16, 0x06, 0x0D, 0x2D, 0x26, 0x23, 0x27, 0x27, 0x25, 0x2D, 0x3B, 0x00, 0x01, 0x04, 0x13, + LV_LCD_CMD_DELAY_MS, LV_LCD_CMD_EOF +}; + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_display_t * lv_st7735_create(uint32_t hor_res, uint32_t ver_res, lv_lcd_flag_t flags, + lv_st7735_send_cmd_cb_t send_cmd_cb, lv_st7735_send_color_cb_t send_color_cb) +{ + lv_display_t * disp = lv_lcd_generic_mipi_create(hor_res, ver_res, flags, send_cmd_cb, send_color_cb); + lv_lcd_generic_mipi_send_cmd_list(disp, init_cmd_list); + return disp; +} + +void lv_st7735_set_gap(lv_display_t * disp, uint16_t x, uint16_t y) +{ + lv_lcd_generic_mipi_set_gap(disp, x, y); +} + +void lv_st7735_set_invert(lv_display_t * disp, bool invert) +{ + lv_lcd_generic_mipi_set_invert(disp, invert); +} + +void lv_st7735_set_gamma_curve(lv_display_t * disp, uint8_t gamma) +{ + lv_lcd_generic_mipi_set_gamma_curve(disp, gamma); +} + +void lv_st7735_send_cmd_list(lv_display_t * disp, const uint8_t * cmd_list) +{ + lv_lcd_generic_mipi_send_cmd_list(disp, cmd_list); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_ST7735*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/st7735/lv_st7735.h b/lib/libesp32_lvgl/lvgl/src/drivers/display/st7735/lv_st7735.h new file mode 100644 index 000000000..062cfe31b --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/st7735/lv_st7735.h @@ -0,0 +1,93 @@ +/* + * lv_st7735.h + * + * This driver is just a wrapper around the generic MIPI compatible LCD controller driver + * + */ + +#ifndef LV_ST7735_H +#define LV_ST7735_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../lcd/lv_lcd_generic_mipi.h" + +#if LV_USE_ST7735 + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef lv_lcd_send_cmd_cb_t lv_st7735_send_cmd_cb_t; +typedef lv_lcd_send_color_cb_t lv_st7735_send_color_cb_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an LCD display with ST7735 driver + * @param hor_res horizontal resolution + * @param ver_res vertical resolution + * @param flags default configuration settings (mirror, RGB ordering, etc.) + * @param send_cmd platform-dependent function to send a command to the LCD controller (usually uses polling transfer) + * @param send_color platform-dependent function to send pixel data to the LCD controller (usually uses DMA transfer: must implement a 'ready' callback) + * @return pointer to the created display + */ +lv_display_t * lv_st7735_create(uint32_t hor_res, uint32_t ver_res, lv_lcd_flag_t flags, + lv_st7735_send_cmd_cb_t send_cmd_cb, lv_st7735_send_color_cb_t send_color_cb); + +/** + * Set gap, i.e., the offset of the (0,0) pixel in the VRAM + * @param disp display object + * @param x x offset + * @param y y offset + */ +void lv_st7735_set_gap(lv_display_t * disp, uint16_t x, uint16_t y); + +/** + * Set color inversion + * @param disp display object + * @param invert false: normal, true: invert + */ +void lv_st7735_set_invert(lv_display_t * disp, bool invert); + +/** + * Set gamma curve + * @param disp display object + * @param gamma gamma curve + */ +void lv_st7735_set_gamma_curve(lv_display_t * disp, uint8_t gamma); + +/** + * Send list of commands. + * @param disp display object + * @param cmd_list controller and panel-specific commands + */ +void lv_st7735_send_cmd_list(lv_display_t * disp, const uint8_t * cmd_list); + +/********************** + * OTHERS + **********************/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_ST7735*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /* LV_ST7735_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/st7789/lv_st7789.c b/lib/libesp32_lvgl/lvgl/src/drivers/display/st7789/lv_st7789.c new file mode 100644 index 000000000..76d08bfb2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/st7789/lv_st7789.c @@ -0,0 +1,116 @@ +/** + * @file lv_st7789.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_st7789.h" + +#if LV_USE_ST7789 + +/********************* + * DEFINES + *********************/ + +#define CMD_FRMCTR1 0xB1 +#define CMD_FRMCTR2 0xB2 +#define CMD_FRMCTR3 0xB3 +#define CMD_INVCTR 0xB4 +#define CMD_DFUNCTR 0xB6 +#define CMD_ETMOD 0xB7 +#define CMD_PWCTR1 0xC0 +#define CMD_PWCTR2 0xC1 +#define CMD_PWCTR3 0xC2 +#define CMD_PWCTR4 0xC3 +#define CMD_PWCTR5 0xC4 +#define CMD_VMCTR 0xC5 +#define CMD_GMCTRP1 0xE0 +#define CMD_GMCTRN1 0xE1 +#define CMD_DOCA 0xE8 +#define CMD_CSCON 0xF0 + +#define CMD_RAMCTRL 0xB0 +#define CMD_PORCTRL 0xB2 /* Porch control */ +#define CMD_GCTRL 0xB7 /* Gate control */ +#define CMD_VCOMS 0xBB /* VCOMS setting */ +#define CMD_LCMCTRL 0xC0 /* LCM control */ +#define CMD_VDVVRHEN 0xC2 /* VDV and VRH command enable */ +#define CMD_VRHS 0xC3 /* VRH set */ +#define CMD_VDVSET 0xC4 /* VDV setting */ +#define CMD_FRCTR2 0xC6 /* FR Control 2 */ +#define CMD_PWCTRL1 0xD0 /* Power control 1 */ +#define CMD_PVGAMCTRL 0xE0 /* Positive Gamma Correction */ +#define CMD_NVGAMCTRL 0xE1 /* Negative Gamma Correction */ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC CONSTANTS + **********************/ + +/* init commands based on LovyanGFX ST7789 driver */ +static const uint8_t init_cmd_list[] = { + CMD_GCTRL, 1, 0x44, /* GCTRL -- panel dependent */ + CMD_VCOMS, 1, 0x24, /* VCOMS -- panel dependent */ + CMD_VRHS, 1, 0x13, /* VRHS - panel dependent */ + CMD_PWCTRL1, 2, 0xa4, 0xa1, + CMD_RAMCTRL, 2, 0x00, 0xC0, /* controls mapping of RGB565 to RGB666 */ + CMD_PVGAMCTRL, 14, 0xd0, 0x00, 0x02, 0x07, 0x0a, 0x28, 0x32, 0x44, 0x42, 0x06, 0x0e, 0x12, 0x14, 0x17, + CMD_NVGAMCTRL, 14, 0xd0, 0x00, 0x02, 0x07, 0x0a, 0x28, 0x31, 0x54, 0x47, 0x0e, 0x1c, 0x17, 0x1b, 0x1e, + LV_LCD_CMD_SET_GAMMA_CURVE, 1, 0x01, + LV_LCD_CMD_DELAY_MS, LV_LCD_CMD_EOF +}; + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_display_t * lv_st7789_create(uint32_t hor_res, uint32_t ver_res, lv_lcd_flag_t flags, + lv_st7789_send_cmd_cb_t send_cmd_cb, lv_st7789_send_color_cb_t send_color_cb) +{ + lv_display_t * disp = lv_lcd_generic_mipi_create(hor_res, ver_res, flags, send_cmd_cb, send_color_cb); + lv_lcd_generic_mipi_send_cmd_list(disp, init_cmd_list); + return disp; +} + +void lv_st7789_set_gap(lv_display_t * disp, uint16_t x, uint16_t y) +{ + lv_lcd_generic_mipi_set_gap(disp, x, y); +} + +void lv_st7789_set_invert(lv_display_t * disp, bool invert) +{ + lv_lcd_generic_mipi_set_invert(disp, invert); +} + +void lv_st7789_set_gamma_curve(lv_display_t * disp, uint8_t gamma) +{ + lv_lcd_generic_mipi_set_gamma_curve(disp, gamma); +} + +void lv_st7789_send_cmd_list(lv_display_t * disp, const uint8_t * cmd_list) +{ + lv_lcd_generic_mipi_send_cmd_list(disp, cmd_list); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_ST7789*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/st7789/lv_st7789.h b/lib/libesp32_lvgl/lvgl/src/drivers/display/st7789/lv_st7789.h new file mode 100644 index 000000000..5cd301948 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/st7789/lv_st7789.h @@ -0,0 +1,93 @@ +/* + * lv_st7789.h + * + * This driver is just a wrapper around the generic MIPI compatible LCD controller driver + * + */ + +#ifndef LV_ST7789_H +#define LV_ST7789_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../lcd/lv_lcd_generic_mipi.h" + +#if LV_USE_ST7789 + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef lv_lcd_send_cmd_cb_t lv_st7789_send_cmd_cb_t; +typedef lv_lcd_send_color_cb_t lv_st7789_send_color_cb_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an LCD display with ST7789 driver + * @param hor_res horizontal resolution + * @param ver_res vertical resolution + * @param flags default configuration settings (mirror, RGB ordering, etc.) + * @param send_cmd platform-dependent function to send a command to the LCD controller (usually uses polling transfer) + * @param send_color platform-dependent function to send pixel data to the LCD controller (usually uses DMA transfer: must implement a 'ready' callback) + * @return pointer to the created display + */ +lv_display_t * lv_st7789_create(uint32_t hor_res, uint32_t ver_res, lv_lcd_flag_t flags, + lv_st7789_send_cmd_cb_t send_cmd_cb, lv_st7789_send_color_cb_t send_color_cb); + +/** + * Set gap, i.e., the offset of the (0,0) pixel in the VRAM + * @param disp display object + * @param x x offset + * @param y y offset + */ +void lv_st7789_set_gap(lv_display_t * disp, uint16_t x, uint16_t y); + +/** + * Set color inversion + * @param disp display object + * @param invert false: normal, true: invert + */ +void lv_st7789_set_invert(lv_display_t * disp, bool invert); + +/** + * Set gamma curve + * @param disp display object + * @param gamma gamma curve + */ +void lv_st7789_set_gamma_curve(lv_display_t * disp, uint8_t gamma); + +/** + * Send list of commands. + * @param disp display object + * @param cmd_list controller and panel-specific commands + */ +void lv_st7789_send_cmd_list(lv_display_t * disp, const uint8_t * cmd_list); + +/********************** + * OTHERS + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_USE_ST7789*/ + +#endif //LV_ST7789_H diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/st7796/lv_st7796.c b/lib/libesp32_lvgl/lvgl/src/drivers/display/st7796/lv_st7796.c new file mode 100644 index 000000000..985b39f01 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/st7796/lv_st7796.c @@ -0,0 +1,121 @@ +/** + * @file lv_st7796.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_st7796.h" + +#if LV_USE_ST7796 + +/********************* + * DEFINES + *********************/ + +#define CMD_FRMCTR1 0xB1 +#define CMD_FRMCTR2 0xB2 +#define CMD_FRMCTR3 0xB3 +#define CMD_INVCTR 0xB4 +#define CMD_DFUNCTR 0xB6 +#define CMD_ETMOD 0xB7 +#define CMD_PWCTR1 0xC0 +#define CMD_PWCTR2 0xC1 +#define CMD_PWCTR3 0xC2 +#define CMD_PWCTR4 0xC3 +#define CMD_PWCTR5 0xC4 +#define CMD_VMCTR 0xC5 +#define CMD_GMCTRP1 0xE0 +#define CMD_GMCTRN1 0xE1 +#define CMD_DOCA 0xE8 +#define CMD_CSCON 0xF0 + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC CONSTANTS + **********************/ + +/* init commands based on LovyanGFX */ +static const uint8_t init_cmd_list[] = { + CMD_CSCON, 1, 0xC3, /* Enable extension command 2 partI */ + CMD_CSCON, 1, 0x96, /* Enable extension command 2 partII */ + CMD_INVCTR, 1, 0x01, /* 1-dot inversion */ + CMD_DFUNCTR, 3, 0x80, /* Display Function Control: Bypass */ + 0x22, /* Source Output Scan from S1 to S960, Gate Output scan from G1 to G480, scan cycle = 2 */ + 0x3B, /* LCD Drive Line = 8 * (59 + 1) */ + CMD_DOCA, 8, 0x40, 0x8A, 0x00, 0x00, + 0x29, /* Source equalizing period time = 22.5 us */ + 0x19, /* Timing for "Gate start" = 25 (Tclk) */ + 0xA5, /* Timing for "Gate End" = 37 (Tclk), Gate driver EQ function ON */ + 0x33, + CMD_PWCTR2, 1, 0x06, /* Power control2: VAP(GVDD) = 3.85 + (vcom + vcom offset), VAN(GVCL) = -3.85 + (vcom + vcom offset) */ + CMD_PWCTR3, 1, 0xA7, /* Power control 3: Source driving current level = low, Gamma driving current level = High */ + CMD_VMCTR, 1, 0x18, /* VCOM Control: VCOM = 0.9 */ + LV_LCD_CMD_DELAY_MS, 12, /* delay 120 ms */ + CMD_GMCTRP1, 14, /* Gamma */ + 0xF0, 0x09, 0x0B, 0x06, 0x04, 0x15, 0x2F, + 0x54, 0x42, 0x3C, 0x17, 0x14, 0x18, 0x1B, + CMD_GMCTRN1, 14, + 0xE0, 0x09, 0x0B, 0x06, 0x04, 0x03, 0x2B, + 0x43, 0x42, 0x3B, 0x16, 0x14, 0x17, 0x1B, + LV_LCD_CMD_DELAY_MS, 12, /* delay 120 ms */ + CMD_CSCON, 1, 0x3C, /* Disable extension command 2 partI */ + CMD_CSCON, 1, 0x69, /* Disable extension command 2 partII */ + LV_LCD_CMD_DELAY_MS, LV_LCD_CMD_EOF +}; + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_display_t * lv_st7796_create(uint32_t hor_res, uint32_t ver_res, lv_lcd_flag_t flags, + lv_st7796_send_cmd_cb_t send_cmd_cb, lv_st7796_send_color_cb_t send_color_cb) +{ + lv_display_t * disp = lv_lcd_generic_mipi_create(hor_res, ver_res, flags, send_cmd_cb, send_color_cb); + lv_lcd_generic_mipi_send_cmd_list(disp, init_cmd_list); + return disp; +} + +void lv_st7796_set_gap(lv_display_t * disp, uint16_t x, uint16_t y) +{ + lv_lcd_generic_mipi_set_gap(disp, x, y); +} + +void lv_st7796_set_invert(lv_display_t * disp, bool invert) +{ + lv_lcd_generic_mipi_set_invert(disp, invert); +} + +void lv_st7796_set_gamma_curve(lv_display_t * disp, uint8_t gamma) +{ + /* NOTE: the generic method is not supported on ST7796, TODO: implement gamma tables */ + LV_UNUSED(disp); + LV_UNUSED(gamma); +} + +void lv_st7796_send_cmd_list(lv_display_t * disp, const uint8_t * cmd_list) +{ + lv_lcd_generic_mipi_send_cmd_list(disp, cmd_list); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_ST7796*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/st7796/lv_st7796.h b/lib/libesp32_lvgl/lvgl/src/drivers/display/st7796/lv_st7796.h new file mode 100644 index 000000000..c34dfe681 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/st7796/lv_st7796.h @@ -0,0 +1,93 @@ +/* + * lv_st7796.h + * + * This driver is just a wrapper around the generic MIPI compatible LCD controller driver + * + */ + +#ifndef LV_ST7796_H +#define LV_ST7796_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../lcd/lv_lcd_generic_mipi.h" + +#if LV_USE_ST7796 + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef lv_lcd_send_cmd_cb_t lv_st7796_send_cmd_cb_t; +typedef lv_lcd_send_color_cb_t lv_st7796_send_color_cb_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an LCD display with ST7796 driver + * @param hor_res horizontal resolution + * @param ver_res vertical resolution + * @param flags default configuration settings (mirror, RGB ordering, etc.) + * @param send_cmd platform-dependent function to send a command to the LCD controller (usually uses polling transfer) + * @param send_color platform-dependent function to send pixel data to the LCD controller (usually uses DMA transfer: must implement a 'ready' callback) + * @return pointer to the created display + */ +lv_display_t * lv_st7796_create(uint32_t hor_res, uint32_t ver_res, lv_lcd_flag_t flags, + lv_st7796_send_cmd_cb_t send_cmd_cb, lv_st7796_send_color_cb_t send_color_cb); + +/** + * Set gap, i.e., the offset of the (0,0) pixel in the VRAM + * @param disp display object + * @param x x offset + * @param y y offset + */ +void lv_st7796_set_gap(lv_display_t * disp, uint16_t x, uint16_t y); + +/** + * Set color inversion + * @param disp display object + * @param invert false: normal, true: invert + */ +void lv_st7796_set_invert(lv_display_t * disp, bool invert); + +/** + * Set gamma curve + * @param disp display object + * @param gamma gamma curve + */ +void lv_st7796_set_gamma_curve(lv_display_t * disp, uint8_t gamma); + +/** + * Send list of commands. + * @param disp display object + * @param cmd_list controller and panel-specific commands + */ +void lv_st7796_send_cmd_list(lv_display_t * disp, const uint8_t * cmd_list); + +/********************** + * OTHERS + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_USE_ST7796*/ + +#endif /* LV_ST7796_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/tft_espi/lv_tft_espi.cpp b/lib/libesp32_lvgl/lvgl/src/drivers/display/tft_espi/lv_tft_espi.cpp new file mode 100644 index 000000000..64e3ee6ab --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/tft_espi/lv_tft_espi.cpp @@ -0,0 +1,83 @@ +/** + * @file lv_tft_espi.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_tft_espi.h" +#if LV_USE_TFT_ESPI + +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + TFT_eSPI * tft; +} lv_tft_espi_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_display_t * lv_tft_espi_create(uint32_t hor_res, uint32_t ver_res, void * buf, uint32_t buf_size_bytes) +{ + lv_tft_espi_t * dsc = (lv_tft_espi_t *)lv_malloc_zeroed(sizeof(lv_tft_espi_t)); + LV_ASSERT_MALLOC(dsc); + if(dsc == NULL) return NULL; + + lv_display_t * disp = lv_display_create(hor_res, ver_res); + if(disp == NULL) { + lv_free(dsc); + return NULL; + } + + dsc->tft = new TFT_eSPI(hor_res, ver_res); + dsc->tft->begin(); /* TFT init */ + dsc->tft->setRotation(3); /* Landscape orientation, flipped */ + lv_display_set_driver_data(disp, (void *)dsc); + lv_display_set_flush_cb(disp, flush_cb); + lv_display_set_buffers(disp, (void *)buf, NULL, buf_size_bytes, LV_DISPLAY_RENDER_MODE_PARTIAL); + return disp; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map) +{ + lv_tft_espi_t * dsc = (lv_tft_espi_t *)lv_display_get_driver_data(disp); + + uint32_t w = (area->x2 - area->x1 + 1); + uint32_t h = (area->y2 - area->y1 + 1); + + dsc->tft->startWrite(); + dsc->tft->setAddrWindow(area->x1, area->y1, w, h); + dsc->tft->pushColors((uint16_t *)px_map, w * h, true); + dsc->tft->endWrite(); + + lv_display_flush_ready(disp); + +} + +#endif /*LV_USE_TFT_ESPI*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/display/tft_espi/lv_tft_espi.h b/lib/libesp32_lvgl/lvgl/src/drivers/display/tft_espi/lv_tft_espi.h new file mode 100644 index 000000000..101057565 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/display/tft_espi/lv_tft_espi.h @@ -0,0 +1,43 @@ +/** + * @file lv_linux_fb_dev_h + * + */ + +#ifndef LV_TFT_ESPI_H +#define LV_TFT_ESPI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../display/lv_display.h" + +#if LV_USE_TFT_ESPI + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +lv_display_t * lv_tft_espi_create(uint32_t hor_res, uint32_t ver_res, void * buf, uint32_t buf_size_bytes); + +/********************** + * MACROS + **********************/ + +#endif /* LV_USE_TFT_ESPI */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV_TFT_ESPI_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/evdev/lv_evdev.c b/lib/libesp32_lvgl/lvgl/src/drivers/evdev/lv_evdev.c new file mode 100644 index 000000000..010ad4274 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/evdev/lv_evdev.c @@ -0,0 +1,223 @@ +/** + * @file lv_evdev.c + * + */ + +/********************** + * INCLUDES + **********************/ +#include "lv_evdev.h" +#if LV_USE_EVDEV + +#include +#include +#include +#include /*To detect BSD*/ +#ifdef BSD + #include +#else + #include +#endif /*BSD*/ +#include "../../misc/lv_assert.h" +#include "../../misc/lv_math.h" +#include "../../stdlib/lv_mem.h" +#include "../../stdlib/lv_string.h" +#include "../../display/lv_display.h" + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + /*Device*/ + int fd; + /*Config*/ + bool swap_axes; + int min_x; + int min_y; + int max_x; + int max_y; + /*State*/ + int root_x; + int root_y; + int key; + lv_indev_state_t state; +} lv_evdev_t; + +/********************** + * STATIC FUNCTIONS + **********************/ + +static int _evdev_process_key(uint16_t code) +{ + switch(code) { + case KEY_UP: + return LV_KEY_UP; + case KEY_DOWN: + return LV_KEY_DOWN; + case KEY_RIGHT: + return LV_KEY_RIGHT; + case KEY_LEFT: + return LV_KEY_LEFT; + case KEY_ESC: + return LV_KEY_ESC; + case KEY_DELETE: + return LV_KEY_DEL; + case KEY_BACKSPACE: + return LV_KEY_BACKSPACE; + case KEY_ENTER: + return LV_KEY_ENTER; + case KEY_NEXT: + case KEY_TAB: + return LV_KEY_NEXT; + case KEY_PREVIOUS: + return LV_KEY_PREV; + case KEY_HOME: + return LV_KEY_HOME; + case KEY_END: + return LV_KEY_END; + default: + return 0; + } +} + +static int _evdev_calibrate(int v, int in_min, int in_max, int out_min, int out_max) +{ + if(in_min != in_max) v = (v - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; + return LV_CLAMP(out_min, v, out_max); +} + +static lv_point_t _evdev_process_pointer(lv_indev_t * indev, int x, int y) +{ + lv_display_t * disp = lv_indev_get_display(indev); + lv_evdev_t * dsc = lv_indev_get_driver_data(indev); + LV_ASSERT_NULL(dsc); + + int swapped_x = dsc->swap_axes ? y : x; + int swapped_y = dsc->swap_axes ? x : y; + + int offset_x = lv_display_get_offset_x(disp); + int offset_y = lv_display_get_offset_y(disp); + int width = lv_display_get_horizontal_resolution(disp); + int height = lv_display_get_vertical_resolution(disp); + + lv_point_t p; + p.x = _evdev_calibrate(swapped_x, dsc->min_x, dsc->max_x, offset_x, offset_x + width - 1); + p.y = _evdev_calibrate(swapped_y, dsc->min_y, dsc->max_y, offset_y, offset_y + height - 1); + return p; +} + +static void _evdev_read(lv_indev_t * indev, lv_indev_data_t * data) +{ + lv_evdev_t * dsc = lv_indev_get_driver_data(indev); + LV_ASSERT_NULL(dsc); + + /*Update dsc with buffered events*/ + struct input_event in = { 0 }; + while(read(dsc->fd, &in, sizeof(in)) > 0) { + if(in.type == EV_REL) { + if(in.code == REL_X) dsc->root_x += in.value; + else if(in.code == REL_Y) dsc->root_y += in.value; + } + else if(in.type == EV_ABS) { + if(in.code == ABS_X || in.code == ABS_MT_POSITION_X) dsc->root_x = in.value; + else if(in.code == ABS_Y || in.code == ABS_MT_POSITION_Y) dsc->root_y = in.value; + else if(in.code == ABS_MT_TRACKING_ID) { + if(in.value == -1) dsc->state = LV_INDEV_STATE_RELEASED; + else if(in.value == 0) dsc->state = LV_INDEV_STATE_PRESSED; + } + } + else if(in.type == EV_KEY) { + if(in.code == BTN_MOUSE || in.code == BTN_TOUCH) { + if(in.value == 0) dsc->state = LV_INDEV_STATE_RELEASED; + else if(in.value == 1) dsc->state = LV_INDEV_STATE_PRESSED; + } + else { + dsc->key = _evdev_process_key(in.code); + if(dsc->key) { + dsc->state = in.value ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; + data->continue_reading = true; /*Keep following events in buffer for now*/ + break; + } + } + } + } + + /*Process and store in data*/ + switch(lv_indev_get_type(indev)) { + case LV_INDEV_TYPE_KEYPAD: + data->state = dsc->state; + data->key = dsc->key; + break; + case LV_INDEV_TYPE_POINTER: + data->state = dsc->state; + data->point = _evdev_process_pointer(indev, dsc->root_x, dsc->root_y); + break; + default: + break; + } +} + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_indev_t * lv_evdev_create(lv_indev_type_t indev_type, const char * dev_path) +{ + lv_evdev_t * dsc = lv_malloc_zeroed(sizeof(lv_evdev_t)); + LV_ASSERT_MALLOC(dsc); + if(dsc == NULL) return NULL; + + dsc->fd = open(dev_path, O_RDONLY | O_NOCTTY | O_CLOEXEC); + if(dsc->fd < 0) { + LV_LOG_ERROR("open failed: %s", strerror(errno)); + goto err_after_malloc; + } + + if(fcntl(dsc->fd, F_SETFL, O_NONBLOCK) < 0) { + LV_LOG_ERROR("fcntl failed: %s", strerror(errno)); + goto err_after_open; + } + + lv_indev_t * indev = lv_indev_create(); + if(indev == NULL) goto err_after_open; + lv_indev_set_type(indev, indev_type); + lv_indev_set_read_cb(indev, _evdev_read); + lv_indev_set_driver_data(indev, dsc); + return indev; + +err_after_open: + close(dsc->fd); +err_after_malloc: + lv_free(dsc); + return NULL; +} + +void lv_evdev_set_swap_axes(lv_indev_t * indev, bool swap_axes) +{ + lv_evdev_t * dsc = lv_indev_get_driver_data(indev); + LV_ASSERT_NULL(dsc); + dsc->swap_axes = swap_axes; +} + +void lv_evdev_set_calibration(lv_indev_t * indev, int min_x, int min_y, int max_x, int max_y) +{ + lv_evdev_t * dsc = lv_indev_get_driver_data(indev); + LV_ASSERT_NULL(dsc); + dsc->min_x = min_x; + dsc->min_y = min_y; + dsc->max_x = max_x; + dsc->max_y = max_y; +} + +void lv_evdev_delete(lv_indev_t * indev) +{ + lv_evdev_t * dsc = lv_indev_get_driver_data(indev); + LV_ASSERT_NULL(dsc); + close(dsc->fd); + lv_free(dsc); + + lv_indev_delete(indev); +} + +#endif /*LV_USE_EVDEV*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/evdev/lv_evdev.h b/lib/libesp32_lvgl/lvgl/src/drivers/evdev/lv_evdev.h new file mode 100644 index 000000000..95ab1544c --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/evdev/lv_evdev.h @@ -0,0 +1,64 @@ +/** + * @file lv_evdev.h + * + */ + +#ifndef LV_EVDEV_H +#define LV_EVDEV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../indev/lv_indev.h" + +#if LV_USE_EVDEV + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create evdev input device. + * @param type LV_INDEV_TYPE_POINTER or LV_INDEV_TYPE_KEYPAD + * @param dev_path device path, e.g., /dev/input/event0 + * @return pointer to input device or NULL if opening failed + */ +lv_indev_t * lv_evdev_create(lv_indev_type_t indev_type, const char * dev_path); + +/** + * Set whether coordinates of pointer device should be swapped. Defaults to + * false. + * @param indev evdev input device + * @param swap_axes whether to swap x and y axes + */ +void lv_evdev_set_swap_axes(lv_indev_t * indev, bool swap_axes); + +/** + * Configure a coordinate transformation for pointer devices. Applied after + * axis swap, if any. Defaults to apply no transformation. + * @param indev evdev input device + * @param min_x pointer coordinate mapped to min x of display + * @param min_y pointer coordinate mapped to min y of display + * @param max_x pointer coordinate mapped to max x of display + * @param max_y pointer coordinate mapped to max y of display + */ +void lv_evdev_set_calibration(lv_indev_t * indev, int min_x, int min_y, int max_x, int max_y); + +/** + * Remove evdev input device. + * @param indev evdev input device to close and free + */ +void lv_evdev_delete(lv_indev_t * indev); + +#endif /*LV_USE_EVDEV*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_EVDEV_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/lv_drivers.h b/lib/libesp32_lvgl/lvgl/src/drivers/lv_drivers.h new file mode 100644 index 000000000..ec126d352 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/lv_drivers.h @@ -0,0 +1,59 @@ +/** + * @file lv_drivers.h + * + */ + +#ifndef LV_DRIVERS_H +#define LV_DRIVERS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "sdl/lv_sdl_window.h" +#include "sdl/lv_sdl_mouse.h" +#include "sdl/lv_sdl_mousewheel.h" +#include "sdl/lv_sdl_keyboard.h" + +#include "x11/lv_x11.h" + +#include "display/drm/lv_linux_drm.h" +#include "display/fb/lv_linux_fbdev.h" + +#include "display/tft_espi/lv_tft_espi.h" + +#include "nuttx/lv_nuttx_entry.h" +#include "nuttx/lv_nuttx_fbdev.h" +#include "nuttx/lv_nuttx_touchscreen.h" +#include "nuttx/lv_nuttx_lcd.h" +#include "nuttx/lv_nuttx_libuv.h" + +#include "evdev/lv_evdev.h" + +#include "windows/lv_windows_input.h" +#include "windows/lv_windows_display.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRIVERS_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_cache.c b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_cache.c new file mode 100644 index 000000000..173ad5428 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_cache.c @@ -0,0 +1,77 @@ +/** + * @file lv_nuttx_cache.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_nuttx_cache.h" +#include "../../../lvgl.h" + +#if LV_USE_NUTTX + +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void invalidate_cache(void * buf, uint32_t stride, lv_color_format_t color_format, const lv_area_t * area); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_nuttx_cache_init(void) +{ + lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers(); + handlers->invalidate_cache_cb = invalidate_cache; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void invalidate_cache(void * buf, uint32_t stride, lv_color_format_t color_format, const lv_area_t * area) +{ + LV_UNUSED(color_format); + LV_ASSERT_NULL(buf); + + lv_uintptr_t start; + lv_uintptr_t end; + + if(area) { + int32_t h = lv_area_get_height(area); + start = (lv_uintptr_t)buf + area->y1 * stride; + end = start + h * stride; + } + else { + /* If area is empty, use stride as length */ + start = (lv_uintptr_t)buf; + end = start + stride; + } + + LV_UNUSED(start); + LV_UNUSED(end); + up_invalidate_dcache(start, end); +} + +#endif /* LV_USE_NUTTX */ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/lv_sjpg.h b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_cache.h similarity index 72% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/lv_sjpg.h rename to lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_cache.h index d06e80de5..693744ea4 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/lv_sjpg.h +++ b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_cache.h @@ -1,10 +1,10 @@ /** - * @file lv_sjpg.h + * @file lv_nuttx_cache.h * */ -#ifndef LV_SJPEG_H -#define LV_SJPEG_H +#ifndef LV_NUTTX_CACHE_H +#define LV_NUTTX_CACHE_H #ifdef __cplusplus extern "C" { @@ -14,8 +14,6 @@ extern "C" { * INCLUDES *********************/ -#if LV_USE_SJPG - /********************* * DEFINES *********************/ @@ -28,16 +26,14 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ -void lv_split_jpeg_init(void); +void lv_nuttx_cache_init(void); /********************** * MACROS **********************/ -#endif /*LV_USE_SJPG*/ - #ifdef __cplusplus -} +} /*extern "C"*/ #endif -#endif /* LV_SJPEG_H */ +#endif /*LV_NUTTX_CACHE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_entry.c b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_entry.c new file mode 100644 index 000000000..e484a137d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_entry.c @@ -0,0 +1,178 @@ +/** + * @file lv_nuttx_entry.h + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_nuttx_entry.h" + +#if LV_USE_NUTTX + +#include +#include +#include +#include "lv_nuttx_cache.h" +#include "lv_nuttx_profiler.h" + +#include "../../../lvgl.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static uint32_t millis(void); +#if LV_USE_LOG + static void syslog_print(lv_log_level_t level, const char * buf); +#endif + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +#if LV_ENABLE_GLOBAL_CUSTOM + +static void lv_global_free(void * data) +{ + if(data) { + free(data); + } +} + +lv_global_t * lv_global_default(void) +{ + static int index = -1; + lv_global_t * data = NULL; + + if(index < 0) { + index = task_tls_alloc(lv_global_free); + } + + if(index >= 0) { + data = (lv_global_t *)task_tls_get_value(index); + if(data == NULL) { + data = (lv_global_t *)calloc(1, sizeof(lv_global_t)); + task_tls_set_value(index, (uintptr_t)data); + } + } + return data; +} +#endif + +void lv_nuttx_dsc_init(lv_nuttx_dsc_t * dsc) +{ + if(dsc == NULL) + return; + + lv_memzero(dsc, sizeof(lv_nuttx_dsc_t)); + dsc->fb_path = "/dev/fb0"; + dsc->input_path = "/dev/input0"; + +#ifdef CONFIG_UINPUT_TOUCH + dsc->utouch_path = "/dev/utouch"; +#endif +} + +void lv_nuttx_init(const lv_nuttx_dsc_t * dsc, lv_nuttx_result_t * result) +{ +#if LV_USE_LOG + lv_log_register_print_cb(syslog_print); +#endif + lv_tick_set_cb(millis); + + lv_nuttx_cache_init(); + +#if LV_USE_PROFILER && LV_USE_PROFILER_BUILTIN + lv_nuttx_profiler_init(); +#endif + + if(result) { + lv_memzero(result, sizeof(lv_nuttx_result_t)); + } + +#if !LV_USE_NUTTX_CUSTOM_INIT + + if(dsc && dsc->fb_path) { + lv_display_t * disp = NULL; + +#if LV_USE_NUTTX_LCD + disp = lv_nuttx_lcd_create(dsc->fb_path); +#else + disp = lv_nuttx_fbdev_create(); + if(lv_nuttx_fbdev_set_file(disp, dsc->fb_path) != 0) { + lv_display_delete(disp); + disp = NULL; + } +#endif + if(result) { + result->disp = disp; + } + } + + if(dsc) { +#if LV_USE_NUTTX_TOUCHSCREEN + if(dsc->input_path) { + lv_indev_t * indev = lv_nuttx_touchscreen_create(dsc->input_path); + if(result) { + result->indev = indev; + } + } + + if(dsc->utouch_path) { + lv_indev_t * indev = lv_nuttx_touchscreen_create(dsc->utouch_path); + if(result) { + result->utouch_indev = indev; + } + } +#endif + } + +#else + + lv_nuttx_init_custom(dsc, result); +#endif +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static uint32_t millis(void) +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + uint32_t tick = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; + + return tick; +} + +#if LV_USE_LOG +static void syslog_print(lv_log_level_t level, const char * buf) +{ + static const int priority[_LV_LOG_LEVEL_NUM] = { + LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR, LOG_CRIT + }; + + syslog(priority[level], "[LVGL] %s", buf); +} +#endif + +#endif /*LV_USE_NUTTX*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_entry.h b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_entry.h new file mode 100644 index 000000000..16c92dbca --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_entry.h @@ -0,0 +1,81 @@ +/** + * @file lv_nuttx_entry.h + * + */ + +/********************* + * INCLUDES + *********************/ + +#ifndef LV_NUTTX_ENTRY_H +#define LV_NUTTX_ENTRY_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../display/lv_display.h" +#include "../../indev/lv_indev.h" + +#if LV_USE_NUTTX + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + const char * fb_path; + const char * input_path; + const char * utouch_path; +} lv_nuttx_dsc_t; + +typedef struct { + lv_display_t * disp; + lv_indev_t * indev; + lv_indev_t * utouch_indev; +} lv_nuttx_result_t; +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the lv_nuttx_dsc_t structure with default values for the NuttX port of LVGL. + * @param dsc Pointer to the lv_nuttx_dsc_t structure to be initialized. + */ +void lv_nuttx_dsc_init(lv_nuttx_dsc_t * dsc); + +/** + * Initialize the LVGL display driver for NuttX using the provided configuration information. + * @param dsc Pointer to the lv_nuttx_dsc_t structure containing the configuration information for the display driver. + * @param result Pointer to the lv_nuttx_result_t structure containing display and input device handler. + */ +void lv_nuttx_init(const lv_nuttx_dsc_t * dsc, lv_nuttx_result_t * result); + +#if LV_USE_NUTTX_CUSTOM_INIT +/** + * Initialize the LVGL display driver for NuttX using the provided custom configuration information. + * @param dsc Pointer to the lv_nuttx_dsc_t structure containing the custom configuration for the display driver. + * @param result Pointer to the lv_nuttx_result_t structure containing display and input device handler. + */ +void lv_nuttx_init_custom(const lv_nuttx_dsc_t * dsc, lv_nuttx_result_t * result); + +#endif /* LV_USE_NUTTX_CUSTOM_INIT */ + +/********************** + * MACROS + **********************/ + +#endif /* LV_USE_NUTTX*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV_NUTTX_ENTRY_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_fbdev.c b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_fbdev.c new file mode 100644 index 000000000..2cf83b027 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_fbdev.c @@ -0,0 +1,320 @@ +/** + * @file lv_nuttx_fbdev.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_nuttx_fbdev.h" +#if LV_USE_NUTTX + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../../lvgl.h" +#include "../../lvgl_private.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + /* fd should be defined at the beginning */ + int fd; + struct fb_videoinfo_s vinfo; + struct fb_planeinfo_s pinfo; + + void * mem; + void * mem2; + uint32_t mem2_yoffset; +} lv_nuttx_fb_t; + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p); +static int fbdev_get_pinfo(int fd, struct fb_planeinfo_s * pinfo); +static int fbdev_init_mem2(lv_nuttx_fb_t * dsc); +static void display_refr_timer_cb(lv_timer_t * tmr); +static void display_release_cb(lv_event_t * e); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_display_t * lv_nuttx_fbdev_create(void) +{ + lv_nuttx_fb_t * dsc = lv_malloc_zeroed(sizeof(lv_nuttx_fb_t)); + LV_ASSERT_MALLOC(dsc); + if(dsc == NULL) return NULL; + + lv_display_t * disp = lv_display_create(800, 480); + if(disp == NULL) { + lv_free(dsc); + return NULL; + } + dsc->fd = -1; + lv_display_set_driver_data(disp, dsc); + lv_display_add_event_cb(disp, display_release_cb, LV_EVENT_DELETE, disp); + lv_display_set_flush_cb(disp, flush_cb); + return disp; +} + +int lv_nuttx_fbdev_set_file(lv_display_t * disp, const char * file) +{ + int ret; + LV_ASSERT(disp && file); + lv_nuttx_fb_t * dsc = lv_display_get_driver_data(disp); + + if(dsc->fd >= 0) close(dsc->fd); + + /* Open the file for reading and writing*/ + + dsc->fd = open(file, O_RDWR); + if(dsc->fd < 0) { + LV_LOG_ERROR("Error: cannot open framebuffer device"); + return -errno; + } + LV_LOG_USER("The framebuffer device was opened successfully"); + + if(ioctl(dsc->fd, FBIOGET_VIDEOINFO, (unsigned long)((uintptr_t)&dsc->vinfo)) < 0) { + LV_LOG_ERROR("ioctl(FBIOGET_VIDEOINFO) failed: %d", errno); + ret = -errno; + goto errout; + } + + LV_LOG_USER("VideoInfo:"); + LV_LOG_USER(" fmt: %u", dsc->vinfo.fmt); + LV_LOG_USER(" xres: %u", dsc->vinfo.xres); + LV_LOG_USER(" yres: %u", dsc->vinfo.yres); + LV_LOG_USER(" nplanes: %u", dsc->vinfo.nplanes); + + if((ret = fbdev_get_pinfo(dsc->fd, &dsc->pinfo)) < 0) { + goto errout; + } + + dsc->mem = mmap(NULL, dsc->pinfo.fblen, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_FILE, dsc->fd, 0); + if(dsc->mem == MAP_FAILED) { + LV_LOG_ERROR("ioctl(FBIOGET_PLANEINFO) failed: %d", errno); + ret = -errno; + goto errout; + } + + /* double buffer mode */ + + if(dsc->pinfo.yres_virtual == (dsc->vinfo.yres * 2)) { + if((ret = fbdev_init_mem2(dsc)) < 0) { + goto errout; + } + } + + lv_display_set_buffers(disp, dsc->mem, dsc->mem2, + (dsc->pinfo.stride * dsc->vinfo.yres), LV_DISP_RENDER_MODE_DIRECT); + lv_display_set_resolution(disp, dsc->vinfo.xres, dsc->vinfo.yres); + lv_timer_set_cb(disp->refr_timer, display_refr_timer_cb); + + LV_LOG_USER("Resolution is set to %dx%d at %" LV_PRId32 "dpi", + dsc->vinfo.xres, dsc->vinfo.yres, lv_display_get_dpi(disp)); + return 0; + +errout: + close(dsc->fd); + dsc->fd = -1; + return ret; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void display_refr_timer_cb(lv_timer_t * tmr) +{ + lv_display_t * disp = lv_timer_get_user_data(tmr); + lv_nuttx_fb_t * dsc = lv_display_get_driver_data(disp); + struct pollfd pfds[1]; + + lv_memzero(pfds, sizeof(pfds)); + pfds[0].fd = dsc->fd; + pfds[0].events = POLLOUT; + + /* Query free fb to draw */ + + if(poll(pfds, 1, 0) < 0) { + return; + } + + if(pfds[0].revents & POLLOUT) { + _lv_display_refr_timer(tmr); + } +} + +static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p) +{ + lv_nuttx_fb_t * dsc = lv_display_get_driver_data(disp); + + /* Skip the non-last flush */ + + if(!lv_display_flush_is_last(disp)) { + lv_display_flush_ready(disp); + return; + } + + if(dsc->mem == NULL || + area->x2 < 0 || area->y2 < 0 || + area->x1 > (int32_t)dsc->vinfo.xres - 1 || area->y1 > (int32_t)dsc->vinfo.yres - 1) { + lv_display_flush_ready(disp); + return; + } + +#if defined(CONFIG_FB_UPDATE) + /*May be some direct update command is required*/ + + struct fb_area_s fb_area; + fb_area.x = area->x1; + fb_area.y = area->y1; + fb_area.w = lv_area_get_width(area); + fb_area.h = lv_area_get_height(area); + if(ioctl(dsc->fd, FBIO_UPDATE, (unsigned long)((uintptr_t)&fb_area)) < 0) { + LV_LOG_ERROR("ioctl(FBIO_UPDATE) failed: %d", errno); + } +#endif + + /* double framebuffer */ + + if(dsc->mem2 != NULL) { + if(disp->buf_act == &disp->buf_1) { + dsc->pinfo.yoffset = 0; + } + else { + dsc->pinfo.yoffset = dsc->mem2_yoffset; + } + + if(ioctl(dsc->fd, FBIOPAN_DISPLAY, (unsigned long)((uintptr_t) & (dsc->pinfo))) < 0) { + LV_LOG_ERROR("ioctl(FBIOPAN_DISPLAY) failed: %d", errno); + } + } + lv_display_flush_ready(disp); +} + +static int fbdev_get_pinfo(int fd, FAR struct fb_planeinfo_s * pinfo) +{ + if(ioctl(fd, FBIOGET_PLANEINFO, (unsigned long)((uintptr_t)pinfo)) < 0) { + LV_LOG_ERROR("ERROR: ioctl(FBIOGET_PLANEINFO) failed: %d", errno); + return -errno; + } + + LV_LOG_USER("PlaneInfo (plane %d):", pinfo->display); + LV_LOG_USER(" mem: %p", pinfo->fbmem); + LV_LOG_USER(" fblen: %zu", pinfo->fblen); + LV_LOG_USER(" stride: %u", pinfo->stride); + LV_LOG_USER(" display: %u", pinfo->display); + LV_LOG_USER(" bpp: %u", pinfo->bpp); + + /* Only these pixel depths are supported. vinfo.fmt is ignored, only + * certain color formats are supported. + */ + + if(pinfo->bpp != 32 && pinfo->bpp != 16 && + pinfo->bpp != 8 && pinfo->bpp != 1) { + LV_LOG_ERROR("bpp = %u not supported", pinfo->bpp); + return -EINVAL; + } + + return 0; +} + +static int fbdev_init_mem2(lv_nuttx_fb_t * dsc) +{ + uintptr_t buf_offset; + struct fb_planeinfo_s pinfo; + int ret; + + lv_memzero(&pinfo, sizeof(pinfo)); + + /* Get display[1] planeinfo */ + + pinfo.display = dsc->pinfo.display + 1; + + if((ret = fbdev_get_pinfo(dsc->fd, &pinfo)) < 0) { + return ret; + } + + /* Check bpp */ + + if(pinfo.bpp != dsc->pinfo.bpp) { + LV_LOG_WARN("mem2 is incorrect"); + return -EINVAL; + } + + /* Check the buffer address offset, + * It needs to be divisible by pinfo.stride + */ + + buf_offset = pinfo.fbmem - dsc->mem; + + if((buf_offset % dsc->pinfo.stride) != 0) { + LV_LOG_WARN("It is detected that buf_offset(%" PRIuPTR ") " + "and stride(%d) are not divisible, please ensure " + "that the driver handles the address offset by itself.", + buf_offset, dsc->pinfo.stride); + } + + /* Calculate the address and yoffset of mem2 */ + + if(buf_offset == 0) { + dsc->mem2_yoffset = dsc->vinfo.yres; + dsc->mem2 = pinfo.fbmem + dsc->mem2_yoffset * pinfo.stride; + LV_LOG_USER("Use consecutive mem2 = %p, yoffset = %" LV_PRIu32, + dsc->mem2, dsc->mem2_yoffset); + } + else { + dsc->mem2_yoffset = buf_offset / dsc->pinfo.stride; + dsc->mem2 = pinfo.fbmem; + LV_LOG_USER("Use non-consecutive mem2 = %p, yoffset = %" LV_PRIu32, + dsc->mem2, dsc->mem2_yoffset); + } + + return 0; +} + +static void display_release_cb(lv_event_t * e) +{ + lv_display_t * disp = (lv_display_t *) lv_event_get_user_data(e); + lv_nuttx_fb_t * dsc = lv_display_get_driver_data(disp); + if(dsc) { + lv_display_set_driver_data(disp, NULL); + lv_display_set_flush_cb(disp, NULL); + + if(dsc->fd >= 0) { + close(dsc->fd); + dsc->fd = -1; + } + lv_free(dsc); + } + LV_LOG_USER("Done"); +} + +#endif /*LV_USE_NUTTX*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_fbdev.h b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_fbdev.h new file mode 100644 index 000000000..994c4973b --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_fbdev.h @@ -0,0 +1,55 @@ +/** + * @file lv_nuttx_fbdev_h + * + */ + +#ifndef LV_NUTTX_FBDEV_H +#define LV_NUTTX_FBDEV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../display/lv_display.h" + +#if LV_USE_NUTTX + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a new display with NuttX backend. + */ +lv_display_t * lv_nuttx_fbdev_create(void); + +/** + * Initialize display with specified framebuffer device + * @param disp pointer to display with NuttX backend + * @param file the name of framebuffer device + */ +int lv_nuttx_fbdev_set_file(lv_display_t * disp, const char * file); + +/********************** + * MACROS + **********************/ + +#endif /* LV_USE_NUTTX */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV_NUTTX_FBDEV_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_lcd.c b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_lcd.c new file mode 100644 index 000000000..c785d222f --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_lcd.c @@ -0,0 +1,238 @@ +/** + * @file lv_nuttx_lcd.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_nuttx_lcd.h" + +#if LV_USE_NUTTX + +#if LV_USE_NUTTX_LCD + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../../lvgl.h" +#include "../../lvgl_private.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + /* fd should be defined at the beginning */ + int fd; + lv_display_t * disp; + struct lcddev_area_s area; + struct lcddev_area_align_s align_info; +} lv_nuttx_lcd_t; + +/********************** + * STATIC PROTOTYPES + **********************/ + +static int32_t align_round_up(int32_t v, uint16_t align); +static void rounder_cb(lv_event_t * e); +static void flush_cb(lv_display_t * disp, const lv_area_t * area_p, + uint8_t * color_p); +static lv_display_t * lcd_init(int fd, int hor_res, int ver_res); +static void display_release_cb(lv_event_t * e); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_display_t * lv_nuttx_lcd_create(const char * dev_path) +{ + struct fb_videoinfo_s vinfo; + struct lcd_planeinfo_s pinfo; + lv_display_t * disp; + int fd; + int ret; + + LV_ASSERT_NULL(dev_path); + + LV_LOG_USER("lcd %s opening", dev_path); + fd = open(dev_path, 0); + if(fd < 0) { + perror("Error: cannot open lcd device"); + return NULL; + } + + LV_LOG_USER("lcd %s open success", dev_path); + + ret = ioctl(fd, LCDDEVIO_GETVIDEOINFO, + (unsigned long)((uintptr_t)&vinfo)); + if(ret < 0) { + perror("Error: ioctl(LCDDEVIO_GETVIDEOINFO) failed"); + close(fd); + return NULL; + } + + ret = ioctl(fd, LCDDEVIO_GETPLANEINFO, + (unsigned long)((uintptr_t)&pinfo)); + if(ret < 0) { + perror("ERROR: ioctl(LCDDEVIO_GETPLANEINFO) failed"); + close(fd); + return NULL; + } + + disp = lcd_init(fd, vinfo.xres, vinfo.yres); + if(disp == NULL) { + close(fd); + } + + return disp; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static int32_t align_round_up(int32_t v, uint16_t align) +{ + return (v + align - 1) & ~(align - 1); +} + +static void rounder_cb(lv_event_t * e) +{ + lv_nuttx_lcd_t * lcd = lv_event_get_user_data(e); + lv_area_t * area = lv_event_get_param(e); + struct lcddev_area_align_s * align_info = &lcd->align_info; + int32_t w; + int32_t h; + + area->x1 &= ~(align_info->col_start_align - 1); + area->y1 &= ~(align_info->row_start_align - 1); + + w = align_round_up(lv_area_get_width(area), align_info->width_align); + h = align_round_up(lv_area_get_height(area), align_info->height_align); + + area->x2 = area->x1 + w - 1; + area->y2 = area->y1 + h - 1; +} + +static void flush_cb(lv_display_t * disp, const lv_area_t * area_p, + uint8_t * color_p) +{ + lv_nuttx_lcd_t * lcd = disp->driver_data; + + lcd->area.row_start = area_p->y1; + lcd->area.row_end = area_p->y2; + lcd->area.col_start = area_p->x1; + lcd->area.col_end = area_p->x2; + lcd->area.data = (uint8_t *)color_p; + ioctl(lcd->fd, LCDDEVIO_PUTAREA, (unsigned long) & (lcd->area)); + lv_display_flush_ready(disp); +} + +static lv_display_t * lcd_init(int fd, int hor_res, int ver_res) +{ + lv_color_t * draw_buf = NULL; + lv_color_t * draw_buf_2 = NULL; + lv_nuttx_lcd_t * lcd = lv_malloc_zeroed(sizeof(lv_nuttx_lcd_t)); + LV_ASSERT_MALLOC(lcd); + if(lcd == NULL) { + LV_LOG_ERROR("lv_nuttx_lcd_t malloc failed"); + return NULL; + } + + lv_display_t * disp = lv_display_create(hor_res, ver_res); + if(disp == NULL) { + lv_free(lcd); + return NULL; + } + + uint32_t px_size = lv_color_format_get_size(lv_display_get_color_format(disp)); +#if LV_NUTTX_LCD_BUFFER_COUNT > 0 + uint32_t buf_size = hor_res * ver_res * px_size; + lv_display_render_mode_t render_mode = LV_DISPLAY_RENDER_MODE_FULL; +#else + uint32_t buf_size = hor_res * LV_NUTTX_LCD_BUFFER_SIZE * px_size; + lv_display_render_mode_t render_mode = LV_DISPLAY_RENDER_MODE_PARTIAL; +#endif + + draw_buf = lv_malloc(buf_size); + if(draw_buf == NULL) { + LV_LOG_ERROR("display draw_buf malloc failed"); + lv_free(lcd); + return NULL; + } + +#if LV_NUTTX_LCD_BUFFER_COUNT == 2 + draw_buf_2 = lv_malloc(buf_size); + if(draw_buf_2 == NULL) { + LV_LOG_ERROR("display draw_buf_2 malloc failed"); + lv_free(lcd); + lv_free(draw_buf); + return NULL; + } +#endif + + lcd->fd = fd; + if(ioctl(fd, LCDDEVIO_GETAREAALIGN, &lcd->align_info) < 0) { + perror("Error: ioctl(LCDDEVIO_GETAREAALIGN) failed"); + } + + lcd->disp = disp; + lv_display_set_buffers(lcd->disp, draw_buf, draw_buf_2, buf_size, render_mode); + lv_display_set_flush_cb(lcd->disp, flush_cb); + lv_display_add_event_cb(lcd->disp, rounder_cb, LV_EVENT_INVALIDATE_AREA, lcd); + lv_display_add_event_cb(lcd->disp, display_release_cb, LV_EVENT_DELETE, lcd->disp); + lv_display_set_driver_data(lcd->disp, lcd); + + return lcd->disp; +} + +static void display_release_cb(lv_event_t * e) +{ + lv_display_t * disp = (lv_display_t *) lv_event_get_user_data(e); + lv_nuttx_lcd_t * dsc = lv_display_get_driver_data(disp); + if(dsc) { + lv_display_set_driver_data(disp, NULL); + lv_display_set_flush_cb(disp, NULL); + + /* clear display buffer */ + if(disp->buf_1) { + lv_free(disp->buf_1); + disp->buf_1 = NULL; + } + if(disp->buf_2) { + lv_free(disp->buf_2); + disp->buf_2 = NULL; + } + + /* close device fb */ + if(dsc->fd >= 0) { + close(dsc->fd); + dsc->fd = -1; + } + lv_free(dsc); + LV_LOG_USER("Done"); + } +} +#endif /*LV_USE_NUTTX_LCD*/ + +#endif /* LV_USE_NUTTX*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_lcd.h b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_lcd.h new file mode 100644 index 000000000..16e24ff8f --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_lcd.h @@ -0,0 +1,49 @@ +/** + * @file lv_nuttx_lcd.h + * + */ + +#ifndef LV_NUTTX_LCD_H +#define LV_NUTTX_LCD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../display/lv_display.h" + +#if LV_USE_NUTTX + +#if LV_USE_NUTTX_LCD + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_display_t * lv_nuttx_lcd_create(const char * dev_path); + +/********************** + * MACROS + **********************/ + +#endif /* LV_USE_NUTTX_LCD */ + +#endif /* LV_USE_NUTTX*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV_NUTTX_LCD_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_libuv.c b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_libuv.c new file mode 100644 index 000000000..f623ae062 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_libuv.c @@ -0,0 +1,340 @@ +/** + * @file lv_nuttx_libuv.c + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_nuttx_libuv.h" +#include + +#include "../../../lvgl.h" +#include "../../lvgl_private.h" + +#if LV_USE_NUTTX + +#if LV_USE_NUTTX_LIBUV +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + int fd; + bool polling; + uv_poll_t fb_poll; + uv_poll_t vsync_poll; +} lv_nuttx_uv_fb_ctx_t; + +typedef struct { + int fd; + uv_poll_t input_poll; + lv_indev_t * indev; +} lv_nuttx_uv_input_ctx_t; + +typedef struct { + uv_timer_t uv_timer; + lv_nuttx_uv_fb_ctx_t fb_ctx; + lv_nuttx_uv_input_ctx_t input_ctx; + int32_t ref_count; +} lv_nuttx_uv_ctx_t; + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void lv_nuttx_uv_timer_cb(uv_timer_t * handle); +static int lv_nuttx_uv_timer_init(lv_nuttx_uv_t * uv_info, lv_nuttx_uv_ctx_t * uv_ctx); +static void lv_nuttx_uv_timer_deinit(lv_nuttx_uv_ctx_t * uv_ctx); + +static void lv_nuttx_uv_vsync_poll_cb(uv_poll_t * handle, int status, int events); +static void lv_nuttx_uv_disp_poll_cb(uv_poll_t * handle, int status, int events); +static void lv_nuttx_uv_disp_refr_req_cb(lv_event_t * e); +static int lv_nuttx_uv_fb_init(lv_nuttx_uv_t * uv_info, lv_nuttx_uv_ctx_t * uv_ctx); +static void lv_nuttx_uv_fb_deinit(lv_nuttx_uv_ctx_t * uv_ctx); + +static void lv_nuttx_uv_input_poll_cb(uv_poll_t * handle, int status, int events); +static int lv_nuttx_uv_input_init(lv_nuttx_uv_t * uv_info, lv_nuttx_uv_ctx_t * uv_ctx); +static void lv_nuttx_uv_input_deinit(lv_nuttx_uv_ctx_t * uv_ctx); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void * lv_nuttx_uv_init(lv_nuttx_uv_t * uv_info) +{ + lv_nuttx_uv_ctx_t * uv_ctx; + int ret; + + uv_ctx = lv_malloc_zeroed(sizeof(lv_nuttx_uv_ctx_t)); + LV_ASSERT_MALLOC(uv_ctx); + if(uv_ctx == NULL) return NULL; + + if((ret = lv_nuttx_uv_timer_init(uv_info, uv_ctx)) < 0) { + LV_LOG_ERROR("lv_nuttx_uv_timer_init fail : %d", ret); + goto err_out; + } + + if((ret = lv_nuttx_uv_fb_init(uv_info, uv_ctx)) < 0) { + LV_LOG_ERROR("lv_nuttx_uv_fb_init fail : %d", ret); + goto err_out; + } + + if((ret = lv_nuttx_uv_input_init(uv_info, uv_ctx)) < 0) { + LV_LOG_ERROR("lv_nuttx_uv_input_init fail : %d", ret); + goto err_out; + } + + return uv_ctx; + +err_out: + lv_free(uv_ctx); + return NULL; +} + +void lv_nuttx_uv_deinit(void ** data) +{ + lv_nuttx_uv_ctx_t * uv_ctx = *data; + + if(uv_ctx == NULL) return; + lv_nuttx_uv_input_deinit(uv_ctx); + lv_nuttx_uv_fb_deinit(uv_ctx); + lv_nuttx_uv_timer_deinit(uv_ctx); + *data = NULL; + LV_LOG_USER("Done"); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_nuttx_uv_timer_cb(uv_timer_t * handle) +{ + uint32_t sleep_ms; + + sleep_ms = lv_timer_handler(); + + if(sleep_ms == LV_NO_TIMER_READY) { + uv_timer_stop(handle); + return; + } + + /* Prevent busy loops. */ + + if(sleep_ms == 0) { + sleep_ms = 1; + } + + LV_LOG_TRACE("sleep_ms = %" LV_PRIu32, sleep_ms); + uv_timer_start(handle, lv_nuttx_uv_timer_cb, sleep_ms, 0); +} + +static void lv_nuttx_uv_timer_resume(void * data) +{ + uv_timer_t * timer = (uv_timer_t *)data; + if(timer) + uv_timer_start(timer, lv_nuttx_uv_timer_cb, 0, 0); +} + +static int lv_nuttx_uv_timer_init(lv_nuttx_uv_t * uv_info, lv_nuttx_uv_ctx_t * uv_ctx) +{ + uv_loop_t * loop = uv_info->loop; + + LV_ASSERT_NULL(uv_ctx); + LV_ASSERT_NULL(loop); + + uv_ctx->uv_timer.data = uv_ctx; + uv_timer_init(loop, &uv_ctx->uv_timer); + uv_ctx->ref_count++; + uv_timer_start(&uv_ctx->uv_timer, lv_nuttx_uv_timer_cb, 1, 1); + + lv_timer_handler_set_resume_cb(lv_nuttx_uv_timer_resume, &uv_ctx->uv_timer); + return 0; +} + +static void lv_nuttx_uv_deinit_cb(uv_handle_t * handle) +{ + lv_nuttx_uv_ctx_t * uv_ctx = handle->data; + if(--uv_ctx->ref_count <= 0) { + LV_LOG_USER("Done"); + lv_free(uv_ctx); + } +} + +static void lv_nuttx_uv_timer_deinit(lv_nuttx_uv_ctx_t * uv_ctx) +{ + lv_timer_handler_set_resume_cb(NULL, NULL); + uv_close((uv_handle_t *)&uv_ctx->uv_timer, lv_nuttx_uv_deinit_cb); + LV_LOG_USER("Done"); +} + +static void lv_nuttx_uv_vsync_poll_cb(uv_poll_t * handle, int status, int events) +{ + LV_UNUSED(handle); + LV_UNUSED(status); + LV_UNUSED(events); + + lv_display_t * d; + d = lv_display_get_next(NULL); + while(d) { + lv_display_send_event(d, LV_EVENT_VSYNC, NULL); + d = lv_display_get_next(d); + } +} + +static void lv_nuttx_uv_disp_poll_cb(uv_poll_t * handle, int status, int events) +{ + lv_nuttx_uv_fb_ctx_t * fb_ctx = &((lv_nuttx_uv_ctx_t *)(handle->data))->fb_ctx; + + LV_UNUSED(status); + LV_UNUSED(events); + uv_poll_stop(handle); + _lv_display_refr_timer(NULL); + fb_ctx->polling = false; +} + +static void lv_nuttx_uv_disp_refr_req_cb(lv_event_t * e) +{ + lv_nuttx_uv_fb_ctx_t * fb_ctx = lv_event_get_user_data(e); + + if(fb_ctx->polling) { + return; + } + fb_ctx->polling = true; + uv_poll_start(&fb_ctx->fb_poll, UV_WRITABLE, lv_nuttx_uv_disp_poll_cb); +} + +static int lv_nuttx_uv_fb_init(lv_nuttx_uv_t * uv_info, lv_nuttx_uv_ctx_t * uv_ctx) +{ + uv_loop_t * loop = uv_info->loop; + lv_display_t * disp = uv_info->disp; + + LV_ASSERT_NULL(uv_ctx); + LV_ASSERT_NULL(disp); + LV_ASSERT_NULL(loop); + + lv_nuttx_uv_fb_ctx_t * fb_ctx = &uv_ctx->fb_ctx; + fb_ctx->fd = *(int *)lv_display_get_driver_data(disp); + + if(fb_ctx->fd <= 0) { + LV_LOG_USER("skip uv fb init."); + return 0; + } + + if(!disp->refr_timer) { + LV_LOG_ERROR("disp->refr_timer is NULL"); + return -EINVAL; + } + + /* Remove default refr timer. */ + + lv_timer_del(disp->refr_timer); + disp->refr_timer = NULL; + + fb_ctx->fb_poll.data = uv_ctx; + uv_poll_init(loop, &fb_ctx->fb_poll, fb_ctx->fd); + uv_ctx->ref_count++; + uv_poll_start(&fb_ctx->fb_poll, UV_WRITABLE, lv_nuttx_uv_disp_poll_cb); + + fb_ctx->vsync_poll.data = uv_ctx; + uv_poll_init(loop, &fb_ctx->vsync_poll, fb_ctx->fd); + uv_ctx->ref_count++; + uv_poll_start(&fb_ctx->vsync_poll, UV_PRIORITIZED, lv_nuttx_uv_vsync_poll_cb); + + LV_LOG_USER("lvgl fb loop start OK"); + + /* Register for the invalidate area event */ + + lv_event_add(&disp->event_list, lv_nuttx_uv_disp_refr_req_cb, LV_EVENT_REFR_REQUEST, fb_ctx); + + return 0; +} + +static void lv_nuttx_uv_fb_deinit(lv_nuttx_uv_ctx_t * uv_ctx) +{ + /* should remove event */ + lv_nuttx_uv_fb_ctx_t * fb_ctx = &uv_ctx->fb_ctx; + if(fb_ctx->fd > 0) { + uv_close((uv_handle_t *)&fb_ctx->fb_poll, lv_nuttx_uv_deinit_cb); + uv_close((uv_handle_t *)&fb_ctx->vsync_poll, lv_nuttx_uv_deinit_cb); + } + LV_LOG_USER("Done"); +} + +static void lv_nuttx_uv_input_poll_cb(uv_poll_t * handle, int status, int events) +{ + lv_indev_t * indev = ((lv_nuttx_uv_ctx_t *)(handle->data))->input_ctx.indev; + + if(status < 0) { + LV_LOG_WARN("input poll error: %s ", uv_strerror(status)); + return; + } + + if(events & UV_READABLE) { + lv_indev_read(indev); + } +} + +static int lv_nuttx_uv_input_init(lv_nuttx_uv_t * uv_info, lv_nuttx_uv_ctx_t * uv_ctx) +{ + uv_loop_t * loop = uv_info->loop; + lv_indev_t * indev = uv_info->indev; + + if(indev == NULL) { + LV_LOG_USER("skip uv input init."); + return 0; + } + + LV_ASSERT_NULL(uv_ctx); + LV_ASSERT_NULL(loop); + + if(lv_indev_get_mode(indev) == LV_INDEV_MODE_EVENT) { + LV_LOG_ERROR("input device has been running in event-driven mode"); + return -EINVAL; + } + + lv_nuttx_uv_input_ctx_t * input_ctx = &uv_ctx->input_ctx; + input_ctx->fd = *(int *)lv_indev_get_driver_data(indev); + if(input_ctx->fd <= 0) { + LV_LOG_ERROR("can't get valid input fd"); + return 0; + } + + input_ctx->indev = indev; + lv_indev_set_mode(indev, LV_INDEV_MODE_EVENT); + + input_ctx->input_poll.data = uv_ctx; + uv_poll_init(loop, &input_ctx->input_poll, input_ctx->fd); + uv_ctx->ref_count++; + uv_poll_start(&input_ctx->input_poll, UV_READABLE, lv_nuttx_uv_input_poll_cb); + + LV_LOG_USER("lvgl input loop start OK"); + + return 0; +} + +static void lv_nuttx_uv_input_deinit(lv_nuttx_uv_ctx_t * uv_ctx) +{ + lv_nuttx_uv_input_ctx_t * input_ctx = &uv_ctx->input_ctx; + if(input_ctx->fd > 0) { + uv_close((uv_handle_t *)&input_ctx->input_poll, lv_nuttx_uv_deinit_cb); + } + LV_LOG_USER("Done"); +} + +#endif /*LV_USE_NUTTX_LIBUV*/ + +#endif /*LV_USE_NUTTX*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_libuv.h b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_libuv.h new file mode 100644 index 000000000..0799e67b1 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_libuv.h @@ -0,0 +1,66 @@ +/** + * @file lv_nuttx_libuv.h + * + */ + +#ifndef LV_NUTTX_LIBUV_H +#define LV_NUTTX_LIBUV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../display/lv_display.h" +#include "../../indev/lv_indev.h" + +#if LV_USE_NUTTX + +#if LV_USE_NUTTX_LIBUV + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + void * loop; + lv_display_t * disp; + lv_indev_t * indev; +} lv_nuttx_uv_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the uv_loop using the provided configuration information. + * @param uv_info Pointer to the lv_nuttx_uv_t structure to be initialized. + */ +void * lv_nuttx_uv_init(lv_nuttx_uv_t * uv_info); + +/** + * Deinitialize the uv_loop configuration for NuttX porting layer. + * @param data Pointer to user data. + */ +void lv_nuttx_uv_deinit(void ** data); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_NUTTX_LIBUV*/ + +#endif /*LV_USE_NUTTX*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_NUTTX_LIBUV_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_profiler.c b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_profiler.c new file mode 100644 index 000000000..3139c98f7 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_profiler.c @@ -0,0 +1,96 @@ +/** + * @file lv_nuttx_profiler.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_nuttx_profiler.h" +#include "../../../lvgl.h" + +#if LV_USE_PROFILER && LV_USE_PROFILER_BUILTIN + +#include +#include + +/********************* + * DEFINES + *********************/ + +#define TICK_TO_USEC(tick) ((tick) / cpu_freq) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static uint32_t cpu_freq = 0; /* MHz */ + +/********************** + * STATIC VARIABLES + **********************/ + +static uint32_t tick_get_cb(void); +static void flush_cb(const char * buf); + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_nuttx_profiler_init(void) +{ + cpu_freq = (uint32_t)up_perf_getfreq() / 1000000; + if(cpu_freq == 0) { + LV_LOG_ERROR("Failed to get CPU frequency"); + return; + } + LV_LOG_USER("CPU frequency: %" LV_PRIu32 " MHz", cpu_freq); + + lv_profiler_builtin_config_t config; + lv_profiler_builtin_config_init(&config); + config.tick_per_sec = 1000000; /* 1 sec = 1000000 usec */ + config.tick_get_cb = tick_get_cb; + config.flush_cb = flush_cb; + lv_profiler_builtin_init(&config); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static uint32_t tick_get_cb(void) +{ + static uint32_t prev_tick = 0; + static uint32_t cur_tick_us = 0; + uint32_t act_time = up_perf_gettime(); + uint32_t elaps; + + /*If there is no overflow in sys_time simple subtract*/ + if(act_time >= prev_tick) { + elaps = act_time - prev_tick; + } + else { + elaps = UINT32_MAX - prev_tick + 1; + elaps += act_time; + } + + cur_tick_us += TICK_TO_USEC(elaps); + prev_tick = act_time; + return cur_tick_us; +} + +static void flush_cb(const char * buf) +{ + printf("%s", buf); +} + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/themes/lv_themes.h b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_profiler.h similarity index 69% rename from lib/libesp32_lvgl/lvgl/src/extra/themes/lv_themes.h rename to lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_profiler.h index 372f6260e..8b8cf6521 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/themes/lv_themes.h +++ b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_profiler.h @@ -1,10 +1,10 @@ /** - * @file lv_themes.h + * @file lv_nuttx_profiler.h * */ -#ifndef LV_THEMES_H -#define LV_THEMES_H +#ifndef LV_NUTTX_PROFILER_H +#define LV_NUTTX_PROFILER_H #ifdef __cplusplus extern "C" { @@ -13,9 +13,6 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "default/lv_theme_default.h" -#include "mono/lv_theme_mono.h" -#include "basic/lv_theme_basic.h" /********************* * DEFINES @@ -29,6 +26,8 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ +void lv_nuttx_profiler_init(void); + /********************** * MACROS **********************/ @@ -37,4 +36,4 @@ extern "C" { } /*extern "C"*/ #endif -#endif /*LV_THEMES_H*/ +#endif /*LV_NUTTX_PROFILER_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_touchscreen.c b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_touchscreen.c new file mode 100644 index 000000000..5dc119677 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_touchscreen.c @@ -0,0 +1,165 @@ +/** + * @file lv_nuttx_touchscreen.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_nuttx_touchscreen.h" + +#if LV_USE_NUTTX + +#if LV_USE_NUTTX_TOUCHSCREEN + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../lvgl_private.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + /* fd should be defined at the beginning */ + int fd; + lv_indev_state_t last_state; + lv_indev_t * indev_drv; +} lv_nuttx_touchscreen_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static void touchscreen_read(lv_indev_t * drv, lv_indev_data_t * data); +static void touchscreen_delete_cb(lv_event_t * e); +static lv_indev_t * touchscreen_init(int fd); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_indev_t * lv_nuttx_touchscreen_create(const char * dev_path) +{ + lv_indev_t * indev; + int fd; + + LV_ASSERT_NULL(dev_path); + LV_LOG_USER("touchscreen %s opening", dev_path); + fd = open(dev_path, O_RDONLY | O_NONBLOCK); + if(fd < 0) { + perror("Error: cannot open touchscreen device"); + return NULL; + } + + LV_LOG_USER("touchscreen %s open success", dev_path); + + indev = touchscreen_init(fd); + + if(indev == NULL) { + close(fd); + } + + return indev; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void touchscreen_read(lv_indev_t * drv, lv_indev_data_t * data) +{ + lv_nuttx_touchscreen_t * touchscreen = drv->driver_data; + struct touch_sample_s sample; + + /* Read one sample */ + + int nbytes = read(touchscreen->fd, &sample, + sizeof(struct touch_sample_s)); + + /* Handle unexpected return values */ + + if(nbytes == sizeof(struct touch_sample_s)) { + uint8_t touch_flags = sample.point[0].flags; + + if(touch_flags & TOUCH_DOWN || touch_flags & TOUCH_MOVE) { + const lv_display_t * disp_drv = drv->disp; + int32_t ver_max = disp_drv->ver_res - 1; + int32_t hor_max = disp_drv->hor_res - 1; + + data->point.x = LV_CLAMP(0, sample.point[0].x, hor_max); + data->point.y = LV_CLAMP(0, sample.point[0].y, ver_max); + touchscreen->last_state = LV_INDEV_STATE_PRESSED; + } + else if(touch_flags & TOUCH_UP) { + touchscreen->last_state = LV_INDEV_STATE_RELEASED; + } + + /* Read until the last point */ + + data->continue_reading = true; + } + + data->state = touchscreen->last_state; +} + +static void touchscreen_delete_cb(lv_event_t * e) +{ + lv_indev_t * indev = (lv_indev_t *) lv_event_get_user_data(e); + lv_nuttx_touchscreen_t * touchscreen = lv_indev_get_driver_data(indev); + if(touchscreen) { + lv_indev_set_driver_data(indev, NULL); + lv_indev_set_read_cb(indev, NULL); + + if(touchscreen->fd >= 0) { + close(touchscreen->fd); + touchscreen->fd = -1; + } + lv_free(touchscreen); + LV_LOG_USER("done"); + } +} + +static lv_indev_t * touchscreen_init(int fd) +{ + lv_nuttx_touchscreen_t * touchscreen; + lv_indev_t * indev = NULL; + + touchscreen = lv_malloc_zeroed(sizeof(lv_nuttx_touchscreen_t)); + if(touchscreen == NULL) { + LV_LOG_ERROR("touchscreen_s malloc failed"); + return NULL; + } + + touchscreen->fd = fd; + touchscreen->last_state = LV_INDEV_STATE_RELEASED; + touchscreen->indev_drv = indev = lv_indev_create(); + + lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); + lv_indev_set_read_cb(indev, touchscreen_read); + lv_indev_set_driver_data(indev, touchscreen); + lv_indev_add_event_cb(indev, touchscreen_delete_cb, LV_EVENT_DELETE, indev); + return indev; +} + +#endif /*LV_USE_NUTTX_TOUCHSCREEN*/ + +#endif /* LV_USE_NUTTX*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_touchscreen.h b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_touchscreen.h new file mode 100644 index 000000000..e0dd1f14f --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/nuttx/lv_nuttx_touchscreen.h @@ -0,0 +1,57 @@ +/** + * @file lv_nuttx_touchscreen.h + * + */ + +/********************* + * INCLUDES + *********************/ + +#ifndef LV_NUTTX_TOUCHSCREEN_H +#define LV_NUTTX_TOUCHSCREEN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../indev/lv_indev.h" + +#if LV_USE_NUTTX + +#if LV_USE_NUTTX_TOUCHSCREEN + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize indev with specified input device. + * @param dev_path path of input device + */ +lv_indev_t * lv_nuttx_touchscreen_create(const char * dev_path); + +/********************** + * MACROS + **********************/ + +#endif /* LV_USE_NUTTX_TOUCHSCREEN */ + +#endif /* LV_USE_NUTTX*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV_NUTTX_TOUCHSCREEN_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_keyboard.c b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_keyboard.c new file mode 100644 index 000000000..012a1a15a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_keyboard.c @@ -0,0 +1,206 @@ +/** + * @file lv_sdl_keyboard.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_sdl_keyboard.h" +#if LV_USE_SDL + +#include "../../indev/lv_indev.h" +#include "../../core/lv_group.h" +#include "../../stdlib/lv_string.h" +#include LV_SDL_INCLUDE_PATH + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + char buf[KEYBOARD_BUFFER_SIZE]; + bool dummy_read; +} lv_sdl_keyboard_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static void sdl_keyboard_read(lv_indev_t * indev, lv_indev_data_t * data); +static uint32_t keycode_to_ctrl_key(SDL_Keycode sdl_key); +static void release_indev_cb(lv_event_t * e); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_indev_t * lv_sdl_keyboard_create(void) +{ + lv_sdl_keyboard_t * dsc = lv_malloc_zeroed(sizeof(lv_sdl_keyboard_t)); + LV_ASSERT_MALLOC(dsc); + if(dsc == NULL) return NULL; + + lv_indev_t * indev = lv_indev_create(); + LV_ASSERT_MALLOC(indev); + if(indev == NULL) { + lv_free(dsc); + return NULL; + } + + lv_indev_set_type(indev, LV_INDEV_TYPE_KEYPAD); + lv_indev_set_read_cb(indev, sdl_keyboard_read); + lv_indev_set_driver_data(indev, dsc); + lv_indev_set_mode(indev, LV_INDEV_MODE_EVENT); + lv_indev_add_event_cb(indev, release_indev_cb, LV_EVENT_DELETE, indev); + + return indev; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void sdl_keyboard_read(lv_indev_t * indev, lv_indev_data_t * data) +{ + lv_sdl_keyboard_t * dev = lv_indev_get_driver_data(indev); + + const size_t len = lv_strlen(dev->buf); + + /*Send a release manually*/ + if(dev->dummy_read) { + dev->dummy_read = false; + data->state = LV_INDEV_STATE_RELEASED; + data->continue_reading = len > 0; + } + /*Send the pressed character*/ + else if(len > 0) { + dev->dummy_read = true; + data->state = LV_INDEV_STATE_PRESSED; + data->key = dev->buf[0]; + memmove(dev->buf, dev->buf + 1, len); + data->continue_reading = true; + } +} + +static void release_indev_cb(lv_event_t * e) +{ + lv_indev_t * indev = (lv_indev_t *) lv_event_get_user_data(e); + lv_sdl_keyboard_t * dev = lv_indev_get_driver_data(indev); + if(dev) { + lv_indev_set_driver_data(indev, NULL); + lv_indev_set_read_cb(indev, NULL); + lv_free(dev); + LV_LOG_INFO("done"); + } +} + +void _lv_sdl_keyboard_handler(SDL_Event * event) +{ + uint32_t win_id = UINT32_MAX; + switch(event->type) { + case SDL_KEYDOWN: + win_id = event->key.windowID; + break; + case SDL_TEXTINPUT: + win_id = event->text.windowID; + break; + default: + return; + } + + lv_display_t * disp = _lv_sdl_get_disp_from_win_id(win_id); + + /*Find a suitable indev*/ + lv_indev_t * indev = lv_indev_get_next(NULL); + while(indev) { + if(lv_indev_get_display(indev) == disp && lv_indev_get_type(indev) == LV_INDEV_TYPE_KEYPAD) { + break; + } + indev = lv_indev_get_next(indev); + } + + if(indev == NULL) return; + lv_sdl_keyboard_t * dsc = lv_indev_get_driver_data(indev); + + /* We only care about SDL_KEYDOWN and SDL_TEXTINPUT events */ + switch(event->type) { + case SDL_KEYDOWN: { /*Button press*/ + const uint32_t ctrl_key = keycode_to_ctrl_key(event->key.keysym.sym); + if(ctrl_key == '\0') + return; + const size_t len = lv_strlen(dsc->buf); + if(len < KEYBOARD_BUFFER_SIZE - 1) { + dsc->buf[len] = ctrl_key; + dsc->buf[len + 1] = '\0'; + } + break; + } + case SDL_TEXTINPUT: { /*Text input*/ + const size_t len = lv_strlen(dsc->buf) + lv_strlen(event->text.text); + if(len < KEYBOARD_BUFFER_SIZE - 1) + strcat(dsc->buf, event->text.text); + } + break; + default: + break; + + } + lv_indev_read(indev); +} + +/** + * Convert a SDL key code to it's LV_KEY_* counterpart or return '\0' if it's not a control character. + * @param sdl_key the key code + * @return LV_KEY_* control character or '\0' + */ +static uint32_t keycode_to_ctrl_key(SDL_Keycode sdl_key) +{ + /*Remap some key to LV_KEY_... to manage groups*/ + switch(sdl_key) { + case SDLK_RIGHT: + case SDLK_KP_PLUS: + return LV_KEY_RIGHT; + + case SDLK_LEFT: + case SDLK_KP_MINUS: + return LV_KEY_LEFT; + + case SDLK_UP: + return LV_KEY_UP; + + case SDLK_DOWN: + return LV_KEY_DOWN; + + case SDLK_ESCAPE: + return LV_KEY_ESC; + + case SDLK_BACKSPACE: + return LV_KEY_BACKSPACE; + + case SDLK_DELETE: + return LV_KEY_DEL; + + case SDLK_KP_ENTER: + case '\r': + return LV_KEY_ENTER; + + case SDLK_TAB: + case SDLK_PAGEDOWN: + return LV_KEY_NEXT; + + case SDLK_PAGEUP: + return LV_KEY_PREV; + + default: + return '\0'; + } +} + +#endif /*LV_USE_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_keyboard.h b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_keyboard.h new file mode 100644 index 000000000..a18b09d8a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_keyboard.h @@ -0,0 +1,46 @@ +/** + * @file lv_sdl_keyboard.h + * + */ + +#ifndef LV_SDL_KEYBOARD_H +#define LV_SDL_KEYBOARD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_sdl_window.h" +#if LV_USE_SDL + +/********************* + * DEFINES + *********************/ +#ifndef KEYBOARD_BUFFER_SIZE +#define KEYBOARD_BUFFER_SIZE 32 +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_indev_t * lv_sdl_keyboard_create(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_SDL*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV_SDL_KEYBOARD_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mouse.c b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mouse.c new file mode 100644 index 000000000..124cd1740 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mouse.c @@ -0,0 +1,181 @@ +/** + * @file lv_sdl_mouse.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_sdl_mouse.h" +#if LV_USE_SDL + +#include "../../core/lv_group.h" +#include "../../stdlib/lv_string.h" + +#include LV_SDL_INCLUDE_PATH +/********************* + * DEFINES + *********************/ + +#ifndef KEYBOARD_BUFFER_SIZE + #define KEYBOARD_BUFFER_SIZE 32 +#endif + +/********************** + * STATIC PROTOTYPES + **********************/ +static void sdl_mouse_read(lv_indev_t * indev, lv_indev_data_t * data); +static void release_indev_cb(lv_event_t * e); + +/********************** + * STATIC VARIABLES + **********************/ + +typedef struct { + int16_t last_x; + int16_t last_y; + bool left_button_down; +} lv_sdl_mouse_t; + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_indev_t * lv_sdl_mouse_create(void) +{ + lv_sdl_mouse_t * dsc = lv_malloc_zeroed(sizeof(lv_sdl_mouse_t)); + LV_ASSERT_MALLOC(dsc); + if(dsc == NULL) return NULL; + + lv_indev_t * indev = lv_indev_create(); + LV_ASSERT_MALLOC(indev); + if(indev == NULL) { + lv_free(dsc); + return NULL; + } + + lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); + lv_indev_set_read_cb(indev, sdl_mouse_read); + lv_indev_set_driver_data(indev, dsc); + + lv_indev_set_mode(indev, LV_INDEV_MODE_EVENT); + lv_indev_add_event_cb(indev, release_indev_cb, LV_EVENT_DELETE, indev); + + return indev; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void sdl_mouse_read(lv_indev_t * indev, lv_indev_data_t * data) +{ + lv_sdl_mouse_t * dsc = lv_indev_get_driver_data(indev); + + /*Store the collected data*/ + data->point.x = dsc->last_x; + data->point.y = dsc->last_y; + data->state = dsc->left_button_down ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; +} + +static void release_indev_cb(lv_event_t * e) +{ + lv_indev_t * indev = (lv_indev_t *) lv_event_get_user_data(e); + lv_sdl_mouse_t * dsc = lv_indev_get_driver_data(indev); + if(dsc) { + lv_indev_set_driver_data(indev, NULL); + lv_indev_set_read_cb(indev, NULL); + lv_free(dsc); + LV_LOG_INFO("done"); + } +} + +void _lv_sdl_mouse_handler(SDL_Event * event) +{ + uint32_t win_id = UINT32_MAX; + switch(event->type) { + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEBUTTONDOWN: + win_id = event->button.windowID; + break; + case SDL_MOUSEMOTION: + win_id = event->motion.windowID; + break; + + case SDL_FINGERUP: + case SDL_FINGERDOWN: + case SDL_FINGERMOTION: +#if SDL_VERSION_ATLEAST(2,0,12) + win_id = event->tfinger.windowID; +#endif + break; + case SDL_WINDOWEVENT: + win_id = event->window.windowID; + break; + default: + return; + } + + lv_display_t * disp = _lv_sdl_get_disp_from_win_id(win_id); + + /*Find a suitable indev*/ + lv_indev_t * indev = lv_indev_get_next(NULL); + while(indev) { + if(lv_indev_get_display(indev) == disp && lv_indev_get_type(indev) == LV_INDEV_TYPE_POINTER) { + break; + } + indev = lv_indev_get_next(indev); + } + + if(indev == NULL) return; + lv_sdl_mouse_t * indev_dev = lv_indev_get_driver_data(indev); + if(indev_dev == NULL) return; + + int32_t hor_res = lv_display_get_horizontal_resolution(disp); + int32_t ver_res = lv_display_get_vertical_resolution(disp); + uint8_t zoom = lv_sdl_window_get_zoom(disp); + + switch(event->type) { + case SDL_WINDOWEVENT: + if(event->window.event == SDL_WINDOWEVENT_LEAVE) { + indev_dev->left_button_down = false; + } + break; + case SDL_MOUSEBUTTONUP: + if(event->button.button == SDL_BUTTON_LEFT) + indev_dev->left_button_down = false; + break; + case SDL_WINDOWEVENT_LEAVE: + indev_dev->left_button_down = false; + break; + case SDL_MOUSEBUTTONDOWN: + if(event->button.button == SDL_BUTTON_LEFT) { + indev_dev->left_button_down = true; + indev_dev->last_x = event->motion.x / zoom; + indev_dev->last_y = event->motion.y / zoom; + } + break; + case SDL_MOUSEMOTION: + indev_dev->last_x = event->motion.x / zoom; + indev_dev->last_y = event->motion.y / zoom; + break; + + case SDL_FINGERUP: + indev_dev->left_button_down = false; + indev_dev->last_x = (int16_t)((float)hor_res * event->tfinger.x / zoom); + indev_dev->last_y = (int16_t)((float)ver_res * event->tfinger.y / zoom); + break; + case SDL_FINGERDOWN: + indev_dev->left_button_down = true; + indev_dev->last_x = (int16_t)((float)hor_res * event->tfinger.x / zoom); + indev_dev->last_y = (int16_t)((float)ver_res * event->tfinger.y / zoom); + break; + case SDL_FINGERMOTION: + indev_dev->last_x = (int16_t)((float)hor_res * event->tfinger.x / zoom); + indev_dev->last_y = (int16_t)((float)ver_res * event->tfinger.y / zoom); + break; + } + lv_indev_read(indev); +} + +#endif /*LV_USE_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mouse.h b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mouse.h new file mode 100644 index 000000000..02e9b576d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mouse.h @@ -0,0 +1,43 @@ +/** + * @file Lv_sdl_mouse.h + * + */ + +#ifndef LV_SDL_MOUSE_H +#define LV_SDL_MOUSE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_sdl_window.h" +#if LV_USE_SDL + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_indev_t * lv_sdl_mouse_create(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_SDL*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV_SDL_MOUSE_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mousewheel.c b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mousewheel.c new file mode 100644 index 000000000..c75fbc4ee --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mousewheel.c @@ -0,0 +1,142 @@ +/** + * @file lv_sdl_mousewheel.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_sdl_mousewheel.h" +#if LV_USE_SDL + +#include "../../core/lv_group.h" +#include "../../indev/lv_indev_private.h" +#include "../../stdlib/lv_string.h" +#include LV_SDL_INCLUDE_PATH + +/********************* + * DEFINES + *********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void sdl_mousewheel_read(lv_indev_t * indev, lv_indev_data_t * data); +static void release_indev_cb(lv_event_t * e); + +/********************** + * STATIC VARIABLES + **********************/ + +typedef struct { + int16_t diff; + lv_indev_state_t state; +} lv_sdl_mousewheel_t; + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_indev_t * lv_sdl_mousewheel_create(void) +{ + lv_sdl_mousewheel_t * dsc = lv_malloc_zeroed(sizeof(lv_sdl_mousewheel_t)); + LV_ASSERT_MALLOC(dsc); + if(dsc == NULL) return NULL; + + lv_indev_t * indev = lv_indev_create(); + if(indev == NULL) { + lv_free(dsc); + return NULL; + } + + lv_indev_set_type(indev, LV_INDEV_TYPE_ENCODER); + lv_indev_set_read_cb(indev, sdl_mousewheel_read); + lv_indev_set_driver_data(indev, dsc); + + lv_indev_set_mode(indev, LV_INDEV_MODE_EVENT); + lv_indev_add_event_cb(indev, release_indev_cb, LV_EVENT_DELETE, indev); + + return indev; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void sdl_mousewheel_read(lv_indev_t * indev, lv_indev_data_t * data) +{ + lv_sdl_mousewheel_t * dsc = lv_indev_get_driver_data(indev); + + data->state = dsc->state; + data->enc_diff = dsc->diff; + dsc->diff = 0; +} + +static void release_indev_cb(lv_event_t * e) +{ + lv_indev_t * indev = (lv_indev_t *) lv_event_get_user_data(e); + lv_sdl_mousewheel_t * dsc = lv_indev_get_driver_data(indev); + if(dsc) { + lv_indev_set_driver_data(indev, NULL); + lv_indev_set_read_cb(indev, NULL); + lv_free(dsc); + LV_LOG_INFO("done"); + } +} + +void _lv_sdl_mousewheel_handler(SDL_Event * event) +{ + uint32_t win_id = UINT32_MAX; + switch(event->type) { + case SDL_MOUSEWHEEL: + win_id = event->wheel.windowID; + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + win_id = event->button.windowID; + break; + default: + return; + } + + lv_display_t * disp = _lv_sdl_get_disp_from_win_id(win_id); + + /*Find a suitable indev*/ + lv_indev_t * indev = lv_indev_get_next(NULL); + while(indev) { + if(lv_indev_get_display(indev) == disp && lv_indev_get_type(indev) == LV_INDEV_TYPE_ENCODER) { + break; + } + indev = lv_indev_get_next(indev); + } + + if(indev == NULL) return; + lv_sdl_mousewheel_t * dsc = lv_indev_get_driver_data(indev); + + switch(event->type) { + case SDL_MOUSEWHEEL: +#ifdef __EMSCRIPTEN__ + /*Escripten scales it wrong*/ + if(event->wheel.y < 0) dsc->diff++; + if(event->wheel.y > 0) dsc->diff--; +#else + dsc->diff = -event->wheel.y; +#endif + break; + case SDL_MOUSEBUTTONDOWN: + if(event->button.button == SDL_BUTTON_MIDDLE) { + dsc->state = LV_INDEV_STATE_PRESSED; + } + break; + case SDL_MOUSEBUTTONUP: + if(event->button.button == SDL_BUTTON_MIDDLE) { + dsc->state = LV_INDEV_STATE_RELEASED; + } + break; + default: + break; + } + lv_indev_read(indev); +} + +#endif /*LV_USE_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mousewheel.h b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mousewheel.h new file mode 100644 index 000000000..6adf6ee02 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_mousewheel.h @@ -0,0 +1,43 @@ +/** + * @file lv_sdl_mousewheel.h + * + */ + +#ifndef LV_SDL_MOUSEWHEEL_H +#define LV_SDL_MOUSEWHEEL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_sdl_window.h" +#if LV_USE_SDL + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_indev_t * lv_sdl_mousewheel_create(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_SDL*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV_DEV_SDL_MOUSEWHEEL_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_window.c b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_window.c new file mode 100644 index 000000000..123703a93 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_window.c @@ -0,0 +1,390 @@ +/** + * @file lv_sdl_window.h + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_sdl_window.h" +#if LV_USE_SDL +#include +#include "../../core/lv_refr.h" +#include "../../stdlib/lv_string.h" +#include "../../core/lv_global.h" +#include "../../lv_init.h" + +#define SDL_MAIN_HANDLED /*To fix SDL's "undefined reference to WinMain" issue*/ +#include LV_SDL_INCLUDE_PATH + +#if LV_USE_DRAW_SDL + #include +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + SDL_Window * window; + SDL_Renderer * renderer; + SDL_Texture * texture; + uint8_t * fb1; + uint8_t * fb2; + uint8_t * fb_act; + uint8_t zoom; + uint8_t ignore_size_chg; +} lv_sdl_window_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p); +static void window_create(lv_display_t * disp); +static void window_update(lv_display_t * disp); +static void texture_resize(lv_display_t * disp); +static void sdl_event_handler(lv_timer_t * t); +static void release_disp_cb(lv_event_t * e); + +/*********************** + * GLOBAL PROTOTYPES + ***********************/ +lv_display_t * _lv_sdl_get_disp_from_win_id(uint32_t win_id); +void _lv_sdl_mouse_handler(SDL_Event * event); +void _lv_sdl_mousewheel_handler(SDL_Event * event); +void _lv_sdl_keyboard_handler(SDL_Event * event); +static void res_chg_event_cb(lv_event_t * e); + +static bool inited = false; + +/********************** + * STATIC VARIABLES + **********************/ +static lv_timer_t * event_handler_timer; + +#define lv_deinit_in_progress LV_GLOBAL_DEFAULT()->deinit_in_progress + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_display_t * lv_sdl_window_create(int32_t hor_res, int32_t ver_res) +{ + if(!inited) { + SDL_Init(SDL_INIT_VIDEO); + SDL_StartTextInput(); + event_handler_timer = lv_timer_create(sdl_event_handler, 5, NULL); + lv_tick_set_cb(SDL_GetTicks); + +#if LV_USE_DRAW_SDL + if(!(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG)) { + fprintf(stderr, "could not initialize sdl2_image: %s\n", IMG_GetError()); + return NULL; + } +#endif + + inited = true; + } + + lv_sdl_window_t * dsc = lv_malloc_zeroed(sizeof(lv_sdl_window_t)); + LV_ASSERT_MALLOC(dsc); + if(dsc == NULL) return NULL; + + lv_display_t * disp = lv_display_create(hor_res, ver_res); + if(disp == NULL) { + lv_free(dsc); + return NULL; + } + lv_display_add_event_cb(disp, release_disp_cb, LV_EVENT_DELETE, disp); + lv_display_set_driver_data(disp, dsc); + window_create(disp); + + lv_display_set_flush_cb(disp, flush_cb); + if(LV_SDL_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL) { + uint8_t * buf1 = malloc(32 * 1024); + uint8_t * buf2 = NULL; +#if LV_SDL_BUF_COUNT == 2 + buf2 = malloc(32 * 1024); +#endif + lv_display_set_buffers(disp, buf1, buf2, + 32 * 1024, LV_DISPLAY_RENDER_MODE_PARTIAL); + } + /*LV_DISPLAY_RENDER_MODE_DIRECT or FULL */ + else { + uint32_t stride = lv_draw_buf_width_to_stride(lv_display_get_horizontal_resolution(disp), + lv_display_get_color_format(disp)); + lv_display_set_buffers(disp, dsc->fb1, dsc->fb2, stride * lv_display_get_vertical_resolution(disp), + LV_SDL_RENDER_MODE); + } + lv_display_add_event_cb(disp, res_chg_event_cb, LV_EVENT_RESOLUTION_CHANGED, NULL); + + return disp; +} + +void lv_sdl_window_set_resizeable(lv_display_t * disp, bool value) +{ + lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); + SDL_SetWindowResizable(dsc->window, value); +} + +void lv_sdl_window_set_zoom(lv_display_t * disp, uint8_t zoom) +{ + lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); + dsc->zoom = zoom; + lv_display_send_event(disp, LV_EVENT_RESOLUTION_CHANGED, NULL); + lv_refr_now(disp); +} + +uint8_t lv_sdl_window_get_zoom(lv_display_t * disp) +{ + lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); + return dsc->zoom; +} + +lv_display_t * _lv_sdl_get_disp_from_win_id(uint32_t win_id) +{ + lv_display_t * disp = lv_display_get_next(NULL); + if(win_id == UINT32_MAX) return disp; + + while(disp) { + lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); + if(SDL_GetWindowID(dsc->window) == win_id) { + return disp; + } + disp = lv_display_get_next(disp); + } + return NULL; +} + +void lv_sdl_window_set_title(lv_display_t * disp, const char * title) +{ + lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); + SDL_SetWindowTitle(dsc->window, title); +} + +void * lv_sdl_window_get_renderer(lv_display_t * disp) +{ + lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); + return dsc->renderer; +} + +void lv_sdl_quit() +{ + if(inited) { + SDL_Quit(); + lv_timer_delete(event_handler_timer); + event_handler_timer = NULL; + inited = false; + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map) +{ + lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); + if(LV_SDL_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL) { + int32_t y; + uint8_t * fb_tmp = dsc->fb_act; + uint32_t px_size = lv_color_format_get_size(lv_display_get_color_format(disp)); + uint32_t px_map_stride = lv_area_get_width(area) * px_size; + int32_t fb_stride = lv_display_get_horizontal_resolution(disp) * px_size; + fb_tmp += area->y1 * fb_stride; + fb_tmp += area->x1 * px_size; + for(y = area->y1; y <= area->y2; y++) { + lv_memcpy(fb_tmp, px_map, px_map_stride); + px_map += px_map_stride; + fb_tmp += fb_stride; + } + } + + /* TYPICALLY YOU DO NOT NEED THIS + * If it was the last part to refresh update the texture of the window.*/ + if(lv_display_flush_is_last(disp)) { + if(LV_SDL_RENDER_MODE != LV_DISPLAY_RENDER_MODE_PARTIAL) { + dsc->fb_act = px_map; + } + window_update(disp); + } + + /*IMPORTANT! It must be called to tell the system the flush is ready*/ + lv_display_flush_ready(disp); +} + +/** + * SDL main thread. All SDL related task have to be handled here! + * It initializes SDL, handles drawing and the mouse. + */ +static void sdl_event_handler(lv_timer_t * t) +{ + LV_UNUSED(t); + + /*Refresh handling*/ + SDL_Event event; + while(SDL_PollEvent(&event)) { + _lv_sdl_mouse_handler(&event); + _lv_sdl_mousewheel_handler(&event); + _lv_sdl_keyboard_handler(&event); + + if(event.type == SDL_WINDOWEVENT) { + lv_display_t * disp = _lv_sdl_get_disp_from_win_id(event.window.windowID); + if(disp == NULL) continue; + lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); + + switch(event.window.event) { +#if SDL_VERSION_ATLEAST(2, 0, 5) + case SDL_WINDOWEVENT_TAKE_FOCUS: +#endif + case SDL_WINDOWEVENT_EXPOSED: + window_update(disp); + break; + case SDL_WINDOWEVENT_RESIZED: + dsc->ignore_size_chg = 1; + lv_display_set_resolution(disp, event.window.data1 / dsc->zoom, event.window.data2 / dsc->zoom); + dsc->ignore_size_chg = 0; + lv_refr_now(disp); + break; + case SDL_WINDOWEVENT_CLOSE: + lv_display_delete(disp); + break; + default: + break; + } + } + if(event.type == SDL_QUIT) { + SDL_Quit(); + lv_deinit(); + inited = false; +#if LV_SDL_DIRECT_EXIT + exit(0); +#endif + } + } +} + +static void window_create(lv_display_t * disp) +{ + lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); + dsc->zoom = 1; + + int flag = SDL_WINDOW_RESIZABLE; +#if LV_SDL_FULLSCREEN + flag |= SDL_WINDOW_FULLSCREEN; +#endif + + int32_t hor_res = lv_display_get_horizontal_resolution(disp); + int32_t ver_res = lv_display_get_vertical_resolution(disp); + dsc->window = SDL_CreateWindow("LVGL Simulator", + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + hor_res * dsc->zoom, ver_res * dsc->zoom, flag); /*last param. SDL_WINDOW_BORDERLESS to hide borders*/ + + dsc->renderer = SDL_CreateRenderer(dsc->window, -1, SDL_RENDERER_SOFTWARE); + texture_resize(disp); + + uint32_t px_size = lv_color_format_get_size(lv_display_get_color_format(disp)); + lv_memset(dsc->fb1, 0xff, hor_res * ver_res * px_size); +#if LV_SDL_BUF_COUNT == 2 + lv_memset(dsc->fb2, 0xff, hor_res * ver_res * px_size); +#endif + /*Some platforms (e.g. Emscripten) seem to require setting the size again */ + SDL_SetWindowSize(dsc->window, hor_res * dsc->zoom, ver_res * dsc->zoom); + texture_resize(disp); +} + +static void window_update(lv_display_t * disp) +{ + lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); +#if LV_USE_DRAW_SDL == 0 + int32_t hor_res = lv_display_get_horizontal_resolution(disp); + uint32_t stride = lv_draw_buf_width_to_stride(hor_res, lv_display_get_color_format(disp)); + SDL_UpdateTexture(dsc->texture, NULL, dsc->fb_act, stride); + + SDL_RenderClear(dsc->renderer); + + /*Update the renderer with the texture containing the rendered image*/ + SDL_RenderCopy(dsc->renderer, dsc->texture, NULL, NULL); +#endif + SDL_RenderPresent(dsc->renderer); +} + +static void texture_resize(lv_display_t * disp) +{ + int32_t hor_res = lv_display_get_horizontal_resolution(disp); + int32_t ver_res = lv_display_get_vertical_resolution(disp); + uint32_t stride = lv_draw_buf_width_to_stride(hor_res, lv_display_get_color_format(disp)); + lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); + + dsc->fb1 = realloc(dsc->fb1, stride * ver_res); + memset(dsc->fb1, 0x00, stride * ver_res); + + if(LV_SDL_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL) { + dsc->fb_act = dsc->fb1; + } + else { +#if LV_SDL_BUF_COUNT == 2 + dsc->fb2 = realloc(dsc->fb2, stride * ver_res); + memset(dsc->fb2, 0x00, stride * ver_res); +#endif + lv_display_set_buffers(disp, dsc->fb1, dsc->fb2, stride * ver_res, LV_SDL_RENDER_MODE); + } + if(dsc->texture) SDL_DestroyTexture(dsc->texture); + +#if LV_COLOR_DEPTH == 32 + SDL_PixelFormatEnum px_format = + SDL_PIXELFORMAT_RGB888; /*same as SDL_PIXELFORMAT_RGB888, but it's not supported in older versions*/ +#elif LV_COLOR_DEPTH == 24 + SDL_PixelFormatEnum px_format = SDL_PIXELFORMAT_BGR24; +#elif LV_COLOR_DEPTH == 16 + SDL_PixelFormatEnum px_format = SDL_PIXELFORMAT_RGB565; +#else +#error("Unsupported color format") +#endif + // px_format = SDL_PIXELFORMAT_BGR24; + + dsc->texture = SDL_CreateTexture(dsc->renderer, px_format, + SDL_TEXTUREACCESS_STATIC, hor_res, ver_res); + SDL_SetTextureBlendMode(dsc->texture, SDL_BLENDMODE_BLEND); +} + +static void res_chg_event_cb(lv_event_t * e) +{ + lv_display_t * disp = lv_event_get_current_target(e); + + int32_t hor_res = lv_display_get_horizontal_resolution(disp); + int32_t ver_res = lv_display_get_vertical_resolution(disp); + lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); + if(dsc->ignore_size_chg == false) { + SDL_SetWindowSize(dsc->window, hor_res * dsc->zoom, ver_res * dsc->zoom); + } + + texture_resize(disp); +} + +static void release_disp_cb(lv_event_t * e) +{ + if(lv_deinit_in_progress) { + lv_sdl_quit(); + } + + lv_display_t * disp = (lv_display_t *) lv_event_get_user_data(e); + + lv_sdl_window_t * dsc = lv_display_get_driver_data(disp); + SDL_DestroyTexture(dsc->texture); + SDL_DestroyRenderer(dsc->renderer); + SDL_DestroyWindow(dsc->window); + if(dsc->fb1) free(dsc->fb1); + if(dsc->fb2) free(dsc->fb2); + lv_free(dsc); + lv_display_set_driver_data(disp, NULL); +} + +#endif /*LV_USE_SDL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_window.h b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_window.h new file mode 100644 index 000000000..53c7b194b --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/sdl/lv_sdl_window.h @@ -0,0 +1,60 @@ +/** + * @file lv_sdl_window.h + * + */ + +#ifndef LV_SDL_DISP_H +#define LV_SDL_DISP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../display/lv_display.h" +#include "../../indev/lv_indev.h" + +#if LV_USE_SDL + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_display_t * lv_sdl_window_create(int32_t hor_res, int32_t ver_res); + +void lv_sdl_window_set_resizeable(lv_display_t * disp, bool value); + +void lv_sdl_window_set_zoom(lv_display_t * disp, uint8_t zoom); + +uint8_t lv_sdl_window_get_zoom(lv_display_t * disp); + +lv_display_t * _lv_sdl_get_disp_from_win_id(uint32_t win_id); + +void lv_sdl_window_set_title(lv_display_t * disp, const char * title); + +void * lv_sdl_window_get_renderer(lv_display_t * disp); + +void lv_sdl_quit(); + +/********************** + * MACROS + **********************/ + +#endif /* LV_DRV_SDL */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV_SDL_DISP_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_context.c b/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_context.c new file mode 100644 index 000000000..7bb1f4a35 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_context.c @@ -0,0 +1,669 @@ +/** + * @file lv_windows_context.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_windows_context.h" +#if LV_USE_WINDOWS + +#include "lv_windows_display.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static uint32_t lv_windows_tick_count_callback(void); + +static void lv_windows_check_display_existence_timer_callback( + lv_timer_t * timer); + +static LRESULT CALLBACK lv_windows_window_message_callback( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +bool lv_windows_pointer_device_window_message_handler( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam, + LRESULT * plResult); + +bool lv_windows_keypad_device_window_message_handler( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam, + LRESULT * plResult); + +bool lv_windows_encoder_device_window_message_handler( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam, + LRESULT * plResult); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_windows_platform_init(void) +{ + lv_tick_set_cb(lv_windows_tick_count_callback); + + lv_timer_create( + lv_windows_check_display_existence_timer_callback, + 200, + NULL); + + // Try to ensure the default group exists. + { + lv_group_t * default_group = lv_group_get_default(); + if(!default_group) { + default_group = lv_group_create(); + if(default_group) { + lv_group_set_default(default_group); + } + } + } + + WNDCLASSEXW window_class; + lv_memzero(&window_class, sizeof(WNDCLASSEXW)); + window_class.cbSize = sizeof(WNDCLASSEXW); + window_class.style = 0; + window_class.lpfnWndProc = lv_windows_window_message_callback; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = NULL; + window_class.hIcon = NULL; + window_class.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); + window_class.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + window_class.lpszMenuName = NULL; + window_class.lpszClassName = L"LVGL.Window"; + window_class.hIconSm = NULL; + LV_ASSERT(RegisterClassExW(&window_class)); +} + +lv_windows_window_context_t * lv_windows_get_window_context( + HWND window_handle) +{ + return (lv_windows_window_context_t *)( + GetPropW(window_handle, L"LVGL.Window.Context")); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static uint32_t lv_windows_tick_count_callback(void) +{ + return GetTickCount(); +} + +static void lv_windows_check_display_existence_timer_callback( + lv_timer_t * timer) +{ + if(!lv_display_get_next(NULL)) { + // Don't use lv_deinit() due to it will cause exception when parallel + // rendering is enabled. + exit(0); + } +} + +static HDC lv_windows_create_frame_buffer( + HWND window_handle, + LONG width, + LONG height, + UINT32 ** pixel_buffer, + SIZE_T * pixel_buffer_size) +{ + HDC frame_buffer_dc_handle = NULL; + + LV_ASSERT_NULL(pixel_buffer); + LV_ASSERT_NULL(pixel_buffer_size); + + HDC window_dc_handle = GetDC(window_handle); + if(window_dc_handle) { + frame_buffer_dc_handle = CreateCompatibleDC(window_dc_handle); + ReleaseDC(window_handle, window_dc_handle); + } + + if(frame_buffer_dc_handle) { +#if (LV_COLOR_DEPTH == 32) || (LV_COLOR_DEPTH == 24) + BITMAPINFO bitmap_info = { 0 }; +#elif (LV_COLOR_DEPTH == 16) + typedef struct _BITMAPINFO_16BPP { + BITMAPINFOHEADER bmiHeader; + DWORD bmiColorMask[3]; + } BITMAPINFO_16BPP, * PBITMAPINFO_16BPP; + + BITMAPINFO_16BPP bitmap_info = { 0 }; +#else +#error [lv_windows] Unsupported LV_COLOR_DEPTH. +#endif + + bitmap_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bitmap_info.bmiHeader.biWidth = width; + bitmap_info.bmiHeader.biHeight = -height; + bitmap_info.bmiHeader.biPlanes = 1; + bitmap_info.bmiHeader.biBitCount = lv_color_format_get_bpp( + LV_COLOR_FORMAT_NATIVE); +#if (LV_COLOR_DEPTH == 32) || (LV_COLOR_DEPTH == 24) + bitmap_info.bmiHeader.biCompression = BI_RGB; +#elif (LV_COLOR_DEPTH == 16) + bitmap_info.bmiHeader.biCompression = BI_BITFIELDS; + bitmap_info.bmiColorMask[0] = 0xF800; + bitmap_info.bmiColorMask[1] = 0x07E0; + bitmap_info.bmiColorMask[2] = 0x001F; +#else +#error [lv_windows] Unsupported LV_COLOR_DEPTH. +#endif + + HBITMAP hBitmap = CreateDIBSection( + frame_buffer_dc_handle, + (PBITMAPINFO)(&bitmap_info), + DIB_RGB_COLORS, + (void **)pixel_buffer, + NULL, + 0); + if(hBitmap) { + *pixel_buffer_size = width * height; + *pixel_buffer_size *= lv_color_format_get_size( + LV_COLOR_FORMAT_NATIVE); + + DeleteObject(SelectObject(frame_buffer_dc_handle, hBitmap)); + DeleteObject(hBitmap); + } + else { + DeleteDC(frame_buffer_dc_handle); + frame_buffer_dc_handle = NULL; + } + } + + return frame_buffer_dc_handle; +} + +static void lv_windows_display_timer_callback(lv_timer_t * timer) +{ + lv_windows_window_context_t * context = lv_timer_get_user_data(timer); + LV_ASSERT_NULL(context); + + if(!context->display_resolution_changed) { + return; + } + + lv_display_set_resolution( + context->display_device_object, + context->requested_display_resolution.x, + context->requested_display_resolution.y); + + int32_t hor_res = lv_display_get_horizontal_resolution( + context->display_device_object); + int32_t ver_res = lv_display_get_vertical_resolution( + context->display_device_object); + + HWND window_handle = lv_windows_get_display_window_handle( + context->display_device_object); + if(window_handle) { + if(context->display_framebuffer_context_handle) { + context->display_framebuffer_base = NULL; + context->display_framebuffer_size = 0; + DeleteDC(context->display_framebuffer_context_handle); + context->display_framebuffer_context_handle = NULL; + } + + context->display_framebuffer_context_handle = + lv_windows_create_frame_buffer( + window_handle, + hor_res, + ver_res, + &context->display_framebuffer_base, + &context->display_framebuffer_size); + if(context->display_framebuffer_context_handle) { + lv_display_set_buffers( + context->display_device_object, + context->display_framebuffer_base, + NULL, + context->display_framebuffer_size, + LV_DISPLAY_RENDER_MODE_DIRECT); + } + } + + context->display_resolution_changed = false; + context->requested_display_resolution.x = 0; + context->requested_display_resolution.y = 0; +} + +static void lv_windows_display_driver_flush_callback( + lv_display_t * display, + const lv_area_t * area, + uint8_t * px_map) +{ + HWND window_handle = lv_windows_get_display_window_handle(display); + if(!window_handle) { + lv_display_flush_ready(display); + return; + } + + lv_windows_window_context_t * context = lv_windows_get_window_context( + window_handle); + if(!context) { + lv_display_flush_ready(display); + return; + } + + if(lv_display_flush_is_last(display)) { +#if (LV_COLOR_DEPTH == 32) || \ + (LV_COLOR_DEPTH == 24) || \ + (LV_COLOR_DEPTH == 16) + UNREFERENCED_PARAMETER(px_map); +#else +#error [lv_windows] Unsupported LV_COLOR_DEPTH. +#endif + + HDC hdc = GetDC(window_handle); + if(hdc) { + SetStretchBltMode(hdc, HALFTONE); + + RECT client_rect; + GetClientRect(window_handle, &client_rect); + + int32_t width = lv_windows_zoom_to_logical( + client_rect.right - client_rect.left, + context->zoom_level); + int32_t height = lv_windows_zoom_to_logical( + client_rect.bottom - client_rect.top, + context->zoom_level); + if(context->simulator_mode) { + width = lv_windows_dpi_to_logical(width, context->window_dpi); + height = lv_windows_dpi_to_logical(height, context->window_dpi); + } + + StretchBlt( + hdc, + client_rect.left, + client_rect.top, + client_rect.right - client_rect.left, + client_rect.bottom - client_rect.top, + context->display_framebuffer_context_handle, + 0, + 0, + width, + height, + SRCCOPY); + + ReleaseDC(window_handle, hdc); + } + } + + lv_display_flush_ready(display); +} + +static UINT lv_windows_get_dpi_for_window(HWND window_handle) +{ + UINT result = (UINT)(-1); + + HMODULE module_handle = LoadLibraryW(L"SHCore.dll"); + if(module_handle) { + typedef enum MONITOR_DPI_TYPE_PRIVATE { + MDT_EFFECTIVE_DPI = 0, + MDT_ANGULAR_DPI = 1, + MDT_RAW_DPI = 2, + MDT_DEFAULT = MDT_EFFECTIVE_DPI + } MONITOR_DPI_TYPE_PRIVATE; + + typedef HRESULT(WINAPI * function_type)( + HMONITOR, MONITOR_DPI_TYPE_PRIVATE, UINT *, UINT *); + + function_type function = (function_type)( + GetProcAddress(module_handle, "GetDpiForMonitor")); + if(function) { + HMONITOR MonitorHandle = MonitorFromWindow( + window_handle, + MONITOR_DEFAULTTONEAREST); + + UINT dpiX = 0; + UINT dpiY = 0; + if(SUCCEEDED(function( + MonitorHandle, + MDT_EFFECTIVE_DPI, + &dpiX, + &dpiY))) { + result = dpiX; + } + } + + FreeLibrary(module_handle); + } + + if(result == (UINT)(-1)) { + HDC hWindowDC = GetDC(window_handle); + if(hWindowDC) { + result = GetDeviceCaps(hWindowDC, LOGPIXELSX); + ReleaseDC(window_handle, hWindowDC); + } + } + + if(result == (UINT)(-1)) { + result = USER_DEFAULT_SCREEN_DPI; + } + + return result; +} + +static BOOL lv_windows_register_touch_window( + HWND window_handle, + ULONG flags) +{ + HMODULE module_handle = GetModuleHandleW(L"user32.dll"); + if(!module_handle) { + return FALSE; + } + + typedef BOOL(WINAPI * function_type)(HWND, ULONG); + + function_type function = (function_type)( + GetProcAddress(module_handle, "RegisterTouchWindow")); + if(!function) { + return FALSE; + } + + return function(window_handle, flags); +} + +static BOOL lv_windows_enable_child_window_dpi_message( + HWND WindowHandle) +{ + // The private Per-Monitor DPI Awareness support extension is Windows 10 + // only. We don't need the private Per-Monitor DPI Awareness support + // extension if the Per-Monitor (V2) DPI Awareness exists. + OSVERSIONINFOEXW os_version_info_ex = { 0 }; + os_version_info_ex.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); + os_version_info_ex.dwMajorVersion = 10; + os_version_info_ex.dwMinorVersion = 0; + os_version_info_ex.dwBuildNumber = 14986; + if(!VerifyVersionInfoW( + &os_version_info_ex, + VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER, + VerSetConditionMask( + VerSetConditionMask( + VerSetConditionMask( + 0, + VER_MAJORVERSION, + VER_GREATER_EQUAL), + VER_MINORVERSION, + VER_GREATER_EQUAL), + VER_BUILDNUMBER, + VER_LESS))) { + return FALSE; + } + + HMODULE module_handle = GetModuleHandleW(L"user32.dll"); + if(!module_handle) { + return FALSE; + } + + typedef BOOL(WINAPI * function_type)(HWND, BOOL); + + function_type function = (function_type)( + GetProcAddress(module_handle, "EnableChildWindowDpiMessage")); + if(!function) { + return FALSE; + } + + return function(WindowHandle, TRUE); +} + +static LRESULT CALLBACK lv_windows_window_message_callback( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch(uMsg) { + case WM_CREATE: { + // Note: Return -1 directly because WM_DESTROY message will be sent + // when destroy the window automatically. We free the resource when + // processing the WM_DESTROY message of this window. + + lv_windows_create_display_data_t * data = + (lv_windows_create_display_data_t *)( + ((LPCREATESTRUCTW)(lParam))->lpCreateParams); + if(!data) { + return -1; + } + + lv_windows_window_context_t * context = + (lv_windows_window_context_t *)(HeapAlloc( + GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(lv_windows_window_context_t))); + if(!context) { + return -1; + } + + if(!SetPropW(hWnd, L"LVGL.Window.Context", (HANDLE)(context))) { + return -1; + } + + context->window_dpi = lv_windows_get_dpi_for_window(hWnd); + context->zoom_level = data->zoom_level; + context->allow_dpi_override = data->allow_dpi_override; + context->simulator_mode = data->simulator_mode; + + context->display_timer_object = lv_timer_create( + lv_windows_display_timer_callback, + LV_DEF_REFR_PERIOD, + context); + + context->display_resolution_changed = false; + context->requested_display_resolution.x = 0; + context->requested_display_resolution.y = 0; + + context->display_device_object = lv_display_create(0, 0); + if(!context->display_device_object) { + return -1; + } + RECT request_content_size; + GetWindowRect(hWnd, &request_content_size); + lv_display_set_resolution( + context->display_device_object, + request_content_size.right - request_content_size.left, + request_content_size.bottom - request_content_size.top); + lv_display_set_flush_cb( + context->display_device_object, + lv_windows_display_driver_flush_callback); + lv_display_set_driver_data( + context->display_device_object, + hWnd); + if(!context->allow_dpi_override) { + lv_display_set_dpi( + context->display_device_object, + context->window_dpi); + } + + if(context->simulator_mode) { + context->display_resolution_changed = true; + context->requested_display_resolution.x = + lv_display_get_horizontal_resolution( + context->display_device_object); + context->requested_display_resolution.y = + lv_display_get_vertical_resolution( + context->display_device_object); + } + + lv_windows_register_touch_window(hWnd, 0); + + lv_windows_enable_child_window_dpi_message(hWnd); + + break; + } + case WM_SIZE: { + if(wParam != SIZE_MINIMIZED) { + lv_windows_window_context_t * context = (lv_windows_window_context_t *)( + lv_windows_get_window_context(hWnd)); + if(context) { + if(!context->simulator_mode) { + context->display_resolution_changed = true; + context->requested_display_resolution.x = LOWORD(lParam); + context->requested_display_resolution.y = HIWORD(lParam); + } + else { + int32_t window_width = lv_windows_dpi_to_physical( + lv_windows_zoom_to_physical( + lv_display_get_horizontal_resolution( + context->display_device_object), + context->zoom_level), + context->window_dpi); + int32_t window_height = lv_windows_dpi_to_physical( + lv_windows_zoom_to_physical( + lv_display_get_vertical_resolution( + context->display_device_object), + context->zoom_level), + context->window_dpi); + + RECT window_rect; + GetWindowRect(hWnd, &window_rect); + + RECT client_rect; + GetClientRect(hWnd, &client_rect); + + int32_t original_window_width = + window_rect.right - window_rect.left; + int32_t original_window_height = + window_rect.bottom - window_rect.top; + + int32_t original_client_width = + client_rect.right - client_rect.left; + int32_t original_client_height = + client_rect.bottom - client_rect.top; + + int32_t reserved_width = + original_window_width - original_client_width; + int32_t reserved_height = + original_window_height - original_client_height; + + SetWindowPos( + hWnd, + NULL, + 0, + 0, + reserved_width + window_width, + reserved_height + window_height, + SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE); + } + } + } + break; + } + case WM_DPICHANGED: { + lv_windows_window_context_t * context = (lv_windows_window_context_t *)( + lv_windows_get_window_context(hWnd)); + if(context) { + context->window_dpi = HIWORD(wParam); + + if(!context->allow_dpi_override) { + lv_display_set_dpi( + context->display_device_object, + context->window_dpi); + } + + LPRECT suggested_rect = (LPRECT)lParam; + + SetWindowPos( + hWnd, + NULL, + suggested_rect->left, + suggested_rect->top, + suggested_rect->right, + suggested_rect->bottom, + SWP_NOZORDER | SWP_NOACTIVATE); + } + + break; + } + case WM_ERASEBKGND: { + return TRUE; + } + case WM_DESTROY: { + lv_windows_window_context_t * context = (lv_windows_window_context_t *)( + RemovePropW(hWnd, L"LVGL.Window.Context")); + if(context) { + lv_display_t * display_device_object = + context->display_device_object; + context->display_device_object = NULL; + lv_display_delete(display_device_object); + DeleteDC(context->display_framebuffer_context_handle); + + lv_timer_delete(context->display_timer_object); + + HeapFree(GetProcessHeap(), 0, context); + } + + PostQuitMessage(0); + + break; + } + default: { + lv_windows_window_context_t * context = (lv_windows_window_context_t *)( + lv_windows_get_window_context(hWnd)); + if(context) { + LRESULT lResult = 0; + if(context->pointer.indev && + lv_windows_pointer_device_window_message_handler( + hWnd, + uMsg, + wParam, + lParam, + &lResult)) { + return lResult; + } + else if(context->keypad.indev && + lv_windows_keypad_device_window_message_handler( + hWnd, + uMsg, + wParam, + lParam, + &lResult)) { + return lResult; + } + else if(context->encoder.indev && + lv_windows_encoder_device_window_message_handler( + hWnd, + uMsg, + wParam, + lParam, + &lResult)) { + return lResult; + } + } + + return DefWindowProcW(hWnd, uMsg, wParam, lParam); + } + } + + return 0; +} + +#endif // LV_USE_WINDOWS diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_context.h b/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_context.h new file mode 100644 index 000000000..20e72af37 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_context.h @@ -0,0 +1,123 @@ +/** + * @file lv_windows_context.h + * + */ + +#ifndef LV_WINDOWS_CONTEXT_H +#define LV_WINDOWS_CONTEXT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../display/lv_display.h" +#include "../../indev/lv_indev.h" + +#if LV_USE_WINDOWS + +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct _lv_windows_pointer_context_t { + lv_indev_state_t state; + lv_point_t point; + lv_indev_t * indev; +} lv_windows_pointer_context_t; + +typedef struct _lv_windows_keypad_queue_item_t { + uint32_t key; + lv_indev_state_t state; +} lv_windows_keypad_queue_item_t; + +typedef struct _lv_windows_keypad_context_t { + CRITICAL_SECTION mutex; + lv_ll_t queue; + uint16_t utf16_high_surrogate; + uint16_t utf16_low_surrogate; + lv_indev_t * indev; +} lv_windows_keypad_context_t; + +typedef struct _lv_windows_encoder_context_t { + lv_indev_state_t state; + int16_t enc_diff; + lv_indev_t * indev; +} lv_windows_encoder_context_t; + +typedef struct _lv_windows_window_context_t { + lv_display_t * display_device_object; + lv_timer_t * display_timer_object; + + int32_t window_dpi; + int32_t zoom_level; + bool allow_dpi_override; + bool simulator_mode; + bool display_resolution_changed; + lv_point_t requested_display_resolution; + + HDC display_framebuffer_context_handle; + uint32_t * display_framebuffer_base; + size_t display_framebuffer_size; + + lv_windows_pointer_context_t pointer; + lv_windows_keypad_context_t keypad; + lv_windows_encoder_context_t encoder; + +} lv_windows_window_context_t; + +typedef struct _lv_windows_create_display_data_t { + const wchar_t * title; + int32_t hor_res; + int32_t ver_res; + int32_t zoom_level; + bool allow_dpi_override; + bool simulator_mode; + HANDLE mutex; + lv_display_t * display; +} lv_windows_create_display_data_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * @brief Initialize the LVGL Windows backend. + * @remark This is a private API which is used for LVGL Windows backend + * implementation. LVGL users shouldn't use that because the + * LVGL has already used it in lv_init. +*/ +void lv_windows_platform_init(void); + +/** + * @brief Get the window context from specific LVGL display window. + * @param window_handle The window handle of specific LVGL display window. + * @return The window context from specific LVGL display window. + * @remark This is a private API which is used for LVGL Windows backend + * implementation. LVGL users shouldn't use that because the + * maintainer doesn't promise the application binary interface + * compatibility for this API. +*/ +lv_windows_window_context_t * lv_windows_get_window_context( + HWND window_handle); + +/********************** + * MACROS + **********************/ + +#endif // LV_USE_WINDOWS + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_WINDOWS_CONTEXT_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_display.c b/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_display.c new file mode 100644 index 000000000..958338ec6 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_display.c @@ -0,0 +1,170 @@ +/** + * @file lv_windows_display.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_windows_display.h" +#if LV_USE_WINDOWS + +#include "lv_windows_context.h" + +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static unsigned int __stdcall lv_windows_display_thread_entrypoint( + void * parameter); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_display_t * lv_windows_create_display( + const wchar_t * title, + int32_t hor_res, + int32_t ver_res, + int32_t zoom_level, + bool allow_dpi_override, + bool simulator_mode) +{ + lv_windows_create_display_data_t data; + + lv_memzero(&data, sizeof(lv_windows_create_display_data_t)); + data.title = title; + data.hor_res = hor_res; + data.ver_res = ver_res; + data.zoom_level = zoom_level; + data.allow_dpi_override = allow_dpi_override; + data.simulator_mode = simulator_mode; + data.mutex = CreateEventExW(NULL, NULL, 0, EVENT_ALL_ACCESS); + data.display = NULL; + if(!data.mutex) { + return NULL; + } + + HANDLE thread = (HANDLE)_beginthreadex( + NULL, + 0, + lv_windows_display_thread_entrypoint, + &data, + 0, + NULL); + LV_ASSERT(thread); + + WaitForSingleObjectEx(data.mutex, INFINITE, FALSE); + + if(thread) { + CloseHandle(thread); + } + + if(data.mutex) { + CloseHandle(data.mutex); + } + + return data.display; +} + +HWND lv_windows_get_display_window_handle(lv_display_t * display) +{ + return (HWND)lv_display_get_driver_data(display); +} + +int32_t lv_windows_zoom_to_logical(int32_t physical, int32_t zoom_level) +{ + return MulDiv(physical, LV_WINDOWS_ZOOM_BASE_LEVEL, zoom_level); +} + +int32_t lv_windows_zoom_to_physical(int32_t logical, int32_t zoom_level) +{ + return MulDiv(logical, zoom_level, LV_WINDOWS_ZOOM_BASE_LEVEL); +} + +int32_t lv_windows_dpi_to_logical(int32_t physical, int32_t dpi) +{ + return MulDiv(physical, USER_DEFAULT_SCREEN_DPI, dpi); +} + +int32_t lv_windows_dpi_to_physical(int32_t logical, int32_t dpi) +{ + return MulDiv(logical, dpi, USER_DEFAULT_SCREEN_DPI); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static unsigned int __stdcall lv_windows_display_thread_entrypoint( + void * parameter) +{ + lv_windows_create_display_data_t * data = parameter; + LV_ASSERT_NULL(data); + + DWORD window_style = WS_OVERLAPPEDWINDOW; + if(data->simulator_mode) { + window_style &= ~(WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME); + } + + HWND window_handle = CreateWindowExW( + WS_EX_CLIENTEDGE, + L"LVGL.Window", + data->title, + window_style, + CW_USEDEFAULT, + 0, + data->hor_res, + data->ver_res, + NULL, + NULL, + NULL, + data); + if(!window_handle) { + return 0; + } + + lv_windows_window_context_t * context = lv_windows_get_window_context( + window_handle); + if(!context) { + return 0; + } + + data->display = context->display_device_object; + + ShowWindow(window_handle, SW_SHOW); + UpdateWindow(window_handle); + + LV_ASSERT(SetEvent(data->mutex)); + + data = NULL; + + MSG message; + while(GetMessageW(&message, NULL, 0, 0)) { + TranslateMessage(&message); + DispatchMessageW(&message); + } + + return 0; +} + +#endif // LV_USE_WINDOWS diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_display.h b/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_display.h new file mode 100644 index 000000000..b9c6f8e94 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_display.h @@ -0,0 +1,127 @@ +/** + * @file lv_windows_display.h + * + */ + +#ifndef LV_WINDOWS_DISPLAY_H +#define LV_WINDOWS_DISPLAY_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../display/lv_display.h" +#include "../../indev/lv_indev.h" + +#if LV_USE_WINDOWS + +#include + +/********************* + * DEFINES + *********************/ + +#define LV_WINDOWS_ZOOM_BASE_LEVEL 100 + +#ifndef USER_DEFAULT_SCREEN_DPI +#define USER_DEFAULT_SCREEN_DPI 96 +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * @brief Create a LVGL display object. + * @param title The window title of LVGL display. + * @param hor_res The horizontal resolution value of LVGL display. + * @param ver_res The vertical resolution value of LVGL display. + * @param zoom_level The zoom level value. Base value is 100 a.k.a 100%. + * @param allow_dpi_override Allow DPI override if true, or follow the + * Windows DPI scaling setting dynamically. + * @param simulator_mode Create simulator mode display if true, or create + * application mode display. + * @return The created LVGL display object. +*/ +lv_display_t * lv_windows_create_display( + const wchar_t * title, + int32_t hor_res, + int32_t ver_res, + int32_t zoom_level, + bool allow_dpi_override, + bool simulator_mode); + +/** + * @brief Get the window handle from specific LVGL display object. + * @param display The specific LVGL display object. + * @return The window handle from specific LVGL display object. +*/ +HWND lv_windows_get_display_window_handle(lv_display_t * display); + +/** + * @brief Get logical pixel value from physical pixel value taken account + * with zoom level. + * @param physical The physical pixel value taken account with zoom level. + * @param zoom_level The zoom level value. Base value is 100 a.k.a 100%. + * @return The logical pixel value. + * @remark It uses the same calculation style as Windows OS implementation. + * It will be useful for integrate LVGL Windows backend to other + * Windows applications. +*/ +int32_t lv_windows_zoom_to_logical(int32_t physical, int32_t zoom_level); + +/** + * @brief Get physical pixel value taken account with zoom level from + * logical pixel value. + * @param logical The logical pixel value. + * @param zoom_level The zoom level value. Base value is 100 a.k.a 100%. + * @return The physical pixel value taken account with zoom level. + * @remark It uses the same calculation style as Windows OS implementation. + * It will be useful for integrate LVGL Windows backend to other + * Windows applications. +*/ +int32_t lv_windows_zoom_to_physical(int32_t logical, int32_t zoom_level); + +/** + * @brief Get logical pixel value from physical pixel value taken account + * with DPI scaling. + * @param physical The physical pixel value taken account with DPI scaling. + * @param dpi The DPI scaling value. Base value is USER_DEFAULT_SCREEN_DPI. + * @return The logical pixel value. + * @remark It uses the same calculation style as Windows OS implementation. + * It will be useful for integrate LVGL Windows backend to other + * Windows applications. +*/ +int32_t lv_windows_dpi_to_logical(int32_t physical, int32_t dpi); + +/** + * @brief Get physical pixel value taken account with DPI scaling from + * logical pixel value. + * @param logical The logical pixel value. + * @param dpi The DPI scaling value. Base value is USER_DEFAULT_SCREEN_DPI. + * @return The physical pixel value taken account with DPI scaling. + * @remark It uses the same calculation style as Windows OS implementation. + * It will be useful for integrate LVGL Windows backend to other + * Windows applications. +*/ +int32_t lv_windows_dpi_to_physical(int32_t logical, int32_t dpi); + +/********************** + * MACROS + **********************/ + +#endif // LV_USE_WINDOWS + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_WINDOWS_DISPLAY_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_input.c b/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_input.c new file mode 100644 index 000000000..9830261cb --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_input.c @@ -0,0 +1,828 @@ +/** + * @file lv_windows_input.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_windows_input.h" +#if LV_USE_WINDOWS + +#include "lv_windows_context.h" +#include "lv_windows_display.h" + +#include + +#include "../../widgets/textarea/lv_textarea.h" +#include "../../widgets/keyboard/lv_keyboard.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void lv_windows_pointer_driver_read_callback( + lv_indev_t * indev, + lv_indev_data_t * data); + +static void lv_windows_release_pointer_device_event_callback(lv_event_t * e); + +static void lv_windows_keypad_driver_read_callback( + lv_indev_t * indev, + lv_indev_data_t * data); + +static void lv_windows_release_keypad_device_event_callback(lv_event_t * e); + +static void lv_windows_encoder_driver_read_callback( + lv_indev_t * indev, + lv_indev_data_t * data); + +static void lv_windows_release_encoder_device_event_callback(lv_event_t * e); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +HWND lv_windows_get_indev_window_handle(lv_indev_t * indev) +{ + return lv_windows_get_display_window_handle(lv_indev_get_display(indev)); +} + +lv_indev_t * lv_windows_acquire_pointer_indev(lv_display_t * display) +{ + HWND window_handle = lv_windows_get_display_window_handle(display); + if(!window_handle) { + return NULL; + } + + lv_windows_window_context_t * context = lv_windows_get_window_context( + window_handle); + if(!context) { + return NULL; + } + + if(!context->pointer.indev) { + context->pointer.state = LV_INDEV_STATE_RELEASED; + context->pointer.point.x = 0; + context->pointer.point.y = 0; + + context->pointer.indev = lv_indev_create(); + if(context->pointer.indev) { + lv_indev_set_type( + context->pointer.indev, + LV_INDEV_TYPE_POINTER); + lv_indev_set_read_cb( + context->pointer.indev, + lv_windows_pointer_driver_read_callback); + lv_indev_set_display( + context->pointer.indev, + context->display_device_object); + lv_indev_add_event_cb( + context->pointer.indev, + lv_windows_release_pointer_device_event_callback, + LV_EVENT_DELETE, + context->pointer.indev); + lv_indev_set_group( + context->pointer.indev, + lv_group_get_default()); + } + } + + return context->pointer.indev; +} + +lv_indev_t * lv_windows_acquire_keypad_indev(lv_display_t * display) +{ + HWND window_handle = lv_windows_get_display_window_handle(display); + if(!window_handle) { + return NULL; + } + + lv_windows_window_context_t * context = lv_windows_get_window_context( + window_handle); + if(!context) { + return NULL; + } + + if(!context->keypad.indev) { + InitializeCriticalSection(&context->keypad.mutex); + _lv_ll_init( + &context->keypad.queue, + sizeof(lv_windows_keypad_queue_item_t)); + context->keypad.utf16_high_surrogate = 0; + context->keypad.utf16_low_surrogate = 0; + + context->keypad.indev = lv_indev_create(); + if(context->keypad.indev) { + lv_indev_set_type( + context->keypad.indev, + LV_INDEV_TYPE_KEYPAD); + lv_indev_set_read_cb( + context->keypad.indev, + lv_windows_keypad_driver_read_callback); + lv_indev_set_display( + context->keypad.indev, + context->display_device_object); + lv_indev_add_event_cb( + context->keypad.indev, + lv_windows_release_keypad_device_event_callback, + LV_EVENT_DELETE, + context->keypad.indev); + lv_indev_set_group( + context->keypad.indev, + lv_group_get_default()); + } + } + + return context->keypad.indev; +} + +lv_indev_t * lv_windows_acquire_encoder_indev(lv_display_t * display) +{ + HWND window_handle = lv_windows_get_display_window_handle(display); + if(!window_handle) { + return NULL; + } + + lv_windows_window_context_t * context = lv_windows_get_window_context( + window_handle); + if(!context) { + return NULL; + } + + if(!context->encoder.indev) { + context->encoder.state = LV_INDEV_STATE_RELEASED; + context->encoder.enc_diff = 0; + + context->encoder.indev = lv_indev_create(); + if(context->encoder.indev) { + lv_indev_set_type( + context->encoder.indev, + LV_INDEV_TYPE_ENCODER); + lv_indev_set_read_cb( + context->encoder.indev, + lv_windows_encoder_driver_read_callback); + lv_indev_set_display( + context->encoder.indev, + context->display_device_object); + lv_indev_add_event_cb( + context->encoder.indev, + lv_windows_release_encoder_device_event_callback, + LV_EVENT_DELETE, + context->encoder.indev); + lv_indev_set_group( + context->encoder.indev, + lv_group_get_default()); + } + } + + return context->encoder.indev; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_windows_pointer_driver_read_callback( + lv_indev_t * indev, + lv_indev_data_t * data) +{ + lv_windows_window_context_t * context = lv_windows_get_window_context( + lv_windows_get_indev_window_handle(indev)); + if(!context) { + return; + } + + data->state = context->pointer.state; + data->point = context->pointer.point; +} + +static void lv_windows_release_pointer_device_event_callback(lv_event_t * e) +{ + lv_indev_t * indev = (lv_indev_t *)lv_event_get_user_data(e); + if(!indev) { + return; + } + + HWND window_handle = lv_windows_get_indev_window_handle(indev); + if(!window_handle) { + return; + } + + lv_windows_window_context_t * context = lv_windows_get_window_context( + window_handle); + if(!context) { + return; + } + + context->pointer.state = LV_INDEV_STATE_RELEASED; + context->pointer.point.x = 0; + context->pointer.point.y = 0; + + context->pointer.indev = NULL; +} + +static BOOL lv_windows_get_touch_input_info( + HTOUCHINPUT touch_input_handle, + UINT input_count, + PTOUCHINPUT inputs, + int item_size) +{ + HMODULE module_handle = GetModuleHandleW(L"user32.dll"); + if(!module_handle) { + return FALSE; + } + + typedef BOOL(WINAPI * function_type)(HTOUCHINPUT, UINT, PTOUCHINPUT, int); + + function_type function = (function_type)( + GetProcAddress(module_handle, "GetTouchInputInfo")); + if(!function) { + return FALSE; + } + + return function(touch_input_handle, input_count, inputs, item_size); +} + +static BOOL lv_windows_close_touch_input_handle( + HTOUCHINPUT touch_input_handle) +{ + HMODULE module_handle = GetModuleHandleW(L"user32.dll"); + if(!module_handle) { + return FALSE; + } + + typedef BOOL(WINAPI * function_type)(HTOUCHINPUT); + + function_type function = (function_type)( + GetProcAddress(module_handle, "CloseTouchInputHandle")); + if(!function) { + return FALSE; + } + + return function(touch_input_handle); +} + +bool lv_windows_pointer_device_window_message_handler( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam, + LRESULT * plResult) +{ + switch(uMsg) { + case WM_MOUSEMOVE: { + lv_windows_window_context_t * context = (lv_windows_window_context_t *)( + lv_windows_get_window_context(hWnd)); + if(context) { + int32_t hor_res = lv_display_get_horizontal_resolution( + context->display_device_object); + int32_t ver_res = lv_display_get_vertical_resolution( + context->display_device_object); + + context->pointer.point.x = lv_windows_zoom_to_logical( + GET_X_LPARAM(lParam), + context->zoom_level); + context->pointer.point.y = lv_windows_zoom_to_logical( + GET_Y_LPARAM(lParam), + context->zoom_level); + if(context->simulator_mode) { + context->pointer.point.x = lv_windows_dpi_to_logical( + context->pointer.point.x, + context->window_dpi); + context->pointer.point.y = lv_windows_dpi_to_logical( + context->pointer.point.y, + context->window_dpi); + } + if(context->pointer.point.x < 0) { + context->pointer.point.x = 0; + } + if(context->pointer.point.x > hor_res - 1) { + context->pointer.point.x = hor_res - 1; + } + if(context->pointer.point.y < 0) { + context->pointer.point.y = 0; + } + if(context->pointer.point.y > ver_res - 1) { + context->pointer.point.y = ver_res - 1; + } + } + + break; + } + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: { + lv_windows_window_context_t * context = (lv_windows_window_context_t *)( + lv_windows_get_window_context(hWnd)); + if(context) { + context->pointer.state = ( + uMsg == WM_LBUTTONDOWN + ? LV_INDEV_STATE_PRESSED + : LV_INDEV_STATE_RELEASED); + } + + break; + } + case WM_TOUCH: { + lv_windows_window_context_t * context = (lv_windows_window_context_t *)( + lv_windows_get_window_context(hWnd)); + if(context) { + UINT input_count = LOWORD(wParam); + HTOUCHINPUT touch_input_handle = (HTOUCHINPUT)(lParam); + + PTOUCHINPUT inputs = malloc(input_count * sizeof(TOUCHINPUT)); + if(inputs) { + if(lv_windows_get_touch_input_info( + touch_input_handle, + input_count, + inputs, + sizeof(TOUCHINPUT))) { + for(UINT i = 0; i < input_count; ++i) { + POINT Point; + Point.x = TOUCH_COORD_TO_PIXEL(inputs[i].x); + Point.y = TOUCH_COORD_TO_PIXEL(inputs[i].y); + if(!ScreenToClient(hWnd, &Point)) { + continue; + } + + context->pointer.point.x = lv_windows_zoom_to_logical( + Point.x, + context->zoom_level); + context->pointer.point.y = lv_windows_zoom_to_logical( + Point.y, + context->zoom_level); + if(context->simulator_mode) { + context->pointer.point.x = lv_windows_dpi_to_logical( + context->pointer.point.x, + context->window_dpi); + context->pointer.point.y = lv_windows_dpi_to_logical( + context->pointer.point.y, + context->window_dpi); + } + + DWORD MousePressedMask = + TOUCHEVENTF_MOVE | TOUCHEVENTF_DOWN; + + context->pointer.state = ( + inputs[i].dwFlags & MousePressedMask + ? LV_INDEV_STATE_PRESSED + : LV_INDEV_STATE_RELEASED); + } + } + + free(inputs); + } + + lv_windows_close_touch_input_handle(touch_input_handle); + } + + break; + } + default: + // Not Handled + return false; + } + + // Handled + *plResult = 0; + return true; +} + +static void lv_windows_keypad_driver_read_callback( + lv_indev_t * indev, + lv_indev_data_t * data) +{ + lv_windows_window_context_t * context = lv_windows_get_window_context( + lv_windows_get_indev_window_handle(indev)); + if(!context) { + return; + } + + EnterCriticalSection(&context->keypad.mutex); + + lv_windows_keypad_queue_item_t * current = (lv_windows_keypad_queue_item_t *)( + _lv_ll_get_head(&context->keypad.queue)); + if(current) { + data->key = current->key; + data->state = current->state; + + _lv_ll_remove(&context->keypad.queue, current); + lv_free(current); + + data->continue_reading = true; + } + + LeaveCriticalSection(&context->keypad.mutex); +} + +static void lv_windows_release_keypad_device_event_callback(lv_event_t * e) +{ + lv_indev_t * indev = (lv_indev_t *)lv_event_get_user_data(e); + if(!indev) { + return; + } + + HWND window_handle = lv_windows_get_indev_window_handle(indev); + if(!window_handle) { + return; + } + + lv_windows_window_context_t * context = lv_windows_get_window_context( + window_handle); + if(!context) { + return; + } + + DeleteCriticalSection(&context->keypad.mutex); + _lv_ll_clear(&context->keypad.queue); + context->keypad.utf16_high_surrogate = 0; + context->keypad.utf16_low_surrogate = 0; + + context->keypad.indev = NULL; +} + +static void lv_windows_push_key_to_keyboard_queue( + lv_windows_window_context_t * context, + uint32_t key, + lv_indev_state_t state) +{ + lv_windows_keypad_queue_item_t * current = (lv_windows_keypad_queue_item_t *)( + _lv_ll_ins_tail(&context->keypad.queue)); + if(current) { + current->key = key; + current->state = state; + } +} + +static HIMC lv_windows_imm_get_context( + HWND window_handle) +{ + HMODULE module_handle = GetModuleHandleW(L"imm32.dll"); + if(!module_handle) { + return FALSE; + } + + typedef HIMC(WINAPI * function_type)(HWND); + + function_type function = (function_type)( + GetProcAddress(module_handle, "ImmGetContext")); + if(!function) { + return FALSE; + } + + return function(window_handle); +} + +static BOOL lv_windows_imm_release_context( + HWND window_handle, + HIMC imm_context_handle) +{ + HMODULE module_handle = GetModuleHandleW(L"imm32.dll"); + if(!module_handle) { + return FALSE; + } + + typedef BOOL(WINAPI * function_type)(HWND, HIMC); + + function_type function = (function_type)( + GetProcAddress(module_handle, "ImmReleaseContext")); + if(!function) { + return FALSE; + } + + return function(window_handle, imm_context_handle); +} + +static HIMC lv_windows_imm_associate_context( + HWND window_handle, + HIMC imm_context_handle) +{ + HMODULE module_handle = GetModuleHandleW(L"imm32.dll"); + if(!module_handle) { + return FALSE; + } + + typedef HIMC(WINAPI * function_type)(HWND, HIMC); + + function_type function = (function_type)( + GetProcAddress(module_handle, "ImmAssociateContext")); + if(!function) { + return FALSE; + } + + return function(window_handle, imm_context_handle); +} + +static BOOL lv_windows_imm_set_composition_window( + HIMC imm_context_handle, + LPCOMPOSITIONFORM composition_form) +{ + HMODULE module_handle = GetModuleHandleW(L"imm32.dll"); + if(!module_handle) { + return FALSE; + } + + typedef BOOL(WINAPI * function_type)(HIMC, LPCOMPOSITIONFORM); + + function_type function = (function_type)( + GetProcAddress(module_handle, "ImmSetCompositionWindow")); + if(!function) { + return FALSE; + } + + return function(imm_context_handle, composition_form); +} + +bool lv_windows_keypad_device_window_message_handler( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam, + LRESULT * plResult) +{ + switch(uMsg) { + case WM_KEYDOWN: + case WM_KEYUP: { + lv_windows_window_context_t * context = (lv_windows_window_context_t *)( + lv_windows_get_window_context(hWnd)); + if(context) { + EnterCriticalSection(&context->keypad.mutex); + + bool skip_translation = false; + uint32_t translated_key = 0; + + switch(wParam) { + case VK_UP: + translated_key = LV_KEY_UP; + break; + case VK_DOWN: + translated_key = LV_KEY_DOWN; + break; + case VK_LEFT: + translated_key = LV_KEY_LEFT; + break; + case VK_RIGHT: + translated_key = LV_KEY_RIGHT; + break; + case VK_ESCAPE: + translated_key = LV_KEY_ESC; + break; + case VK_DELETE: + translated_key = LV_KEY_DEL; + break; + case VK_BACK: + translated_key = LV_KEY_BACKSPACE; + break; + case VK_RETURN: + translated_key = LV_KEY_ENTER; + break; + case VK_TAB: + case VK_NEXT: + translated_key = LV_KEY_NEXT; + break; + case VK_PRIOR: + translated_key = LV_KEY_PREV; + break; + case VK_HOME: + translated_key = LV_KEY_HOME; + break; + case VK_END: + translated_key = LV_KEY_END; + break; + default: + skip_translation = true; + break; + } + + if(!skip_translation) { + lv_windows_push_key_to_keyboard_queue( + context, + translated_key, + ((uMsg == WM_KEYUP) + ? LV_INDEV_STATE_RELEASED + : LV_INDEV_STATE_PRESSED)); + } + + LeaveCriticalSection(&context->keypad.mutex); + } + + break; + } + case WM_CHAR: { + lv_windows_window_context_t * context = (lv_windows_window_context_t *)( + lv_windows_get_window_context(hWnd)); + if(context) { + EnterCriticalSection(&context->keypad.mutex); + + uint16_t raw_code_point = (uint16_t)(wParam); + + if(raw_code_point >= 0x20 && raw_code_point != 0x7F) { + if(IS_HIGH_SURROGATE(raw_code_point)) { + context->keypad.utf16_high_surrogate = raw_code_point; + } + else if(IS_LOW_SURROGATE(raw_code_point)) { + context->keypad.utf16_low_surrogate = raw_code_point; + } + + uint32_t code_point = raw_code_point; + + if(context->keypad.utf16_high_surrogate && + context->keypad.utf16_low_surrogate) { + uint16_t high_surrogate = + context->keypad.utf16_high_surrogate; + uint16_t low_surrogate = + context->keypad.utf16_low_surrogate; + + code_point = (low_surrogate & 0x03FF); + code_point += (((high_surrogate & 0x03FF) + 0x40) << 10); + + context->keypad.utf16_high_surrogate = 0; + context->keypad.utf16_low_surrogate = 0; + } + + uint32_t lvgl_code_point = + _lv_text_unicode_to_encoded(code_point); + + lv_windows_push_key_to_keyboard_queue( + context, + lvgl_code_point, + LV_INDEV_STATE_PRESSED); + lv_windows_push_key_to_keyboard_queue( + context, + lvgl_code_point, + LV_INDEV_STATE_RELEASED); + } + + LeaveCriticalSection(&context->keypad.mutex); + } + + break; + } + case WM_IME_SETCONTEXT: { + if(wParam == TRUE) { + HIMC imm_context_handle = lv_windows_imm_get_context(hWnd); + if(imm_context_handle) { + lv_windows_imm_associate_context( + hWnd, + imm_context_handle); + lv_windows_imm_release_context( + hWnd, + imm_context_handle); + } + } + + *plResult = DefWindowProcW(hWnd, uMsg, wParam, wParam); + break; + } + case WM_IME_STARTCOMPOSITION: { + HIMC imm_context_handle = lv_windows_imm_get_context(hWnd); + if(imm_context_handle) { + lv_obj_t * textarea_object = NULL; + lv_obj_t * focused_object = lv_group_get_focused( + lv_group_get_default()); + if(focused_object) { + const lv_obj_class_t * object_class = lv_obj_get_class( + focused_object); + + if(object_class == &lv_textarea_class) { + textarea_object = focused_object; + } + else if(object_class == &lv_keyboard_class) { + textarea_object = lv_keyboard_get_textarea(focused_object); + } + } + + COMPOSITIONFORM composition_form; + composition_form.dwStyle = CFS_POINT; + composition_form.ptCurrentPos.x = 0; + composition_form.ptCurrentPos.y = 0; + + if(textarea_object) { + lv_textarea_t * textarea = (lv_textarea_t *)(textarea_object); + lv_obj_t * label_object = lv_textarea_get_label(textarea_object); + + composition_form.ptCurrentPos.x = + label_object->coords.x1 + textarea->cursor.area.x1; + composition_form.ptCurrentPos.y = + label_object->coords.y1 + textarea->cursor.area.y1; + } + + lv_windows_imm_set_composition_window( + imm_context_handle, + &composition_form); + lv_windows_imm_release_context( + hWnd, + imm_context_handle); + } + + *plResult = DefWindowProcW(hWnd, uMsg, wParam, wParam); + break; + } + default: + // Not Handled + return false; + } + + // Handled + *plResult = 0; + return true; +} + +static void lv_windows_encoder_driver_read_callback( + lv_indev_t * indev, + lv_indev_data_t * data) +{ + lv_windows_window_context_t * context = lv_windows_get_window_context( + lv_windows_get_indev_window_handle(indev)); + if(!context) { + return; + } + + data->state = context->encoder.state; + data->enc_diff = context->encoder.enc_diff; + context->encoder.enc_diff = 0; +} + +static void lv_windows_release_encoder_device_event_callback(lv_event_t * e) +{ + lv_indev_t * indev = (lv_indev_t *)lv_event_get_user_data(e); + if(!indev) { + return; + } + + HWND window_handle = lv_windows_get_indev_window_handle(indev); + if(!window_handle) { + return; + } + + lv_windows_window_context_t * context = lv_windows_get_window_context( + window_handle); + if(!context) { + return; + } + + context->encoder.state = LV_INDEV_STATE_RELEASED; + context->encoder.enc_diff = 0; + + context->encoder.indev = NULL; +} + +bool lv_windows_encoder_device_window_message_handler( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam, + LRESULT * plResult) +{ + switch(uMsg) { + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: { + lv_windows_window_context_t * context = (lv_windows_window_context_t *)( + lv_windows_get_window_context(hWnd)); + if(context) { + context->encoder.state = ( + uMsg == WM_MBUTTONDOWN + ? LV_INDEV_STATE_PRESSED + : LV_INDEV_STATE_RELEASED); + } + + break; + } + case WM_MOUSEWHEEL: { + lv_windows_window_context_t * context = (lv_windows_window_context_t *)( + lv_windows_get_window_context(hWnd)); + if(context) { + context->encoder.enc_diff = + -(GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA); + } + + break; + } + default: + // Not Handled + return false; + } + + // Handled + *plResult = 0; + return true; +} + +#endif // LV_USE_WINDOWS diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_input.h b/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_input.h new file mode 100644 index 000000000..892014ea3 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/windows/lv_windows_input.h @@ -0,0 +1,83 @@ +/** + * @file lv_windows_input.h + * + */ + +#ifndef LV_WINDOWS_INPUT_H +#define LV_WINDOWS_INPUT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../display/lv_display.h" +#include "../../indev/lv_indev.h" + +#if LV_USE_WINDOWS + +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * @brief Get the window handle from specific LVGL input device object. + * @param indev The specific LVGL input device object. + * @return The window handle from specific LVGL input device object. +*/ +HWND lv_windows_get_indev_window_handle(lv_indev_t * indev); + +/** + * @brief Open a LVGL pointer input device object for the specific LVGL + * display object, or create it if the LVGL pointer input device + * object is not created or removed before. + * @param display The specific LVGL display object. + * @return The LVGL pointer input device object for the specific LVGL + * display object. +*/ +lv_indev_t * lv_windows_acquire_pointer_indev(lv_display_t * display); + +/** + * @brief Open a LVGL keypad input device object for the specific LVGL + * display object, or create it if the LVGL keypad input device + * object is not created or removed before. + * @param display The specific LVGL display object. + * @return The LVGL keypad input device object for the specific LVGL + * display object. +*/ +lv_indev_t * lv_windows_acquire_keypad_indev(lv_display_t * display); + +/** + * @brief Open a LVGL encoder input device object for the specific LVGL + * display object, or create it if the LVGL encoder input device + * object is not created or removed before. + * @param display The specific LVGL display object. + * @return The LVGL encoder input device object for the specific LVGL + * display object. +*/ +lv_indev_t * lv_windows_acquire_encoder_indev(lv_display_t * display); + +/********************** + * MACROS + **********************/ + +#endif // LV_USE_WINDOWS + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_WINDOWS_INPUT_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/x11/lv_x11.h b/lib/libesp32_lvgl/lvgl/src/drivers/x11/lv_x11.h new file mode 100644 index 000000000..a7f626768 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/x11/lv_x11.h @@ -0,0 +1,81 @@ +/** + * @file lv_x11.h + * + */ + +#ifndef LV_X11_H +#define LV_X11_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../display/lv_display.h" +#include "../../indev/lv_indev.h" + +#if LV_USE_X11 + +/********************* + * DEFINES + *********************/ + +/** Header of private display driver user data - for internal use only */ +typedef struct { + struct _XDisplay * display; /**< X11 display object */ + struct _x11_inp_data * inp_data; /**< input user data object */ +} _x11_user_hdr_t; + +/** optional window close callback function type + * @see lv_x11_window_set_close_cb +*/ +typedef void(*lv_x11_close_cb)(void * user_data); + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * create and add keyboard, mouse and scrillwheel objects and connect them to x11 display. + * + * This is a convenience method handling the typical input initialisation of an X11 window: + * - create keyboard (@ref lv_x11_keyboard_create) + * - create mouse (with scrollwheel, @ref lv_x11_mouse_create @ref lv_x11_mousewheel_create) + * + * @param[in] disp the created X11 display object from @ref lv_x11_window_create + * @param[in] mouse_img optional image description for the mouse cursor (NULL for no/invisible mouse cursor) + */ +void lv_x11_inputs_create(lv_display_t * disp, lv_image_dsc_t const * mouse_img); + +/** + * create the X11 display + * + * The minimal initialisation for initializing the X11 display driver with keyboard/mouse support: + * @code + * lv_display_t* disp = lv_x11_window_create("My Window Title", window_width, window_width); + * lv_x11_inputs_create(disp, NULL); + * @endcode + * or with mouse cursor icon: + * @code + * lv_img_dsc_t mouse_symbol = {.....}; + * lv_display_t* disp = lv_x11_window_create("My Window Title", window_width, window_width); + * lv_x11_inputs_create(disp, &mouse_symbol); + * @endcode + * + * @param[in] title title of the created X11 window + * @param[in] hor_res horizontal resolution (=width) of the X11 window + * @param[in] ver_res vertical resolution (=height) of the X11 window + * @return pointer to the display object + */ +lv_display_t * lv_x11_window_create(char const * title, int32_t hor_res, int32_t ver_res); + +#endif /* LV_USE_X11 */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV_X11_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/x11/lv_x11_display.c b/lib/libesp32_lvgl/lvgl/src/drivers/x11/lv_x11_display.c new file mode 100644 index 000000000..7e4de3801 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/x11/lv_x11_display.c @@ -0,0 +1,395 @@ +/** + * @file lv_x11_display.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_x11.h" + +#if LV_USE_X11 + +#include +#include +#include +#include +#include +#include +#include "../../core/lv_obj_pos.h" + +/********************* + * DEFINES + *********************/ +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#define MAX(A, B) ((A) > (B) ? (A) : (B)) + +#if LV_X11_RENDER_MODE_PARTIAL + #define LV_X11_RENDER_MODE LV_DISPLAY_RENDER_MODE_PARTIAL +#elif defined LV_X11_RENDER_MODE_DIRECT + #define LV_X11_RENDER_MODE LV_DISPLAY_RENDER_MODE_DIRECT +#elif defined LV_X11_RENDER_MODE_FULL + #define LV_X11_RENDER_MODE LV_DISPLAY_RENDER_MODE_FULL +#endif + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + /* header (containing X Display + input user data pointer - keep aligned with x11_input module!) */ + _x11_user_hdr_t hdr; + /* X11 related information */ + Window window; /**< X11 window object */ + GC gc; /**< X11 graphics context object */ + Visual * visual; /**< X11 visual */ + int dplanes; /**< X11 display depth */ + XImage * ximage; /**< X11 XImage cache object for updating window content */ + Atom wmDeleteMessage; /**< X11 atom to window object */ + void * xdata; /**< allocated data for XImage */ + /* LVGL related information */ + lv_timer_t * timer; /**< timer object for @ref x11_event_handler */ + lv_color_t * buffer[2]; /**< (double) lv display buffers, depending on @ref LV_X11_RENDER_MODE */ + lv_area_t flush_area; /**< integrated area for a display update */ + /* systemtick by thread related information */ + pthread_t thr_tick; /**< pthread for SysTick simulation */ + bool terminated; /**< flag to germinate SysTick simulation thread */ +} x11_disp_data_t; + +/********************** + * STATIC VARIABLES + **********************/ +#if LV_X11_DIRECT_EXIT + static unsigned int count_windows = 0; +#endif + +/********************** + * MACROS + **********************/ + +/********************** + * STATIC FUNCTIONS + **********************/ + +#if LV_COLOR_DEPTH == 32 +typedef lv_color32_t color_t; +static inline lv_color32_t get_px(color_t p) +{ + return (lv_color32_t)p; +} +#elif LV_COLOR_DEPTH == 24 +typedef lv_color_t color_t; +static inline lv_color32_t get_px(color_t p) +{ + lv_color32_t out = { .red = p.red, .green = p.green, .blue = p.blue }; + return out; +} +#elif LV_COLOR_DEPTH == 16 +typedef lv_color16_t color_t; +static inline lv_color32_t get_px(color_t p) +{ + lv_color32_t out = { .red = p.red << 3, .green = p.green << 2, .blue = p.blue << 3 }; + return out; +} +#elif LV_COLOR_DEPTH == 8 +typedef uint8_t color_t; +static inline lv_color32_t get_px(color_t p) +{ + lv_color32_t out = { .red = p, .green = p, .blue = p }; + return out; +} +#warning ("LV_COLOR_DEPTH=8 delivers black data only - open issue in lvgl?") +#else +#error ("Unsupported LV_COLOR_DEPTH") +#endif + +/** + * Flush the content of the internal buffer the specific area on the display. + * @param[in] disp the created X11 display object from @lv_x11_window_create + * @param[in] area area to be updated + * @param[in] px_map contains the rendered image as raw pixel map and it should be copied to `area` on the display. + * @note @ref lv_display_flush_ready has to be called when it's finished. + */ +static void x11_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map) +{ + x11_disp_data_t * xd = lv_display_get_driver_data(disp); + LV_ASSERT_NULL(xd); + + static const lv_area_t inv_area = { .x1 = 0xFFFF, + .x2 = 0, + .y1 = 0xFFFF, + .y2 = 0 + }; + + /* build display update area until lv_disp_flush_is_last */ + xd->flush_area.x1 = MIN(xd->flush_area.x1, area->x1); + xd->flush_area.x2 = MAX(xd->flush_area.x2, area->x2); + xd->flush_area.y1 = MIN(xd->flush_area.y1, area->y1); + xd->flush_area.y2 = MAX(xd->flush_area.y2, area->y2); + + int32_t hor_res = lv_display_get_horizontal_resolution(disp); + + uint32_t dst_offs; + lv_color32_t * dst_data; + color_t * src_data = (color_t *)px_map + (LV_X11_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL ? 0 : hor_res * + area->y1 + area->x1); + for(int16_t y = area->y1; y <= area->y2; y++) { + dst_offs = area->x1 + y * hor_res; + dst_data = &((lv_color32_t *)(xd->xdata))[dst_offs]; + for(int16_t x = area->x1; x <= area->x2; x++, src_data++, dst_data++) { + *dst_data = get_px(*src_data); + } + src_data += (LV_X11_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL ? 0 : hor_res - (area->x2 - area->x1 + 1)); + } + + if(lv_display_flush_is_last(disp)) { + LV_LOG_TRACE("(%d/%d), %dx%d)", xd->flush_area.x1, xd->flush_area.y1, xd->flush_area.x2 + 1 - xd->flush_area.x1, + xd->flush_area.y2 + 1 - xd->flush_area.y1); + + /* refresh collected display update area only */ + int16_t upd_w = xd->flush_area.x2 - xd->flush_area.x1 + 1; + int16_t upd_h = xd->flush_area.y2 - xd->flush_area.y1 + 1; + XPutImage(xd->hdr.display, xd->window, xd->gc, xd->ximage, xd->flush_area.x1, xd->flush_area.y1, xd->flush_area.x1, + xd->flush_area.y1, upd_w, upd_h); + + /* invalidate collected area */ + xd->flush_area = inv_area; + } + /* Inform the graphics library that you are ready with the flushing */ + lv_display_flush_ready(disp); +} + +/** + * event callbed by lvgl display if resolution has been changed (@ref lv_display_set_resolution has been called) + * @param[in] e event data, containing lv_display_t object + */ +static void x11_resolution_evt_cb(lv_event_t * e) +{ + lv_display_t * disp = lv_event_get_user_data(e); + x11_disp_data_t * xd = lv_display_get_driver_data(disp); + LV_ASSERT_NULL(xd); + + int32_t hor_res = lv_display_get_horizontal_resolution(disp); + int32_t ver_res = lv_display_get_vertical_resolution(disp); + + if(LV_X11_RENDER_MODE != LV_DISPLAY_RENDER_MODE_PARTIAL) { + /* update lvgl full-screen display draw buffers for new display size */ + int sz_buffers = (hor_res * ver_res * (LV_COLOR_DEPTH + 7) / 8); + xd->buffer[0] = lv_realloc(xd->buffer[0], sz_buffers); + xd->buffer[1] = (LV_X11_DOUBLE_BUFFER ? lv_realloc(xd->buffer[1], sz_buffers) : NULL); + lv_display_set_buffers(disp, xd->buffer[0], xd->buffer[1], sz_buffers, LV_X11_RENDER_MODE); + } + + /* re-create cache image with new size */ + XDestroyImage(xd->ximage); + size_t sz_buffers = hor_res * ver_res * sizeof(lv_color32_t); + xd->xdata = malloc(sz_buffers); /* use clib method here, x11 memory not part of device footprint */ + xd->ximage = XCreateImage(xd->hdr.display, xd->visual, xd->dplanes, ZPixmap, 0, xd->xdata, + hor_res, ver_res, lv_color_format_get_bpp(LV_COLOR_FORMAT_ARGB8888), 0); +} + +/** + * event callbed by lvgl display if display has been closed (@ref lv_display_delete has been called) + * @param[in] e event data, containing lv_display_t object + */ +static void x11_disp_delete_evt_cb(lv_event_t * e) +{ + lv_display_t * disp = lv_event_get_user_data(e); + x11_disp_data_t * xd = lv_display_get_driver_data(disp); + + lv_timer_delete(xd->timer); + + lv_display_set_buffers(disp, NULL, NULL, 0, LV_DISPLAY_RENDER_MODE_PARTIAL); + lv_free(xd->buffer[0]); + if(LV_X11_DOUBLE_BUFFER) { + lv_free(xd->buffer[1]); + } + + XDestroyImage(xd->ximage); + XFreeGC(xd->hdr.display, xd->gc); + XUnmapWindow(xd->hdr.display, xd->window); + XDestroyWindow(xd->hdr.display, xd->window); + XFlush(xd->hdr.display); + + lv_free(xd); +#if LV_X11_DIRECT_EXIT + if(0 == --count_windows) { + exit(0); + } +#endif +} + +static void x11_hide_cursor(lv_display_t * disp) +{ + x11_disp_data_t * xd = lv_display_get_driver_data(disp); + LV_ASSERT_NULL(xd); + + XColor black = { .red = 0, .green = 0, .blue = 0 }; + char empty_data[] = { 0 }; + + Pixmap empty_bitmap = XCreateBitmapFromData(xd->hdr.display, xd->window, empty_data, 1, 1); + Cursor inv_cursor = XCreatePixmapCursor(xd->hdr.display, empty_bitmap, empty_bitmap, &black, &black, 0, 0); + XDefineCursor(xd->hdr.display, xd->window, inv_cursor); + XFreeCursor(xd->hdr.display, inv_cursor); + XFreePixmap(xd->hdr.display, empty_bitmap); +} + +/** + * X11 input event handler, predicated to fetch and handle only display related events + * (Window changes) + */ +static int is_disp_event(Display * disp, XEvent * event, XPointer arg) +{ + LV_UNUSED(disp); + LV_UNUSED(arg); + return (event->type == Expose + || (event->type >= DestroyNotify && event->type <= CirculateNotify) /* events from StructureNotifyMask */ + || event->type == ClientMessage); +} +static void x11_event_handler(lv_timer_t * t) +{ + lv_display_t * disp = lv_timer_get_user_data(t); + x11_disp_data_t * xd = lv_display_get_driver_data(disp); + LV_ASSERT_NULL(xd); + + /* handle all outstanding X events */ + XEvent event; + while(XCheckIfEvent(xd->hdr.display, &event, is_disp_event, NULL)) { + LV_LOG_TRACE("Display Event %d", event.type); + switch(event.type) { + case Expose: + if(event.xexpose.count == 0) { + XPutImage(xd->hdr.display, xd->window, xd->gc, xd->ximage, 0, 0, 0, 0, event.xexpose.width, event.xexpose.height); + } + break; + case ConfigureNotify: + if(event.xconfigure.width != lv_display_get_horizontal_resolution(disp) + || event.xconfigure.height != lv_display_get_vertical_resolution(disp)) { + lv_display_set_resolution(disp, event.xconfigure.width, event.xconfigure.height); + } + break; + case ClientMessage: + if(event.xclient.data.l[0] == (long)xd->wmDeleteMessage) { + xd->terminated = true; + void * ret = NULL; + pthread_join(xd->thr_tick, &ret); + lv_display_delete(disp); + return; + } + break; + case MapNotify: + case ReparentNotify: + /*suppress unhandled warning*/ + break; + default: + LV_LOG_WARN("unhandled x11 event: %d", event.type); + } + } +} + +static void * x11_tick_thread(void * data) +{ + x11_disp_data_t * xd = data; + LV_ASSERT_NULL(xd); + + while(!xd->terminated) { + usleep(5000); + lv_tick_inc(5); + } + return NULL; +} + +static void x11_window_create(lv_display_t * disp, char const * title) +{ + x11_disp_data_t * xd = lv_display_get_driver_data(disp); + LV_ASSERT_NULL(xd); + + /* setup display/screen */ + xd->hdr.display = XOpenDisplay(NULL); + int screen = XDefaultScreen(xd->hdr.display); + xd->visual = XDefaultVisual(xd->hdr.display, screen); + + /* create window */ + int32_t hor_res = lv_display_get_horizontal_resolution(disp); + int32_t ver_res = lv_display_get_vertical_resolution(disp); +#if 0 + /* drawing contexts for an window */ + unsigned long col_fg = BlackPixel(xd->hdr.display, screen); + unsigned long col_bg = WhitePixel(xd->hdr.display, screen); + + xd->window = XCreateSimpleWindow(xd->hdr.display, DefaultRootWindow(xd->hdr.display), + 0, 0, hor_res, ver_res, 0, col_fg, col_bg); +#else + xd->window = XCreateWindow(xd->hdr.display, XDefaultRootWindow(xd->hdr.display), + 0, 0, hor_res, ver_res, 0, + XDefaultDepth(xd->hdr.display, screen), InputOutput, + xd->visual, 0, NULL); +#endif + /* window manager properties (yes, use of StdProp is obsolete) */ + XSetStandardProperties(xd->hdr.display, xd->window, title, NULL, None, NULL, 0, NULL); + xd->gc = XCreateGC(xd->hdr.display, xd->window, 0, 0); + + /* allow receiving mouse, keyboard and window change/close events */ + XSelectInput(xd->hdr.display, xd->window, + PointerMotionMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | ExposureMask | + StructureNotifyMask); + xd->wmDeleteMessage = XInternAtom(xd->hdr.display, "WM_DELETE_WINDOW", False); + XSetWMProtocols(xd->hdr.display, xd->window, &xd->wmDeleteMessage, 1); + + x11_hide_cursor(disp); + + /* create cache XImage */ + size_t sz_buffers = hor_res * ver_res * sizeof(lv_color32_t); + xd->dplanes = XDisplayPlanes(xd->hdr.display, screen); + xd->xdata = malloc(sz_buffers); /* use clib method here, x11 memory not part of device footprint */ + xd->ximage = XCreateImage(xd->hdr.display, xd->visual, xd->dplanes, ZPixmap, 0, xd->xdata, + hor_res, ver_res, lv_color_format_get_bpp(LV_COLOR_FORMAT_ARGB8888), 0); + + /* finally bring window on top of the other windows */ + XMapRaised(xd->hdr.display, xd->window); + +#if LV_X11_DIRECT_EXIT + count_windows++; +#endif +} + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_display_t * lv_x11_window_create(char const * title, int32_t hor_res, int32_t ver_res) +{ + x11_disp_data_t * xd = lv_malloc_zeroed(sizeof(x11_disp_data_t)); + LV_ASSERT_MALLOC(xd); + if(NULL == xd) return NULL; + + lv_display_t * disp = lv_display_create(hor_res, ver_res); + if(NULL == disp) { + lv_free(xd); + return NULL; + } + lv_display_set_driver_data(disp, xd); + lv_display_set_flush_cb(disp, x11_flush_cb); + lv_display_add_event_cb(disp, x11_resolution_evt_cb, LV_EVENT_RESOLUTION_CHANGED, disp); + lv_display_add_event_cb(disp, x11_disp_delete_evt_cb, LV_EVENT_DELETE, disp); + + x11_window_create(disp, title); + + int sz_buffers = (hor_res * ver_res * (LV_COLOR_DEPTH + 7) / 8); + if(LV_X11_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL) { + sz_buffers /= 10; + } + xd->buffer[0] = lv_malloc(sz_buffers); + xd->buffer[1] = (LV_X11_DOUBLE_BUFFER ? lv_malloc(sz_buffers) : NULL); + lv_display_set_buffers(disp, xd->buffer[0], xd->buffer[1], sz_buffers, LV_X11_RENDER_MODE); + + xd->timer = lv_timer_create(x11_event_handler, 5, disp); + + /* initialize Tick simulation */ + xd->terminated = false; + pthread_create(&xd->thr_tick, NULL, x11_tick_thread, xd); + + return disp; +} + +#endif /*LV_USE_X11*/ diff --git a/lib/libesp32_lvgl/lvgl/src/drivers/x11/lv_x11_input.c b/lib/libesp32_lvgl/lvgl/src/drivers/x11/lv_x11_input.c new file mode 100644 index 000000000..bf9948204 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/drivers/x11/lv_x11_input.c @@ -0,0 +1,279 @@ +/** + * @file lv_x11_input.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_x11.h" + +#if LV_USE_X11 + +#include +#include +#include +#include "../../stdlib/lv_string.h" +#include "../../widgets/image/lv_image.h" +#include "../../core/lv_obj.h" + +/********************* + * DEFINES + *********************/ +#define MIN(A, B) ((A) < (B) ? (A) : (B)) + +/********************** + * TYPEDEFS + **********************/ + +typedef struct _x11_inp_data { + /* LVGL related information */ + lv_group_t * inp_group; /**< input group for X input elements */ + lv_indev_t * keyboard; /**< keyboard input device object */ + lv_indev_t * mousepointer; /**< mouse input device object */ + lv_indev_t * mousewheel; /**< encoder input device object */ + lv_timer_t * timer; /**< timer object for @ref x11_event_handler */ + /* user input related information */ + char kb_buffer[32]; /**< keyboard buffer for X keyboard inpputs */ + lv_point_t mouse_pos; /**< current reported mouse position */ + bool left_mouse_btn; /**< current state of left mouse button */ + bool right_mouse_btn; /**< current state of right mouse button */ + bool wheel_mouse_btn; /**< current state of wheel (=middle) mouse button */ + int16_t wheel_cnt; /**< mouse wheel increments */ +} x11_inp_data_t; + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * X11 input event handler, predicated to fetch and handle only input related events + * (MotionNotify, ButtonPress/Release, KeyPress/Release) + */ +static int is_inp_event(Display * disp, XEvent * event, XPointer arg) +{ + LV_UNUSED(disp); + LV_UNUSED(arg); + return !(event->type == Expose + || (event->type >= DestroyNotify && event->type <= CirculateNotify) /* events from StructureNotifyMask */ + || event->type == ClientMessage); +} +static void x11_inp_event_handler(lv_timer_t * t) +{ + lv_display_t * disp = lv_timer_get_user_data(t); + _x11_user_hdr_t * disp_hdr = lv_display_get_driver_data(disp); + x11_inp_data_t * xd = disp_hdr->inp_data; + + /* handle all outstanding X events */ + XEvent event; + while(XCheckIfEvent(disp_hdr->display, &event, is_inp_event, NULL)) { + LV_LOG_TRACE("Input Event %d", event.type); + switch(event.type) { + case MotionNotify: + xd->mouse_pos.x = event.xmotion.x; + xd->mouse_pos.y = event.xmotion.y; + break; + case ButtonPress: + switch(event.xbutton.button) { + case Button1: + xd->left_mouse_btn = true; + break; + case Button2: + xd->wheel_mouse_btn = true; + break; + case Button3: + xd->right_mouse_btn = true; + break; + case Button4: /* Scrolled up */ + xd->wheel_cnt--; + break; + case Button5: /* Scrolled down */ + xd->wheel_cnt++; + break; + default: + LV_LOG_WARN("unhandled button press : %d", event.xbutton.button); + } + break; + case ButtonRelease: + switch(event.xbutton.button) { + case Button1: + xd->left_mouse_btn = false; + break; + case Button2: + xd->wheel_mouse_btn = false; + break; + case Button3: + xd->right_mouse_btn = false; + break; + } + break; + case KeyPress: { + size_t len = strlen(xd->kb_buffer); + if(len < (sizeof(xd->kb_buffer) - 2 /* space for 1 char + '\0' */)) { + KeySym key; + int n = XLookupString(&event.xkey, &xd->kb_buffer[len], sizeof(xd->kb_buffer) - (len + 1), &key, NULL); + xd->kb_buffer[len + n] = '\0'; + } + } + break; + case KeyRelease: + break; + default: + LV_LOG_WARN("unhandled x11 event: %d", event.type); + } + } +} + +/** + * event callbed by lvgl display if display has been closed (@ref lv_display_delete has been called) + * @param[in] e event data, containing lv_display_t object + */ +static void x11_inp_delete_evt_cb(lv_event_t * e) +{ + x11_inp_data_t * xd = (x11_inp_data_t *)lv_event_get_user_data(e); + + lv_timer_delete(xd->timer); + lv_free(xd); +} + +/** + * create the local data/timers for the X11 input functionality. + * extracts the user data information from lv_display_t object and initializes the input user object on 1st use. + * @param[in] disp the created X11 display object from @lv_x11_window_create + * @return pointer to the local user data object @x11_inp_data_t + */ +static x11_inp_data_t * x11_input_get_user_data(lv_display_t * disp) +{ + _x11_user_hdr_t * disp_hdr = lv_display_get_driver_data(disp); + LV_ASSERT_NULL(disp_hdr); + x11_inp_data_t ** inp_data = &disp_hdr->inp_data; + + /* create input data set if initial call */ + if(NULL == *inp_data) { + *inp_data = lv_malloc_zeroed(sizeof(x11_inp_data_t)); + LV_ASSERT_MALLOC(*inp_data); + if(NULL != *inp_data) { + /* initialize timer callback for X11 kb/mouse input event reading */ + (*inp_data)->timer = lv_timer_create(x11_inp_event_handler, 1, disp); + lv_display_add_event_cb(disp, x11_inp_delete_evt_cb, LV_EVENT_DELETE, *inp_data); + } + } + return *inp_data; +} + +static void x11_keyboard_read_cb(lv_indev_t * indev, lv_indev_data_t * data) +{ + lv_display_t * disp = lv_indev_get_driver_data(indev); + x11_inp_data_t * xd = x11_input_get_user_data(disp); + + size_t len = strlen(xd->kb_buffer); + if(len > 0) { + data->state = LV_INDEV_STATE_PRESSED; + data->key = xd->kb_buffer[0]; + memmove(xd->kb_buffer, xd->kb_buffer + 1, len); + data->continue_reading = (len > 0); + } + else { + data->state = LV_INDEV_STATE_RELEASED; + } +} + +static void x11_mouse_read_cb(lv_indev_t * indev, lv_indev_data_t * data) +{ + lv_display_t * disp = lv_indev_get_driver_data(indev); + x11_inp_data_t * xd = x11_input_get_user_data(disp); + + int32_t hor_res = lv_display_get_horizontal_resolution(disp); + int32_t ver_res = lv_display_get_vertical_resolution(disp); + + xd->mouse_pos.x = MIN(xd->mouse_pos.x, hor_res - 1); + xd->mouse_pos.y = MIN(xd->mouse_pos.y, ver_res - 1); + + data->point = xd->mouse_pos; + data->state = xd->left_mouse_btn ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; +} + +static void x11_mousewheel_read_cb(lv_indev_t * indev, lv_indev_data_t * data) +{ + lv_display_t * disp = lv_indev_get_driver_data(indev); + x11_inp_data_t * xd = x11_input_get_user_data(disp); + + data->state = xd->wheel_mouse_btn ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; + data->enc_diff = xd->wheel_cnt; + xd->wheel_cnt = 0; +} + +static lv_indev_t * lv_x11_keyboard_create(lv_display_t * disp) +{ + lv_indev_t * indev = lv_indev_create(); + LV_ASSERT_OBJ(indev, MY_CLASS); + if(NULL != indev) { + lv_indev_set_type(indev, LV_INDEV_TYPE_KEYPAD); + lv_indev_set_read_cb(indev, x11_keyboard_read_cb); + lv_indev_set_driver_data(indev, disp); + } + return indev; +} + +static lv_indev_t * lv_x11_mouse_create(lv_display_t * disp, lv_image_dsc_t const * symb) +{ + lv_indev_t * indev = lv_indev_create(); + LV_ASSERT_OBJ(indev, MY_CLASS); + if(NULL != indev) { + lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); + lv_indev_set_read_cb(indev, x11_mouse_read_cb); + lv_indev_set_driver_data(indev, disp); + + /* optional mouse cursor symbol */ + if(NULL != symb) { + lv_obj_t * mouse_cursor = lv_image_create(lv_screen_active()); + lv_image_set_src(mouse_cursor, symb); + lv_indev_set_cursor(indev, mouse_cursor); + } + } + return indev; +} + +static lv_indev_t * lv_x11_mousewheel_create(lv_display_t * disp) +{ + lv_indev_t * indev = lv_indev_create(); + LV_ASSERT_OBJ(indev, MY_CLASS); + if(NULL != indev) { + lv_indev_set_type(indev, LV_INDEV_TYPE_ENCODER); + lv_indev_set_read_cb(indev, x11_mousewheel_read_cb); + lv_indev_set_driver_data(indev, disp); + } + return indev; +} + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_x11_inputs_create(lv_display_t * disp, lv_image_dsc_t const * mouse_img) +{ + x11_inp_data_t * xd = x11_input_get_user_data(disp); + LV_ASSERT_NULL(xd); + + xd->inp_group = lv_group_create(); + lv_group_set_default(xd->inp_group); + + xd->mousepointer = lv_x11_mouse_create(disp, mouse_img); + lv_indev_set_group(xd->mousepointer, xd->inp_group); + + xd->mousewheel = lv_x11_mousewheel_create(disp); + lv_indev_set_group(xd->mousewheel, xd->inp_group); + + xd->keyboard = lv_x11_keyboard_create(disp); + lv_indev_set_group(xd->keyboard, xd->inp_group); +} + +#endif /*LV_USE_X11*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/README.md b/lib/libesp32_lvgl/lvgl/src/extra/README.md deleted file mode 100644 index 80bb49d4f..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Extra components - -This directory contains extra (optional) components to lvgl. -It's a good place for contributions as there are less strict expectations about the completeness and flexibility of the components here. - -In other words, if you have created a complex widget from other widgets, or modified an existing widget with special events, styles or animations, or have a new feature that could work as a plugin to lvgl feel free to the share it here. - -## How to contribute -- Create a [Pull request](https://docs.lvgl.io/8.0/CONTRIBUTING.html#pull-request) with your new content -- Please and follow the [Coding style](https://github.com/lvgl/lvgl/blob/master/docs/CODING_STYLE.md) of LVGL -- Add setter/getter functions in pair -- Update [lv_conf_template.h](https://github.com/lvgl/lvgl/blob/master/lv_conf_template.h) -- Add description in the [docs](https://github.com/lvgl/lvgl/tree/master/docs) -- Add [examples](https://github.com/lvgl/lvgl/tree/master/examples) -- Update the [changelog](https://github.com/lvgl/lvgl/tree/master/docs/CHANGELOG.md) -- Add yourself to the [Contributors](#contributors) section below. - -## Ideas -Here some ideas as inspiration feel free to contribute with ideas too. -- New [Calendar headers](https://github.com/lvgl/lvgl/tree/master/src/extra/widgets/calendar) -- Color picker with RGB and or HSV bars -- Ruler, horizontal or vertical with major and minor ticks and labels -- New [List items types](https://github.com/lvgl/lvgl/tree/master/src/extra/widgets/list) -- [Preloaders](https://www.google.com/search?q=preloader&sxsrf=ALeKk01ddA4YB0WEgLLN1bZNSm8YER7pkg:1623080551559&source=lnms&tbm=isch&sa=X&ved=2ahUKEwiwoN6d7oXxAhVuw4sKHVedBB4Q_AUoAXoECAEQAw&biw=952&bih=940) -- Drop-down list with a container to which content can be added -- 9 patch button: Similar to [lv_imgbtn](https://docs.lvgl.io/8.0/widgets/extra/imgbtn.html) but 9 images for 4 corner, 4 sides and the center - -## Contributors -- lv_animimg: @ZhaoQiang-b45475 -- lv_span: @guoweilkd -- lv_menu: @HX2003 \ No newline at end of file diff --git a/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.h b/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.h deleted file mode 100644 index 5c4f76725..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.h +++ /dev/null @@ -1,194 +0,0 @@ -/** - * @file lv_grid.h - * - */ - -#ifndef LV_GRID_H -#define LV_GRID_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../../core/lv_obj.h" -#if LV_USE_GRID - -/********************* - * DEFINES - *********************/ -/** - * Can be used track size to make the track fill the free space. - * @param x how much space to take proportionally to other FR tracks - * @return a special track size - */ -#define LV_GRID_FR(x) (LV_COORD_MAX - 100 + x) - -#define LV_GRID_CONTENT (LV_COORD_MAX - 101) -LV_EXPORT_CONST_INT(LV_GRID_CONTENT); - -#define LV_GRID_TEMPLATE_LAST (LV_COORD_MAX) -LV_EXPORT_CONST_INT(LV_GRID_TEMPLATE_LAST); - -/********************** - * TYPEDEFS - **********************/ - -/*Can't include lv_obj.h because it includes this header file*/ -struct _lv_obj_t; - -typedef enum { - LV_GRID_ALIGN_START, - LV_GRID_ALIGN_CENTER, - LV_GRID_ALIGN_END, - LV_GRID_ALIGN_STRETCH, - LV_GRID_ALIGN_SPACE_EVENLY, - LV_GRID_ALIGN_SPACE_AROUND, - LV_GRID_ALIGN_SPACE_BETWEEN, -} lv_grid_align_t; - -/********************** - * GLOBAL VARIABLES - **********************/ - -extern uint16_t LV_LAYOUT_GRID; -extern lv_style_prop_t LV_STYLE_GRID_COLUMN_DSC_ARRAY; -extern lv_style_prop_t LV_STYLE_GRID_COLUMN_ALIGN; -extern lv_style_prop_t LV_STYLE_GRID_ROW_DSC_ARRAY; -extern lv_style_prop_t LV_STYLE_GRID_ROW_ALIGN; -extern lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_POS; -extern lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_SPAN; -extern lv_style_prop_t LV_STYLE_GRID_CELL_X_ALIGN; -extern lv_style_prop_t LV_STYLE_GRID_CELL_ROW_POS; -extern lv_style_prop_t LV_STYLE_GRID_CELL_ROW_SPAN; -extern lv_style_prop_t LV_STYLE_GRID_CELL_Y_ALIGN; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -void lv_grid_init(void); - -void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const lv_coord_t col_dsc[], const lv_coord_t row_dsc[]); - -void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid_align_t row_align); - -/** - * Set the cell of an object. The object's parent needs to have grid layout, else nothing will happen - * @param obj pointer to an object - * @param column_align the vertical alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH` - * @param col_pos column ID - * @param col_span number of columns to take (>= 1) - * @param row_align the horizontal alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH` - * @param row_pos row ID - * @param row_span number of rows to take (>= 1) - */ -void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t column_align, uint8_t col_pos, uint8_t col_span, - lv_grid_align_t row_align, uint8_t row_pos, uint8_t row_span); - -/** - * Just a wrapper to `LV_GRID_FR` for bindings. - */ -static inline lv_coord_t lv_grid_fr(uint8_t x) -{ - return LV_GRID_FR(x); -} - -void lv_style_set_grid_row_dsc_array(lv_style_t * style, const lv_coord_t value[]); -void lv_style_set_grid_column_dsc_array(lv_style_t * style, const lv_coord_t value[]); -void lv_style_set_grid_row_align(lv_style_t * style, lv_grid_align_t value); -void lv_style_set_grid_column_align(lv_style_t * style, lv_grid_align_t value); -void lv_style_set_grid_cell_column_pos(lv_style_t * style, lv_coord_t value); -void lv_style_set_grid_cell_column_span(lv_style_t * style, lv_coord_t value); -void lv_style_set_grid_cell_row_pos(lv_style_t * style, lv_coord_t value); -void lv_style_set_grid_cell_row_span(lv_style_t * style, lv_coord_t value); -void lv_style_set_grid_cell_x_align(lv_style_t * style, lv_coord_t value); -void lv_style_set_grid_cell_y_align(lv_style_t * style, lv_coord_t value); - -void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector); -void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector); -void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector); -void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector); -void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); -void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector); - -static inline const lv_coord_t * lv_obj_get_style_grid_row_dsc_array(const lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_ROW_DSC_ARRAY); - return (const lv_coord_t *)v.ptr; -} - -static inline const lv_coord_t * lv_obj_get_style_grid_column_dsc_array(const lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_COLUMN_DSC_ARRAY); - return (const lv_coord_t *)v.ptr; -} - -static inline lv_grid_align_t lv_obj_get_style_grid_row_align(const lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_ROW_ALIGN); - return (lv_grid_align_t)v.num; -} - -static inline lv_grid_align_t lv_obj_get_style_grid_column_align(const lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_COLUMN_ALIGN); - return (lv_grid_align_t)v.num; -} - -static inline lv_coord_t lv_obj_get_style_grid_cell_column_pos(const lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_COLUMN_POS); - return (lv_coord_t)v.num; -} - -static inline lv_coord_t lv_obj_get_style_grid_cell_column_span(const lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_COLUMN_SPAN); - return (lv_coord_t)v.num; -} - -static inline lv_coord_t lv_obj_get_style_grid_cell_row_pos(const lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_ROW_POS); - return (lv_coord_t)v.num; -} - -static inline lv_coord_t lv_obj_get_style_grid_cell_row_span(const lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_ROW_SPAN); - return (lv_coord_t)v.num; -} - -static inline lv_coord_t lv_obj_get_style_grid_cell_x_align(const lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_X_ALIGN); - return (lv_coord_t)v.num; -} - -static inline lv_coord_t lv_obj_get_style_grid_cell_y_align(const lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_Y_ALIGN); - return (lv_coord_t)v.num; -} - -/********************** - * GLOBAL VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ -#endif /*LV_USE_GRID*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_GRID_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/bmp/lv_bmp.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/bmp/lv_bmp.c deleted file mode 100644 index f89a0a8c7..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/bmp/lv_bmp.c +++ /dev/null @@ -1,258 +0,0 @@ -/** - * @file lv_bmp.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../../../lvgl.h" -#if LV_USE_BMP - -#include - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - lv_fs_file_t f; - unsigned int px_offset; - int px_width; - int px_height; - unsigned int bpp; - int row_size_bytes; -} bmp_dsc_t; - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header); -static lv_res_t decoder_open(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc); - - -static lv_res_t decoder_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, - lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf); - -static void decoder_close(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc); - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ -void lv_bmp_init(void) -{ - lv_img_decoder_t * dec = lv_img_decoder_create(); - lv_img_decoder_set_info_cb(dec, decoder_info); - lv_img_decoder_set_open_cb(dec, decoder_open); - lv_img_decoder_set_read_line_cb(dec, decoder_read_line); - lv_img_decoder_set_close_cb(dec, decoder_close); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Get info about a PNG image - * @param src can be file name or pointer to a C array - * @param header store the info here - * @return LV_RES_OK: no error; LV_RES_INV: can't get the info - */ -static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header) -{ - LV_UNUSED(decoder); - - lv_img_src_t src_type = lv_img_src_get_type(src); /*Get the source type*/ - - /*If it's a BMP file...*/ - if(src_type == LV_IMG_SRC_FILE) { - const char * fn = src; - if(strcmp(lv_fs_get_ext(fn), "bmp") == 0) { /*Check the extension*/ - /*Save the data in the header*/ - lv_fs_file_t f; - lv_fs_res_t res = lv_fs_open(&f, src, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) return LV_RES_INV; - uint8_t headers[54]; - - lv_fs_read(&f, headers, 54, NULL); - uint32_t w; - uint32_t h; - memcpy(&w, headers + 18, 4); - memcpy(&h, headers + 22, 4); - header->w = w; - header->h = h; - header->always_zero = 0; - lv_fs_close(&f); -#if LV_COLOR_DEPTH == 32 - uint16_t bpp; - memcpy(&bpp, headers + 28, 2); - header->cf = bpp == 32 ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR; -#else - header->cf = LV_IMG_CF_TRUE_COLOR; -#endif - return LV_RES_OK; - } - } - /* BMP file as data not supported for simplicity. - * Convert them to LVGL compatible C arrays directly. */ - else if(src_type == LV_IMG_SRC_VARIABLE) { - return LV_RES_INV; - } - - return LV_RES_INV; /*If didn't succeeded earlier then it's an error*/ -} - - -/** - * Open a PNG image and return the decided image - * @param src can be file name or pointer to a C array - * @param style style of the image object (unused now but certain formats might use it) - * @return pointer to the decoded image or `LV_IMG_DECODER_OPEN_FAIL` if failed - */ -static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) -{ - LV_UNUSED(decoder); - - /*If it's a PNG file...*/ - if(dsc->src_type == LV_IMG_SRC_FILE) { - const char * fn = dsc->src; - - if(strcmp(lv_fs_get_ext(fn), "bmp") != 0) { - return LV_RES_INV; /*Check the extension*/ - } - - bmp_dsc_t b; - memset(&b, 0x00, sizeof(b)); - - lv_fs_res_t res = lv_fs_open(&b.f, dsc->src, LV_FS_MODE_RD); - if(res == LV_RES_OK) return LV_RES_INV; - - uint8_t header[54]; - lv_fs_read(&b.f, header, 54, NULL); - - if(0x42 != header[0] || 0x4d != header[1]) { - lv_fs_close(&b.f); - return LV_RES_INV; - } - - memcpy(&b.px_offset, header + 10, 4); - memcpy(&b.px_width, header + 18, 4); - memcpy(&b.px_height, header + 22, 4); - memcpy(&b.bpp, header + 28, 2); - b.row_size_bytes = ((b.bpp * b.px_width + 31) / 32) * 4; - - bool color_depth_error = false; - if(LV_COLOR_DEPTH == 32 && (b.bpp != 32 && b.bpp != 24)) { - LV_LOG_WARN("LV_COLOR_DEPTH == 32 but bpp is %d (should be 32 or 24)", b.bpp); - color_depth_error = true; - } - else if(LV_COLOR_DEPTH == 16 && b.bpp != 16) { - LV_LOG_WARN("LV_COLOR_DEPTH == 16 but bpp is %d (should be 16)", b.bpp); - color_depth_error = true; - } - else if(LV_COLOR_DEPTH == 8 && b.bpp != 8) { - LV_LOG_WARN("LV_COLOR_DEPTH == 8 but bpp is %d (should be 8)", b.bpp); - color_depth_error = true; - } - - if(color_depth_error) { - dsc->error_msg = "Color depth mismatch"; - lv_fs_close(&b.f); - return LV_RES_INV; - } - - dsc->user_data = lv_mem_alloc(sizeof(bmp_dsc_t)); - LV_ASSERT_MALLOC(dsc->user_data); - if(dsc->user_data == NULL) return LV_RES_INV; - memcpy(dsc->user_data, &b, sizeof(b)); - - dsc->img_data = NULL; - return LV_RES_OK; - } - /* BMP file as data not supported for simplicity. - * Convert them to LVGL compatible C arrays directly. */ - else if(dsc->src_type == LV_IMG_SRC_VARIABLE) { - return LV_RES_INV; - } - - return LV_RES_INV; /*If not returned earlier then it failed*/ -} - - -static lv_res_t decoder_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, - lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf) -{ - LV_UNUSED(decoder); - - bmp_dsc_t * b = dsc->user_data; - y = (b->px_height - 1) - y; /*BMP images are stored upside down*/ - uint32_t p = b->px_offset + b->row_size_bytes * y; - p += x * (b->bpp / 8); - lv_fs_seek(&b->f, p, LV_FS_SEEK_SET); - lv_fs_read(&b->f, buf, len * (b->bpp / 8), NULL); - -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 1 - for(unsigned int i = 0; i < len * (b->bpp / 8); i += 2) { - buf[i] = buf[i] ^ buf[i + 1]; - buf[i + 1] = buf[i] ^ buf[i + 1]; - buf[i] = buf[i] ^ buf[i + 1]; - } - -#elif LV_COLOR_DEPTH == 32 - if(b->bpp == 32) { - lv_coord_t i; - for(i = 0; i < len; i++) { - uint8_t b0 = buf[i * 4]; - uint8_t b1 = buf[i * 4 + 1]; - uint8_t b2 = buf[i * 4 + 2]; - uint8_t b3 = buf[i * 4 + 3]; - lv_color32_t * c = (lv_color32_t *)&buf[i * 4]; - c->ch.red = b2; - c->ch.green = b1; - c->ch.blue = b0; - c->ch.alpha = b3; - } - } - if(b->bpp == 24) { - lv_coord_t i; - - for(i = len - 1; i >= 0; i--) { - uint8_t * t = &buf[i * 3]; - lv_color32_t * c = (lv_color32_t *)&buf[i * 4]; - c->ch.red = t[2]; - c->ch.green = t[1]; - c->ch.blue = t[0]; - c->ch.alpha = 0xff; - } - } -#endif - - return LV_RES_OK; -} - - -/** - * Free the allocated resources - */ -static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) -{ - LV_UNUSED(decoder); - bmp_dsc_t * b = dsc->user_data; - lv_fs_close(&b->f); - lv_mem_free(dsc->user_data); - -} - -#endif /*LV_USE_BMP*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.c deleted file mode 100644 index 4bf660222..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.c +++ /dev/null @@ -1,687 +0,0 @@ -/** - * @file lv_freetype.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_freetype.h" -#if LV_USE_FREETYPE - -#include "ft2build.h" -#include FT_FREETYPE_H -#include FT_GLYPH_H -#include FT_CACHE_H -#include FT_SIZES_H -#include FT_IMAGE_H -#include FT_OUTLINE_H - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ -typedef struct { - lv_ll_t face_ll; -} lv_faces_control_t; - -typedef struct name_refer_t { - const char * name; /* point to font name string */ - int32_t cnt; /* reference count */ -} name_refer_t; - -typedef struct { - const void * mem; - const char * name; - size_t mem_size; -#if LV_FREETYPE_CACHE_SIZE < 0 - FT_Size size; -#endif - lv_font_t * font; - uint16_t style; - uint16_t height; -} lv_font_fmt_ft_dsc_t; - -/********************** - * STATIC PROTOTYPES - **********************/ -#if LV_FREETYPE_CACHE_SIZE >= 0 -static FT_Error font_face_requester(FTC_FaceID face_id, - FT_Library library_is, FT_Pointer req_data, FT_Face * aface); -static bool lv_ft_font_init_cache(lv_ft_info_t * info); -static void lv_ft_font_destroy_cache(lv_font_t * font); -#else -static FT_Face face_find_in_list(lv_ft_info_t * info); -static void face_add_to_list(FT_Face face); -static void face_remove_from_list(FT_Face face); -static void face_generic_finalizer(void * object); -static bool lv_ft_font_init_nocache(lv_ft_info_t * info); -static void lv_ft_font_destroy_nocache(lv_font_t * font); -#endif - -static const char * name_refer_save(const char * name); -static void name_refer_del(const char * name); -static const char * name_refer_find(const char * name); - -/********************** -* STATIC VARIABLES -**********************/ -static FT_Library library; -static lv_ll_t names_ll; - -#if LV_FREETYPE_CACHE_SIZE >= 0 - static FTC_Manager cache_manager; - static FTC_CMapCache cmap_cache; - static FT_Face current_face = NULL; - - #if LV_FREETYPE_SBIT_CACHE - static FTC_SBitCache sbit_cache; - static FTC_SBit sbit; - #else - static FTC_ImageCache image_cache; - static FT_Glyph image_glyph; - #endif - -#else - static lv_faces_control_t face_control; -#endif - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -bool lv_freetype_init(uint16_t max_faces, uint16_t max_sizes, uint32_t max_bytes) -{ - FT_Error error = FT_Init_FreeType(&library); - if(error) { - LV_LOG_ERROR("init freeType error(%d)", error); - return false; - } - - _lv_ll_init(&names_ll, sizeof(name_refer_t)); - -#if LV_FREETYPE_CACHE_SIZE >= 0 - error = FTC_Manager_New(library, max_faces, max_sizes, - max_bytes, font_face_requester, NULL, &cache_manager); - if(error) { - FT_Done_FreeType(library); - LV_LOG_ERROR("Failed to open cache manager"); - return false; - } - - error = FTC_CMapCache_New(cache_manager, &cmap_cache); - if(error) { - LV_LOG_ERROR("Failed to open Cmap Cache"); - goto Fail; - } - -#if LV_FREETYPE_SBIT_CACHE - error = FTC_SBitCache_New(cache_manager, &sbit_cache); - if(error) { - LV_LOG_ERROR("Failed to open sbit cache"); - goto Fail; - } -#else - error = FTC_ImageCache_New(cache_manager, &image_cache); - if(error) { - LV_LOG_ERROR("Failed to open image cache"); - goto Fail; - } -#endif - - return true; -Fail: - FTC_Manager_Done(cache_manager); - FT_Done_FreeType(library); - return false; -#else - LV_UNUSED(max_faces); - LV_UNUSED(max_sizes); - LV_UNUSED(max_bytes); - _lv_ll_init(&face_control.face_ll, sizeof(FT_Face *)); - return true; -#endif/* LV_FREETYPE_CACHE_SIZE */ -} - -void lv_freetype_destroy(void) -{ -#if LV_FREETYPE_CACHE_SIZE >= 0 - FTC_Manager_Done(cache_manager); -#endif - FT_Done_FreeType(library); -} - -bool lv_ft_font_init(lv_ft_info_t * info) -{ -#if LV_FREETYPE_CACHE_SIZE >= 0 - return lv_ft_font_init_cache(info); -#else - return lv_ft_font_init_nocache(info); -#endif -} - -void lv_ft_font_destroy(lv_font_t * font) -{ -#if LV_FREETYPE_CACHE_SIZE >= 0 - lv_ft_font_destroy_cache(font); -#else - lv_ft_font_destroy_nocache(font); -#endif -} - -/********************** - * STATIC FUNCTIONS - **********************/ -#if LV_FREETYPE_CACHE_SIZE >= 0 - -static FT_Error font_face_requester(FTC_FaceID face_id, - FT_Library library_is, FT_Pointer req_data, FT_Face * aface) -{ - LV_UNUSED(library_is); - LV_UNUSED(req_data); - - lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)face_id; - FT_Error error; - if(dsc->mem) { - error = FT_New_Memory_Face(library, dsc->mem, dsc->mem_size, 0, aface); - } - else { - error = FT_New_Face(library, dsc->name, 0, aface); - } - if(error) { - LV_LOG_ERROR("FT_New_Face error:%d\n", error); - return error; - } - return FT_Err_Ok; -} - -static bool get_bold_glyph(const lv_font_t * font, FT_Face face, - FT_UInt glyph_index, lv_font_glyph_dsc_t * dsc_out) -{ - if(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT)) { - return false; - } - - lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); - if(face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) { - if(dsc->style & FT_FONT_STYLE_BOLD) { - int strength = 1 << 6; - FT_Outline_Embolden(&face->glyph->outline, strength); - } - } - - if(FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL)) { - return false; - } - - dsc_out->adv_w = (face->glyph->metrics.horiAdvance >> 6); - dsc_out->box_h = face->glyph->bitmap.rows; /*Height of the bitmap in [px]*/ - dsc_out->box_w = face->glyph->bitmap.width; /*Width of the bitmap in [px]*/ - dsc_out->ofs_x = face->glyph->bitmap_left; /*X offset of the bitmap in [pf]*/ - dsc_out->ofs_y = face->glyph->bitmap_top - - face->glyph->bitmap.rows; /*Y offset of the bitmap measured from the as line*/ - dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ - - return true; -} - -static bool get_glyph_dsc_cb_cache(const lv_font_t * font, - lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) -{ - LV_UNUSED(unicode_letter_next); - if(unicode_letter < 0x20) { - dsc_out->adv_w = 0; - dsc_out->box_h = 0; - dsc_out->box_w = 0; - dsc_out->ofs_x = 0; - dsc_out->ofs_y = 0; - dsc_out->bpp = 0; - return true; - } - - lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); - - FTC_FaceID face_id = (FTC_FaceID)dsc; - FT_Size face_size; - struct FTC_ScalerRec_ scaler; - scaler.face_id = face_id; - scaler.width = dsc->height; - scaler.height = dsc->height; - scaler.pixel = 1; - if(FTC_Manager_LookupSize(cache_manager, &scaler, &face_size) != 0) { - return false; - } - - FT_Face face = face_size->face; - FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap); - FT_UInt glyph_index = FTC_CMapCache_Lookup(cmap_cache, face_id, charmap_index, unicode_letter); - dsc_out->is_placeholder = glyph_index == 0; - - if(dsc->style & FT_FONT_STYLE_ITALIC) { - FT_Matrix italic_matrix; - italic_matrix.xx = 1 << 16; - italic_matrix.xy = 0x5800; - italic_matrix.yx = 0; - italic_matrix.yy = 1 << 16; - FT_Set_Transform(face, &italic_matrix, NULL); - } - - if(dsc->style & FT_FONT_STYLE_BOLD) { - current_face = face; - if(!get_bold_glyph(font, face, glyph_index, dsc_out)) { - current_face = NULL; - return false; - } - goto end; - } - - FTC_ImageTypeRec desc_type; - desc_type.face_id = face_id; - desc_type.flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL; - desc_type.height = dsc->height; - desc_type.width = dsc->height; - -#if LV_FREETYPE_SBIT_CACHE - FT_Error error = FTC_SBitCache_Lookup(sbit_cache, &desc_type, glyph_index, &sbit, NULL); - if(error) { - LV_LOG_ERROR("SBitCache_Lookup error"); - return false; - } - - dsc_out->adv_w = sbit->xadvance; - dsc_out->box_h = sbit->height; /*Height of the bitmap in [px]*/ - dsc_out->box_w = sbit->width; /*Width of the bitmap in [px]*/ - dsc_out->ofs_x = sbit->left; /*X offset of the bitmap in [pf]*/ - dsc_out->ofs_y = sbit->top - sbit->height; /*Y offset of the bitmap measured from the as line*/ - dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ -#else - FT_Error error = FTC_ImageCache_Lookup(image_cache, &desc_type, glyph_index, &image_glyph, NULL); - if(error) { - LV_LOG_ERROR("ImageCache_Lookup error"); - return false; - } - if(image_glyph->format != FT_GLYPH_FORMAT_BITMAP) { - LV_LOG_ERROR("Glyph_To_Bitmap error"); - return false; - } - - FT_BitmapGlyph glyph_bitmap = (FT_BitmapGlyph)image_glyph; - dsc_out->adv_w = (glyph_bitmap->root.advance.x >> 16); - dsc_out->box_h = glyph_bitmap->bitmap.rows; /*Height of the bitmap in [px]*/ - dsc_out->box_w = glyph_bitmap->bitmap.width; /*Width of the bitmap in [px]*/ - dsc_out->ofs_x = glyph_bitmap->left; /*X offset of the bitmap in [pf]*/ - dsc_out->ofs_y = glyph_bitmap->top - - glyph_bitmap->bitmap.rows; /*Y offset of the bitmap measured from the as line*/ - dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ -#endif - -end: - if((dsc->style & FT_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) { - dsc_out->adv_w = dsc_out->box_w + dsc_out->ofs_x; - } - - return true; -} - -static const uint8_t * get_glyph_bitmap_cb_cache(const lv_font_t * font, uint32_t unicode_letter) -{ - LV_UNUSED(unicode_letter); - - lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); - if(dsc->style & FT_FONT_STYLE_BOLD) { - if(current_face && current_face->glyph->format == FT_GLYPH_FORMAT_BITMAP) { - return (const uint8_t *)(current_face->glyph->bitmap.buffer); - } - return NULL; - } - -#if LV_FREETYPE_SBIT_CACHE - return (const uint8_t *)sbit->buffer; -#else - FT_BitmapGlyph glyph_bitmap = (FT_BitmapGlyph)image_glyph; - return (const uint8_t *)glyph_bitmap->bitmap.buffer; -#endif -} - -static bool lv_ft_font_init_cache(lv_ft_info_t * info) -{ - size_t need_size = sizeof(lv_font_fmt_ft_dsc_t) + sizeof(lv_font_t); - lv_font_fmt_ft_dsc_t * dsc = lv_mem_alloc(need_size); - if(dsc == NULL) return false; - lv_memset_00(dsc, need_size); - - dsc->font = (lv_font_t *)(((char *)dsc) + sizeof(lv_font_fmt_ft_dsc_t)); - dsc->mem = info->mem; - dsc->mem_size = info->mem_size; - dsc->name = name_refer_save(info->name); - dsc->height = info->weight; - dsc->style = info->style; - - /* use to get font info */ - FT_Size face_size; - struct FTC_ScalerRec_ scaler; - scaler.face_id = (FTC_FaceID)dsc; - scaler.width = info->weight; - scaler.height = info->weight; - scaler.pixel = 1; - FT_Error error = FTC_Manager_LookupSize(cache_manager, &scaler, &face_size); - if(error) { - LV_LOG_ERROR("Failed to LookupSize"); - goto Fail; - } - - lv_font_t * font = dsc->font; - font->dsc = dsc; - font->get_glyph_dsc = get_glyph_dsc_cb_cache; - font->get_glyph_bitmap = get_glyph_bitmap_cb_cache; - font->subpx = LV_FONT_SUBPX_NONE; - font->line_height = (face_size->face->size->metrics.height >> 6); - font->base_line = -(face_size->face->size->metrics.descender >> 6); - - FT_Fixed scale = face_size->face->size->metrics.y_scale; - int8_t thickness = FT_MulFix(scale, face_size->face->underline_thickness) >> 6; - font->underline_position = FT_MulFix(scale, face_size->face->underline_position) >> 6; - font->underline_thickness = thickness < 1 ? 1 : thickness; - - /* return to user */ - info->font = font; - - return true; - -Fail: - lv_mem_free(dsc); - return false; -} - -void lv_ft_font_destroy_cache(lv_font_t * font) -{ - if(font == NULL) { - return; - } - - lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); - if(dsc) { - FTC_Manager_RemoveFaceID(cache_manager, (FTC_FaceID)dsc); - name_refer_del(dsc->name); - lv_mem_free(dsc); - } -} -#else/* LV_FREETYPE_CACHE_SIZE */ - -static FT_Face face_find_in_list(lv_ft_info_t * info) -{ - lv_font_fmt_ft_dsc_t * dsc; - FT_Face * pface = _lv_ll_get_head(&face_control.face_ll); - while(pface) { - dsc = (lv_font_fmt_ft_dsc_t *)(*pface)->generic.data; - if(strcmp(dsc->name, info->name) == 0) { - return *pface; - } - pface = _lv_ll_get_next(&face_control.face_ll, pface); - } - - return NULL; -} - -static void face_add_to_list(FT_Face face) -{ - FT_Face * pface; - pface = (FT_Face *)_lv_ll_ins_tail(&face_control.face_ll); - *pface = face; -} - -static void face_remove_from_list(FT_Face face) -{ - FT_Face * pface = _lv_ll_get_head(&face_control.face_ll); - while(pface) { - if(*pface == face) { - _lv_ll_remove(&face_control.face_ll, pface); - lv_mem_free(pface); - break; - } - pface = _lv_ll_get_next(&face_control.face_ll, pface); - } -} - -static void face_generic_finalizer(void * object) -{ - FT_Face face = (FT_Face)object; - face_remove_from_list(face); - LV_LOG_INFO("face finalizer(%p)\n", face); -} - -static bool get_glyph_dsc_cb_nocache(const lv_font_t * font, - lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) -{ - LV_UNUSED(unicode_letter_next); - if(unicode_letter < 0x20) { - dsc_out->adv_w = 0; - dsc_out->box_h = 0; - dsc_out->box_w = 0; - dsc_out->ofs_x = 0; - dsc_out->ofs_y = 0; - dsc_out->bpp = 0; - return true; - } - - FT_Error error; - lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); - FT_Face face = dsc->size->face; - - FT_UInt glyph_index = FT_Get_Char_Index(face, unicode_letter); - - if(face->size != dsc->size) { - FT_Activate_Size(dsc->size); - } - dsc_out->is_placeholder = glyph_index == 0; - - error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); - if(error) { - return false; - } - - if(face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) { - if(dsc->style & FT_FONT_STYLE_BOLD) { - int strength = 1 << 6; - FT_Outline_Embolden(&face->glyph->outline, strength); - } - - if(dsc->style & FT_FONT_STYLE_ITALIC) { - FT_Matrix italic_matrix; - italic_matrix.xx = 1 << 16; - italic_matrix.xy = 0x5800; - italic_matrix.yx = 0; - italic_matrix.yy = 1 << 16; - FT_Outline_Transform(&face->glyph->outline, &italic_matrix); - } - } - - error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); - if(error) { - return false; - } - - dsc_out->adv_w = (face->glyph->metrics.horiAdvance >> 6); - dsc_out->box_h = face->glyph->bitmap.rows; /*Height of the bitmap in [px]*/ - dsc_out->box_w = face->glyph->bitmap.width; /*Width of the bitmap in [px]*/ - dsc_out->ofs_x = face->glyph->bitmap_left; /*X offset of the bitmap in [pf]*/ - dsc_out->ofs_y = face->glyph->bitmap_top - - face->glyph->bitmap.rows; /*Y offset of the bitmap measured from the as line*/ - dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ - - if((dsc->style & FT_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) { - dsc_out->adv_w = dsc_out->box_w + dsc_out->ofs_x; - } - - return true; -} - -static const uint8_t * get_glyph_bitmap_cb_nocache(const lv_font_t * font, uint32_t unicode_letter) -{ - LV_UNUSED(unicode_letter); - lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); - FT_Face face = dsc->size->face; - return (const uint8_t *)(face->glyph->bitmap.buffer); -} - -static bool lv_ft_font_init_nocache(lv_ft_info_t * info) -{ - size_t need_size = sizeof(lv_font_fmt_ft_dsc_t) + sizeof(lv_font_t); - lv_font_fmt_ft_dsc_t * dsc = lv_mem_alloc(need_size); - if(dsc == NULL) return false; - lv_memset_00(dsc, need_size); - - dsc->font = (lv_font_t *)(((char *)dsc) + sizeof(lv_font_fmt_ft_dsc_t)); - dsc->mem = info->mem; - dsc->mem_size = info->mem_size; - dsc->name = name_refer_save(info->name); - dsc->height = info->weight; - dsc->style = info->style; - - FT_Face face = face_find_in_list(info); - if(face == NULL) { - FT_Error error; - if(dsc->mem) { - error = FT_New_Memory_Face(library, dsc->mem, (FT_Long) dsc->mem_size, 0, &face); - } - else { - error = FT_New_Face(library, dsc->name, 0, &face); - } - if(error) { - LV_LOG_WARN("create face error(%d)", error); - goto Fail; - } - - /* link face and face info */ - face->generic.data = dsc; - face->generic.finalizer = face_generic_finalizer; - face_add_to_list(face); - } - else { - FT_Size size; - FT_Error error = FT_New_Size(face, &size); - if(error) { - goto Fail; - } - FT_Activate_Size(size); - FT_Reference_Face(face); - } - - FT_Set_Pixel_Sizes(face, 0, info->weight); - dsc->size = face->size; - - lv_font_t * font = dsc->font; - font->dsc = dsc; - font->get_glyph_dsc = get_glyph_dsc_cb_nocache; - font->get_glyph_bitmap = get_glyph_bitmap_cb_nocache; - font->line_height = (face->size->metrics.height >> 6); - font->base_line = -(face->size->metrics.descender >> 6); - font->subpx = LV_FONT_SUBPX_NONE; - - FT_Fixed scale = face->size->metrics.y_scale; - int8_t thickness = FT_MulFix(scale, face->underline_thickness) >> 6; - font->underline_position = FT_MulFix(scale, face->underline_position) >> 6; - font->underline_thickness = thickness < 1 ? 1 : thickness; - - info->font = font; - return true; - -Fail: - lv_mem_free(dsc); - return false; -} - -static void lv_ft_font_destroy_nocache(lv_font_t * font) -{ - if(font == NULL) { - return; - } - - lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); - if(dsc) { - FT_Face face = dsc->size->face; - FT_Done_Size(dsc->size); - FT_Done_Face(face); - name_refer_del(dsc->name); - lv_mem_free(dsc); - } -} - -#endif/* LV_FREETYPE_CACHE_SIZE */ - -/** - * find name string in names list.name string cnt += 1 if find. - * @param name name string - * @return the string pointer of name. - */ -static const char * name_refer_find(const char * name) -{ - name_refer_t * refer = _lv_ll_get_head(&names_ll); - while(refer) { - if(strcmp(refer->name, name) == 0) { - refer->cnt += 1; - return refer->name; - } - refer = _lv_ll_get_next(&names_ll, refer); - } - return NULL; -} - -/** - * del name string from list. - */ -static void name_refer_del(const char * name) -{ - name_refer_t * refer = _lv_ll_get_head(&names_ll); - while(refer) { - if(strcmp(refer->name, name) == 0) { - refer->cnt -= 1; - if(refer->cnt <= 0) { - _lv_ll_remove(&names_ll, refer); - lv_mem_free((void *)refer->name); - lv_mem_free(refer); - } - return; - } - refer = _lv_ll_get_next(&names_ll, refer); - } - - LV_LOG_WARN("name_in_names_del error(not find:%p).", name); -} - -/** - * save name string to list. - * @param name name string - * @return Saved string pointer - */ -static const char * name_refer_save(const char * name) -{ - const char * pos = name_refer_find(name); - if(pos) { - return pos; - } - - name_refer_t * refer = _lv_ll_ins_tail(&names_ll); - if(refer) { - uint32_t len = strlen(name) + 1; - refer->name = lv_mem_alloc(len); - if(refer->name) { - lv_memcpy((void *)refer->name, name, len); - refer->cnt = 1; - return refer->name; - } - _lv_ll_remove(&names_ll, refer); - lv_mem_free(refer); - } - LV_LOG_WARN("save_name_to_names error(not memory)."); - return ""; -} - -#endif /*LV_USE_FREETYPE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.h deleted file mode 100644 index 247a7fb7f..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @file lv_freetype.h - * - */ -#ifndef LV_FREETYPE_H -#define LV_FREETYPE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../../lvgl.h" -#if LV_USE_FREETYPE - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ -typedef enum { - FT_FONT_STYLE_NORMAL = 0, - FT_FONT_STYLE_ITALIC = 1 << 0, - FT_FONT_STYLE_BOLD = 1 << 1 -} LV_FT_FONT_STYLE; - -typedef struct { - const char * name; /* The name of the font file */ - const void * mem; /* The pointer of the font file */ - size_t mem_size; /* The size of the memory */ - lv_font_t * font; /* point to lvgl font */ - uint16_t weight; /* font size */ - uint16_t style; /* font style */ -} lv_ft_info_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * init freetype library - * @param max_faces Maximum number of opened FT_Face objects managed by this cache instance. Use 0 for defaults. - * @param max_sizes Maximum number of opened FT_Size objects managed by this cache instance. Use 0 for defaults. - * @param max_bytes Maximum number of bytes to use for cached data nodes. Use 0 for defaults. - * Note that this value does not account for managed FT_Face and FT_Size objects. - * @return true on success, otherwise false. - */ -bool lv_freetype_init(uint16_t max_faces, uint16_t max_sizes, uint32_t max_bytes); - -/** - * Destroy freetype library - */ -void lv_freetype_destroy(void); - -/** - * Creates a font with info parameter specified. - * @param info See lv_ft_info_t for details. - * when success, lv_ft_info_t->font point to the font you created. - * @return true on success, otherwise false. - */ -bool lv_ft_font_init(lv_ft_info_t * info); - -/** - * Destroy a font that has been created. - * @param font pointer to font. - */ -void lv_ft_font_destroy(lv_font_t * font); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_FREETYPE*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* LV_FREETYPE_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_littlefs.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_littlefs.c deleted file mode 100644 index 44261c31d..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_littlefs.c +++ /dev/null @@ -1,332 +0,0 @@ -/** - * @file lv_fs_littlefs.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../../../lvgl.h" - -#if LV_USE_FS_LITTLEFS -#include "lfs.h" - -/********************* - * DEFINES - *********************/ - -#if LV_FS_LITTLEFS_LETTER == '\0' - #error "LV_FS_LITTLEFS_LETTER must be an upper case ASCII letter" -#endif - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -static void fs_init(void); - -static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode); -static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p); - -static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br); -static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw); - -static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); -static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); - -static void * fs_dir_open(lv_fs_drv_t * drv, const char * path); -static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn); -static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p); - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void lv_fs_littlefs_init(void) -{ - /*---------------------------------------------------- - * Initialize your storage device and File System - * -------------------------------------------------*/ - fs_init(); - - /*--------------------------------------------------- - * Register the file system interface in LVGL - *--------------------------------------------------*/ - - /*Add a simple drive to open images*/ - static lv_fs_drv_t fs_drv; /*A driver descriptor*/ - lv_fs_drv_init(&fs_drv); - - /*Set up fields...*/ - fs_drv.letter = LV_FS_LITTLEFS_LETTER; - fs_drv.cache_size = LV_FS_LITTLEFS_CACHE_SIZE; - - fs_drv.open_cb = fs_open; - fs_drv.close_cb = fs_close; - fs_drv.read_cb = fs_read; - fs_drv.write_cb = fs_write; - fs_drv.seek_cb = fs_seek; - fs_drv.tell_cb = fs_tell; - - fs_drv.dir_open_cb = fs_dir_open; - fs_drv.dir_close_cb = fs_dir_close; - fs_drv.dir_read_cb = fs_dir_read; - - /*#if LV_USE_USER_DATA*/ - fs_drv.user_data = NULL; - /*#endif*/ - - lv_fs_drv_register(&fs_drv); -} - -/** - * Convenience function to attach registered driver to lfs_t structure by driver-label - * @param label the label assigned to the driver when it was registered - * @param lfs_p the pointer to the lfs_t structure initialized by external code/library - * @return pointer to a driver descriptor or NULL on error - */ -lv_fs_drv_t * lv_fs_littlefs_set_driver(char label, void * lfs_p) -{ - lv_fs_drv_t * drv_p = lv_fs_get_drv(label); - if(drv_p != NULL) drv_p->user_data = (lfs_t *) lfs_p; - return drv_p; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/*Initialize your Storage device and File system.*/ -static void fs_init(void) -{ - /* Initialize the internal flash or SD-card and LittleFS itself. - * Better to do it in your code to keep this library untouched for easy updating */ -} - -/** - * Open a file - * @param drv pointer to a driver where this function belongs - * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) - * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR - * @return pointer to a file descriptor or NULL on error - */ -static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) -{ - lfs_t * lfs_p = drv->user_data; - uint32_t flags = 0; - - flags = mode == LV_FS_MODE_RD ? LFS_O_RDONLY - : mode == LV_FS_MODE_WR ? LFS_O_WRONLY - : mode == (LV_FS_MODE_WR | LV_FS_MODE_RD) ? LFS_O_RDWR : 0; - - lfs_file_t * file_p = lv_mem_alloc(sizeof(lfs_file_t)); - if(file_p == NULL) return NULL; - - int result = lfs_file_open(lfs_p, file_p, path, flags); - - if(result != LFS_ERR_OK) { - lv_mem_free(file_p); - return NULL; - } - - return file_p; -} - -/** - * Close an opened file - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a file_t variable. (opened with fs_open) - * @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum - */ -static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p) -{ - lfs_t * lfs_p = drv->user_data; - - int result = lfs_file_close(lfs_p, file_p); - lv_mem_free(file_p); - /*lv_mem_free( lfs_p );*/ /*allocated and freed by outside-code*/ - - if(result != LFS_ERR_OK) return LV_FS_RES_UNKNOWN; - return LV_FS_RES_OK; -} - -/** - * Read data from an opened file - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a file_t variable. - * @param buf pointer to a memory block where to store the read data - * @param btr number of Bytes To Read - * @param br the real number of read bytes (Byte Read) - * @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum - */ -static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br) -{ - lfs_t * lfs_p = drv->user_data; - - lfs_ssize_t result = lfs_file_read(lfs_p, file_p, buf, btr); - if(result < 0) return LV_FS_RES_UNKNOWN; - - *br = (uint32_t) result; - return LV_FS_RES_OK; -} - -/** - * Write into a file - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a file_t variable - * @param buf pointer to a buffer with the bytes to write - * @param btw Bytes To Write - * @param bw the number of real written bytes (Bytes Written). NULL if unused. - * @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum - */ -static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) -{ -#ifndef LFS_READONLY - lfs_t * lfs_p = drv->user_data; - - lfs_ssize_t result = lfs_file_write(lfs_p, file_p, buf, btw); - if(result < 0 || lfs_file_sync(lfs_p, file_p) < 0) return LV_FS_RES_UNKNOWN; - - *bw = (uint32_t) result; - return LV_FS_RES_OK; -#else - return LV_FS_RES_NOT_IMP; -#endif -} - -/** - * Set the read write pointer. Also expand the file size if necessary. - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a file_t variable. (opened with fs_open ) - * @param pos the new position of read write pointer - * @param whence tells from where to interpret the `pos`. See @lv_fs_whence_t - * @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum - */ -static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence) -{ - lfs_t * lfs_p = drv->user_data; - - int lfs_whence = whence == LV_FS_SEEK_SET ? LFS_SEEK_SET - : whence == LV_FS_SEEK_CUR ? LFS_SEEK_CUR - : whence == LV_FS_SEEK_END ? LFS_SEEK_END : 0; - - lfs_soff_t result = lfs_file_seek(lfs_p, file_p, pos, lfs_whence); - if(result < 0) return LV_FS_RES_UNKNOWN; - - /*pos = result;*/ /*not supported by lv_fs*/ - return LV_FS_RES_OK; -} - -/** - * Give the position of the read write pointer - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a file_t variable. - * @param pos_p pointer to where to store the result - * @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum - */ -static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) -{ - lfs_t * lfs_p = drv->user_data; - - lfs_soff_t result = lfs_file_tell(lfs_p, file_p); - if(result < 0) return LV_FS_RES_UNKNOWN; - - *pos_p = (uint32_t) result; - return LV_FS_RES_OK; -} - -/** - * Initialize a 'lv_fs_dir_t' variable for directory reading - * @param drv pointer to a driver where this function belongs - * @param path path to a directory - * @return pointer to the directory read descriptor or NULL on error - */ -static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) -{ - lfs_t * lfs_p = drv->user_data; - - lfs_dir_t * dir_p = lv_mem_alloc(sizeof(lfs_dir_t)); - if(dir_p == NULL) return NULL; - - int result = lfs_dir_open(lfs_p, dir_p, path); - if(result != LFS_ERR_OK) { - lv_mem_free(dir_p); - return NULL; - } - - return dir_p; -} - -/** - * Read the next filename form a directory. - * The name of the directories will begin with '/' - * @param drv pointer to a driver where this function belongs - * @param rddir_p pointer to an initialized 'lv_fs_dir_t' variable - * @param fn pointer to a buffer to store the filename - * @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum - */ -static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * rddir_p, char * fn) -{ - lfs_t * lfs_p = drv->user_data; - struct lfs_info info; - int result; - - info.name[0] = '\0'; - - do { - result = lfs_dir_read(lfs_p, rddir_p, &info); - if(result > 0) { - if(info.type == LFS_TYPE_DIR) { - fn[0] = '/'; - strcpy(&fn[1], info.name); - } - else strcpy(fn, info.name); - } - else if(result == 0) fn[0] = '\0'; /*dir-scan ended*/ - else return LV_FS_RES_UNKNOWN; - - } while(!strcmp(fn, "/.") || !strcmp(fn, "/..")); - - return LV_FS_RES_OK; -} - -/** - * Close the directory reading - * @param drv pointer to a driver where this function belongs - * @param rddir_p pointer to an initialized 'lv_fs_dir_t' variable - * @return LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum - */ -static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * rddir_p) -{ - lfs_t * lfs_p = drv->user_data; - - int result = lfs_dir_close(lfs_p, rddir_p); - lv_mem_free(rddir_p); - - if(result != LFS_ERR_OK) return LV_FS_RES_UNKNOWN; - return LV_FS_RES_OK; -} - -#else /*LV_USE_FS_LITTLEFS == 0*/ - -#if defined(LV_FS_LITTLEFS_LETTER) && LV_FS_LITTLEFS_LETTER != '\0' - #warning "LV_USE_FS_LITTLEFS is not enabled but LV_FS_LITTLEFS_LETTER is set" -#endif - -#endif /*LV_USE_FS_POSIX*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/lv_gif.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/lv_gif.h deleted file mode 100644 index d8c93dbc0..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/lv_gif.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file lv_gif.h - * - */ - -#ifndef LV_GIF_H -#define LV_GIF_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ - -#include "../../../lvgl.h" -#if LV_USE_GIF - -#include "gifdec.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - lv_img_t img; - gd_GIF * gif; - lv_timer_t * timer; - lv_img_dsc_t imgdsc; - uint32_t last_call; -} lv_gif_t; - -extern const lv_obj_class_t lv_gif_class; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -lv_obj_t * lv_gif_create(lv_obj_t * parent); -void lv_gif_set_src(lv_obj_t * obj, const void * src); -void lv_gif_restart(lv_obj_t * gif); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_GIF*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_GIF_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.c deleted file mode 100644 index 82e18e1a0..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.c +++ /dev/null @@ -1,6469 +0,0 @@ -/* -LodePNG version 20201017 - -Copyright (c) 2005-2020 Lode Vandevenne - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*/ - -/* -The manual and changelog are in the header file "lodepng.h" -Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C. -*/ - -#include "lodepng.h" -#if LV_USE_PNG - -#ifdef LODEPNG_COMPILE_DISK -#include /* LONG_MAX */ -#endif /* LODEPNG_COMPILE_DISK */ - -#ifdef LODEPNG_COMPILE_ALLOCATORS -#include /* allocations */ -#endif /* LODEPNG_COMPILE_ALLOCATORS */ - -#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/ -#pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/ -#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/ -#endif /*_MSC_VER */ - -const char* LODEPNG_VERSION_STRING = "20201017"; - -/* -This source file is built up in the following large parts. The code sections -with the "LODEPNG_COMPILE_" #defines divide this up further in an intermixed way. --Tools for C and common code for PNG and Zlib --C Code for Zlib (huffman, deflate, ...) --C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...) --The C++ wrapper around all of the above -*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* // Tools for C, and common code for PNG and Zlib. // */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*The malloc, realloc and free functions defined here with "lodepng_" in front -of the name, so that you can easily change them to others related to your -platform if needed. Everything else in the code calls these. Pass --DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out -#define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and -define them in your own project's source files without needing to change -lodepng source code. Don't forget to remove "static" if you copypaste them -from here.*/ - -#ifdef LODEPNG_COMPILE_ALLOCATORS -static void* lodepng_malloc(size_t size) { -#ifdef LODEPNG_MAX_ALLOC - if(size > LODEPNG_MAX_ALLOC) return 0; -#endif - return lv_mem_alloc(size); -} - -/* NOTE: when realloc returns NULL, it leaves the original memory untouched */ -static void* lodepng_realloc(void* ptr, size_t new_size) { -#ifdef LODEPNG_MAX_ALLOC - if(new_size > LODEPNG_MAX_ALLOC) return 0; -#endif - return lv_mem_realloc(ptr, new_size); -} - -static void lodepng_free(void* ptr) { - lv_mem_free(ptr); -} -#else /*LODEPNG_COMPILE_ALLOCATORS*/ -/* TODO: support giving additional void* payload to the custom allocators */ -void* lodepng_malloc(size_t size); -void* lodepng_realloc(void* ptr, size_t new_size); -void lodepng_free(void* ptr); -#endif /*LODEPNG_COMPILE_ALLOCATORS*/ - -/* convince the compiler to inline a function, for use when this measurably improves performance */ -/* inline is not available in C90, but use it when supported by the compiler */ -#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined(__cplusplus) && (__cplusplus >= 199711L)) -#define LODEPNG_INLINE inline -#else -#define LODEPNG_INLINE /* not available */ -#endif - -/* restrict is not available in C90, but use it when supported by the compiler */ -#if (defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) ||\ - (defined(_MSC_VER) && (_MSC_VER >= 1400)) || \ - (defined(__WATCOMC__) && (__WATCOMC__ >= 1250) && !defined(__cplusplus)) -#define LODEPNG_RESTRICT __restrict -#else -#define LODEPNG_RESTRICT /* not available */ -#endif - -/* Replacements for C library functions such as memcpy and strlen, to support platforms -where a full C library is not available. The compiler can recognize them and compile -to something as fast. */ - -static void lodepng_memcpy(void* LODEPNG_RESTRICT dst, - const void* LODEPNG_RESTRICT src, size_t size) { - lv_memcpy(dst, src, size); -} - -static void lodepng_memset(void* LODEPNG_RESTRICT dst, - int value, size_t num) { - lv_memset(dst, value, num); -} - -/* does not check memory out of bounds, do not use on untrusted data */ -static size_t lodepng_strlen(const char* a) { - const char* orig = a; - /* avoid warning about unused function in case of disabled COMPILE... macros */ - (void)(&lodepng_strlen); - while(*a) a++; - return (size_t)(a - orig); -} - -#define LODEPNG_MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define LODEPNG_MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define LODEPNG_ABS(x) ((x) < 0 ? -(x) : (x)) - -#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER) -/* Safely check if adding two integers will overflow (no undefined -behavior, compiler removing the code, etc...) and output result. */ -static int lodepng_addofl(size_t a, size_t b, size_t* result) { - *result = a + b; /* Unsigned addition is well defined and safe in C90 */ - return *result < a; -} -#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER)*/ - -#ifdef LODEPNG_COMPILE_DECODER -/* Safely check if multiplying two integers will overflow (no undefined -behavior, compiler removing the code, etc...) and output result. */ -static int lodepng_mulofl(size_t a, size_t b, size_t* result) { - *result = a * b; /* Unsigned multiplication is well defined and safe in C90 */ - return (a != 0 && *result / a != b); -} - -#ifdef LODEPNG_COMPILE_ZLIB -/* Safely check if a + b > c, even if overflow could happen. */ -static int lodepng_gtofl(size_t a, size_t b, size_t c) { - size_t d; - if(lodepng_addofl(a, b, &d)) return 1; - return d > c; -} -#endif /*LODEPNG_COMPILE_ZLIB*/ -#endif /*LODEPNG_COMPILE_DECODER*/ - - -/* -Often in case of an error a value is assigned to a variable and then it breaks -out of a loop (to go to the cleanup phase of a function). This macro does that. -It makes the error handling code shorter and more readable. - -Example: if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83); -*/ -#define CERROR_BREAK(errorvar, code){\ - errorvar = code;\ - break;\ -} - -/*version of CERROR_BREAK that assumes the common case where the error variable is named "error"*/ -#define ERROR_BREAK(code) CERROR_BREAK(error, code) - -/*Set error var to the error code, and return it.*/ -#define CERROR_RETURN_ERROR(errorvar, code){\ - errorvar = code;\ - return code;\ -} - -/*Try the code, if it returns error, also return the error.*/ -#define CERROR_TRY_RETURN(call){\ - unsigned error = call;\ - if(error) return error;\ -} - -/*Set error var to the error code, and return from the void function.*/ -#define CERROR_RETURN(errorvar, code){\ - errorvar = code;\ - return;\ -} - -/* -About uivector, ucvector and string: --All of them wrap dynamic arrays or text strings in a similar way. --LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version. --The string tools are made to avoid problems with compilers that declare things like strncat as deprecated. --They're not used in the interface, only internally in this file as static functions. --As with many other structs in this file, the init and cleanup functions serve as ctor and dtor. -*/ - -#ifdef LODEPNG_COMPILE_ZLIB -#ifdef LODEPNG_COMPILE_ENCODER -/*dynamic vector of unsigned ints*/ -typedef struct uivector { - unsigned* data; - size_t size; /*size in number of unsigned longs*/ - size_t allocsize; /*allocated size in bytes*/ -} uivector; - -static void uivector_cleanup(void* p) { - ((uivector*)p)->size = ((uivector*)p)->allocsize = 0; - lodepng_free(((uivector*)p)->data); - ((uivector*)p)->data = NULL; -} - -/*returns 1 if success, 0 if failure ==> nothing done*/ -static unsigned uivector_resize(uivector* p, size_t size) { - size_t allocsize = size * sizeof(unsigned); - if(allocsize > p->allocsize) { - size_t newsize = allocsize + (p->allocsize >> 1u); - void* data = lodepng_realloc(p->data, newsize); - if(data) { - p->allocsize = newsize; - p->data = (unsigned*)data; - } - else return 0; /*error: not enough memory*/ - } - p->size = size; - return 1; /*success*/ -} - -static void uivector_init(uivector* p) { - p->data = NULL; - p->size = p->allocsize = 0; -} - -/*returns 1 if success, 0 if failure ==> nothing done*/ -static unsigned uivector_push_back(uivector* p, unsigned c) { - if(!uivector_resize(p, p->size + 1)) return 0; - p->data[p->size - 1] = c; - return 1; -} -#endif /*LODEPNG_COMPILE_ENCODER*/ -#endif /*LODEPNG_COMPILE_ZLIB*/ - -/* /////////////////////////////////////////////////////////////////////////// */ - -/*dynamic vector of unsigned chars*/ -typedef struct ucvector { - unsigned char* data; - size_t size; /*used size*/ - size_t allocsize; /*allocated size*/ -} ucvector; - -/*returns 1 if success, 0 if failure ==> nothing done*/ -static unsigned ucvector_resize(ucvector* p, size_t size) { - if(size > p->allocsize) { - size_t newsize = size + (p->allocsize >> 1u); - void* data = lodepng_realloc(p->data, newsize); - if(data) { - p->allocsize = newsize; - p->data = (unsigned char*)data; - } - else return 0; /*error: not enough memory*/ - } - p->size = size; - return 1; /*success*/ -} - -static ucvector ucvector_init(unsigned char* buffer, size_t size) { - ucvector v; - v.data = buffer; - v.allocsize = v.size = size; - return v; -} - -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_PNG -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - -/*free string pointer and set it to NULL*/ -static void string_cleanup(char** out) { - lodepng_free(*out); - *out = NULL; -} - -/*also appends null termination character*/ -static char* alloc_string_sized(const char* in, size_t insize) { - char* out = (char*)lodepng_malloc(insize + 1); - if(out) { - lodepng_memcpy(out, in, insize); - out[insize] = 0; - } - return out; -} - -/* dynamically allocates a new string with a copy of the null terminated input text */ -static char* alloc_string(const char* in) { - return alloc_string_sized(in, lodepng_strlen(in)); -} -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -#endif /*LODEPNG_COMPILE_PNG*/ - -/* ////////////////////////////////////////////////////////////////////////// */ - -#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_PNG) -static unsigned lodepng_read32bitInt(const unsigned char* buffer) { - return (((unsigned)buffer[0] << 24u) | ((unsigned)buffer[1] << 16u) | - ((unsigned)buffer[2] << 8u) | (unsigned)buffer[3]); -} -#endif /*defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_PNG)*/ - -#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER) -/*buffer must have at least 4 allocated bytes available*/ -static void lodepng_set32bitInt(unsigned char* buffer, unsigned value) { - buffer[0] = (unsigned char)((value >> 24) & 0xff); - buffer[1] = (unsigned char)((value >> 16) & 0xff); - buffer[2] = (unsigned char)((value >> 8) & 0xff); - buffer[3] = (unsigned char)((value ) & 0xff); -} -#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / File IO / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_DISK - -/* returns negative value on error. This should be pure C compatible, so no fstat. */ -static long lodepng_filesize(const char* filename) { - lv_fs_file_t f; - lv_fs_res_t res = lv_fs_open(&f, filename, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) return -1; - uint32_t size = 0; - if(lv_fs_seek(&f, 0, LV_FS_SEEK_END) != 0) { - lv_fs_close(&f); - return -1; - } - - lv_fs_tell(&f, &size); - lv_fs_close(&f); - return size; -} - -/* load file into buffer that already has the correct allocated size. Returns error code.*/ -static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename) { - lv_fs_file_t f; - lv_fs_res_t res = lv_fs_open(&f, filename, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) return 78; - - uint32_t br; - res = lv_fs_read(&f, out, size, &br); - if(res != LV_FS_RES_OK) return 78; - if (br != size) return 78; - lv_fs_close(&f); - return 0; -} - -unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) { - long size = lodepng_filesize(filename); - if(size < 0) return 78; - *outsize = (size_t)size; - - *out = (unsigned char*)lodepng_malloc((size_t)size); - if(!(*out) && size > 0) return 83; /*the above malloc failed*/ - - return lodepng_buffer_file(*out, (size_t)size, filename); -} - -/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ -unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename) { - lv_fs_file_t f; - lv_fs_res_t res = lv_fs_open(&f, filename, LV_FS_MODE_WR); - if(res != LV_FS_RES_OK) return 79; - - uint32_t bw; - res = lv_fs_write(&f, buffer, buffersize, &bw); - lv_fs_close(&f); - return 0; -} - -#endif /*LODEPNG_COMPILE_DISK*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* // End of common code and tools. Begin of Zlib related code. // */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_ZLIB -#ifdef LODEPNG_COMPILE_ENCODER - -typedef struct { - ucvector* data; - unsigned char bp; /*ok to overflow, indicates bit pos inside byte*/ -} LodePNGBitWriter; - -static void LodePNGBitWriter_init(LodePNGBitWriter* writer, ucvector* data) { - writer->data = data; - writer->bp = 0; -} - -/*TODO: this ignores potential out of memory errors*/ -#define WRITEBIT(writer, bit){\ - /* append new byte */\ - if(((writer->bp) & 7u) == 0) {\ - if(!ucvector_resize(writer->data, writer->data->size + 1)) return;\ - writer->data->data[writer->data->size - 1] = 0;\ - }\ - (writer->data->data[writer->data->size - 1]) |= (bit << ((writer->bp) & 7u));\ - ++writer->bp;\ -} - -/* LSB of value is written first, and LSB of bytes is used first */ -static void writeBits(LodePNGBitWriter* writer, unsigned value, size_t nbits) { - if(nbits == 1) { /* compiler should statically compile this case if nbits == 1 */ - WRITEBIT(writer, value); - } else { - /* TODO: increase output size only once here rather than in each WRITEBIT */ - size_t i; - for(i = 0; i != nbits; ++i) { - WRITEBIT(writer, (unsigned char)((value >> i) & 1)); - } - } -} - -/* This one is to use for adding huffman symbol, the value bits are written MSB first */ -static void writeBitsReversed(LodePNGBitWriter* writer, unsigned value, size_t nbits) { - size_t i; - for(i = 0; i != nbits; ++i) { - /* TODO: increase output size only once here rather than in each WRITEBIT */ - WRITEBIT(writer, (unsigned char)((value >> (nbits - 1u - i)) & 1u)); - } -} -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#ifdef LODEPNG_COMPILE_DECODER - -typedef struct { - const unsigned char* data; - size_t size; /*size of data in bytes*/ - size_t bitsize; /*size of data in bits, end of valid bp values, should be 8*size*/ - size_t bp; - unsigned buffer; /*buffer for reading bits. NOTE: 'unsigned' must support at least 32 bits*/ -} LodePNGBitReader; - -/* data size argument is in bytes. Returns error if size too large causing overflow */ -static unsigned LodePNGBitReader_init(LodePNGBitReader* reader, const unsigned char* data, size_t size) { - size_t temp; - reader->data = data; - reader->size = size; - /* size in bits, return error if overflow (if size_t is 32 bit this supports up to 500MB) */ - if(lodepng_mulofl(size, 8u, &reader->bitsize)) return 105; - /*ensure incremented bp can be compared to bitsize without overflow even when it would be incremented 32 too much and - trying to ensure 32 more bits*/ - if(lodepng_addofl(reader->bitsize, 64u, &temp)) return 105; - reader->bp = 0; - reader->buffer = 0; - return 0; /*ok*/ -} - -/* -ensureBits functions: -Ensures the reader can at least read nbits bits in one or more readBits calls, -safely even if not enough bits are available. -Returns 1 if there are enough bits available, 0 if not. -*/ - -/*See ensureBits documentation above. This one ensures exactly 1 bit */ -/*static unsigned ensureBits1(LodePNGBitReader* reader) { - if(reader->bp >= reader->bitsize) return 0; - reader->buffer = (unsigned)reader->data[reader->bp >> 3u] >> (reader->bp & 7u); - return 1; -}*/ - -/*See ensureBits documentation above. This one ensures up to 9 bits */ -static unsigned ensureBits9(LodePNGBitReader* reader, size_t nbits) { - size_t start = reader->bp >> 3u; - size_t size = reader->size; - if(start + 1u < size) { - reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u); - reader->buffer >>= (reader->bp & 7u); - return 1; - } else { - reader->buffer = 0; - if(start + 0u < size) reader->buffer |= reader->data[start + 0]; - reader->buffer >>= (reader->bp & 7u); - return reader->bp + nbits <= reader->bitsize; - } -} - -/*See ensureBits documentation above. This one ensures up to 17 bits */ -static unsigned ensureBits17(LodePNGBitReader* reader, size_t nbits) { - size_t start = reader->bp >> 3u; - size_t size = reader->size; - if(start + 2u < size) { - reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) | - ((unsigned)reader->data[start + 2] << 16u); - reader->buffer >>= (reader->bp & 7u); - return 1; - } else { - reader->buffer = 0; - if(start + 0u < size) reader->buffer |= reader->data[start + 0]; - if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u); - reader->buffer >>= (reader->bp & 7u); - return reader->bp + nbits <= reader->bitsize; - } -} - -/*See ensureBits documentation above. This one ensures up to 25 bits */ -static LODEPNG_INLINE unsigned ensureBits25(LodePNGBitReader* reader, size_t nbits) { - size_t start = reader->bp >> 3u; - size_t size = reader->size; - if(start + 3u < size) { - reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) | - ((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u); - reader->buffer >>= (reader->bp & 7u); - return 1; - } else { - reader->buffer = 0; - if(start + 0u < size) reader->buffer |= reader->data[start + 0]; - if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u); - if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u); - reader->buffer >>= (reader->bp & 7u); - return reader->bp + nbits <= reader->bitsize; - } -} - -/*See ensureBits documentation above. This one ensures up to 32 bits */ -static LODEPNG_INLINE unsigned ensureBits32(LodePNGBitReader* reader, size_t nbits) { - size_t start = reader->bp >> 3u; - size_t size = reader->size; - if(start + 4u < size) { - reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) | - ((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u); - reader->buffer >>= (reader->bp & 7u); - reader->buffer |= (((unsigned)reader->data[start + 4] << 24u) << (8u - (reader->bp & 7u))); - return 1; - } else { - reader->buffer = 0; - if(start + 0u < size) reader->buffer |= reader->data[start + 0]; - if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u); - if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u); - if(start + 3u < size) reader->buffer |= ((unsigned)reader->data[start + 3] << 24u); - reader->buffer >>= (reader->bp & 7u); - return reader->bp + nbits <= reader->bitsize; - } -} - -/* Get bits without advancing the bit pointer. Must have enough bits available with ensureBits. Max nbits is 31. */ -static unsigned peekBits(LodePNGBitReader* reader, size_t nbits) { - /* The shift allows nbits to be only up to 31. */ - return reader->buffer & ((1u << nbits) - 1u); -} - -/* Must have enough bits available with ensureBits */ -static void advanceBits(LodePNGBitReader* reader, size_t nbits) { - reader->buffer >>= nbits; - reader->bp += nbits; -} - -/* Must have enough bits available with ensureBits */ -static unsigned readBits(LodePNGBitReader* reader, size_t nbits) { - unsigned result = peekBits(reader, nbits); - advanceBits(reader, nbits); - return result; -} - -#if 0 /*Disable because tests fail due to unused declaration*/ -/* Public for testing only. steps and result must have numsteps values. */ -static unsigned lode_png_test_bitreader(const unsigned char* data, size_t size, - size_t numsteps, const size_t* steps, unsigned* result) { - size_t i; - LodePNGBitReader reader; - unsigned error = LodePNGBitReader_init(&reader, data, size); - if(error) return 0; - for(i = 0; i < numsteps; i++) { - size_t step = steps[i]; - unsigned ok; - if(step > 25) ok = ensureBits32(&reader, step); - else if(step > 17) ok = ensureBits25(&reader, step); - else if(step > 9) ok = ensureBits17(&reader, step); - else ok = ensureBits9(&reader, step); - if(!ok) return 0; - result[i] = readBits(&reader, step); - } - return 1; -} -#endif - -#endif /*LODEPNG_COMPILE_DECODER*/ - -static unsigned reverseBits(unsigned bits, unsigned num) { - /*TODO: implement faster lookup table based version when needed*/ - unsigned i, result = 0; - for(i = 0; i < num; i++) result |= ((bits >> (num - i - 1u)) & 1u) << i; - return result; -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Deflate - Huffman / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#define FIRST_LENGTH_CODE_INDEX 257 -#define LAST_LENGTH_CODE_INDEX 285 -/*256 literals, the end code, some length codes, and 2 unused codes*/ -#define NUM_DEFLATE_CODE_SYMBOLS 288 -/*the distance codes have their own symbols, 30 used, 2 unused*/ -#define NUM_DISTANCE_SYMBOLS 32 -/*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/ -#define NUM_CODE_LENGTH_CODES 19 - -/*the base lengths represented by codes 257-285*/ -static const unsigned LENGTHBASE[29] - = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, - 67, 83, 99, 115, 131, 163, 195, 227, 258}; - -/*the extra bits used by codes 257-285 (added to base length)*/ -static const unsigned LENGTHEXTRA[29] - = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, - 4, 4, 4, 4, 5, 5, 5, 5, 0}; - -/*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/ -static const unsigned DISTANCEBASE[30] - = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, - 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577}; - -/*the extra bits of backwards distances (added to base)*/ -static const unsigned DISTANCEEXTRA[30] - = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, - 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; - -/*the order in which "code length alphabet code lengths" are stored as specified by deflate, out of this the huffman -tree of the dynamic huffman tree lengths is generated*/ -static const unsigned CLCL_ORDER[NUM_CODE_LENGTH_CODES] - = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - -/* ////////////////////////////////////////////////////////////////////////// */ - -/* -Huffman tree struct, containing multiple representations of the tree -*/ -typedef struct HuffmanTree { - unsigned* codes; /*the huffman codes (bit patterns representing the symbols)*/ - unsigned* lengths; /*the lengths of the huffman codes*/ - unsigned maxbitlen; /*maximum number of bits a single code can get*/ - unsigned numcodes; /*number of symbols in the alphabet = number of codes*/ - /* for reading only */ - unsigned char* table_len; /*length of symbol from lookup table, or max length if secondary lookup needed*/ - unsigned short* table_value; /*value of symbol from lookup table, or pointer to secondary table if needed*/ -} HuffmanTree; - -static void HuffmanTree_init(HuffmanTree* tree) { - tree->codes = 0; - tree->lengths = 0; - tree->table_len = 0; - tree->table_value = 0; -} - -static void HuffmanTree_cleanup(HuffmanTree* tree) { - lodepng_free(tree->codes); - lodepng_free(tree->lengths); - lodepng_free(tree->table_len); - lodepng_free(tree->table_value); -} - -/* amount of bits for first huffman table lookup (aka root bits), see HuffmanTree_makeTable and huffmanDecodeSymbol.*/ -/* values 8u and 9u work the fastest */ -#define FIRSTBITS 9u - -/* a symbol value too big to represent any valid symbol, to indicate reading disallowed huffman bits combination, -which is possible in case of only 0 or 1 present symbols. */ -#define INVALIDSYMBOL 65535u - -/* make table for huffman decoding */ -static unsigned HuffmanTree_makeTable(HuffmanTree* tree) { - static const unsigned headsize = 1u << FIRSTBITS; /*size of the first table*/ - static const unsigned mask = (1u << FIRSTBITS) /*headsize*/ - 1u; - size_t i, numpresent, pointer, size; /*total table size*/ - unsigned* maxlens = (unsigned*)lodepng_malloc(headsize * sizeof(unsigned)); - if(!maxlens) return 83; /*alloc fail*/ - - /* compute maxlens: max total bit length of symbols sharing prefix in the first table*/ - lodepng_memset(maxlens, 0, headsize * sizeof(*maxlens)); - for(i = 0; i < tree->numcodes; i++) { - unsigned symbol = tree->codes[i]; - unsigned l = tree->lengths[i]; - unsigned index; - if(l <= FIRSTBITS) continue; /*symbols that fit in first table don't increase secondary table size*/ - /*get the FIRSTBITS MSBs, the MSBs of the symbol are encoded first. See later comment about the reversing*/ - index = reverseBits(symbol >> (l - FIRSTBITS), FIRSTBITS); - maxlens[index] = LODEPNG_MAX(maxlens[index], l); - } - /* compute total table size: size of first table plus all secondary tables for symbols longer than FIRSTBITS */ - size = headsize; - for(i = 0; i < headsize; ++i) { - unsigned l = maxlens[i]; - if(l > FIRSTBITS) size += (1u << (l - FIRSTBITS)); - } - tree->table_len = (unsigned char*)lodepng_malloc(size * sizeof(*tree->table_len)); - tree->table_value = (unsigned short*)lodepng_malloc(size * sizeof(*tree->table_value)); - if(!tree->table_len || !tree->table_value) { - lodepng_free(maxlens); - /* freeing tree->table values is done at a higher scope */ - return 83; /*alloc fail*/ - } - /*initialize with an invalid length to indicate unused entries*/ - for(i = 0; i < size; ++i) tree->table_len[i] = 16; - - /*fill in the first table for long symbols: max prefix size and pointer to secondary tables*/ - pointer = headsize; - for(i = 0; i < headsize; ++i) { - unsigned l = maxlens[i]; - if(l <= FIRSTBITS) continue; - tree->table_len[i] = l; - tree->table_value[i] = pointer; - pointer += (1u << (l - FIRSTBITS)); - } - lodepng_free(maxlens); - - /*fill in the first table for short symbols, or secondary table for long symbols*/ - numpresent = 0; - for(i = 0; i < tree->numcodes; ++i) { - unsigned l = tree->lengths[i]; - unsigned symbol = tree->codes[i]; /*the huffman bit pattern. i itself is the value.*/ - /*reverse bits, because the huffman bits are given in MSB first order but the bit reader reads LSB first*/ - unsigned reverse = reverseBits(symbol, l); - if(l == 0) continue; - numpresent++; - - if(l <= FIRSTBITS) { - /*short symbol, fully in first table, replicated num times if l < FIRSTBITS*/ - unsigned num = 1u << (FIRSTBITS - l); - unsigned j; - for(j = 0; j < num; ++j) { - /*bit reader will read the l bits of symbol first, the remaining FIRSTBITS - l bits go to the MSB's*/ - unsigned index = reverse | (j << l); - if(tree->table_len[index] != 16) return 55; /*invalid tree: long symbol shares prefix with short symbol*/ - tree->table_len[index] = l; - tree->table_value[index] = i; - } - } else { - /*long symbol, shares prefix with other long symbols in first lookup table, needs second lookup*/ - /*the FIRSTBITS MSBs of the symbol are the first table index*/ - unsigned index = reverse & mask; - unsigned maxlen = tree->table_len[index]; - /*log2 of secondary table length, should be >= l - FIRSTBITS*/ - unsigned tablelen = maxlen - FIRSTBITS; - unsigned start = tree->table_value[index]; /*starting index in secondary table*/ - unsigned num = 1u << (tablelen - (l - FIRSTBITS)); /*amount of entries of this symbol in secondary table*/ - unsigned j; - if(maxlen < l) return 55; /*invalid tree: long symbol shares prefix with short symbol*/ - for(j = 0; j < num; ++j) { - unsigned reverse2 = reverse >> FIRSTBITS; /* l - FIRSTBITS bits */ - unsigned index2 = start + (reverse2 | (j << (l - FIRSTBITS))); - tree->table_len[index2] = l; - tree->table_value[index2] = i; - } - } - } - - if(numpresent < 2) { - /* In case of exactly 1 symbol, in theory the huffman symbol needs 0 bits, - but deflate uses 1 bit instead. In case of 0 symbols, no symbols can - appear at all, but such huffman tree could still exist (e.g. if distance - codes are never used). In both cases, not all symbols of the table will be - filled in. Fill them in with an invalid symbol value so returning them from - huffmanDecodeSymbol will cause error. */ - for(i = 0; i < size; ++i) { - if(tree->table_len[i] == 16) { - /* As length, use a value smaller than FIRSTBITS for the head table, - and a value larger than FIRSTBITS for the secondary table, to ensure - valid behavior for advanceBits when reading this symbol. */ - tree->table_len[i] = (i < headsize) ? 1 : (FIRSTBITS + 1); - tree->table_value[i] = INVALIDSYMBOL; - } - } - } else { - /* A good huffman tree has N * 2 - 1 nodes, of which N - 1 are internal nodes. - If that is not the case (due to too long length codes), the table will not - have been fully used, and this is an error (not all bit combinations can be - decoded): an oversubscribed huffman tree, indicated by error 55. */ - for(i = 0; i < size; ++i) { - if(tree->table_len[i] == 16) return 55; - } - } - - return 0; -} - -/* -Second step for the ...makeFromLengths and ...makeFromFrequencies functions. -numcodes, lengths and maxbitlen must already be filled in correctly. return -value is error. -*/ -static unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree) { - unsigned* blcount; - unsigned* nextcode; - unsigned error = 0; - unsigned bits, n; - - tree->codes = (unsigned*)lodepng_malloc(tree->numcodes * sizeof(unsigned)); - blcount = (unsigned*)lodepng_malloc((tree->maxbitlen + 1) * sizeof(unsigned)); - nextcode = (unsigned*)lodepng_malloc((tree->maxbitlen + 1) * sizeof(unsigned)); - if(!tree->codes || !blcount || !nextcode) error = 83; /*alloc fail*/ - - if(!error) { - for(n = 0; n != tree->maxbitlen + 1; n++) blcount[n] = nextcode[n] = 0; - /*step 1: count number of instances of each code length*/ - for(bits = 0; bits != tree->numcodes; ++bits) ++blcount[tree->lengths[bits]]; - /*step 2: generate the nextcode values*/ - for(bits = 1; bits <= tree->maxbitlen; ++bits) { - nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1u; - } - /*step 3: generate all the codes*/ - for(n = 0; n != tree->numcodes; ++n) { - if(tree->lengths[n] != 0) { - tree->codes[n] = nextcode[tree->lengths[n]]++; - /*remove superfluous bits from the code*/ - tree->codes[n] &= ((1u << tree->lengths[n]) - 1u); - } - } - } - - lodepng_free(blcount); - lodepng_free(nextcode); - - if(!error) error = HuffmanTree_makeTable(tree); - return error; -} - -/* -given the code lengths (as stored in the PNG file), generate the tree as defined -by Deflate. maxbitlen is the maximum bits that a code in the tree can have. -return value is error. -*/ -static unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen, - size_t numcodes, unsigned maxbitlen) { - unsigned i; - tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned)); - if(!tree->lengths) return 83; /*alloc fail*/ - for(i = 0; i != numcodes; ++i) tree->lengths[i] = bitlen[i]; - tree->numcodes = (unsigned)numcodes; /*number of symbols*/ - tree->maxbitlen = maxbitlen; - return HuffmanTree_makeFromLengths2(tree); -} - -#ifdef LODEPNG_COMPILE_ENCODER - -/*BPM: Boundary Package Merge, see "A Fast and Space-Economical Algorithm for Length-Limited Coding", -Jyrki Katajainen, Alistair Moffat, Andrew Turpin, 1995.*/ - -/*chain node for boundary package merge*/ -typedef struct BPMNode { - int weight; /*the sum of all weights in this chain*/ - unsigned index; /*index of this leaf node (called "count" in the paper)*/ - struct BPMNode* tail; /*the next nodes in this chain (null if last)*/ - int in_use; -} BPMNode; - -/*lists of chains*/ -typedef struct BPMLists { - /*memory pool*/ - unsigned memsize; - BPMNode* memory; - unsigned numfree; - unsigned nextfree; - BPMNode** freelist; - /*two heads of lookahead chains per list*/ - unsigned listsize; - BPMNode** chains0; - BPMNode** chains1; -} BPMLists; - -/*creates a new chain node with the given parameters, from the memory in the lists */ -static BPMNode* bpmnode_create(BPMLists* lists, int weight, unsigned index, BPMNode* tail) { - unsigned i; - BPMNode* result; - - /*memory full, so garbage collect*/ - if(lists->nextfree >= lists->numfree) { - /*mark only those that are in use*/ - for(i = 0; i != lists->memsize; ++i) lists->memory[i].in_use = 0; - for(i = 0; i != lists->listsize; ++i) { - BPMNode* node; - for(node = lists->chains0[i]; node != 0; node = node->tail) node->in_use = 1; - for(node = lists->chains1[i]; node != 0; node = node->tail) node->in_use = 1; - } - /*collect those that are free*/ - lists->numfree = 0; - for(i = 0; i != lists->memsize; ++i) { - if(!lists->memory[i].in_use) lists->freelist[lists->numfree++] = &lists->memory[i]; - } - lists->nextfree = 0; - } - - result = lists->freelist[lists->nextfree++]; - result->weight = weight; - result->index = index; - result->tail = tail; - return result; -} - -/*sort the leaves with stable mergesort*/ -static void bpmnode_sort(BPMNode* leaves, size_t num) { - BPMNode* mem = (BPMNode*)lodepng_malloc(sizeof(*leaves) * num); - size_t width, counter = 0; - for(width = 1; width < num; width *= 2) { - BPMNode* a = (counter & 1) ? mem : leaves; - BPMNode* b = (counter & 1) ? leaves : mem; - size_t p; - for(p = 0; p < num; p += 2 * width) { - size_t q = (p + width > num) ? num : (p + width); - size_t r = (p + 2 * width > num) ? num : (p + 2 * width); - size_t i = p, j = q, k; - for(k = p; k < r; k++) { - if(i < q && (j >= r || a[i].weight <= a[j].weight)) b[k] = a[i++]; - else b[k] = a[j++]; - } - } - counter++; - } - if(counter & 1) lodepng_memcpy(leaves, mem, sizeof(*leaves) * num); - lodepng_free(mem); -} - -/*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/ -static void boundaryPM(BPMLists* lists, BPMNode* leaves, size_t numpresent, int c, int num) { - unsigned lastindex = lists->chains1[c]->index; - - if(c == 0) { - if(lastindex >= numpresent) return; - lists->chains0[c] = lists->chains1[c]; - lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, 0); - } else { - /*sum of the weights of the head nodes of the previous lookahead chains.*/ - int sum = lists->chains0[c - 1]->weight + lists->chains1[c - 1]->weight; - lists->chains0[c] = lists->chains1[c]; - if(lastindex < numpresent && sum > leaves[lastindex].weight) { - lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, lists->chains1[c]->tail); - return; - } - lists->chains1[c] = bpmnode_create(lists, sum, lastindex, lists->chains1[c - 1]); - /*in the end we are only interested in the chain of the last list, so no - need to recurse if we're at the last one (this gives measurable speedup)*/ - if(num + 1 < (int)(2 * numpresent - 2)) { - boundaryPM(lists, leaves, numpresent, c - 1, num); - boundaryPM(lists, leaves, numpresent, c - 1, num); - } - } -} - -unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, - size_t numcodes, unsigned maxbitlen) { - unsigned error = 0; - unsigned i; - size_t numpresent = 0; /*number of symbols with non-zero frequency*/ - BPMNode* leaves; /*the symbols, only those with > 0 frequency*/ - - if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/ - if((1u << maxbitlen) < (unsigned)numcodes) return 80; /*error: represent all symbols*/ - - leaves = (BPMNode*)lodepng_malloc(numcodes * sizeof(*leaves)); - if(!leaves) return 83; /*alloc fail*/ - - for(i = 0; i != numcodes; ++i) { - if(frequencies[i] > 0) { - leaves[numpresent].weight = (int)frequencies[i]; - leaves[numpresent].index = i; - ++numpresent; - } - } - - lodepng_memset(lengths, 0, numcodes * sizeof(*lengths)); - - /*ensure at least two present symbols. There should be at least one symbol - according to RFC 1951 section 3.2.7. Some decoders incorrectly require two. To - make these work as well ensure there are at least two symbols. The - Package-Merge code below also doesn't work correctly if there's only one - symbol, it'd give it the theoretical 0 bits but in practice zlib wants 1 bit*/ - if(numpresent == 0) { - lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/ - } else if(numpresent == 1) { - lengths[leaves[0].index] = 1; - lengths[leaves[0].index == 0 ? 1 : 0] = 1; - } else { - BPMLists lists; - BPMNode* node; - - bpmnode_sort(leaves, numpresent); - - lists.listsize = maxbitlen; - lists.memsize = 2 * maxbitlen * (maxbitlen + 1); - lists.nextfree = 0; - lists.numfree = lists.memsize; - lists.memory = (BPMNode*)lodepng_malloc(lists.memsize * sizeof(*lists.memory)); - lists.freelist = (BPMNode**)lodepng_malloc(lists.memsize * sizeof(BPMNode*)); - lists.chains0 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); - lists.chains1 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); - if(!lists.memory || !lists.freelist || !lists.chains0 || !lists.chains1) error = 83; /*alloc fail*/ - - if(!error) { - for(i = 0; i != lists.memsize; ++i) lists.freelist[i] = &lists.memory[i]; - - bpmnode_create(&lists, leaves[0].weight, 1, 0); - bpmnode_create(&lists, leaves[1].weight, 2, 0); - - for(i = 0; i != lists.listsize; ++i) { - lists.chains0[i] = &lists.memory[0]; - lists.chains1[i] = &lists.memory[1]; - } - - /*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/ - for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, (int)maxbitlen - 1, (int)i); - - for(node = lists.chains1[maxbitlen - 1]; node; node = node->tail) { - for(i = 0; i != node->index; ++i) ++lengths[leaves[i].index]; - } - } - - lodepng_free(lists.memory); - lodepng_free(lists.freelist); - lodepng_free(lists.chains0); - lodepng_free(lists.chains1); - } - - lodepng_free(leaves); - return error; -} - -/*Create the Huffman tree given the symbol frequencies*/ -static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies, - size_t mincodes, size_t numcodes, unsigned maxbitlen) { - unsigned error = 0; - while(!frequencies[numcodes - 1] && numcodes > mincodes) --numcodes; /*trim zeroes*/ - tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned)); - if(!tree->lengths) return 83; /*alloc fail*/ - tree->maxbitlen = maxbitlen; - tree->numcodes = (unsigned)numcodes; /*number of symbols*/ - - error = lodepng_huffman_code_lengths(tree->lengths, frequencies, numcodes, maxbitlen); - if(!error) error = HuffmanTree_makeFromLengths2(tree); - return error; -} -#endif /*LODEPNG_COMPILE_ENCODER*/ - -/*get the literal and length code tree of a deflated block with fixed tree, as per the deflate specification*/ -static unsigned generateFixedLitLenTree(HuffmanTree* tree) { - unsigned i, error = 0; - unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); - if(!bitlen) return 83; /*alloc fail*/ - - /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/ - for(i = 0; i <= 143; ++i) bitlen[i] = 8; - for(i = 144; i <= 255; ++i) bitlen[i] = 9; - for(i = 256; i <= 279; ++i) bitlen[i] = 7; - for(i = 280; i <= 287; ++i) bitlen[i] = 8; - - error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DEFLATE_CODE_SYMBOLS, 15); - - lodepng_free(bitlen); - return error; -} - -/*get the distance code tree of a deflated block with fixed tree, as specified in the deflate specification*/ -static unsigned generateFixedDistanceTree(HuffmanTree* tree) { - unsigned i, error = 0; - unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); - if(!bitlen) return 83; /*alloc fail*/ - - /*there are 32 distance codes, but 30-31 are unused*/ - for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen[i] = 5; - error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DISTANCE_SYMBOLS, 15); - - lodepng_free(bitlen); - return error; -} - -#ifdef LODEPNG_COMPILE_DECODER - -/* -returns the code. The bit reader must already have been ensured at least 15 bits -*/ -static unsigned huffmanDecodeSymbol(LodePNGBitReader* reader, const HuffmanTree* codetree) { - unsigned short code = peekBits(reader, FIRSTBITS); - unsigned short l = codetree->table_len[code]; - unsigned short value = codetree->table_value[code]; - if(l <= FIRSTBITS) { - advanceBits(reader, l); - return value; - } else { - unsigned index2; - advanceBits(reader, FIRSTBITS); - index2 = value + peekBits(reader, l - FIRSTBITS); - advanceBits(reader, codetree->table_len[index2] - FIRSTBITS); - return codetree->table_value[index2]; - } -} -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_DECODER - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Inflator (Decompressor) / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*get the tree of a deflated block with fixed tree, as specified in the deflate specification -Returns error code.*/ -static unsigned getTreeInflateFixed(HuffmanTree* tree_ll, HuffmanTree* tree_d) { - unsigned error = generateFixedLitLenTree(tree_ll); - if(error) return error; - return generateFixedDistanceTree(tree_d); -} - -/*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/ -static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d, - LodePNGBitReader* reader) { - /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/ - unsigned error = 0; - unsigned n, HLIT, HDIST, HCLEN, i; - - /*see comments in deflateDynamic for explanation of the context and these variables, it is analogous*/ - unsigned* bitlen_ll = 0; /*lit,len code lengths*/ - unsigned* bitlen_d = 0; /*dist code lengths*/ - /*code length code lengths ("clcl"), the bit lengths of the huffman tree used to compress bitlen_ll and bitlen_d*/ - unsigned* bitlen_cl = 0; - HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/ - - if(!ensureBits17(reader, 14)) return 49; /*error: the bit pointer is or will go past the memory*/ - - /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/ - HLIT = readBits(reader, 5) + 257; - /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/ - HDIST = readBits(reader, 5) + 1; - /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/ - HCLEN = readBits(reader, 4) + 4; - - bitlen_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(unsigned)); - if(!bitlen_cl) return 83 /*alloc fail*/; - - HuffmanTree_init(&tree_cl); - - while(!error) { - /*read the code length codes out of 3 * (amount of code length codes) bits*/ - if(lodepng_gtofl(reader->bp, HCLEN * 3, reader->bitsize)) { - ERROR_BREAK(50); /*error: the bit pointer is or will go past the memory*/ - } - for(i = 0; i != HCLEN; ++i) { - ensureBits9(reader, 3); /*out of bounds already checked above */ - bitlen_cl[CLCL_ORDER[i]] = readBits(reader, 3); - } - for(i = HCLEN; i != NUM_CODE_LENGTH_CODES; ++i) { - bitlen_cl[CLCL_ORDER[i]] = 0; - } - - error = HuffmanTree_makeFromLengths(&tree_cl, bitlen_cl, NUM_CODE_LENGTH_CODES, 7); - if(error) break; - - /*now we can use this tree to read the lengths for the tree that this function will return*/ - bitlen_ll = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); - bitlen_d = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); - if(!bitlen_ll || !bitlen_d) ERROR_BREAK(83 /*alloc fail*/); - lodepng_memset(bitlen_ll, 0, NUM_DEFLATE_CODE_SYMBOLS * sizeof(*bitlen_ll)); - lodepng_memset(bitlen_d, 0, NUM_DISTANCE_SYMBOLS * sizeof(*bitlen_d)); - - /*i is the current symbol we're reading in the part that contains the code lengths of lit/len and dist codes*/ - i = 0; - while(i < HLIT + HDIST) { - unsigned code; - ensureBits25(reader, 22); /* up to 15 bits for huffman code, up to 7 extra bits below*/ - code = huffmanDecodeSymbol(reader, &tree_cl); - if(code <= 15) /*a length code*/ { - if(i < HLIT) bitlen_ll[i] = code; - else bitlen_d[i - HLIT] = code; - ++i; - } else if(code == 16) /*repeat previous*/ { - unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/ - unsigned value; /*set value to the previous code*/ - - if(i == 0) ERROR_BREAK(54); /*can't repeat previous if i is 0*/ - - replength += readBits(reader, 2); - - if(i < HLIT + 1) value = bitlen_ll[i - 1]; - else value = bitlen_d[i - HLIT - 1]; - /*repeat this value in the next lengths*/ - for(n = 0; n < replength; ++n) { - if(i >= HLIT + HDIST) ERROR_BREAK(13); /*error: i is larger than the amount of codes*/ - if(i < HLIT) bitlen_ll[i] = value; - else bitlen_d[i - HLIT] = value; - ++i; - } - } else if(code == 17) /*repeat "0" 3-10 times*/ { - unsigned replength = 3; /*read in the bits that indicate repeat length*/ - replength += readBits(reader, 3); - - /*repeat this value in the next lengths*/ - for(n = 0; n < replength; ++n) { - if(i >= HLIT + HDIST) ERROR_BREAK(14); /*error: i is larger than the amount of codes*/ - - if(i < HLIT) bitlen_ll[i] = 0; - else bitlen_d[i - HLIT] = 0; - ++i; - } - } else if(code == 18) /*repeat "0" 11-138 times*/ { - unsigned replength = 11; /*read in the bits that indicate repeat length*/ - replength += readBits(reader, 7); - - /*repeat this value in the next lengths*/ - for(n = 0; n < replength; ++n) { - if(i >= HLIT + HDIST) ERROR_BREAK(15); /*error: i is larger than the amount of codes*/ - - if(i < HLIT) bitlen_ll[i] = 0; - else bitlen_d[i - HLIT] = 0; - ++i; - } - } else /*if(code == INVALIDSYMBOL)*/ { - ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/ - } - /*check if any of the ensureBits above went out of bounds*/ - if(reader->bp > reader->bitsize) { - /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol - (10=no endcode, 11=wrong jump outside of tree)*/ - /* TODO: revise error codes 10,11,50: the above comment is no longer valid */ - ERROR_BREAK(50); /*error, bit pointer jumps past memory*/ - } - } - if(error) break; - - if(bitlen_ll[256] == 0) ERROR_BREAK(64); /*the length of the end code 256 must be larger than 0*/ - - /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/ - error = HuffmanTree_makeFromLengths(tree_ll, bitlen_ll, NUM_DEFLATE_CODE_SYMBOLS, 15); - if(error) break; - error = HuffmanTree_makeFromLengths(tree_d, bitlen_d, NUM_DISTANCE_SYMBOLS, 15); - - break; /*end of error-while*/ - } - - lodepng_free(bitlen_cl); - lodepng_free(bitlen_ll); - lodepng_free(bitlen_d); - HuffmanTree_cleanup(&tree_cl); - - return error; -} - -/*inflate a block with dynamic of fixed Huffman tree. btype must be 1 or 2.*/ -static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader, - unsigned btype, size_t max_output_size) { - unsigned error = 0; - HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/ - HuffmanTree tree_d; /*the huffman tree for distance codes*/ - - HuffmanTree_init(&tree_ll); - HuffmanTree_init(&tree_d); - - if(btype == 1) error = getTreeInflateFixed(&tree_ll, &tree_d); - else /*if(btype == 2)*/ error = getTreeInflateDynamic(&tree_ll, &tree_d, reader); - - while(!error) /*decode all symbols until end reached, breaks at end code*/ { - /*code_ll is literal, length or end code*/ - unsigned code_ll; - ensureBits25(reader, 20); /* up to 15 for the huffman symbol, up to 5 for the length extra bits */ - code_ll = huffmanDecodeSymbol(reader, &tree_ll); - if(code_ll <= 255) /*literal symbol*/ { - if(!ucvector_resize(out, out->size + 1)) ERROR_BREAK(83 /*alloc fail*/); - out->data[out->size - 1] = (unsigned char)code_ll; - } else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/ { - unsigned code_d, distance; - unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/ - size_t start, backward, length; - - /*part 1: get length base*/ - length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX]; - - /*part 2: get extra bits and add the value of that to length*/ - numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX]; - if(numextrabits_l != 0) { - /* bits already ensured above */ - length += readBits(reader, numextrabits_l); - } - - /*part 3: get distance code*/ - ensureBits32(reader, 28); /* up to 15 for the huffman symbol, up to 13 for the extra bits */ - code_d = huffmanDecodeSymbol(reader, &tree_d); - if(code_d > 29) { - if(code_d <= 31) { - ERROR_BREAK(18); /*error: invalid distance code (30-31 are never used)*/ - } else /* if(code_d == INVALIDSYMBOL) */{ - ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/ - } - } - distance = DISTANCEBASE[code_d]; - - /*part 4: get extra bits from distance*/ - numextrabits_d = DISTANCEEXTRA[code_d]; - if(numextrabits_d != 0) { - /* bits already ensured above */ - distance += readBits(reader, numextrabits_d); - } - - /*part 5: fill in all the out[n] values based on the length and dist*/ - start = out->size; - if(distance > start) ERROR_BREAK(52); /*too long backward distance*/ - backward = start - distance; - - if(!ucvector_resize(out, out->size + length)) ERROR_BREAK(83 /*alloc fail*/); - if(distance < length) { - size_t forward; - lodepng_memcpy(out->data + start, out->data + backward, distance); - start += distance; - for(forward = distance; forward < length; ++forward) { - out->data[start++] = out->data[backward++]; - } - } else { - lodepng_memcpy(out->data + start, out->data + backward, length); - } - } else if(code_ll == 256) { - break; /*end code, break the loop*/ - } else /*if(code_ll == INVALIDSYMBOL)*/ { - ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/ - } - /*check if any of the ensureBits above went out of bounds*/ - if(reader->bp > reader->bitsize) { - /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol - (10=no endcode, 11=wrong jump outside of tree)*/ - /* TODO: revise error codes 10,11,50: the above comment is no longer valid */ - ERROR_BREAK(51); /*error, bit pointer jumps past memory*/ - } - if(max_output_size && out->size > max_output_size) { - ERROR_BREAK(109); /*error, larger than max size*/ - } - } - - HuffmanTree_cleanup(&tree_ll); - HuffmanTree_cleanup(&tree_d); - - return error; -} - -static unsigned inflateNoCompression(ucvector* out, LodePNGBitReader* reader, - const LodePNGDecompressSettings* settings) { - size_t bytepos; - size_t size = reader->size; - unsigned LEN, NLEN, error = 0; - - /*go to first boundary of byte*/ - bytepos = (reader->bp + 7u) >> 3u; - - /*read LEN (2 bytes) and NLEN (2 bytes)*/ - if(bytepos + 4 >= size) return 52; /*error, bit pointer will jump past memory*/ - LEN = (unsigned)reader->data[bytepos] + ((unsigned)reader->data[bytepos + 1] << 8u); bytepos += 2; - NLEN = (unsigned)reader->data[bytepos] + ((unsigned)reader->data[bytepos + 1] << 8u); bytepos += 2; - - /*check if 16-bit NLEN is really the one's complement of LEN*/ - if(!settings->ignore_nlen && LEN + NLEN != 65535) { - return 21; /*error: NLEN is not one's complement of LEN*/ - } - - if(!ucvector_resize(out, out->size + LEN)) return 83; /*alloc fail*/ - - /*read the literal data: LEN bytes are now stored in the out buffer*/ - if(bytepos + LEN > size) return 23; /*error: reading outside of in buffer*/ - - lodepng_memcpy(out->data + out->size - LEN, reader->data + bytepos, LEN); - bytepos += LEN; - - reader->bp = bytepos << 3u; - - return error; -} - -static unsigned lodepng_inflatev(ucvector* out, - const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings) { - unsigned BFINAL = 0; - LodePNGBitReader reader; - unsigned error = LodePNGBitReader_init(&reader, in, insize); - - if(error) return error; - - while(!BFINAL) { - unsigned BTYPE; - if(!ensureBits9(&reader, 3)) return 52; /*error, bit pointer will jump past memory*/ - BFINAL = readBits(&reader, 1); - BTYPE = readBits(&reader, 2); - - if(BTYPE == 3) return 20; /*error: invalid BTYPE*/ - else if(BTYPE == 0) error = inflateNoCompression(out, &reader, settings); /*no compression*/ - else error = inflateHuffmanBlock(out, &reader, BTYPE, settings->max_output_size); /*compression, BTYPE 01 or 10*/ - if(!error && settings->max_output_size && out->size > settings->max_output_size) error = 109; - if(error) break; - } - - return error; -} - -unsigned lodepng_inflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings) { - ucvector v = ucvector_init(*out, *outsize); - unsigned error = lodepng_inflatev(&v, in, insize, settings); - *out = v.data; - *outsize = v.size; - return error; -} - -static unsigned inflatev(ucvector* out, const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings) { - if(settings->custom_inflate) { - unsigned error = settings->custom_inflate(&out->data, &out->size, in, insize, settings); - out->allocsize = out->size; - if(error) { - /*the custom inflate is allowed to have its own error codes, however, we translate it to code 110*/ - error = 110; - /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/ - if(settings->max_output_size && out->size > settings->max_output_size) error = 109; - } - return error; - } else { - return lodepng_inflatev(out, in, insize, settings); - } -} - -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_ENCODER - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Deflator (Compressor) / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -static const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258; - -/*search the index in the array, that has the largest value smaller than or equal to the given value, -given array must be sorted (if no value is smaller, it returns the size of the given array)*/ -static size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value) { - /*binary search (only small gain over linear). TODO: use CPU log2 instruction for getting symbols instead*/ - size_t left = 1; - size_t right = array_size - 1; - - while(left <= right) { - size_t mid = (left + right) >> 1; - if(array[mid] >= value) right = mid - 1; - else left = mid + 1; - } - if(left >= array_size || array[left] > value) left--; - return left; -} - -static void addLengthDistance(uivector* values, size_t length, size_t distance) { - /*values in encoded vector are those used by deflate: - 0-255: literal bytes - 256: end - 257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits) - 286-287: invalid*/ - - unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length); - unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]); - unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance); - unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]); - - size_t pos = values->size; - /*TODO: return error when this fails (out of memory)*/ - unsigned ok = uivector_resize(values, values->size + 4); - if(ok) { - values->data[pos + 0] = length_code + FIRST_LENGTH_CODE_INDEX; - values->data[pos + 1] = extra_length; - values->data[pos + 2] = dist_code; - values->data[pos + 3] = extra_distance; - } -} - -/*3 bytes of data get encoded into two bytes. The hash cannot use more than 3 -bytes as input because 3 is the minimum match length for deflate*/ -static const unsigned HASH_NUM_VALUES = 65536; -static const unsigned HASH_BIT_MASK = 65535; /*HASH_NUM_VALUES - 1, but C90 does not like that as initializer*/ - -typedef struct Hash { - int* head; /*hash value to head circular pos - can be outdated if went around window*/ - /*circular pos to prev circular pos*/ - unsigned short* chain; - int* val; /*circular pos to hash value*/ - - /*TODO: do this not only for zeros but for any repeated byte. However for PNG - it's always going to be the zeros that dominate, so not important for PNG*/ - int* headz; /*similar to head, but for chainz*/ - unsigned short* chainz; /*those with same amount of zeros*/ - unsigned short* zeros; /*length of zeros streak, used as a second hash chain*/ -} Hash; - -static unsigned hash_init(Hash* hash, unsigned windowsize) { - unsigned i; - hash->head = (int*)lodepng_malloc(sizeof(int) * HASH_NUM_VALUES); - hash->val = (int*)lodepng_malloc(sizeof(int) * windowsize); - hash->chain = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); - - hash->zeros = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); - hash->headz = (int*)lodepng_malloc(sizeof(int) * (MAX_SUPPORTED_DEFLATE_LENGTH + 1)); - hash->chainz = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); - - if(!hash->head || !hash->chain || !hash->val || !hash->headz|| !hash->chainz || !hash->zeros) { - return 83; /*alloc fail*/ - } - - /*initialize hash table*/ - for(i = 0; i != HASH_NUM_VALUES; ++i) hash->head[i] = -1; - for(i = 0; i != windowsize; ++i) hash->val[i] = -1; - for(i = 0; i != windowsize; ++i) hash->chain[i] = i; /*same value as index indicates uninitialized*/ - - for(i = 0; i <= MAX_SUPPORTED_DEFLATE_LENGTH; ++i) hash->headz[i] = -1; - for(i = 0; i != windowsize; ++i) hash->chainz[i] = i; /*same value as index indicates uninitialized*/ - - return 0; -} - -static void hash_cleanup(Hash* hash) { - lodepng_free(hash->head); - lodepng_free(hash->val); - lodepng_free(hash->chain); - - lodepng_free(hash->zeros); - lodepng_free(hash->headz); - lodepng_free(hash->chainz); -} - - - -static unsigned getHash(const unsigned char* data, size_t size, size_t pos) { - unsigned result = 0; - if(pos + 2 < size) { - /*A simple shift and xor hash is used. Since the data of PNGs is dominated - by zeroes due to the filters, a better hash does not have a significant - effect on speed in traversing the chain, and causes more time spend on - calculating the hash.*/ - result ^= ((unsigned)data[pos + 0] << 0u); - result ^= ((unsigned)data[pos + 1] << 4u); - result ^= ((unsigned)data[pos + 2] << 8u); - } else { - size_t amount, i; - if(pos >= size) return 0; - amount = size - pos; - for(i = 0; i != amount; ++i) result ^= ((unsigned)data[pos + i] << (i * 8u)); - } - return result & HASH_BIT_MASK; -} - -static unsigned countZeros(const unsigned char* data, size_t size, size_t pos) { - const unsigned char* start = data + pos; - const unsigned char* end = start + MAX_SUPPORTED_DEFLATE_LENGTH; - if(end > data + size) end = data + size; - data = start; - while(data != end && *data == 0) ++data; - /*subtracting two addresses returned as 32-bit number (max value is MAX_SUPPORTED_DEFLATE_LENGTH)*/ - return (unsigned)(data - start); -} - -/*wpos = pos & (windowsize - 1)*/ -static void updateHashChain(Hash* hash, size_t wpos, unsigned hashval, unsigned short numzeros) { - hash->val[wpos] = (int)hashval; - if(hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval]; - hash->head[hashval] = (int)wpos; - - hash->zeros[wpos] = numzeros; - if(hash->headz[numzeros] != -1) hash->chainz[wpos] = hash->headz[numzeros]; - hash->headz[numzeros] = (int)wpos; -} - -/* -LZ77-encode the data. Return value is error code. The input are raw bytes, the output -is in the form of unsigned integers with codes representing for example literal bytes, or -length/distance pairs. -It uses a hash table technique to let it encode faster. When doing LZ77 encoding, a -sliding window (of windowsize) is used, and all past bytes in that window can be used as -the "dictionary". A brute force search through all possible distances would be slow, and -this hash technique is one out of several ways to speed this up. -*/ -static unsigned encodeLZ77(uivector* out, Hash* hash, - const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize, - unsigned minmatch, unsigned nicematch, unsigned lazymatching) { - size_t pos; - unsigned i, error = 0; - /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/ - unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8u; - unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64; - - unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/ - unsigned numzeros = 0; - - unsigned offset; /*the offset represents the distance in LZ77 terminology*/ - unsigned length; - unsigned lazy = 0; - unsigned lazylength = 0, lazyoffset = 0; - unsigned hashval; - unsigned current_offset, current_length; - unsigned prev_offset; - const unsigned char *lastptr, *foreptr, *backptr; - unsigned hashpos; - - if(windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/ - if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/ - - if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH; - - for(pos = inpos; pos < insize; ++pos) { - size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/ - unsigned chainlength = 0; - - hashval = getHash(in, insize, pos); - - if(usezeros && hashval == 0) { - if(numzeros == 0) numzeros = countZeros(in, insize, pos); - else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; - } else { - numzeros = 0; - } - - updateHashChain(hash, wpos, hashval, numzeros); - - /*the length and offset found for the current position*/ - length = 0; - offset = 0; - - hashpos = hash->chain[wpos]; - - lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH]; - - /*search for the longest string*/ - prev_offset = 0; - for(;;) { - if(chainlength++ >= maxchainlength) break; - current_offset = (unsigned)(hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize); - - if(current_offset < prev_offset) break; /*stop when went completely around the circular buffer*/ - prev_offset = current_offset; - if(current_offset > 0) { - /*test the next characters*/ - foreptr = &in[pos]; - backptr = &in[pos - current_offset]; - - /*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/ - if(numzeros >= 3) { - unsigned skip = hash->zeros[hashpos]; - if(skip > numzeros) skip = numzeros; - backptr += skip; - foreptr += skip; - } - - while(foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/ { - ++backptr; - ++foreptr; - } - current_length = (unsigned)(foreptr - &in[pos]); - - if(current_length > length) { - length = current_length; /*the longest length*/ - offset = current_offset; /*the offset that is related to this longest length*/ - /*jump out once a length of max length is found (speed gain). This also jumps - out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/ - if(current_length >= nicematch) break; - } - } - - if(hashpos == hash->chain[hashpos]) break; - - if(numzeros >= 3 && length > numzeros) { - hashpos = hash->chainz[hashpos]; - if(hash->zeros[hashpos] != numzeros) break; - } else { - hashpos = hash->chain[hashpos]; - /*outdated hash value, happens if particular value was not encountered in whole last window*/ - if(hash->val[hashpos] != (int)hashval) break; - } - } - - if(lazymatching) { - if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH) { - lazy = 1; - lazylength = length; - lazyoffset = offset; - continue; /*try the next byte*/ - } - if(lazy) { - lazy = 0; - if(pos == 0) ERROR_BREAK(81); - if(length > lazylength + 1) { - /*push the previous character as literal*/ - if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/); - } else { - length = lazylength; - offset = lazyoffset; - hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/ - hash->headz[numzeros] = -1; /*idem*/ - --pos; - } - } - } - if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/); - - /*encode it as length/distance pair or literal value*/ - if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ { - if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); - } else if(length < minmatch || (length == 3 && offset > 4096)) { - /*compensate for the fact that longer offsets have more extra bits, a - length of only 3 may be not worth it then*/ - if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); - } else { - addLengthDistance(out, length, offset); - for(i = 1; i < length; ++i) { - ++pos; - wpos = pos & (windowsize - 1); - hashval = getHash(in, insize, pos); - if(usezeros && hashval == 0) { - if(numzeros == 0) numzeros = countZeros(in, insize, pos); - else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; - } else { - numzeros = 0; - } - updateHashChain(hash, wpos, hashval, numzeros); - } - } - } /*end of the loop through each character of input*/ - - return error; -} - -/* /////////////////////////////////////////////////////////////////////////// */ - -static unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize) { - /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte, - 2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/ - - size_t i, numdeflateblocks = (datasize + 65534u) / 65535u; - unsigned datapos = 0; - for(i = 0; i != numdeflateblocks; ++i) { - unsigned BFINAL, BTYPE, LEN, NLEN; - unsigned char firstbyte; - size_t pos = out->size; - - BFINAL = (i == numdeflateblocks - 1); - BTYPE = 0; - - LEN = 65535; - if(datasize - datapos < 65535u) LEN = (unsigned)datasize - datapos; - NLEN = 65535 - LEN; - - if(!ucvector_resize(out, out->size + LEN + 5)) return 83; /*alloc fail*/ - - firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1u) << 1u) + ((BTYPE & 2u) << 1u)); - out->data[pos + 0] = firstbyte; - out->data[pos + 1] = (unsigned char)(LEN & 255); - out->data[pos + 2] = (unsigned char)(LEN >> 8u); - out->data[pos + 3] = (unsigned char)(NLEN & 255); - out->data[pos + 4] = (unsigned char)(NLEN >> 8u); - lodepng_memcpy(out->data + pos + 5, data + datapos, LEN); - datapos += LEN; - } - - return 0; -} - -/* -write the lz77-encoded data, which has lit, len and dist codes, to compressed stream using huffman trees. -tree_ll: the tree for lit and len codes. -tree_d: the tree for distance codes. -*/ -static void writeLZ77data(LodePNGBitWriter* writer, const uivector* lz77_encoded, - const HuffmanTree* tree_ll, const HuffmanTree* tree_d) { - size_t i = 0; - for(i = 0; i != lz77_encoded->size; ++i) { - unsigned val = lz77_encoded->data[i]; - writeBitsReversed(writer, tree_ll->codes[val], tree_ll->lengths[val]); - if(val > 256) /*for a length code, 3 more things have to be added*/ { - unsigned length_index = val - FIRST_LENGTH_CODE_INDEX; - unsigned n_length_extra_bits = LENGTHEXTRA[length_index]; - unsigned length_extra_bits = lz77_encoded->data[++i]; - - unsigned distance_code = lz77_encoded->data[++i]; - - unsigned distance_index = distance_code; - unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index]; - unsigned distance_extra_bits = lz77_encoded->data[++i]; - - writeBits(writer, length_extra_bits, n_length_extra_bits); - writeBitsReversed(writer, tree_d->codes[distance_code], tree_d->lengths[distance_code]); - writeBits(writer, distance_extra_bits, n_distance_extra_bits); - } - } -} - -/*Deflate for a block of type "dynamic", that is, with freely, optimally, created huffman trees*/ -static unsigned deflateDynamic(LodePNGBitWriter* writer, Hash* hash, - const unsigned char* data, size_t datapos, size_t dataend, - const LodePNGCompressSettings* settings, unsigned final) { - unsigned error = 0; - - /* - A block is compressed as follows: The PNG data is lz77 encoded, resulting in - literal bytes and length/distance pairs. This is then huffman compressed with - two huffman trees. One huffman tree is used for the lit and len values ("ll"), - another huffman tree is used for the dist values ("d"). These two trees are - stored using their code lengths, and to compress even more these code lengths - are also run-length encoded and huffman compressed. This gives a huffman tree - of code lengths "cl". The code lengths used to describe this third tree are - the code length code lengths ("clcl"). - */ - - /*The lz77 encoded data, represented with integers since there will also be length and distance codes in it*/ - uivector lz77_encoded; - HuffmanTree tree_ll; /*tree for lit,len values*/ - HuffmanTree tree_d; /*tree for distance codes*/ - HuffmanTree tree_cl; /*tree for encoding the code lengths representing tree_ll and tree_d*/ - unsigned* frequencies_ll = 0; /*frequency of lit,len codes*/ - unsigned* frequencies_d = 0; /*frequency of dist codes*/ - unsigned* frequencies_cl = 0; /*frequency of code length codes*/ - unsigned* bitlen_lld = 0; /*lit,len,dist code lengths (int bits), literally (without repeat codes).*/ - unsigned* bitlen_lld_e = 0; /*bitlen_lld encoded with repeat codes (this is a rudimentary run length compression)*/ - size_t datasize = dataend - datapos; - - /* - If we could call "bitlen_cl" the the code length code lengths ("clcl"), that is the bit lengths of codes to represent - tree_cl in CLCL_ORDER, then due to the huffman compression of huffman tree representations ("two levels"), there are - some analogies: - bitlen_lld is to tree_cl what data is to tree_ll and tree_d. - bitlen_lld_e is to bitlen_lld what lz77_encoded is to data. - bitlen_cl is to bitlen_lld_e what bitlen_lld is to lz77_encoded. - */ - - unsigned BFINAL = final; - size_t i; - size_t numcodes_ll, numcodes_d, numcodes_lld, numcodes_lld_e, numcodes_cl; - unsigned HLIT, HDIST, HCLEN; - - uivector_init(&lz77_encoded); - HuffmanTree_init(&tree_ll); - HuffmanTree_init(&tree_d); - HuffmanTree_init(&tree_cl); - /* could fit on stack, but >1KB is on the larger side so allocate instead */ - frequencies_ll = (unsigned*)lodepng_malloc(286 * sizeof(*frequencies_ll)); - frequencies_d = (unsigned*)lodepng_malloc(30 * sizeof(*frequencies_d)); - frequencies_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(*frequencies_cl)); - - if(!frequencies_ll || !frequencies_d || !frequencies_cl) error = 83; /*alloc fail*/ - - /*This while loop never loops due to a break at the end, it is here to - allow breaking out of it to the cleanup phase on error conditions.*/ - while(!error) { - lodepng_memset(frequencies_ll, 0, 286 * sizeof(*frequencies_ll)); - lodepng_memset(frequencies_d, 0, 30 * sizeof(*frequencies_d)); - lodepng_memset(frequencies_cl, 0, NUM_CODE_LENGTH_CODES * sizeof(*frequencies_cl)); - - if(settings->use_lz77) { - error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, - settings->minmatch, settings->nicematch, settings->lazymatching); - if(error) break; - } else { - if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83 /*alloc fail*/); - for(i = datapos; i < dataend; ++i) lz77_encoded.data[i - datapos] = data[i]; /*no LZ77, but still will be Huffman compressed*/ - } - - /*Count the frequencies of lit, len and dist codes*/ - for(i = 0; i != lz77_encoded.size; ++i) { - unsigned symbol = lz77_encoded.data[i]; - ++frequencies_ll[symbol]; - if(symbol > 256) { - unsigned dist = lz77_encoded.data[i + 2]; - ++frequencies_d[dist]; - i += 3; - } - } - frequencies_ll[256] = 1; /*there will be exactly 1 end code, at the end of the block*/ - - /*Make both huffman trees, one for the lit and len codes, one for the dist codes*/ - error = HuffmanTree_makeFromFrequencies(&tree_ll, frequencies_ll, 257, 286, 15); - if(error) break; - /*2, not 1, is chosen for mincodes: some buggy PNG decoders require at least 2 symbols in the dist tree*/ - error = HuffmanTree_makeFromFrequencies(&tree_d, frequencies_d, 2, 30, 15); - if(error) break; - - numcodes_ll = LODEPNG_MIN(tree_ll.numcodes, 286); - numcodes_d = LODEPNG_MIN(tree_d.numcodes, 30); - /*store the code lengths of both generated trees in bitlen_lld*/ - numcodes_lld = numcodes_ll + numcodes_d; - bitlen_lld = (unsigned*)lodepng_malloc(numcodes_lld * sizeof(*bitlen_lld)); - /*numcodes_lld_e never needs more size than bitlen_lld*/ - bitlen_lld_e = (unsigned*)lodepng_malloc(numcodes_lld * sizeof(*bitlen_lld_e)); - if(!bitlen_lld || !bitlen_lld_e) ERROR_BREAK(83); /*alloc fail*/ - numcodes_lld_e = 0; - - for(i = 0; i != numcodes_ll; ++i) bitlen_lld[i] = tree_ll.lengths[i]; - for(i = 0; i != numcodes_d; ++i) bitlen_lld[numcodes_ll + i] = tree_d.lengths[i]; - - /*run-length compress bitlen_ldd into bitlen_lld_e by using repeat codes 16 (copy length 3-6 times), - 17 (3-10 zeroes), 18 (11-138 zeroes)*/ - for(i = 0; i != numcodes_lld; ++i) { - unsigned j = 0; /*amount of repetitions*/ - while(i + j + 1 < numcodes_lld && bitlen_lld[i + j + 1] == bitlen_lld[i]) ++j; - - if(bitlen_lld[i] == 0 && j >= 2) /*repeat code for zeroes*/ { - ++j; /*include the first zero*/ - if(j <= 10) /*repeat code 17 supports max 10 zeroes*/ { - bitlen_lld_e[numcodes_lld_e++] = 17; - bitlen_lld_e[numcodes_lld_e++] = j - 3; - } else /*repeat code 18 supports max 138 zeroes*/ { - if(j > 138) j = 138; - bitlen_lld_e[numcodes_lld_e++] = 18; - bitlen_lld_e[numcodes_lld_e++] = j - 11; - } - i += (j - 1); - } else if(j >= 3) /*repeat code for value other than zero*/ { - size_t k; - unsigned num = j / 6u, rest = j % 6u; - bitlen_lld_e[numcodes_lld_e++] = bitlen_lld[i]; - for(k = 0; k < num; ++k) { - bitlen_lld_e[numcodes_lld_e++] = 16; - bitlen_lld_e[numcodes_lld_e++] = 6 - 3; - } - if(rest >= 3) { - bitlen_lld_e[numcodes_lld_e++] = 16; - bitlen_lld_e[numcodes_lld_e++] = rest - 3; - } - else j -= rest; - i += j; - } else /*too short to benefit from repeat code*/ { - bitlen_lld_e[numcodes_lld_e++] = bitlen_lld[i]; - } - } - - /*generate tree_cl, the huffmantree of huffmantrees*/ - for(i = 0; i != numcodes_lld_e; ++i) { - ++frequencies_cl[bitlen_lld_e[i]]; - /*after a repeat code come the bits that specify the number of repetitions, - those don't need to be in the frequencies_cl calculation*/ - if(bitlen_lld_e[i] >= 16) ++i; - } - - error = HuffmanTree_makeFromFrequencies(&tree_cl, frequencies_cl, - NUM_CODE_LENGTH_CODES, NUM_CODE_LENGTH_CODES, 7); - if(error) break; - - /*compute amount of code-length-code-lengths to output*/ - numcodes_cl = NUM_CODE_LENGTH_CODES; - /*trim zeros at the end (using CLCL_ORDER), but minimum size must be 4 (see HCLEN below)*/ - while(numcodes_cl > 4u && tree_cl.lengths[CLCL_ORDER[numcodes_cl - 1u]] == 0) { - numcodes_cl--; - } - - /* - Write everything into the output - - After the BFINAL and BTYPE, the dynamic block consists out of the following: - - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN - - (HCLEN+4)*3 bits code lengths of code length alphabet - - HLIT + 257 code lengths of lit/length alphabet (encoded using the code length - alphabet, + possible repetition codes 16, 17, 18) - - HDIST + 1 code lengths of distance alphabet (encoded using the code length - alphabet, + possible repetition codes 16, 17, 18) - - compressed data - - 256 (end code) - */ - - /*Write block type*/ - writeBits(writer, BFINAL, 1); - writeBits(writer, 0, 1); /*first bit of BTYPE "dynamic"*/ - writeBits(writer, 1, 1); /*second bit of BTYPE "dynamic"*/ - - /*write the HLIT, HDIST and HCLEN values*/ - /*all three sizes take trimmed ending zeroes into account, done either by HuffmanTree_makeFromFrequencies - or in the loop for numcodes_cl above, which saves space. */ - HLIT = (unsigned)(numcodes_ll - 257); - HDIST = (unsigned)(numcodes_d - 1); - HCLEN = (unsigned)(numcodes_cl - 4); - writeBits(writer, HLIT, 5); - writeBits(writer, HDIST, 5); - writeBits(writer, HCLEN, 4); - - /*write the code lengths of the code length alphabet ("bitlen_cl")*/ - for(i = 0; i != numcodes_cl; ++i) writeBits(writer, tree_cl.lengths[CLCL_ORDER[i]], 3); - - /*write the lengths of the lit/len AND the dist alphabet*/ - for(i = 0; i != numcodes_lld_e; ++i) { - writeBitsReversed(writer, tree_cl.codes[bitlen_lld_e[i]], tree_cl.lengths[bitlen_lld_e[i]]); - /*extra bits of repeat codes*/ - if(bitlen_lld_e[i] == 16) writeBits(writer, bitlen_lld_e[++i], 2); - else if(bitlen_lld_e[i] == 17) writeBits(writer, bitlen_lld_e[++i], 3); - else if(bitlen_lld_e[i] == 18) writeBits(writer, bitlen_lld_e[++i], 7); - } - - /*write the compressed data symbols*/ - writeLZ77data(writer, &lz77_encoded, &tree_ll, &tree_d); - /*error: the length of the end code 256 must be larger than 0*/ - if(tree_ll.lengths[256] == 0) ERROR_BREAK(64); - - /*write the end code*/ - writeBitsReversed(writer, tree_ll.codes[256], tree_ll.lengths[256]); - - break; /*end of error-while*/ - } - - /*cleanup*/ - uivector_cleanup(&lz77_encoded); - HuffmanTree_cleanup(&tree_ll); - HuffmanTree_cleanup(&tree_d); - HuffmanTree_cleanup(&tree_cl); - lodepng_free(frequencies_ll); - lodepng_free(frequencies_d); - lodepng_free(frequencies_cl); - lodepng_free(bitlen_lld); - lodepng_free(bitlen_lld_e); - - return error; -} - -static unsigned deflateFixed(LodePNGBitWriter* writer, Hash* hash, - const unsigned char* data, - size_t datapos, size_t dataend, - const LodePNGCompressSettings* settings, unsigned final) { - HuffmanTree tree_ll; /*tree for literal values and length codes*/ - HuffmanTree tree_d; /*tree for distance codes*/ - - unsigned BFINAL = final; - unsigned error = 0; - size_t i; - - HuffmanTree_init(&tree_ll); - HuffmanTree_init(&tree_d); - - error = generateFixedLitLenTree(&tree_ll); - if(!error) error = generateFixedDistanceTree(&tree_d); - - if(!error) { - writeBits(writer, BFINAL, 1); - writeBits(writer, 1, 1); /*first bit of BTYPE*/ - writeBits(writer, 0, 1); /*second bit of BTYPE*/ - - if(settings->use_lz77) /*LZ77 encoded*/ { - uivector lz77_encoded; - uivector_init(&lz77_encoded); - error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, - settings->minmatch, settings->nicematch, settings->lazymatching); - if(!error) writeLZ77data(writer, &lz77_encoded, &tree_ll, &tree_d); - uivector_cleanup(&lz77_encoded); - } else /*no LZ77, but still will be Huffman compressed*/ { - for(i = datapos; i < dataend; ++i) { - writeBitsReversed(writer, tree_ll.codes[data[i]], tree_ll.lengths[data[i]]); - } - } - /*add END code*/ - if(!error) writeBitsReversed(writer,tree_ll.codes[256], tree_ll.lengths[256]); - } - - /*cleanup*/ - HuffmanTree_cleanup(&tree_ll); - HuffmanTree_cleanup(&tree_d); - - return error; -} - -static unsigned lodepng_deflatev(ucvector* out, const unsigned char* in, size_t insize, - const LodePNGCompressSettings* settings) { - unsigned error = 0; - size_t i, blocksize, numdeflateblocks; - Hash hash; - LodePNGBitWriter writer; - - LodePNGBitWriter_init(&writer, out); - - if(settings->btype > 2) return 61; - else if(settings->btype == 0) return deflateNoCompression(out, in, insize); - else if(settings->btype == 1) blocksize = insize; - else /*if(settings->btype == 2)*/ { - /*on PNGs, deflate blocks of 65-262k seem to give most dense encoding*/ - blocksize = insize / 8u + 8; - if(blocksize < 65536) blocksize = 65536; - if(blocksize > 262144) blocksize = 262144; - } - - numdeflateblocks = (insize + blocksize - 1) / blocksize; - if(numdeflateblocks == 0) numdeflateblocks = 1; - - error = hash_init(&hash, settings->windowsize); - - if(!error) { - for(i = 0; i != numdeflateblocks && !error; ++i) { - unsigned final = (i == numdeflateblocks - 1); - size_t start = i * blocksize; - size_t end = start + blocksize; - if(end > insize) end = insize; - - if(settings->btype == 1) error = deflateFixed(&writer, &hash, in, start, end, settings, final); - else if(settings->btype == 2) error = deflateDynamic(&writer, &hash, in, start, end, settings, final); - } - } - - hash_cleanup(&hash); - - return error; -} - -unsigned lodepng_deflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGCompressSettings* settings) { - ucvector v = ucvector_init(*out, *outsize); - unsigned error = lodepng_deflatev(&v, in, insize, settings); - *out = v.data; - *outsize = v.size; - return error; -} - -static unsigned deflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGCompressSettings* settings) { - if(settings->custom_deflate) { - unsigned error = settings->custom_deflate(out, outsize, in, insize, settings); - /*the custom deflate is allowed to have its own error codes, however, we translate it to code 111*/ - return error ? 111 : 0; - } else { - return lodepng_deflate(out, outsize, in, insize, settings); - } -} - -#endif /*LODEPNG_COMPILE_DECODER*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Adler32 / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -static unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len) { - unsigned s1 = adler & 0xffffu; - unsigned s2 = (adler >> 16u) & 0xffffu; - - while(len != 0u) { - unsigned i; - /*at least 5552 sums can be done before the sums overflow, saving a lot of module divisions*/ - unsigned amount = len > 5552u ? 5552u : len; - len -= amount; - for(i = 0; i != amount; ++i) { - s1 += (*data++); - s2 += s1; - } - s1 %= 65521u; - s2 %= 65521u; - } - - return (s2 << 16u) | s1; -} - -/*Return the adler32 of the bytes data[0..len-1]*/ -static unsigned adler32(const unsigned char* data, unsigned len) { - return update_adler32(1u, data, len); -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Zlib / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_DECODER - -static unsigned lodepng_zlib_decompressv(ucvector* out, - const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings) { - unsigned error = 0; - unsigned CM, CINFO, FDICT; - - if(insize < 2) return 53; /*error, size of zlib data too small*/ - /*read information from zlib header*/ - if((in[0] * 256 + in[1]) % 31 != 0) { - /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/ - return 24; - } - - CM = in[0] & 15; - CINFO = (in[0] >> 4) & 15; - /*FCHECK = in[1] & 31;*/ /*FCHECK is already tested above*/ - FDICT = (in[1] >> 5) & 1; - /*FLEVEL = (in[1] >> 6) & 3;*/ /*FLEVEL is not used here*/ - - if(CM != 8 || CINFO > 7) { - /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/ - return 25; - } - if(FDICT != 0) { - /*error: the specification of PNG says about the zlib stream: - "The additional flags shall not specify a preset dictionary."*/ - return 26; - } - - error = inflatev(out, in + 2, insize - 2, settings); - if(error) return error; - - if(!settings->ignore_adler32) { - unsigned ADLER32 = lodepng_read32bitInt(&in[insize - 4]); - unsigned checksum = adler32(out->data, (unsigned)(out->size)); - if(checksum != ADLER32) return 58; /*error, adler checksum not correct, data must be corrupted*/ - } - - return 0; /*no error*/ -} - - -unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, - size_t insize, const LodePNGDecompressSettings* settings) { - ucvector v = ucvector_init(*out, *outsize); - unsigned error = lodepng_zlib_decompressv(&v, in, insize, settings); - *out = v.data; - *outsize = v.size; - return error; -} - -/*expected_size is expected output size, to avoid intermediate allocations. Set to 0 if not known. */ -static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size, - const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) { - unsigned error; - if(settings->custom_zlib) { - error = settings->custom_zlib(out, outsize, in, insize, settings); - if(error) { - /*the custom zlib is allowed to have its own error codes, however, we translate it to code 110*/ - error = 110; - /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/ - if(settings->max_output_size && *outsize > settings->max_output_size) error = 109; - } - } else { - ucvector v = ucvector_init(*out, *outsize); - if(expected_size) { - /*reserve the memory to avoid intermediate reallocations*/ - ucvector_resize(&v, *outsize + expected_size); - v.size = *outsize; - } - error = lodepng_zlib_decompressv(&v, in, insize, settings); - *out = v.data; - *outsize = v.size; - } - return error; -} - -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_ENCODER - -unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, - size_t insize, const LodePNGCompressSettings* settings) { - size_t i; - unsigned error; - unsigned char* deflatedata = 0; - size_t deflatesize = 0; - - error = deflate(&deflatedata, &deflatesize, in, insize, settings); - - *out = NULL; - *outsize = 0; - if(!error) { - *outsize = deflatesize + 6; - *out = (unsigned char*)lodepng_malloc(*outsize); - if(!*out) error = 83; /*alloc fail*/ - } - - if(!error) { - unsigned ADLER32 = adler32(in, (unsigned)insize); - /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/ - unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/ - unsigned FLEVEL = 0; - unsigned FDICT = 0; - unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64; - unsigned FCHECK = 31 - CMFFLG % 31; - CMFFLG += FCHECK; - - (*out)[0] = (unsigned char)(CMFFLG >> 8); - (*out)[1] = (unsigned char)(CMFFLG & 255); - for(i = 0; i != deflatesize; ++i) (*out)[i + 2] = deflatedata[i]; - lodepng_set32bitInt(&(*out)[*outsize - 4], ADLER32); - } - - lodepng_free(deflatedata); - return error; -} - -/* compress using the default or custom zlib function */ -static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, - size_t insize, const LodePNGCompressSettings* settings) { - if(settings->custom_zlib) { - unsigned error = settings->custom_zlib(out, outsize, in, insize, settings); - /*the custom zlib is allowed to have its own error codes, however, we translate it to code 111*/ - return error ? 111 : 0; - } else { - return lodepng_zlib_compress(out, outsize, in, insize, settings); - } -} - -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#else /*no LODEPNG_COMPILE_ZLIB*/ - -#ifdef LODEPNG_COMPILE_DECODER -static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size, - const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) { - if(!settings->custom_zlib) return 87; /*no custom zlib function provided */ - LV_UNUSED(expected_size); - return settings->custom_zlib(out, outsize, in, insize, settings); -} -#endif /*LODEPNG_COMPILE_DECODER*/ -#ifdef LODEPNG_COMPILE_ENCODER -static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, - size_t insize, const LodePNGCompressSettings* settings) { - if(!settings->custom_zlib) return 87; /*no custom zlib function provided */ - return settings->custom_zlib(out, outsize, in, insize, settings); -} -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#endif /*LODEPNG_COMPILE_ZLIB*/ - -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_ENCODER - -/*this is a good tradeoff between speed and compression ratio*/ -#define DEFAULT_WINDOWSIZE 2048 - -void lodepng_compress_settings_init(LodePNGCompressSettings* settings) { - /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/ - settings->btype = 2; - settings->use_lz77 = 1; - settings->windowsize = DEFAULT_WINDOWSIZE; - settings->minmatch = 3; - settings->nicematch = 128; - settings->lazymatching = 1; - - settings->custom_zlib = 0; - settings->custom_deflate = 0; - settings->custom_context = 0; -} - -const LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT_WINDOWSIZE, 3, 128, 1, 0, 0, 0}; - - -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#ifdef LODEPNG_COMPILE_DECODER - -void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) { - settings->ignore_adler32 = 0; - settings->ignore_nlen = 0; - settings->max_output_size = 0; - - settings->custom_zlib = 0; - settings->custom_inflate = 0; - settings->custom_context = 0; -} - -const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0, 0, 0}; - -#endif /*LODEPNG_COMPILE_DECODER*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* // End of Zlib related code. Begin of PNG related code. // */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_PNG - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / CRC32 / */ -/* ////////////////////////////////////////////////////////////////////////// */ - - -#ifndef LODEPNG_NO_COMPILE_CRC -/* CRC polynomial: 0xedb88320 */ -static unsigned lodepng_crc32_table[256] = { - 0u, 1996959894u, 3993919788u, 2567524794u, 124634137u, 1886057615u, 3915621685u, 2657392035u, - 249268274u, 2044508324u, 3772115230u, 2547177864u, 162941995u, 2125561021u, 3887607047u, 2428444049u, - 498536548u, 1789927666u, 4089016648u, 2227061214u, 450548861u, 1843258603u, 4107580753u, 2211677639u, - 325883990u, 1684777152u, 4251122042u, 2321926636u, 335633487u, 1661365465u, 4195302755u, 2366115317u, - 997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u, - 901097722u, 1119000684u, 3686517206u, 2898065728u, 853044451u, 1172266101u, 3705015759u, 2882616665u, - 651767980u, 1373503546u, 3369554304u, 3218104598u, 565507253u, 1454621731u, 3485111705u, 3099436303u, - 671266974u, 1594198024u, 3322730930u, 2970347812u, 795835527u, 1483230225u, 3244367275u, 3060149565u, - 1994146192u, 31158534u, 2563907772u, 4023717930u, 1907459465u, 112637215u, 2680153253u, 3904427059u, - 2013776290u, 251722036u, 2517215374u, 3775830040u, 2137656763u, 141376813u, 2439277719u, 3865271297u, - 1802195444u, 476864866u, 2238001368u, 4066508878u, 1812370925u, 453092731u, 2181625025u, 4111451223u, - 1706088902u, 314042704u, 2344532202u, 4240017532u, 1658658271u, 366619977u, 2362670323u, 4224994405u, - 1303535960u, 984961486u, 2747007092u, 3569037538u, 1256170817u, 1037604311u, 2765210733u, 3554079995u, - 1131014506u, 879679996u, 2909243462u, 3663771856u, 1141124467u, 855842277u, 2852801631u, 3708648649u, - 1342533948u, 654459306u, 3188396048u, 3373015174u, 1466479909u, 544179635u, 3110523913u, 3462522015u, - 1591671054u, 702138776u, 2966460450u, 3352799412u, 1504918807u, 783551873u, 3082640443u, 3233442989u, - 3988292384u, 2596254646u, 62317068u, 1957810842u, 3939845945u, 2647816111u, 81470997u, 1943803523u, - 3814918930u, 2489596804u, 225274430u, 2053790376u, 3826175755u, 2466906013u, 167816743u, 2097651377u, - 4027552580u, 2265490386u, 503444072u, 1762050814u, 4150417245u, 2154129355u, 426522225u, 1852507879u, - 4275313526u, 2312317920u, 282753626u, 1742555852u, 4189708143u, 2394877945u, 397917763u, 1622183637u, - 3604390888u, 2714866558u, 953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u, - 3624741850u, 2936675148u, 906185462u, 1090812512u, 3747672003u, 2825379669u, 829329135u, 1181335161u, - 3412177804u, 3160834842u, 628085408u, 1382605366u, 3423369109u, 3138078467u, 570562233u, 1426400815u, - 3317316542u, 2998733608u, 733239954u, 1555261956u, 3268935591u, 3050360625u, 752459403u, 1541320221u, - 2607071920u, 3965973030u, 1969922972u, 40735498u, 2617837225u, 3943577151u, 1913087877u, 83908371u, - 2512341634u, 3803740692u, 2075208622u, 213261112u, 2463272603u, 3855990285u, 2094854071u, 198958881u, - 2262029012u, 4057260610u, 1759359992u, 534414190u, 2176718541u, 4139329115u, 1873836001u, 414664567u, - 2282248934u, 4279200368u, 1711684554u, 285281116u, 2405801727u, 4167216745u, 1634467795u, 376229701u, - 2685067896u, 3608007406u, 1308918612u, 956543938u, 2808555105u, 3495958263u, 1231636301u, 1047427035u, - 2932959818u, 3654703836u, 1088359270u, 936918000u, 2847714899u, 3736837829u, 1202900863u, 817233897u, - 3183342108u, 3401237130u, 1404277552u, 615818150u, 3134207493u, 3453421203u, 1423857449u, 601450431u, - 3009837614u, 3294710456u, 1567103746u, 711928724u, 3020668471u, 3272380065u, 1510334235u, 755167117u -}; - -/*Return the CRC of the bytes buf[0..len-1].*/ -unsigned lodepng_crc32(const unsigned char* data, size_t length) { - unsigned r = 0xffffffffu; - size_t i; - for(i = 0; i < length; ++i) { - r = lodepng_crc32_table[(r ^ data[i]) & 0xffu] ^ (r >> 8u); - } - return r ^ 0xffffffffu; -} -#else /* !LODEPNG_NO_COMPILE_CRC */ -unsigned lodepng_crc32(const unsigned char* data, size_t length); -#endif /* !LODEPNG_NO_COMPILE_CRC */ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Reading and writing PNG color channel bits / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/* The color channel bits of less-than-8-bit pixels are read with the MSB of bytes first, -so LodePNGBitWriter and LodePNGBitReader can't be used for those. */ - -static unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream) { - unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1); - ++(*bitpointer); - return result; -} - -/* TODO: make this faster */ -static unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) { - unsigned result = 0; - size_t i; - for(i = 0 ; i < nbits; ++i) { - result <<= 1u; - result |= (unsigned)readBitFromReversedStream(bitpointer, bitstream); - } - return result; -} - -static void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) { - /*the current bit in bitstream may be 0 or 1 for this to work*/ - if(bit == 0) bitstream[(*bitpointer) >> 3u] &= (unsigned char)(~(1u << (7u - ((*bitpointer) & 7u)))); - else bitstream[(*bitpointer) >> 3u] |= (1u << (7u - ((*bitpointer) & 7u))); - ++(*bitpointer); -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / PNG chunks / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -unsigned lodepng_chunk_length(const unsigned char* chunk) { - return lodepng_read32bitInt(&chunk[0]); -} - -void lodepng_chunk_type(char type[5], const unsigned char* chunk) { - unsigned i; - for(i = 0; i != 4; ++i) type[i] = (char)chunk[4 + i]; - type[4] = 0; /*null termination char*/ -} - -unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type) { - if(lodepng_strlen(type) != 4) return 0; - return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]); -} - -unsigned char lodepng_chunk_ancillary(const unsigned char* chunk) { - return((chunk[4] & 32) != 0); -} - -unsigned char lodepng_chunk_private(const unsigned char* chunk) { - return((chunk[6] & 32) != 0); -} - -unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk) { - return((chunk[7] & 32) != 0); -} - -unsigned char* lodepng_chunk_data(unsigned char* chunk) { - return &chunk[8]; -} - -const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk) { - return &chunk[8]; -} - -unsigned lodepng_chunk_check_crc(const unsigned char* chunk) { - unsigned length = lodepng_chunk_length(chunk); - unsigned CRC = lodepng_read32bitInt(&chunk[length + 8]); - /*the CRC is taken of the data and the 4 chunk type letters, not the length*/ - unsigned checksum = lodepng_crc32(&chunk[4], length + 4); - if(CRC != checksum) return 1; - else return 0; -} - -void lodepng_chunk_generate_crc(unsigned char* chunk) { - unsigned length = lodepng_chunk_length(chunk); - unsigned CRC = lodepng_crc32(&chunk[4], length + 4); - lodepng_set32bitInt(chunk + 8 + length, CRC); -} - -unsigned char* lodepng_chunk_next(unsigned char* chunk, unsigned char* end) { - if(chunk >= end || end - chunk < 12) return end; /*too small to contain a chunk*/ - if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47 - && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) { - /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */ - return chunk + 8; - } else { - size_t total_chunk_length; - unsigned char* result; - if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end; - result = chunk + total_chunk_length; - if(result < chunk) return end; /*pointer overflow*/ - return result; - } -} - -const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk, const unsigned char* end) { - if(chunk >= end || end - chunk < 12) return end; /*too small to contain a chunk*/ - if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47 - && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) { - /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */ - return chunk + 8; - } else { - size_t total_chunk_length; - const unsigned char* result; - if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end; - result = chunk + total_chunk_length; - if(result < chunk) return end; /*pointer overflow*/ - return result; - } -} - -unsigned char* lodepng_chunk_find(unsigned char* chunk, unsigned char* end, const char type[5]) { - for(;;) { - if(chunk >= end || end - chunk < 12) return 0; /* past file end: chunk + 12 > end */ - if(lodepng_chunk_type_equals(chunk, type)) return chunk; - chunk = lodepng_chunk_next(chunk, end); - } - - return 0; /*Shouldn't reach this*/ -} - -const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]) { - for(;;) { - if(chunk >= end || end - chunk < 12) return 0; /* past file end: chunk + 12 > end */ - if(lodepng_chunk_type_equals(chunk, type)) return chunk; - chunk = lodepng_chunk_next_const(chunk, end); - } - - return 0; /*Shouldn't reach this*/ -} - -unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk) { - unsigned i; - size_t total_chunk_length, new_length; - unsigned char *chunk_start, *new_buffer; - - if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return 77; - if(lodepng_addofl(*outsize, total_chunk_length, &new_length)) return 77; - - new_buffer = (unsigned char*)lodepng_realloc(*out, new_length); - if(!new_buffer) return 83; /*alloc fail*/ - (*out) = new_buffer; - (*outsize) = new_length; - chunk_start = &(*out)[new_length - total_chunk_length]; - - for(i = 0; i != total_chunk_length; ++i) chunk_start[i] = chunk[i]; - - return 0; -} - -/*Sets length and name and allocates the space for data and crc but does not -set data or crc yet. Returns the start of the chunk in chunk. The start of -the data is at chunk + 8. To finalize chunk, add the data, then use -lodepng_chunk_generate_crc */ -static unsigned lodepng_chunk_init(unsigned char** chunk, - ucvector* out, - unsigned length, const char* type) { - size_t new_length = out->size; - if(lodepng_addofl(new_length, length, &new_length)) return 77; - if(lodepng_addofl(new_length, 12, &new_length)) return 77; - if(!ucvector_resize(out, new_length)) return 83; /*alloc fail*/ - *chunk = out->data + new_length - length - 12u; - - /*1: length*/ - lodepng_set32bitInt(*chunk, length); - - /*2: chunk name (4 letters)*/ - lodepng_memcpy(*chunk + 4, type, 4); - - return 0; -} - -/* like lodepng_chunk_create but with custom allocsize */ -static unsigned lodepng_chunk_createv(ucvector* out, - unsigned length, const char* type, const unsigned char* data) { - unsigned char* chunk; - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, length, type)); - - /*3: the data*/ - lodepng_memcpy(chunk + 8, data, length); - - /*4: CRC (of the chunkname characters and the data)*/ - lodepng_chunk_generate_crc(chunk); - - return 0; -} - -unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, - unsigned length, const char* type, const unsigned char* data) { - ucvector v = ucvector_init(*out, *outsize); - unsigned error = lodepng_chunk_createv(&v, length, type, data); - *out = v.data; - *outsize = v.size; - return error; -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Color types, channels, bits / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*checks if the colortype is valid and the bitdepth bd is allowed for this colortype. -Return value is a LodePNG error code.*/ -static unsigned checkColorValidity(LodePNGColorType colortype, unsigned bd) { - switch(colortype) { - case LCT_GREY: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; - case LCT_RGB: if(!( bd == 8 || bd == 16)) return 37; break; - case LCT_PALETTE: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; break; - case LCT_GREY_ALPHA: if(!( bd == 8 || bd == 16)) return 37; break; - case LCT_RGBA: if(!( bd == 8 || bd == 16)) return 37; break; - case LCT_MAX_OCTET_VALUE: return 31; /* invalid color type */ - default: return 31; /* invalid color type */ - } - return 0; /*allowed color type / bits combination*/ -} - -static unsigned getNumColorChannels(LodePNGColorType colortype) { - switch(colortype) { - case LCT_GREY: return 1; - case LCT_RGB: return 3; - case LCT_PALETTE: return 1; - case LCT_GREY_ALPHA: return 2; - case LCT_RGBA: return 4; - case LCT_MAX_OCTET_VALUE: return 0; /* invalid color type */ - default: return 0; /*invalid color type*/ - } -} - -static unsigned lodepng_get_bpp_lct(LodePNGColorType colortype, unsigned bitdepth) { - /*bits per pixel is amount of channels * bits per channel*/ - return getNumColorChannels(colortype) * bitdepth; -} - -/* ////////////////////////////////////////////////////////////////////////// */ - -void lodepng_color_mode_init(LodePNGColorMode* info) { - info->key_defined = 0; - info->key_r = info->key_g = info->key_b = 0; - info->colortype = LCT_RGBA; - info->bitdepth = 8; - info->palette = 0; - info->palettesize = 0; -} - -/*allocates palette memory if needed, and initializes all colors to black*/ -static void lodepng_color_mode_alloc_palette(LodePNGColorMode* info) { - size_t i; - /*if the palette is already allocated, it will have size 1024 so no reallocation needed in that case*/ - /*the palette must have room for up to 256 colors with 4 bytes each.*/ - if(!info->palette) info->palette = (unsigned char*)lodepng_malloc(1024); - if(!info->palette) return; /*alloc fail*/ - for(i = 0; i != 256; ++i) { - /*Initialize all unused colors with black, the value used for invalid palette indices. - This is an error according to the PNG spec, but common PNG decoders make it black instead. - That makes color conversion slightly faster due to no error handling needed.*/ - info->palette[i * 4 + 0] = 0; - info->palette[i * 4 + 1] = 0; - info->palette[i * 4 + 2] = 0; - info->palette[i * 4 + 3] = 255; - } -} - -void lodepng_color_mode_cleanup(LodePNGColorMode* info) { - lodepng_palette_clear(info); -} - -unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source) { - lodepng_color_mode_cleanup(dest); - lodepng_memcpy(dest, source, sizeof(LodePNGColorMode)); - if(source->palette) { - dest->palette = (unsigned char*)lodepng_malloc(1024); - if(!dest->palette && source->palettesize) return 83; /*alloc fail*/ - lodepng_memcpy(dest->palette, source->palette, source->palettesize * 4); - } - return 0; -} - -LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth) { - LodePNGColorMode result; - lodepng_color_mode_init(&result); - result.colortype = colortype; - result.bitdepth = bitdepth; - return result; -} - -static int lodepng_color_mode_equal(const LodePNGColorMode* a, const LodePNGColorMode* b) { - size_t i; - if(a->colortype != b->colortype) return 0; - if(a->bitdepth != b->bitdepth) return 0; - if(a->key_defined != b->key_defined) return 0; - if(a->key_defined) { - if(a->key_r != b->key_r) return 0; - if(a->key_g != b->key_g) return 0; - if(a->key_b != b->key_b) return 0; - } - if(a->palettesize != b->palettesize) return 0; - for(i = 0; i != a->palettesize * 4; ++i) { - if(a->palette[i] != b->palette[i]) return 0; - } - return 1; -} - -void lodepng_palette_clear(LodePNGColorMode* info) { - if(info->palette) lodepng_free(info->palette); - info->palette = 0; - info->palettesize = 0; -} - -unsigned lodepng_palette_add(LodePNGColorMode* info, - unsigned char r, unsigned char g, unsigned char b, unsigned char a) { - if(!info->palette) /*allocate palette if empty*/ { - lodepng_color_mode_alloc_palette(info); - if(!info->palette) return 83; /*alloc fail*/ - } - if(info->palettesize >= 256) { - return 108; /*too many palette values*/ - } - info->palette[4 * info->palettesize + 0] = r; - info->palette[4 * info->palettesize + 1] = g; - info->palette[4 * info->palettesize + 2] = b; - info->palette[4 * info->palettesize + 3] = a; - ++info->palettesize; - return 0; -} - -/*calculate bits per pixel out of colortype and bitdepth*/ -unsigned lodepng_get_bpp(const LodePNGColorMode* info) { - return lodepng_get_bpp_lct(info->colortype, info->bitdepth); -} - -unsigned lodepng_get_channels(const LodePNGColorMode* info) { - return getNumColorChannels(info->colortype); -} - -unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info) { - return info->colortype == LCT_GREY || info->colortype == LCT_GREY_ALPHA; -} - -unsigned lodepng_is_alpha_type(const LodePNGColorMode* info) { - return (info->colortype & 4) != 0; /*4 or 6*/ -} - -unsigned lodepng_is_palette_type(const LodePNGColorMode* info) { - return info->colortype == LCT_PALETTE; -} - -unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info) { - size_t i; - for(i = 0; i != info->palettesize; ++i) { - if(info->palette[i * 4 + 3] < 255) return 1; - } - return 0; -} - -unsigned lodepng_can_have_alpha(const LodePNGColorMode* info) { - return info->key_defined - || lodepng_is_alpha_type(info) - || lodepng_has_palette_alpha(info); -} - -static size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) { - size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth); - size_t n = (size_t)w * (size_t)h; - return ((n / 8u) * bpp) + ((n & 7u) * bpp + 7u) / 8u; -} - -size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color) { - return lodepng_get_raw_size_lct(w, h, color->colortype, color->bitdepth); -} - - -#ifdef LODEPNG_COMPILE_PNG - -/*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer, -and in addition has one extra byte per line: the filter byte. So this gives a larger -result than lodepng_get_raw_size. Set h to 1 to get the size of 1 row including filter byte. */ -static size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, unsigned bpp) { - /* + 1 for the filter byte, and possibly plus padding bits per line. */ - /* Ignoring casts, the expression is equal to (w * bpp + 7) / 8 + 1, but avoids overflow of w * bpp */ - size_t line = ((size_t)(w / 8u) * bpp) + 1u + ((w & 7u) * bpp + 7u) / 8u; - return (size_t)h * line; -} - -#ifdef LODEPNG_COMPILE_DECODER -/*Safely checks whether size_t overflow can be caused due to amount of pixels. -This check is overcautious rather than precise. If this check indicates no overflow, -you can safely compute in a size_t (but not an unsigned): --(size_t)w * (size_t)h * 8 --amount of bytes in IDAT (including filter, padding and Adam7 bytes) --amount of bytes in raw color model -Returns 1 if overflow possible, 0 if not. -*/ -static int lodepng_pixel_overflow(unsigned w, unsigned h, - const LodePNGColorMode* pngcolor, const LodePNGColorMode* rawcolor) { - size_t bpp = LODEPNG_MAX(lodepng_get_bpp(pngcolor), lodepng_get_bpp(rawcolor)); - size_t numpixels, total; - size_t line; /* bytes per line in worst case */ - - if(lodepng_mulofl((size_t)w, (size_t)h, &numpixels)) return 1; - if(lodepng_mulofl(numpixels, 8, &total)) return 1; /* bit pointer with 8-bit color, or 8 bytes per channel color */ - - /* Bytes per scanline with the expression "(w / 8u) * bpp) + ((w & 7u) * bpp + 7u) / 8u" */ - if(lodepng_mulofl((size_t)(w / 8u), bpp, &line)) return 1; - if(lodepng_addofl(line, ((w & 7u) * bpp + 7u) / 8u, &line)) return 1; - - if(lodepng_addofl(line, 5, &line)) return 1; /* 5 bytes overhead per line: 1 filterbyte, 4 for Adam7 worst case */ - if(lodepng_mulofl(line, h, &total)) return 1; /* Total bytes in worst case */ - - return 0; /* no overflow */ -} -#endif /*LODEPNG_COMPILE_DECODER*/ -#endif /*LODEPNG_COMPILE_PNG*/ - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - -static void LodePNGUnknownChunks_init(LodePNGInfo* info) { - unsigned i; - for(i = 0; i != 3; ++i) info->unknown_chunks_data[i] = 0; - for(i = 0; i != 3; ++i) info->unknown_chunks_size[i] = 0; -} - -static void LodePNGUnknownChunks_cleanup(LodePNGInfo* info) { - unsigned i; - for(i = 0; i != 3; ++i) lodepng_free(info->unknown_chunks_data[i]); -} - -static unsigned LodePNGUnknownChunks_copy(LodePNGInfo* dest, const LodePNGInfo* src) { - unsigned i; - - LodePNGUnknownChunks_cleanup(dest); - - for(i = 0; i != 3; ++i) { - size_t j; - dest->unknown_chunks_size[i] = src->unknown_chunks_size[i]; - dest->unknown_chunks_data[i] = (unsigned char*)lodepng_malloc(src->unknown_chunks_size[i]); - if(!dest->unknown_chunks_data[i] && dest->unknown_chunks_size[i]) return 83; /*alloc fail*/ - for(j = 0; j < src->unknown_chunks_size[i]; ++j) { - dest->unknown_chunks_data[i][j] = src->unknown_chunks_data[i][j]; - } - } - - return 0; -} - -/******************************************************************************/ - -static void LodePNGText_init(LodePNGInfo* info) { - info->text_num = 0; - info->text_keys = NULL; - info->text_strings = NULL; -} - -static void LodePNGText_cleanup(LodePNGInfo* info) { - size_t i; - for(i = 0; i != info->text_num; ++i) { - string_cleanup(&info->text_keys[i]); - string_cleanup(&info->text_strings[i]); - } - lodepng_free(info->text_keys); - lodepng_free(info->text_strings); -} - -static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) { - size_t i = 0; - dest->text_keys = NULL; - dest->text_strings = NULL; - dest->text_num = 0; - for(i = 0; i != source->text_num; ++i) { - CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i])); - } - return 0; -} - -static unsigned lodepng_add_text_sized(LodePNGInfo* info, const char* key, const char* str, size_t size) { - char** new_keys = (char**)(lodepng_realloc(info->text_keys, sizeof(char*) * (info->text_num + 1))); - char** new_strings = (char**)(lodepng_realloc(info->text_strings, sizeof(char*) * (info->text_num + 1))); - - if(new_keys) info->text_keys = new_keys; - if(new_strings) info->text_strings = new_strings; - - if(!new_keys || !new_strings) return 83; /*alloc fail*/ - - ++info->text_num; - info->text_keys[info->text_num - 1] = alloc_string(key); - info->text_strings[info->text_num - 1] = alloc_string_sized(str, size); - if(!info->text_keys[info->text_num - 1] || !info->text_strings[info->text_num - 1]) return 83; /*alloc fail*/ - - return 0; -} - -unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str) { - return lodepng_add_text_sized(info, key, str, lodepng_strlen(str)); -} - -void lodepng_clear_text(LodePNGInfo* info) { - LodePNGText_cleanup(info); -} - -/******************************************************************************/ - -static void LodePNGIText_init(LodePNGInfo* info) { - info->itext_num = 0; - info->itext_keys = NULL; - info->itext_langtags = NULL; - info->itext_transkeys = NULL; - info->itext_strings = NULL; -} - -static void LodePNGIText_cleanup(LodePNGInfo* info) { - size_t i; - for(i = 0; i != info->itext_num; ++i) { - string_cleanup(&info->itext_keys[i]); - string_cleanup(&info->itext_langtags[i]); - string_cleanup(&info->itext_transkeys[i]); - string_cleanup(&info->itext_strings[i]); - } - lodepng_free(info->itext_keys); - lodepng_free(info->itext_langtags); - lodepng_free(info->itext_transkeys); - lodepng_free(info->itext_strings); -} - -static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) { - size_t i = 0; - dest->itext_keys = NULL; - dest->itext_langtags = NULL; - dest->itext_transkeys = NULL; - dest->itext_strings = NULL; - dest->itext_num = 0; - for(i = 0; i != source->itext_num; ++i) { - CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i], - source->itext_transkeys[i], source->itext_strings[i])); - } - return 0; -} - -void lodepng_clear_itext(LodePNGInfo* info) { - LodePNGIText_cleanup(info); -} - -static unsigned lodepng_add_itext_sized(LodePNGInfo* info, const char* key, const char* langtag, - const char* transkey, const char* str, size_t size) { - char** new_keys = (char**)(lodepng_realloc(info->itext_keys, sizeof(char*) * (info->itext_num + 1))); - char** new_langtags = (char**)(lodepng_realloc(info->itext_langtags, sizeof(char*) * (info->itext_num + 1))); - char** new_transkeys = (char**)(lodepng_realloc(info->itext_transkeys, sizeof(char*) * (info->itext_num + 1))); - char** new_strings = (char**)(lodepng_realloc(info->itext_strings, sizeof(char*) * (info->itext_num + 1))); - - if(new_keys) info->itext_keys = new_keys; - if(new_langtags) info->itext_langtags = new_langtags; - if(new_transkeys) info->itext_transkeys = new_transkeys; - if(new_strings) info->itext_strings = new_strings; - - if(!new_keys || !new_langtags || !new_transkeys || !new_strings) return 83; /*alloc fail*/ - - ++info->itext_num; - - info->itext_keys[info->itext_num - 1] = alloc_string(key); - info->itext_langtags[info->itext_num - 1] = alloc_string(langtag); - info->itext_transkeys[info->itext_num - 1] = alloc_string(transkey); - info->itext_strings[info->itext_num - 1] = alloc_string_sized(str, size); - - return 0; -} - -unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag, - const char* transkey, const char* str) { - return lodepng_add_itext_sized(info, key, langtag, transkey, str, lodepng_strlen(str)); -} - -/* same as set but does not delete */ -static unsigned lodepng_assign_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) { - if(profile_size == 0) return 100; /*invalid ICC profile size*/ - - info->iccp_name = alloc_string(name); - info->iccp_profile = (unsigned char*)lodepng_malloc(profile_size); - - if(!info->iccp_name || !info->iccp_profile) return 83; /*alloc fail*/ - - lodepng_memcpy(info->iccp_profile, profile, profile_size); - info->iccp_profile_size = profile_size; - - return 0; /*ok*/ -} - -unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) { - if(info->iccp_name) lodepng_clear_icc(info); - info->iccp_defined = 1; - - return lodepng_assign_icc(info, name, profile, profile_size); -} - -void lodepng_clear_icc(LodePNGInfo* info) { - string_cleanup(&info->iccp_name); - lodepng_free(info->iccp_profile); - info->iccp_profile = NULL; - info->iccp_profile_size = 0; - info->iccp_defined = 0; -} -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -void lodepng_info_init(LodePNGInfo* info) { - lodepng_color_mode_init(&info->color); - info->interlace_method = 0; - info->compression_method = 0; - info->filter_method = 0; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - info->background_defined = 0; - info->background_r = info->background_g = info->background_b = 0; - - LodePNGText_init(info); - LodePNGIText_init(info); - - info->time_defined = 0; - info->phys_defined = 0; - - info->gama_defined = 0; - info->chrm_defined = 0; - info->srgb_defined = 0; - info->iccp_defined = 0; - info->iccp_name = NULL; - info->iccp_profile = NULL; - - LodePNGUnknownChunks_init(info); -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -} - -void lodepng_info_cleanup(LodePNGInfo* info) { - lodepng_color_mode_cleanup(&info->color); -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - LodePNGText_cleanup(info); - LodePNGIText_cleanup(info); - - lodepng_clear_icc(info); - - LodePNGUnknownChunks_cleanup(info); -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -} - -unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source) { - lodepng_info_cleanup(dest); - lodepng_memcpy(dest, source, sizeof(LodePNGInfo)); - lodepng_color_mode_init(&dest->color); - CERROR_TRY_RETURN(lodepng_color_mode_copy(&dest->color, &source->color)); - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - CERROR_TRY_RETURN(LodePNGText_copy(dest, source)); - CERROR_TRY_RETURN(LodePNGIText_copy(dest, source)); - if(source->iccp_defined) { - CERROR_TRY_RETURN(lodepng_assign_icc(dest, source->iccp_name, source->iccp_profile, source->iccp_profile_size)); - } - - LodePNGUnknownChunks_init(dest); - CERROR_TRY_RETURN(LodePNGUnknownChunks_copy(dest, source)); -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - return 0; -} - -/* ////////////////////////////////////////////////////////////////////////// */ - -/*index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to*/ -static void addColorBits(unsigned char* out, size_t index, unsigned bits, unsigned in) { - unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/ - /*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/ - unsigned p = index & m; - in &= (1u << bits) - 1u; /*filter out any other bits of the input value*/ - in = in << (bits * (m - p)); - if(p == 0) out[index * bits / 8u] = in; - else out[index * bits / 8u] |= in; -} - -typedef struct ColorTree ColorTree; - -/* -One node of a color tree -This is the data structure used to count the number of unique colors and to get a palette -index for a color. It's like an octree, but because the alpha channel is used too, each -node has 16 instead of 8 children. -*/ -struct ColorTree { - ColorTree* children[16]; /*up to 16 pointers to ColorTree of next level*/ - int index; /*the payload. Only has a meaningful value if this is in the last level*/ -}; - -static void color_tree_init(ColorTree* tree) { - lodepng_memset(tree->children, 0, 16 * sizeof(*tree->children)); - tree->index = -1; -} - -static void color_tree_cleanup(ColorTree* tree) { - int i; - for(i = 0; i != 16; ++i) { - if(tree->children[i]) { - color_tree_cleanup(tree->children[i]); - lodepng_free(tree->children[i]); - } - } -} - -/*returns -1 if color not present, its index otherwise*/ -static int color_tree_get(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) { - int bit = 0; - for(bit = 0; bit < 8; ++bit) { - int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); - if(!tree->children[i]) return -1; - else tree = tree->children[i]; - } - return tree ? tree->index : -1; -} - -#ifdef LODEPNG_COMPILE_ENCODER -static int color_tree_has(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) { - return color_tree_get(tree, r, g, b, a) >= 0; -} -#endif /*LODEPNG_COMPILE_ENCODER*/ - -/*color is not allowed to already exist. -Index should be >= 0 (it's signed to be compatible with using -1 for "doesn't exist") -Returns error code, or 0 if ok*/ -static unsigned color_tree_add(ColorTree* tree, - unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned index) { - int bit; - for(bit = 0; bit < 8; ++bit) { - int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); - if(!tree->children[i]) { - tree->children[i] = (ColorTree*)lodepng_malloc(sizeof(ColorTree)); - if(!tree->children[i]) return 83; /*alloc fail*/ - color_tree_init(tree->children[i]); - } - tree = tree->children[i]; - } - tree->index = (int)index; - return 0; -} - -/*put a pixel, given its RGBA color, into image of any color type*/ -static unsigned rgba8ToPixel(unsigned char* out, size_t i, - const LodePNGColorMode* mode, ColorTree* tree /*for palette*/, - unsigned char r, unsigned char g, unsigned char b, unsigned char a) { - if(mode->colortype == LCT_GREY) { - unsigned char gray = r; /*((unsigned short)r + g + b) / 3u;*/ - if(mode->bitdepth == 8) out[i] = gray; - else if(mode->bitdepth == 16) out[i * 2 + 0] = out[i * 2 + 1] = gray; - else { - /*take the most significant bits of gray*/ - gray = ((unsigned)gray >> (8u - mode->bitdepth)) & ((1u << mode->bitdepth) - 1u); - addColorBits(out, i, mode->bitdepth, gray); - } - } else if(mode->colortype == LCT_RGB) { - if(mode->bitdepth == 8) { - out[i * 3 + 0] = r; - out[i * 3 + 1] = g; - out[i * 3 + 2] = b; - } else { - out[i * 6 + 0] = out[i * 6 + 1] = r; - out[i * 6 + 2] = out[i * 6 + 3] = g; - out[i * 6 + 4] = out[i * 6 + 5] = b; - } - } else if(mode->colortype == LCT_PALETTE) { - int index = color_tree_get(tree, r, g, b, a); - if(index < 0) return 82; /*color not in palette*/ - if(mode->bitdepth == 8) out[i] = index; - else addColorBits(out, i, mode->bitdepth, (unsigned)index); - } else if(mode->colortype == LCT_GREY_ALPHA) { - unsigned char gray = r; /*((unsigned short)r + g + b) / 3u;*/ - if(mode->bitdepth == 8) { - out[i * 2 + 0] = gray; - out[i * 2 + 1] = a; - } else if(mode->bitdepth == 16) { - out[i * 4 + 0] = out[i * 4 + 1] = gray; - out[i * 4 + 2] = out[i * 4 + 3] = a; - } - } else if(mode->colortype == LCT_RGBA) { - if(mode->bitdepth == 8) { - out[i * 4 + 0] = r; - out[i * 4 + 1] = g; - out[i * 4 + 2] = b; - out[i * 4 + 3] = a; - } else { - out[i * 8 + 0] = out[i * 8 + 1] = r; - out[i * 8 + 2] = out[i * 8 + 3] = g; - out[i * 8 + 4] = out[i * 8 + 5] = b; - out[i * 8 + 6] = out[i * 8 + 7] = a; - } - } - - return 0; /*no error*/ -} - -/*put a pixel, given its RGBA16 color, into image of any color 16-bitdepth type*/ -static void rgba16ToPixel(unsigned char* out, size_t i, - const LodePNGColorMode* mode, - unsigned short r, unsigned short g, unsigned short b, unsigned short a) { - if(mode->colortype == LCT_GREY) { - unsigned short gray = r; /*((unsigned)r + g + b) / 3u;*/ - out[i * 2 + 0] = (gray >> 8) & 255; - out[i * 2 + 1] = gray & 255; - } else if(mode->colortype == LCT_RGB) { - out[i * 6 + 0] = (r >> 8) & 255; - out[i * 6 + 1] = r & 255; - out[i * 6 + 2] = (g >> 8) & 255; - out[i * 6 + 3] = g & 255; - out[i * 6 + 4] = (b >> 8) & 255; - out[i * 6 + 5] = b & 255; - } else if(mode->colortype == LCT_GREY_ALPHA) { - unsigned short gray = r; /*((unsigned)r + g + b) / 3u;*/ - out[i * 4 + 0] = (gray >> 8) & 255; - out[i * 4 + 1] = gray & 255; - out[i * 4 + 2] = (a >> 8) & 255; - out[i * 4 + 3] = a & 255; - } else if(mode->colortype == LCT_RGBA) { - out[i * 8 + 0] = (r >> 8) & 255; - out[i * 8 + 1] = r & 255; - out[i * 8 + 2] = (g >> 8) & 255; - out[i * 8 + 3] = g & 255; - out[i * 8 + 4] = (b >> 8) & 255; - out[i * 8 + 5] = b & 255; - out[i * 8 + 6] = (a >> 8) & 255; - out[i * 8 + 7] = a & 255; - } -} - -/*Get RGBA8 color of pixel with index i (y * width + x) from the raw image with given color type.*/ -static void getPixelColorRGBA8(unsigned char* r, unsigned char* g, - unsigned char* b, unsigned char* a, - const unsigned char* in, size_t i, - const LodePNGColorMode* mode) { - if(mode->colortype == LCT_GREY) { - if(mode->bitdepth == 8) { - *r = *g = *b = in[i]; - if(mode->key_defined && *r == mode->key_r) *a = 0; - else *a = 255; - } else if(mode->bitdepth == 16) { - *r = *g = *b = in[i * 2 + 0]; - if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; - else *a = 255; - } else { - unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ - size_t j = i * mode->bitdepth; - unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); - *r = *g = *b = (value * 255) / highest; - if(mode->key_defined && value == mode->key_r) *a = 0; - else *a = 255; - } - } else if(mode->colortype == LCT_RGB) { - if(mode->bitdepth == 8) { - *r = in[i * 3 + 0]; *g = in[i * 3 + 1]; *b = in[i * 3 + 2]; - if(mode->key_defined && *r == mode->key_r && *g == mode->key_g && *b == mode->key_b) *a = 0; - else *a = 255; - } else { - *r = in[i * 6 + 0]; - *g = in[i * 6 + 2]; - *b = in[i * 6 + 4]; - if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r - && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g - && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; - else *a = 255; - } - } else if(mode->colortype == LCT_PALETTE) { - unsigned index; - if(mode->bitdepth == 8) index = in[i]; - else { - size_t j = i * mode->bitdepth; - index = readBitsFromReversedStream(&j, in, mode->bitdepth); - } - /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ - *r = mode->palette[index * 4 + 0]; - *g = mode->palette[index * 4 + 1]; - *b = mode->palette[index * 4 + 2]; - *a = mode->palette[index * 4 + 3]; - } else if(mode->colortype == LCT_GREY_ALPHA) { - if(mode->bitdepth == 8) { - *r = *g = *b = in[i * 2 + 0]; - *a = in[i * 2 + 1]; - } else { - *r = *g = *b = in[i * 4 + 0]; - *a = in[i * 4 + 2]; - } - } else if(mode->colortype == LCT_RGBA) { - if(mode->bitdepth == 8) { - *r = in[i * 4 + 0]; - *g = in[i * 4 + 1]; - *b = in[i * 4 + 2]; - *a = in[i * 4 + 3]; - } else { - *r = in[i * 8 + 0]; - *g = in[i * 8 + 2]; - *b = in[i * 8 + 4]; - *a = in[i * 8 + 6]; - } - } -} - -/*Similar to getPixelColorRGBA8, but with all the for loops inside of the color -mode test cases, optimized to convert the colors much faster, when converting -to the common case of RGBA with 8 bit per channel. buffer must be RGBA with -enough memory.*/ -static void getPixelColorsRGBA8(unsigned char* LODEPNG_RESTRICT buffer, size_t numpixels, - const unsigned char* LODEPNG_RESTRICT in, - const LodePNGColorMode* mode) { - unsigned num_channels = 4; - size_t i; - if(mode->colortype == LCT_GREY) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i]; - buffer[3] = 255; - } - if(mode->key_defined) { - buffer -= numpixels * num_channels; - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - if(buffer[0] == mode->key_r) buffer[3] = 0; - } - } - } else if(mode->bitdepth == 16) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i * 2]; - buffer[3] = mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r ? 0 : 255; - } - } else { - unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ - size_t j = 0; - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); - buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest; - buffer[3] = mode->key_defined && value == mode->key_r ? 0 : 255; - } - } - } else if(mode->colortype == LCT_RGB) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - lodepng_memcpy(buffer, &in[i * 3], 3); - buffer[3] = 255; - } - if(mode->key_defined) { - buffer -= numpixels * num_channels; - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - if(buffer[0] == mode->key_r && buffer[1]== mode->key_g && buffer[2] == mode->key_b) buffer[3] = 0; - } - } - } else { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = in[i * 6 + 0]; - buffer[1] = in[i * 6 + 2]; - buffer[2] = in[i * 6 + 4]; - buffer[3] = mode->key_defined - && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r - && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g - && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b ? 0 : 255; - } - } - } else if(mode->colortype == LCT_PALETTE) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - unsigned index = in[i]; - /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ - lodepng_memcpy(buffer, &mode->palette[index * 4], 4); - } - } else { - size_t j = 0; - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - unsigned index = readBitsFromReversedStream(&j, in, mode->bitdepth); - /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ - lodepng_memcpy(buffer, &mode->palette[index * 4], 4); - } - } - } else if(mode->colortype == LCT_GREY_ALPHA) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0]; - buffer[3] = in[i * 2 + 1]; - } - } else { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0]; - buffer[3] = in[i * 4 + 2]; - } - } - } else if(mode->colortype == LCT_RGBA) { - if(mode->bitdepth == 8) { - lodepng_memcpy(buffer, in, numpixels * 4); - } else { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = in[i * 8 + 0]; - buffer[1] = in[i * 8 + 2]; - buffer[2] = in[i * 8 + 4]; - buffer[3] = in[i * 8 + 6]; - } - } - } -} - -/*Similar to getPixelColorsRGBA8, but with 3-channel RGB output.*/ -static void getPixelColorsRGB8(unsigned char* LODEPNG_RESTRICT buffer, size_t numpixels, - const unsigned char* LODEPNG_RESTRICT in, - const LodePNGColorMode* mode) { - const unsigned num_channels = 3; - size_t i; - if(mode->colortype == LCT_GREY) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i]; - } - } else if(mode->bitdepth == 16) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i * 2]; - } - } else { - unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ - size_t j = 0; - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); - buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest; - } - } - } else if(mode->colortype == LCT_RGB) { - if(mode->bitdepth == 8) { - lodepng_memcpy(buffer, in, numpixels * 3); - } else { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = in[i * 6 + 0]; - buffer[1] = in[i * 6 + 2]; - buffer[2] = in[i * 6 + 4]; - } - } - } else if(mode->colortype == LCT_PALETTE) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - unsigned index = in[i]; - /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ - lodepng_memcpy(buffer, &mode->palette[index * 4], 3); - } - } else { - size_t j = 0; - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - unsigned index = readBitsFromReversedStream(&j, in, mode->bitdepth); - /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ - lodepng_memcpy(buffer, &mode->palette[index * 4], 3); - } - } - } else if(mode->colortype == LCT_GREY_ALPHA) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0]; - } - } else { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0]; - } - } - } else if(mode->colortype == LCT_RGBA) { - if(mode->bitdepth == 8) { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - lodepng_memcpy(buffer, &in[i * 4], 3); - } - } else { - for(i = 0; i != numpixels; ++i, buffer += num_channels) { - buffer[0] = in[i * 8 + 0]; - buffer[1] = in[i * 8 + 2]; - buffer[2] = in[i * 8 + 4]; - } - } - } -} - -/*Get RGBA16 color of pixel with index i (y * width + x) from the raw image with -given color type, but the given color type must be 16-bit itself.*/ -static void getPixelColorRGBA16(unsigned short* r, unsigned short* g, unsigned short* b, unsigned short* a, - const unsigned char* in, size_t i, const LodePNGColorMode* mode) { - if(mode->colortype == LCT_GREY) { - *r = *g = *b = 256 * in[i * 2 + 0] + in[i * 2 + 1]; - if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; - else *a = 65535; - } else if(mode->colortype == LCT_RGB) { - *r = 256u * in[i * 6 + 0] + in[i * 6 + 1]; - *g = 256u * in[i * 6 + 2] + in[i * 6 + 3]; - *b = 256u * in[i * 6 + 4] + in[i * 6 + 5]; - if(mode->key_defined - && 256u * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r - && 256u * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g - && 256u * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; - else *a = 65535; - } else if(mode->colortype == LCT_GREY_ALPHA) { - *r = *g = *b = 256u * in[i * 4 + 0] + in[i * 4 + 1]; - *a = 256u * in[i * 4 + 2] + in[i * 4 + 3]; - } else if(mode->colortype == LCT_RGBA) { - *r = 256u * in[i * 8 + 0] + in[i * 8 + 1]; - *g = 256u * in[i * 8 + 2] + in[i * 8 + 3]; - *b = 256u * in[i * 8 + 4] + in[i * 8 + 5]; - *a = 256u * in[i * 8 + 6] + in[i * 8 + 7]; - } -} - -unsigned lodepng_convert(unsigned char* out, const unsigned char* in, - const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, - unsigned w, unsigned h) { - size_t i; - ColorTree tree; - size_t numpixels = (size_t)w * (size_t)h; - unsigned error = 0; - - if(mode_in->colortype == LCT_PALETTE && !mode_in->palette) { - return 107; /* error: must provide palette if input mode is palette */ - } - - if(lodepng_color_mode_equal(mode_out, mode_in)) { - size_t numbytes = lodepng_get_raw_size(w, h, mode_in); - lodepng_memcpy(out, in, numbytes); - return 0; - } - - if(mode_out->colortype == LCT_PALETTE) { - size_t palettesize = mode_out->palettesize; - const unsigned char* palette = mode_out->palette; - size_t palsize = (size_t)1u << mode_out->bitdepth; - /*if the user specified output palette but did not give the values, assume - they want the values of the input color type (assuming that one is palette). - Note that we never create a new palette ourselves.*/ - if(palettesize == 0) { - palettesize = mode_in->palettesize; - palette = mode_in->palette; - /*if the input was also palette with same bitdepth, then the color types are also - equal, so copy literally. This to preserve the exact indices that were in the PNG - even in case there are duplicate colors in the palette.*/ - if(mode_in->colortype == LCT_PALETTE && mode_in->bitdepth == mode_out->bitdepth) { - size_t numbytes = lodepng_get_raw_size(w, h, mode_in); - lodepng_memcpy(out, in, numbytes); - return 0; - } - } - if(palettesize < palsize) palsize = palettesize; - color_tree_init(&tree); - for(i = 0; i != palsize; ++i) { - const unsigned char* p = &palette[i * 4]; - error = color_tree_add(&tree, p[0], p[1], p[2], p[3], (unsigned)i); - if(error) break; - } - } - - if(!error) { - if(mode_in->bitdepth == 16 && mode_out->bitdepth == 16) { - for(i = 0; i != numpixels; ++i) { - unsigned short r = 0, g = 0, b = 0, a = 0; - getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); - rgba16ToPixel(out, i, mode_out, r, g, b, a); - } - } else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGBA) { - getPixelColorsRGBA8(out, numpixels, in, mode_in); - } else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGB) { - getPixelColorsRGB8(out, numpixels, in, mode_in); - } else { - unsigned char r = 0, g = 0, b = 0, a = 0; - for(i = 0; i != numpixels; ++i) { - getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); - error = rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a); - if(error) break; - } - } - } - - if(mode_out->colortype == LCT_PALETTE) { - color_tree_cleanup(&tree); - } - - return error; -} - - -/* Converts a single rgb color without alpha from one type to another, color bits truncated to -their bitdepth. In case of single channel (gray or palette), only the r channel is used. Slow -function, do not use to process all pixels of an image. Alpha channel not supported on purpose: -this is for bKGD, supporting alpha may prevent it from finding a color in the palette, from the -specification it looks like bKGD should ignore the alpha values of the palette since it can use -any palette index but doesn't have an alpha channel. Idem with ignoring color key. */ -static unsigned lodepng_convert_rgb( - unsigned* r_out, unsigned* g_out, unsigned* b_out, - unsigned r_in, unsigned g_in, unsigned b_in, - const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in) { - unsigned r = 0, g = 0, b = 0; - unsigned mul = 65535 / ((1u << mode_in->bitdepth) - 1u); /*65535, 21845, 4369, 257, 1*/ - unsigned shift = 16 - mode_out->bitdepth; - - if(mode_in->colortype == LCT_GREY || mode_in->colortype == LCT_GREY_ALPHA) { - r = g = b = r_in * mul; - } else if(mode_in->colortype == LCT_RGB || mode_in->colortype == LCT_RGBA) { - r = r_in * mul; - g = g_in * mul; - b = b_in * mul; - } else if(mode_in->colortype == LCT_PALETTE) { - if(r_in >= mode_in->palettesize) return 82; - r = mode_in->palette[r_in * 4 + 0] * 257u; - g = mode_in->palette[r_in * 4 + 1] * 257u; - b = mode_in->palette[r_in * 4 + 2] * 257u; - } else { - return 31; - } - - /* now convert to output format */ - if(mode_out->colortype == LCT_GREY || mode_out->colortype == LCT_GREY_ALPHA) { - *r_out = r >> shift ; - } else if(mode_out->colortype == LCT_RGB || mode_out->colortype == LCT_RGBA) { - *r_out = r >> shift ; - *g_out = g >> shift ; - *b_out = b >> shift ; - } else if(mode_out->colortype == LCT_PALETTE) { - unsigned i; - /* a 16-bit color cannot be in the palette */ - if((r >> 8) != (r & 255) || (g >> 8) != (g & 255) || (b >> 8) != (b & 255)) return 82; - for(i = 0; i < mode_out->palettesize; i++) { - unsigned j = i * 4; - if((r >> 8) == mode_out->palette[j + 0] && (g >> 8) == mode_out->palette[j + 1] && - (b >> 8) == mode_out->palette[j + 2]) { - *r_out = i; - return 0; - } - } - return 82; - } else { - return 31; - } - - return 0; -} - -#ifdef LODEPNG_COMPILE_ENCODER - -void lodepng_color_stats_init(LodePNGColorStats* stats) { - /*stats*/ - stats->colored = 0; - stats->key = 0; - stats->key_r = stats->key_g = stats->key_b = 0; - stats->alpha = 0; - stats->numcolors = 0; - stats->bits = 1; - stats->numpixels = 0; - /*settings*/ - stats->allow_palette = 1; - stats->allow_greyscale = 1; -} - -/*function used for debug purposes with C++*/ -/*void printColorStats(LodePNGColorStats* p) { - std::cout << "colored: " << (int)p->colored << ", "; - std::cout << "key: " << (int)p->key << ", "; - std::cout << "key_r: " << (int)p->key_r << ", "; - std::cout << "key_g: " << (int)p->key_g << ", "; - std::cout << "key_b: " << (int)p->key_b << ", "; - std::cout << "alpha: " << (int)p->alpha << ", "; - std::cout << "numcolors: " << (int)p->numcolors << ", "; - std::cout << "bits: " << (int)p->bits << std::endl; -}*/ - -/*Returns how many bits needed to represent given value (max 8 bit)*/ -static unsigned getValueRequiredBits(unsigned char value) { - if(value == 0 || value == 255) return 1; - /*The scaling of 2-bit and 4-bit values uses multiples of 85 and 17*/ - if(value % 17 == 0) return value % 85 == 0 ? 2 : 4; - return 8; -} - -/*stats must already have been inited. */ -unsigned lodepng_compute_color_stats(LodePNGColorStats* stats, - const unsigned char* in, unsigned w, unsigned h, - const LodePNGColorMode* mode_in) { - size_t i; - ColorTree tree; - size_t numpixels = (size_t)w * (size_t)h; - unsigned error = 0; - - /* mark things as done already if it would be impossible to have a more expensive case */ - unsigned colored_done = lodepng_is_greyscale_type(mode_in) ? 1 : 0; - unsigned alpha_done = lodepng_can_have_alpha(mode_in) ? 0 : 1; - unsigned numcolors_done = 0; - unsigned bpp = lodepng_get_bpp(mode_in); - unsigned bits_done = (stats->bits == 1 && bpp == 1) ? 1 : 0; - unsigned sixteen = 0; /* whether the input image is 16 bit */ - unsigned maxnumcolors = 257; - if(bpp <= 8) maxnumcolors = LODEPNG_MIN(257, stats->numcolors + (1u << bpp)); - - stats->numpixels += numpixels; - - /*if palette not allowed, no need to compute numcolors*/ - if(!stats->allow_palette) numcolors_done = 1; - - color_tree_init(&tree); - - /*If the stats was already filled in from previous data, fill its palette in tree - and mark things as done already if we know they are the most expensive case already*/ - if(stats->alpha) alpha_done = 1; - if(stats->colored) colored_done = 1; - if(stats->bits == 16) numcolors_done = 1; - if(stats->bits >= bpp) bits_done = 1; - if(stats->numcolors >= maxnumcolors) numcolors_done = 1; - - if(!numcolors_done) { - for(i = 0; i < stats->numcolors; i++) { - const unsigned char* color = &stats->palette[i * 4]; - error = color_tree_add(&tree, color[0], color[1], color[2], color[3], i); - if(error) goto cleanup; - } - } - - /*Check if the 16-bit input is truly 16-bit*/ - if(mode_in->bitdepth == 16 && !sixteen) { - unsigned short r = 0, g = 0, b = 0, a = 0; - for(i = 0; i != numpixels; ++i) { - getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); - if((r & 255) != ((r >> 8) & 255) || (g & 255) != ((g >> 8) & 255) || - (b & 255) != ((b >> 8) & 255) || (a & 255) != ((a >> 8) & 255)) /*first and second byte differ*/ { - stats->bits = 16; - sixteen = 1; - bits_done = 1; - numcolors_done = 1; /*counting colors no longer useful, palette doesn't support 16-bit*/ - break; - } - } - } - - if(sixteen) { - unsigned short r = 0, g = 0, b = 0, a = 0; - - for(i = 0; i != numpixels; ++i) { - getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); - - if(!colored_done && (r != g || r != b)) { - stats->colored = 1; - colored_done = 1; - } - - if(!alpha_done) { - unsigned matchkey = (r == stats->key_r && g == stats->key_g && b == stats->key_b); - if(a != 65535 && (a != 0 || (stats->key && !matchkey))) { - stats->alpha = 1; - stats->key = 0; - alpha_done = 1; - } else if(a == 0 && !stats->alpha && !stats->key) { - stats->key = 1; - stats->key_r = r; - stats->key_g = g; - stats->key_b = b; - } else if(a == 65535 && stats->key && matchkey) { - /* Color key cannot be used if an opaque pixel also has that RGB color. */ - stats->alpha = 1; - stats->key = 0; - alpha_done = 1; - } - } - if(alpha_done && numcolors_done && colored_done && bits_done) break; - } - - if(stats->key && !stats->alpha) { - for(i = 0; i != numpixels; ++i) { - getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); - if(a != 0 && r == stats->key_r && g == stats->key_g && b == stats->key_b) { - /* Color key cannot be used if an opaque pixel also has that RGB color. */ - stats->alpha = 1; - stats->key = 0; - alpha_done = 1; - } - } - } - } else /* < 16-bit */ { - unsigned char r = 0, g = 0, b = 0, a = 0; - for(i = 0; i != numpixels; ++i) { - getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); - - if(!bits_done && stats->bits < 8) { - /*only r is checked, < 8 bits is only relevant for grayscale*/ - unsigned bits = getValueRequiredBits(r); - if(bits > stats->bits) stats->bits = bits; - } - bits_done = (stats->bits >= bpp); - - if(!colored_done && (r != g || r != b)) { - stats->colored = 1; - colored_done = 1; - if(stats->bits < 8) stats->bits = 8; /*PNG has no colored modes with less than 8-bit per channel*/ - } - - if(!alpha_done) { - unsigned matchkey = (r == stats->key_r && g == stats->key_g && b == stats->key_b); - if(a != 255 && (a != 0 || (stats->key && !matchkey))) { - stats->alpha = 1; - stats->key = 0; - alpha_done = 1; - if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ - } else if(a == 0 && !stats->alpha && !stats->key) { - stats->key = 1; - stats->key_r = r; - stats->key_g = g; - stats->key_b = b; - } else if(a == 255 && stats->key && matchkey) { - /* Color key cannot be used if an opaque pixel also has that RGB color. */ - stats->alpha = 1; - stats->key = 0; - alpha_done = 1; - if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ - } - } - - if(!numcolors_done) { - if(!color_tree_has(&tree, r, g, b, a)) { - error = color_tree_add(&tree, r, g, b, a, stats->numcolors); - if(error) goto cleanup; - if(stats->numcolors < 256) { - unsigned char* p = stats->palette; - unsigned n = stats->numcolors; - p[n * 4 + 0] = r; - p[n * 4 + 1] = g; - p[n * 4 + 2] = b; - p[n * 4 + 3] = a; - } - ++stats->numcolors; - numcolors_done = stats->numcolors >= maxnumcolors; - } - } - - if(alpha_done && numcolors_done && colored_done && bits_done) break; - } - - if(stats->key && !stats->alpha) { - for(i = 0; i != numpixels; ++i) { - getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); - if(a != 0 && r == stats->key_r && g == stats->key_g && b == stats->key_b) { - /* Color key cannot be used if an opaque pixel also has that RGB color. */ - stats->alpha = 1; - stats->key = 0; - alpha_done = 1; - if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ - } - } - } - - /*make the stats's key always 16-bit for consistency - repeat each byte twice*/ - stats->key_r += (stats->key_r << 8); - stats->key_g += (stats->key_g << 8); - stats->key_b += (stats->key_b << 8); - } - -cleanup: - color_tree_cleanup(&tree); - return error; -} - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS -/*Adds a single color to the color stats. The stats must already have been inited. The color must be given as 16-bit -(with 2 bytes repeating for 8-bit and 65535 for opaque alpha channel). This function is expensive, do not call it for -all pixels of an image but only for a few additional values. */ -static unsigned lodepng_color_stats_add(LodePNGColorStats* stats, - unsigned r, unsigned g, unsigned b, unsigned a) { - unsigned error = 0; - unsigned char image[8]; - LodePNGColorMode mode; - lodepng_color_mode_init(&mode); - image[0] = r >> 8; image[1] = r; image[2] = g >> 8; image[3] = g; - image[4] = b >> 8; image[5] = b; image[6] = a >> 8; image[7] = a; - mode.bitdepth = 16; - mode.colortype = LCT_RGBA; - error = lodepng_compute_color_stats(stats, image, 1, 1, &mode); - lodepng_color_mode_cleanup(&mode); - return error; -} -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -/*Computes a minimal PNG color model that can contain all colors as indicated by the stats. -The stats should be computed with lodepng_compute_color_stats. -mode_in is raw color profile of the image the stats were computed on, to copy palette order from when relevant. -Minimal PNG color model means the color type and bit depth that gives smallest amount of bits in the output image, -e.g. gray if only grayscale pixels, palette if less than 256 colors, color key if only single transparent color, ... -This is used if auto_convert is enabled (it is by default). -*/ -static unsigned auto_choose_color(LodePNGColorMode* mode_out, - const LodePNGColorMode* mode_in, - const LodePNGColorStats* stats) { - unsigned error = 0; - unsigned palettebits; - size_t i, n; - size_t numpixels = stats->numpixels; - unsigned palette_ok, gray_ok; - - unsigned alpha = stats->alpha; - unsigned key = stats->key; - unsigned bits = stats->bits; - - mode_out->key_defined = 0; - - if(key && numpixels <= 16) { - alpha = 1; /*too few pixels to justify tRNS chunk overhead*/ - key = 0; - if(bits < 8) bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ - } - - gray_ok = !stats->colored; - if(!stats->allow_greyscale) gray_ok = 0; - if(!gray_ok && bits < 8) bits = 8; - - n = stats->numcolors; - palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8)); - palette_ok = n <= 256 && bits <= 8 && n != 0; /*n==0 means likely numcolors wasn't computed*/ - if(numpixels < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/ - if(gray_ok && !alpha && bits <= palettebits) palette_ok = 0; /*gray is less overhead*/ - if(!stats->allow_palette) palette_ok = 0; - - if(palette_ok) { - const unsigned char* p = stats->palette; - lodepng_palette_clear(mode_out); /*remove potential earlier palette*/ - for(i = 0; i != stats->numcolors; ++i) { - error = lodepng_palette_add(mode_out, p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3]); - if(error) break; - } - - mode_out->colortype = LCT_PALETTE; - mode_out->bitdepth = palettebits; - - if(mode_in->colortype == LCT_PALETTE && mode_in->palettesize >= mode_out->palettesize - && mode_in->bitdepth == mode_out->bitdepth) { - /*If input should have same palette colors, keep original to preserve its order and prevent conversion*/ - lodepng_color_mode_cleanup(mode_out); - lodepng_color_mode_copy(mode_out, mode_in); - } - } else /*8-bit or 16-bit per channel*/ { - mode_out->bitdepth = bits; - mode_out->colortype = alpha ? (gray_ok ? LCT_GREY_ALPHA : LCT_RGBA) - : (gray_ok ? LCT_GREY : LCT_RGB); - if(key) { - unsigned mask = (1u << mode_out->bitdepth) - 1u; /*stats always uses 16-bit, mask converts it*/ - mode_out->key_r = stats->key_r & mask; - mode_out->key_g = stats->key_g & mask; - mode_out->key_b = stats->key_b & mask; - mode_out->key_defined = 1; - } - } - - return error; -} - -#endif /* #ifdef LODEPNG_COMPILE_ENCODER */ - -/* -Paeth predictor, used by PNG filter type 4 -The parameters are of type short, but should come from unsigned chars, the shorts -are only needed to make the paeth calculation correct. -*/ -static unsigned char paethPredictor(short a, short b, short c) { - short pa = LODEPNG_ABS(b - c); - short pb = LODEPNG_ABS(a - c); - short pc = LODEPNG_ABS(a + b - c - c); - /* return input value associated with smallest of pa, pb, pc (with certain priority if equal) */ - if(pb < pa) { a = b; pa = pb; } - return (pc < pa) ? c : a; -} - -/*shared values used by multiple Adam7 related functions*/ - -static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/ -static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/ -static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/ -static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/ - -/* -Outputs various dimensions and positions in the image related to the Adam7 reduced images. -passw: output containing the width of the 7 passes -passh: output containing the height of the 7 passes -filter_passstart: output containing the index of the start and end of each - reduced image with filter bytes -padded_passstart output containing the index of the start and end of each - reduced image when without filter bytes but with padded scanlines -passstart: output containing the index of the start and end of each reduced - image without padding between scanlines, but still padding between the images -w, h: width and height of non-interlaced image -bpp: bits per pixel -"padded" is only relevant if bpp is less than 8 and a scanline or image does not - end at a full byte -*/ -static void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8], - size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp) { - /*the passstart values have 8 values: the 8th one indicates the byte after the end of the 7th (= last) pass*/ - unsigned i; - - /*calculate width and height in pixels of each pass*/ - for(i = 0; i != 7; ++i) { - passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i]; - passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i]; - if(passw[i] == 0) passh[i] = 0; - if(passh[i] == 0) passw[i] = 0; - } - - filter_passstart[0] = padded_passstart[0] = passstart[0] = 0; - for(i = 0; i != 7; ++i) { - /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/ - filter_passstart[i + 1] = filter_passstart[i] - + ((passw[i] && passh[i]) ? passh[i] * (1u + (passw[i] * bpp + 7u) / 8u) : 0); - /*bits padded if needed to fill full byte at end of each scanline*/ - padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7u) / 8u); - /*only padded at end of reduced image*/ - passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7u) / 8u; - } -} - -#ifdef LODEPNG_COMPILE_DECODER - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / PNG Decoder / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*read the information from the header and store it in the LodePNGInfo. return value is error*/ -unsigned lodepng_inspect(unsigned* w, unsigned* h, LodePNGState* state, - const unsigned char* in, size_t insize) { - unsigned width, height; - LodePNGInfo* info = &state->info_png; - if(insize == 0 || in == 0) { - CERROR_RETURN_ERROR(state->error, 48); /*error: the given data is empty*/ - } - if(insize < 33) { - CERROR_RETURN_ERROR(state->error, 27); /*error: the data length is smaller than the length of a PNG header*/ - } - - /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/ - /* TODO: remove this. One should use a new LodePNGState for new sessions */ - lodepng_info_cleanup(info); - lodepng_info_init(info); - - if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 - || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { - CERROR_RETURN_ERROR(state->error, 28); /*error: the first 8 bytes are not the correct PNG signature*/ - } - if(lodepng_chunk_length(in + 8) != 13) { - CERROR_RETURN_ERROR(state->error, 94); /*error: header size must be 13 bytes*/ - } - if(!lodepng_chunk_type_equals(in + 8, "IHDR")) { - CERROR_RETURN_ERROR(state->error, 29); /*error: it doesn't start with a IHDR chunk!*/ - } - - /*read the values given in the header*/ - width = lodepng_read32bitInt(&in[16]); - height = lodepng_read32bitInt(&in[20]); - /*TODO: remove the undocumented feature that allows to give null pointers to width or height*/ - if(w) *w = width; - if(h) *h = height; - info->color.bitdepth = in[24]; - info->color.colortype = (LodePNGColorType)in[25]; - info->compression_method = in[26]; - info->filter_method = in[27]; - info->interlace_method = in[28]; - - /*errors returned only after the parsing so other values are still output*/ - - /*error: invalid image size*/ - if(width == 0 || height == 0) CERROR_RETURN_ERROR(state->error, 93); - /*error: invalid colortype or bitdepth combination*/ - state->error = checkColorValidity(info->color.colortype, info->color.bitdepth); - if(state->error) return state->error; - /*error: only compression method 0 is allowed in the specification*/ - if(info->compression_method != 0) CERROR_RETURN_ERROR(state->error, 32); - /*error: only filter method 0 is allowed in the specification*/ - if(info->filter_method != 0) CERROR_RETURN_ERROR(state->error, 33); - /*error: only interlace methods 0 and 1 exist in the specification*/ - if(info->interlace_method > 1) CERROR_RETURN_ERROR(state->error, 34); - - if(!state->decoder.ignore_crc) { - unsigned CRC = lodepng_read32bitInt(&in[29]); - unsigned checksum = lodepng_crc32(&in[12], 17); - if(CRC != checksum) { - CERROR_RETURN_ERROR(state->error, 57); /*invalid CRC*/ - } - } - - return state->error; -} - -static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, - size_t bytewidth, unsigned char filterType, size_t length) { - /* - For PNG filter method 0 - unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte, - the filter works byte per byte (bytewidth = 1) - precon is the previous unfiltered scanline, recon the result, scanline the current one - the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead - recon and scanline MAY be the same memory address! precon must be disjoint. - */ - - size_t i; - switch(filterType) { - case 0: - for(i = 0; i != length; ++i) recon[i] = scanline[i]; - break; - case 1: - for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; - for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth]; - break; - case 2: - if(precon) { - for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i]; - } else { - for(i = 0; i != length; ++i) recon[i] = scanline[i]; - } - break; - case 3: - if(precon) { - for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1u); - for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) >> 1u); - } else { - for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; - for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + (recon[i - bytewidth] >> 1u); - } - break; - case 4: - if(precon) { - for(i = 0; i != bytewidth; ++i) { - recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/ - } - - /* Unroll independent paths of the paeth predictor. A 6x and 8x version would also be possible but that - adds too much code. Whether this actually speeds anything up at all depends on compiler and settings. */ - if(bytewidth >= 4) { - for(; i + 3 < length; i += 4) { - size_t j = i - bytewidth; - unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3]; - unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3]; - unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3]; - unsigned char q0 = precon[j + 0], q1 = precon[j + 1], q2 = precon[j + 2], q3 = precon[j + 3]; - recon[i + 0] = s0 + paethPredictor(r0, p0, q0); - recon[i + 1] = s1 + paethPredictor(r1, p1, q1); - recon[i + 2] = s2 + paethPredictor(r2, p2, q2); - recon[i + 3] = s3 + paethPredictor(r3, p3, q3); - } - } else if(bytewidth >= 3) { - for(; i + 2 < length; i += 3) { - size_t j = i - bytewidth; - unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2]; - unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2]; - unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2]; - unsigned char q0 = precon[j + 0], q1 = precon[j + 1], q2 = precon[j + 2]; - recon[i + 0] = s0 + paethPredictor(r0, p0, q0); - recon[i + 1] = s1 + paethPredictor(r1, p1, q1); - recon[i + 2] = s2 + paethPredictor(r2, p2, q2); - } - } else if(bytewidth >= 2) { - for(; i + 1 < length; i += 2) { - size_t j = i - bytewidth; - unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1]; - unsigned char r0 = recon[j + 0], r1 = recon[j + 1]; - unsigned char p0 = precon[i + 0], p1 = precon[i + 1]; - unsigned char q0 = precon[j + 0], q1 = precon[j + 1]; - recon[i + 0] = s0 + paethPredictor(r0, p0, q0); - recon[i + 1] = s1 + paethPredictor(r1, p1, q1); - } - } - - for(; i != length; ++i) { - recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth])); - } - } else { - for(i = 0; i != bytewidth; ++i) { - recon[i] = scanline[i]; - } - for(i = bytewidth; i < length; ++i) { - /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/ - recon[i] = (scanline[i] + recon[i - bytewidth]); - } - } - break; - default: return 36; /*error: invalid filter type given*/ - } - return 0; -} - -static unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) { - /* - For PNG filter method 0 - this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times) - out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline - w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel - in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes) - */ - - unsigned y; - unsigned char* prevline = 0; - - /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ - size_t bytewidth = (bpp + 7u) / 8u; - /*the width of a scanline in bytes, not including the filter type*/ - size_t linebytes = lodepng_get_raw_size_idat(w, 1, bpp) - 1u; - - for(y = 0; y < h; ++y) { - size_t outindex = linebytes * y; - size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ - unsigned char filterType = in[inindex]; - - CERROR_TRY_RETURN(unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes)); - - prevline = &out[outindex]; - } - - return 0; -} - -/* -in: Adam7 interlaced image, with no padding bits between scanlines, but between - reduced images so that each reduced image starts at a byte. -out: the same pixels, but re-ordered so that they're now a non-interlaced image with size w*h -bpp: bits per pixel -out has the following size in bits: w * h * bpp. -in is possibly bigger due to padding bits between reduced images. -out must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation -(because that's likely a little bit faster) -NOTE: comments about padding bits are only relevant if bpp < 8 -*/ -static void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) { - unsigned passw[7], passh[7]; - size_t filter_passstart[8], padded_passstart[8], passstart[8]; - unsigned i; - - Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); - - if(bpp >= 8) { - for(i = 0; i != 7; ++i) { - unsigned x, y, b; - size_t bytewidth = bpp / 8u; - for(y = 0; y < passh[i]; ++y) - for(x = 0; x < passw[i]; ++x) { - size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth; - size_t pixeloutstart = ((ADAM7_IY[i] + (size_t)y * ADAM7_DY[i]) * (size_t)w - + ADAM7_IX[i] + (size_t)x * ADAM7_DX[i]) * bytewidth; - for(b = 0; b < bytewidth; ++b) { - out[pixeloutstart + b] = in[pixelinstart + b]; - } - } - } - } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ { - for(i = 0; i != 7; ++i) { - unsigned x, y, b; - unsigned ilinebits = bpp * passw[i]; - unsigned olinebits = bpp * w; - size_t obp, ibp; /*bit pointers (for out and in buffer)*/ - for(y = 0; y < passh[i]; ++y) - for(x = 0; x < passw[i]; ++x) { - ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp); - obp = (ADAM7_IY[i] + (size_t)y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + (size_t)x * ADAM7_DX[i]) * bpp; - for(b = 0; b < bpp; ++b) { - unsigned char bit = readBitFromReversedStream(&ibp, in); - setBitOfReversedStream(&obp, out, bit); - } - } - } - } -} - -static void removePaddingBits(unsigned char* out, const unsigned char* in, - size_t olinebits, size_t ilinebits, unsigned h) { - /* - After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need - to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers - for the Adam7 code, the color convert code and the output to the user. - in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must - have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits - also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7 - only useful if (ilinebits - olinebits) is a value in the range 1..7 - */ - unsigned y; - size_t diff = ilinebits - olinebits; - size_t ibp = 0, obp = 0; /*input and output bit pointers*/ - for(y = 0; y < h; ++y) { - size_t x; - for(x = 0; x < olinebits; ++x) { - unsigned char bit = readBitFromReversedStream(&ibp, in); - setBitOfReversedStream(&obp, out, bit); - } - ibp += diff; - } -} - -/*out must be buffer big enough to contain full image, and in must contain the full decompressed data from -the IDAT chunks (with filter index bytes and possible padding bits) -return value is error*/ -static unsigned postProcessScanlines(unsigned char* out, unsigned char* in, - unsigned w, unsigned h, const LodePNGInfo* info_png) { - /* - This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype. - Steps: - *) if no Adam7: 1) unfilter 2) remove padding bits (= possible extra bits per scanline if bpp < 8) - *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace - NOTE: the in buffer will be overwritten with intermediate data! - */ - unsigned bpp = lodepng_get_bpp(&info_png->color); - if(bpp == 0) return 31; /*error: invalid colortype*/ - - if(info_png->interlace_method == 0) { - if(bpp < 8 && w * bpp != ((w * bpp + 7u) / 8u) * 8u) { - CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp)); - removePaddingBits(out, in, w * bpp, ((w * bpp + 7u) / 8u) * 8u, h); - } - /*we can immediately filter into the out buffer, no other steps needed*/ - else CERROR_TRY_RETURN(unfilter(out, in, w, h, bpp)); - } else /*interlace_method is 1 (Adam7)*/ { - unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; - unsigned i; - - Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); - - for(i = 0; i != 7; ++i) { - CERROR_TRY_RETURN(unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp)); - /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline, - move bytes instead of bits or move not at all*/ - if(bpp < 8) { - /*remove padding bits in scanlines; after this there still may be padding - bits between the different reduced images: each reduced image still starts nicely at a byte*/ - removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp, - ((passw[i] * bpp + 7u) / 8u) * 8u, passh[i]); - } - } - - Adam7_deinterlace(out, in, w, h, bpp); - } - - return 0; -} - -static unsigned readChunk_PLTE(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) { - unsigned pos = 0, i; - color->palettesize = chunkLength / 3u; - if(color->palettesize == 0 || color->palettesize > 256) return 38; /*error: palette too small or big*/ - lodepng_color_mode_alloc_palette(color); - if(!color->palette && color->palettesize) { - color->palettesize = 0; - return 83; /*alloc fail*/ - } - - for(i = 0; i != color->palettesize; ++i) { - color->palette[4 * i + 0] = data[pos++]; /*R*/ - color->palette[4 * i + 1] = data[pos++]; /*G*/ - color->palette[4 * i + 2] = data[pos++]; /*B*/ - color->palette[4 * i + 3] = 255; /*alpha*/ - } - - return 0; /* OK */ -} - -static unsigned readChunk_tRNS(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) { - unsigned i; - if(color->colortype == LCT_PALETTE) { - /*error: more alpha values given than there are palette entries*/ - if(chunkLength > color->palettesize) return 39; - - for(i = 0; i != chunkLength; ++i) color->palette[4 * i + 3] = data[i]; - } else if(color->colortype == LCT_GREY) { - /*error: this chunk must be 2 bytes for grayscale image*/ - if(chunkLength != 2) return 30; - - color->key_defined = 1; - color->key_r = color->key_g = color->key_b = 256u * data[0] + data[1]; - } else if(color->colortype == LCT_RGB) { - /*error: this chunk must be 6 bytes for RGB image*/ - if(chunkLength != 6) return 41; - - color->key_defined = 1; - color->key_r = 256u * data[0] + data[1]; - color->key_g = 256u * data[2] + data[3]; - color->key_b = 256u * data[4] + data[5]; - } - else return 42; /*error: tRNS chunk not allowed for other color models*/ - - return 0; /* OK */ -} - - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS -/*background color chunk (bKGD)*/ -static unsigned readChunk_bKGD(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { - if(info->color.colortype == LCT_PALETTE) { - /*error: this chunk must be 1 byte for indexed color image*/ - if(chunkLength != 1) return 43; - - /*error: invalid palette index, or maybe this chunk appeared before PLTE*/ - if(data[0] >= info->color.palettesize) return 103; - - info->background_defined = 1; - info->background_r = info->background_g = info->background_b = data[0]; - } else if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) { - /*error: this chunk must be 2 bytes for grayscale image*/ - if(chunkLength != 2) return 44; - - /*the values are truncated to bitdepth in the PNG file*/ - info->background_defined = 1; - info->background_r = info->background_g = info->background_b = 256u * data[0] + data[1]; - } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) { - /*error: this chunk must be 6 bytes for grayscale image*/ - if(chunkLength != 6) return 45; - - /*the values are truncated to bitdepth in the PNG file*/ - info->background_defined = 1; - info->background_r = 256u * data[0] + data[1]; - info->background_g = 256u * data[2] + data[3]; - info->background_b = 256u * data[4] + data[5]; - } - - return 0; /* OK */ -} - -/*text chunk (tEXt)*/ -static unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { - unsigned error = 0; - char *key = 0, *str = 0; - - while(!error) /*not really a while loop, only used to break on error*/ { - unsigned length, string2_begin; - - length = 0; - while(length < chunkLength && data[length] != 0) ++length; - /*even though it's not allowed by the standard, no error is thrown if - there's no null termination char, if the text is empty*/ - if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ - - key = (char*)lodepng_malloc(length + 1); - if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ - - lodepng_memcpy(key, data, length); - key[length] = 0; - - string2_begin = length + 1; /*skip keyword null terminator*/ - - length = (unsigned)(chunkLength < string2_begin ? 0 : chunkLength - string2_begin); - str = (char*)lodepng_malloc(length + 1); - if(!str) CERROR_BREAK(error, 83); /*alloc fail*/ - - lodepng_memcpy(str, data + string2_begin, length); - str[length] = 0; - - error = lodepng_add_text(info, key, str); - - break; - } - - lodepng_free(key); - lodepng_free(str); - - return error; -} - -/*compressed text chunk (zTXt)*/ -static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder, - const unsigned char* data, size_t chunkLength) { - unsigned error = 0; - - /*copy the object to change parameters in it*/ - LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; - - unsigned length, string2_begin; - char *key = 0; - unsigned char* str = 0; - size_t size = 0; - - while(!error) /*not really a while loop, only used to break on error*/ { - for(length = 0; length < chunkLength && data[length] != 0; ++length) ; - if(length + 2 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ - if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ - - key = (char*)lodepng_malloc(length + 1); - if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ - - lodepng_memcpy(key, data, length); - key[length] = 0; - - if(data[length + 1] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ - - string2_begin = length + 2; - if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ - - length = (unsigned)chunkLength - string2_begin; - zlibsettings.max_output_size = decoder->max_text_size; - /*will fail if zlib error, e.g. if length is too small*/ - error = zlib_decompress(&str, &size, 0, &data[string2_begin], - length, &zlibsettings); - /*error: compressed text larger than decoder->max_text_size*/ - if(error && size > zlibsettings.max_output_size) error = 112; - if(error) break; - error = lodepng_add_text_sized(info, key, (char*)str, size); - break; - } - - lodepng_free(key); - lodepng_free(str); - - return error; -} - -/*international text chunk (iTXt)*/ -static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder, - const unsigned char* data, size_t chunkLength) { - unsigned error = 0; - unsigned i; - - /*copy the object to change parameters in it*/ - LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; - - unsigned length, begin, compressed; - char *key = 0, *langtag = 0, *transkey = 0; - - while(!error) /*not really a while loop, only used to break on error*/ { - /*Quick check if the chunk length isn't too small. Even without check - it'd still fail with other error checks below if it's too short. This just gives a different error code.*/ - if(chunkLength < 5) CERROR_BREAK(error, 30); /*iTXt chunk too short*/ - - /*read the key*/ - for(length = 0; length < chunkLength && data[length] != 0; ++length) ; - if(length + 3 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination char, corrupt?*/ - if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ - - key = (char*)lodepng_malloc(length + 1); - if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ - - lodepng_memcpy(key, data, length); - key[length] = 0; - - /*read the compression method*/ - compressed = data[length + 1]; - if(data[length + 2] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ - - /*even though it's not allowed by the standard, no error is thrown if - there's no null termination char, if the text is empty for the next 3 texts*/ - - /*read the langtag*/ - begin = length + 3; - length = 0; - for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length; - - langtag = (char*)lodepng_malloc(length + 1); - if(!langtag) CERROR_BREAK(error, 83); /*alloc fail*/ - - lodepng_memcpy(langtag, data + begin, length); - langtag[length] = 0; - - /*read the transkey*/ - begin += length + 1; - length = 0; - for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length; - - transkey = (char*)lodepng_malloc(length + 1); - if(!transkey) CERROR_BREAK(error, 83); /*alloc fail*/ - - lodepng_memcpy(transkey, data + begin, length); - transkey[length] = 0; - - /*read the actual text*/ - begin += length + 1; - - length = (unsigned)chunkLength < begin ? 0 : (unsigned)chunkLength - begin; - - if(compressed) { - unsigned char* str = 0; - size_t size = 0; - zlibsettings.max_output_size = decoder->max_text_size; - /*will fail if zlib error, e.g. if length is too small*/ - error = zlib_decompress(&str, &size, 0, &data[begin], - length, &zlibsettings); - /*error: compressed text larger than decoder->max_text_size*/ - if(error && size > zlibsettings.max_output_size) error = 112; - if(!error) error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)str, size); - lodepng_free(str); - } else { - error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)(data + begin), length); - } - - break; - } - - lodepng_free(key); - lodepng_free(langtag); - lodepng_free(transkey); - - return error; -} - -static unsigned readChunk_tIME(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { - if(chunkLength != 7) return 73; /*invalid tIME chunk size*/ - - info->time_defined = 1; - info->time.year = 256u * data[0] + data[1]; - info->time.month = data[2]; - info->time.day = data[3]; - info->time.hour = data[4]; - info->time.minute = data[5]; - info->time.second = data[6]; - - return 0; /* OK */ -} - -static unsigned readChunk_pHYs(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { - if(chunkLength != 9) return 74; /*invalid pHYs chunk size*/ - - info->phys_defined = 1; - info->phys_x = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3]; - info->phys_y = 16777216u * data[4] + 65536u * data[5] + 256u * data[6] + data[7]; - info->phys_unit = data[8]; - - return 0; /* OK */ -} - -static unsigned readChunk_gAMA(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { - if(chunkLength != 4) return 96; /*invalid gAMA chunk size*/ - - info->gama_defined = 1; - info->gama_gamma = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3]; - - return 0; /* OK */ -} - -static unsigned readChunk_cHRM(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { - if(chunkLength != 32) return 97; /*invalid cHRM chunk size*/ - - info->chrm_defined = 1; - info->chrm_white_x = 16777216u * data[ 0] + 65536u * data[ 1] + 256u * data[ 2] + data[ 3]; - info->chrm_white_y = 16777216u * data[ 4] + 65536u * data[ 5] + 256u * data[ 6] + data[ 7]; - info->chrm_red_x = 16777216u * data[ 8] + 65536u * data[ 9] + 256u * data[10] + data[11]; - info->chrm_red_y = 16777216u * data[12] + 65536u * data[13] + 256u * data[14] + data[15]; - info->chrm_green_x = 16777216u * data[16] + 65536u * data[17] + 256u * data[18] + data[19]; - info->chrm_green_y = 16777216u * data[20] + 65536u * data[21] + 256u * data[22] + data[23]; - info->chrm_blue_x = 16777216u * data[24] + 65536u * data[25] + 256u * data[26] + data[27]; - info->chrm_blue_y = 16777216u * data[28] + 65536u * data[29] + 256u * data[30] + data[31]; - - return 0; /* OK */ -} - -static unsigned readChunk_sRGB(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) { - if(chunkLength != 1) return 98; /*invalid sRGB chunk size (this one is never ignored)*/ - - info->srgb_defined = 1; - info->srgb_intent = data[0]; - - return 0; /* OK */ -} - -static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecoderSettings* decoder, - const unsigned char* data, size_t chunkLength) { - unsigned error = 0; - unsigned i; - size_t size = 0; - /*copy the object to change parameters in it*/ - LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; - - unsigned length, string2_begin; - - info->iccp_defined = 1; - if(info->iccp_name) lodepng_clear_icc(info); - - for(length = 0; length < chunkLength && data[length] != 0; ++length) ; - if(length + 2 >= chunkLength) return 75; /*no null termination, corrupt?*/ - if(length < 1 || length > 79) return 89; /*keyword too short or long*/ - - info->iccp_name = (char*)lodepng_malloc(length + 1); - if(!info->iccp_name) return 83; /*alloc fail*/ - - info->iccp_name[length] = 0; - for(i = 0; i != length; ++i) info->iccp_name[i] = (char)data[i]; - - if(data[length + 1] != 0) return 72; /*the 0 byte indicating compression must be 0*/ - - string2_begin = length + 2; - if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/ - - length = (unsigned)chunkLength - string2_begin; - zlibsettings.max_output_size = decoder->max_icc_size; - error = zlib_decompress(&info->iccp_profile, &size, 0, - &data[string2_begin], - length, &zlibsettings); - /*error: ICC profile larger than decoder->max_icc_size*/ - if(error && size > zlibsettings.max_output_size) error = 113; - info->iccp_profile_size = size; - if(!error && !info->iccp_profile_size) error = 100; /*invalid ICC profile size*/ - return error; -} -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos, - const unsigned char* in, size_t insize) { - const unsigned char* chunk = in + pos; - unsigned chunkLength; - const unsigned char* data; - unsigned unhandled = 0; - unsigned error = 0; - - if(pos + 4 > insize) return 30; - chunkLength = lodepng_chunk_length(chunk); - if(chunkLength > 2147483647) return 63; - data = lodepng_chunk_data_const(chunk); - if(data + chunkLength + 4 > in + insize) return 30; - - if(lodepng_chunk_type_equals(chunk, "PLTE")) { - error = readChunk_PLTE(&state->info_png.color, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "tRNS")) { - error = readChunk_tRNS(&state->info_png.color, data, chunkLength); -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - } else if(lodepng_chunk_type_equals(chunk, "bKGD")) { - error = readChunk_bKGD(&state->info_png, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "tEXt")) { - error = readChunk_tEXt(&state->info_png, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "zTXt")) { - error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "iTXt")) { - error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "tIME")) { - error = readChunk_tIME(&state->info_png, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "pHYs")) { - error = readChunk_pHYs(&state->info_png, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "gAMA")) { - error = readChunk_gAMA(&state->info_png, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "cHRM")) { - error = readChunk_cHRM(&state->info_png, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "sRGB")) { - error = readChunk_sRGB(&state->info_png, data, chunkLength); - } else if(lodepng_chunk_type_equals(chunk, "iCCP")) { - error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength); -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - } else { - /* unhandled chunk is ok (is not an error) */ - unhandled = 1; - } - - if(!error && !unhandled && !state->decoder.ignore_crc) { - if(lodepng_chunk_check_crc(chunk)) return 57; /*invalid CRC*/ - } - - return error; -} - -/*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/ -static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, - LodePNGState* state, - const unsigned char* in, size_t insize) { - unsigned char IEND = 0; - const unsigned char* chunk; - unsigned char* idat; /*the data from idat chunks, zlib compressed*/ - size_t idatsize = 0; - unsigned char* scanlines = 0; - size_t scanlines_size = 0, expected_size = 0; - size_t outsize = 0; - - /*for unknown chunk order*/ - unsigned unknown = 0; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/ -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - - - /* safe output values in case error happens */ - *out = 0; - *w = *h = 0; - - state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/ - if(state->error) return; - - if(lodepng_pixel_overflow(*w, *h, &state->info_png.color, &state->info_raw)) { - CERROR_RETURN(state->error, 92); /*overflow possible due to amount of pixels*/ - } - - /*the input filesize is a safe upper bound for the sum of idat chunks size*/ - idat = (unsigned char*)lodepng_malloc(insize); - if(!idat) CERROR_RETURN(state->error, 83); /*alloc fail*/ - - chunk = &in[33]; /*first byte of the first chunk after the header*/ - - /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. - IDAT data is put at the start of the in buffer*/ - while(!IEND && !state->error) { - unsigned chunkLength; - const unsigned char* data; /*the data in the chunk*/ - - /*error: size of the in buffer too small to contain next chunk*/ - if((size_t)((chunk - in) + 12) > insize || chunk < in) { - if(state->decoder.ignore_end) break; /*other errors may still happen though*/ - CERROR_BREAK(state->error, 30); - } - - /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/ - chunkLength = lodepng_chunk_length(chunk); - /*error: chunk length larger than the max PNG chunk size*/ - if(chunkLength > 2147483647) { - if(state->decoder.ignore_end) break; /*other errors may still happen though*/ - CERROR_BREAK(state->error, 63); - } - - if((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in) { - CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk*/ - } - - data = lodepng_chunk_data_const(chunk); - - unknown = 0; - - /*IDAT chunk, containing compressed image data*/ - if(lodepng_chunk_type_equals(chunk, "IDAT")) { - size_t newsize; - if(lodepng_addofl(idatsize, chunkLength, &newsize)) CERROR_BREAK(state->error, 95); - if(newsize > insize) CERROR_BREAK(state->error, 95); - lodepng_memcpy(idat + idatsize, data, chunkLength); - idatsize += chunkLength; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - critical_pos = 3; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - } else if(lodepng_chunk_type_equals(chunk, "IEND")) { - /*IEND chunk*/ - IEND = 1; - } else if(lodepng_chunk_type_equals(chunk, "PLTE")) { - /*palette chunk (PLTE)*/ - state->error = readChunk_PLTE(&state->info_png.color, data, chunkLength); - if(state->error) break; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - critical_pos = 2; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - } else if(lodepng_chunk_type_equals(chunk, "tRNS")) { - /*palette transparency chunk (tRNS). Even though this one is an ancillary chunk , it is still compiled - in without 'LODEPNG_COMPILE_ANCILLARY_CHUNKS' because it contains essential color information that - affects the alpha channel of pixels. */ - state->error = readChunk_tRNS(&state->info_png.color, data, chunkLength); - if(state->error) break; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*background color chunk (bKGD)*/ - } else if(lodepng_chunk_type_equals(chunk, "bKGD")) { - state->error = readChunk_bKGD(&state->info_png, data, chunkLength); - if(state->error) break; - } else if(lodepng_chunk_type_equals(chunk, "tEXt")) { - /*text chunk (tEXt)*/ - if(state->decoder.read_text_chunks) { - state->error = readChunk_tEXt(&state->info_png, data, chunkLength); - if(state->error) break; - } - } else if(lodepng_chunk_type_equals(chunk, "zTXt")) { - /*compressed text chunk (zTXt)*/ - if(state->decoder.read_text_chunks) { - state->error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength); - if(state->error) break; - } - } else if(lodepng_chunk_type_equals(chunk, "iTXt")) { - /*international text chunk (iTXt)*/ - if(state->decoder.read_text_chunks) { - state->error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength); - if(state->error) break; - } - } else if(lodepng_chunk_type_equals(chunk, "tIME")) { - state->error = readChunk_tIME(&state->info_png, data, chunkLength); - if(state->error) break; - } else if(lodepng_chunk_type_equals(chunk, "pHYs")) { - state->error = readChunk_pHYs(&state->info_png, data, chunkLength); - if(state->error) break; - } else if(lodepng_chunk_type_equals(chunk, "gAMA")) { - state->error = readChunk_gAMA(&state->info_png, data, chunkLength); - if(state->error) break; - } else if(lodepng_chunk_type_equals(chunk, "cHRM")) { - state->error = readChunk_cHRM(&state->info_png, data, chunkLength); - if(state->error) break; - } else if(lodepng_chunk_type_equals(chunk, "sRGB")) { - state->error = readChunk_sRGB(&state->info_png, data, chunkLength); - if(state->error) break; - } else if(lodepng_chunk_type_equals(chunk, "iCCP")) { - state->error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength); - if(state->error) break; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - } else /*it's not an implemented chunk type, so ignore it: skip over the data*/ { - /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/ - if(!state->decoder.ignore_critical && !lodepng_chunk_ancillary(chunk)) { - CERROR_BREAK(state->error, 69); - } - - unknown = 1; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - if(state->decoder.remember_unknown_chunks) { - state->error = lodepng_chunk_append(&state->info_png.unknown_chunks_data[critical_pos - 1], - &state->info_png.unknown_chunks_size[critical_pos - 1], chunk); - if(state->error) break; - } -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - } - - if(!state->decoder.ignore_crc && !unknown) /*check CRC if wanted, only on known chunk types*/ { - if(lodepng_chunk_check_crc(chunk)) CERROR_BREAK(state->error, 57); /*invalid CRC*/ - } - - if(!IEND) chunk = lodepng_chunk_next_const(chunk, in + insize); - } - - if(!state->error && state->info_png.color.colortype == LCT_PALETTE && !state->info_png.color.palette) { - state->error = 106; /* error: PNG file must have PLTE chunk if color type is palette */ - } - - if(!state->error) { - /*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation. - If the decompressed size does not match the prediction, the image must be corrupt.*/ - if(state->info_png.interlace_method == 0) { - size_t bpp = lodepng_get_bpp(&state->info_png.color); - expected_size = lodepng_get_raw_size_idat(*w, *h, bpp); - } else { - size_t bpp = lodepng_get_bpp(&state->info_png.color); - /*Adam-7 interlaced: expected size is the sum of the 7 sub-images sizes*/ - expected_size = 0; - expected_size += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, bpp); - if(*w > 4) expected_size += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, bpp); - expected_size += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, bpp); - if(*w > 2) expected_size += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, bpp); - expected_size += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, bpp); - if(*w > 1) expected_size += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, bpp); - expected_size += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, bpp); - } - - state->error = zlib_decompress(&scanlines, &scanlines_size, expected_size, idat, idatsize, &state->decoder.zlibsettings); - } - if(!state->error && scanlines_size != expected_size) state->error = 91; /*decompressed size doesn't match prediction*/ - lodepng_free(idat); - - if(!state->error) { - outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color); - *out = (unsigned char*)lodepng_malloc(outsize); - if(!*out) state->error = 83; /*alloc fail*/ - } - if(!state->error) { - lodepng_memset(*out, 0, outsize); - state->error = postProcessScanlines(*out, scanlines, *w, *h, &state->info_png); - } - lodepng_free(scanlines); -} - -unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, - LodePNGState* state, - const unsigned char* in, size_t insize) { - *out = 0; - decodeGeneric(out, w, h, state, in, insize); - if(state->error) return state->error; - if(!state->decoder.color_convert || lodepng_color_mode_equal(&state->info_raw, &state->info_png.color)) { - /*same color type, no copying or converting of data needed*/ - /*store the info_png color settings on the info_raw so that the info_raw still reflects what colortype - the raw image has to the end user*/ - if(!state->decoder.color_convert) { - state->error = lodepng_color_mode_copy(&state->info_raw, &state->info_png.color); - if(state->error) return state->error; - } - } else { /*color conversion needed*/ - unsigned char* data = *out; - size_t outsize; - - /*TODO: check if this works according to the statement in the documentation: "The converter can convert - from grayscale input color type, to 8-bit grayscale or grayscale with alpha"*/ - if(!(state->info_raw.colortype == LCT_RGB || state->info_raw.colortype == LCT_RGBA) - && !(state->info_raw.bitdepth == 8)) { - return 56; /*unsupported color mode conversion*/ - } - - outsize = lodepng_get_raw_size(*w, *h, &state->info_raw); - *out = (unsigned char*)lodepng_malloc(outsize); - if(!(*out)) { - state->error = 83; /*alloc fail*/ - } - else state->error = lodepng_convert(*out, data, &state->info_raw, - &state->info_png.color, *w, *h); - lodepng_free(data); - } - return state->error; -} - -unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, - size_t insize, LodePNGColorType colortype, unsigned bitdepth) { - unsigned error; - LodePNGState state; - lodepng_state_init(&state); - state.info_raw.colortype = colortype; - state.info_raw.bitdepth = bitdepth; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*disable reading things that this function doesn't output*/ - state.decoder.read_text_chunks = 0; - state.decoder.remember_unknown_chunks = 0; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - error = lodepng_decode(out, w, h, &state, in, insize); - lodepng_state_cleanup(&state); - return error; -} - -unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) { - return lodepng_decode_memory(out, w, h, in, insize, LCT_RGBA, 8); -} - -unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) { - return lodepng_decode_memory(out, w, h, in, insize, LCT_RGB, 8); -} - -#ifdef LODEPNG_COMPILE_DISK -unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename, - LodePNGColorType colortype, unsigned bitdepth) { - unsigned char* buffer = 0; - size_t buffersize; - unsigned error; - /* safe output values in case error happens */ - *out = 0; - *w = *h = 0; - error = lodepng_load_file(&buffer, &buffersize, filename); - if(!error) error = lodepng_decode_memory(out, w, h, buffer, buffersize, colortype, bitdepth); - lodepng_free(buffer); - return error; -} - -unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) { - return lodepng_decode_file(out, w, h, filename, LCT_RGBA, 8); -} - -unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) { - return lodepng_decode_file(out, w, h, filename, LCT_RGB, 8); -} -#endif /*LODEPNG_COMPILE_DISK*/ - -void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings) { - settings->color_convert = 1; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - settings->read_text_chunks = 1; - settings->remember_unknown_chunks = 0; - settings->max_text_size = 16777216; - settings->max_icc_size = 16777216; /* 16MB is much more than enough for any reasonable ICC profile */ -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - settings->ignore_crc = 0; - settings->ignore_critical = 0; - settings->ignore_end = 0; - lodepng_decompress_settings_init(&settings->zlibsettings); -} - -#endif /*LODEPNG_COMPILE_DECODER*/ - -#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) - -void lodepng_state_init(LodePNGState* state) { -#ifdef LODEPNG_COMPILE_DECODER - lodepng_decoder_settings_init(&state->decoder); -#endif /*LODEPNG_COMPILE_DECODER*/ -#ifdef LODEPNG_COMPILE_ENCODER - lodepng_encoder_settings_init(&state->encoder); -#endif /*LODEPNG_COMPILE_ENCODER*/ - lodepng_color_mode_init(&state->info_raw); - lodepng_info_init(&state->info_png); - state->error = 1; -} - -void lodepng_state_cleanup(LodePNGState* state) { - lodepng_color_mode_cleanup(&state->info_raw); - lodepng_info_cleanup(&state->info_png); -} - -void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source) { - lodepng_state_cleanup(dest); - *dest = *source; - lodepng_color_mode_init(&dest->info_raw); - lodepng_info_init(&dest->info_png); - dest->error = lodepng_color_mode_copy(&dest->info_raw, &source->info_raw); if(dest->error) return; - dest->error = lodepng_info_copy(&dest->info_png, &source->info_png); if(dest->error) return; -} - -#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ - -#ifdef LODEPNG_COMPILE_ENCODER - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / PNG Encoder / */ -/* ////////////////////////////////////////////////////////////////////////// */ - - -static unsigned writeSignature(ucvector* out) { - size_t pos = out->size; - const unsigned char signature[] = {137, 80, 78, 71, 13, 10, 26, 10}; - /*8 bytes PNG signature, aka the magic bytes*/ - if(!ucvector_resize(out, out->size + 8)) return 83; /*alloc fail*/ - lodepng_memcpy(out->data + pos, signature, 8); - return 0; -} - -static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method) { - unsigned char *chunk, *data; - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 13, "IHDR")); - data = chunk + 8; - - lodepng_set32bitInt(data + 0, w); /*width*/ - lodepng_set32bitInt(data + 4, h); /*height*/ - data[8] = (unsigned char)bitdepth; /*bit depth*/ - data[9] = (unsigned char)colortype; /*color type*/ - data[10] = 0; /*compression method*/ - data[11] = 0; /*filter method*/ - data[12] = interlace_method; /*interlace method*/ - - lodepng_chunk_generate_crc(chunk); - return 0; -} - -/* only adds the chunk if needed (there is a key or palette with alpha) */ -static unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info) { - unsigned char* chunk; - size_t i, j = 8; - - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, info->palettesize * 3, "PLTE")); - - for(i = 0; i != info->palettesize; ++i) { - /*add all channels except alpha channel*/ - chunk[j++] = info->palette[i * 4 + 0]; - chunk[j++] = info->palette[i * 4 + 1]; - chunk[j++] = info->palette[i * 4 + 2]; - } - - lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_tRNS(ucvector* out, const LodePNGColorMode* info) { - unsigned char* chunk = 0; - - if(info->colortype == LCT_PALETTE) { - size_t i, amount = info->palettesize; - /*the tail of palette values that all have 255 as alpha, does not have to be encoded*/ - for(i = info->palettesize; i != 0; --i) { - if(info->palette[4 * (i - 1) + 3] != 255) break; - --amount; - } - if(amount) { - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, amount, "tRNS")); - /*add the alpha channel values from the palette*/ - for(i = 0; i != amount; ++i) chunk[8 + i] = info->palette[4 * i + 3]; - } - } else if(info->colortype == LCT_GREY) { - if(info->key_defined) { - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "tRNS")); - chunk[8] = (unsigned char)(info->key_r >> 8); - chunk[9] = (unsigned char)(info->key_r & 255); - } - } else if(info->colortype == LCT_RGB) { - if(info->key_defined) { - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 6, "tRNS")); - chunk[8] = (unsigned char)(info->key_r >> 8); - chunk[9] = (unsigned char)(info->key_r & 255); - chunk[10] = (unsigned char)(info->key_g >> 8); - chunk[11] = (unsigned char)(info->key_g & 255); - chunk[12] = (unsigned char)(info->key_b >> 8); - chunk[13] = (unsigned char)(info->key_b & 255); - } - } - - if(chunk) lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize, - LodePNGCompressSettings* zlibsettings) { - unsigned error = 0; - unsigned char* zlib = 0; - size_t zlibsize = 0; - - error = zlib_compress(&zlib, &zlibsize, data, datasize, zlibsettings); - if(!error) { - error = lodepng_chunk_createv(out, zlibsize, "IDAT", zlib); - } - lodepng_free(zlib); - return error; -} - -static unsigned addChunk_IEND(ucvector* out) { - return lodepng_chunk_createv(out, 0, "IEND", 0); -} - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - -static unsigned addChunk_tEXt(ucvector* out, const char* keyword, const char* textstring) { - unsigned char* chunk = 0; - size_t keysize = lodepng_strlen(keyword), textsize = lodepng_strlen(textstring); - size_t size = keysize + 1 + textsize; - if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, size, "tEXt")); - lodepng_memcpy(chunk + 8, keyword, keysize); - chunk[8 + keysize] = 0; /*null termination char*/ - lodepng_memcpy(chunk + 9 + keysize, textstring, textsize); - lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_zTXt(ucvector* out, const char* keyword, const char* textstring, - LodePNGCompressSettings* zlibsettings) { - unsigned error = 0; - unsigned char* chunk = 0; - unsigned char* compressed = 0; - size_t compressedsize = 0; - size_t textsize = lodepng_strlen(textstring); - size_t keysize = lodepng_strlen(keyword); - if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ - - error = zlib_compress(&compressed, &compressedsize, - (const unsigned char*)textstring, textsize, zlibsettings); - if(!error) { - size_t size = keysize + 2 + compressedsize; - error = lodepng_chunk_init(&chunk, out, size, "zTXt"); - } - if(!error) { - lodepng_memcpy(chunk + 8, keyword, keysize); - chunk[8 + keysize] = 0; /*null termination char*/ - chunk[9 + keysize] = 0; /*compression method: 0*/ - lodepng_memcpy(chunk + 10 + keysize, compressed, compressedsize); - lodepng_chunk_generate_crc(chunk); - } - - lodepng_free(compressed); - return error; -} - -static unsigned addChunk_iTXt(ucvector* out, unsigned compress, const char* keyword, const char* langtag, - const char* transkey, const char* textstring, LodePNGCompressSettings* zlibsettings) { - unsigned error = 0; - unsigned char* chunk = 0; - unsigned char* compressed = 0; - size_t compressedsize = 0; - size_t textsize = lodepng_strlen(textstring); - size_t keysize = lodepng_strlen(keyword), langsize = lodepng_strlen(langtag), transsize = lodepng_strlen(transkey); - - if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ - - if(compress) { - error = zlib_compress(&compressed, &compressedsize, - (const unsigned char*)textstring, textsize, zlibsettings); - } - if(!error) { - size_t size = keysize + 3 + langsize + 1 + transsize + 1 + (compress ? compressedsize : textsize); - error = lodepng_chunk_init(&chunk, out, size, "iTXt"); - } - if(!error) { - size_t pos = 8; - lodepng_memcpy(chunk + pos, keyword, keysize); - pos += keysize; - chunk[pos++] = 0; /*null termination char*/ - chunk[pos++] = (compress ? 1 : 0); /*compression flag*/ - chunk[pos++] = 0; /*compression method: 0*/ - lodepng_memcpy(chunk + pos, langtag, langsize); - pos += langsize; - chunk[pos++] = 0; /*null termination char*/ - lodepng_memcpy(chunk + pos, transkey, transsize); - pos += transsize; - chunk[pos++] = 0; /*null termination char*/ - if(compress) { - lodepng_memcpy(chunk + pos, compressed, compressedsize); - } else { - lodepng_memcpy(chunk + pos, textstring, textsize); - } - lodepng_chunk_generate_crc(chunk); - } - - lodepng_free(compressed); - return error; -} - -static unsigned addChunk_bKGD(ucvector* out, const LodePNGInfo* info) { - unsigned char* chunk = 0; - if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) { - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "bKGD")); - chunk[8] = (unsigned char)(info->background_r >> 8); - chunk[9] = (unsigned char)(info->background_r & 255); - } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) { - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 6, "bKGD")); - chunk[8] = (unsigned char)(info->background_r >> 8); - chunk[9] = (unsigned char)(info->background_r & 255); - chunk[10] = (unsigned char)(info->background_g >> 8); - chunk[11] = (unsigned char)(info->background_g & 255); - chunk[12] = (unsigned char)(info->background_b >> 8); - chunk[13] = (unsigned char)(info->background_b & 255); - } else if(info->color.colortype == LCT_PALETTE) { - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 1, "bKGD")); - chunk[8] = (unsigned char)(info->background_r & 255); /*palette index*/ - } - if(chunk) lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time) { - unsigned char* chunk; - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 7, "tIME")); - chunk[8] = (unsigned char)(time->year >> 8); - chunk[9] = (unsigned char)(time->year & 255); - chunk[10] = (unsigned char)time->month; - chunk[11] = (unsigned char)time->day; - chunk[12] = (unsigned char)time->hour; - chunk[13] = (unsigned char)time->minute; - chunk[14] = (unsigned char)time->second; - lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info) { - unsigned char* chunk; - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 9, "pHYs")); - lodepng_set32bitInt(chunk + 8, info->phys_x); - lodepng_set32bitInt(chunk + 12, info->phys_y); - chunk[16] = info->phys_unit; - lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_gAMA(ucvector* out, const LodePNGInfo* info) { - unsigned char* chunk; - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 4, "gAMA")); - lodepng_set32bitInt(chunk + 8, info->gama_gamma); - lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_cHRM(ucvector* out, const LodePNGInfo* info) { - unsigned char* chunk; - CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 32, "cHRM")); - lodepng_set32bitInt(chunk + 8, info->chrm_white_x); - lodepng_set32bitInt(chunk + 12, info->chrm_white_y); - lodepng_set32bitInt(chunk + 16, info->chrm_red_x); - lodepng_set32bitInt(chunk + 20, info->chrm_red_y); - lodepng_set32bitInt(chunk + 24, info->chrm_green_x); - lodepng_set32bitInt(chunk + 28, info->chrm_green_y); - lodepng_set32bitInt(chunk + 32, info->chrm_blue_x); - lodepng_set32bitInt(chunk + 36, info->chrm_blue_y); - lodepng_chunk_generate_crc(chunk); - return 0; -} - -static unsigned addChunk_sRGB(ucvector* out, const LodePNGInfo* info) { - unsigned char data = info->srgb_intent; - return lodepng_chunk_createv(out, 1, "sRGB", &data); -} - -static unsigned addChunk_iCCP(ucvector* out, const LodePNGInfo* info, LodePNGCompressSettings* zlibsettings) { - unsigned error = 0; - unsigned char* chunk = 0; - unsigned char* compressed = 0; - size_t compressedsize = 0; - size_t keysize = lodepng_strlen(info->iccp_name); - - if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ - error = zlib_compress(&compressed, &compressedsize, - info->iccp_profile, info->iccp_profile_size, zlibsettings); - if(!error) { - size_t size = keysize + 2 + compressedsize; - error = lodepng_chunk_init(&chunk, out, size, "iCCP"); - } - if(!error) { - lodepng_memcpy(chunk + 8, info->iccp_name, keysize); - chunk[8 + keysize] = 0; /*null termination char*/ - chunk[9 + keysize] = 0; /*compression method: 0*/ - lodepng_memcpy(chunk + 10 + keysize, compressed, compressedsize); - lodepng_chunk_generate_crc(chunk); - } - - lodepng_free(compressed); - return error; -} - -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -static void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline, - size_t length, size_t bytewidth, unsigned char filterType) { - size_t i; - switch(filterType) { - case 0: /*None*/ - for(i = 0; i != length; ++i) out[i] = scanline[i]; - break; - case 1: /*Sub*/ - for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; - for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth]; - break; - case 2: /*Up*/ - if(prevline) { - for(i = 0; i != length; ++i) out[i] = scanline[i] - prevline[i]; - } else { - for(i = 0; i != length; ++i) out[i] = scanline[i]; - } - break; - case 3: /*Average*/ - if(prevline) { - for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - (prevline[i] >> 1); - for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) >> 1); - } else { - for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; - for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - (scanline[i - bytewidth] >> 1); - } - break; - case 4: /*Paeth*/ - if(prevline) { - /*paethPredictor(0, prevline[i], 0) is always prevline[i]*/ - for(i = 0; i != bytewidth; ++i) out[i] = (scanline[i] - prevline[i]); - for(i = bytewidth; i < length; ++i) { - out[i] = (scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth])); - } - } else { - for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; - /*paethPredictor(scanline[i - bytewidth], 0, 0) is always scanline[i - bytewidth]*/ - for(i = bytewidth; i < length; ++i) out[i] = (scanline[i] - scanline[i - bytewidth]); - } - break; - default: return; /*invalid filter type given*/ - } -} - -/* integer binary logarithm, max return value is 31 */ -static size_t ilog2(size_t i) { - size_t result = 0; - if(i >= 65536) { result += 16; i >>= 16; } - if(i >= 256) { result += 8; i >>= 8; } - if(i >= 16) { result += 4; i >>= 4; } - if(i >= 4) { result += 2; i >>= 2; } - if(i >= 2) { result += 1; /*i >>= 1;*/ } - return result; -} - -/* integer approximation for i * log2(i), helper function for LFS_ENTROPY */ -static size_t ilog2i(size_t i) { - size_t l; - if(i == 0) return 0; - l = ilog2(i); - /* approximate i*log2(i): l is integer logarithm, ((i - (1u << l)) << 1u) - linearly approximates the missing fractional part multiplied by i */ - return i * l + ((i - (1u << l)) << 1u); -} - -static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, - const LodePNGColorMode* color, const LodePNGEncoderSettings* settings) { - /* - For PNG filter method 0 - out must be a buffer with as size: h + (w * h * bpp + 7u) / 8u, because there are - the scanlines with 1 extra byte per scanline - */ - - unsigned bpp = lodepng_get_bpp(color); - /*the width of a scanline in bytes, not including the filter type*/ - size_t linebytes = lodepng_get_raw_size_idat(w, 1, bpp) - 1u; - - /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ - size_t bytewidth = (bpp + 7u) / 8u; - const unsigned char* prevline = 0; - unsigned x, y; - unsigned error = 0; - LodePNGFilterStrategy strategy = settings->filter_strategy; - - /* - There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard: - * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e. - use fixed filtering, with the filter None). - * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is - not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply - all five filters and select the filter that produces the smallest sum of absolute values per row. - This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true. - - If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed, - but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum - heuristic is used. - */ - if(settings->filter_palette_zero && - (color->colortype == LCT_PALETTE || color->bitdepth < 8)) strategy = LFS_ZERO; - - if(bpp == 0) return 31; /*error: invalid color type*/ - - if(strategy >= LFS_ZERO && strategy <= LFS_FOUR) { - unsigned char type = (unsigned char)strategy; - for(y = 0; y != h; ++y) { - size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ - size_t inindex = linebytes * y; - out[outindex] = type; /*filter type byte*/ - filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type); - prevline = &in[inindex]; - } - } else if(strategy == LFS_MINSUM) { - /*adaptive filtering*/ - unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ - size_t smallest = 0; - unsigned char type, bestType = 0; - - for(type = 0; type != 5; ++type) { - attempt[type] = (unsigned char*)lodepng_malloc(linebytes); - if(!attempt[type]) error = 83; /*alloc fail*/ - } - - if(!error) { - for(y = 0; y != h; ++y) { - /*try the 5 filter types*/ - for(type = 0; type != 5; ++type) { - size_t sum = 0; - filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); - - /*calculate the sum of the result*/ - if(type == 0) { - for(x = 0; x != linebytes; ++x) sum += (unsigned char)(attempt[type][x]); - } else { - for(x = 0; x != linebytes; ++x) { - /*For differences, each byte should be treated as signed, values above 127 are negative - (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there. - This means filtertype 0 is almost never chosen, but that is justified.*/ - unsigned char s = attempt[type][x]; - sum += s < 128 ? s : (255U - s); - } - } - - /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ - if(type == 0 || sum < smallest) { - bestType = type; - smallest = sum; - } - } - - prevline = &in[y * linebytes]; - - /*now fill the out values*/ - out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ - for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; - } - } - - for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); - } else if(strategy == LFS_ENTROPY) { - unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ - size_t bestSum = 0; - unsigned type, bestType = 0; - unsigned count[256]; - - for(type = 0; type != 5; ++type) { - attempt[type] = (unsigned char*)lodepng_malloc(linebytes); - if(!attempt[type]) error = 83; /*alloc fail*/ - } - - if(!error) { - for(y = 0; y != h; ++y) { - /*try the 5 filter types*/ - for(type = 0; type != 5; ++type) { - size_t sum = 0; - filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); - lodepng_memset(count, 0, 256 * sizeof(*count)); - for(x = 0; x != linebytes; ++x) ++count[attempt[type][x]]; - ++count[type]; /*the filter type itself is part of the scanline*/ - for(x = 0; x != 256; ++x) { - sum += ilog2i(count[x]); - } - /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ - if(type == 0 || sum > bestSum) { - bestType = type; - bestSum = sum; - } - } - - prevline = &in[y * linebytes]; - - /*now fill the out values*/ - out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ - for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; - } - } - - for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); - } else if(strategy == LFS_PREDEFINED) { - for(y = 0; y != h; ++y) { - size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ - size_t inindex = linebytes * y; - unsigned char type = settings->predefined_filters[y]; - out[outindex] = type; /*filter type byte*/ - filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type); - prevline = &in[inindex]; - } - } else if(strategy == LFS_BRUTE_FORCE) { - /*brute force filter chooser. - deflate the scanline after every filter attempt to see which one deflates best. - This is very slow and gives only slightly smaller, sometimes even larger, result*/ - size_t size[5]; - unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ - size_t smallest = 0; - unsigned type = 0, bestType = 0; - unsigned char* dummy; - LodePNGCompressSettings zlibsettings; - lodepng_memcpy(&zlibsettings, &settings->zlibsettings, sizeof(LodePNGCompressSettings)); - /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose, - to simulate the true case where the tree is the same for the whole image. Sometimes it gives - better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare - cases better compression. It does make this a bit less slow, so it's worth doing this.*/ - zlibsettings.btype = 1; - /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG - images only, so disable it*/ - zlibsettings.custom_zlib = 0; - zlibsettings.custom_deflate = 0; - for(type = 0; type != 5; ++type) { - attempt[type] = (unsigned char*)lodepng_malloc(linebytes); - if(!attempt[type]) error = 83; /*alloc fail*/ - } - if(!error) { - for(y = 0; y != h; ++y) /*try the 5 filter types*/ { - for(type = 0; type != 5; ++type) { - unsigned testsize = (unsigned)linebytes; - /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/ - - filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); - size[type] = 0; - dummy = 0; - zlib_compress(&dummy, &size[type], attempt[type], testsize, &zlibsettings); - lodepng_free(dummy); - /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/ - if(type == 0 || size[type] < smallest) { - bestType = type; - smallest = size[type]; - } - } - prevline = &in[y * linebytes]; - out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ - for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; - } - } - for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); - } - else return 88; /* unknown filter strategy */ - - return error; -} - -static void addPaddingBits(unsigned char* out, const unsigned char* in, - size_t olinebits, size_t ilinebits, unsigned h) { - /*The opposite of the removePaddingBits function - olinebits must be >= ilinebits*/ - unsigned y; - size_t diff = olinebits - ilinebits; - size_t obp = 0, ibp = 0; /*bit pointers*/ - for(y = 0; y != h; ++y) { - size_t x; - for(x = 0; x < ilinebits; ++x) { - unsigned char bit = readBitFromReversedStream(&ibp, in); - setBitOfReversedStream(&obp, out, bit); - } - /*obp += diff; --> no, fill in some value in the padding bits too, to avoid - "Use of uninitialised value of size ###" warning from valgrind*/ - for(x = 0; x != diff; ++x) setBitOfReversedStream(&obp, out, 0); - } -} - -/* -in: non-interlaced image with size w*h -out: the same pixels, but re-ordered according to PNG's Adam7 interlacing, with - no padding bits between scanlines, but between reduced images so that each - reduced image starts at a byte. -bpp: bits per pixel -there are no padding bits, not between scanlines, not between reduced images -in has the following size in bits: w * h * bpp. -out is possibly bigger due to padding bits between reduced images -NOTE: comments about padding bits are only relevant if bpp < 8 -*/ -static void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) { - unsigned passw[7], passh[7]; - size_t filter_passstart[8], padded_passstart[8], passstart[8]; - unsigned i; - - Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); - - if(bpp >= 8) { - for(i = 0; i != 7; ++i) { - unsigned x, y, b; - size_t bytewidth = bpp / 8u; - for(y = 0; y < passh[i]; ++y) - for(x = 0; x < passw[i]; ++x) { - size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; - size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth; - for(b = 0; b < bytewidth; ++b) { - out[pixeloutstart + b] = in[pixelinstart + b]; - } - } - } - } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ { - for(i = 0; i != 7; ++i) { - unsigned x, y, b; - unsigned ilinebits = bpp * passw[i]; - unsigned olinebits = bpp * w; - size_t obp, ibp; /*bit pointers (for out and in buffer)*/ - for(y = 0; y < passh[i]; ++y) - for(x = 0; x < passw[i]; ++x) { - ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; - obp = (8 * passstart[i]) + (y * ilinebits + x * bpp); - for(b = 0; b < bpp; ++b) { - unsigned char bit = readBitFromReversedStream(&ibp, in); - setBitOfReversedStream(&obp, out, bit); - } - } - } - } -} - -/*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image. -return value is error**/ -static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in, - unsigned w, unsigned h, - const LodePNGInfo* info_png, const LodePNGEncoderSettings* settings) { - /* - This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps: - *) if no Adam7: 1) add padding bits (= possible extra bits per scanline if bpp < 8) 2) filter - *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter - */ - unsigned bpp = lodepng_get_bpp(&info_png->color); - unsigned error = 0; - - if(info_png->interlace_method == 0) { - *outsize = h + (h * ((w * bpp + 7u) / 8u)); /*image size plus an extra byte per scanline + possible padding bits*/ - *out = (unsigned char*)lodepng_malloc(*outsize); - if(!(*out) && (*outsize)) error = 83; /*alloc fail*/ - - if(!error) { - /*non multiple of 8 bits per scanline, padding bits needed per scanline*/ - if(bpp < 8 && w * bpp != ((w * bpp + 7u) / 8u) * 8u) { - unsigned char* padded = (unsigned char*)lodepng_malloc(h * ((w * bpp + 7u) / 8u)); - if(!padded) error = 83; /*alloc fail*/ - if(!error) { - addPaddingBits(padded, in, ((w * bpp + 7u) / 8u) * 8u, w * bpp, h); - error = filter(*out, padded, w, h, &info_png->color, settings); - } - lodepng_free(padded); - } else { - /*we can immediately filter into the out buffer, no other steps needed*/ - error = filter(*out, in, w, h, &info_png->color, settings); - } - } - } else /*interlace_method is 1 (Adam7)*/ { - unsigned passw[7], passh[7]; - size_t filter_passstart[8], padded_passstart[8], passstart[8]; - unsigned char* adam7; - - Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); - - *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/ - *out = (unsigned char*)lodepng_malloc(*outsize); - if(!(*out)) error = 83; /*alloc fail*/ - - adam7 = (unsigned char*)lodepng_malloc(passstart[7]); - if(!adam7 && passstart[7]) error = 83; /*alloc fail*/ - - if(!error && adam7) { - unsigned i; - - Adam7_interlace(adam7, in, w, h, bpp); - for(i = 0; i != 7; ++i) { - if(bpp < 8) { - unsigned char* padded = (unsigned char*)lodepng_malloc(padded_passstart[i + 1] - padded_passstart[i]); - if(!padded) ERROR_BREAK(83); /*alloc fail*/ - addPaddingBits(padded, &adam7[passstart[i]], - ((passw[i] * bpp + 7u) / 8u) * 8u, passw[i] * bpp, passh[i]); - error = filter(&(*out)[filter_passstart[i]], padded, - passw[i], passh[i], &info_png->color, settings); - lodepng_free(padded); - } else { - error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]], - passw[i], passh[i], &info_png->color, settings); - } - - if(error) break; - } - } - - lodepng_free(adam7); - } - - return error; -} - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS -static unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t datasize) { - unsigned char* inchunk = data; - while((size_t)(inchunk - data) < datasize) { - CERROR_TRY_RETURN(lodepng_chunk_append(&out->data, &out->size, inchunk)); - out->allocsize = out->size; /*fix the allocsize again*/ - inchunk = lodepng_chunk_next(inchunk, data + datasize); - } - return 0; -} - -static unsigned isGrayICCProfile(const unsigned char* profile, unsigned size) { - /* - It is a gray profile if bytes 16-19 are "GRAY", rgb profile if bytes 16-19 - are "RGB ". We do not perform any full parsing of the ICC profile here, other - than check those 4 bytes to grayscale profile. Other than that, validity of - the profile is not checked. This is needed only because the PNG specification - requires using a non-gray color model if there is an ICC profile with "RGB " - (sadly limiting compression opportunities if the input data is grayscale RGB - data), and requires using a gray color model if it is "GRAY". - */ - if(size < 20) return 0; - return profile[16] == 'G' && profile[17] == 'R' && profile[18] == 'A' && profile[19] == 'Y'; -} - -static unsigned isRGBICCProfile(const unsigned char* profile, unsigned size) { - /* See comment in isGrayICCProfile*/ - if(size < 20) return 0; - return profile[16] == 'R' && profile[17] == 'G' && profile[18] == 'B' && profile[19] == ' '; -} -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -unsigned lodepng_encode(unsigned char** out, size_t* outsize, - const unsigned char* image, unsigned w, unsigned h, - LodePNGState* state) { - unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/ - size_t datasize = 0; - ucvector outv = ucvector_init(NULL, 0); - LodePNGInfo info; - const LodePNGInfo* info_png = &state->info_png; - - lodepng_info_init(&info); - - /*provide some proper output values if error will happen*/ - *out = 0; - *outsize = 0; - state->error = 0; - - /*check input values validity*/ - if((info_png->color.colortype == LCT_PALETTE || state->encoder.force_palette) - && (info_png->color.palettesize == 0 || info_png->color.palettesize > 256)) { - state->error = 68; /*invalid palette size, it is only allowed to be 1-256*/ - goto cleanup; - } - if(state->encoder.zlibsettings.btype > 2) { - state->error = 61; /*error: invalid btype*/ - goto cleanup; - } - if(info_png->interlace_method > 1) { - state->error = 71; /*error: invalid interlace mode*/ - goto cleanup; - } - state->error = checkColorValidity(info_png->color.colortype, info_png->color.bitdepth); - if(state->error) goto cleanup; /*error: invalid color type given*/ - state->error = checkColorValidity(state->info_raw.colortype, state->info_raw.bitdepth); - if(state->error) goto cleanup; /*error: invalid color type given*/ - - /* color convert and compute scanline filter types */ - lodepng_info_copy(&info, &state->info_png); - if(state->encoder.auto_convert) { - LodePNGColorStats stats; - lodepng_color_stats_init(&stats); -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - if(info_png->iccp_defined && - isGrayICCProfile(info_png->iccp_profile, info_png->iccp_profile_size)) { - /*the PNG specification does not allow to use palette with a GRAY ICC profile, even - if the palette has only gray colors, so disallow it.*/ - stats.allow_palette = 0; - } - if(info_png->iccp_defined && - isRGBICCProfile(info_png->iccp_profile, info_png->iccp_profile_size)) { - /*the PNG specification does not allow to use grayscale color with RGB ICC profile, so disallow gray.*/ - stats.allow_greyscale = 0; - } -#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ - state->error = lodepng_compute_color_stats(&stats, image, w, h, &state->info_raw); - if(state->error) goto cleanup; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - if(info_png->background_defined) { - /*the background chunk's color must be taken into account as well*/ - unsigned r = 0, g = 0, b = 0; - LodePNGColorMode mode16 = lodepng_color_mode_make(LCT_RGB, 16); - lodepng_convert_rgb(&r, &g, &b, info_png->background_r, info_png->background_g, info_png->background_b, &mode16, &info_png->color); - state->error = lodepng_color_stats_add(&stats, r, g, b, 65535); - if(state->error) goto cleanup; - } -#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ - state->error = auto_choose_color(&info.color, &state->info_raw, &stats); - if(state->error) goto cleanup; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*also convert the background chunk*/ - if(info_png->background_defined) { - if(lodepng_convert_rgb(&info.background_r, &info.background_g, &info.background_b, - info_png->background_r, info_png->background_g, info_png->background_b, &info.color, &info_png->color)) { - state->error = 104; - goto cleanup; - } - } -#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ - } -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - if(info_png->iccp_defined) { - unsigned gray_icc = isGrayICCProfile(info_png->iccp_profile, info_png->iccp_profile_size); - unsigned rgb_icc = isRGBICCProfile(info_png->iccp_profile, info_png->iccp_profile_size); - unsigned gray_png = info.color.colortype == LCT_GREY || info.color.colortype == LCT_GREY_ALPHA; - if(!gray_icc && !rgb_icc) { - state->error = 100; /* Disallowed profile color type for PNG */ - goto cleanup; - } - if(gray_icc != gray_png) { - /*Not allowed to use RGB/RGBA/palette with GRAY ICC profile or vice versa, - or in case of auto_convert, it wasn't possible to find appropriate model*/ - state->error = state->encoder.auto_convert ? 102 : 101; - goto cleanup; - } - } -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - if(!lodepng_color_mode_equal(&state->info_raw, &info.color)) { - unsigned char* converted; - size_t size = ((size_t)w * (size_t)h * (size_t)lodepng_get_bpp(&info.color) + 7u) / 8u; - - converted = (unsigned char*)lodepng_malloc(size); - if(!converted && size) state->error = 83; /*alloc fail*/ - if(!state->error) { - state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h); - } - if(!state->error) { - state->error = preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder); - } - lodepng_free(converted); - if(state->error) goto cleanup; - } else { - state->error = preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder); - if(state->error) goto cleanup; - } - - /* output all PNG chunks */ { -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - size_t i; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - /*write signature and chunks*/ - state->error = writeSignature(&outv); - if(state->error) goto cleanup; - /*IHDR*/ - state->error = addChunk_IHDR(&outv, w, h, info.color.colortype, info.color.bitdepth, info.interlace_method); - if(state->error) goto cleanup; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*unknown chunks between IHDR and PLTE*/ - if(info.unknown_chunks_data[0]) { - state->error = addUnknownChunks(&outv, info.unknown_chunks_data[0], info.unknown_chunks_size[0]); - if(state->error) goto cleanup; - } - /*color profile chunks must come before PLTE */ - if(info.iccp_defined) { - state->error = addChunk_iCCP(&outv, &info, &state->encoder.zlibsettings); - if(state->error) goto cleanup; - } - if(info.srgb_defined) { - state->error = addChunk_sRGB(&outv, &info); - if(state->error) goto cleanup; - } - if(info.gama_defined) { - state->error = addChunk_gAMA(&outv, &info); - if(state->error) goto cleanup; - } - if(info.chrm_defined) { - state->error = addChunk_cHRM(&outv, &info); - if(state->error) goto cleanup; - } -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - /*PLTE*/ - if(info.color.colortype == LCT_PALETTE) { - state->error = addChunk_PLTE(&outv, &info.color); - if(state->error) goto cleanup; - } - if(state->encoder.force_palette && (info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA)) { - /*force_palette means: write suggested palette for truecolor in PLTE chunk*/ - state->error = addChunk_PLTE(&outv, &info.color); - if(state->error) goto cleanup; - } - /*tRNS (this will only add if when necessary) */ - state->error = addChunk_tRNS(&outv, &info.color); - if(state->error) goto cleanup; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*bKGD (must come between PLTE and the IDAt chunks*/ - if(info.background_defined) { - state->error = addChunk_bKGD(&outv, &info); - if(state->error) goto cleanup; - } - /*pHYs (must come before the IDAT chunks)*/ - if(info.phys_defined) { - state->error = addChunk_pHYs(&outv, &info); - if(state->error) goto cleanup; - } - - /*unknown chunks between PLTE and IDAT*/ - if(info.unknown_chunks_data[1]) { - state->error = addUnknownChunks(&outv, info.unknown_chunks_data[1], info.unknown_chunks_size[1]); - if(state->error) goto cleanup; - } -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - /*IDAT (multiple IDAT chunks must be consecutive)*/ - state->error = addChunk_IDAT(&outv, data, datasize, &state->encoder.zlibsettings); - if(state->error) goto cleanup; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*tIME*/ - if(info.time_defined) { - state->error = addChunk_tIME(&outv, &info.time); - if(state->error) goto cleanup; - } - /*tEXt and/or zTXt*/ - for(i = 0; i != info.text_num; ++i) { - if(lodepng_strlen(info.text_keys[i]) > 79) { - state->error = 66; /*text chunk too large*/ - goto cleanup; - } - if(lodepng_strlen(info.text_keys[i]) < 1) { - state->error = 67; /*text chunk too small*/ - goto cleanup; - } - if(state->encoder.text_compression) { - state->error = addChunk_zTXt(&outv, info.text_keys[i], info.text_strings[i], &state->encoder.zlibsettings); - if(state->error) goto cleanup; - } else { - state->error = addChunk_tEXt(&outv, info.text_keys[i], info.text_strings[i]); - if(state->error) goto cleanup; - } - } - /*LodePNG version id in text chunk*/ - if(state->encoder.add_id) { - unsigned already_added_id_text = 0; - for(i = 0; i != info.text_num; ++i) { - const char* k = info.text_keys[i]; - /* Could use strcmp, but we're not calling or reimplementing this C library function for this use only */ - if(k[0] == 'L' && k[1] == 'o' && k[2] == 'd' && k[3] == 'e' && - k[4] == 'P' && k[5] == 'N' && k[6] == 'G' && k[7] == '\0') { - already_added_id_text = 1; - break; - } - } - if(already_added_id_text == 0) { - state->error = addChunk_tEXt(&outv, "LodePNG", LODEPNG_VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/ - if(state->error) goto cleanup; - } - } - /*iTXt*/ - for(i = 0; i != info.itext_num; ++i) { - if(lodepng_strlen(info.itext_keys[i]) > 79) { - state->error = 66; /*text chunk too large*/ - goto cleanup; - } - if(lodepng_strlen(info.itext_keys[i]) < 1) { - state->error = 67; /*text chunk too small*/ - goto cleanup; - } - state->error = addChunk_iTXt( - &outv, state->encoder.text_compression, - info.itext_keys[i], info.itext_langtags[i], info.itext_transkeys[i], info.itext_strings[i], - &state->encoder.zlibsettings); - if(state->error) goto cleanup; - } - - /*unknown chunks between IDAT and IEND*/ - if(info.unknown_chunks_data[2]) { - state->error = addUnknownChunks(&outv, info.unknown_chunks_data[2], info.unknown_chunks_size[2]); - if(state->error) goto cleanup; - } -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - state->error = addChunk_IEND(&outv); - if(state->error) goto cleanup; - } - -cleanup: - lodepng_info_cleanup(&info); - lodepng_free(data); - - /*instead of cleaning the vector up, give it to the output*/ - *out = outv.data; - *outsize = outv.size; - - return state->error; -} - -unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, const unsigned char* image, - unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) { - unsigned error; - LodePNGState state; - lodepng_state_init(&state); - state.info_raw.colortype = colortype; - state.info_raw.bitdepth = bitdepth; - state.info_png.color.colortype = colortype; - state.info_png.color.bitdepth = bitdepth; - lodepng_encode(out, outsize, image, w, h, &state); - error = state.error; - lodepng_state_cleanup(&state); - return error; -} - -unsigned lodepng_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) { - return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGBA, 8); -} - -unsigned lodepng_encode24(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) { - return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGB, 8); -} - -#ifdef LODEPNG_COMPILE_DISK -unsigned lodepng_encode_file(const char* filename, const unsigned char* image, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth) { - unsigned char* buffer; - size_t buffersize; - unsigned error = lodepng_encode_memory(&buffer, &buffersize, image, w, h, colortype, bitdepth); - if(!error) error = lodepng_save_file(buffer, buffersize, filename); - lodepng_free(buffer); - return error; -} - -unsigned lodepng_encode32_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) { - return lodepng_encode_file(filename, image, w, h, LCT_RGBA, 8); -} - -unsigned lodepng_encode24_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) { - return lodepng_encode_file(filename, image, w, h, LCT_RGB, 8); -} -#endif /*LODEPNG_COMPILE_DISK*/ - -void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings) { - lodepng_compress_settings_init(&settings->zlibsettings); - settings->filter_palette_zero = 1; - settings->filter_strategy = LFS_MINSUM; - settings->auto_convert = 1; - settings->force_palette = 0; - settings->predefined_filters = 0; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - settings->add_id = 0; - settings->text_compression = 1; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -} - -#endif /*LODEPNG_COMPILE_ENCODER*/ -#endif /*LODEPNG_COMPILE_PNG*/ - -#ifdef LODEPNG_COMPILE_ERROR_TEXT -/* -This returns the description of a numerical error code in English. This is also -the documentation of all the error codes. -*/ -const char* lodepng_error_text(unsigned code) { - switch(code) { - case 0: return "no error, everything went ok"; - case 1: return "nothing done yet"; /*the Encoder/Decoder has done nothing yet, error checking makes no sense yet*/ - case 10: return "end of input memory reached without huffman end code"; /*while huffman decoding*/ - case 11: return "error in code tree made it jump outside of huffman tree"; /*while huffman decoding*/ - case 13: return "problem while processing dynamic deflate block"; - case 14: return "problem while processing dynamic deflate block"; - case 15: return "problem while processing dynamic deflate block"; - /*this error could happen if there are only 0 or 1 symbols present in the huffman code:*/ - case 16: return "invalid code while processing dynamic deflate block"; - case 17: return "end of out buffer memory reached while inflating"; - case 18: return "invalid distance code while inflating"; - case 19: return "end of out buffer memory reached while inflating"; - case 20: return "invalid deflate block BTYPE encountered while decoding"; - case 21: return "NLEN is not ones complement of LEN in a deflate block"; - - /*end of out buffer memory reached while inflating: - This can happen if the inflated deflate data is longer than the amount of bytes required to fill up - all the pixels of the image, given the color depth and image dimensions. Something that doesn't - happen in a normal, well encoded, PNG image.*/ - case 22: return "end of out buffer memory reached while inflating"; - case 23: return "end of in buffer memory reached while inflating"; - case 24: return "invalid FCHECK in zlib header"; - case 25: return "invalid compression method in zlib header"; - case 26: return "FDICT encountered in zlib header while it's not used for PNG"; - case 27: return "PNG file is smaller than a PNG header"; - /*Checks the magic file header, the first 8 bytes of the PNG file*/ - case 28: return "incorrect PNG signature, it's no PNG or corrupted"; - case 29: return "first chunk is not the header chunk"; - case 30: return "chunk length too large, chunk broken off at end of file"; - case 31: return "illegal PNG color type or bpp"; - case 32: return "illegal PNG compression method"; - case 33: return "illegal PNG filter method"; - case 34: return "illegal PNG interlace method"; - case 35: return "chunk length of a chunk is too large or the chunk too small"; - case 36: return "illegal PNG filter type encountered"; - case 37: return "illegal bit depth for this color type given"; - case 38: return "the palette is too small or too big"; /*0, or more than 256 colors*/ - case 39: return "tRNS chunk before PLTE or has more entries than palette size"; - case 40: return "tRNS chunk has wrong size for grayscale image"; - case 41: return "tRNS chunk has wrong size for RGB image"; - case 42: return "tRNS chunk appeared while it was not allowed for this color type"; - case 43: return "bKGD chunk has wrong size for palette image"; - case 44: return "bKGD chunk has wrong size for grayscale image"; - case 45: return "bKGD chunk has wrong size for RGB image"; - case 48: return "empty input buffer given to decoder. Maybe caused by non-existing file?"; - case 49: return "jumped past memory while generating dynamic huffman tree"; - case 50: return "jumped past memory while generating dynamic huffman tree"; - case 51: return "jumped past memory while inflating huffman block"; - case 52: return "jumped past memory while inflating"; - case 53: return "size of zlib data too small"; - case 54: return "repeat symbol in tree while there was no value symbol yet"; - /*jumped past tree while generating huffman tree, this could be when the - tree will have more leaves than symbols after generating it out of the - given lengths. They call this an oversubscribed dynamic bit lengths tree in zlib.*/ - case 55: return "jumped past tree while generating huffman tree"; - case 56: return "given output image colortype or bitdepth not supported for color conversion"; - case 57: return "invalid CRC encountered (checking CRC can be disabled)"; - case 58: return "invalid ADLER32 encountered (checking ADLER32 can be disabled)"; - case 59: return "requested color conversion not supported"; - case 60: return "invalid window size given in the settings of the encoder (must be 0-32768)"; - case 61: return "invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)"; - /*LodePNG leaves the choice of RGB to grayscale conversion formula to the user.*/ - case 62: return "conversion from color to grayscale not supported"; - /*(2^31-1)*/ - case 63: return "length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk"; - /*this would result in the inability of a deflated block to ever contain an end code. It must be at least 1.*/ - case 64: return "the length of the END symbol 256 in the Huffman tree is 0"; - case 66: return "the length of a text chunk keyword given to the encoder is longer than the maximum of 79 bytes"; - case 67: return "the length of a text chunk keyword given to the encoder is smaller than the minimum of 1 byte"; - case 68: return "tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors"; - case 69: return "unknown chunk type with 'critical' flag encountered by the decoder"; - case 71: return "invalid interlace mode given to encoder (must be 0 or 1)"; - case 72: return "while decoding, invalid compression method encountering in zTXt or iTXt chunk (it must be 0)"; - case 73: return "invalid tIME chunk size"; - case 74: return "invalid pHYs chunk size"; - /*length could be wrong, or data chopped off*/ - case 75: return "no null termination char found while decoding text chunk"; - case 76: return "iTXt chunk too short to contain required bytes"; - case 77: return "integer overflow in buffer size"; - case 78: return "failed to open file for reading"; /*file doesn't exist or couldn't be opened for reading*/ - case 79: return "failed to open file for writing"; - case 80: return "tried creating a tree of 0 symbols"; - case 81: return "lazy matching at pos 0 is impossible"; - case 82: return "color conversion to palette requested while a color isn't in palette, or index out of bounds"; - case 83: return "memory allocation failed"; - case 84: return "given image too small to contain all pixels to be encoded"; - case 86: return "impossible offset in lz77 encoding (internal bug)"; - case 87: return "must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined"; - case 88: return "invalid filter strategy given for LodePNGEncoderSettings.filter_strategy"; - case 89: return "text chunk keyword too short or long: must have size 1-79"; - /*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/ - case 90: return "windowsize must be a power of two"; - case 91: return "invalid decompressed idat size"; - case 92: return "integer overflow due to too many pixels"; - case 93: return "zero width or height is invalid"; - case 94: return "header chunk must have a size of 13 bytes"; - case 95: return "integer overflow with combined idat chunk size"; - case 96: return "invalid gAMA chunk size"; - case 97: return "invalid cHRM chunk size"; - case 98: return "invalid sRGB chunk size"; - case 99: return "invalid sRGB rendering intent"; - case 100: return "invalid ICC profile color type, the PNG specification only allows RGB or GRAY"; - case 101: return "PNG specification does not allow RGB ICC profile on gray color types and vice versa"; - case 102: return "not allowed to set grayscale ICC profile with colored pixels by PNG specification"; - case 103: return "invalid palette index in bKGD chunk. Maybe it came before PLTE chunk?"; - case 104: return "invalid bKGD color while encoding (e.g. palette index out of range)"; - case 105: return "integer overflow of bitsize"; - case 106: return "PNG file must have PLTE chunk if color type is palette"; - case 107: return "color convert from palette mode requested without setting the palette data in it"; - case 108: return "tried to add more than 256 values to a palette"; - /*this limit can be configured in LodePNGDecompressSettings*/ - case 109: return "tried to decompress zlib or deflate data larger than desired max_output_size"; - case 110: return "custom zlib or inflate decompression failed"; - case 111: return "custom zlib or deflate compression failed"; - /*max text size limit can be configured in LodePNGDecoderSettings. This error prevents - unreasonable memory consumption when decoding due to impossibly large text sizes.*/ - case 112: return "compressed text unreasonably large"; - /*max ICC size limit can be configured in LodePNGDecoderSettings. This error prevents - unreasonable memory consumption when decoding due to impossibly large ICC profile*/ - case 113: return "ICC profile unreasonably large"; - } - return "unknown error code"; -} -#endif /*LODEPNG_COMPILE_ERROR_TEXT*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* // C++ Wrapper // */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_CPP -namespace lodepng { - -#ifdef LODEPNG_COMPILE_DISK -unsigned load_file(std::vector& buffer, const std::string& filename) { - long size = lodepng_filesize(filename.c_str()); - if(size < 0) return 78; - buffer.resize((size_t)size); - return size == 0 ? 0 : lodepng_buffer_file(&buffer[0], (size_t)size, filename.c_str()); -} - -/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ -unsigned save_file(const std::vector& buffer, const std::string& filename) { - return lodepng_save_file(buffer.empty() ? 0 : &buffer[0], buffer.size(), filename.c_str()); -} -#endif /* LODEPNG_COMPILE_DISK */ - -#ifdef LODEPNG_COMPILE_ZLIB -#ifdef LODEPNG_COMPILE_DECODER -unsigned decompress(std::vector& out, const unsigned char* in, size_t insize, - const LodePNGDecompressSettings& settings) { - unsigned char* buffer = 0; - size_t buffersize = 0; - unsigned error = zlib_decompress(&buffer, &buffersize, 0, in, insize, &settings); - if(buffer) { - out.insert(out.end(), &buffer[0], &buffer[buffersize]); - lodepng_free(buffer); - } - return error; -} - -unsigned decompress(std::vector& out, const std::vector& in, - const LodePNGDecompressSettings& settings) { - return decompress(out, in.empty() ? 0 : &in[0], in.size(), settings); -} -#endif /* LODEPNG_COMPILE_DECODER */ - -#ifdef LODEPNG_COMPILE_ENCODER -unsigned compress(std::vector& out, const unsigned char* in, size_t insize, - const LodePNGCompressSettings& settings) { - unsigned char* buffer = 0; - size_t buffersize = 0; - unsigned error = zlib_compress(&buffer, &buffersize, in, insize, &settings); - if(buffer) { - out.insert(out.end(), &buffer[0], &buffer[buffersize]); - lodepng_free(buffer); - } - return error; -} - -unsigned compress(std::vector& out, const std::vector& in, - const LodePNGCompressSettings& settings) { - return compress(out, in.empty() ? 0 : &in[0], in.size(), settings); -} -#endif /* LODEPNG_COMPILE_ENCODER */ -#endif /* LODEPNG_COMPILE_ZLIB */ - - -#ifdef LODEPNG_COMPILE_PNG - -State::State() { - lodepng_state_init(this); -} - -State::State(const State& other) { - lodepng_state_init(this); - lodepng_state_copy(this, &other); -} - -State::~State() { - lodepng_state_cleanup(this); -} - -State& State::operator=(const State& other) { - lodepng_state_copy(this, &other); - return *this; -} - -#ifdef LODEPNG_COMPILE_DECODER - -unsigned decode(std::vector& out, unsigned& w, unsigned& h, const unsigned char* in, - size_t insize, LodePNGColorType colortype, unsigned bitdepth) { - unsigned char* buffer = 0; - unsigned error = lodepng_decode_memory(&buffer, &w, &h, in, insize, colortype, bitdepth); - if(buffer && !error) { - State state; - state.info_raw.colortype = colortype; - state.info_raw.bitdepth = bitdepth; - size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); - out.insert(out.end(), &buffer[0], &buffer[buffersize]); - } - lodepng_free(buffer); - return error; -} - -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - const std::vector& in, LodePNGColorType colortype, unsigned bitdepth) { - return decode(out, w, h, in.empty() ? 0 : &in[0], (unsigned)in.size(), colortype, bitdepth); -} - -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - State& state, - const unsigned char* in, size_t insize) { - unsigned char* buffer = NULL; - unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize); - if(buffer && !error) { - size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); - out.insert(out.end(), &buffer[0], &buffer[buffersize]); - } - lodepng_free(buffer); - return error; -} - -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - State& state, - const std::vector& in) { - return decode(out, w, h, state, in.empty() ? 0 : &in[0], in.size()); -} - -#ifdef LODEPNG_COMPILE_DISK -unsigned decode(std::vector& out, unsigned& w, unsigned& h, const std::string& filename, - LodePNGColorType colortype, unsigned bitdepth) { - std::vector buffer; - /* safe output values in case error happens */ - w = h = 0; - unsigned error = load_file(buffer, filename); - if(error) return error; - return decode(out, w, h, buffer, colortype, bitdepth); -} -#endif /* LODEPNG_COMPILE_DECODER */ -#endif /* LODEPNG_COMPILE_DISK */ - -#ifdef LODEPNG_COMPILE_ENCODER -unsigned encode(std::vector& out, const unsigned char* in, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth) { - unsigned char* buffer; - size_t buffersize; - unsigned error = lodepng_encode_memory(&buffer, &buffersize, in, w, h, colortype, bitdepth); - if(buffer) { - out.insert(out.end(), &buffer[0], &buffer[buffersize]); - lodepng_free(buffer); - } - return error; -} - -unsigned encode(std::vector& out, - const std::vector& in, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth) { - if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; - return encode(out, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); -} - -unsigned encode(std::vector& out, - const unsigned char* in, unsigned w, unsigned h, - State& state) { - unsigned char* buffer; - size_t buffersize; - unsigned error = lodepng_encode(&buffer, &buffersize, in, w, h, &state); - if(buffer) { - out.insert(out.end(), &buffer[0], &buffer[buffersize]); - lodepng_free(buffer); - } - return error; -} - -unsigned encode(std::vector& out, - const std::vector& in, unsigned w, unsigned h, - State& state) { - if(lodepng_get_raw_size(w, h, &state.info_raw) > in.size()) return 84; - return encode(out, in.empty() ? 0 : &in[0], w, h, state); -} - -#ifdef LODEPNG_COMPILE_DISK -unsigned encode(const std::string& filename, - const unsigned char* in, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth) { - std::vector buffer; - unsigned error = encode(buffer, in, w, h, colortype, bitdepth); - if(!error) error = save_file(buffer, filename); - return error; -} - -unsigned encode(const std::string& filename, - const std::vector& in, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth) { - if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; - return encode(filename, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); -} -#endif /* LODEPNG_COMPILE_DISK */ -#endif /* LODEPNG_COMPILE_ENCODER */ -#endif /* LODEPNG_COMPILE_PNG */ -} /* namespace lodepng */ -#endif /*LODEPNG_COMPILE_CPP*/ - -#endif /*LV_USE_PNG*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.c deleted file mode 100644 index 9228e29c8..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.c +++ /dev/null @@ -1,278 +0,0 @@ -/** - * @file lv_png.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../../../lvgl.h" -#if LV_USE_PNG - -#include "lv_png.h" -#include "lodepng.h" -#include - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_res_t decoder_info(struct _lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header); -static lv_res_t decoder_open(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc); -static void decoder_close(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc); -static void convert_color_depth(uint8_t * img, uint32_t px_cnt); - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Register the PNG decoder functions in LVGL - */ -void lv_png_init(void) -{ - lv_img_decoder_t * dec = lv_img_decoder_create(); - lv_img_decoder_set_info_cb(dec, decoder_info); - lv_img_decoder_set_open_cb(dec, decoder_open); - lv_img_decoder_set_close_cb(dec, decoder_close); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Get info about a PNG image - * @param src can be file name or pointer to a C array - * @param header store the info here - * @return LV_RES_OK: no error; LV_RES_INV: can't get the info - */ -static lv_res_t decoder_info(struct _lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header) -{ - (void) decoder; /*Unused*/ - lv_img_src_t src_type = lv_img_src_get_type(src); /*Get the source type*/ - - /*If it's a PNG file...*/ - if(src_type == LV_IMG_SRC_FILE) { - const char * fn = src; - if(strcmp(lv_fs_get_ext(fn), "png") == 0) { /*Check the extension*/ - - /* Read the width and height from the file. They have a constant location: - * [16..23]: width - * [24..27]: height - */ - uint32_t size[2]; - lv_fs_file_t f; - lv_fs_res_t res = lv_fs_open(&f, fn, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) return LV_RES_INV; - - lv_fs_seek(&f, 16, LV_FS_SEEK_SET); - - uint32_t rn; - lv_fs_read(&f, &size, 8, &rn); - lv_fs_close(&f); - - if(rn != 8) return LV_RES_INV; - - /*Save the data in the header*/ - header->always_zero = 0; - header->cf = LV_IMG_CF_TRUE_COLOR_ALPHA; - /*The width and height are stored in Big endian format so convert them to little endian*/ - header->w = (lv_coord_t)((size[0] & 0xff000000) >> 24) + ((size[0] & 0x00ff0000) >> 8); - header->h = (lv_coord_t)((size[1] & 0xff000000) >> 24) + ((size[1] & 0x00ff0000) >> 8); - - return LV_RES_OK; - } - } - /*If it's a PNG file in a C array...*/ - else if(src_type == LV_IMG_SRC_VARIABLE) { - const lv_img_dsc_t * img_dsc = src; - const uint32_t data_size = img_dsc->data_size; - const uint32_t * size = ((uint32_t *)img_dsc->data) + 4; - const uint8_t magic[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a}; - if(data_size < sizeof(magic)) return LV_RES_INV; - if(memcmp(magic, img_dsc->data, sizeof(magic))) return LV_RES_INV; - header->always_zero = 0; - - if(img_dsc->header.cf) { - header->cf = img_dsc->header.cf; /*Save the color format*/ - } - else { - header->cf = LV_IMG_CF_TRUE_COLOR_ALPHA; - } - - if(img_dsc->header.w) { - header->w = img_dsc->header.w; /*Save the image width*/ - } - else { - header->w = (lv_coord_t)((size[0] & 0xff000000) >> 24) + ((size[0] & 0x00ff0000) >> 8); - } - - if(img_dsc->header.h) { - header->h = img_dsc->header.h; /*Save the color height*/ - } - else { - header->h = (lv_coord_t)((size[1] & 0xff000000) >> 24) + ((size[1] & 0x00ff0000) >> 8); - } - - return LV_RES_OK; - } - - return LV_RES_INV; /*If didn't succeeded earlier then it's an error*/ -} - - -/** - * Open a PNG image and return the decided image - * @param src can be file name or pointer to a C array - * @param style style of the image object (unused now but certain formats might use it) - * @return pointer to the decoded image or `LV_IMG_DECODER_OPEN_FAIL` if failed - */ -static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) -{ - - (void) decoder; /*Unused*/ - uint32_t error; /*For the return values of PNG decoder functions*/ - - uint8_t * img_data = NULL; - - /*If it's a PNG file...*/ - if(dsc->src_type == LV_IMG_SRC_FILE) { - const char * fn = dsc->src; - if(strcmp(lv_fs_get_ext(fn), "png") == 0) { /*Check the extension*/ - - /*Load the PNG file into buffer. It's still compressed (not decoded)*/ - unsigned char * png_data; /*Pointer to the loaded data. Same as the original file just loaded into the RAM*/ - size_t png_data_size; /*Size of `png_data` in bytes*/ - - error = lodepng_load_file(&png_data, &png_data_size, fn); /*Load the file*/ - if(error) { - LV_LOG_WARN("error %" LV_PRIu32 ": %s\n", error, lodepng_error_text(error)); - return LV_RES_INV; - } - - /*Decode the PNG image*/ - unsigned png_width; /*Will be the width of the decoded image*/ - unsigned png_height; /*Will be the width of the decoded image*/ - - /*Decode the loaded image in ARGB8888 */ - error = lodepng_decode32(&img_data, &png_width, &png_height, png_data, png_data_size); - lv_mem_free(png_data); /*Free the loaded file*/ - if(error) { - if(img_data != NULL) { - lv_mem_free(img_data); - } - LV_LOG_WARN("error %" LV_PRIu32 ": %s\n", error, lodepng_error_text(error)); - return LV_RES_INV; - } - - /*Convert the image to the system's color depth*/ - convert_color_depth(img_data, png_width * png_height); - dsc->img_data = img_data; - return LV_RES_OK; /*The image is fully decoded. Return with its pointer*/ - } - } - /*If it's a PNG file in a C array...*/ - else if(dsc->src_type == LV_IMG_SRC_VARIABLE) { - const lv_img_dsc_t * img_dsc = dsc->src; - unsigned png_width; /*No used, just required by he decoder*/ - unsigned png_height; /*No used, just required by he decoder*/ - - /*Decode the image in ARGB8888 */ - error = lodepng_decode32(&img_data, &png_width, &png_height, img_dsc->data, img_dsc->data_size); - - if(error) { - if(img_data != NULL) { - lv_mem_free(img_data); - } - return LV_RES_INV; - } - - /*Convert the image to the system's color depth*/ - convert_color_depth(img_data, png_width * png_height); - - dsc->img_data = img_data; - return LV_RES_OK; /*Return with its pointer*/ - } - - return LV_RES_INV; /*If not returned earlier then it failed*/ -} - -/** - * Free the allocated resources - */ -static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) -{ - LV_UNUSED(decoder); /*Unused*/ - if(dsc->img_data) { - lv_mem_free((uint8_t *)dsc->img_data); - dsc->img_data = NULL; - } -} - -/** - * If the display is not in 32 bit format (ARGB888) then covert the image to the current color depth - * @param img the ARGB888 image - * @param px_cnt number of pixels in `img` - */ -static void convert_color_depth(uint8_t * img, uint32_t px_cnt) -{ -#if LV_COLOR_DEPTH == 32 - lv_color32_t * img_argb = (lv_color32_t *)img; - lv_color_t c; - lv_color_t * img_c = (lv_color_t *) img; - uint32_t i; - for(i = 0; i < px_cnt; i++) { - c = lv_color_make(img_argb[i].ch.red, img_argb[i].ch.green, img_argb[i].ch.blue); - img_c[i].ch.red = c.ch.blue; - img_c[i].ch.blue = c.ch.red; - } -#elif LV_COLOR_DEPTH == 16 - lv_color32_t * img_argb = (lv_color32_t *)img; - lv_color_t c; - uint32_t i; - for(i = 0; i < px_cnt; i++) { - c = lv_color_make(img_argb[i].ch.blue, img_argb[i].ch.green, img_argb[i].ch.red); - img[i * 3 + 2] = img_argb[i].ch.alpha; - img[i * 3 + 1] = c.full >> 8; - img[i * 3 + 0] = c.full & 0xFF; - } -#elif LV_COLOR_DEPTH == 8 - lv_color32_t * img_argb = (lv_color32_t *)img; - lv_color_t c; - uint32_t i; - for(i = 0; i < px_cnt; i++) { - c = lv_color_make(img_argb[i].ch.red, img_argb[i].ch.green, img_argb[i].ch.blue); - img[i * 2 + 1] = img_argb[i].ch.alpha; - img[i * 2 + 0] = c.full; - } -#elif LV_COLOR_DEPTH == 1 - lv_color32_t * img_argb = (lv_color32_t *)img; - uint8_t b; - uint32_t i; - for(i = 0; i < px_cnt; i++) { - b = img_argb[i].ch.red | img_argb[i].ch.green | img_argb[i].ch.blue; - img[i * 2 + 1] = img_argb[i].ch.alpha; - img[i * 2 + 0] = b > 128 ? 1 : 0; - } -#endif -} - -#endif /*LV_USE_PNG*/ - - diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.c deleted file mode 100644 index bd9f08b36..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.c +++ /dev/null @@ -1,1035 +0,0 @@ -/* - * QR Code generator library (C) - * - * Copyright (c) Project Nayuki. (MIT License) - * https://www.nayuki.io/page/qr-code-generator-library - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - The Software is provided "as is", without warranty of any kind, express or - * implied, including but not limited to the warranties of merchantability, - * fitness for a particular purpose and noninfringement. In no event shall the - * authors or copyright holders be liable for any claim, damages or other - * liability, whether in an action of contract, tort or otherwise, arising from, - * out of or in connection with the Software or the use or other dealings in the - * Software. - */ - -#include -#include -#include -#include "qrcodegen.h" -#include "../../../misc/lv_assert.h" - -#ifndef QRCODEGEN_TEST - #define testable static // Keep functions private -#else - #define testable // Expose private functions -#endif - - -/*---- Forward declarations for private functions ----*/ - -// Regarding all public and private functions defined in this source file: -// - They require all pointer/array arguments to be not null unless the array length is zero. -// - They only read input scalar/array arguments, write to output pointer/array -// arguments, and return scalar values; they are "pure" functions. -// - They don't read mutable global variables or write to any global variables. -// - They don't perform I/O, read the clock, print to console, etc. -// - They allocate a small and constant amount of stack memory. -// - They don't allocate or free any memory on the heap. -// - They don't recurse or mutually recurse. All the code -// could be inlined into the top-level public functions. -// - They run in at most quadratic time with respect to input arguments. -// Most functions run in linear time, and some in constant time. -// There are no unbounded loops or non-obvious termination conditions. -// - They are completely thread-safe if the caller does not give the -// same writable buffer to concurrent calls to these functions. - -testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen); - -testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]); -testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl); -testable int getNumRawDataModules(int ver); - -testable void calcReedSolomonGenerator(int degree, uint8_t result[]); -testable void calcReedSolomonRemainder(const uint8_t data[], int dataLen, - const uint8_t generator[], int degree, uint8_t result[]); -testable uint8_t finiteFieldMultiply(uint8_t x, uint8_t y); - -testable void initializeFunctionModules(int version, uint8_t qrcode[]); -static void drawWhiteFunctionModules(uint8_t qrcode[], int version); -static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]); -testable int getAlignmentPatternPositions(int version, uint8_t result[7]); -static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]); - -static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]); -static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask); -static long getPenaltyScore(const uint8_t qrcode[]); -static void addRunToHistory(unsigned char run, unsigned char history[7]); -static bool hasFinderLikePattern(const unsigned char runHistory[7]); - -testable bool getModule(const uint8_t qrcode[], int x, int y); -testable void setModule(uint8_t qrcode[], int x, int y, bool isBlack); -testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack); -static bool getBit(int x, int i); - -testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars); -testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version); -static int numCharCountBits(enum qrcodegen_Mode mode, int version); - - - -/*---- Private tables of constants ----*/ - -// The set of all legal characters in alphanumeric mode, where each character -// value maps to the index in the string. For checking text and encoding segments. -static const char *ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; - -// For generating error correction codes. -testable const int8_t ECC_CODEWORDS_PER_BLOCK[4][41] = { - // Version: (note that index 0 is for padding, and is set to an illegal value) - //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low - {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium - {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile - {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High -}; - -#define qrcodegen_REED_SOLOMON_DEGREE_MAX 30 // Based on the table above - -// For generating error correction codes. -testable const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41] = { - // Version: (note that index 0 is for padding, and is set to an illegal value) - //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low - {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium - {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile - {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High -}; - -// For automatic mask pattern selection. -static const int PENALTY_N1 = 3; -static const int PENALTY_N2 = 3; -static const int PENALTY_N3 = 40; -static const int PENALTY_N4 = 10; - - - -/*---- High-level QR Code encoding functions ----*/ - -// Public function - see documentation comment in header file. -bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { - - size_t textLen = strlen(text); - if (textLen == 0) - return qrcodegen_encodeSegmentsAdvanced(NULL, 0, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); - size_t bufLen = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion); - - struct qrcodegen_Segment seg; - if (qrcodegen_isNumeric(text)) { - if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_NUMERIC, textLen) > bufLen) - goto fail; - seg = qrcodegen_makeNumeric(text, tempBuffer); - } else if (qrcodegen_isAlphanumeric(text)) { - if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ALPHANUMERIC, textLen) > bufLen) - goto fail; - seg = qrcodegen_makeAlphanumeric(text, tempBuffer); - } else { - if (textLen > bufLen) - goto fail; - for (size_t i = 0; i < textLen; i++) - tempBuffer[i] = (uint8_t)text[i]; - seg.mode = qrcodegen_Mode_BYTE; - seg.bitLength = calcSegmentBitLength(seg.mode, textLen); - if (seg.bitLength == -1) - goto fail; - seg.numChars = (int)textLen; - seg.data = tempBuffer; - } - return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); - -fail: - qrcode[0] = 0; // Set size to invalid value for safety - return false; -} - - -// Public function - see documentation comment in header file. -bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { - - struct qrcodegen_Segment seg; - seg.mode = qrcodegen_Mode_BYTE; - seg.bitLength = calcSegmentBitLength(seg.mode, dataLen); - if (seg.bitLength == -1) { - qrcode[0] = 0; // Set size to invalid value for safety - return false; - } - seg.numChars = (int)dataLen; - seg.data = dataAndTemp; - return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, dataAndTemp, qrcode); -} - - -// Appends the given number of low-order bits of the given value to the given byte-based -// bit buffer, increasing the bit length. Requires 0 <= numBits <= 16 and val < 2^numBits. -testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen) { - LV_ASSERT(0 <= numBits && numBits <= 16 && (unsigned long)val >> numBits == 0); - for (int i = numBits - 1; i >= 0; i--, (*bitLen)++) - buffer[*bitLen >> 3] |= ((val >> i) & 1) << (7 - (*bitLen & 7)); -} - - - -/*---- Low-level QR Code encoding functions ----*/ - -// Public function - see documentation comment in header file. -bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, - enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]) { - return qrcodegen_encodeSegmentsAdvanced(segs, len, ecl, - qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, -1, true, tempBuffer, qrcode); -} - - -// Public function - see documentation comment in header file. -bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, - int minVersion, int maxVersion, int mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]) { - LV_ASSERT(segs != NULL || len == 0); - LV_ASSERT(qrcodegen_VERSION_MIN <= minVersion && minVersion <= maxVersion && maxVersion <= qrcodegen_VERSION_MAX); - LV_ASSERT(0 <= (int)ecl && (int)ecl <= 3 && -1 <= (int)mask && (int)mask <= 7); - - // Find the minimal version number to use - int version, dataUsedBits; - for (version = minVersion; ; version++) { - int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available - dataUsedBits = getTotalBits(segs, len, version); - if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) - break; // This version number is found to be suitable - if (version >= maxVersion) { // All versions in the range could not fit the given data - qrcode[0] = 0; // Set size to invalid value for safety - return false; - } - } - LV_ASSERT(dataUsedBits != -1); - - // Increase the error correction level while the data still fits in the current version number - for (int i = (int)qrcodegen_Ecc_MEDIUM; i <= (int)qrcodegen_Ecc_HIGH; i++) { // From low to high - if (boostEcl && dataUsedBits <= getNumDataCodewords(version, (enum qrcodegen_Ecc)i) * 8) - ecl = (enum qrcodegen_Ecc)i; - } - - // Concatenate all segments to create the data bit string - memset(qrcode, 0, qrcodegen_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0])); - int bitLen = 0; - for (size_t i = 0; i < len; i++) { - const struct qrcodegen_Segment *seg = &segs[i]; - appendBitsToBuffer((int)seg->mode, 4, qrcode, &bitLen); - appendBitsToBuffer(seg->numChars, numCharCountBits(seg->mode, version), qrcode, &bitLen); - for (int j = 0; j < seg->bitLength; j++) - appendBitsToBuffer((seg->data[j >> 3] >> (7 - (j & 7))) & 1, 1, qrcode, &bitLen); - } - LV_ASSERT(bitLen == dataUsedBits); - - // Add terminator and pad up to a byte if applicable - int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; - LV_ASSERT(bitLen <= dataCapacityBits); - int terminatorBits = dataCapacityBits - bitLen; - if (terminatorBits > 4) - terminatorBits = 4; - appendBitsToBuffer(0, terminatorBits, qrcode, &bitLen); - appendBitsToBuffer(0, (8 - bitLen % 8) % 8, qrcode, &bitLen); - LV_ASSERT(bitLen % 8 == 0); - - // Pad with alternating bytes until data capacity is reached - for (uint8_t padByte = 0xEC; bitLen < dataCapacityBits; padByte ^= 0xEC ^ 0x11) - appendBitsToBuffer(padByte, 8, qrcode, &bitLen); - - // Draw function and data codeword modules - addEccAndInterleave(qrcode, version, ecl, tempBuffer); - initializeFunctionModules(version, qrcode); - drawCodewords(tempBuffer, getNumRawDataModules(version) / 8, qrcode); - drawWhiteFunctionModules(qrcode, version); - initializeFunctionModules(version, tempBuffer); - - // Handle masking - if (mask == qrcodegen_Mask_AUTO) { // Automatically choose best mask - long minPenalty = LONG_MAX; - for (int i = 0; i < 8; i++) { - enum qrcodegen_Mask msk = (enum qrcodegen_Mask)i; - applyMask(tempBuffer, qrcode, msk); - drawFormatBits(ecl, msk, qrcode); - long penalty = getPenaltyScore(qrcode); - if (penalty < minPenalty) { - mask = msk; - minPenalty = penalty; - } - applyMask(tempBuffer, qrcode, msk); // Undoes the mask due to XOR - } - } - LV_ASSERT(0 <= (int)mask && (int)mask <= 7); - applyMask(tempBuffer, qrcode, mask); - drawFormatBits(ecl, mask, qrcode); - return true; -} - - - -/*---- Error correction code generation functions ----*/ - -// Appends error correction bytes to each block of the given data array, then interleaves -// bytes from the blocks and stores them in the result array. data[0 : dataLen] contains -// the input data. data[dataLen : rawCodewords] is used as a temporary work area and will -// be clobbered by this function. The final answer is stored in result[0 : rawCodewords]. -testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]) { - // Calculate parameter numbers - LV_ASSERT(0 <= (int)ecl && (int)ecl < 4 && qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); - int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version]; - int blockEccLen = ECC_CODEWORDS_PER_BLOCK [(int)ecl][version]; - int rawCodewords = getNumRawDataModules(version) / 8; - int dataLen = getNumDataCodewords(version, ecl); - int numShortBlocks = numBlocks - rawCodewords % numBlocks; - int shortBlockDataLen = rawCodewords / numBlocks - blockEccLen; - - // Split data into blocks, calculate ECC, and interleave - // (not concatenate) the bytes into a single sequence - uint8_t generator[qrcodegen_REED_SOLOMON_DEGREE_MAX]; - calcReedSolomonGenerator(blockEccLen, generator); - const uint8_t *dat = data; - for (int i = 0; i < numBlocks; i++) { - int datLen = shortBlockDataLen + (i < numShortBlocks ? 0 : 1); - uint8_t *ecc = &data[dataLen]; // Temporary storage - calcReedSolomonRemainder(dat, datLen, generator, blockEccLen, ecc); - for (int j = 0, k = i; j < datLen; j++, k += numBlocks) { // Copy data - if (j == shortBlockDataLen) - k -= numShortBlocks; - result[k] = dat[j]; - } - for (int j = 0, k = dataLen + i; j < blockEccLen; j++, k += numBlocks) // Copy ECC - result[k] = ecc[j]; - dat += datLen; - } -} - - -// Returns the number of 8-bit codewords that can be used for storing data (not ECC), -// for the given version number and error correction level. The result is in the range [9, 2956]. -testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl) { - int v = version, e = (int)ecl; - LV_ASSERT(0 <= e && e < 4); - return getNumRawDataModules(v) / 8 - - ECC_CODEWORDS_PER_BLOCK [e][v] - * NUM_ERROR_CORRECTION_BLOCKS[e][v]; -} - - -// Returns the number of data bits that can be stored in a QR Code of the given version number, after -// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. -// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. -testable int getNumRawDataModules(int ver) { - LV_ASSERT(qrcodegen_VERSION_MIN <= ver && ver <= qrcodegen_VERSION_MAX); - int result = (16 * ver + 128) * ver + 64; - if (ver >= 2) { - int numAlign = ver / 7 + 2; - result -= (25 * numAlign - 10) * numAlign - 55; - if (ver >= 7) - result -= 36; - } - return result; -} - - - -/*---- Reed-Solomon ECC generator functions ----*/ - -// Calculates the Reed-Solomon generator polynomial of the given degree, storing in result[0 : degree]. -testable void calcReedSolomonGenerator(int degree, uint8_t result[]) { - // Start with the monomial x^0 - LV_ASSERT(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); - memset(result, 0, degree * sizeof(result[0])); - result[degree - 1] = 1; - - // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), - // drop the highest term, and store the rest of the coefficients in order of descending powers. - // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). - uint8_t root = 1; - for (int i = 0; i < degree; i++) { - // Multiply the current product by (x - r^i) - for (int j = 0; j < degree; j++) { - result[j] = finiteFieldMultiply(result[j], root); - if (j + 1 < degree) - result[j] ^= result[j + 1]; - } - root = finiteFieldMultiply(root, 0x02); - } -} - - -// Calculates the remainder of the polynomial data[0 : dataLen] when divided by the generator[0 : degree], where all -// polynomials are in big endian and the generator has an implicit leading 1 term, storing the result in result[0 : degree]. -testable void calcReedSolomonRemainder(const uint8_t data[], int dataLen, - const uint8_t generator[], int degree, uint8_t result[]) { - - // Perform polynomial division - LV_ASSERT(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); - memset(result, 0, degree * sizeof(result[0])); - for (int i = 0; i < dataLen; i++) { - uint8_t factor = data[i] ^ result[0]; - memmove(&result[0], &result[1], (degree - 1) * sizeof(result[0])); - result[degree - 1] = 0; - for (int j = 0; j < degree; j++) - result[j] ^= finiteFieldMultiply(generator[j], factor); - } -} - -#undef qrcodegen_REED_SOLOMON_DEGREE_MAX - - -// Returns the product of the two given field elements modulo GF(2^8/0x11D). -// All inputs are valid. This could be implemented as a 256*256 lookup table. -testable uint8_t finiteFieldMultiply(uint8_t x, uint8_t y) { - // Russian peasant multiplication - uint8_t z = 0; - for (int i = 7; i >= 0; i--) { - z = (z << 1) ^ ((z >> 7) * 0x11D); - z ^= ((y >> i) & 1) * x; - } - return z; -} - - - -/*---- Drawing function modules ----*/ - -// Clears the given QR Code grid with white modules for the given -// version's size, then marks every function module as black. -testable void initializeFunctionModules(int version, uint8_t qrcode[]) { - // Initialize QR Code - int qrsize = version * 4 + 17; - memset(qrcode, 0, ((qrsize * qrsize + 7) / 8 + 1) * sizeof(qrcode[0])); - qrcode[0] = (uint8_t)qrsize; - - // Fill horizontal and vertical timing patterns - fillRectangle(6, 0, 1, qrsize, qrcode); - fillRectangle(0, 6, qrsize, 1, qrcode); - - // Fill 3 finder patterns (all corners except bottom right) and format bits - fillRectangle(0, 0, 9, 9, qrcode); - fillRectangle(qrsize - 8, 0, 8, 9, qrcode); - fillRectangle(0, qrsize - 8, 9, 8, qrcode); - - // Fill numerous alignment patterns - uint8_t alignPatPos[7]; - int numAlign = getAlignmentPatternPositions(version, alignPatPos); - for (int i = 0; i < numAlign; i++) { - for (int j = 0; j < numAlign; j++) { - // Don't draw on the three finder corners - if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0))) - fillRectangle(alignPatPos[i] - 2, alignPatPos[j] - 2, 5, 5, qrcode); - } - } - - // Fill version blocks - if (version >= 7) { - fillRectangle(qrsize - 11, 0, 3, 6, qrcode); - fillRectangle(0, qrsize - 11, 6, 3, qrcode); - } -} - - -// Draws white function modules and possibly some black modules onto the given QR Code, without changing -// non-function modules. This does not draw the format bits. This requires all function modules to be previously -// marked black (namely by initializeFunctionModules()), because this may skip redrawing black function modules. -static void drawWhiteFunctionModules(uint8_t qrcode[], int version) { - // Draw horizontal and vertical timing patterns - int qrsize = qrcodegen_getSize(qrcode); - for (int i = 7; i < qrsize - 7; i += 2) { - setModule(qrcode, 6, i, false); - setModule(qrcode, i, 6, false); - } - - // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) - for (int dy = -4; dy <= 4; dy++) { - for (int dx = -4; dx <= 4; dx++) { - int dist = abs(dx); - if (abs(dy) > dist) - dist = abs(dy); - if (dist == 2 || dist == 4) { - setModuleBounded(qrcode, 3 + dx, 3 + dy, false); - setModuleBounded(qrcode, qrsize - 4 + dx, 3 + dy, false); - setModuleBounded(qrcode, 3 + dx, qrsize - 4 + dy, false); - } - } - } - - // Draw numerous alignment patterns - uint8_t alignPatPos[7]; - int numAlign = getAlignmentPatternPositions(version, alignPatPos); - for (int i = 0; i < numAlign; i++) { - for (int j = 0; j < numAlign; j++) { - if ((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0)) - continue; // Don't draw on the three finder corners - for (int dy = -1; dy <= 1; dy++) { - for (int dx = -1; dx <= 1; dx++) - setModule(qrcode, alignPatPos[i] + dx, alignPatPos[j] + dy, dx == 0 && dy == 0); - } - } - } - - // Draw version blocks - if (version >= 7) { - // Calculate error correction code and pack bits - int rem = version; // version is uint6, in the range [7, 40] - for (int i = 0; i < 12; i++) - rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); - long bits = (long)version << 12 | rem; // uint18 - LV_ASSERT(bits >> 18 == 0); - - // Draw two copies - for (int i = 0; i < 6; i++) { - for (int j = 0; j < 3; j++) { - int k = qrsize - 11 + j; - setModule(qrcode, k, i, (bits & 1) != 0); - setModule(qrcode, i, k, (bits & 1) != 0); - bits >>= 1; - } - } - } -} - - -// Draws two copies of the format bits (with its own error correction code) based -// on the given mask and error correction level. This always draws all modules of -// the format bits, unlike drawWhiteFunctionModules() which might skip black modules. -static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]) { - // Calculate error correction code and pack bits - LV_ASSERT(0 <= (int)mask && (int)mask <= 7); - static const int table[] = {1, 0, 3, 2}; - int data = table[(int)ecl] << 3 | (int)mask; // errCorrLvl is uint2, mask is uint3 - int rem = data; - for (int i = 0; i < 10; i++) - rem = (rem << 1) ^ ((rem >> 9) * 0x537); - int bits = (data << 10 | rem) ^ 0x5412; // uint15 - LV_ASSERT(bits >> 15 == 0); - - // Draw first copy - for (int i = 0; i <= 5; i++) - setModule(qrcode, 8, i, getBit(bits, i)); - setModule(qrcode, 8, 7, getBit(bits, 6)); - setModule(qrcode, 8, 8, getBit(bits, 7)); - setModule(qrcode, 7, 8, getBit(bits, 8)); - for (int i = 9; i < 15; i++) - setModule(qrcode, 14 - i, 8, getBit(bits, i)); - - // Draw second copy - int qrsize = qrcodegen_getSize(qrcode); - for (int i = 0; i < 8; i++) - setModule(qrcode, qrsize - 1 - i, 8, getBit(bits, i)); - for (int i = 8; i < 15; i++) - setModule(qrcode, 8, qrsize - 15 + i, getBit(bits, i)); - setModule(qrcode, 8, qrsize - 8, true); // Always black -} - - -// Calculates and stores an ascending list of positions of alignment patterns -// for this version number, returning the length of the list (in the range [0,7]). -// Each position is in the range [0,177), and are used on both the x and y axes. -// This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. -testable int getAlignmentPatternPositions(int version, uint8_t result[7]) { - if (version == 1) - return 0; - int numAlign = version / 7 + 2; - int step = (version == 32) ? 26 : - (version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2; - for (int i = numAlign - 1, pos = version * 4 + 10; i >= 1; i--, pos -= step) - result[i] = pos; - result[0] = 6; - return numAlign; -} - - -// Sets every pixel in the range [left : left + width] * [top : top + height] to black. -static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]) { - for (int dy = 0; dy < height; dy++) { - for (int dx = 0; dx < width; dx++) - setModule(qrcode, left + dx, top + dy, true); - } -} - - - -/*---- Drawing data modules and masking ----*/ - -// Draws the raw codewords (including data and ECC) onto the given QR Code. This requires the initial state of -// the QR Code to be black at function modules and white at codeword modules (including unused remainder bits). -static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]) { - int qrsize = qrcodegen_getSize(qrcode); - int i = 0; // Bit index into the data - // Do the funny zigzag scan - for (int right = qrsize - 1; right >= 1; right -= 2) { // Index of right column in each column pair - if (right == 6) - right = 5; - for (int vert = 0; vert < qrsize; vert++) { // Vertical counter - for (int j = 0; j < 2; j++) { - int x = right - j; // Actual x coordinate - bool upward = ((right + 1) & 2) == 0; - int y = upward ? qrsize - 1 - vert : vert; // Actual y coordinate - if (!getModule(qrcode, x, y) && i < dataLen * 8) { - bool black = getBit(data[i >> 3], 7 - (i & 7)); - setModule(qrcode, x, y, black); - i++; - } - // If this QR Code has any remainder bits (0 to 7), they were assigned as - // 0/false/white by the constructor and are left unchanged by this method - } - } - } - LV_ASSERT(i == dataLen * 8); -} - - -// XORs the codeword modules in this QR Code with the given mask pattern. -// The function modules must be marked and the codeword bits must be drawn -// before masking. Due to the arithmetic of XOR, calling applyMask() with -// the same mask value a second time will undo the mask. A final well-formed -// QR Code needs exactly one (not zero, two, etc.) mask applied. -static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask) { - LV_ASSERT(0 <= (int)mask && (int)mask <= 7); // Disallows qrcodegen_Mask_AUTO - int qrsize = qrcodegen_getSize(qrcode); - for (int y = 0; y < qrsize; y++) { - for (int x = 0; x < qrsize; x++) { - if (getModule(functionModules, x, y)) - continue; - bool invert; - switch ((int)mask) { - case 0: invert = (x + y) % 2 == 0; break; - case 1: invert = y % 2 == 0; break; - case 2: invert = x % 3 == 0; break; - case 3: invert = (x + y) % 3 == 0; break; - case 4: invert = (x / 3 + y / 2) % 2 == 0; break; - case 5: invert = x * y % 2 + x * y % 3 == 0; break; - case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; - case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; - default: LV_ASSERT(false); return; - } - bool val = getModule(qrcode, x, y); - setModule(qrcode, x, y, val ^ invert); - } - } -} - - -// Calculates and returns the penalty score based on state of the given QR Code's current modules. -// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. -static long getPenaltyScore(const uint8_t qrcode[]) { - int qrsize = qrcodegen_getSize(qrcode); - long result = 0; - - // Adjacent modules in row having same color, and finder-like patterns - for (int y = 0; y < qrsize; y++) { - unsigned char runHistory[7] = {0}; - bool color = false; - unsigned char runX = 0; - for (int x = 0; x < qrsize; x++) { - if (getModule(qrcode, x, y) == color) { - runX++; - if (runX == 5) - result += PENALTY_N1; - else if (runX > 5) - result++; - } else { - addRunToHistory(runX, runHistory); - if (!color && hasFinderLikePattern(runHistory)) - result += PENALTY_N3; - color = getModule(qrcode, x, y); - runX = 1; - } - } - addRunToHistory(runX, runHistory); - if (color) - addRunToHistory(0, runHistory); // Dummy run of white - if (hasFinderLikePattern(runHistory)) - result += PENALTY_N3; - } - // Adjacent modules in column having same color, and finder-like patterns - for (int x = 0; x < qrsize; x++) { - unsigned char runHistory[7] = {0}; - bool color = false; - unsigned char runY = 0; - for (int y = 0; y < qrsize; y++) { - if (getModule(qrcode, x, y) == color) { - runY++; - if (runY == 5) - result += PENALTY_N1; - else if (runY > 5) - result++; - } else { - addRunToHistory(runY, runHistory); - if (!color && hasFinderLikePattern(runHistory)) - result += PENALTY_N3; - color = getModule(qrcode, x, y); - runY = 1; - } - } - addRunToHistory(runY, runHistory); - if (color) - addRunToHistory(0, runHistory); // Dummy run of white - if (hasFinderLikePattern(runHistory)) - result += PENALTY_N3; - } - - // 2*2 blocks of modules having same color - for (int y = 0; y < qrsize - 1; y++) { - for (int x = 0; x < qrsize - 1; x++) { - bool color = getModule(qrcode, x, y); - if ( color == getModule(qrcode, x + 1, y) && - color == getModule(qrcode, x, y + 1) && - color == getModule(qrcode, x + 1, y + 1)) - result += PENALTY_N2; - } - } - - // Balance of black and white modules - int black = 0; - for (int y = 0; y < qrsize; y++) { - for (int x = 0; x < qrsize; x++) { - if (getModule(qrcode, x, y)) - black++; - } - } - int total = qrsize * qrsize; // Note that size is odd, so black/total != 1/2 - // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)% - int k = (int)((labs(black * 20L - total * 10L) + total - 1) / total) - 1; - result += k * PENALTY_N4; - return result; -} - - -// Inserts the given value to the front of the given array, which shifts over the -// existing values and deletes the last value. A helper function for getPenaltyScore(). -static void addRunToHistory(unsigned char run, unsigned char history[7]) { - memmove(&history[1], &history[0], 6 * sizeof(history[0])); - history[0] = run; -} - - -// Tests whether the given run history has the pattern of ratio 1:1:3:1:1 in the middle, and -// surrounded by at least 4 on either or both ends. A helper function for getPenaltyScore(). -// Must only be called immediately after a run of white modules has ended. -static bool hasFinderLikePattern(const unsigned char runHistory[7]) { - unsigned char n = runHistory[1]; - // The maximum QR Code size is 177, hence the run length n <= 177. - // Arithmetic is promoted to int, so n*4 will not overflow. - return n > 0 && runHistory[2] == n && runHistory[4] == n && runHistory[5] == n - && runHistory[3] == n * 3 && (runHistory[0] >= n * 4 || runHistory[6] >= n * 4); -} - - - -/*---- Basic QR Code information ----*/ - -// Public function - see documentation comment in header file. -int qrcodegen_getSize(const uint8_t qrcode[]) { - LV_ASSERT(qrcode != NULL); - int result = qrcode[0]; - LV_ASSERT((qrcodegen_VERSION_MIN * 4 + 17) <= result - && result <= (qrcodegen_VERSION_MAX * 4 + 17)); - return result; -} - - -// Public function - see documentation comment in header file. -bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y) { - LV_ASSERT(qrcode != NULL); - int qrsize = qrcode[0]; - return (0 <= x && x < qrsize && 0 <= y && y < qrsize) && getModule(qrcode, x, y); -} - - -// Gets the module at the given coordinates, which must be in bounds. -testable bool getModule(const uint8_t qrcode[], int x, int y) { - int qrsize = qrcode[0]; - LV_ASSERT(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); - int index = y * qrsize + x; - return getBit(qrcode[(index >> 3) + 1], index & 7); -} - - -// Sets the module at the given coordinates, which must be in bounds. -testable void setModule(uint8_t qrcode[], int x, int y, bool isBlack) { - int qrsize = qrcode[0]; - LV_ASSERT(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); - int index = y * qrsize + x; - int bitIndex = index & 7; - int byteIndex = (index >> 3) + 1; - if (isBlack) - qrcode[byteIndex] |= 1 << bitIndex; - else - qrcode[byteIndex] &= (1 << bitIndex) ^ 0xFF; -} - - -// Sets the module at the given coordinates, doing nothing if out of bounds. -testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack) { - int qrsize = qrcode[0]; - if (0 <= x && x < qrsize && 0 <= y && y < qrsize) - setModule(qrcode, x, y, isBlack); -} - - -// Returns true iff the i'th bit of x is set to 1. Requires x >= 0 and 0 <= i <= 14. -static bool getBit(int x, int i) { - return ((x >> i) & 1) != 0; -} - - - -/*---- Segment handling ----*/ - -// Public function - see documentation comment in header file. -bool qrcodegen_isAlphanumeric(const char *text) { - LV_ASSERT(text != NULL); - for (; *text != '\0'; text++) { - if (strchr(ALPHANUMERIC_CHARSET, *text) == NULL) - return false; - } - return true; -} - - -// Public function - see documentation comment in header file. -bool qrcodegen_isNumeric(const char *text) { - LV_ASSERT(text != NULL); - for (; *text != '\0'; text++) { - if (*text < '0' || *text > '9') - return false; - } - return true; -} - - -// Public function - see documentation comment in header file. -size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars) { - int temp = calcSegmentBitLength(mode, numChars); - if (temp == -1) - return SIZE_MAX; - LV_ASSERT(0 <= temp && temp <= INT16_MAX); - return ((size_t)temp + 7) / 8; -} - - -// Returns the number of data bits needed to represent a segment -// containing the given number of characters using the given mode. Notes: -// - Returns -1 on failure, i.e. numChars > INT16_MAX or -// the number of needed bits exceeds INT16_MAX (i.e. 32767). -// - Otherwise, all valid results are in the range [0, INT16_MAX]. -// - For byte mode, numChars measures the number of bytes, not Unicode code points. -// - For ECI mode, numChars must be 0, and the worst-case number of bits is returned. -// An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. -testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars) { - // All calculations are designed to avoid overflow on all platforms - if (numChars > (unsigned int)INT16_MAX) - return -1; - long result = (long)numChars; - if (mode == qrcodegen_Mode_NUMERIC) - result = (result * 10 + 2) / 3; // ceil(10/3 * n) - else if (mode == qrcodegen_Mode_ALPHANUMERIC) - result = (result * 11 + 1) / 2; // ceil(11/2 * n) - else if (mode == qrcodegen_Mode_BYTE) - result *= 8; - else if (mode == qrcodegen_Mode_KANJI) - result *= 13; - else if (mode == qrcodegen_Mode_ECI && numChars == 0) - result = 3 * 8; - else { // Invalid argument - LV_ASSERT(false); - return -1; - } - LV_ASSERT(result >= 0); - if ((unsigned int)result > (unsigned int)INT16_MAX) - return -1; - return (int)result; -} - - -// Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]) { - LV_ASSERT(data != NULL || len == 0); - struct qrcodegen_Segment result; - result.mode = qrcodegen_Mode_BYTE; - result.bitLength = calcSegmentBitLength(result.mode, len); - LV_ASSERT(result.bitLength != -1); - result.numChars = (int)len; - if (len > 0) - memcpy(buf, data, len * sizeof(buf[0])); - result.data = buf; - return result; -} - - -// Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]) { - LV_ASSERT(digits != NULL); - struct qrcodegen_Segment result; - size_t len = strlen(digits); - result.mode = qrcodegen_Mode_NUMERIC; - int bitLen = calcSegmentBitLength(result.mode, len); - LV_ASSERT(bitLen != -1); - result.numChars = (int)len; - if (bitLen > 0) - memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); - result.bitLength = 0; - - unsigned int accumData = 0; - int accumCount = 0; - for (; *digits != '\0'; digits++) { - char c = *digits; - LV_ASSERT('0' <= c && c <= '9'); - accumData = accumData * 10 + (unsigned int)(c - '0'); - accumCount++; - if (accumCount == 3) { - appendBitsToBuffer(accumData, 10, buf, &result.bitLength); - accumData = 0; - accumCount = 0; - } - } - if (accumCount > 0) // 1 or 2 digits remaining - appendBitsToBuffer(accumData, accumCount * 3 + 1, buf, &result.bitLength); - LV_ASSERT(result.bitLength == bitLen); - result.data = buf; - return result; -} - - -// Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]) { - LV_ASSERT(text != NULL); - struct qrcodegen_Segment result; - size_t len = strlen(text); - result.mode = qrcodegen_Mode_ALPHANUMERIC; - int bitLen = calcSegmentBitLength(result.mode, len); - LV_ASSERT(bitLen != -1); - result.numChars = (int)len; - if (bitLen > 0) - memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); - result.bitLength = 0; - - unsigned int accumData = 0; - int accumCount = 0; - for (; *text != '\0'; text++) { - const char *temp = strchr(ALPHANUMERIC_CHARSET, *text); - LV_ASSERT(temp != NULL); - accumData = accumData * 45 + (unsigned int)(temp - ALPHANUMERIC_CHARSET); - accumCount++; - if (accumCount == 2) { - appendBitsToBuffer(accumData, 11, buf, &result.bitLength); - accumData = 0; - accumCount = 0; - } - } - if (accumCount > 0) // 1 character remaining - appendBitsToBuffer(accumData, 6, buf, &result.bitLength); - LV_ASSERT(result.bitLength == bitLen); - result.data = buf; - return result; -} - - -// Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]) { - struct qrcodegen_Segment result; - result.mode = qrcodegen_Mode_ECI; - result.numChars = 0; - result.bitLength = 0; - if (assignVal < 0) { - LV_ASSERT(false); - } else if (assignVal < (1 << 7)) { - memset(buf, 0, 1 * sizeof(buf[0])); - appendBitsToBuffer(assignVal, 8, buf, &result.bitLength); - } else if (assignVal < (1 << 14)) { - memset(buf, 0, 2 * sizeof(buf[0])); - appendBitsToBuffer(2, 2, buf, &result.bitLength); - appendBitsToBuffer(assignVal, 14, buf, &result.bitLength); - } else if (assignVal < 1000000L) { - memset(buf, 0, 3 * sizeof(buf[0])); - appendBitsToBuffer(6, 3, buf, &result.bitLength); - appendBitsToBuffer(assignVal >> 10, 11, buf, &result.bitLength); - appendBitsToBuffer(assignVal & 0x3FF, 10, buf, &result.bitLength); - } else { - LV_ASSERT(false); - } - result.data = buf; - return result; -} - - -// Calculates the number of bits needed to encode the given segments at the given version. -// Returns a non-negative number if successful. Otherwise returns -1 if a segment has too -// many characters to fit its length field, or the total bits exceeds INT16_MAX. -testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version) { - LV_ASSERT(segs != NULL || len == 0); - long result = 0; - for (size_t i = 0; i < len; i++) { - int numChars = segs[i].numChars; - int bitLength = segs[i].bitLength; - LV_ASSERT(0 <= numChars && numChars <= INT16_MAX); - LV_ASSERT(0 <= bitLength && bitLength <= INT16_MAX); - int ccbits = numCharCountBits(segs[i].mode, version); - LV_ASSERT(0 <= ccbits && ccbits <= 16); - if (numChars >= (1L << ccbits)) - return -1; // The segment's length doesn't fit the field's bit width - result += 4L + ccbits + bitLength; - if (result > INT16_MAX) - return -1; // The sum might overflow an int type - } - LV_ASSERT(0 <= result && result <= INT16_MAX); - return (int)result; -} - - -// Returns the bit width of the character count field for a segment in the given mode -// in a QR Code at the given version number. The result is in the range [0, 16]. -static int numCharCountBits(enum qrcodegen_Mode mode, int version) { - LV_ASSERT(qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); - int i = (version + 7) / 17; - switch (mode) { - case qrcodegen_Mode_NUMERIC : { static const int temp[] = {10, 12, 14}; return temp[i]; } - case qrcodegen_Mode_ALPHANUMERIC: { static const int temp[] = { 9, 11, 13}; return temp[i]; } - case qrcodegen_Mode_BYTE : { static const int temp[] = { 8, 16, 16}; return temp[i]; } - case qrcodegen_Mode_KANJI : { static const int temp[] = { 8, 10, 12}; return temp[i]; } - case qrcodegen_Mode_ECI : return 0; - default: LV_ASSERT(false); return -1; // Dummy value - } -} - -int qrcodegen_getMinFitVersion(enum qrcodegen_Ecc ecl, size_t dataLen) -{ - struct qrcodegen_Segment seg; - seg.mode = qrcodegen_Mode_BYTE; - seg.bitLength = calcSegmentBitLength(seg.mode, dataLen); - seg.numChars = (int)dataLen; - - for (int version = qrcodegen_VERSION_MIN; version <= qrcodegen_VERSION_MAX; version++) { - int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available - int dataUsedBits = getTotalBits(&seg, 1, version); - if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) - return version; - } - return -1; -} - -int qrcodegen_version2size(int version) -{ - if (version < qrcodegen_VERSION_MIN || version > qrcodegen_VERSION_MAX) { - return -1; - } - - return ((version - 1)*4 + 21); -} diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/lv_sjpg.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/lv_sjpg.c deleted file mode 100644 index 5a12ea251..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/lv_sjpg.c +++ /dev/null @@ -1,917 +0,0 @@ -/** - * @file lv_sjpg.c - * - */ - -/*---------------------------------------------------------------------------------------------------------------------------------- -/ Added normal JPG support [7/10/2020] -/ ---------- -/ SJPEG is a custom created modified JPEG file format for small embedded platforms. -/ It will contain multiple JPEG fragments all embedded into a single file with a custom header. -/ This makes JPEG decoding easier using any JPEG library. Overall file size will be almost -/ similar to the parent jpeg file. We can generate sjpeg from any jpeg using a python script -/ provided along with this project. -/ (by vinodstanur | 2020 ) -/ SJPEG FILE STRUCTURE -/ -------------------------------------------------------------------------------------------------------------------------------- -/ Bytes | Value | -/ -------------------------------------------------------------------------------------------------------------------------------- -/ -/ 0 - 7 | "_SJPG__" followed by '\0' -/ -/ 8 - 13 | "V1.00" followed by '\0' [VERSION OF SJPG FILE for future compatibiliby] -/ -/ 14 - 15 | X_RESOLUTION (width) [little endian] -/ -/ 16 - 17 | Y_RESOLUTION (height) [little endian] -/ -/ 18 - 19 | TOTAL_FRAMES inside sjpeg [little endian] -/ -/ 20 - 21 | JPEG BLOCK WIDTH (16 normally) [little endian] -/ -/ 22 - [(TOTAL_FRAMES*2 )] | SIZE OF EACH JPEG SPLIT FRAGMENTS (FRAME_INFO_ARRAY) -/ -/ SJPEG data | Each JPEG frame can be extracted from SJPEG data by parsing the FRAME_INFO_ARRAY one time. -/ -/---------------------------------------------------------------------------------------------------------------------------------- -/ JPEG DECODER -/ ------------ -/ We are using TJpgDec - Tiny JPEG Decompressor library from ELM-CHAN for decoding each split-jpeg fragments. -/ The tjpgd.c and tjpgd.h is not modified and those are used as it is. So if any update comes for the tiny-jpeg, -/ just replace those files with updated files. -/---------------------------------------------------------------------------------------------------------------------------------*/ - -/********************* - * INCLUDES - *********************/ - -#include "../../../lvgl.h" -#if LV_USE_SJPG - -#include "tjpgd.h" -#include "lv_sjpg.h" -#include "../../../misc/lv_fs.h" - -/********************* - * DEFINES - *********************/ -#define TJPGD_WORKBUFF_SIZE 4096 //Recommended by TJPGD libray - -//NEVER EDIT THESE OFFSET VALUES -#define SJPEG_VERSION_OFFSET 8 -#define SJPEG_X_RES_OFFSET 14 -#define SJPEG_y_RES_OFFSET 16 -#define SJPEG_TOTAL_FRAMES_OFFSET 18 -#define SJPEG_BLOCK_WIDTH_OFFSET 20 -#define SJPEG_FRAME_INFO_ARRAY_OFFSET 22 - -/********************** - * TYPEDEFS - **********************/ - -enum io_source_type { - SJPEG_IO_SOURCE_C_ARRAY, - SJPEG_IO_SOURCE_DISK, -}; - -typedef struct { - enum io_source_type type; - lv_fs_file_t lv_file; - uint8_t * img_cache_buff; - int img_cache_x_res; - int img_cache_y_res; - uint8_t * raw_sjpg_data; //Used when type==SJPEG_IO_SOURCE_C_ARRAY. - uint32_t raw_sjpg_data_size; //Num bytes pointed to by raw_sjpg_data. - uint32_t raw_sjpg_data_next_read_pos; //Used for all types. -} io_source_t; - - -typedef struct { - uint8_t * sjpeg_data; - uint32_t sjpeg_data_size; - int sjpeg_x_res; - int sjpeg_y_res; - int sjpeg_total_frames; - int sjpeg_single_frame_height; - int sjpeg_cache_frame_index; - uint8_t ** frame_base_array; //to save base address of each split frames upto sjpeg_total_frames. - int * frame_base_offset; //to save base offset for fseek - uint8_t * frame_cache; - uint8_t * workb; //JPG work buffer for jpeg library - JDEC * tjpeg_jd; - io_source_t io; -} SJPEG; - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header); -static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc); -static lv_res_t decoder_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, - lv_coord_t len, uint8_t * buf); -static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc); -static size_t input_func(JDEC * jd, uint8_t * buff, size_t ndata); -static int is_jpg(const uint8_t * raw_data, size_t len); -static void lv_sjpg_cleanup(SJPEG * sjpeg); -static void lv_sjpg_free(SJPEG * sjpeg); - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ -void lv_split_jpeg_init(void) -{ - lv_img_decoder_t * dec = lv_img_decoder_create(); - lv_img_decoder_set_info_cb(dec, decoder_info); - lv_img_decoder_set_open_cb(dec, decoder_open); - lv_img_decoder_set_close_cb(dec, decoder_close); - lv_img_decoder_set_read_line_cb(dec, decoder_read_line); -} - -/********************** - * STATIC FUNCTIONS - **********************/ -/** - * Get info about an SJPG / JPG image - * @param decoder pointer to the decoder where this function belongs - * @param src can be file name or pointer to a C array - * @param header store the info here - * @return LV_RES_OK: no error; LV_RES_INV: can't get the info - */ -static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header) -{ - LV_UNUSED(decoder); - - /*Check whether the type `src` is known by the decoder*/ - /* Read the SJPG/JPG header and find `width` and `height` */ - - lv_img_src_t src_type = lv_img_src_get_type(src); /*Get the source type*/ - - lv_res_t ret = LV_RES_OK; - - if(src_type == LV_IMG_SRC_VARIABLE) { - const lv_img_dsc_t * img_dsc = src; - uint8_t * raw_sjpeg_data = (uint8_t *)img_dsc->data; - const uint32_t raw_sjpeg_data_size = img_dsc->data_size; - - if(!strncmp((char *)raw_sjpeg_data, "_SJPG__", strlen("_SJPG__"))) { - - raw_sjpeg_data += 14; //seek to res info ... refer sjpeg format - header->always_zero = 0; - header->cf = LV_IMG_CF_RAW; - - header->w = *raw_sjpeg_data++; - header->w |= *raw_sjpeg_data++ << 8; - - header->h = *raw_sjpeg_data++; - header->h |= *raw_sjpeg_data++ << 8; - - return ret; - - } - else if(is_jpg(raw_sjpeg_data, raw_sjpeg_data_size) == true) { - header->always_zero = 0; - header->cf = LV_IMG_CF_RAW; - - uint8_t * workb_temp = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); - if(!workb_temp) return LV_RES_INV; - - io_source_t io_source_temp; - io_source_temp.type = SJPEG_IO_SOURCE_C_ARRAY; - io_source_temp.raw_sjpg_data = raw_sjpeg_data; - io_source_temp.raw_sjpg_data_size = raw_sjpeg_data_size; - io_source_temp.raw_sjpg_data_next_read_pos = 0; - - JDEC jd_tmp; - - JRESULT rc = jd_prepare(&jd_tmp, input_func, workb_temp, (size_t)TJPGD_WORKBUFF_SIZE, &io_source_temp); - if(rc == JDR_OK) { - header->w = jd_tmp.width; - header->h = jd_tmp.height; - - } - else { - ret = LV_RES_INV; - goto end; - } - -end: - lv_mem_free(workb_temp); - - return ret; - - } - } - else if(src_type == LV_IMG_SRC_FILE) { - const char * fn = src; - if(strcmp(lv_fs_get_ext(fn), "sjpg") == 0) { - - uint8_t buff[22]; - memset(buff, 0, sizeof(buff)); - - lv_fs_file_t file; - lv_fs_res_t res = lv_fs_open(&file, fn, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) return 78; - - uint32_t rn; - res = lv_fs_read(&file, buff, 8, &rn); - if(res != LV_FS_RES_OK || rn != 8) { - lv_fs_close(&file); - return LV_RES_INV; - } - - if(strcmp((char *)buff, "_SJPG__") == 0) { - lv_fs_seek(&file, 14, LV_FS_SEEK_SET); - res = lv_fs_read(&file, buff, 4, &rn); - if(res != LV_FS_RES_OK || rn != 4) { - lv_fs_close(&file); - return LV_RES_INV; - } - header->always_zero = 0; - header->cf = LV_IMG_CF_RAW; - uint8_t * raw_sjpeg_data = buff; - header->w = *raw_sjpeg_data++; - header->w |= *raw_sjpeg_data++ << 8; - header->h = *raw_sjpeg_data++; - header->h |= *raw_sjpeg_data++ << 8; - lv_fs_close(&file); - return LV_RES_OK; - - } - } - else if(strcmp(lv_fs_get_ext(fn), "jpg") == 0) { - lv_fs_file_t file; - lv_fs_res_t res = lv_fs_open(&file, fn, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) return 78; - - uint8_t * workb_temp = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); - if(!workb_temp) { - lv_fs_close(&file); - return LV_RES_INV; - } - - io_source_t io_source_temp; - io_source_temp.type = SJPEG_IO_SOURCE_DISK; - io_source_temp.raw_sjpg_data_next_read_pos = 0; - io_source_temp.img_cache_buff = NULL; - io_source_temp.lv_file = file; - JDEC jd_tmp; - - JRESULT rc = jd_prepare(&jd_tmp, input_func, workb_temp, (size_t)TJPGD_WORKBUFF_SIZE, &io_source_temp); - lv_mem_free(workb_temp); - lv_fs_close(&file); - - if(rc == JDR_OK) { - header->always_zero = 0; - header->cf = LV_IMG_CF_RAW; - header->w = jd_tmp.width; - header->h = jd_tmp.height; - return LV_RES_OK; - } - } - } - return LV_RES_INV; -} - -static int img_data_cb(JDEC * jd, void * data, JRECT * rect) -{ - io_source_t * io = jd->device; - uint8_t * cache = io->img_cache_buff; - const int xres = io->img_cache_x_res; - uint8_t * buf = data; - const int INPUT_PIXEL_SIZE = 3; - const int row_width = rect->right - rect->left + 1; // Row width in pixels. - const int row_size = row_width * INPUT_PIXEL_SIZE; // Row size (bytes). - - for(int y = rect->top; y <= rect->bottom; y++) { - int row_offset = y * xres * INPUT_PIXEL_SIZE + rect->left * INPUT_PIXEL_SIZE; - memcpy(cache + row_offset, buf, row_size); - buf += row_size; - } - - return 1; -} - -static size_t input_func(JDEC * jd, uint8_t * buff, size_t ndata) -{ - io_source_t * io = jd->device; - - if(!io) return 0; - - if(io->type == SJPEG_IO_SOURCE_C_ARRAY) { - const uint32_t bytes_left = io->raw_sjpg_data_size - io->raw_sjpg_data_next_read_pos; - const uint32_t to_read = ndata <= bytes_left ? (uint32_t)ndata : bytes_left; - if(to_read == 0) - return 0; - if(buff) { - memcpy(buff, io->raw_sjpg_data + io->raw_sjpg_data_next_read_pos, to_read); - } - io->raw_sjpg_data_next_read_pos += to_read; - return to_read; - } - else if(io->type == SJPEG_IO_SOURCE_DISK) { - - lv_fs_file_t * lv_file_p = &(io->lv_file); - - if(buff) { - uint32_t rn = 0; - lv_fs_read(lv_file_p, buff, (uint32_t)ndata, &rn); - return rn; - } - else { - uint32_t pos; - lv_fs_tell(lv_file_p, &pos); - lv_fs_seek(lv_file_p, (uint32_t)(ndata + pos), LV_FS_SEEK_SET); - return ndata; - } - } - return 0; -} - -/** - * Open SJPG image and return the decided image - * @param decoder pointer to the decoder where this function belongs - * @param dsc pointer to a descriptor which describes this decoding session - * @return LV_RES_OK: no error; LV_RES_INV: can't get the info - */ -static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) -{ - LV_UNUSED(decoder); - lv_res_t lv_ret = LV_RES_OK; - - if(dsc->src_type == LV_IMG_SRC_VARIABLE) { - uint8_t * data; - SJPEG * sjpeg = (SJPEG *) dsc->user_data; - const uint32_t raw_sjpeg_data_size = ((lv_img_dsc_t *)dsc->src)->data_size; - if(sjpeg == NULL) { - sjpeg = lv_mem_alloc(sizeof(SJPEG)); - if(!sjpeg) return LV_RES_INV; - - memset(sjpeg, 0, sizeof(SJPEG)); - - dsc->user_data = sjpeg; - sjpeg->sjpeg_data = (uint8_t *)((lv_img_dsc_t *)(dsc->src))->data; - sjpeg->sjpeg_data_size = ((lv_img_dsc_t *)(dsc->src))->data_size; - } - - if(!strncmp((char *) sjpeg->sjpeg_data, "_SJPG__", strlen("_SJPG__"))) { - - data = sjpeg->sjpeg_data; - data += 14; - - sjpeg->sjpeg_x_res = *data++; - sjpeg->sjpeg_x_res |= *data++ << 8; - - sjpeg->sjpeg_y_res = *data++; - sjpeg->sjpeg_y_res |= *data++ << 8; - - sjpeg->sjpeg_total_frames = *data++; - sjpeg->sjpeg_total_frames |= *data++ << 8; - - sjpeg->sjpeg_single_frame_height = *data++; - sjpeg->sjpeg_single_frame_height |= *data++ << 8; - - sjpeg->frame_base_array = lv_mem_alloc(sizeof(uint8_t *) * sjpeg->sjpeg_total_frames); - if(! sjpeg->frame_base_array) { - lv_sjpg_cleanup(sjpeg); - sjpeg = NULL; - return LV_RES_INV; - } - - sjpeg->frame_base_offset = NULL; - - uint8_t * img_frame_base = data + sjpeg->sjpeg_total_frames * 2; - sjpeg->frame_base_array[0] = img_frame_base; - - for(int i = 1; i < sjpeg->sjpeg_total_frames; i++) { - int offset = *data++; - offset |= *data++ << 8; - sjpeg->frame_base_array[i] = sjpeg->frame_base_array[i - 1] + offset; - } - sjpeg->sjpeg_cache_frame_index = -1; - sjpeg->frame_cache = (void *)lv_mem_alloc(sjpeg->sjpeg_x_res * sjpeg->sjpeg_single_frame_height * 3/*2*/); - if(! sjpeg->frame_cache) { - lv_sjpg_cleanup(sjpeg); - sjpeg = NULL; - return LV_RES_INV; - } - sjpeg->io.img_cache_buff = sjpeg->frame_cache; - sjpeg->io.img_cache_x_res = sjpeg->sjpeg_x_res; - sjpeg->workb = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); - if(! sjpeg->workb) { - lv_sjpg_cleanup(sjpeg); - sjpeg = NULL; - return LV_RES_INV; - } - - sjpeg->tjpeg_jd = lv_mem_alloc(sizeof(JDEC)); - if(! sjpeg->tjpeg_jd) { - lv_sjpg_cleanup(sjpeg); - sjpeg = NULL; - return LV_RES_INV; - } - sjpeg->io.type = SJPEG_IO_SOURCE_C_ARRAY; - sjpeg->io.lv_file.file_d = NULL; - dsc->img_data = NULL; - return lv_ret; - } - else if(is_jpg(sjpeg->sjpeg_data, raw_sjpeg_data_size) == true) { - - uint8_t * workb_temp = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); - if(! workb_temp) { - lv_sjpg_cleanup(sjpeg); - sjpeg = NULL; - return LV_RES_INV; - } - io_source_t io_source_temp; - io_source_temp.type = SJPEG_IO_SOURCE_C_ARRAY; - io_source_temp.raw_sjpg_data = sjpeg->sjpeg_data; - io_source_temp.raw_sjpg_data_size = sjpeg->sjpeg_data_size; - io_source_temp.raw_sjpg_data_next_read_pos = 0; - - JDEC jd_tmp; - JRESULT rc = jd_prepare(&jd_tmp, input_func, workb_temp, (size_t)TJPGD_WORKBUFF_SIZE, &io_source_temp); - lv_mem_free(workb_temp); - - - if(rc == JDR_OK) { - sjpeg->sjpeg_x_res = jd_tmp.width; - sjpeg->sjpeg_y_res = jd_tmp.height; - sjpeg->sjpeg_total_frames = 1; - sjpeg->sjpeg_single_frame_height = jd_tmp.height; - - sjpeg->frame_base_array = lv_mem_alloc(sizeof(uint8_t *) * sjpeg->sjpeg_total_frames); - if(! sjpeg->frame_base_array) { - lv_sjpg_cleanup(sjpeg); - sjpeg = NULL; - return LV_RES_INV; - } - sjpeg->frame_base_offset = NULL; - - uint8_t * img_frame_base = sjpeg->sjpeg_data; - sjpeg->frame_base_array[0] = img_frame_base; - - sjpeg->sjpeg_cache_frame_index = -1; - sjpeg->frame_cache = (void *)lv_mem_alloc(sjpeg->sjpeg_x_res * sjpeg->sjpeg_single_frame_height * 3); - if(! sjpeg->frame_cache) { - lv_sjpg_cleanup(sjpeg); - sjpeg = NULL; - return LV_RES_INV; - } - - sjpeg->io.img_cache_buff = sjpeg->frame_cache; - sjpeg->io.img_cache_x_res = sjpeg->sjpeg_x_res; - sjpeg->workb = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); - if(! sjpeg->workb) { - lv_sjpg_cleanup(sjpeg); - sjpeg = NULL; - return LV_RES_INV; - } - - sjpeg->tjpeg_jd = lv_mem_alloc(sizeof(JDEC)); - if(! sjpeg->tjpeg_jd) { - lv_sjpg_cleanup(sjpeg); - sjpeg = NULL; - return LV_RES_INV; - } - - sjpeg->io.type = SJPEG_IO_SOURCE_C_ARRAY; - sjpeg->io.lv_file.file_d = NULL; - dsc->img_data = NULL; - return lv_ret; - } - else { - lv_ret = LV_RES_INV; - goto end; - } - -end: - lv_mem_free(workb_temp); - - return lv_ret; - } - } - else if(dsc->src_type == LV_IMG_SRC_FILE) { - /* If all fine, then the file will be kept open */ - const char * fn = dsc->src; - uint8_t * data; - - if(strcmp(lv_fs_get_ext(fn), "sjpg") == 0) { - - uint8_t buff[22]; - memset(buff, 0, sizeof(buff)); - - - lv_fs_file_t lv_file; - lv_fs_res_t res = lv_fs_open(&lv_file, fn, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) { - return 78; - } - - - uint32_t rn; - res = lv_fs_read(&lv_file, buff, 22, &rn); - if(res != LV_FS_RES_OK || rn != 22) { - lv_fs_close(&lv_file); - return LV_RES_INV; - } - - if(strcmp((char *)buff, "_SJPG__") == 0) { - - SJPEG * sjpeg = (SJPEG *) dsc->user_data; - if(sjpeg == NULL) { - sjpeg = lv_mem_alloc(sizeof(SJPEG)); - - if(! sjpeg) { - lv_fs_close(&lv_file); - return LV_RES_INV; - } - memset(sjpeg, 0, sizeof(SJPEG)); - - dsc->user_data = sjpeg; - sjpeg->sjpeg_data = (uint8_t *)((lv_img_dsc_t *)(dsc->src))->data; - sjpeg->sjpeg_data_size = ((lv_img_dsc_t *)(dsc->src))->data_size; - } - data = buff; - data += 14; - - sjpeg->sjpeg_x_res = *data++; - sjpeg->sjpeg_x_res |= *data++ << 8; - - sjpeg->sjpeg_y_res = *data++; - sjpeg->sjpeg_y_res |= *data++ << 8; - - sjpeg->sjpeg_total_frames = *data++; - sjpeg->sjpeg_total_frames |= *data++ << 8; - - sjpeg->sjpeg_single_frame_height = *data++; - sjpeg->sjpeg_single_frame_height |= *data++ << 8; - - sjpeg->frame_base_array = NULL;//lv_mem_alloc( sizeof(uint8_t *) * sjpeg->sjpeg_total_frames ); - sjpeg->frame_base_offset = lv_mem_alloc(sizeof(int) * sjpeg->sjpeg_total_frames); - if(! sjpeg->frame_base_offset) { - lv_fs_close(&lv_file); - lv_sjpg_cleanup(sjpeg); - return LV_RES_INV; - } - int img_frame_start_offset = (SJPEG_FRAME_INFO_ARRAY_OFFSET + sjpeg->sjpeg_total_frames * 2); - sjpeg->frame_base_offset[0] = img_frame_start_offset; //pointer used to save integer for now... - - for(int i = 1; i < sjpeg->sjpeg_total_frames; i++) { - res = lv_fs_read(&lv_file, buff, 2, &rn); - if(res != LV_FS_RES_OK || rn != 2) { - lv_fs_close(&lv_file); - return LV_RES_INV; - } - - data = buff; - int offset = *data++; - offset |= *data++ << 8; - sjpeg->frame_base_offset[i] = sjpeg->frame_base_offset[i - 1] + offset; - } - - sjpeg->sjpeg_cache_frame_index = -1; //INVALID AT BEGINNING for a forced compare mismatch at first time. - sjpeg->frame_cache = (void *)lv_mem_alloc(sjpeg->sjpeg_x_res * sjpeg->sjpeg_single_frame_height * 3); - if(! sjpeg->frame_cache) { - lv_fs_close(&lv_file); - lv_sjpg_cleanup(sjpeg); - return LV_RES_INV; - } - sjpeg->io.img_cache_buff = sjpeg->frame_cache; - sjpeg->io.img_cache_x_res = sjpeg->sjpeg_x_res; - sjpeg->workb = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); - if(! sjpeg->workb) { - lv_fs_close(&lv_file); - lv_sjpg_cleanup(sjpeg); - return LV_RES_INV; - } - - sjpeg->tjpeg_jd = lv_mem_alloc(sizeof(JDEC)); - if(! sjpeg->tjpeg_jd) { - lv_fs_close(&lv_file); - lv_sjpg_cleanup(sjpeg); - return LV_RES_INV; - } - - sjpeg->io.type = SJPEG_IO_SOURCE_DISK; - sjpeg->io.lv_file = lv_file; - dsc->img_data = NULL; - return LV_RES_OK; - } - } - else if(strcmp(lv_fs_get_ext(fn), "jpg") == 0) { - - lv_fs_file_t lv_file; - lv_fs_res_t res = lv_fs_open(&lv_file, fn, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) { - return LV_RES_INV; - } - - SJPEG * sjpeg = (SJPEG *) dsc->user_data; - if(sjpeg == NULL) { - sjpeg = lv_mem_alloc(sizeof(SJPEG)); - if(! sjpeg) { - lv_fs_close(&lv_file); - return LV_RES_INV; - } - - memset(sjpeg, 0, sizeof(SJPEG)); - dsc->user_data = sjpeg; - sjpeg->sjpeg_data = (uint8_t *)((lv_img_dsc_t *)(dsc->src))->data; - sjpeg->sjpeg_data_size = ((lv_img_dsc_t *)(dsc->src))->data_size; - } - - uint8_t * workb_temp = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); - if(! workb_temp) { - lv_fs_close(&lv_file); - lv_sjpg_cleanup(sjpeg); - return LV_RES_INV; - } - - io_source_t io_source_temp; - io_source_temp.type = SJPEG_IO_SOURCE_DISK; - io_source_temp.raw_sjpg_data_next_read_pos = 0; - io_source_temp.img_cache_buff = NULL; - io_source_temp.lv_file = lv_file; - - JDEC jd_tmp; - - JRESULT rc = jd_prepare(&jd_tmp, input_func, workb_temp, (size_t)TJPGD_WORKBUFF_SIZE, &io_source_temp); - - lv_mem_free(workb_temp); - - - if(rc == JDR_OK) { - sjpeg->sjpeg_x_res = jd_tmp.width; - sjpeg->sjpeg_y_res = jd_tmp.height; - sjpeg->sjpeg_total_frames = 1; - sjpeg->sjpeg_single_frame_height = jd_tmp.height; - - sjpeg->frame_base_array = NULL; - sjpeg->frame_base_offset = lv_mem_alloc(sizeof(uint8_t *) * sjpeg->sjpeg_total_frames); - if(! sjpeg->frame_base_offset) { - lv_fs_close(&lv_file); - lv_sjpg_cleanup(sjpeg); - return LV_RES_INV; - } - - int img_frame_start_offset = 0; - sjpeg->frame_base_offset[0] = img_frame_start_offset; - - sjpeg->sjpeg_cache_frame_index = -1; - sjpeg->frame_cache = (void *)lv_mem_alloc(sjpeg->sjpeg_x_res * sjpeg->sjpeg_single_frame_height * 3); - if(! sjpeg->frame_cache) { - lv_fs_close(&lv_file); - lv_sjpg_cleanup(sjpeg); - return LV_RES_INV; - } - - sjpeg->io.img_cache_buff = sjpeg->frame_cache; - sjpeg->io.img_cache_x_res = sjpeg->sjpeg_x_res; - sjpeg->workb = lv_mem_alloc(TJPGD_WORKBUFF_SIZE); - if(! sjpeg->workb) { - lv_fs_close(&lv_file); - lv_sjpg_cleanup(sjpeg); - return LV_RES_INV; - } - - sjpeg->tjpeg_jd = lv_mem_alloc(sizeof(JDEC)); - if(! sjpeg->tjpeg_jd) { - lv_fs_close(&lv_file); - lv_sjpg_cleanup(sjpeg); - return LV_RES_INV; - } - - sjpeg->io.type = SJPEG_IO_SOURCE_DISK; - sjpeg->io.lv_file = lv_file; - dsc->img_data = NULL; - return LV_RES_OK; - - } - else { - if(dsc->user_data) lv_mem_free(dsc->user_data); - lv_fs_close(&lv_file); - return LV_RES_INV; - } - } - } - - return LV_RES_INV; -} - -/** - * Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`. - * Required only if the "open" function can't open the whole decoded pixel array. (dsc->img_data == NULL) - * @param decoder pointer to the decoder the function associated with - * @param dsc pointer to decoder descriptor - * @param x start x coordinate - * @param y start y coordinate - * @param len number of pixels to decode - * @param buf a buffer to store the decoded pixels - * @return LV_RES_OK: ok; LV_RES_INV: failed - */ - -static lv_res_t decoder_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, - lv_coord_t len, uint8_t * buf) -{ - LV_UNUSED(decoder); - if(dsc->src_type == LV_IMG_SRC_VARIABLE) { - SJPEG * sjpeg = (SJPEG *) dsc->user_data; - JRESULT rc; - - int sjpeg_req_frame_index = y / sjpeg->sjpeg_single_frame_height; - - /*If line not from cache, refresh cache */ - if(sjpeg_req_frame_index != sjpeg->sjpeg_cache_frame_index) { - sjpeg->io.raw_sjpg_data = sjpeg->frame_base_array[ sjpeg_req_frame_index ]; - if(sjpeg_req_frame_index == (sjpeg->sjpeg_total_frames - 1)) { - /*This is the last frame. */ - const uint32_t frame_offset = (uint32_t)(sjpeg->io.raw_sjpg_data - sjpeg->sjpeg_data); - sjpeg->io.raw_sjpg_data_size = sjpeg->sjpeg_data_size - frame_offset; - } - else { - sjpeg->io.raw_sjpg_data_size = - (uint32_t)(sjpeg->frame_base_array[sjpeg_req_frame_index + 1] - sjpeg->io.raw_sjpg_data); - } - sjpeg->io.raw_sjpg_data_next_read_pos = 0; - rc = jd_prepare(sjpeg->tjpeg_jd, input_func, sjpeg->workb, (size_t)TJPGD_WORKBUFF_SIZE, &(sjpeg->io)); - if(rc != JDR_OK) return LV_RES_INV; - rc = jd_decomp(sjpeg->tjpeg_jd, img_data_cb, 0); - if(rc != JDR_OK) return LV_RES_INV; - sjpeg->sjpeg_cache_frame_index = sjpeg_req_frame_index; - } - - int offset = 0; - uint8_t * cache = (uint8_t *)sjpeg->frame_cache + x * 3 + (y % sjpeg->sjpeg_single_frame_height) * sjpeg->sjpeg_x_res * - 3; - -#if LV_COLOR_DEPTH == 32 - for(int i = 0; i < len; i++) { - buf[offset + 3] = 0xff; - buf[offset + 2] = *cache++; - buf[offset + 1] = *cache++; - buf[offset + 0] = *cache++; - offset += 4; - } - -#elif LV_COLOR_DEPTH == 16 - - for(int i = 0; i < len; i++) { - uint16_t col_16bit = (*cache++ & 0xf8) << 8; - col_16bit |= (*cache++ & 0xFC) << 3; - col_16bit |= (*cache++ >> 3); -#if LV_BIG_ENDIAN_SYSTEM == 1 || LV_COLOR_16_SWAP == 1 - buf[offset++] = col_16bit >> 8; - buf[offset++] = col_16bit & 0xff; -#else - buf[offset++] = col_16bit & 0xff; - buf[offset++] = col_16bit >> 8; -#endif // LV_BIG_ENDIAN_SYSTEM - } - -#elif LV_COLOR_DEPTH == 8 - - for(int i = 0; i < len; i++) { - uint8_t col_8bit = (*cache++ & 0xC0); - col_8bit |= (*cache++ & 0xe0) >> 2; - col_8bit |= (*cache++ & 0xe0) >> 5; - buf[offset++] = col_8bit; - } -#else -#error Unsupported LV_COLOR_DEPTH - - -#endif // LV_COLOR_DEPTH - return LV_RES_OK; - } - else if(dsc->src_type == LV_IMG_SRC_FILE) { - SJPEG * sjpeg = (SJPEG *) dsc->user_data; - JRESULT rc; - int sjpeg_req_frame_index = y / sjpeg->sjpeg_single_frame_height; - - lv_fs_file_t * lv_file_p = &(sjpeg->io.lv_file); - if(!lv_file_p) goto end; - - /*If line not from cache, refresh cache */ - if(sjpeg_req_frame_index != sjpeg->sjpeg_cache_frame_index) { - sjpeg->io.raw_sjpg_data_next_read_pos = (int)(sjpeg->frame_base_offset [ sjpeg_req_frame_index ]); - lv_fs_seek(&(sjpeg->io.lv_file), sjpeg->io.raw_sjpg_data_next_read_pos, LV_FS_SEEK_SET); - - rc = jd_prepare(sjpeg->tjpeg_jd, input_func, sjpeg->workb, (size_t)TJPGD_WORKBUFF_SIZE, &(sjpeg->io)); - if(rc != JDR_OK) return LV_RES_INV; - - rc = jd_decomp(sjpeg->tjpeg_jd, img_data_cb, 0); - if(rc != JDR_OK) return LV_RES_INV; - - sjpeg->sjpeg_cache_frame_index = sjpeg_req_frame_index; - } - - int offset = 0; - uint8_t * cache = (uint8_t *)sjpeg->frame_cache + x * 3 + (y % sjpeg->sjpeg_single_frame_height) * sjpeg->sjpeg_x_res * - 3; - -#if LV_COLOR_DEPTH == 32 - for(int i = 0; i < len; i++) { - buf[offset + 3] = 0xff; - buf[offset + 2] = *cache++; - buf[offset + 1] = *cache++; - buf[offset + 0] = *cache++; - offset += 4; - } -#elif LV_COLOR_DEPTH == 16 - - for(int i = 0; i < len; i++) { - uint16_t col_8bit = (*cache++ & 0xf8) << 8; - col_8bit |= (*cache++ & 0xFC) << 3; - col_8bit |= (*cache++ >> 3); -#if LV_BIG_ENDIAN_SYSTEM == 1 || LV_COLOR_16_SWAP == 1 - buf[offset++] = col_8bit >> 8; - buf[offset++] = col_8bit & 0xff; -#else - buf[offset++] = col_8bit & 0xff; - buf[offset++] = col_8bit >> 8; -#endif // LV_BIG_ENDIAN_SYSTEM - } - -#elif LV_COLOR_DEPTH == 8 - - for(int i = 0; i < len; i++) { - uint8_t col_8bit = (*cache++ & 0xC0); - col_8bit |= (*cache++ & 0xe0) >> 2; - col_8bit |= (*cache++ & 0xe0) >> 5; - buf[offset++] = col_8bit; - } - -#else -#error Unsupported LV_COLOR_DEPTH - - -#endif // LV_COLOR_DEPTH - - return LV_RES_OK; - } -end: - return LV_RES_INV; -} - -/** - * Free the allocated resources - * @param decoder pointer to the decoder where this function belongs - * @param dsc pointer to a descriptor which describes this decoding session - */ -static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) -{ - LV_UNUSED(decoder); - /*Free all allocated data*/ - SJPEG * sjpeg = (SJPEG *) dsc->user_data; - if(!sjpeg) return; - - switch(dsc->src_type) { - case LV_IMG_SRC_FILE: - if(sjpeg->io.lv_file.file_d) { - lv_fs_close(&(sjpeg->io.lv_file)); - } - lv_sjpg_cleanup(sjpeg); - break; - - case LV_IMG_SRC_VARIABLE: - lv_sjpg_cleanup(sjpeg); - break; - - default: - ; - } -} - -static int is_jpg(const uint8_t * raw_data, size_t len) -{ - const uint8_t jpg_signature[] = {0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46}; - if(len < sizeof(jpg_signature)) return false; - return memcmp(jpg_signature, raw_data, sizeof(jpg_signature)) == 0; -} - -static void lv_sjpg_free(SJPEG * sjpeg) -{ - if(sjpeg->frame_cache) lv_mem_free(sjpeg->frame_cache); - if(sjpeg->frame_base_array) lv_mem_free(sjpeg->frame_base_array); - if(sjpeg->frame_base_offset) lv_mem_free(sjpeg->frame_base_offset); - if(sjpeg->tjpeg_jd) lv_mem_free(sjpeg->tjpeg_jd); - if(sjpeg->workb) lv_mem_free(sjpeg->workb); -} - -static void lv_sjpg_cleanup(SJPEG * sjpeg) -{ - if(! sjpeg) return; - - lv_sjpg_free(sjpeg); - lv_mem_free(sjpeg); -} - -#endif /*LV_USE_SJPG*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgd.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgd.c deleted file mode 100644 index 47ddefb6e..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgd.c +++ /dev/null @@ -1,1155 +0,0 @@ -/*----------------------------------------------------------------------------/ -/ TJpgDec - Tiny JPEG Decompressor R0.03 (C)ChaN, 2021 -/-----------------------------------------------------------------------------/ -/ The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. -/ This is a free software that opened for education, research and commercial -/ developments under license policy of following terms. -/ -/ Copyright (C) 2021, ChaN, all right reserved. -/ -/ * The TJpgDec module is a free software and there is NO WARRANTY. -/ * No restriction on use. You can use, modify and redistribute it for -/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. -/ * Redistributions of source code must retain the above copyright notice. -/ -/-----------------------------------------------------------------------------/ -/ Oct 04, 2011 R0.01 First release. -/ Feb 19, 2012 R0.01a Fixed decompression fails when scan starts with an escape seq. -/ Sep 03, 2012 R0.01b Added JD_TBLCLIP option. -/ Mar 16, 2019 R0.01c Supprted stdint.h. -/ Jul 01, 2020 R0.01d Fixed wrong integer type usage. -/ May 08, 2021 R0.02 Supprted grayscale image. Separated configuration options. -/ Jun 11, 2021 R0.02a Some performance improvement. -/ Jul 01, 2021 R0.03 Added JD_FASTDECODE option. -/ Some performance improvement. -/----------------------------------------------------------------------------*/ - -#include "tjpgd.h" -#if LV_USE_SJPG - -#if JD_FASTDECODE == 2 -#define HUFF_BIT 10 /* Bit length to apply fast huffman decode */ -#define HUFF_LEN (1 << HUFF_BIT) -#define HUFF_MASK (HUFF_LEN - 1) -#endif - - -/*-----------------------------------------------*/ -/* Zigzag-order to raster-order conversion table */ -/*-----------------------------------------------*/ - -static const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion table */ - 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 -}; - - - -/*-------------------------------------------------*/ -/* Input scale factor of Arai algorithm */ -/* (scaled up 16 bits for fixed point operations) */ -/*-------------------------------------------------*/ - -static const uint16_t Ipsf[64] = { /* See also aa_idct.png */ - (uint16_t)(1.00000*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.17588*8192), (uint16_t)(1.00000*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.27590*8192), - (uint16_t)(1.38704*8192), (uint16_t)(1.92388*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.63099*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.08979*8192), (uint16_t)(0.75066*8192), (uint16_t)(0.38268*8192), - (uint16_t)(1.30656*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.70711*8192), (uint16_t)(1.53636*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.02656*8192), (uint16_t)(0.70711*8192), (uint16_t)(0.36048*8192), - (uint16_t)(1.17588*8192), (uint16_t)(1.63099*8192), (uint16_t)(1.53636*8192), (uint16_t)(1.38268*8192), (uint16_t)(1.17588*8192), (uint16_t)(0.92388*8192), (uint16_t)(0.63638*8192), (uint16_t)(0.32442*8192), - (uint16_t)(1.00000*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.17588*8192), (uint16_t)(1.00000*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.27590*8192), - (uint16_t)(0.78570*8192), (uint16_t)(1.08979*8192), (uint16_t)(1.02656*8192), (uint16_t)(0.92388*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.61732*8192), (uint16_t)(0.42522*8192), (uint16_t)(0.21677*8192), - (uint16_t)(0.54120*8192), (uint16_t)(0.75066*8192), (uint16_t)(0.70711*8192), (uint16_t)(0.63638*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.42522*8192), (uint16_t)(0.29290*8192), (uint16_t)(0.14932*8192), - (uint16_t)(0.27590*8192), (uint16_t)(0.38268*8192), (uint16_t)(0.36048*8192), (uint16_t)(0.32442*8192), (uint16_t)(0.27590*8192), (uint16_t)(0.21678*8192), (uint16_t)(0.14932*8192), (uint16_t)(0.07612*8192) -}; - - - -/*---------------------------------------------*/ -/* Conversion table for fast clipping process */ -/*---------------------------------------------*/ - -#if JD_TBLCLIP - -#define BYTECLIP(v) Clip8[(unsigned int)(v) & 0x3FF] - -static const uint8_t Clip8[1024] = { - /* 0..255 */ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - /* 256..511 */ - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - /* -512..-257 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* -256..-1 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -#else /* JD_TBLCLIP */ - -static uint8_t BYTECLIP (int val) -{ - if (val < 0) return 0; - if (val > 255) return 255; - return (uint8_t)val; -} - -#endif - - - -/*-----------------------------------------------------------------------*/ -/* Allocate a memory block from memory pool */ -/*-----------------------------------------------------------------------*/ - -static void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory available) */ - JDEC* jd, /* Pointer to the decompressor object */ - size_t ndata /* Number of bytes to allocate */ -) -{ - char *rp = 0; - - - ndata = (ndata + 3) & ~3; /* Align block size to the word boundary */ - - if (jd->sz_pool >= ndata) { - jd->sz_pool -= ndata; - rp = (char*)jd->pool; /* Get start of available memory pool */ - jd->pool = (void*)(rp + ndata); /* Allocate requierd bytes */ - } - - return (void*)rp; /* Return allocated memory block (NULL:no memory to allocate) */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Create de-quantization and prescaling tables with a DQT segment */ -/*-----------------------------------------------------------------------*/ - -static JRESULT create_qt_tbl ( /* 0:OK, !0:Failed */ - JDEC* jd, /* Pointer to the decompressor object */ - const uint8_t* data, /* Pointer to the quantizer tables */ - size_t ndata /* Size of input data */ -) -{ - unsigned int i, zi; - uint8_t d; - int32_t *pb; - - - while (ndata) { /* Process all tables in the segment */ - if (ndata < 65) return JDR_FMT1; /* Err: table size is unaligned */ - ndata -= 65; - d = *data++; /* Get table property */ - if (d & 0xF0) return JDR_FMT1; /* Err: not 8-bit resolution */ - i = d & 3; /* Get table ID */ - pb = alloc_pool(jd, 64 * sizeof (int32_t));/* Allocate a memory block for the table */ - if (!pb) return JDR_MEM1; /* Err: not enough memory */ - jd->qttbl[i] = pb; /* Register the table */ - for (i = 0; i < 64; i++) { /* Load the table */ - zi = Zig[i]; /* Zigzag-order to raster-order conversion */ - pb[zi] = (int32_t)((uint32_t)*data++ * Ipsf[zi]); /* Apply scale factor of Arai algorithm to the de-quantizers */ - } - } - - return JDR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Create huffman code tables with a DHT segment */ -/*-----------------------------------------------------------------------*/ - -static JRESULT create_huffman_tbl ( /* 0:OK, !0:Failed */ - JDEC* jd, /* Pointer to the decompressor object */ - const uint8_t* data, /* Pointer to the packed huffman tables */ - size_t ndata /* Size of input data */ -) -{ - unsigned int i, j, b, cls, num; - size_t np; - uint8_t d, *pb, *pd; - uint16_t hc, *ph; - - - while (ndata) { /* Process all tables in the segment */ - if (ndata < 17) return JDR_FMT1; /* Err: wrong data size */ - ndata -= 17; - d = *data++; /* Get table number and class */ - if (d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */ - cls = d >> 4; num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */ - pb = alloc_pool(jd, 16); /* Allocate a memory block for the bit distribution table */ - if (!pb) return JDR_MEM1; /* Err: not enough memory */ - jd->huffbits[num][cls] = pb; - for (np = i = 0; i < 16; i++) { /* Load number of patterns for 1 to 16-bit code */ - np += (pb[i] = *data++); /* Get sum of code words for each code */ - } - ph = alloc_pool(jd, np * sizeof (uint16_t));/* Allocate a memory block for the code word table */ - if (!ph) return JDR_MEM1; /* Err: not enough memory */ - jd->huffcode[num][cls] = ph; - hc = 0; - for (j = i = 0; i < 16; i++) { /* Re-build huffman code word table */ - b = pb[i]; - while (b--) ph[j++] = hc++; - hc <<= 1; - } - - if (ndata < np) return JDR_FMT1; /* Err: wrong data size */ - ndata -= np; - pd = alloc_pool(jd, np); /* Allocate a memory block for the decoded data */ - if (!pd) return JDR_MEM1; /* Err: not enough memory */ - jd->huffdata[num][cls] = pd; - for (i = 0; i < np; i++) { /* Load decoded data corresponds to each code word */ - d = *data++; - if (!cls && d > 11) return JDR_FMT1; - pd[i] = d; - } -#if JD_FASTDECODE == 2 - { /* Create fast huffman decode table */ - unsigned int span, td, ti; - uint16_t *tbl_ac = 0; - uint8_t *tbl_dc = 0; - - if (cls) { - tbl_ac = alloc_pool(jd, HUFF_LEN * sizeof (uint16_t)); /* LUT for AC elements */ - if (!tbl_ac) return JDR_MEM1; /* Err: not enough memory */ - jd->hufflut_ac[num] = tbl_ac; - memset(tbl_ac, 0xFF, HUFF_LEN * sizeof (uint16_t)); /* Default value (0xFFFF: may be long code) */ - } else { - tbl_dc = alloc_pool(jd, HUFF_LEN * sizeof (uint8_t)); /* LUT for AC elements */ - if (!tbl_dc) return JDR_MEM1; /* Err: not enough memory */ - jd->hufflut_dc[num] = tbl_dc; - memset(tbl_dc, 0xFF, HUFF_LEN * sizeof (uint8_t)); /* Default value (0xFF: may be long code) */ - } - for (i = b = 0; b < HUFF_BIT; b++) { /* Create LUT */ - for (j = pb[b]; j; j--) { - ti = ph[i] << (HUFF_BIT - 1 - b) & HUFF_MASK; /* Index of input pattern for the code */ - if (cls) { - td = pd[i++] | ((b + 1) << 8); /* b15..b8: code length, b7..b0: zero run and data length */ - for (span = 1 << (HUFF_BIT - 1 - b); span; span--, tbl_ac[ti++] = (uint16_t)td) ; - } else { - td = pd[i++] | ((b + 1) << 4); /* b7..b4: code length, b3..b0: data length */ - for (span = 1 << (HUFF_BIT - 1 - b); span; span--, tbl_dc[ti++] = (uint8_t)td) ; - } - } - } - jd->longofs[num][cls] = i; /* Code table offset for long code */ - } -#endif - } - - return JDR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Extract a huffman decoded data from input stream */ -/*-----------------------------------------------------------------------*/ - -static int huffext ( /* >=0: decoded data, <0: error code */ - JDEC* jd, /* Pointer to the decompressor object */ - unsigned int id, /* Table ID (0:Y, 1:C) */ - unsigned int cls /* Table class (0:DC, 1:AC) */ -) -{ - size_t dc = jd->dctr; - uint8_t *dp = jd->dptr; - unsigned int d, flg = 0; - -#if JD_FASTDECODE == 0 - uint8_t bm, nd, bl; - const uint8_t *hb = jd->huffbits[id][cls]; /* Bit distribution table */ - const uint16_t *hc = jd->huffcode[id][cls]; /* Code word table */ - const uint8_t *hd = jd->huffdata[id][cls]; /* Data table */ - - - bm = jd->dbit; /* Bit mask to extract */ - d = 0; bl = 16; /* Max code length */ - do { - if (!bm) { /* Next byte? */ - if (!dc) { /* No input data is available, re-fill input buffer */ - dp = jd->inbuf; /* Top of input buffer */ - dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ - } else { - dp++; /* Next data ptr */ - } - dc--; /* Decrement number of available bytes */ - if (flg) { /* In flag sequence? */ - flg = 0; /* Exit flag sequence */ - if (*dp != 0) return 0 - (int)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ - *dp = 0xFF; /* The flag is a data 0xFF */ - } else { - if (*dp == 0xFF) { /* Is start of flag sequence? */ - flg = 1; continue; /* Enter flag sequence, get trailing byte */ - } - } - bm = 0x80; /* Read from MSB */ - } - d <<= 1; /* Get a bit */ - if (*dp & bm) d++; - bm >>= 1; - - for (nd = *hb++; nd; nd--) { /* Search the code word in this bit length */ - if (d == *hc++) { /* Matched? */ - jd->dbit = bm; jd->dctr = dc; jd->dptr = dp; - return *hd; /* Return the decoded data */ - } - hd++; - } - bl--; - } while (bl); - -#else - const uint8_t *hb, *hd; - const uint16_t *hc; - unsigned int nc, bl, wbit = jd->dbit % 32; - uint32_t w = jd->wreg & ((1UL << wbit) - 1); - - - while (wbit < 16) { /* Prepare 16 bits into the working register */ - if (jd->marker) { - d = 0xFF; /* Input stream has stalled for a marker. Generate stuff bits */ - } else { - if (!dc) { /* Buffer empty, re-fill input buffer */ - dp = jd->inbuf; /* Top of input buffer */ - dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ - } - d = *dp++; dc--; - if (flg) { /* In flag sequence? */ - flg = 0; /* Exit flag sequence */ - if (d != 0) jd->marker = d; /* Not an escape of 0xFF but a marker */ - d = 0xFF; - } else { - if (d == 0xFF) { /* Is start of flag sequence? */ - flg = 1; continue; /* Enter flag sequence, get trailing byte */ - } - } - } - w = w << 8 | d; /* Shift 8 bits in the working register */ - wbit += 8; - } - jd->dctr = dc; jd->dptr = dp; - jd->wreg = w; - -#if JD_FASTDECODE == 2 - /* Table serch for the short codes */ - d = (unsigned int)(w >> (wbit - HUFF_BIT)); /* Short code as table index */ - if (cls) { /* AC element */ - d = jd->hufflut_ac[id][d]; /* Table decode */ - if (d != 0xFFFF) { /* It is done if hit in short code */ - jd->dbit = wbit - (d >> 8); /* Snip the code length */ - return d & 0xFF; /* b7..0: zero run and following data bits */ - } - } else { /* DC element */ - d = jd->hufflut_dc[id][d]; /* Table decode */ - if (d != 0xFF) { /* It is done if hit in short code */ - jd->dbit = wbit - (d >> 4); /* Snip the code length */ - return d & 0xF; /* b3..0: following data bits */ - } - } - - /* Incremental serch for the codes longer than HUFF_BIT */ - hb = jd->huffbits[id][cls] + HUFF_BIT; /* Bit distribution table */ - hc = jd->huffcode[id][cls] + jd->longofs[id][cls]; /* Code word table */ - hd = jd->huffdata[id][cls] + jd->longofs[id][cls]; /* Data table */ - bl = HUFF_BIT + 1; -#else - /* Incremental serch for all codes */ - hb = jd->huffbits[id][cls]; /* Bit distribution table */ - hc = jd->huffcode[id][cls]; /* Code word table */ - hd = jd->huffdata[id][cls]; /* Data table */ - bl = 1; -#endif - for ( ; bl <= 16; bl++) { /* Incremental search */ - nc = *hb++; - if (nc) { - d = w >> (wbit - bl); - do { /* Search the code word in this bit length */ - if (d == *hc++) { /* Matched? */ - jd->dbit = wbit - bl; /* Snip the huffman code */ - return *hd; /* Return the decoded data */ - } - hd++; - } while (--nc); - } - } -#endif - - return 0 - (int)JDR_FMT1; /* Err: code not found (may be collapted data) */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Extract N bits from input stream */ -/*-----------------------------------------------------------------------*/ - -static int bitext ( /* >=0: extracted data, <0: error code */ - JDEC* jd, /* Pointer to the decompressor object */ - unsigned int nbit /* Number of bits to extract (1 to 16) */ -) -{ - size_t dc = jd->dctr; - uint8_t *dp = jd->dptr; - unsigned int d, flg = 0; - -#if JD_FASTDECODE == 0 - uint8_t mbit = jd->dbit; - - d = 0; - do { - if (!mbit) { /* Next byte? */ - if (!dc) { /* No input data is available, re-fill input buffer */ - dp = jd->inbuf; /* Top of input buffer */ - dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ - } else { - dp++; /* Next data ptr */ - } - dc--; /* Decrement number of available bytes */ - if (flg) { /* In flag sequence? */ - flg = 0; /* Exit flag sequence */ - if (*dp != 0) return 0 - (int)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ - *dp = 0xFF; /* The flag is a data 0xFF */ - } else { - if (*dp == 0xFF) { /* Is start of flag sequence? */ - flg = 1; continue; /* Enter flag sequence */ - } - } - mbit = 0x80; /* Read from MSB */ - } - d <<= 1; /* Get a bit */ - if (*dp & mbit) d |= 1; - mbit >>= 1; - nbit--; - } while (nbit); - - jd->dbit = mbit; jd->dctr = dc; jd->dptr = dp; - return (int)d; - -#else - unsigned int wbit = jd->dbit % 32; - uint32_t w = jd->wreg & ((1UL << wbit) - 1); - - - while (wbit < nbit) { /* Prepare nbit bits into the working register */ - if (jd->marker) { - d = 0xFF; /* Input stream stalled, generate stuff bits */ - } else { - if (!dc) { /* Buffer empty, re-fill input buffer */ - dp = jd->inbuf; /* Top of input buffer */ - dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ - } - d = *dp++; dc--; - if (flg) { /* In flag sequence? */ - flg = 0; /* Exit flag sequence */ - if (d != 0) jd->marker = d; /* Not an escape of 0xFF but a marker */ - d = 0xFF; - } else { - if (d == 0xFF) { /* Is start of flag sequence? */ - flg = 1; continue; /* Enter flag sequence, get trailing byte */ - } - } - } - w = w << 8 | d; /* Get 8 bits into the working register */ - wbit += 8; - } - jd->wreg = w; jd->dbit = wbit - nbit; - jd->dctr = dc; jd->dptr = dp; - - return (int)(w >> ((wbit - nbit) % 32)); -#endif -} - - - - -/*-----------------------------------------------------------------------*/ -/* Process restart interval */ -/*-----------------------------------------------------------------------*/ - -static JRESULT restart ( - JDEC* jd, /* Pointer to the decompressor object */ - uint16_t rstn /* Expected restert sequense number */ -) -{ - unsigned int i; - uint8_t *dp = jd->dptr; - size_t dc = jd->dctr; - -#if JD_FASTDECODE == 0 - uint16_t d = 0; - - /* Get two bytes from the input stream */ - for (i = 0; i < 2; i++) { - if (!dc) { /* No input data is available, re-fill input buffer */ - dp = jd->inbuf; - dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return JDR_INP; - } else { - dp++; - } - dc--; - d = d << 8 | *dp; /* Get a byte */ - } - jd->dptr = dp; jd->dctr = dc; jd->dbit = 0; - - /* Check the marker */ - if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) { - return JDR_FMT1; /* Err: expected RSTn marker is not detected (may be collapted data) */ - } - -#else - uint16_t marker; - - - if (jd->marker) { /* Generate a maker if it has been detected */ - marker = 0xFF00 | jd->marker; - jd->marker = 0; - } else { - marker = 0; - for (i = 0; i < 2; i++) { /* Get a restart marker */ - if (!dc) { /* No input data is available, re-fill input buffer */ - dp = jd->inbuf; - dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return JDR_INP; - } - marker = (marker << 8) | *dp++; /* Get a byte */ - dc--; - } - jd->dptr = dp; jd->dctr = dc; - } - - /* Check the marker */ - if ((marker & 0xFFD8) != 0xFFD0 || (marker & 7) != (rstn & 7)) { - return JDR_FMT1; /* Err: expected RSTn marker was not detected (may be collapted data) */ - } - - jd->dbit = 0; /* Discard stuff bits */ -#endif - - jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Reset DC offset */ - return JDR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Apply Inverse-DCT in Arai Algorithm (see also aa_idct.png) */ -/*-----------------------------------------------------------------------*/ - -static void block_idct ( - int32_t* src, /* Input block data (de-quantized and pre-scaled for Arai Algorithm) */ - jd_yuv_t* dst /* Pointer to the destination to store the block as byte array */ -) -{ - const int32_t M13 = (int32_t)(1.41421*4096), M2 = (int32_t)(1.08239*4096), M4 = (int32_t)(2.61313*4096), M5 = (int32_t)(1.84776*4096); - int32_t v0, v1, v2, v3, v4, v5, v6, v7; - int32_t t10, t11, t12, t13; - int i; - - /* Process columns */ - for (i = 0; i < 8; i++) { - v0 = src[8 * 0]; /* Get even elements */ - v1 = src[8 * 2]; - v2 = src[8 * 4]; - v3 = src[8 * 6]; - - t10 = v0 + v2; /* Process the even elements */ - t12 = v0 - v2; - t11 = (v1 - v3) * M13 >> 12; - v3 += v1; - t11 -= v3; - v0 = t10 + v3; - v3 = t10 - v3; - v1 = t11 + t12; - v2 = t12 - t11; - - v4 = src[8 * 7]; /* Get odd elements */ - v5 = src[8 * 1]; - v6 = src[8 * 5]; - v7 = src[8 * 3]; - - t10 = v5 - v4; /* Process the odd elements */ - t11 = v5 + v4; - t12 = v6 - v7; - v7 += v6; - v5 = (t11 - v7) * M13 >> 12; - v7 += t11; - t13 = (t10 + t12) * M5 >> 12; - v4 = t13 - (t10 * M2 >> 12); - v6 = t13 - (t12 * M4 >> 12) - v7; - v5 -= v6; - v4 -= v5; - - src[8 * 0] = v0 + v7; /* Write-back transformed values */ - src[8 * 7] = v0 - v7; - src[8 * 1] = v1 + v6; - src[8 * 6] = v1 - v6; - src[8 * 2] = v2 + v5; - src[8 * 5] = v2 - v5; - src[8 * 3] = v3 + v4; - src[8 * 4] = v3 - v4; - - src++; /* Next column */ - } - - /* Process rows */ - src -= 8; - for (i = 0; i < 8; i++) { - v0 = src[0] + (128L << 8); /* Get even elements (remove DC offset (-128) here) */ - v1 = src[2]; - v2 = src[4]; - v3 = src[6]; - - t10 = v0 + v2; /* Process the even elements */ - t12 = v0 - v2; - t11 = (v1 - v3) * M13 >> 12; - v3 += v1; - t11 -= v3; - v0 = t10 + v3; - v3 = t10 - v3; - v1 = t11 + t12; - v2 = t12 - t11; - - v4 = src[7]; /* Get odd elements */ - v5 = src[1]; - v6 = src[5]; - v7 = src[3]; - - t10 = v5 - v4; /* Process the odd elements */ - t11 = v5 + v4; - t12 = v6 - v7; - v7 += v6; - v5 = (t11 - v7) * M13 >> 12; - v7 += t11; - t13 = (t10 + t12) * M5 >> 12; - v4 = t13 - (t10 * M2 >> 12); - v6 = t13 - (t12 * M4 >> 12) - v7; - v5 -= v6; - v4 -= v5; - - /* Descale the transformed values 8 bits and output a row */ -#if JD_FASTDECODE >= 1 - dst[0] = (int16_t)((v0 + v7) >> 8); - dst[7] = (int16_t)((v0 - v7) >> 8); - dst[1] = (int16_t)((v1 + v6) >> 8); - dst[6] = (int16_t)((v1 - v6) >> 8); - dst[2] = (int16_t)((v2 + v5) >> 8); - dst[5] = (int16_t)((v2 - v5) >> 8); - dst[3] = (int16_t)((v3 + v4) >> 8); - dst[4] = (int16_t)((v3 - v4) >> 8); -#else - dst[0] = BYTECLIP((v0 + v7) >> 8); - dst[7] = BYTECLIP((v0 - v7) >> 8); - dst[1] = BYTECLIP((v1 + v6) >> 8); - dst[6] = BYTECLIP((v1 - v6) >> 8); - dst[2] = BYTECLIP((v2 + v5) >> 8); - dst[5] = BYTECLIP((v2 - v5) >> 8); - dst[3] = BYTECLIP((v3 + v4) >> 8); - dst[4] = BYTECLIP((v3 - v4) >> 8); -#endif - - dst += 8; src += 8; /* Next row */ - } -} - - - - -/*-----------------------------------------------------------------------*/ -/* Load all blocks in an MCU into working buffer */ -/*-----------------------------------------------------------------------*/ - -static JRESULT mcu_load ( - JDEC* jd /* Pointer to the decompressor object */ -) -{ - int32_t *tmp = (int32_t*)jd->workbuf; /* Block working buffer for de-quantize and IDCT */ - int d, e; - unsigned int blk, nby, i, bc, z, id, cmp; - jd_yuv_t *bp; - const int32_t *dqf; - - - nby = jd->msx * jd->msy; /* Number of Y blocks (1, 2 or 4) */ - bp = jd->mcubuf; /* Pointer to the first block of MCU */ - - for (blk = 0; blk < nby + 2; blk++) { /* Get nby Y blocks and two C blocks */ - cmp = (blk < nby) ? 0 : blk - nby + 1; /* Component number 0:Y, 1:Cb, 2:Cr */ - - if (cmp && jd->ncomp != 3) { /* Clear C blocks if not exist (monochrome image) */ - for (i = 0; i < 64; bp[i++] = 128) ; - - } else { /* Load Y/C blocks from input stream */ - id = cmp ? 1 : 0; /* Huffman table ID of this component */ - - /* Extract a DC element from input stream */ - d = huffext(jd, id, 0); /* Extract a huffman coded data (bit length) */ - if (d < 0) return (JRESULT)(0 - d); /* Err: invalid code or input */ - bc = (unsigned int)d; - d = jd->dcv[cmp]; /* DC value of previous block */ - if (bc) { /* If there is any difference from previous block */ - e = bitext(jd, bc); /* Extract data bits */ - if (e < 0) return (JRESULT)(0 - e); /* Err: input */ - bc = 1 << (bc - 1); /* MSB position */ - if (!(e & bc)) e -= (bc << 1) - 1; /* Restore negative value if needed */ - d += e; /* Get current value */ - jd->dcv[cmp] = (int16_t)d; /* Save current DC value for next block */ - } - dqf = jd->qttbl[jd->qtid[cmp]]; /* De-quantizer table ID for this component */ - tmp[0] = d * dqf[0] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ - - /* Extract following 63 AC elements from input stream */ - memset(&tmp[1], 0, 63 * sizeof (int32_t)); /* Initialize all AC elements */ - z = 1; /* Top of the AC elements (in zigzag-order) */ - do { - d = huffext(jd, id, 1); /* Extract a huffman coded value (zero runs and bit length) */ - if (d == 0) break; /* EOB? */ - if (d < 0) return (JRESULT)(0 - d); /* Err: invalid code or input error */ - bc = (unsigned int)d; - z += bc >> 4; /* Skip leading zero run */ - if (z >= 64) return JDR_FMT1; /* Too long zero run */ - if (bc &= 0x0F) { /* Bit length? */ - d = bitext(jd, bc); /* Extract data bits */ - if (d < 0) return (JRESULT)(0 - d); /* Err: input device */ - bc = 1 << (bc - 1); /* MSB position */ - if (!(d & bc)) d -= (bc << 1) - 1; /* Restore negative value if needed */ - i = Zig[z]; /* Get raster-order index */ - tmp[i] = d * dqf[i] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ - } - } while (++z < 64); /* Next AC element */ - - if (JD_FORMAT != 2 || !cmp) { /* C components may not be processed if in grayscale output */ - if (z == 1 || (JD_USE_SCALE && jd->scale == 3)) { /* If no AC element or scale ratio is 1/8, IDCT can be ommited and the block is filled with DC value */ - d = (jd_yuv_t)((*tmp / 256) + 128); - if (JD_FASTDECODE >= 1) { - for (i = 0; i < 64; bp[i++] = d) ; - } else { - memset(bp, d, 64); - } - } else { - block_idct(tmp, bp); /* Apply IDCT and store the block to the MCU buffer */ - } - } - } - - bp += 64; /* Next block */ - } - - return JDR_OK; /* All blocks have been loaded successfully */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Output an MCU: Convert YCrCb to RGB and output it in RGB form */ -/*-----------------------------------------------------------------------*/ - -static JRESULT mcu_output ( - JDEC* jd, /* Pointer to the decompressor object */ - int (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ - unsigned int img_x, /* MCU location in the image */ - unsigned int img_y /* MCU location in the image */ -) -{ - const int CVACC = (sizeof (int) > 2) ? 1024 : 128; /* Adaptive accuracy for both 16-/32-bit systems */ - unsigned int ix, iy, mx, my, rx, ry; - int yy, cb, cr; - jd_yuv_t *py, *pc; - uint8_t *pix; - JRECT rect; - - - mx = jd->msx * 8; my = jd->msy * 8; /* MCU size (pixel) */ - rx = (img_x + mx <= jd->width) ? mx : jd->width - img_x; /* Output rectangular size (it may be clipped at right/bottom end of image) */ - ry = (img_y + my <= jd->height) ? my : jd->height - img_y; - if (JD_USE_SCALE) { - rx >>= jd->scale; ry >>= jd->scale; - if (!rx || !ry) return JDR_OK; /* Skip this MCU if all pixel is to be rounded off */ - img_x >>= jd->scale; img_y >>= jd->scale; - } - rect.left = img_x; rect.right = img_x + rx - 1; /* Rectangular area in the frame buffer */ - rect.top = img_y; rect.bottom = img_y + ry - 1; - - - if (!JD_USE_SCALE || jd->scale != 3) { /* Not for 1/8 scaling */ - pix = (uint8_t*)jd->workbuf; - - if (JD_FORMAT != 2) { /* RGB output (build an RGB MCU from Y/C component) */ - for (iy = 0; iy < my; iy++) { - pc = py = jd->mcubuf; - if (my == 16) { /* Double block height? */ - pc += 64 * 4 + (iy >> 1) * 8; - if (iy >= 8) py += 64; - } else { /* Single block height */ - pc += mx * 8 + iy * 8; - } - py += iy * 8; - for (ix = 0; ix < mx; ix++) { - cb = pc[0] - 128; /* Get Cb/Cr component and remove offset */ - cr = pc[64] - 128; - if (mx == 16) { /* Double block width? */ - if (ix == 8) py += 64 - 8; /* Jump to next block if double block heigt */ - pc += ix & 1; /* Step forward chroma pointer every two pixels */ - } else { /* Single block width */ - pc++; /* Step forward chroma pointer every pixel */ - } - yy = *py++; /* Get Y component */ - *pix++ = /*R*/ BYTECLIP(yy + ((int)(1.402 * CVACC) * cr) / CVACC); - *pix++ = /*G*/ BYTECLIP(yy - ((int)(0.344 * CVACC) * cb + (int)(0.714 * CVACC) * cr) / CVACC); - *pix++ = /*B*/ BYTECLIP(yy + ((int)(1.772 * CVACC) * cb) / CVACC); - } - } - } else { /* Monochrome output (build a grayscale MCU from Y comopnent) */ - for (iy = 0; iy < my; iy++) { - py = jd->mcubuf + iy * 8; - if (my == 16) { /* Double block height? */ - if (iy >= 8) py += 64; - } - for (ix = 0; ix < mx; ix++) { - if (mx == 16) { /* Double block width? */ - if (ix == 8) py += 64 - 8; /* Jump to next block if double block height */ - } - *pix++ = (uint8_t)*py++; /* Get and store a Y value as grayscale */ - } - } - } - - /* Descale the MCU rectangular if needed */ - if (JD_USE_SCALE && jd->scale) { - unsigned int x, y, r, g, b, s, w, a; - uint8_t *op; - - /* Get averaged RGB value of each square correcponds to a pixel */ - s = jd->scale * 2; /* Number of shifts for averaging */ - w = 1 << jd->scale; /* Width of square */ - a = (mx - w) * (JD_FORMAT != 2 ? 3 : 1); /* Bytes to skip for next line in the square */ - op = (uint8_t*)jd->workbuf; - for (iy = 0; iy < my; iy += w) { - for (ix = 0; ix < mx; ix += w) { - pix = (uint8_t*)jd->workbuf + (iy * mx + ix) * (JD_FORMAT != 2 ? 3 : 1); - r = g = b = 0; - for (y = 0; y < w; y++) { /* Accumulate RGB value in the square */ - for (x = 0; x < w; x++) { - r += *pix++; /* Accumulate R or Y (monochrome output) */ - if (JD_FORMAT != 2) { /* RGB output? */ - g += *pix++; /* Accumulate G */ - b += *pix++; /* Accumulate B */ - } - } - pix += a; - } /* Put the averaged pixel value */ - *op++ = (uint8_t)(r >> s); /* Put R or Y (monochrome output) */ - if (JD_FORMAT != 2) { /* RGB output? */ - *op++ = (uint8_t)(g >> s); /* Put G */ - *op++ = (uint8_t)(b >> s); /* Put B */ - } - } - } - } - - } else { /* For only 1/8 scaling (left-top pixel in each block are the DC value of the block) */ - - /* Build a 1/8 descaled RGB MCU from discrete comopnents */ - pix = (uint8_t*)jd->workbuf; - pc = jd->mcubuf + mx * my; - cb = pc[0] - 128; /* Get Cb/Cr component and restore right level */ - cr = pc[64] - 128; - for (iy = 0; iy < my; iy += 8) { - py = jd->mcubuf; - if (iy == 8) py += 64 * 2; - for (ix = 0; ix < mx; ix += 8) { - yy = *py; /* Get Y component */ - py += 64; - if (JD_FORMAT != 2) { - *pix++ = /*R*/ BYTECLIP(yy + ((int)(1.402 * CVACC) * cr / CVACC)); - *pix++ = /*G*/ BYTECLIP(yy - ((int)(0.344 * CVACC) * cb + (int)(0.714 * CVACC) * cr) / CVACC); - *pix++ = /*B*/ BYTECLIP(yy + ((int)(1.772 * CVACC) * cb / CVACC)); - } else { - *pix++ = yy; - } - } - } - } - - /* Squeeze up pixel table if a part of MCU is to be truncated */ - mx >>= jd->scale; - if (rx < mx) { /* Is the MCU spans rigit edge? */ - uint8_t *s, *d; - unsigned int x, y; - - s = d = (uint8_t*)jd->workbuf; - for (y = 0; y < ry; y++) { - for (x = 0; x < rx; x++) { /* Copy effective pixels */ - *d++ = *s++; - if (JD_FORMAT != 2) { - *d++ = *s++; - *d++ = *s++; - } - } - s += (mx - rx) * (JD_FORMAT != 2 ? 3 : 1); /* Skip truncated pixels */ - } - } - - /* Convert RGB888 to RGB565 if needed */ - if (JD_FORMAT == 1) { - uint8_t *s = (uint8_t*)jd->workbuf; - uint16_t w, *d = (uint16_t*)s; - unsigned int n = rx * ry; - - do { - w = (*s++ & 0xF8) << 8; /* RRRRR----------- */ - w |= (*s++ & 0xFC) << 3; /* -----GGGGGG----- */ - w |= *s++ >> 3; /* -----------BBBBB */ - *d++ = w; - } while (--n); - } - - /* Output the rectangular */ - return outfunc(jd, jd->workbuf, &rect) ? JDR_OK : JDR_INTR; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Analyze the JPEG image and Initialize decompressor object */ -/*-----------------------------------------------------------------------*/ - -#define LDB_WORD(ptr) (uint16_t)(((uint16_t)*((uint8_t*)(ptr))<<8)|(uint16_t)*(uint8_t*)((ptr)+1)) - - -JRESULT jd_prepare ( - JDEC* jd, /* Blank decompressor object */ - size_t (*infunc)(JDEC*, uint8_t*, size_t), /* JPEG strem input function */ - void* pool, /* Working buffer for the decompression session */ - size_t sz_pool, /* Size of working buffer */ - void* dev /* I/O device identifier for the session */ -) -{ - uint8_t *seg, b; - uint16_t marker; - unsigned int n, i, ofs; - size_t len; - JRESULT rc; - - - memset(jd, 0, sizeof (JDEC)); /* Clear decompression object (this might be a problem if machine's null pointer is not all bits zero) */ - jd->pool = pool; /* Work memroy */ - jd->sz_pool = sz_pool; /* Size of given work memory */ - jd->infunc = infunc; /* Stream input function */ - jd->device = dev; /* I/O device identifier */ - - jd->inbuf = seg = alloc_pool(jd, JD_SZBUF); /* Allocate stream input buffer */ - if (!seg) return JDR_MEM1; - - ofs = marker = 0; /* Find SOI marker */ - do { - if (jd->infunc(jd, seg, 1) != 1) return JDR_INP; /* Err: SOI was not detected */ - ofs++; - marker = marker << 8 | seg[0]; - } while (marker != 0xFFD8); - - for (;;) { /* Parse JPEG segments */ - /* Get a JPEG marker */ - if (jd->infunc(jd, seg, 4) != 4) return JDR_INP; - marker = LDB_WORD(seg); /* Marker */ - len = LDB_WORD(seg + 2); /* Length field */ - if (len <= 2 || (marker >> 8) != 0xFF) return JDR_FMT1; - len -= 2; /* Segent content size */ - ofs += 4 + len; /* Number of bytes loaded */ - - switch (marker & 0xFF) { - case 0xC0: /* SOF0 (baseline JPEG) */ - if (len > JD_SZBUF) return JDR_MEM2; - if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ - - jd->width = LDB_WORD(&seg[3]); /* Image width in unit of pixel */ - jd->height = LDB_WORD(&seg[1]); /* Image height in unit of pixel */ - jd->ncomp = seg[5]; /* Number of color components */ - if (jd->ncomp != 3 && jd->ncomp != 1) return JDR_FMT3; /* Err: Supports only Grayscale and Y/Cb/Cr */ - - /* Check each image component */ - for (i = 0; i < jd->ncomp; i++) { - b = seg[7 + 3 * i]; /* Get sampling factor */ - if (i == 0) { /* Y component */ - if (b != 0x11 && b != 0x22 && b != 0x21) { /* Check sampling factor */ - return JDR_FMT3; /* Err: Supports only 4:4:4, 4:2:0 or 4:2:2 */ - } - jd->msx = b >> 4; jd->msy = b & 15; /* Size of MCU [blocks] */ - } else { /* Cb/Cr component */ - if (b != 0x11) return JDR_FMT3; /* Err: Sampling factor of Cb/Cr must be 1 */ - } - jd->qtid[i] = seg[8 + 3 * i]; /* Get dequantizer table ID for this component */ - if (jd->qtid[i] > 3) return JDR_FMT3; /* Err: Invalid ID */ - } - break; - - case 0xDD: /* DRI - Define Restart Interval */ - if (len > JD_SZBUF) return JDR_MEM2; - if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ - - jd->nrst = LDB_WORD(seg); /* Get restart interval (MCUs) */ - break; - - case 0xC4: /* DHT - Define Huffman Tables */ - if (len > JD_SZBUF) return JDR_MEM2; - if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ - - rc = create_huffman_tbl(jd, seg, len); /* Create huffman tables */ - if (rc) return rc; - break; - - case 0xDB: /* DQT - Define Quaitizer Tables */ - if (len > JD_SZBUF) return JDR_MEM2; - if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ - - rc = create_qt_tbl(jd, seg, len); /* Create de-quantizer tables */ - if (rc) return rc; - break; - - case 0xDA: /* SOS - Start of Scan */ - if (len > JD_SZBUF) return JDR_MEM2; - if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ - - if (!jd->width || !jd->height) return JDR_FMT1; /* Err: Invalid image size */ - if (seg[0] != jd->ncomp) return JDR_FMT3; /* Err: Wrong color components */ - - /* Check if all tables corresponding to each components have been loaded */ - for (i = 0; i < jd->ncomp; i++) { - b = seg[2 + 2 * i]; /* Get huffman table ID */ - if (b != 0x00 && b != 0x11) return JDR_FMT3; /* Err: Different table number for DC/AC element */ - n = i ? 1 : 0; /* Component class */ - if (!jd->huffbits[n][0] || !jd->huffbits[n][1]) { /* Check huffman table for this component */ - return JDR_FMT1; /* Err: Nnot loaded */ - } - if (!jd->qttbl[jd->qtid[i]]) { /* Check dequantizer table for this component */ - return JDR_FMT1; /* Err: Not loaded */ - } - } - - /* Allocate working buffer for MCU and pixel output */ - n = jd->msy * jd->msx; /* Number of Y blocks in the MCU */ - if (!n) return JDR_FMT1; /* Err: SOF0 has not been loaded */ - len = n * 64 * 2 + 64; /* Allocate buffer for IDCT and RGB output */ - if (len < 256) len = 256; /* but at least 256 byte is required for IDCT */ - jd->workbuf = alloc_pool(jd, len); /* and it may occupy a part of following MCU working buffer for RGB output */ - if (!jd->workbuf) return JDR_MEM1; /* Err: not enough memory */ - jd->mcubuf = alloc_pool(jd, (n + 2) * 64 * sizeof (jd_yuv_t)); /* Allocate MCU working buffer */ - if (!jd->mcubuf) return JDR_MEM1; /* Err: not enough memory */ - - /* Align stream read offset to JD_SZBUF */ - if (ofs %= JD_SZBUF) { - jd->dctr = jd->infunc(jd, seg + ofs, (size_t)(JD_SZBUF - ofs)); - } - jd->dptr = seg + ofs - (JD_FASTDECODE ? 0 : 1); - - return JDR_OK; /* Initialization succeeded. Ready to decompress the JPEG image. */ - - case 0xC1: /* SOF1 */ - case 0xC2: /* SOF2 */ - case 0xC3: /* SOF3 */ - case 0xC5: /* SOF5 */ - case 0xC6: /* SOF6 */ - case 0xC7: /* SOF7 */ - case 0xC9: /* SOF9 */ - case 0xCA: /* SOF10 */ - case 0xCB: /* SOF11 */ - case 0xCD: /* SOF13 */ - case 0xCE: /* SOF14 */ - case 0xCF: /* SOF15 */ - case 0xD9: /* EOI */ - return JDR_FMT3; /* Unsuppoted JPEG standard (may be progressive JPEG) */ - - default: /* Unknown segment (comment, exif or etc..) */ - /* Skip segment data (null pointer specifies to remove data from the stream) */ - if (jd->infunc(jd, 0, len) != len) return JDR_INP; - } - } -} - - - - -/*-----------------------------------------------------------------------*/ -/* Start to decompress the JPEG picture */ -/*-----------------------------------------------------------------------*/ - -JRESULT jd_decomp ( - JDEC* jd, /* Initialized decompression object */ - int (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ - uint8_t scale /* Output de-scaling factor (0 to 3) */ -) -{ - unsigned int x, y, mx, my; - uint16_t rst, rsc; - JRESULT rc; - - - if (scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR; - jd->scale = scale; - - mx = jd->msx * 8; my = jd->msy * 8; /* Size of the MCU (pixel) */ - - jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */ - rst = rsc = 0; - - rc = JDR_OK; - for (y = 0; y < jd->height; y += my) { /* Vertical loop of MCUs */ - for (x = 0; x < jd->width; x += mx) { /* Horizontal loop of MCUs */ - if (jd->nrst && rst++ == jd->nrst) { /* Process restart interval if enabled */ - rc = restart(jd, rsc++); - if (rc != JDR_OK) return rc; - rst = 1; - } - rc = mcu_load(jd); /* Load an MCU (decompress huffman coded stream, dequantize and apply IDCT) */ - if (rc != JDR_OK) return rc; - rc = mcu_output(jd, outfunc, x, y); /* Output the MCU (YCbCr to RGB, scaling and output) */ - if (rc != JDR_OK) return rc; - } - } - - return rc; -} - -#endif /*LV_USE_SJPG*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgd.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgd.h deleted file mode 100644 index b255ccfcf..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgd.h +++ /dev/null @@ -1,93 +0,0 @@ -/*----------------------------------------------------------------------------/ -/ TJpgDec - Tiny JPEG Decompressor R0.03 include file (C)ChaN, 2021 -/----------------------------------------------------------------------------*/ -#ifndef DEF_TJPGDEC -#define DEF_TJPGDEC - -#ifdef __cplusplus -extern "C" { -#endif - -#include "../../../lv_conf_internal.h" -#if LV_USE_SJPG - -#include "tjpgdcnf.h" -#include -#include - -#if JD_FASTDECODE >= 1 -typedef int16_t jd_yuv_t; -#else -typedef uint8_t jd_yuv_t; -#endif - - -/* Error code */ -typedef enum { - JDR_OK = 0, /* 0: Succeeded */ - JDR_INTR, /* 1: Interrupted by output function */ - JDR_INP, /* 2: Device error or wrong termination of input stream */ - JDR_MEM1, /* 3: Insufficient memory pool for the image */ - JDR_MEM2, /* 4: Insufficient stream input buffer */ - JDR_PAR, /* 5: Parameter error */ - JDR_FMT1, /* 6: Data format error (may be broken data) */ - JDR_FMT2, /* 7: Right format but not supported */ - JDR_FMT3 /* 8: Not supported JPEG standard */ -} JRESULT; - -/* Rectangular region in the output image */ -typedef struct { - uint16_t left; /* Left end */ - uint16_t right; /* Right end */ - uint16_t top; /* Top end */ - uint16_t bottom; /* Bottom end */ -} JRECT; - -/* Decompressor object structure */ -typedef struct JDEC JDEC; -struct JDEC { - size_t dctr; /* Number of bytes available in the input buffer */ - uint8_t* dptr; /* Current data read ptr */ - uint8_t* inbuf; /* Bit stream input buffer */ - uint8_t dbit; /* Number of bits availavble in wreg or reading bit mask */ - uint8_t scale; /* Output scaling ratio */ - uint8_t msx, msy; /* MCU size in unit of block (width, height) */ - uint8_t qtid[3]; /* Quantization table ID of each component, Y, Cb, Cr */ - uint8_t ncomp; /* Number of color components 1:grayscale, 3:color */ - int16_t dcv[3]; /* Previous DC element of each component */ - uint16_t nrst; /* Restart inverval */ - uint16_t width, height; /* Size of the input image (pixel) */ - uint8_t* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ - uint16_t* huffcode[2][2]; /* Huffman code word tables [id][dcac] */ - uint8_t* huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ - int32_t* qttbl[4]; /* Dequantizer tables [id] */ -#if JD_FASTDECODE >= 1 - uint32_t wreg; /* Working shift register */ - uint8_t marker; /* Detected marker (0:None) */ -#if JD_FASTDECODE == 2 - uint8_t longofs[2][2]; /* Table offset of long code [id][dcac] */ - uint16_t* hufflut_ac[2]; /* Fast huffman decode tables for AC short code [id] */ - uint8_t* hufflut_dc[2]; /* Fast huffman decode tables for DC short code [id] */ -#endif -#endif - void* workbuf; /* Working buffer for IDCT and RGB output */ - jd_yuv_t* mcubuf; /* Working buffer for the MCU */ - void* pool; /* Pointer to available memory pool */ - size_t sz_pool; /* Size of momory pool (bytes available) */ - size_t (*infunc)(JDEC*, uint8_t*, size_t); /* Pointer to jpeg stream input function */ - void* device; /* Pointer to I/O device identifiler for the session */ -}; - - - -/* TJpgDec API functions */ -JRESULT jd_prepare (JDEC* jd, size_t (*infunc)(JDEC*,uint8_t*,size_t), void* pool, size_t sz_pool, void* dev); -JRESULT jd_decomp (JDEC* jd, int (*outfunc)(JDEC*,void*,JRECT*), uint8_t scale); - -#endif /*LV_USE_SJPG*/ - -#ifdef __cplusplus -} -#endif - -#endif /* _TJPGDEC */ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/tiny_ttf/lv_tiny_ttf.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/tiny_ttf/lv_tiny_ttf.c deleted file mode 100644 index c275bfed2..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/tiny_ttf/lv_tiny_ttf.c +++ /dev/null @@ -1,284 +0,0 @@ -#include "lv_tiny_ttf.h" - -#if LV_USE_TINY_TTF -#include -#include "../../../misc/lv_lru.h" - -#define STB_RECT_PACK_IMPLEMENTATION -#define STBRP_STATIC -#define STBTT_STATIC -#define STB_TRUETYPE_IMPLEMENTATION -#define STBTT_HEAP_FACTOR_SIZE_32 50 -#define STBTT_HEAP_FACTOR_SIZE_128 20 -#define STBTT_HEAP_FACTOR_SIZE_DEFAULT 10 -#define STBTT_malloc(x, u) ((void)(u), lv_mem_alloc(x)) -#define STBTT_free(x, u) ((void)(u), lv_mem_free(x)) -#define TTF_MALLOC(x) (lv_mem_alloc(x)) -#define TTF_FREE(x) (lv_mem_free(x)) - -#if LV_TINY_TTF_FILE_SUPPORT -/* a hydra stream that can be in memory or from a file*/ -typedef struct ttf_cb_stream { - lv_fs_file_t * file; - const void * data; - size_t size; - size_t position; -} ttf_cb_stream_t; - -static void ttf_cb_stream_read(ttf_cb_stream_t * stream, void * data, size_t to_read) -{ - if(stream->file != NULL) { - uint32_t br; - lv_fs_read(stream->file, data, to_read, &br); - } - else { - if(to_read + stream->position >= stream->size) { - to_read = stream->size - stream->position; - } - lv_memcpy(data, ((const unsigned char *)stream->data + stream->position), to_read); - stream->position += to_read; - } -} -static void ttf_cb_stream_seek(ttf_cb_stream_t * stream, size_t position) -{ - if(stream->file != NULL) { - lv_fs_seek(stream->file, position, LV_FS_SEEK_SET); - } - else { - if(position > stream->size) { - stream->position = stream->size; - } - else { - stream->position = position; - } - } -} - -/* for stream support */ -#define STBTT_STREAM_TYPE ttf_cb_stream_t * -#define STBTT_STREAM_SEEK(s, x) ttf_cb_stream_seek(s, x); -#define STBTT_STREAM_READ(s, x, y) ttf_cb_stream_read(s, x, y); -#endif /*LV_TINY_TTF_FILE_SUPPORT*/ - -#include "stb_rect_pack.h" -#include "stb_truetype_htcw.h" - -typedef struct ttf_font_desc { - lv_fs_file_t file; -#if LV_TINY_TTF_FILE_SUPPORT - ttf_cb_stream_t stream; -#else - const uint8_t * stream; -#endif - stbtt_fontinfo info; - float scale; - int ascent; - int descent; - lv_lru_t * bitmap_cache; -} ttf_font_desc_t; - -typedef struct ttf_bitmap_cache_key { - uint32_t unicode_letter; - lv_coord_t line_height; -} ttf_bitmap_cache_key_t; - -static bool ttf_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, - uint32_t unicode_letter_next) -{ - if(unicode_letter < 0x20 || - unicode_letter == 0xf8ff || /*LV_SYMBOL_DUMMY*/ - unicode_letter == 0x200c) { /*ZERO WIDTH NON-JOINER*/ - dsc_out->box_w = 0; - dsc_out->adv_w = 0; - dsc_out->box_h = 0; /*height of the bitmap in [px]*/ - dsc_out->ofs_x = 0; /*X offset of the bitmap in [pf]*/ - dsc_out->ofs_y = 0; /*Y offset of the bitmap in [pf]*/ - dsc_out->bpp = 0; - dsc_out->is_placeholder = false; - return true; - } - ttf_font_desc_t * dsc = (ttf_font_desc_t *)font->dsc; - int g1 = stbtt_FindGlyphIndex(&dsc->info, (int)unicode_letter); - if(g1 == 0) { - /* Glyph not found */ - return false; - } - int x1, y1, x2, y2; - - stbtt_GetGlyphBitmapBox(&dsc->info, g1, dsc->scale, dsc->scale, &x1, &y1, &x2, &y2); - int g2 = 0; - if(unicode_letter_next != 0) { - g2 = stbtt_FindGlyphIndex(&dsc->info, (int)unicode_letter_next); - } - int advw, lsb; - stbtt_GetGlyphHMetrics(&dsc->info, g1, &advw, &lsb); - int k = stbtt_GetGlyphKernAdvance(&dsc->info, g1, g2); - dsc_out->adv_w = (uint16_t)floor((((float)advw + (float)k) * dsc->scale) + - 0.5f); /*Horizontal space required by the glyph in [px]*/ - - dsc_out->adv_w = (uint16_t)floor((((float)advw + (float)k) * dsc->scale) + - 0.5f); /*Horizontal space required by the glyph in [px]*/ - dsc_out->box_w = (x2 - x1 + 1); /*width of the bitmap in [px]*/ - dsc_out->box_h = (y2 - y1 + 1); /*height of the bitmap in [px]*/ - dsc_out->ofs_x = x1; /*X offset of the bitmap in [pf]*/ - dsc_out->ofs_y = -y2; /*Y offset of the bitmap measured from the as line*/ - dsc_out->bpp = 8; /*Bits per pixel: 1/2/4/8*/ - dsc_out->is_placeholder = false; - return true; /*true: glyph found; false: glyph was not found*/ -} - -static const uint8_t * ttf_get_glyph_bitmap_cb(const lv_font_t * font, uint32_t unicode_letter) -{ - ttf_font_desc_t * dsc = (ttf_font_desc_t *)font->dsc; - const stbtt_fontinfo * info = (const stbtt_fontinfo *)&dsc->info; - int g1 = stbtt_FindGlyphIndex(info, (int)unicode_letter); - if(g1 == 0) { - /* Glyph not found */ - return NULL; - } - int x1, y1, x2, y2; - stbtt_GetGlyphBitmapBox(info, g1, dsc->scale, dsc->scale, &x1, &y1, &x2, &y2); - int w, h; - w = x2 - x1 + 1; - h = y2 - y1 + 1; - uint32_t stride = w; - /*Try to load from cache*/ - ttf_bitmap_cache_key_t cache_key; - lv_memset(&cache_key, 0, sizeof(cache_key)); /*Zero padding*/ - cache_key.unicode_letter = unicode_letter; - cache_key.line_height = font->line_height; - uint8_t * buffer = NULL; - lv_lru_get(dsc->bitmap_cache, &cache_key, sizeof(cache_key), (void **)&buffer); - if(buffer) { - return buffer; - } - LV_LOG_TRACE("cache miss for letter: %u", unicode_letter); - /*Prepare space in cache*/ - size_t szb = h * stride; - buffer = lv_mem_alloc(szb); - if(!buffer) { - LV_LOG_ERROR("failed to allocate cache value"); - return NULL; - } - lv_memset(buffer, 0, szb); - if(LV_LRU_OK != lv_lru_set(dsc->bitmap_cache, &cache_key, sizeof(cache_key), buffer, szb)) { - LV_LOG_ERROR("failed to add cache value"); - lv_mem_free(buffer); - return NULL; - } - /*Render into cache*/ - stbtt_MakeGlyphBitmap(info, buffer, w, h, stride, dsc->scale, dsc->scale, g1); - return buffer; -} - -static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size_t data_size, lv_coord_t font_size, - size_t cache_size) -{ - if((path == NULL && data == NULL) || 0 >= font_size) { - LV_LOG_ERROR("tiny_ttf: invalid argument\n"); - return NULL; - } - ttf_font_desc_t * dsc = (ttf_font_desc_t *)TTF_MALLOC(sizeof(ttf_font_desc_t)); - if(dsc == NULL) { - LV_LOG_ERROR("tiny_ttf: out of memory\n"); - return NULL; - } -#if LV_TINY_TTF_FILE_SUPPORT - if(path != NULL) { - if(LV_FS_RES_OK != lv_fs_open(&dsc->file, path, LV_FS_MODE_RD)) { - LV_LOG_ERROR("tiny_ttf: unable to open %s\n", path); - goto err_after_dsc; - } - dsc->stream.file = &dsc->file; - } - else { - dsc->stream.file = NULL; - dsc->stream.data = (const uint8_t *)data; - dsc->stream.size = data_size; - dsc->stream.position = 0; - } - if(0 == stbtt_InitFont(&dsc->info, &dsc->stream, stbtt_GetFontOffsetForIndex(&dsc->stream, 0))) { - LV_LOG_ERROR("tiny_ttf: init failed\n"); - goto err_after_dsc; - } - -#else - dsc->stream = (const uint8_t *)data; - LV_UNUSED(data_size); - if(0 == stbtt_InitFont(&dsc->info, dsc->stream, stbtt_GetFontOffsetForIndex(dsc->stream, 0))) { - LV_LOG_ERROR("tiny_ttf: init failed\n"); - goto err_after_dsc; - } -#endif - - dsc->bitmap_cache = lv_lru_create(cache_size, font_size * font_size, lv_mem_free, lv_mem_free); - if(dsc->bitmap_cache == NULL) { - LV_LOG_ERROR("failed to create lru cache"); - goto err_after_dsc; - } - - lv_font_t * out_font = (lv_font_t *)TTF_MALLOC(sizeof(lv_font_t)); - if(out_font == NULL) { - LV_LOG_ERROR("tiny_ttf: out of memory\n"); - goto err_after_bitmap_cache; - } - lv_memset(out_font, 0, sizeof(lv_font_t)); - out_font->get_glyph_dsc = ttf_get_glyph_dsc_cb; - out_font->get_glyph_bitmap = ttf_get_glyph_bitmap_cb; - out_font->dsc = dsc; - lv_tiny_ttf_set_size(out_font, font_size); - return out_font; -err_after_bitmap_cache: - lv_lru_del(dsc->bitmap_cache); -err_after_dsc: - TTF_FREE(dsc); - return NULL; -} -#if LV_TINY_TTF_FILE_SUPPORT -lv_font_t * lv_tiny_ttf_create_file_ex(const char * path, lv_coord_t font_size, size_t cache_size) -{ - return lv_tiny_ttf_create(path, NULL, 0, font_size, cache_size); -} -lv_font_t * lv_tiny_ttf_create_file(const char * path, lv_coord_t font_size) -{ - return lv_tiny_ttf_create_file_ex(path, font_size, 4096); -} -#endif /*LV_TINY_TTF_FILE_SUPPORT*/ -lv_font_t * lv_tiny_ttf_create_data_ex(const void * data, size_t data_size, lv_coord_t font_size, size_t cache_size) -{ - return lv_tiny_ttf_create(NULL, data, data_size, font_size, cache_size); -} -lv_font_t * lv_tiny_ttf_create_data(const void * data, size_t data_size, lv_coord_t font_size) -{ - return lv_tiny_ttf_create_data_ex(data, data_size, font_size, 4096); -} -void lv_tiny_ttf_set_size(lv_font_t * font, lv_coord_t font_size) -{ - if(font_size <= 0) { - LV_LOG_ERROR("invalid font size: %"PRIx32, font_size); - return; - } - ttf_font_desc_t * dsc = (ttf_font_desc_t *)font->dsc; - dsc->scale = stbtt_ScaleForMappingEmToPixels(&dsc->info, font_size); - int line_gap = 0; - stbtt_GetFontVMetrics(&dsc->info, &dsc->ascent, &dsc->descent, &line_gap); - font->line_height = (lv_coord_t)(dsc->scale * (dsc->ascent - dsc->descent + line_gap)); - font->base_line = (lv_coord_t)(dsc->scale * (line_gap - dsc->descent)); -} -void lv_tiny_ttf_destroy(lv_font_t * font) -{ - if(font != NULL) { - if(font->dsc != NULL) { - ttf_font_desc_t * ttf = (ttf_font_desc_t *)font->dsc; -#if LV_TINY_TTF_FILE_SUPPORT - if(ttf->stream.file != NULL) { - lv_fs_close(&ttf->file); - } -#endif - lv_lru_del(ttf->bitmap_cache); - TTF_FREE(ttf); - } - TTF_FREE(font); - } -} -#endif /*LV_USE_TINY_TTF*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.c b/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.c deleted file mode 100644 index 380833725..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.c +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @file lv_extra.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../lvgl.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void lv_extra_init(void) -{ -#if LV_USE_FLEX - lv_flex_init(); -#endif - -#if LV_USE_GRID - lv_grid_init(); -#endif - -#if LV_USE_MSG - lv_msg_init(); -#endif - -#if LV_USE_FS_FATFS != '\0' - lv_fs_fatfs_init(); -#endif - -#if LV_USE_FS_LITTLEFS != '\0' - lv_fs_littlefs_init(); -#endif - -#if LV_USE_FS_STDIO != '\0' - lv_fs_stdio_init(); -#endif - -#if LV_USE_FS_POSIX != '\0' - lv_fs_posix_init(); -#endif - -#if LV_USE_FS_WIN32 != '\0' - lv_fs_win32_init(); -#endif - -#if LV_USE_FFMPEG - lv_ffmpeg_init(); -#endif - -#if LV_USE_PNG - lv_png_init(); -#endif - -#if LV_USE_SJPG - lv_split_jpeg_init(); -#endif - -#if LV_USE_BMP - lv_bmp_init(); -#endif - -#if LV_USE_FREETYPE - /*Init freetype library*/ -# if LV_FREETYPE_CACHE_SIZE >= 0 - lv_freetype_init(LV_FREETYPE_CACHE_FT_FACES, LV_FREETYPE_CACHE_FT_SIZES, LV_FREETYPE_CACHE_SIZE); -# else - lv_freetype_init(0, 0, 0); -# endif -#endif -} - -/********************** - * STATIC FUNCTIONS - **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.mk b/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.mk deleted file mode 100644 index 8d418adb0..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/lv_extra.mk +++ /dev/null @@ -1 +0,0 @@ -CSRCS += $(shell find -L $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/extra -name "*.c") diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/lv_others.h b/lib/libesp32_lvgl/lvgl/src/extra/others/lv_others.h deleted file mode 100644 index 813e338c3..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/lv_others.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @file lv_others.h - * - */ - -#ifndef LV_OTHERS_H -#define LV_OTHERS_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "snapshot/lv_snapshot.h" -#include "monkey/lv_monkey.h" -#include "gridnav/lv_gridnav.h" -// TASMOTA specific -// #include "fragment/lv_fragment.h" -// #include "imgfont/lv_imgfont.h" -// #include "msg/lv_msg.h" -// #include "ime/lv_ime_pinyin.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_OTHERS_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/msg/lv_msg.c b/lib/libesp32_lvgl/lvgl/src/extra/others/msg/lv_msg.c deleted file mode 100644 index d54279c08..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/msg/lv_msg.c +++ /dev/null @@ -1,189 +0,0 @@ -/** - * @file lv_msg.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_msg.h" -#if LV_USE_MSG - -#include "../../../misc/lv_assert.h" -#include "../../../misc/lv_ll.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - uint32_t msg_id; - lv_msg_subscribe_cb_t callback; - void * user_data; - void * _priv_data; /*Internal: used only store 'obj' in lv_obj_subscribe*/ -} sub_dsc_t; - -/********************** - * STATIC PROTOTYPES - **********************/ - -static void notify(lv_msg_t * m); -static void obj_notify_cb(void * s, lv_msg_t * m); -static void obj_delete_event_cb(lv_event_t * e); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_ll_t subs_ll; - -/********************** - * GLOBAL VARIABLES - **********************/ -lv_event_code_t LV_EVENT_MSG_RECEIVED; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -void lv_msg_init(void) -{ - LV_EVENT_MSG_RECEIVED = lv_event_register_id(); - _lv_ll_init(&subs_ll, sizeof(sub_dsc_t)); -} - -void * lv_msg_subsribe(uint32_t msg_id, lv_msg_subscribe_cb_t cb, void * user_data) -{ - sub_dsc_t * s = _lv_ll_ins_tail(&subs_ll); - LV_ASSERT_MALLOC(s); - if(s == NULL) return NULL; - - lv_memset_00(s, sizeof(*s)); - - s->msg_id = msg_id; - s->callback = cb; - s->user_data = user_data; - return s; -} - -void * lv_msg_subsribe_obj(uint32_t msg_id, lv_obj_t * obj, void * user_data) -{ - sub_dsc_t * s = lv_msg_subsribe(msg_id, obj_notify_cb, user_data); - if(s == NULL) return NULL; - s->_priv_data = obj; - - /*If not added yet, add a delete event cb which automatically unsubcribes the object*/ - sub_dsc_t * s_first = lv_obj_get_event_user_data(obj, obj_delete_event_cb); - if(s_first == NULL) { - lv_obj_add_event_cb(obj, obj_delete_event_cb, LV_EVENT_DELETE, s); - } - return s; -} - -void lv_msg_unsubscribe(void * s) -{ - LV_ASSERT_NULL(s); - _lv_ll_remove(&subs_ll, s); - lv_mem_free(s); -} - -uint32_t lv_msg_unsubscribe_obj(uint32_t msg_id, lv_obj_t * obj) -{ - uint32_t cnt = 0; - sub_dsc_t * s = _lv_ll_get_head(&subs_ll); - while(s) { - sub_dsc_t * s_next = _lv_ll_get_next(&subs_ll, s); - if(s->callback == obj_notify_cb && - (s->msg_id == LV_MSG_ID_ANY || s->msg_id == msg_id) && - (obj == NULL || s->_priv_data == obj)) { - lv_msg_unsubscribe(s); - cnt++; - } - - s = s_next; - } - - return cnt; -} - -void lv_msg_send(uint32_t msg_id, const void * payload) -{ - lv_msg_t m; - lv_memset_00(&m, sizeof(m)); - m.id = msg_id; - m.payload = payload; - notify(&m); -} - -uint32_t lv_msg_get_id(lv_msg_t * m) -{ - return m->id; -} - -const void * lv_msg_get_payload(lv_msg_t * m) -{ - return m->payload; -} - -void * lv_msg_get_user_data(lv_msg_t * m) -{ - return m->user_data; -} - -lv_msg_t * lv_event_get_msg(lv_event_t * e) -{ - if(e->code == LV_EVENT_MSG_RECEIVED) { - return lv_event_get_param(e); - } - else { - LV_LOG_WARN("Not interpreted with this event code"); - return NULL; - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void notify(lv_msg_t * m) -{ - sub_dsc_t * s; - _LV_LL_READ(&subs_ll, s) { - if(s->msg_id == m->id && s->callback) { - m->user_data = s->user_data; - m->_priv_data = s->_priv_data; - s->callback(s, m); - } - } -} - -static void obj_notify_cb(void * s, lv_msg_t * m) -{ - LV_UNUSED(s); - lv_event_send(m->_priv_data, LV_EVENT_MSG_RECEIVED, m); -} - -static void obj_delete_event_cb(lv_event_t * e) -{ - lv_obj_t * obj = lv_event_get_target(e); - - sub_dsc_t * s = _lv_ll_get_head(&subs_ll); - sub_dsc_t * s_next; - while(s) { - /*On unsubscribe the list changes s becomes invalid so get next item while it's surely valid*/ - s_next = _lv_ll_get_next(&subs_ll, s); - if(s->_priv_data == obj) { - lv_msg_unsubscribe(s); - } - s = s_next; - } -} - -#endif /*LV_USE_MSG*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/msg/lv_msg.h b/lib/libesp32_lvgl/lvgl/src/extra/others/msg/lv_msg.h deleted file mode 100644 index 0ac2f77d5..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/msg/lv_msg.h +++ /dev/null @@ -1,145 +0,0 @@ -/** - * @file lv_msg.h - * - */ - -#ifndef LV_MSG_H -#define LV_MSG_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../../core/lv_obj.h" -#if LV_USE_MSG - -/********************* - * DEFINES - *********************/ -#define LV_MSG_ID_ANY UINT32_MAX -LV_EXPORT_CONST_INT(LV_MSG_ID_ANY); - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - uint32_t id; /*Identifier of the message*/ - void * user_data; /*Set the the user_data set in `lv_msg_subscribe`*/ - void * _priv_data; /*Used internally*/ - const void * payload; /*Pointer to the data of the message*/ -} lv_msg_t; - -typedef void (*lv_msg_subscribe_cb_t)(void * s, lv_msg_t * msg); - -typedef void (*lv_msg_request_cb_t)(void * r, uint32_t msg_id); - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Called internally to initialize the message module - */ -void lv_msg_init(void); - -/** - * Subscribe to an `msg_id` - * @param msg_id the message ID to listen to - * @param cb callback to call if a message with `msg_id` was sent - * @param user_data arbitrary data which will be available in `cb` too - * @return pointer to a "subscribe object". It can be used the unsubscribe. - */ -void * lv_msg_subsribe(uint32_t msg_id, lv_msg_subscribe_cb_t cb, void * user_data); - -/** - * Subscribe an `lv_obj` to a message. - * `LV_EVENT_MSG_RECEIVED` will be triggered if a message with matching ID was sent - * @param msg_id the message ID to listen to - * @param obj pointer to an `lv_obj` - * @param user_data arbitrary data which will be available in `cb` too - * @return pointer to a "subscribe object". It can be used the unsubscribe. - */ -void * lv_msg_subsribe_obj(uint32_t msg_id, lv_obj_t * obj, void * user_data); - -/** - * Cancel a previous subscription - * @param s pointer to a "subscibe object". - * Return value of `lv_msg_subsribe` or `lv_msg_subsribe_obj` - */ -void lv_msg_unsubscribe(void * s); - -/** - * Unsubscribe an object from a message ID - * @param msg_id the message ID to unsubcribe from or `LV_MSG_ID_ANY` for any message ID - * @param obj the object to unsubscribe or NULL for any object - * @return number of unsubscriptions - */ -uint32_t lv_msg_unsubscribe_obj(uint32_t msg_id, lv_obj_t * obj); - -/** - * Send a message with a given ID and payload - * @param msg_id ID of the message to send - * @param data pointer to the data to send - */ -void lv_msg_send(uint32_t msg_id, const void * payload); - -/** - * Get the ID of a message object. Typically used in the subscriber callback. - * @param m pointer to a message object - * @return the ID of the message - */ -uint32_t lv_msg_get_id(lv_msg_t * m); - -/** - * Get the payload of a message object. Typically used in the subscriber callback. - * @param m pointer to a message object - * @return the payload of the message - */ -const void * lv_msg_get_payload(lv_msg_t * m); - -/** - * Get the user data of a message object. Typically used in the subscriber callback. - * @param m pointer to a message object - * @return the user data of the message - */ -void * lv_msg_get_user_data(lv_msg_t * m); - -/** - * Get the message object from an event object. Can be used in `LV_EVENT_MSG_RECEIVED` events. - * @param e pointer to an event object - * @return the message object or NULL if called with unrelated event code. - */ -lv_msg_t * lv_event_get_msg(lv_event_t * e); - -/*Fix typo*/ -static inline void * lv_msg_subscribe(uint32_t msg_id, lv_msg_subscribe_cb_t cb, void * user_data) -{ - return lv_msg_subsribe(msg_id, cb, user_data); -} - -static inline void * lv_msg_subscribe_obj(uint32_t msg_id, lv_obj_t * obj, void * user_data) -{ - return lv_msg_subsribe_obj(msg_id, obj, user_data); -} - -/********************** - * GLOBAL VARIABLES - **********************/ - -extern lv_event_code_t LV_EVENT_MSG_RECEIVED; - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_MSG*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_MSG_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.c b/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.c deleted file mode 100644 index 1b2275115..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.c +++ /dev/null @@ -1,213 +0,0 @@ -/** - * @file lv_snapshot.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_snapshot.h" -#if LV_USE_SNAPSHOT - -#include -#include "../../../core/lv_disp.h" -#include "../../../core/lv_refr.h" -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** Get the buffer needed for object snapshot image. - * - * @param obj The object to generate snapshot. - * @param cf color format for generated image. - * - * @return the buffer size needed in bytes - */ -uint32_t lv_snapshot_buf_size_needed(lv_obj_t * obj, lv_img_cf_t cf) -{ - LV_ASSERT_NULL(obj); - switch(cf) { - case LV_IMG_CF_TRUE_COLOR: - case LV_IMG_CF_TRUE_COLOR_ALPHA: - case LV_IMG_CF_ALPHA_1BIT: - case LV_IMG_CF_ALPHA_2BIT: - case LV_IMG_CF_ALPHA_4BIT: - case LV_IMG_CF_ALPHA_8BIT: - break; - default: - return 0; - } - - lv_obj_update_layout(obj); - - /*Width and height determine snapshot image size.*/ - lv_coord_t w = lv_obj_get_width(obj); - lv_coord_t h = lv_obj_get_height(obj); - lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj); - w += ext_size * 2; - h += ext_size * 2; - - uint8_t px_size = lv_img_cf_get_px_size(cf); - return w * h * ((px_size + 7) >> 3); -} - -/** Take snapshot for object with its children, save image info to provided buffer. - * - * @param obj The object to generate snapshot. - * @param cf color format for generated image. - * @param dsc image descriptor to store the image result. - * @param buf the buffer to store image data. - * @param buff_size provided buffer size in bytes. - * - * @return LV_RES_OK on success, LV_RES_INV on error. - */ -lv_res_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_img_cf_t cf, lv_img_dsc_t * dsc, void * buf, uint32_t buff_size) -{ - LV_ASSERT_NULL(obj); - LV_ASSERT_NULL(dsc); - LV_ASSERT_NULL(buf); - - switch(cf) { - case LV_IMG_CF_TRUE_COLOR: - case LV_IMG_CF_TRUE_COLOR_ALPHA: - case LV_IMG_CF_ALPHA_1BIT: - case LV_IMG_CF_ALPHA_2BIT: - case LV_IMG_CF_ALPHA_4BIT: - case LV_IMG_CF_ALPHA_8BIT: - break; - default: - return LV_RES_INV; - } - - if(lv_snapshot_buf_size_needed(obj, cf) > buff_size) - return LV_RES_INV; - - /*Width and height determine snapshot image size.*/ - lv_coord_t w = lv_obj_get_width(obj); - lv_coord_t h = lv_obj_get_height(obj); - lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj); - w += ext_size * 2; - h += ext_size * 2; - - lv_area_t snapshot_area; - lv_obj_get_coords(obj, &snapshot_area); - lv_area_increase(&snapshot_area, ext_size, ext_size); - - lv_memset(buf, 0x00, buff_size); - lv_memset_00(dsc, sizeof(lv_img_dsc_t)); - - lv_disp_t * obj_disp = lv_obj_get_disp(obj); - lv_disp_drv_t driver; - lv_disp_drv_init(&driver); - /*In lack of a better idea use the resolution of the object's display*/ - driver.hor_res = lv_disp_get_hor_res(obj_disp); - driver.ver_res = lv_disp_get_hor_res(obj_disp); - lv_disp_drv_use_generic_set_px_cb(&driver, cf); - - lv_disp_t fake_disp; - lv_memset_00(&fake_disp, sizeof(lv_disp_t)); - fake_disp.driver = &driver; - - lv_draw_ctx_t * draw_ctx = lv_mem_alloc(obj_disp->driver->draw_ctx_size); - LV_ASSERT_MALLOC(draw_ctx); - if(draw_ctx == NULL) return LV_RES_INV; - obj_disp->driver->draw_ctx_init(fake_disp.driver, draw_ctx); - fake_disp.driver->draw_ctx = draw_ctx; - draw_ctx->clip_area = &snapshot_area; - draw_ctx->buf_area = &snapshot_area; - draw_ctx->buf = (void *)buf; - driver.draw_ctx = draw_ctx; - - lv_disp_t * refr_ori = _lv_refr_get_disp_refreshing(); - _lv_refr_set_disp_refreshing(&fake_disp); - - lv_obj_redraw(draw_ctx, obj); - - _lv_refr_set_disp_refreshing(refr_ori); - obj_disp->driver->draw_ctx_deinit(fake_disp.driver, draw_ctx); - lv_mem_free(draw_ctx); - - dsc->data = buf; - dsc->header.w = w; - dsc->header.h = h; - dsc->header.cf = cf; - return LV_RES_OK; -} - -/** Take snapshot for object with its children, alloc the memory needed. - * - * @param obj The object to generate snapshot. - * @param cf color format for generated image. - * - * @return a pointer to an image descriptor, or NULL if failed. - */ -lv_img_dsc_t * lv_snapshot_take(lv_obj_t * obj, lv_img_cf_t cf) -{ - LV_ASSERT_NULL(obj); - uint32_t buff_size = lv_snapshot_buf_size_needed(obj, cf); - - void * buf = lv_mem_alloc(buff_size); - LV_ASSERT_MALLOC(buf); - if(buf == NULL) { - return NULL; - } - - lv_img_dsc_t * dsc = lv_mem_alloc(sizeof(lv_img_dsc_t)); - LV_ASSERT_MALLOC(buf); - if(dsc == NULL) { - lv_mem_free(buf); - return NULL; - } - - if(lv_snapshot_take_to_buf(obj, cf, dsc, buf, buff_size) == LV_RES_INV) { - lv_mem_free(buf); - lv_mem_free(dsc); - return NULL; - } - - return dsc; -} - -/** Free the snapshot image returned by @ref lv_snapshot_take - * - * It will firstly free the data image takes, then the image descriptor. - * - * @param dsc The image descriptor generated by lv_snapshot_take. - * - */ -void lv_snapshot_free(lv_img_dsc_t * dsc) -{ - if(!dsc) - return; - - if(dsc->data) - lv_mem_free((void *)dsc->data); - - lv_mem_free(dsc); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -#endif /*LV_USE_SNAPSHOT*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.h b/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.h deleted file mode 100644 index 645192631..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/snapshot/lv_snapshot.h +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @file lv_snapshot.h - * - */ - -#ifndef LV_SNAPSHOT_H -#define LV_SNAPSHOT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include -#include - -#include "../../../lv_conf_internal.h" -#include "../../../core/lv_obj.h" - -/********************* - * DEFINES - *********************/ - -#if LV_USE_SNAPSHOT -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** Take snapshot for object with its children. - * - * @param obj The object to generate snapshot. - * @param cf color format for generated image. - * - * @return a pointer to an image descriptor, or NULL if failed. - */ -lv_img_dsc_t * lv_snapshot_take(lv_obj_t * obj, lv_img_cf_t cf); - -/** Free the snapshot image returned by @ref lv_snapshot_take - * - * It will firstly free the data image takes, then the image descriptor. - * - * @param dsc The image descriptor generated by lv_snapshot_take. - * - */ -void lv_snapshot_free(lv_img_dsc_t * dsc); - -/** Get the buffer needed for object snapshot image. - * - * @param obj The object to generate snapshot. - * @param cf color format for generated image. - * - * @return the buffer size needed in bytes - */ -uint32_t lv_snapshot_buf_size_needed(lv_obj_t * obj, lv_img_cf_t cf); - -/** Take snapshot for object with its children, save image info to provided buffer. - * - * @param obj The object to generate snapshot. - * @param cf color format for generated image. - * @param dsc image descriptor to store the image result. - * @param buff the buffer to store image data. - * @param buff_size provided buffer size in bytes. - * - * @return LV_RES_OK on success, LV_RES_INV on error. - */ -lv_res_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_img_cf_t cf, lv_img_dsc_t * dsc, void * buf, uint32_t buff_size); - - -/********************** - * MACROS - **********************/ -#endif /*LV_USE_SNAPSHOT*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.c b/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.c deleted file mode 100644 index d342455ff..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.c +++ /dev/null @@ -1,428 +0,0 @@ -/** - * @file lv_theme_basic.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../../../lvgl.h" /*To see all the widgets*/ - -#if LV_USE_THEME_BASIC - -#include "lv_theme_basic.h" -#include "../../../misc/lv_gc.h" - -/********************* - * DEFINES - *********************/ -#define COLOR_SCR lv_palette_lighten(LV_PALETTE_GREY, 4) -#define COLOR_WHITE lv_color_white() -#define COLOR_LIGHT lv_palette_lighten(LV_PALETTE_GREY, 2) -#define COLOR_DARK lv_palette_main(LV_PALETTE_GREY) -#define COLOR_DIM lv_palette_darken(LV_PALETTE_GREY, 2) -#define SCROLLBAR_WIDTH 2 - -/********************** - * TYPEDEFS - **********************/ -typedef struct { - lv_style_t scr; - lv_style_t transp; - lv_style_t white; - lv_style_t light; - lv_style_t dark; - lv_style_t dim; - lv_style_t scrollbar; -#if LV_USE_ARC || LV_USE_COLORWHEEL - lv_style_t arc_line; - lv_style_t arc_knob; -#endif -#if LV_USE_TEXTAREA - lv_style_t ta_cursor; -#endif -} my_theme_styles_t; - - -/********************** - * STATIC PROTOTYPES - **********************/ -static void style_init_reset(lv_style_t * style); -static void theme_apply(lv_theme_t * th, lv_obj_t * obj); - -/********************** - * STATIC VARIABLES - **********************/ -static my_theme_styles_t * styles; -static lv_theme_t theme; -static bool inited; - -/********************** - * MACROS - **********************/ - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void style_init(void) -{ - style_init_reset(&styles->scrollbar); - lv_style_set_bg_opa(&styles->scrollbar, LV_OPA_COVER); - lv_style_set_bg_color(&styles->scrollbar, COLOR_DARK); - lv_style_set_width(&styles->scrollbar, SCROLLBAR_WIDTH); - - style_init_reset(&styles->scr); - lv_style_set_bg_opa(&styles->scr, LV_OPA_COVER); - lv_style_set_bg_color(&styles->scr, COLOR_SCR); - lv_style_set_text_color(&styles->scr, COLOR_DIM); - - - style_init_reset(&styles->transp); - lv_style_set_bg_opa(&styles->transp, LV_OPA_TRANSP); - - style_init_reset(&styles->white); - lv_style_set_bg_opa(&styles->white, LV_OPA_COVER); - lv_style_set_bg_color(&styles->white, COLOR_WHITE); - lv_style_set_line_width(&styles->white, 1); - lv_style_set_line_color(&styles->white, COLOR_WHITE); - lv_style_set_arc_width(&styles->white, 2); - lv_style_set_arc_color(&styles->white, COLOR_WHITE); - - style_init_reset(&styles->light); - lv_style_set_bg_opa(&styles->light, LV_OPA_COVER); - lv_style_set_bg_color(&styles->light, COLOR_LIGHT); - lv_style_set_line_width(&styles->light, 1); - lv_style_set_line_color(&styles->light, COLOR_LIGHT); - lv_style_set_arc_width(&styles->light, 2); - lv_style_set_arc_color(&styles->light, COLOR_LIGHT); - - style_init_reset(&styles->dark); - lv_style_set_bg_opa(&styles->dark, LV_OPA_COVER); - lv_style_set_bg_color(&styles->dark, COLOR_DARK); - lv_style_set_line_width(&styles->dark, 1); - lv_style_set_line_color(&styles->dark, COLOR_DARK); - lv_style_set_arc_width(&styles->dark, 2); - lv_style_set_arc_color(&styles->dark, COLOR_DARK); - - style_init_reset(&styles->dim); - lv_style_set_bg_opa(&styles->dim, LV_OPA_COVER); - lv_style_set_bg_color(&styles->dim, COLOR_DIM); - lv_style_set_line_width(&styles->dim, 1); - lv_style_set_line_color(&styles->dim, COLOR_DIM); - lv_style_set_arc_width(&styles->dim, 2); - lv_style_set_arc_color(&styles->dim, COLOR_DIM); - -#if LV_USE_ARC || LV_USE_COLORWHEEL - style_init_reset(&styles->arc_line); - lv_style_set_arc_width(&styles->arc_line, 6); - style_init_reset(&styles->arc_knob); - lv_style_set_pad_all(&styles->arc_knob, 5); -#endif - -#if LV_USE_TEXTAREA - style_init_reset(&styles->ta_cursor); - lv_style_set_border_side(&styles->ta_cursor, LV_BORDER_SIDE_LEFT); - lv_style_set_border_color(&styles->ta_cursor, COLOR_DIM); - lv_style_set_border_width(&styles->ta_cursor, 2); - lv_style_set_bg_opa(&styles->ta_cursor, LV_OPA_TRANSP); - lv_style_set_anim_time(&styles->ta_cursor, 500); -#endif -} - - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -bool lv_theme_basic_is_inited(void) -{ - return LV_GC_ROOT(_lv_theme_basic_styles) == NULL ? false : true; -} - -lv_theme_t * lv_theme_basic_init(lv_disp_t * disp) -{ - - /*This trick is required only to avoid the garbage collection of - *styles' data if LVGL is used in a binding (e.g. Micropython) - *In a general case styles could be in simple `static lv_style_t my_style...` variables*/ - if(!lv_theme_basic_is_inited()) { - inited = false; - LV_GC_ROOT(_lv_theme_basic_styles) = lv_mem_alloc(sizeof(my_theme_styles_t)); - styles = (my_theme_styles_t *)LV_GC_ROOT(_lv_theme_basic_styles); - } - - theme.disp = disp; - theme.font_small = LV_FONT_DEFAULT; - theme.font_normal = LV_FONT_DEFAULT; - theme.font_large = LV_FONT_DEFAULT; - theme.apply_cb = theme_apply; - - style_init(); - - if(disp == NULL || lv_disp_get_theme(disp) == &theme) { - lv_obj_report_style_change(NULL); - } - - inited = true; - - return (lv_theme_t *)&theme; -} - - -static void theme_apply(lv_theme_t * th, lv_obj_t * obj) -{ - LV_UNUSED(th); - - if(lv_obj_get_parent(obj) == NULL) { - lv_obj_add_style(obj, &styles->scr, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - return; - } - - if(lv_obj_check_type(obj, &lv_obj_class)) { -#if LV_USE_TABVIEW - lv_obj_t * parent = lv_obj_get_parent(obj); - /*Tabview content area*/ - if(lv_obj_check_type(parent, &lv_tabview_class)) { - lv_obj_add_style(obj, &styles->scr, 0); - return; - } - /*Tabview pages*/ - else if(lv_obj_check_type(lv_obj_get_parent(parent), &lv_tabview_class)) { - lv_obj_add_style(obj, &styles->scr, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - return; - } -#endif - -#if LV_USE_WIN - /*Header*/ - if(lv_obj_get_index(obj) == 0 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { - lv_obj_add_style(obj, &styles->light, 0); - return; - } - /*Content*/ - else if(lv_obj_get_index(obj) == 1 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { - lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - return; - } -#endif - lv_obj_add_style(obj, &styles->white, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - } -#if LV_USE_BTN - else if(lv_obj_check_type(obj, &lv_btn_class)) { - lv_obj_add_style(obj, &styles->dark, 0); - } -#endif - -#if LV_USE_BTNMATRIX - else if(lv_obj_check_type(obj, &lv_btnmatrix_class)) { -#if LV_USE_MSGBOX - if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_msgbox_class)) { - lv_obj_add_style(obj, &styles->light, LV_PART_ITEMS); - return; - } -#endif -#if LV_USE_TABVIEW - if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_tabview_class)) { - lv_obj_add_style(obj, &styles->light, LV_PART_ITEMS); - return; - } -#endif - lv_obj_add_style(obj, &styles->white, 0); - lv_obj_add_style(obj, &styles->light, LV_PART_ITEMS); - } -#endif - -#if LV_USE_BAR - else if(lv_obj_check_type(obj, &lv_bar_class)) { - lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->dark, LV_PART_INDICATOR); - } -#endif - -#if LV_USE_SLIDER - else if(lv_obj_check_type(obj, &lv_slider_class)) { - lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->dark, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->dim, LV_PART_KNOB); - } -#endif - -#if LV_USE_TABLE - else if(lv_obj_check_type(obj, &lv_table_class)) { - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->light, LV_PART_ITEMS); - } -#endif - -#if LV_USE_CHECKBOX - else if(lv_obj_check_type(obj, &lv_checkbox_class)) { - lv_obj_add_style(obj, &styles->light, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->dark, LV_PART_INDICATOR | LV_STATE_CHECKED); - } -#endif - -#if LV_USE_SWITCH - else if(lv_obj_check_type(obj, &lv_switch_class)) { - lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->dim, LV_PART_KNOB); - } -#endif - -#if LV_USE_CHART - else if(lv_obj_check_type(obj, &lv_chart_class)) { - lv_obj_add_style(obj, &styles->white, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->light, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->dark, LV_PART_TICKS); - lv_obj_add_style(obj, &styles->dark, LV_PART_CURSOR); - } -#endif - -#if LV_USE_ROLLER - else if(lv_obj_check_type(obj, &lv_roller_class)) { - lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->dark, LV_PART_SELECTED); - } -#endif - -#if LV_USE_DROPDOWN - else if(lv_obj_check_type(obj, &lv_dropdown_class)) { - lv_obj_add_style(obj, &styles->white, 0); - } - else if(lv_obj_check_type(obj, &lv_dropdownlist_class)) { - lv_obj_add_style(obj, &styles->white, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->light, LV_PART_SELECTED); - lv_obj_add_style(obj, &styles->dark, LV_PART_SELECTED | LV_STATE_CHECKED); - } -#endif - -#if LV_USE_ARC - else if(lv_obj_check_type(obj, &lv_arc_class)) { - lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->transp, 0); - lv_obj_add_style(obj, &styles->arc_line, 0); - lv_obj_add_style(obj, &styles->dark, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->arc_line, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->dim, LV_PART_KNOB); - lv_obj_add_style(obj, &styles->arc_knob, LV_PART_KNOB); - } -#endif - -#if LV_USE_SPINNER - else if(lv_obj_check_type(obj, &lv_spinner_class)) { - lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->transp, 0); - lv_obj_add_style(obj, &styles->arc_line, 0); - lv_obj_add_style(obj, &styles->dark, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->arc_line, LV_PART_INDICATOR); - } -#endif - -#if LV_USE_COLORWHEEL - else if(lv_obj_check_type(obj, &lv_colorwheel_class)) { - lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->transp, 0); - lv_obj_add_style(obj, &styles->arc_line, 0); - lv_obj_add_style(obj, &styles->dim, LV_PART_KNOB); - lv_obj_add_style(obj, &styles->arc_knob, LV_PART_KNOB); - } -#endif - -#if LV_USE_METER - else if(lv_obj_check_type(obj, &lv_meter_class)) { - lv_obj_add_style(obj, &styles->light, 0); - } -#endif - -#if LV_USE_TEXTAREA - else if(lv_obj_check_type(obj, &lv_textarea_class)) { - lv_obj_add_style(obj, &styles->white, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->ta_cursor, LV_PART_CURSOR | LV_STATE_FOCUSED); - } -#endif - -#if LV_USE_CALENDAR - else if(lv_obj_check_type(obj, &lv_calendar_class)) { - lv_obj_add_style(obj, &styles->light, 0); - } -#endif - -#if LV_USE_KEYBOARD - else if(lv_obj_check_type(obj, &lv_keyboard_class)) { - lv_obj_add_style(obj, &styles->scr, 0); - lv_obj_add_style(obj, &styles->white, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->light, LV_PART_ITEMS | LV_STATE_CHECKED); - } -#endif -#if LV_USE_LIST - else if(lv_obj_check_type(obj, &lv_list_class)) { - lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - return; - } - else if(lv_obj_check_type(obj, &lv_list_text_class)) { - - } - else if(lv_obj_check_type(obj, &lv_list_btn_class)) { - lv_obj_add_style(obj, &styles->dark, 0); - - } -#endif -#if LV_USE_MSGBOX - else if(lv_obj_check_type(obj, &lv_msgbox_class)) { - lv_obj_add_style(obj, &styles->light, 0); - return; - } -#endif -#if LV_USE_SPINBOX - else if(lv_obj_check_type(obj, &lv_spinbox_class)) { - lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->dark, LV_PART_CURSOR); - } -#endif -#if LV_USE_TILEVIEW - else if(lv_obj_check_type(obj, &lv_tileview_class)) { - lv_obj_add_style(obj, &styles->scr, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - } - else if(lv_obj_check_type(obj, &lv_tileview_tile_class)) { - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - } -#endif - -#if LV_USE_COLORWHEEL - else if(lv_obj_check_type(obj, &lv_colorwheel_class)) { - lv_obj_add_style(obj, &styles->light, 0); - lv_obj_add_style(obj, &styles->light, LV_PART_KNOB); - } -#endif - -#if LV_USE_LED - else if(lv_obj_check_type(obj, &lv_led_class)) { - lv_obj_add_style(obj, &styles->light, 0); - } -#endif -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void style_init_reset(lv_style_t * style) -{ - if(inited) { - lv_style_reset(style); - } - else { - lv_style_init(style); - } -} - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.c b/lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.c deleted file mode 100644 index 47392b0d1..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.c +++ /dev/null @@ -1,1181 +0,0 @@ -/** - * @file lv_theme_default.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../../../lvgl.h" /*To see all the widgets*/ - -#if LV_USE_THEME_DEFAULT - -#include "lv_theme_default.h" -#include "../../../misc/lv_gc.h" - -/********************* - * DEFINES - *********************/ -#define MODE_DARK 1 -#define RADIUS_DEFAULT (disp_size == DISP_LARGE ? lv_disp_dpx(theme.disp, 12) : lv_disp_dpx(theme.disp, 8)) - -/*SCREEN*/ -#define LIGHT_COLOR_SCR lv_palette_lighten(LV_PALETTE_GREY, 4) -#define LIGHT_COLOR_CARD lv_color_white() -#define LIGHT_COLOR_TEXT lv_palette_darken(LV_PALETTE_GREY, 4) -#define LIGHT_COLOR_GREY lv_palette_lighten(LV_PALETTE_GREY, 2) -#define DARK_COLOR_SCR lv_color_hex(0x15171A) -#define DARK_COLOR_CARD lv_color_hex(0x282b30) -#define DARK_COLOR_TEXT lv_palette_lighten(LV_PALETTE_GREY, 5) -#define DARK_COLOR_GREY lv_color_hex(0x2f3237) - -#define TRANSITION_TIME LV_THEME_DEFAULT_TRANSITION_TIME -#define BORDER_WIDTH lv_disp_dpx(theme.disp, 2) -#define OUTLINE_WIDTH lv_disp_dpx(theme.disp, 3) - -#define PAD_DEF (disp_size == DISP_LARGE ? lv_disp_dpx(theme.disp, 24) : disp_size == DISP_MEDIUM ? lv_disp_dpx(theme.disp, 20) : lv_disp_dpx(theme.disp, 16)) -#define PAD_SMALL (disp_size == DISP_LARGE ? lv_disp_dpx(theme.disp, 14) : disp_size == DISP_MEDIUM ? lv_disp_dpx(theme.disp, 12) : lv_disp_dpx(theme.disp, 10)) -#define PAD_TINY (disp_size == DISP_LARGE ? lv_disp_dpx(theme.disp, 8) : disp_size == DISP_MEDIUM ? lv_disp_dpx(theme.disp, 6) : lv_disp_dpx(theme.disp, 2)) - -/********************** - * TYPEDEFS - **********************/ -typedef struct { - lv_style_t scr; - lv_style_t scrollbar; - lv_style_t scrollbar_scrolled; - lv_style_t card; - lv_style_t btn; - - /*Utility*/ - lv_style_t bg_color_primary; - lv_style_t bg_color_primary_muted; - lv_style_t bg_color_secondary; - lv_style_t bg_color_secondary_muted; - lv_style_t bg_color_grey; - lv_style_t bg_color_white; - lv_style_t pressed; - lv_style_t disabled; - lv_style_t pad_zero; - lv_style_t pad_tiny; - lv_style_t pad_small; - lv_style_t pad_normal; - lv_style_t pad_gap; - lv_style_t line_space_large; - lv_style_t text_align_center; - lv_style_t outline_primary; - lv_style_t outline_secondary; - lv_style_t circle; - lv_style_t no_radius; - lv_style_t clip_corner; -#if LV_THEME_DEFAULT_GROW - lv_style_t grow; -#endif - lv_style_t transition_delayed; - lv_style_t transition_normal; - lv_style_t anim; - lv_style_t anim_fast; - - /*Parts*/ - lv_style_t knob; - lv_style_t indic; - -#if LV_USE_ARC - lv_style_t arc_indic; - lv_style_t arc_indic_primary; -#endif - -#if LV_USE_CHART - lv_style_t chart_series, chart_indic, chart_ticks, chart_bg; -#endif - -#if LV_USE_DROPDOWN - lv_style_t dropdown_list; -#endif - -#if LV_USE_CHECKBOX - lv_style_t cb_marker, cb_marker_checked; -#endif - -#if LV_USE_SWITCH - lv_style_t switch_knob; -#endif - -#if LV_USE_LINE - lv_style_t line; -#endif - -#if LV_USE_TABLE - lv_style_t table_cell; -#endif - -#if LV_USE_METER - lv_style_t meter_marker, meter_indic; -#endif - -#if LV_USE_TEXTAREA - lv_style_t ta_cursor, ta_placeholder; -#endif - -#if LV_USE_CALENDAR - lv_style_t calendar_btnm_bg, calendar_btnm_day, calendar_header; -#endif - -#if LV_USE_COLORWHEEL - lv_style_t colorwheel_main; -#endif - -#if LV_USE_MENU - lv_style_t menu_bg, menu_cont, menu_sidebar_cont, menu_main_cont, menu_page, menu_header_cont, menu_header_btn, - menu_section, menu_pressed, menu_separator; -#endif - -#if LV_USE_MSGBOX - lv_style_t msgbox_bg, msgbox_btn_bg, msgbox_backdrop_bg; -#endif - -#if LV_USE_KEYBOARD - lv_style_t keyboard_btn_bg; -#endif - -#if LV_USE_LIST - lv_style_t list_bg, list_btn, list_item_grow, list_label; -#endif - -#if LV_USE_TABVIEW - lv_style_t tab_bg_focus, tab_btn; -#endif -#if LV_USE_LED - lv_style_t led; -#endif -} my_theme_styles_t; - -typedef struct { - lv_theme_t base; - uint8_t light : 1; -} my_theme_t; - -typedef enum { - DISP_SMALL = 3, - DISP_MEDIUM = 2, - DISP_LARGE = 1, -} disp_size_t; - -/********************** - * STATIC PROTOTYPES - **********************/ -static void theme_apply(lv_theme_t * th, lv_obj_t * obj); -static void style_init_reset(lv_style_t * style); - -/********************** - * STATIC VARIABLES - **********************/ -static my_theme_styles_t * styles; -static lv_theme_t theme; -static disp_size_t disp_size; -static lv_color_t color_scr; -static lv_color_t color_text; -static lv_color_t color_card; -static lv_color_t color_grey; -static bool inited = false; - - -/********************** - * MACROS - **********************/ - -/********************** - * STATIC FUNCTIONS - **********************/ - - -static lv_color_t dark_color_filter_cb(const lv_color_filter_dsc_t * f, lv_color_t c, lv_opa_t opa) -{ - LV_UNUSED(f); - return lv_color_darken(c, opa); -} - -static lv_color_t grey_filter_cb(const lv_color_filter_dsc_t * f, lv_color_t color, lv_opa_t opa) -{ - LV_UNUSED(f); - if(theme.flags & MODE_DARK) return lv_color_mix(lv_palette_darken(LV_PALETTE_GREY, 2), color, opa); - else return lv_color_mix(lv_palette_lighten(LV_PALETTE_GREY, 2), color, opa); -} - -static void style_init(void) -{ - static const lv_style_prop_t trans_props[] = { - LV_STYLE_BG_OPA, LV_STYLE_BG_COLOR, - LV_STYLE_TRANSFORM_WIDTH, LV_STYLE_TRANSFORM_HEIGHT, - LV_STYLE_TRANSLATE_Y, LV_STYLE_TRANSLATE_X, - LV_STYLE_TRANSFORM_ZOOM, LV_STYLE_TRANSFORM_ANGLE, - LV_STYLE_COLOR_FILTER_OPA, LV_STYLE_COLOR_FILTER_DSC, - 0 - }; - - color_scr = theme.flags & MODE_DARK ? DARK_COLOR_SCR : LIGHT_COLOR_SCR; - color_text = theme.flags & MODE_DARK ? DARK_COLOR_TEXT : LIGHT_COLOR_TEXT; - color_card = theme.flags & MODE_DARK ? DARK_COLOR_CARD : LIGHT_COLOR_CARD; - color_grey = theme.flags & MODE_DARK ? DARK_COLOR_GREY : LIGHT_COLOR_GREY; - - style_init_reset(&styles->transition_delayed); - style_init_reset(&styles->transition_normal); -#if TRANSITION_TIME - static lv_style_transition_dsc_t trans_delayed; - lv_style_transition_dsc_init(&trans_delayed, trans_props, lv_anim_path_linear, TRANSITION_TIME, 70, NULL); - - static lv_style_transition_dsc_t trans_normal; - lv_style_transition_dsc_init(&trans_normal, trans_props, lv_anim_path_linear, TRANSITION_TIME, 0, NULL); - - lv_style_set_transition(&styles->transition_delayed, &trans_delayed); /*Go back to default state with delay*/ - - lv_style_set_transition(&styles->transition_normal, &trans_normal); /*Go back to default state with delay*/ -#endif - - style_init_reset(&styles->scrollbar); - lv_color_t sb_color = (theme.flags & MODE_DARK) ? lv_palette_darken(LV_PALETTE_GREY, - 2) : lv_palette_main(LV_PALETTE_GREY); - lv_style_set_bg_color(&styles->scrollbar, sb_color); - - lv_style_set_radius(&styles->scrollbar, LV_RADIUS_CIRCLE); - lv_style_set_pad_all(&styles->scrollbar, lv_disp_dpx(theme.disp, 7)); - lv_style_set_width(&styles->scrollbar, lv_disp_dpx(theme.disp, 5)); - lv_style_set_bg_opa(&styles->scrollbar, LV_OPA_40); -#if TRANSITION_TIME - lv_style_set_transition(&styles->scrollbar, &trans_normal); -#endif - - style_init_reset(&styles->scrollbar_scrolled); - lv_style_set_bg_opa(&styles->scrollbar_scrolled, LV_OPA_COVER); - - style_init_reset(&styles->scr); - lv_style_set_bg_opa(&styles->scr, LV_OPA_COVER); - lv_style_set_bg_color(&styles->scr, color_scr); - lv_style_set_text_color(&styles->scr, color_text); - lv_style_set_pad_row(&styles->scr, PAD_SMALL); - lv_style_set_pad_column(&styles->scr, PAD_SMALL); - - style_init_reset(&styles->card); - lv_style_set_radius(&styles->card, RADIUS_DEFAULT); - lv_style_set_bg_opa(&styles->card, LV_OPA_COVER); - lv_style_set_bg_color(&styles->card, color_card); - lv_style_set_border_color(&styles->card, color_grey); - lv_style_set_border_width(&styles->card, BORDER_WIDTH); - lv_style_set_border_post(&styles->card, true); - lv_style_set_text_color(&styles->card, color_text); - lv_style_set_pad_all(&styles->card, PAD_DEF); - lv_style_set_pad_row(&styles->card, PAD_SMALL); - lv_style_set_pad_column(&styles->card, PAD_SMALL); - lv_style_set_line_color(&styles->card, lv_palette_main(LV_PALETTE_GREY)); - lv_style_set_line_width(&styles->card, lv_disp_dpx(theme.disp, 1)); - - style_init_reset(&styles->outline_primary); - lv_style_set_outline_color(&styles->outline_primary, theme.color_primary); - lv_style_set_outline_width(&styles->outline_primary, OUTLINE_WIDTH); - lv_style_set_outline_pad(&styles->outline_primary, OUTLINE_WIDTH); - lv_style_set_outline_opa(&styles->outline_primary, LV_OPA_50); - - style_init_reset(&styles->outline_secondary); - lv_style_set_outline_color(&styles->outline_secondary, theme.color_secondary); - lv_style_set_outline_width(&styles->outline_secondary, OUTLINE_WIDTH); - lv_style_set_outline_opa(&styles->outline_secondary, LV_OPA_50); - - style_init_reset(&styles->btn); - lv_style_set_radius(&styles->btn, (disp_size == DISP_LARGE ? lv_disp_dpx(theme.disp, - 16) : disp_size == DISP_MEDIUM ? lv_disp_dpx(theme.disp, 12) : lv_disp_dpx(theme.disp, 8))); - lv_style_set_bg_opa(&styles->btn, LV_OPA_COVER); - lv_style_set_bg_color(&styles->btn, color_grey); - if(!(theme.flags & MODE_DARK)) { - lv_style_set_shadow_color(&styles->btn, lv_palette_main(LV_PALETTE_GREY)); - lv_style_set_shadow_width(&styles->btn, LV_DPX(3)); - lv_style_set_shadow_opa(&styles->btn, LV_OPA_50); - lv_style_set_shadow_ofs_y(&styles->btn, lv_disp_dpx(theme.disp, LV_DPX(4))); - } - lv_style_set_text_color(&styles->btn, color_text); - lv_style_set_pad_hor(&styles->btn, PAD_DEF); - lv_style_set_pad_ver(&styles->btn, PAD_SMALL); - lv_style_set_pad_column(&styles->btn, lv_disp_dpx(theme.disp, 5)); - lv_style_set_pad_row(&styles->btn, lv_disp_dpx(theme.disp, 5)); - - static lv_color_filter_dsc_t dark_filter; - lv_color_filter_dsc_init(&dark_filter, dark_color_filter_cb); - - static lv_color_filter_dsc_t grey_filter; - lv_color_filter_dsc_init(&grey_filter, grey_filter_cb); - - style_init_reset(&styles->pressed); - lv_style_set_color_filter_dsc(&styles->pressed, &dark_filter); - lv_style_set_color_filter_opa(&styles->pressed, 35); - - style_init_reset(&styles->disabled); - lv_style_set_color_filter_dsc(&styles->disabled, &grey_filter); - lv_style_set_color_filter_opa(&styles->disabled, LV_OPA_50); - - style_init_reset(&styles->clip_corner); - lv_style_set_clip_corner(&styles->clip_corner, true); - lv_style_set_border_post(&styles->clip_corner, true); - - style_init_reset(&styles->pad_normal); - lv_style_set_pad_all(&styles->pad_normal, PAD_DEF); - lv_style_set_pad_row(&styles->pad_normal, PAD_DEF); - lv_style_set_pad_column(&styles->pad_normal, PAD_DEF); - - style_init_reset(&styles->pad_small); - lv_style_set_pad_all(&styles->pad_small, PAD_SMALL); - lv_style_set_pad_gap(&styles->pad_small, PAD_SMALL); - - style_init_reset(&styles->pad_gap); - lv_style_set_pad_row(&styles->pad_gap, lv_disp_dpx(theme.disp, 10)); - lv_style_set_pad_column(&styles->pad_gap, lv_disp_dpx(theme.disp, 10)); - - style_init_reset(&styles->line_space_large); - lv_style_set_text_line_space(&styles->line_space_large, lv_disp_dpx(theme.disp, 20)); - - style_init_reset(&styles->text_align_center); - lv_style_set_text_align(&styles->text_align_center, LV_TEXT_ALIGN_CENTER); - - style_init_reset(&styles->pad_zero); - lv_style_set_pad_all(&styles->pad_zero, 0); - lv_style_set_pad_row(&styles->pad_zero, 0); - lv_style_set_pad_column(&styles->pad_zero, 0); - - style_init_reset(&styles->pad_tiny); - lv_style_set_pad_all(&styles->pad_tiny, PAD_TINY); - lv_style_set_pad_row(&styles->pad_tiny, PAD_TINY); - lv_style_set_pad_column(&styles->pad_tiny, PAD_TINY); - - style_init_reset(&styles->bg_color_primary); - lv_style_set_bg_color(&styles->bg_color_primary, theme.color_primary); - lv_style_set_text_color(&styles->bg_color_primary, lv_color_white()); - lv_style_set_bg_opa(&styles->bg_color_primary, LV_OPA_COVER); - - style_init_reset(&styles->bg_color_primary_muted); - lv_style_set_bg_color(&styles->bg_color_primary_muted, theme.color_primary); - lv_style_set_text_color(&styles->bg_color_primary_muted, theme.color_primary); - lv_style_set_bg_opa(&styles->bg_color_primary_muted, LV_OPA_20); - - style_init_reset(&styles->bg_color_secondary); - lv_style_set_bg_color(&styles->bg_color_secondary, theme.color_secondary); - lv_style_set_text_color(&styles->bg_color_secondary, lv_color_white()); - lv_style_set_bg_opa(&styles->bg_color_secondary, LV_OPA_COVER); - - style_init_reset(&styles->bg_color_secondary_muted); - lv_style_set_bg_color(&styles->bg_color_secondary_muted, theme.color_secondary); - lv_style_set_text_color(&styles->bg_color_secondary_muted, theme.color_secondary); - lv_style_set_bg_opa(&styles->bg_color_secondary_muted, LV_OPA_20); - - style_init_reset(&styles->bg_color_grey); - lv_style_set_bg_color(&styles->bg_color_grey, color_grey); - lv_style_set_bg_opa(&styles->bg_color_grey, LV_OPA_COVER); - lv_style_set_text_color(&styles->bg_color_grey, color_text); - - style_init_reset(&styles->bg_color_white); - lv_style_set_bg_color(&styles->bg_color_white, color_card); - lv_style_set_bg_opa(&styles->bg_color_white, LV_OPA_COVER); - lv_style_set_text_color(&styles->bg_color_white, color_text); - - style_init_reset(&styles->circle); - lv_style_set_radius(&styles->circle, LV_RADIUS_CIRCLE); - - style_init_reset(&styles->no_radius); - lv_style_set_radius(&styles->no_radius, 0); - -#if LV_THEME_DEFAULT_GROW - style_init_reset(&styles->grow); - lv_style_set_transform_width(&styles->grow, lv_disp_dpx(theme.disp, 3)); - lv_style_set_transform_height(&styles->grow, lv_disp_dpx(theme.disp, 3)); -#endif - - style_init_reset(&styles->knob); - lv_style_set_bg_color(&styles->knob, theme.color_primary); - lv_style_set_bg_opa(&styles->knob, LV_OPA_COVER); - lv_style_set_pad_all(&styles->knob, lv_disp_dpx(theme.disp, 6)); - lv_style_set_radius(&styles->knob, LV_RADIUS_CIRCLE); - - style_init_reset(&styles->anim); - lv_style_set_anim_time(&styles->anim, 200); - - style_init_reset(&styles->anim_fast); - lv_style_set_anim_time(&styles->anim_fast, 120); - -#if LV_USE_ARC - style_init_reset(&styles->arc_indic); - lv_style_set_arc_color(&styles->arc_indic, color_grey); - lv_style_set_arc_width(&styles->arc_indic, lv_disp_dpx(theme.disp, 15)); - lv_style_set_arc_rounded(&styles->arc_indic, true); - - style_init_reset(&styles->arc_indic_primary); - lv_style_set_arc_color(&styles->arc_indic_primary, theme.color_primary); -#endif - -#if LV_USE_DROPDOWN - style_init_reset(&styles->dropdown_list); - lv_style_set_max_height(&styles->dropdown_list, LV_DPI_DEF * 2); -#endif -#if LV_USE_CHECKBOX - style_init_reset(&styles->cb_marker); - lv_style_set_pad_all(&styles->cb_marker, lv_disp_dpx(theme.disp, 3)); - lv_style_set_border_width(&styles->cb_marker, BORDER_WIDTH); - lv_style_set_border_color(&styles->cb_marker, theme.color_primary); - lv_style_set_bg_color(&styles->cb_marker, color_card); - lv_style_set_bg_opa(&styles->cb_marker, LV_OPA_COVER); - lv_style_set_radius(&styles->cb_marker, RADIUS_DEFAULT / 2); - - style_init_reset(&styles->cb_marker_checked); - lv_style_set_bg_img_src(&styles->cb_marker_checked, LV_SYMBOL_OK); - lv_style_set_text_color(&styles->cb_marker_checked, lv_color_white()); - lv_style_set_text_font(&styles->cb_marker_checked, theme.font_small); -#endif - -#if LV_USE_SWITCH - style_init_reset(&styles->switch_knob); - lv_style_set_pad_all(&styles->switch_knob, - lv_disp_dpx(theme.disp, 4)); - lv_style_set_bg_color(&styles->switch_knob, lv_color_white()); -#endif - -#if LV_USE_LINE - style_init_reset(&styles->line); - lv_style_set_line_width(&styles->line, 1); - lv_style_set_line_color(&styles->line, color_text); -#endif - -#if LV_USE_CHART - style_init_reset(&styles->chart_bg); - lv_style_set_border_post(&styles->chart_bg, false); - lv_style_set_pad_column(&styles->chart_bg, lv_disp_dpx(theme.disp, 10)); - lv_style_set_line_color(&styles->chart_bg, color_grey); - - style_init_reset(&styles->chart_series); - lv_style_set_line_width(&styles->chart_series, lv_disp_dpx(theme.disp, 3)); - lv_style_set_radius(&styles->chart_series, lv_disp_dpx(theme.disp, 3)); - lv_style_set_size(&styles->chart_series, lv_disp_dpx(theme.disp, 8)); - lv_style_set_pad_column(&styles->chart_series, lv_disp_dpx(theme.disp, 2)); - - style_init_reset(&styles->chart_indic); - lv_style_set_radius(&styles->chart_indic, LV_RADIUS_CIRCLE); - lv_style_set_size(&styles->chart_indic, lv_disp_dpx(theme.disp, 8)); - lv_style_set_bg_color(&styles->chart_indic, theme.color_primary); - lv_style_set_bg_opa(&styles->chart_indic, LV_OPA_COVER); - - style_init_reset(&styles->chart_ticks); - lv_style_set_line_width(&styles->chart_ticks, lv_disp_dpx(theme.disp, 1)); - lv_style_set_line_color(&styles->chart_ticks, color_text); - lv_style_set_pad_all(&styles->chart_ticks, lv_disp_dpx(theme.disp, 2)); - lv_style_set_text_color(&styles->chart_ticks, lv_palette_main(LV_PALETTE_GREY)); -#endif - -#if LV_USE_MENU - style_init_reset(&styles->menu_bg); - lv_style_set_pad_all(&styles->menu_bg, 0); - lv_style_set_pad_gap(&styles->menu_bg, 0); - lv_style_set_radius(&styles->menu_bg, 0); - lv_style_set_clip_corner(&styles->menu_bg, true); - lv_style_set_border_side(&styles->menu_bg, LV_BORDER_SIDE_NONE); - - style_init_reset(&styles->menu_section); - lv_style_set_radius(&styles->menu_section, RADIUS_DEFAULT); - lv_style_set_clip_corner(&styles->menu_section, true); - lv_style_set_bg_opa(&styles->menu_section, LV_OPA_COVER); - lv_style_set_bg_color(&styles->menu_section, color_card); - lv_style_set_text_color(&styles->menu_section, color_text); - - style_init_reset(&styles->menu_cont); - lv_style_set_pad_hor(&styles->menu_cont, PAD_SMALL); - lv_style_set_pad_ver(&styles->menu_cont, PAD_SMALL); - lv_style_set_pad_gap(&styles->menu_cont, PAD_SMALL); - lv_style_set_border_width(&styles->menu_cont, lv_disp_dpx(theme.disp, 1)); - lv_style_set_border_opa(&styles->menu_cont, LV_OPA_10); - lv_style_set_border_color(&styles->menu_cont, color_text); - lv_style_set_border_side(&styles->menu_cont, LV_BORDER_SIDE_NONE); - - style_init_reset(&styles->menu_sidebar_cont); - lv_style_set_pad_all(&styles->menu_sidebar_cont, 0); - lv_style_set_pad_gap(&styles->menu_sidebar_cont, 0); - lv_style_set_border_width(&styles->menu_sidebar_cont, lv_disp_dpx(theme.disp, 1)); - lv_style_set_border_opa(&styles->menu_sidebar_cont, LV_OPA_10); - lv_style_set_border_color(&styles->menu_sidebar_cont, color_text); - lv_style_set_border_side(&styles->menu_sidebar_cont, LV_BORDER_SIDE_RIGHT); - - style_init_reset(&styles->menu_main_cont); - lv_style_set_pad_all(&styles->menu_main_cont, 0); - lv_style_set_pad_gap(&styles->menu_main_cont, 0); - - style_init_reset(&styles->menu_header_cont); - lv_style_set_pad_hor(&styles->menu_header_cont, PAD_SMALL); - lv_style_set_pad_ver(&styles->menu_header_cont, PAD_TINY); - lv_style_set_pad_gap(&styles->menu_header_cont, PAD_SMALL); - - style_init_reset(&styles->menu_header_btn); - lv_style_set_pad_hor(&styles->menu_header_btn, PAD_TINY); - lv_style_set_pad_ver(&styles->menu_header_btn, PAD_TINY); - lv_style_set_shadow_opa(&styles->menu_header_btn, LV_OPA_TRANSP); - lv_style_set_bg_opa(&styles->menu_header_btn, LV_OPA_TRANSP); - lv_style_set_text_color(&styles->menu_header_btn, color_text); - - style_init_reset(&styles->menu_page); - lv_style_set_pad_hor(&styles->menu_page, 0); - lv_style_set_pad_gap(&styles->menu_page, 0); - - style_init_reset(&styles->menu_pressed); - lv_style_set_bg_opa(&styles->menu_pressed, LV_OPA_20); - lv_style_set_bg_color(&styles->menu_pressed, lv_palette_main(LV_PALETTE_GREY)); - - style_init_reset(&styles->menu_separator); - lv_style_set_bg_opa(&styles->menu_separator, LV_OPA_TRANSP); - lv_style_set_pad_ver(&styles->menu_separator, PAD_TINY); -#endif - -#if LV_USE_METER - style_init_reset(&styles->meter_marker); - lv_style_set_line_width(&styles->meter_marker, lv_disp_dpx(theme.disp, 5)); - lv_style_set_line_color(&styles->meter_marker, color_text); - lv_style_set_size(&styles->meter_marker, lv_disp_dpx(theme.disp, 20)); - lv_style_set_pad_left(&styles->meter_marker, lv_disp_dpx(theme.disp, 15)); - - style_init_reset(&styles->meter_indic); - lv_style_set_radius(&styles->meter_indic, LV_RADIUS_CIRCLE); - lv_style_set_bg_color(&styles->meter_indic, color_text); - lv_style_set_bg_opa(&styles->meter_indic, LV_OPA_COVER); - lv_style_set_size(&styles->meter_indic, lv_disp_dpx(theme.disp, 15)); -#endif - -#if LV_USE_TABLE - style_init_reset(&styles->table_cell); - lv_style_set_border_width(&styles->table_cell, lv_disp_dpx(theme.disp, 1)); - lv_style_set_border_color(&styles->table_cell, color_grey); - lv_style_set_border_side(&styles->table_cell, LV_BORDER_SIDE_TOP | LV_BORDER_SIDE_BOTTOM); -#endif - -#if LV_USE_TEXTAREA - style_init_reset(&styles->ta_cursor); - lv_style_set_border_color(&styles->ta_cursor, color_text); - lv_style_set_border_width(&styles->ta_cursor, lv_disp_dpx(theme.disp, 2)); - lv_style_set_pad_left(&styles->ta_cursor, - lv_disp_dpx(theme.disp, 1)); - lv_style_set_border_side(&styles->ta_cursor, LV_BORDER_SIDE_LEFT); - lv_style_set_anim_time(&styles->ta_cursor, 400); - - style_init_reset(&styles->ta_placeholder); - lv_style_set_text_color(&styles->ta_placeholder, (theme.flags & MODE_DARK) ? lv_palette_darken(LV_PALETTE_GREY, - 2) : lv_palette_lighten(LV_PALETTE_GREY, 1)); -#endif - -#if LV_USE_CALENDAR - style_init_reset(&styles->calendar_btnm_bg); - lv_style_set_pad_all(&styles->calendar_btnm_bg, PAD_SMALL); - lv_style_set_pad_gap(&styles->calendar_btnm_bg, PAD_SMALL / 2); - - style_init_reset(&styles->calendar_btnm_day); - lv_style_set_border_width(&styles->calendar_btnm_day, lv_disp_dpx(theme.disp, 1)); - lv_style_set_border_color(&styles->calendar_btnm_day, color_grey); - lv_style_set_bg_color(&styles->calendar_btnm_day, color_card); - lv_style_set_bg_opa(&styles->calendar_btnm_day, LV_OPA_20); - - style_init_reset(&styles->calendar_header); - lv_style_set_pad_hor(&styles->calendar_header, PAD_SMALL); - lv_style_set_pad_top(&styles->calendar_header, PAD_SMALL); - lv_style_set_pad_bottom(&styles->calendar_header, PAD_TINY); - lv_style_set_pad_gap(&styles->calendar_header, PAD_SMALL); -#endif - -#if LV_USE_COLORWHEEL - style_init_reset(&styles->colorwheel_main); - lv_style_set_arc_width(&styles->colorwheel_main, lv_disp_dpx(theme.disp, 10)); -#endif - -#if LV_USE_MSGBOX - /*To add space for for the button shadow*/ - style_init_reset(&styles->msgbox_btn_bg); - lv_style_set_pad_all(&styles->msgbox_btn_bg, lv_disp_dpx(theme.disp, 4)); - - style_init_reset(&styles->msgbox_bg); - lv_style_set_max_width(&styles->msgbox_bg, lv_pct(100)); - - style_init_reset(&styles->msgbox_backdrop_bg); - lv_style_set_bg_color(&styles->msgbox_backdrop_bg, lv_palette_main(LV_PALETTE_GREY)); - lv_style_set_bg_opa(&styles->msgbox_backdrop_bg, LV_OPA_50); -#endif -#if LV_USE_KEYBOARD - style_init_reset(&styles->keyboard_btn_bg); - lv_style_set_shadow_width(&styles->keyboard_btn_bg, 0); - lv_style_set_radius(&styles->keyboard_btn_bg, disp_size == DISP_SMALL ? RADIUS_DEFAULT / 2 : RADIUS_DEFAULT); -#endif - -#if LV_USE_TABVIEW - style_init_reset(&styles->tab_btn); - lv_style_set_border_color(&styles->tab_btn, theme.color_primary); - lv_style_set_border_width(&styles->tab_btn, BORDER_WIDTH * 2); - lv_style_set_border_side(&styles->tab_btn, LV_BORDER_SIDE_BOTTOM); - - style_init_reset(&styles->tab_bg_focus); - lv_style_set_outline_pad(&styles->tab_bg_focus, -BORDER_WIDTH); -#endif - -#if LV_USE_LIST - style_init_reset(&styles->list_bg); - lv_style_set_pad_hor(&styles->list_bg, PAD_DEF); - lv_style_set_pad_ver(&styles->list_bg, 0); - lv_style_set_pad_gap(&styles->list_bg, 0); - lv_style_set_clip_corner(&styles->list_bg, true); - - style_init_reset(&styles->list_btn); - lv_style_set_border_width(&styles->list_btn, lv_disp_dpx(theme.disp, 1)); - lv_style_set_border_color(&styles->list_btn, color_grey); - lv_style_set_border_side(&styles->list_btn, LV_BORDER_SIDE_BOTTOM); - lv_style_set_pad_all(&styles->list_btn, PAD_SMALL); - lv_style_set_pad_column(&styles->list_btn, PAD_SMALL); - - style_init_reset(&styles->list_item_grow); - lv_style_set_transform_width(&styles->list_item_grow, PAD_DEF); -#endif - - -#if LV_USE_LED - style_init_reset(&styles->led); - lv_style_set_bg_opa(&styles->led, LV_OPA_COVER); - lv_style_set_bg_color(&styles->led, lv_color_white()); - lv_style_set_bg_grad_color(&styles->led, lv_palette_main(LV_PALETTE_GREY)); - lv_style_set_radius(&styles->led, LV_RADIUS_CIRCLE); - lv_style_set_shadow_width(&styles->led, lv_disp_dpx(theme.disp, 15)); - lv_style_set_shadow_color(&styles->led, lv_color_white()); - lv_style_set_shadow_spread(&styles->led, lv_disp_dpx(theme.disp, 5)); -#endif -} - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, - const lv_font_t * font) -{ - - /*This trick is required only to avoid the garbage collection of - *styles' data if LVGL is used in a binding (e.g. Micropython) - *In a general case styles could be in simple `static lv_style_t my_style...` variables*/ - if(!lv_theme_default_is_inited()) { - inited = false; - LV_GC_ROOT(_lv_theme_default_styles) = lv_mem_alloc(sizeof(my_theme_styles_t)); - styles = (my_theme_styles_t *)LV_GC_ROOT(_lv_theme_default_styles); - } - - if(LV_HOR_RES <= 320) disp_size = DISP_SMALL; - else if(LV_HOR_RES < 720) disp_size = DISP_MEDIUM; - else disp_size = DISP_LARGE; - - theme.disp = disp; - theme.color_primary = color_primary; - theme.color_secondary = color_secondary; - theme.font_small = font; - theme.font_normal = font; - theme.font_large = font; - theme.apply_cb = theme_apply; - theme.flags = dark ? MODE_DARK : 0; - - style_init(); - - if(disp == NULL || lv_disp_get_theme(disp) == &theme) lv_obj_report_style_change(NULL); - - inited = true; - - return (lv_theme_t *)&theme; -} - -lv_theme_t * lv_theme_default_get(void) -{ - if(!lv_theme_default_is_inited()) { - return NULL; - } - - return (lv_theme_t *)&theme; -} - -bool lv_theme_default_is_inited(void) -{ - return LV_GC_ROOT(_lv_theme_default_styles) == NULL ? false : true; -} - - -static void theme_apply(lv_theme_t * th, lv_obj_t * obj) -{ - LV_UNUSED(th); - - if(lv_obj_get_parent(obj) == NULL) { - lv_obj_add_style(obj, &styles->scr, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); - return; - } - - if(lv_obj_check_type(obj, &lv_obj_class)) { -#if LV_USE_TABVIEW - lv_obj_t * parent = lv_obj_get_parent(obj); - /*Tabview content area*/ - if(lv_obj_check_type(parent, &lv_tabview_class)) { - return; - } - /*Tabview pages*/ - else if(lv_obj_check_type(lv_obj_get_parent(parent), &lv_tabview_class)) { - lv_obj_add_style(obj, &styles->pad_normal, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); - return; - } -#endif - -#if LV_USE_WIN - /*Header*/ - if(lv_obj_get_index(obj) == 0 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { - lv_obj_add_style(obj, &styles->bg_color_grey, 0); - lv_obj_add_style(obj, &styles->pad_tiny, 0); - return; - } - /*Content*/ - else if(lv_obj_get_index(obj) == 1 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { - lv_obj_add_style(obj, &styles->scr, 0); - lv_obj_add_style(obj, &styles->pad_normal, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); - return; - } -#endif - - -#if LV_USE_CALENDAR - if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_calendar_class)) { - /*No style*/ - return; - } -#endif - - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); - } -#if LV_USE_BTN - else if(lv_obj_check_type(obj, &lv_btn_class)) { - lv_obj_add_style(obj, &styles->btn, 0); - lv_obj_add_style(obj, &styles->bg_color_primary, 0); - lv_obj_add_style(obj, &styles->transition_delayed, 0); - lv_obj_add_style(obj, &styles->pressed, LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->transition_normal, LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); -#if LV_THEME_DEFAULT_GROW - lv_obj_add_style(obj, &styles->grow, LV_STATE_PRESSED); -#endif - lv_obj_add_style(obj, &styles->bg_color_secondary, LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->disabled, LV_STATE_DISABLED); - -#if LV_USE_MENU - if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_menu_sidebar_header_cont_class) || - lv_obj_check_type(lv_obj_get_parent(obj), &lv_menu_main_header_cont_class)) { - lv_obj_add_style(obj, &styles->menu_header_btn, 0); - lv_obj_add_style(obj, &styles->menu_pressed, LV_STATE_PRESSED); - } -#endif - } -#endif - -#if LV_USE_LINE - else if(lv_obj_check_type(obj, &lv_line_class)) { - lv_obj_add_style(obj, &styles->line, 0); - } -#endif - -#if LV_USE_BTNMATRIX - else if(lv_obj_check_type(obj, &lv_btnmatrix_class)) { -#if LV_USE_MSGBOX - if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_msgbox_class)) { - lv_obj_add_style(obj, &styles->msgbox_btn_bg, 0); - lv_obj_add_style(obj, &styles->pad_gap, 0); - lv_obj_add_style(obj, &styles->btn, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->disabled, LV_PART_ITEMS | LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->bg_color_primary, LV_PART_ITEMS | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->bg_color_primary_muted, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->bg_color_secondary_muted, LV_PART_ITEMS | LV_STATE_EDITED); - return; - } -#endif -#if LV_USE_TABVIEW - if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_tabview_class)) { - lv_obj_add_style(obj, &styles->bg_color_white, 0); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->tab_bg_focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->bg_color_primary_muted, LV_PART_ITEMS | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->tab_btn, LV_PART_ITEMS | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->outline_primary, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_PART_ITEMS | LV_STATE_EDITED); - lv_obj_add_style(obj, &styles->tab_bg_focus, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - return; - } -#endif - -#if LV_USE_CALENDAR - if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_calendar_class)) { - lv_obj_add_style(obj, &styles->calendar_btnm_bg, 0); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); - lv_obj_add_style(obj, &styles->calendar_btnm_day, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->disabled, LV_PART_ITEMS | LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->outline_primary, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_PART_ITEMS | LV_STATE_EDITED); - return; - } -#endif - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); - lv_obj_add_style(obj, &styles->btn, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->disabled, LV_PART_ITEMS | LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->bg_color_primary, LV_PART_ITEMS | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->outline_primary, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_PART_ITEMS | LV_STATE_EDITED); - } -#endif - -#if LV_USE_BAR - else if(lv_obj_check_type(obj, &lv_bar_class)) { - lv_obj_add_style(obj, &styles->bg_color_primary_muted, 0); - lv_obj_add_style(obj, &styles->circle, 0); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); - lv_obj_add_style(obj, &styles->bg_color_primary, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->circle, LV_PART_INDICATOR); - } -#endif - -#if LV_USE_SLIDER - else if(lv_obj_check_type(obj, &lv_slider_class)) { - lv_obj_add_style(obj, &styles->bg_color_primary_muted, 0); - lv_obj_add_style(obj, &styles->circle, 0); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); - lv_obj_add_style(obj, &styles->bg_color_primary, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->circle, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->knob, LV_PART_KNOB); -#if LV_THEME_DEFAULT_GROW - lv_obj_add_style(obj, &styles->grow, LV_PART_KNOB | LV_STATE_PRESSED); -#endif - lv_obj_add_style(obj, &styles->transition_delayed, LV_PART_KNOB); - lv_obj_add_style(obj, &styles->transition_normal, LV_PART_KNOB | LV_STATE_PRESSED); - } -#endif - -#if LV_USE_TABLE - else if(lv_obj_check_type(obj, &lv_table_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->pad_zero, 0); - lv_obj_add_style(obj, &styles->no_radius, 0); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); - lv_obj_add_style(obj, &styles->bg_color_white, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->table_cell, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pad_normal, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->bg_color_primary, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->bg_color_secondary, LV_PART_ITEMS | LV_STATE_EDITED); - } -#endif - -#if LV_USE_CHECKBOX - else if(lv_obj_check_type(obj, &lv_checkbox_class)) { - lv_obj_add_style(obj, &styles->pad_gap, 0); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->disabled, LV_PART_INDICATOR | LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->cb_marker, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->bg_color_primary, LV_PART_INDICATOR | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->cb_marker_checked, LV_PART_INDICATOR | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->pressed, LV_PART_INDICATOR | LV_STATE_PRESSED); -#if LV_THEME_DEFAULT_GROW - lv_obj_add_style(obj, &styles->grow, LV_PART_INDICATOR | LV_STATE_PRESSED); -#endif - lv_obj_add_style(obj, &styles->transition_normal, LV_PART_INDICATOR | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->transition_delayed, LV_PART_INDICATOR); - } -#endif - -#if LV_USE_SWITCH - else if(lv_obj_check_type(obj, &lv_switch_class)) { - lv_obj_add_style(obj, &styles->bg_color_grey, 0); - lv_obj_add_style(obj, &styles->circle, 0); - lv_obj_add_style(obj, &styles->anim_fast, 0); - lv_obj_add_style(obj, &styles->disabled, LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->bg_color_primary, LV_PART_INDICATOR | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->circle, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->disabled, LV_PART_INDICATOR | LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->knob, LV_PART_KNOB); - lv_obj_add_style(obj, &styles->bg_color_white, LV_PART_KNOB); - lv_obj_add_style(obj, &styles->switch_knob, LV_PART_KNOB); - lv_obj_add_style(obj, &styles->disabled, LV_PART_KNOB | LV_STATE_DISABLED); - - lv_obj_add_style(obj, &styles->transition_normal, LV_PART_INDICATOR | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->transition_normal, LV_PART_INDICATOR); - } -#endif - -#if LV_USE_CHART - else if(lv_obj_check_type(obj, &lv_chart_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->pad_small, 0); - lv_obj_add_style(obj, &styles->chart_bg, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); - lv_obj_add_style(obj, &styles->chart_series, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->chart_indic, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->chart_ticks, LV_PART_TICKS); - lv_obj_add_style(obj, &styles->chart_series, LV_PART_CURSOR); - } -#endif - -#if LV_USE_ROLLER - else if(lv_obj_check_type(obj, &lv_roller_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->anim, 0); - lv_obj_add_style(obj, &styles->line_space_large, 0); - lv_obj_add_style(obj, &styles->text_align_center, 0); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); - lv_obj_add_style(obj, &styles->bg_color_primary, LV_PART_SELECTED); - } -#endif - -#if LV_USE_DROPDOWN - else if(lv_obj_check_type(obj, &lv_dropdown_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->pad_small, 0); - lv_obj_add_style(obj, &styles->transition_delayed, 0); - lv_obj_add_style(obj, &styles->transition_normal, LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->pressed, LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); - lv_obj_add_style(obj, &styles->transition_normal, LV_PART_INDICATOR); - } - else if(lv_obj_check_type(obj, &lv_dropdownlist_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->clip_corner, 0); - lv_obj_add_style(obj, &styles->line_space_large, 0); - lv_obj_add_style(obj, &styles->dropdown_list, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); - lv_obj_add_style(obj, &styles->bg_color_white, LV_PART_SELECTED); - lv_obj_add_style(obj, &styles->bg_color_primary, LV_PART_SELECTED | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->pressed, LV_PART_SELECTED | LV_STATE_PRESSED); - } -#endif - -#if LV_USE_ARC - else if(lv_obj_check_type(obj, &lv_arc_class)) { - lv_obj_add_style(obj, &styles->arc_indic, 0); - lv_obj_add_style(obj, &styles->arc_indic, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->arc_indic_primary, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->knob, LV_PART_KNOB); - } -#endif - - -#if LV_USE_SPINNER - else if(lv_obj_check_type(obj, &lv_spinner_class)) { - lv_obj_add_style(obj, &styles->arc_indic, 0); - lv_obj_add_style(obj, &styles->arc_indic, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->arc_indic_primary, LV_PART_INDICATOR); - } -#endif - -#if LV_USE_METER - else if(lv_obj_check_type(obj, &lv_meter_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->circle, 0); - lv_obj_add_style(obj, &styles->meter_indic, LV_PART_INDICATOR); - } -#endif - -#if LV_USE_TEXTAREA - else if(lv_obj_check_type(obj, &lv_textarea_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->pad_small, 0); - lv_obj_add_style(obj, &styles->disabled, LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); - lv_obj_add_style(obj, &styles->ta_cursor, LV_PART_CURSOR | LV_STATE_FOCUSED); - lv_obj_add_style(obj, &styles->ta_placeholder, LV_PART_TEXTAREA_PLACEHOLDER); - } -#endif - -#if LV_USE_CALENDAR - else if(lv_obj_check_type(obj, &lv_calendar_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->pad_zero, 0); - } -#endif - -#if LV_USE_CALENDAR_HEADER_ARROW - else if(lv_obj_check_type(obj, &lv_calendar_header_arrow_class)) { - lv_obj_add_style(obj, &styles->calendar_header, 0); - } -#endif - -#if LV_USE_CALENDAR_HEADER_DROPDOWN - else if(lv_obj_check_type(obj, &lv_calendar_header_dropdown_class)) { - lv_obj_add_style(obj, &styles->calendar_header, 0); - } -#endif - -#if LV_USE_KEYBOARD - else if(lv_obj_check_type(obj, &lv_keyboard_class)) { - lv_obj_add_style(obj, &styles->scr, 0); - lv_obj_add_style(obj, disp_size == DISP_LARGE ? &styles->pad_small : &styles->pad_tiny, 0); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); - lv_obj_add_style(obj, &styles->btn, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->disabled, LV_PART_ITEMS | LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->bg_color_white, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->keyboard_btn_bg, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->bg_color_grey, LV_PART_ITEMS | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->bg_color_primary_muted, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->bg_color_secondary_muted, LV_PART_ITEMS | LV_STATE_EDITED); - } -#endif -#if LV_USE_LIST - else if(lv_obj_check_type(obj, &lv_list_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->list_bg, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); - return; - } - else if(lv_obj_check_type(obj, &lv_list_text_class)) { - lv_obj_add_style(obj, &styles->bg_color_grey, 0); - lv_obj_add_style(obj, &styles->list_item_grow, 0); - } - else if(lv_obj_check_type(obj, &lv_list_btn_class)) { - lv_obj_add_style(obj, &styles->bg_color_white, 0); - lv_obj_add_style(obj, &styles->list_btn, 0); - lv_obj_add_style(obj, &styles->bg_color_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->list_item_grow, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->list_item_grow, LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->pressed, LV_STATE_PRESSED); - - } -#endif -#if LV_USE_MENU - else if(lv_obj_check_type(obj, &lv_menu_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->menu_bg, 0); - } - else if(lv_obj_check_type(obj, &lv_menu_sidebar_cont_class)) { - lv_obj_add_style(obj, &styles->menu_sidebar_cont, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); - } - else if(lv_obj_check_type(obj, &lv_menu_main_cont_class)) { - lv_obj_add_style(obj, &styles->menu_main_cont, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); - } - else if(lv_obj_check_type(obj, &lv_menu_cont_class)) { - lv_obj_add_style(obj, &styles->menu_cont, 0); - lv_obj_add_style(obj, &styles->menu_pressed, LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->bg_color_primary_muted, LV_STATE_PRESSED | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->bg_color_primary_muted, LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->bg_color_primary, LV_STATE_FOCUS_KEY); - } - else if(lv_obj_check_type(obj, &lv_menu_sidebar_header_cont_class) || - lv_obj_check_type(obj, &lv_menu_main_header_cont_class)) { - lv_obj_add_style(obj, &styles->menu_header_cont, 0); - } - else if(lv_obj_check_type(obj, &lv_menu_page_class)) { - lv_obj_add_style(obj, &styles->menu_page, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); - } - else if(lv_obj_check_type(obj, &lv_menu_section_class)) { - lv_obj_add_style(obj, &styles->menu_section, 0); - } - else if(lv_obj_check_type(obj, &lv_menu_separator_class)) { - lv_obj_add_style(obj, &styles->menu_separator, 0); - } -#endif -#if LV_USE_MSGBOX - else if(lv_obj_check_type(obj, &lv_msgbox_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->msgbox_bg, 0); - return; - } - else if(lv_obj_check_type(obj, &lv_msgbox_backdrop_class)) { - lv_obj_add_style(obj, &styles->msgbox_backdrop_bg, 0); - } -#endif -#if LV_USE_SPINBOX - else if(lv_obj_check_type(obj, &lv_spinbox_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->pad_small, 0); - lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->outline_secondary, LV_STATE_EDITED); - lv_obj_add_style(obj, &styles->bg_color_primary, LV_PART_CURSOR); - } -#endif -#if LV_USE_TILEVIEW - else if(lv_obj_check_type(obj, &lv_tileview_class)) { - lv_obj_add_style(obj, &styles->scr, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); - } - else if(lv_obj_check_type(obj, &lv_tileview_tile_class)) { - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); - } -#endif - -#if LV_USE_TABVIEW - else if(lv_obj_check_type(obj, &lv_tabview_class)) { - lv_obj_add_style(obj, &styles->scr, 0); - lv_obj_add_style(obj, &styles->pad_zero, 0); - } -#endif - -#if LV_USE_WIN - else if(lv_obj_check_type(obj, &lv_win_class)) { - lv_obj_add_style(obj, &styles->clip_corner, 0); - } -#endif - -#if LV_USE_COLORWHEEL - else if(lv_obj_check_type(obj, &lv_colorwheel_class)) { - lv_obj_add_style(obj, &styles->colorwheel_main, 0); - lv_obj_add_style(obj, &styles->pad_normal, 0); - lv_obj_add_style(obj, &styles->bg_color_white, LV_PART_KNOB); - lv_obj_add_style(obj, &styles->pad_normal, LV_PART_KNOB); - } -#endif - -#if LV_USE_LED - else if(lv_obj_check_type(obj, &lv_led_class)) { - lv_obj_add_style(obj, &styles->led, 0); - } -#endif -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void style_init_reset(lv_style_t * style) -{ - if(inited) { - lv_style_reset(style); - } - else { - lv_style_init(style); - } -} - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.c b/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.c deleted file mode 100644 index b249e76d5..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.c +++ /dev/null @@ -1,504 +0,0 @@ -/** - * @file lv_theme_mono.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../../../lvgl.h" - -#if LV_USE_THEME_MONO - -#include "lv_theme_mono.h" -#include "../../../misc/lv_gc.h" - -/********************* - * DEFINES - *********************/ - -#define COLOR_FG dark_bg ? lv_color_white() : lv_color_black() -#define COLOR_BG dark_bg ? lv_color_black() : lv_color_white() - -#define BORDER_W_NORMAL 1 -#define BORDER_W_PR 3 -#define BORDER_W_DIS 0 -#define BORDER_W_FOCUS 1 -#define BORDER_W_EDIT 2 -#define PAD_DEF 4 - -/********************** - * TYPEDEFS - **********************/ -typedef struct { - lv_style_t scr; - lv_style_t card; - lv_style_t scrollbar; - lv_style_t btn; - lv_style_t pr; - lv_style_t inv; - lv_style_t disabled; - lv_style_t focus; - lv_style_t edit; - lv_style_t pad_gap; - lv_style_t pad_zero; - lv_style_t no_radius; - lv_style_t radius_circle; - lv_style_t large_border; - lv_style_t large_line_space; - lv_style_t underline; -#if LV_USE_TEXTAREA - lv_style_t ta_cursor; -#endif -} my_theme_styles_t; - - -/********************** - * STATIC PROTOTYPES - **********************/ -static void style_init_reset(lv_style_t * style); -static void theme_apply(lv_theme_t * th, lv_obj_t * obj); - -/********************** - * STATIC VARIABLES - **********************/ -static my_theme_styles_t * styles; -static lv_theme_t theme; -static bool inited; - -/********************** - * MACROS - **********************/ - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void style_init(bool dark_bg, const lv_font_t * font) -{ - style_init_reset(&styles->scrollbar); - lv_style_set_bg_opa(&styles->scrollbar, LV_OPA_COVER); - lv_style_set_bg_color(&styles->scrollbar, COLOR_FG); - lv_style_set_width(&styles->scrollbar, PAD_DEF); - - style_init_reset(&styles->scr); - lv_style_set_bg_opa(&styles->scr, LV_OPA_COVER); - lv_style_set_bg_color(&styles->scr, COLOR_BG); - lv_style_set_text_color(&styles->scr, COLOR_FG); - lv_style_set_pad_row(&styles->scr, PAD_DEF); - lv_style_set_pad_column(&styles->scr, PAD_DEF); - lv_style_set_text_font(&styles->scr, font); - - style_init_reset(&styles->card); - lv_style_set_bg_opa(&styles->card, LV_OPA_COVER); - lv_style_set_bg_color(&styles->card, COLOR_BG); - lv_style_set_border_color(&styles->card, COLOR_FG); - lv_style_set_radius(&styles->card, 2); - lv_style_set_border_width(&styles->card, BORDER_W_NORMAL); - lv_style_set_pad_all(&styles->card, PAD_DEF); - lv_style_set_pad_gap(&styles->card, PAD_DEF); - lv_style_set_text_color(&styles->card, COLOR_FG); - lv_style_set_line_width(&styles->card, 2); - lv_style_set_line_color(&styles->card, COLOR_FG); - lv_style_set_arc_width(&styles->card, 2); - lv_style_set_arc_color(&styles->card, COLOR_FG); - lv_style_set_outline_color(&styles->card, COLOR_FG); - lv_style_set_anim_time(&styles->card, 300); - - style_init_reset(&styles->pr); - lv_style_set_border_width(&styles->pr, BORDER_W_PR); - - style_init_reset(&styles->inv); - lv_style_set_bg_opa(&styles->inv, LV_OPA_COVER); - lv_style_set_bg_color(&styles->inv, COLOR_FG); - lv_style_set_border_color(&styles->inv, COLOR_BG); - lv_style_set_line_color(&styles->inv, COLOR_BG); - lv_style_set_arc_color(&styles->inv, COLOR_BG); - lv_style_set_text_color(&styles->inv, COLOR_BG); - lv_style_set_outline_color(&styles->inv, COLOR_BG); - - style_init_reset(&styles->disabled); - lv_style_set_border_width(&styles->disabled, BORDER_W_DIS); - - style_init_reset(&styles->focus); - lv_style_set_outline_width(&styles->focus, 1); - lv_style_set_outline_pad(&styles->focus, BORDER_W_FOCUS); - - style_init_reset(&styles->edit); - lv_style_set_outline_width(&styles->edit, BORDER_W_EDIT); - - style_init_reset(&styles->large_border); - lv_style_set_border_width(&styles->large_border, BORDER_W_EDIT); - - style_init_reset(&styles->pad_gap); - lv_style_set_pad_gap(&styles->pad_gap, PAD_DEF); - - style_init_reset(&styles->pad_zero); - lv_style_set_pad_all(&styles->pad_zero, 0); - lv_style_set_pad_gap(&styles->pad_zero, 0); - - style_init_reset(&styles->no_radius); - lv_style_set_radius(&styles->no_radius, 0); - - style_init_reset(&styles->radius_circle); - lv_style_set_radius(&styles->radius_circle, LV_RADIUS_CIRCLE); - - style_init_reset(&styles->large_line_space); - lv_style_set_text_line_space(&styles->large_line_space, 6); - - style_init_reset(&styles->underline); - lv_style_set_text_decor(&styles->underline, LV_TEXT_DECOR_UNDERLINE); - -#if LV_USE_TEXTAREA - style_init_reset(&styles->ta_cursor); - lv_style_set_border_side(&styles->ta_cursor, LV_BORDER_SIDE_LEFT); - lv_style_set_border_color(&styles->ta_cursor, COLOR_FG); - lv_style_set_border_width(&styles->ta_cursor, 2); - lv_style_set_bg_opa(&styles->ta_cursor, LV_OPA_TRANSP); - lv_style_set_anim_time(&styles->ta_cursor, 500); -#endif -} - - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -bool lv_theme_mono_is_inited(void) -{ - return LV_GC_ROOT(_lv_theme_default_styles) == NULL ? false : true; -} - -lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t * font) -{ - - /*This trick is required only to avoid the garbage collection of - *styles' data if LVGL is used in a binding (e.g. Micropython) - *In a general case styles could be in simple `static lv_style_t my_style...` variables*/ - if(!inited) { - inited = false; - LV_GC_ROOT(_lv_theme_default_styles) = lv_mem_alloc(sizeof(my_theme_styles_t)); - styles = (my_theme_styles_t *)LV_GC_ROOT(_lv_theme_default_styles); - } - - theme.disp = disp; - theme.font_small = LV_FONT_DEFAULT; - theme.font_normal = LV_FONT_DEFAULT; - theme.font_large = LV_FONT_DEFAULT; - theme.apply_cb = theme_apply; - - style_init(dark_bg, font); - - if(disp == NULL || lv_disp_get_theme(disp) == &theme) lv_obj_report_style_change(NULL); - - inited = true; - - return (lv_theme_t *)&theme; -} - - -static void theme_apply(lv_theme_t * th, lv_obj_t * obj) -{ - LV_UNUSED(th); - - if(lv_obj_get_parent(obj) == NULL) { - lv_obj_add_style(obj, &styles->scr, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - return; - } - - if(lv_obj_check_type(obj, &lv_obj_class)) { -#if LV_USE_TABVIEW - lv_obj_t * parent = lv_obj_get_parent(obj); - /*Tabview content area*/ - if(lv_obj_check_type(parent, &lv_tabview_class)) { - return; - } - /*Tabview pages*/ - else if(lv_obj_check_type(lv_obj_get_parent(parent), &lv_tabview_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->no_radius, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - return; - } -#endif - -#if LV_USE_WIN - /*Header*/ - if(lv_obj_get_index(obj) == 0 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->no_radius, 0); - return; - } - /*Content*/ - else if(lv_obj_get_index(obj) == 1 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->no_radius, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - return; - } -#endif - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - } -#if LV_USE_BTN - else if(lv_obj_check_type(obj, &lv_btn_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->pr, LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->inv, LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->disabled, LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->edit, LV_STATE_EDITED); - } -#endif - -#if LV_USE_BTNMATRIX - else if(lv_obj_check_type(obj, &lv_btnmatrix_class)) { -#if LV_USE_MSGBOX - if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_msgbox_class)) { - lv_obj_add_style(obj, &styles->pad_gap, 0); - lv_obj_add_style(obj, &styles->card, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pr, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->disabled, LV_PART_ITEMS | LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->underline, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->large_border, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - return; - } -#endif -#if LV_USE_TABVIEW - if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_tabview_class)) { - lv_obj_add_style(obj, &styles->pad_gap, 0); - lv_obj_add_style(obj, &styles->card, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pr, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->inv, LV_PART_ITEMS | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->disabled, LV_PART_ITEMS | LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->underline, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->large_border, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - return; - } -#endif - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->card, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pr, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->inv, LV_PART_ITEMS | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->disabled, LV_PART_ITEMS | LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->underline, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->large_border, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - } -#endif - -#if LV_USE_BAR - else if(lv_obj_check_type(obj, &lv_bar_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->pad_zero, 0); - lv_obj_add_style(obj, &styles->inv, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - } -#endif - -#if LV_USE_SLIDER - else if(lv_obj_check_type(obj, &lv_slider_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->pad_zero, 0); - lv_obj_add_style(obj, &styles->inv, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->card, LV_PART_KNOB); - lv_obj_add_style(obj, &styles->radius_circle, LV_PART_KNOB); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->edit, LV_STATE_EDITED); - } -#endif - -#if LV_USE_TABLE - else if(lv_obj_check_type(obj, &lv_table_class)) { - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->card, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->no_radius, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pr, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->inv, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->edit, LV_STATE_EDITED); - } -#endif - -#if LV_USE_CHECKBOX - else if(lv_obj_check_type(obj, &lv_checkbox_class)) { - lv_obj_add_style(obj, &styles->pad_gap, LV_PART_MAIN); - lv_obj_add_style(obj, &styles->card, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->disabled, LV_PART_INDICATOR | LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->inv, LV_PART_INDICATOR | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->pr, LV_PART_INDICATOR | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->edit, LV_STATE_EDITED); - } -#endif - -#if LV_USE_SWITCH - else if(lv_obj_check_type(obj, &lv_switch_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->radius_circle, 0); - lv_obj_add_style(obj, &styles->pad_zero, 0); - lv_obj_add_style(obj, &styles->inv, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->radius_circle, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->card, LV_PART_KNOB); - lv_obj_add_style(obj, &styles->radius_circle, LV_PART_KNOB); - lv_obj_add_style(obj, &styles->pad_zero, LV_PART_KNOB); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->edit, LV_STATE_EDITED); - } -#endif - -#if LV_USE_CHART - else if(lv_obj_check_type(obj, &lv_chart_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->card, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->card, LV_PART_TICKS); - lv_obj_add_style(obj, &styles->card, LV_PART_CURSOR); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - } -#endif - -#if LV_USE_ROLLER - else if(lv_obj_check_type(obj, &lv_roller_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->large_line_space, 0); - lv_obj_add_style(obj, &styles->inv, LV_PART_SELECTED); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->edit, LV_STATE_EDITED); - } -#endif - -#if LV_USE_DROPDOWN - else if(lv_obj_check_type(obj, &lv_dropdown_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->pr, LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->edit, LV_STATE_EDITED); - } - else if(lv_obj_check_type(obj, &lv_dropdownlist_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->large_line_space, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->inv, LV_PART_SELECTED | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->pr, LV_PART_SELECTED | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->edit, LV_STATE_EDITED); - } -#endif - -#if LV_USE_ARC - else if(lv_obj_check_type(obj, &lv_arc_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->inv, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->pad_zero, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->card, LV_PART_KNOB); - lv_obj_add_style(obj, &styles->radius_circle, LV_PART_KNOB); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->edit, LV_STATE_EDITED); - } -#endif - -#if LV_USE_METER - else if(lv_obj_check_type(obj, &lv_meter_class)) { - lv_obj_add_style(obj, &styles->card, 0); - } -#endif - -#if LV_USE_TEXTAREA - else if(lv_obj_check_type(obj, &lv_textarea_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - lv_obj_add_style(obj, &styles->ta_cursor, LV_PART_CURSOR | LV_STATE_FOCUSED); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUSED); - lv_obj_add_style(obj, &styles->edit, LV_STATE_EDITED); - } -#endif - -#if LV_USE_CALENDAR - else if(lv_obj_check_type(obj, &lv_calendar_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->no_radius, 0); - lv_obj_add_style(obj, &styles->pr, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->disabled, LV_PART_ITEMS | LV_STATE_DISABLED); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->edit, LV_STATE_EDITED); - lv_obj_add_style(obj, &styles->large_border, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); - } -#endif - -#if LV_USE_KEYBOARD - else if(lv_obj_check_type(obj, &lv_keyboard_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->card, LV_PART_ITEMS); - lv_obj_add_style(obj, &styles->pr, LV_PART_ITEMS | LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->inv, LV_PART_ITEMS | LV_STATE_CHECKED); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->edit, LV_STATE_EDITED); - lv_obj_add_style(obj, &styles->large_border, LV_PART_ITEMS | LV_STATE_EDITED); - } -#endif -#if LV_USE_LIST - else if(lv_obj_check_type(obj, &lv_list_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - return; - } - else if(lv_obj_check_type(obj, &lv_list_text_class)) { - - } - else if(lv_obj_check_type(obj, &lv_list_btn_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->pr, LV_STATE_PRESSED); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->large_border, LV_STATE_EDITED); - - } -#endif -#if LV_USE_MSGBOX - else if(lv_obj_check_type(obj, &lv_msgbox_class)) { - lv_obj_add_style(obj, &styles->card, 0); - return; - } -#endif -#if LV_USE_SPINBOX - else if(lv_obj_check_type(obj, &lv_spinbox_class)) { - lv_obj_add_style(obj, &styles->card, 0); - lv_obj_add_style(obj, &styles->inv, LV_PART_CURSOR); - lv_obj_add_style(obj, &styles->focus, LV_STATE_FOCUS_KEY); - lv_obj_add_style(obj, &styles->edit, LV_STATE_EDITED); - } -#endif -#if LV_USE_TILEVIEW - else if(lv_obj_check_type(obj, &lv_tileview_class)) { - lv_obj_add_style(obj, &styles->scr, 0); - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - } - else if(lv_obj_check_type(obj, &lv_tileview_tile_class)) { - lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR); - } -#endif - -#if LV_USE_LED - else if(lv_obj_check_type(obj, &lv_led_class)) { - lv_obj_add_style(obj, &styles->card, 0); - } -#endif -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void style_init_reset(lv_style_t * style) -{ - if(inited) { - lv_style_reset(style); - } - else { - lv_style_init(style); - } -} - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/animimg/lv_animimg.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/animimg/lv_animimg.h deleted file mode 100644 index 0ba01f239..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/animimg/lv_animimg.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @file lv_animimg.h - * - */ - -#ifndef LV_ANIM_IMG_H -#define LV_ANIM_IMG_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../../lvgl.h" - -#if LV_USE_ANIMIMG != 0 - -/*Testing of dependencies*/ -#if LV_USE_IMG == 0 -#error "lv_animimg: lv_img is required. Enable it in lv_conf.h (LV_USE_IMG 1)" -#endif - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -extern const lv_obj_class_t lv_animimg_class; - -/*Data of image*/ -typedef struct { - lv_img_t img; - lv_anim_t anim; - /*picture sequence */ - const void ** dsc; - int8_t pic_count; -} lv_animimg_t; - - -/*Image parts*/ -enum { - LV_ANIM_IMG_PART_MAIN, -}; -typedef uint8_t lv_animimg_part_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create an animation image objects - * @param parent pointer to an object, it will be the parent of the new button - * @return pointer to the created animation image object - */ -lv_obj_t * lv_animimg_create(lv_obj_t * parent); - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the image animation images source. - * @param img pointer to an animation image object - * @param dsc pointer to a series images - * @param num images' number - */ -void lv_animimg_set_src(lv_obj_t * img, const void * dsc[], uint8_t num); - -/** - * Startup the image animation. - * @param obj pointer to an animation image object - */ -void lv_animimg_start(lv_obj_t * obj); - -/** - * Set the image animation duration time. unit:ms - * @param img pointer to an animation image object - */ -void lv_animimg_set_duration(lv_obj_t * img, uint32_t duration); - -/** - * Set the image animation reapeatly play times. - * @param img pointer to an animation image object - * @param count the number of times to repeat the animation - */ -void lv_animimg_set_repeat_count(lv_obj_t * img, uint16_t count); - -/*===================== - * Getter functions - *====================*/ - -#endif /*LV_USE_ANIMIMG*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_ANIM_IMG_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.c deleted file mode 100644 index eae31bd4c..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.c +++ /dev/null @@ -1,1810 +0,0 @@ -/** - * @file lv_chart.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_chart.h" -#if LV_USE_CHART != 0 - -#include "../../../misc/lv_assert.h" - -/********************* - * DEFINES - *********************/ -#define MY_CLASS &lv_chart_class - -#define LV_CHART_HDIV_DEF 3 -#define LV_CHART_VDIV_DEF 5 -#define LV_CHART_POINT_CNT_DEF 10 -#define LV_CHART_LABEL_MAX_TEXT_LENGTH 16 - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void lv_chart_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void lv_chart_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void lv_chart_event(const lv_obj_class_t * class_p, lv_event_t * e); - -static void draw_div_lines(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx); -static void draw_series_line(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx); -static void draw_series_bar(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx); -static void draw_series_scatter(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx); -static void draw_cursors(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx); -static void draw_axes(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx); -static uint32_t get_index_from_x(lv_obj_t * obj, lv_coord_t x); -static void invalidate_point(lv_obj_t * obj, uint16_t i); -static void new_points_alloc(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t cnt, lv_coord_t ** a); -lv_chart_tick_dsc_t * get_tick_gsc(lv_obj_t * obj, lv_chart_axis_t axis); - -/********************** - * STATIC VARIABLES - **********************/ -const lv_obj_class_t lv_chart_class = { - .constructor_cb = lv_chart_constructor, - .destructor_cb = lv_chart_destructor, - .event_cb = lv_chart_event, - .width_def = LV_PCT(100), - .height_def = LV_DPI_DEF * 2, - .instance_size = sizeof(lv_chart_t), - .base_class = &lv_obj_class -}; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_obj_t * lv_chart_create(lv_obj_t * parent) -{ - LV_LOG_INFO("begin"); - lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); - lv_obj_class_init_obj(obj); - return obj; -} - -void lv_chart_set_type(lv_obj_t * obj, lv_chart_type_t type) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_t * chart = (lv_chart_t *)obj; - if(chart->type == type) return; - - if(chart->type == LV_CHART_TYPE_SCATTER) { - lv_chart_series_t * ser; - _LV_LL_READ_BACK(&chart->series_ll, ser) { - lv_mem_free(ser->x_points); - ser->x_points = NULL; - } - } - - if(type == LV_CHART_TYPE_SCATTER) { - lv_chart_series_t * ser; - _LV_LL_READ_BACK(&chart->series_ll, ser) { - ser->x_points = lv_mem_alloc(sizeof(lv_point_t) * chart->point_cnt); - LV_ASSERT_MALLOC(ser->x_points); - if(ser->x_points == NULL) return; - } - } - - chart->type = type; - - lv_chart_refresh(obj); -} - -void lv_chart_set_point_count(lv_obj_t * obj, uint16_t cnt) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_t * chart = (lv_chart_t *)obj; - if(chart->point_cnt == cnt) return; - - lv_chart_series_t * ser; - - if(cnt < 1) cnt = 1; - - _LV_LL_READ_BACK(&chart->series_ll, ser) { - if(chart->type == LV_CHART_TYPE_SCATTER) { - if(!ser->x_ext_buf_assigned) new_points_alloc(obj, ser, cnt, &ser->x_points); - } - if(!ser->y_ext_buf_assigned) new_points_alloc(obj, ser, cnt, &ser->y_points); - ser->start_point = 0; - } - - chart->point_cnt = cnt; - - lv_chart_refresh(obj); -} - -void lv_chart_set_range(lv_obj_t * obj, lv_chart_axis_t axis, lv_coord_t min, lv_coord_t max) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - max = max == min ? max + 1 : max; - - lv_chart_t * chart = (lv_chart_t *)obj; - switch(axis) { - case LV_CHART_AXIS_PRIMARY_Y: - chart->ymin[0] = min; - chart->ymax[0] = max; - break; - case LV_CHART_AXIS_SECONDARY_Y: - chart->ymin[1] = min; - chart->ymax[1] = max; - break; - case LV_CHART_AXIS_PRIMARY_X: - chart->xmin[0] = min; - chart->xmax[0] = max; - break; - case LV_CHART_AXIS_SECONDARY_X: - chart->xmin[1] = min; - chart->xmax[1] = max; - break; - default: - LV_LOG_WARN("Invalid axis: %d", axis); - return; - } - - lv_chart_refresh(obj); -} - -void lv_chart_set_update_mode(lv_obj_t * obj, lv_chart_update_mode_t update_mode) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_t * chart = (lv_chart_t *)obj; - if(chart->update_mode == update_mode) return; - - chart->update_mode = update_mode; - lv_obj_invalidate(obj); -} - -void lv_chart_set_div_line_count(lv_obj_t * obj, uint8_t hdiv, uint8_t vdiv) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_t * chart = (lv_chart_t *)obj; - if(chart->hdiv_cnt == hdiv && chart->vdiv_cnt == vdiv) return; - - chart->hdiv_cnt = hdiv; - chart->vdiv_cnt = vdiv; - - lv_obj_invalidate(obj); -} - - -void lv_chart_set_zoom_x(lv_obj_t * obj, uint16_t zoom_x) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_t * chart = (lv_chart_t *)obj; - if(chart->zoom_x == zoom_x) return; - - chart->zoom_x = zoom_x; - lv_obj_refresh_self_size(obj); - /*Be the chart doesn't remain scrolled out*/ - lv_obj_readjust_scroll(obj, LV_ANIM_OFF); - lv_obj_invalidate(obj); -} - -void lv_chart_set_zoom_y(lv_obj_t * obj, uint16_t zoom_y) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_t * chart = (lv_chart_t *)obj; - if(chart->zoom_y == zoom_y) return; - - chart->zoom_y = zoom_y; - lv_obj_refresh_self_size(obj); - /*Be the chart doesn't remain scrolled out*/ - lv_obj_readjust_scroll(obj, LV_ANIM_OFF); - lv_obj_invalidate(obj); -} - -uint16_t lv_chart_get_zoom_x(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_t * chart = (lv_chart_t *)obj; - return chart->zoom_x; -} - -uint16_t lv_chart_get_zoom_y(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_t * chart = (lv_chart_t *)obj; - return chart->zoom_y; -} - -void lv_chart_set_axis_tick(lv_obj_t * obj, lv_chart_axis_t axis, lv_coord_t major_len, lv_coord_t minor_len, - lv_coord_t major_cnt, lv_coord_t minor_cnt, bool label_en, lv_coord_t draw_size) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_tick_dsc_t * t = get_tick_gsc(obj, axis); - t->major_len = major_len; - t->minor_len = minor_len; - t->minor_cnt = minor_cnt; - t->major_cnt = major_cnt; - t->label_en = label_en; - t->draw_size = draw_size; - - lv_obj_refresh_ext_draw_size(obj); - lv_obj_invalidate(obj); -} - -lv_chart_type_t lv_chart_get_type(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_t * chart = (lv_chart_t *)obj; - return chart->type; -} - -uint16_t lv_chart_get_point_count(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_t * chart = (lv_chart_t *)obj; - return chart->point_cnt; -} - -uint16_t lv_chart_get_x_start_point(const lv_obj_t * obj, lv_chart_series_t * ser) -{ - LV_ASSERT_NULL(ser); - lv_chart_t * chart = (lv_chart_t *)obj; - - return chart->update_mode == LV_CHART_UPDATE_MODE_SHIFT ? ser->start_point : 0; -} - -void lv_chart_get_point_pos_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_point_t * p_out) -{ - LV_ASSERT_NULL(obj); - LV_ASSERT_NULL(ser); - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_t * chart = (lv_chart_t *)obj; - if(id >= chart->point_cnt) { - LV_LOG_WARN("Invalid index: %d", id); - p_out->x = 0; - p_out->y = 0; - return; - } - - lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - lv_coord_t h = ((int32_t)lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; - - if(chart->type == LV_CHART_TYPE_LINE) { - p_out->x = (w * id) / (chart->point_cnt - 1); - } - else if(chart->type == LV_CHART_TYPE_SCATTER) { - p_out->x = lv_map(ser->x_points[id], chart->xmin[ser->x_axis_sec], chart->xmax[ser->x_axis_sec], 0, w); - } - else if(chart->type == LV_CHART_TYPE_BAR) { - uint32_t ser_cnt = _lv_ll_get_len(&chart->series_ll); - /*Gap between the column on the X tick*/ - int32_t ser_gap = ((int32_t)lv_obj_get_style_pad_column(obj, LV_PART_ITEMS) * chart->zoom_x) >> 8; - - /*Gap between the columns on adjacent X ticks*/ - int32_t block_gap = ((int32_t)lv_obj_get_style_pad_column(obj, LV_PART_MAIN) * chart->zoom_x) >> 8; - - lv_coord_t block_w = (w - ((chart->point_cnt - 1) * block_gap)) / chart->point_cnt; - - lv_chart_series_t * ser_i = NULL; - uint32_t ser_idx = 0; - _LV_LL_READ_BACK(&chart->series_ll, ser_i) { - if(ser_i == ser) break; - ser_idx++; - } - - p_out->x = (int32_t)((int32_t)(w + block_gap) * id) / chart->point_cnt; - p_out->x += block_w * ser_idx / ser_cnt; - - lv_coord_t col_w = (block_w - (ser_gap * (ser_cnt - 1))) / ser_cnt; - p_out->x += col_w / 2; - } - - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - p_out->x += lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; - p_out->x -= lv_obj_get_scroll_left(obj); - - uint32_t start_point = lv_chart_get_x_start_point(obj, ser); - id = ((int32_t)start_point + id) % chart->point_cnt; - int32_t temp_y = 0; - temp_y = (int32_t)((int32_t)ser->y_points[id] - chart->ymin[ser->y_axis_sec]) * h; - temp_y = temp_y / (chart->ymax[ser->y_axis_sec] - chart->ymin[ser->y_axis_sec]); - p_out->y = h - temp_y; - p_out->y += lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; - p_out->y -= lv_obj_get_scroll_top(obj); -} - -void lv_chart_refresh(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_obj_invalidate(obj); -} - -/*====================== - * Series - *=====================*/ - -lv_chart_series_t * lv_chart_add_series(lv_obj_t * obj, lv_color_t color, lv_chart_axis_t axis) -{ - LV_LOG_INFO("begin"); - - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_t * chart = (lv_chart_t *)obj; - lv_chart_series_t * ser = _lv_ll_ins_head(&chart->series_ll); - LV_ASSERT_MALLOC(ser); - if(ser == NULL) return NULL; - - lv_coord_t def = LV_CHART_POINT_NONE; - - ser->color = color; - ser->y_points = lv_mem_alloc(sizeof(lv_coord_t) * chart->point_cnt); - LV_ASSERT_MALLOC(ser->y_points); - - if(chart->type == LV_CHART_TYPE_SCATTER) { - ser->x_points = lv_mem_alloc(sizeof(lv_coord_t) * chart->point_cnt); - LV_ASSERT_MALLOC(ser->x_points); - } - if(ser->y_points == NULL) { - _lv_ll_remove(&chart->series_ll, ser); - lv_mem_free(ser); - return NULL; - } - - ser->start_point = 0; - ser->y_ext_buf_assigned = false; - ser->hidden = 0; - ser->x_axis_sec = axis & LV_CHART_AXIS_SECONDARY_X ? 1 : 0; - ser->y_axis_sec = axis & LV_CHART_AXIS_SECONDARY_Y ? 1 : 0; - - uint16_t i; - lv_coord_t * p_tmp = ser->y_points; - for(i = 0; i < chart->point_cnt; i++) { - *p_tmp = def; - p_tmp++; - } - - return ser; -} - -void lv_chart_remove_series(lv_obj_t * obj, lv_chart_series_t * series) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - LV_ASSERT_NULL(series); - - lv_chart_t * chart = (lv_chart_t *)obj; - if(!series->y_ext_buf_assigned && series->y_points) lv_mem_free(series->y_points); - - _lv_ll_remove(&chart->series_ll, series); - lv_mem_free(series); - - return; -} - -void lv_chart_hide_series(lv_obj_t * chart, lv_chart_series_t * series, bool hide) -{ - LV_ASSERT_OBJ(chart, MY_CLASS); - LV_ASSERT_NULL(series); - - series->hidden = hide ? 1 : 0; - lv_chart_refresh(chart); -} - - -void lv_chart_set_series_color(lv_obj_t * chart, lv_chart_series_t * series, lv_color_t color) -{ - LV_ASSERT_OBJ(chart, MY_CLASS); - LV_ASSERT_NULL(series); - - series->color = color; - lv_chart_refresh(chart); -} - -void lv_chart_set_x_start_point(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - LV_ASSERT_NULL(ser); - - lv_chart_t * chart = (lv_chart_t *)obj; - if(id >= chart->point_cnt) return; - ser->start_point = id; -} - -lv_chart_series_t * lv_chart_get_series_next(const lv_obj_t * obj, const lv_chart_series_t * ser) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_t * chart = (lv_chart_t *)obj; - if(ser == NULL) return _lv_ll_get_head(&chart->series_ll); - else return _lv_ll_get_next(&chart->series_ll, ser); -} - -/*===================== - * Cursor - *====================*/ - -/** - * Add a cursor with a given color - * @param chart pointer to chart object - * @param color color of the cursor - * @param dir direction of the cursor. `LV_DIR_RIGHT/LEFT/TOP/DOWN/HOR/VER/ALL`. OR-ed values are possible - * @return pointer to the created cursor - */ -lv_chart_cursor_t * lv_chart_add_cursor(lv_obj_t * obj, lv_color_t color, lv_dir_t dir) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_t * chart = (lv_chart_t *)obj; - lv_chart_cursor_t * cursor = _lv_ll_ins_head(&chart->cursor_ll); - LV_ASSERT_MALLOC(cursor); - if(cursor == NULL) return NULL; - - cursor->pos.x = LV_CHART_POINT_NONE; - cursor->pos.y = LV_CHART_POINT_NONE; - cursor->point_id = LV_CHART_POINT_NONE; - cursor->pos_set = 0; - cursor->color = color; - cursor->dir = dir; - - return cursor; -} - -/** - * Set the coordinate of the cursor with respect - * to the origin of series area of the chart. - * @param chart pointer to a chart object. - * @param cursor pointer to the cursor. - * @param pos the new coordinate of cursor relative to the series area - */ -void lv_chart_set_cursor_pos(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_point_t * pos) -{ - LV_ASSERT_NULL(cursor); - LV_UNUSED(chart); - - cursor->pos.x = pos->x; - cursor->pos.y = pos->y; - cursor->pos_set = 1; - lv_chart_refresh(chart); -} - - -/** - * Set the coordinate of the cursor with respect - * to the origin of series area of the chart. - * @param chart pointer to a chart object. - * @param cursor pointer to the cursor. - * @param pos the new coordinate of cursor relative to the series area - */ -void lv_chart_set_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_chart_series_t * ser, uint16_t point_id) -{ - LV_ASSERT_NULL(cursor); - LV_UNUSED(chart); - - cursor->point_id = point_id; - cursor->pos_set = 0; - if(ser == NULL) ser = lv_chart_get_series_next(chart, NULL); - cursor->ser = ser; - lv_chart_refresh(chart); -} -/** - * Get the coordinate of the cursor with respect - * to the origin of series area of the chart. - * @param chart pointer to a chart object - * @param cursor pointer to cursor - * @return coordinate of the cursor as lv_point_t - */ -lv_point_t lv_chart_get_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * cursor) -{ - LV_ASSERT_NULL(cursor); - LV_UNUSED(chart); - - return cursor->pos; -} - -/*===================== - * Set/Get value(s) - *====================*/ - - -void lv_chart_set_all_value(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t value) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - LV_ASSERT_NULL(ser); - - lv_chart_t * chart = (lv_chart_t *)obj; - uint16_t i; - for(i = 0; i < chart->point_cnt; i++) { - ser->y_points[i] = value; - } - ser->start_point = 0; - lv_chart_refresh(obj); -} - -void lv_chart_set_next_value(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t value) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - LV_ASSERT_NULL(ser); - - lv_chart_t * chart = (lv_chart_t *)obj; - ser->y_points[ser->start_point] = value; - invalidate_point(obj, ser->start_point); - ser->start_point = (ser->start_point + 1) % chart->point_cnt; - invalidate_point(obj, ser->start_point); -} - -void lv_chart_set_next_value2(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t x_value, lv_coord_t y_value) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - LV_ASSERT_NULL(ser); - - lv_chart_t * chart = (lv_chart_t *)obj; - - if(chart->type != LV_CHART_TYPE_SCATTER) { - LV_LOG_WARN("Type must be LV_CHART_TYPE_SCATTER"); - return; - } - - ser->x_points[ser->start_point] = x_value; - ser->y_points[ser->start_point] = y_value; - ser->start_point = (ser->start_point + 1) % chart->point_cnt; - invalidate_point(obj, ser->start_point); -} - -void lv_chart_set_value_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_coord_t value) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - LV_ASSERT_NULL(ser); - lv_chart_t * chart = (lv_chart_t *)obj; - - if(id >= chart->point_cnt) return; - ser->y_points[id] = value; - invalidate_point(obj, id); -} - -void lv_chart_set_value_by_id2(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_coord_t x_value, - lv_coord_t y_value) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - LV_ASSERT_NULL(ser); - lv_chart_t * chart = (lv_chart_t *)obj; - - if(chart->type != LV_CHART_TYPE_SCATTER) { - LV_LOG_WARN("Type must be LV_CHART_TYPE_SCATTER"); - return; - } - - if(id >= chart->point_cnt) return; - ser->x_points[id] = x_value; - ser->y_points[id] = y_value; - invalidate_point(obj, id); -} - -void lv_chart_set_ext_y_array(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t array[]) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - LV_ASSERT_NULL(ser); - - if(!ser->y_ext_buf_assigned && ser->y_points) lv_mem_free(ser->y_points); - ser->y_ext_buf_assigned = true; - ser->y_points = array; - lv_obj_invalidate(obj); -} - -void lv_chart_set_ext_x_array(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t array[]) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - LV_ASSERT_NULL(ser); - - if(!ser->x_ext_buf_assigned && ser->x_points) lv_mem_free(ser->x_points); - ser->x_ext_buf_assigned = true; - ser->x_points = array; - lv_obj_invalidate(obj); -} - -lv_coord_t * lv_chart_get_y_array(const lv_obj_t * obj, lv_chart_series_t * ser) -{ - LV_UNUSED(obj); - LV_ASSERT_OBJ(obj, MY_CLASS); - LV_ASSERT_NULL(ser); - return ser->y_points; -} - -lv_coord_t * lv_chart_get_x_array(const lv_obj_t * obj, lv_chart_series_t * ser) -{ - LV_UNUSED(obj); - LV_ASSERT_OBJ(obj, MY_CLASS); - LV_ASSERT_NULL(ser); - return ser->x_points; -} - -uint32_t lv_chart_get_pressed_point(const lv_obj_t * obj) -{ - lv_chart_t * chart = (lv_chart_t *)obj; - return chart->pressed_point_id; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void lv_chart_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) -{ - LV_UNUSED(class_p); - LV_TRACE_OBJ_CREATE("begin"); - - lv_chart_t * chart = (lv_chart_t *)obj; - - _lv_ll_init(&chart->series_ll, sizeof(lv_chart_series_t)); - _lv_ll_init(&chart->cursor_ll, sizeof(lv_chart_cursor_t)); - - chart->ymin[0] = 0; - chart->xmin[0] = 0; - chart->ymin[1] = 0; - chart->xmin[1] = 0; - chart->ymax[0] = 100; - chart->xmax[0] = 100; - chart->ymax[1] = 100; - chart->xmax[1] = 100; - - chart->hdiv_cnt = LV_CHART_HDIV_DEF; - chart->vdiv_cnt = LV_CHART_VDIV_DEF; - chart->point_cnt = LV_CHART_POINT_CNT_DEF; - chart->pressed_point_id = LV_CHART_POINT_NONE; - chart->type = LV_CHART_TYPE_LINE; - chart->update_mode = LV_CHART_UPDATE_MODE_SHIFT; - chart->zoom_x = LV_IMG_ZOOM_NONE; - chart->zoom_y = LV_IMG_ZOOM_NONE; - - LV_TRACE_OBJ_CREATE("finished"); -} - -static void lv_chart_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) -{ - LV_UNUSED(class_p); - LV_TRACE_OBJ_CREATE("begin"); - - lv_chart_t * chart = (lv_chart_t *)obj; - lv_chart_series_t * ser; - while(chart->series_ll.head) { - ser = _lv_ll_get_head(&chart->series_ll); - - if(!ser->y_ext_buf_assigned) lv_mem_free(ser->y_points); - - _lv_ll_remove(&chart->series_ll, ser); - lv_mem_free(ser); - } - _lv_ll_clear(&chart->series_ll); - - lv_chart_cursor_t * cur; - while(chart->cursor_ll.head) { - cur = _lv_ll_get_head(&chart->cursor_ll); - _lv_ll_remove(&chart->cursor_ll, cur); - lv_mem_free(cur); - } - _lv_ll_clear(&chart->cursor_ll); - - LV_TRACE_OBJ_CREATE("finished"); -} - -static void lv_chart_event(const lv_obj_class_t * class_p, lv_event_t * e) -{ - LV_UNUSED(class_p); - - /*Call the ancestor's event handler*/ - lv_res_t res; - - res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; - - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); - - lv_chart_t * chart = (lv_chart_t *)obj; - if(code == LV_EVENT_PRESSED) { - lv_indev_t * indev = lv_indev_get_act(); - lv_point_t p; - lv_indev_get_point(indev, &p); - - p.x -= obj->coords.x1; - uint32_t id = get_index_from_x(obj, p.x + lv_obj_get_scroll_left(obj)); - if(id != (uint32_t)chart->pressed_point_id) { - invalidate_point(obj, id); - invalidate_point(obj, chart->pressed_point_id); - chart->pressed_point_id = id; - lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - } - } - else if(code == LV_EVENT_RELEASED) { - invalidate_point(obj, chart->pressed_point_id); - chart->pressed_point_id = LV_CHART_POINT_NONE; - } - else if(code == LV_EVENT_SIZE_CHANGED) { - lv_obj_refresh_self_size(obj); - } - else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - lv_event_set_ext_draw_size(e, LV_MAX4(chart->tick[0].draw_size, chart->tick[1].draw_size, chart->tick[2].draw_size, - chart->tick[3].draw_size)); - } - else if(code == LV_EVENT_GET_SELF_SIZE) { - lv_point_t * p = lv_event_get_param(e); - p->x = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - p->y = ((int32_t)lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; - } - else if(code == LV_EVENT_DRAW_MAIN) { - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); - draw_div_lines(obj, draw_ctx); - draw_axes(obj, draw_ctx); - - if(_lv_ll_is_empty(&chart->series_ll) == false) { - if(chart->type == LV_CHART_TYPE_LINE) draw_series_line(obj, draw_ctx); - else if(chart->type == LV_CHART_TYPE_BAR) draw_series_bar(obj, draw_ctx); - else if(chart->type == LV_CHART_TYPE_SCATTER) draw_series_scatter(obj, draw_ctx); - } - - draw_cursors(obj, draw_ctx); - } -} - -static void draw_div_lines(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) -{ - lv_chart_t * chart = (lv_chart_t *)obj; - - lv_area_t series_clip_area; - bool mask_ret = _lv_area_intersect(&series_clip_area, &obj->coords, draw_ctx->clip_area); - if(mask_ret == false) return; - - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &series_clip_area; - - int16_t i; - int16_t i_start; - int16_t i_end; - lv_point_t p1; - lv_point_t p2; - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; - lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; - lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - lv_coord_t h = ((int32_t)lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; - - lv_draw_line_dsc_t line_dsc; - lv_draw_line_dsc_init(&line_dsc); - lv_obj_init_draw_line_dsc(obj, LV_PART_MAIN, &line_dsc); - - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.part = LV_PART_MAIN; - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_CHART_DRAW_PART_DIV_LINE_INIT; - part_draw_dsc.line_dsc = &line_dsc; - part_draw_dsc.id = 0xFFFFFFFF; - part_draw_dsc.p1 = NULL; - part_draw_dsc.p2 = NULL; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - - lv_opa_t border_opa = lv_obj_get_style_border_opa(obj, LV_PART_MAIN); - lv_coord_t border_w = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_border_side_t border_side = lv_obj_get_style_border_side(obj, LV_PART_MAIN); - - lv_coord_t scroll_left = lv_obj_get_scroll_left(obj); - lv_coord_t scroll_top = lv_obj_get_scroll_top(obj); - if(chart->hdiv_cnt != 0) { - lv_coord_t y_ofs = obj->coords.y1 + pad_top - scroll_top; - p1.x = obj->coords.x1; - p2.x = obj->coords.x2; - - i_start = 0; - i_end = chart->hdiv_cnt; - if(border_opa > LV_OPA_MIN && border_w > 0) { - if((border_side & LV_BORDER_SIDE_TOP) && (lv_obj_get_style_pad_top(obj, LV_PART_MAIN) == 0)) i_start++; - if((border_side & LV_BORDER_SIDE_BOTTOM) && (lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN) == 0)) i_end--; - } - - for(i = i_start; i < i_end; i++) { - p1.y = (int32_t)((int32_t)h * i) / (chart->hdiv_cnt - 1); - p1.y += y_ofs; - p2.y = p1.y; - - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_CHART_DRAW_PART_DIV_LINE_HOR; - part_draw_dsc.p1 = &p1; - part_draw_dsc.p2 = &p2; - part_draw_dsc.id = i; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_line(draw_ctx, &line_dsc, &p1, &p2); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } - } - - if(chart->vdiv_cnt != 0) { - lv_coord_t x_ofs = obj->coords.x1 + pad_left - scroll_left; - p1.y = obj->coords.y1; - p2.y = obj->coords.y2; - i_start = 0; - i_end = chart->vdiv_cnt; - if(border_opa > LV_OPA_MIN && border_w > 0) { - if((border_side & LV_BORDER_SIDE_LEFT) && (lv_obj_get_style_pad_left(obj, LV_PART_MAIN) == 0)) i_start++; - if((border_side & LV_BORDER_SIDE_RIGHT) && (lv_obj_get_style_pad_right(obj, LV_PART_MAIN) == 0)) i_end--; - } - - for(i = i_start; i < i_end; i++) { - p1.x = (int32_t)((int32_t)w * i) / (chart->vdiv_cnt - 1); - p1.x += x_ofs; - p2.x = p1.x; - - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_CHART_DRAW_PART_DIV_LINE_VER; - part_draw_dsc.p1 = &p1; - part_draw_dsc.p2 = &p2; - part_draw_dsc.id = i; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_line(draw_ctx, &line_dsc, &p1, &p2); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } - } - - part_draw_dsc.id = 0xFFFFFFFF; - part_draw_dsc.p1 = NULL; - part_draw_dsc.p2 = NULL; - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - - draw_ctx->clip_area = clip_area_ori; -} - -static void draw_series_line(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) -{ - lv_area_t clip_area; - if(_lv_area_intersect(&clip_area, &obj->coords, draw_ctx->clip_area) == false) return; - - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &clip_area; - - lv_chart_t * chart = (lv_chart_t *)obj; - if(chart->point_cnt < 2) return; - - uint16_t i; - lv_point_t p1; - lv_point_t p2; - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; - lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; - lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - lv_coord_t h = ((int32_t)lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; - lv_coord_t x_ofs = obj->coords.x1 + pad_left - lv_obj_get_scroll_left(obj); - lv_coord_t y_ofs = obj->coords.y1 + pad_top - lv_obj_get_scroll_top(obj); - lv_chart_series_t * ser; - - lv_area_t series_clip_area; - bool mask_ret = _lv_area_intersect(&series_clip_area, &obj->coords, draw_ctx->clip_area); - if(mask_ret == false) return; - - lv_draw_line_dsc_t line_dsc_default; - lv_draw_line_dsc_init(&line_dsc_default); - lv_obj_init_draw_line_dsc(obj, LV_PART_ITEMS, &line_dsc_default); - - lv_draw_rect_dsc_t point_dsc_default; - lv_draw_rect_dsc_init(&point_dsc_default); - lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &point_dsc_default); - - lv_coord_t point_w = lv_obj_get_style_width(obj, LV_PART_INDICATOR) / 2; - lv_coord_t point_h = lv_obj_get_style_height(obj, LV_PART_INDICATOR) / 2; - - /*Do not bother with line ending is the point will over it*/ - if(LV_MIN(point_w, point_h) > line_dsc_default.width / 2) line_dsc_default.raw_end = 1; - if(line_dsc_default.width == 1) line_dsc_default.raw_end = 1; - - /*If there are at least as much points as pixels then draw only vertical lines*/ - bool crowded_mode = chart->point_cnt >= w ? true : false; - - /*Go through all data lines*/ - _LV_LL_READ_BACK(&chart->series_ll, ser) { - if(ser->hidden) continue; - line_dsc_default.color = ser->color; - point_dsc_default.bg_color = ser->color; - - lv_coord_t start_point = lv_chart_get_x_start_point(obj, ser); - - p1.x = x_ofs; - p2.x = x_ofs; - - lv_coord_t p_act = start_point; - lv_coord_t p_prev = start_point; - int32_t y_tmp = (int32_t)((int32_t)ser->y_points[p_prev] - chart->ymin[ser->y_axis_sec]) * h; - y_tmp = y_tmp / (chart->ymax[ser->y_axis_sec] - chart->ymin[ser->y_axis_sec]); - p2.y = h - y_tmp + y_ofs; - - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_CHART_DRAW_PART_LINE_AND_POINT; - part_draw_dsc.part = LV_PART_ITEMS; - part_draw_dsc.line_dsc = &line_dsc_default; - part_draw_dsc.rect_dsc = &point_dsc_default; - part_draw_dsc.sub_part_ptr = ser; - - lv_coord_t y_min = p2.y; - lv_coord_t y_max = p2.y; - - for(i = 0; i < chart->point_cnt; i++) { - p1.x = p2.x; - p1.y = p2.y; - - if(p1.x > clip_area_ori->x2 + point_w + 1) break; - p2.x = ((w * i) / (chart->point_cnt - 1)) + x_ofs; - - p_act = (start_point + i) % chart->point_cnt; - - y_tmp = (int32_t)((int32_t)ser->y_points[p_act] - chart->ymin[ser->y_axis_sec]) * h; - y_tmp = y_tmp / (chart->ymax[ser->y_axis_sec] - chart->ymin[ser->y_axis_sec]); - p2.y = h - y_tmp + y_ofs; - - if(p2.x < clip_area_ori->x1 - point_w - 1) { - p_prev = p_act; - continue; - } - - /*Don't draw the first point. A second point is also required to draw the line*/ - if(i != 0) { - if(crowded_mode) { - if(ser->y_points[p_prev] != LV_CHART_POINT_NONE && ser->y_points[p_act] != LV_CHART_POINT_NONE) { - /*Draw only one vertical line between the min and max y-values on the same x-value*/ - y_max = LV_MAX(y_max, p2.y); - y_min = LV_MIN(y_min, p2.y); - if(p1.x != p2.x) { - lv_coord_t y_cur = p2.y; - p2.x--; /*It's already on the next x value*/ - p1.x = p2.x; - p1.y = y_min; - p2.y = y_max; - if(p1.y == p2.y) p2.y++; /*If they are the same no line will be drawn*/ - lv_draw_line(draw_ctx, &line_dsc_default, &p1, &p2); - p2.x++; /*Compensate the previous x--*/ - y_min = y_cur; /*Start the line of the next x from the current last y*/ - y_max = y_cur; - } - } - } - else { - lv_area_t point_area; - point_area.x1 = p1.x - point_w; - point_area.x2 = p1.x + point_w; - point_area.y1 = p1.y - point_h; - point_area.y2 = p1.y + point_h; - - part_draw_dsc.id = i - 1; - part_draw_dsc.p1 = ser->y_points[p_prev] != LV_CHART_POINT_NONE ? &p1 : NULL; - part_draw_dsc.p2 = ser->y_points[p_act] != LV_CHART_POINT_NONE ? &p2 : NULL; - part_draw_dsc.draw_area = &point_area; - part_draw_dsc.value = ser->y_points[p_prev]; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - - if(ser->y_points[p_prev] != LV_CHART_POINT_NONE && ser->y_points[p_act] != LV_CHART_POINT_NONE) { - lv_draw_line(draw_ctx, &line_dsc_default, &p1, &p2); - } - - if(point_w && point_h && ser->y_points[p_prev] != LV_CHART_POINT_NONE) { - lv_draw_rect(draw_ctx, &point_dsc_default, &point_area); - } - - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } - - } - p_prev = p_act; - } - - /*Draw the last point*/ - if(!crowded_mode && i == chart->point_cnt) { - - if(ser->y_points[p_act] != LV_CHART_POINT_NONE) { - lv_area_t point_area; - point_area.x1 = p2.x - point_w; - point_area.x2 = p2.x + point_w; - point_area.y1 = p2.y - point_h; - point_area.y2 = p2.y + point_h; - - part_draw_dsc.id = i - 1; - part_draw_dsc.p1 = NULL; - part_draw_dsc.p2 = NULL; - part_draw_dsc.draw_area = &point_area; - part_draw_dsc.value = ser->y_points[p_act]; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_rect(draw_ctx, &point_dsc_default, &point_area); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } - } - } - - draw_ctx->clip_area = clip_area_ori; -} - -static void draw_series_scatter(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) -{ - - lv_area_t clip_area; - if(_lv_area_intersect(&clip_area, &obj->coords, draw_ctx->clip_area) == false) return; - - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &clip_area; - - lv_chart_t * chart = (lv_chart_t *)obj; - - uint16_t i; - lv_point_t p1; - lv_point_t p2; - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - lv_coord_t h = ((int32_t)lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; - lv_coord_t x_ofs = obj->coords.x1 + pad_left + border_width - lv_obj_get_scroll_left(obj); - lv_coord_t y_ofs = obj->coords.y1 + pad_top + border_width - lv_obj_get_scroll_top(obj); - lv_chart_series_t * ser; - - lv_draw_line_dsc_t line_dsc_default; - lv_draw_line_dsc_init(&line_dsc_default); - lv_obj_init_draw_line_dsc(obj, LV_PART_ITEMS, &line_dsc_default); - - lv_draw_rect_dsc_t point_dsc_default; - lv_draw_rect_dsc_init(&point_dsc_default); - lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &point_dsc_default); - - lv_coord_t point_w = lv_obj_get_style_width(obj, LV_PART_INDICATOR) / 2; - lv_coord_t point_h = lv_obj_get_style_height(obj, LV_PART_INDICATOR) / 2; - - /*Do not bother with line ending is the point will over it*/ - if(LV_MIN(point_w, point_h) > line_dsc_default.width / 2) line_dsc_default.raw_end = 1; - if(line_dsc_default.width == 1) line_dsc_default.raw_end = 1; - - /*Go through all data lines*/ - _LV_LL_READ_BACK(&chart->series_ll, ser) { - if(ser->hidden) continue; - line_dsc_default.color = ser->color; - point_dsc_default.bg_color = ser->color; - - lv_coord_t start_point = lv_chart_get_x_start_point(obj, ser); - - p1.x = x_ofs; - p2.x = x_ofs; - - lv_coord_t p_act = start_point; - lv_coord_t p_prev = start_point; - if(ser->y_points[p_act] != LV_CHART_POINT_CNT_DEF) { - p2.x = lv_map(ser->x_points[p_act], chart->xmin[ser->x_axis_sec], chart->xmax[ser->x_axis_sec], 0, w); - p2.x += x_ofs; - - p2.y = lv_map(ser->y_points[p_act], chart->ymin[ser->y_axis_sec], chart->ymax[ser->y_axis_sec], 0, h); - p2.y = h - p2.y; - p2.y += y_ofs; - } - else { - p2.x = LV_COORD_MIN; - p2.y = LV_COORD_MIN; - } - - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.part = LV_PART_ITEMS; - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_CHART_DRAW_PART_LINE_AND_POINT; - part_draw_dsc.line_dsc = &line_dsc_default; - part_draw_dsc.rect_dsc = &point_dsc_default; - part_draw_dsc.sub_part_ptr = ser; - - for(i = 0; i < chart->point_cnt; i++) { - p1.x = p2.x; - p1.y = p2.y; - - p_act = (start_point + i) % chart->point_cnt; - if(ser->y_points[p_act] != LV_CHART_POINT_NONE) { - p2.y = lv_map(ser->y_points[p_act], chart->ymin[ser->y_axis_sec], chart->ymax[ser->y_axis_sec], 0, h); - p2.y = h - p2.y; - p2.y += y_ofs; - - p2.x = lv_map(ser->x_points[p_act], chart->xmin[ser->x_axis_sec], chart->xmax[ser->x_axis_sec], 0, w); - p2.x += x_ofs; - } - else { - p_prev = p_act; - continue; - } - - /*Don't draw the first point. A second point is also required to draw the line*/ - if(i != 0) { - lv_area_t point_area; - point_area.x1 = p1.x - point_w; - point_area.x2 = p1.x + point_w; - point_area.y1 = p1.y - point_h; - point_area.y2 = p1.y + point_h; - - part_draw_dsc.id = i - 1; - part_draw_dsc.p1 = ser->y_points[p_prev] != LV_CHART_POINT_NONE ? &p1 : NULL; - part_draw_dsc.p2 = ser->y_points[p_act] != LV_CHART_POINT_NONE ? &p2 : NULL; - part_draw_dsc.draw_area = &point_area; - part_draw_dsc.value = ser->y_points[p_prev]; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - - if(ser->y_points[p_prev] != LV_CHART_POINT_NONE && ser->y_points[p_act] != LV_CHART_POINT_NONE) { - lv_draw_line(draw_ctx, &line_dsc_default, &p1, &p2); - if(point_w && point_h) { - lv_draw_rect(draw_ctx, &point_dsc_default, &point_area); - } - } - - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } - p_prev = p_act; - } - - /*Draw the last point*/ - if(i == chart->point_cnt) { - - if(ser->y_points[p_act] != LV_CHART_POINT_NONE) { - lv_area_t point_area; - point_area.x1 = p2.x - point_w; - point_area.x2 = p2.x + point_w; - point_area.y1 = p2.y - point_h; - point_area.y2 = p2.y + point_h; - - part_draw_dsc.id = i - 1; - part_draw_dsc.p1 = NULL; - part_draw_dsc.p2 = NULL; - part_draw_dsc.draw_area = &point_area; - part_draw_dsc.value = ser->y_points[p_act]; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_rect(draw_ctx, &point_dsc_default, &point_area); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } - } - } - draw_ctx->clip_area = clip_area_ori; -} - -static void draw_series_bar(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) -{ - lv_area_t clip_area; - if(_lv_area_intersect(&clip_area, &obj->coords, draw_ctx->clip_area) == false) return; - - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &clip_area; - - lv_chart_t * chart = (lv_chart_t *)obj; - - uint16_t i; - lv_area_t col_a; - lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - lv_coord_t h = ((int32_t)lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; - int32_t y_tmp; - lv_chart_series_t * ser; - uint32_t ser_cnt = _lv_ll_get_len(&chart->series_ll); - int32_t block_gap = ((int32_t)lv_obj_get_style_pad_column(obj, - LV_PART_MAIN) * chart->zoom_x) >> 8; /*Gap between the column on ~adjacent X*/ - lv_coord_t block_w = (w - ((chart->point_cnt - 1) * block_gap)) / chart->point_cnt; - int32_t ser_gap = ((int32_t)lv_obj_get_style_pad_column(obj, - LV_PART_ITEMS) * chart->zoom_x) >> 8; /*Gap between the columns on the ~same X*/ - lv_coord_t col_w = (block_w - (ser_cnt - 1) * ser_gap) / ser_cnt; - if(col_w < 1) col_w = 1; - - lv_coord_t border_w = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t x_ofs = pad_left - lv_obj_get_scroll_left(obj) + border_w; - lv_coord_t y_ofs = pad_top - lv_obj_get_scroll_top(obj) + border_w; - - lv_draw_rect_dsc_t col_dsc; - lv_draw_rect_dsc_init(&col_dsc); - lv_obj_init_draw_rect_dsc(obj, LV_PART_ITEMS, &col_dsc); - col_dsc.bg_grad.dir = LV_GRAD_DIR_NONE; - col_dsc.bg_opa = LV_OPA_COVER; - - /*Make the cols longer with `radius` to clip the rounding from the bottom*/ - col_a.y2 = obj->coords.y2 + col_dsc.radius; - - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.part = LV_PART_ITEMS; - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_CHART_DRAW_PART_BAR; - - /*Go through all points*/ - for(i = 0; i < chart->point_cnt; i++) { - lv_coord_t x_act = (int32_t)((int32_t)(w - block_w) * i) / (chart->point_cnt - 1) + obj->coords.x1 + x_ofs; - - part_draw_dsc.id = i; - - /*Draw the current point of all data line*/ - _LV_LL_READ_BACK(&chart->series_ll, ser) { - if(ser->hidden) continue; - - lv_coord_t start_point = lv_chart_get_x_start_point(obj, ser); - - col_a.x1 = x_act; - col_a.x2 = col_a.x1 + col_w - 1; - x_act += col_w + ser_gap; - - if(col_a.x2 < clip_area.x1) continue; - if(col_a.x1 > clip_area.x2) break; - - col_dsc.bg_color = ser->color; - - lv_coord_t p_act = (start_point + i) % chart->point_cnt; - y_tmp = (int32_t)((int32_t)ser->y_points[p_act] - chart->ymin[ser->y_axis_sec]) * h; - y_tmp = y_tmp / (chart->ymax[ser->y_axis_sec] - chart->ymin[ser->y_axis_sec]); - col_a.y1 = h - y_tmp + obj->coords.y1 + y_ofs; - - if(ser->y_points[p_act] != LV_CHART_POINT_NONE) { - part_draw_dsc.draw_area = &col_a; - part_draw_dsc.rect_dsc = &col_dsc; - part_draw_dsc.sub_part_ptr = ser; - part_draw_dsc.value = ser->y_points[p_act]; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_rect(draw_ctx, &col_dsc, &col_a); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } - } - } - draw_ctx->clip_area = clip_area_ori; -} - -static void draw_cursors(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_chart_t * chart = (lv_chart_t *)obj; - if(_lv_ll_is_empty(&chart->cursor_ll)) return; - - lv_area_t clip_area; - if(!_lv_area_intersect(&clip_area, draw_ctx->clip_area, &obj->coords)) return; - - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &clip_area; - - lv_point_t p1; - lv_point_t p2; - lv_chart_cursor_t * cursor; - - lv_draw_line_dsc_t line_dsc_ori; - lv_draw_line_dsc_init(&line_dsc_ori); - lv_obj_init_draw_line_dsc(obj, LV_PART_CURSOR, &line_dsc_ori); - - lv_draw_rect_dsc_t point_dsc_ori; - lv_draw_rect_dsc_init(&point_dsc_ori); - point_dsc_ori.bg_opa = line_dsc_ori.opa; - point_dsc_ori.radius = LV_RADIUS_CIRCLE; - - lv_draw_line_dsc_t line_dsc_tmp; - lv_draw_rect_dsc_t point_dsc_tmp; - - lv_coord_t point_w = lv_obj_get_style_width(obj, LV_PART_CURSOR) / 2; - lv_coord_t point_h = lv_obj_get_style_width(obj, LV_PART_CURSOR) / 2; - - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.line_dsc = &line_dsc_tmp; - part_draw_dsc.rect_dsc = &point_dsc_tmp; - part_draw_dsc.part = LV_PART_CURSOR; - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_CHART_DRAW_PART_CURSOR; - - /*Go through all cursor lines*/ - _LV_LL_READ_BACK(&chart->cursor_ll, cursor) { - lv_memcpy(&line_dsc_tmp, &line_dsc_ori, sizeof(lv_draw_line_dsc_t)); - lv_memcpy(&point_dsc_tmp, &point_dsc_ori, sizeof(lv_draw_rect_dsc_t)); - line_dsc_tmp.color = cursor->color; - point_dsc_tmp.bg_color = cursor->color; - - part_draw_dsc.p1 = &p1; - part_draw_dsc.p2 = &p2; - - lv_coord_t cx; - lv_coord_t cy; - if(cursor->pos_set) { - cx = cursor->pos.x; - cy = cursor->pos.y; - } - else { - if(cursor->point_id == LV_CHART_POINT_NONE) continue; - lv_point_t p; - lv_chart_get_point_pos_by_id(obj, cursor->ser, cursor->point_id, &p); - cx = p.x; - cy = p.y; - } - - cx += obj->coords.x1; - cy += obj->coords.y1; - - lv_area_t point_area; - bool draw_point = point_w && point_h; - if(draw_point) { - point_area.x1 = cx - point_w; - point_area.x2 = cx + point_w; - point_area.y1 = cy - point_h; - point_area.y2 = cy + point_h; - - part_draw_dsc.draw_area = &point_area; - } - else { - part_draw_dsc.draw_area = NULL; - } - - if(cursor->dir & LV_DIR_HOR) { - p1.x = cursor->dir & LV_DIR_LEFT ? obj->coords.x1 : cx; - p1.y = cy; - p2.x = cursor->dir & LV_DIR_RIGHT ? obj->coords.x2 : cx; - p2.y = p1.y; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_line(draw_ctx, &line_dsc_tmp, &p1, &p2); - - if(draw_point) { - lv_draw_rect(draw_ctx, &point_dsc_tmp, &point_area); - } - - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } - - if(cursor->dir & LV_DIR_VER) { - p1.x = cx; - p1.y = cursor->dir & LV_DIR_TOP ? obj->coords.y1 : cy; - p2.x = p1.x; - p2.y = cursor->dir & LV_DIR_BOTTOM ? obj->coords.y2 : cy; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_line(draw_ctx, &line_dsc_tmp, &p1, &p2); - - if(draw_point) { - lv_draw_rect(draw_ctx, &point_dsc_tmp, &point_area); - } - - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } - } - - draw_ctx->clip_area = clip_area_ori; -} - -static void draw_y_ticks(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, lv_chart_axis_t axis) -{ - lv_chart_t * chart = (lv_chart_t *)obj; - - lv_chart_tick_dsc_t * t = get_tick_gsc(obj, axis); - - if(!t->label_en && !t->major_len && !t->minor_len) return; - if(t->major_cnt <= 1) return; - uint32_t total_tick_num = (t->major_cnt - 1) * (t->minor_cnt); - if(total_tick_num == 0) return; - - uint8_t sec_axis = axis == LV_CHART_AXIS_PRIMARY_Y ? 0 : 1; - - uint32_t i; - - lv_point_t p1; - lv_point_t p2; - - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t h = ((int32_t)lv_obj_get_content_height(obj) * chart->zoom_y) >> 8; - lv_coord_t y_ofs = obj->coords.y1 + pad_top + border_width - lv_obj_get_scroll_top(obj); - - lv_coord_t label_gap; - lv_coord_t x_ofs; - if(axis == LV_CHART_AXIS_PRIMARY_Y) { - label_gap = lv_obj_get_style_pad_left(obj, LV_PART_TICKS); - x_ofs = obj->coords.x1; - } - else { - label_gap = lv_obj_get_style_pad_right(obj, LV_PART_TICKS); - x_ofs = obj->coords.x2; - } - - lv_coord_t major_len = t->major_len; - lv_coord_t minor_len = t->minor_len; - /*tick lines on secondary y axis are drawn in other direction*/ - if(axis == LV_CHART_AXIS_SECONDARY_Y) { - major_len *= -1; - minor_len *= -1; - } - - lv_draw_line_dsc_t line_dsc; - lv_draw_line_dsc_init(&line_dsc); - lv_obj_init_draw_line_dsc(obj, LV_PART_TICKS, &line_dsc); - - lv_draw_label_dsc_t label_dsc; - lv_draw_label_dsc_init(&label_dsc); - lv_obj_init_draw_label_dsc(obj, LV_PART_TICKS, &label_dsc); - - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_CHART_DRAW_PART_TICK_LABEL; - part_draw_dsc.id = axis; - part_draw_dsc.part = LV_PART_TICKS; - part_draw_dsc.line_dsc = &line_dsc; - part_draw_dsc.label_dsc = &label_dsc; - - for(i = 0; i <= total_tick_num; i++) { - /*draw a line at moving y position*/ - p2.y = p1.y = y_ofs + (int32_t)((int32_t)(h - line_dsc.width) * i) / total_tick_num; - - /*first point of the tick*/ - p1.x = x_ofs; - - /*move extra pixel out of chart boundary*/ - if(axis == LV_CHART_AXIS_PRIMARY_Y) p1.x--; - else p1.x++; - - /*second point of the tick*/ - bool major = false; - if(i % t->minor_cnt == 0) major = true; - - if(major) p2.x = p1.x - major_len; /*major tick*/ - else p2.x = p1.x - minor_len; /*minor tick*/ - - part_draw_dsc.p1 = &p1; - part_draw_dsc.p2 = &p2; - - int32_t tick_value = lv_map(total_tick_num - i, 0, total_tick_num, chart->ymin[sec_axis], chart->ymax[sec_axis]); - part_draw_dsc.value = tick_value; - - /*add text only to major tick*/ - if(major && t->label_en) { - char buf[LV_CHART_LABEL_MAX_TEXT_LENGTH]; - lv_snprintf(buf, sizeof(buf), "%" LV_PRId32, tick_value); - part_draw_dsc.label_dsc = &label_dsc; - part_draw_dsc.text = buf; - part_draw_dsc.text_length = LV_CHART_LABEL_MAX_TEXT_LENGTH; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - - /*reserve appropriate area*/ - lv_point_t size; - lv_txt_get_size(&size, part_draw_dsc.text, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, LV_COORD_MAX, - LV_TEXT_FLAG_NONE); - - /*set the area at some distance of the major tick len left of the tick*/ - lv_area_t a; - a.y1 = p2.y - size.y / 2; - a.y2 = p2.y + size.y / 2; - - if(!sec_axis) { - a.x1 = p2.x - size.x - label_gap; - a.x2 = p2.x - label_gap; - } - else { - a.x1 = p2.x + label_gap; - a.x2 = p2.x + size.x + label_gap; - } - - if(a.y2 >= obj->coords.y1 && - a.y1 <= obj->coords.y2) { - lv_draw_label(draw_ctx, &label_dsc, &a, part_draw_dsc.text, NULL); - } - } - else { - part_draw_dsc.label_dsc = NULL; - part_draw_dsc.text = NULL; - part_draw_dsc.text_length = 0; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - } - - if(p1.y + line_dsc.width / 2 >= obj->coords.y1 && - p2.y - line_dsc.width / 2 <= obj->coords.y2) { - lv_draw_line(draw_ctx, &line_dsc, &p1, &p2); - } - - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } -} - -static void draw_x_ticks(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, lv_chart_axis_t axis) -{ - lv_chart_t * chart = (lv_chart_t *)obj; - - lv_chart_tick_dsc_t * t = get_tick_gsc(obj, axis); - if(t->major_cnt <= 1) return; - if(!t->label_en && !t->major_len && !t->minor_len) return; - uint32_t total_tick_num = (t->major_cnt - 1) * (t->minor_cnt); - if(total_tick_num == 0) return; - - uint32_t i; - lv_point_t p1; - lv_point_t p2; - - lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - - lv_draw_label_dsc_t label_dsc; - lv_draw_label_dsc_init(&label_dsc); - lv_obj_init_draw_label_dsc(obj, LV_PART_TICKS, &label_dsc); - - lv_coord_t x_ofs = obj->coords.x1 + pad_left - lv_obj_get_scroll_left(obj); - lv_coord_t y_ofs; - lv_coord_t label_gap; - if(axis == LV_CHART_AXIS_PRIMARY_X) { - label_gap = t->label_en ? lv_obj_get_style_pad_bottom(obj, LV_PART_TICKS) : 0; - y_ofs = obj->coords.y2 + 1; - } - else { - label_gap = t->label_en ? lv_obj_get_style_pad_top(obj, LV_PART_TICKS) : 0; - y_ofs = obj->coords.y1 - 1; - } - - if(axis == LV_CHART_AXIS_PRIMARY_X) { - if(y_ofs > draw_ctx->clip_area->y2) return; - if(y_ofs + label_gap + label_dsc.font->line_height + t->major_len < draw_ctx->clip_area->y1) return; - } - - lv_draw_line_dsc_t line_dsc; - lv_draw_line_dsc_init(&line_dsc); - lv_obj_init_draw_line_dsc(obj, LV_PART_TICKS, &line_dsc); - line_dsc.dash_gap = 0; - line_dsc.dash_width = 0; - - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_CHART_DRAW_PART_TICK_LABEL; - part_draw_dsc.id = LV_CHART_AXIS_PRIMARY_X; - part_draw_dsc.part = LV_PART_TICKS; - part_draw_dsc.label_dsc = &label_dsc; - part_draw_dsc.line_dsc = &line_dsc; - - uint8_t sec_axis = axis == LV_CHART_AXIS_PRIMARY_X ? 0 : 1; - - /*The columns ticks should be aligned to the center of blocks*/ - if(chart->type == LV_CHART_TYPE_BAR) { - int32_t block_gap = ((int32_t)lv_obj_get_style_pad_column(obj, - LV_PART_MAIN) * chart->zoom_x) >> 8; /*Gap between the columns on ~adjacent X*/ - lv_coord_t block_w = (w + block_gap) / (chart->point_cnt); - - x_ofs += (block_w - block_gap) / 2; - w -= block_w - block_gap; - } - - p1.y = y_ofs; - for(i = 0; i <= total_tick_num; i++) { /*one extra loop - it may not exist in the list, empty label*/ - bool major = false; - if(i % t->minor_cnt == 0) major = true; - - /*draw a line at moving x position*/ - p2.x = p1.x = x_ofs + (int32_t)((int32_t)(w - line_dsc.width) * i) / total_tick_num; - - if(sec_axis) p2.y = p1.y - (major ? t->major_len : t->minor_len); - else p2.y = p1.y + (major ? t->major_len : t->minor_len); - - part_draw_dsc.p1 = &p1; - part_draw_dsc.p2 = &p2; - - /*add text only to major tick*/ - int32_t tick_value; - if(chart->type == LV_CHART_TYPE_SCATTER) { - tick_value = lv_map(i, 0, total_tick_num, chart->xmin[sec_axis], chart->xmax[sec_axis]); - } - else { - tick_value = i / t->minor_cnt; - } - part_draw_dsc.value = tick_value; - - if(major && t->label_en) { - char buf[LV_CHART_LABEL_MAX_TEXT_LENGTH]; - lv_snprintf(buf, sizeof(buf), "%" LV_PRId32, tick_value); - part_draw_dsc.label_dsc = &label_dsc; - part_draw_dsc.text = buf; - part_draw_dsc.text_length = LV_CHART_LABEL_MAX_TEXT_LENGTH; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - - /*reserve appropriate area*/ - lv_point_t size; - lv_txt_get_size(&size, part_draw_dsc.text, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, LV_COORD_MAX, - LV_TEXT_FLAG_NONE); - - /*set the area at some distance of the major tick len under of the tick*/ - lv_area_t a; - a.x1 = (p2.x - size.x / 2); - a.x2 = (p2.x + size.x / 2); - if(sec_axis) { - a.y2 = p2.y - label_gap; - a.y1 = a.y2 - size.y; - } - else { - a.y1 = p2.y + label_gap; - a.y2 = a.y1 + size.y; - } - - if(a.x2 >= obj->coords.x1 && - a.x1 <= obj->coords.x2) { - lv_draw_label(draw_ctx, &label_dsc, &a, part_draw_dsc.text, NULL); - } - } - else { - part_draw_dsc.label_dsc = NULL; - part_draw_dsc.text = NULL; - part_draw_dsc.text_length = 0; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - } - - if(p1.x + line_dsc.width / 2 >= obj->coords.x1 && - p2.x - line_dsc.width / 2 <= obj->coords.x2) { - lv_draw_line(draw_ctx, &line_dsc, &p1, &p2); - } - - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } -} - -static void draw_axes(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) -{ - draw_y_ticks(obj, draw_ctx, LV_CHART_AXIS_PRIMARY_Y); - draw_y_ticks(obj, draw_ctx, LV_CHART_AXIS_SECONDARY_Y); - draw_x_ticks(obj, draw_ctx, LV_CHART_AXIS_PRIMARY_X); - draw_x_ticks(obj, draw_ctx, LV_CHART_AXIS_SECONDARY_X); -} - -/** - * Get the nearest index to an X coordinate - * @param chart pointer to a chart object - * @param coord the coordination of the point relative to the series area. - * @return the found index - */ -static uint32_t get_index_from_x(lv_obj_t * obj, lv_coord_t x) -{ - lv_chart_t * chart = (lv_chart_t *)obj; - lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - x -= pad_left; - - if(x < 0) return 0; - if(x > w) return chart->point_cnt - 1; - if(chart->type == LV_CHART_TYPE_LINE) return (x * (chart->point_cnt - 1) + w / 2) / w; - if(chart->type == LV_CHART_TYPE_BAR) return (x * chart->point_cnt) / w; - - return 0; -} - -static void invalidate_point(lv_obj_t * obj, uint16_t i) -{ - lv_chart_t * chart = (lv_chart_t *)obj; - if(i >= chart->point_cnt) return; - - lv_coord_t w = ((int32_t)lv_obj_get_content_width(obj) * chart->zoom_x) >> 8; - lv_coord_t scroll_left = lv_obj_get_scroll_left(obj); - - /*In shift mode the whole chart changes so the whole object*/ - if(chart->update_mode == LV_CHART_UPDATE_MODE_SHIFT) { - lv_obj_invalidate(obj); - return; - } - - if(chart->type == LV_CHART_TYPE_LINE) { - lv_coord_t bwidth = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t pleft = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t x_ofs = obj->coords.x1 + pleft + bwidth - scroll_left; - lv_coord_t line_width = lv_obj_get_style_line_width(obj, LV_PART_ITEMS); - lv_coord_t point_w = lv_obj_get_style_width(obj, LV_PART_INDICATOR); - - lv_area_t coords; - lv_area_copy(&coords, &obj->coords); - coords.y1 -= line_width + point_w; - coords.y2 += line_width + point_w; - - if(i < chart->point_cnt - 1) { - coords.x1 = ((w * i) / (chart->point_cnt - 1)) + x_ofs - line_width - point_w; - coords.x2 = ((w * (i + 1)) / (chart->point_cnt - 1)) + x_ofs + line_width + point_w; - lv_obj_invalidate_area(obj, &coords); - } - - if(i > 0) { - coords.x1 = ((w * (i - 1)) / (chart->point_cnt - 1)) + x_ofs - line_width - point_w; - coords.x2 = ((w * i) / (chart->point_cnt - 1)) + x_ofs + line_width + point_w; - lv_obj_invalidate_area(obj, &coords); - } - } - else if(chart->type == LV_CHART_TYPE_BAR) { - lv_area_t col_a; - int32_t block_gap = ((int32_t)lv_obj_get_style_pad_column(obj, - LV_PART_MAIN) * chart->zoom_x) >> 8; /*Gap between the column on ~adjacent X*/ - - lv_coord_t block_w = (w + block_gap) / chart->point_cnt; - - lv_coord_t bwidth = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t x_act; - x_act = (int32_t)((int32_t)(block_w) * i) ; - x_act += obj->coords.x1 + bwidth + lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - - lv_obj_get_coords(obj, &col_a); - col_a.x1 = x_act - scroll_left; - col_a.x2 = col_a.x1 + block_w; - col_a.x1 -= block_gap; - - lv_obj_invalidate_area(obj, &col_a); - } - else { - lv_obj_invalidate(obj); - } -} - -static void new_points_alloc(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t cnt, lv_coord_t ** a) -{ - if((*a) == NULL) return; - - lv_chart_t * chart = (lv_chart_t *) obj; - uint32_t point_cnt_old = chart->point_cnt; - uint32_t i; - - if(ser->start_point != 0) { - lv_coord_t * new_points = lv_mem_alloc(sizeof(lv_coord_t) * cnt); - LV_ASSERT_MALLOC(new_points); - if(new_points == NULL) return; - - if(cnt >= point_cnt_old) { - for(i = 0; i < point_cnt_old; i++) { - new_points[i] = - (*a)[(i + ser->start_point) % point_cnt_old]; /*Copy old contents to new array*/ - } - for(i = point_cnt_old; i < cnt; i++) { - new_points[i] = LV_CHART_POINT_NONE; /*Fill up the rest with default value*/ - } - } - else { - for(i = 0; i < cnt; i++) { - new_points[i] = - (*a)[(i + ser->start_point) % point_cnt_old]; /*Copy old contents to new array*/ - } - } - - /*Switch over pointer from old to new*/ - lv_mem_free((*a)); - (*a) = new_points; - } - else { - (*a) = lv_mem_realloc((*a), sizeof(lv_coord_t) * cnt); - LV_ASSERT_MALLOC((*a)); - if((*a) == NULL) return; - /*Initialize the new points*/ - if(cnt > point_cnt_old) { - for(i = point_cnt_old - 1; i < cnt; i++) { - (*a)[i] = LV_CHART_POINT_NONE; - } - } - } -} - -lv_chart_tick_dsc_t * get_tick_gsc(lv_obj_t * obj, lv_chart_axis_t axis) -{ - lv_chart_t * chart = (lv_chart_t *) obj; - switch(axis) { - case LV_CHART_AXIS_PRIMARY_Y: - return &chart->tick[0]; - case LV_CHART_AXIS_PRIMARY_X: - return &chart->tick[1]; - case LV_CHART_AXIS_SECONDARY_Y: - return &chart->tick[2]; - case LV_CHART_AXIS_SECONDARY_X: - return &chart->tick[3]; - default: - return NULL; - } -} - - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.c deleted file mode 100644 index daf112e93..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.c +++ /dev/null @@ -1,713 +0,0 @@ -/** - * @file lv_colorwheel.c - * - * Based on the work of @AloyseTech and @paulpv. - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_colorwheel.h" -#if LV_USE_COLORWHEEL - -#include "../../../misc/lv_assert.h" - -/********************* - * DEFINES - *********************/ -#define MY_CLASS &lv_colorwheel_class - -#define LV_CPICKER_DEF_QF 3 - -/** - * The OUTER_MASK_WIDTH define is required to assist with the placing of a mask over the outer ring of the widget as when the - * multicoloured radial lines are calculated for the outer ring of the widget their lengths are jittering because of the - * integer based arithmetic. From tests the maximum delta was found to be 2 so the current value is set to 3 to achieve - * appropriate masking. - */ -#define OUTER_MASK_WIDTH 3 - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void lv_colorwheel_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void lv_colorwheel_event(const lv_obj_class_t * class_p, lv_event_t * e); - -static void draw_disc_grad(lv_event_t * e); -static void draw_knob(lv_event_t * e); -static void invalidate_knob(lv_obj_t * obj); -static lv_area_t get_knob_area(lv_obj_t * obj); - -static void next_color_mode(lv_obj_t * obj); -static lv_res_t double_click_reset(lv_obj_t * obj); -static void refr_knob_pos(lv_obj_t * obj); -static lv_color_t angle_to_mode_color_fast(lv_obj_t * obj, uint16_t angle); -static uint16_t get_angle(lv_obj_t * obj); - -/********************** - * STATIC VARIABLES - **********************/ -const lv_obj_class_t lv_colorwheel_class = {.instance_size = sizeof(lv_colorwheel_t), .base_class = &lv_obj_class, - .constructor_cb = lv_colorwheel_constructor, - .event_cb = lv_colorwheel_event, - .width_def = LV_DPI_DEF * 2, - .height_def = LV_DPI_DEF * 2, - .editable = LV_OBJ_CLASS_EDITABLE_TRUE, - }; - -static bool create_knob_recolor; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create a color_picker object - * @param parent pointer to an object, it will be the parent of the new color_picker - * @return pointer to the created color_picker - */ -lv_obj_t * lv_colorwheel_create(lv_obj_t * parent, bool knob_recolor) -{ - LV_LOG_INFO("begin"); - create_knob_recolor = knob_recolor; - - lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); - lv_obj_class_init_obj(obj); - return obj; -} - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the current hsv of a color wheel. - * @param colorwheel pointer to color wheel object - * @param color current selected hsv - * @return true if changed, otherwise false - */ -bool lv_colorwheel_set_hsv(lv_obj_t * obj, lv_color_hsv_t hsv) -{ - if(hsv.h > 360) hsv.h %= 360; - if(hsv.s > 100) hsv.s = 100; - if(hsv.v > 100) hsv.v = 100; - - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; - - if(colorwheel->hsv.h == hsv.h && colorwheel->hsv.s == hsv.s && colorwheel->hsv.v == hsv.v) return false; - - colorwheel->hsv = hsv; - - refr_knob_pos(obj); - - lv_obj_invalidate(obj); - - return true; -} - -/** - * Set the current color of a color wheel. - * @param colorwheel pointer to color wheel object - * @param color current selected color - * @return true if changed, otherwise false - */ -bool lv_colorwheel_set_rgb(lv_obj_t * obj, lv_color_t color) -{ - lv_color32_t c32; - c32.full = lv_color_to32(color); - - return lv_colorwheel_set_hsv(obj, lv_color_rgb_to_hsv(c32.ch.red, c32.ch.green, c32.ch.blue)); -} - -/** - * Set the current color mode. - * @param colorwheel pointer to color wheel object - * @param mode color mode (hue/sat/val) - */ -void lv_colorwheel_set_mode(lv_obj_t * obj, lv_colorwheel_mode_t mode) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; - - colorwheel->mode = mode; - refr_knob_pos(obj); - lv_obj_invalidate(obj); -} - -/** - * Set if the color mode is changed on long press on center - * @param colorwheel pointer to color wheel object - * @param fixed color mode cannot be changed on long press - */ -void lv_colorwheel_set_mode_fixed(lv_obj_t * obj, bool fixed) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; - - colorwheel->mode_fixed = fixed; -} - -/*===================== - * Getter functions - *====================*/ - - -/** - * Get the current selected hsv of a color wheel. - * @param colorwheel pointer to color wheel object - * @return current selected hsv - */ -lv_color_hsv_t lv_colorwheel_get_hsv(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; - - return colorwheel->hsv; -} - -/** - * Get the current selected color of a color wheel. - * @param colorwheel pointer to color wheel object - * @return color current selected color - */ -lv_color_t lv_colorwheel_get_rgb(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; - - return lv_color_hsv_to_rgb(colorwheel->hsv.h, colorwheel->hsv.s, colorwheel->hsv.v); -} - -/** - * Get the current color mode. - * @param colorwheel pointer to color wheel object - * @return color mode (hue/sat/val) - */ -lv_colorwheel_mode_t lv_colorwheel_get_color_mode(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; - - return colorwheel->mode; -} - -/** - * Get if the color mode is changed on long press on center - * @param colorwheel pointer to color wheel object - * @return mode cannot be changed on long press - */ -bool lv_colorwheel_get_color_mode_fixed(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; - - return colorwheel->mode_fixed; -} - -/*===================== - * Other functions - *====================*/ - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void lv_colorwheel_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) -{ - LV_UNUSED(class_p); - lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; - colorwheel->hsv.h = 0; - colorwheel->hsv.s = 100; - colorwheel->hsv.v = 100; - colorwheel->mode = LV_COLORWHEEL_MODE_HUE; - colorwheel->mode_fixed = 0; - colorwheel->last_click_time = 0; - colorwheel->last_change_time = 0; - colorwheel->knob.recolor = create_knob_recolor; - - lv_obj_add_flag(obj, LV_OBJ_FLAG_ADV_HITTEST); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN); - refr_knob_pos(obj); -} - -static void draw_disc_grad(lv_event_t * e) -{ - lv_obj_t * obj = lv_event_get_target(e); - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); - lv_coord_t w = lv_obj_get_width(obj); - lv_coord_t h = lv_obj_get_height(obj); - lv_coord_t cx = obj->coords.x1 + w / 2; - lv_coord_t cy = obj->coords.y1 + h / 2; - lv_coord_t r = w / 2; - - lv_draw_line_dsc_t line_dsc; - lv_draw_line_dsc_init(&line_dsc); - lv_obj_init_draw_line_dsc(obj, LV_PART_MAIN, &line_dsc); - - line_dsc.width = (r * 628 / (256 / LV_CPICKER_DEF_QF)) / 100; - line_dsc.width += 2; - uint16_t i; - uint32_t a = 0; - lv_coord_t cir_w = lv_obj_get_style_arc_width(obj, LV_PART_MAIN); - -#if LV_DRAW_COMPLEX - /*Mask outer and inner ring of widget to tidy up ragged edges of lines while drawing outer ring*/ - lv_draw_mask_radius_param_t mask_out_param; - lv_draw_mask_radius_init(&mask_out_param, &obj->coords, LV_RADIUS_CIRCLE, false); - int16_t mask_out_id = lv_draw_mask_add(&mask_out_param, 0); - - lv_area_t mask_area; - lv_area_copy(&mask_area, &obj->coords); - mask_area.x1 += cir_w; - mask_area.x2 -= cir_w; - mask_area.y1 += cir_w; - mask_area.y2 -= cir_w; - lv_draw_mask_radius_param_t mask_in_param; - lv_draw_mask_radius_init(&mask_in_param, &mask_area, LV_RADIUS_CIRCLE, true); - int16_t mask_in_id = lv_draw_mask_add(&mask_in_param, 0); - - /*The inner and outer line ends will be masked out. - *So make lines a little bit longer because the masking makes a more even result*/ - lv_coord_t cir_w_extra = line_dsc.width; -#else - lv_coord_t cir_w_extra = 0; -#endif - - for(i = 0; i <= 256; i += LV_CPICKER_DEF_QF, a += 360 * LV_CPICKER_DEF_QF) { - line_dsc.color = angle_to_mode_color_fast(obj, i); - uint16_t angle_trigo = (uint16_t)(a >> 8); /*i * 360 / 256 is the scale to apply, but we can skip multiplication here*/ - - lv_point_t p[2]; - p[0].x = cx + ((r + cir_w_extra) * lv_trigo_sin(angle_trigo) >> LV_TRIGO_SHIFT); - p[0].y = cy + ((r + cir_w_extra) * lv_trigo_cos(angle_trigo) >> LV_TRIGO_SHIFT); - p[1].x = cx + ((r - cir_w - cir_w_extra) * lv_trigo_sin(angle_trigo) >> LV_TRIGO_SHIFT); - p[1].y = cy + ((r - cir_w - cir_w_extra) * lv_trigo_cos(angle_trigo) >> LV_TRIGO_SHIFT); - - lv_draw_line(draw_ctx, &line_dsc, &p[0], &p[1]); - } - -#if LV_DRAW_COMPLEX - lv_draw_mask_free_param(&mask_out_param); - lv_draw_mask_free_param(&mask_in_param); - lv_draw_mask_remove_id(mask_out_id); - lv_draw_mask_remove_id(mask_in_id); -#endif -} - -static void draw_knob(lv_event_t * e) -{ - lv_obj_t * obj = lv_event_get_target(e); - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); - lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; - - lv_draw_rect_dsc_t cir_dsc; - lv_draw_rect_dsc_init(&cir_dsc); - lv_obj_init_draw_rect_dsc(obj, LV_PART_KNOB, &cir_dsc); - - cir_dsc.radius = LV_RADIUS_CIRCLE; - - if(colorwheel->knob.recolor) { - cir_dsc.bg_color = lv_colorwheel_get_rgb(obj); - } - - lv_area_t knob_area = get_knob_area(obj); - - lv_draw_rect(draw_ctx, &cir_dsc, &knob_area); -} - -static void invalidate_knob(lv_obj_t * obj) -{ - lv_area_t knob_area = get_knob_area(obj); - - lv_obj_invalidate_area(obj, &knob_area); -} - -static lv_area_t get_knob_area(lv_obj_t * obj) -{ - lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; - - /*Get knob's radius*/ - uint16_t r = 0; - r = lv_obj_get_style_arc_width(obj, LV_PART_MAIN) / 2; - - lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); - lv_coord_t right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); - lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); - lv_coord_t bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); - - lv_area_t knob_area; - knob_area.x1 = obj->coords.x1 + colorwheel->knob.pos.x - r - left; - knob_area.y1 = obj->coords.y1 + colorwheel->knob.pos.y - r - right; - knob_area.x2 = obj->coords.x1 + colorwheel->knob.pos.x + r + top; - knob_area.y2 = obj->coords.y1 + colorwheel->knob.pos.y + r + bottom; - - return knob_area; -} - -static void lv_colorwheel_event(const lv_obj_class_t * class_p, lv_event_t * e) -{ - LV_UNUSED(class_p); - - /*Call the ancestor's event handler*/ - lv_res_t res = lv_obj_event_base(MY_CLASS, e); - - if(res != LV_RES_OK) return; - - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); - lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; - - if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); - lv_coord_t right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); - lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); - lv_coord_t bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); - - lv_coord_t knob_pad = LV_MAX4(left, right, top, bottom) + 2; - lv_coord_t * s = lv_event_get_param(e); - *s = LV_MAX(*s, knob_pad); - } - else if(code == LV_EVENT_SIZE_CHANGED) { - void * param = lv_event_get_param(e); - /*Refresh extended draw area to make knob visible*/ - if(lv_obj_get_width(obj) != lv_area_get_width(param) || - lv_obj_get_height(obj) != lv_area_get_height(param)) { - refr_knob_pos(obj); - } - } - else if(code == LV_EVENT_STYLE_CHANGED) { - /*Refresh extended draw area to make knob visible*/ - refr_knob_pos(obj); - } - else if(code == LV_EVENT_KEY) { - uint32_t c = *((uint32_t *)lv_event_get_param(e)); /*uint32_t because can be UTF-8*/ - - if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { - lv_color_hsv_t hsv_cur; - hsv_cur = colorwheel->hsv; - - switch(colorwheel->mode) { - case LV_COLORWHEEL_MODE_HUE: - hsv_cur.h = (colorwheel->hsv.h + 1) % 360; - break; - case LV_COLORWHEEL_MODE_SATURATION: - hsv_cur.s = (colorwheel->hsv.s + 1) % 100; - break; - case LV_COLORWHEEL_MODE_VALUE: - hsv_cur.v = (colorwheel->hsv.v + 1) % 100; - break; - } - - if(lv_colorwheel_set_hsv(obj, hsv_cur)) { - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; - } - } - else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { - lv_color_hsv_t hsv_cur; - hsv_cur = colorwheel->hsv; - - switch(colorwheel->mode) { - case LV_COLORWHEEL_MODE_HUE: - hsv_cur.h = colorwheel->hsv.h > 0 ? (colorwheel->hsv.h - 1) : 360; - break; - case LV_COLORWHEEL_MODE_SATURATION: - hsv_cur.s = colorwheel->hsv.s > 0 ? (colorwheel->hsv.s - 1) : 100; - break; - case LV_COLORWHEEL_MODE_VALUE: - hsv_cur.v = colorwheel->hsv.v > 0 ? (colorwheel->hsv.v - 1) : 100; - break; - } - - if(lv_colorwheel_set_hsv(obj, hsv_cur)) { - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; - } - } - } - else if(code == LV_EVENT_PRESSED) { - colorwheel->last_change_time = lv_tick_get(); - lv_indev_get_point(lv_indev_get_act(), &colorwheel->last_press_point); - res = double_click_reset(obj); - if(res != LV_RES_OK) return; - } - else if(code == LV_EVENT_PRESSING) { - lv_indev_t * indev = lv_indev_get_act(); - if(indev == NULL) return; - - lv_indev_type_t indev_type = lv_indev_get_type(indev); - lv_point_t p; - if(indev_type == LV_INDEV_TYPE_ENCODER || indev_type == LV_INDEV_TYPE_KEYPAD) { - p.x = obj->coords.x1 + lv_obj_get_width(obj) / 2; - p.y = obj->coords.y1 + lv_obj_get_height(obj) / 2; - } - else { - lv_indev_get_point(indev, &p); - } - - lv_coord_t drag_limit = indev->driver->scroll_limit; - if((LV_ABS(p.x - colorwheel->last_press_point.x) > drag_limit) || - (LV_ABS(p.y - colorwheel->last_press_point.y) > drag_limit)) { - colorwheel->last_change_time = lv_tick_get(); - colorwheel->last_press_point.x = p.x; - colorwheel->last_press_point.y = p.y; - } - - p.x -= obj->coords.x1; - p.y -= obj->coords.y1; - - /*Ignore pressing in the inner area*/ - uint16_t w = lv_obj_get_width(obj); - - int16_t angle = 0; - lv_coord_t cir_w = lv_obj_get_style_arc_width(obj, LV_PART_MAIN); - - lv_coord_t r_in = w / 2; - p.x -= r_in; - p.y -= r_in; - bool on_ring = true; - r_in -= cir_w; - if(r_in > LV_DPI_DEF / 2) { - lv_coord_t inner = cir_w / 2; - r_in -= inner; - - if(r_in < LV_DPI_DEF / 2) r_in = LV_DPI_DEF / 2; - } - - if(p.x * p.x + p.y * p.y < r_in * r_in) { - on_ring = false; - } - - /*If the inner area is being pressed, go to the next color mode on long press*/ - uint32_t diff = lv_tick_elaps(colorwheel->last_change_time); - if(!on_ring && diff > indev->driver->long_press_time && !colorwheel->mode_fixed) { - next_color_mode(obj); - lv_indev_wait_release(lv_indev_get_act()); - return; - } - - /*Set the angle only if pressed on the ring*/ - if(!on_ring) return; - - angle = lv_atan2(p.x, p.y) % 360; - - lv_color_hsv_t hsv_cur; - hsv_cur = colorwheel->hsv; - - switch(colorwheel->mode) { - case LV_COLORWHEEL_MODE_HUE: - hsv_cur.h = angle; - break; - case LV_COLORWHEEL_MODE_SATURATION: - hsv_cur.s = (angle * 100) / 360; - break; - case LV_COLORWHEEL_MODE_VALUE: - hsv_cur.v = (angle * 100) / 360; - break; - } - - if(lv_colorwheel_set_hsv(obj, hsv_cur)) { - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; - } - } - else if(code == LV_EVENT_HIT_TEST) { - lv_hit_test_info_t * info = lv_event_get_param(e);; - - /*Valid clicks can be only in the circle*/ - info->res = _lv_area_is_point_on(&obj->coords, info->point, LV_RADIUS_CIRCLE); - } - else if(code == LV_EVENT_DRAW_MAIN) { - draw_disc_grad(e); - draw_knob(e); - } - else if(code == LV_EVENT_COVER_CHECK) { - lv_cover_check_info_t * info = lv_event_get_param(e); - if(info->res != LV_COVER_RES_MASKED) info->res = LV_COVER_RES_NOT_COVER; - } -} - - - -static void next_color_mode(lv_obj_t * obj) -{ - lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; - colorwheel->mode = (colorwheel->mode + 1) % 3; - refr_knob_pos(obj); - lv_obj_invalidate(obj); -} - -static void refr_knob_pos(lv_obj_t * obj) -{ - invalidate_knob(obj); - - lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; - lv_coord_t w = lv_obj_get_width(obj); - - lv_coord_t scale_w = lv_obj_get_style_arc_width(obj, LV_PART_MAIN); - lv_coord_t r = (w - scale_w) / 2; - uint16_t angle = get_angle(obj); - colorwheel->knob.pos.x = (((int32_t)r * lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT); - colorwheel->knob.pos.y = (((int32_t)r * lv_trigo_cos(angle)) >> LV_TRIGO_SHIFT); - colorwheel->knob.pos.x = colorwheel->knob.pos.x + w / 2; - colorwheel->knob.pos.y = colorwheel->knob.pos.y + w / 2; - - invalidate_knob(obj); -} - -static lv_res_t double_click_reset(lv_obj_t * obj) -{ - lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; - lv_indev_t * indev = lv_indev_get_act(); - /*Double clicked? Use long press time as double click time out*/ - if(lv_tick_elaps(colorwheel->last_click_time) < indev->driver->long_press_time) { - lv_color_hsv_t hsv_cur; - hsv_cur = colorwheel->hsv; - - switch(colorwheel->mode) { - case LV_COLORWHEEL_MODE_HUE: - hsv_cur.h = 0; - break; - case LV_COLORWHEEL_MODE_SATURATION: - hsv_cur.s = 100; - break; - case LV_COLORWHEEL_MODE_VALUE: - hsv_cur.v = 100; - break; - } - - lv_indev_wait_release(indev); - - if(lv_colorwheel_set_hsv(obj, hsv_cur)) { - lv_res_t res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - } - colorwheel->last_click_time = lv_tick_get(); - - return LV_RES_OK; -} - -#define SWAPPTR(A, B) do { uint8_t * t = A; A = B; B = t; } while(0) -#define HSV_PTR_SWAP(sextant,r,g,b) if((sextant) & 2) { SWAPPTR((r), (b)); } if((sextant) & 4) { SWAPPTR((g), (b)); } if(!((sextant) & 6)) { \ - if(!((sextant) & 1)) { SWAPPTR((r), (g)); } } else { if((sextant) & 1) { SWAPPTR((r), (g)); } } - -/** - * Based on the idea from https://www.vagrearg.org/content/hsvrgb - * Here we want to compute an approximate RGB value from a HSV input color space. We don't want to be accurate - * (for that, there's lv_color_hsv_to_rgb), but we want to be fast. - * - * Few tricks are used here: Hue is in range [0; 6 * 256] (so that the sextant is in the high byte and the fractional part is in the low byte) - * both s and v are in [0; 255] range (very convenient to avoid divisions). - * - * We fold all symmetry by swapping the R, G, B pointers so that the code is the same for all sextants. - * We replace division by 255 by a division by 256, a.k.a a shift right by 8 bits. - * This is wrong, but since this is only used to compute the pixels on the screen and not the final color, it's ok. - */ -static void fast_hsv2rgb(uint16_t h, uint8_t s, uint8_t v, uint8_t * r, uint8_t * g, uint8_t * b) -{ - if(!s) { - *r = *g = *b = v; - return; - } - - uint8_t sextant = h >> 8; - HSV_PTR_SWAP(sextant, r, g, b); /*Swap pointers so the conversion code is the same*/ - - *g = v; - - uint8_t bb = ~s; - uint16_t ww = v * bb; /*Don't try to be precise, but instead, be fast*/ - *b = ww >> 8; - - uint8_t h_frac = h & 0xff; - - if(!(sextant & 1)) { - /*Up slope*/ - ww = !h_frac ? ((uint16_t)s << 8) : (s * (uint8_t)(-h_frac)); /*Skip multiply if not required*/ - } - else { - /*Down slope*/ - ww = s * h_frac; - } - bb = ww >> 8; - bb = ~bb; - ww = v * bb; - *r = ww >> 8; -} - -static lv_color_t angle_to_mode_color_fast(lv_obj_t * obj, uint16_t angle) -{ - lv_colorwheel_t * ext = (lv_colorwheel_t *)obj; - uint8_t r = 0, g = 0, b = 0; - static uint16_t h = 0; - static uint8_t s = 0, v = 0, m = 255; - static uint16_t angle_saved = 0xffff; - - /*If the angle is different recalculate scaling*/ - if(angle_saved != angle) m = 255; - angle_saved = angle; - - switch(ext->mode) { - default: - case LV_COLORWHEEL_MODE_HUE: - /*Don't recompute costly scaling if it does not change*/ - if(m != ext->mode) { - s = (uint8_t)(((uint16_t)ext->hsv.s * 51) / 20); - v = (uint8_t)(((uint16_t)ext->hsv.v * 51) / 20); - m = ext->mode; - } - fast_hsv2rgb(angle * 6, s, v, &r, &g, - &b); /*A smart compiler will replace x * 6 by (x << 2) + (x << 1) if it's more efficient*/ - break; - case LV_COLORWHEEL_MODE_SATURATION: - /*Don't recompute costly scaling if it does not change*/ - if(m != ext->mode) { - h = (uint16_t)(((uint32_t)ext->hsv.h * 6 * 256) / 360); - v = (uint8_t)(((uint16_t)ext->hsv.v * 51) / 20); - m = ext->mode; - } - fast_hsv2rgb(h, angle, v, &r, &g, &b); - break; - case LV_COLORWHEEL_MODE_VALUE: - /*Don't recompute costly scaling if it does not change*/ - if(m != ext->mode) { - h = (uint16_t)(((uint32_t)ext->hsv.h * 6 * 256) / 360); - s = (uint8_t)(((uint16_t)ext->hsv.s * 51) / 20); - m = ext->mode; - } - fast_hsv2rgb(h, s, angle, &r, &g, &b); - break; - } - return lv_color_make(r, g, b); -} - -static uint16_t get_angle(lv_obj_t * obj) -{ - lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj; - uint16_t angle; - switch(colorwheel->mode) { - default: - case LV_COLORWHEEL_MODE_HUE: - angle = colorwheel->hsv.h; - break; - case LV_COLORWHEEL_MODE_SATURATION: - angle = (colorwheel->hsv.s * 360) / 100; - break; - case LV_COLORWHEEL_MODE_VALUE: - angle = (colorwheel->hsv.v * 360) / 100 ; - break; - } - return angle; -} - -#endif /*LV_USE_COLORWHEEL*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.h deleted file mode 100644 index e9c9d92ee..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/colorwheel/lv_colorwheel.h +++ /dev/null @@ -1,142 +0,0 @@ -/** - * @file lv_colorwheel.h - * - */ - -#ifndef LV_COLORWHEEL_H -#define LV_COLORWHEEL_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../../lvgl.h" - -#if LV_USE_COLORWHEEL - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -enum { - LV_COLORWHEEL_MODE_HUE, - LV_COLORWHEEL_MODE_SATURATION, - LV_COLORWHEEL_MODE_VALUE -}; -typedef uint8_t lv_colorwheel_mode_t; - - -/*Data of color picker*/ -typedef struct { - lv_obj_t obj; - lv_color_hsv_t hsv; - struct { - lv_point_t pos; - uint8_t recolor : 1; - } knob; - uint32_t last_click_time; - uint32_t last_change_time; - lv_point_t last_press_point; - lv_colorwheel_mode_t mode : 2; - uint8_t mode_fixed : 1; -} lv_colorwheel_t; - -extern const lv_obj_class_t lv_colorwheel_class; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a color picker object with disc shape - * @param parent pointer to an object, it will be the parent of the new color picker - * @param knob_recolor true: set the knob's color to the current color - * @return pointer to the created color picker - */ -lv_obj_t * lv_colorwheel_create(lv_obj_t * parent, bool knob_recolor); - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the current hsv of a color wheel. - * @param colorwheel pointer to color wheel object - * @param color current selected hsv - * @return true if changed, otherwise false - */ -bool lv_colorwheel_set_hsv(lv_obj_t * obj, lv_color_hsv_t hsv); - -/** - * Set the current color of a color wheel. - * @param colorwheel pointer to color wheel object - * @param color current selected color - * @return true if changed, otherwise false - */ -bool lv_colorwheel_set_rgb(lv_obj_t * obj, lv_color_t color); - -/** - * Set the current color mode. - * @param colorwheel pointer to color wheel object - * @param mode color mode (hue/sat/val) - */ -void lv_colorwheel_set_mode(lv_obj_t * obj, lv_colorwheel_mode_t mode); - -/** - * Set if the color mode is changed on long press on center - * @param colorwheel pointer to color wheel object - * @param fixed color mode cannot be changed on long press - */ -void lv_colorwheel_set_mode_fixed(lv_obj_t * obj, bool fixed); - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the current selected hsv of a color wheel. - * @param colorwheel pointer to color wheel object - * @return current selected hsv - */ -lv_color_hsv_t lv_colorwheel_get_hsv(lv_obj_t * obj); - -/** - * Get the current selected color of a color wheel. - * @param colorwheel pointer to color wheel object - * @return color current selected color - */ -lv_color_t lv_colorwheel_get_rgb(lv_obj_t * obj); - -/** - * Get the current color mode. - * @param colorwheel pointer to color wheel object - * @return color mode (hue/sat/val) - */ -lv_colorwheel_mode_t lv_colorwheel_get_color_mode(lv_obj_t * obj); - -/** - * Get if the color mode is changed on long press on center - * @param colorwheel pointer to color wheel object - * @return mode cannot be changed on long press - */ -bool lv_colorwheel_get_color_mode_fixed(lv_obj_t * obj); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_COLORWHEEL*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_COLORWHEEL_H*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.c deleted file mode 100644 index 06c68fb65..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.c +++ /dev/null @@ -1,386 +0,0 @@ -/** - * @file lv_imgbtn.c - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "lv_imgbtn.h" - -#if LV_USE_IMGBTN != 0 - -/********************* - * DEFINES - *********************/ -#define MY_CLASS &lv_imgbtn_class - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void lv_imgbtn_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void draw_main(lv_event_t * e); -static void lv_imgbtn_event(const lv_obj_class_t * class_p, lv_event_t * e); -static void refr_img(lv_obj_t * imgbtn); -static lv_imgbtn_state_t suggest_state(lv_obj_t * imgbtn, lv_imgbtn_state_t state); -lv_imgbtn_state_t get_state(const lv_obj_t * imgbtn); - -/********************** - * STATIC VARIABLES - **********************/ -const lv_obj_class_t lv_imgbtn_class = { - .base_class = &lv_obj_class, - .instance_size = sizeof(lv_imgbtn_t), - .constructor_cb = lv_imgbtn_constructor, - .event_cb = lv_imgbtn_event, -}; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Create an image button object - * @param parent pointer to an object, it will be the parent of the new image button - * @return pointer to the created image button - */ -lv_obj_t * lv_imgbtn_create(lv_obj_t * parent) -{ - LV_LOG_INFO("begin"); - lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); - lv_obj_class_init_obj(obj); - return obj; -} - -/*===================== - * Setter functions - *====================*/ - -/** - * Set images for a state of the image button - * @param obj pointer to an image button object - * @param state for which state set the new image - * @param src_left pointer to an image source for the left side of the button (a C array or path to - * a file) - * @param src_mid pointer to an image source for the middle of the button (ideally 1px wide) (a C - * array or path to a file) - * @param src_right pointer to an image source for the right side of the button (a C array or path - * to a file) - */ -void lv_imgbtn_set_src(lv_obj_t * obj, lv_imgbtn_state_t state, const void * src_left, const void * src_mid, - const void * src_right) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_imgbtn_t * imgbtn = (lv_imgbtn_t *)obj; - - imgbtn->img_src_left[state] = src_left; - imgbtn->img_src_mid[state] = src_mid; - imgbtn->img_src_right[state] = src_right; - - refr_img(obj); -} - -void lv_imgbtn_set_state(lv_obj_t * obj, lv_imgbtn_state_t state) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_state_t obj_state = LV_STATE_DEFAULT; - if(state == LV_IMGBTN_STATE_PRESSED || state == LV_IMGBTN_STATE_CHECKED_PRESSED) obj_state |= LV_STATE_PRESSED; - if(state == LV_IMGBTN_STATE_DISABLED || state == LV_IMGBTN_STATE_CHECKED_DISABLED) obj_state |= LV_STATE_DISABLED; - if(state == LV_IMGBTN_STATE_CHECKED_DISABLED || state == LV_IMGBTN_STATE_CHECKED_PRESSED || - state == LV_IMGBTN_STATE_CHECKED_RELEASED) { - obj_state |= LV_STATE_CHECKED; - } - - lv_obj_clear_state(obj, LV_STATE_CHECKED | LV_STATE_PRESSED | LV_STATE_DISABLED); - lv_obj_add_state(obj, obj_state); - - refr_img(obj); -} - -/*===================== - * Getter functions - *====================*/ - - -/** - * Get the left image in a given state - * @param obj pointer to an image button object - * @param state the state where to get the image (from `lv_btn_state_t`) ` - * @return pointer to the left image source (a C array or path to a file) - */ -const void * lv_imgbtn_get_src_left(lv_obj_t * obj, lv_imgbtn_state_t state) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_imgbtn_t * imgbtn = (lv_imgbtn_t *)obj; - - return imgbtn->img_src_left[state]; -} - -/** - * Get the middle image in a given state - * @param obj pointer to an image button object - * @param state the state where to get the image (from `lv_btn_state_t`) ` - * @return pointer to the middle image source (a C array or path to a file) - */ -const void * lv_imgbtn_get_src_middle(lv_obj_t * obj, lv_imgbtn_state_t state) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_imgbtn_t * imgbtn = (lv_imgbtn_t *)obj; - - return imgbtn->img_src_mid[state]; -} - -/** - * Get the right image in a given state - * @param obj pointer to an image button object - * @param state the state where to get the image (from `lv_btn_state_t`) ` - * @return pointer to the left image source (a C array or path to a file) - */ -const void * lv_imgbtn_get_src_right(lv_obj_t * obj, lv_imgbtn_state_t state) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_imgbtn_t * imgbtn = (lv_imgbtn_t *)obj; - - return imgbtn->img_src_right[state]; -} - - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void lv_imgbtn_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) -{ - LV_UNUSED(class_p); - lv_imgbtn_t * imgbtn = (lv_imgbtn_t *)obj; - /*Initialize the allocated 'ext'*/ - lv_memset_00((void *)imgbtn->img_src_mid, sizeof(imgbtn->img_src_mid)); - lv_memset_00(imgbtn->img_src_left, sizeof(imgbtn->img_src_left)); - lv_memset_00(imgbtn->img_src_right, sizeof(imgbtn->img_src_right)); - - imgbtn->act_cf = LV_IMG_CF_UNKNOWN; -} - - -static void lv_imgbtn_event(const lv_obj_class_t * class_p, lv_event_t * e) -{ - LV_UNUSED(class_p); - - lv_res_t res = lv_obj_event_base(&lv_imgbtn_class, e); - if(res != LV_RES_OK) return; - - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); - if(code == LV_EVENT_PRESSED || code == LV_EVENT_RELEASED || code == LV_EVENT_PRESS_LOST) { - refr_img(obj); - } - else if(code == LV_EVENT_DRAW_MAIN) { - draw_main(e); - } - else if(code == LV_EVENT_COVER_CHECK) { - lv_cover_check_info_t * info = lv_event_get_param(e); - if(info->res != LV_COVER_RES_MASKED) info->res = LV_COVER_RES_NOT_COVER; - } - else if(code == LV_EVENT_GET_SELF_SIZE) { - lv_point_t * p = lv_event_get_self_size_info(e); - lv_imgbtn_t * imgbtn = (lv_imgbtn_t *)obj; - lv_imgbtn_state_t state = suggest_state(obj, get_state(obj)); - if(imgbtn->img_src_left[state] == NULL && - imgbtn->img_src_mid[state] != NULL && - imgbtn->img_src_right[state] == NULL) { - lv_img_header_t header; - lv_img_decoder_get_info(imgbtn->img_src_mid[state], &header); - p->x = LV_MAX(p->x, header.w); - } - } - /*Sent when the widget is checked due to LV_OBJ_FLAG_CHECKABLE */ - else if(code == LV_EVENT_VALUE_CHANGED) { - if(lv_obj_has_state(obj, LV_STATE_CHECKED)) { - lv_imgbtn_set_state(obj, LV_IMGBTN_STATE_CHECKED_RELEASED); - } - else { - lv_imgbtn_set_state(obj, LV_IMGBTN_STATE_RELEASED); - } - } -} - -static void draw_main(lv_event_t * e) -{ - lv_obj_t * obj = lv_event_get_target(e); - lv_imgbtn_t * imgbtn = (lv_imgbtn_t *)obj; - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); - - /*Just draw_main an image*/ - lv_imgbtn_state_t state = suggest_state(obj, get_state(obj)); - - /*Simply draw the middle src if no tiled*/ - const void * src = imgbtn->img_src_left[state]; - - lv_coord_t tw = lv_obj_get_style_transform_width(obj, LV_PART_MAIN); - lv_coord_t th = lv_obj_get_style_transform_height(obj, LV_PART_MAIN); - lv_area_t coords; - lv_area_copy(&coords, &obj->coords); - coords.x1 -= tw; - coords.x2 += tw; - coords.y1 -= th; - coords.y2 += th; - - lv_draw_img_dsc_t img_dsc; - lv_draw_img_dsc_init(&img_dsc); - lv_obj_init_draw_img_dsc(obj, LV_PART_MAIN, &img_dsc); - - lv_img_header_t header; - lv_area_t coords_part; - lv_coord_t left_w = 0; - lv_coord_t right_w = 0; - - if(src) { - lv_img_decoder_get_info(src, &header); - left_w = header.w; - coords_part.x1 = coords.x1; - coords_part.y1 = coords.y1; - coords_part.x2 = coords.x1 + header.w - 1; - coords_part.y2 = coords.y1 + header.h - 1; - lv_draw_img(draw_ctx, &img_dsc, &coords_part, src); - } - - src = imgbtn->img_src_right[state]; - if(src) { - lv_img_decoder_get_info(src, &header); - right_w = header.w; - coords_part.x1 = coords.x2 - header.w + 1; - coords_part.y1 = coords.y1; - coords_part.x2 = coords.x2; - coords_part.y2 = coords.y1 + header.h - 1; - lv_draw_img(draw_ctx, &img_dsc, &coords_part, src); - } - - src = imgbtn->img_src_mid[state]; - if(src) { - lv_area_t clip_area_center; - clip_area_center.x1 = coords.x1 + left_w; - clip_area_center.x2 = coords.x2 - right_w; - clip_area_center.y1 = coords.y1; - clip_area_center.y2 = coords.y2; - - - bool comm_res; - comm_res = _lv_area_intersect(&clip_area_center, &clip_area_center, draw_ctx->clip_area); - if(comm_res) { - lv_coord_t i; - lv_img_decoder_get_info(src, &header); - - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &clip_area_center; - - coords_part.x1 = coords.x1 + left_w; - coords_part.y1 = coords.y1; - coords_part.x2 = coords_part.x1 + header.w - 1; - coords_part.y2 = coords_part.y1 + header.h - 1; - - for(i = coords_part.x1; i < (lv_coord_t)(clip_area_center.x2 + header.w - 1); i += header.w) { - lv_draw_img(draw_ctx, &img_dsc, &coords_part, src); - coords_part.x1 = coords_part.x2 + 1; - coords_part.x2 += header.w; - } - draw_ctx->clip_area = clip_area_ori; - } - } -} - -static void refr_img(lv_obj_t * obj) -{ - lv_imgbtn_t * imgbtn = (lv_imgbtn_t *)obj; - lv_imgbtn_state_t state = suggest_state(obj, get_state(obj)); - lv_img_header_t header; - - const void * src = imgbtn->img_src_mid[state]; - if(src == NULL) return; - - lv_res_t info_res = LV_RES_OK; - info_res = lv_img_decoder_get_info(src, &header); - - if(info_res == LV_RES_OK) { - imgbtn->act_cf = header.cf; - lv_obj_refresh_self_size(obj); - lv_obj_set_height(obj, header.h); /*Keep the user defined width*/ - } - else { - imgbtn->act_cf = LV_IMG_CF_UNKNOWN; - } - - lv_obj_invalidate(obj); -} - -/** - * If `src` is not defined for the current state try to get a state which is related to the current but has `src`. - * E.g. if the PRESSED src is not set but the RELEASED does, use the RELEASED. - * @param imgbtn pointer to an image button - * @param state the state to convert - * @return the suggested state - */ -static lv_imgbtn_state_t suggest_state(lv_obj_t * obj, lv_imgbtn_state_t state) -{ - lv_imgbtn_t * imgbtn = (lv_imgbtn_t *)obj; - if(imgbtn->img_src_mid[state] == NULL) { - switch(state) { - case LV_IMGBTN_STATE_PRESSED: - if(imgbtn->img_src_mid[LV_IMGBTN_STATE_RELEASED]) return LV_IMGBTN_STATE_RELEASED; - break; - case LV_IMGBTN_STATE_CHECKED_RELEASED: - if(imgbtn->img_src_mid[LV_IMGBTN_STATE_RELEASED]) return LV_IMGBTN_STATE_RELEASED; - break; - case LV_IMGBTN_STATE_CHECKED_PRESSED: - if(imgbtn->img_src_mid[LV_IMGBTN_STATE_CHECKED_RELEASED]) return LV_IMGBTN_STATE_CHECKED_RELEASED; - if(imgbtn->img_src_mid[LV_IMGBTN_STATE_PRESSED]) return LV_IMGBTN_STATE_PRESSED; - if(imgbtn->img_src_mid[LV_IMGBTN_STATE_RELEASED]) return LV_IMGBTN_STATE_RELEASED; - break; - case LV_IMGBTN_STATE_DISABLED: - if(imgbtn->img_src_mid[LV_IMGBTN_STATE_RELEASED]) return LV_IMGBTN_STATE_RELEASED; - break; - case LV_IMGBTN_STATE_CHECKED_DISABLED: - if(imgbtn->img_src_mid[LV_IMGBTN_STATE_CHECKED_RELEASED]) return LV_IMGBTN_STATE_CHECKED_RELEASED; - if(imgbtn->img_src_mid[LV_IMGBTN_STATE_RELEASED]) return LV_IMGBTN_STATE_RELEASED; - break; - default: - break; - } - } - - return state; -} - -lv_imgbtn_state_t get_state(const lv_obj_t * imgbtn) -{ - LV_ASSERT_OBJ(imgbtn, MY_CLASS); - - lv_state_t obj_state = lv_obj_get_state(imgbtn); - - if(obj_state & LV_STATE_DISABLED) { - if(obj_state & LV_STATE_CHECKED) return LV_IMGBTN_STATE_CHECKED_DISABLED; - else return LV_IMGBTN_STATE_DISABLED; - } - - if(obj_state & LV_STATE_CHECKED) { - if(obj_state & LV_STATE_PRESSED) return LV_IMGBTN_STATE_CHECKED_PRESSED; - else return LV_IMGBTN_STATE_CHECKED_RELEASED; - } - else { - if(obj_state & LV_STATE_PRESSED) return LV_IMGBTN_STATE_PRESSED; - else return LV_IMGBTN_STATE_RELEASED; - } -} - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h deleted file mode 100644 index 597faea18..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h +++ /dev/null @@ -1,131 +0,0 @@ -/** - * @file lv_imgbtn.h - * - */ - -#ifndef LV_IMGBTN_H -#define LV_IMGBTN_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../../lvgl.h" - -#if LV_USE_IMGBTN != 0 - -/********************* - * DEFINES - *********************/ -typedef enum { - LV_IMGBTN_STATE_RELEASED, - LV_IMGBTN_STATE_PRESSED, - LV_IMGBTN_STATE_DISABLED, - LV_IMGBTN_STATE_CHECKED_RELEASED, - LV_IMGBTN_STATE_CHECKED_PRESSED, - LV_IMGBTN_STATE_CHECKED_DISABLED, - _LV_IMGBTN_STATE_NUM, -} lv_imgbtn_state_t; - -/********************** - * TYPEDEFS - **********************/ -/*Data of image button*/ -typedef struct { - lv_obj_t obj; - const void * img_src_mid[_LV_IMGBTN_STATE_NUM]; /*Store center images to each state*/ - const void * img_src_left[_LV_IMGBTN_STATE_NUM]; /*Store left side images to each state*/ - const void * img_src_right[_LV_IMGBTN_STATE_NUM]; /*Store right side images to each state*/ - lv_img_cf_t act_cf; /*Color format of the currently active image*/ -} lv_imgbtn_t; - -extern const lv_obj_class_t lv_imgbtn_class; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create an image button object - * @param parent pointer to an object, it will be the parent of the new image button - * @return pointer to the created image button - */ -lv_obj_t * lv_imgbtn_create(lv_obj_t * parent); - -/*====================== - * Add/remove functions - *=====================*/ - -/*===================== - * Setter functions - *====================*/ - -/** - * Set images for a state of the image button - * @param imgbtn pointer to an image button object - * @param state for which state set the new image - * @param src_left pointer to an image source for the left side of the button (a C array or path to - * a file) - * @param src_mid pointer to an image source for the middle of the button (ideally 1px wide) (a C - * array or path to a file) - * @param src_right pointer to an image source for the right side of the button (a C array or path - * to a file) - */ -void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_imgbtn_state_t state, const void * src_left, const void * src_mid, - const void * src_right); - - -/** - * Use this function instead of `lv_obj_add/clear_state` to set a state manually - * @param imgbtn pointer to an image button object - * @param state the new state - */ -void lv_imgbtn_set_state(lv_obj_t * imgbtn, lv_imgbtn_state_t state); - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the left image in a given state - * @param imgbtn pointer to an image button object - * @param state the state where to get the image (from `lv_btn_state_t`) ` - * @return pointer to the left image source (a C array or path to a file) - */ -const void * lv_imgbtn_get_src_left(lv_obj_t * imgbtn, lv_imgbtn_state_t state); - -/** - * Get the middle image in a given state - * @param imgbtn pointer to an image button object - * @param state the state where to get the image (from `lv_btn_state_t`) ` - * @return pointer to the middle image source (a C array or path to a file) - */ -const void * lv_imgbtn_get_src_middle(lv_obj_t * imgbtn, lv_imgbtn_state_t state); - -/** - * Get the right image in a given state - * @param imgbtn pointer to an image button object - * @param state the state where to get the image (from `lv_btn_state_t`) ` - * @return pointer to the left image source (a C array or path to a file) - */ -const void * lv_imgbtn_get_src_right(lv_obj_t * imgbtn, lv_imgbtn_state_t state); - - -/*===================== - * Other functions - *====================*/ - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_IMGBTN*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_IMGBTN_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.h deleted file mode 100644 index 0da5595bc..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @file lv_win.h - * - */ - -#ifndef LV_LIST_H -#define LV_LIST_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../../core/lv_obj.h" -#include "../../layouts/flex/lv_flex.h" - -#if LV_USE_LIST - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -extern const lv_obj_class_t lv_list_class; -extern const lv_obj_class_t lv_list_text_class; -extern const lv_obj_class_t lv_list_btn_class; -/********************** - * GLOBAL PROTOTYPES - **********************/ - -lv_obj_t * lv_list_create(lv_obj_t * parent); - -lv_obj_t * lv_list_add_text(lv_obj_t * list, const char * txt); - -lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * icon, const char * txt); - -const char * lv_list_get_btn_text(lv_obj_t * list, lv_obj_t * btn); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_LIST*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_LIST_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/lv_widgets.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/lv_widgets.h deleted file mode 100644 index 114181022..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/lv_widgets.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @file lv_widgets.h - * - */ - -#ifndef LV_WIDGETS_H -#define LV_WIDGETS_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "animimg/lv_animimg.h" -#include "calendar/lv_calendar.h" -#include "calendar/lv_calendar_header_arrow.h" -#include "calendar/lv_calendar_header_dropdown.h" -#include "chart/lv_chart.h" -#include "keyboard/lv_keyboard.h" -#include "list/lv_list.h" -#include "menu/lv_menu.h" -#include "msgbox/lv_msgbox.h" -#include "meter/lv_meter.h" -#include "spinbox/lv_spinbox.h" -#include "spinner/lv_spinner.h" -#include "tabview/lv_tabview.h" -#include "tileview/lv_tileview.h" -#include "win/lv_win.h" -#include "colorwheel/lv_colorwheel.h" -#include "led/lv_led.h" -#include "imgbtn/lv_imgbtn.h" -#include "span/lv_span.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_WIDGETS_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/menu/lv_menu.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/menu/lv_menu.h deleted file mode 100644 index 0449059f8..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/menu/lv_menu.h +++ /dev/null @@ -1,233 +0,0 @@ -/** - * @file lv_menu.h - * - */ - -#ifndef LV_MENU_H -#define LV_MENU_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../../core/lv_obj.h" - -#if LV_USE_MENU - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -enum { - LV_MENU_HEADER_TOP_FIXED, /* Header is positioned at the top */ - LV_MENU_HEADER_TOP_UNFIXED, /* Header is positioned at the top and can be scrolled out of view*/ - LV_MENU_HEADER_BOTTOM_FIXED /* Header is positioned at the bottom */ -}; -typedef uint8_t lv_menu_mode_header_t; - -enum { - LV_MENU_ROOT_BACK_BTN_DISABLED, - LV_MENU_ROOT_BACK_BTN_ENABLED -}; -typedef uint8_t lv_menu_mode_root_back_btn_t; - -typedef struct lv_menu_load_page_event_data_t { - lv_obj_t * menu; - lv_obj_t * page; -} lv_menu_load_page_event_data_t; - -typedef struct { - lv_obj_t * page; -} lv_menu_history_t; - -typedef struct { - lv_obj_t obj; - lv_obj_t * storage; /* a pointer to obj that is the parent of all pages not displayed */ - lv_obj_t * main; - lv_obj_t * main_page; - lv_obj_t * main_header; - lv_obj_t * - main_header_back_btn; /* a pointer to obj that on click triggers back btn event handler, can be same as 'main_header' */ - lv_obj_t * main_header_title; - lv_obj_t * sidebar; - lv_obj_t * sidebar_page; - lv_obj_t * sidebar_header; - lv_obj_t * - sidebar_header_back_btn; /* a pointer to obj that on click triggers back btn event handler, can be same as 'sidebar_header' */ - lv_obj_t * sidebar_header_title; - lv_obj_t * selected_tab; - lv_ll_t history_ll; - uint8_t cur_depth; - uint8_t prev_depth; - uint8_t sidebar_generated : 1; - lv_menu_mode_header_t mode_header : 2; - lv_menu_mode_root_back_btn_t mode_root_back_btn : 1; -} lv_menu_t; - -typedef struct { - lv_obj_t obj; - char * title; -} lv_menu_page_t; - -extern const lv_obj_class_t lv_menu_class; -extern const lv_obj_class_t lv_menu_page_class; -extern const lv_obj_class_t lv_menu_cont_class; -extern const lv_obj_class_t lv_menu_section_class; -extern const lv_obj_class_t lv_menu_separator_class; -extern const lv_obj_class_t lv_menu_sidebar_cont_class; -extern const lv_obj_class_t lv_menu_main_cont_class; -extern const lv_obj_class_t lv_menu_sidebar_header_cont_class; -extern const lv_obj_class_t lv_menu_main_header_cont_class; -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a menu object - * @param parent pointer to an object, it will be the parent of the new menu - * @return pointer to the created menu - */ -lv_obj_t * lv_menu_create(lv_obj_t * parent); - -/** - * Create a menu page object - * @param parent pointer to menu object - * @param title pointer to text for title in header (NULL to not display title) - * @return pointer to the created menu page - */ -lv_obj_t * lv_menu_page_create(lv_obj_t * parent, char * title); - -/** - * Create a menu cont object - * @param parent pointer to an object, it will be the parent of the new menu cont object - * @return pointer to the created menu cont - */ -lv_obj_t * lv_menu_cont_create(lv_obj_t * parent); - -/** - * Create a menu section object - * @param parent pointer to an object, it will be the parent of the new menu section object - * @return pointer to the created menu section - */ -lv_obj_t * lv_menu_section_create(lv_obj_t * parent); - -/** - * Create a menu separator object - * @param parent pointer to an object, it will be the parent of the new menu separator object - * @return pointer to the created menu separator - */ -lv_obj_t * lv_menu_separator_create(lv_obj_t * parent); -/*===================== - * Setter functions - *====================*/ -/** - * Set menu page to display in main - * @param obj pointer to the menu - * @param page pointer to the menu page to set (NULL to clear main and clear menu history) - */ -void lv_menu_set_page(lv_obj_t * obj, lv_obj_t * page); - -/** - * Set menu page to display in sidebar - * @param obj pointer to the menu - * @param page pointer to the menu page to set (NULL to clear sidebar) - */ -void lv_menu_set_sidebar_page(lv_obj_t * obj, lv_obj_t * page); - -/** - * Set the how the header should behave and its position - * @param obj pointer to a menu - * @param mode_header - */ -void lv_menu_set_mode_header(lv_obj_t * obj, lv_menu_mode_header_t mode_header); - -/** - * Set whether back button should appear at root - * @param obj pointer to a menu - * @param mode_root_back_btn - */ -void lv_menu_set_mode_root_back_btn(lv_obj_t * obj, lv_menu_mode_root_back_btn_t mode_root_back_btn); - -/** - * Add menu to the menu item - * @param menu pointer to the menu - * @param obj pointer to the obj - * @param page pointer to the page to load when obj is clicked - */ -void lv_menu_set_load_page_event(lv_obj_t * menu, lv_obj_t * obj, lv_obj_t * page); - -/*===================== - * Getter functions - *====================*/ -/** -* Get a pointer to menu page that is currently displayed in main -* @param obj pointer to the menu -* @return pointer to current page -*/ -lv_obj_t * lv_menu_get_cur_main_page(lv_obj_t * obj); - -/** -* Get a pointer to menu page that is currently displayed in sidebar -* @param obj pointer to the menu -* @return pointer to current page -*/ -lv_obj_t * lv_menu_get_cur_sidebar_page(lv_obj_t * obj); - -/** -* Get a pointer to main header obj -* @param obj pointer to the menu -* @return pointer to main header obj -*/ -lv_obj_t * lv_menu_get_main_header(lv_obj_t * obj); - -/** -* Get a pointer to main header back btn obj -* @param obj pointer to the menu -* @return pointer to main header back btn obj -*/ -lv_obj_t * lv_menu_get_main_header_back_btn(lv_obj_t * obj); - -/** -* Get a pointer to sidebar header obj -* @param obj pointer to the menu -* @return pointer to sidebar header obj -*/ -lv_obj_t * lv_menu_get_sidebar_header(lv_obj_t * obj); - -/** -* Get a pointer to sidebar header obj -* @param obj pointer to the menu -* @return pointer to sidebar header back btn obj -*/ -lv_obj_t * lv_menu_get_sidebar_header_back_btn(lv_obj_t * obj); - -/** - * Check if an obj is a root back btn - * @param menu pointer to the menu - * @return true if it is a root back btn - */ -bool lv_menu_back_btn_is_root(lv_obj_t * menu, lv_obj_t * obj); - -/** - * Clear menu history - * @param obj pointer to the menu - */ -void lv_menu_clear_history(lv_obj_t * obj); -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_MENU*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_MENU_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.c deleted file mode 100644 index f1ea9d507..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.c +++ /dev/null @@ -1,702 +0,0 @@ -/** - * @file lv_meter.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_meter.h" -#if LV_USE_METER != 0 - -#include "../../../misc/lv_assert.h" - -/********************* - * DEFINES - *********************/ -#define MY_CLASS &lv_meter_class - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void lv_meter_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void lv_meter_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void lv_meter_event(const lv_obj_class_t * class_p, lv_event_t * e); -static void draw_arcs(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, const lv_area_t * scale_area); -static void draw_ticks_and_labels(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, const lv_area_t * scale_area); -static void draw_needles(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, const lv_area_t * scale_area); -static void inv_arc(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t old_value, int32_t new_value); -static void inv_line(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value); - -/********************** - * STATIC VARIABLES - **********************/ -const lv_obj_class_t lv_meter_class = { - .constructor_cb = lv_meter_constructor, - .destructor_cb = lv_meter_destructor, - .event_cb = lv_meter_event, - .instance_size = sizeof(lv_meter_t), - .base_class = &lv_obj_class -}; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_obj_t * lv_meter_create(lv_obj_t * parent) -{ - LV_LOG_INFO("begin"); - lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); - lv_obj_class_init_obj(obj); - return obj; -} - -/*===================== - * Add scale - *====================*/ - -lv_meter_scale_t * lv_meter_add_scale(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_meter_t * meter = (lv_meter_t *)obj; - - lv_meter_scale_t * scale = _lv_ll_ins_head(&meter->scale_ll); - LV_ASSERT_MALLOC(scale); - lv_memset_00(scale, sizeof(lv_meter_scale_t)); - - scale->angle_range = 270; - scale->rotation = 90 + (360 - scale->angle_range) / 2; - scale->min = 0; - scale->max = 100; - scale->tick_cnt = 6; - scale->tick_length = 8; - scale->tick_width = 2; - scale->label_gap = 2; - - return scale; -} - -void lv_meter_set_scale_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t cnt, uint16_t width, uint16_t len, - lv_color_t color) -{ - scale->tick_cnt = cnt; - scale->tick_width = width; - scale->tick_length = len; - scale->tick_color = color; - lv_obj_invalidate(obj); -} - -void lv_meter_set_scale_major_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t nth, uint16_t width, - uint16_t len, lv_color_t color, int16_t label_gap) -{ - scale->tick_major_nth = nth; - scale->tick_major_width = width; - scale->tick_major_length = len; - scale->tick_major_color = color; - scale->label_gap = label_gap; - lv_obj_invalidate(obj); -} - -void lv_meter_set_scale_range(lv_obj_t * obj, lv_meter_scale_t * scale, int32_t min, int32_t max, uint32_t angle_range, - uint32_t rotation) -{ - scale->min = min; - scale->max = max; - scale->angle_range = angle_range; - scale->rotation = rotation; - lv_obj_invalidate(obj); -} - -/*===================== - * Add indicator - *====================*/ - -lv_meter_indicator_t * lv_meter_add_needle_line(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, - lv_color_t color, int16_t r_mod) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_meter_t * meter = (lv_meter_t *)obj; - lv_meter_indicator_t * indic = _lv_ll_ins_head(&meter->indicator_ll); - LV_ASSERT_MALLOC(indic); - lv_memset_00(indic, sizeof(lv_meter_indicator_t)); - indic->scale = scale; - indic->opa = LV_OPA_COVER; - - indic->type = LV_METER_INDICATOR_TYPE_NEEDLE_LINE; - indic->type_data.needle_line.width = width; - indic->type_data.needle_line.color = color; - indic->type_data.needle_line.r_mod = r_mod; - lv_obj_invalidate(obj); - - return indic; -} - -lv_meter_indicator_t * lv_meter_add_needle_img(lv_obj_t * obj, lv_meter_scale_t * scale, const void * src, - lv_coord_t pivot_x, lv_coord_t pivot_y) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_meter_t * meter = (lv_meter_t *)obj; - lv_meter_indicator_t * indic = _lv_ll_ins_head(&meter->indicator_ll); - LV_ASSERT_MALLOC(indic); - lv_memset_00(indic, sizeof(lv_meter_indicator_t)); - indic->scale = scale; - indic->opa = LV_OPA_COVER; - - indic->type = LV_METER_INDICATOR_TYPE_NEEDLE_IMG; - indic->type_data.needle_img.src = src; - indic->type_data.needle_img.pivot.x = pivot_x; - indic->type_data.needle_img.pivot.y = pivot_y; - lv_obj_invalidate(obj); - - return indic; -} - -lv_meter_indicator_t * lv_meter_add_arc(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, lv_color_t color, - int16_t r_mod) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_meter_t * meter = (lv_meter_t *)obj; - lv_meter_indicator_t * indic = _lv_ll_ins_head(&meter->indicator_ll); - LV_ASSERT_MALLOC(indic); - lv_memset_00(indic, sizeof(lv_meter_indicator_t)); - indic->scale = scale; - indic->opa = LV_OPA_COVER; - - indic->type = LV_METER_INDICATOR_TYPE_ARC; - indic->type_data.arc.width = width; - indic->type_data.arc.color = color; - indic->type_data.arc.r_mod = r_mod; - - lv_obj_invalidate(obj); - return indic; -} - -lv_meter_indicator_t * lv_meter_add_scale_lines(lv_obj_t * obj, lv_meter_scale_t * scale, lv_color_t color_start, - lv_color_t color_end, bool local, int16_t width_mod) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_meter_t * meter = (lv_meter_t *)obj; - lv_meter_indicator_t * indic = _lv_ll_ins_head(&meter->indicator_ll); - LV_ASSERT_MALLOC(indic); - lv_memset_00(indic, sizeof(lv_meter_indicator_t)); - indic->scale = scale; - indic->opa = LV_OPA_COVER; - - indic->type = LV_METER_INDICATOR_TYPE_SCALE_LINES; - indic->type_data.scale_lines.color_start = color_start; - indic->type_data.scale_lines.color_end = color_end; - indic->type_data.scale_lines.local_grad = local; - indic->type_data.scale_lines.width_mod = width_mod; - - lv_obj_invalidate(obj); - return indic; -} - -/*===================== - * Set indicator value - *====================*/ - -void lv_meter_set_indicator_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value) -{ - int32_t old_start = indic->start_value; - int32_t old_end = indic->end_value; - indic->start_value = value; - indic->end_value = value; - - if(indic->type == LV_METER_INDICATOR_TYPE_ARC) { - inv_arc(obj, indic, old_start, value); - inv_arc(obj, indic, old_end, value); - } - else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG || indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_LINE) { - inv_line(obj, indic, old_start); - inv_line(obj, indic, old_end); - inv_line(obj, indic, value); - } - else { - lv_obj_invalidate(obj); - } -} - -void lv_meter_set_indicator_start_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value) -{ - int32_t old_value = indic->start_value; - indic->start_value = value; - - if(indic->type == LV_METER_INDICATOR_TYPE_ARC) { - inv_arc(obj, indic, old_value, value); - } - else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG || indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_LINE) { - inv_line(obj, indic, old_value); - inv_line(obj, indic, value); - } - else { - lv_obj_invalidate(obj); - } -} - -void lv_meter_set_indicator_end_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value) -{ - int32_t old_value = indic->end_value; - indic->end_value = value; - - if(indic->type == LV_METER_INDICATOR_TYPE_ARC) { - inv_arc(obj, indic, old_value, value); - } - else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG || indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_LINE) { - inv_line(obj, indic, old_value); - inv_line(obj, indic, value); - } - else { - lv_obj_invalidate(obj); - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void lv_meter_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) -{ - LV_UNUSED(class_p); - LV_TRACE_OBJ_CREATE("begin"); - - lv_meter_t * meter = (lv_meter_t *)obj; - - _lv_ll_init(&meter->scale_ll, sizeof(lv_meter_scale_t)); - _lv_ll_init(&meter->indicator_ll, sizeof(lv_meter_indicator_t)); - - LV_TRACE_OBJ_CREATE("finished"); -} - -static void lv_meter_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) -{ - LV_UNUSED(class_p); - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_meter_t * meter = (lv_meter_t *)obj; - _lv_ll_clear(&meter->indicator_ll); - _lv_ll_clear(&meter->scale_ll); - -} - -static void lv_meter_event(const lv_obj_class_t * class_p, lv_event_t * e) -{ - LV_UNUSED(class_p); - - lv_res_t res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; - - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); - if(code == LV_EVENT_DRAW_MAIN) { - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); - lv_area_t scale_area; - lv_obj_get_content_coords(obj, &scale_area); - - draw_arcs(obj, draw_ctx, &scale_area); - draw_ticks_and_labels(obj, draw_ctx, &scale_area); - draw_needles(obj, draw_ctx, &scale_area); - - lv_coord_t r_edge = lv_area_get_width(&scale_area) / 2; - lv_point_t scale_center; - scale_center.x = scale_area.x1 + r_edge; - scale_center.y = scale_area.y1 + r_edge; - - lv_draw_rect_dsc_t mid_dsc; - lv_draw_rect_dsc_init(&mid_dsc); - lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &mid_dsc); - lv_coord_t w = lv_obj_get_style_width(obj, LV_PART_INDICATOR) / 2; - lv_coord_t h = lv_obj_get_style_height(obj, LV_PART_INDICATOR) / 2; - lv_area_t nm_cord; - nm_cord.x1 = scale_center.x - w; - nm_cord.y1 = scale_center.y - h; - nm_cord.x2 = scale_center.x + w; - nm_cord.y2 = scale_center.y + h; - lv_draw_rect(draw_ctx, &mid_dsc, &nm_cord); - } -} - -static void draw_arcs(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, const lv_area_t * scale_area) -{ - lv_meter_t * meter = (lv_meter_t *)obj; - - lv_draw_arc_dsc_t arc_dsc; - lv_draw_arc_dsc_init(&arc_dsc); - arc_dsc.rounded = lv_obj_get_style_arc_rounded(obj, LV_PART_ITEMS); - - lv_coord_t r_out = lv_area_get_width(scale_area) / 2 ; - lv_point_t scale_center; - scale_center.x = scale_area->x1 + r_out; - scale_center.y = scale_area->y1 + r_out; - - lv_opa_t opa_main = lv_obj_get_style_opa_recursive(obj, LV_PART_MAIN); - lv_meter_indicator_t * indic; - - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.arc_dsc = &arc_dsc; - part_draw_dsc.part = LV_PART_INDICATOR; - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_METER_DRAW_PART_ARC; - - _LV_LL_READ_BACK(&meter->indicator_ll, indic) { - if(indic->type != LV_METER_INDICATOR_TYPE_ARC) continue; - - arc_dsc.color = indic->type_data.arc.color; - arc_dsc.width = indic->type_data.arc.width; - arc_dsc.opa = indic->opa > LV_OPA_MAX ? opa_main : (opa_main * indic->opa) >> 8; - - lv_meter_scale_t * scale = indic->scale; - - int32_t start_angle = lv_map(indic->start_value, scale->min, scale->max, scale->rotation, - scale->rotation + scale->angle_range); - int32_t end_angle = lv_map(indic->end_value, scale->min, scale->max, scale->rotation, - scale->rotation + scale->angle_range); - - arc_dsc.start_angle = start_angle; - arc_dsc.end_angle = end_angle; - part_draw_dsc.radius = r_out + indic->type_data.arc.r_mod; - part_draw_dsc.sub_part_ptr = indic; - part_draw_dsc.p1 = &scale_center; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_arc(draw_ctx, &arc_dsc, &scale_center, part_draw_dsc.radius, start_angle, end_angle); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } -} - -static void draw_ticks_and_labels(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, const lv_area_t * scale_area) -{ - lv_meter_t * meter = (lv_meter_t *)obj; - - lv_point_t p_center; - lv_coord_t r_edge = LV_MIN(lv_area_get_width(scale_area) / 2, lv_area_get_height(scale_area) / 2); - p_center.x = scale_area->x1 + r_edge; - p_center.y = scale_area->y1 + r_edge; - - lv_draw_line_dsc_t line_dsc; - lv_draw_line_dsc_init(&line_dsc); - lv_obj_init_draw_line_dsc(obj, LV_PART_TICKS, &line_dsc); - line_dsc.raw_end = 1; - - lv_draw_label_dsc_t label_dsc; - lv_draw_label_dsc_init(&label_dsc); - lv_obj_init_draw_label_dsc(obj, LV_PART_TICKS, &label_dsc); - - lv_meter_scale_t * scale; - - lv_draw_mask_radius_param_t inner_minor_mask; - lv_draw_mask_radius_param_t inner_major_mask; - lv_draw_mask_radius_param_t outer_mask; - - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.part = LV_PART_TICKS; - part_draw_dsc.type = LV_METER_DRAW_PART_TICK; - part_draw_dsc.line_dsc = &line_dsc; - - _LV_LL_READ_BACK(&meter->scale_ll, scale) { - part_draw_dsc.sub_part_ptr = scale; - - lv_coord_t r_out = r_edge; - lv_coord_t r_in_minor = r_out - scale->tick_length; - lv_coord_t r_in_major = r_out - scale->tick_major_length; - - lv_area_t area_inner_minor; - area_inner_minor.x1 = p_center.x - r_in_minor; - area_inner_minor.y1 = p_center.y - r_in_minor; - area_inner_minor.x2 = p_center.x + r_in_minor; - area_inner_minor.y2 = p_center.y + r_in_minor; - lv_draw_mask_radius_init(&inner_minor_mask, &area_inner_minor, LV_RADIUS_CIRCLE, true); - - lv_area_t area_inner_major; - area_inner_major.x1 = p_center.x - r_in_major; - area_inner_major.y1 = p_center.y - r_in_major; - area_inner_major.x2 = p_center.x + r_in_major - 1; - area_inner_major.y2 = p_center.y + r_in_major - 1; - lv_draw_mask_radius_init(&inner_major_mask, &area_inner_major, LV_RADIUS_CIRCLE, true); - - lv_area_t area_outer; - area_outer.x1 = p_center.x - r_out; - area_outer.y1 = p_center.y - r_out; - area_outer.x2 = p_center.x + r_out - 1; - area_outer.y2 = p_center.y + r_out - 1; - lv_draw_mask_radius_init(&outer_mask, &area_outer, LV_RADIUS_CIRCLE, false); - int16_t outer_mask_id = lv_draw_mask_add(&outer_mask, NULL); - - int16_t inner_act_mask_id = LV_MASK_ID_INV; /*Will be added later*/ - - uint32_t minor_cnt = scale->tick_major_nth ? scale->tick_major_nth - 1 : 0xFFFF; - uint16_t i; - for(i = 0; i < scale->tick_cnt; i++) { - minor_cnt++; - bool major = false; - if(minor_cnt == scale->tick_major_nth) { - minor_cnt = 0; - major = true; - } - - int32_t value_of_line = lv_map(i, 0, scale->tick_cnt - 1, scale->min, scale->max); - part_draw_dsc.value = value_of_line; - - lv_color_t line_color = major ? scale->tick_major_color : scale->tick_color; - lv_color_t line_color_ori = line_color; - - lv_coord_t line_width_ori = major ? scale->tick_major_width : scale->tick_width; - lv_coord_t line_width = line_width_ori; - - lv_meter_indicator_t * indic; - _LV_LL_READ_BACK(&meter->indicator_ll, indic) { - if(indic->type != LV_METER_INDICATOR_TYPE_SCALE_LINES) continue; - if(value_of_line >= indic->start_value && value_of_line <= indic->end_value) { - line_width += indic->type_data.scale_lines.width_mod; - - if(indic->type_data.scale_lines.color_start.full == indic->type_data.scale_lines.color_end.full) { - line_color = indic->type_data.scale_lines.color_start; - } - else { - lv_opa_t ratio; - if(indic->type_data.scale_lines.local_grad) { - ratio = lv_map(value_of_line, indic->start_value, indic->end_value, LV_OPA_TRANSP, LV_OPA_COVER); - } - else { - ratio = lv_map(value_of_line, scale->min, scale->max, LV_OPA_TRANSP, LV_OPA_COVER); - } - line_color = lv_color_mix(indic->type_data.scale_lines.color_end, indic->type_data.scale_lines.color_start, ratio); - } - } - } - - int32_t angle_upscale = ((i * scale->angle_range) * 10) / (scale->tick_cnt - 1) + + scale->rotation * 10; - - line_dsc.color = line_color; - line_dsc.width = line_width; - - /*Draw a little bit longer lines to be sure the mask will clip them correctly - *and to get a better precision*/ - lv_point_t p_outer; - p_outer.x = p_center.x + r_out + LV_MAX(LV_DPI_DEF, r_out); - p_outer.y = p_center.y; - lv_point_transform(&p_outer, angle_upscale, 256, &p_center); - - part_draw_dsc.p1 = &p_center; - part_draw_dsc.p2 = &p_outer; - part_draw_dsc.id = i; - part_draw_dsc.label_dsc = &label_dsc; - - /*Draw the text*/ - if(major) { - lv_draw_mask_remove_id(outer_mask_id); - uint32_t r_text = r_in_major - scale->label_gap; - lv_point_t p; - p.x = p_center.x + r_text; - p.y = p_center.y; - lv_point_transform(&p, angle_upscale, 256, &p_center); - - lv_draw_label_dsc_t label_dsc_tmp; - lv_memcpy(&label_dsc_tmp, &label_dsc, sizeof(label_dsc_tmp)); - - part_draw_dsc.label_dsc = &label_dsc_tmp; - char buf[16]; - - lv_snprintf(buf, sizeof(buf), "%" LV_PRId32, value_of_line); - part_draw_dsc.text = buf; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - - lv_point_t label_size; - lv_txt_get_size(&label_size, part_draw_dsc.text, label_dsc_tmp.font, label_dsc_tmp.letter_space, - label_dsc_tmp.line_space, - LV_COORD_MAX, LV_TEXT_FLAG_NONE); - - lv_area_t label_cord; - label_cord.x1 = p.x - label_size.x / 2; - label_cord.y1 = p.y - label_size.y / 2; - label_cord.x2 = label_cord.x1 + label_size.x; - label_cord.y2 = label_cord.y1 + label_size.y; - - lv_draw_label(draw_ctx, part_draw_dsc.label_dsc, &label_cord, part_draw_dsc.text, NULL); - - outer_mask_id = lv_draw_mask_add(&outer_mask, NULL); - } - else { - part_draw_dsc.label_dsc = NULL; - part_draw_dsc.text = NULL; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - } - - inner_act_mask_id = lv_draw_mask_add(major ? &inner_major_mask : &inner_minor_mask, NULL); - lv_draw_line(draw_ctx, &line_dsc, &p_outer, &p_center); - lv_draw_mask_remove_id(inner_act_mask_id); - lv_event_send(obj, LV_EVENT_DRAW_MAIN_END, &part_draw_dsc); - - line_dsc.color = line_color_ori; - line_dsc.width = line_width_ori; - - } - lv_draw_mask_free_param(&inner_minor_mask); - lv_draw_mask_free_param(&inner_major_mask); - lv_draw_mask_free_param(&outer_mask); - lv_draw_mask_remove_id(outer_mask_id); - } -} - - -static void draw_needles(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, const lv_area_t * scale_area) -{ - lv_meter_t * meter = (lv_meter_t *)obj; - - lv_coord_t r_edge = lv_area_get_width(scale_area) / 2; - lv_point_t scale_center; - scale_center.x = scale_area->x1 + r_edge; - scale_center.y = scale_area->y1 + r_edge; - - lv_draw_line_dsc_t line_dsc; - lv_draw_line_dsc_init(&line_dsc); - lv_obj_init_draw_line_dsc(obj, LV_PART_ITEMS, &line_dsc); - - lv_draw_img_dsc_t img_dsc; - lv_draw_img_dsc_init(&img_dsc); - lv_obj_init_draw_img_dsc(obj, LV_PART_ITEMS, &img_dsc); - lv_opa_t opa_main = lv_obj_get_style_opa_recursive(obj, LV_PART_MAIN); - - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.p1 = &scale_center; - part_draw_dsc.part = LV_PART_INDICATOR; - - lv_meter_indicator_t * indic; - _LV_LL_READ_BACK(&meter->indicator_ll, indic) { - lv_meter_scale_t * scale = indic->scale; - part_draw_dsc.sub_part_ptr = indic; - - if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_LINE) { - int32_t angle = lv_map(indic->end_value, scale->min, scale->max, scale->rotation, scale->rotation + scale->angle_range); - lv_coord_t r_out = r_edge + scale->r_mod + indic->type_data.needle_line.r_mod; - lv_point_t p_end; - p_end.y = (lv_trigo_sin(angle) * (r_out)) / LV_TRIGO_SIN_MAX + scale_center.y; - p_end.x = (lv_trigo_cos(angle) * (r_out)) / LV_TRIGO_SIN_MAX + scale_center.x; - line_dsc.color = indic->type_data.needle_line.color; - line_dsc.width = indic->type_data.needle_line.width; - line_dsc.opa = indic->opa > LV_OPA_MAX ? opa_main : (opa_main * indic->opa) >> 8; - - part_draw_dsc.type = LV_METER_DRAW_PART_NEEDLE_LINE; - part_draw_dsc.line_dsc = &line_dsc; - part_draw_dsc.p2 = &p_end; - part_draw_dsc.p1 = &scale_center; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_line(draw_ctx, &line_dsc, part_draw_dsc.p1, &p_end); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } - else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG) { - if(indic->type_data.needle_img.src == NULL) continue; - - int32_t angle = lv_map(indic->end_value, scale->min, scale->max, scale->rotation, scale->rotation + scale->angle_range); - lv_img_header_t info; - lv_img_decoder_get_info(indic->type_data.needle_img.src, &info); - lv_area_t a; - a.x1 = scale_center.x - indic->type_data.needle_img.pivot.x; - a.y1 = scale_center.y - indic->type_data.needle_img.pivot.y; - a.x2 = a.x1 + info.w - 1; - a.y2 = a.y1 + info.h - 1; - - img_dsc.opa = indic->opa > LV_OPA_MAX ? opa_main : (opa_main * indic->opa) >> 8; - img_dsc.pivot.x = indic->type_data.needle_img.pivot.x; - img_dsc.pivot.y = indic->type_data.needle_img.pivot.y; - angle = angle * 10; - if(angle > 3600) angle -= 3600; - img_dsc.angle = angle; - - part_draw_dsc.type = LV_METER_DRAW_PART_NEEDLE_IMG; - part_draw_dsc.img_dsc = &img_dsc; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_img(draw_ctx, &img_dsc, &a, indic->type_data.needle_img.src); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } - } -} - -static void inv_arc(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t old_value, int32_t new_value) -{ - bool rounded = lv_obj_get_style_arc_rounded(obj, LV_PART_ITEMS); - - lv_area_t scale_area; - lv_obj_get_content_coords(obj, &scale_area); - - lv_coord_t r_out = lv_area_get_width(&scale_area) / 2; - lv_point_t scale_center; - scale_center.x = scale_area.x1 + r_out; - scale_center.y = scale_area.y1 + r_out; - - r_out += indic->type_data.arc.r_mod; - - lv_meter_scale_t * scale = indic->scale; - - int32_t start_angle = lv_map(old_value, scale->min, scale->max, scale->rotation, scale->angle_range + scale->rotation); - int32_t end_angle = lv_map(new_value, scale->min, scale->max, scale->rotation, scale->angle_range + scale->rotation); - - lv_area_t a; - lv_draw_arc_get_area(scale_center.x, scale_center.y, r_out, LV_MIN(start_angle, end_angle), LV_MAX(start_angle, - end_angle), indic->type_data.arc.width, rounded, &a); - lv_obj_invalidate_area(obj, &a); -} - - -static void inv_line(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value) -{ - lv_area_t scale_area; - lv_obj_get_content_coords(obj, &scale_area); - - lv_coord_t r_out = lv_area_get_width(&scale_area) / 2; - lv_point_t scale_center; - scale_center.x = scale_area.x1 + r_out; - scale_center.y = scale_area.y1 + r_out; - - lv_meter_scale_t * scale = indic->scale; - - if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_LINE) { - int32_t angle = lv_map(value, scale->min, scale->max, scale->rotation, scale->rotation + scale->angle_range); - r_out += scale->r_mod + indic->type_data.needle_line.r_mod; - lv_point_t p_end; - p_end.y = (lv_trigo_sin(angle) * (r_out)) / LV_TRIGO_SIN_MAX + scale_center.y; - p_end.x = (lv_trigo_cos(angle) * (r_out)) / LV_TRIGO_SIN_MAX + scale_center.x; - - lv_area_t a; - a.x1 = LV_MIN(scale_center.x, p_end.x) - indic->type_data.needle_line.width - 2; - a.y1 = LV_MIN(scale_center.y, p_end.y) - indic->type_data.needle_line.width - 2; - a.x2 = LV_MAX(scale_center.x, p_end.x) + indic->type_data.needle_line.width + 2; - a.y2 = LV_MAX(scale_center.y, p_end.y) + indic->type_data.needle_line.width + 2; - - lv_obj_invalidate_area(obj, &a); - } - else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG) { - int32_t angle = lv_map(value, scale->min, scale->max, scale->rotation, scale->rotation + scale->angle_range); - lv_img_header_t info; - lv_img_decoder_get_info(indic->type_data.needle_img.src, &info); - - angle = angle * 10; - if(angle > 3600) angle -= 3600; - - scale_center.x -= indic->type_data.needle_img.pivot.x; - scale_center.y -= indic->type_data.needle_img.pivot.y; - lv_area_t a; - _lv_img_buf_get_transformed_area(&a, info.w, info.h, angle, LV_IMG_ZOOM_NONE, &indic->type_data.needle_img.pivot); - a.x1 += scale_center.x - 2; - a.y1 += scale_center.y - 2; - a.x2 += scale_center.x + 2; - a.y2 += scale_center.y + 2; - - lv_obj_invalidate_area(obj, &a); - } -} -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.h deleted file mode 100644 index 330bc2a95..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/meter/lv_meter.h +++ /dev/null @@ -1,266 +0,0 @@ -/** - * @file lv_meter.h - * - */ - -#ifndef LV_METER_H -#define LV_METER_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../../lvgl.h" - -#if LV_USE_METER != 0 - -/*Testing of dependencies*/ -#if LV_DRAW_COMPLEX == 0 -#error "lv_meter: Complex drawing is required. Enable it in lv_conf.h (LV_DRAW_COMPLEX 1)" -#endif - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - lv_color_t tick_color; - uint16_t tick_cnt; - uint16_t tick_length; - uint16_t tick_width; - - lv_color_t tick_major_color; - uint16_t tick_major_nth; - uint16_t tick_major_length; - uint16_t tick_major_width; - - int16_t label_gap; - - int32_t min; - int32_t max; - int16_t r_mod; - uint16_t angle_range; - int16_t rotation; -} lv_meter_scale_t; - -enum { - LV_METER_INDICATOR_TYPE_NEEDLE_IMG, - LV_METER_INDICATOR_TYPE_NEEDLE_LINE, - LV_METER_INDICATOR_TYPE_SCALE_LINES, - LV_METER_INDICATOR_TYPE_ARC, -}; -typedef uint8_t lv_meter_indicator_type_t; - -typedef struct { - lv_meter_scale_t * scale; - lv_meter_indicator_type_t type; - lv_opa_t opa; - int32_t start_value; - int32_t end_value; - union { - struct { - const void * src; - lv_point_t pivot; - } needle_img; - struct { - uint16_t width; - int16_t r_mod; - lv_color_t color; - } needle_line; - struct { - uint16_t width; - const void * src; - lv_color_t color; - int16_t r_mod; - } arc; - struct { - int16_t width_mod; - lv_color_t color_start; - lv_color_t color_end; - uint8_t local_grad : 1; - } scale_lines; - } type_data; -} lv_meter_indicator_t; - -/*Data of line meter*/ -typedef struct { - lv_obj_t obj; - lv_ll_t scale_ll; - lv_ll_t indicator_ll; -} lv_meter_t; - -extern const lv_obj_class_t lv_meter_class; - -/** - * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_meter_class` - * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` - */ -typedef enum { - LV_METER_DRAW_PART_ARC, /**< The arc indicator*/ - LV_METER_DRAW_PART_NEEDLE_LINE, /**< The needle lines*/ - LV_METER_DRAW_PART_NEEDLE_IMG, /**< The needle images*/ - LV_METER_DRAW_PART_TICK, /**< The tick lines and labels*/ -} lv_meter_draw_part_type_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a Meter object - * @param parent pointer to an object, it will be the parent of the new bar. - * @return pointer to the created meter - */ -lv_obj_t * lv_meter_create(lv_obj_t * parent); - -/*===================== - * Add scale - *====================*/ - -/** - * Add a new scale to the meter. - * @param obj pointer to a meter object - * @return the new scale - * @note Indicators can be attached to scales. - */ -lv_meter_scale_t * lv_meter_add_scale(lv_obj_t * obj); - -/** - * Set the properties of the ticks of a scale - * @param obj pointer to a meter object - * @param scale pointer to scale (added to `meter`) - * @param cnt number of tick lines - * @param width width of tick lines - * @param len length of tick lines - * @param color color of tick lines - */ -void lv_meter_set_scale_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t cnt, uint16_t width, uint16_t len, - lv_color_t color); - -/** - * Make some "normal" ticks major ticks and set their attributes. - * Texts with the current value are also added to the major ticks. - * @param obj pointer to a meter object - * @param scale pointer to scale (added to `meter`) - * @param nth make every Nth normal tick major tick. (start from the first on the left) - * @param width width of the major ticks - * @param len length of the major ticks - * @param color color of the major ticks - * @param label_gap gap between the major ticks and the labels - */ -void lv_meter_set_scale_major_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t nth, uint16_t width, - uint16_t len, lv_color_t color, int16_t label_gap); - -/** - * Set the value and angular range of a scale. - * @param obj pointer to a meter object - * @param scale pointer to scale (added to `meter`) - * @param min the minimum value - * @param max the maximal value - * @param angle_range the angular range of the scale - * @param rotation the angular offset from the 3 o'clock position (clock-wise) - */ -void lv_meter_set_scale_range(lv_obj_t * obj, lv_meter_scale_t * scale, int32_t min, int32_t max, uint32_t angle_range, - uint32_t rotation); - -/*===================== - * Add indicator - *====================*/ - -/** - * Add a needle line indicator the scale - * @param obj pointer to a meter object - * @param scale pointer to scale (added to `meter`) - * @param width width of the line - * @param color color of the line - * @param r_mod the radius modifier (added to the scale's radius) to get the lines length - * @return the new indicator - */ -lv_meter_indicator_t * lv_meter_add_needle_line(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, - lv_color_t color, int16_t r_mod); - -/** - * Add a needle image indicator the scale - * @param obj pointer to a meter object - * @param scale pointer to scale (added to `meter`) - * @param src the image source of the indicator. path or pointer to ::lv_img_dsc_t - * @param pivot_x the X pivot point of the needle - * @param pivot_y the Y pivot point of the needle - * @return the new indicator - * @note the needle image should point to the right, like -O-----> - */ -lv_meter_indicator_t * lv_meter_add_needle_img(lv_obj_t * obj, lv_meter_scale_t * scale, const void * src, - lv_coord_t pivot_x, lv_coord_t pivot_y); - -/** - * Add an arc indicator the scale - * @param obj pointer to a meter object - * @param scale pointer to scale (added to `meter`) - * @param width width of the arc - * @param color color of the arc - * @param r_mod the radius modifier (added to the scale's radius) to get the outer radius of the arc - * @return the new indicator - */ -lv_meter_indicator_t * lv_meter_add_arc(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, lv_color_t color, - int16_t r_mod); - - -/** - * Add a scale line indicator the scale. It will modify the ticks. - * @param obj pointer to a meter object - * @param scale pointer to scale (added to `meter`) - * @param color_start the start color - * @param color_end the end color - * @param local tell how to map start and end color. true: the indicator's start and end_value; false: the scale's min max value - * @param width_mod add this the affected tick's width - * @return the new indicator - */ -lv_meter_indicator_t * lv_meter_add_scale_lines(lv_obj_t * obj, lv_meter_scale_t * scale, lv_color_t color_start, - lv_color_t color_end, bool local, int16_t width_mod); - -/*===================== - * Set indicator value - *====================*/ - -/** - * Set the value of the indicator. It will set start and and value to the same value - * @param obj pointer to a meter object - * @param indic pointer to an indicator - * @param value the new value - */ -void lv_meter_set_indicator_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value); - -/** - * Set the start value of the indicator. - * @param obj pointer to a meter object - * @param indic pointer to an indicator - * @param value the new value - */ -void lv_meter_set_indicator_start_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value); - -/** - * Set the start value of the indicator. - * @param obj pointer to a meter object - * @param indic pointer to an indicator - * @param value the new value - */ -void lv_meter_set_indicator_end_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_METER*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_METER_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.c deleted file mode 100644 index 54d65e353..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.c +++ /dev/null @@ -1,212 +0,0 @@ -/** - * @file lv_msgbox.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_msgbox.h" -#if LV_USE_MSGBOX - -#include "../../../misc/lv_assert.h" - -/********************* - * DEFINES - *********************/ -#define LV_MSGBOX_FLAG_AUTO_PARENT LV_OBJ_FLAG_WIDGET_1 /*Mark that the parent was automatically created*/ -#define MY_CLASS &lv_msgbox_class - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void msgbox_close_click_event_cb(lv_event_t * e); - -/********************** - * STATIC VARIABLES - **********************/ -const lv_obj_class_t lv_msgbox_class = { - .base_class = &lv_obj_class, - .width_def = LV_DPI_DEF * 2, - .height_def = LV_SIZE_CONTENT, - .instance_size = sizeof(lv_msgbox_t) -}; - -const lv_obj_class_t lv_msgbox_content_class = { - .base_class = &lv_obj_class, - .width_def = LV_PCT(100), - .height_def = LV_SIZE_CONTENT, - .instance_size = sizeof(lv_obj_t) -}; - -const lv_obj_class_t lv_msgbox_backdrop_class = { - .base_class = &lv_obj_class, - .width_def = LV_PCT(100), - .height_def = LV_PCT(100), - .instance_size = sizeof(lv_obj_t) -}; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_obj_t * lv_msgbox_create(lv_obj_t * parent, const char * title, const char * txt, const char * btn_txts[], - bool add_close_btn) -{ - LV_LOG_INFO("begin"); - bool auto_parent = false; - if(parent == NULL) { - auto_parent = true; - parent = lv_obj_class_create_obj(&lv_msgbox_backdrop_class, lv_layer_top()); - LV_ASSERT_MALLOC(parent); - lv_obj_class_init_obj(parent); - lv_obj_clear_flag(parent, LV_OBJ_FLAG_IGNORE_LAYOUT); - lv_obj_set_size(parent, LV_PCT(100), LV_PCT(100)); - } - - lv_obj_t * obj = lv_obj_class_create_obj(&lv_msgbox_class, parent); - LV_ASSERT_MALLOC(obj); - if(obj == NULL) return NULL; - lv_obj_class_init_obj(obj); - lv_msgbox_t * mbox = (lv_msgbox_t *)obj; - - if(auto_parent) lv_obj_add_flag(obj, LV_MSGBOX_FLAG_AUTO_PARENT); - - lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW_WRAP); - - bool has_title = title && strlen(title) > 0; - - /*When a close button is required, we need the empty label as spacer to push the button to the right*/ - if(add_close_btn || has_title) { - mbox->title = lv_label_create(obj); - lv_label_set_text(mbox->title, has_title ? title : ""); - lv_label_set_long_mode(mbox->title, LV_LABEL_LONG_SCROLL_CIRCULAR); - if(add_close_btn) lv_obj_set_flex_grow(mbox->title, 1); - else lv_obj_set_width(mbox->title, LV_PCT(100)); - } - - if(add_close_btn) { - mbox->close_btn = lv_btn_create(obj); - lv_obj_set_ext_click_area(mbox->close_btn, LV_DPX(10)); - lv_obj_add_event_cb(mbox->close_btn, msgbox_close_click_event_cb, LV_EVENT_CLICKED, NULL); - lv_obj_t * label = lv_label_create(mbox->close_btn); - lv_label_set_text(label, LV_SYMBOL_CLOSE); - const lv_font_t * font = lv_obj_get_style_text_font(mbox->close_btn, LV_PART_MAIN); - lv_coord_t close_btn_size = lv_font_get_line_height(font) + LV_DPX(10); - lv_obj_set_size(mbox->close_btn, close_btn_size, close_btn_size); - lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); - } - - mbox->content = lv_obj_class_create_obj(&lv_msgbox_content_class, obj); - LV_ASSERT_MALLOC(mbox->content); - if(mbox->content == NULL) return NULL; - lv_obj_class_init_obj(mbox->content); - - bool has_txt = txt && strlen(txt) > 0; - if(has_txt) { - mbox->text = lv_label_create(mbox->content); - lv_label_set_text(mbox->text, txt); - lv_label_set_long_mode(mbox->text, LV_LABEL_LONG_WRAP); - lv_obj_set_width(mbox->text, lv_pct(100)); - } - - if(btn_txts) { - mbox->btns = lv_btnmatrix_create(obj); - lv_btnmatrix_set_map(mbox->btns, btn_txts); - lv_btnmatrix_set_btn_ctrl_all(mbox->btns, LV_BTNMATRIX_CTRL_CLICK_TRIG | LV_BTNMATRIX_CTRL_NO_REPEAT); - - uint32_t btn_cnt = 0; - while(btn_txts[btn_cnt] && btn_txts[btn_cnt][0] != '\0') { - btn_cnt++; - } - - const lv_font_t * font = lv_obj_get_style_text_font(mbox->btns, LV_PART_ITEMS); - lv_coord_t btn_h = lv_font_get_line_height(font) + LV_DPI_DEF / 10; - lv_obj_set_size(mbox->btns, btn_cnt * (2 * LV_DPI_DEF / 3), btn_h); - lv_obj_set_style_max_width(mbox->btns, lv_pct(100), 0); - lv_obj_add_flag(mbox->btns, LV_OBJ_FLAG_EVENT_BUBBLE); /*To see the event directly on the message box*/ - } - - return obj; -} - - -lv_obj_t * lv_msgbox_get_title(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_msgbox_t * mbox = (lv_msgbox_t *)obj; - return mbox->title; -} - -lv_obj_t * lv_msgbox_get_close_btn(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_msgbox_t * mbox = (lv_msgbox_t *)obj; - return mbox->close_btn; -} - -lv_obj_t * lv_msgbox_get_text(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_msgbox_t * mbox = (lv_msgbox_t *)obj; - return mbox->text; -} - -lv_obj_t * lv_msgbox_get_content(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_msgbox_t * mbox = (lv_msgbox_t *)obj; - return mbox->content; -} - -lv_obj_t * lv_msgbox_get_btns(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_msgbox_t * mbox = (lv_msgbox_t *)obj; - return mbox->btns; -} - -uint16_t lv_msgbox_get_active_btn(lv_obj_t * mbox) -{ - lv_obj_t * btnm = lv_msgbox_get_btns(mbox); - return lv_btnmatrix_get_selected_btn(btnm); -} - -const char * lv_msgbox_get_active_btn_text(lv_obj_t * mbox) -{ - lv_obj_t * btnm = lv_msgbox_get_btns(mbox); - return lv_btnmatrix_get_btn_text(btnm, lv_btnmatrix_get_selected_btn(btnm)); -} - -void lv_msgbox_close(lv_obj_t * mbox) -{ - if(lv_obj_has_flag(mbox, LV_MSGBOX_FLAG_AUTO_PARENT)) lv_obj_del(lv_obj_get_parent(mbox)); - else lv_obj_del(mbox); -} - -void lv_msgbox_close_async(lv_obj_t * dialog) -{ - if(lv_obj_has_flag(dialog, LV_MSGBOX_FLAG_AUTO_PARENT)) lv_obj_del_async(lv_obj_get_parent(dialog)); - else lv_obj_del_async(dialog); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void msgbox_close_click_event_cb(lv_event_t * e) -{ - lv_obj_t * btn = lv_event_get_target(e); - lv_obj_t * mbox = lv_obj_get_parent(btn); - lv_msgbox_close(mbox); -} - -#endif /*LV_USE_MSGBOX*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.h deleted file mode 100644 index 2eaf0d399..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/msgbox/lv_msgbox.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @file lv_mbox.h - * - */ - -#ifndef LV_MSGBOX_H -#define LV_MSGBOX_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../../lvgl.h" - -#if LV_USE_MSGBOX - -/*Testing of dependencies*/ -#if LV_USE_BTNMATRIX == 0 -#error "lv_mbox: lv_btnm is required. Enable it in lv_conf.h (LV_USE_BTNMATRIX 1) " -#endif - -#if LV_USE_LABEL == 0 -#error "lv_mbox: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) " -#endif - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - lv_obj_t obj; - lv_obj_t * title; - lv_obj_t * close_btn; - lv_obj_t * content; - lv_obj_t * text; - lv_obj_t * btns; -} lv_msgbox_t; - -extern const lv_obj_class_t lv_msgbox_class; -extern const lv_obj_class_t lv_msgbox_content_class; -extern const lv_obj_class_t lv_msgbox_backdrop_class; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a message box object - * @param parent pointer to parent or NULL to create a full screen modal message box - * @param title the title of the message box - * @param txt the text of the message box - * @param btn_txts the buttons as an array of texts terminated by an "" element. E.g. {"btn1", "btn2", ""} - * @param add_close_btn true: add a close button - * @return pointer to the message box object - */ -lv_obj_t * lv_msgbox_create(lv_obj_t * parent, const char * title, const char * txt, const char * btn_txts[], - bool add_close_btn); - -lv_obj_t * lv_msgbox_get_title(lv_obj_t * obj); - -lv_obj_t * lv_msgbox_get_close_btn(lv_obj_t * obj); - -lv_obj_t * lv_msgbox_get_text(lv_obj_t * obj); - -lv_obj_t * lv_msgbox_get_content(lv_obj_t * obj); - -lv_obj_t * lv_msgbox_get_btns(lv_obj_t * obj); - -/** - * Get the index of the selected button - * @param mbox message box object - * @return index of the button (LV_BTNMATRIX_BTN_NONE: if unset) - */ -uint16_t lv_msgbox_get_active_btn(lv_obj_t * mbox); - -const char * lv_msgbox_get_active_btn_text(lv_obj_t * mbox); - -void lv_msgbox_close(lv_obj_t * mbox); - -void lv_msgbox_close_async(lv_obj_t * mbox); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_MSGBOX*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_MSGBOX_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.h deleted file mode 100644 index f00d04db7..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.h +++ /dev/null @@ -1,245 +0,0 @@ -/** - * @file lv_span.h - * - */ - -#ifndef LV_SPAN_H -#define LV_SPAN_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../../lvgl.h" - -#if LV_USE_SPAN != 0 - -/********************* - * DEFINES - *********************/ -#ifndef LV_SPAN_SNIPPET_STACK_SIZE -#define LV_SPAN_SNIPPET_STACK_SIZE 64 -#endif - -/********************** - * TYPEDEFS - **********************/ -enum { - LV_SPAN_OVERFLOW_CLIP, - LV_SPAN_OVERFLOW_ELLIPSIS, -}; -typedef uint8_t lv_span_overflow_t; - -enum { - LV_SPAN_MODE_FIXED, /**< fixed the obj size*/ - LV_SPAN_MODE_EXPAND, /**< Expand the object size to the text size*/ - LV_SPAN_MODE_BREAK, /**< Keep width, break the too long lines and expand height*/ -}; -typedef uint8_t lv_span_mode_t; - -typedef struct { - char * txt; /* a pointer to display text */ - lv_obj_t * spangroup; /* a pointer to spangroup */ - lv_style_t style; /* display text style */ - uint8_t static_flag : 1;/* the text is static flag */ -} lv_span_t; - -/** Data of label*/ -typedef struct { - lv_obj_t obj; - int32_t lines; - lv_coord_t indent; /* first line indent */ - lv_coord_t cache_w; /* the cache automatically calculates the width */ - lv_coord_t cache_h; /* similar cache_w */ - lv_ll_t child_ll; - uint8_t mode : 2; /* details see lv_span_mode_t */ - uint8_t overflow : 1; /* details see lv_span_overflow_t */ - uint8_t refresh : 1; /* the spangroup need refresh cache_w and cache_h */ -} lv_spangroup_t; - -extern const lv_obj_class_t lv_spangroup_class; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a spangroup object - * @param par pointer to an object, it will be the parent of the new spangroup - * @return pointer to the created spangroup - */ -lv_obj_t * lv_spangroup_create(lv_obj_t * par); - -/** - * Create a span string descriptor and add to spangroup. - * @param obj pointer to a spangroup object. - * @return pointer to the created span. - */ -lv_span_t * lv_spangroup_new_span(lv_obj_t * obj); - -/** - * Remove the span from the spangroup and free memory. - * @param obj pointer to a spangroup object. - * @param span pointer to a span. - */ -void lv_spangroup_del_span(lv_obj_t * obj, lv_span_t * span); - -/*===================== - * Setter functions - *====================*/ - -/** - * Set a new text for a span. Memory will be allocated to store the text by the span. - * @param span pointer to a span. - * @param text pointer to a text. - */ -void lv_span_set_text(lv_span_t * span, const char * text); - -/** - * Set a static text. It will not be saved by the span so the 'text' variable - * has to be 'alive' while the span exist. - * @param span pointer to a span. - * @param text pointer to a text. - */ -void lv_span_set_text_static(lv_span_t * span, const char * text); - -/** - * Set the align of the spangroup. - * @param obj pointer to a spangroup object. - * @param align see lv_text_align_t for details. - */ -void lv_spangroup_set_align(lv_obj_t * obj, lv_text_align_t align); - -/** - * Set the overflow of the spangroup. - * @param obj pointer to a spangroup object. - * @param overflow see lv_span_overflow_t for details. - */ -void lv_spangroup_set_overflow(lv_obj_t * obj, lv_span_overflow_t overflow); - -/** - * Set the indent of the spangroup. - * @param obj pointer to a spangroup object. - * @param indent The first line indentation - */ -void lv_spangroup_set_indent(lv_obj_t * obj, lv_coord_t indent); - -/** - * Set the mode of the spangroup. - * @param obj pointer to a spangroup object. - * @param mode see lv_span_mode_t for details. - */ -void lv_spangroup_set_mode(lv_obj_t * obj, lv_span_mode_t mode); - -/** - * Set lines of the spangroup. - * @param obj pointer to a spangroup object. - * @param lines max lines that can be displayed in LV_SPAN_MODE_BREAK mode. < 0 means no limit. - */ -void lv_spangroup_set_lines(lv_obj_t * obj, int32_t lines); - -/*===================== - * Getter functions - *====================*/ - -/** - * Get a spangroup child by its index. - * - * @param obj The spangroup object - * @param id the index of the child. - * 0: the oldest (firstly created) child - * 1: the second oldest - * child count-1: the youngest - * -1: the youngest - * -2: the second youngest - * @return The child span at index `id`, or NULL if the ID does not exist - */ -lv_span_t * lv_spangroup_get_child(const lv_obj_t * obj, int32_t id); - -/** - * - * @param obj The spangroup object to get the child count of. - * @return The span count of the spangroup. - */ -uint32_t lv_spangroup_get_child_cnt(const lv_obj_t * obj); - -/** - * get the align of the spangroup. - * @param obj pointer to a spangroup object. - * @return the align value. - */ -lv_text_align_t lv_spangroup_get_align(lv_obj_t * obj); - -/** - * get the overflow of the spangroup. - * @param obj pointer to a spangroup object. - * @return the overflow value. - */ -lv_span_overflow_t lv_spangroup_get_overflow(lv_obj_t * obj); - -/** - * get the indent of the spangroup. - * @param obj pointer to a spangroup object. - * @return the indent value. - */ -lv_coord_t lv_spangroup_get_indent(lv_obj_t * obj); - -/** - * get the mode of the spangroup. - * @param obj pointer to a spangroup object. - */ -lv_span_mode_t lv_spangroup_get_mode(lv_obj_t * obj); - -/** - * get lines of the spangroup. - * @param obj pointer to a spangroup object. - * @return the lines value. - */ -int32_t lv_spangroup_get_lines(lv_obj_t * obj); - -/** - * get max line height of all span in the spangroup. - * @param obj pointer to a spangroup object. - */ -lv_coord_t lv_spangroup_get_max_line_h(lv_obj_t * obj); - -/** - * get the text content width when all span of spangroup on a line. - * @param obj pointer to a spangroup object. - * @param max_width if text content width >= max_width, return max_width - * to reduce computation, if max_width == 0, returns the text content width. - * @return text content width or max_width. - */ -uint32_t lv_spangroup_get_expand_width(lv_obj_t * obj, uint32_t max_width); - -/** - * get the text content height with width fixed. - * @param obj pointer to a spangroup object. - */ -lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width); - - -/*===================== - * Other functions - *====================*/ - -/** - * update the mode of the spangroup. - * @param obj pointer to a spangroup object. - */ -void lv_spangroup_refr_mode(lv_obj_t * obj); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_SPAN*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /*LV_SPAN_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.c b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.c deleted file mode 100755 index f0138238c..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.c +++ /dev/null @@ -1,354 +0,0 @@ -/** - * @file lv_tabview.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_tabview.h" -#if LV_USE_TABVIEW - -#include "../../../misc/lv_assert.h" - -/********************* - * DEFINES - *********************/ -#define MY_CLASS &lv_tabview_class - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void lv_tabview_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void lv_tabview_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void lv_tabview_event(const lv_obj_class_t * class_p, lv_event_t * e); -static void btns_value_changed_event_cb(lv_event_t * e); -static void cont_scroll_end_event_cb(lv_event_t * e); - -/********************** - * STATIC VARIABLES - **********************/ -const lv_obj_class_t lv_tabview_class = { - .constructor_cb = lv_tabview_constructor, - .destructor_cb = lv_tabview_destructor, - .event_cb = lv_tabview_event, - .width_def = LV_PCT(100), - .height_def = LV_PCT(100), - .base_class = &lv_obj_class, - .instance_size = sizeof(lv_tabview_t) -}; - -static lv_dir_t tabpos_create; -static lv_coord_t tabsize_create; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_obj_t * lv_tabview_create(lv_obj_t * parent, lv_dir_t tab_pos, lv_coord_t tab_size) -{ - LV_LOG_INFO("begin"); - tabpos_create = tab_pos; - tabsize_create = tab_size; - - lv_obj_t * obj = lv_obj_class_create_obj(&lv_tabview_class, parent); - lv_obj_class_init_obj(obj); - return obj; -} - -lv_obj_t * lv_tabview_add_tab(lv_obj_t * obj, const char * name) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_tabview_t * tabview = (lv_tabview_t *)obj; - lv_obj_t * cont = lv_tabview_get_content(obj); - - lv_obj_t * page = lv_obj_create(cont); - lv_obj_set_size(page, LV_PCT(100), LV_PCT(100)); - lv_obj_clear_flag(page, LV_OBJ_FLAG_CLICK_FOCUSABLE); - uint32_t tab_id = lv_obj_get_child_cnt(cont); - - lv_obj_t * btns = lv_tabview_get_tab_btns(obj); - - const char ** old_map = (const char **)tabview->map; - const char ** new_map; - - /*top or bottom dir*/ - if(tabview->tab_pos & LV_DIR_VER) { - new_map = lv_mem_alloc((tab_id + 1) * sizeof(const char *)); - lv_memcpy_small(new_map, old_map, sizeof(const char *) * (tab_id - 1)); - new_map[tab_id - 1] = lv_mem_alloc(strlen(name) + 1); - strcpy((char *)new_map[tab_id - 1], name); - new_map[tab_id] = ""; - } - /*left or right dir*/ - else { - new_map = lv_mem_alloc((tab_id * 2) * sizeof(const char *)); - lv_memcpy_small(new_map, old_map, sizeof(const char *) * (tab_id - 1) * 2); - if(tabview->tab_cnt == 0) { - new_map[0] = lv_mem_alloc(strlen(name) + 1); - strcpy((char *)new_map[0], name); - new_map[1] = ""; - } - else { - new_map[tab_id * 2 - 3] = "\n"; - new_map[tab_id * 2 - 2] = lv_mem_alloc(strlen(name) + 1); - new_map[tab_id * 2 - 1] = ""; - strcpy((char *)new_map[(tab_id * 2) - 2], name); - } - } - tabview->map = new_map; - lv_btnmatrix_set_map(btns, (const char **)new_map); - lv_mem_free(old_map); - - lv_btnmatrix_set_btn_ctrl_all(btns, LV_BTNMATRIX_CTRL_CHECKABLE | LV_BTNMATRIX_CTRL_CLICK_TRIG | - LV_BTNMATRIX_CTRL_NO_REPEAT); - - tabview->tab_cnt++; - if(tabview->tab_cnt == 1) { - lv_tabview_set_act(obj, 0, LV_ANIM_OFF); - } - - lv_btnmatrix_set_btn_ctrl(btns, tabview->tab_cur, LV_BTNMATRIX_CTRL_CHECKED); - - return page; -} - -void lv_tabview_rename_tab(lv_obj_t * obj, uint32_t id, const char * new_name) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_tabview_t * tabview = (lv_tabview_t *)obj; - - if(id >= tabview->tab_cnt) return; - if(tabview->tab_pos & LV_DIR_HOR) id *= 2; - - lv_mem_free((void *)tabview->map[id]); - tabview->map[id] = lv_mem_alloc(strlen(new_name) + 1); - strcpy((void *)tabview->map[id], new_name); - lv_obj_invalidate(obj); -} - -void lv_tabview_set_act(lv_obj_t * obj, uint32_t id, lv_anim_enable_t anim_en) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - if(obj->being_deleted) return; - - lv_tabview_t * tabview = (lv_tabview_t *)obj; - - if(id >= tabview->tab_cnt) { - id = tabview->tab_cnt - 1; - } - - /*To be sure lv_obj_get_content_width will return valid value*/ - lv_obj_update_layout(obj); - - lv_obj_t * cont = lv_tabview_get_content(obj); - if(cont == NULL) return; - - if((tabview->tab_pos & LV_DIR_VER) != 0) { - lv_coord_t gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN); - lv_coord_t w = lv_obj_get_content_width(cont); - if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) { - lv_obj_scroll_to_x(cont, id * (gap + w), anim_en); - } - else { - int32_t id_rtl = -(int32_t)id; - lv_obj_scroll_to_x(cont, (gap + w) * id_rtl, anim_en); - } - } - else { - lv_coord_t gap = lv_obj_get_style_pad_row(cont, LV_PART_MAIN); - lv_coord_t h = lv_obj_get_content_height(cont); - lv_obj_scroll_to_y(cont, id * (gap + h), anim_en); - } - - lv_obj_t * btns = lv_tabview_get_tab_btns(obj); - lv_btnmatrix_set_btn_ctrl(btns, id, LV_BTNMATRIX_CTRL_CHECKED); - tabview->tab_cur = id; -} - -uint16_t lv_tabview_get_tab_act(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_tabview_t * tabview = (lv_tabview_t *)obj; - return tabview->tab_cur; -} - -lv_obj_t * lv_tabview_get_content(lv_obj_t * tv) -{ - return lv_obj_get_child(tv, 1); -} - -lv_obj_t * lv_tabview_get_tab_btns(lv_obj_t * tv) -{ - return lv_obj_get_child(tv, 0); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void lv_tabview_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) -{ - LV_UNUSED(class_p); - lv_tabview_t * tabview = (lv_tabview_t *)obj; - - tabview->tab_pos = tabpos_create; - - switch(tabview->tab_pos) { - case LV_DIR_TOP: - lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN); - break; - case LV_DIR_BOTTOM: - lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN_REVERSE); - break; - case LV_DIR_LEFT: - lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW); - break; - case LV_DIR_RIGHT: - lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW_REVERSE); - break; - } - - lv_obj_set_size(obj, LV_PCT(100), LV_PCT(100)); - - lv_obj_t * btnm; - lv_obj_t * cont; - - btnm = lv_btnmatrix_create(obj); - cont = lv_obj_create(obj); - - lv_btnmatrix_set_one_checked(btnm, true); - tabview->map = lv_mem_alloc(sizeof(const char *)); - tabview->map[0] = ""; - lv_btnmatrix_set_map(btnm, (const char **)tabview->map); - lv_obj_add_event_cb(btnm, btns_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, NULL); - lv_obj_add_flag(btnm, LV_OBJ_FLAG_EVENT_BUBBLE); - - lv_obj_add_event_cb(cont, cont_scroll_end_event_cb, LV_EVENT_ALL, NULL); - lv_obj_set_scrollbar_mode(cont, LV_SCROLLBAR_MODE_OFF); - - switch(tabview->tab_pos) { - case LV_DIR_TOP: - case LV_DIR_BOTTOM: - lv_obj_set_size(btnm, LV_PCT(100), tabsize_create); - lv_obj_set_width(cont, LV_PCT(100)); - lv_obj_set_flex_grow(cont, 1); - break; - case LV_DIR_LEFT: - case LV_DIR_RIGHT: - lv_obj_set_size(btnm, tabsize_create, LV_PCT(100)); - lv_obj_set_height(cont, LV_PCT(100)); - lv_obj_set_flex_grow(cont, 1); - break; - } - - lv_group_t * g = lv_group_get_default(); - if(g) lv_group_add_obj(g, btnm); - - if((tabview->tab_pos & LV_DIR_VER) != 0) { - lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_ROW); - lv_obj_set_scroll_snap_x(cont, LV_SCROLL_SNAP_CENTER); - } - else { - lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN); - lv_obj_set_scroll_snap_y(cont, LV_SCROLL_SNAP_CENTER); - } - lv_obj_add_flag(cont, LV_OBJ_FLAG_SCROLL_ONE); - lv_obj_clear_flag(cont, LV_OBJ_FLAG_SCROLL_ON_FOCUS); -} - -static void lv_tabview_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) -{ - LV_UNUSED(class_p); - lv_tabview_t * tabview = (lv_tabview_t *)obj; - - uint32_t i; - if(tabview->tab_pos & LV_DIR_VER) { - for(i = 0; i < tabview->tab_cnt; i++) { - lv_mem_free((void *)tabview->map[i]); - tabview->map[i] = NULL; - } - } - if(tabview->tab_pos & LV_DIR_HOR) { - for(i = 0; i < tabview->tab_cnt; i++) { - lv_mem_free((void *)tabview->map[i * 2]); - tabview->map[i * 2] = NULL; - } - } - - - lv_mem_free(tabview->map); - tabview->map = NULL; -} - -static void lv_tabview_event(const lv_obj_class_t * class_p, lv_event_t * e) -{ - LV_UNUSED(class_p); - lv_res_t res = lv_obj_event_base(&lv_tabview_class, e); - if(res != LV_RES_OK) return; - - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * target = lv_event_get_target(e); - - if(code == LV_EVENT_SIZE_CHANGED) { - lv_tabview_set_act(target, lv_tabview_get_tab_act(target), LV_ANIM_OFF); - } -} - - -static void btns_value_changed_event_cb(lv_event_t * e) -{ - lv_obj_t * btns = lv_event_get_target(e); - - lv_obj_t * tv = lv_obj_get_parent(btns); - uint32_t id = lv_btnmatrix_get_selected_btn(btns); - lv_tabview_set_act(tv, id, LV_ANIM_OFF); -} - -static void cont_scroll_end_event_cb(lv_event_t * e) -{ - lv_obj_t * cont = lv_event_get_target(e); - lv_event_code_t code = lv_event_get_code(e); - - lv_obj_t * tv = lv_obj_get_parent(cont); - lv_tabview_t * tv_obj = (lv_tabview_t *)tv; - if(code == LV_EVENT_LAYOUT_CHANGED) { - lv_tabview_set_act(tv, lv_tabview_get_tab_act(tv), LV_ANIM_OFF); - } - else if(code == LV_EVENT_SCROLL_END) { - lv_indev_t * indev = lv_indev_get_act(); - if(indev && indev->proc.state == LV_INDEV_STATE_PRESSED) { - return; - } - - lv_point_t p; - lv_obj_get_scroll_end(cont, &p); - - lv_coord_t t; - if((tv_obj->tab_pos & LV_DIR_VER) != 0) { - lv_coord_t w = lv_obj_get_content_width(cont); - if(lv_obj_get_style_base_dir(tv, LV_PART_MAIN) == LV_BASE_DIR_RTL) t = -(p.x - w / 2) / w; - else t = (p.x + w / 2) / w; - } - else { - lv_coord_t h = lv_obj_get_content_height(cont); - t = (p.y + h / 2) / h; - } - - if(t < 0) t = 0; - bool new_tab = false; - if(t != lv_tabview_get_tab_act(tv)) new_tab = true; - lv_tabview_set_act(tv, t, LV_ANIM_ON); - - if(new_tab) lv_event_send(tv, LV_EVENT_VALUE_CHANGED, NULL); - } -} -#endif /*LV_USE_TABVIEW*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.h b/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.h deleted file mode 100644 index ee7d7ce41..000000000 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/tabview/lv_tabview.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @file lv_templ.h - * - */ - -#ifndef LV_TABVIEW_H -#define LV_TABVIEW_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../../../lvgl.h" - -#if LV_USE_TABVIEW - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - lv_obj_t obj; - const char ** map; - uint16_t tab_cnt; - uint16_t tab_cur; - lv_dir_t tab_pos; -} lv_tabview_t; - -extern const lv_obj_class_t lv_tabview_class; - -/********************** - * GLOBAL PROTOTYPES - **********************/ -lv_obj_t * lv_tabview_create(lv_obj_t * parent, lv_dir_t tab_pos, lv_coord_t tab_size); - -lv_obj_t * lv_tabview_add_tab(lv_obj_t * tv, const char * name); - -void lv_tabview_rename_tab(lv_obj_t * obj, uint32_t tab_id, const char * new_name); - -lv_obj_t * lv_tabview_get_content(lv_obj_t * tv); - -lv_obj_t * lv_tabview_get_tab_btns(lv_obj_t * tv); - -void lv_tabview_set_act(lv_obj_t * obj, uint32_t id, lv_anim_enable_t anim_en); - -uint16_t lv_tabview_get_tab_act(lv_obj_t * tv); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_TABVIEW*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_TABVIEW_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/font/korean.ttf b/lib/libesp32_lvgl/lvgl/src/font/korean.ttf deleted file mode 100644 index e0ec117ac6ff1e64332f1a9c378e48c760ae73a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3371440 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⋙EIe#Z8ww;Ay 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

B%DWVqcu!Bdpxs>_ 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

KJxHgoOsO}j@%7H zSKZNR)tWhP=0BPS6qF1jcfj^OlBrqr$}xx2K!re{5(m7}} z?qv=_2`CY6T|JNwZIUaMntBBt}MAKC8EN0|w)-DY)$T~1pYRaLwV9wK%4i0nNwH(O`^193`8#?cTY zT570lTchJjohnGzw~nPO9GmOx*p(6qN_kY7p~|odvyEF$qh5JPt46YrfmP2U-{WTAi1^}! zWEcE?=j&%r&pY6{y|;nb5A+Wmw}fM{7`7rCCq~EHTP`?sp}l8Mp{9a{QYxk$*!VebZ$UGMa&*nhAY02xP%Lb z(V#fEf(s(p9Ri~GE>}Ucdj&_x?h`2Ozbs3#N%CV%c7_zDq+2ZplI=ZEQ^c7bB9VPl|^euB^X!? z&p9bOf|$bn$p7`FJ$=mi`L316oQz$4>1!wND+kD1mQNMlckIy4#bdKaTPHiNI8&O- zc!Hg1_kr=0sw?bWzU)}HEw}3g)WK6)(`S4UHC7(XAV#)b(kd_eoR?I&7kl`xkTuoW z9bwMp-V?NlyeWZFv5SH9FM`&lcXBi*UGmWIX}~GPs}KjSux<2Q23KLk(IsPoYL3+_ z)Yp1=<;uWKuf45#EbS+Uwq756-Si-qV-$*mqtoX3>n9()rMSR6I304iW{*wIU9m9g z7}ZPtlEX#hD`5~U0T*uEvpRHJn754qYvm0RvJg^Rn zWz%&Nue-Il$b2o>;DaX7u|J%Shiz^LbI;7n17}8;jY?PN2Su+_bi~C%#>;uAK}uvl zmT}Cln4d#3%cLv-O%6Tp)Y;9|T&9W!97HZyr7^oOyU?r*4c`#- zh9~W4=#lfD)}ccKhx>T^7wEnxz-MX9h8XU{XQG{?ed1BzsA0&hL5Ck!fg7ZS2rp6- z%+q|xkv?j-xr{JCQIW>gl^(0lzAasTJpjJ6y4;!qyt{s|FXR?$Ys-q<|F)4K@*tHnDnT45VwSR;uyV@Wf;qamM;eQa^yw0Wx+C{O%L%Y}l zK3?(xYy z6BUtH;dj_xO4EO^@+iNPw>6bojiFeKxwOuRFO?`2+~b){D40nncu&L^ z^o@Hxb;`rhLH3rNy5fM|)=%I#CvwWF{k2}Niq%Rb`pQ#_7 ztMd_GtKj#NXnfdV>>5Xj!ZFs!T0{}<2RnL+K{b&P;=_U`yTT)(Pd*Dv}sknec?%)**WgB8!3;< zao3CN+nAq99n@!K7{wq(NvIrGflp(7F2uj2C;+8mVU;bV&=%Cdnj*maX|kE}trTE6 z?~QoTLBz%cjS4 zx|>E1c+o-&BSOV6TY1E_?SeZHuv!RKtM``d){x+E^J>2jK`DcQSoL-r=jPy_q>{{Y zstC5b>p6!v67um5dEAwVv=%zWv9Oo*dCNv5ezJOvPB*-`X_1+zEk+|DzY$Sfj}Q*I z+%9L-;xyYU4vW4j5&O>^7N&eG>lB3EB0lnptwNAzLW5C_SjQkW3RwDT;MU*?u>{ zI;HxTQlcruX8%=?f|9EiQ_=6z7fnG^8c7{{_^)&`@ycC%%xCeq*g%p`2vw(3jKFCp zqbiuw&iUb^17jXLdfr);NA!9I<6${Uy*lk|OoWYXSLQgk;L)H=u$mel-9Na=j5rU$ zZZb~=1;p@5(JPN$Q)^q5&gIFkd7g8jkQC1|vy7c%+-(b*1XSC*-Do|U%7!xOLvx#> z%GQxBXPg7kRy(!ZkNOR*T;Ug!NipCR@&>EUswg?ER#Pw*4Byo$7K1Q_6~t+EiN2aD zVRIo=jFDN0GHE_+F`9Z$DHPhMoim&44x@?Q8%B0D;??(I_Dq~cgd-F;lzs6R1e(R~d=s+Wp zNF;434mO88tx7(gO}n*D;r8Ht_dKKI`RLg6NT-oXSTcq7;GxZ9om`6N7}6>)&o6DM z)T~bOg|y4TTz>176Aimx2F9yO<=?=;?9$nNQXg!=0ADRIfF)jMZ#0 z?I`79@sYV48ruARw-^s66DdT1B9U0w8;>MWDFac>-jBKm2kYSrNmQ~ig69QU3-da) zcC`u9MEHiTGHwV=?n}wapaqH#j)0DinQ72#0Sy<~Oe@A7h~Fo=x~tPg<|E~1ihiTZ59`AvBKWJS{7n2 zXP%?G6m3%a4cCGauHW^BTR?>{WqT~j>dW1}q@^+lZ@roqv*GMgC}=geJA02#4u$>5 z2}OfKIx{>tsGKcp)#c<+IduZ1kj83dY$7m_W$qcl-l{XFk8RzYE7bBk<__-M(usIN z&EU?R1MZLAeZ}m6*TtG9ItO;{-qk9`O?t@JTV!G6k9B}ks#yAcU|qe=^Z@J8gIjn{ zHkjKP4p=Phfej~cr_)12gNptMhUp0+W)nR@u$^Px=rvNijr`7_owxFFpVh3mA-y3v;H(-+x2_V=E7l} z7v70`&p-LpP}m3B#X!4@ocztu6;4+&LBGe{l&{^Q*<>>R&(D6-Mz(a>sA{nH6$G`T z=V3?R!aOU}N>RcNq(3#=`&N}BCb1~A7Y&&qTqc!_Q?g3_P@i3;A0*$>(#-ioX=__ZaPf0zOJYFu3qEw;lzldlc{Xj~ zAq9(^+xx73U^F(7wE4LJCL^{vo*xLHC~qK8-|q{hYyNmF%}1BSrC2~A_u0~^%{t`> zWB!yncvn3=^e#r)j3yh zA$C%=`AIA1jihZYPtJYrSeYKwy>`(1LT1tEFa)e#VNcNJGW)_t!6Y!>>7T#g6usZq zw@2dRDVyKbKfg;D@W;4ZC(zjM^JlApSf(Jh#ieLaI(~YyR@Ehc>NdHI4oeiFwX)kR zm?17WBkhA$B6d_}-^6@x4KH(2#pXJ#5sr~G@5N|+AzofV7mz;>M5A29kn$9(XvTRd z3^j7TaN5@P0z;SgS;21$1w={d==_Tsg9@ z&V_j!dcjKWEZN&RU7pyo=bGqnZYnvOF*!wRF~`w(Jd51pXE2NGE_^oS&Hm?0NSEaP zhR@${2iFDYQfq(lr60Z=3AP?4!(sfREO2UJSlhp!~M>a&2-2KUa14ui~dHWSQ3{T@J^JT#LEQ zv_cSa&1fd4I+xTggtm}(Mv2kwg8wOsu22}t^?dn7^E4jl)!)J!I4QdU1e7$Ym}w(GDLK{g}Hc0E{`UMX2Tf;JbYg!mPu!+eFQr{n(zdC7zx9q5>fuTyN>>_ zs&&I}*Lf9njZw=BRip#rtXi&7Gb}-Xo99(Q9@TkHgDwU~l$f@JB zRs(9IFvlgE_6G(3X0y`?lak}GCtZX3%uKkfgtt(`U=sWt`d+F&xtzCVZWz8|=*)b6 zTJLLi(lx_%`yadgEatPowqeix2ZkUG@z%9#0-N-#jAy@(xw#(MaoKgU+hq?>zkwPq zFNdxYIK2oLAE6Ua2BjK(al^eVVekU|dI`F$MPXL`wwDsnM0OE0-p|I`wLYnsdb?5s z9pJGOx5&FeDOMiaK&eD3lL4X7>CeRCV$dH3r7{p~*WPt>8nkdJv9Uhya>(Uw4>{}c zaT>EG;6(A3pW__%h|A?=e)J;jUcdhjfnAM+-KL5tAC(A56h&Xm=Cs<)2=U1y0Ze;1 zkAP;I)$YwiD{J(7RHafWK|i)9!#IM$RSGc{x7UHfu>hhr4bkD^Tp@vjwL^W0Q}Fjb z$NYMQZgId?j{Lcv5VDB`Zgm_#DzzW(fqO&3z|ferpd zT%>lF=#lKM=dAhbhb|ksWIjJ>!xhO^=oPu+4ue*K-hY;~R&OCuWYL80GTSkVgWkdw zB3hgdca`2k3&NP5bfkpw+N%B~MDtmnh-Bk6Bfs0IsCb)2=-X`qRaA`Zmof~~W^J%; z4)t#y?h3t8HL06K`sqBMkXmT#J_fy6>lbUa1>>T@5hhq6W9_z26>nBLBkejzO65|S zRk`d|)1GXqlp7vN7UYR!IF?8^3RSpwOfnnIg>z_yXA0>|Fq}!|(Q=3XXWzkLeiG|* zR`MdxFdjc^lD`AgQ&!N&E58nfK*}m@tK2b$Pw{yw=+$P~aAMTNJG_km?=-~nVx0ln zv<({l2ztGuN~KZPF;_{kU^S|B8iqahDTG4CQIIZ$LMZPuh%{zV1N1ZK;iFVjP%)1i zsG?e(W`n7LD}B+Q=?l_3=szU=OkZ2^oDo>U%M^+IKajplT7>EtmcEOMLcAW8z2J=w z)CL@wpQ%A2S!n<;=j#fWi zyFJj1+T13!PNh@BpBCvLEZ?4m2O9NFV-C(?vtZEIXGSn(URUgPMhAztRndd5wpf#y zfzlA>cJedL!EmZx8(6S9?OX$8)Rs^zp3x$3i=A|GWwux@It&KI?&KhE!H6|F|I=>3 zd_sf1=WgXPsz=gxIs%E>k?1>>1=!occeMM7Vv+Kc#Bx$TT@~#sfEtWR>e&t;qy~ks znhTLw4#?_HCJEuXKIN|`}^CVA}bQ?tW_ zj22t3@n_K8rn6v-9!bO^f+rG*(mRjFQS^0@6VX6C%xB%H#JLYRks7i)6`UQ(AvG?^gh90>A8!?s8&lG9+QYaYR$W+)mJiw?8Rlr$n-=@^d~8XhA#WZV=@eqIbjoX|>;`-MdFZP! zt3l1<3eM=QTf^6ef7n+MCt-)aW0mWu4N;NG*eJ(^D93>{B?~XKhQ)uV!WPm71dml` z6vYUnx;(%OMx~kOeJtrTuDE)r=yv!ABUY}P89W&C&_re-Ux;S1=_CyxC1VMnKN1dm z!AjVy$1*)#x|FKO(T-VyfR`7AR2a1~syb?f<#x{QI#Vr9H705Ug*caqWOCc%Vk5Ct zgK09Dv5)c|r6L|mhVWSpsF&B!xIQ-jP@FKb&%)*%VU8h!-=$W1%~oS^sI@E!l{+eD z|722(j`3cBAI|HRvZ?Jr}HQdazoxPfO5F zdEUV!cZ>>I`qe+!dFR?)ddIQ3;itDvY@e7-MuMJVvXBr=-I0NE(c|qF$Ga!S?i_-O zfvQp3YF2^w)ni4{jtDN7sl@xdNOfh(%LUE`w4MzfjP44E;4INCpSxPQu3WdgHb&yH#qHjk8#FL4(uj zvDoa6j9^FlR&CVH)Z5weB`{*8%&|QUHe{DkyrV?}@jq6xBTlf|Y{bU|Mb|y^XK!#N zF5AD~usA*5&>CO^*)ieMhkU%>DGFXJ>S(lfEM`iIqLlt)6mF-$sU}AEZ<(5YVoNNf z8QnR!Ns)=-?Dxq;_7wA8UYFC7MiEQIA@E{XL>knfHyW-R?KHc$N%I+@U+ql{0Z^Pdx~pO_ zTgZc)6(gsQrvnVr$ul1n@A-=_Zx(lNo$k~kL3K8s5}MUw2J4GK92Yq4K zI-4dgJJ=j$rg2f}?I(=UAB@_T7cZ&Zd}nWrw1%qbw=1iO+0(^1v0yR^?S})dG=HS5zOYxIhe-RU(dIwJyi~naJRHBB2OH z+(~~nmrANJSt*`LU^J;O33rq_GS~BV&KeT48P2YdyS>b7wQC+L0t9DEoIx zp4|oupPpzXTZ<#DTc4D{SL`b3RJaqX>2-{uQOH#~QEhbMoZ@`T5SfDW&6yxb7vuF-j zn=y~uymeE15PD8KV%KY#a5BeH35CATbKk(4%SE4E!NG2`K@%~uf00F@hYYAJs(@Z0 zdU5Gpr9!tK9i{w;3oFSa%G~r=xVJTlv8DEXQY^z#&<;nYw$C4kdoJI7B=Nx=lS8d7 zn|BXZ;VYmz0(X;Po5^TC<}QR%&M0$c`Gzw&OEce0`CA8*LG!q7dSJ(5rI7R_vJ*2g za2w6OKb9~B-9pJJ8mJs4TA7AwpfN;ICr)|r^Ik?S_f1>?}BO|#n%l+kq=<5I;&J?I%I%`I)aV)x{H*pJEG za^>fFhBz_lSQEW!Z`N)LM1y|$Y$?M$)79v8^3+hZQ%S{DiS6-dB3$25PPdb}fG5@s zd8!jPAF8Jb2DrjY|1Rnc&1$7a<22~beFu371IeXDvz_k9Jt>Q@Zv>A_VwzS1Lu4^c z3)a7nw73jw!A4q&z~|OhP(-;!5Bm3ID6LBoySe3oE^Z zmt*}he6$Gx<@mGz<62C}5n=AIremyC$dk1IreqhgQ?-O&ofRuq|BjKuwt>z}o)5%=#m&vM zvgjM{%r4{;0Y1n%^ft_Cl&96Zpron)!fGGZ(Su@d2jXs5z#d*$iO=>Y{zz9?@;N1) zv3k(+JO)WJfv@O`^s5q6^$UN2hJK{;K6fBm73FMpt|<<3$#4<@Oor*w0`%GD_KBH% zW@hNp`i-OTGIuV{S1V497H*NsWRR;%Xp~12k5XryRi_Y73yoM!_DpvC;7lM^ZWL4b z{kcUyv-$Fqg{CK+&vs9CD(0Gh^X#F$NEUN(7*qi>22dEWS24~u8ge+H=scGjo;K?Z zpf4+X2z9*M8B76#_jH=_9X$i3v2>A~{Ufbc3rXZ(iR@k|TSB;F{W&8N9%?u}K1cG} z@n8By1&)GVN=e{AZxIp+&rWA1?p@w&xBLD6kYM#%BL$1Y;+m`Eoi?>PXw|DNN>og_ zD}FJR8r?p3WM<(`y+LgzoW-uE{Y)C7ZHNaBU0?4W^G5lw4)r5u^enxOkGs(BovUC! z&fiRFtv1bv{m1t1FGs?9y~Ub~jwY9`Kn+OHS1UG~IfsIAsiSslz!S}Syw!R(@Dfd%zmS9i_z}HCL$}vv$Ss!V0^s2m_l6 z@2Bs^G#n=>c$3XQ!<)JB%4l~0WGGr_!qIQK7BORidVs0kfY;;0SyXIuJMNZE>ZF+d(noMF7{Mj!4 zR~~AN=5zH(+u-(=V-dTE38;*=)~waz+H@wJWX_qrA#|*xZ>^5bg{A4mq<=n>7F_94 zyxiF)+Q%_2XC@pCg?XPXsO3|RAm?=2?ISMH;wcCog&LDJ2;;h1q0#D_CY_c#wFLEm zY4%d&aWI*(9~+^3M!zH$TVbXeJrgw-=vQA+_Vo*@h0Lu@r}s9-En$BOg^PBVRc~`U zBhBGf&R6ziBc32-}?BjV5e0^*9sTm2KPpW+J(vF zLMF^)+*1qwl1<0k$TIF0-6}bcd=jUf=wKihs5;Q@JGTgS?e&K&IH##Ii|S+>05$DjM2m zSe3@DHW@E_@98-%R=H~NQVm^GvKkY3TsD9_*w^|n*c!)7n=*TMZlFGaypKd}&g?O4Rz{dEb9pPqP>U6TSI}cA63tY=dsG*V7rWQZm8pIqL)ut=^ex>C_1wvzoOlSu_Z0%%;N zCfXhwY}O-~dV%wpFtfzWY(s9;Hl$OUVXFfgRNb!ZdBw09+{nOMgf7&NV1h3L$)9$} z?N=-;*WNo>`z}01IGxP4qhEUcA6~oFliKmdGjHtDI2f!e=^p$U;$3;>dE{s4bL@!2 z5f^b_Fl&EwCfzT*@|;z!t6C~^OmV3Jv83nzSayajlILYQY~wVbY!%ZL(EChh($Vpkn5K!1 zFIa7iUE-w*5x(+*jG68I{JZ4&YVSw28gWv$jAL|bt-#sn?%32BfjiMeMb=+%dkB%f(;ay zbT2vLDzN72lWWpX_*V*Zb7@q8eg&wOUS(MFi(v&S_kR1lZU5Mz?md$=%fHgtBW8L8 zHhEjqehiPpV2|Fnaco8b(~$XIE|rSc9zQ)F&Mn-2utE?Sxw$YFG{}EQWuuzvYJF{LU!LY+fAd%j0Dg49tPSj05>BDae z%==o?K9?CmShn}wRrtwL$l-RI!%mlbIcjm+_=Hn*Ge68HQ_0+WiVPr@lM5c=)ekM~E-W6*^ z2PTuVaTN)Nn&Ec|bm)umg2zpwa#tM^ScNvi1#&&f2&sCr*>$zG86&RL;7X*BT?pieMT^zHLw9yq6t za=gI&XEYVd@MYJ#BaLu(Q)ZD@lUSq~d6&EHxoHL9Enb6Lu!ndjU-i<_7h1oE!$=k2 z?Y+R89eaZ#*e;;))9nK5cRH}f$rA6bnD{Cws!zV_*mZnwD_P5zi7xcOTb``nb>9c4 zsM%*AtjIVq4)pt|_AxU5HFWC6WY}HGw(flWBb`e7ws(FMJgvY!Itwu|3IoP^(s~$7 z(L`-@6g5*0?8wzT<*O1iOQE4`*T<8@cl{sN&47!+$eszAIfI}J*j?`3K{`~NgdDu9 z_hH8}1-()z5(7a0NNojl6{cZ(B+#F8BBjDcJzCBn>Vqy0XtM|qi($9Z86Ljm#ze$j z%++7|KqC6iD1Q)CeTnQI=EvX<%~N)wbu#okl5pZELQAU}tOhM3VYtttdB34Se-=*)jGnaYxmdAuj28o+AzqUHRi&`FlDNjf%C{2L4j?wI@E4 zJ&p;40gFS=?TD-B{FtQ2?mqVs@?-j>L3TvU#6t#~&XMvO(4Z-VF_+-hf!^zC^y!ob zZoo{!Ymo;p%d{VJTNqWm&jb{uP!*V=;-Jxz$~qfEk(J?WNbz<@fR+oaS{#>_V9}7z ze~ye(9LUt=_G?N<%+YoS%>9hsOq@m`IR^2t!PYRg`s@G*9*Hqq3ds z)9esnDWg*U)x#56sa0E(Vtus!jJ(rcElp4`>-(3sPt<2;UFGJ~NHOa3IneB{!gv!> zqhMA;tQYHLVllhMv^8dN8aP9e<9*Dd6B-KsXs%?bWk!eRlMD0l!thupilJNuY%-zX z%gb7ZywAgeam|sCMPq3A@#nnB>lXaL?;Ysd-j3c*v|9CjDXD4Oxe^+Z;$a1hcU+CF zo`-5&LCL&bH6wGY`N}(7u~NQHOr}Kb_5=I)t$QX)b1>3{qDF1>SEKP(s#SASzflPx zfkpEMgZ0eO+b~iJCpL{hY>#<-k zF*BAz5Dzy^u0*+tn&<_d|BzaZj0?OJQ&M|Ik#l6k@M%=+*qyg&L|)Tk_}#O-L@~J9g|3LCj?p7u$AE6(}wwWSD%lP^z75 z*LevU_ydUMwOQ0$nd?9 z6&%f?GKIKIm0zHiKrWUV;Yc7pJDyZgRBuGm;}Vis#k|{yd}e?ZjeJ>DqYU2|aoS;! zF_(#cmL@4;w-vV>23n% zDKS1$$oVSWmfH2bCmtI}9DL;ZZ%}ZMTmW6%U%3gD~UDGXI)DE z7|-`Or02V(=a0N+{rU4~*B5LwGISCa7jKE%JRXxu~UMLlWG>NV>H*W!E}<;CBRwFQ%e@rizSmZYhSu8DQVhu zA9-a)olBkESsw|NOF6-(Fn7h!>Xa-{bZ3R<>Vto*pDh8r@ zU@DwirkE;p2WAqHu&a-$VPFcwqcF?|m_iT-n6g^1Ela}GK99zRS;-+}gL9%DpKlA` z^ZRk$TaYh11e-emf5zsZxLXmgDnwM)R2X6_(n1B~{qVbQ|%w}umg$9Lb@NZy74@H$;1-k*6uWnG;8 z8f-nkl)2V@+(tAGqM`;=zqN~dNf@L+>q|O@&t}_0kjJEVFS*>lI03l2fUDK}GQrlH zqy$zOgWWuOM16&Q0kd6ir$x{r^G*zJ&^&Bu+^}ymwvirRzM+x3ovxX!BknrSTiqU0 zKyX0v7#x_j?iXG3szFwNAMvmt6NC?Dm!hrI_3H1mSQh|&<7f?$(tWCw2{yktM157X zYD}Lj8te`fh+-ORzG=wCJH=)$&^~))K|nYTEb}`g8OkDG4OxV;jZ5bRTPztdaEEry zjnontBRBrm8!neZ`BDtyZdsk(#L$_aHprTrPS=2@}*qRT+8R|{@?xaEt&Lz58eC@ z6(T^Ie#}=PyBRa>zQpcdfg>mNZ1nMi%k%QE!0}&u*ShTdM8oIgOcHzpyu+#;wK*K* z@+O6E_=)S6%5b9rU&3ehi~10jjxC3g8nMJtOUc~n$YnAGzFbE5Jzvg*0CV0PpfG0+ ze(09B)7Uv+e$I_SbVjd}F6xWC^hZlr*})z9&IOons#Tu!d!)gW(g!z^MH%P`~-nVb1J z>~F+cv4scz1>LFxZe0n;aBI{d->8p3aiS(99&8Q9a@Fe04D-**a|Py6>QVryKT7)x z-b5l@F3RNebJ=Y;9sOJ%;-?q=>~%f9&I2#?yl?r;qF@c#MekC;g^I|y3p<%#1_omG z8wB0~+g+^s9Xxy;k(c@o2<8jg5O??mG`sHO7;fbzCP@Z40(4D+WJFXz-N342i5ZJ$ z$YHW)a@)Xdqp0qg?0u5Dk%&04mZqGEblh*gc26j?>8{JK@53L(4LXK zQ+6ji&)g2$t7N(jdyyzNN&i!jXV3i^^I_)pk&)ii_&C++@0Jyq-!Wf=)uDQlGrwN;>ML#t^mTM#Ic! zTGJDwow&z~MT`MYWLu}{$|XC^$x@+|C?!j|-1z3PStXokB*W!3DNfJGUW@qNcIG#T zp48}`IUh0T7<^06J#&aUtO-G|lO%X(_+~ZTvYIELwGE*SJ)HkcKDhYA2ac2{=f48CAk zO*iT=3T2rF1(vihzL9y5v-cD7ov0_1@ur1*7P$U|tc@AW-^b0|Xg~GkWSRN5fr$^@ zd}s479@slfo1P5JUwVK0v9pcxq0ip-m{jkCkz0&xO!g3a19Mce6*qXV7uuwiGV?%r zcyQD{72nkEeWnv$n(53<4L9O+;EsklD(<}L>~`-JcO47(9=`2#AUJw*-zn-w^i5L8 zk*%^v&@c1bH5t3%S?l*^-8=82d!vM9PleFPZw*@oVQ{DjWN08SP9DDWvSC%@h7(uhE#_kc=XHMm7x}zaiZ(ZV3O*|FM#O+>q!ck zknuG*>o*>~I&U@~zI4kibefL@=k0foD_IFnRS@A1Q^@A>?hB(p+8jrUf_bJ7JgTt9 z3|Ivz0Uu~e;WdDm%;UU=aTLxf@rVAI~UNxY(93$&Kn3~#L^k>xOal!kSGIZG<{Br(-!xHK%1-t ziJx9frH={;iAq!#(t{emqoJ~eRU8rcP>^@K`Cy30c8>FU+X=Q4XV_uplgNofrn@%C z^mV(8ibm>@Ji!c1K78Vq%;&D3ABUww3m;V$o7UoD9&dj8;p5HfCGR=)1hA{5g>YsY ziU*)w9!I_U7ucQn{19;ZiqE*vzK~erai%l%@X4F;;Ds?N319-Mtv0RM^-#oy*p4=2 zb-50Nt#CwRHsnh2aRLZ5gJ7|wq?E$SR z&UX*i_RrV1T|Ru(FdsKLL(XDF%#$M}ci0hc*nJ*rb#r_o+Tb>2_El`6$5yTibcH)` z)qm!H} ze-$vl0)LZGz0g_Y_fy8;GhPnoNxZYz|`LSTqlllv?n0XTpPhx3bQ_gX(h1fT$@(GJ+3l6i_mlGu zMIKx`E;dAqA_kA%a0I)Yio$6s`PjvIhY$l9G!_LffrfEd*ck|}qAtUB@sst0S_cM2n zo2Iu&-s7eBc?v4GuwDwPAhjJRjm`%q#&&wN#~XcQ#FX3Vv~RB4k3bCm@2 z4r{b(qh;>>PhFR8XF8owMf7{U3)f$BO`{qZu);l*qd1%SJb%+4UG-M@i=%Kgp(Igr zX`2gg+O{>|@uU)2vtBR1?3#)D;%Kx*wFT}hfzP-Z^=jXTyu8x5kef92jhGd>s*y}Fpi>j@v8 z?u0Yt>FzePRk~7~51Xh*%A-28Q=sIM!t`dqbb@&jzPx+LhTW)G!z}j@;$uXt+Jj(R z%{7;3;n8aQW52IavX>zr@%6LM^nOD4SZJm@JXV?*YUNsXD|t=tcET}F)<4z!?0|qR zdgu?8%Z~1v>JUHYV?D z=8ku+V@+77jk&dfTv7;oW3f7d)u<*=Ic(?>N68cuxNfE8N)<{Z`uujkEXH1q`jLSR zuyYp&oq~@Z$^LoPdhPBv#k%Pw^hz0Kb|0VF+cFoDl~OF1%27)V0f!6<(XdItWEq+t zUhvZP9mFS0<7&OZFo)2Td{l$_?^~|Cb*qCsZ8KQZ$p)tH2Wr?zi=!%WC_RHgfJn_5 zj5@=c^m?UM%d(MbYe=hBg9cxb9bt3icetm9Pe>(sC^A?HU9q5e1$$mT{4F9N2r>2l5)p!xzx;Rd8ecEN>i;Xs++FXzwmm>T zLH~~UWLf5Wj6r6Q*@v(Jfe-`1=vWY^&uj>vtbLU%Bt-7$-AAtOT}SS&GKRu^*~hXm z@=x^ne<$0){D%1>e2#0#q*2j2#`8X^UnH^Nv%X1w*vpcy^?34=Vdjq-AFX`3mSQ#m zCc3jJf*9~W!9wuS(|Dn~SMfljgD=63P!LGx5heN4b3bRe(6z^}uH1QIPm9)GqJA!J zMB5Y^uH?)=wOU_moW1N|JYTuyXi$TBm%_w($lt%t!+>nvQc3jL? z(GZN)lu1Rjl<`n9iZWV@0_CXBcgek@y&}1B>WK7jNKJ*7Wi4O^nSM?XNW+FIXLziyz43ZNHcUuoWV)%;L&`8Ai_yociA3&_F5 zm@i!TIejozKWBh^VT62p_twjX9-C<}U+Dea^Ua6fcK>Mh`j6lHdRpR%v)vAV^G@_^ zxN#5sL!6$dJw|L3@R`9+j8{QyBIakX(!TnYa?}#al4-#(twh~WjjD2lD$LEr-u@fj zO};ezo8NrmbBUg{p@G`=UB22<}FqVg=9C~L0TUBYD_AKDF4M!i@l^qs}fml-;ES>KD1ziOX6d~NyjR~$~zR42rFQVRnfi9;3h%!n=; z3rA{a_bo??n;(1d8?ZcJK_X7_xpNre_1tAwqr~bb4Cx^EsS~?XL0LjO9?}N1a zGIsg>6I+w)w1NzEWzwp+bR^z2E%~eJ(i!W%vbO86ksAdUpy%KVPqLq3)9{Qq zWM|Mhf?|4$6ct)~GL6Pc9<0>XM!f(U<3u$5(JtrSl54io^ZuR5R=afWOWuWIdmy*h zvn|(d=9rmU?=boLbKLCSEAPDfn&n03fgRUAboccqn$GD{H{bKXwY&B@H}AUUuCv!3 zq<3c>76W7nwaal;D}hx-AvMIE2Z7{-o(Cn_o+syeqqwwCXA9>8lROVpW?wH?BiBOR z(7L`)ya=G(F9Lc4d@6KYP@5d08t?^PjGGrj#+-vZ|50xbxxWYBU?Y-V3a*1ce>DJ| zhcg|j=1`p?*+LX7e7zdDh=<&SbpGGL2~xt3noFldtg>)q4~= z^;2*-pz#VwgG-%tJ=qkGW3 zu6Xzatp(Jh2<_FNy!Wxses%+o3aGWm~YS{%#|;j-$pe#)UUIk+%Z$U*jYYMuFY;)Uf#DS)XJQ`=6duGsIfioZD%iM23{Rw zuhYdO$pT6j8eqXeq(KyrNG#k*N*Ee|r9wceP?K=P?tIGXz?w#Iy@4dG>Eq&59*<^d~9ky3`??nUwDZ(O( zf(S?xr3i>9O#~E06cO74)Q1Imiac?1^Z%VYGbzjNlHmLAkisOHIbS_r|Aw}08(O%K zeqO+%A92y5*6wclxyGD2J(wo+n+0)i>?$^zxn>c;IE7#lO-F41{Tp_E@AmdN)z)aB zt94;{^Xz56;~mE$3A4U>#{Ttv$?EW&EnDUe6-$Lp2TrR_hq0(`o}dSd9UB5?QMnKw z0fH!cv8KUUU4T3CCAUrGwQ?YgTiq(D3k* zwX-|JMgOXeTdG7pJu*y^5vr4V1f7XNP4G!1LLIE&rHnUDOp6@o2fKo-IqQmHBSaT% zh-f|7Dzh1F?Fo~O&mI$;^;Mh2<}vC`OvQu&F}Sx#+k&Bvh;wAm84pd1JQIA?yaO8g zf7*9|kNle-Bxmp!kt_Mcu}{m}t9Mtg`9yp}?F;09;qI5jQX>pP#0nZpHcQyxbkq?~ z{>7iyk^KzQejECHsdhDG+CF{tv5#D>u2Az2RjVX{Isg$2byf=7{`hHei)8!`qjeir z)aupkytxXiu%RwYFz#XQk4~ z-+fH@t|*t!FP9&xFXZskwH!V!o9gOH<#P0MmV9PfkWv|sjD4Mb1GZqDk2(Ym)pP}? zB?nT>6oE^prvbR&+aIi$vm<-X(pCIx-uWEN!u1WaaBag9^Dj@fwHJTfd;aGgIVGm!2s$b? zc0c=ToL_tW&I{HJVOXC0wd@F^=7nFTBO)MK2#ZeLbmFByo4 z+Dk?OjOkf)Q-Js}xt;$!aZ?IR2ZVF^N~FU_7F4eLkIvuZAH+Hkl0lfmf^D!2%KRH) z0H^@C8K4ZT=jq&bQ$WI`82;Y?>&y81kLiJRW!shf3(hv{lceS1nFA(nY4R1-0o3xZ zq6=6>#6-#x391!D<8Z;8mFk1jGHIv4^fDRjdrCe%V9vzkuE#3;gJk68{{$92>hY*H zn?+-xXy!I5h(X6FThPcb85}CfFoA=@%p<9>#F?j~r>6k-BQio2uaSEOVlFZopM80H zfS$vb$-PQ+kzRK?{Y>~hPe0AXW)8DxoPLycowP#!$X0O_x^BkM-C1i3Wc5ZanyPIJ z$HXEcRw}RvF0PywkoP9LibF#K!>#eu%GDdciY8#G0Zqv-pSYb-%p6jh=WX(8({9F0 z9>H>MRMSvj{&35A#xRou%L|!wVfo5pE?ZpH>i2m37_jN}25+4f(9AcN&pU8n-ij6U z^KzaH^{idjGdS3@Zf(yHvth|89S;>Oi z*p;qu$7PD5>-lG=2k!B$7jImc%coPtzV5EHzr>AT#r%CUhI4|pO&ffKRuJ2W*ul{B z!=wu0iN3?8=QmBOe2U;=l!StREM)?UN>N*X{Osv~tK@kFW|uE+!lB!k%=Ygf}{4V*eMi z2&}lgVqHlK2ON=6iR35Vo{qKo8)nUArhAoM+UD~+eON_DTFnfhMX1hY-EE1=+|w?4 z?TQ&gKLLC5ZlxW*QX*HP_MDms^$y?qor<{nComOWA?NZ>w~UPu1OJ=pQFkYAakg9T zs$5gPYsLV+MFROvjAT zARXuF$^ONP!z#qF%mw(6298}IJ7b&>IcKntb1W}R#-E3{n7aBzy4scL=uJ8jueJRh3p%a zE{R;aZ0Jw#lJ?O#q>cYySDy!|C2zN@SndIW=ExDVJ^qt$HrWJTQ}cy-R^ze_U;`!F1dWehNZTywd*ea?2hf- zmacs#-gw2f;~*1k%aXD0viGtMNQYaf_rv))eH4Bseb6XHuo3qX!W3W$`k-O2=3p~g z`0#J?P|x32&l@TiT+Z$L9)4u^R)@1t8l1a)^P)M`lH0la#AjYOb-&wPZkxZ9DOdT= zkuSXz!oaDK*>i5+d&x5l_Jkrh=A?64 z5ko;u1GO=ZbP~FE>PRP-PKoW4507xLjYj}rO`d7td+YIi)^ViMp(F33a6H7XuaLn; zu>Ygyr!z@rcz&9uh4GZ#=SP%k(kN-}l2GPUUw8CRZHQ0}}EAGbP5Kszbf4fzZ-wZ)*LV zwRA8Wygh49vu5xs(}eB^MR!kI&x)Ruqr<#p>jmf*m1)J2+x9JGGBcpm1dmbQr$XoZ zh7ZdTu%OixT{%PAG0MgHR4TuCK@NR@i}v?*boA}tM?ar4O-R36$qx?Z%VqkxLawd* zJazx)nHhjONgr4c=|Z#ERF4+cJ}NAbT$m{>|EoH8piQ7gp22z2xA=Fb2_mzT<4!DYp400|*$dnVZdeoNsLk43B*B@$ zIdRX^TYfGyiWx4<(Q*(`+TSuG9pfN(5O&uo*DRYzNSr4@t#5bKXd?W-rVH%cYSdzM z>vbk+wV9l#wPE(Lv;X-0cTHalef0i<2Cd&%^z$cx?p=Nnxr{%Vd~vL0+OWU|xS(=s zbtcE2bZ@bU{%0}qN624Lo(xX-Bhp|Lt0`tkBc4%@{*LLq+J`DrjEJ{nLpS?+Jr_bywr#@)}f+&WIl`I>c{hs{C66 zv2ZvxFpGX3+T2zuwQb(miWcp?(}j9>vAC;Pyv2=@7Kg{<2uB=lE*)!ci>K4^w)R+> zTs(aoOz0XZdghaj+`o{&fW8^ed(70PVm{rwdpFO$F+8v*dFkL_WV)bzcJwylst|dl za?$Z?WBKCgr+xi9(+38Z`~*B=RJeu(s~q`{s2J9Y0M$$(Aw9k1G%5cw83shJOc##D z{CVCs2RWw!&ZVCa1}Q2NqjZW<^Ymg03gDP26m@#U$f6clTNknjET19G06fBt{7(*);_ARx24Z3q8;xZ=F( z*VE^#{h*?~4Na%`C!V4+sD;%HsE`Ap@tQ{FW2Q=Q93qnHz2mu=K(mm)gq&94-=|oe zHfbn0!3t`SCSYm$Bd9Q;KwxHWNslbYCk5mm#NB)2jmeonvVq@DK6mDs{4ICi%}n2= z9S3ES+}jaFn~iDohgpNoiz@mF48kUXo@mdek``kz=IK};im6aGr;@AtNIEfHz3|80 zy?b9ygsPQtu{&?c)aEQY3xP9?r~Nt zjjTSuQn_^XJjVB*(7NdtEJFW@kop+!yP&4a5#5BDS}RSSC%rH7fBB58k{d}?Qz@4T z>x#G@?3287=?pNy>?suXl~&a%PR^c4l(3mipLDm@mXwHV=4hBC>poMaDaeJ7lJ|F{1mTr}@kXmDCoP;V^wq?hZz$v*xkuf6te zVJ6^h;CHyHmJ2J#RUiEXkW9T>>zWKR0BI6L8bq=K)lvxi25B6Xl9nbzsQE3B8Tt87 z%HRJ@jvve#SEze5(y-pCH)F^tvLmQn+bGl8)E0vgCEloiVFNS4#ENQl^M~krVE8f8 zK|39h^M|^|Tw3P)=wpzouzv>289y3UK4RdO-g1Jnhy5X)Vt>$DEb5P~|3tZxrcpUl zCLxK}_@9we9+{ntM3S=y6X9@TcD?0XSkX&-Gq??ylR54U3H`Z3l78{89j(*p@kCPqFu~Zoy-1r+u1PLhQsUYJ6!YT)vSpgz^9<1tmxt&>n~S zYz@?Wh)Z;MwJ_U&4zi63-X2zdU_d8Vs#v*bB`9SMKC9ll{^W}{^ycPOPuO+kig|Nd zt8Nc7dfH{O<2GG)=B9b}#ktk{ZribRJ~lL<-)ist`JwfzF1~W>Ipi~)Us^p!I#OJ7 z`RoA_3UqfbUb?Qc^K)xf&g~vKWoRWsV&VSo#S51|$AA44{|(>2@I=5RYB_0aFJ=V) z2ArTkzflfi!x`~l>0U^JP@k|qxLFU(;-mnnnHC9Bm$gLRZdc#d7k-gD}N#X7pE=#rLr$rF3sCqOpqH!pZvC8 zr|s$4wy&pTGlgI}VwdXJ*!bDdJ3Z-SVVE2gnPuc}@NIM2;MB9&i;j@r?=zV>r#+5V zBj3c^U&JpUJz4837vysp89B9B_*#*>ek45dIdZFN^vBxg z5)w(QC}IbLSZw4c>s9={X_+*=dmK6R42uE#Hyd<8x9g<05@4^x-QcImC;(?kOH4{2 z$rp#ii|-hHgo~y#943@mEE*kWp=*u&7JaFboQjSWIfvb6Pz&}KmByCnK z!_fP%{SiAJ*_N|$rdt|k!UDQUXQIJ-urLc2)-zU)d#qUeBISqC54e#lI&Z(c=h2Bb zBM*-HZe9FOV!iPP5f#Da)lkK&sh8hw-aL#l}fuVVUg=8)()=uCvji%Jo#50 zft_AwFuR!|&>5*C@Py6^3g&`=*<$f#l^kO^O~KwiF9woWlq!jmDBXe7lbzV|N3nN) z%4on6C^N99(V@kT%F+eUakl|?y85(Pn!%WcT5EVU$Sk!&sku$QP_h{GC;V?hsrgb= zsij-1F`to~%f0?OX}5liLL<3RAGs(=m<;I2w0sJ(^jVxqPAA_quTH$zQ4|{!65iy{ z2SrCT7{V3?&f`j@Qdu8GVEtwJmyfR0m=-^D8pVMPx&NbUv`Gg^O;u=KmjMbbmxn^T zlKaIkknuZ~E@Mt;o{Hi>4E$e9zJUtj8r^3%p-=0!*A$(KEeYVn$zon<=mFt26|SD} zq!tyLx+k55-{%&DQ-!k5>j{LMUQOJ<<;^2D}3q{-4Bm?~4?aq!?hb!#Ka}Ey$>qpv$pyop+r4p@1ra&;SR65CtD*nc}OqL+a zlLn2Z+O}f-I*(%Y#j)=WOOcz#p{e%dJV~uQLMtKCsXDCEzn0@e&|WgH}^* z-*!UV;jn+V4*QmDBnk#+TP_3a#|!!@OCyexb=4;!@nzh|%vjRv7v)Nxzdbiq{p3*M0EJPl)G*7Y|+4)W=7D3#x0z zwQBwSqIkb2@qQ}7s*%t>YFY!&q0E+k4k`(Sh(3aN&?CU*Ge)@+l6$zeGtMU)i!~c8#1N2Rq{OFIE_~_4Zb6ZpW))$bo%#k31mxW4H% zMQ>>{ox3OK1T^iVqI3ce;|F`8OW}6xhafjgShKo>Zic^U-LQ@k}12BTk~*)#k2clSJByr)>ahZtUanR6~s&$i8x@*b)&0E)X zcRzpIJ9eX?j?)cee*nyX#ssk0a3%tN_VW+a4T3c?AB((V@mxIV_r^18N#C zu%U=uE)ECuq87`godzRZfoLQYHOuT4uh;E0lc$aX_?m1TaHGhj&lgyY*6VY-3DuFa zy?QNyRm?w127LyshSO?2{QYEQ3iEYXox$(b3(vW;{4Ix}Vdsfk*RLp-zkVbCKJdV_ z49?AN-f`aQy}GY=!`}8blfhGDe#hVA^|u|&Se*IX@bXF<|5RM1Rp_U%#NoIY znw#6QbsQIL%fYdC*`=7rg6SSD<%uq5$lSQ2AqEcU2q`KI$6yNllH?#aEVv=xVit%~ zo&m91=K(qSpSp$sXDAd3J7W`Yg6s1!){QBQ&D-PP3*^HaHXYZud+XBO%hriSqYuOc z1{Vh#48CgL=1r^H+n>1kJ%^F*-eFo+L1!EXeH*~(6%Qpzv`E4tp-cN?Z2+qL0H!c1 zfh$3nF$?N(E}9v?3A2RDJ)g-@jUvbl>ptA1< zDx8)2*$2sYfN9!6TNl5NxYqP~0HPbxDL7R6nhb8Y$7|8&i%D|#$l`I*oXY$!ykWkrnlMy?)3E zH(j)z!Kzf3(u6H4Zj&X1h4k3Sp_Z8}3Z3N8t6Vq`Dk@DzQ=McUkjyOB=`2=@%|P}S z!;vVbG#U&Bl^Uj~3qvI>V!hsq#dijBty8X$s<0`-=|v|UW3q&;8WmyW3WHuF$5w5f zi2*mx;~1u$e}eS6beP_x);Q70w-mu+R;1H;tvamkP%2%SY5yYhH!JY&%MHBl{=dcR z$Fn&*a!i!+Cm>oA1Jd*cgAz#7xm+$F%>bm?9EP>Wkc4UDlWqHWd>&O|=>2yO_;QVa zKh%s)pDRDk1PoG^E-^oE;>T#k!UE%AEI0Zy&g^zN99jdXbqZ!*k(zyBn0+>D-Rzql zBBo>NX|$dk_=W0-7oj7l93p2veTc`^{80rA+GX74VFxeTFfMFUAU9j&Itjn87!E_6 zOnM{4sc1AnoUm7{Ax`{R-0N0(4!F$AU{Yzw&$_~{@?=d?u zJ!~cR7zoj=3C(|0FvC<&33dgPR?yrS13<&JrC_5MgL*g3W%W`RM$=Se9g!KwcIa(Kb1-@2VeShN90SH z31j~a#?haAoWf($Iyv_Ig5%_NIpsL4%Ay=+G$V>$=Qve^<8A`SO!G$a+qhYM)aSgb~~LZWJ-?eo(TRH`o<_Qh@N!we5?SrRHvf-GmG>0;`@ zP|J-z>d7ix5JDaYHy=%K(Fe8UqBQV5#gIFqPsV&X@NnQK-LgWavm=qoIQvW3Ghzz` zvAHJ|ZEcMvGtPk`%xFh6;`WVR%0*#Vs7ywqQAN#bx7+PA8?yN%!ymexM7zTQLVTgF zSssI0sW3z$Ruds6bGYhv6Su!I%V*T$=};UYH;bJd07h11C6czOSw(7?u{xcflgl$v z;6l{WH+CEQtp+ZZw44UHnjSU;TpSr2+~Fpzv?QL6Y0S(HJmmjrHxmyRi=kN5+LqQi z%tn{XXembm`9dHpiP|a&>< z^kXfHTLeFIJee;Q_y?SoB;v!ts*8-ER?7W zlGSacWlKxg798&wiKlMbpS5Bbw8_*=?Ooi+sJim?jH-|nG^s;6y-qecqY54qgU9~P zz5pFnhkbs_>bhMrUFfF+`D8ndT+OwwE@1)k;QX~IpD!Hl=^_s~d@iR0oNwkFD#H(A zt<`pgMeQGO<$wYYN+B66C#UIUk0X^xr$^5&&OW{KvuAgp6hS~ndFkQ`kdbJgodhy+ zRujvZP3|Q+u(Sq#nlbB87@mx^a%F{C?d^4@k#qMrZFX#$5_0Y?dm@%h zjc(<3B#-0T4xB!7q#)l8q#&#<6}Y33F{VhFn#>URrHZ`8caXPGp=Y=seQ(s3g0>y! z7p&HrT2TNInGTb%lcj9>xe#(o6LnV-rAQ+P4jj2162PJ1$u%G_he4rQB8>ow$UN&}Jl{XVhD=?;cGUXSNmo!=R& zB-6=wx6kFaazfxqQSrv)6_+`?YPKMvlL{CNDyvEed84H+%s>VK-Ck)SjSSax|MDwi2NqWD4dh<&P+RYKGL6{$$KI^AR*6UpXA} zm5-$L5$0z8%}FAGRNCWX#7lxiHc&sI~sMm-TI_QVIX=~TLu&Vx`X`I zdT0l_J;IS#C}93fFcyqR^a^|4h`k6{nxnU&-m(I6u|~bm8w#InF&m*CWkyv%BUSy( zYc`7|7F)n-!Y-=aM&$NGp?J)f_S$SR&X9K4h~1e98!_r%sx%sv3YdD>jchby6$czd zslwpUY1EqK8g`xTWd5xOB1W^6Gw2=ZxHrMF8O%*bGSQyN*sOY$4KJdgl-(4!m>EW^ zJ5UK5V3QgGIt(*oMeD7Wa3bk&IK8=o&-<0H*yM_MrZzVb)M~6Dauei2*5U+RUz|kO zQ?TXrW=y311eBHj2b2v;npIQNqpERQhSp7#^y##_L3-sl={bS)4v;?KRp=X}|F=N- ztBY2%GZb+c>?a3ZfsjP2uqF*|P~K>^=q4!d@%RF}{9dBy6gE@)e)71GLqr@3*_@A7Y#JfzQwpFeGxj`g=3IV% zYSwsV=Y>=1K7Z3CE9ZK9QiXzhq}3eoxMDGvx139Kb|ta}&z!0$;CClez7V`?@E+tGu~0Z< zwPTn|21{_g-YeKz~;( z(6~`*kTfb&!!rhubfeyDj&(`_D|fz7!1`dfteo%ZokUGQIzi1=P_qu{u`0r(p8(dg zK+Ed^Yk=m$g}fvzEb8($;)M8iO8#-?WIYS%q;zpgZ7lMWv^MtDnUMG6@-+NRDP5Q2 zufQgvHH%nVH_e*GAgXzSELk!|8s9ohR>?r=`OFWC_fDr`5mhT^La#6_8xiBV7U!|H zc#b7k!uxN8u!O^5tDUP0i;wKbJHEu-cXU~xG34?08Uc@g1Mg)+589;M?qNJm8o+KZ z{5ikaQf-@5c@4%b5u=1UUT=(j2=5!9Q~RgIZvwa|z&lET z_30GR4X{6sN5(P02zAz1;T*~q6w6Qz-Yl*5*Fipeyr_CX>HAsWm74D3Wo{Gj>;ODZ z;B{1}TN2=zsP(G9&<<{Y-vMsUX{VEebyU$8VvZj@$m|}y23Xn8T-kgzdbcdW-GbsT z!6(859ZCQv0mCT~uMr=9ryRLg;4SXN?5h6EXSrQ{J&XD82mHuk_ybY6zajSb-Zj=h4UO5s?2o<)>q+<}rVG2Fz8gCw8Fk@>!`@Ddo z@Zs-2UZijsBQq*)Uv6o4<}=*(&fasUDq@sB9m#t3{Q@1P}o=F^`8}9 zAL}!xa4O}4aY0}l#of6D?U~EC<63)XkG@x2-?x#QvvvF7xTbF~RWR@#Yw#XlXZ`}e z3)8w#typTrY@05=6i?CSXX+2(LBqP^UKgI85-)o3)mpY#EiGDJER|B-KPqn3+T1pe z-aOd9V|(wwtW0JvzqVdNPD6m?;nkuZVB)m%^*k&!xlvzPr_G_Ia#! z#uN#M<2EP4bkS(kAo019Uaek~gnJ#1k+XFQxm=+`x_yk)_4KL1GmH9r2Rd#{xF9~0=l2ck=%A+0G%G@X4B&bCsTjl zf@h%i8)$DPYK5oj%oSvJAwV6UU*t;pp`_dEEZ(2=+U*vXD^^2SLumBvbLM3eXk1SY zJ^jj>bS@jtWt_fpq4(Oe`=X&xw2wR#v#C_Qy&L!Sbik|sA~P#!(4ywsrc@TVm5a({ zjNMyR&JE7Wml?Dfaiv|Ws~L$l81Ea(XHbMKj)hC5a2#^5A9>QVP@CkZGfKiATX^*G zzrn(m^ruUqd?eCa^f|apW^h$0SINyE%vJeS9HI=Ra4sC}DR~{mY-SctS;@~E%vZ1J z@HvCIP0LEvkS9p{U25xTze{R9eLlN+Y5B0{aSyLSyo}b?`;mo2z3|7MjT|10Ibs}) z+}@}h35Kd4siBg@LLuvTk?3E_@DR&Kur$YHnOUe~=J)wANptoK;MFyu7 zg3|ESVWpxpHlLxje3;Kjdz&~^Pi&pYAx_qjQDlXplu|VCdX(yMsvM@%U(gJNHK#w4 zm$=IO(#G9A7uUR}drU=?2m35GyUp*nI=Do*T#m$J;bJKiXKvtBI+LvwPQ-#mtI?>} z8&fE4LN|#&5bq1RUNoDdA*01*@wv@H0qGa#{E66Zc!s>+e(1A*DElx~*x@OV=ZkJ9 z%lgAzi}EQ}6p0P-g<0`1dNk8yTgs%;RJxAa-BDDj>;u8L!RSbNeI41}$CqVNk<_{k z*>Dt%nj%c4(6X&dD2Iq=)Iq@L~T?zFMi2hIh8- zJKHwSskC$1XnHuAX5xu{E*>S}t}t>NUEPsDAkqnr&XrfKDrd7LQnF}ND#Yw)85mP# z=5U3Rw_Nei<~1E%Yv*QT3l<;z)T*_~_~`2$rMYvqmJ9@)}}5gQPXk733-)lJ7%H4{2%dhE}no`%ZFM6wwNRXG>#fyxQS zFk+*rlK74|WFX)Pr-VZ3@0*%s)Qcmrh?}D(!??mp^iEMY{25KPL^gSS?GvTZN0bP9 zPglpbvD62k+uZ3qf=Sv|FfR^o?W@qL;Zm5|;zmJ2%=AtqOBTuV$-b^ws*oS9q_SK` zb>7ad_Ht=ME>$$4-t*Jt?U%RSZ`WH)=}wQ=PP&rk_p~lp@#SkbtS`4M+TLH=v*XTh zZdm8=miLlqau@QB^ZEV#S*gU{X4Pn+I;mf9J@QB=;;hz|-ey)2Vn{E9$%eLGs8bi7 z1u)I4n{sIdzd1FD_>oBd^;|R_@%gZx+htG1v$+V_dE^$&X1eHTEt;ejMd>|ju|)Y7 zNq5QTMgxc@K-Te>G_r|@_h;&LQ?rRj?9XIc9vgd)-2fao(L+z^MO#^@GD3L+)D@LF zkS7RpaI!{YGCRGlSlsC=YBiMI&pVIf11MFm7mD7O;=dcUV$!wUnMU9lCV`VAQg`1? zt?6-ZkMhcEu<1g0Z@3V(P-ssKc5PhSH8N6Ly}mZ6ogQMuxThb5 z{rZ$(PthumZRi~m!m-v#T2_iSt0@{8mz#Lf&ne6edd|dHT~kuKot{b@NvvwbW7n2T zZkM~mrn6fD0k@9?^wdh#3s&lylHDH^7vWA))08cbo2J-mO-`6(&d&P2O|NA$#UtcX27RY_xByQ zx~pHOwZC^wEa)qihPD@?!3c9Qw8G?20rq+Jl6CBNkQ2jP#Ywa5dttxd)Y*xjFC6<4 z`z>tVG_+_Q))Vw-YFSd>;Ooa2XR3ec1w)mw-p_vP&<*59k9Q90FWIe;2)UdUwT`X| z%4B-0-DQzmttI9Oyk={QihY8W!w;g}I}s6S5xRH8)^M{3OSrl4qTSTrtWS?=T+*F{ zj@2u}7$fKKkFumsp>Wu<;f3=B`5ci z1^i#a{Yy5s7u$DiB!3^hhsi3WauIR0o_*FC^Rz0BcJpV>yz;?lVcF*8>7~b^K$iuK zzhGZrRV{QklO1z=ObWY-k+D`R)HY(Dw#eKN7|N5hhZl&$2kvB8Yt)uzF$;%{jNbH) zj=zH}G4Ow7xzDS=`9N9uZ*5TjZxySm@W1KcZ)$5J$8``t{~O{T?LzlA68N;P@yG0= ztVW=`7Pd{K<`n6%{ERiKi59EMTZmLg4`a|UXe}2Od0}4!4uX-1I0D^zN|#j750)Jr z{Wg2b!@c}D zI=%9m?YmRtEQSl0yN4D;XD=QwkA6trf~bl||IymYO3G(la%P7@rBW<9>%1GFmfFXj zV4q_Z&{f%%VlD3Rkw}_k69E<#H8QqE6elDVWu&4^n2`sGR^)dxFnO&a2nrPz99)Q{ zX6f!ML32!e6}%tx;R7CQL8t%c#}C=(UbUbhx$71S!+P2tK|_$Y%#IZeje-$#G!me?NmBf06W$kE4Q4B>8n|^e4Sl@=g9*Y$3$2~bMZVV=ogx`gHeH$I9ACogn=#4S7Z^1^FJpy4ei;x z$y$4sJ&%9yx1$fAw`tehkV>Hed9P#sfu=C6W^`vq2iaM<$6&F0v1A3wAcDC-4uo3nhB>p)ccNWLf^3-9&2ZC@(8x51*^Qz0=kjPS zdn*-ZI^iAtG7~>{$(&RwJ$u&TRR2I%co5sTQhY~1p}@3ki$R4x^CHD3?Gt$ocY_+= z84=&bW;@9MrYt}^BFUd{3(N|lSHPQ8HYY2KhVsyoX!CkE3jpW^;3$w(Y0`b-BCCyy=E4h<3JtzZwz@oP-6Af-nf&MJWvZMRE0O{twK3{MT#@>+0q2 z>Lm6aV!~pCKQqBM-Y7mwxn1&0{`6k{X0o}TEP3M%&_axPGp?nJaU3!IirY#TzYJdq!K$xok79i zQlfW!{j5lf;H-37c^E<}2rABvAC}m8{7;R>aRm2Ie!z?Pdd5e;Cc zU|)vJBI&xOg))iK^H8o5E;uR`4HiSW;bbwv|8x_

L-t0fDvfn?mqgA1vW1@}n~U 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%0DqE37%b&@fz57w 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≫VR%`knrO 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 z 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

Pq;_Z$vt4;s;&6h*}bQH{5TwYj+Ry=kAiqMSC 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 k?S-yNA@%j!?)@)hDBDrgFRS{=IIFgwn@-J7PiN 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 z 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

@i6b069v6;m``@Ad-b7YHZ9*;+Ung2;U!l8nU@ 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

9L|qc=U0lhmd}? zO79@PCMg=5=Nz%IjIO}3&fw7-&R#$J#@qRH(vt$b;ZIxZMYMetdb!8rv5o9M?f+29 z%GdVS*Z=HiALzLEZ4B%0`@b&o{rU(0JSLdzN#)YKP+uq}&uDgt%HU1vvUZ|#(zoj3&tqWTItL1ZWhjgzd?Ez-T472=#UCe}NA6a?| zSt44zk94rD!TE|pxYn_ReCL`EZ8VRZKN{$X^Ax{gfzte{^z~87ilr8^G;y+G@yjgD z0vg3hvqqttGS5grg~+F;LZJxYB+Aacps}O$?=(Ws_l}9Zip0GfqZ1R6aNwFbr&!P2 z5Hr)uz2SGIQ1GVnKCioC#s&Vlm_~Q6MxAh0jFzv!p?lkUJgM4yulH6vdNcKouH@%~ z)$-zEd$q%J&$DWUO1$Q)2x`RPZ>6@^G3<`=n`x93{)7wTM;2C0*rX#G4aP&UC_3n? zR!oj~>3l`|)E+_HM%|&y)+#h=b7-t{ME^)$|RBvi~d7ED@7nekOQ;FFV ziihGkyW8!~#^Y&6(o-yVbr5xJiZJ4-ZO-CiS6;KjU7b*B^aG=7E%>Pt(yzCEazp zvleV@<6*U#y4i)2|B|%mnLS9 zgqMa~(SR*#js-7IhDz;Os#qaUq|3}#3R<^4m~eS9&8krweV(w@?J&XcnTr=Ren(W7 zHu`i*J&;bT#usu~d|G_(sl3KzNF{ASxWj1FTAv}Rfocx4rx|kF?E6b9y(4cQZIz!snw!=KK-;cNkigeVO}3Y^c(~xFrfpJUBcMYnNge*W9Tx>y-tIV`tl0 z+`)r3;wydpY)2}Yf=G-wX`bL<0bC!c!+PDdrt^1QPOiL!966JmL)LtZtP)*uDYJ7sbMUf@ zncefXnIFq9VX6#)!4ZtcXOs{!F#C5C}nDuvTfW z)cxe7PmmD?H-Ia@RuL21x(rQzfGRJYzwr2QA@>_ zq_;4g&WO$C@VKn%I4n6q(X;B*VD3l^E(b)%f*!d_p>X-!Ufc*aP$pj1>yhAU3M&>5 zW* zC1PGSd2Wdthxg~*rFEEc7E2Cqq>U|lX9d@ z=`8bH#Nzk(p=<1WFKqYt9a$^Lfgk!dj;!d78s!Rid9oLHb_{*8x7c(ezHLT)OV$HR zNj@8uu`Qx7Q3!u%M!2wpAvP3x%}7UAbU_H4J2j0MCa@FuNY|YAr-y6)$Qpl8Ub64-9f$qpB?fF7c1!LM^ zG+=2rTWwB-Mk`OoQ`&vpUd)xc%yGZPzawn*8oa7725WcL)WL8l2bWrv3vkxjyRgs_ z*(=puhjx^d82pz;Mh9EDPVz>3-*{c=ub+Nkta=xEH&WU6E8Dhit4J~NmmKPDgAeIj z@n8t-DUCR`c)0g(Q3F*d@tZskL2Xg*Ri%AKSXLR^reN9%AslOQ`5+(XQXf79u4R(P z+>}7u>gXM>!aSuvL(Dk{DwGKoduq1Q(LT51q32uaLhjC|5(}E>R2^tRuGn1l=4Tr3 zgy>ZEpTIM|nQ?S;n_#iJiAl`vASQIN|MX65)rwWn-WRVMok~a7P0mQvYR#6_tK*ok z`Yy&SNdE_K3Qq563hWjJcwnBwa}oj>I$}auIdZDGSL*BAKREbG(EUdkL96EhE zTdiwqDXg3zlddtew+&TIHlvfg2(~I8vEc5@3y;vQhgbmGo%8=B$>BTi}K3#!}M7g99J&dl{#gq3kD7^YdIS1Q3Tt4XOZuC^Dx6NvHnd zT0n(D>1r-~rWdX*4g69bw8L7@-#$`$e>4vPP?3e%-TbSL&hwb_uQ_~JOKhb(?l9=P z&@Y^Dd9EQk?q^xn>Pm&HZ6&oqqe)asPDdmdP-wO499jiMt4a3Kr_3gw+hVyiZLpZM zWtG$Uo0QCCu_5O&7)=JL1V$=v1fgLF?`oHCT^M<8kgD-bH%1Qx4RrG6#noN-*Fw|$ z-V%47AET{mgF(&e^(Ar*sa1ELab&}y?q07HM6Ez?PocZBH3IgaB-7q8u;b80Z-AKt`%jioxC)Q7$f*V0NozIH1aXSb7OJIPYfZn9(#ld6%KEo7QqLnc-+ zyU4cF$CwdOB~5{TzS8BH-*mTVZv5|-UC0dh44Mc0qO<^R-0W0Oi{DB9+l|Ylal`Pn z@Z4=fpCNn&j{}c^-8ffJtpHB#_oRKnzzuD#aI%_rh(wxHJV-PpZ+CCKmUcv~dn?NanKMm;Q)_F%j4SDzeRs9pY8(*7V>_5hGlojh zjroHe;uztG$zn2`T)1hK3hIC2*E4}zQ~-lT`)?|ooKvZ#S}BVWMVz@b?vt11aH23~ z8U}%rZ$q}`42DS|1FbX43t$$vlJX3?ZZw6S-;)!e0{}280|~-n@;w@Ur772*m+)$w zKI{;mq%{v2&f(D{-TQ)I3>whlik!*2crNfCq(~|T#eYxE+{e9ZWmsP)hoJw{E@t*# zB62v|Ky71I1VhlET9I~^3avVYN|7tT1cVjO#)E}?MXFM2P+P+|4BccvL{9W3g@Igj z6rP`dnrq9Jlfi2B^K0SvB$A!`$dM~|Rk$D7VJ! z@UM^k0_Y5D6*ie6L_`-&OqWo&h^uCQsaz`alexkpPs14hr{?dY_X&LsHU*bUBx=EL zzz2^xL~l$ue0ERP=k!mbHym*!-J!r4H4w(DX*~AINHj`rAU_s?kV>{B)ELyXCG{qY zkJ~w5b9$C{_*`z?4_vjj)z!h)N+dnFxHmspABqwy_vQ<@a_L*ok&6bsVzI?BdFt6y zSbv+}>5rqJe>-9F`JEYu+xda5e{A_!z^GQbx<^NU04Z;+8`ZzWuYeY@BWN(0@7;^a z$93PkFTTCeTO3|CvAm}zpGo#~jSu#8`)h$}_hiB7^(0?^ALwD$4%g0-;0Q*aS5*elL>!8`LBa7Dp9ip3oT9J<+jmH+N1-mEV zPN9Fq60-dFAqK-o9{vU3d-2oMQoMwZC)7TJsz=jliUl`I!rM1 z>+u*xqQ9MiiQiA0r)^EvG(gE+fuOzJ;M95}r$qd8b=&sQ4!K;V3RGJwT$#M%2HlNez=D$IlHH5` zEJztQn2wEU-)EBW_bWoENovopSd5z{22AxOV5&A$CHV%IY;Vh%g7S^!U(Nx4t2b^3 zx@lr7-2=P}@Z0Io@@Lw;Nj+LM->}}v>%$hPY*}Eq<)mQNpmkq4X z?O(Y(B$ESbd7x9Gl<8YVMyU!E6{A^eaWaf8W3rnrDp+?fxu&wWz9d~S{SWPk> zU{jJic1-$_30S{ffBWd(UC1)4O*?D11xT`t@D6+;Yp4 zS#2~5DFLlI;Pzx9YTNbq7@DK9ls9B9TluTbMoVm`FNr%R$?< z&Txoul}(lH)q`G`HLJ{O_>brk*GHbLY}&Nx+U?uPeWq$xr&ppoeT3u7WO4V{!_ z$R4)0lNvC6V5PRKUtJO>mpT+fU{O6u_DAP^00DS*vU9*3z{*O214X; zC4p)z%$dzJ=$@@rdetji9Ik{D-)=JilEDeV@tz9jXD-=^3 zHUwp=H_4gY(_0C%g~(32WA?3%t*u*Xd(dt-FLF3$bAk=BBN#e)&ZO*M&dIynLe(PZ zim^t++M%JST%(m`y6T;!McpyIN~^Tj>s8A8_@8q5{zLp*o{RtUS-gD}P&QjLnX9Z# z0CpP6n9VUZ=kWLpB!HC)>tF|^a3hE4hUWOAY_X9~Q%~sSI2&+!I`wpN3VV?3+e21} z4v?vnPXe1$xVDZDstL=+0|3H!6d(WSqs|Av=58Qv%^eJ(XFT`Ux#W#MZ#Z*hyx&A^ z-QWxC3oW1Hm>q%rI(2KpkcSQWHmBFXs1@7d3a#c#d2K2cQ)$p;NG7A)%{3CkjEB~s z@p`=K)w}ns!t-sfwx2moZsFbr{oUyjOKj=#C1)H|p#K|c%~qkImEiu&EaPTj;#+8V zz`1VNO&Ki9LuG@fR0<-WlSw_P*fMW!+0qCaw~Bac zEhaUYoIrDov7pm5`+uLoEeE3pu{Gkh7(^i8si@Y#kK9mmxxaO}_9deaq(Ad^3*jG7oDg}G-_t0RVm(GI8nf8As~fg+6svr8&Oyu83iZItF1_@LE3SCz zy6c!jij((lUkb-845(Pmv#+;TuB%*8yR^-a&)XoKBSj8a^`^qfAlm5yxAPugj}hDv z1@LBv(ceqdy-|T2a&QB)YzcGd44TEAPPT4j>;#&y6bR#&wF&wQCCR@gVf+L;pM#wU z)Pg&vd{icf>jQeE4fPNH*Wh14h1d9Nhy5D&l9do&EBE`~B!-8_)f%O`Z*WPzo?JaK zEKx&)W@6=3o)|v(%Q55rQDz2D&t6wQ$fQ!kYK=-Y5=%)83~Su&@(p#n{ThQtuacXz z(WF}SU!7!ZHIMQiF7)^IMF9Y7BE5?TxQ9WmA6gWHZ-qu0?(6GfWXBHw3ylw$;jf)N z+}9hIsTAsJ_o7L$MEOiWZ!}wZErXIC$aUZg+xb{k`0z%|S7gzJqmDUk{AAlYoP%hB z*i!IT0<2T6k+vegYmn8B(Rt(wBzz&5i{XK}+d*i%%~g?p7V!mHoMhp2E{|r?ur)WH zTct0<{O$?Z(^c6obHAWWlP+$SS-+A?kpmjP-ff6*&yt!}lS%=}W|@wP#Yw{48<|pj zD$K1QU#@Y_aK8z<0vM;$>@&Gc_&^FSyxB>fWFhRuhlim!opKM;r95qJOjP47^ zsE(gjRzKn+#h(Gx?^t-m9I7FUQ-JUzAo=vWLfBb&Z%ZlAMRt+@?dC2-wsRr(k5D)i zFvaX~c&~cmF-zE#44sk)@s^7GB^|oQ2cZok4D2MeiB$<#(CD##<}+ZA+W%3Ade$w1 z6{yN!wy4D-yR9vu)wPwneR`2t<%v~tSrbMp%ybB*v}x0)wrqJN>hQWPu%hui2jkm- zEo%z6xHpq)$N1q)T*_mUFL0Mgz&b8NI{}Boq$<)45?xn03+@VHm6W?Mr&STXA(La# zDvtQo8mZKLn%(X(fk|hKfc9>@9=14b814Dlyxq)_qL%WF%f#zu7W{nwShaAZV93k zy?^=Kv~e2vi3=)!a{M%vy_5SuM;K4$4}W;^MKB7ta_{}}mqZlfwB2Ms5N!Z^k^yh9 z{@LzpxcAYc^Z|+Wg%8c4_E#tT`6AqN5rSMvKl9^uYEvOvSs2I;$!D_g1n|w4H38BBP?UBaBW19KY+N4NM2SchfSq zb;p(!tY5Ti8-o>|M|uh0gvCQE)ZhOCl+c7<(AH|EsnNMdokkD2V&sDVRRToD zw*asMbQhZJjpOe|m3@G_7F}`)#K`<9q==fA?sN7GEm0}eapM zhy35`-Oyn&U)v6oTnnR=C>0ZnIvvk#c@|H#ulQUcoe!L4k0!*|wo?I&-PdwKp}2sD zCoL|#&WOtwy*}YCPzPk}p*3zzGq;;vCJU4V74opl87$>1opy-ls?o|)akmxD%j$I~ zLsT|vf(2o&X3#@qVNZ}Oqq@an9Yz2>t)Si~pMipYbwbTO}y%_-{1#8Q+P9g{D4zm685N`id;?z_#EQ;up{T z&bfW2|EA;p%HwY|dnNZU^iLQ)u~iw&REu8~|5$<1h{(F>n%vU1WV)Qo=4(Z#9Rs3L zjY=Yy8+>^*_I-XkxG)C469h(xipxpovp$Q*f}v)Y;~DNc%EZQP<|<;6R{S&e9ToDW zjXn$`Y?}XApYW{|hbE5S97LpxEm(mCCYl+E;b=`cjQv;cwYW3d6YumK*IK#S@{owOm z-g0e=v95Az(7R;zuV=u0z{QHFd^EJmpLzPI(Fdy0L|ypgMd_1DK_8m99RC&;Q|)9r z6NFduKT4lL;hDzo5g1(f%KR^Cl+^gQ6Z_wT!#x``Dz$9Sa9_+_7+khN2H17oc(#wQ z+}H8Ml`~mC<~wcqrDvUXP$83wg5`KOo*M2G$E^p*Y8$+}3XlOQQ1Saj(Q5v(Pv`f! z#K`XzcAFDQ5)6@)Om?ffQ|)wJP;mME`Wm{4OmAgHd&!G=6isGH-@1*9M*@&4Q5*Xc zQx(wG?NYg1jv+H+*sWC~S=Fdupymdy{Hx=a3*RIVf`+*;_j8|0*);jGTAninvl$m= zBIOD%l(#W8RxRVs zqyl1hdYetBf`6!lG57l0eDVUCl4_`!;gQ6obI|CA+z;uENwqSgsLiN=WH5LeZAFDV z563K3UL?ja(L_`$S4ja!e?FVpy>1;~HSxscvYz&ptJaC(ys&NM$~=OqNJ^aU*ub(y z3XJ7;^bG{0MpnEm)VhA67wYV?zKOM26*O`7CI_y*^fb`;W$d}~9z zefqv3H0h|c$2|>uYN?bup)*@_woD>ONYO$dGYV)A$)i;7@`hq2t5U01p=E^<31aAcNi88TGYqe|KA`Ox&nH2Cc>Cxh+C4RjjY)Pp|!p0CC3@YU^i_vI_ z`s^kt<_6aplCt}D=xZ++saaz4%M};TIdI|#B=IyMZJ*)@27xlYbQU`aVe&@ z-4V)+AfgQuq_@lzwqkmzw4UVpDDDvjsgAEQ^0_cFQan1iN0E%8CZ><^+yy$HDH*|N z!gqL}f}l{NjgsawJD+h;h87*2#B5DNFSobishNGMPzeba7j{uxe?w z=vJdqsAMyhCFJ5y1pT;jC1UOQ6v(fXI`k3@=Lag~(en#Bty1Z^fUG#h;lU1R9Nqb{ zBP!WqgWQVN;k@klQ4uLL_B8@5_XU<>xQozvrJ(-Q*%rC;sh$>*tRN+ z8|atm1=%D%oEfQquC{_w;9Bs<%8@0@>!epji!`%ra=|;0Rm}1-(r^5^{Q0q-Q zc3gYXNzBDjhr@xPRIBUtxY6%|NU+<(y(bK%QY^Se1yX2^@eTH8;HnIP9lnyUYiLjS z6D`nqTuXeLm<{V8$x}TUvYNfbun1)HnT_DAY$j_~F*;tfl(y{oJ~5nGBIfoZcLGkJ7J58i_EUJku}G3j!4+O8U}#`$-I#5kiKjeTsT1YR%*C5A%4L zFx=OSj-m2mj{^?g8hxP9(>+q^Y3<0mg6TZO@YPi@RV#41TyCe`;3W2f!ip&xT=4Jx zkr+rB!aPn(z-jStAA9<#>aN-scJ1PxJMIBvGm?1560yB<*Shn^J)@VN@$IWtPHft@ zqPr`ePPTRottxiQ0yV- zF`La^&b?a;5t6!qS$6`*ONRRNi>Om-z#av+xePy5I0kKnc$#=zjLk&UokY(XwF3I+ zgs#1pYHMN25X}EM{IP+IHEMnSFd>9eYB1lEqUbL^sK(a9O8>;PXYc3U)eC6|QsGDj`1_LpfO5bEoj@mt-xd2#%&>YpBr@8iX zN6}m`H=98J;>YM;z~~RyNd(#yQcupA~6WN{xX>hx-8Oi{d+ zKLGq%VS(^YgN*S0k*h&Sm{@ua_$rW|1Tnx`Ax80s1S{JNN;GTdajQqjcJ4azI0t`< zSGhF#0yo3G?{PrU-y1gj4mdC?5Rki^UVncEV+OK(vMu6^_w*6CmFyu0W=`F%Y(Mo-KM=5;km_T$3_Vid%9TpjmoXw^HJPF=wdLfP5)*ckl*wS?Zc77t zb0*@|WHQspDT9YvBrHZgMZ5xfqQp>@s`AV`%*rx z(++l}o){(hr3^TtsUS3L+>BX-REJ?BB#8dnW zf?^l*$Wudf1#yFh2I)M}kzdHURpdj?oQn9dB1kjY6n2F#HI``2fsFw9vLM?gI{(KnJ+a+?;QJ3hSlj^W!1rc) zlwgXm8&Zc4r|S44^U0;#GSzGxFrrOe(tBJn%s(i*Sff7Zhq{746O4u&sEe7AdCEZ? z#+k;P-edloZE9?CQN*ZL*(wu**sH*Yk0It)z+M-W2%7aJSc<7u2=nu{Q+ZO15n*~( zl!g0Lj=E13;tTpp^AG-9n<7kOIbD0Y?2U(+{*i`v3J&ta$*ftJGoS(GSQ~P5^O}8* zdjwK#_D=3q!qiqSA2C8fpndsRy}i16qDz6AZD{pGhNwQyExMX{<>Pg@FE&27AAm%M zagn11tIL*Xk}9!CHBNto`OZq*t0MWq5@uvNtRM$#?E`(oZ~foM(m@Y&EfvPa^&alG z+*KgB_l%An8W}mXbSd+bV`^4A7OhxU^cz$vM|A+!X^1HyaB{wjzO@x7>@Hq!?{b>y zOp%dc(j#)%h|YxRZVOTDlOf-s0*7kSMGA2U)q^wukOM|Mb&um8;<(N-J8#Tk!+UOBypk_$J=@q8>j^-}yah1S@_s z`5Y&hiW zwRF{XkR16m#h4g(nq9l5SlCwHk`;Cvrab0BAC&UesG;j=hXVOZi~;? z=7dQI44VD^vx;h)+mo^a77$tOHs;|qO6ui(Ah+_)Lx=8M`NQ;5$!0JgML9c|(jxQK zei%XmjVyd!BtvsOtCp+S_&JZ?%b+$AOMjIA`IT4o#nxPQ`QHy8ykMrLgW!Nc2aSK% zvL(0QOknF~R=d;*i_OmcC8n|2tx2oh`X|%SvUNGTLd59RnaN3BYe&$Qo6lp5^++Gl zEM^9f%(f5^O8snTN{|SRbAv-<2`16!A{~Ek@UTkr)Ch$Izm*UxYQXDrd2N+X zSm%p)nlRD$SUth6AA8>HKN5*$&_mQLO(ob{bSA5HwO%U4Y|fs(M<3<>!gT-dQ%~6v zA(uPnxB4^*wNfF@4uaQVAm)}2xjZ4ywsEI$e{D|shqns#IBYMDc9CJV+@n{Xb$AL2 zqUxFRKYpb@ln9g{7oZZ$MC*&YE0x{FZGZ;ZyuT1gYrGnbMj;Zh%*kT7Oy?&*yJyeP zoZ`{*4SFhi=}#YhZ_8SSKl~P0dG)G8NDmO=mpvh1&~kA6GJd(@NU~3ZEbhH_g^G4!|mD9Nq($RhVl|D zO0{m(F*iK7j5T8l3Sa;jyYB<9cDZ}K?k)c%)f#Zx|;orvaVC zsc$AeGyw6Jg^>L4S3efHT%^s5kK|LwBB6cdh}Mz)xE7Sl%08Gsda`@>w%vp)!BJj0 zHlmlQWPM|+DqXq3m3=JjP%K|HUL`^9hv;zxiJlAX`|FXXKh8mkG2k=Ck$A2X$k+B@ z7&!C7#Pgby5H(rxMTZehSm|~9s5F`gsl)4@nS5Vs$*PyBA-md9|HnJYY}G8$%C!n> zAydrvq2(&g|Kx@ncI|p(&a$UTzy8)eCBKM5VrYPy{ZVNU`QPzXD=HVdA-a;P@9d z871D1JLwx4Xa~W-d6G^WPMCU9W|NUPIc36{hz8_pnO0;8N3H1JoC=Y&Kr|CbN4eE= zH})vP3Q~SsD12tp&-2YNjAIK1nAzE~lj(q1;&es*5ns%hiZb7tyTxAH!^Z~>C$^R#gkLuh_Qg7j6|=`v!P>EsV^pm)^6e_X02`Gl+Z_G z&I9m9i8NyNp_X%67T2rG){!lPxEjsdnA3MNwX+X07123oGNnQS)UZutXbD*?I*n`{ zV9p@Hvq)TYm?Wuc)_)eW=bgaj!x6n?X>KzYiYVDK$hTYl^wCG^%DaCB{SwM&!evW? z6yIRsLlsXmqv7eMAYZR~J>hAeBkXTzJPFi4Ajvd6zyCHP@#k*T6E>K=>896y>>BFr zMVnF<@CAY-^xF=zX$c8-c|2OytTL)aPBSbgeM&7v9lz{zyYxqb{rzil%Le=0Z~Wx8 zU*1Svzi4Uearj=1Vff#U5lT4VC6}*QFN`R+jjkZST}xw=^sE{59Yo@DO4|#$TFIwI zd@`AAuFyW~H#>Ep#g9@)JVl?)NFboM?p2&L|KhH$c-dGfwidQ;2f2xAsNW9{@>U*Q zu%b$Cs_70eYXPl^5#%1$v zMZ5;q;!KkQA?*wj5D@2~#h_%071BX!ACVj8A4@BJ+8USwCb|TXggJ*_{=0ZZRKPU# zbfl8LH;P*Nv-G*$*l4L0`qMJZ@br-V+~s;=_3MqmjIM&8tW@cA^_f@s z-Fg{vH*S*p1CvGEDzcNihV169{%O`-Oyvq5pU(`jEvQliqc#hQ8BP{=2AsBx!{<9C z=#2Q>QEwn}UCETnz&HT?gmBmo&diG=^;$9^#vC~JK_-7a=3B)Qt=VkqYU@djI-Ih_ z60duzbNR$H466;KSQyVt{@T)3D+EJ!pU>fRVO-zrLcbNbDT78VlGupH>w7!~?I?HJ z?euc5yZYB`9Pt>WQfKeP2;HYV_UTRZ8C=L3M=^s*dkqI$I_kLrl3u=ah)s%?ktH;N zcUl>vp4Mr@BV;kVA^|Z#e$qH=VdNmx%mpHfNjHN_C+&(gplCi>q~#jzaA6zKn4o## z96&waouHd0B&B`pQv#L`PUl`;9ktKGJ#f`jeG*30(HFex!(yV1v2&fh3p3+-Ipdj ziH0AmGZ0~3>;<2Uk!b-gJ^y>HWFW@o27~~N*|T!wNI?9da4*v-FjIE^rIcOa zD^fP#+2=5c_-abS8H^@W6R^|PYn_%7m9gpdM07Tp_#yyq7jylMCaNzy&6glyj5=Q+ zlpvIF0}&bWUfu)!E|qG3=^hIlqoh_XTv5atUHb7-TQr#Tea{iFThRBDDaV(uh(QNR zZ15QH7#p2>pA%>{jASAySK;SZ9a$w+$W+U>opjmm-Fu+eE)lE1=TPgi^|P0JMWxJ_ zgWnO1@W8tIRMTT1go=%wORr8u|2Hf!J%uEh?mFFJVd|~<44?)V z5@fpjIJp9Vm7n`I!tURHRNL0pwvE0$7J%y@8Z(~IK+qlVn-QnNrDliVnH!zaf|8^-A3_1b^9V;@M$dBbit5%h9t|jT!tNQUtrE8t+8wTjh^bU@5 z&o~Zk-<#4&)vClPn+`If22cHN@K!R7{El+uvi0yfvS@uTz~618a|dY`?INuw0a)Kl z%BL5R;DI{V22j0Os~o@j=8qT+r8uzs=|<}biJO3z&;yFUF3jqhn;`^N-r@zEM^u?S zZ*jh|oM-7yfY~G@ai^B7d<7!71~CucAyX)2tez2B3#n{=nhDn%Xf{hbr3uEnvD14gfFwq0a)|uVWOY~=#94(wk~4=*vfPr~Sl(cDc=DTv7r}W4 z=WJ+XQ-A-WvI+9Vk&eZ~`3_nPDf45wB@f&6fq>WQ4f+sU10Q~heS_^r2e!#%{1o`S zVb>l4g^HzA%wauIoJQ|F>q*4T?j=q;GebyF$?(YJ0$_6PmcxBUSDLOo3L1LnePk2n zdAfXFO-~HJhxBE1Z?GMaYN_!x{3ak@jpCEO9$noNknCnIzY3PP&bC``eVstIQmWSb zf_Cnk?LTlN;|?t}L;HJs`x3ofd5sn!6=6yZEeC@(6oGp>!#eU-hr=Zkiw~&HYMX!o4FtV;Q6@`(H(OX)N_xvL%e$*n1^D?75PJj{_(a|W`D>; zO5A6=N;;EK2IX6|CztEL+h{l|1fs7hK(Oux*xd~7H$ohIy}uR$7I691~P^sc61BIp0<(U zL1yd5b?oYulgn6P&Kj2#%^OP?6R27i(8$D}3&PoRJhA=J$a`7d| z15#QUkb1kv>6RAKOX$6{G80$ynq+D*yN4Vi)7*Xg&pYpvpM3PuuE!p`0&mxS@S{+` z3q=Fytc*ahEnwr5kFq(I2lZ+(e9uvfZ^kJ)3%c`{Sz7m0_NnFXOyIhKZ z&k3agX%R?^3xs6(S<9D%BwCfaylKrvW(mkxCEqnfU)o#TQ#?@Oo*8#UUPr2eG875Ib z0nDZ`qmOPS#x%Cs8w>eZH=BqASOiF|iCA>=A|ApVj{%#8O%!r`KgD+_$bh3VJzjC*I>9)OMr9>;)x%(>aPU-b%J_oi)SKMV&wsc8T^k`@QBfbV!+-;%3G zt|K2iha3<=kFI{oG}9&8y^(3%jJtm)#gc=fgCu&G?4G~+qs=FrpDGrXjnAt1oSXhh z?8n1SWu4~9U2|$@c-|Kr3IV2}XQg?!@K+4Y^^w|(DTw3cGYQme{8rHOvhe5WWj6QY zuNCy5CG+kjZfEG6pvkUvSi(k+KN#}UC(P*yFduMFGsO7+DEkgLxvF~qJ@-!Uz4zXG z*_oZ$-m}T}&8AmE8YKh*(u-hF0Y$_o3PJR*fQpD>p{OX$0`f#rkfI<(c`DEH5G9xY z_uMbN_Ehs*EOEQIT`r8Ti0%N|B5hy;q@CU`~;xCf068pgJ*6tW%K|VE2B<_3md@U zX=24GR>JIdne!S<`PEqqv|KaAWWgta>{+zZ-5lty#nd{z+>%dqW(*FeC2KOP?2=2& zF0D;$vfH@(W>cxz+(@~kRpLM5N|x62R*NRBMyt|gOWm}$*8q;@rN+2&W1%8*8?Ze z1_cP0ObZ~uBPYO^qw|=hcOI=mmlIt)D6}lg+`vX481_XlnZKsfM)f}IB1WEyhRG)~ z*Jz+bknbTUHFYd&&3zJCG53B_%f8gTuWLvBQoW&5I}ecf@3Ta~Pqml85t?50d&* zaivN&46E6x|JhYRY@+yzZ?NBj4jS#dg>iQ`J2oP3+u1SN+i61EO$S3ypem>l@5FYp zb2HgW0^KAe+OQ4c$LvnBrH8TF(4}_3M~@oxQZcEe7n*;q`4iB7E$L;0mkw7pZ+W^b z?)gqP1_|nqsfy`K&6nB2SfN#NRhf+^9XUcXs^Vuqds^2`&E`!%4|xJ!Qw&b-3n6DH zXbqd9zP$-|G!@F(&@{FCg3ME|gS~eWK=rzjOiunmy(X1V02!NWSS*c;FTRu|U%I|< z9t1VTk{b)xbJva(NaViz$nBI*XpW*O^lV)3@mSL)kDYrdIXMe4euw|&@(_CV>XE9H%1MxvD}#eqP;T-Un2b{uwjI-FB~n2d1GG`?J~ zf0@1={d>sex7uTVtAD-U;x+iBVVgg2V%!>!2UD~?038};tjZqC&!4xiCQ?e| z(sW;c7uQ1`L4U{r+j&W%IX(aCn>SC6vw?f>{jY}~e&f5}WuOh?wK!sav-kT^NMm@V zN$7TR--%Cb+*tKd3CEsMco#^at#}h+M`x>U6gcFkf?HLrb&-uDO}4zb$fQIGz*0hF zYn}=0-OglT7X-DYed#zGErPfe*m5 z%oTgZK&-4c;`VtRai`bye4L7kVvl#x;=PI& zQc&uK3jeab-n*oz^yje;9oi>>Te2$(3rQClO4~xV#p#4)SuW^wX8I$)mIgDK0Ery14iw9B)S2;l7K=Oq@c3}J!V$ZL6kNVqhnF`8{~|- zMH6ptZ_39M)Rpi8BC%{wPbj=fyws<}N(h2I?dW28FT((E#9uVKYELrq*NAgBcN)2} z^|288YEMyPFPjDPJReF`OPfF2MvVR%}phSee>e zNHY(u!7N-XeS^!A|6II$-MSAhEL^sJ{Vg$|jT{)47r=Vm%$L@c4Rswdby(46KDJ5V9iZ)XyH{me>GPJfbd zrkM^au^WjQgL7KhQj`vX5;kiiP>5a%Bm9mQkmF06Imo}n!k~(;Y0+~+M@e{pTaZ2u zSbckU3=3EY=R7b8BrW`Pi1GuRaxh=!W=>Z2sc#z~m^?ug*J zu3df=QRLz^!aNgkf!~^bx@UR+wjT2K@wd3ur87yFC>-t0%a258=vcZpu_*8Uin9ke zDLFiqg+r^(V~6rAP{{5dYki@#qm<)by62vI$Sq(0`qznw`?FZbFqS&NpgW~=B?{pjgpeDYcgm!2P)O zs?k=FYsFH~_|8AJE`Tz!^+@Z^rC-MTyM%Z=gPGf(h}mf7QJJ0|HDB=24_HgZ46N2w zfndnd)VS=P1PcWx^S(_nqE>0U5P%pBSH%-LMHF z%qdxsPN%Jck%&cR-~8Ruu{s5pf!z-&n9%7krA<+}YhG%RDSTEA+LPE6g%z_Tr~6c8 zV17C)MHe_;uI7Qsemanjh2u(X$2E&XpAbC{#;hOr%9ZWP1nq4AhlEPbylainFL3=tWedEe;wX z`NP`U5U41?W9N4O-5T^8dGZx|-rq1K4iuk!65itHa?k$lXgcUezbK9t-e!IbNkv93 zNf@%Wgqx>_*O`AEz53BFFv$m>=U$mX$7A?pk3EHzR%G0P8LKg0(wgA0q1LeAu34q> zuP#z&A@MoI^Q+bKncJw)h>;@cekGh9+T43A5jmkSo8VQ&FJ!)4+(%2Xef#!Z_taDQ znBO5)B40|D>SqR&GJ@_@jbOooDmlZ5RQrTG=T2a?+E^h$BV!*pYp%HwroMyOvyZG4 zNA3{hF_!bx|3d;qPmoYJ2rZ>!dKUlo3FW5?hpsAk+XHufC3&*W-9WZ;H*ila9RO<7 z3T~w>2nFPoaJTWhJ-v;7GaSdlzVkiP)2kFZm3C-xi+h)UeRw>GdKu~>># zOWhMS+h8`sb&G89&m&i{cJ4Xi&yS9tIXZgh(*8ci$zB6Y*dI>?Az&{JCDXGUxgRFHe|tW>e$7^e62eNWM@LgytHTxP?r*3x z3Tds`$or-zOK@dUX==l(6Pb9>V&h)7k_GOYA{fXX<$m)Wwa4qV*^S)b5}axKJ8TPP zo6ns}co~&kfq|L8Q^abO6mU!0NRkWOLW$Eq=GTc+swPIVp&? z(#*uFDPJh+gAb$<{+%kl&mVJ!Ln@g<0>=mVE(A)clx?i2205AggTo)NT0%}{`!ePU zCwIvUXXOr}eW)(rv)wC3Hb3^Ui$;tp7;aJZ zD|b?Bv1)RhJqguuXAV;OTm7DB*qHK!!bch)n$+_SjPR3*2wPBJP+2&7nCatI_o@}L z)qeK|^2deB94xB2Tg|6rPbfV6aN&e($gBX^R}3bx&J|DE$fIGC-y4j3-TvRl%t607 z<#f6KsarQaI~X-76z=LG@4+SM2)^}Aa66NHkE)GO#XNBko{mC-I1TcqGk^*bBu{r0 zf^dE>B#gqu5u_<1{~F^Z#%oK@%+d?iI!$y^M4MEo%!SD!UgVXB?%3qyJ)ExHO(X^) z7+yNMW%2AZRFUOYmxKJ}zsX5YZEkWOZ!Y}mQQtss4|N&LSF6sZKOHaob)7x^j>q2o zB|ROmBBA6o3g-?30Dmy)<5NB;l2ZY>9~}KVb0n8YJCHm`4Tny>crD~1l+H+)gzvb6 z`|Mdk(%>EloK;-6VIc)gW<_jpsLH)cQhoi6reBj=w`rKX6m>wNnR;J9nT7{^1K{^m zVt%HDk*EP9L2-FsW^cv4qibpY3@l-}3%y}5|4K{+ZlW$sEVQt`BqlGD87MMY7Wl~# zAe&H7wqJdr%Ap~y^`b+lT8a%!>r47t(|wPxM(I~AbmOBv*dp_^zk_z#kF7NE-S55{ z?5#(?;c%7JW}PbQ^fH?Ci&nie!OEnHEAKEHy8we>hXa9oySN{cDn24vy*K29T(7|u z^mEU|WFEg$VUQc0R+G`l?SI!Bja73OTz%5P9_k7+yz9(Qkho6UzxolM6uv^+gC06Mk`m&U5Wo0A z6^oWJNwTDu!JJ%ru;(>Vb0f$-oTfjA(sQSyg!V(W|57^6p29Y?YYI zI;WDJoxb>J0Dp(Lq_kU%B@9vJNPi>BSUM3iNMvSr6qZtqfqQNZvAdg)C)M=1on))c z)&&F-GwJb1IktzK-`jhndDBfdk@Jsm8lWFA5=6;+q90&qJ0<6SxMa=bBRR8Jq>lU3 z%xm293`(wo5sK#oR63Phr_tMerHl_Hu+}7pmoobZ6{E+&vv|!~wIq<=IXa&fqXpML zKeg}fm_{R(=?o^3!!`0Cw>O(5+jrpY6T9)o+$dPALPF=E7^b>*UP9+SOW(S!xqwEg zFpl)0r>sC8a0DDYFZk`NTb{U^I=1n3@Fg9m^&**I%v%@ZtWmUiA<61D&M{hy?Psz? z4Y6M3RFRR3*5GVURPjFs9VV<9!9SOqC#o9SLM%T8+>vBa<4GYW+FFc?H#m$XCq$fNsVq)cJqE5i=POBuM z4q$f8PDasYVnF5v0~@KBPd%U^(Iev}wSn$hm1(jF^~mNf7QBQSb`anlLcqP2CN zkN4UiJC|WUfApp%dAZJM$fZs0??j1@N4du-CBBDyggNq5%rP*L6~kM;I#BsXAY7=I zO8#6iYQs4B!k|0sb_UT?-3?F+5EMRF?DB4?sPJ@Ft=Au6HFsWkVTCrMbL-Y!wqXPJ z<{0J2%l1_xA$PfHQ=lX^<)Ru_I+3$vjIku#1EtK zHSn680+(!oERx8`Qobi>N2~~ccwOJ_F~GN3`8y3ElCQY<$V%g8D`wKAz_kPPnILdZ z110@9-pzOHf{?$50-dEen7@ipwrn?w#4o@4Jxi%lkzgd>NLQfaxP^Nm7O8aBAUmfa z`C=ic#H1BH!q=Y-7t2+NLapv8l!lMKbtd!kjn!?H?bWUSc-Q=cdB&N^r7bcQ62es8 z2jA)Le6m#bK_^G%P8H89m%rjHW^xW_3jqt7PNx|Nvvn1!g|c4>ky}SLf7M&n>Z8IN zGyPr?56WfwDs-g^Kxza#dR9b4VfChZ`}L=48HjU}(pt#stRvI2uz{E-s~aRIf_)&( zK72$*yS!ZsGfa)0nqZ1~W^t}r6@}M~m$RZIAMM(MiB^Y?_K~PY9-lNI$SpG?p%}rg zI9Tn8GoRuk@ChAay0p~7p5`BIV${2zGxFP*!(xL&$rU%42vUj>@@=&$)Raj??0inI zyFt%AZebWt4UKip3tcxi?`pnI(%%f~t#(6L<8s`8^UXJtBX`|(7iT)&Qsx~kJg62| z-z5Qu&1nzZUcgXVEMF*|90VuAVAL2S61%l}CX-nO;TDl(Prkw3I$W(b@p@k4Q5j5n zpT=zZpT5462M15)ei;Sp~nXwPQMWHfqqG~JvR#S!T?C0m-M2vT58BX$K4@jfF!9@bc&+Z zXffu2M3*tCQq}MFMjbFHc7!c~kaZSKdb!yQxt=71-gK~|iSG9fHflPdQ>NJ=KDrGyS7kuD{ekJ8Jn3WlgQU8^g-|4l*%pn)| zp@JbD4C$dc=88m={imF?-Yb=v;`#GWWm8Ll%*R_=#?-GjIyI-c-t-fkKzk#fT(Ym(^@B8l(xm)8#M#BScC-!C3+K z5V`DrOMY!Nqfn@oI(66Z?oE9?0azYs6ozu=IFq&e9bT)`;jq;`E{{JHgu!XUJlt1u zVtTLiG`hVEa2DXQT4PATu)h?TO+LW>5}fMxy((btYrveW>!|j|s$GPtpGe@tVbn6p zINHq38iC{@RY`%83?ZHTe3%xM%Z(GXg#Yi+*+}nTe5@E9(4EDn)9sDP9zOcmR_3|M z=AP;))zjZt;yA1p+Q!&CyIULw{6C?;e+T(}7x%&6=S+!oB~MY~)?n0?iY60~WP|ED z{`sW9y;`aKPIzO?OFV_&wRkF6%zq|Ui0aQlet$2yw!l3~3JF7Zvp>p<3%dg$J=%4l zphynXJeFGE(A^FkPYRxI0jSL6kgtq(%mB%AIT-7?bIB=}krPCRQ3NuY5Wy@m5CgEs z9fUOv1XKKkx!_WA9{Yivut_&80a-Gl<_*M(CqtY)ScF?O@M(iB@sDPbD^)Mz>4O)mSz zS-Zod%UfLTf8{k6yD6`?m~$%RY(PjaRM*O4(SEf~sU406Rhv3#=~!O>eU?y6 z&shWDH|i?Om>v_w^jIxr=5t^B+6&+QHfi$W0vINHpGg>k@SdQK+W+GnU)=2o55Ps|i& zFMWsvag1=wrqGvp4)^T-v8yNpOSS`g}jP_GW%t&v{F|q=rwK@qI zAazh9hIXU$T&gF9>af-AYCW{`o|Op@kDW(lfb5k|qR?@sW4A28Ug(=Gh1Y2NduhF} zat)F8w!efsH~J349{L@$OraNppuR@`4P?{Lq0Aw^MB8xemgm~{BGl|4{V`|N4Q2}HedeE*% z?yV1uOaSyK8*cU%>WRj{Ad7-=&De1G=A&~#>QhTG2DAky%q3JpN= zp&8gb`sSPt|24B!3x#eiW)TFb*i@mJfSo=1ht62M`0a1UV`(QWP}H_eD#Kj1q$<2( z#__|{-0aqT5K{T7kr>Tsa53s$=-Rk6{%GhLruJXNF8 z%1>A`mMSf7oE2-;imh7~N}xKEZ*o0NGSX~v-{yWw%~bSs26!ru(}_Tc;r&!6PjDip zq}{uxf$E$Y!IhkB%+cZ3u#GFbcV9SJ=2NqdNmb_4(rzy3O^$9bJ;HK z(JLO5ol}*8@luzZ?$75csT^hwxuM=E{>kC!kZye;|3l?DY^Qz&RQCQLpgq={(dFP? zbB;{Sj(N;diMKx4&y1H&F!%I?2Q9vMHtEj!Afz{6&85R7cQTrOf5K?d4v9j+KJqcc ztnX!MX{T|jv#ZmWh=!eccPN}*sOD1P66F2)=V}J=++K3cPS1;cY^HO_$4Bz7@Zq4T30f0@D~w@O0CLbaxMK{lQB2-+|NPgaa2Hz3PLV^d6HY0IkBz}2bLmP)nD z>NL5-YARSO(m{fpC9Jem_>|3Ha51Li7Dw)p1!~8xP}nnbD2^2HQoEhk%%&b)Ii7t_ zkr8V;7NOUl?e#bN$zY9S1-Nd2z@@9Vk94yGq)}&bn1{3#WRbXHk^k2SNqa+9o`~O$ zu)GEn->kq2({+Cj!ILgDb7MZYFtrVkdd1}Qs#I!WVFatDUYMRPiNNLl3JJ|~R_KgR z0&}ma2i+3#)h2fpIe?FQxTz}X>h9(q;Jz;`4|v;Gg&Z-PKjQF5&rf(#*)R{e(}zs~ z)@0Z|J`|Lo!5bLp?#a~a9<^30_Y?{>Q2L|~6$*P^Ik;m2exHiY&1)tf?(EzN|Ia_g ze0T2L$$V8<0JMoH^v>c>Qzhbi5>xB9Qn7rgH9D1AjiZGbd=Q-7SD-H^#762c`4Q+> zKiFaJRp0+0IYfGLs8XAGLNlD>gZ$qX4TBNBQl$rsYK+nm6o0(%+O3coZ7)On0MX+_ zvlReL-d4rpE7jt1dtuo`7nN?gROJo8=y$I8iO1F)!t8`Tg|CgHSngYvs@DBMN5tz2 z14eY9(}eC^&LR@2VQ|3w<#l*c8yVJ9MK|vY9(Nb$9IA#p1VJUWKAaz)=!JEfyrl8puI2+N3KHzidAx}+ARSB%_ZF((v{S#pGdI7Aqxw%VWQ>{?v)pDtb z(e-7;AS^24{v^d@hU{*m$!4+yp#W=R8IXG&8oSmk66;(@i-B_kjP>h(UQx7uGe!sN zY0AgH&DytiLy5OzOV1CJ7wzGgQ$gKHoatc>O7xM|=Bh z$dOdR&aS>;EKV}oWEFB{%IaWi)nayPbQJC)61ll^^+dk=jFVRVB&2h@z_YbDxo&AX zo-&x65y|QR`f&zvbO9Oi@C6_H%%IZhj8<}CL}4=9ul`M1J(e&y?~PtH6!Bq}q2OD^{a} zRc!dvI+a1K*H^Mi<&U^0)KaOx$c=>n4ZuJ-6yFqrEw>|LkEO1TJFD3w52}g;(#)Ux z`%mxfy@mS?@o``DsGV-JOd*w6tuDFM8SokzTn2iF6>ewZGfRiMstGWg)sdd@k9@CS zb!)U@i6^!h36*4x1614IdrH?+Ir6*6D=|1pTi}ZqMp7IPxU#lDgnJ}0ynVjGQ+x?ZPoMReyVn2im_p&G3rC;+ zfFOQpN#6@6oImsULoMO2V61tIUrra2?f|?CJAnQHeKy}T!;ccmB0e5e>H05c0rYG1 z8-*DH{ft*};h)O>;AO2=r!)~~Qf@SxQg=s92CJ=PGFsG+GdH~XGWAG-@wq>|N6^5v z2dQMk3Mn#T&Y0psU8g%(?DSaSi7j=i%sMr$SLM{z#xCf;YbzN1F=ngAVJ~H@QMh)n zhP2J5GU(JMkX-^%gAJ1qb<$+?IOIyD))6neV`7Weq}CZ#W`O9VVt0SA>64%Us%Sw> zD9NN^kq^0fIGgtZd2dOo{eCsY!n!dpCoFTOJrHoi3|edSCUZWWHsy=^9qvFZRC-~l zHfo7}*a5=j(`&GDg!Gzhv{mNEo$;6>mUO1#c^{@Ul=5j-nMciuG;Vt(=JJpVWJR0j zV#9GH`tbY7m;-j)j_P3l>Lliga!X(5`UVO(Y0R0h22g8<@DD}T%*iq)2;9pgI-O3f zsl>}cwaKD0z^;_^Z`-+wpc|;N1y`@K+k<^$V-fstDSxN=F>87PeVYJ~&}HmP>H+jg z^j-bER=)tX{Ew}GjS~}O@xno>L?ZOQkVUjwChc|N_D(KJ>F;Rv$$tNSEAbWYyVFr^ z6!Woo+~4KQ<il1bH8 zpKWtj52|@bTHP2-7qG3FZ*sqo17aZt=+vE5r1M!hq}V{HFlzNSyEl|g*0hk7&n8o$ zR54!$OHx_S!(a<|rgcxcEN1PewJ;i&bwSZYBHLWabiwY>lS*ZN{bDqi^Xpvh5|}98 zJ-WzT2FnETr=kX@(Tjhe*6~;zYU}nidZyeDLi2Om${si+Tl4D%pcnT8=AJ7dl&mt8 zKX7f?532vOX0^?N`L0x{&aRnDh|x)wV-R481cM%E7Mb9mt}?mZ!GOcAQ|go&jm7E- z$Kr|eojzYE?Db-Q$iV}rn2tPprWUA^ECNe#X~&Il3c9Dm*$asQI()=F9wK2YBNZ?2 zjaH)gHV8mVl8=ufSg|H0fb&b(TDlb=ZTcrPuCzq^_-D~YZkw2TDe#Qn3iPq{{q!5q z_Q$XMmJu9Jt?ehapGBKT(kR_Q{Fe}Pg}~SPtis;==4B1Gqx7ooo?B*DQAw`a%m?}%z=1UBWloSr8WXZz-x;v>XR-h zE*9u8?x;c1KhfHT>@xb~_$R98x z78R0RopmS7KUi=%Zp>n*sk;Euh5!;VB-Pk-IStzNC~nBJ4}J6oOJR0o*bEg0ZDMxk z%iL#@*sl^j7`bAJ)tvs-?7C@}O`%ih>-AB&UST$>WpXF_`aYeN%EjZ~#F7(amT*}TbENGexc<`|I3Y-W%OJqY)0eYQ1;SGXaSCjcdA&=VX_gjI!keIAaCj@b!XAVF)zt`%}9C!?OlrpkX>qv*bO}R6QtlyrDJHhS%nks-fP{>6-4F#-cJKvC?`BIWkITYg7;HaqyR+JcQ~|s2q27boFLJ z#0QFt2uMZ;;Prf80J;-p==%m6e#R{Vk-4{Hpx_`XLhp6XNNrS*@=aGVUR$X3F+Q*--ClY5CcdWeGi z9}?%91-)7?FDkWi9l4YHEl~INF7B5NM%(@7uiJwAq0LJbf`hDwWpZfAF-a+zOM1e-2)xTUf)UcWG$J+Kw8v#m^?sEJ$a6q zV)w6S7WQHe(rU{rk1m$)&tt(at;&**bqIi#RtOAQ`D>DfzU2`mMCIwFjUs?Y_pW$4 zI&BmuhoQ%(Q&6b(=DdFAI&eMxp0qdQ|76t`2kMrZ&1d4FhjK7oN!DUMw`Rw|k=;S1 z(h^&9!sf|C70ifL6`4`Z(6qVSS;m*!V7MdN6*>G$WV`IuO*bO6?C2syNx1%1+= z!ljz@tx5VpsmWL)(O*?RRJ#89(q$r4Yci?S;5MifG7Tr{>Lf6kl5`Z&lcrb?A;uiS zefGJI4ZY(ZB$s`PTrBzwx$qoj-C5-9Gd9hOR*iKPlcIp=bL8Bcm`{F)e41ST0dkS( z(o4t%=aEkwWP+PXLbQ>j&RowFMDJUyv84q}Ia(p-e_Oe?cLBg6;(-J-p~4A51Zq9< z-8K40Xzo*iwxv6ZM`7ax2{jpAbSyBQwp5TIZk5G(ddRTUbf|^&ipSqcgUh!s{vMhr znTxF&A7iV1{BV)h_-_*ieqa~qHMV3GcaEbxh>@bR(FyMe#+_r<&&zGrcr{_SDY_ej z&8pd0%j?ao9HUy4O*WHUzKi?QAlY&B(yrhBxOrvI$5jefjJEUAd4ut1NTIxcZL&c@ zm4?FJmR0i}K1LOryf%w!7O5^=kH*-XzZ z$>{$(7}shb3Sg)sc^8QSxT+MU^=sDr?3U9{9Y8{tNg+$mAi50N^y1@Y2sr?~_rzJJJNf+A-1#ZTt z2O>F&&KqVctrjbGhHw$J+N`ZGXk7x`^9T|le?j{j9D4yF*N(FMp~ZTl{RU-jbj9C8 z@ccgaEHdB{_w?b=XBy;RN<|QG4iQT_i(2!iycb<@?YF;e_2uun>)Og2)#@9}zntIY zE(^KC9!CtG4znoDg4T#55IvaiWU^s8e$qH&0p^Y^QmK@coR`1k=tGQ>+Zp^Ja37+e8nw)6izq`TI#N?=}gxrth3M7@Gn&+Vi8XR@FPcz*l z-5^Dr!2iR2Up3;4@V!lhL;6TDIaL9OUu=u9wefH`IzryrBGThvVeu{xdA(sn4BU{( zfIA32mnG^yJ)ZDq0$D3ukMtfx=%UxTp8{|7AnvMv5mDpX$GO*<*EY#H&p^*l!eTUU zFR%_*LZOnXje3J#HSoF5b)R|WZZ;mZIedng-Q|8YVQ{&v8I#Ax{W-CHU|WtizK;yW zF{H0lE~``ym&+e2mG1cHN6Xw#t10HYYOC4@)d!hWJ2AVi0Ml!U+!YJ^-s&iGmyq+y z1Q{2NhYfi0J<0}J@h}Y)$|D`oUgu#lbUkwf-X>tdvM0=t%RfzS7$jRrFusIvdruus zdfm5j1Pluhr}#DzjbrW9|Ja$qu`*C)`a~KG`9vQNOPT)i&!MURu>)TIN7F9$y>!fG zh&h6xL)ghaJMA1_mURQ;ltb5v>OwN#<$iA>-u&N~(T{MqX^{`Z0?QhX4)hi@a*fjM z_qtC?Ob#ORmn;2#NNhWUIxVy-rL~jx$CBwv%xv+PqWzFG)Mm2b`T7CK9nQISaU z#suKZBFQP)L&(-KSI{B2m7P@9&1kpTAFEcgUMOtpj264|<7g~0MF-0mk^a(48dD%v&XCGlX5Cy%&3a8A>8e3MA9Kzs zH1vZDkX&0_ma|@pe#gsZ{_Rd|MZKjQ6LAm13;aE{OxEC4E0BOAk>Qo}+4d#b-d*iS z?2>TnYwbUxkL@k>*`*o7hNY4Fc`Y=YNDLs9k9quSMsMyeo3rcctIy&7yX)u8=S}8L zYDmZqdIQ|^=YH+acZtsJlA4WfsS38fMi{s#l)$@cVAiWQ6WiH!)@Ji5U>RsJ>NHZL z8dF-4MB>uv+vz^i$d&27V|0e%;}i-Ad5tobF*FNA;uA;35QLHKEgfFN!Lowu#K%ou zP;X^=xk+X)70Kt<97bjE)l4|#_lmGBWGLBuZo3n;g;MN~6{|^KH0l(Axod%ujvdk{ zdOVA@ClZJUY934Z0AjBTSjv@ZdecxQJpsPZ=XI2NV@`O{vqh2x8D4~2&I_cJn>8bw0VyoEkekgIgLMweR57AdXU zmy_7#-@S)x@I${j5PA}>=L(ZV=F7Ra%y$8R3X+Xhr(jInNe^xM1#G9zyN!J6_S&YBWb`7$|l_K;ecGTJz$DM5X#dNu||FYf_{BsPcG&!(*D5OyM$z7IK-a zSf)0PY?S@PTgkIVnzQ}A{pMgIRm8LKoR`eeN`Ch}A&5hhye^eG&* zY*Yaq)~LqbSqiJe^%8T(aVLhyq)IflQ(W_H;H^bkC~`sByolOQSj&SQ1HDi~^A{ON zoQv&dM$b|$Xtfj#NUfY9N+uhCPa&Fr0KYLH6UyM~Ba+xwkV5Dz5yz4Tz~Kl|p#yq- z(naJGP~l3Y1#`CD>Y+mOVt!$l&S9G~Pd5k7>ANo{>G|<(%;@d^$^GN(+947@o5arK zK22Ue`Y_3=l>W2|2DfWXR#2xQpq-B8Ay1%8#DYG9L{7|+K&D!C=|{v{68PM|6&dJ9tw@Nc1Pi$D~@5m9BmQ1&*cT$F&gp0 zjX|wc%Zwop^R4%?V$zN(a|2j3agEOYwFQj zl)aPtsgWVBD)-W#GBY#7FejEyOpT=z`}S;5X%(vZ`OV$k+xAVtB37d~W%sURYHW5~ zq>`EDrU%nR{^oB(K8y=uZf|&7*co%XX@PQX!pDybsIjC!c(2tL5BQLS`L30$nVIjR z;f|CBdq`(o491qlYOq&z>R`}ZPMWRL{nex#IGt>@yXn{KjAoP*_e_IGC6Sz(Eu~Xn z^r)2<7?7RR?C-HiVf^Z=b`N*edyGn@RI9Mms*U}id%0l5ZZu_M=}X&CO5e)~RHklT z-QaJjg;_{yqWf>}Ts^xnuQ2HJd6QQCrIOF((dHb)YIHj83yS z&5HV2vCWa+J)Di0)j(!J$D@dGpb2)h^jyoKcS`-41dI;NkLh`)Jg;*)z>9?3@GvQe zMoDg*nFQ8ynhbW4@|q$OW=E(sP+l|@Gy~))^0Ip8aLxQ;l17+JbG+X@i2v(O+ZsK^O(M)8^7x^lqKg=5yH%7L8Yp=Jzue zqsOa8!`$h1DBKzwJk*U&)*CkYJmGl2<9#-6b^BatpT+r%arMIF>L7ZdPUmcPn!I%I zV3GUpyFY({fA+Fd_io}&M)D4cr9VWJ3eqd~*sCP8DQ`6E+`r^V0G1YdA7Gp(hD=(M zE~GXnO=tSG7Mm=nHyF1;w@7JF1kD-~)=maL#xKKs{g;JG(#V&PP&G$`r=2O$ zCFM;)XgiY+%oypyF9&IL73B@SjPzQ{Yr_YZ`<#1eLhT46p}sibO5~z|Vo23aAQLy7 zVKuX?3#|&dbam~ahaP^Iz^>`?m*dU5f&&9P^9%KC#9-^mo9wDO2yqsdN?{R+1Ij}O z#F%`odtny8O2^wN5eULR5Tt);e*E3!#M&LG6wzrf&&}OQ#>OxZldIrBZG7{skCZo+ zw-LwI)JC$g%>7s8y8S0NgVmYdt^XO+SuBnjeZ`;?tCSWZRw$LCdbz%8uB%+`o183T zU6dV}w{Aern{DO1`Bv3W*>zi>KLS6T&Q)Z9T}_5YAjLmM`lzaRgOmzPhE_17IMmr$ljuQ7&Q=Q4A^2xePiG@7Qz~@jT8Z^7;R;u}JtY^%HZ}M{raa$d zJga~o7R&a3@AAvLOY__}$=LkmYu6rLTs+MGdWSQSh`V6bt&%&FQNLIk5BXv#6GY&( zVC8pc(7V0`@vhWb8=)Vw%zNC1ymU{;-rmK{(81UNCAkyUlg_o1%pkjNn(3ci#q^5i zS2Nwibr|oAHd>|1wq4tqE$r@{%%%-YZGp_NL!_??%1;*?Tr)n##zj*TBW!Y@r_2gg zJWD-=_clbJt#R7kS?c61FQK?~1~EP@y79|O{!bg6$_j~7`DR>uKB%1f!uxUFybfBx zek>k{rUX=j17*o`PwSyNxgYq_K=R>-uVa#5eER6KTk%F@`{^68BWF36i#5smzCMt? z)^nd{{X(w|!olCg;c~n9;`9E*{PfxZepsDf7-tGa%CHknS7~RBoh}S=KO&XEGp4h1 zM2v^&3+Lvjr1ad}J=`ssIPne-pSfxkYR4RKYCnXRjn3t4xH}OHK z#55VfL22bZ|2`dT-A+7ojkbB-JpoA^Sdf;qERxi@V~)vk%v+IL(i;l*5M4hr zrbTq&g3{J9@}F7h&BPb!h-B0-kA98^`XQ`4ZZ%v}$<{H82FNw&%Slrd-3 zdXv3iHtC2jsdc-J8I!|t^w;5ogX4ju2~*G0tFAO-$zKte_@u^YR_2ZH=q!}88D-g* zEX=OUrTsNcCRZxxfiuYWeR9J8;ryUhEZs67lPSrTd{58wbaU``R{pJ9!F$X@3#MJG z*U_ook2Srp<4UOCkB&MR%`gMeKUlJg=qG7(WU^H4+b_a=&xLxT8H0jx zh6L11BI352#U$l3YL!S#k6G8{lZe$rcEOL5u!>j>N~0;ZE5LRc-{Pub4cp)k`deO3 z25T;$i|A(H*SbAb#TTN;L%?Eg?|^qIP}q-u8N#2o`cHoH`Op9Mw~a?1z4g{F|NdlR zJNe|38z=uY02NVBL>|<+3m#Lz?+D1kM&Fj}HYvgepUI~ai-^IY_4#tuJ^g#O)X|TT z^_={^vC&+?!o3#cX&AUX2YKLQ$Q%i7>r{qgfviO=(zrlg`cA(}h7R4H;u!bSvEsSs z7RN|_?A!^woi~X$a!pcgGuzWrx61OXgxY2`$h`LCrP$^v?)E^HKw99pZ!oi$l0 zhQ|Wf8#?BU#hhSX!cq3XOvUMYoL2)%Tc8K|oVBs%bcpn0($?Go6#${e{~C`AKGw&t z*)a_DjrGvp80sx`Q;&4@Qh~2!T54TW00n7m#K8-@!zUf?eN^3_0jQ%TSG{zWX$3$# zszQUDJ}y`Jls-ilsTF#y?WJ5+iTYn{s#k;rd?&ezJW}Isq4u69F@xMmhe+@sah(=|0cWHAhm4yN5^6!XRcCxwk%xdoahl z$qA>k!B_QEt8lot>R!^^_Y%WKDuRkOiw)<|K@=18PV~e=jE~Jg+$i8;uy#bd(wzhc zQWzrfvvj2L!aNr%B+PV=5uK%rCKT`OJkf&FwlYtA52x%_?#~qAo8h=;pXFX-PUD__ z?KPr5`ZRg13j*I~3LgUj|43hs0w=wFwX{(zc`;<_?oR=Lq)PYHk6wJ7b_+Zi3&lvz zg7P5{N;5B|!LtyF#`E=jSE10AuXAs5*OMJtAhv6@osGs7E>|REkb{|~iugT*mBd1p zcp7*VtyB{ZFx>GPEk8|+Y}-~rW+S!sk8ef|R)a?E(`>YrPfmBx4)=K-pMi&U>a_J_ zg5)rb2Tgo_4d@b6{0Kz!A;?}VFpHBtY;dNTMt(SlFuK&;T)yDmDM}q1G?(%e{;;5y zZZ8bI>G(iOgD4iY43{qOlo?!eOI=g`d)kSPwTDP4BuYz!P>OTdK7aHPKMx4HXyg`u zMDNl^JvQ%5z#Q_~gSJ5EgoG&=2jK{XfDN`D*Ifz3w6k!{HSa&$-BqYdz-)^pvf-K~ z5bqpz9*Pfi&~=Ca5~yS%}eT?aodZ=n?b>$WRllXBe&8n-Uo z07?rT*Ts`}1NA1ATT^KxCOKyGcVx3OWsw6CF~O@YKC_FebVzG!w(OqSwLJ|2pJeYR z&;N=PlW7`T#n2eNmDh`IBO|YdW_Ml%s|;ie9pusznVAp3{^arxkt?nuA6-K}^5Mhm zu30DyEd2)hU|@DGgnH0CuBItCdNa z2US6^-7BYAh0P zbt@b7&04@)s|l#BdC{Q}iH%`n!0FUrbn#uxM#Y$m(hn!ADtyc~aPo$6N%w{!x=%pn zHmFTVzF>D`O=M^0F8^$Z)M8c-l-IRBt^Jo!!FRwK$nNI8nVOv23?@1z$=ze~%p$k1 zz}<&_0x7#htVJqUDoWH!opheQfA^#oR=vS=s%~~V>|%-9Va>Ap;GPg0cjb-zS3J5YdsY zQ8LJm4>xPjnwsb>W|QJ5%%=O(d|PKZXBNW55_(4(BY6&59TX(-(8s}&9#T|!{;xhzmOZFW(TkWev|v_ zQM1!&Nx;2|yEQSfc2gw)wkbfbaJP|xWBNJFI2yodP|d3ocqhf{J01nHE&Y)ziJNHE z%qF5-PvC(R0k(?lVsE{HTu4qlKu!|*JSw2?9SR7Rw%cpM#fn#ukGOns(r%QsV>FH? ztn*4y@v-wPMBe4t+scK6GE_)^0JpE=DFUjV9zt=uqDA#X8>uVM9}o}`FD1SxYx#Pp z_49l9W_y%=W;qUoc6sm6zXJ!q6eXF%M&MD?)x&?d}2j^$%A|>o};iLdr3BAJa^#a~0R*2qz#gSg_&OceAu~4kHsMlH4R)ZeZsY(yJ z&QGofKHS;K-9gr<)v+WT#zYY6(d(|~E=s~~PnAP|^h?}bL>At>aSQs{^8Fk46p-_d z%Ee-Ktt%2=+;xQr?fO-7a}i%LlQ*!e(eLX@VTNQ;v2sY37p~h1e5pwMi_q#qDPIlK zxuzu5U+MfI`3w3Jk^)366ljkt)u~KU3C|xToWj8aGFy!>C1E6(^+~k#{%M2BVpV%G z4w=fNwCI4#6`O2U{WnGcP8G@a=DI@Y4C)L@185$0b7e^6)!Qv*x7lX-dcMEAX;VX5 zIX*hQA&vBW0Y(D={~>H6`sdgWOF4wFG4ZF^Oah^2*$x`d<848gcM_fP zM2)R;(AtJPl$-8CGk(gkGoK!6B_aG(bPwX|QTBUW=g$E8m7Y!Z-6_H#_O2~|p>N-f z2NLlRi-EZ+luds;=F6lrO1(laiNv9^$BK^L847GUH5oVRwP-*}e7-e{Fj0;5i{IyV z(LDngwt}d1`9JnH>jAA&E3+3e@ewyDC3Yt!Ty9UqsltY)`-S2#?tpJd1e2XBJ8ti| ztK=KzV;kOLveIeQo+B;BN=;Q`)%<#i(L4Y~~cMp#*+(W0T9 zh|oM_S-+@i8YQZ@-nM5M3TN`n@O-j9T8qvYv(Ks9yoeJhJ zk9~txsU119MoT7*#ze+uRV2hZwNoRN*0|q>m0p`I8cyZ_Do{yciD<}&5lTFfDOueP zpY3SoICal?)FLjFh3Bja1Y>gN5slemb(jpS5;krQn?j?|hh%^`2f|^!T&{o}C;q7m zronQbUm3bCjA{`7cR=~{hWtUdSwqn_c#jbK#Dh=9$R28>ljZ zW1c4c@8-P~cRXyjn&WaRmHnd0p>-zV>1~Z*cRNiIz0#mxno%G&?bOicAgl@j5c`gXSVUMM#?rD3zmJN` zXaTf8D4eE!r@woUWN-K*&<4bsWg$9#4KSusBlv61oT1TORck=bh8MQH`=WpSBtE)k zfy(|W=SRo#-JvzB78pbt+1Shiz{T7npbROAk^9-te*W`6a8F_yc*`x^OTtVFSn<<& zdst|fM6OM`^W_B3w8e&IerO3I*vNH8l#9I37piQPp}uxQMuI9+X9qNu`%ZL2xmxP< zORz~*k!r2)g%?uw&Ma$?Ycc4krOP7_mJ*Y~V16Xu+uM6!WaO;DL2_sbCH@H7qJT|8 zx}W=La(v5i-@mwdMz#!+#L=1p=`kpY^%mosy46x zYGM&dd&D+gzNgrl563ZNe-*qvV!fz%f5Hu`a zW-BpVxR23^PTJ0BPTUDS+dabA;{>v8FWDtpy=it8JH(D{AR}zOlg!h{{kyjeppL-+ z1l5Ms(;DNqb1T08iUO`hfZ|73d=D09md~E)@E7G5odVM&xpm_C#iTPYzIGHy8CYsW zg(aD>)|iu4@%&IF+TKU}zMz@XJC^c?U)MWI|M&-$Yy0Ov|MUG&baEu8KrCdO8FWEd zv$d+!0pV=3t4^&Rp?#6Zo4>fax}gSwf;+hxWDZB_>R-G*G}HydAkGewsNWd3g#&v4 zxpH|Tuo^xW_AzM+o|dZZ!65U8JW41=G@h;HE9qAoCqU{8?=uaE3uAQbOr~b?oS!hWNWyPLv(w z>Qffk&YP||Y4>_@MRfgj`*v&U9{1R1Y0X8 z!Q(OCNz-ulf}>m)`5+Xh4v`OXhqyn6Ftf74sW`L=PQ{S6{x?4qa)^6XSGv)Z%{OrL zmGuJn+)m7-Sc1Ne$p$G$i@vc9d|yIl9-m~vEq{UgUch^~F`lZbl?qudT`?GpRn+zp zKp|Bq^z3j&Bir8(*&Ramy*h!GuZRS=50)!rXmRla3k%G>F*Evs)Cu5cF+;$M!8MhX zJO<3lOyxhEt>lYNDf}$M)kggWQ^d+bo!aT}n^G#ZOsBpo>xx*DvJZba5Q@9+#nYR) zq7nZCxuek4^ZzOP4gfi;a_v3mo8Eixz1N+Y?K|7EHJeTEoj^K-00Bd9l2AoT=qQQ^ zQUnnd%atlcEFkDb1g{kPwO%y)`9J6TW}6o-{1Ya#Q?tx@&wJkTyw7u9RI9VtS~-l* zqxuZCX7iD}H*QbMjvjSo(ry+XFkP_wxp!bsGiSyG*b6TK>iyH`)>L{)>{Im9X94Il zJPHB%%p{#kkxQ47eu<#JMTdQoPX!cE+^%J8KqHUFoT3i-8V7PiAe!d_szWVSk{|40bY&rkFz`q1>FI?BQA_TJ#5ft{+^a1^(QDbKxEc zJ&0)qW+HwdY8SD?{Y7iv()DNtpy!!eK5&4)r7g`F`2XfdRHP==YNay%dIXQ8%_`&U zOnJVDGez?KwmW`)&poy@E9J{g_0C19Fh)DTN@G;p^65g!BU7sMu|hbP$fR9TlR_u+ zMtqf2t-0d$##0u*2X%qH-~BGLi#Fsg$AAk90SUHJz~mlmItQ$l*MoH_3~^sHO_?~Y zA1tBbPe{Z=0br;(pOz{;2odKZL~$dd8^>0Vt;KAeq%n1A4~pwNFK%QH2xLrH)Hqwr z#w!~2!R8N!#LuBEKiV&G7yj$1XP)7Ezw#ANIhSxl4lEH)r+r9Sf{?}XNVn@y$UfGf5VozCjm&;w$r&U9K4E|oe>(Of2C4i%bv9j=6{$#3otZG30M~-P@zL@*5M~XRBSE8NVIaoNt#{A~d1-A10 zzIg1|3*@DzufP7DU-Qqmzu)orUp@Xg8X?lj$#a%3zn_1WUz1YFi3If| ztg_iyq0a#jxMIcgagRrUt_1%iq6?WD|8;ul3g9D*3WcL>Y#H#j?Z8L81Pr?#-@JVm zzf?v=dz4nnFgwd)JpA;I%pzZrcMDeFB&QNsasMAQfHX@vLx;yTBd7-p%n{Z zFbb?qo&<`>>5<|=gGt;_Gk#c%-Pm@(ACaG678A$`4q99k2Ge9vcXq{yba<|YG#7r0 zpbB<6v%)BM;q?Ffo_~ULw39gh+8Z_gByv4}(y6cAN4q}z%=FLp@4xrp!3X#3dGO#t zerQ%_VrA47LAB5y2^?#;$C9e%@cHl+c-(bmeTI_8YYs94E+E@p8Y~U zmXDh0bs^dLFwEFYvRuP1sD;{~EVx6S&L5}IvG^39akR%YNCifi$(8=0z z`mAeUZx>3FNmiB zOFt@8OQ>Qg%U$Frmsjx5Y^Xf;SY-ogS#inK)CEhHT!fu>(@iD*?AzAv7=)0SYGlKz zv-x-YN`R_NM(|cZPtH=ndD8i>PXW{1Cs@CG7Qx3Dn1-QpwWVpa-sVk_M2z5nC4gF_ zl1Rbp2AzAG1OmRu*d)GW6kUvToQ6GAgW?$_ZXH!w|6QAfwTOhw6b4^uoB;^_n7j(J zZ7G1|QnnWwe*_p83o=moWZyOm6hA12h%YpL+V{c>{PXl7{u|Fd2Q0GrscWuz{_3lt zLhw6&lAOvPow?ThV|{J0=E0%t^`U{@TsYI$ADsT->~>fkbcQ0{xXoqo-OyrB#wu~_ z2TdXx<@&bX+E*y_-MSbZe0p?bWaK#pX3n-J+S08p{&>io)kh*>E|`dG3z`^%)Xr{^ zx04>9-<;7{weCN=R<4|y@G>UW&Sg;lP&DOHOZYb8{t$M@DPXg{7@UsBn(l5ItG9QO zOgBnFV7%J zV)7~o*XsB+qA z8jzB*r`iH0$Kk^uXJ9%^mlqrabx1b3pC2_mml$l_zRfiDmv_%SeYsq&QtvzWa*_m;y=T@Bh~hD*GzR%^FN_LV{J^+foQ7%ij6$-;TsqE`=x7lti z7Q2AflBpr;VDngAkN#t@IE?3uga634raErJmG;kW>R(0CVKQcL?)}xedU6@#iqQnx zM@HE!PX@8YE5L+^wINpjtzmc1%pw38GFu&rq+>M1WfL^u143FppaJzJw@9brQ2oh_ zk{}mP&07Grk^imgvk(I!Ms`8~!J_fGNI}XxD*Ge!2j;%}Ih4oTYZpSixMh60gRBJ; z?phhYGoqaFH~K4)y%!9(;>F{fF=KfBD3HS&PYvz|mnL2TCf7Nok|V+B8-x z|3txPF&UbT`0*>@kPpn`0dMT2kS7whN8Q2rRe5hhsOmvRA{++B{hC6J^sHQY(bA=K zJYe)8npWw}p>)*O{9d{I-h1z*;7`K=pC{_yriiq`f+YDjwTE8T7cnCDiII@WG>q{kDR!`ue8(njU0$ z%*(ftyUAzozlYu_d63+DJGntJB8*i@zW8~1W|e z;rBY9Q@&9zSxCmr+0(=V_6~& zlIslh_4i`>MAh3-cYTjH=FDEVv0%njH2qa&_wZH^A4_9*Bmq{<*vc{a`M3S$ipO(M+)gg+^9kiS>Y;|t3Q0Hxz^%? zLb=?YOebFmTB0Er^hM*_gO-5J1uYm2WEDgFg}`^}C~(@A&Vj)I@_(fk6(hhs(9tT! zB4$wSYf>Axp6juP0+wE?m#YdL00(ihbq|%VyRLlRdFR2dWT@M)Im-$%3vu^v0M4en zo)0yVlZofRKDtA4a3fj2b_x@hi$=()WYY=s#Jx}=Az;ikkWn(Ugf3mPpoS+Xha=Qy zRXJ4WD%i`j)j6?(TS3WoZf}3sj)vt4^&jDb5bBCZGq`b>fjCSZ79~eSVVO#q4sVlc zfUqhInTe+e0zRuz1Lh-ATGO{<={9~Z8geMqL$P)540lEJ6ARDKclnpzdk-KjXUo~Z zNfBG^X8P1wW?z08$d_D|L2}cPv)(PCh6`Wht490PsgInl+->3 zL;xFM{u|RU2C!ME zxLWJ;c|Bwk|7a;1HMQmAlN)xUgQBVA6MnFI8h{0p7+gm1w}35LUQI(E#^RCt3|=!F zf`)&WJlDa0=|Ot`ucR(y!j7~Yye{-&jlrbLLu6dZ`Qqk)8(jdm|0i*mJ!sBY{0{y# zvA@EYYSCYz6Zw$c9dY~Oa#Y)7!BE_THm*i%vD;m~YHN4B9yV>=w7+6R?cEyk22t!& z5mf0s7;!OzTS1rdW7#b(sT+LUIGOumg!N~y5!PN%CKUqpI3r8*W4~0f)?#huLn)z{ z39*luF(r1(PJH1M5k5CO16}&SglgXL#NI|Pz6!KZzVZ#1X+iD@{vVqeV&t40O&4j` z(0C5GMrlrMHXDmTF-rW=Xb>e*^=C5tFWTx#O)ZLEaxI~r zf-;swOHQgWg0NF5GaJ3WWE`j=g&_%UV^_qRkQo$eT{)WYhOJg<%TIQ4dcdG`dT#nj zKv~?@WXKlY7_ni1E9&(`E=YM9F&LZvw#3XK`qhmb;vT5tV?Ms&QbuSuONn&w_ z&t*%5EP>~e@TQ@x#}VY8O--!Zz^2IM_VnWPC}NN(^u2#Nt9inZ0-cEBnNrQAI5Ucy zpi2X}V#tF*4y-^RX_S*Ri-nR6WN?yZ>h1; z^X*g!?$P)a=d56H;(O-5gq1=BsGd+5gi`ff49T(nkRDkeK9#8>F>{-ZEgJwK zcD7u3rA`~kqpK3@x4Sm*zsZ=*R(;7}b*2H-iODMxJ>eV$XLKY#nls2T0?>Q7e;*P_+r=aUkJf>Z7Un%j$oL(o>0NO_6W@{_??E$|N;{+k6H^kpul1iYqbOy`>@Y}u<;bmw$ zv=Ge-i`vZmiyFE9qukHoUks?XWCd2gVf1vEM#`m4*EJRDk-i}^Jb;uOdKo~8^t7VK zxM&omu-z>G$HadfSpT^w^WS7NYE?0R63-S}ttyWT3xLI_;T~aG7Y+;&)FZ5rl^r0g zWZwuC*ehWkHQ{}DuZRl4qd1}1M+qM@YegRxUvRhQLYZn2%`RD_T5;K>3V9;ZUh4O0 zTDv1@yIkdpmd7VoRz}AMN~nWRFMi+_vg7g_Z!}3Hf!YmZSSbntGv2eU0q%Z z8AB>N$p7P;-z=_M_hpX_e5?>SkV``0sL~QBW)c#3koK@bYLyuchBOj4sbn`&5xNl| zq1o93{;)Zk(ZYH%!bKLLDaL-m#=7~r5$P}UM> zn7AcgV)YZdWZ^xb5umR_h}THeN)(}INwAp{V5bnv3306m;XZB={Xtj(%MRRN<5n2Z z!)p*gutSP%Sz!;?gwsbjK(LR+^CevSDB&D-dY~5luQ&O3+kW2l^G^O(Z}H*lufP5% zFhG1Sd1m$Wp0_>y$~=hW)iRYrzUQ*xa~H`V_pZvuBEdjhWivb0rL~Z&Mh{zBcET23d>&9?1t+tJNA=Pc9Xr!NGeZ?Ldmp=3lPd0v)LR;a|P%e z(VhEt(G$6o_s|ozQ7OTysuz^8#fV`xGDme3-=hfU6TW-g6KW^HMtD$W5y8iZ_Qmqv z>}LsdELP#otl-VP_P{ykfH1|ETj#N0zPwp)b$Ze3#Js;+Bj5czc`U%+)$vwm=UY4{ z?ledy?8Z{K{Q?J)Q1cc%I5?0<*GV=+*>Vr1o|0N`()88#x3%rxzn|QDck|^a*ii1? z9iW6%8YX%t^AItD0D{wFxx2ERzjehR34Z?b7&H|24p!sGXu>)D0+Z1X)617_Dl*Mv zM|JTs@|&zlp+^{xWYQZ+JEkvLGD3Twdg{+V{xRy>A=F+TWjxneS)HV zJpxS14AZxVk`CI{LfTSjQf7#wig+fUj-$5|^m0xKa$h#ZmP8|y>m;piI`28bsfpPa zb8g~E#rzeUG^%oPdkySP3`+e$O`Zw@a+dU3nc<7w9^s2+YlP>@;2fVjFtO)mBWIxK z{+7+fl93`~ZZJm7zK!l(o=-dWxk^XQJoDwG!wRgSzGxTSo$1IvQK}W+DlXxl z-Cum*f#QBrTT)yu!+FB(|I(^e7p`1cDqc}Re&wiKQ6!VfU28^s@kD#AXS5JZ6q2p2 zK(cXgqXI{l0%yyu@K>>>GHQ?Q=<3YWgg4a3?ZoUPMv0r~hrCe9>|qSHauBdfQ#e0B z@7CE04x#RLS}W6Z+{Hm3R0j6qc|TU0NLw?(3YIz+R4AAWV_!Y4I8Ee!44aB&V6o7I z*hBPb!Xd;~gE_c`!~C3}n*sfqkKx&N9sl#6`4^w@8MM!mX8wI5Z~xohNa-o35hH(| z7x-u2eHR`rU?V>M&}k%akho9zPT+Nf=}POf{DrfH|2Y8bLSz9K`rew%cuv+=&aWRKm#=nJAx|ir{BQngeopXV9;b%DP|N{>0=9$gmRe)i%-oviols#^ zDbUknF#^^cJ6R}C;SItPV>1TtpFPNT;Pmi#1@K?9jfvcWghuO)1$NOL({GbU+xW)^ zSFc|E>s6~(y|;Gl+IN2FKptvKK+#=!J|?6U@(RLwAytkL>gU|du{dgBtid6=u z-)pnG^-hD{PA=Q1P-)aBZW~R=QJZ6XZGhINzfGi1lV`qtNnBwv>RSM?lNnG~d$<7Z zU#Zdnju3;PlWgtg{oQ0Mqfp>);eYwjn=We`skM1jCbcfwmMWI=pqVz9wYo|o!KMhl z)!fYA`A*>iTpR|w&y9YY&0&x!+;)T0;{>3abGY2R-$D}ni`Vq^?XB18;n_aghoXA0 zo+{*Kk3cK70?yegPOqH;s{4qbMD*>ZOg;Ena_rkQCYF3oA0ypdPakQJMeV_+8^s=?D*o@aWb=Zh_z>aWXl+AgmzdaA=VZa4UGb5ez3y`6(9J<#(><+``GRL zkHn|TPbSnXf3thXS4?+Cad1%gs?6ouABy^-Y0jF3tKW)4h+Yf{CaEqK#y0V zkgFi$hgy+dpA1Eit3XR<-SU&v0iVwei7TbiY|wumqv4<=@LN3pku>_<-kihb<6p>3 zuH7Qg1lrqHY@o_mDrR@ZgR67>Id910b*oZFn;ShTlQVBJS_AQNu9FoYHQ;;r7WYTa zDX`76vq1DCw>RC>^e}WDpKI!`SH4RQpGC*INU~C(X|7zNS%JaKirSE!WC%f>8ArIX z8SG`7uOj1|t&Pa$)c1sh@P9dHm;j@<0>d%0r#XuiY6Yx06vmm37n$)RFaY!V`W0cw zlIihvvwslAR|A@Iu)qSCs3B~&NXF{e*SRxj;7b#h9k&r0RRK7d7Z;t zDjGCOnJq*i9-z0ug*}+ldd!}p!)-aMY_PiGCBF-E+h|3+$iHV-guq^2u0)}Jq*A5Q z@sKlUNf_k7^2Bo~Ya*IZ9e+IL#0W{k?zQy?-FBBFYWF&JX3$AP%BoZVi5jM=hgD8@ z)NeMEhcK#(apAK!pj;%Cej=I8Iv-2kIDE#+9b?N{IF(A#S0Cvp9LB{Ji;!LG)|Fef zq#rC>Z#Z#ykv67;))*Q*XRjq>TEg0tY^oyXbE^3Y?L% z)%->~`CQAys0?$2L_^G8fWlR-{_2>8ljzKy>(>sWP|gMX0a%nADRo>eSJAas*)o|# zE&yq&iYXchgHm6fh{vo)FXx{FvPwg|dFTlLkoe+T*G$OO3ir;^p>vo{Hs8Agk zor;mz@!v5CL!o8M$WTRc#!FJ3Tp=k8$hc!M`g(y0mPq7NJS8vi6=GIdG+DSmXXeungfj?tpN&{J@n>TvZ_bts2(3lkFHtYCa`GK zCYQ2!O2lLShfo7w$gIg&g+B?aiYt4_`fX&(X0mcMS-PAoUP4C4Nk^P|yHI7>w3Te& zwv%;hX3pV8@r$i7b6uDypS2CjtO<{q=gdWPV}eC7G9%{17&0n2!x@i~c_ScZL9uwn z)37oIT@xIZ*yEqaExfSEPCvzZnlEC8T47Hq)5%;?fo3=?q}JME($KT@Zf7Qz5BO{Y zm?-}ouuSr1s#eEFt+u!Lzxg9igY!|Mg9IQM<+qUId>1*yUkY-^)5@f+#9vF=_^0?o zDWg+|`jy-7+vqo<%VtaXV)5JBE%8Jt#$arzNSuBPtbSSpVCu^hsg71abx=g%e{=BI za__dg4v<8`<*>xOu~5Dj^nb(zjyfL*a-{lVve%Ec3I@96{Iluw%2;egGPx!eoBDpO z<)zpdXN~AxdY>=q^ZVXO===t^HSO~G_`f@rFJIXwR112>*+MG>ywVfU0Tbt3SZ{m^ zn71o{ck61MB74Y5`^XN-$z=NhvQ=`BZ2siwbfe^oGwGU7kX2xV#Jum4Hgf8Ix_jpd zTUJVzO3ovP8$V&iXQSs2>dP)XLd+uHgizL;OM)11Nw5u-I_YOkv;dobamnI{GRcElG%VaVa|{@pF=T4_{~{8TTMCaFuI z)`zJ>slOmWyZ^LSq3u7J&x9m!8+ zPCYd)bD9c7h;XCZ@LTW4RLFNWQjUY zl$d{&FQS9}r1xkILvI(7-Fs;j>_yx#8IaBGWSkDzve?KX*W>I)7WOah&5qoQ+g1Gf znb#L-s98!Rz)jiuHT-}GE}i`(wx+WIFjkMPI!Z-$_yRdQKUf-Dn;)0p^>{~o;T|Vn zQfk?F_(|8FF3V-w3+Y(gdJbfLbvlc!Nq$fz5@}gBcCnGNBXn$v=BM)H%Zz0!~ z&SpYsf2mkrvw7qCvcDPMvqJv<*y=SMsd{~q+Le%!)CMhKXFTc&h8~YNJ$i>Ro#Wqh zEt*`Jb{l0wA=pvZ5F$+MdHPIB9mB@wUOfbKo2pAWvM6ex%&MZ-9S5~)Yx7S64 z*$1>XmWzYz=v-aWz|9~|bcVw8Cwu{kwThfO{lHbW&el$))+~=kqV^qk-q|+Xm(k(d zmMz5_*ZxRE<}&*yI94oL33o1T0N*(dqzZFJABDcT`H z;W)(IOm29Pd_nT%FW$;^-gnm>M zZQxlo3$}bLa~Dz+NQNN#WXot<(2-$!|-gMKhT~}POYgMe$ zT*LUHOqZ<|qP5Lcdv{MYHqp}R*?qzZ7ypibWAo+DuZHRd|$qN4Et3P=`8$_;Er2Cc|F8bTOBPuY;fFH|ha+*!35Xh7=W9u5U z-`Nz6!RfZyXNUAMW&9|gl3walQUqq+5Waj%s%m4YUXtm}}rn1@emi(r+ z_V#U6T(-C1!gA@bz}cRKxVebJWm7(Gbno)WtCuug1FzC|+1_rg6D0B1kiN4pVo^nwkX;R@=s-%iydMgU62VBTF?O6DOgSnV4N##(gjI)8kJ z#f$R~55X&7vf z36k4(?!0}^o;$a0<-a-m(|?jXr`O~_)$J?zLe`6c_w@U-zG(2WD$vnwDM*uPvhfhf z+(FI9z{%-I?ty(-$)4%^sl(adA9Fcn%WXCkZ)9qf{0&RmlU~_VYdf`)3;W5I%NCeDfh>hpL;ii~k&+0;GMgkfK147h;g?_! z;0L5Qa^ZsnFUNA@##j@Mq`9t012qV;Agv2W(i{A5Uwu`kq|}++jwmEjyqunG=yDjr zr4uq(?Apt)*gD7wB9-L$%Q?4epxWgRa-<7loYqKlbDLTRf!sj38ngm2>h^f8IN_8a zWi^KHn3F^x5wZQdr+g1zQ+H8|I2AqqxFFklrx!(I#;clMXIUZI6UYDN1Y|A zvzS3DLN`7gR{K1lvv#`dMgwWMD6|^p&vSl1-5_$13leuvw-i#aDgcTe*b2@xPIi82 zzs>2g8ogSOVMX*T_hxu9h1ckHzJ29MA7H$Btzqb7eH zE{dqfFrp>L-~i*##xPJ*BZ7uwf@7Is&la_>5DznJ(sRNTkH|WO+KZi;#ax+14*=Vo ziG7d@n|FS~FstI-IjXmih$d+SN}|;>n-(z%wwcqE{VReM&oy9i7yCjkMCFZ}83`Y} zI7Ut()7|{pRtx+CP|u867RM}Rr=m6vRCgiV^rOm*5k_s*j1bMSvc-cT4y#JI;SMd;U4rZ5W9jJ@Q|)a0u5 zphiPvrbG*$<@K#i$W}71ivQnu2xvec%x!mq;!+hg^Iixt&~kE4e~){<*9b1}_V{6}%Jk zTY?v@vDyraqXbVjbK5Xc=3d1EwebWqD9F|^UnhFLIDl>c#|JR`6+b|HIjor#cyNW7 zgXo|e6~>u=8PCrA$bN~B1HJ!L65pAs0^>ookgUxsgRXuxs7}B%Yc|**d7xFQd>+3} zCXtw_q%9~>L!C^aQ7N?=j?<93hp3e5tOliGJ*7)aO24NQkW_`!<JAvp?Dov0KFxy-hlTgSU zo`5ZxEX1HJwpeX;du`~qfa%z+WfCSvsUsS8Xk8vl02DkE@_mzoMVS%@e<raH?Ab)luQKAOW;BB7oY=s~Q_(9t$dq8^qBA^=`sF~XuMmy`1j~`{(=BvE{mc?<iI zt!5dff3#Ma!fMMV`tDT6G2v{GXss@T(+VdqSEvGoQb>*{0uiUiW7mT%9PDORnI4_f z)sHSqqNxb6@XwADU!GYpu+=KNob7KcEwAt8`!jV3k7K`x$a8zI6pJgq%BL7!<=JeC#$2I;&DxaQc zqn+)?|HMR*jY*$B+R%DO+2iclvWM2=jo$pl!Bjf?*s4AoH-l zu!fmRxM&wh2bdlF9{^ww;|7Js+stc(=@Yq-L9nGq1>_@PzjzsU(ez9I!@t`4hxWg; z^FNs8C0AW_)n{(G<<@hjD1-H)LL2+TD0u@lE>zF4%C9s=#Xtk{lhm?hsBr;F>Z~kYCStHZEoi-)f#it` zERCJu+FuOse{$36`apXN!TZgCf% z!TJr@@ItK#35Kvmg}HwAxDYO}T?)Lh?hP7%#6b`LEvu!I-1+o7KD9ifAGX>t|`CIzeulWoxbz+zf#LPFHHZ0%764Di@By)8Fg%cg3apQ3EW(7qjuN{ zgy|lv(m?^Gv${TVjGS>AU3UPTz=LGdKC%UEq;0#%36eeJ#6i*}>1b(a@144TH@9{* zWlXBwr|jLy4M^HaxD|6VchqS5tO^ws_x{gj(!9I}cF)FRW|DkSb`ML_*l;X(6cy-a z-Q;Wt%VxQSwnTnRm;SAeBu1u7^eHRAxT!mY$#Mb`lPj}whepdu2A7{%0HZYT0Ql92QObLjc z)nYNVksto@Rb1ZS-)58a50gXF{1pzDE77-jd{m8&@$lwt<$8DTxI(Wt^)6i&E>tT9 z{;TgeLeVfVFqqLrZ3(J@z;GulA-^k++A;s*)Z~WsRWBpp$*mZrwN|V%k*uf!RYN7q zi$g<$gQp}I+Eq5_zz~JT(Nb^q$-uq^2#$^aZvzTbt!XecLWXB+TiaE6AHYB!9h&e) z6rAi%SH$VI8jMDb6knPxm2z8bR=dt*voWk*Cu)H|=E4oTnd4)ffI^kX#|x&VXmcSG zmxQ@ej)D`}BB`~K{y{Ri9omdr$+FGFEZMl8tl-v?RcmOXOe#S71DP2j%Qq3o^=xa< zv@USHA6+A2m11TB^UH-C9+^vo8ycus^=43|%vuY3gRuW`do1qt`rJ8CORZ!A#IB@2 z7`d*+mPl5M4vv6d+`oGVePb=}-nsLRy?Z}<;)%%cAIK|F!Ye|mTKUT#K_EctAiRkz zKe~7CS^QsDt$OC7VHf7sVpk^?#&uCo5unSKKxRUJ{mXHw5&lKvV6_j zw1G<8EzuLVPpLIZjZtgRbb(Rxvf1lc(9zKnpO(Ofuz2~04B$b-*2O*iHU^BhCP{@z`>l>a>B3Fq=_@(3=C>Tnm zU}scn3;7xtn5EjGMS}p|Ve|^A8vkjG-=5sveL`>VNqv3fXFhi<0=8$lkyu<#7ALV8 zn^%EZcVNP1J?0;ouId3;#gV3E^?^&tSKS~vaoZ+t@i>#hjdBhf(ah@y2@&(WpjYhsvt?uim>=?loE5H6s>Lm8 zTK{|XE22>e7yul|LN|vw^N)_d=>-3aZ}}%DTH_tVlfl5$%KlW#=psiO*~!23Id7&| zPPbNCQ}IQMI!e`!nxozNOYm!3o2_>RnEOup7q$D5`^!y6t*Mhb_&+^~%WM35&$A2v zf@oo`V048bo6M+m56(^QfMt!d6$7!TCToi&edCdAURSiH61G#w(jwvm%;A96v@es( znlmm?yC0jXaac~p%8*Q^ab#Na1^}BtnxNA27q=9Las&DP{{9040|$nN==TImO1i!N zpNO4CR*!mRw$mt(vB4)Wp35(Ck0S@t14AvY{0y^lZ@t)6p#EKSkD#x+y-pSzh(-ZO z84{rGohQ&O;7X?3d~^cCIa;D#L6pKe&$?nUHxjDvjg211Z3F1Rk{D6Fb!HngxIlUK zjAlC>KmukMwwWcz1f5VvwElUgzt&t(Vow*!73bmOt!>35gaqvn&dpaI<{uCEQmGVJ zDpavh!f8RvH_cyw>3-qLzw!aKoWoUTG%gHH>i|cgKdPhjEsMD3@S| zYc2efF1ypL#XoHEd3s3zU75{bcvWa0rr9 zPazm7>Sa9~Ts}S&fXza%Az8MOqm5g$xY1e9g!Oc0+QoL52|{ls&A=Fvnb8QzGGbze zDT^0T+^N9!<_ep51w0O3Ed0QXt?^orcmqK+$D`Vq#KtRbj(9^}djjgR8^m-8)tSR( zCsRSQK|;hA3;ZW};vbA~eKqp0Y5p6pzDf-wlzKPhsbG{}*5UTueXaCLw`=QCkJl{G z%e6|G!`@Zbs_FM6PZ4K@x5VT&o3ms#0O3q1$jrvJN26+$UaOZmos;c)o!)jJV0Bt` z35V7GQqXL-8j?n*gL8m7+l|R?SKtY3cA@x;rm%f*3Iw`FmCBZ1KJeB%?_>*wHKo!T z;cs$HDH8%B6uq5e{O@ntvAjjDR?9{<@BHlRb!}YV2Keex*SZ)qxFs}Nfl(umy;u8Uz{exWK9drtpes`1?gCZ3}TAZCr4?o z5Mm8j7VF^6tEI4vfE^!*^q57ko=g}W)wlqjY^t`d;_{`pAA#L9;rThoHNVK4i|jA zxC(~~3(8SUsmw94G;+JSLm@sFgw6+$)kvIyPVCGcW)GHmt19{$R<&h|DgaOLQt==X z-Xv5JglZl82q7VzyT^0_a1Z!Y;mJxf_tf;soz&X7iO+oR<(K)F=qDB%JRU<9Tq?@_ zufP7xbj}gZrUQ;(-klq=1=5Lt%bRkhZ_0QI#b6GhtF(>m=<@ov7E_^+)0E5PQX!Y! z5{o%=u|(PpB^cn^oXyfupbBKOUQVGaj2i7mhzevu8+64VFJEdHC9GCnrnWif2_S)=G^*Z zHD;3m{!L}zUukV08;^t`lI%K>J}v)ZeZZeJ21A7~gqBP(U&fzIni7zGi{gP4BZ*M$ zU$Z=DOC`dxyfe*uU1M6a-{mtH?G`iO`A$X2Z;hye4r>6_UYpk9^STWNhZ#e#Xm}KT zmatSAvfF*=Uf>wRIcEFUrI@|!npf`=IiMKZ!)C;^7dNe__wGBipn7!fPP%oNT0;a( za2^+N*vZiOmYzN3H+~!JD!cEqiOmBOcw>fLK5))DFFt5PabsZ{9ghqhL`umAqVR07#kx8@4tWg z)kxgy(w0mvyALgc8fJ_l>axw{A;-43P<3!^Nq|ZkU$>LLb{_v1IKq(Qx&zUTB8&|s-cxg) zIARt%$e3J_5d9rLgz~ML_^+9(m2_6B(P0(LsZ)3QaDJJ{at6iAr#)dpT3Yn)FF! z7(w=CGhq@=I2f!tJ#sAFf)~ZLr5~qL2QE9c0SliOsfTB5sD?E@U&oFLZrgx zS?7n@HNkXoyy7j~*ZBX$3F7PI-|nGJ-RL8E15SG);0SGrf-B4&^SUD!C%oAPGl(l5 zp|3n_(i%CbBSkQ`sJ2eTnzNvBl^Fv=mmFRp171B_O{cb6*=pwHII(X0bMx@vINI?F zz)^1RQfqV?M3Hj&^0D#M`~2;oP9V3V9{LpDoayKabwryh^tCGJETr-^x9r;YUfk|; zI1&My@8P65;KU$?!_VIrA6&f&kVv$eE6Wx`1kFWdaut&>Hmi1WI3$(8iv%4ij6v!( z7$_oJL3ZN+%EV@|<};Cy6>PCu1OM$@nt)th&MCnjFZY5q>BYgp(?>>57yiE60Q#++ z+kL(OJAatY=Pg1{Lyn$CqN&tW2TRE(U^nkJK{H|x8QKRnsgp@x4?RlGIZTlsfuKS1 z+8qSc!d{}(2^kX0k6;xT#$tJhxuFKaA`~&C<-?vcpcaX-pF|E z@JD0`hOGFE17a2=xTSe)QcS9vJ|>sDN~UxsnnS9s1pt>^$N%Z1BS+ekmAFm=m(p?e_O+O8Vw$3WjS^EHB9CY% zYm^sUa1#HAGz(EuN>p!7{#AkK4OTV4N^Y~6Nz=%Ih>gK}m7RVhJ2Jke!|x$AW-rin3p&DpujrruEp6SEbV{>APAbs4AzGX#?P^PUL=Q#krhZbHwU(IHHn}!SkcI4FVe(i_gKoYVTOP zwieK-RnFAX{x9Xa3*Tj(yOfvMqzHe?aw(YA;%N?|S~8s*{H#ESldl%KZ@1bK&a@SR zrS!^7q1xiW^9oOAM{6QeaDzu#g7&BpiJRL#*4O$A3Df3@gQUj_+zv>c%H)m2uy2$`V)@9_SCOh&Q%EUgG{+puh$PofIx%&$dYDcQ(rz75 zF=k{1<_S=2!hV?NEfFHIQV+Uuf^{!6RWYAqCMb9{q;o8#!~HzQgQSejpWR`O&K_su zw1Tr_FUOySQnu`&*-E1j^ov28P*9fJ#J4m6!EsBpVZ95zs9-0KCLen?WAN<+(uD>2U@ovX?{B`y>pEPjX{ZC$4(U|J2m7e#w zv}%q^WU4Va^t8aR8a3#2GBd^q;~4iaI`x$MS`^?qoz9`LYHrXgWt=5siAFQE=H@Sc zP%&y@68h(s7PNRi{g3h7a4yl_Zk8Ji#(djQYqhl&)gf&#l(JboRpr3QM*ne~j#of9 zbZ~h19{F!GYQ0hofm;sK6Iz?rUkm!9CN=CwZ?n45*wQMHTA1uEn{5l&pvp0g#%M7( zu^+$Xl}k-*W=c~s08K^z=L73i3sO}0S#^_Fs8=^5;va4Fk#@q*ep0ZwFJhvteFW_J zE|9nxOymx-;zYW08#!SU*|Lf(rJ>kvnNS-Mp797kkEy z9wc+baly|CCW2L;XHg6?&MZr?Ll~1Nqsv~%-T{9nb}VMC2u&0CWITuAG^7SXWpklq zv+z&NI8Qd*Ekyp)$cJL@_4cjNXE1+v}rqmXr2wxmefQ*_W|LhPrd0`Q5#%a5cOWxM3f8k~KP{Z=iN!D?@cF?U`C)$8 zWOM{GU7Ah`%G%A~B|DKY!&^&+Nq8BVL^W$_6-Xo3kclDMQ73I&Zx^lEX2u!j`8gp1 z0O7j{hGfU`$ID*SqhJPN$+BE3mxLIP8B93dfTNd1{2I#zXNpT`CGKYaPd9#kPvGbm&UxSDR;4+{QtYyuEmWxrxF7;b zRB{i-p^`{KDCg6kdtWx2RLW%h=AZp6oy+A?_<}dxQY_w*IhkF!ZZZ2nx16btVUmW` z!@lq67ieoBCfz=JB=a7@ao4?|KrWa7JE(AN&}-G~ zf`ec&mq11n6;3%Ag_uiXL50&!1Vpg47RNSW4MJb6VxNySo7Z+@2O+bvN~7C?NUd?K zvPWwl_)78y7|@>e?DAX-GOm0s3)%L96G1g>*2gtvR}2q3L0N8T^L0iuyFdMDMmL>1 za%A5=aCV(`+HRw6rzMwirJVtX-QU>^_6Bz}?KGBMgI3pdk#I2(g(BNMI~?J7Fye7| zJ?=un8+H1_29vSbK45oJ#hNu2Z{13+0(sYyAn*DINWBIF5sN}@N%llK{wrBqyJiZr zl``EqJG%1+ri!akBcE}EqPPWY4a5hdE^pk z#Oh6*qE2VTH3`qD6M^!3Xqh?Dxxek5x5bD}Lg^h@_ zb#r<G%}=%IC<9+cCKg2 zJ6{I~f-VBLRF*W8@U558hW5@Jn(5;X)(IdOmJJ|y7pD&3HCXBZa2X4w*nmQ#&C*R4 z$hgC~2(vNFHWrXhiTQ!OCSqF!D`Cf$$l`!k$Ay#u{{$XPVt4h8K&uOng$`A$qZVv%Tuu?*V+c232A$40y@{C9`6O5e^K zE~PPrX(EkI-I4T=$+It-XJZ84euxJ?f;w51?B zD(P=gfd;2&30h1p3}8W0!m803R0gG5uQBLV+Wl=riI4`0*(!yS4BUmm+%TqF)Jm>d z+SY5phua)VCHiqns#2MaKw`UNRv$DG+;;cZ6Gp$sjVRpB|1`aL{fYt1fGF&3tGcPD z26x0smt{r+thNo-UZ@2kytd}=`P8Q}ZEer?^_{e6(N!0(*qE}r!0jHh$z;T!z}SjL zmmvBo4oQW<ESWwF7vu3Tw>Qu#bE@x1Ia0@&U8l^g1?KT8+X)|&XMZoP_e_#LN zoKh7pr|XKW!ac_SF{Dvr~f%Mu^A5RkvXw4vJQbH3L)sLf>(Q6J+1Wp^akZqgDnsr3R-EbEGedtT!A5{f*J_jxS4ESFVb$!h4zBKn~kVYq$tmF?88uyU<%Go2!U95 z1=l7}X)>0akFJ=o!m4QMIP}1AVl15Op!GJyH z_D0S~1!7r39a&wn?)VyS@2hKT#}QF^dgJoDj))9cs&X!@Vz)%HNZ<@YC3y;~e= z&Cdgn`qV%_MDhP9dk^@ysxy6f&b`yio!)!zy{XJdqhd*xY}uCFd$+L-7-QoCm|{#1 zodBUZ5C{PiOmCqC5|cs_NZ15Oc9(?ghLEt?&9^<)<^P;JGm^}b@<~5?itfxvr@ZGa z&-1(zgD&}6^!3+2+ANo9n{~YBQO9ZbOzp&4IRJLaNTaKxlA-jy2zm78{p`9M53XUy z#Ix?s?V_Net8n_EVd^e2ZwJ6z_me|kCN~If_upO`mbCqFR9CP9gbECGYS2!P&TPwv zF6;fcuxe?YkW|y%io96UdNmCaCRun^utdf1Y^@vmE)W-?i?96}yuOJzYQK!yui~tp zWPV4p!WX%)Xr&5!$g%2OVIT9`|2}z=Bc}4D27BQi<{IPFrHN2QtJEtx!zpGC|AYBq zgG8n?Ws2ztqIB`R{pYCT5x>rAx7&3UIqXnS9?&`@qa=8-CJgypy(d-4LhBt;H!?); z+>(A|qI@hT=UBVbVXj(SUZ1ZJ2%9cw6NZI8yQZd_gXXIKxywLIGJy4wT|D~0%KSVT zmX7>C@5hZ){;dL=;s5@L>-P7_!NVIqeDkA3_WT$eJJ#gnpw0zWi>f~zDrOyOgW2h} zf9WxWQK|RKyjr^|Jprv|kW5@!bmc^OS!O0kPB8P*;atu^lz{YGd_Lb@w*jN3k2!pS z81=go=)wC_HV2+?7P^@|(DPdgbScH9-Hxu#l%sw|V<|fO6~9h)lMUxX-EAW@<3dq4O7N8h7s?3RK`llzb0DlBWFn}8Hob`cY;4xf$5G4DdINd};y9%4 z8GRSQ)uYE@d;JP)FW+9iR{FGzn!%Z5KVAHc?;x^W-sIV5Z`*c=ln?LNaZthkUG-VB zsUQYZS2F1J*PngdXM!eHghT$b?sxcYj-bU6*%h-Sk^%6JWg0YKVcz54IC%5T2M?MJ zRhrx%a|JIem1-j+BfAqSx67~6sdX-=MU$S>orA`b-Wl)h4CK+5fayjLm(3BoNv}$A zRvW+jS?0ZNzyQSJWx0{ecs@U#89~#?zON0VwIrj|%F%64Z;1a80F|Mz&g-xxG;YrJ zX4HWCQQBnj^52X1uUTL9P@(>g1ruaEzpOY>I$@KdJvWp*bjHpnFE1`zw(RPO3G#q0 zk;{6-=vC`UMLeuZff}*c;@4`qA&Jl7vdIHBSHx-e*zJCB@Az8=2B`h2phwI*s1woC zZ96hm*9kS~D;m4!^Z`?9SpW@=d>L~3-7A1cZ9TDy7`8&Jc>5ZL+qe#mWqDTjqd&Kz+0`Ezow?_q=YLO3Cr`e{UTK01Z+4NvS?0{}>I%0ILRelUZYjr4mcav1&4(I9Xhc(U3?N4uOQgNblLcD=$_k6*dSd z@4F8YUwZQX`{jH0>?g-iRc2*t(A7-FNDdcIu1Z#`)s6W);RIN;WLXEK4*-kK^`h6w z&L*7N<@SEq3=r)uKmTD$;4xFWN@aW!9HIz%3;aDh*7E&_z+ku#E9xPU=&ys2F(q^c zTRXmaAhoBIo-Fj}X$JN5(dp2)(_a;BpNDjwqx8fRejcsDrqFqB{i6VhCd@@JXJsf1 z>Vx_lp^D@M=+qxx9Y$K+8MX%_hgdvOs%@|tP7l`y+@81#gb?~ zA=4?92aOiH_e|Z@AAa~feDS|y{+<8VpWy40Pio8BCs#`>#pP<22WJ}AbS!`<75c;H zlW~__DOO84mCE6XMSXsU63_&=(BXW!)-YvLu?YODSlVsO_cyG7MyoiZ#k$(-aGJ#m zXeopit=?tr&H7lmij_W!? zluZIj?E{vDb`Rbmbd>l4JmqOzNxRj@uJK@fh3p`ZpGwKBVE4Ov$w z-Ef7sko7gPcI8rbQ4f=;6wpbyqr?RLj6p=Ul8s%T$qGDTQD0rjQ`wYgicHC`;d=|9Rm!yCArp?;DHDIwCbBJ2ZYprVT z4SbzE`Q10)ep|yZQ%_B6uPknEe*o>yFWaMNP7Ic}S`#+~+2odtJZgLB(0_v^nU0*AJAJkjfpBNGQ4yw>#{2X*up$xNiv0!mgEFsY9V{sQQD3E1 zD1lX>-%W}{`z`5{)8`P()CGurT&T9Y0)rt($l^oVCa|+?i6s14Xho=95f{1t7=*VR zrE9La>=I*dM*#$4Wf=YEJI%g$7)(uVB~!2-z5LjF3*TS#Hc56qPrv?yKe0~ia+b7! z=jOfM^9iKJtw5zQOwtVv44M2V5hI#c1B)vQIYSQgI6`+cZ_Ep&B+io#u_3^r9oCq~ z?gjM_W>C@oLO23ccy2eT-@eP6vr}UuONQr8zx8NPVhYg=C0-mP|N2QDnLm z8b}djUS0o%E%-9==aZuuh**O^Gc?3RbCrB1gfx@FS3@^GlhYPK`A}n28;C-#cO;Wj zccJrq*hHzQR*T!iN~Hl`&=ug6s3mei+LN4WTR$xH6y;!12B0>v2Rd97!EzT?)r+E6 zM6Zjw8_B1>NnU@BoM2xdUw?^tKa@-+JzdGc}Q#cz<8A0<~_PA((%OHVT$ zvr8G2i42N#WOXc>RAp z*IcFLYs$i=_&&%%PIu}ix5S!6ejNS^vO24X`IpEPQnfq~a5&5$@`Fq-3)uV`c%LYN zjD#gh4F|z2WJAPgSXDBSGy+(}7)YDQkGiJ< zM1IfI8QqMpcIt!Asis{XcjWRE+AY@@Jcb~%gP(i9{@prxy~e*|dasLrnOwxznP0Wp z`$6Q47|F2whWT}9=%8P;Dc}s*tWG27&tmk-f__FOin7RjwaMW&Ln;nZ?N0Fb@q1DJ ze!#AAIqXhJo4*fuoZKD^INXu2t8Dqx-x%+xJp))~;`=Cx`o^ z3$DMl>nCCF54z5%*WX?waP>K8#odSX8AhDu6$QcCObYSZYOnzh310MF(Dd2XSaST{ z0k(2CDTy6!8zW-9XvSnx<1awxl~#B5G{ED)kq4P?zd#;kS1%%itb~ve7Yf53qCuYo zaiG~hHxnZvae|<&vtSdat)kGAv32S-UEJwX98N?bCKGZ#&8Vu49&htY+AFomMQA^w zI?O;7P>a^A`n7*RpP6mr{`&g;n?Hzs?8O^zq#d^MH=v7!y?pfO3FfSSzu`Ffcm9*F zK~3)H0}nhvB>Y>~7*fTcMyZw*t0hx3GSC>j_jFBN-DIOcWN1Yb3kE;$i%D~(6cv_j+?yq9KL3*x^3y+Q zPfylIReKcuKBYv?%KEZB`Lla^$hv>|msGjDuA^g}@ISdLqk{}IKo~e<0#A9XT0Fk(Y$0?*7DW?9jB=*p)iBxH_L^?Sk4^s zR{RKMon{h?8s4_|2G1=@--}x1rbI531MpC==y*{t5RP}pjorZWYgMw?`ee9t}A4NLCbk~j@dMMgS zE%XaMBSCL>DgyiTaO{Q8sDO|o;a#t5-+yavVDJ?K5So5h9%#MFf6qAJ){%Pvx zFl3U3M2@~>R&9v+&v*$wa3fuPIvxsG6K0pk^};tT9=j_6g?aze)pQ6DL+0BXCzM*H z!AX66ExU0&X9M0(>(nC9{JYPye?RohU$ho{2~J~;FCG+f;@z-!Z?SDVR~1dd)7#d{ zOi{+Y<%=n5!_=ZGmoEa1Y}!pzZ&$pQ8-s6h1gyz|LGFVj7L4iGI?^dK+i znY6fC%pzaGTne@&ab3n7+D{H%Kx8Zcs3;_g$4O6(bWA4*PFpDLITVPGvjRE2LrBnGPISc>g@x0K@0$Tb({$3{@~ zygqVtB6{z=`xi#;yc7766mS4PXz^46q6GTFoC!7T%LMhLe-Kq0$){g^_DS|3xLgl@ z1vt?Au4S&gfm|St2Elav<`vA&uaf)4k$V6)PQ+&M6+X|6Z#hUfVVWgf!QG)eCF+|A zn|t~YYHd~_DvN$>DIl;GBIq2* z{AB97|Ky!ta~6dUZj|ie0I}&6_9U z{#@2|(;xrXXVzPEDXktlcwb`9yd~ox#GLWF=JyxCAW(P0DU=!cAC$0i)Lp3Ph>e6* zbSTk9qf4jf{?t(XG?kfd1?7U+{m{w*|zX^bI7Bo<@xY1Ck0K?=-bDWfg04!}*HRw7lI!+^wp=gIH#pWaFa_jlad zdF03uFu*|m5}J6w21lxuPVSbu6C0?6<0-fuJsBRA)c{k#5P&{i7dsWi^*VKTe6v<58)ISmuft%_alt zK;|%{33U4(#@p>j&$|WtgAy=FMamNlKqxkw#1$yR&EVA-wGw?iG*S$yvo(9DFSu*@MnJa#h zjICmJ?_$CiqY88>IdB+?Fjq^-Bt>~8SCm|U(0cP@xZv2mH&{cRf831TU#oU(QfrYFVc1|qt~VOjn01`oAeIKQ z+Ca3rchia$5V`Xgj{txPAZ?WaeneXJ!9lWV8PummadP8RP7}sdDGM_Cm81wlIN{vn_LvQe$p402|jf=IJ zsb}UEkLHhNuP)f5p(v!2mC8uI8cO6d304Lv&(#xaOM~a;=SvhyR&wTiNT=f_KQ#1V z7rw}*sM*Fj@S7R!zmDr2TDL51MV0E~yEgz543sj~;#I=ur{6s`#N* z`!o1`+7^>621Eqyt=JD9*%qiN(rEW45wRR$&OuFbu$L?yA$>#St}hbwSiFU~hjv>`IxMU~!Kl186RT@+=%+(n z!4e{S0~01JI{`deJsmkZJ30+U=^_;tBr?41)d1(OY!&PvHGWwlcmP;nkW-ny91n#! zx4EkRhWG%#5;le)j>7(kzwSPydzHH7Bzar%rnN87uRHufZ_FX4Nw|3E+^{Ue){CAm!8M}&bN7gT1AGduNr#=HKSg}^G2Lwf}@m*~3 zClhGy35{IDrtY8y>Y&Dm#UEgvMVoP_g;Hw&7}tYRo3T5*{8ZDRwwk6gtNwLyE(gUc zx~`(1J^-DKx{x~#09Sf0bUCj@&g3m9A-^m7h3Es(uSFjbPBd}iKb|A16XZFfX{0|P zzxyru)jyMuu3*mp^*&S@|KS7j{x8T+-z7gL^WI@T{3r68Uy|eG`Y$lyAYQ>e`Fqls z4VtIx=WjVatHcZ;#1_uRi!S0=4#@dYQ>7)-PNuM2@K{)Jbmd6lEn1<;FI-xcH5VTk zCa_-3m;xSZL=pu7mYTh05^>fCS!GRYNZ(1;6r*jf$p7;Rc&)XWjHHGZRvDrE|7&8`@QP_jVFf&}O z8Q?4$)d__v6jP%DmPAu~fJ7Z(Vv}=XJp{0W3I*hq)2>j!rITm?=l~-^i^U_C>h(&! zBPa($vcQ=oT5?H5sWYmQF0`wk+8fk+a&olG!L=x>+kA`_ok4s) zJxr`6Oyw4X4yV^;hF%li(PGvD`lA#-8PR}PB1`Jk`Z>qG{lSaJjvagO@$@7an)(JK zh~)0-z@TrPV|1WTde5#Ycbd}cFw|| zF!n56RSM`-=$12)T}L`!`?fr4ae4gkoDD>*vuIpp)K0YKOw=llXl*hE+KWbmN$v8w z!zPPCEyaC&SXEDHmH5!S#uAEpHOV@PK@z>u>W>)ECtj&Hs8f>~tDmz0cEU<)uYFtM zwOV{Glf^H-3K|w#3lr0zOx5QTOJoY28;X9$xW)w4dX)C*`=et$CkYt6PK{Y@^H~C9 zSvA5=>{CKs#{mAh;(k>uvQK3#-58V@SvL_<6stO`$k4x zj6$xAjWm!VmX~eSf&PLsGT57v%WhYWj*iax@sTtAYDj_AH*UP)f;~HmI-OdXy6O5o znKkPQNV?I#PYeyNZy=UU;jgQsHoZZldWL4Q;WLSn)U}!Yryze&DwmpW2mUOXC17iSBAe7f}7Mh7S=(HNv z1X#hXl{X)Fekm4+YR4;g{-T1uYEA$ESg9NAm|e1WFT7__wy}6@e4zl>lf+!2$R&4xOxhyq#PJ1gj% z7%MJYvL$+G^^V^9vL$C%HjR&!aE`x49bgM%C$fX#dtV zjzXwfAD>Lc{Z(~7KjKP80iXdOd<>=#?mhg zPunYQt{y>=A0ri|gK7~LpP=^B+=9aJVZ=~^!b+t@O58SINUx{wH@zd9uWcSHcnRI6 z>~a2nsESH}S@9LrpDIJDLV?i3W=EP%oOw-2n5}vd+O{2G`Tf3gz;!U z$DCWIpyFzFv05wFl58~PF#5u2wMHjTrOReel!-Oqi9l({9@TjqIuPw3!a$hwJh8Y1 zlovU-X3M4;r?RF3*@v&Wu@TUy6b6${FR|K225-C3TQ2{%biup@9rE&m(GIlLJg$f= zU$*=g*PjpVav4Wr^})$VvXsQO!d|K+2l~544Gy~p^&OMb;&XC=;Yt+1WemJjv>05e z=h!TIvU`E*U5*a9M`l^M=7?cHW|=wR5lt?&2eN%TYd~j;z)cW$bBOVObG0|0q>}&} zP!yh<{U!ndl!WuzfX}KiD7CD`>EHkZB7e%LJON+T>~fh*Xk+lwp!v*o&!HQE?7Xde z>_fZvo}n~qb(bDKzZd9ff({fP$4rT6$Ptg)YYfl;P`%XJba|J55+egRt?HFC+>v7Isa9%DchI>;m74j7*B<3?QRw}PL%Wg4ojV@0C zH5A#mJh4O+wJU{g=ceslD5%H+iL~1mFu{>b=aZpv`J;E=lShSIot<2L=Gql&y3n0c z*>TCa!y&)lh1w0ZOzy+WI&cRKddZ0z1$Gj!AjOyp_P-@cYk3T726njWZs&NkuI71E!FD4wnkT|B5Qipd9gg&7h=dWC^S zKnGF>DVMY+t664LXf<${&@@}Z4@C8Lk53KmxEh_^bc~h}-<1&`+;Bq8X{DF1+#K)S zwBkbaYt>wE*8V(FB~q;(UQD<6>`hN|(7!mcc1I|B!-cD$b)dR#-yx?AKV^QePCzM= z^F|^lPspW4S2AOzEkPN(FJPCz%izxftSMqe%q)|+d{!^I3>q!bNXktss&aEO>S*6NhWIpaGw&7V`{5JyBNR%|!HH|hqCK|=P(AKtY-#-TV8oilI4;#CW+ zdIP8OjxSoV8WQN3uL9=l$Cxkb;}%7OU^ZSYl0Q`>zA%%_f5zj*APR<`x`EV;u(K5i z=zP#oZkqY_>{!}cIB|J#fgI5@=~^N)8#jzQmnjX|B(R{98djI7KWFrgZ#{D$?h8H zTuddmSkpYFlTMQ-l9FoWoDAo*g`V+%C;1^iU`iT2ZfKc-Qh{^&uy$<0%A^F?!2HD6 zT)<2d!DOSaNDP3QWNHomPVzq>nqmsob{Gbt(^;^JEQYVSZ@uQCPCfd}jP1SncKjZn zNS6*xl;pX|t`X?fKdFeWUb}SGDL$|`nkXgZI-vH$rS8;VUwznQb2@P5X#HRlX@bMu z3AIe{<5^Mc)0fcqK7~EkkIaGMDPRK!8Npss=chUHEq6#@>|t`6hdZ66X=au%1%-Ce zr_^+Y2x^Epr>AXbme5TqB*}&MrG3+mB(z#%2UzP2&IA9*fOj z^BL?Rx5r59ZD_V>vmtrtrX7M>zR&&qqIDa$4{-{O-Zgn(f2apz%{pSMYRkiR@??!U zAnh5O8#iV~N0Mk~@q|3Qe&vyuc5EF(hbe_2GE}UDUBRTu8O!90k%3}Q%9{-#Am%&) zuO~3PD5#Pv`LE_*R;i6L!dSx&qd^hybSBeb`H<->09esut!Z3H9eR@2>9pDB4Kc`rj34j@APwrzUS=MNrc=4 z#vk=NS+)IB;UO8$>)au)*r+rpE$9{uc@l>Fsi+KwgP@#gbq=?S(?iwum2UY(J6}}- z-~8YiJ5#Z9cOTNIINb#oTpT9|q0sn?`4<0}6)ujkm|41fgG#B8xUF`b*B)?m&mA3t z-k0i^k3V(}zlBs2$y8F0?5ai4EepooF{{C3vPWIsD4B2a#S2b&9}1Zz8p1CPjX$?9 zmv=BgEh!zbD6(fel|MbSHI6RWn&RT6=dakZv1)`Z3UA+amcpSn!4NA+rvr|)(mGVD zp-C7THA85^?~eK`dc91=sSL^W>#i{+1L&O{H~F;kgwz&x#PAC$+%dP;CY(8Iq093c z8v=Ttc5BFpYG54&8+IgC)pLlFl_yX;mjYZNX2I(a5Ee}@$tWOUi?a~07;NmA)}Emw z--;AUv>GZCP8YiDDWFy&xCp`~z@xR@ch=vf;0MN5LXtzG9vRPnVrJ=k4?p~kQ$J3^mT@(OR08Pp#dTovremf|B4anW zy)LY0xhqsKQA6!;2hsY7bwsotyB?eY2GJR-tWMR*V-R&=<$R)ECzp2-_8i&bk;#&* zuxO}`YVj-b$eK0FrtNBUaCAv1kwvF@oy3`_#XB1vqh_1S$uy%Q^l}>RNdOTD1d#vJ z*AbIO5E)U7M;-WWjA1BFl0Kw7F@Vunm~pWQ67|;~^_861zSPy+7<@Qoc_0KAq(NOJ! zm;O&VlYU>4)5B3;V%L< zW&GzqC(GG|BMVXllpB&CTR^)`J||ss>Cwg4Zdz55pr1^2< z^r1PS4UsBPl3u$ZTJP(EpcvM29{GWvvp!&KHlPX(Z<3bWgndelqTrHXq_qsHvX)*F z7EGovXu^*qbO@mR+P^BR0EtI4Q}Mj@1Eb%UX|6#99<+7a~^p`NcC3dBOb4k+uG_HH0?AU9 z)nRjl1_o+rm&R!gD~C32?-$D~!E~+O4;HJrFy8G48QEm5oCz?$;!WxNvGJTNGuSht zkSTvIkFHs}_?2Vl)x`K4mBm!8u8iALLA8dHq)NqdZMcvK`4b@q3r%PCJ6uM6Eie#L zsnj$F>HqXD*ls^&*@zs(IPA7fsU~o@M93*ii5`G47JA1lD{JkuR&)#9ePKJnKf#vL z`>~<^jP0gf!`qWzDkH@++mh4F8sjBSXc1n)*XrbcehqQf`G@%Tb2utws&H(1wiNa| zJfT1&QjEmh;1gT|F0IaO4VdEqvx&tICxNZdb}1<#8##kt{D{0*IdxC9`hy&JtP07- z{b!$X)3Ws=@m#ey5b}9!DPJ(0%nlFtRX~KZ#`JoXvAeHUM+o+Wq`G2bN?uqt)PeSz zG@g>6H~XW|9jO6VTSYXr0Jc2Pu&r8144^S07pl-QkRu!<=1wPLq%~@obAb*J9t z3?tPclLoHfzcODu0zoOU;=%2ZixA8IJ`i{c`9)+HFOzQ@n1`Hf(9q$TSKG9HpzP_; zPcGfMMk-T{IHK;LH)w>jhwRyIw=^G`ZcZ-MH|lLVB0JvS$3e8Obn7$tH}y>Em^jN>2C;lla{A2GcbawrrHNWW|5A` zjJ=@`THh_Z(DD^1vHUarr^_sk*D~+}EY97>3WVd#J&;nAVKi43aloN{+14^NH|;!kqe=-*xP-)%G*Hq(eiE zf-y0#QAG{)Nr`DuaryX*yN^!hqy7EENOwnb!Nzbl)Q>iDsYIBSDbOV`9uCJx7lhG; zf;)AB^-k@|aT~A4suJk@ z=qh$0irNK0VC79Oqgkh>{uTc4rnu$lqess-aQjcMK?}ko(OG^7u4(0c{!(VQm&Kb+ z+h(YAL0$KIQ~x-H+5-E2{dQR~o5~~n_IN?GfXse8gC3n*B$9Uu7WQ(c2ZP z_YCwg2FMHY0dPTxm@^p762@);#mkk-1~$kSEtt$AI4q5#Hu0mS7Av01f1Kxk zU#${T{$o0>QLOuCvF-!l<7^k%8alTZ61!#*<8v`c@QH=7q)Q%&srE{2k0u3kx1m4& znVQ94@UUkOy>Nfpox$iv>EeEt-yLx%QSfne+2{1+FaPtCn_Aq}ubNC0r>2dV(ANDbp0sbUexoPTSN0##jtTMfvQ<{BHPM6B=?Lq@QW&o+z zw`v+VXG4rq^>on_^0_*^kr4CTqzqbxtb+fDzdso!%g(sx`&$hJmh;RSR^mg{+sDLgjPB*I(WDLVF%NW4Zg+=Kr>56NGyX`mpiv!4v z@}19E=kzXCBI{ssA>*BlM`N{~Du>QEht_TB3cU%g9`_di_un?)4WR+;)F2UXMvsvM z-nL;Y7t~5`9>py-QMQ<;mUqa#KASM|RTp_tMwh8i@Pp(wrA#4##CQw60 z6Dtc`7pMJ@Az1Hm3Nz*&=*i0heRR5pMrKWyFI>qK!w`!17W;l}x!3Xzp#p!m(qyT!RoK7}i*m!V9 zXTlQk#Q8(ymxjD8YFDUks;t_(Gm?uAk4*3{klul@S{7X>)^6KVxt3L`80nPJnn(u# zY>+AK@rXw()kz$=tRLyb*P_A>WOZDdUS zd}cjVXAP+Ps0`?=i;^=#t|?G*X`fOf*FKh~IXy+4GaK$qt8G?Q(P*?W-x(Jp!K~KB z-2SPz`z4c*Np!JHyR7<7@1j$fHpXUk*8sanx=i4fkiLdMGx!&~Kqd#+!*a z1bAxmtcSZbbLRUg#jc4%ZCejZ%LH57t5wLX&2k$)KN-@xnmQVv?|+ooH($U1ex#M{ zU0<;hN9XzHKhE6BPkn{ShkI&8&ZOsZ`AP&a+wo$e(w|l6G{&w*VQPIE=2)*bB0Vpc zF@R%kZ8|1EEkL|b>GZe^Hn+zLaR7NR98oJFIq9<4Ayt5GwMG@%0a3SP;EmGLLgxRc z&rpX!`m@p-wAGjQG~iX^5CE9DF_xKo0i(LrK2*7!2~bW47UYRo{nDI-l9OksP`Zl%tEtd3!-4YM-0NX$^VdK#W=_ z*%9Bu6S8bj)m@}D>AEQTX>x8Bz@MuDzG*kgA zLk5Rkm6j2SHXK`#DTjh~M9QH^J|6XQa(Qo@hTRT>O>MLRTudg*?o6RjGFvS=tJfdt znm2D*WbN2Uz0%#=n;EZFI-&ueJN8Efw3(e`**`-Z4b1{VE77FA!M_OJG+vrX zGM4q#_7xarx>IJ7AMGay%v$p}Z(m9;oAwoO+2=eE4wZBH_lU$fw){*iNX0qJM^oh3 z)Gj7oic|v?PU)w}GPaiHOu_iZm6xIurLt>iIPD3AL1K{@B7Seo1Pyv<$Cx|A@?v1kh5#e$kqPT{IuHB2*l5M66);k=2lK6|2ynMvne8N`la`z1K)P1q>hc z^a8?ZsrBitH_PH-ie~9f3$8BGJoH(dT-dTr>cR9Zwx<@eSuU~;w=JlE!!9*BM=M~9#4pd1ogJv9l!~viZx!gL~Ii~AY zv^FN5EKAsnE`bnBL#2^vlKz0j0XaOhD^=H$#ao#FIQ7>28uPoUE0}}Jr9+EW?ibz zmkA)5gUgxmGZ`c!2rDIs<9D7#HnIE3wiV3$F(K2_-e|zBqxS~Q%;^78Qjt!Fr5)MP z@Rx>fvRSqi_)wbXpjiqlF2);D+7R{OjCd|e6}}+8Vx|U^vg+zMcJ}P4R`*n*t}Pz#mSX5S?7WUDUih;I`taMt*_Vp{@BRK=AXDx z*Hbz9gcpZjugTQOe4Km5>{M&8+B7dydnXso!~8rh;CdYJ*{GIe7wW7Vv2&~)B~s}k zHS`2#JBwuX0@{Y9T%DDHs|p8AdsSoL1sgRJ!_gt8Hmc=^!S+RHorSt^Vf<@%-hu7I zcmt$P)BDl(+X>!8^xc%k?Qp4q7?0{kit3oqdu~PXh+8#^W zA@%EBH}GrfjBjc)>*jC3>E$i)w=-)EZhg3#FzUPIc=aUGb)5@WbeT4rQ`sZ{916KP zlk)<{ERj3&S(nU~E800D$PZ$%goz~5agQ;TiG`IVYnc3D?%e#>zrM9lC;-UHi0AXq z78J;_n>5>VDA_6vdXv;*?C3Z7KqG@qa=;({E&SmQ-~cv)i}Ii--3UTsW))hYts#rn zkp&>FW3>;6J4Iyu>gDX<(ur|)w3+r1(#9CXSyhep@X%Y~WS{*+YrKUcW+slLndjO0 z9wF}o4;ytBA>%QNy-K5RIs-x;_0PRC{Sr?O#?;kS*Fj|7 z>U6*_a@cbtV;veK&7{4<1If(T;G|roRP`=elnp1MF8;rdYwffnh(Sdbegv+uxA5`D zufNXoeWFi4eeJc6PJJhe$yQfk99bP9Tk1l>FFmQ&C^eaA)MxPe{VJtK;Yy~3BnjG^ zc&spv5zcGDyCF$Jm>;6ms!j?flG@xoG#o}HU1hY}ZGLwc1s))AP+OB*5f4XE(A4R5 z8oAf&4;FKA8ycc{Y(b})Ki&&JgOP5^kLE`67hXtj$e3h&Y&^}S7uFjZnew}e@Vb>N zet!LV{g5}&qLsw@n;)%iCxjGQwtS78UdYK9?$oC7V!P zT!{%o3`IGYveR~LJAQ3Oxu4@?2+=RwId$N7v~b8jN`@gRDgVZO&e25+bD4A~)<>Ql znEGFUfHdU9O*i%PZ$sx2nR5PNDEC6;yVJ?f-H|Z>udLFWRpxk%v&fbA^#GZ`ngP<4 zeWy#KraQ|Xv0RC64^=yu)^gWiwUZHNdI$ZQc)2gZvMfpTcI8Z&;XaE= z?e3`wK0^=2{uSUjyMVJAhc?tEQKI3opkp=qRugSe1Lh%Y9x~@5bm$`;q{Oyk);6Rw zC~!=h=~Q7y&f>9PlhOgE-=ML8?=Qr#*m|gq3D?q}2>wCSPSP5N;M>nU$zFfzS7g`i z5b1K4zyFC;YtYmbOcbn5ITv)ITqPBkePNSXqY_VjRmF&TiIQ2)uO>16U9xwoRFQHz zT^}G$H=~z~9F|wlA1(vOQB=k_N+Xc3dCJ8 zwOne^nvh=zMCbIanqQnKtSl^>x?2?~*MeNUTn{LHnTk*2DWOXQ$vJZYRV3rB>ui~1 zKpTrEVE;_ui@wJefn^(kQpZWrk3{OH-?)ifxraK@;5q&Ojxw9^zNKY<~&;6yv! z*zQQ9;DzSG=${2%2*TEb9nE}tYEp?EQU-g|6^ghN5M1a;#MNRnsYW-@utvzI+x-SV zdQKsS$|y_baJ=g8)8_#QvX&sv$XVcapjnMfzR%PV8-QfCd@wrTp6|5v&2d}R3cw51 z*iuHfSFNj}JBPZmhx=~Y$PiPmvoqU|SXU01wqIwly1V-N%YY%NNukkS$q$ZTUjf9N+sTVXhkKbuGFuq4ghUuICsQDprX28+udNkaKE4SAzV2pn#KQTI2`XAWND`m&^b{ zA3;^en$-EdC_?~;_O%^yoaOQxi$-&xkV#nb!ODI2NU*LAb8=|JQ(D2_-kl@KlPAfo z08CC6<=I7(fS;L_@IO+x;R|yP7e3>&ekY^ zsa;+Ex(hf<>W508Df|%fBw6^N3k5&vddy8=K_S8_b0j7f?og57z6=xZC0Vguibl35 zY0jj&U`c0eaC?8^JZ#^k156d8|I&5SGg16ZeFA<_c*bDkEt(ag_ItN)>1V(`MN90< zZ(?%n_2XamcGdbgP9rbnvhKP)-&vF+%aj`&w!OsXP8eCn*8S)sk!oijPQwsDmPUlvO z;rXf#=LWlL!X?pMHul|bL!iejMI0$bF`&TT#)XnGGioOiiQgG?U{{BA&aR5X;7CUN zczr?o{H7%;08Vw5@qsN1=Ph(UD z4zh9=3ZDzdiIF1}q6Qor{WVyf28|uC1E;qj-GdZnM9)x62#eh&0nh{ha{(9B4C$&k zKxfipy$tMsb2~LLCUlotF@H3z*3R`u%@T8%zQs(sxhiA@#-c>rziYP42BtdW3dLiYxr2j#6NHoOK?9fwzdmH){B%cNH?ASH5+ z1;3fZq_uEBSsPMEN@l;?AE5hAB^rSq?yGDb`>v@DS4E%SUhKh@sFIu|8Uhoc-dXmE zU2Jc6H6V86;m3(>;$k)l93F$#0#0HTcaaQjG_bjcNpz5ucuSb^*RW|}I@|HPfUu>b z-kgi}erZ*pry~)nnb7`6H4&mNB!)d*f+?(!JZdW9T#AWxSDB(1^Tnc1XmjiZ zCv|4vg~Mv*VS65E=6BY2ysbh&=Rh`N_bknUN0oNE&NVB%hw)<{@B!)MkN%E+ZOw6RpQU2;Iuu%&{A4!} z>!gnr|EyDq{0P*clt0UB;Z@a8Fko&x1Di^su_p^In_uVTFs5q#ip2|yKp?A(UayBw z$10ohTMMgKufA^U*4s91`nf4wtvNi-?!2ABHDYIHAteb`%3-;qS`15**Dn6|{cj9ALLH0-oKu9f-{cP0ATw5_1nTwq17c;4erVo>Jc}P@)}g^ z(6%MrGs6F=xTAQ^*`=*24&ZKy)aVC`T*mPoqdm0eXBt?B_hGxxJxt_>&6@yvZ#&MR zyG6Q&axz8kB1bME=L&IlGrc98Cv=+VRLtbIKCA366z>80IDOXWWX+z%>0(Q?Ng~h^ zx)5eGo2|{ap_4CwvQ8&_x7PxFP4R>LH1^@IR^a)2PNK7bMCVGYOI`EfyCd%7^sZ3I zoh%e9U?HduY}`@!kB4LsU$v)ksIiV@!m070dg5XZ#7$nCC*g3q_J4#kj6p#(2v!wg zpLj?&e`vD-OKJJQpxZmzJBH=KtsNcbK0IQbhE)930zETV|`i31ggXHCzfJw%b|<QfOcUcLVMuwUb5k5~Ldru6h*mj=~Yumi(FR^G}X0AO16Z0hGBOf~j&)n1TzyJI8bIC=Edv%_!IRhQN z>Hgkows&YC_2`?Y_;1}pHeLTv!~hCVT<7r;YuW%gjf{n}GkX=w2N8AUCu;pFSqq8y z-c1MV0@*y>F}yI4Oxu9v5qr}4G=+7oWssBbnZYy<4tJ&za&2D(h7e#idn%*+TfK9~ z+&Z7HUhC(7O;SArz420Tu&Ht zfy_$xy?Dj7UFGr@_!DGde&fcQSFZeRM+dV;Ix^holBb929oQ$|2mF5Z(w|;?RxY0J z$=1W^6oM^KVrKrJD zr$Z4EU}MCWK%bKoab*~hjX1y=0*!!8lBl1!#dcywXb9^?m4t*5Z!*sHpK+^mZ>1qV)Gejn+r zx9emGT47u00yWN1b7#N-#%5-I+HH|*$T%?om-7bvb#A$ag!Zgg7re?aL?H>qE zBi$%7A<@h|W`EsCfucSSB@K*%`>mjRE>siH2BOGOQ#Y#?h2WQ%cIv{b@8OGQ4+^9Sf_nDrg4C#1^7JJ1g<%JhCLwp7zrc zhAl{du;YX(b{T5X#F3p_uA6qwmzR zVeg`mH4rY+Zd|ayPsAIZIe0!HPwbcM;V&%_i9`*El$d}3xJ`&I%BlH)Ehuw|nBD1( zc+hlF8HlIC$b!32QNT%PkLbcaJxg!|{-j3%U47}Q9C%ab`xZd18|_K3 zxEvppmyOR2LF_}LiOrk8Vr=0^rNUwzbTw+(q#FzFE_Khn*1DL9@=9b zqye<`w36NQL{a}^`oZ+k*2HGPFw^%bmf1E!3sa8}~S~j4c>|lyqmgn61@g9d@tZ5&syBATf^H@8LDJV~ez>YZ_P>;++15pHXGUB9Se6ap52bu~2HNk!{K@bI00C5nKWiLBJdITLl zldH=Y3x+LWLnN@v!zic+;|V6lPZH^9D`G z8u=r!?8xAp|Hs;Q07zDq>Grv|a*nrh&N-**8DgmDWMqa+NsfUK&1S)cbWZVZ zhm0-75H_!rXo-ym z1p+Rn^R$bgG1QaL7ZhZNPA!3OOIue^m_6nIR|(p4Oe)ycs=ztr_E;@Zs8WT~DZ3gB zD<-R!({mta3>Zyjbnmg}@8XZ(>N|ib><-DESO|sm*_ZOyTRPqdf>6tpfmGj_}hp zv(u?<=v^N2_1E<-ry87|_OjOFHAVS0^Xc~oP@j}`3siJ6~=C&q(d zyHS~nvnwLn8gtLmrG7~k+jr8+w=X)bjlP7TQfZDkq9HD8OQk%mk@ijNxMfNUvx zMUe4!KsdrtF0eB#E$)cp&ge&UKZT+IU9SNm&>3NQsG4(Uvo0L$of|&5R;57K)yEd_ z0pcRh8^pp{v+xsn{tM{ks4WQx@<^bj^~p%Y`#{p7GHO3ba{P7V0RI}cPSw+Op2_L-foUly!xr?zUayT1;F2v4x$4ab?E8}+D8 z$W)fz70aRwUOF0!#fJSxm$kI9a%|(S$~E?|HQmZsU1kc9M-aMvW;QKRqeZRIC=9uD zy_O9_m)fY;*%R?h48^IkGZBnr*Q^?E4h|QyqeE$4=}fiy-2O$Ban%UlPu3Up*NP7~f@xFj~uMT8l8>pMhdz$Thf!IqJ@t&wKmVTxU z{9BEIrY?fLGKocqRWi`WD9uEVvO8%tL`70zH)Au;5#C;T8vl1yPdxGb|N36K z)tXWRj5N?}Le71JFqTk|)xo9=Lz${_78_fw z$;49@W6a$!szHoYh}7+L7R~Jscsz{6>DSw}E|dg?y2cmh(4vg&E!*>> z>&`FBHA+o#WOBxv^wljIsgjL`tGQOYIc|11orpX!{BE*pEXL^Iuv;9ir04McsPE>` z<1e6RvJX|gN9j(F5FIE$B!gw9aMp3mjAZ*NQrbpxLu5G#PLpV7N*g;pg2PdGLn(e2 zJDa}!3p=;_-kYrgs8l!+A&|aUgblJST}&y^s)+Jq_~N?3AYfJDjEa6=nZ_xU$S-Y*0*f4vVRHad`*mg?j z$*fB00M9)CmF8YzbLSzOH`DC6*YOnRx@?6a8d zv|&xSk5!km$nE6DV2G=(&L(w+ggsMQx4c&LYE4jk$ySz;D=rBIaLB?8FG3y4T`f0_ zG5|e-)ym98MFViG-iygxZq#PfLW@o3Z09S^m~5BJp|+^?PFGt#J3N(@XWG?i&>wtN znc28!=9}kls;RA+bgGUiCX1R5I@*HCa&4#)cSa&khLxDy9tY|?n^xrz574th1-_xD z!7tn8t+4_}PP?I7(0w}%6Q%l$lbCHpuOw=4`)Mf~CQSv*9c*&9ngul=oCWl^h!DeL zg~ellu5~Ry4{I9A3%}u(5AAQl{BYMoib5!fMF{RztO0WADO6_LVmZ_pwpw*W^_oTkF=yjV%FL; zP=0>49{?j(Z?)*83e^i`$dH?HcKiLT{>UrK%8VPmO)$kc|B`$ybLy$j>&;d@i=u(H zIXLC>n@~@AdyCV=0+EMejoR)kn$=+CO$fkp#XOw zg$clMDcC+zYJwHCpVTUhUMqo|nOep$N_6NJ*Tp*iwxbVS>H;deOClV??^`2l2iHTv z%bl~ibGfj)g=P8c-JuhoefHTS{7bE8`^mrYJFiqlQ^T~CHj>K8?*OdHpmSOhfNwK? z2gX-48vY|KBFALFpZOaWx;!S2!6t+L;GG{bZ29Ga%kQ`JIUv0D*5i-={7YXVjw6rb z2&bu20!X7Rmr(_s*s_KH=i`pMar<`uE`K@^vp`Ho%Oz57tXnSWDU{4mW&_qH5oL%{Qx`I>acH(Zfn3| z3r#dYDuhOj4Drytz=Fg&dCe*?``p@-Zu@Hq#=Q*F%ox{1QlplVo50=02uV#RpZTzK z2Iv}LA7Ph>E7AQ;@Os@}I(MPINk0Xrh}9831<$!?6n}uw+vz33#of)?{l55=Tu6Xv zAq4r(Yvj5X|7&8!*W*W?xZYi>^-<8iB9sVuHhD*f2ed$lET5coZ*mS!?gm^-FWoUd z=~{-VLVegbh%ATXtwCqP>R|cf0HsutGv0d&G~d9bcb1)OKqibKmTYL4#!OL6=$QS1 zfC5wpKGqGyjjIR$968{Mp$TDh+@{lKASSD`kFWWJ$!s$IM%G%js;(-mNKb); zNb#C9aq#S!w=Ue-qA^su(wue$!!E=~N_QsdZM55KEgqkhCQD9-U!Rr;p#%SBDUzkG@BJqLD<8> zkw}eW>2G*?=4-DLqo>3l1&#Z)6dIsgwkZp1hrzxh-JC6hO?1UMYVx-PcHw z_55$Exq{CG>Ctp(dURy_>mz)cyuqjUM6|)68$doKAS^~;xxQ4^19EN9m<#)vG^Y3KjAWIiM}}bOwsGdc8jbfhrcKd@5*h zr?Ua%+Hzku?RU6RnS>IR^k_UG# zR&^em0&D~Ju+UoSKEeBxJ?UzTo`GH!>ReSZhUkQ=Fao~FyV!)4Us3>}kD`Aiy{pox zSWy5nT1}mTRXRK(M`>Caaib#Wu)1R2fQQq-gInx)912#E0!Fz|uKFA=J@(wo_Ja%B zlG=Ikp-uf#M6|(B!H9NYEf8R?@g`$2(ETagAwTD>HzJaNF9($dQwbFicFN)U3OQ2X z%Y^6u@DXb$lu&~Y2+RnMV4_xUp}5FqDiyoMSOW5%nY6mP)vZW9Ffazxj#%CL!TEcj zbPpzwRI%2yJ2_j%67c#)r}~aZ^8+-h24Bh$9j~NO@wj`KQEO~~6`H~Uy?>i z!HZ5mBMxp5MdjeZn=EM2IDlBwfI-z>OH^uB)?>&-{b#u`DXN8tkjY#n=h~sycJYP{ zuflfXF~skvV;r@Jrt_8 zeNxW@J&CqwEIyRg5nr$!H$q*Bm}CFVv38j2e3nh~!Fl7AiztmMrbiD zx}3_$mO?j^C;IuXk*4^?pDm2N>kTGlXYBn1aqK-FpT=alIv(^Hoo+8j=)_Ve648Lc zz!SE+O`!So8GMMhgt_;B{#goVf+?Dlpp@y2gRWlXeF&g#CaJ*zQnUq!$|;m_mpQDd zc)%HqrDYC(Um3nbC65(R?@(fvQv+6Gm0<@zM6OxA`utU^E?T?xRc6@?=Hgj87vGZ0 zWKU5-pJmtYJa$+KA?AF4z3gzfj1n;V0Cg4MYOAN*4!_lbc>s&w6!2L_YP;f?9ToDd z0_NggL7pzwP(>6$xTgZN-FZDFBnF}s6Cl89Fn1!}AmH_8G%ROgbP7x)ppH7Ov1N~(NOMU}3%SV`@yrf5A~r^A7MdOib3pM_o|_%<4i;3Clj(W^gT4Y;(^P=klV z1Iy%Bch%S2c_1O07#(>feleDuoO*KcEa4O<~1&R|T=ZMj$_? zuI4yOe@trcqdz79vdUB0vIx%$`RL&90z8k^fBox)-MfFnZzp%>r>D=Ho<1}&aZ%Kh z3}f_6OT}E2J}?{FFfFICV)h>VeatHP)a+DCkz12ng=kLk1yEUS+_;F!O5{0)6&NI; zN?#X_=L88Pl`DWE7l8W?wUWjQD$K6k&prW6w}=860lw$Xo=2bt_tl(+D?;PF7~AzBf9paql?$S`ffp(Yyihe^>FEREJ%phmnurV0=h8Mi zeOYQJe?9H{F8{^G>t;(0O#mq~>I*erfBkiGMJ&E!XV|9$YTKZ6I|kdFqcA#F1h(Gh z%J%iu41}vhmtHc!IdUtOmpF+Omkf_oaS4A-O6T(%k->v~1vNM6)Un0&5ebOOwN)c< z5uUu2Yqd%>g;oLiREAwv(0hFxy7?ggf$EV=@v-?d^0i(KT5e!UQazusIh~fe)gNTa z{FbZI4oaF~R_L`vhaP)zXz1jzF>=#yqehdR8v&Jyx{A`M($$vg0smxWPM;OS{o`O) zVEIS?95sSDb3`(K)ua?snJ64N{2Yd@N0IKbWWB{zszBDH4g*rvMSE$^jktH zx6g;rhEbW-_5_N3M`pQbz3!DmW5-iXMA0WODnh-Dq$JuNaw^lMLR6Nl)Ux(yv6A*B ztCSJ|c+X+Pv(F<(rB&WGX3$n5tD&3@m-U$1ni%oXetswd21VpBu)QU|K4zm!+>Kwm z-z!4@O#DAeJoJ(nD!3FA9kW%0#KwkRnqV1A4TkF&42poTuK5_2n%ev?!d>jM{MPKU zHATNn=_rl7{q@@;~{V{GQoe56!~wGk3Y5@37sbPJe0B& znnz9tiL)%quiqQgpzO9Q;`g|tdZk|F3P!Y6x%{pY>VgVG6cOu7Ma-&cz<7+}pZV(r zs~5#7E$Fn&VGDEnkW{HwN|lcg;PA);&}(>jK@7tM_^r{SjO#4 z%CgRo?frFA`Rx5;g*k#B;F6#MYkGZXu^nkj7$nU`4LTd=rU7*%R z0cDEQMxrK;Lsj5DRS<{6^hBE~KB`i$NsR?W-=h7<#EKCR_%$ z(0y3#8ds`+Bo@rkhH#rMv@0OsJ4b8{-I)mSrt+y+1<^8Jv?3=L1S)I@$$Ky6mhQt6FkXF)z(-WPA>%kD&fts3qd7z{~nv&xlV zV2=cC;I0IzB>tj%9yoA@P7^NWy%v8m?n30?(7KBSr^g$McyWRc%J1E=N!x3zwfC$Y z8B{k|k1Lm{)vBmJl26G!@w7(;o_;g7cuP84EeCv7qcM*T5jyuulesja06(z?;{XU# zbs?Qbtr}Cw6&YnP8TTnGv|5=}+`4kWRdfcz@o)r@gee#bn5#f@TU?lDRT`~OnnG9s zTS;Sn_btSndZ2bPu#`1GXYEFJ4|7GcYsvcMA_#HK99hM#BP(a@{)L*`h0IAsFADS^C_prGptPT9}a=Ba1fTU2Y%nu)*inH z^z*w;AUeo4Q>Ra%-Xg@ik96pZ1#~xU$bGo`UO4aRx-NKcK}Cr`1&(uSTm8 z87{Q?FJ*15n6!i`UOE{y23bL0jl2G{~hvUeixan{e&DscDv!vJVUUBT_0Y?L)#J|RL9-jx34m!KjW`e@%6HN(f!EILZ7A3r82avmc zHBVWRs*dbLags9p)q`HVAx`<0Hl%x$cm^;;p?!9Qsa7b+n%1hh~~kD)rQmbh!>AnUJ|^J;IY7}G?`<&wu=D5QdkQh~{z zAwj$=k>OnTksJLkS^?_wzD#gsVS)-Q))3G?e--|gQLm%ZTmxm$i zCY3vA9N;*5J9@eO0^{g0$Sm#!f50nHUahy&b7XcMMg}&J<(oj3yM;`SlL5&C_mN$Y zrY0{vNH(uu!?st=OpQUqXR&n&Vf;KKL$DNTG4ES);dbiI>7p;p>?}0+twLL0@Ef$# zCpZj{=g!9&!pkfa%J32k-d-$gbZu0ql+l;()XIdJF8aG@?DR6~OoR$4Zl(!Oj73^f z!~cb+6}%36#*Y;yMES0)sa$J-hD&7!dRC1Bf4Z+((SshPQ7>k(RyFtmb-k4J1`(_t zy-&;8Y(5JoC)&?|xy6@z_~A=0{lXVoU;EnO!=HKY&81+UZsja8s?{kCgjUYX;fPD= z^=Ff|C8aZiS&JybO#bDuQyjsl(~qd1WdP@O*An|25ZY4jG0$?UQD!ako)2OO9^;0?P$Wnco(SYzWHAbyG1 zt;k!PR=b}6hXEAW7}>5uJ>OT{wyoHguan?X7}0!94FChVp3s__D-QQ#{#3YhC;d0tP{-!wR(x3R1vxQn0CjVTlPQ z-Ni6GVo1(^Bh=uNGpiK)4c3#P};8H4sbvmRr8{t*=}wtrtchXQ8fUGp4&V3X3t4rO9Bs zXt!(hzRy9ii)H@(8KjQ&-+t>+@xK}X0oZ0-E22pt<~G{M=A0;mz(o9 z>lM9Dug#VVerLIygA$l#uv&BmtyXgGoFkJ-SmcPQ9H|)1`K>B{29uG{&&=rD1y@#P z3MW!=PcxMAr(C%-^O*$Z4p`Y}W-2q6J!Zvl5KskeuwE5WUbgRn8ke_jfZr^Fk%>#l#kS{{n@D$zp$U5G(rJ7h8y8XTuW5g(vu zwa+YgGGoJ%gg6%2cfr;Oy2tY0TVSPM1{ zjV6Guu1W96#PR@FX;RU&*Q7#&N3X^*qnIiuo22NJvaHQoPME>kpa)SDSascK^&h#g ztZ_J;y=Eu(?HZnzX#I*5!xuv0#{*sm2zG zWdW3vwcJR#G@2+x&!kR-8ZuoXKg_=~3jDlGwkx-e>Jyah1SHC8oVj`0lUPFv2XVPv z;{v;Tu|M2rSAzOl9s@i^ryd5mq8xoff37yJg)$%BB!m^RRI^^VbWMDy-%mjmddncV zQ(R0%ovWk`!FoDpj-_+dAF7~>b_=-g z+o%_&J2japSx#FhKhDlWd;k)5Kf%L(vDEIA*ZhN&&eMB6cBSgc>rM zim334pRgI&p%jrKH5r?52el*Ne5F{NK*biL#TkH>g@Qq45y)0QKjSC3HTeKKSE&Bs z>P{g56$L!O9Jz{rmAM;O%4_&jAUf!7@c;gJOe#Y;ntzV{6#op(qA(R`HQqnMdu}y< zA2FZpC1|D|LI*(9T1yg>oINVPPRkz%kC)icQrxl-wlxedswLp*o4rn?0iP;>$(-iT6a$&*tVb`<>nl-f zxeSb_y34j=0>5<$@$~u_S2tAxRvhmHMkDblzUPp27j~a;J8l}F@o^4svhbeM%`Vi$ zy6^fzkhFBl%tlwM>kR0l=f>V+S2AB>WGCNvoe9;=l5N$+KLv(ig^fgCm;=VV@}D z`Mi(v6t-GQ)*0NbY07}8*~!w$f>8Eirh8~Ec5SKCr$#IdAYD}&H$qM#-5kKXf9UH zp=Bk)Nf(8y0jc0Rg?xwlR6r7iMFK-@ea}7j9Fbm!c>!ns5a>8kU!&tB zz}VO_@R-s|9bps0>eH*=B6qSHJ-WErB;2pkpNiPHc+%~)TA*X4G^zn=(;1u`XLg#c zCYCW~b!M=y0F(6m)hV~rsjlk$UcQ;uVXCXB)m!=3vr?(ls56?tk|1M%dE8N#gOo-U z3-@b{2DRJcHMp%FJDjQ_7>ue=@Yc9&cAy5#Ej}hAu1V-i3{z;BP{kU-*O)rpX5!LNU?60lI3qp(W)1z>JB0i*ti-X{8_ zP9oL?RMQIF-vUt7Fmt+MCn zh6^uTcjLZ&`v&&!-_KwC|C&EBueF8wxGnS>E8kj}o}QZ8S=?7RP+VQP>#oY`;(-EQ z?9KxR?iBw2hyV9HM_6}1&V(O>BSYi>IE{zM&);0HQchlmRi8Y+kyF>fzCkY2HH65Hr)R(jiq zhJ5pX%m)*2;l<})lD@w1H*^n|?x@t8MUqa|)98!qPR7)ZR2ej>ApvcN6s;PWjMZs3 zdMqwGYIU)Eak@1UJz(!EuPTp~D{gOZeK0*!AF@679QJ=84+xiejgWe)BY|}Y#WDJQmI52>E_?8Q?q{e_L46-)nAl^40eYJx}egC z7Q|u5#WhG@Rbd@x*5$k*SG+vAYV(1a;cOy3Ji2;(s6Sqg4oq$>zX|~whRM!OMdG1k zvWTIsS+@lPzdnc4e&mf*v)60!;$o?!T8!po`Fyq}&sVDfX}kegVJ2S=Ytq>gqk?6w zs;hI8iAgKKB+p9|drn^Q_JzmQA-19kBWAFpzF*cuf^U4P|1<+Wz%yn5sSFbEX0WKG z=xjN-biaZ5++a@_F$%5o?*~@ka}-&!?Rc_-B_CNCWy9<$RQ=Zwx0kG*BkPE7b}`me zL?kY;Noo<)5D-)dHI|rYSM(-&-4YvF`Wv-NJW7ai1WOeHATi*S3*fee;y=t078|3s zOY`RipM&RLS`Xs71}Q{4l`2{J1MswAz3i%xg|k~z)lwGnbb71LA0`|5=X0UBHMpe` z>6<+dvK87uG#ueLPG^!ST|u48<|b_j;{Tg+#6M2K){Rd$hSd z7PCyr#q@R)&S-&EM4xs#oh~52Wf85xWX2dUCr7zR=X3?QO0_!B=Q5kOE#JFb37SR? z^e*V0z&1k_%42i(ns7#=xCsG!OlUf74u0R8Zx(`5%Q|b&?DXhr^`Ki1; zx;(3h_J_x;3We%fWq!@EGv7FOU(sv`WlQ6(IMR6v&~<0ix%60lPG`Y0OXQFVvKjQw z(avzcqDOu7G4@@|hKY6TVe|aBan|dXf^-X^d3!kYPtiy_fmyC$3|a_mCST zz?*}g?k+IY%|jOi6beop*o06-VR1y+&`es?Vx+Bsg`}eE{-}+?1q!BsRiCdnB2osp z;6tw$-P^pa00M!>%{xEpJOQGnkBnKxC%~n`r--Y-&mw9fCKuaMwSr&spxb{13#8Rcv1%nlkBkXoXZb1fzOrj#=Idq@M{X_9R>tRTBpuq34k5%GSE~?r8O`RP)3fo z2r)u8B3emvQHMnhbXf?0g26Io+veoPf?+TFP$X=?al$6zk*+y? z*D2Sn-&AusGL^n0ARrlY333r&*3;V5Mh(IsqhDv!J0I#tD*uu!y>TurD^5&N+SYHR zIfv1vodar5!jyowv$0@Do(X}MYLszUrzaum#bnHeNWxu&AhH4+IG;q`TLusAc+Xuu z5A}Si=QF6@{8LY^9Xywu@CfsnPmoXDO%9V)E6If9(23-{Pm_n)N69DmF_SA6kWO7N z=HJAx(bewwulI%6!a+wl#umaVYACoEa2J^5A`2CZI>NDRrPk9z4%hXUohM(^=BBrR z{*=Bly$IXj1NbYkN#A`6u2wyeMQ_@uGnvr5P$1AI`+5~rel8XrMxR%W88e8yM4;D! zKs%LE17WR+MbOojT0G!zHse@D+vPL-yTHAR>z-&)Ccc z&m)k1@a5sLvJI2tMzqDvQZy?gppRAQ6gnOF{>)LU0VQaN-}W56hW~xQ>v3_3Y?%KK zqQ{pb?kg0764Z~Xku3i&;b68L*8l~cj;7oeEcD6DG7#m0VH)~$EtyRIfFKxi&93b& zG;x%{R&B`T3gF*kkb@w@T3$X^Q}{e4ii?8-RT+)Fsp$l)ZTTuZRw_SGvGWdfn?>y*Js2G`=vq1e(YbZVaYl8;7f+n+41xOD5Ee4u4>U~bLLu(C( zy?C0yINPAFLmHrBm? z-Y>dMdPGx_*N)bam>USSN}3Za)E-0!I`3fTU!A`6(gS%u>lM^>FiY@e#_Vw!3Lsi0 zOu_1a2&V+tV58IX0{>?K!~I46-KPS>LtqY&sU;KBQ`uHo(D5>V>DkB^ zVV%=eiSWkBU@0q-3n-De_>%EjZ~XkBr| zzK17{Ji0WqSY5?5zC;tj5dMGPnF#?nVZz{nK41aKo6i-A9UHLtIVW;kjnnN5wr`~( zuaYM~j}kMgv~s=FSt?b({c5>Z^XZK`g)Nav@c#)CJ}n&xw6sRY{E)B!`yLu8CY{Ah z`J?4pjV8Hu#|3UKK$5W4&4qPMcDJ-lxfGdj$)NF0Sk$slRea&Fcl z$w2)}_yLW74Nxvn9qEzmT}|2~-%F|>RjX(4Bh=jbo99P zBaghxwD~`Nk$-oSmDtM%4_;t^w2rhiHd5QYiHsiy0FtY+d-s_ncE)juBNu*UWcU;f z067Bo&7-;yMd8TrB|>OKtZhxKtXxc@^l7o zibOV@na<~@pDwMgSGCB$^p54D8y`yOjTS>83s9M&;DIu=M(w|Ve0ecA8H^qOBs+BA zy6Nk;?dX$%PcYqEFWS6r3$1)u!VznG&4zI~gsYHdSlkw)RqLvTnnj`Tp+KJTAp1kM z5A%i_dyWyfJdOuq@Ufo3c6r?%w3v@4ySI_ek{#rj)fkH^7h`(1N3wC}R%ShWEZKe> z*(BM!g;~3X87787akhA&+d^H{yi2jcitszENAQW%9ogs&Koe5mC%Dc|*JS=K(LLfK z@qkAy1bA7P7n(5mCe}MX;Ojcc$KM`}!_$g&Z!!HSv)}tP*dpa7iPV(=1GUjP5zPDZ z4pfzc!xx-)0u-Uya;-197pzZubxy6($_BsX3~_LKG~Gd{%hH_J>~vX5+@V6MH6+;BCypU{3}X__iQ3TuXz6{-rRMHIEZCxOAk*fFzyU0!co#t) ziJBu$+YiHA(`*Al89i$0c?@4z9AJTVf+@wM;8>(ZxWA9A)aRvgp@;a_X`!ulua%X$ z1}NZ_cu9u8`CiiFcg(HwI1Er`ma!aHEa~)p32%X8B%u2VCUYRPV7z?ct6wcP1`}Fv zhpFZ3R4Xoaf4Q2K<(G_E)8yYIuxNLpl zoO7n9_wk=ggEQScEX5F6#*DV1{cN2<<3wEQ^g6*sa2&|gWUTR+!c|mutzjp6l}W#v zTu1@h+xS1c{qV!o4%Q>idKl-H79FtRo>|zy`G~Y`19JWz%r@t4xQpELQF0A?E4k_p z=FTg~B^QvJ$)3aHM#is6e^Y3a{Y z_9WIx2cAh_%Swt+3m|9bnNoOKjV6C0YWLV8P=-MkPz}Z0Afb>z_nffjMo@0oQ3Msr z3{s`jKu$~nqbjLDU`BgtQCf-4sc~4vZ8p$>RTXEC6ujsR zYaL;G(B%u;AVVp&yF78uZS?D*L?rD+MZ=9+1p`ySxM&n<3}eEqFYEW2+<1zb;FWPF;OPj>IZQ3Qsm4P;gVQ7MXwI*n{O z1+-FY*OQHF$jnNzY8jatA!8FAQ<=Awg#ts@GP>V879yN7-O~yJT}w&D5JN+E1-n~Z zT#@jghV_=?Ho)sd1PTmbahQ&~>5GVQ58!Ndq#lGVB_=@gtBnT3oH-J8p;ZB4nG~l* zZpESKB@Exwz`;+y+k5Gef3KhS)uVb6PV)TE;xlW; zm0G=YbaJfNADNnH+Kl6)!_n`t5m|co!DVk>yt}4ABRx`S47kD(BZhia#!SLLK0dG; zsiy(6u@Q_xX-!x6LCNJAdH?L1nkqFE8H-}P_To*O3Qs-tUoXB`+_9r5{GaEm7*UYQ zR#nnv5TqE43QsX#dh_Rnz6QvXeC0wO>lr)x1mcP!Sf?wPiaP;VpbLAx*z?_<9|Nr% ze3N|nyUb?N?nf|sI;ntLLV`Z#3Q}86S`Y~!i?wpaHV4HNQ|v`|2V=*IsrTad8#`IV z>(qqd25}zu!&Zbom@a!@q3Itolch#gP_zM zRibFm)63|eWb6L1-7-ZjHedK+R`l)MDbZqVD45X4V?i}ggGO*jnk^1fFqTN^FpIx- zx<5Mz?KhL%X0!MhHUDE9@t67Uy;okfd^x7M6%)%RhnktO;c@U&D`uvKibQrs0uoeO zKs9t4Xw+csvf96eypD6 zSez!T>{hOCbkHMF%G74g!l@y9lMIF(I5bp^U8|4N1-xE|0YT3YfB6A)|7FUX3nPuH z6HJyWM{jl6Z-3cauS85LgVf(B_B~>>1;Qq)-su2!y9B)W29#>$PBJU)UA?lT%+A(_ zf!Tjr7TdUE=Iv___EY>_wpkx^!t50wy_Hei+t^g|1ZWl+L78sw#>}-)5&GXsXLcm( z4!J!pRno}0f_}Tnkuw>s{#Ys7a%Q7RXm-Z}=o!fctmco{G^(eUVbb{ao@aVqA*9FC zw%qvwxr05MSpNWnzMhM=2D{YH{8SxLKf5%b~=E8mu{sl`m z#QdNBS8EC4U^Kg#|2^fqGU-{?nlL#X_B3it(!Jh#wIHYE0}Md85XZ=vL_Cqgw6M~X zi9`|UNPY#fsr=krnIlV^G02&e59uVLl9oC7XvGXMiY&1k)^iZau zIL!@3WGCGmosCB~4|T|5SDkLC?p~sXztE*!tU}?VtXADmj5f>{kCDDsLU^VnI|R|_ zhaVYqPj;SW;kcl;q11LOdAGK)wynO6e2br;vyG5|MCzAJ6w|#bU?b$wpvQgAU3bOm zwE`8ZRt;^~HAekq-eNLX!yo$%GC!j^;LKw9U&@5s5j&?sI0@CHx7OQOaNJ0J2KTb< z_w3%y-yzyE4eh||v>vB9c!ScwI)gMV;`W=3k%&7=-M<01ypA=itgv*c)OJOZKz^dxp4 zTn=^sN|mNd7wUabzBXkAe?Hkb0TGi4A(TE6;gAuz5y!w)_h^KfsaFwKc5RQ&?lv)b zJ%?QMj-G$S{B@*7oOZ^D$z3ziUQhI_@<|w-^j12E4M{Nz86})yzOyRMUyFb*9Pu!< z?w2^cK~1RZqUll#CPjbfuDw*~RpB?WS5~s&PTJGzBp-OVXrA5goyQ5|x{J;asXb zT0*|HO2iHdPcUf23|v^F&?u9kh!%+uLwpvcQKc{v*5<)hK9)LbgHKABv1>#d35 z;g9CBp^ziY*%;dNSJ+%RzcOh{TN^*fcJQZ5K3NZD4! z>xcFuaFEIsZk#1ypWg@KMx`&6OHfW#xm^bZNkCiW2F_&EsW%T{qE5a>maY#(0J<$^ zFrO%qt&=`~`raYXDXBaKwB>Rj;09Mly590uRZh1{BGbDaPLt7_h=(9$MfIrCh>^bv zzgWV&ZVOf2<;Zxp3M@3A?)hwwyKM~<%cDcRY+ZuZLlE>*==3`~;6$8&VjO@qg%g^` z2vM&lRBbC_;M~D3(z+W<{TAFJqEGsh*sbUkWvQtMCK{60Y)b&43!ZH$hH>HC7fh>b z-h$0{eXUSfqbNqaCcDRHz4nHa7>xbL`wB&5EkFCoPu^uJ{Lvr&@JBx)=+!r(X*YT_ z-<%2fE?wqw9y9HAkYg(fi`5=9xlHEk>Zmj+TUwR!DiE2X9d=7U<}niOTJU_CzvG;@B%%a9m=dS3`i95TKRxpe?gE9r@`T^Ofo5-pa|9J>=ORS-=F}c;SV2 z-g)Vz|6q>g|M5rLw)Ne2-+f=ps+>-H-DovY0_WoknA``3Pa(g!fc6#B3qqpfeQsaC z5(g9L5mN^B8UvL*1tSU3F=V|+TM~@`Flkgn9KaZ``YlShj8HU;&X`=|cF;bq*{d_F zIaF~?-R^wA?h88NF8GCMW@KtP)i2F0o36@bvd>93opI%|t9EZg3Zzno z(Gu{P-C|od=;xa2=cW}_=&{S?RyUAGCe~H)R)R9Qocg88(ZlT5*h%!79GK&2f!$^l z^_Y#&2sjD7fi3Mx@LG&8LxThY=?#*=_(iP6_@K?fhKMV|K;ch-uXmvAqy6L<(jI1d zNd;yp3A%}$qx@N@RW3C!1aav3TTzh}Jec6QXr~@XcUoD)X*+)py@h^?%o$?0p87kX z3lA44q&XsBR|xQ^iy9Ep9qOm(8QYn36fkz;&mSRM_}?&x_-~Ud`O~3j>CW&Q*umZ- zd7l3#<}m+H#D2uae1ZQB0gR`roA&uHzx<~69tCmUJMX+hzUM=6P7#5;FyAzL9Uva| z7(L$ew2D5uw(O0_bX0~Sy4J?m6G*7d(KP4hn7`x((&>R*Moll8c_w+<-DAm0Dpg57 zkQzuhv~p{Wh$BX|<(O~ga#f8rtNi_k+*Oadr> z1^feZ9)I-H(ReW$Lq*jKW#?SdpYr<}WSIZu$KAeRnB;Whxm+iCU=O{)jDb`II3dXiBG@C5T&9Ow zJjCKG)}+q^474Ve3)`V6Aa#d0uL&)>gwf$fWd>e?H5Ysizb0n(y3vb@$DJ|o@;MKZ zbp;@ytzl<0oE*-iGsY;F@H%fF>ZN`}wJ`+Xh`o2Xu2(8G>H+@tMqwNf{*jT9gJWZ- zjE`evVA;&_;sUeL7i4qiUOscfG24rjz%N*@_c`Jor%tC+IFbQ(cCOIN1+8A36j~qW z4H`mgH>ZT&p#(L)&jOzxz^QZ%a6aGf>6tIcqgn^oPLm)H`2Yw|h%;#0L!C5lU$;lzElnoh;&-)iRo9S&N?NC)zt{qC_E6y(+T*4U3UT%#!=mOV+A@9+ z%%6Vey55MgYE?UPS=|fdxR-t+&!aC7;a~jUh8yO0*89-4!sXO-g@@rcuKV6Xn_RR+CwaAJ+=oIrDI!fR;_)q}6U{_w*<8@lWt=Ra?||1ty1 z9=L3-sxh_|0Kw+mPK}yn6DcUr>s1zz0Y(fejm$2UI$~#sCqax^b| zjiExKI*>&$P=HkMOr{?=aw+rfd(2!5#&yoj%)Rp8q}6(r+H5khN(HE8wZ3Y=8!@5O z4!DQaX#+(t3+$Q|FkHQJ2Rd-Q5m4A#O)xo(ttk!P_Q<6sI>xUlLf2lw3@*{y`nn>1 z+`iTSjn89Y&me-o5LPU9$8Uizy|?E zPv7y02R?qMF&M*VM%4jgwl@e7S(u z7NYWbdKb#z9zkGl>X>A#D1OsEmpaa9`cDKXh_WSgD5I}@b_q4FA(Pu(L z%gBH>yCI@b8mgEaWS|<(FsVQ2EVilIjMbog`q%_pbVbo-bCw*bpjW3iCNKnN+V54! zNxYB=F~K4ias08yfBTPrghJXYBha&GR*l`Gj0 zJAL5H-B+xdX#p0H!k)KjQ}C1K;gy3cFivLzg()~UjhfQOfyRAN*4G#;>vH{LK?Hnn zvv=~pyZxaP{a1hDBY!rzWRet}t#sPV76uJLCmssemJ3sr34yA}t3Uq{%x%Nd^V`4w z{Zuv!yl*PC?Qo%RIDLSA;1t#Y%kyQ{j-Ohc2`0)&xg8oH*P%;s7)adx?TsHHd+#LI zO70+6UqFtNTttq&1ntx1+YqBqY$jup!Kv;~BO5THv624o{Ew0A_K?GuUdWzy%_+Ot z9g=lhH!(BpcCuv|Gc-v?+39hn-7k32MfN2`^Yb=CkrNA5QNdRJy1jKYoodjJKy?kv zPknI&I1B1i>0>L#?yb~VgbU`)80Izq%=1A4Y>+;pHh&K_s@nWxc0@o%T?2I#RbyJ6 z!dW5L1R~?vs5fW989D3-XyAQ{*xq2v)N(LHSFcZUXIo~}GKl&(eVV1j3JQ3}Bg)}ZjyK3)grxnoV zRie%h&7VnWWn?BHkB*Np@M5d2#1z4Oj%UCX8;dJGYu>yH1ZejvmreIQkX#b=HMygY0n- z@T3YPMz=qGKd~MxMb2Qg1bhtj0~GyFzvDoH^8j~of$JPc#9Y^eqbFd9RJ%J8lKBex za!Uff7yoq1?QZn$*O@KcNrNL2L_Id0U9RSmCp>Ty^Aj8Y*rz|gLk_{*6F+$$X)w%@ zF!L2irztV^&PtBH_z!2PQ6=B}{44KbmQ^ALab(VK)X^HSq{jt6`xDgJ=oEGtnJo0J zR}{en3?cU_(@!b|rj&s=My|#{^`zq>(MS+ZQpUzf>A%7}f1V0Xv-9tciT`LiGL7^T zUuIBp;@>Xv=1|WE6H5{N&?01`(PS}MB-_y-OucgG6K07`q4h)q8@A3Mi=WjQ&6+hH zt9n&0YlI^hU;oaktM~`QuCWJm{-i<0S#)yF=ssM~7@3zaHUdh`FMsV1(J|SzUnTc4 za2*bx&t_Nr;(PzP0^GTZ6aMY7pQw%y=2vL;%1v+JgMW_{_{OB&VjOC` z%Q#i&c|!Y}*oIZj$5q+t++*RlPR_4^lhIkW0LW{Q%@zQS-DuqV)XlcxnM9I zw}MGSs|otnxQ50@taAJk?rY|ym{da6W)3^`TIlNxVvg`RyoV0FhgqPU&W1Xy{@_ls zht!V;%Hd>E$aSRjs7ZA94gE*X|3igZgm?mrZw-BuD9DID0B`M*$6JrTDMLI;N#fjRNN5@B&#c?dkr9P7@SzuD(>B$jZLpuoylbj zb_ah8npJZ09KqvN=TZTqzUuNg z0x`GMYYb+h(L~x+;}VgZY7U#rTHbfe#t7JO^qH}VRy+l;KWAZ0;P(W(1lqhlW|%cu zT#-^eXV-BieOd3;*$n)Dx)O2D5e-uxKs7cVV?PDGLkCzEGr~ljsIPH07~j2ZYjYEs zWjCxNtJ%3MNwQlvFza(n*R=nR6% zZS+?9n7=;mIh?fh^|uXR5-e7Wf#W{?nPHb)Zb?r){IN@OS|EBVDueDhFDXLOlH2_POg=#vp`%vq~6fC^H_YGuz^AHVPd4tqFw@>PegNSU-oSy5xu|1cbB zwy<`fI;jklj(m){k?+5qY`luBx#=eU6Lpg0zbkzCdVl`&pR+w@g5uC!{nMYc+DI9V zSxLQNHlE2}pDOh_dQ)MZz&cFYXOp%D9$eY2EaFo2`r!>jIq@IYYgHX zApnQGVPy8R=y5#D>M%d%!AaD!lI5;Y^&u`2cg%Z9 z{7epJ5))%B9Z18fBLhh|L!!x4rk9PVv})7js^y7>BA_f-lhoYw=fMqe{* z&}wv^zS@^fbK5qSlgI2_p^r8iuBZu|``}BmxCi@Jr$-xgkbW8rV5DAN@2!U+fMK#U zs>QxFt2RMO8+$;3cmmbDpBbK55 zUe?5px0xnOV|5`96c27Az|J8X-Z>#w11!l{5@PSp2_x_NFI>@$@Ia#_g)IxU4xya; zKKYswuKnVp(%Jktn_g2pF-m1D4ZsnX~cXf4F z=jq9r$umsO8HO;x2qHo9AnK4s2?h{#bw3kElr_S#ima<*PP;0rxUTf&|D0RZVE}jC z-`7pk(_OLedCz;^@Vw7cro+pCNPKjnAKhJjd%QK2 zgfal1iTk~ooM7gh%Pv220h+ez1Bb8LGI8Z)d(rqd=$5?wnhrSIT)DuGJwfB zb^&u$K#V6r@dhg5NGO7Mt{4x+;x=@yjR3@L4Ow~4f;oH_j0rln*>D8P16GSM6mRBZ zQLVuYo@x~y2y_#O3?cTWQYaYI#y*I-%LG_JcVXAan}n_$j|Qk-iNZimUe?xgd7<%#luIyfkDGl6j$0=S4?2>QI5zIhn1B z3m2{D6Xu+R9}dsFYfa@l?HUYIFqLW;$;1)I?u;YBA!tG3={<0Owd7 zbN8nekAiUwaa^oBK@|mshk?PwRF{mo=dWqd+uJC!SDIdNT%81nmuB2kVrD()_aM!Q z^Yx8XV{;%r-FT zgf)1#HW#M_O4O<}czMn)@O+5#y6hE@acN%ifVvb4kSn}$#zAJ^LzvD z;#1GJADARPIBM0drOo+w`8lX{(I=+Q)up?`(|3<_*d7d6e%amzn%x%^ncA~WJawZ! z^VD;%-#y^F_oDBBefZT6gR|_(KEkz$$IbO?flXT&h)VA#*H3>fQ&_ihNNHB}(NtOt0$Q(z zwx6@0x$m}mA+)H|IUH1Q%wUOt@Y|sRc1dS}%0n)orHvJbku$lmxHb*yC=S5mj0O|| zEL!k-gU|gW86AWMjP~2!Q)pdGZB!cxa)Q=|4qnFLae}y;{#g4 zb`wBMmVlXeSkyRgL=$9fGuT1-#cxk zV9@3E@aBNgX>?l*PK<6Vod%a~96cl0I0HWX53$cflQOAT3O%+^qU(7lNVCpV)1*hD zG&NacQfviPsF^?pCO$8I?pc#;rZ9Th{HPsLi>eUFfa8Y(L2Z$iEadcBmbb@mYY2Vh zX)gBTzrX=6*1rCXZ**)arC*(><@uJUf3%}BtBvYq<4fJ&pT6&5v?l!J{)eSs?qRI1 zoCEm9l$*P(4Va{lDLkvupse?&>Zv0~`}FVtqbp!-tH@^t*6e7aaiUj_>_2ssh|-@Q zHejGaCH+#owzPS{rnVNOu>E^CZG&%*7cx?0Wo}U^7qV@hnNf517yd(H`H#= zzn-{CG*_u~ccHvt>E)c+)(Kj|=pIRLyiMM|GF=-kH46ts*%DB-h3p~LfzGbW>wqfm z{It2d4AlgC&kx}6ea+weMtX%=C{6#M9km6+)b^pSX*W5nP{$QRUZ2fx1~}`}d21-* zH$y&GWrfd0iI$Ie+=3NE&p;qjw`Fswq& zcj5L;C!}@kcFb~N6A<|MkD!)BXJ`11+0GFm4rqF`*qw6$f&rU6v zt`v2MxUeC5wi7)SX;g-zJAsk4+J+J#E4gx9nxKOpk4aB6s5XXLpg{rVfOWG2yH?bm zJ$P~_WL$LGu?>s2N{^7+GU;@@@jC_>7W`4a{k}$Hz+Pp6EBO%ndp3ZI;Q(|9gpO_5 zDzX-7H(Mr@+hhIK?%Sp3Pc0-ji>SrmEj4CGV`d%xyy<~Nh{97B^VNp*u4ivq zKyV?n7jD1$g;gsTFKT4t9O!()ss2JL6V(;H$y9x6`Nlo&1iF#mCzF$%R&!!#2}x_0 z9lUb+btkS~rh^78Gq!B~#nN5me)|p8A85eYr<0~{Uv5+(xzi~8h~r;j$K@Wk8M+`< z#TfXX)^^6%ZU9T=)_vqcQ0CXi08z^luM>ZRg_t2?4JLFp4Y{E<=^G^tC8}B5_YxP; zWEc^f0}=pA0XzU*DTr?NCx-^uh7`e$Y>uu>M0SUf?kd^jUva(4J>h?=7*+AJ{nf_G;wO`f|SZ07cdM4npT{QR+Fv-8X5`Unl zaUroY?*Xc=yqoj!{-E3I`UhtyoG06K9>B=|1w#TrLqS{~SJ?RZD+ecOy{uw4V@_xfl{Sqq3+Z zUZPmt8Qph?96e6fva2A*OL9tp;bLi$O+;A1W7A?{euCu3fUP{ZpTr4CQPu^bixR6c z9ANAK#3@g#>6Mz~tXy6fn0A+S0lT?N@zF~-;3{Qo6dW>Lgjp13kD}pC4nMlEb7vo& zq?^~f0n@*%-Q8Qw1pCA;3z$ugVKl&(xeyoDTVAlBpFALKyYQ#G9ymt$-*K2e`~7qI z$?+kK5^DN}#?$RwqcfsKQEGT%GV<-|r4uG1<_$K8*jTKFBavtr2oj3KYHbrD^^JF8wJ8ht=(N2?+gSDVBHAy4-KM$ zp{bYp;wVCE1I_*_(=Sc`2C5vaO1k;UFYHrlwVDOnRvwV3Ev$yBHnnqNB$ zEaM=sj6Apcx(F!JziZLOUlT|_|q59<{yLONR&|jI4YMd#t;5$Cx1F>gh_^j-qu_UPVQ9?D^ z{-#Q9kbao`oL3db?wczvQ=To_xg-f$ACeBKRukyMGhK+3ypoh(%SIRhu9fZ} z_g$PL;9&q174cv{FlL`+O~}X7P&6@zh&ma8&q&7@v?8Bli=Xu)v#C4 zo1+m7d+ybLd+56iGx7F29|lZc`_XrtT@>)IR)IKre zBoge_3grB2W;4^RD9^Iaf4_3)47-pX-63|X^ko+j23|zH)qo41a)9elTsfEZMabIb~Y>@bO6nh zPHxy(;>g`saSS804p;%Q6#LW;hj$pkv-VW8y|Cbg783E-g@SM3W=$fHa$m*9G_U@l zY&H_!mfi?2uZs=Q4h%D{gG5>DCvS6ky6YT zgYCR88#YE$5#Jf|@83iU5^g^Al=R3Ad{&g`_{b#wHHuaA(nWdAq_N}^E7D%K->|kOBA!8Y{kI5(l`CFFgG@xygqXil(;5vblfSQwRQZi1< z1m$vG#45x7&{{Yu7nmLM|R;S_OvW=6T3jZ$jVi?7N>0C*@>k{$k7bs^KrhxJM-x zdc&jS+v&sUMZovDOoQH)Mnm*_B_xk|%4x=Tu7vCX-`ayzTmy`br=autLr%&BWHB2q zE-q*n0ru5sqSa`5P*>n$ZXwAf3|EpLOAp&@RxJpfJbjjQzG((tfB{>O+8&C>(uFno-;1v^5QO^wgGs1tB=D(bNZ$!4LbsM%r z_dul<0L?Z9YvR+}{l);#QKfo0(LW5vlZhS^M1W;6Vq6`5+Vzg zJVUb7mv)^f^$zp*)&F$0L6Jib>YBWrX7s|~NiaE$#DXqCcWveVwCqu9a$rTyp=-c! zeH&%3ihbiQ=sf-~gtbhdu`ui}G~01{RaF<(`!DGq+{*->SHpjKDsN@osCx=IqZkVG z(F*)sFT5cAlBvJ+S42W7ym-}yQuYpQ0DTLngKf}%osGuKF zbUM||WMU660B)l5A}tFMRRpE;7$F6cQ105ciCwpQEi;KR7*0>rN*w+9?%0x?r{VGf z^@QM4{+t(dqGgYu6aJ-+8buH6DhK>*w}wIePnR*d>z3w1CV7cuR2k*ho2hTi1{359 z&-{fPl0Hc$0>R~I@2mHQ)7M<1GBQfTb<$sd`Ag_x1%}pVm2RugTJkwP(#5rCAZi1P zoZY-8(yAxCP}3lq6rbkW2M-=UjtI-so&cE(3o;Dmfy%YDgVldcqg9~=%`t|eC;z>= z4)aSYwsvjhIH>cL+B>C=s0wjOA(r%p$ZPtQ`!_YzR&P36`iTu(omCtnoDx(cdQ40$ zD-Kk?QTqZyQnmIckW=K5l)=|5Kz-|zz&#%W_GX|{7$JkSmN7y47l1+T_-e+rj@Xp@ ziSi&W_0%{s48%rE>9msz){sMUC*RD`MNa95tHaG1gIUtC8ImXg9ekovvmg=H4EBc@-XK~E_8R9E9^tlzI4281O3wC zNK(x_(w@Gn{@ioVeF{?5(udnt;`_<77`X{G-r)r~CZ?~fsaP1iq+p6M*gqycP5L_^ zXZz=8S(o&c2W~vQ1Q%3)@jla1UUd^t9|Rpa%G9|E=0^H zk1{I`?`JMhCJ2cEcnrCzWn^G@_Oi`*`Ucm_#ky^O>aD36&jvua7WCS5%R$u7&Y)EsFRS&}2Shd6P;8`G&Hdv?ykb&F z`zqhCNd zb%QCsyNVhV-RDPG^t9<#8gV-gBAihNiQ((yh3AM$`YT!}?&2Srpyb}S@BU-Q9zJ$V zdWw8pdMg>1J~i_NY-kAxs6Z|kb+O84qp?CM9!eF`(;M>!!5L{f99G@r`}xMEe$SL0 z6#)C{)nICEv_b!%W-K70>XnrG5rV7K-I5ZjMf1x_YkOrSw}+OM;&H(%7?UV6F;D4s ztZa|FBKfrVvmqorcy|}*y%pf=)!)uPjxkK7>UkGu4kBBor6piJM6B;m*ae8QzM%N3 z;$_9F3d6_$Kwf&5JOjB8??Zc_YQaDm-Lcy=(f=B z^j1x!K|5N=;^l*g{+a?mE4AL3oPcOae;i+38$7JE1uPwJ>TM>r~m96axJaDq9j#_Tj2;AYX|wwP5)cN|)n zJb>!jFFu0`KWaCgIsr8d`7q0wywHC)+J)N0@GwvgtThrAKYOECE_;a~8W640QyYw+ z>)1Fv`YNDf>rN4+ZWecYCOI$iAVC8#gd)%*DIRQDE}frq$;2x{zk$jI()ykTpUF zJ~Nz~%;CS`jLl*xj#gvp zT^JB-nhaXNPE?JQ*XPwlHi>Spo_yso7K)#$FAYI*mNis|hf+=qTH3x}t-7^JTShuV z-W97xzj7*Qb)(IShCA$>K_323;EoO}Lg-f*K8`TghhC6u;nd;7ie)?O*XEyR2*;0$+LAZtjKvdKmN%>$ zSvuVJ@UeZh`oz}V51l%7<&yr^#TVVxhe0m2b_K+-(Sd3Vu2j~cf87vkUe zOwgY>x*zatGPh25U*O5vGtx1C;DRS7;^4^#;z#ET4BT5a841uinHmg{?H}PC(~Y>x z@3TiSi4)887m~!HHfZ7t#@Y~h(H2Js6Kc>g=_~m~;20;D7it!#-qcFgw7^0*Bi5iF zQivjJnhvyFu59)IDk++^v4q83Vs4ZoW(&c1j02O!e3NVmbMcrz5J|a;Tv7}&po54k zSUQ!`0Q4Q59IY?dd!kw}8IWsPIc*?x^pWE?ACBe-4j&Ni2YpsZ=Fq%n6t(JaK<6l? zSgF{gh<3ayXs0TUxD3S#oaudwuHKneMR(hE&{4fOJn2vu2_bxKfK zn+Z6&*BcL@m$@5obp5BC{cL^&%^-id?-A+edl}wa&{+Y7NeBFwQ4(8$3H^{T7$*%C zsS4WHzGj>nTZLYdakOv99~f!(0VZWKEM2hD^23|bb`S5!*j)k}k$(4818OKL>B|68 zT(ElkAe}(a4jkUM21tqvfEi$=zl8cjqZJx4B|MWT&v6v7FWn}xzBX4|>)gank0>qUUU3Hw;$Y0e~^j-0e6#!M3C==Gq z#Y5C77awWM2fcY(fb4>*sQt}en%N)Fki$_yuM`ZDUN8K6)+7_``z7o5o_gw4W>k9h z>8GE6^}CjgD_{+#(?j8CwwwV;y*4*C++WDIhNG5T@_=`9zG>4NEPWibVR^O65x07I zpEHn1GA}lyf9;dL(`b-%ABiot0K4Y)y4}8_+3gECg5mi1g3)v$(jEmf&&manDSM`T zZry?Vw>fx+7nKl4nDe-Kw(OOkTA>6zy)ZxJ%9;IU zw*|27gLwv%&L++Q{IFJuY7|-Dr*=B{VT%ic#jNTNLoh70dC9~Ut4(iF4vvh30~4cz z2D{6)VcAk1N`3?nVvT|}&Lun{@NFi|ejyU^c&t=a*Af6#j2KQW9vw@d!f%YW+r#x` z!(&?lZZ&X(4vpT(xl^gJ>#x3Txh-PzbD$G^R8t!nPr;)rh0#_6mTfVOPK+cR@rCs| z@L1nc_uqc&`m2xb0sDx~q)cwwvVG(BjajqBp-Ue*baZ%iZPyVX9_Soc8gp`w0ejWe z2crGb&5CL#r6mxrbD;#n!^D;A9E?T57~Doi$9m0-#%Toznu9i>oWk`y2Q_%=AdpM5 zt}YKBMT#SAdcA|D3pRg|yQr4`(LX;X*@o^OIyW$IZs_j2?zO)w=xhp ze9vXK92+q}=0{`myL^6g#3#=lF^b@8F9IiHS1iQ-(0)t-fB>5*#cU0#PDxD}#ySs> zJ%7HCZUosI*yKp9yDw&H+42^n7q1(s{#`qc9{BjA$Dd2yMcsWOzdZBy-P&?~tI6rI z@2vG1ssIskh5lXJmNmVCxZi3uo6;U&08u~kT0EY8R*V@cTcu709I;?x1&9_{N4^XY zuS@z)+Dw(qLs4HCoPXAMCW{TH*9Y^l2s$jJ-WnPJH>W<|*MyX*R-ca#n>6Z8@uI=R zDkFe9@l_kQ@P|3EOOcErH8q4xaw{ZAhUN=MgUYE3RZc=&!$ zLbB7JHfIqqSh0=tKn|PCAeB@43PPT%;2kn=_i+Mr(}SWV3hsOnnr=2N^kgg$oUx0M zccu3# zf*n^lMUXA&E0`UMB}oK0oKSG?AeG&iywq}CLr%>Ry7U%+rJDt(1szZ(u!#oDqL&-c zdz|;f|9ng^N6Mzb=F$-{zzbw`KC>XYxsa7^LkYtKFyn*$_w;|~o_nN?P!1O~9yqi} zEI*J8rYmV2fO-)6_vi8hBQZ-pdBC%|(6H(CmOd8_5QvVs5;hMfpga@;qGiGM4J(9L zCX|)bt$?7O)E0A7Oalp-4o%X3)wE<2G>?P7gmor<| z4N5N)bNB1RX%HW~?7@&b?(qe!;aoLo#t{=Nroj+oRHa(TMnKh^>#HYFic@MMiH*oZ z$^Hyx?QG5r7qGffyJcRUt~MIXJ3sl!-+tl~zyAE^8H3;wVYs2NJ!}s~f`Tt-0Z9*F zyFT6#2uGKVjwGqo#)gNQouOre<3d1X17_S9%j~=3s^7&1@R5w4Q9z?z()H3C`PB!Fu@yhJ%)$HA7 zAM?K$@E7a<$xKSWN91>7#S@K2^I|mU$IRpBlHuk+pV(h7O22Iz1A$22U}HQv*c|Fi zu35OavUb&G%<2PEKp1Dy>-R$*)-R=^-k`-_NW;W4F=M0FitYLpi>@<_}+!LYe_hr@??P9MewSSk-3Z-NgFbX7MwNRNvq38Rk)QGmBM!XO zCbzVlkD{jQDM|lG76bw->4W#gBaces3Ben*XOYoL7soguU=5V3sd%_h2+L>oV5=pc z*?rZdjxa`3DP0ClIkP8I0o8%E-;04BEd0Qg`0d&6y$WjbJQ3U-l3xsbaL5xD174;t?1tuo5RSNtd?@4z;zVCCK9s;bGD59p zWAyORX3lJY0=AV?1!9LDJ$lO#j<=zuq0+#I1q0@2FhS#9HTp=OL_Uz5SN+}x{-MV5 z*}R}-McEgL0ci1*(Esg4PzuH&5+@txY^=%W)&Q3aO3&HINp9yOc6wcP>Hi!<{f*_C zBSFTgA7}5B63_nhr_#@uebUQ6`q5X1Zs^=`#~ozj4b$Iteus7)}LJ8IDcle@HlM@MeHA7@%pt*SGiE7Sj(i<%nUKxlU ze)QN)2Q7BJ1H_3mrR9Pl6Up*e1*M{Z+~YTx>CPc1I{tmGvl92ff~a z!HAkRPVit^513cmY_~bUMJdp^RKoRZk}0umL{JLn>A*;;DVt0>uz=t%(oVmWbGkjC zRdRcxJjRZ~z!fxu7`vxx9f4+Jq~XmqQ!I_-G4UM=4geUZ8uKNbIR8058Sx8t8}epR zcYp2r#TSlD0fVWr+YF-%CN?e^TQNyM?`vFpY~g`&vpG~d4H%jvS~0unv${;kPBaEv z|I%eS&>{+9fpfYLn;XB&*Ve2N{083T_lu$dlQue=-{*_i1+z-?7q=*eKx*N!BKB}& zgv{fL0|Mt3BhhGUY-~VuH^zqri2EK$wtYc#h|PA3Q=LyAGV7*+c#74eR6n5?>jx%^Us@ryzB$Z2v3Ir_QB9tgRj$zmxI zPo?qz8JLTm!CE%c9E_nLs&{2VCQC zvb1T#U^Z7Qt>8ATJJA}fHnNFu#KWuAMiC5x3Ett*{`|ABD9;n5Px=b|VxB|M%P$H+ zM;eiS)E*9(Cq_qNnMnUoW$Dziz9lZJdDNJxo;!Z(*3C|b%Y(Dg7V~<%oX;aTTPLO$ z;*ZtUJwU`*pqo2jF^WS@ zG?oDE(;Jn!5WYYM?#*5AjJJN%TEZMM4%WcF^G6Rp_@MOm`|i5}&}W;Q&&J)Q!AX6! zxWi=BT6R?WU~(j|-Q!-i(w{clY!<89?d%JiOq+*Z{X-m+r&cjp$i||XNSsD6$ws4} zMlkt$Do3jh=~y4?zs%NT5woTC#yTY$_|AwEbgi7*&uZ&OYFA%VJL&;$MTlU;Or=MJ z^uWQLWt~xLZCrTtar6uH(p?3!$>v^$NpoET$AgY1E0g4(0S}1!{k{-i;6?BObAiaB zP6v^U*%((ZshiGkLNw+k?djlqr$6|NokjK7{jmdK+hF&DIMbYYH zt-!Q{58p@#@~fpp#cF^hXB}=QV`IG>gNiZ8+Lfpls}*!ryUQvsEZUH>`;HcYun}j{ zum5ea=A~P*&+Hw}*l4pMCiw}uz70`tD(roY1nQb9?tPH-??z5XLF}?vyL&4bZ4@XksL(MFl=G(kf5v+h3>GnpWUd z!RVn|-g4C$Uo_xXX{-T%Jj(}zaveyGbLcbZ!xT`1&-Hjqu2i%;g><7*$SRX82uVtD z#!rkvkW*s&Cp{43T^^H|%H`rhA(F9TjxsUSrgb`PVW6G_Nrp|2 zMFO~(Ig+cGoO)xwS8zGB7^sz-CUz$$u#SQS#F850&gw=-3G|hgcJQjl-RaSSMwWidKD$-ASx0N6cEJtA!c~v5gXF)q{S>WHZDfa|g^U-V8RcH?<>&{BpTMUbYI`-95CqC9eUEB5Jgj zD%VgG^k6zK_MBZetQWm;-p_O;<>#QbAb<9@7Ka1yk#9MOyY=mFKl$X38Owis;~U@7 zN-Nu>YBfc3U}|AIRg3A>i%9iq>7lfh_u8xx92P-dv?S6f>4Cd8P>4qKXx!FYgH4cE z7;?2n!~~IheJs2YI@hXJD9-T)WM;^KZ2_N^;*q{Lg7F?ky|uWcxU5uKR$L-|Qkr_{ zlpTF$s|`wnTBof{c$zVguM6H#%;5^?^Z4(mvmy%vmo?bh8UH{hg#r2$t2YT`@^qyEIs-R2V z7#6uVYd>#!=1o4*7f8JB+2vQIOHH2~+pkugQ?bM;3Kx4r9F;e#7>mdMUf0)j@n+8C zWK~?m$_sA65n#=KMy~1_{0ZZht|>rSw_r3{^byWyN6*`-^@f5WN*1rg7~Wqqx>z!e z6oZlio6Yf{ph2N4775$sLa@egQ2K8hLxkoluYk~nHH8F!%rE-<{NLw1&s=o{kNPrZ z%%LqB40&Si=<AYF5*FkJBfT@0EuHD9tH5l{Nh948Dx_opLMffeTB5pLK!rlPwcO}U0rC;82 z&pqT4#7V?7ee2CjqINwn(zidBtcoKWJ(A>Q#hu#1IY5aW>OYngB`x}Cm2VD;3(DE6~4K0ManUNJnjDdg5z9X5+8S~z{* zv3HL9Jw6+RuEHR3SX z{D2vl4G=?GQXqQOxqJdA*OH^JeH^oZVlUolDb4`@TP}kIlC6_`6IjK5l3wm&j7l2z zsL16|0HQ2mrb32sD$k2}A0S}2l$EPb(I1f=Uv(x8_I#j3tU;kS?1lNI2*>PiG zXC2F25eLgozDB+=D1C^m!q@wLY6ca-LnZ?QHVJRmgia@@7occuGCcLe9|Ewm^VRQv z|EI5hAH^NP;mQ}2VmO=fn-C}^`kE~;U}%fALK5{h6nD}^3R}1^Rl=}>x#jVgoeVTT z8JB2755)ydVgt}s!{xPWuidagdbN!Z1x3#dfE)dJYnRmPm(=z% z$}k^|gEHJ&P^_=qFu<6=Iq`|+(?Z$SWkgW#d3cqr(I;1oyR**(QAK`%n~NOEPT zdy2>U2kM0-!=u1DX(($B{E*9?Opm;0-<^w4Id{@d2CWZxP!oR!=eW?D=B0?tQ;LP1 z0kMSEDr9U@7@xuvm5=GCDY6v=8t7mHO{7t}hz>@ej1;37;4PClRV2x$8ANC_s-6w2 zXV2@|bDN&D^4E+8`Tw=A{WrGr`RV90XOV7t`|iilEDYUt+u;43vvJALAty#g?rEPp zcaEI6XZmX~Czyz$i4xLIP{YcF^ZrJ+a9*oKu@NzUmMR12Ms{UN;GQwI!Va%l>0niS z*a|K+uU%m7ya>!ljQWm?Fk8W>&zA4FE15tT_bJL|{Kf0>!R!lhsG0|T5of^_ zLY08`N2i9{a_AiEZ`7vtoTy^UTCit%RUmrk;S)C>30RReGD@w(?*KDXlE;qKLfiLo z)ZbDvM&uw^wazHsskk4E{fMAJw7Fn2bLoTRp|_BC-NsyVgE%;kqcBS&0 zpLwUZjcuocj>Jg0b>hR9O6!i_J49}2|6QGvo>0-&H!yHwxSd6N*u}Yzu7nIPM*Ljl#=~sKI)jiWcfDpsA zd-h0|{zpAiL=30Xg&U2|c5vQ3d|autetG9k>}?%l^vBs>z*el7)u;P<60!O!RR69~ zEbRIOp3~Kf)tidO|m(5 zWsS+C=IwBLayw+xnOV1a%l&t(Hc#(^SuaZTeBM&isZ%6$6!VWE8V>9rXjMS{hjuAq=y&UY(dC4 zImwXI7FxA^`LgGZsW}UB>I>Jg$;}*9x!`W zp`Sb1sfhyd^B4ysjKiqMsFBNx0?XhL!wc3)-$I# z&7|cG35*>o9Tho8rm?f57elkubz_&xu~e^c3;4xc00t{~lbY{r=VqpDgS_}nB5m@P zG4iqDwbJEVUfDpjk3W85?<=po(i(il=9Fvx~L>8cZQC@wiLP(+6Ae%q&rLHg74i*lPb zN&h}MdGX@K(!aiUD2zzY430{SfLa3fB4$J0mvDvxiF7pLVlgyf_CmlcoQ~uMmo6O@ zef0&SThKP~i(0K=5IvL7_~=!dV`ZfS86-gUOWVkSSx2%83#^!)LbOo99Xul+SAH+n#oU@awBzeNDkM z{`~Z`5}-1lHIOTWqVaGhfIwLr?{5r%$4gVJml9AJHtUNis{J;DDr<~b7#HZQMLX|7 zE!offo7DH=*u?ThTIjc`F^K5R#iA$yS-+*mr{e-(Qx0MAaLnhijp;9CW)p4y4#NpBn{%NHQ9|Zp|9_YXP(CKSeAympyNlb>i+s z4xKzpEMspO! zOTCL>LVo~x><;O<|9tsny(A4h-M)c*GiBv$_N>Keuy<~C5zoNE!^&cA(q*{lWBrPBSX{+Y8kj2lpNDIPg?aMPasBTBFXYBpSd-NVSme87ypi1S)RHa4gjK__Um zQ?7Ifm|gk?$Y23APynUci`381-5fUvuBz~0-6jkolF>XGJ=x4fm9uwyLU>GQk8=)_vVc-zgo04CLg zS~yk8)l2{%C(@BHRE^kb5?fn+BALSkls*C_E#67TpsH6+|A4$a{UozYy4<5RFiNY# z3gTRcB}tyW5`$9?H>=W^>_KqhPkT>iNb1M4lY(KI4~%L;#njejJll; ziY#{WUbih2Oi%XJAY}&gsO4)*%Io?U@OHh^>@X`sv4bDoao56NJd#962fwd|-~R~m ztP0jPr|7CcUZ=o(CkozFAaH;bN11VuOy`Lsi&cg|KJ_u z+o@+b|M+0fy-2H`Ltk8EQ*lrV{wULU81)DfAlg2|KIuD9YILzb)MMH_^cbl~m8Ye@ z64fAu{5{i>K0ww;ACT^e@g4z9z&!Xiv;Hj2#uEKaIU6f9^J$zC7JVrR?6H#Bohn&? zJ#H*C(Ket9qP9L8+JMYA$K~?ouCh)WwfgOqiUpWUFhS^4J9)1)sO0@#uW^UesXq8% zwewtm|GvIH^2e}SjDi<8>_Ih!iwH=~7LE?f?Z3!Sy?+$#KY(a7;5p`*U`%fR&4(t3 zz_YFbhUq@&qKqgyiWA7n9#nilG1w`cB*%xD2gr5TBJ~QEAn|GM1K6xZ%x$zbhPthd zE8j{6`!QZ@F@W)Nei$~JH`DFg{hIGnE7V`h9V*$ig4&@wMJ?CEXh5I}(TVE09{n4W zxS7}h_953iLEu4OL5>A_$$GaZHk*>oJc6pRgyv#z@{5mw0>asM-+kZx?pNNWsw5W} z^?E}+moz`E)&$+D90)m?;Xy$#X`;{LjAxivzVz*He~kP@`cBdU@yDVolPZ_0U*cJSn#N>pcVIeCnZQ$?Mk*Bx{C0*sV|dLXMB%Qmxp`4#$51LR`gF?RcDd5v zK8AaM{TN>R2Ky`2Q&(e7;H2U@Oi|`LkpOW{qJO!NXzo~y$$-m9;v;YtA0uzOi0P2f z1Y>}B&}^M0LDvq3;-@o;@(42gIQ^ZxVQIak`;XaQCAxlp2FKBTkPC%Zm{8AqBs4wp z;CZvI)CTB5PNM@y2ncnjh6b1P$!kL-6q|7!@~fTy1MY^;x!Igkl{4*%GqVJ~k9tTwW0ol?fmjfQ`EdtO@$60bIc8Q{XIBLO@hV=>#EdBrF$C9bJvF zCOZ&@Kh2a3DVq@}kPEWbMsZ!foGbd=$z-XzqFA(ncK+h&+i_q7#d5w+^n;AD{_1js z^bj_W3vq7{F2ZQiRjaK;JXWd4H5v`a#UoAc)@;*k&|4bofN!v-7zo^%s1AGTsr zFQ0#6^8J7zgOBvb(RR67jp0_HhK#nXTlS+t^y`3CVuG>lWk)@+U zOiM`xKMpVpE+&WBo33XTA3exSC~sUywy!4xO9v&FP80{%Ex}7P93N2fQ1L4T~B|!yE{i+^~V9#p?{(#Bh|X zJ#^@yef#b~1?IVp8*ksa^LuZ#HEZp73|S~S1)DXmFVv+Y7Bq+;X?*(~cP!eBo|)Eo z>M6TE3A75A229Tqwx2uaV2GRfF?7(pZXYjXyQuy^dSuaHIi9VLmFU#i0(-9dj^mrJ zJp$5aH~LBTh)duC9$&zjdMo{qo>{$mHPiV~qty&2FqaXOzBVO>jYGyn{v_EA>Jjgc zq%#u_tkW6u9C2GgW+8ZS)^SN71C;FQ2U3*y4nD|$Ucmd=|H6#^LLfj-f{T+@7jIGA zjq2hf@_ClO=Y5DbA9;*?-~n`;K27KkGpEVmpbHnBd9*7;?KgI)$BxOhqJAZ_U%?_Rw4 z@+C`PS3$(SUjb&+f=X3G=6hI$ymk+)?1y|4d6)C`-G^J)5R9!eT7$=p?x z{yIc{*phw=#*SZDG0C3+KEr8IDjlne7HjmPy2oPf(-uXeO=t;bXhRs0(S4P5U16bM5!Rh z)%ik<#?@v$_<LyQ1+>B;!qd@ooA1+kRa-p`;&?GZX4$n)leBM2X+g{?itejR*BzF7;qAIc8TDAsf)o*@r@j=Amza)^C9IdU`E zr@WOMxSi}$o+W$UaTIdw0?#;Xw7&&znB8wvYW;EOB>~**P2C9874(F*UAbyhhxT(K;)8Z)gUo&3~IWXg9PRAL)CzGAd1paV& zvw=U3NqQf77tmtu%mdVLl=Q{t=8M^{JdS9}+q~Yzpj~$M?BMl7k5Av9vv5uizy+8d z@(GS;JSH|>UTXkKv1(PI**8-6rfVS40mj`TiY*jdqYfvk+4=yIZ>tTcb@bWJox9<7 z3@U2OYON>iuGI3#^>qNP+Zl`WmlyB>LX=-Rt!lL|4YShO|Wn2x@FbY z(748AH0Fjz28z*)7|n(NAB=f@Cg#U=)bSYAstRy?;DKCOTC!wnYBlc(2!UiM;=%Yr z7^1X3N5aOL1(OJ!z1GBJOLSL;23BS1i-V*7U_?eNXw_nnISklqZ{K5h4ZyX*q6Z1z``R2WtGT2#RTv&yA?-K$3F|r;)fNV zR=lQ2cYU)@W3L1eCM2OOWCQpwVN)yuRQw_%!f}U@Gx) zH)P9JR0&ykMJR}BjOcotP_l^dc9+qm_k)v#^91_>ewX{YJkjag0N^EqUW*NyZAu1c z%xQBR=&tOV-VUoI(4m9h=S+PYA9tW{274TvfPH=+-1M8`ykrH z3ryx$zsmR-jDhH!o&b430LO*k4+Y(kbdE#N67Z({(bK-IYyGE>hU{LaGyYG&X&Owi zJG?rGs6mm%a8hg1Six1RG3!QH=~-5jb0av#J1{EKcA__^)aJO+Vdmpj7k4nC=1nd; zMo64Du+lG8X%E9Vl-Q2iG{9v_=J!TyEXX429oiT)e>X?HMM$wYu2y|)@d__*vlRN{ zI!v+-4j$7WVo-$nU??Dn5iacvd%LV0OWVUqlz$Amc)Qk*=6Ed!buTN%n6wxUr?ea^ zdLvAMAZEkEbYGbjv@iBN_`j&0{oLIB3{QCp%HVqxr#m}$lf?_ck*6Xc^tUN_;-FL$ z#T3b8iOE8AkYoi^3ul{086*Ov70Te=rf z^FcgFjg_U|MqJv{#d%drZ0e6^j(O^ga36_69KE4O? zc%}5Ma+&;KB|g44gpd7gd`REfxwG&}jd?EM2zw);kXQW2^nvDDpkGvM_Ta&R#tpaK z)`4wX8YeE=yXx4f4r7E8(8Tq(UPD*wwfCa-T|;y@haS8}?vOp9`2Q4}JBuzNTNjWq zPaTnu=pAT}&1}NNy$9-V00vnZ)?f$^FWyz1uddRgNmRknv5- z1ArbbV%Mx-mfT0Km5=b5GhA+8|1X2$vZti}O7>iG?kM}ZIe_5&6m_OthsCA;l&k4< zsk#JVbiw3BqJ}_g?6qz(8tfHl=^E0N?d8Mx3DP4rP$u#RB+ z&LbiOUC1r8%2=_~s6}&0ls2HUXYmKi{Mt<1h&dwA(tB9enlajpV10GDiFRP%RI~Yw zkH{a=e_eOoiN-*}SB+)MgDs2K<$vLN?=RfXo-Pe8H zdkSOuDyXWRnxWdYqLafH?o7LgM6B`YtXjLtU^l*tIp9l1lcTMp%eG&;en?RThgXkM<9XHJzHtf5fjQcksP_ zRC`i(klb0ZM6UM){H6>9Ec|r7tsODsd&pOkP&2DfguJxnik64rlb>!uUnExlldj*y z?JET_bA{3u&q*fgFgv~BMwC^kM{C?&8i;k1sckuUGAI>f%LF$mrC2QdH4ad;abTb* zSTIYC=Ky@opFoq9q|h}^4FWP2u{nz4BXDS-`AAJriM2y0oFRt}%00n;sLN_{7zyjG z#4}Q@Mm17u)7^NZfwZS|KBqb^^E$?7lS}wp$@J8p<`0iYHbVwy+`D#>(RU`~$mB4nYT6-ZnP8e%JD8 zDFv7weS436Hs4zEbuWer)`p-e}0me_qU@GIp`=&wu2Y;9`5P)wL468V>^`th6oVnh3^OKx*| zIkie6QSWz1L=wHmD3Pl5=~t3*4DMD*WWH_w&6{y_Fvp-Bx$X<-ZCF503Nptqy}2~r z61E%PXbIg6YDwzx(!^aBULdA>R)L?WqdV$3Hg>R9Zoy_rg*}&YC|dP z_2?H&b7x(UL>J3ME5HBfw|p4-UQWy(a;FVuuakc?uq?l*1EM$XqO)4=bvT_aU#8V= zmMH=S@)Lf(4#0R$`e-|e&FE}5n$?bisBfTx!kPixH?}*%z)hk!r-|s@`b>GrYpb=OR^ zxW!sbM8z72+SsgW)kE2doXYH<6t`}Y{jrn{d0J^88i@X{3rQEbVWhDEG|;8%hz~Kn z3{o0;*0)4>RuY_IaO?KDxnDHnqCco1cw7HD7Kju6^uaf`z0WE!XeuF$V zepw1V+h#;}I>wXAmi)Ud7|sTTKB-taG&9zpL?uMrsk1o^d6hybX)R@g7i~fX%N}#O z)MjHM?l3zY7`I4n%3%ft=ei)Z(Djy&sDejB7 zC35x_Xw~(h?y(+d&_UF^{WTjnr%4hN&8t_)z$?W-kg2*1!ab-b6rcQd(S#(BmOtPx3R#BQ^3JzGex!gNd9smM|wOj+iZ-2&5cE zlNq9lX^mayh%FLy`M@j%3# z%R&9R8g1n~$+R=4LP3K0<&Xjbj?&GX)}i&g5%5F&UT4wR0!+J=Wpuh-#b5rixF4;C z;;JuMEZIEMSus-ESjpFg0=QTUVkC;6reh*>PX04g;YwC1WQv^GOc9`SXQY_re0g&@ z|6bf24j>Z`hjiW``rlI~i^c(BCEZT+u`WJ4&VGS;75pYQ-AStK2BGHvi?SQtDM;BM z8piMRvp&XyEt`ADPR4ksSSb+UO6e%0|qpf3$z&h% z9>>2{;r|Q&ORhrvc)y9W4?*i+)M7wgKU{Ohh&=&m=2l`hLc|Uo)mng*Bntjrqqd7w zo&KMi3_2V%bl=igpGJ#Ql&MPSZ%1edrT*~`iMWzp4&i-rA=mbu@t^VcoVxD1I}Bib zvTZ9?uYBOzYfrJFw(+$Iw2)~`M!m>p?`FPGs{EM2K}P_RR3I_PJhh+@i7^y(RjZzQn5;(KDl^{2+(t9v!H;fXdoVyiT;-lA^W#)9 zwc^H`42Ro&e=k3SJ!w7rA|{(zfUV3BG+ufk3nFo$_uE5v#7!I@(-st#zTOWc_y}qW zU{r+luSZ~Xezp*nH|ht?_?tdFQAQ=#@i(2h@y6xT!0%DW29}I+VspTR;YEiIUG{@= zpj`6Jwt3x#H~J22zkk8pCG#WPaDR1RZ2sJ&EuJv6{sGra3eg?r8SdvCf7Yzag1`(Y z$*3%d5p%78b)!7sFQ1e$lrRAfCn%rEn5GkWo83$=R&(gtPFJmNBI}jwxrKK%f86) z*w^lsLM_@(BGnLlRu>8Q7$^Ob1j|&^v z2qQ3&3GbH<4Qt%O$+y-(vxK8SenPhJFLuX5nQP`|qj_JKCE(88o3>j>x{J5*cYf-! z%ZyQL%!L+zg_2-oM#`CW9y@l5;VZ8i`L+G=a5%fgyE5#>CbW`)G&wBhe#!A4uriTc zR>XEV2a0qqq?G4=iF?Yn48S-3jIBZ$Z3cMT@tSu!Ney7w)DVeBnVI1_LkM%#I?^OD z;T}K62%;WMcsul{PQ;qRah}*oT-e5y6@ny6^la{^RX`c2E&i{wAZYnYuP!!6gY9ig zR}AH5kIt{A`%9%Fn8(F(D9EfE{{{cZ@yjn)6>TvC-D=UmqQoF5HKv&7;K3{I{JqHK zN)&uS=F9;(q=sa-=8kVzzI4{i+0J}?`ryd40d)E&dx}Ft`}b}?!2Pkz|Bg|Lqzvao ze55lfbTSUHEk;&p%75(Hwth`@?xK}~J&Rzb)GKT|^lsZ*7DAWATeIvUE6yj&p!>dL z5i_TQ>>)c>0yUVhW%LbCX4qJkW{J4DT*7L>(48wFSc-5>{e=G*=>=GT-WoxtbjpG@ z+6zIaE-?Em%1A7@SuK;x#0yW~ItwX}OjSvH(}_HEWQ?T^3;P_PB3fC|a!%Gi{XQ*( zF~2y_Bes%NHqX2f4}_gCy+B7K7R(;d>uki!@8W;4b>~hqW`ODRfGQ z#t$U)CYy6kfdP{)Uc-=OwU6wPq1ls+md>^m`8O~sP|6maKp*m{LcutynJP;mRiZG-{bv)SJw@y_guj+UXje z<8fkYy4I`}%fZn}XfP~~%E6cU2ps1&bk`pawx!;%h574AR->wztsj)1_ z@&Bm&dwRzc&@rH#&jh+N*0v;TzV03j8=Sq042#x~8H3DfvU~*Xvf%$EnZ|560lLD1 z{lAWvLo7Stl!eutJd;@4C^T}W1Rvc@l&-#jOBGmokHbAY=r*h5kVaCW8%h&MsCCh7 z(rFS)H4)5b^`MuI|Exa{aG1cz6m`#CT8PEGk*lsk%;~s|e{tvDy%!3h$`wc1u*2=# zy!j~Wm4Eb3LZ>HAV+BnUa#=2^QOf0RvOw>!8e}YM$XXl@HR(Z6srl%AfH~q40tR5u zc0)l8UKrU@CRLnMQ7`v;nSam8xiRP<5~!*mPd{FMU9brqh;e=aJrz$&05#_YEtmy1 zhjh&Y?mI@>D-1G>Amby_08_@i0iua8^T}v8&gm3yAuI&UXPsNn{F5e*ShXT(l{|^B2y>ul|j|P<+MaQ(hHVME#@18xEuv&9NSMKSBgcb3W>X}yM4XVGl2F5Uj>AE z3;%w{%+XeqMa0geH4!Ubn z#OhbBN@-@R4s!+ay0%K(6EY_xl2V9ZxQI$6bq<94dOK4tmD?Os4y-+|Pb`JhRadp& z=(IUn2iv`XBxqhU?d&($&!R8Nf~eO6mUUaLwL-$}2n4H;kOk!yeaxuuIwB7?7+fz|g$yi47SdCC18K}J#wV>+P)Xg1H!c`9 zVP%?$D!H1Rjs^$xTM~&)yryGw$32@j-^BlD&-U$C7?ij`<&n|B6FYWX$jZ6#)j^e9 zI*r(DHRc}fN&e!Y7+GHYA^9x#cA5W!vuwxvQyYy2&PQbBxAFF{w+Zwz{+3k;eT?m} z=jc+OLwe?sZrJnA4kk*e)o~H{Q8}j2LSW3{F-4gyY0uL2q&~N)maoDfA=V*)BSI_$}4#PF+EjjY2UfC9PUnXU$+*zM#C7KZ3MuM zdCofYnHt{xKngtdd)@qPnBgoEKX`G&L(=*&E`lxu-Bju#72`U4#?27B!r{=Bg%(dj>0>m4AaAyN>{B)JUZh4h<9)EW!M5G+>sV0K-@u8NW(-Mg;;r< zC^2YTl%kC%1f1l42=>rBGa12AX{2VGN&Qa*bHRq=6w*f)LhH?sXw%j=FA)++`eohL zvsdwE5;*D^FV_TR_WZe?7Ks3$qpT1DA!gaM9dZ?t)dH_Z( ziO}fU%s!>SorNJZ6D9^U3t-d&&>|d1a*jj9k*hCHiTtZ7aiTTPhGr%y+L;H!A<(fi zri3d{YHjN;widI+kkwT9eAeN&)^s+<(3nlB-riM;K%LN2({z=l<6aPHr`>2&_9`su zz(=}h#MItHUj*EdyQ4PEpYEa!02hC#n zaAfJtpE^c4otIv8Uaauo{y%9S&a3rqPg`?@Mc2$rffmP)yd#>9i+uKwvJD41$wj_$TjJaQ;H z*56}Rqemgs*)tQm@60I8NPdItQ%oJQRg1QV3W)2#^>s)}*p|}Sud>fD{{n|Df{Ysa zJvrz=z*hh-f{~3f5Z&hhLs*H#4jc(BOcZ|r#3{gPjlw$o$j9$Dw07#ti1EP_2OJ#) z^@xv#HndodPx3kbmYc7;&X>+4jWlmMb9zbO$dN0_{K`JlqTTH&7n5-6ciwQnNt ziQi#eIB&6*B`up;vbFF$j!BK-z1fMxiTCEF?|IGwQep9#V9-BZe~--+toe_h^eFU@ zHQ(hVtCYix`6-O`h6-adSrt;=U_hwQVg>vH(@Hq4!oh^GARGCYj%?a=8K5PZqPSqB zBsMs8e#`3B+h-K5PK&u{vD&_o{lz7^NT9!CFcwqIvzd~CaLDFI_fw}@>41`n*`<^{ z$&bTUJex3hz3x0Xrdo{XW8UQWagKl6SHNL#g7Bv*ph^lesNo3fw}#8fw7ZZxgnwWIg5 z&$9uQ3=aSqhqQhQtwurFbvez3dfD!Wf+3D^i}|MyUT}d4 z>@iOrX=$iVDq8!>%wdXv{SOuEk_gUeMhT2?2~m{)SkD{2!G0Oqp_0oJcYqbt^b=a)ASlaKhw7ch_L*Z4P|GKWNt0-4X zRI+F~Y4>GHMUNF^5qHQsOfZf@y3Orj{!n?VJWeBYMpyx0{&HzX_0RHK^UAZ9EQ+YH zp0a3XXZg0pYv-qp#(2K1_w^k5dwQgH&obsq<(?JmeCQWf%7ak*y=~dtrL88NJ6oRi zN}E<8v*`6=mvc4FX9|AjMR1RtEkp1+OHiXm@0Eo}Km~Nvgpi!waf`KJ~U8U>ts0YO-E>Y{|@rK?WA5u6qMChDiZqsT0sz+0&yfN2CM z?I&0951hEaCRjka?Z^E64vutEd2dcIm-cMHDIK z{(3|^XZC13V09W?$!Nr1#1vCb9|@P!p|H7V^SWB&rH)RI8T3iily6Fe(>_-+$v?$k zl}VA^#a~gZK7c#_J7BUlXuy?f2_uo1v6@zDPZyDDJIHkv;tWI2eI^Dy4z)2M(5wwp z9LRqzYPgwcKmm~A@eO&f`ocAmTPyvJRxX5PY=#5?CYoR3{znVs2w>_9F4)+Lu`39> zv)Am|b0stU{>v|$iL>oA$}nOhZhlG`2u6zrqd|5b&%f(iFt!jrR6W$wpXhQ;?`zj8 zpwu=z-TyZ8TXySMt}8z5PoUrwj_MEVq8i0-VP_;Mre>4nPu`EgV>ji=iW%nooKc zkQ(e{SCz@Ok&Y7KT8XuV6e>k%azPLVYi|)PB=h=^6E%Z!A)ljX3)X-RE}*BcxfFg2 zzQIQn4>Y@M1VJVwd(@0l&iO>XCmdUga7GajHEWX(@_Qkft;T>?PsWrMhB}&a0*sm29j%ephSZ?0<8I-}O2Q#qVtC-1*e!jDYvAbYoOzkSOV@;LWK zng2ZsgAyT{(OC87Ha`-_HxN_On$ZKmSIe-I^U-h3O)Uft%pslZJkkM?GZ9B1cr#;^ z46^-nf^q?#-%d{>;?*jt2x(58$~om+VofIRyTFjHmx<`{{G_q&LP1Sn`(WRI4-3M^yA94Jj;WZ=-U{S^@2i|QigG|SL#DDO3VH=1|N@M5p zm2r_=s`(pzE)4%ro(V_>5S)%k*I6O zj^nJlJbtYj916x(zTE>82mvd+*Di#qeP1Q{-vxjS~MNuscy13>d31Uq+jr zgt$ud>`=_%N${2i1q?X>hCUcwQtTA~AnGycJ)#$)(R7HfjCeO3+Q=weG7)7=g@Ef& z0dsGA?!G>9k5N~}sTF6FMl1gV)C|=Yslsyd`}~KslU;oGCqw7$nj6MF%!A{PMSw!e z9R>r-7%Ua$O1s_dX3=l)d7dxuJxemo^zySvZqI?n|HeIww}pMpo_!n`Zzm#sb4w5m z$0aSPntzPc76LLs4`(}LqN3v{)4(8OsxymVu1Pu#>+c>aXN7p;j&xh9SMJ zQ)^UOB$%~siY0rxxC8)`Wx`s4_+-+{m2ydPc%WPDayZohFWBb7L; z3Gx!LdLzlOGiixpk7F%pBv-eL6+do*@;7GP#8pI*FU*;=pBiieF}U> zT4%{45}nu5U4s%9iLxmY&H#9w%%i-BqQF9+f7FUpiHe%nENT5X@=DDjg^?yrYdwO( zwZh$-C=g6Z7sDuo;UG5rT8RQE(kOj|o;dnJR`WkSf6tz^ZX6GVxHvYiL+lGge0%mB zVV3bL8WBSr^`w(?6J&0ZjuyX zPaGx5}+ssuu1~cOBb@dTTJ# zQO1n!J)E*fe7+6*t8XFdf9mMP7uWncyHXE3D+%X3?Z+bQTA>s>`%$B0SEoJ!Qn0p}> zrTr*eKn=izImJrlv*fG!Jj4AKA%YeY%29$Avw~CfS7?y%+x3-pu15^iPr5WUT+aRZ zv!53;KKFDq(x?+w8%sWQ{qryQj2@c@BU?N|z2=M1`N%_c?Rd*6nkT?kS`gW~K$dJ_ zibLdLGBZLP*t}wtY4ny%K}Z`5Uq9UNZjDF^D_$xJ85_v0Lc3}6I7gc!cm#h#_W&Q1 z22QtxZbjqRbDy+D^u_i3n7)#3UVYOVj$p6`b@;J)4 zVNU^*W{SVbX2TIL+AXoOkN)j}^Hz3%Q={tNw&y{vW58j9_m+Ve1;(mG*Wds6wa3@* z8g0*IbSjljWlUx&L+ONEWN{1tDVN2J1~Hm;s^yvO!|-cTm42YBn;YJ_Wx;>>WLC9X z=QY^1&U#M$2=HE7FJ6r9_gbwW&k<(H0APyqS241^WQAxySw_DX&9CcLkIqJHxRA8X zA+tpL$Zpi?aV_g{qEJL?VX_;fBN{CL3AJ zZC&eE?9k25J6e5z`x8u{T*Qb?K?i!}l$iFQR3M6fA8I@bQsrQ0|0n^wxP-u1ge}Sax zpZocTue<4{U?yP~%JoC@#%72DF_Yf}Y=m`=zj1h|LnSrpH9l_SG8O^g@7fGHvwJQJ zc`)&y1u(n+XN;HIvgO{*o6l_COwOl8oxdYqt(Pb;jND#PsKpA=M_@Xzz|6mZS=2e? z*(0b=WNN_;WWgrrdTvHz6f+GX&IB`NkR}e0J{PUtBSD-vqckSRYJE~}NJ$}jx^#HH z?g?nNIK|co#!5K3^`KTbiQL4&tOKG**(cYM{Q|!h>(LJAg(t%E1j51)j*UJ3g92~7#CEgJQn?8jYWIm{<2I z@`56;%o$)g?MD0zwE|HF0o^vTV#hKjA=*WmXW3Rp129vxlWd)!pHag=8$+h5me6%= zVnOGsYDJqtU_n@X`XYk0rLU(an{CF>H2s`7&Uir+T5k9k=CKTw+j2T)1?Gk#$y&!? zxU-G(c^x{JRD&*hjoH7>P9lQG!TmQ4;F%5Z^{ zGwrmjzJb5#jvH^hO9cz7p0>QdN4)QX3$9?NvtOxS++~rcc z&8l%Bs}M`lmJDnLoP5reM;vYcK*W-KFvX#DG+#uSLH zm#KA;Y6+SV%gJIYXj4Q8&O*or6Bf%8Ez}67Xkrtb2%Ch1kC=!a;QyadV-vd|+z5+c zn;SJ^=7MiXA_jZN4K+h1RgElM;IDQCW+!LOJ67!AI zCDzG51woCc4)9;U_|i+`iG=;H|&wgfa_B_(V{fy(^qexhh0tOjpn~&#y zMm6iwXMYX;X*2()eYDeB7S;wn#_9j~P{wYO=z$V=A5uq#($)YL{BLs_o4%4RJ@RH6 zlTJx}1Qe=?5crW>PsFXwrKPs1o*mSU5PK7!ehy<8f6DCS`Jepcd)=4TPMtbM#xCW* z!hikPg%?H=Q5!|)3j=QdWPh++s%5evt5UxKYe8fd` zwb)f=y{U?sqB6k-P~OfL*>AEDo^K+pY)$2@m8-@Br*Fl`}VEHa3Bfm zDP{w&eluL^;GoMP&z87YhZ6&ywWe9^Mc<2;@ptS|Oz&8Wpj*1NXHdEm!zh%U(mi6G zUTqFLL(s}0z})RcSJ1A%o_S3mD}drAVFmu)UAf&29 zFQ|A%CKYQn$RGv*$?VpzH>?0-iIwWi#fJz-L}Yc0ue)1evQXOtIc{w04AG+pZv& zqUK!ZR@WmtY#fE2kzqAAB7kg(u4&yP(ghYwxv)WaM_QrAg8rhZ4wNoG1xQM?f1(+x zG$NHcv6T|z1VXWpsL?H*V(RI)jT3+7O}!`g?spUxv(p-i+I7Gul%xAQxAdT|Uy%;P z!mhAft(Rv9l5^E2i$g;U{PLnapWmcIV85}LVZrLIb()B4jmbK_3ahWhfKXPe4S3~H z-Gd?s-zU%yy^(+&L%wB_P*-S1SroGhR8Hn=D^Y`y$S=wJU_c4eW9AwI zfYeQ(&%sK>65{FcR4{beUP-ox)8(JRJZ|8!gFfKDUV?&sRsbxzk% zuhR~=+hEc`YFZVDYBUdz-y`fn%%inx44~PH^Fy=RB_X@Z2}&|^??zf)lwJPZtv4r2 zrMtPSW)CLhYPlghw)8gsg%~EOnYy}B-IwReddP1^J|JJ`-oS#wg@{=WFqI0Nd9+%1Q-~H8x)Wiai4O1y zk0yr-5ai!Z7A>K?WZ9wOoc`%9saC5=*QO2gUneuVhDPHU-6?bTO`Atvy?5{W-gch? zl3t10^i`mPO2t15VcHBMQ+kptd~p&{8CXDf<0-M|z-8QH#ed^b3549uD(H^ri}61c zAEUkMk+b)L=Ufp~;Qg3}M<@8^VA)o-Y;9Rwn=wQxGf7!Aixl&WB@^`8L?$*DX8g%0 z;}oUhjN2fm13l6t!e(O(Ndy>~s5QhWFyC2E!AT=CJjhIIBc&-@Dx|g)aiYj1g`Vox zu%4XKM`+~;&b$O)RciWgdNBlCZ;Bl&HHi}Ea&dF1#1jbFci1i$bVS%p@tGXGOok&-Ua z>#g-wta5bH5i)+-TgCgYu9S+g$pk<7^?8c z%p8~JXsK0i)f-A`hwI6d6j&i-QB7cOqTim7-|(+xSgSJ?=Gu#DgGQ4m7oCnsFo13g zbv6=p=P+XD$JeqZgBO0DU%|h-a_!pfLPD3A*3+?L&6>UBm6O~~pmxCMA1d+}_)(=& zn+zJAp+Ih%Web$!8JCZ%FtYOW!6;f-<)OarGJJ`c+|O;^fAz{~-MwC^MxhGy_T;-e z+alm+OVS+X-qzO@MeaMku;F^n0tsAv^-gC;Y z=kCW;DPNk{33<1$ZOy!J5)TrrrC9j;&6iHN9lFWQK%t@7FVt1o$Hu=&h;Q-2dC4qP ztKorVX3S8b!`_l$r>Z5vd^rGx9Z4wJ>Tb(-_s!I34azMmXY_eYrdb@-@6B!S#d5Zo z6$5bW8nZc{U0ljXqPC>n>w!)oRJ%MLpB`-OFZ16IO57f+3FnrJ; zSEkfLJz~cCTc;0#f{t>GNHVnaaswiCI2eFN$WbartwY0h!KH$cI+7PEry6^r*=-S1|Vdh!PSS10c2eM~6O#GxXXb)fsB1KDFMd#6(vbF@d^{Av zlg(4nbdB_( z3%EzSET$jIzx#Rz|8y}DTBn1%TpRI=P=h{^Gh3$3@w=f{fDI&&hRH?b5O!erG5*J( z>iPpQs~$uYwm7S&U*)s7oO|{hXO8sd?1(f!{&e|RX9@K~Hm=((3imYw}S-Xwi@Z8L0z=OEGE->QLu6lsSAVIdPt?rpsAo6O>DUst&l<`SJ>=H^jFxbMzS_x z4}@LCjl@R4IAe>NI8fb={|DKA(q%S_1!#l$OcFXKKm4{nk?u`RODApKBG;aqR&2F@ z>o-)7lm*3){}Q>!<-xssZ{lCvvv1!4jaZ?St-4{?x^;)ysx;!W zx%0W!tUDFTXFBrvQn1yVjc4*I6DnLlY56Th{>w?o;PnSxH8Q(+(b*Qao3vz3FxPVY zhZX+Mj-r!goVGy0PNWrrJ`4%s@q5@e(Th;m;YuJw-j7u+2S!PV-A$J5AxnUkBU`SI z29&a74(V-Wpu44Fn0}mw`Y`0ZWEW!f`VE>~RTSTw5U%tb+_nzYH06B}oml^u{x}*s z0()ohoRUX)Mxfeq(J9wSfH_{T^e|5$rC4BZVtWo&sya&E?#b|gfnPow-}f49f( zSv=yhKo8sk1rV7|2W2>YFqI5BFz_uHi-+BSX!zBj&h6iy@k#;vK}7xKmRieFIsi4B@`ZgnPn zslfO)Y`BC8p1*IO8MM*j!=P@uln)EP?o9`>F`HQ`H>c2&6d_#JT*?QE{&bNa%oLe1y25|87HtR-p{ga%TL~*HEqsX++``v@H%tdUzp>>cbhZ0V zknNWu{=1yUe{0B!b?8&x0JInt-?mo9GqVFya{V>N+Dpu$X+)>NTCQI`hZU_{$}ALJ zMvhMn3@7+q^=N#GFkHj%OoByT;n)iy1wH>l5K(G$y7)Q2Sa^ooC5&ckdZ_x=P{AmK zpA&m9HO80#Na-ushxoVAgpaZ(2^R?S>d#;>#Sh&9jabF!uZx!QWsJYkiOZF8^5#HS zEu#R$-@z5U-+WG{P>Rm*XEnsdf4>MgL9!dngr~0uS;3pxzyG=CI{)#H>-ix6vmHBj zcq1XJKpTtqMn_Xlf6_rIr!T?lfYJ#$b)DO1&+CjN`5SJ?Z(^L3RrWjDBq>l&l}4pi zRmR*GF;Rh8CWeiBM3}9nMHQeMxz@>+&RXgOIsa0!3p=}G8&lGe<+VEe0El7B3bM4P zfjD3f(T`p?Z0EoZ^@IvpFd}wwQ@x0;cGKZEBg*FY^{`!#Bnk&9jzm8wx_53cfCOQp zLls*;rA1Y^PH6e1x2>5l-}7fP%LcN)=_EIG@;_Rs(*Pl|6_kk>c;spjD3o%e&2Dm5 zxK6cEt=T#>s6RDFq)_VfUd(JDXMQgdX*6zkVa#K}#0;ZBEt2WXZ8@W1k4~EcgPGBA zdgu7_=hB-DA)V8LoQ=5`NFxIH<9F}gvZ@%zSTw0_#n_y7m^K-@D%1v>!&a?Syb}CF zx-L6@t1}o+Bnv*h!ElIga{?Ptip2(X5;_5LX)>t7NKPNQ^idDcOEfvCSqwAIlQ$@^ z`%f^Va8S`SELMtS;(wyBBY_=!7;#?^`C3|Fvn)VIc1Nu>n(!%tD z@7@Y(Pm|5!i+l`9!ajZieAkpksYASVAaN?vG{G*TTctv= z&KYDXMLZjc>qVls6JhA!tEDP+wvb_dDd69Ttm<_~A@yzd0{v!IBD)jGjz4}IXhrX2tbCHO_m?oVY?Y$kywSe0CyRtouSn6@-3!QPTRHaB(^0a=|g_`A)z$~;4 zkJHsMQmY!_P%yjBLtIWGp{n0)B+-F7LMN>wSp3AqIxyM7Yr_mu2Gw9Cnh#h4ZYHfS z2yoMczoB^;ZIu=75lxy=Cu{I6Y4}aG8flebqELfN&_u+WsqV9-fAo?w-EZqz=AB+b zYG~e!^1uB3@6nBU_G$hns61Yx0=%urEg0+&pTBF@J~l5o@Piv~{J~;)T>icBs|tD2 zy7Zm&RZrZ&yvqF>J!YPq$E`CNRA4vgxPQ|;Lkb)6dGtk;ao$?dXETUO;(?Z%T3j{L z)I$bhNu3uBZ+dRkpmBK{6)I|g>$MQUiQ=40s#VcTKZTx$1)1_(9i5wsPB+a9^%3}+ z^z&RHjE}uQ2%#?IA3b>VXebu72vNbp-Zl`$30PF5D+k8*BXmn+oMF;j|pP$PXqAt;yW@c9SsR}gFhX^$1~n|QbkZmkSE z@T)dC8iQO4cQ^tSKpA6pMSVWA!RK(JmzZBBjfZn?r7ITppcU6>w}DOM(z$IOg#O~w zvL_C0DnXe@9qH{Jp4K}p3jTsTFnwrYDp9esNI9;N-M?{p5E}nlcd0TPE-tRrXrz&H zXKyeV3_uLFYV$kEoDp=hDspid+XCFKQ2zo>ACwbO z)DD^|STVEu7!=vE6G2wJDna8WdhVy%iw5_do`AZ~592~ieWBnq=(EjN3X#DC4n%(z z1r+Mljk=?tR6Ll%t=lcMx%tRG8)jT90jv3OJv)pTf@i?E3vnct&~7KSOArnC${SW0 zI|@0G4ilk#v9PsM7mQ_EiVu0bwU*nZx^$GD%O3m^0Y>d;w-NRIC3s#FeQ0g-Y)6>`DI+3TU1zQf@RTPsk_<-?cChsiO)?He#Z@#&c{@!wVp}$2vBe zT)8o*MKJqTx-)oE*d<{DEnG2*tg+4@ijo)ji|)Vk&L@%7LB@Zx zD-lRse)(s}ulW^UzvGUtk#GIr=9|Abe!C}~33XsB~L zo|)4>WXsAiCnFY@m@uEVOJ9stfN{zA7fRpp^tJV7F|nB9DQ(d9eS(#=_z)|tYqkViR&$-i46zvvA_wq3;hY$wtDLXy*YxG3S=i6e?zdo!p`BjD0!XVe&(i| z0y%G=2_<^@=&Dug6Ok-;=FG$78Gg?_pZ@fNDYx| z-1w$wOk)|sxH5%odR(h?IHpCI1I2~hN@=^>Zz{=`aSMyZg{3uId2MN75$C^E&oU}c z2(3|Qw68A$;vjs0P4O|-n_!PhQ%MKxr7!;D9}vi>J^AGO@AnWj|K5vT{AbBB{G%|R+9@mj0moV`Kx#duc5-Io(_-D4}?!G&>l_=)TyLj@EWxB9(4 zEA37bt-ZZbYv0SP`m9KSW(3)@#RrS!#WSXfFu1JZmx}CaOgdAb{_pj1eM3>V-r+C+ z-;rvTq(_Uz2VaO{vZ*=d@OYn#8Np&sTRmR>Z-$wpW5oby*iLSE0h8n2E29wxdr6ys zZLVY|w3Hz8T7Hk>c`?ig`w7NPP;4kEC~%CmY^yC9CGB&;f1OXtMQWAn+V_?mWH<^0 zhCB>DT-1d9M4y8W3~8uC$#aa;zx|x|rMj*!0i07Nf zdh%T3TGK=c*IT&UA3xvq$|FMm|L9$tA`>jQ)w-)?@BI0__deb|{^QO^@4D;x=l}4B zF3imN*UziB+;U6T>C>mL6k1$8@uZy&g=Hdh(jzqzYxPBG(OojPIOph>9=&`{aW4PE zq0&9~KuJS1GIHUZITs4Qle=m2$VbpwD+6^i1EN!@iV~E~c-lQ8!aaBdIZ&j<-$JKs zod7P>gC;Ex*2zbEBsY`k2f7M@1*dg`E(n*}sK?&=*`pjvqRY4Ib&Qu~poX z*Y&Ft)E?;JTz0Ex*RDg1=SS|8qmpE;VyQ7P z_?gq&X@j#P6t0omnGp1#^MIJgoS6b9K9444vk<4mw>RvKgrXzI_ z&GQ8KcYegbe-W8|ius_7h5sF8iwHtF3Z2}jEg_AC447vdn;8Yrw z4vkJCcE!^}{6ez(VhGfUnKG~ei%2I&5karOWUFYg=y51C0IygvIl%whB~ys?dOh^d zO=U7`==2)=!t9}T%x}J(HNrdAr%%+?cXv1cTjH*NUe135y~c@nT-Y!+T<~=6j$q2zfdiKwAw~X2_}tS; zc69J|@)ceLYQWol1!pIZW}8-1KrBt0}%IJZ5xiHZg} z_|3YT(GnOO;WxUpjTCD#^g~xo-R2l6fXWF_s&G&0BU#CM{>9x?!7W_RjnjP{Wl+ft zI+Ne!byi>Na(J9B6kp|BJ{7&^F>1TdyssrT{x1@X3uC$7`K?m)xtjru$)0&QludOw z91hp!%@>dxUVH7ehd0v1CyDgOhX!JUcwDRlq62o_^W3{l^wI_bz7DG4YNgKS4F>ri zVy5tU5ln{x04w%a%Y!*gI5g#E<}!G5Qf0-RE7)>26CN7u>L_Nw6qUZtJ&X%mCMH|K7PHuOE<}-9yIH_8egYnPo4~=MIuF!W^if=AY6~2)D4U;-R`HrhlbhxA zxfnYe@Gw?0Q)gr~I^>$ftY&;)hd(Bh*Gb6i+?znlLlana-Ec8ewu*g@AE&@r7vDvG z(8b5d1|Pp3y2qGb@+t&FUi}qwa{OG~!nnl`kohR{(>^H_2xJ?-d+Lg6v3LW2St?4p zmo2+u@!}6Sj`=b73S=Ig0+ApRs8AuH56iFMoYQ*Pw-GmYq1(~{T(JzSXK~Bw+HBO0 z7vKypqQnpA5mu5+P}H7c{2An!IpQudWhXIV$O44&X&HbKfleOdA|B|)f~Alzkdh0f zAp%A})w-%J&!1Wz|I9rjxz&Y3hYG86BL`>A`f&AX z#>~A`;QwtAgT0VO=yQ$TIq zP7(~0D8~B`V}{Amhx9~@Z$zjUS<&jMlhCD2L|CW@x2DP1YzE|~Nk>Y*5+?W1n4?aM znUv(iFhC*6Kvl9)C80}+3T03@g4CT-gVAuST=UNcur^7%$?e*Egx2PbM{CuRV-80daQE+w)zG1y;+dOr(5>69BsK7T@Qil z$t5?E2x%Y zn0(V0uACXu1|#nlurhK^rBq)X^2b|)7_g;~h7;*_zU@))M_za`JZI)gyh1a(ua?x< z9PUVWZ>LJ5khWK=xk$M?BT`EAOrcat1;SpF<$dsA#c~Yp{55V3`~2VT*H~G}}mrn5vJ@VY$odTjN(V$fp;(u|S_CRl60aERtgeOhNA7}UhP!BoHl#YaM}2-b3Nw1B`+9vbFNUrljxiCr-4+NGQ&E>f zCDpkKs-WM_|H0+;SPgO`%(9Lq|>u4B!^_dgO0zU^z2dR<+Q{I5)Sn z*HYJ>B$r)Bu3~LOf(AY)Ey90af8_~g9fYH-)G?p_6uF!|MXtCSq8}62Yl?>!OtrB4 zQ%nulygov^i@=J)wnir(ZeFENe$+xSndXtP(gQ)i5wgN5o$2@)8T23cjWpt=ZUu9h zfRRVZr}@V&+`s=S6{=o}(cU4fuQd*hwDm@>H*R-3O`UqP%49YY_r)Nm={k>7wSB&l*j4NwQDREpVMa5f)!)nPlladlP(&HW@8woX?3~vUX9gc z*5-6lxi_vf0Y;66T#LyS{Jxuh-bJqH_`9AV7Up^GDegT-$uAcB^lFW?fN)j*KipHN z^Mzb4*j_9+y>Ux8Y z`B<4;H~td1!CH;kWC&YyW`wfN;P z85HswdbCRPHPpj3k-!PYN4@jv%2UnH zHz`w%PB^fH^&Gk|Bv>IT`bp#Gdr_~gZi3z7OhRIk0QxSxTrj7ZgC^3ADZ!@*3Ac)S^%L_sR4tFPQh8H+0aE_CP zy1w*Hi%oAR&~5Z&A~-Ha@z?$%PibbhlWG)$h3MvaY*3Keha;EHM$* z+fE)?$~za#-9Rh)npLB7!`?ZA%fVsPt{EBe6Vd9g0ahko-Y?#Loe*(EJ&`)a=8B_- zs6Bn53q7TbWN8;7CY4e6@3~HN3F%nP$1hi4fte@{foOC z5lbrrzReYoc*`msHXGVBU4Erju4UCmh1I0c%8gdrjRhUXpqs+xuw0MC+a8HJOg6Rc z!||KK(*|Zj3_v?DG^4e3{`?^ZRciT)u|>E>F7j3WPNM{)Y|y!)kw^@>9PvcD!YY&D zP=Fp3Pl#E`Jy$&2f_dkp0!>`7IOI7x`-Xf}d~RDlf0Z-Y+m#Pj{5`Yei0_FtY)QwB z9(|&t!);G;y(!g<&+b&qrX>Bp^18*5kL%f1I{~%U-`5MI)#=yd8=C4MGeO zIsa_VXLcF+Ey$b&_!%(LxK|}7a)T0cDlL{Q=~I}1mQoyn<^W%Vep^e68Xm|G=Gu;y z%UZf>xnpDlBwEo4y=E&}CE89_EMqPv`%e5H%H9J`uCiuy>2uLUN9zdyzAXNkf6^QWatJD{fH!p&sfG>(Dej+G)_^#)i znca>0{eJ)dY$jV~c6RqX&vTdSzV7QLd$3%wkjEaM^hAU zuQ)J)!TDC+EeLkRnGRAa#X3?#HIzt=Sj3o1d6RdZ^VRPtJ zrjT#rvan~)>072aR2sgX-m_ttCqX7JZolu?v2T-aK7Qkk-w?aS#g802_9Eb5t&&{x z#NBs4O^lF;t;X%KO1g-zUK?-*g7FCEI`0jJrgRr#ot5$y@e8jYXml1ckPNpYVltyz zs8$>GLS7BEhH#daB*7L+%v(4cgQiUJq1E%F&tVjWnmkvYUs_f!FDuP2l~5Tp$ss(4$ zYC#Y9ILy4&^O-s98nSTtVy42aT*{2hWc&)+nM5lI(|To&PCKB$aT+^Ebg>)%R5Lhv z{pd1HU`hZxnh1PK>S=fe4Km;lr9dN$_hYHYL^J|NlU94LQ6uW|7-4tHjbh4FL*tjF zhO(PF6p1(!*>u#Z(l~t4R47hH#dqejem@2g8jaOpXoXAYq2T98AQTmi{bWzGd0QW* zZIeB>i8qVC+Pr=H0jZhd*0o_z5RGE{nNP$wL7ZSK0`#HH4&It{MdJxSZ?ouZMuT4Y z3%ET@Zv%cJVCZ3}w0!oQJh*$t+R|m~UrU?JtQzqN=k*OgC~htk$h!5o-FP}~%o3`x z^sz_E7xLa7om#6RiaLtwYRn;e6q*_d;6hI6Y``145Xuo)G+}qceN7I9W%@#{R zr&4)cJk-_IVZ{8(j-I|Xx$eb_mYR?e&K#N1Q63qYq=b0yjCs>)1`{Dyi)Z!`OK-3E zrzgap9yoLeX+l_9v0%a1wd1T^yACr?4NH*ImIn^*fhc~tL_3g-Tp*o}fVWTx#tQ|n z4KOR8$u4m%86J*+l%h}e^>%gk^oD>hYK5NaB-Gxx&&Ah!E1w)a%6MoiG)2Bbbp26{yIq2Id+EcPmRtpOAzR~_ESEMPa0d0WUFNE?h?win%E^uMF%ZMc%` z+QFDJu_oz=R%GSLfO6h zB675hWi%Ocef_gTAv7*%`DV2k22oDui9}sO$mg;;TqeK4Ww-0ll+o0>^)7U`SnNs@ z+ItNan>C-!dQ%n`@7YtjYXtF_QhlPc@I7cDa>~7TmG+Rmbeh%|5X8_Rn+JS`fq)Ka zPReI=q!w&#=*zdj)i+2r{cx*$u!dY>q}hW~{(ST|ETp{-iAo`x;$m#A#N;Cwy^WqZ zk}gx_XAN7-kX#fP8ZGOifQQ*zt+P7O#)7sFkZhdPA`b;=W#Y&Scq$$bcSs9I$P}b| zdkr1ZvOC8}NbT5`yi6YM6_5X}f$O`xx~g9_JGE`w1*}2bOl~NPFOhPF@9pcghizVSQ0eje ztQnIJ3PwEI)W!3~4;zj5f5I{2(;`x;3VKYPeey9I+vVxHaUDg*?*7(!{pM7&pC_T!d`fUIrJ5#g_%r9eE&_{ zhXXM##z|R1GOJIOj3fo=YMt!M}n=T?o^8C`J+vgY2CKjZp)piCV3TX5Hzq&eUPRz=ISDd@y`5Yd}x}pW>l%DCU`g zgW@A(4(?ZqIAU{}%;$7-|A|)mq*To0gu@PGxi(ka700v| z!Dux>Q3HCy;b1fbTth9yDxE<>QjmYNbCCa20!Q;@Gd!?Z6?87pA=1JzPI{{nJ^y@;H12{{B&fwK-U z%N8LWr)mOd?BrH1ry+>s$grrAE`VgyaOLGykOv)(Rb7n;HnM0n|(r1`I-whBw%O!D<-I^$Yriye%5b z#DYOfO&{<@ZB>?2*}X=yMFUz9kDn=C`TSK^F+_)P(LRGO7#8rm8P%~=#H;gpBQEei z#Y|~+>0rHnu(bMWui)@F15TGqq0l1Ve-OQ6*49LgG8j=qloN%Ve|ocLA6dH}xy3=U zY6Z#*#LJe6KZnXr2MMPjjF=&D1#^JxMFR*|%BN|m7rleNLY9%}%yO7BR_CQLC*H<^ zENPu#C9!JKorakd*P?g6wMP&j(GbW1&?PaR!Hj>@Hm@hgzZ1Y$_8THNIbX$jQL-Rj zX24!xJGyOlH5QHenzkTUf9lf3S3V z3Dxy$Pe1);fNY;K<$5W^gu3gUI!{kAtcYKqkW!z+QR^*-F-~ zU{+xqF&oPe5V0tfy=*mE&aPR>EXgq&)=%X8Po!N)OD3CFDS)IaC@)r=!pl;uGNH{{ zGQ5&Ml;b4&bU6Z&`-XwTw$>LICo*^G<*~fFm?fk2ktK8f2#Un+=;cM-jrH zN`woZ=!p*J;%>j^^wSTL`W7?s7B{aJ5N$vgW4LNFsg3HY5DT~mF{#QGv;fw&x-$-! z+0A*wF7NBTH{Em-`SK6_he9}Dj+Ftgm*Ur2#FyQ{w9CdR4Mu;ckaZjEW)QETTJ{N~ z5mZnW!U6!!aTvQ%x1$O#nuU;hVbps@_eP6e(2cyFfYWW$+l;YjF6OCoYK=W$c43IN zC&c@#0VU#RJqZ6@*aN$EkYtnvFSCRmKALmg;ta6puibrY+Xm?83P3<7Kp6D_TvHc4+3-0F$)QE{T|W;&A$ zTS~)WO^JnkoU0Ga3{J&GK-SO@Af^sc4W`^`erua}DQ$tBmuxK}8`jdT(u z4u*7`aDAm*8z)23tDq-jV$-4eBp)az5o1Z9oI21BsaC%JzlZ?7=In3I%*`E`7P=-g zG&m3+EOw{9b;aJjfWti1|3Ylz*8i7u8$1sxyt~9d9y{iAG(Qzz+p=!mB#8J!Sm&M* z28y(}=xeItf7K^XnG((ChDMf6pEi^%6!P`HI>}f20hK6Kr+{^!=B^qn4V4Bytn4h6 zc2WUzy3HH;ezhbNlviEP)yq>NJ&+>3u4P zVD^MIZ$7{*fX!0<9084|Dn0;$1K;zM3cOtAmy@nhqRguic&7yl)0+IyP!326$5l;c zi>-_h6iK;1q@)*Cg^NFeTTxcRu&Yv6f|>NXH3 zT6NhI#+3UHwEUnt@k2-% zvP$t!PV`o3#e-ylBOB;|YbG5S$l_p;ZmJ+yVsvEV={ROTT8;R%SX;)KuzwK24l+4x zRz`4EnL{CfPELc(W`qgXo2(dyYPH+L8n@13&|1uT3=uMWt#&A2+XPu}=~478rNL&I zjh@zH=#r>ja~-*1GX~e5&YU)fl&3+YI36WlP%Ko^m!XITZ|aMX>&ewyFm$@rBr$e` z|4ni;ZrYR+pq>ffo2;seEr4W)zP0ubWnh7SNZ*0|LLq^PyCnQi!j^b=;!CzS6WHZR z*)XexezYZte?4u>7GF5(lrqN;)-PMOmDo30K)NrVy^^E~n^DRz%&zn?(~TCl;1RO0 zmK+=L2VE(L1JENOmyo3&Y0w3v(%Z9^NH_syTs`PldZHA>54Q*-)qt3R#s2YZbc zvl4|^OJ(wmom9^tmr3Q$I%{qvm-jR8R6i(*pFq%nsiNoHS*$n+Tlye&F*GkZ?#_-k zZ+K)SW~vxQ&bi^iJ$sI(6Xb%R!-Gl8RMuGR zPJVrdxWvfY`0SJ>S}y_pox5psU5!KHii8r4KuB-3ngK27f0KK3nPXlF249O@_YTZg z=x8y%C_A_tyswS0JDZwI&Z8~PhspMH(e8};#yII6Z606;XVLP{VNSOXqZtFT#MH)N zXfqxmhiH?tm$HOANW{ow5`Hk>NiM{j^}sSDm)eSuCF@UdARKqesluvA?^}Evl=3T- zj?)g1DK5)Wqahm^GfjMH$Rtq5Om_<1NZ2^oO?Xm8B9Y+BRD~ls<`u^LZ==>WbLj-z+X{YtBdn0Cc8r-@(?{^duT}VU)y=~~;O-_hB zhAprZjNcJ)I_i_AV!j8OMk>>$&)Gh?Y1tzFdfV>Z=i2CmJ2;$7xw?7t9_HzpMjU?i z8I=X%i-VPY`zn}LvEag4xE-2@8@VNdj)tH=u- zR@(?A@FDXu8ruLJ84#MXgjFn9Us{kTS{UnfctNmu9d3|k@sxorKvhPv1vnDtBG0swo1k9!UQfPk;+qf zr^&+$eviknUL365dTVX)weIdsP&|H!qUV2umq({9REVPSJ}j_S{dWN9v=%~bZ4xI< zfGWd!#ZHNF^9}IDC*zo0d_Hp)cj^GS^a5t*0d$_4zOYXdeTmiDZyNFzr9;ES1Q*xy=WRmOm(&ffw7ABZqdex<~Ls!Eg zD^Jo7@l6=3BavU*-_{x~b+YKun9dYs^3XJ>)x$v#U+ciq1KJLBTh%c76DFjk?!GWn5Fb-s7`29aXCwH8 z_}CdJL#pkV#al9$3u(+-)oJySN~BV(!6uv6&KwDTeS_L;fheAx2aA)uzrp6NU66aE zclYiMcT5+r7k|D7m24yGTwK@C%s86i-5WO^V9jA$(jN?ZcYHYUQJq8*Zo^IdX(N+jzPD4|f4{P^Zz#YkROt zsz20UruuMc*k{VirQDo$_eKM#OBm!!RGCaLGip=;HX-{3jFAa35zLZh>t!YeCBOiuA!vUzK_bWE1R5+E>GtlD zV{~9m()p9N2$orXPazB7i(v5p0!BWh#OL&D)M7Vq9~7wkZEDRU$yljYWOZtbI@RdKG?mx)A3AiggmPkpIaJB^G4FNk*wF!LYc!88sH>G& ziiI8h{r6R7ia&A^A16tZZYh!_>#|)LvOuNZ?Ff#VZdjxRMa0rrmeB7G(JE0 zT(398e?Vkf5+mq~e%g4Q=21$84?MfK5ySJqkh6*d=nEfdPP&eqdjr}*ZX#zNWVVro zJJ1olhm7pQeE9uPD+O7Kvsq{`kJ8zEqBS!pYR`t1zL8uDTk%h)9hbkI5K$#XSkZ7& zy29-`aT0gWL(J623s$pTk3x+QHwg~$_O#h$wRi9~4|(kd28Ud0W0lUdp0}D^ z5BjZ;>CHlmKzG~6Z@htS{m(x4&6&R$=%9An%$eEr^hGNnFlAY}Xh{%_2qzGiz4g|o zqfd(ey$vl_P@Q)3VAC6!p8nYlz}aUrJMRIG$f@B79FG37~FQh2jR2N<8%a!ZnvW_t;n0)=F-eYCw{QmEY#~u2l}T+ zEEa=B=bQ<<^&g zXvnzL;^t&O7^6%G^R1!6!{QL0!mM3ER;kFuiD6zF34nQTp`9nlsA<2YvISzr+xgu| zhZQRawS2(+bYs-QG)bnVZn~mS#HzvZhJ~cG8R!~2aUXLZV<%F2m_9VI$B^o&QWwp9 zU(2z~9pbzne8vojpMU%qZ=Yme>r=*)C%T6ZwUQz&DTI$4bmTpp`x;={*lD1eNIk=yx7MWas z57XcV`nuRuf;n>uY0C$WJ7NkU%8ryCPkISYcB_*6#Wj_BSH}1wHH5is$^kW=?GTrS zwo;7y|0}+g7j9yQvy6VQ&t3`{7IaJzPnvUB)%)~TyTOhOHN*E*>skW(LiGB z%DsE{?Yrzhw$R&XN{W9w(pIf8jsQ5N`}$^gB;g4m_+=T$33`QO86jai_}x}7TW=Eo z1ne>tMarc|c0Hpur%E-4*R9*eT#OlWUhovOW?OgBVhcn8M5*<*zPUqXj8M=kEq0w% zKl)L+w!gH$v~SxsEmp{hro*sDB5yjsWiKhSNZOo#Nk1-1{ z$52HFNB+daAmwdSxM-9$p5%_lHRG)Wjih?4^le63PP33!{f>elZLXzS#&+rYC#i*n zF{KHtK)*mgr{-3wAJrrTOj^m-V-0#<>4uPK)NM1breDB5lI%2IM0%NjL13J1I7RyY z3Eb%kMf#`|uS+i>Pb;A6Qq;?kP2wxNH*emJb~>%bmvh(Gar+i8KKHtgWlnd@99%Ytn;CW?AM& zfgR*{z#!;PRvB_Ov=k=jdbE`H|4&=2$Pr)#>dO;oZ&?z5c6A2?z919e5*L z4q6@#N7^0m1zjF!=&_Xrj7nt=FAA$ed<0{K)RWi?&OLLavS{`4vOm?FQgxyTmc`Hv z-fzLxspYb@`W4thONr7>#~ctAlW8=J$Q1wAfQ zsmy}iwrbCrD=^;&+`9;7SiOh*-;4Rlw9Ym_QW>Yr}dxbb`diW=_XL!MwDvTWHB@EF}LeRBUuSSl>#c0ppW+ zw15Dw5uY3wc%rZeB6qIhDW`PquB}{&k5}Gt2lHW7tcvf1F^V-4FQHRbPwZ83hj#w5 z#Y^>*7`0lZ>mQz96vF9bNIX8z0y$yMOQ9cSQ;qgyvcAn)s;;p11Vp* zm|uD3j(wG2B%DKX`o`L=J0|tdTDlT_?nYjG`zUi%xo(;o#9Jj=wQwsTG}I5E6!Eq5h3whJVp7%iboZ!PmFe+zOLyph+%|BMC8 z1&`pebv@B5zK6@rzR=zM+)tlij$e$)aY`H~Z(a%MEG~RugtlnrEl`a-_{6>U_T7E= zlTQJm2*t~G!09ywinfGiX@v-|!lh(Om;FhU^rJ7hINrQNJ!%g$vZ9nnxcnRzzt z`Hj;m@b=r5EffE?Y12%!X<9g>m1dXE8bSQ&_xqi^(-(A?=9QN%E6@AY5VS6o%FU&c zn5oRDu4yzNoyVJ8dfskbQ=I{hLj-;5@1veGPtvcxO7T_2Hx(~{zgJ;0C&Dr*o?-XzzgKgUC3$F>n~f5NwF4p=7%Giv`JtmsKUt0Ko* z^p}v*5h?qT-QXDPCl`Zg+A0k%#rdx=`v=x>9?ooX$1<6M%7Q^vnM6Dq%4Zw2SJcp* z>j-AUQI8W{&nq$XQ7DGfmQ*rK`^tDTCN4W&d?b;|fv>AyI&B~^2p48^JHUviZPT|K z1tG-i4D9RTM^r|sCjS1z%Dm}=U~8(I)2B6iJBB6?YYYH7X3rQX|LvTV$?Pze@Dh5c zEwJMKITP3s>JIF!pNb!ywsGSs+S9G8PMO&_bLGn2%X&*`)%O-ilS=5Ts4 z$wX9#Kv?IC#IosHZP3O#&@Z86)i*kNrVjYQB-27R#SSprlmJ}<)D2y6-IA@4fe!er z29p+E%CJ5aiwA>|ct#BGf_k?~dtGUAPtAirQtR&Oobjg*x;txey+vicL% z!fH3Wy=ctklo$<%S)6*e)8i(`Xk7jWp0@IHZWHgY)FOlf$qF|O>Rbc z^WZ@Y49?H{{ULP99wN8C(nqF=GymRw;poSmhoAk@Okx>P{7q{1!eOn^teiT1s5~h? zV_L6Z9iBQR@!zfKDsDOhn1%BY%w3QfqP6$l6)Q?lJ@wb;pD(XlSC;-4#X90=rD}c+ zf?O`G#j5d_iBq4WpCTf@lHj0ih7`6)m{vq$`cf zM=>CJZzqkwiN*=K5(?jvWvNM3biP#p9y{dniN$%vggj~y=-H)u7cFbkHZsn3bW6Wb zsWG)}#Ilu`w~6O7;n63UgU7^c_ezAfb0r+;{#9&i{z=!x!l|d7ra^s0HB@g_D-DZD zr{V&0I@Z=z1I0ln#3!u!RD5W`3O!=Jsg;c24h78?oxzPJmxSHL+qCyHzgZ>Ss>hH2 zqtQ6Fd^y?P_$iW6FBJ|Eif(x_NByVb-=E6%_eW7-)Io|n7CS?u?}({6hXw){x|&gI zyUIcs;JCsBexTmwg+3N;-uFU7StD(~4hG z*4mro_zChX_ZIo#_Zi+wo+66}7(n(_JNX~-3z%@Mk!-#Zicu>pTSvKq^8Y2hr16_% zb8(dg>VzdjJ8pMzR$BI42B4)M(fSIt%VWV?d--UbhPNdB97{;wq>rT>h{0zQegIur z=_z9aLnfSHT5F^)CGR3~G+_};E?t`Uc(c*2cwBH@w=x_^x#eOF%~zcrjS0n?9o=0P zvi2`O7Xry#3@Xni@h>2VsBLDb%cpG~w<`xcSGg(BSud$|Dm@4FA1_L=DkhyuXE8Wa z>(9p%fONTNy{l7?UekO&8%H(IVD@{HDroP=eSWuJuQR(-g<_)I>`N%w5DM6|ze4AZ z#KRFgl-RW<%$q%X^b_&@EqnK#;*%&=k^f5b_?Ft(kxoFR-DJ?Ya`~K~#NVT| zxV&yW!N7KAb7Al{wL&>lQahctYG-!>pXwtWxpF>-1Pj+#>#*1`X4x4U80ZZ|Q~sP# zuN3tf-bKlT3}*`YJuZ9F#hZ*atyzCv9WuOs;Z8CN&su#!(!X|mZLR`#2B1CXASbbTGNM$oI zI@X>bezr;CLv&_eO2I&J2SB%Mm0B?i1+=mAWtuYOnn;Bw>Ae;79E5<_aq@2N!L#JO zRD<2e*T)og)I2_?v5XoEJ08m*86QKn>F)hk2#vmqQhfKyf~Z!KQDbZOA*=9MOvvj&|W!ST3}IP$?{YH)Y}LvIZAW>4P6slJ;H zclXrMJY?$XnIaB~zuCNHODGx^OmOPT>de8a+v5pr*|LxMZ1mkqg-MmpD_vN;g3Ld) zV*%y~ar%KZQ)h}NuI;!oe+HzDprfEP2OxW=616|VfKirv`$kWxT=h_Trl*uIDAn0; zx>ipZAru@d)|kiZzp9EKBDdgb0cZ>x9d>gUNTF(?s=~ulpYtI5D)do#c=cY?EY@Sf z! ziJi4%QKqlHM6AC4 zJ4W;V50;KzMgH=GAJ{EDDsW_nJ(1zzsp4&~HK;z|r#_p@X$uK1JM&%v_!h^_D@-aB zCIuURu81Fj@2OOkz@m0x?24_1>{botf921Ib8D-)oL$i|XvWBjV=Ga;#Q?hSmIUM+z;fZLciqF1!__HQyV8o##=o9tLXpQOFD z^iHq8lxtM*{q&4E=^BS+{3h%WMNc*Vbm2#q$TNj z?Uye|LXr|INj~T8S88K?^hL*vgqctenWWD-=@na>rO|%XB>ipKC%(85LIqEgL2)Cy z?@jbQIIMXS63N@}m8Z!qhA$p^u+-=)s?a&kTAe<=L5w}b)QzSQhfwP5>Usj*e;-)g zPLxsAMhD@(>r4a#G4YMn5JopUbnq(LgvDS~Sv+>H&k^vOwb2BHkqic_$qJZ(^>TJS z27U%&=#f>kew*DHvim%!rRoh)tzLz`F><)uq%tR0#qSR`& zvd{xCyUiGGg~mhcO#z$9ZqWoGRslz9b_zVC-PNqq$ve>KXo;$T!*!yvN3^Bo<*k*9 z-sbY!{bpV;Z7nZnW)^&cTL%Ka85|a^TD*^Ri!b1QoU8_k%b26>$BThuLtl%vx}wlN zv8;4sNFe|{#Bl-4#na-SE~>^1b8X6xW;SrQ3_4^~+z~J5LQH4z;wm6!1``7<7kB}5 z=NJP9XuPp16T&mXDj)Id3?|q)J(t9gc!MhI(*QRCF~^9PG5auN&p}K^>oqQ$5n_Fz zpcZ8&6$oj_!j!;4bz0!;Mq5w~V_g7jheM=;J*55qRbXxM?BiaEG zxZ4{CuG>Y{37$wP*K}p%joP&ujvI~FS=?!%hu%*f@CD0==g4P|ZhSd5tI0tj-QBVm zZEyE~agK6#@>g0lS$EVEquu>W#lOAu5;3`oe`}Ce%3=rEKTZ5AO1;wk&RBl?y4ePp zN>>CeltkYp_yiBI51n@Q%H=7I4m#@JDrD0MPo?yHz}e`EAr4cA^947U0zV4J;)OU` zoOLPa+I(2~Q%!uotsjq>0O*3()&6A6q=E#Y2~l49*hLqv%w)s|ySvx)_n+R=L%!}9 z9_-@{MzoCK%!o${d9vGLMJXQ&5~@g7XHvZGJO|Pw&!NZu+ z+^oIca(AX|OsN@@IuhFJDS@YQYYM(3o8+-ImK>fOG{LyZ8{yx4_d%%MA3W$y3I&4| z3^$Iry?$H7uzmZH1?0Ou@}L$vtc5)BT%ca^+AyFh63WHH1;%2@VtA<~Xtk+kbq$DL zjR&U<^qQdE$rXG0<3P#32}zc8C0}TiZhOF6ipJ>o27`%=r-Od4L9ej|trm4>=K%Ak z#@lFn1xZ)OmVrUKr=z6>W{NQNx5dAUHKV+uS-9JS_`_38kCMlKatd)8eywU2&0kndE)a2&O9?5 zO$2QQbcQ9TBxho}%Z?ov>?8BUhuZi5!5~QMGlEU9z5jhD3NfyZSa1KlxTpKZq+oPd zlfGOug;+Hd+IK_eyEDb>mgnaU%`Wv7D`j86?-=OnA5IUBOsmyqHK(Qf=S+(`g@D)o zDGg;I?{xg@W;5?}K)L_#wV&7i1|F}f!%gf48~Ut^p8u`=T>LDT$R%^+b#QJ$>EW$8 zC&XW!-K9z_Ygw|82coA*8a)oL&EYf0Y75U@{0H$wZ%5jZclrEDm&0KQSZo@MFhS#l z-D>Kwg0GAId_kjyfNny(#0&zd&WgxO4O{VD%%3TP{}X9x&uvAQ+PTe*8zM+g5%+Qz zk=>VoI<{yDS+)X-BCAdz=aWPigO6(r#u(^*Mn=nCMn{^g?I(TfiS&&d88oxeDJJVC zku@uqvJ09_v9rn~+3q?Mk1{rlh+-kW(ED#Nd3ozlPl1JO(fernM4|Ph6gowvh>L}r z7$+Unth5V)S|O68qy%YdF5O8|RWnM5=C*=p8c0vL<5dxZOW!-edeOZD?q(~Qdgf4x z(?A$>FVHO<6Izgu_6++CX~k+O=$XL*9$snM_vMzEL21syX>3z?&g_>VvP@K_R{peR2+qcPW+;_;ao0)SCF$?Eo`qQO^xdGzLAdXx| z^jBa4LhB1RUDN);RYZL`bJ_J*Ge_AQuVt>h1T0TB01;D;HR-_eWF9Ave2v`t?~-Yd zb=zG{l(itoyn=Mfu|RS#O+AAAK-+;h>0^=^ppk?*KB+J<7Ry3kItB+D@_ z6jupLPo*!xBNL!#t@JzK{a9WnL5%om6!537EAJQPz+e7Szl7dAeuLf4Crvhtv?Sz| zln#NSK8a@SAA3!1pB-x12D8&{MjAdHrC7TwVzL<=UE;%9D{DYCI)$)N_v)hoUpUY} zEMU<&$h-jqX1&gzGqb3>C80=flm5U=@~4nkaL?@izO`|5f0ChnR5 zOg3gr@6n`eeiz~))+IiM=?vA?_4?|ruJi1I$88N*5J6-6P=zlvEPH%Lht6eox=kos zU>=9f1bw<>$mVyr;sy*ndcf*Iu&OlhUWZ_*gxvu?qS2{LTBXrsjtU+NfCF79*x~Sn zJsut+(?(x39CZ4_PBYrmnIq!kWM&S(K%;R=XXlS;OT&j=iRfl_IIP`_0dX!-WAKg? z+g71HZ~{0E)y$DK#C9llgJE-);vB{K%`I~eLl)v}vhd(yMhmjr(tV&H?jb8TF}o*| z<}T9TO*;D!@i0L&YWcY>PDbKjNJZvz&N`EwGs3J`!Ynv+fZ5CKge=(^WFy-%sazbjK%Nb-^hrR&K!zNc;RB&)YieD?6(y&VhCuBX!!7EkF{?ml?%$k%Vax&OA_ zd+tFk(Nnn%{AKr7jvRU7&t%JyBX5SL3>Q1lI^yUhuYUa8bH|VW?j7DtOi3_T^%uo4 zI*y$B(evMwZp^cdmm1<121hZD-e@#n8Y`a98!z26x6t1|d2*r3!G_~nnJ0lxWD)n{@C+1U1WL~~w$1a(X9m|g~6xpCC`up*OPO(U8_lr-Af81(4YJs3DF3K>!AT|U_vuJUCZ&j z=3he?EX_o&+CPW2sN&!mFg1<|U>^(--~hU+l9QoJ*fvyBM}ZtKOHee$nPuk$?lW!G z{Fhe}{vWSHMex{;OWG)1phQ`MNX zcBMdDKRJWT9E|r@(bV3#hQJ64*}N7m(40nJztc>2E4T*(7tUqut~@4o>LFspBrTRq z+D28?(U^jQA`c(7?2I+y=|Q2--79m(b~VTDtlhZt1jCqux2L|$~j?G@Zp4hA%@O4Tqq=!x8M{>QRi-HKppb$cVPmhyRR$^`xUs#LU zs5SXK3I$R0fFJQZo5xf@)uRyw$(BfItcOn8E0VXO>pjK_Q(L7SLzh*Bz)5;+LW*S@ z-*_xG0r^3;m<)O#`>at`HY~whWVNyfTFs8S5$feWbo3(l3$tC>YK-(XH}q};SkUDH zB_uWL-fMSHj;0dpp_ZUq7f;*6*(&qo=+)riv0aFjd9@zGBqopGbe4vCYIdK~>q1dj z#Y{)<1M**pdA;%Wdq*Odzxl$O01(xDHVnxspZL4iUp$S&{J3-OdJ+Ou47K~L!h&4( zLtwnKfe7BA2sRy8o<~6bxsW+`4mpFY*@IQwSO4bcXc8T}SaEt_=%!qdX-Yp~0((Q`SUQ)32; zo$SS2iA1y32}uQDz}=mFWsBf)vY4x>i@1|QxxY9msWBPAdb2w!KVDR=W~f)+ZW_u(|^TI%_U5c9t#hMa8;XW8%4Xpi1uvZcEWTuAALw4M&^0Ey?E zr1o6eEcl9aF#q3rVG%r)ZctgjqrGRa-Po~XD(%s+LyhM)Cin}Q(N4bLFnRLu`QMw> zHSNV&KN*7B>J8%Tml0u1^x1_;JEG*yFBuxkO3 zf_SDiSa`z-k6mQr8L_zdJKtGcEG}Mr{!;1oVyU#N{7gWLL24L+04f`fHn2GZ(Z>k)}H3K9`yKA>_ZQA z^%dwl+@<)I;zjgI^sgdh<0*Rl{I8Kc-@238%{}>T=KSwH${gmNCJ(>(gNN9;+}Kl| zB2OSk;ci>Na5|>LNg!%99x2d`LpP1Iu#Rzwl=!%KgPdx}#u}58Wb+{{E_M!mj}^C$ z?|})HI!R@F{`Iw$CE8K}s7>B|t)182D-vWTJBg$k!6FSQu5n>I#mwdTyW$$495uhpg0BeD81TbwHxQ> z`m9c^(I4+i4h*^--ct=$yZ#iH+4vzDItLT|Lgiu&f~?AJ&So9$xduN(FHd=*eu?fw-GcPlsnE>JWJ3(Gfv>LQ`ZKjS1N~S{y{|L?E6uSbOCag$te(Sh(0vORGZ{zYrus)8 z)o*I(a?XTDiLA*GDMgy_cV%cLzs!6HET&5_MPYmbyt5JoV-b}?@l{snY%MyC+CzTY6&LI?c>SCD6LANx$8QMC z$g0#j{Ie!mtz5r&gNx}Ny_@6;lTVp7_p*X3m323Q={y*vmmmNBN}!f(kCWJ~KCfqa zAgogA^}I2VCn_iw`gCRlKb_?H>whLbV6mA^WJSa`FjS9p_78(+k^}DWYc{4Z!Hy3p z_8^x#Utw$N_wFLQ(XNCDfY4Z6`m-k(OPR~t{(=*8EXQhZ6P$enHZXV3#;RSRa5XK54xp1A!i+b4!O4;~J@&L5T0xu)%PTk~XlHCG>9g@Xn*1~{ngzRGf}UGo z5FSjN`k^|rWCTNJQ~>mH136~BcsaBegp4hp2c}^*Tda2Ndi$EeJ!T{yO9toWvkTX3 zrv34I7cc2VHwwpo7oj@ebB^hYAN`&;It`h0Hek`HkT|?>eRHdqDFtSh&?g3|OdXV` z(na8M;t><$7=4Y*>E5<${VH2^C*+iTxcLXeP0 zUy)YPC-qZs=(jIOtQV^6z5=|aOB9%mwDJOS5!rZ&RJh^1h_TXxWM&`JC{xw2VxEc6 zhfuCj0@k04Rx~ywj0m;{Yp=vv}46?%Qf)sd4G6&|NA%|Z`XvdOYL!|stxb`p=_6xY$S zfpIYRDWS|juIuS1AM{Okro4wIV>UH$iJCqoWQ=FFDh85oc` zMSL@ma60x5#?2NoBjt9xbsY|uw{}#mDW>Bc>*r=t4i^NcnBo4JDXqsH^#MVx>YTJ; zjhKF{hD=IYeMb2LBsru3EXj>V9&MQp<~X-JPX!XvuPbh!5Efr2xowroHX+O($c7`q zqiX{YHtWmVW5q&gJ)_Y&&jV^DEQsCZm!0V|BDkt7-^f#yUOL4gtF* z5a@LGoAiNYx2*r!(JIcR0o?k>P|x?m&Z=Q)ol>XoD)iCpgs|~p4Y0siB&jD*a+MU{ zX2%v?rpEH9!_l)%jWM;e^xLRKZSYv3*0<8nC6QyGoo(D+F6~PpDJ{nwAxGceS&XSo zYKtSzcIyHG-gc}?k9w)6E%OWlf?%sR-g3fIY>Rh&f7oX+rT+kZed21+ysk14}!^l?Cm0)SquP*vn#txNuld_7f zry}C1kIg(hxvEmnOaRBwM}rj1tMx1<(;gCU_IgrrPrx6s_-2VWpDtL)U6;~^+NB{QE6tkLrHPVs6tYFw$G({a?Z+`4r z<`8>5Ip<1pgu9xYe=E6wyXA5QDojo8yu-}F8?Irl;BLB(xoRIXFidlj_HqLXX&GlC z9jN%2kHkWcFCgu}J2~9J3d_h5CghyNNKdNiah0e?QeY+T3i@=sB7KwWyp*l9j5ReA zlD|(@+CBTUfWo36`SsIosF@emC%<@M)6$&KJMGOzZVvBCQlM1zw;b zQ)eh_L-QweYwTtlv~k^2JDpCIT|DMsMn*3sB{P^Cvz~&`pjKM~3qwnODeiWXP($4C zEp&1V$;g=)*I`4vav zvE=IOX)1eY$Q5=VF`0RiZ)-sOhCLLWKV{G%Uh@-m6bAIR0}mqr5VA9_+;G$YUk*+(+8LhosS@NWmT^}3}p68 z#VcL!%CXBN#4bNVEILgw3%tRFK!WOCKbevXvcmkSK!_L4CUa+yS;JtgQ(-gAA$2hW zc``)EJWM{pXvjG;SuHNS1O>^b2fz0CFN$J|gu=`6aZ+6dyg<5H+go39bW$dP4V%Ox zGWL$N-AYM=W1JWE;s3#Gf>2g`g)x&r;f*)`a9Iy?!RT4HE0f_)Iv%|@kyajXc&7Du zVBM?;XH0s3!k{OWkN-#fKzxN1RdKf#@fpG#D)PqSMc60zm0`Ov7OM9?)VdRT*T&SSEDxgD3xpWpY~!1CqL z(ew2@XAQjk+;h({H+{VK<=duw+<)CO&xDh{q}stM&7tm{JGbg^aH8dOjtxCp8{IZ{ zgt@AA6&)&}e&i~MVQYT%{`=y4fBtjs*=LEqe7AVbU?16dcln1Zz19e5h)+cvcFtn5 z7@y5o!d|0JJqi*$ml#9)3v}$?t*8aY36Cwv!GzhmYzDf$>boM;) zOljigT&DSRFe||x`otEnMokiCrk{Q4nj%z^b?$sR^2^3&4gCA1d}b1;Ej)?dOFgD^ z&j#1Fr`h2P5F|_zshl37B0XeR|3_8x2;_nlH2>p+UAG%1O_pyizjYHm8EL-DwgYU(6-xcp=ekuOo zv(Jcg^ywlB5&CX}-^;u-k4g%wca^Po{Py&r;cjp#wF9#joOMrSml79Bd}KalS8C6s zTr7icsJkm00&E)DP}rnY^Tz>4Y#u_eu=Ff_^%|ctKgi ztmVvQdn8{!_*1G3OYP5u3n+aGM=8CHhv*e4z{A<1U1#*HB|*cZoo4iTbkXQy;dIL1 z-ty!WSEO&!fos1eo==`R$3oooQ+SmDRX~l~7pYqxZxOl6Qlaxd?m$y4TB5U)c9~Ro_eYB8TfH*mjHWYaJlU@bi=6rxAM|= zwr;&;=gwQC|9>i8N4AP-Mld>!IO0gxydi6K+sMq2o!0l_^Oj%SJv28IM(xpLw;AC_ zbq1R~m6|pM*hU;@>1mcwWpuT6ft1tw6er=YON==3RnbL+DfkS(ktFJ2rz@x z6yi+CX0X+eBs(4IVx(tI{0@9)521_7;ZgdY4yYT8x!Q}*{^Xe5)w|q|vYxA^b$cQ( zYZfbS)o;Awinqwm9=`bEW8x`d`o%lGiYeUa8?ZUkWWajXI@{jlptr@GuVsB0O^9`8Sz zMClZ!0QBLO1Y_dC&p-d1nI!&$D8+xUDzW>l1vM}^4T5^W?Fq!*i)@VdE&%!&s z^O-9jeDJro-uheVe~P8`!3Q4)_L6F`@2GanK(mI3q>0(-$RT=36~>_+N7X7R_p3yq z5#wOHY8Z#h4D=;K+o9M8Y1v7vMQN!=IQWzC*&|JCnqBNkDv;N%CHk%M=_8R#v0}yw~j>z4pUD{NZpA zY$mhKj_!pr`NNJKcbs+B9n$~!doTI&Irc2(6L^$%=WL-FgEp#>6^PkNv>Z?L3Px?W zpkx7!Oalhefj9@SZ{miQ));w(b>f{pYt+=o>}`stiXRZS_yMz5e2;j=_n1$k|7OvRi=rY2nQZFB%s?*L0Mv8Q zA*AL!PDZbt_-nQNe(Q?UOH2(L!JRsNcCUDkg9IAllYPv_N&Vt)`(-vhbDH>DX8X-5 zP@=i-jILg>g*oSS+{C}1z>WG|rQ+C^4`CRFZS0D96_sWR)N~JVLS@bli-6jcLC@$M zR)om{r+=#6;IC@YNrf;>GM(&?{Q0T$DSE$NNEKQ@V|2Z+9ZbUWS8Xq0HR3W!hA z&sp2(s{Z?-A$}zuia71H?L6+$#Q= zSu1`_tm4N5`0%z1(SM-i?izi6E*)PoNPcl0ZZF(`8?K{DvEs{@*lVF5nUpk7Ej5beaS1Lh^U!I;m@1~AR)~rgB)jFLZsrCB1{c}gQFDX=90?X=Wsf^}idfM==DS%PQ zdi2GWwr}4~2E>cWe(4%i;q&i?4W{a}l~y!YYR2QWM}Z79G|uQdDuzAsgnb$IR4@`CK86Pp@ABE=jg3U9R^q84|JD3 z(`GD3*N`b!&19Gv=nSyvI!pbi@sn*G6$ml2quu1U;)hsEvg7vKZ)YA;^Lm$?Dv9z7 zSFY++K^8LH$W^{~>vtxFQKN#Kv`y)BO>2Jt#(r@cd9rrdWlvv?+tZg_M$eN{>eP^rgI;KODSHpVxXvnVc;0)b_uhN&y=YWNl4V;iYL;!umSo9A zj=LQ@juWT%gcPSZ329D&KpG(d5<-A@q_F=# z<59Vq8Ch>R?>WzT&U5JJI#0czW6r5)+uE{ax6@@MtJ3kw;NEPGy9QpE(sDbt>w8M@ z-K5E`aF>U z9=y)kFr|%@u-q#GW+{||(er?XATP`SH0#Rzi8Jp*ErLPlDsL=#eh=WoC!`b#^KMn$ zy@L4#83Il#o1MA+w>ziy^g(1-+TORO866CFL3CWVDVw55m)m1=>b!D!+qs92KrB>6 z>1sznBV%zetH5~IP^3Kuajkk)u^J+aLOI%9&95WiAPcs9!zJgp$pZdoqk?;O9Ot>{ zSaEfuLj8Z=bIj%39e?=49~kW)|M*98=gD(^uq;NAa`tNj!4_v~S#Q$~@uNqs6>FqA z>4xsUbSx6|87WOMkxpd-c0}+ zK8!&H9|j=dTAX?ktrA`gj%Oph81v_OF?>o1u}OfxFX(}U#lq{_AzwJZ+!`J&Pq5*a z9lrqSwxx>;->?sJDF4{h&i&;&vgz2dV{O-QXT%wiMBOTfKovS??{AX`k>|+_D>ZU; zCW17bJDemC?UW|dMKg%3rjV#x`WX8=Et=Rd-ftU1a)A%cSFBmCD@>A1n3rwwbwC3R9 zYZ{u;vzvb2^$+{#`su{Zjq6&>Xy6nG+?lYLm-^Ov9F^@On|sDqFU^-DSr2-j>yrVb z!}40QSj!5zn``7>JGnpbF5MsAe*2wwn6H=C4EBc#snOxR00bbYb~(dc7FH-k6_LYI zdwToEzDzn)%2p!o5PD4Mpk)ClUC>vrmf)!^Ty2iYnzzt4}bVSuf6s^{Kpm&Re@e7@?XtMn;5C zfbE9}Um?e=+p?Y+X19$p6*O2CPK`6@(*j!Z>P~)*HI9A597UO5W!RVXL?a(|)s?<^ z@X6d*U^Gd!;NXbV>$zslU+MGurQRiWSPTv@#-zp78$uKzVlX}yNPkGtsvwX_`J-Je z5u}RDj!0`I#N5c;xQ@6yop7g=J;5Mz+~HhJJ84Y$gR5trX(vy0bv@nw3?SgAo@V~W zy@_&4VcsHSEgFj*{V$~kkgl=M}(f&CLpf62}5AqU}u4 z_-hTbVaq0FgxyA_wqw+Hj5F(a5xZFsgZE4LF{X=acF=emh)r9p=Up3DG2(MIQuSQy z!Ylmh#0A zdkZatn)_J0dhgz?B@xQ~Np+}y6Pl|R0Sn1}n>MWwK~{o$)Z5-vbWp-7zzd{0L}!HB zm-ZOZicKT3cU0SO<;=+1rJW`fP|09h=Spa4GnJX$%UhXY>LGIf2d)sR-KekI2Ca#2 zvQ1d`^;N$U9Zg$nnT=b?UfL3RlD33i4@oLs9b{tHc4my-vx6C=t)RC}F&jqaI}`AT zUL9_sOPU6c*x!7T6c&~azNA4!<1?X^1^a z`6joI_9tjZSISFKHEOi0AQ#|t#yi_0vC%DOwa5XCNFIM~+e6#6rhLd54#rhlgJN*g zc(l!(^+2gqmkL1_IY_k|6gHJXYX&nzNgf!QX+evU4({wan8oyRCy9_d$-J~04Y^p! z-h$ewFuS4sB3H#t(1A%3wg?;^DwJT`nq8r^FBSHw3`UKJWow?iA9|&7XVMk&89_-T2Wyg`N@QD`+1EmX-14nzr3jSLd#fspRD!nzH6mB0}@TC2%mAz#Fb zRyB9D*=$~yf)USrwL8z4p1|!7&*4VCdNyr^CcUGecPEop23mUhGY=lj!9>Z0me!8M ztGC~^QmRlWQ-iC<*Z21q(e+i9+BP**nch^vT9+ZmcMrG*^R=Dxanb3uX@C;63r~pH z+Nu%OBJ601v8GZk!5V~>LWl@3ZK)?vu|aAHG9q(AWA-+lpWP z>PFNj0e)*GW$q=i_42pg>g2w971?_0t+%#b#r%E(w`*{)jy}yjwk|W2-IP6k93O@< z>&OaR!R_K9+%Qhvz#QL!O_=v#sgC+6PQ_)liW5mtXf}Tmk=qa?9xrsE{KR4V9C)q~ zMt))y8u0fw9-;+CmoGTsEyZFCfm#yk&eG4Y4Hf!%K02rq>#!)v7rFbJ-|u({f71Kt z^}_7uF0B2%yZi4X@Da+BP;QJ z%c7BN*2=x~f!5;(pTWue+ssH-z0CMyhp79^;B*| zo0>8zL=r8@-QJI%#Q2AR zn?)AH?$FIfyWk2Web5>v#l$*D3yajK5`hFdZwT3XMx~+r3rws|O{3P6r7kMg6V?(> zJfPPIJ=_q78SoiTHL>)2JeaFqeDO6#`H$CL13c)clINa7U$$M`Uw-~`HR=ePXa4q! z7Vc}$uKmUE@Ni)*b3yjOeEz}gB`oD5%-o&7r&75mf0&WVSqb-#wg|I)=5Dfw?%t0D zuj5ufbDH6kzKFbWzhFK1dYky{QfI9=j9&FD4wh|XRERTvfPqkLHl$?*!u9A(zZR*c z4e-Z=)0>$!g9y-d9q?7>zzOUnYPA-umwGQ2%9-KU507ml*yNo8e(_*H7Oo@w^^GM( zZ5p~?!BS!iHppAlO7hs$6CZ0#3cUz*0misV=djt2b`Gv8*d!9Cf7y?pyce}^EQz1% zw;Hsnm`ZPyaep9(mTuoP4NOBay>0K(w%*hBtV7v|^3+o{<;lhqGq1LjZ`5i}KKW!D z9!%8|G5Jx8Cy^Q=-dsd}C)o3-R*~3!RxB&ET%(emP*;O)oyihU*z!Gvj0HI=rM=R! z;;wJ5?CG%Rm3o=2lq>#-+fyu(O$6K(gZ-i1UVtJzs zL^()%jZkufhOk=ZrY&T&i&#ula|+xBN@y^M(HCj{MBzCNy!oQ5hz<_~CV0Pzps5Xi z{$q>QX8?QFk1on|k{aVqf7U@LJCc${fEdw{$MeLLjMWCh6ZUo`!Y+`(XiO3P+;|tf z3I9y`nZ5!2JZA@9hGF|9Vv4J{M=QTyWFoQdyg?>Kk%cJ9}IfrBtkkM!twOp@)uATUIO49cPK}M@iIR7<0`{`F7f=#_2IT zpuOa(?%A;cG(5@V_RSsn=Gt-@G!F(^mlV>Gkbyh-9hKD`a9K>ublS?nYqL4X-4gsP;?Gd#ANz#s^G^Cb)eI-vagizNR%p>Bpj;kkblt+Q74rzL`fJT zpAi+6Qn~Xiq1L3fxK80tbb!ue+T2nK;y-~J4+Fxrus7pJ+7BgXifAO43Pv1StyXGt zd7{yd<`z#NnsYmoQF=bsKE4y$2fn$rVc@OL5=2D%1U>l3@pE)4$vk{=Wb*h*8&ejmkS}q28e!?-y{5Gaj{v2}w zciV>_e#o$BIZp25e);aZl(SZO3oIjB%TIp7{X2Upcj7H^BEF`#3-(@88(iTviY0%J z!l|HzH+&8+|@jFs(PAxDZ{vMaZ@{H48nXTq^qPzO&% zWsZmKsM#z=P71+b1wS1}ze9=p(7%B5n$kg$^gO*Qg1 zaSpSk29j=4A78>p{R}Xf`3*~b3Hm+Cs~7NAc(THx!Xd&%S62{OgqOEz#d_I7T9EaRRax&7zQ zY}cb{O$+nIHYCf;MDx){k!p3a@sH_kY1!J+5}OVobuJXv5-qWo7|!ENrj%&k%H4(B zq68d3M#xGdD(fInZhN(Dy5N%2;)e_F!0n*p+=0Zz+KbEe7}P`lY&9N%2^>JTrxYoj4ENbd9B4x zH~f^D?=k|egJ7L_g(furK|YgRE! z2Kf_W&f%jTA79Oh-As*keFIb5PR%u35)2ikLn41r$KmMr7%~y>kw9+*hs)=t67J8V zGlS&5TXpetSE?r+w|a}^=G>A(()Q|~fn%Z>5=RcZ9i9GlerG>dsP1X{@}4~$TtblN zF6Tc!)AaLJHZP929FBZ8nR6wB`Aln}Q1U0;*?2l{0-S=*zTCDV_efl&lrJTIR|n}Y zUifh&BKSCSCR6`3sIq~pan!>u%Uu%rQl#KshEyc2|?%Zdl@+@ ze4&9ef7zg6&?S-X`uWjsSOCaGeda3USLr|b*=ek0rd(n4)tPVoJ8mTOC)~K@Y;nd` zVbV=Ax6I&1ihswAi?fGVQ!clj`>V@AB&l+=bUhwBve_x_L!TGI*UgF6yYSeNqdhSt zf=<+Mya@hXi{Kf-3xXF>kNUdcJwdq^f9o~!WA-QHr5};!g+CzAzK4RF?k5f~ox*ot zB|l_eCojHCo)f-8Uic~fV;k55-FkIeHW>T3Yj{tCepw0C7hCN^`XY0~nW3+PlU=DRB`? zLdzNMn{FfNqUVoBunckY3#(JV{5GGe_snu36`cHx2jzuV7(OQ@#Fkk-9f5GIbny^MG|} znq8apGk=Z#Y{7K|kNkB)pHM#p!C8j6$DJ>e!1gKgwjL5@-w*Znq7cu5a|^XJ9(}M2 zYfdY#)u5~NG~?i`gVX67H{Rc^;kxc%fh+_>*BgC~!_cQvg=QI=)* zf_tw}W+Tn|zAWUtgu?egw1k;hDp{MHKy?60MvWP`VUM?1=KKck1 zF2!r{n963i{q?V@YO<-R>GtY#r4p+y9kXm$*||ho*|}_EJfxJ1I~lXJlG`?M1^Up2 z|4!#!2@LfP_C2;|fvtC;>s%Y~Y??>dBe=A-M+&tUly=7YfN@W6 zB%|o(!ZaMgJY%<#Bp47?=i0!YkrUoX;P=A&skpP#SB zOxBKG%YD7_Vbk-7zCIjfo}c**`CY~Gd+2ePTR!~oUUI{?e&4|zeBcT4tsgu%J@Y=f z|G@_pa#sp?DU**I&3%16+;cDHw-yRp{}fiDgI$!|cK`iEIrH$&L6W@x{+~bmF!}n| zS0^_ChDSo1m5wCa6N&c!jx|9i^4er6ekh_+Kz>VYV1y=9;+l9V{=2yIkzKpuE~Uk! z^3l07!Vmf$`#si%lW3mZ6sU}@=6S%a?yQ3O$4_m8 z*hlv2)fj(g0W_}|m2~0H=c1{+d zGm3N*3_}NkkA8IYxW;njk6e1t)-gp3E>-A(Pwy3a#+MN7=zJ2O4*SW)#cb68G)E#s z=p{ma-ci!Uibu=2e5<>?rDb{7)QV%7b9S6EOiaLd5*JjyY-fH`oO#Y)?5OG;x^N8Y zrBXF?6%^l{zF@2n?HO7(QY^acD!Hs*A(MOlvqFjw`hErmy-*MZ_w|?X$LpB%7?9Sc zI8oCk&_Mi>2&L0R-cGA_HZ~FZ8ETPPl25rWWiIy^j6noc@Jx@ae%I!#nJtJAVLpIM@UknAmQz-RDOUwP$;M{?`OR%xJE z-MM;YqBYmqS&=~jXL(P5@mt?}W9>PuXKz0LCObMaDf>OEArtH=LM=sWph8Q_2m40a z6X!E8pu`HW*TLL6?yqasj|JsQl`7G{s>Z!QT6=nWV$e>Jq?h!sC$e=HBHny((9y0-D7dCGDP69e~tYUV)8Qb-u*n@4VpyfGi4S%`P8a7h#@^j?1VdtcN^} z5yqN>l%0;oITc=z^Ams4fsOif!o<841@@aqeh_J3tx_)oCotSzrUDnVBh4UitQ zMvP*)p}hy%45R-+$&ipCdAu>C9Z`;Mwd#WMR(IazGeGSLMJGZ?oP=7rzsT<2GSv%_ z2j%KrlXt=kkaIcms7wU#lsnU{)*JL43D9CB!e|N^BDtM(;I&N4@n|%hwdE(3Ge1+2 z8{t|A#as_{>sqZWW0LF9H@0LUPRzRy`JTHFTU5c`+akCFS~uV^?%BX}kKqX2Oj;An z)yK$nWO^%e*9n-{YsppHnS7W5bE#oJc@GKLq=laz`nQz1bGmkoT`pkcvR$ zwye*&c{CPLstp>@B1JA|tzB>EDOQ6 zu}+swAqSpgt|(O+J>VXF)Q&ogRhVq=qfnlfhXza#R;D|4I8`cgh@PV7~BI=SIs7me?#A+@*t#)Y-LKhx+ zLX(3SsIdU=O~bT?=8OeOjVbE|%K&68zPxKTe&es9dY}IclmqJsktoar-)d=gvO%Pr zhmqK>?^zh)tv-S#Ea?9BP&+oer*tWIqnQypI=C-a{c*1z`-v?=%+p^0S4-0zNiaV= zdA?U0aJu~tmt%^2jBrLMo%w)V4{ui_o_Tb74P!+aidgd9m0*1c#e2AG%u05x?6B8|njB@)hKx%|MKjyv~BHrX4_t!uFM^o0={X zOPv5su^#@K0PQN8c8o273T7yd-IxYxxVGg zn%V}|ZHkVJjwa|cR$izyc4^mG}c#XLGUR&DNthaao-a#1u?QK(RG-w{n> zurBiI0yb~JiHf)}bN`C=P{vm(c6JuZ?uxNc=zyZ*pJZ1|O_$@P1Dh{F(Jdq8R*|a} z5((Kngp2_zImkU~k!z#{oH|CM`>g3P+E-U8tnE8;5oryF)M00sA3=H!(J}lPbUlMu zQM4oSd4gcgc4Qq>9cI)5vK%#r?Af4TF#!!(3LU??8NzV#)NzbteK_hhwsdf*O`rye z9vz{7vbH`wjPUs9THbz^rJ?UG;Q;jZq1fn8|o zpqL(7Q%Rob;g`Qlq2zYK^DI;D$=Ag}C2E1}wHA5P*dhmrtt|i@9sfMwz1X(MKQs zckV5>d-}`m)~MBCFlse=T3#apjN^3VAMDlX#+tb|Bt+)RHzkee$tfj9U(~Jh1uIYr zQa1TK8Wlu=ZsKl&%HGV!VUN+HR=X`WH*>mXIA2Wymz3yT0eA4aa{^%%gtfG+S`!TR zw4SyNx&+*@Q=kL>WA3>Lmy2alzV9kPXh_DyHC7eG?+8vTzjWWe_0xk;J!1<#5%#$V zHL%kw2MUlUm3Qv&>i~Lj0(BLzJILn!-EC}G=#60a(HM$uK8)_{nAaV?diK&n2b)%np`@9X zqs|*{RE5wZ1iP|j3QL|airt)hQAGKNW*XX>*(_sFZYNT1lw35 zo;E6})Eo}tgJOp>*WQZ4-zT^mMM~nVa9shP!=#TY+*b0?3p%gI;4%gb4}g^W@I!+J zpCjs8v9dkCs+=$9l8F_qndNY;m0Bf6zPaOR^=KkNN4|z3T=w z==c(|5`-P_tm3B*uTMI+j_i1rkYcY8BDAdVzx^(!#S%0*E!=;{(-4T+VpH0k)vb8}tUF)s?m@`y3b8M{yvD8TQD}uROQk*}G&tou3GBvzL&Q zrW%$3AZ5d}+M*X!RQ7)rS6Bw4nc$D#IS7~nRkNoqPj=u36`O*}u>j}5oyvL8GkW1U z{K?I<=+q&TMa&I`sJbUtDzuD)uMO|($Gb*{P%$YYVC-0VbAaBD;E;|K@#&2GeyOlY+A1Ad? zypQ_|T7Ap-a~Y~G3i*MN{$??b<|RA!TuTy}xYpgXD@;-c(IHH?T!Np)t zBC8NP1KIjMs$OtDIdvlwB}B@AXuhfjfDqY+$eh3t)_7y>(GwVPU7fZ&yXdKj!hN=q z`m=@(qAkyEcq@tx#-7b4gS` z>kLgrtu9`!dhKGVE)dS;La3f5M_-|e#Ukm;zKC-|5_?1i7eM`&=bT*%EKT1AUcFfiaYOC7#oEa)KXDfL+|yo1Ch+3ZZh7%Z6)K} zJ@j!G^X-#o2i+QrDQ+{`$zPi|L5P8v@@B>=&XE;s72s0$_H@P)+joyb7F!{m+&YyNtE|Do zz=k!n1GsSM=wR9;6puz)j-EHgs^FFEI6T>B63IqF8}2@Svs$ST-*dqYBcK8oxo?@E ztybgiopYp$o$)X}+N)}0 zy0+FXAwuV$dkUGN9+z|?a{-NxgraSsWv%V#Jc#&7+LGSJM> zN89;3H+B)Jb(^&!uyg z+eAD*XWQbL*DQChrL2 z<+B}bVCm=OyZ9)JzBm5{%s`R5T_U|15vH7gC~WY^eZF{i*b`7nk!59m#$60r*UXzi zx7%!rS%C4r@P^Loc7$BENZj7tGmuQgf=)D|c4b#D-JaOEVxU;+?CYwG_SO>dVAL9U z4IPf8fDmLkt6i_D=q=_Sq8dpo+q8S{m~7)!7a`5O^@541&P?0|TPH!4r+jSv`ed+q zY}ct{yVeerJE1WBR?y|MIRb8%xx*I=T5S>k&Eh4?SH=?-7=63b<%;_~jwW{~o{k0M zx+cBf6%J(zWh?EdLF4BA9!J>W@OfOW_ewS)Ym}Rewu-}Mp>sv`PTs&-F>hbGp&Afs zB|;sTT|$&6q0mVoAYI5ju(Uu)%F?Evgz@lEZXH;rZc)9rC&i8%xu69`hMz@xz+!r^ z3t?l-pNMr?AG?yP9AiGbtb_X|Syg{|Oj{q0U$MjKH6N%0dgZ$l*XS_#QNcL5D02 zWC!wwU?|zDHyRWd!UN>~@jsz~zAZY`N=`5D55!k?O|lTiQg7?(jR~Lz!?1s_&jigqM%7ICD=thmMj|05t2k{_=YhsTT4Y!C?g%(M8!nLiLDv6?6VOu z^~x9UNE#`|fQ61a?xjGnQl$P~24)5UQwRql<+@4$aI@3^@db1BHOZ&v=Zpz`F>iuO z3-~-Fy+!DYOyoAjLc*o+s)ZuGafxe{+YQUvpUUaZ_kMIey!D`ow=mF%AA(tVBka>m+jxOTn{PD3cwo&GU(bP z<6Fw1*6A(hZrnSuy3huI_N!j2+2Iel9kA1^zzhESPqFvQ;N0#IglcvVQDo7|wL}Y> zCs60gro9vuZ)$J&6LjU%0TWX)Y(06vkMf+=h1v#=$3;RK{2}s3m}z@fQiv9F;eglSiN#z6OS#oAdqb;^Hsg;%U9#E0{RfMu7EIh1 zOayS)m)wa=$fSVr6&p<8NuYy9LIGG@k~CSFcTQd$*1MdBsM+aYx(hy!*UXv86V1!3 znP4~>PdHPlNYYkpa+SI7g`wF1ff56bYl|sQE;IYQo^K8#!W2r+v+viX+x9etJ`S4=Yt~jgLGQZ{?`S3%cKlxzD zgeImi#&+hFRaEIjxMTCgXur{9RKt{lnQBm&*zFTj1u?azkKRPeli8WSl74XWSP^#v zxW|IR+bur58^@8&LsK#Q-oKm2RR;uX(RuHD!564XU4^(eg2Awk^bTR0uO+(GL<3d? znobLZ=WPQk{G4gBY7j-9Yx*f$E5S z^bvWo8J?D~h55E~bo~xBc;J&G8@=JR>$fU28u^})k>p>Ex*WvAnH6?BgZ``J%@*#@ zBs=yd`JeCOU7lu!K8>#d_KgM?;%oD`FEf#bf&eQuTUCZ^H6u2fjmAuOZ-PyY_bxLj zA(-gtT{X0P`N{-zvL*hdJ?q-FN||1#SBD~J=*>!#^@-{!OUmj~&1#F9{IrAj2dB6T z=WM*ieqhVSM!*B0bFzIND(12C`W)xLcbP;*eGHljRE%g@lJTZNXc)^fPP-bp%(cxV z&lai#T($_LiCnPojW9m2pivq6h~O+m_JvMV01-T;qR{AupD8{o0)gvK$Mg+s{WEOM zm9OMQjFGU;klJk3IBzn^O-hp{Wzrbs4-@9S_o%#JCu!xL|NGyGvF-og=u4K1kuMgj z4OZxwV}#wnJ-v35Q&%`zIIZ-9ACyij9G&@e6#28Ln?q+g|O6hKf4tu6%vK=qXpb3|y z<)xQ?$t>aCoZ+r2==26fMQPG~^p@?yLg85?n4wXfZuAlG% zRhpF+gN(WLzuLu6c9D+fzL37@2TRb5T zdE2jdxt(FV+j%u?8_2{vCZ^X7Q#Ua~ZJP@4rgUuAF6t?&_CIq1nPib5jo9>c#5r+6 z8VXfg;47*g-%Pr*Ou9g@ZnFf2gEz;#-^-UL@P6;YapBiuCDQPjp#(A?p&+MT;*r8x z>onUNrQvhZEigMB^-2l$3GOBh8q~IPuTz}R)mDz0Wn!S>{$S9qh{cKutz5^9dTm5R z{=$8SEXCszu4zBI^GZa%-TPM@>DgP`G<;Z$G;K@8R}nj1(9#e~&0$l}k8%@_?t>X! zP;WJv9V*7Hu`<_}hLJoXqWzhRmTqy_OyUZdfGVlNU@)CNJsqS7J+t|uEf4?S^Cl;+ z9v%Ju%&V%DS1Qs<)JWYcr5~QPdPztQomq${hJ-r1#f}O{jn5tM>HTgfs*HrdPqaG~ zj7N=FMFM~2an!E2z@pG-#f2K-Rj??LnqB20GBj6*zsOQiFfWVJ6x2YqEyh7`BvR}H z9v@F#;fos0jltv{K_t9C5sC8C!^66m13nC`SEc8l6^Q z6w7=WnZ;%t>;Pg*7}0%bDJo`={P zG!!iB?M9}(Qh93k?#z#W%pEM39Dc7Iy`l7GXTB0(_0j`7H*6cur$SP(gX&pocB~#Q z8x-e%@hIsn4GJZ)e+w$mKGOy#$IIOW^fwlChoc^xw-Vqf53tX{Zs?(E)WNGJ92A@_ z2-K`S4S`E$HM&QQkO6ji7a3d+Q_(QN{8DZloV;>aB~N$#+$Fjo=~A^Ue&+0D_~_Kg zl;|Di28BV5&GG3(AAN^K0T6jd&kCJUwb$bexE+?lxXxjD25Nogn89f`hg=q8!C|qO z^meuG8)#l+i5kpShu`7RWzn0#V1$3D{y*GP%!?4H3e9|t$+U9!(1@sm`|2F7($*qI zp{okuO?x=XJbv<8K5q)uJsj}r<_WCBuIzMD$fkHLP!ziB4Id5Buyqa zlTJ3+Qh@{!N*4h1Fh(k!sn;@FYKwiOdcE7+Njl2}L~OLc2`cGu*wRUjH0s`P+}7*f zXy~*soL^|x=maj>Hppn;7m*vt24ghtM7Mb}GSYDe_ir7~v_7lV*Pyg48nD>^!x)HU zOELHByyO7XYlo`b3t|jwxRi|>A=X61epAq<@dsPcI8?peYh=F6-Go|+nGa(I=+32t z4!w^#Bd_=RjF5*`CA9{-ku!enOJ53R$N6RFWF(XIm7W_nEPmC#IMO+U2f&p|H9og)CO1;T@L7X=C6E0)=mbeC%>ckJq0Hf18Hs;AUa|weftDI zwqn&#x z{+_SUy1{77!XXLZ@?FzGOw%2FS>;6VlUkZ{|ROfGZdl2 zN2jL34>H{=_!@U)kLG^XL07(ke-^&r4I(0s&v@a&7tuGFKSg*LUNQ@WMk;f^mHsAb zF!B2q{{rT4Mp&*~72njl+?*X;Jsvu`u9gD=!3ecN_IN>PHCtNET96#Tc73jdE>seu zQ0&V}w7PRrqT#+vW4l+aFlVO5*2cGQn5?KYjPS;i!mjtUS}Yp1RVw3#!w$X0kg)2l zvXpw7Rk-EPK1dF3(_+AhL!EX@jG|YwK6U&yl3(j22 z=s;7+RMjsjtTm{Bge!%jw9-?|BH;8!+(HNna|w$zc%S6*i4jN9(_LFR zu&m2mF?IHAtzd$CRl$TOVf02FE|FA8?hM$C4v*h&a=ylHyJU1_XFdZqw>@xG|Cl2l znVvXz%gC~`^1UFFbN4vx5x))OADPMFE80ewy>*Kkf4@!>7=goGSWhs*B9+3TXzDLqM>K~pyYQozY6MkM_obE zVE6F>CT4av;Z;Ha!!uxbAA{OhyJJMFv^1X6F-;*Qya%H|89-5 zv+k_0cR#EJx|~07pylDSHHLBm$RRvI6*_PjbrP9|xSna&x}DuYQzwe`(KGCVBRWRt z&YyKw^~mxPEu8#8S!FOJ<><8&GicHIoEhh?Gc)x3ygw7tIn9tbmViU&cf}NHh>qlZ zVQ^`V`;=C-TNQ9xtc-Ch^ch(3xw)C2G2u4uG>=keH8sI^5&JYcv`Ho#p>iygOYS(Z zt7cFx+dqAqSS-0{E4l^&pjez7!i$! zC?t-?HDbR%q}8c4E6|jX`4RW*2N501>azwkCM_roI@JnB_|U!DT5~tF4Mg49L{JqC zy3@IEioNOQ;w9k(%F?eifxFIPoehwMZ`}j@GwfK zI_w4tc}TFT)(U!im~xw4MAe1j%r^A6fxIoq&kndar$Ew+on8%DR*-I>0AB%SP)w6< zl65jYD|ruR)@OwQr;|}{Qh;GcDLT)v;Vm@Ad!GGFK?HyYIDSjiy`lAmbg%Kmjn9I6 z=3wI4UD?=gbuWi~k^8M4>cHoL^WY(B?$2hh&&(y7?`6OJb&Jm*l*#0hdkNYMIk?O3 zBUe8leE505JwLw}JtidAFlf_(DA`@*zTwPfd_Hu#XN(TLoAG$F8icY%hX?NIonDj6 zVMQWJWjS><(#1mIPMZ(yo||gm_-V9GolD96$nA6*sor$u^2^EdP-qywV4cBiw%80d z9r=0}a@s=i6n6woQ&mkc!8R3Y+1HJ(uZZLd`SM+7+(-PIqdJennR42cMmlF=K?Xd? zXW{RlvKeP5trQ)Gc37pMo;AIFc8imsz?kqcgl-us-nKR zg%tCQLN_~Ev#1@WYrYrXXYkiBf$)&1$1^|bbD|6=My9h@0ehyjz>LBO`zFEZbGQO_ zkB#l&j)9<#bn2U(p)xuvLZ({l)P~)u#1ixk(GI0j%pH}P*PF_hSI&SoE;Xf8C5qf0Ijv(*V z@WVjnLaEc|mD@9@vuOAB5&zX|YW%-TDI5RCwTgOIZhGU@oZ0wkj0bWFMi zjjvUjfU^cuE-WV6&`(h)x=%p<1R=Q4lb|1chl-omUpD7v%nQe8>!Y3}RU@1P9eo982g(et08U!!B!Ks2)IFSo09L5gQgndUUa1dr<6yhnZmNW|si( zEAWk&=N3fcM|46za~;*&R#bfdY&9(MLHKk$IgR|Xjk}F(QsJ&Nnw-~a4-|5_ybViBDYLj-W}iP|0%=3x zOJ}nALaR$HmZ`!mwPkv*--1A2s?np08d)G`GJlaoFV`r^Tg&;NV<&gzToliJl6wR`lG7A3gEp{^ zy9DkkQeHonVhY3QLJ*j-lvuo$h{P9&LJ&{A(qWb{UuO;_Q?aDi;c%<5FO>$H&*gIk z0t%(ph<5F6Pe(3fa7V&+XTrt(Ig6u{6|H_^GbCEriWO{BwNxcn>QrW1$Y+b$yl5pX z9=~c5H!@^*sKBsy>O2OuLFZPR)#vb7Gn^{Nm9u%Y$xRzKfJU zn-RSXiE1JikVZY&yo=PZ4OmM!EKAsrbti~ALTvp2pffrhZJy@?Ei%UzAj0h;LDfA~~pD|_V7W_Eaz z@tGi&Tm)b*;cGT|w3SAaba#I~Li!md*0*4q>dDL!txbXrKq8cGcWmfI=A9=7Hn2Xt zn6Lb#M+6IJnC3m<$lgThXKma)$(TQ404I+zj*I7MBMIh5ColAxU2bE@=Cm>IapzTH zDSdhE(zBFOnX)xsie2%v%VN<1RxgP4THBK+qWOGV@(zd>NP`z_A8(`>f$0oo!YJ%L37fX*n}Cw333LHorGOdWgsBvWdV&ldtXXZKeWWReRW%{2!miMLK5wU2L`W zsi11q;V2a9DWz9CT-C?pl^5pu_9x!g@P5q_hchcz%`TVud z2YuIdb~0Dg_`;4!?hAA0uEVx>dZMu~kb7R&8dAD-AvGd>E3h7#@Ax^eKFUR;_VPTz z-GT=MuL-(q#e2ww=QB?{NGdzXMm9wE<&sliGxv~y1)ALFk@7*ZQwW0TG8EmuO1}IZ z?9kbOrI8V#!R2D!IDh!fhA5xjq9SyJ#Wv*o`|@s)1e=WNo#AQ#lWn3eFX<{JY*o4} zaIf#&0Np|6f_aYeQTNVG5;D$qHn~ zr1k^?&O%VFv)gwQmKABy1~LsQnP`1Nra@aEsaj~UglJoLMc8H$BHH~$UT(MgJ?V5@ zDo5xUNJqWVV!6fHTFLvpZm;3}6LOo)VKthsc|xU%Xq0NHSEFTywYt`_)qqCdQuK$W zr6s_g-(HURN+{jMU9VOs#RW55a5?%7t=@8am4@HqzP*R8Be97f0^mr*W_K6A4Piau zD^7*k7xbxY(ddis{6@^2L~B7tq17oQQk}U#4C0vNXKIyR31LsMOy{y#IgTYsC6YZG zdY8wb*)A2Qhu3V5CbOAD!0U9NskvC8Q2CMnak>o!H8fU&xl+;Oh{jx|P>g(Gb21%5 zR3Y_d^L^JOQ2e4V!Izga5v>-CZUbykgx5rD2Qsoy74ewh7QyOT>o8Q0+3jS@IFu3L zI1WJl5b^Xi`^hORgr_%8P(j3LvVlq^uir|g68pNyRcOn#4?05hXu+*+m0*+jCD{n^ zDs^X%nj>n8JoRIPE+q5pQq&N-=w|&*3;oG_x(MHWt}gWgYlX#L$1L&U`GEe@yM?S1 zp$nH?g)N^e7ola%h?tTQwX7wGP>ZAipWhTnL?bjo?eIs@)F+JbXuAy4 zr(TZS#bYOL_v*YRFLI7{X6K*a?6G;PSZGu0^`Kj#{=$;?#O*kCBnmX8RElqts#RFy zVzWo5lc|N?+{&hvE($#-2D%4thW-Sj*6MUZyL0IY?)F%WWFQ$cbjd2*n2Q@U>o1Be zcxm1x7MhVj*GUg;pDGJMW>9qR*mnt;Y7VJG)<`7etk*PCemup{)_^^AA^PPmt(AvK zqL0Mj;~hWdT^&N;FUqm&i-t963 z9VREUCO1$RA|bTOfG*q9YjR7)Abuk7M}4ve-MhFaJOhQK&tdR1zTN@}q}W(ex8 zDyd$ER0lxKyBjYeax~0K;9157~OGlt?(vt z{SneGJd?Cuh1ST|TzVGUeEIq3uuZ}*kPFLcCMfjNGtVm{r{6%X>i~82=#}I$;U(k( z^z{+mc=Z)$2s6hnI`43ss3e>_`5I8&|Kgp}Wv~biqBJAQ$HSVUtBPM+)C}Mo-Wu@X z1-{~4A_N!w_xz%$d$2GwCEmZ~WoRhI*H9d3e5OJbG-R1O@o4PJ{tyQmKhIC3b16SM zB1?pmP}7NZ;SkaFCz8xVC$FV!6I%$`N#;+#&=P0jCsR{DdF^Th_{tyNuhQ$y>5w-T zh$gU8k%*KIjf{4bTH5k*^hp)9RVrz%L9h8PH-u^+DN(-pi^GSxKi+c7E#%0(_ukut zY~~&3yedOgd^{bENq|-Ts-4gOPjIIhbXs}FiCrF+O>Z2@iRB`7*PeZslZ{QN688I| z$W~fm1jIsNX*@L^Kd!}EN@~#q&>mqxK5*)FL@85gthN|Rhn(R3%7kvCNue>D%}Lll zuuC3z}<5Sc>D! zO(c6QbNwacBGOK~?d8$ch21<%O6;~9$T1c@wl5uGl=^v00t;gn#KjpB{_I=`o!2=} zhAtIKUd2VMkH&(ichu(HVf?&;1%t)G(~5Z?iK+}WoMXB`=sV6GQ4)Fu??|ulwyEJf z&%GUoJAGau^m|<8E>M`ncfG?CvgVt#L)d7!G&WO-AT*a^|ZQ;^i0#rfEWi8t6 zs-WF|m!c9$r@gnC2$3UN}WY$H`jZO48HM46Y`;+QK5K z1xPQ@4%U5SY=TT~Aka}886pk+g@uj|mgOAN5vGWG?R@lGs7KiU49v7(eJr+RSWgs8 ztv{$9Qe7K~9exQ^K~K|njl`dABhR%V>*Fb%#@$tC8r?F-G-_&R0>LH~EKmz7xPEx@ zO0Ujibp~8EGeo>DuW-M;2U4{Up{c69_%+*gv?H_ZTW7;;h$P&{x#(-OFS(QnweqO) zICtq>C}eZ&nc7?wDMae_{YNe)8<(KO-R6se^B=zLw&ao}cR%z{YG^3Me-uy#9j|Fo z0E(JAUoXAmJuv$gCr#HmA9vuaeu zrgz@C9XFDC&u(iq4|#n*yA!w5i`;c0B6dS;-3Z|i&?AwrmIOnsO|AZbOaux8^A>l9 znasTGvjM3~*sKm1J9`y<3z@AmOUMuZl59#gzw{UGZYOMJjWHNY%tWG^Y$nHro6a2{ zYek0vNy-Ts90mb~WXpz)t%0QzlV=TXK4rMjiMslq`E4jL2zl%-?(ejlWV)~K?EZeL z3F_i?h^Xz&qVffrw7`YW5!@_z6sngW2!1X29r&a_A&>r?$%8r%KIwdR4D9IHyyjvG z)+dt8SeT132YRydR*;U~EPzLcnSRHIg!rcJw((&BJ(>|0BL7+`Mi##lUQxHY^erRw ziPRqB>pGZ0Kbt{tSsW@XG}$a~(gQrXrj6!eD-ufuQEsJ+PjE*K9=)4Ai@VoA{CVyU zfVX_j7bX0X(2z6~&Qk4`5htMA?{Pk~h&z7ETGFcQpCcDDazR-v5qo&D5k;rVwviIbLZVS-(>P&F@XyPHF$^ zG4Nq+3Vp?BI$12*yREAYU1ny|Z*Zar!s5|6Z_3GqfRg)mO>UaR+ev`{Q_yjAbRsNN zNLABM-%KLUrBYnKB^D0RCKphF_jn*D;MJiqa73rks$HgF#D-ljg#b@Lb||7o$+or_ z1ClCqSmekagDeeou_F2pi%7=giX~jWcr1Vh-(r^!!Mqi%N5o=cb0vKNd(`7&5zUCr zZo9!?vzTD)Avqb0rj;02r8}6awk4AmjZP;OW%J9qx1KPd|5t(0=`ug#{^bK#%9HU# zy}(Ef@Kt{ZU)9cc99#|iem4BoEj21lNmYS&uVQNL1tuU|KT6iJYA^BYk@2)R8MlC( zwV7;S&)f&j4HW-}8K`1Xu8qz^G=Py2L)jg~%A#I!o}&4 z2UFm6(xip~j}V^=#m{Hq6%-WE^~^8fM&N_kri8GCon^LDXdFx|-bsN@0M`2_csKO- zLBT^bx4jteAH#v>jMr&5H1BEou@KSg(Q5U~3->TfPLm^pB?RT&kz&;!N)K=kVExD?8Kk!j(G5HHmmtd}A3t!; zSN>EDSfCjja=CcjMD(2g_{;2X*(y$wG;~cb5ZoYmUeHvFpLrJgfS*sctYNP`j>)jAbm_RN^`AgNWtkbhQXLBrr+&_Sk|L$i1&i}I^z zuYktv(szg$K1H}`xSISz;f)tv1DJHYXQeM?xi|kX?h5Oz zDyuy1b|sRw2zS@Tc8fvo!l(j6o1`N*2z4p-hdiFPv6TQ|$)(lyg5~O~SI4qL%$ATg zWrU}JqBZw=X|L z&N@K$pSpRyaP>-N>qchn>EvW#^XF^GNP$V@ntEr(%b_Wgx?uPkvRO~j@&O31T_6|r zCs>M~&wosZL;PPgW)9N7g$&ZyBJry7zv*?o6lA?RNxNZP>e*+X#n|@`+rDBo zmZcbE(H96zEj-x*1M@Yn+M;r(11^J!Ss6kePp*mQG7xm3jHT8aQ_wAP5Pm39DP$kz zN|LGaiIP>^VLf>N_(Vxz$L6&tkBa5u8t}bOqfja-A;Y4TGCH|dJ@v_)LLr~~#DbcF zm{nFVgJylHbjj3z$WOW7cw|zc7Nl>iULRqQ>W?KXJt2i%tXvGr1k$^ZeCZaH z@I7&om5?u=NlqcvRm+$~!Zo1n?O>82A8SnOMS#^F7pBxL80^$cio`-S3v3tN*QOxx za)8I_*3&9ITx#ARby1JF9{AFxX8v#JpW`-7-%9_c4(#D&t&3-vk~CkPGBTK^DH(Vt zd|Ec?JNXQ#A7VwGXgT-XQ}(2@rA#^-jJPYrX0>bcfvC^5d(Ua7LGcA!L1wMrstN^D z5vzh2x&Qf{R?Q}&GS(p4Y|7$5_Cnlx8@;p zcL+t-SX5Hb_y@!eqfqH^XXR#{ehy}*{gOK$vOD$HyxMG2q%|fpb40Wz*Z)p6S9Yet zfpGlCKl9pM%7if%h`-aH>p^+&*jc#V&BViDV@54TGt`796^@du*3N=S3Pi0kgCXFp ze40+LEEd=2a)(SH>_O?uVAr~oVu{_Qb4NWHgWm+9Un@S?wRx-~=aPvm7+tQElAYsA z+Jthc?4ldbL|aY|E0%raH26TJ_NdJf+qw| z3%1r4?R$(o%s%l5Q+twpL-;g#@N7)lTR@4y&)7s(u@Oix&n4_hq1o@$4CAn2NI*Is zW|cuN;}q_Hh}_S9^8x1Ix5%Tyr^w@{Gvny7Y;EYTY4t_57aA;ShK`q`FYt%>v|UsG z6brK=W?n&2m2;e+92YVJ?n;F)LNRMivrN?#ref%PEHAs%?9PH4P=S;n>In1kii8UO zOytsRMWLc!#+`j)l@X93kkCuv51S`YB*1(vquwAHJ$T9~2M!buAKt(JJZ%#%biFlU z4A^L|f^efK;K>5|qihF8>?cPr@MzK20qL}oskK(UOf7ew=R|3g0kcW5Bcz}?KdqW% ze!5qoH>fVMn=GA4iNR>h>Gg)CX|#H=C04j11KA>Nj9jrYi&;Rz64JlrdGqGwk>)4A zF6WUA63I-Cc-kdHayMkP+WdZ7a#!}`%+pV2PR{Nk-a%+QRKv9}4Alg%~j*-+=F_r(fjric|m_(#^{vP5%_94QjDKWrP6O->h#0>V?1$I^C4dK(uXs=qY7L3YRolnkvD-64O+EM zh*?cNodzut7UmV^>Hm|zmYLY+)|)ckMK%MRw-&Y2?M}(WD66&;?Rl$l?YR#l2*$^! zj)cI~LA&&w>}u{(_>D+n-bFz{p-9|kQ3AoSUL22wDPzhahe^h~G4+s7hDg_h=>~Gt z<26Q=QR`AO?4qbttyQXZIzC{3D-<$B(DDGNV?X{&L?xFh z`~eny9CqNfWKv6IXCJP&FTOZjtL>kUDyu|y`bq@bGSl3VxgLu~j%qBIDHV2ScBHm# z+jiZK9XIXXP44yU+qBWbq(;+e&JU)}&?X-K%MxCk(c!|mAbm=jz!R*0s0g(pWU+O$~y#xZS zAb=dqZ_x*!Mn|L>QXWMg7wreyAvl5eArA@e6Feh$U9hD#|LoJrHh7PF$Vt1%2|I|a zj;$IXT2_yi5LQKDdn>{C&MxmGa*Kh{uo%XolQP>+K9SkUK6C0`cK1DGt8m|0LT=AipV{d~##yA$*c@6DnmljdE~1?!o!p(SEHDU2crb$=X~2`D z%y~sLmi+MOc|N1vt`BJJ7Gn9h%uj{*G51}-w5=(!iF?fFShy`5kr@C76q@V{%35u> zSj>uytVrWZ6yr%X+D5Y;b2J*9MCL@JW3kw7;)cxtiugLF^N15uru6z& zD0FcMf-knfexNBwsC5}NN?9D)R}njPyUFQx>V-IpB9q1BV#Q*Y(`oZq&{%*R7jmDxyMz4&B+xY_?MK)zu>1 zWvb)oS0w-HI<@%##gt4xf-$}I7p1@D1!MM0vpcz4QBY@I;wsO>aEiGHNO#-%m3!pi zIoz{&S#Rs&t$QSxs(kVq9I92^>#@M*EoWiOv^-Hx`;3W%+sum05nDR$HCrueXT;`_ zq1R0pwI<^hIaXnm`}JQz5bd)0d})t65!EJpOJT|`d;O|SNs@F10``191ej-W_i(RO zs?n%@y#u=@hZcoZNUgaB`Zh3D*QU*zD|&@qA_M3{5%9avFX;}VV61jJY+8@O0eDNm z9SR`lsI)k9@npn`u`{-?+UqvNLN28O9Jv!q*Y2UVlyYso4!(dqI@c+lj8;8%3Ia9D z$}PYj&09bgj+4rFhK?Azu{+3I03H&oPi+R5w$W??6sIEBsa0q0JGniysu*0o|0)Hh z3w3}(ZWnaD!>@^Y!&VbGa=aERDEwUkligv}tCid@$&(z*^j5g?f-)*%GVUGrbnXXk zy-4cMD&4QT#Cij(Oa?>Y0P9y-6hV#AZ1-90$keLUz76Y6bQn#mH=Z3`s;yo9r&H&yN2g_vd2qoHyUhop8cqCT+m$E|ph-y-FL|C^N?r zSbq^_OWg*nL=5~pyHGWMLGWG5MQk zlTFS4L-U#REB`{`#_9X~dBp!}`t;EQI?LV0&Kmf)g>T5ck5BdwM?Bp7?^=Rh@1lTJ zC)23%c_jG(RhGG2Zu@lyOMqf23Npz>NFJLUL3a$4K_u%-c)~gz^E_tf2+!#teXkIc zKA=_T)OMXoxX@}H>hrpkYAr0X-jH|8WkcN8dJQ(cE79FiLJ?C@=X?w z?yhJ&7&LPq&SI6KZ3%&>!>^K~Uk!jWvrG-fOAlz9z{z6P-K+38 zY;J>rQK!0khuwu>*lU~Twcul@Q3Mw=ASHv-pjHL;SUU&C;xfiH6isVEOsz7R)ga%| z+B!N9>H}t<{$KN3b3Qa8O8oI+?T}A_7w!dxf~0JK?J*w8b*6m2fXyPtt7%nEAISe~ z8og4i5D~N47in#6XOiY!LjyUW8Z{CNICD%UImQZs&BB55k`{O%y$aO>R2f`GheNBe zJEy+uONPKm>ZdyTA>y|p- z%-+%yO#^>&|IsQF=mO-yXd{fbMS)7dvZ=S30Pg#yTHD*0S9&WTD3I&3`Id?I-{;=r zJ|z?efcG(gUc7HH|KoiiH#jw%LMH)%u${gSOzqS%5`fD^tjjj@W@uq=`rS~$q@BvV zs-ka*e^cN3M<@BHhkG?*Vle9H%A=Q(nz>qNu5ouV5ZE%qC|Mn~h z#H8d-x2u$nx-*&7NA`pbmK=3>xiaT!@lBnuYXvj%y% zj_qa+a6i_fv0Cab0J)>!{zAIS8(Vgj%ez`Ol3UlVy?oWGE6BW}8R=As(&==gjg0TF z{T{GADP%Nlf`DKYEPw0KFOsNvgfvsJa1+_Ej;vV<%K9Z6*D{OP&Fh)T2}Z&XH|6af zl?`Mf={v_x&PvX}U6@J6Xh_pgS#X@nyp@8D;r+wu^F@sgq+i{+i_k_}YB!nN z%l~ACxsQOkIWOvuCZcJ70wi%F@eNUbYo*=OR?dD@(V1=D&IJ=&qiaSc=MPPejRhJ$R;<(<)d zIx2}scrYJxN%CVZd5CBqB-*JA|78WY1f4Yw39)m(Lb06jW)w8B@E*r4CwElIUCbSe z7M(Lb{@p_1RX~nV;426txO~SlyD+6G@g|fo?#l2n0()nL;tY z?e>n2+i$;}ot%36ZJ1wAZXW=33h=|(Q`TrAsZndtMz2#}!+p$*<+w;ESzfDgcQ6-N zy;_G3$vdgcok|C%t{fR;TAzFFuW!6D@IdK28A4h1Hml1H7Vlh2*`P4m94+(Nhgcsj8{rTx-@@*h5H7f^AH)

Bp0$!_d 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�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

oDMxnF^O#!>SnC!{Ohm%QN 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

1hr_H-9?()S)J|`;Dm^He*`3rlR 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ⅈoLw(HL+-*_>($+4xpV?6$iCnA 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%0AiKuMD4QXEFS;-=cw0fi!ff0Npw%F| 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℞3$6I-m>Z(!g)^9k~uTgki*2S+tHJ;%lfk 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

P^zxm^Tfxv{ObS8|Em74 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 zoBuceZ~ou>zxjXj|K|VA|C|3e|8M@^{J;5s^Z(}m&HtPKH~(+`-~7M%fAjz5|IPoK z|2O|{{@?t+`G52O=KszAoBuceZ~ou>zxjXj|K|VA|C|3e|8M@^{J;5s^Z(}m&HtPK zH~(+`-~7M%fAjz5|IPoK|2O|{{@?t+`G52O=KszAoBuceZ~ou>zxjXj|K|VA|C|3e z|8M@^{J;5s^Z(}m&HtPKH~(+`-~7M%fAjz5|IPoK|2O|{{@?t+`G52O=KszAoBuce zZ~ou>zxjXj|K|VA|C|3e|8M@^{J;5s^Z(}m&HtPKH~(+`-~7M%fAjz5|IPoK|2O|{ z{@?t+`G52O=KszAoBuceZ~iC#C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh? zC;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh? zC;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh? zC;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh? zC;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh? zC;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh? zC;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh? zC;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh? zC;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh? zC;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh? zC;lh?C;lh?C;n&tXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mY zXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mY zXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mY zXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mY zXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mY zXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mY zXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mY zXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mY zXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mY zXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mY zXZ{!d7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi z7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi z7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi z7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi z7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi z7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi z7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi z7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi z7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi z7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7yeiNSN>Q2 zSN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2 zSN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2 zSN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2 zSN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2 zSN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2 zSN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2 zSN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2 zSN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2 zSN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2 zSN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN=EtH~u&NH~u&NH~u&N zH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&N zH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&N zH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&N zH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&N zH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&N zH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&N zH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&N zH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&N zH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&N zH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~x42cm8+&cm8+&cm8+&cm8+&cm8+& zcm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+& zcm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+& zcm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+& zcm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+& zcm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+& zcm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+& zcm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+& zcm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+& zcm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+& zcm8+&cm8+&cm8+&cm8+&cm8+&cm6;8fB66K|Kb0`|A+q%{~!K8{D1iW@c-fe!~ci> z5C0$jKm33A|M36e|HJ=>{}2Bk{y+SG`2X<#;s3+`hyM@%AO1i5fB66K|Kb0`|A+q% z{~!K8{D1iW@c-fe!~ci>5C0$jKm33A|M36e|HJ=>{}2Bk{y+SG`2X<#;s3+`hyM@% zAO1i5fB66K|Kb0`|A+q%{~!K8{D1iW@c-fe!~ci>5C0$jKm33A|M36e|HJ=>{}2Bk z{y+SG`2X<#;s3+`hyM@%AO1i5fB66K|Kb0`|A+q%{~!K8{D1iW@c-fe!~ci>5C0$j zKm33A|M36e|HJ=>{}2Bk{y+SG`2X<#;s3+`hyM@%AO1i5fB66K|Kb0`|A+q%{~!K8 z{D1iW@c-fe!~ci>5C0$jKm33A|M36e|HJ=>{}2Bk{y+SG`2X<#;s3+`hyM@%AO1i5 zfB66K|Kb0`|A+q%{~!K8{D1iW@c-fe!~ci>5C0$jKm33A|M36e|HJ=>{}2Bk{y+SG z`2X<#;s3+`hyM@%AO1i5fB66K|Kb0`|A+q%{~!K8{D1iW@c-fe!~ci>5C0$jKm33A z|M36e|HJ=>{}2Bk{y+SG`2X<#;s3+`hyM@%AO1i5fB66K|Kb0`|A+q%{~!K8{D1iW z@c-fe!~ci>5C0$jKm33A|M36e|HJ=>{}2Bk{y+SG`2X<#;s3+`hyM@%AN~*i5B?AS z5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS z5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS z5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS z5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS z5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS z5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS z5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS z5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS z5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS z5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B^X7PySE-PySE-PySE- zPySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE- zPySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE- zPySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE- zPySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE- zPySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE- 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 IU%3bVU)*)=ga7~l diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_loader.c b/lib/libesp32_lvgl/lvgl/src/font/lv_binfont_loader.c similarity index 78% rename from lib/libesp32_lvgl/lvgl/src/font/lv_font_loader.c rename to lib/libesp32_lvgl/lvgl/src/font/lv_binfont_loader.c index f7c061bbe..3d65de9ad 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_loader.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_binfont_loader.c @@ -1,5 +1,5 @@ /** - * @file lv_font_loader.c + * @file lv_binfont_loader.c * */ @@ -12,7 +12,7 @@ #include "../lvgl.h" #include "../misc/lv_fs.h" -#include "lv_font_loader.h" +#include "lv_binfont_loader.h" /********************** * TYPEDEFS @@ -78,31 +78,26 @@ static unsigned int read_bits(bit_iterator_t * it, int n_bits, lv_fs_res_t * res * GLOBAL FUNCTIONS **********************/ -/** - * Loads a `lv_font_t` object from a binary font file - * @param font_name filename where the font file is located - * @return a pointer to the font or NULL in case of error - */ -lv_font_t * lv_font_load(const char * font_name) +lv_font_t * lv_binfont_create(const char * path) { - lv_fs_file_t file; - lv_fs_res_t res = lv_fs_open(&file, font_name, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) - return NULL; + LV_ASSERT_NULL(path); - lv_font_t * font = lv_mem_alloc(sizeof(lv_font_t)); - if(font) { - memset(font, 0, sizeof(lv_font_t)); - if(!lvgl_load_font(&file, font)) { - LV_LOG_WARN("Error loading font file: %s\n", font_name); - /* - * When `lvgl_load_font` fails it can leak some pointers. - * All non-null pointers can be assumed as allocated and - * `lv_font_free` should free them correctly. - */ - lv_font_free(font); - font = NULL; - } + lv_fs_file_t file; + lv_fs_res_t fs_res = lv_fs_open(&file, path, LV_FS_MODE_RD); + if(fs_res != LV_FS_RES_OK) return NULL; + + lv_font_t * font = lv_malloc_zeroed(sizeof(lv_font_t)); + LV_ASSERT_MALLOC(font); + + if(!lvgl_load_font(&file, font)) { + LV_LOG_WARN("Error loading font file: %s", path); + /* + * When `lvgl_load_font` fails it can leak some pointers. + * All non-null pointers can be assumed as allocated and + * `lv_binfont_destroy` should free them correctly. + */ + lv_binfont_destroy(font); + font = NULL; } lv_fs_close(&file); @@ -110,72 +105,54 @@ lv_font_t * lv_font_load(const char * font_name) return font; } -/** - * Frees the memory allocated by the `lv_font_load()` function - * @param font lv_font_t object created by the lv_font_load function - */ -void lv_font_free(lv_font_t * font) +#if LV_USE_FS_MEMFS +lv_font_t * lv_binfont_create_from_buffer(void * buffer, uint32_t size) { - if(NULL != font) { - lv_font_fmt_txt_dsc_t * dsc = (lv_font_fmt_txt_dsc_t *)font->dsc; + lv_fs_path_ex_t mempath; - if(NULL != dsc) { + lv_fs_make_path_from_buffer(&mempath, LV_FS_MEMFS_LETTER, buffer, size); + return lv_binfont_create((const char *)&mempath); +} +#endif - if(dsc->kern_classes == 0) { - lv_font_fmt_txt_kern_pair_t * kern_dsc = - (lv_font_fmt_txt_kern_pair_t *)dsc->kern_dsc; +void lv_binfont_destroy(lv_font_t * font) +{ + if(font == NULL) return; - if(NULL != kern_dsc) { - if(kern_dsc->glyph_ids) - lv_mem_free((void *)kern_dsc->glyph_ids); + const lv_font_fmt_txt_dsc_t * dsc = font->dsc; + if(dsc == NULL) return; - if(kern_dsc->values) - lv_mem_free((void *)kern_dsc->values); - - lv_mem_free((void *)kern_dsc); - } - } - else { - lv_font_fmt_txt_kern_classes_t * kern_dsc = - (lv_font_fmt_txt_kern_classes_t *)dsc->kern_dsc; - - if(NULL != kern_dsc) { - if(kern_dsc->class_pair_values) - lv_mem_free((void *)kern_dsc->class_pair_values); - - if(kern_dsc->left_class_mapping) - lv_mem_free((void *)kern_dsc->left_class_mapping); - - if(kern_dsc->right_class_mapping) - lv_mem_free((void *)kern_dsc->right_class_mapping); - - lv_mem_free((void *)kern_dsc); - } - } - - lv_font_fmt_txt_cmap_t * cmaps = - (lv_font_fmt_txt_cmap_t *)dsc->cmaps; - - if(NULL != cmaps) { - for(int i = 0; i < dsc->cmap_num; ++i) { - if(NULL != cmaps[i].glyph_id_ofs_list) - lv_mem_free((void *)cmaps[i].glyph_id_ofs_list); - if(NULL != cmaps[i].unicode_list) - lv_mem_free((void *)cmaps[i].unicode_list); - } - lv_mem_free(cmaps); - } - - if(NULL != dsc->glyph_bitmap) { - lv_mem_free((void *)dsc->glyph_bitmap); - } - if(NULL != dsc->glyph_dsc) { - lv_mem_free((void *)dsc->glyph_dsc); - } - lv_mem_free(dsc); + if(dsc->kern_classes == 0) { + const lv_font_fmt_txt_kern_pair_t * kern_dsc = dsc->kern_dsc; + if(NULL != kern_dsc) { + lv_free((void *)kern_dsc->glyph_ids); + lv_free((void *)kern_dsc->values); + lv_free((void *)kern_dsc); } - lv_mem_free(font); } + else { + const lv_font_fmt_txt_kern_classes_t * kern_dsc = dsc->kern_dsc; + if(NULL != kern_dsc) { + lv_free((void *)kern_dsc->class_pair_values); + lv_free((void *)kern_dsc->left_class_mapping); + lv_free((void *)kern_dsc->right_class_mapping); + lv_free((void *)kern_dsc); + } + } + + const lv_font_fmt_txt_cmap_t * cmaps = dsc->cmaps; + if(NULL != cmaps) { + for(int i = 0; i < dsc->cmap_num; ++i) { + lv_free((void *)cmaps[i].glyph_id_ofs_list); + lv_free((void *)cmaps[i].unicode_list); + } + lv_free((void *)cmaps); + } + + lv_free((void *)dsc->glyph_bitmap); + lv_free((void *)dsc->glyph_dsc); + lv_free((void *)dsc); + lv_free(font); } /********************** @@ -262,7 +239,7 @@ static bool load_cmaps_tables(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_ds switch(cmap_table[i].format_type) { case LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL: { uint8_t ids_size = sizeof(uint8_t) * cmap_table[i].data_entries_count; - uint8_t * glyph_id_ofs_list = lv_mem_alloc(ids_size); + uint8_t * glyph_id_ofs_list = lv_malloc(ids_size); cmap->glyph_id_ofs_list = glyph_id_ofs_list; @@ -278,7 +255,7 @@ static bool load_cmaps_tables(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_ds case LV_FONT_FMT_TXT_CMAP_SPARSE_FULL: case LV_FONT_FMT_TXT_CMAP_SPARSE_TINY: { uint32_t list_size = sizeof(uint16_t) * cmap_table[i].data_entries_count; - uint16_t * unicode_list = (uint16_t *)lv_mem_alloc(list_size); + uint16_t * unicode_list = (uint16_t *)lv_malloc(list_size); cmap->unicode_list = unicode_list; cmap->list_length = cmap_table[i].data_entries_count; @@ -288,7 +265,7 @@ static bool load_cmaps_tables(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_ds } if(cmap_table[i].format_type == LV_FONT_FMT_TXT_CMAP_SPARSE_FULL) { - uint16_t * buf = lv_mem_alloc(sizeof(uint16_t) * cmap->list_length); + uint16_t * buf = lv_malloc(sizeof(uint16_t) * cmap->list_length); cmap->glyph_id_ofs_list = buf; @@ -319,18 +296,18 @@ static int32_t load_cmaps(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, u } lv_font_fmt_txt_cmap_t * cmaps = - lv_mem_alloc(cmaps_subtables_count * sizeof(lv_font_fmt_txt_cmap_t)); + lv_malloc(cmaps_subtables_count * sizeof(lv_font_fmt_txt_cmap_t)); memset(cmaps, 0, cmaps_subtables_count * sizeof(lv_font_fmt_txt_cmap_t)); font_dsc->cmaps = cmaps; font_dsc->cmap_num = cmaps_subtables_count; - cmap_table_bin_t * cmaps_tables = lv_mem_alloc(sizeof(cmap_table_bin_t) * font_dsc->cmap_num); + cmap_table_bin_t * cmaps_tables = lv_malloc(sizeof(cmap_table_bin_t) * font_dsc->cmap_num); bool success = load_cmaps_tables(fp, font_dsc, cmaps_start, cmaps_tables); - lv_mem_free(cmaps_tables); + lv_free(cmaps_tables); return success ? cmaps_length : -1; } @@ -344,7 +321,7 @@ static int32_t load_glyph(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, } lv_font_fmt_txt_glyph_dsc_t * glyph_dsc = (lv_font_fmt_txt_glyph_dsc_t *) - lv_mem_alloc(loca_count * sizeof(lv_font_fmt_txt_glyph_dsc_t)); + lv_malloc(loca_count * sizeof(lv_font_fmt_txt_glyph_dsc_t)); memset(glyph_dsc, 0, loca_count * sizeof(lv_font_fmt_txt_glyph_dsc_t)); @@ -414,7 +391,7 @@ static int32_t load_glyph(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, } } - uint8_t * glyph_bmp = (uint8_t *)lv_mem_alloc(sizeof(uint8_t) * cur_bmp_size); + uint8_t * glyph_bmp = (uint8_t *)lv_malloc(sizeof(uint8_t) * cur_bmp_size); font_dsc->glyph_bitmap = glyph_bmp; @@ -475,15 +452,15 @@ static int32_t load_glyph(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, * the pointer should be set on the `lv_font_t` data before any possible return. * * When something fails, it returns `false` and the memory on the `lv_font_t` - * still needs to be freed using `lv_font_free`. + * still needs to be freed using `lv_binfont_destroy`. * - * `lv_font_free` will assume that all non-null pointers are allocated and + * `lv_binfont_destroy` will assume that all non-null pointers are allocated and * should be freed. */ static bool lvgl_load_font(lv_fs_file_t * fp, lv_font_t * font) { lv_font_fmt_txt_dsc_t * font_dsc = (lv_font_fmt_txt_dsc_t *) - lv_mem_alloc(sizeof(lv_font_fmt_txt_dsc_t)); + lv_malloc(sizeof(lv_font_fmt_txt_dsc_t)); memset(font_dsc, 0, sizeof(lv_font_fmt_txt_dsc_t)); @@ -532,7 +509,7 @@ static bool lvgl_load_font(lv_fs_file_t * fp, lv_font_t * font) } bool failed = false; - uint32_t * glyph_offset = lv_mem_alloc(sizeof(uint32_t) * (loca_count + 1)); + uint32_t * glyph_offset = lv_malloc(sizeof(uint32_t) * (loca_count + 1)); if(font_header.index_to_loc_format == 0) { for(unsigned int i = 0; i < loca_count; ++i) { @@ -555,7 +532,7 @@ static bool lvgl_load_font(lv_fs_file_t * fp, lv_font_t * font) } if(failed) { - lv_mem_free(glyph_offset); + lv_free(glyph_offset); return false; } @@ -564,12 +541,13 @@ static bool lvgl_load_font(lv_fs_file_t * fp, lv_font_t * font) int32_t glyph_length = load_glyph( fp, font_dsc, glyph_start, glyph_offset, loca_count, &font_header); - lv_mem_free(glyph_offset); + lv_free(glyph_offset); if(glyph_length < 0) { return false; } + /*kerning*/ if(font_header.tables_count < 4) { font_dsc->kern_dsc = NULL; font_dsc->kern_classes = 0; @@ -599,7 +577,7 @@ int32_t load_kern(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, uint8_t f } if(0 == kern_format_type) { /*sorted pairs*/ - lv_font_fmt_txt_kern_pair_t * kern_pair = lv_mem_alloc(sizeof(lv_font_fmt_txt_kern_pair_t)); + lv_font_fmt_txt_kern_pair_t * kern_pair = lv_malloc(sizeof(lv_font_fmt_txt_kern_pair_t)); memset(kern_pair, 0, sizeof(lv_font_fmt_txt_kern_pair_t)); @@ -619,8 +597,8 @@ int32_t load_kern(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, uint8_t f ids_size = sizeof(int16_t) * 2 * glyph_entries; } - uint8_t * glyph_ids = lv_mem_alloc(ids_size); - int8_t * values = lv_mem_alloc(glyph_entries); + uint8_t * glyph_ids = lv_malloc(ids_size); + int8_t * values = lv_malloc(glyph_entries); kern_pair->glyph_ids_size = format; kern_pair->pair_cnt = glyph_entries; @@ -637,7 +615,7 @@ int32_t load_kern(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, uint8_t f } else if(3 == kern_format_type) { /*array M*N of classes*/ - lv_font_fmt_txt_kern_classes_t * kern_classes = lv_mem_alloc(sizeof(lv_font_fmt_txt_kern_classes_t)); + lv_font_fmt_txt_kern_classes_t * kern_classes = lv_malloc(sizeof(lv_font_fmt_txt_kern_classes_t)); memset(kern_classes, 0, sizeof(lv_font_fmt_txt_kern_classes_t)); @@ -656,9 +634,9 @@ int32_t load_kern(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, uint8_t f int kern_values_length = sizeof(int8_t) * kern_table_rows * kern_table_cols; - uint8_t * kern_left = lv_mem_alloc(kern_class_mapping_length); - uint8_t * kern_right = lv_mem_alloc(kern_class_mapping_length); - int8_t * kern_values = lv_mem_alloc(kern_values_length); + uint8_t * kern_left = lv_malloc(kern_class_mapping_length); + uint8_t * kern_right = lv_malloc(kern_class_mapping_length); + int8_t * kern_values = lv_malloc(kern_values_length); kern_classes->left_class_mapping = kern_left; kern_classes->right_class_mapping = kern_right; diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_binfont_loader.h b/lib/libesp32_lvgl/lvgl/src/font/lv_binfont_loader.h new file mode 100644 index 000000000..c8537ebae --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_binfont_loader.h @@ -0,0 +1,61 @@ +/** + * @file lv_binfont_loader.h + * + */ + +#ifndef LV_FONT_LOADER_H +#define LV_FONT_LOADER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Loads a `lv_font_t` object from a binary font file + * @param path path where the font file is located + * @return pointer to font where to load + */ +lv_font_t * lv_binfont_create(const char * font_name); + +#if LV_USE_FS_MEMFS +/** + * Loads a `lv_font_t` object from a memory buffer containing the binary font file. + * Requires LV_USE_FS_MEMFS + * @param buffer address of the font file in the memory + * @param size size of the font file buffer + * @return pointer to font where to load + */ +lv_font_t * lv_binfont_create_from_buffer(void * buffer, uint32_t size); +#endif + +/** + * Frees the memory allocated by the `lv_binfont_create()` function + * @param font lv_font_t object created by the lv_binfont_create function + */ +void lv_binfont_destroy(lv_font_t * font); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_FONT_LOADER_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font.c index d4cc27e19..6cbd8e0d1 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font.c @@ -8,9 +8,11 @@ *********************/ #include "lv_font.h" +#include "../misc/lv_text.h" #include "../misc/lv_utils.h" #include "../misc/lv_log.h" #include "../misc/lv_assert.h" +#include "../stdlib/lv_string.h" /********************* * DEFINES @@ -40,27 +42,14 @@ * GLOBAL FUNCTIONS **********************/ -/** - * Return with the bitmap of a font. - * @param font_p pointer to a font - * @param letter a UNICODE character code - * @return pointer to the bitmap of the letter - */ -const uint8_t * lv_font_get_glyph_bitmap(const lv_font_t * font_p, uint32_t letter) +const void * lv_font_get_glyph_bitmap(lv_font_glyph_dsc_t * g_dsc, uint32_t letter, + lv_draw_buf_t * draw_buf) { + const lv_font_t * font_p = g_dsc->resolved_font; LV_ASSERT_NULL(font_p); - return font_p->get_glyph_bitmap(font_p, letter); + return font_p->get_glyph_bitmap(g_dsc, letter, draw_buf); } -/** - * Get the descriptor of a glyph - * @param font_p pointer to font - * @param dsc_out store the result descriptor here - * @param letter a UNICODE letter code - * @param letter_next the next letter after `letter`. Used for kerning - * @return true: descriptor is successfully loaded into `dsc_out`. - * false: the letter was not found, no data is loaded to `dsc_out` - */ bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_out, uint32_t letter, uint32_t letter_next) { @@ -77,7 +66,7 @@ bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_o dsc_out->resolved_font = NULL; while(f) { - bool found = f->get_glyph_dsc(f, dsc_out, letter, letter_next); + bool found = f->get_glyph_dsc(f, dsc_out, letter, f->kerning == LV_FONT_KERNING_NONE ? 0 : letter_next); if(found) { if(!dsc_out->is_placeholder) { dsc_out->resolved_font = f; @@ -94,27 +83,20 @@ bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_o #if LV_USE_FONT_PLACEHOLDER if(placeholder_font != NULL) { - placeholder_font->get_glyph_dsc(placeholder_font, dsc_out, letter, letter_next); + placeholder_font->get_glyph_dsc(placeholder_font, dsc_out, letter, + placeholder_font->kerning == LV_FONT_KERNING_NONE ? 0 : letter_next); dsc_out->resolved_font = placeholder_font; return true; } #endif - if(letter < 0x20 || - letter == 0xf8ff || /*LV_SYMBOL_DUMMY*/ - letter == 0x200c) { /*ZERO WIDTH NON-JOINER*/ - dsc_out->box_w = 0; - dsc_out->adv_w = 0; - } - else { #if LV_USE_FONT_PLACEHOLDER - dsc_out->box_w = font_p->line_height / 2; - dsc_out->adv_w = dsc_out->box_w + 2; + dsc_out->box_w = font_p->line_height / 2; + dsc_out->adv_w = dsc_out->box_w + 2; #else - dsc_out->box_w = 0; - dsc_out->adv_w = 0; + dsc_out->box_w = 0; + dsc_out->adv_w = 0; #endif - } dsc_out->resolved_font = NULL; dsc_out->box_h = font_p->line_height; @@ -126,21 +108,24 @@ bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_o return false; } -/** - * Get the width of a glyph with kerning - * @param font pointer to a font - * @param letter a UNICODE letter - * @param letter_next the next letter after `letter`. Used for kerning - * @return the width of the glyph - */ uint16_t lv_font_get_glyph_width(const lv_font_t * font, uint32_t letter, uint32_t letter_next) { LV_ASSERT_NULL(font); lv_font_glyph_dsc_t g; + + /*Return zero if letter is marker*/ + if(_lv_text_is_marker(letter)) return 0; + lv_font_get_glyph_dsc(font, &g, letter, letter_next); return g.adv_w; } +void lv_font_set_kerning(lv_font_t * font, lv_font_kerning_t kerning) +{ + LV_ASSERT_NULL(font); + font->kerning = kerning; +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font.h b/lib/libesp32_lvgl/lvgl/src/font/lv_font.h index e3b670c87..77feee414 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font.h +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font.h @@ -19,7 +19,10 @@ extern "C" { #include #include "lv_symbol_def.h" +#include "../draw/lv_draw_buf.h" #include "../misc/lv_area.h" +#include "../misc/lv_types.h" +#include "../misc/cache/lv_cache.h" /********************* * DEFINES @@ -27,6 +30,7 @@ extern "C" { /* imgfont identifier */ #define LV_IMGFONT_BPP 9 +#define LV_VECFONT_BPP 10 /********************** * TYPEDEFS @@ -36,11 +40,10 @@ extern "C" { * General types *-----------------*/ -struct _lv_font_t; /** Describes the properties of a glyph.*/ typedef struct { - const struct _lv_font_t * - resolved_font; /**< Pointer to a font where the glyph was actually found after handling fallbacks*/ + const lv_font_t * + resolved_font; /**< Pointer to a font where the glyph was actually found after handling fallbacks*/ uint16_t adv_w; /**< The glyph needs this space. Draw the next glyph after this width.*/ uint16_t box_w; /**< Width of the glyph's bounding box*/ uint16_t box_h; /**< Height of the glyph's bounding box*/ @@ -48,40 +51,61 @@ typedef struct { int16_t ofs_y; /**< y offset of the bounding box*/ uint8_t bpp: 4; /**< Bit-per-pixel: 1, 2, 4, 8*/ uint8_t is_placeholder: 1; /** Glyph is missing. But placeholder will still be displayed */ + + uint32_t glyph_index; /**< The index of the glyph in the font file. Used by the font cache*/ + lv_cache_entry_t * entry; /**< The cache entry of the glyph draw data. Used by the font cache*/ } lv_font_glyph_dsc_t; /** The bitmaps might be upscaled by 3 to achieve subpixel rendering.*/ -enum { +enum _lv_font_subpx_t { LV_FONT_SUBPX_NONE, LV_FONT_SUBPX_HOR, LV_FONT_SUBPX_VER, LV_FONT_SUBPX_BOTH, }; +#ifdef DOXYGEN +typedef _lv_font_subpx_t lv_font_subpx_t; +#else typedef uint8_t lv_font_subpx_t; +#endif /*DOXYGEN*/ + +/** Adjust letter spacing for specific character pairs.*/ +enum _lv_font_kerning_t { + LV_FONT_KERNING_NORMAL, + LV_FONT_KERNING_NONE, +}; + +#ifdef DOXYGEN +typedef _lv_font_kerning_t lv_font_kerning_t; +#else +typedef uint8_t lv_font_kerning_t; +#endif /*DOXYGEN*/ /** Describe the properties of a font*/ -typedef struct _lv_font_t { +struct _lv_font_t { /** Get a glyph's descriptor from a font*/ - bool (*get_glyph_dsc)(const struct _lv_font_t *, lv_font_glyph_dsc_t *, uint32_t letter, uint32_t letter_next); + bool (*get_glyph_dsc)(const lv_font_t *, lv_font_glyph_dsc_t *, uint32_t letter, uint32_t letter_next); /** Get a glyph's bitmap from a font*/ - const uint8_t * (*get_glyph_bitmap)(const struct _lv_font_t *, uint32_t); + const void * (*get_glyph_bitmap)(lv_font_glyph_dsc_t *, uint32_t, lv_draw_buf_t *); + + /** Release a glyph*/ + void (*release_glyph)(const lv_font_t *, lv_font_glyph_dsc_t *); /*Pointer to the font in a font pack (must have the same line height)*/ - lv_coord_t line_height; /**< The real line height where any text fits*/ - lv_coord_t base_line; /**< Base line measured from the top of the line_height*/ - uint8_t subpx : 2; /**< An element of `lv_font_subpx_t`*/ + int32_t line_height; /**< The real line height where any text fits*/ + int32_t base_line; /**< Base line measured from the top of the line_height*/ + uint8_t subpx : 2; /**< An element of `lv_font_subpx_t`*/ + uint8_t kerning : 1; /**< An element of `lv_font_kerning_t`*/ int8_t underline_position; /**< Distance between the top of the underline and base line (< 0 means below the base line)*/ int8_t underline_thickness; /**< Thickness of the underline*/ const void * dsc; /**< Store implementation specific or run_time data or caching here*/ - const struct _lv_font_t * fallback; /**< Fallback font for missing glyph. Resolved recursively */ -#if LV_USE_USER_DATA + const lv_font_t * fallback; /**< Fallback font for missing glyph. Resolved recursively */ void * user_data; /**< Custom user data for font.*/ -#endif -} lv_font_t; +}; /********************** * GLOBAL PROTOTYPES @@ -89,48 +113,57 @@ typedef struct _lv_font_t { /** * Return with the bitmap of a font. - * @param font_p pointer to a font - * @param letter a UNICODE character code - * @return pointer to the bitmap of the letter + * @param g_dsc the glyph descriptor including which font to use etc. + * @param letter a UNICODE character code + * @param draw_buf a draw buffer that can be used to store the bitmap of the glyph, it's OK not to use it. + * @return pointer to the glyph's data. It can be a draw buffer for bitmap fonts or an image source for imgfonts. */ -const uint8_t * lv_font_get_glyph_bitmap(const lv_font_t * font_p, uint32_t letter); +const void * lv_font_get_glyph_bitmap(lv_font_glyph_dsc_t * g_dsc, uint32_t letter, + lv_draw_buf_t * draw_buf); /** * Get the descriptor of a glyph - * @param font_p pointer to font - * @param dsc_out store the result descriptor here - * @param letter a UNICODE letter code - * @param letter_next the next letter after `letter`. Used for kerning + * @param font pointer to font + * @param dsc_out store the result descriptor here + * @param letter a UNICODE letter code + * @param letter_next the next letter after `letter`. Used for kerning * @return true: descriptor is successfully loaded into `dsc_out`. * false: the letter was not found, no data is loaded to `dsc_out` */ -bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_out, uint32_t letter, +bool lv_font_get_glyph_dsc(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t letter, uint32_t letter_next); /** * Get the width of a glyph with kerning - * @param font pointer to a font - * @param letter a UNICODE letter - * @param letter_next the next letter after `letter`. Used for kerning + * @param font pointer to a font + * @param letter a UNICODE letter + * @param letter_next the next letter after `letter`. Used for kerning * @return the width of the glyph */ uint16_t lv_font_get_glyph_width(const lv_font_t * font, uint32_t letter, uint32_t letter_next); /** * Get the line height of a font. All characters fit into this height - * @param font_p pointer to a font + * @param font pointer to a font * @return the height of a font */ -static inline lv_coord_t lv_font_get_line_height(const lv_font_t * font_p) +static inline int32_t lv_font_get_line_height(const lv_font_t * font) { - return font_p->line_height; + return font->line_height; } +/** + * Configure the use of kerning information stored in a font + * @param font pointer to a font + * @param kerning `LV_FONT_KERNING_NORMAL` (default) or `LV_FONT_KERNING_NONE` + */ +void lv_font_set_kerning(lv_font_t * font, lv_font_kerning_t kerning); + /********************** * MACROS **********************/ -#define LV_FONT_DECLARE(font_name) extern const lv_font_t font_name; +#define LV_FONT_DECLARE(font_name) LV_ATTRIBUTE_EXTERN_DATA extern const lv_font_t font_name; #if LV_FONT_MONTSERRAT_8 LV_FONT_DECLARE(lv_font_montserrat_8) @@ -216,10 +249,6 @@ LV_FONT_DECLARE(lv_font_montserrat_46) LV_FONT_DECLARE(lv_font_montserrat_48) #endif -#if LV_FONT_MONTSERRAT_12_SUBPX -LV_FONT_DECLARE(lv_font_montserrat_12_subpx) -#endif - #if LV_FONT_MONTSERRAT_28_COMPRESSED LV_FONT_DECLARE(lv_font_montserrat_28_compressed) #endif diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font.mk b/lib/libesp32_lvgl/lvgl/src/font/lv_font.mk deleted file mode 100644 index 2201b73f2..000000000 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font.mk +++ /dev/null @@ -1,36 +0,0 @@ -CSRCS += lv_font.c -CSRCS += lv_font_fmt_txt.c -CSRCS += lv_font_loader.c - -CSRCS += lv_font_dejavu_16_persian_hebrew.c -CSRCS += lv_font_montserrat_8.c -CSRCS += lv_font_montserrat_10.c -CSRCS += lv_font_montserrat_12.c -CSRCS += lv_font_montserrat_12_subpx.c -CSRCS += lv_font_montserrat_14.c -CSRCS += lv_font_montserrat_16.c -CSRCS += lv_font_montserrat_18.c -CSRCS += lv_font_montserrat_20.c -CSRCS += lv_font_montserrat_22.c -CSRCS += lv_font_montserrat_24.c -CSRCS += lv_font_montserrat_26.c -CSRCS += lv_font_montserrat_28.c -CSRCS += lv_font_montserrat_28_compressed.c -CSRCS += lv_font_montserrat_30.c -CSRCS += lv_font_montserrat_32.c -CSRCS += lv_font_montserrat_34.c -CSRCS += lv_font_montserrat_36.c -CSRCS += lv_font_montserrat_38.c -CSRCS += lv_font_montserrat_40.c -CSRCS += lv_font_montserrat_42.c -CSRCS += lv_font_montserrat_44.c -CSRCS += lv_font_montserrat_46.c -CSRCS += lv_font_montserrat_48.c -CSRCS += lv_font_simsun_16_cjk.c -CSRCS += lv_font_unscii_8.c -CSRCS += lv_font_unscii_16.c - -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/font -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/font - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/font" diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_dejavu_16_persian_hebrew.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_dejavu_16_persian_hebrew.c index fce6b0ccf..02a95735e 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_dejavu_16_persian_hebrew.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_dejavu_16_persian_hebrew.c @@ -5864,7 +5864,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -6556,15 +6555,13 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { } }; - - /*-------------------- * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -6578,18 +6575,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 0, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_dejavu_16_persian_hebrew = { #else lv_font_t lv_font_dejavu_16_persian_hebrew = { @@ -6608,7 +6602,4 @@ lv_font_t lv_font_dejavu_16_persian_hebrew = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_DEJAVU_16_PERSIAN_HEBREW*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.c index 78beafff5..fa5595f8d 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.c @@ -8,25 +8,23 @@ *********************/ #include "lv_font.h" #include "lv_font_fmt_txt.h" +#include "../core/lv_global.h" #include "../misc/lv_assert.h" #include "../misc/lv_types.h" -#include "../misc/lv_gc.h" #include "../misc/lv_log.h" #include "../misc/lv_utils.h" -#include "../misc/lv_mem.h" +#include "../stdlib/lv_mem.h" /********************* * DEFINES *********************/ +#if LV_USE_FONT_COMPRESSED + #define font_rle LV_GLOBAL_DEFAULT()->font_fmt_rle +#endif /*LV_USE_FONT_COMPRESSED*/ /********************** * TYPEDEFS **********************/ -typedef enum { - RLE_STATE_SINGLE = 0, - RLE_STATE_REPEATE, - RLE_STATE_COUNTER, -} rle_state_t; /********************** * STATIC PROTOTYPES @@ -38,10 +36,9 @@ static int32_t kern_pair_8_compare(const void * ref, const void * element); static int32_t kern_pair_16_compare(const void * ref, const void * element); #if LV_USE_FONT_COMPRESSED - static void decompress(const uint8_t * in, uint8_t * out, lv_coord_t w, lv_coord_t h, uint8_t bpp, bool prefilter); - static inline void decompress_line(uint8_t * out, lv_coord_t w); + static void decompress(const uint8_t * in, uint8_t * out, int32_t w, int32_t h, uint8_t bpp, bool prefilter); + static inline void decompress_line(uint8_t * out, int32_t w); static inline uint8_t get_bits(const uint8_t * in, uint32_t bit_pos, uint8_t len); - static inline void bits_write(uint8_t * out, uint32_t bit_pos, uint8_t val, uint8_t len); static inline void rle_init(const uint8_t * in, uint8_t bpp); static inline uint8_t rle_next(void); #endif /*LV_USE_FONT_COMPRESSED*/ @@ -49,14 +46,18 @@ static int32_t kern_pair_16_compare(const void * ref, const void * element); /********************** * STATIC VARIABLES **********************/ + +static const uint8_t opa4_table[16] = {0, 17, 34, 51, + 68, 85, 102, 119, + 136, 153, 170, 187, + 204, 221, 238, 255 + }; + #if LV_USE_FONT_COMPRESSED - static uint32_t rle_rdp; - static const uint8_t * rle_in; - static uint8_t rle_bpp; - static uint8_t rle_prev_v; - static uint8_t rle_cnt; - static rle_state_t rle_state; -#endif /*LV_USE_FONT_COMPRESSED*/ +static const uint8_t opa3_table[8] = {0, 36, 73, 109, 146, 182, 218, 255}; +#endif + +static const uint8_t opa2_table[4] = {0, 85, 170, 255}; /********************** * GLOBAL PROTOTYPES @@ -70,14 +71,12 @@ static int32_t kern_pair_16_compare(const void * ref, const void * element); * GLOBAL FUNCTIONS **********************/ -/** - * Used as `get_glyph_bitmap` callback in LittelvGL's native font format if the font is uncompressed. - * @param font pointer to font - * @param unicode_letter a unicode letter which bitmap should be get - * @return pointer to the bitmap or NULL if not found - */ -const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t unicode_letter) +const void * lv_font_get_bitmap_fmt_txt(lv_font_glyph_dsc_t * g_dsc, uint32_t unicode_letter, + lv_draw_buf_t * draw_buf) { + const lv_font_t * font = g_dsc->resolved_font; + uint8_t * bitmap_out = draw_buf->data; + if(unicode_letter == '\t') unicode_letter = ' '; lv_font_fmt_txt_dsc_t * fdsc = (lv_font_fmt_txt_dsc_t *)font->dsc; @@ -86,47 +85,75 @@ const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t unic const lv_font_fmt_txt_glyph_dsc_t * gdsc = &fdsc->glyph_dsc[gid]; + int32_t gsize = (int32_t) gdsc->box_w * gdsc->box_h; + if(gsize == 0) return NULL; + if(fdsc->bitmap_format == LV_FONT_FMT_TXT_PLAIN) { - return &fdsc->glyph_bitmap[gdsc->bitmap_index]; + const uint8_t * bitmap_in = &fdsc->glyph_bitmap[gdsc->bitmap_index]; + uint8_t * bitmap_out_tmp = bitmap_out; + int32_t i = 0; + int32_t x, y; + uint32_t stride = lv_draw_buf_width_to_stride(gdsc->box_w, LV_COLOR_FORMAT_A8); + + if(fdsc->bpp == 1) { + for(y = 0; y < gdsc->box_h; y ++) { + for(x = 0; x < gdsc->box_w; x++, i++) { + i = i & 0x7; + if(i == 0) bitmap_out_tmp[x] = (*bitmap_in) & 0x80 ? 0xff : 0x00; + else if(i == 1) bitmap_out_tmp[x] = (*bitmap_in) & 0x40 ? 0xff : 0x00; + else if(i == 2) bitmap_out_tmp[x] = (*bitmap_in) & 0x20 ? 0xff : 0x00; + else if(i == 3) bitmap_out_tmp[x] = (*bitmap_in) & 0x10 ? 0xff : 0x00; + else if(i == 4) bitmap_out_tmp[x] = (*bitmap_in) & 0x08 ? 0xff : 0x00; + else if(i == 5) bitmap_out_tmp[x] = (*bitmap_in) & 0x04 ? 0xff : 0x00; + else if(i == 6) bitmap_out_tmp[x] = (*bitmap_in) & 0x02 ? 0xff : 0x00; + else if(i == 7) { + bitmap_out_tmp[x] = (*bitmap_in) & 0x01 ? 0xff : 0x00; + bitmap_in++; + } + } + bitmap_out_tmp += stride; + } + } + else if(fdsc->bpp == 2) { + for(y = 0; y < gdsc->box_h; y ++) { + for(x = 0; x < gdsc->box_w; x++, i++) { + i = i & 0x3; + if(i == 0) bitmap_out_tmp[x] = opa2_table[(*bitmap_in) >> 6]; + else if(i == 1) bitmap_out_tmp[x] = opa2_table[((*bitmap_in) >> 4) & 0x3]; + else if(i == 2) bitmap_out_tmp[x] = opa2_table[((*bitmap_in) >> 2) & 0x3]; + else if(i == 3) { + bitmap_out_tmp[x] = opa2_table[((*bitmap_in) >> 0) & 0x3]; + bitmap_in++; + } + } + bitmap_out_tmp += stride; + } + + } + else if(fdsc->bpp == 4) { + for(y = 0; y < gdsc->box_h; y ++) { + for(x = 0; x < gdsc->box_w; x++, i++) { + i = i & 0x1; + if(i == 0) { + bitmap_out_tmp[x] = opa4_table[(*bitmap_in) >> 4]; + } + else if(i == 1) { + bitmap_out_tmp[x] = opa4_table[(*bitmap_in) & 0xF]; + bitmap_in++; + } + } + bitmap_out_tmp += stride; + } + } + return draw_buf; } /*Handle compressed bitmap*/ else { #if LV_USE_FONT_COMPRESSED - static size_t last_buf_size = 0; - if(LV_GC_ROOT(_lv_font_decompr_buf) == NULL) last_buf_size = 0; - - uint32_t gsize = gdsc->box_w * gdsc->box_h; - if(gsize == 0) return NULL; - - uint32_t buf_size = gsize; - /*Compute memory size needed to hold decompressed glyph, rounding up*/ - switch(fdsc->bpp) { - case 1: - buf_size = (gsize + 7) >> 3; - break; - case 2: - buf_size = (gsize + 3) >> 2; - break; - case 3: - buf_size = (gsize + 1) >> 1; - break; - case 4: - buf_size = (gsize + 1) >> 1; - break; - } - - if(last_buf_size < buf_size) { - uint8_t * tmp = lv_mem_realloc(LV_GC_ROOT(_lv_font_decompr_buf), buf_size); - LV_ASSERT_MALLOC(tmp); - if(tmp == NULL) return NULL; - LV_GC_ROOT(_lv_font_decompr_buf) = tmp; - last_buf_size = buf_size; - } - - bool prefilter = fdsc->bitmap_format == LV_FONT_FMT_TXT_COMPRESSED ? true : false; - decompress(&fdsc->glyph_bitmap[gdsc->bitmap_index], LV_GC_ROOT(_lv_font_decompr_buf), gdsc->box_w, gdsc->box_h, + bool prefilter = fdsc->bitmap_format == LV_FONT_FMT_TXT_COMPRESSED; + decompress(&fdsc->glyph_bitmap[gdsc->bitmap_index], bitmap_out, gdsc->box_w, gdsc->box_h, (uint8_t)fdsc->bpp, prefilter); - return LV_GC_ROOT(_lv_font_decompr_buf); + return draw_buf; #else /*!LV_USE_FONT_COMPRESSED*/ LV_LOG_WARN("Compressed fonts is used but LV_USE_FONT_COMPRESSED is not enabled in lv_conf.h"); return NULL; @@ -137,14 +164,6 @@ const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t unic return NULL; } -/** - * Used as `get_glyph_dsc` callback in LittelvGL's native font format if the font is uncompressed. - * @param font_p pointer to font - * @param dsc_out store the result descriptor here - * @param letter a UNICODE letter code - * @return true: descriptor is successfully loaded into `dsc_out`. - * false: the letter was not found, no data is loaded to `dsc_out` - */ bool lv_font_get_glyph_dsc_fmt_txt(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) { @@ -189,19 +208,6 @@ bool lv_font_get_glyph_dsc_fmt_txt(const lv_font_t * font, lv_font_glyph_dsc_t * return true; } -/** - * Free the allocated memories. - */ -void _lv_font_clean_up_fmt_txt(void) -{ -#if LV_USE_FONT_COMPRESSED - if(LV_GC_ROOT(_lv_font_decompr_buf)) { - lv_mem_free(LV_GC_ROOT(_lv_font_decompr_buf)); - LV_GC_ROOT(_lv_font_decompr_buf) = NULL; - } -#endif -} - /********************** * STATIC FUNCTIONS **********************/ @@ -212,15 +218,12 @@ static uint32_t get_glyph_dsc_id(const lv_font_t * font, uint32_t letter) lv_font_fmt_txt_dsc_t * fdsc = (lv_font_fmt_txt_dsc_t *)font->dsc; - /*Check the cache first*/ - if(fdsc->cache && letter == fdsc->cache->last_letter) return fdsc->cache->last_glyph_id; - uint16_t i; for(i = 0; i < fdsc->cmap_num; i++) { /*Relative code point*/ uint32_t rcp = letter - fdsc->cmaps[i].range_start; - if(rcp > fdsc->cmaps[i].range_length) continue; + if(rcp >= fdsc->cmaps[i].range_length) continue; uint32_t glyph_id = 0; if(fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY) { glyph_id = fdsc->cmaps[i].glyph_id_start + rcp; @@ -251,18 +254,9 @@ static uint32_t get_glyph_dsc_id(const lv_font_t * font, uint32_t letter) } } - /*Update the cache*/ - if(fdsc->cache) { - fdsc->cache->last_letter = letter; - fdsc->cache->last_glyph_id = glyph_id; - } return glyph_id; } - if(fdsc->cache) { - fdsc->cache->last_letter = letter; - fdsc->cache->last_glyph_id = 0; - } return 0; } @@ -345,6 +339,7 @@ static int32_t kern_pair_16_compare(const void * ref, const void * element) } #if LV_USE_FONT_COMPRESSED + /** * The compress a glyph's bitmap * @param in the compressed bitmap @@ -353,31 +348,44 @@ static int32_t kern_pair_16_compare(const void * ref, const void * element) * @param bpp bit per pixel (bpp = 3 will be converted to bpp = 4) * @param prefilter true: the lines are XORed */ -static void decompress(const uint8_t * in, uint8_t * out, lv_coord_t w, lv_coord_t h, uint8_t bpp, bool prefilter) +static void decompress(const uint8_t * in, uint8_t * out, int32_t w, int32_t h, uint8_t bpp, bool prefilter) { - uint32_t wrp = 0; - uint8_t wr_size = bpp; - if(bpp == 3) wr_size = 4; + const lv_opa_t * opa_table; + switch(bpp) { + case 2: + opa_table = opa2_table; + break; + case 3: + opa_table = opa3_table; + break; + case 4: + opa_table = opa4_table; + break; + default: + LV_LOG_WARN("%d bpp is not handled", bpp); + return; + } rle_init(in, bpp); - uint8_t * line_buf1 = lv_mem_buf_get(w); + uint8_t * line_buf1 = lv_malloc(w); uint8_t * line_buf2 = NULL; if(prefilter) { - line_buf2 = lv_mem_buf_get(w); + line_buf2 = lv_malloc(w); } decompress_line(line_buf1, w); - lv_coord_t y; - lv_coord_t x; + int32_t y; + int32_t x; + uint32_t stride = lv_draw_buf_width_to_stride(w, LV_COLOR_FORMAT_A8); for(x = 0; x < w; x++) { - bits_write(out, wrp, line_buf1[x], bpp); - wrp += wr_size; + out[x] = opa_table[line_buf1[x]]; } + out += stride; for(y = 1; y < h; y++) { if(prefilter) { @@ -385,22 +393,21 @@ static void decompress(const uint8_t * in, uint8_t * out, lv_coord_t w, lv_coord for(x = 0; x < w; x++) { line_buf1[x] = line_buf2[x] ^ line_buf1[x]; - bits_write(out, wrp, line_buf1[x], bpp); - wrp += wr_size; + out[x] = opa_table[line_buf1[x]]; } } else { decompress_line(line_buf1, w); for(x = 0; x < w; x++) { - bits_write(out, wrp, line_buf1[x], bpp); - wrp += wr_size; + out[x] = opa_table[line_buf1[x]]; } } + out += stride; } - lv_mem_buf_release(line_buf1); - lv_mem_buf_release(line_buf2); + lv_free(line_buf1); + lv_free(line_buf2); } /** @@ -408,9 +415,9 @@ static void decompress(const uint8_t * in, uint8_t * out, lv_coord_t w, lv_coord * @param out output buffer * @param w width of the line in pixel count */ -static inline void decompress_line(uint8_t * out, lv_coord_t w) +static inline void decompress_line(uint8_t * out, int32_t w) { - lv_coord_t i; + int32_t i; for(i = 0; i < w; i++) { out[i] = rle_next(); } @@ -458,116 +465,69 @@ static inline uint8_t get_bits(const uint8_t * in, uint32_t bit_pos, uint8_t len } } -/** - * Write `val` data to `bit_pos` position of `out`. The write can NOT cross byte boundary. - * @param out buffer where to write - * @param bit_pos bit index to write - * @param val value to write - * @param len length of bits to write from `val`. (Counted from the LSB). - * @note `len == 3` will be converted to `len = 4` and `val` will be upscaled too - */ -static inline void bits_write(uint8_t * out, uint32_t bit_pos, uint8_t val, uint8_t len) -{ - if(len == 3) { - len = 4; - switch(val) { - case 0: - val = 0; - break; - case 1: - val = 2; - break; - case 2: - val = 4; - break; - case 3: - val = 6; - break; - case 4: - val = 9; - break; - case 5: - val = 11; - break; - case 6: - val = 13; - break; - case 7: - val = 15; - break; - } - } - - uint16_t byte_pos = bit_pos >> 3; - bit_pos = bit_pos & 0x7; - bit_pos = 8 - bit_pos - len; - - uint8_t bit_mask = (uint16_t)((uint16_t) 1 << len) - 1; - out[byte_pos] &= ((~bit_mask) << bit_pos); - out[byte_pos] |= (val << bit_pos); -} - static inline void rle_init(const uint8_t * in, uint8_t bpp) { - rle_in = in; - rle_bpp = bpp; - rle_state = RLE_STATE_SINGLE; - rle_rdp = 0; - rle_prev_v = 0; - rle_cnt = 0; + lv_font_fmt_rle_t * rle = &font_rle; + rle->in = in; + rle->bpp = bpp; + rle->state = RLE_STATE_SINGLE; + rle->rdp = 0; + rle->prev_v = 0; + rle->count = 0; } static inline uint8_t rle_next(void) { uint8_t v = 0; uint8_t ret = 0; + lv_font_fmt_rle_t * rle = &font_rle; - if(rle_state == RLE_STATE_SINGLE) { - ret = get_bits(rle_in, rle_rdp, rle_bpp); - if(rle_rdp != 0 && rle_prev_v == ret) { - rle_cnt = 0; - rle_state = RLE_STATE_REPEATE; + if(rle->state == RLE_STATE_SINGLE) { + ret = get_bits(rle->in, rle->rdp, rle->bpp); + if(rle->rdp != 0 && rle->prev_v == ret) { + rle->count = 0; + rle->state = RLE_STATE_REPEATE; } - rle_prev_v = ret; - rle_rdp += rle_bpp; + rle->prev_v = ret; + rle->rdp += rle->bpp; } - else if(rle_state == RLE_STATE_REPEATE) { - v = get_bits(rle_in, rle_rdp, 1); - rle_cnt++; - rle_rdp += 1; + else if(rle->state == RLE_STATE_REPEATE) { + v = get_bits(rle->in, rle->rdp, 1); + rle->count++; + rle->rdp += 1; if(v == 1) { - ret = rle_prev_v; - if(rle_cnt == 11) { - rle_cnt = get_bits(rle_in, rle_rdp, 6); - rle_rdp += 6; - if(rle_cnt != 0) { - rle_state = RLE_STATE_COUNTER; + ret = rle->prev_v; + if(rle->count == 11) { + rle->count = get_bits(rle->in, rle->rdp, 6); + rle->rdp += 6; + if(rle->count != 0) { + rle->state = RLE_STATE_COUNTER; } else { - ret = get_bits(rle_in, rle_rdp, rle_bpp); - rle_prev_v = ret; - rle_rdp += rle_bpp; - rle_state = RLE_STATE_SINGLE; + ret = get_bits(rle->in, rle->rdp, rle->bpp); + rle->prev_v = ret; + rle->rdp += rle->bpp; + rle->state = RLE_STATE_SINGLE; } } } else { - ret = get_bits(rle_in, rle_rdp, rle_bpp); - rle_prev_v = ret; - rle_rdp += rle_bpp; - rle_state = RLE_STATE_SINGLE; + ret = get_bits(rle->in, rle->rdp, rle->bpp); + rle->prev_v = ret; + rle->rdp += rle->bpp; + rle->state = RLE_STATE_SINGLE; } } - else if(rle_state == RLE_STATE_COUNTER) { - ret = rle_prev_v; - rle_cnt--; - if(rle_cnt == 0) { - ret = get_bits(rle_in, rle_rdp, rle_bpp); - rle_prev_v = ret; - rle_rdp += rle_bpp; - rle_state = RLE_STATE_SINGLE; + else if(rle->state == RLE_STATE_COUNTER) { + ret = rle->prev_v; + rle->count--; + if(rle->count == 0) { + ret = get_bits(rle->in, rle->rdp, rle->bpp); + rle->prev_v = ret; + rle->rdp += rle->bpp; + rle->state = RLE_STATE_SINGLE; } } diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.h b/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.h index 86546a35f..76bade065 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.h +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_fmt_txt.h @@ -46,14 +46,18 @@ typedef struct { } lv_font_fmt_txt_glyph_dsc_t; /** Format of font character map.*/ -enum { +enum _lv_font_fmt_txt_cmap_type_t { LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL, LV_FONT_FMT_TXT_CMAP_SPARSE_FULL, LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY, LV_FONT_FMT_TXT_CMAP_SPARSE_TINY, }; +#ifdef DOXYGEN +typedef _lv_font_fmt_txt_cmap_type_t lv_font_fmt_txt_cmap_type_t; +#else typedef uint8_t lv_font_fmt_txt_cmap_type_t; +#endif /*DOXYGEN*/ /** * Map codepoints to a `glyph_dsc`s @@ -117,8 +121,8 @@ typedef struct { /*To get a kern value of two code points: 1. Get the `glyph_id_left` and `glyph_id_right` from `lv_font_fmt_txt_cmap_t 2. for(i = 0; i < pair_cnt * 2; i += 2) - if(gylph_ids[i] == glyph_id_left && - gylph_ids[i+1] == glyph_id_right) + if(glyph_ids[i] == glyph_id_left && + glyph_ids[i+1] == glyph_id_right) return values[i / 2]; */ const void * glyph_ids; @@ -151,11 +155,6 @@ typedef enum { LV_FONT_FMT_TXT_COMPRESSED_NO_PREFILTER = 1, } lv_font_fmt_txt_bitmap_format_t; -typedef struct { - uint32_t last_letter; - uint32_t last_glyph_id; -} lv_font_fmt_txt_glyph_cache_t; - /*Describe store additional data for fonts*/ typedef struct { /*The bitmaps of all glyphs*/ @@ -192,39 +191,51 @@ typedef struct { * from `lv_font_fmt_txt_bitmap_format_t` */ uint16_t bitmap_format : 2; - - /*Cache the last letter and is glyph id*/ - lv_font_fmt_txt_glyph_cache_t * cache; } lv_font_fmt_txt_dsc_t; +#if LV_USE_FONT_COMPRESSED +typedef enum { + RLE_STATE_SINGLE = 0, + RLE_STATE_REPEATE, + RLE_STATE_COUNTER, +} lv_font_fmt_rle_state_t; + +typedef struct { + uint32_t rdp; + const uint8_t * in; + uint8_t bpp; + uint8_t prev_v; + uint8_t count; + lv_font_fmt_rle_state_t state; +} lv_font_fmt_rle_t; +#endif + /********************** * GLOBAL PROTOTYPES **********************/ /** - * Used as `get_glyph_bitmap` callback in LittelvGL's native font format if the font is uncompressed. - * @param font pointer to font - * @param unicode_letter a unicode letter which bitmap should be get - * @return pointer to the bitmap or NULL if not found + * Used as `get_glyph_bitmap` callback in lvgl's native font format if the font is uncompressed. + * @param g_dsc the glyph descriptor including which font to use etc. + * @param letter a UNICODE character code + * @param draw_buf a draw buffer that can be used to store the bitmap of the glyph, it's OK not to use it. + * @return pointer to an A8 bitmap (not necessarily bitmap_out) or NULL if `unicode_letter` not found */ -const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t letter); +const void * lv_font_get_bitmap_fmt_txt(lv_font_glyph_dsc_t * g_dsc, uint32_t unicode_letter, + lv_draw_buf_t * draw_buf); /** - * Used as `get_glyph_dsc` callback in LittelvGL's native font format if the font is uncompressed. - * @param font_p pointer to font + * Used as `get_glyph_dsc` callback in lvgl's native font format if the font is uncompressed. + * @param font pointer to font * @param dsc_out store the result descriptor here - * @param letter a UNICODE letter code + * @param unicode_letter a UNICODE letter code + * @param unicode_letter_next the unicode letter succeeding the letter under test * @return true: descriptor is successfully loaded into `dsc_out`. * false: the letter was not found, no data is loaded to `dsc_out` */ bool lv_font_get_glyph_dsc_fmt_txt(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next); -/** - * Free the allocated memories. - */ -void _lv_font_clean_up_fmt_txt(void); - /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_10.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_10.c index 485d9f6f3..80fe261a1 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_10.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_10.c @@ -973,7 +973,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -1170,7 +1169,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -1597,7 +1595,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -1611,9 +1608,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -1627,18 +1624,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_10 = { #else lv_font_t lv_font_montserrat_10 = { @@ -1657,7 +1651,4 @@ lv_font_t lv_font_montserrat_10 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_10*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_12.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_12.c index e84d00c3e..6e5c1ea41 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_12.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_12.c @@ -1234,7 +1234,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -1431,7 +1430,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -1858,7 +1856,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -1872,9 +1869,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -1888,18 +1885,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_12 = { #else lv_font_t lv_font_montserrat_12 = { @@ -1918,7 +1912,4 @@ lv_font_t lv_font_montserrat_12 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_12*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_12_subpx.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_12_subpx.c deleted file mode 100644 index 1ffd7ed9e..000000000 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_12_subpx.c +++ /dev/null @@ -1,3865 +0,0 @@ -/******************************************************************************* - * Size: 12 px - * Bpp: 4 - * Opts: --lcd --no-compress --no-prefilter --bpp 4 --size 12 --font Montserrat-Medium.ttf -r 0x20-0x7F,0xB0,0x2022 --font FontAwesome5-Solid+Brands+Regular.woff -r 61441,61448,61451,61452,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61507,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61641,61664,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650 --format lvgl -o lv_font_montserrat_12_subpx.c --force-fast-kern-format - ******************************************************************************/ - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE - #include "lvgl.h" -#else - #include "../../lvgl.h" -#endif - -#ifndef LV_FONT_MONTSERRAT_12_SUBPX - #define LV_FONT_MONTSERRAT_12_SUBPX 1 -#endif - -#if LV_FONT_MONTSERRAT_12_SUBPX - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+0020 " " */ - - /* U+0021 "!" */ - 0x0, 0x6b, 0xff, 0x94, 0x0, 0x5, 0xaf, 0xe9, - 0x30, 0x0, 0x4a, 0xfd, 0x83, 0x0, 0x4, 0x9f, - 0xd7, 0x20, 0x0, 0x39, 0xec, 0x72, 0x0, 0x3, - 0x8d, 0xc6, 0x10, 0x0, 0x2, 0x33, 0x10, 0x0, - 0x2, 0x68, 0x84, 0x10, 0x1, 0x5a, 0xed, 0x83, - 0x0, - - /* U+0022 "\"" */ - 0x3, 0x9e, 0xc6, 0x11, 0x6b, 0xe9, 0x40, 0x0, - 0x38, 0xeb, 0x60, 0x6, 0xbe, 0x93, 0x0, 0x3, - 0x8d, 0xb6, 0x0, 0x5b, 0xe8, 0x30, 0x0, 0x14, - 0x75, 0x30, 0x2, 0x57, 0x41, 0x0, - - /* U+0023 "#" */ - 0x0, 0x0, 0x0, 0x4, 0xad, 0x83, 0x0, 0x0, - 0x38, 0xda, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x6c, 0xb6, 0x10, 0x0, 0x5, 0xad, 0x83, - 0x0, 0x0, 0x0, 0x4, 0x9e, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x61, - 0x0, 0x0, 0x0, 0x5, 0xad, 0x82, 0x0, 0x0, - 0x38, 0xd9, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x6c, 0xc6, 0x10, 0x0, 0x5, 0xad, 0x83, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0xda, - 0x50, 0x0, 0x1, 0x6b, 0xc7, 0x10, 0x0, 0x0, - 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xb6, 0x0, 0x0, 0x0, - 0x1, 0x6c, 0xc6, 0x10, 0x0, 0x4, 0xad, 0x83, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xda, - 0x40, 0x0, 0x1, 0x6c, 0xc6, 0x10, 0x0, 0x0, - 0x0, 0x0, - - /* U+0024 "$" */ - 0x0, 0x0, 0x0, 0x0, 0x4, 0x9c, 0x82, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x4, 0x9c, 0x82, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0x37, 0xac, 0xde, 0xff, 0xff, 0xed, - 0xb9, 0x63, 0x10, 0x0, 0x1, 0x5b, 0xfe, 0xb7, - 0x46, 0xac, 0x95, 0x35, 0x79, 0x74, 0x0, 0x0, - 0x4, 0x9e, 0xe9, 0x40, 0x4, 0x9c, 0x82, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x5b, 0xfe, 0xc9, - 0x67, 0xbc, 0x82, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x26, 0x9b, 0xde, 0xff, 0xfe, 0xca, - 0x85, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x4, 0x9c, 0xa7, 0x7a, 0xdf, 0xea, 0x51, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x4, 0x9c, 0x82, 0x0, - 0x49, 0xfe, 0x93, 0x0, 0x5, 0xad, 0xb8, 0x54, - 0x25, 0xac, 0x95, 0x47, 0xbe, 0xfa, 0x51, 0x0, - 0x0, 0x26, 0x8b, 0xce, 0xff, 0xff, 0xff, 0xec, - 0xa7, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x4, 0x9c, 0x82, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0x46, 0x41, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+0025 "%" */ - 0x0, 0x26, 0xac, 0xcc, 0xcb, 0x84, 0x10, 0x0, - 0x0, 0x0, 0x38, 0xcb, 0x61, 0x0, 0x0, 0x16, - 0xbb, 0x61, 0x0, 0x4, 0xac, 0x82, 0x0, 0x0, - 0x27, 0xcb, 0x62, 0x0, 0x0, 0x0, 0x38, 0xc9, - 0x30, 0x0, 0x1, 0x7c, 0xa4, 0x0, 0x27, 0xcc, - 0x72, 0x0, 0x0, 0x0, 0x0, 0x5, 0xac, 0x72, - 0x0, 0x15, 0xab, 0x72, 0x26, 0xbc, 0x72, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x25, 0x9b, 0xcc, - 0xba, 0x63, 0x26, 0xbc, 0x83, 0x25, 0x9b, 0xcc, - 0xb9, 0x62, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x15, 0xbc, 0x83, 0x15, 0xbc, 0x72, 0x0, 0x16, - 0xbb, 0x72, 0x0, 0x0, 0x0, 0x0, 0x15, 0xac, - 0x94, 0x0, 0x38, 0xc9, 0x30, 0x0, 0x2, 0x7c, - 0xa4, 0x0, 0x0, 0x0, 0x14, 0xac, 0x94, 0x0, - 0x0, 0x16, 0xbb, 0x61, 0x0, 0x4, 0x9c, 0x72, - 0x0, 0x0, 0x4, 0x9c, 0xa4, 0x10, 0x0, 0x0, - 0x0, 0x37, 0xab, 0xba, 0xbb, 0x84, 0x10, - - /* U+0026 "&" */ - 0x0, 0x0, 0x2, 0x59, 0xce, 0xee, 0xed, 0xc9, - 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, - 0xaf, 0xc8, 0x20, 0x0, 0x38, 0xdd, 0x82, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x4a, 0xfc, 0x72, - 0x0, 0x15, 0xae, 0xc6, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x37, 0xce, 0xdb, 0xcd, 0xda, - 0x62, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x37, 0xbd, 0xdd, 0xef, 0xc8, 0x30, 0x0, 0x1, - 0x12, 0x0, 0x0, 0x0, 0x16, 0xce, 0xc7, 0x30, - 0x1, 0x5a, 0xde, 0xb7, 0x23, 0x8d, 0xd8, 0x30, - 0x0, 0x16, 0xbf, 0xb6, 0x0, 0x0, 0x0, 0x1, - 0x5a, 0xde, 0xff, 0xd7, 0x20, 0x0, 0x0, 0x49, - 0xef, 0xc8, 0x42, 0x11, 0x12, 0x36, 0x9c, 0xef, - 0xfe, 0xb6, 0x20, 0x0, 0x0, 0x3, 0x69, 0xcd, - 0xef, 0xff, 0xed, 0xc9, 0x63, 0x12, 0x6b, 0xb7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+0027 "'" */ - 0x3, 0x9e, 0xc6, 0x10, 0x0, 0x38, 0xeb, 0x60, - 0x0, 0x3, 0x8d, 0xb6, 0x0, 0x0, 0x14, 0x75, - 0x30, 0x0, - - /* U+0028 "(" */ - 0x0, 0x0, 0x0, 0x5a, 0xec, 0x72, 0x0, 0x0, - 0x16, 0xbf, 0xb6, 0x10, 0x0, 0x0, 0x5b, 0xfc, - 0x61, 0x0, 0x0, 0x4, 0x9e, 0xd8, 0x30, 0x0, - 0x0, 0x16, 0xbf, 0xb6, 0x0, 0x0, 0x0, 0x27, - 0xcf, 0xa4, 0x0, 0x0, 0x0, 0x28, 0xdf, 0x94, - 0x0, 0x0, 0x0, 0x27, 0xcf, 0xa4, 0x0, 0x0, - 0x0, 0x16, 0xbf, 0xb6, 0x0, 0x0, 0x0, 0x4, - 0x9e, 0xd8, 0x30, 0x0, 0x0, 0x0, 0x5a, 0xfb, - 0x61, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xb5, 0x10, - 0x0, 0x0, 0x0, 0x5a, 0xec, 0x72, - - /* U+0029 ")" */ - 0x16, 0xbe, 0xb5, 0x10, 0x0, 0x0, 0x0, 0x5a, - 0xfc, 0x72, 0x0, 0x0, 0x0, 0x6, 0xbf, 0xc6, - 0x10, 0x0, 0x0, 0x2, 0x7d, 0xfa, 0x40, 0x0, - 0x0, 0x0, 0x5a, 0xfc, 0x71, 0x0, 0x0, 0x0, - 0x49, 0xfd, 0x83, 0x0, 0x0, 0x0, 0x38, 0xee, - 0x93, 0x0, 0x0, 0x0, 0x49, 0xfd, 0x83, 0x0, - 0x0, 0x0, 0x5a, 0xfc, 0x71, 0x0, 0x0, 0x2, - 0x7d, 0xfa, 0x40, 0x0, 0x0, 0x6, 0xbf, 0xb6, - 0x10, 0x0, 0x0, 0x5a, 0xfc, 0x71, 0x0, 0x0, - 0x16, 0xbe, 0xb5, 0x10, 0x0, 0x0, - - /* U+002A "*" */ - 0x0, 0x0, 0x0, 0x0, 0x4a, 0xb6, 0x10, 0x0, - 0x0, 0x0, 0x3, 0x8c, 0xc9, 0x9c, 0xca, 0x9b, - 0xca, 0x51, 0x0, 0x0, 0x2, 0x6b, 0xef, 0xff, - 0xd8, 0x30, 0x0, 0x0, 0x3, 0x8b, 0xa7, 0x8b, - 0xc9, 0x79, 0xba, 0x51, 0x0, 0x0, 0x0, 0x0, - 0x38, 0xa6, 0x10, 0x0, 0x0, - - /* U+002B "+" */ - 0x0, 0x0, 0x0, 0x0, 0x37, 0xb7, 0x30, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0xbf, - 0xa5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x5b, 0xfa, 0x50, 0x0, 0x0, 0x0, 0x0, - 0x27, 0xce, 0xee, 0xef, 0xff, 0xff, 0xee, 0xee, - 0xc7, 0x20, 0x0, 0x1, 0x11, 0x11, 0x6b, 0xfb, - 0x61, 0x11, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x5, 0xbf, 0xa5, 0x0, 0x0, 0x0, 0x0, - - /* U+002C "," */ - 0x1, 0x48, 0x85, 0x20, 0x0, 0x4a, 0xff, 0xc6, - 0x10, 0x0, 0x5b, 0xd8, 0x20, 0x0, 0x39, 0xc8, - 0x30, 0x0, - - /* U+002D "-" */ - 0x4, 0x9f, 0xff, 0xff, 0xff, 0xd8, 0x30, 0x0, - 0x1, 0x22, 0x22, 0x22, 0x22, 0x10, 0x0, - - /* U+002E "." */ - 0x2, 0x6a, 0xa7, 0x30, 0x0, 0x49, 0xdd, 0x94, - 0x0, - - /* U+002F "/" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x13, 0x67, - 0x42, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5b, - 0xfa, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, - 0xaf, 0xb5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x5a, 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x5, 0xae, 0xb6, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x4a, 0xec, 0x61, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x4, 0x9e, 0xc6, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x49, 0xec, 0x71, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0x9e, 0xc7, 0x20, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x39, 0xed, 0x72, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0x8e, 0xd7, 0x20, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x38, 0xdd, 0x82, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0x8d, 0xd8, 0x30, - 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+0030 "0" */ - 0x0, 0x0, 0x2, 0x59, 0xbd, 0xef, 0xfe, 0xdb, - 0x95, 0x20, 0x0, 0x0, 0x0, 0x4, 0xae, 0xfd, - 0xa6, 0x43, 0x34, 0x6a, 0xdf, 0xea, 0x40, 0x0, - 0x1, 0x6c, 0xfd, 0x82, 0x0, 0x0, 0x0, 0x0, - 0x27, 0xdf, 0xc6, 0x10, 0x5, 0xaf, 0xe8, 0x30, - 0x0, 0x0, 0x0, 0x0, 0x3, 0x8d, 0xfa, 0x50, - 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x7c, 0xfb, 0x61, 0x5, 0xaf, 0xe8, 0x30, - 0x0, 0x0, 0x0, 0x0, 0x3, 0x8d, 0xfa, 0x50, - 0x1, 0x6c, 0xfd, 0x72, 0x0, 0x0, 0x0, 0x0, - 0x27, 0xdf, 0xc6, 0x10, 0x0, 0x4, 0xae, 0xfd, - 0xa6, 0x43, 0x34, 0x6a, 0xdf, 0xea, 0x40, 0x0, - 0x0, 0x0, 0x2, 0x59, 0xbd, 0xef, 0xfe, 0xdb, - 0x95, 0x20, 0x0, 0x0, - - /* U+0031 "1" */ - 0x0, 0x39, 0xef, 0xff, 0xff, 0xfd, 0x83, 0x0, - 0x0, 0x12, 0x22, 0x26, 0xbf, 0xd8, 0x30, 0x0, - 0x0, 0x0, 0x0, 0x5b, 0xfd, 0x83, 0x0, 0x0, - 0x0, 0x0, 0x5, 0xbf, 0xd8, 0x30, 0x0, 0x0, - 0x0, 0x0, 0x5b, 0xfd, 0x83, 0x0, 0x0, 0x0, - 0x0, 0x5, 0xbf, 0xd8, 0x30, 0x0, 0x0, 0x0, - 0x0, 0x5b, 0xfd, 0x83, 0x0, 0x0, 0x0, 0x0, - 0x5, 0xbf, 0xd8, 0x30, 0x0, 0x0, 0x0, 0x0, - 0x5b, 0xfd, 0x83, 0x0, - - /* U+0032 "2" */ - 0x0, 0x0, 0x13, 0x79, 0xbd, 0xef, 0xff, 0xed, - 0xc9, 0x62, 0x0, 0x0, 0x0, 0x3, 0x8d, 0xeb, - 0x85, 0x43, 0x33, 0x47, 0xad, 0xfe, 0x83, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x27, 0xcf, 0xc6, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x5a, 0xfe, 0x94, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x5a, - 0xee, 0xb5, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x15, 0xad, 0xec, 0x73, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x5a, 0xde, 0xc8, 0x30, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0xad, - 0xfd, 0xa6, 0x32, 0x22, 0x22, 0x22, 0x21, 0x10, - 0x0, 0x3, 0x8e, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x72, - - /* U+0033 "3" */ - 0x0, 0x3, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa4, 0x0, 0x0, 0x0, 0x12, 0x22, - 0x22, 0x22, 0x22, 0x49, 0xdf, 0xc8, 0x30, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, 0xde, - 0xb6, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x5a, 0xef, 0xc7, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0x7b, 0xcc, 0xde, - 0xfe, 0xc8, 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x27, 0xcf, 0xd7, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x4, 0x9e, 0xf9, 0x40, 0x0, 0x16, 0xbd, 0xc9, - 0x65, 0x43, 0x33, 0x46, 0x9c, 0xff, 0xa5, 0x10, - 0x0, 0x1, 0x36, 0x9b, 0xce, 0xff, 0xff, 0xed, - 0xca, 0x63, 0x10, 0x0, - - /* U+0034 "4" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, 0xde, - 0xb6, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x14, 0x9e, 0xeb, 0x51, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4a, - 0xee, 0xa5, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x15, 0xae, 0xea, 0x51, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x5a, 0xee, 0xa4, 0x10, 0x0, 0x28, 0xdf, 0x94, - 0x0, 0x0, 0x0, 0x0, 0x15, 0xbe, 0xea, 0x41, - 0x0, 0x0, 0x2, 0x8d, 0xf9, 0x40, 0x0, 0x0, - 0x0, 0x38, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xd8, 0x30, 0x0, 0x12, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x25, 0x9e, 0xfa, - 0x62, 0x22, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x38, 0xef, 0x94, 0x0, 0x0, - 0x0, 0x0, - - /* U+0035 "5" */ - 0x0, 0x0, 0x1, 0x7c, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa5, 0x0, 0x0, 0x0, 0x3, 0x9e, - 0xe9, 0x52, 0x22, 0x22, 0x22, 0x22, 0x10, 0x0, - 0x0, 0x0, 0x5, 0xaf, 0xc6, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, 0xcf, - 0xff, 0xff, 0xee, 0xdd, 0xb9, 0x63, 0x10, 0x0, - 0x0, 0x0, 0x1, 0x22, 0x22, 0x22, 0x33, 0x46, - 0x9c, 0xff, 0xb6, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0x8d, 0xfb, 0x60, - 0x0, 0x0, 0x1, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x8d, 0xfb, 0x61, 0x0, 0x4, 0x9e, 0xeb, - 0x86, 0x43, 0x33, 0x45, 0x8c, 0xef, 0xb6, 0x10, - 0x0, 0x0, 0x24, 0x8a, 0xcd, 0xef, 0xff, 0xfe, - 0xca, 0x74, 0x10, 0x0, - - /* U+0036 "6" */ - 0x0, 0x0, 0x1, 0x36, 0x9b, 0xde, 0xff, 0xfe, - 0xdc, 0x95, 0x10, 0x0, 0x0, 0x3, 0x8d, 0xfd, - 0xa7, 0x53, 0x32, 0x22, 0x34, 0x32, 0x0, 0x0, - 0x1, 0x6b, 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x4, 0xaf, 0xd9, 0x66, - 0x9b, 0xde, 0xee, 0xdc, 0xa7, 0x31, 0x0, 0x0, - 0x16, 0xbf, 0xff, 0xec, 0x95, 0x43, 0x23, 0x58, - 0xce, 0xfa, 0x51, 0x0, 0x5, 0xaf, 0xfd, 0x83, - 0x0, 0x0, 0x0, 0x0, 0x28, 0xdf, 0xb5, 0x0, - 0x2, 0x7d, 0xfd, 0x82, 0x0, 0x0, 0x0, 0x0, - 0x27, 0xdf, 0xa5, 0x0, 0x0, 0x15, 0xaf, 0xec, - 0x84, 0x32, 0x12, 0x47, 0xbe, 0xea, 0x51, 0x0, - 0x0, 0x0, 0x13, 0x7a, 0xce, 0xff, 0xff, 0xec, - 0xa7, 0x31, 0x0, 0x0, - - /* U+0037 "7" */ - 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfb, 0x50, 0x0, 0x5a, 0xfd, 0x94, 0x22, - 0x22, 0x22, 0x22, 0x49, 0xdf, 0xc7, 0x20, 0x0, - 0x37, 0xb9, 0x62, 0x0, 0x0, 0x0, 0x3, 0x8e, - 0xfb, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x5a, 0xee, 0x94, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xd8, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x7d, 0xfc, 0x71, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x39, 0xef, 0xa5, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, - 0xaf, 0xe9, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0x6c, 0xfd, 0x82, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+0038 "8" */ - 0x0, 0x0, 0x36, 0x9c, 0xde, 0xff, 0xfe, 0xdc, - 0xa7, 0x31, 0x0, 0x0, 0x0, 0x49, 0xef, 0xc8, - 0x53, 0x11, 0x12, 0x48, 0xcf, 0xea, 0x50, 0x0, - 0x2, 0x7d, 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, - 0x5a, 0xfd, 0x83, 0x0, 0x0, 0x39, 0xef, 0xb7, - 0x31, 0x0, 0x1, 0x37, 0xbe, 0xe9, 0x40, 0x0, - 0x0, 0x2, 0x6b, 0xef, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0x62, 0x0, 0x0, 0x3, 0x8d, 0xfd, 0x95, - 0x21, 0x0, 0x1, 0x24, 0x8c, 0xfe, 0x94, 0x0, - 0x16, 0xcf, 0xc7, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x6, 0xbf, 0xd7, 0x20, 0x3, 0x8d, 0xfd, 0xa6, - 0x32, 0x11, 0x12, 0x35, 0x9c, 0xfe, 0x94, 0x0, - 0x0, 0x2, 0x58, 0xbc, 0xef, 0xff, 0xff, 0xed, - 0xb9, 0x52, 0x0, 0x0, - - /* U+0039 "9" */ - 0x0, 0x13, 0x7a, 0xce, 0xff, 0xff, 0xec, 0xa7, - 0x31, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xeb, 0x63, - 0x21, 0x12, 0x35, 0x9d, 0xeb, 0x61, 0x0, 0x0, - 0x49, 0xfe, 0x83, 0x0, 0x0, 0x0, 0x0, 0x6, - 0xbf, 0xd8, 0x30, 0x0, 0x27, 0xcf, 0xd9, 0x42, - 0x0, 0x0, 0x13, 0x7c, 0xff, 0xfb, 0x60, 0x0, - 0x0, 0x26, 0xad, 0xff, 0xff, 0xff, 0xfd, 0xa7, - 0x9c, 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x11, 0x10, 0x0, 0x3, 0x8d, 0xfb, 0x60, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, - 0xdf, 0xc7, 0x20, 0x0, 0x0, 0x24, 0x65, 0x32, - 0x23, 0x45, 0x8b, 0xef, 0xd9, 0x40, 0x0, 0x0, - 0x1, 0x48, 0xcd, 0xef, 0xff, 0xed, 0xca, 0x74, - 0x10, 0x0, 0x0, 0x0, - - /* U+003A ":" */ - 0x4, 0x9e, 0xe9, 0x40, 0x0, 0x26, 0xaa, 0x73, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26, - 0xaa, 0x73, 0x0, 0x4, 0x9d, 0xd9, 0x40, 0x0, - - /* U+003B ";" */ - 0x4, 0x9e, 0xe9, 0x40, 0x0, 0x26, 0xaa, 0x73, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, - 0x88, 0x52, 0x0, 0x4, 0xaf, 0xfc, 0x61, 0x0, - 0x5, 0xbd, 0x82, 0x0, 0x3, 0x9c, 0x83, 0x0, - 0x0, - - /* U+003C "<" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x23, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, - 0x79, 0xbd, 0xee, 0xb6, 0x10, 0x0, 0x24, 0x79, - 0xbd, 0xee, 0xc9, 0x75, 0x31, 0x0, 0x0, 0x0, - 0x38, 0xdf, 0xec, 0x84, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0x46, 0x9b, 0xde, 0xec, - 0xa7, 0x53, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x46, 0x9b, 0xde, 0xc7, 0x20, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x10, 0x0, - - /* U+003D "=" */ - 0x3, 0x8e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0x83, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x27, 0xce, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xc7, 0x20, 0x0, 0x1, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x0, 0x0, - - /* U+003E ">" */ - 0x1, 0x23, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x26, 0xbe, 0xed, 0xb9, 0x64, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x35, 0x7a, 0xce, 0xed, 0xb9, 0x64, 0x20, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x8c, 0xef, - 0xd8, 0x20, 0x0, 0x0, 0x13, 0x57, 0xac, 0xee, - 0xdb, 0x96, 0x42, 0x0, 0x0, 0x27, 0xce, 0xdb, - 0x96, 0x42, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+003F "?" */ - 0x0, 0x0, 0x14, 0x7a, 0xcd, 0xef, 0xff, 0xed, - 0xca, 0x63, 0x0, 0x0, 0x0, 0x4, 0x9d, 0xda, - 0x75, 0x32, 0x22, 0x36, 0xad, 0xfe, 0x83, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x38, 0xef, 0xa5, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x15, 0xae, 0xea, 0x51, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x49, 0xde, - 0xc8, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x27, 0xdf, 0xc7, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x25, 0x88, 0x52, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, 0xdd, 0x94, - 0x0, 0x0, 0x0, 0x0, - - /* U+0040 "@" */ - 0x0, 0x0, 0x0, 0x0, 0x2, 0x47, 0x9b, 0xcd, - 0xdd, 0xdd, 0xdd, 0xdc, 0xa8, 0x63, 0x10, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, 0x9c, - 0xdb, 0x85, 0x31, 0x0, 0x0, 0x0, 0x0, 0x13, - 0x68, 0xcd, 0xc7, 0x30, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x7c, 0xda, 0x51, 0x1, 0x48, 0xbd, 0xef, - 0xfe, 0xdb, 0x86, 0x9d, 0xe9, 0x56, 0xbd, 0xa4, - 0x10, 0x0, 0x0, 0x4, 0x9d, 0xa5, 0x0, 0x27, - 0xcf, 0xd9, 0x52, 0x10, 0x12, 0x59, 0xdf, 0xfe, - 0x83, 0x1, 0x7c, 0xc7, 0x10, 0x0, 0x4, 0x9d, - 0xa5, 0x0, 0x28, 0xde, 0x94, 0x0, 0x0, 0x0, - 0x0, 0x4, 0xaf, 0xe8, 0x30, 0x1, 0x7c, 0xb6, - 0x0, 0x0, 0x5b, 0xd8, 0x20, 0x4, 0x9f, 0xd7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x27, 0xde, 0x83, - 0x0, 0x5, 0xac, 0x72, 0x0, 0x5, 0xbd, 0x82, - 0x0, 0x28, 0xde, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x4, 0xaf, 0xe8, 0x30, 0x1, 0x6b, 0xb6, 0x0, - 0x0, 0x39, 0xda, 0x50, 0x0, 0x27, 0xcf, 0xd9, - 0x52, 0x10, 0x12, 0x6a, 0xdf, 0xff, 0xa5, 0x12, - 0x7b, 0xc7, 0x20, 0x0, 0x0, 0x49, 0xda, 0x50, - 0x0, 0x1, 0x48, 0xbd, 0xef, 0xfe, 0xdb, 0x84, - 0x35, 0xad, 0xff, 0xeb, 0x73, 0x0, 0x0, 0x0, - 0x0, 0x26, 0xbd, 0xa5, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x59, 0xcd, - 0xb8, 0x53, 0x10, 0x0, 0x0, 0x0, 0x24, 0x54, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x25, 0x79, 0xbd, 0xdd, 0xee, - 0xee, 0xdd, 0xb9, 0x62, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+0041 "A" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, - 0xfd, 0x83, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0xdf, - 0xdd, 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, 0xee, - 0x94, 0x38, 0xdf, 0xb5, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5b, 0xfe, - 0x83, 0x0, 0x27, 0xcf, 0xc7, 0x20, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x7c, 0xfd, - 0x72, 0x0, 0x0, 0x16, 0xcf, 0xe8, 0x30, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x8d, 0xfc, - 0x71, 0x0, 0x0, 0x0, 0x15, 0xbf, 0xfa, 0x50, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xae, 0xff, - 0xff, 0xee, 0xee, 0xee, 0xee, 0xef, 0xff, 0xfb, - 0x61, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xea, - 0x52, 0x11, 0x11, 0x11, 0x11, 0x11, 0x14, 0x8d, - 0xfd, 0x72, 0x0, 0x0, 0x0, 0x27, 0xcf, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x6b, 0xfe, 0x94, 0x0, 0x0, - - /* U+0042 "B" */ - 0x0, 0x16, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xdb, 0x95, 0x20, 0x0, 0x0, 0x1, 0x6b, - 0xfc, 0x72, 0x11, 0x11, 0x11, 0x12, 0x36, 0xad, - 0xfd, 0x72, 0x0, 0x0, 0x16, 0xbf, 0xc7, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x3, 0x8e, 0xfa, 0x50, - 0x0, 0x1, 0x6b, 0xfc, 0x72, 0x0, 0x0, 0x0, - 0x0, 0x14, 0x8d, 0xfc, 0x72, 0x0, 0x0, 0x16, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xea, 0x51, 0x0, 0x0, 0x1, 0x6b, 0xfc, 0x83, - 0x22, 0x22, 0x22, 0x22, 0x34, 0x69, 0xdf, 0xd7, - 0x20, 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x17, 0xcf, 0xc7, 0x10, 0x1, - 0x6b, 0xfc, 0x72, 0x11, 0x11, 0x11, 0x11, 0x13, - 0x58, 0xcf, 0xe9, 0x40, 0x0, 0x16, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xed, 0xc9, 0x63, - 0x0, 0x0, - - /* U+0043 "C" */ - 0x0, 0x0, 0x0, 0x13, 0x69, 0xbd, 0xee, 0xff, - 0xfe, 0xdb, 0x96, 0x31, 0x0, 0x0, 0x0, 0x15, - 0x9e, 0xfe, 0xc9, 0x65, 0x33, 0x33, 0x46, 0x8b, - 0xee, 0xa4, 0x0, 0x0, 0x4a, 0xef, 0xb6, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x49, 0xfe, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, - 0xc7, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x49, 0xfe, 0x94, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x4a, 0xef, 0xb6, 0x20, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x15, 0xae, 0xfe, 0xc9, 0x65, 0x33, 0x33, 0x46, - 0x8b, 0xee, 0xa4, 0x0, 0x0, 0x0, 0x0, 0x13, - 0x69, 0xbd, 0xef, 0xff, 0xfe, 0xdb, 0x96, 0x31, - 0x0, 0x0, - - /* U+0044 "D" */ - 0x0, 0x16, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xed, 0xca, 0x85, 0x30, 0x0, 0x0, 0x0, 0x0, - 0x16, 0xbf, 0xc8, 0x32, 0x22, 0x22, 0x23, 0x35, - 0x69, 0xce, 0xfd, 0x94, 0x10, 0x0, 0x0, 0x16, - 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x7c, 0xfe, 0x93, 0x0, 0x0, 0x16, 0xbf, - 0xc7, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x5, 0xbf, 0xe8, 0x30, 0x0, 0x16, 0xbf, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0x8e, 0xfa, 0x50, 0x0, 0x16, 0xbf, 0xc7, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0xaf, - 0xe8, 0x30, 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0x7c, 0xfe, 0x93, - 0x0, 0x0, 0x16, 0xbf, 0xc8, 0x32, 0x22, 0x22, - 0x23, 0x35, 0x69, 0xce, 0xfd, 0x94, 0x10, 0x0, - 0x0, 0x16, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xed, 0xcb, 0x86, 0x31, 0x0, 0x0, 0x0, - - /* U+0045 "E" */ - 0x0, 0x16, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd8, 0x30, 0x0, 0x16, 0xbf, 0xc8, - 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x0, - 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x16, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfa, 0x50, 0x0, 0x0, 0x16, 0xbf, 0xc8, - 0x32, 0x22, 0x22, 0x22, 0x22, 0x21, 0x0, 0x0, - 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc8, - 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x21, 0x0, - 0x0, 0x16, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfb, 0x50, - - /* U+0046 "F" */ - 0x0, 0x16, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd8, 0x30, 0x0, 0x16, 0xbf, 0xc8, - 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x0, - 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x16, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfa, 0x50, 0x0, 0x0, 0x16, 0xbf, 0xd8, - 0x42, 0x22, 0x22, 0x22, 0x22, 0x21, 0x0, 0x0, - 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+0047 "G" */ - 0x0, 0x0, 0x0, 0x13, 0x69, 0xbc, 0xee, 0xff, - 0xfe, 0xdc, 0xa7, 0x41, 0x0, 0x0, 0x0, 0x15, - 0xae, 0xfe, 0xc9, 0x65, 0x43, 0x33, 0x46, 0x8a, - 0xde, 0xb5, 0x10, 0x0, 0x4a, 0xef, 0xc7, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x49, 0xfe, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, - 0xc7, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x25, 0x87, 0x42, 0x0, 0x49, 0xfe, 0x94, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x9e, 0xe9, - 0x30, 0x0, 0x4a, 0xef, 0xb6, 0x20, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x49, 0xee, 0x93, 0x0, 0x0, - 0x15, 0xae, 0xfe, 0xc9, 0x65, 0x33, 0x33, 0x45, - 0x7a, 0xdf, 0xe8, 0x30, 0x0, 0x0, 0x0, 0x13, - 0x69, 0xbd, 0xee, 0xff, 0xfe, 0xdc, 0xa7, 0x41, - 0x0, 0x0, - - /* U+0048 "H" */ - 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x6, 0xbf, 0xd7, 0x20, 0x1, 0x6b, - 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x6b, 0xfd, 0x72, 0x0, 0x16, 0xbf, 0xc7, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0xbf, 0xd7, - 0x20, 0x1, 0x6b, 0xfc, 0x72, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x6b, 0xfd, 0x72, 0x0, 0x16, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd7, 0x20, 0x1, 0x6b, 0xfd, 0x84, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0x7c, 0xfd, - 0x72, 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x6, 0xbf, 0xd7, 0x20, 0x1, - 0x6b, 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x6b, 0xfd, 0x72, 0x0, 0x16, 0xbf, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0xbf, - 0xd7, 0x20, - - /* U+0049 "I" */ - 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x1, 0x6b, 0xfc, - 0x72, 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x1, 0x6b, - 0xfc, 0x72, 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x1, - 0x6b, 0xfc, 0x72, 0x0, 0x16, 0xbf, 0xc7, 0x20, - 0x1, 0x6b, 0xfc, 0x72, 0x0, 0x16, 0xbf, 0xc7, - 0x20, - - /* U+004A "J" */ - 0x0, 0x0, 0x49, 0xef, 0xff, 0xff, 0xff, 0xff, - 0xfa, 0x40, 0x0, 0x0, 0x0, 0x12, 0x22, 0x22, - 0x22, 0x59, 0xef, 0xa4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0x8e, 0xfa, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xef, - 0xa4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0x8e, 0xfa, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x38, 0xef, 0xa4, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x9f, 0xe9, - 0x30, 0x0, 0x3, 0x8d, 0xc9, 0x53, 0x22, 0x47, - 0xbe, 0xfa, 0x51, 0x0, 0x0, 0x2, 0x58, 0xbd, - 0xef, 0xfe, 0xdb, 0x95, 0x20, 0x0, 0x0, - - /* U+004B "K" */ - 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x27, 0xbe, 0xd9, 0x41, 0x0, 0x1, 0x6b, - 0xfc, 0x72, 0x0, 0x0, 0x0, 0x15, 0xae, 0xeb, - 0x62, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc7, 0x20, - 0x0, 0x14, 0x9d, 0xec, 0x73, 0x0, 0x0, 0x0, - 0x0, 0x1, 0x6b, 0xfc, 0x72, 0x3, 0x7c, 0xed, - 0x94, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, - 0xbf, 0xc9, 0x8b, 0xef, 0xff, 0xc7, 0x20, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x6b, 0xff, 0xff, - 0xc8, 0x45, 0x9d, 0xfd, 0x94, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x16, 0xbf, 0xea, 0x51, 0x0, 0x0, - 0x27, 0xcf, 0xea, 0x51, 0x0, 0x0, 0x0, 0x1, - 0x6b, 0xfc, 0x72, 0x0, 0x0, 0x0, 0x1, 0x5a, - 0xef, 0xc7, 0x20, 0x0, 0x0, 0x16, 0xbf, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x3, 0x8d, 0xfd, - 0x83, 0x0, - - /* U+004C "L" */ - 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc8, - 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x10, 0x0, - 0x0, 0x16, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xb5, 0x0, - - /* U+004D "M" */ - 0x0, 0x16, 0xbf, 0xd8, 0x30, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x6b, 0xfd, 0x83, - 0x0, 0x1, 0x6b, 0xff, 0xfb, 0x61, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x4, 0x9e, 0xff, 0xd8, - 0x30, 0x0, 0x16, 0xbf, 0xee, 0xee, 0xa4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x27, 0xde, 0xee, 0xfd, - 0x83, 0x0, 0x1, 0x6b, 0xfb, 0x76, 0xbe, 0xd8, - 0x30, 0x0, 0x0, 0x1, 0x6b, 0xec, 0x76, 0xaf, - 0xd8, 0x30, 0x0, 0x16, 0xbf, 0xb6, 0x12, 0x7c, - 0xfb, 0x61, 0x0, 0x4, 0x9e, 0xd8, 0x30, 0x4a, - 0xfd, 0x83, 0x0, 0x1, 0x6b, 0xfb, 0x61, 0x0, - 0x39, 0xde, 0x94, 0x37, 0xce, 0xa5, 0x10, 0x4, - 0xaf, 0xd8, 0x30, 0x0, 0x16, 0xbf, 0xb6, 0x10, - 0x0, 0x15, 0xae, 0xff, 0xec, 0x72, 0x0, 0x0, - 0x4a, 0xfd, 0x83, 0x0, 0x1, 0x6b, 0xfb, 0x61, - 0x0, 0x0, 0x2, 0x6b, 0xc8, 0x30, 0x0, 0x0, - 0x4, 0xaf, 0xd8, 0x30, 0x0, 0x16, 0xbf, 0xb6, - 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x4a, 0xfd, 0x83, 0x0, - - /* U+004E "N" */ - 0x0, 0x16, 0xbf, 0xe9, 0x41, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x6, 0xbf, 0xd7, 0x20, 0x1, 0x6b, - 0xff, 0xfe, 0xb5, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x6b, 0xfd, 0x72, 0x0, 0x16, 0xbf, 0xdc, 0xce, - 0xfc, 0x72, 0x0, 0x0, 0x0, 0x6, 0xbf, 0xd7, - 0x20, 0x1, 0x6b, 0xfc, 0x73, 0x4a, 0xef, 0xd8, - 0x30, 0x0, 0x0, 0x6b, 0xfd, 0x72, 0x0, 0x16, - 0xbf, 0xc7, 0x20, 0x3, 0x8d, 0xfe, 0x94, 0x10, - 0x6, 0xbf, 0xd7, 0x20, 0x1, 0x6b, 0xfc, 0x72, - 0x0, 0x0, 0x27, 0xcf, 0xeb, 0x52, 0x6b, 0xfd, - 0x72, 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, - 0x1, 0x6b, 0xef, 0xcc, 0xdf, 0xd7, 0x20, 0x1, - 0x6b, 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, 0x14, - 0xae, 0xff, 0xfd, 0x72, 0x0, 0x16, 0xbf, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xdf, - 0xd7, 0x20, - - /* U+004F "O" */ - 0x0, 0x0, 0x0, 0x13, 0x69, 0xbc, 0xee, 0xff, - 0xfe, 0xdb, 0x97, 0x41, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x59, 0xef, 0xec, 0x96, 0x53, 0x33, 0x34, - 0x68, 0xbe, 0xfe, 0xb6, 0x20, 0x0, 0x0, 0x4a, - 0xef, 0xb6, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x5a, 0xef, 0xb5, 0x10, 0x4, 0x9f, 0xe9, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0x8d, 0xfb, 0x50, 0x16, 0xbf, 0xc7, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x6b, 0xfc, 0x72, 0x4, 0x9f, 0xe9, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x8d, - 0xfb, 0x50, 0x0, 0x4a, 0xef, 0xb6, 0x20, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x5a, 0xef, 0xb5, - 0x10, 0x0, 0x1, 0x5a, 0xef, 0xec, 0x96, 0x43, - 0x33, 0x34, 0x68, 0xbe, 0xfe, 0xb6, 0x20, 0x0, - 0x0, 0x0, 0x0, 0x13, 0x69, 0xbd, 0xee, 0xff, - 0xfe, 0xdb, 0x97, 0x41, 0x0, 0x0, 0x0, - - /* U+0050 "P" */ - 0x0, 0x16, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xdc, 0xa8, 0x52, 0x0, 0x0, 0x0, 0x1, 0x6b, - 0xfc, 0x83, 0x22, 0x22, 0x22, 0x35, 0x7a, 0xdf, - 0xd9, 0x40, 0x0, 0x0, 0x16, 0xbf, 0xc7, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x4, 0x9e, 0xe9, 0x40, - 0x0, 0x1, 0x6b, 0xfc, 0x72, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x39, 0xef, 0xa4, 0x0, 0x0, 0x16, - 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, 0x24, 0x8c, - 0xfe, 0xa5, 0x10, 0x0, 0x1, 0x6b, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0xa7, 0x31, 0x0, - 0x0, 0x0, 0x16, 0xbf, 0xd8, 0x42, 0x22, 0x22, - 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x6b, 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+0051 "Q" */ - 0x0, 0x0, 0x0, 0x13, 0x69, 0xbc, 0xee, 0xff, - 0xfe, 0xdb, 0x97, 0x41, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x14, 0x9d, 0xfe, 0xc9, 0x65, 0x33, - 0x33, 0x46, 0x8b, 0xef, 0xeb, 0x62, 0x0, 0x0, - 0x0, 0x0, 0x49, 0xef, 0xb6, 0x20, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x5a, 0xef, 0xb5, 0x10, - 0x0, 0x0, 0x49, 0xfe, 0x94, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xdf, 0xb5, - 0x0, 0x0, 0x16, 0xbf, 0xc7, 0x20, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6b, 0xfc, - 0x72, 0x0, 0x0, 0x4a, 0xfe, 0x94, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xdf, - 0xb6, 0x0, 0x0, 0x0, 0x5a, 0xff, 0xb6, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5a, 0xef, - 0xb6, 0x10, 0x0, 0x0, 0x0, 0x15, 0xae, 0xfe, - 0xb8, 0x54, 0x32, 0x22, 0x35, 0x7a, 0xdf, 0xeb, - 0x62, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, - 0x7a, 0xcd, 0xef, 0xff, 0xff, 0xec, 0xa8, 0x52, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0x8c, 0xfe, 0xb6, 0x20, - 0x0, 0x26, 0x98, 0x50, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x13, 0x7b, 0xdf, - 0xff, 0xfe, 0xd9, 0x52, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, - - /* U+0052 "R" */ - 0x0, 0x16, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xdc, 0xa8, 0x52, 0x0, 0x0, 0x0, 0x1, 0x6b, - 0xfc, 0x83, 0x22, 0x22, 0x22, 0x35, 0x7a, 0xdf, - 0xd9, 0x40, 0x0, 0x0, 0x16, 0xbf, 0xc7, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x4, 0x9e, 0xe9, 0x40, - 0x0, 0x1, 0x6b, 0xfc, 0x72, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x39, 0xef, 0xa5, 0x0, 0x0, 0x16, - 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, 0x14, 0x8b, - 0xef, 0xb5, 0x10, 0x0, 0x1, 0x6b, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0xb7, 0x41, 0x0, - 0x0, 0x0, 0x16, 0xbf, 0xc8, 0x32, 0x22, 0x22, - 0x26, 0xbe, 0xd9, 0x40, 0x0, 0x0, 0x0, 0x1, - 0x6b, 0xfc, 0x72, 0x0, 0x0, 0x0, 0x1, 0x6b, - 0xfd, 0x83, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x27, 0xcf, 0xd8, - 0x30, 0x0, - - /* U+0053 "S" */ - 0x0, 0x1, 0x37, 0xac, 0xde, 0xff, 0xfe, 0xdc, - 0xb8, 0x63, 0x10, 0x0, 0x1, 0x5b, 0xfe, 0xb7, - 0x43, 0x22, 0x23, 0x45, 0x79, 0x84, 0x0, 0x0, - 0x4, 0x9e, 0xe9, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x5b, 0xfe, 0xc9, - 0x63, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x25, 0x8b, 0xce, 0xff, 0xfd, 0xca, - 0x74, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0x34, 0x69, 0xcf, 0xea, 0x51, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x49, 0xfe, 0x93, 0x0, 0x5, 0xad, 0xb8, 0x64, - 0x32, 0x22, 0x23, 0x48, 0xbe, 0xfb, 0x51, 0x0, - 0x0, 0x25, 0x8a, 0xcd, 0xef, 0xff, 0xfe, 0xdc, - 0xa7, 0x31, 0x0, 0x0, - - /* U+0054 "T" */ - 0x0, 0x4a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfa, 0x50, 0x0, 0x0, 0x12, - 0x22, 0x22, 0x23, 0x7c, 0xfc, 0x83, 0x22, 0x22, - 0x22, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x16, 0xcf, 0xc7, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6c, 0xfc, - 0x71, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x16, 0xcf, 0xc7, 0x10, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x6c, 0xfc, 0x71, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xcf, - 0xc7, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x6c, 0xfc, 0x71, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x16, 0xcf, 0xc7, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+0055 "U" */ - 0x0, 0x27, 0xdf, 0xb6, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x38, 0xef, 0xa4, 0x0, 0x2, 0x7d, - 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0x8e, 0xfa, 0x40, 0x0, 0x27, 0xdf, 0xb6, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xef, 0xa4, - 0x0, 0x2, 0x7d, 0xfb, 0x61, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0x8e, 0xfa, 0x40, 0x0, 0x27, - 0xdf, 0xb6, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x38, 0xef, 0xa4, 0x0, 0x1, 0x6c, 0xfc, 0x71, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x9f, 0xe8, - 0x30, 0x0, 0x4, 0x9e, 0xfa, 0x50, 0x0, 0x0, - 0x0, 0x0, 0x2, 0x8d, 0xfc, 0x61, 0x0, 0x0, - 0x2, 0x7c, 0xfe, 0xb8, 0x54, 0x33, 0x35, 0x7a, - 0xdf, 0xea, 0x50, 0x0, 0x0, 0x0, 0x0, 0x14, - 0x8a, 0xce, 0xff, 0xfe, 0xdd, 0xb8, 0x52, 0x0, - 0x0, 0x0, - - /* U+0056 "V" */ - 0x0, 0x27, 0xcf, 0xc7, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0x8d, 0xfa, 0x51, 0x0, - 0x1, 0x6b, 0xfe, 0x93, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x49, 0xee, 0x94, 0x0, 0x0, 0x0, - 0x5, 0xaf, 0xea, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x5, 0xaf, 0xd8, 0x30, 0x0, 0x0, 0x0, 0x0, - 0x39, 0xef, 0xb6, 0x10, 0x0, 0x0, 0x1, 0x6c, - 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0x7d, 0xfc, 0x72, 0x0, 0x0, 0x27, 0xdf, 0xb6, - 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, - 0xcf, 0xd8, 0x30, 0x3, 0x9e, 0xfa, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, - 0xfe, 0x95, 0x5a, 0xfe, 0x93, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x9e, - 0xfe, 0xef, 0xd7, 0x20, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xdf, - 0xfc, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+0057 "W" */ - 0x27, 0xcf, 0xc7, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x3, 0x9e, 0xfd, 0x83, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x28, 0xdf, 0xa4, 0x0, 0x2, 0x7d, 0xfc, - 0x61, 0x0, 0x0, 0x0, 0x0, 0x39, 0xef, 0xff, - 0xd8, 0x20, 0x0, 0x0, 0x0, 0x2, 0x7d, 0xfa, - 0x50, 0x0, 0x0, 0x28, 0xdf, 0xb6, 0x10, 0x0, - 0x0, 0x3, 0x8e, 0xd9, 0x8b, 0xfd, 0x72, 0x0, - 0x0, 0x0, 0x27, 0xcf, 0xa5, 0x0, 0x0, 0x0, - 0x3, 0x8d, 0xfb, 0x60, 0x0, 0x0, 0x38, 0xee, - 0x83, 0x5, 0xbf, 0xc7, 0x20, 0x0, 0x1, 0x7c, - 0xfb, 0x50, 0x0, 0x0, 0x0, 0x0, 0x38, 0xef, - 0xb5, 0x0, 0x3, 0x8d, 0xe9, 0x30, 0x1, 0x6b, - 0xfc, 0x71, 0x0, 0x16, 0xcf, 0xb6, 0x10, 0x0, - 0x0, 0x0, 0x0, 0x3, 0x9e, 0xfa, 0x50, 0x38, - 0xde, 0x94, 0x0, 0x0, 0x16, 0xbf, 0xc6, 0x11, - 0x6b, 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x49, 0xef, 0xa7, 0x8d, 0xe9, 0x40, 0x0, - 0x0, 0x1, 0x6b, 0xfb, 0x77, 0xbf, 0xc6, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x9e, - 0xff, 0xfe, 0x94, 0x0, 0x0, 0x0, 0x0, 0x16, - 0xbf, 0xff, 0xfc, 0x71, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x4a, 0xff, 0xea, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x6c, 0xff, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, - - /* U+0058 "X" */ - 0x0, 0x1, 0x5a, 0xef, 0xb6, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x49, 0xee, 0xb5, 0x10, 0x0, 0x0, - 0x0, 0x1, 0x5a, 0xef, 0xb6, 0x10, 0x0, 0x0, - 0x49, 0xee, 0xa5, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0x4a, 0xef, 0xb6, 0x21, 0x4a, 0xee, - 0xa5, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0x49, 0xef, 0xdd, 0xee, 0xa4, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0x8d, 0xff, 0xe9, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0x7c, 0xfd, 0xaa, 0xdf, 0xd8, 0x30, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x7c, 0xfd, - 0x83, 0x0, 0x27, 0xcf, 0xd8, 0x30, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0x7c, 0xfd, 0x83, 0x0, - 0x0, 0x0, 0x27, 0xcf, 0xd9, 0x30, 0x0, 0x0, - 0x0, 0x3, 0x8c, 0xfd, 0x83, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x27, 0xcf, 0xd9, 0x40, 0x0, - - /* U+0059 "Y" */ - 0x0, 0x16, 0xcf, 0xd8, 0x30, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x15, 0xae, 0xd8, 0x30, 0x0, 0x0, - 0x0, 0x38, 0xdf, 0xb6, 0x10, 0x0, 0x0, 0x0, - 0x3, 0x8d, 0xea, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x4a, 0xee, 0xa5, 0x0, 0x0, 0x2, 0x7c, - 0xeb, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x6b, 0xfd, 0x83, 0x1, 0x5b, 0xed, 0x72, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x7c, 0xfc, 0xab, 0xee, 0x94, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x4, 0x9e, 0xff, 0xb5, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x6b, 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6b, - 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6b, 0xfc, - 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+005A "Z" */ - 0x16, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfb, 0x50, 0x0, 0x12, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x25, 0x9d, 0xfd, 0x94, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x9d, - 0xfc, 0x73, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x15, 0xae, 0xfb, 0x62, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x26, 0xbf, 0xea, 0x51, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, - 0xcf, 0xd9, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0x49, 0xdf, 0xc7, 0x20, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x5b, 0xef, 0xc8, - 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x21, 0x10, - 0x27, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x83, - - /* U+005B "[" */ - 0x0, 0x16, 0xbf, 0xff, 0xff, 0xc7, 0x10, 0x0, - 0x1, 0x6b, 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, - 0x16, 0xbf, 0xb6, 0x10, 0x0, 0x0, 0x0, 0x1, - 0x6b, 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, 0x16, - 0xbf, 0xb6, 0x10, 0x0, 0x0, 0x0, 0x1, 0x6b, - 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, - 0xb6, 0x10, 0x0, 0x0, 0x0, 0x1, 0x6b, 0xfb, - 0x61, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xb6, - 0x10, 0x0, 0x0, 0x0, 0x1, 0x6b, 0xfb, 0x61, - 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xb6, 0x10, - 0x0, 0x0, 0x0, 0x1, 0x6b, 0xfb, 0x61, 0x0, - 0x0, 0x0, 0x0, 0x16, 0xbf, 0xff, 0xff, 0xc7, - 0x10, 0x0, - - /* U+005C "\\" */ - 0x3, 0x57, 0x52, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x7c, 0xe9, 0x30, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x27, 0xde, 0x83, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0x8d, 0xd8, 0x30, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xdd, - 0x82, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0x8d, 0xd8, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x38, 0xed, 0x72, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0x9e, 0xc7, 0x20, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x49, 0xec, 0x71, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x9e, 0xc7, - 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, - 0xec, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x4, 0xae, 0xb6, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x5a, 0xfb, 0x61, - - /* U+005D "]" */ - 0x0, 0x17, 0xcf, 0xff, 0xff, 0xb6, 0x10, 0x0, - 0x0, 0x0, 0x1, 0x7c, 0xfb, 0x61, 0x0, 0x0, - 0x0, 0x0, 0x16, 0xcf, 0xb6, 0x10, 0x0, 0x0, - 0x0, 0x1, 0x6c, 0xfb, 0x61, 0x0, 0x0, 0x0, - 0x0, 0x16, 0xcf, 0xb6, 0x10, 0x0, 0x0, 0x0, - 0x1, 0x6c, 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, - 0x16, 0xcf, 0xb6, 0x10, 0x0, 0x0, 0x0, 0x1, - 0x6c, 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, 0x16, - 0xcf, 0xb6, 0x10, 0x0, 0x0, 0x0, 0x1, 0x6c, - 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, 0x16, 0xcf, - 0xb6, 0x10, 0x0, 0x0, 0x0, 0x1, 0x7c, 0xfb, - 0x61, 0x0, 0x0, 0x17, 0xcf, 0xff, 0xff, 0xb6, - 0x10, 0x0, - - /* U+005E "^" */ - 0x0, 0x0, 0x0, 0x0, 0x35, 0x76, 0x30, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5a, 0xee, - 0xeb, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x6b, 0xc7, 0x47, 0xcb, 0x61, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x7c, 0xc7, 0x10, 0x17, 0xcc, 0x72, - 0x0, 0x0, 0x0, 0x3, 0x8d, 0xb6, 0x10, 0x0, - 0x16, 0xbd, 0x82, 0x0, 0x0, 0x3, 0x9d, 0xb5, - 0x0, 0x0, 0x0, 0x5, 0xbd, 0x93, 0x0, - - /* U+005F "_" */ - 0x0, 0x48, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0x84, 0x0, - - /* U+0060 "`" */ - 0x2, 0x47, 0x76, 0x31, 0x0, 0x0, 0x0, 0x2, - 0x58, 0xcc, 0x95, 0x10, - - /* U+0061 "a" */ - 0x0, 0x25, 0x8a, 0xcd, 0xef, 0xfe, 0xec, 0xa6, - 0x30, 0x0, 0x0, 0x3, 0x7a, 0x85, 0x42, 0x22, - 0x35, 0x9d, 0xfd, 0x83, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x6b, 0xfb, 0x61, 0x0, - 0x1, 0x48, 0xbc, 0xdd, 0xee, 0xee, 0xee, 0xff, - 0xc7, 0x20, 0x4, 0x9f, 0xe9, 0x41, 0x0, 0x0, - 0x0, 0x5b, 0xfc, 0x72, 0x0, 0x4a, 0xfe, 0x94, - 0x0, 0x0, 0x3, 0x7b, 0xff, 0xc7, 0x20, 0x0, - 0x15, 0x9c, 0xde, 0xed, 0xdc, 0xb8, 0x8b, 0xfc, - 0x72, 0x0, - - /* U+0062 "b" */ - 0x0, 0x39, 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x9e, - 0xe9, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x39, 0xee, 0x94, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0x9e, 0xea, 0x77, 0xac, 0xef, 0xff, - 0xec, 0xa7, 0x41, 0x0, 0x0, 0x0, 0x0, 0x39, - 0xef, 0xff, 0xc8, 0x53, 0x22, 0x24, 0x8b, 0xef, - 0xc7, 0x20, 0x0, 0x0, 0x3, 0x9e, 0xfc, 0x61, - 0x0, 0x0, 0x0, 0x0, 0x5, 0xbf, 0xd8, 0x30, - 0x0, 0x0, 0x39, 0xee, 0x94, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x28, 0xdf, 0xa5, 0x0, 0x0, 0x3, - 0x9e, 0xfc, 0x61, 0x0, 0x0, 0x0, 0x0, 0x15, - 0xbf, 0xd8, 0x30, 0x0, 0x0, 0x39, 0xef, 0xff, - 0xc8, 0x53, 0x22, 0x24, 0x8b, 0xef, 0xc7, 0x20, - 0x0, 0x0, 0x3, 0x9e, 0xe9, 0x67, 0xad, 0xef, - 0xff, 0xec, 0xa7, 0x41, 0x0, 0x0, 0x0, - - /* U+0063 "c" */ - 0x0, 0x0, 0x24, 0x8b, 0xde, 0xff, 0xfe, 0xdb, - 0x84, 0x10, 0x0, 0x3, 0x9d, 0xfd, 0xa6, 0x32, - 0x22, 0x46, 0xac, 0xc7, 0x30, 0x5, 0xaf, 0xd8, - 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0x7c, 0xfb, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x5, 0xaf, 0xd8, 0x30, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x9d, 0xfd, - 0xa6, 0x32, 0x22, 0x46, 0xad, 0xd8, 0x30, 0x0, - 0x0, 0x24, 0x8b, 0xde, 0xff, 0xfe, 0xdb, 0x84, - 0x10, 0x0, - - /* U+0064 "d" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x16, 0xbf, 0xc6, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc6, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x16, 0xbf, 0xc6, 0x10, 0x0, 0x0, 0x25, 0x9b, - 0xde, 0xff, 0xfd, 0xc9, 0x68, 0xcf, 0xc6, 0x10, - 0x0, 0x4a, 0xef, 0xd9, 0x63, 0x22, 0x23, 0x6a, - 0xdf, 0xff, 0xc6, 0x10, 0x5, 0xbf, 0xd8, 0x30, - 0x0, 0x0, 0x0, 0x0, 0x49, 0xef, 0xc6, 0x10, - 0x27, 0xcf, 0xb5, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x16, 0xbf, 0xc6, 0x10, 0x5, 0xbf, 0xd8, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x38, 0xef, 0xc6, 0x10, - 0x0, 0x4a, 0xef, 0xd9, 0x52, 0x10, 0x12, 0x5a, - 0xdf, 0xff, 0xc6, 0x10, 0x0, 0x0, 0x25, 0x9b, - 0xde, 0xff, 0xfe, 0xc9, 0x68, 0xbf, 0xc6, 0x10, - - /* U+0065 "e" */ - 0x0, 0x0, 0x25, 0x9b, 0xde, 0xff, 0xed, 0xc9, - 0x52, 0x0, 0x0, 0x0, 0x0, 0x49, 0xee, 0xc8, - 0x42, 0x11, 0x24, 0x7b, 0xee, 0x94, 0x0, 0x0, - 0x5, 0xaf, 0xc7, 0x20, 0x0, 0x0, 0x0, 0x1, - 0x6c, 0xfb, 0x50, 0x0, 0x27, 0xcf, 0xff, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xfc, 0x72, 0x0, - 0x5, 0xaf, 0xd8, 0x20, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, 0xef, 0xd9, - 0x64, 0x22, 0x23, 0x47, 0xaa, 0x62, 0x0, 0x0, - 0x0, 0x0, 0x25, 0x8b, 0xde, 0xff, 0xfe, 0xdc, - 0x95, 0x20, 0x0, 0x0, - - /* U+0066 "f" */ - 0x0, 0x0, 0x0, 0x1, 0x59, 0xce, 0xff, 0xeb, - 0x62, 0x0, 0x0, 0x0, 0x49, 0xee, 0xa5, 0x11, - 0x22, 0x10, 0x0, 0x0, 0x0, 0x6b, 0xfb, 0x61, - 0x0, 0x0, 0x0, 0x0, 0x27, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xe9, 0x30, 0x0, 0x0, 0x1, 0x6b, - 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x6b, 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x6b, 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0x6b, 0xfb, 0x61, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0x6b, 0xfb, 0x61, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x6b, 0xfb, 0x61, 0x0, - 0x0, 0x0, - - /* U+0067 "g" */ - 0x0, 0x0, 0x25, 0x9b, 0xde, 0xff, 0xfe, 0xc9, - 0x67, 0xae, 0xd8, 0x20, 0x0, 0x49, 0xef, 0xda, - 0x64, 0x22, 0x23, 0x59, 0xcf, 0xff, 0xd8, 0x20, - 0x5, 0xaf, 0xd8, 0x30, 0x0, 0x0, 0x0, 0x0, - 0x27, 0xdf, 0xd8, 0x20, 0x27, 0xcf, 0xb5, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x5, 0xaf, 0xd8, 0x20, - 0x5, 0xaf, 0xd8, 0x30, 0x0, 0x0, 0x0, 0x0, - 0x28, 0xdf, 0xd8, 0x20, 0x0, 0x49, 0xef, 0xda, - 0x63, 0x22, 0x23, 0x6a, 0xdf, 0xff, 0xd8, 0x20, - 0x0, 0x0, 0x25, 0x9b, 0xde, 0xff, 0xfe, 0xc9, - 0x57, 0xaf, 0xc7, 0x20, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x27, 0xcf, 0xb5, 0x0, - 0x0, 0x38, 0xcc, 0x86, 0x43, 0x22, 0x23, 0x58, - 0xbe, 0xea, 0x50, 0x0, 0x0, 0x13, 0x69, 0xbd, - 0xef, 0xff, 0xfe, 0xdc, 0xa6, 0x31, 0x0, 0x0, - - /* U+0068 "h" */ - 0x0, 0x39, 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0xee, 0x94, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x39, 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0xee, 0xa7, - 0x6a, 0xde, 0xff, 0xee, 0xc9, 0x52, 0x0, 0x0, - 0x0, 0x39, 0xef, 0xfe, 0xb7, 0x43, 0x22, 0x46, - 0xae, 0xfc, 0x72, 0x0, 0x0, 0x39, 0xef, 0xb6, - 0x10, 0x0, 0x0, 0x0, 0x27, 0xcf, 0xb6, 0x0, - 0x0, 0x39, 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x5, 0xbf, 0xc7, 0x10, 0x0, 0x39, 0xee, 0x94, - 0x0, 0x0, 0x0, 0x0, 0x5, 0xbf, 0xc7, 0x20, - 0x0, 0x39, 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x5, 0xbf, 0xc7, 0x20, 0x0, 0x39, 0xee, 0x94, - 0x0, 0x0, 0x0, 0x0, 0x5, 0xbf, 0xc7, 0x20, - - /* U+0069 "i" */ - 0x0, 0x49, 0xdd, 0x94, 0x0, 0x2, 0x58, 0x85, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x9e, - 0xe9, 0x40, 0x0, 0x39, 0xee, 0x94, 0x0, 0x3, - 0x9e, 0xe9, 0x40, 0x0, 0x39, 0xee, 0x94, 0x0, - 0x3, 0x9e, 0xe9, 0x40, 0x0, 0x39, 0xee, 0x94, - 0x0, 0x3, 0x9e, 0xe9, 0x40, - - /* U+006A "j" */ - 0x0, 0x0, 0x0, 0x0, 0x38, 0xde, 0xa5, 0x10, - 0x0, 0x0, 0x0, 0x1, 0x47, 0x85, 0x20, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0x8d, 0xfa, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x28, 0xdf, 0xa4, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x8d, 0xfa, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x28, 0xdf, 0xa4, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x8d, 0xfa, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x28, 0xdf, 0xa4, 0x0, 0x0, 0x0, 0x0, 0x2, - 0x8d, 0xfa, 0x40, 0x0, 0x0, 0x0, 0x0, 0x28, - 0xdf, 0x94, 0x0, 0x0, 0x22, 0x21, 0x27, 0xbf, - 0xd7, 0x20, 0x0, 0x38, 0xdf, 0xff, 0xec, 0x84, - 0x10, 0x0, - - /* U+006B "k" */ - 0x0, 0x39, 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0xee, 0x94, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x39, 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0xee, 0x94, - 0x0, 0x0, 0x0, 0x27, 0xbe, 0xda, 0x51, 0x0, - 0x0, 0x39, 0xee, 0x94, 0x0, 0x2, 0x7b, 0xee, - 0xb6, 0x20, 0x0, 0x0, 0x0, 0x39, 0xee, 0x94, - 0x27, 0xbe, 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x39, 0xef, 0xee, 0xef, 0xff, 0xfd, 0x83, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0xef, 0xfc, - 0x73, 0x13, 0x8d, 0xfd, 0x94, 0x0, 0x0, 0x0, - 0x0, 0x39, 0xee, 0x94, 0x0, 0x0, 0x2, 0x7c, - 0xfe, 0xa4, 0x10, 0x0, 0x0, 0x39, 0xee, 0x94, - 0x0, 0x0, 0x0, 0x2, 0x6b, 0xfe, 0xa5, 0x10, - - /* U+006C "l" */ - 0x0, 0x39, 0xee, 0x94, 0x0, 0x3, 0x9e, 0xe9, - 0x40, 0x0, 0x39, 0xee, 0x94, 0x0, 0x3, 0x9e, - 0xe9, 0x40, 0x0, 0x39, 0xee, 0x94, 0x0, 0x3, - 0x9e, 0xe9, 0x40, 0x0, 0x39, 0xee, 0x94, 0x0, - 0x3, 0x9e, 0xe9, 0x40, 0x0, 0x39, 0xee, 0x94, - 0x0, 0x3, 0x9e, 0xe9, 0x40, - - /* U+006D "m" */ - 0x0, 0x39, 0xee, 0x97, 0x7b, 0xde, 0xff, 0xfd, - 0xb9, 0x42, 0x25, 0x9b, 0xde, 0xff, 0xed, 0xb8, - 0x41, 0x0, 0x0, 0x39, 0xef, 0xfd, 0xa6, 0x32, - 0x12, 0x47, 0xcf, 0xff, 0xfe, 0xb6, 0x32, 0x12, - 0x37, 0xbe, 0xfa, 0x51, 0x0, 0x39, 0xef, 0xb6, - 0x10, 0x0, 0x0, 0x0, 0x49, 0xff, 0xc6, 0x10, - 0x0, 0x0, 0x0, 0x49, 0xee, 0x94, 0x0, 0x39, - 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, 0x38, 0xef, - 0xa4, 0x0, 0x0, 0x0, 0x0, 0x28, 0xdf, 0xa5, - 0x0, 0x39, 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x38, 0xef, 0xa4, 0x0, 0x0, 0x0, 0x0, 0x28, - 0xdf, 0xa5, 0x0, 0x39, 0xee, 0x94, 0x0, 0x0, - 0x0, 0x0, 0x38, 0xef, 0xa4, 0x0, 0x0, 0x0, - 0x0, 0x28, 0xdf, 0xa5, 0x0, 0x39, 0xee, 0x94, - 0x0, 0x0, 0x0, 0x0, 0x38, 0xef, 0xa4, 0x0, - 0x0, 0x0, 0x0, 0x28, 0xdf, 0xa5, - - /* U+006E "n" */ - 0x0, 0x39, 0xee, 0x96, 0x7a, 0xde, 0xff, 0xee, - 0xc9, 0x52, 0x0, 0x0, 0x0, 0x39, 0xef, 0xfe, - 0xa6, 0x42, 0x11, 0x35, 0xad, 0xfc, 0x72, 0x0, - 0x0, 0x39, 0xef, 0xb6, 0x10, 0x0, 0x0, 0x0, - 0x17, 0xcf, 0xb6, 0x0, 0x0, 0x39, 0xee, 0x94, - 0x0, 0x0, 0x0, 0x0, 0x5, 0xbf, 0xc7, 0x10, - 0x0, 0x39, 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x5, 0xbf, 0xc7, 0x20, 0x0, 0x39, 0xee, 0x94, - 0x0, 0x0, 0x0, 0x0, 0x5, 0xbf, 0xc7, 0x20, - 0x0, 0x39, 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x5, 0xbf, 0xc7, 0x20, - - /* U+006F "o" */ - 0x0, 0x0, 0x25, 0x8b, 0xde, 0xff, 0xfe, 0xdb, - 0x84, 0x10, 0x0, 0x0, 0x0, 0x49, 0xef, 0xda, - 0x63, 0x22, 0x23, 0x6a, 0xef, 0xd8, 0x30, 0x0, - 0x5, 0xaf, 0xd8, 0x30, 0x0, 0x0, 0x0, 0x0, - 0x49, 0xef, 0xa4, 0x0, 0x27, 0xcf, 0xb5, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc6, 0x10, - 0x5, 0xaf, 0xd8, 0x30, 0x0, 0x0, 0x0, 0x0, - 0x49, 0xef, 0xa4, 0x0, 0x0, 0x49, 0xdf, 0xda, - 0x63, 0x21, 0x23, 0x6a, 0xef, 0xd8, 0x30, 0x0, - 0x0, 0x0, 0x25, 0x8b, 0xde, 0xff, 0xfe, 0xdb, - 0x84, 0x10, 0x0, 0x0, - - /* U+0070 "p" */ - 0x0, 0x39, 0xee, 0x97, 0x7b, 0xde, 0xff, 0xfe, - 0xca, 0x74, 0x10, 0x0, 0x0, 0x0, 0x3, 0x9e, - 0xff, 0xfc, 0x84, 0x21, 0x11, 0x36, 0xae, 0xfc, - 0x72, 0x0, 0x0, 0x0, 0x39, 0xef, 0xc6, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x5a, 0xfd, 0x83, 0x0, - 0x0, 0x3, 0x9e, 0xe9, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x8d, 0xfa, 0x50, 0x0, 0x0, 0x39, - 0xef, 0xc7, 0x10, 0x0, 0x0, 0x0, 0x1, 0x6b, - 0xfd, 0x83, 0x0, 0x0, 0x3, 0x9e, 0xff, 0xfc, - 0x95, 0x32, 0x22, 0x48, 0xcf, 0xfc, 0x72, 0x0, - 0x0, 0x0, 0x39, 0xee, 0x96, 0x6a, 0xce, 0xff, - 0xfe, 0xca, 0x74, 0x10, 0x0, 0x0, 0x0, 0x3, - 0x9e, 0xe9, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0xee, 0x94, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0x9e, 0xe9, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+0071 "q" */ - 0x0, 0x0, 0x25, 0x9b, 0xde, 0xff, 0xfd, 0xc9, - 0x57, 0xbf, 0xc6, 0x10, 0x0, 0x4a, 0xef, 0xda, - 0x63, 0x22, 0x23, 0x6b, 0xef, 0xff, 0xc6, 0x10, - 0x5, 0xbf, 0xd8, 0x30, 0x0, 0x0, 0x0, 0x0, - 0x49, 0xef, 0xc6, 0x10, 0x27, 0xcf, 0xb5, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc6, 0x10, - 0x5, 0xbf, 0xd8, 0x30, 0x0, 0x0, 0x0, 0x0, - 0x49, 0xef, 0xc6, 0x10, 0x0, 0x4a, 0xef, 0xda, - 0x63, 0x21, 0x23, 0x6a, 0xef, 0xff, 0xc6, 0x10, - 0x0, 0x0, 0x25, 0x9b, 0xde, 0xff, 0xfd, 0xb8, - 0x57, 0xbf, 0xc6, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc6, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x16, 0xbf, 0xc6, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc6, 0x10, - - /* U+0072 "r" */ - 0x0, 0x39, 0xee, 0x96, 0x7a, 0xde, 0xc8, 0x20, - 0x3, 0x9e, 0xff, 0xec, 0x86, 0x43, 0x10, 0x0, - 0x39, 0xef, 0xc7, 0x10, 0x0, 0x0, 0x0, 0x3, - 0x9e, 0xf9, 0x40, 0x0, 0x0, 0x0, 0x0, 0x39, - 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, 0x3, 0x9e, - 0xe9, 0x40, 0x0, 0x0, 0x0, 0x0, 0x39, 0xee, - 0x94, 0x0, 0x0, 0x0, 0x0, - - /* U+0073 "s" */ - 0x0, 0x0, 0x2, 0x59, 0xbd, 0xef, 0xff, 0xed, - 0xca, 0x62, 0x0, 0x0, 0x16, 0xbf, 0xd9, 0x52, - 0x11, 0x22, 0x46, 0x64, 0x10, 0x0, 0x1, 0x7c, - 0xfd, 0x95, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x26, 0x9c, 0xef, 0xff, 0xed, 0xc9, - 0x63, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x12, 0x48, 0xcf, 0xe9, 0x30, 0x0, 0x15, 0x89, - 0x64, 0x32, 0x11, 0x23, 0x7b, 0xfd, 0x83, 0x0, - 0x1, 0x48, 0xac, 0xde, 0xff, 0xfe, 0xec, 0xa7, - 0x30, 0x0, - - /* U+0074 "t" */ - 0x0, 0x0, 0x0, 0x35, 0x85, 0x30, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x6b, 0xfb, 0x61, 0x0, - 0x0, 0x0, 0x0, 0x27, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xe9, 0x30, 0x0, 0x0, 0x1, 0x6b, 0xfb, - 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6b, - 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x6b, 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x6b, 0xfb, 0x61, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x4a, 0xfe, 0xa5, 0x21, 0x22, 0x10, - 0x0, 0x0, 0x0, 0x2, 0x6a, 0xde, 0xff, 0xeb, - 0x62, - - /* U+0075 "u" */ - 0x0, 0x4a, 0xfd, 0x83, 0x0, 0x0, 0x0, 0x0, - 0x27, 0xcf, 0xb5, 0x0, 0x0, 0x4a, 0xfd, 0x83, - 0x0, 0x0, 0x0, 0x0, 0x27, 0xcf, 0xb5, 0x0, - 0x0, 0x4a, 0xfd, 0x83, 0x0, 0x0, 0x0, 0x0, - 0x27, 0xcf, 0xb5, 0x0, 0x0, 0x4a, 0xfd, 0x83, - 0x0, 0x0, 0x0, 0x0, 0x27, 0xcf, 0xb5, 0x0, - 0x0, 0x39, 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x49, 0xef, 0xb5, 0x0, 0x0, 0x5, 0xae, 0xeb, - 0x73, 0x21, 0x12, 0x59, 0xcf, 0xff, 0xb5, 0x0, - 0x0, 0x0, 0x14, 0x7b, 0xde, 0xff, 0xfe, 0xc8, - 0x68, 0xcf, 0xb5, 0x0, - - /* U+0076 "v" */ - 0x0, 0x28, 0xdf, 0xb5, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x49, 0xed, 0x83, 0x0, 0x0, 0x0, 0x16, - 0xcf, 0xc6, 0x10, 0x0, 0x0, 0x0, 0x5a, 0xfc, - 0x72, 0x0, 0x0, 0x0, 0x0, 0x15, 0xbf, 0xd7, - 0x20, 0x0, 0x1, 0x6b, 0xfb, 0x61, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x4, 0xae, 0xd8, 0x30, 0x2, - 0x7c, 0xfa, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0x9e, 0xe9, 0x43, 0x8d, 0xe9, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0x8d, 0xfd, 0xde, 0xd8, 0x30, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6c, 0xff, - 0xc7, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+0077 "w" */ - 0x0, 0x16, 0xcf, 0xa5, 0x0, 0x0, 0x0, 0x0, - 0x39, 0xef, 0xb6, 0x10, 0x0, 0x0, 0x0, 0x27, - 0xdd, 0x83, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xa5, - 0x0, 0x0, 0x0, 0x49, 0xef, 0xff, 0xb6, 0x10, - 0x0, 0x0, 0x27, 0xde, 0x83, 0x0, 0x0, 0x0, - 0x0, 0x16, 0xcf, 0xa5, 0x0, 0x0, 0x49, 0xec, - 0x77, 0xae, 0xb6, 0x10, 0x0, 0x27, 0xdd, 0x83, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xa5, - 0x0, 0x49, 0xec, 0x71, 0x4, 0xae, 0xc6, 0x10, - 0x28, 0xdd, 0x83, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x16, 0xbe, 0xa5, 0x59, 0xeb, 0x61, 0x0, - 0x4, 0xae, 0xb6, 0x48, 0xdd, 0x83, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xee, - 0xeb, 0x61, 0x0, 0x0, 0x4, 0x9e, 0xee, 0xed, - 0x82, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x16, 0xbf, 0xfb, 0x61, 0x0, 0x0, 0x0, - 0x4, 0x9e, 0xfd, 0x82, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+0078 "x" */ - 0x0, 0x1, 0x5b, 0xed, 0x94, 0x0, 0x0, 0x1, - 0x49, 0xee, 0xa4, 0x10, 0x0, 0x0, 0x1, 0x5a, - 0xee, 0x94, 0x11, 0x4a, 0xee, 0x94, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x4a, 0xee, 0xdd, 0xed, - 0x93, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x8d, 0xff, 0xc6, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0x6b, 0xed, 0xab, 0xde, - 0xa5, 0x10, 0x0, 0x0, 0x0, 0x0, 0x2, 0x7c, - 0xec, 0x72, 0x0, 0x38, 0xde, 0xb6, 0x10, 0x0, - 0x0, 0x2, 0x7c, 0xfc, 0x72, 0x0, 0x0, 0x0, - 0x38, 0xdf, 0xc6, 0x20, - - /* U+0079 "y" */ - 0x0, 0x28, 0xdf, 0xb5, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x49, 0xed, 0x83, 0x0, 0x0, 0x0, 0x27, - 0xcf, 0xb6, 0x10, 0x0, 0x0, 0x0, 0x4a, 0xec, - 0x72, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xc7, - 0x20, 0x0, 0x0, 0x5a, 0xfc, 0x61, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x5, 0xaf, 0xd7, 0x20, 0x1, - 0x6b, 0xfb, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x4, 0xae, 0xd8, 0x31, 0x6c, 0xea, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0x9e, 0xeb, 0xbd, 0xe9, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x8d, 0xff, - 0xe8, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x5, 0xaf, 0xd7, 0x20, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x53, 0x22, - 0x48, 0xcf, 0xb6, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x14, 0x9c, 0xef, 0xfe, 0xc9, 0x52, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+007A "z" */ - 0x27, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xb6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0x7c, 0xfd, 0x83, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x38, 0xcf, 0xc7, 0x30, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0x9d, 0xeb, 0x62, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x49, 0xee, 0xb5, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, 0xae, 0xea, - 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd7, - 0x20, 0x0, - - /* U+007B "{" */ - 0x0, 0x0, 0x2, 0x7b, 0xdf, 0xfa, 0x50, 0x0, - 0x0, 0x4, 0x9f, 0xea, 0x51, 0x0, 0x0, 0x0, - 0x0, 0x5a, 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, - 0x5, 0xbf, 0xc7, 0x20, 0x0, 0x0, 0x0, 0x0, - 0x5b, 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, 0x16, - 0xbf, 0xc7, 0x10, 0x0, 0x0, 0x4, 0x9f, 0xff, - 0xc6, 0x20, 0x0, 0x0, 0x0, 0x1, 0x38, 0xcf, - 0xc6, 0x10, 0x0, 0x0, 0x0, 0x0, 0x5b, 0xfc, - 0x72, 0x0, 0x0, 0x0, 0x0, 0x5, 0xbf, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x5a, 0xfc, 0x72, - 0x0, 0x0, 0x0, 0x0, 0x4, 0x9f, 0xea, 0x51, - 0x0, 0x0, 0x0, 0x0, 0x3, 0x7b, 0xdf, 0xfa, - 0x50, 0x0, - - /* U+007C "|" */ - 0x0, 0x16, 0xbf, 0xa5, 0x0, 0x1, 0x6b, 0xfa, - 0x50, 0x0, 0x16, 0xbf, 0xa5, 0x0, 0x1, 0x6b, - 0xfa, 0x50, 0x0, 0x16, 0xbf, 0xa5, 0x0, 0x1, - 0x6b, 0xfa, 0x50, 0x0, 0x16, 0xbf, 0xa5, 0x0, - 0x1, 0x6b, 0xfa, 0x50, 0x0, 0x16, 0xbf, 0xa5, - 0x0, 0x1, 0x6b, 0xfa, 0x50, 0x0, 0x16, 0xbf, - 0xa5, 0x0, 0x1, 0x6b, 0xfa, 0x50, 0x0, 0x16, - 0xbf, 0xa5, 0x0, - - /* U+007D "}" */ - 0x0, 0x17, 0xcf, 0xed, 0xa5, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x27, 0xcf, 0xd7, 0x20, 0x0, 0x0, - 0x0, 0x0, 0x49, 0xee, 0x93, 0x0, 0x0, 0x0, - 0x0, 0x4, 0x9e, 0xe9, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x49, 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x3, 0x8e, 0xfa, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x3, 0x8d, 0xff, 0xc7, 0x20, 0x0, 0x0, 0x3, - 0x8d, 0xfb, 0x62, 0x0, 0x0, 0x0, 0x0, 0x49, - 0xee, 0x94, 0x0, 0x0, 0x0, 0x0, 0x4, 0x9e, - 0xe9, 0x40, 0x0, 0x0, 0x0, 0x0, 0x49, 0xee, - 0x93, 0x0, 0x0, 0x0, 0x0, 0x27, 0xcf, 0xd8, - 0x20, 0x0, 0x0, 0x17, 0xcf, 0xed, 0xa5, 0x20, - 0x0, 0x0, - - /* U+007E "~" */ - 0x0, 0x26, 0xbd, 0xee, 0xdb, 0x84, 0x20, 0x5, - 0xac, 0x83, 0x0, 0x38, 0xc9, 0x51, 0x12, 0x58, - 0xbd, 0xdd, 0xca, 0x62, 0x0, - - /* U+00B0 "°" */ - 0x0, 0x3, 0x6a, 0xbb, 0xba, 0x73, 0x0, 0x0, - 0x38, 0xb8, 0x30, 0x0, 0x38, 0xb9, 0x40, 0x16, - 0xa9, 0x40, 0x0, 0x0, 0x39, 0xb7, 0x20, 0x38, - 0xb8, 0x30, 0x0, 0x38, 0xb9, 0x40, 0x0, 0x3, - 0x6a, 0xbb, 0xba, 0x73, 0x0, 0x0, - - /* U+2022 "•" */ - 0x0, 0x2, 0x45, 0x42, 0x0, 0x0, 0x2, 0x7c, - 0xff, 0xfe, 0x83, 0x0, 0x0, 0x49, 0xdf, 0xea, - 0x51, 0x0, - - /* U+F001 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x12, 0x32, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x13, 0x46, 0x79, 0xbc, 0xef, 0xff, 0xff, - 0xa4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x13, 0x56, 0x89, 0xbc, 0xef, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0x9e, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa5, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x5, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xed, 0xca, 0x87, 0x54, 0x23, 0x8d, 0xff, 0xa5, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0xaf, - 0xff, 0xda, 0x87, 0x53, 0x21, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x8d, 0xff, 0xa5, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x5, 0xaf, 0xfd, 0x82, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x8d, - 0xff, 0xa5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x5, 0xaf, 0xfd, 0x82, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0x8d, 0xff, 0xa5, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0xaf, 0xfd, - 0x82, 0x0, 0x0, 0x0, 0x0, 0x24, 0x79, 0xbb, - 0xbc, 0xdf, 0xff, 0xa5, 0x0, 0x0, 0x0, 0x0, - 0x12, 0x33, 0x37, 0xbf, 0xfd, 0x82, 0x0, 0x0, - 0x0, 0x16, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xa5, 0x0, 0x0, 0x15, 0xad, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x82, 0x0, 0x0, 0x0, 0x2, 0x6b, - 0xef, 0xff, 0xff, 0xff, 0xd9, 0x41, 0x0, 0x0, - 0x39, 0xef, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x61, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x22, 0x32, - 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x25, 0x89, - 0xab, 0xaa, 0x87, 0x41, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+F008 "" */ - 0x0, 0x39, 0xb9, 0x54, 0x59, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x95, 0x45, 0x9b, 0x93, 0x0, 0x0, 0x5a, 0xeb, - 0x88, 0x9b, 0xef, 0xb7, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x7c, 0xfe, 0xb8, 0x88, 0xbe, - 0xa5, 0x0, 0x0, 0x5a, 0xc7, 0x10, 0x17, 0xcf, - 0xb5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x6b, 0xfc, 0x61, 0x1, 0x7c, 0xa5, 0x0, 0x0, - 0x5a, 0xfd, 0xcc, 0xce, 0xff, 0xb6, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x12, 0x7c, 0xff, 0xdc, - 0xcc, 0xef, 0xa5, 0x0, 0x0, 0x5a, 0xc6, 0x10, - 0x17, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfb, 0x61, 0x1, 0x6c, 0xa5, - 0x0, 0x0, 0x5a, 0xfd, 0xcc, 0xce, 0xff, 0xb6, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x7c, - 0xff, 0xdc, 0xcc, 0xef, 0xa5, 0x0, 0x0, 0x5a, - 0xc7, 0x10, 0x17, 0xcf, 0xb5, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x6b, 0xfc, 0x61, 0x1, - 0x7c, 0xa5, 0x0, 0x0, 0x5a, 0xeb, 0x88, 0x9b, - 0xef, 0xb7, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x23, 0x7c, 0xfe, 0xb8, 0x88, 0xbe, 0xa5, 0x0, - 0x0, 0x49, 0xb9, 0x54, 0x59, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x95, 0x45, 0x9b, 0x93, 0x0, - - /* U+F00B "" */ - 0x0, 0x38, 0xdf, 0xff, 0xff, 0xfe, 0xb6, 0x25, - 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x83, 0x0, 0x0, 0x5a, 0xff, - 0xff, 0xff, 0xff, 0xd8, 0x46, 0xcf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xa5, 0x0, 0x0, 0x49, 0xef, 0xff, 0xff, 0xff, - 0xc6, 0x25, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x94, 0x0, 0x0, - 0x0, 0x12, 0x33, 0x33, 0x22, 0x10, 0x0, 0x1, - 0x23, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, - 0x33, 0x21, 0x0, 0x0, 0x0, 0x4a, 0xff, 0xff, - 0xff, 0xff, 0xc7, 0x26, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa4, - 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xd8, - 0x46, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, 0x0, 0x4a, - 0xff, 0xff, 0xff, 0xff, 0xc7, 0x26, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xa4, 0x0, 0x0, 0x0, 0x12, 0x33, 0x33, - 0x22, 0x10, 0x0, 0x1, 0x23, 0x33, 0x33, 0x33, - 0x33, 0x33, 0x33, 0x33, 0x33, 0x21, 0x0, 0x0, - 0x0, 0x49, 0xef, 0xff, 0xff, 0xff, 0xc6, 0x25, - 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0x94, 0x0, 0x0, 0x5a, 0xff, - 0xff, 0xff, 0xff, 0xd8, 0x46, 0xcf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xa5, 0x0, 0x0, 0x38, 0xdf, 0xff, 0xff, 0xfe, - 0xb6, 0x25, 0xae, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x83, 0x0, - - /* U+F00C "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0x7c, 0xdc, 0x94, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x38, 0xcf, 0xff, 0xff, 0xfe, - 0x93, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x8c, - 0xff, 0xff, 0xff, 0xfd, 0x84, 0x10, 0x0, 0x0, - 0x1, 0x49, 0xcd, 0xc7, 0x30, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x38, 0xcf, 0xff, 0xff, 0xff, 0xd8, - 0x41, 0x0, 0x0, 0x0, 0x0, 0x39, 0xef, 0xff, - 0xff, 0xfc, 0x83, 0x0, 0x0, 0x3, 0x8c, 0xff, - 0xff, 0xff, 0xfd, 0x84, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0x48, 0xdf, 0xff, 0xff, 0xff, - 0xc8, 0x68, 0xcf, 0xff, 0xff, 0xff, 0xd8, 0x41, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x14, 0x8c, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfc, 0x84, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x48, 0xcf, 0xff, 0xff, 0xff, 0xc8, 0x41, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x13, 0x8c, - 0xdc, 0x83, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F00D "" */ - 0x0, 0x0, 0x13, 0x44, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0x24, 0x42, 0x10, 0x0, 0x0, - 0x27, 0xdf, 0xff, 0xfc, 0x73, 0x0, 0x0, 0x0, - 0x14, 0x8d, 0xff, 0xff, 0xb6, 0x10, 0x0, 0x14, - 0x9d, 0xff, 0xff, 0xff, 0xc7, 0x32, 0x48, 0xdf, - 0xff, 0xff, 0xfd, 0x83, 0x0, 0x0, 0x0, 0x1, - 0x5a, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xd9, 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x16, 0xbf, 0xff, 0xff, 0xff, 0xfe, 0xa5, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x8d, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x73, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x48, 0xdf, 0xff, 0xff, - 0xfd, 0x98, 0xad, 0xff, 0xff, 0xff, 0xc7, 0x30, - 0x0, 0x0, 0x39, 0xef, 0xff, 0xff, 0xd9, 0x41, - 0x0, 0x1, 0x5a, 0xdf, 0xff, 0xff, 0xd7, 0x20, - 0x0, 0x2, 0x59, 0xbb, 0x84, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x15, 0x9b, 0xb9, 0x51, 0x0, - - /* U+F011 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x47, 0x99, 0x74, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0x36, 0x52, 0x0, 0x4, 0x9f, 0xff, - 0xf9, 0x40, 0x0, 0x25, 0x64, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, 0x9d, 0xff, - 0xfc, 0x71, 0x4, 0x9f, 0xff, 0xf9, 0x40, 0x17, - 0xcf, 0xff, 0xea, 0x51, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x15, 0xaf, 0xff, 0xfd, 0x94, 0x10, 0x4, - 0x9f, 0xff, 0xf9, 0x40, 0x1, 0x59, 0xdf, 0xff, - 0xfb, 0x51, 0x0, 0x0, 0x0, 0x2, 0x7d, 0xff, - 0xfd, 0x83, 0x0, 0x0, 0x4, 0x9f, 0xff, 0xf9, - 0x40, 0x0, 0x0, 0x38, 0xdf, 0xff, 0xc7, 0x20, - 0x0, 0x0, 0x16, 0xbf, 0xff, 0xd8, 0x20, 0x0, - 0x0, 0x4, 0x9f, 0xff, 0xf9, 0x40, 0x0, 0x0, - 0x2, 0x8d, 0xff, 0xfb, 0x60, 0x0, 0x0, 0x17, - 0xcf, 0xff, 0xc6, 0x10, 0x0, 0x0, 0x3, 0x9e, - 0xff, 0xe9, 0x30, 0x0, 0x0, 0x1, 0x6c, 0xff, - 0xfc, 0x71, 0x0, 0x0, 0x5, 0xaf, 0xff, 0xe9, - 0x40, 0x0, 0x0, 0x0, 0x1, 0x11, 0x10, 0x0, - 0x0, 0x0, 0x4, 0x9e, 0xff, 0xfa, 0x50, 0x0, - 0x0, 0x1, 0x5a, 0xff, 0xff, 0xb6, 0x10, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6b, - 0xff, 0xff, 0xb6, 0x10, 0x0, 0x0, 0x0, 0x3, - 0x8d, 0xff, 0xff, 0xda, 0x63, 0x10, 0x0, 0x0, - 0x0, 0x1, 0x36, 0xad, 0xff, 0xff, 0xd8, 0x30, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x5a, 0xdf, - 0xff, 0xff, 0xfe, 0xdc, 0xcc, 0xcd, 0xef, 0xff, - 0xff, 0xfd, 0xa5, 0x20, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0x68, 0xad, 0xef, - 0xff, 0xff, 0xff, 0xfe, 0xdb, 0x96, 0x31, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x11, 0x11, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+F013 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x23, - 0x44, 0x44, 0x32, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x27, 0xdf, 0xff, 0xff, 0xfd, 0x72, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x35, 0x64, - 0x11, 0x36, 0xad, 0xff, 0xff, 0xff, 0xff, 0xda, - 0x63, 0x11, 0x46, 0x53, 0x0, 0x0, 0x0, 0x49, - 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x94, 0x0, - 0x16, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xba, 0xab, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0x61, 0x1, 0x37, 0xbe, 0xff, 0xff, 0xff, - 0xc7, 0x20, 0x0, 0x0, 0x2, 0x7c, 0xff, 0xff, - 0xff, 0xeb, 0x73, 0x10, 0x0, 0x2, 0x7c, 0xff, - 0xff, 0xfd, 0x82, 0x0, 0x0, 0x0, 0x0, 0x28, - 0xdf, 0xff, 0xff, 0xd7, 0x20, 0x0, 0x1, 0x37, - 0xbe, 0xff, 0xff, 0xff, 0xc7, 0x20, 0x0, 0x0, - 0x2, 0x7c, 0xff, 0xff, 0xff, 0xeb, 0x73, 0x10, - 0x16, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xba, 0xab, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0x61, 0x0, 0x49, 0xef, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x94, 0x0, 0x0, 0x0, 0x35, 0x64, - 0x11, 0x25, 0x9c, 0xff, 0xff, 0xff, 0xff, 0xc9, - 0x52, 0x11, 0x36, 0x53, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x27, 0xdf, 0xff, 0xff, - 0xfd, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x23, - 0x44, 0x44, 0x32, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+F015 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x25, 0x77, 0x63, 0x10, 0x0, 0x3, - 0x68, 0x88, 0x63, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x59, - 0xdf, 0xff, 0xff, 0xfe, 0xb6, 0x32, 0x7c, 0xff, - 0xfc, 0x71, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x13, 0x7c, 0xef, 0xfe, 0xc8, - 0x54, 0x6a, 0xdf, 0xff, 0xee, 0xef, 0xff, 0xc7, - 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x26, 0xad, 0xff, 0xfd, 0xa5, 0x34, 0x8b, 0xc9, - 0x53, 0x47, 0xbe, 0xff, 0xff, 0xfc, 0x71, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x59, 0xcf, 0xff, - 0xeb, 0x74, 0x36, 0xad, 0xff, 0xff, 0xff, 0xec, - 0x84, 0x35, 0x9d, 0xff, 0xfe, 0xb6, 0x30, 0x0, - 0x0, 0x2, 0x6b, 0xef, 0xff, 0xc9, 0x53, 0x59, - 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xb7, 0x33, 0x6b, 0xef, 0xff, 0xd8, 0x40, 0x0, - 0x3, 0x7a, 0x96, 0x33, 0x6b, 0xef, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xd9, 0x42, 0x48, 0xa9, 0x51, 0x0, 0x0, 0x0, - 0x0, 0x1, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe9, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x16, 0xcf, 0xff, 0xff, 0xff, 0xfa, 0x50, 0x0, - 0x2, 0x7d, 0xff, 0xff, 0xff, 0xfe, 0x94, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6c, - 0xff, 0xff, 0xff, 0xff, 0xa4, 0x0, 0x0, 0x27, - 0xcf, 0xff, 0xff, 0xff, 0xe9, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0xae, 0xff, - 0xff, 0xff, 0xd8, 0x30, 0x0, 0x1, 0x6b, 0xff, - 0xff, 0xff, 0xfd, 0x83, 0x0, 0x0, 0x0, 0x0, - - /* U+F019 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x24, 0x67, 0x77, 0x76, 0x42, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0x7d, 0xff, 0xff, - 0xff, 0xd7, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x8d, 0xff, 0xff, 0xff, 0xd8, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x8d, - 0xff, 0xff, 0xff, 0xd8, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0x8d, 0xff, 0xff, 0xff, - 0xd8, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0x83, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0x49, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x94, 0x10, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x14, 0x9d, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xd9, 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0x23, 0x33, 0x33, 0x33, 0x33, 0x22, - 0x59, 0xdf, 0xff, 0xfd, 0x95, 0x22, 0x33, 0x33, - 0x33, 0x33, 0x32, 0x10, 0x0, 0x0, 0x4a, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0xa5, 0x34, 0x77, - 0x43, 0x5a, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xa4, 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xec, 0xaa, 0xce, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, 0x0, - 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xe9, 0x56, 0xbc, 0x75, - 0x8d, 0xff, 0xa5, 0x0, 0x0, 0x25, 0x9a, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa8, 0x52, - 0x0, - - /* U+F01C "" */ - 0x0, 0x0, 0x0, 0x0, 0x1, 0x49, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xb7, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x15, 0xae, 0xff, 0xda, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x9b, 0xef, - 0xfc, 0x83, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x5a, 0xef, 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0xae, 0xff, - 0xd7, 0x30, 0x0, 0x0, 0x0, 0x15, 0xae, 0xff, - 0xc7, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x4a, 0xef, 0xfc, - 0x82, 0x0, 0x0, 0x38, 0xef, 0xff, 0xda, 0x88, - 0x88, 0x88, 0x63, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x25, 0x78, 0x88, 0x88, 0x9b, 0xef, 0xff, 0xb6, - 0x10, 0x5, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xd8, 0x30, 0x0, 0x0, 0x1, 0x5b, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x82, 0x0, - 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xd8, 0x20, 0x5, 0xaf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x72, 0x0, 0x26, 0xbe, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0x84, 0x0, - - /* U+F021 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x11, 0x11, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x58, 0x99, 0x62, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x13, 0x69, 0xbd, 0xef, 0xff, 0xff, - 0xff, 0xfd, 0xb9, 0x74, 0x20, 0x4, 0x9f, 0xff, - 0xa5, 0x0, 0x0, 0x0, 0x0, 0x3, 0x7b, 0xef, - 0xff, 0xff, 0xdc, 0xaa, 0x99, 0x9a, 0xcd, 0xff, - 0xff, 0xfd, 0xaa, 0xbf, 0xff, 0xa5, 0x0, 0x0, - 0x0, 0x4, 0x9e, 0xff, 0xfe, 0xa6, 0x31, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0x59, 0xcf, 0xff, - 0xff, 0xff, 0xa5, 0x0, 0x0, 0x2, 0x7c, 0xff, - 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, - 0xef, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xa5, - 0x0, 0x0, 0x3, 0x6a, 0xa9, 0x73, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x25, 0x9a, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xa9, 0x63, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x36, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xa9, 0x52, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x37, 0xaa, 0xa6, 0x30, 0x0, - 0x0, 0x5a, 0xff, 0xff, 0xff, 0xfe, 0xee, 0xff, - 0xfe, 0x83, 0x0, 0x0, 0x0, 0x0, 0x0, 0x27, - 0xcf, 0xff, 0xc7, 0x20, 0x0, 0x0, 0x5a, 0xff, - 0xff, 0xff, 0xfc, 0x95, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x13, 0x7b, 0xef, 0xff, 0xe9, 0x40, - 0x0, 0x0, 0x0, 0x5a, 0xff, 0xfb, 0xaa, 0xdf, - 0xff, 0xff, 0xdb, 0xa9, 0x99, 0xaa, 0xcd, 0xff, - 0xff, 0xfe, 0xb7, 0x30, 0x0, 0x0, 0x0, 0x0, - 0x5a, 0xff, 0xfa, 0x40, 0x2, 0x47, 0x9c, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xdb, 0x96, 0x31, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x26, 0x99, 0x85, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x1, 0x11, 0x11, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+F026 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x26, 0xaa, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0x6b, 0xef, 0xff, 0xa5, 0x0, - 0x0, 0x14, 0x78, 0x88, 0x88, 0x89, 0xce, 0xff, - 0xff, 0xff, 0xa5, 0x0, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, - 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa5, 0x0, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, - 0x0, 0x38, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa5, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x37, 0xcf, 0xff, 0xff, 0xa5, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0x7c, 0xff, 0xa4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x10, 0x0, - - /* U+F027 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x26, 0xaa, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26, - 0xbe, 0xff, 0xfa, 0x50, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x14, 0x78, 0x88, 0x88, 0x89, 0xce, - 0xff, 0xff, 0xff, 0xa5, 0x0, 0x13, 0x31, 0x0, - 0x0, 0x0, 0x5, 0xaf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfa, 0x50, 0x16, 0xbe, 0xea, - 0x51, 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, 0x3, 0x8d, - 0xfa, 0x40, 0x0, 0x5, 0xaf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfa, 0x50, 0x15, 0xae, - 0xea, 0x51, 0x0, 0x0, 0x38, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, 0x24, - 0x42, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0x8c, 0xff, 0xff, 0xfa, 0x50, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0x8c, 0xff, 0xa4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x11, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F028 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6b, 0xfd, - 0xa5, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x26, 0xaa, 0x72, - 0x0, 0x0, 0x0, 0x12, 0x11, 0x14, 0x8c, 0xfe, - 0x94, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x26, 0xbe, 0xff, 0xfa, 0x50, 0x0, - 0x0, 0x27, 0xcf, 0xda, 0x52, 0x16, 0xbe, 0xe9, - 0x40, 0x0, 0x0, 0x14, 0x78, 0x88, 0x88, 0x89, - 0xce, 0xff, 0xff, 0xff, 0xa5, 0x0, 0x23, 0x32, - 0x1, 0x4a, 0xdf, 0xb6, 0x13, 0x8d, 0xfa, 0x50, - 0x0, 0x5, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfa, 0x50, 0x15, 0xbe, 0xea, 0x51, - 0x16, 0xbf, 0xc6, 0x13, 0x9e, 0xe9, 0x30, 0x0, - 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xa5, 0x0, 0x3, 0x8d, 0xfa, 0x40, 0x39, - 0xee, 0x83, 0x17, 0xcf, 0xa5, 0x0, 0x5, 0xaf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, - 0x50, 0x15, 0xbe, 0xea, 0x51, 0x16, 0xcf, 0xc6, - 0x13, 0x8e, 0xe9, 0x30, 0x0, 0x38, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, - 0x23, 0x31, 0x1, 0x5a, 0xef, 0xb6, 0x13, 0x8d, - 0xfa, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0x7c, 0xff, 0xff, 0xfa, 0x50, 0x0, 0x0, - 0x27, 0xcf, 0xda, 0x52, 0x16, 0xbf, 0xe9, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0x7c, 0xff, 0xa4, 0x0, 0x0, 0x0, 0x12, - 0x11, 0x15, 0x9d, 0xfe, 0x94, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x11, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6b, - 0xfd, 0xa5, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F03E "" */ - 0x0, 0x26, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xeb, 0x62, 0x0, 0x0, 0x5a, 0xff, - 0xfd, 0xa7, 0x56, 0x7b, 0xef, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xa5, 0x0, 0x0, 0x5a, 0xff, 0xb5, 0x0, 0x0, - 0x1, 0x7c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xee, - 0xef, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, 0x0, - 0x5a, 0xff, 0xeb, 0x63, 0x12, 0x38, 0xcf, 0xff, - 0xff, 0xff, 0xfe, 0xa6, 0x20, 0x13, 0x8c, 0xff, - 0xff, 0xff, 0xa5, 0x0, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xfe, 0xcc, 0xdf, 0xff, 0xff, 0xea, 0x62, - 0x0, 0x0, 0x0, 0x1, 0x38, 0xdf, 0xff, 0xa5, - 0x0, 0x0, 0x5a, 0xff, 0xff, 0xea, 0x62, 0x0, - 0x15, 0x9b, 0xa6, 0x20, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x8d, 0xff, 0xa5, 0x0, 0x0, 0x5a, - 0xff, 0xe9, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x8d, - 0xff, 0xa5, 0x0, 0x0, 0x5a, 0xff, 0xec, 0x98, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x89, 0xce, 0xff, 0xa5, 0x0, - 0x0, 0x26, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xeb, 0x62, 0x0, - - /* U+F043 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x56, - 0x42, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x6c, 0xff, 0xfb, - 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x38, 0xdf, 0xff, 0xff, 0xc7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x5, 0xae, 0xff, 0xff, 0xff, 0xfe, 0x93, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, - 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x83, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x9e, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x83, - 0x0, 0x0, 0x0, 0x3, 0x8d, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x72, - 0x0, 0x0, 0x38, 0xef, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x20, - 0x0, 0x4a, 0xff, 0xe9, 0x56, 0xcf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x30, 0x0, - 0x27, 0xdf, 0xfc, 0x73, 0x5a, 0xef, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xb6, 0x10, 0x0, 0x1, - 0x6b, 0xff, 0xfd, 0xa6, 0x43, 0x47, 0xbe, 0xff, - 0xff, 0xff, 0xea, 0x40, 0x0, 0x0, 0x0, 0x1, - 0x48, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xb7, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x24, 0x56, 0x77, 0x76, 0x54, 0x20, 0x0, - 0x0, 0x0, 0x0, - - /* U+F048 "" */ - 0x25, 0x78, 0x86, 0x30, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x13, 0x67, 0x52, 0x0, 0x4, 0x9f, 0xff, - 0xc6, 0x10, 0x0, 0x0, 0x0, 0x15, 0x9d, 0xff, - 0xfe, 0x83, 0x0, 0x49, 0xff, 0xfc, 0x61, 0x0, - 0x0, 0x26, 0xae, 0xff, 0xff, 0xff, 0xe9, 0x30, - 0x4, 0x9f, 0xff, 0xc6, 0x10, 0x37, 0xbe, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x93, 0x0, 0x49, 0xff, - 0xfd, 0xa9, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe9, 0x30, 0x4, 0x9f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x93, - 0x0, 0x49, 0xff, 0xfe, 0xee, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xe9, 0x30, 0x4, 0x9f, - 0xff, 0xc6, 0x24, 0x9d, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x93, 0x0, 0x49, 0xff, 0xfc, 0x61, - 0x0, 0x3, 0x7c, 0xef, 0xff, 0xff, 0xff, 0xe9, - 0x30, 0x4, 0x9f, 0xff, 0xc6, 0x10, 0x0, 0x0, - 0x2, 0x6b, 0xef, 0xff, 0xfe, 0x93, 0x0, 0x38, - 0xdf, 0xfb, 0x50, 0x0, 0x0, 0x0, 0x0, 0x2, - 0x59, 0xde, 0xb6, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+F04B "" */ - 0x0, 0x1, 0x46, 0x76, 0x31, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x49, 0xff, 0xff, 0xff, 0xda, - 0x74, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0xa7, 0x41, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xdb, 0x74, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0xb8, 0x52, 0x0, - 0x0, 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xeb, 0x84, 0x10, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x61, 0x0, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x73, 0x10, - 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0xb8, 0x42, 0x0, - 0x0, 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xdb, 0x74, 0x20, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0xa7, 0x41, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, - 0xff, 0xff, 0xff, 0xda, 0x74, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0x36, 0x76, 0x31, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+F04C "" */ - 0x0, 0x15, 0xad, 0xef, 0xff, 0xff, 0xfe, 0xc8, - 0x30, 0x0, 0x15, 0xad, 0xef, 0xff, 0xff, 0xfe, - 0xc8, 0x30, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x72, 0x0, 0x5a, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x72, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0x82, 0x0, 0x5a, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x82, 0x0, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x82, 0x0, - 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x82, - 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x82, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0x82, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x82, 0x0, 0x5a, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x82, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0x82, 0x0, 0x5a, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x82, 0x0, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x82, 0x0, - 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x82, - 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x82, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0x82, 0x0, 0x4a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfc, 0x72, 0x0, 0x4a, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x72, 0x0, 0x2, 0x47, 0x88, - 0x99, 0x99, 0x88, 0x63, 0x10, 0x0, 0x2, 0x47, - 0x88, 0x99, 0x99, 0x88, 0x63, 0x10, - - /* U+F04D "" */ - 0x0, 0x2, 0x47, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x63, 0x10, 0x0, 0x4a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x72, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x82, 0x0, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x82, - 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0x82, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x82, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x82, 0x0, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x82, - 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0x82, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x72, 0x0, 0x15, 0xad, 0xef, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0xc8, 0x30, - - /* U+F051 "" */ - 0x2, 0x57, 0x64, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x25, 0x88, 0x85, 0x20, 0x2, 0x7d, 0xff, - 0xfd, 0xa5, 0x20, 0x0, 0x0, 0x0, 0x5, 0xbf, - 0xff, 0xa5, 0x0, 0x28, 0xdf, 0xff, 0xff, 0xfe, - 0xb7, 0x30, 0x0, 0x0, 0x5b, 0xff, 0xfa, 0x50, - 0x2, 0x8d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc8, - 0x31, 0x5, 0xbf, 0xff, 0xa5, 0x0, 0x28, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xda, 0xac, - 0xff, 0xfa, 0x50, 0x2, 0x8d, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, - 0x0, 0x28, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0xee, 0xff, 0xfa, 0x50, 0x2, 0x8d, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x94, 0x25, - 0xbf, 0xff, 0xa5, 0x0, 0x28, 0xdf, 0xff, 0xff, - 0xff, 0xfc, 0x84, 0x10, 0x0, 0x5b, 0xff, 0xfa, - 0x50, 0x2, 0x8d, 0xff, 0xff, 0xeb, 0x73, 0x0, - 0x0, 0x0, 0x5, 0xbf, 0xff, 0xa5, 0x0, 0x15, - 0xae, 0xda, 0x62, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x5a, 0xef, 0xe9, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+F052 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x36, 0x77, 0x52, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x38, 0xcf, 0xff, 0xff, 0xea, 0x51, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x26, 0xbe, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xd9, 0x41, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, 0xae, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xc8, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x14, 0x9d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0xb7, 0x20, 0x0, - 0x0, 0x0, 0x2, 0x6c, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x94, 0x0, 0x0, 0x0, 0x27, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x50, 0x0, - 0x0, 0x0, 0x1, 0x23, 0x34, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x43, - 0x31, 0x0, 0x0, 0x0, 0x0, 0x38, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0x51, 0x0, 0x0, - 0x5, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xd8, 0x20, 0x0, 0x0, 0x27, 0xce, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xea, 0x51, 0x0, 0x0, - - /* U+F053 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x34, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x25, 0xae, 0xff, 0xfb, 0x61, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0x5a, 0xef, 0xff, - 0xfd, 0x94, 0x10, 0x0, 0x0, 0x0, 0x0, 0x25, - 0xae, 0xff, 0xff, 0xd9, 0x41, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x5a, 0xef, 0xff, 0xfd, 0x94, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x3, 0x8d, 0xff, 0xff, - 0xeb, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x27, 0xbe, 0xff, 0xff, 0xc8, 0x30, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x7b, - 0xef, 0xff, 0xfc, 0x83, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x37, 0xce, 0xff, 0xff, - 0xc8, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0x7c, 0xef, 0xff, 0xfa, 0x51, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x37, - 0xab, 0x95, 0x10, 0x0, - - /* U+F054 "" */ - 0x0, 0x2, 0x34, 0x20, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0x8e, 0xff, 0xfc, - 0x83, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x27, 0xbe, 0xff, 0xff, 0xc8, 0x31, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x7b, - 0xef, 0xff, 0xfc, 0x83, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x27, 0xbe, 0xff, 0xff, - 0xc8, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0x8d, 0xff, 0xff, 0xfb, 0x61, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0x5a, 0xef, 0xff, - 0xfd, 0x95, 0x10, 0x0, 0x0, 0x0, 0x0, 0x25, - 0xae, 0xff, 0xff, 0xd9, 0x51, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x5a, 0xef, 0xff, 0xfd, 0x95, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x3, 0x8d, 0xff, 0xff, - 0xd9, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x37, 0xab, 0x85, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+F067 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0x69, 0xa9, 0x84, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x38, 0xdf, 0xff, 0xfb, 0x50, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x38, 0xef, 0xff, 0xfb, 0x60, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xef, 0xff, - 0xfb, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0x57, 0x88, 0x88, 0x88, 0x88, 0x9c, - 0xff, 0xff, 0xfd, 0xb8, 0x88, 0x88, 0x88, 0x88, - 0x74, 0x10, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x72, 0x0, 0x15, 0x9b, 0xbb, - 0xbb, 0xbb, 0xbb, 0xce, 0xff, 0xff, 0xfe, 0xdb, - 0xbb, 0xbb, 0xbb, 0xbb, 0xa7, 0x30, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0xef, 0xff, - 0xfb, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, - 0xef, 0xff, 0xfb, 0x60, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x38, 0xef, 0xff, 0xfb, 0x60, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x15, 0x9c, 0xdd, 0xb7, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F068 "" */ - 0x0, 0x2, 0x45, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x53, 0x10, 0x0, 0x4a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x72, 0x0, 0x26, 0xac, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xc8, 0x40, - - /* U+F06E "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x13, 0x58, - 0xab, 0xcd, 0xef, 0xff, 0xff, 0xed, 0xca, 0x97, - 0x42, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0x49, 0xcf, 0xff, 0xfe, 0xc9, - 0x64, 0x32, 0x23, 0x45, 0x7a, 0xdf, 0xff, 0xfe, - 0xb7, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0x6b, 0xef, 0xff, 0xff, 0xc6, 0x20, 0x0, 0x3, - 0x79, 0x87, 0x52, 0x0, 0x49, 0xdf, 0xff, 0xff, - 0xd9, 0x41, 0x0, 0x0, 0x0, 0x27, 0xcf, 0xff, - 0xff, 0xfe, 0x93, 0x0, 0x0, 0x2, 0x7c, 0xff, - 0xff, 0xea, 0x51, 0x16, 0xbf, 0xff, 0xff, 0xfe, - 0xa5, 0x10, 0x0, 0x49, 0xef, 0xff, 0xff, 0xff, - 0xc6, 0x12, 0x7c, 0xef, 0xff, 0xff, 0xff, 0xff, - 0xf9, 0x40, 0x49, 0xef, 0xff, 0xff, 0xff, 0xc7, - 0x10, 0x0, 0x38, 0xdf, 0xff, 0xff, 0xfe, 0x93, - 0x3, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x61, - 0x16, 0xbf, 0xff, 0xff, 0xfe, 0xa4, 0x10, 0x0, - 0x0, 0x2, 0x6b, 0xef, 0xff, 0xff, 0xc6, 0x20, - 0x26, 0x9b, 0xcc, 0xca, 0x84, 0x11, 0x49, 0xdf, - 0xff, 0xff, 0xd8, 0x41, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x59, 0xcf, 0xff, 0xfe, 0xc9, 0x64, - 0x32, 0x23, 0x45, 0x7a, 0xdf, 0xff, 0xfe, 0xb7, - 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x13, 0x57, 0x9b, 0xcd, 0xef, 0xff, - 0xff, 0xed, 0xca, 0x97, 0x42, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - - /* U+F070 "" */ - 0x0, 0x1, 0x35, 0x42, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0x8d, 0xff, 0xfd, 0x95, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x8c, 0xef, - 0xff, 0xc8, 0x53, 0x46, 0x8a, 0xbd, 0xee, 0xff, - 0xff, 0xed, 0xcb, 0x97, 0x53, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x59, 0xcf, 0xff, 0xff, 0xff, 0xda, 0x75, - 0x43, 0x23, 0x45, 0x79, 0xdf, 0xff, 0xfe, 0xc8, - 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x25, 0x9d, 0xff, 0xfe, - 0xb7, 0x44, 0x7a, 0xa9, 0x74, 0x10, 0x28, 0xcf, - 0xff, 0xff, 0xea, 0x51, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x16, 0xbd, 0xc8, 0x41, 0x0, 0x2, - 0x6a, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x72, - 0x4, 0xaf, 0xff, 0xff, 0xff, 0xb6, 0x20, 0x0, - 0x0, 0x0, 0x0, 0x27, 0xdf, 0xff, 0xff, 0xeb, - 0x73, 0x0, 0x0, 0x26, 0xad, 0xff, 0xff, 0xff, - 0xfb, 0x60, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xe8, - 0x30, 0x0, 0x0, 0x0, 0x0, 0x15, 0xbe, 0xff, - 0xff, 0xff, 0xa5, 0x0, 0x0, 0x0, 0x3, 0x7b, - 0xef, 0xff, 0xeb, 0x67, 0xaf, 0xff, 0xff, 0xff, - 0xb6, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x49, 0xdf, 0xff, 0xff, 0xc8, 0x30, 0x0, 0x0, - 0x0, 0x1, 0x37, 0xbe, 0xff, 0xff, 0xff, 0xff, - 0xea, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0x37, 0xbe, 0xff, 0xff, 0xc9, - 0x64, 0x32, 0x22, 0x10, 0x0, 0x14, 0x8b, 0xef, - 0xff, 0xea, 0x52, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x57, - 0x9b, 0xcd, 0xef, 0xff, 0xfe, 0xb7, 0x30, 0x0, - 0x1, 0x48, 0xce, 0xff, 0xfc, 0x94, 0x10, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x14, 0x8c, 0xff, 0xfe, - 0x83, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0x45, 0x41, 0x0, 0x0, - - /* U+F071 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0x33, 0x21, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x5a, 0xef, 0xff, 0xd8, 0x30, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xae, 0xff, - 0xff, 0xff, 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x38, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xb5, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x7c, 0xff, 0xff, 0xee, 0xdd, 0xde, 0xff, - 0xff, 0xea, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, - 0xff, 0xff, 0xd7, 0x20, 0x0, 0x5a, 0xff, 0xff, - 0xfd, 0x83, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x4a, 0xef, 0xff, 0xff, - 0xfd, 0x72, 0x0, 0x5, 0xaf, 0xff, 0xff, 0xff, - 0xc7, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x3, 0x9d, 0xff, 0xff, 0xff, 0xff, 0xd7, - 0x20, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xfb, - 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x27, - 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xda, 0x87, - 0x8b, 0xef, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xa4, - 0x10, 0x0, 0x0, 0x0, 0x1, 0x6b, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xc7, 0x20, 0x0, 0x4a, - 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd9, 0x30, - 0x0, 0x0, 0x15, 0xae, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x95, 0x21, 0x37, 0xcf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x72, 0x0, - 0x4, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x61, 0x0, 0x1, - 0x46, 0x77, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x87, 0x75, 0x20, 0x0, - - /* U+F074 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x46, - 0x63, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x5, 0xaf, 0xff, 0xc8, 0x31, - 0x0, 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xc8, 0x30, 0x0, 0x0, 0x0, 0x26, 0xbe, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x72, 0x0, 0x0, - 0x48, 0xcd, 0xdd, 0xde, 0xff, 0xff, 0xeb, 0x62, - 0x2, 0x6b, 0xef, 0xff, 0xfe, 0xde, 0xff, 0xff, - 0xff, 0xd9, 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x26, 0xac, 0xa6, 0x46, 0xbe, 0xff, 0xff, - 0xd9, 0x41, 0x5, 0xaf, 0xfd, 0x95, 0x10, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0x6b, 0xef, 0xff, 0xfd, 0x94, 0x10, 0x0, 0x1, - 0x47, 0x62, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x26, 0xbe, 0xff, 0xff, 0xd8, - 0x55, 0x8b, 0xc8, 0x41, 0x5, 0xaf, 0xfd, 0xa5, - 0x10, 0x0, 0x0, 0x0, 0x48, 0xcd, 0xdd, 0xde, - 0xff, 0xff, 0xfc, 0x84, 0x10, 0x49, 0xdf, 0xff, - 0xfe, 0xde, 0xff, 0xff, 0xff, 0xd9, 0x41, 0x0, - 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x41, - 0x0, 0x0, 0x0, 0x15, 0xae, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x62, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x5, 0xaf, 0xff, 0xc8, 0x30, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x46, 0x63, 0x10, 0x0, 0x0, 0x0, - - /* U+F077 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x25, 0x77, 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x6b, 0xef, 0xff, 0xfd, 0x94, 0x10, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x26, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xd9, 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x6b, 0xef, 0xff, 0xfd, 0x94, 0x12, - 0x6b, 0xef, 0xff, 0xfd, 0x94, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x26, 0xbe, 0xff, 0xff, 0xd9, 0x41, - 0x0, 0x0, 0x0, 0x26, 0xbe, 0xff, 0xff, 0xd9, - 0x41, 0x0, 0x0, 0x16, 0xbf, 0xff, 0xfd, 0x94, - 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x6b, - 0xef, 0xff, 0xe9, 0x40, 0x0, 0x0, 0x25, 0x77, - 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x25, 0x77, 0x41, 0x0, - - /* U+F078 "" */ - 0x0, 0x0, 0x25, 0x77, 0x41, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x25, 0x77, - 0x41, 0x0, 0x0, 0x16, 0xbf, 0xff, 0xfd, 0x94, - 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x6b, - 0xef, 0xff, 0xe9, 0x40, 0x0, 0x0, 0x26, 0xbe, - 0xff, 0xff, 0xd9, 0x41, 0x0, 0x0, 0x0, 0x26, - 0xbe, 0xff, 0xff, 0xd9, 0x41, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x6b, 0xef, 0xff, 0xfd, 0x94, 0x12, - 0x6b, 0xef, 0xff, 0xfd, 0x94, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x26, 0xbe, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xd9, 0x41, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x6b, 0xef, 0xff, 0xfd, 0x94, 0x10, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x25, 0x76, 0x41, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F079 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x10, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x38, 0xcf, 0xff, - 0xc8, 0x30, 0x0, 0x3, 0x57, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x76, 0x52, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x38, 0xcf, 0xff, - 0xff, 0xff, 0xff, 0xc8, 0x32, 0x5a, 0xef, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x93, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xaf, 0xff, - 0xcc, 0xcf, 0xfe, 0xcc, 0xdf, 0xff, 0xa4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, 0xef, - 0xe9, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0x45, 0x31, 0x49, 0xef, 0xe9, 0x41, 0x35, 0x42, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, - 0x9e, 0xfe, 0x94, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x4, 0x9e, 0xfe, 0x94, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x49, 0xef, 0xe9, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, 0xef, 0xe9, - 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0x7b, 0xb9, 0x55, 0x9e, 0xfe, 0x95, 0x59, 0xbb, - 0x73, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x9e, - 0xff, 0xc9, 0x77, 0x77, 0x77, 0x77, 0x77, 0x76, - 0x53, 0x36, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xb6, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x38, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd7, 0x20, 0x37, 0xbe, 0xff, 0xff, - 0xfe, 0xb7, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26, - 0xac, 0xa6, 0x30, 0x0, 0x0, 0x0, 0x0, - - /* U+F07B "" */ - 0x0, 0x26, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xa6, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, - 0x98, 0x88, 0x88, 0x88, 0x88, 0x88, 0x77, 0x64, - 0x10, 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xa4, 0x0, 0x0, - 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa5, 0x0, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, - 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, 0x0, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xa5, 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, - 0x0, 0x26, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xeb, 0x62, 0x0, - - /* U+F093 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x44, 0x20, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x37, 0xce, 0xff, - 0xec, 0x73, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0x7c, 0xef, 0xff, 0xff, 0xff, 0xfe, 0xc7, - 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x37, 0xce, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0x73, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x39, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x93, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0x8d, 0xff, 0xff, 0xff, 0xd8, 0x30, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x8d, 0xff, - 0xff, 0xff, 0xd8, 0x20, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2, 0x8d, 0xff, 0xff, 0xff, 0xd8, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0x23, 0x33, 0x33, 0x33, 0x32, 0x13, - 0x8d, 0xff, 0xff, 0xff, 0xd8, 0x31, 0x23, 0x33, - 0x33, 0x33, 0x32, 0x10, 0x0, 0x0, 0x4a, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x94, 0x36, 0x99, 0x99, - 0x99, 0x63, 0x49, 0xef, 0xff, 0xff, 0xff, 0xff, - 0xa4, 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0xca, 0x99, 0x99, 0x99, 0xac, 0xef, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, 0x0, - 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xe9, 0x56, 0xbc, 0x75, - 0x8d, 0xff, 0xa5, 0x0, 0x0, 0x25, 0x9a, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa8, 0x52, - 0x0, - - /* U+F095 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x35, 0x76, - 0x53, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x27, 0xcf, 0xff, 0xff, 0xff, 0xfe, - 0x83, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x9e, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x93, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x49, 0xef, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x5a, 0xdf, 0xff, 0xff, 0xff, 0xe9, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, - 0xef, 0xff, 0xfe, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x27, 0xcf, 0xff, 0xff, 0xd7, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x11, 0x0, 0x0, 0x0, 0x0, 0x1, 0x49, - 0xdf, 0xff, 0xff, 0xe9, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x13, 0x58, 0xac, 0xef, 0xfe, 0xb5, - 0x10, 0x1, 0x36, 0xad, 0xff, 0xff, 0xff, 0xc7, - 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0xef, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xdc, 0xce, 0xff, - 0xff, 0xff, 0xfc, 0x94, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x17, 0xcf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xa6, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0x8d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed, - 0xb9, 0x63, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x77, - 0x76, 0x65, 0x43, 0x20, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+F0C4 "" */ - 0x0, 0x0, 0x2, 0x57, 0x89, 0x98, 0x63, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x23, 0x32, - 0x10, 0x0, 0x0, 0x15, 0xae, 0xff, 0xff, 0xff, - 0xff, 0xd7, 0x20, 0x0, 0x0, 0x1, 0x48, 0xcf, - 0xff, 0xff, 0xea, 0x50, 0x0, 0x49, 0xff, 0xe9, - 0x40, 0x17, 0xcf, 0xfc, 0x71, 0x0, 0x14, 0x8c, - 0xff, 0xff, 0xff, 0xd9, 0x51, 0x0, 0x0, 0x17, - 0xcf, 0xff, 0xdb, 0xce, 0xff, 0xfd, 0x84, 0x48, - 0xcf, 0xff, 0xff, 0xfd, 0x95, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x14, 0x8a, 0xcd, 0xef, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xd9, 0x51, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, - 0x9e, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x20, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x57, - 0x89, 0xbd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xb6, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, - 0xae, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xa7, 0x8b, - 0xef, 0xff, 0xff, 0xeb, 0x62, 0x0, 0x0, 0x0, - 0x0, 0x49, 0xff, 0xe9, 0x40, 0x17, 0xcf, 0xfc, - 0x71, 0x0, 0x27, 0xbe, 0xff, 0xff, 0xfe, 0xb6, - 0x20, 0x0, 0x0, 0x17, 0xcf, 0xff, 0xdb, 0xce, - 0xff, 0xe9, 0x40, 0x0, 0x0, 0x2, 0x6b, 0xef, - 0xff, 0xff, 0xe9, 0x40, 0x0, 0x0, 0x14, 0x8a, - 0xcc, 0xcb, 0x96, 0x30, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x13, 0x56, 0x66, 0x41, 0x0, - - /* U+F0C5 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x23, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x31, 0x12, 0x21, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, - 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x49, - 0xed, 0x94, 0x10, 0x0, 0x0, 0x1, 0x23, 0x44, - 0x32, 0x15, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xa5, 0x49, 0xef, 0xfe, 0xc7, 0x20, 0x0, 0x4a, - 0xff, 0xff, 0xe9, 0x45, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xec, 0x98, 0x88, 0x88, 0x85, 0x20, - 0x0, 0x5a, 0xff, 0xff, 0xe9, 0x45, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfa, 0x50, 0x0, 0x5a, 0xff, 0xff, 0xe9, 0x45, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfa, 0x50, 0x0, 0x5a, 0xff, 0xff, - 0xe9, 0x45, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfa, 0x50, 0x0, 0x5a, - 0xff, 0xff, 0xe9, 0x45, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x50, - 0x0, 0x5a, 0xff, 0xff, 0xe9, 0x45, 0xbf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfa, 0x50, 0x0, 0x5a, 0xff, 0xff, 0xe9, 0x45, - 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfa, 0x40, 0x0, 0x5a, 0xff, 0xff, - 0xfd, 0x95, 0x33, 0x34, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x43, 0x21, 0x0, 0x0, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa5, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x14, 0x67, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x76, 0x31, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+F0C7 "" */ - 0x0, 0x2, 0x47, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x87, 0x52, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x4a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xb6, 0x20, 0x0, 0x0, 0x0, 0x5a, 0xff, 0xd8, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x6b, 0xff, 0xff, 0xeb, 0x62, 0x0, 0x0, 0x5a, - 0xff, 0xd8, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x6b, 0xff, 0xff, 0xff, 0xe9, 0x30, - 0x0, 0x5a, 0xff, 0xeb, 0x97, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0xad, 0xff, 0xff, 0xff, - 0xf9, 0x40, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf9, 0x40, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xd9, 0x42, 0x12, 0x5a, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xf9, 0x40, 0x0, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x72, 0x0, 0x0, - 0x3, 0x8d, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x40, - 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x94, - 0x0, 0x0, 0x5, 0xaf, 0xff, 0xff, 0xff, 0xff, - 0xf9, 0x40, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0xca, 0x9a, 0xce, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf9, 0x40, 0x0, 0x16, 0xad, 0xef, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xed, 0x95, 0x10, - - /* U+F0C9 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x4a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x72, 0x0, 0x26, 0x9a, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xa7, 0x41, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x25, 0x88, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x86, 0x31, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x72, 0x0, 0x0, 0x11, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x11, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x26, 0x9a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xa7, 0x41, 0x0, 0x4a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F0E0 "" */ - 0x0, 0x26, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xeb, 0x62, 0x0, 0x0, 0x49, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xa4, 0x0, 0x0, 0x1, 0x47, 0xbe, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xeb, 0x74, 0x10, 0x0, 0x0, - 0x59, 0xc9, 0x53, 0x47, 0xbe, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x74, - 0x35, 0x9c, 0x95, 0x0, 0x0, 0x5a, 0xff, 0xff, - 0xd9, 0x53, 0x47, 0xbe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xeb, 0x74, 0x35, 0x9c, 0xff, 0xff, 0xa5, - 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xd9, - 0x63, 0x36, 0xad, 0xee, 0xda, 0x63, 0x36, 0x9d, - 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, 0x0, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xda, 0x75, - 0x44, 0x57, 0xad, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xa5, 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, - 0x0, 0x26, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xeb, 0x62, 0x0, - - /* U+F0E7 "" */ - 0x0, 0x0, 0x15, 0x9b, 0xbb, 0xbb, 0xbb, 0xbb, - 0xa8, 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, - 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb6, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x2, 0x7c, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xb6, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xc6, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, - 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0xb6, 0x10, 0x3, 0x8e, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc6, - 0x10, 0x0, 0x49, 0xef, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0x82, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x27, 0xcf, 0xff, 0xff, - 0xe9, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x5, 0xaf, 0xff, 0xfe, 0xa5, 0x10, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x8e, - 0xff, 0xfc, 0x72, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0x7c, 0xff, 0xd8, 0x30, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x5a, 0xfe, 0x94, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x23, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F0EA "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x25, 0x8a, 0xa8, - 0x52, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x38, 0xef, 0xff, 0xff, 0xff, - 0xb8, 0x8c, 0xff, 0xff, 0xff, 0xfc, 0x72, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xff, 0xb8, 0x8c, 0xff, 0xff, 0xff, 0xff, - 0x94, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0xdc, 0xbb, 0xbb, - 0xbb, 0xba, 0x73, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x5a, 0xff, 0xff, 0xff, 0xfc, 0x74, 0x58, - 0x99, 0x99, 0x99, 0x99, 0x52, 0x25, 0x64, 0x10, - 0x0, 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xfa, - 0x55, 0xbf, 0xff, 0xff, 0xff, 0xff, 0x94, 0x4a, - 0xff, 0xda, 0x52, 0x0, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xfa, 0x55, 0xbf, 0xff, 0xff, 0xff, 0xff, - 0xa5, 0x23, 0x56, 0x66, 0x53, 0x10, 0x0, 0x5a, - 0xff, 0xff, 0xff, 0xfa, 0x55, 0xbf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x40, - 0x0, 0x5a, 0xff, 0xff, 0xff, 0xfa, 0x55, 0xbf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf9, 0x40, 0x0, 0x49, 0xef, 0xff, 0xff, 0xfa, - 0x55, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf9, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x5, 0xbf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf9, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x5, 0xaf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x23, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x31, 0x0, - - /* U+F0F3 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x14, 0x65, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x4, 0x9d, 0xff, 0xb6, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x26, 0xad, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xc9, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x49, 0xef, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x72, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x5, 0xaf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x30, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x72, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x8d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, 0x0, - 0x0, 0x2, 0x6b, 0xef, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x93, 0x0, 0x0, 0x39, 0xef, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfb, 0x61, 0x0, 0x1, 0x23, 0x34, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x43, 0x21, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0x7c, 0xff, 0xff, - 0xfe, 0x94, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x46, 0x76, 0x52, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+F11C "" */ - 0x0, 0x26, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0x84, 0x0, 0x5, - 0xaf, 0xfe, 0xc9, 0x88, 0xad, 0xeb, 0x88, 0x8b, - 0xed, 0xa8, 0x8b, 0xee, 0xb8, 0x88, 0x8b, 0xee, - 0xb8, 0x8a, 0xdf, 0xfd, 0x72, 0x0, 0x5a, 0xff, - 0xd8, 0x30, 0x5, 0xbc, 0x71, 0x1, 0x7c, 0xb5, - 0x1, 0x6b, 0xb6, 0x0, 0x0, 0x6b, 0xb6, 0x10, - 0x5b, 0xff, 0xd8, 0x20, 0x5, 0xaf, 0xff, 0xff, - 0xfe, 0xdc, 0xcd, 0xef, 0xed, 0xcc, 0xde, 0xed, - 0xcc, 0xce, 0xff, 0xec, 0xcc, 0xef, 0xff, 0xff, - 0xfd, 0x82, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xa4, - 0x0, 0x38, 0xc8, 0x30, 0x5, 0xaa, 0x40, 0x2, - 0x7d, 0xd7, 0x20, 0x27, 0xcf, 0xff, 0xff, 0xd8, - 0x20, 0x5, 0xaf, 0xff, 0xff, 0xfe, 0xdc, 0xcd, - 0xef, 0xed, 0xcc, 0xde, 0xed, 0xcc, 0xce, 0xff, - 0xec, 0xcc, 0xef, 0xff, 0xff, 0xfd, 0x82, 0x0, - 0x5a, 0xff, 0xd8, 0x30, 0x5, 0xbc, 0x71, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6b, - 0xb6, 0x10, 0x5b, 0xff, 0xd8, 0x20, 0x5, 0xaf, - 0xfe, 0xc9, 0x88, 0xad, 0xeb, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x8b, 0xde, 0xb8, - 0x8a, 0xdf, 0xfd, 0x72, 0x0, 0x26, 0xbe, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0x84, 0x0, - - /* U+F124 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x24, 0x66, 0x53, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0x35, 0x8a, 0xde, 0xff, 0xff, 0xfe, - 0x93, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0x47, 0x9c, 0xef, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0x61, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x13, 0x68, 0xad, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0x93, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, - 0x79, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x20, 0x0, - 0x0, 0x0, 0x26, 0xbe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfa, 0x50, 0x0, 0x0, 0x0, 0x0, 0x38, - 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x83, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x33, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x9d, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xb6, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xea, 0x40, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6c, 0xff, - 0xff, 0xff, 0xfd, 0x82, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0x6c, 0xff, 0xff, 0xff, 0xb5, - 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x6b, 0xff, 0xff, 0xe9, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x46, 0x64, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+F15B "" */ - 0x0, 0x26, 0x9b, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, - 0xba, 0x62, 0x36, 0x74, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x5, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe9, 0x45, 0xaf, 0xfd, 0x94, 0x10, 0x0, - 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x94, 0x5a, 0xff, 0xff, 0xfd, 0x94, - 0x10, 0x0, 0x5, 0xaf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfa, 0x52, 0x34, 0x44, 0x44, 0x44, - 0x31, 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfa, 0x50, 0x0, 0x5, 0xaf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xa5, 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfa, 0x50, 0x0, 0x5, 0xaf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa5, 0x0, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfa, 0x50, 0x0, 0x5, 0xaf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xa5, 0x0, 0x0, 0x5a, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfa, 0x50, 0x0, 0x5, 0xaf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, 0x0, 0x2, - 0x34, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x31, 0x0, 0x0, - - /* U+F1EB "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x35, 0x67, 0x99, 0xab, 0xbb, 0xcb, 0xbb, - 0xa9, 0x97, 0x65, 0x31, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x25, - 0x8b, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x85, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x13, 0x7b, - 0xef, 0xff, 0xff, 0xfe, 0xca, 0x87, 0x54, 0x33, - 0x22, 0x22, 0x23, 0x34, 0x57, 0x8a, 0xce, 0xff, - 0xff, 0xff, 0xeb, 0x73, 0x10, 0x0, 0x0, 0x28, - 0xdf, 0xff, 0xfd, 0xa7, 0x31, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0x37, 0xad, 0xff, 0xff, 0xd8, 0x30, 0x0, - 0x0, 0x2, 0x57, 0x63, 0x0, 0x0, 0x1, 0x25, - 0x79, 0xbc, 0xde, 0xff, 0xff, 0xfe, 0xdc, 0xb9, - 0x75, 0x21, 0x0, 0x0, 0x3, 0x57, 0x52, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x8c, - 0xef, 0xff, 0xff, 0xff, 0xfe, 0xee, 0xee, 0xff, - 0xff, 0xff, 0xff, 0xec, 0x84, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0x6b, 0xef, 0xfc, 0x96, 0x42, 0x10, 0x0, 0x0, - 0x0, 0x12, 0x46, 0x9c, 0xef, 0xeb, 0x62, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0x21, 0x0, 0x0, 0x0, 0x0, - 0x11, 0x10, 0x0, 0x0, 0x0, 0x1, 0x21, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x5a, 0xef, 0xff, 0xea, 0x51, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x49, 0xff, 0xff, 0xff, 0xf9, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x26, 0xac, 0xdc, 0xa6, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+F240 "" */ - 0x0, 0x1, 0x35, 0x67, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x65, 0x20, 0x0, - 0x0, 0x0, 0x4, 0x9f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x83, 0x0, 0x0, 0x0, 0x5a, 0xff, 0xd8, 0x32, - 0x34, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x21, 0x49, - 0xef, 0xff, 0xd8, 0x30, 0x0, 0x5, 0xaf, 0xfd, - 0x84, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, - 0x52, 0x59, 0xce, 0xff, 0xa5, 0x0, 0x0, 0x5a, - 0xff, 0xd8, 0x46, 0xcf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xa5, 0x0, 0x28, 0xdf, 0xfa, 0x50, 0x0, - 0x5, 0xaf, 0xfd, 0x83, 0x59, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xc8, 0x43, 0x8e, 0xff, 0xff, 0xa5, - 0x0, 0x0, 0x5a, 0xff, 0xeb, 0x87, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x9c, 0xff, 0xfc, - 0x94, 0x10, 0x0, 0x2, 0x6c, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xea, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F241 "" */ - 0x0, 0x1, 0x35, 0x67, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x65, 0x20, 0x0, - 0x0, 0x0, 0x4, 0x9f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x83, 0x0, 0x0, 0x0, 0x5a, 0xff, 0xd8, 0x32, - 0x34, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x43, 0x21, 0x0, 0x0, 0x0, 0x49, - 0xef, 0xff, 0xd8, 0x30, 0x0, 0x5, 0xaf, 0xfd, - 0x84, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xc6, 0x10, 0x0, 0x0, - 0x2, 0x59, 0xce, 0xff, 0xa5, 0x0, 0x0, 0x5a, - 0xff, 0xd8, 0x46, 0xcf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x61, 0x0, - 0x0, 0x0, 0x0, 0x28, 0xdf, 0xfa, 0x50, 0x0, - 0x5, 0xaf, 0xfd, 0x83, 0x59, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x95, - 0x0, 0x0, 0x0, 0x3, 0x8e, 0xff, 0xff, 0xa5, - 0x0, 0x0, 0x5a, 0xff, 0xeb, 0x87, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x9c, 0xff, 0xfc, - 0x94, 0x10, 0x0, 0x2, 0x6c, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xea, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F242 "" */ - 0x0, 0x1, 0x35, 0x67, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x65, 0x20, 0x0, - 0x0, 0x0, 0x4, 0x9f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x83, 0x0, 0x0, 0x0, 0x5a, 0xff, 0xd8, 0x32, - 0x34, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x32, - 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, - 0xef, 0xff, 0xd8, 0x30, 0x0, 0x5, 0xaf, 0xfd, - 0x84, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0x82, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x59, 0xce, 0xff, 0xa5, 0x0, 0x0, 0x5a, - 0xff, 0xd8, 0x46, 0xcf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd8, 0x20, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x28, 0xdf, 0xfa, 0x50, 0x0, - 0x5, 0xaf, 0xfd, 0x83, 0x59, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0xca, 0x62, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0x8e, 0xff, 0xff, 0xa5, - 0x0, 0x0, 0x5a, 0xff, 0xeb, 0x87, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x9c, 0xff, 0xfc, - 0x94, 0x10, 0x0, 0x2, 0x6c, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xea, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F243 "" */ - 0x0, 0x1, 0x35, 0x67, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x65, 0x20, 0x0, - 0x0, 0x0, 0x4, 0x9f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x83, 0x0, 0x0, 0x0, 0x5a, 0xff, 0xd8, 0x32, - 0x34, 0x44, 0x44, 0x43, 0x21, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, - 0xef, 0xff, 0xd8, 0x30, 0x0, 0x5, 0xaf, 0xfd, - 0x84, 0x6c, 0xff, 0xff, 0xff, 0xe9, 0x40, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x59, 0xce, 0xff, 0xa5, 0x0, 0x0, 0x5a, - 0xff, 0xd8, 0x46, 0xcf, 0xff, 0xff, 0xfe, 0x94, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x28, 0xdf, 0xfa, 0x50, 0x0, - 0x5, 0xaf, 0xfd, 0x83, 0x59, 0xcc, 0xcc, 0xcc, - 0xb7, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0x8e, 0xff, 0xff, 0xa5, - 0x0, 0x0, 0x5a, 0xff, 0xeb, 0x87, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x9c, 0xff, 0xfc, - 0x94, 0x10, 0x0, 0x2, 0x6c, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xea, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F244 "" */ - 0x0, 0x1, 0x35, 0x67, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x65, 0x20, 0x0, - 0x0, 0x0, 0x4, 0x9f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x83, 0x0, 0x0, 0x0, 0x5a, 0xff, 0xd8, 0x30, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, - 0xef, 0xff, 0xd8, 0x30, 0x0, 0x5, 0xaf, 0xfd, - 0x82, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x59, 0xce, 0xff, 0xa5, 0x0, 0x0, 0x5a, - 0xff, 0xd8, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x28, 0xdf, 0xfa, 0x50, 0x0, - 0x5, 0xaf, 0xfd, 0x82, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0x8e, 0xff, 0xff, 0xa5, - 0x0, 0x0, 0x5a, 0xff, 0xeb, 0x87, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, 0x77, 0x9c, 0xff, 0xfc, - 0x94, 0x10, 0x0, 0x2, 0x6c, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xea, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F287 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x12, 0x33, 0x59, 0xdf, - 0xfe, 0xb6, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x15, 0xad, 0xca, 0x9b, - 0xdf, 0xff, 0xfe, 0x93, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x11, 0x10, 0x0, 0x0, 0x0, 0x38, 0xdb, 0x51, - 0x0, 0x1, 0x24, 0x54, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, - 0x9d, 0xff, 0xff, 0xd9, 0x41, 0x1, 0x6b, 0xd8, - 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x6a, 0xb8, 0x52, 0x0, 0x0, 0x0, - 0x4, 0xaf, 0xff, 0xff, 0xff, 0xfe, 0xed, 0xee, - 0xee, 0xee, 0xee, 0xed, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xde, 0xff, 0xff, 0xfc, 0x72, - 0x0, 0x0, 0x4, 0x9d, 0xff, 0xff, 0xd9, 0x41, - 0x0, 0x0, 0x0, 0x16, 0xbd, 0x83, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x2, 0x6a, 0xb8, 0x52, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x8c, 0xb6, - 0x10, 0x3, 0x57, 0x77, 0x77, 0x42, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x49, 0xcc, 0xba, 0xce, 0xff, 0xff, 0xfb, 0x60, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x12, 0x49, 0xdf, 0xff, 0xff, - 0xb5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+F293 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x23, 0x34, - 0x43, 0x32, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0x6a, 0xde, 0xff, 0xfe, - 0xee, 0xff, 0xff, 0xed, 0xa5, 0x20, 0x0, 0x0, - 0x0, 0x0, 0x1, 0x4a, 0xef, 0xff, 0xff, 0xff, - 0xa5, 0x37, 0xcf, 0xff, 0xff, 0xfd, 0x93, 0x0, - 0x0, 0x0, 0x1, 0x7c, 0xff, 0xff, 0xff, 0xff, - 0xfa, 0x40, 0x1, 0x48, 0xdf, 0xff, 0xff, 0xa5, - 0x0, 0x0, 0x0, 0x5b, 0xff, 0xfd, 0x84, 0x59, - 0xdf, 0xa4, 0x27, 0xa8, 0x42, 0x5b, 0xff, 0xfe, - 0x83, 0x0, 0x0, 0x28, 0xdf, 0xff, 0xff, 0xc7, - 0x32, 0x44, 0x21, 0x34, 0x33, 0x7c, 0xff, 0xff, - 0xfa, 0x50, 0x0, 0x3, 0x8e, 0xff, 0xff, 0xff, - 0xff, 0xc6, 0x20, 0x1, 0x5a, 0xef, 0xff, 0xff, - 0xff, 0xb6, 0x0, 0x0, 0x38, 0xef, 0xff, 0xff, - 0xfe, 0xb6, 0x20, 0x0, 0x1, 0x49, 0xdf, 0xff, - 0xff, 0xfb, 0x60, 0x0, 0x2, 0x7c, 0xff, 0xfe, - 0xb6, 0x22, 0x59, 0x84, 0x26, 0x97, 0x32, 0x5a, - 0xef, 0xff, 0xa5, 0x0, 0x0, 0x4, 0x9f, 0xff, - 0xec, 0xab, 0xdf, 0xfa, 0x41, 0x46, 0x42, 0x59, - 0xdf, 0xff, 0xd8, 0x20, 0x0, 0x0, 0x4, 0x9e, - 0xff, 0xff, 0xff, 0xff, 0xa4, 0x1, 0x5a, 0xdf, - 0xff, 0xff, 0xd8, 0x20, 0x0, 0x0, 0x0, 0x1, - 0x49, 0xdf, 0xff, 0xff, 0xfb, 0xaa, 0xdf, 0xff, - 0xff, 0xfd, 0x94, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x24, 0x68, 0x9a, 0xab, 0xbb, 0xa9, - 0x87, 0x52, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F2ED "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x67, - 0x88, 0x88, 0x87, 0x75, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x37, 0xbb, 0xcc, 0xcc, 0xcc, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed, 0xcc, - 0xcc, 0xcc, 0xb9, 0x51, 0x0, 0x37, 0xbb, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xb9, 0x51, 0x0, 0x0, - 0x24, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x86, 0x30, 0x0, - 0x0, 0x0, 0x49, 0xef, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x61, 0x0, 0x0, 0x0, 0x49, 0xef, 0xff, 0xa5, - 0x5a, 0xff, 0xe9, 0x56, 0xbf, 0xfd, 0x85, 0x8d, - 0xff, 0xfc, 0x61, 0x0, 0x0, 0x0, 0x49, 0xef, - 0xff, 0xa4, 0x4a, 0xff, 0xe8, 0x46, 0xbf, 0xfc, - 0x74, 0x7c, 0xff, 0xfc, 0x61, 0x0, 0x0, 0x0, - 0x49, 0xef, 0xff, 0xa4, 0x4a, 0xff, 0xe8, 0x46, - 0xbf, 0xfc, 0x74, 0x7c, 0xff, 0xfc, 0x61, 0x0, - 0x0, 0x0, 0x49, 0xef, 0xff, 0xa4, 0x4a, 0xff, - 0xe8, 0x46, 0xbf, 0xfc, 0x74, 0x7c, 0xff, 0xfc, - 0x61, 0x0, 0x0, 0x0, 0x49, 0xef, 0xff, 0xa4, - 0x4a, 0xff, 0xe8, 0x46, 0xbf, 0xfc, 0x74, 0x7c, - 0xff, 0xfc, 0x61, 0x0, 0x0, 0x0, 0x49, 0xef, - 0xff, 0xa5, 0x5a, 0xff, 0xe9, 0x56, 0xbf, 0xfd, - 0x85, 0x8d, 0xff, 0xfc, 0x61, 0x0, 0x0, 0x0, - 0x38, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x60, 0x0, - 0x0, 0x0, 0x1, 0x36, 0x77, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x76, 0x42, - 0x0, 0x0, - - /* U+F304 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x67, - 0x63, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x5a, 0xef, 0xff, 0xff, 0xd9, 0x41, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x25, 0x9d, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x72, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2, 0x5a, 0xef, 0xda, 0x53, 0x5a, 0xdf, 0xff, - 0xff, 0xfd, 0x82, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x25, 0xae, 0xff, 0xff, - 0xff, 0xfd, 0xa5, 0x35, 0xad, 0xda, 0x52, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0x5a, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xd8, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x25, 0xae, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xea, 0x52, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x5a, - 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xa5, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x25, 0xae, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xea, 0x52, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0xbf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xa5, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x28, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xea, 0x52, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x4a, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xa5, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x13, 0x67, 0x76, - 0x55, 0x44, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+F55A "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, 0x9c, - 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0x84, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, 0xad, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xa4, 0x0, 0x0, 0x0, 0x0, 0x15, 0xad, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x94, 0x1, - 0x49, 0xdf, 0xfd, 0x94, 0x10, 0x39, 0xdf, 0xff, - 0xff, 0xff, 0xfa, 0x50, 0x0, 0x0, 0x15, 0xad, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x94, 0x10, 0x1, 0x22, 0x10, 0x1, 0x49, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xa5, 0x0, 0x0, 0x39, - 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfb, 0x61, 0x0, 0x0, 0x15, 0xbf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x50, 0x0, - 0x0, 0x15, 0xad, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0x94, 0x10, 0x1, 0x33, 0x10, - 0x1, 0x49, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xa5, - 0x0, 0x0, 0x0, 0x0, 0x15, 0xad, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0x94, 0x11, 0x49, 0xdf, - 0xfd, 0x94, 0x10, 0x49, 0xdf, 0xff, 0xff, 0xff, - 0xfa, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, - 0x9d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x14, 0x9c, 0xef, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xec, 0x84, 0x0, 0x0, - - /* U+F7C2 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x67, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x77, 0x64, 0x20, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x25, 0xad, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x83, - 0x0, 0x0, 0x0, 0x26, 0xbe, 0xff, 0xa4, 0x0, - 0x5b, 0xb6, 0x3, 0x9b, 0x72, 0x28, 0xdf, 0xfa, - 0x50, 0x0, 0x4, 0x9e, 0xff, 0xff, 0xfa, 0x40, - 0x5, 0xbb, 0x60, 0x39, 0xb7, 0x22, 0x8d, 0xff, - 0xa5, 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfa, 0x50, 0x0, 0x5, 0xaf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xa5, 0x0, 0x0, 0x5a, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfa, 0x50, 0x0, 0x5, 0xaf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa5, 0x0, 0x0, 0x5a, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfa, 0x50, 0x0, 0x5, 0xaf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xa5, 0x0, 0x0, 0x5a, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfa, 0x50, 0x0, 0x2, 0x6c, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x62, 0x0, 0x0, 0x0, - 0x1, 0x34, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x31, 0x0, 0x0, 0x0, - - /* U+F8A2 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x12, 0x21, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x48, 0xdf, - 0xb6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x6a, - 0xc9, 0x51, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x27, 0xdf, 0xff, 0xb6, 0x0, 0x0, - 0x0, 0x0, 0x37, 0xce, 0xff, 0xfc, 0x72, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, - 0xdf, 0xff, 0xb6, 0x0, 0x0, 0x3, 0x8c, 0xff, - 0xff, 0xff, 0xff, 0xed, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xff, 0xff, 0xb6, - 0x0, 0x0, 0x16, 0xbe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xa4, 0x0, 0x0, 0x0, - 0x2, 0x6b, 0xef, 0xff, 0xfc, 0x72, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, - 0xad, 0xfc, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0 -}; - - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 52, .box_w = 6, .box_h = 0, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 0, .adv_w = 51, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 41, .adv_w = 75, .box_w = 15, .box_h = 4, .ofs_x = 0, .ofs_y = 5}, - {.bitmap_index = 71, .adv_w = 135, .box_w = 27, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 193, .adv_w = 119, .box_w = 24, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 349, .adv_w = 162, .box_w = 30, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 484, .adv_w = 132, .box_w = 27, .box_h = 10, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 619, .adv_w = 40, .box_w = 9, .box_h = 4, .ofs_x = 0, .ofs_y = 5}, - {.bitmap_index = 637, .adv_w = 65, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 715, .adv_w = 65, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 793, .adv_w = 77, .box_w = 18, .box_h = 5, .ofs_x = -1, .ofs_y = 5}, - {.bitmap_index = 838, .adv_w = 112, .box_w = 21, .box_h = 6, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 901, .adv_w = 44, .box_w = 9, .box_h = 4, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 919, .adv_w = 74, .box_w = 15, .box_h = 2, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 934, .adv_w = 44, .box_w = 9, .box_h = 2, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 943, .adv_w = 68, .box_w = 18, .box_h = 13, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 1060, .adv_w = 128, .box_w = 24, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1168, .adv_w = 71, .box_w = 15, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 1236, .adv_w = 110, .box_w = 24, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 1344, .adv_w = 110, .box_w = 24, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 1452, .adv_w = 128, .box_w = 27, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1574, .adv_w = 110, .box_w = 24, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 1682, .adv_w = 118, .box_w = 24, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1790, .adv_w = 115, .box_w = 24, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1898, .adv_w = 124, .box_w = 24, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 2006, .adv_w = 118, .box_w = 24, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 2114, .adv_w = 44, .box_w = 9, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 2146, .adv_w = 44, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 2187, .adv_w = 112, .box_w = 21, .box_h = 7, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 2261, .adv_w = 112, .box_w = 21, .box_h = 5, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 2314, .adv_w = 112, .box_w = 21, .box_h = 7, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 2388, .adv_w = 110, .box_w = 24, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 2496, .adv_w = 199, .box_w = 39, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 2730, .adv_w = 141, .box_w = 33, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 2879, .adv_w = 145, .box_w = 27, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3001, .adv_w = 139, .box_w = 27, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3123, .adv_w = 159, .box_w = 30, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3258, .adv_w = 129, .box_w = 24, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3366, .adv_w = 122, .box_w = 24, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3474, .adv_w = 148, .box_w = 27, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3596, .adv_w = 156, .box_w = 27, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3718, .adv_w = 60, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3759, .adv_w = 98, .box_w = 21, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 3854, .adv_w = 138, .box_w = 27, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3976, .adv_w = 114, .box_w = 24, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4084, .adv_w = 183, .box_w = 33, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4233, .adv_w = 156, .box_w = 27, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4355, .adv_w = 161, .box_w = 30, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4490, .adv_w = 139, .box_w = 27, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4612, .adv_w = 161, .box_w = 33, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 4810, .adv_w = 140, .box_w = 27, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4932, .adv_w = 119, .box_w = 24, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 5040, .adv_w = 113, .box_w = 27, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 5162, .adv_w = 152, .box_w = 27, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 5284, .adv_w = 137, .box_w = 30, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 5419, .adv_w = 216, .box_w = 42, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 5608, .adv_w = 129, .box_w = 30, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 5743, .adv_w = 124, .box_w = 30, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 5878, .adv_w = 126, .box_w = 24, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 5986, .adv_w = 64, .box_w = 15, .box_h = 13, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 6084, .adv_w = 68, .box_w = 18, .box_h = 13, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 6201, .adv_w = 64, .box_w = 15, .box_h = 13, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 6299, .adv_w = 112, .box_w = 21, .box_h = 6, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 6362, .adv_w = 96, .box_w = 24, .box_h = 1, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 6374, .adv_w = 115, .box_w = 12, .box_h = 2, .ofs_x = 1, .ofs_y = 8}, - {.bitmap_index = 6386, .adv_w = 115, .box_w = 21, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 6460, .adv_w = 131, .box_w = 27, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 6595, .adv_w = 110, .box_w = 21, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 6669, .adv_w = 131, .box_w = 24, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 6789, .adv_w = 118, .box_w = 24, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 6873, .adv_w = 68, .box_w = 18, .box_h = 10, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 6963, .adv_w = 132, .box_w = 24, .box_h = 10, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 7083, .adv_w = 131, .box_w = 24, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 7203, .adv_w = 54, .box_w = 9, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 7248, .adv_w = 55, .box_w = 15, .box_h = 13, .ofs_x = -2, .ofs_y = -3}, - {.bitmap_index = 7346, .adv_w = 118, .box_w = 24, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 7466, .adv_w = 54, .box_w = 9, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 7511, .adv_w = 203, .box_w = 36, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 7637, .adv_w = 131, .box_w = 24, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 7721, .adv_w = 122, .box_w = 24, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 7805, .adv_w = 131, .box_w = 27, .box_h = 10, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 7940, .adv_w = 131, .box_w = 24, .box_h = 10, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 8060, .adv_w = 79, .box_w = 15, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 8113, .adv_w = 96, .box_w = 21, .box_h = 7, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 8187, .adv_w = 79, .box_w = 18, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 8268, .adv_w = 130, .box_w = 24, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 8352, .adv_w = 107, .box_w = 27, .box_h = 7, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 8447, .adv_w = 173, .box_w = 39, .box_h = 7, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 8584, .adv_w = 106, .box_w = 24, .box_h = 7, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 8668, .adv_w = 107, .box_w = 27, .box_h = 10, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 8803, .adv_w = 100, .box_w = 21, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 8877, .adv_w = 67, .box_w = 15, .box_h = 13, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 8975, .adv_w = 57, .box_w = 9, .box_h = 13, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 9034, .adv_w = 67, .box_w = 15, .box_h = 13, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 9132, .adv_w = 112, .box_w = 21, .box_h = 2, .ofs_x = 0, .ofs_y = 4}, - {.bitmap_index = 9153, .adv_w = 80, .box_w = 15, .box_h = 5, .ofs_x = 0, .ofs_y = 5}, - {.bitmap_index = 9191, .adv_w = 60, .box_w = 12, .box_h = 3, .ofs_x = 0, .ofs_y = 2}, - {.bitmap_index = 9209, .adv_w = 192, .box_w = 42, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 9482, .adv_w = 192, .box_w = 42, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 9671, .adv_w = 192, .box_w = 42, .box_h = 11, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 9902, .adv_w = 192, .box_w = 42, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 10091, .adv_w = 132, .box_w = 30, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 10226, .adv_w = 192, .box_w = 42, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 10499, .adv_w = 192, .box_w = 36, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 10733, .adv_w = 216, .box_w = 45, .box_h = 11, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 10981, .adv_w = 192, .box_w = 42, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 11254, .adv_w = 216, .box_w = 45, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 11457, .adv_w = 192, .box_w = 42, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 11730, .adv_w = 96, .box_w = 24, .box_h = 10, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 11850, .adv_w = 144, .box_w = 33, .box_h = 10, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 12015, .adv_w = 216, .box_w = 45, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 12308, .adv_w = 192, .box_w = 42, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 12497, .adv_w = 132, .box_w = 30, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 12692, .adv_w = 168, .box_w = 27, .box_h = 12, .ofs_x = 1, .ofs_y = -2}, - {.bitmap_index = 12854, .adv_w = 168, .box_w = 36, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 13088, .adv_w = 168, .box_w = 36, .box_h = 11, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 13286, .adv_w = 168, .box_w = 36, .box_h = 11, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 13484, .adv_w = 168, .box_w = 27, .box_h = 12, .ofs_x = 1, .ofs_y = -2}, - {.bitmap_index = 13646, .adv_w = 168, .box_w = 39, .box_h = 11, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 13861, .adv_w = 120, .box_w = 24, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 13993, .adv_w = 120, .box_w = 24, .box_h = 11, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 14125, .adv_w = 168, .box_w = 36, .box_h = 11, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 14323, .adv_w = 168, .box_w = 36, .box_h = 3, .ofs_x = -1, .ofs_y = 3}, - {.bitmap_index = 14377, .adv_w = 216, .box_w = 45, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 14580, .adv_w = 240, .box_w = 51, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 14912, .adv_w = 216, .box_w = 45, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 15205, .adv_w = 192, .box_w = 42, .box_h = 11, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 15436, .adv_w = 168, .box_w = 36, .box_h = 7, .ofs_x = -1, .ofs_y = 1}, - {.bitmap_index = 15562, .adv_w = 168, .box_w = 36, .box_h = 7, .ofs_x = -1, .ofs_y = 1}, - {.bitmap_index = 15688, .adv_w = 240, .box_w = 51, .box_h = 10, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 15943, .adv_w = 192, .box_w = 42, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 16132, .adv_w = 192, .box_w = 42, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 16405, .adv_w = 192, .box_w = 42, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 16678, .adv_w = 168, .box_w = 36, .box_h = 11, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 16876, .adv_w = 168, .box_w = 36, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 17110, .adv_w = 168, .box_w = 36, .box_h = 11, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 17308, .adv_w = 168, .box_w = 36, .box_h = 11, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 17506, .adv_w = 192, .box_w = 42, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 17695, .adv_w = 120, .box_w = 27, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 17871, .adv_w = 168, .box_w = 36, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 18105, .adv_w = 168, .box_w = 36, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 18339, .adv_w = 216, .box_w = 45, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 18542, .adv_w = 192, .box_w = 42, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 18815, .adv_w = 144, .box_w = 33, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 19030, .adv_w = 240, .box_w = 51, .box_h = 12, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 19336, .adv_w = 240, .box_w = 51, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 19566, .adv_w = 240, .box_w = 51, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 19796, .adv_w = 240, .box_w = 51, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 20026, .adv_w = 240, .box_w = 51, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 20256, .adv_w = 240, .box_w = 51, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 20486, .adv_w = 240, .box_w = 51, .box_h = 11, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 20767, .adv_w = 168, .box_w = 33, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 20982, .adv_w = 168, .box_w = 36, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 21216, .adv_w = 192, .box_w = 42, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 21489, .adv_w = 240, .box_w = 51, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 21719, .adv_w = 144, .box_w = 33, .box_h = 13, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 21934, .adv_w = 193, .box_w = 42, .box_h = 9, .ofs_x = -1, .ofs_y = 0} -}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_1[] = { - 0x0, 0x1f72, 0xef51, 0xef58, 0xef5b, 0xef5c, 0xef5d, 0xef61, - 0xef63, 0xef65, 0xef69, 0xef6c, 0xef71, 0xef76, 0xef77, 0xef78, - 0xef8e, 0xef93, 0xef98, 0xef9b, 0xef9c, 0xef9d, 0xefa1, 0xefa2, - 0xefa3, 0xefa4, 0xefb7, 0xefb8, 0xefbe, 0xefc0, 0xefc1, 0xefc4, - 0xefc7, 0xefc8, 0xefc9, 0xefcb, 0xefe3, 0xefe5, 0xf014, 0xf015, - 0xf017, 0xf019, 0xf030, 0xf037, 0xf03a, 0xf043, 0xf06c, 0xf074, - 0xf0ab, 0xf13b, 0xf190, 0xf191, 0xf192, 0xf193, 0xf194, 0xf1d7, - 0xf1e3, 0xf23d, 0xf254, 0xf4aa, 0xf712, 0xf7f2 -}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { - { - .range_start = 32, .range_length = 95, .glyph_id_start = 1, - .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY - }, - { - .range_start = 176, .range_length = 63475, .glyph_id_start = 96, - .unicode_list = unicode_list_1, .glyph_id_ofs_list = NULL, .list_length = 62, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY - } -}; - -/*----------------- - * KERNING - *----------------*/ - - -/*Map glyph_ids to kern left classes*/ -static const uint8_t kern_left_class_mapping[] = { - 0, 0, 1, 2, 0, 3, 4, 5, - 2, 6, 7, 8, 9, 10, 9, 10, - 11, 12, 0, 13, 14, 15, 16, 17, - 18, 19, 12, 20, 20, 0, 0, 0, - 21, 22, 23, 24, 25, 22, 26, 27, - 28, 29, 29, 30, 31, 32, 29, 29, - 22, 33, 34, 35, 3, 36, 30, 37, - 37, 38, 39, 40, 41, 42, 43, 0, - 44, 0, 45, 46, 47, 48, 49, 50, - 51, 45, 52, 52, 53, 48, 45, 45, - 46, 46, 54, 55, 56, 57, 51, 58, - 58, 59, 58, 60, 41, 0, 0, 9, - 61, 9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 -}; - -/*Map glyph_ids to kern right classes*/ -static const uint8_t kern_right_class_mapping[] = { - 0, 0, 1, 2, 0, 3, 4, 5, - 2, 6, 7, 8, 9, 10, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 12, - 18, 19, 20, 21, 21, 0, 0, 0, - 22, 23, 24, 25, 23, 25, 25, 25, - 23, 25, 25, 26, 25, 25, 25, 25, - 23, 25, 23, 25, 3, 27, 28, 29, - 29, 30, 31, 32, 33, 34, 35, 0, - 36, 0, 37, 38, 39, 39, 39, 0, - 39, 38, 40, 41, 38, 38, 42, 42, - 39, 42, 39, 42, 43, 44, 45, 46, - 46, 47, 46, 48, 0, 0, 35, 9, - 49, 9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 -}; - -/*Kern values between classes*/ -static const int8_t kern_class_values[] = { - 0, 1, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 2, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 9, 0, 5, -4, 0, 0, - 0, 0, -11, -12, 1, 9, 4, 3, - -8, 1, 9, 1, 8, 2, 6, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 12, 2, -1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4, 0, -6, 0, 0, 0, 0, - 0, -4, 3, 4, 0, 0, -2, 0, - -1, 2, 0, -2, 0, -2, -1, -4, - 0, 0, 0, 0, -2, 0, 0, -2, - -3, 0, 0, -2, 0, -4, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -2, - -2, 0, -3, 0, -5, 0, -23, 0, - 0, -4, 0, 4, 6, 0, 0, -4, - 2, 2, 6, 4, -3, 4, 0, 0, - -11, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -5, -2, -9, 0, -8, - -1, 0, 0, 0, 0, 0, 7, 0, - -6, -2, -1, 1, 0, -3, 0, 0, - -1, -14, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -15, -2, 7, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -8, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 6, - 0, 2, 0, 0, -4, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 7, 2, - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - -7, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, - 4, 2, 6, -2, 0, 0, 4, -2, - -6, -26, 1, 5, 4, 0, -2, 0, - 7, 0, 6, 0, 6, 0, -18, 0, - -2, 6, 0, 6, -2, 4, 2, 0, - 0, 1, -2, 0, 0, -3, 15, 0, - 15, 0, 6, 0, 8, 2, 3, 6, - 0, 0, 0, -7, 0, 0, 0, 0, - 1, -1, 0, 1, -3, -2, -4, 1, - 0, -2, 0, 0, 0, -8, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, -12, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, -11, 0, -12, 0, 0, 0, - 0, -1, 0, 19, -2, -2, 2, 2, - -2, 0, -2, 2, 0, 0, -10, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -19, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, -12, 0, 12, 0, 0, -7, 0, - 6, 0, -13, -19, -13, -4, 6, 0, - 0, -13, 0, 2, -4, 0, -3, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 5, 6, -23, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 0, 1, 0, 0, 0, - 0, 0, 1, 1, -2, -4, 0, -1, - -1, -2, 0, 0, -1, 0, 0, 0, - -4, 0, -2, 0, -4, -4, 0, -5, - -6, -6, -4, 0, -4, 0, -4, 0, - 0, 0, 0, -2, 0, 0, 2, 0, - 1, -2, 0, 1, 0, 0, 0, 2, - -1, 0, 0, 0, -1, 2, 2, -1, - 0, 0, 0, -4, 0, -1, 0, 0, - 0, 0, 0, 1, 0, 2, -1, 0, - -2, 0, -3, 0, 0, -1, 0, 6, - 0, 0, -2, 0, 0, 0, 0, 0, - -1, 1, -1, -1, 0, 0, -2, 0, - -2, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, -1, 0, -2, -2, 0, - 0, 0, 0, 0, 1, 0, 0, -1, - 0, -2, -2, -2, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -1, 0, 0, - 0, 0, -1, -2, 0, -3, 0, -6, - -1, -6, 4, 0, 0, -4, 2, 4, - 5, 0, -5, -1, -2, 0, -1, -9, - 2, -1, 1, -10, 2, 0, 0, 1, - -10, 0, -10, -2, -17, -1, 0, -10, - 0, 4, 5, 0, 2, 0, 0, 0, - 0, 0, 0, -3, -2, 0, -6, 0, - 0, 0, -2, 0, 0, 0, -2, 0, - 0, 0, 0, 0, -1, -1, 0, -1, - -2, 0, 0, 0, 0, 0, 0, 0, - -2, -2, 0, -1, -2, -2, 0, 0, - -2, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -2, -2, 0, -2, - 0, -1, 0, -4, 2, 0, 0, -2, - 1, 2, 2, 0, 0, 0, 0, 0, - 0, -1, 0, 0, 0, 0, 0, 1, - 0, 0, -2, 0, -2, -1, -2, 0, - 0, 0, 0, 0, 0, 0, 2, 0, - -2, 0, 0, 0, 0, -2, -3, 0, - -4, 0, 6, -1, 1, -6, 0, 0, - 5, -10, -10, -8, -4, 2, 0, -2, - -12, -3, 0, -3, 0, -4, 3, -3, - -12, 0, -5, 0, 0, 1, -1, 2, - -1, 0, 2, 0, -6, -7, 0, -10, - -5, -4, -5, -6, -2, -5, 0, -4, - -5, 1, 0, 1, 0, -2, 0, 0, - 0, 1, 0, 2, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -2, - 0, -1, 0, -1, -2, 0, -3, -4, - -4, -1, 0, -6, 0, 0, 0, 0, - 0, 0, -2, 0, 0, 0, 0, 1, - -1, 0, 0, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, - -2, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -3, 0, 2, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -1, 0, 0, 0, - -4, 0, 0, 0, 0, -10, -6, 0, - 0, 0, -3, -10, 0, 0, -2, 2, - 0, -5, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -3, 0, 0, -4, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 0, -3, 0, - 0, 0, 0, 2, 0, 1, -4, -4, - 0, -2, -2, -2, 0, 0, 0, 0, - 0, 0, -6, 0, -2, 0, -3, -2, - 0, -4, -5, -6, -2, 0, -4, 0, - -6, 0, 0, 0, 0, 15, 0, 0, - 1, 0, 0, -2, 0, 2, 0, -8, - 0, 0, 0, 0, 0, -18, -3, 6, - 6, -2, -8, 0, 2, -3, 0, -10, - -1, -2, 2, -13, -2, 2, 0, 3, - -7, -3, -7, -6, -8, 0, 0, -12, - 0, 11, 0, 0, -1, 0, 0, 0, - -1, -1, -2, -5, -6, 0, -18, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, -2, 0, -1, -2, -3, 0, 0, - -4, 0, -2, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, -4, 0, 0, 4, - -1, 2, 0, -4, 2, -1, -1, -5, - -2, 0, -2, -2, -1, 0, -3, -3, - 0, 0, -2, -1, -1, -3, -2, 0, - 0, -2, 0, 2, -1, 0, -4, 0, - 0, 0, -4, 0, -3, 0, -3, -3, - 2, 0, 0, 0, 0, 0, 0, 0, - 0, -4, 2, 0, -3, 0, -1, -2, - -6, -1, -1, -1, -1, -1, -2, -1, - 0, 0, 0, 0, 0, -2, -2, -2, - 0, 0, 0, 0, 2, -1, 0, -1, - 0, 0, 0, -1, -2, -1, -2, -2, - -2, 0, 2, 8, -1, 0, -5, 0, - -1, 4, 0, -2, -8, -2, 3, 0, - 0, -9, -3, 2, -3, 1, 0, -1, - -2, -6, 0, -3, 1, 0, 0, -3, - 0, 0, 0, 2, 2, -4, -4, 0, - -3, -2, -3, -2, -2, 0, -3, 1, - -4, -3, 6, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -3, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - -1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -2, -2, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -3, 0, 0, -2, - 0, 0, -2, -2, 0, 0, 0, 0, - -2, 0, 0, 0, 0, -1, 0, 0, - 0, 0, 0, -1, 0, 0, 0, 0, - -3, 0, -4, 0, 0, 0, -6, 0, - 1, -4, 4, 0, -1, -9, 0, 0, - -4, -2, 0, -8, -5, -5, 0, 0, - -8, -2, -8, -7, -9, 0, -5, 0, - 2, 13, -2, 0, -4, -2, -1, -2, - -3, -5, -3, -7, -8, -4, -2, 0, - 0, -1, 0, 1, 0, 0, -13, -2, - 6, 4, -4, -7, 0, 1, -6, 0, - -10, -1, -2, 4, -18, -2, 1, 0, - 0, -12, -2, -10, -2, -14, 0, 0, - -13, 0, 11, 1, 0, -1, 0, 0, - 0, 0, -1, -1, -7, -1, 0, -12, - 0, 0, 0, 0, -6, 0, -2, 0, - -1, -5, -9, 0, 0, -1, -3, -6, - -2, 0, -1, 0, 0, 0, 0, -9, - -2, -6, -6, -2, -3, -5, -2, -3, - 0, -4, -2, -6, -3, 0, -2, -4, - -2, -4, 0, 1, 0, -1, -6, 0, - 4, 0, -3, 0, 0, 0, 0, 2, - 0, 1, -4, 8, 0, -2, -2, -2, - 0, 0, 0, 0, 0, 0, -6, 0, - -2, 0, -3, -2, 0, -4, -5, -6, - -2, 0, -4, 2, 8, 0, 0, 0, - 0, 15, 0, 0, 1, 0, 0, -2, - 0, 2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - -1, -4, 0, 0, 0, 0, 0, -1, - 0, 0, 0, -2, -2, 0, 0, -4, - -2, 0, 0, -4, 0, 3, -1, 0, - 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 3, 4, 2, -2, 0, -6, - -3, 0, 6, -6, -6, -4, -4, 8, - 3, 2, -17, -1, 4, -2, 0, -2, - 2, -2, -7, 0, -2, 2, -2, -2, - -6, -2, 0, 0, 6, 4, 0, -5, - 0, -11, -2, 6, -2, -7, 1, -2, - -6, -6, -2, 8, 2, 0, -3, 0, - -5, 0, 2, 6, -4, -7, -8, -5, - 6, 0, 1, -14, -2, 2, -3, -1, - -4, 0, -4, -7, -3, -3, -2, 0, - 0, -4, -4, -2, 0, 6, 4, -2, - -11, 0, -11, -3, 0, -7, -11, -1, - -6, -3, -6, -5, 5, 0, 0, -2, - 0, -4, -2, 0, -2, -3, 0, 3, - -6, 2, 0, 0, -10, 0, -2, -4, - -3, -1, -6, -5, -6, -4, 0, -6, - -2, -4, -4, -6, -2, 0, 0, 1, - 9, -3, 0, -6, -2, 0, -2, -4, - -4, -5, -5, -7, -2, -4, 4, 0, - -3, 0, -10, -2, 1, 4, -6, -7, - -4, -6, 6, -2, 1, -18, -3, 4, - -4, -3, -7, 0, -6, -8, -2, -2, - -2, -2, -4, -6, -1, 0, 0, 6, - 5, -1, -12, 0, -12, -4, 5, -7, - -13, -4, -7, -8, -10, -6, 4, 0, - 0, 0, 0, -2, 0, 0, 2, -2, - 4, 1, -4, 4, 0, 0, -6, -1, - 0, -1, 0, 1, 1, -2, 0, 0, - 0, 0, 0, 0, -2, 0, 0, 0, - 0, 2, 6, 0, 0, -2, 0, 0, - 0, 0, -1, -1, -2, 0, 0, 0, - 1, 2, 0, 0, 0, 0, 2, 0, - -2, 0, 7, 0, 3, 1, 1, -2, - 0, 4, 0, 0, 0, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 6, 0, 5, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -12, 0, -2, 3, 0, 6, - 0, 0, 19, 2, -4, -4, 2, 2, - -1, 1, -10, 0, 0, 9, -12, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -13, 7, 27, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, -12, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -3, 0, 0, -4, - -2, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -1, 0, -5, 0, - 0, 1, 0, 0, 2, 25, -4, -2, - 6, 5, -5, 2, 0, 0, 2, 2, - -2, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -25, 5, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -5, - 0, 0, 0, -5, 0, 0, 0, 0, - -4, -1, 0, 0, 0, -4, 0, -2, - 0, -9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -13, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, - 0, -2, 0, 0, -4, 0, -3, 0, - -5, 0, 0, 0, -3, 2, -2, 0, - 0, -5, -2, -4, 0, 0, -5, 0, - -2, 0, -9, 0, -2, 0, 0, -16, - -4, -8, -2, -7, 0, 0, -13, 0, - -5, -1, 0, 0, 0, 0, 0, 0, - 0, 0, -3, -3, -2, -3, 0, 0, - 0, 0, -4, 0, -4, 2, -2, 4, - 0, -1, -4, -1, -3, -4, 0, -2, - -1, -1, 1, -5, -1, 0, 0, 0, - -17, -2, -3, 0, -4, 0, -1, -9, - -2, 0, 0, -1, -2, 0, 0, 0, - 0, 1, 0, -1, -3, -1, 3, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2, 0, 0, 0, 0, 0, - 0, -4, 0, -1, 0, 0, 0, -4, - 2, 0, 0, 0, -5, -2, -4, 0, - 0, -5, 0, -2, 0, -9, 0, 0, - 0, 0, -19, 0, -4, -7, -10, 0, - 0, -13, 0, -1, -3, 0, 0, 0, - 0, 0, 0, 0, 0, -2, -3, -1, - -3, 1, 0, 0, 3, -2, 0, 6, - 9, -2, -2, -6, 2, 9, 3, 4, - -5, 2, 8, 2, 6, 4, 5, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 12, 9, -3, -2, 0, -2, - 15, 8, 15, 0, 0, 0, 2, 0, - 0, 7, 0, 0, -3, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, 0, - 0, 0, 0, 0, 0, 0, 0, 3, - 0, 0, 0, 0, -16, -2, -2, -8, - -9, 0, 0, -13, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -1, - 0, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, -16, -2, -2, - -8, -9, 0, 0, -8, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - -2, 0, 0, 0, -4, 2, 0, -2, - 2, 3, 2, -6, 0, 0, -2, 2, - 0, 2, 0, 0, 0, 0, -5, 0, - -2, -1, -4, 0, -2, -8, 0, 12, - -2, 0, -4, -1, 0, -1, -3, 0, - -2, -5, -4, -2, 0, 0, 0, -3, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, -1, 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, 0, -16, - -2, -2, -8, -9, 0, 0, -13, 0, - 0, 0, 0, 0, 0, 10, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - -3, 0, -6, -2, -2, 6, -2, -2, - -8, 1, -1, 1, -1, -5, 0, 4, - 0, 2, 1, 2, -5, -8, -2, 0, - -7, -4, -5, -8, -7, 0, -3, -4, - -2, -2, -2, -1, -2, -1, 0, -1, - -1, 3, 0, 3, -1, 0, 6, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -1, -2, -2, 0, 0, - -5, 0, -1, 0, -3, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - -12, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -2, -2, 0, -2, - 0, 0, 0, 0, -2, 0, 0, -3, - -2, 2, 0, -3, -4, -1, 0, -6, - -1, -4, -1, -2, 0, -3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, -13, 0, 6, 0, 0, -3, 0, - 0, 0, 0, -2, 0, -2, 0, 0, - -1, 0, 0, -1, 0, -4, 0, 0, - 8, -2, -6, -6, 1, 2, 2, 0, - -5, 1, 3, 1, 6, 1, 6, -1, - -5, 0, 0, -8, 0, 0, -6, -5, - 0, 0, -4, 0, -2, -3, 0, -3, - 0, -3, 0, -1, 3, 0, -2, -6, - -2, 7, 0, 0, -2, 0, -4, 0, - 0, 2, -4, 0, 2, -2, 2, 0, - 0, -6, 0, -1, -1, 0, -2, 2, - -2, 0, 0, 0, -8, -2, -4, 0, - -6, 0, 0, -9, 0, 7, -2, 0, - -3, 0, 1, 0, -2, 0, -2, -6, - 0, -2, 2, 0, 0, 0, 0, -1, - 0, 0, 2, -2, 1, 0, 0, -2, - -1, 0, -2, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -12, 0, 4, 0, - 0, -2, 0, 0, 0, 0, 0, 0, - -2, -2, 0, 0, 0, 4, 0, 4, - 0, 0, 0, 0, 0, -12, -11, 1, - 8, 6, 3, -8, 1, 8, 0, 7, - 0, 4, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 10, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 -}; - - -/*Collect the kern class' data in one place*/ -static const lv_font_fmt_txt_kern_classes_t kern_classes = { - .class_pair_values = kern_class_values, - .left_class_mapping = kern_left_class_mapping, - .right_class_mapping = kern_right_class_mapping, - .left_class_cnt = 61, - .right_class_cnt = 49, -}; - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LV_VERSION_CHECK(8, 0, 0) -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = &kern_classes, - .kern_scale = 16, - .cmap_num = 2, - .bpp = 4, - .kern_classes = 1, - .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; - - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) -const lv_font_t lv_font_montserrat_12_subpx = { -#else -lv_font_t lv_font_montserrat_12_subpx = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 15, /*The maximum line height required by the font*/ - .base_line = 3, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_HOR, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = -1, - .underline_thickness = 1, -#endif - .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -}; - - - -#endif /*#if LV_FONT_MONTSERRAT_12_SUBPX*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_14.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_14.c index cc4da9525..2ba984ee0 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_14.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_14.c @@ -1510,7 +1510,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -1707,7 +1706,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -2134,7 +2132,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -2148,9 +2145,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -2164,18 +2161,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_14 = { #else lv_font_t lv_font_montserrat_14 = { @@ -2194,7 +2188,4 @@ lv_font_t lv_font_montserrat_14 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_14*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_16.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_16.c index 2b0dccf92..36cdea4ee 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_16.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_16.c @@ -1779,7 +1779,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -1976,7 +1975,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -2403,7 +2401,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -2417,9 +2414,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -2433,18 +2430,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_16 = { #else lv_font_t lv_font_montserrat_16 = { @@ -2463,7 +2457,4 @@ lv_font_t lv_font_montserrat_16 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_16*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_18.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_18.c index c2e5d1de7..de7339039 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_18.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_18.c @@ -2179,7 +2179,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -2376,7 +2375,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -2803,7 +2801,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -2817,9 +2814,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -2833,18 +2830,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_18 = { #else lv_font_t lv_font_montserrat_18 = { @@ -2863,7 +2857,4 @@ lv_font_t lv_font_montserrat_18 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_18*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_20.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_20.c index bf1163900..de7e49db4 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_20.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_20.c @@ -2536,7 +2536,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -2733,7 +2732,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -3160,7 +3158,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -3174,9 +3171,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -3190,18 +3187,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_20 = { #else lv_font_t lv_font_montserrat_20 = { @@ -3220,7 +3214,4 @@ lv_font_t lv_font_montserrat_20 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_20*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_22.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_22.c index d96a666a0..33907436c 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_22.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_22.c @@ -2965,7 +2965,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -3162,7 +3161,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -3589,7 +3587,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -3603,9 +3600,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -3619,18 +3616,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_22 = { #else lv_font_t lv_font_montserrat_22 = { @@ -3649,7 +3643,4 @@ lv_font_t lv_font_montserrat_22 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_22*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_24.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_24.c index 9795f7031..ffb9c83f0 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_24.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_24.c @@ -3376,7 +3376,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -3573,7 +3572,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -4000,7 +3998,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -4014,9 +4011,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -4030,18 +4027,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_24 = { #else lv_font_t lv_font_montserrat_24 = { @@ -4060,7 +4054,4 @@ lv_font_t lv_font_montserrat_24 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_24*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_26.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_26.c index 416d84062..93d4f71f8 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_26.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_26.c @@ -3911,7 +3911,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -4108,7 +4107,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -4535,7 +4533,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -4549,9 +4546,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -4565,18 +4562,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_26 = { #else lv_font_t lv_font_montserrat_26 = { @@ -4595,7 +4589,4 @@ lv_font_t lv_font_montserrat_26 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_26*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_28.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_28.c index 0ae2d7eec..a1867474a 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_28.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_28.c @@ -4460,7 +4460,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0, 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -4657,7 +4656,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -5084,7 +5082,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -5098,9 +5095,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -5114,18 +5111,14 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif }; - /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_28 = { #else lv_font_t lv_font_montserrat_28 = { @@ -5144,7 +5137,4 @@ lv_font_t lv_font_montserrat_28 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_28*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_28_compressed.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_28_compressed.c index 461258488..170ab48e0 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_28_compressed.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_28_compressed.c @@ -2590,7 +2590,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0xff, 0x3a, 0xba, 0x40, 0x3f, 0xf9, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -2787,7 +2786,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -3214,7 +3212,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -3228,9 +3225,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -3244,18 +3241,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 1, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_28_compressed = { #else lv_font_t lv_font_montserrat_28_compressed = { @@ -3274,7 +3268,4 @@ lv_font_t lv_font_montserrat_28_compressed = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_28_COMPRESSED*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_30.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_30.c index f5532b399..30e48eb57 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_30.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_30.c @@ -5042,7 +5042,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -5239,7 +5238,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -5666,7 +5664,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -5680,9 +5677,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -5696,18 +5693,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_30 = { #else lv_font_t lv_font_montserrat_30 = { @@ -5726,7 +5720,4 @@ lv_font_t lv_font_montserrat_30 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_30*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_32.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_32.c index f4dad0c96..a12a49c6a 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_32.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_32.c @@ -5531,7 +5531,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -5728,7 +5727,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -6155,7 +6153,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -6169,9 +6166,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -6185,18 +6182,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_32 = { #else lv_font_t lv_font_montserrat_32 = { @@ -6215,7 +6209,4 @@ lv_font_t lv_font_montserrat_32 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_32*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_34.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_34.c index 064bb0a1e..7577c7343 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_34.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_34.c @@ -6330,7 +6330,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -6527,7 +6526,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -6954,7 +6952,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -6968,9 +6965,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -6984,18 +6981,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_34 = { #else lv_font_t lv_font_montserrat_34 = { @@ -7014,7 +7008,4 @@ lv_font_t lv_font_montserrat_34 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_34*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_36.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_36.c index e5b2b6860..f5ef2ec02 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_36.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_36.c @@ -6974,7 +6974,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -7171,7 +7170,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -7598,7 +7596,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -7612,9 +7609,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -7628,18 +7625,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_36 = { #else lv_font_t lv_font_montserrat_36 = { @@ -7658,7 +7652,4 @@ lv_font_t lv_font_montserrat_36 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_36*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_38.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_38.c index 883eae55c..992b5c65f 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_38.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_38.c @@ -7719,7 +7719,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -7916,7 +7915,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -8343,7 +8341,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -8357,9 +8354,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -8373,18 +8370,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_38 = { #else lv_font_t lv_font_montserrat_38 = { @@ -8403,7 +8397,4 @@ lv_font_t lv_font_montserrat_38 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_38*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_40.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_40.c index 0769235e5..36c7d31de 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_40.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_40.c @@ -8567,7 +8567,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0, 0x0, 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -8764,7 +8763,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -9191,7 +9189,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -9205,9 +9202,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -9221,18 +9218,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_40 = { #else lv_font_t lv_font_montserrat_40 = { @@ -9251,7 +9245,4 @@ lv_font_t lv_font_montserrat_40 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_40*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_42.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_42.c index a6563932c..71fdd9311 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_42.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_42.c @@ -9409,7 +9409,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -9606,7 +9605,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -10033,7 +10031,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -10047,9 +10044,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -10063,18 +10060,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_42 = { #else lv_font_t lv_font_montserrat_42 = { @@ -10093,7 +10087,4 @@ lv_font_t lv_font_montserrat_42 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_42*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_44.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_44.c index 4156909d6..07071531e 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_44.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_44.c @@ -10235,7 +10235,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0, 0x0, 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -10432,7 +10431,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -10859,7 +10857,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -10873,9 +10870,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -10889,18 +10886,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_44 = { #else lv_font_t lv_font_montserrat_44 = { @@ -10919,7 +10913,4 @@ lv_font_t lv_font_montserrat_44 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_44*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_46.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_46.c index 745b42c2e..48fa6875c 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_46.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_46.c @@ -11187,7 +11187,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -11384,7 +11383,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -11811,7 +11809,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -11825,9 +11822,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -11841,18 +11838,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_46 = { #else lv_font_t lv_font_montserrat_46 = { @@ -11871,7 +11865,4 @@ lv_font_t lv_font_montserrat_46 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_46*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_48.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_48.c index 9961b8368..1f731ac67 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_48.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_48.c @@ -11888,7 +11888,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -12085,7 +12084,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -12512,7 +12510,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -12526,9 +12523,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -12542,18 +12539,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_48 = { #else lv_font_t lv_font_montserrat_48 = { @@ -12572,7 +12566,4 @@ lv_font_t lv_font_montserrat_48 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_48*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_8.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_8.c index 390333288..698579249 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_8.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_montserrat_8.c @@ -759,7 +759,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x0, 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -956,7 +955,6 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { * KERNING *----------------*/ - /*Map glyph_ids to kern left classes*/ static const uint8_t kern_left_class_mapping[] = { 0, 0, 1, 2, 0, 3, 4, 5, @@ -1383,7 +1381,6 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0 }; - /*Collect the kern class' data in one place*/ static const lv_font_fmt_txt_kern_classes_t kern_classes = { .class_pair_values = kern_class_values, @@ -1397,9 +1394,9 @@ static const lv_font_fmt_txt_kern_classes_t kern_classes = { * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -1413,18 +1410,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 1, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_montserrat_8 = { #else lv_font_t lv_font_montserrat_8 = { @@ -1443,7 +1437,4 @@ lv_font_t lv_font_montserrat_8 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_MONTSERRAT_8*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_simsun_16_cjk.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_simsun_16_cjk.c index bcd7c14c4..d79105891 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_simsun_16_cjk.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_simsun_16_cjk.c @@ -22100,7 +22100,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0x2f, 0xdd, 0xdd, 0x80, 0x0, 0x0, 0x0, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -23723,15 +23722,13 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { } }; - - /*-------------------- * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -23745,18 +23742,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 4, .kern_classes = 0, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_simsun_16_cjk = { #else lv_font_t lv_font_simsun_16_cjk = { @@ -23775,7 +23769,4 @@ lv_font_t lv_font_simsun_16_cjk = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_SIMSUN_16_CJK*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_unscii_16.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_unscii_16.c index d6b0eaa17..b95d51aed 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_unscii_16.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_unscii_16.c @@ -475,7 +475,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0xc0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -584,8 +583,6 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { * CHARACTER MAPPING *--------------------*/ - - /*Collect the unicode lists and glyph_id offsets*/ static const lv_font_fmt_txt_cmap_t cmaps[] = { { @@ -594,15 +591,13 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { } }; - - /*-------------------- * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -616,18 +611,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 1, .kern_classes = 0, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_unscii_16 = { #else lv_font_t lv_font_unscii_16 = { @@ -646,7 +638,4 @@ lv_font_t lv_font_unscii_16 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_UNSCII_16*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_unscii_8.c b/lib/libesp32_lvgl/lvgl/src/font/lv_font_unscii_8.c index 1b03c8576..26b92fbbf 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_unscii_8.c +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_font_unscii_8.c @@ -311,7 +311,6 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0xc1, 0x42, 0xbd, 0x2c, 0x40, 0x81, 0x0 }; - /*--------------------- * GLYPH DESCRIPTION *--------------------*/ @@ -420,8 +419,6 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { * CHARACTER MAPPING *--------------------*/ - - /*Collect the unicode lists and glyph_id offsets*/ static const lv_font_fmt_txt_cmap_t cmaps[] = { { @@ -430,15 +427,13 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { } }; - - /*-------------------- * ALL CUSTOM DATA *--------------------*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 /*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; + static const lv_font_fmt_txt_dsc_t font_dsc = { #else static lv_font_fmt_txt_dsc_t font_dsc = { @@ -452,18 +447,15 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .bpp = 1, .kern_classes = 0, .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; +}; /*----------------- * PUBLIC FONT *----------------*/ /*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) +#if LVGL_VERSION_MAJOR >= 8 const lv_font_t lv_font_unscii_8 = { #else lv_font_t lv_font_unscii_8 = { @@ -482,7 +474,4 @@ lv_font_t lv_font_unscii_8 = { .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ }; - - #endif /*#if LV_FONT_UNSCII_8*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_symbol_def.h b/lib/libesp32_lvgl/lvgl/src/font/lv_symbol_def.h index 696daf189..7c2365869 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_symbol_def.h +++ b/lib/libesp32_lvgl/lvgl/src/font/lv_symbol_def.h @@ -31,7 +31,6 @@ extern "C" { * If they are not predefined, they will use the following values */ - #if !defined LV_SYMBOL_AUDIO #define LV_SYMBOL_AUDIO "\xEF\x80\x81" /*61441, 0xF001*/ #endif diff --git a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal.h b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal.h deleted file mode 100644 index 167da1f4b..000000000 --- a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @file lv_hal.h - * - */ - -#ifndef LV_HAL_H -#define LV_HAL_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "lv_hal_disp.h" -#include "lv_hal_indev.h" -#include "lv_hal_tick.h" - -/********************* - * DEFINES - *********************/ -/** - * Same as Android's DIP. (Different name is chosen to avoid mistype between LV_DPI and LV_DIP) - * 1 dip is 1 px on a 160 DPI screen - * 1 dip is 2 px on a 320 DPI screen - * https://stackoverflow.com/questions/2025282/what-is-the-difference-between-px-dip-dp-and-sp - */ -#define _LV_DPX_CALC(dpi, n) ((n) == 0 ? 0 :LV_MAX((( (dpi) * (n) + 80) / 160), 1)) /*+80 for rounding*/ -#define LV_DPX(n) _LV_DPX_CALC(lv_disp_get_dpi(NULL), n) - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal.mk b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal.mk deleted file mode 100644 index c35ec2d7a..000000000 --- a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal.mk +++ /dev/null @@ -1,8 +0,0 @@ -CSRCS += lv_hal_disp.c -CSRCS += lv_hal_indev.c -CSRCS += lv_hal_tick.c - -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/hal -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/hal - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/hal" diff --git a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.c b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.c deleted file mode 100644 index 6f1c9626d..000000000 --- a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.c +++ /dev/null @@ -1,720 +0,0 @@ -/** - * @file lv_hal_disp.c - * - * @description HAL layer for display driver - * - */ - -/********************* - * INCLUDES - *********************/ -#include -#include -#include "lv_hal.h" -#include "../misc/lv_mem.h" -#include "../misc/lv_gc.h" -#include "../misc/lv_assert.h" -#include "../core/lv_obj.h" -#include "../core/lv_refr.h" -#include "../core/lv_theme.h" -#include "../draw/sdl/lv_draw_sdl.h" -#include "../draw/sw/lv_draw_sw.h" -#include "../draw/sdl/lv_draw_sdl.h" -#include "../draw/stm32_dma2d/lv_gpu_stm32_dma2d.h" -#include "../draw/swm341_dma2d/lv_gpu_swm341_dma2d.h" -#include "../draw/arm2d/lv_gpu_arm2d.h" -#include "../draw/nxp/vglite/lv_draw_vglite.h" -#include "../draw/nxp/pxp/lv_draw_pxp.h" -#include "../draw/renesas/lv_gpu_d2_ra6m3.h" - -#if LV_USE_THEME_DEFAULT - #include "../extra/themes/default/lv_theme_default.h" -#endif - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static lv_obj_tree_walk_res_t invalidate_layout_cb(lv_obj_t * obj, void * user_data); - -static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, - lv_coord_t y, - lv_color_t color, lv_opa_t opa); - -static void set_px_cb_alpha1(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa); - -static void set_px_cb_alpha2(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa); - -static void set_px_cb_alpha4(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa); - -static void set_px_cb_alpha8(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa); - -static void set_px_alpha_generic(lv_img_dsc_t * d, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa); - -/********************** - * STATIC VARIABLES - **********************/ -static lv_disp_t * disp_def; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Initialize a display driver with default values. - * It is used to surly have known values in the fields ant not memory junk. - * After it you can set the fields. - * @param driver pointer to driver variable to initialize - */ -void lv_disp_drv_init(lv_disp_drv_t * driver) -{ - lv_memset_00(driver, sizeof(lv_disp_drv_t)); - - driver->hor_res = 320; - driver->ver_res = 240; - driver->physical_hor_res = -1; - driver->physical_ver_res = -1; - driver->offset_x = 0; - driver->offset_y = 0; - driver->antialiasing = LV_COLOR_DEPTH > 8 ? 1 : 0; - driver->screen_transp = 0; - driver->dpi = LV_DPI_DEF; - driver->color_chroma_key = LV_COLOR_CHROMA_KEY; - -#if LV_USE_GPU_RA6M3_G2D - driver->draw_ctx_init = lv_draw_ra6m3_2d_ctx_init; - driver->draw_ctx_deinit = lv_draw_ra6m3_2d_ctx_init; - driver->draw_ctx_size = sizeof(lv_draw_ra6m3_dma2d_ctx_t); -#elif LV_USE_GPU_STM32_DMA2D - driver->draw_ctx_init = lv_draw_stm32_dma2d_ctx_init; - driver->draw_ctx_deinit = lv_draw_stm32_dma2d_ctx_init; - driver->draw_ctx_size = sizeof(lv_draw_stm32_dma2d_ctx_t); -#elif LV_USE_GPU_SWM341_DMA2D - driver->draw_ctx_init = lv_draw_swm341_dma2d_ctx_init; - driver->draw_ctx_deinit = lv_draw_swm341_dma2d_ctx_init; - driver->draw_ctx_size = sizeof(lv_draw_swm341_dma2d_ctx_t); -#elif LV_USE_GPU_NXP_VG_LITE - driver->draw_ctx_init = lv_draw_vglite_ctx_init; - driver->draw_ctx_deinit = lv_draw_vglite_ctx_deinit; - driver->draw_ctx_size = sizeof(lv_draw_vglite_ctx_t); -#elif LV_USE_GPU_NXP_PXP - driver->draw_ctx_init = lv_draw_pxp_ctx_init; - driver->draw_ctx_deinit = lv_draw_pxp_ctx_deinit; - driver->draw_ctx_size = sizeof(lv_draw_pxp_ctx_t); -#elif LV_USE_GPU_SDL - driver->draw_ctx_init = lv_draw_sdl_init_ctx; - driver->draw_ctx_deinit = lv_draw_sdl_deinit_ctx; - driver->draw_ctx_size = sizeof(lv_draw_sdl_ctx_t); -#elif LV_USE_GPU_ARM2D - driver->draw_ctx_init = lv_draw_arm2d_ctx_init; - driver->draw_ctx_deinit = lv_draw_arm2d_ctx_init; - driver->draw_ctx_size = sizeof(lv_draw_arm2d_ctx_t); -#else - driver->draw_ctx_init = lv_draw_sw_init_ctx; - driver->draw_ctx_deinit = lv_draw_sw_init_ctx; - driver->draw_ctx_size = sizeof(lv_draw_sw_ctx_t); -#endif - -} - -/** - * Initialize a display buffer - * @param draw_buf pointer `lv_disp_draw_buf_t` variable to initialize - * @param buf1 A buffer to be used by LVGL to draw the image. - * Always has to specified and can't be NULL. - * Can be an array allocated by the user. E.g. `static lv_color_t disp_buf1[1024 * 10]` - * Or a memory address e.g. in external SRAM - * @param buf2 Optionally specify a second buffer to make image rendering and image flushing - * (sending to the display) parallel. - * In the `disp_drv->flush` you should use DMA or similar hardware to send - * the image to the display in the background. - * It lets LVGL to render next frame into the other buffer while previous is being - * sent. Set to `NULL` if unused. - * @param size_in_px_cnt size of the `buf1` and `buf2` in pixel count. - */ -void lv_disp_draw_buf_init(lv_disp_draw_buf_t * draw_buf, void * buf1, void * buf2, uint32_t size_in_px_cnt) -{ - lv_memset_00(draw_buf, sizeof(lv_disp_draw_buf_t)); - - draw_buf->buf1 = buf1; - draw_buf->buf2 = buf2; - draw_buf->buf_act = draw_buf->buf1; - draw_buf->size = size_in_px_cnt; -} - -/** - * Register an initialized display driver. - * Automatically set the first display as active. - * @param driver pointer to an initialized 'lv_disp_drv_t' variable. Only its pointer is saved! - * @return pointer to the new display or NULL on error - */ -lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver) -{ - lv_disp_t * disp = _lv_ll_ins_head(&LV_GC_ROOT(_lv_disp_ll)); - LV_ASSERT_MALLOC(disp); - if(!disp) { - return NULL; - } - - /*Create a draw context if not created yet*/ - if(driver->draw_ctx == NULL) { - lv_draw_ctx_t * draw_ctx = lv_mem_alloc(driver->draw_ctx_size); - LV_ASSERT_MALLOC(draw_ctx); - if(draw_ctx == NULL) return NULL; - driver->draw_ctx_init(driver, draw_ctx); - driver->draw_ctx = draw_ctx; - } - - lv_memset_00(disp, sizeof(lv_disp_t)); - - disp->driver = driver; - - disp->inv_en_cnt = 1; - - _lv_ll_init(&disp->sync_areas, sizeof(lv_area_t)); - - lv_disp_t * disp_def_tmp = disp_def; - disp_def = disp; /*Temporarily change the default screen to create the default screens on the - new display*/ - /*Create a refresh timer*/ - disp->refr_timer = lv_timer_create(_lv_disp_refr_timer, LV_DISP_DEF_REFR_PERIOD, disp); - LV_ASSERT_MALLOC(disp->refr_timer); - if(disp->refr_timer == NULL) { - lv_mem_free(disp); - return NULL; - } - - if(driver->full_refresh && driver->draw_buf->size < (uint32_t)driver->hor_res * driver->ver_res) { - driver->full_refresh = 0; - LV_LOG_WARN("full_refresh requires at least screen sized draw buffer(s)"); - } - - disp->bg_color = lv_color_white(); -#if LV_COLOR_SCREEN_TRANSP - disp->bg_opa = LV_OPA_TRANSP; -#else - disp->bg_opa = LV_OPA_COVER; -#endif - -#if LV_USE_THEME_DEFAULT - if(lv_theme_default_is_inited() == false) { - disp->theme = lv_theme_default_init(disp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), - LV_THEME_DEFAULT_DARK, LV_FONT_DEFAULT); - } - else { - disp->theme = lv_theme_default_get(); - } -#endif - - disp->act_scr = lv_obj_create(NULL); /*Create a default screen on the display*/ - disp->top_layer = lv_obj_create(NULL); /*Create top layer on the display*/ - disp->sys_layer = lv_obj_create(NULL); /*Create sys layer on the display*/ - lv_obj_remove_style_all(disp->top_layer); - lv_obj_remove_style_all(disp->sys_layer); - lv_obj_clear_flag(disp->top_layer, LV_OBJ_FLAG_CLICKABLE); - lv_obj_clear_flag(disp->sys_layer, LV_OBJ_FLAG_CLICKABLE); - - lv_obj_set_scrollbar_mode(disp->top_layer, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_scrollbar_mode(disp->sys_layer, LV_SCROLLBAR_MODE_OFF); - - lv_obj_invalidate(disp->act_scr); - - disp_def = disp_def_tmp; /*Revert the default display*/ - if(disp_def == NULL) disp_def = disp; /*Initialize the default display*/ - - lv_timer_ready(disp->refr_timer); /*Be sure the screen will be refreshed immediately on start up*/ - - return disp; -} - -/** - * Update the driver in run time. - * @param disp pointer to a display. (return value of `lv_disp_drv_register`) - * @param new_drv pointer to the new driver - */ -void lv_disp_drv_update(lv_disp_t * disp, lv_disp_drv_t * new_drv) -{ - disp->driver = new_drv; - - if(disp->driver->full_refresh && - disp->driver->draw_buf->size < (uint32_t)disp->driver->hor_res * disp->driver->ver_res) { - disp->driver->full_refresh = 0; - LV_LOG_WARN("full_refresh requires at least screen sized draw buffer(s)"); - } - - lv_coord_t w = lv_disp_get_hor_res(disp); - lv_coord_t h = lv_disp_get_ver_res(disp); - uint32_t i; - for(i = 0; i < disp->screen_cnt; i++) { - lv_area_t prev_coords; - lv_obj_get_coords(disp->screens[i], &prev_coords); - lv_area_set_width(&disp->screens[i]->coords, w); - lv_area_set_height(&disp->screens[i]->coords, h); - lv_event_send(disp->screens[i], LV_EVENT_SIZE_CHANGED, &prev_coords); - } - - /* - * This method is usually called upon orientation change, thus the screen is now a - * different size. - * The object invalidated its previous area. That area is now out of the screen area - * so we reset all invalidated areas and invalidate the active screen's new area only. - */ - lv_memset_00(disp->inv_areas, sizeof(disp->inv_areas)); - lv_memset_00(disp->inv_area_joined, sizeof(disp->inv_area_joined)); - disp->inv_p = 0; - if(disp->act_scr != NULL) lv_obj_invalidate(disp->act_scr); - - lv_obj_tree_walk(NULL, invalidate_layout_cb, NULL); - - if(disp->driver->drv_update_cb) disp->driver->drv_update_cb(disp->driver); -} - -/** - * Remove a display - * @param disp pointer to display - */ -void lv_disp_remove(lv_disp_t * disp) -{ - bool was_default = false; - if(disp == lv_disp_get_default()) was_default = true; - - /*Detach the input devices*/ - lv_indev_t * indev; - indev = lv_indev_get_next(NULL); - while(indev) { - if(indev->driver->disp == disp) { - indev->driver->disp = NULL; - } - indev = lv_indev_get_next(indev); - } - - /** delete screen and other obj */ - if(disp->sys_layer) { - lv_obj_del(disp->sys_layer); - disp->sys_layer = NULL; - } - if(disp->top_layer) { - lv_obj_del(disp->top_layer); - disp->top_layer = NULL; - } - while(disp->screen_cnt != 0) { - /*Delete the screenst*/ - lv_obj_del(disp->screens[0]); - } - - _lv_ll_remove(&LV_GC_ROOT(_lv_disp_ll), disp); - _lv_ll_clear(&disp->sync_areas); - if(disp->refr_timer) lv_timer_del(disp->refr_timer); - lv_mem_free(disp); - - if(was_default) lv_disp_set_default(_lv_ll_get_head(&LV_GC_ROOT(_lv_disp_ll))); -} - -/** - * Set a default display. The new screens will be created on it by default. - * @param disp pointer to a display - */ -void lv_disp_set_default(lv_disp_t * disp) -{ - disp_def = disp; -} - -/** - * Get the default display - * @return pointer to the default display - */ -lv_disp_t * lv_disp_get_default(void) -{ - return disp_def; -} - -/** - * Get the horizontal resolution of a display - * @param disp pointer to a display (NULL to use the default display) - * @return the horizontal resolution of the display - */ -lv_coord_t lv_disp_get_hor_res(lv_disp_t * disp) -{ - if(disp == NULL) disp = lv_disp_get_default(); - - if(disp == NULL) { - return 0; - } - else { - switch(disp->driver->rotated) { - case LV_DISP_ROT_90: - case LV_DISP_ROT_270: - return disp->driver->ver_res; - default: - return disp->driver->hor_res; - } - } -} - -/** - * Get the vertical resolution of a display - * @param disp pointer to a display (NULL to use the default display) - * @return the vertical resolution of the display - */ -lv_coord_t lv_disp_get_ver_res(lv_disp_t * disp) -{ - if(disp == NULL) disp = lv_disp_get_default(); - - if(disp == NULL) { - return 0; - } - else { - switch(disp->driver->rotated) { - case LV_DISP_ROT_90: - case LV_DISP_ROT_270: - return disp->driver->hor_res; - default: - return disp->driver->ver_res; - } - } -} - -/** - * Get the full / physical horizontal resolution of a display - * @param disp pointer to a display (NULL to use the default display) - * @return the full / physical horizontal resolution of the display - */ -lv_coord_t lv_disp_get_physical_hor_res(lv_disp_t * disp) -{ - if(disp == NULL) disp = lv_disp_get_default(); - - if(disp == NULL) { - return 0; - } - else { - switch(disp->driver->rotated) { - case LV_DISP_ROT_90: - case LV_DISP_ROT_270: - return disp->driver->physical_ver_res > 0 ? disp->driver->physical_ver_res : disp->driver->ver_res; - default: - return disp->driver->physical_hor_res > 0 ? disp->driver->physical_hor_res : disp->driver->hor_res; - } - } -} - -/** - * Get the full / physical vertical resolution of a display - * @param disp pointer to a display (NULL to use the default display) - * @return the full / physical vertical resolution of the display - */ -lv_coord_t lv_disp_get_physical_ver_res(lv_disp_t * disp) -{ - if(disp == NULL) disp = lv_disp_get_default(); - - if(disp == NULL) { - return 0; - } - else { - switch(disp->driver->rotated) { - case LV_DISP_ROT_90: - case LV_DISP_ROT_270: - return disp->driver->physical_hor_res > 0 ? disp->driver->physical_hor_res : disp->driver->hor_res; - default: - return disp->driver->physical_ver_res > 0 ? disp->driver->physical_ver_res : disp->driver->ver_res; - } - } -} - -/** - * Get the horizontal offset from the full / physical display - * @param disp pointer to a display (NULL to use the default display) - * @return the horizontal offset from the full / physical display - */ -lv_coord_t lv_disp_get_offset_x(lv_disp_t * disp) -{ - if(disp == NULL) disp = lv_disp_get_default(); - - if(disp == NULL) { - return 0; - } - else { - switch(disp->driver->rotated) { - case LV_DISP_ROT_90: - return disp->driver->offset_y; - case LV_DISP_ROT_180: - return lv_disp_get_physical_hor_res(disp) - disp->driver->offset_x; - case LV_DISP_ROT_270: - return lv_disp_get_physical_hor_res(disp) - disp->driver->offset_y; - default: - return disp->driver->offset_x; - } - } -} - -/** - * Get the vertical offset from the full / physical display - * @param disp pointer to a display (NULL to use the default display) - * @return the horizontal offset from the full / physical display - */ -lv_coord_t lv_disp_get_offset_y(lv_disp_t * disp) -{ - if(disp == NULL) disp = lv_disp_get_default(); - - if(disp == NULL) { - return 0; - } - else { - switch(disp->driver->rotated) { - case LV_DISP_ROT_90: - return disp->driver->offset_x; - case LV_DISP_ROT_180: - return lv_disp_get_physical_ver_res(disp) - disp->driver->offset_y; - case LV_DISP_ROT_270: - return lv_disp_get_physical_ver_res(disp) - disp->driver->offset_x; - default: - return disp->driver->offset_y; - } - } -} - -/** - * Get if anti-aliasing is enabled for a display or not - * @param disp pointer to a display (NULL to use the default display) - * @return true: anti-aliasing is enabled; false: disabled - */ -bool lv_disp_get_antialiasing(lv_disp_t * disp) -{ - if(disp == NULL) disp = lv_disp_get_default(); - if(disp == NULL) return false; - - return disp->driver->antialiasing ? true : false; -} - -/** - * Get the DPI of the display - * @param disp pointer to a display (NULL to use the default display) - * @return dpi of the display - */ -lv_coord_t lv_disp_get_dpi(const lv_disp_t * disp) -{ - if(disp == NULL) disp = lv_disp_get_default(); - if(disp == NULL) return LV_DPI_DEF; /*Do not return 0 because it might be a divider*/ - return disp->driver->dpi; -} - -/** - * Call in the display driver's `flush_cb` function when the flushing is finished - * @param disp_drv pointer to display driver in `flush_cb` where this function is called - */ -void LV_ATTRIBUTE_FLUSH_READY lv_disp_flush_ready(lv_disp_drv_t * disp_drv) -{ - disp_drv->draw_buf->flushing = 0; - disp_drv->draw_buf->flushing_last = 0; -} - -/** - * Tell if it's the last area of the refreshing process. - * Can be called from `flush_cb` to execute some special display refreshing if needed when all areas area flushed. - * @param disp_drv pointer to display driver - * @return true: it's the last area to flush; false: there are other areas too which will be refreshed soon - */ -bool LV_ATTRIBUTE_FLUSH_READY lv_disp_flush_is_last(lv_disp_drv_t * disp_drv) -{ - return disp_drv->draw_buf->flushing_last; -} - -/** - * Get the next display. - * @param disp pointer to the current display. NULL to initialize. - * @return the next display or NULL if no more. Give the first display when the parameter is NULL - */ -lv_disp_t * lv_disp_get_next(lv_disp_t * disp) -{ - if(disp == NULL) - return _lv_ll_get_head(&LV_GC_ROOT(_lv_disp_ll)); - else - return _lv_ll_get_next(&LV_GC_ROOT(_lv_disp_ll), disp); -} - -/** - * Get the internal buffer of a display - * @param disp pointer to a display - * @return pointer to the internal buffers - */ -lv_disp_draw_buf_t * lv_disp_get_draw_buf(lv_disp_t * disp) -{ - return disp->driver->draw_buf; -} - -/** - * Set the rotation of this display. - * @param disp pointer to a display (NULL to use the default display) - * @param rotation rotation angle - */ -void lv_disp_set_rotation(lv_disp_t * disp, lv_disp_rot_t rotation) -{ - if(disp == NULL) disp = lv_disp_get_default(); - if(disp == NULL) return; - - disp->driver->rotated = rotation; - lv_disp_drv_update(disp, disp->driver); -} - -/** - * Get the current rotation of this display. - * @param disp pointer to a display (NULL to use the default display) - * @return rotation angle - */ -lv_disp_rot_t lv_disp_get_rotation(lv_disp_t * disp) -{ - if(disp == NULL) disp = lv_disp_get_default(); - if(disp == NULL) return LV_DISP_ROT_NONE; - return disp->driver->rotated; -} - -void lv_disp_drv_use_generic_set_px_cb(lv_disp_drv_t * disp_drv, lv_img_cf_t cf) -{ - switch(cf) { - case LV_IMG_CF_TRUE_COLOR_ALPHA: - disp_drv->set_px_cb = set_px_true_color_alpha; - break; - case LV_IMG_CF_ALPHA_1BIT: - disp_drv->set_px_cb = set_px_cb_alpha1; - break; - case LV_IMG_CF_ALPHA_2BIT: - disp_drv->set_px_cb = set_px_cb_alpha2; - break; - case LV_IMG_CF_ALPHA_4BIT: - disp_drv->set_px_cb = set_px_cb_alpha4; - break; - case LV_IMG_CF_ALPHA_8BIT: - disp_drv->set_px_cb = set_px_cb_alpha8; - break; - default: - disp_drv->set_px_cb = NULL; - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static lv_obj_tree_walk_res_t invalidate_layout_cb(lv_obj_t * obj, void * user_data) -{ - LV_UNUSED(user_data); - lv_obj_mark_layout_as_dirty(obj); - return LV_OBJ_TREE_WALK_NEXT; -} - -static void set_px_cb_alpha1(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa) -{ - (void) disp_drv; /*Unused*/ - - if(opa <= LV_OPA_MIN) return; - lv_img_dsc_t d; - d.data = buf; - d.header.w = buf_w; - d.header.cf = LV_IMG_CF_ALPHA_1BIT; - - set_px_alpha_generic(&d, x, y, color, opa); -} - -static void set_px_cb_alpha2(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa) -{ - (void) disp_drv; /*Unused*/ - - if(opa <= LV_OPA_MIN) return; - lv_img_dsc_t d; - d.data = buf; - d.header.w = buf_w; - d.header.cf = LV_IMG_CF_ALPHA_2BIT; - - set_px_alpha_generic(&d, x, y, color, opa); -} - -static void set_px_cb_alpha4(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa) -{ - (void) disp_drv; /*Unused*/ - - if(opa <= LV_OPA_MIN) return; - lv_img_dsc_t d; - d.data = buf; - d.header.w = buf_w; - d.header.cf = LV_IMG_CF_ALPHA_4BIT; - - set_px_alpha_generic(&d, x, y, color, opa); -} - -static void set_px_cb_alpha8(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa) -{ - (void) disp_drv; /*Unused*/ - - if(opa <= LV_OPA_MIN) return; - lv_img_dsc_t d; - d.data = buf; - d.header.w = buf_w; - d.header.cf = LV_IMG_CF_ALPHA_8BIT; - - set_px_alpha_generic(&d, x, y, color, opa); -} - -static void set_px_alpha_generic(lv_img_dsc_t * d, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa) -{ - d->header.always_zero = 0; - d->header.h = 1; /*Doesn't matter*/ - - uint8_t br = lv_color_brightness(color); - if(opa < LV_OPA_MAX) { - uint8_t bg = lv_img_buf_get_px_alpha(d, x, y); - br = (uint16_t)((uint16_t)br * opa + (bg * (255 - opa))) >> 8; - } - - lv_img_buf_set_px_alpha(d, x, y, br); -} - -static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, - lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa) -{ - (void) disp_drv; /*Unused*/ - - uint8_t * buf_px = buf + (buf_w * y * LV_IMG_PX_SIZE_ALPHA_BYTE + x * LV_IMG_PX_SIZE_ALPHA_BYTE); - - lv_color_t bg_color; - lv_color_t res_color; - lv_opa_t bg_opa = buf_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; -#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 - bg_color.full = buf_px[0]; - lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &buf_px[2]); - if(buf_px[1] <= LV_OPA_MIN) return; - buf_px[0] = res_color.full; -#elif LV_COLOR_DEPTH == 16 - bg_color.full = buf_px[0] + (buf_px[1] << 8); - lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &buf_px[2]); - if(buf_px[2] <= LV_OPA_MIN) return; - buf_px[0] = res_color.full & 0xff; - buf_px[1] = res_color.full >> 8; -#elif LV_COLOR_DEPTH == 32 - bg_color = *((lv_color_t *)buf_px); - lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &buf_px[3]); - if(buf_px[3] <= LV_OPA_MIN) return; - buf_px[0] = res_color.ch.blue; - buf_px[1] = res_color.ch.green; - buf_px[2] = res_color.ch.red; -#endif - -} diff --git a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.h b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.h deleted file mode 100644 index d5203a0b1..000000000 --- a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.h +++ /dev/null @@ -1,373 +0,0 @@ -/** - * @file lv_hal_disp.h - * - * @description Display Driver HAL interface header file - * - */ - -#ifndef LV_HAL_DISP_H -#define LV_HAL_DISP_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include -#include -#include "lv_hal.h" -#include "../draw/lv_draw.h" -#include "../misc/lv_color.h" -#include "../misc/lv_area.h" -#include "../misc/lv_ll.h" -#include "../misc/lv_timer.h" -#include "../misc/lv_ll.h" - -/********************* - * DEFINES - *********************/ -#ifndef LV_INV_BUF_SIZE -#define LV_INV_BUF_SIZE 32 /*Buffer size for invalid areas*/ -#endif - -#ifndef LV_ATTRIBUTE_FLUSH_READY -#define LV_ATTRIBUTE_FLUSH_READY -#endif - -/********************** - * TYPEDEFS - **********************/ - -struct _lv_obj_t; -struct _lv_disp_t; -struct _lv_disp_drv_t; -struct _lv_theme_t; - -/** - * Structure for holding display buffer information. - */ -typedef struct _lv_disp_draw_buf_t { - void * buf1; /**< First display buffer.*/ - void * buf2; /**< Second display buffer.*/ - - /*Internal, used by the library*/ - void * buf_act; - uint32_t size; /*In pixel count*/ - /*1: flushing is in progress. (It can't be a bit field because when it's cleared from IRQ Read-Modify-Write issue might occur)*/ - volatile int flushing; - /*1: It was the last chunk to flush. (It can't be a bit field because when it's cleared from IRQ Read-Modify-Write issue might occur)*/ - volatile int flushing_last; - volatile uint32_t last_area : 1; /*1: the last area is being rendered*/ - volatile uint32_t last_part : 1; /*1: the last part of the current area is being rendered*/ -} lv_disp_draw_buf_t; - -typedef enum { - LV_DISP_ROT_NONE = 0, - LV_DISP_ROT_90, - LV_DISP_ROT_180, - LV_DISP_ROT_270 -} lv_disp_rot_t; - -/** - * Display Driver structure to be registered by HAL. - * Only its pointer will be saved in `lv_disp_t` so it should be declared as - * `static lv_disp_drv_t my_drv` or allocated dynamically. - */ -typedef struct _lv_disp_drv_t { - - lv_coord_t hor_res; /**< Horizontal resolution.*/ - lv_coord_t ver_res; /**< Vertical resolution.*/ - - lv_coord_t - physical_hor_res; /**< Horizontal resolution of the full / physical display. Set to -1 for fullscreen mode.*/ - lv_coord_t - physical_ver_res; /**< Vertical resolution of the full / physical display. Set to -1 for fullscreen mode.*/ - lv_coord_t - offset_x; /**< Horizontal offset from the full / physical display. Set to 0 for fullscreen mode.*/ - lv_coord_t offset_y; /**< Vertical offset from the full / physical display. Set to 0 for fullscreen mode.*/ - - /** Pointer to a buffer initialized with `lv_disp_draw_buf_init()`. - * LVGL will use this buffer(s) to draw the screens contents*/ - lv_disp_draw_buf_t * draw_buf; - - uint32_t direct_mode : 1; /**< 1: Use screen-sized buffers and draw to absolute coordinates*/ - uint32_t full_refresh : 1; /**< 1: Always make the whole screen redrawn*/ - uint32_t sw_rotate : 1; /**< 1: use software rotation (slower)*/ - uint32_t antialiasing : 1; /**< 1: anti-aliasing is enabled on this display.*/ - uint32_t rotated : 2; /**< 1: turn the display by 90 degree. @warning Does not update coordinates for you!*/ - uint32_t screen_transp : 1; /**Handle if the screen doesn't have a solid (opa == LV_OPA_COVER) background. - * Use only if required because it's slower.*/ - - uint32_t dpi : 10; /** DPI (dot per inch) of the display. Default value is `LV_DPI_DEF`.*/ - - /** MANDATORY: Write the internal buffer (draw_buf) to the display. 'lv_disp_flush_ready()' has to be - * called when finished*/ - void (*flush_cb)(struct _lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p); - - /** OPTIONAL: Extend the invalidated areas to match with the display drivers requirements - * E.g. round `y` to, 8, 16 ..) on a monochrome display*/ - void (*rounder_cb)(struct _lv_disp_drv_t * disp_drv, lv_area_t * area); - - /** OPTIONAL: Set a pixel in a buffer according to the special requirements of the display - * Can be used for color format not supported in LittelvGL. E.g. 2 bit -> 4 gray scales - * @note Much slower then drawing with supported color formats.*/ - void (*set_px_cb)(struct _lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, - lv_color_t color, lv_opa_t opa); - - void (*clear_cb)(struct _lv_disp_drv_t * disp_drv, uint8_t * buf, uint32_t size); - - - /** OPTIONAL: Called after every refresh cycle to tell the rendering and flushing time + the - * number of flushed pixels*/ - void (*monitor_cb)(struct _lv_disp_drv_t * disp_drv, uint32_t time, uint32_t px); - - /** OPTIONAL: Called periodically while lvgl waits for operation to be completed. - * For example flushing or GPU - * User can execute very simple tasks here or yield the task*/ - void (*wait_cb)(struct _lv_disp_drv_t * disp_drv); - - /** OPTIONAL: Called when lvgl needs any CPU cache that affects rendering to be cleaned*/ - void (*clean_dcache_cb)(struct _lv_disp_drv_t * disp_drv); - - /** OPTIONAL: called when driver parameters are updated */ - void (*drv_update_cb)(struct _lv_disp_drv_t * disp_drv); - - /** OPTIONAL: called when start rendering */ - void (*render_start_cb)(struct _lv_disp_drv_t * disp_drv); - - /** On CHROMA_KEYED images this color will be transparent. - * `LV_COLOR_CHROMA_KEY` by default. (lv_conf.h)*/ - lv_color_t color_chroma_key; - - lv_draw_ctx_t * draw_ctx; - void (*draw_ctx_init)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx); - void (*draw_ctx_deinit)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx); - size_t draw_ctx_size; - -#if LV_USE_USER_DATA - void * user_data; /**< Custom display driver user data*/ -#endif - -} lv_disp_drv_t; - -/** - * Display structure. - * @note `lv_disp_drv_t` should be the first member of the structure. - */ -typedef struct _lv_disp_t { - /**< Driver to the display*/ - struct _lv_disp_drv_t * driver; - - /**< A timer which periodically checks the dirty areas and refreshes them*/ - lv_timer_t * refr_timer; - - /**< The theme assigned to the screen*/ - struct _lv_theme_t * theme; - - /** Screens of the display*/ - struct _lv_obj_t ** screens; /**< Array of screen objects.*/ - struct _lv_obj_t * act_scr; /**< Currently active screen on this display*/ - struct _lv_obj_t * prev_scr; /**< Previous screen. Used during screen animations*/ - struct _lv_obj_t * scr_to_load; /**< The screen prepared to load in lv_scr_load_anim*/ - struct _lv_obj_t * top_layer; /**< @see lv_disp_get_layer_top*/ - struct _lv_obj_t * sys_layer; /**< @see lv_disp_get_layer_sys*/ - uint32_t screen_cnt; - uint8_t draw_prev_over_act : 1; /**< 1: Draw previous screen over active screen*/ - uint8_t del_prev : 1; /**< 1: Automatically delete the previous screen when the screen load anim. is ready*/ - uint8_t rendering_in_progress : 1; /**< 1: The current screen rendering is in progress*/ - - lv_opa_t bg_opa; /**flush` you should use DMA or similar hardware to send - * the image to the display in the background. - * It lets LVGL to render next frame into the other buffer while previous is being - * sent. Set to `NULL` if unused. - * @param size_in_px_cnt size of the `buf1` and `buf2` in pixel count. - */ -void lv_disp_draw_buf_init(lv_disp_draw_buf_t * draw_buf, void * buf1, void * buf2, uint32_t size_in_px_cnt); - -/** - * Register an initialized display driver. - * Automatically set the first display as active. - * @param driver pointer to an initialized 'lv_disp_drv_t' variable. Only its pointer is saved! - * @return pointer to the new display or NULL on error - */ -lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver); - -/** - * Update the driver in run time. - * @param disp pointer to a display. (return value of `lv_disp_drv_register`) - * @param new_drv pointer to the new driver - */ -void lv_disp_drv_update(lv_disp_t * disp, lv_disp_drv_t * new_drv); - -/** - * Remove a display - * @param disp pointer to display - */ -void lv_disp_remove(lv_disp_t * disp); - -/** - * Set a default display. The new screens will be created on it by default. - * @param disp pointer to a display - */ -void lv_disp_set_default(lv_disp_t * disp); - -/** - * Get the default display - * @return pointer to the default display - */ -lv_disp_t * lv_disp_get_default(void); - -/** - * Get the horizontal resolution of a display - * @param disp pointer to a display (NULL to use the default display) - * @return the horizontal resolution of the display - */ -lv_coord_t lv_disp_get_hor_res(lv_disp_t * disp); - -/** - * Get the vertical resolution of a display - * @param disp pointer to a display (NULL to use the default display) - * @return the vertical resolution of the display - */ -lv_coord_t lv_disp_get_ver_res(lv_disp_t * disp); - -/** - * Get the full / physical horizontal resolution of a display - * @param disp pointer to a display (NULL to use the default display) - * @return the full / physical horizontal resolution of the display - */ -lv_coord_t lv_disp_get_physical_hor_res(lv_disp_t * disp); - -/** - * Get the full / physical vertical resolution of a display - * @param disp pointer to a display (NULL to use the default display) - * @return the full / physical vertical resolution of the display - */ -lv_coord_t lv_disp_get_physical_ver_res(lv_disp_t * disp); - -/** - * Get the horizontal offset from the full / physical display - * @param disp pointer to a display (NULL to use the default display) - * @return the horizontal offset from the full / physical display - */ -lv_coord_t lv_disp_get_offset_x(lv_disp_t * disp); - -/** - * Get the vertical offset from the full / physical display - * @param disp pointer to a display (NULL to use the default display) - * @return the horizontal offset from the full / physical display - */ -lv_coord_t lv_disp_get_offset_y(lv_disp_t * disp); - -/** - * Get if anti-aliasing is enabled for a display or not - * @param disp pointer to a display (NULL to use the default display) - * @return true: anti-aliasing is enabled; false: disabled - */ -bool lv_disp_get_antialiasing(lv_disp_t * disp); - -/** - * Get the DPI of the display - * @param disp pointer to a display (NULL to use the default display) - * @return dpi of the display - */ -lv_coord_t lv_disp_get_dpi(const lv_disp_t * disp); - - -/** - * Set the rotation of this display. - * @param disp pointer to a display (NULL to use the default display) - * @param rotation rotation angle - */ -void lv_disp_set_rotation(lv_disp_t * disp, lv_disp_rot_t rotation); - -/** - * Get the current rotation of this display. - * @param disp pointer to a display (NULL to use the default display) - * @return rotation angle - */ -lv_disp_rot_t lv_disp_get_rotation(lv_disp_t * disp); - -//! @cond Doxygen_Suppress - -/** - * Call in the display driver's `flush_cb` function when the flushing is finished - * @param disp_drv pointer to display driver in `flush_cb` where this function is called - */ -void /* LV_ATTRIBUTE_FLUSH_READY */ lv_disp_flush_ready(lv_disp_drv_t * disp_drv); - -/** - * Tell if it's the last area of the refreshing process. - * Can be called from `flush_cb` to execute some special display refreshing if needed when all areas area flushed. - * @param disp_drv pointer to display driver - * @return true: it's the last area to flush; false: there are other areas too which will be refreshed soon - */ -bool /* LV_ATTRIBUTE_FLUSH_READY */ lv_disp_flush_is_last(lv_disp_drv_t * disp_drv); - -//! @endcond - -/** - * Get the next display. - * @param disp pointer to the current display. NULL to initialize. - * @return the next display or NULL if no more. Give the first display when the parameter is NULL - */ -lv_disp_t * lv_disp_get_next(lv_disp_t * disp); - -/** - * Get the internal buffer of a display - * @param disp pointer to a display - * @return pointer to the internal buffers - */ -lv_disp_draw_buf_t * lv_disp_get_draw_buf(lv_disp_t * disp); - -void lv_disp_drv_use_generic_set_px_cb(lv_disp_drv_t * disp_drv, lv_img_cf_t cf); - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_indev.c b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_indev.c deleted file mode 100644 index c3661e422..000000000 --- a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_indev.c +++ /dev/null @@ -1,195 +0,0 @@ -/** - * @file lv_hal_indev.c - * - * @description Input device HAL interface - * - */ - -/********************* - * INCLUDES - *********************/ -#include "../misc/lv_assert.h" -#include "../hal/lv_hal_indev.h" -#include "../core/lv_indev.h" -#include "../misc/lv_mem.h" -#include "../misc/lv_gc.h" -#include "lv_hal_disp.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ -#if LV_LOG_TRACE_INDEV - #define INDEV_TRACE(...) LV_LOG_TRACE(__VA_ARGS__) -#else - #define INDEV_TRACE(...) -#endif - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Initialize an input device driver with default values. - * It is used to surly have known values in the fields ant not memory junk. - * After it you can set the fields. - * @param driver pointer to driver variable to initialize - */ -void lv_indev_drv_init(lv_indev_drv_t * driver) -{ - lv_memset_00(driver, sizeof(lv_indev_drv_t)); - - driver->type = LV_INDEV_TYPE_NONE; - driver->scroll_limit = LV_INDEV_DEF_SCROLL_LIMIT; - driver->scroll_throw = LV_INDEV_DEF_SCROLL_THROW; - driver->long_press_time = LV_INDEV_DEF_LONG_PRESS_TIME; - driver->long_press_repeat_time = LV_INDEV_DEF_LONG_PRESS_REP_TIME; - driver->gesture_limit = LV_INDEV_DEF_GESTURE_LIMIT; - driver->gesture_min_velocity = LV_INDEV_DEF_GESTURE_MIN_VELOCITY; -} - -/** - * Register an initialized input device driver. - * @param driver pointer to an initialized 'lv_indev_drv_t' variable. - * Only pointer is saved, so the driver should be static or dynamically allocated. - * @return pointer to the new input device or NULL on error - */ -lv_indev_t * lv_indev_drv_register(lv_indev_drv_t * driver) -{ - if(driver->disp == NULL) driver->disp = lv_disp_get_default(); - - if(driver->disp == NULL) { - LV_LOG_WARN("lv_indev_drv_register: no display registered hence can't attach the indev to " - "a display"); - return NULL; - } - - lv_indev_t * indev = _lv_ll_ins_head(&LV_GC_ROOT(_lv_indev_ll)); - LV_ASSERT_MALLOC(indev); - if(!indev) { - return NULL; - } - - lv_memset_00(indev, sizeof(lv_indev_t)); - indev->driver = driver; - - indev->proc.reset_query = 1; - indev->driver->read_timer = lv_timer_create(lv_indev_read_timer_cb, LV_INDEV_DEF_READ_PERIOD, indev); - - return indev; -} - -/** - * Update the driver in run time. - * @param indev pointer to a input device. (return value of `lv_indev_drv_register`) - * @param new_drv pointer to the new driver - */ -void lv_indev_drv_update(lv_indev_t * indev, lv_indev_drv_t * new_drv) -{ - LV_ASSERT_NULL(indev); - LV_ASSERT_NULL(indev->driver); - LV_ASSERT_NULL(indev->driver->read_timer); - lv_timer_del(indev->driver->read_timer); - - LV_ASSERT_NULL(new_drv); - if(new_drv->disp == NULL) { - new_drv->disp = lv_disp_get_default(); - } - if(new_drv->disp == NULL) { - LV_LOG_WARN("lv_indev_drv_register: no display registered hence can't attach the indev to " - "a display"); - indev->proc.disabled = true; - return; - } - - indev->driver = new_drv; - indev->driver->read_timer = lv_timer_create(lv_indev_read_timer_cb, LV_INDEV_DEF_READ_PERIOD, indev); - indev->proc.reset_query = 1; -} - -/** -* Remove the provided input device. Make sure not to use the provided input device afterwards anymore. -* @param indev pointer to delete -*/ -void lv_indev_delete(lv_indev_t * indev) -{ - LV_ASSERT_NULL(indev); - LV_ASSERT_NULL(indev->driver); - LV_ASSERT_NULL(indev->driver->read_timer); - /*Clean up the read timer first*/ - lv_timer_del(indev->driver->read_timer); - /*Remove the input device from the list*/ - _lv_ll_remove(&LV_GC_ROOT(_lv_indev_ll), indev); - /*Free the memory of the input device*/ - lv_mem_free(indev); -} - -/** - * Get the next input device. - * @param indev pointer to the current input device. NULL to initialize. - * @return the next input devise or NULL if no more. Give the first input device when the parameter - * is NULL - */ -lv_indev_t * lv_indev_get_next(lv_indev_t * indev) -{ - if(indev == NULL) - return _lv_ll_get_head(&LV_GC_ROOT(_lv_indev_ll)); - else - return _lv_ll_get_next(&LV_GC_ROOT(_lv_indev_ll), indev); -} - -/** - * Read data from an input device. - * @param indev pointer to an input device - * @param data input device will write its data here - */ -void _lv_indev_read(lv_indev_t * indev, lv_indev_data_t * data) -{ - lv_memset_00(data, sizeof(lv_indev_data_t)); - - /* For touchpad sometimes users don't set the last pressed coordinate on release. - * So be sure a coordinates are initialized to the last point */ - if(indev->driver->type == LV_INDEV_TYPE_POINTER) { - data->point.x = indev->proc.types.pointer.last_raw_point.x; - data->point.y = indev->proc.types.pointer.last_raw_point.y; - } - /*Similarly set at least the last key in case of the user doesn't set it on release*/ - else if(indev->driver->type == LV_INDEV_TYPE_KEYPAD) { - data->key = indev->proc.types.keypad.last_key; - } - /*For compatibility assume that used button was enter (encoder push)*/ - else if(indev->driver->type == LV_INDEV_TYPE_ENCODER) { - data->key = LV_KEY_ENTER; - } - - if(indev->driver->read_cb) { - INDEV_TRACE("calling indev_read_cb"); - indev->driver->read_cb(indev->driver, data); - } - else { - LV_LOG_WARN("indev_read_cb is not registered"); - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_indev.h b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_indev.h deleted file mode 100644 index 5bbcf530e..000000000 --- a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_indev.h +++ /dev/null @@ -1,240 +0,0 @@ -/** - * @file lv_hal_indev.h - * - * @description Input Device HAL interface layer header file - * - */ - -#ifndef LV_HAL_INDEV_H -#define LV_HAL_INDEV_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#include -#include -#include "../misc/lv_area.h" -#include "../misc/lv_timer.h" - -/********************* - * DEFINES - *********************/ - -/*Drag threshold in pixels*/ -#define LV_INDEV_DEF_SCROLL_LIMIT 10 - -/*Drag throw slow-down in [%]. Greater value -> faster slow-down*/ -#define LV_INDEV_DEF_SCROLL_THROW 10 - -/*Long press time in milliseconds. - *Time to send `LV_EVENT_LONG_PRESSSED`)*/ -#define LV_INDEV_DEF_LONG_PRESS_TIME 400 - -/*Repeated trigger period in long press [ms] - *Time between `LV_EVENT_LONG_PRESSED_REPEAT*/ -#define LV_INDEV_DEF_LONG_PRESS_REP_TIME 100 - - -/*Gesture threshold in pixels*/ -#define LV_INDEV_DEF_GESTURE_LIMIT 50 - -/*Gesture min velocity at release before swipe (pixels)*/ -#define LV_INDEV_DEF_GESTURE_MIN_VELOCITY 3 - - -/********************** - * TYPEDEFS - **********************/ - -struct _lv_obj_t; -struct _lv_disp_t; -struct _lv_group_t; -struct _lv_indev_t; -struct _lv_indev_drv_t; - -/** Possible input device types*/ -typedef enum { - LV_INDEV_TYPE_NONE, /**< Uninitialized state*/ - LV_INDEV_TYPE_POINTER, /**< Touch pad, mouse, external button*/ - LV_INDEV_TYPE_KEYPAD, /**< Keypad or keyboard*/ - LV_INDEV_TYPE_BUTTON, /**< External (hardware button) which is assigned to a specific point of the screen*/ - LV_INDEV_TYPE_ENCODER, /**< Encoder with only Left, Right turn and a Button*/ -} lv_indev_type_t; - -/** States for input devices*/ -typedef enum { - LV_INDEV_STATE_RELEASED = 0, - LV_INDEV_STATE_PRESSED -} lv_indev_state_t; - -/** Data structure passed to an input driver to fill*/ -typedef struct { - lv_point_t point; /**< For LV_INDEV_TYPE_POINTER the currently pressed point*/ - uint32_t key; /**< For LV_INDEV_TYPE_KEYPAD the currently pressed key*/ - uint32_t btn_id; /**< For LV_INDEV_TYPE_BUTTON the currently pressed button*/ - int16_t enc_diff; /**< For LV_INDEV_TYPE_ENCODER number of steps since the previous read*/ - - lv_indev_state_t state; /**< LV_INDEV_STATE_REL or LV_INDEV_STATE_PR*/ - bool continue_reading; /**< If set to true, the read callback is invoked again*/ -} lv_indev_data_t; - -/** Initialized by the user and registered by 'lv_indev_add()'*/ -typedef struct _lv_indev_drv_t { - - /**< Input device type*/ - lv_indev_type_t type; - - /**< Function pointer to read input device data.*/ - void (*read_cb)(struct _lv_indev_drv_t * indev_drv, lv_indev_data_t * data); - - /** Called when an action happened on the input device. - * The second parameter is the event from `lv_event_t`*/ - void (*feedback_cb)(struct _lv_indev_drv_t *, uint8_t); - -#if LV_USE_USER_DATA - void * user_data; -#endif - - /**< Pointer to the assigned display*/ - struct _lv_disp_t * disp; - - /**< Timer to periodically read the input device*/ - lv_timer_t * read_timer; - - /**< Number of pixels to slide before actually drag the object*/ - uint8_t scroll_limit; - - /**< Drag throw slow-down in [%]. Greater value means faster slow-down*/ - uint8_t scroll_throw; - - /**< At least this difference should be between two points to evaluate as gesture*/ - uint8_t gesture_min_velocity; - - /**< At least this difference should be to send a gesture*/ - uint8_t gesture_limit; - - /**< Long press time in milliseconds*/ - uint16_t long_press_time; - - /**< Repeated trigger period in long press [ms]*/ - uint16_t long_press_repeat_time; -} lv_indev_drv_t; - -/** Run time data of input devices - * Internally used by the library, you should not need to touch it. - */ -typedef struct _lv_indev_proc_t { - lv_indev_state_t state; /**< Current state of the input device.*/ - /*Flags*/ - uint8_t long_pr_sent : 1; - uint8_t reset_query : 1; - uint8_t disabled : 1; - uint8_t wait_until_release : 1; - - union { - struct { - /*Pointer and button data*/ - lv_point_t act_point; /**< Current point of input device.*/ - lv_point_t indev_point; - lv_point_t last_point; /**< Last point of input device.*/ - lv_point_t last_raw_point; /**< Last point read from read_cb. */ - lv_point_t vect; /**< Difference between `act_point` and `last_point`.*/ - lv_point_t scroll_sum; /*Count the dragged pixels to check LV_INDEV_DEF_SCROLL_LIMIT*/ - lv_point_t scroll_throw_vect; - lv_point_t scroll_throw_vect_ori; - struct _lv_obj_t * act_obj; /*The object being pressed*/ - struct _lv_obj_t * last_obj; /*The last object which was pressed*/ - struct _lv_obj_t * scroll_obj; /*The object being scrolled*/ - struct _lv_obj_t * last_pressed; /*The lastly pressed object*/ - lv_area_t scroll_area; - - lv_point_t gesture_sum; /*Count the gesture pixels to check LV_INDEV_DEF_GESTURE_LIMIT*/ - /*Flags*/ - lv_dir_t scroll_dir : 4; - lv_dir_t gesture_dir : 4; - uint8_t gesture_sent : 1; - } pointer; - struct { - /*Keypad data*/ - lv_indev_state_t last_state; - uint32_t last_key; - } keypad; - } types; - - uint32_t pr_timestamp; /**< Pressed time stamp*/ - uint32_t longpr_rep_timestamp; /**< Long press repeat time stamp*/ -} _lv_indev_proc_t; - -/** The main input device descriptor with driver, runtime data ('proc') and some additional - * information*/ -typedef struct _lv_indev_t { - struct _lv_indev_drv_t * driver; - _lv_indev_proc_t proc; - struct _lv_obj_t * cursor; /**< Cursor for LV_INPUT_TYPE_POINTER*/ - struct _lv_group_t * group; /**< Keypad destination group*/ - const lv_point_t * btn_points; /**< Array points assigned to the button ()screen will be pressed - here by the buttons*/ -} lv_indev_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Initialize an input device driver with default values. - * It is used to surely have known values in the fields and not memory junk. - * After it you can set the fields. - * @param driver pointer to driver variable to initialize - */ -void lv_indev_drv_init(struct _lv_indev_drv_t * driver); - -/** - * Register an initialized input device driver. - * @param driver pointer to an initialized 'lv_indev_drv_t' variable (can be local variable) - * @return pointer to the new input device or NULL on error - */ -lv_indev_t * lv_indev_drv_register(struct _lv_indev_drv_t * driver); - -/** - * Update the driver in run time. - * @param indev pointer to an input device. (return value of `lv_indev_drv_register`) - * @param new_drv pointer to the new driver - */ -void lv_indev_drv_update(lv_indev_t * indev, struct _lv_indev_drv_t * new_drv); - -/** -* Remove the provided input device. Make sure not to use the provided input device afterwards anymore. -* @param indev pointer to delete -*/ -void lv_indev_delete(lv_indev_t * indev); - -/** - * Get the next input device. - * @param indev pointer to the current input device. NULL to initialize. - * @return the next input device or NULL if there are no more. Provide the first input device when - * the parameter is NULL - */ -lv_indev_t * lv_indev_get_next(lv_indev_t * indev); - -/** - * Read data from an input device. - * @param indev pointer to an input device - * @param data input device will write its data here - */ -void _lv_indev_read(lv_indev_t * indev, lv_indev_data_t * data); - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_tick.h b/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_tick.h deleted file mode 100644 index d493ad351..000000000 --- a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_tick.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @file lv_hal_tick.h - * Provide access to the system tick with 1 millisecond resolution - */ - -#ifndef LV_HAL_TICK_H -#define LV_HAL_TICK_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#include -#include - -/********************* - * DEFINES - *********************/ -#ifndef LV_ATTRIBUTE_TICK_INC -#define LV_ATTRIBUTE_TICK_INC -#endif - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -//! @cond Doxygen_Suppress - -#if !LV_TICK_CUSTOM -/** - * You have to call this function periodically - * @param tick_period the call period of this function in milliseconds - */ -void /* LV_ATTRIBUTE_TICK_INC */ lv_tick_inc(uint32_t tick_period); -#endif - -//! @endcond - -/** - * Get the elapsed milliseconds since start up - * @return the elapsed milliseconds - */ -uint32_t lv_tick_get(void); - -/** - * Get the elapsed milliseconds since a previous time stamp - * @param prev_tick a previous time stamp (return value of lv_tick_get() ) - * @return the elapsed milliseconds since 'prev_tick' - */ -uint32_t lv_tick_elaps(uint32_t prev_tick); - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_HAL_TICK_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/indev/lv_indev.c b/lib/libesp32_lvgl/lvgl/src/indev/lv_indev.c new file mode 100644 index 000000000..5c83739f6 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/indev/lv_indev.c @@ -0,0 +1,1594 @@ +/** + * @file lv_indev.c + * + */ + +/********************* + * INCLUDES + ********************/ +#include "lv_indev_private.h" +#include "lv_indev_scroll.h" +#include "../display/lv_display_private.h" +#include "../core/lv_global.h" +#include "../core/lv_obj.h" +#include "../core/lv_group.h" +#include "../core/lv_refr.h" + +#include "../tick/lv_tick.h" +#include "../misc/lv_timer.h" +#include "../misc/lv_math.h" +#include "../misc/lv_profiler.h" +#include "../stdlib/lv_string.h" + +/********************* + * DEFINES + *********************/ +/*Drag threshold in pixels*/ +#define LV_INDEV_DEF_SCROLL_LIMIT 10 + +/*Drag throw slow-down in [%]. Greater value -> faster slow-down*/ +#define LV_INDEV_DEF_SCROLL_THROW 10 + +/*Long press time in milliseconds. + *Time to send `LV_EVENT_LONG_PRESSSED`)*/ +#define LV_INDEV_DEF_LONG_PRESS_TIME 400 + +/*Repeated trigger period in long press [ms] + *Time between `LV_EVENT_LONG_PRESSED_REPEAT*/ +#define LV_INDEV_DEF_LONG_PRESS_REP_TIME 100 + +/*Gesture threshold in pixels*/ +#define LV_INDEV_DEF_GESTURE_LIMIT 50 + +/*Gesture min velocity at release before swipe (pixels)*/ +#define LV_INDEV_DEF_GESTURE_MIN_VELOCITY 3 + +#if LV_INDEV_DEF_SCROLL_THROW <= 0 + #warning "LV_INDEV_DRAG_THROW must be greater than 0" +#endif + +#define indev_act LV_GLOBAL_DEFAULT()->indev_active +#define indev_obj_act LV_GLOBAL_DEFAULT()->indev_obj_active +#define indev_ll_head &(LV_GLOBAL_DEFAULT()->indev_ll) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data); +static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data); +static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data); +static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data); +static void indev_proc_press(lv_indev_t * indev); +static void indev_proc_release(lv_indev_t * indev); +static lv_obj_t * pointer_search_obj(lv_display_t * disp, lv_point_t * p); +static void indev_proc_reset_query_handler(lv_indev_t * indev); +static void indev_click_focus(lv_indev_t * indev); +static void indev_gesture(lv_indev_t * indev); +static bool indev_reset_check(lv_indev_t * indev); +static void indev_read_core(lv_indev_t * indev, lv_indev_data_t * data); +static void indev_reset_core(lv_indev_t * indev, lv_obj_t * obj); +static lv_result_t send_event(lv_event_code_t code, void * param); + +static void indev_scroll_throw_anim_start(lv_indev_t * indev); +static void indev_scroll_throw_anim_cb(void * var, int32_t v); +static void indev_scroll_throw_anim_completed_cb(lv_anim_t * anim); +static inline void indev_scroll_throw_anim_reset(lv_indev_t * indev) +{ + if(indev) { + indev->pointer.scroll_throw_vect.x = 0; + indev->pointer.scroll_throw_vect.y = 0; + indev->scroll_throw_anim = NULL; + } +} + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ +#if LV_USE_LOG && LV_LOG_TRACE_INDEV + #define LV_TRACE_INDEV(...) LV_LOG_TRACE(__VA_ARGS__) +#else + #define LV_TRACE_INDEV(...) +#endif + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_indev_t * lv_indev_create(void) +{ + lv_display_t * disp = lv_display_get_default(); + if(disp == NULL) { + LV_LOG_WARN("no display was created so far"); + } + + lv_indev_t * indev = _lv_ll_ins_head(indev_ll_head); + LV_ASSERT_MALLOC(indev); + if(!indev) { + return NULL; + } + + lv_memzero(indev, sizeof(lv_indev_t)); + indev->reset_query = 1; + indev->read_timer = lv_timer_create(lv_indev_read_timer_cb, LV_DEF_REFR_PERIOD, indev); + + indev->disp = lv_display_get_default(); + indev->type = LV_INDEV_TYPE_NONE; + indev->mode = LV_INDEV_MODE_TIMER; + indev->scroll_limit = LV_INDEV_DEF_SCROLL_LIMIT; + indev->scroll_throw = LV_INDEV_DEF_SCROLL_THROW; + indev->long_press_time = LV_INDEV_DEF_LONG_PRESS_TIME; + indev->long_press_repeat_time = LV_INDEV_DEF_LONG_PRESS_REP_TIME; + indev->gesture_limit = LV_INDEV_DEF_GESTURE_LIMIT; + indev->gesture_min_velocity = LV_INDEV_DEF_GESTURE_MIN_VELOCITY; + return indev; +} + +void lv_indev_delete(lv_indev_t * indev) +{ + LV_ASSERT_NULL(indev); + + lv_indev_send_event(indev, LV_EVENT_DELETE, NULL); + lv_event_remove_all(&(indev->event_list)); + + /*Clean up the read timer first*/ + if(indev->read_timer) lv_timer_delete(indev->read_timer); + + /*Remove the input device from the list*/ + _lv_ll_remove(indev_ll_head, indev); + /*Free the memory of the input device*/ + lv_free(indev); +} + +lv_indev_t * lv_indev_get_next(lv_indev_t * indev) +{ + if(indev == NULL) + return _lv_ll_get_head(indev_ll_head); + else + return _lv_ll_get_next(indev_ll_head, indev); +} + +void indev_read_core(lv_indev_t * indev, lv_indev_data_t * data) +{ + LV_PROFILER_BEGIN; + lv_memzero(data, sizeof(lv_indev_data_t)); + + /* For touchpad sometimes users don't set the last pressed coordinate on release. + * So be sure a coordinates are initialized to the last point */ + if(indev->type == LV_INDEV_TYPE_POINTER) { + data->point.x = indev->pointer.last_raw_point.x; + data->point.y = indev->pointer.last_raw_point.y; + } + /*Similarly set at least the last key in case of the user doesn't set it on release*/ + else if(indev->type == LV_INDEV_TYPE_KEYPAD) { + data->key = indev->keypad.last_key; + } + /*For compatibility assume that used button was enter (encoder push)*/ + else if(indev->type == LV_INDEV_TYPE_ENCODER) { + data->key = LV_KEY_ENTER; + } + + if(indev->read_cb) { + LV_TRACE_INDEV("calling indev_read_cb"); + indev->read_cb(indev, data); + } + else { + LV_LOG_WARN("indev_read_cb is not registered"); + } + LV_PROFILER_END; +} + +void lv_indev_read_timer_cb(lv_timer_t * timer) +{ + lv_indev_read(timer->user_data); +} + +void lv_indev_read(lv_indev_t * indev_p) +{ + if(!indev_p) return; + + LV_TRACE_INDEV("begin"); + + indev_act = indev_p; + + /*Read and process all indevs*/ + if(indev_p->disp == NULL) return; /*Not assigned to any displays*/ + + /*Handle reset query before processing the point*/ + indev_proc_reset_query_handler(indev_p); + + if(indev_p->disabled || + indev_p->disp->prev_scr != NULL) return; /*Input disabled or screen animation active*/ + + LV_PROFILER_BEGIN; + + bool continue_reading; + lv_indev_data_t data; + + do { + /*Read the data*/ + indev_read_core(indev_p, &data); + continue_reading = indev_p->mode != LV_INDEV_MODE_EVENT && data.continue_reading; + + /*The active object might be deleted even in the read function*/ + indev_proc_reset_query_handler(indev_p); + indev_obj_act = NULL; + + indev_p->state = data.state; + + /*Save the last activity time*/ + if(indev_p->state == LV_INDEV_STATE_PRESSED) { + indev_p->disp->last_activity_time = lv_tick_get(); + } + else if(indev_p->type == LV_INDEV_TYPE_ENCODER && data.enc_diff) { + indev_p->disp->last_activity_time = lv_tick_get(); + } + + if(indev_p->type == LV_INDEV_TYPE_POINTER) { + indev_pointer_proc(indev_p, &data); + } + else if(indev_p->type == LV_INDEV_TYPE_KEYPAD) { + indev_keypad_proc(indev_p, &data); + } + else if(indev_p->type == LV_INDEV_TYPE_ENCODER) { + indev_encoder_proc(indev_p, &data); + } + else if(indev_p->type == LV_INDEV_TYPE_BUTTON) { + indev_button_proc(indev_p, &data); + } + /*Handle reset query if it happened in during processing*/ + indev_proc_reset_query_handler(indev_p); + } while(continue_reading); + + /*End of indev processing, so no act indev*/ + indev_act = NULL; + indev_obj_act = NULL; + + LV_TRACE_INDEV("finished"); + LV_PROFILER_END; +} + +void lv_indev_enable(lv_indev_t * indev, bool en) +{ + uint8_t enable = en ? 0 : 1; + + if(indev) { + indev->disabled = enable; + } + else { + lv_indev_t * i = lv_indev_get_next(NULL); + while(i) { + i->disabled = enable; + i = lv_indev_get_next(i); + } + } +} + +lv_indev_t * lv_indev_active(void) +{ + return indev_act; +} + +void lv_indev_set_type(lv_indev_t * indev, lv_indev_type_t indev_type) +{ + if(indev == NULL) return; + + indev->type = indev_type; + indev->reset_query = 1; +} + +void lv_indev_set_read_cb(lv_indev_t * indev, lv_indev_read_cb_t read_cb) +{ + if(indev == NULL) return; + + indev->read_cb = read_cb; +} + +void lv_indev_set_user_data(lv_indev_t * indev, void * user_data) +{ + if(indev == NULL) return; + indev->user_data = user_data; +} + +void lv_indev_set_driver_data(lv_indev_t * indev, void * driver_data) +{ + if(indev == NULL) return; + indev->driver_data = driver_data; +} + +lv_indev_read_cb_t lv_indev_get_read_cb(lv_indev_t * indev) +{ + if(!indev) { + LV_LOG_WARN("lv_indev_get_read_cb: indev was NULL"); + return NULL; + } + + return indev->read_cb; +} + +lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev) +{ + if(indev == NULL) return LV_INDEV_TYPE_NONE; + + return indev->type; +} + +lv_indev_state_t lv_indev_get_state(const lv_indev_t * indev) +{ + if(indev == NULL) return LV_INDEV_STATE_RELEASED; + + return indev->state; +} + +lv_group_t * lv_indev_get_group(const lv_indev_t * indev) +{ + if(indev == NULL) return NULL; + + return indev->group; +} + +lv_display_t * lv_indev_get_display(const lv_indev_t * indev) +{ + if(indev == NULL) return NULL; + + return indev->disp; +} + +void lv_indev_set_display(lv_indev_t * indev, lv_display_t * disp) +{ + if(indev == NULL) return; + + indev->disp = disp; +} + +void * lv_indev_get_user_data(const lv_indev_t * indev) +{ + if(indev == NULL) return NULL; + return indev->user_data; +} + +void * lv_indev_get_driver_data(const lv_indev_t * indev) +{ + if(indev == NULL) return NULL; + + return indev->driver_data; +} + +void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj) +{ + if(indev) { + indev_reset_core(indev, obj); + } + else { + lv_indev_t * i = lv_indev_get_next(NULL); + while(i) { + indev_reset_core(i, obj); + i = lv_indev_get_next(i); + } + indev_obj_act = NULL; + } +} + +void lv_indev_reset_long_press(lv_indev_t * indev) +{ + indev->long_pr_sent = 0; + indev->longpr_rep_timestamp = lv_tick_get(); + indev->pr_timestamp = lv_tick_get(); +} + +void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj) +{ + if(indev->type != LV_INDEV_TYPE_POINTER) return; + + indev->cursor = cur_obj; + lv_obj_set_parent(indev->cursor, lv_display_get_layer_sys(indev->disp)); + lv_obj_set_pos(indev->cursor, indev->pointer.act_point.x, indev->pointer.act_point.y); + lv_obj_remove_flag(indev->cursor, LV_OBJ_FLAG_CLICKABLE); + lv_obj_add_flag(indev->cursor, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_FLOATING); +} + +void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group) +{ + if(indev->type == LV_INDEV_TYPE_KEYPAD || indev->type == LV_INDEV_TYPE_ENCODER) { + indev->group = group; + } +} + +void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[]) +{ + if(indev->type == LV_INDEV_TYPE_BUTTON) { + indev->btn_points = points; + } +} + +void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point) +{ + if(indev == NULL) { + point->x = 0; + point->y = 0; + return; + } + if(indev->type != LV_INDEV_TYPE_POINTER && indev->type != LV_INDEV_TYPE_BUTTON) { + point->x = -1; + point->y = -1; + } + else { + point->x = indev->pointer.act_point.x; + point->y = indev->pointer.act_point.y; + } +} + +lv_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev) +{ + return indev->pointer.gesture_dir; +} + +uint32_t lv_indev_get_key(const lv_indev_t * indev) +{ + if(indev->type != LV_INDEV_TYPE_KEYPAD) + return 0; + else + return indev->keypad.last_key; +} + +lv_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev) +{ + if(indev == NULL) return false; + if(indev->type != LV_INDEV_TYPE_POINTER && indev->type != LV_INDEV_TYPE_BUTTON) return false; + return indev->pointer.scroll_dir; +} + +lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev) +{ + if(indev == NULL) return NULL; + if(indev->type != LV_INDEV_TYPE_POINTER && indev->type != LV_INDEV_TYPE_BUTTON) return NULL; + return indev->pointer.scroll_obj; +} + +void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point) +{ + point->x = 0; + point->y = 0; + + if(indev == NULL) return; + + if(indev->type == LV_INDEV_TYPE_POINTER || indev->type == LV_INDEV_TYPE_BUTTON) { + point->x = indev->pointer.vect.x; + point->y = indev->pointer.vect.y; + } +} + +void lv_indev_wait_release(lv_indev_t * indev) +{ + if(indev == NULL)return; + indev->wait_until_release = 1; +} + +lv_obj_t * lv_indev_get_active_obj(void) +{ + return indev_obj_act; +} + +lv_timer_t * lv_indev_get_read_timer(lv_indev_t * indev) +{ + if(!indev) { + LV_LOG_WARN("lv_indev_get_read_timer: indev was NULL"); + return NULL; + } + + return indev->read_timer; +} + +lv_indev_mode_t lv_indev_get_mode(lv_indev_t * indev) +{ + if(indev) return indev->mode; + return LV_INDEV_MODE_NONE; +} + +void lv_indev_set_mode(lv_indev_t * indev, lv_indev_mode_t mode) +{ + if(!indev || indev->mode == mode) + return; + + indev->mode = mode; + if(indev->read_timer) { + if(mode == LV_INDEV_MODE_EVENT) { + lv_timer_pause(indev->read_timer); + } + else if(mode == LV_INDEV_MODE_TIMER) { + /* use default timer mode*/ + lv_timer_set_cb(indev->read_timer, lv_indev_read_timer_cb); + lv_timer_resume(indev->read_timer); + } + } +} + +lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point) +{ + lv_obj_t * found_p = NULL; + + /*If this obj is hidden the children are hidden too so return immediately*/ + if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return NULL; + + lv_point_t p_trans = *point; + lv_obj_transform_point(obj, &p_trans, false, true); + + bool hit_test_ok = lv_obj_hit_test(obj, &p_trans); + + /*If the point is on this object check its children too*/ + lv_area_t obj_coords = obj->coords; + if(lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) { + int32_t ext_draw_size = _lv_obj_get_ext_draw_size(obj); + lv_area_increase(&obj_coords, ext_draw_size, ext_draw_size); + } + if(_lv_area_is_point_on(&obj_coords, &p_trans, 0)) { + int32_t i; + uint32_t child_cnt = lv_obj_get_child_count(obj); + + /*If a child matches use it*/ + for(i = child_cnt - 1; i >= 0; i--) { + lv_obj_t * child = obj->spec_attr->children[i]; + found_p = lv_indev_search_obj(child, &p_trans); + if(found_p) return found_p; + } + } + + /*If not return earlier for a clicked child and this obj's hittest was ok use it + *else return NULL*/ + if(hit_test_ok) return obj; + else return NULL; +} + +void lv_indev_add_event_cb(lv_indev_t * indev, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data) +{ + LV_ASSERT_NULL(indev); + + lv_event_add(&indev->event_list, event_cb, filter, user_data); +} + +uint32_t lv_indev_get_event_count(lv_indev_t * indev) +{ + LV_ASSERT_NULL(indev); + return lv_event_get_count(&indev->event_list); +} + +lv_event_dsc_t * lv_indev_get_event_dsc(lv_indev_t * indev, uint32_t index) +{ + LV_ASSERT_NULL(indev); + return lv_event_get_dsc(&indev->event_list, index); + +} + +bool lv_indev_remove_event(lv_indev_t * indev, uint32_t index) +{ + LV_ASSERT_NULL(indev); + + return lv_event_remove(&indev->event_list, index); +} + +uint32_t lv_indev_remove_event_cb_with_user_data(lv_indev_t * indev, lv_event_cb_t event_cb, void * user_data) +{ + LV_ASSERT_NULL(indev); + + uint32_t event_cnt = lv_indev_get_event_count(indev); + uint32_t removed_count = 0; + int32_t i; + + for(i = event_cnt - 1; i >= 0; i--) { + lv_event_dsc_t * dsc = lv_indev_get_event_dsc(indev, i); + if(dsc && dsc->cb == event_cb && dsc->user_data == user_data) { + lv_indev_remove_event(indev, i); + removed_count ++; + } + } + + return removed_count; +} + +lv_result_t lv_indev_send_event(lv_indev_t * indev, lv_event_code_t code, void * param) +{ + + lv_event_t e; + lv_memzero(&e, sizeof(e)); + e.code = code; + e.current_target = indev; + e.original_target = indev; + e.param = param; + lv_result_t res; + res = lv_event_send(&indev->event_list, &e, true); + if(res != LV_RESULT_OK) return res; + + res = lv_event_send(&indev->event_list, &e, false); + if(res != LV_RESULT_OK) return res; + + return res; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Process a new point from LV_INDEV_TYPE_POINTER input device + * @param i pointer to an input device + * @param data pointer to the data read from the input device + */ +static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data) +{ + lv_display_t * disp = i->disp; + /*Save the raw points so they can be used again in indev_read_core*/ + i->pointer.last_raw_point.x = data->point.x; + i->pointer.last_raw_point.y = data->point.y; + + if(disp->rotation == LV_DISPLAY_ROTATION_180 || disp->rotation == LV_DISPLAY_ROTATION_270) { + data->point.x = disp->hor_res - data->point.x - 1; + data->point.y = disp->ver_res - data->point.y - 1; + } + if(disp->rotation == LV_DISPLAY_ROTATION_90 || disp->rotation == LV_DISPLAY_ROTATION_270) { + int32_t tmp = data->point.y; + data->point.y = data->point.x; + data->point.x = disp->ver_res - tmp - 1; + } + + /*Simple sanity check*/ + if(data->point.x < 0) { + LV_LOG_WARN("X is %d which is smaller than zero", (int)data->point.x); + } + if(data->point.x >= lv_display_get_horizontal_resolution(i->disp)) { + LV_LOG_WARN("X is %d which is greater than hor. res", (int)data->point.x); + } + if(data->point.y < 0) { + LV_LOG_WARN("Y is %d which is smaller than zero", (int)data->point.y); + } + if(data->point.y >= lv_display_get_vertical_resolution(i->disp)) { + LV_LOG_WARN("Y is %d which is greater than ver. res", (int)data->point.y); + } + + /*Move the cursor if set and moved*/ + if(i->cursor != NULL && + (i->pointer.last_point.x != data->point.x || i->pointer.last_point.y != data->point.y)) { + lv_obj_set_pos(i->cursor, data->point.x, data->point.y); + } + + i->pointer.act_point.x = data->point.x; + i->pointer.act_point.y = data->point.y; + + if(i->state == LV_INDEV_STATE_PRESSED) { + indev_proc_press(i); + } + else { + indev_proc_release(i); + } + + i->pointer.last_point.x = i->pointer.act_point.x; + i->pointer.last_point.y = i->pointer.act_point.y; +} + +/** + * Process a new point from LV_INDEV_TYPE_KEYPAD input device + * @param i pointer to an input device + * @param data pointer to the data read from the input device + */ +static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data) +{ + if(data->state == LV_INDEV_STATE_PRESSED && i->wait_until_release) return; + + if(i->wait_until_release) { + i->wait_until_release = 0; + i->pr_timestamp = 0; + i->long_pr_sent = 0; + i->keypad.last_state = LV_INDEV_STATE_RELEASED; /*To skip the processing of release*/ + } + + lv_group_t * g = i->group; + if(g == NULL) return; + + indev_obj_act = lv_group_get_focused(g); + if(indev_obj_act == NULL) return; + + bool dis = lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED); + + /*Save the last key to compare it with the current latter on RELEASE*/ + uint32_t prev_key = i->keypad.last_key; + + /*Save the last key. + *It must be done here else `lv_indev_get_key` will return the last key in events*/ + i->keypad.last_key = data->key; + + /*Save the previous state so we can detect state changes below and also set the last state now + *so if any event handler on the way returns `LV_RESULT_INVALID` the last state is remembered + *for the next time*/ + uint32_t prev_state = i->keypad.last_state; + i->keypad.last_state = data->state; + + /*Key press happened*/ + if(data->state == LV_INDEV_STATE_PRESSED && prev_state == LV_INDEV_STATE_RELEASED) { + LV_LOG_INFO("%" LV_PRIu32 " key is pressed", data->key); + i->pr_timestamp = lv_tick_get(); + + /*Move the focus on NEXT*/ + if(data->key == LV_KEY_NEXT) { + lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/ + lv_group_focus_next(g); + if(indev_reset_check(i)) return; + } + /*Move the focus on PREV*/ + else if(data->key == LV_KEY_PREV) { + lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/ + lv_group_focus_prev(g); + if(indev_reset_check(i)) return; + } + else if(!dis) { + /*Simulate a press on the object if ENTER was pressed*/ + if(data->key == LV_KEY_ENTER) { + /*Send the ENTER as a normal KEY*/ + lv_group_send_data(g, LV_KEY_ENTER); + if(indev_reset_check(i)) return; + + if(send_event(LV_EVENT_PRESSED, indev_act) == LV_RESULT_INVALID) return; + + } + else if(data->key == LV_KEY_ESC) { + /*Send the ESC as a normal KEY*/ + lv_group_send_data(g, LV_KEY_ESC); + if(indev_reset_check(i)) return; + + if(send_event(LV_EVENT_CANCEL, indev_act) == LV_RESULT_INVALID) return; + } + /*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/ + else { + lv_group_send_data(g, data->key); + if(indev_reset_check(i)) return; + } + } + } + /*Pressing*/ + else if(!dis && data->state == LV_INDEV_STATE_PRESSED && prev_state == LV_INDEV_STATE_PRESSED) { + + if(data->key == LV_KEY_ENTER) { + if(send_event(LV_EVENT_PRESSING, indev_act) == LV_RESULT_INVALID) return; + } + + /*Long press time has elapsed?*/ + if(i->long_pr_sent == 0 && lv_tick_elaps(i->pr_timestamp) > i->long_press_time) { + i->long_pr_sent = 1; + if(data->key == LV_KEY_ENTER) { + i->longpr_rep_timestamp = lv_tick_get(); + + if(send_event(LV_EVENT_LONG_PRESSED, indev_act) == LV_RESULT_INVALID) return; + } + } + /*Long press repeated time has elapsed?*/ + else if(i->long_pr_sent != 0 && + lv_tick_elaps(i->longpr_rep_timestamp) > i->long_press_repeat_time) { + + i->longpr_rep_timestamp = lv_tick_get(); + + /*Send LONG_PRESS_REP on ENTER*/ + if(data->key == LV_KEY_ENTER) { + if(send_event(LV_EVENT_LONG_PRESSED_REPEAT, indev_act) == LV_RESULT_INVALID) return; + } + /*Move the focus on NEXT again*/ + else if(data->key == LV_KEY_NEXT) { + lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/ + lv_group_focus_next(g); + if(indev_reset_check(i)) return; + } + /*Move the focus on PREV again*/ + else if(data->key == LV_KEY_PREV) { + lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/ + lv_group_focus_prev(g); + if(indev_reset_check(i)) return; + } + /*Just send other keys again to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT)*/ + else { + lv_group_send_data(g, data->key); + if(indev_reset_check(i)) return; + } + } + } + /*Release happened*/ + else if(!dis && data->state == LV_INDEV_STATE_RELEASED && prev_state == LV_INDEV_STATE_PRESSED) { + LV_LOG_INFO("%" LV_PRIu32 " key is released", data->key); + /*The user might clear the key when it was released. Always release the pressed key*/ + data->key = prev_key; + if(data->key == LV_KEY_ENTER) { + + if(send_event(LV_EVENT_RELEASED, indev_act) == LV_RESULT_INVALID) return; + + if(i->long_pr_sent == 0) { + if(send_event(LV_EVENT_SHORT_CLICKED, indev_act) == LV_RESULT_INVALID) return; + } + + if(send_event(LV_EVENT_CLICKED, indev_act) == LV_RESULT_INVALID) return; + + } + i->pr_timestamp = 0; + i->long_pr_sent = 0; + } + indev_obj_act = NULL; +} + +/** + * Process a new point from LV_INDEV_TYPE_ENCODER input device + * @param i pointer to an input device + * @param data pointer to the data read from the input device + */ +static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) +{ + if(data->state == LV_INDEV_STATE_PRESSED && i->wait_until_release) return; + + if(i->wait_until_release) { + i->wait_until_release = 0; + i->pr_timestamp = 0; + i->long_pr_sent = 0; + i->keypad.last_state = LV_INDEV_STATE_RELEASED; /*To skip the processing of release*/ + } + + /*Save the last keys before anything else. + *They need to be already saved if the function returns for any reason*/ + lv_indev_state_t last_state = i->keypad.last_state; + i->keypad.last_state = data->state; + i->keypad.last_key = data->key; + + lv_group_t * g = i->group; + if(g == NULL) return; + + indev_obj_act = lv_group_get_focused(g); + if(indev_obj_act == NULL) return; + + /*Process the steps they are valid only with released button*/ + if(data->state != LV_INDEV_STATE_RELEASED) { + data->enc_diff = 0; + } + + const bool is_disabled = lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED); + + /*Button press happened*/ + if(data->state == LV_INDEV_STATE_PRESSED && last_state == LV_INDEV_STATE_RELEASED) { + LV_LOG_INFO("pressed"); + + i->pr_timestamp = lv_tick_get(); + + if(data->key == LV_KEY_ENTER) { + bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) || + lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE); + if(lv_group_get_editing(g) == true || editable_or_scrollable == false) { + + if(!is_disabled) { + if(send_event(LV_EVENT_PRESSED, indev_act) == LV_RESULT_INVALID) return; + } + } + } + else if(data->key == LV_KEY_LEFT) { + /*emulate encoder left*/ + data->enc_diff--; + } + else if(data->key == LV_KEY_RIGHT) { + /*emulate encoder right*/ + data->enc_diff++; + } + else if(data->key == LV_KEY_ESC) { + /*Send the ESC as a normal KEY*/ + lv_group_send_data(g, LV_KEY_ESC); + if(indev_reset_check(i)) return; + + if(!is_disabled) { + if(send_event(LV_EVENT_CANCEL, indev_act) == LV_RESULT_INVALID) return; + } + } + /*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/ + else { + lv_group_send_data(g, data->key); + if(indev_reset_check(i)) return; + } + } + /*Pressing*/ + else if(data->state == LV_INDEV_STATE_PRESSED && last_state == LV_INDEV_STATE_PRESSED) { + /*Long press*/ + if(i->long_pr_sent == 0 && lv_tick_elaps(i->pr_timestamp) > i->long_press_time) { + + i->long_pr_sent = 1; + i->longpr_rep_timestamp = lv_tick_get(); + + if(data->key == LV_KEY_ENTER) { + bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) || + lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE); + + /*On enter long press toggle edit mode.*/ + if(editable_or_scrollable) { + /*Don't leave edit mode if there is only one object (nowhere to navigate)*/ + if(lv_group_get_obj_count(g) > 1) { + LV_LOG_INFO("toggling edit mode"); + lv_group_set_editing(g, lv_group_get_editing(g) ? false : true); /*Toggle edit mode on long press*/ + lv_obj_remove_state(indev_obj_act, LV_STATE_PRESSED); /*Remove the pressed state manually*/ + } + } + /*If not editable then just send a long press event*/ + else { + if(!is_disabled) { + if(send_event(LV_EVENT_LONG_PRESSED, indev_act) == LV_RESULT_INVALID) return; + } + } + } + + i->long_pr_sent = 1; + } + /*Long press repeated time has elapsed?*/ + else if(i->long_pr_sent != 0 && lv_tick_elaps(i->longpr_rep_timestamp) > i->long_press_repeat_time) { + + i->longpr_rep_timestamp = lv_tick_get(); + + if(data->key == LV_KEY_ENTER) { + if(!is_disabled) { + if(send_event(LV_EVENT_LONG_PRESSED_REPEAT, indev_act) == LV_RESULT_INVALID) return; + } + } + else if(data->key == LV_KEY_LEFT) { + /*emulate encoder left*/ + data->enc_diff--; + } + else if(data->key == LV_KEY_RIGHT) { + /*emulate encoder right*/ + data->enc_diff++; + } + else { + lv_group_send_data(g, data->key); + if(indev_reset_check(i)) return; + } + + } + + } + /*Release happened*/ + else if(data->state == LV_INDEV_STATE_RELEASED && last_state == LV_INDEV_STATE_PRESSED) { + LV_LOG_INFO("released"); + + if(data->key == LV_KEY_ENTER) { + bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) || + lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE); + + /*The button was released on a non-editable object. Just send enter*/ + if(editable_or_scrollable == false) { + if(!is_disabled) { + if(send_event(LV_EVENT_RELEASED, indev_act) == LV_RESULT_INVALID) return; + } + + if(i->long_pr_sent == 0 && !is_disabled) { + if(send_event(LV_EVENT_SHORT_CLICKED, indev_act) == LV_RESULT_INVALID) return; + } + + if(!is_disabled) { + if(send_event(LV_EVENT_CLICKED, indev_act) == LV_RESULT_INVALID) return; + } + + } + /*An object is being edited and the button is released.*/ + else if(lv_group_get_editing(g)) { + /*Ignore long pressed enter release because it comes from mode switch*/ + if(!i->long_pr_sent || lv_group_get_obj_count(g) <= 1) { + if(!is_disabled) { + if(send_event(LV_EVENT_RELEASED, indev_act) == LV_RESULT_INVALID) return; + if(send_event(LV_EVENT_SHORT_CLICKED, indev_act) == LV_RESULT_INVALID) return; + if(send_event(LV_EVENT_CLICKED, indev_act) == LV_RESULT_INVALID) return; + } + + lv_group_send_data(g, LV_KEY_ENTER); + if(indev_reset_check(i)) return; + } + else { + lv_obj_remove_state(indev_obj_act, LV_STATE_PRESSED); /*Remove the pressed state manually*/ + } + } + /*If the focused object is editable and now in navigate mode then on enter switch edit + mode*/ + else if(!i->long_pr_sent) { + LV_LOG_INFO("entering edit mode"); + lv_group_set_editing(g, true); /*Set edit mode*/ + } + } + + i->pr_timestamp = 0; + i->long_pr_sent = 0; + } + indev_obj_act = NULL; + + /*if encoder steps or simulated steps via left/right keys*/ + if(data->enc_diff != 0) { + /*In edit mode send LEFT/RIGHT keys*/ + if(lv_group_get_editing(g)) { + LV_LOG_INFO("rotated by %+d (edit)", data->enc_diff); + int32_t s; + if(data->enc_diff < 0) { + for(s = 0; s < -data->enc_diff; s++) { + lv_group_send_data(g, LV_KEY_LEFT); + if(indev_reset_check(i)) return; + } + } + else if(data->enc_diff > 0) { + for(s = 0; s < data->enc_diff; s++) { + lv_group_send_data(g, LV_KEY_RIGHT); + if(indev_reset_check(i)) return; + } + } + } + /*In navigate mode focus on the next/prev objects*/ + else { + LV_LOG_INFO("rotated by %+d (nav)", data->enc_diff); + int32_t s; + if(data->enc_diff < 0) { + for(s = 0; s < -data->enc_diff; s++) { + lv_group_focus_prev(g); + if(indev_reset_check(i)) return; + } + } + else if(data->enc_diff > 0) { + for(s = 0; s < data->enc_diff; s++) { + lv_group_focus_next(g); + if(indev_reset_check(i)) return; + } + } + } + } +} + +/** + * Process new points from an input device. indev->state.pressed has to be set + * @param indev pointer to an input device state + * @param x x coordinate of the next point + * @param y y coordinate of the next point + */ +static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data) +{ + /*Die gracefully if i->btn_points is NULL*/ + if(i->btn_points == NULL) { + LV_LOG_WARN("btn_points is NULL"); + return; + } + + int32_t x = i->btn_points[data->btn_id].x; + int32_t y = i->btn_points[data->btn_id].y; + + if(LV_INDEV_STATE_RELEASED != data->state) { + if(data->state == LV_INDEV_STATE_PRESSED) { + LV_LOG_INFO("button %" LV_PRIu32 " is pressed (x:%d y:%d)", data->btn_id, (int)x, (int)y); + } + else { + LV_LOG_INFO("button %" LV_PRIu32 " is released (x:%d y:%d)", data->btn_id, (int)x, (int)y); + } + } + + /*If a new point comes always make a release*/ + if(data->state == LV_INDEV_STATE_PRESSED) { + if(i->pointer.last_point.x != x || + i->pointer.last_point.y != y) { + indev_proc_release(i); + } + } + + if(indev_reset_check(i)) return; + + /*Save the new points*/ + i->pointer.act_point.x = x; + i->pointer.act_point.y = y; + + if(data->state == LV_INDEV_STATE_PRESSED) indev_proc_press(i); + else indev_proc_release(i); + + if(indev_reset_check(i)) return; + + i->pointer.last_point.x = i->pointer.act_point.x; + i->pointer.last_point.y = i->pointer.act_point.y; +} + +/** + * Process the pressed state of LV_INDEV_TYPE_POINTER input devices + * @param indev pointer to an input device 'proc' + */ +static void indev_proc_press(lv_indev_t * indev) +{ + LV_LOG_INFO("pressed at x:%d y:%d", (int)indev->pointer.act_point.x, + (int)indev->pointer.act_point.y); + indev_obj_act = indev->pointer.act_obj; + + if(indev->wait_until_release != 0) return; + + lv_display_t * disp = indev_act->disp; + bool new_obj_searched = false; + + /*If there is no last object then search*/ + if(indev_obj_act == NULL) { + indev_obj_act = pointer_search_obj(disp, &indev->pointer.act_point); + new_obj_searched = true; + } + /*If there is an active object it's not scrolled and not protected also search*/ + else if(indev->pointer.scroll_obj == NULL && + lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_PRESS_LOCK) == false) { + indev_obj_act = pointer_search_obj(disp, &indev->pointer.act_point); + new_obj_searched = true; + } + + /*The last object might have scroll throw. Stop it manually*/ + if(new_obj_searched && indev->pointer.last_obj) { + + /*Attempt to stop scroll throw animation firstly*/ + if(!indev->scroll_throw_anim || !lv_anim_delete(indev, indev_scroll_throw_anim_cb)) { + indev_scroll_throw_anim_reset(indev); + } + + _lv_indev_scroll_throw_handler(indev); + if(indev_reset_check(indev)) return; + } + + /*If a new object was found reset some variables and send a pressed event handler*/ + if(indev_obj_act != indev->pointer.act_obj) { + indev->pointer.last_point.x = indev->pointer.act_point.x; + indev->pointer.last_point.y = indev->pointer.act_point.y; + + /*If a new object found the previous was lost, so send a PRESS_LOST event*/ + if(indev->pointer.act_obj != NULL) { + /*Save the obj because in special cases `act_obj` can change in the event */ + lv_obj_t * last_obj = indev->pointer.act_obj; + + lv_obj_send_event(last_obj, LV_EVENT_PRESS_LOST, indev_act); + if(indev_reset_check(indev)) return; + + /*Do nothing until release and a new press*/ + lv_indev_reset(indev, NULL); + lv_indev_wait_release(indev); + return; + } + + indev->pointer.act_obj = indev_obj_act; /*Save the pressed object*/ + indev->pointer.last_obj = indev_obj_act; + + if(indev_obj_act != NULL) { + + /*Save the time when the obj pressed to count long press time.*/ + indev->pr_timestamp = lv_tick_get(); + indev->long_pr_sent = 0; + indev->pointer.scroll_sum.x = 0; + indev->pointer.scroll_sum.y = 0; + indev->pointer.scroll_dir = LV_DIR_NONE; + indev->pointer.gesture_dir = LV_DIR_NONE; + indev->pointer.gesture_sent = 0; + indev->pointer.gesture_sum.x = 0; + indev->pointer.gesture_sum.y = 0; + indev->pointer.vect.x = 0; + indev->pointer.vect.y = 0; + + const bool is_disabled = lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED); + if(!is_disabled) { + if(send_event(LV_EVENT_PRESSED, indev_act) == LV_RESULT_INVALID) return; + } + + if(indev_act->wait_until_release) return; + + /*Handle focus*/ + indev_click_focus(indev_act); + if(indev_reset_check(indev)) return; + + } + } + + /*Calculate the vector and apply a low pass filter: new value = 0.5 * old_value + 0.5 * new_value*/ + indev->pointer.vect.x = indev->pointer.act_point.x - indev->pointer.last_point.x; + indev->pointer.vect.y = indev->pointer.act_point.y - indev->pointer.last_point.y; + + indev->pointer.scroll_throw_vect.x = (indev->pointer.scroll_throw_vect.x + indev->pointer.vect.x) / 2; + indev->pointer.scroll_throw_vect.y = (indev->pointer.scroll_throw_vect.y + indev->pointer.vect.y) / 2; + + indev->pointer.scroll_throw_vect_ori = indev->pointer.scroll_throw_vect; + + if(indev_obj_act) { + const bool is_disabled = lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED); + + if(!is_disabled) { + if(send_event(LV_EVENT_PRESSING, indev_act) == LV_RESULT_INVALID) return; + } + + if(indev_act->wait_until_release) return; + + _lv_indev_scroll_handler(indev); + if(indev_reset_check(indev)) return; + indev_gesture(indev); + if(indev_reset_check(indev)) return; + + if(indev->mode == LV_INDEV_MODE_EVENT && indev->read_timer && lv_timer_get_paused(indev->read_timer)) { + lv_timer_resume(indev->read_timer); + } + + /*If there is no scrolling then check for long press time*/ + if(indev->pointer.scroll_obj == NULL && indev->long_pr_sent == 0) { + /*Send a long press event if enough time elapsed*/ + if(lv_tick_elaps(indev->pr_timestamp) > indev_act->long_press_time) { + if(!is_disabled) { + if(send_event(LV_EVENT_LONG_PRESSED, indev_act) == LV_RESULT_INVALID) return; + } + /*Mark it to do not send the event again*/ + indev->long_pr_sent = 1; + + /*Save the long press time stamp for the long press repeat handler*/ + indev->longpr_rep_timestamp = lv_tick_get(); + } + } + + if(indev->pointer.scroll_obj == NULL && indev->long_pr_sent == 1) { + if(lv_tick_elaps(indev->longpr_rep_timestamp) > indev_act->long_press_repeat_time) { + if(!is_disabled) { + if(send_event(LV_EVENT_LONG_PRESSED_REPEAT, indev_act) == LV_RESULT_INVALID) return; + } + indev->longpr_rep_timestamp = lv_tick_get(); + } + } + } +} + +/** + * Process the released state of LV_INDEV_TYPE_POINTER input devices + * @param proc pointer to an input device 'proc' + */ +static void indev_proc_release(lv_indev_t * indev) +{ + if(indev->wait_until_release) { + lv_obj_send_event(indev->pointer.act_obj, LV_EVENT_PRESS_LOST, indev_act); + if(indev_reset_check(indev)) return; + + indev->pointer.act_obj = NULL; + indev->pointer.last_obj = NULL; + indev->pr_timestamp = 0; + indev->longpr_rep_timestamp = 0; + indev->wait_until_release = 0; + } + indev_obj_act = indev->pointer.act_obj; + lv_obj_t * scroll_obj = indev->pointer.scroll_obj; + + if(indev->mode == LV_INDEV_MODE_EVENT && indev->read_timer && !lv_timer_get_paused(indev->read_timer)) { + lv_timer_pause(indev->read_timer); + } + + if(indev_obj_act) { + LV_LOG_INFO("released"); + + const bool is_disabled = lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED); + + if(!is_disabled) { + if(send_event(LV_EVENT_RELEASED, indev_act) == LV_RESULT_INVALID) return; + } + + if(!is_disabled) { + if(scroll_obj == NULL) { + if(indev->long_pr_sent == 0) { + if(send_event(LV_EVENT_SHORT_CLICKED, indev_act) == LV_RESULT_INVALID) return; + } + if(send_event(LV_EVENT_CLICKED, indev_act) == LV_RESULT_INVALID) return; + } + else { + if(send_event(LV_EVENT_SCROLL_THROW_BEGIN, indev_act) == LV_RESULT_INVALID) return; + } + } + indev->pointer.act_obj = NULL; + indev->pr_timestamp = 0; + indev->longpr_rep_timestamp = 0; + + /*Get the transformed vector with this object*/ + if(scroll_obj) { + int16_t angle = 0; + int16_t scale_x = 256; + int16_t scale_y = 256; + lv_point_t pivot = { 0, 0 }; + lv_obj_t * parent = scroll_obj; + while(parent) { + angle += lv_obj_get_style_transform_rotation(parent, 0); + int32_t zoom_act_x = lv_obj_get_style_transform_scale_x_safe(parent, 0); + int32_t zoom_act_y = lv_obj_get_style_transform_scale_y_safe(parent, 0); + scale_x = (scale_x * zoom_act_x) >> 8; + scale_y = (scale_x * zoom_act_y) >> 8; + parent = lv_obj_get_parent(parent); + } + + if(angle != 0 || scale_y != LV_SCALE_NONE || scale_x != LV_SCALE_NONE) { + angle = -angle; + scale_x = (256 * 256) / scale_x; + scale_y = (256 * 256) / scale_y; + lv_point_transform(&indev->pointer.scroll_throw_vect, angle, scale_x, scale_y, &pivot, false); + lv_point_transform(&indev->pointer.scroll_throw_vect_ori, angle, scale_x, scale_y, &pivot, false); + } + } + + } + + if(scroll_obj) { + if(!indev->scroll_throw_anim) { + indev_scroll_throw_anim_start(indev); + } + + if(indev_reset_check(indev)) return; + } +} + +static lv_obj_t * pointer_search_obj(lv_display_t * disp, lv_point_t * p) +{ + indev_obj_act = lv_indev_search_obj(lv_display_get_layer_sys(disp), p); + if(indev_obj_act) return indev_obj_act; + + indev_obj_act = lv_indev_search_obj(lv_display_get_layer_top(disp), p); + if(indev_obj_act) return indev_obj_act; + + /* Search the object in the active screen */ + indev_obj_act = lv_indev_search_obj(lv_display_get_screen_active(disp), p); + if(indev_obj_act) return indev_obj_act; + + indev_obj_act = lv_indev_search_obj(lv_display_get_layer_bottom(disp), p); + return indev_obj_act; +} + +/** + * Process a new point from LV_INDEV_TYPE_BUTTON input device + * @param i pointer to an input device + * @param data pointer to the data read from the input device + * Reset input device if a reset query has been sent to it + * @param indev pointer to an input device + */ +static void indev_proc_reset_query_handler(lv_indev_t * indev) +{ + if(indev->reset_query) { + indev->pointer.act_obj = NULL; + indev->pointer.last_obj = NULL; + indev->pointer.scroll_obj = NULL; + indev->long_pr_sent = 0; + indev->pr_timestamp = 0; + indev->longpr_rep_timestamp = 0; + indev->pointer.scroll_sum.x = 0; + indev->pointer.scroll_sum.y = 0; + indev->pointer.scroll_dir = LV_DIR_NONE; + indev->pointer.scroll_throw_vect.x = 0; + indev->pointer.scroll_throw_vect.y = 0; + indev->pointer.gesture_sum.x = 0; + indev->pointer.gesture_sum.y = 0; + indev->reset_query = 0; + indev_obj_act = NULL; + } +} + +/** + * Handle focus/defocus on click for POINTER input devices + * @param proc pointer to the state of the indev + */ +static void indev_click_focus(lv_indev_t * indev) +{ + /*Handle click focus*/ + if(lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_CLICK_FOCUSABLE) == false) { + return; + } + + lv_group_t * g_act = lv_obj_get_group(indev_obj_act); + lv_group_t * g_prev = indev->pointer.last_pressed ? lv_obj_get_group(indev->pointer.last_pressed) : NULL; + + /*If both the last and act. obj. are in the same group (or have no group)*/ + if(g_act == g_prev) { + /*The objects are in a group*/ + if(g_act) { + lv_group_focus_obj(indev_obj_act); + if(indev_reset_check(indev)) return; + } + /*The object are not in group*/ + else { + if(indev->pointer.last_pressed != indev_obj_act) { + lv_obj_send_event(indev->pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act); + if(indev_reset_check(indev)) return; + + lv_obj_send_event(indev_obj_act, LV_EVENT_FOCUSED, indev_act); + if(indev_reset_check(indev)) return; + } + } + } + /*The object are not in the same group (in different groups or one has no group)*/ + else { + /*If the prev. obj. is not in a group then defocus it.*/ + if(g_prev == NULL && indev->pointer.last_pressed) { + lv_obj_send_event(indev->pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act); + if(indev_reset_check(indev)) return; + } + /*Focus on a non-group object*/ + else { + if(indev->pointer.last_pressed) { + /*If the prev. object also wasn't in a group defocus it*/ + if(g_prev == NULL) { + lv_obj_send_event(indev->pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act); + if(indev_reset_check(indev)) return; + } + /*If the prev. object also was in a group at least "LEAVE" it instead of defocus*/ + else { + lv_obj_send_event(indev->pointer.last_pressed, LV_EVENT_LEAVE, indev_act); + if(indev_reset_check(indev)) return; + } + } + } + + /*Focus to the act. in its group*/ + if(g_act) { + lv_group_focus_obj(indev_obj_act); + if(indev_reset_check(indev)) return; + } + else { + lv_obj_send_event(indev_obj_act, LV_EVENT_FOCUSED, indev_act); + if(indev_reset_check(indev)) return; + } + } + indev->pointer.last_pressed = indev_obj_act; +} + +/** +* Handle the gesture of indev_proc_p->pointer.act_obj +* @param indev pointer to an input device state +*/ +void indev_gesture(lv_indev_t * indev) +{ + if(indev->pointer.scroll_obj) return; + if(indev->pointer.gesture_sent) return; + + lv_obj_t * gesture_obj = indev->pointer.act_obj; + + /*If gesture parent is active check recursively the gesture attribute*/ + while(gesture_obj && lv_obj_has_flag(gesture_obj, LV_OBJ_FLAG_GESTURE_BUBBLE)) { + gesture_obj = lv_obj_get_parent(gesture_obj); + } + + if(gesture_obj == NULL) return; + + if((LV_ABS(indev->pointer.vect.x) < indev_act->gesture_min_velocity) && + (LV_ABS(indev->pointer.vect.y) < indev_act->gesture_min_velocity)) { + indev->pointer.gesture_sum.x = 0; + indev->pointer.gesture_sum.y = 0; + } + + /*Count the movement by gesture*/ + indev->pointer.gesture_sum.x += indev->pointer.vect.x; + indev->pointer.gesture_sum.y += indev->pointer.vect.y; + + if((LV_ABS(indev->pointer.gesture_sum.x) > indev_act->gesture_limit) || + (LV_ABS(indev->pointer.gesture_sum.y) > indev_act->gesture_limit)) { + + indev->pointer.gesture_sent = 1; + + if(LV_ABS(indev->pointer.gesture_sum.x) > LV_ABS(indev->pointer.gesture_sum.y)) { + if(indev->pointer.gesture_sum.x > 0) + indev->pointer.gesture_dir = LV_DIR_RIGHT; + else + indev->pointer.gesture_dir = LV_DIR_LEFT; + } + else { + if(indev->pointer.gesture_sum.y > 0) + indev->pointer.gesture_dir = LV_DIR_BOTTOM; + else + indev->pointer.gesture_dir = LV_DIR_TOP; + } + + lv_obj_send_event(gesture_obj, LV_EVENT_GESTURE, indev_act); + if(indev_reset_check(indev)) return; + + lv_indev_send_event(indev_act, LV_EVENT_LONG_PRESSED, gesture_obj); + if(indev_reset_check(indev_act)) return; + } +} + +/** + * Checks if the reset_query flag has been set. If so, perform necessary global indev cleanup actions + * @param proc pointer to an input device 'proc' + * @return true if indev query should be immediately truncated. + */ +static bool indev_reset_check(lv_indev_t * indev) +{ + if(indev->reset_query) { + indev_obj_act = NULL; + } + + return indev->reset_query; +} + +/** + * Reset the indev and send event to active obj and scroll obj + * @param indev pointer to an input device + * @param obj pointer to obj +*/ +static void indev_reset_core(lv_indev_t * indev, lv_obj_t * obj) +{ + lv_obj_t * act_obj = NULL; + lv_obj_t * scroll_obj = NULL; + + indev->reset_query = 1; + if(indev_act == indev) indev_obj_act = NULL; + if(indev->type == LV_INDEV_TYPE_POINTER || indev->type == LV_INDEV_TYPE_KEYPAD) { + if(obj == NULL || indev->pointer.last_pressed == obj) { + indev->pointer.last_pressed = NULL; + } + if(obj == NULL || indev->pointer.act_obj == obj) { + if(indev->pointer.act_obj) { + /* Avoid recursive calls */ + act_obj = indev->pointer.act_obj; + indev->pointer.act_obj = NULL; + lv_obj_send_event(act_obj, LV_EVENT_INDEV_RESET, indev); + lv_indev_send_event(indev, LV_EVENT_INDEV_RESET, act_obj); + act_obj = NULL; + } + } + if(obj == NULL || indev->pointer.last_obj == obj) { + indev->pointer.last_obj = NULL; + } + if(obj == NULL || indev->pointer.scroll_obj == obj) { + if(indev->pointer.scroll_obj) { + /* Avoid recursive calls */ + scroll_obj = indev->pointer.scroll_obj; + indev->pointer.scroll_obj = NULL; + lv_obj_send_event(scroll_obj, LV_EVENT_INDEV_RESET, indev); + lv_indev_send_event(indev, LV_EVENT_INDEV_RESET, act_obj); + scroll_obj = NULL; + } + } + } +} + +static lv_result_t send_event(lv_event_code_t code, void * param) +{ + lv_obj_send_event(indev_obj_act, code, param); + if(indev_reset_check(indev_act)) return LV_RESULT_INVALID; + + if(code == LV_EVENT_PRESSED || + code == LV_EVENT_CLICKED || + code == LV_EVENT_RELEASED || + code == LV_EVENT_LONG_PRESSED || + code == LV_EVENT_LONG_PRESSED_REPEAT) { + lv_indev_send_event(indev_act, code, indev_obj_act); + if(indev_reset_check(indev_act)) return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; +} + +static void indev_scroll_throw_anim_cb(void * var, int32_t v) +{ + LV_ASSERT_NULL(var); + LV_UNUSED(v); + lv_indev_t * indev = (lv_indev_t *)var; + + _lv_indev_scroll_throw_handler(indev); + + if(indev->pointer.scroll_dir == LV_DIR_NONE || indev->pointer.scroll_obj == NULL) { + if(indev->scroll_throw_anim) { + LV_LOG_INFO("stop animation"); + lv_anim_delete(indev, indev_scroll_throw_anim_cb); + } + } +} + +static void indev_scroll_throw_anim_completed_cb(lv_anim_t * anim) +{ + if(anim) { + indev_scroll_throw_anim_reset((lv_indev_t *)anim->var); + } +} + +static void indev_scroll_throw_anim_start(lv_indev_t * indev) +{ + LV_ASSERT_NULL(indev); + + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, indev); + lv_anim_set_duration(&a, 1024); + lv_anim_set_values(&a, 0, 1024); + lv_anim_set_exec_cb(&a, indev_scroll_throw_anim_cb); + lv_anim_set_completed_cb(&a, indev_scroll_throw_anim_completed_cb); + lv_anim_set_deleted_cb(&a, indev_scroll_throw_anim_completed_cb); + lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); + + indev->scroll_throw_anim = lv_anim_start(&a); +} diff --git a/lib/libesp32_lvgl/lvgl/src/indev/lv_indev.h b/lib/libesp32_lvgl/lvgl/src/indev/lv_indev.h new file mode 100644 index 000000000..62e44b8ea --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/indev/lv_indev.h @@ -0,0 +1,324 @@ +/** + * @file lv_indev.h + * + */ + +#ifndef LV_INDEV_H +#define LV_INDEV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../core/lv_group.h" +#include "../misc/lv_area.h" +#include "../misc/lv_timer.h" +#include "../misc/lv_event.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** Possible input device types*/ +typedef enum { + LV_INDEV_TYPE_NONE, /**< Uninitialized state*/ + LV_INDEV_TYPE_POINTER, /**< Touch pad, mouse, external button*/ + LV_INDEV_TYPE_KEYPAD, /**< Keypad or keyboard*/ + LV_INDEV_TYPE_BUTTON, /**< External (hardware button) which is assigned to a specific point of the screen*/ + LV_INDEV_TYPE_ENCODER, /**< Encoder with only Left, Right turn and a Button*/ +} lv_indev_type_t; + +/** States for input devices*/ +typedef enum { + LV_INDEV_STATE_RELEASED = 0, + LV_INDEV_STATE_PRESSED +} lv_indev_state_t; + +typedef enum { + LV_INDEV_MODE_NONE = 0, + LV_INDEV_MODE_TIMER, + LV_INDEV_MODE_EVENT, +} lv_indev_mode_t; + +/** Data structure passed to an input driver to fill*/ +typedef struct { + lv_point_t point; /**< For LV_INDEV_TYPE_POINTER the currently pressed point*/ + uint32_t key; /**< For LV_INDEV_TYPE_KEYPAD the currently pressed key*/ + uint32_t btn_id; /**< For LV_INDEV_TYPE_BUTTON the currently pressed button*/ + int16_t enc_diff; /**< For LV_INDEV_TYPE_ENCODER number of steps since the previous read*/ + + lv_indev_state_t state; /**< LV_INDEV_STATE_REL or LV_INDEV_STATE_PR*/ + bool continue_reading; /**< If set to true, the read callback is invoked again*/ +} lv_indev_data_t; + +typedef void (*lv_indev_read_cb_t)(lv_indev_t * indev, lv_indev_data_t * data); + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_indev_t * lv_indev_create(void); + +/** + * Remove the provided input device. Make sure not to use the provided input device afterwards anymore. + * @param indev pointer to delete + */ +void lv_indev_delete(lv_indev_t * indev); + +/** + * Get the next input device. + * @param indev pointer to the current input device. NULL to initialize. + * @return the next input device or NULL if there are no more. Provide the first input device when + * the parameter is NULL + */ +lv_indev_t * lv_indev_get_next(lv_indev_t * indev); + +/** + * Read data from an input device. + * @param indev pointer to an input device + */ +void lv_indev_read(lv_indev_t * indev); + +/** + * Called periodically to read the input devices + * @param timer pointer to a timer to read + */ +void lv_indev_read_timer_cb(lv_timer_t * timer); + +/** + * Enable or disable one or all input devices (default enabled) + * @param indev pointer to an input device or NULL to enable/disable all of them + * @param en true to enable, false to disable + */ +void lv_indev_enable(lv_indev_t * indev, bool en); + +/** + * Get the currently processed input device. Can be used in action functions too. + * @return pointer to the currently processed input device or NULL if no input device processing + * right now + */ +lv_indev_t * lv_indev_active(void); + +/** + * Set the type of an input device + * @param indev pointer to an input device + * @param indev_type the type of the input device from `lv_indev_type_t` (`LV_INDEV_TYPE_...`) + */ +void lv_indev_set_type(lv_indev_t * indev, lv_indev_type_t indev_type); + +void lv_indev_set_read_cb(lv_indev_t * indev, lv_indev_read_cb_t read_cb); + +void lv_indev_set_user_data(lv_indev_t * indev, void * user_data); + +void lv_indev_set_driver_data(lv_indev_t * indev, void * driver_data); + +/** + * Get the type of an input device + * @param indev pointer to an input device + * @return the type of the input device from `lv_hal_indev_type_t` (`LV_INDEV_TYPE_...`) + */ +lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev); + +lv_indev_read_cb_t lv_indev_get_read_cb(lv_indev_t * indev); + +lv_indev_state_t lv_indev_get_state(const lv_indev_t * indev); + +lv_group_t * lv_indev_get_group(const lv_indev_t * indev); + +void lv_indev_set_display(lv_indev_t * indev, struct _lv_display_t * disp); + +lv_display_t * lv_indev_get_display(const lv_indev_t * indev); + +void * lv_indev_get_user_data(const lv_indev_t * indev); + +void * lv_indev_get_driver_data(const lv_indev_t * indev); + +/** + * Reset one or all input devices + * @param indev pointer to an input device to reset or NULL to reset all of them + * @param obj pointer to an object which triggers the reset. + */ +void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj); + +/** + * Reset the long press state of an input device + * @param indev pointer to an input device + */ +void lv_indev_reset_long_press(lv_indev_t * indev); + +/** + * Set a cursor for a pointer input device (for LV_INPUT_TYPE_POINTER and LV_INPUT_TYPE_BUTTON) + * @param indev pointer to an input device + * @param cur_obj pointer to an object to be used as cursor + */ +void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj); + +/** + * Set a destination group for a keypad input device (for LV_INDEV_TYPE_KEYPAD) + * @param indev pointer to an input device + * @param group pointer to a group + */ +void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group); + +/** + * Set the an array of points for LV_INDEV_TYPE_BUTTON. + * These points will be assigned to the buttons to press a specific point on the screen + * @param indev pointer to an input device + * @param points array of points + */ +void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[]); + +/** + * Get the last point of an input device (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON) + * @param indev pointer to an input device + * @param point pointer to a point to store the result + */ +void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point); + +/** +* Get the current gesture direct +* @param indev pointer to an input device +* @return current gesture direct +*/ +lv_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev); + +/** + * Get the last pressed key of an input device (for LV_INDEV_TYPE_KEYPAD) + * @param indev pointer to an input device + * @return the last pressed key (0 on error) + */ +uint32_t lv_indev_get_key(const lv_indev_t * indev); + +/** + * Check the current scroll direction of an input device (for LV_INDEV_TYPE_POINTER and + * LV_INDEV_TYPE_BUTTON) + * @param indev pointer to an input device + * @return LV_DIR_NONE: no scrolling now + * LV_DIR_HOR/VER + */ +lv_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev); + +/** + * Get the currently scrolled object (for LV_INDEV_TYPE_POINTER and + * LV_INDEV_TYPE_BUTTON) + * @param indev pointer to an input device + * @return pointer to the currently scrolled object or NULL if no scrolling by this indev + */ +lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev); + +/** + * Get the movement vector of an input device (for LV_INDEV_TYPE_POINTER and + * LV_INDEV_TYPE_BUTTON) + * @param indev pointer to an input device + * @param point pointer to a point to store the types.pointer.vector + */ +void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point); + +/** + * Do nothing until the next release + * @param indev pointer to an input device + */ +void lv_indev_wait_release(lv_indev_t * indev); + +/** + * Gets a pointer to the currently active object in the currently processed input device. + * @return pointer to currently active object or NULL if no active object + */ +lv_obj_t * lv_indev_get_active_obj(void); + +/** + * Get a pointer to the indev read timer to + * modify its parameters with `lv_timer_...` functions. + * @param indev pointer to an input device + * @return pointer to the indev read refresher timer. (NULL on error) + */ +lv_timer_t * lv_indev_get_read_timer(lv_indev_t * indev); + +/** +* Set the input device's event model: event-driven mode or timer mode. +* @param indev pointer to an input device +* @param mode the mode of input device +*/ +void lv_indev_set_mode(lv_indev_t * indev, lv_indev_mode_t mode); + +/** + * Get the input device's running mode. + * @param indev pointer to an input device + * @return the running mode for the specified input device. + */ +lv_indev_mode_t lv_indev_get_mode(lv_indev_t * indev); + +/** + * Search the most top, clickable object by a point + * @param obj pointer to a start object, typically the screen + * @param point pointer to a point for searching the most top child + * @return pointer to the found object or NULL if there was no suitable object + */ +lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point); + +/** + * Add an event handler to the indev + * @param indev pointer to an indev + * @param event_cb an event callback + * @param filter event code to react or `LV_EVENT_ALL` + * @param user_data optional user_data + */ +void lv_indev_add_event_cb(lv_indev_t * indev, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data); + +/** + * Get the number of event attached to an indev + * @param indev pointer to an indev + * @return number of events + */ +uint32_t lv_indev_get_event_count(lv_indev_t * indev); + +/** + * Get an event descriptor for an event + * @param indev pointer to an indev + * @param index the index of the event + * @return the event descriptor + */ +lv_event_dsc_t * lv_indev_get_event_dsc(lv_indev_t * indev, uint32_t index); + +/** + * Remove an event + * @param indev pointer to an indev + * @param index the index of the event to remove + * @return true: and event was removed; false: no event was removed + */ +bool lv_indev_remove_event(lv_indev_t * indev, uint32_t index); + +/** + * Remove an event_cb with user_data + * @param indev pointer to a indev + * @param event_cb the event_cb of the event to remove + * @param user_data user_data + * @return the count of the event removed + */ +uint32_t lv_indev_remove_event_cb_with_user_data(lv_indev_t * indev, lv_event_cb_t event_cb, void * user_data); + +/** + * Send an event to an indev + * @param indev pointer to an indev + * @param code an event code. LV_EVENT_... + * @param param optional param + * @return LV_RESULT_OK: indev wasn't deleted in the event. + */ +lv_result_t lv_indev_send_event(lv_indev_t * indev, lv_event_code_t code, void * param); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_INDEV_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/indev/lv_indev_private.h b/lib/libesp32_lvgl/lvgl/src/indev/lv_indev_private.h new file mode 100644 index 000000000..70b428836 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/indev/lv_indev_private.h @@ -0,0 +1,119 @@ +/** + * @file lv_indev_private.h + * + */ + +#ifndef LV_INDEV_PRIVATE_H +#define LV_INDEV_PRIVATE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_indev.h" +#include "../misc/lv_anim.h" +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_indev_t { + /**< Input device type*/ + lv_indev_type_t type; + + /**< Function pointer to read input device data.*/ + lv_indev_read_cb_t read_cb; + + lv_indev_state_t state; /**< Current state of the input device.*/ + lv_indev_mode_t mode; + + /*Flags*/ + uint8_t long_pr_sent : 1; + uint8_t reset_query : 1; + uint8_t disabled : 1; + uint8_t wait_until_release : 1; + + uint32_t pr_timestamp; /**< Pressed time stamp*/ + uint32_t longpr_rep_timestamp; /**< Long press repeat time stamp*/ + + void * driver_data; + void * user_data; + + /**< Pointer to the assigned display*/ + lv_display_t * disp; + + /**< Timer to periodically read the input device*/ + lv_timer_t * read_timer; + + /**< Number of pixels to slide before actually drag the object*/ + uint8_t scroll_limit; + + /**< Drag throw slow-down in [%]. Greater value means faster slow-down*/ + uint8_t scroll_throw; + + /**< At least this difference should be between two points to evaluate as gesture*/ + uint8_t gesture_min_velocity; + + /**< At least this difference should be to send a gesture*/ + uint8_t gesture_limit; + + /**< Long press time in milliseconds*/ + uint16_t long_press_time; + + /**< Repeated trigger period in long press [ms]*/ + uint16_t long_press_repeat_time; + + struct { + /*Pointer and button data*/ + lv_point_t act_point; /**< Current point of input device.*/ + lv_point_t last_point; /**< Last point of input device.*/ + lv_point_t last_raw_point; /**< Last point read from read_cb. */ + lv_point_t vect; /**< Difference between `act_point` and `last_point`.*/ + lv_point_t scroll_sum; /*Count the dragged pixels to check LV_INDEV_DEF_SCROLL_LIMIT*/ + lv_point_t scroll_throw_vect; + lv_point_t scroll_throw_vect_ori; + lv_obj_t * act_obj; /*The object being pressed*/ + lv_obj_t * last_obj; /*The last object which was pressed*/ + lv_obj_t * scroll_obj; /*The object being scrolled*/ + lv_obj_t * last_pressed; /*The lastly pressed object*/ + lv_area_t scroll_area; + lv_point_t gesture_sum; /*Count the gesture pixels to check LV_INDEV_DEF_GESTURE_LIMIT*/ + + /*Flags*/ + lv_dir_t scroll_dir : 4; + lv_dir_t gesture_dir : 4; + uint8_t gesture_sent : 1; + } pointer; + struct { + /*Keypad data*/ + lv_indev_state_t last_state; + uint32_t last_key; + } keypad; + + lv_obj_t * cursor; /**< Cursor for LV_INPUT_TYPE_POINTER*/ + lv_group_t * group; /**< Keypad destination group*/ + const lv_point_t * btn_points; /**< Array points assigned to the button ()screen will be pressed + here by the buttons*/ + + lv_event_list_t event_list; + lv_anim_t * scroll_throw_anim; +}; +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_INDEV_PRIVATE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_indev_scroll.c b/lib/libesp32_lvgl/lvgl/src/indev/lv_indev_scroll.c similarity index 56% rename from lib/libesp32_lvgl/lvgl/src/core/lv_indev_scroll.c rename to lib/libesp32_lvgl/lvgl/src/indev/lv_indev_scroll.c index 8a36ab30a..7352d4363 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_indev_scroll.c +++ b/lib/libesp32_lvgl/lvgl/src/indev/lv_indev_scroll.c @@ -7,6 +7,7 @@ * INCLUDES *********************/ #include "lv_indev.h" +#include "lv_indev_private.h" #include "lv_indev_scroll.h" /********************* @@ -21,15 +22,15 @@ /********************** * STATIC PROTOTYPES **********************/ -static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc); -static void init_scroll_limits(_lv_indev_proc_t * proc); -static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs); -static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs); -static void scroll_limit_diff(_lv_indev_proc_t * proc, lv_coord_t * diff_x, lv_coord_t * diff_y); -static lv_coord_t scroll_throw_predict_y(_lv_indev_proc_t * proc); -static lv_coord_t scroll_throw_predict_x(_lv_indev_proc_t * proc); -static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_t scroll_start, lv_coord_t scroll_end, - lv_dir_t dir); +static lv_obj_t * find_scroll_obj(lv_indev_t * indev); +static void init_scroll_limits(lv_indev_t * indev); +static int32_t find_snap_point_x(const lv_obj_t * obj, int32_t min, int32_t max, int32_t ofs); +static int32_t find_snap_point_y(const lv_obj_t * obj, int32_t min, int32_t max, int32_t ofs); +static void scroll_limit_diff(lv_indev_t * indev, int32_t * diff_x, int32_t * diff_y); +static int32_t scroll_throw_predict_y(lv_indev_t * indev); +static int32_t scroll_throw_predict_x(lv_indev_t * indev); +static int32_t elastic_diff(lv_obj_t * scroll_obj, int32_t diff, int32_t scroll_start, int32_t scroll_end, + lv_dir_t dir); /********************** * STATIC VARIABLES @@ -43,54 +44,57 @@ static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_ * GLOBAL FUNCTIONS **********************/ -void _lv_indev_scroll_handler(_lv_indev_proc_t * proc) +void _lv_indev_scroll_handler(lv_indev_t * indev) { - if(proc->types.pointer.vect.x == 0 && proc->types.pointer.vect.y == 0) { + if(indev->pointer.vect.x == 0 && indev->pointer.vect.y == 0) { return; } - lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj; + lv_obj_t * scroll_obj = indev->pointer.scroll_obj; /*If there is no scroll object yet try to find one*/ if(scroll_obj == NULL) { - scroll_obj = find_scroll_obj(proc); + scroll_obj = find_scroll_obj(indev); if(scroll_obj == NULL) return; - init_scroll_limits(proc); + init_scroll_limits(indev); - lv_event_send(scroll_obj, LV_EVENT_SCROLL_BEGIN, NULL); - if(proc->reset_query) return; + lv_obj_send_event(scroll_obj, LV_EVENT_SCROLL_BEGIN, NULL); + if(indev->reset_query) return; } /*Set new position or scroll if the vector is not zero*/ int16_t angle = 0; - int16_t zoom = 256; + int16_t scale_x = 256; + int16_t scale_y = 256; lv_obj_t * parent = scroll_obj; while(parent) { - angle += lv_obj_get_style_transform_angle(parent, 0); - zoom *= (lv_obj_get_style_transform_zoom(parent, 0) / 256); + angle += lv_obj_get_style_transform_rotation(parent, 0); + int32_t zoom_act_x = lv_obj_get_style_transform_scale_x_safe(parent, 0); + int32_t zoom_act_y = lv_obj_get_style_transform_scale_y_safe(parent, 0); + scale_x = (scale_x * zoom_act_x) >> 8; + scale_y = (scale_y * zoom_act_y) >> 8; parent = lv_obj_get_parent(parent); } - if(angle != 0 || zoom != LV_IMG_ZOOM_NONE) { + if(angle != 0 || scale_x != LV_SCALE_NONE || scale_y != LV_SCALE_NONE) { angle = -angle; - zoom = (256 * 256) / zoom; + scale_x = (256 * 256) / scale_x; + scale_y = (256 * 256) / scale_y; lv_point_t pivot = { 0, 0 }; - lv_point_transform(&proc->types.pointer.vect, angle, zoom, &pivot); + lv_point_transform(&indev->pointer.vect, angle, scale_x, scale_y, &pivot, false); } - - - lv_coord_t diff_x = 0; - lv_coord_t diff_y = 0; - if(proc->types.pointer.scroll_dir == LV_DIR_HOR) { - lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj); - lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj); - diff_x = elastic_diff(scroll_obj, proc->types.pointer.vect.x, sl, sr, LV_DIR_HOR); + int32_t diff_x = 0; + int32_t diff_y = 0; + if(indev->pointer.scroll_dir == LV_DIR_HOR) { + int32_t sr = lv_obj_get_scroll_right(scroll_obj); + int32_t sl = lv_obj_get_scroll_left(scroll_obj); + diff_x = elastic_diff(scroll_obj, indev->pointer.vect.x, sl, sr, LV_DIR_HOR); } else { - lv_coord_t st = lv_obj_get_scroll_top(scroll_obj); - lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj); - diff_y = elastic_diff(scroll_obj, proc->types.pointer.vect.y, st, sb, LV_DIR_VER); + int32_t st = lv_obj_get_scroll_top(scroll_obj); + int32_t sb = lv_obj_get_scroll_bottom(scroll_obj); + diff_y = elastic_diff(scroll_obj, indev->pointer.vect.y, st, sb, LV_DIR_VER); } lv_dir_t scroll_dir = lv_obj_get_scroll_dir(scroll_obj); @@ -100,143 +104,143 @@ void _lv_indev_scroll_handler(_lv_indev_proc_t * proc) if((scroll_dir & LV_DIR_BOTTOM) == 0 && diff_y < 0) diff_y = 0; /*Respect the scroll limit area*/ - scroll_limit_diff(proc, &diff_x, &diff_y); + scroll_limit_diff(indev, &diff_x, &diff_y); _lv_obj_scroll_by_raw(scroll_obj, diff_x, diff_y); - if(proc->reset_query) return; - proc->types.pointer.scroll_sum.x += diff_x; - proc->types.pointer.scroll_sum.y += diff_y; + if(indev->reset_query) return; + indev->pointer.scroll_sum.x += diff_x; + indev->pointer.scroll_sum.y += diff_y; } - -void _lv_indev_scroll_throw_handler(_lv_indev_proc_t * proc) +void _lv_indev_scroll_throw_handler(lv_indev_t * indev) { - lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj; + lv_obj_t * scroll_obj = indev->pointer.scroll_obj; if(scroll_obj == NULL) return; - if(proc->types.pointer.scroll_dir == LV_DIR_NONE) return; + if(indev->pointer.scroll_dir == LV_DIR_NONE) return; - lv_indev_t * indev_act = lv_indev_get_act(); - lv_coord_t scroll_throw = indev_act->driver->scroll_throw; + int32_t scroll_throw = indev->scroll_throw; if(lv_obj_has_flag(scroll_obj, LV_OBJ_FLAG_SCROLL_MOMENTUM) == false) { - proc->types.pointer.scroll_throw_vect.y = 0; - proc->types.pointer.scroll_throw_vect.x = 0; + indev->pointer.scroll_throw_vect.y = 0; + indev->pointer.scroll_throw_vect.x = 0; } lv_scroll_snap_t align_x = lv_obj_get_scroll_snap_x(scroll_obj); lv_scroll_snap_t align_y = lv_obj_get_scroll_snap_y(scroll_obj); - if(proc->types.pointer.scroll_dir == LV_DIR_VER) { - proc->types.pointer.scroll_throw_vect.x = 0; + if(indev->pointer.scroll_dir == LV_DIR_VER) { + indev->pointer.scroll_throw_vect.x = 0; /*If no snapping "throw"*/ if(align_y == LV_SCROLL_SNAP_NONE) { - proc->types.pointer.scroll_throw_vect.y = - proc->types.pointer.scroll_throw_vect.y * (100 - scroll_throw) / 100; + indev->pointer.scroll_throw_vect.y = + indev->pointer.scroll_throw_vect.y * (100 - scroll_throw) / 100; - lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj); - lv_coord_t st = lv_obj_get_scroll_top(scroll_obj); + int32_t sb = lv_obj_get_scroll_bottom(scroll_obj); + int32_t st = lv_obj_get_scroll_top(scroll_obj); - proc->types.pointer.scroll_throw_vect.y = elastic_diff(scroll_obj, proc->types.pointer.scroll_throw_vect.y, st, sb, - LV_DIR_VER); + indev->pointer.scroll_throw_vect.y = elastic_diff(scroll_obj, indev->pointer.scroll_throw_vect.y, st, sb, + LV_DIR_VER); - lv_obj_scroll_by(scroll_obj, 0, proc->types.pointer.scroll_throw_vect.y, LV_ANIM_OFF); + _lv_obj_scroll_by_raw(scroll_obj, 0, indev->pointer.scroll_throw_vect.y); + if(indev->reset_query) return; } /*With snapping find the nearest snap point and scroll there*/ else { - lv_coord_t diff_y = scroll_throw_predict_y(proc); - proc->types.pointer.scroll_throw_vect.y = 0; - scroll_limit_diff(proc, NULL, &diff_y); - lv_coord_t y = find_snap_point_y(scroll_obj, LV_COORD_MIN, LV_COORD_MAX, diff_y); + int32_t diff_y = scroll_throw_predict_y(indev); + indev->pointer.scroll_throw_vect.y = 0; + scroll_limit_diff(indev, NULL, &diff_y); + int32_t y = find_snap_point_y(scroll_obj, LV_COORD_MIN, LV_COORD_MAX, diff_y); lv_obj_scroll_by(scroll_obj, 0, diff_y + y, LV_ANIM_ON); + if(indev->reset_query) return; } } - else if(proc->types.pointer.scroll_dir == LV_DIR_HOR) { - proc->types.pointer.scroll_throw_vect.y = 0; + else if(indev->pointer.scroll_dir == LV_DIR_HOR) { + indev->pointer.scroll_throw_vect.y = 0; /*If no snapping "throw"*/ if(align_x == LV_SCROLL_SNAP_NONE) { - proc->types.pointer.scroll_throw_vect.x = - proc->types.pointer.scroll_throw_vect.x * (100 - scroll_throw) / 100; + indev->pointer.scroll_throw_vect.x = + indev->pointer.scroll_throw_vect.x * (100 - scroll_throw) / 100; - lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj); - lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj); + int32_t sl = lv_obj_get_scroll_left(scroll_obj); + int32_t sr = lv_obj_get_scroll_right(scroll_obj); - proc->types.pointer.scroll_throw_vect.x = elastic_diff(scroll_obj, proc->types.pointer.scroll_throw_vect.x, sl, sr, - LV_DIR_HOR); + indev->pointer.scroll_throw_vect.x = elastic_diff(scroll_obj, indev->pointer.scroll_throw_vect.x, sl, sr, + LV_DIR_HOR); - lv_obj_scroll_by(scroll_obj, proc->types.pointer.scroll_throw_vect.x, 0, LV_ANIM_OFF); + _lv_obj_scroll_by_raw(scroll_obj, indev->pointer.scroll_throw_vect.x, 0); + if(indev->reset_query) return; } /*With snapping find the nearest snap point and scroll there*/ else { - lv_coord_t diff_x = scroll_throw_predict_x(proc); - proc->types.pointer.scroll_throw_vect.x = 0; - scroll_limit_diff(proc, &diff_x, NULL); - lv_coord_t x = find_snap_point_x(scroll_obj, LV_COORD_MIN, LV_COORD_MAX, diff_x); + int32_t diff_x = scroll_throw_predict_x(indev); + indev->pointer.scroll_throw_vect.x = 0; + scroll_limit_diff(indev, &diff_x, NULL); + int32_t x = find_snap_point_x(scroll_obj, LV_COORD_MIN, LV_COORD_MAX, diff_x); lv_obj_scroll_by(scroll_obj, x + diff_x, 0, LV_ANIM_ON); + if(indev->reset_query) return; } } /*Check if the scroll has finished*/ - if(proc->types.pointer.scroll_throw_vect.x == 0 && proc->types.pointer.scroll_throw_vect.y == 0) { + if(indev->pointer.scroll_throw_vect.x == 0 && indev->pointer.scroll_throw_vect.y == 0) { /*Revert if scrolled in*/ /*If vertically scrollable and not controlled by snap*/ if(align_y == LV_SCROLL_SNAP_NONE) { - lv_coord_t st = lv_obj_get_scroll_top(scroll_obj); - lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj); + int32_t st = lv_obj_get_scroll_top(scroll_obj); + int32_t sb = lv_obj_get_scroll_bottom(scroll_obj); if(st > 0 || sb > 0) { if(st < 0) { lv_obj_scroll_by(scroll_obj, 0, st, LV_ANIM_ON); + if(indev->reset_query) return; } else if(sb < 0) { lv_obj_scroll_by(scroll_obj, 0, -sb, LV_ANIM_ON); + if(indev->reset_query) return; } } } /*If horizontally scrollable and not controlled by snap*/ if(align_x == LV_SCROLL_SNAP_NONE) { - lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj); - lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj); + int32_t sl = lv_obj_get_scroll_left(scroll_obj); + int32_t sr = lv_obj_get_scroll_right(scroll_obj); if(sl > 0 || sr > 0) { if(sl < 0) { lv_obj_scroll_by(scroll_obj, sl, 0, LV_ANIM_ON); + if(indev->reset_query) return; } else if(sr < 0) { lv_obj_scroll_by(scroll_obj, -sr, 0, LV_ANIM_ON); + if(indev->reset_query) return; } } } - lv_event_send(scroll_obj, LV_EVENT_SCROLL_END, indev_act); - if(proc->reset_query) return; + lv_obj_send_event(scroll_obj, LV_EVENT_SCROLL_END, indev); + if(indev->reset_query) return; - proc->types.pointer.scroll_dir = LV_DIR_NONE; - proc->types.pointer.scroll_obj = NULL; + indev->pointer.scroll_dir = LV_DIR_NONE; + indev->pointer.scroll_obj = NULL; } } -/** - * Predict where would a scroll throw end - * @param indev pointer to an input device - * @param dir `LV_DIR_VER` or `LV_DIR_HOR` - * @return the difference compared to the current position when the throw would be finished - */ -lv_coord_t lv_indev_scroll_throw_predict(lv_indev_t * indev, lv_dir_t dir) +int32_t lv_indev_scroll_throw_predict(lv_indev_t * indev, lv_dir_t dir) { if(indev == NULL) return 0; - lv_coord_t v; + int32_t v; switch(dir) { case LV_DIR_VER: - v = indev->proc.types.pointer.scroll_throw_vect_ori.y; + v = indev->pointer.scroll_throw_vect_ori.y; break; case LV_DIR_HOR: - v = indev->proc.types.pointer.scroll_throw_vect_ori.x; + v = indev->pointer.scroll_throw_vect_ori.x; break; default: return 0; } - lv_coord_t scroll_throw = indev->driver->scroll_throw; - lv_coord_t sum = 0; + int32_t scroll_throw = indev->scroll_throw; + int32_t sum = 0; while(v) { sum += v; v = v * (100 - scroll_throw) / 100; @@ -255,12 +259,11 @@ void lv_indev_scroll_get_snap_dist(lv_obj_t * obj, lv_point_t * p) * STATIC FUNCTIONS **********************/ -static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc) +static lv_obj_t * find_scroll_obj(lv_indev_t * indev) { lv_obj_t * obj_candidate = NULL; lv_dir_t dir_candidate = LV_DIR_NONE; - lv_indev_t * indev_act = lv_indev_get_act(); - lv_coord_t scroll_limit = indev_act->driver->scroll_limit; + int32_t scroll_limit = indev->scroll_limit; /*Go until find a scrollable object in the current direction *More precisely: @@ -269,33 +272,36 @@ static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc) * 3. If an object can be scrolled into the current direction then use it ("real match"") * 4. If can be scrolled on the current axis (hor/ver) save it as candidate (at least show an elastic scroll effect) * 5. Use the last candidate. Always the "deepest" parent or the object from point 3*/ - lv_obj_t * obj_act = proc->types.pointer.act_obj; + lv_obj_t * obj_act = indev->pointer.act_obj; /*Decide if it's a horizontal or vertical scroll*/ bool hor_en = false; bool ver_en = false; - - proc->types.pointer.scroll_sum.x += proc->types.pointer.vect.x; - proc->types.pointer.scroll_sum.y += proc->types.pointer.vect.y; + indev->pointer.scroll_sum.x += indev->pointer.vect.x; + indev->pointer.scroll_sum.y += indev->pointer.vect.y; while(obj_act) { /*Get the transformed scroll_sum with this object*/ int16_t angle = 0; - int32_t zoom = 256; + int32_t scale_x = 256; + int32_t scale_y = 256; lv_point_t pivot = { 0, 0 }; lv_obj_t * parent = obj_act; while(parent) { - angle += lv_obj_get_style_transform_angle(parent, 0); - int32_t zoom_act = lv_obj_get_style_transform_zoom(parent, 0); - zoom = (zoom * zoom_act) >> 8; + angle += lv_obj_get_style_transform_rotation(parent, 0); + int32_t zoom_act_x = lv_obj_get_style_transform_scale_x_safe(parent, 0); + int32_t zoom_act_y = lv_obj_get_style_transform_scale_y_safe(parent, 0); + scale_x = (scale_x * zoom_act_x) >> 8; + scale_y = (scale_y * zoom_act_y) >> 8; parent = lv_obj_get_parent(parent); } - lv_point_t obj_scroll_sum = proc->types.pointer.scroll_sum; - if(angle != 0 || zoom != LV_IMG_ZOOM_NONE) { + lv_point_t obj_scroll_sum = indev->pointer.scroll_sum; + if(angle != 0 || scale_x != LV_SCALE_NONE || scale_y != LV_SCALE_NONE) { angle = -angle; - zoom = (256 * 256) / zoom; - lv_point_transform(&obj_scroll_sum, angle, zoom, &pivot); + scale_x = (256 * 256) / scale_x; + scale_y = (256 * 256) / scale_y; + lv_point_transform(&obj_scroll_sum, angle, scale_x, scale_y, &pivot, false); } if(LV_ABS(obj_scroll_sum.x) > LV_ABS(obj_scroll_sum.y)) { @@ -328,10 +334,10 @@ static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc) if((scroll_dir & LV_DIR_BOTTOM) == 0) down_en = false; /*The object is scrollable to a direction if its content overflow in that direction.*/ - lv_coord_t st = lv_obj_get_scroll_top(obj_act); - lv_coord_t sb = lv_obj_get_scroll_bottom(obj_act); - lv_coord_t sl = lv_obj_get_scroll_left(obj_act); - lv_coord_t sr = lv_obj_get_scroll_right(obj_act); + int32_t st = lv_obj_get_scroll_top(obj_act); + int32_t sb = lv_obj_get_scroll_bottom(obj_act); + int32_t sl = lv_obj_get_scroll_left(obj_act); + int32_t sr = lv_obj_get_scroll_right(obj_act); /*If this object is scrollable into the current scroll direction then save it as a candidate. *It's important only to be scrollable on the current axis (hor/ver) because if the scroll @@ -361,7 +367,7 @@ static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc) (right_en && obj_scroll_sum.x <= - scroll_limit) || (up_en && obj_scroll_sum.y >= scroll_limit) || (down_en && obj_scroll_sum.y <= - scroll_limit)) { - proc->types.pointer.scroll_dir = hor_en ? LV_DIR_HOR : LV_DIR_VER; + indev->pointer.scroll_dir = hor_en ? LV_DIR_HOR : LV_DIR_VER; break; } @@ -375,72 +381,72 @@ static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc) /*Use the last candidate*/ if(obj_candidate) { - proc->types.pointer.scroll_dir = dir_candidate; - proc->types.pointer.scroll_obj = obj_candidate; - proc->types.pointer.scroll_sum.x = 0; - proc->types.pointer.scroll_sum.y = 0; + indev->pointer.scroll_dir = dir_candidate; + indev->pointer.scroll_obj = obj_candidate; + indev->pointer.scroll_sum.x = 0; + indev->pointer.scroll_sum.y = 0; } return obj_candidate; } -static void init_scroll_limits(_lv_indev_proc_t * proc) +static void init_scroll_limits(lv_indev_t * indev) { - lv_obj_t * obj = proc->types.pointer.scroll_obj; + lv_obj_t * obj = indev->pointer.scroll_obj; /*If there no STOP allow scrolling anywhere*/ if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLL_ONE) == false) { - lv_area_set(&proc->types.pointer.scroll_area, LV_COORD_MIN, LV_COORD_MIN, LV_COORD_MAX, LV_COORD_MAX); + lv_area_set(&indev->pointer.scroll_area, LV_COORD_MIN, LV_COORD_MIN, LV_COORD_MAX, LV_COORD_MAX); } /*With STOP limit the scrolling to the perv and next snap point*/ else { switch(lv_obj_get_scroll_snap_y(obj)) { case LV_SCROLL_SNAP_START: - proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y1 + 1, LV_COORD_MAX, 0); - proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y1 - 1, 0); + indev->pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y1 + 1, LV_COORD_MAX, 0); + indev->pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y1 - 1, 0); break; case LV_SCROLL_SNAP_END: - proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y2, LV_COORD_MAX, 0); - proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y2, 0); + indev->pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y2, LV_COORD_MAX, 0); + indev->pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y2, 0); break; case LV_SCROLL_SNAP_CENTER: { - lv_coord_t y_mid = obj->coords.y1 + lv_area_get_height(&obj->coords) / 2; - proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, y_mid + 1, LV_COORD_MAX, 0); - proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, y_mid - 1, 0); + int32_t y_mid = obj->coords.y1 + lv_area_get_height(&obj->coords) / 2; + indev->pointer.scroll_area.y1 = find_snap_point_y(obj, y_mid + 1, LV_COORD_MAX, 0); + indev->pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, y_mid - 1, 0); break; } default: - proc->types.pointer.scroll_area.y1 = LV_COORD_MIN; - proc->types.pointer.scroll_area.y2 = LV_COORD_MAX; + indev->pointer.scroll_area.y1 = LV_COORD_MIN; + indev->pointer.scroll_area.y2 = LV_COORD_MAX; break; } switch(lv_obj_get_scroll_snap_x(obj)) { case LV_SCROLL_SNAP_START: - proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, obj->coords.x1, LV_COORD_MAX, 0); - proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, obj->coords.x1, 0); + indev->pointer.scroll_area.x1 = find_snap_point_x(obj, obj->coords.x1, LV_COORD_MAX, 0); + indev->pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, obj->coords.x1, 0); break; case LV_SCROLL_SNAP_END: - proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, obj->coords.x2, LV_COORD_MAX, 0); - proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, obj->coords.x2, 0); + indev->pointer.scroll_area.x1 = find_snap_point_x(obj, obj->coords.x2, LV_COORD_MAX, 0); + indev->pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, obj->coords.x2, 0); break; case LV_SCROLL_SNAP_CENTER: { - lv_coord_t x_mid = obj->coords.x1 + lv_area_get_width(&obj->coords) / 2; - proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, x_mid + 1, LV_COORD_MAX, 0); - proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, x_mid - 1, 0); + int32_t x_mid = obj->coords.x1 + lv_area_get_width(&obj->coords) / 2; + indev->pointer.scroll_area.x1 = find_snap_point_x(obj, x_mid + 1, LV_COORD_MAX, 0); + indev->pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, x_mid - 1, 0); break; } default: - proc->types.pointer.scroll_area.x1 = LV_COORD_MIN; - proc->types.pointer.scroll_area.x2 = LV_COORD_MAX; + indev->pointer.scroll_area.x1 = LV_COORD_MIN; + indev->pointer.scroll_area.x2 = LV_COORD_MAX; break; } } /*Allow scrolling on the edges. It will be reverted to the edge due to snapping anyway*/ - if(proc->types.pointer.scroll_area.x1 == 0) proc->types.pointer.scroll_area.x1 = LV_COORD_MIN; - if(proc->types.pointer.scroll_area.x2 == 0) proc->types.pointer.scroll_area.x2 = LV_COORD_MAX; - if(proc->types.pointer.scroll_area.y1 == 0) proc->types.pointer.scroll_area.y1 = LV_COORD_MIN; - if(proc->types.pointer.scroll_area.y2 == 0) proc->types.pointer.scroll_area.y2 = LV_COORD_MAX; + if(indev->pointer.scroll_area.x1 == 0) indev->pointer.scroll_area.x1 = LV_COORD_MIN; + if(indev->pointer.scroll_area.x2 == 0) indev->pointer.scroll_area.x2 = LV_COORD_MAX; + if(indev->pointer.scroll_area.y1 == 0) indev->pointer.scroll_area.y1 = LV_COORD_MIN; + if(indev->pointer.scroll_area.y2 == 0) indev->pointer.scroll_area.y2 = LV_COORD_MAX; } /** @@ -452,24 +458,24 @@ static void init_scroll_limits(_lv_indev_proc_t * proc) * what if children are already moved by this value * @return the distance of the snap point. */ -static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs) +static int32_t find_snap_point_x(const lv_obj_t * obj, int32_t min, int32_t max, int32_t ofs) { lv_scroll_snap_t align = lv_obj_get_scroll_snap_x(obj); if(align == LV_SCROLL_SNAP_NONE) return 0; - lv_coord_t dist = LV_COORD_MAX; + int32_t dist = LV_COORD_MAX; - lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + int32_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + int32_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); uint32_t i; - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); for(i = 0; i < child_cnt; i++) { lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) { - lv_coord_t x_child = 0; - lv_coord_t x_parent = 0; + int32_t x_child = 0; + int32_t x_parent = 0; switch(align) { case LV_SCROLL_SNAP_START: x_child = child->coords.x1; @@ -489,7 +495,7 @@ static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coo x_child += ofs; if(x_child >= min && x_child <= max) { - lv_coord_t x = x_child - x_parent; + int32_t x = x_child - x_parent; if(LV_ABS(x) < LV_ABS(dist)) dist = x; } } @@ -507,24 +513,24 @@ static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coo * what if children are already moved by this value * @return the distance of the snap point. */ -static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs) +static int32_t find_snap_point_y(const lv_obj_t * obj, int32_t min, int32_t max, int32_t ofs) { lv_scroll_snap_t align = lv_obj_get_scroll_snap_y(obj); if(align == LV_SCROLL_SNAP_NONE) return 0; - lv_coord_t dist = LV_COORD_MAX; + int32_t dist = LV_COORD_MAX; - lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + int32_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + int32_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); uint32_t i; - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); for(i = 0; i < child_cnt; i++) { lv_obj_t * child = obj->spec_attr->children[i]; if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) { - lv_coord_t y_child = 0; - lv_coord_t y_parent = 0; + int32_t y_child = 0; + int32_t y_parent = 0; switch(align) { case LV_SCROLL_SNAP_START: y_child = child->coords.y1; @@ -544,7 +550,7 @@ static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coo y_child += ofs; if(y_child >= min && y_child <= max) { - lv_coord_t y = y_child - y_parent; + int32_t y = y_child - y_parent; if(LV_ABS(y) < LV_ABS(dist)) dist = y; } } @@ -553,38 +559,35 @@ static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coo return dist == LV_COORD_MAX ? 0 : -dist; } -static void scroll_limit_diff(_lv_indev_proc_t * proc, lv_coord_t * diff_x, lv_coord_t * diff_y) +static void scroll_limit_diff(lv_indev_t * indev, int32_t * diff_x, int32_t * diff_y) { if(diff_y) { - if(proc->types.pointer.scroll_sum.y + *diff_y < proc->types.pointer.scroll_area.y1) { - *diff_y = proc->types.pointer.scroll_area.y1 - proc->types.pointer.scroll_sum.y; + if(indev->pointer.scroll_sum.y + *diff_y < indev->pointer.scroll_area.y1) { + *diff_y = indev->pointer.scroll_area.y1 - indev->pointer.scroll_sum.y; } - if(proc->types.pointer.scroll_sum.y + *diff_y > proc->types.pointer.scroll_area.y2) { - *diff_y = proc->types.pointer.scroll_area.y2 - proc->types.pointer.scroll_sum.y; + if(indev->pointer.scroll_sum.y + *diff_y > indev->pointer.scroll_area.y2) { + *diff_y = indev->pointer.scroll_area.y2 - indev->pointer.scroll_sum.y; } } if(diff_x) { - if(proc->types.pointer.scroll_sum.x + *diff_x < proc->types.pointer.scroll_area.x1) { - *diff_x = proc->types.pointer.scroll_area.x1 - proc->types.pointer.scroll_sum.x; + if(indev->pointer.scroll_sum.x + *diff_x < indev->pointer.scroll_area.x1) { + *diff_x = indev->pointer.scroll_area.x1 - indev->pointer.scroll_sum.x; } - if(proc->types.pointer.scroll_sum.x + *diff_x > proc->types.pointer.scroll_area.x2) { - *diff_x = proc->types.pointer.scroll_area.x2 - proc->types.pointer.scroll_sum.x; + if(indev->pointer.scroll_sum.x + *diff_x > indev->pointer.scroll_area.x2) { + *diff_x = indev->pointer.scroll_area.x2 - indev->pointer.scroll_sum.x; } } } - - -static lv_coord_t scroll_throw_predict_y(_lv_indev_proc_t * proc) +static int32_t scroll_throw_predict_y(lv_indev_t * indev) { - lv_coord_t y = proc->types.pointer.scroll_throw_vect.y; - lv_coord_t move = 0; + int32_t y = indev->pointer.scroll_throw_vect.y; + int32_t move = 0; - lv_indev_t * indev_act = lv_indev_get_act(); - lv_coord_t scroll_throw = indev_act->driver->scroll_throw; + int32_t scroll_throw = indev->scroll_throw; while(y) { move += y; @@ -593,14 +596,12 @@ static lv_coord_t scroll_throw_predict_y(_lv_indev_proc_t * proc) return move; } - -static lv_coord_t scroll_throw_predict_x(_lv_indev_proc_t * proc) +static int32_t scroll_throw_predict_x(lv_indev_t * indev) { - lv_coord_t x = proc->types.pointer.scroll_throw_vect.x; - lv_coord_t move = 0; + int32_t x = indev->pointer.scroll_throw_vect.x; + int32_t move = 0; - lv_indev_t * indev_act = lv_indev_get_act(); - lv_coord_t scroll_throw = indev_act->driver->scroll_throw; + int32_t scroll_throw = indev->scroll_throw; while(x) { move += x; @@ -609,8 +610,8 @@ static lv_coord_t scroll_throw_predict_x(_lv_indev_proc_t * proc) return move; } -static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_t scroll_start, lv_coord_t scroll_end, - lv_dir_t dir) +static int32_t elastic_diff(lv_obj_t * scroll_obj, int32_t diff, int32_t scroll_start, int32_t scroll_end, + lv_dir_t dir) { if(lv_obj_has_flag(scroll_obj, LV_OBJ_FLAG_SCROLL_ELASTIC)) { /*If there is snapping in the current direction don't use the elastic factor because @@ -618,13 +619,13 @@ static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_ lv_scroll_snap_t snap; snap = dir == LV_DIR_HOR ? lv_obj_get_scroll_snap_x(scroll_obj) : lv_obj_get_scroll_snap_y(scroll_obj); - lv_obj_t * act_obj = lv_indev_get_obj_act(); - lv_coord_t snap_point = 0; - lv_coord_t act_obj_point = 0; + lv_obj_t * act_obj = lv_indev_get_active_obj(); + int32_t snap_point = 0; + int32_t act_obj_point = 0; if(dir == LV_DIR_HOR) { - lv_coord_t pad_left = lv_obj_get_style_pad_left(scroll_obj, LV_PART_MAIN); - lv_coord_t pad_right = lv_obj_get_style_pad_right(scroll_obj, LV_PART_MAIN); + int32_t pad_left = lv_obj_get_style_pad_left(scroll_obj, LV_PART_MAIN); + int32_t pad_right = lv_obj_get_style_pad_right(scroll_obj, LV_PART_MAIN); switch(snap) { case LV_SCROLL_SNAP_CENTER: @@ -642,8 +643,8 @@ static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_ } } else { - lv_coord_t pad_top = lv_obj_get_style_pad_top(scroll_obj, LV_PART_MAIN); - lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(scroll_obj, LV_PART_MAIN); + int32_t pad_top = lv_obj_get_style_pad_top(scroll_obj, LV_PART_MAIN); + int32_t pad_bottom = lv_obj_get_style_pad_bottom(scroll_obj, LV_PART_MAIN); switch(snap) { case LV_SCROLL_SNAP_CENTER: @@ -686,5 +687,3 @@ static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_ return diff; } - - diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_indev_scroll.h b/lib/libesp32_lvgl/lvgl/src/indev/lv_indev_scroll.h similarity index 78% rename from lib/libesp32_lvgl/lvgl/src/core/lv_indev_scroll.h rename to lib/libesp32_lvgl/lvgl/src/indev/lv_indev_scroll.h index 76c64d176..64d1d018b 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_indev_scroll.h +++ b/lib/libesp32_lvgl/lvgl/src/indev/lv_indev_scroll.h @@ -13,7 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "lv_obj.h" +#include "../core/lv_obj.h" /********************* * DEFINES @@ -29,15 +29,15 @@ extern "C" { /** * Handle scrolling. Called by LVGL during input device processing - * @param proc pointer to an input device's proc field + * @param indev pointer to an input device */ -void _lv_indev_scroll_handler(_lv_indev_proc_t * proc); +void _lv_indev_scroll_handler(lv_indev_t * indev); /** * Handle throwing after scrolling. Called by LVGL during input device processing - * @param proc pointer to an input device's proc field + * @param indev pointer to an input device */ -void _lv_indev_scroll_throw_handler(_lv_indev_proc_t * proc); +void _lv_indev_scroll_throw_handler(lv_indev_t * indev); /** * Predict where would a scroll throw end @@ -45,7 +45,7 @@ void _lv_indev_scroll_throw_handler(_lv_indev_proc_t * proc); * @param dir ` LV_DIR_VER` or `LV_DIR_HOR` * @return the difference compared to the current position when the throw would be finished */ -lv_coord_t lv_indev_scroll_throw_predict(lv_indev_t * indev, lv_dir_t dir); +int32_t lv_indev_scroll_throw_predict(lv_indev_t * indev, lv_dir_t dir); /** * Get the distance of the nearest snap point diff --git a/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.c b/lib/libesp32_lvgl/lvgl/src/layouts/flex/lv_flex.c similarity index 61% rename from lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.c rename to lib/libesp32_lvgl/lvgl/src/layouts/flex/lv_flex.c index 8f0b4d290..168f9de90 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.c +++ b/lib/libesp32_lvgl/lvgl/src/layouts/flex/lv_flex.c @@ -6,13 +6,17 @@ /********************* * INCLUDES *********************/ -#include "../lv_layouts.h" +#include "lv_flex.h" +#include "../lv_layout.h" +#include "../../core/lv_obj.h" #if LV_USE_FLEX +#include "../../core/lv_global.h" /********************* * DEFINES *********************/ +#define layout_list_def LV_GLOBAL_DEFAULT()->layout_list /********************** * TYPEDEFS @@ -28,24 +32,23 @@ typedef struct { typedef struct { lv_obj_t * item; - lv_coord_t min_size; - lv_coord_t max_size; - lv_coord_t final_size; + int32_t min_size; + int32_t max_size; + int32_t final_size; uint32_t grow_value; uint32_t clamped : 1; } grow_dsc_t; typedef struct { - lv_coord_t track_cross_size; - lv_coord_t track_main_size; /*For all items*/ - lv_coord_t track_fix_main_size; /*For non grow items*/ + int32_t track_cross_size; + int32_t track_main_size; /*For all items*/ + int32_t track_fix_main_size; /*For non grow items*/ uint32_t item_cnt; grow_dsc_t * grow_dsc; uint32_t grow_item_cnt; uint32_t grow_dsc_calc : 1; } track_t; - /********************** * GLOBAL PROTOTYPES **********************/ @@ -54,24 +57,19 @@ typedef struct { * STATIC PROTOTYPES **********************/ static void flex_update(lv_obj_t * cont, void * user_data); -static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, lv_coord_t max_main_size, - lv_coord_t item_gap, track_t * t); -static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, int32_t item_last_id, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t max_main_size, lv_coord_t item_gap, track_t * t); -static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t content_size, lv_coord_t item_cnt, - lv_coord_t * start_pos, lv_coord_t * gap); +static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, int32_t max_main_size, + int32_t item_gap, track_t * t); +static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, int32_t item_last_id, int32_t abs_x, + int32_t abs_y, int32_t max_main_size, int32_t item_gap, track_t * t); +static void place_content(lv_flex_align_t place, int32_t max_size, int32_t content_size, int32_t item_cnt, + int32_t * start_pos, int32_t * gap); static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, int32_t * item_id); +static int32_t lv_obj_get_width_with_margin(const lv_obj_t * obj); +static int32_t lv_obj_get_height_with_margin(const lv_obj_t * obj); /********************** * GLOBAL VARIABLES **********************/ -uint16_t LV_LAYOUT_FLEX; -lv_style_prop_t LV_STYLE_FLEX_FLOW; -lv_style_prop_t LV_STYLE_FLEX_MAIN_PLACE; -lv_style_prop_t LV_STYLE_FLEX_CROSS_PLACE; -lv_style_prop_t LV_STYLE_FLEX_TRACK_PLACE; -lv_style_prop_t LV_STYLE_FLEX_GROW; - /********************** * STATIC VARIABLES @@ -80,6 +78,11 @@ lv_style_prop_t LV_STYLE_FLEX_GROW; /********************** * MACROS **********************/ +#if LV_USE_LOG && LV_LOG_TRACE_LAYOUT + #define LV_TRACE_LAYOUT(...) LV_LOG_TRACE(__VA_ARGS__) +#else + #define LV_TRACE_LAYOUT(...) +#endif /********************** * GLOBAL FUNCTIONS @@ -91,13 +94,9 @@ lv_style_prop_t LV_STYLE_FLEX_GROW; void lv_flex_init(void) { - LV_LAYOUT_FLEX = lv_layout_register(flex_update, NULL); + layout_list_def[LV_LAYOUT_FLEX].cb = flex_update; + layout_list_def[LV_LAYOUT_FLEX].user_data = NULL; - LV_STYLE_FLEX_FLOW = lv_style_register_prop(LV_STYLE_PROP_FLAG_NONE); - LV_STYLE_FLEX_MAIN_PLACE = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); - LV_STYLE_FLEX_CROSS_PLACE = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); - LV_STYLE_FLEX_TRACK_PLACE = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); - LV_STYLE_FLEX_GROW = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); } void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow) @@ -121,88 +120,6 @@ void lv_obj_set_flex_grow(lv_obj_t * obj, uint8_t grow) lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj)); } - -void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value) -{ - lv_style_value_t v = { - .num = (int32_t)value - }; - lv_style_set_prop(style, LV_STYLE_FLEX_FLOW, v); -} - -void lv_style_set_flex_main_place(lv_style_t * style, lv_flex_align_t value) -{ - lv_style_value_t v = { - .num = (int32_t)value - }; - lv_style_set_prop(style, LV_STYLE_FLEX_MAIN_PLACE, v); -} - -void lv_style_set_flex_cross_place(lv_style_t * style, lv_flex_align_t value) -{ - lv_style_value_t v = { - .num = (int32_t)value - }; - lv_style_set_prop(style, LV_STYLE_FLEX_CROSS_PLACE, v); -} - -void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value) -{ - lv_style_value_t v = { - .num = (int32_t)value - }; - lv_style_set_prop(style, LV_STYLE_FLEX_TRACK_PLACE, v); -} - -void lv_style_set_flex_grow(lv_style_t * style, uint8_t value) -{ - lv_style_value_t v = { - .num = (int32_t)value - }; - lv_style_set_prop(style, LV_STYLE_FLEX_GROW, v); -} - - -void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .num = (int32_t) value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_FLOW, v, selector); -} - -void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .num = (int32_t) value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_MAIN_PLACE, v, selector); -} - -void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .num = (int32_t) value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_CROSS_PLACE, v, selector); -} - -void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .num = (int32_t) value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_TRACK_PLACE, v, selector); -} - -void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .num = (int32_t) value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_GROW, v, selector); -} - /********************** * STATIC FUNCTIONS **********************/ @@ -221,25 +138,24 @@ static void flex_update(lv_obj_t * cont, void * user_data) f.cross_place = lv_obj_get_style_flex_cross_place(cont, LV_PART_MAIN); f.track_place = lv_obj_get_style_flex_track_place(cont, LV_PART_MAIN); - bool rtl = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false; - lv_coord_t track_gap = !f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont, - LV_PART_MAIN); - lv_coord_t item_gap = f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont, - LV_PART_MAIN); - lv_coord_t max_main_size = (f.row ? lv_obj_get_content_width(cont) : lv_obj_get_content_height(cont)); - lv_coord_t border_width = lv_obj_get_style_border_width(cont, LV_PART_MAIN); - lv_coord_t abs_y = cont->coords.y1 + lv_obj_get_style_pad_top(cont, - LV_PART_MAIN) + border_width - lv_obj_get_scroll_y(cont); - lv_coord_t abs_x = cont->coords.x1 + lv_obj_get_style_pad_left(cont, - LV_PART_MAIN) + border_width - lv_obj_get_scroll_x(cont); + bool rtl = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL; + int32_t track_gap = !f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont, + LV_PART_MAIN); + int32_t item_gap = f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont, + LV_PART_MAIN); + int32_t max_main_size = (f.row ? lv_obj_get_content_width(cont) : lv_obj_get_content_height(cont)); + int32_t abs_y = cont->coords.y1 + lv_obj_get_style_space_top(cont, + LV_PART_MAIN) - lv_obj_get_scroll_y(cont); + int32_t abs_x = cont->coords.x1 + lv_obj_get_style_space_left(cont, + LV_PART_MAIN) - lv_obj_get_scroll_x(cont); lv_flex_align_t track_cross_place = f.track_place; - lv_coord_t * cross_pos = (f.row ? &abs_y : &abs_x); + int32_t * cross_pos = (f.row ? &abs_y : &abs_x); - lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN); - lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN); + int32_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN); + int32_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN); - /*Content sized objects should squeezed the gap between the children, therefore any alignment will look like `START`*/ + /*Content sized objects should squeeze the gap between the children, therefore any alignment will look like `START`*/ if((f.row && h_set == LV_SIZE_CONTENT && cont->h_layout == 0) || (!f.row && w_set == LV_SIZE_CONTENT && cont->w_layout == 0)) { track_cross_place = LV_FLEX_ALIGN_START; @@ -250,8 +166,8 @@ static void flex_update(lv_obj_t * cont, void * user_data) else if(track_cross_place == LV_FLEX_ALIGN_END) track_cross_place = LV_FLEX_ALIGN_START; } - lv_coord_t total_track_cross_size = 0; - lv_coord_t gap = 0; + int32_t total_track_cross_size = 0; + int32_t gap = 0; uint32_t track_cnt = 0; int32_t track_first_item; int32_t next_track_first_item; @@ -271,7 +187,7 @@ static void flex_update(lv_obj_t * cont, void * user_data) if(track_cnt) total_track_cross_size -= track_gap; /*No gap after the last track*/ /*Place the tracks to get the start position*/ - lv_coord_t max_cross_size = (f.row ? lv_obj_get_content_height(cont) : lv_obj_get_content_width(cont)); + int32_t max_cross_size = (f.row ? lv_obj_get_content_height(cont) : lv_obj_get_content_width(cont)); place_content(track_cross_place, max_cross_size, total_track_cross_size, track_cnt, cross_pos, &gap); } @@ -292,7 +208,7 @@ static void flex_update(lv_obj_t * cont, void * user_data) } children_repos(cont, &f, track_first_item, next_track_first_item, abs_x, abs_y, max_main_size, item_gap, &t); track_first_item = next_track_first_item; - lv_mem_buf_release(t.grow_dsc); + lv_free(t.grow_dsc); t.grow_dsc = NULL; if(rtl && !f.row) { *cross_pos -= gap + track_gap; @@ -307,7 +223,7 @@ static void flex_update(lv_obj_t * cont, void * user_data) lv_obj_refr_size(cont); } - lv_event_send(cont, LV_EVENT_LAYOUT_CHANGED, NULL); + lv_obj_send_event(cont, LV_EVENT_LAYOUT_CHANGED, NULL); LV_TRACE_LAYOUT("finished"); } @@ -315,18 +231,19 @@ static void flex_update(lv_obj_t * cont, void * user_data) /** * Find the last item of a track */ -static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, lv_coord_t max_main_size, - lv_coord_t item_gap, track_t * t) +static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, int32_t max_main_size, + int32_t item_gap, track_t * t) { - lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN); - lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN); + int32_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN); + int32_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN); - /*Can't wrap if the size if auto (i.e. the size depends on the children)*/ + /*Can't wrap if the size is auto (i.e. the size depends on the children)*/ if(f->wrap && ((f->row && w_set == LV_SIZE_CONTENT) || (!f->row && h_set == LV_SIZE_CONTENT))) { f->wrap = false; } - lv_coord_t(*get_main_size)(const lv_obj_t *) = (f->row ? lv_obj_get_width : lv_obj_get_height); - lv_coord_t(*get_cross_size)(const lv_obj_t *) = (!f->row ? lv_obj_get_width : lv_obj_get_height); + int32_t(*get_main_size)(const lv_obj_t *) = (f->row ? lv_obj_get_width_with_margin : lv_obj_get_height_with_margin); + int32_t(*get_cross_size)(const lv_obj_t *) = (!f->row ? lv_obj_get_width_with_margin : + lv_obj_get_height_with_margin); t->track_main_size = 0; t->track_fix_main_size = 0; @@ -347,31 +264,26 @@ static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id t->grow_item_cnt++; t->track_fix_main_size += item_gap; if(t->grow_dsc_calc) { - grow_dsc_t * new_dsc = lv_mem_buf_get(sizeof(grow_dsc_t) * (t->grow_item_cnt)); + grow_dsc_t * new_dsc = lv_realloc(t->grow_dsc, sizeof(grow_dsc_t) * (t->grow_item_cnt)); LV_ASSERT_MALLOC(new_dsc); if(new_dsc == NULL) return item_id; - if(t->grow_dsc) { - lv_memcpy(new_dsc, t->grow_dsc, sizeof(grow_dsc_t) * (t->grow_item_cnt - 1)); - lv_mem_buf_release(t->grow_dsc); - } new_dsc[t->grow_item_cnt - 1].item = item; - new_dsc[t->grow_item_cnt - 1].min_size = f->row ? lv_obj_get_style_min_width(item, - LV_PART_MAIN) : lv_obj_get_style_min_height(item, LV_PART_MAIN); - new_dsc[t->grow_item_cnt - 1].max_size = f->row ? lv_obj_get_style_max_width(item, - LV_PART_MAIN) : lv_obj_get_style_max_height(item, LV_PART_MAIN); + new_dsc[t->grow_item_cnt - 1].min_size = f->row ? lv_obj_get_style_min_width(item, LV_PART_MAIN) + : lv_obj_get_style_min_height(item, LV_PART_MAIN); + new_dsc[t->grow_item_cnt - 1].max_size = f->row ? lv_obj_get_style_max_width(item, LV_PART_MAIN) + : lv_obj_get_style_max_height(item, LV_PART_MAIN); new_dsc[t->grow_item_cnt - 1].grow_value = grow_value; new_dsc[t->grow_item_cnt - 1].clamped = 0; t->grow_dsc = new_dsc; } } else { - lv_coord_t item_size = get_main_size(item); + int32_t item_size = get_main_size(item); if(f->wrap && t->track_fix_main_size + item_size > max_main_size) break; t->track_fix_main_size += item_size + item_gap; } - t->track_cross_size = LV_MAX(get_cross_size(item), t->track_cross_size); t->item_cnt++; } @@ -403,20 +315,26 @@ static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id /** * Position the children in the same track */ -static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, int32_t item_last_id, lv_coord_t abs_x, - lv_coord_t abs_y, lv_coord_t max_main_size, lv_coord_t item_gap, track_t * t) +static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, int32_t item_last_id, int32_t abs_x, + int32_t abs_y, int32_t max_main_size, int32_t item_gap, track_t * t) { - void (*area_set_main_size)(lv_area_t *, lv_coord_t) = (f->row ? lv_area_set_width : lv_area_set_height); - lv_coord_t (*area_get_main_size)(const lv_area_t *) = (f->row ? lv_area_get_width : lv_area_get_height); - lv_coord_t (*area_get_cross_size)(const lv_area_t *) = (!f->row ? lv_area_get_width : lv_area_get_height); + void (*area_set_main_size)(lv_area_t *, int32_t) = (f->row ? lv_area_set_width : lv_area_set_height); + int32_t (*area_get_main_size)(const lv_area_t *) = (f->row ? lv_area_get_width : lv_area_get_height); + int32_t (*area_get_cross_size)(const lv_area_t *) = (!f->row ? lv_area_get_width : lv_area_get_height); + + typedef int32_t (*margin_func_t)(const lv_obj_t *, uint32_t); + margin_func_t get_margin_main_start = (f->row ? lv_obj_get_style_margin_left : lv_obj_get_style_margin_top); + margin_func_t get_margin_main_end = (f->row ? lv_obj_get_style_margin_right : lv_obj_get_style_margin_bottom); + margin_func_t get_margin_cross_start = (!f->row ? lv_obj_get_style_margin_left : lv_obj_get_style_margin_top); + margin_func_t get_margin_cross_end = (!f->row ? lv_obj_get_style_margin_right : lv_obj_get_style_margin_bottom); /*Calculate the size of grow items first*/ uint32_t i; bool grow_reiterate = true; - while(grow_reiterate) { + while(grow_reiterate && t->grow_item_cnt) { grow_reiterate = false; - lv_coord_t grow_value_sum = 0; - lv_coord_t grow_max_size = t->track_main_size - t->track_fix_main_size; + int32_t grow_value_sum = 0; + int32_t grow_max_size = t->track_main_size - t->track_fix_main_size; for(i = 0; i < t->grow_item_cnt; i++) { if(t->grow_dsc[i].clamped == 0) { grow_value_sum += t->grow_dsc[i].grow_value; @@ -425,14 +343,14 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i grow_max_size -= t->grow_dsc[i].final_size; } } - lv_coord_t grow_unit; + int32_t grow_unit; for(i = 0; i < t->grow_item_cnt; i++) { if(t->grow_dsc[i].clamped == 0) { LV_ASSERT(grow_value_sum != 0); grow_unit = grow_max_size / grow_value_sum; - lv_coord_t size = grow_unit * t->grow_dsc[i].grow_value; - lv_coord_t size_clamp = LV_CLAMP(t->grow_dsc[i].min_size, size, t->grow_dsc[i].max_size); + int32_t size = grow_unit * t->grow_dsc[i].grow_value; + int32_t size_clamp = LV_CLAMP(t->grow_dsc[i].min_size, size, t->grow_dsc[i].max_size); if(size_clamp != size) { t->grow_dsc[i].clamped = 1; @@ -445,12 +363,11 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i } } + bool rtl = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL; - bool rtl = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false; + int32_t main_pos = 0; - lv_coord_t main_pos = 0; - - lv_coord_t place_gap = 0; + int32_t place_gap = 0; place_content(f->main_place, max_main_size, t->track_main_size, t->item_cnt, &main_pos, &place_gap); if(f->row && rtl) main_pos += lv_obj_get_content_width(cont); @@ -461,9 +378,9 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i item = get_next_item(cont, f->rev, &item_first_id); continue; } - lv_coord_t grow_size = lv_obj_get_style_flex_grow(item, LV_PART_MAIN); + int32_t grow_size = lv_obj_get_style_flex_grow(item, LV_PART_MAIN); if(grow_size) { - lv_coord_t s = 0; + int32_t s = 0; for(i = 0; i < t->grow_item_cnt; i++) { if(t->grow_dsc[i].item == item) { s = t->grow_dsc[i].final_size; @@ -486,8 +403,8 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i lv_area_t old_coords; lv_area_copy(&old_coords, &item->coords); area_set_main_size(&item->coords, s); - lv_event_send(item, LV_EVENT_SIZE_CHANGED, &old_coords); - lv_event_send(lv_obj_get_parent(item), LV_EVENT_CHILD_CHANGED, item); + lv_obj_send_event(item, LV_EVENT_SIZE_CHANGED, &old_coords); + lv_obj_send_event(lv_obj_get_parent(item), LV_EVENT_CHILD_CHANGED, item); lv_obj_invalidate(item); } } @@ -496,35 +413,37 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i item->h_layout = 0; } - lv_coord_t cross_pos = 0; + int32_t cross_pos = 0; switch(f->cross_place) { case LV_FLEX_ALIGN_CENTER: /*Round up the cross size to avoid rounding error when dividing by 2 *The issue comes up e,g, with column direction with center cross direction if an element's width changes*/ cross_pos = (((t->track_cross_size + 1) & (~1)) - area_get_cross_size(&item->coords)) / 2; + cross_pos += (get_margin_cross_start(item, LV_PART_MAIN) - get_margin_cross_end(item, LV_PART_MAIN)) / 2; break; case LV_FLEX_ALIGN_END: cross_pos = t->track_cross_size - area_get_cross_size(&item->coords); + cross_pos -= get_margin_cross_end(item, LV_PART_MAIN); break; default: + cross_pos += get_margin_cross_start(item, LV_PART_MAIN); break; } if(f->row && rtl) main_pos -= area_get_main_size(&item->coords); - /*Handle percentage value of translate*/ - lv_coord_t tr_x = lv_obj_get_style_translate_x(item, LV_PART_MAIN); - lv_coord_t tr_y = lv_obj_get_style_translate_y(item, LV_PART_MAIN); - lv_coord_t w = lv_obj_get_width(item); - lv_coord_t h = lv_obj_get_height(item); + int32_t tr_x = lv_obj_get_style_translate_x(item, LV_PART_MAIN); + int32_t tr_y = lv_obj_get_style_translate_y(item, LV_PART_MAIN); + int32_t w = lv_obj_get_width(item); + int32_t h = lv_obj_get_height(item); if(LV_COORD_IS_PCT(tr_x)) tr_x = (w * LV_COORD_GET_PCT(tr_x)) / 100; if(LV_COORD_IS_PCT(tr_y)) tr_y = (h * LV_COORD_GET_PCT(tr_y)) / 100; - lv_coord_t diff_x = abs_x - item->coords.x1 + tr_x; - lv_coord_t diff_y = abs_y - item->coords.y1 + tr_y; - diff_x += f->row ? main_pos : cross_pos; - diff_y += f->row ? cross_pos : main_pos; + int32_t diff_x = abs_x - item->coords.x1 + tr_x; + int32_t diff_y = abs_y - item->coords.y1 + tr_y; + diff_x += f->row ? main_pos + get_margin_main_start(item, LV_PART_MAIN) : cross_pos; + diff_y += f->row ? cross_pos : main_pos + get_margin_main_start(item, LV_PART_MAIN); if(diff_x || diff_y) { lv_obj_invalidate(item); @@ -536,7 +455,9 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i lv_obj_move_children_by(item, diff_x, diff_y, false); } - if(!(f->row && rtl)) main_pos += area_get_main_size(&item->coords) + item_gap + place_gap; + if(!(f->row && rtl)) main_pos += area_get_main_size(&item->coords) + item_gap + place_gap + + get_margin_main_start(item, LV_PART_MAIN) + + get_margin_main_end(item, LV_PART_MAIN); else main_pos -= item_gap + place_gap; item = get_next_item(cont, f->rev, &item_first_id); @@ -546,8 +467,8 @@ static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, i /** * Tell a start coordinate and gap for a placement type. */ -static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t content_size, lv_coord_t item_cnt, - lv_coord_t * start_pos, lv_coord_t * gap) +static void place_content(lv_flex_align_t place, int32_t max_size, int32_t content_size, int32_t item_cnt, + int32_t * start_pos, int32_t * gap) { if(item_cnt <= 1) { switch(place) { @@ -571,14 +492,14 @@ static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t *start_pos += max_size - content_size; break; case LV_FLEX_ALIGN_SPACE_BETWEEN: - *gap = (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt - 1); + *gap = (int32_t)(max_size - content_size) / (int32_t)(item_cnt - 1); break; case LV_FLEX_ALIGN_SPACE_AROUND: - *gap += (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt); + *gap += (int32_t)(max_size - content_size) / (int32_t)(item_cnt); *start_pos += *gap / 2; break; case LV_FLEX_ALIGN_SPACE_EVENLY: - *gap = (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt + 1); + *gap = (int32_t)(max_size - content_size) / (int32_t)(item_cnt + 1); *start_pos += *gap; break; default: @@ -600,4 +521,18 @@ static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, int32_t * item_id) } } +static int32_t lv_obj_get_width_with_margin(const lv_obj_t * obj) +{ + return lv_obj_get_style_margin_left(obj, LV_PART_MAIN) + + lv_obj_get_width(obj) + + lv_obj_get_style_margin_right(obj, LV_PART_MAIN); +} + +static int32_t lv_obj_get_height_with_margin(const lv_obj_t * obj) +{ + return lv_obj_get_style_margin_top(obj, LV_PART_MAIN) + + lv_obj_get_height(obj) + + lv_obj_get_style_margin_bottom(obj, LV_PART_MAIN); +} + #endif /*LV_USE_FLEX*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.h b/lib/libesp32_lvgl/lvgl/src/layouts/flex/lv_flex.h similarity index 50% rename from lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.h rename to lib/libesp32_lvgl/lvgl/src/layouts/flex/lv_flex.h index 58c3221e0..17e62790e 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/layouts/flex/lv_flex.h +++ b/lib/libesp32_lvgl/lvgl/src/layouts/flex/lv_flex.h @@ -13,16 +13,15 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../core/lv_obj.h" +#include "../../lv_conf_internal.h" +#include "../../misc/lv_area.h" + #if LV_USE_FLEX /********************* * DEFINES *********************/ -#define LV_OBJ_FLAG_FLEX_IN_NEW_TRACK LV_OBJ_FLAG_LAYOUT_1 -LV_EXPORT_CONST_INT(LV_OBJ_FLAG_FLEX_IN_NEW_TRACK); - #define _LV_FLEX_COLUMN (1 << 0) #define _LV_FLEX_WRAP (1 << 2) #define _LV_FLEX_REVERSE (1 << 3) @@ -32,7 +31,6 @@ LV_EXPORT_CONST_INT(LV_OBJ_FLAG_FLEX_IN_NEW_TRACK); **********************/ /*Can't include lv_obj.h because it includes this header file*/ -struct _lv_obj_t; typedef enum { LV_FLEX_ALIGN_START, @@ -57,12 +55,6 @@ typedef enum { /********************** * GLOBAL VARIABLES **********************/ -extern uint16_t LV_LAYOUT_FLEX; -extern lv_style_prop_t LV_STYLE_FLEX_FLOW; -extern lv_style_prop_t LV_STYLE_FLEX_MAIN_PLACE; -extern lv_style_prop_t LV_STYLE_FLEX_CROSS_PLACE; -extern lv_style_prop_t LV_STYLE_FLEX_TRACK_PLACE; -extern lv_style_prop_t LV_STYLE_FLEX_GROW; /********************** * GLOBAL PROTOTYPES @@ -75,18 +67,18 @@ extern lv_style_prop_t LV_STYLE_FLEX_GROW; void lv_flex_init(void); /** - * Set hot the item should flow - * @param flex pointer to a flex layout descriptor + * Set how the item should flow + * @param obj pointer to an object. The parent must have flex layout else nothing will happen. * @param flow an element of `lv_flex_flow_t`. */ void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow); /** * Set how to place (where to align) the items and tracks - * @param flex pointer: to a flex layout descriptor + * @param obj pointer to an object. The parent must have flex layout else nothing will happen. * @param main_place where to place the items on main axis (in their track). Any value of `lv_flex_align_t`. * @param cross_place where to place the item in their track on the cross axis. `LV_FLEX_ALIGN_START/END/CENTER` - * @param track_place where to place the tracks in the cross direction. Any value of `lv_flex_align_t`. + * @param track_cross_place where to place the tracks in the cross direction. Any value of `lv_flex_align_t`. */ void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place, lv_flex_align_t track_cross_place); @@ -98,47 +90,6 @@ void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_a */ void lv_obj_set_flex_grow(lv_obj_t * obj, uint8_t grow); -void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value); -void lv_style_set_flex_main_place(lv_style_t * style, lv_flex_align_t value); -void lv_style_set_flex_cross_place(lv_style_t * style, lv_flex_align_t value); -void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value); -void lv_style_set_flex_grow(lv_style_t * style, uint8_t value); -void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector); -void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector); -void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector); -void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector); -void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector); - -static inline lv_flex_flow_t lv_obj_get_style_flex_flow(const lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_FLOW); - return (lv_flex_flow_t)v.num; -} - -static inline lv_flex_align_t lv_obj_get_style_flex_main_place(const lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_MAIN_PLACE); - return (lv_flex_align_t)v.num; -} - -static inline lv_flex_align_t lv_obj_get_style_flex_cross_place(const lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_CROSS_PLACE); - return (lv_flex_align_t)v.num; -} - -static inline lv_flex_align_t lv_obj_get_style_flex_track_place(const lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_TRACK_PLACE); - return (lv_flex_align_t)v.num; -} - -static inline uint8_t lv_obj_get_style_flex_grow(const lv_obj_t * obj, uint32_t part) -{ - lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_GROW); - return (uint8_t)v.num; -} - /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.c b/lib/libesp32_lvgl/lvgl/src/layouts/grid/lv_grid.c similarity index 53% rename from lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.c rename to lib/libesp32_lvgl/lvgl/src/layouts/grid/lv_grid.c index 74f8e95fb..e5da88270 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/layouts/grid/lv_grid.c +++ b/lib/libesp32_lvgl/lvgl/src/layouts/grid/lv_grid.c @@ -6,13 +6,19 @@ /********************* * INCLUDES *********************/ -#include "../lv_layouts.h" +#include "lv_grid.h" #if LV_USE_GRID +#include "../../stdlib/lv_string.h" +#include "../lv_layout.h" +#include "../../core/lv_obj.h" +#include "../../core/lv_global.h" /********************* * DEFINES *********************/ +#define layout_list_def LV_GLOBAL_DEFAULT()->layout_list + /** * Some helper defines */ @@ -30,17 +36,16 @@ typedef struct { } item_repos_hint_t; typedef struct { - lv_coord_t * x; - lv_coord_t * y; - lv_coord_t * w; - lv_coord_t * h; + int32_t * x; + int32_t * y; + int32_t * w; + int32_t * h; uint32_t col_num; uint32_t row_num; - lv_coord_t grid_w; - lv_coord_t grid_h; + int32_t grid_w; + int32_t grid_h; } _lv_grid_calc_t; - /********************** * GLOBAL PROTOTYPES **********************/ @@ -54,65 +59,65 @@ static void calc_free(_lv_grid_calc_t * calc); static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c); static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c); static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * hint); -static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t align, lv_coord_t gap, uint32_t track_num, - lv_coord_t * size_array, lv_coord_t * pos_array, bool reverse); -static uint32_t count_tracks(const lv_coord_t * templ); +static int32_t grid_align(int32_t cont_size, bool auto_size, lv_grid_align_t align, int32_t gap, + uint32_t track_num, + int32_t * size_array, int32_t * pos_array, bool reverse); +static uint32_t count_tracks(const int32_t * templ); -static inline const lv_coord_t * get_col_dsc(lv_obj_t * obj) +static inline const int32_t * get_col_dsc(lv_obj_t * obj) { return lv_obj_get_style_grid_column_dsc_array(obj, 0); } -static inline const lv_coord_t * get_row_dsc(lv_obj_t * obj) +static inline const int32_t * get_row_dsc(lv_obj_t * obj) { return lv_obj_get_style_grid_row_dsc_array(obj, 0); } -static inline uint8_t get_col_pos(lv_obj_t * obj) +static inline int32_t get_col_pos(lv_obj_t * obj) { return lv_obj_get_style_grid_cell_column_pos(obj, 0); } -static inline uint8_t get_row_pos(lv_obj_t * obj) +static inline int32_t get_row_pos(lv_obj_t * obj) { return lv_obj_get_style_grid_cell_row_pos(obj, 0); } -static inline uint8_t get_col_span(lv_obj_t * obj) +static inline int32_t get_col_span(lv_obj_t * obj) { return lv_obj_get_style_grid_cell_column_span(obj, 0); } -static inline uint8_t get_row_span(lv_obj_t * obj) +static inline int32_t get_row_span(lv_obj_t * obj) { return lv_obj_get_style_grid_cell_row_span(obj, 0); } -static inline uint8_t get_cell_col_align(lv_obj_t * obj) +static inline lv_grid_align_t get_cell_col_align(lv_obj_t * obj) { return lv_obj_get_style_grid_cell_x_align(obj, 0); } -static inline uint8_t get_cell_row_align(lv_obj_t * obj) +static inline lv_grid_align_t get_cell_row_align(lv_obj_t * obj) { return lv_obj_get_style_grid_cell_y_align(obj, 0); } -static inline uint8_t get_grid_col_align(lv_obj_t * obj) +static inline lv_grid_align_t get_grid_col_align(lv_obj_t * obj) { return lv_obj_get_style_grid_column_align(obj, 0); } -static inline uint8_t get_grid_row_align(lv_obj_t * obj) +static inline lv_grid_align_t get_grid_row_align(lv_obj_t * obj) { return lv_obj_get_style_grid_row_align(obj, 0); } +static inline int32_t get_margin_hor(lv_obj_t * obj) +{ + return lv_obj_get_style_margin_left(obj, LV_PART_MAIN) + + lv_obj_get_style_margin_right(obj, LV_PART_MAIN); +} +static inline int32_t get_margin_ver(lv_obj_t * obj) +{ + return lv_obj_get_style_margin_top(obj, LV_PART_MAIN) + + lv_obj_get_style_margin_bottom(obj, LV_PART_MAIN); +} /********************** * GLOBAL VARIABLES **********************/ -uint16_t LV_LAYOUT_GRID; -lv_style_prop_t LV_STYLE_GRID_COLUMN_DSC_ARRAY; -lv_style_prop_t LV_STYLE_GRID_COLUMN_ALIGN; -lv_style_prop_t LV_STYLE_GRID_ROW_DSC_ARRAY; -lv_style_prop_t LV_STYLE_GRID_ROW_ALIGN; -lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_POS; -lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_SPAN; -lv_style_prop_t LV_STYLE_GRID_CELL_X_ALIGN; -lv_style_prop_t LV_STYLE_GRID_CELL_ROW_POS; -lv_style_prop_t LV_STYLE_GRID_CELL_ROW_SPAN; -lv_style_prop_t LV_STYLE_GRID_CELL_Y_ALIGN; /********************** * STATIC VARIABLES @@ -121,30 +126,23 @@ lv_style_prop_t LV_STYLE_GRID_CELL_Y_ALIGN; /********************** * MACROS **********************/ +#if LV_USE_LOG && LV_LOG_TRACE_LAYOUT + #define LV_TRACE_LAYOUT(...) LV_LOG_TRACE(__VA_ARGS__) +#else + #define LV_TRACE_LAYOUT(...) +#endif /********************** * GLOBAL FUNCTIONS **********************/ - void lv_grid_init(void) { - LV_LAYOUT_GRID = lv_layout_register(grid_update, NULL); - - LV_STYLE_GRID_COLUMN_DSC_ARRAY = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); - LV_STYLE_GRID_ROW_DSC_ARRAY = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); - LV_STYLE_GRID_COLUMN_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); - LV_STYLE_GRID_ROW_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); - - LV_STYLE_GRID_CELL_ROW_SPAN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); - LV_STYLE_GRID_CELL_ROW_POS = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); - LV_STYLE_GRID_CELL_COLUMN_SPAN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); - LV_STYLE_GRID_CELL_COLUMN_POS = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); - LV_STYLE_GRID_CELL_X_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); - LV_STYLE_GRID_CELL_Y_ALIGN = lv_style_register_prop(LV_STYLE_PROP_LAYOUT_REFR); + layout_list_def[LV_LAYOUT_GRID].cb = grid_update; + layout_list_def[LV_LAYOUT_GRID].user_data = NULL; } -void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const lv_coord_t col_dsc[], const lv_coord_t row_dsc[]) +void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const int32_t col_dsc[], const int32_t row_dsc[]) { lv_obj_set_style_grid_column_dsc_array(obj, col_dsc, 0); lv_obj_set_style_grid_row_dsc_array(obj, row_dsc, 0); @@ -158,8 +156,8 @@ void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid } -void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t x_align, uint8_t col_pos, uint8_t col_span, - lv_grid_align_t y_align, uint8_t row_pos, uint8_t row_span) +void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t x_align, int32_t col_pos, int32_t col_span, + lv_grid_align_t y_align, int32_t row_pos, int32_t row_span) { lv_obj_set_style_grid_cell_column_pos(obj, col_pos, 0); @@ -172,171 +170,6 @@ void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t x_align, uint8_t col_p lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj)); } - -void lv_style_set_grid_row_dsc_array(lv_style_t * style, const lv_coord_t value[]) -{ - lv_style_value_t v = { - .ptr = (const void *)value - }; - lv_style_set_prop(style, LV_STYLE_GRID_ROW_DSC_ARRAY, v); -} - -void lv_style_set_grid_column_dsc_array(lv_style_t * style, const lv_coord_t value[]) -{ - lv_style_value_t v = { - .ptr = (const void *)value - }; - lv_style_set_prop(style, LV_STYLE_GRID_COLUMN_DSC_ARRAY, v); -} - -void lv_style_set_grid_row_align(lv_style_t * style, lv_grid_align_t value) -{ - lv_style_value_t v = { - .num = (lv_grid_align_t)value - }; - lv_style_set_prop(style, LV_STYLE_GRID_ROW_ALIGN, v); -} - -void lv_style_set_grid_column_align(lv_style_t * style, lv_grid_align_t value) -{ - lv_style_value_t v = { - .num = (lv_grid_align_t)value - }; - lv_style_set_prop(style, LV_STYLE_GRID_COLUMN_ALIGN, v); -} - - -void lv_style_set_grid_cell_column_pos(lv_style_t * style, lv_coord_t value) -{ - lv_style_value_t v = { - .num = value - }; - lv_style_set_prop(style, LV_STYLE_GRID_CELL_COLUMN_POS, v); -} - -void lv_style_set_grid_cell_column_span(lv_style_t * style, lv_coord_t value) -{ - lv_style_value_t v = { - .num = value - }; - lv_style_set_prop(style, LV_STYLE_GRID_CELL_COLUMN_SPAN, v); -} - -void lv_style_set_grid_cell_row_pos(lv_style_t * style, lv_coord_t value) -{ - lv_style_value_t v = { - .num = value - }; - lv_style_set_prop(style, LV_STYLE_GRID_CELL_ROW_POS, v); -} - -void lv_style_set_grid_cell_row_span(lv_style_t * style, lv_coord_t value) -{ - lv_style_value_t v = { - .num = value - }; - lv_style_set_prop(style, LV_STYLE_GRID_CELL_ROW_SPAN, v); -} - -void lv_style_set_grid_cell_x_align(lv_style_t * style, lv_coord_t value) -{ - lv_style_value_t v = { - .num = value - }; - lv_style_set_prop(style, LV_STYLE_GRID_CELL_X_ALIGN, v); -} - -void lv_style_set_grid_cell_y_align(lv_style_t * style, lv_coord_t value) -{ - lv_style_value_t v = { - .num = value - }; - lv_style_set_prop(style, LV_STYLE_GRID_CELL_Y_ALIGN, v); -} - -void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector) -{ - lv_style_value_t v = { - .ptr = (const void *)value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_ROW_DSC_ARRAY, v, selector); -} - -void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector) -{ - lv_style_value_t v = { - .ptr = (const void *)value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_COLUMN_DSC_ARRAY, v, selector); -} - - -void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .num = (int32_t) value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_ROW_ALIGN, v, selector); -} - -void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .num = (int32_t) value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_COLUMN_ALIGN, v, selector); -} - - -void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .num = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_POS, v, selector); -} - -void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .num = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_SPAN, v, selector); -} - -void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .num = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_ROW_POS, v, selector); -} - -void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .num = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_ROW_SPAN, v, selector); -} - -void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .num = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_X_ALIGN, v, selector); -} - -void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector) -{ - lv_style_value_t v = { - .num = value - }; - lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_Y_ALIGN, v, selector); -} - - /********************** * STATIC FUNCTIONS **********************/ @@ -346,21 +179,20 @@ static void grid_update(lv_obj_t * cont, void * user_data) LV_LOG_INFO("update %p container", (void *)cont); LV_UNUSED(user_data); - const lv_coord_t * col_templ = get_col_dsc(cont); - const lv_coord_t * row_templ = get_row_dsc(cont); - if(col_templ == NULL || row_templ == NULL) return; + // const int32_t * col_templ = get_col_dsc(cont); + // const int32_t * row_templ = get_row_dsc(cont); + // if(col_templ == NULL || row_templ == NULL) return; _lv_grid_calc_t c; calc(cont, &c); item_repos_hint_t hint; - lv_memset_00(&hint, sizeof(hint)); + lv_memzero(&hint, sizeof(hint)); /*Calculate the grids absolute x and y coordinates. *It will be used as helper during item repositioning to avoid calculating this value for every children*/ - lv_coord_t border_widt = lv_obj_get_style_border_width(cont, LV_PART_MAIN); - lv_coord_t pad_left = lv_obj_get_style_pad_left(cont, LV_PART_MAIN) + border_widt; - lv_coord_t pad_top = lv_obj_get_style_pad_top(cont, LV_PART_MAIN) + border_widt; + int32_t pad_left = lv_obj_get_style_space_left(cont, LV_PART_MAIN); + int32_t pad_top = lv_obj_get_style_space_top(cont, LV_PART_MAIN); hint.grid_abs.x = pad_left + cont->coords.x1 - lv_obj_get_scroll_x(cont); hint.grid_abs.y = pad_top + cont->coords.y1 - lv_obj_get_scroll_y(cont); @@ -371,13 +203,13 @@ static void grid_update(lv_obj_t * cont, void * user_data) } calc_free(&c); - lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN); - lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN); + int32_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN); + int32_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN); if(w_set == LV_SIZE_CONTENT || h_set == LV_SIZE_CONTENT) { lv_obj_refr_size(cont); } - lv_event_send(cont, LV_EVENT_LAYOUT_CHANGED, NULL); + lv_obj_send_event(cont, LV_EVENT_LAYOUT_CHANGED, NULL); LV_TRACE_LAYOUT("finished"); } @@ -391,27 +223,27 @@ static void grid_update(lv_obj_t * cont, void * user_data) static void calc(lv_obj_t * cont, _lv_grid_calc_t * calc_out) { if(lv_obj_get_child(cont, 0) == NULL) { - lv_memset_00(calc_out, sizeof(_lv_grid_calc_t)); + lv_memzero(calc_out, sizeof(_lv_grid_calc_t)); return; } calc_rows(cont, calc_out); calc_cols(cont, calc_out); - lv_coord_t col_gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN); - lv_coord_t row_gap = lv_obj_get_style_pad_row(cont, LV_PART_MAIN); + int32_t col_gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN); + int32_t row_gap = lv_obj_get_style_pad_row(cont, LV_PART_MAIN); - bool rev = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false; + bool rev = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL; - lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN); - lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN); - bool auto_w = (w_set == LV_SIZE_CONTENT && !cont->w_layout) ? true : false; - lv_coord_t cont_w = lv_obj_get_content_width(cont); + int32_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN); + int32_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN); + bool auto_w = w_set == LV_SIZE_CONTENT && !cont->w_layout; + int32_t cont_w = lv_obj_get_content_width(cont); calc_out->grid_w = grid_align(cont_w, auto_w, get_grid_col_align(cont), col_gap, calc_out->col_num, calc_out->w, calc_out->x, rev); - bool auto_h = (h_set == LV_SIZE_CONTENT && !cont->h_layout) ? true : false; - lv_coord_t cont_h = lv_obj_get_content_height(cont); + bool auto_h = h_set == LV_SIZE_CONTENT && !cont->h_layout; + int32_t cont_h = lv_obj_get_content_height(cont); calc_out->grid_h = grid_align(cont_h, auto_h, get_grid_row_align(cont), row_gap, calc_out->row_num, calc_out->h, calc_out->y, false); @@ -424,29 +256,50 @@ static void calc(lv_obj_t * cont, _lv_grid_calc_t * calc_out) */ static void calc_free(_lv_grid_calc_t * calc) { - lv_mem_buf_release(calc->x); - lv_mem_buf_release(calc->y); - lv_mem_buf_release(calc->w); - lv_mem_buf_release(calc->h); + lv_free(calc->x); + lv_free(calc->y); + lv_free(calc->w); + lv_free(calc->h); } static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c) { - const lv_coord_t * col_templ = get_col_dsc(cont); - lv_coord_t cont_w = lv_obj_get_content_width(cont); + + const int32_t * col_templ; + col_templ = get_col_dsc(cont); + bool subgrid = false; + if(col_templ == NULL) { + lv_obj_t * parent = lv_obj_get_parent(cont); + col_templ = get_col_dsc(parent); + if(col_templ == NULL) { + LV_LOG_WARN("No col descriptor found even on the parent"); + return; + } + + int32_t pos = get_col_pos(cont); + int32_t span = get_col_span(cont); + + int32_t * col_templ_sub = lv_malloc(sizeof(int32_t) * (span + 1)); + lv_memcpy(col_templ_sub, &col_templ[pos], sizeof(int32_t) * span); + col_templ_sub[span] = LV_GRID_TEMPLATE_LAST; + col_templ = col_templ_sub; + subgrid = true; + } + + int32_t cont_w = lv_obj_get_content_width(cont); c->col_num = count_tracks(col_templ); - c->x = lv_mem_buf_get(sizeof(lv_coord_t) * c->col_num); - c->w = lv_mem_buf_get(sizeof(lv_coord_t) * c->col_num); + c->x = lv_malloc(sizeof(int32_t) * c->col_num); + c->w = lv_malloc(sizeof(int32_t) * c->col_num); /*Set sizes for CONTENT cells*/ uint32_t i; for(i = 0; i < c->col_num; i++) { - lv_coord_t size = LV_COORD_MIN; + int32_t size = LV_COORD_MIN; if(IS_CONTENT(col_templ[i])) { /*Check the size of children of this cell*/ uint32_t ci; - for(ci = 0; ci < lv_obj_get_child_cnt(cont); ci++) { + for(ci = 0; ci < lv_obj_get_child_count(cont); ci++) { lv_obj_t * item = lv_obj_get_child(cont, ci); if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; uint32_t col_span = get_col_span(item); @@ -463,10 +316,10 @@ static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c) } uint32_t col_fr_cnt = 0; - lv_coord_t grid_w = 0; + int32_t grid_w = 0; for(i = 0; i < c->col_num; i++) { - lv_coord_t x = col_templ[i]; + int32_t x = col_templ[i]; if(IS_FR(x)) { col_fr_cnt += GET_FR(x); } @@ -479,17 +332,17 @@ static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c) } } - lv_coord_t col_gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN); + int32_t col_gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN); cont_w -= col_gap * (c->col_num - 1); - lv_coord_t free_w = cont_w - grid_w; + int32_t free_w = cont_w - grid_w; if(free_w < 0) free_w = 0; int32_t last_fr_i = -1; int32_t last_fr_x = 0; for(i = 0; i < c->col_num; i++) { - lv_coord_t x = col_templ[i]; + int32_t x = col_templ[i]; if(IS_FR(x)) { - lv_coord_t f = GET_FR(x); + int32_t f = GET_FR(x); c->w[i] = (free_w * f) / col_fr_cnt; last_fr_i = i; last_fr_x = f; @@ -500,22 +353,46 @@ static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c) if(last_fr_i >= 0) { c->w[last_fr_i] = free_w - ((free_w * (col_fr_cnt - last_fr_x)) / col_fr_cnt); } + + if(subgrid) { + lv_free((void *)col_templ); + } } static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c) { - uint32_t i; - const lv_coord_t * row_templ = get_row_dsc(cont); + const int32_t * row_templ; + row_templ = get_row_dsc(cont); + bool subgrid = false; + if(row_templ == NULL) { + lv_obj_t * parent = lv_obj_get_parent(cont); + row_templ = get_row_dsc(parent); + if(row_templ == NULL) { + LV_LOG_WARN("No row descriptor found even on the parent"); + return; + } + + int32_t pos = get_row_pos(cont); + int32_t span = get_row_span(cont); + + int32_t * row_templ_sub = lv_malloc(sizeof(int32_t) * (span + 1)); + lv_memcpy(row_templ_sub, &row_templ[pos], sizeof(int32_t) * span); + row_templ_sub[span] = LV_GRID_TEMPLATE_LAST; + row_templ = row_templ_sub; + subgrid = true; + } + c->row_num = count_tracks(row_templ); - c->y = lv_mem_buf_get(sizeof(lv_coord_t) * c->row_num); - c->h = lv_mem_buf_get(sizeof(lv_coord_t) * c->row_num); + c->y = lv_malloc(sizeof(int32_t) * c->row_num); + c->h = lv_malloc(sizeof(int32_t) * c->row_num); /*Set sizes for CONTENT cells*/ + uint32_t i; for(i = 0; i < c->row_num; i++) { - lv_coord_t size = LV_COORD_MIN; + int32_t size = LV_COORD_MIN; if(IS_CONTENT(row_templ[i])) { /*Check the size of children of this cell*/ uint32_t ci; - for(ci = 0; ci < lv_obj_get_child_cnt(cont); ci++) { + for(ci = 0; ci < lv_obj_get_child_count(cont); ci++) { lv_obj_t * item = lv_obj_get_child(cont, ci); if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue; uint32_t row_span = get_row_span(item); @@ -532,10 +409,10 @@ static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c) } uint32_t row_fr_cnt = 0; - lv_coord_t grid_h = 0; + int32_t grid_h = 0; for(i = 0; i < c->row_num; i++) { - lv_coord_t x = row_templ[i]; + int32_t x = row_templ[i]; if(IS_FR(x)) { row_fr_cnt += GET_FR(x); } @@ -548,18 +425,17 @@ static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c) } } - - lv_coord_t row_gap = lv_obj_get_style_pad_row(cont, LV_PART_MAIN); - lv_coord_t cont_h = lv_obj_get_content_height(cont) - row_gap * (c->row_num - 1); - lv_coord_t free_h = cont_h - grid_h; + int32_t row_gap = lv_obj_get_style_pad_row(cont, LV_PART_MAIN); + int32_t cont_h = lv_obj_get_content_height(cont) - row_gap * (c->row_num - 1); + int32_t free_h = cont_h - grid_h; if(free_h < 0) free_h = 0; int32_t last_fr_i = -1; int32_t last_fr_x = 0; for(i = 0; i < c->row_num; i++) { - lv_coord_t x = row_templ[i]; + int32_t x = row_templ[i]; if(IS_FR(x)) { - lv_coord_t f = GET_FR(x); + int32_t f = GET_FR(x); c->h[i] = (free_h * f) / row_fr_cnt; last_fr_i = i; last_fr_x = f; @@ -570,6 +446,10 @@ static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c) if(last_fr_i >= 0) { c->h[last_fr_i] = free_h - ((free_h * (row_fr_cnt - last_fr_x)) / row_fr_cnt); } + + if(subgrid) { + lv_free((void *)row_templ); + } } /** @@ -591,15 +471,13 @@ static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * lv_grid_align_t col_align = get_cell_col_align(item); lv_grid_align_t row_align = get_cell_row_align(item); + int32_t col_x1 = c->x[col_pos]; + int32_t col_x2 = c->x[col_pos + col_span - 1] + c->w[col_pos + col_span - 1]; + int32_t col_w = col_x2 - col_x1; - lv_coord_t col_x1 = c->x[col_pos]; - lv_coord_t col_x2 = c->x[col_pos + col_span - 1] + c->w[col_pos + col_span - 1]; - lv_coord_t col_w = col_x2 - col_x1; - - lv_coord_t row_y1 = c->y[row_pos]; - lv_coord_t row_y2 = c->y[row_pos + row_span - 1] + c->h[row_pos + row_span - 1]; - lv_coord_t row_h = row_y2 - row_y1; - + int32_t row_y1 = c->y[row_pos]; + int32_t row_y2 = c->y[row_pos + row_span - 1] + c->h[row_pos + row_span - 1]; + int32_t row_h = row_y2 - row_y1; /*If the item has RTL base dir switch start and end*/ if(lv_obj_get_style_base_dir(item, LV_PART_MAIN) == LV_BASE_DIR_RTL) { @@ -607,28 +485,29 @@ static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * else if(col_align == LV_GRID_ALIGN_END) col_align = LV_GRID_ALIGN_START; } - lv_coord_t x; - lv_coord_t y; - lv_coord_t item_w = lv_area_get_width(&item->coords); - lv_coord_t item_h = lv_area_get_height(&item->coords); + int32_t x; + int32_t y; + int32_t item_w = lv_area_get_width(&item->coords); + int32_t item_h = lv_area_get_height(&item->coords); switch(col_align) { default: case LV_GRID_ALIGN_START: - x = c->x[col_pos]; + x = c->x[col_pos] + lv_obj_get_style_margin_left(item, LV_PART_MAIN); item->w_layout = 0; break; case LV_GRID_ALIGN_STRETCH: - x = c->x[col_pos]; - item_w = col_w; + x = c->x[col_pos] + lv_obj_get_style_margin_left(item, LV_PART_MAIN); + item_w = col_w - get_margin_hor(item); item->w_layout = 1; break; case LV_GRID_ALIGN_CENTER: - x = c->x[col_pos] + (col_w - item_w) / 2; + x = c->x[col_pos] + (col_w - item_w) / 2 + (lv_obj_get_style_margin_left(item, LV_PART_MAIN) - + lv_obj_get_style_margin_right(item, LV_PART_MAIN)) / 2; item->w_layout = 0; break; case LV_GRID_ALIGN_END: - x = c->x[col_pos] + col_w - lv_obj_get_width(item); + x = c->x[col_pos] + col_w - lv_obj_get_width(item) - lv_obj_get_style_margin_right(item, LV_PART_MAIN); item->w_layout = 0; break; } @@ -636,20 +515,21 @@ static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * switch(row_align) { default: case LV_GRID_ALIGN_START: - y = c->y[row_pos]; + y = c->y[row_pos] + lv_obj_get_style_margin_top(item, LV_PART_MAIN); item->h_layout = 0; break; case LV_GRID_ALIGN_STRETCH: - y = c->y[row_pos]; - item_h = row_h; + y = c->y[row_pos] + lv_obj_get_style_margin_top(item, LV_PART_MAIN); + item_h = row_h - get_margin_ver(item); item->h_layout = 1; break; case LV_GRID_ALIGN_CENTER: - y = c->y[row_pos] + (row_h - item_h) / 2; + y = c->y[row_pos] + (row_h - item_h) / 2 + (lv_obj_get_style_margin_top(item, LV_PART_MAIN) - + lv_obj_get_style_margin_bottom(item, LV_PART_MAIN)) / 2; item->h_layout = 0; break; case LV_GRID_ALIGN_END: - y = c->y[row_pos] + row_h - lv_obj_get_height(item); + y = c->y[row_pos] + row_h - lv_obj_get_height(item) - lv_obj_get_style_margin_bottom(item, LV_PART_MAIN); item->h_layout = 0; break; } @@ -662,24 +542,24 @@ static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * lv_area_set_width(&item->coords, item_w); lv_area_set_height(&item->coords, item_h); lv_obj_invalidate(item); - lv_event_send(item, LV_EVENT_SIZE_CHANGED, &old_coords); - lv_event_send(lv_obj_get_parent(item), LV_EVENT_CHILD_CHANGED, item); + lv_obj_send_event(item, LV_EVENT_SIZE_CHANGED, &old_coords); + lv_obj_send_event(lv_obj_get_parent(item), LV_EVENT_CHILD_CHANGED, item); } /*Handle percentage value of translate*/ - lv_coord_t tr_x = lv_obj_get_style_translate_x(item, LV_PART_MAIN); - lv_coord_t tr_y = lv_obj_get_style_translate_y(item, LV_PART_MAIN); - lv_coord_t w = lv_obj_get_width(item); - lv_coord_t h = lv_obj_get_height(item); + int32_t tr_x = lv_obj_get_style_translate_x(item, LV_PART_MAIN); + int32_t tr_y = lv_obj_get_style_translate_y(item, LV_PART_MAIN); + int32_t w = lv_obj_get_width(item); + int32_t h = lv_obj_get_height(item); if(LV_COORD_IS_PCT(tr_x)) tr_x = (w * LV_COORD_GET_PCT(tr_x)) / 100; if(LV_COORD_IS_PCT(tr_y)) tr_y = (h * LV_COORD_GET_PCT(tr_y)) / 100; x += tr_x; y += tr_y; - lv_coord_t diff_x = hint->grid_abs.x + x - item->coords.x1; - lv_coord_t diff_y = hint->grid_abs.y + y - item->coords.y1; + int32_t diff_x = hint->grid_abs.x + x - item->coords.x1; + int32_t diff_y = hint->grid_abs.y + y - item->coords.y1; if(diff_x || diff_y) { lv_obj_invalidate(item); item->coords.x1 += diff_x; @@ -703,10 +583,11 @@ static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * * @param pos_array write the positions of the tracks here * @return the total size of the grid */ -static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t align, lv_coord_t gap, uint32_t track_num, - lv_coord_t * size_array, lv_coord_t * pos_array, bool reverse) +static int32_t grid_align(int32_t cont_size, bool auto_size, lv_grid_align_t align, int32_t gap, + uint32_t track_num, + int32_t * size_array, int32_t * pos_array, bool reverse) { - lv_coord_t grid_size = 0; + int32_t grid_size = 0; uint32_t i; if(auto_size) { @@ -738,17 +619,18 @@ static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t alig break; case LV_GRID_ALIGN_SPACE_BETWEEN: pos_array[0] = 0; - gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num - 1); + gap = (int32_t)(cont_size - grid_size) / (int32_t)(track_num - 1); break; case LV_GRID_ALIGN_SPACE_AROUND: - gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num); + gap = (int32_t)(cont_size - grid_size) / (int32_t)(track_num); pos_array[0] = gap / 2; break; case LV_GRID_ALIGN_SPACE_EVENLY: - gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num + 1); + gap = (int32_t)(cont_size - grid_size) / (int32_t)(track_num + 1); pos_array[0] = gap; break; - + default: + break; } } @@ -757,7 +639,7 @@ static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t alig pos_array[i + 1] = pos_array[i] + size_array[i] + gap; } - lv_coord_t total_gird_size = pos_array[track_num - 1] + size_array[track_num - 1] - pos_array[0]; + int32_t total_gird_size = pos_array[track_num - 1] + size_array[track_num - 1] - pos_array[0]; if(reverse) { for(i = 0; i < track_num; i++) { @@ -770,7 +652,7 @@ static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t alig return total_gird_size; } -static uint32_t count_tracks(const lv_coord_t * templ) +static uint32_t count_tracks(const int32_t * templ) { uint32_t i; for(i = 0; templ[i] != LV_GRID_TEMPLATE_LAST; i++); @@ -778,5 +660,4 @@ static uint32_t count_tracks(const lv_coord_t * templ) return i; } - #endif /*LV_USE_GRID*/ diff --git a/lib/libesp32_lvgl/lvgl/src/layouts/grid/lv_grid.h b/lib/libesp32_lvgl/lvgl/src/layouts/grid/lv_grid.h new file mode 100644 index 000000000..3c64177e4 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/layouts/grid/lv_grid.h @@ -0,0 +1,102 @@ +/** + * @file lv_grid.h + * + */ + +#ifndef LV_GRID_H +#define LV_GRID_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" +#include "../../misc/lv_area.h" + +#if LV_USE_GRID + +/********************* + * DEFINES + *********************/ +/** + * Can be used track size to make the track fill the free space. + * @param x how much space to take proportionally to other FR tracks + * @return a special track size + */ +#define LV_GRID_FR(x) (LV_COORD_MAX - 100 + x) + +#define LV_GRID_CONTENT (LV_COORD_MAX - 101) +LV_EXPORT_CONST_INT(LV_GRID_CONTENT); + +#define LV_GRID_TEMPLATE_LAST (LV_COORD_MAX) +LV_EXPORT_CONST_INT(LV_GRID_TEMPLATE_LAST); + +/********************** + * TYPEDEFS + **********************/ + +/*Can't include lv_obj.h because it includes this header file*/ + +typedef enum { + LV_GRID_ALIGN_START, + LV_GRID_ALIGN_CENTER, + LV_GRID_ALIGN_END, + LV_GRID_ALIGN_STRETCH, + LV_GRID_ALIGN_SPACE_EVENLY, + LV_GRID_ALIGN_SPACE_AROUND, + LV_GRID_ALIGN_SPACE_BETWEEN, +} lv_grid_align_t; + +/********************** + * GLOBAL VARIABLES + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_grid_init(void); + +void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const int32_t col_dsc[], const int32_t row_dsc[]); + +void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid_align_t row_align); + +/** + * Set the cell of an object. The object's parent needs to have grid layout, else nothing will happen + * @param obj pointer to an object + * @param column_align the vertical alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH` + * @param col_pos column ID + * @param col_span number of columns to take (>= 1) + * @param row_align the horizontal alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH` + * @param row_pos row ID + * @param row_span number of rows to take (>= 1) + */ +void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t column_align, int32_t col_pos, int32_t col_span, + lv_grid_align_t row_align, int32_t row_pos, int32_t row_span); + +/** + * Just a wrapper to `LV_GRID_FR` for bindings. + */ +static inline int32_t lv_grid_fr(uint8_t x) +{ + return LV_GRID_FR(x); +} + +/********************** + * GLOBAL VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GRID*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_GRID_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/layouts/lv_layout.c b/lib/libesp32_lvgl/lvgl/src/layouts/lv_layout.c new file mode 100644 index 000000000..a14c1219f --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/layouts/lv_layout.c @@ -0,0 +1,79 @@ +/** + * @file lv_layout.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_layout.h" +#include "../core/lv_global.h" +#include "../core/lv_obj.h" + +/********************* + * DEFINES + *********************/ +#define layout_cnt LV_GLOBAL_DEFAULT()->layout_count +#define layout_list_def LV_GLOBAL_DEFAULT()->layout_list + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void _lv_layout_init(void) +{ + /*Malloc a list for the built in layouts*/ + layout_list_def = lv_malloc(layout_cnt * sizeof(lv_layout_dsc_t)); + +#if LV_USE_FLEX + lv_flex_init(); +#endif + +#if LV_USE_GRID + lv_grid_init(); +#endif +} + +void _lv_layout_deinit(void) +{ + lv_free(layout_list_def); +} + +uint32_t lv_layout_register(lv_layout_update_cb_t cb, void * user_data) +{ + layout_list_def = lv_realloc(layout_list_def, (layout_cnt + 1) * sizeof(lv_layout_dsc_t)); + LV_ASSERT_MALLOC(layout_list_def); + + layout_list_def[layout_cnt].cb = cb; + layout_list_def[layout_cnt].user_data = user_data; + return layout_cnt++; +} + +void _lv_layout_apply(lv_obj_t * obj) +{ + lv_layout_t layout_id = lv_obj_get_style_layout(obj, LV_PART_MAIN); + if(layout_id > 0 && layout_id <= layout_cnt) { + void * user_data = layout_list_def[layout_id].user_data; + layout_list_def[layout_id].cb(obj, user_data); + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/layouts/lv_layout.h b/lib/libesp32_lvgl/lvgl/src/layouts/lv_layout.h new file mode 100644 index 000000000..f8258b598 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/layouts/lv_layout.h @@ -0,0 +1,85 @@ +/** + * @file lv_layouts.h + * + */ + +#ifndef LV_LAYOUTS_H +#define LV_LAYOUTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" +#include "../misc/lv_types.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef void (*lv_layout_update_cb_t)(lv_obj_t *, void * user_data); +typedef struct { + lv_layout_update_cb_t cb; + void * user_data; +} lv_layout_dsc_t; + +typedef enum { + LV_LAYOUT_NONE = 0, + +#if LV_USE_FLEX + LV_LAYOUT_FLEX, +#endif + +#if LV_USE_GRID + LV_LAYOUT_GRID, +#endif + + _LV_LAYOUT_LAST +} lv_layout_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void _lv_layout_init(void); + +void _lv_layout_deinit(void); + +/** + * Register a new layout + * @param cb the layout update callback + * @param user_data custom data that will be passed to `cb` + * @return the ID of the new layout + */ +uint32_t lv_layout_register(lv_layout_update_cb_t cb, void * user_data); + +/** + * Update the layout of a widget + * @param obj pointer to a widget + */ +void _lv_layout_apply(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#if LV_USE_FLEX +#include "flex/lv_flex.h" +#endif /* LV_USE_FLEX */ + +#if LV_USE_GRID +#include "grid/lv_grid.h" +#endif /* LV_USE_GRID */ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_LAYOUTS_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/barcode/code128.c b/lib/libesp32_lvgl/lvgl/src/libs/barcode/code128.c new file mode 100644 index 000000000..88e329fa8 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/barcode/code128.c @@ -0,0 +1,582 @@ +// Copyright (c) 2013, LKC Technologies, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. Redistributions in binary +// form must reproduce the above copyright notice, this list of conditions and +// the following disclaimer in the documentation and/or other materials +// provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT +// HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "../../../lvgl.h" +#if LV_USE_BARCODE + +#include "code128.h" +#include + +#define CODE128_MALLOC lv_malloc +#define CODE128_REALLOC lv_realloc +#define CODE128_FREE lv_free +#define CODE128_MEMSET lv_memset +#define CODE128_STRLEN lv_strlen +#define CODE128_ASSERT LV_ASSERT + +#define CODE128_QUIET_ZONE_LEN 10 +#define CODE128_CHAR_LEN 11 +#define CODE128_STOP_CODE_LEN 13 + +#define CODE128_START_CODE_A 103 +#define CODE128_START_CODE_B 104 +#define CODE128_START_CODE_C 105 + +#define CODE128_MODE_A 'a' +#define CODE128_MODE_B 'b' +#define CODE128_MODE_C 'c' + +#define CODE128_MIN_ENCODE_LEN (CODE128_QUIET_ZONE_LEN * 2 + CODE128_CHAR_LEN * 2 + CODE128_STOP_CODE_LEN) + +static const int code128_pattern[] = { + // value: pattern, bar/space widths + 1740, // 0: 11011001100, 212222 + 1644, // 1: 11001101100, 222122 + 1638, // 2: 11001100110, 222221 + 1176, // 3: 10010011000, 121223 + 1164, // 4: 10010001100, 121322 + 1100, // 5: 10001001100, 131222 + 1224, // 6: 10011001000, 122213 + 1220, // 7: 10011000100, 122312 + 1124, // 8: 10001100100, 132212 + 1608, // 9: 11001001000, 221213 + 1604, // 10: 11001000100, 221312 + 1572, // 11: 11000100100, 231212 + 1436, // 12: 10110011100, 112232 + 1244, // 13: 10011011100, 122132 + 1230, // 14: 10011001110, 122231 + 1484, // 15: 10111001100, 113222 + 1260, // 16: 10011101100, 123122 + 1254, // 17: 10011100110, 123221 + 1650, // 18: 11001110010, 223211 + 1628, // 19: 11001011100, 221132 + 1614, // 20: 11001001110, 221231 + 1764, // 21: 11011100100, 213212 + 1652, // 22: 11001110100, 223112 + 1902, // 23: 11101101110, 312131 + 1868, // 24: 11101001100, 311222 + 1836, // 25: 11100101100, 321122 + 1830, // 26: 11100100110, 321221 + 1892, // 27: 11101100100, 312212 + 1844, // 28: 11100110100, 322112 + 1842, // 29: 11100110010, 322211 + 1752, // 30: 11011011000, 212123 + 1734, // 31: 11011000110, 212321 + 1590, // 32: 11000110110, 232121 + 1304, // 33: 10100011000, 111323 + 1112, // 34: 10001011000, 131123 + 1094, // 35: 10001000110, 131321 + 1416, // 36: 10110001000, 112313 + 1128, // 37: 10001101000, 132113 + 1122, // 38: 10001100010, 132311 + 1672, // 39: 11010001000, 211313 + 1576, // 40: 11000101000, 231113 + 1570, // 41: 11000100010, 231311 + 1464, // 42: 10110111000, 112133 + 1422, // 43: 10110001110 + 1134, // 44: 10001101110 + 1496, // 45: 10111011000, 113123 + 1478, // 46: 10111000110, 113321 + 1142, // 47: 10001110110, 133121 + 1910, // 48: 11101110110, 313121 + 1678, // 49: 11010001110, 211331 + 1582, // 50: 11000101110, 231131 + 1768, // 51: 11011101000, 213113 + 1762, // 52: 11011100010, 213311 + 1774, // 53: 11011101110, 213131 + 1880, // 54: 11101011000, 311123 + 1862, // 55: 11101000110, 311321 + 1814, // 56: 11100010110, 331121 + 1896, // 57: 11101101000, 312113 + 1890, // 58: 11101100010, 312311 + 1818, // 59: 11100011010, 332111 + 1914, // 60: 11101111010, 314111 + 1602, // 61: 11001000010, 221411 + 1930, // 62: 11110001010, 431111 + 1328, // 63: 10100110000, 111224 + 1292, // 64: 10100001100, 111422 + 1200, // 65: 10010110000, 121124 + 1158, // 66: 10010000110, 121421 + 1068, // 67: 10000101100, 141122 + 1062, // 68: 10000100110, 141221 + 1424, // 69: 10110010000, 112214 + 1412, // 70: 10110000100, 112412 + 1232, // 71: 10011010000, 122114 + 1218, // 72: 10011000010, 122411 + 1076, // 73: 10000110100, 142112 + 1074, // 74: 10000110010, 142211 + 1554, // 75: 11000010010, 241211 + 1616, // 76: 11001010000, 221114 + 1978, // 77: 11110111010, 413111 + 1556, // 78: 11000010100, 241112 + 1146, // 79: 10001111010, 134111 + 1340, // 80: 10100111100, 111242 + 1212, // 81: 10010111100, 121142 + 1182, // 82: 10010011110, 121241 + 1508, // 83: 10111100100, 114212 + 1268, // 84: 10011110100, 124112 + 1266, // 85: 10011110010, 124211 + 1956, // 86: 11110100100, 411212 + 1940, // 87: 11110010100, 421112 + 1938, // 88: 11110010010, 421211 + 1758, // 89: 11011011110, 212141 + 1782, // 90: 11011110110, 214121 + 1974, // 91: 11110110110, 412121 + 1400, // 92: 10101111000, 111143 + 1310, // 93: 10100011110, 111341 + 1118, // 94: 10001011110, 131141 + 1512, // 95: 10111101000, 114113 + 1506, // 96: 10111100010, 114311 + 1960, // 97: 11110101000, 411113 + 1954, // 98: 11110100010, 411311 + 1502, // 99: 10111011110, 113141 + 1518, // 100: 10111101110, 114131 + 1886, // 101: 11101011110, 311141 + 1966, // 102: 11110101110, 411131 + 1668, // 103: 11010000100, 211412 + 1680, // 104: 11010010000, 211214 + 1692 // 105: 11010011100, 211232 +}; + +static const int code128_stop_pattern = 6379; // 1100011101011, 2331112 + +struct code128_step { + int prev_ix; // Index of previous step, if any + const char * next_input; // Remaining input + unsigned short len; // The length of the pattern so far (includes this step) + char mode; // State for the current encoding + signed char code; // What code should be written for this step +}; + +struct code128_state { + struct code128_step * steps; + int allocated_steps; + int current_ix; + int todo_ix; + int best_ix; + + size_t maxlength; +}; + +size_t code128_estimate_len(const char * s) +{ + return CODE128_QUIET_ZONE_LEN + + CODE128_CHAR_LEN // start code + + CODE128_CHAR_LEN * (CODE128_STRLEN(s) * 11 / 10) // contents + 10% padding + + CODE128_CHAR_LEN // checksum + + CODE128_STOP_CODE_LEN + + CODE128_QUIET_ZONE_LEN; +} + +static void code128_append_pattern(int pattern, int pattern_length, char * out) +{ + // All patterns have their first bit set by design + CODE128_ASSERT(pattern & (1 << (pattern_length - 1))); + + int i; + for(i = pattern_length - 1; i >= 0; i--) { + // cast avoids warning: implicit conversion from 'int' to 'char' changes value from 255 to -1 [-Wconstant-conversion] + *out++ = (unsigned char)((pattern & (1 << i)) ? 255 : 0); + } +} + +static int code128_append_code(int code, char * out) +{ + CODE128_ASSERT(code >= 0 && code < (int)(sizeof(code128_pattern) / sizeof(code128_pattern[0]))); + code128_append_pattern(code128_pattern[code], CODE128_CHAR_LEN, out); + return CODE128_CHAR_LEN; +} + +static int code128_append_stop_code(char * out) +{ + code128_append_pattern(code128_stop_pattern, CODE128_STOP_CODE_LEN, out); + return CODE128_STOP_CODE_LEN; +} + +static signed char code128_switch_code(char from_mode, char to_mode) +{ + switch(from_mode) { + case CODE128_MODE_A: + switch(to_mode) { + case CODE128_MODE_B: + return 100; + case CODE128_MODE_C: + return 99; + } + break; + + case CODE128_MODE_B: + switch(to_mode) { + case CODE128_MODE_A: + return 101; + case CODE128_MODE_C: + return 99; + } + break; + + case CODE128_MODE_C: + switch(to_mode) { + case CODE128_MODE_B: + return 100; + case CODE128_MODE_A: + return 101; + } + break; + default: + break; + } + + CODE128_ASSERT(0); // Invalid mode switch + return -1; +} + +static signed char code128a_ascii_to_code(signed char value) +{ + if(value >= ' ' && value <= '_') + return (signed char)(value - ' '); + else if(value >= 0 && value < ' ') + return (signed char)(value + 64); + else if(value == (signed char)CODE128_FNC1) + return 102; + else if(value == (signed char)CODE128_FNC2) + return 97; + else if(value == (signed char)CODE128_FNC3) + return 96; + else if(value == (signed char)CODE128_FNC4) + return 101; + else + return -1; +} + +static signed char code128b_ascii_to_code(signed char value) +{ + if(value >= ' ') // value <= 127 is implied + return (signed char)(value - ' '); + else if(value == (signed char)CODE128_FNC1) + return 102; + else if(value == (signed char)CODE128_FNC2) + return 97; + else if(value == (signed char)CODE128_FNC3) + return 96; + else if(value == (signed char)CODE128_FNC4) + return 100; + else + return -1; +} + +static signed char code128c_ascii_to_code(const char * values) +{ + if(values[0] == CODE128_FNC1) + return 102; + + if(values[0] >= '0' && values[0] <= '9' && + values[1] >= '0' && values[1] <= '9') { + char code = 10 * (values[0] - '0') + (values[1] - '0'); + return code; + } + + return -1; +} + +static int code128_do_a_step(struct code128_step * base, int prev_ix, int ix) +{ + struct code128_step * previous_step = &base[prev_ix]; + struct code128_step * step = &base[ix]; + + char value = *previous_step->next_input; + // NOTE: Currently we can't encode NULL + if(value == 0) + return 0; + + step->code = code128a_ascii_to_code(value); + if(step->code < 0) + return 0; + + step->prev_ix = prev_ix; + step->next_input = previous_step->next_input + 1; + step->mode = CODE128_MODE_A; + step->len = previous_step->len + CODE128_CHAR_LEN; + if(step->mode != previous_step->mode) + step->len += CODE128_CHAR_LEN; // Need to switch modes + + return 1; +} + +static int code128_do_b_step(struct code128_step * base, int prev_ix, int ix) +{ + struct code128_step * previous_step = &base[prev_ix]; + struct code128_step * step = &base[ix]; + + char value = *previous_step->next_input; + // NOTE: Currently we can't encode NULL + if(value == 0) + return 0; + + step->code = code128b_ascii_to_code(value); + if(step->code < 0) + return 0; + + step->prev_ix = prev_ix; + step->next_input = previous_step->next_input + 1; + step->mode = CODE128_MODE_B; + step->len = previous_step->len + CODE128_CHAR_LEN; + if(step->mode != previous_step->mode) + step->len += CODE128_CHAR_LEN; // Need to switch modes + + return 1; +} + +static int code128_do_c_step(struct code128_step * base, int prev_ix, int ix) +{ + struct code128_step * previous_step = &base[prev_ix]; + struct code128_step * step = &base[ix]; + + char value = *previous_step->next_input; + // NOTE: Currently we can't encode NULL + if(value == 0) + return 0; + + step->code = code128c_ascii_to_code(previous_step->next_input); + if(step->code < 0) + return 0; + + step->prev_ix = prev_ix; + step->next_input = previous_step->next_input + 1; + + // Mode C consumes 2 characters for codes 0-99 + if(step->code < 100) + step->next_input++; + + step->mode = CODE128_MODE_C; + step->len = previous_step->len + CODE128_CHAR_LEN; + if(step->mode != previous_step->mode) + step->len += CODE128_CHAR_LEN; // Need to switch modes + + return 1; +} + +static struct code128_step * code128_alloc_step(struct code128_state * state) +{ + if(state->todo_ix >= state->allocated_steps) { + state->allocated_steps += 1024; + state->steps = (struct code128_step *) CODE128_REALLOC(state->steps, + state->allocated_steps * sizeof(struct code128_step)); + } + + struct code128_step * step = &state->steps[state->todo_ix]; + + CODE128_MEMSET(step, 0, sizeof(*step)); + return step; +} + +static void code128_do_step(struct code128_state * state) +{ + struct code128_step * step = &state->steps[state->current_ix]; + if(*step->next_input == 0) { + // Done, so see if we have a new shortest encoding. + if((step->len < state->maxlength) || + (state->best_ix < 0 && step->len == state->maxlength)) { + state->best_ix = state->current_ix; + + // Update maxlength to avoid considering anything longer + state->maxlength = step->len; + } + return; + } + + // Don't try if we're already at or beyond the max acceptable + // length; + if(step->len >= state->maxlength) + return; + char mode = step->mode; + + code128_alloc_step(state); + int mode_c_worked = 0; + + // Always try mode C + if(code128_do_c_step(state->steps, state->current_ix, state->todo_ix)) { + state->todo_ix++; + code128_alloc_step(state); + mode_c_worked = 1; + } + + if(mode == CODE128_MODE_A) { + // If A works, stick with A. There's no advantage to switching + // to B proactively if A still works. + if(code128_do_a_step(state->steps, state->current_ix, state->todo_ix) || + code128_do_b_step(state->steps, state->current_ix, state->todo_ix)) + state->todo_ix++; + } + else if(mode == CODE128_MODE_B) { + // The same logic applies here. There's no advantage to switching + // proactively to A if B still works. + if(code128_do_b_step(state->steps, state->current_ix, state->todo_ix) || + code128_do_a_step(state->steps, state->current_ix, state->todo_ix)) + state->todo_ix++; + } + else if(!mode_c_worked) { + // In mode C. If mode C worked and we're in mode C, trying anything + // else is pointless since the mode C encoding will be shorter and + // there won't be any mode switches. + + // If we're leaving mode C, though, try both in case one ends up + // better than the other. + if(code128_do_a_step(state->steps, state->current_ix, state->todo_ix)) { + state->todo_ix++; + code128_alloc_step(state); + } + if(code128_do_b_step(state->steps, state->current_ix, state->todo_ix)) + state->todo_ix++; + } +} + +size_t code128_encode_raw(const char * s, char * out, size_t maxlength) +{ + struct code128_state state; + + const size_t overhead = CODE128_QUIET_ZONE_LEN + + CODE128_CHAR_LEN // checksum + + CODE128_STOP_CODE_LEN + + CODE128_QUIET_ZONE_LEN; + if(maxlength < overhead + CODE128_CHAR_LEN + CODE128_CHAR_LEN) { + // Need space to encode the start character and one additional + // character. + return 0; + } + + state.allocated_steps = 256; + state.steps = (struct code128_step *) CODE128_MALLOC(state.allocated_steps * sizeof(struct code128_step)); + state.current_ix = 0; + state.todo_ix = 0; + state.maxlength = maxlength - overhead; + state.best_ix = -1; + + // Initialize the first 3 steps for the 3 encoding routes (A, B, C) + state.steps[0].prev_ix = -1; + state.steps[0].next_input = s; + state.steps[0].len = CODE128_CHAR_LEN; + state.steps[0].mode = CODE128_MODE_C; + state.steps[0].code = CODE128_START_CODE_C; + + state.steps[1].prev_ix = -1; + state.steps[1].next_input = s; + state.steps[1].len = CODE128_CHAR_LEN; + state.steps[1].mode = CODE128_MODE_A; + state.steps[1].code = CODE128_START_CODE_A; + + state.steps[2].prev_ix = -1; + state.steps[2].next_input = s; + state.steps[2].len = CODE128_CHAR_LEN; + state.steps[2].mode = CODE128_MODE_B; + state.steps[2].code = CODE128_START_CODE_B; + + state.todo_ix = 3; + + // Keep going until no more work + do { + code128_do_step(&state); + state.current_ix++; + } while(state.current_ix != state.todo_ix); + + // If no best_step, then fail. + if(state.best_ix < 0) { + CODE128_FREE(state.steps); + return 0; + } + + // Determine the list of codes + size_t num_codes = state.maxlength / CODE128_CHAR_LEN; + char * codes = CODE128_MALLOC(num_codes); + CODE128_ASSERT(codes); + + struct code128_step * step = &state.steps[state.best_ix]; + size_t i; + for(i = num_codes - 1; i > 0; --i) { + struct code128_step * prev_step = &state.steps[step->prev_ix]; + codes[i] = step->code; + if(step->mode != prev_step->mode) { + --i; + codes[i] = code128_switch_code(prev_step->mode, step->mode); + } + step = prev_step; + } + codes[0] = step->code; + + // Encode everything up to the checksum + size_t actual_length = state.maxlength + overhead; + CODE128_MEMSET(out, 0, CODE128_QUIET_ZONE_LEN); + out += CODE128_QUIET_ZONE_LEN; + for(i = 0; i < num_codes; i++) + out += code128_append_code(codes[i], out); + + // Compute the checksum + int sum = codes[0]; + for(i = 1; i < num_codes; i++) + sum += codes[i] * i; + out += code128_append_code(sum % 103, out); + + // Finalize the code. + out += code128_append_stop_code(out); + CODE128_MEMSET(out, 0, CODE128_QUIET_ZONE_LEN); + + CODE128_FREE(codes); + CODE128_FREE(state.steps); + return actual_length; +} + +/** + * @brief Encode the GS1 string + * + * This converts [FNC1] sequences to raw FNC1 characters and + * removes spaces before encoding the barcodes. + * + * @return the length of barcode data in bytes + */ +size_t code128_encode_gs1(const char * s, char * out, size_t maxlength) +{ + size_t raw_size = CODE128_STRLEN(s) + 1; + char * raw = CODE128_MALLOC(raw_size); + CODE128_ASSERT(raw); + if(!raw) { + return 0; + } + + char * p = raw; + for(; *s != '\0'; s++) { + if(strncmp(s, "[FNC1]", 6) == 0) { + *p++ = CODE128_FNC1; + s += 5; + } + else if(*s != ' ') { + *p++ = *s; + } + } + *p = '\0'; + + size_t length = code128_encode_raw(raw, out, maxlength); + + CODE128_FREE(raw); + + return length; +} + +#endif /*LV_USE_BARCODE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/barcode/code128.h b/lib/libesp32_lvgl/lvgl/src/libs/barcode/code128.h new file mode 100644 index 000000000..51d53d0cc --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/barcode/code128.h @@ -0,0 +1,47 @@ +// Copyright (c) 2013-15, LKC Technologies, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. Redistributions in binary +// form must reproduce the above copyright notice, this list of conditions and +// the following disclaimer in the documentation and/or other materials +// provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT +// HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CODE128_H +#define CODE128_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Since the FNCn characters are not ASCII, define versions here to +// simplify encoding strings that include them. +#define CODE128_FNC1 '\xf1' +#define CODE128_FNC2 '\xf2' +#define CODE128_FNC3 '\xf3' +#define CODE128_FNC4 '\xf4' + +size_t code128_estimate_len(const char * s); +size_t code128_encode_gs1(const char * s, char * out, size_t maxlength); +size_t code128_encode_raw(const char * s, char * out, size_t maxlength); + +#ifdef __cplusplus +} +#endif + +#endif // CODE128_H diff --git a/lib/libesp32_lvgl/lvgl/src/libs/barcode/lv_barcode.c b/lib/libesp32_lvgl/lvgl/src/libs/barcode/lv_barcode.c new file mode 100644 index 000000000..0af46725e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/barcode/lv_barcode.c @@ -0,0 +1,225 @@ +/** + * @file lv_barcode.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_barcode.h" +#if LV_USE_BARCODE + +#include "code128.h" + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_barcode_class + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_barcode_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_barcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static bool lv_barcode_change_buf_size(lv_obj_t * obj, int32_t w, int32_t h); + +/********************** + * STATIC VARIABLES + **********************/ + +const lv_obj_class_t lv_barcode_class = { + .constructor_cb = lv_barcode_constructor, + .destructor_cb = lv_barcode_destructor, + .width_def = LV_SIZE_CONTENT, + .instance_size = sizeof(lv_barcode_t), + .base_class = &lv_canvas_class, + .name = "barcode", +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_barcode_create(lv_obj_t * parent) +{ + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + return obj; +} + +void lv_barcode_set_dark_color(lv_obj_t * obj, lv_color_t color) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_barcode_t * barcode = (lv_barcode_t *)obj; + barcode->dark_color = color; +} + +void lv_barcode_set_light_color(lv_obj_t * obj, lv_color_t color) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_barcode_t * barcode = (lv_barcode_t *)obj; + barcode->light_color = color; +} + +void lv_barcode_set_scale(lv_obj_t * obj, uint16_t scale) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + if(scale == 0) { + scale = 1; + } + + lv_barcode_t * barcode = (lv_barcode_t *)obj; + barcode->scale = scale; +} + +void lv_barcode_set_direction(lv_obj_t * obj, lv_dir_t direction) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_barcode_t * barcode = (lv_barcode_t *)obj; + barcode->direction = direction; +} + +lv_result_t lv_barcode_update(lv_obj_t * obj, const char * data) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(data); + + lv_result_t res = LV_RESULT_INVALID; + lv_barcode_t * barcode = (lv_barcode_t *)obj; + + if(data == NULL || lv_strlen(data) == 0) { + LV_LOG_WARN("data is empty"); + return LV_RESULT_INVALID; + } + + size_t len = code128_estimate_len(data); + LV_LOG_INFO("data: %s, len = %zu", data, len); + + char * out_buf = lv_malloc(len); + LV_ASSERT_MALLOC(out_buf); + if(!out_buf) { + LV_LOG_ERROR("malloc failed for out_buf"); + return LV_RESULT_INVALID; + } + + int32_t barcode_w = code128_encode_gs1(data, out_buf, len); + LV_LOG_INFO("barcode width = %d", (int)barcode_w); + + LV_ASSERT(barcode->scale > 0); + uint16_t scale = barcode->scale; + + int32_t buf_w = (barcode->direction == LV_DIR_HOR) ? barcode_w * scale : 1; + int32_t buf_h = (barcode->direction == LV_DIR_VER) ? barcode_w * scale : 1; + + if(!lv_barcode_change_buf_size(obj, buf_w, buf_h)) { + goto failed; + } + + lv_canvas_set_palette(obj, 0, lv_color_to_32(barcode->dark_color, 0xff)); + lv_canvas_set_palette(obj, 1, lv_color_to_32(barcode->light_color, 0xff)); + + for(int32_t x = 0; x < barcode_w; x++) { + lv_color_t color; + color = lv_color_hex(out_buf[x] ? 0 : 1); + for(uint16_t i = 0; i < scale; i++) { + if(barcode->direction == LV_DIR_HOR) { + lv_canvas_set_px(obj, x * scale + i, 0, color, LV_OPA_COVER); + } + else { + lv_canvas_set_px(obj, 0, x * scale + i, color, LV_OPA_COVER); + } + } + } + + res = LV_RESULT_OK; + +failed: + lv_free(out_buf); + return res; +} + +lv_color_t lv_barcode_get_dark_color(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_barcode_t * barcode = (lv_barcode_t *)obj; + return barcode->dark_color; +} + +lv_color_t lv_barcode_get_light_color(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_barcode_t * barcode = (lv_barcode_t *)obj; + return barcode->light_color; +} + +uint16_t lv_barcode_get_scale(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_barcode_t * barcode = (lv_barcode_t *)obj; + return barcode->scale; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_barcode_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + + lv_barcode_t * barcode = (lv_barcode_t *)obj; + barcode->dark_color = lv_color_black(); + barcode->light_color = lv_color_white(); + barcode->scale = 1; + barcode->direction = LV_DIR_HOR; + lv_image_set_inner_align(obj, LV_IMAGE_ALIGN_TILE); +} + +static void lv_barcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + + lv_draw_buf_t * draw_buf = lv_canvas_get_draw_buf(obj); + if(draw_buf == NULL) return; + lv_image_cache_drop(draw_buf); + + /*@fixme destroy buffer in cache free_cb.*/ + lv_draw_buf_destroy(draw_buf); +} + +static bool lv_barcode_change_buf_size(lv_obj_t * obj, int32_t w, int32_t h) +{ + LV_ASSERT_NULL(obj); + LV_ASSERT(w > 0); + + lv_draw_buf_t * old_buf = lv_canvas_get_draw_buf(obj); + lv_draw_buf_t * new_buf = lv_draw_buf_create(w, h, LV_COLOR_FORMAT_I1, LV_STRIDE_AUTO); + if(new_buf == NULL) { + LV_LOG_ERROR("malloc failed for canvas buffer"); + return false; + } + + lv_canvas_set_draw_buf(obj, new_buf); + LV_LOG_INFO("set canvas buffer: %p, width = %d", new_buf, (int)w); + + if(old_buf != NULL) lv_draw_buf_destroy(old_buf); + return true; +} + +#endif /*LV_USE_BARCODE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/barcode/lv_barcode.h b/lib/libesp32_lvgl/lvgl/src/libs/barcode/lv_barcode.h new file mode 100644 index 000000000..ecd01eb78 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/barcode/lv_barcode.h @@ -0,0 +1,116 @@ +/** + * @file lv_barcode.c + * + */ + +#ifndef LV_BARCODE_H +#define LV_BARCODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_BARCODE + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*Data of barcode*/ +typedef struct { + lv_canvas_t canvas; + lv_color_t dark_color; + lv_color_t light_color; + uint16_t scale; + lv_dir_t direction; +} lv_barcode_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_barcode_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an empty barcode (an `lv_canvas`) object. + * @param parent point to an object where to create the barcode + * @return pointer to the created barcode object + */ +lv_obj_t * lv_barcode_create(lv_obj_t * parent); + +/** + * Set the dark color of a barcode object + * @param obj pointer to barcode object + * @param color dark color of the barcode + */ +void lv_barcode_set_dark_color(lv_obj_t * obj, lv_color_t color); + +/** + * Set the light color of a barcode object + * @param obj pointer to barcode object + * @param color light color of the barcode + */ +void lv_barcode_set_light_color(lv_obj_t * obj, lv_color_t color); + +/** + * Set the scale of a barcode object + * @param obj pointer to barcode object + * @param scale scale factor + */ +void lv_barcode_set_scale(lv_obj_t * obj, uint16_t scale); + +/** + * Set the direction of a barcode object + * @param obj pointer to barcode object + * @param direction draw direction (`LV_DIR_HOR` or `LB_DIR_VER`) + */ +void lv_barcode_set_direction(lv_obj_t * obj, lv_dir_t direction); + +/** + * Set the data of a barcode object + * @param obj pointer to barcode object + * @param data data to display + * @return LV_RESULT_OK: if no error; LV_RESULT_INVALID: on error + */ +lv_result_t lv_barcode_update(lv_obj_t * obj, const char * data); + +/** + * Get the dark color of a barcode object + * @param obj pointer to barcode object + * @return dark color of the barcode + */ +lv_color_t lv_barcode_get_dark_color(lv_obj_t * obj); + +/** + * Get the light color of a barcode object + * @param obj pointer to barcode object + * @return light color of the barcode + */ +lv_color_t lv_barcode_get_light_color(lv_obj_t * obj); + +/** + * Get the scale of a barcode object + * @param obj pointer to barcode object + * @return scale factor + */ +uint16_t lv_barcode_get_scale(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_BARCODE*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_BARCODE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/bin_decoder/lv_bin_decoder.c b/lib/libesp32_lvgl/lvgl/src/libs/bin_decoder/lv_bin_decoder.c new file mode 100644 index 000000000..21ed30e3a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/bin_decoder/lv_bin_decoder.c @@ -0,0 +1,1136 @@ +/** + * @file lv_image_decoder.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_bin_decoder.h" +#include "../../draw/lv_draw_image.h" +#include "../../draw/lv_draw_buf.h" +#include "../../stdlib/lv_string.h" +#include "../../stdlib/lv_sprintf.h" +#include "../../libs/rle/lv_rle.h" + +#if LV_USE_LZ4_EXTERNAL + #include +#endif + +#if LV_USE_LZ4_INTERNAL + #include "../../libs/lz4/lz4.h" +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** + * Data format for compressed image data. + */ + +typedef struct _lv_image_compressed_t { + uint32_t method: 4; /*Compression method, see `lv_image_compress_t`*/ + uint32_t reserved : 28; /*Reserved to be used later*/ + uint32_t compressed_size; /*Compressed data size in byte*/ + uint32_t decompressed_size; /*Decompressed data size in byte*/ + const uint8_t * data; /*Compressed data*/ +} lv_image_compressed_t; + +typedef struct { + lv_fs_file_t * f; + lv_color32_t * palette; + lv_opa_t * opa; + lv_image_compressed_t compressed; + lv_draw_buf_t * decoded; /*A draw buf to store decoded image*/ + lv_draw_buf_t * decompressed; /*Decompressed data could be used directly, thus must also be draw buf*/ + lv_draw_buf_t c_array; /*An C-array image that need to be converted to a draw buf*/ + lv_draw_buf_t * decoded_partial; /*A draw buf for decoded image via get_area_cb*/ +} decoder_data_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static decoder_data_t * get_decoder_data(lv_image_decoder_dsc_t * dsc); +static void free_decoder_data(lv_image_decoder_dsc_t * dsc); +static lv_result_t decode_indexed(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); +static lv_result_t load_indexed(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); +#if LV_BIN_DECODER_RAM_LOAD + static lv_result_t decode_rgb(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); +#endif +static lv_result_t decode_alpha_only(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); +static lv_result_t decode_indexed_line(lv_color_format_t color_format, const lv_color32_t * palette, int32_t x, + int32_t w_px, const uint8_t * in, lv_color32_t * out); +static lv_result_t decode_compressed(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); + +static lv_fs_res_t fs_read_file_at(lv_fs_file_t * f, uint32_t pos, void * buff, uint32_t btr, uint32_t * br); + +static lv_result_t decompress_image(lv_image_decoder_dsc_t * dsc, const lv_image_compressed_t * compressed); + +static void bin_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Initialize the lvgl binary image decoder module + */ +void lv_bin_decoder_init(void) +{ + lv_image_decoder_t * decoder; + + decoder = lv_image_decoder_create(); + LV_ASSERT_MALLOC(decoder); + if(decoder == NULL) { + LV_LOG_WARN("Out of memory"); + return; + } + + lv_image_decoder_set_info_cb(decoder, lv_bin_decoder_info); + lv_image_decoder_set_open_cb(decoder, lv_bin_decoder_open); + lv_image_decoder_set_get_area_cb(decoder, lv_bin_decoder_get_area); + lv_image_decoder_set_close_cb(decoder, lv_bin_decoder_close); + lv_image_decoder_set_cache_free_cb(decoder, (lv_cache_free_cb_t)bin_decoder_cache_free_cb); +} + +lv_result_t lv_bin_decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) +{ + LV_UNUSED(decoder); /*Unused*/ + + lv_image_src_t src_type = lv_image_src_get_type(src); + if(src_type == LV_IMAGE_SRC_VARIABLE) { + lv_image_dsc_t * image = (lv_image_dsc_t *)src; + lv_memcpy(header, &image->header, sizeof(lv_image_header_t)); + } + else if(src_type == LV_IMAGE_SRC_FILE) { + /*Support only "*.bin" files*/ + if(lv_strcmp(lv_fs_get_ext(src), "bin")) return LV_RESULT_INVALID; + + lv_fs_file_t f; + lv_fs_res_t res = lv_fs_open(&f, src, LV_FS_MODE_RD); + if(res == LV_FS_RES_OK) { + uint32_t rn; + res = lv_fs_read(&f, header, sizeof(lv_image_header_t), &rn); + lv_fs_close(&f); + if(res != LV_FS_RES_OK || rn != sizeof(lv_image_header_t)) { + LV_LOG_WARN("Read file header failed: %d", res); + return LV_RESULT_INVALID; + } + + /** + * @todo + * This is a temp backward compatibility solution after adding + * magic in image header. + */ + if(header->magic != LV_IMAGE_HEADER_MAGIC) { + LV_LOG_WARN("Legacy bin image detected: %s", (char *)src); + header->cf = header->magic; + header->magic = LV_IMAGE_HEADER_MAGIC; + } + + /*File is always read to buf, thus data can be modified.*/ + header->flags |= LV_IMAGE_FLAGS_MODIFIABLE; + } + } + else if(src_type == LV_IMAGE_SRC_SYMBOL) { + /*The size depend on the font but it is unknown here. It should be handled outside of the + *function*/ + header->w = 1; + header->h = 1; + /*Symbols always have transparent parts. Important because of cover check in the draw + *function. The actual value doesn't matter because lv_draw_label will draw it*/ + header->cf = LV_COLOR_FORMAT_A8; + } + else { + LV_LOG_WARN("Image get info found unknown src type"); + return LV_RESULT_INVALID; + } + + /*For backward compatibility, all images are not premultiplied for now.*/ + if(header->magic != LV_IMAGE_HEADER_MAGIC) { + header->flags &= ~LV_IMAGE_FLAGS_PREMULTIPLIED; + } + + return LV_RESULT_OK; +} + +/** + * Decode an image from a binary file + * @param decoder pointer to the decoder + * @param dsc pointer to the decoder descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image + */ +lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); + + lv_fs_res_t res = LV_RESULT_INVALID; + bool use_directly = false; /*If the image is already decoded and can be used directly*/ + + /*Open the file if it's a file*/ + if(dsc->src_type == LV_IMAGE_SRC_FILE) { + /*Support only "*.bin" files*/ + if(lv_strcmp(lv_fs_get_ext(dsc->src), "bin")) return LV_RESULT_INVALID; + + /*If the file was open successfully save the file descriptor*/ + decoder_data_t * decoder_data = get_decoder_data(dsc); + if(decoder_data == NULL) { + return LV_RESULT_INVALID; + } + + dsc->user_data = decoder_data; + lv_fs_file_t * f = lv_malloc(sizeof(*f)); + if(f == NULL) { + free_decoder_data(dsc); + return LV_RESULT_INVALID; + } + + res = lv_fs_open(f, dsc->src, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) { + LV_LOG_WARN("Open file failed: %d", res); + lv_free(f); + free_decoder_data(dsc); + return LV_RESULT_INVALID; + } + + decoder_data->f = f; /*Now free_decoder_data will take care of the file*/ + + lv_color_format_t cf = dsc->header.cf; + + if(dsc->header.flags & LV_IMAGE_FLAGS_COMPRESSED) { + res = decode_compressed(decoder, dsc); + } + else if(LV_COLOR_FORMAT_IS_INDEXED(cf)) { + if(dsc->args.use_indexed) { + /*Palette for indexed image and whole image of A8 image are always loaded to RAM for simplicity*/ + res = load_indexed(decoder, dsc); + } + else { + res = decode_indexed(decoder, dsc); + } + } + else if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf)) { + res = decode_alpha_only(decoder, dsc); + } +#if LV_BIN_DECODER_RAM_LOAD + else if(cf == LV_COLOR_FORMAT_ARGB8888 \ + || cf == LV_COLOR_FORMAT_XRGB8888 \ + || cf == LV_COLOR_FORMAT_RGB888 \ + || cf == LV_COLOR_FORMAT_RGB565 \ + || cf == LV_COLOR_FORMAT_RGB565A8) { + res = decode_rgb(decoder, dsc); + } +#else + else { + /* decode them in get_area_cb */ + res = LV_RESULT_OK; + } +#endif + } + + else if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) { + /*The variables should have valid data*/ + lv_image_dsc_t * image = (lv_image_dsc_t *)dsc->src; + if(image->data == NULL) { + return LV_RESULT_INVALID; + } + + lv_color_format_t cf = image->header.cf; + if(dsc->header.flags & LV_IMAGE_FLAGS_COMPRESSED) { + res = decode_compressed(decoder, dsc); + } + else if(LV_COLOR_FORMAT_IS_INDEXED(cf)) { + /*Need decoder data to store converted image*/ + decoder_data_t * decoder_data = get_decoder_data(dsc); + if(decoder_data == NULL) { + return LV_RESULT_INVALID; + } + + if(dsc->args.use_indexed) { + /*Palette for indexed image and whole image of A8 image are always loaded to RAM for simplicity*/ + res = load_indexed(decoder, dsc); + } + else { + res = decode_indexed(decoder, dsc); + } + } + else if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf)) { + /*Alpha only image will need decoder data to store pointer to decoded image, to free it when decoder closes*/ + decoder_data_t * decoder_data = get_decoder_data(dsc); + if(decoder_data == NULL) { + return LV_RESULT_INVALID; + } + + res = decode_alpha_only(decoder, dsc); + } + else { + /*In case of uncompressed formats the image stored in the ROM/RAM. + *So simply give its pointer*/ + + decoder_data_t * decoder_data = get_decoder_data(dsc); + lv_draw_buf_t * decoded = &decoder_data->c_array; + dsc->decoded = decoded; + lv_draw_buf_from_image(decoded, image); + + if(decoded->header.stride == 0) { + /*Use the auto calculated value from decoder_info callback*/ + decoded->header.stride = dsc->header.stride; + } + + res = LV_RESULT_OK; + use_directly = true; /*A variable image that can be used directly.*/ + } + } + + if(res != LV_RESULT_OK) { + free_decoder_data(dsc); + return res; + } + + if(dsc->decoded == NULL) return LV_RESULT_OK; /*Need to read via get_area_cb*/ + + lv_draw_buf_t * decoded = (lv_draw_buf_t *)dsc->decoded; + lv_draw_buf_t * adjusted = lv_image_decoder_post_process(dsc, decoded); + if(adjusted == NULL) { + free_decoder_data(dsc); + return LV_RESULT_INVALID; + } + + /*The adjusted draw buffer is newly allocated.*/ + if(adjusted != decoded) { + use_directly = false; /*Cannot use original image directly*/ + free_decoder_data(dsc); + decoder_data_t * decoder_data = get_decoder_data(dsc); + decoder_data->decoded = adjusted; /*Now this new buffer need to be free'd on decoder close*/ + } + dsc->decoded = adjusted; + + if(use_directly || dsc->args.no_cache) return LV_RESULT_OK; /*Do not put image to cache if it can be used directly.*/ + +#if LV_CACHE_DEF_SIZE > 0 + + /*Add it to cache*/ + lv_image_cache_data_t search_key; + search_key.src_type = dsc->src_type; + search_key.src = dsc->src; + search_key.slot.size = dsc->decoded->data_size; + + lv_cache_entry_t * cache_entry = lv_image_decoder_add_to_cache(decoder, &search_key, dsc->decoded, dsc->user_data); + if(cache_entry == NULL) { + free_decoder_data(dsc); + return LV_RESULT_INVALID; + } + dsc->cache_entry = cache_entry; + decoder_data_t * decoder_data = get_decoder_data(dsc); + decoder_data->decoded = NULL; /*Cache will take care of it*/ +#endif + + return LV_RESULT_OK; +} + +void lv_bin_decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); /*Unused*/ + + decoder_data_t * decoder_data = dsc->user_data; + if(decoder_data && decoder_data->decoded_partial) { + lv_draw_buf_destroy(decoder_data->decoded_partial); + decoder_data->decoded_partial = NULL; + } + + free_decoder_data(dsc); + + if(dsc->cache_entry) { + /*Decoded data is in cache, release it from cache's callback*/ + lv_cache_release(dsc->cache, dsc->cache_entry, NULL); + } + +} + +lv_result_t lv_bin_decoder_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, + const lv_area_t * full_area, lv_area_t * decoded_area) +{ + LV_UNUSED(decoder); /*Unused*/ + + lv_color_format_t cf = dsc->header.cf; + /*Check if cf is supported*/ + + bool supported = LV_COLOR_FORMAT_IS_INDEXED(cf) + || cf == LV_COLOR_FORMAT_ARGB8888 \ + || cf == LV_COLOR_FORMAT_XRGB8888 \ + || cf == LV_COLOR_FORMAT_RGB888 \ + || cf == LV_COLOR_FORMAT_RGB565 \ + || cf == LV_COLOR_FORMAT_RGB565A8; + if(!supported) { + LV_LOG_WARN("CF: %d is not supported", cf); + return LV_RESULT_INVALID; + } + + lv_result_t res = LV_RESULT_INVALID; + decoder_data_t * decoder_data = dsc->user_data; + if(decoder_data == NULL) { + LV_LOG_ERROR("Unexpected null decoder data"); + return LV_RESULT_INVALID; + } + + lv_fs_file_t * f = decoder_data->f; + uint32_t bpp = lv_color_format_get_bpp(cf); + int32_t w_px = lv_area_get_width(full_area); + uint8_t * img_data = NULL; + lv_draw_buf_t * decoded = NULL; + uint32_t offset = 0; + + /*We only support read line by line for now*/ + if(decoded_area->y1 == LV_COORD_MIN) { + /*Indexed image is converted to ARGB888*/ + uint32_t len = LV_COLOR_FORMAT_IS_INDEXED(cf) ? sizeof(lv_color32_t) * 8 : bpp; + lv_color_format_t cf_decoded = LV_COLOR_FORMAT_IS_INDEXED(cf) ? LV_COLOR_FORMAT_ARGB8888 : cf; + + len = (len * w_px) / 8; + decoded = decoder_data->decoded_partial; + if(decoded && decoded->header.w == w_px) { + /*Use existing one directly*/ + } + else { + decoded = lv_draw_buf_create(w_px, 1, cf_decoded, LV_STRIDE_AUTO); + if(decoded == NULL) + return LV_RESULT_INVALID; + } + + *decoded_area = *full_area; + decoded_area->y2 = decoded_area->y1; + decoder_data->decoded_partial = decoded; /*Free on decoder close*/ + } + else { + decoded_area->y1++; + decoded_area->y2++; + decoded = decoder_data->decoded_partial; /*Already alloced*/ + } + + img_data = decoded->data; /*Get the buffer to operate on*/ + + if(decoded_area->y1 > full_area->y2) { + return LV_RESULT_INVALID; + } + + if(LV_COLOR_FORMAT_IS_INDEXED(cf)) { + int32_t x_fraction = decoded_area->x1 % (8 / bpp); + uint32_t len = (w_px * bpp + 7) / 8 + 1; /*10px for 1bpp may across 3bytes*/ + uint8_t * buf = NULL; + + offset += dsc->palette_size * 4; /*Skip palette*/ + offset += decoded_area->y1 * dsc->header.stride; + offset += decoded_area->x1 * bpp / 8; /*Move to x1*/ + if(dsc->src_type == LV_IMAGE_SRC_FILE) { + offset += sizeof(lv_image_header_t); /*File image starts with image header*/ + buf = lv_malloc(len); + LV_ASSERT_NULL(buf); + if(buf == NULL) + return LV_RESULT_INVALID; + + res = fs_read_file_at(f, offset, buf, len, NULL); + if(res != LV_FS_RES_OK) { + lv_free(buf); + return LV_RESULT_INVALID; + } + } + else { + const lv_image_dsc_t * image = dsc->src; + buf = (void *)(image->data + offset); + } + + decode_indexed_line(cf, dsc->palette, x_fraction, w_px, buf, (lv_color32_t *)img_data); + + if(dsc->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)buf); + + dsc->decoded = decoded; /*Return decoded image*/ + return LV_RESULT_OK; + } + + if(cf == LV_COLOR_FORMAT_ARGB8888 || cf == LV_COLOR_FORMAT_XRGB8888 || cf == LV_COLOR_FORMAT_RGB888 + || cf == LV_COLOR_FORMAT_RGB565) { + uint32_t len = (w_px * bpp) / 8; + offset += decoded_area->y1 * dsc->header.stride; + offset += decoded_area->x1 * bpp / 8; /*Move to x1*/ + res = fs_read_file_at(f, offset, img_data, len, NULL); + if(res != LV_FS_RES_OK) { + return LV_RESULT_INVALID; + } + + dsc->decoded = decoded; /*Return decoded image*/ + return LV_RESULT_OK; + } + + if(cf == LV_COLOR_FORMAT_RGB565A8) { + bpp = 16; /* RGB565 + A8 mask*/ + uint32_t len = decoded->header.stride; + offset += decoded_area->y1 * dsc->header.stride; /*Move to y1*/ + offset += decoded_area->x1 * bpp / 8; /*Move to x1*/ + res = fs_read_file_at(f, offset, img_data, len, NULL); + if(res != LV_FS_RES_OK) { + return LV_RESULT_INVALID; + } + + /*Now the A8 mask*/ + offset = sizeof(lv_image_header_t); + offset += dsc->header.h * dsc->header.stride; /*Move to A8 map*/ + offset += decoded_area->y1 * (dsc->header.stride / 2); /*Move to y1*/ + offset += decoded_area->x1 * 1; /*Move to x1*/ + res = fs_read_file_at(f, offset, img_data + len, w_px * 1, NULL); + if(res != LV_FS_RES_OK) { + return LV_RESULT_INVALID; + } + + dsc->decoded = decoded; /*Return decoded image*/ + return LV_RESULT_OK; + } + + return LV_RESULT_INVALID; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static decoder_data_t * get_decoder_data(lv_image_decoder_dsc_t * dsc) +{ + decoder_data_t * data = dsc->user_data; + if(data == NULL) { + data = lv_malloc_zeroed(sizeof(decoder_data_t)); + LV_ASSERT_MALLOC(data); + if(data == NULL) { + LV_LOG_ERROR("Out of memory"); + return NULL; + } + + dsc->user_data = data; + } + + return data; +} + +static void free_decoder_data(lv_image_decoder_dsc_t * dsc) +{ + decoder_data_t * decoder_data = dsc->user_data; + if(decoder_data == NULL) return; + + if(decoder_data->f) { + lv_fs_close(decoder_data->f); + lv_free(decoder_data->f); + } + + if(decoder_data->decoded) lv_draw_buf_destroy(decoder_data->decoded); + if(decoder_data->decompressed) lv_draw_buf_destroy(decoder_data->decompressed); + lv_free(decoder_data->palette); + lv_free(decoder_data); + dsc->user_data = NULL; +} + +static lv_result_t decode_indexed(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); /*Unused*/ + lv_result_t res; + uint32_t rn; + decoder_data_t * decoder_data = dsc->user_data; + lv_fs_file_t * f = decoder_data->f; + lv_color_format_t cf = dsc->header.cf; + uint32_t palette_len = sizeof(lv_color32_t) * LV_COLOR_INDEXED_PALETTE_SIZE(cf); + const lv_color32_t * palette; + const uint8_t * indexed_data = NULL; + lv_draw_buf_t * draw_buf_indexed = NULL; + uint32_t stride = dsc->header.stride; + + bool is_compressed = dsc->header.flags & LV_IMAGE_FLAGS_COMPRESSED; + if(is_compressed) { + uint8_t * data = decoder_data->decompressed->data; + palette = (lv_color32_t *)data; + indexed_data = data + palette_len; + } + else if(dsc->src_type == LV_IMAGE_SRC_FILE) { + /*read palette for indexed image*/ + palette = lv_malloc(palette_len); + LV_ASSERT_MALLOC(palette); + if(palette == NULL) { + LV_LOG_ERROR("Out of memory"); + return LV_RESULT_INVALID; + } + + res = fs_read_file_at(f, sizeof(lv_image_header_t), (uint8_t *)palette, palette_len, &rn); + if(res != LV_FS_RES_OK || rn != palette_len) { + LV_LOG_WARN("Read palette failed: %d", res); + lv_free((void *)palette); + return LV_RESULT_INVALID; + } + + decoder_data->palette = (void *)palette; /*Need to free when decoder closes*/ + +#if LV_BIN_DECODER_RAM_LOAD + draw_buf_indexed = lv_draw_buf_create(dsc->header.w, dsc->header.h, cf, dsc->header.stride); + if(draw_buf_indexed == NULL) { + LV_LOG_ERROR("Draw buffer alloc failed"); + goto exit_with_buf; + } + + indexed_data = draw_buf_indexed->data; + + uint32_t data_len = 0; + if(lv_fs_seek(f, 0, LV_FS_SEEK_END) != LV_FS_RES_OK || + lv_fs_tell(f, &data_len) != LV_FS_RES_OK) { + LV_LOG_WARN("Failed to get file to size"); + goto exit_with_buf; + } + + uint32_t data_offset = sizeof(lv_image_header_t) + palette_len; + data_len -= data_offset; + res = fs_read_file_at(f, data_offset, (uint8_t *)indexed_data, data_len, &rn); + if(res != LV_FS_RES_OK || rn != data_len) { + LV_LOG_WARN("Read indexed image failed: %d", res); + goto exit_with_buf; + } +#endif + } + else if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) { + lv_image_dsc_t * image = (lv_image_dsc_t *)dsc->src; + palette = (lv_color32_t *)image->data; + indexed_data = image->data + palette_len; + } + else { + return LV_RESULT_INVALID; + } + + dsc->palette = palette; + dsc->palette_size = LV_COLOR_INDEXED_PALETTE_SIZE(cf); + +#if LV_BIN_DECODER_RAM_LOAD + /*Convert to ARGB8888, since sw renderer cannot render it directly even it's in RAM*/ + lv_draw_buf_t * decoded = lv_draw_buf_create(dsc->header.w, dsc->header.h, LV_COLOR_FORMAT_ARGB8888, + 0); + if(decoded == NULL) { + LV_LOG_ERROR("No memory for indexed image"); + goto exit_with_buf; + } + + stride = decoded->header.stride; + uint8_t * img_data = decoded->data; + + const uint8_t * in = indexed_data; + uint8_t * out = img_data; + for(uint32_t y = 0; y < dsc->header.h; y++) { + decode_indexed_line(cf, dsc->palette, 0, dsc->header.w, in, (lv_color32_t *)out); + in += dsc->header.stride; + out += stride; + } + + dsc->decoded = decoded; + decoder_data->decoded = decoded; /*Free when decoder closes*/ + if(dsc->src_type == LV_IMAGE_SRC_FILE && !is_compressed) { + decoder_data->palette = (void *)palette; /*Free decoder data on close*/ + lv_draw_buf_destroy(draw_buf_indexed); + } + + return LV_RESULT_OK; +exit_with_buf: + if(dsc->src_type == LV_IMAGE_SRC_FILE && !is_compressed) { + lv_free((void *)palette); + } + + if(draw_buf_indexed) lv_draw_buf_destroy(draw_buf_indexed); + return LV_RESULT_INVALID; +#else + LV_UNUSED(stride); + LV_UNUSED(indexed_data); + LV_UNUSED(draw_buf_indexed); + /*It needs to be read by get_area_cb later*/ + return LV_RESULT_OK; +#endif +} + +static lv_result_t load_indexed(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ +#if LV_BIN_DECODER_RAM_LOAD == 0 + LV_UNUSED(decoder); /*Unused*/ + LV_UNUSED(dsc); /*Unused*/ + LV_LOG_ERROR("LV_BIN_DECODER_RAM_LOAD is disabled"); + return LV_RESULT_INVALID; +#else + + LV_UNUSED(decoder); /*Unused*/ + + lv_result_t res; + uint32_t rn; + decoder_data_t * decoder_data = dsc->user_data; + + if(dsc->header.flags & LV_IMAGE_FLAGS_COMPRESSED) { + /*The decompressed image is already loaded to RAM*/ + dsc->decoded = decoder_data->decompressed; + + /*Transfer ownership to decoded pointer because it's the final data we use.*/ + decoder_data->decoded = decoder_data->decompressed; + decoder_data->decompressed = NULL; + return LV_RESULT_OK; + } + + if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) { + lv_image_dsc_t * image = (lv_image_dsc_t *)dsc->src; + lv_draw_buf_t * decoded = &decoder_data->c_array; + dsc->decoded = decoded; + lv_draw_buf_from_image(decoded, image); + + if(decoded->header.stride == 0) { + /*Use the auto calculated value from decoder_info callback*/ + decoded->header.stride = dsc->header.stride; + } + + return LV_RESULT_OK; + } + + if(dsc->src_type == LV_IMAGE_SRC_FILE) { + lv_color_format_t cf = dsc->header.cf; + lv_fs_file_t * f = decoder_data->f; + lv_draw_buf_t * decoded = lv_draw_buf_create(dsc->header.w, dsc->header.h, cf, dsc->header.stride); + if(decoded == NULL) { + LV_LOG_ERROR("Draw buffer alloc failed"); + return LV_RESULT_INVALID; + } + + uint8_t * data = decoded->data; + uint32_t palette_len = sizeof(lv_color32_t) * LV_COLOR_INDEXED_PALETTE_SIZE(cf); + res = fs_read_file_at(f, sizeof(lv_image_header_t), data, palette_len, &rn); + if(res != LV_FS_RES_OK || rn != palette_len) { + LV_LOG_WARN("Read palette failed: %d", res); + lv_draw_buf_destroy(decoded); + return LV_RESULT_INVALID; + } + + uint32_t data_len = 0; + if(lv_fs_seek(f, 0, LV_FS_SEEK_END) != LV_FS_RES_OK || + lv_fs_tell(f, &data_len) != LV_FS_RES_OK) { + LV_LOG_WARN("Failed to get file to size"); + lv_draw_buf_destroy(decoded); + return LV_RESULT_INVALID; + } + + uint32_t data_offset = sizeof(lv_image_header_t) + palette_len; + data_len -= data_offset; + data += palette_len; + res = fs_read_file_at(f, data_offset, data, data_len, &rn); + if(res != LV_FS_RES_OK || rn != data_len) { + LV_LOG_WARN("Read indexed image failed: %d", res); + lv_draw_buf_destroy(decoded); + return LV_RESULT_INVALID; + } + + decoder_data->decoded = decoded; + dsc->decoded = decoded; + return LV_RESULT_OK; + } + + LV_LOG_ERROR("Unknown src type: %d", dsc->src_type); + return LV_RESULT_INVALID; +#endif +} + +#if LV_BIN_DECODER_RAM_LOAD +static lv_result_t decode_rgb(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); + lv_result_t res; + decoder_data_t * decoder_data = dsc->user_data; + lv_fs_file_t * f = decoder_data->f; + lv_color_format_t cf = dsc->header.cf; + + uint32_t len = dsc->header.stride * dsc->header.h; + if(cf == LV_COLOR_FORMAT_RGB565A8) { + len += (dsc->header.stride / 2) * dsc->header.h; /*A8 mask*/ + } + + lv_draw_buf_t * decoded = lv_draw_buf_create(dsc->header.w, dsc->header.h, cf, dsc->header.stride); + if(decoded == NULL) { + LV_LOG_ERROR("No memory for rgb file read"); + return LV_RESULT_INVALID; + } + + uint8_t * img_data = decoded->data; + + uint32_t rn; + res = fs_read_file_at(f, sizeof(lv_image_header_t), img_data, len, &rn); + if(res != LV_FS_RES_OK || rn != len) { + LV_LOG_WARN("Read rgb file failed: %d", res); + lv_draw_buf_destroy(decoded); + return LV_RESULT_INVALID; + } + + dsc->decoded = decoded; + decoder_data->decoded = decoded; /*Free when decoder closes*/ + return LV_RESULT_OK; +} +#endif + +/** + * Extend A1/2/4 to A8 with interpolation to reduce rounding error. + */ +static inline uint8_t bit_extend(uint8_t value, uint8_t bpp) +{ + if(value == 0) return 0; + + uint8_t res = value; + uint8_t bpp_now = bpp; + while(bpp_now < 8) { + res |= value << (8 - bpp_now); + bpp_now += bpp; + }; + + return res; +} + +static lv_result_t decode_alpha_only(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); + lv_result_t res; + uint32_t rn; + decoder_data_t * decoder_data = dsc->user_data; + uint8_t bpp = lv_color_format_get_bpp(dsc->header.cf); + uint32_t w = (dsc->header.stride * 8) / bpp; + uint32_t buf_stride = (w * 8 + 7) >> 3; /*stride for img_data*/ + uint32_t buf_len = w * dsc->header.h; /*always decode to A8 format*/ + lv_draw_buf_t * decoded; + uint32_t file_len = (uint32_t)dsc->header.stride * dsc->header.h; + + decoded = lv_draw_buf_create(w, dsc->header.h, LV_COLOR_FORMAT_A8, buf_stride); + if(decoded == NULL) { + LV_LOG_ERROR("Out of memory"); + return LV_RESULT_INVALID; + } + + uint8_t * img_data = decoded->data; + + if(dsc->header.flags & LV_IMAGE_FLAGS_COMPRESSED) { + /*Copy from image data*/ + lv_memcpy(img_data, decoder_data->decompressed->data, file_len); + } + else if(dsc->src_type == LV_IMAGE_SRC_FILE) { + res = fs_read_file_at(decoder_data->f, sizeof(lv_image_header_t), img_data, file_len, &rn); + if(res != LV_FS_RES_OK || rn != file_len) { + LV_LOG_WARN("Read header failed: %d", res); + lv_draw_buf_destroy(decoded); + return LV_RESULT_INVALID; + } + } + else if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) { + /*Copy from image data*/ + lv_memcpy(img_data, ((lv_image_dsc_t *)dsc->src)->data, file_len); + } + + if(dsc->header.cf != LV_COLOR_FORMAT_A8) { + /*Convert A1/2/4 to A8 from last pixel to first pixel*/ + uint8_t * in = img_data + file_len - 1; + uint8_t * out = img_data + buf_len - 1; + uint8_t mask = (1 << bpp) - 1; + uint8_t shift = 0; + for(uint32_t i = 0; i < buf_len; i++) { + /** + * Rounding error: + * Take bpp = 4 as example, alpha value of 0x0 to 0x0F should be + * mapped to 0x00 to 0xFF. Using below equation will give us 0x00 to 0xF0 + * thus causes error. We can simply interpolate the value to fix it. + * + * Equation: *out = ((*in >> shift) & mask) << (8 - bpp); + * Ideal: *out = ((*in >> shift) & mask) * 255 / ((1L << bpp) - 1) + */ + uint8_t value = ((*in >> shift) & mask); + *out = bit_extend(value, bpp); + shift += bpp; + if(shift >= 8) { + shift = 0; + in--; + } + out--; + } + } + + decoder_data->decoded = decoded; + dsc->decoded = decoded; + return LV_RESULT_OK; +} + +static lv_result_t decode_compressed(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + uint32_t rn; + uint32_t len; + uint32_t compressed_len; + decoder_data_t * decoder_data = get_decoder_data(dsc); + lv_result_t res; + uint8_t * file_buf = NULL; + lv_image_compressed_t * compressed = &decoder_data->compressed; + + lv_memzero(compressed, sizeof(lv_image_compressed_t)); + + if(dsc->src_type == LV_IMAGE_SRC_FILE) { + lv_fs_file_t * f = decoder_data->f; + + if(lv_fs_seek(f, 0, LV_FS_SEEK_END) != LV_FS_RES_OK || + lv_fs_tell(f, &compressed_len) != LV_FS_RES_OK) { + LV_LOG_WARN("Failed to get compressed file len"); + return LV_RESULT_INVALID; + } + + compressed_len -= sizeof(lv_image_header_t); + compressed_len -= 12; + + /*Read compress header*/ + len = 12; + res = fs_read_file_at(f, sizeof(lv_image_header_t), compressed, len, &rn); + if(res != LV_FS_RES_OK || rn != len) { + LV_LOG_WARN("Read compressed header failed: %d", res); + return LV_RESULT_INVALID; + } + + if(compressed->compressed_size != compressed_len) { + LV_LOG_WARN("Compressed size mismatch: %" LV_PRIu32" != %" LV_PRIu32, compressed->compressed_size, compressed_len); + return LV_RESULT_INVALID; + } + + file_buf = lv_malloc(compressed_len); + if(file_buf == NULL) { + LV_LOG_WARN("No memory for compressed file"); + return LV_RESULT_INVALID; + + } + + /*Continue to read the compressed data following compression header*/ + res = lv_fs_read(f, file_buf, compressed_len, &rn); + if(res != LV_FS_RES_OK || rn != compressed_len) { + LV_LOG_WARN("Read compressed file failed: %d", res); + lv_free(file_buf); + return LV_RESULT_INVALID; + } + + /*Decompress the image*/ + compressed->data = file_buf; + } + else if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) { + lv_image_dsc_t * image = (lv_image_dsc_t *)dsc->src; + compressed_len = image->data_size; + + /*Read compress header*/ + len = 12; + compressed_len -= len; + lv_memcpy(compressed, image->data, len); + compressed->data = image->data + len; + if(compressed->compressed_size != compressed_len) { + LV_LOG_WARN("Compressed size mismatch: %" LV_PRIu32" != %" LV_PRIu32, compressed->compressed_size, compressed_len); + return LV_RESULT_INVALID; + } + } + else { + LV_LOG_WARN("Compressed image only support file or variable"); + return LV_RESULT_INVALID; + } + + res = decompress_image(dsc, compressed); + compressed->data = NULL; /*No need to store the data any more*/ + lv_free(file_buf); + if(res != LV_RESULT_OK) { + LV_LOG_WARN("Decompress failed"); + return LV_RESULT_INVALID; + } + + /*Depends on the cf, need to further decode image like an C-array image*/ + lv_image_dsc_t * image = (lv_image_dsc_t *)dsc->src; + if(image->data == NULL) { + return LV_RESULT_INVALID; + } + + lv_color_format_t cf = dsc->header.cf; + if(LV_COLOR_FORMAT_IS_INDEXED(cf)) { + if(dsc->args.use_indexed) res = load_indexed(decoder, dsc); + else res = decode_indexed(decoder, dsc); + } + else if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf)) { + res = decode_alpha_only(decoder, dsc); + } + else { + /*The decompressed data is the original image data.*/ + dsc->decoded = decoder_data->decompressed; + + /*Transfer ownership of decompressed to `decoded` since it can be used directly*/ + decoder_data->decoded = decoder_data->decompressed; + decoder_data->decompressed = NULL; + res = LV_RESULT_OK; + } + + return res; +} + +static lv_result_t decode_indexed_line(lv_color_format_t color_format, const lv_color32_t * palette, int32_t x, + int32_t w_px, const uint8_t * in, lv_color32_t * out) +{ + uint8_t px_size; + uint16_t mask; + + int8_t shift = 0; + switch(color_format) { + case LV_COLOR_FORMAT_I1: + px_size = 1; + in += x / 8; /*8pixel per byte*/ + shift = 7 - (x & 0x7); + break; + case LV_COLOR_FORMAT_I2: + px_size = 2; + in += x / 4; /*4pixel per byte*/ + shift = 6 - 2 * (x & 0x3); + break; + case LV_COLOR_FORMAT_I4: + px_size = 4; + in += x / 2; /*2pixel per byte*/ + shift = 4 - 4 * (x & 0x1); + break; + case LV_COLOR_FORMAT_I8: + px_size = 8; + in += x; + shift = 0; + break; + default: + return LV_RESULT_INVALID; + } + + mask = (1 << px_size) - 1; /*E.g. px_size = 2; mask = 0x03*/ + + int32_t i; + for(i = 0; i < w_px; i++) { + uint8_t val_act = (*in >> shift) & mask; + out[i] = palette[val_act]; + + shift -= px_size; + if(shift < 0) { + shift = 8 - px_size; + in++; + } + } + return LV_RESULT_OK; +} + +static lv_fs_res_t fs_read_file_at(lv_fs_file_t * f, uint32_t pos, void * buff, uint32_t btr, uint32_t * br) +{ + lv_fs_res_t res; + if(br) *br = 0; + + res = lv_fs_seek(f, pos, LV_FS_SEEK_SET); + if(res != LV_FS_RES_OK) { + return res; + } + + res |= lv_fs_read(f, buff, btr, br); + if(res != LV_FS_RES_OK) { + return res; + } + + return LV_FS_RES_OK; +} + +static lv_result_t decompress_image(lv_image_decoder_dsc_t * dsc, const lv_image_compressed_t * compressed) +{ + /*Need to store decompressed data to decoder to free on close*/ + decoder_data_t * decoder_data = get_decoder_data(dsc); + if(decoder_data == NULL) { + return LV_RESULT_INVALID; + } + + uint8_t * img_data; + uint32_t out_len = compressed->decompressed_size; + uint32_t input_len = compressed->compressed_size; + LV_UNUSED(input_len); + + /** + * @todo + * FIXME, RLE compressed image needs extra memory because decompression operates on + * pixel unit not byte unit. Should optimize RLE decompress to not write to extra memory. + */ + dsc->header.h += 1; + lv_draw_buf_t * decompressed = lv_draw_buf_create(dsc->header.w, dsc->header.h, dsc->header.cf, + dsc->header.stride); + if(decompressed == NULL) { + LV_LOG_WARN("No memory for decompressed image, input: %" LV_PRIu32 ", output: %" LV_PRIu32, input_len, out_len); + return LV_RESULT_INVALID; + } + + dsc->header.h -= 1; /*Change it back*/ + if(decompressed->data_size < out_len) { + LV_LOG_WARN("decompressed size mismatch: %" LV_PRIu32 ", %" LV_PRIu32, decompressed->data_size, out_len); + lv_draw_buf_destroy(decompressed); + return LV_RESULT_INVALID; + } + + img_data = decompressed->data; + + if(compressed->method == LV_IMAGE_COMPRESS_RLE) { +#if LV_USE_RLE + /*Compress always happen on byte*/ + uint32_t pixel_byte; + if(dsc->header.cf == LV_COLOR_FORMAT_RGB565A8) + pixel_byte = 2; + else + pixel_byte = (lv_color_format_get_bpp(dsc->header.cf) + 7) >> 3; + const uint8_t * input = compressed->data; + uint8_t * output = img_data; + uint32_t len; + len = lv_rle_decompress(input, input_len, output, out_len, pixel_byte); + if(len != compressed->decompressed_size) { + LV_LOG_WARN("Decompress failed: %" LV_PRIu32 ", got: %" LV_PRIu32, out_len, len); + lv_draw_buf_destroy(decompressed); + return LV_RESULT_INVALID; + } +#else + LV_LOG_WARN("RLE decompress is not enabled"); + lv_draw_buf_destroy(decompressed); + return LV_RESULT_INVALID; +#endif + } + else if(compressed->method == LV_IMAGE_COMPRESS_LZ4) { +#if LV_USE_LZ4 + const char * input = (const char *)compressed->data; + char * output = (char *)img_data; + int len; + len = LZ4_decompress_safe(input, output, input_len, out_len); + if(len < 0 || (uint32_t)len != compressed->decompressed_size) { + LV_LOG_WARN("Decompress failed: %" LV_PRId32 ", got: %" LV_PRId32, out_len, len); + lv_draw_buf_destroy(decompressed); + return LV_RESULT_INVALID; + } +#else + LV_LOG_WARN("LZ4 decompress is not enabled"); + lv_draw_buf_destroy(decompressed); + return LV_RESULT_INVALID; +#endif + } + else { + LV_UNUSED(img_data); + LV_LOG_WARN("Unknown compression method: %d", compressed->method); + lv_draw_buf_destroy(decompressed); + return LV_RESULT_INVALID; + } + + decoder_data->decompressed = decompressed; /*Free on decoder close*/ + return LV_RESULT_OK; +} + +static void bin_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data) +{ + LV_UNUSED(user_data); /*Unused*/ + + lv_draw_buf_destroy((lv_draw_buf_t *)cached_data->decoded); + if(cached_data->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)cached_data->src); +} diff --git a/lib/libesp32_lvgl/lvgl/src/libs/bin_decoder/lv_bin_decoder.h b/lib/libesp32_lvgl/lvgl/src/libs/bin_decoder/lv_bin_decoder.h new file mode 100644 index 000000000..2966dac39 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/bin_decoder/lv_bin_decoder.h @@ -0,0 +1,70 @@ +/** + * @file lv_bin_decoder.h + * + */ + +#ifndef LV_BIN_DECODER_H +#define LV_BIN_DECODER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../draw/lv_image_decoder.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the binary image decoder module + */ +void lv_bin_decoder_init(void); + +/** + * Get info about a lvgl binary image + * @param decoder the decoder where this function belongs + * @param src the image source: pointer to an `lv_image_dsc_t` variable, a file path or a symbol + * @param header store the image data here + * @return LV_RESULT_OK: the info is successfully stored in `header`; LV_RESULT_INVALID: unknown format or other error. + */ +lv_result_t lv_bin_decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); + +lv_result_t lv_bin_decoder_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, + const lv_area_t * full_area, lv_area_t * decoded_area); + +/** + * Open a lvgl binary image + * @param decoder the decoder where this function belongs + * @param dsc pointer to decoder descriptor. `src`, `style` are already initialized in it. + * @return LV_RESULT_OK: the info is successfully stored in `header`; LV_RESULT_INVALID: unknown format or other error. + */ +lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); + +/** + * Close the pending decoding. Free resources etc. + * @param decoder pointer to the decoder the function associated with + * @param dsc pointer to decoder descriptor + */ +void lv_bin_decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_BIN_DECODER_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/bmp/lv_bmp.c b/lib/libesp32_lvgl/lvgl/src/libs/bmp/lv_bmp.c new file mode 100644 index 000000000..c36f2cc12 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/bmp/lv_bmp.c @@ -0,0 +1,235 @@ +/** + * @file lv_bmp.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_BMP + +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_fs_file_t f; + unsigned int px_offset; + int px_width; + int px_height; + unsigned int bpp; + int row_size_bytes; +} bmp_dsc_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); + +static lv_result_t decoder_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, + const lv_area_t * full_area, lv_area_t * decoded_area); + +static void decoder_close(lv_image_decoder_t * dec, lv_image_decoder_dsc_t * dsc); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ +void lv_bmp_init(void) +{ + lv_image_decoder_t * dec = lv_image_decoder_create(); + lv_image_decoder_set_info_cb(dec, decoder_info); + lv_image_decoder_set_open_cb(dec, decoder_open); + lv_image_decoder_set_get_area_cb(dec, decoder_get_area); + lv_image_decoder_set_close_cb(dec, decoder_close); +} + +void lv_bmp_deinit(void) +{ + lv_image_decoder_t * dec = NULL; + while((dec = lv_image_decoder_get_next(dec)) != NULL) { + if(dec->info_cb == decoder_info) { + lv_image_decoder_delete(dec); + break; + } + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Get info about a BMP image + * @param src can be file name or pointer to a C array + * @param header store the info here + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't get the info + */ +static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) +{ + LV_UNUSED(decoder); + + lv_image_src_t src_type = lv_image_src_get_type(src); /*Get the source type*/ + + /*If it's a BMP file...*/ + if(src_type == LV_IMAGE_SRC_FILE) { + const char * fn = src; + if(lv_strcmp(lv_fs_get_ext(fn), "bmp") == 0) { /*Check the extension*/ + /*Save the data in the header*/ + lv_fs_file_t f; + lv_fs_res_t res = lv_fs_open(&f, src, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) return LV_RESULT_INVALID; + uint8_t headers[54]; + + lv_fs_read(&f, headers, 54, NULL); + uint32_t w; + uint32_t h; + lv_memcpy(&w, headers + 18, 4); + lv_memcpy(&h, headers + 22, 4); + header->w = w; + header->h = h; + lv_fs_close(&f); + + uint16_t bpp; + lv_memcpy(&bpp, headers + 28, 2); + switch(bpp) { + case 16: + header->cf = LV_COLOR_FORMAT_RGB565; + break; + case 24: + header->cf = LV_COLOR_FORMAT_RGB888; + break; + case 32: + header->cf = LV_COLOR_FORMAT_ARGB8888; + break; + default: + LV_LOG_WARN("Not supported bpp: %d", bpp); + return LV_RESULT_OK; + } + return LV_RESULT_OK; + } + } + /* BMP file as data not supported for simplicity. + * Convert them to LVGL compatible C arrays directly. */ + else if(src_type == LV_IMAGE_SRC_VARIABLE) { + return LV_RESULT_INVALID; + } + + return LV_RESULT_INVALID; /*If didn't succeeded earlier then it's an error*/ +} + +/** + * Open a BMP image and return the decided image + * @param decoder pointer to the decoder + * @param dsc pointer to the decoder descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image + */ +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); + + /*If it's a BMP file...*/ + if(dsc->src_type == LV_IMAGE_SRC_FILE) { + const char * fn = dsc->src; + + if(lv_strcmp(lv_fs_get_ext(fn), "bmp") != 0) { + return LV_RESULT_INVALID; /*Check the extension*/ + } + + bmp_dsc_t b; + lv_memset(&b, 0x00, sizeof(b)); + + lv_fs_res_t res = lv_fs_open(&b.f, dsc->src, LV_FS_MODE_RD); + if(res == LV_RESULT_OK) return LV_RESULT_INVALID; + + uint8_t header[54]; + lv_fs_read(&b.f, header, 54, NULL); + + if(0x42 != header[0] || 0x4d != header[1]) { + lv_fs_close(&b.f); + return LV_RESULT_INVALID; + } + + lv_memcpy(&b.px_offset, header + 10, 4); + lv_memcpy(&b.px_width, header + 18, 4); + lv_memcpy(&b.px_height, header + 22, 4); + lv_memcpy(&b.bpp, header + 28, 2); + b.row_size_bytes = ((b.bpp * b.px_width + 31) / 32) * 4; + + dsc->user_data = lv_malloc(sizeof(bmp_dsc_t)); + LV_ASSERT_MALLOC(dsc->user_data); + if(dsc->user_data == NULL) return LV_RESULT_INVALID; + lv_memcpy(dsc->user_data, &b, sizeof(b)); + return LV_RESULT_OK; + } + /* BMP file as data not supported for simplicity. + * Convert them to LVGL compatible C arrays directly. */ + else if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) { + return LV_RESULT_INVALID; + } + + return LV_RESULT_INVALID; /*If not returned earlier then it failed*/ +} + +static lv_result_t decoder_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, + const lv_area_t * full_area, lv_area_t * decoded_area) +{ + LV_UNUSED(decoder); + bmp_dsc_t * b = dsc->user_data; + lv_draw_buf_t * decoded = (void *)dsc->decoded; + + if(decoded_area->y1 == LV_COORD_MIN) { + *decoded_area = *full_area; + decoded_area->y2 = decoded_area->y1; + if(decoded == NULL) decoded = lv_draw_buf_create(lv_area_get_width(full_area), 1, dsc->header.cf, LV_STRIDE_AUTO); + dsc->decoded = decoded; + } + else { + decoded_area->y1++; + decoded_area->y2++; + } + + if(decoded_area->y1 > full_area->y2) { + return LV_RESULT_INVALID; + } + else { + int32_t y = (b->px_height - 1) - (decoded_area->y1); /*BMP images are stored upside down*/ + uint32_t p = b->px_offset + b->row_size_bytes * y; + p += (decoded_area->x1) * (b->bpp / 8); + lv_fs_seek(&b->f, p, LV_FS_SEEK_SET); + uint32_t line_width_byte = lv_area_get_width(full_area) * (b->bpp / 8); + lv_fs_read(&b->f, decoded->data, line_width_byte, NULL); + + return LV_RESULT_OK; + } +} + +/** + * Free the allocated resources + */ +static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); + bmp_dsc_t * b = dsc->user_data; + lv_fs_close(&b->f); + lv_free(dsc->user_data); + if(dsc->decoded) lv_draw_buf_destroy((void *)dsc->decoded); + +} + +#endif /*LV_USE_BMP*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/bmp/lv_bmp.h b/lib/libesp32_lvgl/lvgl/src/libs/bmp/lv_bmp.h similarity index 90% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/bmp/lv_bmp.h rename to lib/libesp32_lvgl/lvgl/src/libs/bmp/lv_bmp.h index db1e54096..a7dbe277b 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/bmp/lv_bmp.h +++ b/lib/libesp32_lvgl/lvgl/src/libs/bmp/lv_bmp.h @@ -13,7 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../lv_conf_internal.h" +#include "../../lv_conf_internal.h" #if LV_USE_BMP /********************* @@ -28,6 +28,7 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ void lv_bmp_init(void); +void lv_bmp_deinit(void); /********************** * MACROS diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.c b/lib/libesp32_lvgl/lvgl/src/libs/ffmpeg/lv_ffmpeg.c similarity index 83% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.c rename to lib/libesp32_lvgl/lvgl/src/libs/ffmpeg/lv_ffmpeg.c index efaa6925e..7efc5773a 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.c +++ b/lib/libesp32_lvgl/lvgl/src/libs/ffmpeg/lv_ffmpeg.c @@ -19,14 +19,10 @@ /********************* * DEFINES *********************/ -#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8 +#if LV_COLOR_DEPTH == 8 #define AV_PIX_FMT_TRUE_COLOR AV_PIX_FMT_RGB8 #elif LV_COLOR_DEPTH == 16 - #if LV_COLOR_16_SWAP == 0 - #define AV_PIX_FMT_TRUE_COLOR AV_PIX_FMT_RGB565LE - #else - #define AV_PIX_FMT_TRUE_COLOR AV_PIX_FMT_RGB565BE - #endif + #define AV_PIX_FMT_TRUE_COLOR AV_PIX_FMT_RGB565LE #elif LV_COLOR_DEPTH == 32 #define AV_PIX_FMT_TRUE_COLOR AV_PIX_FMT_BGR0 #else @@ -48,17 +44,18 @@ struct ffmpeg_context_s { uint8_t * video_dst_data[4]; struct SwsContext * sws_ctx; AVFrame * frame; - AVPacket pkt; + AVPacket * pkt; int video_stream_idx; int video_src_linesize[4]; int video_dst_linesize[4]; enum AVPixelFormat video_dst_pix_fmt; bool has_alpha; + lv_draw_buf_t draw_buf; }; #pragma pack(1) -struct lv_img_pixel_color_s { +struct lv_image_pixel_color_s { lv_color_t c; uint8_t alpha; }; @@ -69,18 +66,18 @@ struct lv_img_pixel_color_s { * STATIC PROTOTYPES **********************/ -static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header); -static lv_res_t decoder_open(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc); -static void decoder_close(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc); +static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); +static void decoder_close(lv_image_decoder_t * dec, lv_image_decoder_dsc_t * dsc); static struct ffmpeg_context_s * ffmpeg_open_file(const char * path); static void ffmpeg_close(struct ffmpeg_context_s * ffmpeg_ctx); static void ffmpeg_close_src_ctx(struct ffmpeg_context_s * ffmpeg_ctx); static void ffmpeg_close_dst_ctx(struct ffmpeg_context_s * ffmpeg_ctx); static int ffmpeg_image_allocate(struct ffmpeg_context_s * ffmpeg_ctx); -static int ffmpeg_get_img_header(const char * path, lv_img_header_t * header); +static int ffmpeg_get_image_header(const char * path, lv_image_header_t * header); static int ffmpeg_get_frame_refr_period(struct ffmpeg_context_s * ffmpeg_ctx); -static uint8_t * ffmpeg_get_img_data(struct ffmpeg_context_s * ffmpeg_ctx); +static uint8_t * ffmpeg_get_image_data(struct ffmpeg_context_s * ffmpeg_ctx); static int ffmpeg_update_next_frame(struct ffmpeg_context_s * ffmpeg_ctx); static int ffmpeg_output_video_frame(struct ffmpeg_context_s * ffmpeg_ctx); static bool ffmpeg_pix_fmt_has_alpha(enum AVPixelFormat pix_fmt); @@ -89,18 +86,16 @@ static bool ffmpeg_pix_fmt_is_yuv(enum AVPixelFormat pix_fmt); static void lv_ffmpeg_player_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void lv_ffmpeg_player_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -#if LV_COLOR_DEPTH != 32 - static void convert_color_depth(uint8_t * img, uint32_t px_cnt); -#endif - /********************** * STATIC VARIABLES **********************/ + const lv_obj_class_t lv_ffmpeg_player_class = { .constructor_cb = lv_ffmpeg_player_constructor, .destructor_cb = lv_ffmpeg_player_destructor, .instance_size = sizeof(lv_ffmpeg_player_t), - .base_class = &lv_img_class + .base_class = &lv_image_class, + .name = "ffmpeg-player", }; /********************** @@ -113,10 +108,10 @@ const lv_obj_class_t lv_ffmpeg_player_class = { void lv_ffmpeg_init(void) { - lv_img_decoder_t * dec = lv_img_decoder_create(); - lv_img_decoder_set_info_cb(dec, decoder_info); - lv_img_decoder_set_open_cb(dec, decoder_open); - lv_img_decoder_set_close_cb(dec, decoder_close); + lv_image_decoder_t * dec = lv_image_decoder_create(); + lv_image_decoder_set_info_cb(dec, decoder_info); + lv_image_decoder_set_open_cb(dec, decoder_open); + lv_image_decoder_set_close_cb(dec, decoder_close); #if LV_FFMPEG_AV_DUMP_FORMAT == 0 av_log_set_level(AV_LOG_QUIET); @@ -143,10 +138,10 @@ lv_obj_t * lv_ffmpeg_player_create(lv_obj_t * parent) return obj; } -lv_res_t lv_ffmpeg_player_set_src(lv_obj_t * obj, const char * path) +lv_result_t lv_ffmpeg_player_set_src(lv_obj_t * obj, const char * path) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_res_t res = LV_RES_INV; + lv_result_t res = LV_RESULT_INVALID; lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj; @@ -175,21 +170,15 @@ lv_res_t lv_ffmpeg_player_set_src(lv_obj_t * obj, const char * path) int height = player->ffmpeg_ctx->video_dec_ctx->height; uint32_t data_size = 0; - if(has_alpha) { - data_size = width * height * LV_IMG_PX_SIZE_ALPHA_BYTE; - } - else { - data_size = width * height * LV_COLOR_SIZE / 8; - } + data_size = width * height * 4; - player->imgdsc.header.always_zero = 0; player->imgdsc.header.w = width; player->imgdsc.header.h = height; player->imgdsc.data_size = data_size; - player->imgdsc.header.cf = has_alpha ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR; - player->imgdsc.data = ffmpeg_get_img_data(player->ffmpeg_ctx); + player->imgdsc.header.cf = has_alpha ? LV_COLOR_FORMAT_ARGB8888 : LV_COLOR_FORMAT_NATIVE; + player->imgdsc.data = ffmpeg_get_image_data(player->ffmpeg_ctx); - lv_img_set_src(&player->img.obj, &(player->imgdsc)); + lv_image_set_src(&player->img.obj, &(player->imgdsc)); int period = ffmpeg_get_frame_refr_period(player->ffmpeg_ctx); @@ -202,7 +191,7 @@ lv_res_t lv_ffmpeg_player_set_src(lv_obj_t * obj, const char * path) LV_LOG_WARN("unable to get frame refresh period"); } - res = LV_RES_OK; + res = LV_RESULT_OK; failed: return res; @@ -258,95 +247,87 @@ void lv_ffmpeg_player_set_auto_restart(lv_obj_t * obj, bool en) * STATIC FUNCTIONS **********************/ -static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header) +static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) { - /* Get the source type */ - lv_img_src_t src_type = lv_img_src_get_type(src); + LV_UNUSED(decoder); - if(src_type == LV_IMG_SRC_FILE) { + /* Get the source type */ + lv_image_src_t src_type = lv_image_src_get_type(src); + + if(src_type == LV_IMAGE_SRC_FILE) { const char * fn = src; - if(ffmpeg_get_img_header(fn, header) < 0) { + if(ffmpeg_get_image_header(fn, header) < 0) { LV_LOG_ERROR("ffmpeg can't get image header"); - return LV_RES_INV; + return LV_RESULT_INVALID; } - return LV_RES_OK; + return LV_RESULT_OK; } /* If didn't succeeded earlier then it's an error */ - return LV_RES_INV; + return LV_RESULT_INVALID; } -static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) +/** + * Decode an image using ffmpeg library + * @param decoder pointer to the decoder + * @param dsc pointer to the decoder descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image + */ +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) { - if(dsc->src_type == LV_IMG_SRC_FILE) { + LV_UNUSED(decoder); + + if(dsc->src_type == LV_IMAGE_SRC_FILE) { const char * path = dsc->src; struct ffmpeg_context_s * ffmpeg_ctx = ffmpeg_open_file(path); if(ffmpeg_ctx == NULL) { - return LV_RES_INV; + return LV_RESULT_INVALID; } if(ffmpeg_image_allocate(ffmpeg_ctx) < 0) { LV_LOG_ERROR("ffmpeg image allocate failed"); ffmpeg_close(ffmpeg_ctx); - return LV_RES_INV; + return LV_RESULT_INVALID; } if(ffmpeg_update_next_frame(ffmpeg_ctx) < 0) { ffmpeg_close(ffmpeg_ctx); LV_LOG_ERROR("ffmpeg update frame failed"); - return LV_RES_INV; + return LV_RESULT_INVALID; } ffmpeg_close_src_ctx(ffmpeg_ctx); - uint8_t * img_data = ffmpeg_get_img_data(ffmpeg_ctx); - -#if LV_COLOR_DEPTH != 32 - if(ffmpeg_ctx->has_alpha) { - convert_color_depth(img_data, dsc->header.w * dsc->header.h); - } -#endif + uint8_t * img_data = ffmpeg_get_image_data(ffmpeg_ctx); dsc->user_data = ffmpeg_ctx; - dsc->img_data = img_data; + lv_draw_buf_t * decoded = &ffmpeg_ctx->draw_buf; + decoded->header = dsc->header; + decoded->header.flags |= LV_IMAGE_FLAGS_MODIFIABLE; + decoded->data = img_data; + decoded->data_size = (uint32_t)dsc->header.stride * dsc->header.h; + decoded->unaligned_data = NULL; + dsc->decoded = decoded; /* The image is fully decoded. Return with its pointer */ - return LV_RES_OK; + return LV_RESULT_OK; } /* If not returned earlier then it failed */ - return LV_RES_INV; + return LV_RESULT_INVALID; } -static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) +static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) { + LV_UNUSED(decoder); struct ffmpeg_context_s * ffmpeg_ctx = dsc->user_data; ffmpeg_close(ffmpeg_ctx); } -#if LV_COLOR_DEPTH != 32 - -static void convert_color_depth(uint8_t * img, uint32_t px_cnt) -{ - lv_color32_t * img_src_p = (lv_color32_t *)img; - struct lv_img_pixel_color_s * img_dst_p = (struct lv_img_pixel_color_s *)img; - - for(uint32_t i = 0; i < px_cnt; i++) { - lv_color32_t temp = *img_src_p; - img_dst_p->c = lv_color_hex(temp.full); - img_dst_p->alpha = temp.ch.alpha; - - img_src_p++; - img_dst_p++; - } -} - -#endif - -static uint8_t * ffmpeg_get_img_data(struct ffmpeg_context_s * ffmpeg_ctx) +static uint8_t * ffmpeg_get_image_data(struct ffmpeg_context_s * ffmpeg_ctx) { uint8_t * img_data = ffmpeg_ctx->video_dst_data[0]; @@ -369,7 +350,7 @@ static bool ffmpeg_pix_fmt_has_alpha(enum AVPixelFormat pix_fmt) return true; } - return (desc->flags & AV_PIX_FMT_FLAG_ALPHA) ? true : false; + return desc->flags & AV_PIX_FMT_FLAG_ALPHA; } static bool ffmpeg_pix_fmt_is_yuv(enum AVPixelFormat pix_fmt) @@ -449,7 +430,7 @@ static int ffmpeg_output_video_frame(struct ffmpeg_context_s * ffmpeg_ctx) } if(!ffmpeg_ctx->has_alpha) { - int lv_linesize = sizeof(lv_color_t) * width; + int lv_linesize = lv_color_format_get_size(LV_COLOR_FORMAT_NATIVE) * width; int dst_linesize = ffmpeg_ctx->video_dst_linesize[0]; if(dst_linesize != lv_linesize) { LV_LOG_WARN("ffmpeg linesize = %d, but lvgl image require %d", @@ -524,7 +505,7 @@ static int ffmpeg_open_codec_context(int * stream_idx, int ret; int stream_index; AVStream * st; - AVCodec * dec = NULL; + const AVCodec * dec = NULL; AVDictionary * opts = NULL; ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0); @@ -574,8 +555,8 @@ static int ffmpeg_open_codec_context(int * stream_idx, return 0; } -static int ffmpeg_get_img_header(const char * filepath, - lv_img_header_t * header) +static int ffmpeg_get_image_header(const char * filepath, + lv_image_header_t * header) { int ret = -1; @@ -603,8 +584,8 @@ static int ffmpeg_get_img_header(const char * filepath, /* allocate image where the decoded image will be put */ header->w = video_dec_ctx->width; header->h = video_dec_ctx->height; - header->always_zero = 0; - header->cf = (has_alpha ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR); + header->cf = has_alpha ? LV_COLOR_FORMAT_ARGB8888 : LV_COLOR_FORMAT_NATIVE; + header->stride = header->w * lv_color_format_get_size(header->cf); ret = 0; } @@ -635,19 +616,19 @@ static int ffmpeg_update_next_frame(struct ffmpeg_context_s * ffmpeg_ctx) while(1) { /* read frames from the file */ - if(av_read_frame(ffmpeg_ctx->fmt_ctx, &(ffmpeg_ctx->pkt)) >= 0) { + if(av_read_frame(ffmpeg_ctx->fmt_ctx, ffmpeg_ctx->pkt) >= 0) { bool is_image = false; /* check if the packet belongs to a stream we are interested in, * otherwise skip it */ - if(ffmpeg_ctx->pkt.stream_index == ffmpeg_ctx->video_stream_idx) { + if(ffmpeg_ctx->pkt->stream_index == ffmpeg_ctx->video_stream_idx) { ret = ffmpeg_decode_packet(ffmpeg_ctx->video_dec_ctx, - &(ffmpeg_ctx->pkt), ffmpeg_ctx); + ffmpeg_ctx->pkt, ffmpeg_ctx); is_image = true; } - av_packet_unref(&(ffmpeg_ctx->pkt)); + av_packet_unref(ffmpeg_ctx->pkt); if(ret < 0) { LV_LOG_WARN("video frame is empty %d", ret); @@ -670,7 +651,7 @@ static int ffmpeg_update_next_frame(struct ffmpeg_context_s * ffmpeg_ctx) struct ffmpeg_context_s * ffmpeg_open_file(const char * path) { - if(path == NULL || strlen(path) == 0) { + if(path == NULL || lv_strlen(path) == 0) { LV_LOG_ERROR("file path is empty"); return NULL; } @@ -767,10 +748,15 @@ static int ffmpeg_image_allocate(struct ffmpeg_context_s * ffmpeg_ctx) return -1; } - /* initialize packet, set data to NULL, let the demuxer fill it */ - av_init_packet(&ffmpeg_ctx->pkt); - ffmpeg_ctx->pkt.data = NULL; - ffmpeg_ctx->pkt.size = 0; + /* allocate packet, set data to NULL, let the demuxer fill it */ + + ffmpeg_ctx->pkt = av_packet_alloc(); + if(ffmpeg_ctx->pkt == NULL) { + LV_LOG_ERROR("av_packet_alloc failed"); + return -1; + } + ffmpeg_ctx->pkt->data = NULL; + ffmpeg_ctx->pkt->size = 0; return 0; } @@ -825,20 +811,16 @@ static void lv_ffmpeg_player_frame_update_cb(lv_timer_t * timer) return; } -#if LV_COLOR_DEPTH != 32 - if(player->ffmpeg_ctx->has_alpha) { - convert_color_depth((uint8_t *)(player->imgdsc.data), - player->imgdsc.header.w * player->imgdsc.header.h); - } -#endif + lv_image_cache_drop(lv_image_get_src(obj)); - lv_img_cache_invalidate_src(lv_img_get_src(obj)); lv_obj_invalidate(obj); } static void lv_ffmpeg_player_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { + + LV_UNUSED(class_p); LV_TRACE_OBJ_CREATE("begin"); lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj; @@ -855,16 +837,18 @@ static void lv_ffmpeg_player_constructor(const lv_obj_class_t * class_p, static void lv_ffmpeg_player_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { + LV_UNUSED(class_p); + LV_TRACE_OBJ_CREATE("begin"); lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj; if(player->timer) { - lv_timer_del(player->timer); + lv_timer_delete(player->timer); player->timer = NULL; } - lv_img_cache_invalidate_src(lv_img_get_src(obj)); + lv_image_cache_drop(lv_image_get_src(obj)); ffmpeg_close(player->ffmpeg_ctx); player->ffmpeg_ctx = NULL; diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.h b/lib/libesp32_lvgl/lvgl/src/libs/ffmpeg/lv_ffmpeg.h similarity index 88% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.h rename to lib/libesp32_lvgl/lvgl/src/libs/ffmpeg/lv_ffmpeg.h index 8c7fc26b1..6c1730609 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.h +++ b/lib/libesp32_lvgl/lvgl/src/libs/ffmpeg/lv_ffmpeg.h @@ -24,12 +24,12 @@ extern "C" { **********************/ struct ffmpeg_context_s; -extern const lv_obj_class_t lv_ffmpeg_player_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_ffmpeg_player_class; typedef struct { - lv_img_t img; + lv_image_t img; lv_timer_t * timer; - lv_img_dsc_t imgdsc; + lv_image_dsc_t imgdsc; bool auto_restart; struct ffmpeg_context_s * ffmpeg_ctx; } lv_ffmpeg_player_t; @@ -69,9 +69,9 @@ lv_obj_t * lv_ffmpeg_player_create(lv_obj_t * parent); * Set the path of the file to be played * @param obj pointer to a ffmpeg_player object * @param path video file path - * @return LV_RES_OK: no error; LV_RES_INV: can't get the info. + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't get the info. */ -lv_res_t lv_ffmpeg_player_set_src(lv_obj_t * obj, const char * path); +lv_result_t lv_ffmpeg_player_set_src(lv_obj_t * obj, const char * path); /** * Set command control video player diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/arial.ttf b/lib/libesp32_lvgl/lvgl/src/libs/freetype/arial.ttf similarity index 100% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/arial.ttf rename to lib/libesp32_lvgl/lvgl/src/libs/freetype/arial.ttf diff --git a/lib/libesp32_lvgl/lvgl/src/libs/freetype/ftmodule.h b/lib/libesp32_lvgl/lvgl/src/libs/freetype/ftmodule.h new file mode 100644 index 000000000..b804b6e30 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/freetype/ftmodule.h @@ -0,0 +1,33 @@ +/* + * This file registers the FreeType modules compiled into the library. + * + * If you use GNU make, this file IS NOT USED! Instead, it is created in + * the objects directory (normally `/objs/`) based on information + * from `/modules.cfg`. + * + * Please read `docs/INSTALL.ANY` and `docs/CUSTOMIZE` how to compile + * FreeType without GNU make. + * + */ + +/* FT_USE_MODULE( FT_Module_Class, autofit_module_class ) */ +FT_USE_MODULE(FT_Driver_ClassRec, tt_driver_class) +/* FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class ) */ +/* FT_USE_MODULE( FT_Driver_ClassRec, cff_driver_class ) */ +/* FT_USE_MODULE( FT_Driver_ClassRec, t1cid_driver_class ) */ +/* FT_USE_MODULE( FT_Driver_ClassRec, pfr_driver_class ) */ +/* FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class ) */ +/* FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class ) */ +/* FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class ) */ +/* FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class ) */ +/* FT_USE_MODULE( FT_Module_Class, psaux_module_class ) */ +/* FT_USE_MODULE( FT_Module_Class, psnames_module_class ) */ +/* FT_USE_MODULE( FT_Module_Class, pshinter_module_class ) */ +FT_USE_MODULE(FT_Module_Class, sfnt_module_class) +FT_USE_MODULE(FT_Renderer_Class, ft_smooth_renderer_class) +/* FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class ) */ +/* FT_USE_MODULE( FT_Renderer_Class, ft_sdf_renderer_class ) */ +/* FT_USE_MODULE( FT_Renderer_Class, ft_bitmap_sdf_renderer_class ) */ +/* FT_USE_MODULE( FT_Renderer_Class, ft_svg_renderer_class ) */ + +/* EOF */ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/freetype/ftoption.h b/lib/libesp32_lvgl/lvgl/src/libs/freetype/ftoption.h new file mode 100644 index 000000000..141278b01 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/freetype/ftoption.h @@ -0,0 +1,964 @@ +/**************************************************************************** + * + * ftoption.h + * + * User-selectable configuration macros (specification only). + * + * Copyright (C) 1996-2022 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + +#ifndef FTOPTION_H_ +#define FTOPTION_H_ + +#include + +FT_BEGIN_HEADER + +/************************************************************************** + * + * USER-SELECTABLE CONFIGURATION MACROS + * + * This file contains the default configuration macro definitions for a + * standard build of the FreeType library. There are three ways to use + * this file to build project-specific versions of the library: + * + * - You can modify this file by hand, but this is not recommended in + * cases where you would like to build several versions of the library + * from a single source directory. + * + * - You can put a copy of this file in your build directory, more + * precisely in `$BUILD/freetype/config/ftoption.h`, where `$BUILD` is + * the name of a directory that is included _before_ the FreeType include + * path during compilation. + * + * The default FreeType Makefiles use the build directory + * `builds/` by default, but you can easily change that for your + * own projects. + * + * - Copy the file to `$BUILD/ft2build.h` and modify it + * slightly to pre-define the macro `FT_CONFIG_OPTIONS_H` used to locate + * this file during the build. For example, + * + * ``` + * #define FT_CONFIG_OPTIONS_H + * #include + * ``` + * + * will use `$BUILD/myftoptions.h` instead of this file for macro + * definitions. + * + * Note also that you can similarly pre-define the macro + * `FT_CONFIG_MODULES_H` used to locate the file listing of the modules + * that are statically linked to the library at compile time. By + * default, this file is ``. + * + * We highly recommend using the third method whenever possible. + * + */ + +/*************************************************************************/ +/*************************************************************************/ +/**** ****/ +/**** G E N E R A L F R E E T Y P E 2 C O N F I G U R A T I O N ****/ +/**** ****/ +/*************************************************************************/ +/*************************************************************************/ + +/*#************************************************************************ + * + * If you enable this configuration option, FreeType recognizes an + * environment variable called `FREETYPE_PROPERTIES`, which can be used to + * control the various font drivers and modules. The controllable + * properties are listed in the section @properties. + * + * You have to undefine this configuration option on platforms that lack + * the concept of environment variables (and thus don't have the `getenv` + * function), for example Windows CE. + * + * `FREETYPE_PROPERTIES` has the following syntax form (broken here into + * multiple lines for better readability). + * + * ``` + * + * ':' + * '=' + * + * ':' + * '=' + * ... + * ``` + * + * Example: + * + * ``` + * FREETYPE_PROPERTIES=truetype:interpreter-version=35 \ + * cff:no-stem-darkening=1 + * ``` + * + */ +#define FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES + +/************************************************************************** + * + * Uncomment the line below if you want to activate LCD rendering + * technology similar to ClearType in this build of the library. This + * technology triples the resolution in the direction color subpixels. To + * mitigate color fringes inherent to this technology, you also need to + * explicitly set up LCD filtering. + * + * When this macro is not defined, FreeType offers alternative LCD + * rendering technology that produces excellent output. + */ +/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ + +/************************************************************************** + * + * Many compilers provide a non-ANSI 64-bit data type that can be used by + * FreeType to speed up some computations. However, this will create some + * problems when compiling the library in strict ANSI mode. + * + * For this reason, the use of 64-bit integers is normally disabled when + * the `__STDC__` macro is defined. You can however disable this by + * defining the macro `FT_CONFIG_OPTION_FORCE_INT64` here. + * + * For most compilers, this will only create compilation warnings when + * building the library. + * + * ObNote: The compiler-specific 64-bit integers are detected in the + * file `ftconfig.h` either statically or through the `configure` + * script on supported platforms. + */ +#undef FT_CONFIG_OPTION_FORCE_INT64 + +/************************************************************************** + * + * If this macro is defined, do not try to use an assembler version of + * performance-critical functions (e.g., @FT_MulFix). You should only do + * that to verify that the assembler function works properly, or to execute + * benchmark tests of the various implementations. + */ +/* #define FT_CONFIG_OPTION_NO_ASSEMBLER */ + +/************************************************************************** + * + * If this macro is defined, try to use an inlined assembler version of the + * @FT_MulFix function, which is a 'hotspot' when loading and hinting + * glyphs, and which should be executed as fast as possible. + * + * Note that if your compiler or CPU is not supported, this will default to + * the standard and portable implementation found in `ftcalc.c`. + */ +#define FT_CONFIG_OPTION_INLINE_MULFIX + +/************************************************************************** + * + * LZW-compressed file support. + * + * FreeType now handles font files that have been compressed with the + * `compress` program. This is mostly used to parse many of the PCF + * files that come with various X11 distributions. The implementation + * uses NetBSD's `zopen` to partially uncompress the file on the fly (see + * `src/lzw/ftgzip.c`). + * + * Define this macro if you want to enable this 'feature'. + */ +#define FT_CONFIG_OPTION_USE_LZW + +/************************************************************************** + * + * Gzip-compressed file support. + * + * FreeType now handles font files that have been compressed with the + * `gzip` program. This is mostly used to parse many of the PCF files + * that come with XFree86. The implementation uses 'zlib' to partially + * uncompress the file on the fly (see `src/gzip/ftgzip.c`). + * + * Define this macro if you want to enable this 'feature'. See also the + * macro `FT_CONFIG_OPTION_SYSTEM_ZLIB` below. + */ +#define FT_CONFIG_OPTION_USE_ZLIB + +/************************************************************************** + * + * ZLib library selection + * + * This macro is only used when `FT_CONFIG_OPTION_USE_ZLIB` is defined. + * It allows FreeType's 'ftgzip' component to link to the system's + * installation of the ZLib library. This is useful on systems like + * Unix or VMS where it generally is already available. + * + * If you let it undefined, the component will use its own copy of the + * zlib sources instead. These have been modified to be included + * directly within the component and **not** export external function + * names. This allows you to link any program with FreeType _and_ ZLib + * without linking conflicts. + * + * Do not `#undef` this macro here since the build system might define + * it for certain configurations only. + * + * If you use a build system like cmake or the `configure` script, + * options set by those programs have precedence, overwriting the value + * here with the configured one. + * + * If you use the GNU make build system directly (that is, without the + * `configure` script) and you define this macro, you also have to pass + * `SYSTEM_ZLIB=yes` as an argument to make. + */ +/* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */ + +/************************************************************************** + * + * Bzip2-compressed file support. + * + * FreeType now handles font files that have been compressed with the + * `bzip2` program. This is mostly used to parse many of the PCF files + * that come with XFree86. The implementation uses `libbz2` to partially + * uncompress the file on the fly (see `src/bzip2/ftbzip2.c`). Contrary + * to gzip, bzip2 currently is not included and need to use the system + * available bzip2 implementation. + * + * Define this macro if you want to enable this 'feature'. + * + * If you use a build system like cmake or the `configure` script, + * options set by those programs have precedence, overwriting the value + * here with the configured one. + */ +/* #define FT_CONFIG_OPTION_USE_BZIP2 */ + +/************************************************************************** + * + * Define to disable the use of file stream functions and types, `FILE`, + * `fopen`, etc. Enables the use of smaller system libraries on embedded + * systems that have multiple system libraries, some with or without file + * stream support, in the cases where file stream support is not necessary + * such as memory loading of font files. + */ +/* #define FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */ + +/************************************************************************** + * + * PNG bitmap support. + * + * FreeType now handles loading color bitmap glyphs in the PNG format. + * This requires help from the external libpng library. Uncompressed + * color bitmaps do not need any external libraries and will be supported + * regardless of this configuration. + * + * Define this macro if you want to enable this 'feature'. + * + * If you use a build system like cmake or the `configure` script, + * options set by those programs have precedence, overwriting the value + * here with the configured one. + */ +/* #define FT_CONFIG_OPTION_USE_PNG */ + +/************************************************************************** + * + * HarfBuzz support. + * + * FreeType uses the HarfBuzz library to improve auto-hinting of OpenType + * fonts. If available, many glyphs not directly addressable by a font's + * character map will be hinted also. + * + * Define this macro if you want to enable this 'feature'. + * + * If you use a build system like cmake or the `configure` script, + * options set by those programs have precedence, overwriting the value + * here with the configured one. + */ +/* #define FT_CONFIG_OPTION_USE_HARFBUZZ */ + +/************************************************************************** + * + * Brotli support. + * + * FreeType uses the Brotli library to provide support for decompressing + * WOFF2 streams. + * + * Define this macro if you want to enable this 'feature'. + * + * If you use a build system like cmake or the `configure` script, + * options set by those programs have precedence, overwriting the value + * here with the configured one. + */ +/* #define FT_CONFIG_OPTION_USE_BROTLI */ + +/************************************************************************** + * + * Glyph Postscript Names handling + * + * By default, FreeType 2 is compiled with the 'psnames' module. This + * module is in charge of converting a glyph name string into a Unicode + * value, or return a Macintosh standard glyph name for the use with the + * TrueType 'post' table. + * + * Undefine this macro if you do not want 'psnames' compiled in your + * build of FreeType. This has the following effects: + * + * - The TrueType driver will provide its own set of glyph names, if you + * build it to support postscript names in the TrueType 'post' table, + * but will not synthesize a missing Unicode charmap. + * + * - The Type~1 driver will not be able to synthesize a Unicode charmap + * out of the glyphs found in the fonts. + * + * You would normally undefine this configuration macro when building a + * version of FreeType that doesn't contain a Type~1 or CFF driver. + */ +#define FT_CONFIG_OPTION_POSTSCRIPT_NAMES + +/************************************************************************** + * + * Postscript Names to Unicode Values support + * + * By default, FreeType~2 is built with the 'psnames' module compiled in. + * Among other things, the module is used to convert a glyph name into a + * Unicode value. This is especially useful in order to synthesize on + * the fly a Unicode charmap from the CFF/Type~1 driver through a big + * table named the 'Adobe Glyph List' (AGL). + * + * Undefine this macro if you do not want the Adobe Glyph List compiled + * in your 'psnames' module. The Type~1 driver will not be able to + * synthesize a Unicode charmap out of the glyphs found in the fonts. + */ +#define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + +/************************************************************************** + * + * Support for Mac fonts + * + * Define this macro if you want support for outline fonts in Mac format + * (mac dfont, mac resource, macbinary containing a mac resource) on + * non-Mac platforms. + * + * Note that the 'FOND' resource isn't checked. + */ +/* #define FT_CONFIG_OPTION_MAC_FONTS */ + +/************************************************************************** + * + * Guessing methods to access embedded resource forks + * + * Enable extra Mac fonts support on non-Mac platforms (e.g., GNU/Linux). + * + * Resource forks which include fonts data are stored sometimes in + * locations which users or developers don't expected. In some cases, + * resource forks start with some offset from the head of a file. In + * other cases, the actual resource fork is stored in file different from + * what the user specifies. If this option is activated, FreeType tries + * to guess whether such offsets or different file names must be used. + * + * Note that normal, direct access of resource forks is controlled via + * the `FT_CONFIG_OPTION_MAC_FONTS` option. + */ +#ifdef FT_CONFIG_OPTION_MAC_FONTS + #define FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK +#endif + +/************************************************************************** + * + * Allow the use of `FT_Incremental_Interface` to load typefaces that + * contain no glyph data, but supply it via a callback function. This is + * required by clients supporting document formats which supply font data + * incrementally as the document is parsed, such as the Ghostscript + * interpreter for the PostScript language. + */ +#define FT_CONFIG_OPTION_INCREMENTAL + +/************************************************************************** + * + * The size in bytes of the render pool used by the scan-line converter to + * do all of its work. + */ +#define FT_RENDER_POOL_SIZE 16384L + +/************************************************************************** + * + * FT_MAX_MODULES + * + * The maximum number of modules that can be registered in a single + * FreeType library object. 32~is the default. + */ +#define FT_MAX_MODULES 32 + +/************************************************************************** + * + * Debug level + * + * FreeType can be compiled in debug or trace mode. In debug mode, + * errors are reported through the 'ftdebug' component. In trace mode, + * additional messages are sent to the standard output during execution. + * + * Define `FT_DEBUG_LEVEL_ERROR` to build the library in debug mode. + * Define `FT_DEBUG_LEVEL_TRACE` to build it in trace mode. + * + * Don't define any of these macros to compile in 'release' mode! + * + * Do not `#undef` these macros here since the build system might define + * them for certain configurations only. + */ +/* #define FT_DEBUG_LEVEL_ERROR */ +/* #define FT_DEBUG_LEVEL_TRACE */ + +/************************************************************************** + * + * Logging + * + * Compiling FreeType in debug or trace mode makes FreeType write error + * and trace log messages to `stderr`. Enabling this macro + * automatically forces the `FT_DEBUG_LEVEL_ERROR` and + * `FT_DEBUG_LEVEL_TRACE` macros and allows FreeType to write error and + * trace log messages to a file instead of `stderr`. For writing logs + * to a file, FreeType uses an the external `dlg` library (the source + * code is in `src/dlg`). + * + * This option needs a C99 compiler. + */ +/* #define FT_DEBUG_LOGGING */ + +/************************************************************************** + * + * Autofitter debugging + * + * If `FT_DEBUG_AUTOFIT` is defined, FreeType provides some means to + * control the autofitter behaviour for debugging purposes with global + * boolean variables (consequently, you should **never** enable this + * while compiling in 'release' mode): + * + * ``` + * _af_debug_disable_horz_hints + * _af_debug_disable_vert_hints + * _af_debug_disable_blue_hints + * ``` + * + * Additionally, the following functions provide dumps of various + * internal autofit structures to stdout (using `printf`): + * + * ``` + * af_glyph_hints_dump_points + * af_glyph_hints_dump_segments + * af_glyph_hints_dump_edges + * af_glyph_hints_get_num_segments + * af_glyph_hints_get_segment_offset + * ``` + * + * As an argument, they use another global variable: + * + * ``` + * _af_debug_hints + * ``` + * + * Please have a look at the `ftgrid` demo program to see how those + * variables and macros should be used. + * + * Do not `#undef` these macros here since the build system might define + * them for certain configurations only. + */ +/* #define FT_DEBUG_AUTOFIT */ + +/************************************************************************** + * + * Memory Debugging + * + * FreeType now comes with an integrated memory debugger that is capable + * of detecting simple errors like memory leaks or double deletes. To + * compile it within your build of the library, you should define + * `FT_DEBUG_MEMORY` here. + * + * Note that the memory debugger is only activated at runtime when when + * the _environment_ variable `FT2_DEBUG_MEMORY` is defined also! + * + * Do not `#undef` this macro here since the build system might define it + * for certain configurations only. + */ +/* #define FT_DEBUG_MEMORY */ + +/************************************************************************** + * + * Module errors + * + * If this macro is set (which is _not_ the default), the higher byte of + * an error code gives the module in which the error has occurred, while + * the lower byte is the real error code. + * + * Setting this macro makes sense for debugging purposes only, since it + * would break source compatibility of certain programs that use + * FreeType~2. + * + * More details can be found in the files `ftmoderr.h` and `fterrors.h`. + */ +#undef FT_CONFIG_OPTION_USE_MODULE_ERRORS + +/************************************************************************** + * + * OpenType SVG Glyph Support + * + * Setting this macro enables support for OpenType SVG glyphs. By + * default, FreeType can only fetch SVG documents. However, it can also + * render them if external rendering hook functions are plugged in at + * runtime. + * + * More details on the hooks can be found in file `otsvg.h`. + */ +#define FT_CONFIG_OPTION_SVG + +/************************************************************************** + * + * Error Strings + * + * If this macro is set, `FT_Error_String` will return meaningful + * descriptions. This is not enabled by default to reduce the overall + * size of FreeType. + * + * More details can be found in the file `fterrors.h`. + */ +#define FT_CONFIG_OPTION_ERROR_STRINGS + +/*************************************************************************/ +/*************************************************************************/ +/**** ****/ +/**** S F N T D R I V E R C O N F I G U R A T I O N ****/ +/**** ****/ +/*************************************************************************/ +/*************************************************************************/ + +/************************************************************************** + * + * Define `TT_CONFIG_OPTION_EMBEDDED_BITMAPS` if you want to support + * embedded bitmaps in all formats using the 'sfnt' module (namely + * TrueType~& OpenType). + */ +#define TT_CONFIG_OPTION_EMBEDDED_BITMAPS + +/************************************************************************** + * + * Define `TT_CONFIG_OPTION_COLOR_LAYERS` if you want to support colored + * outlines (from the 'COLR'/'CPAL' tables) in all formats using the 'sfnt' + * module (namely TrueType~& OpenType). + */ +#define TT_CONFIG_OPTION_COLOR_LAYERS + +/************************************************************************** + * + * Define `TT_CONFIG_OPTION_POSTSCRIPT_NAMES` if you want to be able to + * load and enumerate the glyph Postscript names in a TrueType or OpenType + * file. + * + * Note that when you do not compile the 'psnames' module by undefining the + * above `FT_CONFIG_OPTION_POSTSCRIPT_NAMES`, the 'sfnt' module will + * contain additional code used to read the PS Names table from a font. + * + * (By default, the module uses 'psnames' to extract glyph names.) + */ +#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES + +/************************************************************************** + * + * Define `TT_CONFIG_OPTION_SFNT_NAMES` if your applications need to access + * the internal name table in a SFNT-based format like TrueType or + * OpenType. The name table contains various strings used to describe the + * font, like family name, copyright, version, etc. It does not contain + * any glyph name though. + * + * Accessing SFNT names is done through the functions declared in + * `ftsnames.h`. + */ +#define TT_CONFIG_OPTION_SFNT_NAMES + +/************************************************************************** + * + * TrueType CMap support + * + * Here you can fine-tune which TrueType CMap table format shall be + * supported. + */ +#define TT_CONFIG_CMAP_FORMAT_0 +#define TT_CONFIG_CMAP_FORMAT_2 +#define TT_CONFIG_CMAP_FORMAT_4 +#define TT_CONFIG_CMAP_FORMAT_6 +#define TT_CONFIG_CMAP_FORMAT_8 +#define TT_CONFIG_CMAP_FORMAT_10 +#define TT_CONFIG_CMAP_FORMAT_12 +#define TT_CONFIG_CMAP_FORMAT_13 +#define TT_CONFIG_CMAP_FORMAT_14 + +/*************************************************************************/ +/*************************************************************************/ +/**** ****/ +/**** T R U E T Y P E D R I V E R C O N F I G U R A T I O N ****/ +/**** ****/ +/*************************************************************************/ +/*************************************************************************/ + +/************************************************************************** + * + * Define `TT_CONFIG_OPTION_BYTECODE_INTERPRETER` if you want to compile a + * bytecode interpreter in the TrueType driver. + * + * By undefining this, you will only compile the code necessary to load + * TrueType glyphs without hinting. + * + * Do not `#undef` this macro here, since the build system might define it + * for certain configurations only. + */ +#define TT_CONFIG_OPTION_BYTECODE_INTERPRETER + +/************************************************************************** + * + * Define `TT_CONFIG_OPTION_SUBPIXEL_HINTING` if you want to compile + * subpixel hinting support into the TrueType driver. This modifies the + * TrueType hinting mechanism when anything but `FT_RENDER_MODE_MONO` is + * requested. + * + * In particular, it modifies the bytecode interpreter to interpret (or + * not) instructions in a certain way so that all TrueType fonts look like + * they do in a Windows ClearType (DirectWrite) environment. See [1] for a + * technical overview on what this means. See `ttinterp.h` for more + * details on the LEAN option. + * + * There are three possible values. + * + * Value 1: + * This value is associated with the 'Infinality' moniker, contributed by + * an individual nicknamed Infinality with the goal of making TrueType + * fonts render better than on Windows. A high amount of configurability + * and flexibility, down to rules for single glyphs in fonts, but also + * very slow. Its experimental and slow nature and the original + * developer losing interest meant that this option was never enabled in + * default builds. + * + * The corresponding interpreter version is v38. + * + * Value 2: + * The new default mode for the TrueType driver. The Infinality code + * base was stripped to the bare minimum and all configurability removed + * in the name of speed and simplicity. The configurability was mainly + * aimed at legacy fonts like 'Arial', 'Times New Roman', or 'Courier'. + * Legacy fonts are fonts that modify vertical stems to achieve clean + * black-and-white bitmaps. The new mode focuses on applying a minimal + * set of rules to all fonts indiscriminately so that modern and web + * fonts render well while legacy fonts render okay. + * + * The corresponding interpreter version is v40. + * + * Value 3: + * Compile both, making both v38 and v40 available (the latter is the + * default). + * + * By undefining these, you get rendering behavior like on Windows without + * ClearType, i.e., Windows XP without ClearType enabled and Win9x + * (interpreter version v35). Or not, depending on how much hinting blood + * and testing tears the font designer put into a given font. If you + * define one or both subpixel hinting options, you can switch between + * between v35 and the ones you define (using `FT_Property_Set`). + * + * This option requires `TT_CONFIG_OPTION_BYTECODE_INTERPRETER` to be + * defined. + * + * [1] + * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx + */ +/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */ +#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2 +/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING ( 1 | 2 ) */ + +/************************************************************************** + * + * Define `TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED` to compile the + * TrueType glyph loader to use Apple's definition of how to handle + * component offsets in composite glyphs. + * + * Apple and MS disagree on the default behavior of component offsets in + * composites. Apple says that they should be scaled by the scaling + * factors in the transformation matrix (roughly, it's more complex) while + * MS says they should not. OpenType defines two bits in the composite + * flags array which can be used to disambiguate, but old fonts will not + * have them. + * + * https://www.microsoft.com/typography/otspec/glyf.htm + * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6glyf.html + */ +#undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED + +/************************************************************************** + * + * Define `TT_CONFIG_OPTION_GX_VAR_SUPPORT` if you want to include support + * for Apple's distortable font technology ('fvar', 'gvar', 'cvar', and + * 'avar' tables). Tagged 'Font Variations', this is now part of OpenType + * also. This has many similarities to Type~1 Multiple Masters support. + */ +#define TT_CONFIG_OPTION_GX_VAR_SUPPORT + +/************************************************************************** + * + * Define `TT_CONFIG_OPTION_BDF` if you want to include support for an + * embedded 'BDF~' table within SFNT-based bitmap formats. + */ +#define TT_CONFIG_OPTION_BDF + +/************************************************************************** + * + * Option `TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES` controls the maximum + * number of bytecode instructions executed for a single run of the + * bytecode interpreter, needed to prevent infinite loops. You don't want + * to change this except for very special situations (e.g., making a + * library fuzzer spend less time to handle broken fonts). + * + * It is not expected that this value is ever modified by a configuring + * script; instead, it gets surrounded with `#ifndef ... #endif` so that + * the value can be set as a preprocessor option on the compiler's command + * line. + */ +#ifndef TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES + #define TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES 1000000L +#endif + +/*************************************************************************/ +/*************************************************************************/ +/**** ****/ +/**** T Y P E 1 D R I V E R C O N F I G U R A T I O N ****/ +/**** ****/ +/*************************************************************************/ +/*************************************************************************/ + +/************************************************************************** + * + * `T1_MAX_DICT_DEPTH` is the maximum depth of nest dictionaries and arrays + * in the Type~1 stream (see `t1load.c`). A minimum of~4 is required. + */ +#define T1_MAX_DICT_DEPTH 5 + +/************************************************************************** + * + * `T1_MAX_SUBRS_CALLS` details the maximum number of nested sub-routine + * calls during glyph loading. + */ +#define T1_MAX_SUBRS_CALLS 16 + +/************************************************************************** + * + * `T1_MAX_CHARSTRING_OPERANDS` is the charstring stack's capacity. A + * minimum of~16 is required. + * + * The Chinese font 'MingTiEG-Medium' (covering the CNS 11643 character + * set) needs 256. + */ +#define T1_MAX_CHARSTRINGS_OPERANDS 256 + +/************************************************************************** + * + * Define this configuration macro if you want to prevent the compilation + * of the 't1afm' module, which is in charge of reading Type~1 AFM files + * into an existing face. Note that if set, the Type~1 driver will be + * unable to produce kerning distances. + */ +#undef T1_CONFIG_OPTION_NO_AFM + +/************************************************************************** + * + * Define this configuration macro if you want to prevent the compilation + * of the Multiple Masters font support in the Type~1 driver. + */ +#undef T1_CONFIG_OPTION_NO_MM_SUPPORT + +/************************************************************************** + * + * `T1_CONFIG_OPTION_OLD_ENGINE` controls whether the pre-Adobe Type~1 + * engine gets compiled into FreeType. If defined, it is possible to + * switch between the two engines using the `hinting-engine` property of + * the 'type1' driver module. + */ +/* #define T1_CONFIG_OPTION_OLD_ENGINE */ + +/*************************************************************************/ +/*************************************************************************/ +/**** ****/ +/**** C F F D R I V E R C O N F I G U R A T I O N ****/ +/**** ****/ +/*************************************************************************/ +/*************************************************************************/ + +/************************************************************************** + * + * Using `CFF_CONFIG_OPTION_DARKENING_PARAMETER_{X,Y}{1,2,3,4}` it is + * possible to set up the default values of the four control points that + * define the stem darkening behaviour of the (new) CFF engine. For more + * details please read the documentation of the `darkening-parameters` + * property (file `ftdriver.h`), which allows the control at run-time. + * + * Do **not** undefine these macros! + */ +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 500 +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 400 + +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 1000 +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 275 + +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 1667 +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 275 + +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 2333 +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 0 + +/************************************************************************** + * + * `CFF_CONFIG_OPTION_OLD_ENGINE` controls whether the pre-Adobe CFF engine + * gets compiled into FreeType. If defined, it is possible to switch + * between the two engines using the `hinting-engine` property of the 'cff' + * driver module. + */ +/* #define CFF_CONFIG_OPTION_OLD_ENGINE */ + +/*************************************************************************/ +/*************************************************************************/ +/**** ****/ +/**** P C F D R I V E R C O N F I G U R A T I O N ****/ +/**** ****/ +/*************************************************************************/ +/*************************************************************************/ + +/************************************************************************** + * + * There are many PCF fonts just called 'Fixed' which look completely + * different, and which have nothing to do with each other. When selecting + * 'Fixed' in KDE or Gnome one gets results that appear rather random, the + * style changes often if one changes the size and one cannot select some + * fonts at all. This option makes the 'pcf' module prepend the foundry + * name (plus a space) to the family name. + * + * We also check whether we have 'wide' characters; all put together, we + * get family names like 'Sony Fixed' or 'Misc Fixed Wide'. + * + * If this option is activated, it can be controlled with the + * `no-long-family-names` property of the 'pcf' driver module. + */ +/* #define PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + +/*************************************************************************/ +/*************************************************************************/ +/**** ****/ +/**** A U T O F I T M O D U L E C O N F I G U R A T I O N ****/ +/**** ****/ +/*************************************************************************/ +/*************************************************************************/ + +/************************************************************************** + * + * Compile 'autofit' module with CJK (Chinese, Japanese, Korean) script + * support. + */ +#define AF_CONFIG_OPTION_CJK + +/************************************************************************** + * + * Compile 'autofit' module with fallback Indic script support, covering + * some scripts that the 'latin' submodule of the 'autofit' module doesn't + * (yet) handle. Currently, this needs option `AF_CONFIG_OPTION_CJK`. + */ +#ifdef AF_CONFIG_OPTION_CJK + #define AF_CONFIG_OPTION_INDIC +#endif + +/************************************************************************** + * + * Use TrueType-like size metrics for 'light' auto-hinting. + * + * It is strongly recommended to avoid this option, which exists only to + * help some legacy applications retain its appearance and behaviour with + * respect to auto-hinted TrueType fonts. + * + * The very reason this option exists at all are GNU/Linux distributions + * like Fedora that did not un-patch the following change (which was + * present in FreeType between versions 2.4.6 and 2.7.1, inclusive). + * + * ``` + * 2011-07-16 Steven Chu + * + * [truetype] Fix metrics on size request for scalable fonts. + * ``` + * + * This problematic commit is now reverted (more or less). + */ +/* #define AF_CONFIG_OPTION_TT_SIZE_METRICS */ + +/* */ + +/* + * This macro is obsolete. Support has been removed in FreeType version + * 2.5. + */ +/* #define FT_CONFIG_OPTION_OLD_INTERNALS */ + +/* + * The next three macros are defined if native TrueType hinting is + * requested by the definitions above. Don't change this. + */ +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + #define TT_USE_BYTECODE_INTERPRETER + + #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + #if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 1 + #define TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + #endif + + #if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 2 + #define TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + #endif + #endif +#endif + +/* + * The TT_SUPPORT_COLRV1 macro is defined to indicate to clients that this + * version of FreeType has support for 'COLR' v1 API. This definition is + * useful to FreeType clients that want to build in support for 'COLR' v1 + * depending on a tip-of-tree checkout before it is officially released in + * FreeType, and while the feature cannot yet be tested against using + * version macros. Don't change this macro. This may be removed once the + * feature is in a FreeType release version and version macros can be used + * to test for availability. + */ +#ifdef TT_CONFIG_OPTION_COLOR_LAYERS + #define TT_SUPPORT_COLRV1 +#endif + +/* + * Check CFF darkening parameters. The checks are the same as in function + * `cff_property_set` in file `cffdrivr.c`. + */ +#if CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 < 0 || \ + \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 < 0 || \ + \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 > \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 > \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 > \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 || \ + \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 > 500 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 > 500 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 > 500 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 > 500 + #error "Invalid CFF darkening parameters!" +#endif + +FT_END_HEADER + +#endif /* FTOPTION_H_ */ + +/* END */ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype.c b/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype.c new file mode 100755 index 000000000..7fbe8a16c --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype.c @@ -0,0 +1,453 @@ +/** + * @file lv_freetype.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_freetype.h" + +#if LV_USE_FREETYPE + +#include "lv_freetype_private.h" +#include "../../core/lv_global.h" + +/********************* + * DEFINES + *********************/ + +#define ft_ctx LV_GLOBAL_DEFAULT()->ft_context +#define LV_FREETYPE_OUTLINE_REF_SIZE_DEF 128 + +#if LV_FREETYPE_CACHE_FT_GLYPH_CNT <= 0 + #error "LV_FREETYPE_CACHE_FT_GLYPH_CNT must be greater than 0" +#endif + +/********************** + * TYPEDEFS + **********************/ + +/* Use the pointer storing pathname as the unique request ID of the face */ +typedef struct { + char * pathname; + int ref_cnt; +} face_id_node_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static FT_Error lv_freetype_face_requester(FTC_FaceID face_id, + FT_Library library, + FT_Pointer req_data, + FT_Face * aface); +static void lv_freetype_cleanup(lv_freetype_context_t * ctx); +static FTC_FaceID lv_freetype_req_face_id(lv_freetype_context_t * ctx, const char * pathname); +static void lv_freetype_drop_face_id(lv_freetype_context_t * ctx, FTC_FaceID face_id); +static bool freetype_on_font_create(lv_freetype_font_dsc_t * dsc); +static void freetype_on_font_set_cbs(lv_freetype_font_dsc_t * dsc); + +static bool cache_node_cache_create_cb(lv_freetype_cache_node_t * node, void * user_data); +static void cache_node_cache_free_cb(lv_freetype_cache_node_t * node, void * user_data); +static lv_cache_compare_res_t cache_node_cache_compare_cb(const lv_freetype_cache_node_t * lhs, + const lv_freetype_cache_node_t * rhs); +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_result_t lv_freetype_init(uint32_t max_faces, uint32_t max_sizes, uint32_t max_kilobytes) +{ + if(ft_ctx) { + LV_LOG_WARN("freetype already initialized"); + return LV_RESULT_INVALID; + } + + ft_ctx = lv_malloc_zeroed(sizeof(lv_freetype_context_t)); + LV_ASSERT_MALLOC(ft_ctx); + if(!ft_ctx) { + LV_LOG_ERROR("malloc failed for lv_freetype_context_t"); + return LV_RESULT_INVALID; + } + + lv_freetype_context_t * ctx = lv_freetype_get_context(); + FT_Error error; + + error = FT_Init_FreeType(&ctx->library); + if(error) { + FT_ERROR_MSG("FT_Init_FreeType", error); + return LV_RESULT_INVALID; + } + + error = FTC_Manager_New(ctx->library, + max_faces, + max_sizes, + max_kilobytes * 1024, + lv_freetype_face_requester, + NULL, + &ctx->cache_manager); + if(error) { + FT_ERROR_MSG("FTC_Manager_New", error); + lv_freetype_cleanup(ctx); + return LV_RESULT_INVALID; + } + + error = FTC_CMapCache_New(ctx->cache_manager, &ctx->cmap_cache); + if(error) { + FT_ERROR_MSG("FTC_CMapCache_New", error); + lv_freetype_cleanup(ctx); + return LV_RESULT_INVALID; + } + + _lv_ll_init(&ctx->face_id_ll, sizeof(face_id_node_t)); + + lv_cache_ops_t ops = { + .compare_cb = (lv_cache_compare_cb_t)cache_node_cache_compare_cb, + .create_cb = (lv_cache_create_cb_t)cache_node_cache_create_cb, + .free_cb = (lv_cache_free_cb_t)cache_node_cache_free_cb, + }; + ctx->cache_node_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(lv_freetype_cache_node_t), INT32_MAX, ops); + + return LV_RESULT_OK; +} + +void lv_freetype_uninit(void) +{ + lv_freetype_context_t * ctx = lv_freetype_get_context(); + lv_freetype_cleanup(ctx); + + lv_free(ft_ctx); + ft_ctx = NULL; +} + +lv_font_t * lv_freetype_font_create(const char * pathname, lv_freetype_font_render_mode_t render_mode, uint32_t size, + lv_freetype_font_style_t style) +{ + LV_ASSERT_NULL(pathname); + LV_ASSERT(size > 0); + + size_t pathname_len = lv_strlen(pathname); + LV_ASSERT(pathname_len > 0); + + lv_freetype_context_t * ctx = lv_freetype_get_context(); + + lv_freetype_cache_node_t search_key = { + .pathname = lv_freetype_req_face_id(ctx, pathname), + .style = style, + .render_mode = render_mode, + }; + + bool cache_hitting = true; + lv_cache_entry_t * cache_node_entry = lv_cache_acquire(ctx->cache_node_cache, &search_key, NULL); + if(cache_node_entry == NULL) { + cache_hitting = false; + cache_node_entry = lv_cache_acquire_or_create(ctx->cache_node_cache, &search_key, NULL); + if(cache_node_entry == NULL) { + lv_freetype_drop_face_id(ctx, (FTC_FaceID)search_key.pathname); + LV_LOG_ERROR("cache node creating failed"); + return NULL; + } + } + + lv_freetype_font_dsc_t * dsc = lv_malloc_zeroed(sizeof(lv_freetype_font_dsc_t)); + LV_ASSERT_MALLOC(dsc); + + dsc->face_id = (FTC_FaceID)search_key.pathname; + dsc->render_mode = render_mode; + dsc->context = ctx; + dsc->size = size; + dsc->style = style; + dsc->magic_num = LV_FREETYPE_FONT_DSC_MAGIC_NUM; + dsc->cache_node = lv_cache_entry_get_data(cache_node_entry); + dsc->cache_node_entry = cache_node_entry; + + if(cache_hitting == false && freetype_on_font_create(dsc) == false) { + lv_cache_release(ctx->cache_node_cache, dsc->cache_node_entry, NULL); + lv_freetype_drop_face_id(ctx, dsc->face_id); + lv_free(dsc); + return NULL; + } + freetype_on_font_set_cbs(dsc); + + FT_Face face = dsc->cache_node->face; + FT_Set_Pixel_Sizes(face, 0, size); + + lv_font_t * font = &dsc->font; + font->dsc = dsc; + font->subpx = LV_FONT_SUBPX_NONE; + font->line_height = FT_F26DOT6_TO_INT(face->size->metrics.height); + font->base_line = -FT_F26DOT6_TO_INT(face->size->metrics.descender); + + FT_Fixed scale = face->size->metrics.y_scale; + int8_t thickness = FT_F26DOT6_TO_INT(FT_MulFix(scale, face->underline_thickness)); + font->underline_position = FT_F26DOT6_TO_INT(FT_MulFix(scale, face->underline_position)); + font->underline_thickness = thickness < 1 ? 1 : thickness; + + return font; +} + +void lv_freetype_font_delete(lv_font_t * font) +{ + LV_ASSERT_NULL(font); + lv_freetype_context_t * ctx = lv_freetype_get_context(); + lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)(font->dsc); + LV_ASSERT_NULL(dsc); + LV_ASSERT_FREETYPE_FONT_DSC(dsc); + + lv_cache_release(ctx->cache_node_cache, dsc->cache_node_entry, NULL); + if(lv_cache_entry_get_ref(dsc->cache_node_entry) == 0) { + lv_cache_drop(ctx->cache_node_cache, dsc->cache_node, NULL); + } + + lv_freetype_drop_face_id(dsc->context, dsc->face_id); + + /* invalidate magic number */ + lv_memzero(dsc, sizeof(lv_freetype_font_dsc_t)); + lv_free(dsc); +} + +lv_freetype_context_t * lv_freetype_get_context(void) +{ + return LV_GLOBAL_DEFAULT()->ft_context; +} + +FT_Size lv_freetype_lookup_size(const lv_freetype_font_dsc_t * dsc) +{ + FT_Error error; + lv_freetype_context_t * ctx = dsc->context; + + FT_Size ft_size; + struct FTC_ScalerRec_ scaler; + scaler.face_id = dsc->face_id; + scaler.width = dsc->size; + scaler.height = dsc->size; + scaler.pixel = 1; + error = FTC_Manager_LookupSize(ctx->cache_manager, &scaler, &ft_size); + + if(error) { + FT_ERROR_MSG("FTC_Manager_LookupSize", error); + return NULL; + } + + return ft_size; +} + +void lv_freetype_italic_transform(FT_Face face) +{ + LV_ASSERT_NULL(face); + FT_Matrix matrix; + matrix.xx = FT_INT_TO_F16DOT16(1); + matrix.xy = 0x5800; + matrix.yx = 0; + matrix.yy = FT_INT_TO_F16DOT16(1); + FT_Set_Transform(face, &matrix, NULL); +} + +const char * lv_freetype_get_pathname(FTC_FaceID face_id) +{ + LV_ASSERT_NULL(face_id); + return (const char *)face_id; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static bool freetype_on_font_create(lv_freetype_font_dsc_t * dsc) +{ + lv_cache_t * glyph_cache = lv_freetype_create_glyph_cache(); + if(glyph_cache == NULL) { + LV_LOG_ERROR("glyph cache creating failed"); + return false; + } + dsc->cache_node->glyph_cache = glyph_cache; + + lv_cache_t * draw_data_cache = NULL; + if(dsc->render_mode == LV_FREETYPE_FONT_RENDER_MODE_BITMAP) { + draw_data_cache = lv_freetype_create_draw_data_image(); + } + else if(dsc->render_mode == LV_FREETYPE_FONT_RENDER_MODE_OUTLINE) { + draw_data_cache = lv_freetype_create_draw_data_outline(); + } + else { + LV_LOG_ERROR("unknown render mode"); + return false; + } + + if(draw_data_cache == NULL) { + LV_LOG_ERROR("draw data cache creating failed"); + return false; + } + + dsc->cache_node->draw_data_cache = draw_data_cache; + + return true; +} + +static void freetype_on_font_set_cbs(lv_freetype_font_dsc_t * dsc) +{ + lv_freetype_set_cbs_glyph(dsc); + if(dsc->render_mode == LV_FREETYPE_FONT_RENDER_MODE_BITMAP) { + lv_freetype_set_cbs_image_font(dsc); + } + else if(dsc->render_mode == LV_FREETYPE_FONT_RENDER_MODE_OUTLINE) { + lv_freetype_set_cbs_outline_font(dsc); + } +} + +static FT_Error lv_freetype_face_requester(FTC_FaceID face_id, + FT_Library library, + FT_Pointer req_data, + FT_Face * aface) +{ + LV_UNUSED(library); + LV_UNUSED(req_data); + + const char * pathname = lv_freetype_get_pathname(face_id); + + FT_Error error = FT_New_Face(library, pathname, 0, aface); + if(error) { + FT_ERROR_MSG("FT_New_Face", error); + LV_LOG_ERROR("error pathname = %s", pathname); + } + return error; +} + +static void lv_freetype_cleanup(lv_freetype_context_t * ctx) +{ + LV_ASSERT_NULL(ctx); + if(ctx->cache_node_cache) { + lv_cache_destroy(ctx->cache_node_cache, NULL); + ctx->cache_node_cache = NULL; + } + + if(ctx->cache_manager) { + FTC_Manager_Done(ctx->cache_manager); + ctx->cache_manager = NULL; + } + + if(ctx->library) { + FT_Done_FreeType(ctx->library); + ctx->library = NULL; + } +} + +static FTC_FaceID lv_freetype_req_face_id(lv_freetype_context_t * ctx, const char * pathname) +{ + size_t len = lv_strlen(pathname); + LV_ASSERT(len > 0); + + lv_ll_t * ll_p = &ctx->face_id_ll; + face_id_node_t * node; + + /* search cache */ + _LV_LL_READ(ll_p, node) { + if(strcmp(node->pathname, pathname) == 0) { + node->ref_cnt++; + LV_LOG_INFO("reuse face_id: %s, ref_cnt = %d", node->pathname, node->ref_cnt); + return node->pathname; + } + } + + /* insert new cache */ + node = _lv_ll_ins_tail(ll_p); + LV_ASSERT_MALLOC(node); + + node->pathname = lv_malloc(len + 1); + LV_ASSERT_MALLOC(node->pathname); + strcpy(node->pathname, pathname); + + LV_LOG_INFO("add face_id: %s", node->pathname); + + node->ref_cnt = 1; + return node->pathname; +} + +static void lv_freetype_drop_face_id(lv_freetype_context_t * ctx, FTC_FaceID face_id) +{ + lv_ll_t * ll_p = &ctx->face_id_ll; + face_id_node_t * node; + _LV_LL_READ(ll_p, node) { + if(face_id == node->pathname) { + LV_LOG_INFO("found face_id: %s, ref_cnt = %d", node->pathname, node->ref_cnt); + node->ref_cnt--; + if(node->ref_cnt == 0) { + LV_LOG_INFO("drop face_id: %s", node->pathname); + _lv_ll_remove(ll_p, node); + FTC_Manager_RemoveFaceID(ctx->cache_manager, face_id); + lv_free(node->pathname); + lv_free(node); + } + return; + } + } + + LV_ASSERT_MSG(false, "face_id not found"); +} + +/*----------------- + * Cache Node Cache Callbacks + *----------------*/ + +static bool cache_node_cache_create_cb(lv_freetype_cache_node_t * node, void * user_data) +{ + LV_UNUSED(user_data); + lv_freetype_context_t * ctx = lv_freetype_get_context(); + + /* Cache miss, load face */ + FT_Face face; + FT_Error error = FT_New_Face(ctx->library, node->pathname, 0, &face); + if(error) { + FT_ERROR_MSG("FT_New_Face", error); + return false; + } + + node->ref_size = LV_FREETYPE_OUTLINE_REF_SIZE_DEF; + + if(node->style & LV_FREETYPE_FONT_STYLE_ITALIC) { + lv_freetype_italic_transform(face); + } + + node->face = face; + + return true; +} +static void cache_node_cache_free_cb(lv_freetype_cache_node_t * node, void * user_data) +{ + FT_Done_Face(node->face); + + if(node->glyph_cache) { + lv_cache_destroy(node->glyph_cache, user_data); + node->glyph_cache = NULL; + } + if(node->draw_data_cache) { + lv_cache_destroy(node->draw_data_cache, user_data); + node->draw_data_cache = NULL; + } +} +static lv_cache_compare_res_t cache_node_cache_compare_cb(const lv_freetype_cache_node_t * lhs, + const lv_freetype_cache_node_t * rhs) +{ + if(lhs->render_mode != rhs->render_mode) { + return lhs->render_mode > rhs->render_mode ? 1 : -1; + } + if(lhs->style != rhs->style) { + return lhs->style > rhs->style ? 1 : -1; + } + + int32_t cmp_res = lv_strcmp(lhs->pathname, rhs->pathname); + if(cmp_res != 0) { + return cmp_res > 0 ? 1 : -1; + } + + return 0; +} + +#endif /*LV_USE_FREETYPE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype.h b/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype.h new file mode 100755 index 000000000..eed28a37e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype.h @@ -0,0 +1,144 @@ +/** + * @file lv_freetype.h + * + */ +#ifndef LV_FREETYPE_H +#define LV_FREETYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_FREETYPE + +/********************* + * DEFINES + *********************/ + +#define LV_FREETYPE_F26DOT6_TO_INT(x) ((x) >> 6) +#define LV_FREETYPE_F26DOT6_TO_FLOAT(x) ((float)(x) / 64) + +#define FT_FONT_STYLE_NORMAL LV_FREETYPE_FONT_STYLE_NORMAL +#define FT_FONT_STYLE_ITALIC LV_FREETYPE_FONT_STYLE_ITALIC +#define FT_FONT_STYLE_BOLD LV_FREETYPE_FONT_STYLE_BOLD + +/********************** + * TYPEDEFS + **********************/ + +enum { + LV_FREETYPE_FONT_STYLE_NORMAL = 0, + LV_FREETYPE_FONT_STYLE_ITALIC = 1 << 0, + LV_FREETYPE_FONT_STYLE_BOLD = 1 << 1, +}; + +typedef uint16_t lv_freetype_font_style_t; +typedef lv_freetype_font_style_t LV_FT_FONT_STYLE; + +enum { + LV_FREETYPE_FONT_RENDER_MODE_BITMAP = 0, + LV_FREETYPE_FONT_RENDER_MODE_OUTLINE = 1, +}; + +typedef uint16_t lv_freetype_font_render_mode_t; + +typedef void * lv_freetype_outline_t; + +typedef enum { + LV_FREETYPE_OUTLINE_END, + LV_FREETYPE_OUTLINE_MOVE_TO, + LV_FREETYPE_OUTLINE_LINE_TO, + LV_FREETYPE_OUTLINE_CUBIC_TO, + LV_FREETYPE_OUTLINE_CONIC_TO, +} lv_freetype_outline_type_t; + +typedef struct { + int32_t x; + int32_t y; +} lv_freetype_outline_vector_t; + +typedef struct { + lv_freetype_outline_t outline; + lv_freetype_outline_type_t type; + lv_freetype_outline_vector_t to; + lv_freetype_outline_vector_t control1; + lv_freetype_outline_vector_t control2; +} lv_freetype_outline_event_param_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize the freetype library. + * @param max_faces Maximum number of opened FT_Face objects managed by this cache instance. Use 0 for defaults. + * @param max_sizes Maximum number of opened FT_Size objects managed by this cache instance. Use 0 for defaults. + * @param max_kilobytes Maximum number of kilobytes to use for cached data nodes. Use 0 for defaults. + * Note that this value does not account for managed FT_Face and FT_Size objects. + * @return LV_RESULT_OK on success, otherwise LV_RESULT_INVALID. + */ +lv_result_t lv_freetype_init(uint32_t max_faces, uint32_t max_sizes, uint32_t max_kilobytes); + +/** + * Uninitialize the freetype library + */ +void lv_freetype_uninit(void); + +/** + * Create a freetype font. + * @param pathname font file path. + * @param render_mode font render mode(see @lv_freetype_font_render_mode_t for details). + * @param size font size. + * @param style font style(see lv_freetype_font_style_t for details). + * @return Created font, or NULL on failure. + */ +lv_font_t * lv_freetype_font_create(const char * pathname, lv_freetype_font_render_mode_t render_mode, uint32_t size, + lv_freetype_font_style_t style); + +/** + * Delete a freetype font. + * @param font freetype font to be deleted. + */ +void lv_freetype_font_delete(lv_font_t * font); + +/** + * Register a callback function to generate outlines for FreeType fonts. + * + * @param cb The callback function to be registered. + * @param user_data User data to be passed to the callback function. + * @return The ID of the registered callback function, or a negative value on failure. + */ +void lv_freetype_outline_add_event(lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data); + +/** + * Get the scale of a FreeType font. + * + * @param font The FreeType font to get the scale of. + * @return The scale of the FreeType font. + */ +uint32_t lv_freetype_outline_get_scale(const lv_font_t * font); + +/** + * Check if the font is an outline font. + * + * @param font The FreeType font. + * @return Is outline font on success, otherwise false. + */ +bool lv_freetype_is_outline_font(const lv_font_t * font); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_FREETYPE*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV_FREETYPE_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_glyph.c b/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_glyph.c new file mode 100644 index 000000000..8e9339417 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_glyph.c @@ -0,0 +1,188 @@ +/** + * @file lv_freetype_glyph.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_freetype_private.h" + +#if LV_USE_FREETYPE + +/********************* + * DEFINES + *********************/ + +#define LV_FREETYPE_GLYPH_DSC_CACHE_SIZE (LV_FREETYPE_CACHE_FT_GLYPH_CNT * 2) +/********************** + * TYPEDEFS + **********************/ +typedef struct _lv_freetype_glyph_cache_data_t { + uint32_t unicode; + uint32_t size; + + lv_font_glyph_dsc_t glyph_dsc; +} lv_freetype_glyph_cache_data_t; + +/********************** + * STATIC PROTOTYPES + **********************/ + +static bool freetype_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc, uint32_t unicode_letter, + uint32_t unicode_letter_next); + +static bool freetype_glyph_create_cb(lv_freetype_glyph_cache_data_t * data, void * user_data); +static void freetype_glyph_free_cb(lv_freetype_glyph_cache_data_t * data, void * user_data); +static lv_cache_compare_res_t freetype_glyph_compare_cb(const lv_freetype_glyph_cache_data_t * lhs, + const lv_freetype_glyph_cache_data_t * rhs); +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_cache_t * lv_freetype_create_glyph_cache(void) +{ + lv_cache_ops_t ops = { + .create_cb = (lv_cache_create_cb_t)freetype_glyph_create_cb, + .free_cb = (lv_cache_free_cb_t)freetype_glyph_free_cb, + .compare_cb = (lv_cache_compare_cb_t)freetype_glyph_compare_cb, + }; + + lv_cache_t * glyph_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(lv_freetype_glyph_cache_data_t), + LV_FREETYPE_GLYPH_DSC_CACHE_SIZE, ops); + + return glyph_cache; +} + +void lv_freetype_set_cbs_glyph(lv_freetype_font_dsc_t * dsc) +{ + LV_ASSERT_FREETYPE_FONT_DSC(dsc); + dsc->font.get_glyph_dsc = freetype_get_glyph_dsc_cb; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static bool freetype_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc, uint32_t unicode_letter, + uint32_t unicode_letter_next) +{ + LV_ASSERT_NULL(font); + LV_ASSERT_NULL(g_dsc); + + if(unicode_letter < 0x20) { + g_dsc->adv_w = 0; + g_dsc->box_h = 0; + g_dsc->box_w = 0; + g_dsc->ofs_x = 0; + g_dsc->ofs_y = 0; + g_dsc->bpp = 0; + return true; + } + + lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)font->dsc; + LV_ASSERT_FREETYPE_FONT_DSC(dsc); + + lv_freetype_glyph_cache_data_t search_key = { + .unicode = unicode_letter, + .size = dsc->size, + }; + + lv_cache_t * glyph_cache = dsc->cache_node->glyph_cache; + + lv_cache_entry_t * entry = lv_cache_acquire_or_create(glyph_cache, &search_key, dsc); + if(entry == NULL) { + LV_LOG_ERROR("glyph lookup failed for unicode = 0x%" LV_PRIx32, unicode_letter); + return false; + } + lv_freetype_glyph_cache_data_t * data = lv_cache_entry_get_data(entry); + *g_dsc = data->glyph_dsc; + + if((dsc->style & LV_FREETYPE_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) { + g_dsc->adv_w = g_dsc->box_w + g_dsc->ofs_x; + } + + g_dsc->entry = NULL; + + lv_cache_release(glyph_cache, entry, NULL); + return true; +} + +/*----------------- + * Cache Callbacks + *----------------*/ + +static bool freetype_glyph_create_cb(lv_freetype_glyph_cache_data_t * data, void * user_data) +{ + lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)user_data; + + FT_Error error; + + lv_font_glyph_dsc_t * dsc_out = &data->glyph_dsc; + + FT_Face face = dsc->cache_node->face; + FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap); + FT_UInt glyph_index = FTC_CMapCache_Lookup(dsc->context->cmap_cache, dsc->face_id, charmap_index, data->unicode); + + FT_Set_Pixel_Sizes(face, 0, dsc->size); + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_COMPUTE_METRICS | FT_LOAD_NO_BITMAP); + if(error) { + FT_ERROR_MSG("FT_Load_Glyph", error); + return false; + } + + FT_GlyphSlot glyph = face->glyph; + + if(dsc->render_mode == LV_FREETYPE_FONT_RENDER_MODE_OUTLINE) { + dsc_out->adv_w = FT_F26DOT6_TO_INT(glyph->metrics.horiAdvance); + dsc_out->box_h = FT_F26DOT6_TO_INT(glyph->metrics.height); /*Height of the bitmap in [px]*/ + dsc_out->box_w = FT_F26DOT6_TO_INT(glyph->metrics.width); /*Width of the bitmap in [px]*/ + dsc_out->ofs_x = FT_F26DOT6_TO_INT(glyph->metrics.horiBearingX); /*X offset of the bitmap in [pf]*/ + dsc_out->ofs_y = FT_F26DOT6_TO_INT(glyph->metrics.horiBearingY - + glyph->metrics.height); /*Y offset of the bitmap measured from the as line*/ + dsc_out->bpp = LV_VECFONT_BPP; /*Bit per pixel: 1/2/4/8*/ + } + else if(dsc->render_mode == LV_FREETYPE_FONT_RENDER_MODE_BITMAP) { + FT_Bitmap * glyph_bitmap = &face->glyph->bitmap; + + dsc_out->adv_w = FT_F26DOT6_TO_INT(glyph->advance.x); /*Width of the glyph in [pf]*/ + dsc_out->box_h = glyph_bitmap->rows; /*Height of the bitmap in [px]*/ + dsc_out->box_w = glyph_bitmap->width; /*Width of the bitmap in [px]*/ + dsc_out->ofs_x = glyph->bitmap_left; /*X offset of the bitmap in [pf]*/ + dsc_out->ofs_y = glyph->bitmap_top - + dsc_out->box_h; /*Y offset of the bitmap measured from the as line*/ + dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ + } + + dsc_out->is_placeholder = glyph_index == 0; + dsc_out->glyph_index = glyph_index; + + return true; +} +static void freetype_glyph_free_cb(lv_freetype_glyph_cache_data_t * data, void * user_data) +{ + LV_UNUSED(data); + LV_UNUSED(user_data); +} +static lv_cache_compare_res_t freetype_glyph_compare_cb(const lv_freetype_glyph_cache_data_t * lhs, + const lv_freetype_glyph_cache_data_t * rhs) +{ + if(lhs->unicode != rhs->unicode) { + return lhs->unicode > rhs->unicode ? 1 : -1; + } + if(lhs->size != rhs->size) { + return lhs->size > rhs->size ? 1 : -1; + } + return 0; +} + +#endif /*LV_USE_FREETYPE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_image.c b/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_image.c new file mode 100755 index 000000000..f1ef689e3 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_image.c @@ -0,0 +1,180 @@ +/** + * @file lv_freetype_image.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_freetype_private.h" + +#if LV_USE_FREETYPE + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct _lv_freetype_image_cache_data_t { + FT_UInt glyph_index; + uint32_t size; + + lv_draw_buf_t * draw_buf; +} lv_freetype_image_cache_data_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static const void * freetype_get_glyph_bitmap_cb(lv_font_glyph_dsc_t * g_dsc, + uint32_t unicode_letter, + lv_draw_buf_t * draw_buf); + +static bool freetype_image_create_cb(lv_freetype_image_cache_data_t * data, void * user_data); +static void freetype_image_free_cb(lv_freetype_image_cache_data_t * node, void * user_data); +static lv_cache_compare_res_t freetype_image_compare_cb(const lv_freetype_image_cache_data_t * lhs, + const lv_freetype_image_cache_data_t * rhs); + +static void freetype_image_release_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc); +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_cache_t * lv_freetype_create_draw_data_image(void) +{ + lv_cache_ops_t ops = { + .compare_cb = (lv_cache_compare_cb_t)freetype_image_compare_cb, + .create_cb = (lv_cache_create_cb_t)freetype_image_create_cb, + .free_cb = (lv_cache_free_cb_t)freetype_image_free_cb, + }; + + lv_cache_t * draw_data_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(lv_freetype_image_cache_data_t), + LV_FREETYPE_CACHE_FT_GLYPH_CNT, ops); + + return draw_data_cache; +} + +void lv_freetype_set_cbs_image_font(lv_freetype_font_dsc_t * dsc) +{ + LV_ASSERT_FREETYPE_FONT_DSC(dsc); + dsc->font.get_glyph_bitmap = freetype_get_glyph_bitmap_cb; + dsc->font.release_glyph = freetype_image_release_cb; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static const void * freetype_get_glyph_bitmap_cb(lv_font_glyph_dsc_t * g_dsc, + uint32_t unicode_letter, + lv_draw_buf_t * draw_buf) +{ + LV_UNUSED(unicode_letter); + LV_UNUSED(draw_buf); + const lv_font_t * font = g_dsc->resolved_font; + lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)font->dsc; + LV_ASSERT_FREETYPE_FONT_DSC(dsc); + + FT_Face face = dsc->cache_node->face; + FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap); + FT_UInt glyph_index = FTC_CMapCache_Lookup(dsc->context->cmap_cache, dsc->face_id, charmap_index, unicode_letter); + + lv_cache_t * cache = dsc->cache_node->draw_data_cache; + + lv_freetype_image_cache_data_t search_key = { + .glyph_index = glyph_index, + .size = dsc->size, + }; + + lv_cache_entry_t * entry = lv_cache_acquire_or_create(cache, &search_key, dsc); + + g_dsc->entry = entry; + lv_freetype_image_cache_data_t * cache_node = lv_cache_entry_get_data(entry); + + return cache_node->draw_buf; +} + +static void freetype_image_release_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc) +{ + LV_ASSERT_NULL(font); + lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)font->dsc; + lv_cache_release(dsc->cache_node->draw_data_cache, g_dsc->entry, NULL); + g_dsc->entry = NULL; +} + +/*----------------- + * Cache Callbacks + *----------------*/ + +static bool freetype_image_create_cb(lv_freetype_image_cache_data_t * data, void * user_data) +{ + lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)user_data; + + FT_Error error; + + FT_Face face = dsc->cache_node->face; + FT_Set_Pixel_Sizes(face, 0, dsc->size); + error = FT_Load_Glyph(face, data->glyph_index, FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL); + if(error) { + FT_ERROR_MSG("FT_Load_Glyph", error); + return false; + } + error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); + if(error) { + FT_ERROR_MSG("FT_Render_Glyph", error); + return false; + } + + FT_Glyph glyph; + error = FT_Get_Glyph(face->glyph, &glyph); + if(error) { + FT_ERROR_MSG("FT_Get_Glyph", error); + return false; + } + + FT_BitmapGlyph glyph_bitmap = (FT_BitmapGlyph)glyph; + + uint16_t box_h = glyph_bitmap->bitmap.rows; /*Height of the bitmap in [px]*/ + uint16_t box_w = glyph_bitmap->bitmap.width; /*Width of the bitmap in [px]*/ + + uint32_t stride = lv_draw_buf_width_to_stride(box_w, LV_COLOR_FORMAT_A8); + data->draw_buf = lv_draw_buf_create(box_w, box_h, LV_COLOR_FORMAT_A8, stride); + + for(int y = 0; y < box_h; ++y) { + lv_memcpy((uint8_t *)(data->draw_buf->data) + y * stride, glyph_bitmap->bitmap.buffer + y * box_w, + box_w); + } + + FT_Done_Glyph(glyph); + + return true; +} +static void freetype_image_free_cb(lv_freetype_image_cache_data_t * data, void * user_data) +{ + LV_UNUSED(user_data); + lv_draw_buf_destroy(data->draw_buf); +} +static lv_cache_compare_res_t freetype_image_compare_cb(const lv_freetype_image_cache_data_t * lhs, + const lv_freetype_image_cache_data_t * rhs) +{ + if(lhs->glyph_index != rhs->glyph_index) { + return lhs->glyph_index > rhs->glyph_index ? 1 : -1; + } + if(lhs->size != rhs->size) { + return lhs->size > rhs->size ? 1 : -1; + } + return 0; +} + +#endif /*LV_USE_FREETYPE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_outline.c b/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_outline.c new file mode 100755 index 000000000..6bff04b08 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_outline.c @@ -0,0 +1,368 @@ +/** + * @file lv_freetype_outline.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_freetype_private.h" + +#if LV_USE_FREETYPE + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct _lv_freetype_outline_node_t { + FT_UInt glyph_index; + lv_freetype_outline_t outline; +} lv_freetype_outline_node_t; + +/********************** + * STATIC PROTOTYPES + **********************/ + +static lv_freetype_outline_t outline_create(lv_freetype_context_t * ctx, FT_Face face, FT_UInt glyph_index, + uint32_t size, uint32_t strength); +static lv_result_t outline_delete(lv_freetype_context_t * ctx, lv_freetype_outline_t outline); +static const void * freetype_get_glyph_bitmap_cb(lv_font_glyph_dsc_t * g_dsc, + uint32_t unicode_letter, + lv_draw_buf_t * draw_buf); +static void freetype_release_glyph_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc); + +static lv_cache_entry_t * lv_freetype_outline_lookup(lv_freetype_font_dsc_t * dsc, uint32_t unicode_letter); + +/*glyph dsc cache lru callbacks*/ +static bool freetype_glyph_outline_create_cb(lv_freetype_outline_node_t * node, lv_freetype_font_dsc_t * dsc); +static void freetype_glyph_outline_free_cb(lv_freetype_outline_node_t * node, lv_freetype_font_dsc_t * dsc); +static lv_cache_compare_res_t freetype_glyph_outline_cmp_cb(const lv_freetype_outline_node_t * node_a, + const lv_freetype_outline_node_t * node_b); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_cache_t * lv_freetype_create_draw_data_outline(void) +{ + lv_cache_ops_t glyph_outline_cache_ops = { + .create_cb = (lv_cache_create_cb_t)freetype_glyph_outline_create_cb, + .free_cb = (lv_cache_free_cb_t)freetype_glyph_outline_free_cb, + .compare_cb = (lv_cache_compare_cb_t)freetype_glyph_outline_cmp_cb, + }; + + lv_cache_t * draw_data_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(lv_freetype_outline_node_t), + LV_FREETYPE_CACHE_FT_GLYPH_CNT, + glyph_outline_cache_ops); + + return draw_data_cache; +} + +void lv_freetype_set_cbs_outline_font(lv_freetype_font_dsc_t * dsc) +{ + LV_ASSERT_FREETYPE_FONT_DSC(dsc); + dsc->font.get_glyph_bitmap = freetype_get_glyph_bitmap_cb; + dsc->font.release_glyph = freetype_release_glyph_cb; +} + +void lv_freetype_outline_add_event(lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data) +{ + LV_UNUSED(user_data); + lv_freetype_context_t * ctx = lv_freetype_get_context(); + + LV_UNUSED(filter); + ctx->event_cb = event_cb; +} + +uint32_t lv_freetype_outline_get_scale(const lv_font_t * font) +{ + LV_ASSERT_NULL(font); + const lv_freetype_font_dsc_t * dsc = font->dsc; + LV_ASSERT_FREETYPE_FONT_DSC(dsc); + + return FT_INT_TO_F26DOT6(dsc->size) / dsc->cache_node->ref_size; +} + +bool lv_freetype_is_outline_font(const lv_font_t * font) +{ + LV_ASSERT_NULL(font); + const lv_freetype_font_dsc_t * dsc = font->dsc; + if(!LV_FREETYPE_FONT_DSC_HAS_MAGIC_NUM(dsc)) { + return false; + } + + return dsc->render_mode == LV_FREETYPE_FONT_RENDER_MODE_OUTLINE; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/*------------------- + * OUTLINE CACHE + *------------------*/ + +static bool freetype_glyph_outline_create_cb(lv_freetype_outline_node_t * node, lv_freetype_font_dsc_t * dsc) +{ + lv_freetype_outline_t outline; + outline = outline_create(dsc->context, + dsc->cache_node->face, + node->glyph_index, + dsc->cache_node->ref_size, + dsc->style & LV_FREETYPE_FONT_STYLE_BOLD ? 1 : 0); + + if(!outline) { + return false; + } + + LV_LOG_INFO("glyph_index = 0x%" LV_PRIx32, (uint32_t)node->glyph_index); + + node->outline = outline; + return true; +} + +static void freetype_glyph_outline_free_cb(lv_freetype_outline_node_t * node, lv_freetype_font_dsc_t * dsc) +{ + LV_UNUSED(dsc); + + lv_freetype_outline_t outline = node->outline; + lv_freetype_context_t * ctx = lv_freetype_get_context(); + outline_delete(ctx, outline); +} + +static lv_cache_compare_res_t freetype_glyph_outline_cmp_cb(const lv_freetype_outline_node_t * node_a, + const lv_freetype_outline_node_t * node_b) +{ + if(node_a->glyph_index == node_b->glyph_index) { + return 0; + } + return node_a->glyph_index > node_b->glyph_index ? 1 : -1; +} + +static const void * freetype_get_glyph_bitmap_cb(lv_font_glyph_dsc_t * g_dsc, + uint32_t unicode_letter, + lv_draw_buf_t * draw_buf) +{ + LV_UNUSED(draw_buf); + const lv_font_t * font = g_dsc->resolved_font; + lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)font->dsc; + LV_ASSERT_FREETYPE_FONT_DSC(dsc); + lv_cache_entry_t * entry = lv_freetype_outline_lookup(dsc, unicode_letter); + if(entry == NULL) { + return NULL; + } + lv_freetype_outline_node_t * node = lv_cache_entry_get_data(entry); + + g_dsc->entry = entry; + + return node ? node->outline : NULL; +} + +static void freetype_release_glyph_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc) +{ + LV_ASSERT_NULL(font); + lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)font->dsc; + + if(g_dsc->entry == NULL) { + return; + } + lv_cache_release(dsc->cache_node->draw_data_cache, g_dsc->entry, NULL); + g_dsc->entry = NULL; +} + +static lv_cache_entry_t * lv_freetype_outline_lookup(lv_freetype_font_dsc_t * dsc, uint32_t unicode_letter) +{ + lv_freetype_cache_node_t * cache_node = dsc->cache_node; + + FT_UInt charmap_index = FT_Get_Charmap_Index(cache_node->face->charmap); + FT_UInt glyph_index = FTC_CMapCache_Lookup(dsc->context->cmap_cache, dsc->face_id, charmap_index, unicode_letter); + + lv_freetype_outline_node_t tmp_node; + tmp_node.glyph_index = glyph_index; + + lv_cache_entry_t * entry = lv_cache_acquire_or_create(cache_node->draw_data_cache, &tmp_node, dsc); + if(!entry) { + LV_LOG_ERROR("glyph outline lookup failed for glyph_index = 0x%" LV_PRIx32, (uint32_t)glyph_index); + return NULL; + } + return entry; +} + +static void ft_vector_to_lv_vector(lv_freetype_outline_vector_t * dest, const FT_Vector * src) +{ + dest->x = src ? src->x : 0; + dest->y = src ? src->y : 0; +} + +static lv_result_t outline_send_event(lv_freetype_context_t * ctx, lv_event_code_t code, + lv_freetype_outline_event_param_t * param) +{ + if(!ctx->event_cb) { + LV_LOG_ERROR("event_cb is not set"); + return LV_RESULT_INVALID; + } + + lv_event_t e; + lv_memzero(&e, sizeof(e)); + e.code = code; + e.param = param; + e.user_data = NULL; + + ctx->event_cb(&e); + + return LV_RESULT_OK; +} + +static lv_result_t outline_push_point( + lv_freetype_outline_t outline, + lv_freetype_outline_type_t type, + const FT_Vector * control1, + const FT_Vector * control2, + const FT_Vector * to) +{ + lv_freetype_context_t * ctx = lv_freetype_get_context(); + + lv_freetype_outline_event_param_t param; + lv_memzero(¶m, sizeof(param)); + param.outline = outline; + param.type = type; + ft_vector_to_lv_vector(¶m.control1, control1); + ft_vector_to_lv_vector(¶m.control2, control2); + ft_vector_to_lv_vector(¶m.to, to); + + return outline_send_event(ctx, LV_EVENT_INSERT, ¶m); +} + +static int outline_move_to_cb( + const FT_Vector * to, + void * user) +{ + lv_freetype_outline_t outline = user; + outline_push_point(outline, LV_FREETYPE_OUTLINE_MOVE_TO, NULL, NULL, to); + return FT_Err_Ok; +} + +static int outline_line_to_cb( + const FT_Vector * to, + void * user) +{ + lv_freetype_outline_t outline = user; + outline_push_point(outline, LV_FREETYPE_OUTLINE_LINE_TO, NULL, NULL, to); + return FT_Err_Ok; +} + +static int outline_conic_to_cb( + const FT_Vector * control, + const FT_Vector * to, + void * user) +{ + lv_freetype_outline_t outline = user; + outline_push_point(outline, LV_FREETYPE_OUTLINE_CONIC_TO, control, NULL, to); + return FT_Err_Ok; +} + +static int outline_cubic_to_cb( + const FT_Vector * control1, + const FT_Vector * control2, + const FT_Vector * to, + void * user) +{ + lv_freetype_outline_t outline = user; + outline_push_point(outline, LV_FREETYPE_OUTLINE_CUBIC_TO, control1, control2, to); + return FT_Err_Ok; +} + +static lv_freetype_outline_t outline_create( + lv_freetype_context_t * ctx, + FT_Face face, + FT_UInt glyph_index, + uint32_t size, + uint32_t strength) +{ + LV_ASSERT_NULL(ctx); + FT_Error error; + + error = FT_Set_Pixel_Sizes(face, 0, size); + if(error) { + FT_ERROR_MSG("FT_Set_Char_Size", error); + return NULL; + } + + /* Load glyph */ + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP); + if(error) { + FT_ERROR_MSG("FT_Load_Glyph", error); + return NULL; + } + + if(strength > 0) { + error = FT_Outline_Embolden(&face->glyph->outline, FT_INT_TO_F26DOT6(strength)); + if(error) { + FT_ERROR_MSG("FT_Outline_Embolden", error); + } + } + + lv_result_t res; + lv_freetype_outline_event_param_t param; + + lv_memzero(¶m, sizeof(param)); + res = outline_send_event(ctx, LV_EVENT_CREATE, ¶m); + + lv_freetype_outline_t outline = param.outline; + + if(res != LV_RESULT_OK || !outline) { + LV_LOG_ERROR("Outline object create failed"); + return NULL; + } + + FT_Outline_Funcs outline_funcs = { + .move_to = outline_move_to_cb, + .line_to = outline_line_to_cb, + .conic_to = outline_conic_to_cb, + .cubic_to = outline_cubic_to_cb, + .shift = 0, + .delta = 0 + }; + + /* Run outline decompose again to fill outline data */ + error = FT_Outline_Decompose(&face->glyph->outline, &outline_funcs, outline); + if(error) { + FT_ERROR_MSG("FT_Outline_Decompose", error); + outline_delete(ctx, outline); + return NULL; + } + + /* close outline */ + res = outline_push_point(outline, LV_FREETYPE_OUTLINE_END, NULL, NULL, NULL); + if(res != LV_RESULT_OK) { + LV_LOG_ERROR("Outline object close failed"); + outline_delete(ctx, outline); + return NULL; + } + + return outline; +} + +static lv_result_t outline_delete(lv_freetype_context_t * ctx, lv_freetype_outline_t outline) +{ + lv_freetype_outline_event_param_t param; + lv_memzero(¶m, sizeof(param)); + param.outline = outline; + + return outline_send_event(ctx, LV_EVENT_DELETE, ¶m); +} + +#endif /*LV_USE_FREETYPE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_private.h b/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_private.h new file mode 100755 index 000000000..3e6b4297f --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_freetype_private.h @@ -0,0 +1,146 @@ +/** + * @file lv_freetype_private.h + * + */ + +#ifndef LV_FREETYPE_PRIVATE_H +#define LV_FREETYPE_PRIVATE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../../lvgl.h" + +#if LV_USE_FREETYPE + +#include "ft2build.h" +#include FT_FREETYPE_H +#include FT_GLYPH_H +#include FT_CACHE_H +#include FT_SIZES_H +#include FT_IMAGE_H +#include FT_OUTLINE_H + +/********************* + * DEFINES + *********************/ + +#ifdef FT_CONFIG_OPTION_ERROR_STRINGS +#define FT_ERROR_MSG(msg, error_code) \ + LV_LOG_ERROR(msg " error(0x%x): %s", (int)error_code, FT_Error_String(error_code)) +#else +#define FT_ERROR_MSG(msg, error_code) \ + LV_LOG_ERROR(msg " error(0x%x)", (int)error_code) +#endif + +#if LV_FREETYPE_CACHE_SIZE <= 0 +#error "LV_FREETYPE_CACHE_SIZE must > 0" +#endif + +#define LV_FREETYPE_FONT_DSC_MAGIC_NUM 0x5F5F4654 /* '__FT' */ +#define LV_FREETYPE_FONT_DSC_HAS_MAGIC_NUM(dsc) ((dsc)->magic_num == LV_FREETYPE_FONT_DSC_MAGIC_NUM) +#define LV_ASSERT_FREETYPE_FONT_DSC(dsc) \ + do { \ + LV_ASSERT_NULL(dsc); \ + LV_ASSERT_MSG(LV_FREETYPE_FONT_DSC_HAS_MAGIC_NUM(dsc), "Invalid font descriptor"); \ + } while (0) + +#define FT_INT_TO_F26DOT6(x) ((x) << 6) +#define FT_F26DOT6_TO_INT(x) ((x) >> 6) + +#define FT_INT_TO_F16DOT16(x) ((x) << 16) +#define FT_F16DOT16_TO_INT(x) ((x) >> 16) + +/********************** + * TYPEDEFS + **********************/ + +typedef struct _lv_freetype_cache_node_t lv_freetype_cache_node_t; + +struct _lv_freetype_cache_node_t { + const char * pathname; + lv_freetype_font_style_t style; + lv_freetype_font_render_mode_t render_mode; + + uint32_t ref_size; /**< Reference size for calculating outline glyph's real size.*/ + + FT_Face face; + + /*glyph cache*/ + lv_cache_t * glyph_cache; + + /*draw data cache*/ + lv_cache_t * draw_data_cache; +}; + +typedef struct _lv_freetype_context_t { + FT_Library library; + FTC_Manager cache_manager; + FTC_CMapCache cmap_cache; + lv_ll_t face_id_ll; + lv_event_cb_t event_cb; + + lv_cache_t * cache_node_cache; +} lv_freetype_context_t; + +typedef struct _lv_freetype_font_dsc_t { + uint32_t magic_num; + lv_font_t font; + uint32_t size; + lv_freetype_font_style_t style; + lv_freetype_font_render_mode_t render_mode; + lv_freetype_context_t * context; + lv_freetype_cache_node_t * cache_node; + lv_cache_entry_t * cache_node_entry; + FTC_FaceID face_id; +} lv_freetype_font_dsc_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Get the FreeType context. + * + * @return A pointer to the FreeType context used by LittlevGL. + */ +lv_freetype_context_t * lv_freetype_get_context(void); + +/** + * Look up a FreeType size object for a given font descriptor and size. + * + * @param dsc The font descriptor to use. + * @param size The size of the font. + * @return A pointer to the FreeType size object. + */ +FT_Size lv_freetype_lookup_size(const lv_freetype_font_dsc_t * dsc); + +void lv_freetype_italic_transform(FT_Face face); + +const char * lv_freetype_get_pathname(FTC_FaceID face_id); + +lv_cache_t * lv_freetype_create_glyph_cache(void); +void lv_freetype_set_cbs_glyph(lv_freetype_font_dsc_t * dsc); + +lv_cache_t * lv_freetype_create_draw_data_image(void); +void lv_freetype_set_cbs_image_font(lv_freetype_font_dsc_t * dsc); + +lv_cache_t * lv_freetype_create_draw_data_outline(void); +void lv_freetype_set_cbs_outline_font(lv_freetype_font_dsc_t * dsc); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_FREETYPE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_FREETYPE_PRIVATE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_ftsystem.c b/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_ftsystem.c new file mode 100644 index 000000000..ee0e836b6 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/freetype/lv_ftsystem.c @@ -0,0 +1,291 @@ +/** + * @file lv_ftsystem.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "../../../lvgl.h" +#if LV_USE_FREETYPE && LV_FREETYPE_USE_LVGL_PORT + +#include +#include FT_CONFIG_CONFIG_H +#include +#include +#include +#include +#include + +/********************* + * DEFINES + *********************/ + +/* The macro FT_COMPONENT is used in trace mode. It is an implicit + * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log + * messages during execution. + */ +#undef FT_COMPONENT +#define FT_COMPONENT io + +/* We use the macro STREAM_FILE for convenience to extract the */ +/* system-specific stream handle from a given FreeType stream object */ +#define STREAM_FILE( stream ) ( (lv_fs_file_t*)stream->descriptor.pointer ) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +FT_CALLBACK_DEF(unsigned long) +ft_lv_fs_stream_io(FT_Stream stream, + unsigned long offset, + unsigned char * buffer, + unsigned long count); +FT_CALLBACK_DEF(void) +ft_lv_fs_stream_close(FT_Stream stream); +FT_CALLBACK_DEF(void *) +ft_alloc(FT_Memory memory, + long size); +FT_CALLBACK_DEF(void *) +ft_realloc(FT_Memory memory, + long cur_size, + long new_size, + void * block); +FT_CALLBACK_DEF(void) +ft_free(FT_Memory memory, + void * block); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef FT_DEBUG_MEMORY + + extern FT_Int + ft_mem_debug_init(FT_Memory memory); + + extern void + ft_mem_debug_done(FT_Memory memory); + +#endif + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT + +/* documentation is in ftstream.h */ + +FT_BASE_DEF(FT_Error) +FT_Stream_Open(FT_Stream stream, + const char * filepathname) +{ + lv_fs_file_t file; + + if(!stream) + return FT_THROW(Invalid_Stream_Handle); + + stream->descriptor.pointer = NULL; + stream->pathname.pointer = (char *)filepathname; + stream->base = NULL; + stream->pos = 0; + stream->read = NULL; + stream->close = NULL; + + lv_fs_res_t res = lv_fs_open(&file, filepathname, LV_FS_MODE_RD); + + if(res != LV_FS_RES_OK) { + FT_ERROR(("FT_Stream_Open:" + " could not open `%s'\n", filepathname)); + + return FT_THROW(Cannot_Open_Resource); + } + + lv_fs_seek(&file, 0, LV_FS_SEEK_END); + + uint32_t pos; + res = lv_fs_tell(&file, &pos); + if(res != LV_FS_RES_OK) { + FT_ERROR(("FT_Stream_Open:")); + FT_ERROR((" opened `%s' but zero-sized\n", filepathname)); + lv_fs_close(&file); + return FT_THROW(Cannot_Open_Stream); + } + stream->size = pos; + lv_fs_seek(&file, 0, LV_FS_SEEK_SET); + + lv_fs_file_t * file_p = lv_malloc(sizeof(lv_fs_file_t)); + LV_ASSERT_MALLOC(file_p); + + if(!file_p) { + FT_ERROR(("FT_Stream_Open: malloc failed for file_p")); + lv_fs_close(&file); + return FT_THROW(Cannot_Open_Stream); + } + + *file_p = file; + + stream->descriptor.pointer = file_p; + stream->read = ft_lv_fs_stream_io; + stream->close = ft_lv_fs_stream_close; + + FT_TRACE1(("FT_Stream_Open:")); + FT_TRACE1((" opened `%s' (%ld bytes) successfully\n", + filepathname, stream->size)); + + return FT_Err_Ok; +} + +#endif /* !FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */ + +/* documentation is in ftobjs.h */ + +FT_BASE_DEF(FT_Memory) +FT_New_Memory(void) +{ + FT_Memory memory; + + memory = (FT_Memory)lv_malloc(sizeof(*memory)); + if(memory) { + memory->user = NULL; + memory->alloc = ft_alloc; + memory->realloc = ft_realloc; + memory->free = ft_free; +#ifdef FT_DEBUG_MEMORY + ft_mem_debug_init(memory); +#endif + } + + return memory; +} + +/* documentation is in ftobjs.h */ + +FT_BASE_DEF(void) +FT_Done_Memory(FT_Memory memory) +{ +#ifdef FT_DEBUG_MEMORY + ft_mem_debug_done(memory); +#endif + lv_free(memory); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * The memory allocation function. + * @param memory A pointer to the memory object. + * @param size The requested size in bytes. + * @return The address of newly allocated block. + */ +FT_CALLBACK_DEF(void *) +ft_alloc(FT_Memory memory, + long size) +{ + FT_UNUSED(memory); + + return lv_malloc((size_t)size); +} + +/** + * The memory reallocation function. + * @param memory A pointer to the memory object. + * @param cur_size The current size of the allocated memory block. + * @param new_size The newly requested size in bytes. + * @param block The current address of the block in memory. + * @return The address of the reallocated memory block. + */ +FT_CALLBACK_DEF(void *) +ft_realloc(FT_Memory memory, + long cur_size, + long new_size, + void * block) +{ + FT_UNUSED(memory); + FT_UNUSED(cur_size); + + return lv_realloc(block, (size_t)new_size); +} + +/** + * The memory release function. + * @param memory A pointer to the memory object. + * @param block The address of block in memory to be freed. + */ +FT_CALLBACK_DEF(void) +ft_free(FT_Memory memory, + void * block) +{ + FT_UNUSED(memory); + + lv_free(block); +} + +#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT + +/** + * The function to close a stream. + * @param stream A pointer to the stream object. + */ +FT_CALLBACK_DEF(void) +ft_lv_fs_stream_close(FT_Stream stream) +{ + lv_fs_file_t * file_p = STREAM_FILE(stream); + lv_fs_close(file_p); + lv_free(file_p); + + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = NULL; +} + +/** + * The function to open a stream. + * @param stream A pointer to the stream object. + * @param offset The position in the data stream to start reading. + * @param buffer The address of buffer to store the read data. + * @param count The number of bytes to read from the stream. + * @return The number of bytes actually read. If `count' is zero (this is, + * the function is used for seeking), a non-zero return value + * indicates an error. + */ +FT_CALLBACK_DEF(unsigned long) +ft_lv_fs_stream_io(FT_Stream stream, + unsigned long offset, + unsigned char * buffer, + unsigned long count) +{ + lv_fs_file_t * file_p; + + if(!count && offset > stream->size) + return 1; + + file_p = STREAM_FILE(stream); + + if(stream->pos != offset) + lv_fs_seek(file_p, (long)offset, LV_FS_SEEK_SET); + + if(count == 0) + return 0; + + uint32_t br; + lv_fs_res_t res = lv_fs_read(file_p, buffer, count, &br); + + return res == LV_FS_RES_OK ? br : 0; +} + +#endif /* !FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */ + +#endif/*LV_FREETYPE_USE_LV_FTSYSTEM*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_cbfs.c b/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_cbfs.c new file mode 100644 index 000000000..d4833bb0e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_cbfs.c @@ -0,0 +1,10 @@ +// this file should not exist +#ifdef __GNUC__ + #define IS_NOT_USED __attribute__ ((unused)) +#else + #define IS_NOT_USED +#endif +IS_NOT_USED static void nothing(void) +{ + // do nothing +} \ No newline at end of file diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_fatfs.c b/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_fatfs.c similarity index 68% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_fatfs.c rename to lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_fatfs.c index cc1d2e6d6..44971733b 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_fatfs.c +++ b/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_fatfs.c @@ -11,6 +11,7 @@ #if LV_USE_FS_FATFS #include "ff.h" +#include "../../core/lv_global.h" /********************* * DEFINES *********************/ @@ -35,7 +36,7 @@ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); static void * fs_dir_open(lv_fs_drv_t * drv, const char * path); -static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn); +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn, uint32_t fn_len); static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p); /********************** @@ -62,25 +63,25 @@ void lv_fs_fatfs_init(void) *--------------------------------------------------*/ /*Add a simple drive to open images*/ - static lv_fs_drv_t fs_drv; /*A driver descriptor*/ - lv_fs_drv_init(&fs_drv); + lv_fs_drv_t * fs_drv_p = &(LV_GLOBAL_DEFAULT()->fatfs_fs_drv); + lv_fs_drv_init(fs_drv_p); /*Set up fields...*/ - fs_drv.letter = LV_FS_FATFS_LETTER; - fs_drv.cache_size = LV_FS_FATFS_CACHE_SIZE; + fs_drv_p->letter = LV_FS_FATFS_LETTER; + fs_drv_p->cache_size = LV_FS_FATFS_CACHE_SIZE; - fs_drv.open_cb = fs_open; - fs_drv.close_cb = fs_close; - fs_drv.read_cb = fs_read; - fs_drv.write_cb = fs_write; - fs_drv.seek_cb = fs_seek; - fs_drv.tell_cb = fs_tell; + fs_drv_p->open_cb = fs_open; + fs_drv_p->close_cb = fs_close; + fs_drv_p->read_cb = fs_read; + fs_drv_p->write_cb = fs_write; + fs_drv_p->seek_cb = fs_seek; + fs_drv_p->tell_cb = fs_tell; - fs_drv.dir_close_cb = fs_dir_close; - fs_drv.dir_open_cb = fs_dir_open; - fs_drv.dir_read_cb = fs_dir_read; + fs_drv_p->dir_close_cb = fs_dir_close; + fs_drv_p->dir_open_cb = fs_dir_open; + fs_drv_p->dir_read_cb = fs_dir_read; - lv_fs_drv_register(&fs_drv); + lv_fs_drv_register(fs_drv_p); } /********************** @@ -96,9 +97,9 @@ static void fs_init(void) /** * Open a file - * @param drv pointer to a driver where this function belongs - * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) - * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR + * @param drv pointer to a driver where this function belongs + * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) + * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR * @return pointer to FIL struct or NULL in case of fail */ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) @@ -110,7 +111,7 @@ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) else if(mode == LV_FS_MODE_RD) flags = FA_READ; else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) flags = FA_READ | FA_WRITE | FA_OPEN_ALWAYS; - FIL * f = lv_mem_alloc(sizeof(FIL)); + FIL * f = lv_malloc(sizeof(FIL)); if(f == NULL) return NULL; FRESULT res = f_open(f, path, flags); @@ -118,15 +119,15 @@ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) return f; } else { - lv_mem_free(f); + lv_free(f); return NULL; } } /** * Close an opened file - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a FIL variable. (opened with fs_open) + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FIL variable. (opened with fs_open) * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ @@ -134,17 +135,17 @@ static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p) { LV_UNUSED(drv); f_close(file_p); - lv_mem_free(file_p); + lv_free(file_p); return LV_FS_RES_OK; } /** * Read data from an opened file - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a FIL variable. - * @param buf pointer to a memory block where to store the read data - * @param btr number of Bytes To Read - * @param br the real number of read bytes (Byte Read) + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FIL variable. + * @param buf pointer to a memory block where to store the read data + * @param btr number of Bytes To Read + * @param br the real number of read bytes (Byte Read) * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ @@ -158,11 +159,11 @@ static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_ /** * Write into a file - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a FIL variable - * @param buf pointer to a buffer with the bytes to write - * @param btw Bytes To Write - * @param bw the number of real written bytes (Bytes Written). NULL if unused. + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FIL variable + * @param buf pointer to a buffer with the bytes to write + * @param btw Bytes To Write + * @param bw the number of real written bytes (Bytes Written). NULL if unused. * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) @@ -175,10 +176,10 @@ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, /** * Set the read write pointer. Also expand the file size if necessary. - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a FIL variable. (opened with fs_open ) - * @param pos the new position of read write pointer - * @param whence only LV_SEEK_SET is supported + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FIL variable. (opened with fs_open ) + * @param pos the new position of read write pointer + * @param whence only LV_SEEK_SET is supported * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ @@ -203,9 +204,9 @@ static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs /** * Give the position of the read write pointer - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a FIL variable. - * @param pos_p pointer to to store the result + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FIL variable. + * @param pos_p pointer to to store the result * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ @@ -218,19 +219,19 @@ static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) /** * Initialize a 'DIR' variable for directory reading - * @param drv pointer to a driver where this function belongs - * @param path path to a directory + * @param drv pointer to a driver where this function belongs + * @param path path to a directory * @return pointer to an initialized 'DIR' variable */ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) { LV_UNUSED(drv); - DIR * d = lv_mem_alloc(sizeof(DIR)); + DIR * d = lv_malloc(sizeof(DIR)); if(d == NULL) return NULL; FRESULT res = f_opendir(d, path); if(res != FR_OK) { - lv_mem_free(d); + lv_free(d); d = NULL; } return d; @@ -239,12 +240,13 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) /** * Read the next filename from a directory. * The name of the directories will begin with '/' - * @param drv pointer to a driver where this function belongs - * @param dir_p pointer to an initialized 'DIR' variable - * @param fn pointer to a buffer to store the filename + * @param drv pointer to a driver where this function belongs + * @param dir_p pointer to an initialized 'DIR' variable + * @param fn pointer to a buffer to store the filename + * @param fn_len length of the buffer to store the filename * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ -static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn, uint32_t fn_len) { LV_UNUSED(drv); FRESULT res; @@ -256,19 +258,18 @@ static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) if(res != FR_OK) return LV_FS_RES_UNKNOWN; if(fno.fattrib & AM_DIR) { - fn[0] = '/'; - strcpy(&fn[1], fno.fname); + lv_snprintf(fn, fn_len, "/%s", fno.fname); } - else strcpy(fn, fno.fname); + else lv_strncpy(fn, fno.fname, fn_len); - } while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0); + } while(lv_strcmp(fn, "/.") == 0 || lv_strcmp(fn, "/..") == 0); return LV_FS_RES_OK; } /** * Close the directory reading - * @param drv pointer to a driver where this function belongs + * @param drv pointer to a driver where this function belongs * @param dir_p pointer to an initialized 'DIR' variable * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ @@ -276,7 +277,7 @@ static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p) { LV_UNUSED(drv); f_closedir(dir_p); - lv_mem_free(dir_p); + lv_free(dir_p); return LV_FS_RES_OK; } @@ -287,4 +288,3 @@ static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p) #endif #endif /*LV_USE_FS_POSIX*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_memfs.c b/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_memfs.c new file mode 100644 index 000000000..746f62ea1 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_memfs.c @@ -0,0 +1,215 @@ +/** + * @file lv_fs_memfs.c + * + * File System Interface driver for memory-mapped files + * + * This driver allows using a memory area as a file that can be read by normal file operations. It can + * be used, e.g., to store font files in slow flash memory, and load them into RAM on demand. + * + * You can enable it in lv_conf.h: + * + * #define LV_USE_FS_MEMFS 1 + * + * The actual implementation uses the built-in cache mechanism of the file system interface. + * + * Since this is not an actual file system, file write and directories are not supported. + * + * The default drive letter is 'M', but this can be changed in lv_conf.h: + * + * #define LV_FS_MEMFS_LETTER 'M' + * + * To use it seamlessly with the file system interface a new extended path object has been introduced: + * + * lv_fs_path_ex_t mempath; + * + * This structure can be initialized with the helper function: + * + * lv_fs_make_path_ex(&mempath, (const uint8_t *) & my_mem_buffer, sizeof(my_mem_buffer)); + * + * Then the "file" can be opened with: + * + * lv_fs_file_t file; + * lv_fs_res_t res = lv_fs_open(&file, (const char *) & mempath, LV_FS_MODE_RD); + * + * The path object can be used at any place where a file path is required, e.g.: + * + * lv_font_t* my_font = lv_binfont_create((const char *) & mempath); + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_FS_MEMFS + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** +* STATIC PROTOTYPES +**********************/ + +static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode); +static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p); +static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br); +static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); +static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); + +/********************** + * STATIC VARIABLES + **********************/ + +static lv_fs_drv_t fs_drv; /*A driver descriptor*/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Register a driver for the File system interface + */ +void lv_fs_memfs_init(void) +{ + /*--------------------------------------------------- + * Register the file system interface in LVGL + *--------------------------------------------------*/ + + /*Add a simple drive to open images*/ + lv_fs_drv_init(&fs_drv); + + /*Set up fields...*/ + fs_drv.letter = LV_FS_MEMFS_LETTER; + fs_drv.cache_size = LV_FS_CACHE_FROM_BUFFER; + + fs_drv.open_cb = fs_open; + fs_drv.close_cb = fs_close; + fs_drv.read_cb = fs_read; + fs_drv.write_cb = NULL; + fs_drv.seek_cb = fs_seek; + fs_drv.tell_cb = fs_tell; + + fs_drv.dir_close_cb = NULL; + fs_drv.dir_open_cb = NULL; + fs_drv.dir_read_cb = NULL; + + lv_fs_drv_register(&fs_drv); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Open a file + * @param drv pointer to a driver where this function belongs + * @param path pointer to an extended path object containing the memory buffer address and size + * @param mode read: FS_MODE_RD (currently only reading from the buffer is supported) + * @return pointer to FIL struct or NULL in case of fail + */ +static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) +{ + LV_UNUSED(drv); + LV_UNUSED(mode); + return (void *)path; +} + +/** + * Close an opened file + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. (opened with fs_open) + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p) +{ + LV_UNUSED(drv); + LV_UNUSED(file_p); + return LV_FS_RES_OK; +} + +/** + * Read data from an opened file + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. + * @param buf pointer to a memory block where to store the read data + * @param btr number of Bytes To Read + * @param br the real number of read bytes (Byte Read) + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br) +{ + LV_UNUSED(drv); + LV_UNUSED(file_p); + LV_UNUSED(buf); + LV_UNUSED(btr); + *br = 0; + return LV_FS_RES_OK; +} + +/** + * Set the read pointer. + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. (opened with fs_open ) + * @param pos the new position of read pointer + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence) +{ + /* NOTE: this function is only called to determine the end of the buffer when LV_FS_SEEK_END was given to lv_fs_seek() */ + LV_UNUSED(drv); + lv_fs_file_t * fp = (lv_fs_file_t *)file_p; + switch(whence) { + case LV_FS_SEEK_SET: { + fp->cache->file_position = pos; + break; + } + case LV_FS_SEEK_CUR: { + fp->cache->file_position += pos; + break; + } + case LV_FS_SEEK_END: { + fp->cache->file_position = fp->cache->end - pos; + break; + } + } + if(fp->cache->file_position < fp->cache->start) + fp->cache->file_position = fp->cache->start; + else if(fp->cache->file_position > fp->cache->end) + fp->cache->file_position = fp->cache->end; + return LV_FS_RES_OK; +} + +/** + * Give the position of the read write pointer + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. + * @param pos_p pointer to to store the result + * @return LV_FS_RES_OK: no error, the file is read + * any error from lv_fs_res_t enum + */ +static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) +{ + LV_UNUSED(drv); + *pos_p = ((lv_fs_file_t *)file_p)->cache->file_position; + return LV_FS_RES_OK; +} + +#else /*LV_USE_FS_MEMFS == 0*/ + +#if defined(LV_FS_MEMFS_LETTER) && LV_FS_MEMFS_LETTER != '\0' + #warning "LV_USE_FS_MEMFS is not enabled but LV_FS_MEMFS_LETTER is set" +#endif + +#endif /*LV_USE_FS_MEMFS*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_posix.c b/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_posix.c similarity index 56% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_posix.c rename to lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_posix.c index e656288d3..b345ea969 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_posix.c +++ b/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_posix.c @@ -3,7 +3,6 @@ * */ - /********************* * INCLUDES *********************/ @@ -13,12 +12,9 @@ #include #include -#ifndef WIN32 - #include - #include -#else - #include -#endif +#include +#include +#include /********************* * DEFINES @@ -28,6 +24,12 @@ #error "LV_FS_POSIX_LETTER must be an upper case ASCII letter" #endif +/** The reason for 'fd + 1' is because open() may return a legal fd with a value of 0, + * preventing it from being judged as NULL when converted to a pointer type. + */ +#define FILEP2FD(file_p) ((lv_uintptr_t)file_p - 1) +#define FD2FILEP(fd) ((void *)(lv_uintptr_t)(fd + 1)) + /********************** * TYPEDEFS **********************/ @@ -42,7 +44,7 @@ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); static void * fs_dir_open(lv_fs_drv_t * drv, const char * path); -static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn); +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn, uint32_t fn_len); static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p); /********************** @@ -67,25 +69,25 @@ void lv_fs_posix_init(void) *--------------------------------------------------*/ /*Add a simple drive to open images*/ - static lv_fs_drv_t fs_drv; /*A driver descriptor*/ - lv_fs_drv_init(&fs_drv); + lv_fs_drv_t * fs_drv_p = &(LV_GLOBAL_DEFAULT()->posix_fs_drv); + lv_fs_drv_init(fs_drv_p); /*Set up fields...*/ - fs_drv.letter = LV_FS_POSIX_LETTER; - fs_drv.cache_size = LV_FS_POSIX_CACHE_SIZE; + fs_drv_p->letter = LV_FS_POSIX_LETTER; + fs_drv_p->cache_size = LV_FS_POSIX_CACHE_SIZE; - fs_drv.open_cb = fs_open; - fs_drv.close_cb = fs_close; - fs_drv.read_cb = fs_read; - fs_drv.write_cb = fs_write; - fs_drv.seek_cb = fs_seek; - fs_drv.tell_cb = fs_tell; + fs_drv_p->open_cb = fs_open; + fs_drv_p->close_cb = fs_close; + fs_drv_p->read_cb = fs_read; + fs_drv_p->write_cb = fs_write; + fs_drv_p->seek_cb = fs_seek; + fs_drv_p->tell_cb = fs_tell; - fs_drv.dir_close_cb = fs_dir_close; - fs_drv.dir_open_cb = fs_dir_open; - fs_drv.dir_read_cb = fs_dir_read; + fs_drv_p->dir_close_cb = fs_dir_close; + fs_drv_p->dir_open_cb = fs_dir_open; + fs_drv_p->dir_read_cb = fs_dir_read; - lv_fs_drv_register(&fs_drv); + lv_fs_drv_register(fs_drv_p); } /********************** @@ -94,9 +96,9 @@ void lv_fs_posix_init(void) /** * Open a file - * @param drv pointer to a driver where this function belongs - * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) - * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR + * @param drv pointer to a driver where this function belongs + * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) + * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR * @return a file handle or -1 in case of fail */ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) @@ -115,199 +117,157 @@ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) int f = open(buf, flags, 0666); if(f < 0) return NULL; - return (void *)(lv_uintptr_t)f; + return FD2FILEP(f); } /** * Close an opened file - * @param drv pointer to a driver where this function belongs - * @param file_p a file handle. (opened with fs_open) + * @param drv pointer to a driver where this function belongs + * @param file_p a file handle. (opened with fs_open) * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p) { LV_UNUSED(drv); - close((lv_uintptr_t)file_p); + close(FILEP2FD(file_p)); return LV_FS_RES_OK; } /** * Read data from an opened file - * @param drv pointer to a driver where this function belongs - * @param file_p a file handle variable. - * @param buf pointer to a memory block where to store the read data - * @param btr number of Bytes To Read - * @param br the real number of read bytes (Byte Read) + * @param drv pointer to a driver where this function belongs + * @param file_p a file handle variable. + * @param buf pointer to a memory block where to store the read data + * @param btr number of Bytes To Read + * @param br the real number of read bytes (Byte Read) * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br) { LV_UNUSED(drv); - *br = read((lv_uintptr_t)file_p, buf, btr); + *br = read(FILEP2FD(file_p), buf, btr); return (int32_t)(*br) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK; } /** * Write into a file - * @param drv pointer to a driver where this function belongs - * @param file_p a file handle variable - * @param buf pointer to a buffer with the bytes to write - * @param btw Bytes To Write - * @param bw the number of real written bytes (Bytes Written). NULL if unused. + * @param drv pointer to a driver where this function belongs + * @param file_p a file handle variable + * @param buf pointer to a buffer with the bytes to write + * @param btw Bytes To Write + * @param bw the number of real written bytes (Bytes Written). NULL if unused. * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) { LV_UNUSED(drv); - *bw = write((lv_uintptr_t)file_p, buf, btw); + *bw = write(FILEP2FD(file_p), buf, btw); return (int32_t)(*bw) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK; } /** * Set the read write pointer. Also expand the file size if necessary. - * @param drv pointer to a driver where this function belongs - * @param file_p a file handle variable. (opened with fs_open ) - * @param pos the new position of read write pointer + * @param drv pointer to a driver where this function belongs + * @param file_p a file handle variable. (opened with fs_open ) + * @param pos the new position of read write pointer * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence) { LV_UNUSED(drv); - off_t offset = lseek((lv_uintptr_t)file_p, pos, whence); + int w; + switch(whence) { + case LV_FS_SEEK_SET: + w = SEEK_SET; + break; + case LV_FS_SEEK_CUR: + w = SEEK_CUR; + break; + case LV_FS_SEEK_END: + w = SEEK_END; + break; + default: + return LV_FS_RES_INV_PARAM; + } + + off_t offset = lseek(FILEP2FD(file_p), pos, w); return offset < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK; } /** * Give the position of the read write pointer - * @param drv pointer to a driver where this function belongs - * @param file_p a file handle variable. - * @param pos_p pointer to to store the result + * @param drv pointer to a driver where this function belongs + * @param file_p a file handle variable. + * @param pos_p pointer to to store the result * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) { LV_UNUSED(drv); - off_t offset = lseek((lv_uintptr_t)file_p, 0, SEEK_CUR); + off_t offset = lseek(FILEP2FD(file_p), 0, SEEK_CUR); *pos_p = offset; return offset < 0 ? LV_FS_RES_FS_ERR : LV_FS_RES_OK; } -#ifdef WIN32 - static char next_fn[256]; -#endif - /** * Initialize a 'fs_read_dir_t' variable for directory reading - * @param drv pointer to a driver where this function belongs - * @param path path to a directory + * @param drv pointer to a driver where this function belongs + * @param path path to a directory * @return pointer to an initialized 'DIR' or 'HANDLE' variable */ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) { LV_UNUSED(drv); -#ifndef WIN32 /*Make the path relative to the current directory (the projects root folder)*/ char buf[256]; lv_snprintf(buf, sizeof(buf), LV_FS_POSIX_PATH "%s", path); return opendir(buf); -#else - HANDLE d = INVALID_HANDLE_VALUE; - WIN32_FIND_DATA fdata; - - /*Make the path relative to the current directory (the projects root folder)*/ - char buf[256]; - lv_snprintf(buf, sizeof(buf), LV_FS_POSIX_PATH "%s\\*", path); - - strcpy(next_fn, ""); - d = FindFirstFile(buf, &fdata); - do { - if(strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { - continue; - } - else { - if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - sprintf(next_fn, "/%s", fdata.cFileName); - } - else { - sprintf(next_fn, "%s", fdata.cFileName); - } - break; - } - } while(FindNextFileA(d, &fdata)); - - return d; -#endif } /** * Read the next filename from a directory. * The name of the directories will begin with '/' - * @param drv pointer to a driver where this function belongs - * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable - * @param fn pointer to a buffer to store the filename + * @param drv pointer to a driver where this function belongs + * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable + * @param fn pointer to a buffer to store the filename + * @param fn_len length of the buffer to store the filename * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ -static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn, uint32_t fn_len) { LV_UNUSED(drv); -#ifndef WIN32 struct dirent * entry; do { entry = readdir(dir_p); if(entry) { - if(entry->d_type == DT_DIR) sprintf(fn, "/%s", entry->d_name); - else strcpy(fn, entry->d_name); + if(entry->d_type == DT_DIR) lv_snprintf(fn, fn_len, "/%s", entry->d_name); + else lv_strncpy(fn, entry->d_name, fn_len); } else { - strcpy(fn, ""); + lv_strncpy(fn, "", fn_len); } - } while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0); -#else - strcpy(fn, next_fn); + } while(lv_strcmp(fn, "/.") == 0 || lv_strcmp(fn, "/..") == 0); - strcpy(next_fn, ""); - WIN32_FIND_DATA fdata; - - if(FindNextFile(dir_p, &fdata) == false) return LV_FS_RES_OK; - do { - if(strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { - continue; - } - else { - if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - sprintf(next_fn, "/%s", fdata.cFileName); - } - else { - sprintf(next_fn, "%s", fdata.cFileName); - } - break; - } - } while(FindNextFile(dir_p, &fdata)); - -#endif return LV_FS_RES_OK; } /** * Close the directory reading - * @param drv pointer to a driver where this function belongs + * @param drv pointer to a driver where this function belongs * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p) { LV_UNUSED(drv); -#ifndef WIN32 + closedir(dir_p); -#else - FindClose(dir_p); -#endif return LV_FS_RES_OK; } #else /*LV_USE_FS_POSIX == 0*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_stdio.c b/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_stdio.c similarity index 67% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_stdio.c rename to lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_stdio.c index c2de6880e..fd5c2d183 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_stdio.c +++ b/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_stdio.c @@ -3,7 +3,6 @@ * */ - /********************* * INCLUDES *********************/ @@ -18,6 +17,7 @@ #include #endif +#include "../../core/lv_global.h" /********************* * DEFINES *********************/ @@ -45,7 +45,7 @@ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); static void * fs_dir_open(lv_fs_drv_t * drv, const char * path); -static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn); +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn, uint32_t fn_len); static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p); /********************** @@ -70,25 +70,25 @@ void lv_fs_stdio_init(void) *--------------------------------------------------*/ /*Add a simple drive to open images*/ - static lv_fs_drv_t fs_drv; /*A driver descriptor*/ - lv_fs_drv_init(&fs_drv); + lv_fs_drv_t * fs_drv_p = &(LV_GLOBAL_DEFAULT()->stdio_fs_drv); + lv_fs_drv_init(fs_drv_p); /*Set up fields...*/ - fs_drv.letter = LV_FS_STDIO_LETTER; - fs_drv.cache_size = LV_FS_STDIO_CACHE_SIZE; + fs_drv_p->letter = LV_FS_STDIO_LETTER; + fs_drv_p->cache_size = LV_FS_STDIO_CACHE_SIZE; - fs_drv.open_cb = fs_open; - fs_drv.close_cb = fs_close; - fs_drv.read_cb = fs_read; - fs_drv.write_cb = fs_write; - fs_drv.seek_cb = fs_seek; - fs_drv.tell_cb = fs_tell; + fs_drv_p->open_cb = fs_open; + fs_drv_p->close_cb = fs_close; + fs_drv_p->read_cb = fs_read; + fs_drv_p->write_cb = fs_write; + fs_drv_p->seek_cb = fs_seek; + fs_drv_p->tell_cb = fs_tell; - fs_drv.dir_close_cb = fs_dir_close; - fs_drv.dir_open_cb = fs_dir_open; - fs_drv.dir_read_cb = fs_dir_read; + fs_drv_p->dir_close_cb = fs_dir_close; + fs_drv_p->dir_open_cb = fs_dir_open; + fs_drv_p->dir_read_cb = fs_dir_read; - lv_fs_drv_register(&fs_drv); + lv_fs_drv_register(fs_drv_p); } /********************** @@ -97,9 +97,9 @@ void lv_fs_stdio_init(void) /** * Open a file - * @param drv pointer to a driver where this function belongs - * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) - * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR + * @param drv pointer to a driver where this function belongs + * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) + * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR * @return pointer to FIL struct or NULL in case of fail */ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) @@ -122,8 +122,8 @@ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) /** * Close an opened file - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a FILE variable. (opened with fs_open) + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. (opened with fs_open) * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ @@ -136,11 +136,11 @@ static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p) /** * Read data from an opened file - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a FILE variable. - * @param buf pointer to a memory block where to store the read data - * @param btr number of Bytes To Read - * @param br the real number of read bytes (Byte Read) + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. + * @param buf pointer to a memory block where to store the read data + * @param btr number of Bytes To Read + * @param br the real number of read bytes (Byte Read) * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ @@ -153,11 +153,11 @@ static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_ /** * Write into a file - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a FILE variable - * @param buf pointer to a buffer with the bytes to write - * @param btw Bytes To Write - * @param bw the number of real written bytes (Bytes Written). NULL if unused. + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable + * @param buf pointer to a buffer with the bytes to write + * @param btw Bytes To Write + * @param bw the number of real written bytes (Bytes Written). NULL if unused. * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) @@ -169,24 +169,39 @@ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, /** * Set the read write pointer. Also expand the file size if necessary. - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a FILE variable. (opened with fs_open ) - * @param pos the new position of read write pointer + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. (opened with fs_open ) + * @param pos the new position of read write pointer * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence) { LV_UNUSED(drv); - fseek(file_p, pos, whence); + int w; + switch(whence) { + case LV_FS_SEEK_SET: + w = SEEK_SET; + break; + case LV_FS_SEEK_CUR: + w = SEEK_CUR; + break; + case LV_FS_SEEK_END: + w = SEEK_END; + break; + default: + return LV_FS_RES_INV_PARAM; + } + + fseek(file_p, pos, w); return LV_FS_RES_OK; } /** * Give the position of the read write pointer - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a FILE variable. - * @param pos_p pointer to to store the result + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. + * @param pos_p pointer to to store the result * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ @@ -199,21 +214,21 @@ static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) /** * Initialize a 'DIR' or 'HANDLE' variable for directory reading - * @param drv pointer to a driver where this function belongs - * @param path path to a directory + * @param drv pointer to a driver where this function belongs + * @param path path to a directory * @return pointer to an initialized 'DIR' or 'HANDLE' variable */ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) { LV_UNUSED(drv); - dir_handle_t * handle = (dir_handle_t *)lv_mem_alloc(sizeof(dir_handle_t)); + dir_handle_t * handle = (dir_handle_t *)lv_malloc(sizeof(dir_handle_t)); #ifndef WIN32 /*Make the path relative to the current directory (the projects root folder)*/ char buf[MAX_PATH_LEN]; lv_snprintf(buf, sizeof(buf), LV_FS_STDIO_PATH "%s", path); handle->dir_p = opendir(buf); if(handle->dir_p == NULL) { - lv_mem_free(handle); + lv_free(handle); return NULL; } return handle; @@ -225,10 +240,10 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) char buf[MAX_PATH_LEN]; lv_snprintf(buf, sizeof(buf), LV_FS_STDIO_PATH "%s\\*", path); - strcpy(handle->next_fn, ""); + lv_strcpy(handle->next_fn, ""); handle->dir_p = FindFirstFileA(buf, &fdata); do { - if(strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { + if(lv_strcmp(fdata.cFileName, ".") == 0 || lv_strcmp(fdata.cFileName, "..") == 0) { continue; } else { @@ -243,7 +258,7 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) } while(FindNextFileA(handle->dir_p, &fdata)); if(handle->dir_p == INVALID_HANDLE_VALUE) { - lv_mem_free(handle); + lv_free(handle); return INVALID_HANDLE_VALUE; } return handle; @@ -253,12 +268,13 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) /** * Read the next filename form a directory. * The name of the directories will begin with '/' - * @param drv pointer to a driver where this function belongs - * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable - * @param fn pointer to a buffer to store the filename + * @param drv pointer to a driver where this function belongs + * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable + * @param fn pointer to a buffer to store the filename + * @param fn_len length of the buffer to store the filename * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ -static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn, uint32_t fn_len) { LV_UNUSED(drv); dir_handle_t * handle = (dir_handle_t *)dir_p; @@ -267,22 +283,23 @@ static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) do { entry = readdir(handle->dir_p); if(entry) { - if(entry->d_type == DT_DIR) lv_snprintf(fn, MAX_PATH_LEN, "/%s", entry->d_name); - else strcpy(fn, entry->d_name); + /*Note, DT_DIR is not defined in C99*/ + if(entry->d_type == DT_DIR) lv_snprintf(fn, fn_len, "/%s", entry->d_name); + else lv_strncpy(fn, entry->d_name, fn_len); } else { - strcpy(fn, ""); + lv_strncpy(fn, "", fn_len); } - } while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0); + } while(lv_strcmp(fn, "/.") == 0 || lv_strcmp(fn, "/..") == 0); #else - strcpy(fn, handle->next_fn); + lv_strncpy(fn, handle->next_fn, fn_len); - strcpy(handle->next_fn, ""); + lv_strncpy(handle->next_fn, "", fn_len); WIN32_FIND_DATAA fdata; if(FindNextFileA(handle->dir_p, &fdata) == false) return LV_FS_RES_OK; do { - if(strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { + if(lv_strcmp(fdata.cFileName, ".") == 0 || lv_strcmp(fdata.cFileName, "..") == 0) { continue; } else { @@ -302,7 +319,7 @@ static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) /** * Close the directory reading - * @param drv pointer to a driver where this function belongs + * @param drv pointer to a driver where this function belongs * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ @@ -315,7 +332,7 @@ static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p) #else FindClose(handle->dir_p); #endif - lv_mem_free(handle); + lv_free(handle); return LV_FS_RES_OK; } @@ -326,4 +343,3 @@ static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p) #endif #endif /*LV_USE_FS_POSIX*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_win32.c b/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_win32.c similarity index 81% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_win32.c rename to lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_win32.c index 1a59aa496..4a8ac0a81 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fs_win32.c +++ b/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fs_win32.c @@ -3,7 +3,6 @@ * */ - /********************* * INCLUDES *********************/ @@ -12,7 +11,9 @@ #include #include +#include +#include "../../core/lv_global.h" /********************* * DEFINES *********************/ @@ -40,7 +41,7 @@ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); static void * fs_dir_open(lv_fs_drv_t * drv, const char * path); -static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn); +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn, uint32_t fn_len); static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p); /********************** @@ -65,25 +66,25 @@ void lv_fs_win32_init(void) *--------------------------------------------------*/ /*Add a simple driver to open images*/ - static lv_fs_drv_t fs_drv; /*A driver descriptor*/ - lv_fs_drv_init(&fs_drv); + lv_fs_drv_t * fs_drv_p = &(LV_GLOBAL_DEFAULT()->win32_fs_drv); + lv_fs_drv_init(fs_drv_p); /*Set up fields...*/ - fs_drv.letter = LV_FS_WIN32_LETTER; - fs_drv.cache_size = LV_FS_WIN32_CACHE_SIZE; + fs_drv_p->letter = LV_FS_WIN32_LETTER; + fs_drv_p->cache_size = LV_FS_WIN32_CACHE_SIZE; - fs_drv.open_cb = fs_open; - fs_drv.close_cb = fs_close; - fs_drv.read_cb = fs_read; - fs_drv.write_cb = fs_write; - fs_drv.seek_cb = fs_seek; - fs_drv.tell_cb = fs_tell; + fs_drv_p->open_cb = fs_open; + fs_drv_p->close_cb = fs_close; + fs_drv_p->read_cb = fs_read; + fs_drv_p->write_cb = fs_write; + fs_drv_p->seek_cb = fs_seek; + fs_drv_p->tell_cb = fs_tell; - fs_drv.dir_close_cb = fs_dir_close; - fs_drv.dir_open_cb = fs_dir_open; - fs_drv.dir_read_cb = fs_dir_read; + fs_drv_p->dir_close_cb = fs_dir_close; + fs_drv_p->dir_open_cb = fs_dir_open; + fs_drv_p->dir_read_cb = fs_dir_read; - lv_fs_drv_register(&fs_drv); + lv_fs_drv_register(fs_drv_p); } /********************** @@ -197,9 +198,9 @@ static lv_fs_res_t fs_error_from_win32(DWORD error) /** * Open a file - * @param drv pointer to a driver where this function belongs - * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) - * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR + * @param drv pointer to a driver where this function belongs + * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) + * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR * @return pointer to FIL struct or NULL in case of fail */ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) @@ -233,8 +234,8 @@ static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) /** * Close an opened file - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a FILE variable. (opened with fs_open) + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. (opened with fs_open) * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ @@ -248,11 +249,11 @@ static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p) /** * Read data from an opened file - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a FILE variable. - * @param buf pointer to a memory block where to store the read data - * @param btr number of Bytes To Read - * @param br the real number of read bytes (Byte Read) + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. + * @param buf pointer to a memory block where to store the read data + * @param btr number of Bytes To Read + * @param br the real number of read bytes (Byte Read) * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ @@ -266,11 +267,11 @@ static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_ /** * Write into a file - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a FILE variable - * @param buf pointer to a buffer with the bytes to write - * @param btw Bytes To Write - * @param bw the number of real written bytes (Bytes Written). NULL if unused. + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable + * @param buf pointer to a buffer with the bytes to write + * @param btw Bytes To Write + * @param bw the number of real written bytes (Bytes Written). NULL if unused. * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) @@ -283,9 +284,9 @@ static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, /** * Set the read write pointer. Also expand the file size if necessary. - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a FILE variable. (opened with fs_open ) - * @param pos the new position of read write pointer + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. (opened with fs_open ) + * @param pos the new position of read write pointer * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ @@ -313,9 +314,9 @@ static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs /** * Give the position of the read write pointer - * @param drv pointer to a driver where this function belongs - * @param file_p pointer to a FILE variable. - * @param pos_p pointer to to store the result + * @param drv pointer to a driver where this function belongs + * @param file_p pointer to a FILE variable. + * @param pos_p pointer to to store the result * @return LV_FS_RES_OK: no error, the file is read * any error from lv_fs_res_t enum */ @@ -352,14 +353,14 @@ static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) /** * Initialize a 'DIR' or 'HANDLE' variable for directory reading - * @param drv pointer to a driver where this function belongs - * @param path path to a directory + * @param drv pointer to a driver where this function belongs + * @param path path to a directory * @return pointer to an initialized 'DIR' or 'HANDLE' variable */ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) { LV_UNUSED(drv); - dir_handle_t * handle = (dir_handle_t *)lv_mem_alloc(sizeof(dir_handle_t)); + dir_handle_t * handle = (dir_handle_t *)lv_malloc(sizeof(dir_handle_t)); handle->dir_p = INVALID_HANDLE_VALUE; handle->next_error = LV_FS_RES_OK; WIN32_FIND_DATAA fdata; @@ -372,7 +373,7 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) lv_snprintf(buf, sizeof(buf), "%s\\*", path); #endif - strcpy(handle->next_fn, ""); + lv_strcpy(handle->next_fn, ""); handle->dir_p = FindFirstFileA(buf, &fdata); do { if(is_dots_name(fdata.cFileName)) { @@ -390,7 +391,7 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) } while(FindNextFileA(handle->dir_p, &fdata)); if(handle->dir_p == INVALID_HANDLE_VALUE) { - lv_mem_free(handle); + lv_free(handle); handle->next_error = fs_error_from_win32(GetLastError()); return INVALID_HANDLE_VALUE; } @@ -403,18 +404,19 @@ static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) /** * Read the next filename from a directory. * The name of the directories will begin with '/' - * @param drv pointer to a driver where this function belongs - * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable - * @param fn pointer to a buffer to store the filename + * @param drv pointer to a driver where this function belongs + * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable + * @param fn pointer to a buffer to store the filename + * @param fn_len length of the buffer to store the filename * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ -static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) +static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn, uint32_t fn_len) { LV_UNUSED(drv); dir_handle_t * handle = (dir_handle_t *)dir_p; - strcpy(fn, handle->next_fn); + lv_strcpy(fn, handle->next_fn); lv_fs_res_t current_error = handle->next_error; - strcpy(handle->next_fn, ""); + lv_strcpy(handle->next_fn, ""); WIN32_FIND_DATAA fdata; @@ -442,7 +444,7 @@ static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) /** * Close the directory reading - * @param drv pointer to a driver where this function belongs + * @param drv pointer to a driver where this function belongs * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ @@ -453,7 +455,7 @@ static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p) lv_fs_res_t res = FindClose(handle->dir_p) ? LV_FS_RES_OK : fs_error_from_win32(GetLastError()); - lv_mem_free(handle); + lv_free(handle); return res; } diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fsdrv.h b/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fsdrv.h similarity index 70% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fsdrv.h rename to lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fsdrv.h index b864ad6f3..fcf5bd79e 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/fsdrv/lv_fsdrv.h +++ b/lib/libesp32_lvgl/lvgl/src/libs/fsdrv/lv_fsdrv.h @@ -13,7 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../lv_conf_internal.h" +#include "../../lv_conf_internal.h" /********************* * DEFINES @@ -27,27 +27,26 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ -#if LV_USE_FS_FATFS != '\0' +#if LV_USE_FS_FATFS void lv_fs_fatfs_init(void); #endif -#if LV_USE_FS_LITTLEFS != '\0' -void lv_fs_littlefs_init(void); -lv_fs_drv_t * lv_fs_littlefs_set_driver(char label, void * lfs_p); -#endif - -#if LV_USE_FS_STDIO != '\0' +#if LV_USE_FS_STDIO void lv_fs_stdio_init(void); #endif -#if LV_USE_FS_POSIX != '\0' +#if LV_USE_FS_POSIX void lv_fs_posix_init(void); #endif -#if LV_USE_FS_WIN32 != '\0' +#if LV_USE_FS_WIN32 void lv_fs_win32_init(void); #endif +#if LV_USE_FS_MEMFS +void lv_fs_memfs_init(void); +#endif + /********************** * MACROS **********************/ @@ -57,4 +56,3 @@ void lv_fs_win32_init(void); #endif #endif /*LV_FSDRV_H*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/gifdec.c b/lib/libesp32_lvgl/lvgl/src/libs/gif/gifdec.c similarity index 53% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/gif/gifdec.c rename to lib/libesp32_lvgl/lvgl/src/libs/gif/gifdec.c index 3ee9b7194..b35a5730f 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/gifdec.c +++ b/lib/libesp32_lvgl/lvgl/src/libs/gif/gifdec.c @@ -1,7 +1,7 @@ #include "gifdec.h" -#include "../../../misc/lv_log.h" -#include "../../../misc/lv_mem.h" -#include "../../../misc/lv_color.h" +#include "../../misc/lv_log.h" +#include "../../stdlib/lv_mem.h" +#include "../../misc/lv_color.h" #if LV_USE_GIF #include @@ -20,15 +20,25 @@ typedef struct Entry { typedef struct Table { int bulk; int nentries; - Entry *entries; + Entry * entries; } Table; -static gd_GIF * gif_open(gd_GIF * gif); +#if LV_GIF_CACHE_DECODE_DATA +#define LZW_MAXBITS 12 +#define LZW_TABLE_SIZE (1 << LZW_MAXBITS) +#define LZW_CACHE_SIZE (LZW_TABLE_SIZE * 4) +#endif + +static gd_GIF * gif_open(gd_GIF * gif); static bool f_gif_open(gd_GIF * gif, const void * path, bool is_file); static void f_gif_read(gd_GIF * gif, void * buf, size_t len); static int f_gif_seek(gd_GIF * gif, size_t pos, int k); static void f_gif_close(gd_GIF * gif); +#if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_HELIUM + #include "gifdec_mve.h" +#endif + static uint16_t read_num(gd_GIF * gif) { @@ -38,10 +48,8 @@ read_num(gd_GIF * gif) return bytes[0] + (((uint16_t) bytes[1]) << 8); } - - gd_GIF * -gd_open_gif_file(const char *fname) +gd_open_gif_file(const char * fname) { gd_GIF gif_base; memset(&gif_base, 0, sizeof(gif_base)); @@ -52,9 +60,8 @@ gd_open_gif_file(const char *fname) return gif_open(&gif_base); } - gd_GIF * -gd_open_gif_data(const void *data) +gd_open_gif_data(const void * data) { gd_GIF gif_base; memset(&gif_base, 0, sizeof(gif_base)); @@ -70,20 +77,19 @@ static gd_GIF * gif_open(gd_GIF * gif_base) uint8_t sigver[3]; uint16_t width, height, depth; uint8_t fdsz, bgidx, aspect; - int i; - uint8_t *bgcolor; + uint8_t * bgcolor; int gct_sz; - gd_GIF *gif = NULL; + gd_GIF * gif = NULL; /* Header */ f_gif_read(gif_base, sigver, 3); - if (memcmp(sigver, "GIF", 3) != 0) { + if(memcmp(sigver, "GIF", 3) != 0) { LV_LOG_WARN("invalid signature\n"); goto fail; } /* Version */ f_gif_read(gif_base, sigver, 3); - if (memcmp(sigver, "89a", 3) != 0) { + if(memcmp(sigver, "89a", 3) != 0) { LV_LOG_WARN("invalid version\n"); goto fail; } @@ -93,7 +99,7 @@ static gd_GIF * gif_open(gd_GIF * gif_base) /* FDSZ */ f_gif_read(gif_base, &fdsz, 1); /* Presence of GCT */ - if (!(fdsz & 0x80)) { + if(!(fdsz & 0x80)) { LV_LOG_WARN("no global color table\n"); goto fail; } @@ -107,15 +113,12 @@ static gd_GIF * gif_open(gd_GIF * gif_base) /* Aspect Ratio */ f_gif_read(gif_base, &aspect, 1); /* Create gd_GIF Structure. */ -#if LV_COLOR_DEPTH == 32 - gif = lv_mem_alloc(sizeof(gd_GIF) + 5 * width * height); -#elif LV_COLOR_DEPTH == 16 - gif = lv_mem_alloc(sizeof(gd_GIF) + 4 * width * height); -#elif LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 - gif = lv_mem_alloc(sizeof(gd_GIF) + 3 * width * height); -#endif - - if (!gif) goto fail; +#if LV_GIF_CACHE_DECODE_DATA + gif = lv_malloc(sizeof(gd_GIF) + 5 * width * height + LZW_CACHE_SIZE); + #else + gif = lv_malloc(sizeof(gd_GIF) + 5 * width * height); + #endif + if(!gif) goto fail; memcpy(gif, gif_base, sizeof(gd_GIF)); gif->width = width; gif->height = height; @@ -126,39 +129,25 @@ static gd_GIF * gif_open(gd_GIF * gif_base) gif->palette = &gif->gct; gif->bgindex = bgidx; gif->canvas = (uint8_t *) &gif[1]; -#if LV_COLOR_DEPTH == 32 gif->frame = &gif->canvas[4 * width * height]; -#elif LV_COLOR_DEPTH == 16 - gif->frame = &gif->canvas[3 * width * height]; -#elif LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 - gif->frame = &gif->canvas[2 * width * height]; -#endif - if (gif->bgindex) { + if(gif->bgindex) { memset(gif->frame, gif->bgindex, gif->width * gif->height); } - bgcolor = &gif->palette->colors[gif->bgindex*3]; + bgcolor = &gif->palette->colors[gif->bgindex * 3]; + #if LV_GIF_CACHE_DECODE_DATA + gif->lzw_cache = gif->frame + width * height; + #endif - for (i = 0; i < gif->width * gif->height; i++) { -#if LV_COLOR_DEPTH == 32 - gif->canvas[i*4 + 0] = *(bgcolor + 2); - gif->canvas[i*4 + 1] = *(bgcolor + 1); - gif->canvas[i*4 + 2] = *(bgcolor + 0); - gif->canvas[i*4 + 3] = 0xff; -#elif LV_COLOR_DEPTH == 16 - lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2)); - gif->canvas[i*3 + 0] = c.full & 0xff; - gif->canvas[i*3 + 1] = (c.full >> 8) & 0xff; - gif->canvas[i*3 + 2] = 0xff; -#elif LV_COLOR_DEPTH == 8 - lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2)); - gif->canvas[i*2 + 0] = c.full; - gif->canvas[i*2 + 1] = 0xff; -#elif LV_COLOR_DEPTH == 1 - lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2)); - gif->canvas[i*2 + 0] = c.ch.red > 128 ? 1 : 0; - gif->canvas[i*2 + 1] = 0xff; -#endif +#ifdef GIFDEC_FILL_BG + GIFDEC_FILL_BG(gif->canvas, gif->width * gif->height, 1, gif->width * gif->height, bgcolor, 0xff); +#else + for(int i = 0; i < gif->width * gif->height; i++) { + gif->canvas[i * 4 + 0] = *(bgcolor + 2); + gif->canvas[i * 4 + 1] = *(bgcolor + 1); + gif->canvas[i * 4 + 2] = *(bgcolor + 0); + gif->canvas[i * 4 + 3] = 0xff; } +#endif gif->anim_start = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); gif->loop_count = -1; goto ok; @@ -169,20 +158,20 @@ ok: } static void -discard_sub_blocks(gd_GIF *gif) +discard_sub_blocks(gd_GIF * gif) { uint8_t size; do { f_gif_read(gif, &size, 1); f_gif_seek(gif, size, LV_FS_SEEK_CUR); - } while (size); + } while(size); } static void -read_plain_text_ext(gd_GIF *gif) +read_plain_text_ext(gd_GIF * gif) { - if (gif->plain_text) { + if(gif->plain_text) { uint16_t tx, ty, tw, th; uint8_t cw, ch, fg, bg; size_t sub_block; @@ -198,7 +187,8 @@ read_plain_text_ext(gd_GIF *gif) sub_block = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); gif->plain_text(gif, tx, ty, tw, th, cw, ch, fg, bg); f_gif_seek(gif, sub_block, LV_FS_SEEK_SET); - } else { + } + else { /* Discard plain text metadata. */ f_gif_seek(gif, 13, LV_FS_SEEK_CUR); } @@ -207,7 +197,7 @@ read_plain_text_ext(gd_GIF *gif) } static void -read_graphic_control_ext(gd_GIF *gif) +read_graphic_control_ext(gd_GIF * gif) { uint8_t rdit; @@ -224,9 +214,9 @@ read_graphic_control_ext(gd_GIF *gif) } static void -read_comment_ext(gd_GIF *gif) +read_comment_ext(gd_GIF * gif) { - if (gif->comment) { + if(gif->comment) { size_t sub_block = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); gif->comment(gif); f_gif_seek(gif, sub_block, LV_FS_SEEK_SET); @@ -236,7 +226,7 @@ read_comment_ext(gd_GIF *gif) } static void -read_application_ext(gd_GIF *gif) +read_application_ext(gd_GIF * gif) { char app_id[8]; char app_auth_code[3]; @@ -248,7 +238,7 @@ read_application_ext(gd_GIF *gif) f_gif_read(gif, app_id, 8); /* Application Authentication Code. */ f_gif_read(gif, app_auth_code, 3); - if (!strncmp(app_id, "NETSCAPE", sizeof(app_id))) { + if(!strncmp(app_id, "NETSCAPE", sizeof(app_id))) { /* Discard block size (0x03) and constant byte (0x01). */ f_gif_seek(gif, 2, LV_FS_SEEK_CUR); loop_count = read_num(gif); @@ -256,84 +246,48 @@ read_application_ext(gd_GIF *gif) if(loop_count == 0) { gif->loop_count = 0; } - else{ + else { gif->loop_count = loop_count + 1; } } /* Skip block terminator. */ f_gif_seek(gif, 1, LV_FS_SEEK_CUR); - } else if (gif->application) { + } + else if(gif->application) { size_t sub_block = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); gif->application(gif, app_id, app_auth_code); f_gif_seek(gif, sub_block, LV_FS_SEEK_SET); discard_sub_blocks(gif); - } else { + } + else { discard_sub_blocks(gif); } } static void -read_ext(gd_GIF *gif) +read_ext(gd_GIF * gif) { uint8_t label; f_gif_read(gif, &label, 1); - switch (label) { - case 0x01: - read_plain_text_ext(gif); - break; - case 0xF9: - read_graphic_control_ext(gif); - break; - case 0xFE: - read_comment_ext(gif); - break; - case 0xFF: - read_application_ext(gif); - break; - default: - LV_LOG_WARN("unknown extension: %02X\n", label); + switch(label) { + case 0x01: + read_plain_text_ext(gif); + break; + case 0xF9: + read_graphic_control_ext(gif); + break; + case 0xFE: + read_comment_ext(gif); + break; + case 0xFF: + read_application_ext(gif); + break; + default: + LV_LOG_WARN("unknown extension: %02X\n", label); } } -static Table * -new_table(int key_size) -{ - int key; - int init_bulk = MAX(1 << (key_size + 1), 0x100); - Table *table = lv_mem_alloc(sizeof(*table) + sizeof(Entry) * init_bulk); - if (table) { - table->bulk = init_bulk; - table->nentries = (1 << key_size) + 2; - table->entries = (Entry *) &table[1]; - for (key = 0; key < (1 << key_size); key++) - table->entries[key] = (Entry) {1, 0xFFF, key}; - } - return table; -} - -/* Add table entry. Return value: - * 0 on success - * +1 if key size must be incremented after this addition - * -1 if could not realloc table */ -static int -add_entry(Table **tablep, uint16_t length, uint16_t prefix, uint8_t suffix) -{ - Table *table = *tablep; - if (table->nentries == table->bulk) { - table->bulk *= 2; - table = lv_mem_realloc(table, sizeof(*table) + sizeof(Entry) * table->bulk); - if (!table) return -1; - table->entries = (Entry *) &table[1]; - *tablep = table; - } - table->entries[table->nentries] = (Entry) {length, prefix, suffix}; - table->nentries++; - if ((table->nentries & (table->nentries - 1)) == 0) - return 1; - return 0; -} - static uint16_t get_key(gd_GIF *gif, int key_size, uint8_t *sub_len, uint8_t *shift, uint8_t *byte) { @@ -363,6 +317,192 @@ get_key(gd_GIF *gif, int key_size, uint8_t *sub_len, uint8_t *shift, uint8_t *by return key; } +#if LV_GIF_CACHE_DECODE_DATA +static int +read_image_data(gd_GIF *gif, int interlace) +{ + uint8_t sub_len, shift, byte; + int ret = 0; + int key_size; + int y, pass, linesize; + uint8_t *ptr = NULL; + uint8_t *ptr_row_start = NULL; + uint8_t *ptr_base = NULL; + size_t start, end; + uint16_t key, clear_code, stop_code, curr_code; + int frm_off, frm_size,curr_size,top_slot,new_codes,slot; + /* The first value of the value sequence corresponding to key */ + int first_value; + int last_key; + uint8_t *sp = NULL; + uint8_t *p_stack = NULL; + uint8_t *p_suffix = NULL; + uint16_t *p_prefix = NULL; + + /* get initial key size and clear code, stop code */ + f_gif_read(gif, &byte, 1); + key_size = (int) byte; + clear_code = 1 << key_size; + stop_code = clear_code + 1; + key = 0; + + start = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); + discard_sub_blocks(gif); + end = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); + f_gif_seek(gif, start, LV_FS_SEEK_SET); + + linesize = gif->width; + ptr_base = &gif->frame[gif->fy * linesize + gif->fx]; + ptr_row_start = ptr_base; + ptr = ptr_row_start; + sub_len = shift = 0; + /* decoder */ + pass = 0; + y = 0; + p_stack = gif->lzw_cache; + p_suffix = gif->lzw_cache + LZW_TABLE_SIZE; + p_prefix = (uint16_t*)(gif->lzw_cache + LZW_TABLE_SIZE * 2); + frm_off = 0; + frm_size = gif->fw * gif->fh; + curr_size = key_size + 1; + top_slot = 1 << curr_size; + new_codes = clear_code + 2; + slot = new_codes; + first_value = -1; + last_key = -1; + sp = p_stack; + + while (frm_off < frm_size) { + /* copy data to frame buffer */ + while (sp > p_stack) { + *ptr++ = *(--sp); + frm_off += 1; + /* read one line */ + if ((ptr - ptr_row_start) == gif->fw) { + if (interlace) { + switch(pass) { + case 0: + case 1: + y += 8; + ptr_row_start += linesize * 8; + break; + case 2: + y += 4; + ptr_row_start += linesize * 4; + break; + case 3: + y += 2; + ptr_row_start += linesize * 2; + break; + default: + break; + } + while (y >= gif->fh) { + y = 4 >> pass; + ptr_row_start = ptr_base + linesize * y; + pass++; + } + } else { + ptr_row_start += linesize; + } + ptr = ptr_row_start; + } + } + + key = get_key(gif, curr_size, &sub_len, &shift, &byte); + + if (key == stop_code || key >= LZW_TABLE_SIZE) + break; + + if (key == clear_code) { + curr_size = key_size + 1; + slot = new_codes; + top_slot = 1 << curr_size; + first_value = last_key = -1; + sp = p_stack; + continue; + } + + curr_code = key; + /* + * If the current code is a code that will be added to the decoding + * dictionary, it is composed of the data list corresponding to the + * previous key and its first data. + * */ + if (curr_code == slot && first_value >= 0) { + *sp++ = first_value; + curr_code = last_key; + }else if(curr_code >= slot) + break; + + while (curr_code >= new_codes) { + *sp++ = p_suffix[curr_code]; + curr_code = p_prefix[curr_code]; + } + *sp++ = curr_code; + + /* Add code to decoding dictionary */ + if (slot < top_slot && last_key >= 0) { + p_suffix[slot] = curr_code; + p_prefix[slot++] = last_key; + } + first_value = curr_code; + last_key = key; + if (slot >= top_slot) { + if (curr_size < LZW_MAXBITS) { + top_slot <<= 1; + curr_size += 1; + } + } + } + + if (key == stop_code) f_gif_read(gif, &sub_len, 1); /* Must be zero! */ + f_gif_seek(gif, end, LV_FS_SEEK_SET); + return ret; +} +#else +static Table * +new_table(int key_size) +{ + int key; + int init_bulk = MAX(1 << (key_size + 1), 0x100); + Table * table = lv_malloc(sizeof(*table) + sizeof(Entry) * init_bulk); + if(table) { + table->bulk = init_bulk; + table->nentries = (1 << key_size) + 2; + table->entries = (Entry *) &table[1]; + for(key = 0; key < (1 << key_size); key++) + table->entries[key] = (Entry) { + 1, 0xFFF, key + }; + } + return table; +} + +/* Add table entry. Return value: + * 0 on success + * +1 if key size must be incremented after this addition + * -1 if could not realloc table */ +static int +add_entry(Table ** tablep, uint16_t length, uint16_t prefix, uint8_t suffix) +{ + Table * table = *tablep; + if(table->nentries == table->bulk) { + table->bulk *= 2; + table = lv_realloc(table, sizeof(*table) + sizeof(Entry) * table->bulk); + if(!table) return -1; + table->entries = (Entry *) &table[1]; + *tablep = table; + } + table->entries[table->nentries] = (Entry) { + length, prefix, suffix + }; + table->nentries++; + if((table->nentries & (table->nentries - 1)) == 0) + return 1; + return 0; +} + /* Compute output index of y-th input line, in frame of height h. */ static int interlaced_line_index(int h, int y) @@ -370,15 +510,15 @@ interlaced_line_index(int h, int y) int p; /* number of lines in current pass */ p = (h - 1) / 8 + 1; - if (y < p) /* pass 1 */ + if(y < p) /* pass 1 */ return y * 8; y -= p; p = (h - 5) / 8 + 1; - if (y < p) /* pass 2 */ + if(y < p) /* pass 2 */ return y * 8 + 4; y -= p; p = (h - 3) / 4 + 1; - if (y < p) /* pass 3 */ + if(y < p) /* pass 3 */ return y * 4 + 2; y -= p; /* pass 4 */ @@ -388,14 +528,14 @@ interlaced_line_index(int h, int y) /* Decompress image pixels. * Return 0 on success or -1 on out-of-memory (w.r.t. LZW code table). */ static int -read_image_data(gd_GIF *gif, int interlace) +read_image_data(gd_GIF * gif, int interlace) { uint8_t sub_len, shift, byte; - int init_key_size, key_size, table_is_full=0; - int frm_off, frm_size, str_len=0, i, p, x, y; + int init_key_size, key_size, table_is_full = 0; + int frm_off, frm_size, str_len = 0, i, p, x, y; uint16_t key, clear, stop; int ret; - Table *table; + Table * table; Entry entry = {0}; size_t start, end; @@ -414,55 +554,58 @@ read_image_data(gd_GIF *gif, int interlace) key = get_key(gif, key_size, &sub_len, &shift, &byte); /* clear code */ frm_off = 0; ret = 0; - frm_size = gif->fw*gif->fh; - while (frm_off < frm_size) { - if (key == clear) { + frm_size = gif->fw * gif->fh; + while(frm_off < frm_size) { + if(key == clear) { key_size = init_key_size; table->nentries = (1 << (key_size - 1)) + 2; table_is_full = 0; - } else if (!table_is_full) { + } + else if(!table_is_full) { ret = add_entry(&table, str_len + 1, key, entry.suffix); - if (ret == -1) { - lv_mem_free(table); + if(ret == -1) { + lv_free(table); return -1; } - if (table->nentries == 0x1000) { + if(table->nentries == 0x1000) { ret = 0; table_is_full = 1; } } key = get_key(gif, key_size, &sub_len, &shift, &byte); - if (key == clear) continue; - if (key == stop || key == 0x1000) break; - if (ret == 1) key_size++; + if(key == clear) continue; + if(key == stop || key == 0x1000) break; + if(ret == 1) key_size++; entry = table->entries[key]; str_len = entry.length; - for (i = 0; i < str_len; i++) { + for(i = 0; i < str_len; i++) { p = frm_off + entry.length - 1; x = p % gif->fw; y = p / gif->fw; - if (interlace) + if(interlace) y = interlaced_line_index((int) gif->fh, y); gif->frame[(gif->fy + y) * gif->width + gif->fx + x] = entry.suffix; - if (entry.prefix == 0xFFF) + if(entry.prefix == 0xFFF) break; else entry = table->entries[entry.prefix]; } frm_off += str_len; - if (key < table->nentries - 1 && !table_is_full) + if(key < table->nentries - 1 && !table_is_full) table->entries[table->nentries - 1].suffix = entry.suffix; } - lv_mem_free(table); - if (key == stop) f_gif_read(gif, &sub_len, 1); /* Must be zero! */ + lv_free(table); + if(key == stop) f_gif_read(gif, &sub_len, 1); /* Must be zero! */ f_gif_seek(gif, end, LV_FS_SEEK_SET); return 0; } +#endif + /* Read image. * Return 0 on success or -1 on out-of-memory (w.r.t. LZW code table). */ static int -read_image(gd_GIF *gif) +read_image(gd_GIF * gif) { uint8_t fisrz; int interlace; @@ -476,109 +619,92 @@ read_image(gd_GIF *gif) interlace = fisrz & 0x40; /* Ignore Sort Flag. */ /* Local Color Table? */ - if (fisrz & 0x80) { + if(fisrz & 0x80) { /* Read LCT */ gif->lct.size = 1 << ((fisrz & 0x07) + 1); f_gif_read(gif, gif->lct.colors, 3 * gif->lct.size); gif->palette = &gif->lct; - } else + } + else gif->palette = &gif->gct; /* Image Data. */ return read_image_data(gif, interlace); } static void -render_frame_rect(gd_GIF *gif, uint8_t *buffer) +render_frame_rect(gd_GIF * gif, uint8_t * buffer) { - int i, j, k; - uint8_t index, *color; - i = gif->fy * gif->width + gif->fx; - for (j = 0; j < gif->fh; j++) { - for (k = 0; k < gif->fw; k++) { + int i = gif->fy * gif->width + gif->fx; +#ifdef GIFDEC_RENDER_FRAME + GIFDEC_RENDER_FRAME(&buffer[i * 4], gif->fw, gif->fh, gif->width, + &gif->frame[i], gif->palette->colors, + gif->gce.transparency ? gif->gce.tindex : 0x100); +#else + int j, k; + uint8_t index, * color; + + for(j = 0; j < gif->fh; j++) { + for(k = 0; k < gif->fw; k++) { index = gif->frame[(gif->fy + j) * gif->width + gif->fx + k]; - color = &gif->palette->colors[index*3]; - if (!gif->gce.transparency || index != gif->gce.tindex) { -#if LV_COLOR_DEPTH == 32 - buffer[(i+k)*4 + 0] = *(color + 2); - buffer[(i+k)*4 + 1] = *(color + 1); - buffer[(i+k)*4 + 2] = *(color + 0); - buffer[(i+k)*4 + 3] = 0xFF; -#elif LV_COLOR_DEPTH == 16 - lv_color_t c = lv_color_make(*(color + 0), *(color + 1), *(color + 2)); - buffer[(i+k)*3 + 0] = c.full & 0xff; - buffer[(i+k)*3 + 1] = (c.full >> 8) & 0xff; - buffer[(i+k)*3 + 2] = 0xff; -#elif LV_COLOR_DEPTH == 8 - lv_color_t c = lv_color_make(*(color + 0), *(color + 1), *(color + 2)); - buffer[(i+k)*2 + 0] = c.full; - buffer[(i+k)*2 + 1] = 0xff; -#elif LV_COLOR_DEPTH == 1 - uint8_t b = (*(color + 0)) | (*(color + 1)) | (*(color + 2)); - buffer[(i+k)*2 + 0] = b > 128 ? 1 : 0; - buffer[(i+k)*2 + 1] = 0xff; -#endif + color = &gif->palette->colors[index * 3]; + if(!gif->gce.transparency || index != gif->gce.tindex) { + buffer[(i + k) * 4 + 0] = *(color + 2); + buffer[(i + k) * 4 + 1] = *(color + 1); + buffer[(i + k) * 4 + 2] = *(color + 0); + buffer[(i + k) * 4 + 3] = 0xFF; } } i += gif->width; } +#endif } static void -dispose(gd_GIF *gif) +dispose(gd_GIF * gif) { - int i, j, k; - uint8_t *bgcolor; - switch (gif->gce.disposal) { - case 2: /* Restore to background color. */ - bgcolor = &gif->palette->colors[gif->bgindex*3]; + int i; + uint8_t * bgcolor; + switch(gif->gce.disposal) { + case 2: /* Restore to background color. */ + bgcolor = &gif->palette->colors[gif->bgindex * 3]; - uint8_t opa = 0xff; - if(gif->gce.transparency) opa = 0x00; + uint8_t opa = 0xff; + if(gif->gce.transparency) opa = 0x00; - i = gif->fy * gif->width + gif->fx; - for (j = 0; j < gif->fh; j++) { - for (k = 0; k < gif->fw; k++) { -#if LV_COLOR_DEPTH == 32 - gif->canvas[(i+k)*4 + 0] = *(bgcolor + 2); - gif->canvas[(i+k)*4 + 1] = *(bgcolor + 1); - gif->canvas[(i+k)*4 + 2] = *(bgcolor + 0); - gif->canvas[(i+k)*4 + 3] = opa; -#elif LV_COLOR_DEPTH == 16 - lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2)); - gif->canvas[(i+k)*3 + 0] = c.full & 0xff; - gif->canvas[(i+k)*3 + 1] = (c.full >> 8) & 0xff; - gif->canvas[(i+k)*3 + 2] = opa; -#elif LV_COLOR_DEPTH == 8 - lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2)); - gif->canvas[(i+k)*2 + 0] = c.full; - gif->canvas[(i+k)*2 + 1] = opa; -#elif LV_COLOR_DEPTH == 1 - uint8_t b = (*(bgcolor + 0)) | (*(bgcolor + 1)) | (*(bgcolor + 2)); - gif->canvas[(i+k)*2 + 0] = b > 128 ? 1 : 0; - gif->canvas[(i+k)*2 + 1] = opa; -#endif + i = gif->fy * gif->width + gif->fx; +#ifdef GIFDEC_FILL_BG + GIFDEC_FILL_BG(&(gif->canvas[i * 4]), gif->fw, gif->fh, gif->width, bgcolor, opa); +#else + int j, k; + for(j = 0; j < gif->fh; j++) { + for(k = 0; k < gif->fw; k++) { + gif->canvas[(i + k) * 4 + 0] = *(bgcolor + 2); + gif->canvas[(i + k) * 4 + 1] = *(bgcolor + 1); + gif->canvas[(i + k) * 4 + 2] = *(bgcolor + 0); + gif->canvas[(i + k) * 4 + 3] = opa; + } + i += gif->width; } - i += gif->width; - } - break; - case 3: /* Restore to previous, i.e., don't update canvas.*/ - break; - default: - /* Add frame non-transparent pixels to canvas. */ - render_frame_rect(gif, gif->canvas); +#endif + break; + case 3: /* Restore to previous, i.e., don't update canvas.*/ + break; + default: + /* Add frame non-transparent pixels to canvas. */ + render_frame_rect(gif, gif->canvas); } } /* Return 1 if got a frame; 0 if got GIF trailer; -1 if error. */ int -gd_get_frame(gd_GIF *gif) +gd_get_frame(gd_GIF * gif) { char sep; dispose(gif); f_gif_read(gif, &sep, 1); - while (sep != ',') { - if (sep == ';') { + while(sep != ',') { + if(sep == ';') { f_gif_seek(gif, gif->anim_start, LV_FS_SEEK_SET); if(gif->loop_count == 1 || gif->loop_count < 0) { return 0; @@ -587,43 +713,34 @@ gd_get_frame(gd_GIF *gif) gif->loop_count--; } } - else if (sep == '!') + else if(sep == '!') read_ext(gif); else return -1; f_gif_read(gif, &sep, 1); } - if (read_image(gif) == -1) + if(read_image(gif) == -1) return -1; return 1; } void -gd_render_frame(gd_GIF *gif, uint8_t *buffer) +gd_render_frame(gd_GIF * gif, uint8_t * buffer) { -// uint32_t i; -// uint32_t j; -// for(i = 0, j = 0; i < gif->width * gif->height * 3; i+= 3, j+=4) { -// buffer[j + 0] = gif->canvas[i + 2]; -// buffer[j + 1] = gif->canvas[i + 1]; -// buffer[j + 2] = gif->canvas[i + 0]; -// buffer[j + 3] = 0xFF; -// } -// memcpy(buffer, gif->canvas, gif->width * gif->height * 3); render_frame_rect(gif, buffer); } void -gd_rewind(gd_GIF *gif) +gd_rewind(gd_GIF * gif) { gif->loop_count = -1; f_gif_seek(gif, gif->anim_start, LV_FS_SEEK_SET); } void -gd_close_gif(gd_GIF *gif) +gd_close_gif(gd_GIF * gif) { f_gif_close(gif); - lv_mem_free(gif); + lv_free(gif); } static bool f_gif_open(gd_GIF * gif, const void * path, bool is_file) @@ -636,7 +753,8 @@ static bool f_gif_open(gd_GIF * gif, const void * path, bool is_file) lv_fs_res_t res = lv_fs_open(&gif->fd, path, LV_FS_MODE_RD); if(res != LV_FS_RES_OK) return false; else return true; - } else { + } + else { gif->data = path; return true; } @@ -646,8 +764,8 @@ static void f_gif_read(gd_GIF * gif, void * buf, size_t len) { if(gif->is_file) { lv_fs_read(&gif->fd, buf, len, NULL); - } else - { + } + else { memcpy(buf, &gif->data[gif->f_rw_p], len); gif->f_rw_p += len; } @@ -660,7 +778,8 @@ static int f_gif_seek(gd_GIF * gif, size_t pos, int k) uint32_t x; lv_fs_tell(&gif->fd, &x); return x; - } else { + } + else { if(k == LV_FS_SEEK_CUR) gif->f_rw_p += pos; else if(k == LV_FS_SEEK_SET) gif->f_rw_p = pos; return gif->f_rw_p; diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/gifdec.h b/lib/libesp32_lvgl/lvgl/src/libs/gif/gifdec.h similarity index 51% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/gif/gifdec.h rename to lib/libesp32_lvgl/lvgl/src/libs/gif/gifdec.h index b68fab5d4..71cb9ffbf 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/gifdec.h +++ b/lib/libesp32_lvgl/lvgl/src/libs/gif/gifdec.h @@ -2,16 +2,16 @@ #define GIFDEC_H #include -#include "../../../misc/lv_fs.h" +#include "../../misc/lv_fs.h" #if LV_USE_GIF -typedef struct gd_Palette { +typedef struct _gd_Palette { int size; uint8_t colors[0x100 * 3]; } gd_Palette; -typedef struct gd_GCE { +typedef struct _gd_GCE { uint16_t delay; uint8_t tindex; uint8_t disposal; @@ -21,7 +21,7 @@ typedef struct gd_GCE { -typedef struct gd_GIF { +typedef struct _gd_GIF { lv_fs_file_t fd; const char * data; uint8_t is_file; @@ -31,29 +31,32 @@ typedef struct gd_GIF { uint16_t depth; int32_t loop_count; gd_GCE gce; - gd_Palette *palette; + gd_Palette * palette; gd_Palette lct, gct; void (*plain_text)( - struct gd_GIF *gif, uint16_t tx, uint16_t ty, + struct _gd_GIF * gif, uint16_t tx, uint16_t ty, uint16_t tw, uint16_t th, uint8_t cw, uint8_t ch, uint8_t fg, uint8_t bg ); - void (*comment)(struct gd_GIF *gif); - void (*application)(struct gd_GIF *gif, char id[8], char auth[3]); + void (*comment)(struct _gd_GIF * gif); + void (*application)(struct _gd_GIF * gif, char id[8], char auth[3]); uint16_t fx, fy, fw, fh; uint8_t bgindex; - uint8_t *canvas, *frame; + uint8_t * canvas, * frame; + #if LV_GIF_CACHE_DECODE_DATA + uint8_t *lzw_cache; + #endif } gd_GIF; -gd_GIF * gd_open_gif_file(const char *fname); +gd_GIF * gd_open_gif_file(const char * fname); -gd_GIF * gd_open_gif_data(const void *data); +gd_GIF * gd_open_gif_data(const void * data); -void gd_render_frame(gd_GIF *gif, uint8_t *buffer); +void gd_render_frame(gd_GIF * gif, uint8_t * buffer); -int gd_get_frame(gd_GIF *gif); -void gd_rewind(gd_GIF *gif); -void gd_close_gif(gd_GIF *gif); +int gd_get_frame(gd_GIF * gif); +void gd_rewind(gd_GIF * gif); +void gd_close_gif(gd_GIF * gif); #endif /*LV_USE_GIF*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/gif/gifdec_mve.h b/lib/libesp32_lvgl/lvgl/src/libs/gif/gifdec_mve.h new file mode 100644 index 000000000..6d8339349 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/gif/gifdec_mve.h @@ -0,0 +1,140 @@ +/** + * @file gifdec_mve.h + * + */ + +#ifndef GIFDEC_MVE_H +#define GIFDEC_MVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include "../../misc/lv_color.h" + +/********************* + * DEFINES + *********************/ + +#define GIFDEC_FILL_BG(dst, w, h, stride, color, opa) \ + _gifdec_fill_bg_mve(dst, w, h, stride, color, opa) + +#define GIFDEC_RENDER_FRAME(dst, w, h, stride, frame, pattern, tindex) \ + _gifdec_render_frame_mve(dst, w, h, stride, frame, pattern, tindex) + +/********************** + * MACROS + **********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +static inline void _gifdec_fill_bg_mve(uint8_t * dst, uint16_t w, uint16_t h, uint16_t stride, uint8_t * color, + uint8_t opa) +{ + lv_color32_t c = lv_color32_make(*(color + 0), *(color + 1), *(color + 2), opa); + uint32_t color_32 = *(uint32_t *)&c; + + __asm volatile( + ".p2align 2 \n" + "vdup.32 q0, %[src] \n" + "3: \n" + "mov r0, %[dst] \n" + + "wlstp.32 lr, %[w], 1f \n" + "2: \n" + + "vstrw.32 q0, [r0], #16 \n" + "letp lr, 2b \n" + "1: \n" + "add %[dst], %[iTargetStride] \n" + "subs %[h], #1 \n" + "bne 3b \n" + : [dst] "+r"(dst), + [h] "+r"(h) + : [src] "r"(color_32), + [w] "r"(w), + [iTargetStride] "r"(stride * sizeof(uint32_t)) + : "r0", "q0", "memory", "r14", "cc"); +} + +static inline void _gifdec_render_frame_mve(uint8_t * dst, uint16_t w, uint16_t h, uint16_t stride, uint8_t * frame, + uint8_t * pattern, uint16_t tindex) +{ + if(w == 0 || h == 0) { + return; + } + + __asm volatile( + "vmov.u16 q3, #255 \n" + "vshl.u16 q3, q3, #8 \n" /* left shift 8 for a*/ + + "mov r0, #2 \n" + "vidup.u16 q6, r0, #4 \n" /* [2, 6, 10, 14, 18, 22, 26, 30] */ + "mov r0, #0 \n" + "vidup.u16 q7, r0, #4 \n" /* [0, 4, 8, 12, 16, 20, 24, 28] */ + + "3: \n" + "mov r1, %[dst] \n" + "mov r2, %[frame] \n" + + "wlstp.16 lr, %[w], 1f \n" + "2: \n" + + "mov r0, #3 \n" + "vldrb.u16 q4, [r2], #8 \n" + "vmul.u16 q5, q4, r0 \n" + + "mov r0, #1 \n" + "vldrb.u16 q2, [%[pattern], q5] \n" /* load 8 pixel r*/ + + "vadd.u16 q5, q5, r0 \n" + "vldrb.u16 q1, [%[pattern], q5] \n" /* load 8 pixel g*/ + + "vadd.u16 q5, q5, r0 \n" + "vldrb.u16 q0, [%[pattern], q5] \n" /* load 8 pixel b*/ + + "vshl.u16 q1, q1, #8 \n" /* left shift 8 for g*/ + + "vorr.u16 q0, q0, q1 \n" /* make 8 pixel gb*/ + "vorr.u16 q1, q2, q3 \n" /* make 8 pixel ar*/ + + "vcmp.i16 ne, q4, %[tindex] \n" + "vpstt \n" + "vstrht.16 q0, [r1, q7] \n" + "vstrht.16 q1, [r1, q6] \n" + "add r1, r1, #32 \n" + + "letp lr, 2b \n" + + "1: \n" + "mov r0, %[stride], LSL #2 \n" + "add %[dst], r0 \n" + "add %[frame], %[stride] \n" + "subs %[h], #1 \n" + "bne 3b \n" + + : [dst] "+r"(dst), + [frame] "+r"(frame), + [h] "+r"(h) + : [pattern] "r"(pattern), + [w] "r"(w), + [stride] "r"(stride), + [tindex] "r"(tindex) + : "r0", "r1", "r2", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "memory", "r14", "cc"); +} + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*GIFDEC_MVE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/lv_gif.c b/lib/libesp32_lvgl/lvgl/src/libs/gif/lv_gif.c similarity index 74% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/gif/lv_gif.c rename to lib/libesp32_lvgl/lvgl/src/libs/gif/lv_gif.c index 2bd9e013c..1ab48e30f 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/gif/lv_gif.c +++ b/lib/libesp32_lvgl/lvgl/src/libs/gif/lv_gif.c @@ -20,7 +20,6 @@ * TYPEDEFS **********************/ - /********************** * STATIC PROTOTYPES **********************/ @@ -31,11 +30,13 @@ static void next_frame_task_cb(lv_timer_t * t); /********************** * STATIC VARIABLES **********************/ + const lv_obj_class_t lv_gif_class = { .constructor_cb = lv_gif_constructor, .destructor_cb = lv_gif_destructor, .instance_size = sizeof(lv_gif_t), - .base_class = &lv_img_class + .base_class = &lv_image_class, + .name = "gif", }; /********************** @@ -61,32 +62,32 @@ void lv_gif_set_src(lv_obj_t * obj, const void * src) /*Close previous gif if any*/ if(gifobj->gif) { - lv_img_cache_invalidate_src(&gifobj->imgdsc); + lv_image_cache_drop(lv_image_get_src(obj)); + gd_close_gif(gifobj->gif); gifobj->gif = NULL; gifobj->imgdsc.data = NULL; } - if(lv_img_src_get_type(src) == LV_IMG_SRC_VARIABLE) { - const lv_img_dsc_t * img_dsc = src; + if(lv_image_src_get_type(src) == LV_IMAGE_SRC_VARIABLE) { + const lv_image_dsc_t * img_dsc = src; gifobj->gif = gd_open_gif_data(img_dsc->data); } - else if(lv_img_src_get_type(src) == LV_IMG_SRC_FILE) { + else if(lv_image_src_get_type(src) == LV_IMAGE_SRC_FILE) { gifobj->gif = gd_open_gif_file(src); } if(gifobj->gif == NULL) { - LV_LOG_WARN("Could't load the source"); + LV_LOG_WARN("Couldn't load the source"); return; } gifobj->imgdsc.data = gifobj->gif->canvas; - gifobj->imgdsc.header.always_zero = 0; - gifobj->imgdsc.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA; + gifobj->imgdsc.header.cf = LV_COLOR_FORMAT_ARGB8888; gifobj->imgdsc.header.h = gifobj->gif->height; gifobj->imgdsc.header.w = gifobj->gif->width; gifobj->last_call = lv_tick_get(); - lv_img_set_src(obj, &gifobj->imgdsc); + lv_image_set_src(obj, &gifobj->imgdsc); lv_timer_resume(gifobj->timer); lv_timer_reset(gifobj->timer); @@ -98,11 +99,35 @@ void lv_gif_set_src(lv_obj_t * obj, const void * src) void lv_gif_restart(lv_obj_t * obj) { lv_gif_t * gifobj = (lv_gif_t *) obj; + + if(gifobj->gif == NULL) { + LV_LOG_WARN("Gif resource not loaded correctly"); + return; + } + gd_rewind(gifobj->gif); lv_timer_resume(gifobj->timer); lv_timer_reset(gifobj->timer); } +void lv_gif_pause(lv_obj_t * obj) +{ + lv_gif_t * gifobj = (lv_gif_t *) obj; + lv_timer_pause(gifobj->timer); +} + +void lv_gif_resume(lv_obj_t * obj) +{ + lv_gif_t * gifobj = (lv_gif_t *) obj; + + if(gifobj->gif == NULL) { + LV_LOG_WARN("Gif resource not loaded correctly"); + return; + } + + lv_timer_resume(gifobj->timer); +} + /********************** * STATIC FUNCTIONS **********************/ @@ -122,10 +147,12 @@ static void lv_gif_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { LV_UNUSED(class_p); lv_gif_t * gifobj = (lv_gif_t *) obj; - lv_img_cache_invalidate_src(&gifobj->imgdsc); + + lv_image_cache_drop(lv_image_get_src(obj)); + if(gifobj->gif) gd_close_gif(gifobj->gif); - lv_timer_del(gifobj->timer); + lv_timer_delete(gifobj->timer); } static void next_frame_task_cb(lv_timer_t * t) @@ -140,14 +167,14 @@ static void next_frame_task_cb(lv_timer_t * t) int has_next = gd_get_frame(gifobj->gif); if(has_next == 0) { /*It was the last repeat*/ - lv_res_t res = lv_event_send(obj, LV_EVENT_READY, NULL); + lv_result_t res = lv_obj_send_event(obj, LV_EVENT_READY, NULL); lv_timer_pause(t); if(res != LV_FS_RES_OK) return; } gd_render_frame(gifobj->gif, (uint8_t *)gifobj->imgdsc.data); - lv_img_cache_invalidate_src(lv_img_get_src(obj)); + lv_image_cache_drop(lv_image_get_src(obj)); lv_obj_invalidate(obj); } diff --git a/lib/libesp32_lvgl/lvgl/src/libs/gif/lv_gif.h b/lib/libesp32_lvgl/lvgl/src/libs/gif/lv_gif.h new file mode 100644 index 000000000..9a7ca7a8e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/gif/lv_gif.h @@ -0,0 +1,87 @@ +/** + * @file lv_gif.h + * + */ + +#ifndef LV_GIF_H +#define LV_GIF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../../lvgl.h" +#if LV_USE_GIF + +#include "gifdec.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_image_t img; + gd_GIF * gif; + lv_timer_t * timer; + lv_image_dsc_t imgdsc; + uint32_t last_call; +} lv_gif_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_gif_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a gif object + * @param parent pointer to an object, it will be the parent of the new gif. + * @return pointer to the gif obj + */ +lv_obj_t * lv_gif_create(lv_obj_t * parent); + +/** + * Set the gif data to display on the object + * @param obj pointer to a gif object + * @param src 1) pointer to an ::lv_image_dsc_t descriptor (which contains gif raw data) or + * 2) path to a gif file (e.g. "S:/dir/anim.gif") + */ +void lv_gif_set_src(lv_obj_t * obj, const void * src); + +/** + * Restart a gif animation. + * @param obj pointer to a gif obj + */ +void lv_gif_restart(lv_obj_t * obj); + +/** + * Pause a gif animation. + * @param obj pointer to a gif obj + */ +void lv_gif_pause(lv_obj_t * obj); + +/** + * Resume a gif animation. + * @param obj pointer to a gif obj + */ +void lv_gif_resume(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_GIF*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_GIF_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c b/lib/libesp32_lvgl/lvgl/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c new file mode 100644 index 000000000..59803323c --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c @@ -0,0 +1,459 @@ +/** + * @file lv_libjpeg_turbo.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_LIBJPEG_TURBO + +#include "lv_libjpeg_turbo.h" +#include +#include +#include + +/********************* + * DEFINES + *********************/ +#define JPEG_PIXEL_SIZE 3 /* RGB888 */ +#define JPEG_SIGNATURE 0xFFD8FF +#define IS_JPEG_SIGNATURE(x) (((x) & 0x00FFFFFF) == JPEG_SIGNATURE) + +/********************** + * TYPEDEFS + **********************/ +typedef struct error_mgr_s { + struct jpeg_error_mgr pub; + jmp_buf jb; +} error_mgr_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); +static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); +static lv_draw_buf_t * decode_jpeg_file(const char * filename); +static bool get_jpeg_size(const char * filename, uint32_t * width, uint32_t * height); +static void error_exit(j_common_ptr cinfo); +static void jpeg_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data); +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Register the JPEG decoder functions in LVGL + */ +void lv_libjpeg_turbo_init(void) +{ + lv_image_decoder_t * dec = lv_image_decoder_create(); + lv_image_decoder_set_info_cb(dec, decoder_info); + lv_image_decoder_set_open_cb(dec, decoder_open); + lv_image_decoder_set_close_cb(dec, decoder_close); + lv_image_decoder_set_cache_free_cb(dec, (lv_cache_free_cb_t)jpeg_decoder_cache_free_cb); +} + +void lv_libjpeg_turbo_deinit(void) +{ + lv_image_decoder_t * dec = NULL; + while((dec = lv_image_decoder_get_next(dec)) != NULL) { + if(dec->info_cb == decoder_info) { + lv_image_decoder_delete(dec); + break; + } + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Get info about a JPEG image + * @param src can be file name or pointer to a C array + * @param header store the info here + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't get the info + */ +static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) +{ + LV_UNUSED(decoder); /*Unused*/ + lv_image_src_t src_type = lv_image_src_get_type(src); /*Get the source type*/ + + /*If it's a JPEG file...*/ + if(src_type == LV_IMAGE_SRC_FILE) { + const char * fn = src; + + lv_fs_file_t f; + lv_fs_res_t res = lv_fs_open(&f, fn, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) { + LV_LOG_WARN("Can't open file: %s", fn); + return LV_RESULT_INVALID; + } + + uint32_t jpg_signature = 0; + uint32_t rn; + lv_fs_read(&f, &jpg_signature, sizeof(jpg_signature), &rn); + lv_fs_close(&f); + + if(rn != sizeof(jpg_signature)) { + LV_LOG_WARN("file: %s signature len = %" LV_PRIu32 " error", fn, rn); + return LV_RESULT_INVALID; + } + + bool is_jpeg_ext = (lv_strcmp(lv_fs_get_ext(fn), "jpg") == 0) + || (lv_strcmp(lv_fs_get_ext(fn), "jpeg") == 0); + + if(!IS_JPEG_SIGNATURE(jpg_signature)) { + if(is_jpeg_ext) { + LV_LOG_WARN("file: %s signature = 0X%" LV_PRIX32 " error", fn, jpg_signature); + } + return LV_RESULT_INVALID; + } + + uint32_t width; + uint32_t height; + + if(!get_jpeg_size(fn, &width, &height)) { + return LV_RESULT_INVALID; + } + + /*Save the data in the header*/ + header->cf = LV_COLOR_FORMAT_RGB888; + header->w = width; + header->h = height; + + return LV_RESULT_OK; + } + + return LV_RESULT_INVALID; /*If didn't succeeded earlier then it's an error*/ +} + +/** + * Open a JPEG image and return the decided image + * @param decoder pointer to the decoder + * @param dsc pointer to the decoder descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image + */ +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); /*Unused*/ + + /*If it's a JPEG file...*/ + if(dsc->src_type == LV_IMAGE_SRC_FILE) { + const char * fn = dsc->src; + lv_draw_buf_t * decoded = decode_jpeg_file(fn); + if(decoded == NULL) { + LV_LOG_WARN("decode jpeg file failed"); + return LV_RESULT_INVALID; + } + + dsc->decoded = decoded; + + if(dsc->args.no_cache) return LV_RES_OK; + +#if LV_CACHE_DEF_SIZE > 0 + lv_image_cache_data_t search_key; + search_key.src_type = dsc->src_type; + search_key.src = dsc->src; + search_key.slot.size = decoded->data_size; + + lv_cache_entry_t * entry = lv_image_decoder_add_to_cache(decoder, &search_key, decoded, NULL); + + if(entry == NULL) { + lv_draw_buf_destroy(decoded); + return LV_RESULT_INVALID; + } + dsc->cache_entry = entry; +#endif + return LV_RESULT_OK; /*If not returned earlier then it failed*/ + } + + return LV_RESULT_INVALID; /*If not returned earlier then it failed*/ +} + +/** + * Free the allocated resources + */ +static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); /*Unused*/ + + if(dsc->args.no_cache || LV_CACHE_DEF_SIZE == 0) + lv_draw_buf_destroy((lv_draw_buf_t *)dsc->decoded); + else + lv_cache_release(dsc->cache, dsc->cache_entry, NULL); +} + +static uint8_t * alloc_file(const char * filename, uint32_t * size) +{ + uint8_t * data = NULL; + lv_fs_file_t f; + uint32_t data_size; + uint32_t rn; + lv_fs_res_t res; + + *size = 0; + + res = lv_fs_open(&f, filename, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) { + LV_LOG_WARN("can't open %s", filename); + return NULL; + } + + res = lv_fs_seek(&f, 0, LV_FS_SEEK_END); + if(res != LV_FS_RES_OK) { + goto failed; + } + + res = lv_fs_tell(&f, &data_size); + if(res != LV_FS_RES_OK) { + goto failed; + } + + res = lv_fs_seek(&f, 0, LV_FS_SEEK_SET); + if(res != LV_FS_RES_OK) { + goto failed; + } + + /*Read file to buffer*/ + data = lv_malloc(data_size); + if(data == NULL) { + LV_LOG_WARN("malloc failed for data"); + goto failed; + } + + res = lv_fs_read(&f, data, data_size, &rn); + + if(res == LV_FS_RES_OK && rn == data_size) { + *size = rn; + } + else { + LV_LOG_WARN("read file failed"); + lv_free(data); + data = NULL; + } + +failed: + lv_fs_close(&f); + + return data; +} + +static lv_draw_buf_t * decode_jpeg_file(const char * filename) +{ + /* This struct contains the JPEG decompression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + */ + struct jpeg_decompress_struct cinfo; + /* We use our private extension JPEG error handler. + * Note that this struct must live as long as the main JPEG parameter + * struct, to avoid dangling-pointer problems. + */ + error_mgr_t jerr; + + /* More stuff */ + JSAMPARRAY buffer; /* Output row buffer */ + int row_stride; /* physical row width in output buffer */ + + lv_draw_buf_t * decoded = NULL; + + /* In this example we want to open the input file before doing anything else, + * so that the setjmp() error recovery below can assume the file is open. + * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that + * requires it in order to read binary files. + */ + + uint32_t data_size; + uint8_t * data = alloc_file(filename, &data_size); + if(data == NULL) { + LV_LOG_WARN("can't load file %s", filename); + return NULL; + } + + /* allocate and initialize JPEG decompression object */ + + /* We set up the normal JPEG error routines, then override error_exit. */ + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = error_exit; + /* Establish the setjmp return context for my_error_exit to use. */ + if(setjmp(jerr.jb)) { + + LV_LOG_WARN("decoding error"); + + if(decoded) { + lv_draw_buf_destroy(decoded); + } + + /* If we get here, the JPEG code has signaled an error. + * We need to clean up the JPEG object, close the input file, and return. + */ + jpeg_destroy_decompress(&cinfo); + lv_free(data); + return NULL; + } + /* Now we can initialize the JPEG decompression object. */ + jpeg_create_decompress(&cinfo); + + /* specify data source (eg, a file or buffer) */ + + jpeg_mem_src(&cinfo, data, data_size); + + /* read file parameters with jpeg_read_header() */ + + jpeg_read_header(&cinfo, TRUE); + + /* We can ignore the return value from jpeg_read_header since + * (a) suspension is not possible with the stdio data source, and + * (b) we passed TRUE to reject a tables-only JPEG file as an error. + * See libjpeg.doc for more info. + */ + + /* set parameters for decompression */ + + cinfo.out_color_space = JCS_EXT_BGR; + + /* In this example, we don't need to change any of the defaults set by + * jpeg_read_header(), so we do nothing here. + */ + + /* Start decompressor */ + + jpeg_start_decompress(&cinfo); + + /* We can ignore the return value since suspension is not possible + * with the stdio data source. + */ + + /* We may need to do some setup of our own at this point before reading + * the data. After jpeg_start_decompress() we have the correct scaled + * output image dimensions available, as well as the output colormap + * if we asked for color quantization. + * In this example, we need to make an output work buffer of the right size. + */ + /* JSAMPLEs per row in output buffer */ + row_stride = cinfo.output_width * cinfo.output_components; + /* Make a one-row-high sample array that will go away when done with image */ + buffer = (*cinfo.mem->alloc_sarray) + ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); + + decoded = lv_draw_buf_create(cinfo.output_width, cinfo.output_height, LV_COLOR_FORMAT_RGB888, LV_STRIDE_AUTO); + if(decoded != NULL) { + uint8_t * cur_pos = decoded->data; + size_t stride = cinfo.output_width * JPEG_PIXEL_SIZE; + + /* while (scan lines remain to be read) */ + /* jpeg_read_scanlines(...); */ + + /* Here we use the library's state variable cinfo.output_scanline as the + * loop counter, so that we don't have to keep track ourselves. + */ + while(cinfo.output_scanline < cinfo.output_height) { + /* jpeg_read_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could ask for + * more than one scanline at a time if that's more convenient. + */ + jpeg_read_scanlines(&cinfo, buffer, 1); + + /* Assume put_scanline_someplace wants a pointer and sample count. */ + lv_memcpy(cur_pos, buffer[0], stride); + cur_pos += decoded->header.stride; + } + } + + /* Finish decompression */ + + jpeg_finish_decompress(&cinfo); + + /* We can ignore the return value since suspension is not possible + * with the stdio data source. + */ + + /* Release JPEG decompression object */ + + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_decompress(&cinfo); + + /* After finish_decompress, we can close the input file. + * Here we postpone it until after no more JPEG errors are possible, + * so as to simplify the setjmp error logic above. (Actually, I don't + * think that jpeg_destroy can do an error exit, but why assume anything...) + */ + lv_free(data); + + /* At this point you may want to check to see whether any corrupt-data + * warnings occurred (test whether jerr.pub.num_warnings is nonzero). + */ + + /* And we're done! */ + return decoded; +} + +static bool get_jpeg_size(const char * filename, uint32_t * width, uint32_t * height) +{ + struct jpeg_decompress_struct cinfo; + error_mgr_t jerr; + + uint8_t * data = NULL; + uint32_t data_size; + data = alloc_file(filename, &data_size); + if(data == NULL) { + return false; + } + + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = error_exit; + + if(setjmp(jerr.jb)) { + LV_LOG_WARN("read jpeg head failed"); + jpeg_destroy_decompress(&cinfo); + lv_free(data); + return false; + } + + jpeg_create_decompress(&cinfo); + + jpeg_mem_src(&cinfo, data, data_size); + + int ret = jpeg_read_header(&cinfo, TRUE); + + if(ret == JPEG_HEADER_OK) { + *width = cinfo.image_width; + *height = cinfo.image_height; + } + else { + LV_LOG_WARN("read jpeg head failed: %d", ret); + } + + jpeg_destroy_decompress(&cinfo); + + lv_free(data); + + return (ret == JPEG_HEADER_OK); +} + +static void error_exit(j_common_ptr cinfo) +{ + error_mgr_t * myerr = (error_mgr_t *)cinfo->err; + (*cinfo->err->output_message)(cinfo); + longjmp(myerr->jb, 1); +} + +static void jpeg_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data) +{ + LV_UNUSED(user_data); + + if(cached_data->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)cached_data->src); + lv_draw_buf_destroy((lv_draw_buf_t *)cached_data->decoded); +} + +#endif /*LV_USE_LIBJPEG_TURBO*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/libjpeg_turbo/lv_libjpeg_turbo.h b/lib/libesp32_lvgl/lvgl/src/libs/libjpeg_turbo/lv_libjpeg_turbo.h new file mode 100644 index 000000000..ff5e5df7d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/libjpeg_turbo/lv_libjpeg_turbo.h @@ -0,0 +1,48 @@ +/** + * @file lv_libjpeg_turbo.h + * + */ + +#ifndef LV_LIBJPEG_TURBO_H +#define LV_LIBJPEG_TURBO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" +#if LV_USE_LIBJPEG_TURBO + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Register the JPEG-Turbo decoder functions in LVGL + */ +void lv_libjpeg_turbo_init(void); + +void lv_libjpeg_turbo_deinit(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_LIBJPEG_TURBO*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_LIBJPEG_TURBO_H*/ \ No newline at end of file diff --git a/lib/libesp32_lvgl/lvgl/src/libs/libpng/lv_libpng.c b/lib/libesp32_lvgl/lvgl/src/libs/libpng/lv_libpng.c new file mode 100644 index 000000000..2776e6c2d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/libpng/lv_libpng.c @@ -0,0 +1,296 @@ +/** + * @file lv_libpng.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_LIBPNG + +#include "lv_libpng.h" +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); +static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); +static lv_draw_buf_t * decode_png_file(const char * filename); + +static void png_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data); +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Register the PNG decoder functions in LVGL + */ +void lv_libpng_init(void) +{ + lv_image_decoder_t * dec = lv_image_decoder_create(); + lv_image_decoder_set_info_cb(dec, decoder_info); + lv_image_decoder_set_open_cb(dec, decoder_open); + lv_image_decoder_set_close_cb(dec, decoder_close); + lv_image_decoder_set_cache_free_cb(dec, (lv_cache_free_cb_t)png_decoder_cache_free_cb); +} + +void lv_libpng_deinit(void) +{ + lv_image_decoder_t * dec = NULL; + while((dec = lv_image_decoder_get_next(dec)) != NULL) { + if(dec->info_cb == decoder_info) { + lv_image_decoder_delete(dec); + break; + } + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Get info about a PNG image + * @param src can be file name or pointer to a C array + * @param header store the info here + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't get the info + */ +static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) +{ + LV_UNUSED(decoder); /*Unused*/ + lv_image_src_t src_type = lv_image_src_get_type(src); /*Get the source type*/ + + /*If it's a PNG file...*/ + if(src_type == LV_IMAGE_SRC_FILE) { + const char * fn = src; + + lv_fs_file_t f; + lv_fs_res_t res = lv_fs_open(&f, fn, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) return LV_RESULT_INVALID; + + /* Read the width and height from the file. They have a constant location: + * [16..19]: width + * [20..23]: height + */ + uint8_t buf[24]; + uint32_t rn; + lv_fs_read(&f, buf, sizeof(buf), &rn); + lv_fs_close(&f); + + if(rn != sizeof(buf)) return LV_RESULT_INVALID; + + const uint8_t magic[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a}; + if(memcmp(buf, magic, sizeof(magic)) != 0) return LV_RESULT_INVALID; + + uint32_t * size = (uint32_t *)&buf[16]; + /*Save the data in the header*/ + header->cf = LV_COLOR_FORMAT_ARGB8888; + /*The width and height are stored in Big endian format so convert them to little endian*/ + header->w = (int32_t)((size[0] & 0xff000000) >> 24) + ((size[0] & 0x00ff0000) >> 8); + header->h = (int32_t)((size[1] & 0xff000000) >> 24) + ((size[1] & 0x00ff0000) >> 8); + + return LV_RESULT_OK; + } + + return LV_RESULT_INVALID; /*If didn't succeeded earlier then it's an error*/ +} + +/** + * Open a PNG image and return the decided image + * @param decoder pointer to the decoder + * @param dsc pointer to the decoder descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image + */ +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); /*Unused*/ + + /*If it's a PNG file...*/ + if(dsc->src_type == LV_IMAGE_SRC_FILE) { + const char * fn = dsc->src; + lv_draw_buf_t * decoded = decode_png_file(fn); + if(decoded == NULL) { + return LV_RESULT_INVALID; + } + + lv_draw_buf_t * adjusted = lv_image_decoder_post_process(dsc, decoded); + if(adjusted == NULL) { + lv_draw_buf_destroy(decoded); + return LV_RESULT_INVALID; + } + + /*The adjusted draw buffer is newly allocated.*/ + if(adjusted != decoded) { + lv_draw_buf_destroy(decoded); + decoded = adjusted; + } + + dsc->decoded = decoded; + + if(dsc->args.no_cache) return LV_RES_OK; + +#if LV_CACHE_DEF_SIZE > 0 + lv_image_cache_data_t search_key; + search_key.src_type = dsc->src_type; + search_key.src = dsc->src; + search_key.slot.size = decoded->data_size; + + lv_cache_entry_t * entry = lv_image_decoder_add_to_cache(decoder, &search_key, decoded, NULL); + + if(entry == NULL) { + lv_draw_buf_destroy(decoded); + return LV_RESULT_INVALID; + } + dsc->cache_entry = entry; +#endif + return LV_RESULT_OK; /*The image is fully decoded. Return with its pointer*/ + } + + return LV_RESULT_INVALID; /*If not returned earlier then it failed*/ +} + +/** + * Free the allocated resources + */ +static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); /*Unused*/ + + if(dsc->args.no_cache || LV_CACHE_DEF_SIZE == 0) + lv_draw_buf_destroy((lv_draw_buf_t *)dsc->decoded); + else + lv_cache_release(dsc->cache, dsc->cache_entry, NULL); +} + +static uint8_t * alloc_file(const char * filename, uint32_t * size) +{ + uint8_t * data = NULL; + lv_fs_file_t f; + uint32_t data_size; + uint32_t rn; + lv_fs_res_t res; + + *size = 0; + + res = lv_fs_open(&f, filename, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) { + LV_LOG_WARN("can't open %s", filename); + return NULL; + } + + res = lv_fs_seek(&f, 0, LV_FS_SEEK_END); + if(res != LV_FS_RES_OK) { + goto failed; + } + + res = lv_fs_tell(&f, &data_size); + if(res != LV_FS_RES_OK) { + goto failed; + } + + res = lv_fs_seek(&f, 0, LV_FS_SEEK_SET); + if(res != LV_FS_RES_OK) { + goto failed; + } + + /*Read file to buffer*/ + data = lv_malloc(data_size); + if(data == NULL) { + LV_LOG_WARN("malloc failed for data"); + goto failed; + } + + res = lv_fs_read(&f, data, data_size, &rn); + + if(res == LV_FS_RES_OK && rn == data_size) { + *size = rn; + } + else { + LV_LOG_WARN("read file failed"); + lv_free(data); + data = NULL; + } + +failed: + lv_fs_close(&f); + + return data; +} + +static lv_draw_buf_t * decode_png_file(const char * filename) +{ + int ret; + + /*Prepare png_image*/ + png_image image; + lv_memzero(&image, sizeof(image)); + image.version = PNG_IMAGE_VERSION; + + uint32_t data_size; + uint8_t * data = alloc_file(filename, &data_size); + if(data == NULL) { + LV_LOG_WARN("can't load file: %s", filename); + return NULL; + } + + /*Ready to read file*/ + ret = png_image_begin_read_from_memory(&image, data, data_size); + if(!ret) { + LV_LOG_ERROR("png file: %s read failed: %d", filename, ret); + lv_free(data); + return NULL; + } + + /*Set color format*/ + image.format = PNG_FORMAT_BGRA; + + /*Alloc image buffer*/ + lv_draw_buf_t * decoded; + decoded = lv_draw_buf_create(image.width, image.height, LV_COLOR_FORMAT_ARGB8888, PNG_IMAGE_ROW_STRIDE(image)); + if(decoded == NULL) { + LV_LOG_ERROR("png draw buff alloc %" LV_PRIu32 " failed: %s", PNG_IMAGE_SIZE(image), filename); + lv_free(data); + return NULL; + } + + /*Start decoding*/ + ret = png_image_finish_read(&image, NULL, decoded->data, 0, NULL); + png_image_free(&image); + lv_free(data); + if(!ret) { + LV_LOG_ERROR("png decode failed: %d", ret); + lv_draw_buf_destroy(decoded); + return NULL; + } + + return decoded; +} + +static void png_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data) +{ + LV_UNUSED(user_data); + + if(cached_data->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)cached_data->src); + lv_draw_buf_destroy((lv_draw_buf_t *)cached_data->decoded); +} + +#endif /*LV_USE_LIBPNG*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.h b/lib/libesp32_lvgl/lvgl/src/libs/libpng/lv_libpng.h similarity index 68% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.h rename to lib/libesp32_lvgl/lvgl/src/libs/libpng/lv_libpng.h index 438047238..12794585d 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lv_png.h +++ b/lib/libesp32_lvgl/lvgl/src/libs/libpng/lv_libpng.h @@ -1,10 +1,10 @@ /** - * @file lv_png.h + * @file lv_libpng.h * */ -#ifndef LV_PNG_H -#define LV_PNG_H +#ifndef LV_LIBPNG_H +#define LV_LIBPNG_H #ifdef __cplusplus extern "C" { @@ -13,8 +13,8 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../lv_conf_internal.h" -#if LV_USE_PNG +#include "../../lv_conf_internal.h" +#if LV_USE_LIBPNG /********************* * DEFINES @@ -31,16 +31,18 @@ extern "C" { /** * Register the PNG decoder functions in LVGL */ -void lv_png_init(void); +void lv_libpng_init(void); + +void lv_libpng_deinit(void); /********************** * MACROS **********************/ -#endif /*LV_USE_PNG*/ +#endif /*LV_USE_LIBPNG*/ #ifdef __cplusplus } /* extern "C" */ #endif -#endif /*LV_PNG_H*/ +#endif /*LV_LIBPNG_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/lodepng/lodepng.c b/lib/libesp32_lvgl/lvgl/src/libs/lodepng/lodepng.c new file mode 100644 index 000000000..385cf4588 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/lodepng/lodepng.c @@ -0,0 +1,7053 @@ +/* +LodePNG version 20201017 + +Copyright (c) 2005-2020 Lode Vandevenne + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ + +/* +The manual and changelog are in the header file "lodepng.h" +Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C. +*/ + +#include "lodepng.h" +#if LV_USE_LODEPNG + +#ifdef LODEPNG_COMPILE_DISK + #include /* LONG_MAX */ +#endif /* LODEPNG_COMPILE_DISK */ + +#ifdef LODEPNG_COMPILE_ALLOCATORS + #include /* allocations */ +#endif /* LODEPNG_COMPILE_ALLOCATORS */ + +#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/ + #pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/ + #pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/ +#endif /*_MSC_VER */ + +const char * LODEPNG_VERSION_STRING = "20201017"; + +/* +This source file is built up in the following large parts. The code sections +with the "LODEPNG_COMPILE_" #defines divide this up further in an intermixed way. +-Tools for C and common code for PNG and Zlib +-C Code for Zlib (huffman, deflate, ...) +-C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...) +-The C++ wrapper around all of the above +*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // Tools for C, and common code for PNG and Zlib. // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*The malloc, realloc and free functions defined here with "lodepng_" in front +of the name, so that you can easily change them to others related to your +platform if needed. Everything else in the code calls these. Pass +-DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out +#define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and +define them in your own project's source files without needing to change +lodepng source code. Don't forget to remove "static" if you copypaste them +from here.*/ + +#ifdef LODEPNG_COMPILE_ALLOCATORS +static void * lodepng_malloc(size_t size) +{ +#ifdef LODEPNG_MAX_ALLOC + if(size > LODEPNG_MAX_ALLOC) return 0; +#endif + return lv_malloc(size); +} + +/* NOTE: when realloc returns NULL, it leaves the original memory untouched */ +static void * lodepng_realloc(void * ptr, size_t new_size) +{ +#ifdef LODEPNG_MAX_ALLOC + if(new_size > LODEPNG_MAX_ALLOC) return 0; +#endif + return lv_realloc(ptr, new_size); +} + +static void lodepng_free(void * ptr) +{ + lv_free(ptr); +} +#else /*LODEPNG_COMPILE_ALLOCATORS*/ +/* TODO: support giving additional void* payload to the custom allocators */ +void * lodepng_malloc(size_t size); +void * lodepng_realloc(void * ptr, size_t new_size); +void lodepng_free(void * ptr); +#endif /*LODEPNG_COMPILE_ALLOCATORS*/ + +/* convince the compiler to inline a function, for use when this measurably improves performance */ +/* inline is not available in C90, but use it when supported by the compiler */ +#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define LODEPNG_INLINE inline +#else + #define LODEPNG_INLINE /* not available */ +#endif + +/* restrict is not available in C90, but use it when supported by the compiler */ +#if (defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) ||\ + (defined(_MSC_VER) && (_MSC_VER >= 1400)) || \ + (defined(__WATCOMC__) && (__WATCOMC__ >= 1250) && !defined(__cplusplus)) + #define LODEPNG_RESTRICT __restrict +#else + #define LODEPNG_RESTRICT /* not available */ +#endif + +/* Replacements for C library functions such as memcpy and strlen, to support platforms +where a full C library is not available. The compiler can recognize them and compile +to something as fast. */ + +static void lodepng_memcpy(void * LODEPNG_RESTRICT dst, + const void * LODEPNG_RESTRICT src, size_t size) +{ + lv_memcpy(dst, src, size); +} + +static void lodepng_memset(void * LODEPNG_RESTRICT dst, + int value, size_t num) +{ + lv_memset(dst, value, num); +} + +/* does not check memory out of bounds, do not use on untrusted data */ +static size_t lodepng_strlen(const char * a) +{ + const char * orig = a; + /* avoid warning about unused function in case of disabled COMPILE... macros */ + (void)(&lodepng_strlen); + while(*a) a++; + return (size_t)(a - orig); +} + +#define LODEPNG_MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define LODEPNG_MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define LODEPNG_ABS(x) ((x) < 0 ? -(x) : (x)) + +#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER) +/* Safely check if adding two integers will overflow (no undefined +behavior, compiler removing the code, etc...) and output result. */ +static int lodepng_addofl(size_t a, size_t b, size_t * result) +{ + *result = a + b; /* Unsigned addition is well defined and safe in C90 */ + return *result < a; +} +#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER)*/ + +#ifdef LODEPNG_COMPILE_DECODER +/* Safely check if multiplying two integers will overflow (no undefined +behavior, compiler removing the code, etc...) and output result. */ +static int lodepng_mulofl(size_t a, size_t b, size_t * result) +{ + *result = a * b; /* Unsigned multiplication is well defined and safe in C90 */ + return (a != 0 && *result / a != b); +} + +#ifdef LODEPNG_COMPILE_ZLIB +/* Safely check if a + b > c, even if overflow could happen. */ +static int lodepng_gtofl(size_t a, size_t b, size_t c) +{ + size_t d; + if(lodepng_addofl(a, b, &d)) return 1; + return d > c; +} +#endif /*LODEPNG_COMPILE_ZLIB*/ +#endif /*LODEPNG_COMPILE_DECODER*/ + + +/* +Often in case of an error a value is assigned to a variable and then it breaks +out of a loop (to go to the cleanup phase of a function). This macro does that. +It makes the error handling code shorter and more readable. + +Example: if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83); +*/ +#define CERROR_BREAK(errorvar, code){\ + errorvar = code;\ + break;\ + } + +/*version of CERROR_BREAK that assumes the common case where the error variable is named "error"*/ +#define ERROR_BREAK(code) CERROR_BREAK(error, code) + +/*Set error var to the error code, and return it.*/ +#define CERROR_RETURN_ERROR(errorvar, code){\ + errorvar = code;\ + return code;\ + } + +/*Try the code, if it returns error, also return the error.*/ +#define CERROR_TRY_RETURN(call){\ + unsigned error = call;\ + if(error) return error;\ + } + +/*Set error var to the error code, and return from the void function.*/ +#define CERROR_RETURN(errorvar, code){\ + errorvar = code;\ + return;\ + } + +/* +About uivector, ucvector and string: +-All of them wrap dynamic arrays or text strings in a similar way. +-LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version. +-The string tools are made to avoid problems with compilers that declare things like strncat as deprecated. +-They're not used in the interface, only internally in this file as static functions. +-As with many other structs in this file, the init and cleanup functions serve as ctor and dtor. +*/ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_ENCODER +/*dynamic vector of unsigned ints*/ +typedef struct uivector { + unsigned * data; + size_t size; /*size in number of unsigned longs*/ + size_t allocsize; /*allocated size in bytes*/ +} uivector; + +static void uivector_cleanup(void * p) +{ + ((uivector *)p)->size = ((uivector *)p)->allocsize = 0; + lodepng_free(((uivector *)p)->data); + ((uivector *)p)->data = NULL; +} + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned uivector_resize(uivector * p, size_t size) +{ + size_t allocsize = size * sizeof(unsigned); + if(allocsize > p->allocsize) { + size_t newsize = allocsize + (p->allocsize >> 1u); + void * data = lodepng_realloc(p->data, newsize); + if(data) { + p->allocsize = newsize; + p->data = (unsigned *)data; + } + else return 0; /*error: not enough memory*/ + } + p->size = size; + return 1; /*success*/ +} + +static void uivector_init(uivector * p) +{ + p->data = NULL; + p->size = p->allocsize = 0; +} + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned uivector_push_back(uivector * p, unsigned c) +{ + if(!uivector_resize(p, p->size + 1)) return 0; + p->data[p->size - 1] = c; + return 1; +} +#endif /*LODEPNG_COMPILE_ENCODER*/ +#endif /*LODEPNG_COMPILE_ZLIB*/ + +/* /////////////////////////////////////////////////////////////////////////// */ + +/*dynamic vector of unsigned chars*/ +typedef struct ucvector { + unsigned char * data; + size_t size; /*used size*/ + size_t allocsize; /*allocated size*/ +} ucvector; + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned ucvector_resize(ucvector * p, size_t size) +{ + if(size > p->allocsize) { + size_t newsize = size + (p->allocsize >> 1u); + void * data = lodepng_realloc(p->data, newsize); + if(data) { + p->allocsize = newsize; + p->data = (unsigned char *)data; + } + else return 0; /*error: not enough memory*/ + } + p->size = size; + return 1; /*success*/ +} + +static ucvector ucvector_init(unsigned char * buffer, size_t size) +{ + ucvector v; + v.data = buffer; + v.allocsize = v.size = size; + return v; +} + +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_PNG +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + +/*free string pointer and set it to NULL*/ +static void string_cleanup(char ** out) +{ + lodepng_free(*out); + *out = NULL; +} + +/*also appends null termination character*/ +static char * alloc_string_sized(const char * in, size_t insize) +{ + char * out = (char *)lodepng_malloc(insize + 1); + if(out) { + lodepng_memcpy(out, in, insize); + out[insize] = 0; + } + return out; +} + +/* dynamically allocates a new string with a copy of the null terminated input text */ +static char * alloc_string(const char * in) +{ + return alloc_string_sized(in, lodepng_strlen(in)); +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +/* ////////////////////////////////////////////////////////////////////////// */ + +#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_PNG) +static unsigned lodepng_read32bitInt(const unsigned char * buffer) +{ + return (((unsigned)buffer[0] << 24u) | ((unsigned)buffer[1] << 16u) | + ((unsigned)buffer[2] << 8u) | (unsigned)buffer[3]); +} +#endif /*defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_PNG)*/ + +#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER) +/*buffer must have at least 4 allocated bytes available*/ +static void lodepng_set32bitInt(unsigned char * buffer, unsigned value) +{ + buffer[0] = (unsigned char)((value >> 24) & 0xff); + buffer[1] = (unsigned char)((value >> 16) & 0xff); + buffer[2] = (unsigned char)((value >> 8) & 0xff); + buffer[3] = (unsigned char)((value) & 0xff); +} +#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / File IO / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_DISK + +/* returns negative value on error. This should be pure C compatible, so no fstat. */ +static long lodepng_filesize(const char * filename) +{ + lv_fs_file_t f; + lv_fs_res_t res = lv_fs_open(&f, filename, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) return -1; + uint32_t size = 0; + if(lv_fs_seek(&f, 0, LV_FS_SEEK_END) != 0) { + lv_fs_close(&f); + return -1; + } + + lv_fs_tell(&f, &size); + lv_fs_close(&f); + return size; +} + +/* load file into buffer that already has the correct allocated size. Returns error code.*/ +static unsigned lodepng_buffer_file(unsigned char * out, size_t size, const char * filename) +{ + lv_fs_file_t f; + lv_fs_res_t res = lv_fs_open(&f, filename, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) return 78; + + uint32_t br; + res = lv_fs_read(&f, out, size, &br); + lv_fs_close(&f); + + if(res != LV_FS_RES_OK) return 78; + if(br != size) return 78; + + return 0; +} + +unsigned lodepng_load_file(unsigned char ** out, size_t * outsize, const char * filename) +{ + long size = lodepng_filesize(filename); + if(size < 0) return 78; + *outsize = (size_t)size; + + *out = (unsigned char *)lodepng_malloc((size_t)size); + if(!(*out) && size > 0) return 83; /*the above malloc failed*/ + + return lodepng_buffer_file(*out, (size_t)size, filename); +} + +/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ +unsigned lodepng_save_file(const unsigned char * buffer, size_t buffersize, const char * filename) +{ + lv_fs_file_t f; + lv_fs_res_t res = lv_fs_open(&f, filename, LV_FS_MODE_WR); + if(res != LV_FS_RES_OK) return 79; + + uint32_t bw; + res = lv_fs_write(&f, buffer, buffersize, &bw); + lv_fs_close(&f); + return 0; +} + +#endif /*LODEPNG_COMPILE_DISK*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // End of common code and tools. Begin of Zlib related code. // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_ENCODER + +typedef struct { + ucvector * data; + unsigned char bp; /*ok to overflow, indicates bit pos inside byte*/ +} LodePNGBitWriter; + +static void LodePNGBitWriter_init(LodePNGBitWriter * writer, ucvector * data) +{ + writer->data = data; + writer->bp = 0; +} + +/*TODO: this ignores potential out of memory errors*/ +#define WRITEBIT(writer, bit){\ + /* append new byte */\ + if(((writer->bp) & 7u) == 0) {\ + if(!ucvector_resize(writer->data, writer->data->size + 1)) return;\ + writer->data->data[writer->data->size - 1] = 0;\ + }\ + (writer->data->data[writer->data->size - 1]) |= (bit << ((writer->bp) & 7u));\ + ++writer->bp;\ + } + +/* LSB of value is written first, and LSB of bytes is used first */ +static void writeBits(LodePNGBitWriter * writer, unsigned value, size_t nbits) +{ + if(nbits == 1) { /* compiler should statically compile this case if nbits == 1 */ + WRITEBIT(writer, value); + } + else { + /* TODO: increase output size only once here rather than in each WRITEBIT */ + size_t i; + for(i = 0; i != nbits; ++i) { + WRITEBIT(writer, (unsigned char)((value >> i) & 1)); + } + } +} + +/* This one is to use for adding huffman symbol, the value bits are written MSB first */ +static void writeBitsReversed(LodePNGBitWriter * writer, unsigned value, size_t nbits) +{ + size_t i; + for(i = 0; i != nbits; ++i) { + /* TODO: increase output size only once here rather than in each WRITEBIT */ + WRITEBIT(writer, (unsigned char)((value >> (nbits - 1u - i)) & 1u)); + } +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_DECODER + +typedef struct { + const unsigned char * data; + size_t size; /*size of data in bytes*/ + size_t bitsize; /*size of data in bits, end of valid bp values, should be 8*size*/ + size_t bp; + unsigned buffer; /*buffer for reading bits. NOTE: 'unsigned' must support at least 32 bits*/ +} LodePNGBitReader; + +/* data size argument is in bytes. Returns error if size too large causing overflow */ +static unsigned LodePNGBitReader_init(LodePNGBitReader * reader, const unsigned char * data, size_t size) +{ + size_t temp; + reader->data = data; + reader->size = size; + /* size in bits, return error if overflow (if size_t is 32 bit this supports up to 500MB) */ + if(lodepng_mulofl(size, 8u, &reader->bitsize)) return 105; + /*ensure incremented bp can be compared to bitsize without overflow even when it would be incremented 32 too much and + trying to ensure 32 more bits*/ + if(lodepng_addofl(reader->bitsize, 64u, &temp)) return 105; + reader->bp = 0; + reader->buffer = 0; + return 0; /*ok*/ +} + +/* +ensureBits functions: +Ensures the reader can at least read nbits bits in one or more readBits calls, +safely even if not enough bits are available. +Returns 1 if there are enough bits available, 0 if not. +*/ + +/*See ensureBits documentation above. This one ensures exactly 1 bit */ +/*static unsigned ensureBits1(LodePNGBitReader* reader) { + if(reader->bp >= reader->bitsize) return 0; + reader->buffer = (unsigned)reader->data[reader->bp >> 3u] >> (reader->bp & 7u); + return 1; +}*/ + +/*See ensureBits documentation above. This one ensures up to 9 bits */ +static unsigned ensureBits9(LodePNGBitReader * reader, size_t nbits) +{ + size_t start = reader->bp >> 3u; + size_t size = reader->size; + if(start + 1u < size) { + reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u); + reader->buffer >>= (reader->bp & 7u); + return 1; + } + else { + reader->buffer = 0; + if(start + 0u < size) reader->buffer |= reader->data[start + 0]; + reader->buffer >>= (reader->bp & 7u); + return reader->bp + nbits <= reader->bitsize; + } +} + +/*See ensureBits documentation above. This one ensures up to 17 bits */ +static unsigned ensureBits17(LodePNGBitReader * reader, size_t nbits) +{ + size_t start = reader->bp >> 3u; + size_t size = reader->size; + if(start + 2u < size) { + reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) | + ((unsigned)reader->data[start + 2] << 16u); + reader->buffer >>= (reader->bp & 7u); + return 1; + } + else { + reader->buffer = 0; + if(start + 0u < size) reader->buffer |= reader->data[start + 0]; + if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u); + reader->buffer >>= (reader->bp & 7u); + return reader->bp + nbits <= reader->bitsize; + } +} + +/*See ensureBits documentation above. This one ensures up to 25 bits */ +static LODEPNG_INLINE unsigned ensureBits25(LodePNGBitReader * reader, size_t nbits) +{ + size_t start = reader->bp >> 3u; + size_t size = reader->size; + if(start + 3u < size) { + reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) | + ((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u); + reader->buffer >>= (reader->bp & 7u); + return 1; + } + else { + reader->buffer = 0; + if(start + 0u < size) reader->buffer |= reader->data[start + 0]; + if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u); + if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u); + reader->buffer >>= (reader->bp & 7u); + return reader->bp + nbits <= reader->bitsize; + } +} + +/*See ensureBits documentation above. This one ensures up to 32 bits */ +static LODEPNG_INLINE unsigned ensureBits32(LodePNGBitReader * reader, size_t nbits) +{ + size_t start = reader->bp >> 3u; + size_t size = reader->size; + if(start + 4u < size) { + reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) | + ((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u); + reader->buffer >>= (reader->bp & 7u); + reader->buffer |= (((unsigned)reader->data[start + 4] << 24u) << (8u - (reader->bp & 7u))); + return 1; + } + else { + reader->buffer = 0; + if(start + 0u < size) reader->buffer |= reader->data[start + 0]; + if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u); + if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u); + if(start + 3u < size) reader->buffer |= ((unsigned)reader->data[start + 3] << 24u); + reader->buffer >>= (reader->bp & 7u); + return reader->bp + nbits <= reader->bitsize; + } +} + +/* Get bits without advancing the bit pointer. Must have enough bits available with ensureBits. Max nbits is 31. */ +static unsigned peekBits(LodePNGBitReader * reader, size_t nbits) +{ + /* The shift allows nbits to be only up to 31. */ + return reader->buffer & ((1u << nbits) - 1u); +} + +/* Must have enough bits available with ensureBits */ +static void advanceBits(LodePNGBitReader * reader, size_t nbits) +{ + reader->buffer >>= nbits; + reader->bp += nbits; +} + +/* Must have enough bits available with ensureBits */ +static unsigned readBits(LodePNGBitReader * reader, size_t nbits) +{ + unsigned result = peekBits(reader, nbits); + advanceBits(reader, nbits); + return result; +} + +#if 0 /*Disable because tests fail due to unused declaration*/ +/* Public for testing only. steps and result must have numsteps values. */ +static unsigned lode_png_test_bitreader(const unsigned char * data, size_t size, + size_t numsteps, const size_t * steps, unsigned * result) +{ + size_t i; + LodePNGBitReader reader; + unsigned error = LodePNGBitReader_init(&reader, data, size); + if(error) return 0; + for(i = 0; i < numsteps; i++) { + size_t step = steps[i]; + unsigned ok; + if(step > 25) ok = ensureBits32(&reader, step); + else if(step > 17) ok = ensureBits25(&reader, step); + else if(step > 9) ok = ensureBits17(&reader, step); + else ok = ensureBits9(&reader, step); + if(!ok) return 0; + result[i] = readBits(&reader, step); + } + return 1; +} +#endif + +#endif /*LODEPNG_COMPILE_DECODER*/ + +static unsigned reverseBits(unsigned bits, unsigned num) +{ + /*TODO: implement faster lookup table based version when needed*/ + unsigned i, result = 0; + for(i = 0; i < num; i++) result |= ((bits >> (num - i - 1u)) & 1u) << i; + return result; +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Deflate - Huffman / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#define FIRST_LENGTH_CODE_INDEX 257 +#define LAST_LENGTH_CODE_INDEX 285 +/*256 literals, the end code, some length codes, and 2 unused codes*/ +#define NUM_DEFLATE_CODE_SYMBOLS 288 +/*the distance codes have their own symbols, 30 used, 2 unused*/ +#define NUM_DISTANCE_SYMBOLS 32 +/*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/ +#define NUM_CODE_LENGTH_CODES 19 + +/*the base lengths represented by codes 257-285*/ +static const unsigned LENGTHBASE[29] + = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, + 67, 83, 99, 115, 131, 163, 195, 227, 258 + }; + +/*the extra bits used by codes 257-285 (added to base length)*/ +static const unsigned LENGTHEXTRA[29] + = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 5, 5, 5, 5, 0 + }; + +/*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/ +static const unsigned DISTANCEBASE[30] + = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, + 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 + }; + +/*the extra bits of backwards distances (added to base)*/ +static const unsigned DISTANCEEXTRA[30] + = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 + }; + +/*the order in which "code length alphabet code lengths" are stored as specified by deflate, out of this the huffman +tree of the dynamic huffman tree lengths is generated*/ +static const unsigned CLCL_ORDER[NUM_CODE_LENGTH_CODES] + = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + +/* ////////////////////////////////////////////////////////////////////////// */ + +/* +Huffman tree struct, containing multiple representations of the tree +*/ +typedef struct HuffmanTree { + unsigned * codes; /*the huffman codes (bit patterns representing the symbols)*/ + unsigned * lengths; /*the lengths of the huffman codes*/ + unsigned maxbitlen; /*maximum number of bits a single code can get*/ + unsigned numcodes; /*number of symbols in the alphabet = number of codes*/ + /* for reading only */ + unsigned char * table_len; /*length of symbol from lookup table, or max length if secondary lookup needed*/ + unsigned short * table_value; /*value of symbol from lookup table, or pointer to secondary table if needed*/ +} HuffmanTree; + +static void HuffmanTree_init(HuffmanTree * tree) +{ + tree->codes = 0; + tree->lengths = 0; + tree->table_len = 0; + tree->table_value = 0; +} + +static void HuffmanTree_cleanup(HuffmanTree * tree) +{ + lodepng_free(tree->codes); + lodepng_free(tree->lengths); + lodepng_free(tree->table_len); + lodepng_free(tree->table_value); +} + +/* amount of bits for first huffman table lookup (aka root bits), see HuffmanTree_makeTable and huffmanDecodeSymbol.*/ +/* values 8u and 9u work the fastest */ +#define FIRSTBITS 9u + +/* a symbol value too big to represent any valid symbol, to indicate reading disallowed huffman bits combination, +which is possible in case of only 0 or 1 present symbols. */ +#define INVALIDSYMBOL 65535u + +/* make table for huffman decoding */ +static unsigned HuffmanTree_makeTable(HuffmanTree * tree) +{ + static const unsigned headsize = 1u << FIRSTBITS; /*size of the first table*/ + static const unsigned mask = (1u << FIRSTBITS) /*headsize*/ - 1u; + size_t i, numpresent, pointer, size; /*total table size*/ + unsigned * maxlens = (unsigned *)lodepng_malloc(headsize * sizeof(unsigned)); + if(!maxlens) return 83; /*alloc fail*/ + + /* compute maxlens: max total bit length of symbols sharing prefix in the first table*/ + lodepng_memset(maxlens, 0, headsize * sizeof(*maxlens)); + for(i = 0; i < tree->numcodes; i++) { + unsigned symbol = tree->codes[i]; + unsigned l = tree->lengths[i]; + unsigned index; + if(l <= FIRSTBITS) continue; /*symbols that fit in first table don't increase secondary table size*/ + /*get the FIRSTBITS MSBs, the MSBs of the symbol are encoded first. See later comment about the reversing*/ + index = reverseBits(symbol >> (l - FIRSTBITS), FIRSTBITS); + maxlens[index] = LODEPNG_MAX(maxlens[index], l); + } + /* compute total table size: size of first table plus all secondary tables for symbols longer than FIRSTBITS */ + size = headsize; + for(i = 0; i < headsize; ++i) { + unsigned l = maxlens[i]; + if(l > FIRSTBITS) size += (1u << (l - FIRSTBITS)); + } + tree->table_len = (unsigned char *)lodepng_malloc(size * sizeof(*tree->table_len)); + tree->table_value = (unsigned short *)lodepng_malloc(size * sizeof(*tree->table_value)); + if(!tree->table_len || !tree->table_value) { + lodepng_free(maxlens); + /* freeing tree->table values is done at a higher scope */ + return 83; /*alloc fail*/ + } + /*initialize with an invalid length to indicate unused entries*/ + for(i = 0; i < size; ++i) tree->table_len[i] = 16; + + /*fill in the first table for long symbols: max prefix size and pointer to secondary tables*/ + pointer = headsize; + for(i = 0; i < headsize; ++i) { + unsigned l = maxlens[i]; + if(l <= FIRSTBITS) continue; + tree->table_len[i] = l; + tree->table_value[i] = pointer; + pointer += (1u << (l - FIRSTBITS)); + } + lodepng_free(maxlens); + + /*fill in the first table for short symbols, or secondary table for long symbols*/ + numpresent = 0; + for(i = 0; i < tree->numcodes; ++i) { + unsigned l = tree->lengths[i]; + unsigned symbol = tree->codes[i]; /*the huffman bit pattern. i itself is the value.*/ + /*reverse bits, because the huffman bits are given in MSB first order but the bit reader reads LSB first*/ + unsigned reverse = reverseBits(symbol, l); + if(l == 0) continue; + numpresent++; + + if(l <= FIRSTBITS) { + /*short symbol, fully in first table, replicated num times if l < FIRSTBITS*/ + unsigned num = 1u << (FIRSTBITS - l); + unsigned j; + for(j = 0; j < num; ++j) { + /*bit reader will read the l bits of symbol first, the remaining FIRSTBITS - l bits go to the MSB's*/ + unsigned index = reverse | (j << l); + if(tree->table_len[index] != 16) return 55; /*invalid tree: long symbol shares prefix with short symbol*/ + tree->table_len[index] = l; + tree->table_value[index] = i; + } + } + else { + /*long symbol, shares prefix with other long symbols in first lookup table, needs second lookup*/ + /*the FIRSTBITS MSBs of the symbol are the first table index*/ + unsigned index = reverse & mask; + unsigned maxlen = tree->table_len[index]; + /*log2 of secondary table length, should be >= l - FIRSTBITS*/ + unsigned tablelen = maxlen - FIRSTBITS; + unsigned start = tree->table_value[index]; /*starting index in secondary table*/ + unsigned num = 1u << (tablelen - (l - FIRSTBITS)); /*amount of entries of this symbol in secondary table*/ + unsigned j; + if(maxlen < l) return 55; /*invalid tree: long symbol shares prefix with short symbol*/ + for(j = 0; j < num; ++j) { + unsigned reverse2 = reverse >> FIRSTBITS; /* l - FIRSTBITS bits */ + unsigned index2 = start + (reverse2 | (j << (l - FIRSTBITS))); + tree->table_len[index2] = l; + tree->table_value[index2] = i; + } + } + } + + if(numpresent < 2) { + /* In case of exactly 1 symbol, in theory the huffman symbol needs 0 bits, + but deflate uses 1 bit instead. In case of 0 symbols, no symbols can + appear at all, but such huffman tree could still exist (e.g. if distance + codes are never used). In both cases, not all symbols of the table will be + filled in. Fill them in with an invalid symbol value so returning them from + huffmanDecodeSymbol will cause error. */ + for(i = 0; i < size; ++i) { + if(tree->table_len[i] == 16) { + /* As length, use a value smaller than FIRSTBITS for the head table, + and a value larger than FIRSTBITS for the secondary table, to ensure + valid behavior for advanceBits when reading this symbol. */ + tree->table_len[i] = (i < headsize) ? 1 : (FIRSTBITS + 1); + tree->table_value[i] = INVALIDSYMBOL; + } + } + } + else { + /* A good huffman tree has N * 2 - 1 nodes, of which N - 1 are internal nodes. + If that is not the case (due to too long length codes), the table will not + have been fully used, and this is an error (not all bit combinations can be + decoded): an oversubscribed huffman tree, indicated by error 55. */ + for(i = 0; i < size; ++i) { + if(tree->table_len[i] == 16) return 55; + } + } + + return 0; +} + +/* +Second step for the ...makeFromLengths and ...makeFromFrequencies functions. +numcodes, lengths and maxbitlen must already be filled in correctly. return +value is error. +*/ +static unsigned HuffmanTree_makeFromLengths2(HuffmanTree * tree) +{ + unsigned * blcount; + unsigned * nextcode; + unsigned error = 0; + unsigned bits, n; + + tree->codes = (unsigned *)lodepng_malloc(tree->numcodes * sizeof(unsigned)); + blcount = (unsigned *)lodepng_malloc((tree->maxbitlen + 1) * sizeof(unsigned)); + nextcode = (unsigned *)lodepng_malloc((tree->maxbitlen + 1) * sizeof(unsigned)); + if(!tree->codes || !blcount || !nextcode) error = 83; /*alloc fail*/ + + if(!error) { + for(n = 0; n != tree->maxbitlen + 1; n++) blcount[n] = nextcode[n] = 0; + /*step 1: count number of instances of each code length*/ + for(bits = 0; bits != tree->numcodes; ++bits) ++blcount[tree->lengths[bits]]; + /*step 2: generate the nextcode values*/ + for(bits = 1; bits <= tree->maxbitlen; ++bits) { + nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1u; + } + /*step 3: generate all the codes*/ + for(n = 0; n != tree->numcodes; ++n) { + if(tree->lengths[n] != 0) { + tree->codes[n] = nextcode[tree->lengths[n]]++; + /*remove superfluous bits from the code*/ + tree->codes[n] &= ((1u << tree->lengths[n]) - 1u); + } + } + } + + lodepng_free(blcount); + lodepng_free(nextcode); + + if(!error) error = HuffmanTree_makeTable(tree); + return error; +} + +/* +given the code lengths (as stored in the PNG file), generate the tree as defined +by Deflate. maxbitlen is the maximum bits that a code in the tree can have. +return value is error. +*/ +static unsigned HuffmanTree_makeFromLengths(HuffmanTree * tree, const unsigned * bitlen, + size_t numcodes, unsigned maxbitlen) +{ + unsigned i; + tree->lengths = (unsigned *)lodepng_malloc(numcodes * sizeof(unsigned)); + if(!tree->lengths) return 83; /*alloc fail*/ + for(i = 0; i != numcodes; ++i) tree->lengths[i] = bitlen[i]; + tree->numcodes = (unsigned)numcodes; /*number of symbols*/ + tree->maxbitlen = maxbitlen; + return HuffmanTree_makeFromLengths2(tree); +} + +#ifdef LODEPNG_COMPILE_ENCODER + +/*BPM: Boundary Package Merge, see "A Fast and Space-Economical Algorithm for Length-Limited Coding", +Jyrki Katajainen, Alistair Moffat, Andrew Turpin, 1995.*/ + +/*chain node for boundary package merge*/ +typedef struct BPMNode { + int weight; /*the sum of all weights in this chain*/ + unsigned index; /*index of this leaf node (called "count" in the paper)*/ + struct BPMNode * tail; /*the next nodes in this chain (null if last)*/ + int in_use; +} BPMNode; + +/*lists of chains*/ +typedef struct BPMLists { + /*memory pool*/ + unsigned memsize; + BPMNode * memory; + unsigned numfree; + unsigned nextfree; + BPMNode ** freelist; + /*two heads of lookahead chains per list*/ + unsigned listsize; + BPMNode ** chains0; + BPMNode ** chains1; +} BPMLists; + +/*creates a new chain node with the given parameters, from the memory in the lists */ +static BPMNode * bpmnode_create(BPMLists * lists, int weight, unsigned index, BPMNode * tail) +{ + unsigned i; + BPMNode * result; + + /*memory full, so garbage collect*/ + if(lists->nextfree >= lists->numfree) { + /*mark only those that are in use*/ + for(i = 0; i != lists->memsize; ++i) lists->memory[i].in_use = 0; + for(i = 0; i != lists->listsize; ++i) { + BPMNode * node; + for(node = lists->chains0[i]; node != 0; node = node->tail) node->in_use = 1; + for(node = lists->chains1[i]; node != 0; node = node->tail) node->in_use = 1; + } + /*collect those that are free*/ + lists->numfree = 0; + for(i = 0; i != lists->memsize; ++i) { + if(!lists->memory[i].in_use) lists->freelist[lists->numfree++] = &lists->memory[i]; + } + lists->nextfree = 0; + } + + result = lists->freelist[lists->nextfree++]; + result->weight = weight; + result->index = index; + result->tail = tail; + return result; +} + +/*sort the leaves with stable mergesort*/ +static void bpmnode_sort(BPMNode * leaves, size_t num) +{ + BPMNode * mem = (BPMNode *)lodepng_malloc(sizeof(*leaves) * num); + size_t width, counter = 0; + for(width = 1; width < num; width *= 2) { + BPMNode * a = (counter & 1) ? mem : leaves; + BPMNode * b = (counter & 1) ? leaves : mem; + size_t p; + for(p = 0; p < num; p += 2 * width) { + size_t q = (p + width > num) ? num : (p + width); + size_t r = (p + 2 * width > num) ? num : (p + 2 * width); + size_t i = p, j = q, k; + for(k = p; k < r; k++) { + if(i < q && (j >= r || a[i].weight <= a[j].weight)) b[k] = a[i++]; + else b[k] = a[j++]; + } + } + counter++; + } + if(counter & 1) lodepng_memcpy(leaves, mem, sizeof(*leaves) * num); + lodepng_free(mem); +} + +/*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/ +static void boundaryPM(BPMLists * lists, BPMNode * leaves, size_t numpresent, int c, int num) +{ + unsigned lastindex = lists->chains1[c]->index; + + if(c == 0) { + if(lastindex >= numpresent) return; + lists->chains0[c] = lists->chains1[c]; + lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, 0); + } + else { + /*sum of the weights of the head nodes of the previous lookahead chains.*/ + int sum = lists->chains0[c - 1]->weight + lists->chains1[c - 1]->weight; + lists->chains0[c] = lists->chains1[c]; + if(lastindex < numpresent && sum > leaves[lastindex].weight) { + lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, lists->chains1[c]->tail); + return; + } + lists->chains1[c] = bpmnode_create(lists, sum, lastindex, lists->chains1[c - 1]); + /*in the end we are only interested in the chain of the last list, so no + need to recurse if we're at the last one (this gives measurable speedup)*/ + if(num + 1 < (int)(2 * numpresent - 2)) { + boundaryPM(lists, leaves, numpresent, c - 1, num); + boundaryPM(lists, leaves, numpresent, c - 1, num); + } + } +} + +unsigned lodepng_huffman_code_lengths(unsigned * lengths, const unsigned * frequencies, + size_t numcodes, unsigned maxbitlen) +{ + unsigned error = 0; + unsigned i; + size_t numpresent = 0; /*number of symbols with non-zero frequency*/ + BPMNode * leaves; /*the symbols, only those with > 0 frequency*/ + + if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/ + if((1u << maxbitlen) < (unsigned)numcodes) return 80; /*error: represent all symbols*/ + + leaves = (BPMNode *)lodepng_malloc(numcodes * sizeof(*leaves)); + if(!leaves) return 83; /*alloc fail*/ + + for(i = 0; i != numcodes; ++i) { + if(frequencies[i] > 0) { + leaves[numpresent].weight = (int)frequencies[i]; + leaves[numpresent].index = i; + ++numpresent; + } + } + + lodepng_memset(lengths, 0, numcodes * sizeof(*lengths)); + + /*ensure at least two present symbols. There should be at least one symbol + according to RFC 1951 section 3.2.7. Some decoders incorrectly require two. To + make these work as well ensure there are at least two symbols. The + Package-Merge code below also doesn't work correctly if there's only one + symbol, it'd give it the theoretical 0 bits but in practice zlib wants 1 bit*/ + if(numpresent == 0) { + lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/ + } + else if(numpresent == 1) { + lengths[leaves[0].index] = 1; + lengths[leaves[0].index == 0 ? 1 : 0] = 1; + } + else { + BPMLists lists; + BPMNode * node; + + bpmnode_sort(leaves, numpresent); + + lists.listsize = maxbitlen; + lists.memsize = 2 * maxbitlen * (maxbitlen + 1); + lists.nextfree = 0; + lists.numfree = lists.memsize; + lists.memory = (BPMNode *)lodepng_malloc(lists.memsize * sizeof(*lists.memory)); + lists.freelist = (BPMNode **)lodepng_malloc(lists.memsize * sizeof(BPMNode *)); + lists.chains0 = (BPMNode **)lodepng_malloc(lists.listsize * sizeof(BPMNode *)); + lists.chains1 = (BPMNode **)lodepng_malloc(lists.listsize * sizeof(BPMNode *)); + if(!lists.memory || !lists.freelist || !lists.chains0 || !lists.chains1) error = 83; /*alloc fail*/ + + if(!error) { + for(i = 0; i != lists.memsize; ++i) lists.freelist[i] = &lists.memory[i]; + + bpmnode_create(&lists, leaves[0].weight, 1, 0); + bpmnode_create(&lists, leaves[1].weight, 2, 0); + + for(i = 0; i != lists.listsize; ++i) { + lists.chains0[i] = &lists.memory[0]; + lists.chains1[i] = &lists.memory[1]; + } + + /*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/ + for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, (int)maxbitlen - 1, (int)i); + + for(node = lists.chains1[maxbitlen - 1]; node; node = node->tail) { + for(i = 0; i != node->index; ++i) ++lengths[leaves[i].index]; + } + } + + lodepng_free(lists.memory); + lodepng_free(lists.freelist); + lodepng_free(lists.chains0); + lodepng_free(lists.chains1); + } + + lodepng_free(leaves); + return error; +} + +/*Create the Huffman tree given the symbol frequencies*/ +static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree * tree, const unsigned * frequencies, + size_t mincodes, size_t numcodes, unsigned maxbitlen) +{ + unsigned error = 0; + while(!frequencies[numcodes - 1] && numcodes > mincodes) --numcodes; /*trim zeroes*/ + tree->lengths = (unsigned *)lodepng_malloc(numcodes * sizeof(unsigned)); + if(!tree->lengths) return 83; /*alloc fail*/ + tree->maxbitlen = maxbitlen; + tree->numcodes = (unsigned)numcodes; /*number of symbols*/ + + error = lodepng_huffman_code_lengths(tree->lengths, frequencies, numcodes, maxbitlen); + if(!error) error = HuffmanTree_makeFromLengths2(tree); + return error; +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/*get the literal and length code tree of a deflated block with fixed tree, as per the deflate specification*/ +static unsigned generateFixedLitLenTree(HuffmanTree * tree) +{ + unsigned i, error = 0; + unsigned * bitlen = (unsigned *)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); + if(!bitlen) return 83; /*alloc fail*/ + + /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/ + for(i = 0; i <= 143; ++i) bitlen[i] = 8; + for(i = 144; i <= 255; ++i) bitlen[i] = 9; + for(i = 256; i <= 279; ++i) bitlen[i] = 7; + for(i = 280; i <= 287; ++i) bitlen[i] = 8; + + error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DEFLATE_CODE_SYMBOLS, 15); + + lodepng_free(bitlen); + return error; +} + +/*get the distance code tree of a deflated block with fixed tree, as specified in the deflate specification*/ +static unsigned generateFixedDistanceTree(HuffmanTree * tree) +{ + unsigned i, error = 0; + unsigned * bitlen = (unsigned *)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); + if(!bitlen) return 83; /*alloc fail*/ + + /*there are 32 distance codes, but 30-31 are unused*/ + for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen[i] = 5; + error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DISTANCE_SYMBOLS, 15); + + lodepng_free(bitlen); + return error; +} + +#ifdef LODEPNG_COMPILE_DECODER + +/* +returns the code. The bit reader must already have been ensured at least 15 bits +*/ +static unsigned huffmanDecodeSymbol(LodePNGBitReader * reader, const HuffmanTree * codetree) +{ + unsigned short code = peekBits(reader, FIRSTBITS); + unsigned short l = codetree->table_len[code]; + unsigned short value = codetree->table_value[code]; + if(l <= FIRSTBITS) { + advanceBits(reader, l); + return value; + } + else { + unsigned index2; + advanceBits(reader, FIRSTBITS); + index2 = value + peekBits(reader, l - FIRSTBITS); + advanceBits(reader, codetree->table_len[index2] - FIRSTBITS); + return codetree->table_value[index2]; + } +} +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_DECODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Inflator (Decompressor) / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*get the tree of a deflated block with fixed tree, as specified in the deflate specification +Returns error code.*/ +static unsigned getTreeInflateFixed(HuffmanTree * tree_ll, HuffmanTree * tree_d) +{ + unsigned error = generateFixedLitLenTree(tree_ll); + if(error) return error; + return generateFixedDistanceTree(tree_d); +} + +/*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/ +static unsigned getTreeInflateDynamic(HuffmanTree * tree_ll, HuffmanTree * tree_d, + LodePNGBitReader * reader) +{ + /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/ + unsigned error = 0; + unsigned n, HLIT, HDIST, HCLEN, i; + + /*see comments in deflateDynamic for explanation of the context and these variables, it is analogous*/ + unsigned * bitlen_ll = 0; /*lit,len code lengths*/ + unsigned * bitlen_d = 0; /*dist code lengths*/ + /*code length code lengths ("clcl"), the bit lengths of the huffman tree used to compress bitlen_ll and bitlen_d*/ + unsigned * bitlen_cl = 0; + HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/ + + if(!ensureBits17(reader, 14)) return 49; /*error: the bit pointer is or will go past the memory*/ + + /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/ + HLIT = readBits(reader, 5) + 257; + /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/ + HDIST = readBits(reader, 5) + 1; + /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/ + HCLEN = readBits(reader, 4) + 4; + + bitlen_cl = (unsigned *)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(unsigned)); + if(!bitlen_cl) return 83 /*alloc fail*/; + + HuffmanTree_init(&tree_cl); + + while(!error) { + /*read the code length codes out of 3 * (amount of code length codes) bits*/ + if(lodepng_gtofl(reader->bp, HCLEN * 3, reader->bitsize)) { + ERROR_BREAK(50); /*error: the bit pointer is or will go past the memory*/ + } + for(i = 0; i != HCLEN; ++i) { + ensureBits9(reader, 3); /*out of bounds already checked above */ + bitlen_cl[CLCL_ORDER[i]] = readBits(reader, 3); + } + for(i = HCLEN; i != NUM_CODE_LENGTH_CODES; ++i) { + bitlen_cl[CLCL_ORDER[i]] = 0; + } + + error = HuffmanTree_makeFromLengths(&tree_cl, bitlen_cl, NUM_CODE_LENGTH_CODES, 7); + if(error) break; + + /*now we can use this tree to read the lengths for the tree that this function will return*/ + bitlen_ll = (unsigned *)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); + bitlen_d = (unsigned *)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); + if(!bitlen_ll || !bitlen_d) ERROR_BREAK(83 /*alloc fail*/); + lodepng_memset(bitlen_ll, 0, NUM_DEFLATE_CODE_SYMBOLS * sizeof(*bitlen_ll)); + lodepng_memset(bitlen_d, 0, NUM_DISTANCE_SYMBOLS * sizeof(*bitlen_d)); + + /*i is the current symbol we're reading in the part that contains the code lengths of lit/len and dist codes*/ + i = 0; + while(i < HLIT + HDIST) { + unsigned code; + ensureBits25(reader, 22); /* up to 15 bits for huffman code, up to 7 extra bits below*/ + code = huffmanDecodeSymbol(reader, &tree_cl); + if(code <= 15) { /*a length code*/ + if(i < HLIT) bitlen_ll[i] = code; + else bitlen_d[i - HLIT] = code; + ++i; + } + else if(code == 16) { /*repeat previous*/ + unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/ + unsigned value; /*set value to the previous code*/ + + if(i == 0) ERROR_BREAK(54); /*can't repeat previous if i is 0*/ + + replength += readBits(reader, 2); + + if(i < HLIT + 1) value = bitlen_ll[i - 1]; + else value = bitlen_d[i - HLIT - 1]; + /*repeat this value in the next lengths*/ + for(n = 0; n < replength; ++n) { + if(i >= HLIT + HDIST) ERROR_BREAK(13); /*error: i is larger than the amount of codes*/ + if(i < HLIT) bitlen_ll[i] = value; + else bitlen_d[i - HLIT] = value; + ++i; + } + } + else if(code == 17) { /*repeat "0" 3-10 times*/ + unsigned replength = 3; /*read in the bits that indicate repeat length*/ + replength += readBits(reader, 3); + + /*repeat this value in the next lengths*/ + for(n = 0; n < replength; ++n) { + if(i >= HLIT + HDIST) ERROR_BREAK(14); /*error: i is larger than the amount of codes*/ + + if(i < HLIT) bitlen_ll[i] = 0; + else bitlen_d[i - HLIT] = 0; + ++i; + } + } + else if(code == 18) { /*repeat "0" 11-138 times*/ + unsigned replength = 11; /*read in the bits that indicate repeat length*/ + replength += readBits(reader, 7); + + /*repeat this value in the next lengths*/ + for(n = 0; n < replength; ++n) { + if(i >= HLIT + HDIST) ERROR_BREAK(15); /*error: i is larger than the amount of codes*/ + + if(i < HLIT) bitlen_ll[i] = 0; + else bitlen_d[i - HLIT] = 0; + ++i; + } + } + else { /*if(code == INVALIDSYMBOL)*/ + ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/ + } + /*check if any of the ensureBits above went out of bounds*/ + if(reader->bp > reader->bitsize) { + /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol + (10=no endcode, 11=wrong jump outside of tree)*/ + /* TODO: revise error codes 10,11,50: the above comment is no longer valid */ + ERROR_BREAK(50); /*error, bit pointer jumps past memory*/ + } + } + if(error) break; + + if(bitlen_ll[256] == 0) ERROR_BREAK(64); /*the length of the end code 256 must be larger than 0*/ + + /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/ + error = HuffmanTree_makeFromLengths(tree_ll, bitlen_ll, NUM_DEFLATE_CODE_SYMBOLS, 15); + if(error) break; + error = HuffmanTree_makeFromLengths(tree_d, bitlen_d, NUM_DISTANCE_SYMBOLS, 15); + + break; /*end of error-while*/ + } + + lodepng_free(bitlen_cl); + lodepng_free(bitlen_ll); + lodepng_free(bitlen_d); + HuffmanTree_cleanup(&tree_cl); + + return error; +} + +/*inflate a block with dynamic of fixed Huffman tree. btype must be 1 or 2.*/ +static unsigned inflateHuffmanBlock(ucvector * out, LodePNGBitReader * reader, + unsigned btype, size_t max_output_size) +{ + unsigned error = 0; + HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/ + HuffmanTree tree_d; /*the huffman tree for distance codes*/ + + HuffmanTree_init(&tree_ll); + HuffmanTree_init(&tree_d); + + if(btype == 1) error = getTreeInflateFixed(&tree_ll, &tree_d); + else /*if(btype == 2)*/ error = getTreeInflateDynamic(&tree_ll, &tree_d, reader); + + while(!error) { /*decode all symbols until end reached, breaks at end code*/ + /*code_ll is literal, length or end code*/ + unsigned code_ll; + ensureBits25(reader, 20); /* up to 15 for the huffman symbol, up to 5 for the length extra bits */ + code_ll = huffmanDecodeSymbol(reader, &tree_ll); + if(code_ll <= 255) { /*literal symbol*/ + if(!ucvector_resize(out, out->size + 1)) ERROR_BREAK(83 /*alloc fail*/); + out->data[out->size - 1] = (unsigned char)code_ll; + } + else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) { /*length code*/ + unsigned code_d, distance; + unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/ + size_t start, backward, length; + + /*part 1: get length base*/ + length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX]; + + /*part 2: get extra bits and add the value of that to length*/ + numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX]; + if(numextrabits_l != 0) { + /* bits already ensured above */ + length += readBits(reader, numextrabits_l); + } + + /*part 3: get distance code*/ + ensureBits32(reader, 28); /* up to 15 for the huffman symbol, up to 13 for the extra bits */ + code_d = huffmanDecodeSymbol(reader, &tree_d); + if(code_d > 29) { + if(code_d <= 31) { + ERROR_BREAK(18); /*error: invalid distance code (30-31 are never used)*/ + } + else { /* if(code_d == INVALIDSYMBOL) */ + ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/ + } + } + distance = DISTANCEBASE[code_d]; + + /*part 4: get extra bits from distance*/ + numextrabits_d = DISTANCEEXTRA[code_d]; + if(numextrabits_d != 0) { + /* bits already ensured above */ + distance += readBits(reader, numextrabits_d); + } + + /*part 5: fill in all the out[n] values based on the length and dist*/ + start = out->size; + if(distance > start) ERROR_BREAK(52); /*too long backward distance*/ + backward = start - distance; + + if(!ucvector_resize(out, out->size + length)) ERROR_BREAK(83 /*alloc fail*/); + if(distance < length) { + size_t forward; + lodepng_memcpy(out->data + start, out->data + backward, distance); + start += distance; + for(forward = distance; forward < length; ++forward) { + out->data[start++] = out->data[backward++]; + } + } + else { + lodepng_memcpy(out->data + start, out->data + backward, length); + } + } + else if(code_ll == 256) { + break; /*end code, break the loop*/ + } + else { /*if(code_ll == INVALIDSYMBOL)*/ + ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/ + } + /*check if any of the ensureBits above went out of bounds*/ + if(reader->bp > reader->bitsize) { + /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol + (10=no endcode, 11=wrong jump outside of tree)*/ + /* TODO: revise error codes 10,11,50: the above comment is no longer valid */ + ERROR_BREAK(51); /*error, bit pointer jumps past memory*/ + } + if(max_output_size && out->size > max_output_size) { + ERROR_BREAK(109); /*error, larger than max size*/ + } + } + + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + + return error; +} + +static unsigned inflateNoCompression(ucvector * out, LodePNGBitReader * reader, + const LodePNGDecompressSettings * settings) +{ + size_t bytepos; + size_t size = reader->size; + unsigned LEN, NLEN, error = 0; + + /*go to first boundary of byte*/ + bytepos = (reader->bp + 7u) >> 3u; + + /*read LEN (2 bytes) and NLEN (2 bytes)*/ + if(bytepos + 4 >= size) return 52; /*error, bit pointer will jump past memory*/ + LEN = (unsigned)reader->data[bytepos] + ((unsigned)reader->data[bytepos + 1] << 8u); + bytepos += 2; + NLEN = (unsigned)reader->data[bytepos] + ((unsigned)reader->data[bytepos + 1] << 8u); + bytepos += 2; + + /*check if 16-bit NLEN is really the one's complement of LEN*/ + if(!settings->ignore_nlen && LEN + NLEN != 65535) { + return 21; /*error: NLEN is not one's complement of LEN*/ + } + + if(!ucvector_resize(out, out->size + LEN)) return 83; /*alloc fail*/ + + /*read the literal data: LEN bytes are now stored in the out buffer*/ + if(bytepos + LEN > size) return 23; /*error: reading outside of in buffer*/ + + lodepng_memcpy(out->data + out->size - LEN, reader->data + bytepos, LEN); + bytepos += LEN; + + reader->bp = bytepos << 3u; + + return error; +} + +static unsigned lodepng_inflatev(ucvector * out, + const unsigned char * in, size_t insize, + const LodePNGDecompressSettings * settings) +{ + unsigned BFINAL = 0; + LodePNGBitReader reader; + unsigned error = LodePNGBitReader_init(&reader, in, insize); + + if(error) return error; + + while(!BFINAL) { + unsigned BTYPE; + if(!ensureBits9(&reader, 3)) return 52; /*error, bit pointer will jump past memory*/ + BFINAL = readBits(&reader, 1); + BTYPE = readBits(&reader, 2); + + if(BTYPE == 3) return 20; /*error: invalid BTYPE*/ + else if(BTYPE == 0) error = inflateNoCompression(out, &reader, settings); /*no compression*/ + else error = inflateHuffmanBlock(out, &reader, BTYPE, settings->max_output_size); /*compression, BTYPE 01 or 10*/ + if(!error && settings->max_output_size && out->size > settings->max_output_size) error = 109; + if(error) break; + } + + return error; +} + +unsigned lodepng_inflate(unsigned char ** out, size_t * outsize, + const unsigned char * in, size_t insize, + const LodePNGDecompressSettings * settings) +{ + ucvector v = ucvector_init(*out, *outsize); + unsigned error = lodepng_inflatev(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + return error; +} + +static unsigned inflatev(ucvector * out, const unsigned char * in, size_t insize, + const LodePNGDecompressSettings * settings) +{ + if(settings->custom_inflate) { + unsigned error = settings->custom_inflate(&out->data, &out->size, in, insize, settings); + out->allocsize = out->size; + if(error) { + /*the custom inflate is allowed to have its own error codes, however, we translate it to code 110*/ + error = 110; + /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/ + if(settings->max_output_size && out->size > settings->max_output_size) error = 109; + } + return error; + } + else { + return lodepng_inflatev(out, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Deflator (Compressor) / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +static const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258; + +/*search the index in the array, that has the largest value smaller than or equal to the given value, +given array must be sorted (if no value is smaller, it returns the size of the given array)*/ +static size_t searchCodeIndex(const unsigned * array, size_t array_size, size_t value) +{ + /*binary search (only small gain over linear). TODO: use CPU log2 instruction for getting symbols instead*/ + size_t left = 1; + size_t right = array_size - 1; + + while(left <= right) { + size_t mid = (left + right) >> 1; + if(array[mid] >= value) right = mid - 1; + else left = mid + 1; + } + if(left >= array_size || array[left] > value) left--; + return left; +} + +static void addLengthDistance(uivector * values, size_t length, size_t distance) +{ + /*values in encoded vector are those used by deflate: + 0-255: literal bytes + 256: end + 257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits) + 286-287: invalid*/ + + unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length); + unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]); + unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance); + unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]); + + size_t pos = values->size; + /*TODO: return error when this fails (out of memory)*/ + unsigned ok = uivector_resize(values, values->size + 4); + if(ok) { + values->data[pos + 0] = length_code + FIRST_LENGTH_CODE_INDEX; + values->data[pos + 1] = extra_length; + values->data[pos + 2] = dist_code; + values->data[pos + 3] = extra_distance; + } +} + +/*3 bytes of data get encoded into two bytes. The hash cannot use more than 3 +bytes as input because 3 is the minimum match length for deflate*/ +static const unsigned HASH_NUM_VALUES = 65536; +static const unsigned HASH_BIT_MASK = 65535; /*HASH_NUM_VALUES - 1, but C90 does not like that as initializer*/ + +typedef struct Hash { + int * head; /*hash value to head circular pos - can be outdated if went around window*/ + /*circular pos to prev circular pos*/ + unsigned short * chain; + int * val; /*circular pos to hash value*/ + + /*TODO: do this not only for zeros but for any repeated byte. However for PNG + it's always going to be the zeros that dominate, so not important for PNG*/ + int * headz; /*similar to head, but for chainz*/ + unsigned short * chainz; /*those with same amount of zeros*/ + unsigned short * zeros; /*length of zeros streak, used as a second hash chain*/ +} Hash; + +static unsigned hash_init(Hash * hash, unsigned windowsize) +{ + unsigned i; + hash->head = (int *)lodepng_malloc(sizeof(int) * HASH_NUM_VALUES); + hash->val = (int *)lodepng_malloc(sizeof(int) * windowsize); + hash->chain = (unsigned short *)lodepng_malloc(sizeof(unsigned short) * windowsize); + + hash->zeros = (unsigned short *)lodepng_malloc(sizeof(unsigned short) * windowsize); + hash->headz = (int *)lodepng_malloc(sizeof(int) * (MAX_SUPPORTED_DEFLATE_LENGTH + 1)); + hash->chainz = (unsigned short *)lodepng_malloc(sizeof(unsigned short) * windowsize); + + if(!hash->head || !hash->chain || !hash->val || !hash->headz || !hash->chainz || !hash->zeros) { + return 83; /*alloc fail*/ + } + + /*initialize hash table*/ + for(i = 0; i != HASH_NUM_VALUES; ++i) hash->head[i] = -1; + for(i = 0; i != windowsize; ++i) hash->val[i] = -1; + for(i = 0; i != windowsize; ++i) hash->chain[i] = i; /*same value as index indicates uninitialized*/ + + for(i = 0; i <= MAX_SUPPORTED_DEFLATE_LENGTH; ++i) hash->headz[i] = -1; + for(i = 0; i != windowsize; ++i) hash->chainz[i] = i; /*same value as index indicates uninitialized*/ + + return 0; +} + +static void hash_cleanup(Hash * hash) +{ + lodepng_free(hash->head); + lodepng_free(hash->val); + lodepng_free(hash->chain); + + lodepng_free(hash->zeros); + lodepng_free(hash->headz); + lodepng_free(hash->chainz); +} + + + +static unsigned getHash(const unsigned char * data, size_t size, size_t pos) +{ + unsigned result = 0; + if(pos + 2 < size) { + /*A simple shift and xor hash is used. Since the data of PNGs is dominated + by zeroes due to the filters, a better hash does not have a significant + effect on speed in traversing the chain, and causes more time spend on + calculating the hash.*/ + result ^= ((unsigned)data[pos + 0] << 0u); + result ^= ((unsigned)data[pos + 1] << 4u); + result ^= ((unsigned)data[pos + 2] << 8u); + } + else { + size_t amount, i; + if(pos >= size) return 0; + amount = size - pos; + for(i = 0; i != amount; ++i) result ^= ((unsigned)data[pos + i] << (i * 8u)); + } + return result & HASH_BIT_MASK; +} + +static unsigned countZeros(const unsigned char * data, size_t size, size_t pos) +{ + const unsigned char * start = data + pos; + const unsigned char * end = start + MAX_SUPPORTED_DEFLATE_LENGTH; + if(end > data + size) end = data + size; + data = start; + while(data != end && *data == 0) ++data; + /*subtracting two addresses returned as 32-bit number (max value is MAX_SUPPORTED_DEFLATE_LENGTH)*/ + return (unsigned)(data - start); +} + +/*wpos = pos & (windowsize - 1)*/ +static void updateHashChain(Hash * hash, size_t wpos, unsigned hashval, unsigned short numzeros) +{ + hash->val[wpos] = (int)hashval; + if(hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval]; + hash->head[hashval] = (int)wpos; + + hash->zeros[wpos] = numzeros; + if(hash->headz[numzeros] != -1) hash->chainz[wpos] = hash->headz[numzeros]; + hash->headz[numzeros] = (int)wpos; +} + +/* +LZ77-encode the data. Return value is error code. The input are raw bytes, the output +is in the form of unsigned integers with codes representing for example literal bytes, or +length/distance pairs. +It uses a hash table technique to let it encode faster. When doing LZ77 encoding, a +sliding window (of windowsize) is used, and all past bytes in that window can be used as +the "dictionary". A brute force search through all possible distances would be slow, and +this hash technique is one out of several ways to speed this up. +*/ +static unsigned encodeLZ77(uivector * out, Hash * hash, + const unsigned char * in, size_t inpos, size_t insize, unsigned windowsize, + unsigned minmatch, unsigned nicematch, unsigned lazymatching) +{ + size_t pos; + unsigned i, error = 0; + /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/ + unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8u; + unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64; + + unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/ + unsigned numzeros = 0; + + unsigned offset; /*the offset represents the distance in LZ77 terminology*/ + unsigned length; + unsigned lazy = 0; + unsigned lazylength = 0, lazyoffset = 0; + unsigned hashval; + unsigned current_offset, current_length; + unsigned prev_offset; + const unsigned char * lastptr, * foreptr, * backptr; + unsigned hashpos; + + if(windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/ + if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/ + + if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH; + + for(pos = inpos; pos < insize; ++pos) { + size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/ + unsigned chainlength = 0; + + hashval = getHash(in, insize, pos); + + if(usezeros && hashval == 0) { + if(numzeros == 0) numzeros = countZeros(in, insize, pos); + else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; + } + else { + numzeros = 0; + } + + updateHashChain(hash, wpos, hashval, numzeros); + + /*the length and offset found for the current position*/ + length = 0; + offset = 0; + + hashpos = hash->chain[wpos]; + + lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH]; + + /*search for the longest string*/ + prev_offset = 0; + for(;;) { + if(chainlength++ >= maxchainlength) break; + current_offset = (unsigned)(hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize); + + if(current_offset < prev_offset) break; /*stop when went completely around the circular buffer*/ + prev_offset = current_offset; + if(current_offset > 0) { + /*test the next characters*/ + foreptr = &in[pos]; + backptr = &in[pos - current_offset]; + + /*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/ + if(numzeros >= 3) { + unsigned skip = hash->zeros[hashpos]; + if(skip > numzeros) skip = numzeros; + backptr += skip; + foreptr += skip; + } + + while(foreptr != lastptr && *backptr == *foreptr) { /*maximum supported length by deflate is max length*/ + ++backptr; + ++foreptr; + } + current_length = (unsigned)(foreptr - &in[pos]); + + if(current_length > length) { + length = current_length; /*the longest length*/ + offset = current_offset; /*the offset that is related to this longest length*/ + /*jump out once a length of max length is found (speed gain). This also jumps + out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/ + if(current_length >= nicematch) break; + } + } + + if(hashpos == hash->chain[hashpos]) break; + + if(numzeros >= 3 && length > numzeros) { + hashpos = hash->chainz[hashpos]; + if(hash->zeros[hashpos] != numzeros) break; + } + else { + hashpos = hash->chain[hashpos]; + /*outdated hash value, happens if particular value was not encountered in whole last window*/ + if(hash->val[hashpos] != (int)hashval) break; + } + } + + if(lazymatching) { + if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH) { + lazy = 1; + lazylength = length; + lazyoffset = offset; + continue; /*try the next byte*/ + } + if(lazy) { + lazy = 0; + if(pos == 0) ERROR_BREAK(81); + if(length > lazylength + 1) { + /*push the previous character as literal*/ + if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/); + } + else { + length = lazylength; + offset = lazyoffset; + hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/ + hash->headz[numzeros] = -1; /*idem*/ + --pos; + } + } + } + if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/); + + /*encode it as length/distance pair or literal value*/ + if(length < 3) { /*only lengths of 3 or higher are supported as length/distance pair*/ + if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); + } + else if(length < minmatch || (length == 3 && offset > 4096)) { + /*compensate for the fact that longer offsets have more extra bits, a + length of only 3 may be not worth it then*/ + if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); + } + else { + addLengthDistance(out, length, offset); + for(i = 1; i < length; ++i) { + ++pos; + wpos = pos & (windowsize - 1); + hashval = getHash(in, insize, pos); + if(usezeros && hashval == 0) { + if(numzeros == 0) numzeros = countZeros(in, insize, pos); + else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; + } + else { + numzeros = 0; + } + updateHashChain(hash, wpos, hashval, numzeros); + } + } + } /*end of the loop through each character of input*/ + + return error; +} + +/* /////////////////////////////////////////////////////////////////////////// */ + +static unsigned deflateNoCompression(ucvector * out, const unsigned char * data, size_t datasize) +{ + /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte, + 2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/ + + size_t i, numdeflateblocks = (datasize + 65534u) / 65535u; + unsigned datapos = 0; + for(i = 0; i != numdeflateblocks; ++i) { + unsigned BFINAL, BTYPE, LEN, NLEN; + unsigned char firstbyte; + size_t pos = out->size; + + BFINAL = (i == numdeflateblocks - 1); + BTYPE = 0; + + LEN = 65535; + if(datasize - datapos < 65535u) LEN = (unsigned)datasize - datapos; + NLEN = 65535 - LEN; + + if(!ucvector_resize(out, out->size + LEN + 5)) return 83; /*alloc fail*/ + + firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1u) << 1u) + ((BTYPE & 2u) << 1u)); + out->data[pos + 0] = firstbyte; + out->data[pos + 1] = (unsigned char)(LEN & 255); + out->data[pos + 2] = (unsigned char)(LEN >> 8u); + out->data[pos + 3] = (unsigned char)(NLEN & 255); + out->data[pos + 4] = (unsigned char)(NLEN >> 8u); + lodepng_memcpy(out->data + pos + 5, data + datapos, LEN); + datapos += LEN; + } + + return 0; +} + +/* +write the lz77-encoded data, which has lit, len and dist codes, to compressed stream using huffman trees. +tree_ll: the tree for lit and len codes. +tree_d: the tree for distance codes. +*/ +static void writeLZ77data(LodePNGBitWriter * writer, const uivector * lz77_encoded, + const HuffmanTree * tree_ll, const HuffmanTree * tree_d) +{ + size_t i = 0; + for(i = 0; i != lz77_encoded->size; ++i) { + unsigned val = lz77_encoded->data[i]; + writeBitsReversed(writer, tree_ll->codes[val], tree_ll->lengths[val]); + if(val > 256) { /*for a length code, 3 more things have to be added*/ + unsigned length_index = val - FIRST_LENGTH_CODE_INDEX; + unsigned n_length_extra_bits = LENGTHEXTRA[length_index]; + unsigned length_extra_bits = lz77_encoded->data[++i]; + + unsigned distance_code = lz77_encoded->data[++i]; + + unsigned distance_index = distance_code; + unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index]; + unsigned distance_extra_bits = lz77_encoded->data[++i]; + + writeBits(writer, length_extra_bits, n_length_extra_bits); + writeBitsReversed(writer, tree_d->codes[distance_code], tree_d->lengths[distance_code]); + writeBits(writer, distance_extra_bits, n_distance_extra_bits); + } + } +} + +/*Deflate for a block of type "dynamic", that is, with freely, optimally, created huffman trees*/ +static unsigned deflateDynamic(LodePNGBitWriter * writer, Hash * hash, + const unsigned char * data, size_t datapos, size_t dataend, + const LodePNGCompressSettings * settings, unsigned final) +{ + unsigned error = 0; + + /* + A block is compressed as follows: The PNG data is lz77 encoded, resulting in + literal bytes and length/distance pairs. This is then huffman compressed with + two huffman trees. One huffman tree is used for the lit and len values ("ll"), + another huffman tree is used for the dist values ("d"). These two trees are + stored using their code lengths, and to compress even more these code lengths + are also run-length encoded and huffman compressed. This gives a huffman tree + of code lengths "cl". The code lengths used to describe this third tree are + the code length code lengths ("clcl"). + */ + + /*The lz77 encoded data, represented with integers since there will also be length and distance codes in it*/ + uivector lz77_encoded; + HuffmanTree tree_ll; /*tree for lit,len values*/ + HuffmanTree tree_d; /*tree for distance codes*/ + HuffmanTree tree_cl; /*tree for encoding the code lengths representing tree_ll and tree_d*/ + unsigned * frequencies_ll = 0; /*frequency of lit,len codes*/ + unsigned * frequencies_d = 0; /*frequency of dist codes*/ + unsigned * frequencies_cl = 0; /*frequency of code length codes*/ + unsigned * bitlen_lld = 0; /*lit,len,dist code lengths (int bits), literally (without repeat codes).*/ + unsigned * bitlen_lld_e = 0; /*bitlen_lld encoded with repeat codes (this is a rudimentary run length compression)*/ + size_t datasize = dataend - datapos; + + /* + If we could call "bitlen_cl" the the code length code lengths ("clcl"), that is the bit lengths of codes to represent + tree_cl in CLCL_ORDER, then due to the huffman compression of huffman tree representations ("two levels"), there are + some analogies: + bitlen_lld is to tree_cl what data is to tree_ll and tree_d. + bitlen_lld_e is to bitlen_lld what lz77_encoded is to data. + bitlen_cl is to bitlen_lld_e what bitlen_lld is to lz77_encoded. + */ + + unsigned BFINAL = final; + size_t i; + size_t numcodes_ll, numcodes_d, numcodes_lld, numcodes_lld_e, numcodes_cl; + unsigned HLIT, HDIST, HCLEN; + + uivector_init(&lz77_encoded); + HuffmanTree_init(&tree_ll); + HuffmanTree_init(&tree_d); + HuffmanTree_init(&tree_cl); + /* could fit on stack, but >1KB is on the larger side so allocate instead */ + frequencies_ll = (unsigned *)lodepng_malloc(286 * sizeof(*frequencies_ll)); + frequencies_d = (unsigned *)lodepng_malloc(30 * sizeof(*frequencies_d)); + frequencies_cl = (unsigned *)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(*frequencies_cl)); + + if(!frequencies_ll || !frequencies_d || !frequencies_cl) error = 83; /*alloc fail*/ + + /*This while loop never loops due to a break at the end, it is here to + allow breaking out of it to the cleanup phase on error conditions.*/ + while(!error) { + lodepng_memset(frequencies_ll, 0, 286 * sizeof(*frequencies_ll)); + lodepng_memset(frequencies_d, 0, 30 * sizeof(*frequencies_d)); + lodepng_memset(frequencies_cl, 0, NUM_CODE_LENGTH_CODES * sizeof(*frequencies_cl)); + + if(settings->use_lz77) { + error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, + settings->minmatch, settings->nicematch, settings->lazymatching); + if(error) break; + } + else { + if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83 /*alloc fail*/); + for(i = datapos; i < dataend; + ++i) lz77_encoded.data[i - datapos] = data[i]; /*no LZ77, but still will be Huffman compressed*/ + } + + /*Count the frequencies of lit, len and dist codes*/ + for(i = 0; i != lz77_encoded.size; ++i) { + unsigned symbol = lz77_encoded.data[i]; + ++frequencies_ll[symbol]; + if(symbol > 256) { + unsigned dist = lz77_encoded.data[i + 2]; + ++frequencies_d[dist]; + i += 3; + } + } + frequencies_ll[256] = 1; /*there will be exactly 1 end code, at the end of the block*/ + + /*Make both huffman trees, one for the lit and len codes, one for the dist codes*/ + error = HuffmanTree_makeFromFrequencies(&tree_ll, frequencies_ll, 257, 286, 15); + if(error) break; + /*2, not 1, is chosen for mincodes: some buggy PNG decoders require at least 2 symbols in the dist tree*/ + error = HuffmanTree_makeFromFrequencies(&tree_d, frequencies_d, 2, 30, 15); + if(error) break; + + numcodes_ll = LODEPNG_MIN(tree_ll.numcodes, 286); + numcodes_d = LODEPNG_MIN(tree_d.numcodes, 30); + /*store the code lengths of both generated trees in bitlen_lld*/ + numcodes_lld = numcodes_ll + numcodes_d; + bitlen_lld = (unsigned *)lodepng_malloc(numcodes_lld * sizeof(*bitlen_lld)); + /*numcodes_lld_e never needs more size than bitlen_lld*/ + bitlen_lld_e = (unsigned *)lodepng_malloc(numcodes_lld * sizeof(*bitlen_lld_e)); + if(!bitlen_lld || !bitlen_lld_e) ERROR_BREAK(83); /*alloc fail*/ + numcodes_lld_e = 0; + + for(i = 0; i != numcodes_ll; ++i) bitlen_lld[i] = tree_ll.lengths[i]; + for(i = 0; i != numcodes_d; ++i) bitlen_lld[numcodes_ll + i] = tree_d.lengths[i]; + + /*run-length compress bitlen_ldd into bitlen_lld_e by using repeat codes 16 (copy length 3-6 times), + 17 (3-10 zeroes), 18 (11-138 zeroes)*/ + for(i = 0; i != numcodes_lld; ++i) { + unsigned j = 0; /*amount of repetitions*/ + while(i + j + 1 < numcodes_lld && bitlen_lld[i + j + 1] == bitlen_lld[i]) ++j; + + if(bitlen_lld[i] == 0 && j >= 2) { /*repeat code for zeroes*/ + ++j; /*include the first zero*/ + if(j <= 10) { /*repeat code 17 supports max 10 zeroes*/ + bitlen_lld_e[numcodes_lld_e++] = 17; + bitlen_lld_e[numcodes_lld_e++] = j - 3; + } + else { /*repeat code 18 supports max 138 zeroes*/ + if(j > 138) j = 138; + bitlen_lld_e[numcodes_lld_e++] = 18; + bitlen_lld_e[numcodes_lld_e++] = j - 11; + } + i += (j - 1); + } + else if(j >= 3) { /*repeat code for value other than zero*/ + size_t k; + unsigned num = j / 6u, rest = j % 6u; + bitlen_lld_e[numcodes_lld_e++] = bitlen_lld[i]; + for(k = 0; k < num; ++k) { + bitlen_lld_e[numcodes_lld_e++] = 16; + bitlen_lld_e[numcodes_lld_e++] = 6 - 3; + } + if(rest >= 3) { + bitlen_lld_e[numcodes_lld_e++] = 16; + bitlen_lld_e[numcodes_lld_e++] = rest - 3; + } + else j -= rest; + i += j; + } + else { /*too short to benefit from repeat code*/ + bitlen_lld_e[numcodes_lld_e++] = bitlen_lld[i]; + } + } + + /*generate tree_cl, the huffmantree of huffmantrees*/ + for(i = 0; i != numcodes_lld_e; ++i) { + ++frequencies_cl[bitlen_lld_e[i]]; + /*after a repeat code come the bits that specify the number of repetitions, + those don't need to be in the frequencies_cl calculation*/ + if(bitlen_lld_e[i] >= 16) ++i; + } + + error = HuffmanTree_makeFromFrequencies(&tree_cl, frequencies_cl, + NUM_CODE_LENGTH_CODES, NUM_CODE_LENGTH_CODES, 7); + if(error) break; + + /*compute amount of code-length-code-lengths to output*/ + numcodes_cl = NUM_CODE_LENGTH_CODES; + /*trim zeros at the end (using CLCL_ORDER), but minimum size must be 4 (see HCLEN below)*/ + while(numcodes_cl > 4u && tree_cl.lengths[CLCL_ORDER[numcodes_cl - 1u]] == 0) { + numcodes_cl--; + } + + /* + Write everything into the output + + After the BFINAL and BTYPE, the dynamic block consists out of the following: + - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN + - (HCLEN+4)*3 bits code lengths of code length alphabet + - HLIT + 257 code lengths of lit/length alphabet (encoded using the code length + alphabet, + possible repetition codes 16, 17, 18) + - HDIST + 1 code lengths of distance alphabet (encoded using the code length + alphabet, + possible repetition codes 16, 17, 18) + - compressed data + - 256 (end code) + */ + + /*Write block type*/ + writeBits(writer, BFINAL, 1); + writeBits(writer, 0, 1); /*first bit of BTYPE "dynamic"*/ + writeBits(writer, 1, 1); /*second bit of BTYPE "dynamic"*/ + + /*write the HLIT, HDIST and HCLEN values*/ + /*all three sizes take trimmed ending zeroes into account, done either by HuffmanTree_makeFromFrequencies + or in the loop for numcodes_cl above, which saves space. */ + HLIT = (unsigned)(numcodes_ll - 257); + HDIST = (unsigned)(numcodes_d - 1); + HCLEN = (unsigned)(numcodes_cl - 4); + writeBits(writer, HLIT, 5); + writeBits(writer, HDIST, 5); + writeBits(writer, HCLEN, 4); + + /*write the code lengths of the code length alphabet ("bitlen_cl")*/ + for(i = 0; i != numcodes_cl; ++i) writeBits(writer, tree_cl.lengths[CLCL_ORDER[i]], 3); + + /*write the lengths of the lit/len AND the dist alphabet*/ + for(i = 0; i != numcodes_lld_e; ++i) { + writeBitsReversed(writer, tree_cl.codes[bitlen_lld_e[i]], tree_cl.lengths[bitlen_lld_e[i]]); + /*extra bits of repeat codes*/ + if(bitlen_lld_e[i] == 16) writeBits(writer, bitlen_lld_e[++i], 2); + else if(bitlen_lld_e[i] == 17) writeBits(writer, bitlen_lld_e[++i], 3); + else if(bitlen_lld_e[i] == 18) writeBits(writer, bitlen_lld_e[++i], 7); + } + + /*write the compressed data symbols*/ + writeLZ77data(writer, &lz77_encoded, &tree_ll, &tree_d); + /*error: the length of the end code 256 must be larger than 0*/ + if(tree_ll.lengths[256] == 0) ERROR_BREAK(64); + + /*write the end code*/ + writeBitsReversed(writer, tree_ll.codes[256], tree_ll.lengths[256]); + + break; /*end of error-while*/ + } + + /*cleanup*/ + uivector_cleanup(&lz77_encoded); + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + HuffmanTree_cleanup(&tree_cl); + lodepng_free(frequencies_ll); + lodepng_free(frequencies_d); + lodepng_free(frequencies_cl); + lodepng_free(bitlen_lld); + lodepng_free(bitlen_lld_e); + + return error; +} + +static unsigned deflateFixed(LodePNGBitWriter * writer, Hash * hash, + const unsigned char * data, + size_t datapos, size_t dataend, + const LodePNGCompressSettings * settings, unsigned final) +{ + HuffmanTree tree_ll; /*tree for literal values and length codes*/ + HuffmanTree tree_d; /*tree for distance codes*/ + + unsigned BFINAL = final; + unsigned error = 0; + size_t i; + + HuffmanTree_init(&tree_ll); + HuffmanTree_init(&tree_d); + + error = generateFixedLitLenTree(&tree_ll); + if(!error) error = generateFixedDistanceTree(&tree_d); + + if(!error) { + writeBits(writer, BFINAL, 1); + writeBits(writer, 1, 1); /*first bit of BTYPE*/ + writeBits(writer, 0, 1); /*second bit of BTYPE*/ + + if(settings->use_lz77) { /*LZ77 encoded*/ + uivector lz77_encoded; + uivector_init(&lz77_encoded); + error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, + settings->minmatch, settings->nicematch, settings->lazymatching); + if(!error) writeLZ77data(writer, &lz77_encoded, &tree_ll, &tree_d); + uivector_cleanup(&lz77_encoded); + } + else { /*no LZ77, but still will be Huffman compressed*/ + for(i = datapos; i < dataend; ++i) { + writeBitsReversed(writer, tree_ll.codes[data[i]], tree_ll.lengths[data[i]]); + } + } + /*add END code*/ + if(!error) writeBitsReversed(writer, tree_ll.codes[256], tree_ll.lengths[256]); + } + + /*cleanup*/ + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + + return error; +} + +static unsigned lodepng_deflatev(ucvector * out, const unsigned char * in, size_t insize, + const LodePNGCompressSettings * settings) +{ + unsigned error = 0; + size_t i, blocksize, numdeflateblocks; + Hash hash; + LodePNGBitWriter writer; + + LodePNGBitWriter_init(&writer, out); + + if(settings->btype > 2) return 61; + else if(settings->btype == 0) return deflateNoCompression(out, in, insize); + else if(settings->btype == 1) blocksize = insize; + else { /*if(settings->btype == 2)*/ + /*on PNGs, deflate blocks of 65-262k seem to give most dense encoding*/ + blocksize = insize / 8u + 8; + if(blocksize < 65536) blocksize = 65536; + if(blocksize > 262144) blocksize = 262144; + } + + numdeflateblocks = (insize + blocksize - 1) / blocksize; + if(numdeflateblocks == 0) numdeflateblocks = 1; + + error = hash_init(&hash, settings->windowsize); + + if(!error) { + for(i = 0; i != numdeflateblocks && !error; ++i) { + unsigned final = (i == numdeflateblocks - 1); + size_t start = i * blocksize; + size_t end = start + blocksize; + if(end > insize) end = insize; + + if(settings->btype == 1) error = deflateFixed(&writer, &hash, in, start, end, settings, final); + else if(settings->btype == 2) error = deflateDynamic(&writer, &hash, in, start, end, settings, final); + } + } + + hash_cleanup(&hash); + + return error; +} + +unsigned lodepng_deflate(unsigned char ** out, size_t * outsize, + const unsigned char * in, size_t insize, + const LodePNGCompressSettings * settings) +{ + ucvector v = ucvector_init(*out, *outsize); + unsigned error = lodepng_deflatev(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + return error; +} + +static unsigned deflate(unsigned char ** out, size_t * outsize, + const unsigned char * in, size_t insize, + const LodePNGCompressSettings * settings) +{ + if(settings->custom_deflate) { + unsigned error = settings->custom_deflate(out, outsize, in, insize, settings); + /*the custom deflate is allowed to have its own error codes, however, we translate it to code 111*/ + return error ? 111 : 0; + } + else { + return lodepng_deflate(out, outsize, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Adler32 / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +static unsigned update_adler32(unsigned adler, const unsigned char * data, unsigned len) +{ + unsigned s1 = adler & 0xffffu; + unsigned s2 = (adler >> 16u) & 0xffffu; + + while(len != 0u) { + unsigned i; + /*at least 5552 sums can be done before the sums overflow, saving a lot of module divisions*/ + unsigned amount = len > 5552u ? 5552u : len; + len -= amount; + for(i = 0; i != amount; ++i) { + s1 += (*data++); + s2 += s1; + } + s1 %= 65521u; + s2 %= 65521u; + } + + return (s2 << 16u) | s1; +} + +/*Return the adler32 of the bytes data[0..len-1]*/ +static unsigned adler32(const unsigned char * data, unsigned len) +{ + return update_adler32(1u, data, len); +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Zlib / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_DECODER + +static unsigned lodepng_zlib_decompressv(ucvector * out, + const unsigned char * in, size_t insize, + const LodePNGDecompressSettings * settings) +{ + unsigned error = 0; + unsigned CM, CINFO, FDICT; + + if(insize < 2) return 53; /*error, size of zlib data too small*/ + /*read information from zlib header*/ + if((in[0] * 256 + in[1]) % 31 != 0) { + /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/ + return 24; + } + + CM = in[0] & 15; + CINFO = (in[0] >> 4) & 15; + /*FCHECK = in[1] & 31;*/ /*FCHECK is already tested above*/ + FDICT = (in[1] >> 5) & 1; + /*FLEVEL = (in[1] >> 6) & 3;*/ /*FLEVEL is not used here*/ + + if(CM != 8 || CINFO > 7) { + /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/ + return 25; + } + if(FDICT != 0) { + /*error: the specification of PNG says about the zlib stream: + "The additional flags shall not specify a preset dictionary."*/ + return 26; + } + + error = inflatev(out, in + 2, insize - 2, settings); + if(error) return error; + + if(!settings->ignore_adler32) { + unsigned ADLER32 = lodepng_read32bitInt(&in[insize - 4]); + unsigned checksum = adler32(out->data, (unsigned)(out->size)); + if(checksum != ADLER32) return 58; /*error, adler checksum not correct, data must be corrupted*/ + } + + return 0; /*no error*/ +} + + +unsigned lodepng_zlib_decompress(unsigned char ** out, size_t * outsize, const unsigned char * in, + size_t insize, const LodePNGDecompressSettings * settings) +{ + ucvector v = ucvector_init(*out, *outsize); + unsigned error = lodepng_zlib_decompressv(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + return error; +} + +/*expected_size is expected output size, to avoid intermediate allocations. Set to 0 if not known. */ +static unsigned zlib_decompress(unsigned char ** out, size_t * outsize, size_t expected_size, + const unsigned char * in, size_t insize, const LodePNGDecompressSettings * settings) +{ + unsigned error; + if(settings->custom_zlib) { + error = settings->custom_zlib(out, outsize, in, insize, settings); + if(error) { + /*the custom zlib is allowed to have its own error codes, however, we translate it to code 110*/ + error = 110; + /*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/ + if(settings->max_output_size && *outsize > settings->max_output_size) error = 109; + } + } + else { + ucvector v = ucvector_init(*out, *outsize); + if(expected_size) { + /*reserve the memory to avoid intermediate reallocations*/ + ucvector_resize(&v, *outsize + expected_size); + v.size = *outsize; + } + error = lodepng_zlib_decompressv(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + } + return error; +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER + +unsigned lodepng_zlib_compress(unsigned char ** out, size_t * outsize, const unsigned char * in, + size_t insize, const LodePNGCompressSettings * settings) +{ + size_t i; + unsigned error; + unsigned char * deflatedata = 0; + size_t deflatesize = 0; + + error = deflate(&deflatedata, &deflatesize, in, insize, settings); + + *out = NULL; + *outsize = 0; + if(!error) { + *outsize = deflatesize + 6; + *out = (unsigned char *)lodepng_malloc(*outsize); + if(!*out) error = 83; /*alloc fail*/ + } + + if(!error) { + unsigned ADLER32 = adler32(in, (unsigned)insize); + /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/ + unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/ + unsigned FLEVEL = 0; + unsigned FDICT = 0; + unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64; + unsigned FCHECK = 31 - CMFFLG % 31; + CMFFLG += FCHECK; + + (*out)[0] = (unsigned char)(CMFFLG >> 8); + (*out)[1] = (unsigned char)(CMFFLG & 255); + for(i = 0; i != deflatesize; ++i)(*out)[i + 2] = deflatedata[i]; + lodepng_set32bitInt(&(*out)[*outsize - 4], ADLER32); + } + + lodepng_free(deflatedata); + return error; +} + +/* compress using the default or custom zlib function */ +static unsigned zlib_compress(unsigned char ** out, size_t * outsize, const unsigned char * in, + size_t insize, const LodePNGCompressSettings * settings) +{ + if(settings->custom_zlib) { + unsigned error = settings->custom_zlib(out, outsize, in, insize, settings); + /*the custom zlib is allowed to have its own error codes, however, we translate it to code 111*/ + return error ? 111 : 0; + } + else { + return lodepng_zlib_compress(out, outsize, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#else /*no LODEPNG_COMPILE_ZLIB*/ + +#ifdef LODEPNG_COMPILE_DECODER +static unsigned zlib_decompress(unsigned char ** out, size_t * outsize, size_t expected_size, + const unsigned char * in, size_t insize, const LodePNGDecompressSettings * settings) +{ + if(!settings->custom_zlib) return 87; /*no custom zlib function provided */ + LV_UNUSED(expected_size); + return settings->custom_zlib(out, outsize, in, insize, settings); +} +#endif /*LODEPNG_COMPILE_DECODER*/ +#ifdef LODEPNG_COMPILE_ENCODER +static unsigned zlib_compress(unsigned char ** out, size_t * outsize, const unsigned char * in, + size_t insize, const LodePNGCompressSettings * settings) +{ + if(!settings->custom_zlib) return 87; /*no custom zlib function provided */ + return settings->custom_zlib(out, outsize, in, insize, settings); +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#endif /*LODEPNG_COMPILE_ZLIB*/ + +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_ENCODER + +/*this is a good tradeoff between speed and compression ratio*/ +#define DEFAULT_WINDOWSIZE 2048 + +void lodepng_compress_settings_init(LodePNGCompressSettings * settings) +{ + /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/ + settings->btype = 2; + settings->use_lz77 = 1; + settings->windowsize = DEFAULT_WINDOWSIZE; + settings->minmatch = 3; + settings->nicematch = 128; + settings->lazymatching = 1; + + settings->custom_zlib = 0; + settings->custom_deflate = 0; + settings->custom_context = 0; +} + +const LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT_WINDOWSIZE, 3, 128, 1, 0, 0, 0}; + + +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_DECODER + +void lodepng_decompress_settings_init(LodePNGDecompressSettings * settings) +{ + settings->ignore_adler32 = 0; + settings->ignore_nlen = 0; + settings->max_output_size = 0; + + settings->custom_zlib = 0; + settings->custom_inflate = 0; + settings->custom_context = 0; +} + +const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0, 0, 0}; + +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // End of Zlib related code. Begin of PNG related code. // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_PNG + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / CRC32 / */ +/* ////////////////////////////////////////////////////////////////////////// */ + + +#ifndef LODEPNG_NO_COMPILE_CRC +/* CRC polynomial: 0xedb88320 */ +static unsigned lodepng_crc32_table[256] = { + 0u, 1996959894u, 3993919788u, 2567524794u, 124634137u, 1886057615u, 3915621685u, 2657392035u, + 249268274u, 2044508324u, 3772115230u, 2547177864u, 162941995u, 2125561021u, 3887607047u, 2428444049u, + 498536548u, 1789927666u, 4089016648u, 2227061214u, 450548861u, 1843258603u, 4107580753u, 2211677639u, + 325883990u, 1684777152u, 4251122042u, 2321926636u, 335633487u, 1661365465u, 4195302755u, 2366115317u, + 997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u, + 901097722u, 1119000684u, 3686517206u, 2898065728u, 853044451u, 1172266101u, 3705015759u, 2882616665u, + 651767980u, 1373503546u, 3369554304u, 3218104598u, 565507253u, 1454621731u, 3485111705u, 3099436303u, + 671266974u, 1594198024u, 3322730930u, 2970347812u, 795835527u, 1483230225u, 3244367275u, 3060149565u, + 1994146192u, 31158534u, 2563907772u, 4023717930u, 1907459465u, 112637215u, 2680153253u, 3904427059u, + 2013776290u, 251722036u, 2517215374u, 3775830040u, 2137656763u, 141376813u, 2439277719u, 3865271297u, + 1802195444u, 476864866u, 2238001368u, 4066508878u, 1812370925u, 453092731u, 2181625025u, 4111451223u, + 1706088902u, 314042704u, 2344532202u, 4240017532u, 1658658271u, 366619977u, 2362670323u, 4224994405u, + 1303535960u, 984961486u, 2747007092u, 3569037538u, 1256170817u, 1037604311u, 2765210733u, 3554079995u, + 1131014506u, 879679996u, 2909243462u, 3663771856u, 1141124467u, 855842277u, 2852801631u, 3708648649u, + 1342533948u, 654459306u, 3188396048u, 3373015174u, 1466479909u, 544179635u, 3110523913u, 3462522015u, + 1591671054u, 702138776u, 2966460450u, 3352799412u, 1504918807u, 783551873u, 3082640443u, 3233442989u, + 3988292384u, 2596254646u, 62317068u, 1957810842u, 3939845945u, 2647816111u, 81470997u, 1943803523u, + 3814918930u, 2489596804u, 225274430u, 2053790376u, 3826175755u, 2466906013u, 167816743u, 2097651377u, + 4027552580u, 2265490386u, 503444072u, 1762050814u, 4150417245u, 2154129355u, 426522225u, 1852507879u, + 4275313526u, 2312317920u, 282753626u, 1742555852u, 4189708143u, 2394877945u, 397917763u, 1622183637u, + 3604390888u, 2714866558u, 953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u, + 3624741850u, 2936675148u, 906185462u, 1090812512u, 3747672003u, 2825379669u, 829329135u, 1181335161u, + 3412177804u, 3160834842u, 628085408u, 1382605366u, 3423369109u, 3138078467u, 570562233u, 1426400815u, + 3317316542u, 2998733608u, 733239954u, 1555261956u, 3268935591u, 3050360625u, 752459403u, 1541320221u, + 2607071920u, 3965973030u, 1969922972u, 40735498u, 2617837225u, 3943577151u, 1913087877u, 83908371u, + 2512341634u, 3803740692u, 2075208622u, 213261112u, 2463272603u, 3855990285u, 2094854071u, 198958881u, + 2262029012u, 4057260610u, 1759359992u, 534414190u, 2176718541u, 4139329115u, 1873836001u, 414664567u, + 2282248934u, 4279200368u, 1711684554u, 285281116u, 2405801727u, 4167216745u, 1634467795u, 376229701u, + 2685067896u, 3608007406u, 1308918612u, 956543938u, 2808555105u, 3495958263u, 1231636301u, 1047427035u, + 2932959818u, 3654703836u, 1088359270u, 936918000u, 2847714899u, 3736837829u, 1202900863u, 817233897u, + 3183342108u, 3401237130u, 1404277552u, 615818150u, 3134207493u, 3453421203u, 1423857449u, 601450431u, + 3009837614u, 3294710456u, 1567103746u, 711928724u, 3020668471u, 3272380065u, 1510334235u, 755167117u +}; + +/*Return the CRC of the bytes buf[0..len-1].*/ +unsigned lodepng_crc32(const unsigned char * data, size_t length) +{ + unsigned r = 0xffffffffu; + size_t i; + for(i = 0; i < length; ++i) { + r = lodepng_crc32_table[(r ^ data[i]) & 0xffu] ^ (r >> 8u); + } + return r ^ 0xffffffffu; +} +#else /* !LODEPNG_NO_COMPILE_CRC */ +unsigned lodepng_crc32(const unsigned char * data, size_t length); +#endif /* !LODEPNG_NO_COMPILE_CRC */ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Reading and writing PNG color channel bits / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/* The color channel bits of less-than-8-bit pixels are read with the MSB of bytes first, +so LodePNGBitWriter and LodePNGBitReader can't be used for those. */ + +static unsigned char readBitFromReversedStream(size_t * bitpointer, const unsigned char * bitstream) +{ + unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1); + ++(*bitpointer); + return result; +} + +/* TODO: make this faster */ +static unsigned readBitsFromReversedStream(size_t * bitpointer, const unsigned char * bitstream, size_t nbits) +{ + unsigned result = 0; + size_t i; + for(i = 0 ; i < nbits; ++i) { + result <<= 1u; + result |= (unsigned)readBitFromReversedStream(bitpointer, bitstream); + } + return result; +} + +static void setBitOfReversedStream(size_t * bitpointer, unsigned char * bitstream, unsigned char bit) +{ + /*the current bit in bitstream may be 0 or 1 for this to work*/ + if(bit == 0) bitstream[(*bitpointer) >> 3u] &= (unsigned char)(~(1u << (7u - ((*bitpointer) & 7u)))); + else bitstream[(*bitpointer) >> 3u] |= (1u << (7u - ((*bitpointer) & 7u))); + ++(*bitpointer); +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / PNG chunks / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +unsigned lodepng_chunk_length(const unsigned char * chunk) +{ + return lodepng_read32bitInt(&chunk[0]); +} + +void lodepng_chunk_type(char type[5], const unsigned char * chunk) +{ + unsigned i; + for(i = 0; i != 4; ++i) type[i] = (char)chunk[4 + i]; + type[4] = 0; /*null termination char*/ +} + +unsigned char lodepng_chunk_type_equals(const unsigned char * chunk, const char * type) +{ + if(lodepng_strlen(type) != 4) return 0; + return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]); +} + +unsigned char lodepng_chunk_ancillary(const unsigned char * chunk) +{ + return((chunk[4] & 32) != 0); +} + +unsigned char lodepng_chunk_private(const unsigned char * chunk) +{ + return((chunk[6] & 32) != 0); +} + +unsigned char lodepng_chunk_safetocopy(const unsigned char * chunk) +{ + return((chunk[7] & 32) != 0); +} + +unsigned char * lodepng_chunk_data(unsigned char * chunk) +{ + return &chunk[8]; +} + +const unsigned char * lodepng_chunk_data_const(const unsigned char * chunk) +{ + return &chunk[8]; +} + +unsigned lodepng_chunk_check_crc(const unsigned char * chunk) +{ + unsigned length = lodepng_chunk_length(chunk); + unsigned CRC = lodepng_read32bitInt(&chunk[length + 8]); + /*the CRC is taken of the data and the 4 chunk type letters, not the length*/ + unsigned checksum = lodepng_crc32(&chunk[4], length + 4); + if(CRC != checksum) return 1; + else return 0; +} + +void lodepng_chunk_generate_crc(unsigned char * chunk) +{ + unsigned length = lodepng_chunk_length(chunk); + unsigned CRC = lodepng_crc32(&chunk[4], length + 4); + lodepng_set32bitInt(chunk + 8 + length, CRC); +} + +unsigned char * lodepng_chunk_next(unsigned char * chunk, unsigned char * end) +{ + if(chunk >= end || end - chunk < 12) return end; /*too small to contain a chunk*/ + if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47 + && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) { + /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */ + return chunk + 8; + } + else { + size_t total_chunk_length; + unsigned char * result; + if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end; + result = chunk + total_chunk_length; + if(result < chunk) return end; /*pointer overflow*/ + return result; + } +} + +const unsigned char * lodepng_chunk_next_const(const unsigned char * chunk, const unsigned char * end) +{ + if(chunk >= end || end - chunk < 12) return end; /*too small to contain a chunk*/ + if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47 + && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) { + /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */ + return chunk + 8; + } + else { + size_t total_chunk_length; + const unsigned char * result; + if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end; + result = chunk + total_chunk_length; + if(result < chunk) return end; /*pointer overflow*/ + return result; + } +} + +unsigned char * lodepng_chunk_find(unsigned char * chunk, unsigned char * end, const char type[5]) +{ + for(;;) { + if(chunk >= end || end - chunk < 12) return 0; /* past file end: chunk + 12 > end */ + if(lodepng_chunk_type_equals(chunk, type)) return chunk; + chunk = lodepng_chunk_next(chunk, end); + } + + return 0; /*Shouldn't reach this*/ +} + +const unsigned char * lodepng_chunk_find_const(const unsigned char * chunk, const unsigned char * end, + const char type[5]) +{ + for(;;) { + if(chunk >= end || end - chunk < 12) return 0; /* past file end: chunk + 12 > end */ + if(lodepng_chunk_type_equals(chunk, type)) return chunk; + chunk = lodepng_chunk_next_const(chunk, end); + } + + return 0; /*Shouldn't reach this*/ +} + +unsigned lodepng_chunk_append(unsigned char ** out, size_t * outsize, const unsigned char * chunk) +{ + unsigned i; + size_t total_chunk_length, new_length; + unsigned char * chunk_start, * new_buffer; + + if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return 77; + if(lodepng_addofl(*outsize, total_chunk_length, &new_length)) return 77; + + new_buffer = (unsigned char *)lodepng_realloc(*out, new_length); + if(!new_buffer) return 83; /*alloc fail*/ + (*out) = new_buffer; + (*outsize) = new_length; + chunk_start = &(*out)[new_length - total_chunk_length]; + + for(i = 0; i != total_chunk_length; ++i) chunk_start[i] = chunk[i]; + + return 0; +} + +/*Sets length and name and allocates the space for data and crc but does not +set data or crc yet. Returns the start of the chunk in chunk. The start of +the data is at chunk + 8. To finalize chunk, add the data, then use +lodepng_chunk_generate_crc */ +static unsigned lodepng_chunk_init(unsigned char ** chunk, + ucvector * out, + unsigned length, const char * type) +{ + size_t new_length = out->size; + if(lodepng_addofl(new_length, length, &new_length)) return 77; + if(lodepng_addofl(new_length, 12, &new_length)) return 77; + if(!ucvector_resize(out, new_length)) return 83; /*alloc fail*/ + *chunk = out->data + new_length - length - 12u; + + /*1: length*/ + lodepng_set32bitInt(*chunk, length); + + /*2: chunk name (4 letters)*/ + lodepng_memcpy(*chunk + 4, type, 4); + + return 0; +} + +/* like lodepng_chunk_create but with custom allocsize */ +static unsigned lodepng_chunk_createv(ucvector * out, + unsigned length, const char * type, const unsigned char * data) +{ + unsigned char * chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, length, type)); + + /*3: the data*/ + lodepng_memcpy(chunk + 8, data, length); + + /*4: CRC (of the chunkname characters and the data)*/ + lodepng_chunk_generate_crc(chunk); + + return 0; +} + +unsigned lodepng_chunk_create(unsigned char ** out, size_t * outsize, + unsigned length, const char * type, const unsigned char * data) +{ + ucvector v = ucvector_init(*out, *outsize); + unsigned error = lodepng_chunk_createv(&v, length, type, data); + *out = v.data; + *outsize = v.size; + return error; +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Color types, channels, bits / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*checks if the colortype is valid and the bitdepth bd is allowed for this colortype. +Return value is a LodePNG error code.*/ +static unsigned checkColorValidity(LodePNGColorType colortype, unsigned bd) +{ + switch(colortype) { + case LCT_GREY: + if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; + break; + case LCT_RGB: + if(!(bd == 8 || bd == 16)) return 37; + break; + case LCT_PALETTE: + if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8)) return 37; + break; + case LCT_GREY_ALPHA: + if(!(bd == 8 || bd == 16)) return 37; + break; + case LCT_RGBA: + if(!(bd == 8 || bd == 16)) return 37; + break; + case LCT_MAX_OCTET_VALUE: + return 31; /* invalid color type */ + default: + return 31; /* invalid color type */ + } + return 0; /*allowed color type / bits combination*/ +} + +static unsigned getNumColorChannels(LodePNGColorType colortype) +{ + switch(colortype) { + case LCT_GREY: + return 1; + case LCT_RGB: + return 3; + case LCT_PALETTE: + return 1; + case LCT_GREY_ALPHA: + return 2; + case LCT_RGBA: + return 4; + case LCT_MAX_OCTET_VALUE: + return 0; /* invalid color type */ + default: + return 0; /*invalid color type*/ + } +} + +static unsigned lodepng_get_bpp_lct(LodePNGColorType colortype, unsigned bitdepth) +{ + /*bits per pixel is amount of channels * bits per channel*/ + return getNumColorChannels(colortype) * bitdepth; +} + +/* ////////////////////////////////////////////////////////////////////////// */ + +void lodepng_color_mode_init(LodePNGColorMode * info) +{ + info->key_defined = 0; + info->key_r = info->key_g = info->key_b = 0; + info->colortype = LCT_RGBA; + info->bitdepth = 8; + info->palette = 0; + info->palettesize = 0; +} + +/*allocates palette memory if needed, and initializes all colors to black*/ +static void lodepng_color_mode_alloc_palette(LodePNGColorMode * info) +{ + size_t i; + /*if the palette is already allocated, it will have size 1024 so no reallocation needed in that case*/ + /*the palette must have room for up to 256 colors with 4 bytes each.*/ + if(!info->palette) info->palette = (unsigned char *)lodepng_malloc(1024); + if(!info->palette) return; /*alloc fail*/ + for(i = 0; i != 256; ++i) { + /*Initialize all unused colors with black, the value used for invalid palette indices. + This is an error according to the PNG spec, but common PNG decoders make it black instead. + That makes color conversion slightly faster due to no error handling needed.*/ + info->palette[i * 4 + 0] = 0; + info->palette[i * 4 + 1] = 0; + info->palette[i * 4 + 2] = 0; + info->palette[i * 4 + 3] = 255; + } +} + +void lodepng_color_mode_cleanup(LodePNGColorMode * info) +{ + lodepng_palette_clear(info); +} + +unsigned lodepng_color_mode_copy(LodePNGColorMode * dest, const LodePNGColorMode * source) +{ + lodepng_color_mode_cleanup(dest); + lodepng_memcpy(dest, source, sizeof(LodePNGColorMode)); + if(source->palette) { + dest->palette = (unsigned char *)lodepng_malloc(1024); + if(!dest->palette && source->palettesize) return 83; /*alloc fail*/ + lodepng_memcpy(dest->palette, source->palette, source->palettesize * 4); + } + return 0; +} + +LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth) +{ + LodePNGColorMode result; + lodepng_color_mode_init(&result); + result.colortype = colortype; + result.bitdepth = bitdepth; + return result; +} + +static int lodepng_color_mode_equal(const LodePNGColorMode * a, const LodePNGColorMode * b) +{ + size_t i; + if(a->colortype != b->colortype) return 0; + if(a->bitdepth != b->bitdepth) return 0; + if(a->key_defined != b->key_defined) return 0; + if(a->key_defined) { + if(a->key_r != b->key_r) return 0; + if(a->key_g != b->key_g) return 0; + if(a->key_b != b->key_b) return 0; + } + if(a->palettesize != b->palettesize) return 0; + for(i = 0; i != a->palettesize * 4; ++i) { + if(a->palette[i] != b->palette[i]) return 0; + } + return 1; +} + +void lodepng_palette_clear(LodePNGColorMode * info) +{ + if(info->palette) lodepng_free(info->palette); + info->palette = 0; + info->palettesize = 0; +} + +unsigned lodepng_palette_add(LodePNGColorMode * info, + unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + if(!info->palette) { /*allocate palette if empty*/ + lodepng_color_mode_alloc_palette(info); + if(!info->palette) return 83; /*alloc fail*/ + } + if(info->palettesize >= 256) { + return 108; /*too many palette values*/ + } + info->palette[4 * info->palettesize + 0] = r; + info->palette[4 * info->palettesize + 1] = g; + info->palette[4 * info->palettesize + 2] = b; + info->palette[4 * info->palettesize + 3] = a; + ++info->palettesize; + return 0; +} + +/*calculate bits per pixel out of colortype and bitdepth*/ +unsigned lodepng_get_bpp(const LodePNGColorMode * info) +{ + return lodepng_get_bpp_lct(info->colortype, info->bitdepth); +} + +unsigned lodepng_get_channels(const LodePNGColorMode * info) +{ + return getNumColorChannels(info->colortype); +} + +unsigned lodepng_is_greyscale_type(const LodePNGColorMode * info) +{ + return info->colortype == LCT_GREY || info->colortype == LCT_GREY_ALPHA; +} + +unsigned lodepng_is_alpha_type(const LodePNGColorMode * info) +{ + return (info->colortype & 4) != 0; /*4 or 6*/ +} + +unsigned lodepng_is_palette_type(const LodePNGColorMode * info) +{ + return info->colortype == LCT_PALETTE; +} + +unsigned lodepng_has_palette_alpha(const LodePNGColorMode * info) +{ + size_t i; + for(i = 0; i != info->palettesize; ++i) { + if(info->palette[i * 4 + 3] < 255) return 1; + } + return 0; +} + +unsigned lodepng_can_have_alpha(const LodePNGColorMode * info) +{ + return info->key_defined + || lodepng_is_alpha_type(info) + || lodepng_has_palette_alpha(info); +} + +static size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) +{ + size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth); + size_t n = (size_t)w * (size_t)h; + return ((n / 8u) * bpp) + ((n & 7u) * bpp + 7u) / 8u; +} + +size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode * color) +{ + return lodepng_get_raw_size_lct(w, h, color->colortype, color->bitdepth); +} + + +#ifdef LODEPNG_COMPILE_PNG + +/*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer, +and in addition has one extra byte per line: the filter byte. So this gives a larger +result than lodepng_get_raw_size. Set h to 1 to get the size of 1 row including filter byte. */ +static size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, unsigned bpp) +{ + /* + 1 for the filter byte, and possibly plus padding bits per line. */ + /* Ignoring casts, the expression is equal to (w * bpp + 7) / 8 + 1, but avoids overflow of w * bpp */ + size_t line = ((size_t)(w / 8u) * bpp) + 1u + ((w & 7u) * bpp + 7u) / 8u; + return (size_t)h * line; +} + +#ifdef LODEPNG_COMPILE_DECODER +/*Safely checks whether size_t overflow can be caused due to amount of pixels. +This check is overcautious rather than precise. If this check indicates no overflow, +you can safely compute in a size_t (but not an unsigned): +-(size_t)w * (size_t)h * 8 +-amount of bytes in IDAT (including filter, padding and Adam7 bytes) +-amount of bytes in raw color model +Returns 1 if overflow possible, 0 if not. +*/ +static int lodepng_pixel_overflow(unsigned w, unsigned h, + const LodePNGColorMode * pngcolor, const LodePNGColorMode * rawcolor) +{ + size_t bpp = LODEPNG_MAX(lodepng_get_bpp(pngcolor), lodepng_get_bpp(rawcolor)); + size_t numpixels, total; + size_t line; /* bytes per line in worst case */ + + if(lodepng_mulofl((size_t)w, (size_t)h, &numpixels)) return 1; + if(lodepng_mulofl(numpixels, 8, &total)) return 1; /* bit pointer with 8-bit color, or 8 bytes per channel color */ + + /* Bytes per scanline with the expression "(w / 8u) * bpp) + ((w & 7u) * bpp + 7u) / 8u" */ + if(lodepng_mulofl((size_t)(w / 8u), bpp, &line)) return 1; + if(lodepng_addofl(line, ((w & 7u) * bpp + 7u) / 8u, &line)) return 1; + + if(lodepng_addofl(line, 5, &line)) return 1; /* 5 bytes overhead per line: 1 filterbyte, 4 for Adam7 worst case */ + if(lodepng_mulofl(line, h, &total)) return 1; /* Total bytes in worst case */ + + return 0; /* no overflow */ +} +#endif /*LODEPNG_COMPILE_DECODER*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + +static void LodePNGUnknownChunks_init(LodePNGInfo * info) +{ + unsigned i; + for(i = 0; i != 3; ++i) info->unknown_chunks_data[i] = 0; + for(i = 0; i != 3; ++i) info->unknown_chunks_size[i] = 0; +} + +static void LodePNGUnknownChunks_cleanup(LodePNGInfo * info) +{ + unsigned i; + for(i = 0; i != 3; ++i) lodepng_free(info->unknown_chunks_data[i]); +} + +static unsigned LodePNGUnknownChunks_copy(LodePNGInfo * dest, const LodePNGInfo * src) +{ + unsigned i; + + LodePNGUnknownChunks_cleanup(dest); + + for(i = 0; i != 3; ++i) { + size_t j; + dest->unknown_chunks_size[i] = src->unknown_chunks_size[i]; + dest->unknown_chunks_data[i] = (unsigned char *)lodepng_malloc(src->unknown_chunks_size[i]); + if(!dest->unknown_chunks_data[i] && dest->unknown_chunks_size[i]) return 83; /*alloc fail*/ + for(j = 0; j < src->unknown_chunks_size[i]; ++j) { + dest->unknown_chunks_data[i][j] = src->unknown_chunks_data[i][j]; + } + } + + return 0; +} + +/******************************************************************************/ + +static void LodePNGText_init(LodePNGInfo * info) +{ + info->text_num = 0; + info->text_keys = NULL; + info->text_strings = NULL; +} + +static void LodePNGText_cleanup(LodePNGInfo * info) +{ + size_t i; + for(i = 0; i != info->text_num; ++i) { + string_cleanup(&info->text_keys[i]); + string_cleanup(&info->text_strings[i]); + } + lodepng_free(info->text_keys); + lodepng_free(info->text_strings); +} + +static unsigned LodePNGText_copy(LodePNGInfo * dest, const LodePNGInfo * source) +{ + size_t i = 0; + dest->text_keys = NULL; + dest->text_strings = NULL; + dest->text_num = 0; + for(i = 0; i != source->text_num; ++i) { + CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i])); + } + return 0; +} + +static unsigned lodepng_add_text_sized(LodePNGInfo * info, const char * key, const char * str, size_t size) +{ + char ** new_keys = (char **)(lodepng_realloc(info->text_keys, sizeof(char *) * (info->text_num + 1))); + char ** new_strings = (char **)(lodepng_realloc(info->text_strings, sizeof(char *) * (info->text_num + 1))); + + if(new_keys) info->text_keys = new_keys; + if(new_strings) info->text_strings = new_strings; + + if(!new_keys || !new_strings) return 83; /*alloc fail*/ + + ++info->text_num; + info->text_keys[info->text_num - 1] = alloc_string(key); + info->text_strings[info->text_num - 1] = alloc_string_sized(str, size); + if(!info->text_keys[info->text_num - 1] || !info->text_strings[info->text_num - 1]) return 83; /*alloc fail*/ + + return 0; +} + +unsigned lodepng_add_text(LodePNGInfo * info, const char * key, const char * str) +{ + return lodepng_add_text_sized(info, key, str, lodepng_strlen(str)); +} + +void lodepng_clear_text(LodePNGInfo * info) +{ + LodePNGText_cleanup(info); +} + +/******************************************************************************/ + +static void LodePNGIText_init(LodePNGInfo * info) +{ + info->itext_num = 0; + info->itext_keys = NULL; + info->itext_langtags = NULL; + info->itext_transkeys = NULL; + info->itext_strings = NULL; +} + +static void LodePNGIText_cleanup(LodePNGInfo * info) +{ + size_t i; + for(i = 0; i != info->itext_num; ++i) { + string_cleanup(&info->itext_keys[i]); + string_cleanup(&info->itext_langtags[i]); + string_cleanup(&info->itext_transkeys[i]); + string_cleanup(&info->itext_strings[i]); + } + lodepng_free(info->itext_keys); + lodepng_free(info->itext_langtags); + lodepng_free(info->itext_transkeys); + lodepng_free(info->itext_strings); +} + +static unsigned LodePNGIText_copy(LodePNGInfo * dest, const LodePNGInfo * source) +{ + size_t i = 0; + dest->itext_keys = NULL; + dest->itext_langtags = NULL; + dest->itext_transkeys = NULL; + dest->itext_strings = NULL; + dest->itext_num = 0; + for(i = 0; i != source->itext_num; ++i) { + CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i], + source->itext_transkeys[i], source->itext_strings[i])); + } + return 0; +} + +void lodepng_clear_itext(LodePNGInfo * info) +{ + LodePNGIText_cleanup(info); +} + +static unsigned lodepng_add_itext_sized(LodePNGInfo * info, const char * key, const char * langtag, + const char * transkey, const char * str, size_t size) +{ + char ** new_keys = (char **)(lodepng_realloc(info->itext_keys, sizeof(char *) * (info->itext_num + 1))); + char ** new_langtags = (char **)(lodepng_realloc(info->itext_langtags, sizeof(char *) * (info->itext_num + 1))); + char ** new_transkeys = (char **)(lodepng_realloc(info->itext_transkeys, sizeof(char *) * (info->itext_num + 1))); + char ** new_strings = (char **)(lodepng_realloc(info->itext_strings, sizeof(char *) * (info->itext_num + 1))); + + if(new_keys) info->itext_keys = new_keys; + if(new_langtags) info->itext_langtags = new_langtags; + if(new_transkeys) info->itext_transkeys = new_transkeys; + if(new_strings) info->itext_strings = new_strings; + + if(!new_keys || !new_langtags || !new_transkeys || !new_strings) return 83; /*alloc fail*/ + + ++info->itext_num; + + info->itext_keys[info->itext_num - 1] = alloc_string(key); + info->itext_langtags[info->itext_num - 1] = alloc_string(langtag); + info->itext_transkeys[info->itext_num - 1] = alloc_string(transkey); + info->itext_strings[info->itext_num - 1] = alloc_string_sized(str, size); + + return 0; +} + +unsigned lodepng_add_itext(LodePNGInfo * info, const char * key, const char * langtag, + const char * transkey, const char * str) +{ + return lodepng_add_itext_sized(info, key, langtag, transkey, str, lodepng_strlen(str)); +} + +/* same as set but does not delete */ +static unsigned lodepng_assign_icc(LodePNGInfo * info, const char * name, const unsigned char * profile, + unsigned profile_size) +{ + if(profile_size == 0) return 100; /*invalid ICC profile size*/ + + info->iccp_name = alloc_string(name); + info->iccp_profile = (unsigned char *)lodepng_malloc(profile_size); + + if(!info->iccp_name || !info->iccp_profile) return 83; /*alloc fail*/ + + lodepng_memcpy(info->iccp_profile, profile, profile_size); + info->iccp_profile_size = profile_size; + + return 0; /*ok*/ +} + +unsigned lodepng_set_icc(LodePNGInfo * info, const char * name, const unsigned char * profile, unsigned profile_size) +{ + if(info->iccp_name) lodepng_clear_icc(info); + info->iccp_defined = 1; + + return lodepng_assign_icc(info, name, profile, profile_size); +} + +void lodepng_clear_icc(LodePNGInfo * info) +{ + string_cleanup(&info->iccp_name); + lodepng_free(info->iccp_profile); + info->iccp_profile = NULL; + info->iccp_profile_size = 0; + info->iccp_defined = 0; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +void lodepng_info_init(LodePNGInfo * info) +{ + lodepng_color_mode_init(&info->color); + info->interlace_method = 0; + info->compression_method = 0; + info->filter_method = 0; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + info->background_defined = 0; + info->background_r = info->background_g = info->background_b = 0; + + LodePNGText_init(info); + LodePNGIText_init(info); + + info->time_defined = 0; + info->phys_defined = 0; + + info->gama_defined = 0; + info->chrm_defined = 0; + info->srgb_defined = 0; + info->iccp_defined = 0; + info->iccp_name = NULL; + info->iccp_profile = NULL; + + LodePNGUnknownChunks_init(info); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} + +void lodepng_info_cleanup(LodePNGInfo * info) +{ + lodepng_color_mode_cleanup(&info->color); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + LodePNGText_cleanup(info); + LodePNGIText_cleanup(info); + + lodepng_clear_icc(info); + + LodePNGUnknownChunks_cleanup(info); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} + +unsigned lodepng_info_copy(LodePNGInfo * dest, const LodePNGInfo * source) +{ + lodepng_info_cleanup(dest); + lodepng_memcpy(dest, source, sizeof(LodePNGInfo)); + lodepng_color_mode_init(&dest->color); + CERROR_TRY_RETURN(lodepng_color_mode_copy(&dest->color, &source->color)); + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + CERROR_TRY_RETURN(LodePNGText_copy(dest, source)); + CERROR_TRY_RETURN(LodePNGIText_copy(dest, source)); + if(source->iccp_defined) { + CERROR_TRY_RETURN(lodepng_assign_icc(dest, source->iccp_name, source->iccp_profile, source->iccp_profile_size)); + } + + LodePNGUnknownChunks_init(dest); + CERROR_TRY_RETURN(LodePNGUnknownChunks_copy(dest, source)); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + return 0; +} + +/* ////////////////////////////////////////////////////////////////////////// */ + +/*index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to*/ +static void addColorBits(unsigned char * out, size_t index, unsigned bits, unsigned in) +{ + unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/ + /*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/ + unsigned p = index & m; + in &= (1u << bits) - 1u; /*filter out any other bits of the input value*/ + in = in << (bits * (m - p)); + if(p == 0) out[index * bits / 8u] = in; + else out[index * bits / 8u] |= in; +} + +typedef struct ColorTree ColorTree; + +/* +One node of a color tree +This is the data structure used to count the number of unique colors and to get a palette +index for a color. It's like an octree, but because the alpha channel is used too, each +node has 16 instead of 8 children. +*/ +struct ColorTree { + ColorTree * children[16]; /*up to 16 pointers to ColorTree of next level*/ + int index; /*the payload. Only has a meaningful value if this is in the last level*/ +}; + +static void color_tree_init(ColorTree * tree) +{ + lodepng_memset(tree->children, 0, 16 * sizeof(*tree->children)); + tree->index = -1; +} + +static void color_tree_cleanup(ColorTree * tree) +{ + int i; + for(i = 0; i != 16; ++i) { + if(tree->children[i]) { + color_tree_cleanup(tree->children[i]); + lodepng_free(tree->children[i]); + } + } +} + +/*returns -1 if color not present, its index otherwise*/ +static int color_tree_get(ColorTree * tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + int bit = 0; + for(bit = 0; bit < 8; ++bit) { + int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); + if(!tree->children[i]) return -1; + else tree = tree->children[i]; + } + return tree ? tree->index : -1; +} + +#ifdef LODEPNG_COMPILE_ENCODER +static int color_tree_has(ColorTree * tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + return color_tree_get(tree, r, g, b, a) >= 0; +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/*color is not allowed to already exist. +Index should be >= 0 (it's signed to be compatible with using -1 for "doesn't exist") +Returns error code, or 0 if ok*/ +static unsigned color_tree_add(ColorTree * tree, + unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned index) +{ + int bit; + for(bit = 0; bit < 8; ++bit) { + int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); + if(!tree->children[i]) { + tree->children[i] = (ColorTree *)lodepng_malloc(sizeof(ColorTree)); + if(!tree->children[i]) return 83; /*alloc fail*/ + color_tree_init(tree->children[i]); + } + tree = tree->children[i]; + } + tree->index = (int)index; + return 0; +} + +/*put a pixel, given its RGBA color, into image of any color type*/ +static unsigned rgba8ToPixel(unsigned char * out, size_t i, + const LodePNGColorMode * mode, ColorTree * tree /*for palette*/, + unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + if(mode->colortype == LCT_GREY) { + unsigned char gray = r; /*((unsigned short)r + g + b) / 3u;*/ + if(mode->bitdepth == 8) out[i] = gray; + else if(mode->bitdepth == 16) out[i * 2 + 0] = out[i * 2 + 1] = gray; + else { + /*take the most significant bits of gray*/ + gray = ((unsigned)gray >> (8u - mode->bitdepth)) & ((1u << mode->bitdepth) - 1u); + addColorBits(out, i, mode->bitdepth, gray); + } + } + else if(mode->colortype == LCT_RGB) { + if(mode->bitdepth == 8) { + out[i * 3 + 0] = r; + out[i * 3 + 1] = g; + out[i * 3 + 2] = b; + } + else { + out[i * 6 + 0] = out[i * 6 + 1] = r; + out[i * 6 + 2] = out[i * 6 + 3] = g; + out[i * 6 + 4] = out[i * 6 + 5] = b; + } + } + else if(mode->colortype == LCT_PALETTE) { + int index = color_tree_get(tree, r, g, b, a); + if(index < 0) return 82; /*color not in palette*/ + if(mode->bitdepth == 8) out[i] = index; + else addColorBits(out, i, mode->bitdepth, (unsigned)index); + } + else if(mode->colortype == LCT_GREY_ALPHA) { + unsigned char gray = r; /*((unsigned short)r + g + b) / 3u;*/ + if(mode->bitdepth == 8) { + out[i * 2 + 0] = gray; + out[i * 2 + 1] = a; + } + else if(mode->bitdepth == 16) { + out[i * 4 + 0] = out[i * 4 + 1] = gray; + out[i * 4 + 2] = out[i * 4 + 3] = a; + } + } + else if(mode->colortype == LCT_RGBA) { + if(mode->bitdepth == 8) { + out[i * 4 + 0] = r; + out[i * 4 + 1] = g; + out[i * 4 + 2] = b; + out[i * 4 + 3] = a; + } + else { + out[i * 8 + 0] = out[i * 8 + 1] = r; + out[i * 8 + 2] = out[i * 8 + 3] = g; + out[i * 8 + 4] = out[i * 8 + 5] = b; + out[i * 8 + 6] = out[i * 8 + 7] = a; + } + } + + return 0; /*no error*/ +} + +/*put a pixel, given its RGBA16 color, into image of any color 16-bitdepth type*/ +static void rgba16ToPixel(unsigned char * out, size_t i, + const LodePNGColorMode * mode, + unsigned short r, unsigned short g, unsigned short b, unsigned short a) +{ + if(mode->colortype == LCT_GREY) { + unsigned short gray = r; /*((unsigned)r + g + b) / 3u;*/ + out[i * 2 + 0] = (gray >> 8) & 255; + out[i * 2 + 1] = gray & 255; + } + else if(mode->colortype == LCT_RGB) { + out[i * 6 + 0] = (r >> 8) & 255; + out[i * 6 + 1] = r & 255; + out[i * 6 + 2] = (g >> 8) & 255; + out[i * 6 + 3] = g & 255; + out[i * 6 + 4] = (b >> 8) & 255; + out[i * 6 + 5] = b & 255; + } + else if(mode->colortype == LCT_GREY_ALPHA) { + unsigned short gray = r; /*((unsigned)r + g + b) / 3u;*/ + out[i * 4 + 0] = (gray >> 8) & 255; + out[i * 4 + 1] = gray & 255; + out[i * 4 + 2] = (a >> 8) & 255; + out[i * 4 + 3] = a & 255; + } + else if(mode->colortype == LCT_RGBA) { + out[i * 8 + 0] = (r >> 8) & 255; + out[i * 8 + 1] = r & 255; + out[i * 8 + 2] = (g >> 8) & 255; + out[i * 8 + 3] = g & 255; + out[i * 8 + 4] = (b >> 8) & 255; + out[i * 8 + 5] = b & 255; + out[i * 8 + 6] = (a >> 8) & 255; + out[i * 8 + 7] = a & 255; + } +} + +/*Get RGBA8 color of pixel with index i (y * width + x) from the raw image with given color type.*/ +static void getPixelColorRGBA8(unsigned char * r, unsigned char * g, + unsigned char * b, unsigned char * a, + const unsigned char * in, size_t i, + const LodePNGColorMode * mode) +{ + if(mode->colortype == LCT_GREY) { + if(mode->bitdepth == 8) { + *r = *g = *b = in[i]; + if(mode->key_defined && *r == mode->key_r) *a = 0; + else *a = 255; + } + else if(mode->bitdepth == 16) { + *r = *g = *b = in[i * 2 + 0]; + if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; + else *a = 255; + } + else { + unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ + size_t j = i * mode->bitdepth; + unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); + *r = *g = *b = (value * 255) / highest; + if(mode->key_defined && value == mode->key_r) *a = 0; + else *a = 255; + } + } + else if(mode->colortype == LCT_RGB) { + if(mode->bitdepth == 8) { + *r = in[i * 3 + 0]; + *g = in[i * 3 + 1]; + *b = in[i * 3 + 2]; + if(mode->key_defined && *r == mode->key_r && *g == mode->key_g && *b == mode->key_b) *a = 0; + else *a = 255; + } + else { + *r = in[i * 6 + 0]; + *g = in[i * 6 + 2]; + *b = in[i * 6 + 4]; + if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; + else *a = 255; + } + } + else if(mode->colortype == LCT_PALETTE) { + unsigned index; + if(mode->bitdepth == 8) index = in[i]; + else { + size_t j = i * mode->bitdepth; + index = readBitsFromReversedStream(&j, in, mode->bitdepth); + } + /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ + *r = mode->palette[index * 4 + 0]; + *g = mode->palette[index * 4 + 1]; + *b = mode->palette[index * 4 + 2]; + *a = mode->palette[index * 4 + 3]; + } + else if(mode->colortype == LCT_GREY_ALPHA) { + if(mode->bitdepth == 8) { + *r = *g = *b = in[i * 2 + 0]; + *a = in[i * 2 + 1]; + } + else { + *r = *g = *b = in[i * 4 + 0]; + *a = in[i * 4 + 2]; + } + } + else if(mode->colortype == LCT_RGBA) { + if(mode->bitdepth == 8) { + *r = in[i * 4 + 0]; + *g = in[i * 4 + 1]; + *b = in[i * 4 + 2]; + *a = in[i * 4 + 3]; + } + else { + *r = in[i * 8 + 0]; + *g = in[i * 8 + 2]; + *b = in[i * 8 + 4]; + *a = in[i * 8 + 6]; + } + } +} + +/*Similar to getPixelColorRGBA8, but with all the for loops inside of the color +mode test cases, optimized to convert the colors much faster, when converting +to the common case of RGBA with 8 bit per channel. buffer must be RGBA with +enough memory.*/ +static void getPixelColorsRGBA8(unsigned char * LODEPNG_RESTRICT buffer, size_t numpixels, + const unsigned char * LODEPNG_RESTRICT in, + const LodePNGColorMode * mode) +{ + unsigned num_channels = 4; + size_t i; + if(mode->colortype == LCT_GREY) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i]; + buffer[3] = 255; + } + if(mode->key_defined) { + buffer -= numpixels * num_channels; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + if(buffer[0] == mode->key_r) buffer[3] = 0; + } + } + } + else if(mode->bitdepth == 16) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 2]; + buffer[3] = mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r ? 0 : 255; + } + } + else { + unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); + buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest; + buffer[3] = mode->key_defined && value == mode->key_r ? 0 : 255; + } + } + } + else if(mode->colortype == LCT_RGB) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + lodepng_memcpy(buffer, &in[i * 3], 3); + buffer[3] = 255; + } + if(mode->key_defined) { + buffer -= numpixels * num_channels; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + if(buffer[0] == mode->key_r && buffer[1] == mode->key_g && buffer[2] == mode->key_b) buffer[3] = 0; + } + } + } + else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = in[i * 6 + 0]; + buffer[1] = in[i * 6 + 2]; + buffer[2] = in[i * 6 + 4]; + buffer[3] = mode->key_defined + && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b ? 0 : 255; + } + } + } + else if(mode->colortype == LCT_PALETTE) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned index = in[i]; + /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ + lodepng_memcpy(buffer, &mode->palette[index * 4], 4); + } + } + else { + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned index = readBitsFromReversedStream(&j, in, mode->bitdepth); + /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ + lodepng_memcpy(buffer, &mode->palette[index * 4], 4); + } + } + } + else if(mode->colortype == LCT_GREY_ALPHA) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0]; + buffer[3] = in[i * 2 + 1]; + } + } + else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0]; + buffer[3] = in[i * 4 + 2]; + } + } + } + else if(mode->colortype == LCT_RGBA) { + if(mode->bitdepth == 8) { + lodepng_memcpy(buffer, in, numpixels * 4); + } + else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = in[i * 8 + 0]; + buffer[1] = in[i * 8 + 2]; + buffer[2] = in[i * 8 + 4]; + buffer[3] = in[i * 8 + 6]; + } + } + } +} + +/*Similar to getPixelColorsRGBA8, but with 3-channel RGB output.*/ +static void getPixelColorsRGB8(unsigned char * LODEPNG_RESTRICT buffer, size_t numpixels, + const unsigned char * LODEPNG_RESTRICT in, + const LodePNGColorMode * mode) +{ + const unsigned num_channels = 3; + size_t i; + if(mode->colortype == LCT_GREY) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i]; + } + } + else if(mode->bitdepth == 16) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 2]; + } + } + else { + unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); + buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest; + } + } + } + else if(mode->colortype == LCT_RGB) { + if(mode->bitdepth == 8) { + lodepng_memcpy(buffer, in, numpixels * 3); + } + else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = in[i * 6 + 0]; + buffer[1] = in[i * 6 + 2]; + buffer[2] = in[i * 6 + 4]; + } + } + } + else if(mode->colortype == LCT_PALETTE) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned index = in[i]; + /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ + lodepng_memcpy(buffer, &mode->palette[index * 4], 3); + } + } + else { + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + unsigned index = readBitsFromReversedStream(&j, in, mode->bitdepth); + /*out of bounds of palette not checked: see lodepng_color_mode_alloc_palette.*/ + lodepng_memcpy(buffer, &mode->palette[index * 4], 3); + } + } + } + else if(mode->colortype == LCT_GREY_ALPHA) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0]; + } + } + else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0]; + } + } + } + else if(mode->colortype == LCT_RGBA) { + if(mode->bitdepth == 8) { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + lodepng_memcpy(buffer, &in[i * 4], 3); + } + } + else { + for(i = 0; i != numpixels; ++i, buffer += num_channels) { + buffer[0] = in[i * 8 + 0]; + buffer[1] = in[i * 8 + 2]; + buffer[2] = in[i * 8 + 4]; + } + } + } +} + +/*Get RGBA16 color of pixel with index i (y * width + x) from the raw image with +given color type, but the given color type must be 16-bit itself.*/ +static void getPixelColorRGBA16(unsigned short * r, unsigned short * g, unsigned short * b, unsigned short * a, + const unsigned char * in, size_t i, const LodePNGColorMode * mode) +{ + if(mode->colortype == LCT_GREY) { + *r = *g = *b = 256 * in[i * 2 + 0] + in[i * 2 + 1]; + if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; + else *a = 65535; + } + else if(mode->colortype == LCT_RGB) { + *r = 256u * in[i * 6 + 0] + in[i * 6 + 1]; + *g = 256u * in[i * 6 + 2] + in[i * 6 + 3]; + *b = 256u * in[i * 6 + 4] + in[i * 6 + 5]; + if(mode->key_defined + && 256u * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256u * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256u * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; + else *a = 65535; + } + else if(mode->colortype == LCT_GREY_ALPHA) { + *r = *g = *b = 256u * in[i * 4 + 0] + in[i * 4 + 1]; + *a = 256u * in[i * 4 + 2] + in[i * 4 + 3]; + } + else if(mode->colortype == LCT_RGBA) { + *r = 256u * in[i * 8 + 0] + in[i * 8 + 1]; + *g = 256u * in[i * 8 + 2] + in[i * 8 + 3]; + *b = 256u * in[i * 8 + 4] + in[i * 8 + 5]; + *a = 256u * in[i * 8 + 6] + in[i * 8 + 7]; + } +} + +unsigned lodepng_convert(unsigned char * out, const unsigned char * in, + const LodePNGColorMode * mode_out, const LodePNGColorMode * mode_in, + unsigned w, unsigned h) +{ + size_t i; + ColorTree tree; + size_t numpixels = (size_t)w * (size_t)h; + unsigned error = 0; + + if(mode_in->colortype == LCT_PALETTE && !mode_in->palette) { + return 107; /* error: must provide palette if input mode is palette */ + } + + if(lodepng_color_mode_equal(mode_out, mode_in)) { + size_t numbytes = lodepng_get_raw_size(w, h, mode_in); + lodepng_memcpy(out, in, numbytes); + return 0; + } + + if(mode_out->colortype == LCT_PALETTE) { + size_t palettesize = mode_out->palettesize; + const unsigned char * palette = mode_out->palette; + size_t palsize = (size_t)1u << mode_out->bitdepth; + /*if the user specified output palette but did not give the values, assume + they want the values of the input color type (assuming that one is palette). + Note that we never create a new palette ourselves.*/ + if(palettesize == 0) { + palettesize = mode_in->palettesize; + palette = mode_in->palette; + /*if the input was also palette with same bitdepth, then the color types are also + equal, so copy literally. This to preserve the exact indices that were in the PNG + even in case there are duplicate colors in the palette.*/ + if(mode_in->colortype == LCT_PALETTE && mode_in->bitdepth == mode_out->bitdepth) { + size_t numbytes = lodepng_get_raw_size(w, h, mode_in); + lodepng_memcpy(out, in, numbytes); + return 0; + } + } + if(palettesize < palsize) palsize = palettesize; + color_tree_init(&tree); + for(i = 0; i != palsize; ++i) { + const unsigned char * p = &palette[i * 4]; + error = color_tree_add(&tree, p[0], p[1], p[2], p[3], (unsigned)i); + if(error) break; + } + } + + if(!error) { + if(mode_in->bitdepth == 16 && mode_out->bitdepth == 16) { + for(i = 0; i != numpixels; ++i) { + unsigned short r = 0, g = 0, b = 0, a = 0; + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + rgba16ToPixel(out, i, mode_out, r, g, b, a); + } + } + else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGBA) { + getPixelColorsRGBA8(out, numpixels, in, mode_in); + } + else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGB) { + getPixelColorsRGB8(out, numpixels, in, mode_in); + } + else { + unsigned char r = 0, g = 0, b = 0, a = 0; + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); + error = rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a); + if(error) break; + } + } + } + + if(mode_out->colortype == LCT_PALETTE) { + color_tree_cleanup(&tree); + } + + return error; +} + + +/* Converts a single rgb color without alpha from one type to another, color bits truncated to +their bitdepth. In case of single channel (gray or palette), only the r channel is used. Slow +function, do not use to process all pixels of an image. Alpha channel not supported on purpose: +this is for bKGD, supporting alpha may prevent it from finding a color in the palette, from the +specification it looks like bKGD should ignore the alpha values of the palette since it can use +any palette index but doesn't have an alpha channel. Idem with ignoring color key. */ +static unsigned lodepng_convert_rgb( + unsigned * r_out, unsigned * g_out, unsigned * b_out, + unsigned r_in, unsigned g_in, unsigned b_in, + const LodePNGColorMode * mode_out, const LodePNGColorMode * mode_in) +{ + unsigned r = 0, g = 0, b = 0; + unsigned mul = 65535 / ((1u << mode_in->bitdepth) - 1u); /*65535, 21845, 4369, 257, 1*/ + unsigned shift = 16 - mode_out->bitdepth; + + if(mode_in->colortype == LCT_GREY || mode_in->colortype == LCT_GREY_ALPHA) { + r = g = b = r_in * mul; + } + else if(mode_in->colortype == LCT_RGB || mode_in->colortype == LCT_RGBA) { + r = r_in * mul; + g = g_in * mul; + b = b_in * mul; + } + else if(mode_in->colortype == LCT_PALETTE) { + if(r_in >= mode_in->palettesize) return 82; + r = mode_in->palette[r_in * 4 + 0] * 257u; + g = mode_in->palette[r_in * 4 + 1] * 257u; + b = mode_in->palette[r_in * 4 + 2] * 257u; + } + else { + return 31; + } + + /* now convert to output format */ + if(mode_out->colortype == LCT_GREY || mode_out->colortype == LCT_GREY_ALPHA) { + *r_out = r >> shift ; + } + else if(mode_out->colortype == LCT_RGB || mode_out->colortype == LCT_RGBA) { + *r_out = r >> shift ; + *g_out = g >> shift ; + *b_out = b >> shift ; + } + else if(mode_out->colortype == LCT_PALETTE) { + unsigned i; + /* a 16-bit color cannot be in the palette */ + if((r >> 8) != (r & 255) || (g >> 8) != (g & 255) || (b >> 8) != (b & 255)) return 82; + for(i = 0; i < mode_out->palettesize; i++) { + unsigned j = i * 4; + if((r >> 8) == mode_out->palette[j + 0] && (g >> 8) == mode_out->palette[j + 1] && + (b >> 8) == mode_out->palette[j + 2]) { + *r_out = i; + return 0; + } + } + return 82; + } + else { + return 31; + } + + return 0; +} + +#ifdef LODEPNG_COMPILE_ENCODER + +void lodepng_color_stats_init(LodePNGColorStats * stats) +{ + /*stats*/ + stats->colored = 0; + stats->key = 0; + stats->key_r = stats->key_g = stats->key_b = 0; + stats->alpha = 0; + stats->numcolors = 0; + stats->bits = 1; + stats->numpixels = 0; + /*settings*/ + stats->allow_palette = 1; + stats->allow_greyscale = 1; +} + +/*function used for debug purposes with C++*/ +/*void printColorStats(LodePNGColorStats* p) { + std::cout << "colored: " << (int)p->colored << ", "; + std::cout << "key: " << (int)p->key << ", "; + std::cout << "key_r: " << (int)p->key_r << ", "; + std::cout << "key_g: " << (int)p->key_g << ", "; + std::cout << "key_b: " << (int)p->key_b << ", "; + std::cout << "alpha: " << (int)p->alpha << ", "; + std::cout << "numcolors: " << (int)p->numcolors << ", "; + std::cout << "bits: " << (int)p->bits << std::endl; +}*/ + +/*Returns how many bits needed to represent given value (max 8 bit)*/ +static unsigned getValueRequiredBits(unsigned char value) +{ + if(value == 0 || value == 255) return 1; + /*The scaling of 2-bit and 4-bit values uses multiples of 85 and 17*/ + if(value % 17 == 0) return value % 85 == 0 ? 2 : 4; + return 8; +} + +/*stats must already have been inited. */ +unsigned lodepng_compute_color_stats(LodePNGColorStats * stats, + const unsigned char * in, unsigned w, unsigned h, + const LodePNGColorMode * mode_in) +{ + size_t i; + ColorTree tree; + size_t numpixels = (size_t)w * (size_t)h; + unsigned error = 0; + + /* mark things as done already if it would be impossible to have a more expensive case */ + unsigned colored_done = lodepng_is_greyscale_type(mode_in) ? 1 : 0; + unsigned alpha_done = lodepng_can_have_alpha(mode_in) ? 0 : 1; + unsigned numcolors_done = 0; + unsigned bpp = lodepng_get_bpp(mode_in); + unsigned bits_done = (stats->bits == 1 && bpp == 1) ? 1 : 0; + unsigned sixteen = 0; /* whether the input image is 16 bit */ + unsigned maxnumcolors = 257; + if(bpp <= 8) maxnumcolors = LODEPNG_MIN(257, stats->numcolors + (1u << bpp)); + + stats->numpixels += numpixels; + + /*if palette not allowed, no need to compute numcolors*/ + if(!stats->allow_palette) numcolors_done = 1; + + color_tree_init(&tree); + + /*If the stats was already filled in from previous data, fill its palette in tree + and mark things as done already if we know they are the most expensive case already*/ + if(stats->alpha) alpha_done = 1; + if(stats->colored) colored_done = 1; + if(stats->bits == 16) numcolors_done = 1; + if(stats->bits >= bpp) bits_done = 1; + if(stats->numcolors >= maxnumcolors) numcolors_done = 1; + + if(!numcolors_done) { + for(i = 0; i < stats->numcolors; i++) { + const unsigned char * color = &stats->palette[i * 4]; + error = color_tree_add(&tree, color[0], color[1], color[2], color[3], i); + if(error) goto cleanup; + } + } + + /*Check if the 16-bit input is truly 16-bit*/ + if(mode_in->bitdepth == 16 && !sixteen) { + unsigned short r = 0, g = 0, b = 0, a = 0; + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + if((r & 255) != ((r >> 8) & 255) || (g & 255) != ((g >> 8) & 255) || + (b & 255) != ((b >> 8) & 255) || (a & 255) != ((a >> 8) & 255)) { /*first and second byte differ*/ + stats->bits = 16; + sixteen = 1; + bits_done = 1; + numcolors_done = 1; /*counting colors no longer useful, palette doesn't support 16-bit*/ + break; + } + } + } + + if(sixteen) { + unsigned short r = 0, g = 0, b = 0, a = 0; + + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + + if(!colored_done && (r != g || r != b)) { + stats->colored = 1; + colored_done = 1; + } + + if(!alpha_done) { + unsigned matchkey = (r == stats->key_r && g == stats->key_g && b == stats->key_b); + if(a != 65535 && (a != 0 || (stats->key && !matchkey))) { + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + } + else if(a == 0 && !stats->alpha && !stats->key) { + stats->key = 1; + stats->key_r = r; + stats->key_g = g; + stats->key_b = b; + } + else if(a == 65535 && stats->key && matchkey) { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + } + } + if(alpha_done && numcolors_done && colored_done && bits_done) break; + } + + if(stats->key && !stats->alpha) { + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + if(a != 0 && r == stats->key_r && g == stats->key_g && b == stats->key_b) { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + } + } + } + } + else { /* < 16-bit */ + unsigned char r = 0, g = 0, b = 0, a = 0; + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); + + if(!bits_done && stats->bits < 8) { + /*only r is checked, < 8 bits is only relevant for grayscale*/ + unsigned bits = getValueRequiredBits(r); + if(bits > stats->bits) stats->bits = bits; + } + bits_done = (stats->bits >= bpp); + + if(!colored_done && (r != g || r != b)) { + stats->colored = 1; + colored_done = 1; + if(stats->bits < 8) stats->bits = 8; /*PNG has no colored modes with less than 8-bit per channel*/ + } + + if(!alpha_done) { + unsigned matchkey = (r == stats->key_r && g == stats->key_g && b == stats->key_b); + if(a != 255 && (a != 0 || (stats->key && !matchkey))) { + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + else if(a == 0 && !stats->alpha && !stats->key) { + stats->key = 1; + stats->key_r = r; + stats->key_g = g; + stats->key_b = b; + } + else if(a == 255 && stats->key && matchkey) { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + } + + if(!numcolors_done) { + if(!color_tree_has(&tree, r, g, b, a)) { + error = color_tree_add(&tree, r, g, b, a, stats->numcolors); + if(error) goto cleanup; + if(stats->numcolors < 256) { + unsigned char * p = stats->palette; + unsigned n = stats->numcolors; + p[n * 4 + 0] = r; + p[n * 4 + 1] = g; + p[n * 4 + 2] = b; + p[n * 4 + 3] = a; + } + ++stats->numcolors; + numcolors_done = stats->numcolors >= maxnumcolors; + } + } + + if(alpha_done && numcolors_done && colored_done && bits_done) break; + } + + if(stats->key && !stats->alpha) { + for(i = 0; i != numpixels; ++i) { + getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); + if(a != 0 && r == stats->key_r && g == stats->key_g && b == stats->key_b) { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + stats->alpha = 1; + stats->key = 0; + alpha_done = 1; + if(stats->bits < 8) stats->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + } + } + + /*make the stats's key always 16-bit for consistency - repeat each byte twice*/ + stats->key_r += (stats->key_r << 8); + stats->key_g += (stats->key_g << 8); + stats->key_b += (stats->key_b << 8); + } + +cleanup: + color_tree_cleanup(&tree); + return error; +} + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +/*Adds a single color to the color stats. The stats must already have been inited. The color must be given as 16-bit +(with 2 bytes repeating for 8-bit and 65535 for opaque alpha channel). This function is expensive, do not call it for +all pixels of an image but only for a few additional values. */ +static unsigned lodepng_color_stats_add(LodePNGColorStats * stats, + unsigned r, unsigned g, unsigned b, unsigned a) +{ + unsigned error = 0; + unsigned char image[8]; + LodePNGColorMode mode; + lodepng_color_mode_init(&mode); + image[0] = r >> 8; + image[1] = r; + image[2] = g >> 8; + image[3] = g; + image[4] = b >> 8; + image[5] = b; + image[6] = a >> 8; + image[7] = a; + mode.bitdepth = 16; + mode.colortype = LCT_RGBA; + error = lodepng_compute_color_stats(stats, image, 1, 1, &mode); + lodepng_color_mode_cleanup(&mode); + return error; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +/*Computes a minimal PNG color model that can contain all colors as indicated by the stats. +The stats should be computed with lodepng_compute_color_stats. +mode_in is raw color profile of the image the stats were computed on, to copy palette order from when relevant. +Minimal PNG color model means the color type and bit depth that gives smallest amount of bits in the output image, +e.g. gray if only grayscale pixels, palette if less than 256 colors, color key if only single transparent color, ... +This is used if auto_convert is enabled (it is by default). +*/ +static unsigned auto_choose_color(LodePNGColorMode * mode_out, + const LodePNGColorMode * mode_in, + const LodePNGColorStats * stats) +{ + unsigned error = 0; + unsigned palettebits; + size_t i, n; + size_t numpixels = stats->numpixels; + unsigned palette_ok, gray_ok; + + unsigned alpha = stats->alpha; + unsigned key = stats->key; + unsigned bits = stats->bits; + + mode_out->key_defined = 0; + + if(key && numpixels <= 16) { + alpha = 1; /*too few pixels to justify tRNS chunk overhead*/ + key = 0; + if(bits < 8) bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + + gray_ok = !stats->colored; + if(!stats->allow_greyscale) gray_ok = 0; + if(!gray_ok && bits < 8) bits = 8; + + n = stats->numcolors; + palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8)); + palette_ok = n <= 256 && bits <= 8 && n != 0; /*n==0 means likely numcolors wasn't computed*/ + if(numpixels < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/ + if(gray_ok && !alpha && bits <= palettebits) palette_ok = 0; /*gray is less overhead*/ + if(!stats->allow_palette) palette_ok = 0; + + if(palette_ok) { + const unsigned char * p = stats->palette; + lodepng_palette_clear(mode_out); /*remove potential earlier palette*/ + for(i = 0; i != stats->numcolors; ++i) { + error = lodepng_palette_add(mode_out, p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3]); + if(error) break; + } + + mode_out->colortype = LCT_PALETTE; + mode_out->bitdepth = palettebits; + + if(mode_in->colortype == LCT_PALETTE && mode_in->palettesize >= mode_out->palettesize + && mode_in->bitdepth == mode_out->bitdepth) { + /*If input should have same palette colors, keep original to preserve its order and prevent conversion*/ + lodepng_color_mode_cleanup(mode_out); + lodepng_color_mode_copy(mode_out, mode_in); + } + } + else { /*8-bit or 16-bit per channel*/ + mode_out->bitdepth = bits; + mode_out->colortype = alpha ? (gray_ok ? LCT_GREY_ALPHA : LCT_RGBA) + : (gray_ok ? LCT_GREY : LCT_RGB); + if(key) { + unsigned mask = (1u << mode_out->bitdepth) - 1u; /*stats always uses 16-bit, mask converts it*/ + mode_out->key_r = stats->key_r & mask; + mode_out->key_g = stats->key_g & mask; + mode_out->key_b = stats->key_b & mask; + mode_out->key_defined = 1; + } + } + + return error; +} + +#endif /* #ifdef LODEPNG_COMPILE_ENCODER */ + +/* +Paeth predictor, used by PNG filter type 4 +The parameters are of type short, but should come from unsigned chars, the shorts +are only needed to make the paeth calculation correct. +*/ +static unsigned char paethPredictor(short a, short b, short c) +{ + short pa = LODEPNG_ABS(b - c); + short pb = LODEPNG_ABS(a - c); + short pc = LODEPNG_ABS(a + b - c - c); + /* return input value associated with smallest of pa, pb, pc (with certain priority if equal) */ + if(pb < pa) { + a = b; + pa = pb; + } + return (pc < pa) ? c : a; +} + +/*shared values used by multiple Adam7 related functions*/ + +static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/ +static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/ +static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/ +static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/ + +/* +Outputs various dimensions and positions in the image related to the Adam7 reduced images. +passw: output containing the width of the 7 passes +passh: output containing the height of the 7 passes +filter_passstart: output containing the index of the start and end of each + reduced image with filter bytes +padded_passstart output containing the index of the start and end of each + reduced image when without filter bytes but with padded scanlines +passstart: output containing the index of the start and end of each reduced + image without padding between scanlines, but still padding between the images +w, h: width and height of non-interlaced image +bpp: bits per pixel +"padded" is only relevant if bpp is less than 8 and a scanline or image does not + end at a full byte +*/ +static void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8], + size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp) +{ + /*the passstart values have 8 values: the 8th one indicates the byte after the end of the 7th (= last) pass*/ + unsigned i; + + /*calculate width and height in pixels of each pass*/ + for(i = 0; i != 7; ++i) { + passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i]; + passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i]; + if(passw[i] == 0) passh[i] = 0; + if(passh[i] == 0) passw[i] = 0; + } + + filter_passstart[0] = padded_passstart[0] = passstart[0] = 0; + for(i = 0; i != 7; ++i) { + /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/ + filter_passstart[i + 1] = filter_passstart[i] + + ((passw[i] && passh[i]) ? passh[i] * (1u + (passw[i] * bpp + 7u) / 8u) : 0); + /*bits padded if needed to fill full byte at end of each scanline*/ + padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7u) / 8u); + /*only padded at end of reduced image*/ + passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7u) / 8u; + } +} + +#ifdef LODEPNG_COMPILE_DECODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / PNG Decoder / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*read the information from the header and store it in the LodePNGInfo. return value is error*/ +unsigned lodepng_inspect(unsigned * w, unsigned * h, LodePNGState * state, + const unsigned char * in, size_t insize) +{ + unsigned width, height; + LodePNGInfo * info = &state->info_png; + if(insize == 0 || in == 0) { + CERROR_RETURN_ERROR(state->error, 48); /*error: the given data is empty*/ + } + if(insize < 33) { + CERROR_RETURN_ERROR(state->error, 27); /*error: the data length is smaller than the length of a PNG header*/ + } + + /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/ + /* TODO: remove this. One should use a new LodePNGState for new sessions */ + lodepng_info_cleanup(info); + lodepng_info_init(info); + + if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 + || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { + CERROR_RETURN_ERROR(state->error, 28); /*error: the first 8 bytes are not the correct PNG signature*/ + } + if(lodepng_chunk_length(in + 8) != 13) { + CERROR_RETURN_ERROR(state->error, 94); /*error: header size must be 13 bytes*/ + } + if(!lodepng_chunk_type_equals(in + 8, "IHDR")) { + CERROR_RETURN_ERROR(state->error, 29); /*error: it doesn't start with a IHDR chunk!*/ + } + + /*read the values given in the header*/ + width = lodepng_read32bitInt(&in[16]); + height = lodepng_read32bitInt(&in[20]); + /*TODO: remove the undocumented feature that allows to give null pointers to width or height*/ + if(w) *w = width; + if(h) *h = height; + info->color.bitdepth = in[24]; + info->color.colortype = (LodePNGColorType)in[25]; + info->compression_method = in[26]; + info->filter_method = in[27]; + info->interlace_method = in[28]; + + /*errors returned only after the parsing so other values are still output*/ + + /*error: invalid image size*/ + if(width == 0 || height == 0) CERROR_RETURN_ERROR(state->error, 93); + /*error: invalid colortype or bitdepth combination*/ + state->error = checkColorValidity(info->color.colortype, info->color.bitdepth); + if(state->error) return state->error; + /*error: only compression method 0 is allowed in the specification*/ + if(info->compression_method != 0) CERROR_RETURN_ERROR(state->error, 32); + /*error: only filter method 0 is allowed in the specification*/ + if(info->filter_method != 0) CERROR_RETURN_ERROR(state->error, 33); + /*error: only interlace methods 0 and 1 exist in the specification*/ + if(info->interlace_method > 1) CERROR_RETURN_ERROR(state->error, 34); + + if(!state->decoder.ignore_crc) { + unsigned CRC = lodepng_read32bitInt(&in[29]); + unsigned checksum = lodepng_crc32(&in[12], 17); + if(CRC != checksum) { + CERROR_RETURN_ERROR(state->error, 57); /*invalid CRC*/ + } + } + + return state->error; +} + +static unsigned unfilterScanline(unsigned char * recon, const unsigned char * scanline, const unsigned char * precon, + size_t bytewidth, unsigned char filterType, size_t length) +{ + /* + For PNG filter method 0 + unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte, + the filter works byte per byte (bytewidth = 1) + precon is the previous unfiltered scanline, recon the result, scanline the current one + the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead + recon and scanline MAY be the same memory address! precon must be disjoint. + */ + + size_t i; + switch(filterType) { + case 0: + for(i = 0; i != length; ++i) recon[i] = scanline[i]; + break; + case 1: + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth]; + break; + case 2: + if(precon) { + for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i]; + } + else { + for(i = 0; i != length; ++i) recon[i] = scanline[i]; + } + break; + case 3: + if(precon) { + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1u); + for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) >> 1u); + } + else { + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + (recon[i - bytewidth] >> 1u); + } + break; + case 4: + if(precon) { + for(i = 0; i != bytewidth; ++i) { + recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/ + } + + /* Unroll independent paths of the paeth predictor. A 6x and 8x version would also be possible but that + adds too much code. Whether this actually speeds anything up at all depends on compiler and settings. */ + if(bytewidth >= 4) { + for(; i + 3 < length; i += 4) { + size_t j = i - bytewidth; + unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3]; + unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3]; + unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3]; + unsigned char q0 = precon[j + 0], q1 = precon[j + 1], q2 = precon[j + 2], q3 = precon[j + 3]; + recon[i + 0] = s0 + paethPredictor(r0, p0, q0); + recon[i + 1] = s1 + paethPredictor(r1, p1, q1); + recon[i + 2] = s2 + paethPredictor(r2, p2, q2); + recon[i + 3] = s3 + paethPredictor(r3, p3, q3); + } + } + else if(bytewidth >= 3) { + for(; i + 2 < length; i += 3) { + size_t j = i - bytewidth; + unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2]; + unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2]; + unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2]; + unsigned char q0 = precon[j + 0], q1 = precon[j + 1], q2 = precon[j + 2]; + recon[i + 0] = s0 + paethPredictor(r0, p0, q0); + recon[i + 1] = s1 + paethPredictor(r1, p1, q1); + recon[i + 2] = s2 + paethPredictor(r2, p2, q2); + } + } + else if(bytewidth >= 2) { + for(; i + 1 < length; i += 2) { + size_t j = i - bytewidth; + unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1]; + unsigned char r0 = recon[j + 0], r1 = recon[j + 1]; + unsigned char p0 = precon[i + 0], p1 = precon[i + 1]; + unsigned char q0 = precon[j + 0], q1 = precon[j + 1]; + recon[i + 0] = s0 + paethPredictor(r0, p0, q0); + recon[i + 1] = s1 + paethPredictor(r1, p1, q1); + } + } + + for(; i != length; ++i) { + recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth])); + } + } + else { + for(i = 0; i != bytewidth; ++i) { + recon[i] = scanline[i]; + } + for(i = bytewidth; i < length; ++i) { + /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/ + recon[i] = (scanline[i] + recon[i - bytewidth]); + } + } + break; + default: + return 36; /*error: invalid filter type given*/ + } + return 0; +} + +static unsigned unfilter(unsigned char * out, const unsigned char * in, unsigned w, unsigned h, unsigned bpp) +{ + /* + For PNG filter method 0 + this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times) + out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline + w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel + in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes) + */ + + unsigned y; + unsigned char * prevline = 0; + + /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ + size_t bytewidth = (bpp + 7u) / 8u; + /*the width of a scanline in bytes, not including the filter type*/ + size_t linebytes = lodepng_get_raw_size_idat(w, 1, bpp) - 1u; + + for(y = 0; y < h; ++y) { + size_t outindex = linebytes * y; + size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ + unsigned char filterType = in[inindex]; + + CERROR_TRY_RETURN(unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes)); + + prevline = &out[outindex]; + } + + return 0; +} + +/* +in: Adam7 interlaced image, with no padding bits between scanlines, but between + reduced images so that each reduced image starts at a byte. +out: the same pixels, but re-ordered so that they're now a non-interlaced image with size w*h +bpp: bits per pixel +out has the following size in bits: w * h * bpp. +in is possibly bigger due to padding bits between reduced images. +out must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation +(because that's likely a little bit faster) +NOTE: comments about padding bits are only relevant if bpp < 8 +*/ +static void Adam7_deinterlace(unsigned char * out, const unsigned char * in, unsigned w, unsigned h, unsigned bpp) +{ + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned i; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + if(bpp >= 8) { + for(i = 0; i != 7; ++i) { + unsigned x, y, b; + size_t bytewidth = bpp / 8u; + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) { + size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth; + size_t pixeloutstart = ((ADAM7_IY[i] + (size_t)y * ADAM7_DY[i]) * (size_t)w + + ADAM7_IX[i] + (size_t)x * ADAM7_DX[i]) * bytewidth; + for(b = 0; b < bytewidth; ++b) { + out[pixeloutstart + b] = in[pixelinstart + b]; + } + } + } + } + else { /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ + for(i = 0; i != 7; ++i) { + unsigned x, y, b; + unsigned ilinebits = bpp * passw[i]; + unsigned olinebits = bpp * w; + size_t obp, ibp; /*bit pointers (for out and in buffer)*/ + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) { + ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp); + obp = (ADAM7_IY[i] + (size_t)y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + (size_t)x * ADAM7_DX[i]) * bpp; + for(b = 0; b < bpp; ++b) { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + } + } + } +} + +static void removePaddingBits(unsigned char * out, const unsigned char * in, + size_t olinebits, size_t ilinebits, unsigned h) +{ + /* + After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need + to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers + for the Adam7 code, the color convert code and the output to the user. + in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must + have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits + also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7 + only useful if (ilinebits - olinebits) is a value in the range 1..7 + */ + unsigned y; + size_t diff = ilinebits - olinebits; + size_t ibp = 0, obp = 0; /*input and output bit pointers*/ + for(y = 0; y < h; ++y) { + size_t x; + for(x = 0; x < olinebits; ++x) { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + ibp += diff; + } +} + +/*out must be buffer big enough to contain full image, and in must contain the full decompressed data from +the IDAT chunks (with filter index bytes and possible padding bits) +return value is error*/ +static unsigned postProcessScanlines(unsigned char * out, unsigned char * in, + unsigned w, unsigned h, const LodePNGInfo * info_png) +{ + /* + This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype. + Steps: + *) if no Adam7: 1) unfilter 2) remove padding bits (= possible extra bits per scanline if bpp < 8) + *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace + NOTE: the in buffer will be overwritten with intermediate data! + */ + unsigned bpp = lodepng_get_bpp(&info_png->color); + if(bpp == 0) return 31; /*error: invalid colortype*/ + + if(info_png->interlace_method == 0) { + if(bpp < 8 && w * bpp != ((w * bpp + 7u) / 8u) * 8u) { + CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp)); + removePaddingBits(out, in, w * bpp, ((w * bpp + 7u) / 8u) * 8u, h); + } + /*we can immediately filter into the out buffer, no other steps needed*/ + else CERROR_TRY_RETURN(unfilter(out, in, w, h, bpp)); + } + else { /*interlace_method is 1 (Adam7)*/ + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned i; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + for(i = 0; i != 7; ++i) { + CERROR_TRY_RETURN(unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp)); + /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline, + move bytes instead of bits or move not at all*/ + if(bpp < 8) { + /*remove padding bits in scanlines; after this there still may be padding + bits between the different reduced images: each reduced image still starts nicely at a byte*/ + removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp, + ((passw[i] * bpp + 7u) / 8u) * 8u, passh[i]); + } + } + + Adam7_deinterlace(out, in, w, h, bpp); + } + + return 0; +} + +static unsigned readChunk_PLTE(LodePNGColorMode * color, const unsigned char * data, size_t chunkLength) +{ + unsigned pos = 0, i; + color->palettesize = chunkLength / 3u; + if(color->palettesize == 0 || color->palettesize > 256) return 38; /*error: palette too small or big*/ + lodepng_color_mode_alloc_palette(color); + if(!color->palette && color->palettesize) { + color->palettesize = 0; + return 83; /*alloc fail*/ + } + + for(i = 0; i != color->palettesize; ++i) { + color->palette[4 * i + 0] = data[pos++]; /*R*/ + color->palette[4 * i + 1] = data[pos++]; /*G*/ + color->palette[4 * i + 2] = data[pos++]; /*B*/ + color->palette[4 * i + 3] = 255; /*alpha*/ + } + + return 0; /* OK */ +} + +static unsigned readChunk_tRNS(LodePNGColorMode * color, const unsigned char * data, size_t chunkLength) +{ + unsigned i; + if(color->colortype == LCT_PALETTE) { + /*error: more alpha values given than there are palette entries*/ + if(chunkLength > color->palettesize) return 39; + + for(i = 0; i != chunkLength; ++i) color->palette[4 * i + 3] = data[i]; + } + else if(color->colortype == LCT_GREY) { + /*error: this chunk must be 2 bytes for grayscale image*/ + if(chunkLength != 2) return 30; + + color->key_defined = 1; + color->key_r = color->key_g = color->key_b = 256u * data[0] + data[1]; + } + else if(color->colortype == LCT_RGB) { + /*error: this chunk must be 6 bytes for RGB image*/ + if(chunkLength != 6) return 41; + + color->key_defined = 1; + color->key_r = 256u * data[0] + data[1]; + color->key_g = 256u * data[2] + data[3]; + color->key_b = 256u * data[4] + data[5]; + } + else return 42; /*error: tRNS chunk not allowed for other color models*/ + + return 0; /* OK */ +} + + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +/*background color chunk (bKGD)*/ +static unsigned readChunk_bKGD(LodePNGInfo * info, const unsigned char * data, size_t chunkLength) +{ + if(info->color.colortype == LCT_PALETTE) { + /*error: this chunk must be 1 byte for indexed color image*/ + if(chunkLength != 1) return 43; + + /*error: invalid palette index, or maybe this chunk appeared before PLTE*/ + if(data[0] >= info->color.palettesize) return 103; + + info->background_defined = 1; + info->background_r = info->background_g = info->background_b = data[0]; + } + else if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) { + /*error: this chunk must be 2 bytes for grayscale image*/ + if(chunkLength != 2) return 44; + + /*the values are truncated to bitdepth in the PNG file*/ + info->background_defined = 1; + info->background_r = info->background_g = info->background_b = 256u * data[0] + data[1]; + } + else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) { + /*error: this chunk must be 6 bytes for grayscale image*/ + if(chunkLength != 6) return 45; + + /*the values are truncated to bitdepth in the PNG file*/ + info->background_defined = 1; + info->background_r = 256u * data[0] + data[1]; + info->background_g = 256u * data[2] + data[3]; + info->background_b = 256u * data[4] + data[5]; + } + + return 0; /* OK */ +} + +/*text chunk (tEXt)*/ +static unsigned readChunk_tEXt(LodePNGInfo * info, const unsigned char * data, size_t chunkLength) +{ + unsigned error = 0; + char * key = 0, * str = 0; + + while(!error) { /*not really a while loop, only used to break on error*/ + unsigned length, string2_begin; + + length = 0; + while(length < chunkLength && data[length] != 0) ++length; + /*even though it's not allowed by the standard, no error is thrown if + there's no null termination char, if the text is empty*/ + if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ + + key = (char *)lodepng_malloc(length + 1); + if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(key, data, length); + key[length] = 0; + + string2_begin = length + 1; /*skip keyword null terminator*/ + + length = (unsigned)(chunkLength < string2_begin ? 0 : chunkLength - string2_begin); + str = (char *)lodepng_malloc(length + 1); + if(!str) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(str, data + string2_begin, length); + str[length] = 0; + + error = lodepng_add_text(info, key, str); + + break; + } + + lodepng_free(key); + lodepng_free(str); + + return error; +} + +/*compressed text chunk (zTXt)*/ +static unsigned readChunk_zTXt(LodePNGInfo * info, const LodePNGDecoderSettings * decoder, + const unsigned char * data, size_t chunkLength) +{ + unsigned error = 0; + + /*copy the object to change parameters in it*/ + LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; + + unsigned length, string2_begin; + char * key = 0; + unsigned char * str = 0; + size_t size = 0; + + while(!error) { /*not really a while loop, only used to break on error*/ + for(length = 0; length < chunkLength && data[length] != 0; ++length) ; + if(length + 2 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ + if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ + + key = (char *)lodepng_malloc(length + 1); + if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(key, data, length); + key[length] = 0; + + if(data[length + 1] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ + + string2_begin = length + 2; + if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ + + length = (unsigned)chunkLength - string2_begin; + zlibsettings.max_output_size = decoder->max_text_size; + /*will fail if zlib error, e.g. if length is too small*/ + error = zlib_decompress(&str, &size, 0, &data[string2_begin], + length, &zlibsettings); + /*error: compressed text larger than decoder->max_text_size*/ + if(error && size > zlibsettings.max_output_size) error = 112; + if(error) break; + error = lodepng_add_text_sized(info, key, (char *)str, size); + break; + } + + lodepng_free(key); + lodepng_free(str); + + return error; +} + +/*international text chunk (iTXt)*/ +static unsigned readChunk_iTXt(LodePNGInfo * info, const LodePNGDecoderSettings * decoder, + const unsigned char * data, size_t chunkLength) +{ + unsigned error = 0; + unsigned i; + + /*copy the object to change parameters in it*/ + LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; + + unsigned length, begin, compressed; + char * key = 0, * langtag = 0, * transkey = 0; + + while(!error) { /*not really a while loop, only used to break on error*/ + /*Quick check if the chunk length isn't too small. Even without check + it'd still fail with other error checks below if it's too short. This just gives a different error code.*/ + if(chunkLength < 5) CERROR_BREAK(error, 30); /*iTXt chunk too short*/ + + /*read the key*/ + for(length = 0; length < chunkLength && data[length] != 0; ++length) ; + if(length + 3 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination char, corrupt?*/ + if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ + + key = (char *)lodepng_malloc(length + 1); + if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(key, data, length); + key[length] = 0; + + /*read the compression method*/ + compressed = data[length + 1]; + if(data[length + 2] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ + + /*even though it's not allowed by the standard, no error is thrown if + there's no null termination char, if the text is empty for the next 3 texts*/ + + /*read the langtag*/ + begin = length + 3; + length = 0; + for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length; + + langtag = (char *)lodepng_malloc(length + 1); + if(!langtag) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(langtag, data + begin, length); + langtag[length] = 0; + + /*read the transkey*/ + begin += length + 1; + length = 0; + for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length; + + transkey = (char *)lodepng_malloc(length + 1); + if(!transkey) CERROR_BREAK(error, 83); /*alloc fail*/ + + lodepng_memcpy(transkey, data + begin, length); + transkey[length] = 0; + + /*read the actual text*/ + begin += length + 1; + + length = (unsigned)chunkLength < begin ? 0 : (unsigned)chunkLength - begin; + + if(compressed) { + unsigned char * str = 0; + size_t size = 0; + zlibsettings.max_output_size = decoder->max_text_size; + /*will fail if zlib error, e.g. if length is too small*/ + error = zlib_decompress(&str, &size, 0, &data[begin], + length, &zlibsettings); + /*error: compressed text larger than decoder->max_text_size*/ + if(error && size > zlibsettings.max_output_size) error = 112; + if(!error) error = lodepng_add_itext_sized(info, key, langtag, transkey, (char *)str, size); + lodepng_free(str); + } + else { + error = lodepng_add_itext_sized(info, key, langtag, transkey, (char *)(data + begin), length); + } + + break; + } + + lodepng_free(key); + lodepng_free(langtag); + lodepng_free(transkey); + + return error; +} + +static unsigned readChunk_tIME(LodePNGInfo * info, const unsigned char * data, size_t chunkLength) +{ + if(chunkLength != 7) return 73; /*invalid tIME chunk size*/ + + info->time_defined = 1; + info->time.year = 256u * data[0] + data[1]; + info->time.month = data[2]; + info->time.day = data[3]; + info->time.hour = data[4]; + info->time.minute = data[5]; + info->time.second = data[6]; + + return 0; /* OK */ +} + +static unsigned readChunk_pHYs(LodePNGInfo * info, const unsigned char * data, size_t chunkLength) +{ + if(chunkLength != 9) return 74; /*invalid pHYs chunk size*/ + + info->phys_defined = 1; + info->phys_x = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3]; + info->phys_y = 16777216u * data[4] + 65536u * data[5] + 256u * data[6] + data[7]; + info->phys_unit = data[8]; + + return 0; /* OK */ +} + +static unsigned readChunk_gAMA(LodePNGInfo * info, const unsigned char * data, size_t chunkLength) +{ + if(chunkLength != 4) return 96; /*invalid gAMA chunk size*/ + + info->gama_defined = 1; + info->gama_gamma = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3]; + + return 0; /* OK */ +} + +static unsigned readChunk_cHRM(LodePNGInfo * info, const unsigned char * data, size_t chunkLength) +{ + if(chunkLength != 32) return 97; /*invalid cHRM chunk size*/ + + info->chrm_defined = 1; + info->chrm_white_x = 16777216u * data[ 0] + 65536u * data[ 1] + 256u * data[ 2] + data[ 3]; + info->chrm_white_y = 16777216u * data[ 4] + 65536u * data[ 5] + 256u * data[ 6] + data[ 7]; + info->chrm_red_x = 16777216u * data[ 8] + 65536u * data[ 9] + 256u * data[10] + data[11]; + info->chrm_red_y = 16777216u * data[12] + 65536u * data[13] + 256u * data[14] + data[15]; + info->chrm_green_x = 16777216u * data[16] + 65536u * data[17] + 256u * data[18] + data[19]; + info->chrm_green_y = 16777216u * data[20] + 65536u * data[21] + 256u * data[22] + data[23]; + info->chrm_blue_x = 16777216u * data[24] + 65536u * data[25] + 256u * data[26] + data[27]; + info->chrm_blue_y = 16777216u * data[28] + 65536u * data[29] + 256u * data[30] + data[31]; + + return 0; /* OK */ +} + +static unsigned readChunk_sRGB(LodePNGInfo * info, const unsigned char * data, size_t chunkLength) +{ + if(chunkLength != 1) return 98; /*invalid sRGB chunk size (this one is never ignored)*/ + + info->srgb_defined = 1; + info->srgb_intent = data[0]; + + return 0; /* OK */ +} + +static unsigned readChunk_iCCP(LodePNGInfo * info, const LodePNGDecoderSettings * decoder, + const unsigned char * data, size_t chunkLength) +{ + unsigned error = 0; + unsigned i; + size_t size = 0; + /*copy the object to change parameters in it*/ + LodePNGDecompressSettings zlibsettings = decoder->zlibsettings; + + unsigned length, string2_begin; + + info->iccp_defined = 1; + if(info->iccp_name) lodepng_clear_icc(info); + + for(length = 0; length < chunkLength && data[length] != 0; ++length) ; + if(length + 2 >= chunkLength) return 75; /*no null termination, corrupt?*/ + if(length < 1 || length > 79) return 89; /*keyword too short or long*/ + + info->iccp_name = (char *)lodepng_malloc(length + 1); + if(!info->iccp_name) return 83; /*alloc fail*/ + + info->iccp_name[length] = 0; + for(i = 0; i != length; ++i) info->iccp_name[i] = (char)data[i]; + + if(data[length + 1] != 0) return 72; /*the 0 byte indicating compression must be 0*/ + + string2_begin = length + 2; + if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/ + + length = (unsigned)chunkLength - string2_begin; + zlibsettings.max_output_size = decoder->max_icc_size; + error = zlib_decompress(&info->iccp_profile, &size, 0, + &data[string2_begin], + length, &zlibsettings); + /*error: ICC profile larger than decoder->max_icc_size*/ + if(error && size > zlibsettings.max_output_size) error = 113; + info->iccp_profile_size = size; + if(!error && !info->iccp_profile_size) error = 100; /*invalid ICC profile size*/ + return error; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +unsigned lodepng_inspect_chunk(LodePNGState * state, size_t pos, + const unsigned char * in, size_t insize) +{ + const unsigned char * chunk = in + pos; + unsigned chunkLength; + const unsigned char * data; + unsigned unhandled = 0; + unsigned error = 0; + + if(pos + 4 > insize) return 30; + chunkLength = lodepng_chunk_length(chunk); + if(chunkLength > 2147483647) return 63; + data = lodepng_chunk_data_const(chunk); + if(data + chunkLength + 4 > in + insize) return 30; + + if(lodepng_chunk_type_equals(chunk, "PLTE")) { + error = readChunk_PLTE(&state->info_png.color, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "tRNS")) { + error = readChunk_tRNS(&state->info_png.color, data, chunkLength); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + } + else if(lodepng_chunk_type_equals(chunk, "bKGD")) { + error = readChunk_bKGD(&state->info_png, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "tEXt")) { + error = readChunk_tEXt(&state->info_png, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "zTXt")) { + error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "iTXt")) { + error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "tIME")) { + error = readChunk_tIME(&state->info_png, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "pHYs")) { + error = readChunk_pHYs(&state->info_png, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "gAMA")) { + error = readChunk_gAMA(&state->info_png, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "cHRM")) { + error = readChunk_cHRM(&state->info_png, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "sRGB")) { + error = readChunk_sRGB(&state->info_png, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "iCCP")) { + error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } + else { + /* unhandled chunk is ok (is not an error) */ + unhandled = 1; + } + + if(!error && !unhandled && !state->decoder.ignore_crc) { + if(lodepng_chunk_check_crc(chunk)) return 57; /*invalid CRC*/ + } + + return error; +} + +/*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/ +static void decodeGeneric(unsigned char ** out, unsigned * w, unsigned * h, + LodePNGState * state, + const unsigned char * in, size_t insize) +{ + unsigned char IEND = 0; + const unsigned char * chunk; + unsigned char * idat; /*the data from idat chunks, zlib compressed*/ + size_t idatsize = 0; + unsigned char * scanlines = 0; + size_t scanlines_size = 0, expected_size = 0; + size_t outsize = 0; + + /*for unknown chunk order*/ + unsigned unknown = 0; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + + + /* safe output values in case error happens */ + *out = 0; + *w = *h = 0; + + state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/ + if(state->error) return; + + if(lodepng_pixel_overflow(*w, *h, &state->info_png.color, &state->info_raw)) { + CERROR_RETURN(state->error, 92); /*overflow possible due to amount of pixels*/ + } + + /*the input filesize is a safe upper bound for the sum of idat chunks size*/ + idat = (unsigned char *)lodepng_malloc(insize); + if(!idat) CERROR_RETURN(state->error, 83); /*alloc fail*/ + + chunk = &in[33]; /*first byte of the first chunk after the header*/ + + /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. + IDAT data is put at the start of the in buffer*/ + while(!IEND && !state->error) { + unsigned chunkLength; + const unsigned char * data; /*the data in the chunk*/ + + /*error: size of the in buffer too small to contain next chunk*/ + if((size_t)((chunk - in) + 12) > insize || chunk < in) { + if(state->decoder.ignore_end) break; /*other errors may still happen though*/ + CERROR_BREAK(state->error, 30); + } + + /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/ + chunkLength = lodepng_chunk_length(chunk); + /*error: chunk length larger than the max PNG chunk size*/ + if(chunkLength > 2147483647) { + if(state->decoder.ignore_end) break; /*other errors may still happen though*/ + CERROR_BREAK(state->error, 63); + } + + if((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in) { + CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk*/ + } + + data = lodepng_chunk_data_const(chunk); + + unknown = 0; + + /*IDAT chunk, containing compressed image data*/ + if(lodepng_chunk_type_equals(chunk, "IDAT")) { + size_t newsize; + if(lodepng_addofl(idatsize, chunkLength, &newsize)) CERROR_BREAK(state->error, 95); + if(newsize > insize) CERROR_BREAK(state->error, 95); + lodepng_memcpy(idat + idatsize, data, chunkLength); + idatsize += chunkLength; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + critical_pos = 3; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } + else if(lodepng_chunk_type_equals(chunk, "IEND")) { + /*IEND chunk*/ + IEND = 1; + } + else if(lodepng_chunk_type_equals(chunk, "PLTE")) { + /*palette chunk (PLTE)*/ + state->error = readChunk_PLTE(&state->info_png.color, data, chunkLength); + if(state->error) break; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + critical_pos = 2; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } + else if(lodepng_chunk_type_equals(chunk, "tRNS")) { + /*palette transparency chunk (tRNS). Even though this one is an ancillary chunk , it is still compiled + in without 'LODEPNG_COMPILE_ANCILLARY_CHUNKS' because it contains essential color information that + affects the alpha channel of pixels. */ + state->error = readChunk_tRNS(&state->info_png.color, data, chunkLength); + if(state->error) break; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*background color chunk (bKGD)*/ + } + else if(lodepng_chunk_type_equals(chunk, "bKGD")) { + state->error = readChunk_bKGD(&state->info_png, data, chunkLength); + if(state->error) break; + } + else if(lodepng_chunk_type_equals(chunk, "tEXt")) { + /*text chunk (tEXt)*/ + if(state->decoder.read_text_chunks) { + state->error = readChunk_tEXt(&state->info_png, data, chunkLength); + if(state->error) break; + } + } + else if(lodepng_chunk_type_equals(chunk, "zTXt")) { + /*compressed text chunk (zTXt)*/ + if(state->decoder.read_text_chunks) { + state->error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength); + if(state->error) break; + } + } + else if(lodepng_chunk_type_equals(chunk, "iTXt")) { + /*international text chunk (iTXt)*/ + if(state->decoder.read_text_chunks) { + state->error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength); + if(state->error) break; + } + } + else if(lodepng_chunk_type_equals(chunk, "tIME")) { + state->error = readChunk_tIME(&state->info_png, data, chunkLength); + if(state->error) break; + } + else if(lodepng_chunk_type_equals(chunk, "pHYs")) { + state->error = readChunk_pHYs(&state->info_png, data, chunkLength); + if(state->error) break; + } + else if(lodepng_chunk_type_equals(chunk, "gAMA")) { + state->error = readChunk_gAMA(&state->info_png, data, chunkLength); + if(state->error) break; + } + else if(lodepng_chunk_type_equals(chunk, "cHRM")) { + state->error = readChunk_cHRM(&state->info_png, data, chunkLength); + if(state->error) break; + } + else if(lodepng_chunk_type_equals(chunk, "sRGB")) { + state->error = readChunk_sRGB(&state->info_png, data, chunkLength); + if(state->error) break; + } + else if(lodepng_chunk_type_equals(chunk, "iCCP")) { + state->error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength); + if(state->error) break; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } + else { /*it's not an implemented chunk type, so ignore it: skip over the data*/ + /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/ + if(!state->decoder.ignore_critical && !lodepng_chunk_ancillary(chunk)) { + CERROR_BREAK(state->error, 69); + } + + unknown = 1; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(state->decoder.remember_unknown_chunks) { + state->error = lodepng_chunk_append(&state->info_png.unknown_chunks_data[critical_pos - 1], + &state->info_png.unknown_chunks_size[critical_pos - 1], chunk); + if(state->error) break; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } + + if(!state->decoder.ignore_crc && !unknown) { /*check CRC if wanted, only on known chunk types*/ + if(lodepng_chunk_check_crc(chunk)) CERROR_BREAK(state->error, 57); /*invalid CRC*/ + } + + if(!IEND) chunk = lodepng_chunk_next_const(chunk, in + insize); + } + + if(!state->error && state->info_png.color.colortype == LCT_PALETTE && !state->info_png.color.palette) { + state->error = 106; /* error: PNG file must have PLTE chunk if color type is palette */ + } + + if(!state->error) { + /*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation. + If the decompressed size does not match the prediction, the image must be corrupt.*/ + if(state->info_png.interlace_method == 0) { + size_t bpp = lodepng_get_bpp(&state->info_png.color); + expected_size = lodepng_get_raw_size_idat(*w, *h, bpp); + } + else { + size_t bpp = lodepng_get_bpp(&state->info_png.color); + /*Adam-7 interlaced: expected size is the sum of the 7 sub-images sizes*/ + expected_size = 0; + expected_size += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, bpp); + if(*w > 4) expected_size += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, bpp); + expected_size += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, bpp); + if(*w > 2) expected_size += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, bpp); + expected_size += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, bpp); + if(*w > 1) expected_size += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, bpp); + expected_size += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, bpp); + } + + state->error = zlib_decompress(&scanlines, &scanlines_size, expected_size, idat, idatsize, + &state->decoder.zlibsettings); + } + if(!state->error && scanlines_size != expected_size) state->error = 91; /*decompressed size doesn't match prediction*/ + lodepng_free(idat); + + if(!state->error) { + lv_draw_buf_t * decoded = lv_draw_buf_create(*w, *h, LV_COLOR_FORMAT_ARGB8888, 4 * *w); + if(decoded) { + *out = (unsigned char*)decoded; + outsize = decoded->data_size; + } + else state->error = 83; /*alloc fail*/ + } + if(!state->error) { + lv_draw_buf_t * decoded = (lv_draw_buf_t *)*out; + lodepng_memset(decoded->data, 0, outsize); + state->error = postProcessScanlines(decoded->data, scanlines, *w, *h, &state->info_png); + } + lodepng_free(scanlines); +} + +unsigned lodepng_decode(unsigned char ** out, unsigned * w, unsigned * h, + LodePNGState * state, + const unsigned char * in, size_t insize) +{ + *out = NULL; + decodeGeneric(out, w, h, state, in, insize); + if(state->error) return state->error; + if(!state->decoder.color_convert || lodepng_color_mode_equal(&state->info_raw, &state->info_png.color)) { + /*same color type, no copying or converting of data needed*/ + /*store the info_png color settings on the info_raw so that the info_raw still reflects what colortype + the raw image has to the end user*/ + if(!state->decoder.color_convert) { + state->error = lodepng_color_mode_copy(&state->info_raw, &state->info_png.color); + if(state->error) return state->error; + } + } + else { /*color conversion needed*/ + lv_draw_buf_t * old_buf = (lv_draw_buf_t *)*out; + + /*TODO: check if this works according to the statement in the documentation: "The converter can convert + from grayscale input color type, to 8-bit grayscale or grayscale with alpha"*/ + if(!(state->info_raw.colortype == LCT_RGB || state->info_raw.colortype == LCT_RGBA) + && !(state->info_raw.bitdepth == 8)) { + return 56; /*unsupported color mode conversion*/ + } + + lv_draw_buf_t * new_buf = lv_draw_buf_create(*w, *h, LV_COLOR_FORMAT_ARGB8888, 4 * *w); + if(new_buf == NULL) { + state->error = 83; /*alloc fail*/ + } + else { + state->error = lodepng_convert(new_buf->data, old_buf->data, + &state->info_raw, &state->info_png.color, *w, *h); + + if (state->error) { + lv_draw_buf_destroy(new_buf); + new_buf = NULL; + } + } + + *out = (unsigned char*)new_buf; + lv_draw_buf_destroy(old_buf); + } + return state->error; +} + +unsigned lodepng_decode_memory(unsigned char ** out, unsigned * w, unsigned * h, const unsigned char * in, + size_t insize, LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned error; + LodePNGState state; + lodepng_state_init(&state); + state.info_raw.colortype = colortype; + state.info_raw.bitdepth = bitdepth; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*disable reading things that this function doesn't output*/ + state.decoder.read_text_chunks = 0; + state.decoder.remember_unknown_chunks = 0; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + error = lodepng_decode(out, w, h, &state, in, insize); + lodepng_state_cleanup(&state); + return error; +} + +unsigned lodepng_decode32(unsigned char ** out, unsigned * w, unsigned * h, const unsigned char * in, size_t insize) +{ + return lodepng_decode_memory(out, w, h, in, insize, LCT_RGBA, 8); +} + +unsigned lodepng_decode24(unsigned char ** out, unsigned * w, unsigned * h, const unsigned char * in, size_t insize) +{ + return lodepng_decode_memory(out, w, h, in, insize, LCT_RGB, 8); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned lodepng_decode_file(unsigned char ** out, unsigned * w, unsigned * h, const char * filename, + LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned char * buffer = 0; + size_t buffersize; + unsigned error; + /* safe output values in case error happens */ + *out = 0; + *w = *h = 0; + error = lodepng_load_file(&buffer, &buffersize, filename); + if(!error) error = lodepng_decode_memory(out, w, h, buffer, buffersize, colortype, bitdepth); + lodepng_free(buffer); + return error; +} + +unsigned lodepng_decode32_file(unsigned char ** out, unsigned * w, unsigned * h, const char * filename) +{ + return lodepng_decode_file(out, w, h, filename, LCT_RGBA, 8); +} + +unsigned lodepng_decode24_file(unsigned char ** out, unsigned * w, unsigned * h, const char * filename) +{ + return lodepng_decode_file(out, w, h, filename, LCT_RGB, 8); +} +#endif /*LODEPNG_COMPILE_DISK*/ + +void lodepng_decoder_settings_init(LodePNGDecoderSettings * settings) +{ + settings->color_convert = 1; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + settings->read_text_chunks = 1; + settings->remember_unknown_chunks = 0; + settings->max_text_size = 16777216; + settings->max_icc_size = 16777216; /* 16MB is much more than enough for any reasonable ICC profile */ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + settings->ignore_crc = 0; + settings->ignore_critical = 0; + settings->ignore_end = 0; + lodepng_decompress_settings_init(&settings->zlibsettings); +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) + +void lodepng_state_init(LodePNGState * state) +{ +#ifdef LODEPNG_COMPILE_DECODER + lodepng_decoder_settings_init(&state->decoder); +#endif /*LODEPNG_COMPILE_DECODER*/ +#ifdef LODEPNG_COMPILE_ENCODER + lodepng_encoder_settings_init(&state->encoder); +#endif /*LODEPNG_COMPILE_ENCODER*/ + lodepng_color_mode_init(&state->info_raw); + lodepng_info_init(&state->info_png); + state->error = 1; +} + +void lodepng_state_cleanup(LodePNGState * state) +{ + lodepng_color_mode_cleanup(&state->info_raw); + lodepng_info_cleanup(&state->info_png); +} + +void lodepng_state_copy(LodePNGState * dest, const LodePNGState * source) +{ + lodepng_state_cleanup(dest); + *dest = *source; + lodepng_color_mode_init(&dest->info_raw); + lodepng_info_init(&dest->info_png); + dest->error = lodepng_color_mode_copy(&dest->info_raw, &source->info_raw); + if(dest->error) return; + dest->error = lodepng_info_copy(&dest->info_png, &source->info_png); + if(dest->error) return; +} + +#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ + +#ifdef LODEPNG_COMPILE_ENCODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / PNG Encoder / */ +/* ////////////////////////////////////////////////////////////////////////// */ + + +static unsigned writeSignature(ucvector * out) +{ + size_t pos = out->size; + const unsigned char signature[] = {137, 80, 78, 71, 13, 10, 26, 10}; + /*8 bytes PNG signature, aka the magic bytes*/ + if(!ucvector_resize(out, out->size + 8)) return 83; /*alloc fail*/ + lodepng_memcpy(out->data + pos, signature, 8); + return 0; +} + +static unsigned addChunk_IHDR(ucvector * out, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method) +{ + unsigned char * chunk, * data; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 13, "IHDR")); + data = chunk + 8; + + lodepng_set32bitInt(data + 0, w); /*width*/ + lodepng_set32bitInt(data + 4, h); /*height*/ + data[8] = (unsigned char)bitdepth; /*bit depth*/ + data[9] = (unsigned char)colortype; /*color type*/ + data[10] = 0; /*compression method*/ + data[11] = 0; /*filter method*/ + data[12] = interlace_method; /*interlace method*/ + + lodepng_chunk_generate_crc(chunk); + return 0; +} + +/* only adds the chunk if needed (there is a key or palette with alpha) */ +static unsigned addChunk_PLTE(ucvector * out, const LodePNGColorMode * info) +{ + unsigned char * chunk; + size_t i, j = 8; + + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, info->palettesize * 3, "PLTE")); + + for(i = 0; i != info->palettesize; ++i) { + /*add all channels except alpha channel*/ + chunk[j++] = info->palette[i * 4 + 0]; + chunk[j++] = info->palette[i * 4 + 1]; + chunk[j++] = info->palette[i * 4 + 2]; + } + + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_tRNS(ucvector * out, const LodePNGColorMode * info) +{ + unsigned char * chunk = 0; + + if(info->colortype == LCT_PALETTE) { + size_t i, amount = info->palettesize; + /*the tail of palette values that all have 255 as alpha, does not have to be encoded*/ + for(i = info->palettesize; i != 0; --i) { + if(info->palette[4 * (i - 1) + 3] != 255) break; + --amount; + } + if(amount) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, amount, "tRNS")); + /*add the alpha channel values from the palette*/ + for(i = 0; i != amount; ++i) chunk[8 + i] = info->palette[4 * i + 3]; + } + } + else if(info->colortype == LCT_GREY) { + if(info->key_defined) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "tRNS")); + chunk[8] = (unsigned char)(info->key_r >> 8); + chunk[9] = (unsigned char)(info->key_r & 255); + } + } + else if(info->colortype == LCT_RGB) { + if(info->key_defined) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 6, "tRNS")); + chunk[8] = (unsigned char)(info->key_r >> 8); + chunk[9] = (unsigned char)(info->key_r & 255); + chunk[10] = (unsigned char)(info->key_g >> 8); + chunk[11] = (unsigned char)(info->key_g & 255); + chunk[12] = (unsigned char)(info->key_b >> 8); + chunk[13] = (unsigned char)(info->key_b & 255); + } + } + + if(chunk) lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_IDAT(ucvector * out, const unsigned char * data, size_t datasize, + LodePNGCompressSettings * zlibsettings) +{ + unsigned error = 0; + unsigned char * zlib = 0; + size_t zlibsize = 0; + + error = zlib_compress(&zlib, &zlibsize, data, datasize, zlibsettings); + if(!error) { + error = lodepng_chunk_createv(out, zlibsize, "IDAT", zlib); + } + lodepng_free(zlib); + return error; +} + +static unsigned addChunk_IEND(ucvector * out) +{ + return lodepng_chunk_createv(out, 0, "IEND", 0); +} + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + +static unsigned addChunk_tEXt(ucvector * out, const char * keyword, const char * textstring) +{ + unsigned char * chunk = 0; + size_t keysize = lodepng_strlen(keyword), textsize = lodepng_strlen(textstring); + size_t size = keysize + 1 + textsize; + if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, size, "tEXt")); + lodepng_memcpy(chunk + 8, keyword, keysize); + chunk[8 + keysize] = 0; /*null termination char*/ + lodepng_memcpy(chunk + 9 + keysize, textstring, textsize); + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_zTXt(ucvector * out, const char * keyword, const char * textstring, + LodePNGCompressSettings * zlibsettings) +{ + unsigned error = 0; + unsigned char * chunk = 0; + unsigned char * compressed = 0; + size_t compressedsize = 0; + size_t textsize = lodepng_strlen(textstring); + size_t keysize = lodepng_strlen(keyword); + if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ + + error = zlib_compress(&compressed, &compressedsize, + (const unsigned char *)textstring, textsize, zlibsettings); + if(!error) { + size_t size = keysize + 2 + compressedsize; + error = lodepng_chunk_init(&chunk, out, size, "zTXt"); + } + if(!error) { + lodepng_memcpy(chunk + 8, keyword, keysize); + chunk[8 + keysize] = 0; /*null termination char*/ + chunk[9 + keysize] = 0; /*compression method: 0*/ + lodepng_memcpy(chunk + 10 + keysize, compressed, compressedsize); + lodepng_chunk_generate_crc(chunk); + } + + lodepng_free(compressed); + return error; +} + +static unsigned addChunk_iTXt(ucvector * out, unsigned compress, const char * keyword, const char * langtag, + const char * transkey, const char * textstring, LodePNGCompressSettings * zlibsettings) +{ + unsigned error = 0; + unsigned char * chunk = 0; + unsigned char * compressed = 0; + size_t compressedsize = 0; + size_t textsize = lodepng_strlen(textstring); + size_t keysize = lodepng_strlen(keyword), langsize = lodepng_strlen(langtag), transsize = lodepng_strlen(transkey); + + if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ + + if(compress) { + error = zlib_compress(&compressed, &compressedsize, + (const unsigned char *)textstring, textsize, zlibsettings); + } + if(!error) { + size_t size = keysize + 3 + langsize + 1 + transsize + 1 + (compress ? compressedsize : textsize); + error = lodepng_chunk_init(&chunk, out, size, "iTXt"); + } + if(!error) { + size_t pos = 8; + lodepng_memcpy(chunk + pos, keyword, keysize); + pos += keysize; + chunk[pos++] = 0; /*null termination char*/ + chunk[pos++] = (compress ? 1 : 0); /*compression flag*/ + chunk[pos++] = 0; /*compression method: 0*/ + lodepng_memcpy(chunk + pos, langtag, langsize); + pos += langsize; + chunk[pos++] = 0; /*null termination char*/ + lodepng_memcpy(chunk + pos, transkey, transsize); + pos += transsize; + chunk[pos++] = 0; /*null termination char*/ + if(compress) { + lodepng_memcpy(chunk + pos, compressed, compressedsize); + } + else { + lodepng_memcpy(chunk + pos, textstring, textsize); + } + lodepng_chunk_generate_crc(chunk); + } + + lodepng_free(compressed); + return error; +} + +static unsigned addChunk_bKGD(ucvector * out, const LodePNGInfo * info) +{ + unsigned char * chunk = 0; + if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "bKGD")); + chunk[8] = (unsigned char)(info->background_r >> 8); + chunk[9] = (unsigned char)(info->background_r & 255); + } + else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 6, "bKGD")); + chunk[8] = (unsigned char)(info->background_r >> 8); + chunk[9] = (unsigned char)(info->background_r & 255); + chunk[10] = (unsigned char)(info->background_g >> 8); + chunk[11] = (unsigned char)(info->background_g & 255); + chunk[12] = (unsigned char)(info->background_b >> 8); + chunk[13] = (unsigned char)(info->background_b & 255); + } + else if(info->color.colortype == LCT_PALETTE) { + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 1, "bKGD")); + chunk[8] = (unsigned char)(info->background_r & 255); /*palette index*/ + } + if(chunk) lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_tIME(ucvector * out, const LodePNGTime * time) +{ + unsigned char * chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 7, "tIME")); + chunk[8] = (unsigned char)(time->year >> 8); + chunk[9] = (unsigned char)(time->year & 255); + chunk[10] = (unsigned char)time->month; + chunk[11] = (unsigned char)time->day; + chunk[12] = (unsigned char)time->hour; + chunk[13] = (unsigned char)time->minute; + chunk[14] = (unsigned char)time->second; + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_pHYs(ucvector * out, const LodePNGInfo * info) +{ + unsigned char * chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 9, "pHYs")); + lodepng_set32bitInt(chunk + 8, info->phys_x); + lodepng_set32bitInt(chunk + 12, info->phys_y); + chunk[16] = info->phys_unit; + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_gAMA(ucvector * out, const LodePNGInfo * info) +{ + unsigned char * chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 4, "gAMA")); + lodepng_set32bitInt(chunk + 8, info->gama_gamma); + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_cHRM(ucvector * out, const LodePNGInfo * info) +{ + unsigned char * chunk; + CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 32, "cHRM")); + lodepng_set32bitInt(chunk + 8, info->chrm_white_x); + lodepng_set32bitInt(chunk + 12, info->chrm_white_y); + lodepng_set32bitInt(chunk + 16, info->chrm_red_x); + lodepng_set32bitInt(chunk + 20, info->chrm_red_y); + lodepng_set32bitInt(chunk + 24, info->chrm_green_x); + lodepng_set32bitInt(chunk + 28, info->chrm_green_y); + lodepng_set32bitInt(chunk + 32, info->chrm_blue_x); + lodepng_set32bitInt(chunk + 36, info->chrm_blue_y); + lodepng_chunk_generate_crc(chunk); + return 0; +} + +static unsigned addChunk_sRGB(ucvector * out, const LodePNGInfo * info) +{ + unsigned char data = info->srgb_intent; + return lodepng_chunk_createv(out, 1, "sRGB", &data); +} + +static unsigned addChunk_iCCP(ucvector * out, const LodePNGInfo * info, LodePNGCompressSettings * zlibsettings) +{ + unsigned error = 0; + unsigned char * chunk = 0; + unsigned char * compressed = 0; + size_t compressedsize = 0; + size_t keysize = lodepng_strlen(info->iccp_name); + + if(keysize < 1 || keysize > 79) return 89; /*error: invalid keyword size*/ + error = zlib_compress(&compressed, &compressedsize, + info->iccp_profile, info->iccp_profile_size, zlibsettings); + if(!error) { + size_t size = keysize + 2 + compressedsize; + error = lodepng_chunk_init(&chunk, out, size, "iCCP"); + } + if(!error) { + lodepng_memcpy(chunk + 8, info->iccp_name, keysize); + chunk[8 + keysize] = 0; /*null termination char*/ + chunk[9 + keysize] = 0; /*compression method: 0*/ + lodepng_memcpy(chunk + 10 + keysize, compressed, compressedsize); + lodepng_chunk_generate_crc(chunk); + } + + lodepng_free(compressed); + return error; +} + +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +static void filterScanline(unsigned char * out, const unsigned char * scanline, const unsigned char * prevline, + size_t length, size_t bytewidth, unsigned char filterType) +{ + size_t i; + switch(filterType) { + case 0: /*None*/ + for(i = 0; i != length; ++i) out[i] = scanline[i]; + break; + case 1: /*Sub*/ + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth]; + break; + case 2: /*Up*/ + if(prevline) { + for(i = 0; i != length; ++i) out[i] = scanline[i] - prevline[i]; + } + else { + for(i = 0; i != length; ++i) out[i] = scanline[i]; + } + break; + case 3: /*Average*/ + if(prevline) { + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - (prevline[i] >> 1); + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) >> 1); + } + else { + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - (scanline[i - bytewidth] >> 1); + } + break; + case 4: /*Paeth*/ + if(prevline) { + /*paethPredictor(0, prevline[i], 0) is always prevline[i]*/ + for(i = 0; i != bytewidth; ++i) out[i] = (scanline[i] - prevline[i]); + for(i = bytewidth; i < length; ++i) { + out[i] = (scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth])); + } + } + else { + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; + /*paethPredictor(scanline[i - bytewidth], 0, 0) is always scanline[i - bytewidth]*/ + for(i = bytewidth; i < length; ++i) out[i] = (scanline[i] - scanline[i - bytewidth]); + } + break; + default: + return; /*invalid filter type given*/ + } +} + +/* integer binary logarithm, max return value is 31 */ +static size_t ilog2(size_t i) +{ + size_t result = 0; + if(i >= 65536) { + result += 16; + i >>= 16; + } + if(i >= 256) { + result += 8; + i >>= 8; + } + if(i >= 16) { + result += 4; + i >>= 4; + } + if(i >= 4) { + result += 2; + i >>= 2; + } + if(i >= 2) { + result += 1; /*i >>= 1;*/ + } + return result; +} + +/* integer approximation for i * log2(i), helper function for LFS_ENTROPY */ +static size_t ilog2i(size_t i) +{ + size_t l; + if(i == 0) return 0; + l = ilog2(i); + /* approximate i*log2(i): l is integer logarithm, ((i - (1u << l)) << 1u) + linearly approximates the missing fractional part multiplied by i */ + return i * l + ((i - (1u << l)) << 1u); +} + +static unsigned filter(unsigned char * out, const unsigned char * in, unsigned w, unsigned h, + const LodePNGColorMode * color, const LodePNGEncoderSettings * settings) +{ + /* + For PNG filter method 0 + out must be a buffer with as size: h + (w * h * bpp + 7u) / 8u, because there are + the scanlines with 1 extra byte per scanline + */ + + unsigned bpp = lodepng_get_bpp(color); + /*the width of a scanline in bytes, not including the filter type*/ + size_t linebytes = lodepng_get_raw_size_idat(w, 1, bpp) - 1u; + + /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ + size_t bytewidth = (bpp + 7u) / 8u; + const unsigned char * prevline = 0; + unsigned x, y; + unsigned error = 0; + LodePNGFilterStrategy strategy = settings->filter_strategy; + + /* + There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard: + * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e. + use fixed filtering, with the filter None). + * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is + not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply + all five filters and select the filter that produces the smallest sum of absolute values per row. + This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true. + + If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed, + but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum + heuristic is used. + */ + if(settings->filter_palette_zero && + (color->colortype == LCT_PALETTE || color->bitdepth < 8)) strategy = LFS_ZERO; + + if(bpp == 0) return 31; /*error: invalid color type*/ + + if(strategy >= LFS_ZERO && strategy <= LFS_FOUR) { + unsigned char type = (unsigned char)strategy; + for(y = 0; y != h; ++y) { + size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ + size_t inindex = linebytes * y; + out[outindex] = type; /*filter type byte*/ + filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type); + prevline = &in[inindex]; + } + } + else if(strategy == LFS_MINSUM) { + /*adaptive filtering*/ + unsigned char * attempt[5]; /*five filtering attempts, one for each filter type*/ + size_t smallest = 0; + unsigned char type, bestType = 0; + + for(type = 0; type != 5; ++type) { + attempt[type] = (unsigned char *)lodepng_malloc(linebytes); + if(!attempt[type]) error = 83; /*alloc fail*/ + } + + if(!error) { + for(y = 0; y != h; ++y) { + /*try the 5 filter types*/ + for(type = 0; type != 5; ++type) { + size_t sum = 0; + filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); + + /*calculate the sum of the result*/ + if(type == 0) { + for(x = 0; x != linebytes; ++x) sum += (unsigned char)(attempt[type][x]); + } + else { + for(x = 0; x != linebytes; ++x) { + /*For differences, each byte should be treated as signed, values above 127 are negative + (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there. + This means filtertype 0 is almost never chosen, but that is justified.*/ + unsigned char s = attempt[type][x]; + sum += s < 128 ? s : (255U - s); + } + } + + /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ + if(type == 0 || sum < smallest) { + bestType = type; + smallest = sum; + } + } + + prevline = &in[y * linebytes]; + + /*now fill the out values*/ + out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; + } + } + + for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); + } + else if(strategy == LFS_ENTROPY) { + unsigned char * attempt[5]; /*five filtering attempts, one for each filter type*/ + size_t bestSum = 0; + unsigned type, bestType = 0; + unsigned count[256]; + + for(type = 0; type != 5; ++type) { + attempt[type] = (unsigned char *)lodepng_malloc(linebytes); + if(!attempt[type]) error = 83; /*alloc fail*/ + } + + if(!error) { + for(y = 0; y != h; ++y) { + /*try the 5 filter types*/ + for(type = 0; type != 5; ++type) { + size_t sum = 0; + filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); + lodepng_memset(count, 0, 256 * sizeof(*count)); + for(x = 0; x != linebytes; ++x) ++count[attempt[type][x]]; + ++count[type]; /*the filter type itself is part of the scanline*/ + for(x = 0; x != 256; ++x) { + sum += ilog2i(count[x]); + } + /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ + if(type == 0 || sum > bestSum) { + bestType = type; + bestSum = sum; + } + } + + prevline = &in[y * linebytes]; + + /*now fill the out values*/ + out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; + } + } + + for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); + } + else if(strategy == LFS_PREDEFINED) { + for(y = 0; y != h; ++y) { + size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ + size_t inindex = linebytes * y; + unsigned char type = settings->predefined_filters[y]; + out[outindex] = type; /*filter type byte*/ + filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type); + prevline = &in[inindex]; + } + } + else if(strategy == LFS_BRUTE_FORCE) { + /*brute force filter chooser. + deflate the scanline after every filter attempt to see which one deflates best. + This is very slow and gives only slightly smaller, sometimes even larger, result*/ + size_t size[5]; + unsigned char * attempt[5]; /*five filtering attempts, one for each filter type*/ + size_t smallest = 0; + unsigned type = 0, bestType = 0; + unsigned char * dummy; + LodePNGCompressSettings zlibsettings; + lodepng_memcpy(&zlibsettings, &settings->zlibsettings, sizeof(LodePNGCompressSettings)); + /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose, + to simulate the true case where the tree is the same for the whole image. Sometimes it gives + better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare + cases better compression. It does make this a bit less slow, so it's worth doing this.*/ + zlibsettings.btype = 1; + /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG + images only, so disable it*/ + zlibsettings.custom_zlib = 0; + zlibsettings.custom_deflate = 0; + for(type = 0; type != 5; ++type) { + attempt[type] = (unsigned char *)lodepng_malloc(linebytes); + if(!attempt[type]) error = 83; /*alloc fail*/ + } + if(!error) { + for(y = 0; y != h; ++y) { /*try the 5 filter types*/ + for(type = 0; type != 5; ++type) { + unsigned testsize = (unsigned)linebytes; + /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/ + + filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); + size[type] = 0; + dummy = 0; + zlib_compress(&dummy, &size[type], attempt[type], testsize, &zlibsettings); + lodepng_free(dummy); + /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/ + if(type == 0 || size[type] < smallest) { + bestType = type; + smallest = size[type]; + } + } + prevline = &in[y * linebytes]; + out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; + } + } + for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); + } + else return 88; /* unknown filter strategy */ + + return error; +} + +static void addPaddingBits(unsigned char * out, const unsigned char * in, + size_t olinebits, size_t ilinebits, unsigned h) +{ + /*The opposite of the removePaddingBits function + olinebits must be >= ilinebits*/ + unsigned y; + size_t diff = olinebits - ilinebits; + size_t obp = 0, ibp = 0; /*bit pointers*/ + for(y = 0; y != h; ++y) { + size_t x; + for(x = 0; x < ilinebits; ++x) { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + /*obp += diff; --> no, fill in some value in the padding bits too, to avoid + "Use of uninitialised value of size ###" warning from valgrind*/ + for(x = 0; x != diff; ++x) setBitOfReversedStream(&obp, out, 0); + } +} + +/* +in: non-interlaced image with size w*h +out: the same pixels, but re-ordered according to PNG's Adam7 interlacing, with + no padding bits between scanlines, but between reduced images so that each + reduced image starts at a byte. +bpp: bits per pixel +there are no padding bits, not between scanlines, not between reduced images +in has the following size in bits: w * h * bpp. +out is possibly bigger due to padding bits between reduced images +NOTE: comments about padding bits are only relevant if bpp < 8 +*/ +static void Adam7_interlace(unsigned char * out, const unsigned char * in, unsigned w, unsigned h, unsigned bpp) +{ + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned i; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + if(bpp >= 8) { + for(i = 0; i != 7; ++i) { + unsigned x, y, b; + size_t bytewidth = bpp / 8u; + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) { + size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; + size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth; + for(b = 0; b < bytewidth; ++b) { + out[pixeloutstart + b] = in[pixelinstart + b]; + } + } + } + } + else { /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ + for(i = 0; i != 7; ++i) { + unsigned x, y, b; + unsigned ilinebits = bpp * passw[i]; + unsigned olinebits = bpp * w; + size_t obp, ibp; /*bit pointers (for out and in buffer)*/ + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) { + ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; + obp = (8 * passstart[i]) + (y * ilinebits + x * bpp); + for(b = 0; b < bpp; ++b) { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + } + } + } +} + +/*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image. +return value is error**/ +static unsigned preProcessScanlines(unsigned char ** out, size_t * outsize, const unsigned char * in, + unsigned w, unsigned h, + const LodePNGInfo * info_png, const LodePNGEncoderSettings * settings) +{ + /* + This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps: + *) if no Adam7: 1) add padding bits (= possible extra bits per scanline if bpp < 8) 2) filter + *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter + */ + unsigned bpp = lodepng_get_bpp(&info_png->color); + unsigned error = 0; + + if(info_png->interlace_method == 0) { + *outsize = h + (h * ((w * bpp + 7u) / 8u)); /*image size plus an extra byte per scanline + possible padding bits*/ + *out = (unsigned char *)lodepng_malloc(*outsize); + if(!(*out) && (*outsize)) error = 83; /*alloc fail*/ + + if(!error) { + /*non multiple of 8 bits per scanline, padding bits needed per scanline*/ + if(bpp < 8 && w * bpp != ((w * bpp + 7u) / 8u) * 8u) { + unsigned char * padded = (unsigned char *)lodepng_malloc(h * ((w * bpp + 7u) / 8u)); + if(!padded) error = 83; /*alloc fail*/ + if(!error) { + addPaddingBits(padded, in, ((w * bpp + 7u) / 8u) * 8u, w * bpp, h); + error = filter(*out, padded, w, h, &info_png->color, settings); + } + lodepng_free(padded); + } + else { + /*we can immediately filter into the out buffer, no other steps needed*/ + error = filter(*out, in, w, h, &info_png->color, settings); + } + } + } + else { /*interlace_method is 1 (Adam7)*/ + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned char * adam7; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/ + *out = (unsigned char *)lodepng_malloc(*outsize); + if(!(*out)) error = 83; /*alloc fail*/ + + adam7 = (unsigned char *)lodepng_malloc(passstart[7]); + if(!adam7 && passstart[7]) error = 83; /*alloc fail*/ + + if(!error && adam7) { + unsigned i; + + Adam7_interlace(adam7, in, w, h, bpp); + for(i = 0; i != 7; ++i) { + if(bpp < 8) { + unsigned char * padded = (unsigned char *)lodepng_malloc(padded_passstart[i + 1] - padded_passstart[i]); + if(!padded) ERROR_BREAK(83); /*alloc fail*/ + addPaddingBits(padded, &adam7[passstart[i]], + ((passw[i] * bpp + 7u) / 8u) * 8u, passw[i] * bpp, passh[i]); + error = filter(&(*out)[filter_passstart[i]], padded, + passw[i], passh[i], &info_png->color, settings); + lodepng_free(padded); + } + else { + error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]], + passw[i], passh[i], &info_png->color, settings); + } + + if(error) break; + } + } + + lodepng_free(adam7); + } + + return error; +} + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +static unsigned addUnknownChunks(ucvector * out, unsigned char * data, size_t datasize) +{ + unsigned char * inchunk = data; + while((size_t)(inchunk - data) < datasize) { + CERROR_TRY_RETURN(lodepng_chunk_append(&out->data, &out->size, inchunk)); + out->allocsize = out->size; /*fix the allocsize again*/ + inchunk = lodepng_chunk_next(inchunk, data + datasize); + } + return 0; +} + +static unsigned isGrayICCProfile(const unsigned char * profile, unsigned size) +{ + /* + It is a gray profile if bytes 16-19 are "GRAY", rgb profile if bytes 16-19 + are "RGB ". We do not perform any full parsing of the ICC profile here, other + than check those 4 bytes to grayscale profile. Other than that, validity of + the profile is not checked. This is needed only because the PNG specification + requires using a non-gray color model if there is an ICC profile with "RGB " + (sadly limiting compression opportunities if the input data is grayscale RGB + data), and requires using a gray color model if it is "GRAY". + */ + if(size < 20) return 0; + return profile[16] == 'G' && profile[17] == 'R' && profile[18] == 'A' && profile[19] == 'Y'; +} + +static unsigned isRGBICCProfile(const unsigned char * profile, unsigned size) +{ + /* See comment in isGrayICCProfile*/ + if(size < 20) return 0; + return profile[16] == 'R' && profile[17] == 'G' && profile[18] == 'B' && profile[19] == ' '; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +unsigned lodepng_encode(unsigned char ** out, size_t * outsize, + const unsigned char * image, unsigned w, unsigned h, + LodePNGState * state) +{ + unsigned char * data = 0; /*uncompressed version of the IDAT chunk data*/ + size_t datasize = 0; + ucvector outv = ucvector_init(NULL, 0); + LodePNGInfo info; + const LodePNGInfo * info_png = &state->info_png; + + lodepng_info_init(&info); + + /*provide some proper output values if error will happen*/ + *out = 0; + *outsize = 0; + state->error = 0; + + /*check input values validity*/ + if((info_png->color.colortype == LCT_PALETTE || state->encoder.force_palette) + && (info_png->color.palettesize == 0 || info_png->color.palettesize > 256)) { + state->error = 68; /*invalid palette size, it is only allowed to be 1-256*/ + goto cleanup; + } + if(state->encoder.zlibsettings.btype > 2) { + state->error = 61; /*error: invalid btype*/ + goto cleanup; + } + if(info_png->interlace_method > 1) { + state->error = 71; /*error: invalid interlace mode*/ + goto cleanup; + } + state->error = checkColorValidity(info_png->color.colortype, info_png->color.bitdepth); + if(state->error) goto cleanup; /*error: invalid color type given*/ + state->error = checkColorValidity(state->info_raw.colortype, state->info_raw.bitdepth); + if(state->error) goto cleanup; /*error: invalid color type given*/ + + /* color convert and compute scanline filter types */ + lodepng_info_copy(&info, &state->info_png); + if(state->encoder.auto_convert) { + LodePNGColorStats stats; + lodepng_color_stats_init(&stats); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(info_png->iccp_defined && + isGrayICCProfile(info_png->iccp_profile, info_png->iccp_profile_size)) { + /*the PNG specification does not allow to use palette with a GRAY ICC profile, even + if the palette has only gray colors, so disallow it.*/ + stats.allow_palette = 0; + } + if(info_png->iccp_defined && + isRGBICCProfile(info_png->iccp_profile, info_png->iccp_profile_size)) { + /*the PNG specification does not allow to use grayscale color with RGB ICC profile, so disallow gray.*/ + stats.allow_greyscale = 0; + } +#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ + state->error = lodepng_compute_color_stats(&stats, image, w, h, &state->info_raw); + if(state->error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(info_png->background_defined) { + /*the background chunk's color must be taken into account as well*/ + unsigned r = 0, g = 0, b = 0; + LodePNGColorMode mode16 = lodepng_color_mode_make(LCT_RGB, 16); + lodepng_convert_rgb(&r, &g, &b, info_png->background_r, info_png->background_g, info_png->background_b, &mode16, + &info_png->color); + state->error = lodepng_color_stats_add(&stats, r, g, b, 65535); + if(state->error) goto cleanup; + } +#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ + state->error = auto_choose_color(&info.color, &state->info_raw, &stats); + if(state->error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*also convert the background chunk*/ + if(info_png->background_defined) { + if(lodepng_convert_rgb(&info.background_r, &info.background_g, &info.background_b, + info_png->background_r, info_png->background_g, info_png->background_b, &info.color, &info_png->color)) { + state->error = 104; + goto cleanup; + } + } +#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ + } +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(info_png->iccp_defined) { + unsigned gray_icc = isGrayICCProfile(info_png->iccp_profile, info_png->iccp_profile_size); + unsigned rgb_icc = isRGBICCProfile(info_png->iccp_profile, info_png->iccp_profile_size); + unsigned gray_png = info.color.colortype == LCT_GREY || info.color.colortype == LCT_GREY_ALPHA; + if(!gray_icc && !rgb_icc) { + state->error = 100; /* Disallowed profile color type for PNG */ + goto cleanup; + } + if(gray_icc != gray_png) { + /*Not allowed to use RGB/RGBA/palette with GRAY ICC profile or vice versa, + or in case of auto_convert, it wasn't possible to find appropriate model*/ + state->error = state->encoder.auto_convert ? 102 : 101; + goto cleanup; + } + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + if(!lodepng_color_mode_equal(&state->info_raw, &info.color)) { + unsigned char * converted; + size_t size = ((size_t)w * (size_t)h * (size_t)lodepng_get_bpp(&info.color) + 7u) / 8u; + + converted = (unsigned char *)lodepng_malloc(size); + if(!converted && size) state->error = 83; /*alloc fail*/ + if(!state->error) { + state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h); + } + if(!state->error) { + state->error = preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder); + } + lodepng_free(converted); + if(state->error) goto cleanup; + } + else { + state->error = preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder); + if(state->error) goto cleanup; + } + + /* output all PNG chunks */ { +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + size_t i; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + /*write signature and chunks*/ + state->error = writeSignature(&outv); + if(state->error) goto cleanup; + /*IHDR*/ + state->error = addChunk_IHDR(&outv, w, h, info.color.colortype, info.color.bitdepth, info.interlace_method); + if(state->error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*unknown chunks between IHDR and PLTE*/ + if(info.unknown_chunks_data[0]) { + state->error = addUnknownChunks(&outv, info.unknown_chunks_data[0], info.unknown_chunks_size[0]); + if(state->error) goto cleanup; + } + /*color profile chunks must come before PLTE */ + if(info.iccp_defined) { + state->error = addChunk_iCCP(&outv, &info, &state->encoder.zlibsettings); + if(state->error) goto cleanup; + } + if(info.srgb_defined) { + state->error = addChunk_sRGB(&outv, &info); + if(state->error) goto cleanup; + } + if(info.gama_defined) { + state->error = addChunk_gAMA(&outv, &info); + if(state->error) goto cleanup; + } + if(info.chrm_defined) { + state->error = addChunk_cHRM(&outv, &info); + if(state->error) goto cleanup; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + /*PLTE*/ + if(info.color.colortype == LCT_PALETTE) { + state->error = addChunk_PLTE(&outv, &info.color); + if(state->error) goto cleanup; + } + if(state->encoder.force_palette && (info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA)) { + /*force_palette means: write suggested palette for truecolor in PLTE chunk*/ + state->error = addChunk_PLTE(&outv, &info.color); + if(state->error) goto cleanup; + } + /*tRNS (this will only add if when necessary) */ + state->error = addChunk_tRNS(&outv, &info.color); + if(state->error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*bKGD (must come between PLTE and the IDAt chunks*/ + if(info.background_defined) { + state->error = addChunk_bKGD(&outv, &info); + if(state->error) goto cleanup; + } + /*pHYs (must come before the IDAT chunks)*/ + if(info.phys_defined) { + state->error = addChunk_pHYs(&outv, &info); + if(state->error) goto cleanup; + } + + /*unknown chunks between PLTE and IDAT*/ + if(info.unknown_chunks_data[1]) { + state->error = addUnknownChunks(&outv, info.unknown_chunks_data[1], info.unknown_chunks_size[1]); + if(state->error) goto cleanup; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + /*IDAT (multiple IDAT chunks must be consecutive)*/ + state->error = addChunk_IDAT(&outv, data, datasize, &state->encoder.zlibsettings); + if(state->error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*tIME*/ + if(info.time_defined) { + state->error = addChunk_tIME(&outv, &info.time); + if(state->error) goto cleanup; + } + /*tEXt and/or zTXt*/ + for(i = 0; i != info.text_num; ++i) { + if(lodepng_strlen(info.text_keys[i]) > 79) { + state->error = 66; /*text chunk too large*/ + goto cleanup; + } + if(lodepng_strlen(info.text_keys[i]) < 1) { + state->error = 67; /*text chunk too small*/ + goto cleanup; + } + if(state->encoder.text_compression) { + state->error = addChunk_zTXt(&outv, info.text_keys[i], info.text_strings[i], &state->encoder.zlibsettings); + if(state->error) goto cleanup; + } + else { + state->error = addChunk_tEXt(&outv, info.text_keys[i], info.text_strings[i]); + if(state->error) goto cleanup; + } + } + /*LodePNG version id in text chunk*/ + if(state->encoder.add_id) { + unsigned already_added_id_text = 0; + for(i = 0; i != info.text_num; ++i) { + const char * k = info.text_keys[i]; + /* Could use strcmp, but we're not calling or reimplementing this C library function for this use only */ + if(k[0] == 'L' && k[1] == 'o' && k[2] == 'd' && k[3] == 'e' && + k[4] == 'P' && k[5] == 'N' && k[6] == 'G' && k[7] == '\0') { + already_added_id_text = 1; + break; + } + } + if(already_added_id_text == 0) { + state->error = addChunk_tEXt(&outv, "LodePNG", LODEPNG_VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/ + if(state->error) goto cleanup; + } + } + /*iTXt*/ + for(i = 0; i != info.itext_num; ++i) { + if(lodepng_strlen(info.itext_keys[i]) > 79) { + state->error = 66; /*text chunk too large*/ + goto cleanup; + } + if(lodepng_strlen(info.itext_keys[i]) < 1) { + state->error = 67; /*text chunk too small*/ + goto cleanup; + } + state->error = addChunk_iTXt( + &outv, state->encoder.text_compression, + info.itext_keys[i], info.itext_langtags[i], info.itext_transkeys[i], info.itext_strings[i], + &state->encoder.zlibsettings); + if(state->error) goto cleanup; + } + + /*unknown chunks between IDAT and IEND*/ + if(info.unknown_chunks_data[2]) { + state->error = addUnknownChunks(&outv, info.unknown_chunks_data[2], info.unknown_chunks_size[2]); + if(state->error) goto cleanup; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + state->error = addChunk_IEND(&outv); + if(state->error) goto cleanup; + } + +cleanup: + lodepng_info_cleanup(&info); + lodepng_free(data); + + /*instead of cleaning the vector up, give it to the output*/ + *out = outv.data; + *outsize = outv.size; + + return state->error; +} + +unsigned lodepng_encode_memory(unsigned char ** out, size_t * outsize, const unsigned char * image, + unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned error; + LodePNGState state; + lodepng_state_init(&state); + state.info_raw.colortype = colortype; + state.info_raw.bitdepth = bitdepth; + state.info_png.color.colortype = colortype; + state.info_png.color.bitdepth = bitdepth; + lodepng_encode(out, outsize, image, w, h, &state); + error = state.error; + lodepng_state_cleanup(&state); + return error; +} + +unsigned lodepng_encode32(unsigned char ** out, size_t * outsize, const unsigned char * image, unsigned w, unsigned h) +{ + return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGBA, 8); +} + +unsigned lodepng_encode24(unsigned char ** out, size_t * outsize, const unsigned char * image, unsigned w, unsigned h) +{ + return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGB, 8); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned lodepng_encode_file(const char * filename, const unsigned char * image, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned char * buffer; + size_t buffersize; + unsigned error = lodepng_encode_memory(&buffer, &buffersize, image, w, h, colortype, bitdepth); + if(!error) error = lodepng_save_file(buffer, buffersize, filename); + lodepng_free(buffer); + return error; +} + +unsigned lodepng_encode32_file(const char * filename, const unsigned char * image, unsigned w, unsigned h) +{ + return lodepng_encode_file(filename, image, w, h, LCT_RGBA, 8); +} + +unsigned lodepng_encode24_file(const char * filename, const unsigned char * image, unsigned w, unsigned h) +{ + return lodepng_encode_file(filename, image, w, h, LCT_RGB, 8); +} +#endif /*LODEPNG_COMPILE_DISK*/ + +void lodepng_encoder_settings_init(LodePNGEncoderSettings * settings) +{ + lodepng_compress_settings_init(&settings->zlibsettings); + settings->filter_palette_zero = 1; + settings->filter_strategy = LFS_MINSUM; + settings->auto_convert = 1; + settings->force_palette = 0; + settings->predefined_filters = 0; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + settings->add_id = 0; + settings->text_compression = 1; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} + +#endif /*LODEPNG_COMPILE_ENCODER*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ERROR_TEXT +/* +This returns the description of a numerical error code in English. This is also +the documentation of all the error codes. +*/ +const char * lodepng_error_text(unsigned code) +{ + switch(code) { + case 0: + return "no error, everything went ok"; + case 1: + return "nothing done yet"; /*the Encoder/Decoder has done nothing yet, error checking makes no sense yet*/ + case 10: + return "end of input memory reached without huffman end code"; /*while huffman decoding*/ + case 11: + return "error in code tree made it jump outside of huffman tree"; /*while huffman decoding*/ + case 13: + return "problem while processing dynamic deflate block"; + case 14: + return "problem while processing dynamic deflate block"; + case 15: + return "problem while processing dynamic deflate block"; + /*this error could happen if there are only 0 or 1 symbols present in the huffman code:*/ + case 16: + return "invalid code while processing dynamic deflate block"; + case 17: + return "end of out buffer memory reached while inflating"; + case 18: + return "invalid distance code while inflating"; + case 19: + return "end of out buffer memory reached while inflating"; + case 20: + return "invalid deflate block BTYPE encountered while decoding"; + case 21: + return "NLEN is not ones complement of LEN in a deflate block"; + + /*end of out buffer memory reached while inflating: + This can happen if the inflated deflate data is longer than the amount of bytes required to fill up + all the pixels of the image, given the color depth and image dimensions. Something that doesn't + happen in a normal, well encoded, PNG image.*/ + case 22: + return "end of out buffer memory reached while inflating"; + case 23: + return "end of in buffer memory reached while inflating"; + case 24: + return "invalid FCHECK in zlib header"; + case 25: + return "invalid compression method in zlib header"; + case 26: + return "FDICT encountered in zlib header while it's not used for PNG"; + case 27: + return "PNG file is smaller than a PNG header"; + /*Checks the magic file header, the first 8 bytes of the PNG file*/ + case 28: + return "incorrect PNG signature, it's no PNG or corrupted"; + case 29: + return "first chunk is not the header chunk"; + case 30: + return "chunk length too large, chunk broken off at end of file"; + case 31: + return "illegal PNG color type or bpp"; + case 32: + return "illegal PNG compression method"; + case 33: + return "illegal PNG filter method"; + case 34: + return "illegal PNG interlace method"; + case 35: + return "chunk length of a chunk is too large or the chunk too small"; + case 36: + return "illegal PNG filter type encountered"; + case 37: + return "illegal bit depth for this color type given"; + case 38: + return "the palette is too small or too big"; /*0, or more than 256 colors*/ + case 39: + return "tRNS chunk before PLTE or has more entries than palette size"; + case 40: + return "tRNS chunk has wrong size for grayscale image"; + case 41: + return "tRNS chunk has wrong size for RGB image"; + case 42: + return "tRNS chunk appeared while it was not allowed for this color type"; + case 43: + return "bKGD chunk has wrong size for palette image"; + case 44: + return "bKGD chunk has wrong size for grayscale image"; + case 45: + return "bKGD chunk has wrong size for RGB image"; + case 48: + return "empty input buffer given to decoder. Maybe caused by non-existing file?"; + case 49: + return "jumped past memory while generating dynamic huffman tree"; + case 50: + return "jumped past memory while generating dynamic huffman tree"; + case 51: + return "jumped past memory while inflating huffman block"; + case 52: + return "jumped past memory while inflating"; + case 53: + return "size of zlib data too small"; + case 54: + return "repeat symbol in tree while there was no value symbol yet"; + /*jumped past tree while generating huffman tree, this could be when the + tree will have more leaves than symbols after generating it out of the + given lengths. They call this an oversubscribed dynamic bit lengths tree in zlib.*/ + case 55: + return "jumped past tree while generating huffman tree"; + case 56: + return "given output image colortype or bitdepth not supported for color conversion"; + case 57: + return "invalid CRC encountered (checking CRC can be disabled)"; + case 58: + return "invalid ADLER32 encountered (checking ADLER32 can be disabled)"; + case 59: + return "requested color conversion not supported"; + case 60: + return "invalid window size given in the settings of the encoder (must be 0-32768)"; + case 61: + return "invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)"; + /*LodePNG leaves the choice of RGB to grayscale conversion formula to the user.*/ + case 62: + return "conversion from color to grayscale not supported"; + /*(2^31-1)*/ + case 63: + return "length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk"; + /*this would result in the inability of a deflated block to ever contain an end code. It must be at least 1.*/ + case 64: + return "the length of the END symbol 256 in the Huffman tree is 0"; + case 66: + return "the length of a text chunk keyword given to the encoder is longer than the maximum of 79 bytes"; + case 67: + return "the length of a text chunk keyword given to the encoder is smaller than the minimum of 1 byte"; + case 68: + return "tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors"; + case 69: + return "unknown chunk type with 'critical' flag encountered by the decoder"; + case 71: + return "invalid interlace mode given to encoder (must be 0 or 1)"; + case 72: + return "while decoding, invalid compression method encountering in zTXt or iTXt chunk (it must be 0)"; + case 73: + return "invalid tIME chunk size"; + case 74: + return "invalid pHYs chunk size"; + /*length could be wrong, or data chopped off*/ + case 75: + return "no null termination char found while decoding text chunk"; + case 76: + return "iTXt chunk too short to contain required bytes"; + case 77: + return "integer overflow in buffer size"; + case 78: + return "failed to open file for reading"; /*file doesn't exist or couldn't be opened for reading*/ + case 79: + return "failed to open file for writing"; + case 80: + return "tried creating a tree of 0 symbols"; + case 81: + return "lazy matching at pos 0 is impossible"; + case 82: + return "color conversion to palette requested while a color isn't in palette, or index out of bounds"; + case 83: + return "memory allocation failed"; + case 84: + return "given image too small to contain all pixels to be encoded"; + case 86: + return "impossible offset in lz77 encoding (internal bug)"; + case 87: + return "must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined"; + case 88: + return "invalid filter strategy given for LodePNGEncoderSettings.filter_strategy"; + case 89: + return "text chunk keyword too short or long: must have size 1-79"; + /*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/ + case 90: + return "windowsize must be a power of two"; + case 91: + return "invalid decompressed idat size"; + case 92: + return "integer overflow due to too many pixels"; + case 93: + return "zero width or height is invalid"; + case 94: + return "header chunk must have a size of 13 bytes"; + case 95: + return "integer overflow with combined idat chunk size"; + case 96: + return "invalid gAMA chunk size"; + case 97: + return "invalid cHRM chunk size"; + case 98: + return "invalid sRGB chunk size"; + case 99: + return "invalid sRGB rendering intent"; + case 100: + return "invalid ICC profile color type, the PNG specification only allows RGB or GRAY"; + case 101: + return "PNG specification does not allow RGB ICC profile on gray color types and vice versa"; + case 102: + return "not allowed to set grayscale ICC profile with colored pixels by PNG specification"; + case 103: + return "invalid palette index in bKGD chunk. Maybe it came before PLTE chunk?"; + case 104: + return "invalid bKGD color while encoding (e.g. palette index out of range)"; + case 105: + return "integer overflow of bitsize"; + case 106: + return "PNG file must have PLTE chunk if color type is palette"; + case 107: + return "color convert from palette mode requested without setting the palette data in it"; + case 108: + return "tried to add more than 256 values to a palette"; + /*this limit can be configured in LodePNGDecompressSettings*/ + case 109: + return "tried to decompress zlib or deflate data larger than desired max_output_size"; + case 110: + return "custom zlib or inflate decompression failed"; + case 111: + return "custom zlib or deflate compression failed"; + /*max text size limit can be configured in LodePNGDecoderSettings. This error prevents + unreasonable memory consumption when decoding due to impossibly large text sizes.*/ + case 112: + return "compressed text unreasonably large"; + /*max ICC size limit can be configured in LodePNGDecoderSettings. This error prevents + unreasonable memory consumption when decoding due to impossibly large ICC profile*/ + case 113: + return "ICC profile unreasonably large"; + } + return "unknown error code"; +} +#endif /*LODEPNG_COMPILE_ERROR_TEXT*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // C++ Wrapper // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_CPP +namespace lodepng +{ + +#ifdef LODEPNG_COMPILE_DISK +unsigned load_file(std::vector & buffer, const std::string & filename) +{ + long size = lodepng_filesize(filename.c_str()); + if(size < 0) return 78; + buffer.resize((size_t)size); + return size == 0 ? 0 : lodepng_buffer_file(&buffer[0], (size_t)size, filename.c_str()); +} + +/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ +unsigned save_file(const std::vector & buffer, const std::string & filename) +{ + return lodepng_save_file(buffer.empty() ? 0 : &buffer[0], buffer.size(), filename.c_str()); +} +#endif /* LODEPNG_COMPILE_DISK */ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_DECODER +unsigned decompress(std::vector & out, const unsigned char * in, size_t insize, + const LodePNGDecompressSettings & settings) +{ + unsigned char * buffer = 0; + size_t buffersize = 0; + unsigned error = zlib_decompress(&buffer, &buffersize, 0, in, insize, &settings); + if(buffer) { + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned decompress(std::vector & out, const std::vector & in, + const LodePNGDecompressSettings & settings) +{ + return decompress(out, in.empty() ? 0 : &in[0], in.size(), settings); +} +#endif /* LODEPNG_COMPILE_DECODER */ + +#ifdef LODEPNG_COMPILE_ENCODER +unsigned compress(std::vector & out, const unsigned char * in, size_t insize, + const LodePNGCompressSettings & settings) +{ + unsigned char * buffer = 0; + size_t buffersize = 0; + unsigned error = zlib_compress(&buffer, &buffersize, in, insize, &settings); + if(buffer) { + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned compress(std::vector & out, const std::vector & in, + const LodePNGCompressSettings & settings) +{ + return compress(out, in.empty() ? 0 : &in[0], in.size(), settings); +} +#endif /* LODEPNG_COMPILE_ENCODER */ +#endif /* LODEPNG_COMPILE_ZLIB */ + + +#ifdef LODEPNG_COMPILE_PNG + +State::State() +{ + lodepng_state_init(this); +} + +State::State(const State & other) +{ + lodepng_state_init(this); + lodepng_state_copy(this, &other); +} + +State::~State() +{ + lodepng_state_cleanup(this); +} + +State & State::operator=(const State & other) +{ + lodepng_state_copy(this, &other); + return *this; +} + +#ifdef LODEPNG_COMPILE_DECODER + +unsigned decode(std::vector & out, unsigned & w, unsigned & h, const unsigned char * in, + size_t insize, LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned char * buffer = 0; + unsigned error = lodepng_decode_memory(&buffer, &w, &h, in, insize, colortype, bitdepth); + if(buffer && !error) { + State state; + state.info_raw.colortype = colortype; + state.info_raw.bitdepth = bitdepth; + size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + } + lodepng_free(buffer); + return error; +} + +unsigned decode(std::vector & out, unsigned & w, unsigned & h, + const std::vector & in, LodePNGColorType colortype, unsigned bitdepth) +{ + return decode(out, w, h, in.empty() ? 0 : &in[0], (unsigned)in.size(), colortype, bitdepth); +} + +unsigned decode(std::vector & out, unsigned & w, unsigned & h, + State & state, + const unsigned char * in, size_t insize) +{ + unsigned char * buffer = NULL; + unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize); + if(buffer && !error) { + size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + } + lodepng_free(buffer); + return error; +} + +unsigned decode(std::vector & out, unsigned & w, unsigned & h, + State & state, + const std::vector & in) +{ + return decode(out, w, h, state, in.empty() ? 0 : &in[0], in.size()); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned decode(std::vector & out, unsigned & w, unsigned & h, const std::string & filename, + LodePNGColorType colortype, unsigned bitdepth) +{ + std::vector buffer; + /* safe output values in case error happens */ + w = h = 0; + unsigned error = load_file(buffer, filename); + if(error) return error; + return decode(out, w, h, buffer, colortype, bitdepth); +} +#endif /* LODEPNG_COMPILE_DECODER */ +#endif /* LODEPNG_COMPILE_DISK */ + +#ifdef LODEPNG_COMPILE_ENCODER +unsigned encode(std::vector & out, const unsigned char * in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned char * buffer; + size_t buffersize; + unsigned error = lodepng_encode_memory(&buffer, &buffersize, in, w, h, colortype, bitdepth); + if(buffer) { + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned encode(std::vector & out, + const std::vector & in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) +{ + if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; + return encode(out, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); +} + +unsigned encode(std::vector & out, + const unsigned char * in, unsigned w, unsigned h, + State & state) +{ + unsigned char * buffer; + size_t buffersize; + unsigned error = lodepng_encode(&buffer, &buffersize, in, w, h, &state); + if(buffer) { + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned encode(std::vector & out, + const std::vector & in, unsigned w, unsigned h, + State & state) +{ + if(lodepng_get_raw_size(w, h, &state.info_raw) > in.size()) return 84; + return encode(out, in.empty() ? 0 : &in[0], w, h, state); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned encode(const std::string & filename, + const unsigned char * in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) +{ + std::vector buffer; + unsigned error = encode(buffer, in, w, h, colortype, bitdepth); + if(!error) error = save_file(buffer, filename); + return error; +} + +unsigned encode(const std::string & filename, + const std::vector & in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) +{ + if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; + return encode(filename, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); +} +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_ENCODER */ +#endif /* LODEPNG_COMPILE_PNG */ +} /* namespace lodepng */ +#endif /*LODEPNG_COMPILE_CPP*/ + +#endif /*LV_USE_LODEPNG*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.h b/lib/libesp32_lvgl/lvgl/src/libs/lodepng/lodepng.h similarity index 65% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.h rename to lib/libesp32_lvgl/lvgl/src/libs/lodepng/lodepng.h index dbfed72e5..b23c25a68 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/png/lodepng.h +++ b/lib/libesp32_lvgl/lvgl/src/libs/lodepng/lodepng.h @@ -29,8 +29,8 @@ freely, subject to the following restrictions: #include /*for size_t*/ #include "../../../lvgl.h" -#if LV_USE_PNG -extern const char* LODEPNG_VERSION_STRING; +#if LV_USE_LODEPNG +LV_ATTRIBUTE_EXTERN_DATA extern const char * LODEPNG_VERSION_STRING; /* The following #defines are used to create code sections. They can be disabled @@ -44,72 +44,72 @@ allow implementing a custom lodepng_crc32. /*deflate & zlib. If disabled, you must specify alternative zlib functions in the custom_zlib field of the compress and decompress settings*/ #ifndef LODEPNG_NO_COMPILE_ZLIB -#define LODEPNG_COMPILE_ZLIB + #define LODEPNG_COMPILE_ZLIB #endif /*png encoder and png decoder*/ #ifndef LODEPNG_NO_COMPILE_PNG -#define LODEPNG_COMPILE_PNG + #define LODEPNG_COMPILE_PNG #endif /*deflate&zlib decoder and png decoder*/ #ifndef LODEPNG_NO_COMPILE_DECODER -#define LODEPNG_COMPILE_DECODER + #define LODEPNG_COMPILE_DECODER #endif /*deflate&zlib encoder and png encoder*/ #ifndef LODEPNG_NO_COMPILE_ENCODER -#define LODEPNG_COMPILE_ENCODER + #define LODEPNG_COMPILE_ENCODER #endif /*the optional built in harddisk file loading and saving functions*/ #ifndef LODEPNG_NO_COMPILE_DISK -#define LODEPNG_COMPILE_DISK + #define LODEPNG_COMPILE_DISK #endif /*support for chunks other than IHDR, IDAT, PLTE, tRNS, IEND: ancillary and unknown chunks*/ #ifndef LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS -#define LODEPNG_COMPILE_ANCILLARY_CHUNKS + #define LODEPNG_COMPILE_ANCILLARY_CHUNKS #endif /*ability to convert error numerical codes to English text string*/ #ifndef LODEPNG_NO_COMPILE_ERROR_TEXT -#define LODEPNG_COMPILE_ERROR_TEXT + #define LODEPNG_COMPILE_ERROR_TEXT #endif /*Compile the default allocators (C's free, malloc and realloc). If you disable this, you can define the functions lodepng_free, lodepng_malloc and lodepng_realloc in your source files with custom allocators.*/ #ifndef LODEPNG_NO_COMPILE_ALLOCATORS -#define LODEPNG_COMPILE_ALLOCATORS + #define LODEPNG_COMPILE_ALLOCATORS #endif /*compile the C++ version (you can disable the C++ wrapper here even when compiling for C++)*/ #ifdef __cplusplus -#ifndef LODEPNG_NO_COMPILE_CPP -#define LODEPNG_COMPILE_CPP -#endif + #ifndef LODEPNG_NO_COMPILE_CPP + #define LODEPNG_COMPILE_CPP + #endif #endif #ifdef LODEPNG_COMPILE_CPP -#include -#include + #include + #include #endif /*LODEPNG_COMPILE_CPP*/ #ifdef LODEPNG_COMPILE_PNG /*The PNG color types (also used for raw image).*/ -typedef enum LodePNGColorType { - LCT_GREY = 0, /*grayscale: 1,2,4,8,16 bit*/ - LCT_RGB = 2, /*RGB: 8,16 bit*/ - LCT_PALETTE = 3, /*palette: 1,2,4,8 bit*/ - LCT_GREY_ALPHA = 4, /*grayscale with alpha: 8,16 bit*/ - LCT_RGBA = 6, /*RGB with alpha: 8,16 bit*/ - /*LCT_MAX_OCTET_VALUE lets the compiler allow this enum to represent any invalid - byte value from 0 to 255 that could be present in an invalid PNG file header. Do - not use, compare with or set the name LCT_MAX_OCTET_VALUE, instead either use - the valid color type names above, or numeric values like 1 or 7 when checking for - particular disallowed color type byte values, or cast to integer to print it.*/ - LCT_MAX_OCTET_VALUE = 255 +typedef enum _LodePNGColorType { + LCT_GREY = 0, /*grayscale: 1,2,4,8,16 bit*/ + LCT_RGB = 2, /*RGB: 8,16 bit*/ + LCT_PALETTE = 3, /*palette: 1,2,4,8 bit*/ + LCT_GREY_ALPHA = 4, /*grayscale with alpha: 8,16 bit*/ + LCT_RGBA = 6, /*RGB with alpha: 8,16 bit*/ + /*LCT_MAX_OCTET_VALUE lets the compiler allow this enum to represent any invalid + byte value from 0 to 255 that could be present in an invalid PNG file header. Do + not use, compare with or set the name LCT_MAX_OCTET_VALUE, instead either use + the valid color type names above, or numeric values like 1 or 7 when checking for + particular disallowed color type byte values, or cast to integer to print it.*/ + LCT_MAX_OCTET_VALUE = 255 } LodePNGColorType; #ifdef LODEPNG_COMPILE_DECODER @@ -128,34 +128,34 @@ colortype: the desired color type for the raw output image. See explanation on P bitdepth: the desired bit depth for the raw output image. See explanation on PNG color types. Return value: LodePNG error code (0 means no error). */ -unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, - const unsigned char* in, size_t insize, +unsigned lodepng_decode_memory(unsigned char ** out, unsigned * w, unsigned * h, + const unsigned char * in, size_t insize, LodePNGColorType colortype, unsigned bitdepth); /*Same as lodepng_decode_memory, but always decodes to 32-bit RGBA raw image*/ -unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, - const unsigned char* in, size_t insize); +unsigned lodepng_decode32(unsigned char ** out, unsigned * w, unsigned * h, + const unsigned char * in, size_t insize); /*Same as lodepng_decode_memory, but always decodes to 24-bit RGB raw image*/ -unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, - const unsigned char* in, size_t insize); +unsigned lodepng_decode24(unsigned char ** out, unsigned * w, unsigned * h, + const unsigned char * in, size_t insize); #ifdef LODEPNG_COMPILE_DISK /* Load PNG from disk, from file with given name. Same as the other decode functions, but instead takes a filename as input. */ -unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, - const char* filename, +unsigned lodepng_decode_file(unsigned char ** out, unsigned * w, unsigned * h, + const char * filename, LodePNGColorType colortype, unsigned bitdepth); /*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.*/ -unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, - const char* filename); +unsigned lodepng_decode32_file(unsigned char ** out, unsigned * w, unsigned * h, + const char * filename); /*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.*/ -unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, - const char* filename); +unsigned lodepng_decode24_file(unsigned char ** out, unsigned * w, unsigned * h, + const char * filename); #endif /*LODEPNG_COMPILE_DISK*/ #endif /*LODEPNG_COMPILE_DECODER*/ @@ -177,17 +177,17 @@ colortype: the color type of the raw input image. See explanation on PNG color t bitdepth: the bit depth of the raw input image. See explanation on PNG color types. Return value: LodePNG error code (0 means no error). */ -unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, - const unsigned char* image, unsigned w, unsigned h, +unsigned lodepng_encode_memory(unsigned char ** out, size_t * outsize, + const unsigned char * image, unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth); /*Same as lodepng_encode_memory, but always encodes from 32-bit RGBA raw image.*/ -unsigned lodepng_encode32(unsigned char** out, size_t* outsize, - const unsigned char* image, unsigned w, unsigned h); +unsigned lodepng_encode32(unsigned char ** out, size_t * outsize, + const unsigned char * image, unsigned w, unsigned h); /*Same as lodepng_encode_memory, but always encodes from 24-bit RGB raw image.*/ -unsigned lodepng_encode24(unsigned char** out, size_t* outsize, - const unsigned char* image, unsigned w, unsigned h); +unsigned lodepng_encode24(unsigned char ** out, size_t * outsize, + const unsigned char * image, unsigned w, unsigned h); #ifdef LODEPNG_COMPILE_DISK /* @@ -195,39 +195,40 @@ Converts raw pixel data into a PNG file on disk. Same as the other encode functions, but instead takes a filename as output. NOTE: This overwrites existing files without warning! */ -unsigned lodepng_encode_file(const char* filename, - const unsigned char* image, unsigned w, unsigned h, +unsigned lodepng_encode_file(const char * filename, + const unsigned char * image, unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth); /*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.*/ -unsigned lodepng_encode32_file(const char* filename, - const unsigned char* image, unsigned w, unsigned h); +unsigned lodepng_encode32_file(const char * filename, + const unsigned char * image, unsigned w, unsigned h); /*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.*/ -unsigned lodepng_encode24_file(const char* filename, - const unsigned char* image, unsigned w, unsigned h); +unsigned lodepng_encode24_file(const char * filename, + const unsigned char * image, unsigned w, unsigned h); #endif /*LODEPNG_COMPILE_DISK*/ #endif /*LODEPNG_COMPILE_ENCODER*/ #ifdef LODEPNG_COMPILE_CPP -namespace lodepng { +namespace lodepng +{ #ifdef LODEPNG_COMPILE_DECODER /*Same as lodepng_decode_memory, but decodes to an std::vector. The colortype is the format to output the pixels to. Default is RGBA 8-bit per channel.*/ -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - const unsigned char* in, size_t insize, +unsigned decode(std::vector & out, unsigned & w, unsigned & h, + const unsigned char * in, size_t insize, LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - const std::vector& in, +unsigned decode(std::vector & out, unsigned & w, unsigned & h, + const std::vector & in, LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); #ifdef LODEPNG_COMPILE_DISK /* Converts PNG file from disk to raw pixel data in memory. Same as the other decode functions, but instead takes a filename as input. */ -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - const std::string& filename, +unsigned decode(std::vector & out, unsigned & w, unsigned & h, + const std::string & filename, LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); #endif /* LODEPNG_COMPILE_DISK */ #endif /* LODEPNG_COMPILE_DECODER */ @@ -235,11 +236,11 @@ unsigned decode(std::vector& out, unsigned& w, unsigned& h, #ifdef LODEPNG_COMPILE_ENCODER /*Same as lodepng_encode_memory, but encodes to an std::vector. colortype is that of the raw input data. The output PNG color type will be auto chosen.*/ -unsigned encode(std::vector& out, - const unsigned char* in, unsigned w, unsigned h, +unsigned encode(std::vector & out, + const unsigned char * in, unsigned w, unsigned h, LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); -unsigned encode(std::vector& out, - const std::vector& in, unsigned w, unsigned h, +unsigned encode(std::vector & out, + const std::vector & in, unsigned w, unsigned h, LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); #ifdef LODEPNG_COMPILE_DISK /* @@ -247,11 +248,11 @@ Converts 32-bit RGBA raw pixel data into a PNG file on disk. Same as the other encode functions, but instead takes a filename as output. NOTE: This overwrites existing files without warning! */ -unsigned encode(const std::string& filename, - const unsigned char* in, unsigned w, unsigned h, +unsigned encode(const std::string & filename, + const unsigned char * in, unsigned w, unsigned h, LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); -unsigned encode(const std::string& filename, - const std::vector& in, unsigned w, unsigned h, +unsigned encode(const std::string & filename, + const std::vector & in, unsigned w, unsigned h, LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); #endif /* LODEPNG_COMPILE_DISK */ #endif /* LODEPNG_COMPILE_ENCODER */ @@ -260,42 +261,42 @@ unsigned encode(const std::string& filename, #endif /*LODEPNG_COMPILE_PNG*/ #ifdef LODEPNG_COMPILE_ERROR_TEXT -/*Returns an English description of the numerical error code.*/ -const char* lodepng_error_text(unsigned code); + /*Returns an English description of the numerical error code.*/ + const char * lodepng_error_text(unsigned code); #endif /*LODEPNG_COMPILE_ERROR_TEXT*/ #ifdef LODEPNG_COMPILE_DECODER /*Settings for zlib decompression*/ -typedef struct LodePNGDecompressSettings LodePNGDecompressSettings; -struct LodePNGDecompressSettings { - /* Check LodePNGDecoderSettings for more ignorable errors such as ignore_crc */ - unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/ - unsigned ignore_nlen; /*ignore complement of len checksum in uncompressed blocks*/ +typedef struct _LodePNGDecompressSettings LodePNGDecompressSettings; +struct _LodePNGDecompressSettings { + /* Check LodePNGDecoderSettings for more ignorable errors such as ignore_crc */ + unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/ + unsigned ignore_nlen; /*ignore complement of len checksum in uncompressed blocks*/ - /*Maximum decompressed size, beyond this the decoder may (and is encouraged to) stop decoding, - return an error, output a data size > max_output_size and all the data up to that point. This is - not hard limit nor a guarantee, but can prevent excessive memory usage. This setting is - ignored by the PNG decoder, but is used by the deflate/zlib decoder and can be used by custom ones. - Set to 0 to impose no limit (the default).*/ - size_t max_output_size; + /*Maximum decompressed size, beyond this the decoder may (and is encouraged to) stop decoding, + return an error, output a data size > max_output_size and all the data up to that point. This is + not hard limit nor a guarantee, but can prevent excessive memory usage. This setting is + ignored by the PNG decoder, but is used by the deflate/zlib decoder and can be used by custom ones. + Set to 0 to impose no limit (the default).*/ + size_t max_output_size; - /*use custom zlib decoder instead of built in one (default: null). - Should return 0 if success, any non-0 if error (numeric value not exposed).*/ - unsigned (*custom_zlib)(unsigned char**, size_t*, - const unsigned char*, size_t, - const LodePNGDecompressSettings*); - /*use custom deflate decoder instead of built in one (default: null) - if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate). - Should return 0 if success, any non-0 if error (numeric value not exposed).*/ - unsigned (*custom_inflate)(unsigned char**, size_t*, - const unsigned char*, size_t, - const LodePNGDecompressSettings*); + /*use custom zlib decoder instead of built in one (default: null). + Should return 0 if success, any non-0 if error (numeric value not exposed).*/ + unsigned(*custom_zlib)(unsigned char **, size_t *, + const unsigned char *, size_t, + const LodePNGDecompressSettings *); + /*use custom deflate decoder instead of built in one (default: null) + if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate). + Should return 0 if success, any non-0 if error (numeric value not exposed).*/ + unsigned(*custom_inflate)(unsigned char **, size_t *, + const unsigned char *, size_t, + const LodePNGDecompressSettings *); - const void* custom_context; /*optional custom settings for custom functions*/ + const void * custom_context; /*optional custom settings for custom functions*/ }; -extern const LodePNGDecompressSettings lodepng_default_decompress_settings; -void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings); +LV_ATTRIBUTE_EXTERN_DATA extern const LodePNGDecompressSettings lodepng_default_decompress_settings; +void lodepng_decompress_settings_init(LodePNGDecompressSettings * settings); #endif /*LODEPNG_COMPILE_DECODER*/ #ifdef LODEPNG_COMPILE_ENCODER @@ -303,32 +304,32 @@ void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings); Settings for zlib compression. Tweaking these settings tweaks the balance between speed and compression ratio. */ -typedef struct LodePNGCompressSettings LodePNGCompressSettings; -struct LodePNGCompressSettings /*deflate = compress*/ { - /*LZ77 related settings*/ - unsigned btype; /*the block type for LZ (0, 1, 2 or 3, see zlib standard). Should be 2 for proper compression.*/ - unsigned use_lz77; /*whether or not to use LZ77. Should be 1 for proper compression.*/ - unsigned windowsize; /*must be a power of two <= 32768. higher compresses more but is slower. Default value: 2048.*/ - unsigned minmatch; /*minimum lz77 length. 3 is normally best, 6 can be better for some PNGs. Default: 0*/ - unsigned nicematch; /*stop searching if >= this length found. Set to 258 for best compression. Default: 128*/ - unsigned lazymatching; /*use lazy matching: better compression but a bit slower. Default: true*/ +typedef struct _LodePNGCompressSettings LodePNGCompressSettings; +struct _LodePNGCompressSettings { /*deflate = compress*/ + /*LZ77 related settings*/ + unsigned btype; /*the block type for LZ (0, 1, 2 or 3, see zlib standard). Should be 2 for proper compression.*/ + unsigned use_lz77; /*whether or not to use LZ77. Should be 1 for proper compression.*/ + unsigned windowsize; /*must be a power of two <= 32768. higher compresses more but is slower. Default value: 2048.*/ + unsigned minmatch; /*minimum lz77 length. 3 is normally best, 6 can be better for some PNGs. Default: 0*/ + unsigned nicematch; /*stop searching if >= this length found. Set to 258 for best compression. Default: 128*/ + unsigned lazymatching; /*use lazy matching: better compression but a bit slower. Default: true*/ - /*use custom zlib encoder instead of built in one (default: null)*/ - unsigned (*custom_zlib)(unsigned char**, size_t*, - const unsigned char*, size_t, - const LodePNGCompressSettings*); - /*use custom deflate encoder instead of built in one (default: null) - if custom_zlib is used, custom_deflate is ignored since only the built in - zlib function will call custom_deflate*/ - unsigned (*custom_deflate)(unsigned char**, size_t*, - const unsigned char*, size_t, - const LodePNGCompressSettings*); + /*use custom zlib encoder instead of built in one (default: null)*/ + unsigned(*custom_zlib)(unsigned char **, size_t *, + const unsigned char *, size_t, + const LodePNGCompressSettings *); + /*use custom deflate encoder instead of built in one (default: null) + if custom_zlib is used, custom_deflate is ignored since only the built in + zlib function will call custom_deflate*/ + unsigned(*custom_deflate)(unsigned char **, size_t *, + const unsigned char *, size_t, + const LodePNGCompressSettings *); - const void* custom_context; /*optional custom settings for custom functions*/ + const void * custom_context; /*optional custom settings for custom functions*/ }; -extern const LodePNGCompressSettings lodepng_default_compress_settings; -void lodepng_compress_settings_init(LodePNGCompressSettings* settings); +LV_ATTRIBUTE_EXTERN_DATA extern const LodePNGCompressSettings lodepng_default_compress_settings; +void lodepng_compress_settings_init(LodePNGCompressSettings * settings); #endif /*LODEPNG_COMPILE_ENCODER*/ #ifdef LODEPNG_COMPILE_PNG @@ -337,73 +338,73 @@ Color mode of an image. Contains all information required to decode the pixel bits to RGBA colors. This information is the same as used in the PNG file format, and is used both for PNG and raw image data in LodePNG. */ -typedef struct LodePNGColorMode { - /*header (IHDR)*/ - LodePNGColorType colortype; /*color type, see PNG standard or documentation further in this header file*/ - unsigned bitdepth; /*bits per sample, see PNG standard or documentation further in this header file*/ +typedef struct _LodePNGColorMode { + /*header (IHDR)*/ + LodePNGColorType colortype; /*color type, see PNG standard or documentation further in this header file*/ + unsigned bitdepth; /*bits per sample, see PNG standard or documentation further in this header file*/ - /* - palette (PLTE and tRNS) + /* + palette (PLTE and tRNS) - Dynamically allocated with the colors of the palette, including alpha. - This field may not be allocated directly, use lodepng_color_mode_init first, - then lodepng_palette_add per color to correctly initialize it (to ensure size - of exactly 1024 bytes). + Dynamically allocated with the colors of the palette, including alpha. + This field may not be allocated directly, use lodepng_color_mode_init first, + then lodepng_palette_add per color to correctly initialize it (to ensure size + of exactly 1024 bytes). - The alpha channels must be set as well, set them to 255 for opaque images. + The alpha channels must be set as well, set them to 255 for opaque images. - When decoding, by default you can ignore this palette, since LodePNG already - fills the palette colors in the pixels of the raw RGBA output. + When decoding, by default you can ignore this palette, since LodePNG already + fills the palette colors in the pixels of the raw RGBA output. - The palette is only supported for color type 3. - */ - unsigned char* palette; /*palette in RGBARGBA... order. Must be either 0, or when allocated must have 1024 bytes*/ - size_t palettesize; /*palette size in number of colors (amount of used bytes is 4 * palettesize)*/ + The palette is only supported for color type 3. + */ + unsigned char * palette; /*palette in RGBARGBA... order. Must be either 0, or when allocated must have 1024 bytes*/ + size_t palettesize; /*palette size in number of colors (amount of used bytes is 4 * palettesize)*/ - /* - transparent color key (tRNS) + /* + transparent color key (tRNS) - This color uses the same bit depth as the bitdepth value in this struct, which can be 1-bit to 16-bit. - For grayscale PNGs, r, g and b will all 3 be set to the same. + This color uses the same bit depth as the bitdepth value in this struct, which can be 1-bit to 16-bit. + For grayscale PNGs, r, g and b will all 3 be set to the same. - When decoding, by default you can ignore this information, since LodePNG sets - pixels with this key to transparent already in the raw RGBA output. + When decoding, by default you can ignore this information, since LodePNG sets + pixels with this key to transparent already in the raw RGBA output. - The color key is only supported for color types 0 and 2. - */ - unsigned key_defined; /*is a transparent color key given? 0 = false, 1 = true*/ - unsigned key_r; /*red/grayscale component of color key*/ - unsigned key_g; /*green component of color key*/ - unsigned key_b; /*blue component of color key*/ + The color key is only supported for color types 0 and 2. + */ + unsigned key_defined; /*is a transparent color key given? 0 = false, 1 = true*/ + unsigned key_r; /*red/grayscale component of color key*/ + unsigned key_g; /*green component of color key*/ + unsigned key_b; /*blue component of color key*/ } LodePNGColorMode; /*init, cleanup and copy functions to use with this struct*/ -void lodepng_color_mode_init(LodePNGColorMode* info); -void lodepng_color_mode_cleanup(LodePNGColorMode* info); +void lodepng_color_mode_init(LodePNGColorMode * info); +void lodepng_color_mode_cleanup(LodePNGColorMode * info); /*return value is error code (0 means no error)*/ -unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source); +unsigned lodepng_color_mode_copy(LodePNGColorMode * dest, const LodePNGColorMode * source); /* Makes a temporary LodePNGColorMode that does not need cleanup (no palette) */ LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth); -void lodepng_palette_clear(LodePNGColorMode* info); +void lodepng_palette_clear(LodePNGColorMode * info); /*add 1 color to the palette*/ -unsigned lodepng_palette_add(LodePNGColorMode* info, +unsigned lodepng_palette_add(LodePNGColorMode * info, unsigned char r, unsigned char g, unsigned char b, unsigned char a); /*get the total amount of bits per pixel, based on colortype and bitdepth in the struct*/ -unsigned lodepng_get_bpp(const LodePNGColorMode* info); +unsigned lodepng_get_bpp(const LodePNGColorMode * info); /*get the amount of color channels used, based on colortype in the struct. If a palette is used, it counts as 1 channel.*/ -unsigned lodepng_get_channels(const LodePNGColorMode* info); +unsigned lodepng_get_channels(const LodePNGColorMode * info); /*is it a grayscale type? (only colortype 0 or 4)*/ -unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info); +unsigned lodepng_is_greyscale_type(const LodePNGColorMode * info); /*has it got an alpha channel? (only colortype 2 or 6)*/ -unsigned lodepng_is_alpha_type(const LodePNGColorMode* info); +unsigned lodepng_is_alpha_type(const LodePNGColorMode * info); /*has it got a palette? (only colortype 3)*/ -unsigned lodepng_is_palette_type(const LodePNGColorMode* info); +unsigned lodepng_is_palette_type(const LodePNGColorMode * info); /*only returns true if there is a palette and there is a value in the palette with alpha < 255. Loops through the palette to check this.*/ -unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info); +unsigned lodepng_has_palette_alpha(const LodePNGColorMode * info); /* Check if the given color info indicates the possibility of having non-opaque pixels in the PNG image. Returns true if the image can have translucent or invisible pixels (it still be opaque if it doesn't use such pixels). @@ -411,213 +412,213 @@ Returns false if the image can only have opaque pixels. In detail, it returns true only if it's a color type with alpha, or has a palette with non-opaque values, or if "key_defined" is true. */ -unsigned lodepng_can_have_alpha(const LodePNGColorMode* info); +unsigned lodepng_can_have_alpha(const LodePNGColorMode * info); /*Returns the byte size of a raw image buffer with given width, height and color mode*/ -size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color); +size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode * color); #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS /*The information of a Time chunk in PNG.*/ -typedef struct LodePNGTime { - unsigned year; /*2 bytes used (0-65535)*/ - unsigned month; /*1-12*/ - unsigned day; /*1-31*/ - unsigned hour; /*0-23*/ - unsigned minute; /*0-59*/ - unsigned second; /*0-60 (to allow for leap seconds)*/ +typedef struct _LodePNGTime { + unsigned year; /*2 bytes used (0-65535)*/ + unsigned month; /*1-12*/ + unsigned day; /*1-31*/ + unsigned hour; /*0-23*/ + unsigned minute; /*0-59*/ + unsigned second; /*0-60 (to allow for leap seconds)*/ } LodePNGTime; #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ /*Information about the PNG image, except pixels, width and height.*/ -typedef struct LodePNGInfo { - /*header (IHDR), palette (PLTE) and transparency (tRNS) chunks*/ - unsigned compression_method;/*compression method of the original file. Always 0.*/ - unsigned filter_method; /*filter method of the original file*/ - unsigned interlace_method; /*interlace method of the original file: 0=none, 1=Adam7*/ - LodePNGColorMode color; /*color type and bits, palette and transparency of the PNG file*/ +typedef struct _LodePNGInfo { + /*header (IHDR), palette (PLTE) and transparency (tRNS) chunks*/ + unsigned compression_method;/*compression method of the original file. Always 0.*/ + unsigned filter_method; /*filter method of the original file*/ + unsigned interlace_method; /*interlace method of the original file: 0=none, 1=Adam7*/ + LodePNGColorMode color; /*color type and bits, palette and transparency of the PNG file*/ #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /* - Suggested background color chunk (bKGD) + /* + Suggested background color chunk (bKGD) - This uses the same color mode and bit depth as the PNG (except no alpha channel), - with values truncated to the bit depth in the unsigned integer. + This uses the same color mode and bit depth as the PNG (except no alpha channel), + with values truncated to the bit depth in the unsigned integer. - For grayscale and palette PNGs, the value is stored in background_r. The values - in background_g and background_b are then unused. + For grayscale and palette PNGs, the value is stored in background_r. The values + in background_g and background_b are then unused. - So when decoding, you may get these in a different color mode than the one you requested - for the raw pixels. + So when decoding, you may get these in a different color mode than the one you requested + for the raw pixels. - When encoding with auto_convert, you must use the color model defined in info_png.color for - these values. The encoder normally ignores info_png.color when auto_convert is on, but will - use it to interpret these values (and convert copies of them to its chosen color model). + When encoding with auto_convert, you must use the color model defined in info_png.color for + these values. The encoder normally ignores info_png.color when auto_convert is on, but will + use it to interpret these values (and convert copies of them to its chosen color model). - When encoding, avoid setting this to an expensive color, such as a non-gray value - when the image is gray, or the compression will be worse since it will be forced to - write the PNG with a more expensive color mode (when auto_convert is on). + When encoding, avoid setting this to an expensive color, such as a non-gray value + when the image is gray, or the compression will be worse since it will be forced to + write the PNG with a more expensive color mode (when auto_convert is on). - The decoder does not use this background color to edit the color of pixels. This is a - completely optional metadata feature. - */ - unsigned background_defined; /*is a suggested background color given?*/ - unsigned background_r; /*red/gray/palette component of suggested background color*/ - unsigned background_g; /*green component of suggested background color*/ - unsigned background_b; /*blue component of suggested background color*/ + The decoder does not use this background color to edit the color of pixels. This is a + completely optional metadata feature. + */ + unsigned background_defined; /*is a suggested background color given?*/ + unsigned background_r; /*red/gray/palette component of suggested background color*/ + unsigned background_g; /*green component of suggested background color*/ + unsigned background_b; /*blue component of suggested background color*/ - /* - Non-international text chunks (tEXt and zTXt) + /* + Non-international text chunks (tEXt and zTXt) - The char** arrays each contain num strings. The actual messages are in - text_strings, while text_keys are keywords that give a short description what - the actual text represents, e.g. Title, Author, Description, or anything else. + The char** arrays each contain num strings. The actual messages are in + text_strings, while text_keys are keywords that give a short description what + the actual text represents, e.g. Title, Author, Description, or anything else. - All the string fields below including strings, keys, names and language tags are null terminated. - The PNG specification uses null characters for the keys, names and tags, and forbids null - characters to appear in the main text which is why we can use null termination everywhere here. + All the string fields below including strings, keys, names and language tags are null terminated. + The PNG specification uses null characters for the keys, names and tags, and forbids null + characters to appear in the main text which is why we can use null termination everywhere here. - A keyword is minimum 1 character and maximum 79 characters long (plus the - additional null terminator). It's discouraged to use a single line length - longer than 79 characters for texts. + A keyword is minimum 1 character and maximum 79 characters long (plus the + additional null terminator). It's discouraged to use a single line length + longer than 79 characters for texts. - Don't allocate these text buffers yourself. Use the init/cleanup functions - correctly and use lodepng_add_text and lodepng_clear_text. + Don't allocate these text buffers yourself. Use the init/cleanup functions + correctly and use lodepng_add_text and lodepng_clear_text. - Standard text chunk keywords and strings are encoded using Latin-1. - */ - size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/ - char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/ - char** text_strings; /*the actual text*/ + Standard text chunk keywords and strings are encoded using Latin-1. + */ + size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/ + char ** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/ + char ** text_strings; /*the actual text*/ - /* - International text chunks (iTXt) - Similar to the non-international text chunks, but with additional strings - "langtags" and "transkeys", and the following text encodings are used: - keys: Latin-1, langtags: ASCII, transkeys and strings: UTF-8. - keys must be 1-79 characters (plus the additional null terminator), the other - strings are any length. - */ - size_t itext_num; /*the amount of international texts in this PNG*/ - char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/ - char** itext_langtags; /*language tag for this text's language, ISO/IEC 646 string, e.g. ISO 639 language tag*/ - char** itext_transkeys; /*keyword translated to the international language - UTF-8 string*/ - char** itext_strings; /*the actual international text - UTF-8 string*/ + /* + International text chunks (iTXt) + Similar to the non-international text chunks, but with additional strings + "langtags" and "transkeys", and the following text encodings are used: + keys: Latin-1, langtags: ASCII, transkeys and strings: UTF-8. + keys must be 1-79 characters (plus the additional null terminator), the other + strings are any length. + */ + size_t itext_num; /*the amount of international texts in this PNG*/ + char ** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/ + char ** itext_langtags; /*language tag for this text's language, ISO/IEC 646 string, e.g. ISO 639 language tag*/ + char ** itext_transkeys; /*keyword translated to the international language - UTF-8 string*/ + char ** itext_strings; /*the actual international text - UTF-8 string*/ - /*time chunk (tIME)*/ - unsigned time_defined; /*set to 1 to make the encoder generate a tIME chunk*/ - LodePNGTime time; + /*time chunk (tIME)*/ + unsigned time_defined; /*set to 1 to make the encoder generate a tIME chunk*/ + LodePNGTime time; - /*phys chunk (pHYs)*/ - unsigned phys_defined; /*if 0, there is no pHYs chunk and the values below are undefined, if 1 else there is one*/ - unsigned phys_x; /*pixels per unit in x direction*/ - unsigned phys_y; /*pixels per unit in y direction*/ - unsigned phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/ + /*phys chunk (pHYs)*/ + unsigned phys_defined; /*if 0, there is no pHYs chunk and the values below are undefined, if 1 else there is one*/ + unsigned phys_x; /*pixels per unit in x direction*/ + unsigned phys_y; /*pixels per unit in y direction*/ + unsigned phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/ - /* - Color profile related chunks: gAMA, cHRM, sRGB, iCPP + /* + Color profile related chunks: gAMA, cHRM, sRGB, iCPP - LodePNG does not apply any color conversions on pixels in the encoder or decoder and does not interpret these color - profile values. It merely passes on the information. If you wish to use color profiles and convert colors, please - use these values with a color management library. + LodePNG does not apply any color conversions on pixels in the encoder or decoder and does not interpret these color + profile values. It merely passes on the information. If you wish to use color profiles and convert colors, please + use these values with a color management library. - See the PNG, ICC and sRGB specifications for more information about the meaning of these values. - */ + See the PNG, ICC and sRGB specifications for more information about the meaning of these values. + */ - /* gAMA chunk: optional, overridden by sRGB or iCCP if those are present. */ - unsigned gama_defined; /* Whether a gAMA chunk is present (0 = not present, 1 = present). */ - unsigned gama_gamma; /* Gamma exponent times 100000 */ + /* gAMA chunk: optional, overridden by sRGB or iCCP if those are present. */ + unsigned gama_defined; /* Whether a gAMA chunk is present (0 = not present, 1 = present). */ + unsigned gama_gamma; /* Gamma exponent times 100000 */ - /* cHRM chunk: optional, overridden by sRGB or iCCP if those are present. */ - unsigned chrm_defined; /* Whether a cHRM chunk is present (0 = not present, 1 = present). */ - unsigned chrm_white_x; /* White Point x times 100000 */ - unsigned chrm_white_y; /* White Point y times 100000 */ - unsigned chrm_red_x; /* Red x times 100000 */ - unsigned chrm_red_y; /* Red y times 100000 */ - unsigned chrm_green_x; /* Green x times 100000 */ - unsigned chrm_green_y; /* Green y times 100000 */ - unsigned chrm_blue_x; /* Blue x times 100000 */ - unsigned chrm_blue_y; /* Blue y times 100000 */ + /* cHRM chunk: optional, overridden by sRGB or iCCP if those are present. */ + unsigned chrm_defined; /* Whether a cHRM chunk is present (0 = not present, 1 = present). */ + unsigned chrm_white_x; /* White Point x times 100000 */ + unsigned chrm_white_y; /* White Point y times 100000 */ + unsigned chrm_red_x; /* Red x times 100000 */ + unsigned chrm_red_y; /* Red y times 100000 */ + unsigned chrm_green_x; /* Green x times 100000 */ + unsigned chrm_green_y; /* Green y times 100000 */ + unsigned chrm_blue_x; /* Blue x times 100000 */ + unsigned chrm_blue_y; /* Blue y times 100000 */ - /* - sRGB chunk: optional. May not appear at the same time as iCCP. - If gAMA is also present gAMA must contain value 45455. - If cHRM is also present cHRM must contain respectively 31270,32900,64000,33000,30000,60000,15000,6000. - */ - unsigned srgb_defined; /* Whether an sRGB chunk is present (0 = not present, 1 = present). */ - unsigned srgb_intent; /* Rendering intent: 0=perceptual, 1=rel. colorimetric, 2=saturation, 3=abs. colorimetric */ + /* + sRGB chunk: optional. May not appear at the same time as iCCP. + If gAMA is also present gAMA must contain value 45455. + If cHRM is also present cHRM must contain respectively 31270,32900,64000,33000,30000,60000,15000,6000. + */ + unsigned srgb_defined; /* Whether an sRGB chunk is present (0 = not present, 1 = present). */ + unsigned srgb_intent; /* Rendering intent: 0=perceptual, 1=rel. colorimetric, 2=saturation, 3=abs. colorimetric */ - /* - iCCP chunk: optional. May not appear at the same time as sRGB. + /* + iCCP chunk: optional. May not appear at the same time as sRGB. - LodePNG does not parse or use the ICC profile (except its color space header field for an edge case), a - separate library to handle the ICC data (not included in LodePNG) format is needed to use it for color - management and conversions. + LodePNG does not parse or use the ICC profile (except its color space header field for an edge case), a + separate library to handle the ICC data (not included in LodePNG) format is needed to use it for color + management and conversions. - For encoding, if iCCP is present, gAMA and cHRM are recommended to be added as well with values that match the ICC - profile as closely as possible, if you wish to do this you should provide the correct values for gAMA and cHRM and - enable their '_defined' flags since LodePNG will not automatically compute them from the ICC profile. + For encoding, if iCCP is present, gAMA and cHRM are recommended to be added as well with values that match the ICC + profile as closely as possible, if you wish to do this you should provide the correct values for gAMA and cHRM and + enable their '_defined' flags since LodePNG will not automatically compute them from the ICC profile. - For encoding, the ICC profile is required by the PNG specification to be an "RGB" profile for non-gray - PNG color types and a "GRAY" profile for gray PNG color types. If you disable auto_convert, you must ensure - the ICC profile type matches your requested color type, else the encoder gives an error. If auto_convert is - enabled (the default), and the ICC profile is not a good match for the pixel data, this will result in an encoder - error if the pixel data has non-gray pixels for a GRAY profile, or a silent less-optimal compression of the pixel - data if the pixels could be encoded as grayscale but the ICC profile is RGB. + For encoding, the ICC profile is required by the PNG specification to be an "RGB" profile for non-gray + PNG color types and a "GRAY" profile for gray PNG color types. If you disable auto_convert, you must ensure + the ICC profile type matches your requested color type, else the encoder gives an error. If auto_convert is + enabled (the default), and the ICC profile is not a good match for the pixel data, this will result in an encoder + error if the pixel data has non-gray pixels for a GRAY profile, or a silent less-optimal compression of the pixel + data if the pixels could be encoded as grayscale but the ICC profile is RGB. - To avoid this do not set an ICC profile in the image unless there is a good reason for it, and when doing so - make sure you compute it carefully to avoid the above problems. - */ - unsigned iccp_defined; /* Whether an iCCP chunk is present (0 = not present, 1 = present). */ - char* iccp_name; /* Null terminated string with profile name, 1-79 bytes */ - /* - The ICC profile in iccp_profile_size bytes. - Don't allocate this buffer yourself. Use the init/cleanup functions - correctly and use lodepng_set_icc and lodepng_clear_icc. - */ - unsigned char* iccp_profile; - unsigned iccp_profile_size; /* The size of iccp_profile in bytes */ + To avoid this do not set an ICC profile in the image unless there is a good reason for it, and when doing so + make sure you compute it carefully to avoid the above problems. + */ + unsigned iccp_defined; /* Whether an iCCP chunk is present (0 = not present, 1 = present). */ + char * iccp_name; /* Null terminated string with profile name, 1-79 bytes */ + /* + The ICC profile in iccp_profile_size bytes. + Don't allocate this buffer yourself. Use the init/cleanup functions + correctly and use lodepng_set_icc and lodepng_clear_icc. + */ + unsigned char * iccp_profile; + unsigned iccp_profile_size; /* The size of iccp_profile in bytes */ - /* End of color profile related chunks */ + /* End of color profile related chunks */ - /* - unknown chunks: chunks not known by LodePNG, passed on byte for byte. + /* + unknown chunks: chunks not known by LodePNG, passed on byte for byte. - There are 3 buffers, one for each position in the PNG where unknown chunks can appear. - Each buffer contains all unknown chunks for that position consecutively. - The 3 positions are: - 0: between IHDR and PLTE, 1: between PLTE and IDAT, 2: between IDAT and IEND. + There are 3 buffers, one for each position in the PNG where unknown chunks can appear. + Each buffer contains all unknown chunks for that position consecutively. + The 3 positions are: + 0: between IHDR and PLTE, 1: between PLTE and IDAT, 2: between IDAT and IEND. - For encoding, do not store critical chunks or known chunks that are enabled with a "_defined" flag - above in here, since the encoder will blindly follow this and could then encode an invalid PNG file - (such as one with two IHDR chunks or the disallowed combination of sRGB with iCCP). But do use - this if you wish to store an ancillary chunk that is not supported by LodePNG (such as sPLT or hIST), - or any non-standard PNG chunk. + For encoding, do not store critical chunks or known chunks that are enabled with a "_defined" flag + above in here, since the encoder will blindly follow this and could then encode an invalid PNG file + (such as one with two IHDR chunks or the disallowed combination of sRGB with iCCP). But do use + this if you wish to store an ancillary chunk that is not supported by LodePNG (such as sPLT or hIST), + or any non-standard PNG chunk. - Do not allocate or traverse this data yourself. Use the chunk traversing functions declared - later, such as lodepng_chunk_next and lodepng_chunk_append, to read/write this struct. - */ - unsigned char* unknown_chunks_data[3]; - size_t unknown_chunks_size[3]; /*size in bytes of the unknown chunks, given for protection*/ + Do not allocate or traverse this data yourself. Use the chunk traversing functions declared + later, such as lodepng_chunk_next and lodepng_chunk_append, to read/write this struct. + */ + unsigned char * unknown_chunks_data[3]; + size_t unknown_chunks_size[3]; /*size in bytes of the unknown chunks, given for protection*/ #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ } LodePNGInfo; /*init, cleanup and copy functions to use with this struct*/ -void lodepng_info_init(LodePNGInfo* info); -void lodepng_info_cleanup(LodePNGInfo* info); +void lodepng_info_init(LodePNGInfo * info); +void lodepng_info_cleanup(LodePNGInfo * info); /*return value is error code (0 means no error)*/ -unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source); +unsigned lodepng_info_copy(LodePNGInfo * dest, const LodePNGInfo * source); #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS -unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str); /*push back both texts at once*/ -void lodepng_clear_text(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/ +unsigned lodepng_add_text(LodePNGInfo * info, const char * key, const char * str); /*push back both texts at once*/ +void lodepng_clear_text(LodePNGInfo * info); /*use this to clear the texts again after you filled them in*/ -unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag, - const char* transkey, const char* str); /*push back the 4 texts of 1 chunk at once*/ -void lodepng_clear_itext(LodePNGInfo* info); /*use this to clear the itexts again after you filled them in*/ +unsigned lodepng_add_itext(LodePNGInfo * info, const char * key, const char * langtag, + const char * transkey, const char * str); /*push back the 4 texts of 1 chunk at once*/ +void lodepng_clear_itext(LodePNGInfo * info); /*use this to clear the itexts again after you filled them in*/ /*replaces if exists*/ -unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size); -void lodepng_clear_icc(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/ +unsigned lodepng_set_icc(LodePNGInfo * info, const char * name, const unsigned char * profile, unsigned profile_size); +void lodepng_clear_icc(LodePNGInfo * info); /*use this to clear the texts again after you filled them in*/ #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ /* @@ -631,8 +632,8 @@ For < 8 bpp images, there should not be padding bits at the end of scanlines. For 16-bit per channel colors, uses big endian format like PNG does. Return value is LodePNG error code */ -unsigned lodepng_convert(unsigned char* out, const unsigned char* in, - const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, +unsigned lodepng_convert(unsigned char * out, const unsigned char * in, + const LodePNGColorMode * mode_out, const LodePNGColorMode * mode_in, unsigned w, unsigned h); #ifdef LODEPNG_COMPILE_DECODER @@ -640,146 +641,147 @@ unsigned lodepng_convert(unsigned char* out, const unsigned char* in, Settings for the decoder. This contains settings for the PNG and the Zlib decoder, but not the Info settings from the Info structs. */ -typedef struct LodePNGDecoderSettings { - LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/ +typedef struct _LodePNGDecoderSettings { + LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/ - /* Check LodePNGDecompressSettings for more ignorable errors such as ignore_adler32 */ - unsigned ignore_crc; /*ignore CRC checksums*/ - unsigned ignore_critical; /*ignore unknown critical chunks*/ - unsigned ignore_end; /*ignore issues at end of file if possible (missing IEND chunk, too large chunk, ...)*/ - /* TODO: make a system involving warnings with levels and a strict mode instead. Other potentially recoverable - errors: srgb rendering intent value, size of content of ancillary chunks, more than 79 characters for some - strings, placement/combination rules for ancillary chunks, crc of unknown chunks, allowed characters - in string keys, etc... */ + /* Check LodePNGDecompressSettings for more ignorable errors such as ignore_adler32 */ + unsigned ignore_crc; /*ignore CRC checksums*/ + unsigned ignore_critical; /*ignore unknown critical chunks*/ + unsigned ignore_end; /*ignore issues at end of file if possible (missing IEND chunk, too large chunk, ...)*/ + /* TODO: make a system involving warnings with levels and a strict mode instead. Other potentially recoverable + errors: srgb rendering intent value, size of content of ancillary chunks, more than 79 characters for some + strings, placement/combination rules for ancillary chunks, crc of unknown chunks, allowed characters + in string keys, etc... */ - unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/ + unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/ #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/ + unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/ - /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/ - unsigned remember_unknown_chunks; + /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/ + unsigned remember_unknown_chunks; - /* maximum size for decompressed text chunks. If a text chunk's text is larger than this, an error is returned, - unless reading text chunks is disabled or this limit is set higher or disabled. Set to 0 to allow any size. - By default it is a value that prevents unreasonably large strings from hogging memory. */ - size_t max_text_size; + /* maximum size for decompressed text chunks. If a text chunk's text is larger than this, an error is returned, + unless reading text chunks is disabled or this limit is set higher or disabled. Set to 0 to allow any size. + By default it is a value that prevents unreasonably large strings from hogging memory. */ + size_t max_text_size; - /* maximum size for compressed ICC chunks. If the ICC profile is larger than this, an error will be returned. Set to - 0 to allow any size. By default this is a value that prevents ICC profiles that would be much larger than any - legitimate profile could be to hog memory. */ - size_t max_icc_size; + /* maximum size for compressed ICC chunks. If the ICC profile is larger than this, an error will be returned. Set to + 0 to allow any size. By default this is a value that prevents ICC profiles that would be much larger than any + legitimate profile could be to hog memory. */ + size_t max_icc_size; #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ } LodePNGDecoderSettings; -void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings); +void lodepng_decoder_settings_init(LodePNGDecoderSettings * settings); #endif /*LODEPNG_COMPILE_DECODER*/ #ifdef LODEPNG_COMPILE_ENCODER /*automatically use color type with less bits per pixel if losslessly possible. Default: AUTO*/ -typedef enum LodePNGFilterStrategy { - /*every filter at zero*/ - LFS_ZERO = 0, - /*every filter at 1, 2, 3 or 4 (paeth), unlike LFS_ZERO not a good choice, but for testing*/ - LFS_ONE = 1, - LFS_TWO = 2, - LFS_THREE = 3, - LFS_FOUR = 4, - /*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/ - LFS_MINSUM, - /*Use the filter type that gives smallest Shannon entropy for this scanline. Depending - on the image, this is better or worse than minsum.*/ - LFS_ENTROPY, - /* - Brute-force-search PNG filters by compressing each filter for each scanline. - Experimental, very slow, and only rarely gives better compression than MINSUM. - */ - LFS_BRUTE_FORCE, - /*use predefined_filters buffer: you specify the filter type for each scanline*/ - LFS_PREDEFINED +typedef enum _LodePNGFilterStrategy { + /*every filter at zero*/ + LFS_ZERO = 0, + /*every filter at 1, 2, 3 or 4 (paeth), unlike LFS_ZERO not a good choice, but for testing*/ + LFS_ONE = 1, + LFS_TWO = 2, + LFS_THREE = 3, + LFS_FOUR = 4, + /*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/ + LFS_MINSUM, + /*Use the filter type that gives smallest Shannon entropy for this scanline. Depending + on the image, this is better or worse than minsum.*/ + LFS_ENTROPY, + /* + Brute-force-search PNG filters by compressing each filter for each scanline. + Experimental, very slow, and only rarely gives better compression than MINSUM. + */ + LFS_BRUTE_FORCE, + /*use predefined_filters buffer: you specify the filter type for each scanline*/ + LFS_PREDEFINED } LodePNGFilterStrategy; /*Gives characteristics about the integer RGBA colors of the image (count, alpha channel usage, bit depth, ...), which helps decide which color model to use for encoding. Used internally by default if "auto_convert" is enabled. Public because it's useful for custom algorithms.*/ -typedef struct LodePNGColorStats { - unsigned colored; /*not grayscale*/ - unsigned key; /*image is not opaque and color key is possible instead of full alpha*/ - unsigned short key_r; /*key values, always as 16-bit, in 8-bit case the byte is duplicated, e.g. 65535 means 255*/ - unsigned short key_g; - unsigned short key_b; - unsigned alpha; /*image is not opaque and alpha channel or alpha palette required*/ - unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16 or allow_palette is disabled.*/ - unsigned char palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order, only valid when numcolors is valid*/ - unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for grayscale only. 16 if 16-bit per channel required.*/ - size_t numpixels; +typedef struct _LodePNGColorStats { + unsigned colored; /*not grayscale*/ + unsigned key; /*image is not opaque and color key is possible instead of full alpha*/ + unsigned short key_r; /*key values, always as 16-bit, in 8-bit case the byte is duplicated, e.g. 65535 means 255*/ + unsigned short key_g; + unsigned short key_b; + unsigned alpha; /*image is not opaque and alpha channel or alpha palette required*/ + unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16 or allow_palette is disabled.*/ + unsigned char + palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order, only valid when numcolors is valid*/ + unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for grayscale only. 16 if 16-bit per channel required.*/ + size_t numpixels; - /*user settings for computing/using the stats*/ - unsigned allow_palette; /*default 1. if 0, disallow choosing palette colortype in auto_choose_color, and don't count numcolors*/ - unsigned allow_greyscale; /*default 1. if 0, choose RGB or RGBA even if the image only has gray colors*/ + /*user settings for computing/using the stats*/ + unsigned allow_palette; /*default 1. if 0, disallow choosing palette colortype in auto_choose_color, and don't count numcolors*/ + unsigned allow_greyscale; /*default 1. if 0, choose RGB or RGBA even if the image only has gray colors*/ } LodePNGColorStats; -void lodepng_color_stats_init(LodePNGColorStats* stats); +void lodepng_color_stats_init(LodePNGColorStats * stats); /*Get a LodePNGColorStats of the image. The stats must already have been inited. Returns error code (e.g. alloc fail) or 0 if ok.*/ -unsigned lodepng_compute_color_stats(LodePNGColorStats* stats, - const unsigned char* image, unsigned w, unsigned h, - const LodePNGColorMode* mode_in); +unsigned lodepng_compute_color_stats(LodePNGColorStats * stats, + const unsigned char * image, unsigned w, unsigned h, + const LodePNGColorMode * mode_in); /*Settings for the encoder.*/ -typedef struct LodePNGEncoderSettings { - LodePNGCompressSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/ +typedef struct _LodePNGEncoderSettings { + LodePNGCompressSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/ - unsigned auto_convert; /*automatically choose output PNG color type. Default: true*/ + unsigned auto_convert; /*automatically choose output PNG color type. Default: true*/ - /*If true, follows the official PNG heuristic: if the PNG uses a palette or lower than - 8 bit depth, set all filters to zero. Otherwise use the filter_strategy. Note that to - completely follow the official PNG heuristic, filter_palette_zero must be true and - filter_strategy must be LFS_MINSUM*/ - unsigned filter_palette_zero; - /*Which filter strategy to use when not using zeroes due to filter_palette_zero. - Set filter_palette_zero to 0 to ensure always using your chosen strategy. Default: LFS_MINSUM*/ - LodePNGFilterStrategy filter_strategy; - /*used if filter_strategy is LFS_PREDEFINED. In that case, this must point to a buffer with - the same length as the amount of scanlines in the image, and each value must <= 5. You - have to cleanup this buffer, LodePNG will never free it. Don't forget that filter_palette_zero - must be set to 0 to ensure this is also used on palette or low bitdepth images.*/ - const unsigned char* predefined_filters; + /*If true, follows the official PNG heuristic: if the PNG uses a palette or lower than + 8 bit depth, set all filters to zero. Otherwise use the filter_strategy. Note that to + completely follow the official PNG heuristic, filter_palette_zero must be true and + filter_strategy must be LFS_MINSUM*/ + unsigned filter_palette_zero; + /*Which filter strategy to use when not using zeroes due to filter_palette_zero. + Set filter_palette_zero to 0 to ensure always using your chosen strategy. Default: LFS_MINSUM*/ + LodePNGFilterStrategy filter_strategy; + /*used if filter_strategy is LFS_PREDEFINED. In that case, this must point to a buffer with + the same length as the amount of scanlines in the image, and each value must <= 5. You + have to cleanup this buffer, LodePNG will never free it. Don't forget that filter_palette_zero + must be set to 0 to ensure this is also used on palette or low bitdepth images.*/ + const unsigned char * predefined_filters; - /*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette). - If colortype is 3, PLTE is _always_ created.*/ - unsigned force_palette; + /*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette). + If colortype is 3, PLTE is _always_ created.*/ + unsigned force_palette; #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*add LodePNG identifier and version as a text chunk, for debugging*/ - unsigned add_id; - /*encode text chunks as zTXt chunks instead of tEXt chunks, and use compression in iTXt chunks*/ - unsigned text_compression; + /*add LodePNG identifier and version as a text chunk, for debugging*/ + unsigned add_id; + /*encode text chunks as zTXt chunks instead of tEXt chunks, and use compression in iTXt chunks*/ + unsigned text_compression; #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ } LodePNGEncoderSettings; -void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings); +void lodepng_encoder_settings_init(LodePNGEncoderSettings * settings); #endif /*LODEPNG_COMPILE_ENCODER*/ #if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) /*The settings, state and information for extended encoding and decoding.*/ -typedef struct LodePNGState { +typedef struct _LodePNGState { #ifdef LODEPNG_COMPILE_DECODER - LodePNGDecoderSettings decoder; /*the decoding settings*/ + LodePNGDecoderSettings decoder; /*the decoding settings*/ #endif /*LODEPNG_COMPILE_DECODER*/ #ifdef LODEPNG_COMPILE_ENCODER - LodePNGEncoderSettings encoder; /*the encoding settings*/ + LodePNGEncoderSettings encoder; /*the encoding settings*/ #endif /*LODEPNG_COMPILE_ENCODER*/ - LodePNGColorMode info_raw; /*specifies the format in which you would like to get the raw pixel buffer*/ - LodePNGInfo info_png; /*info of the PNG image obtained after decoding*/ - unsigned error; + LodePNGColorMode info_raw; /*specifies the format in which you would like to get the raw pixel buffer*/ + LodePNGInfo info_png; /*info of the PNG image obtained after decoding*/ + unsigned error; } LodePNGState; /*init, cleanup and copy functions to use with this struct*/ -void lodepng_state_init(LodePNGState* state); -void lodepng_state_cleanup(LodePNGState* state); -void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source); +void lodepng_state_init(LodePNGState * state); +void lodepng_state_cleanup(LodePNGState * state); +void lodepng_state_copy(LodePNGState * dest, const LodePNGState * source); #endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ #ifdef LODEPNG_COMPILE_DECODER @@ -787,18 +789,18 @@ void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source); Same as lodepng_decode_memory, but uses a LodePNGState to allow custom settings and getting much more information about the PNG image and color mode. */ -unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, - LodePNGState* state, - const unsigned char* in, size_t insize); +unsigned lodepng_decode(unsigned char ** out, unsigned * w, unsigned * h, + LodePNGState * state, + const unsigned char * in, size_t insize); /* Read the PNG header, but not the actual data. This returns only the information that is in the IHDR chunk of the PNG, such as width, height and color type. The information is placed in the info_png field of the LodePNGState. */ -unsigned lodepng_inspect(unsigned* w, unsigned* h, - LodePNGState* state, - const unsigned char* in, size_t insize); +unsigned lodepng_inspect(unsigned * w, unsigned * h, + LodePNGState * state, + const unsigned char * in, size_t insize); #endif /*LODEPNG_COMPILE_DECODER*/ /* @@ -813,14 +815,14 @@ Requirements: &in[pos] must point to start of a chunk, must use regular lodepng_inspect first since format of most other chunks depends on IHDR, and if there is a PLTE chunk, that one must be inspected before tRNS or bKGD. */ -unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos, - const unsigned char* in, size_t insize); +unsigned lodepng_inspect_chunk(LodePNGState * state, size_t pos, + const unsigned char * in, size_t insize); #ifdef LODEPNG_COMPILE_ENCODER /*This function allocates the out buffer with standard malloc and stores the size in *outsize.*/ -unsigned lodepng_encode(unsigned char** out, size_t* outsize, - const unsigned char* image, unsigned w, unsigned h, - LodePNGState* state); +unsigned lodepng_encode(unsigned char ** out, size_t * outsize, + const unsigned char * image, unsigned w, unsigned h, + LodePNGState * state); #endif /*LODEPNG_COMPILE_ENCODER*/ /* @@ -852,32 +854,32 @@ Gets the length of the data of the chunk. Total chunk length has 12 bytes more. There must be at least 4 bytes to read from. If the result value is too large, it may be corrupt data. */ -unsigned lodepng_chunk_length(const unsigned char* chunk); +unsigned lodepng_chunk_length(const unsigned char * chunk); /*puts the 4-byte type in null terminated string*/ -void lodepng_chunk_type(char type[5], const unsigned char* chunk); +void lodepng_chunk_type(char type[5], const unsigned char * chunk); /*check if the type is the given type*/ -unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type); +unsigned char lodepng_chunk_type_equals(const unsigned char * chunk, const char * type); /*0: it's one of the critical chunk types, 1: it's an ancillary chunk (see PNG standard)*/ -unsigned char lodepng_chunk_ancillary(const unsigned char* chunk); +unsigned char lodepng_chunk_ancillary(const unsigned char * chunk); /*0: public, 1: private (see PNG standard)*/ -unsigned char lodepng_chunk_private(const unsigned char* chunk); +unsigned char lodepng_chunk_private(const unsigned char * chunk); /*0: the chunk is unsafe to copy, 1: the chunk is safe to copy (see PNG standard)*/ -unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk); +unsigned char lodepng_chunk_safetocopy(const unsigned char * chunk); /*get pointer to the data of the chunk, where the input points to the header of the chunk*/ -unsigned char* lodepng_chunk_data(unsigned char* chunk); -const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk); +unsigned char * lodepng_chunk_data(unsigned char * chunk); +const unsigned char * lodepng_chunk_data_const(const unsigned char * chunk); /*returns 0 if the crc is correct, 1 if it's incorrect (0 for OK as usual!)*/ -unsigned lodepng_chunk_check_crc(const unsigned char* chunk); +unsigned lodepng_chunk_check_crc(const unsigned char * chunk); /*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/ -void lodepng_chunk_generate_crc(unsigned char* chunk); +void lodepng_chunk_generate_crc(unsigned char * chunk); /* Iterate to next chunks, allows iterating through all chunks of the PNG file. @@ -890,32 +892,33 @@ is no more chunk after this or possibly if the chunk is corrupt. Start this process at the 8th byte of the PNG file. In a non-corrupt PNG file, the last chunk should have name "IEND". */ -unsigned char* lodepng_chunk_next(unsigned char* chunk, unsigned char* end); -const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk, const unsigned char* end); +unsigned char * lodepng_chunk_next(unsigned char * chunk, unsigned char * end); +const unsigned char * lodepng_chunk_next_const(const unsigned char * chunk, const unsigned char * end); /*Finds the first chunk with the given type in the range [chunk, end), or returns NULL if not found.*/ -unsigned char* lodepng_chunk_find(unsigned char* chunk, unsigned char* end, const char type[5]); -const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]); +unsigned char * lodepng_chunk_find(unsigned char * chunk, unsigned char * end, const char type[5]); +const unsigned char * lodepng_chunk_find_const(const unsigned char * chunk, const unsigned char * end, + const char type[5]); /* Appends chunk to the data in out. The given chunk should already have its chunk header. The out variable and outsize are updated to reflect the new reallocated buffer. Returns error code (0 if it went ok) */ -unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk); +unsigned lodepng_chunk_append(unsigned char ** out, size_t * outsize, const unsigned char * chunk); /* Appends new chunk to out. The chunk to append is given by giving its length, type and data separately. The type is a 4-letter string. The out variable and outsize are updated to reflect the new reallocated buffer. -Returne error code (0 if it went ok) +Return error code (0 if it went ok) */ -unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, unsigned length, - const char* type, const unsigned char* data); +unsigned lodepng_chunk_create(unsigned char ** out, size_t * outsize, unsigned length, + const char * type, const unsigned char * data); /*Calculate CRC32 of buffer*/ -unsigned lodepng_crc32(const unsigned char* buf, size_t len); +unsigned lodepng_crc32(const unsigned char * buf, size_t len); #endif /*LODEPNG_COMPILE_PNG*/ @@ -928,9 +931,9 @@ part of zlib that is required for PNG, it does not support dictionaries. #ifdef LODEPNG_COMPILE_DECODER /*Inflate a buffer. Inflate is the decompression step of deflate. Out buffer must be freed after use.*/ -unsigned lodepng_inflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings); +unsigned lodepng_inflate(unsigned char ** out, size_t * outsize, + const unsigned char * in, size_t insize, + const LodePNGDecompressSettings * settings); /* Decompresses Zlib data. Reallocates the out buffer and appends the data. The @@ -938,9 +941,9 @@ data must be according to the zlib specification. Either, *out must be NULL and *outsize must be 0, or, *out must be a valid buffer and *outsize its size in bytes. out must be freed by user after usage. */ -unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings); +unsigned lodepng_zlib_decompress(unsigned char ** out, size_t * outsize, + const unsigned char * in, size_t insize, + const LodePNGDecompressSettings * settings); #endif /*LODEPNG_COMPILE_DECODER*/ #ifdef LODEPNG_COMPILE_ENCODER @@ -951,113 +954,115 @@ The data is output in the format of the zlib specification. Either, *out must be NULL and *outsize must be 0, or, *out must be a valid buffer and *outsize its size in bytes. out must be freed by user after usage. */ -unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGCompressSettings* settings); +unsigned lodepng_zlib_compress(unsigned char ** out, size_t * outsize, + const unsigned char * in, size_t insize, + const LodePNGCompressSettings * settings); /* Find length-limited Huffman code for given frequencies. This function is in the public interface only for tests, it's used internally by lodepng_deflate. */ -unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, +unsigned lodepng_huffman_code_lengths(unsigned * lengths, const unsigned * frequencies, size_t numcodes, unsigned maxbitlen); /*Compress a buffer with deflate. See RFC 1951. Out buffer must be freed after use.*/ -unsigned lodepng_deflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGCompressSettings* settings); +unsigned lodepng_deflate(unsigned char ** out, size_t * outsize, + const unsigned char * in, size_t insize, + const LodePNGCompressSettings * settings); #endif /*LODEPNG_COMPILE_ENCODER*/ #endif /*LODEPNG_COMPILE_ZLIB*/ #ifdef LODEPNG_COMPILE_DISK -/* -Load a file from disk into buffer. The function allocates the out buffer, and -after usage you should free it. -out: output parameter, contains pointer to loaded buffer. -outsize: output parameter, size of the allocated out buffer -filename: the path to the file to load -return value: error code (0 means ok) -*/ -unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename); + /* + Load a file from disk into buffer. The function allocates the out buffer, and + after usage you should free it. + out: output parameter, contains pointer to loaded buffer. + outsize: output parameter, size of the allocated out buffer + filename: the path to the file to load + return value: error code (0 means ok) + */ + unsigned lodepng_load_file(unsigned char ** out, size_t * outsize, const char * filename); -/* -Save a file from buffer to disk. Warning, if it exists, this function overwrites -the file without warning! -buffer: the buffer to write -buffersize: size of the buffer to write -filename: the path to the file to save to -return value: error code (0 means ok) -*/ -unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename); + /* + Save a file from buffer to disk. Warning, if it exists, this function overwrites + the file without warning! + buffer: the buffer to write + buffersize: size of the buffer to write + filename: the path to the file to save to + return value: error code (0 means ok) + */ + unsigned lodepng_save_file(const unsigned char * buffer, size_t buffersize, const char * filename); #endif /*LODEPNG_COMPILE_DISK*/ #ifdef LODEPNG_COMPILE_CPP /* The LodePNG C++ wrapper uses std::vectors instead of manually allocated memory buffers. */ -namespace lodepng { +namespace lodepng +{ #ifdef LODEPNG_COMPILE_PNG -class State : public LodePNGState { - public: - State(); - State(const State& other); - ~State(); - State& operator=(const State& other); +class State : public LodePNGState +{ + public: + State(); + State(const State & other); + ~State(); + State & operator=(const State & other); }; #ifdef LODEPNG_COMPILE_DECODER /* Same as other lodepng::decode, but using a State for more settings and information. */ -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - State& state, - const unsigned char* in, size_t insize); -unsigned decode(std::vector& out, unsigned& w, unsigned& h, - State& state, - const std::vector& in); +unsigned decode(std::vector & out, unsigned & w, unsigned & h, + State & state, + const unsigned char * in, size_t insize); +unsigned decode(std::vector & out, unsigned & w, unsigned & h, + State & state, + const std::vector & in); #endif /*LODEPNG_COMPILE_DECODER*/ #ifdef LODEPNG_COMPILE_ENCODER /* Same as other lodepng::encode, but using a State for more settings and information. */ -unsigned encode(std::vector& out, - const unsigned char* in, unsigned w, unsigned h, - State& state); -unsigned encode(std::vector& out, - const std::vector& in, unsigned w, unsigned h, - State& state); +unsigned encode(std::vector & out, + const unsigned char * in, unsigned w, unsigned h, + State & state); +unsigned encode(std::vector & out, + const std::vector & in, unsigned w, unsigned h, + State & state); #endif /*LODEPNG_COMPILE_ENCODER*/ #ifdef LODEPNG_COMPILE_DISK -/* -Load a file from disk into an std::vector. -return value: error code (0 means ok) -*/ -unsigned load_file(std::vector& buffer, const std::string& filename); + /* + Load a file from disk into an std::vector. + return value: error code (0 means ok) + */ + unsigned load_file(std::vector & buffer, const std::string & filename); -/* -Save the binary data in an std::vector to a file on disk. The file is overwritten -without warning. -*/ -unsigned save_file(const std::vector& buffer, const std::string& filename); + /* + Save the binary data in an std::vector to a file on disk. The file is overwritten + without warning. + */ + unsigned save_file(const std::vector & buffer, const std::string & filename); #endif /* LODEPNG_COMPILE_DISK */ #endif /* LODEPNG_COMPILE_PNG */ #ifdef LODEPNG_COMPILE_ZLIB #ifdef LODEPNG_COMPILE_DECODER /* Zlib-decompress an unsigned char buffer */ -unsigned decompress(std::vector& out, const unsigned char* in, size_t insize, - const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); +unsigned decompress(std::vector & out, const unsigned char * in, size_t insize, + const LodePNGDecompressSettings & settings = lodepng_default_decompress_settings); /* Zlib-decompress an std::vector */ -unsigned decompress(std::vector& out, const std::vector& in, - const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); +unsigned decompress(std::vector & out, const std::vector & in, + const LodePNGDecompressSettings & settings = lodepng_default_decompress_settings); #endif /* LODEPNG_COMPILE_DECODER */ #ifdef LODEPNG_COMPILE_ENCODER /* Zlib-compress an unsigned char buffer */ -unsigned compress(std::vector& out, const unsigned char* in, size_t insize, - const LodePNGCompressSettings& settings = lodepng_default_compress_settings); +unsigned compress(std::vector & out, const unsigned char * in, size_t insize, + const LodePNGCompressSettings & settings = lodepng_default_compress_settings); /* Zlib-compress an std::vector */ -unsigned compress(std::vector& out, const std::vector& in, - const LodePNGCompressSettings& settings = lodepng_default_compress_settings); +unsigned compress(std::vector & out, const std::vector & in, + const LodePNGCompressSettings & settings = lodepng_default_compress_settings); #endif /* LODEPNG_COMPILE_ENCODER */ #endif /* LODEPNG_COMPILE_ZLIB */ } /* namespace lodepng */ @@ -1085,7 +1090,7 @@ TODO: [X] provide alternatives for C library functions not present on some platforms (memcpy, ...) */ -#endif /*LV_USE_PNG*/ +#endif /*LV_USE_LODEPNG*/ #endif /*LODEPNG_H inclusion guard*/ @@ -1175,7 +1180,7 @@ The following features are supported by the decoder: *) encoding of PNGs, from any raw image to 24- or 32-bit color, or the same color type as the raw image *) Adam7 interlace and deinterlace for any color type *) loading the image from harddisk or decoding it from a buffer from other sources than harddisk -*) support for alpha channels, including RGBA color model, translucent palettes and color keying +*) support for alpha channels, including RGBA color modelete,translucent palettes and color keying *) zlib decompression (inflate) *) zlib compression (deflate) *) CRC32 and ADLER32 checksums @@ -1772,7 +1777,7 @@ state.decoder.remember_unknown_chunks: whether to read in unknown chunks state.info_raw.colortype: desired color type for decoded image state.info_raw.bitdepth: desired bit depth for decoded image state.info_raw....: more color settings, see struct LodePNGColorMode -state.info_png....: no settings for decoder but ouput, see struct LodePNGInfo +state.info_png....: no settings for decoder but output, see struct LodePNGInfo For encoding: diff --git a/lib/libesp32_lvgl/lvgl/src/libs/lodepng/lv_lodepng.c b/lib/libesp32_lvgl/lvgl/src/libs/lodepng/lv_lodepng.c new file mode 100644 index 000000000..49a1e8825 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/lodepng/lv_lodepng.c @@ -0,0 +1,282 @@ +/** + * @file lv_lodepng.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_LODEPNG + +#include "lv_lodepng.h" +#include "lodepng.h" +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); +static void decoder_close(lv_image_decoder_t * dec, lv_image_decoder_dsc_t * dsc); +static void convert_color_depth(uint8_t * img_p, uint32_t px_cnt); +static lv_draw_buf_t * decode_png_data(const void * png_data, size_t png_data_size); +static void lodepng_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data); +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Register the PNG decoder functions in LVGL + */ +void lv_lodepng_init(void) +{ + lv_image_decoder_t * dec = lv_image_decoder_create(); + lv_image_decoder_set_info_cb(dec, decoder_info); + lv_image_decoder_set_open_cb(dec, decoder_open); + lv_image_decoder_set_close_cb(dec, decoder_close); + lv_image_decoder_set_cache_free_cb(dec, (lv_cache_free_cb_t)lodepng_decoder_cache_free_cb); +} + +void lv_lodepng_deinit(void) +{ + lv_image_decoder_t * dec = NULL; + while((dec = lv_image_decoder_get_next(dec)) != NULL) { + if(dec->info_cb == decoder_info) { + lv_image_decoder_delete(dec); + break; + } + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Get info about a PNG image + * @param decoder pointer to the decoder where this function belongs + * @param src can be file name or pointer to a C array + * @param header image information is set in header parameter + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't get the info + */ +static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) +{ + (void) decoder; /*Unused*/ + lv_image_src_t src_type = lv_image_src_get_type(src); /*Get the source type*/ + + /*If it's a PNG file...*/ + if(src_type == LV_IMAGE_SRC_FILE) { + const char * fn = src; + if(lv_strcmp(lv_fs_get_ext(fn), "png") == 0) { /*Check the extension*/ + + /* Read the width and height from the file. They have a constant location: + * [16..23]: width + * [24..27]: height + */ + uint32_t size[2]; + lv_fs_file_t f; + lv_fs_res_t res = lv_fs_open(&f, fn, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) return LV_RESULT_INVALID; + + lv_fs_seek(&f, 16, LV_FS_SEEK_SET); + + uint32_t rn; + lv_fs_read(&f, &size, 8, &rn); + lv_fs_close(&f); + + if(rn != 8) return LV_RESULT_INVALID; + + /*Save the data in the header*/ + header->cf = LV_COLOR_FORMAT_ARGB8888; + /*The width and height are stored in Big endian format so convert them to little endian*/ + header->w = (int32_t)((size[0] & 0xff000000) >> 24) + ((size[0] & 0x00ff0000) >> 8); + header->h = (int32_t)((size[1] & 0xff000000) >> 24) + ((size[1] & 0x00ff0000) >> 8); + + return LV_RESULT_OK; + } + } + /*If it's a PNG file in a C array...*/ + else if(src_type == LV_IMAGE_SRC_VARIABLE) { + const lv_image_dsc_t * img_dsc = src; + const uint32_t data_size = img_dsc->data_size; + const uint32_t * size = ((uint32_t *)img_dsc->data) + 4; + const uint8_t magic[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a}; + if(data_size < sizeof(magic)) return LV_RESULT_INVALID; + if(memcmp(magic, img_dsc->data, sizeof(magic))) return LV_RESULT_INVALID; + + header->cf = LV_COLOR_FORMAT_ARGB8888; + + if(img_dsc->header.w) { + header->w = img_dsc->header.w; /*Save the image width*/ + } + else { + header->w = (int32_t)((size[0] & 0xff000000) >> 24) + ((size[0] & 0x00ff0000) >> 8); + } + + if(img_dsc->header.h) { + header->h = img_dsc->header.h; /*Save the color height*/ + } + else { + header->h = (int32_t)((size[1] & 0xff000000) >> 24) + ((size[1] & 0x00ff0000) >> 8); + } + + return LV_RESULT_OK; + } + + return LV_RESULT_INVALID; /*If didn't succeeded earlier then it's an error*/ +} + +/** + * Open a PNG image and decode it into dsc.decoded + * @param decoder pointer to the decoder where this function belongs + * @param dsc decoded image descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image + */ +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); + + const uint8_t * png_data = NULL; + size_t png_data_size = 0; + if(dsc->src_type == LV_IMAGE_SRC_FILE) { + const char * fn = dsc->src; + if(lv_strcmp(lv_fs_get_ext(fn), "png") == 0) { /*Check the extension*/ + unsigned error; + error = lodepng_load_file((void *)&png_data, &png_data_size, fn); /*Load the file*/ + if(error) { + if(png_data != NULL) { + lv_free((void *)png_data); + } + LV_LOG_WARN("error %u: %s\n", error, lodepng_error_text(error)); + return LV_RESULT_INVALID; + } + } + } + else if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) { + const lv_image_dsc_t * img_dsc = dsc->src; + png_data = img_dsc->data; + png_data_size = img_dsc->data_size; + } + else { + return LV_RESULT_INVALID; + } + + lv_draw_buf_t * decoded = decode_png_data(png_data, png_data_size); + + if(dsc->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)png_data); + + if(!decoded) { + LV_LOG_WARN("Error decoding PNG\n"); + return LV_RESULT_INVALID; + } + + lv_draw_buf_t * adjusted = lv_image_decoder_post_process(dsc, decoded); + if(adjusted == NULL) { + lv_draw_buf_destroy(decoded); + return LV_RESULT_INVALID; + } + + /*The adjusted draw buffer is newly allocated.*/ + if(adjusted != decoded) { + lv_draw_buf_destroy(decoded); + decoded = adjusted; + } + + dsc->decoded = decoded; + + if(dsc->args.no_cache) return LV_RES_OK; + +#if LV_CACHE_DEF_SIZE > 0 + lv_image_cache_data_t search_key; + search_key.src_type = dsc->src_type; + search_key.src = dsc->src; + search_key.slot.size = decoded->data_size; + + lv_cache_entry_t * entry = lv_image_decoder_add_to_cache(decoder, &search_key, decoded, NULL); + + if(entry == NULL) { + return LV_RESULT_INVALID; + } + dsc->cache_entry = entry; +#endif + + return LV_RESULT_OK; /*If not returned earlier then it failed*/ +} + +/** + * Close PNG image and free data + * @param decoder pointer to the decoder where this function belongs + * @param dsc decoded image descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image + */ +static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); + + if(dsc->args.no_cache || LV_CACHE_DEF_SIZE == 0) + lv_draw_buf_destroy((lv_draw_buf_t *)dsc->decoded); + else + lv_cache_release(dsc->cache, dsc->cache_entry, NULL); +} + +static lv_draw_buf_t * decode_png_data(const void * png_data, size_t png_data_size) +{ + unsigned png_width; /*Not used, just required by the decoder*/ + unsigned png_height; /*Not used, just required by the decoder*/ + lv_draw_buf_t * decoded = NULL; + + /*Decode the image in ARGB8888 */ + unsigned error = lodepng_decode32((unsigned char **)&decoded, &png_width, &png_height, png_data, png_data_size); + if(error) { + if(decoded != NULL) lv_draw_buf_destroy(decoded); + return NULL; + } + + /*Convert the image to the system's color depth*/ + convert_color_depth(decoded->data, png_width * png_height); + + return decoded; +} + +/** + * If the display is not in 32 bit format (ARGB888) then convert the image to the current color depth + * @param img the ARGB888 image + * @param px_cnt number of pixels in `img` + */ +static void convert_color_depth(uint8_t * img_p, uint32_t px_cnt) +{ + lv_color32_t * img_argb = (lv_color32_t *)img_p; + uint32_t i; + for(i = 0; i < px_cnt; i++) { + uint8_t blue = img_argb[i].blue; + img_argb[i].blue = img_argb[i].red; + img_argb[i].red = blue; + } +} + +static void lodepng_decoder_cache_free_cb(lv_image_cache_data_t * cached_data, void * user_data) +{ + LV_UNUSED(user_data); + + if(cached_data->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)cached_data->src); + lv_draw_buf_destroy((lv_draw_buf_t *)cached_data->decoded); +} + +#endif /*LV_USE_LODEPNG*/ diff --git a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.h b/lib/libesp32_lvgl/lvgl/src/libs/lodepng/lv_lodepng.h similarity index 58% rename from lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.h rename to lib/libesp32_lvgl/lvgl/src/libs/lodepng/lv_lodepng.h index 413b1c949..f3dc4b771 100644 --- a/lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.h +++ b/lib/libesp32_lvgl/lvgl/src/libs/lodepng/lv_lodepng.h @@ -1,9 +1,10 @@ /** - * @file lv_draw_sdl_stack_blur.h + * @file lv_lodepng.h * */ -#ifndef LV_DRAW_SDL_STACK_BLUR_H -#define LV_DRAW_SDL_STACK_BLUR_H + +#ifndef LV_LODEPNG_H +#define LV_LODEPNG_H #ifdef __cplusplus extern "C" { @@ -12,12 +13,8 @@ extern "C" { /********************* * INCLUDES *********************/ - #include "../../lv_conf_internal.h" - -#if LV_USE_GPU_SDL - -#include "../../misc/lv_color.h" +#if LV_USE_LODEPNG /********************* * DEFINES @@ -31,16 +28,21 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ -void lv_stack_blur_grayscale(lv_opa_t * buf, uint16_t w, uint16_t h, uint16_t r); +/** + * Register the PNG decoder functions in LVGL + */ +void lv_lodepng_init(void); + +void lv_lodepng_deinit(void); /********************** * MACROS **********************/ -#endif /*LV_USE_GPU_SDL*/ +#endif /*LV_USE_LODEPNG*/ #ifdef __cplusplus -} /*extern "C"*/ +} /* extern "C" */ #endif -#endif /*LV_DRAW_SDL_STACK_BLUR_H*/ +#endif /*LV_LODEPNG_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/lz4/LICENSE b/lib/libesp32_lvgl/lvgl/src/libs/lz4/LICENSE new file mode 100644 index 000000000..488491695 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/lz4/LICENSE @@ -0,0 +1,24 @@ +LZ4 Library +Copyright (c) 2011-2020, Yann Collet +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/libesp32_lvgl/lvgl/src/libs/lz4/lz4.c b/lib/libesp32_lvgl/lvgl/src/libs/lz4/lz4.c new file mode 100644 index 000000000..145f5fbd5 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/lz4/lz4.c @@ -0,0 +1,2761 @@ +/* + LZ4 - Fast LZ compression algorithm + Copyright (C) 2011-2020, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - LZ4 homepage : http://www.lz4.org + - LZ4 source repository : https://github.com/lz4/lz4 +*/ + +#include "../../lv_conf_internal.h" +#if LV_USE_LZ4_INTERNAL + +/*-************************************ +* Tuning parameters +**************************************/ +/* + * LZ4_HEAPMODE : + * Select how stateless compression functions like `LZ4_compress_default()` + * allocate memory for their hash table, + * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()). + */ +#ifndef LZ4_HEAPMODE +# define LZ4_HEAPMODE 0 +#endif + +/* + * LZ4_ACCELERATION_DEFAULT : + * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0 + */ +#define LZ4_ACCELERATION_DEFAULT 1 +/* + * LZ4_ACCELERATION_MAX : + * Any "acceleration" value higher than this threshold + * get treated as LZ4_ACCELERATION_MAX instead (fix #876) + */ +#define LZ4_ACCELERATION_MAX 65537 + + +/*-************************************ +* CPU Feature Detection +**************************************/ +/* LZ4_FORCE_MEMORY_ACCESS + * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. + * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. + * The below switch allow to select different access method for improved performance. + * Method 0 (default) : use `memcpy()`. Safe and portable. + * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). + * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. + * Method 2 : direct access. This method is portable but violate C standard. + * It can generate buggy code on targets which assembly generation depends on alignment. + * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) + * See https://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details. + * Prefer these methods in priority order (0 > 1 > 2) + */ +#ifndef LZ4_FORCE_MEMORY_ACCESS /* can be defined externally */ +# if defined(__GNUC__) && \ + ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) \ + || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) +# define LZ4_FORCE_MEMORY_ACCESS 2 +# elif (defined(__INTEL_COMPILER) && !defined(_WIN32)) || defined(__GNUC__) || defined(_MSC_VER) +# define LZ4_FORCE_MEMORY_ACCESS 1 +# endif +#endif + +/* + * LZ4_FORCE_SW_BITCOUNT + * Define this parameter if your target system or compiler does not support hardware bit count + */ +#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for WinCE doesn't support Hardware bit count */ +# undef LZ4_FORCE_SW_BITCOUNT /* avoid double def */ +# define LZ4_FORCE_SW_BITCOUNT +#endif + + + +/*-************************************ +* Dependency +**************************************/ +/* + * LZ4_SRC_INCLUDED: + * Amalgamation flag, whether lz4.c is included + */ +#ifndef LZ4_SRC_INCLUDED +# define LZ4_SRC_INCLUDED 1 +#endif + +#ifndef LZ4_STATIC_LINKING_ONLY +#define LZ4_STATIC_LINKING_ONLY +#endif + +#ifndef LZ4_DISABLE_DEPRECATE_WARNINGS +#define LZ4_DISABLE_DEPRECATE_WARNINGS /* due to LZ4_decompress_safe_withPrefix64k */ +#endif + +#define LZ4_STATIC_LINKING_ONLY /* LZ4_DISTANCE_MAX */ +#include "lz4.h" +/* see also "memory routines" below */ + + +/*-************************************ +* Compiler Options +**************************************/ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) /* Visual Studio 2005+ */ +# include /* only present in VS2005+ */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +# pragma warning(disable : 6237) /* disable: C6237: conditional expression is always 0 */ +#endif /* _MSC_VER */ + +#ifndef LZ4_FORCE_INLINE +# ifdef _MSC_VER /* Visual Studio */ +# define LZ4_FORCE_INLINE static __forceinline +# else +# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +# ifdef __GNUC__ +# define LZ4_FORCE_INLINE static inline __attribute__((always_inline)) +# else +# define LZ4_FORCE_INLINE static inline +# endif +# else +# define LZ4_FORCE_INLINE static +# endif /* __STDC_VERSION__ */ +# endif /* _MSC_VER */ +#endif /* LZ4_FORCE_INLINE */ + +/* LZ4_FORCE_O2 and LZ4_FORCE_INLINE + * gcc on ppc64le generates an unrolled SIMDized loop for LZ4_wildCopy8, + * together with a simple 8-byte copy loop as a fall-back path. + * However, this optimization hurts the decompression speed by >30%, + * because the execution does not go to the optimized loop + * for typical compressible data, and all of the preamble checks + * before going to the fall-back path become useless overhead. + * This optimization happens only with the -O3 flag, and -O2 generates + * a simple 8-byte copy loop. + * With gcc on ppc64le, all of the LZ4_decompress_* and LZ4_wildCopy8 + * functions are annotated with __attribute__((optimize("O2"))), + * and also LZ4_wildCopy8 is forcibly inlined, so that the O2 attribute + * of LZ4_wildCopy8 does not affect the compression speed. + */ +#if defined(__PPC64__) && defined(__LITTLE_ENDIAN__) && defined(__GNUC__) && !defined(__clang__) +# define LZ4_FORCE_O2 __attribute__((optimize("O2"))) +# undef LZ4_FORCE_INLINE +# define LZ4_FORCE_INLINE static __inline __attribute__((optimize("O2"),always_inline)) +#else +# define LZ4_FORCE_O2 +#endif + +#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__) +# define expect(expr,value) (__builtin_expect ((expr),(value)) ) +#else +# define expect(expr,value) (expr) +#endif + +#ifndef likely +#define likely(expr) expect((expr) != 0, 1) +#endif +#ifndef unlikely +#define unlikely(expr) expect((expr) != 0, 0) +#endif + +/* Should the alignment test prove unreliable, for some reason, + * it can be disabled by setting LZ4_ALIGN_TEST to 0 */ +#ifndef LZ4_ALIGN_TEST /* can be externally provided */ +# define LZ4_ALIGN_TEST 1 +#endif + + +/*-************************************ +* Memory routines +**************************************/ + +/*! LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION : + * Disable relatively high-level LZ4/HC functions that use dynamic memory + * allocation functions (malloc(), calloc(), free()). + * + * Note that this is a compile-time switch. And since it disables + * public/stable LZ4 v1 API functions, we don't recommend using this + * symbol to generate a library for distribution. + * + * The following public functions are removed when this symbol is defined. + * - lz4 : LZ4_createStream, LZ4_freeStream, + * LZ4_createStreamDecode, LZ4_freeStreamDecode, LZ4_create (deprecated) + * - lz4hc : LZ4_createStreamHC, LZ4_freeStreamHC, + * LZ4_createHC (deprecated), LZ4_freeHC (deprecated) + * - lz4frame, lz4file : All LZ4F_* functions + */ +#if defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) +# define ALLOC(s) lz4_error_memory_allocation_is_disabled +# define ALLOC_AND_ZERO(s) lz4_error_memory_allocation_is_disabled +# define FREEMEM(p) lz4_error_memory_allocation_is_disabled +#elif defined(LZ4_USER_MEMORY_FUNCTIONS) +/* memory management functions can be customized by user project. + * Below functions must exist somewhere in the Project + * and be available at link time */ +void* LZ4_malloc(size_t s); +void* LZ4_calloc(size_t n, size_t s); +void LZ4_free(void* p); +# define ALLOC(s) LZ4_malloc(s) +# define ALLOC_AND_ZERO(s) LZ4_calloc(1,s) +# define FREEMEM(p) LZ4_free(p) +#else +# include /* malloc, calloc, free */ +# define ALLOC(s) malloc(s) +# define ALLOC_AND_ZERO(s) calloc(1,s) +# define FREEMEM(p) free(p) +#endif + +#if ! LZ4_FREESTANDING +# include /* memset, memcpy */ +#endif +#if !defined(LZ4_memset) +# define LZ4_memset(p,v,s) memset((p),(v),(s)) +#endif +#define MEM_INIT(p,v,s) LZ4_memset((p),(v),(s)) + + +/*-************************************ +* Common Constants +**************************************/ +#define MINMATCH 4 + +#define WILDCOPYLENGTH 8 +#define LASTLITERALS 5 /* see ../doc/lz4_Block_format.md#parsing-restrictions */ +#define MFLIMIT 12 /* see ../doc/lz4_Block_format.md#parsing-restrictions */ +#define MATCH_SAFEGUARD_DISTANCE ((2*WILDCOPYLENGTH) - MINMATCH) /* ensure it's possible to write 2 x wildcopyLength without overflowing output buffer */ +#define FASTLOOP_SAFE_DISTANCE 64 +static const int LZ4_minLength = (MFLIMIT+1); + +#define KB *(1 <<10) +#define MB *(1 <<20) +#define GB *(1U<<30) + +#define LZ4_DISTANCE_ABSOLUTE_MAX 65535 +#if (LZ4_DISTANCE_MAX > LZ4_DISTANCE_ABSOLUTE_MAX) /* max supported by LZ4 format */ +# error "LZ4_DISTANCE_MAX is too big : must be <= 65535" +#endif + +#define ML_BITS 4 +#define ML_MASK ((1U<=1) +# include +#else +# ifndef assert +# define assert(condition) ((void)0) +# endif +#endif + +#define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use after variable declarations */ + +#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=2) +# include + static int g_debuglog_enable = 1; +# define DEBUGLOG(l, ...) { \ + if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) { \ + fprintf(stderr, __FILE__ " %i: ", __LINE__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, " \n"); \ + } } +#else +# define DEBUGLOG(l, ...) {} /* disabled */ +#endif + +static int LZ4_isAligned(const void* ptr, size_t alignment) +{ + return ((size_t)ptr & (alignment -1)) == 0; +} + + +/*-************************************ +* Types +**************************************/ +#include +#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# include + typedef uint8_t BYTE; + typedef uint16_t U16; + typedef uint32_t U32; + typedef int32_t S32; + typedef uint64_t U64; + typedef uintptr_t uptrval; +#else +# if UINT_MAX != 4294967295UL +# error "LZ4 code (when not C++ or C99) assumes that sizeof(int) == 4" +# endif + typedef unsigned char BYTE; + typedef unsigned short U16; + typedef unsigned int U32; + typedef signed int S32; + typedef unsigned long long U64; + typedef size_t uptrval; /* generally true, except OpenVMS-64 */ +#endif + +#if defined(__x86_64__) + typedef U64 reg_t; /* 64-bits in x32 mode */ +#else + typedef size_t reg_t; /* 32-bits in x32 mode */ +#endif + +typedef enum { + notLimited = 0, + limitedOutput = 1, + fillOutput = 2 +} limitedOutput_directive; + + +/*-************************************ +* Reading and writing into memory +**************************************/ + +/** + * LZ4 relies on memcpy with a constant size being inlined. In freestanding + * environments, the compiler can't assume the implementation of memcpy() is + * standard compliant, so it can't apply its specialized memcpy() inlining + * logic. When possible, use __builtin_memcpy() to tell the compiler to analyze + * memcpy() as if it were standard compliant, so it can inline it in freestanding + * environments. This is needed when decompressing the Linux Kernel, for example. + */ +#if !defined(LZ4_memcpy) +# if defined(__GNUC__) && (__GNUC__ >= 4) +# define LZ4_memcpy(dst, src, size) __builtin_memcpy(dst, src, size) +# else +# define LZ4_memcpy(dst, src, size) memcpy(dst, src, size) +# endif +#endif + +#if !defined(LZ4_memmove) +# if defined(__GNUC__) && (__GNUC__ >= 4) +# define LZ4_memmove __builtin_memmove +# else +# define LZ4_memmove memmove +# endif +#endif + +static unsigned LZ4_isLittleEndian(void) +{ + const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ + return one.c[0]; +} + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) +#define LZ4_PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) +#elif defined(_MSC_VER) +#define LZ4_PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop)) +#endif + +#if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2) +/* lie to the compiler about data alignment; use with caution */ + +static U16 LZ4_read16(const void* memPtr) { return *(const U16*) memPtr; } +static U32 LZ4_read32(const void* memPtr) { return *(const U32*) memPtr; } +static reg_t LZ4_read_ARCH(const void* memPtr) { return *(const reg_t*) memPtr; } + +static void LZ4_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; } +static void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; } + +#elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==1) + +/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ +/* currently only defined for gcc and icc */ +LZ4_PACK(typedef struct { U16 u16; }) LZ4_unalign16; +LZ4_PACK(typedef struct { U32 u32; }) LZ4_unalign32; +LZ4_PACK(typedef struct { reg_t uArch; }) LZ4_unalignST; + +static U16 LZ4_read16(const void* ptr) { return ((const LZ4_unalign16*)ptr)->u16; } +static U32 LZ4_read32(const void* ptr) { return ((const LZ4_unalign32*)ptr)->u32; } +static reg_t LZ4_read_ARCH(const void* ptr) { return ((const LZ4_unalignST*)ptr)->uArch; } + +static void LZ4_write16(void* memPtr, U16 value) { ((LZ4_unalign16*)memPtr)->u16 = value; } +static void LZ4_write32(void* memPtr, U32 value) { ((LZ4_unalign32*)memPtr)->u32 = value; } + +#else /* safe and portable access using memcpy() */ + +static U16 LZ4_read16(const void* memPtr) +{ + U16 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val; +} + +static U32 LZ4_read32(const void* memPtr) +{ + U32 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val; +} + +static reg_t LZ4_read_ARCH(const void* memPtr) +{ + reg_t val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val; +} + +static void LZ4_write16(void* memPtr, U16 value) +{ + LZ4_memcpy(memPtr, &value, sizeof(value)); +} + +static void LZ4_write32(void* memPtr, U32 value) +{ + LZ4_memcpy(memPtr, &value, sizeof(value)); +} + +#endif /* LZ4_FORCE_MEMORY_ACCESS */ + + +static U16 LZ4_readLE16(const void* memPtr) +{ + if (LZ4_isLittleEndian()) { + return LZ4_read16(memPtr); + } else { + const BYTE* p = (const BYTE*)memPtr; + return (U16)((U16)p[0] + (p[1]<<8)); + } +} + +static void LZ4_writeLE16(void* memPtr, U16 value) +{ + if (LZ4_isLittleEndian()) { + LZ4_write16(memPtr, value); + } else { + BYTE* p = (BYTE*)memPtr; + p[0] = (BYTE) value; + p[1] = (BYTE)(value>>8); + } +} + +/* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */ +LZ4_FORCE_INLINE +void LZ4_wildCopy8(void* dstPtr, const void* srcPtr, void* dstEnd) +{ + BYTE* d = (BYTE*)dstPtr; + const BYTE* s = (const BYTE*)srcPtr; + BYTE* const e = (BYTE*)dstEnd; + + do { LZ4_memcpy(d,s,8); d+=8; s+=8; } while (d= 16. */ +LZ4_FORCE_INLINE void +LZ4_wildCopy32(void* dstPtr, const void* srcPtr, void* dstEnd) +{ + BYTE* d = (BYTE*)dstPtr; + const BYTE* s = (const BYTE*)srcPtr; + BYTE* const e = (BYTE*)dstEnd; + + do { LZ4_memcpy(d,s,16); LZ4_memcpy(d+16,s+16,16); d+=32; s+=32; } while (d= dstPtr + MINMATCH + * - there is at least 8 bytes available to write after dstEnd */ +LZ4_FORCE_INLINE void +LZ4_memcpy_using_offset(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const size_t offset) +{ + BYTE v[8]; + + assert(dstEnd >= dstPtr + MINMATCH); + + switch(offset) { + case 1: + MEM_INIT(v, *srcPtr, 8); + break; + case 2: + LZ4_memcpy(v, srcPtr, 2); + LZ4_memcpy(&v[2], srcPtr, 2); +#if defined(_MSC_VER) && (_MSC_VER <= 1937) /* MSVC 2022 ver 17.7 or earlier */ +# pragma warning(push) +# pragma warning(disable : 6385) /* warning C6385: Reading invalid data from 'v'. */ +#endif + LZ4_memcpy(&v[4], v, 4); +#if defined(_MSC_VER) && (_MSC_VER <= 1937) /* MSVC 2022 ver 17.7 or earlier */ +# pragma warning(pop) +#endif + break; + case 4: + LZ4_memcpy(v, srcPtr, 4); + LZ4_memcpy(&v[4], srcPtr, 4); + break; + default: + LZ4_memcpy_using_offset_base(dstPtr, srcPtr, dstEnd, offset); + return; + } + + LZ4_memcpy(dstPtr, v, 8); + dstPtr += 8; + while (dstPtr < dstEnd) { + LZ4_memcpy(dstPtr, v, 8); + dstPtr += 8; + } +} +#endif + + +/*-************************************ +* Common functions +**************************************/ +static unsigned LZ4_NbCommonBytes (reg_t val) +{ + assert(val != 0); + if (LZ4_isLittleEndian()) { + if (sizeof(val) == 8) { +# if defined(_MSC_VER) && (_MSC_VER >= 1800) && (defined(_M_AMD64) && !defined(_M_ARM64EC)) && !defined(LZ4_FORCE_SW_BITCOUNT) +/*-************************************************************************************************* +* ARM64EC is a Microsoft-designed ARM64 ABI compatible with AMD64 applications on ARM64 Windows 11. +* The ARM64EC ABI does not support AVX/AVX2/AVX512 instructions, nor their relevant intrinsics +* including _tzcnt_u64. Therefore, we need to neuter the _tzcnt_u64 code path for ARM64EC. +****************************************************************************************************/ +# if defined(__clang__) && (__clang_major__ < 10) + /* Avoid undefined clang-cl intrinsics issue. + * See https://github.com/lz4/lz4/pull/1017 for details. */ + return (unsigned)__builtin_ia32_tzcnt_u64(val) >> 3; +# else + /* x64 CPUS without BMI support interpret `TZCNT` as `REP BSF` */ + return (unsigned)_tzcnt_u64(val) >> 3; +# endif +# elif defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanForward64(&r, (U64)val); + return (unsigned)r >> 3; +# elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \ + ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \ + !defined(LZ4_FORCE_SW_BITCOUNT) + return (unsigned)__builtin_ctzll((U64)val) >> 3; +# else + const U64 m = 0x0101010101010101ULL; + val ^= val - 1; + return (unsigned)(((U64)((val & (m - 1)) * m)) >> 56); +# endif + } else /* 32 bits */ { +# if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r; + _BitScanForward(&r, (U32)val); + return (unsigned)r >> 3; +# elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \ + ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \ + !defined(__TINYC__) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (unsigned)__builtin_ctz((U32)val) >> 3; +# else + const U32 m = 0x01010101; + return (unsigned)((((val - 1) ^ val) & (m - 1)) * m) >> 24; +# endif + } + } else /* Big Endian CPU */ { + if (sizeof(val)==8) { +# if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \ + ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \ + !defined(__TINYC__) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (unsigned)__builtin_clzll((U64)val) >> 3; +# else +#if 1 + /* this method is probably faster, + * but adds a 128 bytes lookup table */ + static const unsigned char ctz7_tab[128] = { + 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + }; + U64 const mask = 0x0101010101010101ULL; + U64 const t = (((val >> 8) - mask) | val) & mask; + return ctz7_tab[(t * 0x0080402010080402ULL) >> 57]; +#else + /* this method doesn't consume memory space like the previous one, + * but it contains several branches, + * that may end up slowing execution */ + static const U32 by32 = sizeof(val)*4; /* 32 on 64 bits (goal), 16 on 32 bits. + Just to avoid some static analyzer complaining about shift by 32 on 32-bits target. + Note that this code path is never triggered in 32-bits mode. */ + unsigned r; + if (!(val>>by32)) { r=4; } else { r=0; val>>=by32; } + if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } + r += (!val); + return r; +#endif +# endif + } else /* 32 bits */ { +# if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \ + ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \ + !defined(LZ4_FORCE_SW_BITCOUNT) + return (unsigned)__builtin_clz((U32)val) >> 3; +# else + val >>= 8; + val = ((((val + 0x00FFFF00) | 0x00FFFFFF) + val) | + (val + 0x00FF0000)) >> 24; + return (unsigned)val ^ 3; +# endif + } + } +} + + +#define STEPSIZE sizeof(reg_t) +LZ4_FORCE_INLINE +unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit) +{ + const BYTE* const pStart = pIn; + + if (likely(pIn < pInLimit-(STEPSIZE-1))) { + reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); + if (!diff) { + pIn+=STEPSIZE; pMatch+=STEPSIZE; + } else { + return LZ4_NbCommonBytes(diff); + } } + + while (likely(pIn < pInLimit-(STEPSIZE-1))) { + reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); + if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; } + pIn += LZ4_NbCommonBytes(diff); + return (unsigned)(pIn - pStart); + } + + if ((STEPSIZE==8) && (pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; } + if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; } + if ((pIn compression run slower on incompressible data */ + + +/*-************************************ +* Local Structures and types +**************************************/ +typedef enum { clearedTable = 0, byPtr, byU32, byU16 } tableType_t; + +/** + * This enum distinguishes several different modes of accessing previous + * content in the stream. + * + * - noDict : There is no preceding content. + * - withPrefix64k : Table entries up to ctx->dictSize before the current blob + * blob being compressed are valid and refer to the preceding + * content (of length ctx->dictSize), which is available + * contiguously preceding in memory the content currently + * being compressed. + * - usingExtDict : Like withPrefix64k, but the preceding content is somewhere + * else in memory, starting at ctx->dictionary with length + * ctx->dictSize. + * - usingDictCtx : Everything concerning the preceding content is + * in a separate context, pointed to by ctx->dictCtx. + * ctx->dictionary, ctx->dictSize, and table entries + * in the current context that refer to positions + * preceding the beginning of the current compression are + * ignored. Instead, ctx->dictCtx->dictionary and ctx->dictCtx + * ->dictSize describe the location and size of the preceding + * content, and matches are found by looking in the ctx + * ->dictCtx->hashTable. + */ +typedef enum { noDict = 0, withPrefix64k, usingExtDict, usingDictCtx } dict_directive; +typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive; + + +/*-************************************ +* Local Utils +**************************************/ +int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; } +const char* LZ4_versionString(void) { return LZ4_VERSION_STRING; } +int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); } +int LZ4_sizeofState(void) { return sizeof(LZ4_stream_t); } + + +/*-**************************************** +* Internal Definitions, used only in Tests +*******************************************/ +#if defined (__cplusplus) +extern "C" { +#endif + +int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int srcSize); + +int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, + int compressedSize, int maxOutputSize, + const void* dictStart, size_t dictSize); +int LZ4_decompress_safe_partial_forceExtDict(const char* source, char* dest, + int compressedSize, int targetOutputSize, int dstCapacity, + const void* dictStart, size_t dictSize); +#if defined (__cplusplus) +} +#endif + +/*-****************************** +* Compression functions +********************************/ +LZ4_FORCE_INLINE U32 LZ4_hash4(U32 sequence, tableType_t const tableType) +{ + if (tableType == byU16) + return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1))); + else + return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); +} + +LZ4_FORCE_INLINE U32 LZ4_hash5(U64 sequence, tableType_t const tableType) +{ + const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG; + if (LZ4_isLittleEndian()) { + const U64 prime5bytes = 889523592379ULL; + return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog)); + } else { + const U64 prime8bytes = 11400714785074694791ULL; + return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog)); + } +} + +LZ4_FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType) +{ + if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType); + return LZ4_hash4(LZ4_read32(p), tableType); +} + +LZ4_FORCE_INLINE void LZ4_clearHash(U32 h, void* tableBase, tableType_t const tableType) +{ + switch (tableType) + { + default: /* fallthrough */ + case clearedTable: { /* illegal! */ assert(0); return; } + case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = NULL; return; } + case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = 0; return; } + case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = 0; return; } + } +} + +LZ4_FORCE_INLINE void LZ4_putIndexOnHash(U32 idx, U32 h, void* tableBase, tableType_t const tableType) +{ + switch (tableType) + { + default: /* fallthrough */ + case clearedTable: /* fallthrough */ + case byPtr: { /* illegal! */ assert(0); return; } + case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = idx; return; } + case byU16: { U16* hashTable = (U16*) tableBase; assert(idx < 65536); hashTable[h] = (U16)idx; return; } + } +} + +/* LZ4_putPosition*() : only used in byPtr mode */ +LZ4_FORCE_INLINE void LZ4_putPositionOnHash(const BYTE* p, U32 h, + void* tableBase, tableType_t const tableType) +{ + const BYTE** const hashTable = (const BYTE**)tableBase; + assert(tableType == byPtr); (void)tableType; + hashTable[h] = p; +} + +LZ4_FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType) +{ + U32 const h = LZ4_hashPosition(p, tableType); + LZ4_putPositionOnHash(p, h, tableBase, tableType); +} + +/* LZ4_getIndexOnHash() : + * Index of match position registered in hash table. + * hash position must be calculated by using base+index, or dictBase+index. + * Assumption 1 : only valid if tableType == byU32 or byU16. + * Assumption 2 : h is presumed valid (within limits of hash table) + */ +LZ4_FORCE_INLINE U32 LZ4_getIndexOnHash(U32 h, const void* tableBase, tableType_t tableType) +{ + LZ4_STATIC_ASSERT(LZ4_MEMORY_USAGE > 2); + if (tableType == byU32) { + const U32* const hashTable = (const U32*) tableBase; + assert(h < (1U << (LZ4_MEMORY_USAGE-2))); + return hashTable[h]; + } + if (tableType == byU16) { + const U16* const hashTable = (const U16*) tableBase; + assert(h < (1U << (LZ4_MEMORY_USAGE-1))); + return hashTable[h]; + } + assert(0); return 0; /* forbidden case */ +} + +static const BYTE* LZ4_getPositionOnHash(U32 h, const void* tableBase, tableType_t tableType) +{ + assert(tableType == byPtr); (void)tableType; + { const BYTE* const* hashTable = (const BYTE* const*) tableBase; return hashTable[h]; } +} + +LZ4_FORCE_INLINE const BYTE* +LZ4_getPosition(const BYTE* p, + const void* tableBase, tableType_t tableType) +{ + U32 const h = LZ4_hashPosition(p, tableType); + return LZ4_getPositionOnHash(h, tableBase, tableType); +} + +LZ4_FORCE_INLINE void +LZ4_prepareTable(LZ4_stream_t_internal* const cctx, + const int inputSize, + const tableType_t tableType) { + /* If the table hasn't been used, it's guaranteed to be zeroed out, and is + * therefore safe to use no matter what mode we're in. Otherwise, we figure + * out if it's safe to leave as is or whether it needs to be reset. + */ + if ((tableType_t)cctx->tableType != clearedTable) { + assert(inputSize >= 0); + if ((tableType_t)cctx->tableType != tableType + || ((tableType == byU16) && cctx->currentOffset + (unsigned)inputSize >= 0xFFFFU) + || ((tableType == byU32) && cctx->currentOffset > 1 GB) + || tableType == byPtr + || inputSize >= 4 KB) + { + DEBUGLOG(4, "LZ4_prepareTable: Resetting table in %p", cctx); + MEM_INIT(cctx->hashTable, 0, LZ4_HASHTABLESIZE); + cctx->currentOffset = 0; + cctx->tableType = (U32)clearedTable; + } else { + DEBUGLOG(4, "LZ4_prepareTable: Re-use hash table (no reset)"); + } + } + + /* Adding a gap, so all previous entries are > LZ4_DISTANCE_MAX back, + * is faster than compressing without a gap. + * However, compressing with currentOffset == 0 is faster still, + * so we preserve that case. + */ + if (cctx->currentOffset != 0 && tableType == byU32) { + DEBUGLOG(5, "LZ4_prepareTable: adding 64KB to currentOffset"); + cctx->currentOffset += 64 KB; + } + + /* Finally, clear history */ + cctx->dictCtx = NULL; + cctx->dictionary = NULL; + cctx->dictSize = 0; +} + +/** LZ4_compress_generic_validated() : + * inlined, to ensure branches are decided at compilation time. + * The following conditions are presumed already validated: + * - source != NULL + * - inputSize > 0 + */ +LZ4_FORCE_INLINE int LZ4_compress_generic_validated( + LZ4_stream_t_internal* const cctx, + const char* const source, + char* const dest, + const int inputSize, + int* inputConsumed, /* only written when outputDirective == fillOutput */ + const int maxOutputSize, + const limitedOutput_directive outputDirective, + const tableType_t tableType, + const dict_directive dictDirective, + const dictIssue_directive dictIssue, + const int acceleration) +{ + int result; + const BYTE* ip = (const BYTE*)source; + + U32 const startIndex = cctx->currentOffset; + const BYTE* base = (const BYTE*)source - startIndex; + const BYTE* lowLimit; + + const LZ4_stream_t_internal* dictCtx = (const LZ4_stream_t_internal*) cctx->dictCtx; + const BYTE* const dictionary = + dictDirective == usingDictCtx ? dictCtx->dictionary : cctx->dictionary; + const U32 dictSize = + dictDirective == usingDictCtx ? dictCtx->dictSize : cctx->dictSize; + const U32 dictDelta = + (dictDirective == usingDictCtx) ? startIndex - dictCtx->currentOffset : 0; /* make indexes in dictCtx comparable with indexes in current context */ + + int const maybe_extMem = (dictDirective == usingExtDict) || (dictDirective == usingDictCtx); + U32 const prefixIdxLimit = startIndex - dictSize; /* used when dictDirective == dictSmall */ + const BYTE* const dictEnd = dictionary ? dictionary + dictSize : dictionary; + const BYTE* anchor = (const BYTE*) source; + const BYTE* const iend = ip + inputSize; + const BYTE* const mflimitPlusOne = iend - MFLIMIT + 1; + const BYTE* const matchlimit = iend - LASTLITERALS; + + /* the dictCtx currentOffset is indexed on the start of the dictionary, + * while a dictionary in the current context precedes the currentOffset */ + const BYTE* dictBase = (dictionary == NULL) ? NULL : + (dictDirective == usingDictCtx) ? + dictionary + dictSize - dictCtx->currentOffset : + dictionary + dictSize - startIndex; + + BYTE* op = (BYTE*) dest; + BYTE* const olimit = op + maxOutputSize; + + U32 offset = 0; + U32 forwardH; + + DEBUGLOG(5, "LZ4_compress_generic_validated: srcSize=%i, tableType=%u", inputSize, tableType); + assert(ip != NULL); + if (tableType == byU16) assert(inputSize= 1); + + lowLimit = (const BYTE*)source - (dictDirective == withPrefix64k ? dictSize : 0); + + /* Update context state */ + if (dictDirective == usingDictCtx) { + /* Subsequent linked blocks can't use the dictionary. */ + /* Instead, they use the block we just compressed. */ + cctx->dictCtx = NULL; + cctx->dictSize = (U32)inputSize; + } else { + cctx->dictSize += (U32)inputSize; + } + cctx->currentOffset += (U32)inputSize; + cctx->tableType = (U32)tableType; + + if (inputSizehashTable, byPtr); + } else { + LZ4_putIndexOnHash(startIndex, h, cctx->hashTable, tableType); + } } + ip++; forwardH = LZ4_hashPosition(ip, tableType); + + /* Main Loop */ + for ( ; ; ) { + const BYTE* match; + BYTE* token; + const BYTE* filledIp; + + /* Find a match */ + if (tableType == byPtr) { + const BYTE* forwardIp = ip; + int step = 1; + int searchMatchNb = acceleration << LZ4_skipTrigger; + do { + U32 const h = forwardH; + ip = forwardIp; + forwardIp += step; + step = (searchMatchNb++ >> LZ4_skipTrigger); + + if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals; + assert(ip < mflimitPlusOne); + + match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType); + forwardH = LZ4_hashPosition(forwardIp, tableType); + LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType); + + } while ( (match+LZ4_DISTANCE_MAX < ip) + || (LZ4_read32(match) != LZ4_read32(ip)) ); + + } else { /* byU32, byU16 */ + + const BYTE* forwardIp = ip; + int step = 1; + int searchMatchNb = acceleration << LZ4_skipTrigger; + do { + U32 const h = forwardH; + U32 const current = (U32)(forwardIp - base); + U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType); + assert(matchIndex <= current); + assert(forwardIp - base < (ptrdiff_t)(2 GB - 1)); + ip = forwardIp; + forwardIp += step; + step = (searchMatchNb++ >> LZ4_skipTrigger); + + if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals; + assert(ip < mflimitPlusOne); + + if (dictDirective == usingDictCtx) { + if (matchIndex < startIndex) { + /* there was no match, try the dictionary */ + assert(tableType == byU32); + matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32); + match = dictBase + matchIndex; + matchIndex += dictDelta; /* make dictCtx index comparable with current context */ + lowLimit = dictionary; + } else { + match = base + matchIndex; + lowLimit = (const BYTE*)source; + } + } else if (dictDirective == usingExtDict) { + if (matchIndex < startIndex) { + DEBUGLOG(7, "extDict candidate: matchIndex=%5u < startIndex=%5u", matchIndex, startIndex); + assert(startIndex - matchIndex >= MINMATCH); + assert(dictBase); + match = dictBase + matchIndex; + lowLimit = dictionary; + } else { + match = base + matchIndex; + lowLimit = (const BYTE*)source; + } + } else { /* single continuous memory segment */ + match = base + matchIndex; + } + forwardH = LZ4_hashPosition(forwardIp, tableType); + LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType); + + DEBUGLOG(7, "candidate at pos=%u (offset=%u \n", matchIndex, current - matchIndex); + if ((dictIssue == dictSmall) && (matchIndex < prefixIdxLimit)) { continue; } /* match outside of valid area */ + assert(matchIndex < current); + if ( ((tableType != byU16) || (LZ4_DISTANCE_MAX < LZ4_DISTANCE_ABSOLUTE_MAX)) + && (matchIndex+LZ4_DISTANCE_MAX < current)) { + continue; + } /* too far */ + assert((current - matchIndex) <= LZ4_DISTANCE_MAX); /* match now expected within distance */ + + if (LZ4_read32(match) == LZ4_read32(ip)) { + if (maybe_extMem) offset = current - matchIndex; + break; /* match found */ + } + + } while(1); + } + + /* Catch up */ + filledIp = ip; + assert(ip > anchor); /* this is always true as ip has been advanced before entering the main loop */ + if ((match > lowLimit) && unlikely(ip[-1] == match[-1])) { + do { ip--; match--; } while (((ip > anchor) & (match > lowLimit)) && (unlikely(ip[-1] == match[-1]))); + } + + /* Encode Literals */ + { unsigned const litLength = (unsigned)(ip - anchor); + token = op++; + if ((outputDirective == limitedOutput) && /* Check output buffer overflow */ + (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)) ) { + return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */ + } + if ((outputDirective == fillOutput) && + (unlikely(op + (litLength+240)/255 /* litlen */ + litLength /* literals */ + 2 /* offset */ + 1 /* token */ + MFLIMIT - MINMATCH /* min last literals so last match is <= end - MFLIMIT */ > olimit))) { + op--; + goto _last_literals; + } + if (litLength >= RUN_MASK) { + int len = (int)(litLength - RUN_MASK); + *token = (RUN_MASK<= 255 ; len-=255) *op++ = 255; + *op++ = (BYTE)len; + } + else *token = (BYTE)(litLength< olimit)) { + /* the match was too close to the end, rewind and go to last literals */ + op = token; + goto _last_literals; + } + + /* Encode Offset */ + if (maybe_extMem) { /* static test */ + DEBUGLOG(6, " with offset=%u (ext if > %i)", offset, (int)(ip - (const BYTE*)source)); + assert(offset <= LZ4_DISTANCE_MAX && offset > 0); + LZ4_writeLE16(op, (U16)offset); op+=2; + } else { + DEBUGLOG(6, " with offset=%u (same segment)", (U32)(ip - match)); + assert(ip-match <= LZ4_DISTANCE_MAX); + LZ4_writeLE16(op, (U16)(ip - match)); op+=2; + } + + /* Encode MatchLength */ + { unsigned matchCode; + + if ( (dictDirective==usingExtDict || dictDirective==usingDictCtx) + && (lowLimit==dictionary) /* match within extDict */ ) { + const BYTE* limit = ip + (dictEnd-match); + assert(dictEnd > match); + if (limit > matchlimit) limit = matchlimit; + matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit); + ip += (size_t)matchCode + MINMATCH; + if (ip==limit) { + unsigned const more = LZ4_count(limit, (const BYTE*)source, matchlimit); + matchCode += more; + ip += more; + } + DEBUGLOG(6, " with matchLength=%u starting in extDict", matchCode+MINMATCH); + } else { + matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); + ip += (size_t)matchCode + MINMATCH; + DEBUGLOG(6, " with matchLength=%u", matchCode+MINMATCH); + } + + if ((outputDirective) && /* Check output buffer overflow */ + (unlikely(op + (1 + LASTLITERALS) + (matchCode+240)/255 > olimit)) ) { + if (outputDirective == fillOutput) { + /* Match description too long : reduce it */ + U32 newMatchCode = 15 /* in token */ - 1 /* to avoid needing a zero byte */ + ((U32)(olimit - op) - 1 - LASTLITERALS) * 255; + ip -= matchCode - newMatchCode; + assert(newMatchCode < matchCode); + matchCode = newMatchCode; + if (unlikely(ip <= filledIp)) { + /* We have already filled up to filledIp so if ip ends up less than filledIp + * we have positions in the hash table beyond the current position. This is + * a problem if we reuse the hash table. So we have to remove these positions + * from the hash table. + */ + const BYTE* ptr; + DEBUGLOG(5, "Clearing %u positions", (U32)(filledIp - ip)); + for (ptr = ip; ptr <= filledIp; ++ptr) { + U32 const h = LZ4_hashPosition(ptr, tableType); + LZ4_clearHash(h, cctx->hashTable, tableType); + } + } + } else { + assert(outputDirective == limitedOutput); + return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */ + } + } + if (matchCode >= ML_MASK) { + *token += ML_MASK; + matchCode -= ML_MASK; + LZ4_write32(op, 0xFFFFFFFF); + while (matchCode >= 4*255) { + op+=4; + LZ4_write32(op, 0xFFFFFFFF); + matchCode -= 4*255; + } + op += matchCode / 255; + *op++ = (BYTE)(matchCode % 255); + } else + *token += (BYTE)(matchCode); + } + /* Ensure we have enough space for the last literals. */ + assert(!(outputDirective == fillOutput && op + 1 + LASTLITERALS > olimit)); + + anchor = ip; + + /* Test end of chunk */ + if (ip >= mflimitPlusOne) break; + + /* Fill table */ + { U32 const h = LZ4_hashPosition(ip-2, tableType); + if (tableType == byPtr) { + LZ4_putPositionOnHash(ip-2, h, cctx->hashTable, byPtr); + } else { + U32 const idx = (U32)((ip-2) - base); + LZ4_putIndexOnHash(idx, h, cctx->hashTable, tableType); + } } + + /* Test next position */ + if (tableType == byPtr) { + + match = LZ4_getPosition(ip, cctx->hashTable, tableType); + LZ4_putPosition(ip, cctx->hashTable, tableType); + if ( (match+LZ4_DISTANCE_MAX >= ip) + && (LZ4_read32(match) == LZ4_read32(ip)) ) + { token=op++; *token=0; goto _next_match; } + + } else { /* byU32, byU16 */ + + U32 const h = LZ4_hashPosition(ip, tableType); + U32 const current = (U32)(ip-base); + U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType); + assert(matchIndex < current); + if (dictDirective == usingDictCtx) { + if (matchIndex < startIndex) { + /* there was no match, try the dictionary */ + assert(tableType == byU32); + matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32); + match = dictBase + matchIndex; + lowLimit = dictionary; /* required for match length counter */ + matchIndex += dictDelta; + } else { + match = base + matchIndex; + lowLimit = (const BYTE*)source; /* required for match length counter */ + } + } else if (dictDirective==usingExtDict) { + if (matchIndex < startIndex) { + assert(dictBase); + match = dictBase + matchIndex; + lowLimit = dictionary; /* required for match length counter */ + } else { + match = base + matchIndex; + lowLimit = (const BYTE*)source; /* required for match length counter */ + } + } else { /* single memory segment */ + match = base + matchIndex; + } + LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType); + assert(matchIndex < current); + if ( ((dictIssue==dictSmall) ? (matchIndex >= prefixIdxLimit) : 1) + && (((tableType==byU16) && (LZ4_DISTANCE_MAX == LZ4_DISTANCE_ABSOLUTE_MAX)) ? 1 : (matchIndex+LZ4_DISTANCE_MAX >= current)) + && (LZ4_read32(match) == LZ4_read32(ip)) ) { + token=op++; + *token=0; + if (maybe_extMem) offset = current - matchIndex; + DEBUGLOG(6, "seq.start:%i, literals=%u, match.start:%i", + (int)(anchor-(const BYTE*)source), 0, (int)(ip-(const BYTE*)source)); + goto _next_match; + } + } + + /* Prepare next loop */ + forwardH = LZ4_hashPosition(++ip, tableType); + + } + +_last_literals: + /* Encode Last Literals */ + { size_t lastRun = (size_t)(iend - anchor); + if ( (outputDirective) && /* Check output buffer overflow */ + (op + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > olimit)) { + if (outputDirective == fillOutput) { + /* adapt lastRun to fill 'dst' */ + assert(olimit >= op); + lastRun = (size_t)(olimit-op) - 1/*token*/; + lastRun -= (lastRun + 256 - RUN_MASK) / 256; /*additional length tokens*/ + } else { + assert(outputDirective == limitedOutput); + return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */ + } + } + DEBUGLOG(6, "Final literal run : %i literals", (int)lastRun); + if (lastRun >= RUN_MASK) { + size_t accumulator = lastRun - RUN_MASK; + *op++ = RUN_MASK << ML_BITS; + for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; + *op++ = (BYTE) accumulator; + } else { + *op++ = (BYTE)(lastRun< 0); + DEBUGLOG(5, "LZ4_compress_generic: compressed %i bytes into %i bytes", inputSize, result); + return result; +} + +/** LZ4_compress_generic() : + * inlined, to ensure branches are decided at compilation time; + * takes care of src == (NULL, 0) + * and forward the rest to LZ4_compress_generic_validated */ +LZ4_FORCE_INLINE int LZ4_compress_generic( + LZ4_stream_t_internal* const cctx, + const char* const src, + char* const dst, + const int srcSize, + int *inputConsumed, /* only written when outputDirective == fillOutput */ + const int dstCapacity, + const limitedOutput_directive outputDirective, + const tableType_t tableType, + const dict_directive dictDirective, + const dictIssue_directive dictIssue, + const int acceleration) +{ + DEBUGLOG(5, "LZ4_compress_generic: srcSize=%i, dstCapacity=%i", + srcSize, dstCapacity); + + if ((U32)srcSize > (U32)LZ4_MAX_INPUT_SIZE) { return 0; } /* Unsupported srcSize, too large (or negative) */ + if (srcSize == 0) { /* src == NULL supported if srcSize == 0 */ + if (outputDirective != notLimited && dstCapacity <= 0) return 0; /* no output, can't write anything */ + DEBUGLOG(5, "Generating an empty block"); + assert(outputDirective == notLimited || dstCapacity >= 1); + assert(dst != NULL); + dst[0] = 0; + if (outputDirective == fillOutput) { + assert (inputConsumed != NULL); + *inputConsumed = 0; + } + return 1; + } + assert(src != NULL); + + return LZ4_compress_generic_validated(cctx, src, dst, srcSize, + inputConsumed, /* only written into if outputDirective == fillOutput */ + dstCapacity, outputDirective, + tableType, dictDirective, dictIssue, acceleration); +} + + +int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) +{ + LZ4_stream_t_internal* const ctx = & LZ4_initStream(state, sizeof(LZ4_stream_t)) -> internal_donotuse; + assert(ctx != NULL); + if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT; + if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX; + if (maxOutputSize >= LZ4_compressBound(inputSize)) { + if (inputSize < LZ4_64Klimit) { + return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, byU16, noDict, noDictIssue, acceleration); + } else { + const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > LZ4_DISTANCE_MAX)) ? byPtr : byU32; + return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration); + } + } else { + if (inputSize < LZ4_64Klimit) { + return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); + } else { + const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > LZ4_DISTANCE_MAX)) ? byPtr : byU32; + return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, noDict, noDictIssue, acceleration); + } + } +} + +/** + * LZ4_compress_fast_extState_fastReset() : + * A variant of LZ4_compress_fast_extState(). + * + * Using this variant avoids an expensive initialization step. It is only safe + * to call if the state buffer is known to be correctly initialized already + * (see comment in lz4.h on LZ4_resetStream_fast() for a definition of + * "correctly initialized"). + */ +int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration) +{ + LZ4_stream_t_internal* const ctx = &((LZ4_stream_t*)state)->internal_donotuse; + if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT; + if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX; + assert(ctx != NULL); + + if (dstCapacity >= LZ4_compressBound(srcSize)) { + if (srcSize < LZ4_64Klimit) { + const tableType_t tableType = byU16; + LZ4_prepareTable(ctx, srcSize, tableType); + if (ctx->currentOffset) { + return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, 0, notLimited, tableType, noDict, dictSmall, acceleration); + } else { + return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration); + } + } else { + const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32; + LZ4_prepareTable(ctx, srcSize, tableType); + return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration); + } + } else { + if (srcSize < LZ4_64Klimit) { + const tableType_t tableType = byU16; + LZ4_prepareTable(ctx, srcSize, tableType); + if (ctx->currentOffset) { + return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, dstCapacity, limitedOutput, tableType, noDict, dictSmall, acceleration); + } else { + return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, dstCapacity, limitedOutput, tableType, noDict, noDictIssue, acceleration); + } + } else { + const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32; + LZ4_prepareTable(ctx, srcSize, tableType); + return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, dstCapacity, limitedOutput, tableType, noDict, noDictIssue, acceleration); + } + } +} + + +int LZ4_compress_fast(const char* src, char* dest, int srcSize, int dstCapacity, int acceleration) +{ + int result; +#if (LZ4_HEAPMODE) + LZ4_stream_t* const ctxPtr = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ + if (ctxPtr == NULL) return 0; +#else + LZ4_stream_t ctx; + LZ4_stream_t* const ctxPtr = &ctx; +#endif + result = LZ4_compress_fast_extState(ctxPtr, src, dest, srcSize, dstCapacity, acceleration); + +#if (LZ4_HEAPMODE) + FREEMEM(ctxPtr); +#endif + return result; +} + + +int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity) +{ + return LZ4_compress_fast(src, dst, srcSize, dstCapacity, 1); +} + + +/* Note!: This function leaves the stream in an unclean/broken state! + * It is not safe to subsequently use the same state with a _fastReset() or + * _continue() call without resetting it. */ +static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize) +{ + void* const s = LZ4_initStream(state, sizeof (*state)); + assert(s != NULL); (void)s; + + if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) { /* compression success is guaranteed */ + return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1); + } else { + if (*srcSizePtr < LZ4_64Klimit) { + return LZ4_compress_generic(&state->internal_donotuse, src, dst, *srcSizePtr, srcSizePtr, targetDstSize, fillOutput, byU16, noDict, noDictIssue, 1); + } else { + tableType_t const addrMode = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32; + return LZ4_compress_generic(&state->internal_donotuse, src, dst, *srcSizePtr, srcSizePtr, targetDstSize, fillOutput, addrMode, noDict, noDictIssue, 1); + } } +} + + +int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize) +{ +#if (LZ4_HEAPMODE) + LZ4_stream_t* const ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ + if (ctx == NULL) return 0; +#else + LZ4_stream_t ctxBody; + LZ4_stream_t* const ctx = &ctxBody; +#endif + + int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize); + +#if (LZ4_HEAPMODE) + FREEMEM(ctx); +#endif + return result; +} + + + +/*-****************************** +* Streaming functions +********************************/ + +#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) +LZ4_stream_t* LZ4_createStream(void) +{ + LZ4_stream_t* const lz4s = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t)); + LZ4_STATIC_ASSERT(sizeof(LZ4_stream_t) >= sizeof(LZ4_stream_t_internal)); + DEBUGLOG(4, "LZ4_createStream %p", lz4s); + if (lz4s == NULL) return NULL; + LZ4_initStream(lz4s, sizeof(*lz4s)); + return lz4s; +} +#endif + +static size_t LZ4_stream_t_alignment(void) +{ +#if LZ4_ALIGN_TEST + typedef struct { char c; LZ4_stream_t t; } t_a; + return sizeof(t_a) - sizeof(LZ4_stream_t); +#else + return 1; /* effectively disabled */ +#endif +} + +LZ4_stream_t* LZ4_initStream (void* buffer, size_t size) +{ + DEBUGLOG(5, "LZ4_initStream"); + if (buffer == NULL) { return NULL; } + if (size < sizeof(LZ4_stream_t)) { return NULL; } + if (!LZ4_isAligned(buffer, LZ4_stream_t_alignment())) return NULL; + MEM_INIT(buffer, 0, sizeof(LZ4_stream_t_internal)); + return (LZ4_stream_t*)buffer; +} + +/* resetStream is now deprecated, + * prefer initStream() which is more general */ +void LZ4_resetStream (LZ4_stream_t* LZ4_stream) +{ + DEBUGLOG(5, "LZ4_resetStream (ctx:%p)", LZ4_stream); + MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t_internal)); +} + +void LZ4_resetStream_fast(LZ4_stream_t* ctx) { + LZ4_prepareTable(&(ctx->internal_donotuse), 0, byU32); +} + +#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) +int LZ4_freeStream (LZ4_stream_t* LZ4_stream) +{ + if (!LZ4_stream) return 0; /* support free on NULL */ + DEBUGLOG(5, "LZ4_freeStream %p", LZ4_stream); + FREEMEM(LZ4_stream); + return (0); +} +#endif + + +#define HASH_UNIT sizeof(reg_t) +int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) +{ + LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse; + const tableType_t tableType = byU32; + const BYTE* p = (const BYTE*)dictionary; + const BYTE* const dictEnd = p + dictSize; + U32 idx32; + + DEBUGLOG(4, "LZ4_loadDict (%i bytes from %p into %p)", dictSize, dictionary, LZ4_dict); + + /* It's necessary to reset the context, + * and not just continue it with prepareTable() + * to avoid any risk of generating overflowing matchIndex + * when compressing using this dictionary */ + LZ4_resetStream(LZ4_dict); + + /* We always increment the offset by 64 KB, since, if the dict is longer, + * we truncate it to the last 64k, and if it's shorter, we still want to + * advance by a whole window length so we can provide the guarantee that + * there are only valid offsets in the window, which allows an optimization + * in LZ4_compress_fast_continue() where it uses noDictIssue even when the + * dictionary isn't a full 64k. */ + dict->currentOffset += 64 KB; + + if (dictSize < (int)HASH_UNIT) { + return 0; + } + + if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB; + dict->dictionary = p; + dict->dictSize = (U32)(dictEnd - p); + dict->tableType = (U32)tableType; + idx32 = dict->currentOffset - dict->dictSize; + + while (p <= dictEnd-HASH_UNIT) { + U32 const h = LZ4_hashPosition(p, tableType); + LZ4_putIndexOnHash(idx32, h, dict->hashTable, tableType); + p+=3; idx32+=3; + } + + return (int)dict->dictSize; +} + +void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream) +{ + const LZ4_stream_t_internal* dictCtx = (dictionaryStream == NULL) ? NULL : + &(dictionaryStream->internal_donotuse); + + DEBUGLOG(4, "LZ4_attach_dictionary (%p, %p, size %u)", + workingStream, dictionaryStream, + dictCtx != NULL ? dictCtx->dictSize : 0); + + if (dictCtx != NULL) { + /* If the current offset is zero, we will never look in the + * external dictionary context, since there is no value a table + * entry can take that indicate a miss. In that case, we need + * to bump the offset to something non-zero. + */ + if (workingStream->internal_donotuse.currentOffset == 0) { + workingStream->internal_donotuse.currentOffset = 64 KB; + } + + /* Don't actually attach an empty dictionary. + */ + if (dictCtx->dictSize == 0) { + dictCtx = NULL; + } + } + workingStream->internal_donotuse.dictCtx = dictCtx; +} + + +static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, int nextSize) +{ + assert(nextSize >= 0); + if (LZ4_dict->currentOffset + (unsigned)nextSize > 0x80000000) { /* potential ptrdiff_t overflow (32-bits mode) */ + /* rescale hash table */ + U32 const delta = LZ4_dict->currentOffset - 64 KB; + const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize; + int i; + DEBUGLOG(4, "LZ4_renormDictT"); + for (i=0; ihashTable[i] < delta) LZ4_dict->hashTable[i]=0; + else LZ4_dict->hashTable[i] -= delta; + } + LZ4_dict->currentOffset = 64 KB; + if (LZ4_dict->dictSize > 64 KB) LZ4_dict->dictSize = 64 KB; + LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize; + } +} + + +int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, + const char* source, char* dest, + int inputSize, int maxOutputSize, + int acceleration) +{ + const tableType_t tableType = byU32; + LZ4_stream_t_internal* const streamPtr = &LZ4_stream->internal_donotuse; + const char* dictEnd = streamPtr->dictSize ? (const char*)streamPtr->dictionary + streamPtr->dictSize : NULL; + + DEBUGLOG(5, "LZ4_compress_fast_continue (inputSize=%i, dictSize=%u)", inputSize, streamPtr->dictSize); + + LZ4_renormDictT(streamPtr, inputSize); /* fix index overflow */ + if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT; + if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX; + + /* invalidate tiny dictionaries */ + if ( (streamPtr->dictSize < 4) /* tiny dictionary : not enough for a hash */ + && (dictEnd != source) /* prefix mode */ + && (inputSize > 0) /* tolerance : don't lose history, in case next invocation would use prefix mode */ + && (streamPtr->dictCtx == NULL) /* usingDictCtx */ + ) { + DEBUGLOG(5, "LZ4_compress_fast_continue: dictSize(%u) at addr:%p is too small", streamPtr->dictSize, streamPtr->dictionary); + /* remove dictionary existence from history, to employ faster prefix mode */ + streamPtr->dictSize = 0; + streamPtr->dictionary = (const BYTE*)source; + dictEnd = source; + } + + /* Check overlapping input/dictionary space */ + { const char* const sourceEnd = source + inputSize; + if ((sourceEnd > (const char*)streamPtr->dictionary) && (sourceEnd < dictEnd)) { + streamPtr->dictSize = (U32)(dictEnd - sourceEnd); + if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB; + if (streamPtr->dictSize < 4) streamPtr->dictSize = 0; + streamPtr->dictionary = (const BYTE*)dictEnd - streamPtr->dictSize; + } + } + + /* prefix mode : source data follows dictionary */ + if (dictEnd == source) { + if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) + return LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, withPrefix64k, dictSmall, acceleration); + else + return LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, withPrefix64k, noDictIssue, acceleration); + } + + /* external dictionary mode */ + { int result; + if (streamPtr->dictCtx) { + /* We depend here on the fact that dictCtx'es (produced by + * LZ4_loadDict) guarantee that their tables contain no references + * to offsets between dictCtx->currentOffset - 64 KB and + * dictCtx->currentOffset - dictCtx->dictSize. This makes it safe + * to use noDictIssue even when the dict isn't a full 64 KB. + */ + if (inputSize > 4 KB) { + /* For compressing large blobs, it is faster to pay the setup + * cost to copy the dictionary's tables into the active context, + * so that the compression loop is only looking into one table. + */ + LZ4_memcpy(streamPtr, streamPtr->dictCtx, sizeof(*streamPtr)); + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration); + } else { + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingDictCtx, noDictIssue, acceleration); + } + } else { /* small data <= 4 KB */ + if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) { + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, dictSmall, acceleration); + } else { + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration); + } + } + streamPtr->dictionary = (const BYTE*)source; + streamPtr->dictSize = (U32)inputSize; + return result; + } +} + + +/* Hidden debug function, to force-test external dictionary mode */ +int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int srcSize) +{ + LZ4_stream_t_internal* const streamPtr = &LZ4_dict->internal_donotuse; + int result; + + LZ4_renormDictT(streamPtr, srcSize); + + if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) { + result = LZ4_compress_generic(streamPtr, source, dest, srcSize, NULL, 0, notLimited, byU32, usingExtDict, dictSmall, 1); + } else { + result = LZ4_compress_generic(streamPtr, source, dest, srcSize, NULL, 0, notLimited, byU32, usingExtDict, noDictIssue, 1); + } + + streamPtr->dictionary = (const BYTE*)source; + streamPtr->dictSize = (U32)srcSize; + + return result; +} + + +/*! LZ4_saveDict() : + * If previously compressed data block is not guaranteed to remain available at its memory location, + * save it into a safer place (char* safeBuffer). + * Note : no need to call LZ4_loadDict() afterwards, dictionary is immediately usable, + * one can therefore call LZ4_compress_fast_continue() right after. + * @return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error. + */ +int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize) +{ + LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse; + + DEBUGLOG(5, "LZ4_saveDict : dictSize=%i, safeBuffer=%p", dictSize, safeBuffer); + + if ((U32)dictSize > 64 KB) { dictSize = 64 KB; } /* useless to define a dictionary > 64 KB */ + if ((U32)dictSize > dict->dictSize) { dictSize = (int)dict->dictSize; } + + if (safeBuffer == NULL) assert(dictSize == 0); + if (dictSize > 0) { + const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize; + assert(dict->dictionary); + LZ4_memmove(safeBuffer, previousDictEnd - dictSize, (size_t)dictSize); + } + + dict->dictionary = (const BYTE*)safeBuffer; + dict->dictSize = (U32)dictSize; + + return dictSize; +} + + + +/*-******************************* + * Decompression functions + ********************************/ + +typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive; + +#undef MIN +#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) + + +/* variant for decompress_unsafe() + * does not know end of input + * presumes input is well formed + * note : will consume at least one byte */ +static size_t read_long_length_no_check(const BYTE** pp) +{ + size_t b, l = 0; + do { b = **pp; (*pp)++; l += b; } while (b==255); + DEBUGLOG(6, "read_long_length_no_check: +length=%zu using %zu input bytes", l, l/255 + 1) + return l; +} + +/* core decoder variant for LZ4_decompress_fast*() + * for legacy support only : these entry points are deprecated. + * - Presumes input is correctly formed (no defense vs malformed inputs) + * - Does not know input size (presume input buffer is "large enough") + * - Decompress a full block (only) + * @return : nb of bytes read from input. + * Note : this variant is not optimized for speed, just for maintenance. + * the goal is to remove support of decompress_fast*() variants by v2.0 +**/ +LZ4_FORCE_INLINE int +LZ4_decompress_unsafe_generic( + const BYTE* const istart, + BYTE* const ostart, + int decompressedSize, + + size_t prefixSize, + const BYTE* const dictStart, /* only if dict==usingExtDict */ + const size_t dictSize /* note: =0 if dictStart==NULL */ + ) +{ + const BYTE* ip = istart; + BYTE* op = (BYTE*)ostart; + BYTE* const oend = ostart + decompressedSize; + const BYTE* const prefixStart = ostart - prefixSize; + + DEBUGLOG(5, "LZ4_decompress_unsafe_generic"); + if (dictStart == NULL) assert(dictSize == 0); + + while (1) { + /* start new sequence */ + unsigned token = *ip++; + + /* literals */ + { size_t ll = token >> ML_BITS; + if (ll==15) { + /* long literal length */ + ll += read_long_length_no_check(&ip); + } + if ((size_t)(oend-op) < ll) return -1; /* output buffer overflow */ + LZ4_memmove(op, ip, ll); /* support in-place decompression */ + op += ll; + ip += ll; + if ((size_t)(oend-op) < MFLIMIT) { + if (op==oend) break; /* end of block */ + DEBUGLOG(5, "invalid: literals end at distance %zi from end of block", oend-op); + /* incorrect end of block : + * last match must start at least MFLIMIT==12 bytes before end of output block */ + return -1; + } } + + /* match */ + { size_t ml = token & 15; + size_t const offset = LZ4_readLE16(ip); + ip+=2; + + if (ml==15) { + /* long literal length */ + ml += read_long_length_no_check(&ip); + } + ml += MINMATCH; + + if ((size_t)(oend-op) < ml) return -1; /* output buffer overflow */ + + { const BYTE* match = op - offset; + + /* out of range */ + if (offset > (size_t)(op - prefixStart) + dictSize) { + DEBUGLOG(6, "offset out of range"); + return -1; + } + + /* check special case : extDict */ + if (offset > (size_t)(op - prefixStart)) { + /* extDict scenario */ + const BYTE* const dictEnd = dictStart + dictSize; + const BYTE* extMatch = dictEnd - (offset - (size_t)(op-prefixStart)); + size_t const extml = (size_t)(dictEnd - extMatch); + if (extml > ml) { + /* match entirely within extDict */ + LZ4_memmove(op, extMatch, ml); + op += ml; + ml = 0; + } else { + /* match split between extDict & prefix */ + LZ4_memmove(op, extMatch, extml); + op += extml; + ml -= extml; + } + match = prefixStart; + } + + /* match copy - slow variant, supporting overlap copy */ + { size_t u; + for (u=0; u= ipmax before start of loop. Returns initial_error if so. + * @error (output) - error code. Must be set to 0 before call. +**/ +typedef size_t Rvl_t; +static const Rvl_t rvl_error = (Rvl_t)(-1); +LZ4_FORCE_INLINE Rvl_t +read_variable_length(const BYTE** ip, const BYTE* ilimit, + int initial_check) +{ + Rvl_t s, length = 0; + assert(ip != NULL); + assert(*ip != NULL); + assert(ilimit != NULL); + if (initial_check && unlikely((*ip) >= ilimit)) { /* read limit reached */ + return rvl_error; + } + do { + s = **ip; + (*ip)++; + length += s; + if (unlikely((*ip) > ilimit)) { /* read limit reached */ + return rvl_error; + } + /* accumulator overflow detection (32-bit mode only) */ + if ((sizeof(length)<8) && unlikely(length > ((Rvl_t)(-1)/2)) ) { + return rvl_error; + } + } while (s==255); + + return length; +} + +/*! LZ4_decompress_generic() : + * This generic decompression function covers all use cases. + * It shall be instantiated several times, using different sets of directives. + * Note that it is important for performance that this function really get inlined, + * in order to remove useless branches during compilation optimization. + */ +LZ4_FORCE_INLINE int +LZ4_decompress_generic( + const char* const src, + char* const dst, + int srcSize, + int outputSize, /* If endOnInput==endOnInputSize, this value is `dstCapacity` */ + + earlyEnd_directive partialDecoding, /* full, partial */ + dict_directive dict, /* noDict, withPrefix64k, usingExtDict */ + const BYTE* const lowPrefix, /* always <= dst, == dst when no prefix */ + const BYTE* const dictStart, /* only if dict==usingExtDict */ + const size_t dictSize /* note : = 0 if noDict */ + ) +{ + if ((src == NULL) || (outputSize < 0)) { return -1; } + + { const BYTE* ip = (const BYTE*) src; + const BYTE* const iend = ip + srcSize; + + BYTE* op = (BYTE*) dst; + BYTE* const oend = op + outputSize; + BYTE* cpy; + + const BYTE* const dictEnd = (dictStart == NULL) ? NULL : dictStart + dictSize; + + const int checkOffset = (dictSize < (int)(64 KB)); + + + /* Set up the "end" pointers for the shortcut. */ + const BYTE* const shortiend = iend - 14 /*maxLL*/ - 2 /*offset*/; + const BYTE* const shortoend = oend - 14 /*maxLL*/ - 18 /*maxML*/; + + const BYTE* match; + size_t offset; + unsigned token; + size_t length; + + + DEBUGLOG(5, "LZ4_decompress_generic (srcSize:%i, dstSize:%i)", srcSize, outputSize); + + /* Special cases */ + assert(lowPrefix <= op); + if (unlikely(outputSize==0)) { + /* Empty output buffer */ + if (partialDecoding) return 0; + return ((srcSize==1) && (*ip==0)) ? 0 : -1; + } + if (unlikely(srcSize==0)) { return -1; } + + /* LZ4_FAST_DEC_LOOP: + * designed for modern OoO performance cpus, + * where copying reliably 32-bytes is preferable to an unpredictable branch. + * note : fast loop may show a regression for some client arm chips. */ +#if LZ4_FAST_DEC_LOOP + if ((oend - op) < FASTLOOP_SAFE_DISTANCE) { + DEBUGLOG(6, "skip fast decode loop"); + goto safe_decode; + } + + /* Fast loop : decode sequences as long as output < oend-FASTLOOP_SAFE_DISTANCE */ + DEBUGLOG(6, "using fast decode loop"); + while (1) { + /* Main fastloop assertion: We can always wildcopy FASTLOOP_SAFE_DISTANCE */ + assert(oend - op >= FASTLOOP_SAFE_DISTANCE); + assert(ip < iend); + token = *ip++; + length = token >> ML_BITS; /* literal length */ + + /* decode literal length */ + if (length == RUN_MASK) { + size_t const addl = read_variable_length(&ip, iend-RUN_MASK, 1); + if (addl == rvl_error) { + DEBUGLOG(6, "error reading long literal length"); + goto _output_error; + } + length += addl; + if (unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */ + if (unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */ + + /* copy literals */ + LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH); + if ((op+length>oend-32) || (ip+length>iend-32)) { goto safe_literal_copy; } + LZ4_wildCopy32(op, ip, op+length); + ip += length; op += length; + } else if (ip <= iend-(16 + 1/*max lit + offset + nextToken*/)) { + /* We don't need to check oend, since we check it once for each loop below */ + DEBUGLOG(7, "copy %u bytes in a 16-bytes stripe", (unsigned)length); + /* Literals can only be <= 14, but hope compilers optimize better when copy by a register size */ + LZ4_memcpy(op, ip, 16); + ip += length; op += length; + } else { + goto safe_literal_copy; + } + + /* get offset */ + offset = LZ4_readLE16(ip); ip+=2; + DEBUGLOG(6, " offset = %zu", offset); + match = op - offset; + assert(match <= op); /* overflow check */ + + /* get matchlength */ + length = token & ML_MASK; + + if (length == ML_MASK) { + size_t const addl = read_variable_length(&ip, iend - LASTLITERALS + 1, 0); + if (addl == rvl_error) { + DEBUGLOG(6, "error reading long match length"); + goto _output_error; + } + length += addl; + length += MINMATCH; + if (unlikely((uptrval)(op)+length<(uptrval)op)) { goto _output_error; } /* overflow detection */ + if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) { + goto safe_match_copy; + } + } else { + length += MINMATCH; + if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) { + goto safe_match_copy; + } + + /* Fastpath check: skip LZ4_wildCopy32 when true */ + if ((dict == withPrefix64k) || (match >= lowPrefix)) { + if (offset >= 8) { + assert(match >= lowPrefix); + assert(match <= op); + assert(op + 18 <= oend); + + LZ4_memcpy(op, match, 8); + LZ4_memcpy(op+8, match+8, 8); + LZ4_memcpy(op+16, match+16, 2); + op += length; + continue; + } } } + + if ( checkOffset && (unlikely(match + dictSize < lowPrefix)) ) { + DEBUGLOG(6, "Error : pos=%zi, offset=%zi => outside buffers", op-lowPrefix, op-match); + goto _output_error; + } + /* match starting within external dictionary */ + if ((dict==usingExtDict) && (match < lowPrefix)) { + assert(dictEnd != NULL); + if (unlikely(op+length > oend-LASTLITERALS)) { + if (partialDecoding) { + DEBUGLOG(7, "partialDecoding: dictionary match, close to dstEnd"); + length = MIN(length, (size_t)(oend-op)); + } else { + DEBUGLOG(6, "end-of-block condition violated") + goto _output_error; + } } + + if (length <= (size_t)(lowPrefix-match)) { + /* match fits entirely within external dictionary : just copy */ + LZ4_memmove(op, dictEnd - (lowPrefix-match), length); + op += length; + } else { + /* match stretches into both external dictionary and current block */ + size_t const copySize = (size_t)(lowPrefix - match); + size_t const restSize = length - copySize; + LZ4_memcpy(op, dictEnd - copySize, copySize); + op += copySize; + if (restSize > (size_t)(op - lowPrefix)) { /* overlap copy */ + BYTE* const endOfMatch = op + restSize; + const BYTE* copyFrom = lowPrefix; + while (op < endOfMatch) { *op++ = *copyFrom++; } + } else { + LZ4_memcpy(op, lowPrefix, restSize); + op += restSize; + } } + continue; + } + + /* copy match within block */ + cpy = op + length; + + assert((op <= oend) && (oend-op >= 32)); + if (unlikely(offset<16)) { + LZ4_memcpy_using_offset(op, match, cpy, offset); + } else { + LZ4_wildCopy32(op, match, cpy); + } + + op = cpy; /* wildcopy correction */ + } + safe_decode: +#endif + + /* Main Loop : decode remaining sequences where output < FASTLOOP_SAFE_DISTANCE */ + DEBUGLOG(6, "using safe decode loop"); + while (1) { + assert(ip < iend); + token = *ip++; + length = token >> ML_BITS; /* literal length */ + + /* A two-stage shortcut for the most common case: + * 1) If the literal length is 0..14, and there is enough space, + * enter the shortcut and copy 16 bytes on behalf of the literals + * (in the fast mode, only 8 bytes can be safely copied this way). + * 2) Further if the match length is 4..18, copy 18 bytes in a similar + * manner; but we ensure that there's enough space in the output for + * those 18 bytes earlier, upon entering the shortcut (in other words, + * there is a combined check for both stages). + */ + if ( (length != RUN_MASK) + /* strictly "less than" on input, to re-enter the loop with at least one byte */ + && likely((ip < shortiend) & (op <= shortoend)) ) { + /* Copy the literals */ + LZ4_memcpy(op, ip, 16); + op += length; ip += length; + + /* The second stage: prepare for match copying, decode full info. + * If it doesn't work out, the info won't be wasted. */ + length = token & ML_MASK; /* match length */ + offset = LZ4_readLE16(ip); ip += 2; + match = op - offset; + assert(match <= op); /* check overflow */ + + /* Do not deal with overlapping matches. */ + if ( (length != ML_MASK) + && (offset >= 8) + && (dict==withPrefix64k || match >= lowPrefix) ) { + /* Copy the match. */ + LZ4_memcpy(op + 0, match + 0, 8); + LZ4_memcpy(op + 8, match + 8, 8); + LZ4_memcpy(op +16, match +16, 2); + op += length + MINMATCH; + /* Both stages worked, load the next token. */ + continue; + } + + /* The second stage didn't work out, but the info is ready. + * Propel it right to the point of match copying. */ + goto _copy_match; + } + + /* decode literal length */ + if (length == RUN_MASK) { + size_t const addl = read_variable_length(&ip, iend-RUN_MASK, 1); + if (addl == rvl_error) { goto _output_error; } + length += addl; + if (unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */ + if (unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */ + } + +#if LZ4_FAST_DEC_LOOP + safe_literal_copy: +#endif + /* copy literals */ + cpy = op+length; + + LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH); + if ((cpy>oend-MFLIMIT) || (ip+length>iend-(2+1+LASTLITERALS))) { + /* We've either hit the input parsing restriction or the output parsing restriction. + * In the normal scenario, decoding a full block, it must be the last sequence, + * otherwise it's an error (invalid input or dimensions). + * In partialDecoding scenario, it's necessary to ensure there is no buffer overflow. + */ + if (partialDecoding) { + /* Since we are partial decoding we may be in this block because of the output parsing + * restriction, which is not valid since the output buffer is allowed to be undersized. + */ + DEBUGLOG(7, "partialDecoding: copying literals, close to input or output end") + DEBUGLOG(7, "partialDecoding: literal length = %u", (unsigned)length); + DEBUGLOG(7, "partialDecoding: remaining space in dstBuffer : %i", (int)(oend - op)); + DEBUGLOG(7, "partialDecoding: remaining space in srcBuffer : %i", (int)(iend - ip)); + /* Finishing in the middle of a literals segment, + * due to lack of input. + */ + if (ip+length > iend) { + length = (size_t)(iend-ip); + cpy = op + length; + } + /* Finishing in the middle of a literals segment, + * due to lack of output space. + */ + if (cpy > oend) { + cpy = oend; + assert(op<=oend); + length = (size_t)(oend-op); + } + } else { + /* We must be on the last sequence (or invalid) because of the parsing limitations + * so check that we exactly consume the input and don't overrun the output buffer. + */ + if ((ip+length != iend) || (cpy > oend)) { + DEBUGLOG(6, "should have been last run of literals") + DEBUGLOG(6, "ip(%p) + length(%i) = %p != iend (%p)", ip, (int)length, ip+length, iend); + DEBUGLOG(6, "or cpy(%p) > oend(%p)", cpy, oend); + goto _output_error; + } + } + LZ4_memmove(op, ip, length); /* supports overlapping memory regions, for in-place decompression scenarios */ + ip += length; + op += length; + /* Necessarily EOF when !partialDecoding. + * When partialDecoding, it is EOF if we've either + * filled the output buffer or + * can't proceed with reading an offset for following match. + */ + if (!partialDecoding || (cpy == oend) || (ip >= (iend-2))) { + break; + } + } else { + LZ4_wildCopy8(op, ip, cpy); /* can overwrite up to 8 bytes beyond cpy */ + ip += length; op = cpy; + } + + /* get offset */ + offset = LZ4_readLE16(ip); ip+=2; + match = op - offset; + + /* get matchlength */ + length = token & ML_MASK; + + _copy_match: + if (length == ML_MASK) { + size_t const addl = read_variable_length(&ip, iend - LASTLITERALS + 1, 0); + if (addl == rvl_error) { goto _output_error; } + length += addl; + if (unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */ + } + length += MINMATCH; + +#if LZ4_FAST_DEC_LOOP + safe_match_copy: +#endif + if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) goto _output_error; /* Error : offset outside buffers */ + /* match starting within external dictionary */ + if ((dict==usingExtDict) && (match < lowPrefix)) { + assert(dictEnd != NULL); + if (unlikely(op+length > oend-LASTLITERALS)) { + if (partialDecoding) length = MIN(length, (size_t)(oend-op)); + else goto _output_error; /* doesn't respect parsing restriction */ + } + + if (length <= (size_t)(lowPrefix-match)) { + /* match fits entirely within external dictionary : just copy */ + LZ4_memmove(op, dictEnd - (lowPrefix-match), length); + op += length; + } else { + /* match stretches into both external dictionary and current block */ + size_t const copySize = (size_t)(lowPrefix - match); + size_t const restSize = length - copySize; + LZ4_memcpy(op, dictEnd - copySize, copySize); + op += copySize; + if (restSize > (size_t)(op - lowPrefix)) { /* overlap copy */ + BYTE* const endOfMatch = op + restSize; + const BYTE* copyFrom = lowPrefix; + while (op < endOfMatch) *op++ = *copyFrom++; + } else { + LZ4_memcpy(op, lowPrefix, restSize); + op += restSize; + } } + continue; + } + assert(match >= lowPrefix); + + /* copy match within block */ + cpy = op + length; + + /* partialDecoding : may end anywhere within the block */ + assert(op<=oend); + if (partialDecoding && (cpy > oend-MATCH_SAFEGUARD_DISTANCE)) { + size_t const mlen = MIN(length, (size_t)(oend-op)); + const BYTE* const matchEnd = match + mlen; + BYTE* const copyEnd = op + mlen; + if (matchEnd > op) { /* overlap copy */ + while (op < copyEnd) { *op++ = *match++; } + } else { + LZ4_memcpy(op, match, mlen); + } + op = copyEnd; + if (op == oend) { break; } + continue; + } + + if (unlikely(offset<8)) { + LZ4_write32(op, 0); /* silence msan warning when offset==0 */ + op[0] = match[0]; + op[1] = match[1]; + op[2] = match[2]; + op[3] = match[3]; + match += inc32table[offset]; + LZ4_memcpy(op+4, match, 4); + match -= dec64table[offset]; + } else { + LZ4_memcpy(op, match, 8); + match += 8; + } + op += 8; + + if (unlikely(cpy > oend-MATCH_SAFEGUARD_DISTANCE)) { + BYTE* const oCopyLimit = oend - (WILDCOPYLENGTH-1); + if (cpy > oend-LASTLITERALS) { goto _output_error; } /* Error : last LASTLITERALS bytes must be literals (uncompressed) */ + if (op < oCopyLimit) { + LZ4_wildCopy8(op, match, oCopyLimit); + match += oCopyLimit - op; + op = oCopyLimit; + } + while (op < cpy) { *op++ = *match++; } + } else { + LZ4_memcpy(op, match, 8); + if (length > 16) { LZ4_wildCopy8(op+8, match+8, cpy); } + } + op = cpy; /* wildcopy correction */ + } + + /* end of decoding */ + DEBUGLOG(5, "decoded %i bytes", (int) (((char*)op)-dst)); + return (int) (((char*)op)-dst); /* Nb of output bytes decoded */ + + /* Overflow error detected */ + _output_error: + return (int) (-(((const char*)ip)-src))-1; + } +} + + +/*===== Instantiate the API decoding functions. =====*/ + +LZ4_FORCE_O2 +int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize) +{ + return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, + decode_full_block, noDict, + (BYTE*)dest, NULL, 0); +} + +LZ4_FORCE_O2 +int LZ4_decompress_safe_partial(const char* src, char* dst, int compressedSize, int targetOutputSize, int dstCapacity) +{ + dstCapacity = MIN(targetOutputSize, dstCapacity); + return LZ4_decompress_generic(src, dst, compressedSize, dstCapacity, + partial_decode, + noDict, (BYTE*)dst, NULL, 0); +} + +LZ4_FORCE_O2 +int LZ4_decompress_fast(const char* source, char* dest, int originalSize) +{ + DEBUGLOG(5, "LZ4_decompress_fast"); + return LZ4_decompress_unsafe_generic( + (const BYTE*)source, (BYTE*)dest, originalSize, + 0, NULL, 0); +} + +/*===== Instantiate a few more decoding cases, used more than once. =====*/ + +LZ4_FORCE_O2 /* Exported, an obsolete API function. */ +int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize) +{ + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, + decode_full_block, withPrefix64k, + (BYTE*)dest - 64 KB, NULL, 0); +} + +LZ4_FORCE_O2 +static int LZ4_decompress_safe_partial_withPrefix64k(const char* source, char* dest, int compressedSize, int targetOutputSize, int dstCapacity) +{ + dstCapacity = MIN(targetOutputSize, dstCapacity); + return LZ4_decompress_generic(source, dest, compressedSize, dstCapacity, + partial_decode, withPrefix64k, + (BYTE*)dest - 64 KB, NULL, 0); +} + +/* Another obsolete API function, paired with the previous one. */ +int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize) +{ + return LZ4_decompress_unsafe_generic( + (const BYTE*)source, (BYTE*)dest, originalSize, + 64 KB, NULL, 0); +} + +LZ4_FORCE_O2 +static int LZ4_decompress_safe_withSmallPrefix(const char* source, char* dest, int compressedSize, int maxOutputSize, + size_t prefixSize) +{ + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, + decode_full_block, noDict, + (BYTE*)dest-prefixSize, NULL, 0); +} + +LZ4_FORCE_O2 +static int LZ4_decompress_safe_partial_withSmallPrefix(const char* source, char* dest, int compressedSize, int targetOutputSize, int dstCapacity, + size_t prefixSize) +{ + dstCapacity = MIN(targetOutputSize, dstCapacity); + return LZ4_decompress_generic(source, dest, compressedSize, dstCapacity, + partial_decode, noDict, + (BYTE*)dest-prefixSize, NULL, 0); +} + +LZ4_FORCE_O2 +int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, + int compressedSize, int maxOutputSize, + const void* dictStart, size_t dictSize) +{ + DEBUGLOG(5, "LZ4_decompress_safe_forceExtDict"); + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, + decode_full_block, usingExtDict, + (BYTE*)dest, (const BYTE*)dictStart, dictSize); +} + +LZ4_FORCE_O2 +int LZ4_decompress_safe_partial_forceExtDict(const char* source, char* dest, + int compressedSize, int targetOutputSize, int dstCapacity, + const void* dictStart, size_t dictSize) +{ + dstCapacity = MIN(targetOutputSize, dstCapacity); + return LZ4_decompress_generic(source, dest, compressedSize, dstCapacity, + partial_decode, usingExtDict, + (BYTE*)dest, (const BYTE*)dictStart, dictSize); +} + +LZ4_FORCE_O2 +static int LZ4_decompress_fast_extDict(const char* source, char* dest, int originalSize, + const void* dictStart, size_t dictSize) +{ + return LZ4_decompress_unsafe_generic( + (const BYTE*)source, (BYTE*)dest, originalSize, + 0, (const BYTE*)dictStart, dictSize); +} + +/* The "double dictionary" mode, for use with e.g. ring buffers: the first part + * of the dictionary is passed as prefix, and the second via dictStart + dictSize. + * These routines are used only once, in LZ4_decompress_*_continue(). + */ +LZ4_FORCE_INLINE +int LZ4_decompress_safe_doubleDict(const char* source, char* dest, int compressedSize, int maxOutputSize, + size_t prefixSize, const void* dictStart, size_t dictSize) +{ + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, + decode_full_block, usingExtDict, + (BYTE*)dest-prefixSize, (const BYTE*)dictStart, dictSize); +} + +/*===== streaming decompression functions =====*/ + +#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) +LZ4_streamDecode_t* LZ4_createStreamDecode(void) +{ + LZ4_STATIC_ASSERT(sizeof(LZ4_streamDecode_t) >= sizeof(LZ4_streamDecode_t_internal)); + return (LZ4_streamDecode_t*) ALLOC_AND_ZERO(sizeof(LZ4_streamDecode_t)); +} + +int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream) +{ + if (LZ4_stream == NULL) { return 0; } /* support free on NULL */ + FREEMEM(LZ4_stream); + return 0; +} +#endif + +/*! LZ4_setStreamDecode() : + * Use this function to instruct where to find the dictionary. + * This function is not necessary if previous data is still available where it was decoded. + * Loading a size of 0 is allowed (same effect as no dictionary). + * @return : 1 if OK, 0 if error + */ +int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize) +{ + LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; + lz4sd->prefixSize = (size_t)dictSize; + if (dictSize) { + assert(dictionary != NULL); + lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize; + } else { + lz4sd->prefixEnd = (const BYTE*) dictionary; + } + lz4sd->externalDict = NULL; + lz4sd->extDictSize = 0; + return 1; +} + +/*! LZ4_decoderRingBufferSize() : + * when setting a ring buffer for streaming decompression (optional scenario), + * provides the minimum size of this ring buffer + * to be compatible with any source respecting maxBlockSize condition. + * Note : in a ring buffer scenario, + * blocks are presumed decompressed next to each other. + * When not enough space remains for next block (remainingSize < maxBlockSize), + * decoding resumes from beginning of ring buffer. + * @return : minimum ring buffer size, + * or 0 if there is an error (invalid maxBlockSize). + */ +int LZ4_decoderRingBufferSize(int maxBlockSize) +{ + if (maxBlockSize < 0) return 0; + if (maxBlockSize > LZ4_MAX_INPUT_SIZE) return 0; + if (maxBlockSize < 16) maxBlockSize = 16; + return LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize); +} + +/* +*_continue() : + These decoding functions allow decompression of multiple blocks in "streaming" mode. + Previously decoded blocks must still be available at the memory position where they were decoded. + If it's not possible, save the relevant part of decoded data into a safe buffer, + and indicate where it stands using LZ4_setStreamDecode() +*/ +LZ4_FORCE_O2 +int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize) +{ + LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; + int result; + + if (lz4sd->prefixSize == 0) { + /* The first call, no dictionary yet. */ + assert(lz4sd->extDictSize == 0); + result = LZ4_decompress_safe(source, dest, compressedSize, maxOutputSize); + if (result <= 0) return result; + lz4sd->prefixSize = (size_t)result; + lz4sd->prefixEnd = (BYTE*)dest + result; + } else if (lz4sd->prefixEnd == (BYTE*)dest) { + /* They're rolling the current segment. */ + if (lz4sd->prefixSize >= 64 KB - 1) + result = LZ4_decompress_safe_withPrefix64k(source, dest, compressedSize, maxOutputSize); + else if (lz4sd->extDictSize == 0) + result = LZ4_decompress_safe_withSmallPrefix(source, dest, compressedSize, maxOutputSize, + lz4sd->prefixSize); + else + result = LZ4_decompress_safe_doubleDict(source, dest, compressedSize, maxOutputSize, + lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize += (size_t)result; + lz4sd->prefixEnd += result; + } else { + /* The buffer wraps around, or they're switching to another buffer. */ + lz4sd->extDictSize = lz4sd->prefixSize; + lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; + result = LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize, + lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize = (size_t)result; + lz4sd->prefixEnd = (BYTE*)dest + result; + } + + return result; +} + +LZ4_FORCE_O2 int +LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, + const char* source, char* dest, int originalSize) +{ + LZ4_streamDecode_t_internal* const lz4sd = + (assert(LZ4_streamDecode!=NULL), &LZ4_streamDecode->internal_donotuse); + int result; + + DEBUGLOG(5, "LZ4_decompress_fast_continue (toDecodeSize=%i)", originalSize); + assert(originalSize >= 0); + + if (lz4sd->prefixSize == 0) { + DEBUGLOG(5, "first invocation : no prefix nor extDict"); + assert(lz4sd->extDictSize == 0); + result = LZ4_decompress_fast(source, dest, originalSize); + if (result <= 0) return result; + lz4sd->prefixSize = (size_t)originalSize; + lz4sd->prefixEnd = (BYTE*)dest + originalSize; + } else if (lz4sd->prefixEnd == (BYTE*)dest) { + DEBUGLOG(5, "continue using existing prefix"); + result = LZ4_decompress_unsafe_generic( + (const BYTE*)source, (BYTE*)dest, originalSize, + lz4sd->prefixSize, + lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize += (size_t)originalSize; + lz4sd->prefixEnd += originalSize; + } else { + DEBUGLOG(5, "prefix becomes extDict"); + lz4sd->extDictSize = lz4sd->prefixSize; + lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; + result = LZ4_decompress_fast_extDict(source, dest, originalSize, + lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize = (size_t)originalSize; + lz4sd->prefixEnd = (BYTE*)dest + originalSize; + } + + return result; +} + + +/* +Advanced decoding functions : +*_usingDict() : + These decoding functions work the same as "_continue" ones, + the dictionary must be explicitly provided within parameters +*/ + +int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize) +{ + if (dictSize==0) + return LZ4_decompress_safe(source, dest, compressedSize, maxOutputSize); + if (dictStart+dictSize == dest) { + if (dictSize >= 64 KB - 1) { + return LZ4_decompress_safe_withPrefix64k(source, dest, compressedSize, maxOutputSize); + } + assert(dictSize >= 0); + return LZ4_decompress_safe_withSmallPrefix(source, dest, compressedSize, maxOutputSize, (size_t)dictSize); + } + assert(dictSize >= 0); + return LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize, dictStart, (size_t)dictSize); +} + +int LZ4_decompress_safe_partial_usingDict(const char* source, char* dest, int compressedSize, int targetOutputSize, int dstCapacity, const char* dictStart, int dictSize) +{ + if (dictSize==0) + return LZ4_decompress_safe_partial(source, dest, compressedSize, targetOutputSize, dstCapacity); + if (dictStart+dictSize == dest) { + if (dictSize >= 64 KB - 1) { + return LZ4_decompress_safe_partial_withPrefix64k(source, dest, compressedSize, targetOutputSize, dstCapacity); + } + assert(dictSize >= 0); + return LZ4_decompress_safe_partial_withSmallPrefix(source, dest, compressedSize, targetOutputSize, dstCapacity, (size_t)dictSize); + } + assert(dictSize >= 0); + return LZ4_decompress_safe_partial_forceExtDict(source, dest, compressedSize, targetOutputSize, dstCapacity, dictStart, (size_t)dictSize); +} + +int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize) +{ + if (dictSize==0 || dictStart+dictSize == dest) + return LZ4_decompress_unsafe_generic( + (const BYTE*)source, (BYTE*)dest, originalSize, + (size_t)dictSize, NULL, 0); + assert(dictSize >= 0); + return LZ4_decompress_fast_extDict(source, dest, originalSize, dictStart, (size_t)dictSize); +} + + +/*=************************************************* +* Obsolete Functions +***************************************************/ +/* obsolete compression functions */ +int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) +{ + return LZ4_compress_default(source, dest, inputSize, maxOutputSize); +} +int LZ4_compress(const char* src, char* dest, int srcSize) +{ + return LZ4_compress_default(src, dest, srcSize, LZ4_compressBound(srcSize)); +} +int LZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize) +{ + return LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1); +} +int LZ4_compress_withState (void* state, const char* src, char* dst, int srcSize) +{ + return LZ4_compress_fast_extState(state, src, dst, srcSize, LZ4_compressBound(srcSize), 1); +} +int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_stream, const char* src, char* dst, int srcSize, int dstCapacity) +{ + return LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, dstCapacity, 1); +} +int LZ4_compress_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize) +{ + return LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LZ4_compressBound(inputSize), 1); +} + +/* +These decompression functions are deprecated and should no longer be used. +They are only provided here for compatibility with older user programs. +- LZ4_uncompress is totally equivalent to LZ4_decompress_fast +- LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe +*/ +int LZ4_uncompress (const char* source, char* dest, int outputSize) +{ + return LZ4_decompress_fast(source, dest, outputSize); +} +int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) +{ + return LZ4_decompress_safe(source, dest, isize, maxOutputSize); +} + +/* Obsolete Streaming functions */ + +int LZ4_sizeofStreamState(void) { return sizeof(LZ4_stream_t); } + +int LZ4_resetStreamState(void* state, char* inputBuffer) +{ + (void)inputBuffer; + LZ4_resetStream((LZ4_stream_t*)state); + return 0; +} + +#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) +void* LZ4_create (char* inputBuffer) +{ + (void)inputBuffer; + return LZ4_createStream(); +} +#endif + +char* LZ4_slideInputBuffer (void* state) +{ + /* avoid const char * -> char * conversion warning */ + return (char *)(uptrval)((LZ4_stream_t*)state)->internal_donotuse.dictionary; +} + +#endif /* LZ4_COMMONDEFS_ONLY */ + +#endif /* LV_USE_LZ4_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/lz4/lz4.h b/lib/libesp32_lvgl/lvgl/src/libs/lz4/lz4.h new file mode 100644 index 000000000..72080233e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/lz4/lz4.h @@ -0,0 +1,877 @@ +/* + * LZ4 - Fast LZ compression algorithm + * Header File + * Copyright (C) 2011-2020, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - LZ4 homepage : http://www.lz4.org + - LZ4 source repository : https://github.com/lz4/lz4 +*/ + +#include "../../lv_conf_internal.h" +#if LV_USE_LZ4_INTERNAL +#if defined (__cplusplus) +extern "C" { +#endif + +/** + * LVGL's porting + */ +#include "../../lvgl.h" +#define LZ4_FREESTANDING 1 +#define LZ4_memset lv_memset +#define LZ4_memcpy lv_memcpy +#define LZ4_memmove lv_memmove + +#ifndef LZ4_H_2983827168210 +#define LZ4_H_2983827168210 + +/* --- Dependency --- */ +#include /* size_t */ + + +/** + Introduction + + LZ4 is lossless compression algorithm, providing compression speed >500 MB/s per core, + scalable with multi-cores CPU. It features an extremely fast decoder, with speed in + multiple GB/s per core, typically reaching RAM speed limits on multi-core systems. + + The LZ4 compression library provides in-memory compression and decompression functions. + It gives full buffer control to user. + Compression can be done in: + - a single step (described as Simple Functions) + - a single step, reusing a context (described in Advanced Functions) + - unbounded multiple steps (described as Streaming compression) + + lz4.h generates and decodes LZ4-compressed blocks (doc/lz4_Block_format.md). + Decompressing such a compressed block requires additional metadata. + Exact metadata depends on exact decompression function. + For the typical case of LZ4_decompress_safe(), + metadata includes block's compressed size, and maximum bound of decompressed size. + Each application is free to encode and pass such metadata in whichever way it wants. + + lz4.h only handle blocks, it can not generate Frames. + + Blocks are different from Frames (doc/lz4_Frame_format.md). + Frames bundle both blocks and metadata in a specified manner. + Embedding metadata is required for compressed data to be self-contained and portable. + Frame format is delivered through a companion API, declared in lz4frame.h. + The `lz4` CLI can only manage frames. +*/ + +/*^*************************************************************** +* Export parameters +*****************************************************************/ +/* +* LZ4_DLL_EXPORT : +* Enable exporting of functions when building a Windows DLL +* LZ4LIB_VISIBILITY : +* Control library symbols visibility. +*/ +#ifndef LZ4LIB_VISIBILITY +# if defined(__GNUC__) && (__GNUC__ >= 4) +# define LZ4LIB_VISIBILITY __attribute__ ((visibility ("default"))) +# else +# define LZ4LIB_VISIBILITY +# endif +#endif +#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1) +# define LZ4LIB_API __declspec(dllexport) LZ4LIB_VISIBILITY +#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1) +# define LZ4LIB_API __declspec(dllimport) LZ4LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ +#else +# define LZ4LIB_API LZ4LIB_VISIBILITY +#endif + +/*! LZ4_FREESTANDING : + * When this macro is set to 1, it enables "freestanding mode" that is + * suitable for typical freestanding environment which doesn't support + * standard C library. + * + * - LZ4_FREESTANDING is a compile-time switch. + * - It requires the following macros to be defined: + * LZ4_memcpy, LZ4_memmove, LZ4_memset. + * - It only enables LZ4/HC functions which don't use heap. + * All LZ4F_* functions are not supported. + * - See tests/freestanding.c to check its basic setup. + */ +#if defined(LZ4_FREESTANDING) && (LZ4_FREESTANDING == 1) +# define LZ4_HEAPMODE 0 +# define LZ4HC_HEAPMODE 0 +# define LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION 1 +# if !defined(LZ4_memcpy) +# error "LZ4_FREESTANDING requires macro 'LZ4_memcpy'." +# endif +# if !defined(LZ4_memset) +# error "LZ4_FREESTANDING requires macro 'LZ4_memset'." +# endif +# if !defined(LZ4_memmove) +# error "LZ4_FREESTANDING requires macro 'LZ4_memmove'." +# endif +#elif ! defined(LZ4_FREESTANDING) +# define LZ4_FREESTANDING 0 +#endif + + +/*------ Version ------*/ +#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */ +#define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */ +#define LZ4_VERSION_RELEASE 5 /* for tweaks, bug-fixes, or development */ + +#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE) + +#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE +#define LZ4_QUOTE(str) #str +#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str) +#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) /* requires v1.7.3+ */ + +LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version; requires v1.3.0+ */ +LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; useful to check dll version; requires v1.7.5+ */ + + +/*-************************************ +* Tuning parameter +**************************************/ +#define LZ4_MEMORY_USAGE_MIN 10 +#define LZ4_MEMORY_USAGE_DEFAULT 14 +#define LZ4_MEMORY_USAGE_MAX 20 + +/*! + * LZ4_MEMORY_USAGE : + * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; ) + * Increasing memory usage improves compression ratio, at the cost of speed. + * Reduced memory usage may improve speed at the cost of ratio, thanks to better cache locality. + * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache + */ +#ifndef LZ4_MEMORY_USAGE +# define LZ4_MEMORY_USAGE LZ4_MEMORY_USAGE_DEFAULT +#endif + +#if (LZ4_MEMORY_USAGE < LZ4_MEMORY_USAGE_MIN) +# error "LZ4_MEMORY_USAGE is too small !" +#endif + +#if (LZ4_MEMORY_USAGE > LZ4_MEMORY_USAGE_MAX) +# error "LZ4_MEMORY_USAGE is too large !" +#endif + +/*-************************************ +* Simple Functions +**************************************/ +/*! LZ4_compress_default() : + * Compresses 'srcSize' bytes from buffer 'src' + * into already allocated 'dst' buffer of size 'dstCapacity'. + * Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize). + * It also runs faster, so it's a recommended setting. + * If the function cannot compress 'src' into a more limited 'dst' budget, + * compression stops *immediately*, and the function result is zero. + * In which case, 'dst' content is undefined (invalid). + * srcSize : max supported value is LZ4_MAX_INPUT_SIZE. + * dstCapacity : size of buffer 'dst' (which must be already allocated) + * @return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity) + * or 0 if compression fails + * Note : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer). + */ +LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity); + +/*! LZ4_decompress_safe() : + * @compressedSize : is the exact complete size of the compressed block. + * @dstCapacity : is the size of destination buffer (which must be already allocated), + * is an upper bound of decompressed size. + * @return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity) + * If destination buffer is not large enough, decoding will stop and output an error code (negative value). + * If the source stream is detected malformed, the function will stop decoding and return a negative result. + * Note 1 : This function is protected against malicious data packets : + * it will never writes outside 'dst' buffer, nor read outside 'source' buffer, + * even if the compressed block is maliciously modified to order the decoder to do these actions. + * In such case, the decoder stops immediately, and considers the compressed block malformed. + * Note 2 : compressedSize and dstCapacity must be provided to the function, the compressed block does not contain them. + * The implementation is free to send / store / derive this information in whichever way is most beneficial. + * If there is a need for a different format which bundles together both compressed data and its metadata, consider looking at lz4frame.h instead. + */ +LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity); + + +/*-************************************ +* Advanced Functions +**************************************/ +#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */ +#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16) + +/*! LZ4_compressBound() : + Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible) + This function is primarily useful for memory allocation purposes (destination buffer size). + Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example). + Note that LZ4_compress_default() compresses faster when dstCapacity is >= LZ4_compressBound(srcSize) + inputSize : max supported value is LZ4_MAX_INPUT_SIZE + return : maximum output size in a "worst case" scenario + or 0, if input size is incorrect (too large or negative) +*/ +LZ4LIB_API int LZ4_compressBound(int inputSize); + +/*! LZ4_compress_fast() : + Same as LZ4_compress_default(), but allows selection of "acceleration" factor. + The larger the acceleration value, the faster the algorithm, but also the lesser the compression. + It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed. + An acceleration value of "1" is the same as regular LZ4_compress_default() + Values <= 0 will be replaced by LZ4_ACCELERATION_DEFAULT (currently == 1, see lz4.c). + Values > LZ4_ACCELERATION_MAX will be replaced by LZ4_ACCELERATION_MAX (currently == 65537, see lz4.c). +*/ +LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); + + +/*! LZ4_compress_fast_extState() : + * Same as LZ4_compress_fast(), using an externally allocated memory space for its state. + * Use LZ4_sizeofState() to know how much memory must be allocated, + * and allocate it on 8-bytes boundaries (using `malloc()` typically). + * Then, provide this buffer as `void* state` to compression function. + */ +LZ4LIB_API int LZ4_sizeofState(void); +LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); + + +/*! LZ4_compress_destSize() : + * Reverse the logic : compresses as much data as possible from 'src' buffer + * into already allocated buffer 'dst', of size >= 'targetDestSize'. + * This function either compresses the entire 'src' content into 'dst' if it's large enough, + * or fill 'dst' buffer completely with as much data as possible from 'src'. + * note: acceleration parameter is fixed to "default". + * + * *srcSizePtr : will be modified to indicate how many bytes where read from 'src' to fill 'dst'. + * New value is necessarily <= input value. + * @return : Nb bytes written into 'dst' (necessarily <= targetDestSize) + * or 0 if compression fails. + * + * Note : from v1.8.2 to v1.9.1, this function had a bug (fixed in v1.9.2+): + * the produced compressed content could, in specific circumstances, + * require to be decompressed into a destination buffer larger + * by at least 1 byte than the content to decompress. + * If an application uses `LZ4_compress_destSize()`, + * it's highly recommended to update liblz4 to v1.9.2 or better. + * If this can't be done or ensured, + * the receiving decompression function should provide + * a dstCapacity which is > decompressedSize, by at least 1 byte. + * See https://github.com/lz4/lz4/issues/859 for details + */ +LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize); + + +/*! LZ4_decompress_safe_partial() : + * Decompress an LZ4 compressed block, of size 'srcSize' at position 'src', + * into destination buffer 'dst' of size 'dstCapacity'. + * Up to 'targetOutputSize' bytes will be decoded. + * The function stops decoding on reaching this objective. + * This can be useful to boost performance + * whenever only the beginning of a block is required. + * + * @return : the number of bytes decoded in `dst` (necessarily <= targetOutputSize) + * If source stream is detected malformed, function returns a negative result. + * + * Note 1 : @return can be < targetOutputSize, if compressed block contains less data. + * + * Note 2 : targetOutputSize must be <= dstCapacity + * + * Note 3 : this function effectively stops decoding on reaching targetOutputSize, + * so dstCapacity is kind of redundant. + * This is because in older versions of this function, + * decoding operation would still write complete sequences. + * Therefore, there was no guarantee that it would stop writing at exactly targetOutputSize, + * it could write more bytes, though only up to dstCapacity. + * Some "margin" used to be required for this operation to work properly. + * Thankfully, this is no longer necessary. + * The function nonetheless keeps the same signature, in an effort to preserve API compatibility. + * + * Note 4 : If srcSize is the exact size of the block, + * then targetOutputSize can be any value, + * including larger than the block's decompressed size. + * The function will, at most, generate block's decompressed size. + * + * Note 5 : If srcSize is _larger_ than block's compressed size, + * then targetOutputSize **MUST** be <= block's decompressed size. + * Otherwise, *silent corruption will occur*. + */ +LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity); + + +/*-********************************************* +* Streaming Compression Functions +***********************************************/ +typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */ + +/** + Note about RC_INVOKED + + - RC_INVOKED is predefined symbol of rc.exe (the resource compiler which is part of MSVC/Visual Studio). + https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros + + - Since rc.exe is a legacy compiler, it truncates long symbol (> 30 chars) + and reports warning "RC4011: identifier truncated". + + - To eliminate the warning, we surround long preprocessor symbol with + "#if !defined(RC_INVOKED) ... #endif" block that means + "skip this block when rc.exe is trying to read it". +*/ +#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */ +#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) +LZ4LIB_API LZ4_stream_t* LZ4_createStream(void); +LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr); +#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */ +#endif + +/*! LZ4_resetStream_fast() : v1.9.0+ + * Use this to prepare an LZ4_stream_t for a new chain of dependent blocks + * (e.g., LZ4_compress_fast_continue()). + * + * An LZ4_stream_t must be initialized once before usage. + * This is automatically done when created by LZ4_createStream(). + * However, should the LZ4_stream_t be simply declared on stack (for example), + * it's necessary to initialize it first, using LZ4_initStream(). + * + * After init, start any new stream with LZ4_resetStream_fast(). + * A same LZ4_stream_t can be re-used multiple times consecutively + * and compress multiple streams, + * provided that it starts each new stream with LZ4_resetStream_fast(). + * + * LZ4_resetStream_fast() is much faster than LZ4_initStream(), + * but is not compatible with memory regions containing garbage data. + * + * Note: it's only useful to call LZ4_resetStream_fast() + * in the context of streaming compression. + * The *extState* functions perform their own resets. + * Invoking LZ4_resetStream_fast() before is redundant, and even counterproductive. + */ +LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr); + +/*! LZ4_loadDict() : + * Use this function to reference a static dictionary into LZ4_stream_t. + * The dictionary must remain available during compression. + * LZ4_loadDict() triggers a reset, so any previous data will be forgotten. + * The same dictionary will have to be loaded on decompression side for successful decoding. + * Dictionary are useful for better compression of small data (KB range). + * While LZ4 accept any input as dictionary, + * results are generally better when using Zstandard's Dictionary Builder. + * Loading a size of 0 is allowed, and is the same as reset. + * @return : loaded dictionary size, in bytes (necessarily <= 64 KB) + */ +LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize); + +/*! LZ4_compress_fast_continue() : + * Compress 'src' content using data from previously compressed blocks, for better compression ratio. + * 'dst' buffer must be already allocated. + * If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. + * + * @return : size of compressed block + * or 0 if there is an error (typically, cannot fit into 'dst'). + * + * Note 1 : Each invocation to LZ4_compress_fast_continue() generates a new block. + * Each block has precise boundaries. + * Each block must be decompressed separately, calling LZ4_decompress_*() with relevant metadata. + * It's not possible to append blocks together and expect a single invocation of LZ4_decompress_*() to decompress them together. + * + * Note 2 : The previous 64KB of source data is __assumed__ to remain present, unmodified, at same address in memory ! + * + * Note 3 : When input is structured as a double-buffer, each buffer can have any size, including < 64 KB. + * Make sure that buffers are separated, by at least one byte. + * This construction ensures that each block only depends on previous block. + * + * Note 4 : If input buffer is a ring-buffer, it can have any size, including < 64 KB. + * + * Note 5 : After an error, the stream status is undefined (invalid), it can only be reset or freed. + */ +LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); + +/*! LZ4_saveDict() : + * If last 64KB data cannot be guaranteed to remain available at its current memory location, + * save it into a safer place (char* safeBuffer). + * This is schematically equivalent to a memcpy() followed by LZ4_loadDict(), + * but is much faster, because LZ4_saveDict() doesn't need to rebuild tables. + * @return : saved dictionary size in bytes (necessarily <= maxDictSize), or 0 if error. + */ +LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int maxDictSize); + + +/*-********************************************** +* Streaming Decompression Functions +* Bufferless synchronous API +************************************************/ +typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* tracking context */ + +/*! LZ4_createStreamDecode() and LZ4_freeStreamDecode() : + * creation / destruction of streaming decompression tracking context. + * A tracking context can be re-used multiple times. + */ +#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */ +#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) +LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void); +LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream); +#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */ +#endif + +/*! LZ4_setStreamDecode() : + * An LZ4_streamDecode_t context can be allocated once and re-used multiple times. + * Use this function to start decompression of a new stream of blocks. + * A dictionary can optionally be set. Use NULL or size 0 for a reset order. + * Dictionary is presumed stable : it must remain accessible and unmodified during next decompression. + * @return : 1 if OK, 0 if error + */ +LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize); + +/*! LZ4_decoderRingBufferSize() : v1.8.2+ + * Note : in a ring buffer scenario (optional), + * blocks are presumed decompressed next to each other + * up to the moment there is not enough remaining space for next block (remainingSize < maxBlockSize), + * at which stage it resumes from beginning of ring buffer. + * When setting such a ring buffer for streaming decompression, + * provides the minimum size of this ring buffer + * to be compatible with any source respecting maxBlockSize condition. + * @return : minimum ring buffer size, + * or 0 if there is an error (invalid maxBlockSize). + */ +LZ4LIB_API int LZ4_decoderRingBufferSize(int maxBlockSize); +#define LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize) (65536 + 14 + (maxBlockSize)) /* for static allocation; maxBlockSize presumed valid */ + +/*! LZ4_decompress_safe_continue() : + * This decoding function allows decompression of consecutive blocks in "streaming" mode. + * The difference with the usual independent blocks is that + * new blocks are allowed to find references into former blocks. + * A block is an unsplittable entity, and must be presented entirely to the decompression function. + * LZ4_decompress_safe_continue() only accepts one block at a time. + * It's modeled after `LZ4_decompress_safe()` and behaves similarly. + * + * @LZ4_streamDecode : decompression state, tracking the position in memory of past data + * @compressedSize : exact complete size of one compressed block. + * @dstCapacity : size of destination buffer (which must be already allocated), + * must be an upper bound of decompressed size. + * @return : number of bytes decompressed into destination buffer (necessarily <= dstCapacity) + * If destination buffer is not large enough, decoding will stop and output an error code (negative value). + * If the source stream is detected malformed, the function will stop decoding and return a negative result. + * + * The last 64KB of previously decoded data *must* remain available and unmodified + * at the memory position where they were previously decoded. + * If less than 64KB of data has been decoded, all the data must be present. + * + * Special : if decompression side sets a ring buffer, it must respect one of the following conditions : + * - Decompression buffer size is _at least_ LZ4_decoderRingBufferSize(maxBlockSize). + * maxBlockSize is the maximum size of any single block. It can have any value > 16 bytes. + * In which case, encoding and decoding buffers do not need to be synchronized. + * Actually, data can be produced by any source compliant with LZ4 format specification, and respecting maxBlockSize. + * - Synchronized mode : + * Decompression buffer size is _exactly_ the same as compression buffer size, + * and follows exactly same update rule (block boundaries at same positions), + * and decoding function is provided with exact decompressed size of each block (exception for last block of the stream), + * _then_ decoding & encoding ring buffer can have any size, including small ones ( < 64 KB). + * - Decompression buffer is larger than encoding buffer, by a minimum of maxBlockSize more bytes. + * In which case, encoding and decoding buffers do not need to be synchronized, + * and encoding ring buffer can have any size, including small ones ( < 64 KB). + * + * Whenever these conditions are not possible, + * save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression, + * then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block. +*/ +LZ4LIB_API int +LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, + const char* src, char* dst, + int srcSize, int dstCapacity); + + +/*! LZ4_decompress_safe_usingDict() : + * Works the same as + * a combination of LZ4_setStreamDecode() followed by LZ4_decompress_safe_continue() + * However, it's stateless: it doesn't need any LZ4_streamDecode_t state. + * Dictionary is presumed stable : it must remain accessible and unmodified during decompression. + * Performance tip : Decompression speed can be substantially increased + * when dst == dictStart + dictSize. + */ +LZ4LIB_API int +LZ4_decompress_safe_usingDict(const char* src, char* dst, + int srcSize, int dstCapacity, + const char* dictStart, int dictSize); + +/*! LZ4_decompress_safe_partial_usingDict() : + * Behaves the same as LZ4_decompress_safe_partial() + * with the added ability to specify a memory segment for past data. + * Performance tip : Decompression speed can be substantially increased + * when dst == dictStart + dictSize. + */ +LZ4LIB_API int +LZ4_decompress_safe_partial_usingDict(const char* src, char* dst, + int compressedSize, + int targetOutputSize, int maxOutputSize, + const char* dictStart, int dictSize); + +#endif /* LZ4_H_2983827168210 */ + + +/*^************************************* + * !!!!!! STATIC LINKING ONLY !!!!!! + ***************************************/ + +/*-**************************************************************************** + * Experimental section + * + * Symbols declared in this section must be considered unstable. Their + * signatures or semantics may change, or they may be removed altogether in the + * future. They are therefore only safe to depend on when the caller is + * statically linked against the library. + * + * To protect against unsafe usage, not only are the declarations guarded, + * the definitions are hidden by default + * when building LZ4 as a shared/dynamic library. + * + * In order to access these declarations, + * define LZ4_STATIC_LINKING_ONLY in your application + * before including LZ4's headers. + * + * In order to make their implementations accessible dynamically, you must + * define LZ4_PUBLISH_STATIC_FUNCTIONS when building the LZ4 library. + ******************************************************************************/ + +#ifdef LZ4_STATIC_LINKING_ONLY + +#ifndef LZ4_STATIC_3504398509 +#define LZ4_STATIC_3504398509 + +#ifdef LZ4_PUBLISH_STATIC_FUNCTIONS +#define LZ4LIB_STATIC_API LZ4LIB_API +#else +#define LZ4LIB_STATIC_API +#endif + + +/*! LZ4_compress_fast_extState_fastReset() : + * A variant of LZ4_compress_fast_extState(). + * + * Using this variant avoids an expensive initialization step. + * It is only safe to call if the state buffer is known to be correctly initialized already + * (see above comment on LZ4_resetStream_fast() for a definition of "correctly initialized"). + * From a high level, the difference is that + * this function initializes the provided state with a call to something like LZ4_resetStream_fast() + * while LZ4_compress_fast_extState() starts with a call to LZ4_resetStream(). + */ +LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); + +/*! LZ4_attach_dictionary() : + * This is an experimental API that allows + * efficient use of a static dictionary many times. + * + * Rather than re-loading the dictionary buffer into a working context before + * each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a + * working LZ4_stream_t, this function introduces a no-copy setup mechanism, + * in which the working stream references the dictionary stream in-place. + * + * Several assumptions are made about the state of the dictionary stream. + * Currently, only streams which have been prepared by LZ4_loadDict() should + * be expected to work. + * + * Alternatively, the provided dictionaryStream may be NULL, + * in which case any existing dictionary stream is unset. + * + * If a dictionary is provided, it replaces any pre-existing stream history. + * The dictionary contents are the only history that can be referenced and + * logically immediately precede the data compressed in the first subsequent + * compression call. + * + * The dictionary will only remain attached to the working stream through the + * first compression call, at the end of which it is cleared. The dictionary + * stream (and source buffer) must remain in-place / accessible / unchanged + * through the completion of the first compression call on the stream. + */ +LZ4LIB_STATIC_API void +LZ4_attach_dictionary(LZ4_stream_t* workingStream, + const LZ4_stream_t* dictionaryStream); + + +/*! In-place compression and decompression + * + * It's possible to have input and output sharing the same buffer, + * for highly constrained memory environments. + * In both cases, it requires input to lay at the end of the buffer, + * and decompression to start at beginning of the buffer. + * Buffer size must feature some margin, hence be larger than final size. + * + * |<------------------------buffer--------------------------------->| + * |<-----------compressed data--------->| + * |<-----------decompressed size------------------>| + * |<----margin---->| + * + * This technique is more useful for decompression, + * since decompressed size is typically larger, + * and margin is short. + * + * In-place decompression will work inside any buffer + * which size is >= LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize). + * This presumes that decompressedSize > compressedSize. + * Otherwise, it means compression actually expanded data, + * and it would be more efficient to store such data with a flag indicating it's not compressed. + * This can happen when data is not compressible (already compressed, or encrypted). + * + * For in-place compression, margin is larger, as it must be able to cope with both + * history preservation, requiring input data to remain unmodified up to LZ4_DISTANCE_MAX, + * and data expansion, which can happen when input is not compressible. + * As a consequence, buffer size requirements are much higher, + * and memory savings offered by in-place compression are more limited. + * + * There are ways to limit this cost for compression : + * - Reduce history size, by modifying LZ4_DISTANCE_MAX. + * Note that it is a compile-time constant, so all compressions will apply this limit. + * Lower values will reduce compression ratio, except when input_size < LZ4_DISTANCE_MAX, + * so it's a reasonable trick when inputs are known to be small. + * - Require the compressor to deliver a "maximum compressed size". + * This is the `dstCapacity` parameter in `LZ4_compress*()`. + * When this size is < LZ4_COMPRESSBOUND(inputSize), then compression can fail, + * in which case, the return code will be 0 (zero). + * The caller must be ready for these cases to happen, + * and typically design a backup scheme to send data uncompressed. + * The combination of both techniques can significantly reduce + * the amount of margin required for in-place compression. + * + * In-place compression can work in any buffer + * which size is >= (maxCompressedSize) + * with maxCompressedSize == LZ4_COMPRESSBOUND(srcSize) for guaranteed compression success. + * LZ4_COMPRESS_INPLACE_BUFFER_SIZE() depends on both maxCompressedSize and LZ4_DISTANCE_MAX, + * so it's possible to reduce memory requirements by playing with them. + */ + +#define LZ4_DECOMPRESS_INPLACE_MARGIN(compressedSize) (((compressedSize) >> 8) + 32) +#define LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize) ((decompressedSize) + LZ4_DECOMPRESS_INPLACE_MARGIN(decompressedSize)) /**< note: presumes that compressedSize < decompressedSize. note2: margin is overestimated a bit, since it could use compressedSize instead */ + +#ifndef LZ4_DISTANCE_MAX /* history window size; can be user-defined at compile time */ +# define LZ4_DISTANCE_MAX 65535 /* set to maximum value by default */ +#endif + +#define LZ4_COMPRESS_INPLACE_MARGIN (LZ4_DISTANCE_MAX + 32) /* LZ4_DISTANCE_MAX can be safely replaced by srcSize when it's smaller */ +#define LZ4_COMPRESS_INPLACE_BUFFER_SIZE(maxCompressedSize) ((maxCompressedSize) + LZ4_COMPRESS_INPLACE_MARGIN) /**< maxCompressedSize is generally LZ4_COMPRESSBOUND(inputSize), but can be set to any lower value, with the risk that compression can fail (return code 0(zero)) */ + +#endif /* LZ4_STATIC_3504398509 */ +#endif /* LZ4_STATIC_LINKING_ONLY */ + + + +#ifndef LZ4_H_98237428734687 +#define LZ4_H_98237428734687 + +/*-************************************************************ + * Private Definitions + ************************************************************** + * Do not use these definitions directly. + * They are only exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`. + * Accessing members will expose user code to API and/or ABI break in future versions of the library. + **************************************************************/ +#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2) +#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE) +#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */ + +#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# include + typedef int8_t LZ4_i8; + typedef uint8_t LZ4_byte; + typedef uint16_t LZ4_u16; + typedef uint32_t LZ4_u32; +#else + typedef signed char LZ4_i8; + typedef unsigned char LZ4_byte; + typedef unsigned short LZ4_u16; + typedef unsigned int LZ4_u32; +#endif + +/*! LZ4_stream_t : + * Never ever use below internal definitions directly ! + * These definitions are not API/ABI safe, and may change in future versions. + * If you need static allocation, declare or allocate an LZ4_stream_t object. +**/ + +typedef struct LZ4_stream_t_internal LZ4_stream_t_internal; +struct LZ4_stream_t_internal { + LZ4_u32 hashTable[LZ4_HASH_SIZE_U32]; + const LZ4_byte* dictionary; + const LZ4_stream_t_internal* dictCtx; + LZ4_u32 currentOffset; + LZ4_u32 tableType; + LZ4_u32 dictSize; + /* Implicit padding to ensure structure is aligned */ +}; + +#define LZ4_STREAM_MINSIZE ((1UL << LZ4_MEMORY_USAGE) + 32) /* static size, for inter-version compatibility */ +union LZ4_stream_u { + char minStateSize[LZ4_STREAM_MINSIZE]; + LZ4_stream_t_internal internal_donotuse; +}; /* previously typedef'd to LZ4_stream_t */ + + +/*! LZ4_initStream() : v1.9.0+ + * An LZ4_stream_t structure must be initialized at least once. + * This is automatically done when invoking LZ4_createStream(), + * but it's not when the structure is simply declared on stack (for example). + * + * Use LZ4_initStream() to properly initialize a newly declared LZ4_stream_t. + * It can also initialize any arbitrary buffer of sufficient size, + * and will @return a pointer of proper type upon initialization. + * + * Note : initialization fails if size and alignment conditions are not respected. + * In which case, the function will @return NULL. + * Note2: An LZ4_stream_t structure guarantees correct alignment and size. + * Note3: Before v1.9.0, use LZ4_resetStream() instead +**/ +LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size); + + +/*! LZ4_streamDecode_t : + * Never ever use below internal definitions directly ! + * These definitions are not API/ABI safe, and may change in future versions. + * If you need static allocation, declare or allocate an LZ4_streamDecode_t object. +**/ +typedef struct { + const LZ4_byte* externalDict; + const LZ4_byte* prefixEnd; + size_t extDictSize; + size_t prefixSize; +} LZ4_streamDecode_t_internal; + +#define LZ4_STREAMDECODE_MINSIZE 32 +union LZ4_streamDecode_u { + char minStateSize[LZ4_STREAMDECODE_MINSIZE]; + LZ4_streamDecode_t_internal internal_donotuse; +} ; /* previously typedef'd to LZ4_streamDecode_t */ + + + +/*-************************************ +* Obsolete Functions +**************************************/ + +/*! Deprecation warnings + * + * Deprecated functions make the compiler generate a warning when invoked. + * This is meant to invite users to update their source code. + * Should deprecation warnings be a problem, it is generally possible to disable them, + * typically with -Wno-deprecated-declarations for gcc + * or _CRT_SECURE_NO_WARNINGS in Visual. + * + * Another method is to define LZ4_DISABLE_DEPRECATE_WARNINGS + * before including the header file. + */ +#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS +# define LZ4_DEPRECATED(message) /* disable deprecation warnings */ +#else +# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ +# define LZ4_DEPRECATED(message) [[deprecated(message)]] +# elif defined(_MSC_VER) +# define LZ4_DEPRECATED(message) __declspec(deprecated(message)) +# elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 45)) +# define LZ4_DEPRECATED(message) __attribute__((deprecated(message))) +# elif defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 31) +# define LZ4_DEPRECATED(message) __attribute__((deprecated)) +# else +# pragma message("WARNING: LZ4_DEPRECATED needs custom implementation for this compiler") +# define LZ4_DEPRECATED(message) /* disabled */ +# endif +#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */ + +/*! Obsolete compression functions (since v1.7.3) */ +LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* src, char* dest, int srcSize); +LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* src, char* dest, int srcSize, int maxOutputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize); + +/*! Obsolete decompression functions (since v1.8.0) */ +LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize); +LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); + +/* Obsolete streaming functions (since v1.7.0) + * degraded functionality; do not use! + * + * In order to perform streaming compression, these functions depended on data + * that is no longer tracked in the state. They have been preserved as well as + * possible: using them will still produce a correct output. However, they don't + * actually retain any history between compression calls. The compression ratio + * achieved will therefore be no better than compressing each chunk + * independently. + */ +LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API void* LZ4_create (char* inputBuffer); +LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API int LZ4_sizeofStreamState(void); +LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer); +LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state); + +/*! Obsolete streaming decoding functions (since v1.7.0) */ +LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize); +LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize); + +/*! Obsolete LZ4_decompress_fast variants (since v1.9.0) : + * These functions used to be faster than LZ4_decompress_safe(), + * but this is no longer the case. They are now slower. + * This is because LZ4_decompress_fast() doesn't know the input size, + * and therefore must progress more cautiously into the input buffer to not read beyond the end of block. + * On top of that `LZ4_decompress_fast()` is not protected vs malformed or malicious inputs, making it a security liability. + * As a consequence, LZ4_decompress_fast() is strongly discouraged, and deprecated. + * + * The last remaining LZ4_decompress_fast() specificity is that + * it can decompress a block without knowing its compressed size. + * Such functionality can be achieved in a more secure manner + * by employing LZ4_decompress_safe_partial(). + * + * Parameters: + * originalSize : is the uncompressed size to regenerate. + * `dst` must be already allocated, its size must be >= 'originalSize' bytes. + * @return : number of bytes read from source buffer (== compressed size). + * The function expects to finish at block's end exactly. + * If the source stream is detected malformed, the function stops decoding and returns a negative result. + * note : LZ4_decompress_fast*() requires originalSize. Thanks to this information, it never writes past the output buffer. + * However, since it doesn't know its 'src' size, it may read an unknown amount of input, past input buffer bounds. + * Also, since match offsets are not validated, match reads from 'src' may underflow too. + * These issues never happen if input (compressed) data is correct. + * But they may happen if input data is invalid (error or intentional tampering). + * As a consequence, use these functions in trusted environments with trusted data **only**. + */ +LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe() instead") +LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize); +LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_continue() instead") +LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize); +LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_usingDict() instead") +LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize); + +/*! LZ4_resetStream() : + * An LZ4_stream_t structure must be initialized at least once. + * This is done with LZ4_initStream(), or LZ4_resetStream(). + * Consider switching to LZ4_initStream(), + * invoking LZ4_resetStream() will trigger deprecation warnings in the future. + */ +LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr); + + +#endif /* LZ4_H_98237428734687 */ + + +#if defined (__cplusplus) +} +#endif + +#endif /* LV_USE_LZ4_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/lv_qrcode.c b/lib/libesp32_lvgl/lvgl/src/libs/qrcode/lv_qrcode.c similarity index 52% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/lv_qrcode.c rename to lib/libesp32_lvgl/lvgl/src/libs/qrcode/lv_qrcode.c index 079873e13..e6d693237 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/lv_qrcode.c +++ b/lib/libesp32_lvgl/lvgl/src/libs/qrcode/lv_qrcode.c @@ -33,13 +33,11 @@ static void lv_qrcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) const lv_obj_class_t lv_qrcode_class = { .constructor_cb = lv_qrcode_constructor, .destructor_cb = lv_qrcode_destructor, - .base_class = &lv_canvas_class + .instance_size = sizeof(lv_qrcode_t), + .base_class = &lv_canvas_class, + .name = "qrcode", }; -static lv_coord_t size_param; -static lv_color_t dark_color_param; -static lv_color_t light_color_param; - /********************** * MACROS **********************/ @@ -48,62 +46,85 @@ static lv_color_t light_color_param; * GLOBAL FUNCTIONS **********************/ -/** - * Create an empty QR code (an `lv_canvas`) object. - * @param parent point to an object where to create the QR code - * @param size width and height of the QR code - * @param dark_color dark color of the QR code - * @param light_color light color of the QR code - * @return pointer to the created QR code object - */ -lv_obj_t * lv_qrcode_create(lv_obj_t * parent, lv_coord_t size, lv_color_t dark_color, lv_color_t light_color) +lv_obj_t * lv_qrcode_create(lv_obj_t * parent) { LV_LOG_INFO("begin"); - size_param = size; - light_color_param = light_color; - dark_color_param = dark_color; - lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; - } -/** - * Set the data of a QR code object - * @param qrcode pointer to aQ code object - * @param data data to display - * @param data_len length of data in bytes - * @return LV_RES_OK: if no error; LV_RES_INV: on error - */ -lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_len) +void lv_qrcode_set_size(lv_obj_t * obj, int32_t size) { - lv_color_t c; - c.full = 1; - lv_canvas_fill_bg(qrcode, c, LV_OPA_COVER); + LV_ASSERT_OBJ(obj, MY_CLASS); - if(data_len > qrcodegen_BUFFER_LEN_MAX) return LV_RES_INV; - - lv_img_dsc_t * imgdsc = lv_canvas_get_img(qrcode); - - int32_t qr_version = qrcodegen_getMinFitVersion(qrcodegen_Ecc_MEDIUM, data_len); - if(qr_version <= 0) return LV_RES_INV; - int32_t qr_size = qrcodegen_version2size(qr_version); - if(qr_size <= 0) return LV_RES_INV; - int32_t scale = imgdsc->header.w / qr_size; - if(scale <= 0) return LV_RES_INV; - int32_t remain = imgdsc->header.w % qr_size; - - /* The qr version is incremented by four point */ - uint32_t version_extend = remain / (scale << 2); - if(version_extend && qr_version < qrcodegen_VERSION_MAX) { - qr_version = qr_version + version_extend > qrcodegen_VERSION_MAX ? - qrcodegen_VERSION_MAX : qr_version + version_extend; + lv_draw_buf_t * old_buf = lv_canvas_get_draw_buf(obj); + lv_draw_buf_t * new_buf = lv_draw_buf_create(size, size, LV_COLOR_FORMAT_I1, LV_STRIDE_AUTO); + if(new_buf == NULL) { + LV_LOG_ERROR("malloc failed for canvas buffer"); + return; } - uint8_t * qr0 = lv_mem_alloc(qrcodegen_BUFFER_LEN_FOR_VERSION(qr_version)); + lv_canvas_set_draw_buf(obj, new_buf); + LV_LOG_INFO("set canvas buffer: %p, size = %d", new_buf, (int)size); + + /*Clear canvas buffer*/ + lv_canvas_fill_bg(obj, lv_color_white(), LV_OPA_COVER); + + if(old_buf != NULL) lv_draw_buf_destroy(old_buf); +} + +void lv_qrcode_set_dark_color(lv_obj_t * obj, lv_color_t color) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_qrcode_t * qrcode = (lv_qrcode_t *)obj; + qrcode->dark_color = color; +} + +void lv_qrcode_set_light_color(lv_obj_t * obj, lv_color_t color) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_qrcode_t * qrcode = (lv_qrcode_t *)obj; + qrcode->light_color = color; +} + +lv_result_t lv_qrcode_update(lv_obj_t * obj, const void * data, uint32_t data_len) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_qrcode_t * qrcode = (lv_qrcode_t *)obj; + + lv_draw_buf_t * draw_buf = lv_canvas_get_draw_buf(obj); + if(draw_buf == NULL) { + LV_LOG_ERROR("canvas draw buffer is NULL"); + return LV_RESULT_INVALID; + } + + lv_canvas_set_palette(obj, 0, lv_color_to_32(qrcode->dark_color, 0xff)); + lv_canvas_set_palette(obj, 1, lv_color_to_32(qrcode->light_color, 0xff)); + lv_color_t c = lv_color_hex(1); + lv_canvas_fill_bg(obj, c, LV_OPA_COVER); + + if(data_len > qrcodegen_BUFFER_LEN_MAX) return LV_RESULT_INVALID; + + int32_t qr_version = qrcodegen_getMinFitVersion(qrcodegen_Ecc_MEDIUM, data_len); + if(qr_version <= 0) return LV_RESULT_INVALID; + int32_t qr_size = qrcodegen_version2size(qr_version); + if(qr_size <= 0) return LV_RESULT_INVALID; + int32_t scale = draw_buf->header.w / qr_size; + if(scale <= 0) return LV_RESULT_INVALID; + + /* Pick the largest QR code that still maintains scale. */ + for(int32_t i = qr_version + 1; i < qrcodegen_VERSION_MAX; i++) { + if(qrcodegen_version2size(i) * scale > draw_buf->header.w) + break; + + qr_version = i; + } + qr_size = qrcodegen_version2size(qr_version); + + uint8_t * qr0 = lv_malloc(qrcodegen_BUFFER_LEN_FOR_VERSION(qr_version)); LV_ASSERT_MALLOC(qr0); - uint8_t * data_tmp = lv_mem_alloc(qrcodegen_BUFFER_LEN_FOR_VERSION(qr_version)); + uint8_t * data_tmp = lv_malloc(qrcodegen_BUFFER_LEN_FOR_VERSION(qr_version)); LV_ASSERT_MALLOC(data_tmp); lv_memcpy(data_tmp, data, data_len); @@ -113,22 +134,22 @@ lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_le qrcodegen_Mask_AUTO, true); if(!ok) { - lv_mem_free(qr0); - lv_mem_free(data_tmp); - return LV_RES_INV; + lv_free(qr0); + lv_free(data_tmp); + return LV_RESULT_INVALID; } - lv_coord_t obj_w = imgdsc->header.w; + int32_t obj_w = draw_buf->header.w; qr_size = qrcodegen_getSize(qr0); scale = obj_w / qr_size; int scaled = qr_size * scale; int margin = (obj_w - scaled) / 2; - uint8_t * buf_u8 = (uint8_t *)imgdsc->data + 8; /*+8 skip the palette*/ + uint8_t * buf_u8 = (uint8_t *)draw_buf->data + 8; /*+8 skip the palette*/ /* Copy the qr code canvas: * A simple `lv_canvas_set_px` would work but it's slow for so many pixels. * So buffer 1 byte (8 px) from the qr code and set it in the canvas image */ - uint32_t row_byte_cnt = (imgdsc->header.w + 7) >> 3; + uint32_t row_byte_cnt = draw_buf->header.stride; int y; for(y = margin; y < scaled + margin; y += scale) { uint8_t b = 0; @@ -141,8 +162,8 @@ lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_le if(aligned == false && (x & 0x7) == 0) aligned = true; if(aligned == false) { - c.full = a ? 0 : 1; - lv_canvas_set_px_color(qrcode, x, y, c); + c = lv_color_hex(a ? 0 : 1); + lv_canvas_set_px(obj, x, y, c, LV_OPA_COVER); } else { if(!a) b |= (1 << (7 - p)); @@ -173,15 +194,9 @@ lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_le } } - lv_mem_free(qr0); - lv_mem_free(data_tmp); - return LV_RES_OK; -} - - -void lv_qrcode_delete(lv_obj_t * qrcode) -{ - lv_obj_del(qrcode); + lv_free(qr0); + lv_free(data_tmp); + return LV_RESULT_OK; } /********************** @@ -192,24 +207,24 @@ static void lv_qrcode_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj { LV_UNUSED(class_p); - uint32_t buf_size = LV_CANVAS_BUF_SIZE_INDEXED_1BIT(size_param, size_param); - uint8_t * buf = lv_mem_alloc(buf_size); - LV_ASSERT_MALLOC(buf); - if(buf == NULL) return; + /*Set default size*/ + lv_qrcode_set_size(obj, LV_DPI_DEF); - lv_canvas_set_buffer(obj, buf, size_param, size_param, LV_IMG_CF_INDEXED_1BIT); - lv_canvas_set_palette(obj, 0, dark_color_param); - lv_canvas_set_palette(obj, 1, light_color_param); + /*Set default color*/ + lv_qrcode_set_dark_color(obj, lv_color_black()); + lv_qrcode_set_light_color(obj, lv_color_white()); } static void lv_qrcode_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { LV_UNUSED(class_p); - lv_img_dsc_t * img = lv_canvas_get_img(obj); - lv_img_cache_invalidate_src(img); - lv_mem_free((void *)img->data); - img->data = NULL; + lv_draw_buf_t * draw_buf = lv_canvas_get_draw_buf(obj); + if(draw_buf == NULL) return; + lv_image_cache_drop(draw_buf); + + /*@fixme destroy buffer in cache free_cb.*/ + lv_draw_buf_destroy(draw_buf); } #endif /*LV_USE_QRCODE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/lv_qrcode.h b/lib/libesp32_lvgl/lvgl/src/libs/qrcode/lv_qrcode.h similarity index 51% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/lv_qrcode.h rename to lib/libesp32_lvgl/lvgl/src/libs/qrcode/lv_qrcode.h index b0752ace9..36de2b384 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/lv_qrcode.h +++ b/lib/libesp32_lvgl/lvgl/src/libs/qrcode/lv_qrcode.h @@ -20,12 +20,19 @@ extern "C" { * DEFINES *********************/ -extern const lv_obj_class_t lv_qrcode_class; - /********************** * TYPEDEFS **********************/ +/*Data of qrcode*/ +typedef struct { + lv_canvas_t canvas; + lv_color_t dark_color; + lv_color_t light_color; +} lv_qrcode_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_qrcode_class; + /********************** * GLOBAL PROTOTYPES **********************/ @@ -33,28 +40,39 @@ extern const lv_obj_class_t lv_qrcode_class; /** * Create an empty QR code (an `lv_canvas`) object. * @param parent point to an object where to create the QR code - * @param size width and height of the QR code - * @param dark_color dark color of the QR code - * @param light_color light color of the QR code * @return pointer to the created QR code object */ -lv_obj_t * lv_qrcode_create(lv_obj_t * parent, lv_coord_t size, lv_color_t dark_color, lv_color_t light_color); +lv_obj_t * lv_qrcode_create(lv_obj_t * parent); + +/** + * Set QR code size. + * @param obj pointer to a QR code object + * @param size width and height of the QR code + */ +void lv_qrcode_set_size(lv_obj_t * obj, int32_t size); + +/** + * Set QR code dark color. + * @param obj pointer to a QR code object + * @param color dark color of the QR code + */ +void lv_qrcode_set_dark_color(lv_obj_t * obj, lv_color_t color); + +/** + * Set QR code light color. + * @param obj pointer to a QR code object + * @param color light color of the QR code + */ +void lv_qrcode_set_light_color(lv_obj_t * obj, lv_color_t color); /** * Set the data of a QR code object - * @param qrcode pointer to aQ code object + * @param obj pointer to a QR code object * @param data data to display * @param data_len length of data in bytes - * @return LV_RES_OK: if no error; LV_RES_INV: on error + * @return LV_RESULT_OK: if no error; LV_RESULT_INVALID: on error */ -lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_len); - -/** - * DEPRECATED: Use normal lv_obj_del instead - * Delete a QR code object - * @param qrcode pointer to a QR code object - */ -void lv_qrcode_delete(lv_obj_t * qrcode); +lv_result_t lv_qrcode_update(lv_obj_t * obj, const void * data, uint32_t data_len); /********************** * MACROS diff --git a/lib/libesp32_lvgl/lvgl/src/libs/qrcode/qrcodegen.c b/lib/libesp32_lvgl/lvgl/src/libs/qrcode/qrcodegen.c new file mode 100644 index 000000000..8f71f4724 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/qrcode/qrcodegen.c @@ -0,0 +1,1113 @@ +/* + * QR Code generator library (C) + * + * Copyright (c) Project Nayuki. (MIT License) + * https://www.nayuki.io/page/qr-code-generator-library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * - The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * - The Software is provided "as is", without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall the + * authors or copyright holders be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising from, + * out of or in connection with the Software or the use or other dealings in the + * Software. + */ + +#include +#include +#include +#include "qrcodegen.h" +#include "../../misc/lv_assert.h" + +#ifndef QRCODEGEN_TEST + #define testable static // Keep functions private +#else + #define testable // Expose private functions +#endif + + +/*---- Forward declarations for private functions ----*/ + +// Regarding all public and private functions defined in this source file: +// - They require all pointer/array arguments to be not null unless the array length is zero. +// - They only read input scalar/array arguments, write to output pointer/array +// arguments, and return scalar values; they are "pure" functions. +// - They don't read mutable global variables or write to any global variables. +// - They don't perform I/O, read the clock, print to console, etc. +// - They allocate a small and constant amount of stack memory. +// - They don't allocate or free any memory on the heap. +// - They don't recurse or mutually recurse. All the code +// could be inlined into the top-level public functions. +// - They run in at most quadratic time with respect to input arguments. +// Most functions run in linear time, and some in constant time. +// There are no unbounded loops or non-obvious termination conditions. +// - They are completely thread-safe if the caller does not give the +// same writable buffer to concurrent calls to these functions. + +testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int * bitLen); + +testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]); +testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl); +testable int getNumRawDataModules(int ver); + +testable void calcReedSolomonGenerator(int degree, uint8_t result[]); +testable void calcReedSolomonRemainder(const uint8_t data[], int dataLen, + const uint8_t generator[], int degree, uint8_t result[]); +testable uint8_t finiteFieldMultiply(uint8_t x, uint8_t y); + +testable void initializeFunctionModules(int version, uint8_t qrcode[]); +static void drawWhiteFunctionModules(uint8_t qrcode[], int version); +static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]); +testable int getAlignmentPatternPositions(int version, uint8_t result[7]); +static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]); + +static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]); +static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask); +static long getPenaltyScore(const uint8_t qrcode[]); +static void addRunToHistory(unsigned char run, unsigned char history[7]); +static bool hasFinderLikePattern(const unsigned char runHistory[7]); + +testable bool getModule(const uint8_t qrcode[], int x, int y); +testable void setModule(uint8_t qrcode[], int x, int y, bool isBlack); +testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack); +static bool getBit(int x, int i); + +testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars); +testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version); +static int numCharCountBits(enum qrcodegen_Mode mode, int version); + + + +/*---- Private tables of constants ----*/ + +// The set of all legal characters in alphanumeric mode, where each character +// value maps to the index in the string. For checking text and encoding segments. +static const char * ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; + +// For generating error correction codes. +testable const int8_t ECC_CODEWORDS_PER_BLOCK[4][41] = { + // Version: (note that index 0 is for padding, and is set to an illegal value) + //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level + {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low + {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium + {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile + {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High +}; + +#define qrcodegen_REED_SOLOMON_DEGREE_MAX 30 // Based on the table above + +// For generating error correction codes. +testable const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41] = { + // Version: (note that index 0 is for padding, and is set to an illegal value) + //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level + {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low + {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium + {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile + {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High +}; + +// For automatic mask pattern selection. +static const int PENALTY_N1 = 3; +static const int PENALTY_N2 = 3; +static const int PENALTY_N3 = 40; +static const int PENALTY_N4 = 10; + + + +/*---- High-level QR Code encoding functions ----*/ + +// Public function - see documentation comment in header file. +bool qrcodegen_encodeText(const char * text, uint8_t tempBuffer[], uint8_t qrcode[], + enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) +{ + + size_t textLen = strlen(text); + if(textLen == 0) + return qrcodegen_encodeSegmentsAdvanced(NULL, 0, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); + size_t bufLen = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion); + + struct qrcodegen_Segment seg; + if(qrcodegen_isNumeric(text)) { + if(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_NUMERIC, textLen) > bufLen) + goto fail; + seg = qrcodegen_makeNumeric(text, tempBuffer); + } + else if(qrcodegen_isAlphanumeric(text)) { + if(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ALPHANUMERIC, textLen) > bufLen) + goto fail; + seg = qrcodegen_makeAlphanumeric(text, tempBuffer); + } + else { + if(textLen > bufLen) + goto fail; + for(size_t i = 0; i < textLen; i++) + tempBuffer[i] = (uint8_t)text[i]; + seg.mode = qrcodegen_Mode_BYTE; + seg.bitLength = calcSegmentBitLength(seg.mode, textLen); + if(seg.bitLength == -1) + goto fail; + seg.numChars = (int)textLen; + seg.data = tempBuffer; + } + return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); + +fail: + qrcode[0] = 0; // Set size to invalid value for safety + return false; +} + + +// Public function - see documentation comment in header file. +bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], + enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) +{ + + struct qrcodegen_Segment seg; + seg.mode = qrcodegen_Mode_BYTE; + seg.bitLength = calcSegmentBitLength(seg.mode, dataLen); + if(seg.bitLength == -1) { + qrcode[0] = 0; // Set size to invalid value for safety + return false; + } + seg.numChars = (int)dataLen; + seg.data = dataAndTemp; + return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, dataAndTemp, qrcode); +} + + +// Appends the given number of low-order bits of the given value to the given byte-based +// bit buffer, increasing the bit length. Requires 0 <= numBits <= 16 and val < 2^numBits. +testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int * bitLen) +{ + LV_ASSERT(0 <= numBits && numBits <= 16 && (unsigned long)val >> numBits == 0); + for(int i = numBits - 1; i >= 0; i--, (*bitLen)++) + buffer[*bitLen >> 3] |= ((val >> i) & 1) << (7 - (*bitLen & 7)); +} + + + +/*---- Low-level QR Code encoding functions ----*/ + +// Public function - see documentation comment in header file. +bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, + enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]) +{ + return qrcodegen_encodeSegmentsAdvanced(segs, len, ecl, + qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, -1, true, tempBuffer, qrcode); +} + + +// Public function - see documentation comment in header file. +bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, + int minVersion, int maxVersion, int mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]) +{ + LV_ASSERT(segs != NULL || len == 0); + LV_ASSERT(qrcodegen_VERSION_MIN <= minVersion && minVersion <= maxVersion && maxVersion <= qrcodegen_VERSION_MAX); + LV_ASSERT(0 <= (int)ecl && (int)ecl <= 3 && -1 <= (int)mask && (int)mask <= 7); + + // Find the minimal version number to use + int version, dataUsedBits; + for(version = minVersion; ; version++) { + int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available + dataUsedBits = getTotalBits(segs, len, version); + if(dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) + break; // This version number is found to be suitable + if(version >= maxVersion) { // All versions in the range could not fit the given data + qrcode[0] = 0; // Set size to invalid value for safety + return false; + } + } + LV_ASSERT(dataUsedBits != -1); + + // Increase the error correction level while the data still fits in the current version number + for(int i = (int)qrcodegen_Ecc_MEDIUM; i <= (int)qrcodegen_Ecc_HIGH; i++) { // From low to high + if(boostEcl && dataUsedBits <= getNumDataCodewords(version, (enum qrcodegen_Ecc)i) * 8) + ecl = (enum qrcodegen_Ecc)i; + } + + // Concatenate all segments to create the data bit string + memset(qrcode, 0, qrcodegen_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0])); + int bitLen = 0; + for(size_t i = 0; i < len; i++) { + const struct qrcodegen_Segment * seg = &segs[i]; + appendBitsToBuffer((int)seg->mode, 4, qrcode, &bitLen); + appendBitsToBuffer(seg->numChars, numCharCountBits(seg->mode, version), qrcode, &bitLen); + for(int j = 0; j < seg->bitLength; j++) + appendBitsToBuffer((seg->data[j >> 3] >> (7 - (j & 7))) & 1, 1, qrcode, &bitLen); + } + LV_ASSERT(bitLen == dataUsedBits); + + // Add terminator and pad up to a byte if applicable + int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; + LV_ASSERT(bitLen <= dataCapacityBits); + int terminatorBits = dataCapacityBits - bitLen; + if(terminatorBits > 4) + terminatorBits = 4; + appendBitsToBuffer(0, terminatorBits, qrcode, &bitLen); + appendBitsToBuffer(0, (8 - bitLen % 8) % 8, qrcode, &bitLen); + LV_ASSERT(bitLen % 8 == 0); + + // Pad with alternating bytes until data capacity is reached + for(uint8_t padByte = 0xEC; bitLen < dataCapacityBits; padByte ^= 0xEC ^ 0x11) + appendBitsToBuffer(padByte, 8, qrcode, &bitLen); + + // Draw function and data codeword modules + addEccAndInterleave(qrcode, version, ecl, tempBuffer); + initializeFunctionModules(version, qrcode); + drawCodewords(tempBuffer, getNumRawDataModules(version) / 8, qrcode); + drawWhiteFunctionModules(qrcode, version); + initializeFunctionModules(version, tempBuffer); + + // Handle masking + if(mask == qrcodegen_Mask_AUTO) { // Automatically choose best mask + long minPenalty = LONG_MAX; + for(int i = 0; i < 8; i++) { + enum qrcodegen_Mask msk = (enum qrcodegen_Mask)i; + applyMask(tempBuffer, qrcode, msk); + drawFormatBits(ecl, msk, qrcode); + long penalty = getPenaltyScore(qrcode); + if(penalty < minPenalty) { + mask = msk; + minPenalty = penalty; + } + applyMask(tempBuffer, qrcode, msk); // Undoes the mask due to XOR + } + } + LV_ASSERT(0 <= (int)mask && (int)mask <= 7); + applyMask(tempBuffer, qrcode, mask); + drawFormatBits(ecl, mask, qrcode); + return true; +} + + + +/*---- Error correction code generation functions ----*/ + +// Appends error correction bytes to each block of the given data array, then interleaves +// bytes from the blocks and stores them in the result array. data[0 : dataLen] contains +// the input data. data[dataLen : rawCodewords] is used as a temporary work area and will +// be clobbered by this function. The final answer is stored in result[0 : rawCodewords]. +testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]) +{ + // Calculate parameter numbers + LV_ASSERT(0 <= (int)ecl && (int)ecl < 4 && qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); + int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version]; + int blockEccLen = ECC_CODEWORDS_PER_BLOCK [(int)ecl][version]; + int rawCodewords = getNumRawDataModules(version) / 8; + int dataLen = getNumDataCodewords(version, ecl); + int numShortBlocks = numBlocks - rawCodewords % numBlocks; + int shortBlockDataLen = rawCodewords / numBlocks - blockEccLen; + + // Split data into blocks, calculate ECC, and interleave + // (not concatenate) the bytes into a single sequence + uint8_t generator[qrcodegen_REED_SOLOMON_DEGREE_MAX]; + calcReedSolomonGenerator(blockEccLen, generator); + const uint8_t * dat = data; + for(int i = 0; i < numBlocks; i++) { + int datLen = shortBlockDataLen + (i < numShortBlocks ? 0 : 1); + uint8_t * ecc = &data[dataLen]; // Temporary storage + calcReedSolomonRemainder(dat, datLen, generator, blockEccLen, ecc); + for(int j = 0, k = i; j < datLen; j++, k += numBlocks) { // Copy data + if(j == shortBlockDataLen) + k -= numShortBlocks; + result[k] = dat[j]; + } + for(int j = 0, k = dataLen + i; j < blockEccLen; j++, k += numBlocks) // Copy ECC + result[k] = ecc[j]; + dat += datLen; + } +} + + +// Returns the number of 8-bit codewords that can be used for storing data (not ECC), +// for the given version number and error correction level. The result is in the range [9, 2956]. +testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl) +{ + int v = version, e = (int)ecl; + LV_ASSERT(0 <= e && e < 4); + return getNumRawDataModules(v) / 8 + - ECC_CODEWORDS_PER_BLOCK [e][v] + * NUM_ERROR_CORRECTION_BLOCKS[e][v]; +} + + +// Returns the number of data bits that can be stored in a QR Code of the given version number, after +// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. +// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. +testable int getNumRawDataModules(int ver) +{ + LV_ASSERT(qrcodegen_VERSION_MIN <= ver && ver <= qrcodegen_VERSION_MAX); + int result = (16 * ver + 128) * ver + 64; + if(ver >= 2) { + int numAlign = ver / 7 + 2; + result -= (25 * numAlign - 10) * numAlign - 55; + if(ver >= 7) + result -= 36; + } + return result; +} + + + +/*---- Reed-Solomon ECC generator functions ----*/ + +// Calculates the Reed-Solomon generator polynomial of the given degree, storing in result[0 : degree]. +testable void calcReedSolomonGenerator(int degree, uint8_t result[]) +{ + // Start with the monomial x^0 + LV_ASSERT(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); + memset(result, 0, degree * sizeof(result[0])); + result[degree - 1] = 1; + + // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), + // drop the highest term, and store the rest of the coefficients in order of descending powers. + // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). + uint8_t root = 1; + for(int i = 0; i < degree; i++) { + // Multiply the current product by (x - r^i) + for(int j = 0; j < degree; j++) { + result[j] = finiteFieldMultiply(result[j], root); + if(j + 1 < degree) + result[j] ^= result[j + 1]; + } + root = finiteFieldMultiply(root, 0x02); + } +} + + +// Calculates the remainder of the polynomial data[0 : dataLen] when divided by the generator[0 : degree], where all +// polynomials are in big endian and the generator has an implicit leading 1 term, storing the result in result[0 : degree]. +testable void calcReedSolomonRemainder(const uint8_t data[], int dataLen, + const uint8_t generator[], int degree, uint8_t result[]) +{ + + // Perform polynomial division + LV_ASSERT(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); + memset(result, 0, degree * sizeof(result[0])); + for(int i = 0; i < dataLen; i++) { + uint8_t factor = data[i] ^ result[0]; + memmove(&result[0], &result[1], (degree - 1) * sizeof(result[0])); + result[degree - 1] = 0; + for(int j = 0; j < degree; j++) + result[j] ^= finiteFieldMultiply(generator[j], factor); + } +} + +#undef qrcodegen_REED_SOLOMON_DEGREE_MAX + + +// Returns the product of the two given field elements modulo GF(2^8/0x11D). +// All inputs are valid. This could be implemented as a 256*256 lookup table. +testable uint8_t finiteFieldMultiply(uint8_t x, uint8_t y) +{ + // Russian peasant multiplication + uint8_t z = 0; + for(int i = 7; i >= 0; i--) { + z = (z << 1) ^ ((z >> 7) * 0x11D); + z ^= ((y >> i) & 1) * x; + } + return z; +} + + + +/*---- Drawing function modules ----*/ + +// Clears the given QR Code grid with white modules for the given +// version's size, then marks every function module as black. +testable void initializeFunctionModules(int version, uint8_t qrcode[]) +{ + // Initialize QR Code + int qrsize = version * 4 + 17; + memset(qrcode, 0, ((qrsize * qrsize + 7) / 8 + 1) * sizeof(qrcode[0])); + qrcode[0] = (uint8_t)qrsize; + + // Fill horizontal and vertical timing patterns + fillRectangle(6, 0, 1, qrsize, qrcode); + fillRectangle(0, 6, qrsize, 1, qrcode); + + // Fill 3 finder patterns (all corners except bottom right) and format bits + fillRectangle(0, 0, 9, 9, qrcode); + fillRectangle(qrsize - 8, 0, 8, 9, qrcode); + fillRectangle(0, qrsize - 8, 9, 8, qrcode); + + // Fill numerous alignment patterns + uint8_t alignPatPos[7]; + int numAlign = getAlignmentPatternPositions(version, alignPatPos); + for(int i = 0; i < numAlign; i++) { + for(int j = 0; j < numAlign; j++) { + // Don't draw on the three finder corners + if(!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0))) + fillRectangle(alignPatPos[i] - 2, alignPatPos[j] - 2, 5, 5, qrcode); + } + } + + // Fill version blocks + if(version >= 7) { + fillRectangle(qrsize - 11, 0, 3, 6, qrcode); + fillRectangle(0, qrsize - 11, 6, 3, qrcode); + } +} + + +// Draws white function modules and possibly some black modules onto the given QR Code, without changing +// non-function modules. This does not draw the format bits. This requires all function modules to be previously +// marked black (namely by initializeFunctionModules()), because this may skip redrawing black function modules. +static void drawWhiteFunctionModules(uint8_t qrcode[], int version) +{ + // Draw horizontal and vertical timing patterns + int qrsize = qrcodegen_getSize(qrcode); + for(int i = 7; i < qrsize - 7; i += 2) { + setModule(qrcode, 6, i, false); + setModule(qrcode, i, 6, false); + } + + // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) + for(int dy = -4; dy <= 4; dy++) { + for(int dx = -4; dx <= 4; dx++) { + int dist = abs(dx); + if(abs(dy) > dist) + dist = abs(dy); + if(dist == 2 || dist == 4) { + setModuleBounded(qrcode, 3 + dx, 3 + dy, false); + setModuleBounded(qrcode, qrsize - 4 + dx, 3 + dy, false); + setModuleBounded(qrcode, 3 + dx, qrsize - 4 + dy, false); + } + } + } + + // Draw numerous alignment patterns + uint8_t alignPatPos[7]; + int numAlign = getAlignmentPatternPositions(version, alignPatPos); + for(int i = 0; i < numAlign; i++) { + for(int j = 0; j < numAlign; j++) { + if((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0)) + continue; // Don't draw on the three finder corners + for(int dy = -1; dy <= 1; dy++) { + for(int dx = -1; dx <= 1; dx++) + setModule(qrcode, alignPatPos[i] + dx, alignPatPos[j] + dy, dx == 0 && dy == 0); + } + } + } + + // Draw version blocks + if(version >= 7) { + // Calculate error correction code and pack bits + int rem = version; // version is uint6, in the range [7, 40] + for(int i = 0; i < 12; i++) + rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); + long bits = (long)version << 12 | rem; // uint18 + LV_ASSERT(bits >> 18 == 0); + + // Draw two copies + for(int i = 0; i < 6; i++) { + for(int j = 0; j < 3; j++) { + int k = qrsize - 11 + j; + setModule(qrcode, k, i, (bits & 1) != 0); + setModule(qrcode, i, k, (bits & 1) != 0); + bits >>= 1; + } + } + } +} + + +// Draws two copies of the format bits (with its own error correction code) based +// on the given mask and error correction level. This always draws all modules of +// the format bits, unlike drawWhiteFunctionModules() which might skip black modules. +static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]) +{ + // Calculate error correction code and pack bits + LV_ASSERT(0 <= (int)mask && (int)mask <= 7); + static const int table[] = {1, 0, 3, 2}; + int data = table[(int)ecl] << 3 | (int)mask; // errCorrLvl is uint2, mask is uint3 + int rem = data; + for(int i = 0; i < 10; i++) + rem = (rem << 1) ^ ((rem >> 9) * 0x537); + int bits = (data << 10 | rem) ^ 0x5412; // uint15 + LV_ASSERT(bits >> 15 == 0); + + // Draw first copy + for(int i = 0; i <= 5; i++) + setModule(qrcode, 8, i, getBit(bits, i)); + setModule(qrcode, 8, 7, getBit(bits, 6)); + setModule(qrcode, 8, 8, getBit(bits, 7)); + setModule(qrcode, 7, 8, getBit(bits, 8)); + for(int i = 9; i < 15; i++) + setModule(qrcode, 14 - i, 8, getBit(bits, i)); + + // Draw second copy + int qrsize = qrcodegen_getSize(qrcode); + for(int i = 0; i < 8; i++) + setModule(qrcode, qrsize - 1 - i, 8, getBit(bits, i)); + for(int i = 8; i < 15; i++) + setModule(qrcode, 8, qrsize - 15 + i, getBit(bits, i)); + setModule(qrcode, 8, qrsize - 8, true); // Always black +} + + +// Calculates and stores an ascending list of positions of alignment patterns +// for this version number, returning the length of the list (in the range [0,7]). +// Each position is in the range [0,177), and are used on both the x and y axes. +// This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. +testable int getAlignmentPatternPositions(int version, uint8_t result[7]) +{ + if(version == 1) + return 0; + int numAlign = version / 7 + 2; + int step = (version == 32) ? 26 : + (version * 4 + numAlign * 2 + 1) / (numAlign * 2 - 2) * 2; + for(int i = numAlign - 1, pos = version * 4 + 10; i >= 1; i--, pos -= step) + result[i] = pos; + result[0] = 6; + return numAlign; +} + + +// Sets every pixel in the range [left : left + width] * [top : top + height] to black. +static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]) +{ + for(int dy = 0; dy < height; dy++) { + for(int dx = 0; dx < width; dx++) + setModule(qrcode, left + dx, top + dy, true); + } +} + + + +/*---- Drawing data modules and masking ----*/ + +// Draws the raw codewords (including data and ECC) onto the given QR Code. This requires the initial state of +// the QR Code to be black at function modules and white at codeword modules (including unused remainder bits). +static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]) +{ + int qrsize = qrcodegen_getSize(qrcode); + int i = 0; // Bit index into the data + // Do the funny zigzag scan + for(int right = qrsize - 1; right >= 1; right -= 2) { // Index of right column in each column pair + if(right == 6) + right = 5; + for(int vert = 0; vert < qrsize; vert++) { // Vertical counter + for(int j = 0; j < 2; j++) { + int x = right - j; // Actual x coordinate + bool upward = ((right + 1) & 2) == 0; + int y = upward ? qrsize - 1 - vert : vert; // Actual y coordinate + if(!getModule(qrcode, x, y) && i < dataLen * 8) { + bool black = getBit(data[i >> 3], 7 - (i & 7)); + setModule(qrcode, x, y, black); + i++; + } + // If this QR Code has any remainder bits (0 to 7), they were assigned as + // 0/false/white by the constructor and are left unchanged by this method + } + } + } + LV_ASSERT(i == dataLen * 8); +} + + +// XORs the codeword modules in this QR Code with the given mask pattern. +// The function modules must be marked and the codeword bits must be drawn +// before masking. Due to the arithmetic of XOR, calling applyMask() with +// the same mask value a second time will undo the mask. A final well-formed +// QR Code needs exactly one (not zero, two, etc.) mask applied. +static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask) +{ + LV_ASSERT(0 <= (int)mask && (int)mask <= 7); // Disallows qrcodegen_Mask_AUTO + int qrsize = qrcodegen_getSize(qrcode); + for(int y = 0; y < qrsize; y++) { + for(int x = 0; x < qrsize; x++) { + if(getModule(functionModules, x, y)) + continue; + bool invert; + switch((int)mask) { + case 0: + invert = (x + y) % 2 == 0; + break; + case 1: + invert = y % 2 == 0; + break; + case 2: + invert = x % 3 == 0; + break; + case 3: + invert = (x + y) % 3 == 0; + break; + case 4: + invert = (x / 3 + y / 2) % 2 == 0; + break; + case 5: + invert = x * y % 2 + x * y % 3 == 0; + break; + case 6: + invert = (x * y % 2 + x * y % 3) % 2 == 0; + break; + case 7: + invert = ((x + y) % 2 + x * y % 3) % 2 == 0; + break; + default: + LV_ASSERT(false); + return; + } + bool val = getModule(qrcode, x, y); + setModule(qrcode, x, y, val ^ invert); + } + } +} + + +// Calculates and returns the penalty score based on state of the given QR Code's current modules. +// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. +static long getPenaltyScore(const uint8_t qrcode[]) +{ + int qrsize = qrcodegen_getSize(qrcode); + long result = 0; + + // Adjacent modules in row having same color, and finder-like patterns + for(int y = 0; y < qrsize; y++) { + unsigned char runHistory[7] = {0}; + bool color = false; + unsigned char runX = 0; + for(int x = 0; x < qrsize; x++) { + if(getModule(qrcode, x, y) == color) { + runX++; + if(runX == 5) + result += PENALTY_N1; + else if(runX > 5) + result++; + } + else { + addRunToHistory(runX, runHistory); + if(!color && hasFinderLikePattern(runHistory)) + result += PENALTY_N3; + color = getModule(qrcode, x, y); + runX = 1; + } + } + addRunToHistory(runX, runHistory); + if(color) + addRunToHistory(0, runHistory); // Dummy run of white + if(hasFinderLikePattern(runHistory)) + result += PENALTY_N3; + } + // Adjacent modules in column having same color, and finder-like patterns + for(int x = 0; x < qrsize; x++) { + unsigned char runHistory[7] = {0}; + bool color = false; + unsigned char runY = 0; + for(int y = 0; y < qrsize; y++) { + if(getModule(qrcode, x, y) == color) { + runY++; + if(runY == 5) + result += PENALTY_N1; + else if(runY > 5) + result++; + } + else { + addRunToHistory(runY, runHistory); + if(!color && hasFinderLikePattern(runHistory)) + result += PENALTY_N3; + color = getModule(qrcode, x, y); + runY = 1; + } + } + addRunToHistory(runY, runHistory); + if(color) + addRunToHistory(0, runHistory); // Dummy run of white + if(hasFinderLikePattern(runHistory)) + result += PENALTY_N3; + } + + // 2*2 blocks of modules having same color + for(int y = 0; y < qrsize - 1; y++) { + for(int x = 0; x < qrsize - 1; x++) { + bool color = getModule(qrcode, x, y); + if(color == getModule(qrcode, x + 1, y) && + color == getModule(qrcode, x, y + 1) && + color == getModule(qrcode, x + 1, y + 1)) + result += PENALTY_N2; + } + } + + // Balance of black and white modules + int black = 0; + for(int y = 0; y < qrsize; y++) { + for(int x = 0; x < qrsize; x++) { + if(getModule(qrcode, x, y)) + black++; + } + } + int total = qrsize * qrsize; // Note that size is odd, so black/total != 1/2 + // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)% + int k = (int)((labs(black * 20L - total * 10L) + total - 1) / total) - 1; + result += k * PENALTY_N4; + return result; +} + + +// Inserts the given value to the front of the given array, which shifts over the +// existing values and deletes the last value. A helper function for getPenaltyScore(). +static void addRunToHistory(unsigned char run, unsigned char history[7]) +{ + memmove(&history[1], &history[0], 6 * sizeof(history[0])); + history[0] = run; +} + + +// Tests whether the given run history has the pattern of ratio 1:1:3:1:1 in the middle, and +// surrounded by at least 4 on either or both ends. A helper function for getPenaltyScore(). +// Must only be called immediately after a run of white modules has ended. +static bool hasFinderLikePattern(const unsigned char runHistory[7]) +{ + unsigned char n = runHistory[1]; + // The maximum QR Code size is 177, hence the run length n <= 177. + // Arithmetic is promoted to int, so n*4 will not overflow. + return n > 0 && runHistory[2] == n && runHistory[4] == n && runHistory[5] == n + && runHistory[3] == n * 3 && (runHistory[0] >= n * 4 || runHistory[6] >= n * 4); +} + + + +/*---- Basic QR Code information ----*/ + +// Public function - see documentation comment in header file. +int qrcodegen_getSize(const uint8_t qrcode[]) +{ + LV_ASSERT(qrcode != NULL); + int result = qrcode[0]; + LV_ASSERT((qrcodegen_VERSION_MIN * 4 + 17) <= result + && result <= (qrcodegen_VERSION_MAX * 4 + 17)); + return result; +} + + +// Public function - see documentation comment in header file. +bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y) +{ + LV_ASSERT(qrcode != NULL); + int qrsize = qrcode[0]; + return (0 <= x && x < qrsize && 0 <= y && y < qrsize) && getModule(qrcode, x, y); +} + + +// Gets the module at the given coordinates, which must be in bounds. +testable bool getModule(const uint8_t qrcode[], int x, int y) +{ + int qrsize = qrcode[0]; + LV_ASSERT(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); + int index = y * qrsize + x; + return getBit(qrcode[(index >> 3) + 1], index & 7); +} + + +// Sets the module at the given coordinates, which must be in bounds. +testable void setModule(uint8_t qrcode[], int x, int y, bool isBlack) +{ + int qrsize = qrcode[0]; + LV_ASSERT(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); + int index = y * qrsize + x; + int bitIndex = index & 7; + int byteIndex = (index >> 3) + 1; + if(isBlack) + qrcode[byteIndex] |= 1 << bitIndex; + else + qrcode[byteIndex] &= (1 << bitIndex) ^ 0xFF; +} + + +// Sets the module at the given coordinates, doing nothing if out of bounds. +testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack) +{ + int qrsize = qrcode[0]; + if(0 <= x && x < qrsize && 0 <= y && y < qrsize) + setModule(qrcode, x, y, isBlack); +} + + +// Returns true iff the i'th bit of x is set to 1. Requires x >= 0 and 0 <= i <= 14. +static bool getBit(int x, int i) +{ + return ((x >> i) & 1) != 0; +} + + + +/*---- Segment handling ----*/ + +// Public function - see documentation comment in header file. +bool qrcodegen_isAlphanumeric(const char * text) +{ + LV_ASSERT(text != NULL); + for(; *text != '\0'; text++) { + if(strchr(ALPHANUMERIC_CHARSET, *text) == NULL) + return false; + } + return true; +} + + +// Public function - see documentation comment in header file. +bool qrcodegen_isNumeric(const char * text) +{ + LV_ASSERT(text != NULL); + for(; *text != '\0'; text++) { + if(*text < '0' || *text > '9') + return false; + } + return true; +} + + +// Public function - see documentation comment in header file. +size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars) +{ + int temp = calcSegmentBitLength(mode, numChars); + if(temp == -1) + return SIZE_MAX; + LV_ASSERT(0 <= temp && temp <= INT16_MAX); + return ((size_t)temp + 7) / 8; +} + + +// Returns the number of data bits needed to represent a segment +// containing the given number of characters using the given mode. Notes: +// - Returns -1 on failure, i.e. numChars > INT16_MAX or +// the number of needed bits exceeds INT16_MAX (i.e. 32767). +// - Otherwise, all valid results are in the range [0, INT16_MAX]. +// - For byte mode, numChars measures the number of bytes, not Unicode code points. +// - For ECI mode, numChars must be 0, and the worst-case number of bits is returned. +// An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. +testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars) +{ + // All calculations are designed to avoid overflow on all platforms + if(numChars > (unsigned int)INT16_MAX) + return -1; + long result = (long)numChars; + if(mode == qrcodegen_Mode_NUMERIC) + result = (result * 10 + 2) / 3; // ceil(10/3 * n) + else if(mode == qrcodegen_Mode_ALPHANUMERIC) + result = (result * 11 + 1) / 2; // ceil(11/2 * n) + else if(mode == qrcodegen_Mode_BYTE) + result *= 8; + else if(mode == qrcodegen_Mode_KANJI) + result *= 13; + else if(mode == qrcodegen_Mode_ECI && numChars == 0) + result = 3 * 8; + else { // Invalid argument + LV_ASSERT(false); + return -1; + } + LV_ASSERT(result >= 0); + if((unsigned int)result > (unsigned int)INT16_MAX) + return -1; + return (int)result; +} + + +// Public function - see documentation comment in header file. +struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]) +{ + LV_ASSERT(data != NULL || len == 0); + struct qrcodegen_Segment result; + result.mode = qrcodegen_Mode_BYTE; + result.bitLength = calcSegmentBitLength(result.mode, len); + LV_ASSERT(result.bitLength != -1); + result.numChars = (int)len; + if(len > 0) + memcpy(buf, data, len * sizeof(buf[0])); + result.data = buf; + return result; +} + + +// Public function - see documentation comment in header file. +struct qrcodegen_Segment qrcodegen_makeNumeric(const char * digits, uint8_t buf[]) +{ + LV_ASSERT(digits != NULL); + struct qrcodegen_Segment result; + size_t len = strlen(digits); + result.mode = qrcodegen_Mode_NUMERIC; + int bitLen = calcSegmentBitLength(result.mode, len); + LV_ASSERT(bitLen != -1); + result.numChars = (int)len; + if(bitLen > 0) + memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); + result.bitLength = 0; + + unsigned int accumData = 0; + int accumCount = 0; + for(; *digits != '\0'; digits++) { + char c = *digits; + LV_ASSERT('0' <= c && c <= '9'); + accumData = accumData * 10 + (unsigned int)(c - '0'); + accumCount++; + if(accumCount == 3) { + appendBitsToBuffer(accumData, 10, buf, &result.bitLength); + accumData = 0; + accumCount = 0; + } + } + if(accumCount > 0) // 1 or 2 digits remaining + appendBitsToBuffer(accumData, accumCount * 3 + 1, buf, &result.bitLength); + LV_ASSERT(result.bitLength == bitLen); + result.data = buf; + return result; +} + + +// Public function - see documentation comment in header file. +struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char * text, uint8_t buf[]) +{ + LV_ASSERT(text != NULL); + struct qrcodegen_Segment result; + size_t len = strlen(text); + result.mode = qrcodegen_Mode_ALPHANUMERIC; + int bitLen = calcSegmentBitLength(result.mode, len); + LV_ASSERT(bitLen != -1); + result.numChars = (int)len; + if(bitLen > 0) + memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); + result.bitLength = 0; + + unsigned int accumData = 0; + int accumCount = 0; + for(; *text != '\0'; text++) { + const char * temp = strchr(ALPHANUMERIC_CHARSET, *text); + LV_ASSERT(temp != NULL); + accumData = accumData * 45 + (unsigned int)(temp - ALPHANUMERIC_CHARSET); + accumCount++; + if(accumCount == 2) { + appendBitsToBuffer(accumData, 11, buf, &result.bitLength); + accumData = 0; + accumCount = 0; + } + } + if(accumCount > 0) // 1 character remaining + appendBitsToBuffer(accumData, 6, buf, &result.bitLength); + LV_ASSERT(result.bitLength == bitLen); + result.data = buf; + return result; +} + + +// Public function - see documentation comment in header file. +struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]) +{ + struct qrcodegen_Segment result; + result.mode = qrcodegen_Mode_ECI; + result.numChars = 0; + result.bitLength = 0; + if(assignVal < 0) { + LV_ASSERT(false); + } + else if(assignVal < (1 << 7)) { + memset(buf, 0, 1 * sizeof(buf[0])); + appendBitsToBuffer(assignVal, 8, buf, &result.bitLength); + } + else if(assignVal < (1 << 14)) { + memset(buf, 0, 2 * sizeof(buf[0])); + appendBitsToBuffer(2, 2, buf, &result.bitLength); + appendBitsToBuffer(assignVal, 14, buf, &result.bitLength); + } + else if(assignVal < 1000000L) { + memset(buf, 0, 3 * sizeof(buf[0])); + appendBitsToBuffer(6, 3, buf, &result.bitLength); + appendBitsToBuffer(assignVal >> 10, 11, buf, &result.bitLength); + appendBitsToBuffer(assignVal & 0x3FF, 10, buf, &result.bitLength); + } + else { + LV_ASSERT(false); + } + result.data = buf; + return result; +} + + +// Calculates the number of bits needed to encode the given segments at the given version. +// Returns a non-negative number if successful. Otherwise returns -1 if a segment has too +// many characters to fit its length field, or the total bits exceeds INT16_MAX. +testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version) +{ + LV_ASSERT(segs != NULL || len == 0); + long result = 0; + for(size_t i = 0; i < len; i++) { + int numChars = segs[i].numChars; + int bitLength = segs[i].bitLength; + LV_ASSERT(0 <= numChars && numChars <= INT16_MAX); + LV_ASSERT(0 <= bitLength && bitLength <= INT16_MAX); + int ccbits = numCharCountBits(segs[i].mode, version); + LV_ASSERT(0 <= ccbits && ccbits <= 16); + if(numChars >= (1L << ccbits)) + return -1; // The segment's length doesn't fit the field's bit width + result += 4L + ccbits + bitLength; + if(result > INT16_MAX) + return -1; // The sum might overflow an int type + } + LV_ASSERT(0 <= result && result <= INT16_MAX); + return (int)result; +} + + +// Returns the bit width of the character count field for a segment in the given mode +// in a QR Code at the given version number. The result is in the range [0, 16]. +static int numCharCountBits(enum qrcodegen_Mode mode, int version) +{ + LV_ASSERT(qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); + int i = (version + 7) / 17; + switch(mode) { + case qrcodegen_Mode_NUMERIC : { + static const int temp[] = {10, 12, 14}; + return temp[i]; + } + case qrcodegen_Mode_ALPHANUMERIC: { + static const int temp[] = { 9, 11, 13}; + return temp[i]; + } + case qrcodegen_Mode_BYTE : { + static const int temp[] = { 8, 16, 16}; + return temp[i]; + } + case qrcodegen_Mode_KANJI : { + static const int temp[] = { 8, 10, 12}; + return temp[i]; + } + case qrcodegen_Mode_ECI : + return 0; + default: + LV_ASSERT(false); + return -1; // Dummy value + } +} + +int qrcodegen_getMinFitVersion(enum qrcodegen_Ecc ecl, size_t dataLen) +{ + struct qrcodegen_Segment seg; + seg.mode = qrcodegen_Mode_BYTE; + seg.bitLength = calcSegmentBitLength(seg.mode, dataLen); + seg.numChars = (int)dataLen; + + for(int version = qrcodegen_VERSION_MIN; version <= qrcodegen_VERSION_MAX; version++) { + int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available + int dataUsedBits = getTotalBits(&seg, 1, version); + if(dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) + return version; + } + return -1; +} + +int qrcodegen_version2size(int version) +{ + if(version < qrcodegen_VERSION_MIN || version > qrcodegen_VERSION_MAX) { + return -1; + } + + return ((version - 1) * 4 + 21); +} diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.h b/lib/libesp32_lvgl/lvgl/src/libs/qrcode/qrcodegen.h similarity index 82% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.h rename to lib/libesp32_lvgl/lvgl/src/libs/qrcode/qrcodegen.h index b484e9175..986bada58 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.h +++ b/lib/libesp32_lvgl/lvgl/src/libs/qrcode/qrcodegen.h @@ -55,12 +55,12 @@ extern "C" { * The error correction level in a QR Code symbol. */ enum qrcodegen_Ecc { - // Must be declared in ascending order of error protection - // so that an internal qrcodegen function works properly - qrcodegen_Ecc_LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords - qrcodegen_Ecc_MEDIUM , // The QR Code can tolerate about 15% erroneous codewords - qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords - qrcodegen_Ecc_HIGH , // The QR Code can tolerate about 30% erroneous codewords + // Must be declared in ascending order of error protection + // so that an internal qrcodegen function works properly + qrcodegen_Ecc_LOW = 0, // The QR Code can tolerate about 7% erroneous codewords + qrcodegen_Ecc_MEDIUM, // The QR Code can tolerate about 15% erroneous codewords + qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords + qrcodegen_Ecc_HIGH, // The QR Code can tolerate about 30% erroneous codewords }; @@ -68,18 +68,18 @@ enum qrcodegen_Ecc { * The mask pattern used in a QR Code symbol. */ enum qrcodegen_Mask { - // A special value to tell the QR Code encoder to - // automatically select an appropriate mask pattern - qrcodegen_Mask_AUTO = -1, - // The eight actual mask patterns - qrcodegen_Mask_0 = 0, - qrcodegen_Mask_1, - qrcodegen_Mask_2, - qrcodegen_Mask_3, - qrcodegen_Mask_4, - qrcodegen_Mask_5, - qrcodegen_Mask_6, - qrcodegen_Mask_7, + // A special value to tell the QR Code encoder to + // automatically select an appropriate mask pattern + qrcodegen_Mask_AUTO = -1, + // The eight actual mask patterns + qrcodegen_Mask_0 = 0, + qrcodegen_Mask_1, + qrcodegen_Mask_2, + qrcodegen_Mask_3, + qrcodegen_Mask_4, + qrcodegen_Mask_5, + qrcodegen_Mask_6, + qrcodegen_Mask_7, }; @@ -87,11 +87,11 @@ enum qrcodegen_Mask { * Describes how a segment's data bits are interpreted. */ enum qrcodegen_Mode { - qrcodegen_Mode_NUMERIC = 0x1, - qrcodegen_Mode_ALPHANUMERIC = 0x2, - qrcodegen_Mode_BYTE = 0x4, - qrcodegen_Mode_KANJI = 0x8, - qrcodegen_Mode_ECI = 0x7, + qrcodegen_Mode_NUMERIC = 0x1, + qrcodegen_Mode_ALPHANUMERIC = 0x2, + qrcodegen_Mode_BYTE = 0x4, + qrcodegen_Mode_KANJI = 0x8, + qrcodegen_Mode_ECI = 0x7, }; @@ -107,22 +107,22 @@ enum qrcodegen_Mode { * the largest QR Code (version 40) has 31329 modules. */ struct qrcodegen_Segment { - // The mode indicator of this segment. - enum qrcodegen_Mode mode; - - // The length of this segment's unencoded data. Measured in characters for - // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. - // Always zero or positive. Not the same as the data's bit length. - int numChars; - - // The data bits of this segment, packed in bitwise big endian. - // Can be null if the bit length is zero. - uint8_t *data; - - // The number of valid data bits used in the buffer. Requires - // 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8. - // The character count (numChars) must agree with the mode and the bit buffer length. - int bitLength; + // The mode indicator of this segment. + enum qrcodegen_Mode mode; + + // The length of this segment's unencoded data. Measured in characters for + // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. + // Always zero or positive. Not the same as the data's bit length. + int numChars; + + // The data bits of this segment, packed in bitwise big endian. + // Can be null if the bit length is zero. + uint8_t * data; + + // The number of valid data bits used in the buffer. Requires + // 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8. + // The character count (numChars) must agree with the mode and the bit buffer length. + int bitLength; }; @@ -166,8 +166,8 @@ struct qrcodegen_Segment { * - Please consult the QR Code specification for information on * data capacities per version, ECC level, and text encoding mode. */ -bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); +bool qrcodegen_encodeText(const char * text, uint8_t tempBuffer[], uint8_t qrcode[], + enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); /* @@ -189,7 +189,7 @@ bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode * data capacities per version, ECC level, and text encoding mode. */ bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); + enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); /*---- Functions (low level) to generate QR Codes ----*/ @@ -207,7 +207,7 @@ bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcod * But the qrcode array must not overlap tempBuffer or any segment's data buffer. */ bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, - enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]); + enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]); /* @@ -226,7 +226,7 @@ bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, * But the qrcode array must not overlap tempBuffer or any segment's data buffer. */ bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, - int minVersion, int maxVersion, int mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]); + int minVersion, int maxVersion, int mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]); /* @@ -234,14 +234,14 @@ bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], siz * A string is encodable iff each character is in the following set: 0 to 9, A to Z * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon. */ -bool qrcodegen_isAlphanumeric(const char *text); +bool qrcodegen_isAlphanumeric(const char * text); /* * Tests whether the given string can be encoded as a segment in numeric mode. * A string is encodable iff each character is in the range 0 to 9. */ -bool qrcodegen_isNumeric(const char *text); +bool qrcodegen_isNumeric(const char * text); /* @@ -269,7 +269,7 @@ struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, u /* * Returns a segment representing the given string of decimal digits encoded in numeric mode. */ -struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]); +struct qrcodegen_Segment qrcodegen_makeNumeric(const char * digits, uint8_t buf[]); /* @@ -277,7 +277,7 @@ struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[] * The characters allowed are: 0 to 9, A to Z (uppercase only), space, * dollar, percent, asterisk, plus, hyphen, period, slash, colon. */ -struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]); +struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char * text, uint8_t buf[]); /* diff --git a/lib/libesp32_lvgl/lvgl/src/libs/rle/lv_rle.c b/lib/libesp32_lvgl/lvgl/src/libs/rle/lv_rle.c new file mode 100644 index 000000000..f19660b8b --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/rle/lv_rle.c @@ -0,0 +1,99 @@ +/** + * @file lv_rle.c + */ + +/********************* + * INCLUDES + *********************/ + +#include "../../stdlib/lv_string.h" +#include "lv_rle.h" + +#if LV_USE_RLE + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +uint32_t lv_rle_decompress(const uint8_t * input, + uint32_t input_buff_len, uint8_t * output, + uint32_t output_buff_len, uint8_t blk_size) +{ + uint32_t ctrl_byte; + uint32_t rd_len = 0; + uint32_t wr_len = 0; + + while(rd_len < input_buff_len) { + ctrl_byte = input[0]; + rd_len++; + input++; + if(rd_len > input_buff_len) + return 0; + + if(ctrl_byte & 0x80) { + /* copy directly from input to output */ + uint32_t bytes = blk_size * (ctrl_byte & 0x7f); + rd_len += bytes; + if(rd_len > input_buff_len) + return 0; + + wr_len += bytes; + if(wr_len > output_buff_len) + return 0; + + lv_memcpy(output, input, bytes); + output += bytes; + input += bytes; + } + else { + rd_len += blk_size; + if(rd_len > input_buff_len) + return 0; + + wr_len += blk_size * ctrl_byte; + if(wr_len > output_buff_len) + return 0; + + if(blk_size == 1) { + /* optimize the most common case. */ + lv_memset(output, input[0], ctrl_byte); + output += ctrl_byte; + } + else { + for(uint32_t i = 0; i < ctrl_byte; i++) { + lv_memcpy(output, input, blk_size); + output += blk_size; + } + } + input += blk_size; + } + } + + return wr_len; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_RLE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/rle/lv_rle.h b/lib/libesp32_lvgl/lvgl/src/libs/rle/lv_rle.h new file mode 100644 index 000000000..a6298cbca --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/rle/lv_rle.h @@ -0,0 +1,46 @@ +/** + * @file lv_rle.h + * + */ + +#ifndef LV_RLE_H +#define LV_RLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_RLE + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +uint32_t lv_rle_decompress(const uint8_t * input, + uint32_t input_buff_len, uint8_t * output, + uint32_t output_buff_len, uint8_t blk_size); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_RLE*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_RLE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/rlottie/lv_rlottie.c b/lib/libesp32_lvgl/lvgl/src/libs/rlottie/lv_rlottie.c similarity index 61% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/rlottie/lv_rlottie.c rename to lib/libesp32_lvgl/lvgl/src/libs/rlottie/lv_rlottie.c index a264948c3..33b671f1f 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/rlottie/lv_rlottie.c +++ b/lib/libesp32_lvgl/lvgl/src/libs/rlottie/lv_rlottie.c @@ -32,17 +32,24 @@ static void next_frame_task_cb(lv_timer_t * t); /********************** * STATIC VARIABLES **********************/ + const lv_obj_class_t lv_rlottie_class = { .constructor_cb = lv_rlottie_constructor, .destructor_cb = lv_rlottie_destructor, .instance_size = sizeof(lv_rlottie_t), - .base_class = &lv_img_class + .base_class = &lv_image_class, + .name = "rlottie", }; -static lv_coord_t create_width; -static lv_coord_t create_height; -static const char * rlottie_desc_create; -static const char * path_create; +typedef struct { + int32_t width; + int32_t height; + const char * rlottie_desc; + const char * path; +} lv_rlottie_create_info_t; + +/*Only used in lv_obj_class_create_obj, no affect multiple instances*/ +static lv_rlottie_create_info_t create_info; /********************** * MACROS @@ -52,29 +59,26 @@ static const char * path_create; * GLOBAL FUNCTIONS **********************/ -lv_obj_t * lv_rlottie_create_from_file(lv_obj_t * parent, lv_coord_t width, lv_coord_t height, const char * path) +lv_obj_t * lv_rlottie_create_from_file(lv_obj_t * parent, int32_t width, int32_t height, const char * path) { - - create_width = width; - create_height = height; - path_create = path; - rlottie_desc_create = NULL; + create_info.width = width; + create_info.height = height; + create_info.path = path; + create_info.rlottie_desc = NULL; LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); lv_obj_class_init_obj(obj); return obj; - } -lv_obj_t * lv_rlottie_create_from_raw(lv_obj_t * parent, lv_coord_t width, lv_coord_t height, const char * rlottie_desc) +lv_obj_t * lv_rlottie_create_from_raw(lv_obj_t * parent, int32_t width, int32_t height, const char * rlottie_desc) { - - create_width = width; - create_height = height; - rlottie_desc_create = rlottie_desc; - path_create = NULL; + create_info.width = width; + create_info.height = height; + create_info.rlottie_desc = rlottie_desc; + create_info.path = NULL; LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); @@ -109,11 +113,11 @@ static void lv_rlottie_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob LV_UNUSED(class_p); lv_rlottie_t * rlottie = (lv_rlottie_t *) obj; - if(rlottie_desc_create) { - rlottie->animation = lottie_animation_from_data(rlottie_desc_create, rlottie_desc_create, ""); + if(create_info.rlottie_desc) { + rlottie->animation = lottie_animation_from_data(create_info.rlottie_desc, create_info.rlottie_desc, ""); } - else if(path_create) { - rlottie->animation = lottie_animation_from_file(path_create); + else if(create_info.path) { + rlottie->animation = lottie_animation_from_file(create_info.path); } if(rlottie->animation == NULL) { LV_LOG_WARN("The aniamtion can't be opened"); @@ -124,23 +128,22 @@ static void lv_rlottie_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob rlottie->framerate = (size_t)lottie_animation_get_framerate(rlottie->animation); rlottie->current_frame = 0; - rlottie->scanline_width = create_width * LV_ARGB32 / 8; + rlottie->scanline_width = create_info.width * LV_ARGB32 / 8; - size_t allocaled_buf_size = (create_width * create_height * LV_ARGB32 / 8); - rlottie->allocated_buf = lv_mem_alloc(allocaled_buf_size); + size_t allocaled_buf_size = (create_info.width * create_info.height * LV_ARGB32 / 8); + rlottie->allocated_buf = lv_malloc(allocaled_buf_size); if(rlottie->allocated_buf != NULL) { rlottie->allocated_buffer_size = allocaled_buf_size; memset(rlottie->allocated_buf, 0, allocaled_buf_size); } - rlottie->imgdsc.header.always_zero = 0; - rlottie->imgdsc.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA; - rlottie->imgdsc.header.h = create_height; - rlottie->imgdsc.header.w = create_width; + rlottie->imgdsc.header.cf = LV_COLOR_FORMAT_ARGB8888; + rlottie->imgdsc.header.h = create_info.height; + rlottie->imgdsc.header.w = create_info.width; rlottie->imgdsc.data = (void *)rlottie->allocated_buf; rlottie->imgdsc.data_size = allocaled_buf_size; - lv_img_set_src(obj, &rlottie->imgdsc); + lv_image_set_src(obj, &rlottie->imgdsc); rlottie->play_ctrl = LV_RLOTTIE_CTRL_FORWARD | LV_RLOTTIE_CTRL_PLAY | LV_RLOTTIE_CTRL_LOOP; rlottie->dest_frame = rlottie->total_frames; /* invalid destination frame so it's possible to pause on frame 0 */ @@ -150,7 +153,6 @@ static void lv_rlottie_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob lv_obj_update_layout(obj); } - static void lv_rlottie_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { LV_UNUSED(class_p); @@ -166,63 +168,22 @@ static void lv_rlottie_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj } if(rlottie->task) { - lv_timer_del(rlottie->task); + lv_timer_delete(rlottie->task); rlottie->task = NULL; rlottie->play_ctrl = LV_RLOTTIE_CTRL_FORWARD; rlottie->dest_frame = 0; } - lv_img_cache_invalidate_src(&rlottie->imgdsc); + lv_image_cache_drop(&rlottie->imgdsc); + if(rlottie->allocated_buf) { - lv_mem_free(rlottie->allocated_buf); + lv_free(rlottie->allocated_buf); rlottie->allocated_buf = NULL; rlottie->allocated_buffer_size = 0; } } -#if LV_COLOR_DEPTH == 16 -static void convert_to_rgba5658(uint32_t * pix, const size_t width, const size_t height) -{ - /* rlottie draws in ARGB32 format, but LVGL only deal with RGB565 format with (optional 8 bit alpha channel) - so convert in place here the received buffer to LVGL format. */ - uint8_t * dest = (uint8_t *)pix; - uint32_t * src = pix; - for(size_t y = 0; y < height; y++) { - /* Convert a 4 bytes per pixel in format ARGB to R5G6B5A8 format - naive way: - r = ((c & 0xFF0000) >> 19) - g = ((c & 0xFF00) >> 10) - b = ((c & 0xFF) >> 3) - rgb565 = (r << 11) | (g << 5) | b - a = c >> 24; - That's 3 mask, 6 bitshift and 2 or operations - - A bit better: - r = ((c & 0xF80000) >> 8) - g = ((c & 0xFC00) >> 5) - b = ((c & 0xFF) >> 3) - rgb565 = r | g | b - a = c >> 24; - That's 3 mask, 3 bitshifts and 2 or operations */ - for(size_t x = 0; x < width; x++) { - uint32_t in = src[x]; -#if LV_COLOR_16_SWAP == 0 - uint16_t r = (uint16_t)(((in & 0xF80000) >> 8) | ((in & 0xFC00) >> 5) | ((in & 0xFF) >> 3)); -#else - /* We want: rrrr rrrr GGGg gggg bbbb bbbb => gggb bbbb rrrr rGGG */ - uint16_t r = (uint16_t)(((in & 0xF80000) >> 16) | ((in & 0xFC00) >> 13) | ((in & 0x1C00) << 3) | ((in & 0xF8) << 5)); -#endif - - lv_memcpy(dest, &r, sizeof(r)); - dest[sizeof(r)] = (uint8_t)(in >> 24); - dest += LV_IMG_PX_SIZE_ALPHA_BYTE; - } - src += width; - } -} -#endif - static void next_frame_task_cb(lv_timer_t * t) { lv_obj_t * obj = t->user_data; @@ -244,7 +205,7 @@ static void next_frame_task_cb(lv_timer_t * t) if((rlottie->play_ctrl & LV_RLOTTIE_CTRL_LOOP) == LV_RLOTTIE_CTRL_LOOP) rlottie->current_frame = rlottie->total_frames - 1; else { - lv_event_send(obj, LV_EVENT_READY, NULL); + lv_obj_send_event(obj, LV_EVENT_READY, NULL); lv_timer_pause(t); return; } @@ -257,7 +218,7 @@ static void next_frame_task_cb(lv_timer_t * t) if((rlottie->play_ctrl & LV_RLOTTIE_CTRL_LOOP) == LV_RLOTTIE_CTRL_LOOP) rlottie->current_frame = 0; else { - lv_event_send(obj, LV_EVENT_READY, NULL); + lv_obj_send_event(obj, LV_EVENT_READY, NULL); lv_timer_pause(t); return; } @@ -274,10 +235,6 @@ static void next_frame_task_cb(lv_timer_t * t) rlottie->scanline_width ); -#if LV_COLOR_DEPTH == 16 - convert_to_rgba5658(rlottie->allocated_buf, rlottie->imgdsc.header.w, rlottie->imgdsc.header.h); -#endif - lv_obj_invalidate(obj); } diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/rlottie/lv_rlottie.h b/lib/libesp32_lvgl/lvgl/src/libs/rlottie/lv_rlottie.h similarity index 82% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/rlottie/lv_rlottie.h rename to lib/libesp32_lvgl/lvgl/src/libs/rlottie/lv_rlottie.h index d66dc22c0..652a1a9aa 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/rlottie/lv_rlottie.h +++ b/lib/libesp32_lvgl/lvgl/src/libs/rlottie/lv_rlottie.h @@ -34,10 +34,10 @@ typedef enum { /** definition in lottieanimation_capi.c */ struct Lottie_Animation_S; typedef struct { - lv_img_t img_ext; + lv_image_t img_ext; struct Lottie_Animation_S * animation; lv_timer_t * task; - lv_img_dsc_t imgdsc; + lv_image_dsc_t imgdsc; size_t total_frames; size_t current_frame; size_t framerate; @@ -48,15 +48,15 @@ typedef struct { size_t dest_frame; } lv_rlottie_t; -extern const lv_obj_class_t lv_rlottie_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_rlottie_class; /********************** * GLOBAL PROTOTYPES **********************/ -lv_obj_t * lv_rlottie_create_from_file(lv_obj_t * parent, lv_coord_t width, lv_coord_t height, const char * path); +lv_obj_t * lv_rlottie_create_from_file(lv_obj_t * parent, int32_t width, int32_t height, const char * path); -lv_obj_t * lv_rlottie_create_from_raw(lv_obj_t * parent, lv_coord_t width, lv_coord_t height, +lv_obj_t * lv_rlottie_create_from_raw(lv_obj_t * parent, int32_t width, int32_t height, const char * rlottie_desc); void lv_rlottie_set_play_mode(lv_obj_t * rlottie, const lv_rlottie_ctrl_t ctrl); diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/add_lvgl_if.sh b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/add_lvgl_if.sh new file mode 100755 index 000000000..43ce90306 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/add_lvgl_if.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +#Add LVGL #if LV_USE_THORVG_INTERNAL guard +#Usage +# find -name "*.cpp" | xargs ./add_lvgl_if.sh +# find -name "t*.h" | xargs ./add_lvgl_if.sh + +sed '0,/\*\/$/ {/\*\/$/ {n; s|^|\n#include "../../lv_conf_internal.h"\n#if LV_USE_THORVG_INTERNAL\n|}}' $@ -i + +sed -i -e '$a\ +\ +#endif /* LV_USE_THORVG_INTERNAL */\ +' $@ -i diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/config.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/config.h new file mode 100644 index 000000000..abeed9415 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/config.h @@ -0,0 +1,15 @@ +/* + * Autogenerated by the Meson build system. + * Do not edit, your changes will be lost. + */ + +#pragma once + +#define THORVG_CAPI_BINDING_SUPPORT 1 + +#define THORVG_SVG_LOADER_SUPPORT 1 + +#define THORVG_SW_RASTER_SUPPORT 1 + +#define THORVG_VERSION_STRING "0.11.99" + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/thorvg.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/thorvg.h new file mode 100644 index 000000000..7f5a84b94 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/thorvg.h @@ -0,0 +1,1925 @@ +/*! + * @file thorvg.h + * + * The main APIs enabling the TVG initialization, preparation of the canvas and provisioning of its content: + * - drawing shapes: line, arc, curve, path, polygon... + * - drawing pictures: tvg, svg, png, jpg, bitmap... + * - drawing fillings: solid, linear and radial gradient... + * - drawing stroking: continuous stroking with arbitrary width, join, cap, dash styles. + * - drawing composition: blending, masking, path clipping... + * - drawing scene graph & affine transformation (translation, rotation, scale, ...) + * and finally drawing the canvas and TVG termination. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + + +#ifndef _THORVG_H_ +#define _THORVG_H_ + +#include +#include +#include +#include + +#ifdef TVG_API + #undef TVG_API +#endif + +#ifndef TVG_STATIC + #ifdef _WIN32 + #if TVG_BUILD + #define TVG_API __declspec(dllexport) + #else + #define TVG_API __declspec(dllimport) + #endif + #elif (defined(__SUNPRO_C) || defined(__SUNPRO_CC)) + #define TVG_API __global + #else + #if (defined(__GNUC__) && __GNUC__ >= 4) || defined(__INTEL_COMPILER) + #define TVG_API __attribute__ ((visibility("default"))) + #else + #define TVG_API + #endif + #endif +#else + #define TVG_API +#endif + +#ifdef TVG_DEPRECATED + #undef TVG_DEPRECATED +#endif + +#ifdef _WIN32 + #define TVG_DEPRECATED __declspec(deprecated) +#elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) + #define TVG_DEPRECATED __attribute__ ((__deprecated__)) +#else + #define TVG_DEPRECATED +#endif + +#define _TVG_DECLARE_PRIVATE(A) \ + struct Impl; \ + Impl* pImpl; \ +protected: \ + A(const A&) = delete; \ + const A& operator=(const A&) = delete; \ + A() + +#define _TVG_DISABLE_CTOR(A) \ + A() = delete; \ + ~A() = delete + +#define _TVG_DECLARE_ACCESSOR(A) \ + friend A + +namespace tvg +{ + +class RenderMethod; +class Animation; + +/** + * @defgroup ThorVG ThorVG + * @brief ThorVG classes and enumerations providing C++ APIs. + */ + +/**@{*/ + +/** + * @brief Enumeration specifying the result from the APIs. + */ +enum class Result +{ + Success = 0, ///< The value returned in case of a correct request execution. + InvalidArguments, ///< The value returned in the event of a problem with the arguments given to the API - e.g. empty paths or null pointers. + InsufficientCondition, ///< The value returned in case the request cannot be processed - e.g. asking for properties of an object, which does not exist. + FailedAllocation, ///< The value returned in case of unsuccessful memory allocation. + MemoryCorruption, ///< The value returned in the event of bad memory handling - e.g. failing in pointer releasing or casting + NonSupport, ///< The value returned in case of choosing unsupported options. + Unknown ///< The value returned in all other cases. +}; + + +/** + * @brief Enumeration specifying the values of the path commands accepted by TVG. + * + * Not to be confused with the path commands from the svg path element (like M, L, Q, H and many others). + * TVG interprets all of them and translates to the ones from the PathCommand values. + */ +enum class PathCommand +{ + Close = 0, ///< Ends the current sub-path and connects it with its initial point. This command doesn't expect any points. + MoveTo, ///< Sets a new initial point of the sub-path and a new current point. This command expects 1 point: the starting position. + LineTo, ///< Draws a line from the current point to the given point and sets a new value of the current point. This command expects 1 point: the end-position of the line. + CubicTo ///< Draws a cubic Bezier curve from the current point to the given point using two given control points and sets a new value of the current point. This command expects 3 points: the 1st control-point, the 2nd control-point, the end-point of the curve. +}; + + +/** + * @brief Enumeration determining the ending type of a stroke in the open sub-paths. + */ +enum class StrokeCap +{ + Square = 0, ///< The stroke is extended in both end-points of a sub-path by a rectangle, with the width equal to the stroke width and the length equal to the half of the stroke width. For zero length sub-paths the square is rendered with the size of the stroke width. + Round, ///< The stroke is extended in both end-points of a sub-path by a half circle, with a radius equal to the half of a stroke width. For zero length sub-paths a full circle is rendered. + Butt ///< The stroke ends exactly at each of the two end-points of a sub-path. For zero length sub-paths no stroke is rendered. +}; + + +/** + * @brief Enumeration determining the style used at the corners of joined stroked path segments. + */ +enum class StrokeJoin +{ + Bevel = 0, ///< The outer corner of the joined path segments is bevelled at the join point. The triangular region of the corner is enclosed by a straight line between the outer corners of each stroke. + Round, ///< The outer corner of the joined path segments is rounded. The circular region is centered at the join point. + Miter ///< The outer corner of the joined path segments is spiked. The spike is created by extension beyond the join point of the outer edges of the stroke until they intersect. In case the extension goes beyond the limit, the join style is converted to the Bevel style. +}; + + +/** + * @brief Enumeration specifying how to fill the area outside the gradient bounds. + */ +enum class FillSpread +{ + Pad = 0, ///< The remaining area is filled with the closest stop color. + Reflect, ///< The gradient pattern is reflected outside the gradient area until the expected region is filled. + Repeat ///< The gradient pattern is repeated continuously beyond the gradient area until the expected region is filled. +}; + + +/** + * @brief Enumeration specifying the algorithm used to establish which parts of the shape are treated as the inside of the shape. + */ +enum class FillRule +{ + Winding = 0, ///< A line from the point to a location outside the shape is drawn. The intersections of the line with the path segment of the shape are counted. Starting from zero, if the path segment of the shape crosses the line clockwise, one is added, otherwise one is subtracted. If the resulting sum is non zero, the point is inside the shape. + EvenOdd ///< A line from the point to a location outside the shape is drawn and its intersections with the path segments of the shape are counted. If the number of intersections is an odd number, the point is inside the shape. +}; + + +/** + * @brief Enumeration indicating the method used in the composition of two objects - the target and the source. + * + * Notation: S(Source), T(Target), SA(Source Alpha), TA(Target Alpha) + * + * @see Paint::composite() + */ +enum class CompositeMethod +{ + None = 0, ///< No composition is applied. + ClipPath, ///< The intersection of the source and the target is determined and only the resulting pixels from the source are rendered. + AlphaMask, ///< Alpha Masking using the compositing target's pixels as an alpha value. + InvAlphaMask, ///< Alpha Masking using the complement to the compositing target's pixels as an alpha value. + LumaMask, ///< Alpha Masking using the grayscale (0.2125R + 0.7154G + 0.0721*B) of the compositing target's pixels. @since 0.9 + InvLumaMask, ///< Alpha Masking using the grayscale (0.2125R + 0.7154G + 0.0721*B) of the complement to the compositing target's pixels. + AddMask, ///< Combines the target and source objects pixels using target alpha. (T * TA) + (S * (255 - TA)) @BETA_API + SubtractMask, ///< Subtracts the source color from the target color while considering their respective target alpha. (T * TA) - (S * (255 - TA)) @BETA_API + IntersectMask, ///< Computes the result by taking the minimum value between the target alpha and the source alpha and multiplies it with the target color. (T * min(TA, SA)) @BETA_API + DifferenceMask ///< Calculates the absolute difference between the target color and the source color multiplied by the complement of the target alpha. abs(T - S * (255 - TA)) @BETA_API +}; + + +/** + * @brief Enumeration indicates the method used for blending paint. Please refer to the respective formulas for each method. + * + * Notation: S(source paint as the top layer), D(destination as the bottom layer), Sa(source paint alpha), Da(destination alpha) + * + * @see Paint::blend() + * + * @BETA_API + */ +enum class BlendMethod : uint8_t +{ + Normal = 0, ///< Perform the alpha blending(default). S if (Sa == 255), otherwise (Sa * S) + (255 - Sa) * D + Add, ///< Simply adds pixel values of one layer with the other. (S + D) + Screen, ///< The values of the pixels in the two layers are inverted, multiplied, and then inverted again. (S + D) - (S * D) + Multiply, ///< Takes the RGB channel values from 0 to 255 of each pixel in the top layer and multiples them with the values for the corresponding pixel from the bottom layer. (S * D) + Overlay, ///< Combines Multiply and Screen blend modes. (2 * S * D) if (2 * D < Da), otherwise (Sa * Da) - 2 * (Da - S) * (Sa - D) + Difference, ///< Subtracts the bottom layer from the top layer or the other way around, to always get a non-negative value. (S - D) if (S > D), otherwise (D - S) + Exclusion, ///< The result is twice the product of the top and bottom layers, subtracted from their sum. s + d - (2 * s * d) + SrcOver, ///< Replace the bottom layer with the top layer. + Darken, ///< Creates a pixel that retains the smallest components of the top and bottom layer pixels. min(S, D) + Lighten, ///< Only has the opposite action of Darken Only. max(S, D) + ColorDodge, ///< Divides the bottom layer by the inverted top layer. D / (255 - S) + ColorBurn, ///< Divides the inverted bottom layer by the top layer, and then inverts the result. 255 - (255 - D) / S + HardLight, ///< The same as Overlay but with the color roles reversed. (2 * S * D) if (S < Sa), otherwise (Sa * Da) - 2 * (Da - S) * (Sa - D) + SoftLight ///< The same as Overlay but with applying pure black or white does not result in pure black or white. (1 - 2 * S) * (D ^ 2) + (2 * S * D) +}; + + +/** + * @brief Enumeration specifying the engine type used for the graphics backend. For multiple backends bitwise operation is allowed. + */ +enum class CanvasEngine +{ + Sw = (1 << 1), ///< CPU rasterizer. + Gl = (1 << 2), ///< OpenGL rasterizer. + Wg = (1 << 3), ///< WebGPU rasterizer. @BETA_API +}; + + +/** + * @brief A data structure representing a point in two-dimensional space. + */ +struct Point +{ + float x, y; +}; + + +/** + * @brief A data structure representing a three-dimensional matrix. + * + * The elements e11, e12, e21 and e22 represent the rotation matrix, including the scaling factor. + * The elements e13 and e23 determine the translation of the object along the x and y-axis, respectively. + * The elements e31 and e32 are set to 0, e33 is set to 1. + */ +struct Matrix +{ + float e11, e12, e13; + float e21, e22, e23; + float e31, e32, e33; +}; + + +/** + * @brief A data structure representing a texture mesh vertex + * + * @param pt The vertex coordinate + * @param uv The normalized texture coordinate in the range (0.0..1.0, 0.0..1.0) + * + * @BETA_API + */ +struct Vertex +{ + Point pt; + Point uv; +}; + + +/** + * @brief A data structure representing a triange in a texture mesh + * + * @param vertex The three vertices that make up the polygon + * + * @BETA_API + */ +struct Polygon +{ + Vertex vertex[3]; +}; + + +/** + * @class Paint + * + * @brief An abstract class for managing graphical elements. + * + * A graphical element in TVG is any object composed into a Canvas. + * Paint represents such a graphical object and its behaviors such as duplication, transformation and composition. + * TVG recommends the user to regard a paint as a set of volatile commands. They can prepare a Paint and then request a Canvas to run them. + */ +class TVG_API Paint +{ +public: + virtual ~Paint(); + + /** + * @brief Sets the angle by which the object is rotated. + * + * The angle in measured clockwise from the horizontal axis. + * The rotational axis passes through the point on the object with zero coordinates. + * + * @param[in] degree The value of the angle in degrees. + * + * @return Result::Success when succeed, Result::FailedAllocation otherwise. + */ + Result rotate(float degree) noexcept; + + /** + * @brief Sets the scale value of the object. + * + * @param[in] factor The value of the scaling factor. The default value is 1. + * + * @return Result::Success when succeed, Result::FailedAllocation otherwise. + */ + Result scale(float factor) noexcept; + + /** + * @brief Sets the values by which the object is moved in a two-dimensional space. + * + * The origin of the coordinate system is in the upper left corner of the canvas. + * The horizontal and vertical axes point to the right and down, respectively. + * + * @param[in] x The value of the horizontal shift. + * @param[in] y The value of the vertical shift. + * + * @return Result::Success when succeed, Result::FailedAllocation otherwise. + */ + Result translate(float x, float y) noexcept; + + /** + * @brief Sets the matrix of the affine transformation for the object. + * + * The augmented matrix of the transformation is expected to be given. + * + * @param[in] m The 3x3 augmented matrix. + * + * @return Result::Success when succeed, Result::FailedAllocation otherwise. + */ + Result transform(const Matrix& m) noexcept; + + /** + * @brief Gets the matrix of the affine transformation of the object. + * + * The values of the matrix can be set by the transform() API, as well by the translate(), + * scale() and rotate(). In case no transformation was applied, the identity matrix is returned. + * + * @return The augmented transformation matrix. + * + * @since 0.4 + */ + Matrix transform() noexcept; + + /** + * @brief Sets the opacity of the object. + * + * @param[in] o The opacity value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. + * + * @return Result::Success when succeed. + * + * @note Setting the opacity with this API may require multiple render pass for composition. It is recommended to avoid changing the opacity if possible. + * @note ClipPath won't use the opacity value. (see: enum class CompositeMethod::ClipPath) + */ + Result opacity(uint8_t o) noexcept; + + /** + * @brief Sets the composition target object and the composition method. + * + * @param[in] target The paint of the target object. + * @param[in] method The method used to composite the source object with the target. + * + * @return Result::Success when succeed, Result::InvalidArguments otherwise. + */ + Result composite(std::unique_ptr target, CompositeMethod method) noexcept; + + /** + * @brief Sets the blending method for the paint object. + * + * The blending feature allows you to combine colors to create visually appealing effects, including transparency, lighting, shading, and color mixing, among others. + * its process involves the combination of colors or images from the source paint object with the destination (the lower layer image) using blending operations. + * The blending operation is determined by the chosen @p BlendMethod, which specifies how the colors or images are combined. + * + * @param[in] method The blending method to be set. + * + * @return Result::Success when the blending method is successfully set. + * + * @BETA_API + */ + Result blend(BlendMethod method) const noexcept; + + /** + * @brief Gets the bounding box of the paint object before any transformation. + * + * @param[out] x The x coordinate of the upper left corner of the object. + * @param[out] y The y coordinate of the upper left corner of the object. + * @param[out] w The width of the object. + * @param[out] h The height of the object. + * + * @return Result::Success when succeed, Result::InsufficientCondition otherwise. + * + * @note The bounding box doesn't indicate the final rendered region. It's the smallest rectangle that encloses the object. + * @see Paint::bounds(float* x, float* y, float* w, float* h, bool transformed); + * @deprecated Use bounds(float* x, float* y, float* w, float* h, bool transformed) instead + */ + TVG_DEPRECATED Result bounds(float* x, float* y, float* w, float* h) const noexcept; + + /** + * @brief Gets the axis-aligned bounding box of the paint object. + * + * In case @p transform is @c true, all object's transformations are applied first, and then the bounding box is established. Otherwise, the bounding box is determined before any transformations. + * + * @param[out] x The x coordinate of the upper left corner of the object. + * @param[out] y The y coordinate of the upper left corner of the object. + * @param[out] w The width of the object. + * @param[out] h The height of the object. + * @param[in] transformed If @c true, the paint's transformations are taken into account, otherwise they aren't. + * + * @return Result::Success when succeed, Result::InsufficientCondition otherwise. + * + * @note The bounding box doesn't indicate the actual drawing region. It's the smallest rectangle that encloses the object. + */ + Result bounds(float* x, float* y, float* w, float* h, bool transformed) const noexcept; + + /** + * @brief Duplicates the object. + * + * Creates a new object and sets its all properties as in the original object. + * + * @return The created object when succeed, @c nullptr otherwise. + */ + Paint* duplicate() const noexcept; + + /** + * @brief Gets the opacity value of the object. + * + * @return The opacity value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. + */ + uint8_t opacity() const noexcept; + + /** + * @brief Gets the composition target object and the composition method. + * + * @param[out] target The paint of the target object. + * + * @return The method used to composite the source object with the target. + * + * @since 0.5 + */ + CompositeMethod composite(const Paint** target) const noexcept; + + /** + * @brief Gets the blending method of the object. + * + * @return The blending method + * + * @BETA_API + */ + BlendMethod blend() const noexcept; + + /** + * @brief Return the unique id value of the paint instance. + * + * This method can be called for checking the current concrete instance type. + * + * @return The type id of the Paint instance. + */ + uint32_t identifier() const noexcept; + + _TVG_DECLARE_PRIVATE(Paint); +}; + + +/** + * @class Fill + * + * @brief An abstract class representing the gradient fill of the Shape object. + * + * It contains the information about the gradient colors and their arrangement + * inside the gradient bounds. The gradients bounds are defined in the LinearGradient + * or RadialGradient class, depending on the type of the gradient to be used. + * It specifies the gradient behavior in case the area defined by the gradient bounds + * is smaller than the area to be filled. + */ +class TVG_API Fill +{ +public: + /** + * @brief A data structure storing the information about the color and its relative position inside the gradient bounds. + */ + struct ColorStop + { + float offset; /**< The relative position of the color. */ + uint8_t r; /**< The red color channel value in the range [0 ~ 255]. */ + uint8_t g; /**< The green color channel value in the range [0 ~ 255]. */ + uint8_t b; /**< The blue color channel value in the range [0 ~ 255]. */ + uint8_t a; /**< The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. */ + }; + + virtual ~Fill(); + + /** + * @brief Sets the parameters of the colors of the gradient and their position. + * + * @param[in] colorStops An array of ColorStop data structure. + * @param[in] cnt The count of the @p colorStops array equal to the colors number used in the gradient. + * + * @return Result::Success when succeed. + */ + Result colorStops(const ColorStop* colorStops, uint32_t cnt) noexcept; + + /** + * @brief Sets the FillSpread value, which specifies how to fill the area outside the gradient bounds. + * + * @param[in] s The FillSpread value. + * + * @return Result::Success when succeed. + */ + Result spread(FillSpread s) noexcept; + + /** + * @brief Sets the matrix of the affine transformation for the gradient fill. + * + * The augmented matrix of the transformation is expected to be given. + * + * @param[in] m The 3x3 augmented matrix. + * + * @return Result::Success when succeed, Result::FailedAllocation otherwise. + */ + Result transform(const Matrix& m) noexcept; + + /** + * @brief Gets the parameters of the colors of the gradient, their position and number. + * + * @param[out] colorStops A pointer to the memory location, where the array of the gradient's ColorStop is stored. + * + * @return The number of colors used in the gradient. This value corresponds to the length of the @p colorStops array. + */ + uint32_t colorStops(const ColorStop** colorStops) const noexcept; + + /** + * @brief Gets the FillSpread value of the fill. + * + * @return The FillSpread value of this Fill. + */ + FillSpread spread() const noexcept; + + /** + * @brief Gets the matrix of the affine transformation of the gradient fill. + * + * In case no transformation was applied, the identity matrix is returned. + * + * @retval The augmented transformation matrix. + */ + Matrix transform() const noexcept; + + /** + * @brief Creates a copy of the Fill object. + * + * Return a newly created Fill object with the properties copied from the original. + * + * @return A copied Fill object when succeed, @c nullptr otherwise. + */ + Fill* duplicate() const noexcept; + + /** + * @brief Return the unique id value of the Fill instance. + * + * This method can be called for checking the current concrete instance type. + * + * @return The type id of the Fill instance. + */ + uint32_t identifier() const noexcept; + + _TVG_DECLARE_PRIVATE(Fill); +}; + + +/** + * @class Canvas + * + * @brief An abstract class for drawing graphical elements. + * + * A canvas is an entity responsible for drawing the target. It sets up the drawing engine and the buffer, which can be drawn on the screen. It also manages given Paint objects. + * + * @note A Canvas behavior depends on the raster engine though the final content of the buffer is expected to be identical. + * @warning The Paint objects belonging to one Canvas can't be shared among multiple Canvases. + */ +class TVG_API Canvas +{ +public: + Canvas(RenderMethod*); + virtual ~Canvas(); + + /** + * @brief Sets the size of the container, where all the paints pushed into the Canvas are stored. + * + * If the number of objects pushed into the Canvas is known in advance, calling the function + * prevents multiple memory reallocation, thus improving the performance. + * + * @param[in] n The number of objects for which the memory is to be reserved. + * + * @return Result::Success when succeed. + */ + TVG_DEPRECATED Result reserve(uint32_t n) noexcept; + + /** + * @brief Returns the list of the paints that currently held by the Canvas. + * + * This function provides the list of paint nodes, allowing users a direct opportunity to modify the scene tree. + * + * @warning Please avoid accessing the paints during Canvas update/draw. You can access them after calling sync(). + * @see Canvas::sync() + * + * @BETA_API + */ + std::list& paints() noexcept; + + /** + * @brief Passes drawing elements to the Canvas using Paint objects. + * + * Only pushed paints in the canvas will be drawing targets. + * They are retained by the canvas until you call Canvas::clear(). + * + * @param[in] paint A Paint object to be drawn. + * + * @retval Result::Success When succeed. + * @retval Result::MemoryCorruption In case a @c nullptr is passed as the argument. + * @retval Result::InsufficientCondition An internal error. + * + * @note The rendering order of the paints is the same as the order as they were pushed into the canvas. Consider sorting the paints before pushing them if you intend to use layering. + * @see Canvas::paints() + * @see Canvas::clear() + */ + virtual Result push(std::unique_ptr paint) noexcept; + + /** + * @brief Clear the internal canvas resources that used for the drawing. + * + * This API sets the total number of paints pushed into the canvas to zero. + * Depending on the value of the @p free argument, the paints are either freed or retained. + * So if you need to update paint properties while maintaining the existing scene structure, you can set @p free = false. + * + * @param[in] free If @c true, the memory occupied by paints is deallocated, otherwise it is not. + * + * @return Result::Success when succeed, Result::InsufficientCondition otherwise. + * + * @see Canvas::push() + * @see Canvas::paints() + */ + virtual Result clear(bool free = true) noexcept; + + /** + * @brief Request the canvas to update the paint objects. + * + * If a @c nullptr is passed all paint objects retained by the Canvas are updated, + * otherwise only the paint to which the given @p paint points. + * + * @param[in] paint A pointer to the Paint object or @c nullptr. + * + * @return Result::Success when succeed, Result::InsufficientCondition otherwise. + * + * @note The Update behavior can be asynchronous if the assigned thread number is greater than zero. + */ + virtual Result update(Paint* paint = nullptr) noexcept; + + /** + * @brief Requests the canvas to draw the Paint objects. + * + * @return Result::Success when succeed, Result::InsufficientCondition otherwise. + * + * @note Drawing can be asynchronous if the assigned thread number is greater than zero. To guarantee the drawing is done, call sync() afterwards. + * @see Canvas::sync() + */ + virtual Result draw() noexcept; + + /** + * @brief Guarantees that drawing task is finished. + * + * The Canvas rendering can be performed asynchronously. To make sure that rendering is finished, + * the sync() must be called after the draw() regardless of threading. + * + * @return Result::Success when succeed, Result::InsufficientCondition otherwise. + * @see Canvas::draw() + */ + virtual Result sync() noexcept; + + _TVG_DECLARE_PRIVATE(Canvas); +}; + + +/** + * @class LinearGradient + * + * @brief A class representing the linear gradient fill of the Shape object. + * + * Besides the APIs inherited from the Fill class, it enables setting and getting the linear gradient bounds. + * The behavior outside the gradient bounds depends on the value specified in the spread API. + */ +class TVG_API LinearGradient final : public Fill +{ +public: + ~LinearGradient(); + + /** + * @brief Sets the linear gradient bounds. + * + * The bounds of the linear gradient are defined as a surface constrained by two parallel lines crossing + * the given points (@p x1, @p y1) and (@p x2, @p y2), respectively. Both lines are perpendicular to the line linking + * (@p x1, @p y1) and (@p x2, @p y2). + * + * @param[in] x1 The horizontal coordinate of the first point used to determine the gradient bounds. + * @param[in] y1 The vertical coordinate of the first point used to determine the gradient bounds. + * @param[in] x2 The horizontal coordinate of the second point used to determine the gradient bounds. + * @param[in] y2 The vertical coordinate of the second point used to determine the gradient bounds. + * + * @return Result::Success when succeed. + * + * @note In case the first and the second points are equal, an object filled with such a gradient fill is not rendered. + */ + Result linear(float x1, float y1, float x2, float y2) noexcept; + + /** + * @brief Gets the linear gradient bounds. + * + * The bounds of the linear gradient are defined as a surface constrained by two parallel lines crossing + * the given points (@p x1, @p y1) and (@p x2, @p y2), respectively. Both lines are perpendicular to the line linking + * (@p x1, @p y1) and (@p x2, @p y2). + * + * @param[out] x1 The horizontal coordinate of the first point used to determine the gradient bounds. + * @param[out] y1 The vertical coordinate of the first point used to determine the gradient bounds. + * @param[out] x2 The horizontal coordinate of the second point used to determine the gradient bounds. + * @param[out] y2 The vertical coordinate of the second point used to determine the gradient bounds. + * + * @return Result::Success when succeed. + */ + Result linear(float* x1, float* y1, float* x2, float* y2) const noexcept; + + /** + * @brief Creates a new LinearGradient object. + * + * @return A new LinearGradient object. + */ + static std::unique_ptr gen() noexcept; + + /** + * @brief Return the unique id value of this class. + * + * This method can be referred for identifying the LinearGradient class type. + * + * @return The type id of the LinearGradient class. + */ + static uint32_t identifier() noexcept; + + _TVG_DECLARE_PRIVATE(LinearGradient); +}; + + +/** + * @class RadialGradient + * + * @brief A class representing the radial gradient fill of the Shape object. + * + */ +class TVG_API RadialGradient final : public Fill +{ +public: + ~RadialGradient(); + + /** + * @brief Sets the radial gradient bounds. + * + * The radial gradient bounds are defined as a circle centered in a given point (@p cx, @p cy) of a given radius. + * + * @param[in] cx The horizontal coordinate of the center of the bounding circle. + * @param[in] cy The vertical coordinate of the center of the bounding circle. + * @param[in] radius The radius of the bounding circle. + * + * @return Result::Success when succeed, Result::InvalidArguments in case the @p radius value is zero or less. + */ + Result radial(float cx, float cy, float radius) noexcept; + + /** + * @brief Gets the radial gradient bounds. + * + * The radial gradient bounds are defined as a circle centered in a given point (@p cx, @p cy) of a given radius. + * + * @param[out] cx The horizontal coordinate of the center of the bounding circle. + * @param[out] cy The vertical coordinate of the center of the bounding circle. + * @param[out] radius The radius of the bounding circle. + * + * @return Result::Success when succeed. + */ + Result radial(float* cx, float* cy, float* radius) const noexcept; + + /** + * @brief Creates a new RadialGradient object. + * + * @return A new RadialGradient object. + */ + static std::unique_ptr gen() noexcept; + + /** + * @brief Return the unique id value of this class. + * + * This method can be referred for identifying the RadialGradient class type. + * + * @return The type id of the RadialGradient class. + */ + static uint32_t identifier() noexcept; + + _TVG_DECLARE_PRIVATE(RadialGradient); +}; + + +/** + * @class Shape + * + * @brief A class representing two-dimensional figures and their properties. + * + * A shape has three major properties: shape outline, stroking, filling. The outline in the Shape is retained as the path. + * Path can be composed by accumulating primitive commands such as moveTo(), lineTo(), cubicTo(), or complete shape interfaces such as appendRect(), appendCircle(), etc. + * Path can consists of sub-paths. One sub-path is determined by a close command. + * + * The stroke of Shape is an optional property in case the Shape needs to be represented with/without the outline borders. + * It's efficient since the shape path and the stroking path can be shared with each other. It's also convenient when controlling both in one context. + */ +class TVG_API Shape final : public Paint +{ +public: + ~Shape(); + + /** + * @brief Resets the properties of the shape path. + * + * The transformation matrix, the color, the fill and the stroke properties are retained. + * + * @return Result::Success when succeed. + * + * @note The memory, where the path data is stored, is not deallocated at this stage for caching effect. + */ + Result reset() noexcept; + + /** + * @brief Sets the initial point of the sub-path. + * + * The value of the current point is set to the given point. + * + * @param[in] x The horizontal coordinate of the initial point of the sub-path. + * @param[in] y The vertical coordinate of the initial point of the sub-path. + * + * @return Result::Success when succeed. + */ + Result moveTo(float x, float y) noexcept; + + /** + * @brief Adds a new point to the sub-path, which results in drawing a line from the current point to the given end-point. + * + * The value of the current point is set to the given end-point. + * + * @param[in] x The horizontal coordinate of the end-point of the line. + * @param[in] y The vertical coordinate of the end-point of the line. + * + * @return Result::Success when succeed. + * + * @note In case this is the first command in the path, it corresponds to the moveTo() call. + */ + Result lineTo(float x, float y) noexcept; + + /** + * @brief Adds new points to the sub-path, which results in drawing a cubic Bezier curve starting + * at the current point and ending at the given end-point (@p x, @p y) using the control points (@p cx1, @p cy1) and (@p cx2, @p cy2). + * + * The value of the current point is set to the given end-point. + * + * @param[in] cx1 The horizontal coordinate of the 1st control point. + * @param[in] cy1 The vertical coordinate of the 1st control point. + * @param[in] cx2 The horizontal coordinate of the 2nd control point. + * @param[in] cy2 The vertical coordinate of the 2nd control point. + * @param[in] x The horizontal coordinate of the end-point of the curve. + * @param[in] y The vertical coordinate of the end-point of the curve. + * + * @return Result::Success when succeed. + * + * @note In case this is the first command in the path, no data from the path are rendered. + */ + Result cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) noexcept; + + /** + * @brief Closes the current sub-path by drawing a line from the current point to the initial point of the sub-path. + * + * The value of the current point is set to the initial point of the closed sub-path. + * + * @return Result::Success when succeed. + * + * @note In case the sub-path does not contain any points, this function has no effect. + */ + Result close() noexcept; + + /** + * @brief Appends a rectangle to the path. + * + * The rectangle with rounded corners can be achieved by setting non-zero values to @p rx and @p ry arguments. + * The @p rx and @p ry values specify the radii of the ellipse defining the rounding of the corners. + * + * The position of the rectangle is specified by the coordinates of its upper left corner - @p x and @p y arguments. + * + * The rectangle is treated as a new sub-path - it is not connected with the previous sub-path. + * + * The value of the current point is set to (@p x + @p rx, @p y) - in case @p rx is greater + * than @p w/2 the current point is set to (@p x + @p w/2, @p y) + * + * @param[in] x The horizontal coordinate of the upper left corner of the rectangle. + * @param[in] y The vertical coordinate of the upper left corner of the rectangle. + * @param[in] w The width of the rectangle. + * @param[in] h The height of the rectangle. + * @param[in] rx The x-axis radius of the ellipse defining the rounded corners of the rectangle. + * @param[in] ry The y-axis radius of the ellipse defining the rounded corners of the rectangle. + * + * @return Result::Success when succeed. + * + * @note For @p rx and @p ry greater than or equal to the half of @p w and the half of @p h, respectively, the shape become an ellipse. + */ + Result appendRect(float x, float y, float w, float h, float rx = 0, float ry = 0) noexcept; + + /** + * @brief Appends an ellipse to the path. + * + * The position of the ellipse is specified by the coordinates of its center - @p cx and @p cy arguments. + * + * The ellipse is treated as a new sub-path - it is not connected with the previous sub-path. + * + * The value of the current point is set to (@p cx, @p cy - @p ry). + * + * @param[in] cx The horizontal coordinate of the center of the ellipse. + * @param[in] cy The vertical coordinate of the center of the ellipse. + * @param[in] rx The x-axis radius of the ellipse. + * @param[in] ry The y-axis radius of the ellipse. + * + * @return Result::Success when succeed. + */ + Result appendCircle(float cx, float cy, float rx, float ry) noexcept; + + /** + * @brief Appends a circular arc to the path. + * + * The arc is treated as a new sub-path - it is not connected with the previous sub-path. + * The current point value is set to the end-point of the arc in case @p pie is @c false, and to the center of the arc otherwise. + * + * @param[in] cx The horizontal coordinate of the center of the arc. + * @param[in] cy The vertical coordinate of the center of the arc. + * @param[in] radius The radius of the arc. + * @param[in] startAngle The start angle of the arc given in degrees, measured counter-clockwise from the horizontal line. + * @param[in] sweep The central angle of the arc given in degrees, measured counter-clockwise from @p startAngle. + * @param[in] pie Specifies whether to draw radii from the arc's center to both of its end-point - drawn if @c true. + * + * @return Result::Success when succeed. + * + * @note Setting @p sweep value greater than 360 degrees, is equivalent to calling appendCircle(cx, cy, radius, radius). + */ + Result appendArc(float cx, float cy, float radius, float startAngle, float sweep, bool pie) noexcept; + + /** + * @brief Appends a given sub-path to the path. + * + * The current point value is set to the last point from the sub-path. + * For each command from the @p cmds array, an appropriate number of points in @p pts array should be specified. + * If the number of points in the @p pts array is different than the number required by the @p cmds array, the shape with this sub-path will not be displayed on the screen. + * + * @param[in] cmds The array of the commands in the sub-path. + * @param[in] cmdCnt The number of the sub-path's commands. + * @param[in] pts The array of the two-dimensional points. + * @param[in] ptsCnt The number of the points in the @p pts array. + * + * @return Result::Success when succeed, Result::InvalidArguments otherwise. + * + * @note The interface is designed for optimal path setting if the caller has a completed path commands already. + */ + Result appendPath(const PathCommand* cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt) noexcept; + + /** + * @brief Sets the stroke width for all of the figures from the path. + * + * @param[in] width The width of the stroke. The default value is 0. + * + * @return Result::Success when succeed, Result::FailedAllocation otherwise. + */ + Result stroke(float width) noexcept; + + /** + * @brief Sets the color of the stroke for all of the figures from the path. + * + * @param[in] r The red color channel value in the range [0 ~ 255]. The default value is 0. + * @param[in] g The green color channel value in the range [0 ~ 255]. The default value is 0. + * @param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0. + * @param[in] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. The default value is 0. + * + * @return Result::Success when succeed, Result::FailedAllocation otherwise. + */ + Result stroke(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) noexcept; + + /** + * @brief Sets the gradient fill of the stroke for all of the figures from the path. + * + * @param[in] f The gradient fill. + * + * @retval Result::Success When succeed. + * @retval Result::FailedAllocation An internal error with a memory allocation for an object to be filled. + * @retval Result::MemoryCorruption In case a @c nullptr is passed as the argument. + */ + Result stroke(std::unique_ptr f) noexcept; + + /** + * @brief Sets the dash pattern of the stroke. + * + * @param[in] dashPattern The array of consecutive pair values of the dash length and the gap length. + * @param[in] cnt The length of the @p dashPattern array. + * + * @retval Result::Success When succeed. + * @retval Result::FailedAllocation An internal error with a memory allocation for an object to be dashed. + * @retval Result::InvalidArguments In case @p dashPattern is @c nullptr and @p cnt > 0, @p cnt is zero, any of the dash pattern values is zero or less. + * + * @note To reset the stroke dash pattern, pass @c nullptr to @p dashPattern and zero to @p cnt. + * @warning @p cnt must be greater than 1 if the dash pattern is valid. + */ + Result stroke(const float* dashPattern, uint32_t cnt) noexcept; + + /** + * @brief Sets the cap style of the stroke in the open sub-paths. + * + * @param[in] cap The cap style value. The default value is @c StrokeCap::Square. + * + * @return Result::Success when succeed, Result::FailedAllocation otherwise. + */ + Result stroke(StrokeCap cap) noexcept; + + /** + * @brief Sets the join style for stroked path segments. + * + * The join style is used for joining the two line segment while stroking the path. + * + * @param[in] join The join style value. The default value is @c StrokeJoin::Bevel. + * + * @return Result::Success when succeed, Result::FailedAllocation otherwise. + */ + Result stroke(StrokeJoin join) noexcept; + + + /** + * @brief Sets the stroke miterlimit. + * + * @param[in] miterlimit The miterlimit imposes a limit on the extent of the stroke join, when the @c StrokeJoin::Miter join style is set. The default value is 4. + * + * @return Result::Success when succeed, Result::NonSupport unsupported value, Result::FailedAllocation otherwise. + * + * @since 0.11 + */ + Result strokeMiterlimit(float miterlimit) noexcept; + + /** + * @brief Sets the solid color for all of the figures from the path. + * + * The parts of the shape defined as inner are colored. + * + * @param[in] r The red color channel value in the range [0 ~ 255]. The default value is 0. + * @param[in] g The green color channel value in the range [0 ~ 255]. The default value is 0. + * @param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0. + * @param[in] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. The default value is 0. + * + * @return Result::Success when succeed. + * + * @note Either a solid color or a gradient fill is applied, depending on what was set as last. + * @note ClipPath won't use the fill values. (see: enum class CompositeMethod::ClipPath) + */ + Result fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) noexcept; + + /** + * @brief Sets the gradient fill for all of the figures from the path. + * + * The parts of the shape defined as inner are filled. + * + * @param[in] f The unique pointer to the gradient fill. + * + * @return Result::Success when succeed, Result::MemoryCorruption otherwise. + * + * @note Either a solid color or a gradient fill is applied, depending on what was set as last. + */ + Result fill(std::unique_ptr f) noexcept; + + /** + * @brief Sets the fill rule for the Shape object. + * + * @param[in] r The fill rule value. The default value is @c FillRule::Winding. + * + * @return Result::Success when succeed. + */ + Result fill(FillRule r) noexcept; + + + /** + * @brief Sets the rendering order of the stroke and the fill. + * + * @param[in] strokeFirst If @c true the stroke is rendered before the fill, otherwise the stroke is rendered as the second one (the default option). + * + * @return Result::Success when succeed, Result::FailedAllocation otherwise. + * + * @since 0.10 + */ + Result order(bool strokeFirst) noexcept; + + + /** + * @brief Gets the commands data of the path. + * + * @param[out] cmds The pointer to the array of the commands from the path. + * + * @return The length of the @p cmds array when succeed, zero otherwise. + */ + uint32_t pathCommands(const PathCommand** cmds) const noexcept; + + /** + * @brief Gets the points values of the path. + * + * @param[out] pts The pointer to the array of the two-dimensional points from the path. + * + * @return The length of the @p pts array when succeed, zero otherwise. + */ + uint32_t pathCoords(const Point** pts) const noexcept; + + /** + * @brief Gets the pointer to the gradient fill of the shape. + * + * @return The pointer to the gradient fill of the stroke when succeed, @c nullptr in case no fill was set. + */ + const Fill* fill() const noexcept; + + /** + * @brief Gets the solid color of the shape. + * + * @param[out] r The red color channel value in the range [0 ~ 255]. + * @param[out] g The green color channel value in the range [0 ~ 255]. + * @param[out] b The blue color channel value in the range [0 ~ 255]. + * @param[out] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. + * + * @return Result::Success when succeed. + */ + Result fillColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a = nullptr) const noexcept; + + /** + * @brief Gets the fill rule value. + * + * @return The fill rule value of the shape. + */ + FillRule fillRule() const noexcept; + + /** + * @brief Gets the stroke width. + * + * @return The stroke width value when succeed, zero if no stroke was set. + */ + float strokeWidth() const noexcept; + + /** + * @brief Gets the color of the shape's stroke. + * + * @param[out] r The red color channel value in the range [0 ~ 255]. + * @param[out] g The green color channel value in the range [0 ~ 255]. + * @param[out] b The blue color channel value in the range [0 ~ 255]. + * @param[out] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. + * + * @return Result::Success when succeed, Result::InsufficientCondition otherwise. + */ + Result strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a = nullptr) const noexcept; + + /** + * @brief Gets the pointer to the gradient fill of the stroke. + * + * @return The pointer to the gradient fill of the stroke when succeed, @c nullptr otherwise. + */ + const Fill* strokeFill() const noexcept; + + /** + * @brief Gets the dash pattern of the stroke. + * + * @param[out] dashPattern The pointer to the memory, where the dash pattern array is stored. + * + * @return The length of the @p dashPattern array. + */ + uint32_t strokeDash(const float** dashPattern) const noexcept; + + /** + * @brief Gets the cap style used for stroking the path. + * + * @return The cap style value of the stroke. + */ + StrokeCap strokeCap() const noexcept; + + /** + * @brief Gets the join style value used for stroking the path. + * + * @return The join style value of the stroke. + */ + StrokeJoin strokeJoin() const noexcept; + + /** + * @brief Gets the stroke miterlimit. + * + * @return The stroke miterlimit value when succeed, 4 if no stroke was set. + * + * @since 0.11 + */ + float strokeMiterlimit() const noexcept; + + /** + * @brief Creates a new Shape object. + * + * @return A new Shape object. + */ + static std::unique_ptr gen() noexcept; + + /** + * @brief Return the unique id value of this class. + * + * This method can be referred for identifying the Shape class type. + * + * @return The type id of the Shape class. + */ + static uint32_t identifier() noexcept; + + _TVG_DECLARE_PRIVATE(Shape); +}; + + +/** + * @class Picture + * + * @brief A class representing an image read in one of the supported formats: raw, svg, png, jpg, lottie(json) and etc. + * Besides the methods inherited from the Paint, it provides methods to load & draw images on the canvas. + * + * @note Supported formats are depended on the available TVG loaders. + * @note See Animation class if the picture data is animatable. + */ +class TVG_API Picture final : public Paint +{ +public: + ~Picture(); + + /** + * @brief Loads a picture data directly from a file. + * + * @param[in] path A path to the picture file. + * + * @retval Result::Success When succeed. + * @retval Result::InvalidArguments In case the @p path is invalid. + * @retval Result::NonSupport When trying to load a file with an unknown extension. + * @retval Result::Unknown If an error occurs at a later stage. + * + * @note The Load behavior can be asynchronous if the assigned thread number is greater than zero. + * @see Initializer::init() + */ + Result load(const std::string& path) noexcept; + + /** + * @brief Loads a picture data from a memory block of a given size. + * + * @param[in] data A pointer to a memory location where the content of the picture file is stored. + * @param[in] size The size in bytes of the memory occupied by the @p data. + * @param[in] copy Decides whether the data should be copied into the engine local buffer. + * + * @retval Result::Success When succeed. + * @retval Result::InvalidArguments In case no data are provided or the @p size is zero or less. + * @retval Result::NonSupport When trying to load a file with an unknown extension. + * @retval Result::Unknown If an error occurs at a later stage. + * + * @warning: you have responsibility to release the @p data memory if the @p copy is true + * @deprecated Use load(const char* data, uint32_t size, const std::string& mimeType, bool copy) instead. + * @see Result load(const char* data, uint32_t size, const std::string& mimeType, bool copy = false) noexcept + */ + TVG_DEPRECATED Result load(const char* data, uint32_t size, bool copy = false) noexcept; + + /** + * @brief Loads a picture data from a memory block of a given size. + * + * @param[in] data A pointer to a memory location where the content of the picture file is stored. + * @param[in] size The size in bytes of the memory occupied by the @p data. + * @param[in] mimeType Mimetype or extension of data such as "jpg", "jpeg", "lottie", "svg", "svg+xml", "png", etc. In case an empty string or an unknown type is provided, the loaders will be tried one by one. + * @param[in] copy If @c true the data are copied into the engine local buffer, otherwise they are not. + * + * @retval Result::Success When succeed. + * @retval Result::InvalidArguments In case no data are provided or the @p size is zero or less. + * @retval Result::NonSupport When trying to load a file with an unknown extension. + * @retval Result::Unknown If an error occurs at a later stage. + * + * @warning: It's the user responsibility to release the @p data memory if the @p copy is @c true. + * + * @note If you are unsure about the MIME type, you can provide an empty value like @c "", and thorvg will attempt to figure it out. + * @since 0.5 + */ + Result load(const char* data, uint32_t size, const std::string& mimeType, bool copy = false) noexcept; + + /** + * @brief Resizes the picture content to the given width and height. + * + * The picture content is resized while keeping the default size aspect ratio. + * The scaling factor is established for each of dimensions and the smaller value is applied to both of them. + * + * @param[in] w A new width of the image in pixels. + * @param[in] h A new height of the image in pixels. + * + * @return Result::Success when succeed, Result::InsufficientCondition otherwise. + */ + Result size(float w, float h) noexcept; + + /** + * @brief Gets the size of the image. + * + * @param[out] w The width of the image in pixels. + * @param[out] h The height of the image in pixels. + * + * @return Result::Success when succeed. + */ + Result size(float* w, float* h) const noexcept; + + /** + * @brief Loads a raw data from a memory block with a given size. + * + * @retval Result::Success When succeed, Result::InsufficientCondition otherwise. + * @retval Result::FailedAllocation An internal error possibly with memory allocation. + * + * @since 0.9 + */ + Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy) noexcept; + + /** + * @brief Sets or removes the triangle mesh to deform the image. + * + * If a mesh is provided, the transform property of the Picture will apply to the triangle mesh, and the + * image data will be used as the texture. + * + * If @p triangles is @c nullptr, or @p triangleCnt is 0, the mesh will be removed. + * + * Only raster image types are supported at this time (png, jpg). Vector types like svg and tvg do not support. + * mesh deformation. However, if required you should be able to render a vector image to a raster image and then apply a mesh. + * + * @param[in] triangles An array of Polygons(triangles) that make up the mesh, or null to remove the mesh. + * @param[in] triangleCnt The number of Polygons(triangles) provided, or 0 to remove the mesh. + * + * @retval Result::Success When succeed. + * @retval Result::Unknown If fails + * + * @note The Polygons are copied internally, so modifying them after calling Mesh::mesh has no affect. + * @warning Please do not use it, this API is not official one. It could be modified in the next version. + * + * @BETA_API + */ + Result mesh(const Polygon* triangles, uint32_t triangleCnt) noexcept; + + /** + * @brief Return the number of triangles in the mesh, and optionally get a pointer to the array of triangles in the mesh. + * + * @param[out] triangles Optional. A pointer to the array of Polygons used by this mesh. + * + * @return uint32_t The number of polygons in the array. + * + * @note Modifying the triangles returned by this method will modify them directly within the mesh. + * @warning Please do not use it, this API is not official one. It could be modified in the next version. + * + * @BETA_API + */ + uint32_t mesh(const Polygon** triangles) const noexcept; + + /** + * @brief Creates a new Picture object. + * + * @return A new Picture object. + */ + static std::unique_ptr gen() noexcept; + + /** + * @brief Return the unique id value of this class. + * + * This method can be referred for identifying the Picture class type. + * + * @return The type id of the Picture class. + */ + static uint32_t identifier() noexcept; + + _TVG_DECLARE_ACCESSOR(Animation); + _TVG_DECLARE_PRIVATE(Picture); +}; + + +/** + * @class Scene + * + * @brief A class to composite children paints. + * + * As the traditional graphics rendering method, TVG also enables scene-graph mechanism. + * This feature supports an array function for managing the multiple paints as one group paint. + * + * As a group, the scene can be transformed, made translucent and composited with other target paints, + * its children will be affected by the scene world. + */ +class TVG_API Scene final : public Paint +{ +public: + ~Scene(); + + /** + * @brief Passes drawing elements to the Scene using Paint objects. + * + * Only the paints pushed into the scene will be the drawn targets. + * The paints are retained by the scene until Scene::clear() is called. + * + * @param[in] paint A Paint object to be drawn. + * + * @return Result::Success when succeed, Result::MemoryCorruption otherwise. + * + * @note The rendering order of the paints is the same as the order as they were pushed. Consider sorting the paints before pushing them if you intend to use layering. + * @see Scene::paints() + * @see Scene::clear() + */ + Result push(std::unique_ptr paint) noexcept; + + /** + * @brief Sets the size of the container, where all the paints pushed into the Scene are stored. + * + * If the number of objects pushed into the scene is known in advance, calling the function + * prevents multiple memory reallocation, thus improving the performance. + * + * @param[in] size The number of objects for which the memory is to be reserved. + * + * @return Result::Success when succeed, Result::FailedAllocation otherwise. + */ + TVG_DEPRECATED Result reserve(uint32_t size) noexcept; + + /** + * @brief Returns the list of the paints that currently held by the Scene. + * + * This function provides the list of paint nodes, allowing users a direct opportunity to modify the scene tree. + * + * @warning Please avoid accessing the paints during Scene update/draw. You can access them after calling Canvas::sync(). + * @see Canvas::sync() + * @see Scene::push() + * @see Scene::clear() + * + * @BETA_API + */ + std::list& paints() noexcept; + + /** + * @brief Sets the total number of the paints pushed into the scene to be zero. + * Depending on the value of the @p free argument, the paints are freed or not. + * + * @param[in] free If @c true, the memory occupied by paints is deallocated, otherwise it is not. + * + * @return Result::Success when succeed + * + * @warning If you don't free the paints they become dangled. They are supposed to be reused, otherwise you are responsible for their lives. Thus please use the @p free argument only when you know how it works, otherwise it's not recommended. + * + * @since 0.2 + */ + Result clear(bool free = true) noexcept; + + /** + * @brief Creates a new Scene object. + * + * @return A new Scene object. + */ + static std::unique_ptr gen() noexcept; + + /** + * @brief Return the unique id value of this class. + * + * This method can be referred for identifying the Scene class type. + * + * @return The type id of the Scene class. + */ + static uint32_t identifier() noexcept; + + _TVG_DECLARE_PRIVATE(Scene); +}; + + +/** + * @class SwCanvas + * + * @brief A class for the rendering graphical elements with a software raster engine. + */ +class TVG_API SwCanvas final : public Canvas +{ +public: + ~SwCanvas(); + + /** + * @brief Enumeration specifying the methods of combining the 8-bit color channels into 32-bit color. + */ + enum Colorspace + { + ABGR8888 = 0, ///< The channels are joined in the order: alpha, blue, green, red. Colors are alpha-premultiplied. (a << 24 | b << 16 | g << 8 | r) + ARGB8888, ///< The channels are joined in the order: alpha, red, green, blue. Colors are alpha-premultiplied. (a << 24 | r << 16 | g << 8 | b) + ABGR8888S, ///< @BETA_API The channels are joined in the order: alpha, blue, green, red. Colors are un-alpha-premultiplied. + ARGB8888S, ///< @BETA_API The channels are joined in the order: alpha, red, green, blue. Colors are un-alpha-premultiplied. + }; + + /** + * @brief Enumeration specifying the methods of Memory Pool behavior policy. + * @since 0.4 + */ + enum MempoolPolicy + { + Default = 0, ///< Default behavior that ThorVG is designed to. + Shareable, ///< Memory Pool is shared among the SwCanvases. + Individual ///< Allocate designated memory pool that is only used by current instance. + }; + + /** + * @brief Sets the target buffer for the rasterization. + * + * The buffer of a desirable size should be allocated and owned by the caller. + * + * @param[in] buffer A pointer to a memory block of the size @p stride x @p h, where the raster data are stored. + * @param[in] stride The stride of the raster image - greater than or equal to @p w. + * @param[in] w The width of the raster image. + * @param[in] h The height of the raster image. + * @param[in] cs The value specifying the way the 32-bits colors should be read/written. + * + * @retval Result::Success When succeed. + * @retval Result::MemoryCorruption When casting in the internal function implementation failed. + * @retval Result::InvalidArguments In case no valid pointer is provided or the width, or the height or the stride is zero. + * @retval Result::NonSupport In case the software engine is not supported. + * + * @warning Do not access @p buffer during Canvas::draw() - Canvas::sync(). It should not be accessed while TVG is writing on it. + */ + Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Colorspace cs) noexcept; + + /** + * @brief Set sw engine memory pool behavior policy. + * + * Basically ThorVG draws a lot of shapes, it allocates/deallocates a few chunk of memory + * while processing rendering. It internally uses one shared memory pool + * which can be reused among the canvases in order to avoid memory overhead. + * + * Thus ThorVG suggests using a memory pool policy to satisfy user demands, + * if it needs to guarantee the thread-safety of the internal data access. + * + * @param[in] policy The method specifying the Memory Pool behavior. The default value is @c MempoolPolicy::Default. + * + * @retval Result::Success When succeed. + * @retval Result::InsufficientCondition If the canvas contains some paints already. + * @retval Result::NonSupport In case the software engine is not supported. + * + * @note When @c policy is set as @c MempoolPolicy::Individual, the current instance of canvas uses its own individual + * memory data, which is not shared with others. This is necessary when the canvas is accessed on a worker-thread. + * + * @warning It's not allowed after pushing any paints. + * + * @since 0.4 + */ + Result mempool(MempoolPolicy policy) noexcept; + + /** + * @brief Creates a new SwCanvas object. + * @return A new SwCanvas object. + */ + static std::unique_ptr gen() noexcept; + + _TVG_DECLARE_PRIVATE(SwCanvas); +}; + + +/** + * @class GlCanvas + * + * @brief A class for the rendering graphic elements with a GL raster engine. + * + * @warning Please do not use it. This class is not fully supported yet. + * + * @BETA_API + */ +class TVG_API GlCanvas final : public Canvas +{ +public: + ~GlCanvas(); + + /** + * @brief Sets the target buffer for the rasterization. + * + * @warning Please do not use it, this API is not official one. It could be modified in the next version. + * + * @BETA_API + */ + Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept; + + /** + * @brief Creates a new GlCanvas object. + * + * @return A new GlCanvas object. + * + * @BETA_API + */ + static std::unique_ptr gen() noexcept; + + _TVG_DECLARE_PRIVATE(GlCanvas); +}; + + +/** + * @class WgCanvas + * + * @brief A class for the rendering graphic elements with a WebGPU raster engine. + * + * @warning Please do not use it. This class is not fully supported yet. + * + * @BETA_API + */ +class TVG_API WgCanvas final : public Canvas +{ +public: + ~WgCanvas(); + + /** + * @brief Sets the target window for the rasterization. + * + * @warning Please do not use it, this API is not official one. It could be modified in the next version. + * + * @BETA_API + */ + Result target(void* window, uint32_t w, uint32_t h) noexcept; + + /** + * @brief Creates a new WgCanvas object. + * + * @return A new WgCanvas object. + * + * @BETA_API + */ + static std::unique_ptr gen() noexcept; + + _TVG_DECLARE_PRIVATE(WgCanvas); +}; + + +/** + * @class Initializer + * + * @brief A class that enables initialization and termination of the TVG engines. + */ +class TVG_API Initializer final +{ +public: + /** + * @brief Initializes TVG engines. + * + * TVG requires the running-engine environment. + * TVG runs its own task-scheduler for parallelizing rendering tasks efficiently. + * You can indicate the number of threads, the count of which is designated @p threads. + * In the initialization step, TVG will generate/spawn the threads as set by @p threads count. + * + * @param[in] engine The engine types to initialize. This is relative to the Canvas types, in which it will be used. For multiple backends bitwise operation is allowed. + * @param[in] threads The number of additional threads. Zero indicates only the main thread is to be used. + * + * @retval Result::Success When succeed. + * @retval Result::FailedAllocation An internal error possibly with memory allocation. + * @retval Result::InvalidArguments If unknown engine type chosen. + * @retval Result::NonSupport In case the engine type is not supported on the system. + * @retval Result::Unknown Others. + * + * @note The Initializer keeps track of the number of times it was called. Threads count is fixed at the first init() call. + * @see Initializer::term() + */ + static Result init(CanvasEngine engine, uint32_t threads) noexcept; + + /** + * @brief Terminates TVG engines. + * + * @param[in] engine The engine types to terminate. This is relative to the Canvas types, in which it will be used. For multiple backends bitwise operation is allowed + * + * @retval Result::Success When succeed. + * @retval Result::InsufficientCondition In case there is nothing to be terminated. + * @retval Result::InvalidArguments If unknown engine type chosen. + * @retval Result::NonSupport In case the engine type is not supported on the system. + * @retval Result::Unknown Others. + * + * @note Initializer does own reference counting for multiple calls. + * @see Initializer::init() + */ + static Result term(CanvasEngine engine) noexcept; + + _TVG_DISABLE_CTOR(Initializer); +}; + + +/** + * @class Animation + * + * @brief The Animation class enables manipulation of animatable images. + * + * This class supports the display and control of animation frames. + * + * @BETA_API + */ + +class TVG_API Animation +{ +public: + ~Animation(); + + /** + * @brief Specifies the current frame in the animation. + * + * @param[in] no The index of the animation frame to be displayed. The index should be less than the totalFrame(). + * + * @retval Result::Success Successfully set the frame. + * @retval Result::InsufficientCondition No animatable data loaded from the Picture. + * @retval Result::NonSupport The Picture data does not support animations. + * + * @see totalFrame() + * + * @BETA_API + */ + Result frame(uint32_t no) noexcept; + + /** + * @brief Retrieves a picture instance associated with this animation instance. + * + * This function provides access to the picture instance that can be used to load animation formats, such as Lottie(json). + * After setting up the picture, it can be pushed to the designated canvas, enabling control over animation frames + * with this Animation instance. + * + * @return A picture instance that is tied to this animation. + * + * @warning The picture instance is owned by Animation. It should not be deleted manually. + * + * @BETA_API + */ + Picture* picture() const noexcept; + + /** + * @brief Retrieves the current frame number of the animation. + * + * @return The current frame number of the animation, between 0 and totalFrame() - 1. + * + * @note If the Picture is not properly configured, this function will return 0. + * + * @see Animation::frame(uint32_t no) + * @see Animation::totalFrame() + * + * @BETA_API + */ + uint32_t curFrame() const noexcept; + + /** + * @brief Retrieves the total number of frames in the animation. + * + * @return The total number of frames in the animation. + * + * @note Frame numbering starts from 0. + * @note If the Picture is not properly configured, this function will return 0. + * + * @BETA_API + */ + uint32_t totalFrame() const noexcept; + + /** + * @brief Retrieves the duration of the animation in seconds. + * + * @return The duration of the animation in seconds. + * + * @note If the Picture is not properly configured, this function will return 0. + * + * @BETA_API + */ + float duration() const noexcept; + + /** + * @brief Creates a new Animation object. + * + * @return A new Animation object. + * + * @BETA_API + */ + static std::unique_ptr gen() noexcept; + + _TVG_DECLARE_PRIVATE(Animation); +}; + + +/** + * @class Saver + * + * @brief A class for exporting a paint object into a specified file, from which to recover the paint data later. + * + * ThorVG provides a feature for exporting & importing paint data. The Saver role is to export the paint data to a file. + * It's useful when you need to save the composed scene or image from a paint object and recreate it later. + * + * The file format is decided by the extension name(i.e. "*.tvg") while the supported formats depend on the TVG packaging environment. + * If it doesn't support the file format, the save() method returns the @c Result::NonSuppport result. + * + * Once you export a paint to the file successfully, you can recreate it using the Picture class. + * + * @see Picture::load() + * + * @since 0.5 + */ +class TVG_API Saver final +{ +public: + ~Saver(); + + /** + * @brief Exports the given @p paint data to the given @p path + * + * If the saver module supports any compression mechanism, it will optimize the data size. + * This might affect the encoding/decoding time in some cases. You can turn off the compression + * if you wish to optimize for speed. + * + * @param[in] paint The paint to be saved with all its associated properties. + * @param[in] path A path to the file, in which the paint data is to be saved. + * @param[in] compress If @c true then compress data if possible. + * + * @retval Result::Success When succeed. + * @retval Result::InsufficientCondition If currently saving other resources. + * @retval Result::NonSupport When trying to save a file with an unknown extension or in an unsupported format. + * @retval Result::MemoryCorruption An internal error. + * @retval Result::Unknown In case an empty paint is to be saved. + * + * @note Saving can be asynchronous if the assigned thread number is greater than zero. To guarantee the saving is done, call sync() afterwards. + * @see Saver::sync() + * + * @since 0.5 + */ + Result save(std::unique_ptr paint, const std::string& path, bool compress = true) noexcept; + + /** + * @brief Guarantees that the saving task is finished. + * + * The behavior of the Saver works on a sync/async basis, depending on the threading setting of the Initializer. + * Thus, if you wish to have a benefit of it, you must call sync() after the save() in the proper delayed time. + * Otherwise, you can call sync() immediately. + * + * @retval Result::Success when succeed. + * @retval Result::InsufficientCondition otherwise. + * + * @note The asynchronous tasking is dependent on the Saver module implementation. + * @see Saver::save() + * + * @since 0.5 + */ + Result sync() noexcept; + + /** + * @brief Creates a new Saver object. + * + * @return A new Saver object. + * + * @since 0.5 + */ + static std::unique_ptr gen() noexcept; + + _TVG_DECLARE_PRIVATE(Saver); +}; + + +/** + * @class Accessor + * + * @brief The Accessor is a utility class to debug the Scene structure by traversing the scene-tree. + * + * The Accessor helps you search specific nodes to read the property information, figure out the structure of the scene tree and its size. + * + * @warning We strongly warn you not to change the paints of a scene unless you really know the design-structure. + * + * @since 0.10 + */ +class TVG_API Accessor final +{ +public: + ~Accessor(); + + /** + * @brief Set the access function for traversing the Picture scene tree nodes. + * + * @param[in] picture The picture node to traverse the internal scene-tree. + * @param[in] func The callback function calling for every paint nodes of the Picture. + * + * @return Return the given @p picture instance. + * + * @note The bitmap based picture might not have the scene-tree. + */ + std::unique_ptr set(std::unique_ptr picture, std::function func) noexcept; + + /** + * @brief Creates a new Accessor object. + * + * @return A new Accessor object. + */ + static std::unique_ptr gen() noexcept; + + _TVG_DECLARE_PRIVATE(Accessor); +}; + + +/** + * @brief The cast() function is a utility function used to cast a 'Paint' to type 'T'. + * @since 0.11 + */ +template +std::unique_ptr cast(Paint* paint) +{ + return std::unique_ptr(static_cast(paint)); +} + + +/** + * @brief The cast() function is a utility function used to cast a 'Fill' to type 'T'. + * @since 0.11 + */ +template +std::unique_ptr cast(Fill* fill) +{ + return std::unique_ptr(static_cast(fill)); +} + + +/** @}*/ + +} //namespace + +#endif //_THORVG_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/thorvg_capi.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/thorvg_capi.h new file mode 100644 index 000000000..1f31cb71d --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/thorvg_capi.h @@ -0,0 +1,2334 @@ +/*! +* \file thorvg_capi.h +* +* \brief The module provides C bindings for the ThorVG library. +* Please refer to src/examples/Capi.cpp to find the thorvg_capi usage examples. +* +* The thorvg_capi module allows to implement the ThorVG client and provides +* the following functionalities: +* - drawing shapes: line, arc, curve, polygon, circle, user-defined, ... +* - filling: solid, linear and radial gradient +* - scene graph & affine transformation (translation, rotation, scale, ...) +* - stroking: width, join, cap, dash +* - composition: blending, masking, path clipping +* - pictures: SVG, PNG, JPG, bitmap +* +*/ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef __THORVG_CAPI_H__ +#define __THORVG_CAPI_H__ + +#include +#include + +#ifdef TVG_API + #undef TVG_API +#endif + +#ifndef TVG_STATIC + #ifdef _WIN32 + #if TVG_BUILD + #define TVG_API __declspec(dllexport) + #else + #define TVG_API __declspec(dllimport) + #endif + #elif (defined(__SUNPRO_C) || defined(__SUNPRO_CC)) + #define TVG_API __global + #else + #if (defined(__GNUC__) && __GNUC__ >= 4) || defined(__INTEL_COMPILER) + #define TVG_API __attribute__ ((visibility("default"))) + #else + #define TVG_API + #endif + #endif +#else + #define TVG_API +#endif + +#ifdef TVG_DEPRECATED + #undef TVG_DEPRECATED +#endif + +#ifdef _WIN32 + #define TVG_DEPRECATED __declspec(deprecated) +#elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) + #define TVG_DEPRECATED __attribute__ ((__deprecated__)) +#else + #define TVG_DEPRECATED +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* \defgroup ThorVG_CAPI ThorVG_CAPI +* \brief ThorVG C language binding APIs. +* +* \{ +*/ + + +/** +* \brief A structure responsible for managing and drawing graphical elements. +* +* It sets up the target buffer, which can be drawn on the screen. It stores the Tvg_Paint objects (Shape, Scene, Picture). +*/ +typedef struct _Tvg_Canvas Tvg_Canvas; + + +/** +* \brief A structure representing a graphical element. +* +* \warning The TvgPaint objects can not be shared between Canvases. +*/ +typedef struct _Tvg_Paint Tvg_Paint; + + +/** +* \brief A structure representing a gradient fill of a Tvg_Paint object. +*/ +typedef struct _Tvg_Gradient Tvg_Gradient; + + +/** +* \brief A structure representing an object that enables to save a Tvg_Paint object into a file. +*/ +typedef struct _Tvg_Saver Tvg_Saver; + +/** +* \brief A structure representing an animation controller object. (BETA_API) +*/ +typedef struct _Tvg_Animation Tvg_Animation; + + +/** +* \brief Enumeration specifying the engine type used for the graphics backend. For multiple backends bitwise operation is allowed. +* +* \ingroup ThorVGCapi_Initializer +*/ +typedef enum { + TVG_ENGINE_SW = (1 << 1), ///< CPU rasterizer. + TVG_ENGINE_GL = (1 << 2) ///< OpenGL rasterizer. +} Tvg_Engine; + + +/** + * \brief Enumeration specifying the result from the APIs. + */ +typedef enum { + TVG_RESULT_SUCCESS = 0, ///< The value returned in case of a correct request execution. + TVG_RESULT_INVALID_ARGUMENT, ///< The value returned in the event of a problem with the arguments given to the API - e.g. empty paths or null pointers. + TVG_RESULT_INSUFFICIENT_CONDITION, ///< The value returned in case the request cannot be processed - e.g. asking for properties of an object, which does not exist. + TVG_RESULT_FAILED_ALLOCATION, ///< The value returned in case of unsuccessful memory allocation. + TVG_RESULT_MEMORY_CORRUPTION, ///< The value returned in the event of bad memory handling - e.g. failing in pointer releasing or casting + TVG_RESULT_NOT_SUPPORTED, ///< The value returned in case of choosing unsupported options. + TVG_RESULT_UNKNOWN ///< The value returned in all other cases. +} Tvg_Result; + + +/** + * \brief Enumeration indicating the method used in the composition of two objects - the target and the source. + * + * \ingroup ThorVGCapi_Paint + */ +typedef enum { + TVG_COMPOSITE_METHOD_NONE = 0, ///< No composition is applied. + TVG_COMPOSITE_METHOD_CLIP_PATH, ///< The intersection of the source and the target is determined and only the resulting pixels from the source are rendered. + TVG_COMPOSITE_METHOD_ALPHA_MASK, ///< The pixels of the source and the target are alpha blended. As a result, only the part of the source, which intersects with the target is visible. + TVG_COMPOSITE_METHOD_INVERSE_ALPHA_MASK, ///< The pixels of the source and the complement to the target's pixels are alpha blended. As a result, only the part of the source which is not covered by the target is visible. + TVG_COMPOSITE_METHOD_LUMA_MASK, ///< The source pixels are converted to grayscale (luma value) and alpha blended with the target. As a result, only the part of the source which intersects with the target is visible. \since 0.9 + TVG_COMPOSITE_METHOD_INVERSE_LUMA_MASK ///< The source pixels are converted to grayscale (luma value) and complement to the target's pixels are alpha blended. As a result, only the part of the source which is not covered by the target is visible. \BETA_API +} Tvg_Composite_Method; + +/** + * @brief Enumeration indicates the method used for blending paint. Please refer to the respective formulas for each method. + * + * \ingroup ThorVGCapi_Paint + * + * @BETA_API + */ +typedef enum { + TVG_BLEND_METHOD_NORMAL = 0, ///< Perform the alpha blending(default). S if (Sa == 255), otherwise (Sa * S) + (255 - Sa) * D + TVG_BLEND_METHOD_ADD, ///< Simply adds pixel values of one layer with the other. (S + D) + TVG_BLEND_METHOD_SCREEN, ///< The values of the pixels in the two layers are inverted, multiplied, and then inverted again. (S + D) - (S * D) + TVG_BLEND_METHOD_MULTIPLY, ///< Takes the RGB channel values from 0 to 255 of each pixel in the top layer and multiples them with the values for the corresponding pixel from the bottom layer. (S * D) + TVG_BLEND_METHOD_OVERLAY, ///< Combines Multiply and Screen blend modes. (2 * S * D) if (2 * D < Da), otherwise (Sa * Da) - 2 * (Da - S) * (Sa - D) + TVG_BLEND_METHOD_DIFFERENCE, ///< Subtracts the bottom layer from the top layer or the other way around, to always get a non-negative value. (S - D) if (S > D), otherwise (D - S) + TVG_BLEND_METHOD_EXCLUSION, ///< The result is twice the product of the top and bottom layers, subtracted from their sum. s + d - (2 * s * d) + TVG_BLEND_METHOD_SRCOVER, ///< Replace the bottom layer with the top layer. + TVG_BLEND_METHOD_DARKEN, ///< Creates a pixel that retains the smallest components of the top and bottom layer pixels. min(S, D) + TVG_BLEND_METHOD_LIGHTEN, ///< Only has the opposite action of Darken Only. max(S, D) + TVG_BLEND_METHOD_COLORDODGE, ///< Divides the bottom layer by the inverted top layer. D / (255 - S) + TVG_BLEND_METHOD_COLORBURN, ///< Divides the inverted bottom layer by the top layer, and then inverts the result. 255 - (255 - D) / S + TVG_BLEND_METHOD_HARDLIGHT, ///< The same as Overlay but with the color roles reversed. (2 * S * D) if (S < Sa), otherwise (Sa * Da) - 2 * (Da - S) * (Sa - D) + TVG_BLEND_METHOD_SOFTLIGHT ///< The same as Overlay but with applying pure black or white does not result in pure black or white. (1 - 2 * S) * (D ^ 2) + (2 * S * D) +} Tvg_Blend_Method; + + +/** + * \brief Enumeration indicating the ThorVG class type. + * + * \ingroup ThorVGCapi_Paint + * + * \since 0.9 + */ +typedef enum { + TVG_IDENTIFIER_UNDEF = 0, ///< Undefined type. + TVG_IDENTIFIER_SHAPE, ///< A shape type paint. + TVG_IDENTIFIER_SCENE, ///< A scene type paint. + TVG_IDENTIFIER_PICTURE, ///< A picture type paint. + TVG_IDENTIFIER_LINEAR_GRAD, ///< A linear gradient type. + TVG_IDENTIFIER_RADIAL_GRAD ///< A radial gradient type. +} Tvg_Identifier; + + +/** + * \addtogroup ThorVGCapi_Shape + * \{ + */ + +/** + * \brief Enumeration specifying the values of the path commands accepted by TVG. + * + * Not to be confused with the path commands from the svg path element (like M, L, Q, H and many others). + * TVG interprets all of them and translates to the ones from the PathCommand values. + */ +typedef enum { + TVG_PATH_COMMAND_CLOSE = 0, ///< Ends the current sub-path and connects it with its initial point - corresponds to Z command in the svg path commands. + TVG_PATH_COMMAND_MOVE_TO, ///< Sets a new initial point of the sub-path and a new current point - corresponds to M command in the svg path commands. + TVG_PATH_COMMAND_LINE_TO, ///< Draws a line from the current point to the given point and sets a new value of the current point - corresponds to L command in the svg path commands. + TVG_PATH_COMMAND_CUBIC_TO ///< Draws a cubic Bezier curve from the current point to the given point using two given control points and sets a new value of the current point - corresponds to C command in the svg path commands. +} Tvg_Path_Command; + + +/** + * \brief Enumeration determining the ending type of a stroke in the open sub-paths. + */ +typedef enum { + TVG_STROKE_CAP_SQUARE = 0, ///< The stroke is extended in both endpoints of a sub-path by a rectangle, with the width equal to the stroke width and the length equal to the half of the stroke width. For zero length sub-paths the square is rendered with the size of the stroke width. + TVG_STROKE_CAP_ROUND, ///< The stroke is extended in both endpoints of a sub-path by a half circle, with a radius equal to the half of a stroke width. For zero length sub-paths a full circle is rendered. + TVG_STROKE_CAP_BUTT ///< The stroke ends exactly at each of the two endpoints of a sub-path. For zero length sub-paths no stroke is rendered. +} Tvg_Stroke_Cap; + + +/** + * \brief Enumeration specifying how to fill the area outside the gradient bounds. + */ +typedef enum { + TVG_STROKE_JOIN_BEVEL = 0, ///< The outer corner of the joined path segments is bevelled at the join point. The triangular region of the corner is enclosed by a straight line between the outer corners of each stroke. + TVG_STROKE_JOIN_ROUND, ///< The outer corner of the joined path segments is rounded. The circular region is centered at the join point. + TVG_STROKE_JOIN_MITER ///< The outer corner of the joined path segments is spiked. The spike is created by extension beyond the join point of the outer edges of the stroke until they intersect. In case the extension goes beyond the limit, the join style is converted to the Bevel style. +} Tvg_Stroke_Join; + + +/** + * \brief Enumeration specifying how to fill the area outside the gradient bounds. + */ +typedef enum { + TVG_STROKE_FILL_PAD = 0, ///< The remaining area is filled with the closest stop color. + TVG_STROKE_FILL_REFLECT, ///< The gradient pattern is reflected outside the gradient area until the expected region is filled. + TVG_STROKE_FILL_REPEAT ///< The gradient pattern is repeated continuously beyond the gradient area until the expected region is filled. +} Tvg_Stroke_Fill; + + +/** + * \brief Enumeration specifying the algorithm used to establish which parts of the shape are treated as the inside of the shape. + */ +typedef enum { + TVG_FILL_RULE_WINDING = 0, ///< A line from the point to a location outside the shape is drawn. The intersections of the line with the path segment of the shape are counted. Starting from zero, if the path segment of the shape crosses the line clockwise, one is added, otherwise one is subtracted. If the resulting sum is non zero, the point is inside the shape. + TVG_FILL_RULE_EVEN_ODD ///< A line from the point to a location outside the shape is drawn and its intersections with the path segments of the shape are counted. If the number of intersections is an odd number, the point is inside the shape. +} Tvg_Fill_Rule; + +/** \} */ // end addtogroup ThorVGCapi_Shape + + +/*! +* \addtogroup ThorVGCapi_Gradient +* \{ +*/ + +/*! +* \brief A data structure storing the information about the color and its relative position inside the gradient bounds. +*/ +typedef struct +{ + float offset; /**< The relative position of the color. */ + uint8_t r; /**< The red color channel value in the range [0 ~ 255]. */ + uint8_t g; /**< The green color channel value in the range [0 ~ 255]. */ + uint8_t b; /**< The blue color channel value in the range [0 ~ 255]. */ + uint8_t a; /**< The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. */ +} Tvg_Color_Stop; + +/** \} */ // end addtogroup ThorVGCapi_Gradient + + +/** + * \brief A data structure representing a point in two-dimensional space. + */ +typedef struct +{ + float x, y; +} Tvg_Point; + + +/** + * \brief A data structure representing a three-dimensional matrix. + * + * The elements e11, e12, e21 and e22 represent the rotation matrix, including the scaling factor. + * The elements e13 and e23 determine the translation of the object along the x and y-axis, respectively. + * The elements e31 and e32 are set to 0, e33 is set to 1. + */ +typedef struct +{ + float e11, e12, e13; + float e21, e22, e23; + float e31, e32, e33; +} Tvg_Matrix; + + +/** +* \defgroup ThorVGCapi_Initializer Initializer +* \brief A module enabling initialization and termination of the TVG engines. +* +* \{ +*/ + +/************************************************************************/ +/* Engine API */ +/************************************************************************/ +/*! +* \brief Initializes TVG engines. +* +* TVG requires the running-engine environment. +* TVG runs its own task-scheduler for parallelizing rendering tasks efficiently. +* You can indicate the number of threads, the count of which is designated @p threads. +* In the initialization step, TVG will generate/spawn the threads as set by @p threads count. +* +* \code +* tvg_engine_init(TVG_ENGINE_SW, 0); //Initialize software renderer and use the main thread only +* \endcode +* +* \param[in] engine_method The engine types to initialize. This is relative to the Canvas types, in which it will be used. For multiple backends bitwise operation is allowed. +* - TVG_ENGINE_SW: CPU rasterizer +* - TVG_ENGINE_GL: OpenGL rasterizer (not supported yet) +* \param[in] threads The number of additional threads used to perform rendering. Zero indicates only the main thread is to be used. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error possibly with memory allocation. +* \retval TVG_RESULT_INVALID_ARGUMENT Unknown engine type. +* \retval TVG_RESULT_NOT_SUPPORTED Unsupported engine type. +* \retval TVG_RESULT_UNKNOWN Other error. +* +* \note The Initializer keeps track of the number of times it was called. Threads count is fixed at the first init() call. +* \see tvg_engine_term() +* \see Tvg_Engine +*/ +TVG_API Tvg_Result tvg_engine_init(Tvg_Engine engine_method, unsigned threads); + + +/*! +* \brief Terminates TVG engines. +* +* It should be called in case of termination of the TVG client with the same engine types as were passed when tvg_engine_init() was called. +* +* \code +* tvg_engine_init(TVG_ENGINE_SW, 0); +* //define canvas and shapes, update shapes, general rendering calls +* tvg_engine_term(TVG_ENGINE_SW); +* \endcode +* +* \param engine_method The engine types to terminate. This is relative to the Canvas types, in which it will be used. For multiple backends bitwise operation is allowed +* - TVG_ENGINE_SW: CPU rasterizer +* - TVG_ENGINE_GL: OpenGL rasterizer (not supported yet) +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION Nothing to be terminated. +* \retval TVG_RESULT_INVALID_ARGUMENT Unknown engine type. +* \retval TVG_RESULT_NOT_SUPPORTED Unsupported engine type. +* \retval TVG_RESULT_UNKNOWN An internal error. +* +* \see tvg_engine_init() +* \see Tvg_Engine +*/ +TVG_API Tvg_Result tvg_engine_term(Tvg_Engine engine_method); + + +/** \} */ // end defgroup ThorVGCapi_Initializer + + +/** +* \defgroup ThorVGCapi_Canvas Canvas +* \brief A module for managing and drawing graphical elements. +* +* A canvas is an entity responsible for drawing the target. It sets up the drawing engine and the buffer, which can be drawn on the screen. It also manages given Paint objects. +* +* \note A Canvas behavior depends on the raster engine though the final content of the buffer is expected to be identical. +* \warning The Paint objects belonging to one Canvas can't be shared among multiple Canvases. +\{ +*/ + + +/** +* \defgroup ThorVGCapi_SwCanvas SwCanvas +* \ingroup ThorVGCapi_Canvas +* +* \brief A module for rendering the graphical elements using the software engine. +* +* \{ +*/ + +/************************************************************************/ +/* SwCanvas API */ +/************************************************************************/ + +/** + * \brief Enumeration specifying the methods of Memory Pool behavior policy. + */ +typedef enum { + TVG_MEMPOOL_POLICY_DEFAULT = 0, ///< Default behavior that ThorVG is designed to. + TVG_MEMPOOL_POLICY_SHAREABLE, ///< Memory Pool is shared among canvases. + TVG_MEMPOOL_POLICY_INDIVIDUAL ///< Allocate designated memory pool that is used only by the current canvas instance. +} Tvg_Mempool_Policy; + + +/** + * \brief Enumeration specifying the methods of combining the 8-bit color channels into 32-bit color. + */ +typedef enum { + TVG_COLORSPACE_ABGR8888 = 0, ///< The 8-bit color channels are combined into 32-bit color in the order: alpha, blue, green, red. + TVG_COLORSPACE_ARGB8888 ///< The 8-bit color channels are combined into 32-bit color in the order: alpha, red, green, blue. +} Tvg_Colorspace; + + +/*! +* \brief Creates a Canvas object. +* +* \code +* Tvg_Canvas *canvas = NULL; +* +* tvg_engine_init(TVG_ENGINE_SW, 4); +* canvas = tvg_swcanvas_create(); +* +* //set up the canvas buffer +* uint32_t *buffer = NULL; +* buffer = (uint32_t*) malloc(sizeof(uint32_t) * 100 * 100); +* if (!buffer) return; +* +* tvg_swcanvas_set_target(canvas, buffer, 100, 100, 100, TVG_COLORSPACE_ARGB8888); +* +* //set up paints and add them into the canvas before drawing it +* +* tvg_canvas_destroy(canvas); +* tvg_engine_term(TVG_ENGINE_SW); +* \endcode +* +* \return A new Tvg_Canvas object. +*/ +TVG_API Tvg_Canvas* tvg_swcanvas_create(); + + +/*! +* \brief Sets the buffer used in the rasterization process and defines the used colorspace. +* +* For optimisation reasons TVG does not allocate memory for the output buffer on its own. +* The buffer of a desirable size should be allocated and owned by the caller. +* +* \param[in] canvas The Tvg_Canvas object managing the @p buffer. +* \param[in] buffer A pointer to the allocated memory block of the size @p stride x @p h. +* \param[in] stride The stride of the raster image - in most cases same value as @p w. +* \param[in] w The width of the raster image. +* \param[in] h The height of the raster image. +* \param[in] cs The colorspace value defining the way the 32-bits colors should be read/written. +* - TVG_COLORSPACE_ABGR8888 +* - TVG_COLORSPACE_ARGB8888 +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_MEMORY_CORRUPTION Casting in the internal function implementation failed. +* \retval TVG_RESULT_INVALID_ARGUMENTS An invalid canvas or buffer pointer passed or one of the @p stride, @p w or @p h being zero. +* \retval TVG_RESULT_NOT_SUPPORTED The software engine is not supported. +* +* \warning Do not access @p buffer during tvg_canvas_draw() - tvg_canvas_sync(). It should not be accessed while TVG is writing on it. +* +* \see Tvg_Colorspace +*/ +TVG_API Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Tvg_Colorspace cs); + + +/*! +* \brief Sets the software engine memory pool behavior policy. +* +* ThorVG draws a lot of shapes, it allocates/deallocates a few chunk of memory +* while processing rendering. It internally uses one shared memory pool +* which can be reused among the canvases in order to avoid memory overhead. +* +* Thus ThorVG suggests using a memory pool policy to satisfy user demands, +* if it needs to guarantee the thread-safety of the internal data access. +* +* \param[in] canvas The Tvg_Canvas object of which the Memory Pool behavior is to be specified. +* \param[in] policy The method specifying the Memory Pool behavior. The default value is @c TVG_MEMPOOL_POLICY_DEFAULT. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENTS An invalid canvas pointer passed. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION The canvas contains some paints already. +* \retval TVG_RESULT_NOT_SUPPORTED The software engine is not supported. +* +* \note When @c policy is set as @c TVG_MEMPOOL_POLICY_INDIVIDUAL, the current instance of canvas uses its own individual +* memory data, which is not shared with others. This is necessary when the canvas is accessed on a worker-thread. +* +* \warning It's not allowed after pushing any paints. +*/ +TVG_API Tvg_Result tvg_swcanvas_set_mempool(Tvg_Canvas* canvas, Tvg_Mempool_Policy policy); + +/** \} */ // end defgroup ThorVGCapi_SwCanvas + + +/************************************************************************/ +/* Common Canvas API */ +/************************************************************************/ +/*! +* \brief Clears the canvas internal data, releases all paints stored by the canvas and destroys the canvas object itself. +* +* \code +* static Tvg_Canvas *canvas = NULL; +* static uint32_t *buffer = NULL; +* +* static void _init() { +* canvas = tvg_swcanvas_create(); +* buffer = (uint32_t*) malloc(sizeof(uint32_t) * 100 * 100); +* tvg_swcanvas_set_target(canvas, buffer, 100, 100, 100, TVG_COLORSPACE_ARGB8888); +* } +* +* //a task called from main function in a loop +* static void _job(const int cmd) { +* //define a valid rectangle shape +* switch (cmd) { +* case CMD_EXIT: return 0; +* case CMD_ADD_RECT: +* tvg_canvas_push(canvas, rect); +* break; +* case CMD_DEL_RECT: +* tvg_paint_del(rect); +* //now to safely delete Tvg_Canvas, tvg_canvas_clear() API have to be used +* break; +* default: +* break; +* } +* } +* +* int main(int argc, char **argv) { +* int cmd = 0; +* int stop = 1; +* +* tvg_engine_init(TVG_ENGINE_SW, 4); +* +* while (stop) { +* //wait for a command e.g. from a console +* stop = _job(cmd); +* } +* tvg_canvas_clear(canvas, false); +* tvg_canvas_destroy(canvas); +* tvg_engine_term(TVG_ENGINE_SW); +* return 0; +* } +* +* tvg_canvas_destroy(canvas); +* tvg_engine_term(TVG_ENGINE_SW) +* \endcode +* +* \param[in] canvas The Tvg_Canvas object to be destroyed. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid pointer to the Tvg_Canvas object is passed. +* +* \note If the paints from the canvas should not be released, the tvg_canvas_clear() with a @c free argument value set to @c false should be called. +* Please be aware that in such a case TVG is not responsible for the paints release anymore and it has to be done manually in order to avoid memory leaks. +* +* \see tvg_paint_del(), tvg_canvas_clear() +*/ +TVG_API Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas); + + +/*! +* \brief Inserts a drawing element into the canvas using a Tvg_Paint object. +* +* \param[in] canvas The Tvg_Canvas object managing the @p paint. +* \param[in] paint The Tvg_Paint object to be drawn. +* +* Only the paints pushed into the canvas will be drawing targets. +* They are retained by the canvas until you call tvg_canvas_clear(). +* If you know the number of the pushed objects in advance, please call tvg_canvas_reserve(). +* +* \return Tvg_Result return values: +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT In case a @c nullptr is passed as the argument. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION An internal error. +* +* \note The rendering order of the paints is the same as the order as they were pushed. Consider sorting the paints before pushing them if you intend to use layering. +* \see tvg_canvas_clear() +*/ +TVG_API Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint); + + +/*! +* \brief Reserves a memory block where the objects pushed into a canvas are stored. +* +* If the number of Tvg_Paints to be stored in a canvas is known in advance, calling this function reduces the multiple +* memory allocations thus improves the performance. +* +* \code +* Tvg_Canvas *canvas = NULL; +* +* tvg_engine_init(TVG_ENGINE_SW, 4); +* canvas = tvg_swcanvas_create(); +* +* uint32_t *buffer = NULL; +* buffer = (uint32_t*) malloc(sizeof(uint32_t) * 100 * 100); +* if (!buffer) return; +* +* tvg_swcanvas_set_target(canvas, buffer, 100, 100, 100, TVG_COLORSPACE_ARGB8888); +* +* tvg_canvas_destroy(canvas); +* tvg_engine_term(TVG_ENGINE_SW) +* \endcode +* +* \param[in] canvas The Tvg_Canvas object managing the reserved memory. +* \param[in] n The number of objects for which the memory is to be reserved. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Canvas pointer. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with memory allocation. +*/ +TVG_DEPRECATED TVG_API Tvg_Result tvg_canvas_reserve(Tvg_Canvas* canvas, uint32_t n); + + +/*! +* \brief Sets the total number of the paints pushed into the canvas to be zero. +* Tvg_Paint objects stored in the canvas are released if @p free is set to @c true, otherwise the memory is not deallocated and +* all paints should be released manually in order to avoid memory leaks. +* +* \param[in] canvas The Tvg_Canvas object to be cleared. +* \param[in] free If @c true the memory occupied by paints is deallocated, otherwise it is not. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Canvas pointer. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION An internal error. +* +* \warning Please use the @p free argument only when you know how it works, otherwise it's not recommended. +* +* \see tvg_canvas_destroy() +*/ +TVG_API Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool free); + + +/*! +* \brief Updates all paints in a canvas. +* +* Should be called before drawing in order to prepare paints for the rendering. +* +* \code +* //A frame drawing example. Thread safety and events implementation is skipped to show only TVG code. +* +* static Tvg_Canvas *canvas = NULL; +* static Tvg_Paint *rect = NULL; +* +* int _frame_render(void) { +* tvg_canvas_update(canvas); +* tvg_canvas_draw(canvas); +* tvg_canvas_sync(canvas); +* } +* +* //event handler from your code or third party library +* void _event_handler(event *event_data) { +* if (!event_data) return NULL; +* switch(event_data.type) { +* case EVENT_RECT_ADD: +* if (!rect) { +* tvg_shape_append_rect(rect, 10, 10, 50, 50, 0, 0); +* tvg_shape_set_stroke_width(rect, 1.0f); +* tvg_shape_set_stroke_color(rect, 255, 0, 0, 255); +* tvg_canvas_push(canvas, rect); +* } +* break; +* case EVENT_RECT_MOVE: +* if (rect) tvg_paint_translate(rect, 10.0, 10.0); +* break; +* default: +* break; +* } +* } +* +* int main(int argc, char **argv) { +* //example handler from your code or third party lib +* event_handler_add(handler, _event_handler); +* +* //create frame rendering process which calls _frame_render() function. +* app_loop_begin(_frame_render); +* app_loop_finish(); +* cleanup(); +* } +* \endcode +* +* \param[in] canvas The Tvg_Canvas object to be updated. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Canvas pointer. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION An internal error. +* +* \see tvg_canvas_update_paint() +*/ +TVG_API Tvg_Result tvg_canvas_update(Tvg_Canvas* canvas); + + +/*! +* \brief Updates the given Tvg_Paint object from the canvas before the rendering. +* +* If a client application using the TVG library does not update the entire canvas with tvg_canvas_update() in the frame +* rendering process, Tvg_Paint objects previously added to the canvas should be updated manually with this function. +* +* \param[in] canvas The Tvg_Canvas object to which the @p paint belongs. +* \param[in] paint The Tvg_Paint object to be updated. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT In case a @c nullptr is passed as the argument. +* +* \see tvg_canvas_update() +*/ +TVG_API Tvg_Result tvg_canvas_update_paint(Tvg_Canvas* canvas, Tvg_Paint* paint); + + +/*! +* \brief Requests the canvas to draw the Tvg_Paint objects. +* +* All paints from the given canvas will be rasterized to the buffer. +* +* \param[in] canvas The Tvg_Canvas object containing elements to be drawn. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Canvas pointer. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION An internal error. +* +* \note Drawing can be asynchronous based on the assigned thread number. To guarantee the drawing is done, call tvg_canvas_sync() afterwards. +* \see tvg_canvas_sync() +*/ +TVG_API Tvg_Result tvg_canvas_draw(Tvg_Canvas* canvas); + + +/*! +* \brief Guarantees that the drawing process is finished. +* +* Since the canvas rendering can be performed asynchronously, it should be called after the tvg_canvas_draw(). +* +* \param[in] canvas The Tvg_Canvas object containing elements which were drawn. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Canvas pointer. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION An internal error. +* +* \see tvg_canvas_draw() +*/ +TVG_API Tvg_Result tvg_canvas_sync(Tvg_Canvas* canvas); + + +/** \} */ // end defgroup ThorVGCapi_Canvas + + +/** +* \defgroup ThorVGCapi_Paint Paint +* \brief A module for managing graphical elements. It enables duplication, transformation and composition. +* +* \{ +*/ + +/************************************************************************/ +/* Paint API */ +/************************************************************************/ +/*! +* \brief Releases the given Tvg_Paint object. +* +* \code +* //example of cleanup function +* Tvg_Paint *rect = NULL; //rectangle shape added in other function +* +* //rectangle delete API +* int rectangle_delete(void) { +* if (rect) tvg_paint_del(rect); +* rect = NULL; +* } +* +* int cleanup(void) { +* tvg_canvas_clear(canvas, false); +* tvg_canvas_destroy(canvas); +* canvas = NULL; +* } +* \endcode +* +* \param[in] paint The Tvg_Paint object to be released. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* +* \warning If this function is used, tvg_canvas_clear() with the @c free argument value set to @c false should be used in order to avoid unexpected behaviours. +* +* \see tvg_canvas_clear(), tvg_canvas_destroy() +*/ +TVG_API Tvg_Result tvg_paint_del(Tvg_Paint* paint); + + +/*! +* \brief Scales the given Tvg_Paint object by the given factor. +* +* \param[in] paint The Tvg_Paint object to be scaled. +* \param[in] factor The value of the scaling factor. The default value is 1. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with memory allocation. +*/ +TVG_API Tvg_Result tvg_paint_scale(Tvg_Paint* paint, float factor); + + +/*! +* \brief Rotates the given Tvg_Paint by the given angle. +* +* The angle in measured clockwise from the horizontal axis. +* The rotational axis passes through the point on the object with zero coordinates. +* +* \param[in] paint The Tvg_Paint object to be rotated. +* \param[in] degree The value of the rotation angle in degrees. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with memory allocation. +*/ +TVG_API Tvg_Result tvg_paint_rotate(Tvg_Paint* paint, float degree); + + +/*! +* \brief Moves the given Tvg_Paint in a two-dimensional space. +* +* The origin of the coordinate system is in the upper left corner of the canvas. +* The horizontal and vertical axes point to the right and down, respectively. +* +* \param[in] paint The Tvg_Paint object to be shifted. +* \param[in] x The value of the horizontal shift. +* \param[in] y The value of the vertical shift. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with memory allocation. +*/ +TVG_API Tvg_Result tvg_paint_translate(Tvg_Paint* paint, float x, float y); + + +/*! +* \brief Transforms the given Tvg_Paint using the augmented transformation matrix. +* +* The augmented matrix of the transformation is expected to be given. +* +* \param[in] paint The Tvg_Paint object to be transformed. +* \param[in] m The 3x3 augmented matrix. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT A @c nullptr is passed as the argument. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with memory allocation. +*/ +TVG_API Tvg_Result tvg_paint_set_transform(Tvg_Paint* paint, const Tvg_Matrix* m); + + +/*! +* \brief Gets the matrix of the affine transformation of the given Tvg_Paint object. +* +* In case no transformation was applied, the identity matrix is returned. +* +* \param[in] paint The Tvg_Paint object of which to get the transformation matrix. +* \param[out] m The 3x3 augmented matrix. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT A @c nullptr is passed as the argument. +*/ +TVG_API Tvg_Result tvg_paint_get_transform(Tvg_Paint* paint, Tvg_Matrix* m); + + +/*! +* \brief Sets the opacity of the given Tvg_Paint. +* +* \param[in] paint The Tvg_Paint object of which the opacity value is to be set. +* \param[in] opacity The opacity value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* +* \note Setting the opacity with this API may require multiple renderings using a composition. It is recommended to avoid changing the opacity if possible. +*/ +TVG_API Tvg_Result tvg_paint_set_opacity(Tvg_Paint* paint, uint8_t opacity); + + +/*! +* \brief Gets the opacity of the given Tvg_Paint. +* +* \param[in] paint The Tvg_Paint object of which to get the opacity value. +* \param[out] opacity The opacity value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT In case a @c nullptr is passed as the argument. +*/ +TVG_API Tvg_Result tvg_paint_get_opacity(const Tvg_Paint* paint, uint8_t* opacity); + + +/*! +* \brief Duplicates the given Tvg_Paint object. +* +* Creates a new object and sets its all properties as in the original object. +* +* \param[in] paint The Tvg_Paint object to be copied. +* +* \return A copied Tvg_Paint object if succeed, @c nullptr otherwise. +*/ +TVG_API Tvg_Paint* tvg_paint_duplicate(Tvg_Paint* paint); + + +/*! +* \brief Gets the axis-aligned bounding box of the Tvg_Paint object. +* +* \param[in] paint The Tvg_Paint object of which to get the bounds. +* \param[out] x The x coordinate of the upper left corner of the object. +* \param[out] y The y coordinate of the upper left corner of the object. +* \param[out] w The width of the object. +* \param[out] h The height of the object. +* \param[in] transformed If @c true, the transformation of the paint is taken into account, otherwise it isn't. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION Other errors. +* +* \note The bounding box doesn't indicate the actual drawing region. It's the smallest rectangle that encloses the object. +*/ +TVG_API Tvg_Result tvg_paint_get_bounds(const Tvg_Paint* paint, float* x, float* y, float* w, float* h, bool transformed); + + +/*! +* \brief Sets the composition target object and the composition method. +* +* \param[in] paint The source object of the composition. +* \param[in] target The target object of the composition. +* \param[in] method The method used to composite the source object with the target. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid @p paint or @p target object or the @p method equal to TVG_COMPOSITE_METHOD_NONE. +*/ +TVG_API Tvg_Result tvg_paint_set_composite_method(Tvg_Paint* paint, Tvg_Paint* target, Tvg_Composite_Method method); + + +/** +* \brief Gets the composition target object and the composition method. +* +* \param[in] paint The source object of the composition. +* \param[out] target The target object of the composition. +* \param[out] method The method used to composite the source object with the target. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT A @c nullptr is passed as the argument. +*/ +TVG_API Tvg_Result tvg_paint_get_composite_method(const Tvg_Paint* paint, const Tvg_Paint** target, Tvg_Composite_Method* method); + + +/** +* \brief Gets the unique id value of the paint instance indicating the instance type. +* +* \param[in] paint The Tvg_Paint object of which to get the identifier value. +* \param[out] identifier The unique identifier of the paint instance type. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT In case a @c nullptr is passed as the argument. +* +* \since 0.9 +*/ +TVG_API Tvg_Result tvg_paint_get_identifier(const Tvg_Paint* paint, Tvg_Identifier* identifier); + + +/** + * @brief Sets the blending method for the paint object. + * + * The blending feature allows you to combine colors to create visually appealing effects, including transparency, lighting, shading, and color mixing, among others. + * its process involves the combination of colors or images from the source paint object with the destination (the lower layer image) using blending operations. + * The blending operation is determined by the chosen @p BlendMethod, which specifies how the colors or images are combined. + * + * \param[in] paint The Tvg_Paint object of which to get the identifier value. + * \param[in] method The blending method to be set. + * + * \return Tvg_Result enumeration. + * \retval TVG_RESULT_INVALID_ARGUMENT In case a @c nullptr is passed as the argument. + * + * @BETA_API + */ +TVG_API Tvg_Result tvg_paint_set_blend_method(const Tvg_Paint* paint, Tvg_Blend_Method method); + + +/** + * @brief Gets the blending method for the paint object. + * + * The blending feature allows you to combine colors to create visually appealing effects, including transparency, lighting, shading, and color mixing, among others. + * its process involves the combination of colors or images from the source paint object with the destination (the lower layer image) using blending operations. + * The blending operation is determined by the chosen @p BlendMethod, which specifies how the colors or images are combined. + * + * \param[in] paint The Tvg_Paint object of which to get the identifier value. + * \param[out] method The blending method of the paint. + * + * \return Tvg_Result enumeration. + * \retval TVG_RESULT_INVALID_ARGUMENT In case a @c nullptr is passed as the argument. + * + * @BETA_API + */ +TVG_API Tvg_Result tvg_paint_get_blend_method(const Tvg_Paint* paint, Tvg_Blend_Method* method); + + +/** \} */ // end defgroup ThorVGCapi_Paint + +/** +* \defgroup ThorVGCapi_Shape Shape +* +* \brief A module for managing two-dimensional figures and their properties. +* +* A shape has three major properties: shape outline, stroking, filling. The outline in the shape is retained as the path. +* Path can be composed by accumulating primitive commands such as tvg_shape_move_to(), tvg_shape_line_to(), tvg_shape_cubic_to() or complete shape interfaces such as tvg_shape_append_rect(), tvg_shape_append_circle(), etc. +* Path can consists of sub-paths. One sub-path is determined by a close command. +* +* The stroke of a shape is an optional property in case the shape needs to be represented with/without the outline borders. +* It's efficient since the shape path and the stroking path can be shared with each other. It's also convenient when controlling both in one context. +* +* \{ +*/ + +/************************************************************************/ +/* Shape API */ +/************************************************************************/ +/*! +* \brief Creates a new shape object. +* +* \return A new shape object. +*/ +TVG_API Tvg_Paint* tvg_shape_new(); + + +/*! +* \brief Resets the shape path properties. +* +* The color, the fill and the stroke properties are retained. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* +* \note The memory, where the path data is stored, is not deallocated at this stage for caching effect. +*/ +TVG_API Tvg_Result tvg_shape_reset(Tvg_Paint* paint); + + +/*! +* \brief Sets the initial point of the sub-path. +* +* The value of the current point is set to the given point. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] x The horizontal coordinate of the initial point of the sub-path. +* \param[in] y The vertical coordinate of the initial point of the sub-path. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +*/ +TVG_API Tvg_Result tvg_shape_move_to(Tvg_Paint* paint, float x, float y); + + +/*! +* \brief Adds a new point to the sub-path, which results in drawing a line from the current point to the given end-point. +* +* The value of the current point is set to the given end-point. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] x The horizontal coordinate of the end-point of the line. +* \param[in] y The vertical coordinate of the end-point of the line. + +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* +* \note In case this is the first command in the path, it corresponds to the tvg_shape_move_to() call. +*/ +TVG_API Tvg_Result tvg_shape_line_to(Tvg_Paint* paint, float x, float y); + + +/*! +* \brief Adds new points to the sub-path, which results in drawing a cubic Bezier curve. +* +* The Bezier curve starts at the current point and ends at the given end-point (@p x, @p y). Two control points (@p cx1, @p cy1) and (@p cx2, @p cy2) are used to determine the shape of the curve. +* The value of the current point is set to the given end-point. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] cx1 The horizontal coordinate of the 1st control point. +* \param[in] cy1 The vertical coordinate of the 1st control point. +* \param[in] cx2 The horizontal coordinate of the 2nd control point. +* \param[in] cy2 The vertical coordinate of the 2nd control point. +* \param[in] x The horizontal coordinate of the endpoint of the curve. +* \param[in] y The vertical coordinate of the endpoint of the curve. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* +* \note In case this is the first command in the path, no data from the path are rendered. +*/ +TVG_API Tvg_Result tvg_shape_cubic_to(Tvg_Paint* paint, float cx1, float cy1, float cx2, float cy2, float x, float y); + + +/*! +* \brief Closes the current sub-path by drawing a line from the current point to the initial point of the sub-path. +* +* The value of the current point is set to the initial point of the closed sub-path. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* +* \note In case the sub-path does not contain any points, this function has no effect. +*/ +TVG_API Tvg_Result tvg_shape_close(Tvg_Paint* paint); + + +/*! +* \brief Appends a rectangle to the path. +* +* The rectangle with rounded corners can be achieved by setting non-zero values to @p rx and @p ry arguments. +* The @p rx and @p ry values specify the radii of the ellipse defining the rounding of the corners. +* +* The position of the rectangle is specified by the coordinates of its upper left corner - @p x and @p y arguments. +* +* The rectangle is treated as a new sub-path - it is not connected with the previous sub-path. +* +* The value of the current point is set to (@p x + @p rx, @p y) - in case @p rx is greater +* than @p w/2 the current point is set to (@p x + @p w/2, @p y) +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] x The horizontal coordinate of the upper left corner of the rectangle. +* \param[in] y The vertical coordinate of the upper left corner of the rectangle. +* \param[in] w The width of the rectangle. +* \param[in] h The height of the rectangle. +* \param[in] rx The x-axis radius of the ellipse defining the rounded corners of the rectangle. +* \param[in] ry The y-axis radius of the ellipse defining the rounded corners of the rectangle. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* +& \note For @p rx and @p ry greater than or equal to the half of @p w and the half of @p h, respectively, the shape become an ellipse. +*/ +TVG_API Tvg_Result tvg_shape_append_rect(Tvg_Paint* paint, float x, float y, float w, float h, float rx, float ry); + + +/*! +* \brief Appends an ellipse to the path. +* +* The position of the ellipse is specified by the coordinates of its center - @p cx and @p cy arguments. +* +* The ellipse is treated as a new sub-path - it is not connected with the previous sub-path. +* +* The value of the current point is set to (@p cx, @p cy - @p ry). +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] cx The horizontal coordinate of the center of the ellipse. +* \param[in] cy The vertical coordinate of the center of the ellipse. +* \param[in] rx The x-axis radius of the ellipse. +* \param[in] ry The y-axis radius of the ellipse. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +*/ +TVG_API Tvg_Result tvg_shape_append_circle(Tvg_Paint* paint, float cx, float cy, float rx, float ry); + + +/*! +* \brief Appends a circular arc to the path. +* +* The arc is treated as a new sub-path - it is not connected with the previous sub-path. +* The current point value is set to the end-point of the arc in case @p pie is @c false, and to the center of the arc otherwise. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] cx The horizontal coordinate of the center of the arc. +* \param[in] cy The vertical coordinate of the center of the arc. +* \param[in] radius The radius of the arc. +* \param[in] startAngle The start angle of the arc given in degrees, measured counter-clockwise from the horizontal line. +* \param[in] sweep The central angle of the arc given in degrees, measured counter-clockwise from @p startAngle. +* \param[in] pie Specifies whether to draw radii from the arc's center to both of its end-point - drawn if @c true. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* +* \note Setting @p sweep value greater than 360 degrees, is equivalent to calling tvg_shape_append_circle(paint, cx, cy, radius, radius). +*/ +TVG_API Tvg_Result tvg_shape_append_arc(Tvg_Paint* paint, float cx, float cy, float radius, float startAngle, float sweep, uint8_t pie); + + +/*! +* \brief Appends a given sub-path to the path. +* +* The current point value is set to the last point from the sub-path. +* For each command from the @p cmds array, an appropriate number of points in @p pts array should be specified. +* If the number of points in the @p pts array is different than the number required by the @p cmds array, the shape with this sub-path will not be displayed on the screen. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] cmds The array of the commands in the sub-path. +* \param[in] cmdCnt The length of the @p cmds array. +* \param[in] pts The array of the two-dimensional points. +* \param[in] ptsCnt The length of the @p pts array. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT A @c nullptr passed as the argument or @p cmdCnt or @p ptsCnt equal to zero. +*/ +TVG_API Tvg_Result tvg_shape_append_path(Tvg_Paint* paint, const Tvg_Path_Command* cmds, uint32_t cmdCnt, const Tvg_Point* pts, uint32_t ptsCnt); + + +/*! +* \brief Gets the points values of the path. +* +* The function does not allocate any data, it operates on internal memory. There is no need to free the @p pts array. +* +* \code +* Tvg_Shape *shape = tvg_shape_new(); +* Tvg_Point *coords = NULL; +* uint32_t len = 0; +* +* tvg_shape_append_circle(shape, 10, 10, 50, 50); +* tvg_shape_get_path_coords(shape, (const Tvg_Point**)&coords, &len); +* //TVG approximates a circle by four Bezier curves. In the example above the coords array stores their coordinates. +* \endcode +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[out] pts The pointer to the array of the two-dimensional points from the path. +* \param[out] cnt The length of the @p pts array. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT A @c nullptr passed as the argument. +*/ +TVG_API Tvg_Result tvg_shape_get_path_coords(const Tvg_Paint* paint, const Tvg_Point** pts, uint32_t* cnt); + + +/*! +* \brief Gets the commands data of the path. +* +* The function does not allocate any data. There is no need to free the @p cmds array. +* +* \code +* Tvg_Shape *shape = tvg_shape_new(); +* Tvg_Path_Command *cmds = NULL; +* uint32_t len = 0; +* +* tvg_shape_append_circle(shape, 10, 10, 50, 50); +* tvg_shape_get_path_commands(shape, (const Tvg_Path_Command**)&cmds, &len); +* //TVG approximates a circle by four Bezier curves. In the example above the cmds array stores the commands of the path data. +* \endcode +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[out] cmds The pointer to the array of the commands from the path. +* \param[out] cnt The length of the @p cmds array. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT A @c nullptr passed as the argument. +*/ +TVG_API Tvg_Result tvg_shape_get_path_commands(const Tvg_Paint* paint, const Tvg_Path_Command** cmds, uint32_t* cnt); + + +/*! +* \brief Sets the stroke width for all of the figures from the @p paint. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] width The width of the stroke. The default value is 0. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with a memory allocation. +*/ +TVG_API Tvg_Result tvg_shape_set_stroke_width(Tvg_Paint* paint, float width); + + +/*! +* \brief Gets the shape's stroke width. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[out] width The stroke width. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid pointer passed as an argument. +*/ +TVG_API Tvg_Result tvg_shape_get_stroke_width(const Tvg_Paint* paint, float* width); + + +/*! +* \brief Sets the shape's stroke color. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] r The red color channel value in the range [0 ~ 255]. The default value is 0. +* \param[in] g The green color channel value in the range [0 ~ 255]. The default value is 0. +* \param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0. +* \param[in] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with a memory allocation. +* +* \note Either a solid color or a gradient fill is applied, depending on what was set as last. +*/ +TVG_API Tvg_Result tvg_shape_set_stroke_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a); + + +/*! +* \brief Gets the shape's stroke color. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[out] r The red color channel value in the range [0 ~ 255]. The default value is 0. +* \param[out] g The green color channel value in the range [0 ~ 255]. The default value is 0. +* \param[out] b The blue color channel value in the range [0 ~ 255]. The default value is 0. +* \param[out] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION No stroke was set. +*/ +TVG_API Tvg_Result tvg_shape_get_stroke_color(const Tvg_Paint* paint, uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a); + + +/*! +* \brief Sets the linear gradient fill of the stroke for all of the figures from the path. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] grad The linear gradient fill. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with a memory allocation. +* \retval TVG_RESULT_MEMORY_CORRUPTION An invalid Tvg_Gradient pointer. +* +* \note Either a solid color or a gradient fill is applied, depending on what was set as last. +*/ +TVG_API Tvg_Result tvg_shape_set_stroke_linear_gradient(Tvg_Paint* paint, Tvg_Gradient* grad); + + +/*! +* \brief Sets the radial gradient fill of the stroke for all of the figures from the path. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] grad The radial gradient fill. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with a memory allocation. +* \retval TVG_RESULT_MEMORY_CORRUPTION An invalid Tvg_Gradient pointer. +* +* \note Either a solid color or a gradient fill is applied, depending on what was set as last. +*/ +TVG_API Tvg_Result tvg_shape_set_stroke_radial_gradient(Tvg_Paint* paint, Tvg_Gradient* grad); + + +/*! +* \brief Gets the gradient fill of the shape's stroke. +* +* The function does not allocate any memory. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[out] grad The gradient fill. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid pointer passed as an argument. +*/ +TVG_API Tvg_Result tvg_shape_get_stroke_gradient(const Tvg_Paint* paint, Tvg_Gradient** grad); + + +/*! +* \brief Sets the shape's stroke dash pattern. +* +* \code +* //dash pattern examples +* float dashPattern[2] = {20, 10}; // -- -- -- +* float dashPattern[2] = {40, 20}; // ---- ---- ---- +* float dashPattern[4] = {10, 20, 30, 40} // - --- - --- +* \endcode +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] dashPattern The array of consecutive pair values of the dash length and the gap length. +* \param[in] cnt The size of the @p dashPattern array. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid pointer passed as an argument and @p cnt > 0, the given length of the array is less than two or any of the @p dashPattern values is zero or less. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with a memory allocation. +* +* \note To reset the stroke dash pattern, pass @c nullptr to @p dashPattern and zero to @p cnt. +*/ +TVG_API Tvg_Result tvg_shape_set_stroke_dash(Tvg_Paint* paint, const float* dashPattern, uint32_t cnt); + + +/*! +* \brief Gets the dash pattern of the stroke. +* +* The function does not allocate any memory. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[out] dashPattern The array of consecutive pair values of the dash length and the gap length. +* \param[out] cnt The size of the @p dashPattern array. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid pointer passed as an argument. +*/ +TVG_API Tvg_Result tvg_shape_get_stroke_dash(const Tvg_Paint* paint, const float** dashPattern, uint32_t* cnt); + + +/*! +* \brief Sets the cap style used for stroking the path. +* +* The cap style specifies the shape to be used at the end of the open stroked sub-paths. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] cap The cap style value. The default value is @c TVG_STROKE_CAP_SQUARE. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with a memory allocation. +*/ +TVG_API Tvg_Result tvg_shape_set_stroke_cap(Tvg_Paint* paint, Tvg_Stroke_Cap cap); + + +/*! +* \brief Gets the stroke cap style used for stroking the path. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[out] cap The cap style value. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid pointer passed as an argument. +*/ +TVG_API Tvg_Result tvg_shape_get_stroke_cap(const Tvg_Paint* paint, Tvg_Stroke_Cap* cap); + + +/*! +* \brief Sets the join style for stroked path segments. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] join The join style value. The default value is @c TVG_STROKE_JOIN_BEVEL. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with a memory allocation. +*/ +TVG_API Tvg_Result tvg_shape_set_stroke_join(Tvg_Paint* paint, Tvg_Stroke_Join join); + + +/*! +* \brief The function gets the stroke join method +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[out] join The join style value. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid pointer passed as an argument. +*/ +TVG_API Tvg_Result tvg_shape_get_stroke_join(const Tvg_Paint* paint, Tvg_Stroke_Join* join); + + +/*! +* \brief Sets the stroke miterlimit. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] miterlimit The miterlimit imposes a limit on the extent of the stroke join when the @c TVG_STROKE_JOIN_MITER join style is set. The default value is 4. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_NOT_SUPPORTED Unsupported value. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with a memory allocation. +* +* \since 0.11 +*/ +TVG_API Tvg_Result tvg_shape_set_stroke_miterlimit(Tvg_Paint* paint, float miterlimit); + + +/*! +* \brief The function gets the stroke miterlimit. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[out] miterlimit The stroke miterlimit. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid pointer passed as an argument. +* +* \since 0.11 +*/ +TVG_API Tvg_Result tvg_shape_get_stroke_miterlimit(const Tvg_Paint* paint, float* miterlimit); + + +/*! +* \brief Sets the shape's solid color. +* +* The parts of the shape defined as inner are colored. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] r The red color channel value in the range [0 ~ 255]. The default value is 0. +* \param[in] g The green color channel value in the range [0 ~ 255]. The default value is 0. +* \param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0. +* \param[in] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. The default value is 0. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* +* \note Either a solid color or a gradient fill is applied, depending on what was set as last. +* \see tvg_shape_set_fill_rule() +*/ +TVG_API Tvg_Result tvg_shape_set_fill_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a); + + +/*! +* \brief Gets the shape's solid color. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[out] r The red color channel value in the range [0 ~ 255]. The default value is 0. +* \param[out] g The green color channel value in the range [0 ~ 255]. The default value is 0. +* \param[out] b The blue color channel value in the range [0 ~ 255]. The default value is 0. +* \param[out] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. The default value is 0. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +*/ +TVG_API Tvg_Result tvg_shape_get_fill_color(const Tvg_Paint* paint, uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a); + + +/*! +* \brief Sets the shape's fill rule. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] rule The fill rule value. The default value is @c TVG_FILL_RULE_WINDING. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +*/ +TVG_API Tvg_Result tvg_shape_set_fill_rule(Tvg_Paint* paint, Tvg_Fill_Rule rule); + + +/*! +* \brief Gets the shape's fill rule. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[out] rule shape's fill rule +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid pointer passed as an argument. +*/ +TVG_API Tvg_Result tvg_shape_get_fill_rule(const Tvg_Paint* paint, Tvg_Fill_Rule* rule); + + +/*! +* \brief Sets the rendering order of the stroke and the fill. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] strokeFirst If @c true the stroke is rendered before the fill, otherwise the stroke is rendered as the second one (the default option). +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with a memory allocation. +* +* \since 0.10 +*/ +TVG_API Tvg_Result tvg_shape_set_paint_order(Tvg_Paint* paint, bool strokeFirst); + + +/*! +* \brief Sets the linear gradient fill for all of the figures from the path. +* +* The parts of the shape defined as inner are filled. +* +* \code +* Tvg_Gradient* grad = tvg_linear_gradient_new(); +* tvg_linear_gradient_set(grad, 700, 700, 800, 800); +* Tvg_Color_Stop color_stops[4] = +* { +* {0.0 , 0, 0, 0, 255}, +* {0.25, 255, 0, 0, 255}, +* {0.5 , 0, 255, 0, 255}, +* {1.0 , 0, 0, 255, 255} +* }; +* tvg_gradient_set_color_stops(grad, color_stops, 4); +* tvg_shape_set_linear_gradient(shape, grad); +* \endcode +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] grad The linear gradient fill. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_MEMORY_CORRUPTION An invalid Tvg_Gradient pointer. +* +* \note Either a solid color or a gradient fill is applied, depending on what was set as last. +* \see tvg_shape_set_fill_rule() +*/ +TVG_API Tvg_Result tvg_shape_set_linear_gradient(Tvg_Paint* paint, Tvg_Gradient* grad); + + +/*! +* \brief Sets the radial gradient fill for all of the figures from the path. +* +* The parts of the shape defined as inner are filled. +* +* \code +* Tvg_Gradient* grad = tvg_radial_gradient_new(); +* tvg_radial_gradient_set(grad, 550, 550, 50); +* Tvg_Color_Stop color_stops[4] = +* { +* {0.0 , 0, 0, 0, 255}, +* {0.25, 255, 0, 0, 255}, +* {0.5 , 0, 255, 0, 255}, +* {1.0 , 0, 0, 255, 255} +* }; +* tvg_gradient_set_color_stops(grad, color_stops, 4); +* tvg_shape_set_radial_gradient(shape, grad); +* \endcode +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[in] grad The radial gradient fill. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_MEMORY_CORRUPTION An invalid Tvg_Gradient pointer. +* +* \note Either a solid color or a gradient fill is applied, depending on what was set as last. +* \see tvg_shape_set_fill_rule() +*/ +TVG_API Tvg_Result tvg_shape_set_radial_gradient(Tvg_Paint* paint, Tvg_Gradient* grad); + + +/*! +* \brief Gets the gradient fill of the shape. +* +* The function does not allocate any data. +* +* \param[in] paint A Tvg_Paint pointer to the shape object. +* \param[out] grad The gradient fill. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid pointer passed as an argument. +*/ +TVG_API Tvg_Result tvg_shape_get_gradient(const Tvg_Paint* paint, Tvg_Gradient** grad); + + +/** \} */ // end defgroup ThorVGCapi_Shape + + +/** +* \defgroup ThorVGCapi_Gradient Gradient +* \brief A module managing the gradient fill of objects. +* +* The module enables to set and to get the gradient colors and their arrangement inside the gradient bounds, +* to specify the gradient bounds and the gradient behavior in case the area defined by the gradient bounds +* is smaller than the area to be filled. +* +* \{ +*/ + +/************************************************************************/ +/* Gradient API */ +/************************************************************************/ +/*! +* \brief Creates a new linear gradient object. +* +* \code +* Tvg_Paint* shape = tvg_shape_new(); +* tvg_shape_append_rect(shape, 700, 700, 100, 100, 20, 20); +* Tvg_Gradient* grad = tvg_linear_gradient_new(); +* tvg_linear_gradient_set(grad, 700, 700, 800, 800); +* Tvg_Color_Stop color_stops[2] = +* { +* {0.0, 0, 0, 0, 255}, +* {1.0, 0, 255, 0, 255}, +* }; +* tvg_gradient_set_color_stops(grad, color_stops, 2); +* tvg_shape_set_linear_gradient(shape, grad); +* \endcode +* +* \return A new linear gradient object. +*/ +TVG_API Tvg_Gradient* tvg_linear_gradient_new(); + + +/*! +* \brief Creates a new radial gradient object. +* +* \code +* Tvg_Paint* shape = tvg_shape_new(); +* tvg_shape_append_rect(shape, 700, 700, 100, 100, 20, 20); +* Tvg_Gradient* grad = tvg_radial_gradient_new(); +* tvg_radial_gradient_set(grad, 550, 550, 50); +* Tvg_Color_Stop color_stops[2] = +* { +* {0.0, 0, 0, 0, 255}, +* {1.0, 0, 255, 0, 255}, +* }; +* tvg_gradient_set_color_stops(grad, color_stops, 2); +* tvg_shape_set_radial_gradient(shape, grad); +* \endcode +* +* \return A new radial gradient object. +*/ +TVG_API Tvg_Gradient* tvg_radial_gradient_new(); + + +/*! +* \brief Sets the linear gradient bounds. +* +* The bounds of the linear gradient are defined as a surface constrained by two parallel lines crossing +* the given points (@p x1, @p y1) and (@p x2, @p y2), respectively. Both lines are perpendicular to the line linking +* (@p x1, @p y1) and (@p x2, @p y2). +* +* \param[in] grad The Tvg_Gradient object of which bounds are to be set. +* @param[in] x1 The horizontal coordinate of the first point used to determine the gradient bounds. +* @param[in] y1 The vertical coordinate of the first point used to determine the gradient bounds. +* @param[in] x2 The horizontal coordinate of the second point used to determine the gradient bounds. +* @param[in] y2 The vertical coordinate of the second point used to determine the gradient bounds. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Gradient pointer. +* +* \note In case the first and the second points are equal, an object filled with such a gradient fill is not rendered. +*/ +TVG_API Tvg_Result tvg_linear_gradient_set(Tvg_Gradient* grad, float x1, float y1, float x2, float y2); + + +/*! +* \brief Gets the linear gradient bounds. +* +* The bounds of the linear gradient are defined as a surface constrained by two parallel lines crossing +* the given points (@p x1, @p y1) and (@p x2, @p y2), respectively. Both lines are perpendicular to the line linking +* (@p x1, @p y1) and (@p x2, @p y2). +* +* \param[in] grad The Tvg_Gradient object of which to get the bounds. +* \param[out] x1 The horizontal coordinate of the first point used to determine the gradient bounds. +* \param[out] y1 The vertical coordinate of the first point used to determine the gradient bounds. +* \param[out] x2 The horizontal coordinate of the second point used to determine the gradient bounds. +* \param[out] y2 The vertical coordinate of the second point used to determine the gradient bounds. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Gradient pointer. +*/ +TVG_API Tvg_Result tvg_linear_gradient_get(Tvg_Gradient* grad, float* x1, float* y1, float* x2, float* y2); + + +/*! +* \brief Sets the radial gradient bounds. +* +* The radial gradient bounds are defined as a circle centered in a given point (@p cx, @p cy) of a given radius. +* +* \param[in] grad The Tvg_Gradient object of which bounds are to be set. +* \param[in] cx The horizontal coordinate of the center of the bounding circle. +* \param[in] cy The vertical coordinate of the center of the bounding circle. +* \param[in] radius The radius of the bounding circle. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Gradient pointer or the @p radius value less than zero. +*/ +TVG_API Tvg_Result tvg_radial_gradient_set(Tvg_Gradient* grad, float cx, float cy, float radius); + + +/*! +* \brief The function gets radial gradient center point ant radius +* +* \param[in] grad The Tvg_Gradient object of which bounds are to be set. +* \param[out] cx The horizontal coordinate of the center of the bounding circle. +* \param[out] cy The vertical coordinate of the center of the bounding circle. +* \param[out] radius The radius of the bounding circle. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Gradient pointer. +*/ +TVG_API Tvg_Result tvg_radial_gradient_get(Tvg_Gradient* grad, float* cx, float* cy, float* radius); + + +/*! +* \brief Sets the parameters of the colors of the gradient and their position. +* +* \param[in] grad The Tvg_Gradient object of which the color information is to be set. +* \param[in] color_stop An array of Tvg_Color_Stop data structure. +* \param[in] cnt The size of the @p color_stop array equal to the colors number used in the gradient. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Gradient pointer. +*/ +TVG_API Tvg_Result tvg_gradient_set_color_stops(Tvg_Gradient* grad, const Tvg_Color_Stop* color_stop, uint32_t cnt); + + +/*! +* \brief Gets the parameters of the colors of the gradient, their position and number +* +* The function does not allocate any memory. +* +* \param[in] grad The Tvg_Gradient object of which to get the color information. +* \param[out] color_stop An array of Tvg_Color_Stop data structure. +* \param[out] cnt The size of the @p color_stop array equal to the colors number used in the gradient. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT A @c nullptr passed as the argument. +*/ +TVG_API Tvg_Result tvg_gradient_get_color_stops(const Tvg_Gradient* grad, const Tvg_Color_Stop** color_stop, uint32_t* cnt); + + +/*! +* \brief Sets the Tvg_Stroke_Fill value, which specifies how to fill the area outside the gradient bounds. +* +* \param[in] grad The Tvg_Gradient object. +* \param[in] spread The FillSpread value. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Gradient pointer. +*/ +TVG_API Tvg_Result tvg_gradient_set_spread(Tvg_Gradient* grad, const Tvg_Stroke_Fill spread); + + +/*! +* \brief Gets the FillSpread value of the gradient object. +* +* \param[in] grad The Tvg_Gradient object. +* \param[out] spread The FillSpread value. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT A @c nullptr passed as the argument. +*/ +TVG_API Tvg_Result tvg_gradient_get_spread(const Tvg_Gradient* grad, Tvg_Stroke_Fill* spread); + + +/*! +* \brief Sets the matrix of the affine transformation for the gradient object. +* +* The augmented matrix of the transformation is expected to be given. +* +* \param[in] grad The Tvg_Gradient object to be transformed. +* \param[in] m The 3x3 augmented matrix. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT A @c nullptr is passed as the argument. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with a memory allocation. +*/ +TVG_API Tvg_Result tvg_gradient_set_transform(Tvg_Gradient* grad, const Tvg_Matrix* m); + + +/*! +* \brief Gets the matrix of the affine transformation of the gradient object. +* +* In case no transformation was applied, the identity matrix is set. +* +* \param[in] grad The Tvg_Gradient object of which to get the transformation matrix. +* \param[out] m The 3x3 augmented matrix. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT A @c nullptr is passed as the argument. +*/ +TVG_API Tvg_Result tvg_gradient_get_transform(const Tvg_Gradient* grad, Tvg_Matrix* m); + +/** +* \brief Gets the unique id value of the gradient instance indicating the instance type. +* +* \param[in] grad The Tvg_Gradient object of which to get the identifier value. +* \param[out] identifier The unique identifier of the gradient instance type. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT In case a @c nullptr is passed as the argument. +* +* \since 0.9 +*/ +TVG_API Tvg_Result tvg_gradient_get_identifier(const Tvg_Gradient* grad, Tvg_Identifier* identifier); + + +/*! +* \brief Duplicates the given Tvg_Gradient object. +* +* Creates a new object and sets its all properties as in the original object. +* +* \param[in] grad The Tvg_Gradient object to be copied. +* +* \return A copied Tvg_Gradient object if succeed, @c nullptr otherwise. +*/ +TVG_API Tvg_Gradient* tvg_gradient_duplicate(Tvg_Gradient* grad); + + +/*! +* \brief Deletes the given gradient object. +* +* \param[in] grad The gradient object to be deleted. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Gradient pointer. +*/ +TVG_API Tvg_Result tvg_gradient_del(Tvg_Gradient* grad); + + +/** \} */ // end defgroup ThorVGCapi_Gradient + + +/** +* \defgroup ThorVGCapi_Picture Picture +* +* \brief A module enabling to create and to load an image in one of the supported formats: svg, png, jpg, lottie and raw. +* +* +* \{ +*/ + +/************************************************************************/ +/* Picture API */ +/************************************************************************/ +/*! +* \brief Creates a new picture object. +* +* \return A new picture object. +*/ +TVG_API Tvg_Paint* tvg_picture_new(); + + +/*! +* \brief Loads a picture data directly from a file. +* +* \param[in] paint A Tvg_Paint pointer to the picture object. +* \param[in] path The absolute path to the image file. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer or an empty @p path. +* \retval TVG_RESULT_NOT_SUPPORTED A file with an unknown extension. +* \retval TVG_RESULT_UNKNOWN An error at a later stage. +*/ +TVG_API Tvg_Result tvg_picture_load(Tvg_Paint* paint, const char* path); + + +/*! +* \brief Loads a picture data from a memory block of a given size. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer or no data are provided or the @p width or @p height value is zero or less. +* \retval TVG_RESULT_FAILED_ALLOCATION A problem with memory allocation occurs. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION An error occurs at a later stage. +* +* \since 0.9 +*/ +TVG_API Tvg_Result tvg_picture_load_raw(Tvg_Paint* paint, uint32_t *data, uint32_t w, uint32_t h, bool copy); + + +/*! +* \brief Loads a picture data from a memory block of a given size. +* +* \param[in] paint A Tvg_Paint pointer to the picture object. +* \param[in] data A pointer to a memory location where the content of the picture file is stored. +* \param[in] size The size in bytes of the memory occupied by the @p data. +* \param[in] mimetype Mimetype or extension of data such as "jpg", "jpeg", "svg", "svg+xml", "lottie", "png", etc. In case an empty string or an unknown type is provided, the loaders will be tried one by one. +* \param[in] copy If @c true the data are copied into the engine local buffer, otherwise they are not. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT In case a @c nullptr is passed as the argument or the @p size is zero or less. +* \retval TVG_RESULT_NOT_SUPPORTED A file with an unknown extension. +* \retval TVG_RESULT_UNKNOWN An error at a later stage. +* +* \warning: It's the user responsibility to release the @p data memory if the @p copy is @c true. +*/ +TVG_API Tvg_Result tvg_picture_load_data(Tvg_Paint* paint, const char *data, uint32_t size, const char *mimetype, bool copy); + + +/*! +* \brief Resizes the picture content to the given width and height. +* +* The picture content is resized while keeping the default size aspect ratio. +* The scaling factor is established for each of dimensions and the smaller value is applied to both of them. +* +* \param[in] paint A Tvg_Paint pointer to the picture object. +* \param[in] w A new width of the image in pixels. +* \param[in] h A new height of the image in pixels. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION An internal error. +*/ +TVG_API Tvg_Result tvg_picture_set_size(Tvg_Paint* paint, float w, float h); + + +/*! +* \brief Gets the size of the loaded picture. +* +* \param[in] paint A Tvg_Paint pointer to the picture object. +* \param[out] w A width of the image in pixels. +* \param[out] h A height of the image in pixels. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +*/ +TVG_API Tvg_Result tvg_picture_get_size(const Tvg_Paint* paint, float* w, float* h); + + +/** \} */ // end defgroup ThorVGCapi_Picture + + +/** +* \defgroup ThorVGCapi_Scene Scene +* \brief A module managing the multiple paints as one group paint. +* +* As a group, scene can be transformed, translucent, composited with other target paints, +* its children will be affected by the scene world. +* +* \{ +*/ + +/************************************************************************/ +/* Scene API */ +/************************************************************************/ +/*! +* \brief Creates a new scene object. +* +* A scene object is used to group many paints into one object, which can be manipulated using TVG APIs. +* +* \return A new scene object. +*/ +TVG_API Tvg_Paint* tvg_scene_new(); + + +/*! +* \brief Sets the size of the container, where all the paints pushed into the scene are stored. +* +* If the number of objects pushed into the scene is known in advance, calling the function +* prevents multiple memory reallocation, thus improving the performance. +* +* \param[in] scene A Tvg_Paint pointer to the scene object. +* \param[in] size The number of objects for which the memory is to be reserved. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with a memory allocation. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. +*/ +TVG_DEPRECATED TVG_API Tvg_Result tvg_scene_reserve(Tvg_Paint* scene, uint32_t size); + + +/*! +* \brief Passes drawing elements to the scene using Tvg_Paint objects. +* +* Only the paints pushed into the scene will be the drawn targets. +* The paints are retained by the scene until the tvg_scene_clear() is called. +* If you know the number of pushed objects in advance, please call tvg_scene_reserve(). +* +* \param[in] scene A Tvg_Paint pointer to the scene object. +* \param[in] paint A graphical object to be drawn. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT A @c nullptr passed as the argument. +* \retval TVG_RESULT_MEMORY_CORRUPTION An internal error. +* +* \note The rendering order of the paints is the same as the order as they were pushed. Consider sorting the paints before pushing them if you intend to use layering. +*/ +TVG_API Tvg_Result tvg_scene_push(Tvg_Paint* scene, Tvg_Paint* paint); + + +/*! +* \brief Clears a Tvg_Scene objects from pushed paints. +* +* Tvg_Paint objects stored in the scene are released if @p free is set to @c true, otherwise the memory is not deallocated and +* all paints should be released manually in order to avoid memory leaks. +* +* \param[in] scene The Tvg_Scene object to be cleared. +* \param[in] free If @c true the memory occupied by paints is deallocated, otherwise it is not. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Canvas pointer. +* +* \warning Please use the @p free argument only when you know how it works, otherwise it's not recommended. +*/ +TVG_API Tvg_Result tvg_scene_clear(Tvg_Paint* scene, bool free); + +/** \} */ // end defgroup ThorVGCapi_Scene + + +/** +* \defgroup ThorVGCapi_Saver Saver +* \brief A module for exporting a paint object into a specified file. +* +* The module enables to save the composed scene and/or image from a paint object. +* Once it's successfully exported to a file, it can be recreated using the Picture module. +* +* \{ +*/ + +/************************************************************************/ +/* Saver API */ +/************************************************************************/ +/*! +* \brief Creates a new Tvg_Saver object. +* +* \return A new Tvg_Saver object. +*/ +TVG_API Tvg_Saver* tvg_saver_new(); + + +/*! +* \brief Exports the given @p paint data to the given @p path +* +* If the saver module supports any compression mechanism, it will optimize the data size. +* This might affect the encoding/decoding time in some cases. You can turn off the compression +* if you wish to optimize for speed. +* +* \param[in] saver The Tvg_Saver object connected with the saving task. +* \param[in] paint The paint to be saved with all its associated properties. +* \param[in] path A path to the file, in which the paint data is to be saved. +* \param[in] compress If @c true then compress data if possible. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT A @c nullptr passed as the argument. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION Currently saving other resources. +* \retval TVG_RESULT_NOT_SUPPORTED Trying to save a file with an unknown extension or in an unsupported format. +* \retval TVG_RESULT_MEMORY_CORRUPTION An internal error. +* \retval TVG_RESULT_UNKNOWN An empty paint is to be saved. +* +* \note Saving can be asynchronous if the assigned thread number is greater than zero. To guarantee the saving is done, call tvg_saver_sync() afterwards. +* \see tvg_saver_sync() +*/ +TVG_API Tvg_Result tvg_saver_save(Tvg_Saver* saver, Tvg_Paint* paint, const char* path, bool compress); + + +/*! +* \brief Guarantees that the saving task is finished. +* +* The behavior of the Saver module works on a sync/async basis, depending on the threading setting of the Initializer. +* Thus, if you wish to have a benefit of it, you must call tvg_saver_sync() after the tvg_saver_save() in the proper delayed time. +* Otherwise, you can call tvg_saver_sync() immediately. +* +* \param[in] saver The Tvg_Saver object connected with the saving task. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT A @c nullptr passed as the argument. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION No saving task is running. +* +* \note The asynchronous tasking is dependent on the Saver module implementation. +* \see tvg_saver_save() +*/ +TVG_API Tvg_Result tvg_saver_sync(Tvg_Saver* saver); + + +/*! +* \brief Deletes the given Tvg_Saver object. +* +* \param[in] saver The Tvg_Saver object to be deleted. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Saver pointer. +*/ +TVG_API Tvg_Result tvg_saver_del(Tvg_Saver* saver); + + +/** \} */ // end defgroup ThorVGCapi_Saver + + +/** +* \defgroup ThorVGCapi_Animation Animation +* \brief A module for manipulation of animatable images. +* +* The module supports the display and control of animation frames. +* +* \{ +*/ + +/************************************************************************/ +/* Animation API */ +/************************************************************************/ + +/*! +* \brief Creates a new Animation object. (BETA_API) +* +* \return Tvg_Animation A new Tvg_Animation object. +*/ +TVG_API Tvg_Animation* tvg_animation_new(); + + +/*! +* \brief Specifies the current frame in the animation. (BETA_API) +* +* \param[in] animation A Tvg_Animation pointer to the animation object. +* \param[in] no The index of the animation frame to be displayed. The index should be less than the tvg_animatio_total_frame(). +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Animation pointer. +* \retval TVG_RESULT_INSUFFICIENT_CONDITION No animatable data loaded from the Picture. +* \retval TVG_RESULT_NOT_SUPPORTED The picture data does not support animations. +* +* \see tvg_animation_get_total_frame() +*/ +TVG_API Tvg_Result tvg_animation_set_frame(Tvg_Animation* animation, uint32_t no); + + +/*! +* \brief Retrieves a picture instance associated with this animation instance. (BETA_API) +* +* This function provides access to the picture instance that can be used to load animation formats, such as Lottie(json). +* After setting up the picture, it can be pushed to the designated canvas, enabling control over animation frames +* with this Animation instance. +* +* \param[in] animation A Tvg_Animation pointer to the animation object. +* +* \return A picture instance that is tied to this animation. +* +* \warning The picture instance is owned by Animation. It should not be deleted manually. +*/ +TVG_API Tvg_Paint* tvg_animation_get_picture(Tvg_Animation* animation); + + +/*! +* \brief Retrieves the current frame number of the animation. (BETA_API) +* +* \param[in] animation A Tvg_Animation pointer to the animation object. +* \param[in] no The current frame number of the animation, between 0 and totalFrame() - 1. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Animation pointer or @p no +* +* \see tvg_animation_get_total_frame() +* \see tvg_animation_set_frame() +*/ +TVG_API Tvg_Result tvg_animation_get_frame(Tvg_Animation* animation, uint32_t* no); + + +/*! +* \brief Retrieves the total number of frames in the animation. (BETA_API) +* +* \param[in] animation A Tvg_Animation pointer to the animation object. +* \param[in] cnt The total number of frames in the animation. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Animation pointer or @p cnt. +* +* \note Frame numbering starts from 0. +* \note If the Picture is not properly configured, this function will return 0. +*/ +TVG_API Tvg_Result tvg_animation_get_total_frame(Tvg_Animation* animation, uint32_t* cnt); + + +/*! +* \brief Retrieves the duration of the animation in seconds. (BETA_API) +* +* \param[in] animation A Tvg_Animation pointer to the animation object. +* \param[in] duration The duration of the animation in seconds. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Animation pointer or @p duration. +* +* \note If the Picture is not properly configured, this function will return 0. +*/ +TVG_API Tvg_Result tvg_animation_get_duration(Tvg_Animation* animation, float* duration); + + +/*! +* \brief Deletes the given Tvg_Animation object. +* +* \param[in] animation The Tvg_Animation object to be deleted. +* +* \return Tvg_Result enumeration. +* \retval TVG_RESULT_SUCCESS Succeed. +* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Animation pointer. +*/ +TVG_API Tvg_Result tvg_animation_del(Tvg_Animation* animation); + + +/** \} */ // end defgroup ThorVG_CAPI + + +#ifdef __cplusplus +} +#endif + +#endif //_THORVG_CAPI_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgAnimation.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgAnimation.cpp new file mode 100644 index 000000000..ae5e8f94e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgAnimation.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgCommon.h" +#include "tvgFrameModule.h" +#include "tvgPaint.h" +#include "tvgPicture.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +struct Animation::Impl +{ + Picture* picture = nullptr; + + Impl() + { + picture = Picture::gen().release(); + PP(picture)->ref(); + } + + ~Impl() + { + if (PP(picture)->unref() == 0) { + delete(picture); + } + } +}; + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +Animation::~Animation() +{ + delete(pImpl); +} + + +Animation::Animation() : pImpl(new Impl) +{ +} + + +Result Animation::frame(uint32_t no) noexcept +{ + auto loader = pImpl->picture->pImpl->loader.get(); + + if (!loader) return Result::InsufficientCondition; + if (!loader->animatable()) return Result::NonSupport; + + if (static_cast(loader)->frame(no)) return Result::Success; + return Result::InsufficientCondition; +} + + +Picture* Animation::picture() const noexcept +{ + return pImpl->picture; +} + + +uint32_t Animation::curFrame() const noexcept +{ + auto loader = pImpl->picture->pImpl->loader.get(); + + if (!loader) return 0; + if (!loader->animatable()) return 0; + + return static_cast(loader)->curFrame(); +} + + +uint32_t Animation::totalFrame() const noexcept +{ + auto loader = pImpl->picture->pImpl->loader.get(); + + if (!loader) return 0; + if (!loader->animatable()) return 0; + + return static_cast(loader)->totalFrame(); +} + + +float Animation::duration() const noexcept +{ + auto loader = pImpl->picture->pImpl->loader.get(); + + if (!loader) return 0; + if (!loader->animatable()) return 0; + + return static_cast(loader)->duration(); +} + + +unique_ptr Animation::gen() noexcept +{ + return unique_ptr(new Animation); +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgArray.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgArray.h new file mode 100644 index 000000000..41accc13b --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgArray.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_ARRAY_H_ +#define _TVG_ARRAY_H_ + +#include +#include + +namespace tvg +{ + +template +struct Array +{ + T* data = nullptr; + uint32_t count = 0; + uint32_t reserved = 0; + + Array(){} + + Array(const Array& rhs) + { + reset(); + *this = rhs; + } + + void push(T element) + { + if (count + 1 > reserved) { + reserved = count + (count + 2) / 2; + data = static_cast(realloc(data, sizeof(T) * reserved)); + } + data[count++] = element; + } + + void push(Array& rhs) + { + grow(rhs.count); + memcpy(data + count, rhs.data, rhs.count * sizeof(T)); + count += rhs.count; + } + + bool reserve(uint32_t size) + { + if (size > reserved) { + reserved = size; + data = static_cast(realloc(data, sizeof(T) * reserved)); + } + return true; + } + + bool grow(uint32_t size) + { + return reserve(count + size); + } + + const T& operator[](size_t idx) const + { + return data[idx]; + } + + T& operator[](size_t idx) + { + return data[idx]; + } + + T* end() + { + return data + count; + } + + const T* end() const + { + return data + count; + } + + const T& last() const + { + return data[count - 1]; + } + + const T& first() const + { + return data[0]; + } + + T& last() + { + return data[count - 1]; + } + + T& first() + { + return data[0]; + } + + void pop() + { + if (count > 0) --count; + } + + void reset() + { + free(data); + data = nullptr; + count = reserved = 0; + } + + void clear() + { + count = 0; + } + + bool empty() const + { + return count == 0; + } + + template + void sort() + { + qsort(data, 0, static_cast(count) - 1); + } + + void operator=(const Array& rhs) + { + reserve(rhs.count); + if (rhs.count > 0) memcpy(data, rhs.data, sizeof(T) * rhs.count); + count = rhs.count; + } + + ~Array() + { + free(data); + } + +private: + template + void qsort(T* arr, int32_t low, int32_t high) + { + if (low < high) { + int32_t i = low; + int32_t j = high; + T tmp = arr[low]; + while (i < j) { + while (i < j && !COMPARE{}(arr[j], tmp)) --j; + if (i < j) { + arr[i] = arr[j]; + ++i; + } + while (i < j && COMPARE{}(arr[i], tmp)) ++i; + if (i < j) { + arr[j] = arr[i]; + --j; + } + } + arr[i] = tmp; + qsort(arr, low, i - 1); + qsort(arr, i + 1, high); + } + } +}; + +} + +#endif //_TVG_ARRAY_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgBezier.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgBezier.cpp new file mode 100644 index 000000000..e00fc1855 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgBezier.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgMath.h" +#include "tvgBezier.h" + +#define BEZIER_EPSILON 1e-4f + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static float _lineLength(const Point& pt1, const Point& pt2) +{ + /* approximate sqrt(x*x + y*y) using alpha max plus beta min algorithm. + With alpha = 1, beta = 3/8, giving results with the largest error less + than 7% compared to the exact value. */ + Point diff = {pt2.x - pt1.x, pt2.y - pt1.y}; + if (diff.x < 0) diff.x = -diff.x; + if (diff.y < 0) diff.y = -diff.y; + return (diff.x > diff.y) ? (diff.x + diff.y * 0.375f) : (diff.y + diff.x * 0.375f); +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +namespace tvg +{ + +void bezSplit(const Bezier&cur, Bezier& left, Bezier& right) +{ + auto c = (cur.ctrl1.x + cur.ctrl2.x) * 0.5f; + left.ctrl1.x = (cur.start.x + cur.ctrl1.x) * 0.5f; + right.ctrl2.x = (cur.ctrl2.x + cur.end.x) * 0.5f; + left.start.x = cur.start.x; + right.end.x = cur.end.x; + left.ctrl2.x = (left.ctrl1.x + c) * 0.5f; + right.ctrl1.x = (right.ctrl2.x + c) * 0.5f; + left.end.x = right.start.x = (left.ctrl2.x + right.ctrl1.x) * 0.5f; + + c = (cur.ctrl1.y + cur.ctrl2.y) * 0.5f; + left.ctrl1.y = (cur.start.y + cur.ctrl1.y) * 0.5f; + right.ctrl2.y = (cur.ctrl2.y + cur.end.y) * 0.5f; + left.start.y = cur.start.y; + right.end.y = cur.end.y; + left.ctrl2.y = (left.ctrl1.y + c) * 0.5f; + right.ctrl1.y = (right.ctrl2.y + c) * 0.5f; + left.end.y = right.start.y = (left.ctrl2.y + right.ctrl1.y) * 0.5f; +} + + +float bezLength(const Bezier& cur) +{ + Bezier left, right; + auto len = _lineLength(cur.start, cur.ctrl1) + _lineLength(cur.ctrl1, cur.ctrl2) + _lineLength(cur.ctrl2, cur.end); + auto chord = _lineLength(cur.start, cur.end); + + if (fabsf(len - chord) > BEZIER_EPSILON) { + bezSplit(cur, left, right); + return bezLength(left) + bezLength(right); + } + return len; +} + + +void bezSplitLeft(Bezier& cur, float at, Bezier& left) +{ + left.start = cur.start; + + left.ctrl1.x = cur.start.x + at * (cur.ctrl1.x - cur.start.x); + left.ctrl1.y = cur.start.y + at * (cur.ctrl1.y - cur.start.y); + + left.ctrl2.x = cur.ctrl1.x + at * (cur.ctrl2.x - cur.ctrl1.x); //temporary holding spot + left.ctrl2.y = cur.ctrl1.y + at * (cur.ctrl2.y - cur.ctrl1.y); //temporary holding spot + + cur.ctrl2.x = cur.ctrl2.x + at * (cur.end.x - cur.ctrl2.x); + cur.ctrl2.y = cur.ctrl2.y + at * (cur.end.y - cur.ctrl2.y); + + cur.ctrl1.x = left.ctrl2.x + at * (cur.ctrl2.x - left.ctrl2.x); + cur.ctrl1.y = left.ctrl2.y + at * (cur.ctrl2.y - left.ctrl2.y); + + left.ctrl2.x = left.ctrl1.x + at * (left.ctrl2.x - left.ctrl1.x); + left.ctrl2.y = left.ctrl1.y + at * (left.ctrl2.y - left.ctrl1.y); + + left.end.x = cur.start.x = left.ctrl2.x + at * (cur.ctrl1.x - left.ctrl2.x); + left.end.y = cur.start.y = left.ctrl2.y + at * (cur.ctrl1.y - left.ctrl2.y); +} + + +float bezAt(const Bezier& bz, float at, float length) +{ + auto biggest = 1.0f; + auto smallest = 0.0f; + auto t = 0.5f; + + //just in case to prevent an infinite loop + if (at <= 0) return 0.0f; + if (at >= length) return 1.0f; + + while (true) { + auto right = bz; + Bezier left; + bezSplitLeft(right, t, left); + length = bezLength(left); + if (fabsf(length - at) < BEZIER_EPSILON || fabsf(smallest - biggest) < BEZIER_EPSILON) { + break; + } + if (length < at) { + smallest = t; + t = (t + biggest) * 0.5f; + } else { + biggest = t; + t = (smallest + t) * 0.5f; + } + } + return t; +} + + +void bezSplitAt(const Bezier& cur, float at, Bezier& left, Bezier& right) +{ + right = cur; + auto t = bezAt(right, at, bezLength(right)); + bezSplitLeft(right, t, left); +} + + +Point bezPointAt(const Bezier& bz, float t) +{ + Point cur; + auto it = 1.0f - t; + + auto ax = bz.start.x * it + bz.ctrl1.x * t; + auto bx = bz.ctrl1.x * it + bz.ctrl2.x * t; + auto cx = bz.ctrl2.x * it + bz.end.x * t; + ax = ax * it + bx * t; + bx = bx * it + cx * t; + cur.x = ax * it + bx * t; + + float ay = bz.start.y * it + bz.ctrl1.y * t; + float by = bz.ctrl1.y * it + bz.ctrl2.y * t; + float cy = bz.ctrl2.y * it + bz.end.y * t; + ay = ay * it + by * t; + by = by * it + cy * t; + cur.y = ay * it + by * t; + + return cur; +} + + +float bezAngleAt(const Bezier& bz, float t) +{ + if (t < 0 || t > 1) return 0; + + //derivate + // p'(t) = 3 * (-(1-2t+t^2) * p0 + (1 - 4 * t + 3 * t^2) * p1 + (2 * t - 3 * + // t^2) * p2 + t^2 * p3) + float mt = 1.0f - t; + float d = t * t; + float a = -mt * mt; + float b = 1 - 4 * t + 3 * d; + float c = 2 * t - 3 * d; + + Point pt ={a * bz.start.x + b * bz.ctrl1.x + c * bz.ctrl2.x + d * bz.end.x, a * bz.start.y + b * bz.ctrl1.y + c * bz.ctrl2.y + d * bz.end.y}; + pt.x *= 3; + pt.y *= 3; + + return atan2(pt.x, pt.y) * 180.0f / 3.141592f; +} + + +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgBezier.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgBezier.h new file mode 100644 index 000000000..24f70f336 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgBezier.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_BEZIER_H_ +#define _TVG_BEZIER_H_ + +#include "tvgCommon.h" + +namespace tvg +{ + +struct Bezier +{ + Point start; + Point ctrl1; + Point ctrl2; + Point end; +}; + +void bezSplit(const Bezier&cur, Bezier& left, Bezier& right); +float bezLength(const Bezier& cur); +void bezSplitLeft(Bezier& cur, float at, Bezier& left); +float bezAt(const Bezier& bz, float at, float length); +void bezSplitAt(const Bezier& cur, float at, Bezier& left, Bezier& right); +Point bezPointAt(const Bezier& bz, float t); +float bezAngleAt(const Bezier& bz, float t); + +} + +#endif //_TVG_BEZIER_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCanvas.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCanvas.cpp new file mode 100644 index 000000000..4da0e5e12 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCanvas.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgCanvas.h" + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +Canvas::Canvas(RenderMethod *pRenderer):pImpl(new Impl(pRenderer)) +{ +} + + +Canvas::~Canvas() +{ + delete(pImpl); +} + + +Result Canvas::reserve(TVG_UNUSED uint32_t n) noexcept +{ + return Result::NonSupport; +} + + +list& Canvas::paints() noexcept +{ + return pImpl->paints; +} + + +Result Canvas::push(unique_ptr paint) noexcept +{ + return pImpl->push(std::move(paint)); +} + + +Result Canvas::clear(bool free) noexcept +{ + return pImpl->clear(free); +} + + +Result Canvas::draw() noexcept +{ + TVGLOG("COMMON", "Draw S. -------------------------------- Canvas(%p)", this); + auto ret = pImpl->draw(); + TVGLOG("COMMON", "Draw E. -------------------------------- Canvas(%p)", this); + + return ret; +} + + +Result Canvas::update(Paint* paint) noexcept +{ + TVGLOG("COMMON", "Update S. ------------------------------ Canvas(%p)", this); + auto ret = pImpl->update(paint, false); + TVGLOG("COMMON", "Update E. ------------------------------ Canvas(%p)", this); + + return ret; +} + + +Result Canvas::sync() noexcept +{ + return pImpl->sync(); +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCanvas.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCanvas.h new file mode 100644 index 000000000..852f7db43 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCanvas.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_CANVAS_IMPL_H_ +#define _TVG_CANVAS_IMPL_H_ + +#include "tvgPaint.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +struct Canvas::Impl +{ + list paints; + RenderMethod* renderer; + bool refresh = false; //if all paints should be updated by force. + bool drawing = false; //on drawing condition? + + Impl(RenderMethod* pRenderer):renderer(pRenderer) + { + } + + ~Impl() + { + clear(true); + delete(renderer); + } + + Result push(unique_ptr paint) + { + //You can not push paints during rendering. + if (drawing) return Result::InsufficientCondition; + + auto p = paint.release(); + if (!p) return Result::MemoryCorruption; + PP(p)->ref(); + paints.push_back(p); + + return update(p, true); + } + + Result clear(bool free) + { + //Clear render target before drawing + if (!renderer || !renderer->clear()) return Result::InsufficientCondition; + + //Free paints + if (free) { + for (auto paint : paints) { + P(paint)->unref(); + if (paint->pImpl->dispose(*renderer) && P(paint)->refCnt == 0) { + delete(paint); + } + } + paints.clear(); + } + drawing = false; + + return Result::Success; + } + + void needRefresh() + { + refresh = true; + } + + Result update(Paint* paint, bool force) + { + if (paints.empty() || drawing || !renderer) return Result::InsufficientCondition; + + Array clips; + auto flag = RenderUpdateFlag::None; + if (refresh || force) flag = RenderUpdateFlag::All; + + //Update single paint node + if (paint) { + //Optimize Me: Can we skip the searching? + for (auto paint2 : paints) { + if (paint2 == paint) { + paint->pImpl->update(*renderer, nullptr, clips, 255, flag); + return Result::Success; + } + } + return Result::InvalidArguments; + //Update all retained paint nodes + } else { + for (auto paint : paints) { + paint->pImpl->update(*renderer, nullptr, clips, 255, flag); + } + } + + refresh = false; + + return Result::Success; + } + + Result draw() + { + if (drawing || paints.empty() || !renderer || !renderer->preRender()) return Result::InsufficientCondition; + + bool rendered = false; + for (auto paint : paints) { + if (paint->pImpl->render(*renderer)) rendered = true; + } + + if (!rendered || !renderer->postRender()) return Result::InsufficientCondition; + + drawing = true; + + return Result::Success; + } + + Result sync() + { + if (!drawing) return Result::InsufficientCondition; + + if (renderer->sync()) { + drawing = false; + return Result::Success; + } + + return Result::InsufficientCondition; + } +}; + +#endif /* _TVG_CANVAS_IMPL_H_ */ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCapi.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCapi.cpp new file mode 100644 index 000000000..203a11d09 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCapi.cpp @@ -0,0 +1,784 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include +#include "thorvg.h" +#include "thorvg_capi.h" + +using namespace std; +using namespace tvg; + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/* Engine API */ +/************************************************************************/ + +TVG_API Tvg_Result tvg_engine_init(Tvg_Engine engine_method, unsigned threads) +{ + return (Tvg_Result) Initializer::init(CanvasEngine(engine_method), threads); +} + + +TVG_API Tvg_Result tvg_engine_term(Tvg_Engine engine_method) +{ + return (Tvg_Result) Initializer::term(CanvasEngine(engine_method)); +} + + +/************************************************************************/ +/* Canvas API */ +/************************************************************************/ + +TVG_API Tvg_Canvas* tvg_swcanvas_create() +{ + return (Tvg_Canvas*) SwCanvas::gen().release(); +} + + +TVG_API Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas) +{ + if (!canvas) return TVG_RESULT_INVALID_ARGUMENT; + delete(reinterpret_cast(canvas)); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_swcanvas_set_mempool(Tvg_Canvas* canvas, Tvg_Mempool_Policy policy) +{ + if (!canvas) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(canvas)->mempool(static_cast(policy)); +} + + +TVG_API Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Tvg_Colorspace cs) +{ + if (!canvas) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(canvas)->target(buffer, stride, w, h, static_cast(cs)); +} + + +TVG_API Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint) +{ + if (!canvas || !paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(canvas)->push(unique_ptr((Paint*)paint)); +} + + +TVG_API Tvg_Result tvg_canvas_reserve(Tvg_Canvas* canvas, uint32_t n) +{ + return TVG_RESULT_NOT_SUPPORTED; +} + + +TVG_API Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool free) +{ + if (!canvas) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(canvas)->clear(free); +} + + +TVG_API Tvg_Result tvg_canvas_update(Tvg_Canvas* canvas) +{ + if (!canvas) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(canvas)->update(nullptr); +} + + +TVG_API Tvg_Result tvg_canvas_update_paint(Tvg_Canvas* canvas, Tvg_Paint* paint) +{ + if (!canvas || !paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(canvas)->update((Paint*) paint); +} + + +TVG_API Tvg_Result tvg_canvas_draw(Tvg_Canvas* canvas) +{ + if (!canvas) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(canvas)->draw(); +} + + +TVG_API Tvg_Result tvg_canvas_sync(Tvg_Canvas* canvas) +{ + if (!canvas) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(canvas)->sync(); +} + + +/************************************************************************/ +/* Paint API */ +/************************************************************************/ + +TVG_API Tvg_Result tvg_paint_del(Tvg_Paint* paint) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + delete(reinterpret_cast(paint)); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_paint_scale(Tvg_Paint* paint, float factor) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->scale(factor); +} + + +TVG_API Tvg_Result tvg_paint_rotate(Tvg_Paint* paint, float degree) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->rotate(degree); +} + + +TVG_API Tvg_Result tvg_paint_translate(Tvg_Paint* paint, float x, float y) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->translate(x, y); +} + + +TVG_API Tvg_Result tvg_paint_set_transform(Tvg_Paint* paint, const Tvg_Matrix* m) +{ + if (!paint || !m) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->transform(*(reinterpret_cast(m))); +} + + +TVG_API Tvg_Result tvg_paint_get_transform(Tvg_Paint* paint, Tvg_Matrix* m) +{ + if (!paint || !m) return TVG_RESULT_INVALID_ARGUMENT; + *reinterpret_cast(m) = reinterpret_cast(paint)->transform(); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Paint* tvg_paint_duplicate(Tvg_Paint* paint) +{ + if (!paint) return nullptr; + return (Tvg_Paint*) reinterpret_cast(paint)->duplicate(); +} + + +TVG_API Tvg_Result tvg_paint_set_opacity(Tvg_Paint* paint, uint8_t opacity) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->opacity(opacity); +} + + +TVG_API Tvg_Result tvg_paint_get_opacity(const Tvg_Paint* paint, uint8_t* opacity) +{ + if (!paint || !opacity) return TVG_RESULT_INVALID_ARGUMENT; + *opacity = reinterpret_cast(paint)->opacity(); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_paint_get_bounds(const Tvg_Paint* paint, float* x, float* y, float* w, float* h, bool transformed) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->bounds(x, y, w, h, transformed); +} + + +TVG_API Tvg_Result tvg_paint_set_composite_method(Tvg_Paint* paint, Tvg_Paint* target, Tvg_Composite_Method method) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->composite(unique_ptr((Paint*)(target)), (CompositeMethod)method); +} + + +TVG_API Tvg_Result tvg_paint_get_composite_method(const Tvg_Paint* paint, const Tvg_Paint** target, Tvg_Composite_Method* method) +{ + if (!paint || !target || !method) return TVG_RESULT_INVALID_ARGUMENT; + *reinterpret_cast(method) = reinterpret_cast(paint)->composite(reinterpret_cast(target)); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_paint_set_blend_method(const Tvg_Paint* paint, Tvg_Blend_Method method) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->blend((BlendMethod)method); +} + + +TVG_API Tvg_Result tvg_paint_get_blend_method(const Tvg_Paint* paint, Tvg_Blend_Method* method) +{ + if (!paint || !method) return TVG_RESULT_INVALID_ARGUMENT; + *method = static_cast(reinterpret_cast(paint)->blend()); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_paint_get_identifier(const Tvg_Paint* paint, Tvg_Identifier* identifier) +{ + if (!paint || !identifier) return TVG_RESULT_INVALID_ARGUMENT; + *identifier = static_cast(reinterpret_cast(paint)->identifier()); + return TVG_RESULT_SUCCESS; +} + +/************************************************************************/ +/* Shape API */ +/************************************************************************/ + +TVG_API Tvg_Paint* tvg_shape_new() +{ + return (Tvg_Paint*) Shape::gen().release(); +} + + +TVG_API Tvg_Result tvg_shape_reset(Tvg_Paint* paint) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->reset(); +} + + +TVG_API Tvg_Result tvg_shape_move_to(Tvg_Paint* paint, float x, float y) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->moveTo(x, y); +} + + +TVG_API Tvg_Result tvg_shape_line_to(Tvg_Paint* paint, float x, float y) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->lineTo(x, y); +} + + +TVG_API Tvg_Result tvg_shape_cubic_to(Tvg_Paint* paint, float cx1, float cy1, float cx2, float cy2, float x, float y) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->cubicTo(cx1, cy1, cx2, cy2, x, y); +} + + +TVG_API Tvg_Result tvg_shape_close(Tvg_Paint* paint) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->close(); +} + + +TVG_API Tvg_Result tvg_shape_append_rect(Tvg_Paint* paint, float x, float y, float w, float h, float rx, float ry) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->appendRect(x, y, w, h, rx, ry); +} + + +TVG_API Tvg_Result tvg_shape_append_arc(Tvg_Paint* paint, float cx, float cy, float radius, float startAngle, float sweep, uint8_t pie) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->appendArc(cx, cy, radius, startAngle, sweep, pie); +} + + +TVG_API Tvg_Result tvg_shape_append_circle(Tvg_Paint* paint, float cx, float cy, float rx, float ry) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->appendCircle(cx, cy, rx, ry); +} + + +TVG_API Tvg_Result tvg_shape_append_path(Tvg_Paint* paint, const Tvg_Path_Command* cmds, uint32_t cmdCnt, const Tvg_Point* pts, uint32_t ptsCnt) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->appendPath((const PathCommand*)cmds, cmdCnt, (const Point*)pts, ptsCnt); +} + + +TVG_API Tvg_Result tvg_shape_get_path_coords(const Tvg_Paint* paint, const Tvg_Point** pts, uint32_t* cnt) +{ + if (!paint || !pts || !cnt) return TVG_RESULT_INVALID_ARGUMENT; + *cnt = reinterpret_cast(paint)->pathCoords((const Point**)pts); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_shape_get_path_commands(const Tvg_Paint* paint, const Tvg_Path_Command** cmds, uint32_t* cnt) +{ + if (!paint || !cmds || !cnt) return TVG_RESULT_INVALID_ARGUMENT; + *cnt = reinterpret_cast(paint)->pathCommands((const PathCommand**)cmds); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_shape_set_stroke_width(Tvg_Paint* paint, float width) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->stroke(width); +} + + +TVG_API Tvg_Result tvg_shape_get_stroke_width(const Tvg_Paint* paint, float* width) +{ + if (!paint || !width) return TVG_RESULT_INVALID_ARGUMENT; + *width = reinterpret_cast(paint)->strokeWidth(); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_shape_set_stroke_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->stroke(r, g, b, a); +} + + +TVG_API Tvg_Result tvg_shape_get_stroke_color(const Tvg_Paint* paint, uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->strokeColor(r, g, b, a); +} + + +TVG_API Tvg_Result tvg_shape_set_stroke_linear_gradient(Tvg_Paint* paint, Tvg_Gradient* gradient) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->stroke(unique_ptr((LinearGradient*)(gradient))); +} + + +TVG_API Tvg_Result tvg_shape_set_stroke_radial_gradient(Tvg_Paint* paint, Tvg_Gradient* gradient) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->stroke(unique_ptr((RadialGradient*)(gradient))); +} + + +TVG_API Tvg_Result tvg_shape_get_stroke_gradient(const Tvg_Paint* paint, Tvg_Gradient** gradient) +{ + if (!paint || !gradient) return TVG_RESULT_INVALID_ARGUMENT; + *gradient = (Tvg_Gradient*)(reinterpret_cast(paint)->strokeFill()); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_shape_set_stroke_dash(Tvg_Paint* paint, const float* dashPattern, uint32_t cnt) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->stroke(dashPattern, cnt); +} + + +TVG_API Tvg_Result tvg_shape_get_stroke_dash(const Tvg_Paint* paint, const float** dashPattern, uint32_t* cnt) +{ + if (!paint || !cnt || !dashPattern) return TVG_RESULT_INVALID_ARGUMENT; + *cnt = reinterpret_cast(paint)->strokeDash(dashPattern); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_shape_set_stroke_cap(Tvg_Paint* paint, Tvg_Stroke_Cap cap) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->stroke((StrokeCap)cap); +} + + +TVG_API Tvg_Result tvg_shape_get_stroke_cap(const Tvg_Paint* paint, Tvg_Stroke_Cap* cap) +{ + if (!paint || !cap) return TVG_RESULT_INVALID_ARGUMENT; + *cap = (Tvg_Stroke_Cap) reinterpret_cast(paint)->strokeCap(); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_shape_set_stroke_join(Tvg_Paint* paint, Tvg_Stroke_Join join) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->stroke((StrokeJoin)join); +} + + +TVG_API Tvg_Result tvg_shape_get_stroke_join(const Tvg_Paint* paint, Tvg_Stroke_Join* join) +{ + if (!paint || !join) return TVG_RESULT_INVALID_ARGUMENT; + *join = (Tvg_Stroke_Join) reinterpret_cast(paint)->strokeJoin(); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_shape_set_stroke_miterlimit(Tvg_Paint* paint, float ml) +{ + if (ml < 0.0f) return TVG_RESULT_NOT_SUPPORTED; + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->strokeMiterlimit(ml); +} + + +TVG_API Tvg_Result tvg_shape_get_stroke_miterlimit(const Tvg_Paint* paint, float* ml) +{ + if (!paint || !ml) return TVG_RESULT_INVALID_ARGUMENT; + *ml = reinterpret_cast(paint)->strokeMiterlimit(); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_shape_set_fill_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->fill(r, g, b, a); +} + + +TVG_API Tvg_Result tvg_shape_get_fill_color(const Tvg_Paint* paint, uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->fillColor(r, g, b, a); +} + + +TVG_API Tvg_Result tvg_shape_set_fill_rule(Tvg_Paint* paint, Tvg_Fill_Rule rule) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->fill((FillRule)rule); +} + + +TVG_API Tvg_Result tvg_shape_get_fill_rule(const Tvg_Paint* paint, Tvg_Fill_Rule* rule) +{ + if (!paint || !rule) return TVG_RESULT_INVALID_ARGUMENT; + *rule = (Tvg_Fill_Rule) reinterpret_cast(paint)->fillRule(); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_shape_set_paint_order(Tvg_Paint* paint, bool strokeFirst) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->order(strokeFirst); +} + + +TVG_API Tvg_Result tvg_shape_set_linear_gradient(Tvg_Paint* paint, Tvg_Gradient* gradient) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->fill(unique_ptr((LinearGradient*)(gradient))); +} + + +TVG_API Tvg_Result tvg_shape_set_radial_gradient(Tvg_Paint* paint, Tvg_Gradient* gradient) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->fill(unique_ptr((RadialGradient*)(gradient))); +} + + +TVG_API Tvg_Result tvg_shape_get_gradient(const Tvg_Paint* paint, Tvg_Gradient** gradient) +{ + if (!paint || !gradient) return TVG_RESULT_INVALID_ARGUMENT; + *gradient = (Tvg_Gradient*)(reinterpret_cast(paint)->fill()); + return TVG_RESULT_SUCCESS; +} + +/************************************************************************/ +/* Picture API */ +/************************************************************************/ + +TVG_API Tvg_Paint* tvg_picture_new() +{ + return (Tvg_Paint*) Picture::gen().release(); +} + + +TVG_API Tvg_Result tvg_picture_load(Tvg_Paint* paint, const char* path) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->load(path); +} + + +TVG_API Tvg_Result tvg_picture_load_raw(Tvg_Paint* paint, uint32_t *data, uint32_t w, uint32_t h, bool copy) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->load(data, w, h, copy); +} + + +TVG_API Tvg_Result tvg_picture_load_data(Tvg_Paint* paint, const char *data, uint32_t size, const char *mimetype, bool copy) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->load(data, size, mimetype ? mimetype : "", copy); +} + + +TVG_API Tvg_Result tvg_picture_set_size(Tvg_Paint* paint, float w, float h) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->size(w, h); +} + + +TVG_API Tvg_Result tvg_picture_get_size(const Tvg_Paint* paint, float* w, float* h) +{ + if (!paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(paint)->size(w, h); +} + + +/************************************************************************/ +/* Gradient API */ +/************************************************************************/ + +TVG_API Tvg_Gradient* tvg_linear_gradient_new() +{ + return (Tvg_Gradient*)LinearGradient::gen().release(); +} + + +TVG_API Tvg_Gradient* tvg_radial_gradient_new() +{ + return (Tvg_Gradient*)RadialGradient::gen().release(); +} + + +TVG_API Tvg_Gradient* tvg_gradient_duplicate(Tvg_Gradient* grad) +{ + if (!grad) return nullptr; + return (Tvg_Gradient*) reinterpret_cast(grad)->duplicate(); +} + + +TVG_API Tvg_Result tvg_gradient_del(Tvg_Gradient* grad) +{ + if (!grad) return TVG_RESULT_INVALID_ARGUMENT; + delete(reinterpret_cast(grad)); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_linear_gradient_set(Tvg_Gradient* grad, float x1, float y1, float x2, float y2) +{ + if (!grad) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(grad)->linear(x1, y1, x2, y2); +} + + +TVG_API Tvg_Result tvg_linear_gradient_get(Tvg_Gradient* grad, float* x1, float* y1, float* x2, float* y2) +{ + if (!grad) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(grad)->linear(x1, y1, x2, y2); +} + + +TVG_API Tvg_Result tvg_radial_gradient_set(Tvg_Gradient* grad, float cx, float cy, float radius) +{ + if (!grad) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(grad)->radial(cx, cy, radius); +} + + +TVG_API Tvg_Result tvg_radial_gradient_get(Tvg_Gradient* grad, float* cx, float* cy, float* radius) +{ + if (!grad) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(grad)->radial(cx, cy, radius); +} + + +TVG_API Tvg_Result tvg_gradient_set_color_stops(Tvg_Gradient* grad, const Tvg_Color_Stop* color_stop, uint32_t cnt) +{ + if (!grad) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(grad)->colorStops(reinterpret_cast(color_stop), cnt); +} + + +TVG_API Tvg_Result tvg_gradient_get_color_stops(const Tvg_Gradient* grad, const Tvg_Color_Stop** color_stop, uint32_t* cnt) +{ + if (!grad || !color_stop || !cnt) return TVG_RESULT_INVALID_ARGUMENT; + *cnt = reinterpret_cast(grad)->colorStops(reinterpret_cast(color_stop)); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_gradient_set_spread(Tvg_Gradient* grad, const Tvg_Stroke_Fill spread) +{ + if (!grad) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(grad)->spread((FillSpread)spread); +} + + +TVG_API Tvg_Result tvg_gradient_get_spread(const Tvg_Gradient* grad, Tvg_Stroke_Fill* spread) +{ + if (!grad || !spread) return TVG_RESULT_INVALID_ARGUMENT; + *spread = (Tvg_Stroke_Fill) reinterpret_cast(grad)->spread(); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_gradient_set_transform(Tvg_Gradient* grad, const Tvg_Matrix* m) +{ + if (!grad || !m) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(grad)->transform(*(reinterpret_cast(m))); +} + + +TVG_API Tvg_Result tvg_gradient_get_transform(const Tvg_Gradient* grad, Tvg_Matrix* m) +{ + if (!grad || !m) return TVG_RESULT_INVALID_ARGUMENT; + *reinterpret_cast(m) = reinterpret_cast(const_cast(grad))->transform(); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_gradient_get_identifier(const Tvg_Gradient* grad, Tvg_Identifier* identifier) +{ + if (!grad || !identifier) return TVG_RESULT_INVALID_ARGUMENT; + *identifier = static_cast(reinterpret_cast(grad)->identifier()); + return TVG_RESULT_SUCCESS; +} + +/************************************************************************/ +/* Scene API */ +/************************************************************************/ + +TVG_API Tvg_Paint* tvg_scene_new() +{ + return (Tvg_Paint*) Scene::gen().release(); +} + + +TVG_API Tvg_Result tvg_scene_reserve(Tvg_Paint* scene, uint32_t size) +{ + return TVG_RESULT_NOT_SUPPORTED; +} + + +TVG_API Tvg_Result tvg_scene_push(Tvg_Paint* scene, Tvg_Paint* paint) +{ + if (!scene || !paint) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(scene)->push(unique_ptr((Paint*)paint)); +} + + +TVG_API Tvg_Result tvg_scene_clear(Tvg_Paint* scene, bool free) +{ + if (!scene) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(scene)->clear(free); +} + + +/************************************************************************/ +/* Saver API */ +/************************************************************************/ + +TVG_API Tvg_Saver* tvg_saver_new() +{ + return (Tvg_Saver*) Saver::gen().release(); +} + + +TVG_API Tvg_Result tvg_saver_save(Tvg_Saver* saver, Tvg_Paint* paint, const char* path, bool compress) +{ + if (!saver || !paint || !path) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(saver)->save(unique_ptr((Paint*)paint), path, compress); +} + + +TVG_API Tvg_Result tvg_saver_sync(Tvg_Saver* saver) +{ + if (!saver) return TVG_RESULT_INVALID_ARGUMENT; + return (Tvg_Result) reinterpret_cast(saver)->sync(); +} + + +TVG_API Tvg_Result tvg_saver_del(Tvg_Saver* saver) +{ + if (!saver) return TVG_RESULT_INVALID_ARGUMENT; + delete(reinterpret_cast(saver)); + return TVG_RESULT_SUCCESS; +} + + +/************************************************************************/ +/* Animation API */ +/************************************************************************/ + +TVG_API Tvg_Animation* tvg_animation_new() +{ + return (Tvg_Animation*) Animation::gen().release(); +} + + +TVG_API Tvg_Result tvg_animation_set_frame(Tvg_Animation* animation, uint32_t no) +{ + return TVG_RESULT_INVALID_ARGUMENT; +// if (!animation) return TVG_RESULT_INVALID_ARGUMENT; +// return (Tvg_Result) reinterpret_cast(animation)->frame(no); +} + + +TVG_API Tvg_Result tvg_animation_get_frame(Tvg_Animation* animation, uint32_t* no) +{ + if (!animation || !no) return TVG_RESULT_INVALID_ARGUMENT; + *no = reinterpret_cast(animation)->curFrame(); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_animation_get_total_frame(Tvg_Animation* animation, uint32_t* cnt) +{ + if (!animation || !cnt) return TVG_RESULT_INVALID_ARGUMENT; + *cnt = reinterpret_cast(animation)->totalFrame(); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Paint* tvg_animation_get_picture(Tvg_Animation* animation) +{ + if (!animation) return nullptr; + return (Tvg_Paint*) reinterpret_cast(animation)->picture(); +} + + +TVG_API Tvg_Result tvg_animation_get_duration(Tvg_Animation* animation, float* duration) +{ + if (!animation || !duration) return TVG_RESULT_INVALID_ARGUMENT; + *duration = reinterpret_cast(animation)->duration(); + return TVG_RESULT_SUCCESS; +} + + +TVG_API Tvg_Result tvg_animation_del(Tvg_Animation* animation) +{ + if (!animation) return TVG_RESULT_INVALID_ARGUMENT; + delete(reinterpret_cast(animation)); + return TVG_RESULT_SUCCESS; +} + +#ifdef __cplusplus +} +#endif + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCommon.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCommon.h new file mode 100644 index 000000000..d70681170 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCommon.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_COMMON_H_ +#define _TVG_COMMON_H_ + +#include "config.h" +#include "thorvg.h" + +using namespace std; +using namespace tvg; + +//for MSVC Compat +#ifdef _MSC_VER + #define TVG_UNUSED + #define strncasecmp _strnicmp + #define strcasecmp _stricmp +#else + #define TVG_UNUSED __attribute__ ((__unused__)) +#endif + +// Portable 'fallthrough' attribute +#if __has_cpp_attribute(fallthrough) + #ifdef _MSC_VER + #define TVG_FALLTHROUGH [[fallthrough]]; + #else + #define TVG_FALLTHROUGH __attribute__ ((fallthrough)); + #endif +#else + #define TVG_FALLTHROUGH +#endif + +#if defined(_MSC_VER) && defined(__clang__) + #define strncpy strncpy_s + #define strdup _strdup +#endif + +//TVG class identifier values +#define TVG_CLASS_ID_UNDEFINED 0 +#define TVG_CLASS_ID_SHAPE 1 +#define TVG_CLASS_ID_SCENE 2 +#define TVG_CLASS_ID_PICTURE 3 +#define TVG_CLASS_ID_LINEAR 4 +#define TVG_CLASS_ID_RADIAL 5 + +enum class FileType { Tvg = 0, Svg, Lottie, Raw, Png, Jpg, Webp, Unknown }; + +using Size = Point; + +#ifdef THORVG_LOG_ENABLED + constexpr auto ErrorColor = "\033[31m"; //red + constexpr auto ErrorBgColor = "\033[41m";//bg red + constexpr auto LogColor = "\033[32m"; //green + constexpr auto LogBgColor = "\033[42m"; //bg green + constexpr auto GreyColor = "\033[90m"; //grey + constexpr auto ResetColors = "\033[0m"; //default + #define TVGERR(tag, fmt, ...) fprintf(stderr, "%s[E]%s %s" tag "%s (%s %d): %s" fmt "\n", ErrorBgColor, ResetColors, ErrorColor, GreyColor, __FILE__, __LINE__, ResetColors, ##__VA_ARGS__) + #define TVGLOG(tag, fmt, ...) fprintf(stdout, "%s[L]%s %s" tag "%s (%s %d): %s" fmt "\n", LogBgColor, ResetColors, LogColor, GreyColor, __FILE__, __LINE__, ResetColors, ##__VA_ARGS__) +#else + #define TVGERR(...) do {} while(0) + #define TVGLOG(...) do {} while(0) +#endif + +uint16_t THORVG_VERSION_NUMBER(); + + +#define P(A) ((A)->pImpl) //Access to pimpl. +#define PP(A) (((Paint*)(A))->pImpl) //Access to pimpl. + +#endif //_TVG_COMMON_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCompressor.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCompressor.cpp new file mode 100644 index 000000000..20941712f --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCompressor.cpp @@ -0,0 +1,481 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +/* + * Lempel–Ziv–Welch (LZW) encoder/decoder by Guilherme R. Lampert(guilherme.ronaldo.lampert@gmail.com) + + * This is the compression scheme used by the GIF image format and the Unix 'compress' tool. + * Main differences from this implementation is that End Of Input (EOI) and Clear Codes (CC) + * are not stored in the output and the max code length in bits is 12, vs 16 in compress. + * + * EOI is simply detected by the end of the data stream, while CC happens if the + * dictionary gets filled. Data is written/read from bit streams, which handle + * byte-alignment for us in a transparent way. + + * The decoder relies on the hardcoded data layout produced by the encoder, since + * no additional reconstruction data is added to the output, so they must match. + * The nice thing about LZW is that we can reconstruct the dictionary directly from + * the stream of codes generated by the encoder, so this avoids storing additional + * headers in the bit stream. + + * The output code length is variable. It starts with the minimum number of bits + * required to store the base byte-sized dictionary and automatically increases + * as the dictionary gets larger (it starts at 9-bits and grows to 10-bits when + * code 512 is added, then 11-bits when 1024 is added, and so on). If the dictionary + * is filled (4096 items for a 12-bits dictionary), the whole thing is cleared and + * the process starts over. This is the main reason why the encoder and the decoder + * must match perfectly, since the lengths of the codes will not be specified with + * the data itself. + + * USEFUL LINKS: + * https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Welch + * http://rosettacode.org/wiki/LZW_compression + * http://www.cs.duke.edu/csed/curious/compression/lzw.html + * http://www.cs.cf.ac.uk/Dave/Multimedia/node214.html + * http://marknelson.us/1989/10/01/lzw-data-compression/ + */ +#include "config.h" + + + +#include +#include +#include "tvgCompressor.h" + +namespace tvg { + + +/************************************************************************/ +/* LZW Implementation */ +/************************************************************************/ + + +//LZW Dictionary helper: +constexpr int Nil = -1; +constexpr int MaxDictBits = 12; +constexpr int StartBits = 9; +constexpr int FirstCode = (1 << (StartBits - 1)); // 256 +constexpr int MaxDictEntries = (1 << MaxDictBits); // 4096 + + +//Round up to the next power-of-two number, e.g. 37 => 64 +static int nextPowerOfTwo(int num) +{ + --num; + for (size_t i = 1; i < sizeof(num) * 8; i <<= 1) { + num = num | num >> i; + } + return ++num; +} + + +struct BitStreamWriter +{ + uint8_t* stream; //Growable buffer to store our bits. Heap allocated & owned by the class instance. + int bytesAllocated; //Current size of heap-allocated stream buffer *in bytes*. + int granularity; //Amount bytesAllocated multiplies by when auto-resizing in appendBit(). + int currBytePos; //Current byte being written to, from 0 to bytesAllocated-1. + int nextBitPos; //Bit position within the current byte to access next. 0 to 7. + int numBitsWritten; //Number of bits in use from the stream buffer, not including byte-rounding padding. + + void internalInit() + { + stream = nullptr; + bytesAllocated = 0; + granularity = 2; + currBytePos = 0; + nextBitPos = 0; + numBitsWritten = 0; + } + + uint8_t* allocBytes(const int bytesWanted, uint8_t * oldPtr, const int oldSize) + { + auto newMemory = static_cast(malloc(bytesWanted)); + memset(newMemory, 0, bytesWanted); + + if (oldPtr) { + memcpy(newMemory, oldPtr, oldSize); + free(oldPtr); + } + return newMemory; + } + + BitStreamWriter() + { + /* 8192 bits for a start (1024 bytes). It will resize if needed. + Default granularity is 2. */ + internalInit(); + allocate(8192); + } + + BitStreamWriter(const int initialSizeInBits, const int growthGranularity = 2) + { + internalInit(); + setGranularity(growthGranularity); + allocate(initialSizeInBits); + } + + ~BitStreamWriter() + { + free(stream); + } + + void allocate(int bitsWanted) + { + //Require at least a byte. + if (bitsWanted <= 0) bitsWanted = 8; + + //Round upwards if needed: + if ((bitsWanted % 8) != 0) bitsWanted = nextPowerOfTwo(bitsWanted); + + //We might already have the required count. + const int sizeInBytes = bitsWanted / 8; + if (sizeInBytes <= bytesAllocated) return; + + stream = allocBytes(sizeInBytes, stream, bytesAllocated); + bytesAllocated = sizeInBytes; + } + + void appendBit(const int bit) + { + const uint32_t mask = uint32_t(1) << nextBitPos; + stream[currBytePos] = (stream[currBytePos] & ~mask) | (-bit & mask); + ++numBitsWritten; + + if (++nextBitPos == 8) { + nextBitPos = 0; + if (++currBytePos == bytesAllocated) allocate(bytesAllocated * granularity * 8); + } + } + + void appendBitsU64(const uint64_t num, const int bitCount) + { + for (int b = 0; b < bitCount; ++b) { + const uint64_t mask = uint64_t(1) << b; + const int bit = !!(num & mask); + appendBit(bit); + } + } + + uint8_t* release() + { + auto oldPtr = stream; + internalInit(); + return oldPtr; + } + + void setGranularity(const int growthGranularity) + { + granularity = (growthGranularity >= 2) ? growthGranularity : 2; + } + + int getByteCount() const + { + int usedBytes = numBitsWritten / 8; + int leftovers = numBitsWritten % 8; + if (leftovers != 0) ++usedBytes; + return usedBytes; + } +}; + + +struct BitStreamReader +{ + const uint8_t* stream; // Pointer to the external bit stream. Not owned by the reader. + const int sizeInBytes; // Size of the stream *in bytes*. Might include padding. + const int sizeInBits; // Size of the stream *in bits*, padding *not* include. + int currBytePos = 0; // Current byte being read in the stream. + int nextBitPos = 0; // Bit position within the current byte to access next. 0 to 7. + int numBitsRead = 0; // Total bits read from the stream so far. Never includes byte-rounding padding. + + BitStreamReader(const uint8_t* bitStream, const int byteCount, const int bitCount) : stream(bitStream), sizeInBytes(byteCount), sizeInBits(bitCount) + { + } + + bool readNextBit(int& bitOut) + { + if (numBitsRead >= sizeInBits) return false; //We are done. + + const uint32_t mask = uint32_t(1) << nextBitPos; + bitOut = !!(stream[currBytePos] & mask); + ++numBitsRead; + + if (++nextBitPos == 8) { + nextBitPos = 0; + ++currBytePos; + } + return true; + } + + uint64_t readBitsU64(const int bitCount) + { + uint64_t num = 0; + for (int b = 0; b < bitCount; ++b) { + int bit; + if (!readNextBit(bit)) break; + /* Based on a "Stanford bit-hack": + http://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching */ + const uint64_t mask = uint64_t(1) << b; + num = (num & ~mask) | (-bit & mask); + } + return num; + } + + bool isEndOfStream() const + { + return numBitsRead >= sizeInBits; + } +}; + + +struct Dictionary +{ + struct Entry + { + int code; + int value; + }; + + //Dictionary entries 0-255 are always reserved to the byte/ASCII range. + int size; + Entry entries[MaxDictEntries]; + + Dictionary() + { + /* First 256 dictionary entries are reserved to the byte/ASCII range. + Additional entries follow for the character sequences found in the input. + Up to 4096 - 256 (MaxDictEntries - FirstCode). */ + size = FirstCode; + + for (int i = 0; i < size; ++i) { + entries[i].code = Nil; + entries[i].value = i; + } + } + + int findIndex(const int code, const int value) const + { + if (code == Nil) return value; + + //Linear search for now. + //TODO: Worth optimizing with a proper hash-table? + for (int i = 0; i < size; ++i) { + if (entries[i].code == code && entries[i].value == value) return i; + } + return Nil; + } + + bool add(const int code, const int value) + { + if (size == MaxDictEntries) return false; + entries[size].code = code; + entries[size].value = value; + ++size; + return true; + } + + bool flush(int & codeBitsWidth) + { + if (size == (1 << codeBitsWidth)) { + ++codeBitsWidth; + if (codeBitsWidth > MaxDictBits) { + //Clear the dictionary (except the first 256 byte entries). + codeBitsWidth = StartBits; + size = FirstCode; + return true; + } + } + return false; + } +}; + + +static bool outputByte(int code, uint8_t*& output, int outputSizeBytes, int& bytesDecodedSoFar) +{ + if (bytesDecodedSoFar >= outputSizeBytes) return false; + *output++ = static_cast(code); + ++bytesDecodedSoFar; + return true; +} + + +static bool outputSequence(const Dictionary& dict, int code, uint8_t*& output, int outputSizeBytes, int& bytesDecodedSoFar, int& firstByte) +{ + /* A sequence is stored backwards, so we have to write + it to a temp then output the buffer in reverse. */ + int i = 0; + uint8_t sequence[MaxDictEntries]; + + do { + sequence[i++] = dict.entries[code].value; + code = dict.entries[code].code; + } while (code >= 0); + + firstByte = sequence[--i]; + + for (; i >= 0; --i) { + if (!outputByte(sequence[i], output, outputSizeBytes, bytesDecodedSoFar)) return false; + } + return true; +} + + +uint8_t* lzwDecode(const uint8_t* compressed, uint32_t compressedSizeBytes, uint32_t compressedSizeBits, uint32_t uncompressedSizeBytes) +{ + int code = Nil; + int prevCode = Nil; + int firstByte = 0; + int bytesDecoded = 0; + int codeBitsWidth = StartBits; + auto uncompressed = (uint8_t*) malloc(sizeof(uint8_t) * uncompressedSizeBytes); + auto ptr = uncompressed; + + /* We'll reconstruct the dictionary based on the bit stream codes. + Unlike Huffman encoding, we don't store the dictionary as a prefix to the data. */ + Dictionary dictionary; + BitStreamReader bitStream(compressed, compressedSizeBytes, compressedSizeBits); + + /* We check to avoid an overflow of the user buffer. + If the buffer is smaller than the decompressed size, we break the loop and return the current decompression count. */ + while (!bitStream.isEndOfStream()) { + code = static_cast(bitStream.readBitsU64(codeBitsWidth)); + + if (prevCode == Nil) { + if (!outputByte(code, ptr, uncompressedSizeBytes, bytesDecoded)) break; + firstByte = code; + prevCode = code; + continue; + } + if (code >= dictionary.size) { + if (!outputSequence(dictionary, prevCode, ptr, uncompressedSizeBytes, bytesDecoded, firstByte)) break; + if (!outputByte(firstByte, ptr, uncompressedSizeBytes, bytesDecoded)) break; + } else if (!outputSequence(dictionary, code, ptr, uncompressedSizeBytes, bytesDecoded, firstByte)) break; + + dictionary.add(prevCode, firstByte); + if (dictionary.flush(codeBitsWidth)) prevCode = Nil; + else prevCode = code; + } + + return uncompressed; +} + + +uint8_t* lzwEncode(const uint8_t* uncompressed, uint32_t uncompressedSizeBytes, uint32_t* compressedSizeBytes, uint32_t* compressedSizeBits) +{ + //LZW encoding context: + int code = Nil; + int codeBitsWidth = StartBits; + Dictionary dictionary; + + //Output bit stream we write to. This will allocate memory as needed to accommodate the encoded data. + BitStreamWriter bitStream; + + for (; uncompressedSizeBytes > 0; --uncompressedSizeBytes, ++uncompressed) { + const int value = *uncompressed; + const int index = dictionary.findIndex(code, value); + + if (index != Nil) { + code = index; + continue; + } + + //Write the dictionary code using the minimum bit-with: + bitStream.appendBitsU64(code, codeBitsWidth); + + //Flush it when full so we can restart the sequences. + if (!dictionary.flush(codeBitsWidth)) { + //There's still space for this sequence. + dictionary.add(code, value); + } + code = value; + } + + //Residual code at the end: + if (code != Nil) bitStream.appendBitsU64(code, codeBitsWidth); + + //Pass ownership of the compressed data buffer to the user pointer: + *compressedSizeBytes = bitStream.getByteCount(); + *compressedSizeBits = bitStream.numBitsWritten; + + return bitStream.release(); +} + + +/************************************************************************/ +/* B64 Implementation */ +/************************************************************************/ + + +size_t b64Decode(const char* encoded, const size_t len, char** decoded) +{ + static constexpr const char B64_INDEX[256] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 0, 0, 0, 0, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 + }; + + + if (!decoded || !encoded || len == 0) return 0; + + auto reserved = 3 * (1 + (len >> 2)) + 1; + auto output = static_cast(malloc(reserved * sizeof(char))); + if (!output) return 0; + output[reserved - 1] = '\0'; + + size_t idx = 0; + + while (*encoded && *(encoded + 1)) { + if (*encoded <= 0x20) { + ++encoded; + continue; + } + + auto value1 = B64_INDEX[(size_t)encoded[0]]; + auto value2 = B64_INDEX[(size_t)encoded[1]]; + output[idx++] = (value1 << 2) + ((value2 & 0x30) >> 4); + + if (!encoded[2] || encoded[2] == '=' || encoded[2] == '.') break; + auto value3 = B64_INDEX[(size_t)encoded[2]]; + output[idx++] = ((value2 & 0x0f) << 4) + ((value3 & 0x3c) >> 2); + + if (!encoded[3] || encoded[3] == '=' || encoded[3] == '.') break; + auto value4 = B64_INDEX[(size_t)encoded[3]]; + output[idx++] = ((value3 & 0x03) << 6) + value4; + encoded += 4; + } + *decoded = output; + return reserved; +} + + +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCompressor.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCompressor.h new file mode 100644 index 000000000..6d9dfce1b --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgCompressor.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_COMPRESSOR_H_ +#define _TVG_COMPRESSOR_H_ + +#include + +namespace tvg +{ + uint8_t* lzwEncode(const uint8_t* uncompressed, uint32_t uncompressedSizeBytes, uint32_t* compressedSizeBytes, uint32_t* compressedSizeBits); + uint8_t* lzwDecode(const uint8_t* compressed, uint32_t compressedSizeBytes, uint32_t compressedSizeBits, uint32_t uncompressedSizeBytes); + size_t b64Decode(const char* encoded, const size_t len, char** decoded); +} + +#endif //_TVG_COMPRESSOR_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgFill.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgFill.cpp new file mode 100644 index 000000000..152883445 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgFill.cpp @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgFill.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +Fill* RadialGradient::Impl::duplicate() +{ + auto ret = RadialGradient::gen(); + if (!ret) return nullptr; + + ret->pImpl->cx = cx; + ret->pImpl->cy = cy; + ret->pImpl->r = r; + ret->pImpl->fx = fx; + ret->pImpl->fy = fy; + ret->pImpl->fr = fr; + + return ret.release(); +} + + +Result RadialGradient::Impl::radial(float cx, float cy, float r, float fx, float fy, float fr) +{ + if (r < 0 || fr < 0) return Result::InvalidArguments; + + this->cx = cx; + this->cy = cy; + this->r = r; + this->fx = fx; + this->fy = fy; + this->fr = fr; + + return Result::Success; +}; + + +Fill* LinearGradient::Impl::duplicate() +{ + auto ret = LinearGradient::gen(); + if (!ret) return nullptr; + + ret->pImpl->x1 = x1; + ret->pImpl->y1 = y1; + ret->pImpl->x2 = x2; + ret->pImpl->y2 = y2; + + return ret.release(); +}; + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +Fill::Fill():pImpl(new Impl()) +{ +} + + +Fill::~Fill() +{ + delete(pImpl); +} + + +Result Fill::colorStops(const ColorStop* colorStops, uint32_t cnt) noexcept +{ + if ((!colorStops && cnt > 0) || (colorStops && cnt == 0)) return Result::InvalidArguments; + + if (cnt == 0) { + if (pImpl->colorStops) { + free(pImpl->colorStops); + pImpl->colorStops = nullptr; + pImpl->cnt = 0; + } + return Result::Success; + } + + if (pImpl->cnt != cnt) { + pImpl->colorStops = static_cast(realloc(pImpl->colorStops, cnt * sizeof(ColorStop))); + } + + pImpl->cnt = cnt; + memcpy(pImpl->colorStops, colorStops, cnt * sizeof(ColorStop)); + + return Result::Success; +} + + +uint32_t Fill::colorStops(const ColorStop** colorStops) const noexcept +{ + if (colorStops) *colorStops = pImpl->colorStops; + + return pImpl->cnt; +} + + +Result Fill::spread(FillSpread s) noexcept +{ + pImpl->spread = s; + + return Result::Success; +} + + +FillSpread Fill::spread() const noexcept +{ + return pImpl->spread; +} + + +Result Fill::transform(const Matrix& m) noexcept +{ + if (!pImpl->transform) { + pImpl->transform = static_cast(malloc(sizeof(Matrix))); + } + *pImpl->transform = m; + return Result::Success; +} + + +Matrix Fill::transform() const noexcept +{ + if (pImpl->transform) return *pImpl->transform; + return {1, 0, 0, 0, 1, 0, 0, 0, 1}; +} + + +Fill* Fill::duplicate() const noexcept +{ + return pImpl->duplicate(); +} + + +uint32_t Fill::identifier() const noexcept +{ + return pImpl->id; +} + + +RadialGradient::RadialGradient():pImpl(new Impl()) +{ + Fill::pImpl->id = TVG_CLASS_ID_RADIAL; + Fill::pImpl->method(new FillDup(pImpl)); +} + + +RadialGradient::~RadialGradient() +{ + delete(pImpl); +} + + +Result RadialGradient::radial(float cx, float cy, float r) noexcept +{ + return pImpl->radial(cx, cy, r, cx, cy, 0.0f); +} + + +Result RadialGradient::radial(float* cx, float* cy, float* r) const noexcept +{ + if (cx) *cx = pImpl->cx; + if (cy) *cy = pImpl->cy; + if (r) *r = pImpl->r; + + return Result::Success; +} + + +unique_ptr RadialGradient::gen() noexcept +{ + return unique_ptr(new RadialGradient); +} + + +uint32_t RadialGradient::identifier() noexcept +{ + return TVG_CLASS_ID_RADIAL; +} + + +LinearGradient::LinearGradient():pImpl(new Impl()) +{ + Fill::pImpl->id = TVG_CLASS_ID_LINEAR; + Fill::pImpl->method(new FillDup(pImpl)); +} + + +LinearGradient::~LinearGradient() +{ + delete(pImpl); +} + + +Result LinearGradient::linear(float x1, float y1, float x2, float y2) noexcept +{ + pImpl->x1 = x1; + pImpl->y1 = y1; + pImpl->x2 = x2; + pImpl->y2 = y2; + + return Result::Success; +} + + +Result LinearGradient::linear(float* x1, float* y1, float* x2, float* y2) const noexcept +{ + if (x1) *x1 = pImpl->x1; + if (x2) *x2 = pImpl->x2; + if (y1) *y1 = pImpl->y1; + if (y2) *y2 = pImpl->y2; + + return Result::Success; +} + + +unique_ptr LinearGradient::gen() noexcept +{ + return unique_ptr(new LinearGradient); +} + + +uint32_t LinearGradient::identifier() noexcept +{ + return TVG_CLASS_ID_LINEAR; +} + + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgFill.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgFill.h new file mode 100644 index 000000000..159540398 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgFill.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_FILL_H_ +#define _TVG_FILL_H_ + +#include +#include +#include "tvgCommon.h" + +template +struct DuplicateMethod +{ + virtual ~DuplicateMethod() {} + virtual T* duplicate() = 0; +}; + +template +struct FillDup : DuplicateMethod +{ + T* inst = nullptr; + + FillDup(T* _inst) : inst(_inst) {} + ~FillDup() {} + + Fill* duplicate() override + { + return inst->duplicate(); + } +}; + +struct Fill::Impl +{ + ColorStop* colorStops = nullptr; + Matrix* transform = nullptr; + uint32_t cnt = 0; + FillSpread spread; + DuplicateMethod* dup = nullptr; + uint8_t id; + + ~Impl() + { + delete(dup); + free(colorStops); + free(transform); + } + + void method(DuplicateMethod* dup) + { + this->dup = dup; + } + + Fill* duplicate() + { + auto ret = dup->duplicate(); + if (!ret) return nullptr; + + ret->pImpl->cnt = cnt; + ret->pImpl->spread = spread; + ret->pImpl->colorStops = static_cast(malloc(sizeof(ColorStop) * cnt)); + memcpy(ret->pImpl->colorStops, colorStops, sizeof(ColorStop) * cnt); + if (transform) { + ret->pImpl->transform = static_cast(malloc(sizeof(Matrix))); + *ret->pImpl->transform = *transform; + } + return ret; + } +}; + + +struct RadialGradient::Impl +{ + float cx = 0.0f, cy = 0.0f; + float fx = 0.0f, fy = 0.0f; + float r = 0.0f, fr = 0.0f; + + Fill* duplicate(); + Result radial(float cx, float cy, float r, float fx, float fy, float fr); +}; + + +struct LinearGradient::Impl +{ + float x1 = 0.0f; + float y1 = 0.0f; + float x2 = 0.0f; + float y2 = 0.0f; + + Fill* duplicate(); +}; + + +#endif //_TVG_FILL_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgFrameModule.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgFrameModule.h new file mode 100644 index 000000000..726b84c84 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgFrameModule.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_FRAME_MODULE_H_ +#define _TVG_FRAME_MODULE_H_ + +#include "tvgLoadModule.h" + +namespace tvg +{ + +class FrameModule: public LoadModule +{ +public: + virtual ~FrameModule() {} + + virtual bool frame(uint32_t frameNo) = 0; //set the current frame number + + virtual uint32_t totalFrame() = 0; //return the total frame count + virtual uint32_t curFrame() = 0; //return the current frame number + virtual float duration() = 0; //return the animation duration in seconds + + virtual bool animatable() override { return true; } +}; + +} + +#endif //_TVG_FRAME_MODULE_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgInitializer.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgInitializer.cpp new file mode 100644 index 000000000..66d260276 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgInitializer.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgCommon.h" +#include "tvgTaskScheduler.h" +#include "tvgLoader.h" + +#ifdef _WIN32 + #include +#endif + +#ifdef THORVG_SW_RASTER_SUPPORT + #include "tvgSwRenderer.h" +#endif + +#ifdef THORVG_GL_RASTER_SUPPORT + #include "tvgGlRenderer.h" +#endif + +#ifdef THORVG_WG_RASTER_SUPPORT + #include "tvgWgRenderer.h" +#endif + + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static int _initCnt = 0; +static uint16_t _version = 0; + +//enum class operation helper +static constexpr bool operator &(CanvasEngine a, CanvasEngine b) +{ + return int(a) & int(b); +} + +static bool _buildVersionInfo() +{ + auto SRC = THORVG_VERSION_STRING; //ex) 0.3.99 + auto p = SRC; + const char* x; + + char major[3]; + x = strchr(p, '.'); + if (!x) return false; + memcpy(major, p, x - p); + major[x - p] = '\0'; + p = x + 1; + + char minor[3]; + x = strchr(p, '.'); + if (!x) return false; + memcpy(minor, p, x - p); + minor[x - p] = '\0'; + p = x + 1; + + char micro[3]; + x = SRC + strlen(THORVG_VERSION_STRING); + memcpy(micro, p, x - p); + micro[x - p] = '\0'; + + char sum[7]; + snprintf(sum, sizeof(sum), "%s%s%s", major, minor, micro); + + _version = atoi(sum); + + return true; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept +{ + auto nonSupport = true; + if (static_cast(engine) == 0) return Result::InvalidArguments; + + if (engine & CanvasEngine::Sw) { + #ifdef THORVG_SW_RASTER_SUPPORT + if (!SwRenderer::init(threads)) return Result::FailedAllocation; + nonSupport = false; + #endif + } + + if (engine & CanvasEngine::Gl) { + #ifdef THORVG_GL_RASTER_SUPPORT + if (!GlRenderer::init(threads)) return Result::FailedAllocation; + nonSupport = false; + #endif + } + + if (engine & CanvasEngine::Wg) { + #ifdef THORVG_WG_RASTER_SUPPORT + if (!WgRenderer::init(threads)) return Result::FailedAllocation; + nonSupport = false; + #endif + } + + if (nonSupport) return Result::NonSupport; + + if (_initCnt++ > 0) return Result::Success; + + if (!_buildVersionInfo()) return Result::Unknown; + + if (!LoaderMgr::init()) return Result::Unknown; + + TaskScheduler::init(threads); + + return Result::Success; +} + + +Result Initializer::term(CanvasEngine engine) noexcept +{ + if (_initCnt == 0) return Result::InsufficientCondition; + + auto nonSupport = true; + if (static_cast(engine) == 0) return Result::InvalidArguments; + + if (engine & CanvasEngine::Sw) { + #ifdef THORVG_SW_RASTER_SUPPORT + if (!SwRenderer::term()) return Result::InsufficientCondition; + nonSupport = false; + #endif + } + + if (engine & CanvasEngine::Gl) { + #ifdef THORVG_GL_RASTER_SUPPORT + if (!GlRenderer::term()) return Result::InsufficientCondition; + nonSupport = false; + #endif + } + + if (engine & CanvasEngine::Wg) { + #ifdef THORVG_WG_RASTER_SUPPORT + if (!WgRenderer::term()) return Result::InsufficientCondition; + nonSupport = false; + #endif + } + + if (nonSupport) return Result::NonSupport; + + if (--_initCnt > 0) return Result::Success; + + if (!LoaderMgr::term()) return Result::Unknown; + + return Result::Success; +} + + +uint16_t THORVG_VERSION_NUMBER() +{ + return _version; +} + + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgIteratorAccessor.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgIteratorAccessor.h new file mode 100644 index 000000000..ac7015fe4 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgIteratorAccessor.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_ITERATOR_ACCESSOR_H_ +#define _TVG_ITERATOR_ACCESSOR_H_ + +#include "tvgPaint.h" + +namespace tvg +{ + +class IteratorAccessor +{ +public: + //Utility Method: Iterator Accessor + static Iterator* iterator(const Paint* paint) + { + return paint->pImpl->iterator(); + } +}; + +} + +#endif //_TVG_ITERATOR_ACCESSOR_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgLoadModule.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgLoadModule.h new file mode 100644 index 000000000..7ccf94850 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgLoadModule.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_LOAD_MODULE_H_ +#define _TVG_LOAD_MODULE_H_ + +#include "tvgRender.h" + +namespace tvg +{ + +class LoadModule +{ +public: + float w = 0, h = 0; //default image size + ColorSpace cs = ColorSpace::Unsupported; //must be clarified at open() + + virtual ~LoadModule() {} + + virtual bool open(const string& path) { return false; } + virtual bool open(const char* data, uint32_t size, bool copy) { return false; } + virtual bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) { return false; } + + //Override this if the vector-format has own resizing policy. + virtual bool resize(Paint* paint, float w, float h) { return false; } + + virtual bool animatable() { return false; } //true if this loader supports animation. + virtual void sync() {}; //finish immediately if any async update jobs. + + virtual bool read() = 0; + virtual bool close() = 0; + + virtual unique_ptr bitmap() { return nullptr; } + virtual unique_ptr paint() { return nullptr; } +}; + +} + +#endif //_TVG_LOAD_MODULE_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgLoader.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgLoader.cpp new file mode 100644 index 000000000..3a2cb32a4 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgLoader.cpp @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgLoader.h" + +#ifdef THORVG_SVG_LOADER_SUPPORT + #include "tvgSvgLoader.h" +#endif + +#ifdef THORVG_PNG_LOADER_SUPPORT + #include "tvgPngLoader.h" +#endif + +#ifdef THORVG_TVG_LOADER_SUPPORT + #include "tvgTvgLoader.h" +#endif + +#ifdef THORVG_JPG_LOADER_SUPPORT + #include "tvgJpgLoader.h" +#endif + +#ifdef THORVG_WEBP_LOADER_SUPPORT + #include "tvgWebpLoader.h" +#endif + +#ifdef THORVG_LOTTIE_LOADER_SUPPORT + #include "tvgLottieLoader.h" +#endif + +#include "tvgRawLoader.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static LoadModule* _find(FileType type) +{ + switch(type) { + case FileType::Tvg: { +#ifdef THORVG_TVG_LOADER_SUPPORT + return new TvgLoader; +#endif + break; + } + case FileType::Svg: { +#ifdef THORVG_SVG_LOADER_SUPPORT + return new SvgLoader; +#endif + break; + } + case FileType::Lottie: { +#ifdef THORVG_LOTTIE_LOADER_SUPPORT + return new LottieLoader; +#endif + break; + } + case FileType::Raw: { + return new RawLoader; + break; + } + case FileType::Png: { +#ifdef THORVG_PNG_LOADER_SUPPORT + return new PngLoader; +#endif + break; + } + case FileType::Jpg: { +#ifdef THORVG_JPG_LOADER_SUPPORT + return new JpgLoader; +#endif + break; + } + case FileType::Webp: { +#ifdef THORVG_WEBP_LOADER_SUPPORT + return new WebpLoader; +#endif + break; + } + default: { + break; + } + } + +#ifdef THORVG_LOG_ENABLED + const char *format; + switch(type) { + case FileType::Tvg: { + format = "TVG"; + break; + } + case FileType::Svg: { + format = "SVG"; + break; + } + case FileType::Lottie: { + format = "lottie(json)"; + break; + } + case FileType::Raw: { + format = "RAW"; + break; + } + case FileType::Png: { + format = "PNG"; + break; + } + case FileType::Jpg: { + format = "JPG"; + break; + } + case FileType::Webp: { + format = "WEBP"; + break; + } + default: { + format = "???"; + break; + } + } + TVGLOG("LOADER", "%s format is not supported", format); +#endif + return nullptr; +} + + +static LoadModule* _findByPath(const string& path) +{ + auto ext = path.substr(path.find_last_of(".") + 1); + if (!ext.compare("tvg")) return _find(FileType::Tvg); + if (!ext.compare("svg")) return _find(FileType::Svg); + if (!ext.compare("json")) return _find(FileType::Lottie); + if (!ext.compare("lottie")) return _find(FileType::Lottie); + if (!ext.compare("png")) return _find(FileType::Png); + if (!ext.compare("jpg")) return _find(FileType::Jpg); + if (!ext.compare("webp")) return _find(FileType::Webp); + return nullptr; +} + + +static LoadModule* _findByType(const string& mimeType) +{ + if (mimeType.empty()) return nullptr; + + auto type = FileType::Unknown; + + if (mimeType == "tvg") type = FileType::Tvg; + else if (mimeType == "svg" || mimeType == "svg+xml") type = FileType::Svg; + else if (mimeType == "lottie") type = FileType::Lottie; + else if (mimeType == "raw") type = FileType::Raw; + else if (mimeType == "png") type = FileType::Png; + else if (mimeType == "jpg" || mimeType == "jpeg") type = FileType::Jpg; + else if (mimeType == "webp") type = FileType::Webp; + else { + TVGLOG("LOADER", "Given mimetype is unknown = \"%s\".", mimeType.c_str()); + return nullptr; + } + + return _find(type); +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + + +bool LoaderMgr::init() +{ + //TODO: + + return true; +} + + +bool LoaderMgr::term() +{ + //TODO: + + return true; +} + + +shared_ptr LoaderMgr::loader(const string& path, bool* invalid) +{ + *invalid = false; + + if (auto loader = _findByPath(path)) { + if (loader->open(path)) return shared_ptr(loader); + else delete(loader); + *invalid = true; + } + return nullptr; +} + + +shared_ptr LoaderMgr::loader(const char* data, uint32_t size, const string& mimeType, bool copy) +{ + //Try with the given MimeType + if (!mimeType.empty()) { + if (auto loader = _findByType(mimeType)) { + if (loader->open(data, size, copy)) { + return shared_ptr(loader); + } else { + TVGLOG("LOADER", "Given mimetype \"%s\" seems incorrect or not supported.", mimeType.c_str()); + delete(loader); + } + } + //Unkown MimeType. Try with the candidates in the order + } else { + for (int i = 0; i < static_cast(FileType::Unknown); i++) { + auto loader = _find(static_cast(i)); + if (loader) { + if (loader->open(data, size, copy)) return shared_ptr(loader); + else delete(loader); + } + } + } + return nullptr; +} + + +shared_ptr LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool copy) +{ + //function is dedicated for raw images only + auto loader = new RawLoader; + if (loader->open(data, w, h, copy)) return shared_ptr(loader); + else delete(loader); + + return nullptr; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgLoader.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgLoader.h new file mode 100644 index 000000000..7acdc943a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgLoader.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_LOADER_H_ +#define _TVG_LOADER_H_ + +#include "tvgLoadModule.h" + +struct LoaderMgr +{ + static bool init(); + static bool term(); + static shared_ptr loader(const string& path, bool* invalid); + static shared_ptr loader(const char* data, uint32_t size, const string& mimeType, bool copy); + static shared_ptr loader(const uint32_t* data, uint32_t w, uint32_t h, bool copy); +}; + +#endif //_TVG_LOADER_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgMath.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgMath.cpp new file mode 100644 index 000000000..cf43490df --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgMath.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgMath.h" + + +bool mathInverse(const Matrix* m, Matrix* out) +{ + auto det = m->e11 * (m->e22 * m->e33 - m->e32 * m->e23) - + m->e12 * (m->e21 * m->e33 - m->e23 * m->e31) + + m->e13 * (m->e21 * m->e32 - m->e22 * m->e31); + + if (mathZero(det)) return false; + + auto invDet = 1 / det; + + out->e11 = (m->e22 * m->e33 - m->e32 * m->e23) * invDet; + out->e12 = (m->e13 * m->e32 - m->e12 * m->e33) * invDet; + out->e13 = (m->e12 * m->e23 - m->e13 * m->e22) * invDet; + out->e21 = (m->e23 * m->e31 - m->e21 * m->e33) * invDet; + out->e22 = (m->e11 * m->e33 - m->e13 * m->e31) * invDet; + out->e23 = (m->e21 * m->e13 - m->e11 * m->e23) * invDet; + out->e31 = (m->e21 * m->e32 - m->e31 * m->e22) * invDet; + out->e32 = (m->e31 * m->e12 - m->e11 * m->e32) * invDet; + out->e33 = (m->e11 * m->e22 - m->e21 * m->e12) * invDet; + + return true; +} + + +Matrix mathMultiply(const Matrix* lhs, const Matrix* rhs) +{ + Matrix m; + + m.e11 = lhs->e11 * rhs->e11 + lhs->e12 * rhs->e21 + lhs->e13 * rhs->e31; + m.e12 = lhs->e11 * rhs->e12 + lhs->e12 * rhs->e22 + lhs->e13 * rhs->e32; + m.e13 = lhs->e11 * rhs->e13 + lhs->e12 * rhs->e23 + lhs->e13 * rhs->e33; + + m.e21 = lhs->e21 * rhs->e11 + lhs->e22 * rhs->e21 + lhs->e23 * rhs->e31; + m.e22 = lhs->e21 * rhs->e12 + lhs->e22 * rhs->e22 + lhs->e23 * rhs->e32; + m.e23 = lhs->e21 * rhs->e13 + lhs->e22 * rhs->e23 + lhs->e23 * rhs->e33; + + m.e31 = lhs->e31 * rhs->e11 + lhs->e32 * rhs->e21 + lhs->e33 * rhs->e31; + m.e32 = lhs->e31 * rhs->e12 + lhs->e32 * rhs->e22 + lhs->e33 * rhs->e32; + m.e33 = lhs->e31 * rhs->e13 + lhs->e32 * rhs->e23 + lhs->e33 * rhs->e33; + + return m; +} + + +void mathRotate(Matrix* m, float degree) +{ + if (degree == 0.0f) return; + + auto radian = degree / 180.0f * (float)M_PI; + auto cosVal = cosf((float)radian); + auto sinVal = sinf((float)radian); + + m->e12 = m->e11 * -sinVal; + m->e11 *= cosVal; + m->e21 = m->e22 * sinVal; + m->e22 *= cosVal; +} + + +bool mathIdentity(const Matrix* m) +{ + if (m->e11 != 1.0f || m->e12 != 0.0f || m->e13 != 0.0f || + m->e21 != 0.0f || m->e22 != 1.0f || m->e23 != 0.0f || + m->e31 != 0.0f || m->e32 != 0.0f || m->e33 != 1.0f) { + return false; + } + return true; +} + + +void mathMultiply(Point* pt, const Matrix* transform) +{ + auto tx = pt->x * transform->e11 + pt->y * transform->e12 + transform->e13; + auto ty = pt->x * transform->e21 + pt->y * transform->e22 + transform->e23; + pt->x = tx; + pt->y = ty; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgMath.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgMath.h new file mode 100644 index 000000000..3f48e3cac --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgMath.h @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_MATH_H_ +#define _TVG_MATH_H_ + + #define _USE_MATH_DEFINES + +#include +#include +#include "tvgCommon.h" + +#define MATH_PI 3.14159265358979323846f +#define MATH_PI2 1.57079632679489661923f + +#define mathMin(x, y) (((x) < (y)) ? (x) : (y)) +#define mathMax(x, y) (((x) > (y)) ? (x) : (y)) + + +bool mathInverse(const Matrix* m, Matrix* out); +Matrix mathMultiply(const Matrix* lhs, const Matrix* rhs); +void mathRotate(Matrix* m, float degree); +bool mathIdentity(const Matrix* m); +void mathMultiply(Point* pt, const Matrix* transform); + + +static inline bool mathZero(float a) +{ + return (fabsf(a) < FLT_EPSILON) ? true : false; +} + + +static inline bool mathEqual(float a, float b) +{ + return (fabsf(a - b) < FLT_EPSILON); +} + + +static inline bool mathEqual(const Matrix& a, const Matrix& b) +{ + if (!mathEqual(a.e11, b.e11) || !mathEqual(a.e12, b.e12) || !mathEqual(a.e13, b.e13) || + !mathEqual(a.e21, b.e21) || !mathEqual(a.e22, b.e22) || !mathEqual(a.e23, b.e23) || + !mathEqual(a.e31, b.e31) || !mathEqual(a.e32, b.e32) || !mathEqual(a.e33, b.e33)) { + return false; + } + return true; +} + + +static inline bool mathRightAngle(const Matrix* m) +{ + auto radian = fabsf(atan2f(m->e21, m->e11)); + if (radian < FLT_EPSILON || mathEqual(radian, float(M_PI_2)) || mathEqual(radian, float(M_PI))) return true; + return false; +} + + +static inline bool mathSkewed(const Matrix* m) +{ + return (fabsf(m->e21 + m->e12) > FLT_EPSILON); +} + + +static inline void mathIdentity(Matrix* m) +{ + m->e11 = 1.0f; + m->e12 = 0.0f; + m->e13 = 0.0f; + m->e21 = 0.0f; + m->e22 = 1.0f; + m->e23 = 0.0f; + m->e31 = 0.0f; + m->e32 = 0.0f; + m->e33 = 1.0f; +} + + +static inline void mathTransform(Matrix* transform, Point* coord) +{ + auto x = coord->x; + auto y = coord->y; + coord->x = x * transform->e11 + y * transform->e12 + transform->e13; + coord->y = x * transform->e21 + y * transform->e22 + transform->e23; +} + + +static inline void mathScale(Matrix* m, float sx, float sy) +{ + m->e11 *= sx; + m->e22 *= sy; +} + + +static inline void mathScaleR(Matrix* m, float x, float y) +{ + if (x != 1.0f) { + m->e11 *= x; + m->e21 *= x; + } + if (y != 1.0f) { + m->e22 *= y; + m->e12 *= y; + } +} + + +static inline void mathTranslate(Matrix* m, float x, float y) +{ + m->e13 += x; + m->e23 += y; +} + + +static inline void mathTranslateR(Matrix* m, float x, float y) +{ + if (x == 0.0f && y == 0.0f) return; + m->e13 += (x * m->e11 + y * m->e12); + m->e23 += (x * m->e21 + y * m->e22); +} + + +static inline void mathLog(Matrix* m) +{ + TVGLOG("MATH", "Matrix: [%f %f %f] [%f %f %f] [%f %f %f]", m->e11, m->e12, m->e13, m->e21, m->e22, m->e23, m->e31, m->e32, m->e33); +} + + +static inline float mathLength(const Point* a, const Point* b) +{ + auto x = b->x - a->x; + auto y = b->y - a->y; + + if (x < 0) x = -x; + if (y < 0) y = -y; + + return (x > y) ? (x + 0.375f * y) : (y + 0.375f * x); +} + + +static inline Point operator-(const Point& lhs, const Point& rhs) +{ + return {lhs.x - rhs.x, lhs.y - rhs.y}; +} + + +static inline Point operator+(const Point& lhs, const Point& rhs) +{ + return {lhs.x + rhs.x, lhs.y + rhs.y}; +} + + +static inline Point operator*(const Point& lhs, float rhs) +{ + return {lhs.x * rhs, lhs.y * rhs}; +} + + +template +static inline T mathLerp(const T &start, const T &end, float t) +{ + return static_cast(start + (end - start) * t); +} + + +#endif //_TVG_MATH_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPaint.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPaint.cpp new file mode 100644 index 000000000..50ba3e6cc --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPaint.cpp @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgMath.h" +#include "tvgPaint.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + + +static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform, RenderTransform* rTransform, RenderRegion& viewport) +{ + /* Access Shape class by Paint is bad... but it's ok still it's an internal usage. */ + auto shape = static_cast(cmpTarget); + + //Rectangle Candidates? + const Point* pts; + if (shape->pathCoords(&pts) != 4) return false; + + if (rTransform) rTransform->update(); + + //No rotation and no skewing + if (pTransform && (!mathRightAngle(&pTransform->m) || mathSkewed(&pTransform->m))) return false; + if (rTransform && (!mathRightAngle(&rTransform->m) || mathSkewed(&rTransform->m))) return false; + + //Perpendicular Rectangle? + auto pt1 = pts + 0; + auto pt2 = pts + 1; + auto pt3 = pts + 2; + auto pt4 = pts + 3; + + if ((mathEqual(pt1->x, pt2->x) && mathEqual(pt2->y, pt3->y) && mathEqual(pt3->x, pt4->x) && mathEqual(pt1->y, pt4->y)) || + (mathEqual(pt2->x, pt3->x) && mathEqual(pt1->y, pt2->y) && mathEqual(pt1->x, pt4->x) && mathEqual(pt3->y, pt4->y))) { + + auto v1 = *pt1; + auto v2 = *pt3; + + if (rTransform) { + mathMultiply(&v1, &rTransform->m); + mathMultiply(&v2, &rTransform->m); + } + + if (pTransform) { + mathMultiply(&v1, &pTransform->m); + mathMultiply(&v2, &pTransform->m); + } + + //sorting + if (v1.x > v2.x) { + auto tmp = v2.x; + v2.x = v1.x; + v1.x = tmp; + } + + if (v1.y > v2.y) { + auto tmp = v2.y; + v2.y = v1.y; + v1.y = tmp; + } + + viewport.x = static_cast(v1.x); + viewport.y = static_cast(v1.y); + viewport.w = static_cast(ceil(v2.x - viewport.x)); + viewport.h = static_cast(ceil(v2.y - viewport.y)); + + if (viewport.w < 0) viewport.w = 0; + if (viewport.h < 0) viewport.h = 0; + + return true; + } + + return false; +} + + +Paint* Paint::Impl::duplicate() +{ + auto ret = smethod->duplicate(); + + //duplicate Transform + if (rTransform) { + ret->pImpl->rTransform = new RenderTransform(); + *ret->pImpl->rTransform = *rTransform; + ret->pImpl->renderFlag |= RenderUpdateFlag::Transform; + } + + ret->pImpl->opacity = opacity; + + if (compData) ret->pImpl->composite(ret, compData->target->duplicate(), compData->method); + + return ret; +} + + +bool Paint::Impl::rotate(float degree) +{ + if (rTransform) { + if (mathEqual(degree, rTransform->degree)) return true; + } else { + if (mathZero(degree)) return true; + rTransform = new RenderTransform(); + } + rTransform->degree = degree; + if (!rTransform->overriding) renderFlag |= RenderUpdateFlag::Transform; + + return true; +} + + +bool Paint::Impl::scale(float factor) +{ + if (rTransform) { + if (mathEqual(factor, rTransform->scale)) return true; + } else { + if (mathEqual(factor, 1.0f)) return true; + rTransform = new RenderTransform(); + } + rTransform->scale = factor; + if (!rTransform->overriding) renderFlag |= RenderUpdateFlag::Transform; + + return true; +} + + +bool Paint::Impl::translate(float x, float y) +{ + if (rTransform) { + if (mathEqual(x, rTransform->x) && mathEqual(y, rTransform->y)) return true; + } else { + if (mathZero(x) && mathZero(y)) return true; + rTransform = new RenderTransform(); + } + rTransform->x = x; + rTransform->y = y; + if (!rTransform->overriding) renderFlag |= RenderUpdateFlag::Transform; + + return true; +} + + +bool Paint::Impl::render(RenderMethod& renderer) +{ + Compositor* cmp = nullptr; + + /* Note: only ClipPath is processed in update() step. + Create a composition image. */ + if (compData && compData->method != CompositeMethod::ClipPath && !(compData->target->pImpl->ctxFlag & ContextFlag::FastTrack)) { + auto region = smethod->bounds(renderer); + if (MASK_REGION_MERGING(compData->method)) region.add(compData->target->pImpl->smethod->bounds(renderer)); + if (region.w == 0 || region.h == 0) return true; + cmp = renderer.target(region, COMPOSITE_TO_COLORSPACE(renderer, compData->method)); + if (renderer.beginComposite(cmp, CompositeMethod::None, 255)) { + compData->target->pImpl->render(renderer); + } + } + + if (cmp) renderer.beginComposite(cmp, compData->method, compData->target->pImpl->opacity); + + renderer.blend(blendMethod); + auto ret = smethod->render(renderer); + + if (cmp) renderer.endComposite(cmp); + + return ret; +} + + +RenderData Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransform, Array& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper) +{ + if (renderFlag & RenderUpdateFlag::Transform) { + if (!rTransform) return nullptr; + if (!rTransform->update()) { + delete(rTransform); + rTransform = nullptr; + } + } + + /* 1. Composition Pre Processing */ + RenderData trd = nullptr; //composite target render data + RenderRegion viewport; + bool compFastTrack = false; + bool childClipper = false; + + if (compData) { + auto target = compData->target; + auto method = compData->method; + target->pImpl->ctxFlag &= ~ContextFlag::FastTrack; //reset + + /* If the transformation has no rotational factors and the ClipPath/Alpha(InvAlpha)Masking involves a simple rectangle, + we can optimize by using the viewport instead of the regular ClipPath/AlphaMasking sequence for improved performance. */ + auto tryFastTrack = false; + if (target->identifier() == TVG_CLASS_ID_SHAPE) { + if (method == CompositeMethod::ClipPath) tryFastTrack = true; + else { + auto shape = static_cast(target); + uint8_t a; + shape->fillColor(nullptr, nullptr, nullptr, &a); + //no gradient fill & no compositions of the composition target. + if (!shape->fill() && !(PP(shape)->compData)) { + if (method == CompositeMethod::AlphaMask && a == 255 && PP(shape)->opacity == 255) tryFastTrack = true; + else if (method == CompositeMethod::InvAlphaMask && (a == 0 || PP(shape)->opacity == 0)) tryFastTrack = true; + } + } + if (tryFastTrack) { + RenderRegion viewport2; + if ((compFastTrack = _compFastTrack(target, pTransform, target->pImpl->rTransform, viewport2))) { + viewport = renderer.viewport(); + viewport2.intersect(viewport); + renderer.viewport(viewport2); + target->pImpl->ctxFlag |= ContextFlag::FastTrack; + } + } + } + if (!compFastTrack) { + childClipper = compData->method == CompositeMethod::ClipPath ? true : false; + trd = target->pImpl->update(renderer, pTransform, clips, 255, pFlag, childClipper); + if (childClipper) clips.push(trd); + } + } + + /* 2. Main Update */ + RenderData rd = nullptr; + auto newFlag = static_cast(pFlag | renderFlag); + renderFlag = RenderUpdateFlag::None; + opacity = MULTIPLY(opacity, this->opacity); + + if (rTransform && pTransform) { + RenderTransform outTransform(pTransform, rTransform); + rd = smethod->update(renderer, &outTransform, clips, opacity, newFlag, clipper); + } else { + auto outTransform = pTransform ? pTransform : rTransform; + rd = smethod->update(renderer, outTransform, clips, opacity, newFlag, clipper); + } + + /* 3. Composition Post Processing */ + if (compFastTrack) renderer.viewport(viewport); + else if (childClipper) clips.pop(); + + return rd; +} + + +bool Paint::Impl::bounds(float* x, float* y, float* w, float* h, bool transformed, bool stroking) +{ + Matrix* m = nullptr; + + //Case: No transformed, quick return! + if (!transformed || !(m = this->transform())) return smethod->bounds(x, y, w, h, stroking); + + //Case: Transformed + auto tx = 0.0f; + auto ty = 0.0f; + auto tw = 0.0f; + auto th = 0.0f; + + auto ret = smethod->bounds(&tx, &ty, &tw, &th, stroking); + + //Get vertices + Point pt[4] = {{tx, ty}, {tx + tw, ty}, {tx + tw, ty + th}, {tx, ty + th}}; + + //New bounding box + auto x1 = FLT_MAX; + auto y1 = FLT_MAX; + auto x2 = -FLT_MAX; + auto y2 = -FLT_MAX; + + //Compute the AABB after transformation + for (int i = 0; i < 4; i++) { + mathMultiply(&pt[i], m); + + if (pt[i].x < x1) x1 = pt[i].x; + if (pt[i].x > x2) x2 = pt[i].x; + if (pt[i].y < y1) y1 = pt[i].y; + if (pt[i].y > y2) y2 = pt[i].y; + } + + if (x) *x = x1; + if (y) *y = y1; + if (w) *w = x2 - x1; + if (h) *h = y2 - y1; + + return ret; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +Paint :: Paint() : pImpl(new Impl()) +{ +} + + +Paint :: ~Paint() +{ + delete(pImpl); +} + + +Result Paint::rotate(float degree) noexcept +{ + if (pImpl->rotate(degree)) return Result::Success; + return Result::FailedAllocation; +} + + +Result Paint::scale(float factor) noexcept +{ + if (pImpl->scale(factor)) return Result::Success; + return Result::FailedAllocation; +} + + +Result Paint::translate(float x, float y) noexcept +{ + if (pImpl->translate(x, y)) return Result::Success; + return Result::FailedAllocation; +} + + +Result Paint::transform(const Matrix& m) noexcept +{ + if (pImpl->transform(m)) return Result::Success; + return Result::FailedAllocation; +} + + +Matrix Paint::transform() noexcept +{ + auto pTransform = pImpl->transform(); + if (pTransform) return *pTransform; + return {1, 0, 0, 0, 1, 0, 0, 0, 1}; +} + + +TVG_DEPRECATED Result Paint::bounds(float* x, float* y, float* w, float* h) const noexcept +{ + return this->bounds(x, y, w, h, false); +} + + +Result Paint::bounds(float* x, float* y, float* w, float* h, bool transform) const noexcept +{ + if (pImpl->bounds(x, y, w, h, transform, true)) return Result::Success; + return Result::InsufficientCondition; +} + + +Paint* Paint::duplicate() const noexcept +{ + return pImpl->duplicate(); +} + + +Result Paint::composite(std::unique_ptr target, CompositeMethod method) noexcept +{ + auto p = target.release(); + if (pImpl->composite(this, p, method)) return Result::Success; + delete(p); + return Result::InvalidArguments; +} + + +CompositeMethod Paint::composite(const Paint** target) const noexcept +{ + if (pImpl->compData) { + if (target) *target = pImpl->compData->target; + return pImpl->compData->method; + } else { + if (target) *target = nullptr; + return CompositeMethod::None; + } +} + + +Result Paint::opacity(uint8_t o) noexcept +{ + if (pImpl->opacity == o) return Result::Success; + + pImpl->opacity = o; + pImpl->renderFlag |= RenderUpdateFlag::Color; + + return Result::Success; +} + + +uint8_t Paint::opacity() const noexcept +{ + return pImpl->opacity; +} + + +uint32_t Paint::identifier() const noexcept +{ + return pImpl->id; +} + + +Result Paint::blend(BlendMethod method) const noexcept +{ + pImpl->blendMethod = method; + + return Result::Success; +} + + +BlendMethod Paint::blend() const noexcept +{ + return pImpl->blendMethod; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPaint.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPaint.h new file mode 100644 index 000000000..ea5878d85 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPaint.h @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_PAINT_H_ +#define _TVG_PAINT_H_ + +#include "tvgRender.h" +#include "tvgMath.h" + +namespace tvg +{ + enum ContextFlag : uint8_t {Invalid = 0, FastTrack = 1}; + + struct Iterator + { + virtual ~Iterator() {} + virtual const Paint* next() = 0; + virtual uint32_t count() = 0; + virtual void begin() = 0; + }; + + struct StrategyMethod + { + virtual ~StrategyMethod() {} + + virtual bool dispose(RenderMethod& renderer) = 0; //return true if the deletion is allowed. + virtual void* update(RenderMethod& renderer, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper) = 0; //Return engine data if it has. + virtual bool render(RenderMethod& renderer) = 0; + virtual bool bounds(float* x, float* y, float* w, float* h, bool stroking) = 0; + virtual RenderRegion bounds(RenderMethod& renderer) const = 0; + virtual Paint* duplicate() = 0; + virtual Iterator* iterator() = 0; + }; + + struct Composite + { + Paint* target; + Paint* source; + CompositeMethod method; + }; + + struct Paint::Impl + { + StrategyMethod* smethod = nullptr; + RenderTransform* rTransform = nullptr; + Composite* compData = nullptr; + BlendMethod blendMethod = BlendMethod::Normal; //uint8_t + uint8_t renderFlag = RenderUpdateFlag::None; + uint8_t ctxFlag = ContextFlag::Invalid; + uint8_t id; + uint8_t opacity = 255; + uint8_t refCnt = 0; + + ~Impl() + { + if (compData) { + delete(compData->target); + free(compData); + } + delete(smethod); + delete(rTransform); + } + + uint8_t ref() + { + if (refCnt == 255) TVGERR("RENDERER", "Corrupted reference count!"); + return (++refCnt); + } + + uint8_t unref() + { + if (refCnt == 0) TVGERR("RENDERER", "Corrupted reference count!"); + return (--refCnt); + } + + void method(StrategyMethod* method) + { + smethod = method; + } + + bool transform(const Matrix& m) + { + if (!rTransform) { + if (mathIdentity(&m)) return true; + rTransform = new RenderTransform(); + if (!rTransform) return false; + } + rTransform->override(m); + renderFlag |= RenderUpdateFlag::Transform; + + return true; + } + + Matrix* transform() + { + if (rTransform) { + rTransform->update(); + return &rTransform->m; + } + return nullptr; + } + + RenderRegion bounds(RenderMethod& renderer) const + { + return smethod->bounds(renderer); + } + + bool dispose(RenderMethod& renderer) + { + if (compData) compData->target->pImpl->dispose(renderer); + return smethod->dispose(renderer); + } + + Iterator* iterator() + { + return smethod->iterator(); + } + + bool composite(Paint* source, Paint* target, CompositeMethod method) + { + //Invalid case + if ((!target && method != CompositeMethod::None) || (target && method == CompositeMethod::None)) return false; + + if (compData) { + delete(compData->target); + //Reset scenario + if (!target && method == CompositeMethod::None) { + free(compData); + compData = nullptr; + return true; + } + } else { + if (!target && method == CompositeMethod::None) return true; + compData = static_cast(calloc(1, sizeof(Composite))); + } + compData->target = target; + compData->source = source; + compData->method = method; + return true; + } + + bool rotate(float degree); + bool scale(float factor); + bool translate(float x, float y); + bool bounds(float* x, float* y, float* w, float* h, bool transformed, bool stroking); + RenderData update(RenderMethod& renderer, const RenderTransform* pTransform, Array& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper = false); + bool render(RenderMethod& renderer); + Paint* duplicate(); + }; + + + template + struct PaintMethod : StrategyMethod + { + T* inst = nullptr; + + PaintMethod(T* _inst) : inst(_inst) {} + ~PaintMethod() {} + + bool bounds(float* x, float* y, float* w, float* h, bool stroking) override + { + return inst->bounds(x, y, w, h, stroking); + } + + RenderRegion bounds(RenderMethod& renderer) const override + { + return inst->bounds(renderer); + } + + bool dispose(RenderMethod& renderer) override + { + return inst->dispose(renderer); + } + + RenderData update(RenderMethod& renderer, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag renderFlag, bool clipper) override + { + return inst->update(renderer, transform, clips, opacity, renderFlag, clipper); + } + + bool render(RenderMethod& renderer) override + { + return inst->render(renderer); + } + + Paint* duplicate() override + { + return inst->duplicate(); + } + + Iterator* iterator() override + { + return inst->iterator(); + } + }; +} + +#endif //_TVG_PAINT_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPicture.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPicture.cpp new file mode 100644 index 000000000..e58d68ea3 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPicture.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgPicture.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +RenderUpdateFlag Picture::Impl::load() +{ + if (loader) { + if (!paint) { + if (auto p = loader->paint()) { + paint = p.release(); + loader->close(); + if (w != loader->w || h != loader->h) { + if (!resizing) { + w = loader->w; + h = loader->h; + } + loader->resize(paint, w, h); + resizing = false; + } + if (paint) return RenderUpdateFlag::None; + } + } else loader->sync(); + + if (!surface) { + if ((surface = loader->bitmap().release())) { + loader->close(); + return RenderUpdateFlag::Image; + } + } + } + return RenderUpdateFlag::None; +} + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +Picture::Picture() : pImpl(new Impl(this)) +{ + Paint::pImpl->id = TVG_CLASS_ID_PICTURE; + Paint::pImpl->method(new PaintMethod(pImpl)); +} + + +Picture::~Picture() +{ + delete(pImpl); +} + + +unique_ptr Picture::gen() noexcept +{ + return unique_ptr(new Picture); +} + + +uint32_t Picture::identifier() noexcept +{ + return TVG_CLASS_ID_PICTURE; +} + + +Result Picture::load(const std::string& path) noexcept +{ + if (path.empty()) return Result::InvalidArguments; + + return pImpl->load(path); +} + + +Result Picture::load(const char* data, uint32_t size, const string& mimeType, bool copy) noexcept +{ + if (!data || size <= 0) return Result::InvalidArguments; + + return pImpl->load(data, size, mimeType, copy); +} + + +TVG_DEPRECATED Result Picture::load(const char* data, uint32_t size, bool copy) noexcept +{ + return load(data, size, "", copy); +} + + +Result Picture::load(uint32_t* data, uint32_t w, uint32_t h, bool copy) noexcept +{ + if (!data || w <= 0 || h <= 0) return Result::InvalidArguments; + + return pImpl->load(data, w, h, copy); +} + + +Result Picture::size(float w, float h) noexcept +{ + if (pImpl->size(w, h)) return Result::Success; + return Result::InsufficientCondition; +} + + +Result Picture::size(float* w, float* h) const noexcept +{ + if (!pImpl->loader) return Result::InsufficientCondition; + if (w) *w = pImpl->w; + if (h) *h = pImpl->h; + return Result::Success; +} + + +Result Picture::mesh(const Polygon* triangles, uint32_t triangleCnt) noexcept +{ + if (!triangles && triangleCnt > 0) return Result::InvalidArguments; + if (triangles && triangleCnt == 0) return Result::InvalidArguments; + + pImpl->mesh(triangles, triangleCnt); + return Result::Success; +} + + +uint32_t Picture::mesh(const Polygon** triangles) const noexcept +{ + if (triangles) *triangles = pImpl->rm.triangles; + return pImpl->rm.triangleCnt; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPicture.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPicture.h new file mode 100644 index 000000000..a9a52a98f --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgPicture.h @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_PICTURE_IMPL_H_ +#define _TVG_PICTURE_IMPL_H_ + +#include +#include "tvgPaint.h" +#include "tvgLoader.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +struct PictureIterator : Iterator +{ + Paint* paint = nullptr; + Paint* ptr = nullptr; + + PictureIterator(Paint* p) : paint(p) {} + + const Paint* next() override + { + if (!ptr) ptr = paint; + else ptr = nullptr; + return ptr; + } + + uint32_t count() override + { + if (paint) return 1; + else return 0; + } + + void begin() override + { + ptr = nullptr; + } +}; + + +struct Picture::Impl +{ + shared_ptr loader = nullptr; + + Paint* paint = nullptr; //vector picture uses + Surface* surface = nullptr; //bitmap picture uses + RenderData rd = nullptr; //engine data + float w = 0, h = 0; + RenderMesh rm; //mesh data + Picture* picture = nullptr; + bool resizing = false; + bool needComp = false; //need composition + + Impl(Picture* p) : picture(p) + { + } + + ~Impl() + { + delete(paint); + delete(surface); + } + + bool dispose(RenderMethod& renderer) + { + if (paint) paint->pImpl->dispose(renderer); + else if (surface) renderer.dispose(rd); + rd = nullptr; + return true; + } + + RenderTransform resizeTransform(const RenderTransform* pTransform) + { + //Overriding Transformation by the desired image size + auto sx = w / loader->w; + auto sy = h / loader->h; + auto scale = sx < sy ? sx : sy; + + RenderTransform tmp; + tmp.m = {scale, 0, 0, 0, scale, 0, 0, 0, 1}; + + if (!pTransform) return tmp; + else return RenderTransform(pTransform, &tmp); + } + + bool needComposition(uint8_t opacity) + { + //In this case, paint(scene) would try composition itself. + if (opacity < 255) return false; + + //Composition test + const Paint* target; + auto method = picture->composite(&target); + if (!target || method == tvg::CompositeMethod::ClipPath) return false; + if (target->pImpl->opacity == 255 || target->pImpl->opacity == 0) return false; + + return true; + } + + RenderData update(RenderMethod &renderer, const RenderTransform* pTransform, Array& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper) + { + auto flag = load(); + + if (surface) { + auto transform = resizeTransform(pTransform); + rd = renderer.prepare(surface, &rm, rd, &transform, clips, opacity, static_cast(pFlag | flag)); + } else if (paint) { + if (resizing) { + loader->resize(paint, w, h); + resizing = false; + } + needComp = needComposition(opacity) ? true : false; + rd = paint->pImpl->update(renderer, pTransform, clips, opacity, static_cast(pFlag | flag), clipper); + } + return rd; + } + + bool render(RenderMethod &renderer) + { + bool ret = false; + if (surface) return renderer.renderImage(rd); + else if (paint) { + Compositor* cmp = nullptr; + if (needComp) { + cmp = renderer.target(bounds(renderer), renderer.colorSpace()); + renderer.beginComposite(cmp, CompositeMethod::None, 255); + } + ret = paint->pImpl->render(renderer); + if (cmp) renderer.endComposite(cmp); + } + return ret; + } + + bool size(float w, float h) + { + this->w = w; + this->h = h; + resizing = true; + return true; + } + + bool bounds(float* x, float* y, float* w, float* h, bool stroking) + { + if (rm.triangleCnt > 0) { + auto triangles = rm.triangles; + auto min = triangles[0].vertex[0].pt; + auto max = triangles[0].vertex[0].pt; + + for (uint32_t i = 0; i < rm.triangleCnt; ++i) { + if (triangles[i].vertex[0].pt.x < min.x) min.x = triangles[i].vertex[0].pt.x; + else if (triangles[i].vertex[0].pt.x > max.x) max.x = triangles[i].vertex[0].pt.x; + if (triangles[i].vertex[0].pt.y < min.y) min.y = triangles[i].vertex[0].pt.y; + else if (triangles[i].vertex[0].pt.y > max.y) max.y = triangles[i].vertex[0].pt.y; + + if (triangles[i].vertex[1].pt.x < min.x) min.x = triangles[i].vertex[1].pt.x; + else if (triangles[i].vertex[1].pt.x > max.x) max.x = triangles[i].vertex[1].pt.x; + if (triangles[i].vertex[1].pt.y < min.y) min.y = triangles[i].vertex[1].pt.y; + else if (triangles[i].vertex[1].pt.y > max.y) max.y = triangles[i].vertex[1].pt.y; + + if (triangles[i].vertex[2].pt.x < min.x) min.x = triangles[i].vertex[2].pt.x; + else if (triangles[i].vertex[2].pt.x > max.x) max.x = triangles[i].vertex[2].pt.x; + if (triangles[i].vertex[2].pt.y < min.y) min.y = triangles[i].vertex[2].pt.y; + else if (triangles[i].vertex[2].pt.y > max.y) max.y = triangles[i].vertex[2].pt.y; + } + if (x) *x = min.x; + if (y) *y = min.y; + if (w) *w = max.x - min.x; + if (h) *h = max.y - min.y; + } else { + if (x) *x = 0; + if (y) *y = 0; + if (w) *w = this->w; + if (h) *h = this->h; + } + return true; + } + + RenderRegion bounds(RenderMethod& renderer) + { + if (rd) return renderer.region(rd); + if (paint) return paint->pImpl->bounds(renderer); + return {0, 0, 0, 0}; + } + + Result load(const string& path) + { + if (paint || surface) return Result::InsufficientCondition; + if (loader) loader->close(); + bool invalid; //Invalid Path + loader = LoaderMgr::loader(path, &invalid); + if (!loader) { + if (invalid) return Result::InvalidArguments; + return Result::NonSupport; + } + if (!loader->read()) return Result::Unknown; + w = loader->w; + h = loader->h; + return Result::Success; + } + + Result load(const char* data, uint32_t size, const string& mimeType, bool copy) + { + if (paint || surface) return Result::InsufficientCondition; + if (loader) loader->close(); + loader = LoaderMgr::loader(data, size, mimeType, copy); + if (!loader) return Result::NonSupport; + if (!loader->read()) return Result::Unknown; + w = loader->w; + h = loader->h; + return Result::Success; + } + + Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy) + { + if (paint || surface) return Result::InsufficientCondition; + if (loader) loader->close(); + loader = LoaderMgr::loader(data, w, h, copy); + if (!loader) return Result::FailedAllocation; + this->w = loader->w; + this->h = loader->h; + return Result::Success; + } + + void mesh(const Polygon* triangles, const uint32_t triangleCnt) + { + if (triangles && triangleCnt > 0) { + this->rm.triangleCnt = triangleCnt; + this->rm.triangles = (Polygon*)malloc(sizeof(Polygon) * triangleCnt); + memcpy(this->rm.triangles, triangles, sizeof(Polygon) * triangleCnt); + } else { + free(this->rm.triangles); + this->rm.triangles = nullptr; + this->rm.triangleCnt = 0; + } + } + + Paint* duplicate() + { + load(); + + auto ret = Picture::gen(); + + auto dup = ret.get()->pImpl; + if (paint) dup->paint = paint->duplicate(); + + dup->loader = loader; + if (surface) { + dup->surface = new Surface; + *dup->surface = *surface; + //TODO: A dupilcation is not a proxy... it needs copy of the pixel data? + dup->surface->owner = false; + } + dup->w = w; + dup->h = h; + dup->resizing = resizing; + + if (rm.triangleCnt > 0) { + dup->rm.triangleCnt = rm.triangleCnt; + dup->rm.triangles = (Polygon*)malloc(sizeof(Polygon) * rm.triangleCnt); + memcpy(dup->rm.triangles, rm.triangles, sizeof(Polygon) * rm.triangleCnt); + } + + return ret.release(); + } + + Iterator* iterator() + { + load(); + return new PictureIterator(paint); + } + + uint32_t* data(uint32_t* w, uint32_t* h) + { + //Try it, If not loaded yet. + load(); + + if (loader) { + if (w) *w = static_cast(loader->w); + if (h) *h = static_cast(loader->h); + } else { + if (w) *w = 0; + if (h) *h = 0; + } + if (surface) return surface->buf32; + else return nullptr; + } + + RenderUpdateFlag load(); +}; + +#endif //_TVG_PICTURE_IMPL_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRawLoader.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRawLoader.cpp new file mode 100644 index 000000000..b20c7fda8 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRawLoader.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include +#include +#include "tvgLoader.h" +#include "tvgRawLoader.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +RawLoader::~RawLoader() +{ + if (copy && content) { + free((void*)content); + content = nullptr; + } +} + + +bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) +{ + if (!data || w == 0 || h == 0) return false; + + this->w = (float)w; + this->h = (float)h; + this->copy = copy; + + if (copy) { + content = (uint32_t*)malloc(sizeof(uint32_t) * w * h); + if (!content) return false; + memcpy((void*)content, data, sizeof(uint32_t) * w * h); + } + else content = const_cast(data); + + cs = ColorSpace::ARGB8888; + + return true; +} + + +bool RawLoader::read() +{ + return true; +} + + +bool RawLoader::close() +{ + return true; +} + + +unique_ptr RawLoader::bitmap() +{ + if (!content) return nullptr; + + //TODO: It's better to keep this surface instance in the loader side + auto surface = new Surface; + surface->buf32 = content; + surface->stride = static_cast(w); + surface->w = static_cast(w); + surface->h = static_cast(h); + surface->cs = cs; + surface->channelSize = sizeof(uint32_t); + surface->premultiplied = false; + surface->owner = true; + + return unique_ptr(surface); +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRawLoader.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRawLoader.h new file mode 100644 index 000000000..bc3851f55 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRawLoader.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_RAW_LOADER_H_ +#define _TVG_RAW_LOADER_H_ + +class RawLoader : public LoadModule +{ +public: + uint32_t* content = nullptr; + bool copy = false; + + ~RawLoader(); + + using LoadModule::open; + bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) override; + bool read() override; + bool close() override; + + unique_ptr bitmap() override; +}; + + +#endif //_TVG_RAW_LOADER_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRender.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRender.cpp new file mode 100644 index 000000000..9994c8cbb --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRender.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgMath.h" +#include "tvgRender.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +void RenderTransform::override(const Matrix& m) +{ + this->m = m; + overriding = true; +} + + +bool RenderTransform::update() +{ + if (overriding) return true; + + //Init Status + if (mathZero(x) && mathZero(y) && mathZero(degree) && mathEqual(scale, 1)) return false; + + mathIdentity(&m); + + mathScale(&m, scale, scale); + + if (!mathZero(degree)) mathRotate(&m, degree); + + mathTranslate(&m, x, y); + + return true; +} + + +RenderTransform::RenderTransform() +{ +} + + +RenderTransform::RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs) +{ + m = mathMultiply(&lhs->m, &rhs->m); +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRender.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRender.h new file mode 100644 index 000000000..d95c37cc0 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgRender.h @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_RENDER_H_ +#define _TVG_RENDER_H_ + +#include "tvgCommon.h" +#include "tvgArray.h" + +namespace tvg +{ + +using RenderData = void*; +using pixel_t = uint32_t; + +enum RenderUpdateFlag : uint8_t {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 255}; + +struct Surface; + +enum ColorSpace +{ + ABGR8888 = 0, //The channels are joined in the order: alpha, blue, green, red. Colors are alpha-premultiplied. + ARGB8888, //The channels are joined in the order: alpha, red, green, blue. Colors are alpha-premultiplied. + ABGR8888S, //The channels are joined in the order: alpha, blue, green, red. Colors are un-alpha-premultiplied. + ARGB8888S, //The channels are joined in the order: alpha, red, green, blue. Colors are un-alpha-premultiplied. + Grayscale8, //One single channel data. + Unsupported //TODO: Change to the default, At the moment, we put it in the last to align with SwCanvas::Colorspace. +}; + +struct Surface +{ + union { + pixel_t* data; //system based data pointer + uint32_t* buf32; //for explicit 32bits channels + uint8_t* buf8; //for explicit 8bits grayscale + }; + uint32_t stride; + uint32_t w, h; + ColorSpace cs; + uint8_t channelSize; + + bool premultiplied; //Alpha-premultiplied + bool owner; //Only owner could modify the buffer +}; + +struct Compositor +{ + CompositeMethod method; + uint8_t opacity; +}; + +struct RenderMesh +{ + Polygon* triangles = nullptr; + uint32_t triangleCnt = 0; + + ~RenderMesh() + { + free(triangles); + } +}; + +struct RenderRegion +{ + int32_t x, y, w, h; + + void intersect(const RenderRegion& rhs) + { + auto x1 = x + w; + auto y1 = y + h; + auto x2 = rhs.x + rhs.w; + auto y2 = rhs.y + rhs.h; + + x = (x > rhs.x) ? x : rhs.x; + y = (y > rhs.y) ? y : rhs.y; + w = ((x1 < x2) ? x1 : x2) - x; + h = ((y1 < y2) ? y1 : y2) - y; + + if (w < 0) w = 0; + if (h < 0) h = 0; + } + + void add(const RenderRegion& rhs) + { + if (rhs.x < x) { + w += (x - rhs.x); + x = rhs.x; + } + if (rhs.y < y) { + h += (y - rhs.y); + y = rhs.y; + } + if (rhs.x + rhs.w > x + w) w = (rhs.x + rhs.w) - x; + if (rhs.y + rhs.h > y + h) h = (rhs.y + rhs.h) - y; + } +}; + +struct RenderTransform +{ + Matrix m; //3x3 Matrix Elements + float x = 0.0f; + float y = 0.0f; + float degree = 0.0f; //rotation degree + float scale = 1.0f; //scale factor + bool overriding = false; //user transform? + + bool update(); + void override(const Matrix& m); + + RenderTransform(); + RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs); +}; + +struct RenderStroke +{ + float width = 0.0f; + uint8_t color[4] = {0, 0, 0, 0}; + Fill *fill = nullptr; + float* dashPattern = nullptr; + uint32_t dashCnt = 0; + float dashOffset = 0.0f; + StrokeCap cap = StrokeCap::Square; + StrokeJoin join = StrokeJoin::Bevel; + float miterlimit = 4.0f; + bool strokeFirst = false; + + struct { + float begin = 0.0f; + float end = 1.0f; + } trim; + + ~RenderStroke() + { + free(dashPattern); + delete(fill); + } +}; + +struct RenderShape +{ + struct + { + Array cmds; + Array pts; + } path; + + Fill *fill = nullptr; + RenderStroke *stroke = nullptr; + uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a + FillRule rule = FillRule::Winding; + + ~RenderShape() + { + delete(fill); + delete(stroke); + } + + void fillColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const + { + if (r) *r = color[0]; + if (g) *g = color[1]; + if (b) *b = color[2]; + if (a) *a = color[3]; + } + + float strokeWidth() const + { + if (!stroke) return 0; + return stroke->width; + } + + bool strokeTrim() const + { + if (!stroke) return false; + if (stroke->trim.begin == 0.0f && stroke->trim.end == 1.0f) return false; + if (stroke->trim.begin == 1.0f && stroke->trim.end == 0.0f) return false; + return true; + } + + bool strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const + { + if (!stroke) return false; + + if (r) *r = stroke->color[0]; + if (g) *g = stroke->color[1]; + if (b) *b = stroke->color[2]; + if (a) *a = stroke->color[3]; + + return true; + } + + const Fill* strokeFill() const + { + if (!stroke) return nullptr; + return stroke->fill; + } + + uint32_t strokeDash(const float** dashPattern, float* offset) const + { + if (!stroke) return 0; + if (dashPattern) *dashPattern = stroke->dashPattern; + if (offset) *offset = stroke->dashOffset; + return stroke->dashCnt; + } + + StrokeCap strokeCap() const + { + if (!stroke) return StrokeCap::Square; + return stroke->cap; + } + + StrokeJoin strokeJoin() const + { + if (!stroke) return StrokeJoin::Bevel; + return stroke->join; + } + + float strokeMiterlimit() const + { + if (!stroke) return 4.0f; + + return stroke->miterlimit;; + } +}; + +class RenderMethod +{ +public: + virtual ~RenderMethod() {} + virtual RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) = 0; + virtual RenderData prepare(const Array& scene, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags) = 0; + virtual RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags) = 0; + virtual bool preRender() = 0; + virtual bool renderShape(RenderData data) = 0; + virtual bool renderImage(RenderData data) = 0; + virtual bool postRender() = 0; + virtual bool dispose(RenderData data) = 0; + virtual RenderRegion region(RenderData data) = 0; + virtual RenderRegion viewport() = 0; + virtual bool viewport(const RenderRegion& vp) = 0; + virtual bool blend(BlendMethod method) = 0; + virtual ColorSpace colorSpace() = 0; + + virtual bool clear() = 0; + virtual bool sync() = 0; + + virtual Compositor* target(const RenderRegion& region, ColorSpace cs) = 0; + virtual bool beginComposite(Compositor* cmp, CompositeMethod method, uint8_t opacity) = 0; + virtual bool endComposite(Compositor* cmp) = 0; +}; + +static inline bool MASK_REGION_MERGING(CompositeMethod method) +{ + switch(method) { + case CompositeMethod::AlphaMask: + case CompositeMethod::InvAlphaMask: + case CompositeMethod::LumaMask: + case CompositeMethod::InvLumaMask: + case CompositeMethod::SubtractMask: + case CompositeMethod::IntersectMask: + return false; + //these might expand the rendering region + case CompositeMethod::AddMask: + case CompositeMethod::DifferenceMask: + return true; + default: + TVGERR("RENDERER", "Unsupported Composite Method! = %d", (int)method); + return false; + } +} + +static inline uint8_t CHANNEL_SIZE(ColorSpace cs) +{ + switch(cs) { + case ColorSpace::ABGR8888: + case ColorSpace::ABGR8888S: + case ColorSpace::ARGB8888: + case ColorSpace::ARGB8888S: + return sizeof(uint32_t); + case ColorSpace::Grayscale8: + return sizeof(uint8_t); + case ColorSpace::Unsupported: + default: + TVGERR("RENDERER", "Unsupported Channel Size! = %d", (int)cs); + return 0; + } +} + +static inline ColorSpace COMPOSITE_TO_COLORSPACE(RenderMethod& renderer, CompositeMethod method) +{ + switch(method) { + case CompositeMethod::AlphaMask: + case CompositeMethod::InvAlphaMask: + case CompositeMethod::AddMask: + case CompositeMethod::DifferenceMask: + case CompositeMethod::SubtractMask: + case CompositeMethod::IntersectMask: + return ColorSpace::Grayscale8; + //TODO: Optimize Luma/InvLuma colorspace to Grayscale8 + case CompositeMethod::LumaMask: + case CompositeMethod::InvLumaMask: + return renderer.colorSpace(); + default: + TVGERR("RENDERER", "Unsupported Composite Size! = %d", (int)method); + return ColorSpace::Unsupported; + } +} + +static inline uint8_t MULTIPLY(uint8_t c, uint8_t a) +{ + return (((c) * (a) + 0xff) >> 8); +} + + +} + +#endif //_TVG_RENDER_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSaveModule.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSaveModule.h new file mode 100644 index 000000000..cff1a81db --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSaveModule.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_SAVE_MODULE_H_ +#define _TVG_SAVE_MODULE_H_ + +#include "tvgIteratorAccessor.h" + +namespace tvg +{ + +class SaveModule +{ +public: + virtual ~SaveModule() {} + + virtual bool save(Paint* paint, const string& path, bool compress) = 0; + virtual bool close() = 0; +}; + +} + +#endif //_TVG_SAVE_MODULE_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSaver.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSaver.cpp new file mode 100644 index 000000000..4fd9848e3 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSaver.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgCommon.h" +#include "tvgSaveModule.h" + +#ifdef THORVG_TVG_SAVER_SUPPORT + #include "tvgTvgSaver.h" +#endif + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +struct Saver::Impl +{ + SaveModule* saveModule = nullptr; + ~Impl() + { + delete(saveModule); + } +}; + + +static SaveModule* _find(FileType type) +{ + switch(type) { + case FileType::Tvg: { +#ifdef THORVG_TVG_SAVER_SUPPORT + return new TvgSaver; +#endif + break; + } + default: { + break; + } + } + +#ifdef THORVG_LOG_ENABLED + const char *format; + switch(type) { + case FileType::Tvg: { + format = "TVG"; + break; + } + default: { + format = "???"; + break; + } + } + TVGLOG("SAVER", "%s format is not supported", format); +#endif + return nullptr; +} + + +static SaveModule* _find(const string& path) +{ + auto ext = path.substr(path.find_last_of(".") + 1); + if (!ext.compare("tvg")) { + return _find(FileType::Tvg); + } + return nullptr; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +Saver::Saver() : pImpl(new Impl()) +{ +} + + +Saver::~Saver() +{ + delete(pImpl); +} + + +Result Saver::save(std::unique_ptr paint, const string& path, bool compress) noexcept +{ + auto p = paint.release(); + if (!p) return Result::MemoryCorruption; + + //Already on saving an other resource. + if (pImpl->saveModule) { + delete(p); + return Result::InsufficientCondition; + } + + if (auto saveModule = _find(path)) { + if (saveModule->save(p, path, compress)) { + pImpl->saveModule = saveModule; + return Result::Success; + } else { + delete(p); + delete(saveModule); + return Result::Unknown; + } + } + delete(p); + return Result::NonSupport; +} + + +Result Saver::sync() noexcept +{ + if (!pImpl->saveModule) return Result::InsufficientCondition; + pImpl->saveModule->close(); + delete(pImpl->saveModule); + pImpl->saveModule = nullptr; + + return Result::Success; +} + + +unique_ptr Saver::gen() noexcept +{ + return unique_ptr(new Saver); +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgScene.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgScene.cpp new file mode 100644 index 000000000..122cd5354 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgScene.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgScene.h" + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +Scene::Scene() : pImpl(new Impl(this)) +{ + Paint::pImpl->id = TVG_CLASS_ID_SCENE; + Paint::pImpl->method(new PaintMethod(pImpl)); +} + + +Scene::~Scene() +{ + delete(pImpl); +} + + +unique_ptr Scene::gen() noexcept +{ + return unique_ptr(new Scene); +} + + +uint32_t Scene::identifier() noexcept +{ + return TVG_CLASS_ID_SCENE; +} + + +Result Scene::push(unique_ptr paint) noexcept +{ + auto p = paint.release(); + if (!p) return Result::MemoryCorruption; + PP(p)->ref(); + pImpl->paints.push_back(p); + + return Result::Success; +} + + +Result Scene::reserve(TVG_UNUSED uint32_t size) noexcept +{ + return Result::NonSupport; +} + + +Result Scene::clear(bool free) noexcept +{ + pImpl->clear(free); + + return Result::Success; +} + + +list& Scene::paints() noexcept +{ + return pImpl->paints; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgScene.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgScene.h new file mode 100644 index 000000000..f626e993e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgScene.h @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_SCENE_IMPL_H_ +#define _TVG_SCENE_IMPL_H_ + +#include +#include "tvgPaint.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +struct SceneIterator : Iterator +{ + list* paints; + list::iterator itr; + + SceneIterator(list* p) : paints(p) + { + begin(); + } + + const Paint* next() override + { + if (itr == paints->end()) return nullptr; + auto paint = *itr; + ++itr; + return paint; + } + + uint32_t count() override + { + return paints->size(); + } + + void begin() override + { + itr = paints->begin(); + } +}; + +struct Scene::Impl +{ + list paints; + RenderMethod* renderer = nullptr; //keep it for explicit clear + RenderData rd = nullptr; + Scene* scene = nullptr; + uint8_t opacity; //for composition + bool needComp; //composite or not + + Impl(Scene* s) : scene(s) + { + } + + ~Impl() + { + for (auto paint : paints) { + if (paint->pImpl->unref() == 0) delete(paint); + } + } + + bool dispose(RenderMethod& renderer) + { + for (auto paint : paints) { + paint->pImpl->dispose(renderer); + } + + renderer.dispose(rd); + this->renderer = nullptr; + this->rd = nullptr; + + return true; + } + + bool needComposition(uint8_t opacity) + { + if (opacity == 0 || paints.empty()) return false; + + //Masking may require composition (even if opacity == 255) + auto compMethod = scene->composite(nullptr); + if (compMethod != CompositeMethod::None && compMethod != CompositeMethod::ClipPath) return true; + + //Blending may require composition (even if opacity == 255) + if (scene->blend() != BlendMethod::Normal) return true; + + //Half translucent requires intermediate composition. + if (opacity == 255) return false; + + //If scene has several children or only scene, it may require composition. + //OPTIMIZE: the bitmap type of the picture would not need the composition. + //OPTIMIZE: a single paint of a scene would not need the composition. + if (paints.size() == 1 && paints.front()->identifier() == TVG_CLASS_ID_SHAPE) return false; + + return true; + } + + RenderData update(RenderMethod &renderer, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flag, bool clipper) + { + if ((needComp = needComposition(opacity))) { + /* Overriding opacity value. If this scene is half-translucent, + It must do intermeidate composition with that opacity value. */ + this->opacity = opacity; + opacity = 255; + } + + this->renderer = &renderer; + + if (clipper) { + Array rds; + rds.reserve(paints.size()); + for (auto paint : paints) { + rds.push(paint->pImpl->update(renderer, transform, clips, opacity, flag, true)); + } + rd = renderer.prepare(rds, rd, transform, clips, opacity, flag); + return rd; + } else { + for (auto paint : paints) { + paint->pImpl->update(renderer, transform, clips, opacity, flag, false); + } + return nullptr; + } + } + + bool render(RenderMethod& renderer) + { + Compositor* cmp = nullptr; + + if (needComp) { + cmp = renderer.target(bounds(renderer), renderer.colorSpace()); + renderer.beginComposite(cmp, CompositeMethod::None, opacity); + } + + for (auto paint : paints) { + if (!paint->pImpl->render(renderer)) return false; + } + + if (cmp) renderer.endComposite(cmp); + + return true; + } + + RenderRegion bounds(RenderMethod& renderer) const + { + if (paints.empty()) return {0, 0, 0, 0}; + + int32_t x1 = INT32_MAX; + int32_t y1 = INT32_MAX; + int32_t x2 = 0; + int32_t y2 = 0; + + for (auto paint : paints) { + auto region = paint->pImpl->bounds(renderer); + + //Merge regions + if (region.x < x1) x1 = region.x; + if (x2 < region.x + region.w) x2 = (region.x + region.w); + if (region.y < y1) y1 = region.y; + if (y2 < region.y + region.h) y2 = (region.y + region.h); + } + + return {x1, y1, (x2 - x1), (y2 - y1)}; + } + + bool bounds(float* px, float* py, float* pw, float* ph, bool stroking) + { + if (paints.empty()) return false; + + auto x1 = FLT_MAX; + auto y1 = FLT_MAX; + auto x2 = -FLT_MAX; + auto y2 = -FLT_MAX; + + for (auto paint : paints) { + auto x = FLT_MAX; + auto y = FLT_MAX; + auto w = 0.0f; + auto h = 0.0f; + + if (!P(paint)->bounds(&x, &y, &w, &h, true, stroking)) continue; + + //Merge regions + if (x < x1) x1 = x; + if (x2 < x + w) x2 = (x + w); + if (y < y1) y1 = y; + if (y2 < y + h) y2 = (y + h); + } + + if (px) *px = x1; + if (py) *py = y1; + if (pw) *pw = (x2 - x1); + if (ph) *ph = (y2 - y1); + + return true; + } + + Paint* duplicate() + { + auto ret = Scene::gen(); + + auto dup = ret.get()->pImpl; + + for (auto paint : paints) { + auto cdup = paint->duplicate(); + P(cdup)->ref(); + dup->paints.push_back(cdup); + } + + return ret.release(); + } + + void clear(bool free) + { + auto dispose = renderer ? true : false; + + for (auto paint : paints) { + if (dispose) free &= P(paint)->dispose(*renderer); + if (P(paint)->unref() == 0 && free) delete(paint); + } + paints.clear(); + renderer = nullptr; + } + + Iterator* iterator() + { + return new SceneIterator(&paints); + } +}; + +#endif //_TVG_SCENE_IMPL_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgShape.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgShape.cpp new file mode 100644 index 000000000..e43c07f2f --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgShape.cpp @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgMath.h" +#include "tvgShape.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ +constexpr auto PATH_KAPPA = 0.552284f; + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +Shape :: Shape() : pImpl(new Impl(this)) +{ + Paint::pImpl->id = TVG_CLASS_ID_SHAPE; + Paint::pImpl->method(new PaintMethod(pImpl)); +} + + +Shape :: ~Shape() +{ + delete(pImpl); +} + + +unique_ptr Shape::gen() noexcept +{ + return unique_ptr(new Shape); +} + + +uint32_t Shape::identifier() noexcept +{ + return TVG_CLASS_ID_SHAPE; +} + + +Result Shape::reset() noexcept +{ + pImpl->rs.path.cmds.clear(); + pImpl->rs.path.pts.clear(); + + pImpl->flag = RenderUpdateFlag::Path; + + return Result::Success; +} + + +uint32_t Shape::pathCommands(const PathCommand** cmds) const noexcept +{ + if (!cmds) return 0; + + *cmds = pImpl->rs.path.cmds.data; + return pImpl->rs.path.cmds.count; +} + + +uint32_t Shape::pathCoords(const Point** pts) const noexcept +{ + if (!pts) return 0; + + *pts = pImpl->rs.path.pts.data; + return pImpl->rs.path.pts.count; +} + + +Result Shape::appendPath(const PathCommand *cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt) noexcept +{ + if (cmdCnt == 0 || ptsCnt == 0 || !cmds || !pts) return Result::InvalidArguments; + + pImpl->grow(cmdCnt, ptsCnt); + pImpl->append(cmds, cmdCnt, pts, ptsCnt); + + return Result::Success; +} + + +Result Shape::moveTo(float x, float y) noexcept +{ + pImpl->moveTo(x, y); + + return Result::Success; +} + + +Result Shape::lineTo(float x, float y) noexcept +{ + pImpl->lineTo(x, y); + + return Result::Success; +} + + +Result Shape::cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) noexcept +{ + pImpl->cubicTo(cx1, cy1, cx2, cy2, x, y); + + return Result::Success; +} + + +Result Shape::close() noexcept +{ + pImpl->close(); + + return Result::Success; +} + + +Result Shape::appendCircle(float cx, float cy, float rx, float ry) noexcept +{ + auto rxKappa = rx * PATH_KAPPA; + auto ryKappa = ry * PATH_KAPPA; + + pImpl->grow(6, 13); + pImpl->moveTo(cx, cy - ry); + pImpl->cubicTo(cx + rxKappa, cy - ry, cx + rx, cy - ryKappa, cx + rx, cy); + pImpl->cubicTo(cx + rx, cy + ryKappa, cx + rxKappa, cy + ry, cx, cy + ry); + pImpl->cubicTo(cx - rxKappa, cy + ry, cx - rx, cy + ryKappa, cx - rx, cy); + pImpl->cubicTo(cx - rx, cy - ryKappa, cx - rxKappa, cy - ry, cx, cy - ry); + pImpl->close(); + + return Result::Success; +} + +Result Shape::appendArc(float cx, float cy, float radius, float startAngle, float sweep, bool pie) noexcept +{ + //just circle + if (sweep >= 360.0f || sweep <= -360.0f) return appendCircle(cx, cy, radius, radius); + + startAngle = (startAngle * MATH_PI) / 180.0f; + sweep = sweep * MATH_PI / 180.0f; + + auto nCurves = ceil(fabsf(sweep / MATH_PI2)); + auto sweepSign = (sweep < 0 ? -1 : 1); + auto fract = fmodf(sweep, MATH_PI2); + fract = (mathZero(fract)) ? MATH_PI2 * sweepSign : fract; + + //Start from here + Point start = {radius * cosf(startAngle), radius * sinf(startAngle)}; + + if (pie) { + pImpl->moveTo(cx, cy); + pImpl->lineTo(start.x + cx, start.y + cy); + } else { + pImpl->moveTo(start.x + cx, start.y + cy); + } + + for (int i = 0; i < nCurves; ++i) { + auto endAngle = startAngle + ((i != nCurves - 1) ? float(M_PI_2) * sweepSign : fract); + Point end = {radius * cosf(endAngle), radius * sinf(endAngle)}; + + //variables needed to calculate bezier control points + + //get bezier control points using article: + //(http://itc.ktu.lt/index.php/ITC/article/view/11812/6479) + auto ax = start.x; + auto ay = start.y; + auto bx = end.x; + auto by = end.y; + auto q1 = ax * ax + ay * ay; + auto q2 = ax * bx + ay * by + q1; + auto k2 = (4.0f/3.0f) * ((sqrtf(2 * q1 * q2) - q2) / (ax * by - ay * bx)); + + start = end; //Next start point is the current end point + + end.x += cx; + end.y += cy; + + Point ctrl1 = {ax - k2 * ay + cx, ay + k2 * ax + cy}; + Point ctrl2 = {bx + k2 * by + cx, by - k2 * bx + cy}; + + pImpl->cubicTo(ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, end.x, end.y); + + startAngle = endAngle; + } + + if (pie) pImpl->close(); + + return Result::Success; +} + + +Result Shape::appendRect(float x, float y, float w, float h, float rx, float ry) noexcept +{ + auto halfW = w * 0.5f; + auto halfH = h * 0.5f; + + //clamping cornerRadius by minimum size + if (rx > halfW) rx = halfW; + if (ry > halfH) ry = halfH; + + //rectangle + if (rx == 0 && ry == 0) { + pImpl->grow(5, 4); + pImpl->moveTo(x, y); + pImpl->lineTo(x + w, y); + pImpl->lineTo(x + w, y + h); + pImpl->lineTo(x, y + h); + pImpl->close(); + //circle + } else if (mathEqual(rx, halfW) && mathEqual(ry, halfH)) { + return appendCircle(x + (w * 0.5f), y + (h * 0.5f), rx, ry); + } else { + auto hrx = rx * 0.5f; + auto hry = ry * 0.5f; + pImpl->grow(10, 17); + pImpl->moveTo(x + rx, y); + pImpl->lineTo(x + w - rx, y); + pImpl->cubicTo(x + w - rx + hrx, y, x + w, y + ry - hry, x + w, y + ry); + pImpl->lineTo(x + w, y + h - ry); + pImpl->cubicTo(x + w, y + h - ry + hry, x + w - rx + hrx, y + h, x + w - rx, y + h); + pImpl->lineTo(x + rx, y + h); + pImpl->cubicTo(x + rx - hrx, y + h, x, y + h - ry + hry, x, y + h - ry); + pImpl->lineTo(x, y + ry); + pImpl->cubicTo(x, y + ry - hry, x + rx - hrx, y, x + rx, y); + pImpl->close(); + } + + return Result::Success; +} + + +Result Shape::fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept +{ + if (pImpl->rs.fill) { + delete(pImpl->rs.fill); + pImpl->rs.fill = nullptr; + pImpl->flag |= RenderUpdateFlag::Gradient; + } + + if (r == pImpl->rs.color[0] && g == pImpl->rs.color[1] && b == pImpl->rs.color[2] && a == pImpl->rs.color[3]) return Result::Success; + + pImpl->rs.color[0] = r; + pImpl->rs.color[1] = g; + pImpl->rs.color[2] = b; + pImpl->rs.color[3] = a; + pImpl->flag |= RenderUpdateFlag::Color; + + return Result::Success; +} + + +Result Shape::fill(unique_ptr f) noexcept +{ + auto p = f.release(); + if (!p) return Result::MemoryCorruption; + + if (pImpl->rs.fill && pImpl->rs.fill != p) delete(pImpl->rs.fill); + pImpl->rs.fill = p; + pImpl->flag |= RenderUpdateFlag::Gradient; + + return Result::Success; +} + + +Result Shape::fillColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept +{ + pImpl->rs.fillColor(r, g, b, a); + + return Result::Success; +} + + +const Fill* Shape::fill() const noexcept +{ + return pImpl->rs.fill; +} + + +Result Shape::order(bool strokeFirst) noexcept +{ + if (!pImpl->strokeFirst(strokeFirst)) return Result::FailedAllocation; + + return Result::Success; +} + + +Result Shape::stroke(float width) noexcept +{ + if (!pImpl->strokeWidth(width)) return Result::FailedAllocation; + + return Result::Success; +} + + +float Shape::strokeWidth() const noexcept +{ + return pImpl->rs.strokeWidth(); +} + + +Result Shape::stroke(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept +{ + if (!pImpl->strokeColor(r, g, b, a)) return Result::FailedAllocation; + + return Result::Success; +} + + +Result Shape::strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept +{ + if (!pImpl->rs.strokeColor(r, g, b, a)) return Result::InsufficientCondition; + + return Result::Success; +} + + +Result Shape::stroke(unique_ptr f) noexcept +{ + return pImpl->strokeFill(std::move(f)); +} + + +const Fill* Shape::strokeFill() const noexcept +{ + return pImpl->rs.strokeFill(); +} + + +Result Shape::stroke(const float* dashPattern, uint32_t cnt) noexcept +{ + return pImpl->strokeDash(dashPattern, cnt, 0); +} + + +uint32_t Shape::strokeDash(const float** dashPattern) const noexcept +{ + return pImpl->rs.strokeDash(dashPattern, nullptr); +} + + +Result Shape::stroke(StrokeCap cap) noexcept +{ + if (!pImpl->strokeCap(cap)) return Result::FailedAllocation; + + return Result::Success; +} + + +Result Shape::stroke(StrokeJoin join) noexcept +{ + if (!pImpl->strokeJoin(join)) return Result::FailedAllocation; + + return Result::Success; +} + +Result Shape::strokeMiterlimit(float miterlimit) noexcept +{ + // https://www.w3.org/TR/SVG2/painting.html#LineJoin + // - A negative value for stroke-miterlimit must be treated as an illegal value. + if (miterlimit < 0.0f) return Result::NonSupport; + // TODO Find out a reasonable max value. + if (!pImpl->strokeMiterlimit(miterlimit)) return Result::FailedAllocation; + + return Result::Success; +} + + +StrokeCap Shape::strokeCap() const noexcept +{ + return pImpl->rs.strokeCap(); +} + + +StrokeJoin Shape::strokeJoin() const noexcept +{ + return pImpl->rs.strokeJoin(); +} + +float Shape::strokeMiterlimit() const noexcept +{ + return pImpl->rs.strokeMiterlimit(); +} + + +Result Shape::fill(FillRule r) noexcept +{ + pImpl->rs.rule = r; + + return Result::Success; +} + + +FillRule Shape::fillRule() const noexcept +{ + return pImpl->rs.rule; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgShape.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgShape.h new file mode 100644 index 000000000..161932d11 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgShape.h @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_SHAPE_IMPL_H_ +#define _TVG_SHAPE_IMPL_H_ + +#include +#include "tvgMath.h" +#include "tvgPaint.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +struct Shape::Impl +{ + RenderShape rs; //shape data + RenderData rd = nullptr; //engine data + Shape* shape; + uint8_t flag = RenderUpdateFlag::None; + uint8_t opacity; //for composition + bool needComp; //composite or not + + Impl(Shape* s) : shape(s) + { + } + + bool dispose(RenderMethod& renderer) + { + renderer.dispose(rd); + rd = nullptr; + return true; + } + + bool render(RenderMethod& renderer) + { + Compositor* cmp = nullptr; + bool ret; + + if (needComp) { + cmp = renderer.target(bounds(renderer), renderer.colorSpace()); + renderer.beginComposite(cmp, CompositeMethod::None, opacity); + } + ret = renderer.renderShape(rd); + if (cmp) renderer.endComposite(cmp); + return ret; + } + + bool needComposition(uint8_t opacity) + { + if (opacity == 0) return false; + + //Shape composition is only necessary when stroking & fill are valid. + if (!rs.stroke || rs.stroke->width < FLT_EPSILON || (!rs.stroke->fill && rs.stroke->color[3] == 0)) return false; + if (!rs.fill && rs.color[3] == 0) return false; + + //translucent fill & stroke + if (opacity < 255) return true; + + //Composition test + const Paint* target; + auto method = shape->composite(&target); + if (!target || method == tvg::CompositeMethod::ClipPath) return false; + if (target->pImpl->opacity == 255 || target->pImpl->opacity == 0) return false; + + return true; + } + + RenderData update(RenderMethod& renderer, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper) + { + if ((needComp = needComposition(opacity))) { + /* Overriding opacity value. If this scene is half-translucent, + It must do intermeidate composition with that opacity value. */ + this->opacity = opacity; + opacity = 255; + } + + rd = renderer.prepare(rs, rd, transform, clips, opacity, static_cast(pFlag | flag), clipper); + flag = RenderUpdateFlag::None; + return rd; + } + + RenderRegion bounds(RenderMethod& renderer) + { + return renderer.region(rd); + } + + bool bounds(float* x, float* y, float* w, float* h, bool stroking) + { + //Path bounding size + if (rs.path.pts.count > 0 ) { + auto pts = rs.path.pts.data; + Point min = { pts->x, pts->y }; + Point max = { pts->x, pts->y }; + + for (auto pts2 = pts + 1; pts2 < rs.path.pts.end(); ++pts2) { + if (pts2->x < min.x) min.x = pts2->x; + if (pts2->y < min.y) min.y = pts2->y; + if (pts2->x > max.x) max.x = pts2->x; + if (pts2->y > max.y) max.y = pts2->y; + } + + if (x) *x = min.x; + if (y) *y = min.y; + if (w) *w = max.x - min.x; + if (h) *h = max.y - min.y; + } + + //Stroke feathering + if (stroking && rs.stroke) { + if (x) *x -= rs.stroke->width * 0.5f; + if (y) *y -= rs.stroke->width * 0.5f; + if (w) *w += rs.stroke->width; + if (h) *h += rs.stroke->width; + } + return rs.path.pts.count > 0 ? true : false; + } + + void reserveCmd(uint32_t cmdCnt) + { + rs.path.cmds.reserve(cmdCnt); + } + + void reservePts(uint32_t ptsCnt) + { + rs.path.pts.reserve(ptsCnt); + } + + void grow(uint32_t cmdCnt, uint32_t ptsCnt) + { + rs.path.cmds.grow(cmdCnt); + rs.path.pts.grow(ptsCnt); + } + + void append(const PathCommand* cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt) + { + memcpy(rs.path.cmds.end(), cmds, sizeof(PathCommand) * cmdCnt); + memcpy(rs.path.pts.end(), pts, sizeof(Point) * ptsCnt); + rs.path.cmds.count += cmdCnt; + rs.path.pts.count += ptsCnt; + + flag |= RenderUpdateFlag::Path; + } + + void moveTo(float x, float y) + { + rs.path.cmds.push(PathCommand::MoveTo); + rs.path.pts.push({x, y}); + + flag |= RenderUpdateFlag::Path; + } + + void lineTo(float x, float y) + { + rs.path.cmds.push(PathCommand::LineTo); + rs.path.pts.push({x, y}); + + flag |= RenderUpdateFlag::Path; + } + + void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) + { + rs.path.cmds.push(PathCommand::CubicTo); + rs.path.pts.push({cx1, cy1}); + rs.path.pts.push({cx2, cy2}); + rs.path.pts.push({x, y}); + + flag |= RenderUpdateFlag::Path; + } + + void close() + { + //Don't close multiple times. + if (rs.path.cmds.count > 0 && rs.path.cmds.last() == PathCommand::Close) return; + + rs.path.cmds.push(PathCommand::Close); + + flag |= RenderUpdateFlag::Path; + } + + bool strokeWidth(float width) + { + if (!rs.stroke) rs.stroke = new RenderStroke(); + rs.stroke->width = width; + flag |= RenderUpdateFlag::Stroke; + + return true; + } + + bool strokeTrim(float begin, float end) + { + if (!rs.stroke) { + if (begin == 0.0f && end == 1.0f) return true; + rs.stroke = new RenderStroke(); + } + + if (mathEqual(rs.stroke->trim.begin, begin) && mathEqual(rs.stroke->trim.end, end)) return true; + + rs.stroke->trim.begin = begin; + rs.stroke->trim.end = end; + flag |= RenderUpdateFlag::Stroke; + + return true; + } + + bool strokeCap(StrokeCap cap) + { + if (!rs.stroke) rs.stroke = new RenderStroke(); + rs.stroke->cap = cap; + flag |= RenderUpdateFlag::Stroke; + + return true; + } + + bool strokeJoin(StrokeJoin join) + { + if (!rs.stroke) rs.stroke = new RenderStroke(); + rs.stroke->join = join; + flag |= RenderUpdateFlag::Stroke; + + return true; + } + + bool strokeMiterlimit(float miterlimit) + { + if (!rs.stroke) rs.stroke = new RenderStroke(); + rs.stroke->miterlimit = miterlimit; + flag |= RenderUpdateFlag::Stroke; + + return true; + } + + bool strokeColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a) + { + if (!rs.stroke) rs.stroke = new RenderStroke(); + if (rs.stroke->fill) { + delete(rs.stroke->fill); + rs.stroke->fill = nullptr; + flag |= RenderUpdateFlag::GradientStroke; + } + + rs.stroke->color[0] = r; + rs.stroke->color[1] = g; + rs.stroke->color[2] = b; + rs.stroke->color[3] = a; + + flag |= RenderUpdateFlag::Stroke; + + return true; + } + + Result strokeFill(unique_ptr f) + { + auto p = f.release(); + if (!p) return Result::MemoryCorruption; + + if (!rs.stroke) rs.stroke = new RenderStroke(); + if (rs.stroke->fill && rs.stroke->fill != p) delete(rs.stroke->fill); + rs.stroke->fill = p; + + flag |= RenderUpdateFlag::Stroke; + flag |= RenderUpdateFlag::GradientStroke; + + return Result::Success; + } + + Result strokeDash(const float* pattern, uint32_t cnt, float offset) + { + if ((cnt == 1) || (!pattern && cnt > 0) || (pattern && cnt == 0)) { + return Result::InvalidArguments; + } + + for (uint32_t i = 0; i < cnt; i++) { + if (pattern[i] < FLT_EPSILON) return Result::InvalidArguments; + } + + //Reset dash + if (!pattern && cnt == 0) { + free(rs.stroke->dashPattern); + rs.stroke->dashPattern = nullptr; + } else { + if (!rs.stroke) rs.stroke = new RenderStroke(); + if (rs.stroke->dashCnt != cnt) { + free(rs.stroke->dashPattern); + rs.stroke->dashPattern = nullptr; + } + if (!rs.stroke->dashPattern) { + rs.stroke->dashPattern = static_cast(malloc(sizeof(float) * cnt)); + if (!rs.stroke->dashPattern) return Result::FailedAllocation; + } + for (uint32_t i = 0; i < cnt; ++i) { + rs.stroke->dashPattern[i] = pattern[i]; + } + } + rs.stroke->dashCnt = cnt; + rs.stroke->dashOffset = offset; + flag |= RenderUpdateFlag::Stroke; + + return Result::Success; + } + + bool strokeFirst() + { + if (!rs.stroke) return true; + return rs.stroke->strokeFirst; + } + + bool strokeFirst(bool strokeFirst) + { + if (!rs.stroke) rs.stroke = new RenderStroke(); + rs.stroke->strokeFirst = strokeFirst; + flag |= RenderUpdateFlag::Stroke; + + return true; + } + + void update(RenderUpdateFlag flag) + { + this->flag |= flag; + } + + Paint* duplicate() + { + auto ret = Shape::gen(); + + auto dup = ret.get()->pImpl; + dup->rs.rule = rs.rule; + + //Color + memcpy(dup->rs.color, rs.color, sizeof(rs.color)); + dup->flag = RenderUpdateFlag::Color; + + //Path + if (rs.path.cmds.count > 0 && rs.path.pts.count > 0) { + dup->rs.path.cmds = rs.path.cmds; + dup->rs.path.pts = rs.path.pts; + dup->flag |= RenderUpdateFlag::Path; + } + + //Stroke + if (rs.stroke) { + dup->rs.stroke = new RenderStroke(); + *dup->rs.stroke = *rs.stroke; + memcpy(dup->rs.stroke->color, rs.stroke->color, sizeof(rs.stroke->color)); + if (rs.stroke->dashCnt > 0) { + dup->rs.stroke->dashPattern = static_cast(malloc(sizeof(float) * rs.stroke->dashCnt)); + memcpy(dup->rs.stroke->dashPattern, rs.stroke->dashPattern, sizeof(float) * rs.stroke->dashCnt); + } + if (rs.stroke->fill) { + dup->rs.stroke->fill = rs.stroke->fill->duplicate(); + dup->flag |= RenderUpdateFlag::GradientStroke; + } + dup->flag |= RenderUpdateFlag::Stroke; + } + + //Fill + if (rs.fill) { + dup->rs.fill = rs.fill->duplicate(); + dup->flag |= RenderUpdateFlag::Gradient; + } + + return ret.release(); + } + + Iterator* iterator() + { + return nullptr; + } +}; + +#endif //_TVG_SHAPE_IMPL_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgStr.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgStr.cpp new file mode 100644 index 000000000..25630c7e9 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgStr.cpp @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "config.h" +#include +#include +#include "tvgMath.h" +#include "tvgStr.h" + + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static inline bool _floatExact(float a, float b) +{ + return memcmp(&a, &b, sizeof(float)) == 0; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +namespace tvg { + +/* + * https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strtof-strtof-l-wcstof-wcstof-l?view=msvc-160 + * + * src should be one of the following form : + * + * [whitespace] [sign] {digits [radix digits] | radix digits} [{e | E} [sign] digits] + * [whitespace] [sign] {INF | INFINITY} + * [whitespace] [sign] NAN [sequence] + * + * No hexadecimal form supported + * no sequence supported after NAN + */ +float strToFloat(const char *nPtr, char **endPtr) +{ + if (endPtr) *endPtr = (char *) (nPtr); + if (!nPtr) return 0.0f; + + auto a = nPtr; + auto iter = nPtr; + auto val = 0.0f; + unsigned long long integerPart = 0; + int minus = 1; + + //ignore leading whitespaces + while (isspace(*iter)) iter++; + + //signed or not + if (*iter == '-') { + minus = -1; + iter++; + } else if (*iter == '+') { + iter++; + } + + if (tolower(*iter) == 'i') { + if ((tolower(*(iter + 1)) == 'n') && (tolower(*(iter + 2)) == 'f')) iter += 3; + else goto error; + + if (tolower(*(iter)) == 'i') { + if ((tolower(*(iter + 1)) == 'n') && (tolower(*(iter + 2)) == 'i') && (tolower(*(iter + 3)) == 't') && + (tolower(*(iter + 4)) == 'y')) + iter += 5; + else goto error; + } + if (endPtr) *endPtr = (char *) (iter); + return (minus == -1) ? -INFINITY : INFINITY; + } + + if (tolower(*iter) == 'n') { + if ((tolower(*(iter + 1)) == 'a') && (tolower(*(iter + 2)) == 'n')) iter += 3; + else goto error; + + if (endPtr) *endPtr = (char *) (iter); + return (minus == -1) ? -NAN : NAN; + } + + //Optional: integer part before dot + if (isdigit(*iter)) { + for (; isdigit(*iter); iter++) { + integerPart = integerPart * 10ULL + (unsigned long long) (*iter - '0'); + } + a = iter; + } else if (*iter != '.') { + goto success; + } + + val = static_cast(integerPart); + + //Optional: decimal part after dot + if (*iter == '.') { + unsigned long long decimalPart = 0; + unsigned long long pow10 = 1; + int count = 0; + + iter++; + + if (isdigit(*iter)) { + for (; isdigit(*iter); iter++, count++) { + if (count < 19) { + decimalPart = decimalPart * 10ULL + +static_cast(*iter - '0'); + pow10 *= 10ULL; + } + } + } else if (isspace(*iter)) { //skip if there is a space after the dot. + a = iter; + goto success; + } + + val += static_cast(decimalPart) / static_cast(pow10); + a = iter; + } + + //Optional: exponent + if (*iter == 'e' || *iter == 'E') { + ++iter; + + //Exception: svg may have 'em' unit for fonts. ex) 5em, 10.5em + if ((*iter == 'm') || (*iter == 'M')) { + //TODO: We don't support font em unit now, but has to multiply val * font size later... + a = iter + 1; + goto success; + } + + //signed or not + int minus_e = 1; + + if (*iter == '-') { + minus_e = -1; + ++iter; + } else if (*iter == '+') { + iter++; + } + + unsigned int exponentPart = 0; + + if (isdigit(*iter)) { + while (*iter == '0') iter++; + for (; isdigit(*iter); iter++) { + exponentPart = exponentPart * 10U + static_cast(*iter - '0'); + } + } else if (!isdigit(*(a - 1))) { + a = nPtr; + goto success; + } else if (*iter == 0) { + goto success; + } + + //if ((_floatExact(val, 2.2250738585072011f)) && ((minus_e * static_cast(exponentPart)) <= -308)) { + if ((_floatExact(val, 1.175494351f)) && ((minus_e * static_cast(exponentPart)) <= -38)) { + //val *= 1.0e-308f; + val *= 1.0e-38f; + a = iter; + goto success; + } + + a = iter; + auto scale = 1.0f; + + while (exponentPart >= 8U) { + scale *= (float)1E8; + exponentPart -= 8U; + } + while (exponentPart > 0U) { + scale *= 10.0f; + exponentPart--; + } + val = (minus_e == -1) ? (val / scale) : (val * scale); + } else if ((iter > nPtr) && !isdigit(*(iter - 1))) { + a = nPtr; + goto success; + } + +success: + if (endPtr) *endPtr = (char *)(a); + return minus * val; + +error: + if (endPtr) *endPtr = (char *)(nPtr); + return 0.0f; +} + + +int str2int(const char* str, size_t n) +{ + int ret = 0; + for(size_t i = 0; i < n; ++i) { + ret = ret * 10 + (str[i] - '0'); + } + return ret; +} + +char* strDuplicate(const char *str, size_t n) +{ + auto len = strlen(str); + if (len < n) n = len; + + auto ret = (char *) malloc(n + 1); + if (!ret) return nullptr; + ret[n] = '\0'; + + return (char *) memcpy(ret, str, n); +} + +char* strDirname(const char* path) +{ + const char *ptr = strrchr(path, '/'); +#ifdef _WIN32 + if (ptr) ptr = strrchr(ptr + 1, '\\'); +#endif + int len = int(ptr + 1 - path); // +1 to include '/' + return strDuplicate(path, len); +} + +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgStr.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgStr.h new file mode 100644 index 000000000..eb664e2f5 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgStr.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_STR_H_ +#define _TVG_STR_H_ + +#include + +namespace tvg +{ + +float strToFloat(const char *nPtr, char **endPtr); //convert to float +int str2int(const char* str, size_t n); //convert to integer +char* strDuplicate(const char *str, size_t n); //copy the string +char* strDirname(const char* path); //return the full directory name + +} +#endif //_TVG_STR_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgCssStyle.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgCssStyle.cpp new file mode 100644 index 000000000..89e45d401 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgCssStyle.cpp @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2022 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgSvgCssStyle.h" + +#include + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static bool _isImportanceApplicable(SvgStyleFlags &toFlagsImportance, SvgStyleFlags fromFlagsImportance, SvgStyleFlags flag) +{ + if (!(toFlagsImportance & flag) && (fromFlagsImportance & flag)) { + return true; + } + return false; +} + +static void _copyStyle(SvgStyleProperty* to, const SvgStyleProperty* from) +{ + if (from == nullptr) return; + //Copy the properties of 'from' only if they were explicitly set (not the default ones). + if ((from->curColorSet && !(to->flags & SvgStyleFlags::Color)) || + _isImportanceApplicable(to->flagsImportance, from->flagsImportance, SvgStyleFlags::Color)) { + to->color = from->color; + to->curColorSet = true; + to->flags = (to->flags | SvgStyleFlags::Color); + if (from->flagsImportance & SvgStyleFlags::Color) { + to->flagsImportance = (to->flagsImportance | SvgStyleFlags::Color); + } + } + //Fill + if (((from->fill.flags & SvgFillFlags::Paint) && !(to->flags & SvgStyleFlags::Fill)) || + _isImportanceApplicable(to->flagsImportance, from->flagsImportance, SvgStyleFlags::Fill)) { + to->fill.paint.color = from->fill.paint.color; + to->fill.paint.none = from->fill.paint.none; + to->fill.paint.curColor = from->fill.paint.curColor; + if (from->fill.paint.url) { + if (to->fill.paint.url) free(to->fill.paint.url); + to->fill.paint.url = strdup(from->fill.paint.url); + } + to->fill.flags = (to->fill.flags | SvgFillFlags::Paint); + to->flags = (to->flags | SvgStyleFlags::Fill); + if (from->flagsImportance & SvgStyleFlags::Fill) { + to->flagsImportance = (to->flagsImportance | SvgStyleFlags::Fill); + } + } + if (((from->fill.flags & SvgFillFlags::Opacity) && !(to->flags & SvgStyleFlags::FillOpacity)) || + _isImportanceApplicable(to->flagsImportance, from->flagsImportance, SvgStyleFlags::FillOpacity)) { + to->fill.opacity = from->fill.opacity; + to->fill.flags = (to->fill.flags | SvgFillFlags::Opacity); + to->flags = (to->flags | SvgStyleFlags::FillOpacity); + if (from->flagsImportance & SvgStyleFlags::FillOpacity) { + to->flagsImportance = (to->flagsImportance | SvgStyleFlags::FillOpacity); + } + } + if (((from->fill.flags & SvgFillFlags::FillRule) && !(to->flags & SvgStyleFlags::FillRule)) || + _isImportanceApplicable(to->flagsImportance, from->flagsImportance, SvgStyleFlags::FillRule)) { + to->fill.fillRule = from->fill.fillRule; + to->fill.flags = (to->fill.flags | SvgFillFlags::FillRule); + to->flags = (to->flags | SvgStyleFlags::FillRule); + if (from->flagsImportance & SvgStyleFlags::FillRule) { + to->flagsImportance = (to->flagsImportance | SvgStyleFlags::FillRule); + } + } + //Stroke + if (((from->stroke.flags & SvgStrokeFlags::Paint) && !(to->flags & SvgStyleFlags::Stroke)) || + _isImportanceApplicable(to->flagsImportance, from->flagsImportance, SvgStyleFlags::Stroke)) { + to->stroke.paint.color = from->stroke.paint.color; + to->stroke.paint.none = from->stroke.paint.none; + to->stroke.paint.curColor = from->stroke.paint.curColor; + if (from->stroke.paint.url) { + if (to->stroke.paint.url) free(to->stroke.paint.url); + to->stroke.paint.url = strdup(from->stroke.paint.url); + } + to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Paint); + to->flags = (to->flags | SvgStyleFlags::Stroke); + if (from->flagsImportance & SvgStyleFlags::Stroke) { + to->flagsImportance = (to->flagsImportance | SvgStyleFlags::Stroke); + } + } + if (((from->stroke.flags & SvgStrokeFlags::Opacity) && !(to->flags & SvgStyleFlags::StrokeOpacity)) || + _isImportanceApplicable(to->flagsImportance, from->flagsImportance, SvgStyleFlags::StrokeOpacity)) { + to->stroke.opacity = from->stroke.opacity; + to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Opacity); + to->flags = (to->flags | SvgStyleFlags::StrokeOpacity); + if (from->flagsImportance & SvgStyleFlags::StrokeOpacity) { + to->flagsImportance = (to->flagsImportance | SvgStyleFlags::StrokeOpacity); + } + } + if (((from->stroke.flags & SvgStrokeFlags::Width) && !(to->flags & SvgStyleFlags::StrokeWidth)) || + _isImportanceApplicable(to->flagsImportance, from->flagsImportance, SvgStyleFlags::StrokeWidth)) { + to->stroke.width = from->stroke.width; + to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Width); + to->flags = (to->flags | SvgStyleFlags::StrokeWidth); + if (from->flagsImportance & SvgStyleFlags::StrokeWidth) { + to->flagsImportance = (to->flagsImportance | SvgStyleFlags::StrokeWidth); + } + } + if (((from->stroke.flags & SvgStrokeFlags::Dash) && !(to->flags & SvgStyleFlags::StrokeDashArray)) || + _isImportanceApplicable(to->flagsImportance, from->flagsImportance, SvgStyleFlags::StrokeDashArray)) { + if (from->stroke.dash.array.count > 0) { + to->stroke.dash.array.clear(); + to->stroke.dash.array.reserve(from->stroke.dash.array.count); + for (uint32_t i = 0; i < from->stroke.dash.array.count; ++i) { + to->stroke.dash.array.push(from->stroke.dash.array[i]); + } + to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Dash); + to->flags = (to->flags | SvgStyleFlags::StrokeDashArray); + if (from->flagsImportance & SvgStyleFlags::StrokeDashArray) { + to->flagsImportance = (to->flagsImportance | SvgStyleFlags::StrokeDashArray); + } + } + } + if (((from->stroke.flags & SvgStrokeFlags::Cap) && !(to->flags & SvgStyleFlags::StrokeLineCap)) || + _isImportanceApplicable(to->flagsImportance, from->flagsImportance, SvgStyleFlags::StrokeLineCap)) { + to->stroke.cap = from->stroke.cap; + to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Cap); + to->flags = (to->flags | SvgStyleFlags::StrokeLineCap); + if (from->flagsImportance & SvgStyleFlags::StrokeLineCap) { + to->flagsImportance = (to->flagsImportance | SvgStyleFlags::StrokeLineCap); + } + } + if (((from->stroke.flags & SvgStrokeFlags::Join) && !(to->flags & SvgStyleFlags::StrokeLineJoin)) || + _isImportanceApplicable(to->flagsImportance, from->flagsImportance, SvgStyleFlags::StrokeLineJoin)) { + to->stroke.join = from->stroke.join; + to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Join); + to->flags = (to->flags | SvgStyleFlags::StrokeLineJoin); + if (from->flagsImportance & SvgStyleFlags::StrokeLineJoin) { + to->flagsImportance = (to->flagsImportance | SvgStyleFlags::StrokeLineJoin); + } + } + //Opacity + //TODO: it can be set to be 255 and shouldn't be changed by attribute 'opacity' + if ((from->opacity < 255 && !(to->flags & SvgStyleFlags::Opacity)) || + _isImportanceApplicable(to->flagsImportance, from->flagsImportance, SvgStyleFlags::Opacity)) { + to->opacity = from->opacity; + to->flags = (to->flags | SvgStyleFlags::Opacity); + if (from->flagsImportance & SvgStyleFlags::Opacity) { + to->flagsImportance = (to->flagsImportance | SvgStyleFlags::Opacity); + } + } +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +void cssCopyStyleAttr(SvgNode* to, const SvgNode* from) +{ + //Copy matrix attribute + if (from->transform && !(to->style->flags & SvgStyleFlags::Transform)) { + to->transform = (Matrix*)malloc(sizeof(Matrix)); + if (to->transform) { + *to->transform = *from->transform; + to->style->flags = (to->style->flags | SvgStyleFlags::Transform); + } + } + //Copy style attribute + _copyStyle(to->style, from->style); + + if (from->style->clipPath.url) { + if (to->style->clipPath.url) free(to->style->clipPath.url); + to->style->clipPath.url = strdup(from->style->clipPath.url); + } + if (from->style->mask.url) { + if (to->style->mask.url) free(to->style->mask.url); + to->style->mask.url = strdup(from->style->mask.url); + } +} + + +SvgNode* cssFindStyleNode(const SvgNode* style, const char* title, SvgNodeType type) +{ + if (!style) return nullptr; + + auto child = style->child.data; + for (uint32_t i = 0; i < style->child.count; ++i, ++child) { + if ((*child)->type == type) { + if ((!title && !(*child)->id) || (title && (*child)->id && !strcmp((*child)->id, title))) return (*child); + } + } + return nullptr; +} + + +SvgNode* cssFindStyleNode(const SvgNode* style, const char* title) +{ + if (!style || !title) return nullptr; + + auto child = style->child.data; + for (uint32_t i = 0; i < style->child.count; ++i, ++child) { + if ((*child)->type == SvgNodeType::CssStyle) { + if ((*child)->id && !strcmp((*child)->id, title)) return (*child); + } + } + return nullptr; +} + + +void cssUpdateStyle(SvgNode* doc, SvgNode* style) +{ + if (doc->child.count > 0) { + auto child = doc->child.data; + for (uint32_t i = 0; i < doc->child.count; ++i, ++child) { + if (auto cssNode = cssFindStyleNode(style, nullptr, (*child)->type)) { + cssCopyStyleAttr(*child, cssNode); + } + cssUpdateStyle(*child, style); + } + } +} + + +void cssApplyStyleToPostponeds(Array& postponeds, SvgNode* style) +{ + for (uint32_t i = 0; i < postponeds.count; ++i) { + auto nodeIdPair = postponeds[i]; + + //css styling: tag.name has higher priority than .name + if (auto cssNode = cssFindStyleNode(style, nodeIdPair.id, nodeIdPair.node->type)) { + cssCopyStyleAttr(nodeIdPair.node, cssNode); + } + if (auto cssNode = cssFindStyleNode(style, nodeIdPair.id)) { + cssCopyStyleAttr(nodeIdPair.node, cssNode); + } + } +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgCssStyle.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgCssStyle.h new file mode 100644 index 000000000..d718ede64 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgCssStyle.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_SVG_CSS_STYLE_H_ +#define _TVG_SVG_CSS_STYLE_H_ + +#include "tvgSvgLoaderCommon.h" + +void cssCopyStyleAttr(SvgNode* to, const SvgNode* from); +SvgNode* cssFindStyleNode(const SvgNode* style, const char* title, SvgNodeType type); +SvgNode* cssFindStyleNode(const SvgNode* style, const char* title); +void cssUpdateStyle(SvgNode* doc, SvgNode* style); +void cssApplyStyleToPostponeds(Array& postponeds, SvgNode* style); + +#endif //_TVG_SVG_CSS_STYLE_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgLoader.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgLoader.cpp new file mode 100644 index 000000000..efca81245 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgLoader.cpp @@ -0,0 +1,3759 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +/* + * Copyright notice for the EFL: + + * Copyright (C) EFL developers (see AUTHORS) + + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include "tvgLoader.h" +#include "tvgXmlParser.h" +#include "tvgSvgLoader.h" +#include "tvgSvgSceneBuilder.h" +#include "tvgStr.h" +#include "tvgSvgCssStyle.h" +#include "tvgMath.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +/* + * According to: https://www.w3.org/TR/SVG2/coords.html#Units + * and: https://www.w3.org/TR/css-values-4/#absolute-lengths + */ +#define PX_PER_IN 96 //1 in = 96 px +#define PX_PER_PC 16 //1 pc = 1/6 in -> PX_PER_IN/6 +#define PX_PER_PT 1.333333f //1 pt = 1/72 in -> PX_PER_IN/72 +#define PX_PER_MM 3.779528f //1 in = 25.4 mm -> PX_PER_IN/25.4 +#define PX_PER_CM 37.79528f //1 in = 2.54 cm -> PX_PER_IN/2.54 + +typedef bool (*parseAttributes)(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data); +typedef SvgNode* (*FactoryMethod)(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func); +typedef SvgStyleGradient* (*GradientFactoryMethod)(SvgLoaderData* loader, const char* buf, unsigned bufLength); + +static char* _skipSpace(const char* str, const char* end) +{ + while (((end && str < end) || (!end && *str != '\0')) && isspace(*str)) { + ++str; + } + return (char*) str; +} + + +static char* _copyId(const char* str) +{ + if (!str) return nullptr; + + return strdup(str); +} + + +static const char* _skipComma(const char* content) +{ + content = _skipSpace(content, nullptr); + if (*content == ',') return content + 1; + return content; +} + + +static bool _parseNumber(const char** content, float* number) +{ + char* end = nullptr; + + *number = strToFloat(*content, &end); + //If the start of string is not number + if ((*content) == end) return false; + //Skip comma if any + *content = _skipComma(end); + + return true; +} + + +static constexpr struct +{ + AspectRatioAlign align; + const char* tag; +} alignTags[] = { + { AspectRatioAlign::XMinYMin, "xMinYMin" }, + { AspectRatioAlign::XMidYMin, "xMidYMin" }, + { AspectRatioAlign::XMaxYMin, "xMaxYMin" }, + { AspectRatioAlign::XMinYMid, "xMinYMid" }, + { AspectRatioAlign::XMidYMid, "xMidYMid" }, + { AspectRatioAlign::XMaxYMid, "xMaxYMid" }, + { AspectRatioAlign::XMinYMax, "xMinYMax" }, + { AspectRatioAlign::XMidYMax, "xMidYMax" }, + { AspectRatioAlign::XMaxYMax, "xMaxYMax" }, +}; + + +static void _parseAspectRatio(const char** content, AspectRatioAlign* align, AspectRatioMeetOrSlice* meetOrSlice) +{ + if (!strcmp(*content, "none")) { + *align = AspectRatioAlign::None; + return; + } + + for (unsigned int i = 0; i < sizeof(alignTags) / sizeof(alignTags[0]); i++) { + if (!strncmp(*content, alignTags[i].tag, 8)) { + *align = alignTags[i].align; + *content += 8; + *content = _skipSpace(*content, nullptr); + break; + } + } + + if (!strcmp(*content, "meet")) { + *meetOrSlice = AspectRatioMeetOrSlice::Meet; + } else if (!strcmp(*content, "slice")) { + *meetOrSlice = AspectRatioMeetOrSlice::Slice; + } +} + + +/** + * According to https://www.w3.org/TR/SVG/coords.html#Units + */ +static float _toFloat(const SvgParser* svgParse, const char* str, SvgParserLengthType type) +{ + float parsedValue = strToFloat(str, nullptr); + + if (strstr(str, "cm")) parsedValue *= PX_PER_CM; + else if (strstr(str, "mm")) parsedValue *= PX_PER_MM; + else if (strstr(str, "pt")) parsedValue *= PX_PER_PT; + else if (strstr(str, "pc")) parsedValue *= PX_PER_PC; + else if (strstr(str, "in")) parsedValue *= PX_PER_IN; + else if (strstr(str, "%")) { + if (type == SvgParserLengthType::Vertical) parsedValue = (parsedValue / 100.0f) * svgParse->global.h; + else if (type == SvgParserLengthType::Horizontal) parsedValue = (parsedValue / 100.0f) * svgParse->global.w; + else //if other then it's radius + { + float max = svgParse->global.w; + if (max < svgParse->global.h) + max = svgParse->global.h; + parsedValue = (parsedValue / 100.0f) * max; + } + } + //TODO: Implement 'em', 'ex' attributes + + return parsedValue; +} + + +static float _gradientToFloat(const SvgParser* svgParse, const char* str, bool& isPercentage) +{ + char* end = nullptr; + + float parsedValue = strToFloat(str, &end); + isPercentage = false; + + if (strstr(str, "%")) { + parsedValue = parsedValue / 100.0f; + isPercentage = true; + } + else if (strstr(str, "cm")) parsedValue *= PX_PER_CM; + else if (strstr(str, "mm")) parsedValue *= PX_PER_MM; + else if (strstr(str, "pt")) parsedValue *= PX_PER_PT; + else if (strstr(str, "pc")) parsedValue *= PX_PER_PC; + else if (strstr(str, "in")) parsedValue *= PX_PER_IN; + //TODO: Implement 'em', 'ex' attributes + + return parsedValue; +} + + +static float _toOffset(const char* str) +{ + char* end = nullptr; + auto strEnd = str + strlen(str); + + float parsedValue = strToFloat(str, &end); + + end = _skipSpace(end, nullptr); + auto ptr = strstr(str, "%"); + + if (ptr) { + parsedValue = parsedValue / 100.0f; + if (end != ptr || (end + 1) != strEnd) return 0; + } else if (end != strEnd) return 0; + + return parsedValue; +} + + +static int _toOpacity(const char* str) +{ + char* end = nullptr; + float opacity = strToFloat(str, &end); + + if (end) { + if (end[0] == '%' && end[1] == '\0') return lrint(opacity * 2.55f); + else if (*end == '\0') return lrint(opacity * 255); + } + return 255; +} + + +static SvgMaskType _toMaskType(const char* str) +{ + if (!strcmp(str, "Alpha")) return SvgMaskType::Alpha; + + return SvgMaskType::Luminance; +} + + +//The default rendering order: fill, stroke, markers +//If any is omitted, will be rendered in its default order after the specified ones. +static bool _toPaintOrder(const char* str) +{ + uint8_t position = 1; + uint8_t strokePosition = 0; + uint8_t fillPosition = 0; + + while (*str != '\0') { + str = _skipSpace(str, nullptr); + if (!strncmp(str, "fill", 4)) { + fillPosition = position++; + str += 4; + } else if (!strncmp(str, "stroke", 6)) { + strokePosition = position++; + str += 6; + } else if (!strncmp(str, "markers", 7)) { + str += 7; + } else { + return _toPaintOrder("fill stroke"); + } + } + + if (fillPosition == 0) fillPosition = position++; + if (strokePosition == 0) strokePosition = position++; + + return fillPosition < strokePosition; +} + + +#define _PARSE_TAG(Type, Name, Name1, Tags_Array, Default) \ + static Type _to##Name1(const char* str) \ + { \ + unsigned int i; \ + \ + for (i = 0; i < sizeof(Tags_Array) / sizeof(Tags_Array[0]); i++) { \ + if (!strcmp(str, Tags_Array[i].tag)) return Tags_Array[i].Name; \ + } \ + return Default; \ + } + + +/* parse the line cap used during stroking a path. + * Value: butt | round | square | inherit + * Initial: butt + * https://www.w3.org/TR/SVG/painting.html + */ +static constexpr struct +{ + StrokeCap lineCap; + const char* tag; +} lineCapTags[] = { + { StrokeCap::Butt, "butt" }, + { StrokeCap::Round, "round" }, + { StrokeCap::Square, "square" } +}; + + +_PARSE_TAG(StrokeCap, lineCap, LineCap, lineCapTags, StrokeCap::Butt) + + +/* parse the line join used during stroking a path. + * Value: miter | round | bevel | inherit + * Initial: miter + * https://www.w3.org/TR/SVG/painting.html + */ +static constexpr struct +{ + StrokeJoin lineJoin; + const char* tag; +} lineJoinTags[] = { + { StrokeJoin::Miter, "miter" }, + { StrokeJoin::Round, "round" }, + { StrokeJoin::Bevel, "bevel" } +}; + + +_PARSE_TAG(StrokeJoin, lineJoin, LineJoin, lineJoinTags, StrokeJoin::Miter) + + +/* parse the fill rule used during filling a path. + * Value: nonzero | evenodd | inherit + * Initial: nonzero + * https://www.w3.org/TR/SVG/painting.html + */ +static constexpr struct +{ + FillRule fillRule; + const char* tag; +} fillRuleTags[] = { + { FillRule::EvenOdd, "evenodd" } +}; + + +_PARSE_TAG(FillRule, fillRule, FillRule, fillRuleTags, FillRule::Winding) + + +/* parse the dash pattern used during stroking a path. + * Value: none | | inherit + * Initial: none + * https://www.w3.org/TR/SVG/painting.html + */ +static void _parseDashArray(SvgLoaderData* loader, const char *str, SvgDash* dash) +{ + if (!strncmp(str, "none", 4)) return; + + char *end = nullptr; + + while (*str) { + str = _skipComma(str); + float parsedValue = strToFloat(str, &end); + if (str == end) break; + if (parsedValue <= 0.0f) break; + if (*end == '%') { + ++end; + //Refers to the diagonal length of the viewport. + //https://www.w3.org/TR/SVG2/coords.html#Units + parsedValue = (sqrtf(powf(loader->svgParse->global.w, 2) + powf(loader->svgParse->global.h, 2)) / sqrtf(2.0f)) * (parsedValue / 100.0f); + } + (*dash).array.push(parsedValue); + str = end; + } + //If dash array size is 1, it means that dash and gap size are the same. + if ((*dash).array.count == 1) (*dash).array.push((*dash).array[0]); +} + + +static char* _idFromUrl(const char* url) +{ + url = _skipSpace(url, nullptr); + if ((*url) == '(') { + ++url; + url = _skipSpace(url, nullptr); + } + + if ((*url) == '\'') ++url; + if ((*url) == '#') ++url; + + int i = 0; + while (url[i] > ' ' && url[i] != ')' && url[i] != '\'') ++i; + + return strDuplicate(url, i); +} + + +static unsigned char _parseColor(const char* value, char** end) +{ + float r; + + r = strToFloat(value, end); + *end = _skipSpace(*end, nullptr); + if (**end == '%') { + r = 255 * r / 100; + (*end)++; + } + *end = _skipSpace(*end, nullptr); + + if (r < 0 || r > 255) { + *end = nullptr; + return 0; + } + + return lrint(r); +} + + +static constexpr struct +{ + const char* name; + unsigned int value; +} colors[] = { + { "aliceblue", 0xfff0f8ff }, + { "antiquewhite", 0xfffaebd7 }, + { "aqua", 0xff00ffff }, + { "aquamarine", 0xff7fffd4 }, + { "azure", 0xfff0ffff }, + { "beige", 0xfff5f5dc }, + { "bisque", 0xffffe4c4 }, + { "black", 0xff000000 }, + { "blanchedalmond", 0xffffebcd }, + { "blue", 0xff0000ff }, + { "blueviolet", 0xff8a2be2 }, + { "brown", 0xffa52a2a }, + { "burlywood", 0xffdeb887 }, + { "cadetblue", 0xff5f9ea0 }, + { "chartreuse", 0xff7fff00 }, + { "chocolate", 0xffd2691e }, + { "coral", 0xffff7f50 }, + { "cornflowerblue", 0xff6495ed }, + { "cornsilk", 0xfffff8dc }, + { "crimson", 0xffdc143c }, + { "cyan", 0xff00ffff }, + { "darkblue", 0xff00008b }, + { "darkcyan", 0xff008b8b }, + { "darkgoldenrod", 0xffb8860b }, + { "darkgray", 0xffa9a9a9 }, + { "darkgrey", 0xffa9a9a9 }, + { "darkgreen", 0xff006400 }, + { "darkkhaki", 0xffbdb76b }, + { "darkmagenta", 0xff8b008b }, + { "darkolivegreen", 0xff556b2f }, + { "darkorange", 0xffff8c00 }, + { "darkorchid", 0xff9932cc }, + { "darkred", 0xff8b0000 }, + { "darksalmon", 0xffe9967a }, + { "darkseagreen", 0xff8fbc8f }, + { "darkslateblue", 0xff483d8b }, + { "darkslategray", 0xff2f4f4f }, + { "darkslategrey", 0xff2f4f4f }, + { "darkturquoise", 0xff00ced1 }, + { "darkviolet", 0xff9400d3 }, + { "deeppink", 0xffff1493 }, + { "deepskyblue", 0xff00bfff }, + { "dimgray", 0xff696969 }, + { "dimgrey", 0xff696969 }, + { "dodgerblue", 0xff1e90ff }, + { "firebrick", 0xffb22222 }, + { "floralwhite", 0xfffffaf0 }, + { "forestgreen", 0xff228b22 }, + { "fuchsia", 0xffff00ff }, + { "gainsboro", 0xffdcdcdc }, + { "ghostwhite", 0xfff8f8ff }, + { "gold", 0xffffd700 }, + { "goldenrod", 0xffdaa520 }, + { "gray", 0xff808080 }, + { "grey", 0xff808080 }, + { "green", 0xff008000 }, + { "greenyellow", 0xffadff2f }, + { "honeydew", 0xfff0fff0 }, + { "hotpink", 0xffff69b4 }, + { "indianred", 0xffcd5c5c }, + { "indigo", 0xff4b0082 }, + { "ivory", 0xfffffff0 }, + { "khaki", 0xfff0e68c }, + { "lavender", 0xffe6e6fa }, + { "lavenderblush", 0xfffff0f5 }, + { "lawngreen", 0xff7cfc00 }, + { "lemonchiffon", 0xfffffacd }, + { "lightblue", 0xffadd8e6 }, + { "lightcoral", 0xfff08080 }, + { "lightcyan", 0xffe0ffff }, + { "lightgoldenrodyellow", 0xfffafad2 }, + { "lightgray", 0xffd3d3d3 }, + { "lightgrey", 0xffd3d3d3 }, + { "lightgreen", 0xff90ee90 }, + { "lightpink", 0xffffb6c1 }, + { "lightsalmon", 0xffffa07a }, + { "lightseagreen", 0xff20b2aa }, + { "lightskyblue", 0xff87cefa }, + { "lightslategray", 0xff778899 }, + { "lightslategrey", 0xff778899 }, + { "lightsteelblue", 0xffb0c4de }, + { "lightyellow", 0xffffffe0 }, + { "lime", 0xff00ff00 }, + { "limegreen", 0xff32cd32 }, + { "linen", 0xfffaf0e6 }, + { "magenta", 0xffff00ff }, + { "maroon", 0xff800000 }, + { "mediumaquamarine", 0xff66cdaa }, + { "mediumblue", 0xff0000cd }, + { "mediumorchid", 0xffba55d3 }, + { "mediumpurple", 0xff9370d8 }, + { "mediumseagreen", 0xff3cb371 }, + { "mediumslateblue", 0xff7b68ee }, + { "mediumspringgreen", 0xff00fa9a }, + { "mediumturquoise", 0xff48d1cc }, + { "mediumvioletred", 0xffc71585 }, + { "midnightblue", 0xff191970 }, + { "mintcream", 0xfff5fffa }, + { "mistyrose", 0xffffe4e1 }, + { "moccasin", 0xffffe4b5 }, + { "navajowhite", 0xffffdead }, + { "navy", 0xff000080 }, + { "oldlace", 0xfffdf5e6 }, + { "olive", 0xff808000 }, + { "olivedrab", 0xff6b8e23 }, + { "orange", 0xffffa500 }, + { "orangered", 0xffff4500 }, + { "orchid", 0xffda70d6 }, + { "palegoldenrod", 0xffeee8aa }, + { "palegreen", 0xff98fb98 }, + { "paleturquoise", 0xffafeeee }, + { "palevioletred", 0xffd87093 }, + { "papayawhip", 0xffffefd5 }, + { "peachpuff", 0xffffdab9 }, + { "peru", 0xffcd853f }, + { "pink", 0xffffc0cb }, + { "plum", 0xffdda0dd }, + { "powderblue", 0xffb0e0e6 }, + { "purple", 0xff800080 }, + { "red", 0xffff0000 }, + { "rosybrown", 0xffbc8f8f }, + { "royalblue", 0xff4169e1 }, + { "saddlebrown", 0xff8b4513 }, + { "salmon", 0xfffa8072 }, + { "sandybrown", 0xfff4a460 }, + { "seagreen", 0xff2e8b57 }, + { "seashell", 0xfffff5ee }, + { "sienna", 0xffa0522d }, + { "silver", 0xffc0c0c0 }, + { "skyblue", 0xff87ceeb }, + { "slateblue", 0xff6a5acd }, + { "slategray", 0xff708090 }, + { "slategrey", 0xff708090 }, + { "snow", 0xfffffafa }, + { "springgreen", 0xff00ff7f }, + { "steelblue", 0xff4682b4 }, + { "tan", 0xffd2b48c }, + { "teal", 0xff008080 }, + { "thistle", 0xffd8bfd8 }, + { "tomato", 0xffff6347 }, + { "turquoise", 0xff40e0d0 }, + { "violet", 0xffee82ee }, + { "wheat", 0xfff5deb3 }, + { "white", 0xffffffff }, + { "whitesmoke", 0xfff5f5f5 }, + { "yellow", 0xffffff00 }, + { "yellowgreen", 0xff9acd32 } +}; + + +static void _toColor(const char* str, uint8_t* r, uint8_t* g, uint8_t* b, char** ref) +{ + unsigned int len = strlen(str); + char *red, *green, *blue; + unsigned char tr, tg, tb; + + if (len == 4 && str[0] == '#') { + //Case for "#456" should be interprete as "#445566" + if (isxdigit(str[1]) && isxdigit(str[2]) && isxdigit(str[3])) { + char tmp[3] = { '\0', '\0', '\0' }; + tmp[0] = str[1]; + tmp[1] = str[1]; + *r = strtol(tmp, nullptr, 16); + tmp[0] = str[2]; + tmp[1] = str[2]; + *g = strtol(tmp, nullptr, 16); + tmp[0] = str[3]; + tmp[1] = str[3]; + *b = strtol(tmp, nullptr, 16); + } + } else if (len == 7 && str[0] == '#') { + if (isxdigit(str[1]) && isxdigit(str[2]) && isxdigit(str[3]) && isxdigit(str[4]) && isxdigit(str[5]) && isxdigit(str[6])) { + char tmp[3] = { '\0', '\0', '\0' }; + tmp[0] = str[1]; + tmp[1] = str[2]; + *r = strtol(tmp, nullptr, 16); + tmp[0] = str[3]; + tmp[1] = str[4]; + *g = strtol(tmp, nullptr, 16); + tmp[0] = str[5]; + tmp[1] = str[6]; + *b = strtol(tmp, nullptr, 16); + } + } else if (len >= 10 && (str[0] == 'r' || str[0] == 'R') && (str[1] == 'g' || str[1] == 'G') && (str[2] == 'b' || str[2] == 'B') && str[3] == '(' && str[len - 1] == ')') { + tr = _parseColor(str + 4, &red); + if (red && *red == ',') { + tg = _parseColor(red + 1, &green); + if (green && *green == ',') { + tb = _parseColor(green + 1, &blue); + if (blue && blue[0] == ')' && blue[1] == '\0') { + *r = tr; + *g = tg; + *b = tb; + } + } + } + } else if (ref && len >= 3 && !strncmp(str, "url", 3)) { + if (*ref) free(*ref); + *ref = _idFromUrl((const char*)(str + 3)); + } else { + //Handle named color + for (unsigned int i = 0; i < (sizeof(colors) / sizeof(colors[0])); i++) { + if (!strcasecmp(colors[i].name, str)) { + *r = (((uint8_t*)(&(colors[i].value)))[2]); + *g = (((uint8_t*)(&(colors[i].value)))[1]); + *b = (((uint8_t*)(&(colors[i].value)))[0]); + return; + } + } + } +} + + +static char* _parseNumbersArray(char* str, float* points, int* ptCount, int len) +{ + int count = 0; + char* end = nullptr; + + str = _skipSpace(str, nullptr); + while ((count < len) && (isdigit(*str) || *str == '-' || *str == '+' || *str == '.')) { + points[count++] = strToFloat(str, &end); + str = end; + str = _skipSpace(str, nullptr); + if (*str == ',') ++str; + //Eat the rest of space + str = _skipSpace(str, nullptr); + } + *ptCount = count; + return str; +} + + +enum class MatrixState { + Unknown, + Matrix, + Translate, + Rotate, + Scale, + SkewX, + SkewY +}; + + +#define MATRIX_DEF(Name, Value) \ + { \ +#Name, sizeof(#Name), Value \ + } + + +static constexpr struct +{ + const char* tag; + int sz; + MatrixState state; +} matrixTags[] = { + MATRIX_DEF(matrix, MatrixState::Matrix), + MATRIX_DEF(translate, MatrixState::Translate), + MATRIX_DEF(rotate, MatrixState::Rotate), + MATRIX_DEF(scale, MatrixState::Scale), + MATRIX_DEF(skewX, MatrixState::SkewX), + MATRIX_DEF(skewY, MatrixState::SkewY) +}; + + +static void _matrixCompose(const Matrix* m1, const Matrix* m2, Matrix* dst) +{ + auto a11 = (m1->e11 * m2->e11) + (m1->e12 * m2->e21) + (m1->e13 * m2->e31); + auto a12 = (m1->e11 * m2->e12) + (m1->e12 * m2->e22) + (m1->e13 * m2->e32); + auto a13 = (m1->e11 * m2->e13) + (m1->e12 * m2->e23) + (m1->e13 * m2->e33); + + auto a21 = (m1->e21 * m2->e11) + (m1->e22 * m2->e21) + (m1->e23 * m2->e31); + auto a22 = (m1->e21 * m2->e12) + (m1->e22 * m2->e22) + (m1->e23 * m2->e32); + auto a23 = (m1->e21 * m2->e13) + (m1->e22 * m2->e23) + (m1->e23 * m2->e33); + + auto a31 = (m1->e31 * m2->e11) + (m1->e32 * m2->e21) + (m1->e33 * m2->e31); + auto a32 = (m1->e31 * m2->e12) + (m1->e32 * m2->e22) + (m1->e33 * m2->e32); + auto a33 = (m1->e31 * m2->e13) + (m1->e32 * m2->e23) + (m1->e33 * m2->e33); + + dst->e11 = a11; + dst->e12 = a12; + dst->e13 = a13; + dst->e21 = a21; + dst->e22 = a22; + dst->e23 = a23; + dst->e31 = a31; + dst->e32 = a32; + dst->e33 = a33; +} + + +/* parse transform attribute + * https://www.w3.org/TR/SVG/coords.html#TransformAttribute + */ +static Matrix* _parseTransformationMatrix(const char* value) +{ + const int POINT_CNT = 8; + + auto matrix = (Matrix*)malloc(sizeof(Matrix)); + if (!matrix) return nullptr; + *matrix = {1, 0, 0, 0, 1, 0, 0, 0, 1}; + + float points[POINT_CNT]; + int ptCount = 0; + char* str = (char*)value; + char* end = str + strlen(str); + + while (str < end) { + auto state = MatrixState::Unknown; + + if (isspace(*str) || (*str == ',')) { + ++str; + continue; + } + for (unsigned int i = 0; i < sizeof(matrixTags) / sizeof(matrixTags[0]); i++) { + if (!strncmp(matrixTags[i].tag, str, matrixTags[i].sz - 1)) { + state = matrixTags[i].state; + str += (matrixTags[i].sz - 1); + break; + } + } + if (state == MatrixState::Unknown) goto error; + + str = _skipSpace(str, end); + if (*str != '(') goto error; + ++str; + str = _parseNumbersArray(str, points, &ptCount, POINT_CNT); + if (*str != ')') goto error; + ++str; + + if (state == MatrixState::Matrix) { + if (ptCount != 6) goto error; + Matrix tmp = {points[0], points[2], points[4], points[1], points[3], points[5], 0, 0, 1}; + _matrixCompose(matrix, &tmp, matrix); + } else if (state == MatrixState::Translate) { + if (ptCount == 1) { + Matrix tmp = {1, 0, points[0], 0, 1, 0, 0, 0, 1}; + _matrixCompose(matrix, &tmp, matrix); + } else if (ptCount == 2) { + Matrix tmp = {1, 0, points[0], 0, 1, points[1], 0, 0, 1}; + _matrixCompose(matrix, &tmp, matrix); + } else goto error; + } else if (state == MatrixState::Rotate) { + //Transform to signed. + points[0] = fmod(points[0], (float)360); + if (points[0] < 0) points[0] += 360; + auto c = cosf(points[0] * (float)(M_PI / 180.0)); + auto s = sinf(points[0] * (float)(M_PI / 180.0)); + if (ptCount == 1) { + Matrix tmp = { c, -s, 0, s, c, 0, 0, 0, 1 }; + _matrixCompose(matrix, &tmp, matrix); + } else if (ptCount == 3) { + Matrix tmp = { 1, 0, points[1], 0, 1, points[2], 0, 0, 1 }; + _matrixCompose(matrix, &tmp, matrix); + tmp = { c, -s, 0, s, c, 0, 0, 0, 1 }; + _matrixCompose(matrix, &tmp, matrix); + tmp = { 1, 0, -points[1], 0, 1, -points[2], 0, 0, 1 }; + _matrixCompose(matrix, &tmp, matrix); + } else { + goto error; + } + } else if (state == MatrixState::Scale) { + if (ptCount < 1 || ptCount > 2) goto error; + auto sx = points[0]; + auto sy = sx; + if (ptCount == 2) sy = (float)points[1]; + Matrix tmp = { sx, 0, 0, 0, sy, 0, 0, 0, 1 }; + _matrixCompose(matrix, &tmp, matrix); + } + } + return matrix; +error: + if (matrix) free(matrix); + return nullptr; +} + + +#define LENGTH_DEF(Name, Value) \ + { \ +#Name, sizeof(#Name), Value \ + } + + +static void _postpone(Array& nodes, SvgNode *node, char* id) +{ + nodes.push({node, id}); +} + + +/* +// TODO - remove? +static constexpr struct +{ + const char* tag; + int sz; + SvgLengthType type; +} lengthTags[] = { + LENGTH_DEF(%, SvgLengthType::Percent), + LENGTH_DEF(px, SvgLengthType::Px), + LENGTH_DEF(pc, SvgLengthType::Pc), + LENGTH_DEF(pt, SvgLengthType::Pt), + LENGTH_DEF(mm, SvgLengthType::Mm), + LENGTH_DEF(cm, SvgLengthType::Cm), + LENGTH_DEF(in, SvgLengthType::In) +}; + +static float _parseLength(const char* str, SvgLengthType* type) +{ + float value; + int sz = strlen(str); + + *type = SvgLengthType::Px; + for (unsigned int i = 0; i < sizeof(lengthTags) / sizeof(lengthTags[0]); i++) { + if (lengthTags[i].sz - 1 == sz && !strncmp(lengthTags[i].tag, str, sz)) *type = lengthTags[i].type; + } + value = svgUtilStrtof(str, nullptr); + return value; +} +*/ + +static bool _parseStyleAttr(void* data, const char* key, const char* value); +static bool _parseStyleAttr(void* data, const char* key, const char* value, bool style); + + +static bool _attrParseSvgNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgNode* node = loader->svgParse->node; + SvgDocNode* doc = &(node->node.doc); + + if (!strcmp(key, "width")) { + doc->w = _toFloat(loader->svgParse, value, SvgParserLengthType::Horizontal); + if (strstr(value, "%") && !(doc->viewFlag & SvgViewFlag::Viewbox)) { + doc->viewFlag = (doc->viewFlag | SvgViewFlag::WidthInPercent); + } else { + doc->viewFlag = (doc->viewFlag | SvgViewFlag::Width); + } + } else if (!strcmp(key, "height")) { + doc->h = _toFloat(loader->svgParse, value, SvgParserLengthType::Vertical); + if (strstr(value, "%") && !(doc->viewFlag & SvgViewFlag::Viewbox)) { + doc->viewFlag = (doc->viewFlag | SvgViewFlag::HeightInPercent); + } else { + doc->viewFlag = (doc->viewFlag | SvgViewFlag::Height); + } + } else if (!strcmp(key, "viewBox")) { + if (_parseNumber(&value, &doc->vx)) { + if (_parseNumber(&value, &doc->vy)) { + if (_parseNumber(&value, &doc->vw)) { + if (_parseNumber(&value, &doc->vh)) { + doc->viewFlag = (doc->viewFlag | SvgViewFlag::Viewbox); + loader->svgParse->global.h = doc->vh; + } + loader->svgParse->global.w = doc->vw; + } + loader->svgParse->global.y = doc->vy; + } + loader->svgParse->global.x = doc->vx; + } + if ((doc->viewFlag & SvgViewFlag::Viewbox) && (doc->vw < 0.0f || doc->vh < 0.0f)) { + doc->viewFlag = (SvgViewFlag)((uint32_t)doc->viewFlag & ~(uint32_t)SvgViewFlag::Viewbox); + TVGLOG("SVG", "Negative values of the width and/or height - the attribute invalidated."); + } + if (!(doc->viewFlag & SvgViewFlag::Viewbox)) { + loader->svgParse->global.x = loader->svgParse->global.y = 0.0f; + loader->svgParse->global.w = loader->svgParse->global.h = 1.0f; + } + } else if (!strcmp(key, "preserveAspectRatio")) { + _parseAspectRatio(&value, &doc->align, &doc->meetOrSlice); + } else if (!strcmp(key, "style")) { + return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); +#ifdef THORVG_LOG_ENABLED + } else if ((!strcmp(key, "x") || !strcmp(key, "y")) && fabsf(strToFloat(value, nullptr)) > FLT_EPSILON) { + TVGLOG("SVG", "Unsupported attributes used [Elements type: Svg][Attribute: %s][Value: %s]", key, value); +#endif + } else { + return _parseStyleAttr(loader, key, value, false); + } + return true; +} + + +//https://www.w3.org/TR/SVGTiny12/painting.html#SpecifyingPaint +static void _handlePaintAttr(SvgPaint* paint, const char* value) +{ + if (!strcmp(value, "none")) { + //No paint property + paint->none = true; + return; + } + paint->none = false; + if (!strcmp(value, "currentColor")) { + paint->curColor = true; + return; + } + _toColor(value, &paint->color.r, &paint->color.g, &paint->color.b, &paint->url); +} + + +static void _handleColorAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) +{ + SvgStyleProperty* style = node->style; + style->curColorSet = true; + _toColor(value, &style->color.r, &style->color.g, &style->color.b, nullptr); +} + + +static void _handleFillAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) +{ + SvgStyleProperty* style = node->style; + style->fill.flags = (style->fill.flags | SvgFillFlags::Paint); + _handlePaintAttr(&style->fill.paint, value); +} + + +static void _handleStrokeAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) +{ + SvgStyleProperty* style = node->style; + style->stroke.flags = (style->stroke.flags | SvgStrokeFlags::Paint); + _handlePaintAttr(&style->stroke.paint, value); +} + + +static void _handleStrokeOpacityAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) +{ + node->style->stroke.flags = (node->style->stroke.flags | SvgStrokeFlags::Opacity); + node->style->stroke.opacity = _toOpacity(value); +} + +static void _handleStrokeDashArrayAttr(SvgLoaderData* loader, SvgNode* node, const char* value) +{ + node->style->stroke.flags = (node->style->stroke.flags | SvgStrokeFlags::Dash); + _parseDashArray(loader, value, &node->style->stroke.dash); +} + +static void _handleStrokeDashOffsetAttr(SvgLoaderData* loader, SvgNode* node, const char* value) +{ + node->style->stroke.flags = (node->style->stroke.flags | SvgStrokeFlags::DashOffset); + node->style->stroke.dash.offset = _toFloat(loader->svgParse, value, SvgParserLengthType::Horizontal); +} + +static void _handleStrokeWidthAttr(SvgLoaderData* loader, SvgNode* node, const char* value) +{ + node->style->stroke.flags = (node->style->stroke.flags | SvgStrokeFlags::Width); + node->style->stroke.width = _toFloat(loader->svgParse, value, SvgParserLengthType::Horizontal); +} + + +static void _handleStrokeLineCapAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) +{ + node->style->stroke.flags = (node->style->stroke.flags | SvgStrokeFlags::Cap); + node->style->stroke.cap = _toLineCap(value); +} + + +static void _handleStrokeLineJoinAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) +{ + node->style->stroke.flags = (node->style->stroke.flags | SvgStrokeFlags::Join); + node->style->stroke.join = _toLineJoin(value); +} + +static void _handleStrokeMiterlimitAttr(SvgLoaderData* loader, SvgNode* node, const char* value) +{ + char* end = nullptr; + const float miterlimit = strToFloat(value, &end); + + // https://www.w3.org/TR/SVG2/painting.html#LineJoin + // - A negative value for stroke-miterlimit must be treated as an illegal value. + if (miterlimit < 0.0f) { + TVGERR("SVG", "A stroke-miterlimit change (%f <- %f) with a negative value is omitted.", + node->style->stroke.miterlimit, miterlimit); + return; + } + + node->style->stroke.flags = (node->style->stroke.flags | SvgStrokeFlags::Miterlimit); + node->style->stroke.miterlimit = miterlimit; +} + +static void _handleFillRuleAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) +{ + node->style->fill.flags = (node->style->fill.flags | SvgFillFlags::FillRule); + node->style->fill.fillRule = _toFillRule(value); +} + + +static void _handleOpacityAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) +{ + node->style->opacity = _toOpacity(value); +} + + +static void _handleFillOpacityAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) +{ + node->style->fill.flags = (node->style->fill.flags | SvgFillFlags::Opacity); + node->style->fill.opacity = _toOpacity(value); +} + + +static void _handleTransformAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) +{ + node->transform = _parseTransformationMatrix(value); +} + + +static void _handleClipPathAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) +{ + SvgStyleProperty* style = node->style; + int len = strlen(value); + if (len >= 3 && !strncmp(value, "url", 3)) { + if (style->clipPath.url) free(style->clipPath.url); + style->clipPath.url = _idFromUrl((const char*)(value + 3)); + } +} + + +static void _handleMaskAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) +{ + SvgStyleProperty* style = node->style; + int len = strlen(value); + if (len >= 3 && !strncmp(value, "url", 3)) { + if (style->mask.url) free(style->mask.url); + style->mask.url = _idFromUrl((const char*)(value + 3)); + } +} + + +static void _handleMaskTypeAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) +{ + node->node.mask.type = _toMaskType(value); +} + + +static void _handleDisplayAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) +{ + //TODO : The display attribute can have various values as well as "none". + // The default is "inline" which means visible and "none" means invisible. + // Depending on the type of node, additional functionality may be required. + // refer to https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/display + if (!strcmp(value, "none")) node->display = false; + else node->display = true; +} + + +static void _handlePaintOrderAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) +{ + node->style->flags = (node->style->flags | SvgStyleFlags::PaintOrder); + node->style->paintOrder = _toPaintOrder(value); +} + + +static void _handleCssClassAttr(SvgLoaderData* loader, SvgNode* node, const char* value) +{ + auto cssClass = &node->style->cssClass; + + if (*cssClass && value) free(*cssClass); + *cssClass = _copyId(value); + + bool cssClassFound = false; + + //css styling: tag.name has higher priority than .name + if (auto cssNode = cssFindStyleNode(loader->cssStyle, *cssClass, node->type)) { + cssClassFound = true; + cssCopyStyleAttr(node, cssNode); + } + if (auto cssNode = cssFindStyleNode(loader->cssStyle, *cssClass)) { + cssClassFound = true; + cssCopyStyleAttr(node, cssNode); + } + + if (!cssClassFound) _postpone(loader->nodesToStyle, node, *cssClass); +} + + +typedef void (*styleMethod)(SvgLoaderData* loader, SvgNode* node, const char* value); + +#define STYLE_DEF(Name, Name1, Flag) { #Name, sizeof(#Name), _handle##Name1##Attr, Flag } + + +static constexpr struct +{ + const char* tag; + int sz; + styleMethod tagHandler; + SvgStyleFlags flag; +} styleTags[] = { + STYLE_DEF(color, Color, SvgStyleFlags::Color), + STYLE_DEF(fill, Fill, SvgStyleFlags::Fill), + STYLE_DEF(fill-rule, FillRule, SvgStyleFlags::FillRule), + STYLE_DEF(fill-opacity, FillOpacity, SvgStyleFlags::FillOpacity), + STYLE_DEF(opacity, Opacity, SvgStyleFlags::Opacity), + STYLE_DEF(stroke, Stroke, SvgStyleFlags::Stroke), + STYLE_DEF(stroke-width, StrokeWidth, SvgStyleFlags::StrokeWidth), + STYLE_DEF(stroke-linejoin, StrokeLineJoin, SvgStyleFlags::StrokeLineJoin), + STYLE_DEF(stroke-miterlimit, StrokeMiterlimit, SvgStyleFlags::StrokeMiterlimit), + STYLE_DEF(stroke-linecap, StrokeLineCap, SvgStyleFlags::StrokeLineCap), + STYLE_DEF(stroke-opacity, StrokeOpacity, SvgStyleFlags::StrokeOpacity), + STYLE_DEF(stroke-dasharray, StrokeDashArray, SvgStyleFlags::StrokeDashArray), + STYLE_DEF(stroke-dashoffset, StrokeDashOffset, SvgStyleFlags::StrokeDashOffset), + STYLE_DEF(transform, Transform, SvgStyleFlags::Transform), + STYLE_DEF(clip-path, ClipPath, SvgStyleFlags::ClipPath), + STYLE_DEF(mask, Mask, SvgStyleFlags::Mask), + STYLE_DEF(mask-type, MaskType, SvgStyleFlags::MaskType), + STYLE_DEF(display, Display, SvgStyleFlags::Display), + STYLE_DEF(paint-order, PaintOrder, SvgStyleFlags::PaintOrder) +}; + + +static bool _parseStyleAttr(void* data, const char* key, const char* value, bool style) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgNode* node = loader->svgParse->node; + int sz; + if (!key || !value) return false; + + //Trim the white space + key = _skipSpace(key, nullptr); + value = _skipSpace(value, nullptr); + + sz = strlen(key); + for (unsigned int i = 0; i < sizeof(styleTags) / sizeof(styleTags[0]); i++) { + if (styleTags[i].sz - 1 == sz && !strncmp(styleTags[i].tag, key, sz)) { + bool importance = false; + if (auto ptr = strstr(value, "!important")) { + size_t size = ptr - value; + while (size > 0 && isspace(value[size - 1])) { + size--; + } + value = strDuplicate(value, size); + importance = true; + } + if (style) { + if (importance || !(node->style->flagsImportance & styleTags[i].flag)) { + styleTags[i].tagHandler(loader, node, value); + node->style->flags = (node->style->flags | styleTags[i].flag); + } + } else if (!(node->style->flags & styleTags[i].flag)) { + styleTags[i].tagHandler(loader, node, value); + } + if (importance) { + node->style->flagsImportance = (node->style->flags | styleTags[i].flag); + free(const_cast(value)); + } + return true; + } + } + + return false; +} + + +static bool _parseStyleAttr(void* data, const char* key, const char* value) +{ + return _parseStyleAttr(data, key, value, true); +} + + +/* parse g node + * https://www.w3.org/TR/SVG/struct.html#Groups + */ +static bool _attrParseGNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgNode* node = loader->svgParse->node; + + if (!strcmp(key, "style")) { + return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + } else if (!strcmp(key, "transform")) { + node->transform = _parseTransformationMatrix(value); + } else if (!strcmp(key, "id")) { + if (node->id && value) free(node->id); + node->id = _copyId(value); + } else if (!strcmp(key, "class")) { + _handleCssClassAttr(loader, node, value); + } else if (!strcmp(key, "clip-path")) { + _handleClipPathAttr(loader, node, value); + } else if (!strcmp(key, "mask")) { + _handleMaskAttr(loader, node, value); + } else { + return _parseStyleAttr(loader, key, value, false); + } + return true; +} + + +/* parse clipPath node + * https://www.w3.org/TR/SVG/struct.html#Groups + */ +static bool _attrParseClipPathNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgNode* node = loader->svgParse->node; + SvgClipNode* clip = &(node->node.clip); + + if (!strcmp(key, "style")) { + return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + } else if (!strcmp(key, "transform")) { + node->transform = _parseTransformationMatrix(value); + } else if (!strcmp(key, "id")) { + if (node->id && value) free(node->id); + node->id = _copyId(value); + } else if (!strcmp(key, "class")) { + _handleCssClassAttr(loader, node, value); + } else if (!strcmp(key, "clipPathUnits")) { + if (!strcmp(value, "objectBoundingBox")) clip->userSpace = false; + } else { + return _parseStyleAttr(loader, key, value, false); + } + return true; +} + + +static bool _attrParseMaskNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgNode* node = loader->svgParse->node; + SvgMaskNode* mask = &(node->node.mask); + + if (!strcmp(key, "style")) { + return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + } else if (!strcmp(key, "transform")) { + node->transform = _parseTransformationMatrix(value); + } else if (!strcmp(key, "id")) { + if (node->id && value) free(node->id); + node->id = _copyId(value); + } else if (!strcmp(key, "class")) { + _handleCssClassAttr(loader, node, value); + } else if (!strcmp(key, "maskContentUnits")) { + if (!strcmp(value, "objectBoundingBox")) mask->userSpace = false; + } else if (!strcmp(key, "mask-type")) { + mask->type = _toMaskType(value); + } else { + return _parseStyleAttr(loader, key, value, false); + } + return true; +} + + +static bool _attrParseCssStyleNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgNode* node = loader->svgParse->node; + + if (!strcmp(key, "id")) { + if (node->id && value) free(node->id); + node->id = _copyId(value); + } else { + return _parseStyleAttr(loader, key, value, false); + } + return true; +} + + +static bool _attrParseSymbolNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgNode* node = loader->svgParse->node; + SvgSymbolNode* symbol = &(node->node.symbol); + + if (!strcmp(key, "viewBox")) { + if (!_parseNumber(&value, &symbol->vx) || !_parseNumber(&value, &symbol->vy)) return false; + if (!_parseNumber(&value, &symbol->vw) || !_parseNumber(&value, &symbol->vh)) return false; + symbol->hasViewBox = true; + } else if (!strcmp(key, "width")) { + symbol->w = _toFloat(loader->svgParse, value, SvgParserLengthType::Horizontal); + symbol->hasWidth = true; + } else if (!strcmp(key, "height")) { + symbol->h = _toFloat(loader->svgParse, value, SvgParserLengthType::Vertical); + symbol->hasHeight = true; + } else if (!strcmp(key, "preserveAspectRatio")) { + _parseAspectRatio(&value, &symbol->align, &symbol->meetOrSlice); + } else if (!strcmp(key, "overflow")) { + if (!strcmp(value, "visible")) symbol->overflowVisible = true; + } else { + return _attrParseGNode(data, key, value); + } + + return true; +} + + +static SvgNode* _createNode(SvgNode* parent, SvgNodeType type) +{ + SvgNode* node = (SvgNode*)calloc(1, sizeof(SvgNode)); + + if (!node) return nullptr; + + //Default fill property + node->style = (SvgStyleProperty*)calloc(1, sizeof(SvgStyleProperty)); + + if (!node->style) { + free(node); + return nullptr; + } + + //Update the default value of stroke and fill + //https://www.w3.org/TR/SVGTiny12/painting.html#SpecifyingPaint + node->style->fill.paint.none = false; + //Default fill opacity is 1 + node->style->fill.opacity = 255; + node->style->opacity = 255; + //Default current color is not set + node->style->fill.paint.curColor = false; + node->style->curColorSet = false; + //Default fill rule is nonzero + node->style->fill.fillRule = FillRule::Winding; + + //Default stroke is none + node->style->stroke.paint.none = true; + //Default stroke opacity is 1 + node->style->stroke.opacity = 255; + //Default stroke current color is not set + node->style->stroke.paint.curColor = false; + //Default stroke width is 1 + node->style->stroke.width = 1; + //Default line cap is butt + node->style->stroke.cap = StrokeCap::Butt; + //Default line join is miter + node->style->stroke.join = StrokeJoin::Miter; + node->style->stroke.miterlimit = 4.0f; + node->style->stroke.scale = 1.0; + + node->style->paintOrder = _toPaintOrder("fill stroke"); + + //Default display is true("inline"). + node->display = true; + + node->parent = parent; + node->type = type; + + if (parent) parent->child.push(node); + return node; +} + + +static SvgNode* _createDefsNode(TVG_UNUSED SvgLoaderData* loader, TVG_UNUSED SvgNode* parent, const char* buf, unsigned bufLength, TVG_UNUSED parseAttributes func) +{ + if (loader->def && loader->doc->node.doc.defs) return loader->def; + SvgNode* node = _createNode(nullptr, SvgNodeType::Defs); + + loader->def = node; + loader->doc->node.doc.defs = node; + return node; +} + + +static SvgNode* _createGNode(TVG_UNUSED SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) +{ + loader->svgParse->node = _createNode(parent, SvgNodeType::G); + if (!loader->svgParse->node) return nullptr; + + func(buf, bufLength, _attrParseGNode, loader); + return loader->svgParse->node; +} + + +static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) +{ + loader->svgParse->node = _createNode(parent, SvgNodeType::Doc); + if (!loader->svgParse->node) return nullptr; + SvgDocNode* doc = &(loader->svgParse->node->node.doc); + + loader->svgParse->global.w = 1.0f; + loader->svgParse->global.h = 1.0f; + + doc->align = AspectRatioAlign::XMidYMid; + doc->meetOrSlice = AspectRatioMeetOrSlice::Meet; + doc->viewFlag = SvgViewFlag::None; + func(buf, bufLength, _attrParseSvgNode, loader); + + if (!(doc->viewFlag & SvgViewFlag::Viewbox)) { + if (doc->viewFlag & SvgViewFlag::Width) { + loader->svgParse->global.w = doc->w; + } + if (doc->viewFlag & SvgViewFlag::Height) { + loader->svgParse->global.h = doc->h; + } + } + return loader->svgParse->node; +} + + +static SvgNode* _createMaskNode(SvgLoaderData* loader, SvgNode* parent, TVG_UNUSED const char* buf, TVG_UNUSED unsigned bufLength, parseAttributes func) +{ + loader->svgParse->node = _createNode(parent, SvgNodeType::Mask); + if (!loader->svgParse->node) return nullptr; + + loader->svgParse->node->node.mask.userSpace = true; + loader->svgParse->node->node.mask.type = SvgMaskType::Luminance; + + func(buf, bufLength, _attrParseMaskNode, loader); + + return loader->svgParse->node; +} + + +static SvgNode* _createClipPathNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) +{ + loader->svgParse->node = _createNode(parent, SvgNodeType::ClipPath); + if (!loader->svgParse->node) return nullptr; + + loader->svgParse->node->display = false; + loader->svgParse->node->node.clip.userSpace = true; + + func(buf, bufLength, _attrParseClipPathNode, loader); + + return loader->svgParse->node; +} + + +static SvgNode* _createCssStyleNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) +{ + loader->svgParse->node = _createNode(parent, SvgNodeType::CssStyle); + if (!loader->svgParse->node) return nullptr; + + func(buf, bufLength, _attrParseCssStyleNode, loader); + + return loader->svgParse->node; +} + + +static SvgNode* _createSymbolNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) +{ + loader->svgParse->node = _createNode(parent, SvgNodeType::Symbol); + if (!loader->svgParse->node) return nullptr; + + loader->svgParse->node->display = false; + loader->svgParse->node->node.symbol.align = AspectRatioAlign::XMidYMid; + loader->svgParse->node->node.symbol.meetOrSlice = AspectRatioMeetOrSlice::Meet; + loader->svgParse->node->node.symbol.overflowVisible = false; + + loader->svgParse->node->node.symbol.hasViewBox = false; + loader->svgParse->node->node.symbol.hasWidth = false; + loader->svgParse->node->node.symbol.hasHeight = false; + loader->svgParse->node->node.symbol.vx = 0.0f; + loader->svgParse->node->node.symbol.vy = 0.0f; + + func(buf, bufLength, _attrParseSymbolNode, loader); + + return loader->svgParse->node; +} + + +static bool _attrParsePathNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgNode* node = loader->svgParse->node; + SvgPathNode* path = &(node->node.path); + + if (!strcmp(key, "d")) { + if (path->path) free(path->path); + //Temporary: need to copy + path->path = _copyId(value); + } else if (!strcmp(key, "style")) { + return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + } else if (!strcmp(key, "clip-path")) { + _handleClipPathAttr(loader, node, value); + } else if (!strcmp(key, "mask")) { + _handleMaskAttr(loader, node, value); + } else if (!strcmp(key, "id")) { + if (node->id && value) free(node->id); + node->id = _copyId(value); + } else if (!strcmp(key, "class")) { + _handleCssClassAttr(loader, node, value); + } else { + return _parseStyleAttr(loader, key, value, false); + } + return true; +} + + +static SvgNode* _createPathNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) +{ + loader->svgParse->node = _createNode(parent, SvgNodeType::Path); + + if (!loader->svgParse->node) return nullptr; + + func(buf, bufLength, _attrParsePathNode, loader); + + return loader->svgParse->node; +} + + +static constexpr struct +{ + const char* tag; + SvgParserLengthType type; + int sz; + size_t offset; +} circleTags[] = { + {"cx", SvgParserLengthType::Horizontal, sizeof("cx"), offsetof(SvgCircleNode, cx)}, + {"cy", SvgParserLengthType::Vertical, sizeof("cy"), offsetof(SvgCircleNode, cy)}, + {"r", SvgParserLengthType::Other, sizeof("r"), offsetof(SvgCircleNode, r)} +}; + + +/* parse the attributes for a circle element. + * https://www.w3.org/TR/SVG/shapes.html#CircleElement + */ +static bool _attrParseCircleNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgNode* node = loader->svgParse->node; + SvgCircleNode* circle = &(node->node.circle); + unsigned char* array; + int sz = strlen(key); + + array = (unsigned char*)circle; + for (unsigned int i = 0; i < sizeof(circleTags) / sizeof(circleTags[0]); i++) { + if (circleTags[i].sz - 1 == sz && !strncmp(circleTags[i].tag, key, sz)) { + *((float*)(array + circleTags[i].offset)) = _toFloat(loader->svgParse, value, circleTags[i].type); + return true; + } + } + + if (!strcmp(key, "style")) { + return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + } else if (!strcmp(key, "clip-path")) { + _handleClipPathAttr(loader, node, value); + } else if (!strcmp(key, "mask")) { + _handleMaskAttr(loader, node, value); + } else if (!strcmp(key, "id")) { + if (node->id && value) free(node->id); + node->id = _copyId(value); + } else if (!strcmp(key, "class")) { + _handleCssClassAttr(loader, node, value); + } else { + return _parseStyleAttr(loader, key, value, false); + } + return true; +} + + +static SvgNode* _createCircleNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) +{ + loader->svgParse->node = _createNode(parent, SvgNodeType::Circle); + + if (!loader->svgParse->node) return nullptr; + + func(buf, bufLength, _attrParseCircleNode, loader); + return loader->svgParse->node; +} + + +static constexpr struct +{ + const char* tag; + SvgParserLengthType type; + int sz; + size_t offset; +} ellipseTags[] = { + {"cx", SvgParserLengthType::Horizontal, sizeof("cx"), offsetof(SvgEllipseNode, cx)}, + {"cy", SvgParserLengthType::Vertical, sizeof("cy"), offsetof(SvgEllipseNode, cy)}, + {"rx", SvgParserLengthType::Horizontal, sizeof("rx"), offsetof(SvgEllipseNode, rx)}, + {"ry", SvgParserLengthType::Vertical, sizeof("ry"), offsetof(SvgEllipseNode, ry)} +}; + + +/* parse the attributes for an ellipse element. + * https://www.w3.org/TR/SVG/shapes.html#EllipseElement + */ +static bool _attrParseEllipseNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgNode* node = loader->svgParse->node; + SvgEllipseNode* ellipse = &(node->node.ellipse); + unsigned char* array; + int sz = strlen(key); + + array = (unsigned char*)ellipse; + for (unsigned int i = 0; i < sizeof(ellipseTags) / sizeof(ellipseTags[0]); i++) { + if (ellipseTags[i].sz - 1 == sz && !strncmp(ellipseTags[i].tag, key, sz)) { + *((float*)(array + ellipseTags[i].offset)) = _toFloat(loader->svgParse, value, ellipseTags[i].type); + return true; + } + } + + if (!strcmp(key, "id")) { + if (node->id && value) free(node->id); + node->id = _copyId(value); + } else if (!strcmp(key, "class")) { + _handleCssClassAttr(loader, node, value); + } else if (!strcmp(key, "style")) { + return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + } else if (!strcmp(key, "clip-path")) { + _handleClipPathAttr(loader, node, value); + } else if (!strcmp(key, "mask")) { + _handleMaskAttr(loader, node, value); + } else { + return _parseStyleAttr(loader, key, value, false); + } + return true; +} + + +static SvgNode* _createEllipseNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) +{ + loader->svgParse->node = _createNode(parent, SvgNodeType::Ellipse); + + if (!loader->svgParse->node) return nullptr; + + func(buf, bufLength, _attrParseEllipseNode, loader); + return loader->svgParse->node; +} + + +static bool _attrParsePolygonPoints(const char* str, SvgPolygonNode* polygon) +{ + float num; + while (_parseNumber(&str, &num)) polygon->pts.push(num); + return true; +} + + +/* parse the attributes for a polygon element. + * https://www.w3.org/TR/SVG/shapes.html#PolylineElement + */ +static bool _attrParsePolygonNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgNode* node = loader->svgParse->node; + SvgPolygonNode* polygon = nullptr; + + if (node->type == SvgNodeType::Polygon) polygon = &(node->node.polygon); + else polygon = &(node->node.polyline); + + if (!strcmp(key, "points")) { + return _attrParsePolygonPoints(value, polygon); + } else if (!strcmp(key, "style")) { + return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + } else if (!strcmp(key, "clip-path")) { + _handleClipPathAttr(loader, node, value); + } else if (!strcmp(key, "mask")) { + _handleMaskAttr(loader, node, value); + } else if (!strcmp(key, "id")) { + if (node->id && value) free(node->id); + node->id = _copyId(value); + } else if (!strcmp(key, "class")) { + _handleCssClassAttr(loader, node, value); + } else { + return _parseStyleAttr(loader, key, value, false); + } + return true; +} + + +static SvgNode* _createPolygonNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) +{ + loader->svgParse->node = _createNode(parent, SvgNodeType::Polygon); + + if (!loader->svgParse->node) return nullptr; + + func(buf, bufLength, _attrParsePolygonNode, loader); + return loader->svgParse->node; +} + + +static SvgNode* _createPolylineNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) +{ + loader->svgParse->node = _createNode(parent, SvgNodeType::Polyline); + + if (!loader->svgParse->node) return nullptr; + + func(buf, bufLength, _attrParsePolygonNode, loader); + return loader->svgParse->node; +} + +static constexpr struct +{ + const char* tag; + SvgParserLengthType type; + int sz; + size_t offset; +} rectTags[] = { + {"x", SvgParserLengthType::Horizontal, sizeof("x"), offsetof(SvgRectNode, x)}, + {"y", SvgParserLengthType::Vertical, sizeof("y"), offsetof(SvgRectNode, y)}, + {"width", SvgParserLengthType::Horizontal, sizeof("width"), offsetof(SvgRectNode, w)}, + {"height", SvgParserLengthType::Vertical, sizeof("height"), offsetof(SvgRectNode, h)}, + {"rx", SvgParserLengthType::Horizontal, sizeof("rx"), offsetof(SvgRectNode, rx)}, + {"ry", SvgParserLengthType::Vertical, sizeof("ry"), offsetof(SvgRectNode, ry)} +}; + + +/* parse the attributes for a rect element. + * https://www.w3.org/TR/SVG/shapes.html#RectElement + */ +static bool _attrParseRectNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgNode* node = loader->svgParse->node; + SvgRectNode* rect = &(node->node.rect); + unsigned char* array; + bool ret = true; + int sz = strlen(key); + + array = (unsigned char*)rect; + for (unsigned int i = 0; i < sizeof(rectTags) / sizeof(rectTags[0]); i++) { + if (rectTags[i].sz - 1 == sz && !strncmp(rectTags[i].tag, key, sz)) { + *((float*)(array + rectTags[i].offset)) = _toFloat(loader->svgParse, value, rectTags[i].type); + + //Case if only rx or ry is declared + if (!strncmp(rectTags[i].tag, "rx", sz)) rect->hasRx = true; + if (!strncmp(rectTags[i].tag, "ry", sz)) rect->hasRy = true; + + if ((rect->rx >= FLT_EPSILON) && (rect->ry < FLT_EPSILON) && rect->hasRx && !rect->hasRy) rect->ry = rect->rx; + if ((rect->ry >= FLT_EPSILON) && (rect->rx < FLT_EPSILON) && !rect->hasRx && rect->hasRy) rect->rx = rect->ry; + return ret; + } + } + + if (!strcmp(key, "id")) { + if (node->id && value) free(node->id); + node->id = _copyId(value); + } else if (!strcmp(key, "class")) { + _handleCssClassAttr(loader, node, value); + } else if (!strcmp(key, "style")) { + ret = simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + } else if (!strcmp(key, "clip-path")) { + _handleClipPathAttr(loader, node, value); + } else if (!strcmp(key, "mask")) { + _handleMaskAttr(loader, node, value); + } else { + ret = _parseStyleAttr(loader, key, value, false); + } + + return ret; +} + + +static SvgNode* _createRectNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) +{ + loader->svgParse->node = _createNode(parent, SvgNodeType::Rect); + + if (!loader->svgParse->node) return nullptr; + + loader->svgParse->node->node.rect.hasRx = loader->svgParse->node->node.rect.hasRy = false; + + func(buf, bufLength, _attrParseRectNode, loader); + return loader->svgParse->node; +} + + +static constexpr struct +{ + const char* tag; + SvgParserLengthType type; + int sz; + size_t offset; +} lineTags[] = { + {"x1", SvgParserLengthType::Horizontal, sizeof("x1"), offsetof(SvgLineNode, x1)}, + {"y1", SvgParserLengthType::Vertical, sizeof("y1"), offsetof(SvgLineNode, y1)}, + {"x2", SvgParserLengthType::Horizontal, sizeof("x2"), offsetof(SvgLineNode, x2)}, + {"y2", SvgParserLengthType::Vertical, sizeof("y2"), offsetof(SvgLineNode, y2)} +}; + + +/* parse the attributes for a line element. + * https://www.w3.org/TR/SVG/shapes.html#LineElement + */ +static bool _attrParseLineNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgNode* node = loader->svgParse->node; + SvgLineNode* line = &(node->node.line); + unsigned char* array; + int sz = strlen(key); + + array = (unsigned char*)line; + for (unsigned int i = 0; i < sizeof(lineTags) / sizeof(lineTags[0]); i++) { + if (lineTags[i].sz - 1 == sz && !strncmp(lineTags[i].tag, key, sz)) { + *((float*)(array + lineTags[i].offset)) = _toFloat(loader->svgParse, value, lineTags[i].type); + return true; + } + } + + if (!strcmp(key, "id")) { + if (node->id && value) free(node->id); + node->id = _copyId(value); + } else if (!strcmp(key, "class")) { + _handleCssClassAttr(loader, node, value); + } else if (!strcmp(key, "style")) { + return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + } else if (!strcmp(key, "clip-path")) { + _handleClipPathAttr(loader, node, value); + } else if (!strcmp(key, "mask")) { + _handleMaskAttr(loader, node, value); + } else { + return _parseStyleAttr(loader, key, value, false); + } + return true; +} + + +static SvgNode* _createLineNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) +{ + loader->svgParse->node = _createNode(parent, SvgNodeType::Line); + + if (!loader->svgParse->node) return nullptr; + + func(buf, bufLength, _attrParseLineNode, loader); + return loader->svgParse->node; +} + + +static char* _idFromHref(const char* href) +{ + href = _skipSpace(href, nullptr); + if ((*href) == '#') href++; + return strdup(href); +} + + +static constexpr struct +{ + const char* tag; + SvgParserLengthType type; + int sz; + size_t offset; +} imageTags[] = { + {"x", SvgParserLengthType::Horizontal, sizeof("x"), offsetof(SvgRectNode, x)}, + {"y", SvgParserLengthType::Vertical, sizeof("y"), offsetof(SvgRectNode, y)}, + {"width", SvgParserLengthType::Horizontal, sizeof("width"), offsetof(SvgRectNode, w)}, + {"height", SvgParserLengthType::Vertical, sizeof("height"), offsetof(SvgRectNode, h)}, +}; + + +/* parse the attributes for a image element. + * https://www.w3.org/TR/SVG/embedded.html#ImageElement + */ +static bool _attrParseImageNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgNode* node = loader->svgParse->node; + SvgImageNode* image = &(node->node.image); + unsigned char* array; + int sz = strlen(key); + + array = (unsigned char*)image; + for (unsigned int i = 0; i < sizeof(imageTags) / sizeof(imageTags[0]); i++) { + if (imageTags[i].sz - 1 == sz && !strncmp(imageTags[i].tag, key, sz)) { + *((float*)(array + imageTags[i].offset)) = _toFloat(loader->svgParse, value, imageTags[i].type); + return true; + } + } + + if (!strcmp(key, "href") || !strcmp(key, "xlink:href")) { + if (image->href && value) free(image->href); + image->href = _idFromHref(value); + } else if (!strcmp(key, "id")) { + if (node->id && value) free(node->id); + node->id = _copyId(value); + } else if (!strcmp(key, "class")) { + _handleCssClassAttr(loader, node, value); + } else if (!strcmp(key, "style")) { + return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + } else if (!strcmp(key, "clip-path")) { + _handleClipPathAttr(loader, node, value); + } else if (!strcmp(key, "mask")) { + _handleMaskAttr(loader, node, value); + } else if (!strcmp(key, "transform")) { + node->transform = _parseTransformationMatrix(value); + } else { + return _parseStyleAttr(loader, key, value); + } + return true; +} + + +static SvgNode* _createImageNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) +{ + loader->svgParse->node = _createNode(parent, SvgNodeType::Image); + + if (!loader->svgParse->node) return nullptr; + + func(buf, bufLength, _attrParseImageNode, loader); + return loader->svgParse->node; +} + + +static SvgNode* _getDefsNode(SvgNode* node) +{ + if (!node) return nullptr; + + while (node->parent != nullptr) { + node = node->parent; + } + + if (node->type == SvgNodeType::Doc) return node->node.doc.defs; + if (node->type == SvgNodeType::Defs) return node; + + return nullptr; +} + + +static SvgNode* _findNodeById(SvgNode *node, const char* id) +{ + if (!node) return nullptr; + + SvgNode* result = nullptr; + if (node->id && !strcmp(node->id, id)) return node; + + if (node->child.count > 0) { + auto child = node->child.data; + for (uint32_t i = 0; i < node->child.count; ++i, ++child) { + result = _findNodeById(*child, id); + if (result) break; + } + } + return result; +} + + +static constexpr struct +{ + const char* tag; + SvgParserLengthType type; + int sz; + size_t offset; +} useTags[] = { + {"x", SvgParserLengthType::Horizontal, sizeof("x"), offsetof(SvgUseNode, x)}, + {"y", SvgParserLengthType::Vertical, sizeof("y"), offsetof(SvgUseNode, y)}, + {"width", SvgParserLengthType::Horizontal, sizeof("width"), offsetof(SvgUseNode, w)}, + {"height", SvgParserLengthType::Vertical, sizeof("height"), offsetof(SvgUseNode, h)} +}; + + +static void _cloneNode(SvgNode* from, SvgNode* parent, int depth); +static bool _attrParseUseNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgNode *defs, *nodeFrom, *node = loader->svgParse->node; + char* id; + + SvgUseNode* use = &(node->node.use); + int sz = strlen(key); + unsigned char* array = (unsigned char*)use; + for (unsigned int i = 0; i < sizeof(useTags) / sizeof(useTags[0]); i++) { + if (useTags[i].sz - 1 == sz && !strncmp(useTags[i].tag, key, sz)) { + *((float*)(array + useTags[i].offset)) = _toFloat(loader->svgParse, value, useTags[i].type); + + if (useTags[i].offset == offsetof(SvgUseNode, w)) use->isWidthSet = true; + else if (useTags[i].offset == offsetof(SvgUseNode, h)) use->isHeightSet = true; + + return true; + } + } + + if (!strcmp(key, "href") || !strcmp(key, "xlink:href")) { + id = _idFromHref(value); + defs = _getDefsNode(node); + nodeFrom = _findNodeById(defs, id); + if (nodeFrom) { + _cloneNode(nodeFrom, node, 0); + if (nodeFrom->type == SvgNodeType::Symbol) use->symbol = nodeFrom; + free(id); + } else { + //some svg export software include element at the end of the file + //if so the 'from' element won't be found now and we have to repeat finding + //after the whole file is parsed + _postpone(loader->cloneNodes, node, id); + } + } else { + return _attrParseGNode(data, key, value); + } + return true; +} + + +static SvgNode* _createUseNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) +{ + loader->svgParse->node = _createNode(parent, SvgNodeType::Use); + + if (!loader->svgParse->node) return nullptr; + + loader->svgParse->node->node.use.isWidthSet = false; + loader->svgParse->node->node.use.isHeightSet = false; + + func(buf, bufLength, _attrParseUseNode, loader); + return loader->svgParse->node; +} + + +//TODO: Implement 'text' primitive +static constexpr struct +{ + const char* tag; + int sz; + FactoryMethod tagHandler; +} graphicsTags[] = { + {"use", sizeof("use"), _createUseNode}, + {"circle", sizeof("circle"), _createCircleNode}, + {"ellipse", sizeof("ellipse"), _createEllipseNode}, + {"path", sizeof("path"), _createPathNode}, + {"polygon", sizeof("polygon"), _createPolygonNode}, + {"rect", sizeof("rect"), _createRectNode}, + {"polyline", sizeof("polyline"), _createPolylineNode}, + {"line", sizeof("line"), _createLineNode}, + {"image", sizeof("image"), _createImageNode} +}; + + +static constexpr struct +{ + const char* tag; + int sz; + FactoryMethod tagHandler; +} groupTags[] = { + {"defs", sizeof("defs"), _createDefsNode}, + {"g", sizeof("g"), _createGNode}, + {"svg", sizeof("svg"), _createSvgNode}, + {"mask", sizeof("mask"), _createMaskNode}, + {"clipPath", sizeof("clipPath"), _createClipPathNode}, + {"style", sizeof("style"), _createCssStyleNode}, + {"symbol", sizeof("symbol"), _createSymbolNode} +}; + + +#define FIND_FACTORY(Short_Name, Tags_Array) \ + static FactoryMethod \ + _find##Short_Name##Factory(const char* name) \ + { \ + unsigned int i; \ + int sz = strlen(name); \ + \ + for (i = 0; i < sizeof(Tags_Array) / sizeof(Tags_Array[0]); i++) { \ + if (Tags_Array[i].sz - 1 == sz && !strncmp(Tags_Array[i].tag, name, sz)) { \ + return Tags_Array[i].tagHandler; \ + } \ + } \ + return nullptr; \ + } + +FIND_FACTORY(Group, groupTags) +FIND_FACTORY(Graphics, graphicsTags) + + +FillSpread _parseSpreadValue(const char* value) +{ + auto spread = FillSpread::Pad; + + if (!strcmp(value, "reflect")) { + spread = FillSpread::Reflect; + } else if (!strcmp(value, "repeat")) { + spread = FillSpread::Repeat; + } + + return spread; +} + + +static void _handleRadialCxAttr(SvgLoaderData* loader, SvgRadialGradient* radial, const char* value) +{ + radial->cx = _gradientToFloat(loader->svgParse, value, radial->isCxPercentage); + if (!loader->svgParse->gradient.parsedFx) { + radial->fx = radial->cx; + radial->isFxPercentage = radial->isCxPercentage; + } +} + + +static void _handleRadialCyAttr(SvgLoaderData* loader, SvgRadialGradient* radial, const char* value) +{ + radial->cy = _gradientToFloat(loader->svgParse, value, radial->isCyPercentage); + if (!loader->svgParse->gradient.parsedFy) { + radial->fy = radial->cy; + radial->isFyPercentage = radial->isCyPercentage; + } +} + + +static void _handleRadialFxAttr(SvgLoaderData* loader, SvgRadialGradient* radial, const char* value) +{ + radial->fx = _gradientToFloat(loader->svgParse, value, radial->isFxPercentage); + loader->svgParse->gradient.parsedFx = true; +} + + +static void _handleRadialFyAttr(SvgLoaderData* loader, SvgRadialGradient* radial, const char* value) +{ + radial->fy = _gradientToFloat(loader->svgParse, value, radial->isFyPercentage); + loader->svgParse->gradient.parsedFy = true; +} + + +static void _handleRadialFrAttr(SvgLoaderData* loader, SvgRadialGradient* radial, const char* value) +{ + radial->fr = _gradientToFloat(loader->svgParse, value, radial->isFrPercentage); +} + + +static void _handleRadialRAttr(SvgLoaderData* loader, SvgRadialGradient* radial, const char* value) +{ + radial->r = _gradientToFloat(loader->svgParse, value, radial->isRPercentage); +} + + +static void _recalcRadialCxAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace) +{ + if (userSpace && !radial->isCxPercentage) radial->cx = radial->cx / loader->svgParse->global.w; +} + + +static void _recalcRadialCyAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace) +{ + if (userSpace && !radial->isCyPercentage) radial->cy = radial->cy / loader->svgParse->global.h; +} + + +static void _recalcRadialFxAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace) +{ + if (userSpace && !radial->isFxPercentage) radial->fx = radial->fx / loader->svgParse->global.w; +} + + +static void _recalcRadialFyAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace) +{ + if (userSpace && !radial->isFyPercentage) radial->fy = radial->fy / loader->svgParse->global.h; +} + + +static void _recalcRadialFrAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace) +{ + // scaling factor based on the Units paragraph from : https://www.w3.org/TR/2015/WD-SVG2-20150915/coords.html + if (userSpace && !radial->isFrPercentage) radial->fr = radial->fr / (sqrtf(powf(loader->svgParse->global.h, 2) + powf(loader->svgParse->global.w, 2)) / sqrtf(2.0)); +} + + +static void _recalcRadialRAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace) +{ + // scaling factor based on the Units paragraph from : https://www.w3.org/TR/2015/WD-SVG2-20150915/coords.html + if (userSpace && !radial->isRPercentage) radial->r = radial->r / (sqrtf(powf(loader->svgParse->global.h, 2) + powf(loader->svgParse->global.w, 2)) / sqrtf(2.0)); +} + + +static void _recalcInheritedRadialCxAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace) +{ + if (!radial->isCxPercentage) { + if (userSpace) radial->cx /= loader->svgParse->global.w; + else radial->cx *= loader->svgParse->global.w; + } +} + + +static void _recalcInheritedRadialCyAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace) +{ + if (!radial->isCyPercentage) { + if (userSpace) radial->cy /= loader->svgParse->global.h; + else radial->cy *= loader->svgParse->global.h; + } +} + + +static void _recalcInheritedRadialFxAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace) +{ + if (!radial->isFxPercentage) { + if (userSpace) radial->fx /= loader->svgParse->global.w; + else radial->fx *= loader->svgParse->global.w; + } +} + + +static void _recalcInheritedRadialFyAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace) +{ + if (!radial->isFyPercentage) { + if (userSpace) radial->fy /= loader->svgParse->global.h; + else radial->fy *= loader->svgParse->global.h; + } +} + + +static void _recalcInheritedRadialFrAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace) +{ + if (!radial->isFrPercentage) { + if (userSpace) radial->fr /= sqrtf(powf(loader->svgParse->global.h, 2) + powf(loader->svgParse->global.w, 2)) / sqrtf(2.0); + else radial->fr *= sqrtf(powf(loader->svgParse->global.h, 2) + powf(loader->svgParse->global.w, 2)) / sqrtf(2.0); + } +} + + +static void _recalcInheritedRadialRAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace) +{ + if (!radial->isRPercentage) { + if (userSpace) radial->r /= sqrtf(powf(loader->svgParse->global.h, 2) + powf(loader->svgParse->global.w, 2)) / sqrtf(2.0); + else radial->r *= sqrtf(powf(loader->svgParse->global.h, 2) + powf(loader->svgParse->global.w, 2)) / sqrtf(2.0); + } +} + + +static void _inheritRadialCxAttr(SvgStyleGradient* to, SvgStyleGradient* from) +{ + to->radial->cx = from->radial->cx; + to->radial->isCxPercentage = from->radial->isCxPercentage; + to->flags = (to->flags | SvgGradientFlags::Cx); +} + + +static void _inheritRadialCyAttr(SvgStyleGradient* to, SvgStyleGradient* from) +{ + to->radial->cy = from->radial->cy; + to->radial->isCyPercentage = from->radial->isCyPercentage; + to->flags = (to->flags | SvgGradientFlags::Cy); +} + + +static void _inheritRadialFxAttr(SvgStyleGradient* to, SvgStyleGradient* from) +{ + to->radial->fx = from->radial->fx; + to->radial->isFxPercentage = from->radial->isFxPercentage; + to->flags = (to->flags | SvgGradientFlags::Fx); +} + + +static void _inheritRadialFyAttr(SvgStyleGradient* to, SvgStyleGradient* from) +{ + to->radial->fy = from->radial->fy; + to->radial->isFyPercentage = from->radial->isFyPercentage; + to->flags = (to->flags | SvgGradientFlags::Fy); +} + + +static void _inheritRadialFrAttr(SvgStyleGradient* to, SvgStyleGradient* from) +{ + to->radial->fr = from->radial->fr; + to->radial->isFrPercentage = from->radial->isFrPercentage; + to->flags = (to->flags | SvgGradientFlags::Fr); +} + + +static void _inheritRadialRAttr(SvgStyleGradient* to, SvgStyleGradient* from) +{ + to->radial->r = from->radial->r; + to->radial->isRPercentage = from->radial->isRPercentage; + to->flags = (to->flags | SvgGradientFlags::R); +} + + +typedef void (*radialMethod)(SvgLoaderData* loader, SvgRadialGradient* radial, const char* value); +typedef void (*radialInheritMethod)(SvgStyleGradient* to, SvgStyleGradient* from); +typedef void (*radialMethodRecalc)(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace); + + +#define RADIAL_DEF(Name, Name1, Flag) \ + { \ +#Name, sizeof(#Name), _handleRadial##Name1##Attr, _inheritRadial##Name1##Attr, _recalcRadial##Name1##Attr, _recalcInheritedRadial##Name1##Attr, Flag \ + } + + +static constexpr struct +{ + const char* tag; + int sz; + radialMethod tagHandler; + radialInheritMethod tagInheritHandler; + radialMethodRecalc tagRecalc; + radialMethodRecalc tagInheritedRecalc; + SvgGradientFlags flag; +} radialTags[] = { + RADIAL_DEF(cx, Cx, SvgGradientFlags::Cx), + RADIAL_DEF(cy, Cy, SvgGradientFlags::Cy), + RADIAL_DEF(fx, Fx, SvgGradientFlags::Fx), + RADIAL_DEF(fy, Fy, SvgGradientFlags::Fy), + RADIAL_DEF(r, R, SvgGradientFlags::R), + RADIAL_DEF(fr, Fr, SvgGradientFlags::Fr) +}; + + +static bool _attrParseRadialGradientNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgStyleGradient* grad = loader->svgParse->styleGrad; + SvgRadialGradient* radial = grad->radial; + int sz = strlen(key); + + for (unsigned int i = 0; i < sizeof(radialTags) / sizeof(radialTags[0]); i++) { + if (radialTags[i].sz - 1 == sz && !strncmp(radialTags[i].tag, key, sz)) { + radialTags[i].tagHandler(loader, radial, value); + grad->flags = (grad->flags | radialTags[i].flag); + return true; + } + } + + if (!strcmp(key, "id")) { + if (grad->id && value) free(grad->id); + grad->id = _copyId(value); + } else if (!strcmp(key, "spreadMethod")) { + grad->spread = _parseSpreadValue(value); + grad->flags = (grad->flags | SvgGradientFlags::SpreadMethod); + } else if (!strcmp(key, "href") || !strcmp(key, "xlink:href")) { + if (grad->ref && value) free(grad->ref); + grad->ref = _idFromHref(value); + } else if (!strcmp(key, "gradientUnits")) { + if (!strcmp(value, "userSpaceOnUse")) grad->userSpace = true; + grad->flags = (grad->flags | SvgGradientFlags::GradientUnits); + } else if (!strcmp(key, "gradientTransform")) { + grad->transform = _parseTransformationMatrix(value); + } else { + return false; + } + + return true; +} + + +static SvgStyleGradient* _createRadialGradient(SvgLoaderData* loader, const char* buf, unsigned bufLength) +{ + auto grad = (SvgStyleGradient*)(calloc(1, sizeof(SvgStyleGradient))); + loader->svgParse->styleGrad = grad; + + grad->flags = SvgGradientFlags::None; + grad->type = SvgGradientType::Radial; + grad->userSpace = false; + grad->radial = (SvgRadialGradient*)calloc(1, sizeof(SvgRadialGradient)); + if (!grad->radial) { + grad->clear(); + free(grad); + return nullptr; + } + /** + * Default values of gradient transformed into global percentage + */ + grad->radial->cx = 0.5f; + grad->radial->cy = 0.5f; + grad->radial->fx = 0.5f; + grad->radial->fy = 0.5f; + grad->radial->r = 0.5f; + grad->radial->isCxPercentage = true; + grad->radial->isCyPercentage = true; + grad->radial->isFxPercentage = true; + grad->radial->isFyPercentage = true; + grad->radial->isRPercentage = true; + grad->radial->isFrPercentage = true; + + loader->svgParse->gradient.parsedFx = false; + loader->svgParse->gradient.parsedFy = false; + simpleXmlParseAttributes(buf, bufLength, + _attrParseRadialGradientNode, loader); + + for (unsigned int i = 0; i < sizeof(radialTags) / sizeof(radialTags[0]); i++) { + radialTags[i].tagRecalc(loader, grad->radial, grad->userSpace); + } + + return loader->svgParse->styleGrad; +} + + +static bool _attrParseStopsStyle(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + auto stop = &loader->svgParse->gradStop; + + if (!strcmp(key, "stop-opacity")) { + stop->a = _toOpacity(value); + loader->svgParse->flags = (loader->svgParse->flags | SvgStopStyleFlags::StopOpacity); + } else if (!strcmp(key, "stop-color")) { + _toColor(value, &stop->r, &stop->g, &stop->b, nullptr); + loader->svgParse->flags = (loader->svgParse->flags | SvgStopStyleFlags::StopColor); + } else { + return false; + } + + return true; +} + + +static bool _attrParseStops(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + auto stop = &loader->svgParse->gradStop; + + if (!strcmp(key, "offset")) { + stop->offset = _toOffset(value); + } else if (!strcmp(key, "stop-opacity")) { + if (!(loader->svgParse->flags & SvgStopStyleFlags::StopOpacity)) { + stop->a = _toOpacity(value); + } + } else if (!strcmp(key, "stop-color")) { + if (!(loader->svgParse->flags & SvgStopStyleFlags::StopColor)) { + _toColor(value, &stop->r, &stop->g, &stop->b, nullptr); + } + } else if (!strcmp(key, "style")) { + simpleXmlParseW3CAttribute(value, strlen(value), _attrParseStopsStyle, data); + } else { + return false; + } + + return true; +} + + +static void _handleLinearX1Attr(SvgLoaderData* loader, SvgLinearGradient* linear, const char* value) +{ + linear->x1 = _gradientToFloat(loader->svgParse, value, linear->isX1Percentage); +} + + +static void _handleLinearY1Attr(SvgLoaderData* loader, SvgLinearGradient* linear, const char* value) +{ + linear->y1 = _gradientToFloat(loader->svgParse, value, linear->isY1Percentage); +} + + +static void _handleLinearX2Attr(SvgLoaderData* loader, SvgLinearGradient* linear, const char* value) +{ + linear->x2 = _gradientToFloat(loader->svgParse, value, linear->isX2Percentage); +} + + +static void _handleLinearY2Attr(SvgLoaderData* loader, SvgLinearGradient* linear, const char* value) +{ + linear->y2 = _gradientToFloat(loader->svgParse, value, linear->isY2Percentage); +} + + +static void _recalcLinearX1Attr(SvgLoaderData* loader, SvgLinearGradient* linear, bool userSpace) +{ + if (userSpace && !linear->isX1Percentage) linear->x1 = linear->x1 / loader->svgParse->global.w; +} + + +static void _recalcLinearY1Attr(SvgLoaderData* loader, SvgLinearGradient* linear, bool userSpace) +{ + if (userSpace && !linear->isY1Percentage) linear->y1 = linear->y1 / loader->svgParse->global.h; +} + + +static void _recalcLinearX2Attr(SvgLoaderData* loader, SvgLinearGradient* linear, bool userSpace) +{ + if (userSpace && !linear->isX2Percentage) linear->x2 = linear->x2 / loader->svgParse->global.w; +} + + +static void _recalcLinearY2Attr(SvgLoaderData* loader, SvgLinearGradient* linear, bool userSpace) +{ + if (userSpace && !linear->isY2Percentage) linear->y2 = linear->y2 / loader->svgParse->global.h; +} + + +static void _recalcInheritedLinearX1Attr(SvgLoaderData* loader, SvgLinearGradient* linear, bool userSpace) +{ + if (!linear->isX1Percentage) { + if (userSpace) linear->x1 /= loader->svgParse->global.w; + else linear->x1 *= loader->svgParse->global.w; + } +} + + +static void _recalcInheritedLinearX2Attr(SvgLoaderData* loader, SvgLinearGradient* linear, bool userSpace) +{ + if (!linear->isX2Percentage) { + if (userSpace) linear->x2 /= loader->svgParse->global.w; + else linear->x2 *= loader->svgParse->global.w; + } +} + + +static void _recalcInheritedLinearY1Attr(SvgLoaderData* loader, SvgLinearGradient* linear, bool userSpace) +{ + if (!linear->isY1Percentage) { + if (userSpace) linear->y1 /= loader->svgParse->global.h; + else linear->y1 *= loader->svgParse->global.h; + } +} + + +static void _recalcInheritedLinearY2Attr(SvgLoaderData* loader, SvgLinearGradient* linear, bool userSpace) +{ + if (!linear->isY2Percentage) { + if (userSpace) linear->y2 /= loader->svgParse->global.h; + else linear->y2 *= loader->svgParse->global.h; + } +} + + +static void _inheritLinearX1Attr(SvgStyleGradient* to, SvgStyleGradient* from) +{ + to->linear->x1 = from->linear->x1; + to->linear->isX1Percentage = from->linear->isX1Percentage; + to->flags = (to->flags | SvgGradientFlags::X1); +} + + +static void _inheritLinearX2Attr(SvgStyleGradient* to, SvgStyleGradient* from) +{ + to->linear->x2 = from->linear->x2; + to->linear->isX2Percentage = from->linear->isX2Percentage; + to->flags = (to->flags | SvgGradientFlags::X2); +} + + +static void _inheritLinearY1Attr(SvgStyleGradient* to, SvgStyleGradient* from) +{ + to->linear->y1 = from->linear->y1; + to->linear->isY1Percentage = from->linear->isY1Percentage; + to->flags = (to->flags | SvgGradientFlags::Y1); +} + + +static void _inheritLinearY2Attr(SvgStyleGradient* to, SvgStyleGradient* from) +{ + to->linear->y2 = from->linear->y2; + to->linear->isY2Percentage = from->linear->isY2Percentage; + to->flags = (to->flags | SvgGradientFlags::Y2); +} + + +typedef void (*Linear_Method)(SvgLoaderData* loader, SvgLinearGradient* linear, const char* value); +typedef void (*Linear_Inherit_Method)(SvgStyleGradient* to, SvgStyleGradient* from); +typedef void (*Linear_Method_Recalc)(SvgLoaderData* loader, SvgLinearGradient* linear, bool userSpace); + + +#define LINEAR_DEF(Name, Name1, Flag) \ + { \ +#Name, sizeof(#Name), _handleLinear##Name1##Attr, _inheritLinear##Name1##Attr, _recalcLinear##Name1##Attr, _recalcInheritedLinear##Name1##Attr, Flag \ + } + + +static constexpr struct +{ + const char* tag; + int sz; + Linear_Method tagHandler; + Linear_Inherit_Method tagInheritHandler; + Linear_Method_Recalc tagRecalc; + Linear_Method_Recalc tagInheritedRecalc; + SvgGradientFlags flag; +} linear_tags[] = { + LINEAR_DEF(x1, X1, SvgGradientFlags::X1), + LINEAR_DEF(y1, Y1, SvgGradientFlags::Y1), + LINEAR_DEF(x2, X2, SvgGradientFlags::X2), + LINEAR_DEF(y2, Y2, SvgGradientFlags::Y2) +}; + + +static bool _attrParseLinearGradientNode(void* data, const char* key, const char* value) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + SvgStyleGradient* grad = loader->svgParse->styleGrad; + SvgLinearGradient* linear = grad->linear; + int sz = strlen(key); + + for (unsigned int i = 0; i < sizeof(linear_tags) / sizeof(linear_tags[0]); i++) { + if (linear_tags[i].sz - 1 == sz && !strncmp(linear_tags[i].tag, key, sz)) { + linear_tags[i].tagHandler(loader, linear, value); + grad->flags = (grad->flags | linear_tags[i].flag); + return true; + } + } + + if (!strcmp(key, "id")) { + if (grad->id && value) free(grad->id); + grad->id = _copyId(value); + } else if (!strcmp(key, "spreadMethod")) { + grad->spread = _parseSpreadValue(value); + grad->flags = (grad->flags | SvgGradientFlags::SpreadMethod); + } else if (!strcmp(key, "href") || !strcmp(key, "xlink:href")) { + if (grad->ref && value) free(grad->ref); + grad->ref = _idFromHref(value); + } else if (!strcmp(key, "gradientUnits")) { + if (!strcmp(value, "userSpaceOnUse")) grad->userSpace = true; + grad->flags = (grad->flags | SvgGradientFlags::GradientUnits); + } else if (!strcmp(key, "gradientTransform")) { + grad->transform = _parseTransformationMatrix(value); + } else { + return false; + } + + return true; +} + + +static SvgStyleGradient* _createLinearGradient(SvgLoaderData* loader, const char* buf, unsigned bufLength) +{ + auto grad = (SvgStyleGradient*)(calloc(1, sizeof(SvgStyleGradient))); + loader->svgParse->styleGrad = grad; + + grad->flags = SvgGradientFlags::None; + grad->type = SvgGradientType::Linear; + grad->userSpace = false; + grad->linear = (SvgLinearGradient*)calloc(1, sizeof(SvgLinearGradient)); + if (!grad->linear) { + grad->clear(); + free(grad); + return nullptr; + } + /** + * Default value of x2 is 100% - transformed to the global percentage + */ + grad->linear->x2 = 1.0f; + grad->linear->isX2Percentage = true; + + simpleXmlParseAttributes(buf, bufLength, _attrParseLinearGradientNode, loader); + + for (unsigned int i = 0; i < sizeof(linear_tags) / sizeof(linear_tags[0]); i++) { + linear_tags[i].tagRecalc(loader, grad->linear, grad->userSpace); + } + + return loader->svgParse->styleGrad; +} + + +#define GRADIENT_DEF(Name, Name1) \ + { \ +#Name, sizeof(#Name), _create##Name1 \ + } + + +/** + * In the case when the gradients lengths are given as numbers (not percentages) + * in the current user coordinate system, they are recalculated into percentages + * related to the canvas width and height. + */ +static constexpr struct +{ + const char* tag; + int sz; + GradientFactoryMethod tagHandler; +} gradientTags[] = { + GRADIENT_DEF(linearGradient, LinearGradient), + GRADIENT_DEF(radialGradient, RadialGradient) +}; + + +static GradientFactoryMethod _findGradientFactory(const char* name) +{ + int sz = strlen(name); + + for (unsigned int i = 0; i < sizeof(gradientTags) / sizeof(gradientTags[0]); i++) { + if (gradientTags[i].sz - 1 == sz && !strncmp(gradientTags[i].tag, name, sz)) { + return gradientTags[i].tagHandler; + } + } + return nullptr; +} + + +static void _cloneGradStops(Array& dst, const Array& src) +{ + for (uint32_t i = 0; i < src.count; ++i) { + dst.push(src[i]); + } +} + + +static void _inheritGradient(SvgLoaderData* loader, SvgStyleGradient* to, SvgStyleGradient* from) +{ + if (!to || !from) return; + + if (!(to->flags & SvgGradientFlags::SpreadMethod) && (from->flags & SvgGradientFlags::SpreadMethod)) { + to->spread = from->spread; + to->flags = (to->flags | SvgGradientFlags::SpreadMethod); + } + bool gradUnitSet = (to->flags & SvgGradientFlags::GradientUnits); + if (!(to->flags & SvgGradientFlags::GradientUnits) && (from->flags & SvgGradientFlags::GradientUnits)) { + to->userSpace = from->userSpace; + to->flags = (to->flags | SvgGradientFlags::GradientUnits); + } + + if (!to->transform && from->transform) { + to->transform = (Matrix*)malloc(sizeof(Matrix)); + if (to->transform) memcpy(to->transform, from->transform, sizeof(Matrix)); + } + + if (to->type == SvgGradientType::Linear && from->type == SvgGradientType::Linear) { + for (unsigned int i = 0; i < sizeof(linear_tags) / sizeof(linear_tags[0]); i++) { + bool coordSet = to->flags & linear_tags[i].flag; + if (!(to->flags & linear_tags[i].flag) && (from->flags & linear_tags[i].flag)) { + linear_tags[i].tagInheritHandler(to, from); + } + + //GradUnits not set directly, coord set + if (!gradUnitSet && coordSet) { + linear_tags[i].tagRecalc(loader, to->linear, to->userSpace); + } + //GradUnits set, coord not set directly + if (to->userSpace == from->userSpace) continue; + if (gradUnitSet && !coordSet) { + linear_tags[i].tagInheritedRecalc(loader, to->linear, to->userSpace); + } + } + } else if (to->type == SvgGradientType::Radial && from->type == SvgGradientType::Radial) { + for (unsigned int i = 0; i < sizeof(radialTags) / sizeof(radialTags[0]); i++) { + bool coordSet = (to->flags & radialTags[i].flag); + if (!(to->flags & radialTags[i].flag) && (from->flags & radialTags[i].flag)) { + radialTags[i].tagInheritHandler(to, from); + } + + //GradUnits not set directly, coord set + if (!gradUnitSet && coordSet) { + radialTags[i].tagRecalc(loader, to->radial, to->userSpace); + } + //GradUnits set, coord not set directly + if (to->userSpace == from->userSpace) continue; + if (gradUnitSet && !coordSet) { + radialTags[i].tagInheritedRecalc(loader, to->radial, to->userSpace); + } + } + } + + if (to->stops.empty()) _cloneGradStops(to->stops, from->stops); +} + + +static SvgStyleGradient* _cloneGradient(SvgStyleGradient* from) +{ + if (!from) return nullptr; + + auto grad = (SvgStyleGradient*)(calloc(1, sizeof(SvgStyleGradient))); + if (!grad) return nullptr; + + grad->type = from->type; + grad->id = from->id ? _copyId(from->id) : nullptr; + grad->ref = from->ref ? _copyId(from->ref) : nullptr; + grad->spread = from->spread; + grad->userSpace = from->userSpace; + grad->flags = from->flags; + + if (from->transform) { + grad->transform = (Matrix*)calloc(1, sizeof(Matrix)); + if (grad->transform) memcpy(grad->transform, from->transform, sizeof(Matrix)); + } + + if (grad->type == SvgGradientType::Linear) { + grad->linear = (SvgLinearGradient*)calloc(1, sizeof(SvgLinearGradient)); + if (!grad->linear) goto error_grad_alloc; + memcpy(grad->linear, from->linear, sizeof(SvgLinearGradient)); + } else if (grad->type == SvgGradientType::Radial) { + grad->radial = (SvgRadialGradient*)calloc(1, sizeof(SvgRadialGradient)); + if (!grad->radial) goto error_grad_alloc; + memcpy(grad->radial, from->radial, sizeof(SvgRadialGradient)); + } + + _cloneGradStops(grad->stops, from->stops); + + return grad; + + error_grad_alloc: + if (grad) { + grad->clear(); + free(grad); + } + return nullptr; +} + + +static void _styleInherit(SvgStyleProperty* child, const SvgStyleProperty* parent) +{ + if (parent == nullptr) return; + //Inherit the property of parent if not present in child. + if (!child->curColorSet) { + child->color = parent->color; + child->curColorSet = parent->curColorSet; + } + if (!(child->flags & SvgStyleFlags::PaintOrder)) { + child->paintOrder = parent->paintOrder; + } + //Fill + if (!(child->fill.flags & SvgFillFlags::Paint)) { + child->fill.paint.color = parent->fill.paint.color; + child->fill.paint.none = parent->fill.paint.none; + child->fill.paint.curColor = parent->fill.paint.curColor; + if (parent->fill.paint.url) { + if (child->fill.paint.url) free(child->fill.paint.url); + child->fill.paint.url = _copyId(parent->fill.paint.url); + } + } + if (!(child->fill.flags & SvgFillFlags::Opacity)) { + child->fill.opacity = parent->fill.opacity; + } + if (!(child->fill.flags & SvgFillFlags::FillRule)) { + child->fill.fillRule = parent->fill.fillRule; + } + //Stroke + if (!(child->stroke.flags & SvgStrokeFlags::Paint)) { + child->stroke.paint.color = parent->stroke.paint.color; + child->stroke.paint.none = parent->stroke.paint.none; + child->stroke.paint.curColor = parent->stroke.paint.curColor; + if (parent->stroke.paint.url) { + if (child->stroke.paint.url) free(child->stroke.paint.url); + child->stroke.paint.url = _copyId(parent->stroke.paint.url); + } + } + if (!(child->stroke.flags & SvgStrokeFlags::Opacity)) { + child->stroke.opacity = parent->stroke.opacity; + } + if (!(child->stroke.flags & SvgStrokeFlags::Width)) { + child->stroke.width = parent->stroke.width; + } + if (!(child->stroke.flags & SvgStrokeFlags::Dash)) { + if (parent->stroke.dash.array.count > 0) { + child->stroke.dash.array.clear(); + child->stroke.dash.array.reserve(parent->stroke.dash.array.count); + for (uint32_t i = 0; i < parent->stroke.dash.array.count; ++i) { + child->stroke.dash.array.push(parent->stroke.dash.array[i]); + } + } + } + if (!(child->stroke.flags & SvgStrokeFlags::DashOffset)) { + child->stroke.dash.offset = parent->stroke.dash.offset; + } + if (!(child->stroke.flags & SvgStrokeFlags::Cap)) { + child->stroke.cap = parent->stroke.cap; + } + if (!(child->stroke.flags & SvgStrokeFlags::Join)) { + child->stroke.join = parent->stroke.join; + } + if (!(child->stroke.flags & SvgStrokeFlags::Miterlimit)) { + child->stroke.miterlimit = parent->stroke.miterlimit; + } +} + + +static void _styleCopy(SvgStyleProperty* to, const SvgStyleProperty* from) +{ + if (from == nullptr) return; + //Copy the properties of 'from' only if they were explicitly set (not the default ones). + if (from->curColorSet) { + to->color = from->color; + to->curColorSet = true; + } + if (from->flags & SvgStyleFlags::PaintOrder) { + to->paintOrder = from->paintOrder; + } + //Fill + to->fill.flags = (to->fill.flags | from->fill.flags); + if (from->fill.flags & SvgFillFlags::Paint) { + to->fill.paint.color = from->fill.paint.color; + to->fill.paint.none = from->fill.paint.none; + to->fill.paint.curColor = from->fill.paint.curColor; + if (from->fill.paint.url) { + if (to->fill.paint.url) free(to->fill.paint.url); + to->fill.paint.url = _copyId(from->fill.paint.url); + } + } + if (from->fill.flags & SvgFillFlags::Opacity) { + to->fill.opacity = from->fill.opacity; + } + if (from->fill.flags & SvgFillFlags::FillRule) { + to->fill.fillRule = from->fill.fillRule; + } + //Stroke + to->stroke.flags = (to->stroke.flags | from->stroke.flags); + if (from->stroke.flags & SvgStrokeFlags::Paint) { + to->stroke.paint.color = from->stroke.paint.color; + to->stroke.paint.none = from->stroke.paint.none; + to->stroke.paint.curColor = from->stroke.paint.curColor; + if (from->stroke.paint.url) { + if (to->stroke.paint.url) free(to->stroke.paint.url); + to->stroke.paint.url = _copyId(from->stroke.paint.url); + } + } + if (from->stroke.flags & SvgStrokeFlags::Opacity) { + to->stroke.opacity = from->stroke.opacity; + } + if (from->stroke.flags & SvgStrokeFlags::Width) { + to->stroke.width = from->stroke.width; + } + if (from->stroke.flags & SvgStrokeFlags::Dash) { + if (from->stroke.dash.array.count > 0) { + to->stroke.dash.array.clear(); + to->stroke.dash.array.reserve(from->stroke.dash.array.count); + for (uint32_t i = 0; i < from->stroke.dash.array.count; ++i) { + to->stroke.dash.array.push(from->stroke.dash.array[i]); + } + } + } + if (from->stroke.flags & SvgStrokeFlags::DashOffset) { + to->stroke.dash.offset = from->stroke.dash.offset; + } + if (from->stroke.flags & SvgStrokeFlags::Cap) { + to->stroke.cap = from->stroke.cap; + } + if (from->stroke.flags & SvgStrokeFlags::Join) { + to->stroke.join = from->stroke.join; + } + if (from->stroke.flags & SvgStrokeFlags::Miterlimit) { + to->stroke.miterlimit = from->stroke.miterlimit; + } +} + + +static void _copyAttr(SvgNode* to, const SvgNode* from) +{ + //Copy matrix attribute + if (from->transform) { + to->transform = (Matrix*)malloc(sizeof(Matrix)); + if (to->transform) *to->transform = *from->transform; + } + //Copy style attribute + _styleCopy(to->style, from->style); + to->style->flags = (to->style->flags | from->style->flags); + if (from->style->clipPath.url) { + if (to->style->clipPath.url) free(to->style->clipPath.url); + to->style->clipPath.url = strdup(from->style->clipPath.url); + } + if (from->style->mask.url) { + if (to->style->mask.url) free(to->style->mask.url); + to->style->mask.url = strdup(from->style->mask.url); + } + + //Copy node attribute + switch (from->type) { + case SvgNodeType::Circle: { + to->node.circle.cx = from->node.circle.cx; + to->node.circle.cy = from->node.circle.cy; + to->node.circle.r = from->node.circle.r; + break; + } + case SvgNodeType::Ellipse: { + to->node.ellipse.cx = from->node.ellipse.cx; + to->node.ellipse.cy = from->node.ellipse.cy; + to->node.ellipse.rx = from->node.ellipse.rx; + to->node.ellipse.ry = from->node.ellipse.ry; + break; + } + case SvgNodeType::Rect: { + to->node.rect.x = from->node.rect.x; + to->node.rect.y = from->node.rect.y; + to->node.rect.w = from->node.rect.w; + to->node.rect.h = from->node.rect.h; + to->node.rect.rx = from->node.rect.rx; + to->node.rect.ry = from->node.rect.ry; + to->node.rect.hasRx = from->node.rect.hasRx; + to->node.rect.hasRy = from->node.rect.hasRy; + break; + } + case SvgNodeType::Line: { + to->node.line.x1 = from->node.line.x1; + to->node.line.y1 = from->node.line.y1; + to->node.line.x2 = from->node.line.x2; + to->node.line.y2 = from->node.line.y2; + break; + } + case SvgNodeType::Path: { + if (from->node.path.path) { + if (to->node.path.path) free(to->node.path.path); + to->node.path.path = strdup(from->node.path.path); + } + break; + } + case SvgNodeType::Polygon: { + if ((to->node.polygon.pts.count = from->node.polygon.pts.count)) { + to->node.polygon.pts = from->node.polygon.pts; + } + break; + } + case SvgNodeType::Polyline: { + if ((to->node.polyline.pts.count = from->node.polyline.pts.count)) { + to->node.polyline.pts = from->node.polyline.pts; + } + break; + } + case SvgNodeType::Image: { + to->node.image.x = from->node.image.x; + to->node.image.y = from->node.image.y; + to->node.image.w = from->node.image.w; + to->node.image.h = from->node.image.h; + if (from->node.image.href) { + if (to->node.image.href) free(to->node.image.href); + to->node.image.href = strdup(from->node.image.href); + } + break; + } + case SvgNodeType::Use: { + to->node.use.x = from->node.use.x; + to->node.use.y = from->node.use.y; + to->node.use.w = from->node.use.w; + to->node.use.h = from->node.use.h; + to->node.use.isWidthSet = from->node.use.isWidthSet; + to->node.use.isHeightSet = from->node.use.isHeightSet; + to->node.use.symbol = from->node.use.symbol; + break; + } + default: { + break; + } + } +} + + +static void _cloneNode(SvgNode* from, SvgNode* parent, int depth) +{ + /* Exception handling: Prevent invalid SVG data input. + The size is the arbitrary value, we need an experimental size. */ + if (depth == 8192) { + TVGERR("SVG", "Infinite recursive call - stopped after %d calls! Svg file may be incorrectly formatted.", depth); + return; + } + + SvgNode* newNode; + if (!from || !parent || from == parent) return; + + newNode = _createNode(parent, from->type); + if (!newNode) return; + + _styleInherit(newNode->style, parent->style); + _copyAttr(newNode, from); + + auto child = from->child.data; + for (uint32_t i = 0; i < from->child.count; ++i, ++child) { + _cloneNode(*child, newNode, depth + 1); + } +} + + +static void _clonePostponedNodes(Array* cloneNodes, SvgNode* doc) +{ + for (uint32_t i = 0; i < cloneNodes->count; ++i) { + auto nodeIdPair = (*cloneNodes)[i]; + auto defs = _getDefsNode(nodeIdPair.node); + auto nodeFrom = _findNodeById(defs, nodeIdPair.id); + if (!nodeFrom) nodeFrom = _findNodeById(doc, nodeIdPair.id); + _cloneNode(nodeFrom, nodeIdPair.node, 0); + if (nodeFrom && nodeFrom->type == SvgNodeType::Symbol && nodeIdPair.node->type == SvgNodeType::Use) { + nodeIdPair.node->node.use.symbol = nodeFrom; + } + free(nodeIdPair.id); + } +} + + +static constexpr struct +{ + const char* tag; + size_t sz; +} popArray[] = { + {"g", sizeof("g")}, + {"svg", sizeof("svg")}, + {"defs", sizeof("defs")}, + {"mask", sizeof("mask")}, + {"clipPath", sizeof("clipPath")}, + {"style", sizeof("style")}, + {"symbol", sizeof("symbol")} +}; + + +static void _svgLoaderParserXmlClose(SvgLoaderData* loader, const char* content) +{ + content = _skipSpace(content, nullptr); + + for (unsigned int i = 0; i < sizeof(popArray) / sizeof(popArray[0]); i++) { + if (!strncmp(content, popArray[i].tag, popArray[i].sz - 1)) { + loader->stack.pop(); + break; + } + } + + loader->level--; +} + + +static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content, unsigned int length, bool empty) +{ + const char* attrs = nullptr; + int attrsLength = 0; + int sz = length; + char tagName[20] = ""; + FactoryMethod method; + GradientFactoryMethod gradientMethod; + SvgNode *node = nullptr, *parent = nullptr; + loader->level++; + attrs = simpleXmlFindAttributesTag(content, length); + + if (!attrs) { + //Parse the empty tag + attrs = content; + while ((attrs != nullptr) && *attrs != '>') attrs++; + if (empty) attrs--; + } + + if (attrs) { + //Find out the tag name starting from content till sz length + sz = attrs - content; + while ((sz > 0) && (isspace(content[sz - 1]))) sz--; + if ((unsigned)sz >= sizeof(tagName)) return; + strncpy(tagName, content, sz); + tagName[sz] = '\0'; + attrsLength = length - sz; + } + + if ((method = _findGroupFactory(tagName))) { + //Group + if (empty) return; + if (!loader->doc) { + if (strcmp(tagName, "svg")) return; //Not a valid svg document + node = method(loader, nullptr, attrs, attrsLength, simpleXmlParseAttributes); + loader->doc = node; + } else { + if (!strcmp(tagName, "svg")) return; //Already loaded (SvgNodeType::Doc) tag + if (loader->stack.count > 0) parent = loader->stack.last(); + else parent = loader->doc; + if (!strcmp(tagName, "style")) { + // TODO: For now only the first style node is saved. After the css id selector + // is introduced this if condition shouldin't be necessary any more + if (!loader->cssStyle) { + node = method(loader, nullptr, attrs, attrsLength, simpleXmlParseAttributes); + loader->cssStyle = node; + loader->doc->node.doc.style = node; + loader->style = true; + } + } else { + node = method(loader, parent, attrs, attrsLength, simpleXmlParseAttributes); + } + } + + if (!node) return; + if (node->type != SvgNodeType::Defs || !empty) { + loader->stack.push(node); + } + } else if ((method = _findGraphicsFactory(tagName))) { + if (loader->stack.count > 0) parent = loader->stack.last(); + else parent = loader->doc; + node = method(loader, parent, attrs, attrsLength, simpleXmlParseAttributes); + } else if ((gradientMethod = _findGradientFactory(tagName))) { + SvgStyleGradient* gradient; + gradient = gradientMethod(loader, attrs, attrsLength); + //FIXME: The current parsing structure does not distinguish end tags. + // There is no way to know if the currently parsed gradient is in defs. + // If a gradient is declared outside of defs after defs is set, it is included in the gradients of defs. + // But finally, the loader has a gradient style list regardless of defs. + // This is only to support this when multiple gradients are declared, even if no defs are declared. + // refer to: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs + if (loader->def && loader->doc->node.doc.defs) { + loader->def->node.defs.gradients.push(gradient); + } else { + loader->gradients.push(gradient); + } + loader->latestGradient = gradient; + } else if (!strcmp(tagName, "stop")) { + if (!loader->latestGradient) { + TVGLOG("SVG", "Stop element is used outside of the Gradient element"); + return; + } + /* default value for opacity */ + loader->svgParse->gradStop = {0.0f, 0, 0, 0, 255}; + loader->svgParse->flags = SvgStopStyleFlags::StopDefault; + simpleXmlParseAttributes(attrs, attrsLength, _attrParseStops, loader); + loader->latestGradient->stops.push(loader->svgParse->gradStop); + } else if (!isIgnoreUnsupportedLogElements(tagName)) { + TVGLOG("SVG", "Unsupported elements used [Elements: %s]", tagName); + } +} + + +static void _svgLoaderParserXmlCssStyle(SvgLoaderData* loader, const char* content, unsigned int length) +{ + char* tag; + char* name; + const char* attrs = nullptr; + unsigned int attrsLength = 0; + + FactoryMethod method; + GradientFactoryMethod gradientMethod; + SvgNode *node = nullptr; + + while (auto next = simpleXmlParseCSSAttribute(content, length, &tag, &name, &attrs, &attrsLength)) { + if ((method = _findGroupFactory(tag))) { + if ((node = method(loader, loader->cssStyle, attrs, attrsLength, simpleXmlParseW3CAttribute))) node->id = _copyId(name); + } else if ((method = _findGraphicsFactory(tag))) { + if ((node = method(loader, loader->cssStyle, attrs, attrsLength, simpleXmlParseW3CAttribute))) node->id = _copyId(name); + } else if ((gradientMethod = _findGradientFactory(tag))) { + TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag); + } else if (!strcmp(tag, "stop")) { + TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag); + } else if (!strcmp(tag, "all")) { + if ((node = _createCssStyleNode(loader, loader->cssStyle, attrs, attrsLength, simpleXmlParseW3CAttribute))) node->id = _copyId(name); + } else if (!isIgnoreUnsupportedLogElements(tag)) { + TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag); + } + + length -= next - content; + content = next; + + free(tag); + free(name); + } + loader->style = false; +} + + +static bool _svgLoaderParser(void* data, SimpleXMLType type, const char* content, unsigned int length) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + + switch (type) { + case SimpleXMLType::Open: { + _svgLoaderParserXmlOpen(loader, content, length, false); + break; + } + case SimpleXMLType::OpenEmpty: { + _svgLoaderParserXmlOpen(loader, content, length, true); + break; + } + case SimpleXMLType::Close: { + _svgLoaderParserXmlClose(loader, content); + break; + } + case SimpleXMLType::Data: + case SimpleXMLType::CData: { + if (loader->style) _svgLoaderParserXmlCssStyle(loader, content, length); + break; + } + case SimpleXMLType::DoctypeChild: { + break; + } + case SimpleXMLType::Ignored: + case SimpleXMLType::Comment: + case SimpleXMLType::Doctype: { + break; + } + default: { + break; + } + } + + return true; +} + + +static void _inefficientNodeCheck(TVG_UNUSED SvgNode* node) +{ +#ifdef THORVG_LOG_ENABLED + auto type = simpleXmlNodeTypeToString(node->type); + + if (!node->display && node->type != SvgNodeType::ClipPath && node->type != SvgNodeType::Symbol) TVGLOG("SVG", "Inefficient elements used [Display is none][Node Type : %s]", type); + if (node->style->opacity == 0) TVGLOG("SVG", "Inefficient elements used [Opacity is zero][Node Type : %s]", type); + if (node->style->fill.opacity == 0 && node->style->stroke.opacity == 0) TVGLOG("SVG", "Inefficient elements used [Fill opacity and stroke opacity are zero][Node Type : %s]", type); + + switch (node->type) { + case SvgNodeType::Path: { + if (!node->node.path.path) TVGLOG("SVG", "Inefficient elements used [Empty path][Node Type : %s]", type); + break; + } + case SvgNodeType::Ellipse: { + if (node->node.ellipse.rx == 0 && node->node.ellipse.ry == 0) TVGLOG("SVG", "Inefficient elements used [Size is zero][Node Type : %s]", type); + break; + } + case SvgNodeType::Polygon: + case SvgNodeType::Polyline: { + if (node->node.polygon.pts.count < 2) TVGLOG("SVG", "Inefficient elements used [Invalid Polygon][Node Type : %s]", type); + break; + } + case SvgNodeType::Circle: { + if (node->node.circle.r == 0) TVGLOG("SVG", "Inefficient elements used [Size is zero][Node Type : %s]", type); + break; + } + case SvgNodeType::Rect: { + if (node->node.rect.w == 0 && node->node.rect.h) TVGLOG("SVG", "Inefficient elements used [Size is zero][Node Type : %s]", type); + break; + } + case SvgNodeType::Line: { + if (node->node.line.x1 == node->node.line.x2 && node->node.line.y1 == node->node.line.y2) TVGLOG("SVG", "Inefficient elements used [Size is zero][Node Type : %s]", type); + break; + } + default: break; + } +#endif +} + + +static void _updateStyle(SvgNode* node, SvgStyleProperty* parentStyle) +{ + _styleInherit(node->style, parentStyle); + _inefficientNodeCheck(node); + + auto child = node->child.data; + for (uint32_t i = 0; i < node->child.count; ++i, ++child) { + _updateStyle(*child, node->style); + } +} + + +static SvgStyleGradient* _gradientDup(SvgLoaderData* loader, Array* gradients, const char* id) +{ + SvgStyleGradient* result = nullptr; + + auto gradList = gradients->data; + + for (uint32_t i = 0; i < gradients->count; ++i) { + if ((*gradList)->id && !strcmp((*gradList)->id, id)) { + result = _cloneGradient(*gradList); + break; + } + ++gradList; + } + + if (result && result->ref) { + gradList = gradients->data; + for (uint32_t i = 0; i < gradients->count; ++i) { + if ((*gradList)->id && !strcmp((*gradList)->id, result->ref)) { + _inheritGradient(loader, result, *gradList); + break; + } + ++gradList; + } + } + + return result; +} + + +static void _updateGradient(SvgLoaderData* loader, SvgNode* node, Array* gradients) +{ + if (node->child.count > 0) { + auto child = node->child.data; + for (uint32_t i = 0; i < node->child.count; ++i, ++child) { + _updateGradient(loader, *child, gradients); + } + } else { + if (node->style->fill.paint.url) { + auto newGrad = _gradientDup(loader, gradients, node->style->fill.paint.url); + if (newGrad) { + if (node->style->fill.paint.gradient) { + node->style->fill.paint.gradient->clear(); + free(node->style->fill.paint.gradient); + } + node->style->fill.paint.gradient = newGrad; + } + } + if (node->style->stroke.paint.url) { + auto newGrad = _gradientDup(loader, gradients, node->style->stroke.paint.url); + if (newGrad) { + if (node->style->stroke.paint.gradient) { + node->style->stroke.paint.gradient->clear(); + free(node->style->stroke.paint.gradient); + } + node->style->stroke.paint.gradient = newGrad; + } + } + } +} + + +static void _updateComposite(SvgNode* node, SvgNode* root) +{ + if (node->style->clipPath.url && !node->style->clipPath.node) { + SvgNode* findResult = _findNodeById(root, node->style->clipPath.url); + if (findResult) node->style->clipPath.node = findResult; + } + if (node->style->mask.url && !node->style->mask.node) { + SvgNode* findResult = _findNodeById(root, node->style->mask.url); + if (findResult) node->style->mask.node = findResult; + } + if (node->child.count > 0) { + auto child = node->child.data; + for (uint32_t i = 0; i < node->child.count; ++i, ++child) { + _updateComposite(*child, root); + } + } +} + + +static void _freeNodeStyle(SvgStyleProperty* style) +{ + if (!style) return; + + //style->clipPath.node and style->mask.node has only the addresses of node. Therefore, node is released from _freeNode. + free(style->clipPath.url); + free(style->mask.url); + free(style->cssClass); + + if (style->fill.paint.gradient) { + style->fill.paint.gradient->clear(); + free(style->fill.paint.gradient); + } + if (style->stroke.paint.gradient) { + style->stroke.paint.gradient->clear(); + free(style->stroke.paint.gradient); + } + free(style->fill.paint.url); + free(style->stroke.paint.url); + style->stroke.dash.array.reset(); + free(style); +} + + +static void _freeNode(SvgNode* node) +{ + if (!node) return; + + auto child = node->child.data; + for (uint32_t i = 0; i < node->child.count; ++i, ++child) { + _freeNode(*child); + } + node->child.reset(); + + free(node->id); + free(node->transform); + _freeNodeStyle(node->style); + switch (node->type) { + case SvgNodeType::Path: { + free(node->node.path.path); + break; + } + case SvgNodeType::Polygon: { + free(node->node.polygon.pts.data); + break; + } + case SvgNodeType::Polyline: { + free(node->node.polyline.pts.data); + break; + } + case SvgNodeType::Doc: { + _freeNode(node->node.doc.defs); + _freeNode(node->node.doc.style); + break; + } + case SvgNodeType::Defs: { + auto gradients = node->node.defs.gradients.data; + for (size_t i = 0; i < node->node.defs.gradients.count; ++i) { + (*gradients)->clear(); + free(*gradients); + ++gradients; + } + node->node.defs.gradients.reset(); + break; + } + case SvgNodeType::Image: { + free(node->node.image.href); + break; + } + default: { + break; + } + } + free(node); +} + + +static bool _svgLoaderParserForValidCheckXmlOpen(SvgLoaderData* loader, const char* content, unsigned int length) +{ + const char* attrs = nullptr; + int sz = length; + char tagName[20] = ""; + FactoryMethod method; + SvgNode *node = nullptr; + int attrsLength = 0; + loader->level++; + attrs = simpleXmlFindAttributesTag(content, length); + + if (!attrs) { + //Parse the empty tag + attrs = content; + while ((attrs != nullptr) && *attrs != '>') attrs++; + } + + if (attrs) { + sz = attrs - content; + while ((sz > 0) && (isspace(content[sz - 1]))) sz--; + if ((unsigned)sz >= sizeof(tagName)) return false; + strncpy(tagName, content, sz); + tagName[sz] = '\0'; + attrsLength = length - sz; + } + + if ((method = _findGroupFactory(tagName))) { + if (!loader->doc) { + if (strcmp(tagName, "svg")) return true; //Not a valid svg document + node = method(loader, nullptr, attrs, attrsLength, simpleXmlParseAttributes); + loader->doc = node; + loader->stack.push(node); + return false; + } + } + return true; +} + + +static bool _svgLoaderParserForValidCheck(void* data, SimpleXMLType type, const char* content, unsigned int length) +{ + SvgLoaderData* loader = (SvgLoaderData*)data; + bool res = true;; + + switch (type) { + case SimpleXMLType::Open: + case SimpleXMLType::OpenEmpty: { + //If 'res' is false, it means tag is found. + res = _svgLoaderParserForValidCheckXmlOpen(loader, content, length); + break; + } + default: { + break; + } + } + + return res; +} + + +void SvgLoader::clear(bool all) +{ + //flush out the intermediate data + free(loaderData.svgParse); + loaderData.svgParse = nullptr; + + for (auto gradient = loaderData.gradients.data; gradient < loaderData.gradients.end(); ++gradient) { + (*gradient)->clear(); + free(*gradient); + } + loaderData.gradients.reset(); + + _freeNode(loaderData.doc); + loaderData.doc = nullptr; + loaderData.stack.reset(); + + if (!all) return; + + for (auto p = loaderData.images.data; p < loaderData.images.end(); ++p) { + free(*p); + } + loaderData.images.reset(); + + if (copy) free((char*)content); + size = 0; + content = nullptr; + copy = false; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +SvgLoader::SvgLoader() +{ +} + + +SvgLoader::~SvgLoader() +{ + close(); +} + + +void SvgLoader::run(unsigned tid) +{ + //According to the SVG standard the value of the width/height of the viewbox set to 0 disables rendering + if ((viewFlag & SvgViewFlag::Viewbox) && (fabsf(vw) <= FLT_EPSILON || fabsf(vh) <= FLT_EPSILON)) { + TVGLOG("SVG", "The width and/or height set to 0 - rendering disabled."); + root = Scene::gen(); + return; + } + + if (!simpleXmlParse(content, size, true, _svgLoaderParser, &(loaderData))) return; + + if (loaderData.doc) { + auto defs = loaderData.doc->node.doc.defs; + + if (loaderData.nodesToStyle.count > 0) cssApplyStyleToPostponeds(loaderData.nodesToStyle, loaderData.cssStyle); + if (loaderData.cssStyle) cssUpdateStyle(loaderData.doc, loaderData.cssStyle); + + if (loaderData.cloneNodes.count > 0) _clonePostponedNodes(&loaderData.cloneNodes, loaderData.doc); + + _updateComposite(loaderData.doc, loaderData.doc); + if (defs) _updateComposite(loaderData.doc, defs); + + _updateStyle(loaderData.doc, nullptr); + if (defs) _updateStyle(defs, nullptr); + + if (loaderData.gradients.count > 0) _updateGradient(&loaderData, loaderData.doc, &loaderData.gradients); + if (defs) _updateGradient(&loaderData, loaderData.doc, &defs->node.defs.gradients); + } + root = svgSceneBuild(loaderData, {vx, vy, vw, vh}, w, h, align, meetOrSlice, svgPath, viewFlag); + + //In case no viewbox and width/height data is provided the completion of loading + //has to be forced, in order to establish this data based on the whole picture. + if (!(viewFlag & SvgViewFlag::Viewbox)) { + //Override viewbox & size again after svg loading. + vx = loaderData.doc->node.doc.vx; + vy = loaderData.doc->node.doc.vy; + vw = loaderData.doc->node.doc.vw; + vh = loaderData.doc->node.doc.vh; + w = loaderData.doc->node.doc.w; + h = loaderData.doc->node.doc.h; + } + + clear(false); +} + + +bool SvgLoader::header() +{ + //For valid check, only tag is parsed first. + //If the tag is found, the loaded file is valid and stores viewbox information. + //After that, the remaining content data is parsed in order with async. + loaderData.svgParse = (SvgParser*)malloc(sizeof(SvgParser)); + if (!loaderData.svgParse) return false; + + loaderData.svgParse->flags = SvgStopStyleFlags::StopDefault; + viewFlag = SvgViewFlag::None; + + simpleXmlParse(content, size, true, _svgLoaderParserForValidCheck, &(loaderData)); + + if (loaderData.doc && loaderData.doc->type == SvgNodeType::Doc) { + viewFlag = loaderData.doc->node.doc.viewFlag; + align = loaderData.doc->node.doc.align; + meetOrSlice = loaderData.doc->node.doc.meetOrSlice; + + if (viewFlag & SvgViewFlag::Viewbox) { + vx = loaderData.doc->node.doc.vx; + vy = loaderData.doc->node.doc.vy; + vw = loaderData.doc->node.doc.vw; + vh = loaderData.doc->node.doc.vh; + + if (viewFlag & SvgViewFlag::Width) w = loaderData.doc->node.doc.w; + else { + w = loaderData.doc->node.doc.vw; + if (viewFlag & SvgViewFlag::WidthInPercent) { + w *= loaderData.doc->node.doc.w; + viewFlag = (viewFlag ^ SvgViewFlag::WidthInPercent); + } + viewFlag = (viewFlag | SvgViewFlag::Width); + } + if (viewFlag & SvgViewFlag::Height) h = loaderData.doc->node.doc.h; + else { + h = loaderData.doc->node.doc.vh; + if (viewFlag & SvgViewFlag::HeightInPercent) { + h *= loaderData.doc->node.doc.h; + viewFlag = (viewFlag ^ SvgViewFlag::HeightInPercent); + } + viewFlag = (viewFlag | SvgViewFlag::Height); + } + //In case no viewbox and width/height data is provided the completion of loading + //has to be forced, in order to establish this data based on the whole picture. + } else { + //Before loading, set default viewbox & size if they are empty + vx = vy = 0.0f; + if (viewFlag & SvgViewFlag::Width) { + vw = w = loaderData.doc->node.doc.w; + } else { + vw = 1.0f; + if (viewFlag & SvgViewFlag::WidthInPercent) { + w = loaderData.doc->node.doc.w; + } else w = 1.0f; + } + + if (viewFlag & SvgViewFlag::Height) { + vh = h = loaderData.doc->node.doc.h; + } else { + vh = 1.0f; + if (viewFlag & SvgViewFlag::HeightInPercent) { + h = loaderData.doc->node.doc.h; + } else h = 1.0f; + } + + run(0); + } + + return true; + } + + TVGLOG("SVG", "No SVG File. There is no "); + return false; +} + + +bool SvgLoader::open(const char* data, uint32_t size, bool copy) +{ + clear(); + + if (copy) { + content = (char*)malloc(size); + if (!content) return false; + memcpy((char*)content, data, size); + } else content = data; + + this->size = size; + this->copy = copy; + + return header(); +} + + +bool SvgLoader::open(const string& path) +{ + clear(); + + ifstream f; + f.open(path); + + if (!f.is_open()) return false; + + svgPath = path; + getline(f, filePath, '\0'); + f.close(); + + if (filePath.empty()) return false; + + content = filePath.c_str(); + size = filePath.size(); + + return header(); +} + + +bool SvgLoader::resize(Paint* paint, float w, float h) +{ + if (!paint) return false; + + auto sx = w / this->w; + auto sy = h / this->h; + Matrix m = {sx, 0, 0, 0, sy, 0, 0, 0, 1}; + paint->transform(m); + + return true; +} + + +bool SvgLoader::read() +{ + if (!content || size == 0) return false; + + //the loading has been already completed in header() + if (root) return true; + + TaskScheduler::request(this); + + return true; +} + + +bool SvgLoader::close() +{ + this->done(); + + clear(); + + return true; +} + + +unique_ptr SvgLoader::paint() +{ + this->done(); + return std::move(root); +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgLoader.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgLoader.h new file mode 100644 index 000000000..38ead0ebc --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgLoader.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_SVG_LOADER_H_ +#define _TVG_SVG_LOADER_H_ + +#include "tvgTaskScheduler.h" +#include "tvgSvgLoaderCommon.h" + +class SvgLoader : public LoadModule, public Task +{ +public: + string filePath; + string svgPath = ""; + const char* content = nullptr; + uint32_t size = 0; + + SvgLoaderData loaderData; + unique_ptr root; + + bool copy = false; + + SvgLoader(); + ~SvgLoader(); + + using LoadModule::open; + bool open(const string& path) override; + bool open(const char* data, uint32_t size, bool copy) override; + bool resize(Paint* paint, float w, float h) override; + bool read() override; + bool close() override; + + unique_ptr paint() override; + +private: + SvgViewFlag viewFlag = SvgViewFlag::None; + AspectRatioAlign align = AspectRatioAlign::XMidYMid; + AspectRatioMeetOrSlice meetOrSlice = AspectRatioMeetOrSlice::Meet; + float vx = 0; + float vy = 0; + float vw = 0; + float vh = 0; + + bool header(); + void clear(bool all = true); + void run(unsigned tid) override; +}; + + +#endif //_TVG_SVG_LOADER_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgLoaderCommon.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgLoaderCommon.h new file mode 100644 index 000000000..6df7237d7 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgLoaderCommon.h @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_SVG_LOADER_COMMON_H_ +#define _TVG_SVG_LOADER_COMMON_H_ + +#include "tvgCommon.h" +#include "tvgArray.h" + +struct SvgNode; +struct SvgStyleGradient; + +//NOTE: Please update simpleXmlNodeTypeToString() as well. +enum class SvgNodeType +{ + Doc, + G, + Defs, + Animation, + Arc, + Circle, + Ellipse, + Image, + Line, + Path, + Polygon, + Polyline, + Rect, + Text, + TextArea, + Tspan, + Use, + Video, + ClipPath, + Mask, + CssStyle, + Symbol, + Unknown +}; + +/* +// TODO - remove? +enum class SvgLengthType +{ + Percent, + Px, + Pc, + Pt, + Mm, + Cm, + In, +}; +*/ + +enum class SvgFillFlags +{ + Paint = 0x01, + Opacity = 0x02, + Gradient = 0x04, + FillRule = 0x08, + ClipPath = 0x16 +}; + +constexpr bool operator &(SvgFillFlags a, SvgFillFlags b) +{ + return int(a) & int(b); +} + +constexpr SvgFillFlags operator |(SvgFillFlags a, SvgFillFlags b) +{ + return SvgFillFlags(int(a) | int(b)); +} + +enum class SvgStrokeFlags +{ + Paint = 0x1, + Opacity = 0x2, + Gradient = 0x4, + Scale = 0x8, + Width = 0x10, + Cap = 0x20, + Join = 0x40, + Dash = 0x80, + Miterlimit = 0x100, + DashOffset = 0x200 +}; + +constexpr bool operator &(SvgStrokeFlags a, SvgStrokeFlags b) +{ + return int(a) & int(b); +} + +constexpr SvgStrokeFlags operator |(SvgStrokeFlags a, SvgStrokeFlags b) +{ + return SvgStrokeFlags(int(a) | int(b)); +} + + +enum class SvgGradientType +{ + Linear, + Radial +}; + +enum class SvgStyleFlags +{ + Color = 0x01, + Fill = 0x02, + FillRule = 0x04, + FillOpacity = 0x08, + Opacity = 0x010, + Stroke = 0x20, + StrokeWidth = 0x40, + StrokeLineJoin = 0x80, + StrokeLineCap = 0x100, + StrokeOpacity = 0x200, + StrokeDashArray = 0x400, + Transform = 0x800, + ClipPath = 0x1000, + Mask = 0x2000, + MaskType = 0x4000, + Display = 0x8000, + PaintOrder = 0x10000, + StrokeMiterlimit = 0x20000, + StrokeDashOffset = 0x40000, +}; + +constexpr bool operator &(SvgStyleFlags a, SvgStyleFlags b) +{ + return int(a) & int(b); +} + +constexpr SvgStyleFlags operator |(SvgStyleFlags a, SvgStyleFlags b) +{ + return SvgStyleFlags(int(a) | int(b)); +} + +enum class SvgStopStyleFlags +{ + StopDefault = 0x0, + StopOpacity = 0x01, + StopColor = 0x02 +}; + +constexpr bool operator &(SvgStopStyleFlags a, SvgStopStyleFlags b) +{ + return int(a) & int(b); +} + +constexpr SvgStopStyleFlags operator |(SvgStopStyleFlags a, SvgStopStyleFlags b) +{ + return SvgStopStyleFlags(int(a) | int(b)); +} + +enum class SvgGradientFlags +{ + None = 0x0, + GradientUnits = 0x1, + SpreadMethod = 0x2, + X1 = 0x4, + X2 = 0x8, + Y1 = 0x10, + Y2 = 0x20, + Cx = 0x40, + Cy = 0x80, + R = 0x100, + Fx = 0x200, + Fy = 0x400, + Fr = 0x800 +}; + +constexpr bool operator &(SvgGradientFlags a, SvgGradientFlags b) +{ + return int(a) & int(b); +} + +constexpr SvgGradientFlags operator |(SvgGradientFlags a, SvgGradientFlags b) +{ + return SvgGradientFlags(int(a) | int(b)); +} + +enum class SvgFillRule +{ + Winding = 0, + OddEven = 1 +}; + +enum class SvgMaskType +{ + Luminance = 0, + Alpha +}; + +//Length type to recalculate %, pt, pc, mm, cm etc +enum class SvgParserLengthType +{ + Vertical, + Horizontal, + //In case of, for example, radius of radial gradient + Other +}; + +enum class SvgViewFlag +{ + None = 0x0, + Width = 0x01, //viewPort width + Height = 0x02, //viewPort height + Viewbox = 0x04, //viewBox x,y,w,h - used only if all 4 are correctly set + WidthInPercent = 0x08, + HeightInPercent = 0x10 +}; + +constexpr bool operator &(SvgViewFlag a, SvgViewFlag b) +{ + return static_cast(a) & static_cast(b); +} + +constexpr SvgViewFlag operator |(SvgViewFlag a, SvgViewFlag b) +{ + return SvgViewFlag(int(a) | int(b)); +} + +constexpr SvgViewFlag operator ^(SvgViewFlag a, SvgViewFlag b) +{ + return SvgViewFlag(int(a) ^ int(b)); +} + +enum class AspectRatioAlign +{ + None, + XMinYMin, + XMidYMin, + XMaxYMin, + XMinYMid, + XMidYMid, + XMaxYMid, + XMinYMax, + XMidYMax, + XMaxYMax +}; + +enum class AspectRatioMeetOrSlice +{ + Meet, + Slice +}; + +struct SvgDocNode +{ + float w; //unit: point or in percentage see: SvgViewFlag + float h; //unit: point or in percentage see: SvgViewFlag + float vx; + float vy; + float vw; + float vh; + SvgViewFlag viewFlag; + SvgNode* defs; + SvgNode* style; + AspectRatioAlign align; + AspectRatioMeetOrSlice meetOrSlice; +}; + +struct SvgGNode +{ +}; + +struct SvgDefsNode +{ + Array gradients; +}; + +struct SvgSymbolNode +{ + float w, h; + float vx, vy, vw, vh; + AspectRatioAlign align; + AspectRatioMeetOrSlice meetOrSlice; + bool overflowVisible; + bool hasViewBox; + bool hasWidth; + bool hasHeight; +}; + +struct SvgUseNode +{ + float x, y, w, h; + bool isWidthSet; + bool isHeightSet; + SvgNode* symbol; +}; + +struct SvgEllipseNode +{ + float cx; + float cy; + float rx; + float ry; +}; + +struct SvgCircleNode +{ + float cx; + float cy; + float r; +}; + +struct SvgRectNode +{ + float x; + float y; + float w; + float h; + float rx; + float ry; + bool hasRx; + bool hasRy; +}; + +struct SvgLineNode +{ + float x1; + float y1; + float x2; + float y2; +}; + +struct SvgImageNode +{ + float x, y, w, h; + char* href; +}; + +struct SvgPathNode +{ + char* path; +}; + +struct SvgPolygonNode +{ + Array pts; +}; + +struct SvgClipNode +{ + bool userSpace; +}; + +struct SvgMaskNode +{ + SvgMaskType type; + bool userSpace; +}; + +struct SvgCssStyleNode +{ +}; + +struct SvgLinearGradient +{ + float x1; + float y1; + float x2; + float y2; + bool isX1Percentage; + bool isY1Percentage; + bool isX2Percentage; + bool isY2Percentage; +}; + +struct SvgRadialGradient +{ + float cx; + float cy; + float fx; + float fy; + float r; + float fr; + bool isCxPercentage; + bool isCyPercentage; + bool isFxPercentage; + bool isFyPercentage; + bool isRPercentage; + bool isFrPercentage; +}; + +struct SvgComposite +{ + char *url; + SvgNode* node; + bool applying; //flag for checking circular dependency. +}; + +struct SvgColor +{ + uint8_t r; + uint8_t g; + uint8_t b; +}; + +struct SvgPaint +{ + SvgStyleGradient* gradient; + char *url; + SvgColor color; + bool none; + bool curColor; +}; + +struct SvgDash +{ + Array array; + float offset; +}; + +struct SvgStyleGradient +{ + SvgGradientType type; + char* id; + char* ref; + FillSpread spread; + SvgRadialGradient* radial; + SvgLinearGradient* linear; + Matrix* transform; + Array stops; + SvgGradientFlags flags; + bool userSpace; + + void clear() + { + stops.reset(); + free(transform); + free(radial); + free(linear); + free(ref); + free(id); + } +}; + +struct SvgStyleFill +{ + SvgFillFlags flags; + SvgPaint paint; + int opacity; + FillRule fillRule; +}; + +struct SvgStyleStroke +{ + SvgStrokeFlags flags; + SvgPaint paint; + int opacity; + float scale; + float width; + float centered; + StrokeCap cap; + StrokeJoin join; + float miterlimit; + SvgDash dash; +}; + +struct SvgStyleProperty +{ + SvgStyleFill fill; + SvgStyleStroke stroke; + SvgComposite clipPath; + SvgComposite mask; + int opacity; + SvgColor color; + bool curColorSet; + char* cssClass; + bool paintOrder; //true if default (fill, stroke), false otherwise + SvgStyleFlags flags; + SvgStyleFlags flagsImportance; //indicates the importance of the flag - if set, higher priority is applied (https://drafts.csswg.org/css-cascade-4/#importance) +}; + +struct SvgNode +{ + SvgNodeType type; + SvgNode* parent; + Array child; + char *id; + SvgStyleProperty *style; + Matrix* transform; + union { + SvgGNode g; + SvgDocNode doc; + SvgDefsNode defs; + SvgUseNode use; + SvgCircleNode circle; + SvgEllipseNode ellipse; + SvgPolygonNode polygon; + SvgPolygonNode polyline; + SvgRectNode rect; + SvgPathNode path; + SvgLineNode line; + SvgImageNode image; + SvgMaskNode mask; + SvgClipNode clip; + SvgCssStyleNode cssStyle; + SvgSymbolNode symbol; + } node; + bool display; + ~SvgNode(); +}; + +struct SvgParser +{ + SvgNode* node; + SvgStyleGradient* styleGrad; + Fill::ColorStop gradStop; + SvgStopStyleFlags flags; + struct + { + float x, y, w, h; + } global; + struct + { + bool parsedFx; + bool parsedFy; + } gradient; +}; + +struct SvgNodeIdPair +{ + SvgNode* node; + char *id; +}; + +struct SvgLoaderData +{ + Array stack; + SvgNode* doc = nullptr; + SvgNode* def = nullptr; + SvgNode* cssStyle = nullptr; + Array gradients; + SvgStyleGradient* latestGradient = nullptr; //For stops + SvgParser* svgParse = nullptr; + Array cloneNodes; + Array nodesToStyle; + Array images; //embedded images + int level = 0; + bool result = false; + bool style = false; +}; + +struct Box +{ + float x, y, w, h; +}; + +#endif + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgPath.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgPath.cpp new file mode 100644 index 000000000..46ec157f3 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgPath.cpp @@ -0,0 +1,561 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +/* + * Copyright notice for the EFL: + + * Copyright (C) EFL developers (see AUTHORS) + + * All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _USE_MATH_DEFINES //Math Constants are not defined in Standard C/C++. + +#include +#include +#include +#include "tvgSvgLoaderCommon.h" +#include "tvgSvgPath.h" +#include "tvgStr.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static char* _skipComma(const char* content) +{ + while (*content && isspace(*content)) { + content++; + } + if (*content == ',') return (char*)content + 1; + return (char*)content; +} + + +static bool _parseNumber(char** content, float* number) +{ + char* end = NULL; + *number = strToFloat(*content, &end); + //If the start of string is not number + if ((*content) == end) return false; + //Skip comma if any + *content = _skipComma(end); + return true; +} + + +static bool _parseFlag(char** content, int* number) +{ + char* end = NULL; + if (*(*content) != '0' && *(*content) != '1') return false; + *number = *(*content) - '0'; + *content += 1; + end = *content; + *content = _skipComma(end); + + return true; +} + + +void _pathAppendArcTo(Array* cmds, Array* pts, Point* cur, Point* curCtl, float x, float y, float rx, float ry, float angle, bool largeArc, bool sweep) +{ + float cxp, cyp, cx, cy; + float sx, sy; + float cosPhi, sinPhi; + float dx2, dy2; + float x1p, y1p; + float x1p2, y1p2; + float rx2, ry2; + float lambda; + float c; + float at; + float theta1, deltaTheta; + float nat; + float delta, bcp; + float cosPhiRx, cosPhiRy; + float sinPhiRx, sinPhiRy; + float cosTheta1, sinTheta1; + int segments; + + //Some helpful stuff is available here: + //http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes + sx = cur->x; + sy = cur->y; + + //If start and end points are identical, then no arc is drawn + if ((fabsf(x - sx) < (1.0f / 256.0f)) && (fabsf(y - sy) < (1.0f / 256.0f))) return; + + //Correction of out-of-range radii, see F6.6.1 (step 2) + rx = fabsf(rx); + ry = fabsf(ry); + + angle = angle * (float)M_PI / 180.0f; + cosPhi = cosf(angle); + sinPhi = sinf(angle); + dx2 = (sx - x) / 2.0f; + dy2 = (sy - y) / 2.0f; + x1p = cosPhi * dx2 + sinPhi * dy2; + y1p = cosPhi * dy2 - sinPhi * dx2; + x1p2 = x1p * x1p; + y1p2 = y1p * y1p; + rx2 = rx * rx; + ry2 = ry * ry; + lambda = (x1p2 / rx2) + (y1p2 / ry2); + + //Correction of out-of-range radii, see F6.6.2 (step 4) + if (lambda > 1.0f) { + //See F6.6.3 + float lambdaRoot = sqrtf(lambda); + + rx *= lambdaRoot; + ry *= lambdaRoot; + //Update rx2 and ry2 + rx2 = rx * rx; + ry2 = ry * ry; + } + + c = (rx2 * ry2) - (rx2 * y1p2) - (ry2 * x1p2); + + //Check if there is no possible solution + //(i.e. we can't do a square root of a negative value) + if (c < 0.0f) { + //Scale uniformly until we have a single solution + //(see F6.2) i.e. when c == 0.0 + float scale = sqrtf(1.0f - c / (rx2 * ry2)); + rx *= scale; + ry *= scale; + //Update rx2 and ry2 + rx2 = rx * rx; + ry2 = ry * ry; + + //Step 2 (F6.5.2) - simplified since c == 0.0 + cxp = 0.0f; + cyp = 0.0f; + //Step 3 (F6.5.3 first part) - simplified since cxp and cyp == 0.0 + cx = 0.0f; + cy = 0.0f; + } else { + //Complete c calculation + c = sqrtf(c / ((rx2 * y1p2) + (ry2 * x1p2))); + //Inverse sign if Fa == Fs + if (largeArc == sweep) c = -c; + + //Step 2 (F6.5.2) + cxp = c * (rx * y1p / ry); + cyp = c * (-ry * x1p / rx); + + //Step 3 (F6.5.3 first part) + cx = cosPhi * cxp - sinPhi * cyp; + cy = sinPhi * cxp + cosPhi * cyp; + } + + //Step 3 (F6.5.3 second part) we now have the center point of the ellipse + cx += (sx + x) / 2.0f; + cy += (sy + y) / 2.0f; + + //Sstep 4 (F6.5.4) + //We dont' use arccos (as per w3c doc), see + //http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm + //Note: atan2 (0.0, 1.0) == 0.0 + at = atan2(((y1p - cyp) / ry), ((x1p - cxp) / rx)); + theta1 = (at < 0.0f) ? 2.0f * (float)M_PI + at : at; + + nat = atan2(((-y1p - cyp) / ry), ((-x1p - cxp) / rx)); + deltaTheta = (nat < at) ? 2.0f * (float)M_PI - at + nat : nat - at; + + if (sweep) { + //Ensure delta theta < 0 or else add 360 degrees + if (deltaTheta < 0.0f) deltaTheta += (float)(2.0f * (float)M_PI); + } else { + //Ensure delta theta > 0 or else substract 360 degrees + if (deltaTheta > 0.0f) deltaTheta -= (float)(2.0f * (float)M_PI); + } + + //Add several cubic bezier to approximate the arc + //(smaller than 90 degrees) + //We add one extra segment because we want something + //Smaller than 90deg (i.e. not 90 itself) + segments = static_cast(fabsf(deltaTheta / float(M_PI_2)) + 1.0f); + delta = deltaTheta / segments; + + //http://www.stillhq.com/ctpfaq/2001/comp.text.pdf-faq-2001-04.txt (section 2.13) + bcp = 4.0f / 3.0f * (1.0f - cosf(delta / 2.0f)) / sinf(delta / 2.0f); + + cosPhiRx = cosPhi * rx; + cosPhiRy = cosPhi * ry; + sinPhiRx = sinPhi * rx; + sinPhiRy = sinPhi * ry; + + cosTheta1 = cosf(theta1); + sinTheta1 = sinf(theta1); + + for (int i = 0; i < segments; ++i) { + //End angle (for this segment) = current + delta + float c1x, c1y, ex, ey, c2x, c2y; + float theta2 = theta1 + delta; + float cosTheta2 = cosf(theta2); + float sinTheta2 = sinf(theta2); + Point p[3]; + + //First control point (based on start point sx,sy) + c1x = sx - bcp * (cosPhiRx * sinTheta1 + sinPhiRy * cosTheta1); + c1y = sy + bcp * (cosPhiRy * cosTheta1 - sinPhiRx * sinTheta1); + + //End point (for this segment) + ex = cx + (cosPhiRx * cosTheta2 - sinPhiRy * sinTheta2); + ey = cy + (sinPhiRx * cosTheta2 + cosPhiRy * sinTheta2); + + //Second control point (based on end point ex,ey) + c2x = ex + bcp * (cosPhiRx * sinTheta2 + sinPhiRy * cosTheta2); + c2y = ey + bcp * (sinPhiRx * sinTheta2 - cosPhiRy * cosTheta2); + cmds->push(PathCommand::CubicTo); + p[0] = {c1x, c1y}; + p[1] = {c2x, c2y}; + p[2] = {ex, ey}; + pts->push(p[0]); + pts->push(p[1]); + pts->push(p[2]); + *curCtl = p[1]; + *cur = p[2]; + + //Next start point is the current end point (same for angle) + sx = ex; + sy = ey; + theta1 = theta2; + //Avoid recomputations + cosTheta1 = cosTheta2; + sinTheta1 = sinTheta2; + } +} + +static int _numberCount(char cmd) +{ + int count = 0; + switch (cmd) { + case 'M': + case 'm': + case 'L': + case 'l': + case 'T': + case 't': { + count = 2; + break; + } + case 'C': + case 'c': + case 'E': + case 'e': { + count = 6; + break; + } + case 'H': + case 'h': + case 'V': + case 'v': { + count = 1; + break; + } + case 'S': + case 's': + case 'Q': + case 'q': { + count = 4; + break; + } + case 'A': + case 'a': { + count = 7; + break; + } + default: + break; + } + return count; +} + + +static bool _processCommand(Array* cmds, Array* pts, char cmd, float* arr, int count, Point* cur, Point* curCtl, Point* startPoint, bool *isQuadratic) +{ + switch (cmd) { + case 'm': + case 'l': + case 'c': + case 's': + case 'q': + case 't': { + for (int i = 0; i < count - 1; i += 2) { + arr[i] = arr[i] + cur->x; + arr[i + 1] = arr[i + 1] + cur->y; + } + break; + } + case 'h': { + arr[0] = arr[0] + cur->x; + break; + } + case 'v': { + arr[0] = arr[0] + cur->y; + break; + } + case 'a': { + arr[5] = arr[5] + cur->x; + arr[6] = arr[6] + cur->y; + break; + } + default: { + break; + } + } + + switch (cmd) { + case 'm': + case 'M': { + Point p = {arr[0], arr[1]}; + cmds->push(PathCommand::MoveTo); + pts->push(p); + *cur = {arr[0], arr[1]}; + *startPoint = {arr[0], arr[1]}; + break; + } + case 'l': + case 'L': { + Point p = {arr[0], arr[1]}; + cmds->push(PathCommand::LineTo); + pts->push(p); + *cur = {arr[0], arr[1]}; + break; + } + case 'c': + case 'C': { + Point p[3]; + cmds->push(PathCommand::CubicTo); + p[0] = {arr[0], arr[1]}; + p[1] = {arr[2], arr[3]}; + p[2] = {arr[4], arr[5]}; + pts->push(p[0]); + pts->push(p[1]); + pts->push(p[2]); + *curCtl = p[1]; + *cur = p[2]; + *isQuadratic = false; + break; + } + case 's': + case 'S': { + Point p[3], ctrl; + if ((cmds->count > 1) && (cmds->last() == PathCommand::CubicTo) && + !(*isQuadratic)) { + ctrl.x = 2 * cur->x - curCtl->x; + ctrl.y = 2 * cur->y - curCtl->y; + } else { + ctrl = *cur; + } + cmds->push(PathCommand::CubicTo); + p[0] = ctrl; + p[1] = {arr[0], arr[1]}; + p[2] = {arr[2], arr[3]}; + pts->push(p[0]); + pts->push(p[1]); + pts->push(p[2]); + *curCtl = p[1]; + *cur = p[2]; + *isQuadratic = false; + break; + } + case 'q': + case 'Q': { + Point p[3]; + float ctrl_x0 = (cur->x + 2 * arr[0]) * (1.0f / 3.0f); + float ctrl_y0 = (cur->y + 2 * arr[1]) * (1.0f / 3.0f); + float ctrl_x1 = (arr[2] + 2 * arr[0]) * (1.0f / 3.0f); + float ctrl_y1 = (arr[3] + 2 * arr[1]) * (1.0f / 3.0f); + cmds->push(PathCommand::CubicTo); + p[0] = {ctrl_x0, ctrl_y0}; + p[1] = {ctrl_x1, ctrl_y1}; + p[2] = {arr[2], arr[3]}; + pts->push(p[0]); + pts->push(p[1]); + pts->push(p[2]); + *curCtl = {arr[0], arr[1]}; + *cur = p[2]; + *isQuadratic = true; + break; + } + case 't': + case 'T': { + Point p[3], ctrl; + if ((cmds->count > 1) && (cmds->last() == PathCommand::CubicTo) && + *isQuadratic) { + ctrl.x = 2 * cur->x - curCtl->x; + ctrl.y = 2 * cur->y - curCtl->y; + } else { + ctrl = *cur; + } + float ctrl_x0 = (cur->x + 2 * ctrl.x) * (1.0f / 3.0f); + float ctrl_y0 = (cur->y + 2 * ctrl.y) * (1.0f / 3.0f); + float ctrl_x1 = (arr[0] + 2 * ctrl.x) * (1.0f / 3.0f); + float ctrl_y1 = (arr[1] + 2 * ctrl.y) * (1.0f / 3.0f); + cmds->push(PathCommand::CubicTo); + p[0] = {ctrl_x0, ctrl_y0}; + p[1] = {ctrl_x1, ctrl_y1}; + p[2] = {arr[0], arr[1]}; + pts->push(p[0]); + pts->push(p[1]); + pts->push(p[2]); + *curCtl = {ctrl.x, ctrl.y}; + *cur = p[2]; + *isQuadratic = true; + break; + } + case 'h': + case 'H': { + Point p = {arr[0], cur->y}; + cmds->push(PathCommand::LineTo); + pts->push(p); + cur->x = arr[0]; + break; + } + case 'v': + case 'V': { + Point p = {cur->x, arr[0]}; + cmds->push(PathCommand::LineTo); + pts->push(p); + cur->y = arr[0]; + break; + } + case 'z': + case 'Z': { + cmds->push(PathCommand::Close); + *cur = *startPoint; + break; + } + case 'a': + case 'A': { + _pathAppendArcTo(cmds, pts, cur, curCtl, arr[5], arr[6], arr[0], arr[1], arr[2], arr[3], arr[4]); + *cur = *curCtl = {arr[5], arr[6]}; + *isQuadratic = false; + break; + } + default: { + return false; + } + } + return true; +} + + +static char* _nextCommand(char* path, char* cmd, float* arr, int* count) +{ + int large, sweep; + + path = _skipComma(path); + if (isalpha(*path)) { + *cmd = *path; + path++; + *count = _numberCount(*cmd); + } else { + if (*cmd == 'm') *cmd = 'l'; + else if (*cmd == 'M') *cmd = 'L'; + } + if (*count == 7) { + //Special case for arc command + if (_parseNumber(&path, &arr[0])) { + if (_parseNumber(&path, &arr[1])) { + if (_parseNumber(&path, &arr[2])) { + if (_parseFlag(&path, &large)) { + if (_parseFlag(&path, &sweep)) { + if (_parseNumber(&path, &arr[5])) { + if (_parseNumber(&path, &arr[6])) { + arr[3] = (float)large; + arr[4] = (float)sweep; + return path; + } + } + } + } + } + } + } + *count = 0; + return NULL; + } + for (int i = 0; i < *count; i++) { + if (!_parseNumber(&path, &arr[i])) { + *count = 0; + return NULL; + } + path = _skipComma(path); + } + return path; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + + +bool svgPathToTvgPath(const char* svgPath, Array& cmds, Array& pts) +{ + float numberArray[7]; + int numberCount = 0; + Point cur = { 0, 0 }; + Point curCtl = { 0, 0 }; + Point startPoint = { 0, 0 }; + char cmd = 0; + bool isQuadratic = false; + char* path = (char*)svgPath; + + while ((path[0] != '\0')) { + path = _nextCommand(path, &cmd, numberArray, &numberCount); + if (!path) break; + if (!_processCommand(&cmds, &pts, cmd, numberArray, numberCount, &cur, &curCtl, &startPoint, &isQuadratic)) break; + } + + return true; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgPath.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgPath.h new file mode 100644 index 000000000..5ac02cd6a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgPath.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_SVG_PATH_H_ +#define _TVG_SVG_PATH_H_ + +#include "tvgCommon.h" + +bool svgPathToTvgPath(const char* svgPath, Array& cmds, Array& pts); + +#endif //_TVG_SVG_PATH_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgSceneBuilder.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgSceneBuilder.cpp new file mode 100644 index 000000000..ace3d32e5 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgSceneBuilder.cpp @@ -0,0 +1,890 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgMath.h" /* to include math.h before cstring */ +#include +#include +#include "tvgShape.h" +#include "tvgCompressor.h" +#include "tvgPaint.h" +#include "tvgFill.h" +#include "tvgStr.h" +#include "tvgSvgLoaderCommon.h" +#include "tvgSvgSceneBuilder.h" +#include "tvgSvgPath.h" +#include "tvgSvgUtil.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static bool _appendShape(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath); +static bool _appendClipShape(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath, const Matrix* transform); +static unique_ptr _sceneBuildHelper(SvgLoaderData& loaderData, const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, int depth, bool* isMaskWhite = nullptr); + + +static inline bool _isGroupType(SvgNodeType type) +{ + if (type == SvgNodeType::Doc || type == SvgNodeType::G || type == SvgNodeType::Use || type == SvgNodeType::ClipPath || type == SvgNodeType::Symbol) return true; + return false; +} + + +//According to: https://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBoxUnits (the last paragraph) +//a stroke width should be ignored for bounding box calculations +static Box _boundingBox(const Shape* shape) +{ + float x, y, w, h; + shape->bounds(&x, &y, &w, &h, false); + + if (auto strokeW = shape->strokeWidth()) { + x += 0.5f * strokeW; + y += 0.5f * strokeW; + w -= strokeW; + h -= strokeW; + } + + return {x, y, w, h}; +} + + +static void _transformMultiply(const Matrix* mBBox, Matrix* gradTransf) +{ + gradTransf->e13 = gradTransf->e13 * mBBox->e11 + mBBox->e13; + gradTransf->e12 *= mBBox->e11; + gradTransf->e11 *= mBBox->e11; + + gradTransf->e23 = gradTransf->e23 * mBBox->e22 + mBBox->e23; + gradTransf->e22 *= mBBox->e22; + gradTransf->e21 *= mBBox->e22; +} + + +static unique_ptr _applyLinearGradientProperty(SvgStyleGradient* g, const Shape* vg, const Box& vBox, int opacity) +{ + Fill::ColorStop* stops; + int stopCount = 0; + auto fillGrad = LinearGradient::gen(); + + bool isTransform = (g->transform ? true : false); + Matrix finalTransform = {1, 0, 0, 0, 1, 0, 0, 0, 1}; + if (isTransform) finalTransform = *g->transform; + + if (g->userSpace) { + g->linear->x1 = g->linear->x1 * vBox.w; + g->linear->y1 = g->linear->y1 * vBox.h; + g->linear->x2 = g->linear->x2 * vBox.w; + g->linear->y2 = g->linear->y2 * vBox.h; + } else { + Matrix m = {vBox.w, 0, vBox.x, 0, vBox.h, vBox.y, 0, 0, 1}; + if (isTransform) _transformMultiply(&m, &finalTransform); + else { + finalTransform = m; + isTransform = true; + } + } + + if (isTransform) fillGrad->transform(finalTransform); + + fillGrad->linear(g->linear->x1, g->linear->y1, g->linear->x2, g->linear->y2); + fillGrad->spread(g->spread); + + //Update the stops + stopCount = g->stops.count; + if (stopCount > 0) { + stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop)); + if (!stops) return fillGrad; + auto prevOffset = 0.0f; + for (uint32_t i = 0; i < g->stops.count; ++i) { + auto colorStop = &g->stops[i]; + //Use premultiplied color + stops[i].r = colorStop->r; + stops[i].g = colorStop->g; + stops[i].b = colorStop->b; + stops[i].a = static_cast((colorStop->a * opacity) / 255); + stops[i].offset = colorStop->offset; + //check the offset corner cases - refer to: https://svgwg.org/svg2-draft/pservers.html#StopNotes + if (colorStop->offset < prevOffset) stops[i].offset = prevOffset; + else if (colorStop->offset > 1) stops[i].offset = 1; + prevOffset = stops[i].offset; + } + fillGrad->colorStops(stops, stopCount); + free(stops); + } + return fillGrad; +} + + +static unique_ptr _applyRadialGradientProperty(SvgStyleGradient* g, const Shape* vg, const Box& vBox, int opacity) +{ + Fill::ColorStop *stops; + int stopCount = 0; + auto fillGrad = RadialGradient::gen(); + + bool isTransform = (g->transform ? true : false); + Matrix finalTransform = {1, 0, 0, 0, 1, 0, 0, 0, 1}; + if (isTransform) finalTransform = *g->transform; + + if (g->userSpace) { + //The radius scalling is done according to the Units section: + //https://www.w3.org/TR/2015/WD-SVG2-20150915/coords.html + g->radial->cx = g->radial->cx * vBox.w; + g->radial->cy = g->radial->cy * vBox.h; + g->radial->r = g->radial->r * sqrtf(powf(vBox.w, 2.0f) + powf(vBox.h, 2.0f)) / sqrtf(2.0f); + g->radial->fx = g->radial->fx * vBox.w; + g->radial->fy = g->radial->fy * vBox.h; + g->radial->fr = g->radial->fr * sqrtf(powf(vBox.w, 2.0f) + powf(vBox.h, 2.0f)) / sqrtf(2.0f); + } else { + Matrix m = {vBox.w, 0, vBox.x, 0, vBox.h, vBox.y, 0, 0, 1}; + if (isTransform) _transformMultiply(&m, &finalTransform); + else { + finalTransform = m; + isTransform = true; + } + } + + if (isTransform) fillGrad->transform(finalTransform); + + P(fillGrad)->radial(g->radial->cx, g->radial->cy, g->radial->r, g->radial->fx, g->radial->fy, g->radial->fr); + fillGrad->spread(g->spread); + + //Update the stops + stopCount = g->stops.count; + if (stopCount > 0) { + stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop)); + if (!stops) return fillGrad; + auto prevOffset = 0.0f; + for (uint32_t i = 0; i < g->stops.count; ++i) { + auto colorStop = &g->stops[i]; + //Use premultiplied color + stops[i].r = colorStop->r; + stops[i].g = colorStop->g; + stops[i].b = colorStop->b; + stops[i].a = static_cast((colorStop->a * opacity) / 255); + stops[i].offset = colorStop->offset; + //check the offset corner cases - refer to: https://svgwg.org/svg2-draft/pservers.html#StopNotes + if (colorStop->offset < prevOffset) stops[i].offset = prevOffset; + else if (colorStop->offset > 1) stops[i].offset = 1; + prevOffset = stops[i].offset; + } + fillGrad->colorStops(stops, stopCount); + free(stops); + } + return fillGrad; +} + + +//The SVG standard allows only for 'use' nodes that point directly to a basic shape. +static bool _appendClipUseNode(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath) +{ + if (node->child.count != 1) return false; + auto child = *(node->child.data); + + Matrix finalTransform = {1, 0, 0, 0, 1, 0, 0, 0, 1}; + if (node->transform) finalTransform = *node->transform; + if (node->node.use.x != 0.0f || node->node.use.y != 0.0f) { + Matrix m = {1, 0, node->node.use.x, 0, 1, node->node.use.y, 0, 0, 1}; + finalTransform = mathMultiply(&finalTransform, &m); + } + if (child->transform) finalTransform = mathMultiply(child->transform, &finalTransform); + + return _appendClipShape(loaderData, child, shape, vBox, svgPath, mathIdentity((const Matrix*)(&finalTransform)) ? nullptr : &finalTransform); +} + + +static bool _appendClipChild(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath, bool clip) +{ + if (node->type == SvgNodeType::Use) { + return _appendClipUseNode(loaderData, node, shape, vBox, svgPath); + } + return _appendClipShape(loaderData, node, shape, vBox, svgPath, nullptr); +} + + +static Matrix _compositionTransform(Paint* paint, const SvgNode* node, const SvgNode* compNode, SvgNodeType type) +{ + Matrix m = {1, 0, 0, 0, 1, 0, 0, 0, 1}; + //The initial mask transformation ignored according to the SVG standard. + if (node->transform && type != SvgNodeType::Mask) { + m = *node->transform; + } + if (compNode->transform) { + m = mathMultiply(&m, compNode->transform); + } + if (!compNode->node.clip.userSpace) { + float x, y, w, h; + P(paint)->bounds(&x, &y, &w, &h, false, false); + Matrix mBBox = {w, 0, x, 0, h, y, 0, 0, 1}; + m = mathMultiply(&m, &mBBox); + } + return m; +} + + +static void _applyComposition(SvgLoaderData& loaderData, Paint* paint, const SvgNode* node, const Box& vBox, const string& svgPath) +{ + /* ClipPath */ + /* Do not drop in Circular Dependency for ClipPath. + Composition can be applied recursively if its children nodes have composition target to this one. */ + if (node->style->clipPath.applying) { + TVGLOG("SVG", "Multiple Composition Tried! Check out Circular dependency?"); + } else { + auto compNode = node->style->clipPath.node; + if (compNode && compNode->child.count > 0) { + node->style->clipPath.applying = true; + + auto comp = Shape::gen(); + + auto child = compNode->child.data; + auto valid = false; //Composite only when valid shapes exist + + for (uint32_t i = 0; i < compNode->child.count; ++i, ++child) { + if (_appendClipChild(loaderData, *child, comp.get(), vBox, svgPath, compNode->child.count > 1)) valid = true; + } + + if (valid) { + Matrix finalTransform = _compositionTransform(paint, node, compNode, SvgNodeType::ClipPath); + comp->transform(finalTransform); + + paint->composite(std::move(comp), CompositeMethod::ClipPath); + } + + node->style->clipPath.applying = false; + } + } + + /* Mask */ + /* Do not drop in Circular Dependency for Mask. + Composition can be applied recursively if its children nodes have composition target to this one. */ + if (node->style->mask.applying) { + TVGLOG("SVG", "Multiple Composition Tried! Check out Circular dependency?"); + } else { + auto compNode = node->style->mask.node; + if (compNode && compNode->child.count > 0) { + node->style->mask.applying = true; + + bool isMaskWhite = true; + if (auto comp = _sceneBuildHelper(loaderData, compNode, vBox, svgPath, true, 0, &isMaskWhite)) { + if (!compNode->node.mask.userSpace) { + Matrix finalTransform = _compositionTransform(paint, node, compNode, SvgNodeType::Mask); + comp->transform(finalTransform); + } else { + if (node->transform) comp->transform(*node->transform); + } + + if (compNode->node.mask.type == SvgMaskType::Luminance && !isMaskWhite) { + paint->composite(std::move(comp), CompositeMethod::LumaMask); + } else { + paint->composite(std::move(comp), CompositeMethod::AlphaMask); + } + } + + node->style->mask.applying = false; + } + } +} + + +static void _applyProperty(SvgLoaderData& loaderData, SvgNode* node, Shape* vg, const Box& vBox, const string& svgPath, bool clip) +{ + SvgStyleProperty* style = node->style; + + //Clip transformation is applied directly to the path in the _appendClipShape function + if (node->transform && !clip) vg->transform(*node->transform); + if (node->type == SvgNodeType::Doc || !node->display) return; + + //If fill property is nullptr then do nothing + if (style->fill.paint.none) { + //Do nothing + } else if (style->fill.paint.gradient) { + Box bBox = vBox; + if (!style->fill.paint.gradient->userSpace) bBox = _boundingBox(vg); + + if (style->fill.paint.gradient->type == SvgGradientType::Linear) { + auto linear = _applyLinearGradientProperty(style->fill.paint.gradient, vg, bBox, style->fill.opacity); + vg->fill(std::move(linear)); + } else if (style->fill.paint.gradient->type == SvgGradientType::Radial) { + auto radial = _applyRadialGradientProperty(style->fill.paint.gradient, vg, bBox, style->fill.opacity); + vg->fill(std::move(radial)); + } + } else if (style->fill.paint.url) { + //TODO: Apply the color pointed by url + } else if (style->fill.paint.curColor) { + //Apply the current style color + vg->fill(style->color.r, style->color.g, style->color.b, style->fill.opacity); + } else { + //Apply the fill color + vg->fill(style->fill.paint.color.r, style->fill.paint.color.g, style->fill.paint.color.b, style->fill.opacity); + } + + //Apply the fill rule + vg->fill((tvg::FillRule)style->fill.fillRule); + //Rendering order + vg->order(!style->paintOrder); + + //Apply node opacity + if (style->opacity < 255) vg->opacity(style->opacity); + + if (node->type == SvgNodeType::G || node->type == SvgNodeType::Use) return; + + //Apply the stroke style property + vg->stroke(style->stroke.width); + vg->stroke(style->stroke.cap); + vg->stroke(style->stroke.join); + vg->strokeMiterlimit(style->stroke.miterlimit); + if (style->stroke.dash.array.count > 0) { + P(vg)->strokeDash(style->stroke.dash.array.data, style->stroke.dash.array.count, style->stroke.dash.offset); + } + + //If stroke property is nullptr then do nothing + if (style->stroke.paint.none) { + vg->stroke(0.0f); + } else if (style->stroke.paint.gradient) { + Box bBox = vBox; + if (!style->stroke.paint.gradient->userSpace) bBox = _boundingBox(vg); + + if (style->stroke.paint.gradient->type == SvgGradientType::Linear) { + auto linear = _applyLinearGradientProperty(style->stroke.paint.gradient, vg, bBox, style->stroke.opacity); + vg->stroke(std::move(linear)); + } else if (style->stroke.paint.gradient->type == SvgGradientType::Radial) { + auto radial = _applyRadialGradientProperty(style->stroke.paint.gradient, vg, bBox, style->stroke.opacity); + vg->stroke(std::move(radial)); + } + } else if (style->stroke.paint.url) { + //TODO: Apply the color pointed by url + } else if (style->stroke.paint.curColor) { + //Apply the current style color + vg->stroke(style->color.r, style->color.g, style->color.b, style->stroke.opacity); + } else { + //Apply the stroke color + vg->stroke(style->stroke.paint.color.r, style->stroke.paint.color.g, style->stroke.paint.color.b, style->stroke.opacity); + } + + _applyComposition(loaderData, vg, node, vBox, svgPath); +} + + +static unique_ptr _shapeBuildHelper(SvgLoaderData& loaderData, SvgNode* node, const Box& vBox, const string& svgPath) +{ + auto shape = Shape::gen(); + if (_appendShape(loaderData, node, shape.get(), vBox, svgPath)) return shape; + else return nullptr; +} + + +static bool _recognizeShape(SvgNode* node, Shape* shape) +{ + switch (node->type) { + case SvgNodeType::Path: { + if (node->node.path.path) { + Array cmds; + Array pts; + if (svgPathToTvgPath(node->node.path.path, cmds, pts)) { + shape->appendPath(cmds.data, cmds.count, pts.data, pts.count); + } + } + break; + } + case SvgNodeType::Ellipse: { + shape->appendCircle(node->node.ellipse.cx, node->node.ellipse.cy, node->node.ellipse.rx, node->node.ellipse.ry); + break; + } + case SvgNodeType::Polygon: { + if (node->node.polygon.pts.count < 2) break; + auto pts = node->node.polygon.pts.data; + shape->moveTo(pts[0], pts[1]); + for (pts += 2; pts < node->node.polygon.pts.end(); pts += 2) { + shape->lineTo(pts[0], pts[1]); + } + shape->close(); + break; + } + case SvgNodeType::Polyline: { + if (node->node.polyline.pts.count < 2) break; + auto pts = node->node.polyline.pts.data; + shape->moveTo(pts[0], pts[1]); + for (pts += 2; pts < node->node.polyline.pts.end(); pts += 2) { + shape->lineTo(pts[0], pts[1]); + } + break; + } + case SvgNodeType::Circle: { + shape->appendCircle(node->node.circle.cx, node->node.circle.cy, node->node.circle.r, node->node.circle.r); + break; + } + case SvgNodeType::Rect: { + shape->appendRect(node->node.rect.x, node->node.rect.y, node->node.rect.w, node->node.rect.h, node->node.rect.rx, node->node.rect.ry); + break; + } + case SvgNodeType::Line: { + shape->moveTo(node->node.line.x1, node->node.line.y1); + shape->lineTo(node->node.line.x2, node->node.line.y2); + break; + } + default: { + return false; + } + } + return true; +} + + +static bool _appendShape(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath) +{ + if (!_recognizeShape(node, shape)) return false; + + _applyProperty(loaderData, node, shape, vBox, svgPath, false); + return true; +} + + +static bool _appendClipShape(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath, const Matrix* transform) +{ + //The 'transform' matrix has higher priority than the node->transform, since it already contains it + auto m = transform ? transform : (node->transform ? node->transform : nullptr); + + uint32_t currentPtsCnt = 0; + if (m) { + const Point *tmp = nullptr; + currentPtsCnt = shape->pathCoords(&tmp); + } + + if (!_recognizeShape(node, shape)) return false; + + if (m) { + const Point *pts = nullptr; + auto ptsCnt = shape->pathCoords(&pts); + + auto p = const_cast(pts) + currentPtsCnt; + while (currentPtsCnt++ < ptsCnt) mathMultiply(p++, m); + } + + _applyProperty(loaderData, node, shape, vBox, svgPath, true); + return true; +} + + +enum class imageMimeTypeEncoding +{ + base64 = 0x1, + utf8 = 0x2 +}; + +constexpr imageMimeTypeEncoding operator|(imageMimeTypeEncoding a, imageMimeTypeEncoding b) { + return static_cast(static_cast(a) | static_cast(b)); +} + +constexpr bool operator&(imageMimeTypeEncoding a, imageMimeTypeEncoding b) { + return (static_cast(a) & static_cast(b)); +} + + +static constexpr struct +{ + const char* name; + int sz; + imageMimeTypeEncoding encoding; +} imageMimeTypes[] = { + {"jpeg", sizeof("jpeg"), imageMimeTypeEncoding::base64}, + {"png", sizeof("png"), imageMimeTypeEncoding::base64}, + {"svg+xml", sizeof("svg+xml"), imageMimeTypeEncoding::base64 | imageMimeTypeEncoding::utf8}, +}; + + +static bool _isValidImageMimeTypeAndEncoding(const char** href, const char** mimetype, imageMimeTypeEncoding* encoding) { + if (strncmp(*href, "image/", sizeof("image/") - 1)) return false; //not allowed mime type + *href += sizeof("image/") - 1; + + //RFC2397 data:[][;base64], + //mediatype := [ type "/" subtype ] *( ";" parameter ) + //parameter := attribute "=" value + for (unsigned int i = 0; i < sizeof(imageMimeTypes) / sizeof(imageMimeTypes[0]); i++) { + if (!strncmp(*href, imageMimeTypes[i].name, imageMimeTypes[i].sz - 1)) { + *href += imageMimeTypes[i].sz - 1; + *mimetype = imageMimeTypes[i].name; + + while (**href && **href != ',') { + while (**href && **href != ';') ++(*href); + if (!**href) return false; + ++(*href); + + if (imageMimeTypes[i].encoding & imageMimeTypeEncoding::base64) { + if (!strncmp(*href, "base64,", sizeof("base64,") - 1)) { + *href += sizeof("base64,") - 1; + *encoding = imageMimeTypeEncoding::base64; + return true; //valid base64 + } + } + if (imageMimeTypes[i].encoding & imageMimeTypeEncoding::utf8) { + if (!strncmp(*href, "utf8,", sizeof("utf8,") - 1)) { + *href += sizeof("utf8,") - 1; + *encoding = imageMimeTypeEncoding::utf8; + return true; //valid utf8 + } + } + } + //no encoding defined + if (**href == ',' && (imageMimeTypes[i].encoding & imageMimeTypeEncoding::utf8)) { + ++(*href); + *encoding = imageMimeTypeEncoding::utf8; + return true; //allow no encoding defined if utf8 expected + } + return false; + } + } + return false; +} + +#include "tvgTaskScheduler.h" + +static unique_ptr _imageBuildHelper(SvgLoaderData& loaderData, SvgNode* node, const Box& vBox, const string& svgPath) +{ + if (!node->node.image.href) return nullptr; + auto picture = Picture::gen(); + + TaskScheduler::async(false); //force to load a picture on the same thread + + const char* href = node->node.image.href; + if (!strncmp(href, "data:", sizeof("data:") - 1)) { + href += sizeof("data:") - 1; + const char* mimetype; + imageMimeTypeEncoding encoding; + if (!_isValidImageMimeTypeAndEncoding(&href, &mimetype, &encoding)) return nullptr; //not allowed mime type or encoding + char *decoded = nullptr; + if (encoding == imageMimeTypeEncoding::base64) { + auto size = b64Decode(href, strlen(href), &decoded); + if (picture->load(decoded, size, mimetype, false) != Result::Success) { + free(decoded); + TaskScheduler::async(true); + return nullptr; + } + } else { + auto size = svgUtilURLDecode(href, &decoded); + if (picture->load(decoded, size, mimetype, false) != Result::Success) { + free(decoded); + TaskScheduler::async(true); + return nullptr; + } + } + loaderData.images.push(decoded); + } else { + if (!strncmp(href, "file://", sizeof("file://") - 1)) href += sizeof("file://") - 1; + //TODO: protect against recursive svg image loading + //Temporarily disable embedded svg: + const char *dot = strrchr(href, '.'); + if (dot && !strcmp(dot, ".svg")) { + TVGLOG("SVG", "Embedded svg file is disabled."); + TaskScheduler::async(true); + return nullptr; + } + string imagePath = href; + if (strncmp(href, "/", 1)) { + auto last = svgPath.find_last_of("/"); + imagePath = svgPath.substr(0, (last == string::npos ? 0 : last + 1)) + imagePath; + } + if (picture->load(imagePath) != Result::Success) { + TaskScheduler::async(true); + return nullptr; + } + } + + TaskScheduler::async(true); + + float w, h; + Matrix m = {1, 0, 0, 0, 1, 0, 0, 0, 1}; + if (picture->size(&w, &h) == Result::Success && w > 0 && h > 0) { + auto sx = node->node.image.w / w; + auto sy = node->node.image.h / h; + m = {sx, 0, node->node.image.x, 0, sy, node->node.image.y, 0, 0, 1}; + } + if (node->transform) m = mathMultiply(node->transform, &m); + picture->transform(m); + + _applyComposition(loaderData, picture.get(), node, vBox, svgPath); + + return picture; +} + + +static Matrix _calculateAspectRatioMatrix(AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, float width, float height, const Box& box) +{ + auto sx = width / box.w; + auto sy = height / box.h; + auto tvx = box.x * sx; + auto tvy = box.y * sy; + + if (align == AspectRatioAlign::None) + return {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1}; + + //Scale + if (meetOrSlice == AspectRatioMeetOrSlice::Meet) { + if (sx < sy) sy = sx; + else sx = sy; + } else { + if (sx < sy) sx = sy; + else sy = sx; + } + + //Align + tvx = box.x * sx; + tvy = box.y * sy; + auto tvw = box.w * sx; + auto tvh = box.h * sy; + + switch (align) { + case AspectRatioAlign::XMinYMin: { + break; + } + case AspectRatioAlign::XMidYMin: { + tvx -= (width - tvw) * 0.5f; + break; + } + case AspectRatioAlign::XMaxYMin: { + tvx -= width - tvw; + break; + } + case AspectRatioAlign::XMinYMid: { + tvy -= (height - tvh) * 0.5f; + break; + } + case AspectRatioAlign::XMidYMid: { + tvx -= (width - tvw) * 0.5f; + tvy -= (height - tvh) * 0.5f; + break; + } + case AspectRatioAlign::XMaxYMid: { + tvx -= width - tvw; + tvy -= (height - tvh) * 0.5f; + break; + } + case AspectRatioAlign::XMinYMax: { + tvy -= height - tvh; + break; + } + case AspectRatioAlign::XMidYMax: { + tvx -= (width - tvw) * 0.5f; + tvy -= height - tvh; + break; + } + case AspectRatioAlign::XMaxYMax: { + tvx -= width - tvw; + tvy -= height - tvh; + break; + } + default: { + break; + } + } + + return {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1}; +} + + +static unique_ptr _useBuildHelper(SvgLoaderData& loaderData, const SvgNode* node, const Box& vBox, const string& svgPath, int depth, bool* isMaskWhite) +{ + unique_ptr finalScene; + auto scene = _sceneBuildHelper(loaderData, node, vBox, svgPath, false, depth + 1, isMaskWhite); + + // mUseTransform = mUseTransform * mTranslate + Matrix mUseTransform = {1, 0, 0, 0, 1, 0, 0, 0, 1}; + if (node->transform) mUseTransform = *node->transform; + if (node->node.use.x != 0.0f || node->node.use.y != 0.0f) { + Matrix mTranslate = {1, 0, node->node.use.x, 0, 1, node->node.use.y, 0, 0, 1}; + mUseTransform = mathMultiply(&mUseTransform, &mTranslate); + } + + if (node->node.use.symbol) { + auto symbol = node->node.use.symbol->node.symbol; + + auto width = (symbol.hasWidth ? symbol.w : vBox.w); + if (node->node.use.isWidthSet) width = node->node.use.w; + auto height = (symbol.hasHeight ? symbol.h : vBox.h);; + if (node->node.use.isHeightSet) height = node->node.use.h; + auto vw = (symbol.hasViewBox ? symbol.vw : width); + auto vh = (symbol.hasViewBox ? symbol.vh : height); + + Matrix mViewBox = {1, 0, 0, 0, 1, 0, 0, 0, 1}; + if ((!mathEqual(width, vw) || !mathEqual(height, vh)) && vw > 0 && vh > 0) { + Box box = {symbol.vx, symbol.vy, vw, vh}; + mViewBox = _calculateAspectRatioMatrix(symbol.align, symbol.meetOrSlice, width, height, box); + } else if (!mathZero(symbol.vx) || !mathZero(symbol.vy)) { + mViewBox = {1, 0, -symbol.vx, 0, 1, -symbol.vy, 0, 0, 1}; + } + + // mSceneTransform = mUseTransform * mSymbolTransform * mViewBox + Matrix mSceneTransform = mViewBox; + if (node->node.use.symbol->transform) { + mSceneTransform = mathMultiply(node->node.use.symbol->transform, &mViewBox); + } + mSceneTransform = mathMultiply(&mUseTransform, &mSceneTransform); + scene->transform(mSceneTransform); + + if (node->node.use.symbol->node.symbol.overflowVisible) { + finalScene = std::move(scene); + } else { + auto viewBoxClip = Shape::gen(); + viewBoxClip->appendRect(0, 0, width, height, 0, 0); + + // mClipTransform = mUseTransform * mSymbolTransform + Matrix mClipTransform = mUseTransform; + if (node->node.use.symbol->transform) { + mClipTransform = mathMultiply(&mUseTransform, node->node.use.symbol->transform); + } + viewBoxClip->transform(mClipTransform); + + auto compositeLayer = Scene::gen(); + compositeLayer->composite(std::move(viewBoxClip), CompositeMethod::ClipPath); + compositeLayer->push(std::move(scene)); + + auto root = Scene::gen(); + root->push(std::move(compositeLayer)); + + finalScene = std::move(root); + } + } else { + scene->transform(mUseTransform); + finalScene = std::move(scene); + } + + return finalScene; +} + + +static unique_ptr _sceneBuildHelper(SvgLoaderData& loaderData, const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, int depth, bool* isMaskWhite) +{ + /* Exception handling: Prevent invalid SVG data input. + The size is the arbitrary value, we need an experimental size. */ + if (depth > 2192) { + TVGERR("SVG", "Infinite recursive call - stopped after %d calls! Svg file may be incorrectly formatted.", depth); + return nullptr; + } + + if (_isGroupType(node->type) || mask) { + auto scene = Scene::gen(); + // For a Symbol node, the viewBox transformation has to be applied first - see _useBuildHelper() + if (!mask && node->transform && node->type != SvgNodeType::Symbol) scene->transform(*node->transform); + + if (node->display && node->style->opacity != 0) { + auto child = node->child.data; + for (uint32_t i = 0; i < node->child.count; ++i, ++child) { + if (_isGroupType((*child)->type)) { + if ((*child)->type == SvgNodeType::Use) + scene->push(_useBuildHelper(loaderData, *child, vBox, svgPath, depth + 1, isMaskWhite)); + else + scene->push(_sceneBuildHelper(loaderData, *child, vBox, svgPath, false, depth + 1, isMaskWhite)); + } else if ((*child)->type == SvgNodeType::Image) { + auto image = _imageBuildHelper(loaderData, *child, vBox, svgPath); + if (image) { + scene->push(std::move(image)); + if (isMaskWhite) *isMaskWhite = false; + } + } else if ((*child)->type != SvgNodeType::Mask) { + auto shape = _shapeBuildHelper(loaderData, *child, vBox, svgPath); + if (shape) { + if (isMaskWhite) { + uint8_t r, g, b; + shape->fillColor(&r, &g, &b); + if (shape->fill() || r < 255 || g < 255 || b < 255 || shape->strokeFill() || + (shape->strokeColor(&r, &g, &b) == Result::Success && (r < 255 || g < 255 || b < 255))) { + *isMaskWhite = false; + } + } + scene->push(std::move(shape)); + } + } + } + _applyComposition(loaderData, scene.get(), node, vBox, svgPath); + scene->opacity(node->style->opacity); + } + return scene; + } + return nullptr; +} + + +static void _updateInvalidViewSize(const Scene* scene, Box& vBox, float& w, float& h, SvgViewFlag viewFlag) +{ + bool validWidth = (viewFlag & SvgViewFlag::Width); + bool validHeight = (viewFlag & SvgViewFlag::Height); + + float x, y; + scene->bounds(&x, &y, &vBox.w, &vBox.h, false); + if (!validWidth && !validHeight) { + vBox.x = x; + vBox.y = y; + } else { + if (validWidth) vBox.w = w; + if (validHeight) vBox.h = h; + } + + //the size would have 1x1 or percentage values. + if (!validWidth) w *= vBox.w; + if (!validHeight) h *= vBox.h; +} + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +unique_ptr svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag) +{ + //TODO: aspect ratio is valid only if viewBox was set + + if (!loaderData.doc || (loaderData.doc->type != SvgNodeType::Doc)) return nullptr; + + auto docNode = _sceneBuildHelper(loaderData, loaderData.doc, vBox, svgPath, false, 0); + + if (!(viewFlag & SvgViewFlag::Viewbox)) _updateInvalidViewSize(docNode.get(), vBox, w, h, viewFlag); + + if (!mathEqual(w, vBox.w) || !mathEqual(h, vBox.h)) { + Matrix m = _calculateAspectRatioMatrix(align, meetOrSlice, w, h, vBox); + docNode->transform(m); + } else if (!mathZero(vBox.x) || !mathZero(vBox.y)) { + docNode->translate(-vBox.x, -vBox.y); + } + + auto viewBoxClip = Shape::gen(); + viewBoxClip->appendRect(0, 0, w, h, 0, 0); + viewBoxClip->fill(0, 0, 0); + + auto compositeLayer = Scene::gen(); + compositeLayer->composite(std::move(viewBoxClip), CompositeMethod::ClipPath); + compositeLayer->push(std::move(docNode)); + + auto root = Scene::gen(); + root->push(std::move(compositeLayer)); + + loaderData.doc->node.doc.vx = vBox.x; + loaderData.doc->node.doc.vy = vBox.y; + loaderData.doc->node.doc.vw = vBox.w; + loaderData.doc->node.doc.vh = vBox.h; + loaderData.doc->node.doc.w = w; + loaderData.doc->node.doc.h = h; + + return root; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgSceneBuilder.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgSceneBuilder.h new file mode 100644 index 000000000..5a401e713 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgSceneBuilder.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_SVG_SCENE_BUILDER_H_ +#define _TVG_SVG_SCENE_BUILDER_H_ + +#include "tvgCommon.h" + +unique_ptr svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag); + +#endif //_TVG_SVG_SCENE_BUILDER_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgUtil.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgUtil.cpp new file mode 100644 index 000000000..3c5da6cac --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgUtil.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include +#include "tvgSvgUtil.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static uint8_t _hexCharToDec(const char c) +{ + if (c >= 'a') return c - 'a' + 10; + else if (c >= 'A') return c - 'A' + 10; + else return c - '0'; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +size_t svgUtilURLDecode(const char *src, char** dst) +{ + if (!src) return 0; + + auto length = strlen(src); + if (length == 0) return 0; + + char* decoded = (char*)malloc(sizeof(char) * length + 1); + decoded[length] = '\0'; + + char a, b; + int idx =0; + while (*src) { + if (*src == '%' && + ((a = src[1]) && (b = src[2])) && + (isxdigit(a) && isxdigit(b))) { + decoded[idx++] = (_hexCharToDec(a) << 4) + _hexCharToDec(b); + src+=3; + } else if (*src == '+') { + decoded[idx++] = ' '; + src++; + } else { + decoded[idx++] = *src++; + } + } + + *dst = decoded; + return length + 1; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgUtil.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgUtil.h new file mode 100644 index 000000000..c32298387 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSvgUtil.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_SVG_UTIL_H_ +#define _TVG_SVG_UTIL_H_ + +#include "tvgCommon.h" + +size_t svgUtilURLDecode(const char *src, char** dst); + +#endif //_TVG_SVG_UTIL_H_ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwCanvas.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwCanvas.cpp new file mode 100644 index 000000000..b53fe26ed --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwCanvas.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgCanvas.h" + +#ifdef THORVG_SW_RASTER_SUPPORT + #include "tvgSwRenderer.h" +#else + class SwRenderer : public RenderMethod + { + //Non Supported. Dummy Class */ + }; +#endif + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +struct SwCanvas::Impl +{ +}; + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +#ifdef THORVG_SW_RASTER_SUPPORT +SwCanvas::SwCanvas() : Canvas(SwRenderer::gen()), pImpl(new Impl) +#else +SwCanvas::SwCanvas() : Canvas(nullptr), pImpl(new Impl) +#endif +{ +} + + +SwCanvas::~SwCanvas() +{ + delete(pImpl); +} + + +Result SwCanvas::mempool(MempoolPolicy policy) noexcept +{ +#ifdef THORVG_SW_RASTER_SUPPORT + //We know renderer type, avoid dynamic_cast for performance. + auto renderer = static_cast(Canvas::pImpl->renderer); + if (!renderer) return Result::MemoryCorruption; + + //It can't change the policy during the running. + if (!Canvas::pImpl->paints.empty()) return Result::InsufficientCondition; + + if (policy == MempoolPolicy::Individual) renderer->mempool(false); + else renderer->mempool(true); + + return Result::Success; +#endif + return Result::NonSupport; +} + + +Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Colorspace cs) noexcept +{ +#ifdef THORVG_SW_RASTER_SUPPORT + //We know renderer type, avoid dynamic_cast for performance. + auto renderer = static_cast(Canvas::pImpl->renderer); + if (!renderer) return Result::MemoryCorruption; + + if (!renderer->target(buffer, stride, w, h, static_cast(cs))) return Result::InvalidArguments; + + //Paints must be updated again with this new target. + Canvas::pImpl->needRefresh(); + + return Result::Success; +#endif + return Result::NonSupport; +} + + +unique_ptr SwCanvas::gen() noexcept +{ +#ifdef THORVG_SW_RASTER_SUPPORT + if (SwRenderer::init() <= 0) return nullptr; + return unique_ptr(new SwCanvas); +#endif + return nullptr; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwCommon.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwCommon.h new file mode 100644 index 000000000..591b1c96f --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwCommon.h @@ -0,0 +1,580 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_SW_COMMON_H_ +#define _TVG_SW_COMMON_H_ + +#include "tvgCommon.h" +#include "tvgRender.h" + +#include + +#if 0 +#include +static double timeStamp() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (tv.tv_sec + tv.tv_usec / 1000000.0); +} +#endif + +#define SW_CURVE_TYPE_POINT 0 +#define SW_CURVE_TYPE_CUBIC 1 +#define SW_ANGLE_PI (180L << 16) +#define SW_ANGLE_2PI (SW_ANGLE_PI << 1) +#define SW_ANGLE_PI2 (SW_ANGLE_PI >> 1) + +using SwCoord = signed long; +using SwFixed = signed long long; + + +static inline float TO_FLOAT(SwCoord val) +{ + return static_cast(val) / 64.0f; +} + +struct SwPoint +{ + SwCoord x, y; + + SwPoint& operator+=(const SwPoint& rhs) + { + x += rhs.x; + y += rhs.y; + return *this; + } + + SwPoint operator+(const SwPoint& rhs) const + { + return {x + rhs.x, y + rhs.y}; + } + + SwPoint operator-(const SwPoint& rhs) const + { + return {x - rhs.x, y - rhs.y}; + } + + bool operator==(const SwPoint& rhs) const + { + return (x == rhs.x && y == rhs.y); + } + + bool operator!=(const SwPoint& rhs) const + { + return (x != rhs.x || y != rhs.y); + } + + bool zero() const + { + if (x == 0 && y == 0) return true; + else return false; + } + + bool small() const + { + //2 is epsilon... + if (abs(x) < 2 && abs(y) < 2) return true; + else return false; + } + + Point toPoint() const + { + return {TO_FLOAT(x), TO_FLOAT(y)}; + } +}; + +struct SwSize +{ + SwCoord w, h; +}; + +struct SwOutline +{ + Array pts; //the outline's points + Array cntrs; //the contour end points + Array types; //curve type + Array closed; //opened or closed path? + FillRule fillRule; +}; + +struct SwSpan +{ + uint16_t x, y; + uint16_t len; + uint8_t coverage; +}; + +struct SwRleData +{ + SwSpan *spans; + uint32_t alloc; + uint32_t size; +}; + +struct SwBBox +{ + SwPoint min, max; + + void reset() + { + min.x = min.y = max.x = max.y = 0; + } +}; + +struct SwFill +{ + struct SwLinear { + float dx, dy; + float len; + float offset; + }; + + struct SwRadial { + float a11, a12, a13; + float a21, a22, a23; + float fx, fy, fr; + float dx, dy, dr; + float invA, a; + }; + + union { + SwLinear linear; + SwRadial radial; + }; + + uint32_t* ctable; + FillSpread spread; + + bool translucent; +}; + +struct SwStrokeBorder +{ + uint32_t ptsCnt; + uint32_t maxPts; + SwPoint* pts; + uint8_t* tags; + int32_t start; //index of current sub-path start point + bool movable; //true: for ends of lineto borders +}; + +struct SwStroke +{ + SwFixed angleIn; + SwFixed angleOut; + SwPoint center; + SwFixed lineLength; + SwFixed subPathAngle; + SwPoint ptStartSubPath; + SwFixed subPathLineLength; + SwFixed width; + SwFixed miterlimit; + + StrokeCap cap; + StrokeJoin join; + StrokeJoin joinSaved; + SwFill* fill = nullptr; + + SwStrokeBorder borders[2]; + + float sx, sy; + + bool firstPt; + bool closedSubPath; + bool handleWideStrokes; +}; + +struct SwDashStroke +{ + SwOutline* outline = nullptr; + float curLen = 0; + int32_t curIdx = 0; + Point ptStart = {0, 0}; + Point ptCur = {0, 0}; + float* pattern = nullptr; + uint32_t cnt = 0; + bool curOpGap = false; + bool move = true; +}; + +struct SwShape +{ + SwOutline* outline = nullptr; + SwStroke* stroke = nullptr; + SwFill* fill = nullptr; + SwRleData* rle = nullptr; + SwRleData* strokeRle = nullptr; + SwBBox bbox; //Keep it boundary without stroke region. Using for optimal filling. + + bool fastTrack = false; //Fast Track: axis-aligned rectangle without any clips? +}; + +struct SwImage +{ + SwOutline* outline = nullptr; + SwRleData* rle = nullptr; + union { + pixel_t* data; //system based data pointer + uint32_t* buf32; //for explicit 32bits channels + uint8_t* buf8; //for explicit 8bits grayscale + }; + uint32_t w, h, stride; + int32_t ox = 0; //offset x + int32_t oy = 0; //offset y + float scale; + uint8_t channelSize; + + bool direct = false; //draw image directly (with offset) + bool scaled = false; //draw scaled image +}; + +typedef uint8_t(*SwMask)(uint8_t s, uint8_t d, uint8_t a); //src, dst, alpha +typedef uint32_t(*SwBlender)(uint32_t s, uint32_t d, uint8_t a); //src, dst, alpha +typedef uint32_t(*SwJoin)(uint8_t r, uint8_t g, uint8_t b, uint8_t a); //color channel join +typedef uint8_t(*SwAlpha)(uint8_t*); //blending alpha + +struct SwCompositor; + +struct SwSurface : Surface +{ + SwJoin join; + SwAlpha alphas[4]; //Alpha:2, InvAlpha:3, Luma:4, InvLuma:5 + SwBlender blender = nullptr; //blender (optional) + SwCompositor* compositor = nullptr; //compositor (optional) + BlendMethod blendMethod; //blending method (uint8_t) + + SwAlpha alpha(CompositeMethod method) + { + auto idx = (int)(method) - 2; //0: None, 1: ClipPath + return alphas[idx > 3 ? 0 : idx]; //CompositeMethod has only four Matting methods. + } +}; + +struct SwCompositor : Compositor +{ + SwSurface* recoverSfc; //Recover surface when composition is started + SwCompositor* recoverCmp; //Recover compositor when composition is done + SwImage image; + SwBBox bbox; + bool valid; +}; + +struct SwMpool +{ + SwOutline* outline; + SwOutline* strokeOutline; + SwOutline* dashOutline; + unsigned allocSize; +}; + +static inline SwCoord TO_SWCOORD(float val) +{ + return SwCoord(val * 64.0f); +} + +static inline uint32_t JOIN(uint8_t c0, uint8_t c1, uint8_t c2, uint8_t c3) +{ + return (c0 << 24 | c1 << 16 | c2 << 8 | c3); +} + +static inline uint32_t ALPHA_BLEND(uint32_t c, uint32_t a) +{ + return (((((c >> 8) & 0x00ff00ff) * a + 0x00ff00ff) & 0xff00ff00) + + ((((c & 0x00ff00ff) * a + 0x00ff00ff) >> 8) & 0x00ff00ff)); +} + +static inline uint32_t INTERPOLATE(uint32_t s, uint32_t d, uint8_t a) +{ + return (((((((s >> 8) & 0xff00ff) - ((d >> 8) & 0xff00ff)) * a) + (d & 0xff00ff00)) & 0xff00ff00) + ((((((s & 0xff00ff) - (d & 0xff00ff)) * a) >> 8) + (d & 0xff00ff)) & 0xff00ff)); +} + +static inline uint8_t INTERPOLATE8(uint8_t s, uint8_t d, uint8_t a) +{ + return (((s) * (a) + 0xff) >> 8) + (((d) * ~(a) + 0xff) >> 8); +} + +static inline SwCoord HALF_STROKE(float width) +{ + return TO_SWCOORD(width * 0.5f); +} + +static inline uint8_t A(uint32_t c) +{ + return ((c) >> 24); +} + +static inline uint8_t IA(uint32_t c) +{ + return (~(c) >> 24); +} + +static inline uint8_t C1(uint32_t c) +{ + return ((c) >> 16); +} + +static inline uint8_t C2(uint32_t c) +{ + return ((c) >> 8); +} + +static inline uint8_t C3(uint32_t c) +{ + return (c); +} + +static inline uint32_t opBlendInterp(uint32_t s, uint32_t d, uint8_t a) +{ + return INTERPOLATE(s, d, a); +} + +static inline uint32_t opBlendNormal(uint32_t s, uint32_t d, uint8_t a) +{ + auto t = ALPHA_BLEND(s, a); + return t + ALPHA_BLEND(d, IA(t)); +} + +static inline uint32_t opBlendPreNormal(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) +{ + return s + ALPHA_BLEND(d, IA(s)); +} + +static inline uint32_t opBlendSrcOver(uint32_t s, TVG_UNUSED uint32_t d, TVG_UNUSED uint8_t a) +{ + return s; +} + +//TODO: BlendMethod could remove the alpha parameter. +static inline uint32_t opBlendDifference(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) +{ + //if (s > d) => s - d + //else => d - s + auto c1 = (C1(s) > C1(d)) ? (C1(s) - C1(d)) : (C1(d) - C1(s)); + auto c2 = (C2(s) > C2(d)) ? (C2(s) - C2(d)) : (C2(d) - C2(s)); + auto c3 = (C3(s) > C3(d)) ? (C3(s) - C3(d)) : (C3(d) - C3(s)); + return JOIN(255, c1, c2, c3); +} + +static inline uint32_t opBlendExclusion(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) +{ + //A + B - 2AB + auto c1 = std::min(255, C1(s) + C1(d) - std::min(255, (C1(s) * C1(d)) << 1)); + auto c2 = std::min(255, C2(s) + C2(d) - std::min(255, (C2(s) * C2(d)) << 1)); + auto c3 = std::min(255, C3(s) + C3(d) - std::min(255, (C3(s) * C3(d)) << 1)); + return JOIN(255, c1, c2, c3); +} + +static inline uint32_t opBlendAdd(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) +{ + // s + d + auto c1 = std::min(C1(s) + C1(d), 255); + auto c2 = std::min(C2(s) + C2(d), 255); + auto c3 = std::min(C3(s) + C3(d), 255); + return JOIN(255, c1, c2, c3); +} + +static inline uint32_t opBlendScreen(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) +{ + // s + d - s * d + auto c1 = C1(s) + C1(d) - MULTIPLY(C1(s), C1(d)); + auto c2 = C2(s) + C2(d) - MULTIPLY(C2(s), C2(d)); + auto c3 = C3(s) + C3(d) - MULTIPLY(C3(s), C3(d)); + return JOIN(255, c1, c2, c3); +} + + +static inline uint32_t opBlendMultiply(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) +{ + // s * d + auto c1 = MULTIPLY(C1(s), C1(d)); + auto c2 = MULTIPLY(C2(s), C2(d)); + auto c3 = MULTIPLY(C3(s), C3(d)); + return JOIN(255, c1, c2, c3); +} + + +static inline uint32_t opBlendOverlay(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) +{ + // if (2 * d < da) => 2 * s * d, + // else => 1 - 2 * (1 - s) * (1 - d) + auto c1 = (C1(d) < 128) ? std::min(255, 2 * MULTIPLY(C1(s), C1(d))) : (255 - std::min(255, 2 * MULTIPLY(255 - C1(s), 255 - C1(d)))); + auto c2 = (C2(d) < 128) ? std::min(255, 2 * MULTIPLY(C2(s), C2(d))) : (255 - std::min(255, 2 * MULTIPLY(255 - C2(s), 255 - C2(d)))); + auto c3 = (C3(d) < 128) ? std::min(255, 2 * MULTIPLY(C3(s), C3(d))) : (255 - std::min(255, 2 * MULTIPLY(255 - C3(s), 255 - C3(d)))); + return JOIN(255, c1, c2, c3); +} + +static inline uint32_t opBlendDarken(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) +{ + // min(s, d) + auto c1 = std::min(C1(s), C1(d)); + auto c2 = std::min(C2(s), C2(d)); + auto c3 = std::min(C3(s), C3(d)); + return JOIN(255, c1, c2, c3); +} + +static inline uint32_t opBlendLighten(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) +{ + // max(s, d) + auto c1 = std::max(C1(s), C1(d)); + auto c2 = std::max(C2(s), C2(d)); + auto c3 = std::max(C3(s), C3(d)); + return JOIN(255, c1, c2, c3); +} + +static inline uint32_t opBlendColorDodge(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) +{ + // d / (1 - s) + auto is = 0xffffffff - s; + auto c1 = (C1(is) > 0) ? (C1(d) / C1(is)) : C1(d); + auto c2 = (C2(is) > 0) ? (C2(d) / C2(is)) : C2(d); + auto c3 = (C3(is) > 0) ? (C3(d) / C3(is)) : C3(d); + return JOIN(255, c1, c2, c3); +} + +static inline uint32_t opBlendColorBurn(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) +{ + // 1 - (1 - d) / s + auto id = 0xffffffff - d; + auto c1 = 255 - ((C1(s) > 0) ? (C1(id) / C1(s)) : C1(id)); + auto c2 = 255 - ((C2(s) > 0) ? (C2(id) / C2(s)) : C2(id)); + auto c3 = 255 - ((C3(s) > 0) ? (C3(id) / C3(s)) : C3(id)); + return JOIN(255, c1, c2, c3); +} + +static inline uint32_t opBlendHardLight(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) +{ + auto c1 = (C1(s) < 128) ? std::min(255, 2 * MULTIPLY(C1(s), C1(d))) : (255 - std::min(255, 2 * MULTIPLY(255 - C1(s), 255 - C1(d)))); + auto c2 = (C2(s) < 128) ? std::min(255, 2 * MULTIPLY(C2(s), C2(d))) : (255 - std::min(255, 2 * MULTIPLY(255 - C2(s), 255 - C2(d)))); + auto c3 = (C3(s) < 128) ? std::min(255, 2 * MULTIPLY(C3(s), C3(d))) : (255 - std::min(255, 2 * MULTIPLY(255 - C3(s), 255 - C3(d)))); + return JOIN(255, c1, c2, c3); +} + +static inline uint32_t opBlendSoftLight(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) +{ + //(255 - 2 * s) * (d * d) + (2 * s * b) + auto c1 = std::min(255, MULTIPLY(255 - std::min(255, 2 * C1(s)), MULTIPLY(C1(d), C1(d))) + 2 * MULTIPLY(C1(s), C1(d))); + auto c2 = std::min(255, MULTIPLY(255 - std::min(255, 2 * C2(s)), MULTIPLY(C2(d), C2(d))) + 2 * MULTIPLY(C2(s), C2(d))); + auto c3 = std::min(255, MULTIPLY(255 - std::min(255, 2 * C3(s)), MULTIPLY(C3(d), C3(d))) + 2 * MULTIPLY(C3(s), C3(d))); + return JOIN(255, c1, c2, c3); +} + + +int64_t mathMultiply(int64_t a, int64_t b); +int64_t mathDivide(int64_t a, int64_t b); +int64_t mathMulDiv(int64_t a, int64_t b, int64_t c); +void mathRotate(SwPoint& pt, SwFixed angle); +SwFixed mathTan(SwFixed angle); +SwFixed mathAtan(const SwPoint& pt); +SwFixed mathCos(SwFixed angle); +SwFixed mathSin(SwFixed angle); +void mathSplitCubic(SwPoint* base); +SwFixed mathDiff(SwFixed angle1, SwFixed angle2); +SwFixed mathLength(const SwPoint& pt); +bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut); +SwFixed mathMean(SwFixed angle1, SwFixed angle2); +SwPoint mathTransform(const Point* to, const Matrix* transform); +bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, SwBBox& renderRegion, bool fastTrack); +bool mathClipBBox(const SwBBox& clipper, SwBBox& clipee); + +void shapeReset(SwShape* shape); +bool shapePrepare(SwShape* shape, const RenderShape* rshape, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite); +bool shapePrepared(const SwShape* shape); +bool shapeGenRle(SwShape* shape, const RenderShape* rshape, bool antiAlias); +void shapeDelOutline(SwShape* shape, SwMpool* mpool, uint32_t tid); +void shapeResetStroke(SwShape* shape, const RenderShape* rshape, const Matrix* transform); +bool shapeGenStrokeRle(SwShape* shape, const RenderShape* rshape, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid); +void shapeFree(SwShape* shape); +void shapeDelStroke(SwShape* shape); +bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint8_t opacity, bool ctable); +bool shapeGenStrokeFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint8_t opacity, bool ctable); +void shapeResetFill(SwShape* shape); +void shapeResetStrokeFill(SwShape* shape); +void shapeDelFill(SwShape* shape); +void shapeDelStrokeFill(SwShape* shape); + +void strokeReset(SwStroke* stroke, const RenderShape* shape, const Matrix* transform); +bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline); +SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid); +void strokeFree(SwStroke* stroke); + +bool imagePrepare(SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid); +bool imageGenRle(SwImage* image, const SwBBox& renderRegion, bool antiAlias); +void imageDelOutline(SwImage* image, SwMpool* mpool, uint32_t tid); +void imageReset(SwImage* image); +void imageFree(SwImage* image); + +bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, SwSurface* surface, uint8_t opacity, bool ctable); +void fillReset(SwFill* fill); +void fillFree(SwFill* fill); + +//OPTIMIZE_ME: Skip the function pointer access +void fillLinear(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask maskOp, uint8_t opacity); //composite masking ver. +void fillLinear(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask maskOp, uint8_t opacity); //direct masking ver. +void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a); //blending ver. +void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a); //blending + BlendingMethod(op2) ver. +void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity); //matting ver. + +void fillRadial(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask op, uint8_t a); //composite masking ver. +void fillRadial(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask op, uint8_t a) ; //direct masking ver. +void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a); //blending ver. +void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a); //blending + BlendingMethod(op2) ver. +void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity); //matting ver. + +SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& renderRegion, bool antiAlias); +SwRleData* rleRender(const SwBBox* bbox); +void rleFree(SwRleData* rle); +void rleReset(SwRleData* rle); +void rleMerge(SwRleData* rle, SwRleData* clip1, SwRleData* clip2); +void rleClipPath(SwRleData* rle, const SwRleData* clip); +void rleClipRect(SwRleData* rle, const SwBBox* clip); + +SwMpool* mpoolInit(uint32_t threads); +bool mpoolTerm(SwMpool* mpool); +bool mpoolClear(SwMpool* mpool); +SwOutline* mpoolReqOutline(SwMpool* mpool, unsigned idx); +void mpoolRetOutline(SwMpool* mpool, unsigned idx); +SwOutline* mpoolReqStrokeOutline(SwMpool* mpool, unsigned idx); +void mpoolRetStrokeOutline(SwMpool* mpool, unsigned idx); +SwOutline* mpoolReqDashOutline(SwMpool* mpool, unsigned idx); +void mpoolRetDashOutline(SwMpool* mpool, unsigned idx); + +bool rasterCompositor(SwSurface* surface); +bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id); +bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); +bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& bbox, uint8_t opacity); +bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); +bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id); +bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h); +void rasterPixel32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len); +void rasterGrayscale8(uint8_t *dst, uint8_t val, uint32_t offset, int32_t len); +void rasterUnpremultiply(Surface* surface); +void rasterPremultiply(Surface* surface); +bool rasterConvertCS(Surface* surface, ColorSpace to); + +#endif /* _TVG_SW_COMMON_H_ */ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwFill.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwFill.cpp new file mode 100644 index 000000000..c4a697d35 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwFill.cpp @@ -0,0 +1,785 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgMath.h" +#include "tvgSwCommon.h" +#include "tvgFill.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +#define RADIAL_A_THRESHOLD 0.0005f +#define GRADIENT_STOP_SIZE 1024 +#define FIXPT_BITS 8 +#define FIXPT_SIZE (1<radial.a + * B = 2 * (dr * fr + rx * dx + ry * dy) + * C = fr^2 - rx^2 - ry^2 + * Derivatives are computed with respect to dx. + * This procedure aims to optimize and eliminate the need to calculate all values from the beginning + * for consecutive x values with a constant y. The Taylor series expansions are computed as long as + * its terms are non-zero. + */ +static void _calculateCoefficients(const SwFill* fill, uint32_t x, uint32_t y, float& b, float& deltaB, float& det, float& deltaDet, float& deltaDeltaDet) +{ + auto radial = &fill->radial; + + auto rx = (x + 0.5f) * radial->a11 + (y + 0.5f) * radial->a12 + radial->a13 - radial->fx; + auto ry = (x + 0.5f) * radial->a21 + (y + 0.5f) * radial->a22 + radial->a23 - radial->fy; + + b = (radial->dr * radial->fr + rx * radial->dx + ry * radial->dy) * radial->invA; + deltaB = (radial->a11 * radial->dx + radial->a21 * radial->dy) * radial->invA; + + auto rr = rx * rx + ry * ry; + auto deltaRr = 2.0f * (rx * radial->a11 + ry * radial->a21) * radial->invA; + auto deltaDeltaRr = 2.0f * (radial->a11 * radial->a11 + radial->a21 * radial->a21) * radial->invA; + + det = b * b + (rr - radial->fr * radial->fr) * radial->invA; + deltaDet = 2.0f * b * deltaB + deltaB * deltaB + deltaRr + deltaDeltaRr; + deltaDeltaDet = 2.0f * deltaB * deltaB + deltaDeltaRr; +} + + +static bool _updateColorTable(SwFill* fill, const Fill* fdata, const SwSurface* surface, uint8_t opacity) +{ + if (!fill->ctable) { + fill->ctable = static_cast(malloc(GRADIENT_STOP_SIZE * sizeof(uint32_t))); + if (!fill->ctable) return false; + } + + const Fill::ColorStop* colors; + auto cnt = fdata->colorStops(&colors); + if (cnt == 0 || !colors) return false; + + auto pColors = colors; + + auto a = MULTIPLY(pColors->a, opacity); + if (a < 255) fill->translucent = true; + + auto r = pColors->r; + auto g = pColors->g; + auto b = pColors->b; + auto rgba = surface->join(r, g, b, a); + + auto inc = 1.0f / static_cast(GRADIENT_STOP_SIZE); + auto pos = 1.5f * inc; + uint32_t i = 0; + + fill->ctable[i++] = ALPHA_BLEND(rgba | 0xff000000, a); + + while (pos <= pColors->offset) { + fill->ctable[i] = fill->ctable[i - 1]; + ++i; + pos += inc; + } + + for (uint32_t j = 0; j < cnt - 1; ++j) { + auto curr = colors + j; + auto next = curr + 1; + auto delta = 1.0f / (next->offset - curr->offset); + auto a2 = MULTIPLY(next->a, opacity); + if (!fill->translucent && a2 < 255) fill->translucent = true; + + auto rgba2 = surface->join(next->r, next->g, next->b, a2); + + while (pos < next->offset && i < GRADIENT_STOP_SIZE) { + auto t = (pos - curr->offset) * delta; + auto dist = static_cast(255 * t); + auto dist2 = 255 - dist; + + auto color = INTERPOLATE(rgba, rgba2, dist2); + fill->ctable[i] = ALPHA_BLEND((color | 0xff000000), (color >> 24)); + + ++i; + pos += inc; + } + rgba = rgba2; + a = a2; + } + rgba = ALPHA_BLEND((rgba | 0xff000000), a); + + for (; i < GRADIENT_STOP_SIZE; ++i) + fill->ctable[i] = rgba; + + //Make sure the last color stop is represented at the end of the table + fill->ctable[GRADIENT_STOP_SIZE - 1] = rgba; + + return true; +} + + +bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const Matrix* transform) +{ + float x1, x2, y1, y2; + if (linear->linear(&x1, &y1, &x2, &y2) != Result::Success) return false; + + fill->linear.dx = x2 - x1; + fill->linear.dy = y2 - y1; + fill->linear.len = fill->linear.dx * fill->linear.dx + fill->linear.dy * fill->linear.dy; + + if (fill->linear.len < FLT_EPSILON) return true; + + fill->linear.dx /= fill->linear.len; + fill->linear.dy /= fill->linear.len; + fill->linear.offset = -fill->linear.dx * x1 - fill->linear.dy * y1; + + auto gradTransform = linear->transform(); + bool isTransformation = !mathIdentity((const Matrix*)(&gradTransform)); + + if (isTransformation) { + if (transform) gradTransform = mathMultiply(transform, &gradTransform); + } else if (transform) { + gradTransform = *transform; + isTransformation = true; + } + + if (isTransformation) { + Matrix invTransform; + if (!mathInverse(&gradTransform, &invTransform)) return false; + + fill->linear.offset += fill->linear.dx * invTransform.e13 + fill->linear.dy * invTransform.e23; + + auto dx = fill->linear.dx; + fill->linear.dx = dx * invTransform.e11 + fill->linear.dy * invTransform.e21; + fill->linear.dy = dx * invTransform.e12 + fill->linear.dy * invTransform.e22; + + fill->linear.len = fill->linear.dx * fill->linear.dx + fill->linear.dy * fill->linear.dy; + if (fill->linear.len < FLT_EPSILON) return true; + } + + return true; +} + + +bool _prepareRadial(SwFill* fill, const RadialGradient* radial, const Matrix* transform) +{ + auto cx = P(radial)->cx; + auto cy = P(radial)->cy; + auto r = P(radial)->r; + auto fx = P(radial)->fx; + auto fy = P(radial)->fy; + auto fr = P(radial)->fr; + + if (r < FLT_EPSILON) return true; + + fill->radial.dr = r - fr; + fill->radial.dx = cx - fx; + fill->radial.dy = cy - fy; + fill->radial.fr = fr; + fill->radial.fx = fx; + fill->radial.fy = fy; + fill->radial.a = fill->radial.dr * fill->radial.dr - fill->radial.dx * fill->radial.dx - fill->radial.dy * fill->radial.dy; + + //This condition fulfills the SVG 1.1 std: + //the focal point, if outside the end circle, is moved to be on the end circle + //See: the SVG 2 std requirements: https://www.w3.org/TR/SVG2/pservers.html#RadialGradientNotes + if (fill->radial.a < 0) { + auto dist = sqrtf(fill->radial.dx * fill->radial.dx + fill->radial.dy * fill->radial.dy); + fill->radial.fx = cx + r * (fx - cx) / dist; + fill->radial.fy = cy + r * (fy - cy) / dist; + fill->radial.dx = cx - fill->radial.fx; + fill->radial.dy = cy - fill->radial.fy; + fill->radial.a = fill->radial.dr * fill->radial.dr - fill->radial.dx * fill->radial.dx - fill->radial.dy * fill->radial.dy; + } + + if (fill->radial.a > 0) fill->radial.invA = 1.0f / fill->radial.a; + + auto gradTransform = radial->transform(); + bool isTransformation = !mathIdentity((const Matrix*)(&gradTransform)); + + if (transform) { + if (isTransformation) gradTransform = mathMultiply(transform, &gradTransform); + else { + gradTransform = *transform; + isTransformation = true; + } + } + + if (isTransformation) { + Matrix invTransform; + if (!mathInverse(&gradTransform, &invTransform)) return false; + fill->radial.a11 = invTransform.e11; + fill->radial.a12 = invTransform.e12; + fill->radial.a13 = invTransform.e13; + fill->radial.a21 = invTransform.e21; + fill->radial.a22 = invTransform.e22; + fill->radial.a23 = invTransform.e23; + } else { + fill->radial.a11 = fill->radial.a22 = 1.0f; + fill->radial.a12 = fill->radial.a13 = 0.0f; + fill->radial.a21 = fill->radial.a23 = 0.0f; + } + return true; +} + + +static inline uint32_t _clamp(const SwFill* fill, int32_t pos) +{ + switch (fill->spread) { + case FillSpread::Pad: { + if (pos >= GRADIENT_STOP_SIZE) pos = GRADIENT_STOP_SIZE - 1; + else if (pos < 0) pos = 0; + break; + } + case FillSpread::Repeat: { + pos = pos % GRADIENT_STOP_SIZE; + if (pos < 0) pos = GRADIENT_STOP_SIZE + pos; + break; + } + case FillSpread::Reflect: { + auto limit = GRADIENT_STOP_SIZE * 2; + pos = pos % limit; + if (pos < 0) pos = limit + pos; + if (pos >= GRADIENT_STOP_SIZE) pos = (limit - pos - 1); + break; + } + } + return pos; +} + + +static inline uint32_t _fixedPixel(const SwFill* fill, int32_t pos) +{ + int32_t i = (pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS; + return fill->ctable[_clamp(fill, i)]; +} + + +static inline uint32_t _pixel(const SwFill* fill, float pos) +{ + auto i = static_cast(pos * (GRADIENT_STOP_SIZE - 1) + 0.5f); + return fill->ctable[_clamp(fill, i)]; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + + +void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity) +{ + //edge case + if (fill->radial.a < RADIAL_A_THRESHOLD) { + auto radial = &fill->radial; + auto rx = (x + 0.5f) * radial->a11 + (y + 0.5f) * radial->a12 + radial->a13 - radial->fx; + auto ry = (x + 0.5f) * radial->a21 + (y + 0.5f) * radial->a22 + radial->a23 - radial->fy; + + if (opacity == 255) { + for (uint32_t i = 0 ; i < len ; ++i, ++dst, cmp += csize) { + auto x0 = 0.5f * (rx * rx + ry * ry - radial->fr * radial->fr) / (radial->dr * radial->fr + rx * radial->dx + ry * radial->dy); + *dst = opBlendNormal(_pixel(fill, x0), *dst, alpha(cmp)); + rx += radial->a11; + ry += radial->a21; + } + } else { + for (uint32_t i = 0 ; i < len ; ++i, ++dst, cmp += csize) { + auto x0 = 0.5f * (rx * rx + ry * ry - radial->fr * radial->fr) / (radial->dr * radial->fr + rx * radial->dx + ry * radial->dy); + *dst = opBlendNormal(_pixel(fill, x0), *dst, MULTIPLY(opacity, alpha(cmp))); + rx += radial->a11; + ry += radial->a21; + } + } + } else { + float b, deltaB, det, deltaDet, deltaDeltaDet; + _calculateCoefficients(fill, x, y, b, deltaB, det, deltaDet, deltaDeltaDet); + + if (opacity == 255) { + for (uint32_t i = 0 ; i < len ; ++i, ++dst, cmp += csize) { + *dst = opBlendNormal(_pixel(fill, sqrtf(det) - b), *dst, alpha(cmp)); + det += deltaDet; + deltaDet += deltaDeltaDet; + b += deltaB; + } + } else { + for (uint32_t i = 0 ; i < len ; ++i, ++dst, cmp += csize) { + *dst = opBlendNormal(_pixel(fill, sqrtf(det) - b), *dst, MULTIPLY(opacity, alpha(cmp))); + det += deltaDet; + deltaDet += deltaDeltaDet; + b += deltaB; + } + } + } +} + + +void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a) +{ + if (fill->radial.a < RADIAL_A_THRESHOLD) { + auto radial = &fill->radial; + auto rx = (x + 0.5f) * radial->a11 + (y + 0.5f) * radial->a12 + radial->a13 - radial->fx; + auto ry = (x + 0.5f) * radial->a21 + (y + 0.5f) * radial->a22 + radial->a23 - radial->fy; + for (uint32_t i = 0; i < len; ++i, ++dst) { + auto x0 = 0.5f * (rx * rx + ry * ry - radial->fr * radial->fr) / (radial->dr * radial->fr + rx * radial->dx + ry * radial->dy); + *dst = op(_pixel(fill, x0), *dst, a); + rx += radial->a11; + ry += radial->a21; + } + } else { + float b, deltaB, det, deltaDet, deltaDeltaDet; + _calculateCoefficients(fill, x, y, b, deltaB, det, deltaDet, deltaDeltaDet); + + for (uint32_t i = 0; i < len; ++i, ++dst) { + *dst = op(_pixel(fill, sqrtf(det) - b), *dst, a); + det += deltaDet; + deltaDet += deltaDeltaDet; + b += deltaB; + } + } +} + + +void fillRadial(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask maskOp, uint8_t a) +{ + if (fill->radial.a < RADIAL_A_THRESHOLD) { + auto radial = &fill->radial; + auto rx = (x + 0.5f) * radial->a11 + (y + 0.5f) * radial->a12 + radial->a13 - radial->fx; + auto ry = (x + 0.5f) * radial->a21 + (y + 0.5f) * radial->a22 + radial->a23 - radial->fy; + for (uint32_t i = 0 ; i < len ; ++i, ++dst) { + auto x0 = 0.5f * (rx * rx + ry * ry - radial->fr * radial->fr) / (radial->dr * radial->fr + rx * radial->dx + ry * radial->dy); + auto src = MULTIPLY(a, A(_pixel(fill, x0))); + *dst = maskOp(src, *dst, ~src); + rx += radial->a11; + ry += radial->a21; + } + } else { + float b, deltaB, det, deltaDet, deltaDeltaDet; + _calculateCoefficients(fill, x, y, b, deltaB, det, deltaDet, deltaDeltaDet); + + for (uint32_t i = 0 ; i < len ; ++i, ++dst) { + auto src = MULTIPLY(a, A(_pixel(fill, sqrtf(det) - b))); + *dst = maskOp(src, *dst, ~src); + det += deltaDet; + deltaDet += deltaDeltaDet; + b += deltaB; + } + } +} + + +void fillRadial(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask maskOp, uint8_t a) +{ + if (fill->radial.a < RADIAL_A_THRESHOLD) { + auto radial = &fill->radial; + auto rx = (x + 0.5f) * radial->a11 + (y + 0.5f) * radial->a12 + radial->a13 - radial->fx; + auto ry = (x + 0.5f) * radial->a21 + (y + 0.5f) * radial->a22 + radial->a23 - radial->fy; + for (uint32_t i = 0 ; i < len ; ++i, ++dst, ++cmp) { + auto x0 = 0.5f * (rx * rx + ry * ry - radial->fr * radial->fr) / (radial->dr * radial->fr + rx * radial->dx + ry * radial->dy); + auto src = MULTIPLY(A(A(_pixel(fill, x0))), a); + auto tmp = maskOp(src, *cmp, 0); + *dst = tmp + MULTIPLY(*dst, ~tmp); + rx += radial->a11; + ry += radial->a21; + } + } else { + float b, deltaB, det, deltaDet, deltaDeltaDet; + _calculateCoefficients(fill, x, y, b, deltaB, det, deltaDet, deltaDeltaDet); + + for (uint32_t i = 0 ; i < len ; ++i, ++dst, ++cmp) { + auto src = MULTIPLY(A(_pixel(fill, sqrtf(det))), a); + auto tmp = maskOp(src, *cmp, 0); + *dst = tmp + MULTIPLY(*dst, ~tmp); + deltaDet += deltaDeltaDet; + b += deltaB; + } + } +} + + +void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a) +{ + if (fill->radial.a < RADIAL_A_THRESHOLD) { + auto radial = &fill->radial; + auto rx = (x + 0.5f) * radial->a11 + (y + 0.5f) * radial->a12 + radial->a13 - radial->fx; + auto ry = (x + 0.5f) * radial->a21 + (y + 0.5f) * radial->a22 + radial->a23 - radial->fy; + + if (a == 255) { + for (uint32_t i = 0; i < len; ++i, ++dst) { + auto x0 = 0.5f * (rx * rx + ry * ry - radial->fr * radial->fr) / (radial->dr * radial->fr + rx * radial->dx + ry * radial->dy); + auto tmp = op(_pixel(fill, x0), *dst, 255); + *dst = op2(tmp, *dst, 255); + rx += radial->a11; + ry += radial->a21; + } + } else { + for (uint32_t i = 0; i < len; ++i, ++dst) { + auto x0 = 0.5f * (rx * rx + ry * ry - radial->fr * radial->fr) / (radial->dr * radial->fr + rx * radial->dx + ry * radial->dy); + auto tmp = op(_pixel(fill, x0), *dst, 255); + auto tmp2 = op2(tmp, *dst, 255); + *dst = INTERPOLATE(tmp2, *dst, a); + rx += radial->a11; + ry += radial->a21; + } + } + } else { + float b, deltaB, det, deltaDet, deltaDeltaDet; + _calculateCoefficients(fill, x, y, b, deltaB, det, deltaDet, deltaDeltaDet); + if (a == 255) { + for (uint32_t i = 0 ; i < len ; ++i, ++dst) { + auto tmp = op(_pixel(fill, sqrtf(det) - b), *dst, 255); + *dst = op2(tmp, *dst, 255); + det += deltaDet; + deltaDet += deltaDeltaDet; + b += deltaB; + } + } else { + for (uint32_t i = 0 ; i < len ; ++i, ++dst) { + auto tmp = op(_pixel(fill, sqrtf(det) - b), *dst, 255); + auto tmp2 = op2(tmp, *dst, 255); + *dst = INTERPOLATE(tmp2, *dst, a); + det += deltaDet; + deltaDet += deltaDeltaDet; + b += deltaB; + } + } + } +} + + +void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity) +{ + //Rotation + float rx = x + 0.5f; + float ry = y + 0.5f; + float t = (fill->linear.dx * rx + fill->linear.dy * ry + fill->linear.offset) * (GRADIENT_STOP_SIZE - 1); + float inc = (fill->linear.dx) * (GRADIENT_STOP_SIZE - 1); + + if (opacity == 255) { + if (mathZero(inc)) { + auto color = _fixedPixel(fill, static_cast(t * FIXPT_SIZE)); + for (uint32_t i = 0; i < len; ++i, ++dst, cmp += csize) { + *dst = opBlendNormal(color, *dst, alpha(cmp)); + } + return; + } + + auto vMax = static_cast(INT32_MAX >> (FIXPT_BITS + 1)); + auto vMin = -vMax; + auto v = t + (inc * len); + + //we can use fixed point math + if (v < vMax && v > vMin) { + auto t2 = static_cast(t * FIXPT_SIZE); + auto inc2 = static_cast(inc * FIXPT_SIZE); + for (uint32_t j = 0; j < len; ++j, ++dst, cmp += csize) { + *dst = opBlendNormal(_fixedPixel(fill, t2), *dst, alpha(cmp)); + t2 += inc2; + } + //we have to fallback to float math + } else { + uint32_t counter = 0; + while (counter++ < len) { + *dst = opBlendNormal(_pixel(fill, t / GRADIENT_STOP_SIZE), *dst, alpha(cmp)); + ++dst; + t += inc; + cmp += csize; + } + } + } else { + if (mathZero(inc)) { + auto color = _fixedPixel(fill, static_cast(t * FIXPT_SIZE)); + for (uint32_t i = 0; i < len; ++i, ++dst, cmp += csize) { + *dst = opBlendNormal(color, *dst, MULTIPLY(alpha(cmp), opacity)); + } + return; + } + + auto vMax = static_cast(INT32_MAX >> (FIXPT_BITS + 1)); + auto vMin = -vMax; + auto v = t + (inc * len); + + //we can use fixed point math + if (v < vMax && v > vMin) { + auto t2 = static_cast(t * FIXPT_SIZE); + auto inc2 = static_cast(inc * FIXPT_SIZE); + for (uint32_t j = 0; j < len; ++j, ++dst, cmp += csize) { + *dst = opBlendNormal(_fixedPixel(fill, t2), *dst, MULTIPLY(alpha(cmp), opacity)); + t2 += inc2; + } + //we have to fallback to float math + } else { + uint32_t counter = 0; + while (counter++ < len) { + *dst = opBlendNormal(_pixel(fill, t / GRADIENT_STOP_SIZE), *dst, MULTIPLY(opacity, alpha(cmp))); + ++dst; + t += inc; + cmp += csize; + } + } + } +} + + +void fillLinear(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask maskOp, uint8_t a) +{ + //Rotation + float rx = x + 0.5f; + float ry = y + 0.5f; + float t = (fill->linear.dx * rx + fill->linear.dy * ry + fill->linear.offset) * (GRADIENT_STOP_SIZE - 1); + float inc = (fill->linear.dx) * (GRADIENT_STOP_SIZE - 1); + + if (mathZero(inc)) { + auto src = MULTIPLY(a, A(_fixedPixel(fill, static_cast(t * FIXPT_SIZE)))); + for (uint32_t i = 0; i < len; ++i, ++dst) { + *dst = maskOp(src, *dst, ~src); + } + return; + } + + auto vMax = static_cast(INT32_MAX >> (FIXPT_BITS + 1)); + auto vMin = -vMax; + auto v = t + (inc * len); + + //we can use fixed point math + if (v < vMax && v > vMin) { + auto t2 = static_cast(t * FIXPT_SIZE); + auto inc2 = static_cast(inc * FIXPT_SIZE); + for (uint32_t j = 0; j < len; ++j, ++dst) { + auto src = MULTIPLY(_fixedPixel(fill, t2), a); + *dst = maskOp(src, *dst, ~src); + t2 += inc2; + } + //we have to fallback to float math + } else { + uint32_t counter = 0; + while (counter++ < len) { + auto src = MULTIPLY(_pixel(fill, t / GRADIENT_STOP_SIZE), a); + *dst = maskOp(src, *dst, ~src); + ++dst; + t += inc; + } + } +} + + +void fillLinear(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask maskOp, uint8_t a) +{ + //Rotation + float rx = x + 0.5f; + float ry = y + 0.5f; + float t = (fill->linear.dx * rx + fill->linear.dy * ry + fill->linear.offset) * (GRADIENT_STOP_SIZE - 1); + float inc = (fill->linear.dx) * (GRADIENT_STOP_SIZE - 1); + + if (mathZero(inc)) { + auto src = A(_fixedPixel(fill, static_cast(t * FIXPT_SIZE))); + src = MULTIPLY(src, a); + for (uint32_t i = 0; i < len; ++i, ++dst, ++cmp) { + auto tmp = maskOp(src, *cmp, 0); + *dst = tmp + MULTIPLY(*dst, ~tmp); + } + return; + } + + auto vMax = static_cast(INT32_MAX >> (FIXPT_BITS + 1)); + auto vMin = -vMax; + auto v = t + (inc * len); + + //we can use fixed point math + if (v < vMax && v > vMin) { + auto t2 = static_cast(t * FIXPT_SIZE); + auto inc2 = static_cast(inc * FIXPT_SIZE); + for (uint32_t j = 0; j < len; ++j, ++dst, ++cmp) { + auto src = MULTIPLY(a, A(_fixedPixel(fill, t2))); + auto tmp = maskOp(src, *cmp, 0); + *dst = tmp + MULTIPLY(*dst, ~tmp); + t2 += inc2; + } + //we have to fallback to float math + } else { + uint32_t counter = 0; + while (counter++ < len) { + auto src = MULTIPLY(A(_pixel(fill, t / GRADIENT_STOP_SIZE)), a); + auto tmp = maskOp(src, *cmp, 0); + *dst = tmp + MULTIPLY(*dst, ~tmp); + ++dst; + ++cmp; + t += inc; + } + } +} + + +void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a) +{ + //Rotation + float rx = x + 0.5f; + float ry = y + 0.5f; + float t = (fill->linear.dx * rx + fill->linear.dy * ry + fill->linear.offset) * (GRADIENT_STOP_SIZE - 1); + float inc = (fill->linear.dx) * (GRADIENT_STOP_SIZE - 1); + + if (mathZero(inc)) { + auto color = _fixedPixel(fill, static_cast(t * FIXPT_SIZE)); + for (uint32_t i = 0; i < len; ++i, ++dst) { + *dst = op(color, *dst, a); + } + return; + } + + auto vMax = static_cast(INT32_MAX >> (FIXPT_BITS + 1)); + auto vMin = -vMax; + auto v = t + (inc * len); + + //we can use fixed point math + if (v < vMax && v > vMin) { + auto t2 = static_cast(t * FIXPT_SIZE); + auto inc2 = static_cast(inc * FIXPT_SIZE); + for (uint32_t j = 0; j < len; ++j, ++dst) { + *dst = op(_fixedPixel(fill, t2), *dst, a); + t2 += inc2; + } + //we have to fallback to float math + } else { + uint32_t counter = 0; + while (counter++ < len) { + *dst = op(_pixel(fill, t / GRADIENT_STOP_SIZE), *dst, a); + ++dst; + t += inc; + } + } +} + + +void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a) +{ + //Rotation + float rx = x + 0.5f; + float ry = y + 0.5f; + float t = (fill->linear.dx * rx + fill->linear.dy * ry + fill->linear.offset) * (GRADIENT_STOP_SIZE - 1); + float inc = (fill->linear.dx) * (GRADIENT_STOP_SIZE - 1); + + if (mathZero(inc)) { + auto color = _fixedPixel(fill, static_cast(t * FIXPT_SIZE)); + if (a == 255) { + for (uint32_t i = 0; i < len; ++i, ++dst) { + auto tmp = op(color, *dst, a); + *dst = op2(tmp, *dst, 255); + } + } else { + for (uint32_t i = 0; i < len; ++i, ++dst) { + auto tmp = op(color, *dst, a); + auto tmp2 = op2(tmp, *dst, 255); + *dst = INTERPOLATE(tmp2, *dst, a); + } + } + return; + } + + auto vMax = static_cast(INT32_MAX >> (FIXPT_BITS + 1)); + auto vMin = -vMax; + auto v = t + (inc * len); + + if (a == 255) { + //we can use fixed point math + if (v < vMax && v > vMin) { + auto t2 = static_cast(t * FIXPT_SIZE); + auto inc2 = static_cast(inc * FIXPT_SIZE); + for (uint32_t j = 0; j < len; ++j, ++dst) { + auto tmp = op(_fixedPixel(fill, t2), *dst, 255); + *dst = op2(tmp, *dst, 255); + t2 += inc2; + } + //we have to fallback to float math + } else { + uint32_t counter = 0; + while (counter++ < len) { + auto tmp = op(_pixel(fill, t / GRADIENT_STOP_SIZE), *dst, 255); + *dst = op2(tmp, *dst, 255); + ++dst; + t += inc; + } + } + } else { + //we can use fixed point math + if (v < vMax && v > vMin) { + auto t2 = static_cast(t * FIXPT_SIZE); + auto inc2 = static_cast(inc * FIXPT_SIZE); + for (uint32_t j = 0; j < len; ++j, ++dst) { + auto tmp = op(_fixedPixel(fill, t2), *dst, 255); + auto tmp2 = op2(tmp, *dst, 255); + *dst = INTERPOLATE(tmp2, *dst, a); + t2 += inc2; + } + //we have to fallback to float math + } else { + uint32_t counter = 0; + while (counter++ < len) { + auto tmp = op(_pixel(fill, t / GRADIENT_STOP_SIZE), *dst, 255); + auto tmp2 = op2(tmp, *dst, 255); + *dst = INTERPOLATE(tmp2, *dst, a); + ++dst; + t += inc; + } + } + } +} + + +bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, SwSurface* surface, uint8_t opacity, bool ctable) +{ + if (!fill) return false; + + fill->spread = fdata->spread(); + + if (ctable) { + if (!_updateColorTable(fill, fdata, surface, opacity)) return false; + } + + if (fdata->identifier() == TVG_CLASS_ID_LINEAR) { + return _prepareLinear(fill, static_cast(fdata), transform); + } else if (fdata->identifier() == TVG_CLASS_ID_RADIAL) { + return _prepareRadial(fill, static_cast(fdata), transform); + } + + //LOG: What type of gradient?! + + return false; +} + + +void fillReset(SwFill* fill) +{ + if (fill->ctable) { + free(fill->ctable); + fill->ctable = nullptr; + } + fill->translucent = false; +} + + +void fillFree(SwFill* fill) +{ + if (!fill) return; + + if (fill->ctable) free(fill->ctable); + + free(fill); +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwImage.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwImage.cpp new file mode 100644 index 000000000..040c38930 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwImage.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgMath.h" +#include "tvgSwCommon.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static inline bool _onlyShifted(const Matrix* m) +{ + if (mathEqual(m->e11, 1.0f) && mathEqual(m->e22, 1.0f) && mathZero(m->e12) && mathZero(m->e21)) return true; + return false; +} + + +static bool _genOutline(SwImage* image, const RenderMesh* mesh, const Matrix* transform, SwMpool* mpool, unsigned tid) +{ + image->outline = mpoolReqOutline(mpool, tid); + auto outline = image->outline; + + outline->pts.reserve(5); + outline->types.reserve(5); + outline->cntrs.reserve(1); + outline->closed.reserve(1); + + Point to[4]; + if (mesh->triangleCnt > 0) { + // TODO: Optimise me. We appear to calculate this exact min/max bounding area in multiple + // places. We should be able to re-use one we have already done? Also see: + // tvgPicture.h --> bounds + // tvgSwRasterTexmap.h --> _rasterTexmapPolygonMesh + // + // TODO: Should we calculate the exact path(s) of the triangle mesh instead? + // i.e. copy tvgSwShape.capp -> _genOutline? + // + // TODO: Cntrs? + auto triangles = mesh->triangles; + auto min = triangles[0].vertex[0].pt; + auto max = triangles[0].vertex[0].pt; + + for (uint32_t i = 0; i < mesh->triangleCnt; ++i) { + if (triangles[i].vertex[0].pt.x < min.x) min.x = triangles[i].vertex[0].pt.x; + else if (triangles[i].vertex[0].pt.x > max.x) max.x = triangles[i].vertex[0].pt.x; + if (triangles[i].vertex[0].pt.y < min.y) min.y = triangles[i].vertex[0].pt.y; + else if (triangles[i].vertex[0].pt.y > max.y) max.y = triangles[i].vertex[0].pt.y; + + if (triangles[i].vertex[1].pt.x < min.x) min.x = triangles[i].vertex[1].pt.x; + else if (triangles[i].vertex[1].pt.x > max.x) max.x = triangles[i].vertex[1].pt.x; + if (triangles[i].vertex[1].pt.y < min.y) min.y = triangles[i].vertex[1].pt.y; + else if (triangles[i].vertex[1].pt.y > max.y) max.y = triangles[i].vertex[1].pt.y; + + if (triangles[i].vertex[2].pt.x < min.x) min.x = triangles[i].vertex[2].pt.x; + else if (triangles[i].vertex[2].pt.x > max.x) max.x = triangles[i].vertex[2].pt.x; + if (triangles[i].vertex[2].pt.y < min.y) min.y = triangles[i].vertex[2].pt.y; + else if (triangles[i].vertex[2].pt.y > max.y) max.y = triangles[i].vertex[2].pt.y; + } + to[0] = {min.x, min.y}; + to[1] = {max.x, min.y}; + to[2] = {max.x, max.y}; + to[3] = {min.x, max.y}; + } else { + auto w = static_cast(image->w); + auto h = static_cast(image->h); + to[0] = {0, 0}; + to[1] = {w, 0}; + to[2] = {w, h}; + to[3] = {0, h}; + } + + for (int i = 0; i < 4; i++) { + outline->pts.push(mathTransform(&to[i], transform)); + outline->types.push(SW_CURVE_TYPE_POINT); + } + + outline->pts.push(outline->pts[0]); + outline->types.push(SW_CURVE_TYPE_POINT); + outline->cntrs.push(outline->pts.count - 1); + outline->closed.push(true); + + image->outline = outline; + + return true; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +bool imagePrepare(SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid) +{ + image->direct = _onlyShifted(transform); + + //Fast track: Non-transformed image but just shifted. + if (image->direct) { + image->ox = -static_cast(round(transform->e13)); + image->oy = -static_cast(round(transform->e23)); + //Figure out the scale factor by transform matrix + } else { + auto scaleX = sqrtf((transform->e11 * transform->e11) + (transform->e21 * transform->e21)); + auto scaleY = sqrtf((transform->e22 * transform->e22) + (transform->e12 * transform->e12)); + image->scale = (fabsf(scaleX - scaleY) > 0.01f) ? 1.0f : scaleX; + + if (mathZero(transform->e12) && mathZero(transform->e21)) image->scaled = true; + else image->scaled = false; + } + + if (!_genOutline(image, mesh, transform, mpool, tid)) return false; + return mathUpdateOutlineBBox(image->outline, clipRegion, renderRegion, image->direct); +} + + +bool imageGenRle(SwImage* image, const SwBBox& renderRegion, bool antiAlias) +{ + if ((image->rle = rleRender(image->rle, image->outline, renderRegion, antiAlias))) return true; + + return false; +} + + +void imageDelOutline(SwImage* image, SwMpool* mpool, uint32_t tid) +{ + mpoolRetOutline(mpool, tid); + image->outline = nullptr; +} + + +void imageReset(SwImage* image) +{ + rleReset(image->rle); +} + + +void imageFree(SwImage* image) +{ + rleFree(image->rle); +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwMath.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwMath.cpp new file mode 100644 index 000000000..b636c04cf --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwMath.cpp @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgMath.h" +#include "tvgSwCommon.h" + + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static float TO_RADIAN(SwFixed angle) +{ + return (float(angle) / 65536.0f) * (MATH_PI / 180.0f); +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +SwFixed mathMean(SwFixed angle1, SwFixed angle2) +{ + return angle1 + mathDiff(angle1, angle2) / 2; +} + + +bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut) +{ + auto d1 = base[2] - base[3]; + auto d2 = base[1] - base[2]; + auto d3 = base[0] - base[1]; + + if (d1 == d2 || d2 == d3) { + if (d3.small()) angleIn = angleMid = angleOut = 0; + else angleIn = angleMid = angleOut = mathAtan(d3); + return true; + } + + if (d1.small()) { + if (d2.small()) { + if (d3.small()) { + angleIn = angleMid = angleOut = 0; + return true; + } else { + angleIn = angleMid = angleOut = mathAtan(d3); + } + } else { + if (d3.small()) { + angleIn = angleMid = angleOut = mathAtan(d2); + } else { + angleIn = angleMid = mathAtan(d2); + angleOut = mathAtan(d3); + } + } + } else { + if (d2.small()) { + if (d3.small()) { + angleIn = angleMid = angleOut = mathAtan(d1); + } else { + angleIn = mathAtan(d1); + angleOut = mathAtan(d3); + angleMid = mathMean(angleIn, angleOut); + } + } else { + if (d3.small()) { + angleIn = mathAtan(d1); + angleMid = angleOut = mathAtan(d2); + } else { + angleIn = mathAtan(d1); + angleMid = mathAtan(d2); + angleOut = mathAtan(d3); + } + } + } + + auto theta1 = abs(mathDiff(angleIn, angleMid)); + auto theta2 = abs(mathDiff(angleMid, angleOut)); + + if ((theta1 < (SW_ANGLE_PI / 8)) && (theta2 < (SW_ANGLE_PI / 8))) return true; + return false; +} + + +int64_t mathMultiply(int64_t a, int64_t b) +{ + int32_t s = 1; + + //move sign + if (a < 0) { + a = -a; + s = -s; + } + if (b < 0) { + b = -b; + s = -s; + } + int64_t c = (a * b + 0x8000L) >> 16; + return (s > 0) ? c : -c; +} + + +int64_t mathDivide(int64_t a, int64_t b) +{ + int32_t s = 1; + + //move sign + if (a < 0) { + a = -a; + s = -s; + } + if (b < 0) { + b = -b; + s = -s; + } + int64_t q = b > 0 ? ((a << 16) + (b >> 1)) / b : 0x7FFFFFFFL; + return (s < 0 ? -q : q); +} + + +int64_t mathMulDiv(int64_t a, int64_t b, int64_t c) +{ + int32_t s = 1; + + //move sign + if (a < 0) { + a = -a; + s = -s; + } + if (b < 0) { + b = -b; + s = -s; + } + if (c < 0) { + c = -c; + s = -s; + } + int64_t d = c > 0 ? (a * b + (c >> 1)) / c : 0x7FFFFFFFL; + + return (s > 0 ? d : -d); +} + + +void mathRotate(SwPoint& pt, SwFixed angle) +{ + if (angle == 0 || pt.zero()) return; + + Point v = pt.toPoint(); + + auto radian = TO_RADIAN(angle); + auto cosv = cosf(radian); + auto sinv = sinf(radian); + + pt.x = SwCoord(roundf((v.x * cosv - v.y * sinv) * 64.0f)); + pt.y = SwCoord(roundf((v.x * sinv + v.y * cosv) * 64.0f)); +} + + +SwFixed mathTan(SwFixed angle) +{ + if (angle == 0) return 0; + return SwFixed(tanf(TO_RADIAN(angle)) * 65536.0f); +} + + +SwFixed mathAtan(const SwPoint& pt) +{ + if (pt.zero()) return 0; + return SwFixed(atan2f(TO_FLOAT(pt.y), TO_FLOAT(pt.x)) * (180.0f / MATH_PI) * 65536.0f); +} + + +SwFixed mathSin(SwFixed angle) +{ + if (angle == 0) return 0; + return mathCos(SW_ANGLE_PI2 - angle); +} + + +SwFixed mathCos(SwFixed angle) +{ + return SwFixed(cosf(TO_RADIAN(angle)) * 65536.0f); +} + + +SwFixed mathLength(const SwPoint& pt) +{ + if (pt.zero()) return 0; + + //trivial case + if (pt.x == 0) return abs(pt.y); + if (pt.y == 0) return abs(pt.x); + + auto v = pt.toPoint(); + //return static_cast(sqrtf(v.x * v.x + v.y * v.y) * 65536.0f); + + /* approximate sqrt(x*x + y*y) using alpha max plus beta min algorithm. + With alpha = 1, beta = 3/8, giving results with the largest error less + than 7% compared to the exact value. */ + if (v.x < 0) v.x = -v.x; + if (v.y < 0) v.y = -v.y; + return (SwFixed)((v.x > v.y) ? (v.x + v.y * 0.375f) : (v.y + v.x * 0.375f)); +} + + +void mathSplitCubic(SwPoint* base) +{ + SwCoord a, b, c, d; + + base[6].x = base[3].x; + c = base[1].x; + d = base[2].x; + base[1].x = a = (base[0].x + c) >> 1; + base[5].x = b = (base[3].x + d) >> 1; + c = (c + d) >> 1; + base[2].x = a = (a + c) >> 1; + base[4].x = b = (b + c) >> 1; + base[3].x = (a + b) >> 1; + + base[6].y = base[3].y; + c = base[1].y; + d = base[2].y; + base[1].y = a = (base[0].y + c) >> 1; + base[5].y = b = (base[3].y + d) >> 1; + c = (c + d) >> 1; + base[2].y = a = (a + c) >> 1; + base[4].y = b = (b + c) >> 1; + base[3].y = (a + b) >> 1; +} + + +SwFixed mathDiff(SwFixed angle1, SwFixed angle2) +{ + auto delta = angle2 - angle1; + + delta %= SW_ANGLE_2PI; + if (delta < 0) delta += SW_ANGLE_2PI; + if (delta > SW_ANGLE_PI) delta -= SW_ANGLE_2PI; + + return delta; +} + + +SwPoint mathTransform(const Point* to, const Matrix* transform) +{ + if (!transform) return {TO_SWCOORD(to->x), TO_SWCOORD(to->y)}; + + auto tx = to->x * transform->e11 + to->y * transform->e12 + transform->e13; + auto ty = to->x * transform->e21 + to->y * transform->e22 + transform->e23; + + return {TO_SWCOORD(tx), TO_SWCOORD(ty)}; +} + + +bool mathClipBBox(const SwBBox& clipper, SwBBox& clipee) +{ + clipee.max.x = (clipee.max.x < clipper.max.x) ? clipee.max.x : clipper.max.x; + clipee.max.y = (clipee.max.y < clipper.max.y) ? clipee.max.y : clipper.max.y; + clipee.min.x = (clipee.min.x > clipper.min.x) ? clipee.min.x : clipper.min.x; + clipee.min.y = (clipee.min.y > clipper.min.y) ? clipee.min.y : clipper.min.y; + + //Check valid region + if (clipee.max.x - clipee.min.x < 1 && clipee.max.y - clipee.min.y < 1) return false; + + //Check boundary + if (clipee.min.x >= clipper.max.x || clipee.min.y >= clipper.max.y || + clipee.max.x <= clipper.min.x || clipee.max.y <= clipper.min.y) return false; + + return true; +} + + +bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, SwBBox& renderRegion, bool fastTrack) +{ + if (!outline) return false; + + auto pt = outline->pts.data; + + if (outline->pts.empty() || outline->cntrs.empty()) { + renderRegion.reset(); + return false; + } + + auto xMin = pt->x; + auto xMax = pt->x; + auto yMin = pt->y; + auto yMax = pt->y; + + for (++pt; pt < outline->pts.end(); ++pt) { + if (xMin > pt->x) xMin = pt->x; + if (xMax < pt->x) xMax = pt->x; + if (yMin > pt->y) yMin = pt->y; + if (yMax < pt->y) yMax = pt->y; + } + //Since no antialiasing is applied in the Fast Track case, + //the rasterization region has to be rearranged. + //https://github.com/Samsung/thorvg/issues/916 + if (fastTrack) { + renderRegion.min.x = static_cast(round(xMin / 64.0f)); + renderRegion.max.x = static_cast(round(xMax / 64.0f)); + renderRegion.min.y = static_cast(round(yMin / 64.0f)); + renderRegion.max.y = static_cast(round(yMax / 64.0f)); + } else { + renderRegion.min.x = xMin >> 6; + renderRegion.max.x = (xMax + 63) >> 6; + renderRegion.min.y = yMin >> 6; + renderRegion.max.y = (yMax + 63) >> 6; + } + return mathClipBBox(clipRegion, renderRegion); +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwMemPool.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwMemPool.cpp new file mode 100644 index 000000000..b9675e59c --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwMemPool.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgSwCommon.h" + + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +SwOutline* mpoolReqOutline(SwMpool* mpool, unsigned idx) +{ + return &mpool->outline[idx]; +} + + +void mpoolRetOutline(SwMpool* mpool, unsigned idx) +{ + mpool->outline[idx].pts.clear(); + mpool->outline[idx].cntrs.clear(); + mpool->outline[idx].types.clear(); + mpool->outline[idx].closed.clear(); +} + + +SwOutline* mpoolReqStrokeOutline(SwMpool* mpool, unsigned idx) +{ + return &mpool->strokeOutline[idx]; +} + + +void mpoolRetStrokeOutline(SwMpool* mpool, unsigned idx) +{ + mpool->strokeOutline[idx].pts.clear(); + mpool->strokeOutline[idx].cntrs.clear(); + mpool->strokeOutline[idx].types.clear(); + mpool->strokeOutline[idx].closed.clear(); +} + + +SwOutline* mpoolReqDashOutline(SwMpool* mpool, unsigned idx) +{ + return &mpool->dashOutline[idx]; +} + + +void mpoolRetDashOutline(SwMpool* mpool, unsigned idx) +{ + mpool->dashOutline[idx].pts.clear(); + mpool->dashOutline[idx].cntrs.clear(); + mpool->dashOutline[idx].types.clear(); + mpool->dashOutline[idx].closed.clear(); +} + + +SwMpool* mpoolInit(uint32_t threads) +{ + auto allocSize = threads + 1; + + auto mpool = static_cast(calloc(sizeof(SwMpool), 1)); + mpool->outline = static_cast(calloc(1, sizeof(SwOutline) * allocSize)); + mpool->strokeOutline = static_cast(calloc(1, sizeof(SwOutline) * allocSize)); + mpool->dashOutline = static_cast(calloc(1, sizeof(SwOutline) * allocSize)); + mpool->allocSize = allocSize; + return mpool; +} + + +bool mpoolClear(SwMpool* mpool) +{ + for (unsigned i = 0; i < mpool->allocSize; ++i) { + mpool->outline[i].pts.reset(); + mpool->outline[i].cntrs.reset(); + mpool->outline[i].types.reset(); + mpool->outline[i].closed.reset(); + + mpool->strokeOutline[i].pts.reset(); + mpool->strokeOutline[i].cntrs.reset(); + mpool->strokeOutline[i].types.reset(); + mpool->strokeOutline[i].closed.reset(); + + mpool->dashOutline[i].pts.reset(); + mpool->dashOutline[i].cntrs.reset(); + mpool->dashOutline[i].types.reset(); + mpool->dashOutline[i].closed.reset(); + } + + return true; +} + + +bool mpoolTerm(SwMpool* mpool) +{ + if (!mpool) return false; + + mpoolClear(mpool); + + free(mpool->outline); + free(mpool->strokeOutline); + free(mpool->dashOutline); + free(mpool); + + return true; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRaster.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRaster.cpp new file mode 100644 index 000000000..dc8c76eb1 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRaster.cpp @@ -0,0 +1,1957 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifdef _WIN32 + #include +#elif defined(__linux__) + #include +#else + #include +#endif + +#include "tvgMath.h" +#include "tvgRender.h" +#include "tvgSwCommon.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ +constexpr auto DOWN_SCALE_TOLERANCE = 0.5f; + +struct FillLinear +{ + void operator()(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask op, uint8_t a) + { + fillLinear(fill, dst, y, x, len, op, a); + } + + void operator()(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask op, uint8_t a) + { + fillLinear(fill, dst, y, x, len, cmp, op, a); + } + + void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a) + { + fillLinear(fill, dst, y, x, len, op, a); + } + + void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity) + { + fillLinear(fill, dst, y, x, len, cmp, alpha, csize, opacity); + } + + void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a) + { + fillLinear(fill, dst, y, x, len, op, op2, a); + } + +}; + +struct FillRadial +{ + void operator()(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask op, uint8_t a) + { + fillRadial(fill, dst, y, x, len, op, a); + } + + void operator()(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask op, uint8_t a) + { + fillRadial(fill, dst, y, x, len, cmp, op, a); + } + + void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a) + { + fillRadial(fill, dst, y, x, len, op, a); + } + + void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity) + { + fillRadial(fill, dst, y, x, len, cmp, alpha, csize, opacity); + } + + void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a) + { + fillRadial(fill, dst, y, x, len, op, op2, a); + } +}; + + +static inline uint8_t _alpha(uint8_t* a) +{ + return *a; +} + + +static inline uint8_t _ialpha(uint8_t* a) +{ + return ~(*a); +} + + +static inline uint8_t _abgrLuma(uint8_t* c) +{ + auto v = *(uint32_t*)c; + return ((((v&0xff)*54) + (((v>>8)&0xff)*183) + (((v>>16)&0xff)*19))) >> 8; //0.2125*R + 0.7154*G + 0.0721*B +} + + +static inline uint8_t _argbLuma(uint8_t* c) +{ + auto v = *(uint32_t*)c; + return ((((v&0xff)*19) + (((v>>8)&0xff)*183) + (((v>>16)&0xff)*54))) >> 8; //0.0721*B + 0.7154*G + 0.2125*R +} + + +static inline uint8_t _abgrInvLuma(uint8_t* c) +{ + return ~_abgrLuma(c); +} + + +static inline uint8_t _argbInvLuma(uint8_t* c) +{ + return ~_argbLuma(c); +} + + +static inline uint32_t _abgrJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + return (a << 24 | b << 16 | g << 8 | r); +} + + +static inline uint32_t _argbJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + return (a << 24 | r << 16 | g << 8 | b); +} + +static inline bool _blending(const SwSurface* surface) +{ + return (surface->blender) ? true : false; +} + + +/* OPTIMIZE_ME: Probably, we can separate masking(8bits) / composition(32bits) + This would help to enhance the performance by avoiding the unnecessary matting from the composition */ +static inline bool _compositing(const SwSurface* surface) +{ + if (!surface->compositor || (int)surface->compositor->method <= (int)CompositeMethod::ClipPath) return false; + return true; +} + + +static inline bool _matting(const SwSurface* surface) +{ + if ((int)surface->compositor->method < (int)CompositeMethod::AddMask) return true; + else return false; +} + +static inline uint8_t _opMaskNone(uint8_t s, TVG_UNUSED uint8_t d, TVG_UNUSED uint8_t a) +{ + return s; +} + +static inline uint8_t _opMaskAdd(uint8_t s, uint8_t d, uint8_t a) +{ + return s + MULTIPLY(d, a); +} + + +static inline uint8_t _opMaskSubtract(uint8_t s, uint8_t d, TVG_UNUSED uint8_t a) +{ + return MULTIPLY(s, 255 - d); +} + + +static inline uint8_t _opMaskIntersect(uint8_t s, uint8_t d, TVG_UNUSED uint8_t a) +{ + return MULTIPLY(s, d); +} + + +static inline uint8_t _opMaskDifference(uint8_t s, uint8_t d, uint8_t a) +{ + return MULTIPLY(s, 255 - d) + MULTIPLY(d, a); +} + + +static inline bool _direct(CompositeMethod method) +{ + //subtract & Intersect allows the direct composition + if (method == CompositeMethod::SubtractMask || method == CompositeMethod::IntersectMask) return true; + return false; +} + + +static inline SwMask _getMaskOp(CompositeMethod method) +{ + switch (method) { + case CompositeMethod::AddMask: return _opMaskAdd; + case CompositeMethod::SubtractMask: return _opMaskSubtract; + case CompositeMethod::DifferenceMask: return _opMaskDifference; + case CompositeMethod::IntersectMask: return _opMaskIntersect; + default: return nullptr; + } +} + + +static bool _compositeMaskImage(SwSurface* surface, const SwImage* image, const SwBBox& region) +{ + auto dbuffer = &surface->buf8[region.min.y * surface->stride + region.min.x]; + auto sbuffer = image->buf8 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + + for (auto y = region.min.y; y < region.max.y; ++y) { + auto dst = dbuffer; + auto src = sbuffer; + for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) { + *dst = *src + MULTIPLY(*dst, ~*src); + } + dbuffer += surface->stride; + sbuffer += image->stride; + } + return true; +} + + +#include "tvgSwRasterTexmap.h" +#include "tvgSwRasterC.h" +#include "tvgSwRasterAvx.h" +#include "tvgSwRasterNeon.h" + + +static inline uint32_t _sampleSize(float scale) +{ + auto sampleSize = static_cast(0.5f / scale); + if (sampleSize == 0) sampleSize = 1; + return sampleSize; +} + + +//Bilinear Interpolation +//OPTIMIZE_ME: Skip the function pointer access +static uint32_t _interpUpScaler(const uint32_t *img, TVG_UNUSED uint32_t stride, uint32_t w, uint32_t h, float sx, float sy, TVG_UNUSED int32_t miny, TVG_UNUSED int32_t maxy, TVG_UNUSED int32_t n) +{ + auto rx = (size_t)(sx); + auto ry = (size_t)(sy); + auto rx2 = rx + 1; + if (rx2 >= w) rx2 = w - 1; + auto ry2 = ry + 1; + if (ry2 >= h) ry2 = h - 1; + + auto dx = static_cast((sx - rx) * 255.0f); + auto dy = static_cast((sy - ry) * 255.0f); + + auto c1 = img[rx + ry * w]; + auto c2 = img[rx2 + ry * w]; + auto c3 = img[rx2 + ry2 * w]; + auto c4 = img[rx + ry2 * w]; + + return INTERPOLATE(INTERPOLATE(c3, c4, dx), INTERPOLATE(c2, c1, dx), dy); +} + + +//2n x 2n Mean Kernel +//OPTIMIZE_ME: Skip the function pointer access +static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t w, uint32_t h, float sx, TVG_UNUSED float sy, int32_t miny, int32_t maxy, int32_t n) +{ + size_t c[4] = {0, 0, 0, 0}; + + int32_t minx = (int32_t)sx - n; + if (minx < 0) minx = 0; + + int32_t maxx = (int32_t)sx + n; + if (maxx >= (int32_t)w) maxx = w; + + auto src = img + minx + miny * stride; + + for (auto y = miny; y < maxy; ++y) { + auto p = src; + for (auto x = minx; x < maxx; ++x, ++p) { + c[0] += *p >> 24; + c[1] += (*p >> 16) & 0xff; + c[2] += (*p >> 8) & 0xff; + c[3] += *p & 0xff; + } + src += stride; + } + + n = (maxy - miny) * (maxx - minx); + + c[0] /= n; + c[1] /= n; + c[2] /= n; + c[3] /= n; + + return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; +} + + +/************************************************************************/ +/* Rect */ +/************************************************************************/ + +static bool _rasterCompositeMaskedRect(SwSurface* surface, const SwBBox& region, SwMask maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + auto w = static_cast(region.max.x - region.min.x); + auto h = static_cast(region.max.y - region.min.y); + auto cstride = surface->compositor->image.stride; + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); //compositor buffer + auto ialpha = 255 - a; + + for (uint32_t y = 0; y < h; ++y) { + auto cmp = cbuffer; + for (uint32_t x = 0; x < w; ++x, ++cmp) { + *cmp = maskOp(a, *cmp, ialpha); + } + cbuffer += cstride; + } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); +} + + +static bool _rasterDirectMaskedRect(SwSurface* surface, const SwBBox& region, SwMask maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + auto w = static_cast(region.max.x - region.min.x); + auto h = static_cast(region.max.y - region.min.y); + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x); //compositor buffer + auto dbuffer = surface->buf8 + (region.min.y * surface->stride + region.min.x); //destination buffer + + for (uint32_t y = 0; y < h; ++y) { + auto cmp = cbuffer; + auto dst = dbuffer; + for (uint32_t x = 0; x < w; ++x, ++cmp, ++dst) { + auto tmp = maskOp(a, *cmp, 0); //not use alpha. + *dst = tmp + MULTIPLY(*dst, ~tmp); + } + cbuffer += surface->compositor->image.stride; + dbuffer += surface->stride; + } + return true; +} + + +static bool _rasterMaskedRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + //8bit masking channels composition + if (surface->channelSize != sizeof(uint8_t)) return false; + + TVGLOG("SW_ENGINE", "Masked(%d) Rect [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); + + auto maskOp = _getMaskOp(surface->compositor->method); + if (_direct(surface->compositor->method)) return _rasterDirectMaskedRect(surface, region, maskOp, r, g, b, a); + else return _rasterCompositeMaskedRect(surface, region, maskOp, r, g, b, a); + return false; +} + + +static bool _rasterMattedRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + auto w = static_cast(region.max.x - region.min.x); + auto h = static_cast(region.max.y - region.min.y); + auto csize = surface->compositor->image.channelSize; + auto cbuffer = surface->compositor->image.buf8 + ((region.min.y * surface->compositor->image.stride + region.min.x) * csize); //compositor buffer + auto alpha = surface->alpha(surface->compositor->method); + + TVGLOG("SW_ENGINE", "Matted(%d) Rect [Region: %lu %lu %u %u]", (int)surface->compositor->method, region.min.x, region.min.y, w, h); + + //32bits channels + if (surface->channelSize == sizeof(uint32_t)) { + auto color = surface->join(r, g, b, a); + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface->stride]; + auto cmp = &cbuffer[y * surface->compositor->image.stride * csize]; + for (uint32_t x = 0; x < w; ++x, ++dst, cmp += csize) { + *dst = INTERPOLATE(color, *dst, alpha(cmp)); + } + } + //8bits grayscale + } else if (surface->channelSize == sizeof(uint8_t)) { + auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x; + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface->stride]; + auto cmp = &cbuffer[y * surface->compositor->image.stride * csize]; + for (uint32_t x = 0; x < w; ++x, ++dst, cmp += csize) { + *dst = INTERPOLATE8(a, *dst, alpha(cmp)); + } + } + } + return true; +} + + +static bool _rasterBlendingRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + if (surface->channelSize != sizeof(uint32_t)) return false; + + auto w = static_cast(region.max.x - region.min.x); + auto h = static_cast(region.max.y - region.min.y); + auto color = surface->join(r, g, b, a); + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; + auto ialpha = 255 - a; + + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface->stride]; + for (uint32_t x = 0; x < w; ++x, ++dst) { + *dst = surface->blender(color, *dst, ialpha); + } + } + return true; +} + + +static bool _rasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ +#if defined(THORVG_AVX_VECTOR_SUPPORT) + return avxRasterTranslucentRect(surface, region, r, g, b, a); +#elif defined(THORVG_NEON_VECTOR_SUPPORT) + return neonRasterTranslucentRect(surface, region, r, g, b, a); +#else + return cRasterTranslucentRect(surface, region, r, g, b, a); +#endif +} + + +static bool _rasterSolidRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b) +{ + auto w = static_cast(region.max.x - region.min.x); + auto h = static_cast(region.max.y - region.min.y); + + //32bits channels + if (surface->channelSize == sizeof(uint32_t)) { + auto color = surface->join(r, g, b, 255); + auto buffer = surface->buf32 + (region.min.y * surface->stride); + for (uint32_t y = 0; y < h; ++y) { + rasterPixel32(buffer + y * surface->stride, color, region.min.x, w); + } + return true; + } + //8bits grayscale + if (surface->channelSize == sizeof(uint8_t)) { + for (uint32_t y = 0; y < h; ++y) { + rasterGrayscale8(surface->buf8, 255, (y + region.min.y) * surface->stride + region.min.x, w); + } + return true; + } + return false; +} + + +static bool _rasterRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + if (_compositing(surface)) { + if (_matting(surface)) return _rasterMattedRect(surface, region, r, g, b, a); + else return _rasterMaskedRect(surface, region, r, g, b, a); + } else if (_blending(surface)) { + return _rasterBlendingRect(surface, region, r, g, b, a); + } else { + if (a == 255) return _rasterSolidRect(surface, region, r, g, b); + else return _rasterTranslucentRect(surface, region, r, g, b, a); + } + return false; +} + + +/************************************************************************/ +/* Rle */ +/************************************************************************/ + +static bool _rasterCompositeMaskedRle(SwSurface* surface, SwRleData* rle, SwMask maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + auto span = rle->spans; + auto cbuffer = surface->compositor->image.buf8; + auto cstride = surface->compositor->image.stride; + uint8_t src; + + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto cmp = &cbuffer[span->y * cstride + span->x]; + if (span->coverage == 255) src = a; + else src = MULTIPLY(a, span->coverage); + auto ialpha = 255 - src; + for (auto x = 0; x < span->len; ++x, ++cmp) { + *cmp = maskOp(src, *cmp, ialpha); + } + } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); +} + + +static bool _rasterDirectMaskedRle(SwSurface* surface, SwRleData* rle, SwMask maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + auto span = rle->spans; + auto cbuffer = surface->compositor->image.buf8; + auto cstride = surface->compositor->image.stride; + uint8_t src; + + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto cmp = &cbuffer[span->y * cstride + span->x]; + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + if (span->coverage == 255) src = a; + else src = MULTIPLY(a, span->coverage); + for (auto x = 0; x < span->len; ++x, ++cmp, ++dst) { + auto tmp = maskOp(src, *cmp, 0); //not use alpha + *dst = tmp + MULTIPLY(*dst, ~tmp); + } + } + return true; +} + + +static bool _rasterMaskedRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + TVGLOG("SW_ENGINE", "Masked(%d) Rle", (int)surface->compositor->method); + + //8bit masking channels composition + if (surface->channelSize != sizeof(uint8_t)) return false; + + auto maskOp = _getMaskOp(surface->compositor->method); + if (_direct(surface->compositor->method)) return _rasterDirectMaskedRle(surface, rle, maskOp, r, g, b, a); + else return _rasterCompositeMaskedRle(surface, rle, maskOp, r, g, b, a); + return false; +} + + +static bool _rasterMattedRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + TVGLOG("SW_ENGINE", "Matted(%d) Rle", (int)surface->compositor->method); + + auto span = rle->spans; + auto cbuffer = surface->compositor->image.buf8; + auto csize = surface->compositor->image.channelSize; + auto alpha = surface->alpha(surface->compositor->method); + + //32bit channels + if (surface->channelSize == sizeof(uint32_t)) { + uint32_t src; + auto color = surface->join(r, g, b, a); + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize]; + if (span->coverage == 255) src = color; + else src = ALPHA_BLEND(color, span->coverage); + for (uint32_t x = 0; x < span->len; ++x, ++dst, cmp += csize) { + auto tmp = ALPHA_BLEND(src, alpha(cmp)); + *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + } + } + return true; + } + //8bit grayscale + if (surface->channelSize == sizeof(uint8_t)) { + uint8_t src; + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize]; + if (span->coverage == 255) src = a; + else src = MULTIPLY(a, span->coverage); + for (uint32_t x = 0; x < span->len; ++x, ++dst, cmp += csize) { + *dst = INTERPOLATE8(src, *dst, alpha(cmp)); + } + } + return true; + } + return false; +} + + +static bool _rasterBlendingRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + if (surface->channelSize != sizeof(uint32_t)) return false; + + auto span = rle->spans; + auto color = surface->join(r, g, b, a); + auto ialpha = 255 - a; + + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + if (span->coverage == 255) { + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + *dst = surface->blender(color, *dst, ialpha); + } + } else { + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + auto tmp = surface->blender(color, *dst, ialpha); + *dst = INTERPOLATE(tmp, *dst, span->coverage); + } + } + } + return true; +} + + +static bool _rasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ +#if defined(THORVG_AVX_VECTOR_SUPPORT) + return avxRasterTranslucentRle(surface, rle, r, g, b, a); +#elif defined(THORVG_NEON_VECTOR_SUPPORT) + return neonRasterTranslucentRle(surface, rle, r, g, b, a); +#else + return cRasterTranslucentRle(surface, rle, r, g, b, a); +#endif +} + + +static bool _rasterSolidRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b) +{ + auto span = rle->spans; + + //32bit channels + if (surface->channelSize == sizeof(uint32_t)) { + auto color = surface->join(r, g, b, 255); + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + if (span->coverage == 255) { + rasterPixel32(surface->buf32 + span->y * surface->stride, color, span->x, span->len); + } else { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + auto src = ALPHA_BLEND(color, span->coverage); + auto ialpha = 255 - span->coverage; + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + *dst = src + ALPHA_BLEND(*dst, ialpha); + } + } + } + //8bit grayscale + } else if (surface->channelSize == sizeof(uint8_t)) { + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + if (span->coverage == 255) { + rasterGrayscale8(surface->buf8, span->coverage, span->y * surface->stride + span->x, span->len); + } else { + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + auto ialpha = 255 - span->coverage; + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + *dst = span->coverage + MULTIPLY(*dst, ialpha); + } + } + } + } + return true; +} + + +static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + if (!rle) return false; + + if (_compositing(surface)) { + if (_matting(surface)) return _rasterMattedRle(surface, rle, r, g, b, a); + else return _rasterMaskedRle(surface, rle, r, g, b, a); + } else if (_blending(surface)) { + return _rasterBlendingRle(surface, rle, r, g, b, a); + } else { + if (a == 255) return _rasterSolidRle(surface, rle, r, g, b); + else return _rasterTranslucentRle(surface, rle, r, g, b, a); + } + return false; +} + + +/************************************************************************/ +/* RLE Scaled Image */ +/************************************************************************/ + +#define SCALED_IMAGE_RANGE_Y(y) \ + auto sy = (y) * itransform->e22 + itransform->e23; \ + auto my = (int32_t)round(sy); \ + if (my < 0 || (uint32_t)sy >= image->h) continue; \ + if (scaleMethod == _interpDownScaler) { \ + miny = my - (int32_t)sampleSize; \ + if (miny < 0) miny = 0; \ + maxy = my + (int32_t)sampleSize; \ + if (maxy >= (int32_t)image->h) maxy = (int32_t)image->h; \ + } + +#define SCALED_IMAGE_RANGE_X \ + auto sx = x * itransform->e11 + itransform->e13; \ + if ((int32_t)round(sx) < 0 || (uint32_t) sx >= image->w) continue; + + +#if 0 //Enable it when GRAYSCALE image is supported +static bool _rasterCompositeScaledMaskedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwMask maskOp, uint8_t opacity) +{ + auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image->scale); + auto span = image->rle->spans; + int32_t miny = 0, maxy = 0; + + for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + SCALED_IMAGE_RANGE_Y(span->y) + auto cmp = &surface->compositor->image.buf8[span->y * surface->compositor->image.stride + span->x]; + auto a = MULTIPLY(span->coverage, opacity); + for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++cmp) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (a < 255) src = MULTIPLY(src, a); + *cmp = maskOp(src, *cmp, ~src); + } + } + return true; +} + + +static bool _rasterDirectScaledMaskedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwMask maskOp, uint8_t opacity) +{ + auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image->scale); + auto span = image->rle->spans; + int32_t miny = 0, maxy = 0; + + for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + SCALED_IMAGE_RANGE_Y(span->y) + auto cmp = &surface->compositor->image.buf8[span->y * surface->compositor->image.stride + span->x]; + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + auto a = MULTIPLY(span->coverage, opacity); + for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++cmp, ++dst) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (a < 255) src = MULTIPLY(src, a); + src = maskOp(src, *cmp, 0); //not use alpha + *dst = src + MULTIPLY(*dst, ~src); + } + } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); +} +#endif + +static bool _rasterScaledMaskedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +{ +#if 0 //Enable it when GRAYSCALE image is supported + TVGLOG("SW_ENGINE", "Scaled Masked(%d) Rle Image", (int)surface->compositor->method); + + //8bit masking channels composition + if (surface->channelSize != sizeof(uint8_t)) return false; + + auto maskOp = _getMaskOp(surface->compositor->method); + if (_direct(surface->compositor->method)) return _rasterDirectScaledMaskedRleImage(surface, image, itransform, region, maskOp, opacity); + else return _rasterCompositeScaledMaskedRleImage(surface, image, itransform, region, maskOp, opacity); +#endif + return false; +} + + +static bool _rasterScaledMattedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +{ + TVGLOG("SW_ENGINE", "Scaled Matted(%d) Rle Image", (int)surface->compositor->method); + + auto span = image->rle->spans; + auto csize = surface->compositor->image.channelSize; + auto alpha = surface->alpha(surface->compositor->method); + auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image->scale); + int32_t miny = 0, maxy = 0; + + for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + SCALED_IMAGE_RANGE_Y(span->y) + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + auto cmp = &surface->compositor->image.buf8[(span->y * surface->compositor->image.stride + span->x) * csize]; + auto a = MULTIPLY(span->coverage, opacity); + for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, cmp += csize) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + src = ALPHA_BLEND(src, (a == 255) ? alpha(cmp) : MULTIPLY(alpha(cmp), a)); + *dst = src + ALPHA_BLEND(*dst, IA(src)); + } + } + + return true; +} + + +static bool _rasterScaledBlendingRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +{ + auto span = image->rle->spans; + auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image->scale); + int32_t miny = 0, maxy = 0; + + for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + SCALED_IMAGE_RANGE_Y(span->y) + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + auto alpha = MULTIPLY(span->coverage, opacity); + if (alpha == 255) { + for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + auto tmp = surface->blender(src, *dst, 255); + *dst = INTERPOLATE(tmp, *dst, A(src)); + } + } else { + for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (opacity < 255) src = ALPHA_BLEND(src, opacity); + auto tmp = surface->blender(src, *dst, 255); + *dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(src))); + } + } + } + return true; +} + + +static bool _rasterScaledRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +{ + auto span = image->rle->spans; + auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image->scale); + int32_t miny = 0, maxy = 0; + + for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + SCALED_IMAGE_RANGE_Y(span->y) + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + auto alpha = MULTIPLY(span->coverage, opacity); + for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (alpha < 255) src = ALPHA_BLEND(src, alpha); + *dst = src + ALPHA_BLEND(*dst, IA(src)); + } + } + return true; +} + + +static bool _scaledRleImage(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox& region, uint8_t opacity) +{ + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported scaled rle image!"); + return false; + } + + Matrix itransform; + + if (transform) { + if (!mathInverse(transform, &itransform)) return false; + } else mathIdentity(&itransform); + + if (_compositing(surface)) { + if (_matting(surface)) return _rasterScaledMattedRleImage(surface, image, &itransform, region, opacity); + else return _rasterScaledMaskedRleImage(surface, image, &itransform, region, opacity); + } else if (_blending(surface)) { + return _rasterScaledBlendingRleImage(surface, image, &itransform, region, opacity); + } else { + return _rasterScaledRleImage(surface, image, &itransform, region, opacity); + } + return false; +} + + +/************************************************************************/ +/* RLE Direct Image */ +/************************************************************************/ + +#if 0 //Enable it when GRAYSCALE image is supported +static bool _rasterCompositeDirectMaskedRleImage(SwSurface* surface, const SwImage* image, SwMask maskOp, uint8_t opacity) +{ + auto span = image->rle->spans; + auto cbuffer = surface->compositor->image.buf8; + auto ctride = surface->compositor->image.stride; + + for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + auto src = image->buf8 + (span->y + image->oy) * image->stride + (span->x + image->ox); + auto cmp = &cbuffer[span->y * ctride + span->x]; + auto alpha = MULTIPLY(span->coverage, opacity); + if (alpha == 255) { + for (uint32_t x = 0; x < span->len; ++x, ++src, ++cmp) { + *cmp = maskOp(*src, *cmp, ~*src); + } + } else { + for (uint32_t x = 0; x < span->len; ++x, ++src, ++cmp) { + auto tmp = MULTIPLY(*src, alpha); + *cmp = maskOp(*src, *cmp, ~tmp); + } + } + } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); +} + + +static bool _rasterDirectDirectMaskedRleImage(SwSurface* surface, const SwImage* image, SwMask maskOp, uint8_t opacity) +{ + auto span = image->rle->spans; + auto cbuffer = surface->compositor->image.buf8; + auto ctride = surface->compositor->image.stride; + + for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + auto src = image->buf8 + (span->y + image->oy) * image->stride + (span->x + image->ox); + auto cmp = &cbuffer[span->y * ctride + span->x]; + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + auto alpha = MULTIPLY(span->coverage, opacity); + if (alpha == 255) { + for (uint32_t x = 0; x < span->len; ++x, ++src, ++cmp, ++dst) { + auto tmp = maskOp(*src, *cmp, 0); //not use alpha + *dst = INTERPOLATE8(tmp, *dst, (255 - tmp)); + } + } else { + for (uint32_t x = 0; x < span->len; ++x, ++src, ++cmp, ++dst) { + auto tmp = maskOp(MULTIPLY(*src, alpha), *cmp, 0); //not use alpha + *dst = INTERPOLATE8(tmp, *dst, (255 - tmp)); + } + } + } + return true; +} +#endif + +static bool _rasterDirectMaskedRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity) +{ +#if 0 //Enable it when GRAYSCALE image is supported + TVGLOG("SW_ENGINE", "Direct Masked(%d) Rle Image", (int)surface->compositor->method); + + //8bit masking channels composition + if (surface->channelSize != sizeof(uint8_t)) return false; + + auto maskOp = _getMaskOp(surface->compositor->method); + if (_direct(surface->compositor->method)) _rasterDirectDirectMaskedRleImage(surface, image, maskOp, opacity); + else return _rasterCompositeDirectMaskedRleImage(surface, image, maskOp, opacity); +#endif + return false; +} + + +static bool _rasterDirectMattedRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity) +{ + TVGLOG("SW_ENGINE", "Direct Matted(%d) Rle Image", (int)surface->compositor->method); + + auto span = image->rle->spans; + auto csize = surface->compositor->image.channelSize; + auto cbuffer = surface->compositor->image.buf8; + auto alpha = surface->alpha(surface->compositor->method); + + for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize]; + auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); + auto a = MULTIPLY(span->coverage, opacity); + if (a == 255) { + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img, cmp += csize) { + auto tmp = ALPHA_BLEND(*img, alpha(cmp)); + *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + } + } else { + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img, cmp += csize) { + auto tmp = ALPHA_BLEND(*img, MULTIPLY(a, alpha(cmp))); + *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + } + } + } + return true; +} + + +static bool _rasterDirectBlendingRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity) +{ + auto span = image->rle->spans; + + for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); + auto alpha = MULTIPLY(span->coverage, opacity); + if (alpha == 255) { + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) { + *dst = surface->blender(*img, *dst, IA(*img)); + } + } else if (opacity == 255) { + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) { + auto tmp = surface->blender(*img, *dst, 255); + *dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(*img))); + } + } else { + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) { + auto src = ALPHA_BLEND(*img, opacity); + auto tmp = surface->blender(src, *dst, IA(src)); + *dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(src))); + } + } + } + return true; +} + + +static bool _rasterDirectRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity) +{ + auto span = image->rle->spans; + + for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); + auto alpha = MULTIPLY(span->coverage, opacity); + if (alpha == 255) { + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) { + *dst = *img + ALPHA_BLEND(*dst, IA(*img)); + } + } else { + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) { + auto src = ALPHA_BLEND(*img, alpha); + *dst = src + ALPHA_BLEND(*dst, IA(src)); + } + } + } + return true; +} + + +static bool _directRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity) +{ + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported grayscale rle image!"); + return false; + } + + if (_compositing(surface)) { + if (_matting(surface)) return _rasterDirectMattedRleImage(surface, image, opacity); + else return _rasterDirectMaskedRleImage(surface, image, opacity); + } else if (_blending(surface)) { + return _rasterDirectBlendingRleImage(surface, image, opacity); + } else { + return _rasterDirectRleImage(surface, image, opacity); + } + return false; +} + + +/************************************************************************/ +/*Scaled Image */ +/************************************************************************/ + +#if 0 //Enable it when GRAYSCALE image is supported +static bool _rasterCompositeScaledMaskedImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwMask maskOp, uint8_t opacity) +{ + auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image->scale); + auto cstride = surface->compositor->image.stride; + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); + int32_t miny = 0, maxy = 0; + + for (auto y = region.min.y; y < region.max.y; ++y) { + SCALED_IMAGE_RANGE_Y(y) + auto cmp = cbuffer; + for (auto x = region.min.x; x < region.max.x; ++x, ++cmp) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (opacity < 255) src = MULTIPLY(src, opacity); + *cmp = maskOp(src, *cmp, ~src); + } + cbuffer += cstride; + } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); +} + + +static bool _rasterDirectScaledMaskedImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwMask maskOp, uint8_t opacity) +{ + auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image->scale); + auto cstride = surface->compositor->image.stride; + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); + auto dbuffer = surface->buf8 + (region.min.y * surface->stride + region.min.x); + int32_t miny = 0, maxy = 0; + + for (auto y = region.min.y; y < region.max.y; ++y) { + SCALED_IMAGE_RANGE_Y(y) + auto cmp = cbuffer; + auto dst = dbuffer; + for (auto x = region.min.x; x < region.max.x; ++x, ++cmp, ++dst) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (opacity < 255) src = MULTIPLY(src, opacity); + src = maskOp(src, *cmp, 0); //not use alpha + *dst = src + MULTIPLY(*dst, ~src); + } + cbuffer += cstride; + dbuffer += surface->stride; + } + return true; +} +#endif + +static bool _rasterScaledMaskedImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +{ +#if 0 //Enable it when GRAYSCALE image is supported + TVGLOG("SW_ENGINE", "Scaled Masked(%d) Image [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); + + auto maskOp = _getMaskOp(surface->compositor->method); + if (_direct(surface->compositor->method)) return _rasterDirectScaledMaskedImage(surface, image, itransform, region, maskOp, opacity); + else return _rasterCompositeScaledMaskedImage(surface, image, itransform, region, maskOp, opacity); +#endif + return false; +} + + +static bool _rasterScaledMattedImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +{ + auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x); + auto csize = surface->compositor->image.channelSize; + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; + auto alpha = surface->alpha(surface->compositor->method); + + TVGLOG("SW_ENGINE", "Scaled Matted(%d) Image [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); + + auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image->scale); + int32_t miny = 0, maxy = 0; + + for (auto y = region.min.y; y < region.max.y; ++y) { + SCALED_IMAGE_RANGE_Y(y) + auto dst = dbuffer; + auto cmp = cbuffer; + for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + auto tmp = ALPHA_BLEND(src, opacity == 255 ? alpha(cmp) : MULTIPLY(opacity, alpha(cmp))); + *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + } + dbuffer += surface->stride; + cbuffer += surface->compositor->image.stride * csize; + } + return true; +} + + +static bool _rasterScaledBlendingImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +{ + auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x); + auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image->scale); + int32_t miny = 0, maxy = 0; + + for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) { + SCALED_IMAGE_RANGE_Y(y) + auto dst = dbuffer; + for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (opacity < 255) ALPHA_BLEND(src, opacity); + auto tmp = surface->blender(src, *dst, 255); + *dst = INTERPOLATE(tmp, *dst, A(src)); + } + } + return true; +} + + +static bool _rasterScaledImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +{ + auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x); + auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image->scale); + int32_t miny = 0, maxy = 0; + + for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) { + SCALED_IMAGE_RANGE_Y(y) + auto dst = dbuffer; + for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { + SCALED_IMAGE_RANGE_X + auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + if (opacity < 255) src = ALPHA_BLEND(src, opacity); + *dst = src + ALPHA_BLEND(*dst, IA(src)); + } + } + return true; +} + + +static bool _scaledImage(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox& region, uint8_t opacity) +{ + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported grayscale Textmap polygon mesh!"); + return false; + } + + Matrix itransform; + + if (transform) { + if (!mathInverse(transform, &itransform)) return false; + } else mathIdentity(&itransform); + + if (_compositing(surface)) { + if (_matting(surface)) return _rasterScaledMattedImage(surface, image, &itransform, region, opacity); + else return _rasterScaledMaskedImage(surface, image, &itransform, region, opacity); + } else if (_blending(surface)) { + return _rasterScaledBlendingImage(surface, image, &itransform, region, opacity); + } else { + return _rasterScaledImage(surface, image, &itransform, region, opacity); + } + return false; +} + + +/************************************************************************/ +/* Direct Image */ +/************************************************************************/ + +#if 0 //Enable it when GRAYSCALE image is supported +static bool _rasterCompositeDirectMaskedImage(SwSurface* surface, const SwImage* image, const SwBBox& region, SwMask maskOp, uint8_t opacity) +{ + auto h = static_cast(region.max.y - region.min.y); + auto w = static_cast(region.max.x - region.min.x); + auto cstride = surface->compositor->image.stride; + + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); //compositor buffer + auto sbuffer = image->buf8 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + + for (uint32_t y = 0; y < h; ++y) { + auto cmp = cbuffer; + auto src = sbuffer; + if (opacity == 255) { + for (uint32_t x = 0; x < w; ++x, ++src, ++cmp) { + *cmp = maskOp(*src, *cmp, ~*src); + } + } else { + for (uint32_t x = 0; x < w; ++x, ++src, ++cmp) { + auto tmp = MULTIPLY(*src, opacity); + *cmp = maskOp(tmp, *cmp, ~tmp); + } + } + cbuffer += cstride; + sbuffer += image->stride; + } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); +} + + +static bool _rasterDirectDirectMaskedImage(SwSurface* surface, const SwImage* image, const SwBBox& region, SwMask maskOp, uint8_t opacity) +{ + auto h = static_cast(region.max.y - region.min.y); + auto w = static_cast(region.max.x - region.min.x); + auto cstride = surface->compositor->image.stride; + + auto cbuffer = surface->compositor->image.buf32 + (region.min.y * cstride + region.min.x); //compositor buffer + auto dbuffer = surface->buf8 + (region.min.y * surface->stride + region.min.x); //destination buffer + auto sbuffer = image->buf8 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + + for (uint32_t y = 0; y < h; ++y) { + auto cmp = cbuffer; + auto dst = dbuffer; + auto src = sbuffer; + if (opacity == 255) { + for (uint32_t x = 0; x < w; ++x, ++src, ++cmp, ++dst) { + auto tmp = maskOp(*src, *cmp, 0); //not use alpha + *dst = tmp + MULTIPLY(*dst, ~tmp); + } + } else { + for (uint32_t x = 0; x < w; ++x, ++src, ++cmp, ++dst) { + auto tmp = maskOp(MULTIPLY(*src, opacity), *cmp, 0); //not use alpha + *dst = tmp + MULTIPLY(*dst, ~tmp); + } + } + cbuffer += cstride; + dbuffer += surface->stride; + sbuffer += image->stride; + } + return true; +} +#endif + +static bool _rasterDirectMaskedImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) +{ + TVGERR("SW_ENGINE", "Not Supported: Direct Masked(%d) Image [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); + +#if 0 //Enable it when GRAYSCALE image is supported + auto maskOp = _getMaskOp(surface->compositor->method); + if (_direct(surface->compositor->method)) return _rasterDirectDirectMaskedImage(surface, image, region, maskOp, opacity); + else return _rasterCompositeDirectMaskedImage(surface, image, region, maskOp, opacity); +#endif + return false; +} + + +static bool _rasterDirectMattedImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) +{ + auto h = static_cast(region.max.y - region.min.y); + auto w = static_cast(region.max.x - region.min.x); + auto csize = surface->compositor->image.channelSize; + auto alpha = surface->alpha(surface->compositor->method); + auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; //compositor buffer + + TVGLOG("SW_ENGINE", "Direct Matted(%d) Image [Region: %lu %lu %u %u]", (int)surface->compositor->method, region.min.x, region.min.y, w, h); + + //32 bits + if (surface->channelSize == sizeof(uint32_t)) { + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; + for (uint32_t y = 0; y < h; ++y) { + auto dst = buffer; + auto cmp = cbuffer; + auto src = sbuffer; + if (opacity == 255) { + for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { + auto tmp = ALPHA_BLEND(*src, alpha(cmp)); + *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + } + } else { + for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { + auto tmp = ALPHA_BLEND(*src, MULTIPLY(opacity, alpha(cmp))); + *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + } + } + buffer += surface->stride; + cbuffer += surface->compositor->image.stride * csize; + sbuffer += image->stride; + } + //8 bits + } else if (surface->channelSize == sizeof(uint8_t)) { + auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x; + for (uint32_t y = 0; y < h; ++y) { + auto dst = buffer; + auto cmp = cbuffer; + auto src = sbuffer; + if (opacity == 255) { + for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { + *dst = MULTIPLY(A(*src), alpha(cmp)); + } + } else { + for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { + *dst = MULTIPLY(A(*src), MULTIPLY(opacity, alpha(cmp))); + } + } + buffer += surface->stride; + cbuffer += surface->compositor->image.stride * csize; + sbuffer += image->stride; + } + } + return true; +} + + +static bool _rasterDirectBlendingImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) +{ + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported grayscale image!"); + return false; + } + + auto dbuffer = &surface->buf32[region.min.y * surface->stride + region.min.x]; + auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + + for (auto y = region.min.y; y < region.max.y; ++y) { + auto dst = dbuffer; + auto src = sbuffer; + if (opacity == 255) { + for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) { + auto tmp = surface->blender(*src, *dst, 255); + *dst = INTERPOLATE(tmp, *dst, A(*src)); + } + } else { + for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++src) { + auto tmp = ALPHA_BLEND(*src, opacity); + auto tmp2 = surface->blender(tmp, *dst, 255); + *dst = INTERPOLATE(tmp2, *dst, A(tmp)); + } + } + dbuffer += surface->stride; + sbuffer += image->stride; + } + return true; +} + + +static bool _rasterDirectImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) +{ + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported grayscale image!"); + return false; + } + + auto dbuffer = &surface->buf32[region.min.y * surface->stride + region.min.x]; + auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + + for (auto y = region.min.y; y < region.max.y; ++y) { + auto dst = dbuffer; + auto src = sbuffer; + if (opacity == 255) { + for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) { + *dst = *src + ALPHA_BLEND(*dst, IA(*src)); + } + } else { + for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++src) { + auto tmp = ALPHA_BLEND(*src, opacity); + *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + } + } + dbuffer += surface->stride; + sbuffer += image->stride; + } + return true; +} + + +//Blenders for the following scenarios: [Composition / Non-Composition] * [Opaque / Translucent] +static bool _directImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) +{ + if (_compositing(surface)) { + if (_matting(surface)) return _rasterDirectMattedImage(surface, image, region, opacity); + else return _rasterDirectMaskedImage(surface, image, region, opacity); + } else if (_blending(surface)) { + return _rasterDirectBlendingImage(surface, image, region, opacity); + } else { + return _rasterDirectImage(surface, image, region, opacity); + } + return false; +} + + +//Blenders for the following scenarios: [RLE / Whole] * [Direct / Scaled / Transformed] +static bool _rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, const SwBBox& region, uint8_t opacity) +{ + //RLE Image + if (image->rle) { + if (image->direct) return _directRleImage(surface, image, opacity); + else if (image->scaled) return _scaledRleImage(surface, image, transform, region, opacity); + else return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity); + //Whole Image + } else { + if (image->direct) return _directImage(surface, image, region, opacity); + else if (image->scaled) return _scaledImage(surface, image, transform, region, opacity); + else return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity); + } +} + + +/************************************************************************/ +/* Rect Gradient */ +/************************************************************************/ + +template +static bool _rasterCompositeGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, SwMask maskOp) +{ + auto h = static_cast(region.max.y - region.min.y); + auto w = static_cast(region.max.x - region.min.x); + auto cstride = surface->compositor->image.stride; + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); + + for (uint32_t y = 0; y < h; ++y) { + fillMethod()(fill, cbuffer, region.min.y + y, region.min.x, w, maskOp, 255); + cbuffer += surface->stride; + } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); +} + + +template +static bool _rasterDirectGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, SwMask maskOp) +{ + auto h = static_cast(region.max.y - region.min.y); + auto w = static_cast(region.max.x - region.min.x); + auto cstride = surface->compositor->image.stride; + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); + auto dbuffer = surface->buf8 + (region.min.y * surface->stride + region.min.x); + + for (uint32_t y = 0; y < h; ++y) { + fillMethod()(fill, dbuffer, region.min.y + y, region.min.x, w, cbuffer, maskOp, 255); + cbuffer += cstride; + dbuffer += surface->stride; + } + return true; +} + + +template +static bool _rasterGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) +{ + auto method = surface->compositor->method; + + TVGLOG("SW_ENGINE", "Masked(%d) Gradient [Region: %lu %lu %lu %lu]", (int)method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); + + auto maskOp = _getMaskOp(method); + + if (_direct(method)) return _rasterDirectGradientMaskedRect(surface, region, fill, maskOp); + else return _rasterCompositeGradientMaskedRect(surface, region, fill, maskOp); + + return false; +} + + +template +static bool _rasterGradientMattedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) +{ + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; + auto h = static_cast(region.max.y - region.min.y); + auto w = static_cast(region.max.x - region.min.x); + auto csize = surface->compositor->image.channelSize; + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; + auto alpha = surface->alpha(surface->compositor->method); + + TVGLOG("SW_ENGINE", "Matted(%d) Gradient [Region: %lu %lu %u %u]", (int)surface->compositor->method, region.min.x, region.min.y, w, h); + + for (uint32_t y = 0; y < h; ++y) { + fillMethod()(fill, buffer, region.min.y + y, region.min.x, w, cbuffer, alpha, csize, 255); + buffer += surface->stride; + cbuffer += surface->stride * csize; + } + return true; +} + + +template +static bool _rasterBlendingGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) +{ + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; + auto w = static_cast(region.max.x - region.min.x); + auto h = static_cast(region.max.y - region.min.y); + + if (fill->translucent) { + for (uint32_t y = 0; y < h; ++y) { + fillMethod()(fill, buffer + y * surface->stride, region.min.y + y, region.min.x, w, opBlendPreNormal, surface->blender, 255); + } + } else { + for (uint32_t y = 0; y < h; ++y) { + fillMethod()(fill, buffer + y * surface->stride, region.min.y + y, region.min.x, w, opBlendSrcOver, surface->blender, 255); + } + } + return true; +} + +template +static bool _rasterTranslucentGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) +{ + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; + auto h = static_cast(region.max.y - region.min.y); + auto w = static_cast(region.max.x - region.min.x); + + for (uint32_t y = 0; y < h; ++y) { + fillMethod()(fill, buffer, region.min.y + y, region.min.x, w, opBlendPreNormal, 255); + buffer += surface->stride; + } + return true; +} + + +template +static bool _rasterSolidGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) +{ + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; + auto w = static_cast(region.max.x - region.min.x); + auto h = static_cast(region.max.y - region.min.y); + + for (uint32_t y = 0; y < h; ++y) { + fillMethod()(fill, buffer + y * surface->stride, region.min.y + y, region.min.x, w, opBlendSrcOver, 255); + } + return true; +} + + +static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) +{ + if (fill->linear.len < FLT_EPSILON) return false; + + if (_compositing(surface)) { + if (_matting(surface)) return _rasterGradientMattedRect(surface, region, fill); + else return _rasterGradientMaskedRect(surface, region, fill); + } else if (_blending(surface)) { + return _rasterBlendingGradientRect(surface, region, fill); + } else { + if (fill->translucent) return _rasterTranslucentGradientRect(surface, region, fill); + else _rasterSolidGradientRect(surface, region, fill); + } + return false; +} + + +static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) +{ + if (_compositing(surface)) { + if (_matting(surface)) return _rasterGradientMattedRect(surface, region, fill); + else return _rasterGradientMaskedRect(surface, region, fill); + } else if (_blending(surface)) { + return _rasterBlendingGradientRect(surface, region, fill); + } else { + if (fill->translucent) return _rasterTranslucentGradientRect(surface, region, fill); + else _rasterSolidGradientRect(surface, region, fill); + } + return false; +} + + +/************************************************************************/ +/* Rle Gradient */ +/************************************************************************/ + +template +static bool _rasterCompositeGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, SwMask maskOp) +{ + auto span = rle->spans; + auto cstride = surface->compositor->image.stride; + auto cbuffer = surface->compositor->image.buf8; + + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto cmp = &cbuffer[span->y * cstride + span->x]; + fillMethod()(fill, cmp, span->y, span->x, span->len, maskOp, span->coverage); + } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); +} + + +template +static bool _rasterDirectGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, SwMask maskOp) +{ + auto span = rle->spans; + auto cstride = surface->compositor->image.stride; + auto cbuffer = surface->compositor->image.buf8; + auto dbuffer = surface->buf8; + + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto cmp = &cbuffer[span->y * cstride + span->x]; + auto dst = &dbuffer[span->y * surface->stride + span->x]; + fillMethod()(fill, dst, span->y, span->x, span->len, cmp, maskOp, span->coverage); + } + return true; +} + + +template +static bool _rasterGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) +{ + auto method = surface->compositor->method; + + TVGLOG("SW_ENGINE", "Masked(%d) Rle Linear Gradient", (int)method); + + auto maskOp = _getMaskOp(method); + + if (_direct(method)) return _rasterDirectGradientMaskedRle(surface, rle, fill, maskOp); + else return _rasterCompositeGradientMaskedRle(surface, rle, fill, maskOp); + return false; +} + + +template +static bool _rasterGradientMattedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) +{ + TVGLOG("SW_ENGINE", "Matted(%d) Rle Linear Gradient", (int)surface->compositor->method); + + auto span = rle->spans; + auto csize = surface->compositor->image.channelSize; + auto cbuffer = surface->compositor->image.buf8; + auto alpha = surface->alpha(surface->compositor->method); + + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize]; + fillMethod()(fill, dst, span->y, span->x, span->len, cmp, alpha, csize, span->coverage); + } + return true; +} + + +template +static bool _rasterBlendingGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) +{ + auto span = rle->spans; + + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + fillMethod()(fill, dst, span->y, span->x, span->len, opBlendPreNormal, surface->blender, span->coverage); + } + return true; +} + + +template +static bool _rasterTranslucentGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) +{ + auto span = rle->spans; + + //32 bits + if (surface->channelSize == sizeof(uint32_t)) { + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, opBlendPreNormal, 255); + else fillMethod()(fill, dst, span->y, span->x, span->len, opBlendNormal, span->coverage); + } + //8 bits + } else if (surface->channelSize == sizeof(uint8_t)) { + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + fillMethod()(fill, dst, span->y, span->x, span->len, _opMaskAdd, 255); + } + } + return true; +} + + +template +static bool _rasterSolidGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) +{ + auto span = rle->spans; + + //32 bits + if (surface->channelSize == sizeof(uint32_t)) { + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, opBlendSrcOver, 255); + else fillMethod()(fill, dst, span->y, span->x, span->len, opBlendInterp, span->coverage); + } + //8 bits + } else if (surface->channelSize == sizeof(uint8_t)) { + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, _opMaskNone, 255); + else fillMethod()(fill, dst, span->y, span->x, span->len, _opMaskAdd, span->coverage); + } + } + + return true; +} + + +static bool _rasterLinearGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) +{ + if (!rle || fill->linear.len < FLT_EPSILON) return false; + + if (_compositing(surface)) { + if (_matting(surface)) return _rasterGradientMattedRle(surface, rle, fill); + else return _rasterGradientMaskedRle(surface, rle, fill); + } else if (_blending(surface)) { + return _rasterBlendingGradientRle(surface, rle, fill); + } else { + if (fill->translucent) return _rasterTranslucentGradientRle(surface, rle, fill); + else return _rasterSolidGradientRle(surface, rle, fill); + } + return false; +} + + +static bool _rasterRadialGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) +{ + if (!rle) return false; + + if (_compositing(surface)) { + if (_matting(surface)) return _rasterGradientMattedRle(surface, rle, fill); + else return _rasterGradientMaskedRle(surface, rle, fill); + } else if (_blending(surface)) { + _rasterBlendingGradientRle(surface, rle, fill); + } else { + if (fill->translucent) _rasterTranslucentGradientRle(surface, rle, fill); + else return _rasterSolidGradientRle(surface, rle, fill); + } + return false; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + + +void rasterGrayscale8(uint8_t *dst, uint8_t val, uint32_t offset, int32_t len) +{ + //OPTIMIZE_ME: Support SIMD + cRasterPixels(dst, val, offset, len); +} + + +void rasterPixel32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len) +{ +#if defined(THORVG_AVX_VECTOR_SUPPORT) + avxRasterPixel32(dst, val, offset, len); +#elif defined(THORVG_NEON_VECTOR_SUPPORT) + neonRasterPixel32(dst, val, offset, len); +#else + cRasterPixels(dst, val, offset, len); +#endif +} + + +bool rasterCompositor(SwSurface* surface) +{ + //See CompositeMethod, Alpha:3, InvAlpha:4, Luma:5, InvLuma:6 + surface->alphas[0] = _alpha; + surface->alphas[1] = _ialpha; + + if (surface->cs == ColorSpace::ABGR8888 || surface->cs == ColorSpace::ABGR8888S) { + surface->join = _abgrJoin; + surface->alphas[2] = _abgrLuma; + surface->alphas[3] = _abgrInvLuma; + } else if (surface->cs == ColorSpace::ARGB8888 || surface->cs == ColorSpace::ARGB8888S) { + surface->join = _argbJoin; + surface->alphas[2] = _argbLuma; + surface->alphas[3] = _argbInvLuma; + } else { + TVGERR("SW_ENGINE", "Unsupported Colorspace(%d) is expected!", surface->cs); + return false; + } + return true; +} + + +bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h) +{ + if (!surface || !surface->buf32 || surface->stride == 0 || surface->w == 0 || surface->h == 0) return false; + + //32 bits + if (surface->channelSize == sizeof(uint32_t)) { + //full clear + if (w == surface->stride) { + rasterPixel32(surface->buf32, 0x00000000, surface->stride * y, w * h); + //partial clear + } else { + for (uint32_t i = 0; i < h; i++) { + rasterPixel32(surface->buf32, 0x00000000, (surface->stride * y + x) + (surface->stride * i), w); + } + } + //8 bits + } else if (surface->channelSize == sizeof(uint8_t)) { + //full clear + if (w == surface->stride) { + rasterGrayscale8(surface->buf8, 0x00, surface->stride * y, w * h); + //partial clear + } else { + for (uint32_t i = 0; i < h; i++) { + rasterGrayscale8(surface->buf8, 0x00, (surface->stride * y + x) + (surface->stride * i), w); + } + } + } + return true; +} + + +void rasterUnpremultiply(Surface* surface) +{ + if (surface->channelSize != sizeof(uint32_t)) return; + + TVGLOG("SW_ENGINE", "Unpremultiply [Size: %d x %d]", surface->w, surface->h); + + //OPTIMIZE_ME: +SIMD + for (uint32_t y = 0; y < surface->h; y++) { + auto buffer = surface->buf32 + surface->stride * y; + for (uint32_t x = 0; x < surface->w; ++x) { + uint8_t a = buffer[x] >> 24; + if (a == 255) { + continue; + } else if (a == 0) { + buffer[x] = 0x00ffffff; + } else { + uint16_t r = ((buffer[x] >> 8) & 0xff00) / a; + uint16_t g = ((buffer[x]) & 0xff00) / a; + uint16_t b = ((buffer[x] << 8) & 0xff00) / a; + if (r > 0xff) r = 0xff; + if (g > 0xff) g = 0xff; + if (b > 0xff) b = 0xff; + buffer[x] = (a << 24) | (r << 16) | (g << 8) | (b); + } + } + } + surface->premultiplied = false; +} + + +void rasterPremultiply(Surface* surface) +{ + if (surface->channelSize != sizeof(uint32_t)) return; + + TVGLOG("SW_ENGINE", "Premultiply [Size: %d x %d]", surface->w, surface->h); + + //OPTIMIZE_ME: +SIMD + auto buffer = surface->buf32; + for (uint32_t y = 0; y < surface->h; ++y, buffer += surface->stride) { + auto dst = buffer; + for (uint32_t x = 0; x < surface->w; ++x, ++dst) { + auto c = *dst; + auto a = (c >> 24); + *dst = (c & 0xff000000) + ((((c >> 8) & 0xff) * a) & 0xff00) + ((((c & 0x00ff00ff) * a) >> 8) & 0x00ff00ff); + } + } + surface->premultiplied = true; +} + + +bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id) +{ + if (!shape->fill) return false; + + if (shape->fastTrack) { + if (id == TVG_CLASS_ID_LINEAR) return _rasterLinearGradientRect(surface, shape->bbox, shape->fill); + else if (id == TVG_CLASS_ID_RADIAL)return _rasterRadialGradientRect(surface, shape->bbox, shape->fill); + } else { + if (id == TVG_CLASS_ID_LINEAR) return _rasterLinearGradientRle(surface, shape->rle, shape->fill); + else if (id == TVG_CLASS_ID_RADIAL) return _rasterRadialGradientRle(surface, shape->rle, shape->fill); + } + return false; +} + + +bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id) +{ + if (!shape->stroke || !shape->stroke->fill || !shape->strokeRle) return false; + + if (id == TVG_CLASS_ID_LINEAR) return _rasterLinearGradientRle(surface, shape->strokeRle, shape->stroke->fill); + else if (id == TVG_CLASS_ID_RADIAL) return _rasterRadialGradientRle(surface, shape->strokeRle, shape->stroke->fill); + + return false; +} + + +bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + if (a < 255) { + r = MULTIPLY(r, a); + g = MULTIPLY(g, a); + b = MULTIPLY(b, a); + } + if (shape->fastTrack) return _rasterRect(surface, shape->bbox, r, g, b, a); + else return _rasterRle(surface, shape->rle, r, g, b, a); +} + + +bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + if (a < 255) { + r = MULTIPLY(r, a); + g = MULTIPLY(g, a); + b = MULTIPLY(b, a); + } + + return _rasterRle(surface, shape->strokeRle, r, g, b, a); +} + + +bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& bbox, uint8_t opacity) +{ + //Verify Boundary + if (bbox.max.x < 0 || bbox.max.y < 0 || bbox.min.x >= static_cast(surface->w) || bbox.min.y >= static_cast(surface->h)) return false; + + if (mesh && mesh->triangleCnt > 0) return _rasterTexmapPolygonMesh(surface, image, mesh, transform, &bbox, opacity); + else return _rasterImage(surface, image, transform, bbox, opacity); +} + + +bool rasterConvertCS(Surface* surface, ColorSpace to) +{ + //TOOD: Support SIMD accelerations + auto from = surface->cs; + + if (((from == ColorSpace::ABGR8888) || (from == ColorSpace::ABGR8888S)) && ((to == ColorSpace::ARGB8888) || (to == ColorSpace::ARGB8888S))) { + surface->cs = to; + return cRasterABGRtoARGB(surface); + } + if (((from == ColorSpace::ARGB8888) || (from == ColorSpace::ARGB8888S)) && ((to == ColorSpace::ABGR8888) || (to == ColorSpace::ABGR8888S))) { + surface->cs = to; + return cRasterARGBtoABGR(surface); + } + + return false; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterAvx.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterAvx.h new file mode 100644 index 000000000..633abf1db --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterAvx.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifdef THORVG_AVX_VECTOR_SUPPORT + +#include + +#define N_32BITS_IN_128REG 4 +#define N_32BITS_IN_256REG 8 + +static inline __m128i ALPHA_BLEND(__m128i c, __m128i a) +{ + //1. set the masks for the A/G and R/B channels + auto AG = _mm_set1_epi32(0xff00ff00); + auto RB = _mm_set1_epi32(0x00ff00ff); + + //2. mask the alpha vector - originally quartet [a, a, a, a] + auto aAG = _mm_and_si128(a, AG); + auto aRB = _mm_and_si128(a, RB); + + //3. calculate the alpha blending of the 2nd and 4th channel + //- mask the color vector + //- multiply it by the masked alpha vector + //- add the correction to compensate bit shifting used instead of dividing by 255 + //- shift bits - corresponding to division by 256 + auto even = _mm_and_si128(c, RB); + even = _mm_mullo_epi16(even, aRB); + even =_mm_add_epi16(even, RB); + even = _mm_srli_epi16(even, 8); + + //4. calculate the alpha blending of the 1st and 3rd channel: + //- mask the color vector + //- multiply it by the corresponding masked alpha vector and store the high bits of the result + //- add the correction to compensate division by 256 instead of by 255 (next step) + //- remove the low 8 bits to mimic the division by 256 + auto odd = _mm_and_si128(c, AG); + odd = _mm_mulhi_epu16(odd, aAG); + odd = _mm_add_epi16(odd, RB); + odd = _mm_and_si128(odd, AG); + + //5. the final result + return _mm_or_si128(odd, even); +} + + +static void avxRasterPixel32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len) +{ + //1. calculate how many iterations we need to cover the length + uint32_t iterations = len / N_32BITS_IN_256REG; + uint32_t avxFilled = iterations * N_32BITS_IN_256REG; + + //2. set the beginning of the array + dst += offset; + + //3. fill the octets + for (uint32_t i = 0; i < iterations; ++i, dst += N_32BITS_IN_256REG) { + _mm256_storeu_si256((__m256i*)dst, _mm256_set1_epi32(val)); + } + + //4. fill leftovers (in the first step we have to set the pointer to the place where the avx job is done) + int32_t leftovers = len - avxFilled; + while (leftovers--) *dst++ = val; +} + + +static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + if (surface->channelSize != sizeof(uint32_t)) { + TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize); + return false; + } + + auto color = surface->join(r, g, b, a); + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; + auto h = static_cast(region.max.y - region.min.y); + auto w = static_cast(region.max.x - region.min.x); + + uint32_t ialpha = 255 - a; + + auto avxColor = _mm_set1_epi32(color); + auto avxIalpha = _mm_set1_epi8(ialpha); + + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface->stride]; + + //1. fill the not aligned memory (for 128-bit registers a 16-bytes alignment is required) + auto notAligned = ((uintptr_t)dst & 0xf) / 4; + if (notAligned) { + notAligned = (N_32BITS_IN_128REG - notAligned > w ? w : N_32BITS_IN_128REG - notAligned); + for (uint32_t x = 0; x < notAligned; ++x, ++dst) { + *dst = color + ALPHA_BLEND(*dst, ialpha); + } + } + + //2. fill the aligned memory - N_32BITS_IN_128REG pixels processed at once + uint32_t iterations = (w - notAligned) / N_32BITS_IN_128REG; + uint32_t avxFilled = iterations * N_32BITS_IN_128REG; + auto avxDst = (__m128i*)dst; + for (uint32_t x = 0; x < iterations; ++x, ++avxDst) { + *avxDst = _mm_add_epi32(avxColor, ALPHA_BLEND(*avxDst, avxIalpha)); + } + + //3. fill the remaining pixels + int32_t leftovers = w - notAligned - avxFilled; + dst += avxFilled; + while (leftovers--) { + *dst = color + ALPHA_BLEND(*dst, ialpha); + dst++; + } + } + return true; +} + + +static bool avxRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + if (surface->channelSize != sizeof(uint32_t)) { + TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize); + return false; + } + + auto color = surface->join(r, g, b, a); + auto span = rle->spans; + uint32_t src; + + for (uint32_t i = 0; i < rle->size; ++i) { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + + if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage); + else src = color; + + auto ialpha = IA(src); + + //1. fill the not aligned memory (for 128-bit registers a 16-bytes alignment is required) + auto notAligned = ((uintptr_t)dst & 0xf) / 4; + if (notAligned) { + notAligned = (N_32BITS_IN_128REG - notAligned > span->len ? span->len : N_32BITS_IN_128REG - notAligned); + for (uint32_t x = 0; x < notAligned; ++x, ++dst) { + *dst = src + ALPHA_BLEND(*dst, ialpha); + } + } + + //2. fill the aligned memory using avx - N_32BITS_IN_128REG pixels processed at once + //In order to avoid unneccessary avx variables declarations a check is made whether there are any iterations at all + uint32_t iterations = (span->len - notAligned) / N_32BITS_IN_128REG; + uint32_t avxFilled = 0; + if (iterations > 0) { + auto avxSrc = _mm_set1_epi32(src); + auto avxIalpha = _mm_set1_epi8(ialpha); + + avxFilled = iterations * N_32BITS_IN_128REG; + auto avxDst = (__m128i*)dst; + for (uint32_t x = 0; x < iterations; ++x, ++avxDst) { + *avxDst = _mm_add_epi32(avxSrc, ALPHA_BLEND(*avxDst, avxIalpha)); + } + } + + //3. fill the remaining pixels + int32_t leftovers = span->len - notAligned - avxFilled; + dst += avxFilled; + while (leftovers--) { + *dst = src + ALPHA_BLEND(*dst, ialpha); + dst++; + } + + ++span; + } + return true; +} + + +#endif + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterC.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterC.h new file mode 100644 index 000000000..c7f2840f8 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterC.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +template +static void inline cRasterPixels(PIXEL_T* dst, PIXEL_T val, uint32_t offset, int32_t len) +{ + dst += offset; + + //fix the misaligned memory + auto alignOffset = (long long) dst % 8; + if (alignOffset > 0) { + if (sizeof(PIXEL_T) == 4) alignOffset /= 4; + else if (sizeof(PIXEL_T) == 1) alignOffset = 8 - alignOffset; + while (alignOffset > 0 && len > 0) { + *dst++ = val; + --len; + --alignOffset; + } + } + + //64bits faster clear + if ((sizeof(PIXEL_T) == 4)) { + auto val64 = (uint64_t(val) << 32) | uint64_t(val); + while (len > 1) { + *reinterpret_cast(dst) = val64; + len -= 2; + dst += 2; + } + } else if (sizeof(PIXEL_T) == 1) { + auto val32 = (uint32_t(val) << 24) | (uint32_t(val) << 16) | (uint32_t(val) << 8) | uint32_t(val); + auto val64 = (uint64_t(val32) << 32) | val32; + while (len > 7) { + *reinterpret_cast(dst) = val64; + len -= 8; + dst += 8; + } + } + + //leftovers + while (len--) *dst++ = val; +} + + +static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + auto span = rle->spans; + + //32bit channels + if (surface->channelSize == sizeof(uint32_t)) { + auto color = surface->join(r, g, b, a); + uint32_t src; + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage); + else src = color; + auto ialpha = IA(src); + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + *dst = src + ALPHA_BLEND(*dst, ialpha); + } + } + //8bit grayscale + } else if (surface->channelSize == sizeof(uint8_t)) { + uint8_t src; + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + if (span->coverage < 255) src = MULTIPLY(span->coverage, a); + else src = a; + auto ialpha = ~a; + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + *dst = src + MULTIPLY(*dst, ialpha); + } + } + } + return true; +} + + +static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + auto h = static_cast(region.max.y - region.min.y); + auto w = static_cast(region.max.x - region.min.x); + + //32bits channels + if (surface->channelSize == sizeof(uint32_t)) { + auto color = surface->join(r, g, b, a); + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; + auto ialpha = 255 - a; + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface->stride]; + for (uint32_t x = 0; x < w; ++x, ++dst) { + *dst = color + ALPHA_BLEND(*dst, ialpha); + } + } + //8bit grayscale + } else if (surface->channelSize == sizeof(uint8_t)) { + auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x; + auto ialpha = ~a; + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface->stride]; + for (uint32_t x = 0; x < w; ++x, ++dst) { + *dst = a + MULTIPLY(*dst, ialpha); + } + } + } + return true; +} + + +static bool inline cRasterABGRtoARGB(Surface* surface) +{ + TVGLOG("SW_ENGINE", "Convert ColorSpace ABGR - ARGB [Size: %d x %d]", surface->w, surface->h); + + //64bits faster converting + if (surface->w % 2 == 0) { + auto buffer = reinterpret_cast(surface->buf32); + for (uint32_t y = 0; y < surface->h; ++y, buffer += surface->stride / 2) { + auto dst = buffer; + for (uint32_t x = 0; x < surface->w / 2; ++x, ++dst) { + auto c = *dst; + //flip Blue, Red channels + *dst = (c & 0xff000000ff000000) + ((c & 0x00ff000000ff0000) >> 16) + (c & 0x0000ff000000ff00) + ((c & 0x000000ff000000ff) << 16); + } + } + //default converting + } else { + auto buffer = surface->buf32; + for (uint32_t y = 0; y < surface->h; ++y, buffer += surface->stride) { + auto dst = buffer; + for (uint32_t x = 0; x < surface->w; ++x, ++dst) { + auto c = *dst; + //flip Blue, Red channels + *dst = (c & 0xff000000) + ((c & 0x00ff0000) >> 16) + (c & 0x0000ff00) + ((c & 0x000000ff) << 16); + } + } + } + return true; +} + + +static bool inline cRasterARGBtoABGR(Surface* surface) +{ + //exactly same with ABGRtoARGB + return cRasterABGRtoARGB(surface); +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterNeon.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterNeon.h new file mode 100644 index 000000000..97e4706a3 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterNeon.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifdef THORVG_NEON_VECTOR_SUPPORT + +#include + +static inline uint8x8_t ALPHA_BLEND(uint8x8_t c, uint8x8_t a) +{ + uint16x8_t t = vmull_u8(c, a); + return vshrn_n_u16(t, 8); +} + + +static void neonRasterPixel32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len) +{ + uint32_t iterations = len / 4; + uint32_t neonFilled = iterations * 4; + + dst += offset; + uint32x4_t vectorVal = {val, val, val, val}; + + for (uint32_t i = 0; i < iterations; ++i) { + vst1q_u32(dst, vectorVal); + dst += 4; + } + + int32_t leftovers = len - neonFilled; + while (leftovers--) *dst++ = val; +} + + +static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + if (surface->channelSize != sizeof(uint32_t)) { + TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize); + return false; + } + + auto color = surface->blender.join(r, g, b, a); + auto span = rle->spans; + uint32_t src; + uint8x8_t *vDst = nullptr; + uint16_t align; + + for (uint32_t i = 0; i < rle->size; ++i) { + if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage); + else src = color; + + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + auto ialpha = IALPHA(src); + + if ((((uint32_t) dst) & 0x7) != 0) { + //fill not aligned byte + *dst = src + ALPHA_BLEND(*dst, ialpha); + vDst = (uint8x8_t*)(dst + 1); + align = 1; + } else { + vDst = (uint8x8_t*) dst; + align = 0; + } + + uint8x8_t vSrc = (uint8x8_t) vdup_n_u32(src); + uint8x8_t vIalpha = vdup_n_u8((uint8_t) ialpha); + + for (uint32_t x = 0; x < (span->len - align) / 2; ++x) + vDst[x] = vadd_u8(vSrc, ALPHA_BLEND(vDst[x], vIalpha)); + + auto leftovers = (span->len - align) % 2; + if (leftovers > 0) dst[span->len - 1] = src + ALPHA_BLEND(dst[span->len - 1], ialpha); + + ++span; + } + return true; +} + + +static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + if (surface->channelSize != sizeof(uint32_t)) { + TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize); + return false; + } + + auto color = surface->blender.join(r, g, b, a); + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; + auto h = static_cast(region.max.y - region.min.y); + auto w = static_cast(region.max.x - region.min.x); + auto ialpha = 255 - a; + + auto vColor = vdup_n_u32(color); + auto vIalpha = vdup_n_u8((uint8_t) ialpha); + + uint8x8_t* vDst = nullptr; + uint32_t align; + + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface->stride]; + + if ((((uint32_t) dst) & 0x7) != 0) { + //fill not aligned byte + *dst = color + ALPHA_BLEND(*dst, ialpha); + vDst = (uint8x8_t*) (dst + 1); + align = 1; + } else { + vDst = (uint8x8_t*) dst; + align = 0; + } + + for (uint32_t x = 0; x < (w - align) / 2; ++x) + vDst[x] = vadd_u8((uint8x8_t)vColor, ALPHA_BLEND(vDst[x], vIalpha)); + + auto leftovers = (w - align) % 2; + if (leftovers > 0) dst[w - 1] = color + ALPHA_BLEND(dst[w - 1], ialpha); + } + return true; +} + +#endif + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterTexmap.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterTexmap.h new file mode 100644 index 000000000..d7353c7c2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRasterTexmap.h @@ -0,0 +1,1213 @@ +/* + * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +struct AALine +{ + int32_t x[2]; + int32_t coverage[2]; + int32_t length[2]; +}; + +struct AASpans +{ + AALine *lines; + int32_t yStart; + int32_t yEnd; +}; + +static inline void _swap(float& a, float& b, float& tmp) +{ + tmp = a; + a = b; + b = tmp; +} + + +//Careful! Shared resource, No support threading +static float dudx, dvdx; +static float dxdya, dxdyb, dudya, dvdya; +static float xa, xb, ua, va; + + +//Y Range exception handling +static bool _arrange(const SwImage* image, const SwBBox* region, int& yStart, int& yEnd) +{ + int32_t regionTop, regionBottom; + + if (region) { + regionTop = region->min.y; + regionBottom = region->max.y; + } else { + regionTop = image->rle->spans->y; + regionBottom = image->rle->spans[image->rle->size - 1].y; + } + + if (yStart >= regionBottom) return false; + + if (yStart < regionTop) yStart = regionTop; + if (yEnd > regionBottom) yEnd = regionBottom; + + return true; +} + + +static bool _rasterMaskedPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, AASpans* aaSpans, uint8_t opacity, uint8_t dirFlag = 0) +{ + return false; + +#if 0 //Enable it when GRAYSCALE image is supported + auto maskOp = _getMaskOp(surface->compositor->method); + auto direct = _direct(surface->compositor->method); + float _dudx = dudx, _dvdx = dvdx; + float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya; + float _xa = xa, _xb = xb, _ua = ua, _va = va; + auto sbuf = image->buf8; + int32_t sw = static_cast(image->stride); + int32_t sh = image->h; + int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay; + int32_t vv = 0, uu = 0; + int32_t minx = INT32_MAX, maxx = INT32_MIN; + float dx, u, v, iptr; + SwSpan* span = nullptr; //used only when rle based. + + if (!_arrange(image, region, yStart, yEnd)) return false; + + //Loop through all lines in the segment + uint32_t spanIdx = 0; + + if (region) { + minx = region->min.x; + maxx = region->max.x; + } else { + span = image->rle->spans; + while (span->y < yStart) { + ++span; + ++spanIdx; + } + } + + y = yStart; + + while (y < yEnd) { + x1 = (int32_t)_xa; + x2 = (int32_t)_xb; + + if (!region) { + minx = INT32_MAX; + maxx = INT32_MIN; + //one single row, could be consisted of multiple spans. + while (span->y == y && spanIdx < image->rle->size) { + if (minx > span->x) minx = span->x; + if (maxx < span->x + span->len) maxx = span->x + span->len; + ++span; + ++spanIdx; + } + } + if (x1 < minx) x1 = minx; + if (x2 > maxx) x2 = maxx; + + //Anti-Aliasing frames + ay = y - aaSpans->yStart; + if (aaSpans->lines[ay].x[0] > x1) aaSpans->lines[ay].x[0] = x1; + if (aaSpans->lines[ay].x[1] < x2) aaSpans->lines[ay].x[1] = x2; + + //Range allowed + if ((x2 - x1) >= 1 && (x1 < maxx) && (x2 > minx)) { + + //Perform subtexel pre-stepping on UV + dx = 1 - (_xa - x1); + u = _ua + dx * _dudx; + v = _va + dx * _dvdx; + + x = x1; + + auto cmp = &surface->compositor->image.buf8[y * surface->compositor->image.stride + x1]; + auto dst = &surface->buf8[y * surface->stride + x1]; + + if (opacity == 255) { + //Draw horizontal line + while (x++ < x2) { + uu = (int) u; + if (uu >= sw) continue; + vv = (int) v; + if (vv >= sh) continue; + + ar = (int)(255 * (1 - modff(u, &iptr))); + ab = (int)(255 * (1 - modff(v, &iptr))); + iru = uu + 1; + irv = vv + 1; + + px = *(sbuf + (vv * sw) + uu); + + /* horizontal interpolate */ + if (iru < sw) { + /* right pixel */ + int px2 = *(sbuf + (vv * sw) + iru); + px = INTERPOLATE(px, px2, ar); + } + /* vertical interpolate */ + if (irv < sh) { + /* bottom pixel */ + int px2 = *(sbuf + (irv * sw) + uu); + + /* horizontal interpolate */ + if (iru < sw) { + /* bottom right pixel */ + int px3 = *(sbuf + (irv * sw) + iru); + px2 = INTERPOLATE(px2, px3, ar); + } + px = INTERPOLATE(px, px2, ab); + } + if (direct) { + auto tmp = maskOp(px, *cmp, 0); //not use alpha + *dst = tmp + MULTIPLY(*dst, ~tmp); + ++dst; + } else { + *cmp = maskOp(px, *cmp, ~px); + } + ++cmp; + + //Step UV horizontally + u += _dudx; + v += _dvdx; + //range over? + if ((uint32_t)v >= image->h) break; + } + } else { + //Draw horizontal line + while (x++ < x2) { + uu = (int) u; + if (uu >= sw) continue; + vv = (int) v; + if (vv >= sh) continue; + + ar = (int)(255 * (1 - modff(u, &iptr))); + ab = (int)(255 * (1 - modff(v, &iptr))); + iru = uu + 1; + irv = vv + 1; + + px = *(sbuf + (vv * sw) + uu); + + /* horizontal interpolate */ + if (iru < sw) { + /* right pixel */ + int px2 = *(sbuf + (vv * sw) + iru); + px = INTERPOLATE(px, px2, ar); + } + /* vertical interpolate */ + if (irv < sh) { + /* bottom pixel */ + int px2 = *(sbuf + (irv * sw) + uu); + + /* horizontal interpolate */ + if (iru < sw) { + /* bottom right pixel */ + int px3 = *(sbuf + (irv * sw) + iru); + px2 = INTERPOLATE(px2, px3, ar); + } + px = INTERPOLATE(px, px2, ab); + } + + if (direct) { + auto tmp = maskOp(MULTIPLY(px, opacity), *cmp, 0); + *dst = tmp + MULTIPLY(*dst, ~tmp); + ++dst; + } else { + auto tmp = MULTIPLY(px, opacity); + *cmp = maskOp(tmp, *cmp, ~px); + } + ++cmp; + + //Step UV horizontally + u += _dudx; + v += _dvdx; + //range over? + if ((uint32_t)v >= image->h) break; + } + } + } + + //Step along both edges + _xa += _dxdya; + _xb += _dxdyb; + _ua += _dudya; + _va += _dvdya; + + if (!region && spanIdx >= image->rle->size) break; + + ++y; + } + xa = _xa; + xb = _xb; + ua = _ua; + va = _va; + + return true; +#endif +} + + +static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, AASpans* aaSpans, uint8_t opacity) +{ + float _dudx = dudx, _dvdx = dvdx; + float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya; + float _xa = xa, _xb = xb, _ua = ua, _va = va; + auto sbuf = image->buf32; + auto dbuf = surface->buf32; + int32_t sw = static_cast(image->stride); + int32_t sh = image->h; + int32_t dw = surface->stride; + int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay; + int32_t vv = 0, uu = 0; + int32_t minx = INT32_MAX, maxx = INT32_MIN; + float dx, u, v, iptr; + uint32_t* buf; + SwSpan* span = nullptr; //used only when rle based. + + if (!_arrange(image, region, yStart, yEnd)) return; + + //Loop through all lines in the segment + uint32_t spanIdx = 0; + + if (region) { + minx = region->min.x; + maxx = region->max.x; + } else { + span = image->rle->spans; + while (span->y < yStart) { + ++span; + ++spanIdx; + } + } + + y = yStart; + + while (y < yEnd) { + x1 = (int32_t)_xa; + x2 = (int32_t)_xb; + + if (!region) { + minx = INT32_MAX; + maxx = INT32_MIN; + //one single row, could be consisted of multiple spans. + while (span->y == y && spanIdx < image->rle->size) { + if (minx > span->x) minx = span->x; + if (maxx < span->x + span->len) maxx = span->x + span->len; + ++span; + ++spanIdx; + } + } + if (x1 < minx) x1 = minx; + if (x2 > maxx) x2 = maxx; + + //Anti-Aliasing frames + ay = y - aaSpans->yStart; + if (aaSpans->lines[ay].x[0] > x1) aaSpans->lines[ay].x[0] = x1; + if (aaSpans->lines[ay].x[1] < x2) aaSpans->lines[ay].x[1] = x2; + + //Range allowed + if ((x2 - x1) >= 1 && (x1 < maxx) && (x2 > minx)) { + + //Perform subtexel pre-stepping on UV + dx = 1 - (_xa - x1); + u = _ua + dx * _dudx; + v = _va + dx * _dvdx; + + buf = dbuf + ((y * dw) + x1); + + x = x1; + + if (opacity == 255) { + //Draw horizontal line + while (x++ < x2) { + uu = (int) u; + if (uu >= sw) continue; + vv = (int) v; + if (vv >= sh) continue; + + ar = (int)(255 * (1 - modff(u, &iptr))); + ab = (int)(255 * (1 - modff(v, &iptr))); + iru = uu + 1; + irv = vv + 1; + + px = *(sbuf + (vv * sw) + uu); + + /* horizontal interpolate */ + if (iru < sw) { + /* right pixel */ + int px2 = *(sbuf + (vv * sw) + iru); + px = INTERPOLATE(px, px2, ar); + } + /* vertical interpolate */ + if (irv < sh) { + /* bottom pixel */ + int px2 = *(sbuf + (irv * sw) + uu); + + /* horizontal interpolate */ + if (iru < sw) { + /* bottom right pixel */ + int px3 = *(sbuf + (irv * sw) + iru); + px2 = INTERPOLATE(px2, px3, ar); + } + px = INTERPOLATE(px, px2, ab); + } + *buf = surface->blender(px, *buf, IA(px)); + ++buf; + + //Step UV horizontally + u += _dudx; + v += _dvdx; + //range over? + if ((uint32_t)v >= image->h) break; + } + } else { + //Draw horizontal line + while (x++ < x2) { + uu = (int) u; + if (uu >= sw) continue; + vv = (int) v; + if (vv >= sh) continue; + + ar = (int)(255 * (1 - modff(u, &iptr))); + ab = (int)(255 * (1 - modff(v, &iptr))); + iru = uu + 1; + irv = vv + 1; + + px = *(sbuf + (vv * sw) + uu); + + /* horizontal interpolate */ + if (iru < sw) { + /* right pixel */ + int px2 = *(sbuf + (vv * sw) + iru); + px = INTERPOLATE(px, px2, ar); + } + /* vertical interpolate */ + if (irv < sh) { + /* bottom pixel */ + int px2 = *(sbuf + (irv * sw) + uu); + + /* horizontal interpolate */ + if (iru < sw) { + /* bottom right pixel */ + int px3 = *(sbuf + (irv * sw) + iru); + px2 = INTERPOLATE(px2, px3, ar); + } + px = INTERPOLATE(px, px2, ab); + } + auto src = ALPHA_BLEND(px, opacity); + *buf = surface->blender(src, *buf, IA(src)); + ++buf; + + //Step UV horizontally + u += _dudx; + v += _dvdx; + //range over? + if ((uint32_t)v >= image->h) break; + } + } + } + + //Step along both edges + _xa += _dxdya; + _xb += _dxdyb; + _ua += _dudya; + _va += _dvdya; + + if (!region && spanIdx >= image->rle->size) break; + + ++y; + } + xa = _xa; + xb = _xb; + ua = _ua; + va = _va; +} + + +static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, AASpans* aaSpans, uint8_t opacity, bool matting) +{ + float _dudx = dudx, _dvdx = dvdx; + float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya; + float _xa = xa, _xb = xb, _ua = ua, _va = va; + auto sbuf = image->buf32; + auto dbuf = surface->buf32; + int32_t sw = static_cast(image->stride); + int32_t sh = image->h; + int32_t dw = surface->stride; + int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay; + int32_t vv = 0, uu = 0; + int32_t minx = INT32_MAX, maxx = INT32_MIN; + float dx, u, v, iptr; + uint32_t* buf; + SwSpan* span = nullptr; //used only when rle based. + + //for matting(composition) + auto csize = matting ? surface->compositor->image.channelSize: 0; + auto alpha = matting ? surface->alpha(surface->compositor->method) : nullptr; + uint8_t* cmp = nullptr; + + if (!_arrange(image, region, yStart, yEnd)) return; + + //Loop through all lines in the segment + uint32_t spanIdx = 0; + + if (region) { + minx = region->min.x; + maxx = region->max.x; + } else { + span = image->rle->spans; + while (span->y < yStart) { + ++span; + ++spanIdx; + } + } + + y = yStart; + + while (y < yEnd) { + x1 = (int32_t)_xa; + x2 = (int32_t)_xb; + + if (!region) { + minx = INT32_MAX; + maxx = INT32_MIN; + //one single row, could be consisted of multiple spans. + while (span->y == y && spanIdx < image->rle->size) { + if (minx > span->x) minx = span->x; + if (maxx < span->x + span->len) maxx = span->x + span->len; + ++span; + ++spanIdx; + } + } + if (x1 < minx) x1 = minx; + if (x2 > maxx) x2 = maxx; + + //Anti-Aliasing frames + ay = y - aaSpans->yStart; + if (aaSpans->lines[ay].x[0] > x1) aaSpans->lines[ay].x[0] = x1; + if (aaSpans->lines[ay].x[1] < x2) aaSpans->lines[ay].x[1] = x2; + + //Range allowed + if ((x2 - x1) >= 1 && (x1 < maxx) && (x2 > minx)) { + + //Perform subtexel pre-stepping on UV + dx = 1 - (_xa - x1); + u = _ua + dx * _dudx; + v = _va + dx * _dvdx; + + buf = dbuf + ((y * dw) + x1); + + x = x1; + + if (matting) cmp = &surface->compositor->image.buf8[(y * surface->compositor->image.stride + x1) * csize]; + + if (opacity == 255) { + //Draw horizontal line + while (x++ < x2) { + uu = (int) u; + if (uu >= sw) continue; + vv = (int) v; + if (vv >= sh) continue; + + ar = (int)(255 * (1 - modff(u, &iptr))); + ab = (int)(255 * (1 - modff(v, &iptr))); + iru = uu + 1; + irv = vv + 1; + + px = *(sbuf + (vv * sw) + uu); + + /* horizontal interpolate */ + if (iru < sw) { + /* right pixel */ + int px2 = *(sbuf + (vv * sw) + iru); + px = INTERPOLATE(px, px2, ar); + } + /* vertical interpolate */ + if (irv < sh) { + /* bottom pixel */ + int px2 = *(sbuf + (irv * sw) + uu); + + /* horizontal interpolate */ + if (iru < sw) { + /* bottom right pixel */ + int px3 = *(sbuf + (irv * sw) + iru); + px2 = INTERPOLATE(px2, px3, ar); + } + px = INTERPOLATE(px, px2, ab); + } + uint32_t src; + if (matting) { + src = ALPHA_BLEND(px, alpha(cmp)); + cmp += csize; + } else { + src = px; + } + *buf = src + ALPHA_BLEND(*buf, IA(src)); + ++buf; + + //Step UV horizontally + u += _dudx; + v += _dvdx; + //range over? + if ((uint32_t)v >= image->h) break; + } + } else { + //Draw horizontal line + while (x++ < x2) { + uu = (int) u; + vv = (int) v; + + ar = (int)(255 * (1 - modff(u, &iptr))); + ab = (int)(255 * (1 - modff(v, &iptr))); + iru = uu + 1; + irv = vv + 1; + + if (vv >= sh) continue; + + px = *(sbuf + (vv * sw) + uu); + + /* horizontal interpolate */ + if (iru < sw) { + /* right pixel */ + int px2 = *(sbuf + (vv * sw) + iru); + px = INTERPOLATE(px, px2, ar); + } + /* vertical interpolate */ + if (irv < sh) { + /* bottom pixel */ + int px2 = *(sbuf + (irv * sw) + uu); + + /* horizontal interpolate */ + if (iru < sw) { + /* bottom right pixel */ + int px3 = *(sbuf + (irv * sw) + iru); + px2 = INTERPOLATE(px2, px3, ar); + } + px = INTERPOLATE(px, px2, ab); + } + uint32_t src; + if (matting) { + src = ALPHA_BLEND(px, MULTIPLY(opacity, alpha(cmp))); + cmp += csize; + } else { + src = ALPHA_BLEND(px, opacity); + } + *buf = src + ALPHA_BLEND(*buf, IA(src)); + ++buf; + + //Step UV horizontally + u += _dudx; + v += _dvdx; + //range over? + if ((uint32_t)v >= image->h) break; + } + } + } + + //Step along both edges + _xa += _dxdya; + _xb += _dxdyb; + _ua += _dudya; + _va += _dvdya; + + if (!region && spanIdx >= image->rle->size) break; + + ++y; + } + xa = _xa; + xb = _xb; + ua = _ua; + va = _va; +} + + +/* This mapping algorithm is based on Mikael Kalms's. */ +static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox* region, Polygon& polygon, AASpans* aaSpans, uint8_t opacity) +{ + float x[3] = {polygon.vertex[0].pt.x, polygon.vertex[1].pt.x, polygon.vertex[2].pt.x}; + float y[3] = {polygon.vertex[0].pt.y, polygon.vertex[1].pt.y, polygon.vertex[2].pt.y}; + float u[3] = {polygon.vertex[0].uv.x, polygon.vertex[1].uv.x, polygon.vertex[2].uv.x}; + float v[3] = {polygon.vertex[0].uv.y, polygon.vertex[1].uv.y, polygon.vertex[2].uv.y}; + + float off_y; + float dxdy[3] = {0.0f, 0.0f, 0.0f}; + float tmp; + + auto upper = false; + + //Sort the vertices in ascending Y order + if (y[0] > y[1]) { + _swap(x[0], x[1], tmp); + _swap(y[0], y[1], tmp); + _swap(u[0], u[1], tmp); + _swap(v[0], v[1], tmp); + } + if (y[0] > y[2]) { + _swap(x[0], x[2], tmp); + _swap(y[0], y[2], tmp); + _swap(u[0], u[2], tmp); + _swap(v[0], v[2], tmp); + } + if (y[1] > y[2]) { + _swap(x[1], x[2], tmp); + _swap(y[1], y[2], tmp); + _swap(u[1], u[2], tmp); + _swap(v[1], v[2], tmp); + } + + //Y indexes + int yi[3] = {(int)y[0], (int)y[1], (int)y[2]}; + + //Skip drawing if it's too thin to cover any pixels at all. + if ((yi[0] == yi[1] && yi[0] == yi[2]) || ((int) x[0] == (int) x[1] && (int) x[0] == (int) x[2])) return; + + //Calculate horizontal and vertical increments for UV axes (these calcs are certainly not optimal, although they're stable (handles any dy being 0) + auto denom = ((x[2] - x[0]) * (y[1] - y[0]) - (x[1] - x[0]) * (y[2] - y[0])); + + //Skip poly if it's an infinitely thin line + if (mathZero(denom)) return; + + denom = 1 / denom; //Reciprocal for speeding up + dudx = ((u[2] - u[0]) * (y[1] - y[0]) - (u[1] - u[0]) * (y[2] - y[0])) * denom; + dvdx = ((v[2] - v[0]) * (y[1] - y[0]) - (v[1] - v[0]) * (y[2] - y[0])) * denom; + auto dudy = ((u[1] - u[0]) * (x[2] - x[0]) - (u[2] - u[0]) * (x[1] - x[0])) * denom; + auto dvdy = ((v[1] - v[0]) * (x[2] - x[0]) - (v[2] - v[0]) * (x[1] - x[0])) * denom; + + //Calculate X-slopes along the edges + if (y[1] > y[0]) dxdy[0] = (x[1] - x[0]) / (y[1] - y[0]); + if (y[2] > y[0]) dxdy[1] = (x[2] - x[0]) / (y[2] - y[0]); + if (y[2] > y[1]) dxdy[2] = (x[2] - x[1]) / (y[2] - y[1]); + + //Determine which side of the polygon the longer edge is on + auto side = (dxdy[1] > dxdy[0]) ? true : false; + + if (mathEqual(y[0], y[1])) side = x[0] > x[1]; + if (mathEqual(y[1], y[2])) side = x[2] > x[1]; + + auto regionTop = region ? region->min.y : image->rle->spans->y; //Normal Image or Rle Image? + auto compositing = _compositing(surface); //Composition required + auto blending = _blending(surface); //Blending required + + //Longer edge is on the left side + if (!side) { + //Calculate slopes along left edge + dxdya = dxdy[1]; + dudya = dxdya * dudx + dudy; + dvdya = dxdya * dvdx + dvdy; + + //Perform subpixel pre-stepping along left edge + auto dy = 1.0f - (y[0] - yi[0]); + xa = x[0] + dy * dxdya; + ua = u[0] + dy * dudya; + va = v[0] + dy * dvdya; + + //Draw upper segment if possibly visible + if (yi[0] < yi[1]) { + off_y = y[0] < regionTop ? (regionTop - y[0]) : 0; + xa += (off_y * dxdya); + ua += (off_y * dudya); + va += (off_y * dvdya); + + // Set right edge X-slope and perform subpixel pre-stepping + dxdyb = dxdy[0]; + xb = x[0] + dy * dxdyb + (off_y * dxdyb); + + if (compositing) { + if (_matting(surface)) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity, true); + else _rasterMaskedPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity, 1); + } else if (blending) { + _rasterBlendingPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity); + } else { + _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity, false); + } + upper = true; + } + //Draw lower segment if possibly visible + if (yi[1] < yi[2]) { + off_y = y[1] < regionTop ? (regionTop - y[1]) : 0; + if (!upper) { + xa += (off_y * dxdya); + ua += (off_y * dudya); + va += (off_y * dvdya); + } + // Set right edge X-slope and perform subpixel pre-stepping + dxdyb = dxdy[2]; + xb = x[1] + (1 - (y[1] - yi[1])) * dxdyb + (off_y * dxdyb); + if (compositing) { + if (_matting(surface)) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity, true); + else _rasterMaskedPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity, 2); + } else if (blending) { + _rasterBlendingPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity); + } else { + _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity, false); + } + } + //Longer edge is on the right side + } else { + //Set right edge X-slope and perform subpixel pre-stepping + dxdyb = dxdy[1]; + auto dy = 1.0f - (y[0] - yi[0]); + xb = x[0] + dy * dxdyb; + + //Draw upper segment if possibly visible + if (yi[0] < yi[1]) { + off_y = y[0] < regionTop ? (regionTop - y[0]) : 0; + xb += (off_y *dxdyb); + + // Set slopes along left edge and perform subpixel pre-stepping + dxdya = dxdy[0]; + dudya = dxdya * dudx + dudy; + dvdya = dxdya * dvdx + dvdy; + + xa = x[0] + dy * dxdya + (off_y * dxdya); + ua = u[0] + dy * dudya + (off_y * dudya); + va = v[0] + dy * dvdya + (off_y * dvdya); + + if (compositing) { + if (_matting(surface)) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity, true); + else _rasterMaskedPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity, 3); + } else if (blending) { + _rasterBlendingPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity); + } else { + _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity, false); + } + upper = true; + } + //Draw lower segment if possibly visible + if (yi[1] < yi[2]) { + off_y = y[1] < regionTop ? (regionTop - y[1]) : 0; + if (!upper) xb += (off_y *dxdyb); + + // Set slopes along left edge and perform subpixel pre-stepping + dxdya = dxdy[2]; + dudya = dxdya * dudx + dudy; + dvdya = dxdya * dvdx + dvdy; + dy = 1 - (y[1] - yi[1]); + xa = x[1] + dy * dxdya + (off_y * dxdya); + ua = u[1] + dy * dudya + (off_y * dudya); + va = v[1] + dy * dvdya + (off_y * dvdya); + + if (compositing) { + if (_matting(surface)) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity, true); + else _rasterMaskedPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity, 4); + } else if (blending) { + _rasterBlendingPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity); + } else { + _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity, false); + } + } + } +} + + +static AASpans* _AASpans(float ymin, float ymax, const SwImage* image, const SwBBox* region) +{ + auto yStart = static_cast(ymin); + auto yEnd = static_cast(ymax); + + if (!_arrange(image, region, yStart, yEnd)) return nullptr; + + auto aaSpans = static_cast(malloc(sizeof(AASpans))); + aaSpans->yStart = yStart; + aaSpans->yEnd = yEnd; + + //Initialize X range + auto height = yEnd - yStart; + + aaSpans->lines = static_cast(calloc(height, sizeof(AALine))); + + for (int32_t i = 0; i < height; i++) { + aaSpans->lines[i].x[0] = INT32_MAX; + aaSpans->lines[i].x[1] = INT32_MIN; + } + return aaSpans; +} + + +static void _calcIrregularCoverage(AALine* lines, int32_t eidx, int32_t y, int32_t diagonal, int32_t edgeDist, bool reverse) +{ + if (eidx == 1) reverse = !reverse; + int32_t coverage = (255 / (diagonal + 2)); + int32_t tmp; + for (int32_t ry = 0; ry < (diagonal + 2); ry++) { + tmp = y - ry - edgeDist; + if (tmp < 0) return; + lines[tmp].length[eidx] = 1; + if (reverse) lines[tmp].coverage[eidx] = 255 - (coverage * ry); + else lines[tmp].coverage[eidx] = (coverage * ry); + } +} + + +static void _calcVertCoverage(AALine *lines, int32_t eidx, int32_t y, int32_t rewind, bool reverse) +{ + if (eidx == 1) reverse = !reverse; + int32_t coverage = (255 / (rewind + 1)); + int32_t tmp; + for (int ry = 1; ry < (rewind + 1); ry++) { + tmp = y - ry; + if (tmp < 0) return; + lines[tmp].length[eidx] = 1; + if (reverse) lines[tmp].coverage[eidx] = (255 - (coverage * ry)); + else lines[tmp].coverage[eidx] = (coverage * ry); + } +} + + +static void _calcHorizCoverage(AALine *lines, int32_t eidx, int32_t y, int32_t x, int32_t x2) +{ + if (lines[y].length[eidx] < abs(x - x2)) { + lines[y].length[eidx] = abs(x - x2); + lines[y].coverage[eidx] = (255 / (lines[y].length[eidx] + 1)); + } +} + + +/* + * This Anti-Aliasing mechanism is originated from Hermet Park's idea. + * To understand this AA logic, you can refer this page: + * www.hermet.pe.kr/122 (hermetpark@gmail.com) +*/ +static void _calcAAEdge(AASpans *aaSpans, int32_t eidx) +{ +//Previous edge direction: +#define DirOutHor 0x0011 +#define DirOutVer 0x0001 +#define DirInHor 0x0010 +#define DirInVer 0x0000 +#define DirNone 0x1000 + +#define PUSH_VERTEX() \ + do { \ + pEdge.x = lines[y].x[eidx]; \ + pEdge.y = y; \ + ptx[0] = tx[0]; \ + ptx[1] = tx[1]; \ + } while (0) + + int32_t y = 0; + SwPoint pEdge = {-1, -1}; //previous edge point + SwPoint edgeDiff = {0, 0}; //temporary used for point distance + + /* store bigger to tx[0] between prev and current edge's x positions. */ + int32_t tx[2] = {0, 0}; + /* back up prev tx values */ + int32_t ptx[2] = {0, 0}; + int32_t diagonal = 0; //straight diagonal pixels count + + auto yStart = aaSpans->yStart; + auto yEnd = aaSpans->yEnd; + auto lines = aaSpans->lines; + + int32_t prevDir = DirNone; + int32_t curDir = DirNone; + + yEnd -= yStart; + + //Start Edge + if (y < yEnd) { + pEdge.x = lines[y].x[eidx]; + pEdge.y = y; + } + + //Calculates AA Edges + for (y++; y < yEnd; y++) { + //Ready tx + if (eidx == 0) { + tx[0] = pEdge.x; + tx[1] = lines[y].x[0]; + } else { + tx[0] = lines[y].x[1]; + tx[1] = pEdge.x; + } + edgeDiff.x = (tx[0] - tx[1]); + edgeDiff.y = (y - pEdge.y); + + //Confirm current edge direction + if (edgeDiff.x > 0) { + if (edgeDiff.y == 1) curDir = DirOutHor; + else curDir = DirOutVer; + } else if (edgeDiff.x < 0) { + if (edgeDiff.y == 1) curDir = DirInHor; + else curDir = DirInVer; + } else curDir = DirNone; + + //straight diagonal increase + if ((curDir == prevDir) && (y < yEnd)) { + if ((abs(edgeDiff.x) == 1) && (edgeDiff.y == 1)) { + ++diagonal; + PUSH_VERTEX(); + continue; + } + } + + switch (curDir) { + case DirOutHor: { + _calcHorizCoverage(lines, eidx, y, tx[0], tx[1]); + if (diagonal > 0) { + _calcIrregularCoverage(lines, eidx, y, diagonal, 0, true); + diagonal = 0; + } + /* Increment direction is changed: Outside Vertical -> Outside Horizontal */ + if (prevDir == DirOutVer) _calcHorizCoverage(lines, eidx, pEdge.y, ptx[0], ptx[1]); + + //Trick, but fine-tunning! + if (y == 1) _calcHorizCoverage(lines, eidx, pEdge.y, tx[0], tx[1]); + PUSH_VERTEX(); + } + break; + case DirOutVer: { + _calcVertCoverage(lines, eidx, y, edgeDiff.y, true); + if (diagonal > 0) { + _calcIrregularCoverage(lines, eidx, y, diagonal, edgeDiff.y, false); + diagonal = 0; + } + /* Increment direction is changed: Outside Horizontal -> Outside Vertical */ + if (prevDir == DirOutHor) _calcHorizCoverage(lines, eidx, pEdge.y, ptx[0], ptx[1]); + PUSH_VERTEX(); + } + break; + case DirInHor: { + _calcHorizCoverage(lines, eidx, (y - 1), tx[0], tx[1]); + if (diagonal > 0) { + _calcIrregularCoverage(lines, eidx, y, diagonal, 0, false); + diagonal = 0; + } + /* Increment direction is changed: Outside Horizontal -> Inside Horizontal */ + if (prevDir == DirOutHor) _calcHorizCoverage(lines, eidx, pEdge.y, ptx[0], ptx[1]); + PUSH_VERTEX(); + } + break; + case DirInVer: { + _calcVertCoverage(lines, eidx, y, edgeDiff.y, false); + if (prevDir == DirOutHor) edgeDiff.y -= 1; //Weird, fine tuning????????????????????? + if (diagonal > 0) { + _calcIrregularCoverage(lines, eidx, y, diagonal, edgeDiff.y, true); + diagonal = 0; + } + /* Increment direction is changed: Outside Horizontal -> Inside Vertical */ + if (prevDir == DirOutHor) _calcHorizCoverage(lines, eidx, pEdge.y, ptx[0], ptx[1]); + PUSH_VERTEX(); + } + break; + } + if (curDir != DirNone) prevDir = curDir; + } + + //leftovers...? + if ((edgeDiff.y == 1) && (edgeDiff.x != 0)) { + if (y >= yEnd) y = (yEnd - 1); + _calcHorizCoverage(lines, eidx, y - 1, ptx[0], ptx[1]); + _calcHorizCoverage(lines, eidx, y, tx[0], tx[1]); + } else { + ++y; + if (y > yEnd) y = yEnd; + _calcVertCoverage(lines, eidx, y, (edgeDiff.y + 1), (prevDir & 0x00000001)); + } +} + + +static bool _apply(SwSurface* surface, AASpans* aaSpans) +{ + auto y = aaSpans->yStart; + uint32_t pixel; + uint32_t* dst; + int32_t pos; + + //left side + _calcAAEdge(aaSpans, 0); + //right side + _calcAAEdge(aaSpans, 1); + + while (y < aaSpans->yEnd) { + auto line = &aaSpans->lines[y - aaSpans->yStart]; + auto width = line->x[1] - line->x[0]; + if (width > 0) { + auto offset = y * surface->stride; + + //Left edge + dst = surface->buf32 + (offset + line->x[0]); + if (line->x[0] > 1) pixel = *(dst - 1); + else pixel = *dst; + + pos = 1; + while (pos <= line->length[0]) { + *dst = INTERPOLATE(*dst, pixel, line->coverage[0] * pos); + ++dst; + ++pos; + } + + //Right edge + dst = surface->buf32 + (offset + line->x[1] - 1); + if (line->x[1] < (int32_t)(surface->w - 1)) pixel = *(dst + 1); + else pixel = *dst; + + pos = width; + while ((int32_t)(width - line->length[1]) < pos) { + *dst = INTERPOLATE(*dst, pixel, 255 - (line->coverage[1] * (line->length[1] - (width - pos)))); + --dst; + --pos; + } + } + y++; + } + + free(aaSpans->lines); + free(aaSpans); + + return true; +} + + +/* + 2 triangles constructs 1 mesh. + below figure illustrates vert[4] index info. + If you need better quality, please divide a mesh by more number of triangles. + + 0 -- 1 + | / | + | / | + 3 -- 2 +*/ +static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint8_t opacity) +{ + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported grayscale Textmap polygon!"); + return false; + } + + //Exceptions: No dedicated drawing area? + if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false; + + /* Prepare vertices. + shift XY coordinates to match the sub-pixeling technique. */ + Vertex vertices[4]; + vertices[0] = {{0.0f, 0.0f}, {0.0f, 0.0f}}; + vertices[1] = {{float(image->w), 0.0f}, {float(image->w), 0.0f}}; + vertices[2] = {{float(image->w), float(image->h)}, {float(image->w), float(image->h)}}; + vertices[3] = {{0.0f, float(image->h)}, {0.0f, float(image->h)}}; + + float ys = FLT_MAX, ye = -1.0f; + for (int i = 0; i < 4; i++) { + mathMultiply(&vertices[i].pt, transform); + + if (vertices[i].pt.y < ys) ys = vertices[i].pt.y; + if (vertices[i].pt.y > ye) ye = vertices[i].pt.y; + } + + auto aaSpans = _AASpans(ys, ye, image, region); + if (!aaSpans) return true; + + Polygon polygon; + + //Draw the first polygon + polygon.vertex[0] = vertices[0]; + polygon.vertex[1] = vertices[1]; + polygon.vertex[2] = vertices[3]; + + _rasterPolygonImage(surface, image, region, polygon, aaSpans, opacity); + + //Draw the second polygon + polygon.vertex[0] = vertices[1]; + polygon.vertex[1] = vertices[2]; + polygon.vertex[2] = vertices[3]; + + _rasterPolygonImage(surface, image, region, polygon, aaSpans, opacity); + +#if 0 + if (_compositing(surface) && _masking(surface) && !_direct(surface->compositor->method)) { + _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); + } +#endif + return _apply(surface, aaSpans); +} + + +/* + Provide any number of triangles to draw a mesh using the supplied image. + Indexes are not used, so each triangle (Polygon) vertex has to be defined, even if they copy the previous one. + Example: + + 0 -- 1 0 -- 1 0 + | / | --> | / / | + | / | | / / | + 2 -- 3 2 1 -- 2 + + Should provide two Polygons, one for each triangle. + // TODO: region? +*/ +static bool _rasterTexmapPolygonMesh(SwSurface* surface, const SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox* region, uint8_t opacity) +{ + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported grayscale Textmap polygon mesh!"); + return false; + } + + //Exceptions: No dedicated drawing area? + if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false; + + // Step polygons once to transform + auto transformedTris = (Polygon*)malloc(sizeof(Polygon) * mesh->triangleCnt); + float ys = FLT_MAX, ye = -1.0f; + for (uint32_t i = 0; i < mesh->triangleCnt; i++) { + transformedTris[i] = mesh->triangles[i]; + mathMultiply(&transformedTris[i].vertex[0].pt, transform); + mathMultiply(&transformedTris[i].vertex[1].pt, transform); + mathMultiply(&transformedTris[i].vertex[2].pt, transform); + + if (transformedTris[i].vertex[0].pt.y < ys) ys = transformedTris[i].vertex[0].pt.y; + else if (transformedTris[i].vertex[0].pt.y > ye) ye = transformedTris[i].vertex[0].pt.y; + if (transformedTris[i].vertex[1].pt.y < ys) ys = transformedTris[i].vertex[1].pt.y; + else if (transformedTris[i].vertex[1].pt.y > ye) ye = transformedTris[i].vertex[1].pt.y; + if (transformedTris[i].vertex[2].pt.y < ys) ys = transformedTris[i].vertex[2].pt.y; + else if (transformedTris[i].vertex[2].pt.y > ye) ye = transformedTris[i].vertex[2].pt.y; + + // Convert normalized UV coordinates to image coordinates + transformedTris[i].vertex[0].uv.x *= (float)image->w; + transformedTris[i].vertex[0].uv.y *= (float)image->h; + transformedTris[i].vertex[1].uv.x *= (float)image->w; + transformedTris[i].vertex[1].uv.y *= (float)image->h; + transformedTris[i].vertex[2].uv.x *= (float)image->w; + transformedTris[i].vertex[2].uv.y *= (float)image->h; + } + + // Get AA spans and step polygons again to draw + if (auto aaSpans = _AASpans(ys, ye, image, region)) { + for (uint32_t i = 0; i < mesh->triangleCnt; i++) { + _rasterPolygonImage(surface, image, region, transformedTris[i], aaSpans, opacity); + } +#if 0 + if (_compositing(surface) && _masking(surface) && !_direct(surface->compositor->method)) { + _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); + } +#endif + _apply(surface, aaSpans); + } + free(transformedTris); + return true; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRenderer.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRenderer.cpp new file mode 100644 index 000000000..007c09edb --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRenderer.cpp @@ -0,0 +1,866 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgMath.h" +#include "tvgSwCommon.h" +#include "tvgTaskScheduler.h" +#include "tvgSwRenderer.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ +static int32_t initEngineCnt = false; +static int32_t rendererCnt = 0; +static SwMpool* globalMpool = nullptr; +static uint32_t threadsCnt = 0; + +struct SwTask : Task +{ + SwSurface* surface = nullptr; + SwMpool* mpool = nullptr; + SwBBox bbox = {{0, 0}, {0, 0}}; //Whole Rendering Region + Matrix* transform = nullptr; + Array clips; + RenderUpdateFlag flags = RenderUpdateFlag::None; + uint8_t opacity; + bool pushed = false; //Pushed into task list? + bool disposed = false; //Disposed task? + + RenderRegion bounds() const + { + RenderRegion region; + + //Range over? + region.x = bbox.min.x > 0 ? bbox.min.x : 0; + region.y = bbox.min.y > 0 ? bbox.min.y : 0; + region.w = bbox.max.x - region.x; + region.h = bbox.max.y - region.y; + if (region.w < 0) region.w = 0; + if (region.h < 0) region.h = 0; + + return region; + } + + virtual bool dispose() = 0; + virtual bool clip(SwRleData* target) = 0; + virtual SwRleData* rle() = 0; + + virtual ~SwTask() + { + free(transform); + } +}; + + +struct SwShapeTask : SwTask +{ + SwShape shape; + const RenderShape* rshape = nullptr; + bool cmpStroking = false; + bool clipper = false; + + /* We assume that if the stroke width is greater than 2, + the shape's outline beneath the stroke could be adequately covered by the stroke drawing. + Therefore, antialiasing is disabled under this condition. + Additionally, the stroke style should not be dashed. */ + bool antialiasing(float strokeWidth) + { + return strokeWidth < 2.0f || rshape->stroke->dashCnt > 0 || rshape->stroke->strokeFirst; + } + + float validStrokeWidth() + { + if (!rshape->stroke) return 0.0f; + + auto width = rshape->stroke->width; + if (mathZero(width)) return 0.0f; + + if (!rshape->stroke->fill && (MULTIPLY(rshape->stroke->color[3], opacity) == 0)) return 0.0f; + if (mathZero(rshape->stroke->trim.begin - rshape->stroke->trim.end)) return 0.0f; + + if (transform) return (width * sqrt(transform->e11 * transform->e11 + transform->e12 * transform->e12)); + else return width; + } + + + bool clip(SwRleData* target) override + { + if (shape.fastTrack) rleClipRect(target, &bbox); + else if (shape.rle) rleClipPath(target, shape.rle); + else return false; + + return true; + } + + SwRleData* rle() override + { + if (!shape.rle && shape.fastTrack) { + shape.rle = rleRender(&shape.bbox); + } + return shape.rle; + } + + void run(unsigned tid) override + { + if (opacity == 0 && !clipper) return; //Invisible + + auto strokeWidth = validStrokeWidth(); + bool visibleFill = false; + auto clipRegion = bbox; + + //This checks also for the case, if the invisible shape turned to visible by alpha. + auto prepareShape = false; + if (!shapePrepared(&shape) && (flags & RenderUpdateFlag::Color)) prepareShape = true; + + //Shape + if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform) || prepareShape) { + uint8_t alpha = 0; + rshape->fillColor(nullptr, nullptr, nullptr, &alpha); + alpha = MULTIPLY(alpha, opacity); + visibleFill = (alpha > 0 || rshape->fill); + if (visibleFill || clipper) { + shapeReset(&shape); + if (!shapePrepare(&shape, rshape, transform, clipRegion, bbox, mpool, tid, clips.count > 0 ? true : false)) goto err; + } + } + //Fill + if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) { + if (visibleFill || clipper) { + if (!shapeGenRle(&shape, rshape, antialiasing(strokeWidth))) goto err; + } + if (auto fill = rshape->fill) { + auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false; + if (ctable) shapeResetFill(&shape); + if (!shapeGenFillColors(&shape, fill, transform, surface, opacity, ctable)) goto err; + } else { + shapeDelFill(&shape); + } + } + //Stroke + if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { + if (strokeWidth > 0.0f) { + shapeResetStroke(&shape, rshape, transform); + if (!shapeGenStrokeRle(&shape, rshape, transform, clipRegion, bbox, mpool, tid)) goto err; + + if (auto fill = rshape->strokeFill()) { + auto ctable = (flags & RenderUpdateFlag::GradientStroke) ? true : false; + if (ctable) shapeResetStrokeFill(&shape); + if (!shapeGenStrokeFillColors(&shape, fill, transform, surface, opacity, ctable)) goto err; + } else { + shapeDelStrokeFill(&shape); + } + } else { + shapeDelStroke(&shape); + } + } + + //Clear current task memorypool here if the clippers would use the same memory pool + shapeDelOutline(&shape, mpool, tid); + + //Clip Path + for (auto clip = clips.data; clip < clips.end(); ++clip) { + auto clipper = static_cast(*clip); + //Clip shape rle + if (shape.rle && !clipper->clip(shape.rle)) goto err; + //Clip stroke rle + if (shape.strokeRle && !clipper->clip(shape.strokeRle)) goto err; + } + return; + + err: + shapeReset(&shape); + shapeDelOutline(&shape, mpool, tid); + } + + bool dispose() override + { + shapeFree(&shape); + return true; + } +}; + + +struct SwSceneTask : SwTask +{ + Array scene; //list of paints render data (SwTask) + SwRleData* sceneRle = nullptr; + + bool clip(SwRleData* target) override + { + //Only one shape + if (scene.count == 1) { + return static_cast(*scene.data)->clip(target); + } + + //More than one shapes + if (sceneRle) rleClipPath(target, sceneRle); + else TVGLOG("SW_ENGINE", "No clippers in a scene?"); + + return true; + } + + SwRleData* rle() override + { + return sceneRle; + } + + void run(unsigned tid) override + { + //TODO: Skip the run if the scene hans't changed. + if (!sceneRle) sceneRle = static_cast(calloc(1, sizeof(SwRleData))); + else rleReset(sceneRle); + + //Merge shapes if it has more than one shapes + if (scene.count > 1) { + //Merge first two clippers + auto clipper1 = static_cast(*scene.data); + auto clipper2 = static_cast(*(scene.data + 1)); + + rleMerge(sceneRle, clipper1->rle(), clipper2->rle()); + + //Unify the remained clippers + for (auto rd = scene.data + 2; rd < scene.end(); ++rd) { + auto clipper = static_cast(*rd); + rleMerge(sceneRle, sceneRle, clipper->rle()); + } + } + } + + bool dispose() override + { + rleFree(sceneRle); + return true; + } +}; + + +struct SwImageTask : SwTask +{ + SwImage image; + Surface* source; //Image source + const RenderMesh* mesh = nullptr; //Should be valid ptr in action + + bool clip(SwRleData* target) override + { + TVGERR("SW_ENGINE", "Image is used as ClipPath?"); + return true; + } + + SwRleData* rle() override + { + TVGERR("SW_ENGINE", "Image is used as Scene ClipPath?"); + return nullptr; + } + + void run(unsigned tid) override + { + auto clipRegion = bbox; + + //Convert colorspace if it's not aligned. + if (source->owner) { + if (source->cs != surface->cs) rasterConvertCS(source, surface->cs); + if (!source->premultiplied) rasterPremultiply(source); + } + + image.data = source->data; + image.w = source->w; + image.h = source->h; + image.stride = source->stride; + image.channelSize = source->channelSize; + + //Invisible shape turned to visible by alpha. + if ((flags & (RenderUpdateFlag::Image | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) && (opacity > 0)) { + imageReset(&image); + if (!image.data || image.w == 0 || image.h == 0) goto end; + + if (!imagePrepare(&image, mesh, transform, clipRegion, bbox, mpool, tid)) goto end; + + // TODO: How do we clip the triangle mesh? Only clip non-meshed images for now + if (mesh->triangleCnt == 0 && clips.count > 0) { + if (!imageGenRle(&image, bbox, false)) goto end; + if (image.rle) { + //Clear current task memorypool here if the clippers would use the same memory pool + imageDelOutline(&image, mpool, tid); + for (auto clip = clips.data; clip < clips.end(); ++clip) { + auto clipper = static_cast(*clip); + if (!clipper->clip(image.rle)) goto err; + } + return; + } + } + } + goto end; + err: + rleReset(image.rle); + end: + imageDelOutline(&image, mpool, tid); + } + + bool dispose() override + { + imageFree(&image); + return true; + } +}; + + +static void _termEngine() +{ + if (rendererCnt > 0) return; + + mpoolTerm(globalMpool); + globalMpool = nullptr; +} + + +static void _renderFill(SwShapeTask* task, SwSurface* surface, uint8_t opacity) +{ + uint8_t r, g, b, a; + if (auto fill = task->rshape->fill) { + rasterGradientShape(surface, &task->shape, fill->identifier()); + } else { + task->rshape->fillColor(&r, &g, &b, &a); + a = MULTIPLY(opacity, a); + if (a > 0) rasterShape(surface, &task->shape, r, g, b, a); + } +} + +static void _renderStroke(SwShapeTask* task, SwSurface* surface, uint8_t opacity) +{ + uint8_t r, g, b, a; + if (auto strokeFill = task->rshape->strokeFill()) { + rasterGradientStroke(surface, &task->shape, strokeFill->identifier()); + } else { + if (task->rshape->strokeColor(&r, &g, &b, &a)) { + a = MULTIPLY(opacity, a); + if (a > 0) rasterStroke(surface, &task->shape, r, g, b, a); + } + } +} + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +SwRenderer::~SwRenderer() +{ + clearCompositors(); + + delete(surface); + + if (!sharedMpool) mpoolTerm(mpool); + + --rendererCnt; + + if (rendererCnt == 0 && initEngineCnt == 0) _termEngine(); +} + + +bool SwRenderer::clear() +{ + for (auto task = tasks.data; task < tasks.end(); ++task) { + if ((*task)->disposed) { + delete(*task); + } else { + (*task)->done(); + (*task)->pushed = false; + } + } + tasks.clear(); + + if (!sharedMpool) mpoolClear(mpool); + + if (surface) { + vport.x = vport.y = 0; + vport.w = surface->w; + vport.h = surface->h; + } + + return true; +} + + +bool SwRenderer::sync() +{ + return true; +} + + +RenderRegion SwRenderer::viewport() +{ + return vport; +} + + +bool SwRenderer::viewport(const RenderRegion& vp) +{ + vport = vp; + return true; +} + + +bool SwRenderer::target(pixel_t* data, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs) +{ + if (!data || stride == 0 || w == 0 || h == 0 || w > stride) return false; + + if (!surface) surface = new SwSurface; + + surface->data = data; + surface->stride = stride; + surface->w = w; + surface->h = h; + surface->cs = cs; + surface->channelSize = CHANNEL_SIZE(cs); + surface->premultiplied = true; + surface->owner = true; + + vport.x = vport.y = 0; + vport.w = surface->w; + vport.h = surface->h; + + return rasterCompositor(surface); +} + + +bool SwRenderer::preRender() +{ +#if LV_USE_DRAW_VG_LITE && LV_USE_VG_LITE_THORVG + return true; +#else + return rasterClear(surface, 0, 0, surface->w, surface->h); +#endif +} + + +void SwRenderer::clearCompositors() +{ + //Free Composite Caches + for (auto comp = compositors.data; comp < compositors.end(); ++comp) { + free((*comp)->compositor->image.data); + delete((*comp)->compositor); + delete(*comp); + } + compositors.reset(); +} + + +bool SwRenderer::postRender() +{ + //Unmultiply alpha if needed + if (surface->cs == ColorSpace::ABGR8888S || surface->cs == ColorSpace::ARGB8888S) { + rasterUnpremultiply(surface); + } + + for (auto task = tasks.data; task < tasks.end(); ++task) { + if ((*task)->disposed) delete(*task); + else (*task)->pushed = false; + } + tasks.clear(); + + clearCompositors(); + return true; +} + + +bool SwRenderer::renderImage(RenderData data) +{ + auto task = static_cast(data); + task->done(); + + if (task->opacity == 0) return true; + + return rasterImage(surface, &task->image, task->mesh, task->transform, task->bbox, task->opacity); +} + + +bool SwRenderer::renderShape(RenderData data) +{ + auto task = static_cast(data); + if (!task) return false; + + task->done(); + + if (task->opacity == 0) return true; + + //Main raster stage + if (task->rshape->stroke && task->rshape->stroke->strokeFirst) { + _renderStroke(task, surface, task->opacity); + _renderFill(task, surface, task->opacity); + } else { + _renderFill(task, surface, task->opacity); + _renderStroke(task, surface, task->opacity); + } + + return true; +} + + +bool SwRenderer::blend(BlendMethod method) +{ + if (surface->blendMethod == method) return true; + surface->blendMethod = method; + + switch (method) { + case BlendMethod::Add: + surface->blender = opBlendAdd; + break; + case BlendMethod::Screen: + surface->blender = opBlendScreen; + break; + case BlendMethod::Multiply: + surface->blender = opBlendMultiply; + break; + case BlendMethod::Overlay: + surface->blender = opBlendOverlay; + break; + case BlendMethod::Difference: + surface->blender = opBlendDifference; + break; + case BlendMethod::Exclusion: + surface->blender = opBlendExclusion; + break; + case BlendMethod::SrcOver: + surface->blender = opBlendSrcOver; + break; + case BlendMethod::Darken: + surface->blender = opBlendDarken; + break; + case BlendMethod::Lighten: + surface->blender = opBlendLighten; + break; + case BlendMethod::ColorDodge: + surface->blender = opBlendColorDodge; + break; + case BlendMethod::ColorBurn: + surface->blender = opBlendColorBurn; + break; + case BlendMethod::HardLight: + surface->blender = opBlendHardLight; + break; + case BlendMethod::SoftLight: + surface->blender = opBlendSoftLight; + break; + default: + surface->blender = nullptr; + break; + } + return false; +} + + +RenderRegion SwRenderer::region(RenderData data) +{ + return static_cast(data)->bounds(); +} + + +bool SwRenderer::beginComposite(Compositor* cmp, CompositeMethod method, uint8_t opacity) +{ + if (!cmp) return false; + auto p = static_cast(cmp); + + p->method = method; + p->opacity = opacity; + + //Current Context? + if (p->method != CompositeMethod::None) { + surface = p->recoverSfc; + surface->compositor = p; + } + + return true; +} + + +bool SwRenderer::mempool(bool shared) +{ + if (shared == sharedMpool) return true; + + if (shared) { + if (!sharedMpool) { + if (!mpoolTerm(mpool)) return false; + mpool = globalMpool; + } + } else { + if (sharedMpool) mpool = mpoolInit(threadsCnt); + } + + sharedMpool = shared; + + if (mpool) return true; + return false; +} + + +Compositor* SwRenderer::target(const RenderRegion& region, ColorSpace cs) +{ + auto x = region.x; + auto y = region.y; + auto w = region.w; + auto h = region.h; + auto sw = static_cast(surface->w); + auto sh = static_cast(surface->h); + + //Out of boundary + if (x >= sw || y >= sh || x + w < 0 || y + h < 0) return nullptr; + + SwSurface* cmp = nullptr; + + auto reqChannelSize = CHANNEL_SIZE(cs); + + //Use cached data + for (auto p = compositors.data; p < compositors.end(); ++p) { + if ((*p)->compositor->valid && (*p)->compositor->image.channelSize == reqChannelSize) { + cmp = *p; + break; + } + } + + //New Composition + if (!cmp) { + cmp = new SwSurface; + + //Inherits attributes from main surface + *cmp = *surface; + + cmp->compositor = new SwCompositor; + + //TODO: We can optimize compositor surface size from (surface->stride x surface->h) to Parameter(w x h) + cmp->compositor->image.data = (pixel_t*)malloc(reqChannelSize * surface->stride * surface->h); + cmp->channelSize = cmp->compositor->image.channelSize = reqChannelSize; + + compositors.push(cmp); + } + + //Boundary Check + if (x + w > sw) w = (sw - x); + if (y + h > sh) h = (sh - y); + + cmp->compositor->recoverSfc = surface; + cmp->compositor->recoverCmp = surface->compositor; + cmp->compositor->valid = false; + cmp->compositor->bbox.min.x = x; + cmp->compositor->bbox.min.y = y; + cmp->compositor->bbox.max.x = x + w; + cmp->compositor->bbox.max.y = y + h; + cmp->compositor->image.stride = surface->stride; + cmp->compositor->image.w = surface->w; + cmp->compositor->image.h = surface->h; + cmp->compositor->image.direct = true; + + cmp->data = cmp->compositor->image.data; + cmp->w = cmp->compositor->image.w; + cmp->h = cmp->compositor->image.h; + + rasterClear(cmp, x, y, w, h); + + //Switch render target + surface = cmp; + + return cmp->compositor; +} + + +bool SwRenderer::endComposite(Compositor* cmp) +{ + if (!cmp) return false; + + auto p = static_cast(cmp); + p->valid = true; + + //Recover Context + surface = p->recoverSfc; + surface->compositor = p->recoverCmp; + + //Default is alpha blending + if (p->method == CompositeMethod::None) { + return rasterImage(surface, &p->image, nullptr, nullptr, p->bbox, p->opacity); + } + + return true; +} + + +ColorSpace SwRenderer::colorSpace() +{ + if (surface) return surface->cs; + else return ColorSpace::Unsupported; +} + + +bool SwRenderer::dispose(RenderData data) +{ + auto task = static_cast(data); + if (!task) return true; + task->done(); + task->dispose(); + + if (task->pushed) task->disposed = true; + else delete(task); + + return true; +} + + +void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, const Array& clips, uint8_t opacity, RenderUpdateFlag flags) +{ + if (!surface) return task; + if (flags == RenderUpdateFlag::None) return task; + + //Finish previous task if it has duplicated request. + task->done(); + + //TODO: Failed threading them. It would be better if it's possible. + //See: https://github.com/thorvg/thorvg/issues/1409 + //Guarantee composition targets get ready. + for (auto clip = clips.data; clip < clips.end(); ++clip) { + static_cast(*clip)->done(); + } + + task->clips = clips; + + if (transform) { + if (!task->transform) task->transform = static_cast(malloc(sizeof(Matrix))); + *task->transform = transform->m; + } else { + if (task->transform) free(task->transform); + task->transform = nullptr; + } + + //zero size? + if (task->transform) { + if (task->transform->e11 == 0.0f && task->transform->e12 == 0.0f) return task; //zero width + if (task->transform->e21 == 0.0f && task->transform->e22 == 0.0f) return task; //zero height + } + + task->opacity = opacity; + task->surface = surface; + task->mpool = mpool; + task->flags = flags; + task->bbox.min.x = mathMax(static_cast(0), static_cast(vport.x)); + task->bbox.min.y = mathMax(static_cast(0), static_cast(vport.y)); + task->bbox.max.x = mathMin(static_cast(surface->w), static_cast(vport.x + vport.w)); + task->bbox.max.y = mathMin(static_cast(surface->h), static_cast(vport.y + vport.h)); + + if (!task->pushed) { + task->pushed = true; + tasks.push(task); + } + + TaskScheduler::request(task); + + return task; +} + + +RenderData SwRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags) +{ + //prepare task + auto task = static_cast(data); + if (!task) task = new SwImageTask; + task->source = surface; + task->mesh = mesh; + return prepareCommon(task, transform, clips, opacity, flags); +} + + +RenderData SwRenderer::prepare(const Array& scene, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags) +{ + //prepare task + auto task = static_cast(data); + if (!task) task = new SwSceneTask; + task->scene = scene; + + //TODO: Failed threading them. It would be better if it's possible. + //See: https://github.com/thorvg/thorvg/issues/1409 + //Guarantee composition targets get ready. + for (auto task = scene.data; task < scene.end(); ++task) { + static_cast(*task)->done(); + } + return prepareCommon(task, transform, clips, opacity, flags); +} + + +RenderData SwRenderer::prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) +{ + //prepare task + auto task = static_cast(data); + if (!task) { + task = new SwShapeTask; + task->rshape = &rshape; + } + task->clipper = clipper; + + return prepareCommon(task, transform, clips, opacity, flags); +} + + +SwRenderer::SwRenderer():mpool(globalMpool) +{ +} + + +bool SwRenderer::init(uint32_t threads) +{ + if ((initEngineCnt++) > 0) return true; + + threadsCnt = threads; + + //Share the memory pool among the renderer + globalMpool = mpoolInit(threads); + if (!globalMpool) { + --initEngineCnt; + return false; + } + + return true; +} + + +int32_t SwRenderer::init() +{ + return initEngineCnt; +} + + +bool SwRenderer::term() +{ + if ((--initEngineCnt) > 0) return true; + + initEngineCnt = 0; + + _termEngine(); + + return true; +} + +SwRenderer* SwRenderer::gen() +{ + ++rendererCnt; + return new SwRenderer(); +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRenderer.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRenderer.h new file mode 100644 index 000000000..8df5a2143 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRenderer.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_SW_RENDERER_H_ +#define _TVG_SW_RENDERER_H_ + +#include "tvgRender.h" + +struct SwSurface; +struct SwTask; +struct SwCompositor; +struct SwMpool; + +namespace tvg +{ + +class SwRenderer : public RenderMethod +{ +public: + RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) override; + RenderData prepare(const Array& scene, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags) override; + RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags) override; + bool preRender() override; + bool renderShape(RenderData data) override; + bool renderImage(RenderData data) override; + bool postRender() override; + bool dispose(RenderData data) override; + RenderRegion region(RenderData data) override; + RenderRegion viewport() override; + bool viewport(const RenderRegion& vp) override; + bool blend(BlendMethod method) override; + ColorSpace colorSpace() override; + + bool clear() override; + bool sync() override; + bool target(pixel_t* data, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs); + bool mempool(bool shared); + + Compositor* target(const RenderRegion& region, ColorSpace cs) override; + bool beginComposite(Compositor* cmp, CompositeMethod method, uint8_t opacity) override; + bool endComposite(Compositor* cmp) override; + void clearCompositors(); + + static SwRenderer* gen(); + static bool init(uint32_t threads); + static int32_t init(); + static bool term(); + +private: + SwSurface* surface = nullptr; //active surface + Array tasks; //async task list + Array compositors; //render targets cache list + SwMpool* mpool; //private memory pool + RenderRegion vport; //viewport + bool sharedMpool = true; //memory-pool behavior policy + + SwRenderer(); + ~SwRenderer(); + + RenderData prepareCommon(SwTask* task, const RenderTransform* transform, const Array& clips, uint8_t opacity, RenderUpdateFlag flags); +}; + +} + +#endif /* _TVG_SW_RENDERER_H_ */ + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRle.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRle.cpp new file mode 100644 index 000000000..e541e943b --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwRle.cpp @@ -0,0 +1,1134 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +/* + * The FreeType Project LICENSE + * ---------------------------- + + * 2006-Jan-27 + + * Copyright 1996-2002, 2006 by + * David Turner, Robert Wilhelm, and Werner Lemberg + + + + * Introduction + * ============ + + * The FreeType Project is distributed in several archive packages; + * some of them may contain, in addition to the FreeType font engine, + * various tools and contributions which rely on, or relate to, the + * FreeType Project. + + * This license applies to all files found in such packages, and + * which do not fall under their own explicit license. The license + * affects thus the FreeType font engine, the test programs, + * documentation and makefiles, at the very least. + + * This license was inspired by the BSD, Artistic, and IJG + * (Independent JPEG Group) licenses, which all encourage inclusion + * and use of free software in commercial and freeware products + * alike. As a consequence, its main points are that: + + * o We don't promise that this software works. However, we will be + * interested in any kind of bug reports. (`as is' distribution) + + * o You can use this software for whatever you want, in parts or + * full form, without having to pay us. (`royalty-free' usage) + + * o You may not pretend that you wrote this software. If you use + * it, or only parts of it, in a program, you must acknowledge + * somewhere in your documentation that you have used the + * FreeType code. (`credits') + + * We specifically permit and encourage the inclusion of this + * software, with or without modifications, in commercial products. + * We disclaim all warranties covering The FreeType Project and + * assume no liability related to The FreeType Project. + + + * Finally, many people asked us for a preferred form for a + * credit/disclaimer to use in compliance with this license. We thus + * encourage you to use the following text: + + * """ + * Portions of this software are copyright � The FreeType + * Project (www.freetype.org). All rights reserved. + * """ + + * Please replace with the value from the FreeType version you + * actually use. + +* Legal Terms +* =========== + +* 0. Definitions +* -------------- + +* Throughout this license, the terms `package', `FreeType Project', +* and `FreeType archive' refer to the set of files originally +* distributed by the authors (David Turner, Robert Wilhelm, and +* Werner Lemberg) as the `FreeType Project', be they named as alpha, +* beta or final release. + +* `You' refers to the licensee, or person using the project, where +* `using' is a generic term including compiling the project's source +* code as well as linking it to form a `program' or `executable'. +* This program is referred to as `a program using the FreeType +* engine'. + +* This license applies to all files distributed in the original +* FreeType Project, including all source code, binaries and +* documentation, unless otherwise stated in the file in its +* original, unmodified form as distributed in the original archive. +* If you are unsure whether or not a particular file is covered by +* this license, you must contact us to verify this. + +* The FreeType Project is copyright (C) 1996-2000 by David Turner, +* Robert Wilhelm, and Werner Lemberg. All rights reserved except as +* specified below. + +* 1. No Warranty +* -------------- + +* THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY +* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +* PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS +* BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO +* USE, OF THE FREETYPE PROJECT. + +* 2. Redistribution +* ----------------- + +* This license grants a worldwide, royalty-free, perpetual and +* irrevocable right and license to use, execute, perform, compile, +* display, copy, create derivative works of, distribute and +* sublicense the FreeType Project (in both source and object code +* forms) and derivative works thereof for any purpose; and to +* authorize others to exercise some or all of the rights granted +* herein, subject to the following conditions: + +* o Redistribution of source code must retain this license file +* (`FTL.TXT') unaltered; any additions, deletions or changes to +* the original files must be clearly indicated in accompanying +* documentation. The copyright notices of the unaltered, +* original files must be preserved in all copies of source +* files. + +* o Redistribution in binary form must provide a disclaimer that +* states that the software is based in part of the work of the +* FreeType Team, in the distribution documentation. We also +* encourage you to put an URL to the FreeType web page in your +* documentation, though this isn't mandatory. + +* These conditions apply to any software derived from or based on +* the FreeType Project, not just the unmodified files. If you use +* our work, you must acknowledge us. However, no fee need be paid +* to us. + +* 3. Advertising +* -------------- + +* Neither the FreeType authors and contributors nor you shall use +* the name of the other for commercial, advertising, or promotional +* purposes without specific prior written permission. + +* We suggest, but do not require, that you use one or more of the +* following phrases to refer to this software in your documentation +* or advertising materials: `FreeType Project', `FreeType Engine', +* `FreeType library', or `FreeType Distribution'. + +* As you have not signed this license, you are not required to +* accept it. However, as the FreeType Project is copyrighted +* material, only this license, or another one contracted with the +* authors, grants you the right to use, distribute, and modify it. +* Therefore, by using, distributing, or modifying the FreeType +* Project, you indicate that you understand and accept all the terms +* of this license. + +* 4. Contacts +* ----------- + +* There are two mailing lists related to FreeType: + +* o freetype@nongnu.org + +* Discusses general use and applications of FreeType, as well as +* future and wanted additions to the library and distribution. +* If you are looking for support, start in this list if you +* haven't found anything to help you in the documentation. + +* o freetype-devel@nongnu.org + +* Discusses bugs, as well as engine internals, design issues, +* specific licenses, porting, etc. + +* Our home page can be found at + +* http://www.freetype.org +*/ + +#include +#include +#include +#include "tvgSwCommon.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +constexpr auto MAX_SPANS = 256; +constexpr auto PIXEL_BITS = 8; //must be at least 6 bits! +constexpr auto ONE_PIXEL = (1L << PIXEL_BITS); + +using Area = long; + +struct Band +{ + SwCoord min, max; +}; + +struct Cell +{ + SwCoord x; + SwCoord cover; + Area area; + Cell *next; +}; + +struct RleWorker +{ + SwRleData* rle; + + SwPoint cellPos; + SwPoint cellMin; + SwPoint cellMax; + SwCoord cellXCnt; + SwCoord cellYCnt; + + Area area; + SwCoord cover; + + Cell* cells; + ptrdiff_t maxCells; + ptrdiff_t cellsCnt; + + SwPoint pos; + + SwPoint bezStack[32 * 3 + 1]; + int levStack[32]; + + SwOutline* outline; + + SwSpan spans[MAX_SPANS]; + int spansCnt; + int ySpan; + + int bandSize; + int bandShoot; + + jmp_buf jmpBuf; + + void* buffer; + long bufferSize; + + Cell** yCells; + SwCoord yCnt; + + bool invalid; + bool antiAlias; +}; + + +static inline SwPoint UPSCALE(const SwPoint& pt) +{ + return {SwCoord(((unsigned long) pt.x) << (PIXEL_BITS - 6)), SwCoord(((unsigned long) pt.y) << (PIXEL_BITS - 6))}; +} + + +static inline SwPoint TRUNC(const SwPoint& pt) +{ + return {pt.x >> PIXEL_BITS, pt.y >> PIXEL_BITS}; +} + + +static inline SwCoord TRUNC(const SwCoord x) +{ + return x >> PIXEL_BITS; +} + + +static inline SwPoint SUBPIXELS(const SwPoint& pt) +{ + return {SwCoord(((unsigned long) pt.x) << PIXEL_BITS), SwCoord(((unsigned long) pt.y) << PIXEL_BITS)}; +} + + +static inline SwCoord SUBPIXELS(const SwCoord x) +{ + return SwCoord(((unsigned long) x) << PIXEL_BITS); +} + +/* + * Approximate sqrt(x*x+y*y) using the `alpha max plus beta min' + * algorithm. We use alpha = 1, beta = 3/8, giving us results with a + * largest error less than 7% compared to the exact value. + */ +static inline SwCoord HYPOT(SwPoint pt) +{ + if (pt.x < 0) pt.x = -pt.x; + if (pt.y < 0) pt.y = -pt.y; + return ((pt.x > pt.y) ? (pt.x + (3 * pt.y >> 3)) : (pt.y + (3 * pt.x >> 3))); +} + +static void _genSpan(SwRleData* rle, const SwSpan* spans, uint32_t count) +{ + auto newSize = rle->size + count; + + /* allocate enough memory for new spans */ + /* alloc is required to prevent free and reallocation */ + /* when the rle needs to be regenerated because of attribute change. */ + if (rle->alloc < newSize) { + rle->alloc = (newSize * 2); + //OPTIMIZE: use mempool! + rle->spans = static_cast(realloc(rle->spans, rle->alloc * sizeof(SwSpan))); + } + + //copy the new spans to the allocated memory + SwSpan* lastSpan = rle->spans + rle->size; + memcpy(lastSpan, spans, count * sizeof(SwSpan)); + + rle->size = newSize; +} + + +static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoord acount) +{ + x += rw.cellMin.x; + y += rw.cellMin.y; + + //Clip Y range + if (y < rw.cellMin.y || y >= rw.cellMax.y) return; + + /* compute the coverage line's coverage, depending on the outline fill rule */ + /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */ + auto coverage = static_cast(area >> (PIXEL_BITS * 2 + 1 - 8)); //range 0 - 255 + + if (coverage < 0) coverage = -coverage; + + if (rw.outline->fillRule == FillRule::EvenOdd) { + coverage &= 511; + if (coverage > 255) coverage = 511 - coverage; + } else { + //normal non-zero winding rule + if (coverage > 255) coverage = 255; + } + + //span has ushort coordinates. check limit overflow + if (x >= SHRT_MAX) { + TVGERR("SW_ENGINE", "X-coordiante overflow!"); + x = SHRT_MAX; + } + if (y >= SHRT_MAX) { + TVGERR("SW_ENGINE", "Y Coordiante overflow!"); + y = SHRT_MAX; + } + + if (coverage > 0) { + if (!rw.antiAlias) coverage = 255; + auto count = rw.spansCnt; + auto span = rw.spans + count - 1; + + //see whether we can add this span to the current list + if ((count > 0) && (rw.ySpan == y) && + (span->x + span->len == x) && (span->coverage == coverage)) { + + //Clip x range + SwCoord xOver = 0; + if (x + acount >= rw.cellMax.x) xOver -= (x + acount - rw.cellMax.x); + if (x < rw.cellMin.x) xOver -= (rw.cellMin.x - x); + + //span->len += (acount + xOver) - 1; + span->len += (acount + xOver); + return; + } + + if (count >= MAX_SPANS) { + _genSpan(rw.rle, rw.spans, count); + rw.spansCnt = 0; + rw.ySpan = 0; + span = rw.spans; + } else { + ++span; + } + + //Clip x range + SwCoord xOver = 0; + if (x + acount >= rw.cellMax.x) xOver -= (x + acount - rw.cellMax.x); + if (x < rw.cellMin.x) { + xOver -= (rw.cellMin.x - x); + x = rw.cellMin.x; + } + + //Nothing to draw + if (acount + xOver <= 0) return; + + //add a span to the current list + span->x = x; + span->y = y; + span->len = (acount + xOver); + span->coverage = coverage; + ++rw.spansCnt; + rw.ySpan = y; + } +} + + +static void _sweep(RleWorker& rw) +{ + if (rw.cellsCnt == 0) return; + + rw.spansCnt = 0; + rw.ySpan = 0; + + for (int y = 0; y < rw.yCnt; ++y) { + auto cover = 0; + auto x = 0; + auto cell = rw.yCells[y]; + + while (cell) { + if (cell->x > x && cover != 0) _horizLine(rw, x, y, cover * (ONE_PIXEL * 2), cell->x - x); + cover += cell->cover; + auto area = cover * (ONE_PIXEL * 2) - cell->area; + if (area != 0 && cell->x >= 0) _horizLine(rw, cell->x, y, area, 1); + x = cell->x + 1; + cell = cell->next; + } + + if (cover != 0) _horizLine(rw, x, y, cover * (ONE_PIXEL * 2), rw.cellXCnt - x); + } + + if (rw.spansCnt > 0) _genSpan(rw.rle, rw.spans, rw.spansCnt); +} + + +static Cell* _findCell(RleWorker& rw) +{ + auto x = rw.cellPos.x; + if (x > rw.cellXCnt) x = rw.cellXCnt; + + auto pcell = &rw.yCells[rw.cellPos.y]; + + while(true) { + Cell* cell = *pcell; + if (!cell || cell->x > x) break; + if (cell->x == x) return cell; + pcell = &cell->next; + } + + if (rw.cellsCnt >= rw.maxCells) longjmp(rw.jmpBuf, 1); + + auto cell = rw.cells + rw.cellsCnt++; + cell->x = x; + cell->area = 0; + cell->cover = 0; + cell->next = *pcell; + *pcell = cell; + + return cell; +} + + +static void _recordCell(RleWorker& rw) +{ + if (rw.area | rw.cover) { + auto cell = _findCell(rw); + cell->area += rw.area; + cell->cover += rw.cover; + } +} + + +static void _setCell(RleWorker& rw, SwPoint pos) +{ + /* Move the cell pointer to a new position. We set the `invalid' */ + /* flag to indicate that the cell isn't part of those we're interested */ + /* in during the render phase. This means that: */ + /* */ + /* . the new vertical position must be within min_ey..max_ey-1. */ + /* . the new horizontal position must be strictly less than max_ex */ + /* */ + /* Note that if a cell is to the left of the clipping region, it is */ + /* actually set to the (min_ex-1) horizontal position. */ + + /* All cells that are on the left of the clipping region go to the + min_ex - 1 horizontal position. */ + pos.x -= rw.cellMin.x; + pos.y -= rw.cellMin.y; + + if (pos.x > rw.cellMax.x) pos.x = rw.cellMax.x; + + //Are we moving to a different cell? + if (pos != rw.cellPos) { + //Record the current one if it is valid + if (!rw.invalid) _recordCell(rw); + } + + rw.area = 0; + rw.cover = 0; + rw.cellPos = pos; + rw.invalid = ((unsigned)pos.y >= (unsigned)rw.cellYCnt || pos.x >= rw.cellXCnt); +} + + +static void _startCell(RleWorker& rw, SwPoint pos) +{ + if (pos.x > rw.cellMax.x) pos.x = rw.cellMax.x; + if (pos.x < rw.cellMin.x) pos.x = rw.cellMin.x; + + rw.area = 0; + rw.cover = 0; + rw.cellPos = pos - rw.cellMin; + rw.invalid = false; + + _setCell(rw, pos); +} + + +static void _moveTo(RleWorker& rw, const SwPoint& to) +{ + //record current cell, if any */ + if (!rw.invalid) _recordCell(rw); + + //start to a new position + _startCell(rw, TRUNC(to)); + + rw.pos = to; +} + + +static void _lineTo(RleWorker& rw, const SwPoint& to) +{ +#define SW_UDIV(a, b) \ + static_cast(((unsigned long)(a) * (unsigned long)(b)) >> \ + (sizeof(long) * CHAR_BIT - PIXEL_BITS)) + + auto e1 = TRUNC(rw.pos); + auto e2 = TRUNC(to); + + //vertical clipping + if ((e1.y >= rw.cellMax.y && e2.y >= rw.cellMax.y) || (e1.y < rw.cellMin.y && e2.y < rw.cellMin.y)) { + rw.pos = to; + return; + } + + auto diff = to - rw.pos; + auto f1 = rw.pos - SUBPIXELS(e1); + SwPoint f2; + + //inside one cell + if (e1 == e2) { + ; + //any horizontal line + } else if (diff.y == 0) { + e1.x = e2.x; + _setCell(rw, e1); + } else if (diff.x == 0) { + //vertical line up + if (diff.y > 0) { + do { + f2.y = ONE_PIXEL; + rw.cover += (f2.y - f1.y); + rw.area += (f2.y - f1.y) * f1.x * 2; + f1.y = 0; + ++e1.y; + _setCell(rw, e1); + } while(e1.y != e2.y); + //vertical line down + } else { + do { + f2.y = 0; + rw.cover += (f2.y - f1.y); + rw.area += (f2.y - f1.y) * f1.x * 2; + f1.y = ONE_PIXEL; + --e1.y; + _setCell(rw, e1); + } while(e1.y != e2.y); + } + //any other line + } else { + Area prod = diff.x * f1.y - diff.y * f1.x; + + /* These macros speed up repetitive divisions by replacing them + with multiplications and right shifts. */ + auto dx_r = static_cast(ULONG_MAX >> PIXEL_BITS) / (diff.x); + auto dy_r = static_cast(ULONG_MAX >> PIXEL_BITS) / (diff.y); + + /* The fundamental value `prod' determines which side and the */ + /* exact coordinate where the line exits current cell. It is */ + /* also easily updated when moving from one cell to the next. */ + do { + auto px = diff.x * ONE_PIXEL; + auto py = diff.y * ONE_PIXEL; + + //left + if (prod <= 0 && prod - px > 0) { + f2 = {0, SW_UDIV(-prod, -dx_r)}; + prod -= py; + rw.cover += (f2.y - f1.y); + rw.area += (f2.y - f1.y) * (f1.x + f2.x); + f1 = {ONE_PIXEL, f2.y}; + --e1.x; + //up + } else if (prod - px <= 0 && prod - px + py > 0) { + prod -= px; + f2 = {SW_UDIV(-prod, dy_r), ONE_PIXEL}; + rw.cover += (f2.y - f1.y); + rw.area += (f2.y - f1.y) * (f1.x + f2.x); + f1 = {f2.x, 0}; + ++e1.y; + //right + } else if (prod - px + py <= 0 && prod + py >= 0) { + prod += py; + f2 = {ONE_PIXEL, SW_UDIV(prod, dx_r)}; + rw.cover += (f2.y - f1.y); + rw.area += (f2.y - f1.y) * (f1.x + f2.x); + f1 = {0, f2.y}; + ++e1.x; + //down + } else { + f2 = {SW_UDIV(prod, -dy_r), 0}; + prod += px; + rw.cover += (f2.y - f1.y); + rw.area += (f2.y - f1.y) * (f1.x + f2.x); + f1 = {f2.x, ONE_PIXEL}; + --e1.y; + } + + _setCell(rw, e1); + + } while(e1 != e2); + } + + f2 = {to.x - SUBPIXELS(e2.x), to.y - SUBPIXELS(e2.y)}; + rw.cover += (f2.y - f1.y); + rw.area += (f2.y - f1.y) * (f1.x + f2.x); + rw.pos = to; +} + + +static void _cubicTo(RleWorker& rw, const SwPoint& ctrl1, const SwPoint& ctrl2, const SwPoint& to) +{ + auto arc = rw.bezStack; + arc[0] = to; + arc[1] = ctrl2; + arc[2] = ctrl1; + arc[3] = rw.pos; + + //Short-cut the arc that crosses the current band + auto min = arc[0].y; + auto max = arc[0].y; + + SwCoord y; + for (auto i = 1; i < 4; ++i) { + y = arc[i].y; + if (y < min) min = y; + if (y > max) max = y; + } + + if (TRUNC(min) >= rw.cellMax.y || TRUNC(max) < rw.cellMin.y) goto draw; + + /* Decide whether to split or draw. See `Rapid Termination */ + /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */ + /* F. Hain, at */ + /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */ + while (true) { + { + //diff is the P0 - P3 chord vector + auto diff = arc[3] - arc[0]; + auto L = HYPOT(diff); + + //avoid possible arithmetic overflow below by splitting + if (L > SHRT_MAX) goto split; + + //max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1) + auto sLimit = L * (ONE_PIXEL / 6); + + auto diff1 = arc[1] - arc[0]; + auto s = diff.y * diff1.x - diff.x * diff1.y; + if (s < 0) s = -s; + if (s > sLimit) goto split; + + //s is L * the perpendicular distance from P2 to the line P0 - P3 + auto diff2 = arc[2] - arc[0]; + s = diff.y * diff2.x - diff.x * diff2.y; + if (s < 0) s = -s; + if (s > sLimit) goto split; + + /* Split super curvy segments where the off points are so far + from the chord that the angles P0-P1-P3 or P0-P2-P3 become + acute as detected by appropriate dot products */ + if (diff1.x * (diff1.x - diff.x) + diff1.y * (diff1.y - diff.y) > 0 || + diff2.x * (diff2.x - diff.x) + diff2.y * (diff2.y - diff.y) > 0) + goto split; + + //no reason to split + goto draw; + } + split: + mathSplitCubic(arc); + arc += 3; + continue; + + draw: + _lineTo(rw, arc[0]); + if (arc == rw.bezStack) return; + arc -= 3; + } +} + + +static void _decomposeOutline(RleWorker& rw) +{ + auto outline = rw.outline; + auto first = 0; //index of first point in contour + + for (auto cntr = outline->cntrs.data; cntr < outline->cntrs.end(); ++cntr) { + auto last = *cntr; + auto limit = outline->pts.data + last; + auto start = UPSCALE(outline->pts[first]); + auto pt = outline->pts.data + first; + auto types = outline->types.data + first; + + _moveTo(rw, UPSCALE(outline->pts[first])); + + while (pt < limit) { + ++pt; + ++types; + + //emit a single line_to + if (types[0] == SW_CURVE_TYPE_POINT) { + _lineTo(rw, UPSCALE(*pt)); + //types cubic + } else { + pt += 2; + types += 2; + + if (pt <= limit) { + _cubicTo(rw, UPSCALE(pt[-2]), UPSCALE(pt[-1]), UPSCALE(pt[0])); + continue; + } + _cubicTo(rw, UPSCALE(pt[-2]), UPSCALE(pt[-1]), start); + goto close; + } + } + _lineTo(rw, start); + close: + first = last + 1; + } +} + + +static int _genRle(RleWorker& rw) +{ + if (setjmp(rw.jmpBuf) == 0) { + _decomposeOutline(rw); + if (!rw.invalid) _recordCell(rw); + return 0; + } + return -1; //lack of cell memory +} + + +static SwSpan* _intersectSpansRegion(const SwRleData *clip, const SwRleData *target, SwSpan *outSpans, uint32_t outSpansCnt) +{ + auto out = outSpans; + auto spans = target->spans; + auto end = target->spans + target->size; + auto clipSpans = clip->spans; + auto clipEnd = clip->spans + clip->size; + + while (spans < end && clipSpans < clipEnd) { + //align y cooridnates. + if (clipSpans->y > spans->y) { + ++spans; + continue; + } + if (spans->y > clipSpans->y) { + ++clipSpans; + continue; + } + + //Try clipping with all clip spans which have a same y coordinate. + auto temp = clipSpans; + while(temp < clipEnd && outSpansCnt > 0 && temp->y == clipSpans->y) { + auto sx1 = spans->x; + auto sx2 = sx1 + spans->len; + auto cx1 = temp->x; + auto cx2 = cx1 + temp->len; + + //The span must be left(x1) to right(x2) direction. Not intersected. + if (cx2 < sx1 || sx2 < cx1) { + ++temp; + continue; + } + + //clip span region. + auto x = sx1 > cx1 ? sx1 : cx1; + auto len = (sx2 < cx2 ? sx2 : cx2) - x; + if (len > 0) { + out->x = x; + out->y = temp->y; + out->len = len; + out->coverage = (uint8_t)(((spans->coverage * temp->coverage) + 0xff) >> 8); + ++out; + --outSpansCnt; + } + ++temp; + } + ++spans; + } + return out; +} + + +static SwSpan* _intersectSpansRect(const SwBBox *bbox, const SwRleData *targetRle, SwSpan *outSpans, uint32_t outSpansCnt) +{ + auto out = outSpans; + auto spans = targetRle->spans; + auto end = targetRle->spans + targetRle->size; + auto minx = static_cast(bbox->min.x); + auto miny = static_cast(bbox->min.y); + auto maxx = minx + static_cast(bbox->max.x - bbox->min.x) - 1; + auto maxy = miny + static_cast(bbox->max.y - bbox->min.y) - 1; + + while (outSpansCnt > 0 && spans < end) { + if (spans->y > maxy) { + spans = end; + break; + } + if (spans->y < miny || spans->x > maxx || spans->x + spans->len <= minx) { + ++spans; + continue; + } + if (spans->x < minx) { + out->len = (spans->len - (minx - spans->x)) < (maxx - minx + 1) ? (spans->len - (minx - spans->x)) : (maxx - minx + 1); + out->x = minx; + } + else { + out->x = spans->x; + out->len = spans->len < (maxx - spans->x + 1) ? spans->len : (maxx - spans->x + 1); + } + if (out->len > 0) { + out->y = spans->y; + out->coverage = spans->coverage; + ++out; + --outSpansCnt; + } + ++spans; + } + return out; +} + + +static SwSpan* _mergeSpansRegion(const SwRleData *clip1, const SwRleData *clip2, SwSpan *outSpans) +{ + auto out = outSpans; + auto spans1 = clip1->spans; + auto end1 = clip1->spans + clip1->size; + auto spans2 = clip2->spans; + auto end2 = clip2->spans + clip2->size; + + //list two spans up in y order + //TODO: Remove duplicated regions? + while (spans1 < end1 && spans2 < end2) { + while (spans1 < end1 && spans1->y <= spans2->y) { + *out = *spans1; + ++spans1; + ++out; + } + if (spans1 >= end1) break; + while (spans2 < end2 && spans2->y <= spans1->y) { + *out = *spans2; + ++spans2; + ++out; + } + } + + //Leftovers + while (spans1 < end1) { + *out = *spans1; + ++spans1; + ++out; + } + while (spans2 < end2) { + *out = *spans2; + ++spans2; + ++out; + } + + return out; +} + + +void _replaceClipSpan(SwRleData *rle, SwSpan* clippedSpans, uint32_t size) +{ + free(rle->spans); + rle->spans = clippedSpans; + rle->size = rle->alloc = size; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& renderRegion, bool antiAlias) +{ + constexpr auto RENDER_POOL_SIZE = 16384L; + constexpr auto BAND_SIZE = 40; + + //TODO: We can preserve several static workers in advance + RleWorker rw; + Cell buffer[RENDER_POOL_SIZE / sizeof(Cell)]; + + //Init Cells + rw.buffer = buffer; + rw.bufferSize = sizeof(buffer); + rw.yCells = reinterpret_cast(buffer); + rw.cells = nullptr; + rw.maxCells = 0; + rw.cellsCnt = 0; + rw.area = 0; + rw.cover = 0; + rw.invalid = true; + rw.cellMin = renderRegion.min; + rw.cellMax = renderRegion.max; + rw.cellXCnt = rw.cellMax.x - rw.cellMin.x; + rw.cellYCnt = rw.cellMax.y - rw.cellMin.y; + rw.ySpan = 0; + rw.outline = const_cast(outline); + rw.bandSize = rw.bufferSize / (sizeof(Cell) * 8); //bandSize: 64 + rw.bandShoot = 0; + rw.antiAlias = antiAlias; + + if (!rle) rw.rle = reinterpret_cast(calloc(1, sizeof(SwRleData))); + else rw.rle = rle; + + //Generate RLE + Band bands[BAND_SIZE]; + Band* band; + + /* set up vertical bands */ + auto bandCnt = static_cast((rw.cellMax.y - rw.cellMin.y) / rw.bandSize); + if (bandCnt == 0) bandCnt = 1; + else if (bandCnt >= BAND_SIZE) bandCnt = (BAND_SIZE - 1); + + auto min = rw.cellMin.y; + auto yMax = rw.cellMax.y; + SwCoord max; + int ret; + + for (int n = 0; n < bandCnt; ++n, min = max) { + max = min + rw.bandSize; + if (n == bandCnt -1 || max > yMax) max = yMax; + + bands[0].min = min; + bands[0].max = max; + band = bands; + + while (band >= bands) { + rw.yCells = static_cast(rw.buffer); + rw.yCnt = band->max - band->min; + + int cellStart = sizeof(Cell*) * (int)rw.yCnt; + int cellMod = cellStart % sizeof(Cell); + + if (cellMod > 0) cellStart += sizeof(Cell) - cellMod; + + auto cellEnd = rw.bufferSize; + cellEnd -= cellEnd % sizeof(Cell); + + auto cellsMax = reinterpret_cast((char*)rw.buffer + cellEnd); + rw.cells = reinterpret_cast((char*)rw.buffer + cellStart); + + if (rw.cells >= cellsMax) goto reduce_bands; + + rw.maxCells = cellsMax - rw.cells; + if (rw.maxCells < 2) goto reduce_bands; + + for (int y = 0; y < rw.yCnt; ++y) + rw.yCells[y] = nullptr; + + rw.cellsCnt = 0; + rw.invalid = true; + rw.cellMin.y = band->min; + rw.cellMax.y = band->max; + rw.cellYCnt = band->max - band->min; + + ret = _genRle(rw); + if (ret == 0) { + _sweep(rw); + --band; + continue; + } else if (ret == 1) { + goto error; + } + + reduce_bands: + /* render pool overflow: we will reduce the render band by half */ + auto bottom = band->min; + auto top = band->max; + auto middle = bottom + ((top - bottom) >> 1); + + /* This is too complex for a single scanline; there must + be some problems */ + if (middle == bottom) goto error; + + if (bottom - top >= rw.bandSize) ++rw.bandShoot; + + band[1].min = bottom; + band[1].max = middle; + band[0].min = middle; + band[0].max = top; + ++band; + } + } + + if (rw.bandShoot > 8 && rw.bandSize > 16) + rw.bandSize = (rw.bandSize >> 1); + + return rw.rle; + +error: + free(rw.rle); + rw.rle = nullptr; + return nullptr; +} + + +SwRleData* rleRender(const SwBBox* bbox) +{ + auto width = static_cast(bbox->max.x - bbox->min.x); + auto height = static_cast(bbox->max.y - bbox->min.y); + + auto rle = static_cast(malloc(sizeof(SwRleData))); + rle->spans = static_cast(malloc(sizeof(SwSpan) * height)); + rle->size = height; + rle->alloc = height; + + auto span = rle->spans; + for (uint16_t i = 0; i < height; ++i, ++span) { + span->x = bbox->min.x; + span->y = bbox->min.y + i; + span->len = width; + span->coverage = 255; + } + + return rle; +} + + +void rleReset(SwRleData* rle) +{ + if (!rle) return; + rle->size = 0; +} + + +void rleFree(SwRleData* rle) +{ + if (!rle) return; + if (rle->spans) free(rle->spans); + free(rle); +} + + +void rleMerge(SwRleData* rle, SwRleData* clip1, SwRleData* clip2) +{ + if (!rle || (!clip1 && !clip2)) return; + if (clip1 && clip1->size == 0 && clip2 && clip2->size == 0) return; + + TVGLOG("SW_ENGINE", "Unifying Rle!"); + + //clip1 is empty, just copy clip2 + if (!clip1 || clip1->size == 0) { + if (clip2) { + auto spans = static_cast(malloc(sizeof(SwSpan) * (clip2->size))); + memcpy(spans, clip2->spans, clip2->size); + _replaceClipSpan(rle, spans, clip2->size); + } else { + _replaceClipSpan(rle, nullptr, 0); + } + return; + } + + //clip2 is empty, just copy clip1 + if (!clip2 || clip2->size == 0) { + if (clip1) { + auto spans = static_cast(malloc(sizeof(SwSpan) * (clip1->size))); + memcpy(spans, clip1->spans, clip1->size); + _replaceClipSpan(rle, spans, clip1->size); + } else { + _replaceClipSpan(rle, nullptr, 0); + } + return; + } + + auto spanCnt = clip1->size + clip2->size; + auto spans = static_cast(malloc(sizeof(SwSpan) * spanCnt)); + auto spansEnd = _mergeSpansRegion(clip1, clip2, spans); + + _replaceClipSpan(rle, spans, spansEnd - spans); +} + + +void rleClipPath(SwRleData *rle, const SwRleData *clip) +{ + if (rle->size == 0 || clip->size == 0) return; + auto spanCnt = rle->size > clip->size ? rle->size : clip->size; + auto spans = static_cast(malloc(sizeof(SwSpan) * (spanCnt))); + auto spansEnd = _intersectSpansRegion(clip, rle, spans, spanCnt); + + _replaceClipSpan(rle, spans, spansEnd - spans); + + TVGLOG("SW_ENGINE", "Using ClipPath!"); +} + + +void rleClipRect(SwRleData *rle, const SwBBox* clip) +{ + if (rle->size == 0) return; + auto spans = static_cast(malloc(sizeof(SwSpan) * (rle->size))); + auto spansEnd = _intersectSpansRect(clip, rle, spans, rle->size); + + _replaceClipSpan(rle, spans, spansEnd - spans); + + TVGLOG("SW_ENGINE", "Using ClipRect!"); +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwShape.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwShape.cpp new file mode 100644 index 000000000..6a9ea5330 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwShape.cpp @@ -0,0 +1,686 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include "tvgSwCommon.h" +#include "tvgMath.h" +#include "tvgBezier.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +struct Line +{ + Point pt1; + Point pt2; +}; + + +static float _lineLength(const Point& pt1, const Point& pt2) +{ + /* approximate sqrt(x*x + y*y) using alpha max plus beta min algorithm. + With alpha = 1, beta = 3/8, giving results with the largest error less + than 7% compared to the exact value. */ + Point diff = {pt2.x - pt1.x, pt2.y - pt1.y}; + if (diff.x < 0) diff.x = -diff.x; + if (diff.y < 0) diff.y = -diff.y; + return (diff.x > diff.y) ? (diff.x + diff.y * 0.375f) : (diff.y + diff.x * 0.375f); +} + + +static void _lineSplitAt(const Line& cur, float at, Line& left, Line& right) +{ + auto len = _lineLength(cur.pt1, cur.pt2); + auto dx = ((cur.pt2.x - cur.pt1.x) / len) * at; + auto dy = ((cur.pt2.y - cur.pt1.y) / len) * at; + left.pt1 = cur.pt1; + left.pt2.x = left.pt1.x + dx; + left.pt2.y = left.pt1.y + dy; + right.pt1 = left.pt2; + right.pt2 = cur.pt2; +} + + +static void _outlineEnd(SwOutline& outline) +{ + if (outline.pts.empty()) return; + outline.cntrs.push(outline.pts.count - 1); +} + + +static void _outlineMoveTo(SwOutline& outline, const Point* to, const Matrix* transform) +{ + if (outline.pts.count > 0) outline.cntrs.push(outline.pts.count - 1); + + outline.pts.push(mathTransform(to, transform)); + outline.types.push(SW_CURVE_TYPE_POINT); +} + + +static void _outlineLineTo(SwOutline& outline, const Point* to, const Matrix* transform) +{ + outline.pts.push(mathTransform(to, transform)); + outline.types.push(SW_CURVE_TYPE_POINT); +} + + +static void _outlineCubicTo(SwOutline& outline, const Point* ctrl1, const Point* ctrl2, const Point* to, const Matrix* transform) +{ + outline.pts.push(mathTransform(ctrl1, transform)); + outline.types.push(SW_CURVE_TYPE_CUBIC); + + outline.pts.push(mathTransform(ctrl2, transform)); + outline.types.push(SW_CURVE_TYPE_CUBIC); + + outline.pts.push(mathTransform(to, transform)); + outline.types.push(SW_CURVE_TYPE_POINT); +} + + +static void _outlineClose(SwOutline& outline) +{ + uint32_t i = 0; + + if (outline.cntrs.count > 0) i = outline.cntrs.last() + 1; + else i = 0; //First Path + + //Make sure there is at least one point in the current path + if (outline.pts.count == i) return; + + //Close the path + outline.pts.push(outline.pts[i]); + outline.types.push(SW_CURVE_TYPE_POINT); + outline.closed.push(true); +} + + +static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* transform) +{ + Line cur = {dash.ptCur, *to}; + auto len = _lineLength(cur.pt1, cur.pt2); + + if (len < dash.curLen) { + dash.curLen -= len; + if (!dash.curOpGap) { + if (dash.move) { + _outlineMoveTo(*dash.outline, &dash.ptCur, transform); + dash.move = false; + } + _outlineLineTo(*dash.outline, to, transform); + } + } else { + while (len > dash.curLen) { + Line left, right; + if (dash.curLen > 0) { + len -= dash.curLen; + _lineSplitAt(cur, dash.curLen, left, right); + if (!dash.curOpGap) { + if (dash.move || dash.pattern[dash.curIdx] - dash.curLen < FLT_EPSILON) { + _outlineMoveTo(*dash.outline, &left.pt1, transform); + dash.move = false; + } + _outlineLineTo(*dash.outline, &left.pt2, transform); + } + } else { + right = cur; + } + dash.curIdx = (dash.curIdx + 1) % dash.cnt; + dash.curLen = dash.pattern[dash.curIdx]; + dash.curOpGap = !dash.curOpGap; + cur = right; + dash.ptCur = cur.pt1; + dash.move = true; + } + //leftovers + dash.curLen -= len; + if (!dash.curOpGap) { + if (dash.move) { + _outlineMoveTo(*dash.outline, &cur.pt1, transform); + dash.move = false; + } + _outlineLineTo(*dash.outline, &cur.pt2, transform); + } + if (dash.curLen < 1 && TO_SWCOORD(len) > 1) { + //move to next dash + dash.curIdx = (dash.curIdx + 1) % dash.cnt; + dash.curLen = dash.pattern[dash.curIdx]; + dash.curOpGap = !dash.curOpGap; + } + } + dash.ptCur = *to; +} + + +static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ctrl2, const Point* to, const Matrix* transform) +{ + Bezier cur = {dash.ptCur, *ctrl1, *ctrl2, *to}; + auto len = bezLength(cur); + + if (len < dash.curLen) { + dash.curLen -= len; + if (!dash.curOpGap) { + if (dash.move) { + _outlineMoveTo(*dash.outline, &dash.ptCur, transform); + dash.move = false; + } + _outlineCubicTo(*dash.outline, ctrl1, ctrl2, to, transform); + } + } else { + while (len > dash.curLen) { + Bezier left, right; + if (dash.curLen > 0) { + len -= dash.curLen; + bezSplitAt(cur, dash.curLen, left, right); + if (!dash.curOpGap) { + if (dash.move || dash.pattern[dash.curIdx] - dash.curLen < FLT_EPSILON) { + _outlineMoveTo(*dash.outline, &left.start, transform); + dash.move = false; + } + _outlineCubicTo(*dash.outline, &left.ctrl1, &left.ctrl2, &left.end, transform); + } + } else { + right = cur; + } + dash.curIdx = (dash.curIdx + 1) % dash.cnt; + dash.curLen = dash.pattern[dash.curIdx]; + dash.curOpGap = !dash.curOpGap; + cur = right; + dash.ptCur = right.start; + dash.move = true; + } + //leftovers + dash.curLen -= len; + if (!dash.curOpGap) { + if (dash.move) { + _outlineMoveTo(*dash.outline, &cur.start, transform); + dash.move = false; + } + _outlineCubicTo(*dash.outline, &cur.ctrl1, &cur.ctrl2, &cur.end, transform); + } + if (dash.curLen < 1 && TO_SWCOORD(len) > 1) { + //move to next dash + dash.curIdx = (dash.curIdx + 1) % dash.cnt; + dash.curLen = dash.pattern[dash.curIdx]; + dash.curOpGap = !dash.curOpGap; + } + } + dash.ptCur = *to; +} + + +static void _dashClose(SwDashStroke& dash, const Matrix* transform) +{ + _dashLineTo(dash, &dash.ptStart, transform); +} + + +static void _dashMoveTo(SwDashStroke& dash, uint32_t offIdx, float offset, const Point* pts, const Matrix* transform) +{ + dash.curIdx = offIdx % dash.cnt; + dash.curLen = dash.pattern[dash.curIdx] - offset; + dash.curOpGap = offIdx % 2; + dash.ptStart = dash.ptCur = *pts; + dash.move = true; +} + + +static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* transform, float length, SwMpool* mpool, unsigned tid) +{ + const PathCommand* cmds = rshape->path.cmds.data; + auto cmdCnt = rshape->path.cmds.count; + const Point* pts = rshape->path.pts.data; + auto ptsCnt = rshape->path.pts.count; + + //No actual shape data + if (cmdCnt == 0 || ptsCnt == 0) return nullptr; + + SwDashStroke dash; + auto offset = 0.0f; + auto trimmed = false; + + dash.cnt = rshape->strokeDash((const float**)&dash.pattern, &offset); + + //dash by trimming. + if (length > 0.0f && dash.cnt == 0) { + auto begin = length * rshape->stroke->trim.begin; + auto end = length * rshape->stroke->trim.end; + + //TODO: mix trimming + dash style + + //default + if (end > begin) { + if (begin > 0) dash.cnt += 4; + else dash.cnt += 2; + //looping + } else dash.cnt += 3; + + dash.pattern = (float*)malloc(sizeof(float) * dash.cnt); + + if (dash.cnt == 2) { + dash.pattern[0] = end - begin; + dash.pattern[1] = length - (end - begin); + } else if (dash.cnt == 3) { + dash.pattern[0] = end; + dash.pattern[1] = (begin - end); + dash.pattern[2] = length - begin; + } else { + dash.pattern[0] = 0; //zero dash to start with a space. + dash.pattern[1] = begin; + dash.pattern[2] = end - begin; + dash.pattern[3] = length - (end - begin); + } + + trimmed = true; + //just a dasy style. + } else { + if (dash.cnt == 0) return nullptr; + } + + //offset? + auto patternLength = 0.0f; + uint32_t offIdx = 0; + if (!mathZero(offset)) { + for (size_t i = 0; i < dash.cnt; ++i) patternLength += dash.pattern[i]; + bool isOdd = dash.cnt % 2; + if (isOdd) patternLength *= 2; + + offset = fmod(offset, patternLength); + if (offset < 0) offset += patternLength; + + for (size_t i = 0; i < dash.cnt * (1 + (size_t)isOdd); ++i, ++offIdx) { + auto curPattern = dash.pattern[i % dash.cnt]; + if (offset < curPattern) break; + offset -= curPattern; + } + } + + dash.outline = mpoolReqDashOutline(mpool, tid); + + //smart reservation + auto closeCnt = 0; + auto moveCnt = 0; + + for (auto cmd = rshape->path.cmds.data; cmd < rshape->path.cmds.end(); ++cmd) { + if (*cmd == PathCommand::Close) ++closeCnt; + else if (*cmd == PathCommand::MoveTo) ++moveCnt; + } + + //No idea exact count.... Reserve Approximitely 20x... + //OPTIMIZE: we can directly copy the path points when the close is occupied with a point. + dash.outline->pts.grow(20 * (closeCnt + ptsCnt + 1)); + dash.outline->types.grow(20 * (closeCnt + ptsCnt + 1)); + dash.outline->cntrs.grow(20 * (moveCnt + 1)); + + while (cmdCnt-- > 0) { + switch (*cmds) { + case PathCommand::Close: { + _dashClose(dash, transform); + break; + } + case PathCommand::MoveTo: { + _dashMoveTo(dash, offIdx, offset, pts, transform); + ++pts; + break; + } + case PathCommand::LineTo: { + _dashLineTo(dash, pts, transform); + ++pts; + break; + } + case PathCommand::CubicTo: { + _dashCubicTo(dash, pts, pts + 1, pts + 2, transform); + pts += 3; + break; + } + } + ++cmds; + } + + _outlineEnd(*dash.outline); + + if (trimmed) free(dash.pattern); + + return dash.outline; +} + + +static float _outlineLength(const RenderShape* rshape) +{ + const PathCommand* cmds = rshape->path.cmds.data; + auto cmdCnt = rshape->path.cmds.count; + const Point* pts = rshape->path.pts.data; + auto ptsCnt = rshape->path.pts.count; + + //No actual shape data + if (cmdCnt == 0 || ptsCnt == 0) return 0.0f; + + const Point* close = nullptr; + auto length = 0.0f; + + //Compute the whole length + while (cmdCnt-- > 0) { + switch (*cmds) { + case PathCommand::Close: { + length += mathLength(pts - 1, close); + ++pts; + break; + } + case PathCommand::MoveTo: { + close = pts; + ++pts; + break; + } + case PathCommand::LineTo: { + length += mathLength(pts - 1, pts); + ++pts; + break; + } + case PathCommand::CubicTo: { + length += bezLength({*(pts - 1), *pts, *(pts + 1), *(pts + 2)}); + pts += 3; + break; + } + } + ++cmds; + } + return length; +} + + +static bool _axisAlignedRect(const SwOutline* outline) +{ + //Fast Track: axis-aligned rectangle? + if (outline->pts.count != 5) return false; + + auto pt1 = outline->pts.data + 0; + auto pt2 = outline->pts.data + 1; + auto pt3 = outline->pts.data + 2; + auto pt4 = outline->pts.data + 3; + + auto a = SwPoint{pt1->x, pt3->y}; + auto b = SwPoint{pt3->x, pt1->y}; + + if ((*pt2 == a && *pt4 == b) || (*pt2 == b && *pt4 == a)) return true; + + return false; +} + + +static bool _genOutline(SwShape* shape, const RenderShape* rshape, const Matrix* transform, SwMpool* mpool, unsigned tid, bool hasComposite) +{ + const PathCommand* cmds = rshape->path.cmds.data; + auto cmdCnt = rshape->path.cmds.count; + const Point* pts = rshape->path.pts.data; + auto ptsCnt = rshape->path.pts.count; + + //No actual shape data + if (cmdCnt == 0 || ptsCnt == 0) return false; + + //smart reservation + auto moveCnt = 0; + auto closeCnt = 0; + + for (auto cmd = rshape->path.cmds.data; cmd < rshape->path.cmds.end(); ++cmd) { + if (*cmd == PathCommand::Close) ++closeCnt; + else if (*cmd == PathCommand::MoveTo) ++moveCnt; + } + + shape->outline = mpoolReqOutline(mpool, tid); + auto outline = shape->outline; + + //OPTIMIZE: we can directly copy the path points when the close is occupied with a point. + outline->pts.grow(ptsCnt + closeCnt + 1); + outline->types.grow(ptsCnt + closeCnt + 1); + outline->cntrs.grow(moveCnt + 1); + + //Dash outlines are always opened. + //Only normal outlines use this information, it sholud be same to their contour counts. + outline->closed.reserve(outline->cntrs.reserved); + + memset(outline->closed.data, 0x0, sizeof(bool) * outline->closed.reserved); + + //Generate Outlines + while (cmdCnt-- > 0) { + switch (*cmds) { + case PathCommand::Close: { + _outlineClose(*outline); + break; + } + case PathCommand::MoveTo: { + _outlineMoveTo(*outline, pts, transform); + ++pts; + break; + } + case PathCommand::LineTo: { + _outlineLineTo(*outline, pts, transform); + ++pts; + break; + } + case PathCommand::CubicTo: { + _outlineCubicTo(*outline, pts, pts + 1, pts + 2, transform); + pts += 3; + break; + } + } + ++cmds; + } + + _outlineEnd(*outline); + + outline->fillRule = rshape->rule; + shape->outline = outline; + + shape->fastTrack = (!hasComposite && _axisAlignedRect(shape->outline)); + return true; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +bool shapePrepare(SwShape* shape, const RenderShape* rshape, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite) +{ + if (!_genOutline(shape, rshape, transform, mpool, tid, hasComposite)) return false; + if (!mathUpdateOutlineBBox(shape->outline, clipRegion, renderRegion, shape->fastTrack)) return false; + + //Keep it for Rasterization Region + shape->bbox = renderRegion; + + //Check valid region + if (renderRegion.max.x - renderRegion.min.x < 1 && renderRegion.max.y - renderRegion.min.y < 1) return false; + + //Check boundary + if (renderRegion.min.x >= clipRegion.max.x || renderRegion.min.y >= clipRegion.max.y || + renderRegion.max.x <= clipRegion.min.x || renderRegion.max.y <= clipRegion.min.y) return false; + + return true; +} + + +bool shapePrepared(const SwShape* shape) +{ + return shape->rle ? true : false; +} + + +bool shapeGenRle(SwShape* shape, TVG_UNUSED const RenderShape* rshape, bool antiAlias) +{ + //FIXME: Should we draw it? + //Case: Stroke Line + //if (shape.outline->opened) return true; + + //Case A: Fast Track Rectangle Drawing + if (shape->fastTrack) return true; + + //Case B: Normal Shape RLE Drawing + if ((shape->rle = rleRender(shape->rle, shape->outline, shape->bbox, antiAlias))) return true; + + return false; +} + + +void shapeDelOutline(SwShape* shape, SwMpool* mpool, uint32_t tid) +{ + mpoolRetOutline(mpool, tid); + shape->outline = nullptr; +} + + +void shapeReset(SwShape* shape) +{ + rleReset(shape->rle); + rleReset(shape->strokeRle); + shape->fastTrack = false; + shape->bbox.reset(); +} + + +void shapeFree(SwShape* shape) +{ + rleFree(shape->rle); + shapeDelFill(shape); + + if (shape->stroke) { + rleFree(shape->strokeRle); + strokeFree(shape->stroke); + } +} + + +void shapeDelStroke(SwShape* shape) +{ + if (!shape->stroke) return; + rleFree(shape->strokeRle); + shape->strokeRle = nullptr; + strokeFree(shape->stroke); + shape->stroke = nullptr; +} + + +void shapeResetStroke(SwShape* shape, const RenderShape* rshape, const Matrix* transform) +{ + if (!shape->stroke) shape->stroke = static_cast(calloc(1, sizeof(SwStroke))); + auto stroke = shape->stroke; + if (!stroke) return; + + strokeReset(stroke, rshape, transform); + rleReset(shape->strokeRle); +} + + +bool shapeGenStrokeRle(SwShape* shape, const RenderShape* rshape, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid) +{ + SwOutline* shapeOutline = nullptr; + SwOutline* strokeOutline = nullptr; + auto dashStroking = false; + auto ret = true; + + auto length = rshape->strokeTrim() ? _outlineLength(rshape) : 0.0f; + + //Dash style (+trimming) + if (rshape->stroke->dashCnt > 0 || length > 0) { + shapeOutline = _genDashOutline(rshape, transform, length, mpool, tid); + if (!shapeOutline) return false; + dashStroking = true; + //Normal style + } else { + if (!shape->outline) { + if (!_genOutline(shape, rshape, transform, mpool, tid, false)) return false; + } + shapeOutline = shape->outline; + } + + if (!strokeParseOutline(shape->stroke, *shapeOutline)) { + ret = false; + goto clear; + } + + strokeOutline = strokeExportOutline(shape->stroke, mpool, tid); + + if (!mathUpdateOutlineBBox(strokeOutline, clipRegion, renderRegion, false)) { + ret = false; + goto clear; + } + + shape->strokeRle = rleRender(shape->strokeRle, strokeOutline, renderRegion, true); + +clear: + if (dashStroking) mpoolRetDashOutline(mpool, tid); + mpoolRetStrokeOutline(mpool, tid); + + return ret; +} + + +bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint8_t opacity, bool ctable) +{ + return fillGenColorTable(shape->fill, fill, transform, surface, opacity, ctable); +} + + +bool shapeGenStrokeFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint8_t opacity, bool ctable) +{ + return fillGenColorTable(shape->stroke->fill, fill, transform, surface, opacity, ctable); +} + + +void shapeResetFill(SwShape* shape) +{ + if (!shape->fill) { + shape->fill = static_cast(calloc(1, sizeof(SwFill))); + if (!shape->fill) return; + } + fillReset(shape->fill); +} + + +void shapeResetStrokeFill(SwShape* shape) +{ + if (!shape->stroke->fill) { + shape->stroke->fill = static_cast(calloc(1, sizeof(SwFill))); + if (!shape->stroke->fill) return; + } + fillReset(shape->stroke->fill); +} + + +void shapeDelFill(SwShape* shape) +{ + if (!shape->fill) return; + fillFree(shape->fill); + shape->fill = nullptr; +} + + +void shapeDelStrokeFill(SwShape* shape) +{ + if (!shape->stroke->fill) return; + fillFree(shape->stroke->fill); + shape->stroke->fill = nullptr; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwStroke.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwStroke.cpp new file mode 100644 index 000000000..c097c6063 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgSwStroke.cpp @@ -0,0 +1,915 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include +#include +#include "tvgSwCommon.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static constexpr auto SW_STROKE_TAG_POINT = 1; +static constexpr auto SW_STROKE_TAG_CUBIC = 2; +static constexpr auto SW_STROKE_TAG_BEGIN = 4; +static constexpr auto SW_STROKE_TAG_END = 8; + +static inline SwFixed SIDE_TO_ROTATE(const int32_t s) +{ + return (SW_ANGLE_PI2 - static_cast(s) * SW_ANGLE_PI); +} + + +static inline void SCALE(const SwStroke& stroke, SwPoint& pt) +{ + pt.x = static_cast(pt.x * stroke.sx); + pt.y = static_cast(pt.y * stroke.sy); +} + + +static void _growBorder(SwStrokeBorder* border, uint32_t newPts) +{ + auto maxOld = border->maxPts; + auto maxNew = border->ptsCnt + newPts; + + if (maxNew <= maxOld) return; + + auto maxCur = maxOld; + + while (maxCur < maxNew) + maxCur += (maxCur >> 1) + 16; + //OPTIMIZE: use mempool! + border->pts = static_cast(realloc(border->pts, maxCur * sizeof(SwPoint))); + border->tags = static_cast(realloc(border->tags, maxCur * sizeof(uint8_t))); + border->maxPts = maxCur; +} + + +static void _borderClose(SwStrokeBorder* border, bool reverse) +{ + auto start = border->start; + auto count = border->ptsCnt; + + //Don't record empty paths! + if (count <= start + 1U) { + border->ptsCnt = start; + } else { + /* Copy the last point to the start of this sub-path, + since it contains the adjusted starting coordinates */ + border->ptsCnt = --count; + border->pts[start] = border->pts[count]; + + if (reverse) { + //reverse the points + auto pt1 = border->pts + start + 1; + auto pt2 = border->pts + count - 1; + + while (pt1 < pt2) { + auto tmp = *pt1; + *pt1 = *pt2; + *pt2 = tmp; + ++pt1; + --pt2; + } + + //reverse the tags + auto tag1 = border->tags + start + 1; + auto tag2 = border->tags + count - 1; + + while (tag1 < tag2) { + auto tmp = *tag1; + *tag1 = *tag2; + *tag2 = tmp; + ++tag1; + --tag2; + } + } + + border->tags[start] |= SW_STROKE_TAG_BEGIN; + border->tags[count - 1] |= SW_STROKE_TAG_END; + } + + border->start = -1; + border->movable = false; +} + + +static void _borderCubicTo(SwStrokeBorder* border, const SwPoint& ctrl1, const SwPoint& ctrl2, const SwPoint& to) +{ + _growBorder(border, 3); + + auto pt = border->pts + border->ptsCnt; + auto tag = border->tags + border->ptsCnt; + + pt[0] = ctrl1; + pt[1] = ctrl2; + pt[2] = to; + + tag[0] = SW_STROKE_TAG_CUBIC; + tag[1] = SW_STROKE_TAG_CUBIC; + tag[2] = SW_STROKE_TAG_POINT; + + border->ptsCnt += 3; + border->movable = false; +} + + +static void _borderArcTo(SwStrokeBorder* border, const SwPoint& center, SwFixed radius, SwFixed angleStart, SwFixed angleDiff, SwStroke& stroke) +{ + constexpr SwFixed ARC_CUBIC_ANGLE = SW_ANGLE_PI / 2; + SwPoint a = {static_cast(radius), 0}; + mathRotate(a, angleStart); + SCALE(stroke, a); + a += center; + + auto total = angleDiff; + auto angle = angleStart; + auto rotate = (angleDiff >= 0) ? SW_ANGLE_PI2 : -SW_ANGLE_PI2; + + while (total != 0) { + auto step = total; + if (step > ARC_CUBIC_ANGLE) step = ARC_CUBIC_ANGLE; + else if (step < -ARC_CUBIC_ANGLE) step = -ARC_CUBIC_ANGLE; + + auto next = angle + step; + auto theta = step; + if (theta < 0) theta = -theta; + + theta >>= 1; + + //compute end point + SwPoint b = {static_cast(radius), 0}; + mathRotate(b, next); + SCALE(stroke, b); + b += center; + + //compute first and second control points + auto length = mathMulDiv(radius, mathSin(theta) * 4, (0x10000L + mathCos(theta)) * 3); + + SwPoint a2 = {static_cast(length), 0}; + mathRotate(a2, angle + rotate); + SCALE(stroke, a2); + a2 += a; + + SwPoint b2 = {static_cast(length), 0}; + mathRotate(b2, next - rotate); + SCALE(stroke, b2); + b2 += b; + + //add cubic arc + _borderCubicTo(border, a2, b2, b); + + //process the rest of the arc? + a = b; + total -= step; + angle = next; + } +} + + +static void _borderLineTo(SwStrokeBorder* border, const SwPoint& to, bool movable) +{ + if (border->movable) { + //move last point + border->pts[border->ptsCnt - 1] = to; + } else { + //don't add zero-length line_to + if (border->ptsCnt > 0 && (border->pts[border->ptsCnt - 1] - to).small()) return; + + _growBorder(border, 1); + border->pts[border->ptsCnt] = to; + border->tags[border->ptsCnt] = SW_STROKE_TAG_POINT; + border->ptsCnt += 1; + } + + border->movable = movable; +} + + +static void _borderMoveTo(SwStrokeBorder* border, SwPoint& to) +{ + //close current open path if any? + if (border->start >= 0) _borderClose(border, false); + + border->start = border->ptsCnt; + border->movable = false; + + _borderLineTo(border, to, false); +} + + +static void _arcTo(SwStroke& stroke, int32_t side) +{ + auto border = stroke.borders + side; + auto rotate = SIDE_TO_ROTATE(side); + auto total = mathDiff(stroke.angleIn, stroke.angleOut); + if (total == SW_ANGLE_PI) total = -rotate * 2; + + _borderArcTo(border, stroke.center, stroke.width, stroke.angleIn + rotate, total, stroke); + border->movable = false; +} + + +static void _outside(SwStroke& stroke, int32_t side, SwFixed lineLength) +{ + auto border = stroke.borders + side; + + if (stroke.join == StrokeJoin::Round) { + _arcTo(stroke, side); + } else { + //this is a mitered (pointed) or beveled (truncated) corner + auto rotate = SIDE_TO_ROTATE(side); + auto bevel = (stroke.join == StrokeJoin::Bevel) ? true : false; + SwFixed phi = 0; + SwFixed thcos = 0; + + if (!bevel) { + auto theta = mathDiff(stroke.angleIn, stroke.angleOut); + if (theta == SW_ANGLE_PI) { + theta = rotate; + phi = stroke.angleIn; + } else { + theta /= 2; + phi = stroke.angleIn + theta + rotate; + } + + thcos = mathCos(theta); + auto sigma = mathMultiply(stroke.miterlimit, thcos); + + //is miter limit exceeded? + if (sigma < 0x10000L) bevel = true; + } + + //this is a bevel (broken angle) + if (bevel) { + SwPoint delta = {static_cast(stroke.width), 0}; + mathRotate(delta, stroke.angleOut + rotate); + SCALE(stroke, delta); + delta += stroke.center; + border->movable = false; + _borderLineTo(border, delta, false); + //this is a miter (intersection) + } else { + auto length = mathDivide(stroke.width, thcos); + SwPoint delta = {static_cast(length), 0}; + mathRotate(delta, phi); + SCALE(stroke, delta); + delta += stroke.center; + _borderLineTo(border, delta, false); + + /* Now add and end point + Only needed if not lineto (lineLength is zero for curves) */ + if (lineLength == 0) { + delta = {static_cast(stroke.width), 0}; + mathRotate(delta, stroke.angleOut + rotate); + SCALE(stroke, delta); + delta += stroke.center; + _borderLineTo(border, delta, false); + } + } + } +} + + +static void _inside(SwStroke& stroke, int32_t side, SwFixed lineLength) +{ + auto border = stroke.borders + side; + auto theta = mathDiff(stroke.angleIn, stroke.angleOut) / 2; + SwPoint delta; + bool intersect = false; + + /* Only intersect borders if between two line_to's and both + lines are long enough (line length is zero for curves). */ + if (border->movable && lineLength > 0) { + //compute minimum required length of lines + SwFixed minLength = abs(mathMultiply(stroke.width, mathTan(theta))); + if (stroke.lineLength >= minLength && lineLength >= minLength) intersect = true; + } + + auto rotate = SIDE_TO_ROTATE(side); + + if (!intersect) { + delta = {static_cast(stroke.width), 0}; + mathRotate(delta, stroke.angleOut + rotate); + SCALE(stroke, delta); + delta += stroke.center; + border->movable = false; + } else { + //compute median angle + auto phi = stroke.angleIn + theta; + auto thcos = mathCos(theta); + delta = {static_cast(mathDivide(stroke.width, thcos)), 0}; + mathRotate(delta, phi + rotate); + SCALE(stroke, delta); + delta += stroke.center; + } + + _borderLineTo(border, delta, false); +} + + +void _processCorner(SwStroke& stroke, SwFixed lineLength) +{ + auto turn = mathDiff(stroke.angleIn, stroke.angleOut); + + //no specific corner processing is required if the turn is 0 + if (turn == 0) return; + + //when we turn to the right, the inside side is 0 + int32_t inside = 0; + + //otherwise, the inside is 1 + if (turn < 0) inside = 1; + + //process the inside + _inside(stroke, inside, lineLength); + + //process the outside + _outside(stroke, 1 - inside, lineLength); +} + + +void _firstSubPath(SwStroke& stroke, SwFixed startAngle, SwFixed lineLength) +{ + SwPoint delta = {static_cast(stroke.width), 0}; + mathRotate(delta, startAngle + SW_ANGLE_PI2); + SCALE(stroke, delta); + + auto pt = stroke.center + delta; + auto border = stroke.borders; + _borderMoveTo(border, pt); + + pt = stroke.center - delta; + ++border; + _borderMoveTo(border, pt); + + /* Save angle, position and line length for last join + lineLength is zero for curves */ + stroke.subPathAngle = startAngle; + stroke.firstPt = false; + stroke.subPathLineLength = lineLength; +} + + +static void _lineTo(SwStroke& stroke, const SwPoint& to) +{ + auto delta = to - stroke.center; + + //a zero-length lineto is a no-op; avoid creating a spurious corner + if (delta.zero()) return; + + //compute length of line + auto angle = mathAtan(delta); + + /* The lineLength is used to determine the intersection of strokes outlines. + The scale needs to be reverted since the stroke width has not been scaled. + An alternative option is to scale the width of the stroke properly by + calculating the mixture of the sx/sy rating on the stroke direction. */ + delta.x = static_cast(delta.x / stroke.sx); + delta.y = static_cast(delta.y / stroke.sy); + auto lineLength = mathLength(delta); + + delta = {static_cast(stroke.width), 0}; + mathRotate(delta, angle + SW_ANGLE_PI2); + SCALE(stroke, delta); + + //process corner if necessary + if (stroke.firstPt) { + /* This is the first segment of a subpath. We need to add a point to each border + at their respective starting point locations. */ + _firstSubPath(stroke, angle, lineLength); + } else { + //process the current corner + stroke.angleOut = angle; + _processCorner(stroke, lineLength); + } + + //now add a line segment to both the inside and outside paths + auto border = stroke.borders; + auto side = 1; + + while (side >= 0) { + auto pt = to + delta; + + //the ends of lineto borders are movable + _borderLineTo(border, pt, true); + + delta.x = -delta.x; + delta.y = -delta.y; + + --side; + ++border; + } + + stroke.angleIn = angle; + stroke.center = to; + stroke.lineLength = lineLength; +} + + +static void _cubicTo(SwStroke& stroke, const SwPoint& ctrl1, const SwPoint& ctrl2, const SwPoint& to) +{ + SwPoint bezStack[37]; //TODO: static? + auto limit = bezStack + 32; + auto arc = bezStack; + auto firstArc = true; + arc[0] = to; + arc[1] = ctrl2; + arc[2] = ctrl1; + arc[3] = stroke.center; + + while (arc >= bezStack) { + SwFixed angleIn, angleOut, angleMid; + + //initialize with current direction + angleIn = angleOut = angleMid = stroke.angleIn; + + if (arc < limit && !mathSmallCubic(arc, angleIn, angleMid, angleOut)) { + if (stroke.firstPt) stroke.angleIn = angleIn; + mathSplitCubic(arc); + arc += 3; + continue; + } + + if (firstArc) { + firstArc = false; + //process corner if necessary + if (stroke.firstPt) { + _firstSubPath(stroke, angleIn, 0); + } else { + stroke.angleOut = angleIn; + _processCorner(stroke, 0); + } + } else if (abs(mathDiff(stroke.angleIn, angleIn)) > (SW_ANGLE_PI / 8) / 4) { + //if the deviation from one arc to the next is too great add a round corner + stroke.center = arc[3]; + stroke.angleOut = angleIn; + stroke.join = StrokeJoin::Round; + + _processCorner(stroke, 0); + + //reinstate line join style + stroke.join = stroke.joinSaved; + } + + //the arc's angle is small enough; we can add it directly to each border + auto theta1 = mathDiff(angleIn, angleMid) / 2; + auto theta2 = mathDiff(angleMid, angleOut) / 2; + auto phi1 = mathMean(angleIn, angleMid); + auto phi2 = mathMean(angleMid, angleOut); + auto length1 = mathDivide(stroke.width, mathCos(theta1)); + auto length2 = mathDivide(stroke.width, mathCos(theta2)); + SwFixed alpha0 = 0; + + //compute direction of original arc + if (stroke.handleWideStrokes) { + alpha0 = mathAtan(arc[0] - arc[3]); + } + + auto border = stroke.borders; + int32_t side = 0; + + while (side < 2) { + auto rotate = SIDE_TO_ROTATE(side); + + //compute control points + SwPoint _ctrl1 = {static_cast(length1), 0}; + mathRotate(_ctrl1, phi1 + rotate); + SCALE(stroke, _ctrl1); + _ctrl1 += arc[2]; + + SwPoint _ctrl2 = {static_cast(length2), 0}; + mathRotate(_ctrl2, phi2 + rotate); + SCALE(stroke, _ctrl2); + _ctrl2 += arc[1]; + + //compute end point + SwPoint _end = {static_cast(stroke.width), 0}; + mathRotate(_end, angleOut + rotate); + SCALE(stroke, _end); + _end += arc[0]; + + if (stroke.handleWideStrokes) { + /* determine whether the border radius is greater than the radius of + curvature of the original arc */ + auto _start = border->pts[border->ptsCnt - 1]; + auto alpha1 = mathAtan(_end - _start); + + //is the direction of the border arc opposite to that of the original arc? + if (abs(mathDiff(alpha0, alpha1)) > SW_ANGLE_PI / 2) { + + //use the sine rule to find the intersection point + auto beta = mathAtan(arc[3] - _start); + auto gamma = mathAtan(arc[0] - _end); + auto bvec = _end - _start; + auto blen = mathLength(bvec); + auto sinA = abs(mathSin(alpha1 - gamma)); + auto sinB = abs(mathSin(beta - gamma)); + auto alen = mathMulDiv(blen, sinA, sinB); + + SwPoint delta = {static_cast(alen), 0}; + mathRotate(delta, beta); + delta += _start; + + //circumnavigate the negative sector backwards + border->movable = false; + _borderLineTo(border, delta, false); + _borderLineTo(border, _end, false); + _borderCubicTo(border, _ctrl2, _ctrl1, _start); + + //and then move to the endpoint + _borderLineTo(border, _end, false); + + ++side; + ++border; + continue; + } + } + _borderCubicTo(border, _ctrl1, _ctrl2, _end); + ++side; + ++border; + } + arc -= 3; + stroke.angleIn = angleOut; + } + stroke.center = to; +} + + +static void _addCap(SwStroke& stroke, SwFixed angle, int32_t side) +{ + if (stroke.cap == StrokeCap::Square) { + auto rotate = SIDE_TO_ROTATE(side); + auto border = stroke.borders + side; + + SwPoint delta = {static_cast(stroke.width), 0}; + mathRotate(delta, angle); + SCALE(stroke, delta); + + SwPoint delta2 = {static_cast(stroke.width), 0}; + mathRotate(delta2, angle + rotate); + SCALE(stroke, delta2); + delta += stroke.center + delta2; + + _borderLineTo(border, delta, false); + + delta = {static_cast(stroke.width), 0}; + mathRotate(delta, angle); + SCALE(stroke, delta); + + delta2 = {static_cast(stroke.width), 0}; + mathRotate(delta2, angle - rotate); + SCALE(stroke, delta2); + delta += delta2 + stroke.center; + + _borderLineTo(border, delta, false); + + } else if (stroke.cap == StrokeCap::Round) { + + stroke.angleIn = angle; + stroke.angleOut = angle + SW_ANGLE_PI; + _arcTo(stroke, side); + return; + + } else { //Butt + auto rotate = SIDE_TO_ROTATE(side); + auto border = stroke.borders + side; + + SwPoint delta = {static_cast(stroke.width), 0}; + mathRotate(delta, angle + rotate); + SCALE(stroke, delta); + delta += stroke.center; + + _borderLineTo(border, delta, false); + + delta = {static_cast(stroke.width), 0}; + mathRotate(delta, angle - rotate); + SCALE(stroke, delta); + delta += stroke.center; + + _borderLineTo(border, delta, false); + } +} + + +static void _addReverseLeft(SwStroke& stroke, bool opened) +{ + auto right = stroke.borders + 0; + auto left = stroke.borders + 1; + auto newPts = left->ptsCnt - left->start; + + if (newPts <= 0) return; + + _growBorder(right, newPts); + + auto dstPt = right->pts + right->ptsCnt; + auto dstTag = right->tags + right->ptsCnt; + auto srcPt = left->pts + left->ptsCnt - 1; + auto srcTag = left->tags + left->ptsCnt - 1; + + while (srcPt >= left->pts + left->start) { + *dstPt = *srcPt; + *dstTag = *srcTag; + + if (opened) { + dstTag[0] &= ~(SW_STROKE_TAG_BEGIN | SW_STROKE_TAG_END); + } else { + //switch begin/end tags if necessary + auto ttag = dstTag[0] & (SW_STROKE_TAG_BEGIN | SW_STROKE_TAG_END); + if (ttag == SW_STROKE_TAG_BEGIN || ttag == SW_STROKE_TAG_END) + dstTag[0] ^= (SW_STROKE_TAG_BEGIN | SW_STROKE_TAG_END); + } + --srcPt; + --srcTag; + ++dstPt; + ++dstTag; + } + + left->ptsCnt = left->start; + right->ptsCnt += newPts; + right->movable = false; + left->movable = false; +} + + +static void _beginSubPath(SwStroke& stroke, const SwPoint& to, bool closed) +{ + /* We cannot process the first point because there is not enough + information regarding its corner/cap. Later, it will be processed + in the _endSubPath() */ + + stroke.firstPt = true; + stroke.center = to; + stroke.closedSubPath = closed; + + /* Determine if we need to check whether the border radius is greater + than the radius of curvature of a curve, to handle this case specially. + This is only required if bevel joins or butt caps may be created because + round & miter joins and round & square caps cover the nagative sector + created with wide strokes. */ + if ((stroke.join != StrokeJoin::Round) || (!stroke.closedSubPath && stroke.cap == StrokeCap::Butt)) + stroke.handleWideStrokes = true; + else + stroke.handleWideStrokes = false; + + stroke.ptStartSubPath = to; + stroke.angleIn = 0; +} + + +static void _endSubPath(SwStroke& stroke) +{ + if (stroke.closedSubPath) { + //close the path if needed + if (stroke.center != stroke.ptStartSubPath) + _lineTo(stroke, stroke.ptStartSubPath); + + //process the corner + stroke.angleOut = stroke.subPathAngle; + auto turn = mathDiff(stroke.angleIn, stroke.angleOut); + + //No specific corner processing is required if the turn is 0 + if (turn != 0) { + //when we turn to the right, the inside is 0 + int32_t inside = 0; + + //otherwise, the inside is 1 + if (turn < 0) inside = 1; + + _inside(stroke, inside, stroke.subPathLineLength); //inside + _outside(stroke, 1 - inside, stroke.subPathLineLength); //outside + } + + _borderClose(stroke.borders + 0, false); + _borderClose(stroke.borders + 1, true); + } else { + auto right = stroke.borders; + + /* all right, this is an opened path, we need to add a cap between + right & left, add the reverse of left, then add a final cap + between left & right */ + _addCap(stroke, stroke.angleIn, 0); + + //add reversed points from 'left' to 'right' + _addReverseLeft(stroke, true); + + //now add the final cap + stroke.center = stroke.ptStartSubPath; + _addCap(stroke, stroke.subPathAngle + SW_ANGLE_PI, 0); + + /* now end the right subpath accordingly. The left one is rewind + and deosn't need further processing */ + _borderClose(right, false); + } +} + + +static void _getCounts(SwStrokeBorder* border, uint32_t& ptsCnt, uint32_t& cntrsCnt) +{ + auto count = border->ptsCnt; + auto tags = border->tags; + uint32_t _ptsCnt = 0; + uint32_t _cntrsCnt = 0; + bool inCntr = false; + + while (count > 0) { + if (tags[0] & SW_STROKE_TAG_BEGIN) { + if (inCntr) goto fail; + inCntr = true; + } else if (!inCntr) goto fail; + + if (tags[0] & SW_STROKE_TAG_END) { + inCntr = false; + ++_cntrsCnt; + } + --count; + ++_ptsCnt; + ++tags; + } + + if (inCntr) goto fail; + + ptsCnt = _ptsCnt; + cntrsCnt = _cntrsCnt; + + return; + +fail: + ptsCnt = 0; + cntrsCnt = 0; +} + + +static void _exportBorderOutline(const SwStroke& stroke, SwOutline* outline, uint32_t side) +{ + auto border = stroke.borders + side; + if (border->ptsCnt == 0) return; + + memcpy(outline->pts.data + outline->pts.count, border->pts, border->ptsCnt * sizeof(SwPoint)); + + auto cnt = border->ptsCnt; + auto src = border->tags; + auto tags = outline->types.data + outline->types.count; + auto idx = outline->pts.count; + + while (cnt > 0) { + if (*src & SW_STROKE_TAG_POINT) *tags = SW_CURVE_TYPE_POINT; + else if (*src & SW_STROKE_TAG_CUBIC) *tags = SW_CURVE_TYPE_CUBIC; + else TVGERR("SW_ENGINE", "Invalid stroke tag was given! = %d", *src); + if (*src & SW_STROKE_TAG_END) outline->cntrs.push(idx); + ++src; + ++tags; + ++idx; + --cnt; + } + outline->pts.count += border->ptsCnt; + outline->types.count += border->ptsCnt; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +void strokeFree(SwStroke* stroke) +{ + if (!stroke) return; + + //free borders + if (stroke->borders[0].pts) free(stroke->borders[0].pts); + if (stroke->borders[0].tags) free(stroke->borders[0].tags); + if (stroke->borders[1].pts) free(stroke->borders[1].pts); + if (stroke->borders[1].tags) free(stroke->borders[1].tags); + + fillFree(stroke->fill); + stroke->fill = nullptr; + + free(stroke); +} + + +void strokeReset(SwStroke* stroke, const RenderShape* rshape, const Matrix* transform) +{ + if (transform) { + stroke->sx = sqrtf(powf(transform->e11, 2.0f) + powf(transform->e21, 2.0f)); + stroke->sy = sqrtf(powf(transform->e12, 2.0f) + powf(transform->e22, 2.0f)); + } else { + stroke->sx = stroke->sy = 1.0f; + } + + stroke->width = HALF_STROKE(rshape->strokeWidth()); + stroke->cap = rshape->strokeCap(); + stroke->miterlimit = static_cast(rshape->strokeMiterlimit()) << 16; + + //Save line join: it can be temporarily changed when stroking curves... + stroke->joinSaved = stroke->join = rshape->strokeJoin(); + + stroke->borders[0].ptsCnt = 0; + stroke->borders[0].start = -1; + stroke->borders[1].ptsCnt = 0; + stroke->borders[1].start = -1; +} + + +bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline) +{ + uint32_t first = 0; + uint32_t i = 0; + + for (auto cntr = outline.cntrs.data; cntr < outline.cntrs.end(); ++cntr, ++i) { + auto last = *cntr; //index of last point in contour + auto limit = outline.pts.data + last; + + //Skip empty points + if (last <= first) { + first = last + 1; + continue; + } + + auto start = outline.pts[first]; + auto pt = outline.pts.data + first; + auto types = outline.types.data + first; + auto type = types[0]; + + //A contour cannot start with a cubic control point + if (type == SW_CURVE_TYPE_CUBIC) return false; + + auto closed = outline.closed.data ? outline.closed.data[i]: false; + + _beginSubPath(*stroke, start, closed); + + while (pt < limit) { + ++pt; + ++types; + + //emit a signel line_to + if (types[0] == SW_CURVE_TYPE_POINT) { + _lineTo(*stroke, *pt); + //types cubic + } else { + if (pt + 1 > limit || types[1] != SW_CURVE_TYPE_CUBIC) return false; + + pt += 2; + types += 2; + + if (pt <= limit) { + _cubicTo(*stroke, pt[-2], pt[-1], pt[0]); + continue; + } + _cubicTo(*stroke, pt[-2], pt[-1], start); + goto close; + } + } + close: + if (!stroke->firstPt) _endSubPath(*stroke); + first = last + 1; + } + return true; +} + + +SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid) +{ + uint32_t count1, count2, count3, count4; + + _getCounts(stroke->borders + 0, count1, count2); + _getCounts(stroke->borders + 1, count3, count4); + + auto ptsCnt = count1 + count3; + auto cntrsCnt = count2 + count4; + + auto outline = mpoolReqStrokeOutline(mpool, tid); + outline->pts.reserve(ptsCnt); + outline->types.reserve(ptsCnt); + outline->cntrs.reserve(cntrsCnt); + + _exportBorderOutline(*stroke, outline, 0); //left + _exportBorderOutline(*stroke, outline, 1); //right + + return outline; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgTaskScheduler.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgTaskScheduler.cpp new file mode 100644 index 000000000..cad12c3a8 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgTaskScheduler.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include +#include +#include "tvgTaskScheduler.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +namespace tvg { + +static thread_local bool _async = true; //toggle async tasking for each thread on/off + + +struct TaskSchedulerImpl +{ + TaskSchedulerImpl(unsigned threadCnt) + { + } + + ~TaskSchedulerImpl() + { + } + + void request(Task* task) + { + task->run(0); + } +}; + +} + +static TaskSchedulerImpl* inst = nullptr; + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +void TaskScheduler::init(unsigned threads) +{ + if (inst) return; + inst = new TaskSchedulerImpl(threads); +} + +void TaskScheduler::request(Task* task) +{ + if (inst) inst->request(task); +} + +void TaskScheduler::async(bool on) +{ + _async = on; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgTaskScheduler.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgTaskScheduler.h new file mode 100644 index 000000000..41d6f9bef --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgTaskScheduler.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_TASK_SCHEDULER_H_ +#define _TVG_TASK_SCHEDULER_H_ + +#include "tvgCommon.h" + +namespace tvg +{ + +struct Task; + +struct TaskScheduler +{ + static void init(unsigned threads); + static void request(Task* task); + static void async(bool on); +}; + +struct Task +{ +private: + +public: + virtual ~Task() = default; + + void done() + { + } + +protected: + virtual void run(unsigned tid) = 0; + +private: + void operator()(unsigned tid) + { + run(tid); + + } + + void prepare() + { + } + + friend struct TaskSchedulerImpl; +}; + +} + +#endif //_TVG_TASK_SCHEDULER_H_ + + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgXmlParser.cpp b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgXmlParser.cpp new file mode 100644 index 000000000..6bd35ba81 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgXmlParser.cpp @@ -0,0 +1,591 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#include +#include +#include + +#ifdef _WIN32 + #include +#elif defined(__linux__) + #include +#else + #include +#endif + +#include "tvgXmlParser.h" +#include "tvgStr.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +bool _isIgnoreUnsupportedLogAttributes(TVG_UNUSED const char* tagAttribute, TVG_UNUSED const char* tagValue) +{ +#ifdef THORVG_LOG_ENABLED + const auto attributesNum = 6; + const struct + { + const char* tag; + bool tagWildcard; //If true, it is assumed that a wildcard is used after the tag. (ex: tagName*) + const char* value; + } attributes[] = { + {"id", false, nullptr}, + {"data-name", false, nullptr}, + {"overflow", false, "visible"}, + {"version", false, nullptr}, + {"xmlns", true, nullptr}, + {"xml:space", false, nullptr}, + }; + + for (unsigned int i = 0; i < attributesNum; ++i) { + if (!strncmp(tagAttribute, attributes[i].tag, attributes[i].tagWildcard ? strlen(attributes[i].tag) : strlen(tagAttribute))) { + if (attributes[i].value && tagValue) { + if (!strncmp(tagValue, attributes[i].value, strlen(tagValue))) { + return true; + } else continue; + } + return true; + } + } + return false; +#endif + return true; +} + + +static const char* _simpleXmlFindWhiteSpace(const char* itr, const char* itrEnd) +{ + for (; itr < itrEnd; itr++) { + if (isspace((unsigned char)*itr)) break; + } + return itr; +} + + +static const char* _simpleXmlSkipWhiteSpace(const char* itr, const char* itrEnd) +{ + for (; itr < itrEnd; itr++) { + if (!isspace((unsigned char)*itr)) break; + } + return itr; +} + + +static const char* _simpleXmlUnskipWhiteSpace(const char* itr, const char* itrStart) +{ + for (itr--; itr > itrStart; itr--) { + if (!isspace((unsigned char)*itr)) break; + } + return itr + 1; +} + + +static const char* _simpleXmlSkipXmlEntities(const char* itr, const char* itrEnd) +{ + auto p = itr; + while (itr < itrEnd && *itr == '&') { + for (int i = 0; i < NUMBER_OF_XML_ENTITIES; ++i) { + if (strncmp(itr, xmlEntity[i], xmlEntityLength[i]) == 0) { + itr += xmlEntityLength[i]; + break; + } + } + if (itr == p) break; + p = itr; + } + return itr; +} + + +static const char* _simpleXmlUnskipXmlEntities(const char* itr, const char* itrStart) +{ + auto p = itr; + while (itr > itrStart && *(itr - 1) == ';') { + for (int i = 0; i < NUMBER_OF_XML_ENTITIES; ++i) { + if (itr - xmlEntityLength[i] > itrStart && + strncmp(itr - xmlEntityLength[i], xmlEntity[i], xmlEntityLength[i]) == 0) { + itr -= xmlEntityLength[i]; + break; + } + } + if (itr == p) break; + p = itr; + } + return itr; +} + + +static const char* _skipWhiteSpacesAndXmlEntities(const char* itr, const char* itrEnd) +{ + itr = _simpleXmlSkipWhiteSpace(itr, itrEnd); + auto p = itr; + while (true) { + if (p != (itr = _simpleXmlSkipXmlEntities(itr, itrEnd))) p = itr; + else break; + if (p != (itr = _simpleXmlSkipWhiteSpace(itr, itrEnd))) p = itr; + else break; + } + return itr; +} + + +static const char* _unskipWhiteSpacesAndXmlEntities(const char* itr, const char* itrStart) +{ + itr = _simpleXmlUnskipWhiteSpace(itr, itrStart); + auto p = itr; + while (true) { + if (p != (itr = _simpleXmlUnskipXmlEntities(itr, itrStart))) p = itr; + else break; + if (p != (itr = _simpleXmlUnskipWhiteSpace(itr, itrStart))) p = itr; + else break; + } + return itr; +} + + +static const char* _simpleXmlFindStartTag(const char* itr, const char* itrEnd) +{ + return (const char*)memchr(itr, '<', itrEnd - itr); +} + + +static const char* _simpleXmlFindEndTag(const char* itr, const char* itrEnd) +{ + bool insideQuote = false; + for (; itr < itrEnd; itr++) { + if (*itr == '"') insideQuote = !insideQuote; + if (!insideQuote) { + if ((*itr == '>') || (*itr == '<')) + return itr; + } + } + return nullptr; +} + + +static const char* _simpleXmlFindEndCommentTag(const char* itr, const char* itrEnd) +{ + for (; itr < itrEnd; itr++) { + if ((*itr == '-') && ((itr + 1 < itrEnd) && (*(itr + 1) == '-')) && ((itr + 2 < itrEnd) && (*(itr + 2) == '>'))) return itr + 2; + } + return nullptr; +} + + +static const char* _simpleXmlFindEndCdataTag(const char* itr, const char* itrEnd) +{ + for (; itr < itrEnd; itr++) { + if ((*itr == ']') && ((itr + 1 < itrEnd) && (*(itr + 1) == ']')) && ((itr + 2 < itrEnd) && (*(itr + 2) == '>'))) return itr + 2; + } + return nullptr; +} + + +static const char* _simpleXmlFindDoctypeChildEndTag(const char* itr, const char* itrEnd) +{ + for (; itr < itrEnd; itr++) { + if (*itr == '>') return itr; + } + return nullptr; +} + + +static SimpleXMLType _getXMLType(const char* itr, const char* itrEnd, size_t &toff) +{ + toff = 0; + if (itr[1] == '/') { + toff = 1; + return SimpleXMLType::Close; + } else if (itr[1] == '?') { + toff = 1; + return SimpleXMLType::Processing; + } else if (itr[1] == '!') { + if ((itr + sizeof("") - 1 < itrEnd) && (!memcmp(itr + 2, "DOCTYPE", sizeof("DOCTYPE") - 1)) && ((itr[2 + sizeof("DOCTYPE") - 1] == '>') || (isspace((unsigned char)itr[2 + sizeof("DOCTYPE") - 1])))) { + toff = sizeof("!DOCTYPE") - 1; + return SimpleXMLType::Doctype; + } else if ((itr + sizeof("") - 1 < itrEnd) && (!memcmp(itr + 2, "[CDATA[", sizeof("[CDATA[") - 1))) { + toff = sizeof("![CDATA[") - 1; + return SimpleXMLType::CData; + } else if ((itr + sizeof("") - 1 < itrEnd) && (!memcmp(itr + 2, "--", sizeof("--") - 1))) { + toff = sizeof("!--") - 1; + return SimpleXMLType::Comment; + } else if (itr + sizeof("") - 1 < itrEnd) { + toff = sizeof("!") - 1; + return SimpleXMLType::DoctypeChild; + } + return SimpleXMLType::Open; + } + return SimpleXMLType::Open; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +const char* simpleXmlNodeTypeToString(TVG_UNUSED SvgNodeType type) +{ +#ifdef THORVG_LOG_ENABLED + static const char* TYPE_NAMES[] = { + "Svg", + "G", + "Defs", + "Animation", + "Arc", + "Circle", + "Ellipse", + "Image", + "Line", + "Path", + "Polygon", + "Polyline", + "Rect", + "Text", + "TextArea", + "Tspan", + "Use", + "Video", + "ClipPath", + "Mask", + "Symbol", + "Unknown", + }; + return TYPE_NAMES[(int) type]; +#endif + return nullptr; +} + + +bool isIgnoreUnsupportedLogElements(TVG_UNUSED const char* tagName) +{ +#ifdef THORVG_LOG_ENABLED + const auto elementsNum = 1; + const char* const elements[] = { "title" }; + + for (unsigned int i = 0; i < elementsNum; ++i) { + if (!strncmp(tagName, elements[i], strlen(tagName))) { + return true; + } + } + return false; +#else + return true; +#endif +} + + +bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data) +{ + const char *itr = buf, *itrEnd = buf + bufLength; + char* tmpBuf = (char*)malloc(bufLength + 1); + + if (!buf || !func || !tmpBuf) goto error; + + while (itr < itrEnd) { + const char* p = _skipWhiteSpacesAndXmlEntities(itr, itrEnd); + const char *key, *keyEnd, *value, *valueEnd; + char* tval; + + if (p == itrEnd) goto success; + + key = p; + for (keyEnd = key; keyEnd < itrEnd; keyEnd++) { + if ((*keyEnd == '=') || (isspace((unsigned char)*keyEnd))) break; + } + if (keyEnd == itrEnd) goto error; + if (keyEnd == key) continue; + + if (*keyEnd == '=') value = keyEnd + 1; + else { + value = (const char*)memchr(keyEnd, '=', itrEnd - keyEnd); + if (!value) goto error; + value++; + } + keyEnd = _simpleXmlUnskipXmlEntities(keyEnd, key); + + value = _skipWhiteSpacesAndXmlEntities(value, itrEnd); + if (value == itrEnd) goto error; + + if ((*value == '"') || (*value == '\'')) { + valueEnd = (const char*)memchr(value + 1, *value, itrEnd - value); + if (!valueEnd) goto error; + value++; + } else { + valueEnd = _simpleXmlFindWhiteSpace(value, itrEnd); + } + + itr = valueEnd + 1; + + value = _skipWhiteSpacesAndXmlEntities(value, itrEnd); + valueEnd = _unskipWhiteSpacesAndXmlEntities(valueEnd, value); + + memcpy(tmpBuf, key, keyEnd - key); + tmpBuf[keyEnd - key] = '\0'; + + tval = tmpBuf + (keyEnd - key) + 1; + int i = 0; + while (value < valueEnd) { + value = _simpleXmlSkipXmlEntities(value, valueEnd); + tval[i++] = *value; + value++; + } + tval[i] = '\0'; + + if (!func((void*)data, tmpBuf, tval)) { + if (!_isIgnoreUnsupportedLogAttributes(tmpBuf, tval)) { + TVGLOG("SVG", "Unsupported attributes used [Elements type: %s][Id : %s][Attribute: %s][Value: %s]", simpleXmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type), ((SvgLoaderData*)data)->svgParse->node->id ? ((SvgLoaderData*)data)->svgParse->node->id : "NO_ID", tmpBuf, tval ? tval : "NONE"); + } + } + } + +success: + free(tmpBuf); + return true; + +error: + free(tmpBuf); + return false; +} + + +bool simpleXmlParse(const char* buf, unsigned bufLength, bool strip, simpleXMLCb func, const void* data) +{ + const char *itr = buf, *itrEnd = buf + bufLength; + + if (!buf || !func) return false; + + while (itr < itrEnd) { + if (itr[0] == '<') { + //Invalid case + if (itr + 1 >= itrEnd) return false; + + size_t toff = 0; + SimpleXMLType type = _getXMLType(itr, itrEnd, toff); + + const char* p; + if (type == SimpleXMLType::CData) p = _simpleXmlFindEndCdataTag(itr + 1 + toff, itrEnd); + else if (type == SimpleXMLType::DoctypeChild) p = _simpleXmlFindDoctypeChildEndTag(itr + 1 + toff, itrEnd); + else if (type == SimpleXMLType::Comment) p = _simpleXmlFindEndCommentTag(itr + 1 + toff, itrEnd); + else p = _simpleXmlFindEndTag(itr + 1 + toff, itrEnd); + + if (p) { + //Invalid case: '<' nested + if (*p == '<' && type != SimpleXMLType::Doctype) return false; + const char *start, *end; + + start = itr + 1 + toff; + end = p; + + switch (type) { + case SimpleXMLType::Open: { + if (p[-1] == '/') { + type = SimpleXMLType::OpenEmpty; + end--; + } + break; + } + case SimpleXMLType::CData: { + if (!memcmp(p - 2, "]]", 2)) end -= 2; + break; + } + case SimpleXMLType::Processing: { + if (p[-1] == '?') end--; + break; + } + case SimpleXMLType::Comment: { + if (!memcmp(p - 2, "--", 2)) end -= 2; + break; + } + default: { + break; + } + } + + if (strip && (type != SimpleXMLType::CData)) { + start = _skipWhiteSpacesAndXmlEntities(start, end); + end = _unskipWhiteSpacesAndXmlEntities(end, start); + } + + if (!func((void*)data, type, start, (unsigned int)(end - start))) return false; + + itr = p + 1; + } else { + return false; + } + } else { + const char *p, *end; + + if (strip) { + p = itr; + p = _skipWhiteSpacesAndXmlEntities(p, itrEnd); + if (p) { + if (!func((void*)data, SimpleXMLType::Ignored, itr, (unsigned int)(p - itr))) return false; + itr = p; + } + } + + p = _simpleXmlFindStartTag(itr, itrEnd); + if (!p) p = itrEnd; + + end = p; + if (strip) end = _unskipWhiteSpacesAndXmlEntities(end, itr); + + if (itr != end && !func((void*)data, SimpleXMLType::Data, itr, (unsigned int)(end - itr))) return false; + + if (strip && (end < p) && !func((void*)data, SimpleXMLType::Ignored, end, (unsigned int)(p - end))) return false; + + itr = p; + } + } + return true; +} + + +bool simpleXmlParseW3CAttribute(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data) +{ + const char* end; + char* key; + char* val; + char* next; + + if (!buf) return false; + + end = buf + bufLength; + key = (char*)alloca(end - buf + 1); + val = (char*)alloca(end - buf + 1); + + if (buf == end) return true; + + do { + char* sep = (char*)strchr(buf, ':'); + next = (char*)strchr(buf, ';'); + if (sep >= end) { + next = nullptr; + sep = nullptr; + } + if (next >= end) next = nullptr; + + key[0] = '\0'; + val[0] = '\0'; + + if (next == nullptr && sep != nullptr) { + memcpy(key, buf, sep - buf); + key[sep - buf] = '\0'; + + memcpy(val, sep + 1, end - sep - 1); + val[end - sep - 1] = '\0'; + } else if (sep < next && sep != nullptr) { + memcpy(key, buf, sep - buf); + key[sep - buf] = '\0'; + + memcpy(val, sep + 1, next - sep - 1); + val[next - sep - 1] = '\0'; + } else if (next) { + memcpy(key, buf, next - buf); + key[next - buf] = '\0'; + } + + if (key[0]) { + key = const_cast(_simpleXmlSkipWhiteSpace(key, key + strlen(key))); + key[_simpleXmlUnskipWhiteSpace(key + strlen(key) , key) - key] = '\0'; + val = const_cast(_simpleXmlSkipWhiteSpace(val, val + strlen(val))); + val[_simpleXmlUnskipWhiteSpace(val + strlen(val) , val) - val] = '\0'; + + if (!func((void*)data, key, val)) { + if (!_isIgnoreUnsupportedLogAttributes(key, val)) { + TVGLOG("SVG", "Unsupported attributes used [Elements type: %s][Id : %s][Attribute: %s][Value: %s]", simpleXmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type), ((SvgLoaderData*)data)->svgParse->node->id ? ((SvgLoaderData*)data)->svgParse->node->id : "NO_ID", key, val ? val : "NONE"); + } + } + } + + buf = next + 1; + } while (next != nullptr); + + return true; +} + + +/* + * Supported formats: + * tag {}, .name {}, tag.name{} + */ +const char* simpleXmlParseCSSAttribute(const char* buf, unsigned bufLength, char** tag, char** name, const char** attrs, unsigned* attrsLength) +{ + if (!buf) return nullptr; + + *tag = *name = nullptr; + *attrsLength = 0; + + auto itr = _simpleXmlSkipWhiteSpace(buf, buf + bufLength); + auto itrEnd = (const char*)memchr(buf, '{', bufLength); + + if (!itrEnd || itr == itrEnd) return nullptr; + + auto nextElement = (const char*)memchr(itrEnd, '}', bufLength - (itrEnd - buf)); + if (!nextElement) return nullptr; + + *attrs = itrEnd + 1; + *attrsLength = nextElement - *attrs; + + const char *p; + + itrEnd = _simpleXmlUnskipWhiteSpace(itrEnd, itr); + if (*(itrEnd - 1) == '.') return nullptr; + + for (p = itr; p < itrEnd; p++) { + if (*p == '.') break; + } + + if (p == itr) *tag = strdup("all"); + else *tag = strDuplicate(itr, p - itr); + + if (p == itrEnd) *name = nullptr; + else *name = strDuplicate(p + 1, itrEnd - p - 1); + + return (nextElement ? nextElement + 1 : nullptr); +} + + +const char* simpleXmlFindAttributesTag(const char* buf, unsigned bufLength) +{ + const char *itr = buf, *itrEnd = buf + bufLength; + + for (; itr < itrEnd; itr++) { + if (!isspace((unsigned char)*itr)) { + //User skip tagname and already gave it the attributes. + if (*itr == '=') return buf; + } else { + itr = _simpleXmlUnskipXmlEntities(itr, buf); + if (itr == itrEnd) return nullptr; + return itr; + } + } + + return nullptr; +} + +#endif /* LV_USE_THORVG_INTERNAL */ + diff --git a/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgXmlParser.h b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgXmlParser.h new file mode 100644 index 000000000..e1cf2de2e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/thorvg/tvgXmlParser.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "../../lv_conf_internal.h" +#if LV_USE_THORVG_INTERNAL + +#ifndef _TVG_SIMPLE_XML_PARSER_H_ +#define _TVG_SIMPLE_XML_PARSER_H_ + +#include "tvgSvgLoaderCommon.h" + +#define NUMBER_OF_XML_ENTITIES 8 +const char* const xmlEntity[] = {""", " ", "'", "&", "<", ">", "#", "'"}; +const int xmlEntityLength[] = {6, 6, 6, 5, 4, 4, 6, 6}; + +enum class SimpleXMLType +{ + Open = 0, //!< \ + OpenEmpty, //!< \ + Close, //!< \ + Data, //!< tag text data + CData, //!< \ + Error, //!< error contents + Processing, //!< \ \ + Doctype, //!< \ + Ignored, //!< whatever is ignored by parser, like whitespace + DoctypeChild //!< \tiny_ttf_cache +/********************** + * TYPEDEFS + **********************/ +typedef struct ttf_font_desc { + lv_fs_file_t file; +#if LV_TINY_TTF_FILE_SUPPORT != 0 + ttf_cb_stream_t stream; +#else + const uint8_t * stream; +#endif + stbtt_fontinfo info; + float scale; + int ascent; + int descent; +} ttf_font_desc_t; + +typedef struct _tiny_ttf_cache_data_t { + lv_font_t * font; + uint32_t unicode; + uint32_t size; + lv_draw_buf_t * draw_buf; +} tiny_ttf_cache_data_t; +/********************** + * STATIC PROTOTYPES + **********************/ +static bool ttf_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, + uint32_t unicode_letter_next); +static const void * ttf_get_glyph_bitmap_cb(lv_font_glyph_dsc_t * g_dsc, + uint32_t unicode_letter, lv_draw_buf_t * draw_buf); +static void ttf_release_glyph_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc); +static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size_t data_size, + int32_t font_size, + size_t cache_size); + +static bool tiny_ttf_cache_create_cb(tiny_ttf_cache_data_t * node, void * user_data); +static void tiny_ttf_cache_free_cb(tiny_ttf_cache_data_t * node, void * user_data); +static lv_cache_compare_res_t tiny_ttf_cache_compare_cb(const tiny_ttf_cache_data_t * lhs, + const tiny_ttf_cache_data_t * rhs); +/********************** + * GLOBAL VARIABLES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_tiny_ttf_set_size(lv_font_t * font, int32_t font_size) +{ + if(font_size <= 0) { + LV_LOG_ERROR("invalid font size: %"PRIx32, font_size); + return; + } + ttf_font_desc_t * dsc = (ttf_font_desc_t *)font->dsc; + dsc->scale = stbtt_ScaleForMappingEmToPixels(&dsc->info, font_size); + int line_gap = 0; + stbtt_GetFontVMetrics(&dsc->info, &dsc->ascent, &dsc->descent, &line_gap); + font->line_height = (int32_t)(dsc->scale * (dsc->ascent - dsc->descent + line_gap)); + font->base_line = (int32_t)(dsc->scale * (line_gap - dsc->descent)); +} + +void lv_tiny_ttf_destroy(lv_font_t * font) +{ + LV_ASSERT_NULL(font); + + if(font->dsc != NULL) { + ttf_font_desc_t * ttf = (ttf_font_desc_t *)font->dsc; +#if LV_TINY_TTF_FILE_SUPPORT != 0 + if(ttf->stream.file != NULL) { + lv_fs_close(&ttf->file); + } +#endif + lv_cache_drop_all(tiny_ttf_cache, (void *)font->dsc); + lv_free(ttf); + font->dsc = NULL; + } + + lv_free(font); +} + +void lv_tiny_ttf_init(void) +{ + lv_cache_ops_t ops = { + .compare_cb = (lv_cache_compare_cb_t)tiny_ttf_cache_compare_cb, + .create_cb = (lv_cache_create_cb_t)tiny_ttf_cache_create_cb, + .free_cb = (lv_cache_free_cb_t)tiny_ttf_cache_free_cb, + }; + + tiny_ttf_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(tiny_ttf_cache_data_t), 128, ops); +} + +void lv_tiny_ttf_deinit(void) +{ + lv_cache_destroy(tiny_ttf_cache, NULL); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#if LV_TINY_TTF_FILE_SUPPORT != 0 +static void ttf_cb_stream_read(ttf_cb_stream_t * stream, void * data, size_t to_read) +{ + if(stream->file != NULL) { + uint32_t br; + lv_fs_read(stream->file, data, to_read, &br); + } + else { + if(to_read + stream->position >= stream->size) { + to_read = stream->size - stream->position; + } + memcpy(data, ((const unsigned char *)stream->data + stream->position), to_read); + stream->position += to_read; + } +} +static void ttf_cb_stream_seek(ttf_cb_stream_t * stream, size_t position) +{ + if(stream->file != NULL) { + lv_fs_seek(stream->file, position, LV_FS_SEEK_SET); + } + else { + if(position > stream->size) { + stream->position = stream->size; + } + else { + stream->position = position; + } + } +} +#endif + +static bool ttf_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, + uint32_t unicode_letter_next) +{ + if(unicode_letter < 0x20 || + unicode_letter == 0xf8ff || /*LV_SYMBOL_DUMMY*/ + unicode_letter == 0x200c) { /*ZERO WIDTH NON-JOINER*/ + dsc_out->box_w = 0; + dsc_out->adv_w = 0; + dsc_out->box_h = 0; /*height of the bitmap in [px]*/ + dsc_out->ofs_x = 0; /*X offset of the bitmap in [pf]*/ + dsc_out->ofs_y = 0; /*Y offset of the bitmap in [pf]*/ + dsc_out->bpp = 0; + dsc_out->is_placeholder = false; + return true; + } + ttf_font_desc_t * dsc = (ttf_font_desc_t *)font->dsc; + int g1 = stbtt_FindGlyphIndex(&dsc->info, (int)unicode_letter); + if(g1 == 0) { + /* Glyph not found */ + return false; + } + int x1, y1, x2, y2; + + stbtt_GetGlyphBitmapBox(&dsc->info, g1, dsc->scale, dsc->scale, &x1, &y1, &x2, &y2); + int g2 = 0; + if(unicode_letter_next != 0) { + g2 = stbtt_FindGlyphIndex(&dsc->info, (int)unicode_letter_next); + } + int advw, lsb; + stbtt_GetGlyphHMetrics(&dsc->info, g1, &advw, &lsb); + int k = stbtt_GetGlyphKernAdvance(&dsc->info, g1, g2); + dsc_out->adv_w = (uint16_t)floor((((float)advw + (float)k) * dsc->scale) + + 0.5f); /*Horizontal space required by the glyph in [px]*/ + dsc_out->box_w = (x2 - x1 + 1); /*width of the bitmap in [px]*/ + dsc_out->box_h = (y2 - y1 + 1); /*height of the bitmap in [px]*/ + dsc_out->ofs_x = x1; /*X offset of the bitmap in [pf]*/ + dsc_out->ofs_y = -y2; /*Y offset of the bitmap measured from the as line*/ + dsc_out->bpp = 8; /*Bits per pixel: 1/2/4/8*/ + dsc_out->is_placeholder = false; + return true; /*true: glyph found; false: glyph was not found*/ +} + +static const void * ttf_get_glyph_bitmap_cb(lv_font_glyph_dsc_t * g_dsc, + uint32_t unicode_letter, lv_draw_buf_t * draw_buf) +{ + LV_UNUSED(draw_buf); + const lv_font_t * font = g_dsc->resolved_font; + tiny_ttf_cache_data_t search_key = { + .font = (lv_font_t *)font, + .unicode = unicode_letter, + .size = font->line_height, + }; + + lv_cache_entry_t * entry = lv_cache_acquire_or_create(tiny_ttf_cache, &search_key, (void *)font->dsc); + + if(entry == NULL) { + LV_LOG_ERROR("cache not allocated\n"); + return NULL; + } + + g_dsc->entry = entry; + tiny_ttf_cache_data_t * cached_data = lv_cache_entry_get_data(entry); + return cached_data->draw_buf; +} + +static void ttf_release_glyph_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc) +{ + LV_ASSERT_NULL(font); + if(g_dsc->entry == NULL) { + return; + } + lv_cache_release(tiny_ttf_cache, g_dsc->entry, NULL); + g_dsc->entry = NULL; +} + +static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size_t data_size, int32_t font_size, + size_t cache_size) +{ + LV_UNUSED(data_size); + LV_UNUSED(cache_size); + if((path == NULL && data == NULL) || 0 >= font_size) { + LV_LOG_ERROR("tiny_ttf: invalid argument\n"); + return NULL; + } + ttf_font_desc_t * dsc = lv_malloc_zeroed(sizeof(ttf_font_desc_t)); + if(dsc == NULL) { + LV_LOG_ERROR("tiny_ttf: out of memory\n"); + return NULL; + } +#if LV_TINY_TTF_FILE_SUPPORT != 0 + if(path != NULL) { + if(LV_FS_RES_OK != lv_fs_open(&dsc->file, path, LV_FS_MODE_RD)) { + lv_free(dsc); + LV_LOG_ERROR("tiny_ttf: unable to open %s\n", path); + return NULL; + } + dsc->stream.file = &dsc->file; + } + else { + dsc->stream.data = (const uint8_t *)data; + dsc->stream.size = data_size; + } + if(0 == stbtt_InitFont(&dsc->info, &dsc->stream, stbtt_GetFontOffsetForIndex(&dsc->stream, 0))) { + lv_free(dsc); + LV_LOG_ERROR("tiny_ttf: init failed\n"); + return NULL; + } + +#else + dsc->stream = (const uint8_t *)data; + if(0 == stbtt_InitFont(&dsc->info, dsc->stream, stbtt_GetFontOffsetForIndex(dsc->stream, 0))) { + lv_free(dsc); + LV_LOG_ERROR("tiny_ttf: init failed\n"); + return NULL; + } +#endif + + lv_font_t * out_font = lv_malloc_zeroed(sizeof(lv_font_t)); + if(out_font == NULL) { + lv_free(dsc); + LV_LOG_ERROR("tiny_ttf: out of memory\n"); + return NULL; + } + out_font->get_glyph_dsc = ttf_get_glyph_dsc_cb; + out_font->get_glyph_bitmap = ttf_get_glyph_bitmap_cb; + out_font->release_glyph = ttf_release_glyph_cb; + out_font->dsc = dsc; + lv_tiny_ttf_set_size(out_font, font_size); + return out_font; +} +#if LV_TINY_TTF_FILE_SUPPORT != 0 +lv_font_t * lv_tiny_ttf_create_file_ex(const char * path, int32_t font_size, size_t cache_size) +{ + return lv_tiny_ttf_create(path, NULL, 0, font_size, cache_size); +} +lv_font_t * lv_tiny_ttf_create_file(const char * path, int32_t font_size) +{ + return lv_tiny_ttf_create(path, NULL, 0, font_size, 0); +} +#endif +lv_font_t * lv_tiny_ttf_create_data_ex(const void * data, size_t data_size, int32_t font_size, size_t cache_size) +{ + return lv_tiny_ttf_create(NULL, data, data_size, font_size, cache_size); +} +lv_font_t * lv_tiny_ttf_create_data(const void * data, size_t data_size, int32_t font_size) +{ + return lv_tiny_ttf_create(NULL, data, data_size, font_size, 0); +} + +/*----------------- + * Cache Callbacks + *----------------*/ + +static bool tiny_ttf_cache_create_cb(tiny_ttf_cache_data_t * node, void * user_data) +{ + + ttf_font_desc_t * dsc = (ttf_font_desc_t *)user_data; + uint32_t unicode_letter = node->unicode; + + const stbtt_fontinfo * info = (const stbtt_fontinfo *)&dsc->info; + int g1 = stbtt_FindGlyphIndex(info, (int)unicode_letter); + if(g1 == 0) { + /* Glyph not found */ + return false; + } + int x1, y1, x2, y2; + stbtt_GetGlyphBitmapBox(info, g1, dsc->scale, dsc->scale, &x1, &y1, &x2, &y2); + int w, h; + w = x2 - x1 + 1; + h = y2 - y1 + 1; + lv_draw_buf_t * draw_buf = lv_draw_buf_create(w, h, LV_COLOR_FORMAT_A8, LV_STRIDE_AUTO); + if(NULL == draw_buf) { + LV_LOG_ERROR("tiny_ttf: out of memory\n"); + return false; + } + + lv_draw_buf_clear(draw_buf, NULL); + + uint32_t stride = draw_buf->header.stride; + stbtt_MakeGlyphBitmap(info, draw_buf->data, w, h, stride, dsc->scale, dsc->scale, g1); + + node->draw_buf = draw_buf; + return true; +} + +static void tiny_ttf_cache_free_cb(tiny_ttf_cache_data_t * node, void * user_data) +{ + LV_UNUSED(user_data); + + lv_draw_buf_destroy(node->draw_buf); +} + +static lv_cache_compare_res_t tiny_ttf_cache_compare_cb(const tiny_ttf_cache_data_t * lhs, + const tiny_ttf_cache_data_t * rhs) +{ + if(lhs->font != rhs->font) { + return lhs->font > rhs->font ? 1 : -1; + } + + if(lhs->unicode != rhs->unicode) { + return lhs->unicode > rhs->unicode ? 1 : -1; + } + + if(lhs->size != rhs->size) { + return lhs->size > rhs->size ? 1 : -1; + } + + return 0; +} + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/tiny_ttf/lv_tiny_ttf.h b/lib/libesp32_lvgl/lvgl/src/libs/tiny_ttf/lv_tiny_ttf.h similarity index 75% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/tiny_ttf/lv_tiny_ttf.h rename to lib/libesp32_lvgl/lvgl/src/libs/tiny_ttf/lv_tiny_ttf.h index fe0936b3b..3ad65219d 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/tiny_ttf/lv_tiny_ttf.h +++ b/lib/libesp32_lvgl/lvgl/src/libs/tiny_ttf/lv_tiny_ttf.h @@ -29,22 +29,26 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ -#if LV_TINY_TTF_FILE_SUPPORT +#if LV_TINY_TTF_FILE_SUPPORT !=0 /* create a font from the specified file or path with the specified line height.*/ -lv_font_t * lv_tiny_ttf_create_file(const char * path, lv_coord_t font_size); +lv_font_t * lv_tiny_ttf_create_file(const char * path, int32_t font_size); /* create a font from the specified file or path with the specified line height with the specified cache size.*/ -lv_font_t * lv_tiny_ttf_create_file_ex(const char * path, lv_coord_t font_size, size_t cache_size); -#endif /*LV_TINY_TTF_FILE_SUPPORT*/ +lv_font_t * lv_tiny_ttf_create_file_ex(const char * path, int32_t font_size, size_t cache_size); +#endif + +void lv_tiny_ttf_init(void); + +void lv_tiny_ttf_deinit(void); /* create a font from the specified data pointer with the specified line height.*/ -lv_font_t * lv_tiny_ttf_create_data(const void * data, size_t data_size, lv_coord_t font_size); +lv_font_t * lv_tiny_ttf_create_data(const void * data, size_t data_size, int32_t font_size); /* create a font from the specified data pointer with the specified line height and the specified cache size.*/ -lv_font_t * lv_tiny_ttf_create_data_ex(const void * data, size_t data_size, lv_coord_t font_size, size_t cache_size); +lv_font_t * lv_tiny_ttf_create_data_ex(const void * data, size_t data_size, int32_t font_size, size_t cache_size); /* set the size of the font to a new font_size*/ -void lv_tiny_ttf_set_size(lv_font_t * font, lv_coord_t font_size); +void lv_tiny_ttf_set_size(lv_font_t * font, int32_t font_size); /* destroy a font previously created with lv_tiny_ttf_create_xxxx()*/ void lv_tiny_ttf_destroy(lv_font_t * font); diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/tiny_ttf/stb_rect_pack.h b/lib/libesp32_lvgl/lvgl/src/libs/tiny_ttf/stb_rect_pack.h similarity index 99% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/tiny_ttf/stb_rect_pack.h rename to lib/libesp32_lvgl/lvgl/src/libs/tiny_ttf/stb_rect_pack.h index 413e5047d..b265df907 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/tiny_ttf/stb_rect_pack.h +++ b/lib/libesp32_lvgl/lvgl/src/libs/tiny_ttf/stb_rect_pack.h @@ -97,7 +97,6 @@ typedef int stbrp_coord; #pragma GCC diagnostic ignored "-Wunused-function" #endif - STBRP_DEF int stbrp_pack_rects(stbrp_context * context, stbrp_rect * rects, int num_rects); // Assign packed locations to rectangles. The rectangles are of type // 'stbrp_rect' defined below, stored in the array 'rects', and there @@ -136,7 +135,6 @@ struct stbrp_rect { }; // 16 bytes, nominally - STBRP_DEF void stbrp_init_target(stbrp_context * context, int width, int height, stbrp_node * nodes, int num_nodes); // Initialize a rectangle packer to: // pack a rectangle that is 'width' by 'height' in dimensions @@ -163,7 +161,6 @@ STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context * context, int allow_o // change the handling of the out-of-temp-memory scenario, described above. // If you call init again, this will be reset to the default (false). - STBRP_DEF void stbrp_setup_heuristic(stbrp_context * context, int heuristic); // Optionally select which packing heuristic the library should use. Different // heuristics will produce better/worse results for different data sets. @@ -175,7 +172,6 @@ enum { STBRP_HEURISTIC_Skyline_BF_sortHeight }; - ////////////////////////////////////////////////////////////////////////////// // // the details of the following structures don't matter to you, but they must diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/tiny_ttf/stb_truetype_htcw.h b/lib/libesp32_lvgl/lvgl/src/libs/tiny_ttf/stb_truetype_htcw.h similarity index 99% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/tiny_ttf/stb_truetype_htcw.h rename to lib/libesp32_lvgl/lvgl/src/libs/tiny_ttf/stb_truetype_htcw.h index d0e839d9d..e91997b4b 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/tiny_ttf/stb_truetype_htcw.h +++ b/lib/libesp32_lvgl/lvgl/src/libs/tiny_ttf/stb_truetype_htcw.h @@ -418,7 +418,6 @@ int main(int arg, char ** argv) } #endif - ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// //// @@ -590,7 +589,6 @@ STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar * chardata, int pw, int // // It's inefficient; you might want to c&p it and optimize it. - ////////////////////////////////////////////////////////////////////////////// // // NEW TEXTURE BAKING API @@ -769,7 +767,6 @@ STBTT_DEF int stbtt_InitFont(stbtt_fontinfo * info, const unsigned char * data, // need to do anything special to free it, because the contents are pure // value data with no additional data structures. Returns 0 on failure. - ////////////////////////////////////////////////////////////////////////////// // // CHARACTER TO GLYPH-INDEX CONVERSIOn @@ -781,7 +778,6 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo * info, int unicode_code // codepoint-based functions. // Returns 0 if the character codepoint is not defined in the font. - ////////////////////////////////////////////////////////////////////////////// // // CHARACTER PROPERTIES @@ -968,7 +964,6 @@ STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo * font, int glyph, f STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo * font, int glyph, float scale_x, float scale_y, float shift_x, float shift_y, int * ix0, int * iy0, int * ix1, int * iy1); - // @TODO: don't expose this structure typedef struct { int w, h, stride; @@ -1044,8 +1039,6 @@ STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo * info, flo // The algorithm has not been optimized at all, so expect it to be slow // if computing lots of characters or very large sizes. - - ////////////////////////////////////////////////////////////////////////////// // // Finding the right font... @@ -1374,7 +1367,6 @@ static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) // on platforms that don't allow misaligned reads, if we want to allow // truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE - #ifdef STBTT_STREAM_TYPE static stbtt_uint8 ttBYTE(STBTT_STREAM_TYPE s, stbtt_uint32 offset) { @@ -3075,7 +3067,6 @@ typedef struct stbtt__edge { int invert; } stbtt__edge; - typedef struct stbtt__active_edge { struct stbtt__active_edge * next; #if STBTT_RASTERIZER_VERSION==1 @@ -4637,7 +4628,6 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context * spc, const unsigned char stbtt_pack_range * ranges, int num_ranges); #endif - STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context * spc, stbrp_rect * rects, int num_rects) { stbrp_pack_rects((stbrp_context *)spc->pack_info, rects, num_rects); @@ -4711,7 +4701,6 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context * spc, const unsigned char return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); } - #ifdef STBTT_STREAM_TYPE STBTT_DEF void stbtt_GetScaledFontVMetrics(STBTT_STREAM_TYPE fontdata, int index, float size, float * ascent, float * descent, float * lineGap); @@ -4720,7 +4709,6 @@ STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char * fontdata, int i float * descent, float * lineGap); #endif - #ifdef STBTT_STREAM_TYPE STBTT_DEF void stbtt_GetScaledFontVMetrics(STBTT_STREAM_TYPE fontdata, int index, float size, float * ascent, float * descent, float * lineGap) @@ -5372,7 +5360,6 @@ static int stbtt__matchpair(stbtt_uint8 * fc, stbtt_uint32 nm, stbtt_uint8 * nam #pragma GCC diagnostic ignored "-Wcast-qual" #endif - #ifdef STBTT_STREAM_TYPE STBTT_DEF int stbtt_BakeFontBitmap(STBTT_STREAM_TYPE data, int offset, float pixel_height, unsigned char * pixels, int pw, int ph, @@ -5465,7 +5452,6 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char * s1, int len1, cons #endif // STB_TRUETYPE_IMPLEMENTATION - // FULL VERSION HISTORY // // 1.25 (2021-07-11) many fixes diff --git a/lib/libesp32_lvgl/lvgl/src/libs/tjpgd/lv_tjpgd.c b/lib/libesp32_lvgl/lvgl/src/libs/tjpgd/lv_tjpgd.c new file mode 100644 index 000000000..2185c2828 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/tjpgd/lv_tjpgd.c @@ -0,0 +1,289 @@ +/** + * @file lv_tjpgd.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "../../../lvgl.h" +#if LV_USE_TJPGD + +#include "tjpgd.h" +#include "lv_tjpgd.h" +#include "../../misc/lv_fs.h" + +/********************* + * DEFINES + *********************/ +#define TJPGD_WORKBUFF_SIZE 4096 //Recommended by TJPGD library + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); + +static lv_result_t decoder_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, + const lv_area_t * full_area, lv_area_t * decoded_area); +static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); +static size_t input_func(JDEC * jd, uint8_t * buff, size_t ndata); +static int is_jpg(const uint8_t * raw_data, size_t len); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_tjpgd_init(void) +{ + lv_image_decoder_t * dec = lv_image_decoder_create(); + lv_image_decoder_set_info_cb(dec, decoder_info); + lv_image_decoder_set_open_cb(dec, decoder_open); + lv_image_decoder_set_get_area_cb(dec, decoder_get_area); + lv_image_decoder_set_close_cb(dec, decoder_close); +} + +void lv_tjpgd_deinit(void) +{ + lv_image_decoder_t * dec = NULL; + while((dec = lv_image_decoder_get_next(dec)) != NULL) { + if(dec->info_cb == decoder_info) { + lv_image_decoder_delete(dec); + break; + } + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) +{ + LV_UNUSED(decoder); + + lv_image_src_t src_type = lv_image_src_get_type(src); + + if(src_type == LV_IMAGE_SRC_VARIABLE) { + const lv_image_dsc_t * img_dsc = src; + uint8_t * raw_data = (uint8_t *)img_dsc->data; + const uint32_t raw_data_size = img_dsc->data_size; + + if(is_jpg(raw_data, raw_data_size) == true) { +#if LV_USE_FS_MEMFS + header->cf = LV_COLOR_FORMAT_RAW; + header->w = img_dsc->header.w; + header->h = img_dsc->header.h; + header->stride = img_dsc->header.w * 3; + return LV_RESULT_OK; +#else + LV_LOG_WARN("LV_USE_FS_MEMFS needs to enabled to decode from data"); + return LV_RESULT_INVALID; +#endif + } + } + else if(src_type == LV_IMAGE_SRC_FILE) { + const char * fn = src; + if((lv_strcmp(lv_fs_get_ext(fn), "jpg") == 0) || (lv_strcmp(lv_fs_get_ext(fn), "jpeg") == 0)) { + lv_fs_file_t f; + lv_fs_res_t res; + res = lv_fs_open(&f, fn, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) return LV_RESULT_INVALID; + + uint8_t workb[TJPGD_WORKBUFF_SIZE]; + JDEC jd; + JRESULT rc = jd_prepare(&jd, input_func, workb, TJPGD_WORKBUFF_SIZE, &f); + if(rc) { + LV_LOG_WARN("jd_prepare error: %d", rc); + lv_fs_close(&f); + return LV_RESULT_INVALID; + } + header->cf = LV_COLOR_FORMAT_RAW; + header->w = jd.width; + header->h = jd.height; + header->stride = jd.width * 3; + + lv_fs_close(&f); + return LV_RESULT_OK; + } + } + return LV_RESULT_INVALID; +} + +static size_t input_func(JDEC * jd, uint8_t * buff, size_t ndata) +{ + lv_fs_file_t * f = jd->device; + if(!f) return 0; + + if(buff) { + uint32_t rn = 0; + lv_fs_read(f, buff, (uint32_t)ndata, &rn); + return rn; + } + else { + uint32_t pos; + lv_fs_tell(f, &pos); + lv_fs_seek(f, (uint32_t)(ndata + pos), LV_FS_SEEK_SET); + return ndata; + } + return 0; +} + +/** + * Decode a JPG image and return the decoded data. + * @param decoder pointer to the decoder + * @param dsc pointer to the decoder descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image + */ +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); + lv_fs_file_t * f = lv_malloc(sizeof(lv_fs_file_t)); + if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) { +#if LV_USE_FS_MEMFS + const lv_image_dsc_t * img_dsc = dsc->src; + if(is_jpg(img_dsc->data, img_dsc->data_size) == true) { + lv_fs_path_ex_t path; + lv_fs_make_path_from_buffer(&path, LV_FS_MEMFS_LETTER, img_dsc->data, img_dsc->data_size); + lv_fs_res_t res; + res = lv_fs_open(f, (const char *)&path, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) { + lv_free(f); + return LV_RESULT_INVALID; + } + } +#else + LV_LOG_WARN("LV_USE_FS_MEMFS needs to enabled to decode from data"); + return LV_RESULT_INVALID; +#endif + } + else if(dsc->src_type == LV_IMAGE_SRC_FILE) { + const char * fn = dsc->src; + if((lv_strcmp(lv_fs_get_ext(fn), "jpg") == 0) || (lv_strcmp(lv_fs_get_ext(fn), "jpeg") == 0)) { + lv_fs_res_t res; + res = lv_fs_open(f, fn, LV_FS_MODE_RD); + if(res != LV_FS_RES_OK) { + lv_free(f); + return LV_RESULT_INVALID; + } + } + } + + uint8_t * workb_temp = lv_malloc(TJPGD_WORKBUFF_SIZE); + JDEC * jd = lv_malloc(sizeof(JDEC)); + dsc->user_data = jd; + JRESULT rc = jd_prepare(jd, input_func, workb_temp, (size_t)TJPGD_WORKBUFF_SIZE, f); + if(rc) return rc; + + dsc->header.cf = LV_COLOR_FORMAT_RGB888; + dsc->header.w = jd->width; + dsc->header.h = jd->height; + dsc->header.stride = jd->width * 3; + + if(rc != JDR_OK) { + lv_free(workb_temp); + lv_free(jd); + return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; +} + +static lv_result_t decoder_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, + const lv_area_t * full_area, lv_area_t * decoded_area) +{ + LV_UNUSED(decoder); + LV_UNUSED(full_area); + + JDEC * jd = dsc->user_data; + lv_draw_buf_t * decoded = (void *)dsc->decoded; + if(decoded == NULL) decoded = lv_malloc_zeroed(sizeof(lv_draw_buf_t)); + dsc->decoded = decoded; + + uint32_t mx, my; + mx = jd->msx * 8; + my = jd->msy * 8; /* Size of the MCU (pixel) */ + if(decoded_area->y1 == LV_COORD_MIN) { + decoded_area->y1 = 0; + decoded_area->y2 = my - 1; + decoded_area->x1 = -mx; + decoded_area->x2 = -1; + jd->scale = 0; + jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */ + jd->rst = 0; + jd->rsc = 0; + decoded->data = jd->workbuf; + decoded->header = dsc->header; + decoded->header.stride = mx * 3; + } + + decoded_area->x1 += mx; + decoded_area->x2 += mx; + + if(decoded_area->x1 >= jd->width) { + decoded_area->x1 = 0; + decoded_area->x2 = mx - 1; + decoded_area->y1 += my; + decoded_area->y2 += my; + } + + decoded->header.w = mx; + decoded->header.h = my; + decoded->data_size = decoded->header.stride * decoded->header.h; + + /* Process restart interval if enabled */ + JRESULT rc; + if(jd->nrst && jd->rst++ == jd->nrst) { + rc = jd_restart(jd, jd->rsc++); + if(rc != JDR_OK) return rc; + jd->rst = 1; + } + + /* Load an MCU (decompress huffman coded stream, dequantize and apply IDCT) */ + rc = jd_mcu_load(jd); + if(rc != JDR_OK) return rc; + + /* Output the MCU (YCbCr to RGB, scaling and output) */ + rc = jd_mcu_output(jd, NULL, decoded_area->x1, decoded_area->y1); + if(rc != JDR_OK) return rc; + + return LV_RESULT_OK; +} + +/** + * Free the allocated resources + * @param decoder pointer to the decoder where this function belongs + * @param dsc pointer to a descriptor which describes this decoding session + */ +static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +{ + LV_UNUSED(decoder); + JDEC * jd = dsc->user_data; + lv_fs_close(jd->device); + lv_free(jd->device); + lv_free(jd->pool_original); + lv_free(jd); + lv_free((void *)dsc->decoded); +} + +static int is_jpg(const uint8_t * raw_data, size_t len) +{ + const uint8_t jpg_signature[] = {0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46}; + if(len < sizeof(jpg_signature)) return false; + return memcmp(jpg_signature, raw_data, sizeof(jpg_signature)) == 0; +} + +#endif /*LV_USE_TJPGD*/ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/tjpgd/lv_tjpgd.h b/lib/libesp32_lvgl/lvgl/src/libs/tjpgd/lv_tjpgd.h new file mode 100644 index 000000000..ec35800b2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/tjpgd/lv_tjpgd.h @@ -0,0 +1,45 @@ +/** + * @file lv_tjpgd.h + * + */ + +#ifndef LV_TJPGD_H +#define LV_TJPGD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#if LV_USE_TJPGD + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_tjpgd_init(void); + +void lv_tjpgd_deinit(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_TJPGD*/ + +#ifdef __cplusplus +} +#endif + +#endif /* LV_TJPGD_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/libs/tjpgd/tjpgd.c b/lib/libesp32_lvgl/lvgl/src/libs/tjpgd/tjpgd.c new file mode 100644 index 000000000..22dfd5632 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/tjpgd/tjpgd.c @@ -0,0 +1,1137 @@ +/*----------------------------------------------------------------------------/ +/ TJpgDec - Tiny JPEG Decompressor R0.03 (C)ChaN, 2021 +/-----------------------------------------------------------------------------/ +/ The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. +/ This is a free software that opened for education, research and commercial +/ developments under license policy of following terms. +/ +/ Copyright (C) 2021, ChaN, all right reserved. +/ +/ * The TJpgDec module is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/-----------------------------------------------------------------------------/ +/ Oct 04, 2011 R0.01 First release. +/ Feb 19, 2012 R0.01a Fixed decompression fails when scan starts with an escape seq. +/ Sep 03, 2012 R0.01b Added JD_TBLCLIP option. +/ Mar 16, 2019 R0.01c Supported stdint.h. +/ Jul 01, 2020 R0.01d Fixed wrong integer type usage. +/ May 08, 2021 R0.02 Supported grayscale image. Separated configuration options. +/ Jun 11, 2021 R0.02a Some performance improvement. +/ Jul 01, 2021 R0.03 Added JD_FASTDECODE option. +/ Some performance improvement. +/----------------------------------------------------------------------------*/ + +#include "tjpgd.h" + + +#if JD_FASTDECODE == 2 + #define HUFF_BIT 10 /* Bit length to apply fast huffman decode */ + #define HUFF_LEN (1 << HUFF_BIT) + #define HUFF_MASK (HUFF_LEN - 1) +#endif + + +/*-----------------------------------------------*/ +/* Zigzag-order to raster-order conversion table */ +/*-----------------------------------------------*/ + +static const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion table */ + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + + + +/*-------------------------------------------------*/ +/* Input scale factor of Arai algorithm */ +/* (scaled up 16 bits for fixed point operations) */ +/*-------------------------------------------------*/ + +static const uint16_t Ipsf[64] = { /* See also aa_idct.png */ + (uint16_t)(1.00000 * 8192), (uint16_t)(1.38704 * 8192), (uint16_t)(1.30656 * 8192), (uint16_t)(1.17588 * 8192), (uint16_t)(1.00000 * 8192), (uint16_t)(0.78570 * 8192), (uint16_t)(0.54120 * 8192), (uint16_t)(0.27590 * 8192), + (uint16_t)(1.38704 * 8192), (uint16_t)(1.92388 * 8192), (uint16_t)(1.81226 * 8192), (uint16_t)(1.63099 * 8192), (uint16_t)(1.38704 * 8192), (uint16_t)(1.08979 * 8192), (uint16_t)(0.75066 * 8192), (uint16_t)(0.38268 * 8192), + (uint16_t)(1.30656 * 8192), (uint16_t)(1.81226 * 8192), (uint16_t)(1.70711 * 8192), (uint16_t)(1.53636 * 8192), (uint16_t)(1.30656 * 8192), (uint16_t)(1.02656 * 8192), (uint16_t)(0.70711 * 8192), (uint16_t)(0.36048 * 8192), + (uint16_t)(1.17588 * 8192), (uint16_t)(1.63099 * 8192), (uint16_t)(1.53636 * 8192), (uint16_t)(1.38268 * 8192), (uint16_t)(1.17588 * 8192), (uint16_t)(0.92388 * 8192), (uint16_t)(0.63638 * 8192), (uint16_t)(0.32442 * 8192), + (uint16_t)(1.00000 * 8192), (uint16_t)(1.38704 * 8192), (uint16_t)(1.30656 * 8192), (uint16_t)(1.17588 * 8192), (uint16_t)(1.00000 * 8192), (uint16_t)(0.78570 * 8192), (uint16_t)(0.54120 * 8192), (uint16_t)(0.27590 * 8192), + (uint16_t)(0.78570 * 8192), (uint16_t)(1.08979 * 8192), (uint16_t)(1.02656 * 8192), (uint16_t)(0.92388 * 8192), (uint16_t)(0.78570 * 8192), (uint16_t)(0.61732 * 8192), (uint16_t)(0.42522 * 8192), (uint16_t)(0.21677 * 8192), + (uint16_t)(0.54120 * 8192), (uint16_t)(0.75066 * 8192), (uint16_t)(0.70711 * 8192), (uint16_t)(0.63638 * 8192), (uint16_t)(0.54120 * 8192), (uint16_t)(0.42522 * 8192), (uint16_t)(0.29290 * 8192), (uint16_t)(0.14932 * 8192), + (uint16_t)(0.27590 * 8192), (uint16_t)(0.38268 * 8192), (uint16_t)(0.36048 * 8192), (uint16_t)(0.32442 * 8192), (uint16_t)(0.27590 * 8192), (uint16_t)(0.21678 * 8192), (uint16_t)(0.14932 * 8192), (uint16_t)(0.07612 * 8192) +}; + + + +/*---------------------------------------------*/ +/* Conversion table for fast clipping process */ +/*---------------------------------------------*/ + +#if JD_TBLCLIP + +#define BYTECLIP(v) Clip8[(unsigned int)(v) & 0x3FF] + +static const uint8_t Clip8[1024] = { + /* 0..255 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + /* 256..511 */ + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* -512..-257 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* -256..-1 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +#else /* JD_TBLCLIP */ + +static uint8_t BYTECLIP(int val) +{ + if(val < 0) return 0; + if(val > 255) return 255; + return (uint8_t)val; +} + +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Allocate a memory block from memory pool */ +/*-----------------------------------------------------------------------*/ + +static void * alloc_pool( /* Pointer to allocated memory block (NULL:no memory available) */ + JDEC * jd, /* Pointer to the decompressor object */ + size_t ndata /* Number of bytes to allocate */ +) +{ + char * rp = 0; + + + ndata = (ndata + 3) & ~3; /* Align block size to the word boundary */ + + if(jd->sz_pool >= ndata) { + jd->sz_pool -= ndata; + rp = (char *)jd->pool; /* Get start of available memory pool */ + jd->pool = (void *)(rp + ndata); /* Allocate required bytes */ + } + + return (void *)rp; /* Return allocated memory block (NULL:no memory to allocate) */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Create de-quantization and prescaling tables with a DQT segment */ +/*-----------------------------------------------------------------------*/ + +static JRESULT create_qt_tbl( /* 0:OK, !0:Failed */ + JDEC * jd, /* Pointer to the decompressor object */ + const uint8_t * data, /* Pointer to the quantizer tables */ + size_t ndata /* Size of input data */ +) +{ + unsigned int i, zi; + uint8_t d; + int32_t * pb; + + + while(ndata) { /* Process all tables in the segment */ + if(ndata < 65) return JDR_FMT1; /* Err: table size is unaligned */ + ndata -= 65; + d = *data++; /* Get table property */ + if(d & 0xF0) return JDR_FMT1; /* Err: not 8-bit resolution */ + i = d & 3; /* Get table ID */ + pb = alloc_pool(jd, 64 * sizeof(int32_t)); /* Allocate a memory block for the table */ + if(!pb) return JDR_MEM1; /* Err: not enough memory */ + jd->qttbl[i] = pb; /* Register the table */ + for(i = 0; i < 64; i++) { /* Load the table */ + zi = Zig[i]; /* Zigzag-order to raster-order conversion */ + pb[zi] = (int32_t)((uint32_t) * data++ * Ipsf[zi]); /* Apply scale factor of Arai algorithm to the de-quantizers */ + } + } + + return JDR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Create huffman code tables with a DHT segment */ +/*-----------------------------------------------------------------------*/ + +static JRESULT create_huffman_tbl( /* 0:OK, !0:Failed */ + JDEC * jd, /* Pointer to the decompressor object */ + const uint8_t * data, /* Pointer to the packed huffman tables */ + size_t ndata /* Size of input data */ +) +{ + unsigned int i, j, b, cls, num; + size_t np; + uint8_t d, * pb, * pd; + uint16_t hc, * ph; + + + while(ndata) { /* Process all tables in the segment */ + if(ndata < 17) return JDR_FMT1; /* Err: wrong data size */ + ndata -= 17; + d = *data++; /* Get table number and class */ + if(d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */ + cls = d >> 4; + num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */ + pb = alloc_pool(jd, 16); /* Allocate a memory block for the bit distribution table */ + if(!pb) return JDR_MEM1; /* Err: not enough memory */ + jd->huffbits[num][cls] = pb; + for(np = i = 0; i < 16; i++) { /* Load number of patterns for 1 to 16-bit code */ + np += (pb[i] = *data++); /* Get sum of code words for each code */ + } + ph = alloc_pool(jd, np * sizeof(uint16_t)); /* Allocate a memory block for the code word table */ + if(!ph) return JDR_MEM1; /* Err: not enough memory */ + jd->huffcode[num][cls] = ph; + hc = 0; + for(j = i = 0; i < 16; i++) { /* Re-build huffman code word table */ + b = pb[i]; + while(b--) ph[j++] = hc++; + hc <<= 1; + } + + if(ndata < np) return JDR_FMT1; /* Err: wrong data size */ + ndata -= np; + pd = alloc_pool(jd, np); /* Allocate a memory block for the decoded data */ + if(!pd) return JDR_MEM1; /* Err: not enough memory */ + jd->huffdata[num][cls] = pd; + for(i = 0; i < np; i++) { /* Load decoded data corresponds to each code word */ + d = *data++; + if(!cls && d > 11) return JDR_FMT1; + pd[i] = d; + } +#if JD_FASTDECODE == 2 + { /* Create fast huffman decode table */ + unsigned int span, td, ti; + uint16_t * tbl_ac = 0; + uint8_t * tbl_dc = 0; + + if(cls) { + tbl_ac = alloc_pool(jd, HUFF_LEN * sizeof(uint16_t)); /* LUT for AC elements */ + if(!tbl_ac) return JDR_MEM1; /* Err: not enough memory */ + jd->hufflut_ac[num] = tbl_ac; + memset(tbl_ac, 0xFF, HUFF_LEN * sizeof(uint16_t)); /* Default value (0xFFFF: may be long code) */ + } + else { + tbl_dc = alloc_pool(jd, HUFF_LEN * sizeof(uint8_t)); /* LUT for AC elements */ + if(!tbl_dc) return JDR_MEM1; /* Err: not enough memory */ + jd->hufflut_dc[num] = tbl_dc; + memset(tbl_dc, 0xFF, HUFF_LEN * sizeof(uint8_t)); /* Default value (0xFF: may be long code) */ + } + for(i = b = 0; b < HUFF_BIT; b++) { /* Create LUT */ + for(j = pb[b]; j; j--) { + ti = ph[i] << (HUFF_BIT - 1 - b) & HUFF_MASK; /* Index of input pattern for the code */ + if(cls) { + td = pd[i++] | ((b + 1) << 8); /* b15..b8: code length, b7..b0: zero run and data length */ + for(span = 1 << (HUFF_BIT - 1 - b); span; span--, tbl_ac[ti++] = (uint16_t)td) ; + } + else { + td = pd[i++] | ((b + 1) << 4); /* b7..b4: code length, b3..b0: data length */ + for(span = 1 << (HUFF_BIT - 1 - b); span; span--, tbl_dc[ti++] = (uint8_t)td) ; + } + } + } + jd->longofs[num][cls] = i; /* Code table offset for long code */ + } +#endif + } + + return JDR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Extract a huffman decoded data from input stream */ +/*-----------------------------------------------------------------------*/ + +static int huffext( /* >=0: decoded data, <0: error code */ + JDEC * jd, /* Pointer to the decompressor object */ + unsigned int id, /* Table ID (0:Y, 1:C) */ + unsigned int cls /* Table class (0:DC, 1:AC) */ +) +{ + size_t dc = jd->dctr; + uint8_t * dp = jd->dptr; + unsigned int d, flg = 0; + +#if JD_FASTDECODE == 0 + uint8_t bm, nd, bl; + const uint8_t * hb = jd->huffbits[id][cls]; /* Bit distribution table */ + const uint16_t * hc = jd->huffcode[id][cls]; /* Code word table */ + const uint8_t * hd = jd->huffdata[id][cls]; /* Data table */ + + + bm = jd->dbit; /* Bit mask to extract */ + d = 0; + bl = 16; /* Max code length */ + do { + if(!bm) { /* Next byte? */ + if(!dc) { /* No input data is available, re-fill input buffer */ + dp = jd->inbuf; /* Top of input buffer */ + dc = jd->infunc(jd, dp, JD_SZBUF); + if(!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ + } + else { + dp++; /* Next data ptr */ + } + dc--; /* Decrement number of available bytes */ + if(flg) { /* In flag sequence? */ + flg = 0; /* Exit flag sequence */ + if(*dp != 0) return 0 - (int)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ + *dp = 0xFF; /* The flag is a data 0xFF */ + } + else { + if(*dp == 0xFF) { /* Is start of flag sequence? */ + flg = 1; + continue; /* Enter flag sequence, get trailing byte */ + } + } + bm = 0x80; /* Read from MSB */ + } + d <<= 1; /* Get a bit */ + if(*dp & bm) d++; + bm >>= 1; + + for(nd = *hb++; nd; nd--) { /* Search the code word in this bit length */ + if(d == *hc++) { /* Matched? */ + jd->dbit = bm; + jd->dctr = dc; + jd->dptr = dp; + return *hd; /* Return the decoded data */ + } + hd++; + } + bl--; + } while(bl); + +#else + const uint8_t * hb, * hd; + const uint16_t * hc; + unsigned int nc, bl, wbit = jd->dbit % 32; + uint32_t w = jd->wreg & ((1UL << wbit) - 1); + + + while(wbit < 16) { /* Prepare 16 bits into the working register */ + if(jd->marker) { + d = 0xFF; /* Input stream has stalled for a marker. Generate stuff bits */ + } + else { + if(!dc) { /* Buffer empty, re-fill input buffer */ + dp = jd->inbuf; /* Top of input buffer */ + dc = jd->infunc(jd, dp, JD_SZBUF); + if(!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ + } + d = *dp++; + dc--; + if(flg) { /* In flag sequence? */ + flg = 0; /* Exit flag sequence */ + if(d != 0) jd->marker = d; /* Not an escape of 0xFF but a marker */ + d = 0xFF; + } + else { + if(d == 0xFF) { /* Is start of flag sequence? */ + flg = 1; + continue; /* Enter flag sequence, get trailing byte */ + } + } + } + w = w << 8 | d; /* Shift 8 bits in the working register */ + wbit += 8; + } + jd->dctr = dc; + jd->dptr = dp; + jd->wreg = w; + +#if JD_FASTDECODE == 2 + /* Table search for the short codes */ + d = (unsigned int)(w >> (wbit - HUFF_BIT)); /* Short code as table index */ + if(cls) { /* AC element */ + d = jd->hufflut_ac[id][d]; /* Table decode */ + if(d != 0xFFFF) { /* It is done if hit in short code */ + jd->dbit = wbit - (d >> 8); /* Snip the code length */ + return d & 0xFF; /* b7..0: zero run and following data bits */ + } + } + else { /* DC element */ + d = jd->hufflut_dc[id][d]; /* Table decode */ + if(d != 0xFF) { /* It is done if hit in short code */ + jd->dbit = wbit - (d >> 4); /* Snip the code length */ + return d & 0xF; /* b3..0: following data bits */ + } + } + + /* Incremental search for the codes longer than HUFF_BIT */ + hb = jd->huffbits[id][cls] + HUFF_BIT; /* Bit distribution table */ + hc = jd->huffcode[id][cls] + jd->longofs[id][cls]; /* Code word table */ + hd = jd->huffdata[id][cls] + jd->longofs[id][cls]; /* Data table */ + bl = HUFF_BIT + 1; +#else + /* Incremental search for all codes */ + hb = jd->huffbits[id][cls]; /* Bit distribution table */ + hc = jd->huffcode[id][cls]; /* Code word table */ + hd = jd->huffdata[id][cls]; /* Data table */ + bl = 1; +#endif + for(; bl <= 16; bl++) { /* Incremental search */ + nc = *hb++; + if(nc) { + d = w >> (wbit - bl); + do { /* Search the code word in this bit length */ + if(d == *hc++) { /* Matched? */ + jd->dbit = wbit - bl; /* Snip the huffman code */ + return *hd; /* Return the decoded data */ + } + hd++; + } while(--nc); + } + } +#endif + + return 0 - (int)JDR_FMT1; /* Err: code not found (may be collapted data) */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Extract N bits from input stream */ +/*-----------------------------------------------------------------------*/ + +static int bitext( /* >=0: extracted data, <0: error code */ + JDEC * jd, /* Pointer to the decompressor object */ + unsigned int nbit /* Number of bits to extract (1 to 16) */ +) +{ + size_t dc = jd->dctr; + uint8_t * dp = jd->dptr; + unsigned int d, flg = 0; + +#if JD_FASTDECODE == 0 + uint8_t mbit = jd->dbit; + + d = 0; + do { + if(!mbit) { /* Next byte? */ + if(!dc) { /* No input data is available, re-fill input buffer */ + dp = jd->inbuf; /* Top of input buffer */ + dc = jd->infunc(jd, dp, JD_SZBUF); + if(!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ + } + else { + dp++; /* Next data ptr */ + } + dc--; /* Decrement number of available bytes */ + if(flg) { /* In flag sequence? */ + flg = 0; /* Exit flag sequence */ + if(*dp != 0) return 0 - (int)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ + *dp = 0xFF; /* The flag is a data 0xFF */ + } + else { + if(*dp == 0xFF) { /* Is start of flag sequence? */ + flg = 1; + continue; /* Enter flag sequence */ + } + } + mbit = 0x80; /* Read from MSB */ + } + d <<= 1; /* Get a bit */ + if(*dp & mbit) d |= 1; + mbit >>= 1; + nbit--; + } while(nbit); + + jd->dbit = mbit; + jd->dctr = dc; + jd->dptr = dp; + return (int)d; + +#else + unsigned int wbit = jd->dbit % 32; + uint32_t w = jd->wreg & ((1UL << wbit) - 1); + + + while(wbit < nbit) { /* Prepare nbit bits into the working register */ + if(jd->marker) { + d = 0xFF; /* Input stream stalled, generate stuff bits */ + } + else { + if(!dc) { /* Buffer empty, re-fill input buffer */ + dp = jd->inbuf; /* Top of input buffer */ + dc = jd->infunc(jd, dp, JD_SZBUF); + if(!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */ + } + d = *dp++; + dc--; + if(flg) { /* In flag sequence? */ + flg = 0; /* Exit flag sequence */ + if(d != 0) jd->marker = d; /* Not an escape of 0xFF but a marker */ + d = 0xFF; + } + else { + if(d == 0xFF) { /* Is start of flag sequence? */ + flg = 1; + continue; /* Enter flag sequence, get trailing byte */ + } + } + } + w = w << 8 | d; /* Get 8 bits into the working register */ + wbit += 8; + } + jd->wreg = w; + jd->dbit = wbit - nbit; + jd->dctr = dc; + jd->dptr = dp; + + return (int)(w >> ((wbit - nbit) % 32)); +#endif +} + + + + +/*-----------------------------------------------------------------------*/ +/* Process restart interval */ +/*-----------------------------------------------------------------------*/ + +JRESULT jd_restart( + JDEC * jd, /* Pointer to the decompressor object */ + uint16_t rstn /* Expected restert sequence number */ +) +{ + unsigned int i; + uint8_t * dp = jd->dptr; + size_t dc = jd->dctr; + +#if JD_FASTDECODE == 0 + uint16_t d = 0; + + /* Get two bytes from the input stream */ + for(i = 0; i < 2; i++) { + if(!dc) { /* No input data is available, re-fill input buffer */ + dp = jd->inbuf; + dc = jd->infunc(jd, dp, JD_SZBUF); + if(!dc) return JDR_INP; + } + else { + dp++; + } + dc--; + d = d << 8 | *dp; /* Get a byte */ + } + jd->dptr = dp; + jd->dctr = dc; + jd->dbit = 0; + + /* Check the marker */ + if((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) { + return JDR_FMT1; /* Err: expected RSTn marker is not detected (may be collapted data) */ + } + +#else + uint16_t marker; + + + if(jd->marker) { /* Generate a maker if it has been detected */ + marker = 0xFF00 | jd->marker; + jd->marker = 0; + } + else { + marker = 0; + for(i = 0; i < 2; i++) { /* Get a restart marker */ + if(!dc) { /* No input data is available, re-fill input buffer */ + dp = jd->inbuf; + dc = jd->infunc(jd, dp, JD_SZBUF); + if(!dc) return JDR_INP; + } + marker = (marker << 8) | *dp++; /* Get a byte */ + dc--; + } + jd->dptr = dp; + jd->dctr = dc; + } + + /* Check the marker */ + if((marker & 0xFFD8) != 0xFFD0 || (marker & 7) != (rstn & 7)) { + return JDR_FMT1; /* Err: expected RSTn marker was not detected (may be collapted data) */ + } + + jd->dbit = 0; /* Discard stuff bits */ +#endif + + jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Reset DC offset */ + return JDR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Apply Inverse-DCT in Arai Algorithm (see also aa_idct.png) */ +/*-----------------------------------------------------------------------*/ + +static void block_idct( + int32_t * src, /* Input block data (de-quantized and pre-scaled for Arai Algorithm) */ + jd_yuv_t * dst /* Pointer to the destination to store the block as byte array */ +) +{ + const int32_t M13 = (int32_t)(1.41421 * 4096), M2 = (int32_t)(1.08239 * 4096), M4 = (int32_t)(2.61313 * 4096), + M5 = (int32_t)(1.84776 * 4096); + int32_t v0, v1, v2, v3, v4, v5, v6, v7; + int32_t t10, t11, t12, t13; + int i; + + /* Process columns */ + for(i = 0; i < 8; i++) { + v0 = src[8 * 0]; /* Get even elements */ + v1 = src[8 * 2]; + v2 = src[8 * 4]; + v3 = src[8 * 6]; + + t10 = v0 + v2; /* Process the even elements */ + t12 = v0 - v2; + t11 = (v1 - v3) * M13 >> 12; + v3 += v1; + t11 -= v3; + v0 = t10 + v3; + v3 = t10 - v3; + v1 = t11 + t12; + v2 = t12 - t11; + + v4 = src[8 * 7]; /* Get odd elements */ + v5 = src[8 * 1]; + v6 = src[8 * 5]; + v7 = src[8 * 3]; + + t10 = v5 - v4; /* Process the odd elements */ + t11 = v5 + v4; + t12 = v6 - v7; + v7 += v6; + v5 = (t11 - v7) * M13 >> 12; + v7 += t11; + t13 = (t10 + t12) * M5 >> 12; + v4 = t13 - (t10 * M2 >> 12); + v6 = t13 - (t12 * M4 >> 12) - v7; + v5 -= v6; + v4 -= v5; + + src[8 * 0] = v0 + v7; /* Write-back transformed values */ + src[8 * 7] = v0 - v7; + src[8 * 1] = v1 + v6; + src[8 * 6] = v1 - v6; + src[8 * 2] = v2 + v5; + src[8 * 5] = v2 - v5; + src[8 * 3] = v3 + v4; + src[8 * 4] = v3 - v4; + + src++; /* Next column */ + } + + /* Process rows */ + src -= 8; + for(i = 0; i < 8; i++) { + v0 = src[0] + (128L << 8); /* Get even elements (remove DC offset (-128) here) */ + v1 = src[2]; + v2 = src[4]; + v3 = src[6]; + + t10 = v0 + v2; /* Process the even elements */ + t12 = v0 - v2; + t11 = (v1 - v3) * M13 >> 12; + v3 += v1; + t11 -= v3; + v0 = t10 + v3; + v3 = t10 - v3; + v1 = t11 + t12; + v2 = t12 - t11; + + v4 = src[7]; /* Get odd elements */ + v5 = src[1]; + v6 = src[5]; + v7 = src[3]; + + t10 = v5 - v4; /* Process the odd elements */ + t11 = v5 + v4; + t12 = v6 - v7; + v7 += v6; + v5 = (t11 - v7) * M13 >> 12; + v7 += t11; + t13 = (t10 + t12) * M5 >> 12; + v4 = t13 - (t10 * M2 >> 12); + v6 = t13 - (t12 * M4 >> 12) - v7; + v5 -= v6; + v4 -= v5; + + /* Descale the transformed values 8 bits and output a row */ +#if JD_FASTDECODE >= 1 + dst[0] = (int16_t)((v0 + v7) >> 8); + dst[7] = (int16_t)((v0 - v7) >> 8); + dst[1] = (int16_t)((v1 + v6) >> 8); + dst[6] = (int16_t)((v1 - v6) >> 8); + dst[2] = (int16_t)((v2 + v5) >> 8); + dst[5] = (int16_t)((v2 - v5) >> 8); + dst[3] = (int16_t)((v3 + v4) >> 8); + dst[4] = (int16_t)((v3 - v4) >> 8); +#else + dst[0] = BYTECLIP((v0 + v7) >> 8); + dst[7] = BYTECLIP((v0 - v7) >> 8); + dst[1] = BYTECLIP((v1 + v6) >> 8); + dst[6] = BYTECLIP((v1 - v6) >> 8); + dst[2] = BYTECLIP((v2 + v5) >> 8); + dst[5] = BYTECLIP((v2 - v5) >> 8); + dst[3] = BYTECLIP((v3 + v4) >> 8); + dst[4] = BYTECLIP((v3 - v4) >> 8); +#endif + + dst += 8; + src += 8; /* Next row */ + } +} + + + + +/*-----------------------------------------------------------------------*/ +/* Load all blocks in an MCU into working buffer */ +/*-----------------------------------------------------------------------*/ + +JRESULT jd_mcu_load( + JDEC * jd /* Pointer to the decompressor object */ +) +{ + int32_t * tmp = (int32_t *)jd->workbuf; /* Block working buffer for de-quantize and IDCT */ + int d, e; + unsigned int blk, nby, i, bc, z, id, cmp; + jd_yuv_t * bp; + const int32_t * dqf; + + + nby = jd->msx * jd->msy; /* Number of Y blocks (1, 2 or 4) */ + bp = jd->mcubuf; /* Pointer to the first block of MCU */ + + for(blk = 0; blk < nby + 2; blk++) { /* Get nby Y blocks and two C blocks */ + cmp = (blk < nby) ? 0 : blk - nby + 1; /* Component number 0:Y, 1:Cb, 2:Cr */ + + if(cmp && jd->ncomp != 3) { /* Clear C blocks if not exist (monochrome image) */ + for(i = 0; i < 64; bp[i++] = 128) ; + + } + else { /* Load Y/C blocks from input stream */ + id = cmp ? 1 : 0; /* Huffman table ID of this component */ + + /* Extract a DC element from input stream */ + d = huffext(jd, id, 0); /* Extract a huffman coded data (bit length) */ + if(d < 0) return (JRESULT)(0 - d); /* Err: invalid code or input */ + bc = (unsigned int)d; + d = jd->dcv[cmp]; /* DC value of previous block */ + if(bc) { /* If there is any difference from previous block */ + e = bitext(jd, bc); /* Extract data bits */ + if(e < 0) return (JRESULT)(0 - e); /* Err: input */ + bc = 1 << (bc - 1); /* MSB position */ + if(!(e & bc)) e -= (bc << 1) - 1; /* Restore negative value if needed */ + d += e; /* Get current value */ + jd->dcv[cmp] = (int16_t)d; /* Save current DC value for next block */ + } + dqf = jd->qttbl[jd->qtid[cmp]]; /* De-quantizer table ID for this component */ + tmp[0] = d * dqf[0] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ + + /* Extract following 63 AC elements from input stream */ + memset(&tmp[1], 0, 63 * sizeof(int32_t)); /* Initialize all AC elements */ + z = 1; /* Top of the AC elements (in zigzag-order) */ + do { + d = huffext(jd, id, 1); /* Extract a huffman coded value (zero runs and bit length) */ + if(d == 0) break; /* EOB? */ + if(d < 0) return (JRESULT)(0 - d); /* Err: invalid code or input error */ + bc = (unsigned int)d; + z += bc >> 4; /* Skip leading zero run */ + if(z >= 64) return JDR_FMT1; /* Too long zero run */ + if(bc &= 0x0F) { /* Bit length? */ + d = bitext(jd, bc); /* Extract data bits */ + if(d < 0) return (JRESULT)(0 - d); /* Err: input device */ + bc = 1 << (bc - 1); /* MSB position */ + if(!(d & bc)) d -= (bc << 1) - 1; /* Restore negative value if needed */ + i = Zig[z]; /* Get raster-order index */ + tmp[i] = d * dqf[i] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ + } + } while(++z < 64); /* Next AC element */ + + if(JD_FORMAT != 2 || !cmp) { /* C components may not be processed if in grayscale output */ + if(z == 1 || (JD_USE_SCALE && + jd->scale == + 3)) { /* If no AC element or scale ratio is 1/8, IDCT can be omitted and the block is filled with DC value */ + d = (jd_yuv_t)((*tmp / 256) + 128); + if(JD_FASTDECODE >= 1) { + for(i = 0; i < 64; bp[i++] = d) ; + } + else { + memset(bp, d, 64); + } + } + else { + block_idct(tmp, bp); /* Apply IDCT and store the block to the MCU buffer */ + } + } + } + + bp += 64; /* Next block */ + } + + return JDR_OK; /* All blocks have been loaded successfully */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Output an MCU: Convert YCrCb to RGB and output it in RGB form */ +/*-----------------------------------------------------------------------*/ + +JRESULT jd_mcu_output( + JDEC * jd, /* Pointer to the decompressor object */ + int (*outfunc)(JDEC *, void *, JRECT *), /* RGB output function */ + unsigned int x, /* MCU location in the image */ + unsigned int y /* MCU location in the image */ +) +{ + const int CVACC = (sizeof(int) > 2) ? 1024 : 128; /* Adaptive accuracy for both 16-/32-bit systems */ + unsigned int ix, iy, mx, my, rx, ry; + int yy, cb, cr; + jd_yuv_t * py, * pc; + uint8_t * pix; + JRECT rect; + + + mx = jd->msx * 8; + my = jd->msy * 8; /* MCU size (pixel) */ + rx = (x + mx <= jd->width) ? mx : jd->width - + x; /* Output rectangular size (it may be clipped at right/bottom end of image) */ + ry = (y + my <= jd->height) ? my : jd->height - y; + if(JD_USE_SCALE) { + rx >>= jd->scale; + ry >>= jd->scale; + if(!rx || !ry) return JDR_OK; /* Skip this MCU if all pixel is to be rounded off */ + x >>= jd->scale; + y >>= jd->scale; + } + rect.left = x; + rect.right = x + rx - 1; /* Rectangular area in the frame buffer */ + rect.top = y; + rect.bottom = y + ry - 1; + + + if(!JD_USE_SCALE || jd->scale != 3) { /* Not for 1/8 scaling */ + pix = (uint8_t *)jd->workbuf; + + if(JD_FORMAT != 2) { /* RGB output (build an RGB MCU from Y/C component) */ + for(iy = 0; iy < my; iy++) { + pc = py = jd->mcubuf; + if(my == 16) { /* Double block height? */ + pc += 64 * 4 + (iy >> 1) * 8; + if(iy >= 8) py += 64; + } + else { /* Single block height */ + pc += mx * 8 + iy * 8; + } + py += iy * 8; + for(ix = 0; ix < mx; ix++) { + cb = pc[0] - 128; /* Get Cb/Cr component and remove offset */ + cr = pc[64] - 128; + if(mx == 16) { /* Double block width? */ + if(ix == 8) py += 64 - 8; /* Jump to next block if double block height */ + pc += ix & 1; /* Step forward chroma pointer every two pixels */ + } + else { /* Single block width */ + pc++; /* Step forward chroma pointer every pixel */ + } + yy = *py++; /* Get Y component */ + *pix++ = /*B*/ BYTECLIP(yy + ((int)(1.772 * CVACC) * cb) / CVACC); + *pix++ = /*G*/ BYTECLIP(yy - ((int)(0.344 * CVACC) * cb + (int)(0.714 * CVACC) * cr) / CVACC); + *pix++ = /*R*/ BYTECLIP(yy + ((int)(1.402 * CVACC) * cr) / CVACC); + } + } + } + } + + /* Squeeze up pixel table if a part of MCU is to be truncated */ + mx >>= jd->scale; + if(rx < mx) { /* Is the MCU spans rigit edge? */ + uint8_t * s, * d; + unsigned int xi, yi; + + s = d = (uint8_t *)jd->workbuf; + for(yi = 0; yi < ry; yi++) { + for(xi = 0; xi < rx; xi++) { /* Copy effective pixels */ + *d++ = *s++; + if(JD_FORMAT != 2) { + *d++ = *s++; + *d++ = *s++; + } + } + s += (mx - rx) * (JD_FORMAT != 2 ? 3 : 1); /* Skip truncated pixels */ + } + } + + /* Convert RGB888 to RGB565 if needed */ + if(JD_FORMAT == 1) { + uint8_t * s = (uint8_t *)jd->workbuf; + uint16_t w, * d = (uint16_t *)s; + unsigned int n = rx * ry; + + do { + w = (*s++ & 0xF8) << 8; /* RRRRR----------- */ + w |= (*s++ & 0xFC) << 3; /* -----GGGGGG----- */ + w |= *s++ >> 3; /* -----------BBBBB */ + *d++ = w; + } while(--n); + } + + /* Output the rectangular */ + if(outfunc) return outfunc(jd, jd->workbuf, &rect) ? JDR_OK : JDR_INTR; + return 0; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Analyze the JPEG image and Initialize decompressor object */ +/*-----------------------------------------------------------------------*/ + +#define LDB_WORD(ptr) (uint16_t)(((uint16_t)*((uint8_t*)(ptr))<<8)|(uint16_t)*(uint8_t*)((ptr)+1)) + + +JRESULT jd_prepare( + JDEC * jd, /* Blank decompressor object */ + size_t (*infunc)(JDEC *, uint8_t *, size_t), /* JPEG strem input function */ + void * pool, /* Working buffer for the decompression session */ + size_t sz_pool, /* Size of working buffer */ + void * dev /* I/O device identifier for the session */ +) +{ + uint8_t * seg, b; + uint16_t marker; + unsigned int n, i, ofs; + size_t len; + JRESULT rc; + + + memset(jd, 0, sizeof( + JDEC)); /* Clear decompression object (this might be a problem if machine's null pointer is not all bits zero) */ + jd->pool = pool; /* Work memory */ + jd->pool_original = pool; + jd->sz_pool = sz_pool; /* Size of given work memory */ + jd->infunc = infunc; /* Stream input function */ + jd->device = dev; /* I/O device identifier */ + + jd->inbuf = seg = alloc_pool(jd, JD_SZBUF); /* Allocate stream input buffer */ + if(!seg) return JDR_MEM1; + + ofs = marker = 0; /* Find SOI marker */ + do { + if(jd->infunc(jd, seg, 1) != 1) return JDR_INP; /* Err: SOI was not detected */ + ofs++; + marker = marker << 8 | seg[0]; + } while(marker != 0xFFD8); + + for(;;) { /* Parse JPEG segments */ + /* Get a JPEG marker */ + if(jd->infunc(jd, seg, 4) != 4) return JDR_INP; + marker = LDB_WORD(seg); /* Marker */ + len = LDB_WORD(seg + 2); /* Length field */ + if(len <= 2 || (marker >> 8) != 0xFF) return JDR_FMT1; + len -= 2; /* Segent content size */ + ofs += 4 + len; /* Number of bytes loaded */ + + switch(marker & 0xFF) { + case 0xC0: /* SOF0 (baseline JPEG) */ + if(len > JD_SZBUF) return JDR_MEM2; + if(jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ + + jd->width = LDB_WORD(&seg[3]); /* Image width in unit of pixel */ + jd->height = LDB_WORD(&seg[1]); /* Image height in unit of pixel */ + jd->ncomp = seg[5]; /* Number of color components */ + if(jd->ncomp != 3 && jd->ncomp != 1) return JDR_FMT3; /* Err: Supports only Grayscale and Y/Cb/Cr */ + + /* Check each image component */ + for(i = 0; i < jd->ncomp; i++) { + b = seg[7 + 3 * i]; /* Get sampling factor */ + if(i == 0) { /* Y component */ + if(b != 0x11 && b != 0x22 && b != 0x21) { /* Check sampling factor */ + return JDR_FMT3; /* Err: Supports only 4:4:4, 4:2:0 or 4:2:2 */ + } + jd->msx = b >> 4; + jd->msy = b & 15; /* Size of MCU [blocks] */ + } + else { /* Cb/Cr component */ + if(b != 0x11) return JDR_FMT3; /* Err: Sampling factor of Cb/Cr must be 1 */ + } + jd->qtid[i] = seg[8 + 3 * i]; /* Get dequantizer table ID for this component */ + if(jd->qtid[i] > 3) return JDR_FMT3; /* Err: Invalid ID */ + } + break; + + case 0xDD: /* DRI - Define Restart Interval */ + if(len > JD_SZBUF) return JDR_MEM2; + if(jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ + + jd->nrst = LDB_WORD(seg); /* Get restart interval (MCUs) */ + break; + + case 0xC4: /* DHT - Define Huffman Tables */ + if(len > JD_SZBUF) return JDR_MEM2; + if(jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ + + rc = create_huffman_tbl(jd, seg, len); /* Create huffman tables */ + if(rc) return rc; + break; + + case 0xDB: /* DQT - Define Quaitizer Tables */ + if(len > JD_SZBUF) return JDR_MEM2; + if(jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ + + rc = create_qt_tbl(jd, seg, len); /* Create de-quantizer tables */ + if(rc) return rc; + break; + + case 0xDA: /* SOS - Start of Scan */ + if(len > JD_SZBUF) return JDR_MEM2; + if(jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */ + + if(!jd->width || !jd->height) return JDR_FMT1; /* Err: Invalid image size */ + if(seg[0] != jd->ncomp) return JDR_FMT3; /* Err: Wrong color components */ + + /* Check if all tables corresponding to each components have been loaded */ + for(i = 0; i < jd->ncomp; i++) { + b = seg[2 + 2 * i]; /* Get huffman table ID */ + if(b != 0x00 && b != 0x11) return JDR_FMT3; /* Err: Different table number for DC/AC element */ + n = i ? 1 : 0; /* Component class */ + if(!jd->huffbits[n][0] || !jd->huffbits[n][1]) { /* Check huffman table for this component */ + return JDR_FMT1; /* Err: Nnot loaded */ + } + if(!jd->qttbl[jd->qtid[i]]) { /* Check dequantizer table for this component */ + return JDR_FMT1; /* Err: Not loaded */ + } + } + + /* Allocate working buffer for MCU and pixel output */ + n = jd->msy * jd->msx; /* Number of Y blocks in the MCU */ + if(!n) return JDR_FMT1; /* Err: SOF0 has not been loaded */ + len = n * 64 * 2 + 64; /* Allocate buffer for IDCT and RGB output */ + if(len < 256) len = 256; /* but at least 256 byte is required for IDCT */ + jd->workbuf = alloc_pool(jd, + len); /* and it may occupy a part of following MCU working buffer for RGB output */ + if(!jd->workbuf) return JDR_MEM1; /* Err: not enough memory */ + jd->mcubuf = alloc_pool(jd, (n + 2) * 64 * sizeof(jd_yuv_t)); /* Allocate MCU working buffer */ + if(!jd->mcubuf) return JDR_MEM1; /* Err: not enough memory */ + + /* Align stream read offset to JD_SZBUF */ + if(ofs %= JD_SZBUF) { + jd->dctr = jd->infunc(jd, seg + ofs, (size_t)(JD_SZBUF - ofs)); + } + jd->dptr = seg + ofs - (JD_FASTDECODE ? 0 : 1); + + return JDR_OK; /* Initialization succeeded. Ready to decompress the JPEG image. */ + + case 0xC1: /* SOF1 */ + case 0xC2: /* SOF2 */ + case 0xC3: /* SOF3 */ + case 0xC5: /* SOF5 */ + case 0xC6: /* SOF6 */ + case 0xC7: /* SOF7 */ + case 0xC9: /* SOF9 */ + case 0xCA: /* SOF10 */ + case 0xCB: /* SOF11 */ + case 0xCD: /* SOF13 */ + case 0xCE: /* SOF14 */ + case 0xCF: /* SOF15 */ + case 0xD9: /* EOI */ + return JDR_FMT3; /* Unsuppoted JPEG standard (may be progressive JPEG) */ + + default: /* Unknown segment (comment, exif or etc..) */ + /* Skip segment data (null pointer specifies to remove data from the stream) */ + if(jd->infunc(jd, 0, len) != len) return JDR_INP; + } + } +} + + + + +/*-----------------------------------------------------------------------*/ +/* Start to decompress the JPEG picture */ +/*-----------------------------------------------------------------------*/ + +JRESULT jd_decomp( + JDEC * jd, /* Initialized decompression object */ + int (*outfunc)(JDEC *, void *, JRECT *), /* RGB output function */ + uint8_t scale /* Output de-scaling factor (0 to 3) */ +) +{ + unsigned int x, y, mx, my; + uint16_t rst, rsc; + JRESULT rc; + + + if(scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR; + jd->scale = scale; + + mx = jd->msx * 8; + my = jd->msy * 8; /* Size of the MCU (pixel) */ + + jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */ + rst = rsc = 0; + + rc = JDR_OK; + for(y = 0; y < jd->height; y += my) { /* Vertical loop of MCUs */ + for(x = 0; x < jd->width; x += mx) { /* Horizontal loop of MCUs */ + if(jd->nrst && rst++ == jd->nrst) { /* Process restart interval if enabled */ + rc = jd_restart(jd, rsc++); + if(rc != JDR_OK) return rc; + rst = 1; + } + rc = jd_mcu_load(jd); /* Load an MCU (decompress huffman coded stream, dequantize and apply IDCT) */ + if(rc != JDR_OK) return rc; + rc = jd_mcu_output(jd, outfunc, x, y); /* Output the MCU (YCbCr to RGB, scaling and output) */ + if(rc != JDR_OK) return rc; + } + } + + return rc; +} diff --git a/lib/libesp32_lvgl/lvgl/src/libs/tjpgd/tjpgd.h b/lib/libesp32_lvgl/lvgl/src/libs/tjpgd/tjpgd.h new file mode 100644 index 000000000..f1b578820 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/libs/tjpgd/tjpgd.h @@ -0,0 +1,103 @@ +/*----------------------------------------------------------------------------/ +/ TJpgDec - Tiny JPEG Decompressor R0.03 include file (C)ChaN, 2021 +/----------------------------------------------------------------------------*/ +#ifndef DEF_TJPGDEC +#define DEF_TJPGDEC + +#ifdef __cplusplus +extern "C" { +#endif + +#include "tjpgdcnf.h" +#include +#include + +#if JD_FASTDECODE >= 1 +typedef int16_t jd_yuv_t; +#else +typedef uint8_t jd_yuv_t; +#endif + + +/* Error code */ +typedef enum { + JDR_OK = 0, /* 0: Succeeded */ + JDR_INTR, /* 1: Interrupted by output function */ + JDR_INP, /* 2: Device error or wrong termination of input stream */ + JDR_MEM1, /* 3: Insufficient memory pool for the image */ + JDR_MEM2, /* 4: Insufficient stream input buffer */ + JDR_PAR, /* 5: Parameter error */ + JDR_FMT1, /* 6: Data format error (may be broken data) */ + JDR_FMT2, /* 7: Right format but not supported */ + JDR_FMT3 /* 8: Not supported JPEG standard */ +} JRESULT; + + + +/* Rectangular region in the output image */ +typedef struct { + uint16_t left; /* Left end */ + uint16_t right; /* Right end */ + uint16_t top; /* Top end */ + uint16_t bottom; /* Bottom end */ +} JRECT; + + + +/* Decompressor object structure */ +typedef struct JDEC JDEC; +struct JDEC { + size_t dctr; /* Number of bytes available in the input buffer */ + uint8_t * dptr; /* Current data read ptr */ + uint8_t * inbuf; /* Bit stream input buffer */ + uint8_t dbit; /* Number of bits available in wreg or reading bit mask */ + uint8_t scale; /* Output scaling ratio */ + uint8_t msx, msy; /* MCU size in unit of block (width, height) */ + uint8_t qtid[3]; /* Quantization table ID of each component, Y, Cb, Cr */ + uint8_t ncomp; /* Number of color components 1:grayscale, 3:color */ + int16_t dcv[3]; /* Previous DC element of each component */ + uint16_t nrst; /* Restart interval */ + uint16_t rst; /* Restart count*/ + uint16_t rsc; /* Expected restart sequence ID*/ + uint16_t width, height; /* Size of the input image (pixel) */ + uint8_t * huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ + uint16_t * huffcode[2][2]; /* Huffman code word tables [id][dcac] */ + uint8_t * huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ + int32_t * qttbl[4]; /* Dequantizer tables [id] */ +#if JD_FASTDECODE >= 1 + uint32_t wreg; /* Working shift register */ + uint8_t marker; /* Detected marker (0:None) */ +#if JD_FASTDECODE == 2 + uint8_t longofs[2][2]; /* Table offset of long code [id][dcac] */ + uint16_t * hufflut_ac[2]; /* Fast huffman decode tables for AC short code [id] */ + uint8_t * hufflut_dc[2]; /* Fast huffman decode tables for DC short code [id] */ +#endif +#endif + void * workbuf; /* Working buffer for IDCT and RGB output */ + jd_yuv_t * mcubuf; /* Working buffer for the MCU */ + void * pool; /* Pointer to available memory pool */ + void * pool_original; /* Pointer to original pool */ + size_t sz_pool; /* Size of memory pool (bytes available) */ + size_t (*infunc)(JDEC *, uint8_t *, size_t); /* Pointer to jpeg stream input function */ + void * device; /* Pointer to I/O device identifier for the session */ +}; + + + +/* TJpgDec API functions */ +JRESULT jd_prepare(JDEC * jd, size_t (*infunc)(JDEC *, uint8_t *, size_t), void * pool, size_t sz_pool, void * dev); + +JRESULT jd_decomp(JDEC * jd, int (*outfunc)(JDEC *, void *, JRECT *), uint8_t scale); + +JRESULT jd_mcu_load(JDEC * jd); + +JRESULT jd_mcu_output(JDEC * jd, int (*outfunc)(JDEC *, void *, JRECT *), unsigned int x, unsigned int y); + +JRESULT jd_restart(JDEC * jd, uint16_t rstn); + + +#ifdef __cplusplus +} +#endif + +#endif /* _TJPGDEC */ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgdcnf.h b/lib/libesp32_lvgl/lvgl/src/libs/tjpgd/tjpgdcnf.h similarity index 84% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgdcnf.h rename to lib/libesp32_lvgl/lvgl/src/libs/tjpgd/tjpgdcnf.h index 6d425e6f1..dc27d6a95 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/sjpg/tjpgdcnf.h +++ b/lib/libesp32_lvgl/lvgl/src/libs/tjpgd/tjpgdcnf.h @@ -2,29 +2,29 @@ /* TJpgDec System Configurations R0.03 */ /*----------------------------------------------*/ -#define JD_SZBUF 512 +#define JD_SZBUF 512 /* Specifies size of stream input buffer */ -#define JD_FORMAT 0 +#define JD_FORMAT 0 /* Specifies output pixel format. / 0: RGB888 (24-bit/pix) / 1: RGB565 (16-bit/pix) / 2: Grayscale (8-bit/pix) */ -#define JD_USE_SCALE 1 +#define JD_USE_SCALE 0 /* Switches output descaling feature. / 0: Disable / 1: Enable */ -#define JD_TBLCLIP 1 +#define JD_TBLCLIP 1 /* Use table conversion for saturation arithmetic. A bit faster, but increases 1 KB of code size. / 0: Disable / 1: Enable */ -#define JD_FASTDECODE 0 +#define JD_FASTDECODE 1 /* Optimization level / 0: Basic optimization. Suitable for 8/16-bit MCUs. / 1: + 32-bit barrel shifter. Suitable for 32-bit MCUs. diff --git a/lib/libesp32_lvgl/lvgl/src/lv_api_map.h b/lib/libesp32_lvgl/lvgl/src/lv_api_map.h index f2b640a4a..b69504a4f 100644 --- a/lib/libesp32_lvgl/lvgl/src/lv_api_map.h +++ b/lib/libesp32_lvgl/lvgl/src/lv_api_map.h @@ -19,14 +19,37 @@ extern "C" { * DEFINES *********************/ -#define LV_NO_TASK_READY LV_NO_TIMER_READY -#define LV_INDEV_STATE_REL LV_INDEV_STATE_RELEASED -#define LV_INDEV_STATE_PR LV_INDEV_STATE_PRESSED -#define LV_OBJ_FLAG_SNAPABLE LV_OBJ_FLAG_SNAPPABLE /*Fixed typo*/ +#define LV_DISP_ROTATION_0 LV_DISPLAY_ROTATION_0 +#define LV_DISP_ROTATION_90 LV_DISPLAY_ROTATION_90 +#define LV_DISP_ROTATION_180 LV_DISPLAY_ROTATION_180 +#define LV_DISP_ROTATION_270 LV_DISPLAY_ROTATION_270 + +#define LV_DISP_RENDER_MODE_PARTIAL LV_DISPLAY_RENDER_MODE_PARTIAL +#define LV_DISP_RENDER_MODE_DIRECT LV_DISPLAY_RENDER_MODE_DIRECT +#define LV_DISP_RENDER_MODE_FULL LV_DISPLAY_RENDER_MODE_FULL + +#define LV_BTNMATRIX_BTN_NONE LV_BUTTONMATRIX_BUTTON_NONE + +#define LV_BTNMATRIX_CTRL_HIDDEN LV_BUTTONMATRIX_CTRL_HIDDEN +#define LV_BTNMATRIX_CTRL_NO_REPEAT LV_BUTTONMATRIX_CTRL_NO_REPEAT +#define LV_BTNMATRIX_CTRL_DISABLED LV_BUTTONMATRIX_CTRL_DISABLED +#define LV_BTNMATRIX_CTRL_CHECKABLE LV_BUTTONMATRIX_CTRL_CHECKABLE +#define LV_BTNMATRIX_CTRL_CHECKED LV_BUTTONMATRIX_CTRL_CHECKED +#define LV_BTNMATRIX_CTRL_CLICK_TRIG LV_BUTTONMATRIX_CTRL_CLICK_TRIG +#define LV_BTNMATRIX_CTRL_POPOVER LV_BUTTONMATRIX_CTRL_POPOVER +#define LV_BTNMATRIX_CTRL_CUSTOM_1 LV_BUTTONMATRIX_CTRL_CUSTOM_1 +#define LV_BTNMATRIX_CTRL_CUSTOM_2 LV_BUTTONMATRIX_CTRL_CUSTOM_2 /********************** * TYPEDEFS **********************/ +typedef int32_t lv_coord_t; +typedef lv_result_t lv_res_t; +typedef lv_image_dsc_t lv_img_dsc_t; +typedef lv_display_t lv_disp_t; +typedef lv_display_rotation_t lv_disp_rotation_t; +typedef lv_display_render_mode_t lv_disp_render_t; +typedef lv_anim_completed_cb_t lv_anim_ready_cb_t; /********************** * GLOBAL PROTOTYPES @@ -37,15 +60,6 @@ static inline LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_task_handler(void) return lv_timer_handler(); } -/********************** - * MACROS - **********************/ - - -/********************** - * INLINE FUNCTIONS - **********************/ - /** * Move the object to the foreground. * It will look like if it was created as the last child of its parent. @@ -55,7 +69,12 @@ static inline LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_task_handler(void) static inline void lv_obj_move_foreground(lv_obj_t * obj) { lv_obj_t * parent = lv_obj_get_parent(obj); - lv_obj_move_to_index(obj, lv_obj_get_child_cnt(parent) - 1); + if(!parent) { + LV_LOG_WARN("parent is NULL"); + return; + } + + lv_obj_move_to_index(obj, lv_obj_get_child_count(parent) - 1); } /** @@ -69,18 +88,177 @@ static inline void lv_obj_move_background(lv_obj_t * obj) lv_obj_move_to_index(obj, 0); } +/********************** + * MACROS + **********************/ +#define LV_RES_OK LV_RESULT_OK +#define LV_RES_INV LV_RESULT_INVALID +#define LV_INDEV_STATE_PR LV_INDEV_STATE_PRESSED +#define LV_INDEV_STATE_REL LV_INDEV_STATE_RELEASED + +#define lv_obj_del lv_obj_delete +#define lv_obj_del_async lv_obj_delete_async +#define lv_obj_clear_flag lv_obj_remove_flag +#define lv_obj_clear_state lv_obj_remove_state + +#define lv_indev_set_disp lv_indev_set_display +#define lv_indev_get_act lv_indev_active +#define lv_scr_act lv_screen_active +#define lv_disp_remove lv_display_delete +#define lv_disp_set_default lv_display_set_default +#define lv_disp_get_default lv_display_get_default +#define lv_disp_get_next lv_display_get_next +#define lv_disp_set_rotation lv_display_set_rotation +#define lv_disp_get_hor_res lv_display_get_horizontal_resolution +#define lv_disp_get_ver_res lv_display_get_vertical_resolution +#define lv_disp_get_physical_hor_res lv_display_get_physical_horizontal_resolution +#define lv_disp_get_physical_ver_res lv_display_get_physical_vertical_resolution +#define lv_disp_get_offset_x lv_display_get_offset_x +#define lv_disp_get_offset_y lv_display_get_offset_y +#define lv_disp_get_rotation lv_display_get_rotation +#define lv_disp_get_dpi lv_display_get_dpi +#define lv_disp_get_antialiasing lv_display_get_antialiasing +#define lv_disp_flush_ready lv_display_flush_ready +#define lv_disp_flush_is_last lv_display_flush_is_last +#define lv_disp_get_scr_act lv_display_get_screen_active +#define lv_disp_get_scr_prev lv_display_get_screen_prev +#define lv_disp_load_scr lv_screen_load +#define lv_disp_get_layer_top lv_display_get_layer_top +#define lv_disp_get_layer_sys lv_display_get_layer_sys +#define lv_disp_send_event lv_display_send_event +#define lv_disp_set_theme lv_display_set_theme +#define lv_disp_get_theme lv_display_get_theme +#define lv_disp_get_inactive_time lv_display_get_inactive_time +#define lv_disp_trig_activity lv_display_trigger_activity +#define lv_disp_enable_invalidation lv_display_enable_invalidation +#define lv_disp_is_invalidation_enabled lv_display_is_invalidation_enabled +#define _lv_disp_refr_timer _lv_display_refr_timer +#define _lv_disp_get_refr_timer lv_display_get_refr_timer + +#define lv_timer_del lv_timer_delete + +#define lv_anim_del lv_anim_delete +#define lv_anim_del_all lv_anim_delete_all +#define lv_anim_set_ready_cb lv_anim_set_completed_cb + +#define lv_group_del lv_group_delete + +#define lv_txt_get_size lv_text_get_size +#define lv_txt_get_width lv_text_get_width + +#define lv_img_create lv_image_create +#define lv_img_set_src lv_image_set_src +#define lv_img_set_offset_x lv_image_set_offset_x +#define lv_img_set_offset_y lv_image_set_offset_y +#define lv_img_set_angle lv_image_set_rotation +#define lv_img_set_pivot lv_image_set_pivot +#define lv_img_set_zoom lv_image_set_scale +#define lv_img_set_antialias lv_image_set_antialias +#define lv_img_get_src lv_image_get_src +#define lv_img_get_offset_x lv_image_get_offset_x +#define lv_img_get_offset_y lv_image_get_offset_y +#define lv_img_get_angle lv_image_get_rotation +#define lv_img_get_pivot lv_image_get_pivot +#define lv_img_get_zoom lv_image_get_scale +#define lv_img_get_antialias lv_image_get_antialias + +#define lv_list_set_btn_text lv_list_set_button_text +#define lv_list_get_btn_text lv_list_get_button_text +#define lv_list_add_btn lv_list_add_button + +#define lv_btn_create lv_button_create + +#define lv_btnmatrix_create lv_buttonmatrix_create +#define lv_btnmatrix_set_map lv_buttonmatrix_set_map +#define lv_btnmatrix_set_ctrl_map lv_buttonmatrix_set_ctrl_map +#define lv_btnmatrix_set_selected_btn lv_buttonmatrix_set_selected_button +#define lv_btnmatrix_set_btn_ctrl lv_buttonmatrix_set_button_ctrl +#define lv_btnmatrix_clear_btn_ctrl lv_buttonmatrix_clear_button_ctrl +#define lv_btnmatrix_set_btn_ctrl_all lv_buttonmatrix_set_button_ctrl_all +#define lv_btnmatrix_clear_btn_ctrl_all lv_buttonmatrix_clear_button_ctrl_all +#define lv_btnmatrix_set_btn_width lv_buttonmatrix_set_button_width +#define lv_btnmatrix_set_one_checked lv_buttonmatrix_set_one_checked +#define lv_btnmatrix_get_map lv_buttonmatrix_get_map +#define lv_btnmatrix_get_selected_btn lv_buttonmatrix_get_selected_button +#define lv_btnmatrix_get_button_text lv_buttonmatrix_get_button_text +#define lv_btnmatrix_has_button_ctrl lv_buttonmatrix_has_button_ctrl +#define lv_btnmatrix_get_one_checked lv_buttonmatrix_get_one_checked + +#define lv_tabview_get_tab_btns lv_tabview_get_tab_bar +#define lv_tabview_get_tab_act lv_tabview_get_tab_active +#define lv_tabview_set_act lv_tabview_set_active + +#define lv_tileview_get_tile_act lv_tileview_get_tile_active +#define lv_obj_set_tile_id lv_tileview_set_tile_by_index +#define lv_obj_set_tile lv_tileview_set_tile + +#define lv_roller_set_visible_row_cnt lv_roller_set_visible_row_count +#define lv_roller_get_option_cnt lv_roller_get_option_count + +#define lv_table_set_col_cnt lv_table_set_column_count +#define lv_table_set_row_cnt lv_table_set_row_count +#define lv_table_get_col_cnt lv_table_get_column_count +#define lv_table_get_row_cnt lv_table_get_row_count +#define lv_table_set_col_width lv_table_set_column_width +#define lv_table_get_col_width lv_table_get_column_width + +#define lv_dropdown_get_option_cnt lv_dropdown_get_option_count + +#define lv_obj_get_child_cnt lv_obj_get_child_count +#define lv_obj_get_disp lv_obj_get_display +#define lv_obj_delete_anim_ready_cb lv_obj_delete_anim_completed_cb + +#define LV_STYLE_ANIM_TIME LV_STYLE_ANIM_DURATION +#define LV_STYLE_IMG_OPA LV_STYLE_IMAGE_OPA +#define LV_STYLE_IMG_RECOLOR LV_STYLE_IMAGE_RECOLOR +#define LV_STYLE_IMG_RECOLOR_OPA LV_STYLE_IMAGE_RECOLOR_OPA +#define LV_STYLE_SHADOW_OFS_X LV_STYLE_SHADOW_OFFSET_X +#define LV_STYLE_SHADOW_OFS_Y LV_STYLE_SHADOW_OFFSET_Y +#define LV_STYLE_TRANSFORM_ANGLE LV_STYLE_TRANSFORM_ROTATION + +#define lv_obj_get_style_anim_time lv_obj_get_style_anim_duration +#define lv_obj_get_style_img_opa lv_obj_get_style_image_opa +#define lv_obj_get_style_img_recolor lv_obj_get_style_image_recolor +#define lv_obj_get_style_img_recolor_filtered lv_obj_get_style_image_recolor_filtered +#define lv_obj_get_style_img_recolor_opa lv_obj_get_style_image_recolor_opa +#define lv_obj_get_style_shadow_ofs_x lv_obj_get_style_shadow_offset_x +#define lv_obj_get_style_shadow_ofs_y lv_obj_get_style_shadow_offset_y +#define lv_obj_get_style_transform_angle lv_obj_get_style_transform_rotation + +#define lv_obj_set_style_anim_time lv_obj_set_style_anim_duration +#define lv_obj_set_style_img_opa lv_obj_set_style_image_opa +#define lv_obj_set_style_img_recolor lv_obj_set_style_image_recolor +#define lv_obj_set_style_img_recolor_opa lv_obj_set_style_image_recolor_opa +#define lv_obj_set_style_shadow_ofs_x lv_obj_set_style_shadow_offset_x +#define lv_obj_set_style_shadow_ofs_y lv_obj_set_style_shadow_offset_y +#define lv_obj_set_style_transform_zoom lv_obj_set_style_transform_scale +#define lv_obj_set_style_transform_angle lv_obj_set_style_transform_rotation + +#define lv_style_set_anim_time lv_style_set_anim_duration +#define lv_style_set_img_opa lv_style_set_image_opa +#define lv_style_set_img_recolor lv_style_set_image_recolor +#define lv_style_set_img_recolor_opa lv_style_set_image_recolor_opa +#define lv_style_set_shadow_ofs_x lv_style_set_shadow_offset_x +#define lv_style_set_shadow_ofs_y lv_style_set_shadow_offset_y +#define lv_style_set_transform_angle lv_style_set_transform_rotation +#define lv_style_set_transform_zoom lv_style_set_transform_scale + +#define LV_ZOOM_NONE LV_SCALE_NONE + +#define lv_image_decoder_built_in_open lv_bin_decoder_open +#define lv_image_decoder_built_in_close lv_bin_decoder_close + +/********************** + * MACROS + **********************/ +/** Use this macro to declare an image in a C file*/ +#define LV_IMG_DECLARE(var_name) extern const lv_image_dsc_t var_name; /********************** * DEPRECATED FUNCTIONS **********************/ -static inline uint32_t lv_obj_get_child_id(const struct _lv_obj_t * obj) -{ - LV_LOG_WARN("lv_obj_get_child_id(obj) is deprecated, please use lv_obj_get_index(obj)."); - return lv_obj_get_index(obj); -} - #ifdef __cplusplus } /*extern "C"*/ #endif diff --git a/lib/libesp32_lvgl/lvgl/src/lv_conf_internal.h b/lib/libesp32_lvgl/lvgl/src/lv_conf_internal.h index 0c297081c..2fff711cf 100644 --- a/lib/libesp32_lvgl/lvgl/src/lv_conf_internal.h +++ b/lib/libesp32_lvgl/lvgl/src/lv_conf_internal.h @@ -8,7 +8,25 @@ #define LV_CONF_INTERNAL_H /* clang-format off */ -#include +/*Config options*/ +#define LV_OS_NONE 0 +#define LV_OS_PTHREAD 1 +#define LV_OS_FREERTOS 2 +#define LV_OS_CMSIS_RTOS2 3 +#define LV_OS_RTTHREAD 4 +#define LV_OS_WINDOWS 5 +#define LV_OS_CUSTOM 255 + +#define LV_STDLIB_BUILTIN 0 +#define LV_STDLIB_CLIB 1 +#define LV_STDLIB_MICROPYTHON 2 +#define LV_STDLIB_RTTHREAD 3 +#define LV_STDLIB_CUSTOM 255 + +#define LV_DRAW_SW_ASM_NONE 0 +#define LV_DRAW_SW_ASM_NEON 1 +#define LV_DRAW_SW_ASM_HELIUM 2 +#define LV_DRAW_SW_ASM_CUSTOM 255 /* Handle special Kconfig options */ #ifndef LV_KCONFIG_IGNORE @@ -55,13 +73,11 @@ * Start parsing lv_conf_template.h -----------------------------------*/ -#include - /*==================== COLOR SETTINGS *====================*/ -/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/ +/*Color depth: 8 (A8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/ #ifndef LV_COLOR_DEPTH #ifdef CONFIG_LV_COLOR_DEPTH #define LV_COLOR_DEPTH CONFIG_LV_COLOR_DEPTH @@ -70,64 +86,56 @@ #endif #endif -/*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/ -#ifndef LV_COLOR_16_SWAP - #ifdef CONFIG_LV_COLOR_16_SWAP - #define LV_COLOR_16_SWAP CONFIG_LV_COLOR_16_SWAP - #else - #define LV_COLOR_16_SWAP 0 - #endif -#endif - -/*Enable features to draw on transparent background. - *It's required if opa, and transform_* style properties are used. - *Can be also used if the UI is above another layer, e.g. an OSD menu or video player.*/ -#ifndef LV_COLOR_SCREEN_TRANSP - #ifdef CONFIG_LV_COLOR_SCREEN_TRANSP - #define LV_COLOR_SCREEN_TRANSP CONFIG_LV_COLOR_SCREEN_TRANSP - #else - #define LV_COLOR_SCREEN_TRANSP 0 - #endif -#endif - -/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. - * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */ -#ifndef LV_COLOR_MIX_ROUND_OFS - #ifdef CONFIG_LV_COLOR_MIX_ROUND_OFS - #define LV_COLOR_MIX_ROUND_OFS CONFIG_LV_COLOR_MIX_ROUND_OFS - #else - #define LV_COLOR_MIX_ROUND_OFS 0 - #endif -#endif - -/*Images pixels with this color will not be drawn if they are chroma keyed)*/ -#ifndef LV_COLOR_CHROMA_KEY - #ifdef CONFIG_LV_COLOR_CHROMA_KEY - #define LV_COLOR_CHROMA_KEY CONFIG_LV_COLOR_CHROMA_KEY - #else - #define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/ - #endif -#endif - /*========================= - MEMORY SETTINGS + STDLIB WRAPPER SETTINGS *=========================*/ -/*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/ -#ifndef LV_MEM_CUSTOM - #ifdef CONFIG_LV_MEM_CUSTOM - #define LV_MEM_CUSTOM CONFIG_LV_MEM_CUSTOM +/* Possible values + * - LV_STDLIB_BUILTIN: LVGL's built in implementation + * - LV_STDLIB_CLIB: Standard C functions, like malloc, strlen, etc + * - LV_STDLIB_MICROPYTHON: MicroPython implementation + * - LV_STDLIB_RTTHREAD: RT-Thread implementation + * - LV_STDLIB_CUSTOM: Implement the functions externally + */ +#ifndef LV_USE_STDLIB_MALLOC + #ifdef CONFIG_LV_USE_STDLIB_MALLOC + #define LV_USE_STDLIB_MALLOC CONFIG_LV_USE_STDLIB_MALLOC #else - #define LV_MEM_CUSTOM 0 + #define LV_USE_STDLIB_MALLOC LV_STDLIB_BUILTIN #endif #endif -#if LV_MEM_CUSTOM == 0 - /*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/ +#ifndef LV_USE_STDLIB_STRING + #ifdef CONFIG_LV_USE_STDLIB_STRING + #define LV_USE_STDLIB_STRING CONFIG_LV_USE_STDLIB_STRING + #else + #define LV_USE_STDLIB_STRING LV_STDLIB_BUILTIN + #endif +#endif +#ifndef LV_USE_STDLIB_SPRINTF + #ifdef CONFIG_LV_USE_STDLIB_SPRINTF + #define LV_USE_STDLIB_SPRINTF CONFIG_LV_USE_STDLIB_SPRINTF + #else + #define LV_USE_STDLIB_SPRINTF LV_STDLIB_BUILTIN + #endif +#endif + + +#if LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN + /*Size of the memory available for `lv_malloc()` in bytes (>= 2kB)*/ #ifndef LV_MEM_SIZE #ifdef CONFIG_LV_MEM_SIZE #define LV_MEM_SIZE CONFIG_LV_MEM_SIZE #else - #define LV_MEM_SIZE (48U * 1024U) /*[bytes]*/ + #define LV_MEM_SIZE (64 * 1024U) /*[bytes]*/ + #endif + #endif + + /*Size of the memory expand for `lv_malloc()` in bytes*/ + #ifndef LV_MEM_POOL_EXPAND_SIZE + #ifdef CONFIG_LV_MEM_POOL_EXPAND_SIZE + #define LV_MEM_POOL_EXPAND_SIZE CONFIG_LV_MEM_POOL_EXPAND_SIZE + #else + #define LV_MEM_POOL_EXPAND_SIZE 0 #endif #endif @@ -156,108 +164,21 @@ #endif #endif #endif - -#else /*LV_MEM_CUSTOM*/ - #ifndef LV_MEM_CUSTOM_INCLUDE - #ifdef CONFIG_LV_MEM_CUSTOM_INCLUDE - #define LV_MEM_CUSTOM_INCLUDE CONFIG_LV_MEM_CUSTOM_INCLUDE - #else - #define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ - #endif - #endif - #ifndef LV_MEM_CUSTOM_ALLOC - #ifdef CONFIG_LV_MEM_CUSTOM_ALLOC - #define LV_MEM_CUSTOM_ALLOC CONFIG_LV_MEM_CUSTOM_ALLOC - #else - #define LV_MEM_CUSTOM_ALLOC malloc - #endif - #endif - #ifndef LV_MEM_CUSTOM_FREE - #ifdef CONFIG_LV_MEM_CUSTOM_FREE - #define LV_MEM_CUSTOM_FREE CONFIG_LV_MEM_CUSTOM_FREE - #else - #define LV_MEM_CUSTOM_FREE free - #endif - #endif - #ifndef LV_MEM_CUSTOM_REALLOC - #ifdef CONFIG_LV_MEM_CUSTOM_REALLOC - #define LV_MEM_CUSTOM_REALLOC CONFIG_LV_MEM_CUSTOM_REALLOC - #else - #define LV_MEM_CUSTOM_REALLOC realloc - #endif - #endif -#endif /*LV_MEM_CUSTOM*/ - -/*Number of the intermediate memory buffer used during rendering and other internal processing mechanisms. - *You will see an error log message if there wasn't enough buffers. */ -#ifndef LV_MEM_BUF_MAX_NUM - #ifdef CONFIG_LV_MEM_BUF_MAX_NUM - #define LV_MEM_BUF_MAX_NUM CONFIG_LV_MEM_BUF_MAX_NUM - #else - #define LV_MEM_BUF_MAX_NUM 16 - #endif -#endif - -/*Use the standard `memcpy` and `memset` instead of LVGL's own functions. (Might or might not be faster).*/ -#ifndef LV_MEMCPY_MEMSET_STD - #ifdef CONFIG_LV_MEMCPY_MEMSET_STD - #define LV_MEMCPY_MEMSET_STD CONFIG_LV_MEMCPY_MEMSET_STD - #else - #define LV_MEMCPY_MEMSET_STD 0 - #endif -#endif +#endif /*LV_USE_MALLOC == LV_STDLIB_BUILTIN*/ /*==================== HAL SETTINGS *====================*/ -/*Default display refresh period. LVG will redraw changed areas with this period time*/ -#ifndef LV_DISP_DEF_REFR_PERIOD - #ifdef CONFIG_LV_DISP_DEF_REFR_PERIOD - #define LV_DISP_DEF_REFR_PERIOD CONFIG_LV_DISP_DEF_REFR_PERIOD +/*Default display refresh, input device read and animation step period.*/ +#ifndef LV_DEF_REFR_PERIOD + #ifdef CONFIG_LV_DEF_REFR_PERIOD + #define LV_DEF_REFR_PERIOD CONFIG_LV_DEF_REFR_PERIOD #else - #define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ + #define LV_DEF_REFR_PERIOD 33 /*[ms]*/ #endif #endif -/*Input device read period in milliseconds*/ -#ifndef LV_INDEV_DEF_READ_PERIOD - #ifdef CONFIG_LV_INDEV_DEF_READ_PERIOD - #define LV_INDEV_DEF_READ_PERIOD CONFIG_LV_INDEV_DEF_READ_PERIOD - #else - #define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/ - #endif -#endif - -/*Use a custom tick source that tells the elapsed time in milliseconds. - *It removes the need to manually update the tick with `lv_tick_inc()`)*/ -#ifndef LV_TICK_CUSTOM - #ifdef CONFIG_LV_TICK_CUSTOM - #define LV_TICK_CUSTOM CONFIG_LV_TICK_CUSTOM - #else - #define LV_TICK_CUSTOM 0 - #endif -#endif -#if LV_TICK_CUSTOM - #ifndef LV_TICK_CUSTOM_INCLUDE - #ifdef CONFIG_LV_TICK_CUSTOM_INCLUDE - #define LV_TICK_CUSTOM_INCLUDE CONFIG_LV_TICK_CUSTOM_INCLUDE - #else - #define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ - #endif - #endif - #ifndef LV_TICK_CUSTOM_SYS_TIME_EXPR - #ifdef CONFIG_LV_TICK_CUSTOM_SYS_TIME_EXPR - #define LV_TICK_CUSTOM_SYS_TIME_EXPR CONFIG_LV_TICK_CUSTOM_SYS_TIME_EXPR - #else - #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ - #endif - #endif - /*If using lvgl as ESP32 component*/ - // #define LV_TICK_CUSTOM_INCLUDE "esp_timer.h" - // #define LV_TICK_CUSTOM_SYS_TIME_EXPR ((esp_timer_get_time() / 1000LL)) -#endif /*LV_TICK_CUSTOM*/ - /*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings. *(Not so important, you can adjust it to modify default sizes and spaces)*/ #ifndef LV_DPI_DEF @@ -268,287 +189,285 @@ #endif #endif +/*================= + * OPERATING SYSTEM + *=================*/ +/*Select an operating system to use. Possible options: + * - LV_OS_NONE + * - LV_OS_PTHREAD + * - LV_OS_FREERTOS + * - LV_OS_CMSIS_RTOS2 + * - LV_OS_RTTHREAD + * - LV_OS_WINDOWS + * - LV_OS_CUSTOM */ +#ifndef LV_USE_OS + #ifdef CONFIG_LV_USE_OS + #define LV_USE_OS CONFIG_LV_USE_OS + #else + #define LV_USE_OS LV_OS_NONE + #endif +#endif + +#if LV_USE_OS == LV_OS_CUSTOM + #ifndef LV_OS_CUSTOM_INCLUDE + #ifdef CONFIG_LV_OS_CUSTOM_INCLUDE + #define LV_OS_CUSTOM_INCLUDE CONFIG_LV_OS_CUSTOM_INCLUDE + #else + #define LV_OS_CUSTOM_INCLUDE + #endif + #endif +#endif + +/*======================== + * RENDERING CONFIGURATION + *========================*/ + +/*Align the stride of all layers and images to this bytes*/ +#ifndef LV_DRAW_BUF_STRIDE_ALIGN + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_DRAW_BUF_STRIDE_ALIGN + #define LV_DRAW_BUF_STRIDE_ALIGN CONFIG_LV_DRAW_BUF_STRIDE_ALIGN + #else + #define LV_DRAW_BUF_STRIDE_ALIGN 0 + #endif + #else + #define LV_DRAW_BUF_STRIDE_ALIGN 1 + #endif +#endif + +/*Align the start address of draw_buf addresses to this bytes*/ +#ifndef LV_DRAW_BUF_ALIGN + #ifdef CONFIG_LV_DRAW_BUF_ALIGN + #define LV_DRAW_BUF_ALIGN CONFIG_LV_DRAW_BUF_ALIGN + #else + #define LV_DRAW_BUF_ALIGN 4 + #endif +#endif + +#ifndef LV_USE_DRAW_SW + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_DRAW_SW + #define LV_USE_DRAW_SW CONFIG_LV_USE_DRAW_SW + #else + #define LV_USE_DRAW_SW 0 + #endif + #else + #define LV_USE_DRAW_SW 1 + #endif +#endif +#if LV_USE_DRAW_SW == 1 + /* Set the number of draw unit. + * > 1 requires an operating system enabled in `LV_USE_OS` + * > 1 means multiply threads will render the screen in parallel */ + #ifndef LV_DRAW_SW_DRAW_UNIT_CNT + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_DRAW_SW_DRAW_UNIT_CNT + #define LV_DRAW_SW_DRAW_UNIT_CNT CONFIG_LV_DRAW_SW_DRAW_UNIT_CNT + #else + #define LV_DRAW_SW_DRAW_UNIT_CNT 0 + #endif + #else + #define LV_DRAW_SW_DRAW_UNIT_CNT 1 + #endif + #endif + + /* Use Arm-2D to accelerate the sw render */ + #ifndef LV_USE_DRAW_ARM2D_SYNC + #ifdef CONFIG_LV_USE_DRAW_ARM2D_SYNC + #define LV_USE_DRAW_ARM2D_SYNC CONFIG_LV_USE_DRAW_ARM2D_SYNC + #else + #define LV_USE_DRAW_ARM2D_SYNC 0 + #endif + #endif + + /* If a widget has `style_opa < 255` (not `bg_opa`, `text_opa` etc) or not NORMAL blend mode + * it is buffered into a "simple" layer before rendering. The widget can be buffered in smaller chunks. + * "Transformed layers" (if `transform_angle/zoom` are set) use larger buffers + * and can't be drawn in chunks. */ + + /*The target buffer size for simple layer chunks.*/ + #ifndef LV_DRAW_SW_LAYER_SIMPLE_BUF_SIZE + #ifdef CONFIG_LV_DRAW_SW_LAYER_SIMPLE_BUF_SIZE + #define LV_DRAW_SW_LAYER_SIMPLE_BUF_SIZE CONFIG_LV_DRAW_SW_LAYER_SIMPLE_BUF_SIZE + #else + #define LV_DRAW_SW_LAYER_SIMPLE_BUF_SIZE (24 * 1024) /*[bytes]*/ + #endif + #endif + + /* 0: use a simple renderer capable of drawing only simple rectangles with gradient, images, texts, and straight lines only + * 1: use a complex renderer capable of drawing rounded corners, shadow, skew lines, and arcs too */ + #ifndef LV_DRAW_SW_COMPLEX + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_DRAW_SW_COMPLEX + #define LV_DRAW_SW_COMPLEX CONFIG_LV_DRAW_SW_COMPLEX + #else + #define LV_DRAW_SW_COMPLEX 0 + #endif + #else + #define LV_DRAW_SW_COMPLEX 1 + #endif + #endif + + #if LV_DRAW_SW_COMPLEX == 1 + /*Allow buffering some shadow calculation. + *LV_DRAW_SW_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius` + *Caching has LV_DRAW_SW_SHADOW_CACHE_SIZE^2 RAM cost*/ + #ifndef LV_DRAW_SW_SHADOW_CACHE_SIZE + #ifdef CONFIG_LV_DRAW_SW_SHADOW_CACHE_SIZE + #define LV_DRAW_SW_SHADOW_CACHE_SIZE CONFIG_LV_DRAW_SW_SHADOW_CACHE_SIZE + #else + #define LV_DRAW_SW_SHADOW_CACHE_SIZE 0 + #endif + #endif + + /* Set number of maximally cached circle data. + * The circumference of 1/4 circle are saved for anti-aliasing + * radius * 4 bytes are used per circle (the most often used radiuses are saved) + * 0: to disable caching */ + #ifndef LV_DRAW_SW_CIRCLE_CACHE_SIZE + #ifdef CONFIG_LV_DRAW_SW_CIRCLE_CACHE_SIZE + #define LV_DRAW_SW_CIRCLE_CACHE_SIZE CONFIG_LV_DRAW_SW_CIRCLE_CACHE_SIZE + #else + #define LV_DRAW_SW_CIRCLE_CACHE_SIZE 4 + #endif + #endif + #endif + + #ifndef LV_USE_DRAW_SW_ASM + #ifdef CONFIG_LV_USE_DRAW_SW_ASM + #define LV_USE_DRAW_SW_ASM CONFIG_LV_USE_DRAW_SW_ASM + #else + #define LV_USE_DRAW_SW_ASM LV_DRAW_SW_ASM_NONE + #endif + #endif + + #if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_CUSTOM + #ifndef LV_DRAW_SW_ASM_CUSTOM_INCLUDE + #ifdef CONFIG_LV_DRAW_SW_ASM_CUSTOM_INCLUDE + #define LV_DRAW_SW_ASM_CUSTOM_INCLUDE CONFIG_LV_DRAW_SW_ASM_CUSTOM_INCLUDE + #else + #define LV_DRAW_SW_ASM_CUSTOM_INCLUDE "" + #endif + #endif + #endif +#endif + +/* Use NXP's VG-Lite GPU on iMX RTxxx platforms. */ +#ifndef LV_USE_DRAW_VGLITE + #ifdef CONFIG_LV_USE_DRAW_VGLITE + #define LV_USE_DRAW_VGLITE CONFIG_LV_USE_DRAW_VGLITE + #else + #define LV_USE_DRAW_VGLITE 0 + #endif +#endif + +#if LV_USE_DRAW_VGLITE + /* Enable blit quality degradation workaround recommended for screen's dimension > 352 pixels. */ + #ifndef LV_USE_VGLITE_BLIT_SPLIT + #ifdef CONFIG_LV_USE_VGLITE_BLIT_SPLIT + #define LV_USE_VGLITE_BLIT_SPLIT CONFIG_LV_USE_VGLITE_BLIT_SPLIT + #else + #define LV_USE_VGLITE_BLIT_SPLIT 0 + #endif + #endif + + #if LV_USE_OS + /* Enable VGLite draw async. Queue multiple tasks and flash them once to the GPU. */ + #ifndef LV_USE_VGLITE_DRAW_ASYNC + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_VGLITE_DRAW_ASYNC + #define LV_USE_VGLITE_DRAW_ASYNC CONFIG_LV_USE_VGLITE_DRAW_ASYNC + #else + #define LV_USE_VGLITE_DRAW_ASYNC 0 + #endif + #else + #define LV_USE_VGLITE_DRAW_ASYNC 1 + #endif + #endif + #endif + + /* Enable VGLite asserts. */ + #ifndef LV_USE_VGLITE_ASSERT + #ifdef CONFIG_LV_USE_VGLITE_ASSERT + #define LV_USE_VGLITE_ASSERT CONFIG_LV_USE_VGLITE_ASSERT + #else + #define LV_USE_VGLITE_ASSERT 0 + #endif + #endif +#endif + +/* Use NXP's PXP on iMX RTxxx platforms. */ +#ifndef LV_USE_DRAW_PXP + #ifdef CONFIG_LV_USE_DRAW_PXP + #define LV_USE_DRAW_PXP CONFIG_LV_USE_DRAW_PXP + #else + #define LV_USE_DRAW_PXP 0 + #endif +#endif + +#if LV_USE_DRAW_PXP + /* Enable PXP asserts. */ + #ifndef LV_USE_PXP_ASSERT + #ifdef CONFIG_LV_USE_PXP_ASSERT + #define LV_USE_PXP_ASSERT CONFIG_LV_USE_PXP_ASSERT + #else + #define LV_USE_PXP_ASSERT 0 + #endif + #endif +#endif + +/* Use Renesas Dave2D on RA platforms. */ +#ifndef LV_USE_DRAW_DAVE2D + #ifdef CONFIG_LV_USE_DRAW_DAVE2D + #define LV_USE_DRAW_DAVE2D CONFIG_LV_USE_DRAW_DAVE2D + #else + #define LV_USE_DRAW_DAVE2D 0 + #endif +#endif + +/* Draw using cached SDL textures*/ +#ifndef LV_USE_DRAW_SDL + #ifdef CONFIG_LV_USE_DRAW_SDL + #define LV_USE_DRAW_SDL CONFIG_LV_USE_DRAW_SDL + #else + #define LV_USE_DRAW_SDL 0 + #endif +#endif + +/* Use VG-Lite GPU. */ +#ifndef LV_USE_DRAW_VG_LITE + #ifdef CONFIG_LV_USE_DRAW_VG_LITE + #define LV_USE_DRAW_VG_LITE CONFIG_LV_USE_DRAW_VG_LITE + #else + #define LV_USE_DRAW_VG_LITE 0 + #endif +#endif + +#if LV_USE_DRAW_VG_LITE +/* Enable VG-Lite custom external 'gpu_init()' function */ +#ifndef LV_VG_LITE_USE_GPU_INIT + #ifdef CONFIG_LV_VG_LITE_USE_GPU_INIT + #define LV_VG_LITE_USE_GPU_INIT CONFIG_LV_VG_LITE_USE_GPU_INIT + #else + #define LV_VG_LITE_USE_GPU_INIT 0 + #endif +#endif + +/* Enable VG-Lite assert. */ +#ifndef LV_VG_LITE_USE_ASSERT + #ifdef CONFIG_LV_VG_LITE_USE_ASSERT + #define LV_VG_LITE_USE_ASSERT CONFIG_LV_VG_LITE_USE_ASSERT + #else + #define LV_VG_LITE_USE_ASSERT 0 + #endif +#endif + +#endif + /*======================= * FEATURE CONFIGURATION *=======================*/ -/*------------- - * Drawing - *-----------*/ - -/*Enable complex draw engine. - *Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/ -#ifndef LV_DRAW_COMPLEX - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_DRAW_COMPLEX - #define LV_DRAW_COMPLEX CONFIG_LV_DRAW_COMPLEX - #else - #define LV_DRAW_COMPLEX 0 - #endif - #else - #define LV_DRAW_COMPLEX 1 - #endif -#endif -#if LV_DRAW_COMPLEX != 0 - - /*Allow buffering some shadow calculation. - *LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius` - *Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/ - #ifndef LV_SHADOW_CACHE_SIZE - #ifdef CONFIG_LV_SHADOW_CACHE_SIZE - #define LV_SHADOW_CACHE_SIZE CONFIG_LV_SHADOW_CACHE_SIZE - #else - #define LV_SHADOW_CACHE_SIZE 0 - #endif - #endif - - /* Set number of maximally cached circle data. - * The circumference of 1/4 circle are saved for anti-aliasing - * radius * 4 bytes are used per circle (the most often used radiuses are saved) - * 0: to disable caching */ - #ifndef LV_CIRCLE_CACHE_SIZE - #ifdef CONFIG_LV_CIRCLE_CACHE_SIZE - #define LV_CIRCLE_CACHE_SIZE CONFIG_LV_CIRCLE_CACHE_SIZE - #else - #define LV_CIRCLE_CACHE_SIZE 4 - #endif - #endif -#endif /*LV_DRAW_COMPLEX*/ - -/** - * "Simple layers" are used when a widget has `style_opa < 255` to buffer the widget into a layer - * and blend it as an image with the given opacity. - * Note that `bg_opa`, `text_opa` etc don't require buffering into layer) - * The widget can be buffered in smaller chunks to avoid using large buffers. - * - * - LV_LAYER_SIMPLE_BUF_SIZE: [bytes] the optimal target buffer size. LVGL will try to allocate it - * - LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE: [bytes] used if `LV_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated. - * - * Both buffer sizes are in bytes. - * "Transformed layers" (where transform_angle/zoom properties are used) use larger buffers - * and can't be drawn in chunks. So these settings affects only widgets with opacity. - */ -#ifndef LV_LAYER_SIMPLE_BUF_SIZE - #ifdef CONFIG_LV_LAYER_SIMPLE_BUF_SIZE - #define LV_LAYER_SIMPLE_BUF_SIZE CONFIG_LV_LAYER_SIMPLE_BUF_SIZE - #else - #define LV_LAYER_SIMPLE_BUF_SIZE (24 * 1024) - #endif -#endif -#ifndef LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE - #ifdef CONFIG_LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE - #define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE CONFIG_LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE - #else - #define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE (3 * 1024) - #endif -#endif - -/*Default image cache size. Image caching keeps the images opened. - *If only the built-in image formats are used there is no real advantage of caching. (I.e. if no new image decoder is added) - *With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. - *However the opened images might consume additional RAM. - *0: to disable caching*/ -#ifndef LV_IMG_CACHE_DEF_SIZE - #ifdef CONFIG_LV_IMG_CACHE_DEF_SIZE - #define LV_IMG_CACHE_DEF_SIZE CONFIG_LV_IMG_CACHE_DEF_SIZE - #else - #define LV_IMG_CACHE_DEF_SIZE 0 - #endif -#endif - -/*Number of stops allowed per gradient. Increase this to allow more stops. - *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ -#ifndef LV_GRADIENT_MAX_STOPS - #ifdef CONFIG_LV_GRADIENT_MAX_STOPS - #define LV_GRADIENT_MAX_STOPS CONFIG_LV_GRADIENT_MAX_STOPS - #else - #define LV_GRADIENT_MAX_STOPS 2 - #endif -#endif - -/*Default gradient buffer size. - *When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again. - *LV_GRAD_CACHE_DEF_SIZE sets the size of this cache in bytes. - *If the cache is too small the map will be allocated only while it's required for the drawing. - *0 mean no caching.*/ -#ifndef LV_GRAD_CACHE_DEF_SIZE - #ifdef CONFIG_LV_GRAD_CACHE_DEF_SIZE - #define LV_GRAD_CACHE_DEF_SIZE CONFIG_LV_GRAD_CACHE_DEF_SIZE - #else - #define LV_GRAD_CACHE_DEF_SIZE 0 - #endif -#endif - -/*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display) - *LV_DITHER_GRADIENT implies allocating one or two more lines of the object's rendering surface - *The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion */ -#ifndef LV_DITHER_GRADIENT - #ifdef CONFIG_LV_DITHER_GRADIENT - #define LV_DITHER_GRADIENT CONFIG_LV_DITHER_GRADIENT - #else - #define LV_DITHER_GRADIENT 0 - #endif -#endif -#if LV_DITHER_GRADIENT - /*Add support for error diffusion dithering. - *Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing. - *The increase in memory consumption is (24 bits * object's width)*/ - #ifndef LV_DITHER_ERROR_DIFFUSION - #ifdef CONFIG_LV_DITHER_ERROR_DIFFUSION - #define LV_DITHER_ERROR_DIFFUSION CONFIG_LV_DITHER_ERROR_DIFFUSION - #else - #define LV_DITHER_ERROR_DIFFUSION 0 - #endif - #endif -#endif - -/*Maximum buffer size to allocate for rotation. - *Only used if software rotation is enabled in the display driver.*/ -#ifndef LV_DISP_ROT_MAX_BUF - #ifdef CONFIG_LV_DISP_ROT_MAX_BUF - #define LV_DISP_ROT_MAX_BUF CONFIG_LV_DISP_ROT_MAX_BUF - #else - #define LV_DISP_ROT_MAX_BUF (10*1024) - #endif -#endif - -/*------------- - * GPU - *-----------*/ - -/*Use Arm's 2D acceleration library Arm-2D */ -#ifndef LV_USE_GPU_ARM2D - #ifdef CONFIG_LV_USE_GPU_ARM2D - #define LV_USE_GPU_ARM2D CONFIG_LV_USE_GPU_ARM2D - #else - #define LV_USE_GPU_ARM2D 0 - #endif -#endif - -/*Use STM32's DMA2D (aka Chrom Art) GPU*/ -#ifndef LV_USE_GPU_STM32_DMA2D - #ifdef CONFIG_LV_USE_GPU_STM32_DMA2D - #define LV_USE_GPU_STM32_DMA2D CONFIG_LV_USE_GPU_STM32_DMA2D - #else - #define LV_USE_GPU_STM32_DMA2D 0 - #endif -#endif -#if LV_USE_GPU_STM32_DMA2D - /*Must be defined to include path of CMSIS header of target processor - e.g. "stm32f7xx.h" or "stm32f4xx.h"*/ - #ifndef LV_GPU_DMA2D_CMSIS_INCLUDE - #ifdef CONFIG_LV_GPU_DMA2D_CMSIS_INCLUDE - #define LV_GPU_DMA2D_CMSIS_INCLUDE CONFIG_LV_GPU_DMA2D_CMSIS_INCLUDE - #else - #define LV_GPU_DMA2D_CMSIS_INCLUDE - #endif - #endif -#endif - -/*Enable RA6M3 G2D GPU*/ -#ifndef LV_USE_GPU_RA6M3_G2D - #ifdef CONFIG_LV_USE_GPU_RA6M3_G2D - #define LV_USE_GPU_RA6M3_G2D CONFIG_LV_USE_GPU_RA6M3_G2D - #else - #define LV_USE_GPU_RA6M3_G2D 0 - #endif -#endif -#if LV_USE_GPU_RA6M3_G2D - /*include path of target processor - e.g. "hal_data.h"*/ - #ifndef LV_GPU_RA6M3_G2D_INCLUDE - #ifdef CONFIG_LV_GPU_RA6M3_G2D_INCLUDE - #define LV_GPU_RA6M3_G2D_INCLUDE CONFIG_LV_GPU_RA6M3_G2D_INCLUDE - #else - #define LV_GPU_RA6M3_G2D_INCLUDE "hal_data.h" - #endif - #endif -#endif - -/*Use SWM341's DMA2D GPU*/ -#ifndef LV_USE_GPU_SWM341_DMA2D - #ifdef CONFIG_LV_USE_GPU_SWM341_DMA2D - #define LV_USE_GPU_SWM341_DMA2D CONFIG_LV_USE_GPU_SWM341_DMA2D - #else - #define LV_USE_GPU_SWM341_DMA2D 0 - #endif -#endif -#if LV_USE_GPU_SWM341_DMA2D - #ifndef LV_GPU_SWM341_DMA2D_INCLUDE - #ifdef CONFIG_LV_GPU_SWM341_DMA2D_INCLUDE - #define LV_GPU_SWM341_DMA2D_INCLUDE CONFIG_LV_GPU_SWM341_DMA2D_INCLUDE - #else - #define LV_GPU_SWM341_DMA2D_INCLUDE "SWM341.h" - #endif - #endif -#endif - -/*Use NXP's PXP GPU iMX RTxxx platforms*/ -#ifndef LV_USE_GPU_NXP_PXP - #ifdef CONFIG_LV_USE_GPU_NXP_PXP - #define LV_USE_GPU_NXP_PXP CONFIG_LV_USE_GPU_NXP_PXP - #else - #define LV_USE_GPU_NXP_PXP 0 - #endif -#endif -#if LV_USE_GPU_NXP_PXP - /*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c) - * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS - * has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected. - *0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init() - */ - #ifndef LV_USE_GPU_NXP_PXP_AUTO_INIT - #ifdef CONFIG_LV_USE_GPU_NXP_PXP_AUTO_INIT - #define LV_USE_GPU_NXP_PXP_AUTO_INIT CONFIG_LV_USE_GPU_NXP_PXP_AUTO_INIT - #else - #define LV_USE_GPU_NXP_PXP_AUTO_INIT 0 - #endif - #endif -#endif - -/*Use NXP's VG-Lite GPU iMX RTxxx platforms*/ -#ifndef LV_USE_GPU_NXP_VG_LITE - #ifdef CONFIG_LV_USE_GPU_NXP_VG_LITE - #define LV_USE_GPU_NXP_VG_LITE CONFIG_LV_USE_GPU_NXP_VG_LITE - #else - #define LV_USE_GPU_NXP_VG_LITE 0 - #endif -#endif - -/*Use SDL renderer API*/ -#ifndef LV_USE_GPU_SDL - #ifdef CONFIG_LV_USE_GPU_SDL - #define LV_USE_GPU_SDL CONFIG_LV_USE_GPU_SDL - #else - #define LV_USE_GPU_SDL 0 - #endif -#endif -#if LV_USE_GPU_SDL - #ifndef LV_GPU_SDL_INCLUDE_PATH - #ifdef CONFIG_LV_GPU_SDL_INCLUDE_PATH - #define LV_GPU_SDL_INCLUDE_PATH CONFIG_LV_GPU_SDL_INCLUDE_PATH - #else - #define LV_GPU_SDL_INCLUDE_PATH - #endif - #endif - /*Texture cache size, 8MB by default*/ - #ifndef LV_GPU_SDL_LRU_SIZE - #ifdef CONFIG_LV_GPU_SDL_LRU_SIZE - #define LV_GPU_SDL_LRU_SIZE CONFIG_LV_GPU_SDL_LRU_SIZE - #else - #define LV_GPU_SDL_LRU_SIZE (1024 * 1024 * 8) - #endif - #endif - /*Custom blend mode for mask drawing, disable if you need to link with older SDL2 lib*/ - #ifndef LV_GPU_SDL_CUSTOM_BLEND_MODE - #ifdef CONFIG_LV_GPU_SDL_CUSTOM_BLEND_MODE - #define LV_GPU_SDL_CUSTOM_BLEND_MODE CONFIG_LV_GPU_SDL_CUSTOM_BLEND_MODE - #else - #define LV_GPU_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6)) - #endif - #endif -#endif - /*------------- * Logging *-----------*/ @@ -588,6 +507,34 @@ #endif #endif + /*1: Enable print timestamp; + *0: Disable print timestamp*/ + #ifndef LV_LOG_USE_TIMESTAMP + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_USE_TIMESTAMP + #define LV_LOG_USE_TIMESTAMP CONFIG_LV_LOG_USE_TIMESTAMP + #else + #define LV_LOG_USE_TIMESTAMP 0 + #endif + #else + #define LV_LOG_USE_TIMESTAMP 1 + #endif + #endif + + /*1: Print file and line number of the log; + *0: Do not print file and line number of the log*/ + #ifndef LV_LOG_USE_FILE_LINE + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_USE_FILE_LINE + #define LV_LOG_USE_FILE_LINE CONFIG_LV_LOG_USE_FILE_LINE + #else + #define LV_LOG_USE_FILE_LINE 0 + #endif + #else + #define LV_LOG_USE_FILE_LINE 1 + #endif + #endif + /*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/ #ifndef LV_LOG_TRACE_MEM #ifdef _LV_KCONFIG_PRESENT @@ -677,6 +624,17 @@ #define LV_LOG_TRACE_ANIM 1 #endif #endif + #ifndef LV_LOG_TRACE_CACHE + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LOG_TRACE_CACHE + #define LV_LOG_TRACE_CACHE CONFIG_LV_LOG_TRACE_CACHE + #else + #define LV_LOG_TRACE_CACHE 0 + #endif + #else + #define LV_LOG_TRACE_CACHE 1 + #endif + #endif #endif /*LV_USE_LOG*/ @@ -747,46 +705,9 @@ #endif /*------------- - * Others + * Debug *-----------*/ -/*1: Show CPU usage and FPS count*/ -#ifndef LV_USE_PERF_MONITOR - #ifdef CONFIG_LV_USE_PERF_MONITOR - #define LV_USE_PERF_MONITOR CONFIG_LV_USE_PERF_MONITOR - #else - #define LV_USE_PERF_MONITOR 0 - #endif -#endif -#if LV_USE_PERF_MONITOR - #ifndef LV_USE_PERF_MONITOR_POS - #ifdef CONFIG_LV_USE_PERF_MONITOR_POS - #define LV_USE_PERF_MONITOR_POS CONFIG_LV_USE_PERF_MONITOR_POS - #else - #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT - #endif - #endif -#endif - -/*1: Show the used memory and the memory fragmentation - * Requires LV_MEM_CUSTOM = 0*/ -#ifndef LV_USE_MEM_MONITOR - #ifdef CONFIG_LV_USE_MEM_MONITOR - #define LV_USE_MEM_MONITOR CONFIG_LV_USE_MEM_MONITOR - #else - #define LV_USE_MEM_MONITOR 0 - #endif -#endif -#if LV_USE_MEM_MONITOR - #ifndef LV_USE_MEM_MONITOR_POS - #ifdef CONFIG_LV_USE_MEM_MONITOR_POS - #define LV_USE_MEM_MONITOR_POS CONFIG_LV_USE_MEM_MONITOR_POS - #else - #define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT - #endif - #endif -#endif - /*1: Draw random colored rectangles over the redrawn areas*/ #ifndef LV_USE_REFR_DEBUG #ifdef CONFIG_LV_USE_REFR_DEBUG @@ -796,76 +717,179 @@ #endif #endif -/*Change the built in (v)snprintf functions*/ -#ifndef LV_SPRINTF_CUSTOM - #ifdef CONFIG_LV_SPRINTF_CUSTOM - #define LV_SPRINTF_CUSTOM CONFIG_LV_SPRINTF_CUSTOM +/*1: Draw a red overlay for ARGB layers and a green overlay for RGB layers*/ +#ifndef LV_USE_LAYER_DEBUG + #ifdef CONFIG_LV_USE_LAYER_DEBUG + #define LV_USE_LAYER_DEBUG CONFIG_LV_USE_LAYER_DEBUG #else - #define LV_SPRINTF_CUSTOM 0 - #endif -#endif -#if LV_SPRINTF_CUSTOM - #ifndef LV_SPRINTF_INCLUDE - #ifdef CONFIG_LV_SPRINTF_INCLUDE - #define LV_SPRINTF_INCLUDE CONFIG_LV_SPRINTF_INCLUDE - #else - #define LV_SPRINTF_INCLUDE - #endif - #endif - #ifndef lv_snprintf - #ifdef CONFIG_LV_SNPRINTF - #define lv_snprintf CONFIG_LV_SNPRINTF - #else - #define lv_snprintf snprintf - #endif - #endif - #ifndef lv_vsnprintf - #ifdef CONFIG_LV_VSNPRINTF - #define lv_vsnprintf CONFIG_LV_VSNPRINTF - #else - #define lv_vsnprintf vsnprintf - #endif - #endif -#else /*LV_SPRINTF_CUSTOM*/ - #ifndef LV_SPRINTF_USE_FLOAT - #ifdef CONFIG_LV_SPRINTF_USE_FLOAT - #define LV_SPRINTF_USE_FLOAT CONFIG_LV_SPRINTF_USE_FLOAT - #else - #define LV_SPRINTF_USE_FLOAT 0 - #endif - #endif -#endif /*LV_SPRINTF_CUSTOM*/ - -#ifndef LV_USE_USER_DATA - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_USER_DATA - #define LV_USE_USER_DATA CONFIG_LV_USE_USER_DATA - #else - #define LV_USE_USER_DATA 0 - #endif - #else - #define LV_USE_USER_DATA 1 + #define LV_USE_LAYER_DEBUG 0 #endif #endif -/*Garbage Collector settings - *Used if lvgl is bound to higher level language and the memory is managed by that language*/ -#ifndef LV_ENABLE_GC - #ifdef CONFIG_LV_ENABLE_GC - #define LV_ENABLE_GC CONFIG_LV_ENABLE_GC +/*1: Draw overlays with different colors for each draw_unit's tasks. + *Also add the index number of the draw unit on white background. + *For layers add the index number of the draw unit on black background.*/ +#ifndef LV_USE_PARALLEL_DRAW_DEBUG + #ifdef CONFIG_LV_USE_PARALLEL_DRAW_DEBUG + #define LV_USE_PARALLEL_DRAW_DEBUG CONFIG_LV_USE_PARALLEL_DRAW_DEBUG #else - #define LV_ENABLE_GC 0 + #define LV_USE_PARALLEL_DRAW_DEBUG 0 #endif #endif -#if LV_ENABLE_GC != 0 - #ifndef LV_GC_INCLUDE - #ifdef CONFIG_LV_GC_INCLUDE - #define LV_GC_INCLUDE CONFIG_LV_GC_INCLUDE + +/*------------- + * Others + *-----------*/ + +#ifndef LV_ENABLE_GLOBAL_CUSTOM + #ifdef CONFIG_LV_ENABLE_GLOBAL_CUSTOM + #define LV_ENABLE_GLOBAL_CUSTOM CONFIG_LV_ENABLE_GLOBAL_CUSTOM + #else + #define LV_ENABLE_GLOBAL_CUSTOM 0 + #endif +#endif +#if LV_ENABLE_GLOBAL_CUSTOM + /*Header to include for the custom 'lv_global' function"*/ + #ifndef LV_GLOBAL_CUSTOM_INCLUDE + #ifdef CONFIG_LV_GLOBAL_CUSTOM_INCLUDE + #define LV_GLOBAL_CUSTOM_INCLUDE CONFIG_LV_GLOBAL_CUSTOM_INCLUDE #else - #define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ + #define LV_GLOBAL_CUSTOM_INCLUDE #endif #endif -#endif /*LV_ENABLE_GC*/ +#endif + +/*Default cache size in bytes. + *Used by image decoders such as `lv_lodepng` to keep the decoded image in the memory. + *If size is not set to 0, the decoder will fail to decode when the cache is full. + *If size is 0, the cache function is not enabled and the decoded mem will be released immediately after use.*/ +#ifndef LV_CACHE_DEF_SIZE + #ifdef CONFIG_LV_CACHE_DEF_SIZE + #define LV_CACHE_DEF_SIZE CONFIG_LV_CACHE_DEF_SIZE + #else + #define LV_CACHE_DEF_SIZE 0 + #endif +#endif + +/*Default number of image header cache entries. The cache is used to store the headers of images + *The main logic is like `LV_CACHE_DEF_SIZE` but for image headers.*/ +#ifndef LV_IMAGE_HEADER_CACHE_DEF_CNT + #ifdef CONFIG_LV_IMAGE_HEADER_CACHE_DEF_CNT + #define LV_IMAGE_HEADER_CACHE_DEF_CNT CONFIG_LV_IMAGE_HEADER_CACHE_DEF_CNT + #else + #define LV_IMAGE_HEADER_CACHE_DEF_CNT 0 + #endif +#endif + +/*Number of stops allowed per gradient. Increase this to allow more stops. + *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ +#ifndef LV_GRADIENT_MAX_STOPS + #ifdef CONFIG_LV_GRADIENT_MAX_STOPS + #define LV_GRADIENT_MAX_STOPS CONFIG_LV_GRADIENT_MAX_STOPS + #else + #define LV_GRADIENT_MAX_STOPS 2 + #endif +#endif + +/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. + * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */ +#ifndef LV_COLOR_MIX_ROUND_OFS + #ifdef CONFIG_LV_COLOR_MIX_ROUND_OFS + #define LV_COLOR_MIX_ROUND_OFS CONFIG_LV_COLOR_MIX_ROUND_OFS + #else + #define LV_COLOR_MIX_ROUND_OFS 0 + #endif +#endif + +/* Add 2 x 32 bit variables to each lv_obj_t to speed up getting style properties */ +#ifndef LV_OBJ_STYLE_CACHE + #ifdef CONFIG_LV_OBJ_STYLE_CACHE + #define LV_OBJ_STYLE_CACHE CONFIG_LV_OBJ_STYLE_CACHE + #else + #define LV_OBJ_STYLE_CACHE 0 + #endif +#endif + +/* Add `id` field to `lv_obj_t` */ +#ifndef LV_USE_OBJ_ID + #ifdef CONFIG_LV_USE_OBJ_ID + #define LV_USE_OBJ_ID CONFIG_LV_USE_OBJ_ID + #else + #define LV_USE_OBJ_ID 0 + #endif +#endif + +/* Use lvgl builtin method for obj ID */ +#ifndef LV_USE_OBJ_ID_BUILTIN + #ifdef CONFIG_LV_USE_OBJ_ID_BUILTIN + #define LV_USE_OBJ_ID_BUILTIN CONFIG_LV_USE_OBJ_ID_BUILTIN + #else + #define LV_USE_OBJ_ID_BUILTIN 0 + #endif +#endif + +/*Use obj property set/get API*/ +#ifndef LV_USE_OBJ_PROPERTY + #ifdef CONFIG_LV_USE_OBJ_PROPERTY + #define LV_USE_OBJ_PROPERTY CONFIG_LV_USE_OBJ_PROPERTY + #else + #define LV_USE_OBJ_PROPERTY 0 + #endif +#endif + +/* VG-Lite Simulator */ +/*Requires: LV_USE_THORVG_INTERNAL or LV_USE_THORVG_EXTERNAL */ +#ifndef LV_USE_VG_LITE_THORVG + #ifdef CONFIG_LV_USE_VG_LITE_THORVG + #define LV_USE_VG_LITE_THORVG CONFIG_LV_USE_VG_LITE_THORVG + #else + #define LV_USE_VG_LITE_THORVG 0 + #endif +#endif + +#if LV_USE_VG_LITE_THORVG + + /*Enable LVGL's blend mode support*/ + #ifndef LV_VG_LITE_THORVG_LVGL_BLEND_SUPPORT + #ifdef CONFIG_LV_VG_LITE_THORVG_LVGL_BLEND_SUPPORT + #define LV_VG_LITE_THORVG_LVGL_BLEND_SUPPORT CONFIG_LV_VG_LITE_THORVG_LVGL_BLEND_SUPPORT + #else + #define LV_VG_LITE_THORVG_LVGL_BLEND_SUPPORT 0 + #endif + #endif + + /*Enable YUV color format support*/ + #ifndef LV_VG_LITE_THORVG_YUV_SUPPORT + #ifdef CONFIG_LV_VG_LITE_THORVG_YUV_SUPPORT + #define LV_VG_LITE_THORVG_YUV_SUPPORT CONFIG_LV_VG_LITE_THORVG_YUV_SUPPORT + #else + #define LV_VG_LITE_THORVG_YUV_SUPPORT 0 + #endif + #endif + + /*Enable 16 pixels alignment*/ + #ifndef LV_VG_LITE_THORVG_16PIXELS_ALIGN + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_VG_LITE_THORVG_16PIXELS_ALIGN + #define LV_VG_LITE_THORVG_16PIXELS_ALIGN CONFIG_LV_VG_LITE_THORVG_16PIXELS_ALIGN + #else + #define LV_VG_LITE_THORVG_16PIXELS_ALIGN 0 + #endif + #else + #define LV_VG_LITE_THORVG_16PIXELS_ALIGN 1 + #endif + #endif + + /*Enable multi-thread render*/ + #ifndef LV_VG_LITE_THORVG_THREAD_RENDER + #ifdef CONFIG_LV_VG_LITE_THORVG_THREAD_RENDER + #define LV_VG_LITE_THORVG_THREAD_RENDER CONFIG_LV_VG_LITE_THORVG_THREAD_RENDER + #else + #define LV_VG_LITE_THORVG_THREAD_RENDER 0 + #endif + #endif + +#endif /*===================== * COMPILER SETTINGS @@ -898,7 +922,7 @@ #endif #endif -/*Define a custom attribute to `lv_disp_flush_ready` function*/ +/*Define a custom attribute to `lv_display_flush_ready` function*/ #ifndef LV_ATTRIBUTE_FLUSH_READY #ifdef CONFIG_LV_ATTRIBUTE_FLUSH_READY #define LV_ATTRIBUTE_FLUSH_READY CONFIG_LV_ATTRIBUTE_FLUSH_READY @@ -957,15 +981,6 @@ #endif #endif -/*Prefix variables that are used in GPU accelerated operations, often these need to be placed in RAM sections that are DMA accessible*/ -#ifndef LV_ATTRIBUTE_DMA - #ifdef CONFIG_LV_ATTRIBUTE_DMA - #define LV_ATTRIBUTE_DMA CONFIG_LV_ATTRIBUTE_DMA - #else - #define LV_ATTRIBUTE_DMA - #endif -#endif - /*Export integer constant to binding. This macro is used with constants in the form of LV_ that *should also appear on LVGL binding API such as Micropython.*/ #ifndef LV_EXPORT_CONST_INT @@ -976,12 +991,21 @@ #endif #endif -/*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/ -#ifndef LV_USE_LARGE_COORD - #ifdef CONFIG_LV_USE_LARGE_COORD - #define LV_USE_LARGE_COORD CONFIG_LV_USE_LARGE_COORD +/*Prefix all global extern data with this*/ +#ifndef LV_ATTRIBUTE_EXTERN_DATA + #ifdef CONFIG_LV_ATTRIBUTE_EXTERN_DATA + #define LV_ATTRIBUTE_EXTERN_DATA CONFIG_LV_ATTRIBUTE_EXTERN_DATA #else - #define LV_USE_LARGE_COORD 0 + #define LV_ATTRIBUTE_EXTERN_DATA + #endif +#endif + +/* Use `float` as `lv_value_precise_t` */ +#ifndef LV_USE_FLOAT + #ifdef CONFIG_LV_USE_FLOAT + #define LV_USE_FLOAT CONFIG_LV_USE_FLOAT + #else + #define LV_USE_FLOAT 0 #endif #endif @@ -1144,13 +1168,6 @@ #endif /*Demonstrate special features*/ -#ifndef LV_FONT_MONTSERRAT_12_SUBPX - #ifdef CONFIG_LV_FONT_MONTSERRAT_12_SUBPX - #define LV_FONT_MONTSERRAT_12_SUBPX CONFIG_LV_FONT_MONTSERRAT_12_SUBPX - #else - #define LV_FONT_MONTSERRAT_12_SUBPX 0 - #endif -#endif #ifndef LV_FONT_MONTSERRAT_28_COMPRESSED #ifdef CONFIG_LV_FONT_MONTSERRAT_28_COMPRESSED #define LV_FONT_MONTSERRAT_28_COMPRESSED CONFIG_LV_FONT_MONTSERRAT_28_COMPRESSED @@ -1229,25 +1246,6 @@ #endif #endif -/*Enable subpixel rendering*/ -#ifndef LV_USE_FONT_SUBPX - #ifdef CONFIG_LV_USE_FONT_SUBPX - #define LV_USE_FONT_SUBPX CONFIG_LV_USE_FONT_SUBPX - #else - #define LV_USE_FONT_SUBPX 0 - #endif -#endif -#if LV_USE_FONT_SUBPX - /*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/ - #ifndef LV_FONT_SUBPX_BGR - #ifdef CONFIG_LV_FONT_SUBPX_BGR - #define LV_FONT_SUBPX_BGR CONFIG_LV_FONT_SUBPX_BGR - #else - #define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/ - #endif - #endif -#endif - /*Enable drawing placeholders when glyph dsc is not found*/ #ifndef LV_USE_FONT_PLACEHOLDER #ifdef _LV_KCONFIG_PRESENT @@ -1284,7 +1282,7 @@ #ifdef CONFIG_LV_TXT_BREAK_CHARS #define LV_TXT_BREAK_CHARS CONFIG_LV_TXT_BREAK_CHARS #else - #define LV_TXT_BREAK_CHARS " ,.;:-_" + #define LV_TXT_BREAK_CHARS " ,.;:-_)]}" #endif #endif @@ -1318,15 +1316,6 @@ #endif #endif -/*The control character to use for signalling text recoloring.*/ -#ifndef LV_TXT_COLOR_CMD - #ifdef CONFIG_LV_TXT_COLOR_CMD - #define LV_TXT_COLOR_CMD CONFIG_LV_TXT_COLOR_CMD - #else - #define LV_TXT_COLOR_CMD "#" - #endif -#endif - /*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts. *The direction will be processed according to the Unicode Bidirectional Algorithm: *https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ @@ -1362,11 +1351,35 @@ #endif /*================== - * WIDGET USAGE + * WIDGETS *================*/ /*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/ +#ifndef LV_WIDGETS_HAS_DEFAULT_VALUE + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_WIDGETS_HAS_DEFAULT_VALUE + #define LV_WIDGETS_HAS_DEFAULT_VALUE CONFIG_LV_WIDGETS_HAS_DEFAULT_VALUE + #else + #define LV_WIDGETS_HAS_DEFAULT_VALUE 0 + #endif + #else + #define LV_WIDGETS_HAS_DEFAULT_VALUE 1 + #endif +#endif + +#ifndef LV_USE_ANIMIMG + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_ANIMIMG + #define LV_USE_ANIMIMG CONFIG_LV_USE_ANIMIMG + #else + #define LV_USE_ANIMIMG 0 + #endif + #else + #define LV_USE_ANIMIMG 1 + #endif +#endif + #ifndef LV_USE_ARC #ifdef _LV_KCONFIG_PRESENT #ifdef CONFIG_LV_USE_ARC @@ -1391,220 +1404,27 @@ #endif #endif -#ifndef LV_USE_BTN +#ifndef LV_USE_BUTTON #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_BTN - #define LV_USE_BTN CONFIG_LV_USE_BTN + #ifdef CONFIG_LV_USE_BUTTON + #define LV_USE_BUTTON CONFIG_LV_USE_BUTTON #else - #define LV_USE_BTN 0 + #define LV_USE_BUTTON 0 #endif #else - #define LV_USE_BTN 1 + #define LV_USE_BUTTON 1 #endif #endif -#ifndef LV_USE_BTNMATRIX +#ifndef LV_USE_BUTTONMATRIX #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_BTNMATRIX - #define LV_USE_BTNMATRIX CONFIG_LV_USE_BTNMATRIX + #ifdef CONFIG_LV_USE_BUTTONMATRIX + #define LV_USE_BUTTONMATRIX CONFIG_LV_USE_BUTTONMATRIX #else - #define LV_USE_BTNMATRIX 0 + #define LV_USE_BUTTONMATRIX 0 #endif #else - #define LV_USE_BTNMATRIX 1 - #endif -#endif - -#ifndef LV_USE_CANVAS - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_CANVAS - #define LV_USE_CANVAS CONFIG_LV_USE_CANVAS - #else - #define LV_USE_CANVAS 0 - #endif - #else - #define LV_USE_CANVAS 1 - #endif -#endif - -#ifndef LV_USE_CHECKBOX - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_CHECKBOX - #define LV_USE_CHECKBOX CONFIG_LV_USE_CHECKBOX - #else - #define LV_USE_CHECKBOX 0 - #endif - #else - #define LV_USE_CHECKBOX 1 - #endif -#endif - -#ifndef LV_USE_DROPDOWN - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_DROPDOWN - #define LV_USE_DROPDOWN CONFIG_LV_USE_DROPDOWN - #else - #define LV_USE_DROPDOWN 0 - #endif - #else - #define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ - #endif -#endif - -#ifndef LV_USE_IMG - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_IMG - #define LV_USE_IMG CONFIG_LV_USE_IMG - #else - #define LV_USE_IMG 0 - #endif - #else - #define LV_USE_IMG 1 /*Requires: lv_label*/ - #endif -#endif - -#ifndef LV_USE_LABEL - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_LABEL - #define LV_USE_LABEL CONFIG_LV_USE_LABEL - #else - #define LV_USE_LABEL 0 - #endif - #else - #define LV_USE_LABEL 1 - #endif -#endif -#if LV_USE_LABEL - #ifndef LV_LABEL_TEXT_SELECTION - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_LABEL_TEXT_SELECTION - #define LV_LABEL_TEXT_SELECTION CONFIG_LV_LABEL_TEXT_SELECTION - #else - #define LV_LABEL_TEXT_SELECTION 0 - #endif - #else - #define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ - #endif - #endif - #ifndef LV_LABEL_LONG_TXT_HINT - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_LABEL_LONG_TXT_HINT - #define LV_LABEL_LONG_TXT_HINT CONFIG_LV_LABEL_LONG_TXT_HINT - #else - #define LV_LABEL_LONG_TXT_HINT 0 - #endif - #else - #define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ - #endif - #endif -#endif - -#ifndef LV_USE_LINE - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_LINE - #define LV_USE_LINE CONFIG_LV_USE_LINE - #else - #define LV_USE_LINE 0 - #endif - #else - #define LV_USE_LINE 1 - #endif -#endif - -#ifndef LV_USE_ROLLER - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_ROLLER - #define LV_USE_ROLLER CONFIG_LV_USE_ROLLER - #else - #define LV_USE_ROLLER 0 - #endif - #else - #define LV_USE_ROLLER 1 /*Requires: lv_label*/ - #endif -#endif -#if LV_USE_ROLLER - #ifndef LV_ROLLER_INF_PAGES - #ifdef CONFIG_LV_ROLLER_INF_PAGES - #define LV_ROLLER_INF_PAGES CONFIG_LV_ROLLER_INF_PAGES - #else - #define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/ - #endif - #endif -#endif - -#ifndef LV_USE_SLIDER - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_SLIDER - #define LV_USE_SLIDER CONFIG_LV_USE_SLIDER - #else - #define LV_USE_SLIDER 0 - #endif - #else - #define LV_USE_SLIDER 1 /*Requires: lv_bar*/ - #endif -#endif - -#ifndef LV_USE_SWITCH - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_SWITCH - #define LV_USE_SWITCH CONFIG_LV_USE_SWITCH - #else - #define LV_USE_SWITCH 0 - #endif - #else - #define LV_USE_SWITCH 1 - #endif -#endif - -#ifndef LV_USE_TEXTAREA - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_TEXTAREA - #define LV_USE_TEXTAREA CONFIG_LV_USE_TEXTAREA - #else - #define LV_USE_TEXTAREA 0 - #endif - #else - #define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ - #endif -#endif -#if LV_USE_TEXTAREA != 0 - #ifndef LV_TEXTAREA_DEF_PWD_SHOW_TIME - #ifdef CONFIG_LV_TEXTAREA_DEF_PWD_SHOW_TIME - #define LV_TEXTAREA_DEF_PWD_SHOW_TIME CONFIG_LV_TEXTAREA_DEF_PWD_SHOW_TIME - #else - #define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ - #endif - #endif -#endif - -#ifndef LV_USE_TABLE - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_TABLE - #define LV_USE_TABLE CONFIG_LV_USE_TABLE - #else - #define LV_USE_TABLE 0 - #endif - #else - #define LV_USE_TABLE 1 - #endif -#endif - -/*================== - * EXTRA COMPONENTS - *==================*/ - -/*----------- - * Widgets - *----------*/ -#ifndef LV_USE_ANIMIMG - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_ANIMIMG - #define LV_USE_ANIMIMG CONFIG_LV_USE_ANIMIMG - #else - #define LV_USE_ANIMIMG 0 - #endif - #else - #define LV_USE_ANIMIMG 1 + #define LV_USE_BUTTONMATRIX 1 #endif #endif @@ -1676,6 +1496,18 @@ #endif #endif /*LV_USE_CALENDAR*/ +#ifndef LV_USE_CANVAS + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_CANVAS + #define LV_USE_CANVAS CONFIG_LV_USE_CANVAS + #else + #define LV_USE_CANVAS 0 + #endif + #else + #define LV_USE_CANVAS 1 + #endif +#endif + #ifndef LV_USE_CHART #ifdef _LV_KCONFIG_PRESENT #ifdef CONFIG_LV_USE_CHART @@ -1688,27 +1520,51 @@ #endif #endif -#ifndef LV_USE_COLORWHEEL +#ifndef LV_USE_CHECKBOX #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_COLORWHEEL - #define LV_USE_COLORWHEEL CONFIG_LV_USE_COLORWHEEL + #ifdef CONFIG_LV_USE_CHECKBOX + #define LV_USE_CHECKBOX CONFIG_LV_USE_CHECKBOX #else - #define LV_USE_COLORWHEEL 0 + #define LV_USE_CHECKBOX 0 #endif #else - #define LV_USE_COLORWHEEL 1 + #define LV_USE_CHECKBOX 1 #endif #endif -#ifndef LV_USE_IMGBTN +#ifndef LV_USE_DROPDOWN #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_IMGBTN - #define LV_USE_IMGBTN CONFIG_LV_USE_IMGBTN + #ifdef CONFIG_LV_USE_DROPDOWN + #define LV_USE_DROPDOWN CONFIG_LV_USE_DROPDOWN #else - #define LV_USE_IMGBTN 0 + #define LV_USE_DROPDOWN 0 #endif #else - #define LV_USE_IMGBTN 1 + #define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ + #endif +#endif + +#ifndef LV_USE_IMAGE + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_IMAGE + #define LV_USE_IMAGE CONFIG_LV_USE_IMAGE + #else + #define LV_USE_IMAGE 0 + #endif + #else + #define LV_USE_IMAGE 1 /*Requires: lv_label*/ + #endif +#endif + +#ifndef LV_USE_IMAGEBUTTON + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_IMAGEBUTTON + #define LV_USE_IMAGEBUTTON CONFIG_LV_USE_IMAGEBUTTON + #else + #define LV_USE_IMAGEBUTTON 0 + #endif + #else + #define LV_USE_IMAGEBUTTON 1 #endif #endif @@ -1724,6 +1580,49 @@ #endif #endif +#ifndef LV_USE_LABEL + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_LABEL + #define LV_USE_LABEL CONFIG_LV_USE_LABEL + #else + #define LV_USE_LABEL 0 + #endif + #else + #define LV_USE_LABEL 1 + #endif +#endif +#if LV_USE_LABEL + #ifndef LV_LABEL_TEXT_SELECTION + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LABEL_TEXT_SELECTION + #define LV_LABEL_TEXT_SELECTION CONFIG_LV_LABEL_TEXT_SELECTION + #else + #define LV_LABEL_TEXT_SELECTION 0 + #endif + #else + #define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ + #endif + #endif + #ifndef LV_LABEL_LONG_TXT_HINT + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_LABEL_LONG_TXT_HINT + #define LV_LABEL_LONG_TXT_HINT CONFIG_LV_LABEL_LONG_TXT_HINT + #else + #define LV_LABEL_LONG_TXT_HINT 0 + #endif + #else + #define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ + #endif + #endif + #ifndef LV_LABEL_WAIT_CHAR_COUNT + #ifdef CONFIG_LV_LABEL_WAIT_CHAR_COUNT + #define LV_LABEL_WAIT_CHAR_COUNT CONFIG_LV_LABEL_WAIT_CHAR_COUNT + #else + #define LV_LABEL_WAIT_CHAR_COUNT 3 /*The count of wait chart*/ + #endif + #endif +#endif + #ifndef LV_USE_LED #ifdef _LV_KCONFIG_PRESENT #ifdef CONFIG_LV_USE_LED @@ -1736,6 +1635,18 @@ #endif #endif +#ifndef LV_USE_LINE + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_LINE + #define LV_USE_LINE CONFIG_LV_USE_LINE + #else + #define LV_USE_LINE 0 + #endif + #else + #define LV_USE_LINE 1 + #endif +#endif + #ifndef LV_USE_LIST #ifdef _LV_KCONFIG_PRESENT #ifdef CONFIG_LV_USE_LIST @@ -1760,18 +1671,6 @@ #endif #endif -#ifndef LV_USE_METER - #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_METER - #define LV_USE_METER CONFIG_LV_USE_METER - #else - #define LV_USE_METER 0 - #endif - #else - #define LV_USE_METER 1 - #endif -#endif - #ifndef LV_USE_MSGBOX #ifdef _LV_KCONFIG_PRESENT #ifdef CONFIG_LV_USE_MSGBOX @@ -1784,6 +1683,42 @@ #endif #endif +#ifndef LV_USE_ROLLER + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_ROLLER + #define LV_USE_ROLLER CONFIG_LV_USE_ROLLER + #else + #define LV_USE_ROLLER 0 + #endif + #else + #define LV_USE_ROLLER 1 /*Requires: lv_label*/ + #endif +#endif + +#ifndef LV_USE_SCALE + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_SCALE + #define LV_USE_SCALE CONFIG_LV_USE_SCALE + #else + #define LV_USE_SCALE 0 + #endif + #else + #define LV_USE_SCALE 1 + #endif +#endif + +#ifndef LV_USE_SLIDER + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_SLIDER + #define LV_USE_SLIDER CONFIG_LV_USE_SLIDER + #else + #define LV_USE_SLIDER 0 + #endif + #else + #define LV_USE_SLIDER 1 /*Requires: lv_bar*/ + #endif +#endif + #ifndef LV_USE_SPAN #ifdef _LV_KCONFIG_PRESENT #ifdef CONFIG_LV_USE_SPAN @@ -1830,6 +1765,51 @@ #endif #endif +#ifndef LV_USE_SWITCH + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_SWITCH + #define LV_USE_SWITCH CONFIG_LV_USE_SWITCH + #else + #define LV_USE_SWITCH 0 + #endif + #else + #define LV_USE_SWITCH 1 + #endif +#endif + +#ifndef LV_USE_TEXTAREA + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_TEXTAREA + #define LV_USE_TEXTAREA CONFIG_LV_USE_TEXTAREA + #else + #define LV_USE_TEXTAREA 0 + #endif + #else + #define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ + #endif +#endif +#if LV_USE_TEXTAREA != 0 + #ifndef LV_TEXTAREA_DEF_PWD_SHOW_TIME + #ifdef CONFIG_LV_TEXTAREA_DEF_PWD_SHOW_TIME + #define LV_TEXTAREA_DEF_PWD_SHOW_TIME CONFIG_LV_TEXTAREA_DEF_PWD_SHOW_TIME + #else + #define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ + #endif + #endif +#endif + +#ifndef LV_USE_TABLE + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_TABLE + #define LV_USE_TABLE CONFIG_LV_USE_TABLE + #else + #define LV_USE_TABLE 0 + #endif + #else + #define LV_USE_TABLE 1 + #endif +#endif + #ifndef LV_USE_TABVIEW #ifdef _LV_KCONFIG_PRESENT #ifdef CONFIG_LV_USE_TABVIEW @@ -1866,9 +1846,9 @@ #endif #endif -/*----------- - * Themes - *----------*/ +/*================== + * THEMES + *==================*/ /*A simple, impressive and very complete theme*/ #ifndef LV_USE_THEME_DEFAULT @@ -1917,15 +1897,15 @@ #endif /*LV_USE_THEME_DEFAULT*/ /*A very simple theme that is a good starting point for a custom theme*/ -#ifndef LV_USE_THEME_BASIC +#ifndef LV_USE_THEME_SIMPLE #ifdef _LV_KCONFIG_PRESENT - #ifdef CONFIG_LV_USE_THEME_BASIC - #define LV_USE_THEME_BASIC CONFIG_LV_USE_THEME_BASIC + #ifdef CONFIG_LV_USE_THEME_SIMPLE + #define LV_USE_THEME_SIMPLE CONFIG_LV_USE_THEME_SIMPLE #else - #define LV_USE_THEME_BASIC 0 + #define LV_USE_THEME_SIMPLE 0 #endif #else - #define LV_USE_THEME_BASIC 1 + #define LV_USE_THEME_SIMPLE 1 #endif #endif @@ -1942,9 +1922,9 @@ #endif #endif -/*----------- - * Layouts - *----------*/ +/*================== + * LAYOUTS + *==================*/ /*A layout similar to Flexbox in CSS.*/ #ifndef LV_USE_FLEX @@ -1972,9 +1952,9 @@ #endif #endif -/*--------------------- - * 3rd party libraries - *--------------------*/ +/*==================== + * 3RD PARTS LIBRARIES + *====================*/ /*File system interfaces for common APIs */ @@ -2099,37 +2079,39 @@ #endif #endif -/*API for LittleFS (library needs to be added separately). Uses lfs_file_open, lfs_file_read, etc*/ -#ifndef LV_USE_FS_LITTLEFS - #ifdef CONFIG_LV_USE_FS_LITTLEFS - #define LV_USE_FS_LITTLEFS CONFIG_LV_USE_FS_LITTLEFS +/*API for memory-mapped file access. */ +#ifndef LV_USE_FS_MEMFS + #ifdef CONFIG_LV_USE_FS_MEMFS + #define LV_USE_FS_MEMFS CONFIG_LV_USE_FS_MEMFS #else - #define LV_USE_FS_LITTLEFS 0 + #define LV_USE_FS_MEMFS 0 #endif #endif -#if LV_USE_FS_LITTLEFS - #ifndef LV_FS_LITTLEFS_LETTER - #ifdef CONFIG_LV_FS_LITTLEFS_LETTER - #define LV_FS_LITTLEFS_LETTER CONFIG_LV_FS_LITTLEFS_LETTER +#if LV_USE_FS_MEMFS + #ifndef LV_FS_MEMFS_LETTER + #ifdef CONFIG_LV_FS_MEMFS_LETTER + #define LV_FS_MEMFS_LETTER CONFIG_LV_FS_MEMFS_LETTER #else - #define LV_FS_LITTLEFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ - #endif - #endif - #ifndef LV_FS_LITTLEFS_CACHE_SIZE - #ifdef CONFIG_LV_FS_LITTLEFS_CACHE_SIZE - #define LV_FS_LITTLEFS_CACHE_SIZE CONFIG_LV_FS_LITTLEFS_CACHE_SIZE - #else - #define LV_FS_LITTLEFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ + #define LV_FS_MEMFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ #endif #endif #endif -/*PNG decoder library*/ -#ifndef LV_USE_PNG - #ifdef CONFIG_LV_USE_PNG - #define LV_USE_PNG CONFIG_LV_USE_PNG +/*LODEPNG decoder library*/ +#ifndef LV_USE_LODEPNG + #ifdef CONFIG_LV_USE_LODEPNG + #define LV_USE_LODEPNG CONFIG_LV_USE_LODEPNG #else - #define LV_USE_PNG 0 + #define LV_USE_LODEPNG 0 + #endif +#endif + +/*PNG decoder(libpng) library*/ +#ifndef LV_USE_LIBPNG + #ifdef CONFIG_LV_USE_LIBPNG + #define LV_USE_LIBPNG CONFIG_LV_USE_LIBPNG + #else + #define LV_USE_LIBPNG 0 #endif #endif @@ -2144,11 +2126,21 @@ /* JPG + split JPG decoder library. * Split JPG is a custom format optimized for embedded systems. */ -#ifndef LV_USE_SJPG - #ifdef CONFIG_LV_USE_SJPG - #define LV_USE_SJPG CONFIG_LV_USE_SJPG +#ifndef LV_USE_TJPGD + #ifdef CONFIG_LV_USE_TJPGD + #define LV_USE_TJPGD CONFIG_LV_USE_TJPGD #else - #define LV_USE_SJPG 0 + #define LV_USE_TJPGD 0 + #endif +#endif + +/* libjpeg-turbo decoder library. + * Supports complete JPEG specifications and high-performance JPEG decoding. */ +#ifndef LV_USE_LIBJPEG_TURBO + #ifdef CONFIG_LV_USE_LIBJPEG_TURBO + #define LV_USE_LIBJPEG_TURBO CONFIG_LV_USE_LIBJPEG_TURBO + #else + #define LV_USE_LIBJPEG_TURBO 0 #endif #endif @@ -2160,6 +2152,35 @@ #define LV_USE_GIF 0 #endif #endif +#if LV_USE_GIF +/*GIF decoder accelerate*/ +#ifndef LV_GIF_CACHE_DECODE_DATA + #ifdef CONFIG_LV_GIF_CACHE_DECODE_DATA + #define LV_GIF_CACHE_DECODE_DATA CONFIG_LV_GIF_CACHE_DECODE_DATA + #else + #define LV_GIF_CACHE_DECODE_DATA 0 + #endif +#endif +#endif + + +/*Decode bin images to RAM*/ +#ifndef LV_BIN_DECODER_RAM_LOAD + #ifdef CONFIG_LV_BIN_DECODER_RAM_LOAD + #define LV_BIN_DECODER_RAM_LOAD CONFIG_LV_BIN_DECODER_RAM_LOAD + #else + #define LV_BIN_DECODER_RAM_LOAD 0 + #endif +#endif + +/*RLE decompress library*/ +#ifndef LV_USE_RLE + #ifdef CONFIG_LV_USE_RLE + #define LV_USE_RLE CONFIG_LV_USE_RLE + #else + #define LV_USE_RLE 0 + #endif +#endif /*QR code library*/ #ifndef LV_USE_QRCODE @@ -2170,6 +2191,15 @@ #endif #endif +/*Barcode code library*/ +#ifndef LV_USE_BARCODE + #ifdef CONFIG_LV_USE_BARCODE + #define LV_USE_BARCODE CONFIG_LV_USE_BARCODE + #else + #define LV_USE_BARCODE 0 + #endif +#endif + /*FreeType library*/ #ifndef LV_USE_FREETYPE #ifdef CONFIG_LV_USE_FREETYPE @@ -2179,45 +2209,50 @@ #endif #endif #if LV_USE_FREETYPE - /*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/ + /*Memory used by FreeType to cache characters in kilobytes*/ #ifndef LV_FREETYPE_CACHE_SIZE #ifdef CONFIG_LV_FREETYPE_CACHE_SIZE #define LV_FREETYPE_CACHE_SIZE CONFIG_LV_FREETYPE_CACHE_SIZE #else - #define LV_FREETYPE_CACHE_SIZE (16 * 1024) + #define LV_FREETYPE_CACHE_SIZE 768 #endif #endif - #if LV_FREETYPE_CACHE_SIZE >= 0 - /* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */ - /* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */ - /* if font size >= 256, must be configured as image cache */ - #ifndef LV_FREETYPE_SBIT_CACHE - #ifdef CONFIG_LV_FREETYPE_SBIT_CACHE - #define LV_FREETYPE_SBIT_CACHE CONFIG_LV_FREETYPE_SBIT_CACHE - #else - #define LV_FREETYPE_SBIT_CACHE 0 - #endif + + /*Let FreeType to use LVGL memory and file porting*/ + #ifndef LV_FREETYPE_USE_LVGL_PORT + #ifdef CONFIG_LV_FREETYPE_USE_LVGL_PORT + #define LV_FREETYPE_USE_LVGL_PORT CONFIG_LV_FREETYPE_USE_LVGL_PORT + #else + #define LV_FREETYPE_USE_LVGL_PORT 0 #endif - /* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */ - /* (0:use system defaults) */ - #ifndef LV_FREETYPE_CACHE_FT_FACES - #ifdef CONFIG_LV_FREETYPE_CACHE_FT_FACES - #define LV_FREETYPE_CACHE_FT_FACES CONFIG_LV_FREETYPE_CACHE_FT_FACES - #else - #define LV_FREETYPE_CACHE_FT_FACES 0 - #endif + #endif + + /* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */ + /* (0:use system defaults) */ + #ifndef LV_FREETYPE_CACHE_FT_FACES + #ifdef CONFIG_LV_FREETYPE_CACHE_FT_FACES + #define LV_FREETYPE_CACHE_FT_FACES CONFIG_LV_FREETYPE_CACHE_FT_FACES + #else + #define LV_FREETYPE_CACHE_FT_FACES 8 #endif - #ifndef LV_FREETYPE_CACHE_FT_SIZES - #ifdef CONFIG_LV_FREETYPE_CACHE_FT_SIZES - #define LV_FREETYPE_CACHE_FT_SIZES CONFIG_LV_FREETYPE_CACHE_FT_SIZES - #else - #define LV_FREETYPE_CACHE_FT_SIZES 0 - #endif + #endif + #ifndef LV_FREETYPE_CACHE_FT_SIZES + #ifdef CONFIG_LV_FREETYPE_CACHE_FT_SIZES + #define LV_FREETYPE_CACHE_FT_SIZES CONFIG_LV_FREETYPE_CACHE_FT_SIZES + #else + #define LV_FREETYPE_CACHE_FT_SIZES 8 + #endif + #endif + #ifndef LV_FREETYPE_CACHE_FT_GLYPH_CNT + #ifdef CONFIG_LV_FREETYPE_CACHE_FT_GLYPH_CNT + #define LV_FREETYPE_CACHE_FT_GLYPH_CNT CONFIG_LV_FREETYPE_CACHE_FT_GLYPH_CNT + #else + #define LV_FREETYPE_CACHE_FT_GLYPH_CNT 256 #endif #endif #endif -/*Tiny TTF library*/ +/* Built-in TTF decoder */ #ifndef LV_USE_TINY_TTF #ifdef CONFIG_LV_USE_TINY_TTF #define LV_USE_TINY_TTF CONFIG_LV_USE_TINY_TTF @@ -2226,7 +2261,7 @@ #endif #endif #if LV_USE_TINY_TTF - /*Load TTF data from files*/ + /* Enable loading TTF data from files */ #ifndef LV_TINY_TTF_FILE_SUPPORT #ifdef CONFIG_LV_TINY_TTF_FILE_SUPPORT #define LV_TINY_TTF_FILE_SUPPORT CONFIG_LV_TINY_TTF_FILE_SUPPORT @@ -2245,6 +2280,60 @@ #endif #endif +/*Enable Vector Graphic APIs*/ +#ifndef LV_USE_VECTOR_GRAPHIC + #ifdef CONFIG_LV_USE_VECTOR_GRAPHIC + #define LV_USE_VECTOR_GRAPHIC CONFIG_LV_USE_VECTOR_GRAPHIC + #else + #define LV_USE_VECTOR_GRAPHIC 0 + #endif +#endif + +/* Enable ThorVG (vector graphics library) from the src/libs folder */ +#ifndef LV_USE_THORVG_INTERNAL + #ifdef CONFIG_LV_USE_THORVG_INTERNAL + #define LV_USE_THORVG_INTERNAL CONFIG_LV_USE_THORVG_INTERNAL + #else + #define LV_USE_THORVG_INTERNAL 0 + #endif +#endif + +/* Enable ThorVG by assuming that its installed and linked to the project */ +#ifndef LV_USE_THORVG_EXTERNAL + #ifdef CONFIG_LV_USE_THORVG_EXTERNAL + #define LV_USE_THORVG_EXTERNAL CONFIG_LV_USE_THORVG_EXTERNAL + #else + #define LV_USE_THORVG_EXTERNAL 0 + #endif +#endif + +/*Enable LZ4 compress/decompress lib*/ +#ifndef LV_USE_LZ4 + #ifdef CONFIG_LV_USE_LZ4 + #define LV_USE_LZ4 CONFIG_LV_USE_LZ4 + #else + #define LV_USE_LZ4 0 + #endif +#endif + +/*Use lvgl built-in LZ4 lib*/ +#ifndef LV_USE_LZ4_INTERNAL + #ifdef CONFIG_LV_USE_LZ4_INTERNAL + #define LV_USE_LZ4_INTERNAL CONFIG_LV_USE_LZ4_INTERNAL + #else + #define LV_USE_LZ4_INTERNAL 0 + #endif +#endif + +/*Use external LZ4 library*/ +#ifndef LV_USE_LZ4_EXTERNAL + #ifdef CONFIG_LV_USE_LZ4_EXTERNAL + #define LV_USE_LZ4_EXTERNAL CONFIG_LV_USE_LZ4_EXTERNAL + #else + #define LV_USE_LZ4_EXTERNAL 0 + #endif +#endif + /*FFmpeg library for image decoding and playing videos *Supports all major image formats so do not enable other image decoder with it*/ #ifndef LV_USE_FFMPEG @@ -2265,9 +2354,9 @@ #endif #endif -/*----------- - * Others - *----------*/ +/*================== + * OTHERS + *==================*/ /*1: Enable API to take snapshot for object*/ #ifndef LV_USE_SNAPSHOT @@ -2278,6 +2367,152 @@ #endif #endif +/*1: Enable system monitor component*/ +#ifndef LV_USE_SYSMON + #ifdef CONFIG_LV_USE_SYSMON + #define LV_USE_SYSMON CONFIG_LV_USE_SYSMON + #else + #define LV_USE_SYSMON 0 + #endif +#endif +#if LV_USE_SYSMON + /*Get the idle percentage. E.g. uint32_t my_get_idle(void);*/ + #ifndef LV_SYSMON_GET_IDLE + #ifdef CONFIG_LV_SYSMON_GET_IDLE + #define LV_SYSMON_GET_IDLE CONFIG_LV_SYSMON_GET_IDLE + #else + #define LV_SYSMON_GET_IDLE lv_timer_get_idle + #endif + #endif + + /*1: Show CPU usage and FPS count + * Requires `LV_USE_SYSMON = 1`*/ + #ifndef LV_USE_PERF_MONITOR + #ifdef CONFIG_LV_USE_PERF_MONITOR + #define LV_USE_PERF_MONITOR CONFIG_LV_USE_PERF_MONITOR + #else + #define LV_USE_PERF_MONITOR 0 + #endif + #endif + #if LV_USE_PERF_MONITOR + #ifndef LV_USE_PERF_MONITOR_POS + #ifdef CONFIG_LV_USE_PERF_MONITOR_POS + #define LV_USE_PERF_MONITOR_POS CONFIG_LV_USE_PERF_MONITOR_POS + #else + #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT + #endif + #endif + + /*0: Displays performance data on the screen, 1: Prints performance data using log.*/ + #ifndef LV_USE_PERF_MONITOR_LOG_MODE + #ifdef CONFIG_LV_USE_PERF_MONITOR_LOG_MODE + #define LV_USE_PERF_MONITOR_LOG_MODE CONFIG_LV_USE_PERF_MONITOR_LOG_MODE + #else + #define LV_USE_PERF_MONITOR_LOG_MODE 0 + #endif + #endif + #endif + + /*1: Show the used memory and the memory fragmentation + * Requires `LV_USE_BUILTIN_MALLOC = 1` + * Requires `LV_USE_SYSMON = 1`*/ + #ifndef LV_USE_MEM_MONITOR + #ifdef CONFIG_LV_USE_MEM_MONITOR + #define LV_USE_MEM_MONITOR CONFIG_LV_USE_MEM_MONITOR + #else + #define LV_USE_MEM_MONITOR 0 + #endif + #endif + #if LV_USE_MEM_MONITOR + #ifndef LV_USE_MEM_MONITOR_POS + #ifdef CONFIG_LV_USE_MEM_MONITOR_POS + #define LV_USE_MEM_MONITOR_POS CONFIG_LV_USE_MEM_MONITOR_POS + #else + #define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT + #endif + #endif + #endif + +#endif /*LV_USE_SYSMON*/ + +/*1: Enable the runtime performance profiler*/ +#ifndef LV_USE_PROFILER + #ifdef CONFIG_LV_USE_PROFILER + #define LV_USE_PROFILER CONFIG_LV_USE_PROFILER + #else + #define LV_USE_PROFILER 0 + #endif +#endif +#if LV_USE_PROFILER + /*1: Enable the built-in profiler*/ + #ifndef LV_USE_PROFILER_BUILTIN + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_PROFILER_BUILTIN + #define LV_USE_PROFILER_BUILTIN CONFIG_LV_USE_PROFILER_BUILTIN + #else + #define LV_USE_PROFILER_BUILTIN 0 + #endif + #else + #define LV_USE_PROFILER_BUILTIN 1 + #endif + #endif + #if LV_USE_PROFILER_BUILTIN + /*Default profiler trace buffer size*/ + #ifndef LV_PROFILER_BUILTIN_BUF_SIZE + #ifdef CONFIG_LV_PROFILER_BUILTIN_BUF_SIZE + #define LV_PROFILER_BUILTIN_BUF_SIZE CONFIG_LV_PROFILER_BUILTIN_BUF_SIZE + #else + #define LV_PROFILER_BUILTIN_BUF_SIZE (16 * 1024) /*[bytes]*/ + #endif + #endif + #endif + + /*Header to include for the profiler*/ + #ifndef LV_PROFILER_INCLUDE + #ifdef CONFIG_LV_PROFILER_INCLUDE + #define LV_PROFILER_INCLUDE CONFIG_LV_PROFILER_INCLUDE + #else + #define LV_PROFILER_INCLUDE "lvgl/src/misc/lv_profiler_builtin.h" + #endif + #endif + + /*Profiler start point function*/ + #ifndef LV_PROFILER_BEGIN + #ifdef CONFIG_LV_PROFILER_BEGIN + #define LV_PROFILER_BEGIN CONFIG_LV_PROFILER_BEGIN + #else + #define LV_PROFILER_BEGIN LV_PROFILER_BUILTIN_BEGIN + #endif + #endif + + /*Profiler end point function*/ + #ifndef LV_PROFILER_END + #ifdef CONFIG_LV_PROFILER_END + #define LV_PROFILER_END CONFIG_LV_PROFILER_END + #else + #define LV_PROFILER_END LV_PROFILER_BUILTIN_END + #endif + #endif + + /*Profiler start point function with custom tag*/ + #ifndef LV_PROFILER_BEGIN_TAG + #ifdef CONFIG_LV_PROFILER_BEGIN_TAG + #define LV_PROFILER_BEGIN_TAG CONFIG_LV_PROFILER_BEGIN_TAG + #else + #define LV_PROFILER_BEGIN_TAG LV_PROFILER_BUILTIN_BEGIN_TAG + #endif + #endif + + /*Profiler end point function with custom tag*/ + #ifndef LV_PROFILER_END_TAG + #ifdef CONFIG_LV_PROFILER_END_TAG + #define LV_PROFILER_END_TAG CONFIG_LV_PROFILER_END_TAG + #else + #define LV_PROFILER_END_TAG LV_PROFILER_BUILTIN_END_TAG + #endif + #endif +#endif + /*1: Enable Monkey test*/ #ifndef LV_USE_MONKEY #ifdef CONFIG_LV_USE_MONKEY @@ -2314,12 +2549,16 @@ #endif #endif -/*1: Enable a published subscriber based messaging system */ -#ifndef LV_USE_MSG - #ifdef CONFIG_LV_USE_MSG - #define LV_USE_MSG CONFIG_LV_USE_MSG +/*1: Enable an observer pattern implementation*/ +#ifndef LV_USE_OBSERVER + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_OBSERVER + #define LV_USE_OBSERVER CONFIG_LV_USE_OBSERVER + #else + #define LV_USE_OBSERVER 0 + #endif #else - #define LV_USE_MSG 0 + #define LV_USE_OBSERVER 1 #endif #endif @@ -2376,7 +2615,333 @@ #define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3 #endif #endif - #endif // LV_IME_PINYIN_USE_K9_MODE + #endif /*LV_IME_PINYIN_USE_K9_MODE*/ +#endif + +/*1: Enable file explorer*/ +/*Requires: lv_table*/ +#ifndef LV_USE_FILE_EXPLORER + #ifdef CONFIG_LV_USE_FILE_EXPLORER + #define LV_USE_FILE_EXPLORER CONFIG_LV_USE_FILE_EXPLORER + #else + #define LV_USE_FILE_EXPLORER 0 + #endif +#endif +#if LV_USE_FILE_EXPLORER + /*Maximum length of path*/ + #ifndef LV_FILE_EXPLORER_PATH_MAX_LEN + #ifdef CONFIG_LV_FILE_EXPLORER_PATH_MAX_LEN + #define LV_FILE_EXPLORER_PATH_MAX_LEN CONFIG_LV_FILE_EXPLORER_PATH_MAX_LEN + #else + #define LV_FILE_EXPLORER_PATH_MAX_LEN (128) + #endif + #endif + /*Quick access bar, 1:use, 0:not use*/ + /*Requires: lv_list*/ + #ifndef LV_FILE_EXPLORER_QUICK_ACCESS + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_FILE_EXPLORER_QUICK_ACCESS + #define LV_FILE_EXPLORER_QUICK_ACCESS CONFIG_LV_FILE_EXPLORER_QUICK_ACCESS + #else + #define LV_FILE_EXPLORER_QUICK_ACCESS 0 + #endif + #else + #define LV_FILE_EXPLORER_QUICK_ACCESS 1 + #endif + #endif +#endif + +/*================== + * DEVICES + *==================*/ + +/*Use SDL to open window on PC and handle mouse and keyboard*/ +#ifndef LV_USE_SDL + #ifdef CONFIG_LV_USE_SDL + #define LV_USE_SDL CONFIG_LV_USE_SDL + #else + #define LV_USE_SDL 0 + #endif +#endif +#if LV_USE_SDL + #ifndef LV_SDL_INCLUDE_PATH + #ifdef CONFIG_LV_SDL_INCLUDE_PATH + #define LV_SDL_INCLUDE_PATH CONFIG_LV_SDL_INCLUDE_PATH + #else + #define LV_SDL_INCLUDE_PATH + #endif + #endif + #ifndef LV_SDL_RENDER_MODE + #ifdef CONFIG_LV_SDL_RENDER_MODE + #define LV_SDL_RENDER_MODE CONFIG_LV_SDL_RENDER_MODE + #else + #define LV_SDL_RENDER_MODE LV_DISPLAY_RENDER_MODE_DIRECT /*LV_DISPLAY_RENDER_MODE_DIRECT is recommended for best performance*/ + #endif + #endif + #ifndef LV_SDL_BUF_COUNT + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_SDL_BUF_COUNT + #define LV_SDL_BUF_COUNT CONFIG_LV_SDL_BUF_COUNT + #else + #define LV_SDL_BUF_COUNT 0 + #endif + #else + #define LV_SDL_BUF_COUNT 1 /*1 or 2*/ + #endif + #endif + #ifndef LV_SDL_FULLSCREEN + #ifdef CONFIG_LV_SDL_FULLSCREEN + #define LV_SDL_FULLSCREEN CONFIG_LV_SDL_FULLSCREEN + #else + #define LV_SDL_FULLSCREEN 0 /*1: Make the window full screen by default*/ + #endif + #endif + #ifndef LV_SDL_DIRECT_EXIT + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_SDL_DIRECT_EXIT + #define LV_SDL_DIRECT_EXIT CONFIG_LV_SDL_DIRECT_EXIT + #else + #define LV_SDL_DIRECT_EXIT 0 + #endif + #else + #define LV_SDL_DIRECT_EXIT 1 /*1: Exit the application when all SDL windows are closed*/ + #endif + #endif +#endif + +/*Use X11 to open window on Linux desktop and handle mouse and keyboard*/ +#ifndef LV_USE_X11 + #ifdef CONFIG_LV_USE_X11 + #define LV_USE_X11 CONFIG_LV_USE_X11 + #else + #define LV_USE_X11 0 + #endif +#endif +#if LV_USE_X11 + #ifndef LV_X11_DIRECT_EXIT + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_X11_DIRECT_EXIT + #define LV_X11_DIRECT_EXIT CONFIG_LV_X11_DIRECT_EXIT + #else + #define LV_X11_DIRECT_EXIT 0 + #endif + #else + #define LV_X11_DIRECT_EXIT 1 /*Exit the application when all X11 windows have been closed*/ + #endif + #endif + #ifndef LV_X11_DOUBLE_BUFFER + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_X11_DOUBLE_BUFFER + #define LV_X11_DOUBLE_BUFFER CONFIG_LV_X11_DOUBLE_BUFFER + #else + #define LV_X11_DOUBLE_BUFFER 0 + #endif + #else + #define LV_X11_DOUBLE_BUFFER 1 /*Use double buffers for endering*/ + #endif + #endif + /*select only 1 of the following render modes (LV_X11_RENDER_MODE_PARTIAL preferred!)*/ + #ifndef LV_X11_RENDER_MODE_PARTIAL + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_X11_RENDER_MODE_PARTIAL + #define LV_X11_RENDER_MODE_PARTIAL CONFIG_LV_X11_RENDER_MODE_PARTIAL + #else + #define LV_X11_RENDER_MODE_PARTIAL 0 + #endif + #else + #define LV_X11_RENDER_MODE_PARTIAL 1 /*Partial render mode (preferred)*/ + #endif + #endif + #ifndef LV_X11_RENDER_MODE_DIRECT + #ifdef CONFIG_LV_X11_RENDER_MODE_DIRECT + #define LV_X11_RENDER_MODE_DIRECT CONFIG_LV_X11_RENDER_MODE_DIRECT + #else + #define LV_X11_RENDER_MODE_DIRECT 0 /*direct render mode*/ + #endif + #endif + #ifndef LV_X11_RENDER_MODE_FULL + #ifdef CONFIG_LV_X11_RENDER_MODE_FULL + #define LV_X11_RENDER_MODE_FULL CONFIG_LV_X11_RENDER_MODE_FULL + #else + #define LV_X11_RENDER_MODE_FULL 0 /*Full render mode*/ + #endif + #endif +#endif + +/*Driver for /dev/fb*/ +#ifndef LV_USE_LINUX_FBDEV + #ifdef CONFIG_LV_USE_LINUX_FBDEV + #define LV_USE_LINUX_FBDEV CONFIG_LV_USE_LINUX_FBDEV + #else + #define LV_USE_LINUX_FBDEV 0 + #endif +#endif +#if LV_USE_LINUX_FBDEV + #ifndef LV_LINUX_FBDEV_BSD + #ifdef CONFIG_LV_LINUX_FBDEV_BSD + #define LV_LINUX_FBDEV_BSD CONFIG_LV_LINUX_FBDEV_BSD + #else + #define LV_LINUX_FBDEV_BSD 0 + #endif + #endif + #ifndef LV_LINUX_FBDEV_RENDER_MODE + #ifdef CONFIG_LV_LINUX_FBDEV_RENDER_MODE + #define LV_LINUX_FBDEV_RENDER_MODE CONFIG_LV_LINUX_FBDEV_RENDER_MODE + #else + #define LV_LINUX_FBDEV_RENDER_MODE LV_DISPLAY_RENDER_MODE_PARTIAL + #endif + #endif + #ifndef LV_LINUX_FBDEV_BUFFER_COUNT + #ifdef CONFIG_LV_LINUX_FBDEV_BUFFER_COUNT + #define LV_LINUX_FBDEV_BUFFER_COUNT CONFIG_LV_LINUX_FBDEV_BUFFER_COUNT + #else + #define LV_LINUX_FBDEV_BUFFER_COUNT 0 + #endif + #endif + #ifndef LV_LINUX_FBDEV_BUFFER_SIZE + #ifdef CONFIG_LV_LINUX_FBDEV_BUFFER_SIZE + #define LV_LINUX_FBDEV_BUFFER_SIZE CONFIG_LV_LINUX_FBDEV_BUFFER_SIZE + #else + #define LV_LINUX_FBDEV_BUFFER_SIZE 60 + #endif + #endif +#endif + +/*Use Nuttx to open window and handle touchscreen*/ +#ifndef LV_USE_NUTTX + #ifdef CONFIG_LV_USE_NUTTX + #define LV_USE_NUTTX CONFIG_LV_USE_NUTTX + #else + #define LV_USE_NUTTX 0 + #endif +#endif + +#if LV_USE_NUTTX + #ifndef LV_USE_NUTTX_LIBUV + #ifdef CONFIG_LV_USE_NUTTX_LIBUV + #define LV_USE_NUTTX_LIBUV CONFIG_LV_USE_NUTTX_LIBUV + #else + #define LV_USE_NUTTX_LIBUV 0 + #endif + #endif + + /*Use Nuttx custom init API to open window and handle touchscreen*/ + #ifndef LV_USE_NUTTX_CUSTOM_INIT + #ifdef CONFIG_LV_USE_NUTTX_CUSTOM_INIT + #define LV_USE_NUTTX_CUSTOM_INIT CONFIG_LV_USE_NUTTX_CUSTOM_INIT + #else + #define LV_USE_NUTTX_CUSTOM_INIT 0 + #endif + #endif + + /*Driver for /dev/lcd*/ + #ifndef LV_USE_NUTTX_LCD + #ifdef CONFIG_LV_USE_NUTTX_LCD + #define LV_USE_NUTTX_LCD CONFIG_LV_USE_NUTTX_LCD + #else + #define LV_USE_NUTTX_LCD 0 + #endif + #endif + #if LV_USE_NUTTX_LCD + #ifndef LV_NUTTX_LCD_BUFFER_COUNT + #ifdef CONFIG_LV_NUTTX_LCD_BUFFER_COUNT + #define LV_NUTTX_LCD_BUFFER_COUNT CONFIG_LV_NUTTX_LCD_BUFFER_COUNT + #else + #define LV_NUTTX_LCD_BUFFER_COUNT 0 + #endif + #endif + #ifndef LV_NUTTX_LCD_BUFFER_SIZE + #ifdef CONFIG_LV_NUTTX_LCD_BUFFER_SIZE + #define LV_NUTTX_LCD_BUFFER_SIZE CONFIG_LV_NUTTX_LCD_BUFFER_SIZE + #else + #define LV_NUTTX_LCD_BUFFER_SIZE 60 + #endif + #endif + #endif + + /*Driver for /dev/input*/ + #ifndef LV_USE_NUTTX_TOUCHSCREEN + #ifdef CONFIG_LV_USE_NUTTX_TOUCHSCREEN + #define LV_USE_NUTTX_TOUCHSCREEN CONFIG_LV_USE_NUTTX_TOUCHSCREEN + #else + #define LV_USE_NUTTX_TOUCHSCREEN 0 + #endif + #endif + +#endif + +/*Driver for /dev/dri/card*/ +#ifndef LV_USE_LINUX_DRM + #ifdef CONFIG_LV_USE_LINUX_DRM + #define LV_USE_LINUX_DRM CONFIG_LV_USE_LINUX_DRM + #else + #define LV_USE_LINUX_DRM 0 + #endif +#endif + +/*Interface for TFT_eSPI*/ +#ifndef LV_USE_TFT_ESPI + #ifdef CONFIG_LV_USE_TFT_ESPI + #define LV_USE_TFT_ESPI CONFIG_LV_USE_TFT_ESPI + #else + #define LV_USE_TFT_ESPI 0 + #endif +#endif + +/*Driver for evdev input devices*/ +#ifndef LV_USE_EVDEV + #ifdef CONFIG_LV_USE_EVDEV + #define LV_USE_EVDEV CONFIG_LV_USE_EVDEV + #else + #define LV_USE_EVDEV 0 + #endif +#endif + +/*Drivers for LCD devices connected via SPI/parallel port*/ +#ifndef LV_USE_ST7735 + #ifdef CONFIG_LV_USE_ST7735 + #define LV_USE_ST7735 CONFIG_LV_USE_ST7735 + #else + #define LV_USE_ST7735 0 + #endif +#endif +#ifndef LV_USE_ST7789 + #ifdef CONFIG_LV_USE_ST7789 + #define LV_USE_ST7789 CONFIG_LV_USE_ST7789 + #else + #define LV_USE_ST7789 0 + #endif +#endif +#ifndef LV_USE_ST7796 + #ifdef CONFIG_LV_USE_ST7796 + #define LV_USE_ST7796 CONFIG_LV_USE_ST7796 + #else + #define LV_USE_ST7796 0 + #endif +#endif +#ifndef LV_USE_ILI9341 + #ifdef CONFIG_LV_USE_ILI9341 + #define LV_USE_ILI9341 CONFIG_LV_USE_ILI9341 + #else + #define LV_USE_ILI9341 0 + #endif +#endif + +#ifndef LV_USE_GENERIC_MIPI + #ifdef CONFIG_LV_USE_GENERIC_MIPI + #define LV_USE_GENERIC_MIPI CONFIG_LV_USE_GENERIC_MIPI + #else + #define LV_USE_GENERIC_MIPI (LV_USE_ST7735 | LV_USE_ST7789 | LV_USE_ST7796 | LV_USE_ILI9341) + #endif +#endif + +/* LVGL Windows backend */ +#ifndef LV_USE_WINDOWS + #ifdef CONFIG_LV_USE_WINDOWS + #define LV_USE_WINDOWS CONFIG_LV_USE_WINDOWS + #else + #define LV_USE_WINDOWS 0 + #endif #endif /*================== @@ -2409,14 +2974,14 @@ #endif #endif #if LV_USE_DEMO_WIDGETS -#ifndef LV_DEMO_WIDGETS_SLIDESHOW - #ifdef CONFIG_LV_DEMO_WIDGETS_SLIDESHOW - #define LV_DEMO_WIDGETS_SLIDESHOW CONFIG_LV_DEMO_WIDGETS_SLIDESHOW - #else - #define LV_DEMO_WIDGETS_SLIDESHOW 0 + #ifndef LV_DEMO_WIDGETS_SLIDESHOW + #ifdef CONFIG_LV_DEMO_WIDGETS_SLIDESHOW + #define LV_DEMO_WIDGETS_SLIDESHOW CONFIG_LV_DEMO_WIDGETS_SLIDESHOW + #else + #define LV_DEMO_WIDGETS_SLIDESHOW 0 + #endif #endif #endif -#endif /*Demonstrate the usage of encoder and keyboard*/ #ifndef LV_USE_DEMO_KEYPAD_AND_ENCODER @@ -2435,16 +3000,15 @@ #define LV_USE_DEMO_BENCHMARK 0 #endif #endif -#if LV_USE_DEMO_BENCHMARK -/*Use RGB565A8 images with 16 bit color depth instead of ARGB8565*/ -#ifndef LV_DEMO_BENCHMARK_RGB565A8 - #ifdef CONFIG_LV_DEMO_BENCHMARK_RGB565A8 - #define LV_DEMO_BENCHMARK_RGB565A8 CONFIG_LV_DEMO_BENCHMARK_RGB565A8 + +/*Render test for each primitives. Requires at least 480x272 display*/ +#ifndef LV_USE_DEMO_RENDER + #ifdef CONFIG_LV_USE_DEMO_RENDER + #define LV_USE_DEMO_RENDER CONFIG_LV_USE_DEMO_RENDER #else - #define LV_DEMO_BENCHMARK_RGB565A8 0 + #define LV_USE_DEMO_RENDER 0 #endif #endif -#endif /*Stress test for LVGL*/ #ifndef LV_USE_DEMO_STRESS @@ -2501,17 +3065,64 @@ #endif #endif +/*Flex layout demo*/ +#ifndef LV_USE_DEMO_FLEX_LAYOUT + #ifdef CONFIG_LV_USE_DEMO_FLEX_LAYOUT + #define LV_USE_DEMO_FLEX_LAYOUT CONFIG_LV_USE_DEMO_FLEX_LAYOUT + #else + #define LV_USE_DEMO_FLEX_LAYOUT 0 + #endif +#endif + +/*Smart-phone like multi-language demo*/ +#ifndef LV_USE_DEMO_MULTILANG + #ifdef CONFIG_LV_USE_DEMO_MULTILANG + #define LV_USE_DEMO_MULTILANG CONFIG_LV_USE_DEMO_MULTILANG + #else + #define LV_USE_DEMO_MULTILANG 0 + #endif +#endif + +/*Widget transformation demo*/ +#ifndef LV_USE_DEMO_TRANSFORM + #ifdef CONFIG_LV_USE_DEMO_TRANSFORM + #define LV_USE_DEMO_TRANSFORM CONFIG_LV_USE_DEMO_TRANSFORM + #else + #define LV_USE_DEMO_TRANSFORM 0 + #endif +#endif + +/*Demonstrate scroll settings*/ +#ifndef LV_USE_DEMO_SCROLL + #ifdef CONFIG_LV_USE_DEMO_SCROLL + #define LV_USE_DEMO_SCROLL CONFIG_LV_USE_DEMO_SCROLL + #else + #define LV_USE_DEMO_SCROLL 0 + #endif +#endif + +/*Vector graphic demo*/ +#ifndef LV_USE_DEMO_VECTOR_GRAPHIC + #ifdef CONFIG_LV_USE_DEMO_VECTOR_GRAPHIC + #define LV_USE_DEMO_VECTOR_GRAPHIC CONFIG_LV_USE_DEMO_VECTOR_GRAPHIC + #else + #define LV_USE_DEMO_VECTOR_GRAPHIC 0 + #endif +#endif /*---------------------------------- * End of parsing lv_conf_template.h -----------------------------------*/ +#ifndef __ASSEMBLY__ LV_EXPORT_CONST_INT(LV_DPI_DEF); +LV_EXPORT_CONST_INT(LV_DRAW_BUF_STRIDE_ALIGN); +LV_EXPORT_CONST_INT(LV_DRAW_BUF_ALIGN); +#endif #undef _LV_KCONFIG_PRESENT - /*Set some defines if a dependency is disabled*/ #if LV_USE_LOG == 0 #define LV_LOG_LEVEL LV_LOG_LEVEL_NONE diff --git a/lib/libesp32_lvgl/lvgl/src/lv_conf_kconfig.h b/lib/libesp32_lvgl/lvgl/src/lv_conf_kconfig.h index 80f706192..c5c971d4d 100644 --- a/lib/libesp32_lvgl/lvgl/src/lv_conf_kconfig.h +++ b/lib/libesp32_lvgl/lvgl/src/lv_conf_kconfig.h @@ -26,11 +26,51 @@ extern "C" { #endif /*LV_CONF_KCONFIG_EXTERNAL_INCLUDE*/ /******************* - * LV COLOR CHROMA KEY + * LV_USE_STDLIB_MALLOC *******************/ -#ifdef CONFIG_LV_COLOR_CHROMA_KEY_HEX -# define CONFIG_LV_COLOR_CHROMA_KEY lv_color_hex(CONFIG_LV_COLOR_CHROMA_KEY_HEX) +#ifdef CONFIG_LV_USE_BUILTIN_MALLOC +# define CONFIG_LV_USE_STDLIB_MALLOC LV_STDLIB_BUILTIN +#elif defined(CONFIG_LV_USE_CLIB_MALLOC) +# define CONFIG_LV_USE_STDLIB_MALLOC LV_STDLIB_CLIB +#elif defined(CONFIG_LV_USE_MICROPYTHON_MALLOC) +# define CONFIG_LV_USE_STDLIB_MALLOC LV_STDLIB_MICROPYTHON +#elif defined(CONFIG_LV_USE_RTTHREAD_MALLOC) +# define CONFIG_LV_USE_STDLIB_MALLOC LV_STDLIB_RTTHREAD +#elif defined (CONFIG_LV_USE_CUSTOM_MALLOC) +# define CONFIG_LV_USE_STDLIB_MALLOC LV_STDLIB_CUSTOM +#endif + +/******************* + * LV_USE_STDLIB_STRING + *******************/ + +#ifdef CONFIG_LV_USE_BUILTIN_STRING +# define CONFIG_LV_USE_STDLIB_STRING LV_STDLIB_BUILTIN +#elif defined(CONFIG_LV_USE_CLIB_STRING) +# define CONFIG_LV_USE_STDLIB_STRING LV_STDLIB_CLIB +#elif defined(CONFIG_LV_USE_MICROPYTHON_STRING) +# define CONFIG_LV_USE_STDLIB_STRING LV_STDLIB_MICROPYTHON +#elif defined(CONFIG_LV_USE_RTTHREAD_STRING) +# define CONFIG_LV_USE_STDLIB_STRING LV_STDLIB_RTTHREAD +#elif defined (CONFIG_LV_USE_CUSTOM_STRING) +# define CONFIG_LV_USE_STDLIB_STRING LV_STDLIB_CUSTOM +#endif + +/******************* + * LV_USE_STDLIB_SPRINTF + *******************/ + +#ifdef CONFIG_LV_USE_BUILTIN_SPRINTF +# define CONFIG_LV_USE_STDLIB_SPRINTF LV_STDLIB_BUILTIN +#elif defined(CONFIG_LV_USE_CLIB_SPRINTF) +# define CONFIG_LV_USE_STDLIB_SPRINTF LV_STDLIB_CLIB +#elif defined(CONFIG_LV_USE_MICROPYTHON_SPRINTF) +# define CONFIG_LV_USE_STDLIB_SPRINTF LV_STDLIB_MICROPYTHON +#elif defined(CONFIG_LV_USE_RTTHREAD_SPRINTF) +# define CONFIG_LV_USE_STDLIB_SPRINTF LV_STDLIB_RTTHREAD +#elif defined (CONFIG_LV_USE_CUSTOM_SPRINTF) +# define CONFIG_LV_USE_STDLIB_SPRINTF LV_STDLIB_CUSTOM #endif /******************* @@ -38,16 +78,24 @@ extern "C" { *******************/ #ifdef CONFIG_LV_MEM_SIZE_KILOBYTES +# if(CONFIG_LV_MEM_SIZE_KILOBYTES < 2) +# error "LV_MEM_SIZE >= 2kB is required" +# endif + # define CONFIG_LV_MEM_SIZE (CONFIG_LV_MEM_SIZE_KILOBYTES * 1024U) #endif +#ifdef CONFIG_LV_MEM_POOL_EXPAND_SIZE_KILOBYTES +# define CONFIG_LV_MEM_POOL_EXPAND_SIZE (CONFIG_LV_MEM_POOL_EXPAND_SIZE_KILOBYTES * 1024U) +#endif + /*------------------ * MONITOR POSITION *-----------------*/ #ifdef CONFIG_LV_PERF_MONITOR_ALIGN_TOP_LEFT # define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_TOP_LEFT -#elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_TOP_MID) +#elif defined(CONFIG_LV_USE_PERF_MONITOR_ALIGN_TOP_MID) # define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_TOP_MID #elif defined(CONFIG_LV_PERF_MONITOR_ALIGN_TOP_RIGHT) # define CONFIG_LV_USE_PERF_MONITOR_POS LV_ALIGN_TOP_RIGHT @@ -67,7 +115,7 @@ extern "C" { #ifdef CONFIG_LV_MEM_MONITOR_ALIGN_TOP_LEFT # define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_LEFT -#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_TOP_MID) +#elif defined(CONFIG_LV_USE_MEM_MONITOR_ALIGN_TOP_MID) # define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_MID #elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_TOP_RIGHT) # define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_RIGHT @@ -175,6 +223,18 @@ extern "C" { # define CONFIG_LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO #endif +/*------------------ + * LINUX FBDEV + *-----------------*/ + +#ifdef CONFIG_LV_LINUX_FBDEV_RENDER_MODE_PARTIAL +# define CONFIG_LV_LINUX_FBDEV_RENDER_MODE LV_DISPLAY_RENDER_MODE_PARTIAL +#elif defined(CONFIG_LV_LINUX_FBDEV_RENDER_MODE_DIRECT) +# define CONFIG_LV_LINUX_FBDEV_RENDER_MODE LV_DISPLAY_RENDER_MODE_DIRECT +#elif defined(CONFIG_LV_LINUX_FBDEV_RENDER_MODE_FULL) +# define CONFIG_LV_LINUX_FBDEV_RENDER_MODE LV_DISPLAY_RENDER_MODE_FULL +#endif + #ifdef __cplusplus } /*extern "C"*/ #endif diff --git a/lib/libesp32_lvgl/lvgl/src/lv_init.c b/lib/libesp32_lvgl/lvgl/src/lv_init.c new file mode 100644 index 000000000..eb36021f1 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/lv_init.c @@ -0,0 +1,416 @@ +/** + * @file lv_init.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "core/lv_global.h" +#include "core/lv_obj.h" +#include "display/lv_display_private.h" +#include "indev/lv_indev_private.h" +#include "layouts/lv_layout.h" +#include "libs/bin_decoder/lv_bin_decoder.h" +#include "libs/bmp/lv_bmp.h" +#include "libs/ffmpeg/lv_ffmpeg.h" +#include "libs/freetype/lv_freetype.h" +#include "libs/fsdrv/lv_fsdrv.h" +#include "libs/gif/lv_gif.h" +#include "libs/tjpgd/lv_tjpgd.h" +#include "libs/libjpeg_turbo/lv_libjpeg_turbo.h" +#include "libs/lodepng/lv_lodepng.h" +#include "libs/libpng/lv_libpng.h" +#include "draw/lv_draw.h" +#include "misc/lv_async.h" +#include "misc/lv_fs.h" +#if LV_USE_DRAW_VGLITE + #include "draw/nxp/vglite/lv_draw_vglite.h" +#endif +#if LV_USE_DRAW_PXP + #include "draw/nxp/pxp/lv_draw_pxp.h" +#endif +#if LV_USE_DRAW_DAVE2D + #include "draw/renesas/dave2d/lv_draw_dave2d.h" +#endif +#if LV_USE_DRAW_SDL + #include "draw/sdl/lv_draw_sdl.h" +#endif +#if LV_USE_DRAW_VG_LITE + #include "draw/vg_lite/lv_draw_vg_lite.h" +#endif +#if LV_USE_WINDOWS + #include "drivers/windows/lv_windows_context.h" +#endif + +/********************* + * DEFINES + *********************/ +#define lv_initialized LV_GLOBAL_DEFAULT()->inited +#define lv_deinit_in_progress LV_GLOBAL_DEFAULT()->deinit_in_progress + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ +#if LV_ENABLE_GLOBAL_CUSTOM == 0 + lv_global_t lv_global; +#endif + +/********************** + * MACROS + **********************/ + +#ifndef LV_GLOBAL_INIT + #define LV_GLOBAL_INIT(__GLOBAL_PTR) lv_global_init((lv_global_t *)(__GLOBAL_PTR)) +#endif + +/********************** + * GLOBAL FUNCTIONS + **********************/ +static inline void lv_global_init(lv_global_t * global) +{ + LV_ASSERT_NULL(global); + + if(global == NULL) { + LV_LOG_ERROR("lv_global cannot be null"); + return; + } + + lv_memzero(global, sizeof(lv_global_t)); + + _lv_ll_init(&(global->disp_ll), sizeof(lv_display_t)); + _lv_ll_init(&(global->indev_ll), sizeof(lv_indev_t)); + + global->memory_zero = ZERO_MEM_SENTINEL; + global->style_refresh = true; + global->layout_count = _LV_LAYOUT_LAST; + global->style_last_custom_prop_id = (uint32_t)_LV_STYLE_LAST_BUILT_IN_PROP; + global->area_trans_cache.angle_prev = INT32_MIN; + global->event_last_register_id = _LV_EVENT_LAST; + lv_rand_set_seed(0x1234ABCD); + +#if defined(LV_DRAW_SW_SHADOW_CACHE_SIZE) && LV_DRAW_SW_SHADOW_CACHE_SIZE > 0 + global->sw_shadow_cache.cache_size = -1; + global->sw_shadow_cache.cache_r = -1; +#endif +} + +static inline void _lv_cleanup_devices(lv_global_t * global) +{ + LV_ASSERT_NULL(global); + + if(global) { + /* cleanup indev and display */ + _lv_ll_clear_custom(&(global->indev_ll), (void (*)(void *)) lv_indev_delete); + _lv_ll_clear_custom(&(global->disp_ll), (void (*)(void *)) lv_display_delete); + } +} + +bool lv_is_initialized(void) +{ +#if LV_ENABLE_GLOBAL_CUSTOM + if(LV_GLOBAL_DEFAULT()) return lv_initialized; + else return false; +#else + return lv_initialized; +#endif +} + +void lv_init(void) +{ + /*First initialize Garbage Collection if needed*/ +#ifdef LV_GC_INIT + LV_GC_INIT(); +#endif + + /*Do nothing if already initialized*/ + if(lv_initialized) { + LV_LOG_WARN("lv_init: already initialized"); + return; + } + + LV_LOG_INFO("begin"); + + /*Initialize members of static variable lv_global */ + LV_GLOBAL_INIT(LV_GLOBAL_DEFAULT()); + + lv_mem_init(); + + _lv_draw_buf_init_handlers(); + +#if LV_USE_SPAN != 0 + lv_span_stack_init(); +#endif + +#if LV_USE_PROFILER && LV_USE_PROFILER_BUILTIN + lv_profiler_builtin_config_t profiler_config; + lv_profiler_builtin_config_init(&profiler_config); + lv_profiler_builtin_init(&profiler_config); +#endif + + _lv_timer_core_init(); + + _lv_fs_init(); + + _lv_layout_init(); + + _lv_anim_core_init(); + + _lv_group_init(); + + lv_draw_init(); + +#if LV_USE_DRAW_SW + lv_draw_sw_init(); +#endif + +#if LV_USE_DRAW_VGLITE + lv_draw_vglite_init(); +#endif + +#if LV_USE_DRAW_PXP + lv_draw_pxp_init(); +#endif + +#if LV_USE_DRAW_DAVE2D + lv_draw_dave2d_init(); +#endif + +#if LV_USE_DRAW_SDL + lv_draw_sdl_init(); +#endif + +#if LV_USE_WINDOWS + lv_windows_platform_init(); +#endif + + _lv_obj_style_init(); + + /*Initialize the screen refresh system*/ + _lv_refr_init(); + +#if LV_USE_SYSMON + _lv_sysmon_builtin_init(); +#endif + + _lv_image_decoder_init(); + lv_bin_decoder_init(); /*LVGL built-in binary image decoder*/ + +#if LV_USE_DRAW_VG_LITE + lv_draw_vg_lite_init(); +#endif + + /*Test if the IDE has UTF-8 encoding*/ + const char * txt = "Á"; + + uint8_t * txt_u8 = (uint8_t *)txt; + if(txt_u8[0] != 0xc3 || txt_u8[1] != 0x81 || txt_u8[2] != 0x00) { + LV_LOG_WARN("The strings have no UTF-8 encoding. Non-ASCII characters won't be displayed."); + } + + uint32_t endianness_test = 0x11223344; + uint8_t * endianness_test_p = (uint8_t *) &endianness_test; + bool big_endian = endianness_test_p[0] == 0x11; + + if(big_endian) { + LV_ASSERT_MSG(LV_BIG_ENDIAN_SYSTEM == 1, + "It's a big endian system but LV_BIG_ENDIAN_SYSTEM is not enabled in lv_conf.h"); + } + else { + LV_ASSERT_MSG(LV_BIG_ENDIAN_SYSTEM == 0, + "It's a little endian system but LV_BIG_ENDIAN_SYSTEM is enabled in lv_conf.h"); + } + +#if LV_USE_ASSERT_MEM_INTEGRITY + LV_LOG_WARN("Memory integrity checks are enabled via LV_USE_ASSERT_MEM_INTEGRITY which makes LVGL much slower"); +#endif + +#if LV_USE_ASSERT_OBJ + LV_LOG_WARN("Object sanity checks are enabled via LV_USE_ASSERT_OBJ which makes LVGL much slower"); +#endif + +#if LV_USE_ASSERT_STYLE + LV_LOG_WARN("Style sanity checks are enabled that uses more RAM"); +#endif + +#if LV_LOG_LEVEL == LV_LOG_LEVEL_TRACE + LV_LOG_WARN("Log level is set to 'Trace' which makes LVGL much slower"); +#endif + +#if LV_USE_FS_FATFS != '\0' + lv_fs_fatfs_init(); +#endif + +#if LV_USE_FS_STDIO != '\0' + lv_fs_stdio_init(); +#endif + +#if LV_USE_FS_POSIX != '\0' + lv_fs_posix_init(); +#endif + +#if LV_USE_FS_WIN32 != '\0' + lv_fs_win32_init(); +#endif + +#if LV_USE_FS_MEMFS + lv_fs_memfs_init(); +#endif + +#if LV_USE_LODEPNG + lv_lodepng_init(); +#endif + +#if LV_USE_LIBPNG + lv_libpng_init(); +#endif + +#if LV_USE_TJPGD + lv_tjpgd_init(); +#endif + +#if LV_USE_LIBJPEG_TURBO + lv_libjpeg_turbo_init(); +#endif + +#if LV_USE_BMP + lv_bmp_init(); +#endif + + /*Make FFMPEG last because the last converter will be checked first and + *it's superior to any other */ +#if LV_USE_FFMPEG + lv_ffmpeg_init(); +#endif + +// #if LV_USE_FREETYPE +// /*Init freetype library*/ +// # if LV_FREETYPE_CACHE_SIZE >= 0 +// lv_freetype_init(LV_FREETYPE_CACHE_FT_FACES, LV_FREETYPE_CACHE_FT_SIZES, LV_FREETYPE_CACHE_SIZE); +// # else +// lv_freetype_init(0, 0, 0); +// # endif +// #endif + +#if LV_USE_TINY_TTF + lv_tiny_ttf_init(); +#endif + + lv_initialized = true; + + LV_LOG_TRACE("finished"); +} + +void lv_deinit(void) +{ + /*Do nothing if already deinit*/ + if(!lv_initialized) { + LV_LOG_WARN("lv_deinit: already deinit!"); + return; + } + + if(lv_deinit_in_progress) return; + + lv_deinit_in_progress = true; + +#if LV_USE_SYSMON + _lv_sysmon_builtin_deinit(); +#endif + + lv_display_set_default(NULL); + + _lv_cleanup_devices(LV_GLOBAL_DEFAULT()); + +#if LV_USE_SPAN != 0 + lv_span_stack_deinit(); +#endif + +#if LV_USE_DRAW_SW + lv_draw_sw_deinit(); +#endif + +#if LV_USE_FREETYPE + lv_freetype_uninit(); +#endif + +#if LV_USE_TINY_TTF + lv_tiny_ttf_deinit(); +#endif + +#if LV_USE_THEME_DEFAULT + lv_theme_default_deinit(); +#endif + +#if LV_USE_THEME_SIMPLE + lv_theme_simple_deinit(); +#endif + +#if LV_USE_THEME_MONO + lv_theme_mono_deinit(); +#endif + + _lv_image_decoder_deinit(); + + _lv_refr_deinit(); + + _lv_obj_style_deinit(); + +#if LV_USE_DRAW_PXP + lv_draw_pxp_deinit(); +#endif + +#if LV_USE_DRAW_VGLITE + lv_draw_vglite_deinit(); +#endif + +#if LV_USE_DRAW_VG_LITE + lv_draw_vg_lite_deinit(); +#endif + +#if LV_USE_DRAW_SW + lv_draw_sw_deinit(); +#endif + + lv_draw_deinit(); + + _lv_group_deinit(); + + _lv_anim_core_deinit(); + + _lv_layout_deinit(); + + _lv_fs_deinit(); + + _lv_timer_core_deinit(); + +#if LV_USE_PROFILER && LV_USE_PROFILER_BUILTIN + lv_profiler_builtin_uninit(); +#endif + +#if LV_USE_OBJ_ID_BUILTIN + lv_objid_builtin_destroy(); +#endif + + lv_mem_deinit(); + + lv_initialized = false; + + LV_LOG_INFO("lv_deinit done"); + +#if LV_USE_LOG + lv_log_register_print_cb(NULL); +#endif + +} + +/********************** + * STATIC FUNCTIONS + **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/lv_init.h b/lib/libesp32_lvgl/lvgl/src/lv_init.h new file mode 100644 index 000000000..e5b551f05 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/lv_init.h @@ -0,0 +1,55 @@ +/** + * @file lv_init.h + * + */ + +#ifndef LV_INIT_H +#define LV_INIT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include "lv_conf_internal.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize LVGL library. + * Should be called before any other LVGL related function. + */ +void lv_init(void); + +/** + * Deinit the 'lv' library + */ +void lv_deinit(void); + +/** + * Returns whether the 'lv' library is currently initialized + */ +bool lv_is_initialized(void); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_INIT_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/lvgl.h b/lib/libesp32_lvgl/lvgl/src/lvgl.h index a7db27c36..e4533da11 100644 --- a/lib/libesp32_lvgl/lvgl/src/lvgl.h +++ b/lib/libesp32_lvgl/lvgl/src/lvgl.h @@ -13,8 +13,8 @@ extern "C" { /********************* * INCLUDES *********************/ - #include "../lvgl.h" +#include "lv_conf_internal.h" /********************* * DEFINES diff --git a/lib/libesp32_lvgl/lvgl/src/font/lv_font_loader.h b/lib/libesp32_lvgl/lvgl/src/lvgl_private.h similarity index 69% rename from lib/libesp32_lvgl/lvgl/src/font/lv_font_loader.h rename to lib/libesp32_lvgl/lvgl/src/lvgl_private.h index 783cb2e75..c6fc5990a 100644 --- a/lib/libesp32_lvgl/lvgl/src/font/lv_font_loader.h +++ b/lib/libesp32_lvgl/lvgl/src/lvgl_private.h @@ -1,10 +1,10 @@ /** - * @file lv_font_loader.h + * @file lvgl_private.h * */ -#ifndef LV_FONT_LOADER_H -#define LV_FONT_LOADER_H +#ifndef LVGL_PRIVATE_H +#define LVGL_PRIVATE_H #ifdef __cplusplus extern "C" { @@ -13,6 +13,8 @@ extern "C" { /********************* * INCLUDES *********************/ +#include "display/lv_display_private.h" +#include "indev/lv_indev_private.h" /********************* * DEFINES @@ -26,9 +28,6 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ -lv_font_t * lv_font_load(const char * fontName); -void lv_font_free(lv_font_t * font); - /********************** * MACROS **********************/ @@ -37,4 +36,4 @@ void lv_font_free(lv_font_t * font); } /*extern "C"*/ #endif -#endif /*LV_FONT_LOADER_H*/ +#endif /*LVGL_PRIVATE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/cache/_lv_cache_lru_rb.c b/lib/libesp32_lvgl/lvgl/src/misc/cache/_lv_cache_lru_rb.c new file mode 100644 index 000000000..18fcc5cc4 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/cache/_lv_cache_lru_rb.c @@ -0,0 +1,404 @@ +/** +* @file _lv_cache_lru_rb.c +* +*/ + +/********************* + * INCLUDES + *********************/ +#include "_lv_cache_lru_rb.h" +#include "../../stdlib/lv_sprintf.h" +#include "../../stdlib/lv_string.h" +#include "../lv_ll.h" +#include "../lv_rb.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef uint32_t (get_data_size_cb_t)(const void * data); + +struct _lv_lru_rb_t { + lv_cache_t cache; + + lv_rb_t rb; + lv_ll_t ll; + + get_data_size_cb_t * get_data_size_cb; +}; +typedef struct _lv_lru_rb_t lv_lru_rb_t_; +/********************** + * STATIC PROTOTYPES + **********************/ + +static void * alloc_cb(void); +static bool init_cnt_cb(lv_cache_t * cache); +static bool init_size_cb(lv_cache_t * cache); +static void destroy_cb(lv_cache_t * cache, void * user_data); + +static lv_cache_entry_t * get_cb(lv_cache_t * cache, const void * key, void * user_data); +static lv_cache_entry_t * add_cb(lv_cache_t * cache, const void * key, void * user_data); +static void remove_cb(lv_cache_t * cache, lv_cache_entry_t * entry, void * user_data); +static void drop_cb(lv_cache_t * cache, const void * key, void * user_data); +static void drop_all_cb(lv_cache_t * cache, void * user_data); + +static void * alloc_new_node(lv_lru_rb_t_ * lru, void * key, void * user_data); +inline static void ** get_lru_node(lv_lru_rb_t_ * lru, lv_rb_node_t * node); + +static uint32_t cnt_get_data_size_cb(const void * data); +static uint32_t size_get_data_size_cb(const void * data); + +/********************** + * GLOBAL VARIABLES + **********************/ +const lv_cache_class_t lv_cache_class_lru_rb_count = { + .alloc_cb = alloc_cb, + .init_cb = init_cnt_cb, + .destroy_cb = destroy_cb, + + .get_cb = get_cb, + .add_cb = add_cb, + .remove_cb = remove_cb, + .drop_cb = drop_cb, + .drop_all_cb = drop_all_cb +}; + +const lv_cache_class_t lv_cache_class_lru_rb_size = { + .alloc_cb = alloc_cb, + .init_cb = init_size_cb, + .destroy_cb = destroy_cb, + + .get_cb = get_cb, + .add_cb = add_cb, + .remove_cb = remove_cb, + .drop_cb = drop_cb, + .drop_all_cb = drop_all_cb +}; +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/********************** + * STATIC FUNCTIONS + **********************/ +static void * alloc_new_node(lv_lru_rb_t_ * lru, void * key, void * user_data) +{ + LV_UNUSED(user_data); + + LV_ASSERT_NULL(lru); + LV_ASSERT_NULL(key); + + if(lru == NULL || key == NULL) { + return NULL; + } + + lv_rb_node_t * node = lv_rb_insert(&lru->rb, key); + if(node == NULL) + goto FAILED_HANDLER2; + + void * data = node->data; + lv_cache_entry_t * entry = lv_cache_entry_get_entry(data, lru->cache.node_size); + lv_memcpy(data, key, lru->cache.node_size); + + void * lru_node = _lv_ll_ins_head(&lru->ll); + if(lru_node == NULL) + goto FAILED_HANDLER1; + + lv_memcpy(lru_node, &node, sizeof(void *)); + lv_memcpy(get_lru_node(lru, node), &lru_node, sizeof(void *)); + + lv_cache_entry_init(entry, &lru->cache, lru->cache.node_size); + goto FAILED_HANDLER2; + +FAILED_HANDLER1: + lv_rb_drop_node(&lru->rb, node); + node = NULL; +FAILED_HANDLER2: + return node; +} + +inline static void ** get_lru_node(lv_lru_rb_t_ * lru, lv_rb_node_t * node) +{ + return (void **)((char *)node->data + lru->rb.size - sizeof(void *)); +} + +static void * alloc_cb(void) +{ + void * res = lv_malloc(sizeof(lv_lru_rb_t_)); + LV_ASSERT_MALLOC(res); + if(res == NULL) { + LV_LOG_ERROR("malloc failed"); + return NULL; + } + + lv_memzero(res, sizeof(lv_lru_rb_t_)); + return res; +} + +static bool init_cnt_cb(lv_cache_t * cache) +{ + lv_lru_rb_t_ * lru = (lv_lru_rb_t_ *)cache; + + LV_ASSERT_NULL(lru->cache.ops.compare_cb); + LV_ASSERT_NULL(lru->cache.ops.free_cb); + LV_ASSERT(lru->cache.node_size > 0); + + if(lru->cache.node_size <= 0 || lru->cache.max_size <= 0 + || lru->cache.ops.compare_cb == NULL || lru->cache.ops.free_cb == NULL) { + return false; + } + + /*add void* to store the ll node pointer*/ + if(!lv_rb_init(&lru->rb, lru->cache.ops.compare_cb, lv_cache_entry_get_size(lru->cache.node_size) + sizeof(void *))) { + return NULL; + } + _lv_ll_init(&lru->ll, sizeof(void *)); + + lru->get_data_size_cb = cnt_get_data_size_cb; + + return lru; +} + +static bool init_size_cb(lv_cache_t * cache) +{ + lv_lru_rb_t_ * lru = (lv_lru_rb_t_ *)cache; + + LV_ASSERT_NULL(lru->cache.ops.compare_cb); + LV_ASSERT_NULL(lru->cache.ops.free_cb); + LV_ASSERT(lru->cache.node_size > 0); + + if(lru->cache.node_size <= 0 || lru->cache.max_size <= 0 + || lru->cache.ops.compare_cb == NULL || lru->cache.ops.free_cb == NULL) { + return false; + } + + /*add void* to store the ll node pointer*/ + if(!lv_rb_init(&lru->rb, lru->cache.ops.compare_cb, lv_cache_entry_get_size(lru->cache.node_size) + sizeof(void *))) { + return NULL; + } + _lv_ll_init(&lru->ll, sizeof(void *)); + + lru->get_data_size_cb = size_get_data_size_cb; + + return lru; +} + +static void destroy_cb(lv_cache_t * cache, void * user_data) +{ + LV_UNUSED(user_data); + + lv_lru_rb_t_ * lru = (lv_lru_rb_t_ *)cache; + + LV_ASSERT_NULL(lru); + + if(lru == NULL) { + return; + } + + cache->clz->drop_all_cb(cache, user_data); +} + +static lv_cache_entry_t * get_cb(lv_cache_t * cache, const void * key, void * user_data) +{ + LV_UNUSED(user_data); + + lv_lru_rb_t_ * lru = (lv_lru_rb_t_ *)cache; + + LV_ASSERT_NULL(lru); + LV_ASSERT_NULL(key); + + if(lru == NULL || key == NULL) { + return NULL; + } + + /*try the first ll node first*/ + void * head = _lv_ll_get_head(&lru->ll); + if(head) { + lv_rb_node_t * node = *(lv_rb_node_t **)head; + void * data = node->data; + lv_cache_entry_t * entry = lv_cache_entry_get_entry(data, cache->node_size); + if(lru->cache.ops.compare_cb(data, key) == 0) { + return entry; + } + } + + lv_rb_node_t * node = lv_rb_find(&lru->rb, key); + /*cache hit*/ + if(node) { + void * lru_node = *get_lru_node(lru, node); + head = _lv_ll_get_head(&lru->ll); + _lv_ll_move_before(&lru->ll, lru_node, head); + + lv_cache_entry_t * entry = lv_cache_entry_get_entry(node->data, cache->node_size); + return entry; + } + return NULL; +} + +static lv_cache_entry_t * add_cb(lv_cache_t * cache, const void * key, void * user_data) +{ + LV_UNUSED(user_data); + + lv_lru_rb_t_ * lru = (lv_lru_rb_t_ *)cache; + + LV_ASSERT_NULL(lru); + LV_ASSERT_NULL(key); + + if(lru == NULL || key == NULL) { + return NULL; + } + + uint32_t data_size = lru->get_data_size_cb(key); + if(data_size > lru->cache.max_size) { + LV_LOG_ERROR("data size (%" LV_PRIu32 ") is larger than max size (%" LV_PRIu32 ")", data_size, + (uint32_t)lru->cache.max_size); + return NULL; + } + + void * tail = _lv_ll_get_tail(&lru->ll); + void * curr = tail; + while(cache->size + data_size > lru->cache.max_size) { + if(curr == NULL) { + LV_LOG_ERROR("failed to drop cache"); + return NULL; + } + + lv_rb_node_t * tail_node = *(lv_rb_node_t **)curr; + void * search_key = tail_node->data; + lv_cache_entry_t * entry = lv_cache_entry_get_entry(search_key, cache->node_size); + if(lv_cache_entry_get_ref(entry) == 0) { + cache->clz->drop_cb(cache, search_key, user_data); + curr = _lv_ll_get_tail(&lru->ll); + continue; + } + + curr = _lv_ll_get_prev(&lru->ll, curr); + } + + /*cache miss*/ + lv_rb_node_t * new_node = alloc_new_node(lru, (void *)key, user_data); + if(new_node == NULL) { + return NULL; + } + + lv_cache_entry_t * entry = lv_cache_entry_get_entry(new_node->data, cache->node_size); + + cache->size += data_size; + + return entry; +} + +static void remove_cb(lv_cache_t * cache, lv_cache_entry_t * entry, void * user_data) +{ + LV_UNUSED(user_data); + + lv_lru_rb_t_ * lru = (lv_lru_rb_t_ *)cache; + + LV_ASSERT_NULL(lru); + LV_ASSERT_NULL(entry); + + if(lru == NULL || entry == NULL) { + return; + } + + void * data = lv_cache_entry_get_data(entry); + lv_rb_node_t * node = lv_rb_find(&lru->rb, data); + if(node == NULL) { + return; + } + + void * lru_node = *get_lru_node(lru, node); + lv_rb_remove_node(&lru->rb, node); + _lv_ll_remove(&lru->ll, lru_node); + lv_free(lru_node); + + cache->size -= lru->get_data_size_cb(data); +} + +static void drop_cb(lv_cache_t * cache, const void * key, void * user_data) +{ + lv_lru_rb_t_ * lru = (lv_lru_rb_t_ *)cache; + + LV_ASSERT_NULL(lru); + LV_ASSERT_NULL(key); + + if(lru == NULL || key == NULL) { + return; + } + + lv_rb_node_t * node = lv_rb_find(&lru->rb, key); + if(node == NULL) { + return; + } + + void * data = node->data; + + lru->cache.ops.free_cb(data, user_data); + cache->size -= lru->get_data_size_cb(data); + + lv_cache_entry_t * entry = lv_cache_entry_get_entry(data, cache->node_size); + void * lru_node = *get_lru_node(lru, node); + + lv_rb_remove_node(&lru->rb, node); + lv_cache_entry_delete(entry); + + _lv_ll_remove(&lru->ll, lru_node); + lv_free(lru_node); +} + +static void drop_all_cb(lv_cache_t * cache, void * user_data) +{ + lv_lru_rb_t_ * lru = (lv_lru_rb_t_ *)cache; + + LV_ASSERT_NULL(lru); + + if(lru == NULL) { + return; + } + + uint32_t used_cnt = 0; + lv_rb_node_t ** node; + _LV_LL_READ(&lru->ll, node) { + /*free user handled data and do other clean up*/ + void * search_key = (*node)->data; + lv_cache_entry_t * entry = lv_cache_entry_get_entry(search_key, cache->node_size); + if(lv_cache_entry_get_ref(entry) == 0) { + lru->cache.ops.free_cb(search_key, user_data); + } + else { + LV_LOG_WARN("entry (%p) is still referenced (%" LV_PRId32 ")", entry, lv_cache_entry_get_ref(entry)); + used_cnt++; + } + } + if(used_cnt > 0) { + LV_LOG_WARN("%" LV_PRId32 " entries are still referenced", used_cnt); + } + + lv_rb_destroy(&lru->rb); + _lv_ll_clear(&lru->ll); + + cache->size = 0; +} + +static uint32_t cnt_get_data_size_cb(const void * data) +{ + LV_UNUSED(data); + return 1; +} + +static uint32_t size_get_data_size_cb(const void * data) +{ + lv_cache_slot_size_t * slot = (lv_cache_slot_size_t *)data; + return slot->size; +} diff --git a/lib/libesp32_lvgl/lvgl/src/misc/cache/_lv_cache_lru_rb.h b/lib/libesp32_lvgl/lvgl/src/misc/cache/_lv_cache_lru_rb.h new file mode 100644 index 000000000..a27110b94 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/cache/_lv_cache_lru_rb.h @@ -0,0 +1,44 @@ +/** +* @file _lv_cache_lru_rb.h +* +*/ + +#ifndef LV_CACHE_LRU_RB_H +#define LV_CACHE_LRU_RB_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_cache_entry.h" +#include "lv_cache_private.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/************************* + * GLOBAL VARIABLES + *************************/ +LV_ATTRIBUTE_EXTERN_DATA extern const lv_cache_class_t lv_cache_class_lru_rb_count; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_cache_class_t lv_cache_class_lru_rb_size; +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_CACHE_LRU_RB_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache.c b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache.c new file mode 100644 index 000000000..46abe430c --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache.c @@ -0,0 +1,217 @@ +/** +* @file lv_cache.c +* +*/ + +/********************* + * INCLUDES + *********************/ +#include "lv_cache.h" +#include "../../stdlib/lv_sprintf.h" +#include "../lv_assert.h" +#include "lv_cache_entry_private.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void cache_drop_internal_no_lock(lv_cache_t * cache, const void * key, void * user_data); +/********************** + * GLOBAL VARIABLES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_cache_t * lv_cache_create(const lv_cache_class_t * cache_class, + size_t node_size, size_t max_size, + lv_cache_ops_t ops) +{ + lv_cache_t * cache = cache_class->alloc_cb(); + LV_ASSERT_MALLOC(cache); + + cache->clz = cache_class; + cache->node_size = node_size; + cache->max_size = max_size; + cache->size = 0; + cache->ops = ops; + + if(cache->clz->init_cb(cache) == false) { + LV_LOG_ERROR("Cache init failed"); + lv_free(cache); + return NULL; + } + + lv_mutex_init(&cache->lock); + + return cache; +} + +void lv_cache_destroy(lv_cache_t * cache, void * user_data) +{ + LV_ASSERT_NULL(cache); + + lv_mutex_lock(&cache->lock); + cache->clz->destroy_cb(cache, user_data); + lv_mutex_unlock(&cache->lock); + lv_mutex_delete(&cache->lock); + lv_free(cache); +} + +lv_cache_entry_t * lv_cache_acquire(lv_cache_t * cache, const void * key, void * user_data) +{ + LV_ASSERT_NULL(cache); + LV_ASSERT_NULL(key); + + lv_mutex_lock(&cache->lock); + lv_cache_entry_t * entry = cache->clz->get_cb(cache, key, user_data); + if(entry != NULL) { + lv_cache_entry_acquire_data(entry); + } + lv_mutex_unlock(&cache->lock); + return entry; +} +void lv_cache_release(lv_cache_t * cache, lv_cache_entry_t * entry, void * user_data) +{ + LV_ASSERT_NULL(entry); + + lv_mutex_lock(&cache->lock); + lv_cache_entry_release_data(entry, user_data); + + if(lv_cache_entry_get_ref(entry) == 0 && lv_cache_entry_is_invalid(entry)) { + cache->ops.free_cb(lv_cache_entry_get_data(entry), user_data); + lv_cache_entry_delete(entry); + } + lv_mutex_unlock(&cache->lock); +} +lv_cache_entry_t * lv_cache_add(lv_cache_t * cache, const void * key, void * user_data) +{ + LV_ASSERT_NULL(cache); + LV_ASSERT_NULL(key); + + lv_mutex_lock(&cache->lock); + lv_cache_entry_t * entry = cache->clz->add_cb(cache, key, user_data); + if(entry != NULL) { + lv_cache_entry_acquire_data(entry); + } + lv_mutex_unlock(&cache->lock); + return entry; +} +lv_cache_entry_t * lv_cache_acquire_or_create(lv_cache_t * cache, const void * key, void * user_data) +{ + LV_ASSERT_NULL(cache); + LV_ASSERT_NULL(key); + + lv_mutex_lock(&cache->lock); + lv_cache_entry_t * entry = cache->clz->get_cb(cache, key, user_data); + if(entry != NULL) { + lv_cache_entry_acquire_data(entry); + lv_mutex_unlock(&cache->lock); + return entry; + } + entry = cache->clz->add_cb(cache, key, user_data); + if(entry == NULL) { + lv_mutex_unlock(&cache->lock); + return NULL; + } + bool create_res = cache->ops.create_cb(lv_cache_entry_get_data(entry), user_data); + if(create_res == false) { + cache->clz->remove_cb(cache, entry, user_data); + lv_cache_entry_delete(entry); + entry = NULL; + } + else { + lv_cache_entry_acquire_data(entry); + } + lv_mutex_unlock(&cache->lock); + return entry; +} +void lv_cache_drop(lv_cache_t * cache, const void * key, void * user_data) +{ + LV_ASSERT_NULL(cache); + LV_ASSERT_NULL(key); + + lv_mutex_lock(&cache->lock); + cache_drop_internal_no_lock(cache, key, user_data); + lv_mutex_unlock(&cache->lock); +} +void lv_cache_drop_all(lv_cache_t * cache, void * user_data) +{ + LV_ASSERT_NULL(cache); + + lv_mutex_lock(&cache->lock); + cache->clz->drop_all_cb(cache, user_data); + lv_mutex_unlock(&cache->lock); +} + +void lv_cache_set_max_size(lv_cache_t * cache, size_t max_size, void * user_data) +{ + LV_UNUSED(user_data); + cache->max_size = max_size; +} +size_t lv_cache_get_max_size(lv_cache_t * cache, void * user_data) +{ + LV_UNUSED(user_data); + return cache->max_size; +} +size_t lv_cache_get_size(lv_cache_t * cache, void * user_data) +{ + LV_UNUSED(user_data); + return cache->size; +} +size_t lv_cache_get_free_size(lv_cache_t * cache, void * user_data) +{ + LV_UNUSED(user_data); + return cache->max_size - cache->size; +} +void lv_cache_set_compare_cb(lv_cache_t * cache, lv_cache_compare_cb_t compare_cb, void * user_data) +{ + LV_UNUSED(user_data); + cache->ops.compare_cb = compare_cb; +} +void lv_cache_set_create_cb(lv_cache_t * cache, lv_cache_create_cb_t alloc_cb, void * user_data) +{ + LV_UNUSED(user_data); + cache->ops.create_cb = alloc_cb; +} +void lv_cache_set_free_cb(lv_cache_t * cache, lv_cache_free_cb_t free_cb, void * user_data) +{ + LV_UNUSED(user_data); + cache->ops.free_cb = free_cb; +} +/********************** + * STATIC FUNCTIONS + **********************/ +static void cache_drop_internal_no_lock(lv_cache_t * cache, const void * key, void * user_data) +{ + lv_cache_entry_t * entry = cache->clz->get_cb(cache, key, user_data); + if(entry == NULL) { + return; + } + + if(lv_cache_entry_get_ref(entry) == 0) { + cache->clz->remove_cb(cache, entry, user_data); + cache->ops.free_cb(lv_cache_entry_get_data(entry), user_data); + lv_cache_entry_delete(entry); + } + else { + lv_cache_entry_set_invalid(entry, true); + cache->clz->remove_cb(cache, entry, user_data); + } +} diff --git a/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache.h b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache.h new file mode 100644 index 000000000..c79a00e76 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache.h @@ -0,0 +1,67 @@ +/** +* @file lv_cache.h +* +*/ + +#ifndef LV_CACHE1_H +#define LV_CACHE1_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_cache_entry.h" +#include "lv_cache_private.h" +#include +#include + +#include "_lv_cache_lru_rb.h" + +#include "lv_image_cache.h" +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +lv_cache_t * lv_cache_create(const lv_cache_class_t * cache_class, + size_t node_size, size_t max_size, + lv_cache_ops_t ops); +void lv_cache_destroy(lv_cache_t * cache, void * user_data); + +lv_cache_entry_t * lv_cache_acquire(lv_cache_t * cache, const void * key, void * user_data); +lv_cache_entry_t * lv_cache_acquire_or_create(lv_cache_t * cache, const void * key, void * user_data); +lv_cache_entry_t * lv_cache_add(lv_cache_t * cache, const void * key, void * user_data); +void lv_cache_release(lv_cache_t * cache, lv_cache_entry_t * entry, void * user_data); +void lv_cache_drop(lv_cache_t * cache, const void * key, void * user_data); +void lv_cache_drop_all(lv_cache_t * cache, void * user_data); + +void lv_cache_set_max_size(lv_cache_t * cache, size_t max_size, void * user_data); +size_t lv_cache_get_max_size(lv_cache_t * cache, void * user_data); +size_t lv_cache_get_size(lv_cache_t * cache, void * user_data); +size_t lv_cache_get_free_size(lv_cache_t * cache, void * user_data); + +void lv_cache_set_compare_cb(lv_cache_t * cache, lv_cache_compare_cb_t compare_cb, void * user_data); +void lv_cache_set_create_cb(lv_cache_t * cache, lv_cache_create_cb_t alloc_cb, void * user_data); +void lv_cache_set_free_cb(lv_cache_t * cache, lv_cache_free_cb_t free_cb, void * user_data); +/************************* + * GLOBAL VARIABLES + *************************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_CACHE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_entry.c b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_entry.c new file mode 100644 index 000000000..242e1a0f2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_entry.c @@ -0,0 +1,167 @@ +/** +* @file lv_cache_entry.c +* + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_cache_entry.h" +#include "../../stdlib/lv_sprintf.h" +#include "../lv_assert.h" +#include "lv_cache.h" +#include "lv_cache_entry_private.h" +#include "lv_cache_private.h" +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +struct _lv_cache_entry_t { + const lv_cache_t * cache; + int32_t ref_cnt; + uint32_t node_size; + + bool is_invalid; +}; +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * GLOBAL VARIABLES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_cache_entry_reset_ref(lv_cache_entry_t * entry) +{ + LV_ASSERT_NULL(entry); + entry->ref_cnt = 0; +} +void lv_cache_entry_inc_ref(lv_cache_entry_t * entry) +{ + LV_ASSERT_NULL(entry); + entry->ref_cnt++; +} +void lv_cache_entry_dec_ref(lv_cache_entry_t * entry) +{ + LV_ASSERT_NULL(entry); + entry->ref_cnt--; + if(entry->ref_cnt < 0) { + LV_LOG_WARN("ref_cnt(%" LV_PRIu32 ") < 0", entry->ref_cnt); + entry->ref_cnt = 0; + } +} +int32_t lv_cache_entry_get_ref(lv_cache_entry_t * entry) +{ + LV_ASSERT_NULL(entry); + return entry->ref_cnt; +} +uint32_t lv_cache_entry_get_node_size(lv_cache_entry_t * entry) +{ + return entry->node_size; +} +void lv_cache_entry_set_node_size(lv_cache_entry_t * entry, uint32_t node_size) +{ + LV_ASSERT_NULL(entry); + entry->node_size = node_size; +} +void lv_cache_entry_set_invalid(lv_cache_entry_t * entry, bool is_invalid) +{ + LV_ASSERT_NULL(entry); + entry->is_invalid = is_invalid; +} +bool lv_cache_entry_is_invalid(lv_cache_entry_t * entry) +{ + LV_ASSERT_NULL(entry); + return entry->is_invalid; +} +void * lv_cache_entry_get_data(lv_cache_entry_t * entry) +{ + LV_ASSERT_NULL(entry); + return (uint8_t *)entry - entry->node_size; +} +void * lv_cache_entry_acquire_data(lv_cache_entry_t * entry) +{ + LV_ASSERT_NULL(entry); + + lv_cache_entry_inc_ref(entry); + return lv_cache_entry_get_data(entry); +} +void lv_cache_entry_release_data(lv_cache_entry_t * entry, void * user_data) +{ + LV_UNUSED(user_data); + + LV_ASSERT_NULL(entry); + if(lv_cache_entry_get_ref(entry) == 0) { + LV_LOG_ERROR("ref_cnt(%" LV_PRIu32 ") == 0", entry->ref_cnt); + return; + } + + lv_cache_entry_dec_ref(entry); +} +lv_cache_entry_t * lv_cache_entry_get_entry(void * data, const uint32_t node_size) +{ + LV_ASSERT_NULL(data); + return (lv_cache_entry_t *)((uint8_t *)data + node_size); +} +void lv_cache_entry_set_cache(lv_cache_entry_t * entry, const lv_cache_t * cache) +{ + LV_ASSERT_NULL(entry); + entry->cache = cache; +} +const lv_cache_t * lv_cache_entry_get_cache(const lv_cache_entry_t * entry) +{ + LV_ASSERT_NULL(entry); + return entry->cache; +} + +uint32_t lv_cache_entry_get_size(const uint32_t node_size) +{ + return node_size + sizeof(lv_cache_entry_t); +} +lv_cache_entry_t * lv_cache_entry_alloc(const uint32_t node_size, const lv_cache_t * cache) +{ + void * res = lv_malloc_zeroed(lv_cache_entry_get_size(node_size)); + LV_ASSERT_MALLOC(res) + if(res == NULL) { + LV_LOG_ERROR("malloc failed"); + return NULL; + } + lv_cache_entry_t * entry = (lv_cache_entry_t *)res; + lv_cache_entry_init(entry, cache, node_size); + return (lv_cache_entry_t *)((uint8_t *)entry + node_size); +} +void lv_cache_entry_init(lv_cache_entry_t * entry, const lv_cache_t * cache, const uint32_t node_size) +{ + LV_ASSERT_NULL(entry); + LV_ASSERT_NULL(cache); + + entry->cache = cache; + entry->node_size = node_size; + entry->ref_cnt = 0; + entry->is_invalid = false; +} +void lv_cache_entry_delete(lv_cache_entry_t * entry) +{ + LV_ASSERT_NULL(entry); + + void * data = lv_cache_entry_get_data(entry); + lv_free(data); +} +/********************** + * STATIC FUNCTIONS + **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_entry.h b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_entry.h new file mode 100644 index 000000000..c2f8585ea --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_entry.h @@ -0,0 +1,55 @@ +/** +* @file lv_cache_entry.h +* + */ + +#ifndef LV_CACHE_ENTRY_H +#define LV_CACHE_ENTRY_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../osal/lv_os.h" +#include "../lv_types.h" +#include "lv_cache_private.h" +#include +#include +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +uint32_t lv_cache_entry_get_size(const uint32_t node_size); +int32_t lv_cache_entry_get_ref(lv_cache_entry_t * entry); +uint32_t lv_cache_entry_get_node_size(lv_cache_entry_t * entry); +bool lv_cache_entry_is_invalid(lv_cache_entry_t * entry); +void * lv_cache_entry_get_data(lv_cache_entry_t * entry); +const lv_cache_t * lv_cache_entry_get_cache(const lv_cache_entry_t * entry); +lv_cache_entry_t * lv_cache_entry_get_entry(void * data, const uint32_t node_size); + +lv_cache_entry_t * lv_cache_entry_alloc(const uint32_t node_size, const lv_cache_t * cache); +void lv_cache_entry_init(lv_cache_entry_t * entry, const lv_cache_t * cache, const uint32_t node_size); +void lv_cache_entry_delete(lv_cache_entry_t * entry); +/************************* + * GLOBAL VARIABLES + *************************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_CACHE_ENTRY_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_entry_private.h b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_entry_private.h new file mode 100644 index 000000000..227585e1e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_entry_private.h @@ -0,0 +1,51 @@ +/** +* @file lv_cache_entry_private.h +* + */ + +#ifndef LV_CACHE_ENTRY_PRIVATE +#define LV_CACHE_ENTRY_PRIVATE + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_types.h" +#include +#include +#include "../../osal/lv_os.h" +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +void lv_cache_entry_reset_ref(lv_cache_entry_t * entry); +void lv_cache_entry_inc_ref(lv_cache_entry_t * entry); +void lv_cache_entry_dec_ref(lv_cache_entry_t * entry); +void lv_cache_entry_set_node_size(lv_cache_entry_t * entry, uint32_t node_size); +void lv_cache_entry_set_invalid(lv_cache_entry_t * entry, bool is_invalid); +void lv_cache_entry_set_cache(lv_cache_entry_t * entry, const lv_cache_t * cache); +void * lv_cache_entry_acquire_data(lv_cache_entry_t * entry); +void lv_cache_entry_release_data(lv_cache_entry_t * entry, void * user_data); +/************************* + * GLOBAL VARIABLES + *************************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_CACHE_ENTRY_PRIVATE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_private.h b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_private.h new file mode 100644 index 000000000..7a83e04d0 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_cache_private.h @@ -0,0 +1,114 @@ +/** +* @file lv_cache_private.h +* +*/ + +#ifndef LV_CACHE_PRIVATE_H +#define LV_CACHE_PRIVATE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_types.h" +#include +#include +#include "../../osal/lv_os.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/*----------------- + * Cache entry slot + *----------------*/ +struct _lv_cache_ops_t; +struct _lv_cache_t; +struct _lv_cache_class_t; +struct _lv_cache_entry_t; + +typedef struct _lv_cache_ops_t lv_cache_ops_t; +typedef struct _lv_cache_t lv_cache_t; +typedef struct _lv_cache_class_t lv_cache_class_t; +typedef struct _lv_cache_entry_t lv_cache_entry_t; + +typedef int8_t lv_cache_compare_res_t; +typedef bool (*lv_cache_create_cb_t)(void * node, void * user_data); +typedef void (*lv_cache_free_cb_t)(void * node, void * user_data); +typedef lv_cache_compare_res_t (*lv_cache_compare_cb_t)(const void * a, const void * b); + +typedef void * (*lv_cache_alloc_cb_t)(void); +typedef bool (*lv_cache_init_cb_t)(lv_cache_t * cache); +typedef void (*lv_cache_destroy_cb_t)(lv_cache_t * cache, void * user_data); +typedef lv_cache_entry_t * (*lv_cache_get_cb_t)(lv_cache_t * cache, const void * key, void * user_data); +typedef lv_cache_entry_t * (*lv_cache_add_cb_t)(lv_cache_t * cache, const void * key, void * user_data); +typedef void (*lv_cache_remove_cb_t)(lv_cache_t * cache, lv_cache_entry_t * entry, void * user_data); +typedef void (*lv_cache_drop_cb_t)(lv_cache_t * cache, const void * key, void * user_data); +typedef void (*lv_cache_clear_cb_t)(lv_cache_t * cache, void * user_data); + +struct _lv_cache_ops_t { + lv_cache_compare_cb_t compare_cb; + lv_cache_create_cb_t create_cb; + lv_cache_free_cb_t free_cb; +}; + +struct _lv_cache_t { + const lv_cache_class_t * clz; + + size_t node_size; + + size_t max_size; + size_t size; + + lv_cache_ops_t ops; + + lv_mutex_t lock; +}; + +struct _lv_cache_class_t { + lv_cache_alloc_cb_t alloc_cb; + lv_cache_init_cb_t init_cb; + lv_cache_destroy_cb_t destroy_cb; + + lv_cache_get_cb_t get_cb; + lv_cache_add_cb_t add_cb; + lv_cache_remove_cb_t remove_cb; + lv_cache_drop_cb_t drop_cb; + lv_cache_clear_cb_t drop_all_cb; +}; + +/*----------------- + * Cache entry slot + *----------------*/ + +struct _lv_cache_slot_size_t; + +typedef struct _lv_cache_slot_size_t lv_cache_slot_size_t; + +struct _lv_cache_slot_size_t { + size_t size; +}; +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/************************* + * GLOBAL VARIABLES + *************************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_CACHE_PRIVATE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_image_cache.c b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_image_cache.c new file mode 100644 index 000000000..728224669 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_image_cache.c @@ -0,0 +1,59 @@ +/** +* @file lv_image_cache.c +* + */ + +/********************* + * INCLUDES + *********************/ +#include "../lv_assert.h" +#include "lv_image_cache.h" +#include "../../core/lv_global.h" +/********************* + * DEFINES + *********************/ +#define img_cache_p (LV_GLOBAL_DEFAULT()->img_cache) +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * GLOBAL VARIABLES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ +void lv_image_cache_drop(const void * src) +{ +#if LV_CACHE_DEF_SIZE > 0 + if(src == NULL) { + lv_cache_drop_all(img_cache_p, NULL); + return; + } + + lv_image_cache_data_t search_key = { + .src = src, + .src_type = lv_image_src_get_type(src), + }; + + lv_cache_drop(img_cache_p, &search_key, NULL); +#else + LV_UNUSED(src); +#endif +} +/********************** + * STATIC FUNCTIONS + **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/layouts/lv_layouts.h b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_image_cache.h similarity index 60% rename from lib/libesp32_lvgl/lvgl/src/extra/layouts/lv_layouts.h rename to lib/libesp32_lvgl/lvgl/src/misc/cache/lv_image_cache.h index 9c1e958d6..3b23b3dfb 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/layouts/lv_layouts.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/cache/lv_image_cache.h @@ -1,10 +1,10 @@ /** - * @file lv_layouts.h - * +* @file lv_image_cache.h +* */ -#ifndef LV_LAYOUTS_H -#define LV_LAYOUTS_H +#ifndef LV_IMAGE_CACHE_H +#define LV_IMAGE_CACHE_H #ifdef __cplusplus extern "C" { @@ -13,8 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "flex/lv_flex.h" -#include "grid/lv_grid.h" +#include "lv_cache_private.h" /********************* * DEFINES @@ -27,18 +26,17 @@ extern "C" { /********************** * GLOBAL PROTOTYPES **********************/ +void lv_image_cache_drop(const void * src); +/************************* + * GLOBAL VARIABLES + *************************/ /********************** * MACROS **********************/ -#if LV_USE_LOG && LV_LOG_TRACE_LAYOUT -# define LV_TRACE_LAYOUT(...) LV_LOG_TRACE(__VA_ARGS__) -#else -# define LV_TRACE_LAYOUT(...) -#endif #ifdef __cplusplus } /*extern "C"*/ #endif -#endif /*LV_LAYOUTS_H*/ +#endif /*LV_IMAGE_CACHE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.c index 4e4253a6e..8d88372a2 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.c @@ -8,18 +8,21 @@ *********************/ #include "lv_anim.h" -#include "../hal/lv_hal_tick.h" +#include "../core/lv_global.h" +#include "../tick/lv_tick.h" #include "lv_assert.h" #include "lv_timer.h" #include "lv_math.h" -#include "lv_mem.h" -#include "lv_gc.h" +#include "../stdlib/lv_mem.h" +#include "../stdlib/lv_string.h" /********************* * DEFINES *********************/ #define LV_ANIM_RESOLUTION 1024 #define LV_ANIM_RES_SHIFT 10 +#define state LV_GLOBAL_DEFAULT()->anim_state +#define anim_ll_p &(state.anim_ll) /********************** * TYPEDEFS @@ -30,42 +33,49 @@ **********************/ static void anim_timer(lv_timer_t * param); static void anim_mark_list_change(void); -static void anim_ready_handler(lv_anim_t * a); +static void anim_completed_handler(lv_anim_t * a); +static int32_t lv_anim_path_cubic_bezier(const lv_anim_t * a, int32_t x1, + int32_t y1, int32_t x2, int32_t y2); +static uint32_t convert_speed_to_time(uint32_t speed, int32_t start, int32_t end); +static void resolve_time(lv_anim_t * a); +static bool remove_concurrent_anims(lv_anim_t * a_current); +static bool delete_core(void * var, void * cb, bool custom_exec_cb); /********************** * STATIC VARIABLES **********************/ -static uint32_t last_timer_run; -static bool anim_list_changed; -static bool anim_run_round; -static lv_timer_t * _lv_anim_tmr; /********************** * MACROS **********************/ -#if LV_LOG_TRACE_ANIM - #define TRACE_ANIM(...) LV_LOG_TRACE(__VA_ARGS__) +#if LV_USE_LOG && LV_LOG_TRACE_ANIM + #define LV_TRACE_ANIM(...) LV_LOG_TRACE(__VA_ARGS__) #else - #define TRACE_ANIM(...) + #define LV_TRACE_ANIM(...) #endif - /********************** * GLOBAL FUNCTIONS **********************/ void _lv_anim_core_init(void) { - _lv_ll_init(&LV_GC_ROOT(_lv_anim_ll), sizeof(lv_anim_t)); - _lv_anim_tmr = lv_timer_create(anim_timer, LV_DISP_DEF_REFR_PERIOD, NULL); + _lv_ll_init(anim_ll_p, sizeof(lv_anim_t)); + state.timer = lv_timer_create(anim_timer, LV_DEF_REFR_PERIOD, NULL); anim_mark_list_change(); /*Turn off the animation timer*/ - anim_list_changed = false; + state.anim_list_changed = false; + state.anim_run_round = false; +} + +void _lv_anim_core_deinit(void) +{ + lv_anim_delete_all(); } void lv_anim_init(lv_anim_t * a) { - lv_memset_00(a, sizeof(lv_anim_t)); - a->time = 500; + lv_memzero(a, sizeof(lv_anim_t)); + a->duration = 500; a->start_value = 0; a->end_value = 100; a->repeat_cnt = 1; @@ -75,25 +85,18 @@ void lv_anim_init(lv_anim_t * a) lv_anim_t * lv_anim_start(const lv_anim_t * a) { - TRACE_ANIM("begin"); - - /*Do not let two animations for the same 'var' with the same 'exec_cb'*/ - if(a->exec_cb != NULL) lv_anim_del(a->var, a->exec_cb); /*exec_cb == NULL would delete all animations of var*/ - - /*If the list is empty the anim timer was suspended and it's last run measure is invalid*/ - if(_lv_ll_is_empty(&LV_GC_ROOT(_lv_anim_ll))) { - last_timer_run = lv_tick_get(); - } + LV_TRACE_ANIM("begin"); /*Add the new animation to the animation linked list*/ - lv_anim_t * new_anim = _lv_ll_ins_head(&LV_GC_ROOT(_lv_anim_ll)); + lv_anim_t * new_anim = _lv_ll_ins_head(anim_ll_p); LV_ASSERT_MALLOC(new_anim); if(new_anim == NULL) return NULL; /*Initialize the animation descriptor*/ lv_memcpy(new_anim, a, sizeof(lv_anim_t)); if(a->var == a) new_anim->var = new_anim; - new_anim->run_round = anim_run_round; + new_anim->run_round = state.anim_run_round; + new_anim->last_timer_run = lv_tick_get(); /*Set the start value*/ if(new_anim->early_apply) { @@ -101,75 +104,59 @@ lv_anim_t * lv_anim_start(const lv_anim_t * a) int32_t v_ofs = new_anim->get_value_cb(new_anim); new_anim->start_value += v_ofs; new_anim->end_value += v_ofs; + } - if(new_anim->exec_cb && new_anim->var) new_anim->exec_cb(new_anim->var, new_anim->start_value); + resolve_time(new_anim); + + /*Do not let two animations for the same 'var' with the same 'exec_cb'*/ + if(a->exec_cb || a->custom_exec_cb) remove_concurrent_anims(new_anim); + + if(new_anim->exec_cb) { + new_anim->exec_cb(new_anim->var, new_anim->start_value); + } + if(new_anim->custom_exec_cb) { + new_anim->custom_exec_cb(new_anim, new_anim->start_value); + } } /*Creating an animation changed the linked list. *It's important if it happens in a ready callback. (see `anim_timer`)*/ anim_mark_list_change(); - TRACE_ANIM("finished"); + LV_TRACE_ANIM("finished"); return new_anim; } -uint32_t lv_anim_get_playtime(lv_anim_t * a) +uint32_t lv_anim_get_playtime(const lv_anim_t * a) { - uint32_t playtime = LV_ANIM_PLAYTIME_INFINITE; + if(a->repeat_cnt == LV_ANIM_REPEAT_INFINITE) { + return LV_ANIM_PLAYTIME_INFINITE; + } - if(a->repeat_cnt == LV_ANIM_REPEAT_INFINITE) - return playtime; - - playtime = a->time - a->act_time; - if(a->playback_now == 0) - playtime += a->playback_delay + a->playback_time; - - if(a->repeat_cnt <= 1) - return playtime; - - playtime += (a->repeat_delay + a->time + - a->playback_delay + a->playback_time) * - (a->repeat_cnt - 1); + uint32_t repeate_cnt = a->repeat_cnt; + if(repeate_cnt < 1) repeate_cnt = 1; + uint32_t playtime = a->repeat_delay + a->duration + a->playback_delay + a->playback_duration; + playtime = playtime * a->repeat_cnt; return playtime; } -bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb) +bool lv_anim_delete(void * var, lv_anim_exec_xcb_t exec_cb) { - lv_anim_t * a; - lv_anim_t * a_next; - bool del = false; - a = _lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll)); - while(a != NULL) { - /*'a' might be deleted, so get the next object while 'a' is valid*/ - a_next = _lv_ll_get_next(&LV_GC_ROOT(_lv_anim_ll), a); - - if((a->var == var || var == NULL) && (a->exec_cb == exec_cb || exec_cb == NULL)) { - _lv_ll_remove(&LV_GC_ROOT(_lv_anim_ll), a); - if(a->deleted_cb != NULL) a->deleted_cb(a); - lv_mem_free(a); - anim_mark_list_change(); /*Read by `anim_timer`. It need to know if a delete occurred in - the linked list*/ - del = true; - } - - a = a_next; - } - - return del; + return delete_core(var, exec_cb, false); } -void lv_anim_del_all(void) +void lv_anim_delete_all(void) { - _lv_ll_clear(&LV_GC_ROOT(_lv_anim_ll)); + _lv_ll_clear(anim_ll_p); anim_mark_list_change(); } lv_anim_t * lv_anim_get(void * var, lv_anim_exec_xcb_t exec_cb) { lv_anim_t * a; - _LV_LL_READ(&LV_GC_ROOT(_lv_anim_ll), a) { + _LV_LL_READ(anim_ll_p, a) { if(a->var == var && (a->exec_cb == exec_cb || exec_cb == NULL)) { return a; } @@ -178,30 +165,48 @@ lv_anim_t * lv_anim_get(void * var, lv_anim_exec_xcb_t exec_cb) return NULL; } -struct _lv_timer_t * lv_anim_get_timer(void) +lv_timer_t * lv_anim_get_timer(void) { - return _lv_anim_tmr; + return state.timer; } uint16_t lv_anim_count_running(void) { uint16_t cnt = 0; lv_anim_t * a; - _LV_LL_READ(&LV_GC_ROOT(_lv_anim_ll), a) cnt++; + _LV_LL_READ(anim_ll_p, a) cnt++; return cnt; } -uint32_t lv_anim_speed_to_time(uint32_t speed, int32_t start, int32_t end) +uint32_t lv_anim_speed_clamped(uint32_t speed, uint32_t min_time, uint32_t max_time) { - uint32_t d = LV_ABS(start - end); - uint32_t time = (d * 1000) / speed; - if(time == 0) { - time++; + if(speed > 10000) { + LV_LOG_WARN("speed is truncated to 10000 (was %"LV_PRIu32")", speed); + speed = 10230; + } + if(min_time > 10000) { + LV_LOG_WARN("min_time is truncated to 10000 (was %"LV_PRIu32")", min_time); + min_time = 10230; + } + if(max_time > 10000) { + LV_LOG_WARN("max_time is truncated to 10000 (was %"LV_PRIu32")", max_time); + max_time = 10230; } - return time; + /*Lower the resolution to fit the 0.1023 range*/ + speed = (speed + 5) / 10; + min_time = (min_time + 5) / 10; + max_time = (max_time + 5) / 10; + + return 0x80000000 + (max_time << 20) + (min_time << 10) + speed; + +} + +uint32_t lv_anim_speed(uint32_t speed) +{ + return lv_anim_speed_clamped(speed, 0, 10000); } void lv_anim_refr_now(void) @@ -212,7 +217,7 @@ void lv_anim_refr_now(void) int32_t lv_anim_path_linear(const lv_anim_t * a) { /*Calculate the current step*/ - int32_t step = lv_map(a->act_time, 0, a->time, 0, LV_ANIM_RESOLUTION); + int32_t step = lv_map(a->act_time, 0, a->duration, 0, LV_ANIM_RESOLUTION); /*Get the new value which will be proportional to `step` *and the `start` and `end` values*/ @@ -226,64 +231,31 @@ int32_t lv_anim_path_linear(const lv_anim_t * a) int32_t lv_anim_path_ease_in(const lv_anim_t * a) { - /*Calculate the current step*/ - uint32_t t = lv_map(a->act_time, 0, a->time, 0, LV_BEZIER_VAL_MAX); - int32_t step = lv_bezier3(t, 0, 50, 100, LV_BEZIER_VAL_MAX); - - int32_t new_value; - new_value = step * (a->end_value - a->start_value); - new_value = new_value >> LV_BEZIER_VAL_SHIFT; - new_value += a->start_value; - - return new_value; + return lv_anim_path_cubic_bezier(a, LV_BEZIER_VAL_FLOAT(0.42), LV_BEZIER_VAL_FLOAT(0), + LV_BEZIER_VAL_FLOAT(1), LV_BEZIER_VAL_FLOAT(1)); } int32_t lv_anim_path_ease_out(const lv_anim_t * a) { - /*Calculate the current step*/ - uint32_t t = lv_map(a->act_time, 0, a->time, 0, LV_BEZIER_VAL_MAX); - int32_t step = lv_bezier3(t, 0, 900, 950, LV_BEZIER_VAL_MAX); - - int32_t new_value; - new_value = step * (a->end_value - a->start_value); - new_value = new_value >> LV_BEZIER_VAL_SHIFT; - new_value += a->start_value; - - return new_value; + return lv_anim_path_cubic_bezier(a, LV_BEZIER_VAL_FLOAT(0), LV_BEZIER_VAL_FLOAT(0), + LV_BEZIER_VAL_FLOAT(0.58), LV_BEZIER_VAL_FLOAT(1)); } int32_t lv_anim_path_ease_in_out(const lv_anim_t * a) { - /*Calculate the current step*/ - uint32_t t = lv_map(a->act_time, 0, a->time, 0, LV_BEZIER_VAL_MAX); - int32_t step = lv_bezier3(t, 0, 50, 952, LV_BEZIER_VAL_MAX); - - int32_t new_value; - new_value = step * (a->end_value - a->start_value); - new_value = new_value >> LV_BEZIER_VAL_SHIFT; - new_value += a->start_value; - - return new_value; + return lv_anim_path_cubic_bezier(a, LV_BEZIER_VAL_FLOAT(0.42), LV_BEZIER_VAL_FLOAT(0), + LV_BEZIER_VAL_FLOAT(0.58), LV_BEZIER_VAL_FLOAT(1)); } int32_t lv_anim_path_overshoot(const lv_anim_t * a) { - /*Calculate the current step*/ - uint32_t t = lv_map(a->act_time, 0, a->time, 0, LV_BEZIER_VAL_MAX); - int32_t step = lv_bezier3(t, 0, 1000, 1300, LV_BEZIER_VAL_MAX); - - int32_t new_value; - new_value = step * (a->end_value - a->start_value); - new_value = new_value >> LV_BEZIER_VAL_SHIFT; - new_value += a->start_value; - - return new_value; + return lv_anim_path_cubic_bezier(a, 341, 0, 683, 1300); } int32_t lv_anim_path_bounce(const lv_anim_t * a) { /*Calculate the current step*/ - int32_t t = lv_map(a->act_time, 0, a->time, 0, LV_BEZIER_VAL_MAX); + int32_t t = lv_map(a->act_time, 0, a->duration, 0, LV_BEZIER_VAL_MAX); int32_t diff = (a->end_value - a->start_value); /*3 bounces has 5 parts: 3 down and 2 up. One part is t / 5 long*/ @@ -333,16 +305,21 @@ int32_t lv_anim_path_bounce(const lv_anim_t * a) int32_t lv_anim_path_step(const lv_anim_t * a) { - if(a->act_time >= a->time) + if(a->act_time >= a->duration) return a->end_value; else return a->start_value; } +int32_t lv_anim_path_custom_bezier3(const lv_anim_t * a) +{ + const struct _lv_anim_bezier3_para_t * para = &a->parameter.bezier3; + return lv_anim_path_cubic_bezier(a, para->x1, para->y1, para->x2, para->y2); +} + /********************** * STATIC FUNCTIONS **********************/ - /** * Periodically handle the animations. * @param param unused @@ -351,37 +328,49 @@ static void anim_timer(lv_timer_t * param) { LV_UNUSED(param); - uint32_t elaps = lv_tick_elaps(last_timer_run); - /*Flip the run round*/ - anim_run_round = anim_run_round ? false : true; + state.anim_run_round = state.anim_run_round ? false : true; - lv_anim_t * a = _lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll)); + lv_anim_t * a = _lv_ll_get_head(anim_ll_p); while(a != NULL) { - /*It can be set by `lv_anim_del()` typically in `end_cb`. If set then an animation delete - * happened in `anim_ready_handler` which could make this linked list reading corrupt + + // printf("%p, %d\n", a, a->start_value); + + uint32_t elaps = lv_tick_elaps(a->last_timer_run); + a->act_time += elaps; + + a->last_timer_run = lv_tick_get(); + + /*It can be set by `lv_anim_delete()` typically in `end_cb`. If set then an animation delete + * happened in `anim_completed_handler` which could make this linked list reading corrupt * because the list is changed meanwhile */ - anim_list_changed = false; + state.anim_list_changed = false; - if(a->run_round != anim_run_round) { - a->run_round = anim_run_round; /*The list readying might be reset so need to know which anim has run already*/ + if(a->run_round != state.anim_run_round) { + a->run_round = state.anim_run_round; /*The list readying might be reset so need to know which anim has run already*/ /*The animation will run now for the first time. Call `start_cb`*/ - int32_t new_act_time = a->act_time + elaps; - if(!a->start_cb_called && a->act_time <= 0 && new_act_time >= 0) { + if(!a->start_cb_called && a->act_time >= 0) { + if(a->early_apply == 0 && a->get_value_cb) { int32_t v_ofs = a->get_value_cb(a); a->start_value += v_ofs; a->end_value += v_ofs; } + + resolve_time(a); + if(a->start_cb) a->start_cb(a); a->start_cb_called = 1; + + /*Do not let two animations for the same 'var' with the same 'exec_cb'*/ + remove_concurrent_anims(a); } - a->act_time += elaps; + if(a->act_time >= 0) { - if(a->act_time > a->time) a->act_time = a->time; + if(a->act_time > a->duration) a->act_time = a->duration; int32_t new_value; new_value = a->path_cb(a); @@ -390,32 +379,32 @@ static void anim_timer(lv_timer_t * param) a->current_value = new_value; /*Apply the calculated value*/ if(a->exec_cb) a->exec_cb(a->var, new_value); + if(!state.anim_list_changed && a->custom_exec_cb) a->custom_exec_cb(a, new_value); } /*If the time is elapsed the animation is ready*/ - if(a->act_time >= a->time) { - anim_ready_handler(a); + if(!state.anim_list_changed && a->act_time >= a->duration) { + anim_completed_handler(a); } } } /*If the linked list changed due to anim. delete then it's not safe to continue *the reading of the list from here -> start from the head*/ - if(anim_list_changed) - a = _lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll)); + if(state.anim_list_changed) + a = _lv_ll_get_head(anim_ll_p); else - a = _lv_ll_get_next(&LV_GC_ROOT(_lv_anim_ll), a); + a = _lv_ll_get_next(anim_ll_p, a); } - last_timer_run = lv_tick_get(); } /** - * Called when an animation is ready to do the necessary thinks + * Called when an animation is completed to do the necessary things * e.g. repeat, play back, delete etc. * @param a pointer to an animation descriptor */ -static void anim_ready_handler(lv_anim_t * a) +static void anim_completed_handler(lv_anim_t * a) { /*In the end of a forward anim decrement repeat cnt.*/ if(a->playback_now == 0 && a->repeat_cnt > 0 && a->repeat_cnt != LV_ANIM_REPEAT_INFINITE) { @@ -425,24 +414,24 @@ static void anim_ready_handler(lv_anim_t * a) /*Delete the animation if * - no repeat left and no play back (simple one shot animation) * - no repeat, play back is enabled and play back is ready*/ - if(a->repeat_cnt == 0 && (a->playback_time == 0 || a->playback_now == 1)) { + if(a->repeat_cnt == 0 && (a->playback_duration == 0 || a->playback_now == 1)) { /*Delete the animation from the list. - * This way the `ready_cb` will see the animations like it's animation is ready deleted*/ - _lv_ll_remove(&LV_GC_ROOT(_lv_anim_ll), a); + * This way the `completed_cb` will see the animations like it's animation is already deleted*/ + _lv_ll_remove(anim_ll_p, a); /*Flag that the list has changed*/ anim_mark_list_change(); /*Call the callback function at the end*/ - if(a->ready_cb != NULL) a->ready_cb(a); + if(a->completed_cb != NULL) a->completed_cb(a); if(a->deleted_cb != NULL) a->deleted_cb(a); - lv_mem_free(a); + lv_free(a); } /*If the animation is not deleted then restart it*/ else { a->act_time = -(int32_t)(a->repeat_delay); /*Restart the animation*/ /*Swap the start and end values in play back mode*/ - if(a->playback_time != 0) { + if(a->playback_duration != 0) { /*If now turning back use the 'playback_pause*/ if(a->playback_now == 0) a->act_time = -(int32_t)(a->playback_delay); @@ -452,19 +441,122 @@ static void anim_ready_handler(lv_anim_t * a) int32_t tmp = a->start_value; a->start_value = a->end_value; a->end_value = tmp; - /*Swap the time and playback_time*/ - tmp = a->time; - a->time = a->playback_time; - a->playback_time = tmp; + /*Swap the time and playback_duration*/ + tmp = a->duration; + a->duration = a->playback_duration; + a->playback_duration = tmp; } } } static void anim_mark_list_change(void) { - anim_list_changed = true; - if(_lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll)) == NULL) - lv_timer_pause(_lv_anim_tmr); + state.anim_list_changed = true; + if(_lv_ll_get_head(anim_ll_p) == NULL) + lv_timer_pause(state.timer); else - lv_timer_resume(_lv_anim_tmr); + lv_timer_resume(state.timer); +} + +static int32_t lv_anim_path_cubic_bezier(const lv_anim_t * a, int32_t x1, int32_t y1, int32_t x2, int32_t y2) +{ + /*Calculate the current step*/ + uint32_t t = lv_map(a->act_time, 0, a->duration, 0, LV_BEZIER_VAL_MAX); + int32_t step = lv_cubic_bezier(t, x1, y1, x2, y2); + + int32_t new_value; + new_value = step * (a->end_value - a->start_value); + new_value = new_value >> LV_BEZIER_VAL_SHIFT; + new_value += a->start_value; + + return new_value; +} + +static uint32_t convert_speed_to_time(uint32_t speed_or_time, int32_t start, int32_t end) +{ + /*It was a simple time*/ + if((speed_or_time & 0x80000000) == 0) return speed_or_time; + + uint32_t d = LV_ABS(start - end); + uint32_t speed = speed_or_time & 0x3FF; + uint32_t time = (d * 100) / speed; /*Speed is in 10 units per sec*/ + uint32_t max_time = (speed_or_time >> 20) & 0x3FF; + uint32_t min_time = (speed_or_time >> 10) & 0x3FF; + + return LV_CLAMP(min_time * 10, time, max_time * 10); +} + +static void resolve_time(lv_anim_t * a) +{ + a->duration = convert_speed_to_time(a->duration, a->start_value, a->end_value); + a->playback_duration = convert_speed_to_time(a->playback_duration, a->start_value, a->end_value); + a->playback_delay = convert_speed_to_time(a->playback_delay, a->start_value, a->end_value); + a->repeat_delay = convert_speed_to_time(a->repeat_delay, a->start_value, a->end_value); +} + +/** + * Remove animations which are animating the same var with the same exec_cb + * and they are already running or they have early_apply + * @param a_current the current animation, use its var and exec_cb as reference to know what to remove + * @return true: at least one animation was delete + */ +static bool remove_concurrent_anims(lv_anim_t * a_current) +{ + if(a_current->exec_cb == NULL && a_current->custom_exec_cb == NULL) return false; + + lv_anim_t * a; + bool del_any = false; + a = _lv_ll_get_head(anim_ll_p); + while(a != NULL) { + bool del = false; + /*We can't test for custom_exec_cb equality because in the MicroPython binding + *a wrapper callback is used here an the real callback data is stored in the `user_data`. + *Therefore equality check would remove all animations.*/ + if(a != a_current && + (a->act_time >= 0 || a->early_apply) && + (a->var == a_current->var) && + ((a->exec_cb && a->exec_cb == a_current->exec_cb) + /*|| (a->custom_exec_cb && a->custom_exec_cb == a_current->custom_exec_cb)*/)) { + _lv_ll_remove(anim_ll_p, a); + if(a->deleted_cb != NULL) a->deleted_cb(a); + lv_free(a); + /*Read by `anim_timer`. It need to know if a delete occurred in the linked list*/ + anim_mark_list_change(); + + del_any = true; + del = true; + } + + /*Always start from the head on delete, because we don't know + *how `anim_ll_p` was changes in `a->deleted_cb` */ + a = del ? _lv_ll_get_head(anim_ll_p) : _lv_ll_get_next(anim_ll_p, a); + } + + return del_any; +} + +static bool delete_core(void * var, void * cb, bool custom_exec_cb) +{ + lv_anim_t * a; + bool del_any = false; + a = _lv_ll_get_head(anim_ll_p); + while(a != NULL) { + bool del = false; + void * a_cb = custom_exec_cb ? (void *)a->custom_exec_cb : (void *)a->exec_cb; + if((a->var == var || var == NULL) && (a_cb == cb || cb == NULL)) { + _lv_ll_remove(anim_ll_p, a); + if(a->deleted_cb != NULL) a->deleted_cb(a); + lv_free(a); + anim_mark_list_change(); /*Read by `anim_timer`. It need to know if a delete occurred in + the linked list*/ + del_any = true; + del = true; + } + + /*Always start from the head on delete, because we don't know + *how `anim_ll_p` was changes in `a->deleted_cb` */ + a = del ? _lv_ll_get_head(anim_ll_p) : _lv_ll_get_next(anim_ll_p, a); + } + + return del_any; } diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.h index faef72787..bff3b33a4 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim.h @@ -14,6 +14,10 @@ extern "C" { * INCLUDES *********************/ #include "../lv_conf_internal.h" +#include "lv_types.h" +#include "lv_math.h" +#include "lv_timer.h" +#include "lv_ll.h" #include #include @@ -26,6 +30,52 @@ extern "C" { #define LV_ANIM_REPEAT_INFINITE 0xFFFF #define LV_ANIM_PLAYTIME_INFINITE 0xFFFFFFFF +/* + * Macros used to set cubic-bezier anim parameter. + * Parameters come from https://easings.net/ + * + * Usage: + * + * lv_anim_t a; + * lv_anim_init(&a); + * ... + * lv_anim_set_path_cb(&a, lv_anim_path_custom_bezier3); + * LV_ANIM_SET_EASE_IN_SINE(&a); //Set cubic-bezier anim parameter to easeInSine + * ... + * lv_anim_start(&a); + */ + +#define _PARA(a, x1, y1, x2, y2) ((a)->parameter.bezier3 = \ +(struct _lv_anim_bezier3_para_t) { \ + LV_BEZIER_VAL_FLOAT(x1), LV_BEZIER_VAL_FLOAT(y1), \ + LV_BEZIER_VAL_FLOAT(x2), LV_BEZIER_VAL_FLOAT(y2) } \ + ) + +#define LV_ANIM_SET_EASE_IN_SINE(a) _PARA(a, 0.12, 0, 0.39, 0) +#define LV_ANIM_SET_EASE_OUT_SINE(a) _PARA(a, 0.61, 1, 0.88, 1) +#define LV_ANIM_SET_EASE_IN_OUT_SINE(a) _PARA(a, 0.37, 0, 0.63, 1) +#define LV_ANIM_SET_EASE_IN_QUAD(a) _PARA(a, 0.11, 0, 0.5, 0) +#define LV_ANIM_SET_EASE_OUT_QUAD(a) _PARA(a, 0.5, 1, 0.89, 1) +#define LV_ANIM_SET_EASE_IN_OUT_QUAD(a) _PARA(a, 0.45, 0, 0.55, 1) +#define LV_ANIM_SET_EASE_IN_CUBIC(a) _PARA(a, 0.32, 0, 0.67, 0) +#define LV_ANIM_SET_EASE_OUT_CUBIC(a) _PARA(a, 0.33, 1, 0.68, 1) +#define LV_ANIM_SET_EASE_IN_OUT_CUBIC(a) _PARA(a, 0.65, 0, 0.35, 1) +#define LV_ANIM_SET_EASE_IN_QUART(a) _PARA(a, 0.5, 0, 0.75, 0) +#define LV_ANIM_SET_EASE_OUT_QUART(a) _PARA(a, 0.25, 1, 0.5, 1) +#define LV_ANIM_SET_EASE_IN_OUT_QUART(a) _PARA(a, 0.76, 0, 0.24, 1) +#define LV_ANIM_SET_EASE_IN_QUINT(a) _PARA(a, 0.64, 0, 0.78, 0) +#define LV_ANIM_SET_EASE_OUT_QUINT(a) _PARA(a, 0.22, 1, 0.36, 1) +#define LV_ANIM_SET_EASE_IN_OUT_QUINT(a) _PARA(a, 0.83, 0, 0.17, 1) +#define LV_ANIM_SET_EASE_IN_EXPO(a) _PARA(a, 0.7, 0, 0.84, 0) +#define LV_ANIM_SET_EASE_OUT_EXPO(a) _PARA(a, 0.16, 1, 0.3, 1) +#define LV_ANIM_SET_EASE_IN_OUT_EXPO(a) _PARA(a, 0.87, 0, 0.13, 1) +#define LV_ANIM_SET_EASE_IN_CIRC(a) _PARA(a, 0.55, 0, 1, 0.45) +#define LV_ANIM_SET_EASE_OUT_CIRC(a) _PARA(a, 0, 0.55, 0.45, 1) +#define LV_ANIM_SET_EASE_IN_OUT_CIRC(a) _PARA(a, 0.85, 0, 0.15, 1) +#define LV_ANIM_SET_EASE_IN_BACK(a) _PARA(a, 0.36, 0, 0.66, -0.56) +#define LV_ANIM_SET_EASE_OUT_BACK(a) _PARA(a, 0.34, 1.56, 0.64, 1) +#define LV_ANIM_SET_EASE_IN_OUT_BACK(a) _PARA(a, 0.68, -0.6, 0.32, 1.6) + LV_EXPORT_CONST_INT(LV_ANIM_REPEAT_INFINITE); LV_EXPORT_CONST_INT(LV_ANIM_PLAYTIME_INFINITE); @@ -39,11 +89,15 @@ typedef enum { LV_ANIM_ON, } lv_anim_enable_t; -struct _lv_anim_t; -struct _lv_timer_t; +typedef struct { + bool anim_list_changed; + bool anim_run_round; + lv_timer_t * timer; + lv_ll_t anim_ll; +} lv_anim_state_t; /** Get the current value during an animation*/ -typedef int32_t (*lv_anim_path_cb_t)(const struct _lv_anim_t *); +typedef int32_t (*lv_anim_path_cb_t)(const lv_anim_t *); /** Generic prototype of "animator" functions. * First parameter is the variable to animate. @@ -55,58 +109,75 @@ typedef void (*lv_anim_exec_xcb_t)(void *, int32_t); /** Same as `lv_anim_exec_xcb_t` but receives `lv_anim_t *` as the first parameter. * It's more consistent but less convenient. Might be used by binding generator functions.*/ -typedef void (*lv_anim_custom_exec_cb_t)(struct _lv_anim_t *, int32_t); +typedef void (*lv_anim_custom_exec_cb_t)(lv_anim_t *, int32_t); /** Callback to call when the animation is ready*/ -typedef void (*lv_anim_ready_cb_t)(struct _lv_anim_t *); +typedef void (*lv_anim_completed_cb_t)(lv_anim_t *); /** Callback to call when the animation really stars (considering `delay`)*/ -typedef void (*lv_anim_start_cb_t)(struct _lv_anim_t *); +typedef void (*lv_anim_start_cb_t)(lv_anim_t *); /** Callback used when the animation values are relative to get the current value*/ -typedef int32_t (*lv_anim_get_value_cb_t)(struct _lv_anim_t *); +typedef int32_t (*lv_anim_get_value_cb_t)(lv_anim_t *); /** Callback used when the animation is deleted*/ -typedef void (*lv_anim_deleted_cb_t)(struct _lv_anim_t *); +typedef void (*lv_anim_deleted_cb_t)(lv_anim_t *); + +typedef struct _lv_anim_bezier3_para_t { + int16_t x1; + int16_t y1; + int16_t x2; + int16_t y2; +} lv_anim_bezier3_para_t; /**< Parameter used when path is custom_bezier*/ /** Describes an animation*/ -typedef struct _lv_anim_t { - void * var; /**duration = duration; +} + +/** + * Legacy `lv_anim_set_time` API will be removed soon, use `lv_anim_set_duration` instead. + */ static inline void lv_anim_set_time(lv_anim_t * a, uint32_t duration) { - a->time = duration; + lv_anim_set_duration(a, duration); } /** @@ -169,7 +248,7 @@ static inline void lv_anim_set_delay(lv_anim_t * a, uint32_t delay) static inline void lv_anim_set_values(lv_anim_t * a, int32_t start, int32_t end) { a->start_value = start; - a->current_value = start; + a->current_value = INT32_MIN; a->end_value = end; } @@ -178,14 +257,12 @@ static inline void lv_anim_set_values(lv_anim_t * a, int32_t start, int32_t end) * `lv_anim_t * ` as its first parameter instead of `void *`. * This function might be used when LVGL is bound to other languages because * it's more consistent to have `lv_anim_t *` as first parameter. - * The variable to animate can be stored in the animation's `user_data` * @param a pointer to an initialized `lv_anim_t` variable * @param exec_cb a function to execute. */ static inline void lv_anim_set_custom_exec_cb(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) { - a->var = a; - a->exec_cb = (lv_anim_exec_xcb_t)exec_cb; + a->custom_exec_cb = exec_cb; } /** @@ -220,13 +297,13 @@ static inline void lv_anim_set_get_value_cb(lv_anim_t * a, lv_anim_get_value_cb_ } /** - * Set a function call when the animation is ready - * @param a pointer to an initialized `lv_anim_t` variable - * @param ready_cb a function call when the animation is ready + * Set a function call when the animation is completed + * @param a pointer to an initialized `lv_anim_t` variable + * @param completed_cb a function call when the animation is fully completed */ -static inline void lv_anim_set_ready_cb(lv_anim_t * a, lv_anim_ready_cb_t ready_cb) +static inline void lv_anim_set_completed_cb(lv_anim_t * a, lv_anim_completed_cb_t completed_cb) { - a->ready_cb = ready_cb; + a->completed_cb = completed_cb; } /** @@ -244,9 +321,17 @@ static inline void lv_anim_set_deleted_cb(lv_anim_t * a, lv_anim_deleted_cb_t de * @param a pointer to an initialized `lv_anim_t` variable * @param time the duration of the playback animation in milliseconds. 0: disable playback */ -static inline void lv_anim_set_playback_time(lv_anim_t * a, uint32_t time) +static inline void lv_anim_set_playback_duration(lv_anim_t * a, uint32_t duration) { - a->playback_time = time; + a->playback_duration = duration; +} + +/** + * Legacy `lv_anim_set_playback_time` API will be removed soon, use `lv_anim_set_playback_duration` instead. + */ +static inline void lv_anim_set_playback_time(lv_anim_t * a, uint32_t duration) +{ + lv_anim_set_playback_duration(a, duration); } /** @@ -295,12 +380,27 @@ static inline void lv_anim_set_early_apply(lv_anim_t * a, bool en) * @param a pointer to an initialized `lv_anim_t` variable * @param user_data pointer to the new user_data. */ -#if LV_USE_USER_DATA static inline void lv_anim_set_user_data(lv_anim_t * a, void * user_data) { a->user_data = user_data; } -#endif + +/** + * Set parameter for cubic bezier path + * @param a pointer to an initialized `lv_anim_t` variable + * @param x1 first control point + * @param y1 + * @param y1 second control point + */ +static inline void lv_anim_set_bezier3_param(lv_anim_t * a, int16_t x1, int16_t y1, int16_t x2, int16_t y2) +{ + struct _lv_anim_bezier3_para_t * para = &a->parameter.bezier3; + + para->x1 = x1; + para->x2 = x2; + para->y1 = y1; + para->y2 = y2; +} /** * Create an animation @@ -314,7 +414,7 @@ lv_anim_t * lv_anim_start(const lv_anim_t * a); * @param a pointer to an initialized `lv_anim_t` variable * @return delay before the animation in milliseconds */ -static inline uint32_t lv_anim_get_delay(lv_anim_t * a) +static inline uint32_t lv_anim_get_delay(const lv_anim_t * a) { return -a->act_time; } @@ -324,33 +424,51 @@ static inline uint32_t lv_anim_get_delay(lv_anim_t * a) * @param a pointer to an animation. * @return the play time in milliseconds. */ -uint32_t lv_anim_get_playtime(lv_anim_t * a); +uint32_t lv_anim_get_playtime(const lv_anim_t * a); + +/** + * Get the duration of an animation + * @param a pointer to an initialized `lv_anim_t` variable + * @return the duration of the animation in milliseconds + */ +static inline uint32_t lv_anim_get_time(const lv_anim_t * a) +{ + return a->duration; +} + +/** + * Get the repeat count of the animation. + * @param a pointer to an initialized `lv_anim_t` variable + * @return the repeat count or `LV_ANIM_REPEAT_INFINITE` for infinite repetition. 0: disabled repetition. + */ +static inline uint16_t lv_anim_get_repeat_count(const lv_anim_t * a) +{ + return a->repeat_cnt; +} /** * Get the user_data field of the animation * @param a pointer to an initialized `lv_anim_t` variable * @return the pointer to the custom user_data of the animation */ -#if LV_USE_USER_DATA -static inline void * lv_anim_get_user_data(lv_anim_t * a) +static inline void * lv_anim_get_user_data(const lv_anim_t * a) { return a->user_data; } -#endif /** - * Delete an animation of a variable with a given animator function + * Delete animation(s) of a variable with a given animator function * @param var pointer to variable * @param exec_cb a function pointer which is animating 'var', * or NULL to ignore it and delete all the animations of 'var * @return true: at least 1 animation is deleted, false: no animation is deleted */ -bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb); +bool lv_anim_delete(void * var, lv_anim_exec_xcb_t exec_cb); /** * Delete all the animations */ -void lv_anim_del_all(void); +void lv_anim_delete_all(void); /** * Get the animation of a variable and its `exec_cb`. @@ -364,7 +482,7 @@ lv_anim_t * lv_anim_get(void * var, lv_anim_exec_xcb_t exec_cb); * Get global animation refresher timer. * @return pointer to the animation refresher timer. */ -struct _lv_timer_t * lv_anim_get_timer(void); +lv_timer_t * lv_anim_get_timer(void); /** * Delete an animation by getting the animated variable from `a`. @@ -377,9 +495,9 @@ struct _lv_timer_t * lv_anim_get_timer(void); * or NULL to ignore it and delete all the animations of 'var * @return true: at least 1 animation is deleted, false: no animation is deleted */ -static inline bool lv_anim_custom_del(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) +static inline bool lv_anim_custom_delete(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb) { - return lv_anim_del(a ? a->var : NULL, (lv_anim_exec_xcb_t)exec_cb); + return lv_anim_delete(a ? a->var : NULL, (lv_anim_exec_xcb_t)exec_cb); } /** @@ -403,13 +521,25 @@ static inline lv_anim_t * lv_anim_custom_get(lv_anim_t * a, lv_anim_custom_exec_ uint16_t lv_anim_count_running(void); /** - * Calculate the time of an animation with a given speed and the start and end values - * @param speed speed of animation in unit/sec - * @param start start value of the animation - * @param end end value of the animation - * @return the required time [ms] for the animation with the given parameters + * Store the speed as a special value which can be used as time in animations. + * It will be converted to time internally based on the start and end values + * @param speed the speed of the animation in with unit / sec resolution in 0..10k range + * @return a special value which can be used as an animation time */ -uint32_t lv_anim_speed_to_time(uint32_t speed, int32_t start, int32_t end); +uint32_t lv_anim_speed(uint32_t speed); + +/** + * Store the speed as a special value which can be used as time in animations. + * It will be converted to time internally based on the start and end values + * @param speed the speed of the animation in as unit / sec resolution in 0..10k range + * @param min_time the minimum time in 0..10k range + * @param max_time the maximum time in 0..10k range + * @return a special value in where all three values are stored and can be used as an animation time + * @note internally speed is stored as 10 unit/sec + * @note internally min/max_time are stored with 10 ms unit + * + */ +uint32_t lv_anim_speed_clamped(uint32_t speed, uint32_t min_time, uint32_t max_time); /** * Manually refresh the state of the animations. @@ -469,6 +599,13 @@ int32_t lv_anim_path_bounce(const lv_anim_t * a); */ int32_t lv_anim_path_step(const lv_anim_t * a); +/** + * A custom cubic bezier animation path, need to specify cubic-parameters in a->parameter.bezier3 + * @param a pointer to an animation + * @return the current value to set + */ +int32_t lv_anim_path_custom_bezier3(const lv_anim_t * a); + /********************** * GLOBAL VARIABLES **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_anim_timeline.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim_timeline.c index 08d5321fb..0acd24312 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_anim_timeline.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim_timeline.c @@ -6,9 +6,10 @@ /********************* * INCLUDES *********************/ -#include "lv_anim_timeline.h" -#include "lv_mem.h" #include "lv_assert.h" +#include "lv_anim_timeline.h" +#include "../stdlib/lv_mem.h" +#include "../stdlib/lv_string.h" /********************* * DEFINES @@ -17,7 +18,6 @@ /********************** * TYPEDEFS **********************/ - /*Data of anim_timeline_dsc*/ typedef struct { lv_anim_t anim; @@ -28,13 +28,16 @@ typedef struct { struct _lv_anim_timeline_t { lv_anim_timeline_dsc_t * anim_dsc; /**< Dynamically allocated anim dsc array*/ uint32_t anim_dsc_cnt; /**< The length of anim dsc array*/ + uint32_t act_time; /**< Current time of the animation*/ bool reverse; /**< Reverse playback*/ }; /********************** * STATIC PROTOTYPES **********************/ -static void lv_anim_timeline_virtual_exec_cb(void * var, int32_t v); +static void anim_timeline_exec_cb(void * var, int32_t v); +static void anim_timeline_set_act_time(lv_anim_timeline_t * at, uint32_t act_time); +static int32_t anim_timeline_path_cb(const lv_anim_t * a); /********************** * STATIC VARIABLES @@ -50,79 +53,59 @@ static void lv_anim_timeline_virtual_exec_cb(void * var, int32_t v); lv_anim_timeline_t * lv_anim_timeline_create(void) { - lv_anim_timeline_t * at = (lv_anim_timeline_t *)lv_mem_alloc(sizeof(lv_anim_timeline_t)); - + lv_anim_timeline_t * at = lv_malloc_zeroed(sizeof(lv_anim_timeline_t)); LV_ASSERT_MALLOC(at); - - if(at) lv_memset_00(at, sizeof(lv_anim_timeline_t)); - return at; } -void lv_anim_timeline_del(lv_anim_timeline_t * at) +void lv_anim_timeline_delete(lv_anim_timeline_t * at) { LV_ASSERT_NULL(at); - lv_anim_timeline_stop(at); + lv_anim_timeline_pause(at); - lv_mem_free(at->anim_dsc); - lv_mem_free(at); + lv_free(at->anim_dsc); + lv_free(at); } -void lv_anim_timeline_add(lv_anim_timeline_t * at, uint32_t start_time, lv_anim_t * a) +void lv_anim_timeline_add(lv_anim_timeline_t * at, uint32_t start_time, const lv_anim_t * a) { LV_ASSERT_NULL(at); at->anim_dsc_cnt++; - at->anim_dsc = lv_mem_realloc(at->anim_dsc, at->anim_dsc_cnt * sizeof(lv_anim_timeline_dsc_t)); + at->anim_dsc = lv_realloc(at->anim_dsc, at->anim_dsc_cnt * sizeof(lv_anim_timeline_dsc_t)); LV_ASSERT_MALLOC(at->anim_dsc); at->anim_dsc[at->anim_dsc_cnt - 1].anim = *a; at->anim_dsc[at->anim_dsc_cnt - 1].start_time = start_time; - - /*Add default var and virtual exec_cb, used to delete animation.*/ - if(a->var == NULL && a->exec_cb == NULL) { - at->anim_dsc[at->anim_dsc_cnt - 1].anim.var = at; - at->anim_dsc[at->anim_dsc_cnt - 1].anim.exec_cb = lv_anim_timeline_virtual_exec_cb; - } } uint32_t lv_anim_timeline_start(lv_anim_timeline_t * at) { LV_ASSERT_NULL(at); - const uint32_t playtime = lv_anim_timeline_get_playtime(at); - bool reverse = at->reverse; - - for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) { - lv_anim_t a = at->anim_dsc[i].anim; - uint32_t start_time = at->anim_dsc[i].start_time; - - if(reverse) { - int32_t temp = a.start_value; - a.start_value = a.end_value; - a.end_value = temp; - lv_anim_set_delay(&a, playtime - (start_time + a.time)); - } - else { - lv_anim_set_delay(&a, start_time); - } - - lv_anim_start(&a); - } + uint32_t playtime = lv_anim_timeline_get_playtime(at); + uint32_t start = at->act_time; + uint32_t end = at->reverse ? 0 : playtime; + uint32_t duration = end > start ? end - start : start - end; + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, at); + lv_anim_set_exec_cb(&a, anim_timeline_exec_cb); + lv_anim_set_values(&a, start, end); + lv_anim_set_time(&a, duration); + lv_anim_set_path_cb(&a, anim_timeline_path_cb); + lv_anim_start(&a); return playtime; } -void lv_anim_timeline_stop(lv_anim_timeline_t * at) +void lv_anim_timeline_pause(lv_anim_timeline_t * at) { LV_ASSERT_NULL(at); - for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) { - lv_anim_t * a = &(at->anim_dsc[i].anim); - lv_anim_del(a->var, a->exec_cb); - } + lv_anim_delete(at, anim_timeline_exec_cb); } void lv_anim_timeline_set_reverse(lv_anim_timeline_t * at, bool reverse) @@ -135,32 +118,9 @@ void lv_anim_timeline_set_progress(lv_anim_timeline_t * at, uint16_t progress) { LV_ASSERT_NULL(at); - const uint32_t playtime = lv_anim_timeline_get_playtime(at); - const uint32_t act_time = progress * playtime / 0xFFFF; - - for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) { - lv_anim_t * a = &(at->anim_dsc[i].anim); - - if(a->exec_cb == NULL) { - continue; - } - - uint32_t start_time = at->anim_dsc[i].start_time; - int32_t value = 0; - - if(act_time < start_time) { - value = a->start_value; - } - else if(act_time < (start_time + a->time)) { - a->act_time = act_time - start_time; - value = a->path_cb(a); - } - else { - value = a->end_value; - } - - a->exec_cb(a->var, value); - } + uint32_t playtime = lv_anim_timeline_get_playtime(at); + uint32_t act_time = lv_map(progress, 0, LV_ANIM_TIMELINE_PROGRESS_MAX, 0, playtime); + anim_timeline_set_act_time(at, act_time); } uint32_t lv_anim_timeline_get_playtime(lv_anim_timeline_t * at) @@ -187,12 +147,56 @@ bool lv_anim_timeline_get_reverse(lv_anim_timeline_t * at) return at->reverse; } +uint16_t lv_anim_timeline_get_progress(lv_anim_timeline_t * at) +{ + LV_ASSERT_NULL(at); + uint32_t playtime = lv_anim_timeline_get_playtime(at); + return lv_map(at->act_time, 0, playtime, 0, LV_ANIM_TIMELINE_PROGRESS_MAX); +} + /********************** * STATIC FUNCTIONS **********************/ -static void lv_anim_timeline_virtual_exec_cb(void * var, int32_t v) +static void anim_timeline_set_act_time(lv_anim_timeline_t * at, uint32_t act_time) { - LV_UNUSED(var); - LV_UNUSED(v); + at->act_time = act_time; + for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) { + lv_anim_t * a = &(at->anim_dsc[i].anim); + + if(a->exec_cb == NULL && a->custom_exec_cb == NULL) { + continue; + } + + uint32_t start_time = at->anim_dsc[i].start_time; + int32_t value = 0; + if(act_time < start_time && a->early_apply) { + value = a->start_value; + if(a->exec_cb) a->exec_cb(a->var, value); + if(a->custom_exec_cb) a->custom_exec_cb(a, value); + } + else if(act_time >= start_time && act_time <= (start_time + a->duration)) { + a->act_time = act_time - start_time; + value = a->path_cb(a); + if(a->exec_cb) a->exec_cb(a->var, value); + if(a->custom_exec_cb) a->custom_exec_cb(a, value); + } + else if(act_time > start_time + a->duration) { + value = a->end_value; + if(a->exec_cb) a->exec_cb(a->var, value); + if(a->custom_exec_cb) a->custom_exec_cb(a, value); + } + } +} + +static int32_t anim_timeline_path_cb(const lv_anim_t * a) +{ + /* Directly map original timestamps to avoid loss of accuracy */ + return lv_map(a->act_time, 0, a->duration, a->start_value, a->end_value); +} + +static void anim_timeline_exec_cb(void * var, int32_t v) +{ + lv_anim_timeline_t * at = var; + anim_timeline_set_act_time(at, v); } diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_anim_timeline.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim_timeline.h index d4dd0fcf3..dd2707041 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_anim_timeline.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_anim_timeline.h @@ -19,12 +19,12 @@ extern "C" { * DEFINES *********************/ +#define LV_ANIM_TIMELINE_PROGRESS_MAX 0xFFFF + /********************** * TYPEDEFS **********************/ -struct _lv_anim_timeline_t; - typedef struct _lv_anim_timeline_t lv_anim_timeline_t; /********************** @@ -41,7 +41,7 @@ lv_anim_timeline_t * lv_anim_timeline_create(void); * Delete animation timeline. * @param at pointer to the animation timeline. */ -void lv_anim_timeline_del(lv_anim_timeline_t * at); +void lv_anim_timeline_delete(lv_anim_timeline_t * at); /** * Add animation to the animation timeline. @@ -49,7 +49,7 @@ void lv_anim_timeline_del(lv_anim_timeline_t * at); * @param start_time the time the animation started on the timeline, note that start_time will override the value of delay. * @param a pointer to an animation. */ -void lv_anim_timeline_add(lv_anim_timeline_t * at, uint32_t start_time, lv_anim_t * a); +void lv_anim_timeline_add(lv_anim_timeline_t * at, uint32_t start_time, const lv_anim_t * a); /** * Start the animation timeline. @@ -59,10 +59,10 @@ void lv_anim_timeline_add(lv_anim_timeline_t * at, uint32_t start_time, lv_anim_ uint32_t lv_anim_timeline_start(lv_anim_timeline_t * at); /** - * Stop the animation timeline. + * Pause the animation timeline. * @param at pointer to the animation timeline. */ -void lv_anim_timeline_stop(lv_anim_timeline_t * at); +void lv_anim_timeline_pause(lv_anim_timeline_t * at); /** * Set the playback direction of the animation timeline. @@ -92,6 +92,13 @@ uint32_t lv_anim_timeline_get_playtime(lv_anim_timeline_t * at); */ bool lv_anim_timeline_get_reverse(lv_anim_timeline_t * at); +/** + * Get the progress of the animation timeline. + * @param at pointer to the animation timeline. + * @return return value 0~65535 to map 0~100% animation progress. + */ +uint16_t lv_anim_timeline_get_progress(lv_anim_timeline_t * at); + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_area.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_area.c index 493b70880..bfda7b347 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_area.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_area.c @@ -7,6 +7,7 @@ * INCLUDES *********************/ #include "../lv_conf_internal.h" +#include "../core/lv_global.h" #include "lv_area.h" #include "lv_math.h" @@ -14,6 +15,7 @@ /********************* * DEFINES *********************/ +#define trans_cache LV_GLOBAL_DEFAULT()->area_trans_cache /********************** * TYPEDEFS @@ -37,15 +39,7 @@ static bool lv_point_within_circle(const lv_area_t * area, const lv_point_t * p) * GLOBAL FUNCTIONS **********************/ -/** - * Initialize an area - * @param area_p pointer to an area - * @param x1 left coordinate of the area - * @param y1 top coordinate of the area - * @param x2 right coordinate of the area - * @param y2 bottom coordinate of the area - */ -void lv_area_set(lv_area_t * area_p, lv_coord_t x1, lv_coord_t y1, lv_coord_t x2, lv_coord_t y2) +void lv_area_set(lv_area_t * area_p, int32_t x1, int32_t y1, int32_t x2, int32_t y2) { area_p->x1 = x1; area_p->y1 = y1; @@ -53,47 +47,26 @@ void lv_area_set(lv_area_t * area_p, lv_coord_t x1, lv_coord_t y1, lv_coord_t x2 area_p->y2 = y2; } -/** - * Set the width of an area - * @param area_p pointer to an area - * @param w the new width of the area (w == 1 makes x1 == x2) - */ -void lv_area_set_width(lv_area_t * area_p, lv_coord_t w) +void lv_area_set_width(lv_area_t * area_p, int32_t w) { area_p->x2 = area_p->x1 + w - 1; } -/** - * Set the height of an area - * @param area_p pointer to an area - * @param h the new height of the area (h == 1 makes y1 == y2) - */ -void lv_area_set_height(lv_area_t * area_p, lv_coord_t h) +void lv_area_set_height(lv_area_t * area_p, int32_t h) { area_p->y2 = area_p->y1 + h - 1; } -/** - * Set the position of an area (width and height will be kept) - * @param area_p pointer to an area - * @param x the new x coordinate of the area - * @param y the new y coordinate of the area - */ -void _lv_area_set_pos(lv_area_t * area_p, lv_coord_t x, lv_coord_t y) +void _lv_area_set_pos(lv_area_t * area_p, int32_t x, int32_t y) { - lv_coord_t w = lv_area_get_width(area_p); - lv_coord_t h = lv_area_get_height(area_p); + int32_t w = lv_area_get_width(area_p); + int32_t h = lv_area_get_height(area_p); area_p->x1 = x; area_p->y1 = y; lv_area_set_width(area_p, w); lv_area_set_height(area_p, h); } -/** - * Return with area of an area (x * y) - * @param area_p pointer to an area - * @return size of area - */ uint32_t lv_area_get_size(const lv_area_t * area_p) { uint32_t size; @@ -103,7 +76,7 @@ uint32_t lv_area_get_size(const lv_area_t * area_p) return size; } -void lv_area_increase(lv_area_t * area, lv_coord_t w_extra, lv_coord_t h_extra) +void lv_area_increase(lv_area_t * area, int32_t w_extra, int32_t h_extra) { area->x1 -= w_extra; area->x2 += w_extra; @@ -111,7 +84,7 @@ void lv_area_increase(lv_area_t * area, lv_coord_t w_extra, lv_coord_t h_extra) area->y2 += h_extra; } -void lv_area_move(lv_area_t * area, lv_coord_t x_ofs, lv_coord_t y_ofs) +void lv_area_move(lv_area_t * area, int32_t x_ofs, int32_t y_ofs) { area->x1 += x_ofs; area->x2 += x_ofs; @@ -119,13 +92,6 @@ void lv_area_move(lv_area_t * area, lv_coord_t x_ofs, lv_coord_t y_ofs) area->y2 += y_ofs; } -/** - * Get the common parts of two areas - * @param res_p pointer to an area, the result will be stored here - * @param a1_p pointer to the first area - * @param a2_p pointer to the second area - * @return false: the two area has NO common parts, res_p is invalid - */ bool _lv_area_intersect(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_t * a2_p) { /*Get the smaller area from 'a1_p' and 'a2_p'*/ @@ -143,14 +109,7 @@ bool _lv_area_intersect(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area return union_ok; } -/** - * Get resulting sub areas after removing the common parts of two areas from the first area - * @param res_p pointer to an array of areas with a count of 4, the resulting areas will be stored here - * @param a1_p pointer to the first area - * @param a2_p pointer to the second area - * @return number of results or -1 if no intersect - */ -int8_t _lv_area_diff(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_t * a2_p) +int8_t _lv_area_diff(lv_area_t res_p[], const lv_area_t * a1_p, const lv_area_t * a2_p) { /*Areas have no common parts*/ if(!_lv_area_is_on(a1_p, a2_p)) return -1; @@ -163,11 +122,11 @@ int8_t _lv_area_diff(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_t /*Get required information*/ lv_area_t n; - lv_coord_t a1_w = lv_area_get_width(a1_p) - 1; - lv_coord_t a1_h = lv_area_get_height(a1_p) - 1; + int32_t a1_w = lv_area_get_width(a1_p) - 1; + int32_t a1_h = lv_area_get_height(a1_p) - 1; /*Compute top rectangle*/ - lv_coord_t th = a2_p->y1 - a1_p->y1; + int32_t th = a2_p->y1 - a1_p->y1; if(th > 0) { n.x1 = a1_p->x1; n.y1 = a1_p->y1; @@ -177,7 +136,7 @@ int8_t _lv_area_diff(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_t } /*Compute the bottom rectangle*/ - lv_coord_t bh = a1_h - (a2_p->y2 - a1_p->y1); + int32_t bh = a1_h - (a2_p->y2 - a1_p->y1); if(bh > 0 && a2_p->y2 < a1_p->y2) { n.x1 = a1_p->x1; n.y1 = a2_p->y2; @@ -187,12 +146,12 @@ int8_t _lv_area_diff(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_t } /*Compute side height*/ - lv_coord_t y1 = a2_p->y1 > a1_p->y1 ? a2_p->y1 : a1_p->y1; - lv_coord_t y2 = a2_p->y2 < a1_p->y2 ? a2_p->y2 : a1_p->y2; - lv_coord_t sh = y2 - y1; + int32_t y1 = a2_p->y1 > a1_p->y1 ? a2_p->y1 : a1_p->y1; + int32_t y2 = a2_p->y2 < a1_p->y2 ? a2_p->y2 : a1_p->y2; + int32_t sh = y2 - y1; /*Compute the left rectangle*/ - lv_coord_t lw = a2_p->x1 - a1_p->x1; + int32_t lw = a2_p->x1 - a1_p->x1; if(lw > 0 && sh > 0) { n.x1 = a1_p->x1; n.y1 = y1; @@ -202,7 +161,7 @@ int8_t _lv_area_diff(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_t } /*Compute the right rectangle*/ - lv_coord_t rw = a1_w - (a2_p->x2 - a1_p->x1); + int32_t rw = a1_w - (a2_p->x2 - a1_p->x1); if(rw > 0) { n.x1 = a2_p->x2; n.y1 = y1; @@ -215,12 +174,6 @@ int8_t _lv_area_diff(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_t return res_c; } -/** - * Join two areas into a third which involves the other two - * @param res_p pointer to an area, the result will be stored here - * @param a1_p pointer to the first area - * @param a2_p pointer to the second area - */ void _lv_area_join(lv_area_t * a_res_p, const lv_area_t * a1_p, const lv_area_t * a2_p) { a_res_p->x1 = LV_MIN(a1_p->x1, a2_p->x1); @@ -229,14 +182,7 @@ void _lv_area_join(lv_area_t * a_res_p, const lv_area_t * a1_p, const lv_area_t a_res_p->y2 = LV_MAX(a1_p->y2, a2_p->y2); } -/** - * Check if a point is on an area - * @param a_p pointer to an area - * @param p_p pointer to a point - * @param radius radius of area (e.g. for rounded rectangle) - * @return false:the point is out of the area - */ -bool _lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p, lv_coord_t radius) +bool _lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p, int32_t radius) { /*First check the basic area*/ bool is_on_rect = false; @@ -250,9 +196,9 @@ bool _lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p, lv_coor /*No radius, it is within the rectangle*/ return true; } - lv_coord_t w = lv_area_get_width(a_p) / 2; - lv_coord_t h = lv_area_get_height(a_p) / 2; - lv_coord_t max_radius = LV_MIN(w, h); + int32_t w = lv_area_get_width(a_p) / 2; + int32_t h = lv_area_get_height(a_p) / 2; + int32_t max_radius = LV_MIN(w, h); if(radius > max_radius) radius = max_radius; @@ -296,12 +242,6 @@ bool _lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p, lv_coor return true; } -/** - * Check if two area has common parts - * @param a1_p pointer to an area. - * @param a2_p pointer to an other area - * @return false: a1_p and a2_p has no common parts - */ bool _lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p) { if((a1_p->x1 <= a2_p->x2) && (a1_p->x2 >= a2_p->x1) && (a1_p->y1 <= a2_p->y2) && (a1_p->y2 >= a2_p->y1)) { @@ -312,14 +252,7 @@ bool _lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p) } } -/** - * Check if an area is fully on an other - * @param ain_p pointer to an area which could be in 'aholder_p' - * @param aholder_p pointer to an area which could involve 'ain_p' - * @param radius radius of `aholder_p` (e.g. for rounded rectangle) - * @return true: `ain_p` is fully inside `aholder_p` - */ -bool _lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p, lv_coord_t radius) +bool _lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p, int32_t radius) { bool is_in = false; @@ -334,33 +267,22 @@ bool _lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p, lv_coo /*Check if the corner points are inside the radius or not*/ lv_point_t p; - p.x = ain_p->x1; - p.y = ain_p->y1; + lv_point_set(&p, ain_p->x1, ain_p->y1); if(_lv_area_is_point_on(aholder_p, &p, radius) == false) return false; - p.x = ain_p->x2; - p.y = ain_p->y1; + lv_point_set(&p, ain_p->x2, ain_p->y1); if(_lv_area_is_point_on(aholder_p, &p, radius) == false) return false; - p.x = ain_p->x1; - p.y = ain_p->y2; + lv_point_set(&p, ain_p->x1, ain_p->y2); if(_lv_area_is_point_on(aholder_p, &p, radius) == false) return false; - p.x = ain_p->x2; - p.y = ain_p->y2; + lv_point_set(&p, ain_p->x2, ain_p->y2); if(_lv_area_is_point_on(aholder_p, &p, radius) == false) return false; return true; } -/** - * Check if an area is fully out of an other - * @param aout_p pointer to an area which could be in 'aholder_p' - * @param aholder_p pointer to an area which could involve 'ain_p' - * @param radius radius of `aholder_p` (e.g. for rounded rectangle) - * @return true: `aout_p` is fully outside `aholder_p` - */ -bool _lv_area_is_out(const lv_area_t * aout_p, const lv_area_t * aholder_p, lv_coord_t radius) +bool _lv_area_is_out(const lv_area_t * aout_p, const lv_area_t * aholder_p, int32_t radius) { if(aout_p->x2 < aholder_p->x1 || aout_p->y2 < aholder_p->y1 || aout_p->x1 > aholder_p->x2 || aout_p->y1 > aholder_p->y2) { @@ -372,20 +294,16 @@ bool _lv_area_is_out(const lv_area_t * aout_p, const lv_area_t * aholder_p, lv_c /*Check if the corner points are outside the radius or not*/ lv_point_t p; - p.x = aout_p->x1; - p.y = aout_p->y1; + lv_point_set(&p, aout_p->x1, aout_p->y1); if(_lv_area_is_point_on(aholder_p, &p, radius)) return false; - p.x = aout_p->x2; - p.y = aout_p->y1; + lv_point_set(&p, aout_p->x2, aout_p->y1); if(_lv_area_is_point_on(aholder_p, &p, radius)) return false; - p.x = aout_p->x1; - p.y = aout_p->y2; + lv_point_set(&p, aout_p->x1, aout_p->y2); if(_lv_area_is_point_on(aholder_p, &p, radius)) return false; - p.x = aout_p->x2; - p.y = aout_p->y2; + lv_point_set(&p, aout_p->x2, aout_p->y2); if(_lv_area_is_point_on(aholder_p, &p, radius)) return false; return true; @@ -396,18 +314,11 @@ bool _lv_area_is_equal(const lv_area_t * a, const lv_area_t * b) return a->x1 == b->x1 && a->x2 == b->x2 && a->y1 == b->y1 && a->y2 == b->y2; } -/** - * Align an area to an other - * @param base an are where the other will be aligned - * @param to_align the area to align - * @param align `LV_ALIGN_...` - * @param res x/y coordinates where `to_align` align area should be placed - */ -void lv_area_align(const lv_area_t * base, lv_area_t * to_align, lv_align_t align, lv_coord_t ofs_x, lv_coord_t ofs_y) +void lv_area_align(const lv_area_t * base, lv_area_t * to_align, lv_align_t align, int32_t ofs_x, int32_t ofs_y) { - lv_coord_t x; - lv_coord_t y; + int32_t x; + int32_t y; switch(align) { case LV_ALIGN_CENTER: x = lv_area_get_width(base) / 2 - lv_area_get_width(to_align) / 2; @@ -520,8 +431,8 @@ void lv_area_align(const lv_area_t * base, lv_area_t * to_align, lv_align_t alig x += base->x1; y += base->y1; - lv_coord_t w = lv_area_get_width(to_align); - lv_coord_t h = lv_area_get_height(to_align); + int32_t w = lv_area_get_width(to_align); + int32_t h = lv_area_get_height(to_align); to_align->x1 = x + ofs_x; to_align->y1 = y + ofs_y; to_align->x2 = to_align->x1 + w - 1; @@ -529,9 +440,10 @@ void lv_area_align(const lv_area_t * base, lv_area_t * to_align, lv_align_t alig } #define _LV_TRANSFORM_TRIGO_SHIFT 10 -void lv_point_transform(lv_point_t * p, int32_t angle, int32_t zoom, const lv_point_t * pivot) +void lv_point_transform(lv_point_t * p, int32_t angle, int32_t scale_x, int32_t scale_y, const lv_point_t * pivot, + bool zoom_first) { - if(angle == 0 && zoom == 256) { + if(angle == 0 && scale_x == 256 && scale_y == 256) { return; } @@ -539,15 +451,12 @@ void lv_point_transform(lv_point_t * p, int32_t angle, int32_t zoom, const lv_po p->y -= pivot->y; if(angle == 0) { - p->x = (((int32_t)(p->x) * zoom) >> 8) + pivot->x; - p->y = (((int32_t)(p->y) * zoom) >> 8) + pivot->y; + p->x = (((int32_t)(p->x) * scale_x) >> 8) + pivot->x; + p->y = (((int32_t)(p->y) * scale_y) >> 8) + pivot->y; return; } - - static int32_t angle_prev = INT32_MIN; - static int32_t sinma; - static int32_t cosma; - if(angle_prev != angle) { + lv_area_transform_cache_t * cache = &trans_cache; + if(cache->angle_prev != angle) { int32_t angle_limited = angle; if(angle_limited > 3600) angle_limited -= 3600; if(angle_limited < 0) angle_limited += 3600; @@ -562,40 +471,48 @@ void lv_point_transform(lv_point_t * p, int32_t angle, int32_t zoom, const lv_po int32_t c1 = lv_trigo_sin(angle_low + 90); int32_t c2 = lv_trigo_sin(angle_high + 90); - sinma = (s1 * (10 - angle_rem) + s2 * angle_rem) / 10; - cosma = (c1 * (10 - angle_rem) + c2 * angle_rem) / 10; - sinma = sinma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT); - cosma = cosma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT); - angle_prev = angle; + cache->sinma = (s1 * (10 - angle_rem) + s2 * angle_rem) / 10; + cache->cosma = (c1 * (10 - angle_rem) + c2 * angle_rem) / 10; + cache->sinma = cache->sinma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT); + cache->cosma = cache->cosma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT); + cache->angle_prev = angle; } int32_t x = p->x; int32_t y = p->y; - if(zoom == 256) { - p->x = ((cosma * x - sinma * y) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x; - p->y = ((sinma * x + cosma * y) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y; + if(scale_x == 256 && scale_y == 256) { + p->x = ((cache->cosma * x - cache->sinma * y) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x; + p->y = ((cache->sinma * x + cache->cosma * y) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y; } else { - p->x = (((cosma * x - sinma * y) * zoom) >> (_LV_TRANSFORM_TRIGO_SHIFT + 8)) + pivot->x; - p->y = (((sinma * x + cosma * y) * zoom) >> (_LV_TRANSFORM_TRIGO_SHIFT + 8)) + pivot->y; + if(zoom_first) { + x *= scale_x; + y *= scale_y; + p->x = (((cache->cosma * x - cache->sinma * y)) >> (_LV_TRANSFORM_TRIGO_SHIFT + 8)) + pivot->x; + p->y = (((cache->sinma * x + cache->cosma * y)) >> (_LV_TRANSFORM_TRIGO_SHIFT + 8)) + pivot->y; + } + else { + p->x = (((cache->cosma * x - cache->sinma * y) * scale_x) >> (_LV_TRANSFORM_TRIGO_SHIFT + 8)) + pivot->x; + p->y = (((cache->sinma * x + cache->cosma * y) * scale_y) >> (_LV_TRANSFORM_TRIGO_SHIFT + 8)) + pivot->y; + } + } } - /********************** * STATIC FUNCTIONS **********************/ static bool lv_point_within_circle(const lv_area_t * area, const lv_point_t * p) { - lv_coord_t r = (area->x2 - area->x1) / 2; + int32_t r = (area->x2 - area->x1) / 2; /*Circle center*/ - lv_coord_t cx = area->x1 + r; - lv_coord_t cy = area->y1 + r; + int32_t cx = area->x1 + r; + int32_t cy = area->y1 + r; /*Simplify the code by moving everything to (0, 0)*/ - lv_coord_t px = p->x - cx; - lv_coord_t py = p->y - cy; + int32_t px = p->x - cx; + int32_t py = p->y - cy; uint32_t r_sqrd = r * r; uint32_t dist = (px * px) + (py * py); diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_area.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_area.h index 48dc80744..8916efd92 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_area.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_area.h @@ -14,6 +14,7 @@ extern "C" { * INCLUDES *********************/ #include "../lv_conf_internal.h" +#include "lv_types.h" #include #include @@ -21,12 +22,6 @@ extern "C" { * DEFINES *********************/ -#if LV_USE_LARGE_COORD -typedef int32_t lv_coord_t; -#else -typedef int16_t lv_coord_t; -#endif - /********************** * TYPEDEFS **********************/ @@ -35,20 +30,26 @@ typedef int16_t lv_coord_t; * Represents a point on the screen. */ typedef struct { - lv_coord_t x; - lv_coord_t y; + int32_t x; + int32_t y; } lv_point_t; +typedef struct { + lv_value_precise_t x; + lv_value_precise_t y; +} lv_point_precise_t; + /** Represents an area of the screen.*/ typedef struct { - lv_coord_t x1; - lv_coord_t y1; - lv_coord_t x2; - lv_coord_t y2; + int32_t x1; + int32_t y1; + int32_t x2; + int32_t y2; } lv_area_t; /** Alignments*/ -enum { + +enum _lv_align_t { LV_ALIGN_DEFAULT = 0, LV_ALIGN_TOP_LEFT, LV_ALIGN_TOP_MID, @@ -73,9 +74,14 @@ enum { LV_ALIGN_OUT_RIGHT_MID, LV_ALIGN_OUT_RIGHT_BOTTOM, }; -typedef uint8_t lv_align_t; -enum { +#ifdef DOXYGEN +typedef _lv_align_t lv_align_t; +#else +typedef uint8_t lv_align_t; +#endif /*DOXYGEN*/ + +enum _lv_dir_t { LV_DIR_NONE = 0x00, LV_DIR_LEFT = (1 << 0), LV_DIR_RIGHT = (1 << 1), @@ -86,7 +92,17 @@ enum { LV_DIR_ALL = LV_DIR_HOR | LV_DIR_VER, }; +#ifdef DOXYGEN +typedef _lv_dir_t lv_dir_t; +#else typedef uint8_t lv_dir_t; +#endif /*DOXYGEN*/ + +typedef struct { + int32_t angle_prev; + int32_t sinma; + int32_t cosma; +} lv_area_transform_cache_t; /********************** * GLOBAL PROTOTYPES @@ -100,7 +116,7 @@ typedef uint8_t lv_dir_t; * @param x2 right coordinate of the area * @param y2 bottom coordinate of the area */ -void lv_area_set(lv_area_t * area_p, lv_coord_t x1, lv_coord_t y1, lv_coord_t x2, lv_coord_t y2); +void lv_area_set(lv_area_t * area_p, int32_t x1, int32_t y1, int32_t x2, int32_t y2); /** * Copy an area @@ -120,9 +136,9 @@ inline static void lv_area_copy(lv_area_t * dest, const lv_area_t * src) * @param area_p pointer to an area * @return the width of the area (if x1 == x2 -> width = 1) */ -static inline lv_coord_t lv_area_get_width(const lv_area_t * area_p) +static inline int32_t lv_area_get_width(const lv_area_t * area_p) { - return (lv_coord_t)(area_p->x2 - area_p->x1 + 1); + return (int32_t)(area_p->x2 - area_p->x1 + 1); } /** @@ -130,9 +146,9 @@ static inline lv_coord_t lv_area_get_width(const lv_area_t * area_p) * @param area_p pointer to an area * @return the height of the area (if y1 == y2 -> height = 1) */ -static inline lv_coord_t lv_area_get_height(const lv_area_t * area_p) +static inline int32_t lv_area_get_height(const lv_area_t * area_p) { - return (lv_coord_t)(area_p->y2 - area_p->y1 + 1); + return (int32_t)(area_p->y2 - area_p->y1 + 1); } /** @@ -140,14 +156,14 @@ static inline lv_coord_t lv_area_get_height(const lv_area_t * area_p) * @param area_p pointer to an area * @param w the new width of the area (w == 1 makes x1 == x2) */ -void lv_area_set_width(lv_area_t * area_p, lv_coord_t w); +void lv_area_set_width(lv_area_t * area_p, int32_t w); /** * Set the height of an area * @param area_p pointer to an area * @param h the new height of the area (h == 1 makes y1 == y2) */ -void lv_area_set_height(lv_area_t * area_p, lv_coord_t h); +void lv_area_set_height(lv_area_t * area_p, int32_t h); /** * Set the position of an area (width and height will be kept) @@ -155,7 +171,7 @@ void lv_area_set_height(lv_area_t * area_p, lv_coord_t h); * @param x the new x coordinate of the area * @param y the new y coordinate of the area */ -void _lv_area_set_pos(lv_area_t * area_p, lv_coord_t x, lv_coord_t y); +void _lv_area_set_pos(lv_area_t * area_p, int32_t x, int32_t y); /** * Return with area of an area (x * y) @@ -164,9 +180,9 @@ void _lv_area_set_pos(lv_area_t * area_p, lv_coord_t x, lv_coord_t y); */ uint32_t lv_area_get_size(const lv_area_t * area_p); -void lv_area_increase(lv_area_t * area, lv_coord_t w_extra, lv_coord_t h_extra); +void lv_area_increase(lv_area_t * area, int32_t w_extra, int32_t h_extra); -void lv_area_move(lv_area_t * area, lv_coord_t x_ofs, lv_coord_t y_ofs); +void lv_area_move(lv_area_t * area, int32_t x_ofs, int32_t y_ofs); /** * Get the common parts of two areas @@ -184,11 +200,11 @@ bool _lv_area_intersect(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area * @param a2_p pointer to the second area * @return number of results (max 4) or -1 if no intersect */ -int8_t _lv_area_diff(lv_area_t * res_p, const lv_area_t * a1_p, const lv_area_t * a2_p); +int8_t _lv_area_diff(lv_area_t res_p[], const lv_area_t * a1_p, const lv_area_t * a2_p); /** * Join two areas into a third which involves the other two - * @param res_p pointer to an area, the result will be stored here + * @param a_res_p pointer to an area, the result will be stored here * @param a1_p pointer to the first area * @param a2_p pointer to the second area */ @@ -201,7 +217,7 @@ void _lv_area_join(lv_area_t * a_res_p, const lv_area_t * a1_p, const lv_area_t * @param radius radius of area (e.g. for rounded rectangle) * @return false:the point is out of the area */ -bool _lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p, lv_coord_t radius); +bool _lv_area_is_point_on(const lv_area_t * a_p, const lv_point_t * p_p, int32_t radius); /** * Check if two area has common parts @@ -218,8 +234,7 @@ bool _lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p); * @param radius radius of `aholder_p` (e.g. for rounded rectangle) * @return true: `ain_p` is fully inside `aholder_p` */ -bool _lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p, lv_coord_t radius); - +bool _lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p, int32_t radius); /** * Check if an area is fully out of an other @@ -228,7 +243,7 @@ bool _lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p, lv_coo * @param radius radius of `aholder_p` (e.g. for rounded rectangle) * @return true: `aout_p` is fully outside `aholder_p` */ -bool _lv_area_is_out(const lv_area_t * aout_p, const lv_area_t * aholder_p, lv_coord_t radius); +bool _lv_area_is_out(const lv_area_t * aout_p, const lv_area_t * aholder_p, int32_t radius); /** * Check if 2 area is the same @@ -239,23 +254,66 @@ bool _lv_area_is_equal(const lv_area_t * a, const lv_area_t * b); /** * Align an area to an other - * @param base an are where the other will be aligned + * @param base an area where the other will be aligned * @param to_align the area to align * @param align `LV_ALIGN_...` + * @param ofs_x X offset + * @param ofs_y Y offset */ -void lv_area_align(const lv_area_t * base, lv_area_t * to_align, lv_align_t align, lv_coord_t ofs_x, lv_coord_t ofs_y); +void lv_area_align(const lv_area_t * base, lv_area_t * to_align, lv_align_t align, int32_t ofs_x, int32_t ofs_y); -void lv_point_transform(lv_point_t * p, int32_t angle, int32_t zoom, const lv_point_t * pivot); +void lv_point_transform(lv_point_t * p, int32_t angle, int32_t scale_x, int32_t scale_y, const lv_point_t * pivot, + bool zoom_first); + +static inline lv_point_t lv_point_from_precise(const lv_point_precise_t * p) +{ + lv_point_t point = { + (int32_t)p->x, (int32_t)p->y + }; + + return point; +} + +static inline lv_point_precise_t lv_point_to_precise(const lv_point_t * p) +{ + lv_point_precise_t point = { + (lv_value_precise_t)p->x, (lv_value_precise_t)p->y + }; + + return point; +} + +static inline void lv_point_set(lv_point_t * p, int32_t x, int32_t y) +{ + p->x = x; + p->y = y; +} + +static inline void lv_point_precise_set(lv_point_precise_t * p, lv_value_precise_t x, lv_value_precise_t y) +{ + p->x = x; + p->y = y; +} + +static inline void lv_point_swap(lv_point_t * p1, lv_point_t * p2) +{ + lv_point_t tmp = *p1; + *p1 = *p2; + *p2 = tmp; +} + +static inline void lv_point_precise_swap(lv_point_precise_t * p1, lv_point_precise_t * p2) +{ + lv_point_precise_t tmp = *p1; + *p1 = *p2; + *p2 = tmp; +} /********************** * MACROS **********************/ -#if LV_USE_LARGE_COORD #define _LV_COORD_TYPE_SHIFT (29U) -#else -#define _LV_COORD_TYPE_SHIFT (13U) -#endif #define _LV_COORD_TYPE_MASK (3 << _LV_COORD_TYPE_SHIFT) #define _LV_COORD_TYPE(x) ((x) & _LV_COORD_TYPE_MASK) /*Extract type specifiers*/ @@ -265,15 +323,14 @@ void lv_point_transform(lv_point_t * p, int32_t angle, int32_t zoom, const lv_po #define _LV_COORD_TYPE_SPEC (1 << _LV_COORD_TYPE_SHIFT) #define _LV_COORD_TYPE_PX_NEG (3 << _LV_COORD_TYPE_SHIFT) -#define LV_COORD_IS_PX(x) (_LV_COORD_TYPE(x) == _LV_COORD_TYPE_PX || \ - _LV_COORD_TYPE(x) == _LV_COORD_TYPE_PX_NEG ? true : false) -#define LV_COORD_IS_SPEC(x) (_LV_COORD_TYPE(x) == _LV_COORD_TYPE_SPEC ? true : false) +#define LV_COORD_IS_PX(x) (_LV_COORD_TYPE(x) == _LV_COORD_TYPE_PX || _LV_COORD_TYPE(x) == _LV_COORD_TYPE_PX_NEG) +#define LV_COORD_IS_SPEC(x) (_LV_COORD_TYPE(x) == _LV_COORD_TYPE_SPEC) #define LV_COORD_SET_SPEC(x) ((x) | _LV_COORD_TYPE_SPEC) /*Special coordinates*/ #define LV_PCT(x) (x < 0 ? LV_COORD_SET_SPEC(1000 - (x)) : LV_COORD_SET_SPEC(x)) -#define LV_COORD_IS_PCT(x) ((LV_COORD_IS_SPEC(x) && _LV_COORD_PLAIN(x) <= 2000) ? true : false) +#define LV_COORD_IS_PCT(x) ((LV_COORD_IS_SPEC(x) && _LV_COORD_PLAIN(x) <= 2000)) #define LV_COORD_GET_PCT(x) (_LV_COORD_PLAIN(x) > 1000 ? 1000 - _LV_COORD_PLAIN(x) : _LV_COORD_PLAIN(x)) #define LV_SIZE_CONTENT LV_COORD_SET_SPEC(2001) @@ -287,16 +344,25 @@ LV_EXPORT_CONST_INT(LV_COORD_MAX); LV_EXPORT_CONST_INT(LV_COORD_MIN); /** - * Convert a percentage value to `lv_coord_t`. + * Convert a percentage value to `int32_t`. * Percentage values are stored in special range * @param x the percentage (0..1000) * @return a coordinate that stores the percentage */ -static inline lv_coord_t lv_pct(lv_coord_t x) +static inline int32_t lv_pct(int32_t x) { return LV_PCT(x); } +static inline int32_t lv_pct_to_px(int32_t v, int32_t base) +{ + if(LV_COORD_IS_PCT(v)) { + return (LV_COORD_GET_PCT(v) * base) / 100; + } + + return v; +} + #ifdef __cplusplus } /*extern "C"*/ #endif diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_array.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_array.c new file mode 100644 index 000000000..4d07949d5 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_array.c @@ -0,0 +1,172 @@ +/** + * @file lv_array.c + * Array. + * The nodes are dynamically allocated by the 'lv_mem' module, + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_array.h" +#include "../stdlib/lv_mem.h" +#include "../stdlib/lv_string.h" + +#include "lv_assert.h" +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ +void lv_array_init(lv_array_t * array, uint32_t capacity, uint32_t element_size) +{ + array->size = 0; + array->capacity = capacity; + array->element_size = element_size; + + array->data = lv_malloc(capacity * element_size); + LV_ASSERT_MALLOC(array->data); +} + +void lv_array_deinit(lv_array_t * array) +{ + if(array->data) { + lv_free(array->data); + array->data = NULL; + } + + array->size = 0; + array->capacity = 0; +} + +void lv_array_copy(lv_array_t * target, const lv_array_t * source) +{ + if(lv_array_is_empty(source)) { + return; + } + lv_array_deinit(target); + lv_array_init(target, source->capacity, source->element_size); + lv_memcpy(target->data, source->data, source->size * source->element_size); + target->size = source->size; +} + +lv_result_t lv_array_remove(lv_array_t * array, uint32_t index) +{ + if(index >= array->size) { + return LV_RESULT_INVALID; + } + + /*Shortcut*/ + if(index == array->size - 1) { + lv_array_resize(array, array->size - 1); + return LV_RESULT_OK; + } + + uint8_t * start = lv_array_at(array, index); + uint8_t * remaining = start + array->element_size; + uint32_t remaining_size = (array->size - index - 1) * array->element_size; + lv_memcpy(start, remaining, remaining_size); + lv_array_resize(array, array->size - 1); + return LV_RESULT_OK; +} + +lv_result_t lv_array_erase(lv_array_t * array, uint32_t start, uint32_t end) +{ + if(end > array->size) { + end = array->size; + } + + if(start >= end) { + return LV_RESULT_INVALID; + } + + /*Shortcut*/ + if(end == array->size) { + lv_array_resize(array, start); + return LV_RESULT_OK; + } + + uint8_t * start_p = lv_array_at(array, start); + uint8_t * remaining = start_p + (end - start) * array->element_size; + uint32_t remaining_size = (array->size - end) * array->element_size; + lv_memcpy(start_p, remaining, remaining_size); + lv_array_resize(array, array->size - (end - start)); + return LV_RESULT_OK; +} + +void lv_array_resize(lv_array_t * array, uint32_t new_capacity) +{ + uint8_t * data = lv_realloc(array->data, new_capacity * array->element_size); + LV_ASSERT_NULL(data); + array->data = data; + array->capacity = new_capacity; + if(array->size > new_capacity) { + array->size = new_capacity; + } +} + +lv_result_t lv_array_concat(lv_array_t * array, const lv_array_t * other) +{ + LV_ASSERT_NULL(array->data); + uint32_t size = other->size; + if(array->size + size > array->capacity) { + /*array is full*/ + lv_array_resize(array, array->size + size); + } + + uint8_t * data = array->data + array->size * array->element_size; + lv_memcpy(data, other->data, array->element_size * size); + array->size += size; + return LV_RESULT_OK; +} + +lv_result_t lv_array_push_back(lv_array_t * array, const void * element) +{ + LV_ASSERT_NULL(array->data); + + if(array->size == array->capacity) { + /*array is full*/ + lv_array_resize(array, array->capacity + 1); + } + + uint8_t * data = array->data + array->size * array->element_size; + lv_memcpy(data, element, array->element_size); + array->size++; + return LV_RESULT_OK; +} + +void * lv_array_at(const lv_array_t * array, uint32_t index) +{ + if(index >= array->size) { + return NULL; + } + + LV_ASSERT_NULL(array->data); + return array->data + index * array->element_size; +} + +lv_result_t lv_array_assign(lv_array_t * array, uint32_t index, const void * value) +{ + uint8_t * data = lv_array_at(array, index); + if(data == NULL) return LV_RESULT_INVALID; + + lv_memcpy(data, value, array->element_size); + return LV_RESULT_OK; +} diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_array.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_array.h new file mode 100644 index 000000000..3cdb1c6c6 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_array.h @@ -0,0 +1,203 @@ +/** + * @file lv_array.h + * Array. The elements are dynamically allocated by the 'lv_mem' module. + */ + +#ifndef LV_ARRAY_H +#define LV_ARRAY_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include +#include + +#include "lv_types.h" + +/********************* + * DEFINES + *********************/ +#define LV_ARRAY_DEFAULT_CAPACITY 8 + +/********************** + * TYPEDEFS + **********************/ + +/** Description of a array*/ +typedef struct { + uint8_t * data; + uint32_t size; + uint32_t capacity; + uint32_t element_size; +} lv_array_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Init an array. + * @param array pointer to an `lv_array_t` variable to initialize + * @param capacity the initial capacity of the array + * @param element_size the size of an element in bytes + */ +void lv_array_init(lv_array_t * array, uint32_t capacity, uint32_t element_size); + +/** + * Resize the array to the given capacity. + * @note if the new capacity is smaller than the current size, the array will be truncated. + * @param array pointer to an `lv_array_t` variable + * @param new_capacity the new capacity of the array + */ +void lv_array_resize(lv_array_t * array, uint32_t new_capacity); + +/** + * Deinit the array, and free the allocated memory + * @param array pointer to an `lv_array_t` variable to deinitialize + */ +void lv_array_deinit(lv_array_t * array); + +/** + * Return how many elements are stored in the array. + * @param array pointer to an `lv_array_t` variable + * @return the number of elements stored in the array + */ +static inline uint32_t lv_array_size(const lv_array_t * array) +{ + return array->size; +} + +/** + * Return the capacity of the array, i.e. how many elements can be stored. + * @param array pointer to an `lv_array_t` variable + * @return the capacity of the array + */ +static inline uint32_t lv_array_capacity(const lv_array_t * array) +{ + return array->capacity; +} + +/** + * Return if the array is empty + * @param array pointer to an `lv_array_t` variable + * @return true: array is empty; false: array is not empty + */ +static inline bool lv_array_is_empty(const lv_array_t * array) +{ + return array->size == 0; +} + +/** + * Return if the array is full + * @param array pointer to an `lv_array_t` variable + * @return true: array is full; false: array is not full + */ +static inline bool lv_array_is_full(const lv_array_t * array) +{ + return array->size == array->capacity; +} + +/** + * Copy an array to another. + * @note this will create a new array with the same capacity and size as the source array. + * @param target pointer to an `lv_array_t` variable to copy to + * @param source pointer to an `lv_array_t` variable to copy from + */ +void lv_array_copy(lv_array_t * target, const lv_array_t * source); + +/** + * Remove all elements in array. + * @param array pointer to an `lv_array_t` variable + */ +static inline void lv_array_clear(lv_array_t * array) +{ + array->size = 0; +} + +/** + * Remove the element at the specified position in the array. + * @param array pointer to an `lv_array_t` variable + * @param index the index of the element to remove + * @return LV_RESULT_OK: success, otherwise: error + */ +lv_result_t lv_array_remove(lv_array_t * array, uint32_t index); + +/** + * Remove from the array either a single element or a range of elements ([start, end)). + * @note This effectively reduces the container size by the number of elements removed. + * @note When start equals to end, the function has no effect. + * @param array pointer to an `lv_array_t` variable + * @param start the index of the first element to be removed + * @param end the index of the first element that is not to be removed + * @return LV_RESULT_OK: success, otherwise: error + */ +lv_result_t lv_array_erase(lv_array_t * array, uint32_t start, uint32_t end); + +/** + * Concatenate two arrays. Adds new elements to the end of the array. + * @note The destination array is automatically expanded as necessary. + * @param array pointer to an `lv_array_t` variable + * @param other pointer to the array to concatenate + * @return LV_RESULT_OK: success, otherwise: error + */ +lv_result_t lv_array_concat(lv_array_t * array, const lv_array_t * other); + +/** + * Push back element. Adds a new element to the end of the array. + * If the array capacity is not enough for the new element, the array will be resized automatically. + * @param array pointer to an `lv_array_t` variable + * @param element pointer to the element to add + * @return LV_RESULT_OK: success, otherwise: error + */ +lv_result_t lv_array_push_back(lv_array_t * array, const void * element); + +/** + * Assigns one content to the array, replacing its current content. + * @param array pointer to an `lv_array_t` variable + * @param index the index of the element to replace + * @param value pointer to the elements to add + * @return true: success; false: error + */ +lv_result_t lv_array_assign(lv_array_t * array, uint32_t index, const void * value); + +/** + * Returns a pointer to the element at position n in the array. + * @param array pointer to an `lv_array_t` variable + * @param index the index of the element to return + * @return a pointer to the requested element, NULL if `index` is out of range + */ +void * lv_array_at(const lv_array_t * array, uint32_t index); + +/** + * Returns a pointer to the first element in the array. + * @param array pointer to an `lv_array_t` variable + * @return a pointer to the first element in the array + */ +static inline void * lv_array_front(const lv_array_t * array) +{ + return lv_array_at(array, 0); +} + +/** + * Returns a pointer to the last element in the array. + * @param array pointer to an `lv_array_t` variable + */ +static inline void * lv_array_back(const lv_array_t * array) +{ + return lv_array_at(array, lv_array_size(array) - 1); +} + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_assert.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_assert.h index 48db7443c..1b1b3b174 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_assert.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_assert.h @@ -15,7 +15,7 @@ extern "C" { *********************/ #include "../lv_conf_internal.h" #include "lv_log.h" -#include "lv_mem.h" +#include "../stdlib/lv_mem.h" #include LV_ASSERT_HANDLER_INCLUDE /********************* @@ -42,12 +42,12 @@ extern "C" { } \ } while(0) -#define LV_ASSERT_MSG(expr, msg) \ - do { \ - if(!(expr)) { \ - LV_LOG_ERROR("Asserted at expression: %s (%s)", #expr, msg); \ - LV_ASSERT_HANDLER \ - } \ +#define LV_ASSERT_MSG(expr, format, ...) \ + do { \ + if(!(expr)) { \ + LV_LOG_ERROR("Asserted at expression: %s " format , #expr, ##__VA_ARGS__); \ + LV_ASSERT_HANDLER \ + } \ } while(0) /*----------------- @@ -67,7 +67,7 @@ extern "C" { #endif #if LV_USE_ASSERT_MEM_INTEGRITY -# define LV_ASSERT_MEM_INTEGRITY() LV_ASSERT_MSG(lv_mem_test() == LV_RES_OK, "Memory integrity error"); +# define LV_ASSERT_MEM_INTEGRITY() LV_ASSERT_MSG(lv_mem_test() == LV_RESULT_OK, "Memory integrity error"); #else # define LV_ASSERT_MEM_INTEGRITY() #endif diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_async.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_async.c index c4941e811..591d2303f 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_async.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_async.c @@ -8,8 +8,8 @@ *********************/ #include "lv_async.h" -#include "lv_mem.h" #include "lv_timer.h" +#include "../stdlib/lv_mem.h" /********************* * DEFINES @@ -42,33 +42,33 @@ static void lv_async_timer_cb(lv_timer_t * timer); * GLOBAL FUNCTIONS **********************/ -lv_res_t lv_async_call(lv_async_cb_t async_xcb, void * user_data) +lv_result_t lv_async_call(lv_async_cb_t async_xcb, void * user_data) { /*Allocate an info structure*/ - lv_async_info_t * info = lv_mem_alloc(sizeof(lv_async_info_t)); + lv_async_info_t * info = lv_malloc(sizeof(lv_async_info_t)); if(info == NULL) - return LV_RES_INV; + return LV_RESULT_INVALID; /*Create a new timer*/ lv_timer_t * timer = lv_timer_create(lv_async_timer_cb, 0, info); if(timer == NULL) { - lv_mem_free(info); - return LV_RES_INV; + lv_free(info); + return LV_RESULT_INVALID; } info->cb = async_xcb; info->user_data = user_data; lv_timer_set_repeat_count(timer, 1); - return LV_RES_OK; + return LV_RESULT_OK; } -lv_res_t lv_async_call_cancel(lv_async_cb_t async_xcb, void * user_data) +lv_result_t lv_async_call_cancel(lv_async_cb_t async_xcb, void * user_data) { lv_timer_t * timer = lv_timer_get_next(NULL); - lv_res_t res = LV_RES_INV; + lv_result_t res = LV_RESULT_INVALID; while(timer != NULL) { /*Find the next timer node*/ @@ -80,9 +80,9 @@ lv_res_t lv_async_call_cancel(lv_async_cb_t async_xcb, void * user_data) /*Match user function callback and user data*/ if(info->cb == async_xcb && info->user_data == user_data) { - lv_timer_del(timer); - lv_mem_free(info); - res = LV_RES_OK; + lv_timer_delete(timer); + lv_free(info); + res = LV_RESULT_OK; } } @@ -98,8 +98,11 @@ lv_res_t lv_async_call_cancel(lv_async_cb_t async_xcb, void * user_data) static void lv_async_timer_cb(lv_timer_t * timer) { + /*Save the info because an lv_async_call_cancel might delete it in the callback*/ lv_async_info_t * info = (lv_async_info_t *)timer->user_data; + lv_async_info_t info_save = *info; + lv_timer_delete(timer); + lv_free(info); - info->cb(info->user_data); - lv_mem_free(info); + info_save.cb(info_save.user_data); } diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_async.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_async.h index 4ad5756d9..362a0ffad 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_async.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_async.h @@ -41,14 +41,14 @@ typedef void (*lv_async_cb_t)(void *); * the `func_name(object, callback, ...)` convention) * @param user_data custom parameter */ -lv_res_t lv_async_call(lv_async_cb_t async_xcb, void * user_data); +lv_result_t lv_async_call(lv_async_cb_t async_xcb, void * user_data); /** * Cancel an asynchronous function call * @param async_xcb a callback which is the task itself. * @param user_data custom parameter */ -lv_res_t lv_async_call_cancel(lv_async_cb_t async_xcb, void * user_data); +lv_result_t lv_async_call_cancel(lv_async_cb_t async_xcb, void * user_data); /********************** * MACROS diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.c index 70af1c4b4..1fa374dfc 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.c @@ -8,8 +8,9 @@ *********************/ #include #include "lv_bidi.h" -#include "lv_txt.h" -#include "../misc/lv_mem.h" +#include "lv_text.h" +#include "../stdlib/lv_mem.h" +#include "../stdlib/lv_string.h" #if LV_USE_BIDI @@ -31,6 +32,11 @@ typedef struct { lv_base_dir_t dir; } bracket_stack_t; +typedef struct { + bracket_stack_t br_stack[LV_BIDI_BRACKLET_DEPTH]; + uint8_t br_stack_p; +} lv_bidi_ctx_t; + /********************** * STATIC PROTOTYPES **********************/ @@ -41,12 +47,14 @@ static bool lv_bidi_letter_is_weak(uint32_t letter); static bool lv_bidi_letter_is_rtl(uint32_t letter); static bool lv_bidi_letter_is_neutral(uint32_t letter); -static lv_base_dir_t get_next_run(const char * txt, lv_base_dir_t base_dir, uint32_t max_len, uint32_t * len, +static lv_base_dir_t get_next_run(lv_bidi_ctx_t * ctx, const char * txt, lv_base_dir_t base_dir, uint32_t max_len, + uint32_t * len, uint16_t * pos_conv_len); static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t * pos_conv_out, uint16_t pos_conv_rd_base, uint16_t pos_conv_len); static uint32_t char_change_to_pair(uint32_t letter); -static lv_base_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32_t len, uint32_t letter, +static lv_base_dir_t bracket_process(lv_bidi_ctx_t * ctx, const char * txt, uint32_t next_pos, uint32_t len, + uint32_t letter, lv_base_dir_t base_dir); static void fill_pos_conv(uint16_t * out, uint16_t len, uint16_t index); static uint32_t get_txt_len(const char * txt, uint32_t max_len); @@ -56,8 +64,6 @@ static uint32_t get_txt_len(const char * txt, uint32_t max_len); **********************/ static const uint8_t bracket_left[] = {"<({["}; static const uint8_t bracket_right[] = {">)}]"}; -static bracket_stack_t br_stack[LV_BIDI_BRACKLET_DEPTH]; -static uint8_t br_stack_p; /********************** * MACROS @@ -67,13 +73,6 @@ static uint8_t br_stack_p; * GLOBAL FUNCTIONS **********************/ -/** - * Convert a text to get the characters in the correct visual order according to - * Unicode Bidirectional Algorithm - * @param str_in the text to process - * @param str_out store the result here. Has the be `strlen(str_in)` length - * @param base_dir `LV_BASE_DIR_LTR` or `LV_BASE_DIR_RTL` - */ void _lv_bidi_process(const char * str_in, char * str_out, lv_base_dir_t base_dir) { if(base_dir == LV_BASE_DIR_AUTO) base_dir = _lv_bidi_detect_base_dir(str_in); @@ -110,7 +109,7 @@ lv_base_dir_t _lv_bidi_detect_base_dir(const char * txt) uint32_t i = 0; uint32_t letter; while(txt[i] != '\0') { - letter = _lv_txt_encoded_next(txt, &i); + letter = _lv_text_encoded_next(txt, &i); lv_base_dir_t dir; dir = lv_bidi_get_letter_dir(letter); @@ -122,28 +121,16 @@ lv_base_dir_t _lv_bidi_detect_base_dir(const char * txt) else return LV_BIDI_BASE_DIR_DEF; } -/** - * Get the logical position of a character in a line - * @param str_in the input string. Can be only one line. - * @param bidi_txt internally the text is bidi processed which buffer can be get here. - * If not required anymore has to freed with `lv_mem_free()` - * Can be `NULL` is unused - * @param len length of the line in character count - * @param base_dir base direction of the text: `LV_BASE_DIR_LTR` or `LV_BASE_DIR_RTL` - * @param visual_pos the visual character position which logical position should be get - * @param is_rtl tell the char at `visual_pos` is RTL or LTR context - * @return the logical character position - */ uint16_t _lv_bidi_get_logical_pos(const char * str_in, char ** bidi_txt, uint32_t len, lv_base_dir_t base_dir, uint32_t visual_pos, bool * is_rtl) { uint32_t pos_conv_len = get_txt_len(str_in, len); - char * buf = lv_mem_buf_get(len + 1); + char * buf = lv_malloc(len + 1); if(buf == NULL) return (uint16_t) -1; - uint16_t * pos_conv_buf = lv_mem_buf_get(pos_conv_len * sizeof(uint16_t)); + uint16_t * pos_conv_buf = lv_malloc(pos_conv_len * sizeof(uint16_t)); if(pos_conv_buf == NULL) { - lv_mem_buf_release(buf); + lv_free(buf); return (uint16_t) -1; } @@ -153,34 +140,22 @@ uint16_t _lv_bidi_get_logical_pos(const char * str_in, char ** bidi_txt, uint32_ if(is_rtl) *is_rtl = IS_RTL_POS(pos_conv_buf[visual_pos]); - if(bidi_txt == NULL) lv_mem_buf_release(buf); + if(bidi_txt == NULL) lv_free(buf); uint16_t res = GET_POS(pos_conv_buf[visual_pos]); - lv_mem_buf_release(pos_conv_buf); + lv_free(pos_conv_buf); return res; } -/** - * Get the visual position of a character in a line - * @param str_in the input string. Can be only one line. - * @param bidi_txt internally the text is bidi processed which buffer can be get here. - * If not required anymore has to freed with `lv_mem_free()` - * Can be `NULL` is unused - * @param len length of the line in character count - * @param base_dir base direction of the text: `LV_BASE_DIR_LTR` or `LV_BASE_DIR_RTL` - * @param logical_pos the logical character position which visual position should be get - * @param is_rtl tell the char at `logical_pos` is RTL or LTR context - * @return the visual character position - */ uint16_t _lv_bidi_get_visual_pos(const char * str_in, char ** bidi_txt, uint16_t len, lv_base_dir_t base_dir, uint32_t logical_pos, bool * is_rtl) { uint32_t pos_conv_len = get_txt_len(str_in, len); - char * buf = lv_mem_buf_get(len + 1); + char * buf = lv_malloc(len + 1); if(buf == NULL) return (uint16_t) -1; - uint16_t * pos_conv_buf = lv_mem_buf_get(pos_conv_len * sizeof(uint16_t)); + uint16_t * pos_conv_buf = lv_malloc(pos_conv_len * sizeof(uint16_t)); if(pos_conv_buf == NULL) { - lv_mem_buf_release(buf); + lv_free(buf); return (uint16_t) -1; } @@ -192,27 +167,17 @@ uint16_t _lv_bidi_get_visual_pos(const char * str_in, char ** bidi_txt, uint16_t if(GET_POS(pos_conv_buf[i]) == logical_pos) { if(is_rtl) *is_rtl = IS_RTL_POS(pos_conv_buf[i]); - lv_mem_buf_release(pos_conv_buf); + lv_free(pos_conv_buf); - if(bidi_txt == NULL) lv_mem_buf_release(buf); + if(bidi_txt == NULL) lv_free(buf); return i; } } - lv_mem_buf_release(pos_conv_buf); - if(bidi_txt == NULL) lv_mem_buf_release(buf); + lv_free(pos_conv_buf); + if(bidi_txt == NULL) lv_free(buf); return (uint16_t) -1; } -/** - * Bidi process a paragraph of text - * @param str_in the string to process - * @param str_out store the result here - * @param len length of the text - * @param base_dir base dir of the text - * @param pos_conv_out an `uint16_t` array to store the related logical position of the character. - * Can be `NULL` is unused - * @param pos_conv_len length of `pos_conv_out` in element count - */ void _lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_base_dir_t base_dir, uint16_t * pos_conv_out, uint16_t pos_conv_len) { @@ -239,19 +204,20 @@ void _lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t le lv_base_dir_t dir = base_dir; /*Empty the bracket stack*/ - br_stack_p = 0; + lv_bidi_ctx_t ctx; + lv_memzero(&ctx, sizeof(ctx)); /*Process neutral chars in the beginning*/ while(rd < len) { - uint32_t letter = _lv_txt_encoded_next(str_in, &rd); + uint32_t letter = _lv_text_encoded_next(str_in, &rd); pos_conv_rd++; dir = lv_bidi_get_letter_dir(letter); - if(dir == LV_BASE_DIR_NEUTRAL) dir = bracket_process(str_in, rd, len, letter, base_dir); - if(dir != LV_BASE_DIR_NEUTRAL && dir != LV_BASE_DIR_WEAK) break; + if(dir == LV_BASE_DIR_NEUTRAL) dir = bracket_process(&ctx, str_in, rd, len, letter, base_dir); + else if(dir != LV_BASE_DIR_WEAK) break; } - if(rd && str_in[rd] != '\0') { - _lv_txt_encoded_prev(str_in, &rd); + if(rd && str_in[rd] != '\0' && rd < len) { + _lv_text_encoded_prev(str_in, &rd); pos_conv_rd--; } @@ -277,7 +243,7 @@ void _lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t le /*Get and process the runs*/ while(rd < len && str_in[rd]) { - run_dir = get_next_run(&str_in[rd], base_dir, len - rd, &run_len, &pos_conv_run_len); + run_dir = get_next_run(&ctx, &str_in[rd], base_dir, len - rd, &run_len, &pos_conv_run_len); if(base_dir == LV_BASE_DIR_LTR) { if(run_dir == LV_BASE_DIR_LTR) { @@ -328,10 +294,10 @@ static uint32_t lv_bidi_get_next_paragraph(const char * txt) { uint32_t i = 0; - _lv_txt_encoded_next(txt, &i); + _lv_text_encoded_next(txt, &i); while(txt[i] != '\0' && txt[i] != '\n' && txt[i] != '\r') { - _lv_txt_encoded_next(txt, &i); + _lv_text_encoded_next(txt, &i); } return i; @@ -361,7 +327,7 @@ static bool lv_bidi_letter_is_weak(uint32_t letter) static const char weaks[] = "0123456789"; do { - uint32_t x = _lv_txt_encoded_next(weaks, &i); + uint32_t x = _lv_text_encoded_next(weaks, &i); if(letter == x) { return true; } @@ -412,7 +378,7 @@ static uint32_t get_txt_len(const char * txt, uint32_t max_len) uint32_t i = 0; while(i < max_len && txt[i] != '\0') { - _lv_txt_encoded_next(txt, &i); + _lv_text_encoded_next(txt, &i); len++; } @@ -428,7 +394,8 @@ static void fill_pos_conv(uint16_t * out, uint16_t len, uint16_t index) } } -static lv_base_dir_t get_next_run(const char * txt, lv_base_dir_t base_dir, uint32_t max_len, uint32_t * len, +static lv_base_dir_t get_next_run(lv_bidi_ctx_t * ctx, const char * txt, lv_base_dir_t base_dir, uint32_t max_len, + uint32_t * len, uint16_t * pos_conv_len) { uint32_t i = 0; @@ -436,17 +403,17 @@ static lv_base_dir_t get_next_run(const char * txt, lv_base_dir_t base_dir, uint uint16_t pos_conv_i = 0; - letter = _lv_txt_encoded_next(txt, NULL); + letter = _lv_text_encoded_next(txt, NULL); lv_base_dir_t dir = lv_bidi_get_letter_dir(letter); - if(dir == LV_BASE_DIR_NEUTRAL) dir = bracket_process(txt, 0, max_len, letter, base_dir); + if(dir == LV_BASE_DIR_NEUTRAL) dir = bracket_process(ctx, txt, 0, max_len, letter, base_dir); /*Find the first strong char. Skip the neutrals*/ while(dir == LV_BASE_DIR_NEUTRAL || dir == LV_BASE_DIR_WEAK) { - letter = _lv_txt_encoded_next(txt, &i); + letter = _lv_text_encoded_next(txt, &i); pos_conv_i++; dir = lv_bidi_get_letter_dir(letter); - if(dir == LV_BASE_DIR_NEUTRAL) dir = bracket_process(txt, i, max_len, letter, base_dir); + if(dir == LV_BASE_DIR_NEUTRAL) dir = bracket_process(ctx, txt, i, max_len, letter, base_dir); if(dir == LV_BASE_DIR_LTR || dir == LV_BASE_DIR_RTL) break; @@ -467,10 +434,10 @@ static lv_base_dir_t get_next_run(const char * txt, lv_base_dir_t base_dir, uint /*Find the next char which has different direction*/ lv_base_dir_t next_dir = base_dir; while(i_prev < max_len && txt[i] != '\0' && txt[i] != '\n' && txt[i] != '\r') { - letter = _lv_txt_encoded_next(txt, &i); + letter = _lv_text_encoded_next(txt, &i); pos_conv_i++; next_dir = lv_bidi_get_letter_dir(letter); - if(next_dir == LV_BASE_DIR_NEUTRAL) next_dir = bracket_process(txt, i, max_len, letter, base_dir); + if(next_dir == LV_BASE_DIR_NEUTRAL) next_dir = bracket_process(ctx, txt, i, max_len, letter, base_dir); if(next_dir == LV_BASE_DIR_WEAK) { if(run_dir == LV_BASE_DIR_RTL) { @@ -530,7 +497,7 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t * uint16_t pos_conv_wr = 0; while(i) { - uint32_t letter = _lv_txt_encoded_prev(src, &i); + uint32_t letter = _lv_text_encoded_prev(src, &i); uint16_t pos_conv_letter = --pos_conv_i; /*Keep weak letters (numbers) as LTR*/ @@ -540,7 +507,7 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t * uint16_t pos_conv_last_weak = pos_conv_i; uint16_t pos_conv_first_weak = pos_conv_i; while(i) { - letter = _lv_txt_encoded_prev(src, &i); + letter = _lv_text_encoded_prev(src, &i); pos_conv_letter = --pos_conv_i; /*No need to call `char_change_to_pair` because there not such chars here*/ @@ -548,7 +515,7 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t * /*Finish on non-weak char*/ /*but treat number and currency related chars as weak*/ if(lv_bidi_letter_is_weak(letter) == false && letter != '.' && letter != ',' && letter != '$' && letter != '%') { - _lv_txt_encoded_next(src, &i); /*Rewind one letter*/ + _lv_text_encoded_next(src, &i); /*Rewind one letter*/ pos_conv_i++; first_weak = i; pos_conv_first_weak = pos_conv_i; @@ -569,7 +536,7 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t * /*Simply store in reversed order*/ else { - uint32_t letter_size = _lv_txt_encoded_size((const char *)&src[i]); + uint32_t letter_size = _lv_text_encoded_size((const char *)&src[i]); /*Swap arithmetical symbols*/ if(letter_size == 1) { uint32_t new_letter = letter = char_change_to_pair(letter); @@ -604,7 +571,8 @@ static uint32_t char_change_to_pair(uint32_t letter) return letter; } -static lv_base_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32_t len, uint32_t letter, +static lv_base_dir_t bracket_process(lv_bidi_ctx_t * ctx, const char * txt, uint32_t next_pos, uint32_t len, + uint32_t letter, lv_base_dir_t base_dir) { lv_base_dir_t bracket_dir = LV_BASE_DIR_NEUTRAL; @@ -617,7 +585,7 @@ static lv_base_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32 *If a char with base dir. direction is found then the brackets will have `base_dir` direction*/ uint32_t txt_i = next_pos; while(txt_i < len) { - uint32_t letter_next = _lv_txt_encoded_next(txt, &txt_i); + uint32_t letter_next = _lv_text_encoded_next(txt, &txt_i); if(letter_next == bracket_right[i]) { /*Closing bracket found*/ break; @@ -639,9 +607,9 @@ static lv_base_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32 /*If there were no matching strong chars in the brackets then check the previous chars*/ txt_i = next_pos; - if(txt_i) _lv_txt_encoded_prev(txt, &txt_i); + if(txt_i) _lv_text_encoded_prev(txt, &txt_i); while(txt_i > 0) { - uint32_t letter_next = _lv_txt_encoded_prev(txt, &txt_i); + uint32_t letter_next = _lv_text_encoded_prev(txt, &txt_i); lv_base_dir_t letter_dir = lv_bidi_get_letter_dir(letter_next); if(letter_dir == LV_BASE_DIR_LTR || letter_dir == LV_BASE_DIR_RTL) { bracket_dir = letter_dir; @@ -662,19 +630,19 @@ static lv_base_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32 /*The letter was an opening bracket*/ if(bracket_left[i] != '\0') { - if(bracket_dir == LV_BASE_DIR_NEUTRAL || br_stack_p == LV_BIDI_BRACKLET_DEPTH) return LV_BASE_DIR_NEUTRAL; + if(bracket_dir == LV_BASE_DIR_NEUTRAL || ctx->br_stack_p == LV_BIDI_BRACKLET_DEPTH) return LV_BASE_DIR_NEUTRAL; - br_stack[br_stack_p].bracklet_pos = i; - br_stack[br_stack_p].dir = bracket_dir; + ctx->br_stack[ctx->br_stack_p].bracklet_pos = i; + ctx->br_stack[ctx->br_stack_p].dir = bracket_dir; - br_stack_p++; + ctx->br_stack_p++; return bracket_dir; } - else if(br_stack_p > 0) { + else if(ctx->br_stack_p > 0) { /*Is the letter a closing bracket of the last opening?*/ - if(letter == bracket_right[br_stack[br_stack_p - 1].bracklet_pos]) { - bracket_dir = br_stack[br_stack_p - 1].dir; - br_stack_p--; + if(letter == bracket_right[ctx->br_stack[ctx->br_stack_p - 1].bracklet_pos]) { + bracket_dir = ctx->br_stack[ctx->br_stack_p - 1].dir; + ctx->br_stack_p--; return bracket_dir; } } diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.h index a27b58086..e5b19c295 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.h @@ -17,7 +17,7 @@ extern "C" { #include #include -#include "lv_txt.h" +#include "lv_text.h" /********************* * DEFINES @@ -30,7 +30,7 @@ extern "C" { /********************** * TYPEDEFS **********************/ -enum { +enum _lv_base_dir_t { LV_BASE_DIR_LTR = 0x00, LV_BASE_DIR_RTL = 0x01, LV_BASE_DIR_AUTO = 0x02, @@ -39,7 +39,11 @@ enum { LV_BASE_DIR_WEAK = 0x21, }; +#ifdef DOXYGEN +typedef _lv_base_dir_t lv_base_dir_t; +#else typedef uint8_t lv_base_dir_t; +#endif /*DOXYGEN*/ /********************** * GLOBAL PROTOTYPES @@ -66,7 +70,7 @@ lv_base_dir_t _lv_bidi_detect_base_dir(const char * txt); * Get the logical position of a character in a line * @param str_in the input string. Can be only one line. * @param bidi_txt internally the text is bidi processed which buffer can be get here. - * If not required anymore has to freed with `lv_mem_free()` + * If not required anymore has to freed with `lv_free()` * Can be `NULL` is unused * @param len length of the line in character count * @param base_dir base direction of the text: `LV_BASE_DIR_LTR` or `LV_BASE_DIR_RTL` @@ -81,7 +85,7 @@ uint16_t _lv_bidi_get_logical_pos(const char * str_in, char ** bidi_txt, uint32_ * Get the visual position of a character in a line * @param str_in the input string. Can be only one line. * @param bidi_txt internally the text is bidi processed which buffer can be get here. - * If not required anymore has to freed with `lv_mem_free()` + * If not required anymore has to freed with `lv_free()` * Can be `NULL` is unused * @param len length of the line in character count * @param base_dir base direction of the text: `LV_BASE_DIR_LTR` or `LV_BASE_DIR_RTL` @@ -113,7 +117,6 @@ void _lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t le */ void lv_bidi_calculate_align(lv_text_align_t * align, lv_base_dir_t * base_dir, const char * txt); - /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_color.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_color.c index 9ad5a143d..942b75427 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_color.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_color.c @@ -8,6 +8,7 @@ *********************/ #include "lv_color.h" #include "lv_log.h" +#include "../misc/lv_color.h" /********************* * DEFINES @@ -20,6 +21,13 @@ /********************** * STATIC PROTOTYPES **********************/ +static lv_color_t lv_color_filter_shade_cb(const lv_color_filter_dsc_t * dsc, lv_color_t c, lv_opa_t opa); + +/********************** + * GLOBAL VARIABLES + **********************/ + +const lv_color_filter_dsc_t lv_color_filter_shade = {.filter_cb = lv_color_filter_shade_cb}; /********************** * STATIC VARIABLES @@ -33,98 +41,80 @@ * GLOBAL FUNCTIONS **********************/ -void LV_ATTRIBUTE_FAST_MEM lv_color_fill(lv_color_t * buf, lv_color_t color, uint32_t px_num) +uint8_t lv_color_format_get_bpp(lv_color_format_t cf) { -#if LV_COLOR_DEPTH == 16 - uintptr_t buf_int = (uintptr_t)buf; - if(buf_int & 0x3) { - *buf = color; - buf++; - px_num--; + switch(cf) { + case LV_COLOR_FORMAT_I1: + case LV_COLOR_FORMAT_A1: + return 1; + case LV_COLOR_FORMAT_I2: + case LV_COLOR_FORMAT_A2: + return 2; + case LV_COLOR_FORMAT_I4: + case LV_COLOR_FORMAT_A4: + return 4; + case LV_COLOR_FORMAT_L8: + case LV_COLOR_FORMAT_A8: + case LV_COLOR_FORMAT_I8: + return 8; + case LV_COLOR_FORMAT_RGB565: + return 16; + + case LV_COLOR_FORMAT_RGB565A8: + case LV_COLOR_FORMAT_RGB888: + return 24; + case LV_COLOR_FORMAT_ARGB8888: + case LV_COLOR_FORMAT_XRGB8888: + return 32; + + case LV_COLOR_FORMAT_UNKNOWN: + default: + return 0; } +} - uint32_t c32 = (uint32_t)color.full + ((uint32_t)color.full << 16); - uint32_t * buf32 = (uint32_t *)buf; - - while(px_num > 16) { - *buf32 = c32; - buf32++; - *buf32 = c32; - buf32++; - *buf32 = c32; - buf32++; - *buf32 = c32; - buf32++; - - *buf32 = c32; - buf32++; - *buf32 = c32; - buf32++; - *buf32 = c32; - buf32++; - *buf32 = c32; - buf32++; - - px_num -= 16; +bool lv_color_format_has_alpha(lv_color_format_t cf) +{ + switch(cf) { + case LV_COLOR_FORMAT_A1: + case LV_COLOR_FORMAT_A2: + case LV_COLOR_FORMAT_A4: + case LV_COLOR_FORMAT_A8: + case LV_COLOR_FORMAT_I1: + case LV_COLOR_FORMAT_I2: + case LV_COLOR_FORMAT_I4: + case LV_COLOR_FORMAT_I8: + case LV_COLOR_FORMAT_RGB565A8: + case LV_COLOR_FORMAT_ARGB8888: + return true; + default: + return false; } +} - buf = (lv_color_t *)buf32; +lv_color32_t lv_color_to_32(lv_color_t color, lv_opa_t opa) +{ + lv_color32_t c32; + c32.red = color.red; + c32.green = color.green; + c32.blue = color.blue; + c32.alpha = opa; + return c32; +} - while(px_num) { - *buf = color; - buf++; - px_num--; - } -#else - while(px_num > 16) { - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; +uint16_t lv_color_to_u16(lv_color_t color) +{ + return ((color.red & 0xF8) << 8) + ((color.green & 0xFC) << 3) + ((color.blue & 0xF8) >> 3); +} - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; - - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; - - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; - *buf = color; - buf++; - - px_num -= 16; - } - while(px_num) { - *buf = color; - buf++; - px_num--; - } -#endif +uint32_t lv_color_to_u32(lv_color_t color) +{ + return (uint32_t)((uint32_t)0xff << 24) + (color.red << 16) + (color.green << 8) + (color.blue); } lv_color_t lv_color_lighten(lv_color_t c, lv_opa_t lvl) { + return lv_color_mix(lv_color_white(), c, lvl); } @@ -133,21 +123,6 @@ lv_color_t lv_color_darken(lv_color_t c, lv_opa_t lvl) return lv_color_mix(lv_color_black(), c, lvl); } -lv_color_t lv_color_change_lightness(lv_color_t c, lv_opa_t lvl) -{ - /*It'd be better to convert the color to HSL, change L and convert back to RGB.*/ - if(lvl == LV_OPA_50) return c; - else if(lvl < LV_OPA_50) return lv_color_darken(c, (LV_OPA_50 - lvl) * 2); - else return lv_color_lighten(c, (lvl - LV_OPA_50) * 2); -} - -/** - * Convert a HSV color to RGB - * @param h hue [0..359] - * @param s saturation [0..100] - * @param v value [0..100] - * @return the given RGB color in RGB (with LV_COLOR_DEPTH depth) - */ lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v) { h = (uint32_t)((uint32_t)h * 255) / 360; @@ -206,13 +181,6 @@ lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v) return result; } -/** - * Convert a 32-bit RGB color to HSV - * @param r8 8-bit red - * @param g8 8-bit green - * @param b8 8-bit blue - * @return the given RGB color in HSV - */ lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8) { uint16_t r = ((uint32_t)r8 << 10) / 255; @@ -264,106 +232,31 @@ lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8) * @param color color * @return the given color in HSV */ -lv_color_hsv_t lv_color_to_hsv(lv_color_t color) +lv_color_hsv_t lv_color_to_hsv(lv_color_t c) { - lv_color32_t color32; - color32.full = lv_color_to32(color); - return lv_color_rgb_to_hsv(color32.ch.red, color32.ch.green, color32.ch.blue); + return lv_color_rgb_to_hsv(c.red, c.green, c.blue); } -lv_color_t lv_palette_main(lv_palette_t p) +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Helper function to easily create color filters + * @param dsc pointer to a color filter descriptor + * @param c the color to modify + * @param opa the intensity of the modification + * - LV_OPA_50: do nothing + * - < LV_OPA_50: darken + * - LV_OPA_0: fully black + * - > LV_OPA_50: lighten + * - LV_OPA_100: fully white + * @return the modified color + */ +static lv_color_t lv_color_filter_shade_cb(const lv_color_filter_dsc_t * dsc, lv_color_t c, lv_opa_t opa) { - static const lv_color_t colors[] = { - LV_COLOR_MAKE(0xF4, 0x43, 0x36), LV_COLOR_MAKE(0xE9, 0x1E, 0x63), LV_COLOR_MAKE(0x9C, 0x27, 0xB0), LV_COLOR_MAKE(0x67, 0x3A, 0xB7), - LV_COLOR_MAKE(0x3F, 0x51, 0xB5), LV_COLOR_MAKE(0x21, 0x96, 0xF3), LV_COLOR_MAKE(0x03, 0xA9, 0xF4), LV_COLOR_MAKE(0x00, 0xBC, 0xD4), - LV_COLOR_MAKE(0x00, 0x96, 0x88), LV_COLOR_MAKE(0x4C, 0xAF, 0x50), LV_COLOR_MAKE(0x8B, 0xC3, 0x4A), LV_COLOR_MAKE(0xCD, 0xDC, 0x39), - LV_COLOR_MAKE(0xFF, 0xEB, 0x3B), LV_COLOR_MAKE(0xFF, 0xC1, 0x07), LV_COLOR_MAKE(0xFF, 0x98, 0x00), LV_COLOR_MAKE(0xFF, 0x57, 0x22), - LV_COLOR_MAKE(0x79, 0x55, 0x48), LV_COLOR_MAKE(0x60, 0x7D, 0x8B), LV_COLOR_MAKE(0x9E, 0x9E, 0x9E) - }; - - if(p >= _LV_PALETTE_LAST) { - LV_LOG_WARN("Invalid palette: %d", p); - return lv_color_black(); - } - - return colors[p]; - -} - -lv_color_t lv_palette_lighten(lv_palette_t p, uint8_t lvl) -{ - static const lv_color_t colors[][5] = { - {LV_COLOR_MAKE(0xEF, 0x53, 0x50), LV_COLOR_MAKE(0xE5, 0x73, 0x73), LV_COLOR_MAKE(0xEF, 0x9A, 0x9A), LV_COLOR_MAKE(0xFF, 0xCD, 0xD2), LV_COLOR_MAKE(0xFF, 0xEB, 0xEE)}, - {LV_COLOR_MAKE(0xEC, 0x40, 0x7A), LV_COLOR_MAKE(0xF0, 0x62, 0x92), LV_COLOR_MAKE(0xF4, 0x8F, 0xB1), LV_COLOR_MAKE(0xF8, 0xBB, 0xD0), LV_COLOR_MAKE(0xFC, 0xE4, 0xEC)}, - {LV_COLOR_MAKE(0xAB, 0x47, 0xBC), LV_COLOR_MAKE(0xBA, 0x68, 0xC8), LV_COLOR_MAKE(0xCE, 0x93, 0xD8), LV_COLOR_MAKE(0xE1, 0xBE, 0xE7), LV_COLOR_MAKE(0xF3, 0xE5, 0xF5)}, - {LV_COLOR_MAKE(0x7E, 0x57, 0xC2), LV_COLOR_MAKE(0x95, 0x75, 0xCD), LV_COLOR_MAKE(0xB3, 0x9D, 0xDB), LV_COLOR_MAKE(0xD1, 0xC4, 0xE9), LV_COLOR_MAKE(0xED, 0xE7, 0xF6)}, - {LV_COLOR_MAKE(0x5C, 0x6B, 0xC0), LV_COLOR_MAKE(0x79, 0x86, 0xCB), LV_COLOR_MAKE(0x9F, 0xA8, 0xDA), LV_COLOR_MAKE(0xC5, 0xCA, 0xE9), LV_COLOR_MAKE(0xE8, 0xEA, 0xF6)}, - {LV_COLOR_MAKE(0x42, 0xA5, 0xF5), LV_COLOR_MAKE(0x64, 0xB5, 0xF6), LV_COLOR_MAKE(0x90, 0xCA, 0xF9), LV_COLOR_MAKE(0xBB, 0xDE, 0xFB), LV_COLOR_MAKE(0xE3, 0xF2, 0xFD)}, - {LV_COLOR_MAKE(0x29, 0xB6, 0xF6), LV_COLOR_MAKE(0x4F, 0xC3, 0xF7), LV_COLOR_MAKE(0x81, 0xD4, 0xFA), LV_COLOR_MAKE(0xB3, 0xE5, 0xFC), LV_COLOR_MAKE(0xE1, 0xF5, 0xFE)}, - {LV_COLOR_MAKE(0x26, 0xC6, 0xDA), LV_COLOR_MAKE(0x4D, 0xD0, 0xE1), LV_COLOR_MAKE(0x80, 0xDE, 0xEA), LV_COLOR_MAKE(0xB2, 0xEB, 0xF2), LV_COLOR_MAKE(0xE0, 0xF7, 0xFA)}, - {LV_COLOR_MAKE(0x26, 0xA6, 0x9A), LV_COLOR_MAKE(0x4D, 0xB6, 0xAC), LV_COLOR_MAKE(0x80, 0xCB, 0xC4), LV_COLOR_MAKE(0xB2, 0xDF, 0xDB), LV_COLOR_MAKE(0xE0, 0xF2, 0xF1)}, - {LV_COLOR_MAKE(0x66, 0xBB, 0x6A), LV_COLOR_MAKE(0x81, 0xC7, 0x84), LV_COLOR_MAKE(0xA5, 0xD6, 0xA7), LV_COLOR_MAKE(0xC8, 0xE6, 0xC9), LV_COLOR_MAKE(0xE8, 0xF5, 0xE9)}, - {LV_COLOR_MAKE(0x9C, 0xCC, 0x65), LV_COLOR_MAKE(0xAE, 0xD5, 0x81), LV_COLOR_MAKE(0xC5, 0xE1, 0xA5), LV_COLOR_MAKE(0xDC, 0xED, 0xC8), LV_COLOR_MAKE(0xF1, 0xF8, 0xE9)}, - {LV_COLOR_MAKE(0xD4, 0xE1, 0x57), LV_COLOR_MAKE(0xDC, 0xE7, 0x75), LV_COLOR_MAKE(0xE6, 0xEE, 0x9C), LV_COLOR_MAKE(0xF0, 0xF4, 0xC3), LV_COLOR_MAKE(0xF9, 0xFB, 0xE7)}, - {LV_COLOR_MAKE(0xFF, 0xEE, 0x58), LV_COLOR_MAKE(0xFF, 0xF1, 0x76), LV_COLOR_MAKE(0xFF, 0xF5, 0x9D), LV_COLOR_MAKE(0xFF, 0xF9, 0xC4), LV_COLOR_MAKE(0xFF, 0xFD, 0xE7)}, - {LV_COLOR_MAKE(0xFF, 0xCA, 0x28), LV_COLOR_MAKE(0xFF, 0xD5, 0x4F), LV_COLOR_MAKE(0xFF, 0xE0, 0x82), LV_COLOR_MAKE(0xFF, 0xEC, 0xB3), LV_COLOR_MAKE(0xFF, 0xF8, 0xE1)}, - {LV_COLOR_MAKE(0xFF, 0xA7, 0x26), LV_COLOR_MAKE(0xFF, 0xB7, 0x4D), LV_COLOR_MAKE(0xFF, 0xCC, 0x80), LV_COLOR_MAKE(0xFF, 0xE0, 0xB2), LV_COLOR_MAKE(0xFF, 0xF3, 0xE0)}, - {LV_COLOR_MAKE(0xFF, 0x70, 0x43), LV_COLOR_MAKE(0xFF, 0x8A, 0x65), LV_COLOR_MAKE(0xFF, 0xAB, 0x91), LV_COLOR_MAKE(0xFF, 0xCC, 0xBC), LV_COLOR_MAKE(0xFB, 0xE9, 0xE7)}, - {LV_COLOR_MAKE(0x8D, 0x6E, 0x63), LV_COLOR_MAKE(0xA1, 0x88, 0x7F), LV_COLOR_MAKE(0xBC, 0xAA, 0xA4), LV_COLOR_MAKE(0xD7, 0xCC, 0xC8), LV_COLOR_MAKE(0xEF, 0xEB, 0xE9)}, - {LV_COLOR_MAKE(0x78, 0x90, 0x9C), LV_COLOR_MAKE(0x90, 0xA4, 0xAE), LV_COLOR_MAKE(0xB0, 0xBE, 0xC5), LV_COLOR_MAKE(0xCF, 0xD8, 0xDC), LV_COLOR_MAKE(0xEC, 0xEF, 0xF1)}, - {LV_COLOR_MAKE(0xBD, 0xBD, 0xBD), LV_COLOR_MAKE(0xE0, 0xE0, 0xE0), LV_COLOR_MAKE(0xEE, 0xEE, 0xEE), LV_COLOR_MAKE(0xF5, 0xF5, 0xF5), LV_COLOR_MAKE(0xFA, 0xFA, 0xFA)}, - }; - - if(p >= _LV_PALETTE_LAST) { - LV_LOG_WARN("Invalid palette: %d", p); - return lv_color_black(); - } - - if(lvl == 0 || lvl > 5) { - LV_LOG_WARN("Invalid level: %d. Must be 1..5", lvl); - return lv_color_black(); - } - - lvl--; - - return colors[p][lvl]; -} - -lv_color_t lv_palette_darken(lv_palette_t p, uint8_t lvl) -{ - static const lv_color_t colors[][4] = { - {LV_COLOR_MAKE(0xE5, 0x39, 0x35), LV_COLOR_MAKE(0xD3, 0x2F, 0x2F), LV_COLOR_MAKE(0xC6, 0x28, 0x28), LV_COLOR_MAKE(0xB7, 0x1C, 0x1C)}, - {LV_COLOR_MAKE(0xD8, 0x1B, 0x60), LV_COLOR_MAKE(0xC2, 0x18, 0x5B), LV_COLOR_MAKE(0xAD, 0x14, 0x57), LV_COLOR_MAKE(0x88, 0x0E, 0x4F)}, - {LV_COLOR_MAKE(0x8E, 0x24, 0xAA), LV_COLOR_MAKE(0x7B, 0x1F, 0xA2), LV_COLOR_MAKE(0x6A, 0x1B, 0x9A), LV_COLOR_MAKE(0x4A, 0x14, 0x8C)}, - {LV_COLOR_MAKE(0x5E, 0x35, 0xB1), LV_COLOR_MAKE(0x51, 0x2D, 0xA8), LV_COLOR_MAKE(0x45, 0x27, 0xA0), LV_COLOR_MAKE(0x31, 0x1B, 0x92)}, - {LV_COLOR_MAKE(0x39, 0x49, 0xAB), LV_COLOR_MAKE(0x30, 0x3F, 0x9F), LV_COLOR_MAKE(0x28, 0x35, 0x93), LV_COLOR_MAKE(0x1A, 0x23, 0x7E)}, - {LV_COLOR_MAKE(0x1E, 0x88, 0xE5), LV_COLOR_MAKE(0x19, 0x76, 0xD2), LV_COLOR_MAKE(0x15, 0x65, 0xC0), LV_COLOR_MAKE(0x0D, 0x47, 0xA1)}, - {LV_COLOR_MAKE(0x03, 0x9B, 0xE5), LV_COLOR_MAKE(0x02, 0x88, 0xD1), LV_COLOR_MAKE(0x02, 0x77, 0xBD), LV_COLOR_MAKE(0x01, 0x57, 0x9B)}, - {LV_COLOR_MAKE(0x00, 0xAC, 0xC1), LV_COLOR_MAKE(0x00, 0x97, 0xA7), LV_COLOR_MAKE(0x00, 0x83, 0x8F), LV_COLOR_MAKE(0x00, 0x60, 0x64)}, - {LV_COLOR_MAKE(0x00, 0x89, 0x7B), LV_COLOR_MAKE(0x00, 0x79, 0x6B), LV_COLOR_MAKE(0x00, 0x69, 0x5C), LV_COLOR_MAKE(0x00, 0x4D, 0x40)}, - {LV_COLOR_MAKE(0x43, 0xA0, 0x47), LV_COLOR_MAKE(0x38, 0x8E, 0x3C), LV_COLOR_MAKE(0x2E, 0x7D, 0x32), LV_COLOR_MAKE(0x1B, 0x5E, 0x20)}, - {LV_COLOR_MAKE(0x7C, 0xB3, 0x42), LV_COLOR_MAKE(0x68, 0x9F, 0x38), LV_COLOR_MAKE(0x55, 0x8B, 0x2F), LV_COLOR_MAKE(0x33, 0x69, 0x1E)}, - {LV_COLOR_MAKE(0xC0, 0xCA, 0x33), LV_COLOR_MAKE(0xAF, 0xB4, 0x2B), LV_COLOR_MAKE(0x9E, 0x9D, 0x24), LV_COLOR_MAKE(0x82, 0x77, 0x17)}, - {LV_COLOR_MAKE(0xFD, 0xD8, 0x35), LV_COLOR_MAKE(0xFB, 0xC0, 0x2D), LV_COLOR_MAKE(0xF9, 0xA8, 0x25), LV_COLOR_MAKE(0xF5, 0x7F, 0x17)}, - {LV_COLOR_MAKE(0xFF, 0xB3, 0x00), LV_COLOR_MAKE(0xFF, 0xA0, 0x00), LV_COLOR_MAKE(0xFF, 0x8F, 0x00), LV_COLOR_MAKE(0xFF, 0x6F, 0x00)}, - {LV_COLOR_MAKE(0xFB, 0x8C, 0x00), LV_COLOR_MAKE(0xF5, 0x7C, 0x00), LV_COLOR_MAKE(0xEF, 0x6C, 0x00), LV_COLOR_MAKE(0xE6, 0x51, 0x00)}, - {LV_COLOR_MAKE(0xF4, 0x51, 0x1E), LV_COLOR_MAKE(0xE6, 0x4A, 0x19), LV_COLOR_MAKE(0xD8, 0x43, 0x15), LV_COLOR_MAKE(0xBF, 0x36, 0x0C)}, - {LV_COLOR_MAKE(0x6D, 0x4C, 0x41), LV_COLOR_MAKE(0x5D, 0x40, 0x37), LV_COLOR_MAKE(0x4E, 0x34, 0x2E), LV_COLOR_MAKE(0x3E, 0x27, 0x23)}, - {LV_COLOR_MAKE(0x54, 0x6E, 0x7A), LV_COLOR_MAKE(0x45, 0x5A, 0x64), LV_COLOR_MAKE(0x37, 0x47, 0x4F), LV_COLOR_MAKE(0x26, 0x32, 0x38)}, - {LV_COLOR_MAKE(0x75, 0x75, 0x75), LV_COLOR_MAKE(0x61, 0x61, 0x61), LV_COLOR_MAKE(0x42, 0x42, 0x42), LV_COLOR_MAKE(0x21, 0x21, 0x21)}, - }; - - if(p >= _LV_PALETTE_LAST) { - LV_LOG_WARN("Invalid palette: %d", p); - return lv_color_black(); - } - - if(lvl == 0 || lvl > 4) { - LV_LOG_WARN("Invalid level: %d. Must be 1..4", lvl); - return lv_color_black(); - } - - lvl--; - - return colors[p][lvl]; + LV_UNUSED(dsc); + if(opa == LV_OPA_50) return c; + if(opa < LV_OPA_50) return lv_color_lighten(c, (LV_OPA_50 - opa) * 2); + else return lv_color_darken(c, (opa - LV_OPA_50 * LV_OPA_50) * 2); } diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_color.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_color.h index 61b5013ac..5170e4696 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_color.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_color.h @@ -17,28 +17,29 @@ extern "C" { #include "lv_assert.h" #include "lv_math.h" #include "lv_types.h" - -/*Error checking*/ -#if LV_COLOR_DEPTH == 24 -#error "LV_COLOR_DEPTH 24 is deprecated. Use LV_COLOR_DEPTH 32 instead (lv_conf.h)" -#endif - -#if LV_COLOR_DEPTH != 16 && LV_COLOR_16_SWAP != 0 -#error "LV_COLOR_16_SWAP requires LV_COLOR_DEPTH == 16. Set it in lv_conf.h" -#endif - #include +#include /********************* * DEFINES *********************/ LV_EXPORT_CONST_INT(LV_COLOR_DEPTH); -LV_EXPORT_CONST_INT(LV_COLOR_16_SWAP); + +#if LV_COLOR_DEPTH == 8 +#define _LV_COLOR_NATIVE_WITH_ALPHA_SIZE 2 +#elif LV_COLOR_DEPTH == 16 +#define _LV_COLOR_NATIVE_WITH_ALPHA_SIZE 3 +#elif LV_COLOR_DEPTH == 24 +#define _LV_COLOR_NATIVE_WITH_ALPHA_SIZE 4 +#elif LV_COLOR_DEPTH == 32 +#define _LV_COLOR_NATIVE_WITH_ALPHA_SIZE 4 +#endif /** * Opacity percentages. */ -enum { + +enum _lv_opa_t { LV_OPA_TRANSP = 0, LV_OPA_0 = 0, LV_OPA_10 = 25, @@ -54,605 +55,330 @@ enum { LV_OPA_COVER = 255, }; +#ifdef DOXYGEN +typedef _lv_opa_t lv_opa_t; +#else +typedef uint8_t lv_opa_t; +#endif /*DOXYGEN*/ + #define LV_OPA_MIN 2 /*Opacities below this will be transparent*/ #define LV_OPA_MAX 253 /*Opacities above this will fully cover*/ -#if LV_COLOR_DEPTH == 1 -#define LV_COLOR_SIZE 8 -#elif LV_COLOR_DEPTH == 8 -#define LV_COLOR_SIZE 8 -#elif LV_COLOR_DEPTH == 16 -#define LV_COLOR_SIZE 16 -#elif LV_COLOR_DEPTH == 32 -#define LV_COLOR_SIZE 32 -#else -#error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!" -#endif - -#if defined(__cplusplus) && !defined(_LV_COLOR_HAS_MODERN_CPP) -/** -* MSVC compiler's definition of the __cplusplus indicating 199711L regardless to C++ standard version -* see https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-cplusplus -* so we use _MSC_VER macro instead of __cplusplus -*/ -#ifdef _MSC_VER -#if _MSC_VER >= 1900 /*Visual Studio 2015*/ -#define _LV_COLOR_HAS_MODERN_CPP 1 -#endif -#else -#if __cplusplus >= 201103L -#define _LV_COLOR_HAS_MODERN_CPP 1 -#endif -#endif -#endif /*__cplusplus*/ - -#ifndef _LV_COLOR_HAS_MODERN_CPP -#define _LV_COLOR_HAS_MODERN_CPP 0 -#endif - -#if _LV_COLOR_HAS_MODERN_CPP -/*Fix msvc compiler error C4576 inside C++ code*/ -#define _LV_COLOR_MAKE_TYPE_HELPER lv_color_t -#else -#define _LV_COLOR_MAKE_TYPE_HELPER (lv_color_t) -#endif - -/*--------------------------------------- - * Macros for all existing color depths - * to set/get values of the color channels - *------------------------------------------*/ -# define LV_COLOR_SET_R1(c, v) (c).ch.red = (uint8_t)((v) & 0x1) -# define LV_COLOR_SET_G1(c, v) (c).ch.green = (uint8_t)((v) & 0x1) -# define LV_COLOR_SET_B1(c, v) (c).ch.blue = (uint8_t)((v) & 0x1) -# define LV_COLOR_SET_A1(c, v) do {} while(0) - -# define LV_COLOR_GET_R1(c) (c).ch.red -# define LV_COLOR_GET_G1(c) (c).ch.green -# define LV_COLOR_GET_B1(c) (c).ch.blue -# define LV_COLOR_GET_A1(c) 0xFF - -# define _LV_COLOR_ZERO_INITIALIZER1 {0x00} -# define LV_COLOR_MAKE1(r8, g8, b8) {(uint8_t)((b8 >> 7) | (g8 >> 7) | (r8 >> 7))} - -# define LV_COLOR_SET_R8(c, v) (c).ch.red = (uint8_t)((v) & 0x7U) -# define LV_COLOR_SET_G8(c, v) (c).ch.green = (uint8_t)((v) & 0x7U) -# define LV_COLOR_SET_B8(c, v) (c).ch.blue = (uint8_t)((v) & 0x3U) -# define LV_COLOR_SET_A8(c, v) do {} while(0) - -# define LV_COLOR_GET_R8(c) (c).ch.red -# define LV_COLOR_GET_G8(c) (c).ch.green -# define LV_COLOR_GET_B8(c) (c).ch.blue -# define LV_COLOR_GET_A8(c) 0xFF - -# define _LV_COLOR_ZERO_INITIALIZER8 {{0x00, 0x00, 0x00}} -# define LV_COLOR_MAKE8(r8, g8, b8) {{(uint8_t)((b8 >> 6) & 0x3U), (uint8_t)((g8 >> 5) & 0x7U), (uint8_t)((r8 >> 5) & 0x7U)}} - -# define LV_COLOR_SET_R16(c, v) (c).ch.red = (uint8_t)((v) & 0x1FU) -#if LV_COLOR_16_SWAP == 0 -# define LV_COLOR_SET_G16(c, v) (c).ch.green = (uint8_t)((v) & 0x3FU) -#else -# define LV_COLOR_SET_G16(c, v) {(c).ch.green_h = (uint8_t)(((v) >> 3) & 0x7); (c).ch.green_l = (uint8_t)((v) & 0x7);} -#endif -# define LV_COLOR_SET_B16(c, v) (c).ch.blue = (uint8_t)((v) & 0x1FU) -# define LV_COLOR_SET_A16(c, v) do {} while(0) - -# define LV_COLOR_GET_R16(c) (c).ch.red -#if LV_COLOR_16_SWAP == 0 -# define LV_COLOR_GET_G16(c) (c).ch.green -#else -# define LV_COLOR_GET_G16(c) (((c).ch.green_h << 3) + (c).ch.green_l) -#endif -# define LV_COLOR_GET_B16(c) (c).ch.blue -# define LV_COLOR_GET_A16(c) 0xFF - -#if LV_COLOR_16_SWAP == 0 -# define _LV_COLOR_ZERO_INITIALIZER16 {{0x00, 0x00, 0x00}} -# define LV_COLOR_MAKE16(r8, g8, b8) {{(uint8_t)((b8 >> 3) & 0x1FU), (uint8_t)((g8 >> 2) & 0x3FU), (uint8_t)((r8 >> 3) & 0x1FU)}} -#else -# define _LV_COLOR_ZERO_INITIALIZER16 {{0x00, 0x00, 0x00, 0x00}} -# define LV_COLOR_MAKE16(r8, g8, b8) {{(uint8_t)((g8 >> 5) & 0x7U), (uint8_t)((r8 >> 3) & 0x1FU), (uint8_t)((b8 >> 3) & 0x1FU), (uint8_t)((g8 >> 2) & 0x7U)}} -#endif - -# define LV_COLOR_SET_R32(c, v) (c).ch.red = (uint8_t)((v) & 0xFF) -# define LV_COLOR_SET_G32(c, v) (c).ch.green = (uint8_t)((v) & 0xFF) -# define LV_COLOR_SET_B32(c, v) (c).ch.blue = (uint8_t)((v) & 0xFF) -# define LV_COLOR_SET_A32(c, v) (c).ch.alpha = (uint8_t)((v) & 0xFF) - -# define LV_COLOR_GET_R32(c) (c).ch.red -# define LV_COLOR_GET_G32(c) (c).ch.green -# define LV_COLOR_GET_B32(c) (c).ch.blue -# define LV_COLOR_GET_A32(c) (c).ch.alpha - -# define _LV_COLOR_ZERO_INITIALIZER32 {{0x00, 0x00, 0x00, 0x00}} -# define LV_COLOR_MAKE32(r8, g8, b8) {{b8, g8, r8, 0xff}} /*Fix 0xff alpha*/ - -/*--------------------------------------- - * Macros for the current color depth - * to set/get values of the color channels - *------------------------------------------*/ -#define LV_COLOR_SET_R(c, v) LV_CONCAT(LV_COLOR_SET_R, LV_COLOR_DEPTH)(c, v) -#define LV_COLOR_SET_G(c, v) LV_CONCAT(LV_COLOR_SET_G, LV_COLOR_DEPTH)(c, v) -#define LV_COLOR_SET_B(c, v) LV_CONCAT(LV_COLOR_SET_B, LV_COLOR_DEPTH)(c, v) -#define LV_COLOR_SET_A(c, v) LV_CONCAT(LV_COLOR_SET_A, LV_COLOR_DEPTH)(c, v) - -#define LV_COLOR_GET_R(c) LV_CONCAT(LV_COLOR_GET_R, LV_COLOR_DEPTH)(c) -#define LV_COLOR_GET_G(c) LV_CONCAT(LV_COLOR_GET_G, LV_COLOR_DEPTH)(c) -#define LV_COLOR_GET_B(c) LV_CONCAT(LV_COLOR_GET_B, LV_COLOR_DEPTH)(c) -#define LV_COLOR_GET_A(c) LV_CONCAT(LV_COLOR_GET_A, LV_COLOR_DEPTH)(c) - -#define _LV_COLOR_ZERO_INITIALIZER LV_CONCAT(_LV_COLOR_ZERO_INITIALIZER, LV_COLOR_DEPTH) -#define LV_COLOR_MAKE(r8, g8, b8) LV_CONCAT(LV_COLOR_MAKE, LV_COLOR_DEPTH)(r8, g8, b8) +#define LV_COLOR_FORMAT_GET_BPP(cf) ( \ + (cf) == LV_COLOR_FORMAT_I1 ? 1 : \ + (cf) == LV_COLOR_FORMAT_A1 ? 1 : \ + (cf) == LV_COLOR_FORMAT_I2 ? 2 : \ + (cf) == LV_COLOR_FORMAT_A2 ? 2 : \ + (cf) == LV_COLOR_FORMAT_I4 ? 4 : \ + (cf) == LV_COLOR_FORMAT_A4 ? 4 : \ + (cf) == LV_COLOR_FORMAT_L8 ? 8 : \ + (cf) == LV_COLOR_FORMAT_A8 ? 8 : \ + (cf) == LV_COLOR_FORMAT_I8 ? 8 : \ + (cf) == LV_COLOR_FORMAT_RGB565 ? 16 : \ + (cf) == LV_COLOR_FORMAT_RGB565A8 ? 24 : \ + (cf) == LV_COLOR_FORMAT_RGB888 ? 24 : \ + (cf) == LV_COLOR_FORMAT_ARGB8888 ? 32 : \ + (cf) == LV_COLOR_FORMAT_XRGB8888 ? 32 : \ + 0 \ + ) /********************** * TYPEDEFS **********************/ -typedef union { - uint8_t full; /*must be declared first to set all bits of byte via initializer list*/ - union { - uint8_t blue : 1; - uint8_t green : 1; - uint8_t red : 1; - } ch; -} lv_color1_t; +typedef struct { + uint8_t blue; + uint8_t green; + uint8_t red; +} lv_color_t; -typedef union { - struct { - uint8_t blue : 2; - uint8_t green : 3; - uint8_t red : 3; - } ch; - uint8_t full; -} lv_color8_t; - -typedef union { - struct { -#if LV_COLOR_16_SWAP == 0 - uint16_t blue : 5; - uint16_t green : 6; - uint16_t red : 5; -#else - uint16_t green_h : 3; - uint16_t red : 5; - uint16_t blue : 5; - uint16_t green_l : 3; -#endif - } ch; - uint16_t full; +typedef struct { + uint16_t blue : 5; + uint16_t green : 6; + uint16_t red : 5; } lv_color16_t; -typedef union { - struct { - uint8_t blue; - uint8_t green; - uint8_t red; - uint8_t alpha; - } ch; - uint32_t full; +typedef struct { + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t alpha; } lv_color32_t; -typedef LV_CONCAT3(uint, LV_COLOR_SIZE, _t) lv_color_int_t; -typedef LV_CONCAT3(lv_color, LV_COLOR_DEPTH, _t) lv_color_t; - typedef struct { uint16_t h; uint8_t s; uint8_t v; } lv_color_hsv_t; -//! @cond Doxygen_Suppress -/*No idea where the guard is required but else throws warnings in the docs*/ -typedef uint8_t lv_opa_t; -//! @endcond +enum _lv_color_format_t { + LV_COLOR_FORMAT_UNKNOWN = 0, -struct _lv_color_filter_dsc_t; + LV_COLOR_FORMAT_RAW = 0x01, + LV_COLOR_FORMAT_RAW_ALPHA = 0x02, -typedef lv_color_t (*lv_color_filter_cb_t)(const struct _lv_color_filter_dsc_t *, lv_color_t, lv_opa_t); + /*<=1 byte (+alpha) formats*/ + LV_COLOR_FORMAT_L8 = 0x06, + LV_COLOR_FORMAT_I1 = 0x07, + LV_COLOR_FORMAT_I2 = 0x08, + LV_COLOR_FORMAT_I4 = 0x09, + LV_COLOR_FORMAT_I8 = 0x0A, + LV_COLOR_FORMAT_A8 = 0x0E, -typedef struct _lv_color_filter_dsc_t { - lv_color_filter_cb_t filter_cb; - void * user_data; -} lv_color_filter_dsc_t; + /*2 byte (+alpha) formats*/ + LV_COLOR_FORMAT_RGB565 = 0x12, + LV_COLOR_FORMAT_RGB565A8 = 0x14 /**< Color array followed by Alpha array*/, + /*3 byte (+alpha) formats*/ + LV_COLOR_FORMAT_RGB888 = 0x0F, + LV_COLOR_FORMAT_ARGB8888 = 0x10, + LV_COLOR_FORMAT_XRGB8888 = 0x11, -typedef enum { - LV_PALETTE_RED, - LV_PALETTE_PINK, - LV_PALETTE_PURPLE, - LV_PALETTE_DEEP_PURPLE, - LV_PALETTE_INDIGO, - LV_PALETTE_BLUE, - LV_PALETTE_LIGHT_BLUE, - LV_PALETTE_CYAN, - LV_PALETTE_TEAL, - LV_PALETTE_GREEN, - LV_PALETTE_LIGHT_GREEN, - LV_PALETTE_LIME, - LV_PALETTE_YELLOW, - LV_PALETTE_AMBER, - LV_PALETTE_ORANGE, - LV_PALETTE_DEEP_ORANGE, - LV_PALETTE_BROWN, - LV_PALETTE_BLUE_GREY, - LV_PALETTE_GREY, - _LV_PALETTE_LAST, - LV_PALETTE_NONE = 0xff, -} lv_palette_t; + /*Formats not supported by software renderer but kept here so GPU can use it*/ + LV_COLOR_FORMAT_A1 = 0x0B, + LV_COLOR_FORMAT_A2 = 0x0C, + LV_COLOR_FORMAT_A4 = 0x0D, + + /* reference to https://wiki.videolan.org/YUV/ */ + /*YUV planar formats*/ + LV_COLOR_FORMAT_YUV_START = 0x20, + LV_COLOR_FORMAT_I420 = LV_COLOR_FORMAT_YUV_START, /*YUV420 planar(3 plane)*/ + LV_COLOR_FORMAT_I422 = 0x21, /*YUV422 planar(3 plane)*/ + LV_COLOR_FORMAT_I444 = 0x22, /*YUV444 planar(3 plane)*/ + LV_COLOR_FORMAT_I400 = 0x23, /*YUV400 no chroma channel*/ + LV_COLOR_FORMAT_NV21 = 0x24, /*YUV420 planar(2 plane), UV plane in 'V, U, V, U'*/ + LV_COLOR_FORMAT_NV12 = 0x25, /*YUV420 planar(2 plane), UV plane in 'U, V, U, V'*/ + + /*YUV packed formats*/ + LV_COLOR_FORMAT_YUY2 = 0x26, /*YUV422 packed like 'Y U Y V'*/ + LV_COLOR_FORMAT_UYVY = 0x27, /*YUV422 packed like 'U Y V Y'*/ + + LV_COLOR_FORMAT_YUV_END = LV_COLOR_FORMAT_UYVY, + + /*Color formats in which LVGL can render*/ +#if LV_COLOR_DEPTH == 8 + LV_COLOR_FORMAT_NATIVE = LV_COLOR_FORMAT_L8, +#elif LV_COLOR_DEPTH == 16 + LV_COLOR_FORMAT_NATIVE = LV_COLOR_FORMAT_RGB565, + LV_COLOR_FORMAT_NATIVE_WITH_ALPHA = LV_COLOR_FORMAT_RGB565A8, +#elif LV_COLOR_DEPTH == 24 + LV_COLOR_FORMAT_NATIVE = LV_COLOR_FORMAT_RGB888, + LV_COLOR_FORMAT_NATIVE_WITH_ALPHA = LV_COLOR_FORMAT_ARGB8888, +#elif LV_COLOR_DEPTH == 32 + LV_COLOR_FORMAT_NATIVE = LV_COLOR_FORMAT_XRGB8888, + LV_COLOR_FORMAT_NATIVE_WITH_ALPHA = LV_COLOR_FORMAT_ARGB8888, +#endif +}; + +#ifdef DOXYGEN +typedef _lv_color_format_t lv_color_format_t; +#else +typedef uint8_t lv_color_format_t; +#endif /*DOXYGEN*/ + +#define LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf) ((cf) >= LV_COLOR_FORMAT_A1 && (cf) <= LV_COLOR_FORMAT_A8) +#define LV_COLOR_FORMAT_IS_INDEXED(cf) ((cf) >= LV_COLOR_FORMAT_I1 && (cf) <= LV_COLOR_FORMAT_I8) +#define LV_COLOR_FORMAT_IS_YUV(cf) ((cf) >= LV_COLOR_FORMAT_YUV_START && (cf) <= LV_COLOR_FORMAT_YUV_END) +#define LV_COLOR_INDEXED_PALETTE_SIZE(cf) ((cf) == LV_COLOR_FORMAT_I1 ? 2 :\ + (cf) == LV_COLOR_FORMAT_I2 ? 4 :\ + (cf) == LV_COLOR_FORMAT_I4 ? 16 :\ + (cf) == LV_COLOR_FORMAT_I8 ? 256 : 0) + +/********************** + * MACROS + **********************/ + +#define LV_COLOR_MAKE(r8, g8, b8) {b8, g8, r8} + +#define LV_OPA_MIX2(a1, a2) (((int32_t)(a1) * (a2)) >> 8) +#define LV_OPA_MIX3(a1, a2, a3) (((int32_t)(a1) * (a2) * (a3)) >> 16) /********************** * GLOBAL PROTOTYPES **********************/ -/*In color conversations: - * - When converting to bigger color type the LSB weight of 1 LSB is calculated - * E.g. 16 bit Red has 5 bits - * 8 bit Red has 3 bits - * ---------------------- - * 8 bit red LSB = (2^5 - 1) / (2^3 - 1) = 31 / 7 = 4 - * - * - When calculating to smaller color type simply shift out the LSBs - * E.g. 8 bit Red has 3 bits - * 16 bit Red has 5 bits - * ---------------------- - * Shift right with 5 - 3 = 2 +/** + * Get the pixel size of a color format in bits, bpp + * @param src_cf a color format (`LV_COLOR_FORMAT_...`) + * @return the pixel size in bits */ -static inline uint8_t lv_color_to1(lv_color_t color) -{ -#if LV_COLOR_DEPTH == 1 - return color.full; -#elif LV_COLOR_DEPTH == 8 - if((LV_COLOR_GET_R(color) & 0x4) || (LV_COLOR_GET_G(color) & 0x4) || (LV_COLOR_GET_B(color) & 0x2)) { - return 1; - } - else { - return 0; - } -#elif LV_COLOR_DEPTH == 16 - if((LV_COLOR_GET_R(color) & 0x10) || (LV_COLOR_GET_G(color) & 0x20) || (LV_COLOR_GET_B(color) & 0x10)) { - return 1; - } - else { - return 0; - } -#elif LV_COLOR_DEPTH == 32 - if((LV_COLOR_GET_R(color) & 0x80) || (LV_COLOR_GET_G(color) & 0x80) || (LV_COLOR_GET_B(color) & 0x80)) { - return 1; - } - else { - return 0; - } -#endif -} - -static inline uint8_t lv_color_to8(lv_color_t color) -{ -#if LV_COLOR_DEPTH == 1 - if(color.full == 0) - return 0; - else - return 0xFF; -#elif LV_COLOR_DEPTH == 8 - return color.full; -#elif LV_COLOR_DEPTH == 16 - lv_color8_t ret; - LV_COLOR_SET_R8(ret, LV_COLOR_GET_R(color) >> 2); /*5 - 3 = 2*/ - LV_COLOR_SET_G8(ret, LV_COLOR_GET_G(color) >> 3); /*6 - 3 = 3*/ - LV_COLOR_SET_B8(ret, LV_COLOR_GET_B(color) >> 3); /*5 - 2 = 3*/ - return ret.full; -#elif LV_COLOR_DEPTH == 32 - lv_color8_t ret; - LV_COLOR_SET_R8(ret, LV_COLOR_GET_R(color) >> 5); /*8 - 3 = 5*/ - LV_COLOR_SET_G8(ret, LV_COLOR_GET_G(color) >> 5); /*8 - 3 = 5*/ - LV_COLOR_SET_B8(ret, LV_COLOR_GET_B(color) >> 6); /*8 - 2 = 6*/ - return ret.full; -#endif -} - -static inline uint16_t lv_color_to16(lv_color_t color) -{ -#if LV_COLOR_DEPTH == 1 - if(color.full == 0) - return 0; - else - return 0xFFFF; -#elif LV_COLOR_DEPTH == 8 - lv_color16_t ret; - LV_COLOR_SET_R16(ret, LV_COLOR_GET_R(color) * 4); /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/ - LV_COLOR_SET_G16(ret, LV_COLOR_GET_G(color) * 9); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/ - LV_COLOR_SET_B16(ret, LV_COLOR_GET_B(color) * 10); /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/ - return ret.full; -#elif LV_COLOR_DEPTH == 16 - return color.full; -#elif LV_COLOR_DEPTH == 32 - lv_color16_t ret; - LV_COLOR_SET_R16(ret, LV_COLOR_GET_R(color) >> 3); /*8 - 5 = 3*/ - LV_COLOR_SET_G16(ret, LV_COLOR_GET_G(color) >> 2); /*8 - 6 = 2*/ - LV_COLOR_SET_B16(ret, LV_COLOR_GET_B(color) >> 3); /*8 - 5 = 3*/ - return ret.full; -#endif -} - -static inline uint32_t lv_color_to32(lv_color_t color) -{ -#if LV_COLOR_DEPTH == 1 - if(color.full == 0) - return 0xFF000000; - else - return 0xFFFFFFFF; -#elif LV_COLOR_DEPTH == 8 - lv_color32_t ret; - LV_COLOR_SET_R32(ret, LV_COLOR_GET_R(color) * 36); /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/ - LV_COLOR_SET_G32(ret, LV_COLOR_GET_G(color) * 36); /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/ - LV_COLOR_SET_B32(ret, LV_COLOR_GET_B(color) * 85); /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/ - LV_COLOR_SET_A32(ret, 0xFF); - return ret.full; -#elif LV_COLOR_DEPTH == 16 - /** - * The floating point math for conversion is: - * valueto = valuefrom * ( (2^bitsto - 1) / (float)(2^bitsfrom - 1) ) - * The faster integer math for conversion is: - * valueto = ( valuefrom * multiplier + adder ) >> divisor - * multiplier = FLOOR( ( (2^bitsto - 1) << divisor ) / (float)(2^bitsfrom - 1) ) - * - * Find the first divisor where ( adder >> divisor ) <= 0 - * - * 5-bit to 8-bit: ( 31 * multiplier + adder ) >> divisor = 255 - * divisor multiplier adder min (0) max (31) - * 0 8 7 7 255 - * 1 16 14 7 255 - * 2 32 28 7 255 - * 3 65 25 3 255 - * 4 131 19 1 255 - * 5 263 7 0 255 - * - * 6-bit to 8-bit: 255 = ( 63 * multiplier + adder ) >> divisor - * divisor multiplier adder min (0) max (63) - * 0 4 3 3 255 - * 1 8 6 3 255 - * 2 16 12 3 255 - * 3 32 24 3 255 - * 4 64 48 3 255 - * 5 129 33 1 255 - * 6 259 3 0 255 - */ - - lv_color32_t ret; - LV_COLOR_SET_R32(ret, (LV_COLOR_GET_R(color) * 263 + 7) >> 5); - LV_COLOR_SET_G32(ret, (LV_COLOR_GET_G(color) * 259 + 3) >> 6); - LV_COLOR_SET_B32(ret, (LV_COLOR_GET_B(color) * 263 + 7) >> 5); - LV_COLOR_SET_A32(ret, 0xFF); - return ret.full; -#elif LV_COLOR_DEPTH == 32 - return color.full; -#endif -} - -//! @cond Doxygen_Suppress +uint8_t lv_color_format_get_bpp(lv_color_format_t cf); /** - * Mix two colors with a given ratio. - * @param c1 the first color to mix (usually the foreground) - * @param c2 the second color to mix (usually the background) - * @param mix The ratio of the colors. 0: full `c2`, 255: full `c1`, 127: half `c1` and half`c2` - * @return the mixed color + * Get the pixel size of a color format in bytes + * @param src_cf a color format (`LV_COLOR_FORMAT_...`) + * @return the pixel size in bytes */ -static inline lv_color_t LV_ATTRIBUTE_FAST_MEM lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix) +static inline uint8_t lv_color_format_get_size(lv_color_format_t cf) { - lv_color_t ret; - -#if LV_COLOR_DEPTH == 16 && LV_COLOR_MIX_ROUND_OFS == 0 -#if LV_COLOR_16_SWAP == 1 - c1.full = c1.full << 8 | c1.full >> 8; - c2.full = c2.full << 8 | c2.full >> 8; -#endif - /*Source: https://stackoverflow.com/a/50012418/1999969*/ - mix = (uint32_t)((uint32_t)mix + 4) >> 3; - uint32_t bg = (uint32_t)((uint32_t)c2.full | ((uint32_t)c2.full << 16)) & - 0x7E0F81F; /*0b00000111111000001111100000011111*/ - uint32_t fg = (uint32_t)((uint32_t)c1.full | ((uint32_t)c1.full << 16)) & 0x7E0F81F; - uint32_t result = ((((fg - bg) * mix) >> 5) + bg) & 0x7E0F81F; - ret.full = (uint16_t)((result >> 16) | result); -#if LV_COLOR_16_SWAP == 1 - ret.full = ret.full << 8 | ret.full >> 8; -#endif -#elif LV_COLOR_DEPTH != 1 - /*LV_COLOR_DEPTH == 8, 16 or 32*/ - LV_COLOR_SET_R(ret, LV_UDIV255((uint16_t)LV_COLOR_GET_R(c1) * mix + LV_COLOR_GET_R(c2) * - (255 - mix) + LV_COLOR_MIX_ROUND_OFS)); - LV_COLOR_SET_G(ret, LV_UDIV255((uint16_t)LV_COLOR_GET_G(c1) * mix + LV_COLOR_GET_G(c2) * - (255 - mix) + LV_COLOR_MIX_ROUND_OFS)); - LV_COLOR_SET_B(ret, LV_UDIV255((uint16_t)LV_COLOR_GET_B(c1) * mix + LV_COLOR_GET_B(c2) * - (255 - mix) + LV_COLOR_MIX_ROUND_OFS)); - LV_COLOR_SET_A(ret, 0xFF); -#else - /*LV_COLOR_DEPTH == 1*/ - ret.full = mix > LV_OPA_50 ? c1.full : c2.full; -#endif - - return ret; -} - -static inline void LV_ATTRIBUTE_FAST_MEM lv_color_premult(lv_color_t c, uint8_t mix, uint16_t * out) -{ -#if LV_COLOR_DEPTH != 1 - out[0] = (uint16_t)LV_COLOR_GET_R(c) * mix; - out[1] = (uint16_t)LV_COLOR_GET_G(c) * mix; - out[2] = (uint16_t)LV_COLOR_GET_B(c) * mix; -#else - (void) mix; - /*Pre-multiplication can't be used with 1 bpp*/ - out[0] = LV_COLOR_GET_R(c); - out[1] = LV_COLOR_GET_G(c); - out[2] = LV_COLOR_GET_B(c); -#endif - + return (lv_color_format_get_bpp(cf) + 7) >> 3; } /** - * Mix two colors with a given ratio. It runs faster then `lv_color_mix` but requires some pre computation. - * @param premult_c1 The first color. Should be preprocessed with `lv_color_premult(c1)` - * @param c2 The second color. As it is no pre computation required on it - * @param mix The ratio of the colors. 0: full `c1`, 255: full `c2`, 127: half `c1` and half `c2`. - * Should be modified like mix = `255 - mix` - * @return the mixed color - * @note 255 won't give clearly `c1`. + * Check if a color format has alpha channel or not + * @param src_cf a color format (`LV_COLOR_FORMAT_...`) + * @return true: has alpha channel; false: doesn't have alpha channel */ -static inline lv_color_t LV_ATTRIBUTE_FAST_MEM lv_color_mix_premult(uint16_t * premult_c1, lv_color_t c2, uint8_t mix) -{ - lv_color_t ret; -#if LV_COLOR_DEPTH != 1 - /*LV_COLOR_DEPTH == 8 or 32*/ - LV_COLOR_SET_R(ret, LV_UDIV255(premult_c1[0] + LV_COLOR_GET_R(c2) * mix + LV_COLOR_MIX_ROUND_OFS)); - LV_COLOR_SET_G(ret, LV_UDIV255(premult_c1[1] + LV_COLOR_GET_G(c2) * mix + LV_COLOR_MIX_ROUND_OFS)); - LV_COLOR_SET_B(ret, LV_UDIV255(premult_c1[2] + LV_COLOR_GET_B(c2) * mix + LV_COLOR_MIX_ROUND_OFS)); - LV_COLOR_SET_A(ret, 0xFF); -#else - /*LV_COLOR_DEPTH == 1*/ - /*Restore color1*/ - lv_color_t c1; - LV_COLOR_SET_R(c1, premult_c1[0]); - LV_COLOR_SET_G(c1, premult_c1[1]); - LV_COLOR_SET_B(c1, premult_c1[2]); - ret.full = mix > LV_OPA_50 ? c2.full : c1.full; -#endif +bool lv_color_format_has_alpha(lv_color_format_t src_cf); - return ret; +/** + * Create an ARGB8888 color from RGB888 + alpha + * @param color an RGB888 color + * @param opa the alpha value + * @return the ARGB8888 color + */ +lv_color32_t lv_color_to_32(lv_color_t color, lv_opa_t opa); + +/** + * Convert an RGB888 color to an integer + * @param c an RGB888 color + * @return `c` as an integer + */ +static inline uint32_t lv_color_to_int(lv_color_t c) +{ + uint8_t * tmp = (uint8_t *) &c; + return tmp[0] + (tmp[1] << 8) + (tmp[2] << 16); } /** - * Mix two colors. Both color can have alpha value. - * @param bg_color background color - * @param bg_opa alpha of the background color - * @param fg_color foreground color - * @param fg_opa alpha of the foreground color - * @param res_color the result color - * @param res_opa the result opacity + * Check if two RGB888 color are equal + * @param c1 the first color + * @param c2 the second color + * @return true: equal */ -static inline void LV_ATTRIBUTE_FAST_MEM lv_color_mix_with_alpha(lv_color_t bg_color, lv_opa_t bg_opa, - lv_color_t fg_color, lv_opa_t fg_opa, - lv_color_t * res_color, lv_opa_t * res_opa) +static inline bool lv_color_eq(lv_color_t c1, lv_color_t c2) { - /*Pick the foreground if it's fully opaque or the Background is fully transparent*/ - if(fg_opa >= LV_OPA_MAX || bg_opa <= LV_OPA_MIN) { - res_color->full = fg_color.full; - *res_opa = fg_opa; - } - /*Transparent foreground: use the Background*/ - else if(fg_opa <= LV_OPA_MIN) { - res_color->full = bg_color.full; - *res_opa = bg_opa; - } - /*Opaque background: use simple mix*/ - else if(bg_opa >= LV_OPA_MAX) { - *res_color = lv_color_mix(fg_color, bg_color, fg_opa); - *res_opa = LV_OPA_COVER; - } - /*Both colors have alpha. Expensive calculation need to be applied*/ - else { - /*Save the parameters and the result. If they will be asked again don't compute again*/ - static lv_opa_t fg_opa_save = 0; - static lv_opa_t bg_opa_save = 0; - static lv_color_t fg_color_save = _LV_COLOR_ZERO_INITIALIZER; - static lv_color_t bg_color_save = _LV_COLOR_ZERO_INITIALIZER; - static lv_color_t res_color_saved = _LV_COLOR_ZERO_INITIALIZER; - static lv_opa_t res_opa_saved = 0; - - if(fg_opa != fg_opa_save || bg_opa != bg_opa_save || fg_color.full != fg_color_save.full || - bg_color.full != bg_color_save.full) { - fg_opa_save = fg_opa; - bg_opa_save = bg_opa; - fg_color_save.full = fg_color.full; - bg_color_save.full = bg_color.full; - /*Info: - * https://en.wikipedia.org/wiki/Alpha_compositing#Analytical_derivation_of_the_over_operator*/ - res_opa_saved = 255 - ((uint16_t)((uint16_t)(255 - fg_opa) * (255 - bg_opa)) >> 8); - LV_ASSERT(res_opa_saved != 0); - lv_opa_t ratio = (uint16_t)((uint16_t)fg_opa * 255) / res_opa_saved; - res_color_saved = lv_color_mix(fg_color, bg_color, ratio); - - } - - res_color->full = res_color_saved.full; - *res_opa = res_opa_saved; - } + return lv_color_to_int(c1) == lv_color_to_int(c2); } -//! @endcond - /** - * Get the brightness of a color - * @param color a color - * @return the brightness [0..255] + * Check if two ARGB8888 color are equal + * @param c1 the first color + * @param c2 the second color + * @return true: equal */ -static inline uint8_t lv_color_brightness(lv_color_t color) +static inline bool lv_color32_eq(lv_color32_t c1, lv_color32_t c2) { - lv_color32_t c32; - c32.full = lv_color_to32(color); - uint16_t bright = (uint16_t)(3u * LV_COLOR_GET_R32(c32) + LV_COLOR_GET_B32(c32) + 4u * LV_COLOR_GET_G32(c32)); - return (uint8_t)(bright >> 3); -} - -static inline lv_color_t lv_color_make(uint8_t r, uint8_t g, uint8_t b) -{ - return _LV_COLOR_MAKE_TYPE_HELPER LV_COLOR_MAKE(r, g, b); + return *((uint32_t *)&c1) == *((uint32_t *)&c2); } +/** + * Create a color from 0x000000..0xffffff input + * @param c the hex input + * @return the color + */ static inline lv_color_t lv_color_hex(uint32_t c) { -#if LV_COLOR_DEPTH == 16 - lv_color_t r; -#if LV_COLOR_16_SWAP == 0 - /* Convert a 4 bytes per pixel in format ARGB32 to R5G6B5 format - naive way (by calling lv_color_make with components): - r = ((c & 0xFF0000) >> 19) - g = ((c & 0xFF00) >> 10) - b = ((c & 0xFF) >> 3) - rgb565 = (r << 11) | (g << 5) | b - That's 3 mask, 5 bitshift and 2 or operations - - A bit better: - r = ((c & 0xF80000) >> 8) - g = ((c & 0xFC00) >> 5) - b = ((c & 0xFF) >> 3) - rgb565 = r | g | b - That's 3 mask, 3 bitshifts and 2 or operations */ - r.full = (uint16_t)(((c & 0xF80000) >> 8) | ((c & 0xFC00) >> 5) | ((c & 0xFF) >> 3)); -#else - /* We want: rrrr rrrr GGGg gggg bbbb bbbb => gggb bbbb rrrr rGGG */ - r.full = (uint16_t)(((c & 0xF80000) >> 16) | ((c & 0xFC00) >> 13) | ((c & 0x1C00) << 3) | ((c & 0xF8) << 5)); -#endif - return r; -#elif LV_COLOR_DEPTH == 32 - lv_color_t r; - r.full = c | 0xFF000000; - return r; -#else /*LV_COLOR_DEPTH == 8*/ - return lv_color_make((uint8_t)((c >> 16) & 0xFF), (uint8_t)((c >> 8) & 0xFF), (uint8_t)(c & 0xFF)); -#endif + lv_color_t ret; + ret.red = (c >> 16) & 0xff; + ret.green = (c >> 8) & 0xff; + ret.blue = (c >> 0) & 0xff; + return ret; } +/** + * Create an RGB888 color + * @param r the red channel (0..255) + * @param g the green channel (0..255) + * @param b the blue channel (0..255) + * @return the color + */ +static inline lv_color_t lv_color_make(uint8_t r, uint8_t g, uint8_t b) +{ + lv_color_t ret; + ret.red = r; + ret.green = g; + ret.blue = b; + return ret; +} + +/** + * Create an ARGB8888 color + * @param r the red channel (0..255) + * @param g the green channel (0..255) + * @param b the blue channel (0..255) + * @param a the alpha channel (0..255) + * @return the color + */ +static inline lv_color32_t lv_color32_make(uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + lv_color32_t ret; + ret.red = r; + ret.green = g; + ret.blue = b; + ret.alpha = a; + return ret; +} + +/** + * Create a color from 0x000..0xfff input + * @param c the hex input (e.g. 0x123 will be 0x112233) + * @return the color + */ static inline lv_color_t lv_color_hex3(uint32_t c) { return lv_color_make((uint8_t)(((c >> 4) & 0xF0) | ((c >> 8) & 0xF)), (uint8_t)((c & 0xF0) | ((c & 0xF0) >> 4)), (uint8_t)((c & 0xF) | ((c & 0xF) << 4))); } -static inline void lv_color_filter_dsc_init(lv_color_filter_dsc_t * dsc, lv_color_filter_cb_t cb) +/** + * Convert am RGB888 color to RGB565 stored in `uint16_t` + * @param color and RGB888 color + * @return `color` as RGB565 on `uin16_t` + */ +uint16_t lv_color_to_u16(lv_color_t color); + +/** + * Convert am RGB888 color to XRGB8888 stored in `uint32_t` + * @param color and RGB888 color + * @return `color` as XRGB8888 on `uin32_t` (the alpha channel is always set to 0xFF) + */ +uint32_t lv_color_to_u32(lv_color_t color); + +/** + * Mix two RGB565 colors + * @param c1 the first color (typically the foreground color) + * @param c2 the second color (typically the background color) + * @param mix 0..255, or LV_OPA_0/10/20... + * @return mix == 0: c2 + * mix == 255: c1 + * mix == 128: 0.5 x c1 + 0.5 x c2 + */ +LV_ATTRIBUTE_FAST_MEM static inline uint16_t lv_color_16_16_mix(uint16_t c1, uint16_t c2, uint8_t mix) { - dsc->filter_cb = cb; + if(mix == 255) return c1; + if(mix == 0) return c2; + + uint16_t ret; + + /* Source: https://stackoverflow.com/a/50012418/1999969*/ + mix = (uint32_t)((uint32_t)mix + 4) >> 3; + + /*0x7E0F81F = 0b00000111111000001111100000011111*/ + uint32_t bg = (uint32_t)(c2 | ((uint32_t)c2 << 16)) & 0x7E0F81F; + uint32_t fg = (uint32_t)(c1 | ((uint32_t)c1 << 16)) & 0x7E0F81F; + uint32_t result = ((((fg - bg) * mix) >> 5) + bg) & 0x7E0F81F; + ret = (uint16_t)(result >> 16) | result; + + return ret; } -//! @cond Doxygen_Suppress -//! -void /* LV_ATTRIBUTE_FAST_MEM */ lv_color_fill(lv_color_t * buf, lv_color_t color, uint32_t px_num); - -//! @endcond +/** + * Mix white to a color + * @param c the base color + * @param lvl the intensity of white (0: no change, 255: fully white) + * @return the mixed color + */ lv_color_t lv_color_lighten(lv_color_t c, lv_opa_t lvl); +/** + * Mix black to a color + * @param c the base color + * @param lvl the intensity of black (0: no change, 255: fully black) + * @return the mixed color + */ lv_color_t lv_color_darken(lv_color_t c, lv_opa_t lvl); -lv_color_t lv_color_change_lightness(lv_color_t c, lv_opa_t lvl); - /** * Convert a HSV color to RGB * @param h hue [0..359] @@ -678,36 +404,49 @@ lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8); */ lv_color_hsv_t lv_color_to_hsv(lv_color_t color); -/** - * Just a wrapper around LV_COLOR_CHROMA_KEY because it might be more convenient to use a function in some cases - * @return LV_COLOR_CHROMA_KEY - */ -static inline lv_color_t lv_color_chroma_key(void) -{ - return LV_COLOR_CHROMA_KEY; -} - -/********************** - * PREDEFINED COLORS - **********************/ /*Source: https://vuetifyjs.com/en/styles/colors/#material-colors*/ -lv_color_t lv_palette_main(lv_palette_t p); +/** + * A helper for white color + * @return a white color + */ static inline lv_color_t lv_color_white(void) { return lv_color_make(0xff, 0xff, 0xff); } + +/** + * A helper for black color + * @return a black color + */ static inline lv_color_t lv_color_black(void) { - return lv_color_make(0x00, 0x0, 0x00); + return lv_color_make(0x00, 0x00, 0x00); +} + +static inline void lv_color_premultiply(lv_color32_t * c) +{ + c->red = LV_OPA_MIX2(c->red, c->alpha); + c->green = LV_OPA_MIX2(c->green, c->alpha); + c->blue = LV_OPA_MIX2(c->blue, c->alpha); +} + +static inline void lv_color16_premultiply(lv_color16_t * c, lv_opa_t a) +{ + c->red = LV_OPA_MIX2(c->red, a); + c->green = LV_OPA_MIX2(c->green, a); + c->blue = LV_OPA_MIX2(c->blue, a); } -lv_color_t lv_palette_lighten(lv_palette_t p, uint8_t lvl); -lv_color_t lv_palette_darken(lv_palette_t p, uint8_t lvl); /********************** * MACROS **********************/ +#include "lv_palette.h" +#include "lv_color_op.h" + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_color_filter_dsc_t lv_color_filter_shade; + #ifdef __cplusplus } /*extern "C"*/ #endif diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_gc.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_color_op.c similarity index 56% rename from lib/libesp32_lvgl/lvgl/src/misc/lv_gc.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_color_op.c index 95bb5499a..5e2fb3455 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_gc.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_color_op.c @@ -1,12 +1,14 @@ /** - * @file lv_gc.c + * @file lv_color.c * */ /********************* * INCLUDES *********************/ -#include "lv_gc.h" +#include "lv_color.h" +#include "lv_log.h" +#include "../misc/lv_color.h" /********************* * DEFINES @@ -24,10 +26,6 @@ * STATIC VARIABLES **********************/ -#if(!defined(LV_ENABLE_GC)) || LV_ENABLE_GC == 0 - LV_ROOTS -#endif /*LV_ENABLE_GC*/ - /********************** * MACROS **********************/ @@ -35,13 +33,3 @@ /********************** * GLOBAL FUNCTIONS **********************/ - -void _lv_gc_clear_roots(void) -{ -#define LV_CLEAR_ROOT(root_type, root_name) lv_memset_00(&LV_GC_ROOT(root_name), sizeof(LV_GC_ROOT(root_name))); - LV_ITERATE_ROOTS(LV_CLEAR_ROOT) -} - -/********************** - * STATIC FUNCTIONS - **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_color_op.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_color_op.h new file mode 100644 index 000000000..efcde364f --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_color_op.h @@ -0,0 +1,112 @@ +/** + * @file lv_color_op.h + * + */ + +#ifndef LV_COLOR_OP_H +#define LV_COLOR_OP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_assert.h" +#include "lv_math.h" +#include "lv_color.h" +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_color_filter_dsc_t; + +typedef lv_color_t (*lv_color_filter_cb_t)(const struct _lv_color_filter_dsc_t *, lv_color_t, lv_opa_t); + +typedef struct _lv_color_filter_dsc_t { + lv_color_filter_cb_t filter_cb; + void * user_data; +} lv_color_filter_dsc_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Mix two colors with a given ratio. + * @param c1 the first color to mix (usually the foreground) + * @param c2 the second color to mix (usually the background) + * @param mix The ratio of the colors. 0: full `c2`, 255: full `c1`, 127: half `c1` and half`c2` + * @return the mixed color + */ +LV_ATTRIBUTE_FAST_MEM static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix) +{ + lv_color_t ret; + + ret.red = LV_UDIV255((uint16_t)c1.red * mix + c2.red * (255 - mix) + LV_COLOR_MIX_ROUND_OFS); + ret.green = LV_UDIV255((uint16_t)c1.green * mix + c2.green * (255 - mix) + LV_COLOR_MIX_ROUND_OFS); + ret.blue = LV_UDIV255((uint16_t)c1.blue * mix + c2.blue * (255 - mix) + LV_COLOR_MIX_ROUND_OFS); + return ret; +} + +/** + * + * @param fg + * @param bg + * @return + * @note Use bg.alpha in the return value + * @note Use fg.alpha as mix ratio + */ +static inline lv_color32_t lv_color_mix32(lv_color32_t fg, lv_color32_t bg) +{ + if(fg.alpha >= LV_OPA_MAX) { + fg.alpha = bg.alpha; + return fg; + } + if(fg.alpha <= LV_OPA_MIN) { + return bg; + } + bg.red = (uint32_t)((uint32_t)fg.red * fg.alpha + (uint32_t)bg.red * (255 - fg.alpha)) >> 8; + bg.green = (uint32_t)((uint32_t)fg.green * fg.alpha + (uint32_t)bg.green * (255 - fg.alpha)) >> 8; + bg.blue = (uint32_t)((uint32_t)fg.blue * fg.alpha + (uint32_t)bg.blue * (255 - fg.alpha)) >> 8; + return bg; +} + +//! @endcond + +/** + * Get the brightness of a color + * @param color a color + * @return the brightness [0..255] + */ +static inline uint8_t lv_color_brightness(lv_color_t c) +{ + uint16_t bright = (uint16_t)(3u * c.red + c.green + 4u * c.blue); + return (uint8_t)(bright >> 3); +} + +static inline void lv_color_filter_dsc_init(lv_color_filter_dsc_t * dsc, lv_color_filter_cb_t cb) +{ + dsc->filter_cb = cb; +} + +/********************** + * PREDEFINED COLORS + **********************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_COLOR_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_event.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_event.c new file mode 100644 index 000000000..7fbd94510 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_event.c @@ -0,0 +1,193 @@ +/** + * @file lv_event.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_event.h" +#include "../core/lv_global.h" +#include "../stdlib/lv_mem.h" +#include "lv_assert.h" +#include + +/********************* + * DEFINES + *********************/ + +#define event_head LV_GLOBAL_DEFAULT()->event_header +#define event_last_id LV_GLOBAL_DEFAULT()->event_last_register_id + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +#if LV_USE_LOG && LV_LOG_TRACE_EVENT + #define LV_TRACE_EVENT(...) LV_LOG_TRACE(__VA_ARGS__) +#else + #define LV_TRACE_EVENT(...) +#endif + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void _lv_event_push(lv_event_t * e) +{ + /*Build a simple linked list from the objects used in the events + *It's important to know if this object was deleted by a nested event + *called from this `event_cb`.*/ + e->prev = event_head; + event_head = e; + +} + +void _lv_event_pop(lv_event_t * e) +{ + event_head = e->prev; +} + +lv_result_t lv_event_send(lv_event_list_t * list, lv_event_t * e, bool preprocess) +{ + if(list == NULL) return LV_RESULT_OK; + + uint32_t i = 0; + lv_event_dsc_t * dsc = lv_array_at(list, 0); + for(i = 0; i < lv_array_size(list); i++) { + if(dsc[i].cb == NULL) continue; + bool is_preprocessed = (dsc[i].filter & LV_EVENT_PREPROCESS) != 0; + if(is_preprocessed != preprocess) continue; + lv_event_code_t filter = dsc[i].filter & ~LV_EVENT_PREPROCESS; + if(filter == LV_EVENT_ALL || filter == e->code) { + e->user_data = dsc[i].user_data; + dsc[i].cb(e); + if(e->stop_processing) return LV_RESULT_OK; + + /*Stop if the object is deleted*/ + if(e->deleted) return LV_RESULT_INVALID; + + } + } + return LV_RESULT_OK; +} + +void lv_event_add(lv_event_list_t * list, lv_event_cb_t cb, lv_event_code_t filter, + void * user_data) +{ + lv_event_dsc_t dsc = { 0 }; + dsc.cb = cb; + dsc.filter = filter; + dsc.user_data = user_data; + + if(lv_array_size(list) == 0) { + /*event list hasn't been initialized.*/ + lv_array_init(list, 1, sizeof(lv_event_dsc_t)); + } + + lv_array_push_back(list, &dsc); +} + +uint32_t lv_event_get_count(lv_event_list_t * list) +{ + LV_ASSERT_NULL(list); + return lv_array_size(list); +} + +lv_event_dsc_t * lv_event_get_dsc(lv_event_list_t * list, uint32_t index) +{ + LV_ASSERT_NULL(list); + return lv_array_at(list, index); +} + +lv_event_cb_t lv_event_dsc_get_cb(lv_event_dsc_t * dsc) +{ + LV_ASSERT_NULL(dsc); + return dsc->cb; +} + +void * lv_event_dsc_get_user_data(lv_event_dsc_t * dsc) +{ + LV_ASSERT_NULL(dsc); + return dsc->user_data; + +} + +bool lv_event_remove(lv_event_list_t * list, uint32_t index) +{ + LV_ASSERT_NULL(list); + return lv_array_remove(list, index); +} + +void lv_event_remove_all(lv_event_list_t * list) +{ + LV_ASSERT_NULL(list); + lv_array_deinit(list); +} + +void * lv_event_get_current_target(lv_event_t * e) +{ + return e->current_target; +} + +void * lv_event_get_target(lv_event_t * e) +{ + return e->original_target; +} + +lv_event_code_t lv_event_get_code(lv_event_t * e) +{ + return e->code & ~LV_EVENT_PREPROCESS; +} + +void * lv_event_get_param(lv_event_t * e) +{ + return e->param; +} + +void * lv_event_get_user_data(lv_event_t * e) +{ + return e->user_data; +} + +void lv_event_stop_bubbling(lv_event_t * e) +{ + e->stop_bubbling = 1; +} + +void lv_event_stop_processing(lv_event_t * e) +{ + e->stop_processing = 1; +} + +uint32_t lv_event_register_id(void) +{ + event_last_id ++; + return event_last_id; +} + +void _lv_event_mark_deleted(void * target) +{ + lv_event_t * e = event_head; + + while(e) { + if(e->original_target == target || e->current_target == target) e->deleted = 1; + e = e->prev; + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_event.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_event.h new file mode 100644 index 000000000..d5926dd1b --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_event.h @@ -0,0 +1,241 @@ +/** + * @file lv_event.h + * + */ + +#ifndef LV_EVENT_H +#define LV_EVENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include +#include "lv_types.h" +#include "../lv_conf_internal.h" + +#include "lv_array.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef void (*lv_event_cb_t)(lv_event_t * e); + +typedef struct { + lv_event_cb_t cb; + void * user_data; + uint32_t filter; +} lv_event_dsc_t; + +/** + * Type of event being sent to the object. + */ +typedef enum { + LV_EVENT_ALL = 0, + + /** Input device events*/ + LV_EVENT_PRESSED, /**< The object has been pressed*/ + LV_EVENT_PRESSING, /**< The object is being pressed (called continuously while pressing)*/ + LV_EVENT_PRESS_LOST, /**< The object is still being pressed but slid cursor/finger off of the object */ + LV_EVENT_SHORT_CLICKED, /**< The object was pressed for a short period of time, then released it. Not called if scrolled.*/ + LV_EVENT_LONG_PRESSED, /**< Object has been pressed for at least `long_press_time`. Not called if scrolled.*/ + LV_EVENT_LONG_PRESSED_REPEAT, /**< Called after `long_press_time` in every `long_press_repeat_time` ms. Not called if scrolled.*/ + LV_EVENT_CLICKED, /**< Called on release if not scrolled (regardless to long press)*/ + LV_EVENT_RELEASED, /**< Called in every cases when the object has been released*/ + LV_EVENT_SCROLL_BEGIN, /**< Scrolling begins. The event parameter is a pointer to the animation of the scroll. Can be modified*/ + LV_EVENT_SCROLL_THROW_BEGIN, + LV_EVENT_SCROLL_END, /**< Scrolling ends*/ + LV_EVENT_SCROLL, /**< Scrolling*/ + LV_EVENT_GESTURE, /**< A gesture is detected. Get the gesture with `lv_indev_get_gesture_dir(lv_indev_active());` */ + LV_EVENT_KEY, /**< A key is sent to the object. Get the key with `lv_indev_get_key(lv_indev_active());`*/ + LV_EVENT_FOCUSED, /**< The object is focused*/ + LV_EVENT_DEFOCUSED, /**< The object is defocused*/ + LV_EVENT_LEAVE, /**< The object is defocused but still selected*/ + LV_EVENT_HIT_TEST, /**< Perform advanced hit-testing*/ + LV_EVENT_INDEV_RESET, /**< Indev has been reset*/ + + /** Drawing events*/ + LV_EVENT_COVER_CHECK, /**< Check if the object fully covers an area. The event parameter is `lv_cover_check_info_t *`.*/ + LV_EVENT_REFR_EXT_DRAW_SIZE, /**< Get the required extra draw area around the object (e.g. for shadow). The event parameter is `int32_t *` to store the size.*/ + LV_EVENT_DRAW_MAIN_BEGIN, /**< Starting the main drawing phase*/ + LV_EVENT_DRAW_MAIN, /**< Perform the main drawing*/ + LV_EVENT_DRAW_MAIN_END, /**< Finishing the main drawing phase*/ + LV_EVENT_DRAW_POST_BEGIN, /**< Starting the post draw phase (when all children are drawn)*/ + LV_EVENT_DRAW_POST, /**< Perform the post draw phase (when all children are drawn)*/ + LV_EVENT_DRAW_POST_END, /**< Finishing the post draw phase (when all children are drawn)*/ + LV_EVENT_DRAW_TASK_ADDED, /**< Adding a draw task */ + + /** Special events*/ + LV_EVENT_VALUE_CHANGED, /**< The object's value has changed (i.e. slider moved)*/ + LV_EVENT_INSERT, /**< A text is inserted to the object. The event data is `char *` being inserted.*/ + LV_EVENT_REFRESH, /**< Notify the object to refresh something on it (for the user)*/ + LV_EVENT_READY, /**< A process has finished*/ + LV_EVENT_CANCEL, /**< A process has been cancelled */ + + /** Other events*/ + LV_EVENT_CREATE, /**< Object is being created*/ + LV_EVENT_DELETE, /**< Object is being deleted*/ + LV_EVENT_CHILD_CHANGED, /**< Child was removed, added, or its size, position were changed */ + LV_EVENT_CHILD_CREATED, /**< Child was created, always bubbles up to all parents*/ + LV_EVENT_CHILD_DELETED, /**< Child was deleted, always bubbles up to all parents*/ + LV_EVENT_SCREEN_UNLOAD_START, /**< A screen unload started, fired immediately when scr_load is called*/ + LV_EVENT_SCREEN_LOAD_START, /**< A screen load started, fired when the screen change delay is expired*/ + LV_EVENT_SCREEN_LOADED, /**< A screen was loaded*/ + LV_EVENT_SCREEN_UNLOADED, /**< A screen was unloaded*/ + LV_EVENT_SIZE_CHANGED, /**< Object coordinates/size have changed*/ + LV_EVENT_STYLE_CHANGED, /**< Object's style has changed*/ + LV_EVENT_LAYOUT_CHANGED, /**< The children position has changed due to a layout recalculation*/ + LV_EVENT_GET_SELF_SIZE, /**< Get the internal size of a widget*/ + + /** Events of optional LVGL components*/ + LV_EVENT_INVALIDATE_AREA, + LV_EVENT_RESOLUTION_CHANGED, + LV_EVENT_COLOR_FORMAT_CHANGED, + LV_EVENT_REFR_REQUEST, + LV_EVENT_REFR_START, + LV_EVENT_REFR_READY, + LV_EVENT_RENDER_START, + LV_EVENT_RENDER_READY, + LV_EVENT_FLUSH_START, + LV_EVENT_FLUSH_FINISH, + + LV_EVENT_VSYNC, + + _LV_EVENT_LAST, /** Number of default events*/ + + LV_EVENT_PREPROCESS = 0x8000, /** This is a flag that can be set with an event so it's processed + before the class default event processing */ +} lv_event_code_t; + +typedef lv_array_t lv_event_list_t; + +struct _lv_event_t { + void * current_target; + void * original_target; + lv_event_code_t code; + void * user_data; + void * param; + lv_event_t * prev; + uint8_t deleted : 1; + uint8_t stop_processing : 1; + uint8_t stop_bubbling : 1; +}; + +/** + * @brief Event callback. + * Events are used to notify the user of some action being taken on the object. + * For details, see ::lv_event_t. + */ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void _lv_event_push(lv_event_t * e); + +void _lv_event_pop(lv_event_t * e); + +lv_result_t lv_event_send(lv_event_list_t * list, lv_event_t * e, bool preprocess); + +void lv_event_add(lv_event_list_t * list, lv_event_cb_t cb, lv_event_code_t filter, void * user_data); + +uint32_t lv_event_get_count(lv_event_list_t * list); + +lv_event_dsc_t * lv_event_get_dsc(lv_event_list_t * list, uint32_t index); + +lv_event_cb_t lv_event_dsc_get_cb(lv_event_dsc_t * dsc); + +void * lv_event_dsc_get_user_data(lv_event_dsc_t * dsc); + +bool lv_event_remove(lv_event_list_t * list, uint32_t index); + +void lv_event_remove_all(lv_event_list_t * list); + +/** + * Get the object originally targeted by the event. It's the same even if the event is bubbled. + * @param e pointer to the event descriptor + * @return the target of the event_code + */ +void * lv_event_get_target(lv_event_t * e); + +/** + * Get the current target of the event. It's the object which event handler being called. + * If the event is not bubbled it's the same as "normal" target. + * @param e pointer to the event descriptor + * @return pointer to the current target of the event_code + */ +void * lv_event_get_current_target(lv_event_t * e); + +/** + * Get the event code of an event + * @param e pointer to the event descriptor + * @return the event code. (E.g. `LV_EVENT_CLICKED`, `LV_EVENT_FOCUSED`, etc) + */ +lv_event_code_t lv_event_get_code(lv_event_t * e); + +/** + * Get the parameter passed when the event was sent + * @param e pointer to the event descriptor + * @return pointer to the parameter + */ +void * lv_event_get_param(lv_event_t * e); + +/** + * Get the user_data passed when the event was registered on the object + * @param e pointer to the event descriptor + * @return pointer to the user_data + */ +void * lv_event_get_user_data(lv_event_t * e); + +/** + * Stop the event from bubbling. + * This is only valid when called in the middle of an event processing chain. + * @param e pointer to the event descriptor + */ +void lv_event_stop_bubbling(lv_event_t * e); + +/** + * Stop processing this event. + * This is only valid when called in the middle of an event processing chain. + * @param e pointer to the event descriptor + */ +void lv_event_stop_processing(lv_event_t * e); + +/** + * Register a new, custom event ID. + * It can be used the same way as e.g. `LV_EVENT_CLICKED` to send custom events + * @return the new event id + * @example + * uint32_t LV_EVENT_MINE = 0; + * ... + * e = lv_event_register_id(); + * ... + * lv_obj_send_event(obj, LV_EVENT_MINE, &some_data); + */ +uint32_t lv_event_register_id(void); + +/** + * Nested events can be called and one of them might belong to an object that is being deleted. + * Mark this object's `event_temp_data` deleted to know that its `lv_obj_send_event` should return `LV_RESULT_INVALID` + * @param target pointer to an event target which was deleted + */ +void _lv_event_mark_deleted(void * target); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_EVENT_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.c index 52f3ce07d..921d30658 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.c @@ -8,14 +8,16 @@ *********************/ #include "lv_fs.h" -#include "../misc/lv_assert.h" -#include "lv_ll.h" #include -#include "lv_gc.h" +#include "../misc/lv_assert.h" +#include "../stdlib/lv_string.h" +#include "lv_ll.h" +#include "../core/lv_global.h" /********************* * DEFINES *********************/ +#define fsdrv_ll_p &(LV_GLOBAL_DEFAULT()->fsdrv_ll) /********************** * TYPEDEFS @@ -40,7 +42,12 @@ static const char * lv_fs_get_real_path(const char * path); void _lv_fs_init(void) { - _lv_ll_init(&LV_GC_ROOT(_lv_fsdrv_ll), sizeof(lv_fs_drv_t *)); + _lv_ll_init(fsdrv_ll_p, sizeof(lv_fs_drv_t *)); +} + +void _lv_fs_deinit(void) +{ + _lv_ll_clear(fsdrv_ll_p); } bool lv_fs_is_ready(char letter) @@ -81,27 +88,52 @@ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mo return LV_FS_RES_NOT_IMP; } - const char * real_path = lv_fs_get_real_path(path); - void * file_d = drv->open_cb(drv, real_path, mode); + file_p->drv = drv; - if(file_d == NULL || file_d == (void *)(-1)) { - return LV_FS_RES_UNKNOWN; + /* For memory-mapped files we set the file handle to our file descriptor so that we can access the cache from the file operations */ + if(drv->cache_size == LV_FS_CACHE_FROM_BUFFER) { + file_p->file_d = file_p; + } + else { + const char * real_path = lv_fs_get_real_path(path); + void * file_d = drv->open_cb(drv, real_path, mode); + if(file_d == NULL || file_d == (void *)(-1)) { + return LV_FS_RES_UNKNOWN; + } + file_p->file_d = file_d; } - file_p->drv = drv; - file_p->file_d = file_d; - if(drv->cache_size) { - file_p->cache = lv_mem_alloc(sizeof(lv_fs_file_cache_t)); + file_p->cache = lv_malloc_zeroed(sizeof(lv_fs_file_cache_t)); LV_ASSERT_MALLOC(file_p->cache); - lv_memset_00(file_p->cache, sizeof(lv_fs_file_cache_t)); - file_p->cache->start = UINT32_MAX; /*Set an invalid range by default*/ - file_p->cache->end = UINT32_MAX - 1; + + /* If this is a memory-mapped file, then set "cache" to the memory buffer */ + if(drv->cache_size == LV_FS_CACHE_FROM_BUFFER) { + lv_fs_path_ex_t * path_ex = (lv_fs_path_ex_t *)path; + file_p->cache->buffer = (void *)path_ex->buffer; + file_p->cache->start = 0; + file_p->cache->file_position = 0; + file_p->cache->end = path_ex->size; + } + /*Set an invalid range by default*/ + else { + file_p->cache->start = UINT32_MAX; + file_p->cache->end = UINT32_MAX - 1; + } } return LV_FS_RES_OK; } +void lv_fs_make_path_from_buffer(lv_fs_path_ex_t * path, char letter, const void * buf, uint32_t size) +{ + path->path[0] = letter; + path->path[1] = ':'; + path->path[2] = 0; + path->buffer = buf; + path->size = size; +} + lv_fs_res_t lv_fs_close(lv_fs_file_t * file_p) { if(file_p->drv == NULL) { @@ -115,11 +147,12 @@ lv_fs_res_t lv_fs_close(lv_fs_file_t * file_p) lv_fs_res_t res = file_p->drv->close_cb(file_p->drv, file_p->file_d); if(file_p->drv->cache_size && file_p->cache) { - if(file_p->cache->buffer) { - lv_mem_free(file_p->cache->buffer); + /* Only free cache if it was pre-allocated (for memory-mapped files it is never allocated) */ + if(file_p->drv->cache_size != LV_FS_CACHE_FROM_BUFFER && file_p->cache->buffer) { + lv_free(file_p->cache->buffer); } - lv_mem_free(file_p->cache); + lv_free(file_p->cache); } file_p->file_d = NULL; @@ -136,12 +169,18 @@ static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, char * buf, uint32_t uint32_t start = file_p->cache->start; uint32_t end = file_p->cache->end; char * buffer = file_p->cache->buffer; - uint16_t buffer_size = file_p->drv->cache_size; + uint32_t buffer_size = file_p->drv->cache_size; - if(start <= file_position && file_position < end) { + if(start <= file_position && file_position <= end) { /* Data can be read from cache buffer */ - uint16_t buffer_offset = file_position - start; - uint32_t buffer_remaining_length = LV_MIN((uint32_t)buffer_size - buffer_offset, (uint32_t)end - file_position); + uint32_t buffer_remaining_length = (uint32_t)end - file_position + 1; + uint32_t buffer_offset = (end - start) - buffer_remaining_length + 1; + + /* Do not allow reading beyond the actual memory block for memory-mapped files */ + if(file_p->drv->cache_size == LV_FS_CACHE_FROM_BUFFER) { + if(btr > buffer_remaining_length) + btr = buffer_remaining_length - 1; + } if(btr <= buffer_remaining_length) { /*Data is in cache buffer, and buffer end not reached, no need to read from FS*/ @@ -152,8 +191,11 @@ static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, char * buf, uint32_t /*First part of data is in cache buffer, but we need to read rest of data from FS*/ lv_memcpy(buf, buffer + buffer_offset, buffer_remaining_length); + file_p->drv->seek_cb(file_p->drv, file_p->file_d, file_p->cache->end + 1, + LV_FS_SEEK_SET); + uint32_t bytes_read_to_buffer = 0; - if(btr > buffer_size) { + if(btr - buffer_remaining_length > buffer_size) { /*If remaining data chuck is bigger than buffer size, then do not use cache, instead read it directly from FS*/ res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)(buf + buffer_remaining_length), btr - buffer_remaining_length, &bytes_read_to_buffer); @@ -161,8 +203,8 @@ static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, char * buf, uint32_t else { /*If remaining data chunk is smaller than buffer size, then read into cache buffer*/ res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)buffer, buffer_size, &bytes_read_to_buffer); - file_p->cache->start = file_p->cache->end; - file_p->cache->end = file_p->cache->start + bytes_read_to_buffer; + file_p->cache->start = file_p->cache->end + 1; + file_p->cache->end = file_p->cache->start + bytes_read_to_buffer - 1; uint16_t data_chunk_remaining = LV_MIN(btr - buffer_remaining_length, bytes_read_to_buffer); lv_memcpy(buf + buffer_remaining_length, buffer, data_chunk_remaining); @@ -171,6 +213,9 @@ static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, char * buf, uint32_t } } else { + file_p->drv->seek_cb(file_p->drv, file_p->file_d, file_p->cache->file_position, + LV_FS_SEEK_SET); + /*Data is not in cache buffer*/ if(btr > buffer_size) { /*If bigger data is requested, then do not use cache, instead read it directly*/ @@ -179,7 +224,7 @@ static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, char * buf, uint32_t else { /*If small data is requested, then read from FS into cache buffer*/ if(buffer == NULL) { - file_p->cache->buffer = lv_mem_alloc(buffer_size); + file_p->cache->buffer = lv_malloc(buffer_size); LV_ASSERT_MALLOC(file_p->cache->buffer); buffer = file_p->cache->buffer; } @@ -187,7 +232,7 @@ static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, char * buf, uint32_t uint32_t bytes_read_to_buffer = 0; res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)buffer, buffer_size, &bytes_read_to_buffer); file_p->cache->start = file_position; - file_p->cache->end = file_p->cache->start + bytes_read_to_buffer; + file_p->cache->end = file_p->cache->start + bytes_read_to_buffer - 1; *br = LV_MIN(btr, bytes_read_to_buffer); lv_memcpy(buf, buffer, *br); @@ -235,10 +280,21 @@ lv_fs_res_t lv_fs_write(lv_fs_file_t * file_p, const void * buf, uint32_t btw, u return LV_FS_RES_NOT_IMP; } + lv_fs_res_t res = LV_FS_RES_OK; + + /*Need to do FS seek before writing data to FS*/ + if(file_p->drv->cache_size) { + res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, file_p->cache->file_position, LV_FS_SEEK_SET); + if(res != LV_FS_RES_OK) return res; + } + uint32_t bw_tmp = 0; - lv_fs_res_t res = file_p->drv->write_cb(file_p->drv, file_p->file_d, buf, btw, &bw_tmp); + res = file_p->drv->write_cb(file_p->drv, file_p->file_d, buf, btw, &bw_tmp); if(bw != NULL) *bw = bw_tmp; + if(file_p->drv->cache_size && res == LV_FS_RES_OK) + file_p->cache->file_position += bw_tmp; + return res; } @@ -276,7 +332,7 @@ lv_fs_res_t lv_fs_seek(lv_fs_file_t * file_p, uint32_t pos, lv_fs_whence_t whenc break; } case LV_FS_SEEK_END: { - /*Because we don't know the file size, we do a little trick: do a FS seek, then get new file position from FS*/ + /*Because we don't know the file size, we do a little trick: do a FS seek, then get the new file position from FS*/ res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, pos, whence); if(res == LV_FS_RES_OK) { uint32_t tmp_position; @@ -355,8 +411,12 @@ lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path) return LV_FS_RES_OK; } -lv_fs_res_t lv_fs_dir_read(lv_fs_dir_t * rddir_p, char * fn) +lv_fs_res_t lv_fs_dir_read(lv_fs_dir_t * rddir_p, char * fn, uint32_t fn_len) { + if(fn_len == 0) { + return LV_FS_RES_INV_PARAM; + } + if(rddir_p->drv == NULL || rddir_p->dir_d == NULL) { fn[0] = '\0'; return LV_FS_RES_INV_PARAM; @@ -367,7 +427,7 @@ lv_fs_res_t lv_fs_dir_read(lv_fs_dir_t * rddir_p, char * fn) return LV_FS_RES_NOT_IMP; } - lv_fs_res_t res = rddir_p->drv->dir_read_cb(rddir_p->drv, rddir_p->dir_d, fn); + lv_fs_res_t res = rddir_p->drv->dir_read_cb(rddir_p->drv, rddir_p->dir_d, fn, fn_len); return res; } @@ -392,14 +452,14 @@ lv_fs_res_t lv_fs_dir_close(lv_fs_dir_t * rddir_p) void lv_fs_drv_init(lv_fs_drv_t * drv) { - lv_memset_00(drv, sizeof(lv_fs_drv_t)); + lv_memzero(drv, sizeof(lv_fs_drv_t)); } void lv_fs_drv_register(lv_fs_drv_t * drv_p) { /*Save the new driver*/ lv_fs_drv_t ** new_drv; - new_drv = _lv_ll_ins_head(&LV_GC_ROOT(_lv_fsdrv_ll)); + new_drv = _lv_ll_ins_head(fsdrv_ll_p); LV_ASSERT_MALLOC(new_drv); if(new_drv == NULL) return; @@ -410,7 +470,7 @@ lv_fs_drv_t * lv_fs_get_drv(char letter) { lv_fs_drv_t ** drv; - _LV_LL_READ(&LV_GC_ROOT(_lv_fsdrv_ll), drv) { + _LV_LL_READ(fsdrv_ll_p, drv) { if((*drv)->letter == letter) { return *drv; } @@ -424,7 +484,7 @@ char * lv_fs_get_letters(char * buf) lv_fs_drv_t ** drv; uint8_t i = 0; - _LV_LL_READ(&LV_GC_ROOT(_lv_fsdrv_ll), drv) { + _LV_LL_READ(fsdrv_ll_p, drv) { buf[i] = (*drv)->letter; i++; } @@ -437,7 +497,7 @@ char * lv_fs_get_letters(char * buf) const char * lv_fs_get_ext(const char * fn) { size_t i; - for(i = strlen(fn); i > 0; i--) { + for(i = lv_strlen(fn); i > 0; i--) { if(fn[i] == '.') { return &fn[i + 1]; } @@ -451,7 +511,7 @@ const char * lv_fs_get_ext(const char * fn) char * lv_fs_up(char * path) { - size_t len = strlen(path); + size_t len = lv_strlen(path); if(len == 0) return path; len--; /*Go before the trailing '\0'*/ @@ -477,7 +537,7 @@ char * lv_fs_up(char * path) const char * lv_fs_get_last(const char * path) { - size_t len = strlen(path); + size_t len = lv_strlen(path); if(len == 0) return path; len--; /*Go before the trailing '\0'*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.h index c941402c5..ae29456ef 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_fs.h @@ -24,6 +24,8 @@ extern "C" { #define LV_FS_MAX_FN_LENGTH 64 #define LV_FS_MAX_PATH_LENGTH 256 +#define LV_FS_CACHE_FROM_BUFFER UINT32_MAX + /********************** * TYPEDEFS **********************/ @@ -31,7 +33,7 @@ extern "C" { /** * Errors in the file system module. */ -enum { +enum _lv_fs_res_t { LV_FS_RES_OK = 0, LV_FS_RES_HW_ERR, /*Low level hardware error*/ LV_FS_RES_FS_ERR, /*Error in the file system structure*/ @@ -46,16 +48,26 @@ enum { LV_FS_RES_INV_PARAM, /*Invalid parameter among arguments*/ LV_FS_RES_UNKNOWN, /*Other unknown error*/ }; + +#ifdef DOXYGEN +typedef _lv_fs_res_t lv_fs_res_t; +#else typedef uint8_t lv_fs_res_t; +#endif /*DOXYGEN*/ /** * File open mode. */ -enum { +enum _lv_fs_mode_t { LV_FS_MODE_WR = 0x01, LV_FS_MODE_RD = 0x02, }; + +#ifdef DOXYGEN +typedef _lv_fs_mode_t lv_fs_mode_t; +#else typedef uint8_t lv_fs_mode_t; +#endif /*DOXYGEN*/ /** * Seek modes. @@ -66,26 +78,26 @@ typedef enum { LV_FS_SEEK_END = 0x02, /**< Set the position from the end of the file*/ } lv_fs_whence_t; -typedef struct _lv_fs_drv_t { +struct _lv_fs_drv_t; +typedef struct _lv_fs_drv_t lv_fs_drv_t; +struct _lv_fs_drv_t { char letter; - uint16_t cache_size; - bool (*ready_cb)(struct _lv_fs_drv_t * drv); + uint32_t cache_size; + bool (*ready_cb)(lv_fs_drv_t * drv); - void * (*open_cb)(struct _lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode); - lv_fs_res_t (*close_cb)(struct _lv_fs_drv_t * drv, void * file_p); - lv_fs_res_t (*read_cb)(struct _lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br); - lv_fs_res_t (*write_cb)(struct _lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw); - lv_fs_res_t (*seek_cb)(struct _lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); - lv_fs_res_t (*tell_cb)(struct _lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); + void * (*open_cb)(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode); + lv_fs_res_t (*close_cb)(lv_fs_drv_t * drv, void * file_p); + lv_fs_res_t (*read_cb)(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br); + lv_fs_res_t (*write_cb)(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw); + lv_fs_res_t (*seek_cb)(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); + lv_fs_res_t (*tell_cb)(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); - void * (*dir_open_cb)(struct _lv_fs_drv_t * drv, const char * path); - lv_fs_res_t (*dir_read_cb)(struct _lv_fs_drv_t * drv, void * rddir_p, char * fn); - lv_fs_res_t (*dir_close_cb)(struct _lv_fs_drv_t * drv, void * rddir_p); + void * (*dir_open_cb)(lv_fs_drv_t * drv, const char * path); + lv_fs_res_t (*dir_read_cb)(lv_fs_drv_t * drv, void * rddir_p, char * fn, uint32_t fn_len); + lv_fs_res_t (*dir_close_cb)(lv_fs_drv_t * drv, void * rddir_p); -#if LV_USE_USER_DATA void * user_data; /**< Custom file user data*/ -#endif -} lv_fs_drv_t; +}; typedef struct { uint32_t start; @@ -100,6 +112,13 @@ typedef struct { lv_fs_file_cache_t * cache; } lv_fs_file_t; +/* Extended path object to specify the buffer for memory-mapped files */ +typedef struct { + char path[4]; /* This is needed to make it compatible with a normal path */ + const void * buffer; + uint32_t size; +} lv_fs_path_ex_t; + typedef struct { void * dir_d; lv_fs_drv_t * drv; @@ -114,9 +133,14 @@ typedef struct { */ void _lv_fs_init(void); +/** + * Deinitialize the File system interface + */ +void _lv_fs_deinit(void); + /** * Initialize a file system driver with default values. - * It is used to surly have known values in the fields ant not memory junk. + * It is used to ensure all fields have known values and not memory junk. * After it you can set the fields. * @param drv pointer to driver variable to initialize */ @@ -154,6 +178,15 @@ bool lv_fs_is_ready(char letter); */ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mode); +/** + * Make a path object for the memory-mapped file compatible with the file system interface + * @param path path to a lv_fs_path_ex object + * @param letter the letter of the driver. E.g. `LV_FS_MEMFS_LETTER` + * @param buf address of the memory buffer + * @param size size of the memory buffer in bytes + */ +void lv_fs_make_path_from_buffer(lv_fs_path_ex_t * path, char letter, const void * buf, uint32_t size); + /** * Close an already opened file * @param file_p pointer to a lv_fs_file_t variable @@ -193,7 +226,7 @@ lv_fs_res_t lv_fs_seek(lv_fs_file_t * file_p, uint32_t pos, lv_fs_whence_t whenc /** * Give the position of the read write pointer * @param file_p pointer to a lv_fs_file_t variable - * @param pos_p pointer to store the position of the read write pointer + * @param pos pointer to store the position of the read write pointer * @return LV_FS_RES_OK or any error from 'fs_res_t' */ lv_fs_res_t lv_fs_tell(lv_fs_file_t * file_p, uint32_t * pos); @@ -211,9 +244,10 @@ lv_fs_res_t lv_fs_dir_open(lv_fs_dir_t * rddir_p, const char * path); * The name of the directories will begin with '/' * @param rddir_p pointer to an initialized 'fs_dir_t' variable * @param fn pointer to a buffer to store the filename + * @param fn_len length of the buffer to store the filename * @return LV_FS_RES_OK or any error from lv_fs_res_t enum */ -lv_fs_res_t lv_fs_dir_read(lv_fs_dir_t * rddir_p, char * fn); +lv_fs_res_t lv_fs_dir_read(lv_fs_dir_t * rddir_p, char * fn, uint32_t fn_len); /** * Close the directory reading diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_gc.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_gc.h deleted file mode 100644 index 9d7d1bb92..000000000 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_gc.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @file lv_gc.h - * - */ - -#ifndef LV_GC_H -#define LV_GC_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" -#include -#include "lv_mem.h" -#include "lv_ll.h" -#include "lv_timer.h" -#include "lv_types.h" -#include "../draw/lv_img_cache.h" -#include "../draw/lv_draw_mask.h" -#include "../core/lv_obj_pos.h" - -/********************* - * DEFINES - *********************/ -#if LV_IMG_CACHE_DEF_SIZE -# define LV_IMG_CACHE_DEF 1 -#else -# define LV_IMG_CACHE_DEF 0 -#endif - -#define LV_DISPATCH(f, t, n) f(t, n) -#define LV_DISPATCH_COND(f, t, n, m, v) LV_CONCAT3(LV_DISPATCH, m, v)(f, t, n) - -#define LV_DISPATCH00(f, t, n) LV_DISPATCH(f, t, n) -#define LV_DISPATCH01(f, t, n) -#define LV_DISPATCH10(f, t, n) -#define LV_DISPATCH11(f, t, n) LV_DISPATCH(f, t, n) - -#define LV_ITERATE_ROOTS(f) \ - LV_DISPATCH(f, lv_ll_t, _lv_timer_ll) /*Linked list to store the lv_timers*/ \ - LV_DISPATCH(f, lv_ll_t, _lv_disp_ll) /*Linked list of display device*/ \ - LV_DISPATCH(f, lv_ll_t, _lv_indev_ll) /*Linked list of input device*/ \ - LV_DISPATCH(f, lv_ll_t, _lv_fsdrv_ll) \ - LV_DISPATCH(f, lv_ll_t, _lv_anim_ll) \ - LV_DISPATCH(f, lv_ll_t, _lv_group_ll) \ - LV_DISPATCH(f, lv_ll_t, _lv_img_decoder_ll) \ - LV_DISPATCH(f, lv_ll_t, _lv_obj_style_trans_ll) \ - LV_DISPATCH(f, lv_layout_dsc_t *, _lv_layout_list) \ - LV_DISPATCH_COND(f, _lv_img_cache_entry_t*, _lv_img_cache_array, LV_IMG_CACHE_DEF, 1) \ - LV_DISPATCH_COND(f, _lv_img_cache_entry_t, _lv_img_cache_single, LV_IMG_CACHE_DEF, 0) \ - LV_DISPATCH(f, lv_timer_t*, _lv_timer_act) \ - LV_DISPATCH(f, lv_mem_buf_arr_t , lv_mem_buf) \ - LV_DISPATCH_COND(f, _lv_draw_mask_radius_circle_dsc_arr_t , _lv_circle_cache, LV_DRAW_COMPLEX, 1) \ - LV_DISPATCH_COND(f, _lv_draw_mask_saved_arr_t , _lv_draw_mask_list, LV_DRAW_COMPLEX, 1) \ - LV_DISPATCH(f, void * , _lv_theme_default_styles) \ - LV_DISPATCH(f, void * , _lv_theme_basic_styles) \ - LV_DISPATCH_COND(f, uint8_t *, _lv_font_decompr_buf, LV_USE_FONT_COMPRESSED, 1) \ - LV_DISPATCH(f, uint8_t * , _lv_grad_cache_mem) \ - LV_DISPATCH(f, uint8_t * , _lv_style_custom_prop_flag_lookup_table) - -#define LV_DEFINE_ROOT(root_type, root_name) root_type root_name; -#define LV_ROOTS LV_ITERATE_ROOTS(LV_DEFINE_ROOT) - -#if LV_ENABLE_GC == 1 -#if LV_MEM_CUSTOM != 1 -#error "GC requires CUSTOM_MEM" -#endif /*LV_MEM_CUSTOM*/ -#include LV_GC_INCLUDE -#else /*LV_ENABLE_GC*/ -#define LV_GC_ROOT(x) x -#define LV_EXTERN_ROOT(root_type, root_name) extern root_type root_name; -LV_ITERATE_ROOTS(LV_EXTERN_ROOT) -#endif /*LV_ENABLE_GC*/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -void _lv_gc_clear_roots(void); - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_GC_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.c index e7582316b..6debda073 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.c @@ -8,7 +8,7 @@ * INCLUDES *********************/ #include "lv_ll.h" -#include "lv_mem.h" +#include "../stdlib/lv_mem.h" /********************* * DEFINES @@ -39,11 +39,6 @@ static void node_set_next(lv_ll_t * ll_p, lv_ll_node_t * act, lv_ll_node_t * nex * GLOBAL FUNCTIONS **********************/ -/** - * Initialize linked list - * @param ll_p pointer to lv_ll_t variable - * @param node_size the size of 1 node in bytes - */ void _lv_ll_init(lv_ll_t * ll_p, uint32_t node_size) { ll_p->head = NULL; @@ -59,16 +54,11 @@ void _lv_ll_init(lv_ll_t * ll_p, uint32_t node_size) ll_p->n_size = node_size; } -/** - * Add a new head to a linked list - * @param ll_p pointer to linked list - * @return pointer to the new head - */ void * _lv_ll_ins_head(lv_ll_t * ll_p) { lv_ll_node_t * n_new; - n_new = lv_mem_alloc(ll_p->n_size + LL_NODE_META_SIZE); + n_new = lv_malloc(ll_p->n_size + LL_NODE_META_SIZE); if(n_new != NULL) { node_set_prev(ll_p, n_new, NULL); /*No prev. before the new head*/ @@ -87,12 +77,6 @@ void * _lv_ll_ins_head(lv_ll_t * ll_p) return n_new; } -/** - * Insert a new node in front of the n_act node - * @param ll_p pointer to linked list - * @param n_act pointer a node - * @return pointer to the new node - */ void * _lv_ll_ins_prev(lv_ll_t * ll_p, void * n_act) { lv_ll_node_t * n_new; @@ -104,7 +88,7 @@ void * _lv_ll_ins_prev(lv_ll_t * ll_p, void * n_act) if(n_new == NULL) return NULL; } else { - n_new = lv_mem_alloc(ll_p->n_size + LL_NODE_META_SIZE); + n_new = lv_malloc(ll_p->n_size + LL_NODE_META_SIZE); if(n_new == NULL) return NULL; lv_ll_node_t * n_prev; @@ -118,16 +102,11 @@ void * _lv_ll_ins_prev(lv_ll_t * ll_p, void * n_act) return n_new; } -/** - * Add a new tail to a linked list - * @param ll_p pointer to linked list - * @return pointer to the new tail - */ void * _lv_ll_ins_tail(lv_ll_t * ll_p) { lv_ll_node_t * n_new; - n_new = lv_mem_alloc(ll_p->n_size + LL_NODE_META_SIZE); + n_new = lv_malloc(ll_p->n_size + LL_NODE_META_SIZE); if(n_new != NULL) { node_set_next(ll_p, n_new, NULL); /*No next after the new tail*/ @@ -145,12 +124,6 @@ void * _lv_ll_ins_tail(lv_ll_t * ll_p) return n_new; } -/** - * Remove the node 'node_p' from 'll_p' linked list. - * It does not free the memory of node. - * @param ll_p pointer to the linked list of 'node_p' - * @param node_p pointer to node in 'll_p' linked list - */ void _lv_ll_remove(lv_ll_t * ll_p, void * node_p) { if(ll_p == NULL) return; @@ -184,11 +157,7 @@ void _lv_ll_remove(lv_ll_t * ll_p, void * node_p) } } -/** - * Remove and free all elements from a linked list. The list remain valid but become empty. - * @param ll_p pointer to linked list - */ -void _lv_ll_clear(lv_ll_t * ll_p) +void _lv_ll_clear_custom(lv_ll_t * ll_p, void(*cleanup)(void *)) { void * i; void * i_next; @@ -198,22 +167,17 @@ void _lv_ll_clear(lv_ll_t * ll_p) while(i != NULL) { i_next = _lv_ll_get_next(ll_p, i); - - _lv_ll_remove(ll_p, i); - lv_mem_free(i); - + if(cleanup == NULL) { + _lv_ll_remove(ll_p, i); + lv_free(i); + } + else { + cleanup(i); + } i = i_next; } } -/** - * Move a node to a new linked list - * @param ll_ori_p pointer to the original (old) linked list - * @param ll_new_p pointer to the new linked list - * @param node pointer to a node - * @param head true: be the head in the new list - * false be the tail in the new list - */ void _lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool head) { _lv_ll_remove(ll_ori_p, node); @@ -248,34 +212,18 @@ void _lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node, bool h } } -/** - * Return with head node of the linked list - * @param ll_p pointer to linked list - * @return pointer to the head of 'll_p' - */ void * _lv_ll_get_head(const lv_ll_t * ll_p) { if(ll_p == NULL) return NULL; return ll_p->head; } -/** - * Return with tail node of the linked list - * @param ll_p pointer to linked list - * @return pointer to the tail of 'll_p' - */ void * _lv_ll_get_tail(const lv_ll_t * ll_p) { if(ll_p == NULL) return NULL; return ll_p->tail; } -/** - * Return with the pointer of the next node after 'n_act' - * @param ll_p pointer to linked list - * @param n_act pointer a node - * @return pointer to the next node - */ void * _lv_ll_get_next(const lv_ll_t * ll_p, const void * n_act) { /*Pointer to the next node is stored in the end of this node. @@ -285,12 +233,6 @@ void * _lv_ll_get_next(const lv_ll_t * ll_p, const void * n_act) return *((lv_ll_node_t **)n_act_d); } -/** - * Return with the pointer of the previous node before 'n_act' - * @param ll_p pointer to linked list - * @param n_act pointer a node - * @return pointer to the previous node - */ void * _lv_ll_get_prev(const lv_ll_t * ll_p, const void * n_act) { /*Pointer to the prev. node is stored in the end of this node. @@ -300,11 +242,6 @@ void * _lv_ll_get_prev(const lv_ll_t * ll_p, const void * n_act) return *((lv_ll_node_t **)n_act_d); } -/** - * Return the length of the linked list. - * @param ll_p pointer to linked list - * @return length of the linked list - */ uint32_t _lv_ll_get_len(const lv_ll_t * ll_p) { uint32_t len = 0; @@ -317,12 +254,6 @@ uint32_t _lv_ll_get_len(const lv_ll_t * ll_p) return len; } -/** - * Move a node before an other node in the same linked list - * @param ll_p pointer to a linked list - * @param n_act pointer to node to move - * @param n_after pointer to a node which should be after `n_act` - */ void _lv_ll_move_before(lv_ll_t * ll_p, void * n_act, void * n_after) { if(n_act == n_after) return; /*Can't move before itself*/ @@ -351,11 +282,6 @@ void _lv_ll_move_before(lv_ll_t * ll_p, void * n_act, void * n_after) if(n_before == NULL) ll_p->head = n_act; } -/** - * Check if a linked list is empty - * @param ll_p pointer to a linked list - * @return true: the linked list is empty; false: not empty - */ bool _lv_ll_is_empty(lv_ll_t * ll_p) { if(ll_p == NULL) return true; diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.h index d38f69285..676e404fd 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_ll.h @@ -76,11 +76,16 @@ void * _lv_ll_ins_tail(lv_ll_t * ll_p); */ void _lv_ll_remove(lv_ll_t * ll_p, void * node_p); +void _lv_ll_clear_custom(lv_ll_t * ll_p, void(*cleanup)(void *)); + /** * Remove and free all elements from a linked list. The list remain valid but become empty. * @param ll_p pointer to linked list */ -void _lv_ll_clear(lv_ll_t * ll_p); +static inline void _lv_ll_clear(lv_ll_t * ll_p) +{ + _lv_ll_clear_custom(ll_p, NULL); +} /** * Move a node to a new linked list diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_log.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_log.c index d79463f2b..d72c11bd0 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_log.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_log.c @@ -11,8 +11,11 @@ #include #include -#include "lv_printf.h" -#include "../hal/lv_hal_tick.h" +#include "../stdlib/lv_sprintf.h" +#include "../stdlib/lv_mem.h" +#include "../stdlib/lv_string.h" +#include "../tick/lv_tick.h" +#include "../core/lv_global.h" #if LV_LOG_PRINTF #include @@ -21,6 +24,26 @@ /********************* * DEFINES *********************/ +#if LV_LOG_USE_TIMESTAMP + #define last_log_time LV_GLOBAL_DEFAULT()->log_last_log_time +#endif +#define custom_print_cb LV_GLOBAL_DEFAULT()->custom_log_print_cb + +#if LV_LOG_USE_TIMESTAMP + #define LOG_TIMESTAMP_FMT "\t(%" LV_PRIu32 ".%03" LV_PRIu32 ", +%" LV_PRIu32 ")\t" + #define LOG_TIMESTAMP_EXPR t / 1000, t % 1000, t - last_log_time, +#else + #define LOG_TIMESTAMP_FMT + #define LOG_TIMESTAMP_EXPR +#endif + +#if LV_LOG_USE_FILE_LINE + #define LOG_FILE_LINE_FMT " %s:%d" + #define LOG_FILE_LINE_EXPR , &file[p], line +#else + #define LOG_FILE_LINE_FMT + #define LOG_FILE_LINE_EXPR +#endif /********************** * TYPEDEFS @@ -33,7 +56,6 @@ /********************** * STATIC VARIABLES **********************/ -static lv_log_print_g_cb_t custom_print_cb; /********************** * MACROS @@ -43,71 +65,57 @@ static lv_log_print_g_cb_t custom_print_cb; * GLOBAL FUNCTIONS **********************/ -/** - * Register custom print/write function to call when a log is added. - * It can format its "File path", "Line number" and "Description" as required - * and send the formatted log message to a console or serial port. - * @param print_cb a function pointer to print a log - */ void lv_log_register_print_cb(lv_log_print_g_cb_t print_cb) { custom_print_cb = print_cb; } -/** - * Add a log - * @param level the level of log. (From `lv_log_level_t` enum) - * @param file name of the file when the log added - * @param line line number in the source code where the log added - * @param func name of the function when the log added - * @param format printf-like format string - * @param ... parameters for `format` - */ void _lv_log_add(lv_log_level_t level, const char * file, int line, const char * func, const char * format, ...) { if(level >= _LV_LOG_LEVEL_NUM) return; /*Invalid level*/ - static uint32_t last_log_time = 0; - if(level >= LV_LOG_LEVEL) { va_list args; va_start(args, format); +#if LV_LOG_USE_FILE_LINE /*Use only the file name not the path*/ size_t p; - for(p = strlen(file); p > 0; p--) { + for(p = lv_strlen(file); p > 0; p--) { if(file[p] == '/' || file[p] == '\\') { p++; /*Skip the slash*/ break; } } +#else + LV_UNUSED(file); + LV_UNUSED(line); +#endif +#if LV_LOG_USE_TIMESTAMP uint32_t t = lv_tick_get(); +#endif static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error", "User"}; #if LV_LOG_PRINTF - printf("[%s]\t(%" LV_PRId32 ".%03" LV_PRId32 ", +%" LV_PRId32 ")\t %s: ", - lvl_prefix[level], t / 1000, t % 1000, t - last_log_time, func); + printf("[%s]" LOG_TIMESTAMP_FMT " %s: ", + lvl_prefix[level], LOG_TIMESTAMP_EXPR func); vprintf(format, args); - printf(" \t(in %s line #%d)\n", &file[p], line); + printf(LOG_FILE_LINE_FMT "\n" LOG_FILE_LINE_EXPR); #else if(custom_print_cb) { char buf[512]; -#if LV_SPRINTF_CUSTOM char msg[256]; lv_vsnprintf(msg, sizeof(msg), format, args); - lv_snprintf(buf, sizeof(buf), "[%s]\t(%" LV_PRId32 ".%03" LV_PRId32 ", +%" LV_PRId32 ")\t %s: %s \t(in %s line #%d)\n", - lvl_prefix[level], t / 1000, t % 1000, t - last_log_time, func, msg, &file[p], line); -#else - lv_vaformat_t vaf = {format, &args}; - lv_snprintf(buf, sizeof(buf), "[%s]\t(%" LV_PRId32 ".%03" LV_PRId32 ", +%" LV_PRId32 ")\t %s: %pV \t(in %s line #%d)\n", - lvl_prefix[level], t / 1000, t % 1000, t - last_log_time, func, (void *)&vaf, &file[p], line); -#endif - custom_print_cb(buf); + lv_snprintf(buf, sizeof(buf), "[%s]" LOG_TIMESTAMP_FMT " %s: %s" LOG_FILE_LINE_FMT "\n", + lvl_prefix[level], LOG_TIMESTAMP_EXPR func, msg LOG_FILE_LINE_EXPR); + custom_print_cb(level, buf); } #endif +#if LV_LOG_USE_TIMESTAMP last_log_time = t; +#endif va_end(args); } } @@ -124,13 +132,8 @@ void lv_log(const char * format, ...) #else if(custom_print_cb) { char buf[512]; -#if LV_SPRINTF_CUSTOM lv_vsnprintf(buf, sizeof(buf), format, args); -#else - lv_vaformat_t vaf = {format, &args}; - lv_snprintf(buf, sizeof(buf), "%pV", (void *)&vaf); -#endif - custom_print_cb(buf); + custom_print_cb(LV_LOG_LEVEL_USER, buf); } #endif diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_log.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_log.h index 9a009930d..87ca3820a 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_log.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_log.h @@ -42,6 +42,15 @@ LV_EXPORT_CONST_INT(LV_LOG_LEVEL_NONE); typedef int8_t lv_log_level_t; #if LV_USE_LOG + +#if LV_LOG_USE_FILE_LINE +#define LV_LOG_FILE __FILE__ +#define LV_LOG_LINE __LINE__ +#else +#define LV_LOG_FILE NULL +#define LV_LOG_LINE 0 +#endif + /********************** * TYPEDEFS **********************/ @@ -49,7 +58,7 @@ typedef int8_t lv_log_level_t; /** * Log print function. Receives a string buffer to print". */ -typedef void (*lv_log_print_g_cb_t)(const char * buf); +typedef void (*lv_log_print_g_cb_t)(lv_log_level_t level, const char * buf); /********************** * GLOBAL PROTOTYPES @@ -88,7 +97,7 @@ void _lv_log_add(lv_log_level_t level, const char * file, int line, **********************/ #ifndef LV_LOG_TRACE # if LV_LOG_LEVEL <= LV_LOG_LEVEL_TRACE -# define LV_LOG_TRACE(...) _lv_log_add(LV_LOG_LEVEL_TRACE, __FILE__, __LINE__, __func__, __VA_ARGS__) +# define LV_LOG_TRACE(...) _lv_log_add(LV_LOG_LEVEL_TRACE, LV_LOG_FILE, LV_LOG_LINE, __func__, __VA_ARGS__) # else # define LV_LOG_TRACE(...) do {}while(0) # endif @@ -96,7 +105,7 @@ void _lv_log_add(lv_log_level_t level, const char * file, int line, #ifndef LV_LOG_INFO # if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO -# define LV_LOG_INFO(...) _lv_log_add(LV_LOG_LEVEL_INFO, __FILE__, __LINE__, __func__, __VA_ARGS__) +# define LV_LOG_INFO(...) _lv_log_add(LV_LOG_LEVEL_INFO, LV_LOG_FILE, LV_LOG_LINE, __func__, __VA_ARGS__) # else # define LV_LOG_INFO(...) do {}while(0) # endif @@ -104,7 +113,7 @@ void _lv_log_add(lv_log_level_t level, const char * file, int line, #ifndef LV_LOG_WARN # if LV_LOG_LEVEL <= LV_LOG_LEVEL_WARN -# define LV_LOG_WARN(...) _lv_log_add(LV_LOG_LEVEL_WARN, __FILE__, __LINE__, __func__, __VA_ARGS__) +# define LV_LOG_WARN(...) _lv_log_add(LV_LOG_LEVEL_WARN, LV_LOG_FILE, LV_LOG_LINE, __func__, __VA_ARGS__) # else # define LV_LOG_WARN(...) do {}while(0) # endif @@ -112,7 +121,7 @@ void _lv_log_add(lv_log_level_t level, const char * file, int line, #ifndef LV_LOG_ERROR # if LV_LOG_LEVEL <= LV_LOG_LEVEL_ERROR -# define LV_LOG_ERROR(...) _lv_log_add(LV_LOG_LEVEL_ERROR, __FILE__, __LINE__, __func__, __VA_ARGS__) +# define LV_LOG_ERROR(...) _lv_log_add(LV_LOG_LEVEL_ERROR, LV_LOG_FILE, LV_LOG_LINE, __func__, __VA_ARGS__) # else # define LV_LOG_ERROR(...) do {}while(0) # endif @@ -120,7 +129,7 @@ void _lv_log_add(lv_log_level_t level, const char * file, int line, #ifndef LV_LOG_USER # if LV_LOG_LEVEL <= LV_LOG_LEVEL_USER -# define LV_LOG_USER(...) _lv_log_add(LV_LOG_LEVEL_USER, __FILE__, __LINE__, __func__, __VA_ARGS__) +# define LV_LOG_USER(...) _lv_log_add(LV_LOG_LEVEL_USER, LV_LOG_FILE, LV_LOG_LINE, __func__, __VA_ARGS__) # else # define LV_LOG_USER(...) do {}while(0) # endif diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.c old mode 100644 new mode 100755 index 6ff83903e..5f3618cf4 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.c @@ -10,7 +10,8 @@ #include "lv_lru.h" #include "lv_math.h" -#include "lv_mem.h" +#include "../stdlib/lv_mem.h" +#include "../stdlib/lv_string.h" #include "lv_assert.h" #include "lv_log.h" @@ -70,12 +71,11 @@ static lv_lru_item_t * lv_lru_pop_or_create_item(lv_lru_t * cache); * GLOBAL FUNCTIONS **********************/ -lv_lru_t * lv_lru_create(size_t cache_size, size_t average_length, lv_lru_free_t * value_free, - lv_lru_free_t * key_free) +lv_lru_t * lv_lru_create(size_t cache_size, size_t average_length, lv_lru_free_cb_t value_free, + lv_lru_free_cb_t key_free) { // create the cache - lv_lru_t * cache = (lv_lru_t *) lv_mem_alloc(sizeof(lv_lru_t)); - lv_memset_00(cache, sizeof(lv_lru_t)); + lv_lru_t * cache = lv_malloc_zeroed(sizeof(lv_lru_t)); if(!cache) { LV_LOG_WARN("LRU Cache unable to create cache object"); return NULL; @@ -85,27 +85,25 @@ lv_lru_t * lv_lru_create(size_t cache_size, size_t average_length, lv_lru_free_t cache->free_memory = cache_size; cache->total_memory = cache_size; cache->seed = lv_rand(1, UINT32_MAX); - cache->value_free = value_free ? value_free : lv_mem_free; - cache->key_free = key_free ? key_free : lv_mem_free; + cache->value_free = value_free ? value_free : lv_free; + cache->key_free = key_free ? key_free : lv_free; // size the hash table to a guestimate of the number of slots required (assuming a perfect hash) - cache->items = (lv_lru_item_t **) lv_mem_alloc(sizeof(lv_lru_item_t *) * cache->hash_table_size); - lv_memset_00(cache->items, sizeof(lv_lru_item_t *) * cache->hash_table_size); + cache->items = lv_malloc_zeroed(sizeof(lv_lru_item_t *) * cache->hash_table_size); if(!cache->items) { LV_LOG_WARN("LRU Cache unable to create cache hash table"); - lv_mem_free(cache); + lv_free(cache); return NULL; } return cache; } - -void lv_lru_del(lv_lru_t * cache) +void lv_lru_delete(lv_lru_t * cache) { LV_ASSERT_NULL(cache); // free each of the cached items, and the hash table - lv_lru_item_t * item = NULL, *next = NULL; + lv_lru_item_t * item = NULL, * next = NULL; uint32_t i = 0; if(cache->items) { for(; i < cache->hash_table_size; i++) { @@ -115,27 +113,26 @@ void lv_lru_del(lv_lru_t * cache) cache->value_free(item->value); cache->key_free(item->key); cache->free_memory += item->value_length; - lv_mem_free(item); + lv_free(item); item = next; } } - lv_mem_free(cache->items); + lv_free(cache->items); } if(cache->free_items) { item = cache->free_items; while(item) { next = (lv_lru_item_t *) item->next; - lv_mem_free(item); + lv_free(item); item = next; } } // free the cache - lv_mem_free(cache); + lv_free(cache); } - lv_lru_res_t lv_lru_set(lv_lru_t * cache, const void * key, size_t key_length, void * value, size_t value_length) { test_for_missing_cache(); @@ -146,7 +143,7 @@ lv_lru_res_t lv_lru_set(lv_lru_t * cache, const void * key, size_t key_length, v // see if the key already exists uint32_t hash_index = lv_lru_hash(cache, key, key_length); int required = 0; - lv_lru_item_t * item = NULL, *prev = NULL; + lv_lru_item_t * item = NULL, * prev = NULL; item = cache->items[hash_index]; while(item && lv_lru_cmp_keys(item, key, key_length)) { @@ -166,7 +163,7 @@ lv_lru_res_t lv_lru_set(lv_lru_t * cache, const void * key, size_t key_length, v // insert a new item item = lv_lru_pop_or_create_item(cache); item->value = value; - item->key = lv_mem_alloc(key_length); + item->key = lv_malloc(key_length); memcpy(item->key, key, key_length); item->value_length = value_length; item->key_length = key_length; @@ -188,7 +185,6 @@ lv_lru_res_t lv_lru_set(lv_lru_t * cache, const void * key, size_t key_length, v return LV_LRU_OK; } - lv_lru_res_t lv_lru_get(lv_lru_t * cache, const void * key, size_t key_size, void ** value) { test_for_missing_cache(); @@ -218,7 +214,7 @@ lv_lru_res_t lv_lru_remove(lv_lru_t * cache, const void * key, size_t key_size) test_for_missing_key(); // loop until we find the item, or hit the end of a chain - lv_lru_item_t * item = NULL, *prev = NULL; + lv_lru_item_t * item = NULL, * prev = NULL; uint32_t hash_index = lv_lru_hash(cache, key, key_size); item = cache->items[hash_index]; @@ -236,8 +232,8 @@ lv_lru_res_t lv_lru_remove(lv_lru_t * cache, const void * key, size_t key_size) void lv_lru_remove_lru_item(lv_lru_t * cache) { - lv_lru_item_t * min_item = NULL, *min_prev = NULL; - lv_lru_item_t * item = NULL, *prev = NULL; + lv_lru_item_t * min_item = NULL, * min_prev = NULL; + lv_lru_item_t * item = NULL, * prev = NULL; uint32_t i = 0, min_index = -1; uint64_t min_access_count = -1; @@ -326,7 +322,7 @@ static void lv_lru_remove_item(lv_lru_t * cache, lv_lru_item_t * prev, lv_lru_it cache->key_free(item->key); // push the item to the free items queue - lv_memset_00(item, sizeof(lv_lru_item_t)); + lv_memzero(item, sizeof(lv_lru_item_t)); item->next = cache->free_items; cache->free_items = item; } @@ -338,11 +334,10 @@ static lv_lru_item_t * lv_lru_pop_or_create_item(lv_lru_t * cache) if(cache->free_items) { item = cache->free_items; cache->free_items = item->next; - lv_memset_00(item, sizeof(lv_lru_item_t)); + lv_memzero(item, sizeof(lv_lru_item_t)); } else { - item = (lv_lru_item_t *) lv_mem_alloc(sizeof(lv_lru_item_t)); - lv_memset_00(item, sizeof(lv_lru_item_t)); + item = lv_malloc_zeroed(sizeof(lv_lru_item_t)); } return item; diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.h old mode 100644 new mode 100755 index 2d0134e5c..02172d202 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_lru.h @@ -21,7 +21,6 @@ extern "C" { #include #include - /********************* * DEFINES *********************/ @@ -39,7 +38,8 @@ typedef enum { LV_LRU_VALUE_TOO_LARGE } lv_lru_res_t; -typedef void (lv_lru_free_t)(void * v); +typedef void (*lv_lru_free_cb_t)(void * v); + typedef struct _lv_lru_item_t lv_lru_item_t; typedef struct lv_lru_t { @@ -50,20 +50,19 @@ typedef struct lv_lru_t { size_t average_item_length; size_t hash_table_size; uint32_t seed; - lv_lru_free_t * value_free; - lv_lru_free_t * key_free; + lv_lru_free_cb_t value_free; + lv_lru_free_cb_t key_free; lv_lru_item_t * free_items; } lv_lru_t; - /********************** * GLOBAL PROTOTYPES **********************/ -lv_lru_t * lv_lru_create(size_t cache_size, size_t average_length, lv_lru_free_t * value_free, - lv_lru_free_t * key_free); +lv_lru_t * lv_lru_create(size_t cache_size, size_t average_length, lv_lru_free_cb_t value_free, + lv_lru_free_cb_t key_free); -void lv_lru_del(lv_lru_t * cache); +void lv_lru_delete(lv_lru_t * cache); lv_lru_res_t lv_lru_set(lv_lru_t * cache, const void * key, size_t key_length, void * value, size_t value_length); diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_math.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_math.c index cf2d0fba4..11f3f50ad 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_math.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_math.c @@ -7,15 +7,24 @@ * INCLUDES *********************/ #include "lv_math.h" +#include "../core/lv_global.h" /********************* * DEFINES *********************/ +#define rand_seed LV_GLOBAL_DEFAULT()->math_rand_seed /********************** * TYPEDEFS **********************/ +#define CUBIC_NEWTON_ITERATIONS 8 +#define CUBIC_PRECISION_BITS 10 /* 10 or 14 bits recommended, int64_t calculation is used for >14bit precision */ + +#if CUBIC_PRECISION_BITS < 10 || CUBIC_PRECISION_BITS > 20 + #error "cubic precision bits should be in range of [10, 20] for 32bit/64bit calculations." +#endif + /********************** * STATIC PROTOTYPES **********************/ @@ -23,13 +32,13 @@ /********************** * STATIC VARIABLES **********************/ -static const int16_t sin0_90_table[] = { +static const uint16_t sin0_90_table[] = { 0, 572, 1144, 1715, 2286, 2856, 3425, 3993, 4560, 5126, 5690, 6252, 6813, 7371, 7927, 8481, - 9032, 9580, 10126, 10668, 11207, 11743, 12275, 12803, 13328, 13848, 14364, 14876, 15383, 15886, 16383, 16876, - 17364, 17846, 18323, 18794, 19260, 19720, 20173, 20621, 21062, 21497, 21925, 22347, 22762, 23170, 23571, 23964, - 24351, 24730, 25101, 25465, 25821, 26169, 26509, 26841, 27165, 27481, 27788, 28087, 28377, 28659, 28932, 29196, - 29451, 29697, 29934, 30162, 30381, 30591, 30791, 30982, 31163, 31335, 31498, 31650, 31794, 31927, 32051, 32165, - 32269, 32364, 32448, 32523, 32587, 32642, 32687, 32722, 32747, 32762, 32767 + 9032, 9580, 10126, 10668, 11207, 11743, 12275, 12803, 13328, 13848, 14365, 14876, 15384, 15886, 16384, 16877, + 17364, 17847, 18324, 18795, 19261, 19720, 20174, 20622, 21063, 21498, 21926, 22348, 22763, 23170, 23571, 23965, + 24351, 24730, 25102, 25466, 25822, 26170, 26510, 26842, 27166, 27482, 27789, 28088, 28378, 28660, 28932, 29197, + 29452, 29698, 29935, 30163, 30382, 30592, 30792, 30983, 31164, 31336, 31499, 31651, 31795, 31928, 32052, 32166, + 32270, 32365, 32449, 32524, 32588, 32643, 32688, 32723, 32748, 32763, 32768 }; /********************** @@ -40,17 +49,11 @@ static const int16_t sin0_90_table[] = { * GLOBAL FUNCTIONS **********************/ -/** - * Return with sinus of an angle - * @param angle - * @return sinus of 'angle'. sin(-90) = -32767, sin(90) = 32767 - */ -int16_t LV_ATTRIBUTE_FAST_MEM lv_trigo_sin(int16_t angle) +LV_ATTRIBUTE_FAST_MEM int32_t lv_trigo_sin(int16_t angle) { - int16_t ret = 0; - angle = angle % 360; - - if(angle < 0) angle = 360 + angle; + int32_t ret = 0; + while(angle < 0) angle += 360; + while(angle >= 360) angle -= 360; if(angle < 90) { ret = sin0_90_table[angle]; @@ -68,51 +71,147 @@ int16_t LV_ATTRIBUTE_FAST_MEM lv_trigo_sin(int16_t angle) ret = -sin0_90_table[angle]; } + if(ret == 32767) return 32768; + else if(ret == -32767) return -32768; + else return ret; +} + +/** + * cubic-bezier Reference: + * + * https://github.com/gre/bezier-easing + * https://opensource.apple.com/source/WebCore/WebCore-955.66/platform/graphics/UnitBezier.h + * + * Copyright (c) 2014 Gaëtan Renaudeau + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +static int32_t do_cubic_bezier(int32_t t, int32_t a, int32_t b, int32_t c) +{ + /*a * t^3 + b * t^2 + c * t*/ +#if CUBIC_PRECISION_BITS > 14 + int64_t ret; +#else + int32_t ret; +#endif + + ret = a; + ret = (ret * t) >> CUBIC_PRECISION_BITS; + ret = ((ret + b) * t) >> CUBIC_PRECISION_BITS; + ret = ((ret + c) * t) >> CUBIC_PRECISION_BITS; return ret; } -/** - * Calculate a value of a Cubic Bezier function. - * @param t time in range of [0..LV_BEZIER_VAL_MAX] - * @param u0 start values in range of [0..LV_BEZIER_VAL_MAX] - * @param u1 control value 1 values in range of [0..LV_BEZIER_VAL_MAX] - * @param u2 control value 2 in range of [0..LV_BEZIER_VAL_MAX] - * @param u3 end values in range of [0..LV_BEZIER_VAL_MAX] - * @return the value calculated from the given parameters in range of [0..LV_BEZIER_VAL_MAX] - */ -uint32_t lv_bezier3(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) +int32_t lv_cubic_bezier(int32_t x, int32_t x1, int32_t y1, int32_t x2, int32_t y2) { - uint32_t t_rem = 1024 - t; - uint32_t t_rem2 = (t_rem * t_rem) >> 10; - uint32_t t_rem3 = (t_rem2 * t_rem) >> 10; - uint32_t t2 = (t * t) >> 10; - uint32_t t3 = (t2 * t) >> 10; + int32_t ax, bx, cx, ay, by, cy; + int32_t tl, tr, t; /*t in cubic-bezier function, used for bisection */ + int32_t xs; /*x sampled on curve */ +#if CUBIC_PRECISION_BITS > 14 + int64_t d; /*slope value at specified t*/ +#else + int32_t d; +#endif - uint32_t v1 = (t_rem3 * u0) >> 10; - uint32_t v2 = (3 * t_rem2 * t * u1) >> 20; - uint32_t v3 = (3 * t_rem * t2 * u2) >> 20; - uint32_t v4 = (t3 * u3) >> 10; + if(x == 0 || x == LV_BEZIER_VAL_MAX) return x; - return v1 + v2 + v3 + v4; + /* input is always LV_BEZIER_VAL_SHIFT bit precision */ + +#if CUBIC_PRECISION_BITS != LV_BEZIER_VAL_SHIFT + x <<= CUBIC_PRECISION_BITS - LV_BEZIER_VAL_SHIFT; + x1 <<= CUBIC_PRECISION_BITS - LV_BEZIER_VAL_SHIFT; + x2 <<= CUBIC_PRECISION_BITS - LV_BEZIER_VAL_SHIFT; + y1 <<= CUBIC_PRECISION_BITS - LV_BEZIER_VAL_SHIFT; + y2 <<= CUBIC_PRECISION_BITS - LV_BEZIER_VAL_SHIFT; +#endif + + cx = 3 * x1; + bx = 3 * (x2 - x1) - cx; + ax = (1L << CUBIC_PRECISION_BITS) - cx - bx; + + cy = 3 * y1; + by = 3 * (y2 - y1) - cy; + ay = (1L << CUBIC_PRECISION_BITS) - cy - by; + + /*Try Newton's method firstly */ + t = x; /*Make a guess*/ + for(int i = 0; i < CUBIC_NEWTON_ITERATIONS; i++) { + /*Check if x on curve at t matches input x*/ + xs = do_cubic_bezier(t, ax, bx, cx) - x; + if(LV_ABS(xs) <= 1) goto found; + + /* get slop at t, d = 3 * ax * t^2 + 2 * bx + t + cx */ + d = ax; /* use 64bit operation if needed. */ + d = (3 * d * t) >> CUBIC_PRECISION_BITS; + d = ((d + 2 * bx) * t) >> CUBIC_PRECISION_BITS; + d += cx; + + if(LV_ABS(d) <= 1) break; + + d = ((int64_t)xs * (1L << CUBIC_PRECISION_BITS)) / d; + if(d == 0) break; /*Reached precision limits*/ + t -= d; + } + + /*Fallback to bisection method for reliability*/ + tl = 0, tr = 1L << CUBIC_PRECISION_BITS, t = x; + + if(t < tl) { + t = tl; + goto found; + } + + if(t > tr) { + t = tr; + goto found; + } + + while(tl < tr) { + xs = do_cubic_bezier(t, ax, bx, cx); + if(LV_ABS(xs - x) <= 1) goto found; + x > xs ? (tl = t) : (tr = t); + t = (tr - tl) / 2 + tl; + if(t == tl) break; + } + + /*Failed to find suitable t for given x, return a value anyway.*/ +found: + /*Return y at t*/ +#if CUBIC_PRECISION_BITS != LV_BEZIER_VAL_SHIFT + return do_cubic_bezier(t, ay, by, cy) >> (CUBIC_PRECISION_BITS - LV_BEZIER_VAL_SHIFT); +#else + return do_cubic_bezier(t, ay, by, cy); +#endif } -/** - * Get the square root of a number - * @param x integer which square root should be calculated - * @param q store the result here. q->i: integer part, q->f: fractional part in 1/256 unit - * @param mask optional to skip some iterations if the magnitude of the root is known. - * Set to 0x8000 by default. - * If root < 16: mask = 0x80 - * If root < 256: mask = 0x800 - * Else: mask = 0x8000 - */ -void LV_ATTRIBUTE_FAST_MEM lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask) +LV_ATTRIBUTE_FAST_MEM void lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask) { x = x << 8; /*To get 4 bit precision. (sqrt(256) = 16 = 4 bit)*/ uint32_t root = 0; uint32_t trial; - // http://ww1.microchip.com/...en/AppNotes/91040a.pdf + /*http://ww1.microchip.com/...en/AppNotes/91040a.pdf*/ do { trial = root + mask; if(trial * trial <= x) root = trial; @@ -123,94 +222,83 @@ void LV_ATTRIBUTE_FAST_MEM lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask) q->f = (root & 0xf) << 4; } -/** - * Calculate the atan2 of a vector. - * @param x - * @param y - * @return the angle in degree calculated from the given parameters in range of [0..360] - */ uint16_t lv_atan2(int x, int y) { - // Fast XY vector to integer degree algorithm - Jan 2011 www.RomanBlack.com - // Converts any XY values including 0 to a degree value that should be - // within +/- 1 degree of the accurate value without needing - // large slow trig functions like ArcTan() or ArcCos(). - // NOTE! at least one of the X or Y values must be non-zero! - // This is the full version, for all 4 quadrants and will generate - // the angle in integer degrees from 0-360. - // Any values of X and Y are usable including negative values provided - // they are between -1456 and 1456 so the 16bit multiply does not overflow. - + /** + * Fast XY vector to integer degree algorithm - Jan 2011 www.RomanBlack.com + * Converts any XY values including 0 to a degree value that should be + * within +/- 1 degree of the accurate value without needing + * large slow trig functions like ArcTan() or ArcCos(). + * NOTE! at least one of the X or Y values must be non-zero! + * This is the full version, for all 4 quadrants and will generate + * the angle in integer degrees from 0-360. + * Any values of X and Y are usable including negative values provided + * they are between -1456 and 1456 so the 16bit multiply does not overflow. + */ unsigned char negflag; unsigned char tempdegree; unsigned char comp; - unsigned int degree; // this will hold the result + unsigned int degree; /*this will hold the result*/ unsigned int ux; unsigned int uy; - // Save the sign flags then remove signs and get XY as unsigned ints + /*Save the sign flags then remove signs and get XY as unsigned ints*/ negflag = 0; if(x < 0) { - negflag += 0x01; // x flag bit - x = (0 - x); // is now + + negflag += 0x01; /*x flag bit*/ + x = (0 - x); /*is now +*/ } - ux = x; // copy to unsigned var before multiply + ux = x; /*copy to unsigned var before multiply*/ if(y < 0) { - negflag += 0x02; // y flag bit - y = (0 - y); // is now + + negflag += 0x02; /*y flag bit*/ + y = (0 - y); /*is now +*/ } - uy = y; // copy to unsigned var before multiply + uy = y; /*copy to unsigned var before multiply*/ - // 1. Calc the scaled "degrees" + /*1. Calc the scaled "degrees"*/ if(ux > uy) { - degree = (uy * 45) / ux; // degree result will be 0-45 range - negflag += 0x10; // octant flag bit + degree = (uy * 45) / ux; /*degree result will be 0-45 range*/ + negflag += 0x10; /*octant flag bit*/ } else { - degree = (ux * 45) / uy; // degree result will be 0-45 range + degree = (ux * 45) / uy; /*degree result will be 0-45 range*/ } - // 2. Compensate for the 4 degree error curve + /*2. Compensate for the 4 degree error curve*/ comp = 0; - tempdegree = degree; // use an unsigned char for speed! - if(tempdegree > 22) { // if top half of range + tempdegree = degree; /*use an unsigned char for speed!*/ + if(tempdegree > 22) { /*if top half of range*/ if(tempdegree <= 44) comp++; if(tempdegree <= 41) comp++; if(tempdegree <= 37) comp++; - if(tempdegree <= 32) comp++; // max is 4 degrees compensated + if(tempdegree <= 32) comp++; /*max is 4 degrees compensated*/ } - else { // else is lower half of range + else { /*else is lower half of range*/ if(tempdegree >= 2) comp++; if(tempdegree >= 6) comp++; if(tempdegree >= 10) comp++; - if(tempdegree >= 15) comp++; // max is 4 degrees compensated + if(tempdegree >= 15) comp++; /*max is 4 degrees compensated*/ } - degree += comp; // degree is now accurate to +/- 1 degree! + degree += comp; /*degree is now accurate to +/- 1 degree!*/ - // Invert degree if it was X>Y octant, makes 0-45 into 90-45 + /*Invert degree if it was X>Y octant, makes 0-45 into 90-45*/ if(negflag & 0x10) degree = (90 - degree); - // 3. Degree is now 0-90 range for this quadrant, - // need to invert it for whichever quadrant it was in - if(negflag & 0x02) { // if -Y - if(negflag & 0x01) // if -Y -X + /*3. Degree is now 0-90 range for this quadrant,*/ + /*need to invert it for whichever quadrant it was in*/ + if(negflag & 0x02) { /*if -Y*/ + if(negflag & 0x01) /*if -Y -X*/ degree = (180 + degree); - else // else is -Y +X + else /*else is -Y +X*/ degree = (180 - degree); } - else { // else is +Y - if(negflag & 0x01) // if +Y -X + else { /*else is +Y*/ + if(negflag & 0x01) /*if +Y -X*/ degree = (360 - degree); } return degree; } -/** - * Calculate the integer exponents. - * @param base - * @param power - * @return base raised to the power exponent - */ int64_t lv_pow(int64_t base, int8_t exp) { int64_t result = 1; @@ -224,15 +312,6 @@ int64_t lv_pow(int64_t base, int8_t exp) return result; } -/** - * Get the mapped of a number given an input and output range - * @param x integer which mapped value should be calculated - * @param min_in min input range - * @param max_in max input range - * @param min_out max output range - * @param max_out max output range - * @return the mapped number - */ int32_t lv_map(int32_t x, int32_t min_in, int32_t max_in, int32_t min_out, int32_t max_out) { if(max_in >= min_in && x >= max_in) return max_out; @@ -254,18 +333,21 @@ int32_t lv_map(int32_t x, int32_t min_in, int32_t max_in, int32_t min_out, int32 return ((x - min_in) * delta_out) / delta_in + min_out; } +void lv_rand_set_seed(uint32_t seed) +{ + rand_seed = seed; +} + uint32_t lv_rand(uint32_t min, uint32_t max) { - static uint32_t a = 0x1234ABCD; /*Seed*/ - /*Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs"*/ - uint32_t x = a; + uint32_t x = rand_seed; x ^= x << 13; x ^= x >> 17; x ^= x << 5; - a = x; + rand_seed = x; - return (a % (max - min + 1)) + min; + return (rand_seed % (max - min + 1)) + min; } /********************** diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_math.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_math.h index 771b4aa5d..904b44718 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_math.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_math.h @@ -15,15 +15,20 @@ extern "C" { *********************/ #include "../lv_conf_internal.h" #include +#include "lv_types.h" /********************* * DEFINES *********************/ -#define LV_TRIGO_SIN_MAX 32767 +#define LV_TRIGO_SIN_MAX 32768 #define LV_TRIGO_SHIFT 15 /**< >> LV_TRIGO_SHIFT to normalize*/ -#define LV_BEZIER_VAL_MAX 1024 /**< Max time in Bezier functions (not [0..1] to use integers)*/ #define LV_BEZIER_VAL_SHIFT 10 /**< log2(LV_BEZIER_VAL_MAX): used to normalize up scaled values*/ +#define LV_BEZIER_VAL_MAX (1L << LV_BEZIER_VAL_SHIFT) /**< Max time in Bezier functions (not [0..1] to use integers)*/ +#define LV_BEZIER_VAL_FLOAT(f) ((int32_t)((f) * LV_BEZIER_VAL_MAX)) /**< Convert const float number cubic-bezier values to fix-point value*/ + +/*Align up value x to align, align must be a power of two*/ +#define LV_ALIGN_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1)) /********************** * TYPEDEFS @@ -44,25 +49,41 @@ typedef struct { * @param angle * @return sinus of 'angle'. sin(-90) = -32767, sin(90) = 32767 */ -int16_t /* LV_ATTRIBUTE_FAST_MEM */ lv_trigo_sin(int16_t angle); +LV_ATTRIBUTE_FAST_MEM int32_t lv_trigo_sin(int16_t angle); -static inline int16_t LV_ATTRIBUTE_FAST_MEM lv_trigo_cos(int16_t angle) +static inline LV_ATTRIBUTE_FAST_MEM int32_t lv_trigo_cos(int16_t angle) { return lv_trigo_sin(angle + 90); } //! @endcond +/** + * Calculate the y value of cubic-bezier(x1, y1, x2, y2) function as specified x. + * @param x time in range of [0..LV_BEZIER_VAL_MAX] + * @param x1 x of control point 1 in range of [0..LV_BEZIER_VAL_MAX] + * @param y1 y of control point 1 in range of [0..LV_BEZIER_VAL_MAX] + * @param x2 x of control point 2 in range of [0..LV_BEZIER_VAL_MAX] + * @param y2 y of control point 2 in range of [0..LV_BEZIER_VAL_MAX] + * @return the value calculated + */ +int32_t lv_cubic_bezier(int32_t x, int32_t x1, int32_t y1, int32_t x2, int32_t y2); + /** * Calculate a value of a Cubic Bezier function. * @param t time in range of [0..LV_BEZIER_VAL_MAX] - * @param u0 start values in range of [0..LV_BEZIER_VAL_MAX] + * @param u0 must be 0 * @param u1 control value 1 values in range of [0..LV_BEZIER_VAL_MAX] * @param u2 control value 2 in range of [0..LV_BEZIER_VAL_MAX] - * @param u3 end values in range of [0..LV_BEZIER_VAL_MAX] + * @param u3 must be LV_BEZIER_VAL_MAX * @return the value calculated from the given parameters in range of [0..LV_BEZIER_VAL_MAX] */ -uint32_t lv_bezier3(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3); +static inline int32_t lv_bezier3(int32_t t, int32_t u0, uint32_t u1, int32_t u2, int32_t u3) +{ + LV_UNUSED(u0); + LV_UNUSED(u3); + return lv_cubic_bezier(t, 341, u1, 683, u2); +} /** * Calculate the atan2 of a vector. @@ -84,14 +105,14 @@ uint16_t lv_atan2(int x, int y); * If root < 256: mask = 0x800 * Else: mask = 0x8000 */ -void /* LV_ATTRIBUTE_FAST_MEM */ lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask); +LV_ATTRIBUTE_FAST_MEM void lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask); //! @endcond /** * Calculate the integer exponents. * @param base - * @param power + * @param exp * @return base raised to the power exponent */ int64_t lv_pow(int64_t base, int8_t exp); @@ -107,6 +128,12 @@ int64_t lv_pow(int64_t base, int8_t exp); */ int32_t lv_map(int32_t x, int32_t min_in, int32_t max_in, int32_t min_out, int32_t max_out); +/** + * Set the seed of the pseudo random number generator + * @param seed a number to initialize the random generator + */ +void lv_rand_set_seed(uint32_t seed); + /** * Get a pseudo random number in the given range * @param min the minimum value diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_mem.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_mem.c deleted file mode 100644 index 25f24c97e..000000000 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_mem.c +++ /dev/null @@ -1,566 +0,0 @@ -/** - * @file lv_mem.c - * General and portable implementation of malloc and free. - * The dynamic memory monitoring is also supported. - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_mem.h" -#include "lv_tlsf.h" -#include "lv_gc.h" -#include "lv_assert.h" -#include "lv_log.h" - -#if LV_MEM_CUSTOM != 0 - #include LV_MEM_CUSTOM_INCLUDE -#endif - -#ifdef LV_MEM_POOL_INCLUDE - #include LV_MEM_POOL_INCLUDE -#endif - -/********************* - * DEFINES - *********************/ -/*memset the allocated memories to 0xaa and freed memories to 0xbb (just for testing purposes)*/ -#ifndef LV_MEM_ADD_JUNK - #define LV_MEM_ADD_JUNK 0 -#endif - -#ifdef LV_ARCH_64 - #define MEM_UNIT uint64_t - #define ALIGN_MASK 0x7 -#else - #define MEM_UNIT uint32_t - #define ALIGN_MASK 0x3 -#endif - -#define ZERO_MEM_SENTINEL 0xa1b2c3d4 - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -#if LV_MEM_CUSTOM == 0 - static void lv_mem_walker(void * ptr, size_t size, int used, void * user); -#endif - -/********************** - * STATIC VARIABLES - **********************/ -#if LV_MEM_CUSTOM == 0 - static lv_tlsf_t tlsf; - static uint32_t cur_used; - static uint32_t max_used; -#endif - -static uint32_t zero_mem = ZERO_MEM_SENTINEL; /*Give the address of this variable if 0 byte should be allocated*/ - -/********************** - * MACROS - **********************/ -#if LV_LOG_TRACE_MEM - #define MEM_TRACE(...) LV_LOG_TRACE(__VA_ARGS__) -#else - #define MEM_TRACE(...) -#endif - -#define COPY32 *d32 = *s32; d32++; s32++; -#define COPY8 *d8 = *s8; d8++; s8++; -#define SET32(x) *d32 = x; d32++; -#define SET8(x) *d8 = x; d8++; -#define REPEAT8(expr) expr expr expr expr expr expr expr expr - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Initialize the dyn_mem module (work memory and other variables) - */ -void lv_mem_init(void) -{ -#if LV_MEM_CUSTOM == 0 - -#if LV_MEM_ADR == 0 -#ifdef LV_MEM_POOL_ALLOC - tlsf = lv_tlsf_create_with_pool((void *)LV_MEM_POOL_ALLOC(LV_MEM_SIZE), LV_MEM_SIZE); -#else - /*Allocate a large array to store the dynamically allocated data*/ - static LV_ATTRIBUTE_LARGE_RAM_ARRAY MEM_UNIT work_mem_int[LV_MEM_SIZE / sizeof(MEM_UNIT)]; - tlsf = lv_tlsf_create_with_pool((void *)work_mem_int, LV_MEM_SIZE); -#endif -#else - tlsf = lv_tlsf_create_with_pool((void *)LV_MEM_ADR, LV_MEM_SIZE); -#endif -#endif - -#if LV_MEM_ADD_JUNK - LV_LOG_WARN("LV_MEM_ADD_JUNK is enabled which makes LVGL much slower"); -#endif -} - -/** - * Clean up the memory buffer which frees all the allocated memories. - * @note It work only if `LV_MEM_CUSTOM == 0` - */ -void lv_mem_deinit(void) -{ -#if LV_MEM_CUSTOM == 0 - lv_tlsf_destroy(tlsf); - lv_mem_init(); -#endif -} - -/** - * Allocate a memory dynamically - * @param size size of the memory to allocate in bytes - * @return pointer to the allocated memory - */ -void * lv_mem_alloc(size_t size) -{ - MEM_TRACE("allocating %lu bytes", (unsigned long)size); - if(size == 0) { - MEM_TRACE("using zero_mem"); - return &zero_mem; - } - -#if LV_MEM_CUSTOM == 0 - void * alloc = lv_tlsf_malloc(tlsf, size); -#else - void * alloc = LV_MEM_CUSTOM_ALLOC(size); -#endif - - if(alloc == NULL) { - LV_LOG_INFO("couldn't allocate memory (%lu bytes)", (unsigned long)size); -#if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO - lv_mem_monitor_t mon; - lv_mem_monitor(&mon); - LV_LOG_INFO("used: %6d (%3d %%), frag: %3d %%, biggest free: %6d", - (int)(mon.total_size - mon.free_size), mon.used_pct, mon.frag_pct, - (int)mon.free_biggest_size); -#endif - } -#if LV_MEM_ADD_JUNK - else { - lv_memset(alloc, 0xaa, size); - } -#endif - - if(alloc) { -#if LV_MEM_CUSTOM == 0 - cur_used += size; - max_used = LV_MAX(cur_used, max_used); -#endif - MEM_TRACE("allocated at %p", alloc); - } - return alloc; -} - -/** - * Free an allocated data - * @param data pointer to an allocated memory - */ -void lv_mem_free(void * data) -{ - MEM_TRACE("freeing %p", data); - if(data == &zero_mem) return; - if(data == NULL) return; - -#if LV_MEM_CUSTOM == 0 -# if LV_MEM_ADD_JUNK - lv_memset(data, 0xbb, lv_tlsf_block_size(data)); -# endif - size_t size = lv_tlsf_free(tlsf, data); - if(cur_used > size) cur_used -= size; - else cur_used = 0; -#else - LV_MEM_CUSTOM_FREE(data); -#endif -} - -/** - * Reallocate a memory with a new size. The old content will be kept. - * @param data pointer to an allocated memory. - * Its content will be copied to the new memory block and freed - * @param new_size the desired new size in byte - * @return pointer to the new memory - */ -void * lv_mem_realloc(void * data_p, size_t new_size) -{ - MEM_TRACE("reallocating %p with %lu size", data_p, (unsigned long)new_size); - if(new_size == 0) { - MEM_TRACE("using zero_mem"); - lv_mem_free(data_p); - return &zero_mem; - } - - if(data_p == &zero_mem) return lv_mem_alloc(new_size); - -#if LV_MEM_CUSTOM == 0 - void * new_p = lv_tlsf_realloc(tlsf, data_p, new_size); -#else - void * new_p = LV_MEM_CUSTOM_REALLOC(data_p, new_size); -#endif - if(new_p == NULL) { - LV_LOG_ERROR("couldn't allocate memory"); - return NULL; - } - - MEM_TRACE("allocated at %p", new_p); - return new_p; -} - -lv_res_t lv_mem_test(void) -{ - if(zero_mem != ZERO_MEM_SENTINEL) { - LV_LOG_WARN("zero_mem is written"); - return LV_RES_INV; - } - -#if LV_MEM_CUSTOM == 0 - if(lv_tlsf_check(tlsf)) { - LV_LOG_WARN("failed"); - return LV_RES_INV; - } - - if(lv_tlsf_check_pool(lv_tlsf_get_pool(tlsf))) { - LV_LOG_WARN("pool failed"); - return LV_RES_INV; - } -#endif - MEM_TRACE("passed"); - return LV_RES_OK; -} - -/** - * Give information about the work memory of dynamic allocation - * @param mon_p pointer to a lv_mem_monitor_t variable, - * the result of the analysis will be stored here - */ -void lv_mem_monitor(lv_mem_monitor_t * mon_p) -{ - /*Init the data*/ - lv_memset(mon_p, 0, sizeof(lv_mem_monitor_t)); -#if LV_MEM_CUSTOM == 0 - MEM_TRACE("begin"); - - lv_tlsf_walk_pool(lv_tlsf_get_pool(tlsf), lv_mem_walker, mon_p); - - mon_p->total_size = LV_MEM_SIZE; - mon_p->used_pct = 100 - (100U * mon_p->free_size) / mon_p->total_size; - if(mon_p->free_size > 0) { - mon_p->frag_pct = mon_p->free_biggest_size * 100U / mon_p->free_size; - mon_p->frag_pct = 100 - mon_p->frag_pct; - } - else { - mon_p->frag_pct = 0; /*no fragmentation if all the RAM is used*/ - } - - mon_p->max_used = max_used; - - MEM_TRACE("finished"); -#endif -} - - -/** - * Get a temporal buffer with the given size. - * @param size the required size - */ -void * lv_mem_buf_get(uint32_t size) -{ - if(size == 0) return NULL; - - MEM_TRACE("begin, getting %d bytes", size); - - /*Try to find a free buffer with suitable size*/ - int8_t i_guess = -1; - for(uint8_t i = 0; i < LV_MEM_BUF_MAX_NUM; i++) { - if(LV_GC_ROOT(lv_mem_buf[i]).used == 0 && LV_GC_ROOT(lv_mem_buf[i]).size >= size) { - if(LV_GC_ROOT(lv_mem_buf[i]).size == size) { - LV_GC_ROOT(lv_mem_buf[i]).used = 1; - return LV_GC_ROOT(lv_mem_buf[i]).p; - } - else if(i_guess < 0) { - i_guess = i; - } - /*If size of `i` is closer to `size` prefer it*/ - else if(LV_GC_ROOT(lv_mem_buf[i]).size < LV_GC_ROOT(lv_mem_buf[i_guess]).size) { - i_guess = i; - } - } - } - - if(i_guess >= 0) { - LV_GC_ROOT(lv_mem_buf[i_guess]).used = 1; - MEM_TRACE("returning already allocated buffer (buffer id: %d, address: %p)", i_guess, - LV_GC_ROOT(lv_mem_buf[i_guess]).p); - return LV_GC_ROOT(lv_mem_buf[i_guess]).p; - } - - /*Reallocate a free buffer*/ - for(uint8_t i = 0; i < LV_MEM_BUF_MAX_NUM; i++) { - if(LV_GC_ROOT(lv_mem_buf[i]).used == 0) { - /*if this fails you probably need to increase your LV_MEM_SIZE/heap size*/ - void * buf = lv_mem_realloc(LV_GC_ROOT(lv_mem_buf[i]).p, size); - LV_ASSERT_MSG(buf != NULL, "Out of memory, can't allocate a new buffer (increase your LV_MEM_SIZE/heap size)"); - if(buf == NULL) return NULL; - - LV_GC_ROOT(lv_mem_buf[i]).used = 1; - LV_GC_ROOT(lv_mem_buf[i]).size = size; - LV_GC_ROOT(lv_mem_buf[i]).p = buf; - MEM_TRACE("allocated (buffer id: %d, address: %p)", i, LV_GC_ROOT(lv_mem_buf[i]).p); - return LV_GC_ROOT(lv_mem_buf[i]).p; - } - } - - LV_LOG_ERROR("no more buffers. (increase LV_MEM_BUF_MAX_NUM)"); - LV_ASSERT_MSG(false, "No more buffers. Increase LV_MEM_BUF_MAX_NUM."); - return NULL; -} - -/** - * Release a memory buffer - * @param p buffer to release - */ -void lv_mem_buf_release(void * p) -{ - MEM_TRACE("begin (address: %p)", p); - - for(uint8_t i = 0; i < LV_MEM_BUF_MAX_NUM; i++) { - if(LV_GC_ROOT(lv_mem_buf[i]).p == p) { - LV_GC_ROOT(lv_mem_buf[i]).used = 0; - return; - } - } - - LV_LOG_ERROR("p is not a known buffer"); -} - -/** - * Free all memory buffers - */ -void lv_mem_buf_free_all(void) -{ - for(uint8_t i = 0; i < LV_MEM_BUF_MAX_NUM; i++) { - if(LV_GC_ROOT(lv_mem_buf[i]).p) { - lv_mem_free(LV_GC_ROOT(lv_mem_buf[i]).p); - LV_GC_ROOT(lv_mem_buf[i]).p = NULL; - LV_GC_ROOT(lv_mem_buf[i]).used = 0; - LV_GC_ROOT(lv_mem_buf[i]).size = 0; - } - } -} - -#if LV_MEMCPY_MEMSET_STD == 0 -/** - * Same as `memcpy` but optimized for 4 byte operation. - * @param dst pointer to the destination buffer - * @param src pointer to the source buffer - * @param len number of byte to copy - */ -void * LV_ATTRIBUTE_FAST_MEM lv_memcpy(void * dst, const void * src, size_t len) -{ - uint8_t * d8 = dst; - const uint8_t * s8 = src; - - lv_uintptr_t d_align = (lv_uintptr_t)d8 & ALIGN_MASK; - lv_uintptr_t s_align = (lv_uintptr_t)s8 & ALIGN_MASK; - - /*Byte copy for unaligned memories*/ - if(s_align != d_align) { - while(len > 32) { - REPEAT8(COPY8); - REPEAT8(COPY8); - REPEAT8(COPY8); - REPEAT8(COPY8); - len -= 32; - } - while(len) { - COPY8 - len--; - } - return dst; - } - - /*Make the memories aligned*/ - if(d_align) { - d_align = ALIGN_MASK + 1 - d_align; - while(d_align && len) { - COPY8; - d_align--; - len--; - } - } - - uint32_t * d32 = (uint32_t *)d8; - const uint32_t * s32 = (uint32_t *)s8; - while(len > 32) { - REPEAT8(COPY32) - len -= 32; - } - - while(len > 4) { - COPY32; - len -= 4; - } - - d8 = (uint8_t *)d32; - s8 = (const uint8_t *)s32; - while(len) { - COPY8 - len--; - } - - return dst; -} - -/** - * Same as `memset` but optimized for 4 byte operation. - * @param dst pointer to the destination buffer - * @param v value to set [0..255] - * @param len number of byte to set - */ -void LV_ATTRIBUTE_FAST_MEM lv_memset(void * dst, uint8_t v, size_t len) -{ - - uint8_t * d8 = (uint8_t *)dst; - - uintptr_t d_align = (lv_uintptr_t) d8 & ALIGN_MASK; - - /*Make the address aligned*/ - if(d_align) { - d_align = ALIGN_MASK + 1 - d_align; - while(d_align && len) { - SET8(v); - len--; - d_align--; - } - } - - uint32_t v32 = (uint32_t)v + ((uint32_t)v << 8) + ((uint32_t)v << 16) + ((uint32_t)v << 24); - - uint32_t * d32 = (uint32_t *)d8; - - while(len > 32) { - REPEAT8(SET32(v32)); - len -= 32; - } - - while(len > 4) { - SET32(v32); - len -= 4; - } - - d8 = (uint8_t *)d32; - while(len) { - SET8(v); - len--; - } -} - -/** - * Same as `memset(dst, 0x00, len)` but optimized for 4 byte operation. - * @param dst pointer to the destination buffer - * @param len number of byte to set - */ -void LV_ATTRIBUTE_FAST_MEM lv_memset_00(void * dst, size_t len) -{ - uint8_t * d8 = (uint8_t *)dst; - uintptr_t d_align = (lv_uintptr_t) d8 & ALIGN_MASK; - - /*Make the address aligned*/ - if(d_align) { - d_align = ALIGN_MASK + 1 - d_align; - while(d_align && len) { - SET8(0); - len--; - d_align--; - } - } - - uint32_t * d32 = (uint32_t *)d8; - while(len > 32) { - REPEAT8(SET32(0)); - len -= 32; - } - - while(len > 4) { - SET32(0); - len -= 4; - } - - d8 = (uint8_t *)d32; - while(len) { - SET8(0); - len--; - } -} - -/** - * Same as `memset(dst, 0xFF, len)` but optimized for 4 byte operation. - * @param dst pointer to the destination buffer - * @param len number of byte to set - */ -void LV_ATTRIBUTE_FAST_MEM lv_memset_ff(void * dst, size_t len) -{ - uint8_t * d8 = (uint8_t *)dst; - uintptr_t d_align = (lv_uintptr_t) d8 & ALIGN_MASK; - - /*Make the address aligned*/ - if(d_align) { - d_align = ALIGN_MASK + 1 - d_align; - while(d_align && len) { - SET8(0xFF); - len--; - d_align--; - } - } - - uint32_t * d32 = (uint32_t *)d8; - while(len > 32) { - REPEAT8(SET32(0xFFFFFFFF)); - len -= 32; - } - - while(len > 4) { - SET32(0xFFFFFFFF); - len -= 4; - } - - d8 = (uint8_t *)d32; - while(len) { - SET8(0xFF); - len--; - } -} - -#endif /*LV_MEMCPY_MEMSET_STD*/ - -/********************** - * STATIC FUNCTIONS - **********************/ - -#if LV_MEM_CUSTOM == 0 -static void lv_mem_walker(void * ptr, size_t size, int used, void * user) -{ - LV_UNUSED(ptr); - - lv_mem_monitor_t * mon_p = user; - if(used) { - mon_p->used_cnt++; - } - else { - mon_p->free_cnt++; - mon_p->free_size += size; - if(size > mon_p->free_biggest_size) - mon_p->free_biggest_size = size; - } -} -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_mem.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_mem.h deleted file mode 100644 index 9be942524..000000000 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_mem.h +++ /dev/null @@ -1,243 +0,0 @@ -/** - * @file lv_mem.h - * - */ - -#ifndef LV_MEM_H -#define LV_MEM_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#include -#include -#include - -#include "lv_types.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/** - * Heap information structure. - */ -typedef struct { - uint32_t total_size; /**< Total heap size*/ - uint32_t free_cnt; - uint32_t free_size; /**< Size of available memory*/ - uint32_t free_biggest_size; - uint32_t used_cnt; - uint32_t max_used; /**< Max size of Heap memory used*/ - uint8_t used_pct; /**< Percentage used*/ - uint8_t frag_pct; /**< Amount of fragmentation*/ -} lv_mem_monitor_t; - -typedef struct { - void * p; - uint16_t size; - uint8_t used : 1; -} lv_mem_buf_t; - -typedef lv_mem_buf_t lv_mem_buf_arr_t[LV_MEM_BUF_MAX_NUM]; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Initialize the dyn_mem module (work memory and other variables) - */ -void lv_mem_init(void); - -/** - * Clean up the memory buffer which frees all the allocated memories. - * @note It work only if `LV_MEM_CUSTOM == 0` - */ -void lv_mem_deinit(void); - -/** - * Allocate a memory dynamically - * @param size size of the memory to allocate in bytes - * @return pointer to the allocated memory - */ -void * lv_mem_alloc(size_t size); - -/** - * Free an allocated data - * @param data pointer to an allocated memory - */ -void lv_mem_free(void * data); - -/** - * Reallocate a memory with a new size. The old content will be kept. - * @param data pointer to an allocated memory. - * Its content will be copied to the new memory block and freed - * @param new_size the desired new size in byte - * @return pointer to the new memory, NULL on failure - */ -void * lv_mem_realloc(void * data_p, size_t new_size); - -/** - * - * @return - */ -lv_res_t lv_mem_test(void); - -/** - * Give information about the work memory of dynamic allocation - * @param mon_p pointer to a lv_mem_monitor_t variable, - * the result of the analysis will be stored here - */ -void lv_mem_monitor(lv_mem_monitor_t * mon_p); - - -/** - * Get a temporal buffer with the given size. - * @param size the required size - */ -void * lv_mem_buf_get(uint32_t size); - -/** - * Release a memory buffer - * @param p buffer to release - */ -void lv_mem_buf_release(void * p); - -/** - * Free all memory buffers - */ -void lv_mem_buf_free_all(void); - -//! @cond Doxygen_Suppress - -#if LV_MEMCPY_MEMSET_STD - -/** - * Wrapper for the standard memcpy - * @param dst pointer to the destination buffer - * @param src pointer to the source buffer - * @param len number of byte to copy - */ -static inline void * lv_memcpy(void * dst, const void * src, size_t len) -{ - return memcpy(dst, src, len); -} - -/** - * Wrapper for the standard memcpy - * @param dst pointer to the destination buffer - * @param src pointer to the source buffer - * @param len number of byte to copy - */ -static inline void * lv_memcpy_small(void * dst, const void * src, size_t len) -{ - return memcpy(dst, src, len); -} - -/** - * Wrapper for the standard memset - * @param dst pointer to the destination buffer - * @param v value to set [0..255] - * @param len number of byte to set - */ -static inline void lv_memset(void * dst, uint8_t v, size_t len) -{ - memset(dst, v, len); -} - -/** - * Wrapper for the standard memset with fixed 0x00 value - * @param dst pointer to the destination buffer - * @param len number of byte to set - */ -static inline void lv_memset_00(void * dst, size_t len) -{ - memset(dst, 0x00, len); -} - -/** - * Wrapper for the standard memset with fixed 0xFF value - * @param dst pointer to the destination buffer - * @param len number of byte to set - */ -static inline void lv_memset_ff(void * dst, size_t len) -{ - memset(dst, 0xFF, len); -} - -#else -/** - * Same as `memcpy` but optimized for 4 byte operation. - * @param dst pointer to the destination buffer - * @param src pointer to the source buffer - * @param len number of byte to copy - */ -void * /* LV_ATTRIBUTE_FAST_MEM */ lv_memcpy(void * dst, const void * src, size_t len); - -/** - * Same as `memcpy` but optimized to copy only a few bytes. - * @param dst pointer to the destination buffer - * @param src pointer to the source buffer - * @param len number of byte to copy - */ -static inline void * LV_ATTRIBUTE_FAST_MEM lv_memcpy_small(void * dst, const void * src, size_t len) -{ - uint8_t * d8 = (uint8_t *)dst; - const uint8_t * s8 = (const uint8_t *)src; - - while(len) { - *d8 = *s8; - d8++; - s8++; - len--; - } - - return dst; -} - -/** - * Same as `memset` but optimized for 4 byte operation. - * @param dst pointer to the destination buffer - * @param v value to set [0..255] - * @param len number of byte to set - */ -void /* LV_ATTRIBUTE_FAST_MEM */ lv_memset(void * dst, uint8_t v, size_t len); - -/** - * Same as `memset(dst, 0x00, len)` but optimized for 4 byte operation. - * @param dst pointer to the destination buffer - * @param len number of byte to set - */ -void /* LV_ATTRIBUTE_FAST_MEM */ lv_memset_00(void * dst, size_t len); - -/** - * Same as `memset(dst, 0xFF, len)` but optimized for 4 byte operation. - * @param dst pointer to the destination buffer - * @param len number of byte to set - */ -void /* LV_ATTRIBUTE_FAST_MEM */ lv_memset_ff(void * dst, size_t len); - -//! @endcond - -#endif - -/********************** - * MACROS - **********************/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_MEM_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_misc.mk b/lib/libesp32_lvgl/lvgl/src/misc/lv_misc.mk deleted file mode 100644 index 1dfd4eec9..000000000 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_misc.mk +++ /dev/null @@ -1,26 +0,0 @@ -CSRCS += lv_anim.c -CSRCS += lv_anim_timeline.c -CSRCS += lv_area.c -CSRCS += lv_async.c -CSRCS += lv_bidi.c -CSRCS += lv_color.c -CSRCS += lv_fs.c -CSRCS += lv_gc.c -CSRCS += lv_ll.c -CSRCS += lv_log.c -CSRCS += lv_lru.c -CSRCS += lv_math.c -CSRCS += lv_mem.c -CSRCS += lv_printf.c -CSRCS += lv_style.c -CSRCS += lv_style_gen.c -CSRCS += lv_timer.c -CSRCS += lv_tlsf.c -CSRCS += lv_txt.c -CSRCS += lv_txt_ap.c -CSRCS += lv_utils.c - -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/misc -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/misc - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/misc" diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_palette.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_palette.c new file mode 100644 index 000000000..31aa66cf9 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_palette.c @@ -0,0 +1,130 @@ +/** + * @file lv_palette.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_palette.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_color_t lv_palette_main(lv_palette_t p) +{ + static const lv_color_t colors[] = { + LV_COLOR_MAKE(0xF4, 0x43, 0x36), LV_COLOR_MAKE(0xE9, 0x1E, 0x63), LV_COLOR_MAKE(0x9C, 0x27, 0xB0), LV_COLOR_MAKE(0x67, 0x3A, 0xB7), + LV_COLOR_MAKE(0x3F, 0x51, 0xB5), LV_COLOR_MAKE(0x21, 0x96, 0xF3), LV_COLOR_MAKE(0x03, 0xA9, 0xF4), LV_COLOR_MAKE(0x00, 0xBC, 0xD4), + LV_COLOR_MAKE(0x00, 0x96, 0x88), LV_COLOR_MAKE(0x4C, 0xAF, 0x50), LV_COLOR_MAKE(0x8B, 0xC3, 0x4A), LV_COLOR_MAKE(0xCD, 0xDC, 0x39), + LV_COLOR_MAKE(0xFF, 0xEB, 0x3B), LV_COLOR_MAKE(0xFF, 0xC1, 0x07), LV_COLOR_MAKE(0xFF, 0x98, 0x00), LV_COLOR_MAKE(0xFF, 0x57, 0x22), + LV_COLOR_MAKE(0x79, 0x55, 0x48), LV_COLOR_MAKE(0x60, 0x7D, 0x8B), LV_COLOR_MAKE(0x9E, 0x9E, 0x9E) + }; + + if(p >= _LV_PALETTE_LAST) { + LV_LOG_WARN("Invalid palette: %d", p); + return lv_color_black(); + } + + return colors[p]; + +} + +lv_color_t lv_palette_lighten(lv_palette_t p, uint8_t lvl) +{ + static const lv_color_t colors[][5] = { + {LV_COLOR_MAKE(0xEF, 0x53, 0x50), LV_COLOR_MAKE(0xE5, 0x73, 0x73), LV_COLOR_MAKE(0xEF, 0x9A, 0x9A), LV_COLOR_MAKE(0xFF, 0xCD, 0xD2), LV_COLOR_MAKE(0xFF, 0xEB, 0xEE)}, + {LV_COLOR_MAKE(0xEC, 0x40, 0x7A), LV_COLOR_MAKE(0xF0, 0x62, 0x92), LV_COLOR_MAKE(0xF4, 0x8F, 0xB1), LV_COLOR_MAKE(0xF8, 0xBB, 0xD0), LV_COLOR_MAKE(0xFC, 0xE4, 0xEC)}, + {LV_COLOR_MAKE(0xAB, 0x47, 0xBC), LV_COLOR_MAKE(0xBA, 0x68, 0xC8), LV_COLOR_MAKE(0xCE, 0x93, 0xD8), LV_COLOR_MAKE(0xE1, 0xBE, 0xE7), LV_COLOR_MAKE(0xF3, 0xE5, 0xF5)}, + {LV_COLOR_MAKE(0x7E, 0x57, 0xC2), LV_COLOR_MAKE(0x95, 0x75, 0xCD), LV_COLOR_MAKE(0xB3, 0x9D, 0xDB), LV_COLOR_MAKE(0xD1, 0xC4, 0xE9), LV_COLOR_MAKE(0xED, 0xE7, 0xF6)}, + {LV_COLOR_MAKE(0x5C, 0x6B, 0xC0), LV_COLOR_MAKE(0x79, 0x86, 0xCB), LV_COLOR_MAKE(0x9F, 0xA8, 0xDA), LV_COLOR_MAKE(0xC5, 0xCA, 0xE9), LV_COLOR_MAKE(0xE8, 0xEA, 0xF6)}, + {LV_COLOR_MAKE(0x42, 0xA5, 0xF5), LV_COLOR_MAKE(0x64, 0xB5, 0xF6), LV_COLOR_MAKE(0x90, 0xCA, 0xF9), LV_COLOR_MAKE(0xBB, 0xDE, 0xFB), LV_COLOR_MAKE(0xE3, 0xF2, 0xFD)}, + {LV_COLOR_MAKE(0x29, 0xB6, 0xF6), LV_COLOR_MAKE(0x4F, 0xC3, 0xF7), LV_COLOR_MAKE(0x81, 0xD4, 0xFA), LV_COLOR_MAKE(0xB3, 0xE5, 0xFC), LV_COLOR_MAKE(0xE1, 0xF5, 0xFE)}, + {LV_COLOR_MAKE(0x26, 0xC6, 0xDA), LV_COLOR_MAKE(0x4D, 0xD0, 0xE1), LV_COLOR_MAKE(0x80, 0xDE, 0xEA), LV_COLOR_MAKE(0xB2, 0xEB, 0xF2), LV_COLOR_MAKE(0xE0, 0xF7, 0xFA)}, + {LV_COLOR_MAKE(0x26, 0xA6, 0x9A), LV_COLOR_MAKE(0x4D, 0xB6, 0xAC), LV_COLOR_MAKE(0x80, 0xCB, 0xC4), LV_COLOR_MAKE(0xB2, 0xDF, 0xDB), LV_COLOR_MAKE(0xE0, 0xF2, 0xF1)}, + {LV_COLOR_MAKE(0x66, 0xBB, 0x6A), LV_COLOR_MAKE(0x81, 0xC7, 0x84), LV_COLOR_MAKE(0xA5, 0xD6, 0xA7), LV_COLOR_MAKE(0xC8, 0xE6, 0xC9), LV_COLOR_MAKE(0xE8, 0xF5, 0xE9)}, + {LV_COLOR_MAKE(0x9C, 0xCC, 0x65), LV_COLOR_MAKE(0xAE, 0xD5, 0x81), LV_COLOR_MAKE(0xC5, 0xE1, 0xA5), LV_COLOR_MAKE(0xDC, 0xED, 0xC8), LV_COLOR_MAKE(0xF1, 0xF8, 0xE9)}, + {LV_COLOR_MAKE(0xD4, 0xE1, 0x57), LV_COLOR_MAKE(0xDC, 0xE7, 0x75), LV_COLOR_MAKE(0xE6, 0xEE, 0x9C), LV_COLOR_MAKE(0xF0, 0xF4, 0xC3), LV_COLOR_MAKE(0xF9, 0xFB, 0xE7)}, + {LV_COLOR_MAKE(0xFF, 0xEE, 0x58), LV_COLOR_MAKE(0xFF, 0xF1, 0x76), LV_COLOR_MAKE(0xFF, 0xF5, 0x9D), LV_COLOR_MAKE(0xFF, 0xF9, 0xC4), LV_COLOR_MAKE(0xFF, 0xFD, 0xE7)}, + {LV_COLOR_MAKE(0xFF, 0xCA, 0x28), LV_COLOR_MAKE(0xFF, 0xD5, 0x4F), LV_COLOR_MAKE(0xFF, 0xE0, 0x82), LV_COLOR_MAKE(0xFF, 0xEC, 0xB3), LV_COLOR_MAKE(0xFF, 0xF8, 0xE1)}, + {LV_COLOR_MAKE(0xFF, 0xA7, 0x26), LV_COLOR_MAKE(0xFF, 0xB7, 0x4D), LV_COLOR_MAKE(0xFF, 0xCC, 0x80), LV_COLOR_MAKE(0xFF, 0xE0, 0xB2), LV_COLOR_MAKE(0xFF, 0xF3, 0xE0)}, + {LV_COLOR_MAKE(0xFF, 0x70, 0x43), LV_COLOR_MAKE(0xFF, 0x8A, 0x65), LV_COLOR_MAKE(0xFF, 0xAB, 0x91), LV_COLOR_MAKE(0xFF, 0xCC, 0xBC), LV_COLOR_MAKE(0xFB, 0xE9, 0xE7)}, + {LV_COLOR_MAKE(0x8D, 0x6E, 0x63), LV_COLOR_MAKE(0xA1, 0x88, 0x7F), LV_COLOR_MAKE(0xBC, 0xAA, 0xA4), LV_COLOR_MAKE(0xD7, 0xCC, 0xC8), LV_COLOR_MAKE(0xEF, 0xEB, 0xE9)}, + {LV_COLOR_MAKE(0x78, 0x90, 0x9C), LV_COLOR_MAKE(0x90, 0xA4, 0xAE), LV_COLOR_MAKE(0xB0, 0xBE, 0xC5), LV_COLOR_MAKE(0xCF, 0xD8, 0xDC), LV_COLOR_MAKE(0xEC, 0xEF, 0xF1)}, + {LV_COLOR_MAKE(0xBD, 0xBD, 0xBD), LV_COLOR_MAKE(0xE0, 0xE0, 0xE0), LV_COLOR_MAKE(0xEE, 0xEE, 0xEE), LV_COLOR_MAKE(0xF5, 0xF5, 0xF5), LV_COLOR_MAKE(0xFA, 0xFA, 0xFA)}, + }; + + if(p >= _LV_PALETTE_LAST) { + LV_LOG_WARN("Invalid palette: %d", p); + return lv_color_black(); + } + + if(lvl == 0 || lvl > 5) { + LV_LOG_WARN("Invalid level: %d. Must be 1..5", lvl); + return lv_color_black(); + } + + lvl--; + + return colors[p][lvl]; +} + +lv_color_t lv_palette_darken(lv_palette_t p, uint8_t lvl) +{ + static const lv_color_t colors[][4] = { + {LV_COLOR_MAKE(0xE5, 0x39, 0x35), LV_COLOR_MAKE(0xD3, 0x2F, 0x2F), LV_COLOR_MAKE(0xC6, 0x28, 0x28), LV_COLOR_MAKE(0xB7, 0x1C, 0x1C)}, + {LV_COLOR_MAKE(0xD8, 0x1B, 0x60), LV_COLOR_MAKE(0xC2, 0x18, 0x5B), LV_COLOR_MAKE(0xAD, 0x14, 0x57), LV_COLOR_MAKE(0x88, 0x0E, 0x4F)}, + {LV_COLOR_MAKE(0x8E, 0x24, 0xAA), LV_COLOR_MAKE(0x7B, 0x1F, 0xA2), LV_COLOR_MAKE(0x6A, 0x1B, 0x9A), LV_COLOR_MAKE(0x4A, 0x14, 0x8C)}, + {LV_COLOR_MAKE(0x5E, 0x35, 0xB1), LV_COLOR_MAKE(0x51, 0x2D, 0xA8), LV_COLOR_MAKE(0x45, 0x27, 0xA0), LV_COLOR_MAKE(0x31, 0x1B, 0x92)}, + {LV_COLOR_MAKE(0x39, 0x49, 0xAB), LV_COLOR_MAKE(0x30, 0x3F, 0x9F), LV_COLOR_MAKE(0x28, 0x35, 0x93), LV_COLOR_MAKE(0x1A, 0x23, 0x7E)}, + {LV_COLOR_MAKE(0x1E, 0x88, 0xE5), LV_COLOR_MAKE(0x19, 0x76, 0xD2), LV_COLOR_MAKE(0x15, 0x65, 0xC0), LV_COLOR_MAKE(0x0D, 0x47, 0xA1)}, + {LV_COLOR_MAKE(0x03, 0x9B, 0xE5), LV_COLOR_MAKE(0x02, 0x88, 0xD1), LV_COLOR_MAKE(0x02, 0x77, 0xBD), LV_COLOR_MAKE(0x01, 0x57, 0x9B)}, + {LV_COLOR_MAKE(0x00, 0xAC, 0xC1), LV_COLOR_MAKE(0x00, 0x97, 0xA7), LV_COLOR_MAKE(0x00, 0x83, 0x8F), LV_COLOR_MAKE(0x00, 0x60, 0x64)}, + {LV_COLOR_MAKE(0x00, 0x89, 0x7B), LV_COLOR_MAKE(0x00, 0x79, 0x6B), LV_COLOR_MAKE(0x00, 0x69, 0x5C), LV_COLOR_MAKE(0x00, 0x4D, 0x40)}, + {LV_COLOR_MAKE(0x43, 0xA0, 0x47), LV_COLOR_MAKE(0x38, 0x8E, 0x3C), LV_COLOR_MAKE(0x2E, 0x7D, 0x32), LV_COLOR_MAKE(0x1B, 0x5E, 0x20)}, + {LV_COLOR_MAKE(0x7C, 0xB3, 0x42), LV_COLOR_MAKE(0x68, 0x9F, 0x38), LV_COLOR_MAKE(0x55, 0x8B, 0x2F), LV_COLOR_MAKE(0x33, 0x69, 0x1E)}, + {LV_COLOR_MAKE(0xC0, 0xCA, 0x33), LV_COLOR_MAKE(0xAF, 0xB4, 0x2B), LV_COLOR_MAKE(0x9E, 0x9D, 0x24), LV_COLOR_MAKE(0x82, 0x77, 0x17)}, + {LV_COLOR_MAKE(0xFD, 0xD8, 0x35), LV_COLOR_MAKE(0xFB, 0xC0, 0x2D), LV_COLOR_MAKE(0xF9, 0xA8, 0x25), LV_COLOR_MAKE(0xF5, 0x7F, 0x17)}, + {LV_COLOR_MAKE(0xFF, 0xB3, 0x00), LV_COLOR_MAKE(0xFF, 0xA0, 0x00), LV_COLOR_MAKE(0xFF, 0x8F, 0x00), LV_COLOR_MAKE(0xFF, 0x6F, 0x00)}, + {LV_COLOR_MAKE(0xFB, 0x8C, 0x00), LV_COLOR_MAKE(0xF5, 0x7C, 0x00), LV_COLOR_MAKE(0xEF, 0x6C, 0x00), LV_COLOR_MAKE(0xE6, 0x51, 0x00)}, + {LV_COLOR_MAKE(0xF4, 0x51, 0x1E), LV_COLOR_MAKE(0xE6, 0x4A, 0x19), LV_COLOR_MAKE(0xD8, 0x43, 0x15), LV_COLOR_MAKE(0xBF, 0x36, 0x0C)}, + {LV_COLOR_MAKE(0x6D, 0x4C, 0x41), LV_COLOR_MAKE(0x5D, 0x40, 0x37), LV_COLOR_MAKE(0x4E, 0x34, 0x2E), LV_COLOR_MAKE(0x3E, 0x27, 0x23)}, + {LV_COLOR_MAKE(0x54, 0x6E, 0x7A), LV_COLOR_MAKE(0x45, 0x5A, 0x64), LV_COLOR_MAKE(0x37, 0x47, 0x4F), LV_COLOR_MAKE(0x26, 0x32, 0x38)}, + {LV_COLOR_MAKE(0x75, 0x75, 0x75), LV_COLOR_MAKE(0x61, 0x61, 0x61), LV_COLOR_MAKE(0x42, 0x42, 0x42), LV_COLOR_MAKE(0x21, 0x21, 0x21)}, + }; + + if(p >= _LV_PALETTE_LAST) { + LV_LOG_WARN("Invalid palette: %d", p); + return lv_color_black(); + } + + if(lvl == 0 || lvl > 4) { + LV_LOG_WARN("Invalid level: %d. Must be 1..4", lvl); + return lv_color_black(); + } + + lvl--; + + return colors[p][lvl]; +} diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_palette.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_palette.h new file mode 100644 index 000000000..fedac9eee --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_palette.h @@ -0,0 +1,69 @@ +/** + * @file lv_palette.h + * + */ + +#ifndef LV_PALETTE_H +#define LV_PALETTE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_color.h" +#include +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef enum { + LV_PALETTE_RED, + LV_PALETTE_PINK, + LV_PALETTE_PURPLE, + LV_PALETTE_DEEP_PURPLE, + LV_PALETTE_INDIGO, + LV_PALETTE_BLUE, + LV_PALETTE_LIGHT_BLUE, + LV_PALETTE_CYAN, + LV_PALETTE_TEAL, + LV_PALETTE_GREEN, + LV_PALETTE_LIGHT_GREEN, + LV_PALETTE_LIME, + LV_PALETTE_YELLOW, + LV_PALETTE_AMBER, + LV_PALETTE_ORANGE, + LV_PALETTE_DEEP_ORANGE, + LV_PALETTE_BROWN, + LV_PALETTE_BLUE_GREY, + LV_PALETTE_GREY, + _LV_PALETTE_LAST, + LV_PALETTE_NONE = 0xff, +} lv_palette_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/*Source: https://vuetifyjs.com/en/styles/colors/#material-colors*/ + +lv_color_t lv_palette_main(lv_palette_t p); +lv_color_t lv_palette_lighten(lv_palette_t p, uint8_t lvl); +lv_color_t lv_palette_darken(lv_palette_t p, uint8_t lvl); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_PALETTE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_printf.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_printf.h deleted file mode 100644 index 09563db6e..000000000 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_printf.h +++ /dev/null @@ -1,98 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// \author (c) Marco Paland (info@paland.com) -// 2014-2019, PALANDesign Hannover, Germany -// -// \license The MIT License (MIT) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on -// embedded systems with a very limited resources. -// Use this instead of bloated standard/newlib printf. -// These routines are thread safe and reentrant. -// -/////////////////////////////////////////////////////////////////////////////// - -/*Original repository: https://github.com/mpaland/printf*/ - -#ifndef _LV_PRINTF_H_ -#define _LV_PRINTF_H_ - -#if defined(__has_include) - #if __has_include() - #include - /* platform-specific printf format for int32_t, usually "d" or "ld" */ - #define LV_PRId32 PRId32 - #define LV_PRIu32 PRIu32 - #define LV_PRIx32 PRIx32 - #define LV_PRIX32 PRIX32 - #else - #define LV_PRId32 "d" - #define LV_PRIu32 "u" - #define LV_PRIx32 "x" - #define LV_PRIX32 "X" - #endif -#else - /* hope this is correct for ports without __has_include or without inttypes.h */ - #define LV_PRId32 "d" - #define LV_PRIu32 "u" - #define LV_PRIx32 "x" - #define LV_PRIX32 "X" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#include "../lv_conf_internal.h" - -#if LV_SPRINTF_CUSTOM == 0 - -#include -#include - -#include "lv_types.h" - -typedef struct { - const char * fmt; - va_list * va; -} lv_vaformat_t; - -/** - * Tiny snprintf/vsnprintf implementation - * \param buffer A pointer to the buffer where to store the formatted string - * \param count The maximum number of characters to store in the buffer, including a terminating null character - * \param format A string that specifies the format of the output - * \param va A value identifying a variable arguments list - * \return The number of characters that COULD have been written into the buffer, not counting the terminating - * null character. A value equal or larger than count indicates truncation. Only when the returned value - * is non-negative and less than count, the string has been completely written. - */ -int lv_snprintf(char * buffer, size_t count, const char * format, ...) LV_FORMAT_ATTRIBUTE(3, 4); -int lv_vsnprintf(char * buffer, size_t count, const char * format, va_list va) LV_FORMAT_ATTRIBUTE(3, 0); - -#else -#include LV_SPRINTF_INCLUDE -#endif - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif // _LV_PRINTF_H_ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_profiler.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_profiler.h new file mode 100644 index 000000000..47d5bd243 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_profiler.h @@ -0,0 +1,52 @@ +/** + * @file lv_profiler.h + * + */ + +#ifndef LV_PROFILER_H +#define LV_PROFILER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../lv_conf_internal.h" + +#if LV_USE_PROFILER + +#include LV_PROFILER_INCLUDE + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#else + +#define LV_PROFILER_BEGIN +#define LV_PROFILER_END +#define LV_PROFILER_BEGIN_TAG(tag) LV_UNUSED(tag) +#define LV_PROFILER_END_TAG(tag) LV_UNUSED(tag) + +#endif /*LV_USE_PROFILER*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_PROFILER_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_profiler_builtin.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_profiler_builtin.c new file mode 100644 index 000000000..ca6d2f2cc --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_profiler_builtin.c @@ -0,0 +1,168 @@ +/** + * @file lv_profiler_builtin.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_profiler_builtin.h" +#include "../lvgl.h" +#include "../core/lv_global.h" + +/********************* + * DEFINES + *********************/ + +#if LV_USE_PROFILER && LV_USE_PROFILER_BUILTIN + +#define profiler_ctx LV_GLOBAL_DEFAULT()->profiler_context + +#define LV_PROFILER_STR_MAX_LEN 128 +#define LV_PROFILER_TICK_PER_SEC_MAX 1000000 + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void default_flush_cb(const char * buf); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_profiler_builtin_config_init(lv_profiler_builtin_config_t * config) +{ + LV_ASSERT_NULL(config); + lv_memzero(config, sizeof(lv_profiler_builtin_config_t)); + config->buf_size = LV_PROFILER_BUILTIN_BUF_SIZE; + config->tick_per_sec = 1000; + config->tick_get_cb = lv_tick_get; + config->flush_cb = default_flush_cb; +} + +void lv_profiler_builtin_init(const lv_profiler_builtin_config_t * config) +{ + LV_ASSERT_NULL(config); + LV_ASSERT_NULL(config->tick_get_cb); + + uint32_t num = config->buf_size / sizeof(lv_profiler_builtin_item_t); + if(num == 0) { + LV_LOG_WARN("buf_size must > %d", (int)sizeof(lv_profiler_builtin_item_t)); + return; + } + + if(config->tick_per_sec == 0 || config->tick_per_sec > LV_PROFILER_TICK_PER_SEC_MAX) { + LV_LOG_WARN("tick_per_sec range must be between 1~%d", LV_PROFILER_TICK_PER_SEC_MAX); + return; + } + + /*Free the old item_arr memory*/ + if(profiler_ctx.item_arr != NULL) { + lv_profiler_builtin_uninit(); + } + + lv_memzero(&profiler_ctx, sizeof(profiler_ctx)); + profiler_ctx.item_arr = lv_malloc(num * sizeof(lv_profiler_builtin_item_t)); + LV_ASSERT_MALLOC(profiler_ctx.item_arr); + + if(profiler_ctx.item_arr == NULL) { + LV_LOG_ERROR("malloc failed for item_arr"); + return; + } + + profiler_ctx.item_num = num; + profiler_ctx.config = *config; + + if(profiler_ctx.config.flush_cb) { + /* add profiler header for perfetto */ + profiler_ctx.config.flush_cb("# tracer: nop\n"); + profiler_ctx.config.flush_cb("#\n"); + } + + lv_profiler_builtin_set_enable(true); + + LV_LOG_INFO("init OK, item_num = %d", (int)num); +} + +void lv_profiler_builtin_uninit(void) +{ + LV_ASSERT_NULL(profiler_ctx.item_arr); + lv_free(profiler_ctx.item_arr); + lv_memzero(&profiler_ctx, sizeof(profiler_ctx)); +} + +void lv_profiler_builtin_set_enable(bool enable) +{ + profiler_ctx.enable = enable; +} + +void lv_profiler_builtin_flush(void) +{ + LV_ASSERT_NULL(profiler_ctx.item_arr); + if(!profiler_ctx.config.flush_cb) { + LV_LOG_WARN("flush_cb is not registered"); + return; + } + + uint32_t cur = 0; + char buf[LV_PROFILER_STR_MAX_LEN]; + uint32_t tick_per_sec = profiler_ctx.config.tick_per_sec; + while(cur < profiler_ctx.cur_index) { + lv_profiler_builtin_item_t * item = &profiler_ctx.item_arr[cur++]; + uint32_t sec = item->tick / tick_per_sec; + uint32_t usec = (item->tick % tick_per_sec) * (LV_PROFILER_TICK_PER_SEC_MAX / tick_per_sec); + lv_snprintf(buf, sizeof(buf), + " LVGL-1 [0] %" LV_PRIu32 ".%06" LV_PRIu32 ": tracing_mark_write: %c|1|%s\n", + sec, + usec, + item->tag, + item->func); + profiler_ctx.config.flush_cb(buf); + } +} + +void lv_profiler_builtin_write(const char * func, char tag) +{ + LV_ASSERT_NULL(profiler_ctx.item_arr); + LV_ASSERT_NULL(func); + + if(!profiler_ctx.enable) { + return; + } + + if(profiler_ctx.cur_index >= profiler_ctx.item_num) { + lv_profiler_builtin_flush(); + profiler_ctx.cur_index = 0; + } + + lv_profiler_builtin_item_t * item = &profiler_ctx.item_arr[profiler_ctx.cur_index]; + item->func = func; + item->tag = tag; + item->tick = profiler_ctx.config.tick_get_cb(); + profiler_ctx.cur_index++; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void default_flush_cb(const char * buf) +{ + LV_LOG("%s", buf); +} + +#endif /*LV_USE_PROFILER_BUILTIN*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_profiler_builtin.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_profiler_builtin.h new file mode 100644 index 000000000..ac41377e0 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_profiler_builtin.h @@ -0,0 +1,117 @@ +/** + * @file lv_profiler_builtin.h + * + */ + +#ifndef LV_PROFILER_BUILTIN_H +#define LV_PROFILER_BUILTIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../lv_conf_internal.h" + +#if LV_USE_PROFILER && LV_USE_PROFILER_BUILTIN + +#include +#include +#include + +/********************* + * DEFINES + *********************/ + +#define LV_PROFILER_BUILTIN_BEGIN_TAG(tag) lv_profiler_builtin_write((tag), 'B') +#define LV_PROFILER_BUILTIN_END_TAG(tag) lv_profiler_builtin_write((tag), 'E') +#define LV_PROFILER_BUILTIN_BEGIN LV_PROFILER_BUILTIN_BEGIN_TAG(__func__) +#define LV_PROFILER_BUILTIN_END LV_PROFILER_BUILTIN_END_TAG(__func__) + +/********************** + * TYPEDEFS + **********************/ + +/** + * @brief LVGL profiler built-in configuration structure + */ +typedef struct { + size_t buf_size; /**< The size of the buffer used for profiling data */ + uint32_t tick_per_sec; /**< The number of ticks per second */ + uint32_t (*tick_get_cb)(void); /**< Callback function to get the current tick count */ + void (*flush_cb)(const char * buf); /**< Callback function to flush the profiling data */ +} lv_profiler_builtin_config_t; + +/** + * @brief Structure representing a built-in profiler item in LVGL + */ +typedef struct { + char tag; /**< The tag of the profiler item */ + uint32_t tick; /**< The tick value of the profiler item */ + const char * func; /**< A pointer to the function associated with the profiler item */ +} lv_profiler_builtin_item_t; + +/** + * @brief Structure representing a context for the LVGL built-in profiler + */ +typedef struct { + lv_profiler_builtin_item_t * item_arr; /**< Pointer to an array of profiler items */ + uint32_t item_num; /**< Number of profiler items in the array */ + uint32_t cur_index; /**< Index of the current profiler item */ + lv_profiler_builtin_config_t config; /**< Configuration for the built-in profiler */ + bool enable; /**< Whether the built-in profiler is enabled */ +} lv_profiler_builtin_ctx_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * @brief Initialize the configuration of the built-in profiler + * @param config Pointer to the configuration structure of the built-in profiler + */ +void lv_profiler_builtin_config_init(lv_profiler_builtin_config_t * config); + +/** + * @brief Initialize the built-in profiler with the given configuration + * @param config Pointer to the configuration structure of the built-in profiler + */ +void lv_profiler_builtin_init(const lv_profiler_builtin_config_t * config); + +/** + * @brief Uninitialize the built-in profiler + */ +void lv_profiler_builtin_uninit(void); + +/** + * @brief Enable or disable the built-in profiler + * @param enable true to enable the built-in profiler, false to disable + */ +void lv_profiler_builtin_set_enable(bool enable); + +/** + * @brief Flush the profiling data to the console + */ +void lv_profiler_builtin_flush(void); + +/** + * @brief Write the profiling data for a function with the given tag + * @param func Name of the function being profiled + * @param tag Tag to associate with the profiling data for the function + */ +void lv_profiler_builtin_write(const char * func, char tag); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_PROFILER_BUILTIN*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_PROFILER_BUILTIN_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_rb.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_rb.c new file mode 100755 index 000000000..b53ee6ae2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_rb.c @@ -0,0 +1,556 @@ +/** + * @file lv_rb.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_rb.h" +#include "../stdlib/lv_string.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static lv_rb_node_t * rb_create_node(lv_rb_t * tree); +static lv_rb_node_t * rb_find_leaf_parent(lv_rb_t * tree, lv_rb_node_t * node); +static void rb_right_rotate(lv_rb_t * tree, lv_rb_node_t * node); +static void rb_left_rotate(lv_rb_t * tree, lv_rb_node_t * node); +static void rb_insert_color(lv_rb_t * tree, lv_rb_node_t * node); +static void rb_delete_color(lv_rb_t * tree, lv_rb_node_t * node1, lv_rb_node_t * node2); + +/********************** + * GLOBAL VARIABLES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +bool lv_rb_init(lv_rb_t * tree, lv_rb_compare_t compare, size_t node_size) +{ + LV_ASSERT_NULL(tree); + LV_ASSERT_NULL(compare); + LV_ASSERT(node_size > 0); + + if(tree == NULL || compare == NULL || node_size == 0) { + return false; + } + + lv_memzero(tree, sizeof(lv_rb_t)); + + tree->root = NULL; + tree->compare = compare; + tree->size = node_size; + + return true; +} + +lv_rb_node_t * lv_rb_insert(lv_rb_t * tree, void * key) +{ + LV_ASSERT_NULL(tree); + if(tree == NULL) { + return NULL; + } + + lv_rb_node_t * node = lv_rb_find(tree, key); + if(node) return node; + else { + node = rb_create_node(tree); + if(node == NULL) return NULL; + + if(tree->root == NULL) { + tree->root = node; + node->parent = NULL; + node->color = LV_RB_COLOR_BLACK; + return node; + } + } + + void * new_data = node->data; + node->data = key; + lv_rb_node_t * parent = rb_find_leaf_parent(tree, node); + + node->parent = parent; + node->color = LV_RB_COLOR_RED; + + if(tree->compare(key, parent->data) < 0) parent->left = node; + else parent->right = node; + + rb_insert_color(tree, node); + + node->data = new_data; + return node; +} + +lv_rb_node_t * lv_rb_find(lv_rb_t * tree, const void * key) +{ + LV_ASSERT_NULL(tree); + if(tree == NULL) { + return NULL; + } + + lv_rb_node_t * current = tree->root; + + while(current != NULL) { + lv_rb_compare_res_t cmp = tree->compare(key, current->data); + + if(cmp == 0) { + return current; + } + else if(cmp < 0) { + current = current->left; + } + else { + current = current->right; + } + } + + return NULL; +} + +void * lv_rb_remove_node(lv_rb_t * tree, lv_rb_node_t * node) +{ + lv_rb_node_t * child = NULL; + lv_rb_node_t * parent = NULL; + lv_rb_color_t color = LV_RB_COLOR_BLACK; + + if(node->left != NULL && node->right != NULL) { + lv_rb_node_t * replace = node; + replace = lv_rb_minimum_from(replace->right); + + if(node->parent != NULL) { + if(node->parent->left == node) { + node->parent->left = replace; + } + else { + node->parent->right = replace; + } + } + else { + tree->root = replace; + } + + child = replace->right; + parent = replace->parent; + color = replace->color; + + if(parent == node) { + parent = replace; + } + else { + if(child != NULL) { + child->parent = parent; + } + parent->left = child; + replace->right = node->right; + node->right->parent = replace; + } + + replace->parent = node->parent; + replace->color = node->color; + replace->left = node->left; + node->left->parent = replace; + + if(color == LV_RB_COLOR_BLACK) { + rb_delete_color(tree, child, parent); + } + + void * data = node->data; + lv_free(node); + return data; + } + + child = node->right != NULL ? node->right : node->left; + parent = node->parent; + color = node->color; + + if(child != NULL) { + child->parent = parent; + } + + if(parent != NULL) { + if(parent->left == node) { + parent->left = child; + } + else { + parent->right = child; + } + } + else { + tree->root = child; + } + + if(color == LV_RB_COLOR_BLACK) { + rb_delete_color(tree, child, parent); + } + + void * data = node->data; + lv_free(node); + return data; +} + +void * lv_rb_remove(lv_rb_t * tree, const void * key) +{ + LV_ASSERT_NULL(tree); + if(tree == NULL) { + return NULL; + } + + lv_rb_node_t * node = lv_rb_find(tree, key); + LV_ASSERT_NULL(node); + if(node == NULL) { + LV_LOG_WARN("rb delete %d not found", (int)(uintptr_t)key); + return NULL; + } + + return lv_rb_remove_node(tree, node); +} + +bool lv_rb_drop_node(lv_rb_t * tree, lv_rb_node_t * node) +{ + LV_ASSERT_NULL(tree); + if(tree == NULL) { + return false; + } + + void * data = lv_rb_remove_node(tree, node); + if(data) { + lv_free(data); + return true; + } + return false; +} + +bool lv_rb_drop(lv_rb_t * tree, const void * key) +{ + LV_ASSERT_NULL(tree); + if(tree == NULL) { + return NULL; + } + + void * data = lv_rb_remove(tree, key); + if(data) { + lv_free(data); + return true; + } + return false; +} + +void lv_rb_destroy(lv_rb_t * tree) +{ + LV_ASSERT_NULL(tree); + + if(tree == NULL) { + return; + } + + lv_rb_node_t * node = tree->root; + lv_rb_node_t * parent = NULL; + + while(node != NULL) { + if(node->left != NULL) { + node = node->left; + } + else if(node->right != NULL) { + node = node->right; + } + else { + parent = node->parent; + if(parent != NULL) { + if(parent->left == node) { + parent->left = NULL; + } + else { + parent->right = NULL; + } + } + lv_free(node->data); + lv_free(node); + node = parent; + } + } + tree->root = NULL; +} + +lv_rb_node_t * lv_rb_minimum(lv_rb_t * tree) +{ + LV_ASSERT_NULL(tree); + if(tree == NULL) { + return NULL; + } + return lv_rb_minimum_from(tree->root); +} + +lv_rb_node_t * lv_rb_maximum(lv_rb_t * tree) +{ + LV_ASSERT_NULL(tree); + if(tree == NULL) { + return NULL; + } + return lv_rb_maximum_from(tree->root); +} + +lv_rb_node_t * lv_rb_minimum_from(lv_rb_node_t * node) +{ + while(node->left != NULL) { + node = node->left; + } + + return node; +} + +lv_rb_node_t * lv_rb_maximum_from(lv_rb_node_t * node) +{ + while(node->right != NULL) { + node = node->right; + } + + return node; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static lv_rb_node_t * rb_create_node(lv_rb_t * tree) +{ + lv_rb_node_t * node = lv_malloc_zeroed(sizeof(lv_rb_node_t)); + LV_ASSERT_MALLOC(node); + if(node == NULL) { + return NULL; + } + + node->data = lv_malloc_zeroed(tree->size); + LV_ASSERT_MALLOC(node->data); + if(node->data == NULL) { + lv_free(node); + return NULL; + } + + node->color = LV_RB_COLOR_RED; + node->left = NULL; + node->right = NULL; + + return node; +} + +static lv_rb_node_t * rb_find_leaf_parent(lv_rb_t * tree, lv_rb_node_t * node) +{ + lv_rb_node_t * current = tree->root; + lv_rb_node_t * parent = current; + + while(current != NULL) { + parent = current; + + if(tree->compare(node->data, current->data) < 0) { + current = current->left; + } + else { + current = current->right; + } + } + + return parent; +} + +static void rb_right_rotate(lv_rb_t * tree, lv_rb_node_t * node) +{ + lv_rb_node_t * left = node->left; + node->left = left->right; + + if(left->right != NULL) { + left->right->parent = node; + } + + left->parent = node->parent; + + if(node->parent == NULL) { + tree->root = left; + } + else if(node == node->parent->right) { + node->parent->right = left; + } + else { + node->parent->left = left; + } + + left->right = node; + node->parent = left; +} + +static void rb_left_rotate(lv_rb_t * tree, lv_rb_node_t * node) +{ + lv_rb_node_t * right = node->right; + node->right = right->left; + + if(right->left != NULL) { + right->left->parent = node; + } + + right->parent = node->parent; + + if(node->parent == NULL) { + tree->root = right; + } + else if(node == node->parent->left) { + node->parent->left = right; + } + else { + node->parent->right = right; + } + + right->left = node; + node->parent = right; +} + +static void rb_insert_color(lv_rb_t * tree, lv_rb_node_t * node) +{ + lv_rb_node_t * parent = NULL; + lv_rb_node_t * gparent = NULL; + + while((parent = node->parent) && parent->color == LV_RB_COLOR_RED) { + gparent = parent->parent; + + if(parent == gparent->left) { + { + lv_rb_node_t * uncle = gparent->right; + if(uncle && uncle->color == LV_RB_COLOR_RED) { + uncle->color = LV_RB_COLOR_BLACK; + parent->color = LV_RB_COLOR_BLACK; + gparent->color = LV_RB_COLOR_RED; + node = gparent; + continue; + } + } + + if(parent->right == node) { + lv_rb_node_t * tmp; + rb_left_rotate(tree, parent); + tmp = parent; + parent = node; + node = tmp; + } + + parent->color = LV_RB_COLOR_BLACK; + gparent->color = LV_RB_COLOR_RED; + rb_right_rotate(tree, gparent); + } + else { + { + lv_rb_node_t * uncle = gparent->left; + if(uncle && uncle->color == LV_RB_COLOR_RED) { + uncle->color = LV_RB_COLOR_BLACK; + parent->color = LV_RB_COLOR_BLACK; + gparent->color = LV_RB_COLOR_RED; + node = gparent; + continue; + } + } + + if(parent->left == node) { + lv_rb_node_t * tmp; + rb_right_rotate(tree, parent); + tmp = parent; + parent = node; + node = tmp; + } + + parent->color = LV_RB_COLOR_BLACK; + gparent->color = LV_RB_COLOR_RED; + rb_left_rotate(tree, gparent); + } + } + + tree->root->color = LV_RB_COLOR_BLACK; +} + +static void rb_delete_color(lv_rb_t * tree, lv_rb_node_t * node1, lv_rb_node_t * node2) +{ + LV_ASSERT_NULL(tree); + if(tree == NULL) { + return; + } + + while((node1 == NULL || node1->color == LV_RB_COLOR_BLACK) && node1 != tree->root) { + if(node2->left == node1) { + lv_rb_node_t * pNode2 = node2->right; + if(pNode2->color == LV_RB_COLOR_RED) { + pNode2->color = LV_RB_COLOR_BLACK; + node2->color = LV_RB_COLOR_RED; + rb_left_rotate(tree, node2); + pNode2 = node2->right; + } + + if((pNode2->left == NULL || pNode2->left->color == LV_RB_COLOR_BLACK) + && (pNode2->right == NULL || pNode2->right->color == LV_RB_COLOR_BLACK)) { + pNode2->color = LV_RB_COLOR_RED; + node1 = node2; + node2 = node2->parent; + } + else { + if(pNode2->right == NULL || pNode2->right->color == LV_RB_COLOR_BLACK) { + pNode2->left->color = LV_RB_COLOR_BLACK; + pNode2->color = LV_RB_COLOR_RED; + rb_right_rotate(tree, pNode2); + pNode2 = node2->right; + } + pNode2->color = node2->color; + node2->color = LV_RB_COLOR_BLACK; + pNode2->right->color = LV_RB_COLOR_BLACK; + rb_left_rotate(tree, node2); + node1 = tree->root; + break; + } + } + else { + lv_rb_node_t * pNode2 = node2->left; + if(pNode2->color == LV_RB_COLOR_RED) { + pNode2->color = LV_RB_COLOR_BLACK; + node2->color = LV_RB_COLOR_RED; + rb_right_rotate(tree, node2); + pNode2 = node2->left; + } + + if((pNode2->left == NULL || pNode2->left->color == LV_RB_COLOR_BLACK) + && (pNode2->right == NULL || pNode2->right->color == LV_RB_COLOR_BLACK)) { + pNode2->color = LV_RB_COLOR_RED; + node1 = node2; + node2 = node2->parent; + } + else { + if(pNode2->left == NULL || pNode2->left->color == LV_RB_COLOR_BLACK) { + pNode2->right->color = LV_RB_COLOR_BLACK; + pNode2->color = LV_RB_COLOR_RED; + rb_left_rotate(tree, pNode2); + pNode2 = node2->left; + } + pNode2->color = node2->color; + node2->color = LV_RB_COLOR_BLACK; + pNode2->left->color = LV_RB_COLOR_BLACK; + rb_right_rotate(tree, node2); + node1 = tree->root; + break; + } + } + } + if(node1 != NULL) + node1->color = LV_RB_COLOR_BLACK; +} diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_rb.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_rb.h new file mode 100755 index 000000000..1533cea75 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_rb.h @@ -0,0 +1,80 @@ +/** + * @file lv_rb.h + * + */ + +#ifndef LV_RB_H +#define LV_RB_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_types.h" +#include "stdbool.h" +#include "lv_assert.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef enum { + LV_RB_COLOR_RED, + LV_RB_COLOR_BLACK +} lv_rb_color_t; + +typedef struct lv_rb_node_t { + struct lv_rb_node_t * parent; + struct lv_rb_node_t * left; + struct lv_rb_node_t * right; + lv_rb_color_t color; + void * data; +} lv_rb_node_t; + +typedef int8_t lv_rb_compare_res_t; + +typedef lv_rb_compare_res_t (*lv_rb_compare_t)(const void * a, const void * b); + +typedef struct { + lv_rb_node_t * root; + lv_rb_compare_t compare; + size_t size; +} lv_rb_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +bool lv_rb_init(lv_rb_t * tree, lv_rb_compare_t compare, size_t node_size); +lv_rb_node_t * lv_rb_insert(lv_rb_t * tree, void * key); +lv_rb_node_t * lv_rb_find(lv_rb_t * tree, const void * key); +void * lv_rb_remove_node(lv_rb_t * tree, lv_rb_node_t * node); +void * lv_rb_remove(lv_rb_t * tree, const void * key); +bool lv_rb_drop_node(lv_rb_t * tree, lv_rb_node_t * node); +bool lv_rb_drop(lv_rb_t * tree, const void * key); +lv_rb_node_t * lv_rb_minimum(lv_rb_t * node); +lv_rb_node_t * lv_rb_maximum(lv_rb_t * node); +lv_rb_node_t * lv_rb_minimum_from(lv_rb_node_t * node); +lv_rb_node_t * lv_rb_maximum_from(lv_rb_node_t * node); +void lv_rb_destroy(lv_rb_t * tree); + +/************************* + * GLOBAL VARIABLES + *************************/ + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_RB_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_style.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_style.c index 994be8126..276746160 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_style.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_style.c @@ -7,14 +7,18 @@ * INCLUDES *********************/ #include "lv_style.h" -#include "../misc/lv_gc.h" -#include "../misc/lv_mem.h" +#include "../core/lv_global.h" +#include "../stdlib/lv_mem.h" +#include "../stdlib/lv_string.h" #include "lv_assert.h" #include "lv_types.h" /********************* * DEFINES *********************/ +#define _lv_style_custom_prop_flag_lookup_table_size LV_GLOBAL_DEFAULT()->style_custom_table_size +#define _lv_style_custom_prop_flag_lookup_table LV_GLOBAL_DEFAULT()->style_custom_prop_flag_lookup_table +#define last_custom_prop_id LV_GLOBAL_DEFAULT()->style_last_custom_prop_id /********************** * TYPEDEFS @@ -24,40 +28,43 @@ * STATIC PROTOTYPES **********************/ -static void lv_style_set_prop_internal(lv_style_t * style, lv_style_prop_t prop_and_meta, lv_style_value_t value, - void (*value_adjustment_helper)(lv_style_prop_t, lv_style_value_t, uint16_t *, lv_style_value_t *)); -static void lv_style_set_prop_helper(lv_style_prop_t prop, lv_style_value_t value, uint16_t * prop_storage, - lv_style_value_t * value_storage); -static void lv_style_set_prop_meta_helper(lv_style_prop_t prop, lv_style_value_t value, uint16_t * prop_storage, - lv_style_value_t * value_storage); - /********************** * GLOBAL VARIABLES **********************/ -const uint8_t _lv_style_builtin_prop_flag_lookup_table[_LV_STYLE_NUM_BUILT_IN_PROPS] = { - [LV_STYLE_WIDTH] = LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_MIN_WIDTH] = LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_MAX_WIDTH] = LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_HEIGHT] = LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_MIN_HEIGHT] = LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_MAX_HEIGHT] = LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_X] = LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_Y] = LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_ALIGN] = LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_TRANSFORM_WIDTH] = LV_STYLE_PROP_EXT_DRAW, - [LV_STYLE_TRANSFORM_HEIGHT] = LV_STYLE_PROP_EXT_DRAW, - [LV_STYLE_TRANSLATE_X] = LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, - [LV_STYLE_TRANSLATE_Y] = LV_STYLE_PROP_LAYOUT_REFR | LV_STYLE_PROP_PARENT_LAYOUT_REFR, - [LV_STYLE_TRANSFORM_ZOOM] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYER_REFR, - [LV_STYLE_TRANSFORM_ANGLE] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYER_REFR, +const lv_style_prop_t lv_style_const_prop_id_inv = LV_STYLE_PROP_INV; - [LV_STYLE_PAD_TOP] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_PAD_BOTTOM] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_PAD_LEFT] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_PAD_RIGHT] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_PAD_ROW] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_PAD_COLUMN] = LV_STYLE_PROP_EXT_DRAW | LV_STYLE_PROP_LAYOUT_REFR, +const uint8_t _lv_style_builtin_prop_flag_lookup_table[_LV_STYLE_NUM_BUILT_IN_PROPS] = { + [LV_STYLE_WIDTH] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_MIN_WIDTH] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_MAX_WIDTH] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_HEIGHT] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_MIN_HEIGHT] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_MAX_HEIGHT] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_LENGTH] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE, + [LV_STYLE_X] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_Y] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_ALIGN] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_TRANSFORM_WIDTH] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_TRANSFORM, + [LV_STYLE_TRANSFORM_HEIGHT] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_TRANSFORM, + [LV_STYLE_TRANSLATE_X] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE | LV_STYLE_PROP_FLAG_PARENT_LAYOUT_UPDATE, + [LV_STYLE_TRANSLATE_Y] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE | LV_STYLE_PROP_FLAG_PARENT_LAYOUT_UPDATE, + [LV_STYLE_TRANSFORM_SCALE_X] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYER_UPDATE | LV_STYLE_PROP_FLAG_TRANSFORM, + [LV_STYLE_TRANSFORM_SCALE_Y] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYER_UPDATE | LV_STYLE_PROP_FLAG_TRANSFORM, + [LV_STYLE_TRANSFORM_SKEW_X] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYER_UPDATE | LV_STYLE_PROP_FLAG_TRANSFORM, + [LV_STYLE_TRANSFORM_SKEW_Y] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYER_UPDATE | LV_STYLE_PROP_FLAG_TRANSFORM, + [LV_STYLE_TRANSFORM_ROTATION] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYER_UPDATE | LV_STYLE_PROP_FLAG_TRANSFORM, + + [LV_STYLE_PAD_TOP] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_PAD_BOTTOM] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_PAD_LEFT] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_PAD_RIGHT] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_PAD_ROW] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_PAD_COLUMN] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_MARGIN_TOP] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_MARGIN_BOTTOM] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_MARGIN_LEFT] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_MARGIN_RIGHT] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, [LV_STYLE_BG_COLOR] = 0, [LV_STYLE_BG_OPA] = 0, @@ -65,81 +72,98 @@ const uint8_t _lv_style_builtin_prop_flag_lookup_table[_LV_STYLE_NUM_BUILT_IN_PR [LV_STYLE_BG_GRAD_DIR] = 0, [LV_STYLE_BG_MAIN_STOP] = 0, [LV_STYLE_BG_GRAD_STOP] = 0, + [LV_STYLE_BG_MAIN_OPA] = 0, + [LV_STYLE_BG_GRAD_OPA] = 0, [LV_STYLE_BG_GRAD] = 0, - [LV_STYLE_BG_DITHER_MODE] = 0, - [LV_STYLE_BG_IMG_SRC] = LV_STYLE_PROP_EXT_DRAW, - [LV_STYLE_BG_IMG_OPA] = 0, - [LV_STYLE_BG_IMG_RECOLOR] = 0, - [LV_STYLE_BG_IMG_RECOLOR_OPA] = 0, - [LV_STYLE_BG_IMG_TILED] = 0, + [LV_STYLE_BG_IMAGE_SRC] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE, + [LV_STYLE_BG_IMAGE_OPA] = 0, + [LV_STYLE_BG_IMAGE_RECOLOR] = 0, + [LV_STYLE_BG_IMAGE_RECOLOR_OPA] = 0, + [LV_STYLE_BG_IMAGE_TILED] = 0, [LV_STYLE_BORDER_COLOR] = 0, [LV_STYLE_BORDER_OPA] = 0, - [LV_STYLE_BORDER_WIDTH] = LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_BORDER_WIDTH] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, [LV_STYLE_BORDER_SIDE] = 0, [LV_STYLE_BORDER_POST] = 0, - [LV_STYLE_OUTLINE_WIDTH] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_OUTLINE_WIDTH] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE, [LV_STYLE_OUTLINE_COLOR] = 0, - [LV_STYLE_OUTLINE_OPA] = LV_STYLE_PROP_EXT_DRAW, - [LV_STYLE_OUTLINE_PAD] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_OUTLINE_OPA] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE, + [LV_STYLE_OUTLINE_PAD] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE, - [LV_STYLE_SHADOW_WIDTH] = LV_STYLE_PROP_EXT_DRAW, - [LV_STYLE_SHADOW_OFS_X] = LV_STYLE_PROP_EXT_DRAW, - [LV_STYLE_SHADOW_OFS_Y] = LV_STYLE_PROP_EXT_DRAW, - [LV_STYLE_SHADOW_SPREAD] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_SHADOW_WIDTH] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE, + [LV_STYLE_SHADOW_OFFSET_X] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE, + [LV_STYLE_SHADOW_OFFSET_Y] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE, + [LV_STYLE_SHADOW_SPREAD] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE, [LV_STYLE_SHADOW_COLOR] = 0, - [LV_STYLE_SHADOW_OPA] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_SHADOW_OPA] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE, - [LV_STYLE_IMG_OPA] = 0, - [LV_STYLE_IMG_RECOLOR] = 0, - [LV_STYLE_IMG_RECOLOR_OPA] = 0, + [LV_STYLE_IMAGE_OPA] = 0, + [LV_STYLE_IMAGE_RECOLOR] = 0, + [LV_STYLE_IMAGE_RECOLOR_OPA] = 0, - [LV_STYLE_LINE_WIDTH] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_LINE_WIDTH] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE, [LV_STYLE_LINE_DASH_WIDTH] = 0, [LV_STYLE_LINE_DASH_GAP] = 0, [LV_STYLE_LINE_ROUNDED] = 0, [LV_STYLE_LINE_COLOR] = 0, [LV_STYLE_LINE_OPA] = 0, - [LV_STYLE_ARC_WIDTH] = LV_STYLE_PROP_EXT_DRAW, + [LV_STYLE_ARC_WIDTH] = LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE, [LV_STYLE_ARC_ROUNDED] = 0, [LV_STYLE_ARC_COLOR] = 0, [LV_STYLE_ARC_OPA] = 0, - [LV_STYLE_ARC_IMG_SRC] = 0, + [LV_STYLE_ARC_IMAGE_SRC] = 0, - [LV_STYLE_TEXT_COLOR] = LV_STYLE_PROP_INHERIT, - [LV_STYLE_TEXT_OPA] = LV_STYLE_PROP_INHERIT, - [LV_STYLE_TEXT_FONT] = LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_TEXT_LETTER_SPACE] = LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_TEXT_LINE_SPACE] = LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_TEXT_DECOR] = LV_STYLE_PROP_INHERIT, - [LV_STYLE_TEXT_ALIGN] = LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, + [LV_STYLE_TEXT_COLOR] = LV_STYLE_PROP_FLAG_INHERITABLE, + [LV_STYLE_TEXT_OPA] = LV_STYLE_PROP_FLAG_INHERITABLE, + [LV_STYLE_TEXT_FONT] = LV_STYLE_PROP_FLAG_INHERITABLE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_TEXT_LETTER_SPACE] = LV_STYLE_PROP_FLAG_INHERITABLE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_TEXT_LINE_SPACE] = LV_STYLE_PROP_FLAG_INHERITABLE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_TEXT_DECOR] = LV_STYLE_PROP_FLAG_INHERITABLE, + [LV_STYLE_TEXT_ALIGN] = LV_STYLE_PROP_FLAG_INHERITABLE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, [LV_STYLE_RADIUS] = 0, [LV_STYLE_CLIP_CORNER] = 0, - [LV_STYLE_OPA] = 0, - [LV_STYLE_OPA_LAYERED] = LV_STYLE_PROP_LAYER_REFR, - [LV_STYLE_COLOR_FILTER_DSC] = LV_STYLE_PROP_INHERIT, - [LV_STYLE_COLOR_FILTER_OPA] = LV_STYLE_PROP_INHERIT, - [LV_STYLE_ANIM_TIME] = 0, - [LV_STYLE_ANIM_SPEED] = 0, + [LV_STYLE_OPA] = 0, + [LV_STYLE_OPA_LAYERED] = LV_STYLE_PROP_FLAG_LAYER_UPDATE, + [LV_STYLE_COLOR_FILTER_DSC] = LV_STYLE_PROP_FLAG_INHERITABLE, + [LV_STYLE_COLOR_FILTER_OPA] = LV_STYLE_PROP_FLAG_INHERITABLE, + [LV_STYLE_ANIM_DURATION] = 0, [LV_STYLE_TRANSITION] = 0, - [LV_STYLE_BLEND_MODE] = LV_STYLE_PROP_LAYER_REFR, - [LV_STYLE_LAYOUT] = LV_STYLE_PROP_LAYOUT_REFR, - [LV_STYLE_BASE_DIR] = LV_STYLE_PROP_INHERIT | LV_STYLE_PROP_LAYOUT_REFR, -}; + [LV_STYLE_BLEND_MODE] = LV_STYLE_PROP_FLAG_LAYER_UPDATE, + [LV_STYLE_LAYOUT] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_BASE_DIR] = LV_STYLE_PROP_FLAG_INHERITABLE | LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, -uint32_t _lv_style_custom_prop_flag_lookup_table_size = 0; +#if LV_USE_FLEX + [LV_STYLE_FLEX_FLOW] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_FLEX_MAIN_PLACE] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_FLEX_CROSS_PLACE] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_FLEX_TRACK_PLACE] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_FLEX_GROW] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, +#endif + +#if LV_USE_GRID + [LV_STYLE_GRID_COLUMN_DSC_ARRAY] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_GRID_ROW_DSC_ARRAY] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_GRID_COLUMN_ALIGN] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_GRID_ROW_ALIGN] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_GRID_CELL_ROW_SPAN] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_GRID_CELL_ROW_POS] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_GRID_CELL_COLUMN_SPAN] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_GRID_CELL_COLUMN_POS] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_GRID_CELL_X_ALIGN] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, + [LV_STYLE_GRID_CELL_Y_ALIGN] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE, +#endif + +}; /********************** * STATIC VARIABLES **********************/ -static uint16_t last_custom_prop_id = (uint16_t)_LV_STYLE_LAST_BUILT_IN_PROP; -static const lv_style_value_t null_style_value = { .num = 0 }; - /********************** * MACROS **********************/ @@ -156,7 +180,7 @@ void lv_style_init(lv_style_t * style) } #endif - lv_memset_00(style, sizeof(lv_style_t)); + lv_memzero(style, sizeof(lv_style_t)); #if LV_USE_ASSERT_STYLE style->sentinel = LV_STYLE_SENTINEL_VALUE; #endif @@ -166,13 +190,8 @@ void lv_style_reset(lv_style_t * style) { LV_ASSERT_STYLE(style); - if(style->prop1 == LV_STYLE_PROP_ANY) { - LV_LOG_ERROR("Cannot reset const style"); - return; - } - - if(style->prop_cnt > 1) lv_mem_free(style->v_p.values_and_props); - lv_memset_00(style, sizeof(lv_style_t)); + if(style->prop_cnt != 255) lv_free(style->values_and_props); + lv_memzero(style, sizeof(lv_style_t)); #if LV_USE_ASSERT_STYLE style->sentinel = LV_STYLE_SENTINEL_VALUE; #endif @@ -180,15 +199,15 @@ void lv_style_reset(lv_style_t * style) lv_style_prop_t lv_style_register_prop(uint8_t flag) { - if(LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table) == NULL) { + if(_lv_style_custom_prop_flag_lookup_table == NULL) { _lv_style_custom_prop_flag_lookup_table_size = 0; last_custom_prop_id = (uint16_t)_LV_STYLE_LAST_BUILT_IN_PROP; } - if(((last_custom_prop_id + 1) & LV_STYLE_PROP_META_MASK) != 0) { - LV_LOG_ERROR("No more custom property IDs available"); - return LV_STYLE_PROP_INV; - } + // if((last_custom_prop_id + 1) != 0) { + // LV_LOG_ERROR("No more custom property IDs available"); + // return LV_STYLE_PROP_INV; + // } /* * Allocate the lookup table if it's not yet available. @@ -198,19 +217,19 @@ lv_style_prop_t lv_style_register_prop(uint8_t flag) /* Round required_size up to the nearest 32-byte value */ required_size = (required_size + 31) & ~31; LV_ASSERT_MSG(required_size > 0, "required size has become 0?"); - uint8_t * old_p = LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table); - uint8_t * new_p = lv_mem_realloc(old_p, required_size * sizeof(uint8_t)); + uint8_t * old_p = _lv_style_custom_prop_flag_lookup_table; + uint8_t * new_p = lv_realloc(old_p, required_size * sizeof(uint8_t)); if(new_p == NULL) { LV_LOG_ERROR("Unable to allocate space for custom property lookup table"); return LV_STYLE_PROP_INV; } - LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table) = new_p; + _lv_style_custom_prop_flag_lookup_table = new_p; _lv_style_custom_prop_flag_lookup_table_size = required_size; } last_custom_prop_id++; /* This should never happen - we should bail out above */ - LV_ASSERT_NULL(LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table)); - LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table)[last_custom_prop_id - _LV_STYLE_NUM_BUILT_IN_PROPS] = flag; + LV_ASSERT_NULL(_lv_style_custom_prop_flag_lookup_table); + _lv_style_custom_prop_flag_lookup_table[last_custom_prop_id - _LV_STYLE_NUM_BUILT_IN_PROPS] = flag; return last_custom_prop_id; } @@ -223,56 +242,40 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop) { LV_ASSERT_STYLE(style); - if(style->prop1 == LV_STYLE_PROP_ANY) { + if(lv_style_is_const(style)) { LV_LOG_ERROR("Cannot remove prop from const style"); return false; } if(style->prop_cnt == 0) return false; - if(style->prop_cnt == 1) { - if(LV_STYLE_PROP_ID_MASK(style->prop1) == prop) { - style->prop1 = LV_STYLE_PROP_INV; - style->prop_cnt = 0; - return true; - } - return false; - } - - uint8_t * tmp = style->v_p.values_and_props + style->prop_cnt * sizeof(lv_style_value_t); - uint16_t * old_props = (uint16_t *)tmp; + uint8_t * tmp = (lv_style_prop_t *)style->values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + uint8_t * old_props = (uint8_t *)tmp; uint32_t i; for(i = 0; i < style->prop_cnt; i++) { - if(LV_STYLE_PROP_ID_MASK(old_props[i]) == prop) { - lv_style_value_t * old_values = (lv_style_value_t *)style->v_p.values_and_props; + if(old_props[i] == prop) { + lv_style_value_t * old_values = (lv_style_value_t *)style->values_and_props; - if(style->prop_cnt == 2) { - style->prop_cnt = 1; - style->prop1 = i == 0 ? old_props[1] : old_props[0]; - style->v_p.value1 = i == 0 ? old_values[1] : old_values[0]; - } - else { - size_t size = (style->prop_cnt - 1) * (sizeof(lv_style_value_t) + sizeof(uint16_t)); - uint8_t * new_values_and_props = lv_mem_alloc(size); - if(new_values_and_props == NULL) return false; - style->v_p.values_and_props = new_values_and_props; - style->prop_cnt--; + size_t size = (style->prop_cnt - 1) * (sizeof(lv_style_value_t) + sizeof(lv_style_prop_t)); + uint8_t * new_values_and_props = lv_malloc(size); + if(new_values_and_props == NULL) return false; + style->values_and_props = new_values_and_props; + style->prop_cnt--; - tmp = new_values_and_props + style->prop_cnt * sizeof(lv_style_value_t); - uint16_t * new_props = (uint16_t *)tmp; - lv_style_value_t * new_values = (lv_style_value_t *)new_values_and_props; + tmp = new_values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + uint8_t * new_props = (uint8_t *)tmp; + lv_style_value_t * new_values = (lv_style_value_t *)new_values_and_props; - uint32_t j; - for(i = j = 0; j <= style->prop_cnt; - j++) { /*<=: because prop_cnt already reduced but all the old props. needs to be checked.*/ - if(old_props[j] != prop) { - new_values[i] = old_values[j]; - new_props[i++] = old_props[j]; - } + uint32_t j; + for(i = j = 0; j <= style->prop_cnt; + j++) { /*<=: because prop_cnt already reduced but all the old props. needs to be checked.*/ + if(old_props[j] != prop) { + new_values[i] = old_values[j]; + new_props[i++] = old_props[j]; } } - lv_mem_free(old_values); + lv_free(old_values); return true; } } @@ -282,12 +285,51 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop) void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_t value) { - lv_style_set_prop_internal(style, prop, value, lv_style_set_prop_helper); -} + LV_ASSERT_STYLE(style); -void lv_style_set_prop_meta(lv_style_t * style, lv_style_prop_t prop, uint16_t meta) -{ - lv_style_set_prop_internal(style, prop | meta, null_style_value, lv_style_set_prop_meta_helper); + if(lv_style_is_const(style)) { + LV_LOG_ERROR("Cannot set property of constant style"); + return; + } + + LV_ASSERT(prop != LV_STYLE_PROP_INV); + + lv_style_prop_t * props; + int32_t i; + + if(style->values_and_props) { + props = (lv_style_prop_t *)style->values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + for(i = style->prop_cnt - 1; i >= 0; i--) { + if(props[i] == prop) { + lv_style_value_t * values = (lv_style_value_t *)style->values_and_props; + values[i] = value; + return; + } + } + } + + size_t size = (style->prop_cnt + 1) * (sizeof(lv_style_value_t) + sizeof(lv_style_prop_t)); + uint8_t * values_and_props = lv_realloc(style->values_and_props, size); + if(values_and_props == NULL) return; + style->values_and_props = values_and_props; + + props = values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + /*Shift all props to make place for the value before them*/ + for(i = style->prop_cnt - 1; i >= 0; i--) { + props[i + sizeof(lv_style_value_t) / sizeof(lv_style_prop_t)] = props[i]; + } + style->prop_cnt++; + + /*Go to the new position with the props*/ + props = values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + lv_style_value_t * values = (lv_style_value_t *)values_and_props; + + /*Set the new property and value*/ + props[style->prop_cnt - 1] = prop; + values[style->prop_cnt - 1] = value; + + uint32_t group = _lv_style_get_prop_group(prop); + style->has_group |= (uint32_t)1 << group; } lv_style_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value) @@ -298,28 +340,28 @@ lv_style_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, void lv_style_transition_dsc_init(lv_style_transition_dsc_t * tr, const lv_style_prop_t props[], lv_anim_path_cb_t path_cb, uint32_t time, uint32_t delay, void * user_data) { - lv_memset_00(tr, sizeof(lv_style_transition_dsc_t)); + lv_memzero(tr, sizeof(lv_style_transition_dsc_t)); tr->props = props; tr->path_xcb = path_cb == NULL ? lv_anim_path_linear : path_cb; tr->time = time; tr->delay = delay; -#if LV_USE_USER_DATA tr->user_data = user_data; -#else - LV_UNUSED(user_data); -#endif } lv_style_value_t lv_style_prop_get_default(lv_style_prop_t prop) { - lv_style_value_t value; + const lv_color_t black = LV_COLOR_MAKE(0x00, 0x00, 0x00); + const lv_color_t white = LV_COLOR_MAKE(0xff, 0xff, 0xff); switch(prop) { - case LV_STYLE_TRANSFORM_ZOOM: - value.num = LV_IMG_ZOOM_NONE; - break; + case LV_STYLE_TRANSFORM_SCALE_X: + case LV_STYLE_TRANSFORM_SCALE_Y: + return (lv_style_value_t) { + .num = LV_SCALE_NONE + }; case LV_STYLE_BG_COLOR: - value.color = lv_color_white(); - break; + return (lv_style_value_t) { + .color = white + }; case LV_STYLE_BG_GRAD_COLOR: case LV_STYLE_BORDER_COLOR: case LV_STYLE_SHADOW_COLOR: @@ -327,161 +369,69 @@ lv_style_value_t lv_style_prop_get_default(lv_style_prop_t prop) case LV_STYLE_ARC_COLOR: case LV_STYLE_LINE_COLOR: case LV_STYLE_TEXT_COLOR: - case LV_STYLE_IMG_RECOLOR: - value.color = lv_color_black(); - break; + case LV_STYLE_IMAGE_RECOLOR: + return (lv_style_value_t) { + .color = black + }; case LV_STYLE_OPA: case LV_STYLE_OPA_LAYERED: case LV_STYLE_BORDER_OPA: case LV_STYLE_TEXT_OPA: - case LV_STYLE_IMG_OPA: - case LV_STYLE_BG_IMG_OPA: + case LV_STYLE_IMAGE_OPA: + case LV_STYLE_BG_GRAD_OPA: + case LV_STYLE_BG_MAIN_OPA: + case LV_STYLE_BG_IMAGE_OPA: case LV_STYLE_OUTLINE_OPA: case LV_STYLE_SHADOW_OPA: case LV_STYLE_LINE_OPA: case LV_STYLE_ARC_OPA: - value.num = LV_OPA_COVER; - break; + return (lv_style_value_t) { + .num = LV_OPA_COVER + }; case LV_STYLE_BG_GRAD_STOP: - value.num = 255; - break; + return (lv_style_value_t) { + .num = 255 + }; case LV_STYLE_BORDER_SIDE: - value.num = LV_BORDER_SIDE_FULL; - break; + return (lv_style_value_t) { + .num = LV_BORDER_SIDE_FULL + }; case LV_STYLE_TEXT_FONT: - value.ptr = LV_FONT_DEFAULT; - break; + return (lv_style_value_t) { + .ptr = LV_FONT_DEFAULT + }; case LV_STYLE_MAX_WIDTH: case LV_STYLE_MAX_HEIGHT: - value.num = LV_COORD_MAX; - break; + return (lv_style_value_t) { + .num = LV_COORD_MAX + }; default: - value.ptr = NULL; - value.num = 0; - break; + return (lv_style_value_t) { + .ptr = 0 + }; } - - return value; } bool lv_style_is_empty(const lv_style_t * style) { LV_ASSERT_STYLE(style); - return style->prop_cnt == 0 ? true : false; -} - -uint8_t _lv_style_get_prop_group(lv_style_prop_t prop) -{ - uint16_t group = (prop & 0x1FF) >> 4; - if(group > 7) group = 7; /*The MSB marks all the custom properties*/ - return (uint8_t)group; + return style->prop_cnt == 0; } uint8_t _lv_style_prop_lookup_flags(lv_style_prop_t prop) { - extern const uint8_t _lv_style_builtin_prop_flag_lookup_table[]; - extern uint32_t _lv_style_custom_prop_flag_lookup_table_size; - if(prop == LV_STYLE_PROP_ANY) return LV_STYLE_PROP_ALL; /*Any prop can have any flags*/ + if(prop == LV_STYLE_PROP_ANY) return LV_STYLE_PROP_FLAG_ALL; /*Any prop can have any flags*/ if(prop == LV_STYLE_PROP_INV) return 0; if(prop < _LV_STYLE_NUM_BUILT_IN_PROPS) return _lv_style_builtin_prop_flag_lookup_table[prop]; prop -= _LV_STYLE_NUM_BUILT_IN_PROPS; - if(LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table) != NULL && prop < _lv_style_custom_prop_flag_lookup_table_size) - return LV_GC_ROOT(_lv_style_custom_prop_flag_lookup_table)[prop]; + if(_lv_style_custom_prop_flag_lookup_table != NULL && prop < _lv_style_custom_prop_flag_lookup_table_size) + return _lv_style_custom_prop_flag_lookup_table[prop]; return 0; } /********************** * STATIC FUNCTIONS **********************/ - -static void lv_style_set_prop_helper(lv_style_prop_t prop, lv_style_value_t value, uint16_t * prop_storage, - lv_style_value_t * value_storage) -{ - *prop_storage = prop; - *value_storage = value; -} - -static void lv_style_set_prop_meta_helper(lv_style_prop_t prop, lv_style_value_t value, uint16_t * prop_storage, - lv_style_value_t * value_storage) -{ - LV_UNUSED(value); - LV_UNUSED(value_storage); - *prop_storage = prop; /* meta is OR-ed into the prop ID already */ -} - -static void lv_style_set_prop_internal(lv_style_t * style, lv_style_prop_t prop_and_meta, lv_style_value_t value, - void (*value_adjustment_helper)(lv_style_prop_t, lv_style_value_t, uint16_t *, lv_style_value_t *)) -{ - LV_ASSERT_STYLE(style); - - if(style->prop1 == LV_STYLE_PROP_ANY) { - LV_LOG_ERROR("Cannot set property of constant style"); - return; - } - - lv_style_prop_t prop_id = LV_STYLE_PROP_ID_MASK(prop_and_meta); - - if(style->prop_cnt > 1) { - uint8_t * tmp = style->v_p.values_and_props + style->prop_cnt * sizeof(lv_style_value_t); - uint16_t * props = (uint16_t *)tmp; - int32_t i; - for(i = style->prop_cnt - 1; i >= 0; i--) { - if(LV_STYLE_PROP_ID_MASK(props[i]) == prop_id) { - lv_style_value_t * values = (lv_style_value_t *)style->v_p.values_and_props; - value_adjustment_helper(prop_and_meta, value, &props[i], &values[i]); - return; - } - } - - size_t size = (style->prop_cnt + 1) * (sizeof(lv_style_value_t) + sizeof(uint16_t)); - uint8_t * values_and_props = lv_mem_realloc(style->v_p.values_and_props, size); - if(values_and_props == NULL) return; - style->v_p.values_and_props = values_and_props; - - tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t); - props = (uint16_t *)tmp; - /*Shift all props to make place for the value before them*/ - for(i = style->prop_cnt - 1; i >= 0; i--) { - props[i + sizeof(lv_style_value_t) / sizeof(uint16_t)] = props[i]; - } - style->prop_cnt++; - - /*Go to the new position wit the props*/ - tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t); - props = (uint16_t *)tmp; - lv_style_value_t * values = (lv_style_value_t *)values_and_props; - - /*Set the new property and value*/ - value_adjustment_helper(prop_and_meta, value, &props[style->prop_cnt - 1], &values[style->prop_cnt - 1]); - } - else if(style->prop_cnt == 1) { - if(LV_STYLE_PROP_ID_MASK(style->prop1) == prop_id) { - value_adjustment_helper(prop_and_meta, value, &style->prop1, &style->v_p.value1); - return; - } - size_t size = (style->prop_cnt + 1) * (sizeof(lv_style_value_t) + sizeof(uint16_t)); - uint8_t * values_and_props = lv_mem_alloc(size); - if(values_and_props == NULL) return; - lv_style_value_t value_tmp = style->v_p.value1; - style->v_p.values_and_props = values_and_props; - style->prop_cnt++; - - uint8_t * tmp = values_and_props + style->prop_cnt * sizeof(lv_style_value_t); - uint16_t * props = (uint16_t *)tmp; - lv_style_value_t * values = (lv_style_value_t *)values_and_props; - props[0] = style->prop1; - values[0] = value_tmp; - value_adjustment_helper(prop_and_meta, value, &props[1], &values[1]); - } - else { - style->prop_cnt = 1; - value_adjustment_helper(prop_and_meta, value, &style->prop1, &style->v_p.value1); - } - - uint8_t group = _lv_style_get_prop_group(prop_id); - style->has_group |= 1 << group; -} - diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_style.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_style.h index 77bf28362..7e5ed75be 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_style.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_style.h @@ -19,10 +19,11 @@ extern "C" { #include "lv_color.h" #include "lv_area.h" #include "lv_anim.h" -#include "lv_txt.h" +#include "lv_text.h" #include "lv_types.h" #include "lv_assert.h" #include "lv_bidi.h" +#include "../layouts/lv_layout.h" /********************* * DEFINES @@ -35,46 +36,41 @@ extern "C" { * * The rest of the flags will have _FLAG added to their name in v9. */ -#define LV_STYLE_PROP_FLAG_NONE (0) -#define LV_STYLE_PROP_INHERIT (1 << 0) /*Inherited*/ -#define LV_STYLE_PROP_EXT_DRAW (1 << 1) /*Requires ext. draw size update when changed*/ -#define LV_STYLE_PROP_LAYOUT_REFR (1 << 2) /*Requires layout update when changed*/ -#define LV_STYLE_PROP_PARENT_LAYOUT_REFR (1 << 3) /*Requires layout update on parent when changed*/ -#define LV_STYLE_PROP_LAYER_REFR (1 << 4) /*Affects layer handling*/ -#define LV_STYLE_PROP_ALL (0x1F) /*Indicating all flags*/ +#define LV_STYLE_PROP_FLAG_NONE (0) +#define LV_STYLE_PROP_FLAG_INHERITABLE (1 << 0) /*Inherited*/ +#define LV_STYLE_PROP_FLAG_EXT_DRAW_UPDATE (1 << 1) /*Requires ext. draw size update when changed*/ +#define LV_STYLE_PROP_FLAG_LAYOUT_UPDATE (1 << 2) /*Requires layout update when changed*/ +#define LV_STYLE_PROP_FLAG_PARENT_LAYOUT_UPDATE (1 << 3) /*Requires layout update on parent when changed*/ +#define LV_STYLE_PROP_FLAG_LAYER_UPDATE (1 << 4) /*Affects layer handling*/ +#define LV_STYLE_PROP_FLAG_TRANSFORM (1 << 5) /*Affects the object's transformation*/ +#define LV_STYLE_PROP_FLAG_ALL (0x3F) /*Indicating all flags*/ /** * Other constants */ -#define LV_IMG_ZOOM_NONE 256 /*Value for not zooming the image*/ -LV_EXPORT_CONST_INT(LV_IMG_ZOOM_NONE); +#define LV_SCALE_NONE 256 /*Value for not zooming the image*/ +LV_EXPORT_CONST_INT(LV_SCALE_NONE); // *INDENT-OFF* #if LV_USE_ASSERT_STYLE #define LV_STYLE_CONST_INIT(var_name, prop_array) \ const lv_style_t var_name = { \ .sentinel = LV_STYLE_SENTINEL_VALUE, \ - .v_p = { .const_props = prop_array }, \ - .has_group = 0xFF, \ - .prop1 = LV_STYLE_PROP_ANY, \ - .prop_cnt = (sizeof(prop_array) / sizeof((prop_array)[0])), \ + .values_and_props = (void*)prop_array, \ + .has_group = 0xFFFFFFFF, \ + .prop_cnt = 255 \ } #else #define LV_STYLE_CONST_INIT(var_name, prop_array) \ const lv_style_t var_name = { \ - .v_p = { .const_props = prop_array }, \ - .has_group = 0xFF, \ - .prop1 = LV_STYLE_PROP_ANY, \ - .prop_cnt = (sizeof(prop_array) / sizeof((prop_array)[0])), \ + .values_and_props = prop_array, \ + .has_group = 0xFFFFFFFF, \ + .prop_cnt = 255, \ } #endif // *INDENT-ON* -#define LV_STYLE_PROP_META_INHERIT 0x8000 -#define LV_STYLE_PROP_META_INITIAL 0x4000 -#define LV_STYLE_PROP_META_MASK (LV_STYLE_PROP_META_INHERIT | LV_STYLE_PROP_META_INITIAL) - -#define LV_STYLE_PROP_ID_MASK(prop) ((lv_style_prop_t)((prop) & ~LV_STYLE_PROP_META_MASK)) +#define LV_STYLE_CONST_PROPS_END { .prop_ptr = NULL, .value = { .num = 0 } } /********************** * TYPEDEFS @@ -83,33 +79,40 @@ LV_EXPORT_CONST_INT(LV_IMG_ZOOM_NONE); /** * Possible options how to blend opaque drawings */ -enum { +enum _lv_blend_mode_t { LV_BLEND_MODE_NORMAL, /**< Simply mix according to the opacity value*/ LV_BLEND_MODE_ADDITIVE, /**< Add the respective color channels*/ LV_BLEND_MODE_SUBTRACTIVE,/**< Subtract the foreground from the background*/ LV_BLEND_MODE_MULTIPLY, /**< Multiply the foreground and background*/ - LV_BLEND_MODE_REPLACE, /**< Replace background with foreground in the area*/ }; +#ifdef DOXYGEN +typedef _lv_blend_mode_t lv_blend_mode_t; +#else typedef uint8_t lv_blend_mode_t; +#endif /*DOXYGEN*/ /** * Some options to apply decorations on texts. * 'OR'ed values can be used. */ -enum { +enum _lv_text_decor_t { LV_TEXT_DECOR_NONE = 0x00, LV_TEXT_DECOR_UNDERLINE = 0x01, LV_TEXT_DECOR_STRIKETHROUGH = 0x02, }; +#ifdef DOXYGEN +typedef _lv_text_decor_t lv_text_decor_t; +#else typedef uint8_t lv_text_decor_t; +#endif /*DOXYGEN*/ /** * Selects on which sides border should be drawn * 'OR'ed values can be used. */ -enum { +enum _lv_border_side_t { LV_BORDER_SIDE_NONE = 0x00, LV_BORDER_SIDE_BOTTOM = 0x01, LV_BORDER_SIDE_TOP = 0x02, @@ -118,36 +121,34 @@ enum { LV_BORDER_SIDE_FULL = 0x0F, LV_BORDER_SIDE_INTERNAL = 0x10, /**< FOR matrix-like objects (e.g. Button matrix)*/ }; + +#ifdef DOXYGEN +typedef _lv_border_side_t lv_border_side_t; +#else typedef uint8_t lv_border_side_t; +#endif /*DOXYGEN*/ /** * The direction of the gradient. */ -enum { +enum _lv_grad_dir_t { LV_GRAD_DIR_NONE, /**< No gradient (the `grad_color` property is ignored)*/ LV_GRAD_DIR_VER, /**< Vertical (top to bottom) gradient*/ LV_GRAD_DIR_HOR, /**< Horizontal (left to right) gradient*/ }; +#ifdef DOXYGEN +typedef _lv_grad_dir_t lv_grad_dir_t; +#else typedef uint8_t lv_grad_dir_t; - -/** - * The dithering algorithm for the gradient - * Depends on LV_DITHER_GRADIENT - */ -enum { - LV_DITHER_NONE, /**< No dithering, colors are just quantized to the output resolution*/ - LV_DITHER_ORDERED, /**< Ordered dithering. Faster to compute and use less memory but lower quality*/ - LV_DITHER_ERR_DIFF, /**< Error diffusion mode. Slower to compute and use more memory but give highest dither quality*/ -}; - -typedef uint8_t lv_dither_mode_t; +#endif /*DOXYGEN*/ /** A gradient stop definition. * This matches a color and a position in a virtual 0-255 scale. */ typedef struct { lv_color_t color; /**< The stop color */ + lv_opa_t opa; /**< The opacity of the color*/ uint8_t frac; /**< The stop position in 1/255 unit */ } lv_gradient_stop_t; @@ -157,8 +158,6 @@ typedef struct { uint8_t stops_count; /**< The number of used stops in the array */ lv_grad_dir_t dir : 3; /**< The gradient direction. * Any of LV_GRAD_DIR_HOR, LV_GRAD_DIR_VER, LV_GRAD_DIR_NONE */ - lv_dither_mode_t dither : 3; /**< Whether to dither the gradient or not. - * Any of LV_DITHER_NONE, LV_DITHER_ORDERED, LV_DITHER_ERR_DIFF */ } lv_grad_dsc_t; /** @@ -175,131 +174,183 @@ typedef union { * * Props are split into groups of 16. When adding a new prop to a group, ensure it does not overflow into the next one. */ -typedef enum { +enum _lv_style_prop_t { LV_STYLE_PROP_INV = 0, /*Group 0*/ LV_STYLE_WIDTH = 1, - LV_STYLE_MIN_WIDTH = 2, - LV_STYLE_MAX_WIDTH = 3, - LV_STYLE_HEIGHT = 4, - LV_STYLE_MIN_HEIGHT = 5, - LV_STYLE_MAX_HEIGHT = 6, - LV_STYLE_X = 7, - LV_STYLE_Y = 8, - LV_STYLE_ALIGN = 9, - LV_STYLE_LAYOUT = 10, - LV_STYLE_RADIUS = 11, + LV_STYLE_HEIGHT = 2, + LV_STYLE_LENGTH = 3, + + LV_STYLE_MIN_WIDTH = 4, + LV_STYLE_MAX_WIDTH = 5, + LV_STYLE_MIN_HEIGHT = 6, + LV_STYLE_MAX_HEIGHT = 7, + + LV_STYLE_X = 8, + LV_STYLE_Y = 9, + LV_STYLE_ALIGN = 10, + + LV_STYLE_RADIUS = 12, /*Group 1*/ LV_STYLE_PAD_TOP = 16, LV_STYLE_PAD_BOTTOM = 17, LV_STYLE_PAD_LEFT = 18, LV_STYLE_PAD_RIGHT = 19, + LV_STYLE_PAD_ROW = 20, LV_STYLE_PAD_COLUMN = 21, - LV_STYLE_BASE_DIR = 22, - LV_STYLE_CLIP_CORNER = 23, + LV_STYLE_LAYOUT = 22, + + LV_STYLE_MARGIN_TOP = 24, + LV_STYLE_MARGIN_BOTTOM = 25, + LV_STYLE_MARGIN_LEFT = 26, + LV_STYLE_MARGIN_RIGHT = 27, /*Group 2*/ - LV_STYLE_BG_COLOR = 32, - LV_STYLE_BG_OPA = 33, - LV_STYLE_BG_GRAD_COLOR = 34, - LV_STYLE_BG_GRAD_DIR = 35, - LV_STYLE_BG_MAIN_STOP = 36, - LV_STYLE_BG_GRAD_STOP = 37, + LV_STYLE_BG_COLOR = 28, + LV_STYLE_BG_OPA = 29, + + LV_STYLE_BG_GRAD_DIR = 32, + LV_STYLE_BG_MAIN_STOP = 33, + LV_STYLE_BG_GRAD_STOP = 34, + LV_STYLE_BG_GRAD_COLOR = 35, + + LV_STYLE_BG_MAIN_OPA = 36, + LV_STYLE_BG_GRAD_OPA = 37, LV_STYLE_BG_GRAD = 38, - LV_STYLE_BG_DITHER_MODE = 39, - LV_STYLE_BG_IMG_SRC = 40, - LV_STYLE_BG_IMG_OPA = 41, - LV_STYLE_BG_IMG_RECOLOR = 42, - LV_STYLE_BG_IMG_RECOLOR_OPA = 43, - LV_STYLE_BG_IMG_TILED = 44, + LV_STYLE_BASE_DIR = 39, + + LV_STYLE_BG_IMAGE_SRC = 40, + LV_STYLE_BG_IMAGE_OPA = 41, + LV_STYLE_BG_IMAGE_RECOLOR = 42, + LV_STYLE_BG_IMAGE_RECOLOR_OPA = 43, + + LV_STYLE_BG_IMAGE_TILED = 44, + LV_STYLE_CLIP_CORNER = 45, /*Group 3*/ - LV_STYLE_BORDER_COLOR = 48, - LV_STYLE_BORDER_OPA = 49, - LV_STYLE_BORDER_WIDTH = 50, - LV_STYLE_BORDER_SIDE = 51, - LV_STYLE_BORDER_POST = 52, - LV_STYLE_OUTLINE_WIDTH = 53, - LV_STYLE_OUTLINE_COLOR = 54, - LV_STYLE_OUTLINE_OPA = 55, - LV_STYLE_OUTLINE_PAD = 56, + LV_STYLE_BORDER_WIDTH = 48, + LV_STYLE_BORDER_COLOR = 49, + LV_STYLE_BORDER_OPA = 50, + + LV_STYLE_BORDER_SIDE = 52, + LV_STYLE_BORDER_POST = 53, + + LV_STYLE_OUTLINE_WIDTH = 56, + LV_STYLE_OUTLINE_COLOR = 57, + LV_STYLE_OUTLINE_OPA = 58, + LV_STYLE_OUTLINE_PAD = 59, /*Group 4*/ - LV_STYLE_SHADOW_WIDTH = 64, - LV_STYLE_SHADOW_OFS_X = 65, - LV_STYLE_SHADOW_OFS_Y = 66, - LV_STYLE_SHADOW_SPREAD = 67, - LV_STYLE_SHADOW_COLOR = 68, - LV_STYLE_SHADOW_OPA = 69, - LV_STYLE_IMG_OPA = 70, - LV_STYLE_IMG_RECOLOR = 71, - LV_STYLE_IMG_RECOLOR_OPA = 72, - LV_STYLE_LINE_WIDTH = 73, - LV_STYLE_LINE_DASH_WIDTH = 74, - LV_STYLE_LINE_DASH_GAP = 75, - LV_STYLE_LINE_ROUNDED = 76, - LV_STYLE_LINE_COLOR = 77, - LV_STYLE_LINE_OPA = 78, + LV_STYLE_SHADOW_WIDTH = 60, + LV_STYLE_SHADOW_COLOR = 61, + LV_STYLE_SHADOW_OPA = 62, + + LV_STYLE_SHADOW_OFFSET_X = 64, + LV_STYLE_SHADOW_OFFSET_Y = 65, + LV_STYLE_SHADOW_SPREAD = 66, + + LV_STYLE_IMAGE_OPA = 68, + LV_STYLE_IMAGE_RECOLOR = 69, + LV_STYLE_IMAGE_RECOLOR_OPA = 70, + + LV_STYLE_LINE_WIDTH = 72, + LV_STYLE_LINE_DASH_WIDTH = 73, + LV_STYLE_LINE_DASH_GAP = 74, + LV_STYLE_LINE_ROUNDED = 75, + LV_STYLE_LINE_COLOR = 76, + LV_STYLE_LINE_OPA = 77, /*Group 5*/ LV_STYLE_ARC_WIDTH = 80, LV_STYLE_ARC_ROUNDED = 81, LV_STYLE_ARC_COLOR = 82, LV_STYLE_ARC_OPA = 83, - LV_STYLE_ARC_IMG_SRC = 84, - LV_STYLE_TEXT_COLOR = 85, - LV_STYLE_TEXT_OPA = 86, - LV_STYLE_TEXT_FONT = 87, - LV_STYLE_TEXT_LETTER_SPACE = 88, - LV_STYLE_TEXT_LINE_SPACE = 89, - LV_STYLE_TEXT_DECOR = 90, - LV_STYLE_TEXT_ALIGN = 91, + LV_STYLE_ARC_IMAGE_SRC = 84, - /*Group 6*/ - LV_STYLE_OPA = 96, - LV_STYLE_OPA_LAYERED = 97, - LV_STYLE_COLOR_FILTER_DSC = 98, - LV_STYLE_COLOR_FILTER_OPA = 99, - LV_STYLE_ANIM = 100, - LV_STYLE_ANIM_TIME = 101, - LV_STYLE_ANIM_SPEED = 102, - LV_STYLE_TRANSITION = 103, - LV_STYLE_BLEND_MODE = 104, - LV_STYLE_TRANSFORM_WIDTH = 105, - LV_STYLE_TRANSFORM_HEIGHT = 106, - LV_STYLE_TRANSLATE_X = 107, - LV_STYLE_TRANSLATE_Y = 108, - LV_STYLE_TRANSFORM_ZOOM = 109, - LV_STYLE_TRANSFORM_ANGLE = 110, + LV_STYLE_TEXT_COLOR = 88, + LV_STYLE_TEXT_OPA = 89, + LV_STYLE_TEXT_FONT = 90, + + LV_STYLE_TEXT_LETTER_SPACE = 91, + LV_STYLE_TEXT_LINE_SPACE = 92, + LV_STYLE_TEXT_DECOR = 93, + LV_STYLE_TEXT_ALIGN = 94, + + LV_STYLE_OPA = 95, + LV_STYLE_OPA_LAYERED = 96, + LV_STYLE_COLOR_FILTER_DSC = 97, + LV_STYLE_COLOR_FILTER_OPA = 98, + LV_STYLE_ANIM = 99, + LV_STYLE_ANIM_DURATION = 100, + LV_STYLE_TRANSITION = 102, + LV_STYLE_BLEND_MODE = 103, + LV_STYLE_TRANSFORM_WIDTH = 104, + LV_STYLE_TRANSFORM_HEIGHT = 105, + LV_STYLE_TRANSLATE_X = 106, + LV_STYLE_TRANSLATE_Y = 107, + LV_STYLE_TRANSFORM_SCALE_X = 108, + LV_STYLE_TRANSFORM_SCALE_Y = 109, + LV_STYLE_TRANSFORM_ROTATION = 110, LV_STYLE_TRANSFORM_PIVOT_X = 111, LV_STYLE_TRANSFORM_PIVOT_Y = 112, + LV_STYLE_TRANSFORM_SKEW_X = 113, + LV_STYLE_TRANSFORM_SKEW_Y = 114, + +#if LV_USE_FLEX + LV_STYLE_FLEX_FLOW = 115, + LV_STYLE_FLEX_MAIN_PLACE = 116, + LV_STYLE_FLEX_CROSS_PLACE = 117, + LV_STYLE_FLEX_TRACK_PLACE = 118, + LV_STYLE_FLEX_GROW = 119, +#endif + +#if LV_USE_GRID + LV_STYLE_GRID_COLUMN_ALIGN = 120, + LV_STYLE_GRID_ROW_ALIGN = 121, + LV_STYLE_GRID_ROW_DSC_ARRAY = 122, + LV_STYLE_GRID_COLUMN_DSC_ARRAY = 123, + LV_STYLE_GRID_CELL_COLUMN_POS = 124, + LV_STYLE_GRID_CELL_COLUMN_SPAN = 125, + LV_STYLE_GRID_CELL_X_ALIGN = 126, + LV_STYLE_GRID_CELL_ROW_POS = 127, + LV_STYLE_GRID_CELL_ROW_SPAN = 128, + LV_STYLE_GRID_CELL_Y_ALIGN = 129, +#endif + + _LV_STYLE_LAST_BUILT_IN_PROP = 130, - _LV_STYLE_LAST_BUILT_IN_PROP = 112, _LV_STYLE_NUM_BUILT_IN_PROPS = _LV_STYLE_LAST_BUILT_IN_PROP + 1, - LV_STYLE_PROP_ANY = 0xFFFF, - _LV_STYLE_PROP_CONST = 0xFFFF /* magic value for const styles */ -} lv_style_prop_t; - -enum { - LV_STYLE_RES_NOT_FOUND, - LV_STYLE_RES_FOUND, - LV_STYLE_RES_INHERIT + LV_STYLE_PROP_ANY = 0xFF, + _LV_STYLE_PROP_CONST = 0xFF /* magic value for const styles */ }; +#ifdef DOXYGEN +typedef _lv_style_prop_t lv_style_prop_t; +#else +typedef uint8_t lv_style_prop_t; +#endif /*DOXYGEN*/ + +enum _lv_style_res_t { + LV_STYLE_RES_NOT_FOUND, + LV_STYLE_RES_FOUND, +}; + +#ifdef DOXYGEN +typedef _lv_style_res_t lv_style_res_t; +#else typedef uint8_t lv_style_res_t; +#endif /*DOXYGEN*/ /** * Descriptor for style transitions */ typedef struct { const lv_style_prop_t * props; /**< An array with the properties to animate.*/ -#if LV_USE_USER_DATA void * user_data; /**< A custom user data that will be passed to the animation's user_data */ -#endif lv_anim_path_cb_t path_xcb; /**< A path for the animation.*/ uint32_t time; /**< Duration of the transition in [ms]*/ uint32_t delay; /**< Delay before the transition in [ms]*/ @@ -309,7 +360,7 @@ typedef struct { * Descriptor of a constant style property. */ typedef struct { - lv_style_prop_t prop; + const lv_style_prop_t * prop_ptr; lv_style_value_t value; } lv_style_const_prop_t; @@ -322,24 +373,16 @@ typedef struct { uint32_t sentinel; #endif - /*If there is only one property store it directly. - *For more properties allocate an array*/ - union { - lv_style_value_t value1; - uint8_t * values_and_props; - const lv_style_const_prop_t * const_props; - } v_p; + void * values_and_props; - uint16_t prop1; - uint8_t has_group; - uint8_t prop_cnt; + uint32_t has_group; + uint8_t prop_cnt; /**< 255 means it's a constant style*/ } lv_style_t; /********************** * GLOBAL PROTOTYPES **********************/ - /** * Initialize a style * @param style pointer to a style to initialize @@ -355,6 +398,17 @@ void lv_style_init(lv_style_t * style); */ void lv_style_reset(lv_style_t * style); +/** + * Check if a style is constant + * @param style pointer to a style + * @return true: the style is constant + */ +static inline bool lv_style_is_const(const lv_style_t * style) +{ + if(style->prop_cnt == 255) return true; + return false; +} + /** * Register a new style property for custom usage * @return a new property ID, or LV_STYLE_PROP_INV if there are no more available. @@ -393,22 +447,13 @@ bool lv_style_remove_prop(lv_style_t * style, lv_style_prop_t prop); */ void lv_style_set_prop(lv_style_t * style, lv_style_prop_t prop, lv_style_value_t value); -/** - * Set a special meta state for a property in a style. - * This function shouldn't be used directly by the user. - * @param style pointer to style - * @param prop the ID of a property (e.g. `LV_STYLE_BG_COLOR`) - * @param meta the meta value to attach to the property in the style - */ -void lv_style_set_prop_meta(lv_style_t * style, lv_style_prop_t prop, uint16_t meta); - /** * Get the value of a property * @param style pointer to a style * @param prop the ID of a property * @param value pointer to a `lv_style_value_t` variable to store the value - * @return LV_RES_INV: the property wasn't found in the style (`value` is unchanged) - * LV_RES_OK: the property was fond, and `value` is set accordingly + * @return LV_RESULT_INVALID: the property wasn't found in the style (`value` is unchanged) + * LV_RESULT_OK: the property was fond, and `value` is set accordingly * @note For performance reasons there are no sanity check on `style` */ lv_style_res_t lv_style_get_prop(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value); @@ -441,57 +486,34 @@ lv_style_value_t lv_style_prop_get_default(lv_style_prop_t prop); * @param style pointer to a style * @param prop the ID of a property * @param value pointer to a `lv_style_value_t` variable to store the value - * @return LV_RES_INV: the property wasn't found in the style (`value` is unchanged) - * LV_RES_OK: the property was fond, and `value` is set accordingly + * @return LV_RESULT_INVALID: the property wasn't found in the style (`value` is unchanged) + * LV_RESULT_OK: the property was fond, and `value` is set accordingly * @note For performance reasons there are no sanity check on `style` * @note This function is the same as ::lv_style_get_prop but inlined. Use it only on performance critical places */ static inline lv_style_res_t lv_style_get_prop_inlined(const lv_style_t * style, lv_style_prop_t prop, lv_style_value_t * value) { - if(style->prop1 == LV_STYLE_PROP_ANY) { - const lv_style_const_prop_t * const_prop; + if(lv_style_is_const(style)) { + lv_style_const_prop_t * props = (lv_style_const_prop_t *)style->values_and_props; uint32_t i; - for(i = 0; i < style->prop_cnt; i++) { - const_prop = style->v_p.const_props + i; - lv_style_prop_t prop_id = LV_STYLE_PROP_ID_MASK(const_prop->prop); - if(prop_id == prop) { - if(const_prop->prop & LV_STYLE_PROP_META_INHERIT) - return LV_STYLE_RES_INHERIT; - *value = (const_prop->prop & LV_STYLE_PROP_META_INITIAL) ? lv_style_prop_get_default(prop_id) : const_prop->value; - return LV_STYLE_RES_FOUND; - } - } - return LV_STYLE_RES_NOT_FOUND; - } - - if(style->prop_cnt == 0) return LV_STYLE_RES_NOT_FOUND; - - if(style->prop_cnt > 1) { - uint8_t * tmp = style->v_p.values_and_props + style->prop_cnt * sizeof(lv_style_value_t); - uint16_t * props = (uint16_t *)tmp; - uint32_t i; - for(i = 0; i < style->prop_cnt; i++) { - lv_style_prop_t prop_id = LV_STYLE_PROP_ID_MASK(props[i]); - if(prop_id == prop) { - if(props[i] & LV_STYLE_PROP_META_INHERIT) - return LV_STYLE_RES_INHERIT; - if(props[i] & LV_STYLE_PROP_META_INITIAL) - *value = lv_style_prop_get_default(prop_id); - else { - lv_style_value_t * values = (lv_style_value_t *)style->v_p.values_and_props; - *value = values[i]; - } + for(i = 0; props[i].prop_ptr; i++) { + if(*props[i].prop_ptr == prop) { + *value = props[i].value; return LV_STYLE_RES_FOUND; } } } - else if(LV_STYLE_PROP_ID_MASK(style->prop1) == prop) { - if(style->prop1 & LV_STYLE_PROP_META_INHERIT) - return LV_STYLE_RES_INHERIT; - *value = (style->prop1 & LV_STYLE_PROP_META_INITIAL) ? lv_style_prop_get_default(LV_STYLE_PROP_ID_MASK( - style->prop1)) : style->v_p.value1; - return LV_STYLE_RES_FOUND; + else { + lv_style_prop_t * props = (lv_style_prop_t *)style->values_and_props + style->prop_cnt * sizeof(lv_style_value_t); + uint32_t i; + for(i = 0; i < style->prop_cnt; i++) { + if(props[i] == prop) { + lv_style_value_t * values = (lv_style_value_t *)style->values_and_props; + *value = values[i]; + return LV_STYLE_RES_FOUND; + } + } } return LV_STYLE_RES_NOT_FOUND; } @@ -507,9 +529,15 @@ bool lv_style_is_empty(const lv_style_t * style); * Tell the group of a property. If the a property from a group is set in a style the (1 << group) bit of style->has_group is set. * It allows early skipping the style if the property is not exists in the style at all. * @param prop a style property - * @return the group [0..7] 7 means all the custom properties with index > 112 + * @return the group [0..30] 30 means all the custom properties with index > 120 */ -uint8_t _lv_style_get_prop_group(lv_style_prop_t prop); +static inline uint32_t _lv_style_get_prop_group(lv_style_prop_t prop) +{ + uint32_t group = prop >> 2; + if(group > 30) group = 31; /*The MSB marks all the custom properties*/ + return group; + +} /** * Get the flags of a built-in or custom property. @@ -521,13 +549,13 @@ uint8_t _lv_style_prop_lookup_flags(lv_style_prop_t prop); #include "lv_style_gen.h" -static inline void lv_style_set_size(lv_style_t * style, lv_coord_t value) +static inline void lv_style_set_size(lv_style_t * style, int32_t width, int32_t height) { - lv_style_set_width(style, value); - lv_style_set_height(style, value); + lv_style_set_width(style, width); + lv_style_set_height(style, height); } -static inline void lv_style_set_pad_all(lv_style_t * style, lv_coord_t value) +static inline void lv_style_set_pad_all(lv_style_t * style, int32_t value) { lv_style_set_pad_left(style, value); lv_style_set_pad_right(style, value); @@ -535,24 +563,30 @@ static inline void lv_style_set_pad_all(lv_style_t * style, lv_coord_t value) lv_style_set_pad_bottom(style, value); } -static inline void lv_style_set_pad_hor(lv_style_t * style, lv_coord_t value) +static inline void lv_style_set_pad_hor(lv_style_t * style, int32_t value) { lv_style_set_pad_left(style, value); lv_style_set_pad_right(style, value); } -static inline void lv_style_set_pad_ver(lv_style_t * style, lv_coord_t value) +static inline void lv_style_set_pad_ver(lv_style_t * style, int32_t value) { lv_style_set_pad_top(style, value); lv_style_set_pad_bottom(style, value); } -static inline void lv_style_set_pad_gap(lv_style_t * style, lv_coord_t value) +static inline void lv_style_set_pad_gap(lv_style_t * style, int32_t value) { lv_style_set_pad_row(style, value); lv_style_set_pad_column(style, value); } +static inline void lv_style_set_transform_scale(lv_style_t * style, int32_t value) +{ + lv_style_set_transform_scale_x(style, value); + lv_style_set_transform_scale_y(style, value); +} + /** * @brief Check if the style property has a specified behavioral flag. * @@ -572,6 +606,8 @@ static inline bool lv_style_prop_has_flag(lv_style_prop_t prop, uint8_t flag) * GLOBAL VARIABLES *************************/ +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t lv_style_const_prop_id_inv; + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.c index 0b8479d29..c0aacab0b 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.c @@ -1,6 +1,14 @@ + +/* + ********************************************************************** + * DO NOT EDIT + * This file is automatically generated by "style_api_gen.py" + ********************************************************************** + */ + #include "lv_style.h" -void lv_style_set_width(lv_style_t * style, lv_coord_t value) +void lv_style_set_width(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -8,7 +16,9 @@ void lv_style_set_width(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_WIDTH, v); } -void lv_style_set_min_width(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_WIDTH = LV_STYLE_WIDTH; + +void lv_style_set_min_width(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -16,7 +26,9 @@ void lv_style_set_min_width(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_MIN_WIDTH, v); } -void lv_style_set_max_width(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_MIN_WIDTH = LV_STYLE_MIN_WIDTH; + +void lv_style_set_max_width(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -24,7 +36,9 @@ void lv_style_set_max_width(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_MAX_WIDTH, v); } -void lv_style_set_height(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_MAX_WIDTH = LV_STYLE_MAX_WIDTH; + +void lv_style_set_height(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -32,7 +46,9 @@ void lv_style_set_height(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_HEIGHT, v); } -void lv_style_set_min_height(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_HEIGHT = LV_STYLE_HEIGHT; + +void lv_style_set_min_height(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -40,7 +56,9 @@ void lv_style_set_min_height(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_MIN_HEIGHT, v); } -void lv_style_set_max_height(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_MIN_HEIGHT = LV_STYLE_MIN_HEIGHT; + +void lv_style_set_max_height(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -48,7 +66,19 @@ void lv_style_set_max_height(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_MAX_HEIGHT, v); } -void lv_style_set_x(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_MAX_HEIGHT = LV_STYLE_MAX_HEIGHT; + +void lv_style_set_length(lv_style_t * style, int32_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_LENGTH, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_LENGTH = LV_STYLE_LENGTH; + +void lv_style_set_x(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -56,7 +86,9 @@ void lv_style_set_x(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_X, v); } -void lv_style_set_y(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_X = LV_STYLE_X; + +void lv_style_set_y(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -64,6 +96,8 @@ void lv_style_set_y(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_Y, v); } +const lv_style_prop_t _lv_style_const_prop_id_Y = LV_STYLE_Y; + void lv_style_set_align(lv_style_t * style, lv_align_t value) { lv_style_value_t v = { @@ -72,7 +106,9 @@ void lv_style_set_align(lv_style_t * style, lv_align_t value) lv_style_set_prop(style, LV_STYLE_ALIGN, v); } -void lv_style_set_transform_width(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_ALIGN = LV_STYLE_ALIGN; + +void lv_style_set_transform_width(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -80,7 +116,9 @@ void lv_style_set_transform_width(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_TRANSFORM_WIDTH, v); } -void lv_style_set_transform_height(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_WIDTH = LV_STYLE_TRANSFORM_WIDTH; + +void lv_style_set_transform_height(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -88,7 +126,9 @@ void lv_style_set_transform_height(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_TRANSFORM_HEIGHT, v); } -void lv_style_set_translate_x(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_HEIGHT = LV_STYLE_TRANSFORM_HEIGHT; + +void lv_style_set_translate_x(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -96,7 +136,9 @@ void lv_style_set_translate_x(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_TRANSLATE_X, v); } -void lv_style_set_translate_y(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_TRANSLATE_X = LV_STYLE_TRANSLATE_X; + +void lv_style_set_translate_y(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -104,23 +146,39 @@ void lv_style_set_translate_y(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_TRANSLATE_Y, v); } -void lv_style_set_transform_zoom(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_TRANSLATE_Y = LV_STYLE_TRANSLATE_Y; + +void lv_style_set_transform_scale_x(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value }; - lv_style_set_prop(style, LV_STYLE_TRANSFORM_ZOOM, v); + lv_style_set_prop(style, LV_STYLE_TRANSFORM_SCALE_X, v); } -void lv_style_set_transform_angle(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_SCALE_X = LV_STYLE_TRANSFORM_SCALE_X; + +void lv_style_set_transform_scale_y(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value }; - lv_style_set_prop(style, LV_STYLE_TRANSFORM_ANGLE, v); + lv_style_set_prop(style, LV_STYLE_TRANSFORM_SCALE_Y, v); } -void lv_style_set_transform_pivot_x(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_SCALE_Y = LV_STYLE_TRANSFORM_SCALE_Y; + +void lv_style_set_transform_rotation(lv_style_t * style, int32_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_TRANSFORM_ROTATION, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_ROTATION = LV_STYLE_TRANSFORM_ROTATION; + +void lv_style_set_transform_pivot_x(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -128,7 +186,9 @@ void lv_style_set_transform_pivot_x(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_TRANSFORM_PIVOT_X, v); } -void lv_style_set_transform_pivot_y(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_PIVOT_X = LV_STYLE_TRANSFORM_PIVOT_X; + +void lv_style_set_transform_pivot_y(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -136,7 +196,29 @@ void lv_style_set_transform_pivot_y(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_TRANSFORM_PIVOT_Y, v); } -void lv_style_set_pad_top(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_PIVOT_Y = LV_STYLE_TRANSFORM_PIVOT_Y; + +void lv_style_set_transform_skew_x(lv_style_t * style, int32_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_TRANSFORM_SKEW_X, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_SKEW_X = LV_STYLE_TRANSFORM_SKEW_X; + +void lv_style_set_transform_skew_y(lv_style_t * style, int32_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_TRANSFORM_SKEW_Y, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_SKEW_Y = LV_STYLE_TRANSFORM_SKEW_Y; + +void lv_style_set_pad_top(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -144,7 +226,9 @@ void lv_style_set_pad_top(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_PAD_TOP, v); } -void lv_style_set_pad_bottom(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_PAD_TOP = LV_STYLE_PAD_TOP; + +void lv_style_set_pad_bottom(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -152,7 +236,9 @@ void lv_style_set_pad_bottom(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_PAD_BOTTOM, v); } -void lv_style_set_pad_left(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_PAD_BOTTOM = LV_STYLE_PAD_BOTTOM; + +void lv_style_set_pad_left(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -160,7 +246,9 @@ void lv_style_set_pad_left(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_PAD_LEFT, v); } -void lv_style_set_pad_right(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_PAD_LEFT = LV_STYLE_PAD_LEFT; + +void lv_style_set_pad_right(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -168,7 +256,9 @@ void lv_style_set_pad_right(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_PAD_RIGHT, v); } -void lv_style_set_pad_row(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_PAD_RIGHT = LV_STYLE_PAD_RIGHT; + +void lv_style_set_pad_row(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -176,7 +266,9 @@ void lv_style_set_pad_row(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_PAD_ROW, v); } -void lv_style_set_pad_column(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_PAD_ROW = LV_STYLE_PAD_ROW; + +void lv_style_set_pad_column(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -184,6 +276,48 @@ void lv_style_set_pad_column(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_PAD_COLUMN, v); } +const lv_style_prop_t _lv_style_const_prop_id_PAD_COLUMN = LV_STYLE_PAD_COLUMN; + +void lv_style_set_margin_top(lv_style_t * style, int32_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_MARGIN_TOP, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_MARGIN_TOP = LV_STYLE_MARGIN_TOP; + +void lv_style_set_margin_bottom(lv_style_t * style, int32_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_MARGIN_BOTTOM, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_MARGIN_BOTTOM = LV_STYLE_MARGIN_BOTTOM; + +void lv_style_set_margin_left(lv_style_t * style, int32_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_MARGIN_LEFT, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_MARGIN_LEFT = LV_STYLE_MARGIN_LEFT; + +void lv_style_set_margin_right(lv_style_t * style, int32_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_MARGIN_RIGHT, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_MARGIN_RIGHT = LV_STYLE_MARGIN_RIGHT; + void lv_style_set_bg_color(lv_style_t * style, lv_color_t value) { lv_style_value_t v = { @@ -192,6 +326,8 @@ void lv_style_set_bg_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_BG_COLOR, v); } +const lv_style_prop_t _lv_style_const_prop_id_BG_COLOR = LV_STYLE_BG_COLOR; + void lv_style_set_bg_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -200,6 +336,8 @@ void lv_style_set_bg_opa(lv_style_t * style, lv_opa_t value) lv_style_set_prop(style, LV_STYLE_BG_OPA, v); } +const lv_style_prop_t _lv_style_const_prop_id_BG_OPA = LV_STYLE_BG_OPA; + void lv_style_set_bg_grad_color(lv_style_t * style, lv_color_t value) { lv_style_value_t v = { @@ -208,6 +346,8 @@ void lv_style_set_bg_grad_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_BG_GRAD_COLOR, v); } +const lv_style_prop_t _lv_style_const_prop_id_BG_GRAD_COLOR = LV_STYLE_BG_GRAD_COLOR; + void lv_style_set_bg_grad_dir(lv_style_t * style, lv_grad_dir_t value) { lv_style_value_t v = { @@ -216,7 +356,9 @@ void lv_style_set_bg_grad_dir(lv_style_t * style, lv_grad_dir_t value) lv_style_set_prop(style, LV_STYLE_BG_GRAD_DIR, v); } -void lv_style_set_bg_main_stop(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_BG_GRAD_DIR = LV_STYLE_BG_GRAD_DIR; + +void lv_style_set_bg_main_stop(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -224,7 +366,9 @@ void lv_style_set_bg_main_stop(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_BG_MAIN_STOP, v); } -void lv_style_set_bg_grad_stop(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_BG_MAIN_STOP = LV_STYLE_BG_MAIN_STOP; + +void lv_style_set_bg_grad_stop(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -232,6 +376,28 @@ void lv_style_set_bg_grad_stop(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_BG_GRAD_STOP, v); } +const lv_style_prop_t _lv_style_const_prop_id_BG_GRAD_STOP = LV_STYLE_BG_GRAD_STOP; + +void lv_style_set_bg_main_opa(lv_style_t * style, lv_opa_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_BG_MAIN_OPA, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_BG_MAIN_OPA = LV_STYLE_BG_MAIN_OPA; + +void lv_style_set_bg_grad_opa(lv_style_t * style, lv_opa_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_BG_GRAD_OPA, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_BG_GRAD_OPA = LV_STYLE_BG_GRAD_OPA; + void lv_style_set_bg_grad(lv_style_t * style, const lv_grad_dsc_t * value) { lv_style_value_t v = { @@ -240,54 +406,58 @@ void lv_style_set_bg_grad(lv_style_t * style, const lv_grad_dsc_t * value) lv_style_set_prop(style, LV_STYLE_BG_GRAD, v); } -void lv_style_set_bg_dither_mode(lv_style_t * style, lv_dither_mode_t value) -{ - lv_style_value_t v = { - .num = (int32_t)value - }; - lv_style_set_prop(style, LV_STYLE_BG_DITHER_MODE, v); -} +const lv_style_prop_t _lv_style_const_prop_id_BG_GRAD = LV_STYLE_BG_GRAD; -void lv_style_set_bg_img_src(lv_style_t * style, const void * value) +void lv_style_set_bg_image_src(lv_style_t * style, const void * value) { lv_style_value_t v = { .ptr = value }; - lv_style_set_prop(style, LV_STYLE_BG_IMG_SRC, v); + lv_style_set_prop(style, LV_STYLE_BG_IMAGE_SRC, v); } -void lv_style_set_bg_img_opa(lv_style_t * style, lv_opa_t value) +const lv_style_prop_t _lv_style_const_prop_id_BG_IMAGE_SRC = LV_STYLE_BG_IMAGE_SRC; + +void lv_style_set_bg_image_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { .num = (int32_t)value }; - lv_style_set_prop(style, LV_STYLE_BG_IMG_OPA, v); + lv_style_set_prop(style, LV_STYLE_BG_IMAGE_OPA, v); } -void lv_style_set_bg_img_recolor(lv_style_t * style, lv_color_t value) +const lv_style_prop_t _lv_style_const_prop_id_BG_IMAGE_OPA = LV_STYLE_BG_IMAGE_OPA; + +void lv_style_set_bg_image_recolor(lv_style_t * style, lv_color_t value) { lv_style_value_t v = { .color = value }; - lv_style_set_prop(style, LV_STYLE_BG_IMG_RECOLOR, v); + lv_style_set_prop(style, LV_STYLE_BG_IMAGE_RECOLOR, v); } -void lv_style_set_bg_img_recolor_opa(lv_style_t * style, lv_opa_t value) +const lv_style_prop_t _lv_style_const_prop_id_BG_IMAGE_RECOLOR = LV_STYLE_BG_IMAGE_RECOLOR; + +void lv_style_set_bg_image_recolor_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { .num = (int32_t)value }; - lv_style_set_prop(style, LV_STYLE_BG_IMG_RECOLOR_OPA, v); + lv_style_set_prop(style, LV_STYLE_BG_IMAGE_RECOLOR_OPA, v); } -void lv_style_set_bg_img_tiled(lv_style_t * style, bool value) +const lv_style_prop_t _lv_style_const_prop_id_BG_IMAGE_RECOLOR_OPA = LV_STYLE_BG_IMAGE_RECOLOR_OPA; + +void lv_style_set_bg_image_tiled(lv_style_t * style, bool value) { lv_style_value_t v = { .num = (int32_t)value }; - lv_style_set_prop(style, LV_STYLE_BG_IMG_TILED, v); + lv_style_set_prop(style, LV_STYLE_BG_IMAGE_TILED, v); } +const lv_style_prop_t _lv_style_const_prop_id_BG_IMAGE_TILED = LV_STYLE_BG_IMAGE_TILED; + void lv_style_set_border_color(lv_style_t * style, lv_color_t value) { lv_style_value_t v = { @@ -296,6 +466,8 @@ void lv_style_set_border_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_BORDER_COLOR, v); } +const lv_style_prop_t _lv_style_const_prop_id_BORDER_COLOR = LV_STYLE_BORDER_COLOR; + void lv_style_set_border_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -304,7 +476,9 @@ void lv_style_set_border_opa(lv_style_t * style, lv_opa_t value) lv_style_set_prop(style, LV_STYLE_BORDER_OPA, v); } -void lv_style_set_border_width(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_BORDER_OPA = LV_STYLE_BORDER_OPA; + +void lv_style_set_border_width(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -312,6 +486,8 @@ void lv_style_set_border_width(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_BORDER_WIDTH, v); } +const lv_style_prop_t _lv_style_const_prop_id_BORDER_WIDTH = LV_STYLE_BORDER_WIDTH; + void lv_style_set_border_side(lv_style_t * style, lv_border_side_t value) { lv_style_value_t v = { @@ -320,6 +496,8 @@ void lv_style_set_border_side(lv_style_t * style, lv_border_side_t value) lv_style_set_prop(style, LV_STYLE_BORDER_SIDE, v); } +const lv_style_prop_t _lv_style_const_prop_id_BORDER_SIDE = LV_STYLE_BORDER_SIDE; + void lv_style_set_border_post(lv_style_t * style, bool value) { lv_style_value_t v = { @@ -328,7 +506,9 @@ void lv_style_set_border_post(lv_style_t * style, bool value) lv_style_set_prop(style, LV_STYLE_BORDER_POST, v); } -void lv_style_set_outline_width(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_BORDER_POST = LV_STYLE_BORDER_POST; + +void lv_style_set_outline_width(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -336,6 +516,8 @@ void lv_style_set_outline_width(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_OUTLINE_WIDTH, v); } +const lv_style_prop_t _lv_style_const_prop_id_OUTLINE_WIDTH = LV_STYLE_OUTLINE_WIDTH; + void lv_style_set_outline_color(lv_style_t * style, lv_color_t value) { lv_style_value_t v = { @@ -344,6 +526,8 @@ void lv_style_set_outline_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_OUTLINE_COLOR, v); } +const lv_style_prop_t _lv_style_const_prop_id_OUTLINE_COLOR = LV_STYLE_OUTLINE_COLOR; + void lv_style_set_outline_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -352,7 +536,9 @@ void lv_style_set_outline_opa(lv_style_t * style, lv_opa_t value) lv_style_set_prop(style, LV_STYLE_OUTLINE_OPA, v); } -void lv_style_set_outline_pad(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_OUTLINE_OPA = LV_STYLE_OUTLINE_OPA; + +void lv_style_set_outline_pad(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -360,7 +546,9 @@ void lv_style_set_outline_pad(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_OUTLINE_PAD, v); } -void lv_style_set_shadow_width(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_OUTLINE_PAD = LV_STYLE_OUTLINE_PAD; + +void lv_style_set_shadow_width(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -368,23 +556,29 @@ void lv_style_set_shadow_width(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_SHADOW_WIDTH, v); } -void lv_style_set_shadow_ofs_x(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_SHADOW_WIDTH = LV_STYLE_SHADOW_WIDTH; + +void lv_style_set_shadow_offset_x(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value }; - lv_style_set_prop(style, LV_STYLE_SHADOW_OFS_X, v); + lv_style_set_prop(style, LV_STYLE_SHADOW_OFFSET_X, v); } -void lv_style_set_shadow_ofs_y(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_SHADOW_OFFSET_X = LV_STYLE_SHADOW_OFFSET_X; + +void lv_style_set_shadow_offset_y(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value }; - lv_style_set_prop(style, LV_STYLE_SHADOW_OFS_Y, v); + lv_style_set_prop(style, LV_STYLE_SHADOW_OFFSET_Y, v); } -void lv_style_set_shadow_spread(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_SHADOW_OFFSET_Y = LV_STYLE_SHADOW_OFFSET_Y; + +void lv_style_set_shadow_spread(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -392,6 +586,8 @@ void lv_style_set_shadow_spread(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_SHADOW_SPREAD, v); } +const lv_style_prop_t _lv_style_const_prop_id_SHADOW_SPREAD = LV_STYLE_SHADOW_SPREAD; + void lv_style_set_shadow_color(lv_style_t * style, lv_color_t value) { lv_style_value_t v = { @@ -400,6 +596,8 @@ void lv_style_set_shadow_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_SHADOW_COLOR, v); } +const lv_style_prop_t _lv_style_const_prop_id_SHADOW_COLOR = LV_STYLE_SHADOW_COLOR; + void lv_style_set_shadow_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -408,31 +606,39 @@ void lv_style_set_shadow_opa(lv_style_t * style, lv_opa_t value) lv_style_set_prop(style, LV_STYLE_SHADOW_OPA, v); } -void lv_style_set_img_opa(lv_style_t * style, lv_opa_t value) +const lv_style_prop_t _lv_style_const_prop_id_SHADOW_OPA = LV_STYLE_SHADOW_OPA; + +void lv_style_set_image_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { .num = (int32_t)value }; - lv_style_set_prop(style, LV_STYLE_IMG_OPA, v); + lv_style_set_prop(style, LV_STYLE_IMAGE_OPA, v); } -void lv_style_set_img_recolor(lv_style_t * style, lv_color_t value) +const lv_style_prop_t _lv_style_const_prop_id_IMAGE_OPA = LV_STYLE_IMAGE_OPA; + +void lv_style_set_image_recolor(lv_style_t * style, lv_color_t value) { lv_style_value_t v = { .color = value }; - lv_style_set_prop(style, LV_STYLE_IMG_RECOLOR, v); + lv_style_set_prop(style, LV_STYLE_IMAGE_RECOLOR, v); } -void lv_style_set_img_recolor_opa(lv_style_t * style, lv_opa_t value) +const lv_style_prop_t _lv_style_const_prop_id_IMAGE_RECOLOR = LV_STYLE_IMAGE_RECOLOR; + +void lv_style_set_image_recolor_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { .num = (int32_t)value }; - lv_style_set_prop(style, LV_STYLE_IMG_RECOLOR_OPA, v); + lv_style_set_prop(style, LV_STYLE_IMAGE_RECOLOR_OPA, v); } -void lv_style_set_line_width(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_IMAGE_RECOLOR_OPA = LV_STYLE_IMAGE_RECOLOR_OPA; + +void lv_style_set_line_width(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -440,7 +646,9 @@ void lv_style_set_line_width(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_LINE_WIDTH, v); } -void lv_style_set_line_dash_width(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_LINE_WIDTH = LV_STYLE_LINE_WIDTH; + +void lv_style_set_line_dash_width(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -448,7 +656,9 @@ void lv_style_set_line_dash_width(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_LINE_DASH_WIDTH, v); } -void lv_style_set_line_dash_gap(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_LINE_DASH_WIDTH = LV_STYLE_LINE_DASH_WIDTH; + +void lv_style_set_line_dash_gap(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -456,6 +666,8 @@ void lv_style_set_line_dash_gap(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_LINE_DASH_GAP, v); } +const lv_style_prop_t _lv_style_const_prop_id_LINE_DASH_GAP = LV_STYLE_LINE_DASH_GAP; + void lv_style_set_line_rounded(lv_style_t * style, bool value) { lv_style_value_t v = { @@ -464,6 +676,8 @@ void lv_style_set_line_rounded(lv_style_t * style, bool value) lv_style_set_prop(style, LV_STYLE_LINE_ROUNDED, v); } +const lv_style_prop_t _lv_style_const_prop_id_LINE_ROUNDED = LV_STYLE_LINE_ROUNDED; + void lv_style_set_line_color(lv_style_t * style, lv_color_t value) { lv_style_value_t v = { @@ -472,6 +686,8 @@ void lv_style_set_line_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_LINE_COLOR, v); } +const lv_style_prop_t _lv_style_const_prop_id_LINE_COLOR = LV_STYLE_LINE_COLOR; + void lv_style_set_line_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -480,7 +696,9 @@ void lv_style_set_line_opa(lv_style_t * style, lv_opa_t value) lv_style_set_prop(style, LV_STYLE_LINE_OPA, v); } -void lv_style_set_arc_width(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_LINE_OPA = LV_STYLE_LINE_OPA; + +void lv_style_set_arc_width(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -488,6 +706,8 @@ void lv_style_set_arc_width(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_ARC_WIDTH, v); } +const lv_style_prop_t _lv_style_const_prop_id_ARC_WIDTH = LV_STYLE_ARC_WIDTH; + void lv_style_set_arc_rounded(lv_style_t * style, bool value) { lv_style_value_t v = { @@ -496,6 +716,8 @@ void lv_style_set_arc_rounded(lv_style_t * style, bool value) lv_style_set_prop(style, LV_STYLE_ARC_ROUNDED, v); } +const lv_style_prop_t _lv_style_const_prop_id_ARC_ROUNDED = LV_STYLE_ARC_ROUNDED; + void lv_style_set_arc_color(lv_style_t * style, lv_color_t value) { lv_style_value_t v = { @@ -504,6 +726,8 @@ void lv_style_set_arc_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_ARC_COLOR, v); } +const lv_style_prop_t _lv_style_const_prop_id_ARC_COLOR = LV_STYLE_ARC_COLOR; + void lv_style_set_arc_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -512,14 +736,18 @@ void lv_style_set_arc_opa(lv_style_t * style, lv_opa_t value) lv_style_set_prop(style, LV_STYLE_ARC_OPA, v); } -void lv_style_set_arc_img_src(lv_style_t * style, const void * value) +const lv_style_prop_t _lv_style_const_prop_id_ARC_OPA = LV_STYLE_ARC_OPA; + +void lv_style_set_arc_image_src(lv_style_t * style, const void * value) { lv_style_value_t v = { .ptr = value }; - lv_style_set_prop(style, LV_STYLE_ARC_IMG_SRC, v); + lv_style_set_prop(style, LV_STYLE_ARC_IMAGE_SRC, v); } +const lv_style_prop_t _lv_style_const_prop_id_ARC_IMAGE_SRC = LV_STYLE_ARC_IMAGE_SRC; + void lv_style_set_text_color(lv_style_t * style, lv_color_t value) { lv_style_value_t v = { @@ -528,6 +756,8 @@ void lv_style_set_text_color(lv_style_t * style, lv_color_t value) lv_style_set_prop(style, LV_STYLE_TEXT_COLOR, v); } +const lv_style_prop_t _lv_style_const_prop_id_TEXT_COLOR = LV_STYLE_TEXT_COLOR; + void lv_style_set_text_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -536,6 +766,8 @@ void lv_style_set_text_opa(lv_style_t * style, lv_opa_t value) lv_style_set_prop(style, LV_STYLE_TEXT_OPA, v); } +const lv_style_prop_t _lv_style_const_prop_id_TEXT_OPA = LV_STYLE_TEXT_OPA; + void lv_style_set_text_font(lv_style_t * style, const lv_font_t * value) { lv_style_value_t v = { @@ -544,7 +776,9 @@ void lv_style_set_text_font(lv_style_t * style, const lv_font_t * value) lv_style_set_prop(style, LV_STYLE_TEXT_FONT, v); } -void lv_style_set_text_letter_space(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_TEXT_FONT = LV_STYLE_TEXT_FONT; + +void lv_style_set_text_letter_space(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -552,7 +786,9 @@ void lv_style_set_text_letter_space(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_TEXT_LETTER_SPACE, v); } -void lv_style_set_text_line_space(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_TEXT_LETTER_SPACE = LV_STYLE_TEXT_LETTER_SPACE; + +void lv_style_set_text_line_space(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -560,6 +796,8 @@ void lv_style_set_text_line_space(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_TEXT_LINE_SPACE, v); } +const lv_style_prop_t _lv_style_const_prop_id_TEXT_LINE_SPACE = LV_STYLE_TEXT_LINE_SPACE; + void lv_style_set_text_decor(lv_style_t * style, lv_text_decor_t value) { lv_style_value_t v = { @@ -568,6 +806,8 @@ void lv_style_set_text_decor(lv_style_t * style, lv_text_decor_t value) lv_style_set_prop(style, LV_STYLE_TEXT_DECOR, v); } +const lv_style_prop_t _lv_style_const_prop_id_TEXT_DECOR = LV_STYLE_TEXT_DECOR; + void lv_style_set_text_align(lv_style_t * style, lv_text_align_t value) { lv_style_value_t v = { @@ -576,7 +816,9 @@ void lv_style_set_text_align(lv_style_t * style, lv_text_align_t value) lv_style_set_prop(style, LV_STYLE_TEXT_ALIGN, v); } -void lv_style_set_radius(lv_style_t * style, lv_coord_t value) +const lv_style_prop_t _lv_style_const_prop_id_TEXT_ALIGN = LV_STYLE_TEXT_ALIGN; + +void lv_style_set_radius(lv_style_t * style, int32_t value) { lv_style_value_t v = { .num = (int32_t)value @@ -584,6 +826,8 @@ void lv_style_set_radius(lv_style_t * style, lv_coord_t value) lv_style_set_prop(style, LV_STYLE_RADIUS, v); } +const lv_style_prop_t _lv_style_const_prop_id_RADIUS = LV_STYLE_RADIUS; + void lv_style_set_clip_corner(lv_style_t * style, bool value) { lv_style_value_t v = { @@ -592,6 +836,8 @@ void lv_style_set_clip_corner(lv_style_t * style, bool value) lv_style_set_prop(style, LV_STYLE_CLIP_CORNER, v); } +const lv_style_prop_t _lv_style_const_prop_id_CLIP_CORNER = LV_STYLE_CLIP_CORNER; + void lv_style_set_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -600,6 +846,8 @@ void lv_style_set_opa(lv_style_t * style, lv_opa_t value) lv_style_set_prop(style, LV_STYLE_OPA, v); } +const lv_style_prop_t _lv_style_const_prop_id_OPA = LV_STYLE_OPA; + void lv_style_set_opa_layered(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -608,6 +856,8 @@ void lv_style_set_opa_layered(lv_style_t * style, lv_opa_t value) lv_style_set_prop(style, LV_STYLE_OPA_LAYERED, v); } +const lv_style_prop_t _lv_style_const_prop_id_OPA_LAYERED = LV_STYLE_OPA_LAYERED; + void lv_style_set_color_filter_dsc(lv_style_t * style, const lv_color_filter_dsc_t * value) { lv_style_value_t v = { @@ -616,6 +866,8 @@ void lv_style_set_color_filter_dsc(lv_style_t * style, const lv_color_filter_dsc lv_style_set_prop(style, LV_STYLE_COLOR_FILTER_DSC, v); } +const lv_style_prop_t _lv_style_const_prop_id_COLOR_FILTER_DSC = LV_STYLE_COLOR_FILTER_DSC; + void lv_style_set_color_filter_opa(lv_style_t * style, lv_opa_t value) { lv_style_value_t v = { @@ -624,6 +876,8 @@ void lv_style_set_color_filter_opa(lv_style_t * style, lv_opa_t value) lv_style_set_prop(style, LV_STYLE_COLOR_FILTER_OPA, v); } +const lv_style_prop_t _lv_style_const_prop_id_COLOR_FILTER_OPA = LV_STYLE_COLOR_FILTER_OPA; + void lv_style_set_anim(lv_style_t * style, const lv_anim_t * value) { lv_style_value_t v = { @@ -632,21 +886,17 @@ void lv_style_set_anim(lv_style_t * style, const lv_anim_t * value) lv_style_set_prop(style, LV_STYLE_ANIM, v); } -void lv_style_set_anim_time(lv_style_t * style, uint32_t value) +const lv_style_prop_t _lv_style_const_prop_id_ANIM = LV_STYLE_ANIM; + +void lv_style_set_anim_duration(lv_style_t * style, uint32_t value) { lv_style_value_t v = { .num = (int32_t)value }; - lv_style_set_prop(style, LV_STYLE_ANIM_TIME, v); + lv_style_set_prop(style, LV_STYLE_ANIM_DURATION, v); } -void lv_style_set_anim_speed(lv_style_t * style, uint32_t value) -{ - lv_style_value_t v = { - .num = (int32_t)value - }; - lv_style_set_prop(style, LV_STYLE_ANIM_SPEED, v); -} +const lv_style_prop_t _lv_style_const_prop_id_ANIM_DURATION = LV_STYLE_ANIM_DURATION; void lv_style_set_transition(lv_style_t * style, const lv_style_transition_dsc_t * value) { @@ -656,6 +906,8 @@ void lv_style_set_transition(lv_style_t * style, const lv_style_transition_dsc_t lv_style_set_prop(style, LV_STYLE_TRANSITION, v); } +const lv_style_prop_t _lv_style_const_prop_id_TRANSITION = LV_STYLE_TRANSITION; + void lv_style_set_blend_mode(lv_style_t * style, lv_blend_mode_t value) { lv_style_value_t v = { @@ -664,6 +916,8 @@ void lv_style_set_blend_mode(lv_style_t * style, lv_blend_mode_t value) lv_style_set_prop(style, LV_STYLE_BLEND_MODE, v); } +const lv_style_prop_t _lv_style_const_prop_id_BLEND_MODE = LV_STYLE_BLEND_MODE; + void lv_style_set_layout(lv_style_t * style, uint16_t value) { lv_style_value_t v = { @@ -672,6 +926,8 @@ void lv_style_set_layout(lv_style_t * style, uint16_t value) lv_style_set_prop(style, LV_STYLE_LAYOUT, v); } +const lv_style_prop_t _lv_style_const_prop_id_LAYOUT = LV_STYLE_LAYOUT; + void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value) { lv_style_value_t v = { @@ -679,3 +935,160 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value) }; lv_style_set_prop(style, LV_STYLE_BASE_DIR, v); } + +const lv_style_prop_t _lv_style_const_prop_id_BASE_DIR = LV_STYLE_BASE_DIR; +#if LV_USE_FLEX + +void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_FLEX_FLOW, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_FLEX_FLOW = LV_STYLE_FLEX_FLOW; + +void lv_style_set_flex_main_place(lv_style_t * style, lv_flex_align_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_FLEX_MAIN_PLACE, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_FLEX_MAIN_PLACE = LV_STYLE_FLEX_MAIN_PLACE; + +void lv_style_set_flex_cross_place(lv_style_t * style, lv_flex_align_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_FLEX_CROSS_PLACE, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_FLEX_CROSS_PLACE = LV_STYLE_FLEX_CROSS_PLACE; + +void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_FLEX_TRACK_PLACE, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_FLEX_TRACK_PLACE = LV_STYLE_FLEX_TRACK_PLACE; + +void lv_style_set_flex_grow(lv_style_t * style, uint8_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_FLEX_GROW, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_FLEX_GROW = LV_STYLE_FLEX_GROW; +#endif /*LV_USE_FLEX*/ + +#if LV_USE_GRID + +void lv_style_set_grid_column_dsc_array(lv_style_t * style, const int32_t * value) +{ + lv_style_value_t v = { + .ptr = value + }; + lv_style_set_prop(style, LV_STYLE_GRID_COLUMN_DSC_ARRAY, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_GRID_COLUMN_DSC_ARRAY = LV_STYLE_GRID_COLUMN_DSC_ARRAY; + +void lv_style_set_grid_column_align(lv_style_t * style, lv_grid_align_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_GRID_COLUMN_ALIGN, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_GRID_COLUMN_ALIGN = LV_STYLE_GRID_COLUMN_ALIGN; + +void lv_style_set_grid_row_dsc_array(lv_style_t * style, const int32_t * value) +{ + lv_style_value_t v = { + .ptr = value + }; + lv_style_set_prop(style, LV_STYLE_GRID_ROW_DSC_ARRAY, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_GRID_ROW_DSC_ARRAY = LV_STYLE_GRID_ROW_DSC_ARRAY; + +void lv_style_set_grid_row_align(lv_style_t * style, lv_grid_align_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_GRID_ROW_ALIGN, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_GRID_ROW_ALIGN = LV_STYLE_GRID_ROW_ALIGN; + +void lv_style_set_grid_cell_column_pos(lv_style_t * style, int32_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_GRID_CELL_COLUMN_POS, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_GRID_CELL_COLUMN_POS = LV_STYLE_GRID_CELL_COLUMN_POS; + +void lv_style_set_grid_cell_x_align(lv_style_t * style, lv_grid_align_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_GRID_CELL_X_ALIGN, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_GRID_CELL_X_ALIGN = LV_STYLE_GRID_CELL_X_ALIGN; + +void lv_style_set_grid_cell_column_span(lv_style_t * style, int32_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_GRID_CELL_COLUMN_SPAN, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_GRID_CELL_COLUMN_SPAN = LV_STYLE_GRID_CELL_COLUMN_SPAN; + +void lv_style_set_grid_cell_row_pos(lv_style_t * style, int32_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_GRID_CELL_ROW_POS, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_GRID_CELL_ROW_POS = LV_STYLE_GRID_CELL_ROW_POS; + +void lv_style_set_grid_cell_y_align(lv_style_t * style, lv_grid_align_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_GRID_CELL_Y_ALIGN, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_GRID_CELL_Y_ALIGN = LV_STYLE_GRID_CELL_Y_ALIGN; + +void lv_style_set_grid_cell_row_span(lv_style_t * style, int32_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_GRID_CELL_ROW_SPAN, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_GRID_CELL_ROW_SPAN = LV_STYLE_GRID_CELL_ROW_SPAN; +#endif /*LV_USE_GRID*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.h index 66ba068c8..f02553f87 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_style_gen.h @@ -1,510 +1,781 @@ -void lv_style_set_width(lv_style_t * style, lv_coord_t value); -void lv_style_set_min_width(lv_style_t * style, lv_coord_t value); -void lv_style_set_max_width(lv_style_t * style, lv_coord_t value); -void lv_style_set_height(lv_style_t * style, lv_coord_t value); -void lv_style_set_min_height(lv_style_t * style, lv_coord_t value); -void lv_style_set_max_height(lv_style_t * style, lv_coord_t value); -void lv_style_set_x(lv_style_t * style, lv_coord_t value); -void lv_style_set_y(lv_style_t * style, lv_coord_t value); + +/* + ********************************************************************** + * DO NOT EDIT + * This file is automatically generated by "style_api_gen.py" + ********************************************************************** + */ + +#ifndef LV_STYLE_GEN_H +#define LV_STYLE_GEN_H + +void lv_style_set_width(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_WIDTH; +void lv_style_set_min_width(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_MIN_WIDTH; +void lv_style_set_max_width(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_MAX_WIDTH; +void lv_style_set_height(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_HEIGHT; +void lv_style_set_min_height(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_MIN_HEIGHT; +void lv_style_set_max_height(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_MAX_HEIGHT; +void lv_style_set_length(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_LENGTH; +void lv_style_set_x(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_X; +void lv_style_set_y(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_Y; void lv_style_set_align(lv_style_t * style, lv_align_t value); -void lv_style_set_transform_width(lv_style_t * style, lv_coord_t value); -void lv_style_set_transform_height(lv_style_t * style, lv_coord_t value); -void lv_style_set_translate_x(lv_style_t * style, lv_coord_t value); -void lv_style_set_translate_y(lv_style_t * style, lv_coord_t value); -void lv_style_set_transform_zoom(lv_style_t * style, lv_coord_t value); -void lv_style_set_transform_angle(lv_style_t * style, lv_coord_t value); -void lv_style_set_transform_pivot_x(lv_style_t * style, lv_coord_t value); -void lv_style_set_transform_pivot_y(lv_style_t * style, lv_coord_t value); -void lv_style_set_pad_top(lv_style_t * style, lv_coord_t value); -void lv_style_set_pad_bottom(lv_style_t * style, lv_coord_t value); -void lv_style_set_pad_left(lv_style_t * style, lv_coord_t value); -void lv_style_set_pad_right(lv_style_t * style, lv_coord_t value); -void lv_style_set_pad_row(lv_style_t * style, lv_coord_t value); -void lv_style_set_pad_column(lv_style_t * style, lv_coord_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_ALIGN; +void lv_style_set_transform_width(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_WIDTH; +void lv_style_set_transform_height(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_HEIGHT; +void lv_style_set_translate_x(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TRANSLATE_X; +void lv_style_set_translate_y(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TRANSLATE_Y; +void lv_style_set_transform_scale_x(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_SCALE_X; +void lv_style_set_transform_scale_y(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_SCALE_Y; +void lv_style_set_transform_rotation(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_ROTATION; +void lv_style_set_transform_pivot_x(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_PIVOT_X; +void lv_style_set_transform_pivot_y(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_PIVOT_Y; +void lv_style_set_transform_skew_x(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_SKEW_X; +void lv_style_set_transform_skew_y(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TRANSFORM_SKEW_Y; +void lv_style_set_pad_top(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_PAD_TOP; +void lv_style_set_pad_bottom(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_PAD_BOTTOM; +void lv_style_set_pad_left(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_PAD_LEFT; +void lv_style_set_pad_right(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_PAD_RIGHT; +void lv_style_set_pad_row(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_PAD_ROW; +void lv_style_set_pad_column(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_PAD_COLUMN; +void lv_style_set_margin_top(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_MARGIN_TOP; +void lv_style_set_margin_bottom(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_MARGIN_BOTTOM; +void lv_style_set_margin_left(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_MARGIN_LEFT; +void lv_style_set_margin_right(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_MARGIN_RIGHT; void lv_style_set_bg_color(lv_style_t * style, lv_color_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BG_COLOR; void lv_style_set_bg_opa(lv_style_t * style, lv_opa_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BG_OPA; void lv_style_set_bg_grad_color(lv_style_t * style, lv_color_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BG_GRAD_COLOR; void lv_style_set_bg_grad_dir(lv_style_t * style, lv_grad_dir_t value); -void lv_style_set_bg_main_stop(lv_style_t * style, lv_coord_t value); -void lv_style_set_bg_grad_stop(lv_style_t * style, lv_coord_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BG_GRAD_DIR; +void lv_style_set_bg_main_stop(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BG_MAIN_STOP; +void lv_style_set_bg_grad_stop(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BG_GRAD_STOP; +void lv_style_set_bg_main_opa(lv_style_t * style, lv_opa_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BG_MAIN_OPA; +void lv_style_set_bg_grad_opa(lv_style_t * style, lv_opa_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BG_GRAD_OPA; void lv_style_set_bg_grad(lv_style_t * style, const lv_grad_dsc_t * value); -void lv_style_set_bg_dither_mode(lv_style_t * style, lv_dither_mode_t value); -void lv_style_set_bg_img_src(lv_style_t * style, const void * value); -void lv_style_set_bg_img_opa(lv_style_t * style, lv_opa_t value); -void lv_style_set_bg_img_recolor(lv_style_t * style, lv_color_t value); -void lv_style_set_bg_img_recolor_opa(lv_style_t * style, lv_opa_t value); -void lv_style_set_bg_img_tiled(lv_style_t * style, bool value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BG_GRAD; +void lv_style_set_bg_image_src(lv_style_t * style, const void * value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BG_IMAGE_SRC; +void lv_style_set_bg_image_opa(lv_style_t * style, lv_opa_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BG_IMAGE_OPA; +void lv_style_set_bg_image_recolor(lv_style_t * style, lv_color_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BG_IMAGE_RECOLOR; +void lv_style_set_bg_image_recolor_opa(lv_style_t * style, lv_opa_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BG_IMAGE_RECOLOR_OPA; +void lv_style_set_bg_image_tiled(lv_style_t * style, bool value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BG_IMAGE_TILED; void lv_style_set_border_color(lv_style_t * style, lv_color_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BORDER_COLOR; void lv_style_set_border_opa(lv_style_t * style, lv_opa_t value); -void lv_style_set_border_width(lv_style_t * style, lv_coord_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BORDER_OPA; +void lv_style_set_border_width(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BORDER_WIDTH; void lv_style_set_border_side(lv_style_t * style, lv_border_side_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BORDER_SIDE; void lv_style_set_border_post(lv_style_t * style, bool value); -void lv_style_set_outline_width(lv_style_t * style, lv_coord_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BORDER_POST; +void lv_style_set_outline_width(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_OUTLINE_WIDTH; void lv_style_set_outline_color(lv_style_t * style, lv_color_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_OUTLINE_COLOR; void lv_style_set_outline_opa(lv_style_t * style, lv_opa_t value); -void lv_style_set_outline_pad(lv_style_t * style, lv_coord_t value); -void lv_style_set_shadow_width(lv_style_t * style, lv_coord_t value); -void lv_style_set_shadow_ofs_x(lv_style_t * style, lv_coord_t value); -void lv_style_set_shadow_ofs_y(lv_style_t * style, lv_coord_t value); -void lv_style_set_shadow_spread(lv_style_t * style, lv_coord_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_OUTLINE_OPA; +void lv_style_set_outline_pad(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_OUTLINE_PAD; +void lv_style_set_shadow_width(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_SHADOW_WIDTH; +void lv_style_set_shadow_offset_x(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_SHADOW_OFFSET_X; +void lv_style_set_shadow_offset_y(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_SHADOW_OFFSET_Y; +void lv_style_set_shadow_spread(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_SHADOW_SPREAD; void lv_style_set_shadow_color(lv_style_t * style, lv_color_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_SHADOW_COLOR; void lv_style_set_shadow_opa(lv_style_t * style, lv_opa_t value); -void lv_style_set_img_opa(lv_style_t * style, lv_opa_t value); -void lv_style_set_img_recolor(lv_style_t * style, lv_color_t value); -void lv_style_set_img_recolor_opa(lv_style_t * style, lv_opa_t value); -void lv_style_set_line_width(lv_style_t * style, lv_coord_t value); -void lv_style_set_line_dash_width(lv_style_t * style, lv_coord_t value); -void lv_style_set_line_dash_gap(lv_style_t * style, lv_coord_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_SHADOW_OPA; +void lv_style_set_image_opa(lv_style_t * style, lv_opa_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_IMAGE_OPA; +void lv_style_set_image_recolor(lv_style_t * style, lv_color_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_IMAGE_RECOLOR; +void lv_style_set_image_recolor_opa(lv_style_t * style, lv_opa_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_IMAGE_RECOLOR_OPA; +void lv_style_set_line_width(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_LINE_WIDTH; +void lv_style_set_line_dash_width(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_LINE_DASH_WIDTH; +void lv_style_set_line_dash_gap(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_LINE_DASH_GAP; void lv_style_set_line_rounded(lv_style_t * style, bool value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_LINE_ROUNDED; void lv_style_set_line_color(lv_style_t * style, lv_color_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_LINE_COLOR; void lv_style_set_line_opa(lv_style_t * style, lv_opa_t value); -void lv_style_set_arc_width(lv_style_t * style, lv_coord_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_LINE_OPA; +void lv_style_set_arc_width(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_ARC_WIDTH; void lv_style_set_arc_rounded(lv_style_t * style, bool value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_ARC_ROUNDED; void lv_style_set_arc_color(lv_style_t * style, lv_color_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_ARC_COLOR; void lv_style_set_arc_opa(lv_style_t * style, lv_opa_t value); -void lv_style_set_arc_img_src(lv_style_t * style, const void * value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_ARC_OPA; +void lv_style_set_arc_image_src(lv_style_t * style, const void * value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_ARC_IMAGE_SRC; void lv_style_set_text_color(lv_style_t * style, lv_color_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TEXT_COLOR; void lv_style_set_text_opa(lv_style_t * style, lv_opa_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TEXT_OPA; void lv_style_set_text_font(lv_style_t * style, const lv_font_t * value); -void lv_style_set_text_letter_space(lv_style_t * style, lv_coord_t value); -void lv_style_set_text_line_space(lv_style_t * style, lv_coord_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TEXT_FONT; +void lv_style_set_text_letter_space(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TEXT_LETTER_SPACE; +void lv_style_set_text_line_space(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TEXT_LINE_SPACE; void lv_style_set_text_decor(lv_style_t * style, lv_text_decor_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TEXT_DECOR; void lv_style_set_text_align(lv_style_t * style, lv_text_align_t value); -void lv_style_set_radius(lv_style_t * style, lv_coord_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TEXT_ALIGN; +void lv_style_set_radius(lv_style_t * style, int32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_RADIUS; void lv_style_set_clip_corner(lv_style_t * style, bool value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_CLIP_CORNER; void lv_style_set_opa(lv_style_t * style, lv_opa_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_OPA; void lv_style_set_opa_layered(lv_style_t * style, lv_opa_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_OPA_LAYERED; void lv_style_set_color_filter_dsc(lv_style_t * style, const lv_color_filter_dsc_t * value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_COLOR_FILTER_DSC; void lv_style_set_color_filter_opa(lv_style_t * style, lv_opa_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_COLOR_FILTER_OPA; void lv_style_set_anim(lv_style_t * style, const lv_anim_t * value); -void lv_style_set_anim_time(lv_style_t * style, uint32_t value); -void lv_style_set_anim_speed(lv_style_t * style, uint32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_ANIM; +void lv_style_set_anim_duration(lv_style_t * style, uint32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_ANIM_DURATION; void lv_style_set_transition(lv_style_t * style, const lv_style_transition_dsc_t * value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_TRANSITION; void lv_style_set_blend_mode(lv_style_t * style, lv_blend_mode_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BLEND_MODE; void lv_style_set_layout(lv_style_t * style, uint16_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_LAYOUT; void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BASE_DIR; +#if LV_USE_FLEX + + void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value); + LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_FLEX_FLOW; + void lv_style_set_flex_main_place(lv_style_t * style, lv_flex_align_t value); + LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_FLEX_MAIN_PLACE; + void lv_style_set_flex_cross_place(lv_style_t * style, lv_flex_align_t value); + LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_FLEX_CROSS_PLACE; + void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value); + LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_FLEX_TRACK_PLACE; + void lv_style_set_flex_grow(lv_style_t * style, uint8_t value); + LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_FLEX_GROW; +#endif /*LV_USE_FLEX*/ + +#if LV_USE_GRID + + void lv_style_set_grid_column_dsc_array(lv_style_t * style, const int32_t * value); + LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_GRID_COLUMN_DSC_ARRAY; + void lv_style_set_grid_column_align(lv_style_t * style, lv_grid_align_t value); + LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_GRID_COLUMN_ALIGN; + void lv_style_set_grid_row_dsc_array(lv_style_t * style, const int32_t * value); + LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_GRID_ROW_DSC_ARRAY; + void lv_style_set_grid_row_align(lv_style_t * style, lv_grid_align_t value); + LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_GRID_ROW_ALIGN; + void lv_style_set_grid_cell_column_pos(lv_style_t * style, int32_t value); + LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_GRID_CELL_COLUMN_POS; + void lv_style_set_grid_cell_x_align(lv_style_t * style, lv_grid_align_t value); + LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_GRID_CELL_X_ALIGN; + void lv_style_set_grid_cell_column_span(lv_style_t * style, int32_t value); + LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_GRID_CELL_COLUMN_SPAN; + void lv_style_set_grid_cell_row_pos(lv_style_t * style, int32_t value); + LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_GRID_CELL_ROW_POS; + void lv_style_set_grid_cell_y_align(lv_style_t * style, lv_grid_align_t value); + LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_GRID_CELL_Y_ALIGN; + void lv_style_set_grid_cell_row_span(lv_style_t * style, int32_t value); + LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_GRID_CELL_ROW_SPAN; +#endif /*LV_USE_GRID*/ #define LV_STYLE_CONST_WIDTH(val) \ { \ - .prop = LV_STYLE_WIDTH, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_WIDTH, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_MIN_WIDTH(val) \ { \ - .prop = LV_STYLE_MIN_WIDTH, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_MIN_WIDTH, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_MAX_WIDTH(val) \ { \ - .prop = LV_STYLE_MAX_WIDTH, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_MAX_WIDTH, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_HEIGHT(val) \ { \ - .prop = LV_STYLE_HEIGHT, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_HEIGHT, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_MIN_HEIGHT(val) \ { \ - .prop = LV_STYLE_MIN_HEIGHT, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_MIN_HEIGHT, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_MAX_HEIGHT(val) \ { \ - .prop = LV_STYLE_MAX_HEIGHT, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_MAX_HEIGHT, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_LENGTH(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_LENGTH, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_X(val) \ { \ - .prop = LV_STYLE_X, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_X, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_Y(val) \ { \ - .prop = LV_STYLE_Y, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_Y, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_ALIGN(val) \ { \ - .prop = LV_STYLE_ALIGN, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_ALIGN, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_TRANSFORM_WIDTH(val) \ { \ - .prop = LV_STYLE_TRANSFORM_WIDTH, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_TRANSFORM_WIDTH, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_TRANSFORM_HEIGHT(val) \ { \ - .prop = LV_STYLE_TRANSFORM_HEIGHT, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_TRANSFORM_HEIGHT, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_TRANSLATE_X(val) \ { \ - .prop = LV_STYLE_TRANSLATE_X, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_TRANSLATE_X, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_TRANSLATE_Y(val) \ { \ - .prop = LV_STYLE_TRANSLATE_Y, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_TRANSLATE_Y, .value = { .num = (int32_t)val } \ } -#define LV_STYLE_CONST_TRANSFORM_ZOOM(val) \ +#define LV_STYLE_CONST_TRANSFORM_SCALE_X(val) \ { \ - .prop = LV_STYLE_TRANSFORM_ZOOM, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_TRANSFORM_SCALE_X, .value = { .num = (int32_t)val } \ } -#define LV_STYLE_CONST_TRANSFORM_ANGLE(val) \ +#define LV_STYLE_CONST_TRANSFORM_SCALE_Y(val) \ { \ - .prop = LV_STYLE_TRANSFORM_ANGLE, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_TRANSFORM_SCALE_Y, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_TRANSFORM_ROTATION(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_TRANSFORM_ROTATION, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_TRANSFORM_PIVOT_X(val) \ { \ - .prop = LV_STYLE_TRANSFORM_PIVOT_X, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_TRANSFORM_PIVOT_X, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_TRANSFORM_PIVOT_Y(val) \ { \ - .prop = LV_STYLE_TRANSFORM_PIVOT_Y, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_TRANSFORM_PIVOT_Y, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_TRANSFORM_SKEW_X(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_TRANSFORM_SKEW_X, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_TRANSFORM_SKEW_Y(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_TRANSFORM_SKEW_Y, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_PAD_TOP(val) \ { \ - .prop = LV_STYLE_PAD_TOP, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_PAD_TOP, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_PAD_BOTTOM(val) \ { \ - .prop = LV_STYLE_PAD_BOTTOM, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_PAD_BOTTOM, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_PAD_LEFT(val) \ { \ - .prop = LV_STYLE_PAD_LEFT, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_PAD_LEFT, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_PAD_RIGHT(val) \ { \ - .prop = LV_STYLE_PAD_RIGHT, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_PAD_RIGHT, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_PAD_ROW(val) \ { \ - .prop = LV_STYLE_PAD_ROW, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_PAD_ROW, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_PAD_COLUMN(val) \ { \ - .prop = LV_STYLE_PAD_COLUMN, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_PAD_COLUMN, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_MARGIN_TOP(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_MARGIN_TOP, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_MARGIN_BOTTOM(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_MARGIN_BOTTOM, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_MARGIN_LEFT(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_MARGIN_LEFT, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_MARGIN_RIGHT(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_MARGIN_RIGHT, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_BG_COLOR(val) \ { \ - .prop = LV_STYLE_BG_COLOR, .value = { .color = val } \ + .prop_ptr = &_lv_style_const_prop_id_BG_COLOR, .value = { .color = val } \ } #define LV_STYLE_CONST_BG_OPA(val) \ { \ - .prop = LV_STYLE_BG_OPA, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_BG_OPA, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_BG_GRAD_COLOR(val) \ { \ - .prop = LV_STYLE_BG_GRAD_COLOR, .value = { .color = val } \ + .prop_ptr = &_lv_style_const_prop_id_BG_GRAD_COLOR, .value = { .color = val } \ } #define LV_STYLE_CONST_BG_GRAD_DIR(val) \ { \ - .prop = LV_STYLE_BG_GRAD_DIR, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_BG_GRAD_DIR, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_BG_MAIN_STOP(val) \ { \ - .prop = LV_STYLE_BG_MAIN_STOP, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_BG_MAIN_STOP, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_BG_GRAD_STOP(val) \ { \ - .prop = LV_STYLE_BG_GRAD_STOP, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_BG_GRAD_STOP, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_BG_MAIN_OPA(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_BG_MAIN_OPA, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_BG_GRAD_OPA(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_BG_GRAD_OPA, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_BG_GRAD(val) \ { \ - .prop = LV_STYLE_BG_GRAD, .value = { .ptr = val } \ + .prop_ptr = &_lv_style_const_prop_id_BG_GRAD, .value = { .ptr = val } \ } -#define LV_STYLE_CONST_BG_DITHER_MODE(val) \ +#define LV_STYLE_CONST_BG_IMAGE_SRC(val) \ { \ - .prop = LV_STYLE_BG_DITHER_MODE, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_BG_IMAGE_SRC, .value = { .ptr = val } \ } -#define LV_STYLE_CONST_BG_IMG_SRC(val) \ +#define LV_STYLE_CONST_BG_IMAGE_OPA(val) \ { \ - .prop = LV_STYLE_BG_IMG_SRC, .value = { .ptr = val } \ + .prop_ptr = &_lv_style_const_prop_id_BG_IMAGE_OPA, .value = { .num = (int32_t)val } \ } -#define LV_STYLE_CONST_BG_IMG_OPA(val) \ +#define LV_STYLE_CONST_BG_IMAGE_RECOLOR(val) \ { \ - .prop = LV_STYLE_BG_IMG_OPA, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_BG_IMAGE_RECOLOR, .value = { .color = val } \ } -#define LV_STYLE_CONST_BG_IMG_RECOLOR(val) \ +#define LV_STYLE_CONST_BG_IMAGE_RECOLOR_OPA(val) \ { \ - .prop = LV_STYLE_BG_IMG_RECOLOR, .value = { .color = val } \ + .prop_ptr = &_lv_style_const_prop_id_BG_IMAGE_RECOLOR_OPA, .value = { .num = (int32_t)val } \ } -#define LV_STYLE_CONST_BG_IMG_RECOLOR_OPA(val) \ +#define LV_STYLE_CONST_BG_IMAGE_TILED(val) \ { \ - .prop = LV_STYLE_BG_IMG_RECOLOR_OPA, .value = { .num = (int32_t)val } \ - } - -#define LV_STYLE_CONST_BG_IMG_TILED(val) \ - { \ - .prop = LV_STYLE_BG_IMG_TILED, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_BG_IMAGE_TILED, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_BORDER_COLOR(val) \ { \ - .prop = LV_STYLE_BORDER_COLOR, .value = { .color = val } \ + .prop_ptr = &_lv_style_const_prop_id_BORDER_COLOR, .value = { .color = val } \ } #define LV_STYLE_CONST_BORDER_OPA(val) \ { \ - .prop = LV_STYLE_BORDER_OPA, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_BORDER_OPA, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_BORDER_WIDTH(val) \ { \ - .prop = LV_STYLE_BORDER_WIDTH, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_BORDER_WIDTH, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_BORDER_SIDE(val) \ { \ - .prop = LV_STYLE_BORDER_SIDE, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_BORDER_SIDE, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_BORDER_POST(val) \ { \ - .prop = LV_STYLE_BORDER_POST, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_BORDER_POST, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_OUTLINE_WIDTH(val) \ { \ - .prop = LV_STYLE_OUTLINE_WIDTH, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_OUTLINE_WIDTH, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_OUTLINE_COLOR(val) \ { \ - .prop = LV_STYLE_OUTLINE_COLOR, .value = { .color = val } \ + .prop_ptr = &_lv_style_const_prop_id_OUTLINE_COLOR, .value = { .color = val } \ } #define LV_STYLE_CONST_OUTLINE_OPA(val) \ { \ - .prop = LV_STYLE_OUTLINE_OPA, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_OUTLINE_OPA, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_OUTLINE_PAD(val) \ { \ - .prop = LV_STYLE_OUTLINE_PAD, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_OUTLINE_PAD, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_SHADOW_WIDTH(val) \ { \ - .prop = LV_STYLE_SHADOW_WIDTH, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_SHADOW_WIDTH, .value = { .num = (int32_t)val } \ } -#define LV_STYLE_CONST_SHADOW_OFS_X(val) \ +#define LV_STYLE_CONST_SHADOW_OFFSET_X(val) \ { \ - .prop = LV_STYLE_SHADOW_OFS_X, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_SHADOW_OFFSET_X, .value = { .num = (int32_t)val } \ } -#define LV_STYLE_CONST_SHADOW_OFS_Y(val) \ +#define LV_STYLE_CONST_SHADOW_OFFSET_Y(val) \ { \ - .prop = LV_STYLE_SHADOW_OFS_Y, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_SHADOW_OFFSET_Y, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_SHADOW_SPREAD(val) \ { \ - .prop = LV_STYLE_SHADOW_SPREAD, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_SHADOW_SPREAD, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_SHADOW_COLOR(val) \ { \ - .prop = LV_STYLE_SHADOW_COLOR, .value = { .color = val } \ + .prop_ptr = &_lv_style_const_prop_id_SHADOW_COLOR, .value = { .color = val } \ } #define LV_STYLE_CONST_SHADOW_OPA(val) \ { \ - .prop = LV_STYLE_SHADOW_OPA, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_SHADOW_OPA, .value = { .num = (int32_t)val } \ } -#define LV_STYLE_CONST_IMG_OPA(val) \ +#define LV_STYLE_CONST_IMAGE_OPA(val) \ { \ - .prop = LV_STYLE_IMG_OPA, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_IMAGE_OPA, .value = { .num = (int32_t)val } \ } -#define LV_STYLE_CONST_IMG_RECOLOR(val) \ +#define LV_STYLE_CONST_IMAGE_RECOLOR(val) \ { \ - .prop = LV_STYLE_IMG_RECOLOR, .value = { .color = val } \ + .prop_ptr = &_lv_style_const_prop_id_IMAGE_RECOLOR, .value = { .color = val } \ } -#define LV_STYLE_CONST_IMG_RECOLOR_OPA(val) \ +#define LV_STYLE_CONST_IMAGE_RECOLOR_OPA(val) \ { \ - .prop = LV_STYLE_IMG_RECOLOR_OPA, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_IMAGE_RECOLOR_OPA, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_LINE_WIDTH(val) \ { \ - .prop = LV_STYLE_LINE_WIDTH, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_LINE_WIDTH, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_LINE_DASH_WIDTH(val) \ { \ - .prop = LV_STYLE_LINE_DASH_WIDTH, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_LINE_DASH_WIDTH, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_LINE_DASH_GAP(val) \ { \ - .prop = LV_STYLE_LINE_DASH_GAP, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_LINE_DASH_GAP, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_LINE_ROUNDED(val) \ { \ - .prop = LV_STYLE_LINE_ROUNDED, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_LINE_ROUNDED, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_LINE_COLOR(val) \ { \ - .prop = LV_STYLE_LINE_COLOR, .value = { .color = val } \ + .prop_ptr = &_lv_style_const_prop_id_LINE_COLOR, .value = { .color = val } \ } #define LV_STYLE_CONST_LINE_OPA(val) \ { \ - .prop = LV_STYLE_LINE_OPA, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_LINE_OPA, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_ARC_WIDTH(val) \ { \ - .prop = LV_STYLE_ARC_WIDTH, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_ARC_WIDTH, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_ARC_ROUNDED(val) \ { \ - .prop = LV_STYLE_ARC_ROUNDED, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_ARC_ROUNDED, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_ARC_COLOR(val) \ { \ - .prop = LV_STYLE_ARC_COLOR, .value = { .color = val } \ + .prop_ptr = &_lv_style_const_prop_id_ARC_COLOR, .value = { .color = val } \ } #define LV_STYLE_CONST_ARC_OPA(val) \ { \ - .prop = LV_STYLE_ARC_OPA, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_ARC_OPA, .value = { .num = (int32_t)val } \ } -#define LV_STYLE_CONST_ARC_IMG_SRC(val) \ +#define LV_STYLE_CONST_ARC_IMAGE_SRC(val) \ { \ - .prop = LV_STYLE_ARC_IMG_SRC, .value = { .ptr = val } \ + .prop_ptr = &_lv_style_const_prop_id_ARC_IMAGE_SRC, .value = { .ptr = val } \ } #define LV_STYLE_CONST_TEXT_COLOR(val) \ { \ - .prop = LV_STYLE_TEXT_COLOR, .value = { .color = val } \ + .prop_ptr = &_lv_style_const_prop_id_TEXT_COLOR, .value = { .color = val } \ } #define LV_STYLE_CONST_TEXT_OPA(val) \ { \ - .prop = LV_STYLE_TEXT_OPA, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_TEXT_OPA, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_TEXT_FONT(val) \ { \ - .prop = LV_STYLE_TEXT_FONT, .value = { .ptr = val } \ + .prop_ptr = &_lv_style_const_prop_id_TEXT_FONT, .value = { .ptr = val } \ } #define LV_STYLE_CONST_TEXT_LETTER_SPACE(val) \ { \ - .prop = LV_STYLE_TEXT_LETTER_SPACE, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_TEXT_LETTER_SPACE, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_TEXT_LINE_SPACE(val) \ { \ - .prop = LV_STYLE_TEXT_LINE_SPACE, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_TEXT_LINE_SPACE, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_TEXT_DECOR(val) \ { \ - .prop = LV_STYLE_TEXT_DECOR, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_TEXT_DECOR, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_TEXT_ALIGN(val) \ { \ - .prop = LV_STYLE_TEXT_ALIGN, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_TEXT_ALIGN, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_RADIUS(val) \ { \ - .prop = LV_STYLE_RADIUS, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_RADIUS, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_CLIP_CORNER(val) \ { \ - .prop = LV_STYLE_CLIP_CORNER, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_CLIP_CORNER, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_OPA(val) \ { \ - .prop = LV_STYLE_OPA, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_OPA, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_OPA_LAYERED(val) \ { \ - .prop = LV_STYLE_OPA_LAYERED, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_OPA_LAYERED, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_COLOR_FILTER_DSC(val) \ { \ - .prop = LV_STYLE_COLOR_FILTER_DSC, .value = { .ptr = val } \ + .prop_ptr = &_lv_style_const_prop_id_COLOR_FILTER_DSC, .value = { .ptr = val } \ } #define LV_STYLE_CONST_COLOR_FILTER_OPA(val) \ { \ - .prop = LV_STYLE_COLOR_FILTER_OPA, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_COLOR_FILTER_OPA, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_ANIM(val) \ { \ - .prop = LV_STYLE_ANIM, .value = { .ptr = val } \ + .prop_ptr = &_lv_style_const_prop_id_ANIM, .value = { .ptr = val } \ } -#define LV_STYLE_CONST_ANIM_TIME(val) \ +#define LV_STYLE_CONST_ANIM_DURATION(val) \ { \ - .prop = LV_STYLE_ANIM_TIME, .value = { .num = (int32_t)val } \ - } - -#define LV_STYLE_CONST_ANIM_SPEED(val) \ - { \ - .prop = LV_STYLE_ANIM_SPEED, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_ANIM_DURATION, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_TRANSITION(val) \ { \ - .prop = LV_STYLE_TRANSITION, .value = { .ptr = val } \ + .prop_ptr = &_lv_style_const_prop_id_TRANSITION, .value = { .ptr = val } \ } #define LV_STYLE_CONST_BLEND_MODE(val) \ { \ - .prop = LV_STYLE_BLEND_MODE, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_BLEND_MODE, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_LAYOUT(val) \ { \ - .prop = LV_STYLE_LAYOUT, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_LAYOUT, .value = { .num = (int32_t)val } \ } #define LV_STYLE_CONST_BASE_DIR(val) \ { \ - .prop = LV_STYLE_BASE_DIR, .value = { .num = (int32_t)val } \ + .prop_ptr = &_lv_style_const_prop_id_BASE_DIR, .value = { .num = (int32_t)val } \ } +#if LV_USE_FLEX + +#define LV_STYLE_CONST_FLEX_FLOW(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_FLEX_FLOW, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_FLEX_MAIN_PLACE(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_FLEX_MAIN_PLACE, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_FLEX_CROSS_PLACE(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_FLEX_CROSS_PLACE, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_FLEX_TRACK_PLACE(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_FLEX_TRACK_PLACE, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_FLEX_GROW(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_FLEX_GROW, .value = { .num = (int32_t)val } \ + } +#endif /*LV_USE_FLEX*/ + +#if LV_USE_GRID + +#define LV_STYLE_CONST_GRID_COLUMN_DSC_ARRAY(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_GRID_COLUMN_DSC_ARRAY, .value = { .ptr = val } \ + } + +#define LV_STYLE_CONST_GRID_COLUMN_ALIGN(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_GRID_COLUMN_ALIGN, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_GRID_ROW_DSC_ARRAY(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_GRID_ROW_DSC_ARRAY, .value = { .ptr = val } \ + } + +#define LV_STYLE_CONST_GRID_ROW_ALIGN(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_GRID_ROW_ALIGN, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_GRID_CELL_COLUMN_POS(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_GRID_CELL_COLUMN_POS, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_GRID_CELL_X_ALIGN(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_GRID_CELL_X_ALIGN, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_GRID_CELL_COLUMN_SPAN(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_GRID_CELL_COLUMN_SPAN, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_GRID_CELL_ROW_POS(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_GRID_CELL_ROW_POS, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_GRID_CELL_Y_ALIGN(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_GRID_CELL_Y_ALIGN, .value = { .num = (int32_t)val } \ + } + +#define LV_STYLE_CONST_GRID_CELL_ROW_SPAN(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_GRID_CELL_ROW_SPAN, .value = { .num = (int32_t)val } \ + } +#endif /*LV_USE_GRID*/ + +#endif /* LV_STYLE_GEN_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_text.c similarity index 67% rename from lib/libesp32_lvgl/lvgl/src/misc/lv_txt.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_text.c index da7eca0bb..b9e96de6e 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_text.c @@ -1,5 +1,5 @@ /** - * @file lv_txt.c + * @file lv_text.c * */ @@ -7,12 +7,13 @@ * INCLUDES *********************/ #include -#include "lv_txt.h" -#include "lv_txt_ap.h" +#include "lv_text.h" +#include "lv_text_ap.h" #include "lv_math.h" #include "lv_log.h" -#include "lv_mem.h" #include "lv_assert.h" +#include "../stdlib/lv_mem.h" +#include "../stdlib/lv_string.h" /********************* * DEFINES @@ -28,23 +29,23 @@ **********************/ #if LV_TXT_ENC == LV_TXT_ENC_UTF8 - static uint8_t lv_txt_utf8_size(const char * str); - static uint32_t lv_txt_unicode_to_utf8(uint32_t letter_uni); - static uint32_t lv_txt_utf8_conv_wc(uint32_t c); - static uint32_t lv_txt_utf8_next(const char * txt, uint32_t * i); - static uint32_t lv_txt_utf8_prev(const char * txt, uint32_t * i_start); - static uint32_t lv_txt_utf8_get_byte_id(const char * txt, uint32_t utf8_id); - static uint32_t lv_txt_utf8_get_char_id(const char * txt, uint32_t byte_id); - static uint32_t lv_txt_utf8_get_length(const char * txt); + static uint8_t lv_text_utf8_size(const char * str); + static uint32_t lv_text_unicode_to_utf8(uint32_t letter_uni); + static uint32_t lv_text_utf8_conv_wc(uint32_t c); + static uint32_t lv_text_utf8_next(const char * txt, uint32_t * i); + static uint32_t lv_text_utf8_prev(const char * txt, uint32_t * i_start); + static uint32_t lv_text_utf8_get_byte_id(const char * txt, uint32_t utf8_id); + static uint32_t lv_text_utf8_get_char_id(const char * txt, uint32_t byte_id); + static uint32_t lv_text_utf8_get_length(const char * txt); #elif LV_TXT_ENC == LV_TXT_ENC_ASCII - static uint8_t lv_txt_iso8859_1_size(const char * str); - static uint32_t lv_txt_unicode_to_iso8859_1(uint32_t letter_uni); - static uint32_t lv_txt_iso8859_1_conv_wc(uint32_t c); - static uint32_t lv_txt_iso8859_1_next(const char * txt, uint32_t * i); - static uint32_t lv_txt_iso8859_1_prev(const char * txt, uint32_t * i_start); - static uint32_t lv_txt_iso8859_1_get_byte_id(const char * txt, uint32_t utf8_id); - static uint32_t lv_txt_iso8859_1_get_char_id(const char * txt, uint32_t byte_id); - static uint32_t lv_txt_iso8859_1_get_length(const char * txt); + static uint8_t lv_text_iso8859_1_size(const char * str); + static uint32_t lv_text_unicode_to_iso8859_1(uint32_t letter_uni); + static uint32_t lv_text_iso8859_1_conv_wc(uint32_t c); + static uint32_t lv_text_iso8859_1_next(const char * txt, uint32_t * i); + static uint32_t lv_text_iso8859_1_prev(const char * txt, uint32_t * i_start); + static uint32_t lv_text_iso8859_1_get_byte_id(const char * txt, uint32_t utf8_id); + static uint32_t lv_text_iso8859_1_get_char_id(const char * txt, uint32_t byte_id); + static uint32_t lv_text_iso8859_1_get_length(const char * txt); #endif /********************** * STATIC VARIABLES @@ -54,23 +55,23 @@ * GLOBAL VARIABLES **********************/ #if LV_TXT_ENC == LV_TXT_ENC_UTF8 - uint8_t (*_lv_txt_encoded_size)(const char *) = lv_txt_utf8_size; - uint32_t (*_lv_txt_unicode_to_encoded)(uint32_t) = lv_txt_unicode_to_utf8; - uint32_t (*_lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_utf8_conv_wc; - uint32_t (*_lv_txt_encoded_next)(const char *, uint32_t *) = lv_txt_utf8_next; - uint32_t (*_lv_txt_encoded_prev)(const char *, uint32_t *) = lv_txt_utf8_prev; - uint32_t (*_lv_txt_encoded_get_byte_id)(const char *, uint32_t) = lv_txt_utf8_get_byte_id; - uint32_t (*_lv_txt_encoded_get_char_id)(const char *, uint32_t) = lv_txt_utf8_get_char_id; - uint32_t (*_lv_txt_get_encoded_length)(const char *) = lv_txt_utf8_get_length; + uint8_t (*_lv_text_encoded_size)(const char *) = lv_text_utf8_size; + uint32_t (*_lv_text_unicode_to_encoded)(uint32_t) = lv_text_unicode_to_utf8; + uint32_t (*_lv_text_encoded_conv_wc)(uint32_t) = lv_text_utf8_conv_wc; + uint32_t (*_lv_text_encoded_next)(const char *, uint32_t *) = lv_text_utf8_next; + uint32_t (*_lv_text_encoded_prev)(const char *, uint32_t *) = lv_text_utf8_prev; + uint32_t (*_lv_text_encoded_get_byte_id)(const char *, uint32_t) = lv_text_utf8_get_byte_id; + uint32_t (*_lv_text_encoded_get_char_id)(const char *, uint32_t) = lv_text_utf8_get_char_id; + uint32_t (*_lv_text_get_encoded_length)(const char *) = lv_text_utf8_get_length; #elif LV_TXT_ENC == LV_TXT_ENC_ASCII - uint8_t (*_lv_txt_encoded_size)(const char *) = lv_txt_iso8859_1_size; - uint32_t (*_lv_txt_unicode_to_encoded)(uint32_t) = lv_txt_unicode_to_iso8859_1; - uint32_t (*_lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_iso8859_1_conv_wc; - uint32_t (*_lv_txt_encoded_next)(const char *, uint32_t *) = lv_txt_iso8859_1_next; - uint32_t (*_lv_txt_encoded_prev)(const char *, uint32_t *) = lv_txt_iso8859_1_prev; - uint32_t (*_lv_txt_encoded_get_byte_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_byte_id; - uint32_t (*_lv_txt_encoded_get_char_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_char_id; - uint32_t (*_lv_txt_get_encoded_length)(const char *) = lv_txt_iso8859_1_get_length; + uint8_t (*_lv_text_encoded_size)(const char *) = lv_text_iso8859_1_size; + uint32_t (*_lv_text_unicode_to_encoded)(uint32_t) = lv_text_unicode_to_iso8859_1; + uint32_t (*_lv_text_encoded_conv_wc)(uint32_t) = lv_text_iso8859_1_conv_wc; + uint32_t (*_lv_text_encoded_next)(const char *, uint32_t *) = lv_text_iso8859_1_next; + uint32_t (*_lv_text_encoded_prev)(const char *, uint32_t *) = lv_text_iso8859_1_prev; + uint32_t (*_lv_text_encoded_get_byte_id)(const char *, uint32_t) = lv_text_iso8859_1_get_byte_id; + uint32_t (*_lv_text_encoded_get_char_id)(const char *, uint32_t) = lv_text_iso8859_1_get_char_id; + uint32_t (*_lv_text_get_encoded_length)(const char *) = lv_text_iso8859_1_get_length; #endif @@ -88,8 +89,8 @@ * GLOBAL FUNCTIONS **********************/ -void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, lv_coord_t letter_space, - lv_coord_t line_space, lv_coord_t max_width, lv_text_flag_t flag) +void lv_text_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, int32_t letter_space, + int32_t line_space, int32_t max_width, lv_text_flag_t flag) { size_res->x = 0; size_res->y = 0; @@ -105,10 +106,10 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * /*Calc. the height and longest line*/ while(text[line_start] != '\0') { - new_line_start += _lv_txt_get_next_line(&text[line_start], font, letter_space, max_width, NULL, flag); + new_line_start += _lv_text_get_next_line(&text[line_start], font, letter_space, max_width, NULL, flag); - if((unsigned long)size_res->y + (unsigned long)letter_height + (unsigned long)line_space > LV_MAX_OF(lv_coord_t)) { - LV_LOG_WARN("lv_txt_get_size: integer overflow while calculating text height"); + if((unsigned long)size_res->y + (unsigned long)letter_height + (unsigned long)line_space > LV_MAX_OF(int32_t)) { + LV_LOG_WARN("integer overflow while calculating text height"); return; } else { @@ -117,8 +118,7 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * } /*Calculate the longest line*/ - lv_coord_t act_line_length = lv_txt_get_width(&text[line_start], new_line_start - line_start, font, letter_space, - flag); + int32_t act_line_length = lv_text_get_width(&text[line_start], new_line_start - line_start, font, letter_space); size_res->x = LV_MAX(act_line_length, size_res->x); line_start = new_line_start; @@ -145,7 +145,7 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * * * If the first character is a break character, returns the next index. * - * Example calls from lv_txt_get_next_line() assuming sufficient max_width and + * Example calls from lv_text_get_next_line() assuming sufficient max_width and * txt = "Test text\n" * 0123456789 * @@ -153,7 +153,7 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * * 1. Return i=4, pointing at breakchar ' ', for the string "Test" * 2. Return i=5, since i=4 was a breakchar. * 3. Return i=9, pointing at breakchar '\n' - * 4. Parenting lv_txt_get_next_line() would detect subsequent '\0' + * 4. Parenting lv_text_get_next_line() would detect subsequent '\0' * * TODO: Returned word_w_ptr may overestimate the returned word's width when * max_width is reached. In current usage, this has no impact. @@ -164,13 +164,12 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * * @param max_width max width of the text (break the lines to fit this size). Set COORD_MAX to avoid line breaks * @param flags settings for the text from 'txt_flag_type' enum * @param[out] word_w_ptr width (in pixels) of the parsed word. May be NULL. - * @param cmd_state pointer to a txt_cmd_state_t variable which stores the current state of command processing * @param force Force return the fraction of the word that can fit in the provided space. * @return the index of the first char of the next word (in byte index not letter index. With UTF-8 they are different) */ -static uint32_t lv_txt_get_next_word(const char * txt, const lv_font_t * font, - lv_coord_t letter_space, lv_coord_t max_width, - lv_text_flag_t flag, uint32_t * word_w_ptr, lv_text_cmd_state_t * cmd_state, bool force) +static uint32_t lv_text_get_next_word(const char * txt, const lv_font_t * font, + int32_t letter_space, int32_t max_width, + lv_text_flag_t flag, uint32_t * word_w_ptr, bool force) { if(txt == NULL || txt[0] == '\0') return 0; if(font == NULL) return 0; @@ -180,30 +179,20 @@ static uint32_t lv_txt_get_next_word(const char * txt, const lv_font_t * font, uint32_t i = 0, i_next = 0, i_next_next = 0; /*Iterating index into txt*/ uint32_t letter = 0; /*Letter at i*/ uint32_t letter_next = 0; /*Letter at i_next*/ - lv_coord_t letter_w; - lv_coord_t cur_w = 0; /*Pixel Width of transversed string*/ + int32_t letter_w; + int32_t cur_w = 0; /*Pixel Width of transversed string*/ uint32_t word_len = 0; /*Number of characters in the transversed word*/ uint32_t break_index = NO_BREAK_FOUND; /*only used for "long" words*/ uint32_t break_letter_count = 0; /*Number of characters up to the long word break point*/ - letter = _lv_txt_encoded_next(txt, &i_next); + letter = _lv_text_encoded_next(txt, &i_next); i_next_next = i_next; /*Obtain the full word, regardless if it fits or not in max_width*/ while(txt[i] != '\0') { - letter_next = _lv_txt_encoded_next(txt, &i_next_next); + letter_next = _lv_text_encoded_next(txt, &i_next_next); word_len++; - /*Handle the recolor command*/ - if((flag & LV_TEXT_FLAG_RECOLOR) != 0) { - if(_lv_txt_is_cmd(cmd_state, letter) != false) { - i = i_next; - i_next = i_next_next; - letter = letter_next; - continue; /*Skip the letter if it is part of a command*/ - } - } - letter_w = lv_font_get_glyph_width(font, letter, letter_next); cur_w += letter_w; @@ -219,13 +208,19 @@ static uint32_t lv_txt_get_next_word(const char * txt, const lv_font_t * font, } /*Check for new line chars and breakchars*/ - if(letter == '\n' || letter == '\r' || _lv_txt_is_break_char(letter)) { + if(letter == '\n' || letter == '\r' || _lv_text_is_break_char(letter)) { /*Update the output width on the first character if it fits. *Must do this here in case first letter is a break character.*/ if(i == 0 && break_index == NO_BREAK_FOUND && word_w_ptr != NULL) *word_w_ptr = cur_w; word_len--; break; } + else if(_lv_text_is_a_word(letter_next) || _lv_text_is_a_word(letter)) { + /*Found a word for single letter, usually true for CJK*/ + *word_w_ptr = cur_w; + i = i_next; + break; + } /*Update the output width*/ if(word_w_ptr != NULL && break_index == NO_BREAK_FOUND) *word_w_ptr = cur_w; @@ -262,9 +257,11 @@ static uint32_t lv_txt_get_next_word(const char * txt, const lv_font_t * font, int32_t n_move = LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN - (word_len - break_letter_count); /*Move pointer "i" backwards*/ for(; n_move > 0; n_move--) { - _lv_txt_encoded_prev(txt, &i); - // TODO: it would be appropriate to update the returned word width here - // However, in current usage, this doesn't impact anything. + _lv_text_encoded_prev(txt, &i); + /** + * TODO: it would be appropriate to update the returned + * word width hereHowever, in current usage, this doesn't impact anything. + */ } } return i; @@ -276,9 +273,9 @@ static uint32_t lv_txt_get_next_word(const char * txt, const lv_font_t * font, #endif } -uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, - lv_coord_t letter_space, lv_coord_t max_width, - lv_coord_t * used_width, lv_text_flag_t flag) +uint32_t _lv_text_get_next_line(const char * txt, const lv_font_t * font, + int32_t letter_space, int32_t max_width, + int32_t * used_width, lv_text_flag_t flag) { if(used_width) *used_width = 0; @@ -286,9 +283,9 @@ uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, if(txt[0] == '\0') return 0; if(font == NULL) return 0; - lv_coord_t line_w = 0; + int32_t line_w = 0; - /*If max_width doesn't mater simply find the new line character + /*If max_width doesn't matter simply find the new line character *without thinking about word wrapping*/ if((flag & LV_TEXT_FLAG_EXPAND) || (flag & LV_TEXT_FLAG_FIT)) { uint32_t i; @@ -301,12 +298,11 @@ uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, } if(flag & LV_TEXT_FLAG_EXPAND) max_width = LV_COORD_MAX; - lv_text_cmd_state_t cmd_state = LV_TEXT_CMD_STATE_WAIT; uint32_t i = 0; /*Iterating index into txt*/ while(txt[i] != '\0' && max_width > 0) { uint32_t word_w = 0; - uint32_t advance = lv_txt_get_next_word(&txt[i], font, letter_space, max_width, flag, &word_w, &cmd_state, i == 0); + uint32_t advance = lv_text_get_next_word(&txt[i], font, letter_space, max_width, flag, &word_w, i == 0); max_width -= word_w; line_w += word_w; @@ -327,7 +323,7 @@ uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, /*Always step at least one to avoid infinite loops*/ if(i == 0) { - uint32_t letter = _lv_txt_encoded_next(txt, &i); + uint32_t letter = _lv_text_encoded_next(txt, &i); if(used_width != NULL) { line_w = lv_font_get_glyph_width(font, letter, '\0'); } @@ -340,30 +336,22 @@ uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, return i; } -lv_coord_t lv_txt_get_width(const char * txt, uint32_t length, const lv_font_t * font, lv_coord_t letter_space, - lv_text_flag_t flag) +int32_t lv_text_get_width(const char * txt, uint32_t length, const lv_font_t * font, int32_t letter_space) { if(txt == NULL) return 0; if(font == NULL) return 0; if(txt[0] == '\0') return 0; uint32_t i = 0; - lv_coord_t width = 0; - lv_text_cmd_state_t cmd_state = LV_TEXT_CMD_STATE_WAIT; + int32_t width = 0; if(length != 0) { while(i < length) { uint32_t letter; uint32_t letter_next; - _lv_txt_encoded_letter_next_2(txt, &letter, &letter_next, &i); + _lv_text_encoded_letter_next_2(txt, &letter, &letter_next, &i); - if((flag & LV_TEXT_FLAG_RECOLOR) != 0) { - if(_lv_txt_is_cmd(&cmd_state, letter) != false) { - continue; - } - } - - lv_coord_t char_width = lv_font_get_glyph_width(font, letter, letter_next); + int32_t char_width = lv_font_get_glyph_width(font, letter, letter_next); if(char_width > 0) { width += char_width; width += letter_space; @@ -379,47 +367,16 @@ lv_coord_t lv_txt_get_width(const char * txt, uint32_t length, const lv_font_t * return width; } -bool _lv_txt_is_cmd(lv_text_cmd_state_t * state, uint32_t c) -{ - bool ret = false; - - if(c == (uint32_t)LV_TXT_COLOR_CMD[0]) { - if(*state == LV_TEXT_CMD_STATE_WAIT) { /*Start char*/ - *state = LV_TEXT_CMD_STATE_PAR; - ret = true; - } - /*Other start char in parameter is escaped cmd. char*/ - else if(*state == LV_TEXT_CMD_STATE_PAR) { - *state = LV_TEXT_CMD_STATE_WAIT; - } - /*Command end*/ - else if(*state == LV_TEXT_CMD_STATE_IN) { - *state = LV_TEXT_CMD_STATE_WAIT; - ret = true; - } - } - - /*Skip the color parameter and wait the space after it*/ - if(*state == LV_TEXT_CMD_STATE_PAR) { - if(c == ' ') { - *state = LV_TEXT_CMD_STATE_IN; /*After the parameter the text is in the command*/ - } - ret = true; - } - - return ret; -} - -void _lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt) +void _lv_text_ins(char * txt_buf, uint32_t pos, const char * ins_txt) { if(txt_buf == NULL || ins_txt == NULL) return; - size_t old_len = strlen(txt_buf); - size_t ins_len = strlen(ins_txt); + size_t old_len = lv_strlen(txt_buf); + size_t ins_len = lv_strlen(ins_txt); if(ins_len == 0) return; size_t new_len = ins_len + old_len; - pos = _lv_txt_encoded_get_byte_id(txt_buf, pos); /*Convert to byte index instead of letter index*/ + pos = _lv_text_encoded_get_byte_id(txt_buf, pos); /*Convert to byte index instead of letter index*/ /*Copy the second part into the end to make place to text to insert*/ size_t i; @@ -428,17 +385,17 @@ void _lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt) } /*Copy the text into the new space*/ - lv_memcpy_small(txt_buf + pos, ins_txt, ins_len); + lv_memcpy(txt_buf + pos, ins_txt, ins_len); } -void _lv_txt_cut(char * txt, uint32_t pos, uint32_t len) +void _lv_text_cut(char * txt, uint32_t pos, uint32_t len) { if(txt == NULL) return; - size_t old_len = strlen(txt); + size_t old_len = lv_strlen(txt); - pos = _lv_txt_encoded_get_byte_id(txt, pos); /*Convert to byte index instead of letter index*/ - len = _lv_txt_encoded_get_byte_id(&txt[pos], len); + pos = _lv_text_encoded_get_byte_id(txt, pos); /*Convert to byte index instead of letter index*/ + len = _lv_text_encoded_get_byte_id(&txt[pos], len); /*Copy the second part into the end to make place to text to insert*/ uint32_t i; @@ -447,7 +404,7 @@ void _lv_txt_cut(char * txt, uint32_t pos, uint32_t len) } } -char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap) +char * _lv_text_set_text_vfmt(const char * fmt, va_list ap) { /*Allocate space for the new text by using trick from C99 standard section 7.19.6.12*/ va_list ap_copy; @@ -458,7 +415,7 @@ char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap) char * text = 0; #if LV_USE_ARABIC_PERSIAN_CHARS /*Put together the text according to the format string*/ - char * raw_txt = lv_mem_buf_get(len + 1); + char * raw_txt = lv_malloc(len + 1); LV_ASSERT_MALLOC(raw_txt); if(raw_txt == NULL) { return NULL; @@ -467,22 +424,21 @@ char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap) lv_vsnprintf(raw_txt, len + 1, fmt, ap); /*Get the size of the Arabic text and process it*/ - size_t len_ap = _lv_txt_ap_calc_bytes_cnt(raw_txt); - text = lv_mem_alloc(len_ap + 1); + size_t len_ap = _lv_text_ap_calc_bytes_count(raw_txt); + text = lv_malloc(len_ap + 1); LV_ASSERT_MALLOC(text); if(text == NULL) { return NULL; } - _lv_txt_ap_proc(raw_txt, text); + _lv_text_ap_proc(raw_txt, text); - lv_mem_buf_release(raw_txt); + lv_free(raw_txt); #else - text = lv_mem_alloc(len + 1); + text = lv_malloc(len + 1); LV_ASSERT_MALLOC(text); if(text == NULL) { return NULL; } - text[len] = 0; /*Ensure NULL termination*/ lv_vsnprintf(text, len + 1, fmt, ap); #endif @@ -490,10 +446,10 @@ char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap) return text; } -void _lv_txt_encoded_letter_next_2(const char * txt, uint32_t * letter, uint32_t * letter_next, uint32_t * ofs) +void _lv_text_encoded_letter_next_2(const char * txt, uint32_t * letter, uint32_t * letter_next, uint32_t * ofs) { - *letter = _lv_txt_encoded_next(txt, ofs); - *letter_next = *letter != '\0' ? _lv_txt_encoded_next(&txt[*ofs], NULL) : 0; + *letter = _lv_text_encoded_next(txt, ofs); + *letter_next = *letter != '\0' ? _lv_text_encoded_next(&txt[*ofs], NULL) : 0; } #if LV_TXT_ENC == LV_TXT_ENC_UTF8 @@ -506,7 +462,7 @@ void _lv_txt_encoded_letter_next_2(const char * txt, uint32_t * letter, uint32_t * @param str pointer to a character in a string * @return length of the UTF-8 character (1,2,3 or 4), 0 on invalid code. */ -static uint8_t lv_txt_utf8_size(const char * str) +static uint8_t lv_text_utf8_size(const char * str) { if(LV_IS_ASCII(str[0])) return 1; @@ -524,7 +480,7 @@ static uint8_t lv_txt_utf8_size(const char * str) * @param letter_uni a Unicode letter * @return UTF-8 coded character in Little Endian to be compatible with C chars (e.g. 'Á', 'Ű') */ -static uint32_t lv_txt_unicode_to_utf8(uint32_t letter_uni) +static uint32_t lv_text_unicode_to_utf8(uint32_t letter_uni) { if(letter_uni < 128) return letter_uni; uint8_t bytes[4]; @@ -560,14 +516,14 @@ static uint32_t lv_txt_unicode_to_utf8(uint32_t letter_uni) * @param c a wide character or a Little endian number * @return `c` in big endian */ -static uint32_t lv_txt_utf8_conv_wc(uint32_t c) +static uint32_t lv_text_utf8_conv_wc(uint32_t c) { #if LV_BIG_ENDIAN_SYSTEM == 0 /*Swap the bytes (UTF-8 is big endian, but the MCUs are little endian)*/ if((c & 0x80) != 0) { uint32_t swapped; uint8_t c8[4]; - lv_memcpy_small(c8, &c, 4); + lv_memcpy(c8, &c, 4); swapped = (c8[0] << 24) + (c8[1] << 16) + (c8[2] << 8) + (c8[3]); uint8_t i; for(i = 0; i < 4; i++) { @@ -588,7 +544,7 @@ static uint32_t lv_txt_utf8_conv_wc(uint32_t c) * NULL to use txt[0] as index * @return the decoded Unicode character or 0 on invalid UTF-8 code */ -static uint32_t lv_txt_utf8_next(const char * txt, uint32_t * i) +static uint32_t lv_text_utf8_next(const char * txt, uint32_t * i) { /** * Unicode to UTF-8 @@ -663,7 +619,7 @@ static uint32_t lv_txt_utf8_next(const char * txt, uint32_t * i) * UTF-8 char in 'txt'. * @return the decoded Unicode character or 0 on invalid UTF-8 code */ -static uint32_t lv_txt_utf8_prev(const char * txt, uint32_t * i) +static uint32_t lv_text_utf8_prev(const char * txt, uint32_t * i) { uint8_t c_size; uint8_t cnt = 0; @@ -673,7 +629,7 @@ static uint32_t lv_txt_utf8_prev(const char * txt, uint32_t * i) do { if(cnt >= 4) return 0; /*No UTF-8 char found before the initial*/ - c_size = _lv_txt_encoded_size(&txt[*i]); + c_size = _lv_text_encoded_size(&txt[*i]); if(c_size == 0) { if(*i != 0) (*i)--; @@ -684,7 +640,7 @@ static uint32_t lv_txt_utf8_prev(const char * txt, uint32_t * i) } while(c_size == 0); uint32_t i_tmp = *i; - uint32_t letter = _lv_txt_encoded_next(txt, &i_tmp); /*Character found, get it*/ + uint32_t letter = _lv_text_encoded_next(txt, &i_tmp); /*Character found, get it*/ return letter; } @@ -696,12 +652,12 @@ static uint32_t lv_txt_utf8_prev(const char * txt, uint32_t * i) * @param utf8_id character index * @return byte index of the 'utf8_id'th letter */ -static uint32_t lv_txt_utf8_get_byte_id(const char * txt, uint32_t utf8_id) +static uint32_t lv_text_utf8_get_byte_id(const char * txt, uint32_t utf8_id) { uint32_t i; uint32_t byte_cnt = 0; for(i = 0; i < utf8_id && txt[byte_cnt] != '\0'; i++) { - uint8_t c_size = _lv_txt_encoded_size(&txt[byte_cnt]); + uint8_t c_size = _lv_text_encoded_size(&txt[byte_cnt]); /* If the char was invalid tell it's 1 byte long*/ byte_cnt += c_size ? c_size : 1; } @@ -716,13 +672,13 @@ static uint32_t lv_txt_utf8_get_byte_id(const char * txt, uint32_t utf8_id) * @param byte_id byte index * @return character index of the letter at 'byte_id'th position */ -static uint32_t lv_txt_utf8_get_char_id(const char * txt, uint32_t byte_id) +static uint32_t lv_text_utf8_get_char_id(const char * txt, uint32_t byte_id) { uint32_t i = 0; uint32_t char_cnt = 0; while(i < byte_id) { - _lv_txt_encoded_next(txt, &i); /*'i' points to the next letter so use the prev. value*/ + _lv_text_encoded_next(txt, &i); /*'i' points to the next letter so use the prev. value*/ char_cnt++; } @@ -735,13 +691,13 @@ static uint32_t lv_txt_utf8_get_char_id(const char * txt, uint32_t byte_id) * @param txt a '\0' terminated char string * @return number of characters */ -static uint32_t lv_txt_utf8_get_length(const char * txt) +static uint32_t lv_text_utf8_get_length(const char * txt) { uint32_t len = 0; uint32_t i = 0; while(txt[i] != '\0') { - _lv_txt_encoded_next(txt, &i); + _lv_text_encoded_next(txt, &i); len++; } @@ -758,7 +714,7 @@ static uint32_t lv_txt_utf8_get_length(const char * txt) * @param str pointer to a character in a string * @return length of the UTF-8 character (1,2,3 or 4). O on invalid code */ -static uint8_t lv_txt_iso8859_1_size(const char * str) +static uint8_t lv_text_iso8859_1_size(const char * str) { LV_UNUSED(str); /*Unused*/ return 1; @@ -769,7 +725,7 @@ static uint8_t lv_txt_iso8859_1_size(const char * str) * @param letter_uni a Unicode letter * @return ISO8859-1 coded character in Little Endian to be compatible with C chars (e.g. 'Á', 'Ű') */ -static uint32_t lv_txt_unicode_to_iso8859_1(uint32_t letter_uni) +static uint32_t lv_text_unicode_to_iso8859_1(uint32_t letter_uni) { if(letter_uni < 256) return letter_uni; @@ -783,7 +739,7 @@ static uint32_t lv_txt_unicode_to_iso8859_1(uint32_t letter_uni) * @param c a character, e.g. 'A' * @return same as `c` */ -static uint32_t lv_txt_iso8859_1_conv_wc(uint32_t c) +static uint32_t lv_text_iso8859_1_conv_wc(uint32_t c) { return c; } @@ -796,7 +752,7 @@ static uint32_t lv_txt_iso8859_1_conv_wc(uint32_t c) * NULL to use txt[0] as index * @return the decoded Unicode character or 0 on invalid UTF-8 code */ -static uint32_t lv_txt_iso8859_1_next(const char * txt, uint32_t * i) +static uint32_t lv_text_iso8859_1_next(const char * txt, uint32_t * i) { if(i == NULL) return txt[0]; /*Get the next char*/ @@ -811,7 +767,7 @@ static uint32_t lv_txt_iso8859_1_next(const char * txt, uint32_t * i) * @param i start byte index in 'txt' where to start. After the call it will point to the previous UTF-8 char in 'txt'. * @return the decoded Unicode character or 0 on invalid UTF-8 code */ -static uint32_t lv_txt_iso8859_1_prev(const char * txt, uint32_t * i) +static uint32_t lv_text_iso8859_1_prev(const char * txt, uint32_t * i) { if(i == NULL) return *(txt - 1); /*Get the prev. char*/ @@ -828,7 +784,7 @@ static uint32_t lv_txt_iso8859_1_prev(const char * txt, uint32_t * i) * @param utf8_id character index * @return byte index of the 'utf8_id'th letter */ -static uint32_t lv_txt_iso8859_1_get_byte_id(const char * txt, uint32_t utf8_id) +static uint32_t lv_text_iso8859_1_get_byte_id(const char * txt, uint32_t utf8_id) { LV_UNUSED(txt); /*Unused*/ return utf8_id; /*In Non encoded no difference*/ @@ -841,7 +797,7 @@ static uint32_t lv_txt_iso8859_1_get_byte_id(const char * txt, uint32_t utf8_id) * @param byte_id byte index * @return character index of the letter at 'byte_id'th position */ -static uint32_t lv_txt_iso8859_1_get_char_id(const char * txt, uint32_t byte_id) +static uint32_t lv_text_iso8859_1_get_char_id(const char * txt, uint32_t byte_id) { LV_UNUSED(txt); /*Unused*/ return byte_id; /*In Non encoded no difference*/ @@ -853,9 +809,9 @@ static uint32_t lv_txt_iso8859_1_get_char_id(const char * txt, uint32_t byte_id) * @param txt a '\0' terminated char string * @return number of characters */ -static uint32_t lv_txt_iso8859_1_get_length(const char * txt) +static uint32_t lv_text_iso8859_1_get_length(const char * txt) { - return strlen(txt); + return lv_strlen(txt); } #else diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_text.h similarity index 59% rename from lib/libesp32_lvgl/lvgl/src/misc/lv_txt.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_text.h index 46050dc3c..b2eddab4e 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_txt.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_text.h @@ -1,10 +1,10 @@ /** - * @file lv_txt.h + * @file lv_text.h * */ -#ifndef LV_TXT_H -#define LV_TXT_H +#ifndef LV_TEXT_H +#define LV_TEXT_H #ifdef __cplusplus extern "C" { @@ -19,15 +19,12 @@ extern "C" { #include #include "lv_area.h" #include "../font/lv_font.h" -#include "lv_printf.h" +#include "../stdlib/lv_sprintf.h" #include "lv_types.h" /********************* * DEFINES *********************/ -#ifndef LV_TXT_COLOR_CMD -#define LV_TXT_COLOR_CMD "#" -#endif #define LV_TXT_ENC_UTF8 1 #define LV_TXT_ENC_ASCII 2 @@ -39,31 +36,32 @@ extern "C" { /** * Options for text rendering. */ -enum { - LV_TEXT_FLAG_NONE = 0x00, - LV_TEXT_FLAG_RECOLOR = 0x01, /**< Enable parsing of recolor command*/ - LV_TEXT_FLAG_EXPAND = 0x02, /**< Ignore max-width to avoid automatic word wrapping*/ - LV_TEXT_FLAG_FIT = 0x04, /**< Max-width is already equal to the longest line. (Used to skip some calculation)*/ -}; -typedef uint8_t lv_text_flag_t; -/** - * State machine for text renderer.*/ -enum { - LV_TEXT_CMD_STATE_WAIT, /**< Waiting for command*/ - LV_TEXT_CMD_STATE_PAR, /**< Processing the parameter*/ - LV_TEXT_CMD_STATE_IN, /**< Processing the command*/ +enum _lv_text_flag_t { + LV_TEXT_FLAG_NONE = 0x00, + LV_TEXT_FLAG_EXPAND = 0x01, /**< Ignore max-width to avoid automatic word wrapping*/ + LV_TEXT_FLAG_FIT = 0x02, /**< Max-width is already equal to the longest line. (Used to skip some calculation)*/ }; -typedef uint8_t lv_text_cmd_state_t; + +#ifdef DOXYGEN +typedef _lv_text_flag_t lv_text_flag_t; +#else +typedef uint8_t lv_text_flag_t; +#endif /*DOXYGEN*/ /** Label align policy*/ -enum { +enum _lv_text_align_t { LV_TEXT_ALIGN_AUTO, /**< Align text auto*/ LV_TEXT_ALIGN_LEFT, /**< Align text to left*/ LV_TEXT_ALIGN_CENTER, /**< Align text to center*/ LV_TEXT_ALIGN_RIGHT, /**< Align text to right*/ }; + +#ifdef DOXYGEN +typedef _lv_text_align_t lv_text_align_t; +#else typedef uint8_t lv_text_align_t; +#endif /*DOXYGEN*/ /********************** * GLOBAL PROTOTYPES @@ -76,12 +74,13 @@ typedef uint8_t lv_text_align_t; * @param font pointer to font of the text * @param letter_space letter space of the text * @param line_space line space of the text - * @param flags settings for the text from ::lv_text_flag_t * @param max_width max width of the text (break the lines to fit this size). Set COORD_MAX to avoid + * @param flag settings for the text from ::lv_text_flag_t + * line breaks */ -void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, lv_coord_t letter_space, - lv_coord_t line_space, lv_coord_t max_width, lv_text_flag_t flag); +void lv_text_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, int32_t letter_space, + int32_t line_space, int32_t max_width, lv_text_flag_t flag); /** * Get the next line of text. Check line length and break chars too. @@ -92,12 +91,12 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * * line breaks * @param used_width When used_width != NULL, save the width of this line if * flag == LV_TEXT_FLAG_NONE, otherwise save -1. - * @param flags settings for the text from 'txt_flag_type' enum + * @param flag settings for the text from 'txt_flag_type' enum * @return the index of the first char of the new line (in byte index not letter index. With UTF-8 * they are different) */ -uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coord_t letter_space, - lv_coord_t max_width, lv_coord_t * used_width, lv_text_flag_t flag); +uint32_t _lv_text_get_next_line(const char * txt, const lv_font_t * font, int32_t letter_space, + int32_t max_width, int32_t * used_width, lv_text_flag_t flag); /** * Give the length of a text with a given font @@ -106,21 +105,9 @@ uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coor * UTF-8) * @param font pointer to a font * @param letter_space letter space - * @param flags settings for the text from 'txt_flag_t' enum * @return length of a char_num long text */ -lv_coord_t lv_txt_get_width(const char * txt, uint32_t length, const lv_font_t * font, lv_coord_t letter_space, - lv_text_flag_t flag); - -/** - * Check next character in a string and decide if the character is part of the command or not - * @param state pointer to a txt_cmd_state_t variable which stores the current state of command - * processing - * @param c the current character - * @return true: the character is part of a command and should not be written, - * false: the character should be written - */ -bool _lv_txt_is_cmd(lv_text_cmd_state_t * state, uint32_t c); +int32_t lv_text_get_width(const char * txt, uint32_t length, const lv_font_t * font, int32_t letter_space); /** * Insert a string into an other @@ -128,7 +115,7 @@ bool _lv_txt_is_cmd(lv_text_cmd_state_t * state, uint32_t c); * @param pos position to insert (0: before the original text, 1: after the first char etc.) * @param ins_txt text to insert, must be '\0' terminated */ -void _lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt); +void _lv_text_ins(char * txt_buf, uint32_t pos, const char * ins_txt); /** * Delete a part of a string @@ -137,14 +124,16 @@ void _lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt); * char etc.) * @param len number of characters to delete */ -void _lv_txt_cut(char * txt, uint32_t pos, uint32_t len); +void _lv_text_cut(char * txt, uint32_t pos, uint32_t len); /** * return a new formatted text. Memory will be allocated to store the text. * @param fmt `printf`-like format + * @param ap items to print + * @return pointer to the allocated text string. */ -char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap) LV_FORMAT_ATTRIBUTE(1, 0); +char * _lv_text_set_text_vfmt(const char * fmt, va_list ap) LV_FORMAT_ATTRIBUTE(1, 0); /** * Decode two encoded character from a string. @@ -155,23 +144,18 @@ char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap) LV_FORMAT_ATTRIBUTE(1 * After the call it will point to the next encoded char in 'txt'. * NULL to use txt[0] as index */ -void _lv_txt_encoded_letter_next_2(const char * txt, uint32_t * letter, uint32_t * letter_next, uint32_t * ofs); +void _lv_text_encoded_letter_next_2(const char * txt, uint32_t * letter, uint32_t * letter_next, uint32_t * ofs); /** * Test if char is break char or not (a text can broken here or not) * @param letter a letter * @return false: 'letter' is not break char */ -static inline bool _lv_txt_is_break_char(uint32_t letter) +static inline bool _lv_text_is_break_char(uint32_t letter) { uint8_t i; bool ret = false; - /* each chinese character can be break */ - if(letter >= 0x4E00 && letter <= 0x9FA5) { - return true; - } - /*Compare the letter to TXT_BREAK_CHARS*/ for(i = 0; LV_TXT_BREAK_CHARS[i] != '\0'; i++) { if(letter == (uint32_t)LV_TXT_BREAK_CHARS[i]) { @@ -183,6 +167,94 @@ static inline bool _lv_txt_is_break_char(uint32_t letter) return ret; } +/** + * Test if char is break char or not (a text can broken here or not) + * @param letter a letter + * @return false: 'letter' is not break char + */ +static inline bool _lv_text_is_a_word(uint32_t letter) +{ + /*Cheap check on invalid letter*/ + if(letter == 0) return false; + + /*CJK Unified Ideographs*/ + if(letter >= 0x4E00 && letter <= 0x9FFF) { + return true; + } + + /*Fullwidth ASCII variants*/ + if(letter >= 0xFF01 && letter <= 0xFF5E) { + return true; + } + + /*CJK symbols and punctuation*/ + if(letter >= 0x3000 && letter <= 0x303F) { + return true; + } + + /*CJK Radicals Supplement*/ + if(letter >= 0x2E80 && letter <= 0x2EFF) { + return true; + } + + /*CJK Strokes*/ + if(letter >= 0x31C0 && letter <= 0x31EF) { + return true; + } + + /*Hiragana and Katakana*/ + if(letter >= 0x3040 && letter <= 0x30FF) { + return true; + } + + /*Chinese Vertical Forms*/ + if(letter >= 0xFE10 && letter <= 0xFE1F) { + return true; + } + + /*CJK Compatibility Forms*/ + if(letter >= 0xFE30 && letter <= 0xFE4F) { + return true; + } + + return false; +} + +/** + * Test if character can be treated as marker, and don't need to be rendered. + * Note, this is not a full list. Add your findings to the list. + * + * @param letter a letter + * @return true if so + */ +static inline bool _lv_text_is_marker(uint32_t letter) +{ + if(letter < 0x20) return true; + + /*U+061C ARABIC LETTER MARK, see https://www.compart.com/en/unicode/block/U+0600*/ + if(letter == 0x061C) return true; + + /*U+115F HANGUL CHOSEONG FILLER, See https://www.compart.com/en/unicode/block/U+1100*/ + if(letter == 0x115F) return true; + /*U+1160 HANGUL JUNGSEONG FILLER*/ + if(letter == 0x1160) return true; + + /*See https://www.compart.com/en/unicode/block/U+1800*/ + if(letter >= 0x180B && letter <= 0x180E) return true; + + /*See https://www.compart.com/en/unicode/block/U+2000*/ + if(letter >= 0x200B && letter <= 0x200F) return true; + if(letter >= 0x2028 && letter <= 0x202F) return true; + if(letter >= 0x205F && letter <= 0x206F) return true; + + /*U+FEFF ZERO WIDTH NO-BREAK SPACE, see https://www.compart.com/en/unicode/block/U+FE70*/ + if(letter == 0xFEFF) return true; + + if(letter == 0xF8FF) return true; /*LV_SYMBOL_DUMMY*/ + + return false; +} + /*************************************************************** * GLOBAL FUNCTION POINTERS FOR CHARACTER ENCODING INTERFACE ***************************************************************/ @@ -192,21 +264,21 @@ static inline bool _lv_txt_is_break_char(uint32_t letter) * @param str pointer to a character in a string * @return length of the encoded character (1,2,3 ...). O in invalid */ -extern uint8_t (*_lv_txt_encoded_size)(const char *); +extern uint8_t (*_lv_text_encoded_size)(const char *); /** * Convert a Unicode letter to encoded * @param letter_uni a Unicode letter * @return Encoded character in Little Endian to be compatible with C chars (e.g. 'Á', 'Ü') */ -extern uint32_t (*_lv_txt_unicode_to_encoded)(uint32_t); +extern uint32_t (*_lv_text_unicode_to_encoded)(uint32_t); /** * Convert a wide character, e.g. 'Á' little endian to be compatible with the encoded format. * @param c a wide character * @return `c` in the encoded format */ -extern uint32_t (*_lv_txt_encoded_conv_wc)(uint32_t c); +extern uint32_t (*_lv_text_encoded_conv_wc)(uint32_t c); /** * Decode the next encoded character from a string. @@ -216,7 +288,7 @@ extern uint32_t (*_lv_txt_encoded_conv_wc)(uint32_t c); * NULL to use txt[0] as index * @return the decoded Unicode character or 0 on invalid data code */ -extern uint32_t (*_lv_txt_encoded_next)(const char *, uint32_t *); +extern uint32_t (*_lv_text_encoded_next)(const char *, uint32_t *); /** * Get the previous encoded character form a string. @@ -225,7 +297,7 @@ extern uint32_t (*_lv_txt_encoded_next)(const char *, uint32_t *); * encoded char in 'txt'. * @return the decoded Unicode character or 0 on invalid data */ -extern uint32_t (*_lv_txt_encoded_prev)(const char *, uint32_t *); +extern uint32_t (*_lv_text_encoded_prev)(const char *, uint32_t *); /** * Convert a letter index (in the encoded text) to byte index. @@ -234,7 +306,7 @@ extern uint32_t (*_lv_txt_encoded_prev)(const char *, uint32_t *); * @param enc_id letter index * @return byte index of the 'enc_id'th letter */ -extern uint32_t (*_lv_txt_encoded_get_byte_id)(const char *, uint32_t); +extern uint32_t (*_lv_text_encoded_get_byte_id)(const char *, uint32_t); /** * Convert a byte index (in an encoded text) to character index. @@ -243,7 +315,7 @@ extern uint32_t (*_lv_txt_encoded_get_byte_id)(const char *, uint32_t); * @param byte_id byte index * @return character index of the letter at 'byte_id'th position */ -extern uint32_t (*_lv_txt_encoded_get_char_id)(const char *, uint32_t); +extern uint32_t (*_lv_text_encoded_get_char_id)(const char *, uint32_t); /** * Get the number of characters (and NOT bytes) in a string. @@ -251,7 +323,7 @@ extern uint32_t (*_lv_txt_encoded_get_char_id)(const char *, uint32_t); * @param txt a '\0' terminated char string * @return number of characters */ -extern uint32_t (*_lv_txt_get_encoded_length)(const char *); +extern uint32_t (*_lv_text_get_encoded_length)(const char *); /********************** * MACROS @@ -261,4 +333,4 @@ extern uint32_t (*_lv_txt_get_encoded_length)(const char *); } /*extern "C"*/ #endif -#endif /*LV_TXT_H*/ +#endif /*LV_TEXT_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_txt_ap.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_text_ap.c similarity index 87% rename from lib/libesp32_lvgl/lvgl/src/misc/lv_txt_ap.c rename to lib/libesp32_lvgl/lvgl/src/misc/lv_text_ap.c index 54faf8b4f..95e0dd772 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_txt_ap.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_text_ap.c @@ -1,5 +1,5 @@ /** - * @file lv_txt_ap.c + * @file lv_text_ap.c * */ @@ -8,9 +8,9 @@ *********************/ #include #include "lv_bidi.h" -#include "lv_txt.h" -#include "lv_txt_ap.h" -#include "lv_mem.h" +#include "lv_text.h" +#include "lv_text_ap.h" +#include "../stdlib/lv_mem.h" #include "../draw/lv_draw.h" /********************* @@ -23,7 +23,7 @@ typedef struct { uint8_t char_offset; uint16_t char_end_form; - int8_t char_begining_form_offset; + int8_t char_beginning_form_offset; int8_t char_middle_form_offset; int8_t char_isolated_form_offset; struct { @@ -37,8 +37,8 @@ typedef struct { **********************/ #if LV_USE_ARABIC_PERSIAN_CHARS == 1 static uint32_t lv_ap_get_char_index(uint16_t c); -static uint32_t lv_txt_lam_alef(uint32_t ch_curr, uint32_t ch_next); -static bool lv_txt_is_arabic_vowel(uint16_t c); +static uint32_t lv_text_lam_alef(uint32_t ch_curr, uint32_t ch_next); +static bool lv_text_is_arabic_vowel(uint16_t c); /********************** * STATIC VARIABLES @@ -106,7 +106,7 @@ const ap_chars_map_t ap_chars_map[] = { /********************** * GLOBAL FUNCTIONS **********************/ -uint32_t _lv_txt_ap_calc_bytes_cnt(const char * txt) +uint32_t _lv_text_ap_calc_bytes_count(const char * txt) { uint32_t txt_length = 0; uint32_t chars_cnt = 0; @@ -114,12 +114,12 @@ uint32_t _lv_txt_ap_calc_bytes_cnt(const char * txt) uint32_t i, j; uint32_t ch_enc; - txt_length = _lv_txt_get_encoded_length(txt); + txt_length = _lv_text_get_encoded_length(txt); i = 0; j = 0; while(i < txt_length) { - ch_enc = _lv_txt_encoded_next(txt, &j); + ch_enc = _lv_text_encoded_next(txt, &j); current_ap_idx = lv_ap_get_char_index(ch_enc); if(current_ap_idx != LV_UNDEF_ARABIC_PERSIAN_CHARS) @@ -140,7 +140,7 @@ uint32_t _lv_txt_ap_calc_bytes_cnt(const char * txt) return chars_cnt + 1; } -void _lv_txt_ap_proc(const char * txt, char * txt_out) +void _lv_text_ap_proc(const char * txt, char * txt_out) { uint32_t txt_length = 0; uint32_t index_current, idx_next, idx_previous, i, j; @@ -148,15 +148,15 @@ void _lv_txt_ap_proc(const char * txt, char * txt_out) uint32_t * ch_fin; char * txt_out_temp; - txt_length = _lv_txt_get_encoded_length(txt); + txt_length = _lv_text_get_encoded_length(txt); - ch_enc = (uint32_t *)lv_mem_alloc(sizeof(uint32_t) * (txt_length + 1)); - ch_fin = (uint32_t *)lv_mem_alloc(sizeof(uint32_t) * (txt_length + 1)); + ch_enc = (uint32_t *)lv_malloc(sizeof(uint32_t) * (txt_length + 1)); + ch_fin = (uint32_t *)lv_malloc(sizeof(uint32_t) * (txt_length + 1)); i = 0; j = 0; while(j < txt_length) - ch_enc[j++] = _lv_txt_encoded_next(txt, &i); + ch_enc[j++] = _lv_text_encoded_next(txt, &i); ch_enc[j] = 0; @@ -167,13 +167,13 @@ void _lv_txt_ap_proc(const char * txt, char * txt_out) index_current = lv_ap_get_char_index(ch_enc[i]); idx_next = lv_ap_get_char_index(ch_enc[i + 1]); - if(lv_txt_is_arabic_vowel(ch_enc[i])) { // Current character is a vowel + if(lv_text_is_arabic_vowel(ch_enc[i])) { // Current character is a vowel ch_fin[j] = ch_enc[i]; i++; j++; continue; // Skip this character } - else if(lv_txt_is_arabic_vowel(ch_enc[i + 1])) { // Next character is a vowel + else if(lv_text_is_arabic_vowel(ch_enc[i + 1])) { // Next character is a vowel idx_next = lv_ap_get_char_index(ch_enc[i + 2]); // Skip the vowel character to join with the character after it } @@ -190,7 +190,7 @@ void _lv_txt_ap_proc(const char * txt, char * txt_out) uint8_t conjunction_to_next = ((i == txt_length - 1) || idx_next == LV_UNDEF_ARABIC_PERSIAN_CHARS) ? 0 : ap_chars_map[idx_next].ap_chars_conjunction.conj_to_previous; - uint32_t lam_alef = lv_txt_lam_alef(index_current, idx_next); + uint32_t lam_alef = lv_text_lam_alef(index_current, idx_next); if(lam_alef) { if(conjunction_to_previuse) { lam_alef ++; @@ -205,7 +205,7 @@ void _lv_txt_ap_proc(const char * txt, char * txt_out) if(conjunction_to_previuse && conjunction_to_next) ch_fin[j] = ap_chars_map[index_current].char_end_form + ap_chars_map[index_current].char_middle_form_offset; else if(!conjunction_to_previuse && conjunction_to_next) - ch_fin[j] = ap_chars_map[index_current].char_end_form + ap_chars_map[index_current].char_begining_form_offset; + ch_fin[j] = ap_chars_map[index_current].char_end_form + ap_chars_map[index_current].char_beginning_form_offset; else if(conjunction_to_previuse && !conjunction_to_next) ch_fin[j] = ap_chars_map[index_current].char_end_form; else @@ -219,7 +219,7 @@ void _lv_txt_ap_proc(const char * txt, char * txt_out) ch_enc[i] = 0; for(i = 0; i < j; i++) ch_enc[i] = ch_fin[i]; - lv_mem_free(ch_fin); + lv_free(ch_fin); txt_out_temp = txt_out; i = 0; @@ -247,7 +247,7 @@ void _lv_txt_ap_proc(const char * txt, char * txt_out) i++; } *(txt_out_temp) = '\0'; - lv_mem_free(ch_enc); + lv_free(ch_enc); } /********************** * STATIC FUNCTIONS @@ -259,7 +259,7 @@ static uint32_t lv_ap_get_char_index(uint16_t c) if(c == (ap_chars_map[i].char_offset + LV_AP_ALPHABET_BASE_CODE)) return i; else if(c == ap_chars_map[i].char_end_form //is it an End form - || c == (ap_chars_map[i].char_end_form + ap_chars_map[i].char_begining_form_offset) //is it a Beginning form + || c == (ap_chars_map[i].char_end_form + ap_chars_map[i].char_beginning_form_offset) //is it a Beginning form || c == (ap_chars_map[i].char_end_form + ap_chars_map[i].char_middle_form_offset) //is it a middle form || c == (ap_chars_map[i].char_end_form + ap_chars_map[i].char_isolated_form_offset)) { //is it an isolated form return i; @@ -268,7 +268,7 @@ static uint32_t lv_ap_get_char_index(uint16_t c) return LV_UNDEF_ARABIC_PERSIAN_CHARS; } -static uint32_t lv_txt_lam_alef(uint32_t ch_curr, uint32_t ch_next) +static uint32_t lv_text_lam_alef(uint32_t ch_curr, uint32_t ch_next) { uint32_t ch_code = 0; if(ap_chars_map[ch_curr].char_offset != 34) { @@ -293,7 +293,7 @@ static uint32_t lv_txt_lam_alef(uint32_t ch_curr, uint32_t ch_next) return 0; } -static bool lv_txt_is_arabic_vowel(uint16_t c) +static bool lv_text_is_arabic_vowel(uint16_t c) { return (c >= 0x064B) && (c <= 0x0652); } diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_txt_ap.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_text_ap.h similarity index 76% rename from lib/libesp32_lvgl/lvgl/src/misc/lv_txt_ap.h rename to lib/libesp32_lvgl/lvgl/src/misc/lv_text_ap.h index e2d94b8da..df6357fc9 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_txt_ap.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_text_ap.h @@ -1,10 +1,10 @@ /** - * @file lv_txt_ap.h + * @file lv_text_ap.h * */ -#ifndef LV_TXT_AP_H -#define LV_TXT_AP_H +#ifndef LV_TEXT_AP_H +#define LV_TEXT_AP_H #ifdef __cplusplus extern "C" { @@ -14,7 +14,7 @@ extern "C" { * INCLUDES *********************/ #include -#include "lv_txt.h" +#include "lv_text.h" #include "../draw/lv_draw.h" #if LV_USE_ARABIC_PERSIAN_CHARS == 1 @@ -33,8 +33,8 @@ extern "C" { /********************** * GLOBAL PROTOTYPES **********************/ -uint32_t _lv_txt_ap_calc_bytes_cnt(const char * txt); -void _lv_txt_ap_proc(const char * txt, char * txt_out); +uint32_t _lv_text_ap_calc_bytes_count(const char * txt); +void _lv_text_ap_proc(const char * txt, char * txt_out); /********************** * MACROS @@ -46,4 +46,4 @@ void _lv_txt_ap_proc(const char * txt, char * txt_out); } /*extern "C"*/ #endif -#endif /*LV_TXT_AP_H*/ +#endif /*LV_TEXT_AP_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.c index a21038a36..5537e5910 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.c @@ -6,18 +6,24 @@ * INCLUDES *********************/ #include "lv_timer.h" -#include "../hal/lv_hal_tick.h" +#include "../core/lv_global.h" +#include "../tick/lv_tick.h" +#include "../stdlib/lv_mem.h" +#include "../stdlib/lv_sprintf.h" #include "lv_assert.h" -#include "lv_mem.h" #include "lv_ll.h" -#include "lv_gc.h" +#include "lv_profiler.h" /********************* * DEFINES *********************/ + #define IDLE_MEAS_PERIOD 500 /*[ms]*/ #define DEF_PERIOD 500 +#define state LV_GLOBAL_DEFAULT()->timer_state +#define timer_ll_p &(state.timer_ll) + /********************** * TYPEDEFS **********************/ @@ -27,148 +33,136 @@ **********************/ static bool lv_timer_exec(lv_timer_t * timer); static uint32_t lv_timer_time_remaining(lv_timer_t * timer); +static void lv_timer_handler_resume(void); /********************** * STATIC VARIABLES **********************/ -static bool lv_timer_run = false; -static uint8_t idle_last = 0; -static bool timer_deleted; -static bool timer_created; /********************** * MACROS **********************/ -#if LV_LOG_TRACE_TIMER - #define TIMER_TRACE(...) LV_LOG_TRACE(__VA_ARGS__) +#if LV_USE_LOG && LV_LOG_TRACE_TIMER + #define LV_TRACE_TIMER(...) LV_LOG_TRACE(__VA_ARGS__) #else - #define TIMER_TRACE(...) + #define LV_TRACE_TIMER(...) #endif /********************** * GLOBAL FUNCTIONS **********************/ -/** - * Init the lv_timer module - */ void _lv_timer_core_init(void) { - _lv_ll_init(&LV_GC_ROOT(_lv_timer_ll), sizeof(lv_timer_t)); + _lv_ll_init(timer_ll_p, sizeof(lv_timer_t)); /*Initially enable the lv_timer handling*/ lv_timer_enable(true); } -/** - * Call it periodically to handle lv_timers. - * @return the time after which it must be called again - */ -uint32_t LV_ATTRIBUTE_TIMER_HANDLER lv_timer_handler(void) +LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void) { - TIMER_TRACE("begin"); + LV_TRACE_TIMER("begin"); + lv_timer_state_t * state_p = &state; /*Avoid concurrent running of the timer handler*/ - static bool already_running = false; - if(already_running) { - TIMER_TRACE("already running, concurrent calls are not allow, returning"); + if(state_p->already_running) { + LV_TRACE_TIMER("already running, concurrent calls are not allow, returning"); return 1; } - already_running = true; + state_p->already_running = true; - if(lv_timer_run == false) { - already_running = false; /*Release mutex*/ + if(state_p->lv_timer_run == false) { + state_p->already_running = false; /*Release mutex*/ return 1; } - static uint32_t idle_period_start = 0; - static uint32_t busy_time = 0; - + LV_PROFILER_BEGIN; uint32_t handler_start = lv_tick_get(); if(handler_start == 0) { - static uint32_t run_cnt = 0; - run_cnt++; - if(run_cnt > 100) { - run_cnt = 0; + state.run_cnt++; + if(state.run_cnt > 100) { + state.run_cnt = 0; LV_LOG_WARN("It seems lv_tick_inc() is not called."); } } /*Run all timer from the list*/ lv_timer_t * next; + lv_timer_t * timer_active; + lv_ll_t * timer_head = timer_ll_p; do { - timer_deleted = false; - timer_created = false; - LV_GC_ROOT(_lv_timer_act) = _lv_ll_get_head(&LV_GC_ROOT(_lv_timer_ll)); - while(LV_GC_ROOT(_lv_timer_act)) { + state_p->timer_deleted = false; + state_p->timer_created = false; + + timer_active = _lv_ll_get_head(timer_head); + while(timer_active) { /*The timer might be deleted if it runs only once ('repeat_count = 1') *So get next element until the current is surely valid*/ - next = _lv_ll_get_next(&LV_GC_ROOT(_lv_timer_ll), LV_GC_ROOT(_lv_timer_act)); + next = _lv_ll_get_next(timer_head, timer_active); - if(lv_timer_exec(LV_GC_ROOT(_lv_timer_act))) { + if(lv_timer_exec(timer_active)) { /*If a timer was created or deleted then this or the next item might be corrupted*/ - if(timer_created || timer_deleted) { - TIMER_TRACE("Start from the first timer again because a timer was created or deleted"); + if(state_p->timer_created || state_p->timer_deleted) { + LV_TRACE_TIMER("Start from the first timer again because a timer was created or deleted"); break; } } - LV_GC_ROOT(_lv_timer_act) = next; /*Load the next timer*/ + timer_active = next; /*Load the next timer*/ } - } while(LV_GC_ROOT(_lv_timer_act)); + } while(timer_active); - uint32_t time_till_next = LV_NO_TIMER_READY; - next = _lv_ll_get_head(&LV_GC_ROOT(_lv_timer_ll)); + uint32_t time_until_next = LV_NO_TIMER_READY; + next = _lv_ll_get_head(timer_head); while(next) { if(!next->paused) { uint32_t delay = lv_timer_time_remaining(next); - if(delay < time_till_next) - time_till_next = delay; + if(delay < time_until_next) + time_until_next = delay; } - next = _lv_ll_get_next(&LV_GC_ROOT(_lv_timer_ll), next); /*Find the next timer*/ + next = _lv_ll_get_next(timer_head, next); /*Find the next timer*/ } - busy_time += lv_tick_elaps(handler_start); - uint32_t idle_period_time = lv_tick_elaps(idle_period_start); + state_p->busy_time += lv_tick_elaps(handler_start); + uint32_t idle_period_time = lv_tick_elaps(state_p->idle_period_start); if(idle_period_time >= IDLE_MEAS_PERIOD) { - idle_last = (busy_time * 100) / idle_period_time; /*Calculate the busy percentage*/ - idle_last = idle_last > 100 ? 0 : 100 - idle_last; /*But we need idle time*/ - busy_time = 0; - idle_period_start = lv_tick_get(); + state_p->idle_last = (state_p->busy_time * 100) / idle_period_time; /*Calculate the busy percentage*/ + state_p->idle_last = state_p->idle_last > 100 ? 0 : 100 - state_p->idle_last; /*But we need idle time*/ + state_p->busy_time = 0; + state_p->idle_period_start = lv_tick_get(); } - already_running = false; /*Release the mutex*/ + state_p->timer_time_until_next = time_until_next; + state_p->already_running = false; /*Release the mutex*/ - TIMER_TRACE("finished (%d ms until the next timer call)", time_till_next); - return time_till_next; + LV_TRACE_TIMER("finished (%" LV_PRIu32 " ms until the next timer call)", time_until_next); + LV_PROFILER_END; + return time_until_next; +} + +LV_ATTRIBUTE_TIMER_HANDLER void lv_timer_periodic_handler(void) +{ + lv_timer_state_t * state_p = &state; + if(lv_tick_elaps(state_p->periodic_last_tick) >= state_p->timer_time_until_next) { + LV_TRACE_TIMER("calling lv_timer_handler()"); + lv_timer_handler(); + state_p->periodic_last_tick = lv_tick_get(); + } } -/** - * Create an "empty" timer. It needs to initialized with at least - * `lv_timer_set_cb` and `lv_timer_set_period` - * @return pointer to the created timer - */ lv_timer_t * lv_timer_create_basic(void) { return lv_timer_create(NULL, DEF_PERIOD, NULL); } -/** - * Create a new lv_timer - * @param timer_xcb a callback which is the timer itself. It will be called periodically. - * (the 'x' in the argument name indicates that it's not a fully generic function because it not follows - * the `func_name(object, callback, ...)` convention) - * @param period call period in ms unit - * @param user_data custom parameter - * @return pointer to the new timer - */ lv_timer_t * lv_timer_create(lv_timer_cb_t timer_xcb, uint32_t period, void * user_data) { lv_timer_t * new_timer = NULL; - new_timer = _lv_ll_ins_head(&LV_GC_ROOT(_lv_timer_ll)); + new_timer = _lv_ll_ins_head(timer_ll_p); LV_ASSERT_MALLOC(new_timer); if(new_timer == NULL) return NULL; @@ -178,114 +172,106 @@ lv_timer_t * lv_timer_create(lv_timer_cb_t timer_xcb, uint32_t period, void * us new_timer->paused = 0; new_timer->last_run = lv_tick_get(); new_timer->user_data = user_data; + new_timer->auto_delete = true; - timer_created = true; + state.timer_created = true; + + lv_timer_handler_resume(); return new_timer; } -/** - * Set the callback the timer (the function to call periodically) - * @param timer pointer to a timer - * @param timer_cb the function to call periodically - */ void lv_timer_set_cb(lv_timer_t * timer, lv_timer_cb_t timer_cb) { + LV_ASSERT_NULL(timer); timer->timer_cb = timer_cb; } -/** - * Delete a lv_timer - * @param timer pointer to timer created by timer - */ -void lv_timer_del(lv_timer_t * timer) +void lv_timer_delete(lv_timer_t * timer) { - _lv_ll_remove(&LV_GC_ROOT(_lv_timer_ll), timer); - timer_deleted = true; + _lv_ll_remove(timer_ll_p, timer); + state.timer_deleted = true; - lv_mem_free(timer); + lv_free(timer); } -/** - * Pause/resume a timer. - * @param timer pointer to an lv_timer - */ void lv_timer_pause(lv_timer_t * timer) { + LV_ASSERT_NULL(timer); timer->paused = true; } void lv_timer_resume(lv_timer_t * timer) { + LV_ASSERT_NULL(timer); timer->paused = false; + lv_timer_handler_resume(); } -/** - * Set new period for a lv_timer - * @param timer pointer to a lv_timer - * @param period the new period - */ void lv_timer_set_period(lv_timer_t * timer, uint32_t period) { + LV_ASSERT_NULL(timer); timer->period = period; } -/** - * Make a lv_timer ready. It will not wait its period. - * @param timer pointer to a lv_timer. - */ void lv_timer_ready(lv_timer_t * timer) { + LV_ASSERT_NULL(timer); timer->last_run = lv_tick_get() - timer->period - 1; } -/** - * Set the number of times a timer will repeat. - * @param timer pointer to a lv_timer. - * @param repeat_count -1 : infinity; 0 : stop ; n >0: residual times - */ void lv_timer_set_repeat_count(lv_timer_t * timer, int32_t repeat_count) { + LV_ASSERT_NULL(timer); timer->repeat_count = repeat_count; } -/** - * Reset a lv_timer. - * It will be called the previously set period milliseconds later. - * @param timer pointer to a lv_timer. - */ +void lv_timer_set_auto_delete(lv_timer_t * timer, bool auto_delete) +{ + LV_ASSERT_NULL(timer); + timer->auto_delete = auto_delete; +} + +void lv_timer_set_user_data(lv_timer_t * timer, void * user_data) +{ + LV_ASSERT_NULL(timer); + timer->user_data = user_data; +} + void lv_timer_reset(lv_timer_t * timer) { + LV_ASSERT_NULL(timer); timer->last_run = lv_tick_get(); + lv_timer_handler_resume(); } -/** - * Enable or disable the whole lv_timer handling - * @param en true: lv_timer handling is running, false: lv_timer handling is suspended - */ void lv_timer_enable(bool en) { - lv_timer_run = en; + state.lv_timer_run = en; + if(en) lv_timer_handler_resume(); } -/** - * Get idle percentage - * @return the lv_timer idle in percentage - */ -uint8_t lv_timer_get_idle(void) +void _lv_timer_core_deinit(void) { - return idle_last; + lv_timer_enable(false); + + _lv_ll_clear(timer_ll_p); +} + +uint32_t lv_timer_get_idle(void) +{ + return state.idle_last; +} + +uint32_t lv_timer_get_time_until_next(void) +{ + return state.timer_time_until_next; } -/** - * Iterate through the timers - * @param timer NULL to start iteration or the previous return value to get the next timer - * @return the next timer or NULL if there is no more timer - */ lv_timer_t * lv_timer_get_next(lv_timer_t * timer) { - if(timer == NULL) return _lv_ll_get_head(&LV_GC_ROOT(_lv_timer_ll)); - else return _lv_ll_get_next(&LV_GC_ROOT(_lv_timer_ll), timer); + if(timer == NULL) return _lv_ll_get_head(timer_ll_p); + else return _lv_ll_get_next(timer_ll_p, timer); } /********************** @@ -309,17 +295,31 @@ static bool lv_timer_exec(lv_timer_t * timer) int32_t original_repeat_count = timer->repeat_count; if(timer->repeat_count > 0) timer->repeat_count--; timer->last_run = lv_tick_get(); - TIMER_TRACE("calling timer callback: %p", *((void **)&timer->timer_cb)); + LV_TRACE_TIMER("calling timer callback: %p", *((void **)&timer->timer_cb)); + if(timer->timer_cb && original_repeat_count != 0) timer->timer_cb(timer); - TIMER_TRACE("timer callback %p finished", *((void **)&timer->timer_cb)); + + if(!state.timer_deleted) { + LV_TRACE_TIMER("timer callback %p finished", *((void **)&timer->timer_cb)); + } + else { + LV_TRACE_TIMER("timer callback finished"); + } + LV_ASSERT_MEM_INTEGRITY(); exec = true; } - if(timer_deleted == false) { /*The timer might be deleted by itself as well*/ + if(state.timer_deleted == false) { /*The timer might be deleted by itself as well*/ if(timer->repeat_count == 0) { /*The repeat count is over, delete the timer*/ - TIMER_TRACE("deleting timer with %p callback because the repeat count is over", *((void **)&timer->timer_cb)); - lv_timer_del(timer); + if(timer->auto_delete) { + LV_TRACE_TIMER("deleting timer with %p callback because the repeat count is over", *((void **)&timer->timer_cb)); + lv_timer_delete(timer); + } + else { + LV_TRACE_TIMER("pausing timer with %p callback because the repeat count is over", *((void **)&timer->timer_cb)); + lv_timer_pause(timer); + } } } @@ -339,3 +339,21 @@ static uint32_t lv_timer_time_remaining(lv_timer_t * timer) return 0; return timer->period - elp; } + +/** + * Call the ready lv_timer + */ +static void lv_timer_handler_resume(void) +{ + /*If there is a timer which is ready to run then resume the timer loop*/ + state.timer_time_until_next = 0; + if(state.resume_cb) { + state.resume_cb(state.resume_data); + } +} + +void lv_timer_handler_set_resume_cb(lv_timer_handler_resume_cb_t cb, void * data) +{ + state.resume_cb = cb; + state.resume_data = data; +} diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.h index 50da8c9da..06576a853 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_timer.h @@ -13,7 +13,9 @@ extern "C" { * INCLUDES *********************/ #include "../lv_conf_internal.h" -#include "../hal/lv_hal_tick.h" +#include "../tick/lv_tick.h" +#include "lv_types.h" +#include "lv_ll.h" #include #include @@ -31,24 +33,47 @@ extern "C" { * TYPEDEFS **********************/ -struct _lv_timer_t; - /** * Timers execute this type of functions. */ -typedef void (*lv_timer_cb_t)(struct _lv_timer_t *); +typedef void (*lv_timer_cb_t)(lv_timer_t *); + +/** + * Timer handler resume this type of function. + */ +typedef void (*lv_timer_handler_resume_cb_t)(void * data); /** * Descriptor of a lv_timer */ -typedef struct _lv_timer_t { +struct _lv_timer_t { uint32_t period; /**< How often the timer should run*/ uint32_t last_run; /**< Last time the timer ran*/ lv_timer_cb_t timer_cb; /**< Timer function*/ void * user_data; /**< Custom user data*/ int32_t repeat_count; /**< 1: One time; -1 : infinity; n>0: residual times*/ uint32_t paused : 1; -} lv_timer_t; + uint32_t auto_delete : 1; +}; + +typedef struct { + lv_ll_t timer_ll; /*Linked list to store the lv_timers*/ + + bool lv_timer_run; + uint8_t idle_last; + bool timer_deleted; + bool timer_created; + uint32_t timer_time_until_next; + + bool already_running; + uint32_t periodic_last_tick; + uint32_t busy_time; + uint32_t idle_period_start; + uint32_t run_cnt; + + lv_timer_handler_resume_cb_t resume_cb; + void * resume_data; +} lv_timer_state_t; /********************** * GLOBAL PROTOTYPES @@ -59,13 +84,18 @@ typedef struct _lv_timer_t { */ void _lv_timer_core_init(void); +/** + * Deinit the lv_timer module + */ +void _lv_timer_core_deinit(void); + //! @cond Doxygen_Suppress /** * Call it periodically to handle lv_timers. * @return time till it needs to be run next (in ms) */ -uint32_t /* LV_ATTRIBUTE_TIMER_HANDLER */ lv_timer_handler(void); +LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void); //! @endcond @@ -73,22 +103,35 @@ uint32_t /* LV_ATTRIBUTE_TIMER_HANDLER */ lv_timer_handler(void); * Call it in the super-loop of main() or threads. It will run lv_timer_handler() * with a given period in ms. You can use it with sleep or delay in OS environment. * This function is used to simplify the porting. - * @param __ms the period for running lv_timer_handler() + * @param period the period for running lv_timer_handler() + * @return the time after which it must be called again */ -static inline uint32_t LV_ATTRIBUTE_TIMER_HANDLER lv_timer_handler_run_in_period(uint32_t ms) +static inline LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler_run_in_period(uint32_t period) { static uint32_t last_tick = 0; - uint32_t curr_tick = lv_tick_get(); - if((curr_tick - last_tick) >= (ms)) { - last_tick = curr_tick; + if(lv_tick_elaps(last_tick) >= period) { + last_tick = lv_tick_get(); return lv_timer_handler(); } return 1; } /** - * Create an "empty" timer. It needs to initialized with at least + * Call it in the super-loop of main() or threads. It will automatically call lv_timer_handler() at the right time. + * This function is used to simplify the porting. + */ +LV_ATTRIBUTE_TIMER_HANDLER void lv_timer_periodic_handler(void); + +/** + * Set the resume callback to the timer handler + * @param cb the function to call when timer handler is resumed + * @param data pointer to a resume data + */ +void lv_timer_handler_set_resume_cb(lv_timer_handler_resume_cb_t cb, void * data); + +/** + * Create an "empty" timer. It needs to be initialized with at least * `lv_timer_set_cb` and `lv_timer_set_period` * @return pointer to the created timer */ @@ -109,18 +152,22 @@ lv_timer_t * lv_timer_create(lv_timer_cb_t timer_xcb, uint32_t period, void * us * Delete a lv_timer * @param timer pointer to an lv_timer */ -void lv_timer_del(lv_timer_t * timer); +void lv_timer_delete(lv_timer_t * timer); /** - * Pause/resume a timer. + * Pause a timer. * @param timer pointer to an lv_timer */ void lv_timer_pause(lv_timer_t * timer); +/** + * Resume a timer. + * @param timer pointer to an lv_timer + */ void lv_timer_resume(lv_timer_t * timer); /** - * Set the callback the timer (the function to call periodically) + * Set the callback to the timer (the function to call periodically) * @param timer pointer to a timer * @param timer_cb the function to call periodically */ @@ -146,6 +193,20 @@ void lv_timer_ready(lv_timer_t * timer); */ void lv_timer_set_repeat_count(lv_timer_t * timer, int32_t repeat_count); +/** + * Set whether a lv_timer will be deleted automatically when it is called `repeat_count` times. + * @param timer pointer to a lv_timer. + * @param auto_delete true: auto delete; false: timer will be paused when it is called `repeat_count` times. + */ +void lv_timer_set_auto_delete(lv_timer_t * timer, bool auto_delete); + +/** + * Set custom parameter to the lv_timer. + * @param timer pointer to a lv_timer. + * @param user_data custom parameter + */ +void lv_timer_set_user_data(lv_timer_t * timer, void * user_data); + /** * Reset a lv_timer. * It will be called the previously set period milliseconds later. @@ -163,7 +224,13 @@ void lv_timer_enable(bool en); * Get idle percentage * @return the lv_timer idle in percentage */ -uint8_t lv_timer_get_idle(void); +uint32_t lv_timer_get_idle(void); + +/** + * Get the time remaining until the next timer will run + * @return the time remaining in ms + */ +uint32_t lv_timer_get_time_until_next(void); /** * Iterate through the timers @@ -172,6 +239,26 @@ uint8_t lv_timer_get_idle(void); */ lv_timer_t * lv_timer_get_next(lv_timer_t * timer); +/** + * Get the user_data passed when the timer was created + * @param timer pointer to the lv_timer + * @return pointer to the user_data + */ +static inline void * lv_timer_get_user_data(lv_timer_t * timer) +{ + return timer->user_data; +} + +/** + * Get the pause state of a timer + * @param timer pointer to a lv_timer + * @return true: timer is paused; false: timer is running + */ +static inline bool lv_timer_get_paused(lv_timer_t * timer) +{ + return timer->paused; +} + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_types.h b/lib/libesp32_lvgl/lvgl/src/misc/lv_types.h index 84aee1030..1b992c150 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_types.h +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_types.h @@ -13,20 +13,24 @@ extern "C" { /********************* * INCLUDES *********************/ +#include "../lv_conf_internal.h" + +#ifndef __ASSEMBLY__ #include +#endif /********************* * DEFINES *********************/ -// If __UINTPTR_MAX__ or UINTPTR_MAX are available, use them to determine arch size +/*If __UINTPTR_MAX__ or UINTPTR_MAX are available, use them to determine arch size*/ #if defined(__UINTPTR_MAX__) && __UINTPTR_MAX__ > 0xFFFFFFFF #define LV_ARCH_64 #elif defined(UINTPTR_MAX) && UINTPTR_MAX > 0xFFFFFFFF #define LV_ARCH_64 -// Otherwise use compiler-dependent means to determine arch size +/*Otherwise use compiler-dependent means to determine arch size*/ #elif defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__) || defined (__aarch64__) #define LV_ARCH_64 @@ -36,31 +40,111 @@ extern "C" { * TYPEDEFS **********************/ +/* Exclude C enum and struct definitions when included by assembly code */ +#ifndef __ASSEMBLY__ + /** * LVGL error codes. */ -enum { - LV_RES_INV = 0, /*Typically indicates that the object is deleted (become invalid) in the action +enum _lv_result_t { + LV_RESULT_INVALID = 0, /*Typically indicates that the object is deleted (become invalid) in the action function or an operation was failed*/ - LV_RES_OK, /*The object is valid (no deleted) after the action*/ + LV_RESULT_OK, /*The object is valid (no deleted) after the action*/ }; -typedef uint8_t lv_res_t; + +#ifdef DOXYGEN +typedef _lv_result_t lv_result_t; +#else +typedef uint8_t lv_result_t; +#endif /*DOXYGEN*/ #if defined(__cplusplus) || __STDC_VERSION__ >= 199901L -// If c99 or newer, use the definition of uintptr_t directly from +/*If c99 or newer, use the definition of uintptr_t directly from */ typedef uintptr_t lv_uintptr_t; +typedef intptr_t lv_intptr_t; #else -// Otherwise, use the arch size determination +/*Otherwise, use the arch size determination*/ #ifdef LV_ARCH_64 typedef uint64_t lv_uintptr_t; +typedef int64_t lv_intptr_t; #else typedef uint32_t lv_uintptr_t; +typedef int32_t lv_intptr_t; #endif #endif +#if LV_USE_FLOAT +typedef float lv_value_precise_t; +#else +typedef int32_t lv_value_precise_t; +#endif + +/** + * Typedefs from various lvgl modules. + * They are defined here to avoid circular dependencies. + */ + +struct _lv_obj_t; +typedef struct _lv_obj_t lv_obj_t; + +#ifdef DOXYGEN +typedef _lv_state_t lv_state_t; +typedef _lv_part_t lv_part_t; +typedef _lv_obj_flag_t lv_obj_flag_t; +#else +typedef uint16_t lv_state_t; +typedef uint32_t lv_part_t; +typedef uint32_t lv_obj_flag_t; +#endif /*DOXYGEN*/ + +struct _lv_obj_class_t; +typedef struct _lv_obj_class_t lv_obj_class_t; + +struct _lv_group_t; +typedef struct _lv_group_t lv_group_t; + +#ifdef DOXYGEN +typedef _lv_key_t lv_key_t; +#else +typedef uint8_t lv_key_t; +#endif /*DOXYGEN*/ + +struct _lv_display_t; +typedef struct _lv_display_t lv_display_t; + +struct _lv_layer_t; +typedef struct _lv_layer_t lv_layer_t; +struct _lv_draw_unit_t; +typedef struct _lv_draw_unit_t lv_draw_unit_t; +struct _lv_draw_task_t; +typedef struct _lv_draw_task_t lv_draw_task_t; + +struct _lv_indev_t; +typedef struct _lv_indev_t lv_indev_t; + +struct _lv_event_t; +typedef struct _lv_event_t lv_event_t; + +struct _lv_timer_t; +typedef struct _lv_timer_t lv_timer_t; + +struct _lv_theme_t; +typedef struct _lv_theme_t lv_theme_t; + +struct _lv_anim_t; +typedef struct _lv_anim_t lv_anim_t; + +struct _lv_font_t; +typedef struct _lv_font_t lv_font_t; + +struct _lv_image_decoder_t; +typedef struct _lv_image_decoder_t lv_image_decoder_t; + +#endif /*__ASSEMBLY__*/ + /********************** * GLOBAL PROTOTYPES **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_utils.c b/lib/libesp32_lvgl/lvgl/src/misc/lv_utils.c index e17a231de..7738770bc 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_utils.c +++ b/lib/libesp32_lvgl/lvgl/src/misc/lv_utils.c @@ -34,23 +34,6 @@ * GLOBAL FUNCTIONS **********************/ -/** Searches base[0] to base[n - 1] for an item that matches *key. - * - * @note The function cmp must return negative if its first - * argument (the search key) is less than its second (a table entry), - * zero if equal, and positive if greater. - * - * @note Items in the array must be in ascending order. - * - * @param key Pointer to item being searched for - * @param base Pointer to first element to search - * @param n Number of elements - * @param size Size of each element - * @param cmp Pointer to comparison function (see #unicode_list_compare as a comparison function - * example) - * - * @return a pointer to a matching item, or NULL if none exists. - */ void * _lv_utils_bsearch(const void * key, const void * base, uint32_t n, uint32_t size, int32_t (*cmp)(const void * pRef, const void * pElement)) { diff --git a/lib/libesp32_lvgl/lvgl/src/osal/lv_cmsis_rtos2.c b/lib/libesp32_lvgl/lvgl/src/osal/lv_cmsis_rtos2.c new file mode 100644 index 000000000..028520f18 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/osal/lv_cmsis_rtos2.c @@ -0,0 +1,190 @@ +/** + * @file lv_cmsis_rtos2.c + * + */ + +/* + * Copyright (C) 2023 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_os.h" + +#if LV_USE_OS == LV_OS_CMSIS_RTOS2 + +#include "../misc/lv_log.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_result_t lv_thread_init(lv_thread_t * thread, lv_thread_prio_t prio, void (*callback)(void *), size_t stack_size, + void * user_data) +{ + static const osPriority_t prio_map[] = { + [LV_THREAD_PRIO_LOWEST] = osPriorityLow, + [LV_THREAD_PRIO_LOW] = osPriorityBelowNormal, + [LV_THREAD_PRIO_MID] = osPriorityNormal, + [LV_THREAD_PRIO_HIGH] = osPriorityHigh, + [LV_THREAD_PRIO_HIGHEST] = osPriorityRealtime7, + }; + + osThreadAttr_t c_tThreadAttribute = { + .stack_size = stack_size, + .priority = prio_map[prio], + }; + + *thread = osThreadNew(callback, user_data, &c_tThreadAttribute); + + if(NULL == *thread) { + LV_LOG_WARN("Error: Failed to create a cmsis-rtos2 thread."); + return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; + +} + +lv_result_t lv_thread_delete(lv_thread_t * thread) +{ + osThreadDetach(*thread); + osStatus_t status = osThreadTerminate(*thread); + if(status == osOK) { + return LV_RESULT_OK; + } + return LV_RESULT_INVALID; +} + +lv_result_t lv_mutex_init(lv_mutex_t * mutex) +{ + const osMutexAttr_t Thread_Mutex_attr = { + "LVGLMutex", + osMutexRecursive | osMutexPrioInherit | osMutexRobust, + }; + + *mutex = osMutexNew(&Thread_Mutex_attr); + if(*mutex == NULL) { + LV_LOG_WARN("Error: failed to create cmsis-rtos mutex"); + return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; + +} + +lv_result_t lv_mutex_lock(lv_mutex_t * mutex) +{ + osStatus_t status = osMutexAcquire(*mutex, 0U); + if(status != osOK) { + LV_LOG_WARN("Error: failed to lock cmsis-rtos2 mutex %d", (int)status); + return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_lock_isr(lv_mutex_t * mutex) +{ + osStatus_t status = osMutexAcquire(*mutex, 0U); + if(status != osOK) { + LV_LOG_WARN("Error: failed to lock cmsis-rtos2 mutex in an ISR %d", (int)status); + return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_unlock(lv_mutex_t * mutex) +{ + osStatus_t status = osMutexRelease(*mutex); + if(status != osOK) { + LV_LOG_WARN("Error: failed to release cmsis-rtos2 mutex %d", (int)status); + return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_delete(lv_mutex_t * mutex) +{ + osStatus_t status = osMutexDelete(*mutex); + if(status != osOK) { + LV_LOG_WARN("Error: failed to delete cmsis-rtos2 mutex %d", (int)status); + return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_init(lv_thread_sync_t * sync) +{ + *sync = osEventFlagsNew(NULL); + if(NULL == *sync) { + LV_LOG_WARN("Error: failed to create a cmsis-rtos2 EventFlag"); + return LV_RESULT_INVALID; + } + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_wait(lv_thread_sync_t * sync) +{ + uint32_t ret = osEventFlagsWait(*sync, 0x01, osFlagsWaitAny, osWaitForever); + if(ret & (1 << 31)) { + LV_LOG_WARN("Error: failed to wait a cmsis-rtos2 EventFlag %d", ret); + return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_signal(lv_thread_sync_t * sync) +{ + uint32_t ret = osEventFlagsSet(*sync, 0x01); + if(ret & (1 << 31)) { + LV_LOG_WARN("Error: failed to set a cmsis-rtos2 EventFlag %d", ret); + return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_delete(lv_thread_sync_t * sync) +{ + osStatus_t status = osEventFlagsDelete(*sync); + if(status != osOK) { + LV_LOG_WARN("Error: failed to delete a cmsis-rtos2 EventFlag %d", (int)status); + return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_OS == LV_OS_CMSIS_RTOS2*/ diff --git a/lib/libesp32_lvgl/lvgl/src/osal/lv_cmsis_rtos2.h b/lib/libesp32_lvgl/lvgl/src/osal/lv_cmsis_rtos2.h new file mode 100644 index 000000000..62481e7e8 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/osal/lv_cmsis_rtos2.h @@ -0,0 +1,53 @@ +/** + * @file lv_cmsis_rtos2.h + * + */ + +/* + * Copyright (C) 2023 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef LV_CMSIS_RTOS2_H +#define LV_CMSIS_RTOS2_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#if LV_USE_OS == LV_OS_CMSIS_RTOS2 + +#include "cmsis_os2.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef osThreadId_t lv_thread_t; + +typedef osMutexId_t lv_mutex_t; + +typedef osEventFlagsId_t lv_thread_sync_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_OS == LV_OS_CMSIS_RTOS2*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_OS_CMSIS_RTOS2*/ diff --git a/lib/libesp32_lvgl/lvgl/src/osal/lv_freertos.c b/lib/libesp32_lvgl/lvgl/src/osal/lv_freertos.c new file mode 100644 index 000000000..bc3f7d9d8 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/osal/lv_freertos.c @@ -0,0 +1,423 @@ +/** + * @file lv_freertos.c + * + */ + +/** + * Copyright 2023 NXP + * + * SPDX-License-Identifier: MIT + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_os.h" + +#if LV_USE_OS == LV_OS_FREERTOS + +#include "atomic.h" +#include "../misc/lv_log.h" + +/********************* + * DEFINES + *********************/ + +#define ulMAX_COUNT 10U +#ifndef pcTASK_NAME + #define pcTASK_NAME "lvglDraw" +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void prvRunThread(void * pxArg); + +static void prvMutexInit(lv_mutex_t * pxMutex); + +static void prvCheckMutexInit(lv_mutex_t * pxMutex); + +#if !USE_FREERTOS_TASK_NOTIFY +static void prvCondInit(lv_thread_sync_t * pxCond); + +static void prvCheckCondInit(lv_thread_sync_t * pxCond); + +static void prvTestAndDecrement(lv_thread_sync_t * pxCond, + uint32_t ulLocalWaitingThreads); +#endif + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_result_t lv_thread_init(lv_thread_t * pxThread, lv_thread_prio_t xSchedPriority, + void (*pvStartRoutine)(void *), size_t usStackSize, + void * xAttr) +{ + pxThread->xTaskArg = xAttr; + pxThread->pvStartRoutine = pvStartRoutine; + + BaseType_t xTaskCreateStatus = xTaskCreate( + prvRunThread, + pcTASK_NAME, + (uint16_t)usStackSize, + (void *)pxThread, + tskIDLE_PRIORITY + xSchedPriority, + &pxThread->xTaskHandle); + + /* Ensure that the FreeRTOS task was successfully created. */ + if(xTaskCreateStatus != pdPASS) { + LV_LOG_ERROR("xTaskCreate failed!"); + return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; +} + +lv_result_t lv_thread_delete(lv_thread_t * pxThread) +{ + vTaskDelete(pxThread->xTaskHandle); + + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_init(lv_mutex_t * pxMutex) +{ + /* If mutex in uninitialized, perform initialization. */ + prvCheckMutexInit(pxMutex); + + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_lock(lv_mutex_t * pxMutex) +{ + /* If mutex in uninitialized, perform initialization. */ + prvCheckMutexInit(pxMutex); + + BaseType_t xMutexTakeStatus = xSemaphoreTake(pxMutex->xMutex, portMAX_DELAY); + if(xMutexTakeStatus != pdTRUE) { + LV_LOG_ERROR("xSemaphoreTake failed!"); + return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_lock_isr(lv_mutex_t * pxMutex) +{ + /* If mutex in uninitialized, perform initialization. */ + prvCheckMutexInit(pxMutex); + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + BaseType_t xMutexTakeStatus = xSemaphoreTakeFromISR(pxMutex->xMutex, &xHigherPriorityTaskWoken); + if(xMutexTakeStatus != pdTRUE) { + LV_LOG_ERROR("xSemaphoreTake failed!"); + return LV_RESULT_INVALID; + } + + /* If xHigherPriorityTaskWoken is now set to pdTRUE then a context switch + should be performed to ensure the interrupt returns directly to the highest + priority task. The macro used for this purpose is dependent on the port in + use and may be called portEND_SWITCHING_ISR(). */ + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_unlock(lv_mutex_t * pxMutex) +{ + /* If mutex in uninitialized, perform initialization. */ + prvCheckMutexInit(pxMutex); + + BaseType_t xMutexGiveStatus = xSemaphoreGive(pxMutex->xMutex); + if(xMutexGiveStatus != pdTRUE) { + LV_LOG_ERROR("xSemaphoreGive failed!"); + return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_delete(lv_mutex_t * pxMutex) +{ + vSemaphoreDelete(pxMutex->xMutex); + pxMutex->xIsInitialized = pdFALSE; + + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_init(lv_thread_sync_t * pxCond) +{ +#if USE_FREERTOS_TASK_NOTIFY + /* Store the handle of the calling task. */ + pxCond->xTaskToNotify = xTaskGetCurrentTaskHandle(); +#else + /* If the cond is uninitialized, perform initialization. */ + prvCheckCondInit(pxCond); +#endif + + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_wait(lv_thread_sync_t * pxCond) +{ + lv_result_t lvRes = LV_RESULT_OK; + +#if USE_FREERTOS_TASK_NOTIFY + LV_UNUSED(pxCond); + + /* Wait for other task to notify this task. */ + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); +#else + uint32_t ulLocalWaitingThreads; + + /* If the cond is uninitialized, perform initialization. */ + prvCheckCondInit(pxCond); + + /* Acquire the mutex. */ + xSemaphoreTake(pxCond->xSyncMutex, portMAX_DELAY); + + while(!pxCond->xSyncSignal) { + /* Increase the counter of threads blocking on condition variable, then + * release the mutex. */ + + /* Atomically increments thread waiting by 1, and + * stores number of threads waiting before increment. */ + ulLocalWaitingThreads = Atomic_Increment_u32(&pxCond->ulWaitingThreads); + + BaseType_t xMutexStatus = xSemaphoreGive(pxCond->xSyncMutex); + + /* Wait on the condition variable. */ + if(xMutexStatus == pdTRUE) { + BaseType_t xCondWaitStatus = xSemaphoreTake( + pxCond->xCondWaitSemaphore, + portMAX_DELAY); + + /* Relock the mutex. */ + xSemaphoreTake(pxCond->xSyncMutex, portMAX_DELAY); + + if(xCondWaitStatus != pdTRUE) { + LV_LOG_ERROR("xSemaphoreTake(xCondWaitSemaphore) failed!"); + lvRes = LV_RESULT_INVALID; + + /* Atomically decrements thread waiting by 1. + * If iLocalWaitingThreads is updated by other thread(s) in between, + * this implementation guarantees to decrement by 1 based on the + * value currently in pxCond->ulWaitingThreads. */ + prvTestAndDecrement(pxCond, ulLocalWaitingThreads + 1); + } + } + else { + LV_LOG_ERROR("xSemaphoreGive(xSyncMutex) failed!"); + lvRes = LV_RESULT_INVALID; + + /* Atomically decrements thread waiting by 1. + * If iLocalWaitingThreads is updated by other thread(s) in between, + * this implementation guarantees to decrement by 1 based on the + * value currently in pxCond->ulWaitingThreads. */ + prvTestAndDecrement(pxCond, ulLocalWaitingThreads + 1); + } + } + + pxCond->xSyncSignal = pdFALSE; + + /* Release the mutex. */ + xSemaphoreGive(pxCond->xSyncMutex); +#endif + + return lvRes; +} + +lv_result_t lv_thread_sync_signal(lv_thread_sync_t * pxCond) +{ +#if USE_FREERTOS_TASK_NOTIFY + /* Send a notification to the task waiting. */ + xTaskNotifyGive(pxCond->xTaskToNotify); +#else + /* If the cond is uninitialized, perform initialization. */ + prvCheckCondInit(pxCond); + + /* Acquire the mutex. */ + xSemaphoreTake(pxCond->xSyncMutex, portMAX_DELAY); + + pxCond->xSyncSignal = pdTRUE; + + /* Local copy of number of threads waiting. */ + uint32_t ulLocalWaitingThreads = pxCond->ulWaitingThreads; + + /* Test local copy of threads waiting is larger than zero. */ + while(ulLocalWaitingThreads > 0) { + /* Atomically check whether the copy in memory has changed. + * If not, set the copy of threads waiting in memory to zero. */ + if(ATOMIC_COMPARE_AND_SWAP_SUCCESS == Atomic_CompareAndSwap_u32( + &pxCond->ulWaitingThreads, + 0, + ulLocalWaitingThreads)) { + /* Unblock all. */ + for(uint32_t i = 0; i < ulLocalWaitingThreads; i++) { + xSemaphoreGive(pxCond->xCondWaitSemaphore); + } + + break; + } + + /* Local copy is out dated. Reload from memory and retry. */ + ulLocalWaitingThreads = pxCond->ulWaitingThreads; + } + + /* Release the mutex. */ + xSemaphoreGive(pxCond->xSyncMutex); +#endif + + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_delete(lv_thread_sync_t * pxCond) +{ +#if USE_FREERTOS_TASK_NOTIFY + LV_UNUSED(pxCond); +#else + /* Cleanup all resources used by the cond. */ + vSemaphoreDelete(pxCond->xCondWaitSemaphore); + vSemaphoreDelete(pxCond->xSyncMutex); + pxCond->ulWaitingThreads = 0; + pxCond->xSyncSignal = pdFALSE; + pxCond->xIsInitialized = pdFALSE; +#endif + + return LV_RESULT_OK; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void prvRunThread(void * pxArg) +{ + lv_thread_t * pxThread = (lv_thread_t *)pxArg; + + /* Run the thread routine. */ + pxThread->pvStartRoutine((void *)pxThread->xTaskArg); + + vTaskDelete(NULL); +} + +static void prvMutexInit(lv_mutex_t * pxMutex) +{ + pxMutex->xMutex = xSemaphoreCreateMutex(); + + /* Ensure that the FreeRTOS mutex was successfully created. */ + if(pxMutex->xMutex == NULL) { + LV_LOG_ERROR("xSemaphoreCreateMutex failed!"); + return; + } + + /* Mutex successfully created. */ + pxMutex->xIsInitialized = pdTRUE; +} + +static void prvCheckMutexInit(lv_mutex_t * pxMutex) +{ + /* Check if the mutex needs to be initialized. */ + if(pxMutex->xIsInitialized == pdFALSE) { + /* Mutex initialization must be in a critical section to prevent two threads + * from initializing it at the same time. */ + taskENTER_CRITICAL(); + + /* Check again that the mutex is still uninitialized, i.e. it wasn't + * initialized while this function was waiting to enter the critical + * section. */ + if(pxMutex->xIsInitialized == pdFALSE) { + prvMutexInit(pxMutex); + } + + /* Exit the critical section. */ + taskEXIT_CRITICAL(); + } +} + +#if !USE_FREERTOS_TASK_NOTIFY +static void prvCondInit(lv_thread_sync_t * pxCond) +{ + pxCond->xCondWaitSemaphore = xSemaphoreCreateCounting(ulMAX_COUNT, 0U); + + /* Ensure that the FreeRTOS semaphore was successfully created. */ + if(pxCond->xCondWaitSemaphore == NULL) { + LV_LOG_ERROR("xSemaphoreCreateCounting failed!"); + return; + } + + pxCond->xSyncMutex = xSemaphoreCreateMutex(); + + /* Ensure that the FreeRTOS mutex was successfully created. */ + if(pxCond->xSyncMutex == NULL) { + LV_LOG_ERROR("xSemaphoreCreateMutex failed!"); + /* Cleanup. */ + vSemaphoreDelete(pxCond->xCondWaitSemaphore); + return; + } + + /* Condition variable successfully created. */ + pxCond->ulWaitingThreads = 0; + pxCond->xSyncSignal = pdFALSE; + pxCond->xIsInitialized = pdTRUE; +} + +static void prvCheckCondInit(lv_thread_sync_t * pxCond) +{ + BaseType_t xSemCreateStatus = pdTRUE; + + /* Check if the condition variable needs to be initialized. */ + if(pxCond->xIsInitialized == pdFALSE) { + /* Cond initialization must be in a critical section to prevent two + * threads from initializing it at the same time. */ + taskENTER_CRITICAL(); + + /* Check again that the condition is still uninitialized, i.e. it wasn't + * initialized while this function was waiting to enter the critical + * section. */ + if(pxCond->xIsInitialized == pdFALSE) { + prvCondInit(pxCond); + } + + /* Exit the critical section. */ + taskEXIT_CRITICAL(); + } +} + +static void prvTestAndDecrement(lv_thread_sync_t * pxCond, + uint32_t ulLocalWaitingThreads) +{ + /* Test local copy of threads waiting is larger than zero. */ + while(ulLocalWaitingThreads > 0) { + /* Atomically check whether the copy in memory has changed. + * If not, decrease the copy of threads waiting in memory. */ + if(ATOMIC_COMPARE_AND_SWAP_SUCCESS == Atomic_CompareAndSwap_u32( + &pxCond->ulWaitingThreads, + ulLocalWaitingThreads - 1, + ulLocalWaitingThreads)) { + /* Signal one succeeded. Break. */ + break; + } + + /* Local copy may be out dated. Reload from memory and retry. */ + ulLocalWaitingThreads = pxCond->ulWaitingThreads; + } +} +#endif + +#endif /*LV_USE_OS == LV_OS_FREERTOS*/ diff --git a/lib/libesp32_lvgl/lvgl/src/osal/lv_freertos.h b/lib/libesp32_lvgl/lvgl/src/osal/lv_freertos.h new file mode 100644 index 000000000..06f98f39a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/osal/lv_freertos.h @@ -0,0 +1,84 @@ +/** + * @file lv_freertos.h + * + */ + +/** + * Copyright 2023 NXP + * + * SPDX-License-Identifier: MIT + */ + +#ifndef LV_FREERTOS_H +#define LV_FREERTOS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_os.h" + +#if LV_USE_OS == LV_OS_FREERTOS + +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/********************* + * DEFINES + *********************/ + +/* + * Unblocking an RTOS task with a direct notification is 45% faster and uses less RAM + * than unblocking a task using an intermediary object such as a binary semaphore. + * + * RTOS task notifications can only be used when there is only one task that can be the recipient of the event. + */ +#define USE_FREERTOS_TASK_NOTIFY 1 + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + void (*pvStartRoutine)(void *); /**< Application thread function. */ + void * xTaskArg; /**< Arguments for application thread function. */ + TaskHandle_t xTaskHandle; /**< FreeRTOS task handle. */ +} lv_thread_t; + +typedef struct { + BaseType_t xIsInitialized; /**< Set to pdTRUE if this mutex is initialized, pdFALSE otherwise. */ + SemaphoreHandle_t xMutex; /**< FreeRTOS mutex. */ +} lv_mutex_t; + +typedef struct { +#if USE_FREERTOS_TASK_NOTIFY + TaskHandle_t xTaskToNotify; +#else + BaseType_t + xIsInitialized; /**< Set to pdTRUE if this condition variable is initialized, pdFALSE otherwise. */ + SemaphoreHandle_t xCondWaitSemaphore; /**< Threads block on this semaphore in lv_thread_sync_wait. */ + uint32_t ulWaitingThreads; /**< The number of threads currently waiting on this condition variable. */ + SemaphoreHandle_t xSyncMutex; /**< Threads take this mutex before accessing the condition variable. */ + BaseType_t xSyncSignal; /**< Set to pdTRUE if the thread is signaled, pdFALSE otherwise. */ +#endif +} lv_thread_sync_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_OS == LV_OS_FREERTOS*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_FREERTOS_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/osal/lv_os.h b/lib/libesp32_lvgl/lvgl/src/osal/lv_os.h new file mode 100644 index 000000000..9b3254fc2 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/osal/lv_os.h @@ -0,0 +1,155 @@ +/** + * @file lv_os.h + * + */ + +#ifndef LV_OS_H +#define LV_OS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * OS OPTIONS + *********************/ + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include "../misc/lv_types.h" +#include + +#if LV_USE_OS == LV_OS_NONE +#include "lv_os_none.h" +#elif LV_USE_OS == LV_OS_PTHREAD +#include "lv_pthread.h" +#elif LV_USE_OS == LV_OS_FREERTOS +#include "lv_freertos.h" +#elif LV_USE_OS == LV_OS_CMSIS_RTOS2 +#include "lv_cmsis_rtos2.h" +#elif LV_USE_OS == LV_OS_RTTHREAD +#include "lv_rtthread.h" +#elif LV_USE_OS == LV_OS_WINDOWS +#include "lv_windows.h" +#elif LV_USE_OS == LV_OS_CUSTOM +#include LV_OS_CUSTOM_INCLUDE +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef enum { + LV_THREAD_PRIO_LOWEST, + LV_THREAD_PRIO_LOW, + LV_THREAD_PRIO_MID, + LV_THREAD_PRIO_HIGH, + LV_THREAD_PRIO_HIGHEST, +} lv_thread_prio_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/*---------------------------------------- + * These functions needs to be implemented + * for specific operating systems + *---------------------------------------*/ + +/** + * Create a new thread + * @param thread a variable in which the thread will be stored + * @param prio priority of the thread + * @param callback function of the thread + * @param stack_size stack size in bytes + * @param user_data arbitrary data, will be available in the callback + * @return LV_RESULT_OK: success; LV_RESULT_INVALID: failure + */ +lv_result_t lv_thread_init(lv_thread_t * thread, lv_thread_prio_t prio, void (*callback)(void *), size_t stack_size, + void * user_data); + +/** + * Delete a thread + * @param thread the thread to delete + * @return LV_RESULT_OK: success; LV_RESULT_INVALID: failure + */ +lv_result_t lv_thread_delete(lv_thread_t * thread); + +/** + * Create a mutex + * @param mutex a variable in which the thread will be stored + * @return LV_RESULT_OK: success; LV_RESULT_INVALID: failure + */ +lv_result_t lv_mutex_init(lv_mutex_t * mutex); + +/** + * Lock a mutex + * @param mutex the mutex to lock + * @return LV_RESULT_OK: success; LV_RESULT_INVALID: failure + */ +lv_result_t lv_mutex_lock(lv_mutex_t * mutex); + +/** + * Lock a mutex from interrupt + * @param mutex the mutex to lock + * @return LV_RESULT_OK: success; LV_RESULT_INVALID: failure + */ +lv_result_t lv_mutex_lock_isr(lv_mutex_t * mutex); + +/** + * Unlock a mutex + * @param mutex the mutex to unlock + * @return LV_RESULT_OK: success; LV_RESULT_INVALID: failure + */ +lv_result_t lv_mutex_unlock(lv_mutex_t * mutex); + +/** + * Delete a mutex + * @param mutex the mutex to delete + * @return LV_RESULT_OK: success; LV_RESULT_INVALID: failure + */ +lv_result_t lv_mutex_delete(lv_mutex_t * mutex); + +/** + * Create a thread synchronization object + * @param sync a variable in which the sync will be stored + * @return LV_RESULT_OK: success; LV_RESULT_INVALID: failure + */ +lv_result_t lv_thread_sync_init(lv_thread_sync_t * sync); + +/** + * Wait for a "signal" on a sync object + * @param sync a sync object + * @return LV_RESULT_OK: success; LV_RESULT_INVALID: failure + */ +lv_result_t lv_thread_sync_wait(lv_thread_sync_t * sync); + +/** + * Send a wake-up signal to a sync object + * @param sync a sync object + * @return LV_RESULT_OK: success; LV_RESULT_INVALID: failure + */ +lv_result_t lv_thread_sync_signal(lv_thread_sync_t * sync); + +/** + * Delete a sync object + * @param sync a sync object to delete + * @return LV_RESULT_OK: success; LV_RESULT_INVALID: failure + */ +lv_result_t lv_thread_sync_delete(lv_thread_sync_t * sync); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_OS_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/osal/lv_os_none.c b/lib/libesp32_lvgl/lvgl/src/osal/lv_os_none.c new file mode 100644 index 000000000..4e044d057 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/osal/lv_os_none.c @@ -0,0 +1,120 @@ +/** + * @file lv_os_none.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_os.h" + +#if LV_USE_OS == LV_OS_NONE +#include "../misc/lv_types.h" +#include "../misc/lv_assert.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_result_t lv_thread_init(lv_thread_t * thread, lv_thread_prio_t prio, void (*callback)(void *), size_t stack_size, + void * user_data) +{ + LV_UNUSED(thread); + LV_UNUSED(callback); + LV_UNUSED(prio); + LV_UNUSED(stack_size); + LV_UNUSED(user_data); + LV_ASSERT(0); + return LV_RESULT_INVALID; +} + +lv_result_t lv_thread_delete(lv_thread_t * thread) +{ + LV_UNUSED(thread); + LV_ASSERT(0); + return LV_RESULT_INVALID; +} + +lv_result_t lv_mutex_init(lv_mutex_t * mutex) +{ + LV_UNUSED(mutex); + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_lock(lv_mutex_t * mutex) +{ + LV_UNUSED(mutex); + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_lock_isr(lv_mutex_t * mutex) +{ + LV_UNUSED(mutex); + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_unlock(lv_mutex_t * mutex) +{ + LV_UNUSED(mutex); + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_delete(lv_mutex_t * mutex) +{ + LV_UNUSED(mutex); + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_init(lv_thread_sync_t * sync) +{ + LV_UNUSED(sync); + LV_ASSERT(0); + return LV_RESULT_INVALID; +} + +lv_result_t lv_thread_sync_wait(lv_thread_sync_t * sync) +{ + LV_UNUSED(sync); + LV_ASSERT(0); + return LV_RESULT_INVALID; +} + +lv_result_t lv_thread_sync_signal(lv_thread_sync_t * sync) +{ + LV_UNUSED(sync); + LV_ASSERT(0); + return LV_RESULT_INVALID; +} + +lv_result_t lv_thread_sync_delete(lv_thread_sync_t * sync) +{ + LV_UNUSED(sync); + LV_ASSERT(0); + return LV_RESULT_INVALID; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_OS == LV_OS_NONE*/ diff --git a/lib/libesp32_lvgl/lvgl/src/osal/lv_os_none.h b/lib/libesp32_lvgl/lvgl/src/osal/lv_os_none.h new file mode 100644 index 000000000..e08a0dc42 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/osal/lv_os_none.h @@ -0,0 +1,43 @@ +/** + * @file lv_os_none.h + * + */ + +#ifndef LV_OS_NONE_H +#define LV_OS_NONE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#if LV_USE_OS == LV_OS_NONE + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef int lv_mutex_t; +typedef int lv_thread_t; +typedef int lv_thread_sync_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_OS == LV_OS_NONE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_OS_NONE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/osal/lv_pthread.c b/lib/libesp32_lvgl/lvgl/src/osal/lv_pthread.c new file mode 100644 index 000000000..68676c946 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/osal/lv_pthread.c @@ -0,0 +1,164 @@ +/** + * @file lv_pthread.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_os.h" + +#if LV_USE_OS == LV_OS_PTHREAD + +#include +#include "../misc/lv_log.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void * generic_callback(void * user_data); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_result_t lv_thread_init(lv_thread_t * thread, lv_thread_prio_t prio, void (*callback)(void *), size_t stack_size, + void * user_data) +{ + LV_UNUSED(prio); + LV_UNUSED(stack_size); + thread->callback = callback; + thread->user_data = user_data; + pthread_create(&thread->thread, NULL, generic_callback, thread); + return LV_RESULT_OK; +} + +lv_result_t lv_thread_delete(lv_thread_t * thread) +{ + int ret = pthread_join(thread->thread, NULL); + if(ret != 0) { + LV_LOG_WARN("Error: %d", ret); + return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_init(lv_mutex_t * mutex) +{ + int ret = pthread_mutex_init(mutex, NULL); + if(ret) { + LV_LOG_WARN("Error: %d", ret); + return LV_RESULT_INVALID; + } + else { + return LV_RESULT_OK; + } +} + +lv_result_t lv_mutex_lock(lv_mutex_t * mutex) +{ + int ret = pthread_mutex_lock(mutex); + if(ret) { + LV_LOG_WARN("Error: %d", ret); + return LV_RESULT_INVALID; + } + else { + return LV_RESULT_OK; + } +} + +lv_result_t lv_mutex_lock_isr(lv_mutex_t * mutex) +{ + int ret = pthread_mutex_lock(mutex); + if(ret) { + LV_LOG_WARN("Error: %d", ret); + return LV_RESULT_INVALID; + } + else { + return LV_RESULT_OK; + } +} + +lv_result_t lv_mutex_unlock(lv_mutex_t * mutex) +{ + int ret = pthread_mutex_unlock(mutex); + if(ret) { + LV_LOG_WARN("Error: %d", ret); + return LV_RESULT_INVALID; + } + else { + return LV_RESULT_OK; + } +} + +lv_result_t lv_mutex_delete(lv_mutex_t * mutex) +{ + pthread_mutex_destroy(mutex); + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_init(lv_thread_sync_t * sync) +{ + pthread_mutex_init(&sync->mutex, 0); + pthread_cond_init(&sync->cond, 0); + sync->v = false; + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_wait(lv_thread_sync_t * sync) +{ + pthread_mutex_lock(&sync->mutex); + while(!sync->v) { + pthread_cond_wait(&sync->cond, &sync->mutex); + } + sync->v = false; + pthread_mutex_unlock(&sync->mutex); + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_signal(lv_thread_sync_t * sync) +{ + pthread_mutex_lock(&sync->mutex); + sync->v = true; + pthread_cond_signal(&sync->cond); + pthread_mutex_unlock(&sync->mutex); + + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_delete(lv_thread_sync_t * sync) +{ + pthread_mutex_destroy(&sync->mutex); + pthread_cond_destroy(&sync->cond); + return LV_RESULT_OK; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void * generic_callback(void * user_data) +{ + lv_thread_t * thread = user_data; + thread->callback(thread->user_data); + return NULL; +} + +#endif /*LV_USE_OS == LV_OS_PTHREAD*/ diff --git a/lib/libesp32_lvgl/lvgl/src/osal/lv_pthread.h b/lib/libesp32_lvgl/lvgl/src/osal/lv_pthread.h new file mode 100644 index 000000000..e7abc90cf --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/osal/lv_pthread.h @@ -0,0 +1,57 @@ +/** + * @file lv_pthread.h + * + */ + +#ifndef LV_PTHREAD_H +#define LV_PTHREAD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#if LV_USE_OS == LV_OS_PTHREAD + +#include +#include +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + pthread_t thread; + void (*callback)(void *); + void * user_data; +} lv_thread_t; + +typedef pthread_mutex_t lv_mutex_t; + +typedef struct { + pthread_mutex_t mutex; + pthread_cond_t cond; + bool v; +} lv_thread_sync_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_OS == LV_OS_PTHREAD*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_PTHREAD_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/osal/lv_rtthread.c b/lib/libesp32_lvgl/lvgl/src/osal/lv_rtthread.c new file mode 100644 index 000000000..39f78d784 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/osal/lv_rtthread.c @@ -0,0 +1,184 @@ +/** + * @file lv_rtthread.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_os.h" + +#if LV_USE_OS == LV_OS_RTTHREAD + +#include "../misc/lv_log.h" + +/********************* + * DEFINES + *********************/ + +#define THREAD_TIMESLICE 20U + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_result_t lv_thread_init(lv_thread_t * thread, lv_thread_prio_t prio, void (*callback)(void *), size_t stack_size, + void * user_data) +{ + thread->thread = rt_thread_create("thread", + callback, + user_data, + stack_size, + prio, + THREAD_TIMESLICE); + rt_err_t ret = rt_thread_startup(thread->thread); + if(ret) { + LV_LOG_WARN("Error: %d", ret); + return LV_RESULT_INVALID; + } + else { + return LV_RESULT_OK; + } +} + +lv_result_t lv_thread_delete(lv_thread_t * thread) +{ + rt_err_t ret = rt_thread_delete(thread->thread); + if(ret) { + LV_LOG_WARN("Error: %d", ret); + return LV_RESULT_INVALID; + } + else { + return LV_RESULT_OK; + } +} + +lv_result_t lv_mutex_init(lv_mutex_t * mutex) +{ + mutex->mutex = rt_mutex_create("mutex", RT_IPC_FLAG_PRIO); + if(mutex->mutex == RT_NULL) { + LV_LOG_WARN("create mutex failed"); + return LV_RESULT_INVALID; + } + else { + return LV_RESULT_OK; + } +} + +lv_result_t lv_mutex_lock(lv_mutex_t * mutex) +{ + rt_err_t ret = rt_mutex_take(mutex->mutex, RT_WAITING_FOREVER); + if(ret) { + LV_LOG_WARN("Error: %d", ret); + return LV_RESULT_INVALID; + } + else { + return LV_RESULT_OK; + } +} + +lv_result_t lv_mutex_lock_isr(lv_mutex_t * mutex) +{ + rt_err_t ret = rt_mutex_take(mutex->mutex, RT_WAITING_FOREVER); + if(ret) { + LV_LOG_WARN("Error: %d", ret); + return LV_RESULT_INVALID; + } + else { + return LV_RESULT_OK; + } +} + +lv_result_t lv_mutex_unlock(lv_mutex_t * mutex) +{ + rt_err_t ret = rt_mutex_release(mutex->mutex); + if(ret) { + LV_LOG_WARN("Error: %d", ret); + return LV_RESULT_INVALID; + } + else { + return LV_RESULT_OK; + } +} + +lv_result_t lv_mutex_delete(lv_mutex_t * mutex) +{ + rt_err_t ret = rt_mutex_delete(mutex->mutex); + if(ret) { + LV_LOG_WARN("Error: %d", ret); + return LV_RESULT_INVALID; + } + else { + return LV_RESULT_OK; + } +} + +lv_result_t lv_thread_sync_init(lv_thread_sync_t * sync) +{ + sync->sem = rt_sem_create("sem", 0, RT_IPC_FLAG_PRIO); + if(sync->sem == RT_NULL) { + LV_LOG_WARN("create semaphore failed"); + return LV_RESULT_INVALID; + } + else { + return LV_RESULT_OK; + } +} + +lv_result_t lv_thread_sync_wait(lv_thread_sync_t * sync) +{ + rt_err_t ret = rt_sem_take(sync->sem, RT_WAITING_FOREVER); + if(ret) { + LV_LOG_WARN("Error: %d", ret); + return LV_RESULT_INVALID; + } + else { + return LV_RESULT_OK; + } +} + +lv_result_t lv_thread_sync_signal(lv_thread_sync_t * sync) +{ + rt_err_t ret = rt_sem_release(sync->sem); + if(ret) { + LV_LOG_WARN("Error: %d", ret); + return LV_RESULT_INVALID; + } + else { + return LV_RESULT_OK; + } +} + +lv_result_t lv_thread_sync_delete(lv_thread_sync_t * sync) +{ + rt_err_t ret = rt_sem_delete(sync->sem); + if(ret) { + LV_LOG_WARN("Error: %d", ret); + return LV_RESULT_INVALID; + } + else { + return LV_RESULT_OK; + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_OS == LV_OS_RTTHREAD*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/lv_libs.h b/lib/libesp32_lvgl/lvgl/src/osal/lv_rtthread.h similarity index 53% rename from lib/libesp32_lvgl/lvgl/src/extra/libs/lv_libs.h rename to lib/libesp32_lvgl/lvgl/src/osal/lv_rtthread.h index 1fefe6c11..255a47afe 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/lv_libs.h +++ b/lib/libesp32_lvgl/lvgl/src/osal/lv_rtthread.h @@ -1,10 +1,10 @@ /** - * @file lv_libs.h + * @file lv_rtthread.h * */ -#ifndef LV_LIBS_H -#define LV_LIBS_H +#ifndef LV_RTTHREAD_H +#define LV_RTTHREAD_H #ifdef __cplusplus extern "C" { @@ -13,16 +13,10 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "bmp/lv_bmp.h" -#include "fsdrv/lv_fsdrv.h" -#include "png/lv_png.h" -#include "gif/lv_gif.h" -#include "qrcode/lv_qrcode.h" -#include "sjpg/lv_sjpg.h" -#include "freetype/lv_freetype.h" -#include "rlottie/lv_rlottie.h" -#include "ffmpeg/lv_ffmpeg.h" -#include "tiny_ttf/lv_tiny_ttf.h" +#if LV_USE_OS == LV_OS_RTTHREAD + +#include +#include /********************* * DEFINES @@ -31,6 +25,17 @@ extern "C" { /********************** * TYPEDEFS **********************/ +typedef struct { + rt_thread_t thread; +} lv_thread_t; + +typedef struct { + rt_mutex_t mutex; +} lv_mutex_t; + +typedef struct { + rt_sem_t sem; +} lv_thread_sync_t; /********************** * GLOBAL PROTOTYPES @@ -40,8 +45,10 @@ extern "C" { * MACROS **********************/ +#endif /*LV_USE_OS == LV_OS_RTTHREAD*/ + #ifdef __cplusplus } /*extern "C"*/ #endif -#endif /*LV_LIBS_H*/ +#endif /*LV_RTTHREAD_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/osal/lv_windows.c b/lib/libesp32_lvgl/lvgl/src/osal/lv_windows.c new file mode 100644 index 000000000..0d6a33d66 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/osal/lv_windows.c @@ -0,0 +1,215 @@ +/** + * @file lv_windows.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_os.h" + +#if LV_USE_OS == LV_OS_WINDOWS + +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + void (*callback)(void *); + void * user_data; +} lv_thread_init_data_t; + +/********************** + * STATIC PROTOTYPES + **********************/ + +static unsigned __stdcall thread_start_routine(void * parameter); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_result_t lv_thread_init( + lv_thread_t * thread, + lv_thread_prio_t prio, + void (*callback)(void *), + size_t stack_size, + void * user_data) +{ + if(!thread) { + return LV_RESULT_INVALID; + } + + static const int prio_map[] = { + [LV_THREAD_PRIO_LOWEST] = THREAD_PRIORITY_LOWEST, + [LV_THREAD_PRIO_LOW] = THREAD_PRIORITY_BELOW_NORMAL, + [LV_THREAD_PRIO_MID] = THREAD_PRIORITY_NORMAL, + [LV_THREAD_PRIO_HIGH] = THREAD_PRIORITY_ABOVE_NORMAL, + [LV_THREAD_PRIO_HIGHEST] = THREAD_PRIORITY_HIGHEST, + }; + + lv_thread_init_data_t * init_data = + (lv_thread_init_data_t *)(malloc( + sizeof(lv_thread_init_data_t))); + if(!init_data) { + return LV_RESULT_INVALID; + } + init_data->callback = callback; + init_data->user_data = user_data; + + /* + Reference: https://learn.microsoft.com/en-us/windows/win32/api + /processthreadsapi/nf-processthreadsapi-createthread + + A thread in an executable that calls the C run-time library (CRT) should + use the _beginthreadex and _endthreadex functions for thread management + rather than CreateThread and ExitThread; this requires the use of the + multithreaded version of the CRT. If a thread created using CreateThread + calls the CRT, the CRT may terminate the process in low-memory conditions. + */ + *thread = (HANDLE)(_beginthreadex( + NULL, + (unsigned)(stack_size), + thread_start_routine, + init_data, + 0, + NULL)); + if(!*thread) { + return LV_RESULT_INVALID; + } + + /* + Try to set the thread priority. (Not mandatory for creating a new thread.) + */ + SetThreadPriority(*thread, prio_map[prio]); + + return LV_RESULT_OK; +} + +lv_result_t lv_thread_delete(lv_thread_t * thread) +{ + lv_result_t result = LV_RESULT_OK; + + if(!TerminateThread(thread, 0)) { + result = LV_RESULT_INVALID; + } + + CloseHandle(thread); + + return result; +} + +lv_result_t lv_mutex_init(lv_mutex_t * mutex) +{ + InitializeCriticalSection(mutex); + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_lock(lv_mutex_t * mutex) +{ + EnterCriticalSection(mutex); + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_lock_isr(lv_mutex_t * mutex) +{ + EnterCriticalSection(mutex); + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_unlock(lv_mutex_t * mutex) +{ + LeaveCriticalSection(mutex); + return LV_RESULT_OK; +} + +lv_result_t lv_mutex_delete(lv_mutex_t * mutex) +{ + DeleteCriticalSection(mutex); + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_init(lv_thread_sync_t * sync) +{ + if(!sync) { + return LV_RESULT_INVALID; + } + + InitializeCriticalSection(&sync->cs); + InitializeConditionVariable(&sync->cv); + + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_wait(lv_thread_sync_t * sync) +{ + if(!sync) { + return LV_RESULT_INVALID; + } + + EnterCriticalSection(&sync->cs); + while(!sync->v) { + SleepConditionVariableCS(&sync->cv, &sync->cs, INFINITE); + } + sync->v = false; + LeaveCriticalSection(&sync->cs); + + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_signal(lv_thread_sync_t * sync) +{ + if(!sync) { + return LV_RESULT_INVALID; + } + + EnterCriticalSection(&sync->cs); + sync->v = true; + WakeConditionVariable(&sync->cv); + LeaveCriticalSection(&sync->cs); + + return LV_RESULT_OK; +} + +lv_result_t lv_thread_sync_delete(lv_thread_sync_t * sync) +{ + if(!sync) { + return LV_RESULT_INVALID; + } + + DeleteCriticalSection(&sync->cs); + + return LV_RESULT_OK; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static unsigned __stdcall thread_start_routine(void * parameter) +{ + lv_thread_init_data_t * init_data = (lv_thread_init_data_t *)(parameter); + if(init_data) { + init_data->callback(init_data->user_data); + free(init_data); + } + + return 0; +} + +#endif /*LV_USE_OS == LV_OS_WINDOWS*/ diff --git a/lib/libesp32_lvgl/lvgl/src/osal/lv_windows.h b/lib/libesp32_lvgl/lvgl/src/osal/lv_windows.h new file mode 100644 index 000000000..fd930e872 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/osal/lv_windows.h @@ -0,0 +1,54 @@ +/** + * @file lv_windows.h + * + */ + +#ifndef LV_WINDOWS_H +#define LV_WINDOWS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#if LV_USE_OS == LV_OS_WINDOWS + +#include +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef HANDLE lv_thread_t; + +typedef CRITICAL_SECTION lv_mutex_t; + +typedef struct { + CRITICAL_SECTION cs; + CONDITION_VARIABLE cv; + bool v; +} lv_thread_sync_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_OS == LV_OS_WINDOWS*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_WINDOWS_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/others/file_explorer/lv_file_explorer.c b/lib/libesp32_lvgl/lvgl/src/others/file_explorer/lv_file_explorer.c new file mode 100644 index 000000000..acc73f004 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/others/file_explorer/lv_file_explorer.c @@ -0,0 +1,704 @@ +/** + * @file lv_file_explorer.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_file_explorer.h" +#if LV_USE_FILE_EXPLORER != 0 + +#include "../../core/lv_global.h" + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_file_explorer_class + +#define FILE_EXPLORER_QUICK_ACCESS_AREA_WIDTH (22) +#define FILE_EXPLORER_BROWSER_AREA_WIDTH (100 - FILE_EXPLORER_QUICK_ACCESS_AREA_WIDTH) + +#define quick_access_list_button_style (LV_GLOBAL_DEFAULT()->fe_list_button_style) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_file_explorer_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); + +static void browser_file_event_handler(lv_event_t * e); +#if LV_FILE_EXPLORER_QUICK_ACCESS + static void quick_access_event_handler(lv_event_t * e); + static void quick_access_area_event_handler(lv_event_t * e); +#endif + +static void init_style(lv_obj_t * obj); +static void show_dir(lv_obj_t * obj, const char * path); +static void strip_ext(char * dir); +static void file_explorer_sort(lv_obj_t * obj); +static void sort_by_file_kind(lv_obj_t * tb, int16_t lo, int16_t hi); +static void exch_table_item(lv_obj_t * tb, int16_t i, int16_t j); +static bool is_end_with(const char * str1, const char * str2); + +/********************** + * STATIC VARIABLES + **********************/ + +const lv_obj_class_t lv_file_explorer_class = { + .constructor_cb = lv_file_explorer_constructor, + .width_def = LV_SIZE_CONTENT, + .height_def = LV_SIZE_CONTENT, + .instance_size = sizeof(lv_file_explorer_t), + .base_class = &lv_obj_class, + .name = "file-explorer", +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_file_explorer_create(lv_obj_t * parent) +{ + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + return obj; +} + +/*===================== + * Setter functions + *====================*/ +#if LV_FILE_EXPLORER_QUICK_ACCESS +void lv_file_explorer_set_quick_access_path(lv_obj_t * obj, lv_file_explorer_dir_t dir, const char * path) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + /*If path is unavailable */ + if((path == NULL) || (lv_strlen(path) <= 0)) return; + + char ** dir_str = NULL; + switch(dir) { + case LV_EXPLORER_HOME_DIR: + dir_str = &(explorer->home_dir); + break; + case LV_EXPLORER_MUSIC_DIR: + dir_str = &(explorer->music_dir); + break; + case LV_EXPLORER_PICTURES_DIR: + dir_str = &(explorer->pictures_dir); + break; + case LV_EXPLORER_VIDEO_DIR: + dir_str = &(explorer->video_dir); + break; + case LV_EXPLORER_DOCS_DIR: + dir_str = &(explorer->docs_dir); + break; + case LV_EXPLORER_FS_DIR: + dir_str = &(explorer->fs_dir); + break; + + default: + return; + break; + } + + /*Free the old text*/ + if(*dir_str != NULL) { + lv_free(*dir_str); + *dir_str = NULL; + } + + /*Allocate space for the new text*/ + *dir_str = lv_strdup(path); +} + +#endif + +void lv_file_explorer_set_sort(lv_obj_t * obj, lv_file_explorer_sort_t sort) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + explorer->sort = sort; + + file_explorer_sort(obj); +} + +/*===================== + * Getter functions + *====================*/ +const char * lv_file_explorer_get_selected_file_name(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + return explorer->sel_fn; +} + +const char * lv_file_explorer_get_current_path(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + return explorer->current_path; +} + +lv_obj_t * lv_file_explorer_get_file_table(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + return explorer->file_table; +} + +lv_obj_t * lv_file_explorer_get_header(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + return explorer->head_area; +} + +lv_obj_t * lv_file_explorer_get_quick_access_area(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + return explorer->quick_access_area; +} + +lv_obj_t * lv_file_explorer_get_path_label(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + return explorer->path_label; +} + +#if LV_FILE_EXPLORER_QUICK_ACCESS +lv_obj_t * lv_file_explorer_get_places_list(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + return explorer->list_places; +} + +lv_obj_t * lv_file_explorer_get_device_list(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + return explorer->list_device; +} + +#endif + +lv_file_explorer_sort_t lv_file_explorer_get_sort(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + return explorer->sort; +} + +/*===================== + * Other functions + *====================*/ +void lv_file_explorer_open_dir(lv_obj_t * obj, const char * dir) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + show_dir(obj, dir); +} + +/********************** + * STATIC FUNCTIONS + **********************/ +static void lv_file_explorer_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + LV_TRACE_OBJ_CREATE("begin"); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + +#if LV_FILE_EXPLORER_QUICK_ACCESS + explorer->home_dir = NULL; + explorer->video_dir = NULL; + explorer->pictures_dir = NULL; + explorer->music_dir = NULL; + explorer->docs_dir = NULL; + explorer->fs_dir = NULL; +#endif + + explorer->sort = LV_EXPLORER_SORT_NONE; + + lv_memzero(explorer->current_path, sizeof(explorer->current_path)); + + lv_obj_set_size(obj, LV_PCT(100), LV_PCT(100)); + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN); + + explorer->cont = lv_obj_create(obj); + lv_obj_set_width(explorer->cont, LV_PCT(100)); + lv_obj_set_flex_grow(explorer->cont, 1); + +#if LV_FILE_EXPLORER_QUICK_ACCESS + /*Quick access bar area on the left*/ + explorer->quick_access_area = lv_obj_create(explorer->cont); + lv_obj_set_size(explorer->quick_access_area, LV_PCT(FILE_EXPLORER_QUICK_ACCESS_AREA_WIDTH), LV_PCT(100)); + lv_obj_set_flex_flow(explorer->quick_access_area, LV_FLEX_FLOW_COLUMN); + lv_obj_add_event_cb(explorer->quick_access_area, quick_access_area_event_handler, LV_EVENT_ALL, + explorer); +#endif + + /*File table area on the right*/ + explorer->browser_area = lv_obj_create(explorer->cont); +#if LV_FILE_EXPLORER_QUICK_ACCESS + lv_obj_set_size(explorer->browser_area, LV_PCT(FILE_EXPLORER_BROWSER_AREA_WIDTH), LV_PCT(100)); +#else + lv_obj_set_size(explorer->browser_area, LV_PCT(100), LV_PCT(100)); +#endif + lv_obj_set_flex_flow(explorer->browser_area, LV_FLEX_FLOW_COLUMN); + + /*The area displayed above the file browse list(head)*/ + explorer->head_area = lv_obj_create(explorer->browser_area); + lv_obj_set_size(explorer->head_area, LV_PCT(100), LV_PCT(14)); + lv_obj_remove_flag(explorer->head_area, LV_OBJ_FLAG_SCROLLABLE); + +#if LV_FILE_EXPLORER_QUICK_ACCESS + /*Two lists of quick access bar*/ + lv_obj_t * btn; + /*list 1*/ + explorer->list_device = lv_list_create(explorer->quick_access_area); + lv_obj_set_size(explorer->list_device, LV_PCT(100), LV_SIZE_CONTENT); + lv_obj_set_style_bg_color(lv_list_add_text(explorer->list_device, "DEVICE"), lv_palette_main(LV_PALETTE_ORANGE), 0); + + btn = lv_list_add_button(explorer->list_device, NULL, LV_SYMBOL_DRIVE " File System"); + lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj); + + /*list 2*/ + explorer->list_places = lv_list_create(explorer->quick_access_area); + lv_obj_set_size(explorer->list_places, LV_PCT(100), LV_SIZE_CONTENT); + lv_obj_set_style_bg_color(lv_list_add_text(explorer->list_places, "PLACES"), lv_palette_main(LV_PALETTE_LIME), 0); + + btn = lv_list_add_button(explorer->list_places, NULL, LV_SYMBOL_HOME " HOME"); + lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj); + btn = lv_list_add_button(explorer->list_places, NULL, LV_SYMBOL_VIDEO " Video"); + lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj); + btn = lv_list_add_button(explorer->list_places, NULL, LV_SYMBOL_IMAGE " Pictures"); + lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj); + btn = lv_list_add_button(explorer->list_places, NULL, LV_SYMBOL_AUDIO " Music"); + lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj); + btn = lv_list_add_button(explorer->list_places, NULL, LV_SYMBOL_FILE " Documents"); + lv_obj_add_event_cb(btn, quick_access_event_handler, LV_EVENT_CLICKED, obj); +#endif + + /*Show current path*/ + explorer->path_label = lv_label_create(explorer->head_area); + lv_label_set_text(explorer->path_label, LV_SYMBOL_EYE_OPEN"https://lvgl.io"); + lv_obj_center(explorer->path_label); + + /*Table showing the contents of the table of contents*/ + explorer->file_table = lv_table_create(explorer->browser_area); + lv_obj_set_size(explorer->file_table, LV_PCT(100), LV_PCT(86)); + lv_table_set_column_width(explorer->file_table, 0, LV_PCT(100)); + lv_table_set_column_count(explorer->file_table, 1); + lv_obj_add_event_cb(explorer->file_table, browser_file_event_handler, LV_EVENT_ALL, obj); + + /*only scroll up and down*/ + lv_obj_set_scroll_dir(explorer->file_table, LV_DIR_TOP | LV_DIR_BOTTOM); + + /*Initialize style*/ + init_style(obj); + + LV_TRACE_OBJ_CREATE("finished"); +} + +static void init_style(lv_obj_t * obj) +{ + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + /*lv_file_explorer obj style*/ + lv_obj_set_style_radius(obj, 0, 0); + lv_obj_set_style_bg_color(obj, lv_color_hex(0xf2f1f6), 0); + + /*main container style*/ + lv_obj_set_style_radius(explorer->cont, 0, 0); + lv_obj_set_style_bg_opa(explorer->cont, LV_OPA_0, 0); + lv_obj_set_style_border_width(explorer->cont, 0, 0); + lv_obj_set_style_outline_width(explorer->cont, 0, 0); + lv_obj_set_style_pad_column(explorer->cont, 0, 0); + lv_obj_set_style_pad_row(explorer->cont, 0, 0); + lv_obj_set_style_flex_flow(explorer->cont, LV_FLEX_FLOW_ROW, 0); + lv_obj_set_style_pad_all(explorer->cont, 0, 0); + lv_obj_set_style_layout(explorer->cont, LV_LAYOUT_FLEX, 0); + + /*head cont style*/ + lv_obj_set_style_radius(explorer->head_area, 0, 0); + lv_obj_set_style_border_width(explorer->head_area, 0, 0); + lv_obj_set_style_pad_top(explorer->head_area, 0, 0); + +#if LV_FILE_EXPLORER_QUICK_ACCESS + /*Quick access bar container style*/ + lv_obj_set_style_pad_all(explorer->quick_access_area, 0, 0); + lv_obj_set_style_pad_row(explorer->quick_access_area, 20, 0); + lv_obj_set_style_radius(explorer->quick_access_area, 0, 0); + lv_obj_set_style_border_width(explorer->quick_access_area, 1, 0); + lv_obj_set_style_outline_width(explorer->quick_access_area, 0, 0); + lv_obj_set_style_bg_color(explorer->quick_access_area, lv_color_hex(0xf2f1f6), 0); +#endif + + /*File browser container style*/ + lv_obj_set_style_pad_all(explorer->browser_area, 0, 0); + lv_obj_set_style_pad_row(explorer->browser_area, 0, 0); + lv_obj_set_style_radius(explorer->browser_area, 0, 0); + lv_obj_set_style_border_width(explorer->browser_area, 0, 0); + lv_obj_set_style_outline_width(explorer->browser_area, 0, 0); + lv_obj_set_style_bg_color(explorer->browser_area, lv_color_hex(0xffffff), 0); + + /*Style of the table in the browser container*/ + lv_obj_set_style_bg_color(explorer->file_table, lv_color_hex(0xffffff), 0); + lv_obj_set_style_pad_all(explorer->file_table, 0, 0); + lv_obj_set_style_radius(explorer->file_table, 0, 0); + lv_obj_set_style_border_width(explorer->file_table, 0, 0); + lv_obj_set_style_outline_width(explorer->file_table, 0, 0); + +#if LV_FILE_EXPLORER_QUICK_ACCESS + /*Style of the list in the quick access bar*/ + lv_obj_set_style_border_width(explorer->list_device, 0, 0); + lv_obj_set_style_outline_width(explorer->list_device, 0, 0); + lv_obj_set_style_radius(explorer->list_device, 0, 0); + lv_obj_set_style_pad_all(explorer->list_device, 0, 0); + + lv_obj_set_style_border_width(explorer->list_places, 0, 0); + lv_obj_set_style_outline_width(explorer->list_places, 0, 0); + lv_obj_set_style_radius(explorer->list_places, 0, 0); + lv_obj_set_style_pad_all(explorer->list_places, 0, 0); + + /*Style of the quick access list btn in the quick access bar*/ + lv_style_init(&quick_access_list_button_style); + lv_style_set_border_width(&quick_access_list_button_style, 0); + lv_style_set_bg_color(&quick_access_list_button_style, lv_color_hex(0xf2f1f6)); + + uint32_t i, j; + for(i = 0; i < lv_obj_get_child_count(explorer->quick_access_area); i++) { + lv_obj_t * child = lv_obj_get_child(explorer->quick_access_area, i); + if(lv_obj_check_type(child, &lv_list_class)) { + for(j = 0; j < lv_obj_get_child_count(child); j++) { + lv_obj_t * list_child = lv_obj_get_child(child, j); + if(lv_obj_check_type(list_child, &lv_list_button_class)) { + lv_obj_add_style(list_child, &quick_access_list_button_style, 0); + } + } + } + } +#endif + +} + +#if LV_FILE_EXPLORER_QUICK_ACCESS +static void quick_access_event_handler(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * btn = lv_event_get_current_target(e); + lv_obj_t * obj = lv_event_get_user_data(e); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + if(code == LV_EVENT_CLICKED) { + char ** path = NULL; + lv_obj_t * label = lv_obj_get_child(btn, -1); + char * label_text = lv_label_get_text(label); + + if((lv_strcmp(label_text, LV_SYMBOL_HOME " HOME") == 0)) { + path = &(explorer->home_dir); + } + else if((lv_strcmp(label_text, LV_SYMBOL_VIDEO " Video") == 0)) { + path = &(explorer->video_dir); + } + else if((lv_strcmp(label_text, LV_SYMBOL_IMAGE " Pictures") == 0)) { + path = &(explorer->pictures_dir); + } + else if((lv_strcmp(label_text, LV_SYMBOL_AUDIO " Music") == 0)) { + path = &(explorer->music_dir); + } + else if((lv_strcmp(label_text, LV_SYMBOL_FILE " Documents") == 0)) { + path = &(explorer->docs_dir); + } + else if((lv_strcmp(label_text, LV_SYMBOL_DRIVE " File System") == 0)) { + path = &(explorer->fs_dir); + } + + if(path != NULL) + show_dir(obj, *path); + } +} + +static void quick_access_area_event_handler(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * area = lv_event_get_current_target(e); + lv_obj_t * obj = lv_event_get_user_data(e); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + if(code == LV_EVENT_LAYOUT_CHANGED) { + if(lv_obj_has_flag(area, LV_OBJ_FLAG_HIDDEN)) + lv_obj_set_size(explorer->browser_area, LV_PCT(100), LV_PCT(100)); + else + lv_obj_set_size(explorer->browser_area, LV_PCT(FILE_EXPLORER_BROWSER_AREA_WIDTH), LV_PCT(100)); + } +} +#endif + +static void browser_file_event_handler(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * obj = lv_event_get_user_data(e); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + if(code == LV_EVENT_VALUE_CHANGED) { + char file_name[LV_FILE_EXPLORER_PATH_MAX_LEN]; + const char * str_fn = NULL; + uint32_t row; + uint32_t col; + + lv_memzero(file_name, sizeof(file_name)); + lv_table_get_selected_cell(explorer->file_table, &row, &col); + str_fn = lv_table_get_cell_value(explorer->file_table, row, col); + + str_fn = str_fn + 5; + if((lv_strcmp(str_fn, ".") == 0)) return; + + if((lv_strcmp(str_fn, "..") == 0) && (lv_strlen(explorer->current_path) > 3)) { + strip_ext(explorer->current_path); + /*Remove the last '/' character*/ + strip_ext(explorer->current_path); + lv_snprintf((char *)file_name, sizeof(file_name), "%s", explorer->current_path); + } + else { + if(lv_strcmp(str_fn, "..") != 0) { + lv_snprintf((char *)file_name, sizeof(file_name), "%s%s", explorer->current_path, str_fn); + } + } + + lv_fs_dir_t dir; + if(lv_fs_dir_open(&dir, file_name) == LV_FS_RES_OK) { + lv_fs_dir_close(&dir); + show_dir(obj, (char *)file_name); + } + else { + if(lv_strcmp(str_fn, "..") != 0) { + explorer->sel_fn = str_fn; + lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); + } + } + } + else if(code == LV_EVENT_SIZE_CHANGED) { + lv_table_set_column_width(explorer->file_table, 0, lv_obj_get_width(explorer->file_table)); + } + else if((code == LV_EVENT_CLICKED) || (code == LV_EVENT_RELEASED)) { + lv_obj_send_event(obj, LV_EVENT_CLICKED, NULL); + } +} + +static void show_dir(lv_obj_t * obj, const char * path) +{ + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + char fn[LV_FILE_EXPLORER_PATH_MAX_LEN]; + uint16_t index = 0; + lv_fs_dir_t dir; + lv_fs_res_t res; + + res = lv_fs_dir_open(&dir, path); + if(res != LV_FS_RES_OK) { + LV_LOG_USER("Open dir error %d!", res); + return; + } + + lv_table_set_cell_value_fmt(explorer->file_table, index++, 0, LV_SYMBOL_DIRECTORY " %s", "."); + lv_table_set_cell_value_fmt(explorer->file_table, index++, 0, LV_SYMBOL_DIRECTORY " %s", ".."); + lv_table_set_cell_value(explorer->file_table, 0, 1, "0"); + lv_table_set_cell_value(explorer->file_table, 1, 1, "0"); + + while(1) { + res = lv_fs_dir_read(&dir, fn, sizeof(fn)); + if(res != LV_FS_RES_OK) { + LV_LOG_USER("Driver, file or directory is not exists %d!", res); + break; + } + + /*fn is empty, if not more files to read*/ + if(lv_strlen(fn) == 0) { + LV_LOG_USER("Not more files to read!"); + break; + } + + if((is_end_with(fn, ".png") == true) || (is_end_with(fn, ".PNG") == true) || \ + (is_end_with(fn, ".jpg") == true) || (is_end_with(fn, ".JPG") == true) || \ + (is_end_with(fn, ".bmp") == true) || (is_end_with(fn, ".BMP") == true) || \ + (is_end_with(fn, ".gif") == true) || (is_end_with(fn, ".GIF") == true)) { + lv_table_set_cell_value_fmt(explorer->file_table, index, 0, LV_SYMBOL_IMAGE " %s", fn); + lv_table_set_cell_value(explorer->file_table, index, 1, "1"); + } + else if((is_end_with(fn, ".mp3") == true) || (is_end_with(fn, ".MP3") == true)) { + lv_table_set_cell_value_fmt(explorer->file_table, index, 0, LV_SYMBOL_AUDIO " %s", fn); + lv_table_set_cell_value(explorer->file_table, index, 1, "2"); + } + else if((is_end_with(fn, ".mp4") == true) || (is_end_with(fn, ".MP4") == true)) { + lv_table_set_cell_value_fmt(explorer->file_table, index, 0, LV_SYMBOL_VIDEO " %s", fn); + lv_table_set_cell_value(explorer->file_table, index, 1, "3"); + } + else if((is_end_with(fn, ".") == true) || (is_end_with(fn, "..") == true)) { + /*is dir*/ + continue; + } + else if(fn[0] == '/') {/*is dir*/ + lv_table_set_cell_value_fmt(explorer->file_table, index, 0, LV_SYMBOL_DIRECTORY " %s", fn + 1); + lv_table_set_cell_value(explorer->file_table, index, 1, "0"); + } + else { + lv_table_set_cell_value_fmt(explorer->file_table, index, 0, LV_SYMBOL_FILE " %s", fn); + lv_table_set_cell_value(explorer->file_table, index, 1, "4"); + } + + index++; + } + + lv_fs_dir_close(&dir); + + lv_table_set_row_count(explorer->file_table, index); + file_explorer_sort(obj); + lv_obj_send_event(obj, LV_EVENT_READY, NULL); + + /*Move the table to the top*/ + lv_obj_scroll_to_y(explorer->file_table, 0, LV_ANIM_OFF); + + lv_memzero(explorer->current_path, sizeof(explorer->current_path)); + lv_strncpy(explorer->current_path, path, sizeof(explorer->current_path) - 1); + lv_label_set_text_fmt(explorer->path_label, LV_SYMBOL_EYE_OPEN" %s", path); + + size_t current_path_len = lv_strlen(explorer->current_path); + if((*((explorer->current_path) + current_path_len) != '/') && (current_path_len < LV_FILE_EXPLORER_PATH_MAX_LEN)) { + *((explorer->current_path) + current_path_len) = '/'; + } +} + +/*Remove the specified suffix*/ +static void strip_ext(char * dir) +{ + char * end = dir + lv_strlen(dir); + + while(end >= dir && *end != '/') { + --end; + } + + if(end > dir) { + *end = '\0'; + } + else if(end == dir) { + *(end + 1) = '\0'; + } +} + +static void exch_table_item(lv_obj_t * tb, int16_t i, int16_t j) +{ + const char * tmp; + tmp = lv_table_get_cell_value(tb, i, 0); + lv_table_set_cell_value(tb, 0, 2, tmp); + lv_table_set_cell_value(tb, i, 0, lv_table_get_cell_value(tb, j, 0)); + lv_table_set_cell_value(tb, j, 0, lv_table_get_cell_value(tb, 0, 2)); + + tmp = lv_table_get_cell_value(tb, i, 1); + lv_table_set_cell_value(tb, 0, 2, tmp); + lv_table_set_cell_value(tb, i, 1, lv_table_get_cell_value(tb, j, 1)); + lv_table_set_cell_value(tb, j, 1, lv_table_get_cell_value(tb, 0, 2)); +} + +static void file_explorer_sort(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_file_explorer_t * explorer = (lv_file_explorer_t *)obj; + + uint16_t sum = lv_table_get_row_count(explorer->file_table); + + if(sum > 1) { + switch(explorer->sort) { + case LV_EXPLORER_SORT_NONE: + break; + case LV_EXPLORER_SORT_KIND: + sort_by_file_kind(explorer->file_table, 0, (sum - 1)); + break; + default: + break; + } + } +} + +/*Quick sort 3 way*/ +static void sort_by_file_kind(lv_obj_t * tb, int16_t lo, int16_t hi) +{ + if(lo >= hi) return; + + int16_t lt = lo; + int16_t i = lo + 1; + int16_t gt = hi; + const char * v = lv_table_get_cell_value(tb, lo, 1); + while(i <= gt) { + if(lv_strcmp(lv_table_get_cell_value(tb, i, 1), v) < 0) + exch_table_item(tb, lt++, i++); + else if(lv_strcmp(lv_table_get_cell_value(tb, i, 1), v) > 0) + exch_table_item(tb, i, gt--); + else + i++; + } + + sort_by_file_kind(tb, lo, lt - 1); + sort_by_file_kind(tb, gt + 1, hi); +} + +static bool is_end_with(const char * str1, const char * str2) +{ + if(str1 == NULL || str2 == NULL) + return false; + + uint16_t len1 = lv_strlen(str1); + uint16_t len2 = lv_strlen(str2); + if((len1 < len2) || (len1 == 0 || len2 == 0)) + return false; + + while(len2 >= 1) { + if(str2[len2 - 1] != str1[len1 - 1]) + return false; + + len2--; + len1--; + } + + return true; +} + +#endif /*LV_USE_FILE_EXPLORER*/ diff --git a/lib/libesp32_lvgl/lvgl/src/others/file_explorer/lv_file_explorer.h b/lib/libesp32_lvgl/lvgl/src/others/file_explorer/lv_file_explorer.h new file mode 100644 index 000000000..cdebe7a49 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/others/file_explorer/lv_file_explorer.h @@ -0,0 +1,191 @@ +/** + * @file lv_file_explorer.h + * + */ + +#ifndef LV_FILE_EXPLORER_H +#define LV_FILE_EXPLORER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_FILE_EXPLORER != 0 + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef enum { + LV_EXPLORER_SORT_NONE, + LV_EXPLORER_SORT_KIND, +} lv_file_explorer_sort_t; + +#if LV_FILE_EXPLORER_QUICK_ACCESS +typedef enum { + LV_EXPLORER_HOME_DIR, + LV_EXPLORER_MUSIC_DIR, + LV_EXPLORER_PICTURES_DIR, + LV_EXPLORER_VIDEO_DIR, + LV_EXPLORER_DOCS_DIR, + LV_EXPLORER_FS_DIR, +} lv_file_explorer_dir_t; +#endif + +/*Data of canvas*/ +typedef struct { + lv_obj_t obj; + lv_obj_t * cont; + lv_obj_t * head_area; + lv_obj_t * browser_area; + lv_obj_t * file_table; + lv_obj_t * path_label; +#if LV_FILE_EXPLORER_QUICK_ACCESS + lv_obj_t * quick_access_area; + lv_obj_t * list_device; + lv_obj_t * list_places; + char * home_dir; + char * music_dir; + char * pictures_dir; + char * video_dir; + char * docs_dir; + char * fs_dir; +#endif + const char * sel_fn; + char current_path[LV_FILE_EXPLORER_PATH_MAX_LEN]; + lv_file_explorer_sort_t sort; +} lv_file_explorer_t; + +extern const lv_obj_class_t lv_file_explorer_class; + +/*********************** + * GLOBAL VARIABLES + ***********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +lv_obj_t * lv_file_explorer_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +#if LV_FILE_EXPLORER_QUICK_ACCESS +/** + * Set file_explorer + * @param obj pointer to a label object + * @param dir the dir from 'lv_file_explorer_dir_t' enum. + * @param path path + + */ +void lv_file_explorer_set_quick_access_path(lv_obj_t * obj, lv_file_explorer_dir_t dir, const char * path); +#endif + +/** + * Set file_explorer sort + * @param obj pointer to a file explorer object + * @param sort the sort from 'lv_file_explorer_sort_t' enum. + */ +void lv_file_explorer_set_sort(lv_obj_t * obj, lv_file_explorer_sort_t sort); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get file explorer Selected file + * @param obj pointer to a file explorer object + * @return pointer to the file explorer selected file name + */ +const char * lv_file_explorer_get_selected_file_name(const lv_obj_t * obj); + +/** + * Get file explorer cur path + * @param obj pointer to a file explorer object + * @return pointer to the file explorer cur path + */ +const char * lv_file_explorer_get_current_path(const lv_obj_t * obj); + +/** + * Get file explorer head area obj + * @param obj pointer to a file explorer object + * @return pointer to the file explorer head area obj(lv_obj) + */ +lv_obj_t * lv_file_explorer_get_header(lv_obj_t * obj); + +/** + * Get file explorer head area obj + * @param obj pointer to a file explorer object + * @return pointer to the file explorer quick access area obj(lv_obj) + */ +lv_obj_t * lv_file_explorer_get_quick_access_area(lv_obj_t * obj); + +/** + * Get file explorer path obj(label) + * @param obj pointer to a file explorer object + * @return pointer to the file explorer path obj(lv_label) + */ +lv_obj_t * lv_file_explorer_get_path_label(lv_obj_t * obj); + +#if LV_FILE_EXPLORER_QUICK_ACCESS +/** + * Get file explorer places list obj(lv_list) + * @param obj pointer to a file explorer object + * @return pointer to the file explorer places list obj(lv_list) + */ +lv_obj_t * lv_file_explorer_get_places_list(lv_obj_t * obj); + +/** + * Get file explorer device list obj(lv_list) + * @param obj pointer to a file explorer object + * @return pointer to the file explorer device list obj(lv_list) + */ +lv_obj_t * lv_file_explorer_get_device_list(lv_obj_t * obj); +#endif + +/** + * Get file explorer file list obj(lv_table) + * @param obj pointer to a file explorer object + * @return pointer to the file explorer file table obj(lv_table) + */ +lv_obj_t * lv_file_explorer_get_file_table(lv_obj_t * obj); + +/** + * Set file_explorer sort + * @param obj pointer to a file explorer object + * @return the current mode from 'lv_file_explorer_sort_t' + */ +lv_file_explorer_sort_t lv_file_explorer_get_sort(const lv_obj_t * obj); + +/*===================== + * Other functions + *====================*/ + +/** + * Open a specified path + * @param obj pointer to a file explorer object + * @param dir pointer to the path + */ +void lv_file_explorer_open_dir(lv_obj_t * obj, const char * dir); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_FILE_EXPLORER*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_FILE_EXPLORER_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/README.md b/lib/libesp32_lvgl/lvgl/src/others/fragment/README.md similarity index 100% rename from lib/libesp32_lvgl/lvgl/src/extra/others/fragment/README.md rename to lib/libesp32_lvgl/lvgl/src/others/fragment/README.md diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment.c b/lib/libesp32_lvgl/lvgl/src/others/fragment/lv_fragment.c similarity index 78% rename from lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment.c rename to lib/libesp32_lvgl/lvgl/src/others/fragment/lv_fragment.c index a2cdfadc2..c04b3e84c 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment.c +++ b/lib/libesp32_lvgl/lvgl/src/others/fragment/lv_fragment.c @@ -10,6 +10,7 @@ #include "lv_fragment.h" #if LV_USE_FRAGMENT +#include "../../stdlib/lv_string.h" /********************** * STATIC PROTOTYPES @@ -25,9 +26,8 @@ lv_fragment_t * lv_fragment_create(const lv_fragment_class_t * cls, void * args) { LV_ASSERT_NULL(cls); LV_ASSERT_NULL(cls->create_obj_cb); - LV_ASSERT(cls->instance_size > 0); - lv_fragment_t * instance = lv_mem_alloc(cls->instance_size); - lv_memset_00(instance, cls->instance_size); + LV_ASSERT(cls->instance_size >= sizeof(lv_fragment_t)); + lv_fragment_t * instance = lv_malloc_zeroed(cls->instance_size); instance->cls = cls; instance->child_manager = lv_fragment_manager_create(instance); if(cls->constructor_cb) { @@ -36,7 +36,7 @@ lv_fragment_t * lv_fragment_create(const lv_fragment_class_t * cls, void * args) return instance; } -void lv_fragment_del(lv_fragment_t * fragment) +void lv_fragment_delete(lv_fragment_t * fragment) { LV_ASSERT_NULL(fragment); if(fragment->managed) { @@ -44,15 +44,15 @@ void lv_fragment_del(lv_fragment_t * fragment) return; } if(fragment->obj) { - lv_fragment_del_obj(fragment); + lv_fragment_delete_obj(fragment); } /* Objects will leak if this function called before objects deleted */ const lv_fragment_class_t * cls = fragment->cls; if(cls->destructor_cb) { cls->destructor_cb(fragment); } - lv_fragment_manager_del(fragment->child_manager); - lv_mem_free(fragment); + lv_fragment_manager_delete(fragment->child_manager); + lv_free(fragment); } lv_fragment_manager_t * lv_fragment_get_manager(lv_fragment_t * fragment) @@ -97,15 +97,26 @@ lv_obj_t * lv_fragment_create_obj(lv_fragment_t * fragment, lv_obj_t * container return obj; } -void lv_fragment_del_obj(lv_fragment_t * fragment) +void lv_fragment_delete_obj(lv_fragment_t * fragment) { LV_ASSERT_NULL(fragment); - lv_fragment_manager_del_obj(fragment->child_manager); + lv_fragment_manager_delete_obj(fragment->child_manager); lv_fragment_managed_states_t * states = fragment->managed; if(states) { if(!states->obj_created) return; states->destroying_obj = true; - bool cb_removed = lv_obj_remove_event_cb(fragment->obj, cb_delete_assertion); + + uint32_t i; + uint32_t event_cnt = lv_obj_get_event_count(fragment->obj); + bool cb_removed = false; + for(i = 0; i < event_cnt; i++) { + lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(fragment->obj, i); + if(lv_event_dsc_get_cb(event_dsc) == cb_delete_assertion) { + cb_removed = lv_obj_remove_event(fragment->obj, i); + break; + } + } + LV_ASSERT(cb_removed); } LV_ASSERT_NULL(fragment->obj); @@ -113,7 +124,7 @@ void lv_fragment_del_obj(lv_fragment_t * fragment) if(cls->obj_will_delete_cb) { cls->obj_will_delete_cb(fragment, fragment->obj); } - lv_obj_del(fragment->obj); + lv_obj_delete(fragment->obj); if(cls->obj_deleted_cb) { cls->obj_deleted_cb(fragment, fragment->obj); } @@ -127,7 +138,7 @@ void lv_fragment_recreate_obj(lv_fragment_t * fragment) { LV_ASSERT_NULL(fragment); LV_ASSERT_NULL(fragment->managed); - lv_fragment_del_obj(fragment); + lv_fragment_delete_obj(fragment); lv_fragment_create_obj(fragment, *fragment->managed->container); } diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment.h b/lib/libesp32_lvgl/lvgl/src/others/fragment/lv_fragment.h similarity index 94% rename from lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment.h rename to lib/libesp32_lvgl/lvgl/src/others/fragment/lv_fragment.h index da30b39a5..593b5b575 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment.h +++ b/lib/libesp32_lvgl/lvgl/src/others/fragment/lv_fragment.h @@ -13,12 +13,10 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../lv_conf_internal.h" +#include "../../core/lv_obj.h" #if LV_USE_FRAGMENT -#include "../../../core/lv_obj.h" - /********************* * DEFINES *********************/ @@ -129,7 +127,7 @@ struct _lv_fragment_class_t { /** * Fragment states */ -typedef struct _lv_fragment_managed_states_t { +struct _lv_fragment_managed_states_t { /** * Class of the fragment */ @@ -151,14 +149,14 @@ typedef struct _lv_fragment_managed_states_t { */ bool obj_created; /** - * true before `lv_fragment_del_obj` is called. Don't touch any object if this is true + * true before `lv_fragment_delete_obj` is called. Don't touch any object if this is true */ bool destroying_obj; /** * true if this fragment is in navigation stack that can be popped */ bool in_stack; -} lv_fragment_managed_states_t; +}; /********************** * GLOBAL PROTOTYPES @@ -175,7 +173,7 @@ lv_fragment_manager_t * lv_fragment_manager_create(lv_fragment_t * parent); * Destroy fragment manager instance * @param manager Fragment manager instance */ -void lv_fragment_manager_del(lv_fragment_manager_t * manager); +void lv_fragment_manager_delete(lv_fragment_manager_t * manager); /** * Create object of all fragments managed by this manager. @@ -187,7 +185,7 @@ void lv_fragment_manager_create_obj(lv_fragment_manager_t * manager); * Delete object created by all fragments managed by this manager. Instance of fragments will not be deleted. * @param manager Fragment manager instance */ -void lv_fragment_manager_del_obj(lv_fragment_manager_t * manager); +void lv_fragment_manager_delete_obj(lv_fragment_manager_t * manager); /** * Attach fragment to manager, and add to container. @@ -266,7 +264,6 @@ lv_fragment_t * lv_fragment_manager_find_by_container(lv_fragment_manager_t * ma */ lv_fragment_t * lv_fragment_manager_get_parent_fragment(lv_fragment_manager_t * manager); - /** * Create a fragment instance. * @@ -280,7 +277,7 @@ lv_fragment_t * lv_fragment_create(const lv_fragment_class_t * cls, void * args) * Destroy a fragment. * @param fragment Fragment instance. */ -void lv_fragment_del(lv_fragment_t * fragment); +void lv_fragment_delete(lv_fragment_t * fragment); /** * Get associated manager of this fragment @@ -317,7 +314,7 @@ lv_obj_t * lv_fragment_create_obj(lv_fragment_t * fragment, lv_obj_t * container * * @param fragment Fragment instance. */ -void lv_fragment_del_obj(lv_fragment_t * fragment); +void lv_fragment_delete_obj(lv_fragment_t * fragment); /** * Destroy obj in fragment, and recreate them. @@ -325,7 +322,6 @@ void lv_fragment_del_obj(lv_fragment_t * fragment); */ void lv_fragment_recreate_obj(lv_fragment_t * fragment); - /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment_manager.c b/lib/libesp32_lvgl/lvgl/src/others/fragment/lv_fragment_manager.c similarity index 87% rename from lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment_manager.c rename to lib/libesp32_lvgl/lvgl/src/others/fragment/lv_fragment_manager.c index ade721587..73b0c9df2 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/fragment/lv_fragment_manager.c +++ b/lib/libesp32_lvgl/lvgl/src/others/fragment/lv_fragment_manager.c @@ -11,7 +11,8 @@ #if LV_USE_FRAGMENT -#include "../../../misc/lv_ll.h" +#include "../../misc/lv_ll.h" +#include "../../stdlib/lv_string.h" /********************* * DEFINES @@ -36,16 +37,15 @@ struct _lv_fragment_manager_t { lv_ll_t stack; }; - /********************** * STATIC PROTOTYPES **********************/ static void item_create_obj(lv_fragment_managed_states_t * item); -static void item_del_obj(lv_fragment_managed_states_t * item); +static void item_delete_obj(lv_fragment_managed_states_t * item); -static void item_del_fragment(lv_fragment_managed_states_t * item); +static void item_delete_fragment(lv_fragment_managed_states_t * item); static lv_fragment_managed_states_t * fragment_attach(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container); @@ -64,25 +64,24 @@ static lv_fragment_managed_states_t * fragment_attach(lv_fragment_manager_t * ma lv_fragment_manager_t * lv_fragment_manager_create(lv_fragment_t * parent) { - lv_fragment_manager_t * instance = lv_mem_alloc(sizeof(lv_fragment_manager_t)); - lv_memset_00(instance, sizeof(lv_fragment_manager_t)); + lv_fragment_manager_t * instance = lv_malloc_zeroed(sizeof(lv_fragment_manager_t)); instance->parent = parent; _lv_ll_init(&instance->attached, sizeof(lv_fragment_managed_states_t)); _lv_ll_init(&instance->stack, sizeof(lv_fragment_stack_item_t)); return instance; } -void lv_fragment_manager_del(lv_fragment_manager_t * manager) +void lv_fragment_manager_delete(lv_fragment_manager_t * manager) { LV_ASSERT_NULL(manager); lv_fragment_managed_states_t * states; _LV_LL_READ_BACK(&manager->attached, states) { - item_del_obj(states); - item_del_fragment(states); + item_delete_obj(states); + item_delete_fragment(states); } _lv_ll_clear(&manager->attached); _lv_ll_clear(&manager->stack); - lv_mem_free(manager); + lv_free(manager); } void lv_fragment_manager_create_obj(lv_fragment_manager_t * manager) @@ -99,12 +98,12 @@ void lv_fragment_manager_create_obj(lv_fragment_manager_t * manager) } } -void lv_fragment_manager_del_obj(lv_fragment_manager_t * manager) +void lv_fragment_manager_delete_obj(lv_fragment_manager_t * manager) { LV_ASSERT_NULL(manager); lv_fragment_managed_states_t * states = NULL; _LV_LL_READ_BACK(&manager->attached, states) { - item_del_obj(states); + item_delete_obj(states); } } @@ -139,13 +138,13 @@ void lv_fragment_manager_remove(lv_fragment_manager_t * manager, lv_fragment_t * } if(item) { _lv_ll_remove(&manager->stack, item); - lv_mem_free(item); + lv_free(item); } } - item_del_obj(states); - item_del_fragment(states); + item_delete_obj(states); + item_delete_fragment(states); _lv_ll_remove(&manager->attached, states); - lv_mem_free(states); + lv_free(states); if(prev && was_top) { item_create_obj(prev); } @@ -155,13 +154,13 @@ void lv_fragment_manager_push(lv_fragment_manager_t * manager, lv_fragment_t * f { lv_fragment_stack_item_t * top = _lv_ll_get_tail(&manager->stack); if(top != NULL) { - item_del_obj(top->states); + item_delete_obj(top->states); } lv_fragment_managed_states_t * states = fragment_attach(manager, fragment, container); states->in_stack = true; /*Add fragment to the top of the stack*/ lv_fragment_stack_item_t * item = _lv_ll_ins_tail(&manager->stack); - lv_memset_00(item, sizeof(lv_fragment_stack_item_t)); + lv_memzero(item, sizeof(lv_fragment_stack_item_t)); item->states = states; item_create_obj(states); } @@ -238,27 +237,26 @@ static void item_create_obj(lv_fragment_managed_states_t * item) lv_fragment_create_obj(item->instance, item->container ? *item->container : NULL); } -static void item_del_obj(lv_fragment_managed_states_t * item) +static void item_delete_obj(lv_fragment_managed_states_t * item) { - lv_fragment_del_obj(item->instance); + lv_fragment_delete_obj(item->instance); } /** * Detach, then destroy fragment * @param item fragment states */ -static void item_del_fragment(lv_fragment_managed_states_t * item) +static void item_delete_fragment(lv_fragment_managed_states_t * item) { lv_fragment_t * instance = item->instance; if(instance->cls->detached_cb) { instance->cls->detached_cb(instance); } instance->managed = NULL; - lv_fragment_del(instance); + lv_fragment_delete(instance); item->instance = NULL; } - static lv_fragment_managed_states_t * fragment_attach(lv_fragment_manager_t * manager, lv_fragment_t * fragment, lv_obj_t * const * container) { @@ -266,7 +264,7 @@ static lv_fragment_managed_states_t * fragment_attach(lv_fragment_manager_t * ma LV_ASSERT(fragment); LV_ASSERT(fragment->managed == NULL); lv_fragment_managed_states_t * states = _lv_ll_ins_tail(&manager->attached); - lv_memset_00(states, sizeof(lv_fragment_managed_states_t)); + lv_memzero(states, sizeof(lv_fragment_managed_states_t)); states->cls = fragment->cls; states->manager = manager; states->container = container; diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.c b/lib/libesp32_lvgl/lvgl/src/others/gridnav/lv_gridnav.c similarity index 80% rename from lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.c rename to lib/libesp32_lvgl/lvgl/src/others/gridnav/lv_gridnav.c index 505a977b8..f49c62d0c 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.c +++ b/lib/libesp32_lvgl/lvgl/src/others/gridnav/lv_gridnav.c @@ -9,9 +9,9 @@ #include "lv_gridnav.h" #if LV_USE_GRIDNAV -#include "../../../misc/lv_assert.h" -#include "../../../misc/lv_math.h" -#include "../../../core/lv_indev.h" +#include "../../misc/lv_assert.h" +#include "../../misc/lv_math.h" +#include "../../indev/lv_indev.h" /********************* * DEFINES @@ -44,8 +44,8 @@ static lv_obj_t * find_chid(lv_obj_t * obj, lv_obj_t * start_child, find_mode_t static lv_obj_t * find_first_focusable(lv_obj_t * obj); static lv_obj_t * find_last_focusable(lv_obj_t * obj); static bool obj_is_focuable(lv_obj_t * obj); -static lv_coord_t get_x_center(lv_obj_t * obj); -static lv_coord_t get_y_center(lv_obj_t * obj); +static int32_t get_x_center(lv_obj_t * obj); +static int32_t get_y_center(lv_obj_t * obj); /********************** * STATIC VARIABLES @@ -63,28 +63,46 @@ void lv_gridnav_add(lv_obj_t * obj, lv_gridnav_ctrl_t ctrl) { lv_gridnav_remove(obj); /*Be sure to not add gridnav twice*/ - lv_gridnav_dsc_t * dsc = lv_mem_alloc(sizeof(lv_gridnav_dsc_t)); + lv_gridnav_dsc_t * dsc = lv_malloc(sizeof(lv_gridnav_dsc_t)); LV_ASSERT_MALLOC(dsc); dsc->ctrl = ctrl; dsc->focused_obj = NULL; lv_obj_add_event_cb(obj, gridnav_event_cb, LV_EVENT_ALL, dsc); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_WITH_ARROW); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLL_WITH_ARROW); } void lv_gridnav_remove(lv_obj_t * obj) { - lv_gridnav_dsc_t * dsc = lv_obj_get_event_user_data(obj, gridnav_event_cb); - if(dsc == NULL) return; /* no gridnav on this object */ + lv_event_dsc_t * event_dsc = NULL; + uint32_t event_cnt = lv_obj_get_event_count(obj); + uint32_t i; + for(i = 0; i < event_cnt; i++) { + event_dsc = lv_obj_get_event_dsc(obj, i); + if(lv_event_dsc_get_cb(event_dsc) == gridnav_event_cb) { + lv_free(lv_event_dsc_get_user_data(event_dsc)); + lv_obj_remove_event(obj, i); + break; + } + } - lv_mem_free(dsc); - lv_obj_remove_event_cb(obj, gridnav_event_cb); } void lv_gridnav_set_focused(lv_obj_t * cont, lv_obj_t * to_focus, lv_anim_enable_t anim_en) { LV_ASSERT_NULL(to_focus); - lv_gridnav_dsc_t * dsc = lv_obj_get_event_user_data(cont, gridnav_event_cb); + + uint32_t i; + uint32_t event_cnt = lv_obj_get_event_count(cont); + lv_gridnav_dsc_t * dsc = NULL; + for(i = 0; i < event_cnt; i++) { + lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(cont, i); + if(lv_event_dsc_get_cb(event_dsc) == gridnav_event_cb) { + dsc = lv_event_dsc_get_user_data(event_dsc); + break; + } + } + if(dsc == NULL) { LV_LOG_WARN("`cont` is not a gridnav container"); return; @@ -95,7 +113,10 @@ void lv_gridnav_set_focused(lv_obj_t * cont, lv_obj_t * to_focus, lv_anim_enable return; } - lv_obj_clear_state(dsc->focused_obj, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY); + if(dsc->focused_obj) { + lv_obj_remove_state(dsc->focused_obj, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY); + } + lv_obj_add_state(to_focus, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY); lv_obj_scroll_to_view(to_focus, anim_en); dsc->focused_obj = to_focus; @@ -113,7 +134,7 @@ static void gridnav_event_cb(lv_event_t * e) lv_event_code_t code = lv_event_get_code(e); if(code == LV_EVENT_KEY) { - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); if(child_cnt == 0) return; if(dsc->focused_obj == NULL) dsc->focused_obj = find_first_focusable(obj); @@ -125,7 +146,7 @@ static void gridnav_event_cb(lv_event_t * e) if(key == LV_KEY_RIGHT) { if((dsc->ctrl & LV_GRIDNAV_CTRL_SCROLL_FIRST) && lv_obj_has_flag(dsc->focused_obj, LV_OBJ_FLAG_SCROLLABLE) && lv_obj_get_scroll_right(dsc->focused_obj) > 0) { - lv_coord_t d = lv_obj_get_width(dsc->focused_obj) / 4; + int32_t d = lv_obj_get_width(dsc->focused_obj) / 4; if(d <= 0) d = 1; lv_obj_scroll_by_bounded(dsc->focused_obj, -d, 0, LV_ANIM_ON); } @@ -145,7 +166,7 @@ static void gridnav_event_cb(lv_event_t * e) else if(key == LV_KEY_LEFT) { if((dsc->ctrl & LV_GRIDNAV_CTRL_SCROLL_FIRST) && lv_obj_has_flag(dsc->focused_obj, LV_OBJ_FLAG_SCROLLABLE) && lv_obj_get_scroll_left(dsc->focused_obj) > 0) { - lv_coord_t d = lv_obj_get_width(dsc->focused_obj) / 4; + int32_t d = lv_obj_get_width(dsc->focused_obj) / 4; if(d <= 0) d = 1; lv_obj_scroll_by_bounded(dsc->focused_obj, d, 0, LV_ANIM_ON); } @@ -165,7 +186,7 @@ static void gridnav_event_cb(lv_event_t * e) else if(key == LV_KEY_DOWN) { if((dsc->ctrl & LV_GRIDNAV_CTRL_SCROLL_FIRST) && lv_obj_has_flag(dsc->focused_obj, LV_OBJ_FLAG_SCROLLABLE) && lv_obj_get_scroll_bottom(dsc->focused_obj) > 0) { - lv_coord_t d = lv_obj_get_height(dsc->focused_obj) / 4; + int32_t d = lv_obj_get_height(dsc->focused_obj) / 4; if(d <= 0) d = 1; lv_obj_scroll_by_bounded(dsc->focused_obj, 0, -d, LV_ANIM_ON); } @@ -184,7 +205,7 @@ static void gridnav_event_cb(lv_event_t * e) else if(key == LV_KEY_UP) { if((dsc->ctrl & LV_GRIDNAV_CTRL_SCROLL_FIRST) && lv_obj_has_flag(dsc->focused_obj, LV_OBJ_FLAG_SCROLLABLE) && lv_obj_get_scroll_top(dsc->focused_obj) > 0) { - lv_coord_t d = lv_obj_get_height(dsc->focused_obj) / 4; + int32_t d = lv_obj_get_height(dsc->focused_obj) / 4; if(d <= 0) d = 1; lv_obj_scroll_by_bounded(dsc->focused_obj, 0, d, LV_ANIM_ON); } @@ -202,12 +223,12 @@ static void gridnav_event_cb(lv_event_t * e) } else { if(lv_group_get_focused(lv_obj_get_group(obj)) == obj) { - lv_event_send(dsc->focused_obj, LV_EVENT_KEY, &key); + lv_obj_send_event(dsc->focused_obj, LV_EVENT_KEY, &key); } } if(guess && guess != dsc->focused_obj) { - lv_obj_clear_state(dsc->focused_obj, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY); + lv_obj_remove_state(dsc->focused_obj, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY); lv_obj_add_state(guess, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY); lv_obj_scroll_to_view(guess, LV_ANIM_ON); dsc->focused_obj = guess; @@ -217,13 +238,13 @@ static void gridnav_event_cb(lv_event_t * e) if(dsc->focused_obj == NULL) dsc->focused_obj = find_first_focusable(obj); if(dsc->focused_obj) { lv_obj_add_state(dsc->focused_obj, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY); - lv_obj_clear_state(dsc->focused_obj, LV_STATE_PRESSED); /*Be sure the focuses obj is not stuck in pressed state*/ + lv_obj_remove_state(dsc->focused_obj, LV_STATE_PRESSED); /*Be sure the focuses obj is not stuck in pressed state*/ lv_obj_scroll_to_view(dsc->focused_obj, LV_ANIM_OFF); } } else if(code == LV_EVENT_DEFOCUSED) { if(dsc->focused_obj) { - lv_obj_clear_state(dsc->focused_obj, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY); + lv_obj_remove_state(dsc->focused_obj, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY); } } else if(code == LV_EVENT_CHILD_CREATED) { @@ -251,13 +272,13 @@ static void gridnav_event_cb(lv_event_t * e) lv_gridnav_remove(obj); } else if(code == LV_EVENT_PRESSED || code == LV_EVENT_PRESSING || code == LV_EVENT_PRESS_LOST || - code == LV_EVENT_LONG_PRESSED || code == LV_EVENT_LONG_PRESSED_REPEAT || + code == LV_EVENT_SHORT_CLICKED || code == LV_EVENT_LONG_PRESSED || code == LV_EVENT_LONG_PRESSED_REPEAT || code == LV_EVENT_CLICKED || code == LV_EVENT_RELEASED) { if(lv_group_get_focused(lv_obj_get_group(obj)) == obj) { /*Forward press/release related event too*/ - lv_indev_type_t t = lv_indev_get_type(lv_indev_get_act()); + lv_indev_type_t t = lv_indev_get_type(lv_indev_active()); if(t == LV_INDEV_TYPE_ENCODER || t == LV_INDEV_TYPE_KEYPAD) { - lv_event_send(dsc->focused_obj, code, lv_indev_get_act()); + lv_obj_send_event(dsc->focused_obj, code, lv_indev_active()); } } } @@ -265,22 +286,22 @@ static void gridnav_event_cb(lv_event_t * e) static lv_obj_t * find_chid(lv_obj_t * obj, lv_obj_t * start_child, find_mode_t mode) { - lv_coord_t x_start = get_x_center(start_child); - lv_coord_t y_start = get_y_center(start_child); - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + int32_t x_start = get_x_center(start_child); + int32_t y_start = get_y_center(start_child); + uint32_t child_cnt = lv_obj_get_child_count(obj); lv_obj_t * guess = NULL; - lv_coord_t x_err_guess = LV_COORD_MAX; - lv_coord_t y_err_guess = LV_COORD_MAX; - lv_coord_t h_half = lv_obj_get_height(start_child) / 2; - lv_coord_t h_max = lv_obj_get_height(obj) + lv_obj_get_scroll_top(obj) + lv_obj_get_scroll_bottom(obj); + int32_t x_err_guess = LV_COORD_MAX; + int32_t y_err_guess = LV_COORD_MAX; + int32_t h_half = lv_obj_get_height(start_child) / 2; + int32_t h_max = lv_obj_get_height(obj) + lv_obj_get_scroll_top(obj) + lv_obj_get_scroll_bottom(obj); uint32_t i; for(i = 0; i < child_cnt; i++) { lv_obj_t * child = lv_obj_get_child(obj, i); if(child == start_child) continue; if(obj_is_focuable(child) == false) continue; - lv_coord_t x_err = 0; - lv_coord_t y_err = 0; + int32_t x_err = 0; + int32_t y_err = 0; switch(mode) { case FIND_LEFT: x_err = get_x_center(child) - x_start; @@ -335,7 +356,7 @@ static lv_obj_t * find_chid(lv_obj_t * obj, lv_obj_t * start_child, find_mode_t static lv_obj_t * find_first_focusable(lv_obj_t * obj) { - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); uint32_t i; for(i = 0; i < child_cnt; i++) { lv_obj_t * child = lv_obj_get_child(obj, i); @@ -347,7 +368,7 @@ static lv_obj_t * find_first_focusable(lv_obj_t * obj) static lv_obj_t * find_last_focusable(lv_obj_t * obj) { - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); int32_t i; for(i = child_cnt - 1; i >= 0; i--) { lv_obj_t * child = lv_obj_get_child(obj, i); @@ -363,12 +384,12 @@ static bool obj_is_focuable(lv_obj_t * obj) else return false; } -static lv_coord_t get_x_center(lv_obj_t * obj) +static int32_t get_x_center(lv_obj_t * obj) { return obj->coords.x1 + lv_area_get_width(&obj->coords) / 2; } -static lv_coord_t get_y_center(lv_obj_t * obj) +static int32_t get_y_center(lv_obj_t * obj) { return obj->coords.y1 + lv_area_get_height(&obj->coords) / 2; } diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.h b/lib/libesp32_lvgl/lvgl/src/others/gridnav/lv_gridnav.h similarity index 98% rename from lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.h rename to lib/libesp32_lvgl/lvgl/src/others/gridnav/lv_gridnav.h index f480ded46..29b86fc1d 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.h +++ b/lib/libesp32_lvgl/lvgl/src/others/gridnav/lv_gridnav.h @@ -53,7 +53,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../core/lv_obj.h" +#include "../../core/lv_obj.h" #if LV_USE_GRIDNAV diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/ime/lv_ime_pinyin.c b/lib/libesp32_lvgl/lvgl/src/others/ime/lv_ime_pinyin.c similarity index 77% rename from lib/libesp32_lvgl/lvgl/src/extra/others/ime/lv_ime_pinyin.c rename to lib/libesp32_lvgl/lvgl/src/others/ime/lv_ime_pinyin.c index 9834154fb..4a358baed 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/ime/lv_ime_pinyin.c +++ b/lib/libesp32_lvgl/lvgl/src/others/ime/lv_ime_pinyin.c @@ -10,11 +10,13 @@ #if LV_USE_IME_PINYIN != 0 #include +#include "../../core/lv_global.h" /********************* * DEFINES *********************/ #define MY_CLASS &lv_ime_pinyin_class +#define cand_len LV_GLOBAL_DEFAULT()->ime_cand_len /********************** * TYPEDEFS @@ -29,7 +31,7 @@ static void lv_ime_pinyin_style_change_event(lv_event_t * e); static void lv_ime_pinyin_kb_event(lv_event_t * e); static void lv_ime_pinyin_cand_panel_event(lv_event_t * e); -static void init_pinyin_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict); +static void init_pinyin_dict(lv_obj_t * obj, const lv_pinyin_dict_t * dict); static void pinyin_input_proc(lv_obj_t * obj); static void pinyin_page_proc(lv_obj_t * obj, uint16_t btn); static char * pinyin_search_matching(lv_obj_t * obj, char * py_str, uint16_t * cand_num); @@ -46,6 +48,7 @@ static void pinyin_ime_clear_data(lv_obj_t * obj); /********************** * STATIC VARIABLES **********************/ + const lv_obj_class_t lv_ime_pinyin_class = { .constructor_cb = lv_ime_pinyin_constructor, .destructor_cb = lv_ime_pinyin_destructor, @@ -53,18 +56,19 @@ const lv_obj_class_t lv_ime_pinyin_class = { .height_def = LV_SIZE_CONTENT, .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, .instance_size = sizeof(lv_ime_pinyin_t), - .base_class = &lv_obj_class + .base_class = &lv_obj_class, + .name = "ime-pinyin", }; #if LV_IME_PINYIN_USE_K9_MODE -static char * lv_btnm_def_pinyin_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 20] = {\ - ",\0", "1#\0", "abc \0", "def\0", LV_SYMBOL_BACKSPACE"\0", "\n\0", - ".\0", "ghi\0", "jkl\0", "mno\0", LV_SYMBOL_KEYBOARD"\0", "\n\0", - "?\0", "pqrs\0", "tuv\0", "wxyz\0", LV_SYMBOL_NEW_LINE"\0", "\n\0", - LV_SYMBOL_LEFT"\0", "\0" - }; +static const char * lv_btnm_def_pinyin_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 21] = {\ + ",\0", "123\0", "abc \0", "def\0", LV_SYMBOL_BACKSPACE"\0", "\n\0", + ".\0", "ghi\0", "jkl\0", "mno\0", LV_SYMBOL_KEYBOARD"\0", "\n\0", + "?\0", "pqrs\0", "tuv\0", "wxyz\0", LV_SYMBOL_NEW_LINE"\0", "\n\0", + LV_SYMBOL_LEFT"\0", "\0" + }; -static lv_btnmatrix_ctrl_t default_kb_ctrl_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 16] = { 1 }; +static lv_buttonmatrix_ctrl_t default_kb_ctrl_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 17] = { 1 }; static char lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 2][LV_IME_PINYIN_K9_MAX_INPUT] = {0}; #endif @@ -72,7 +76,7 @@ static char lv_pinyin_cand_str[LV_IME_PINYIN_CAND_TEXT_NUM][4]; static char * lv_btnm_def_pinyin_sel_map[LV_IME_PINYIN_CAND_TEXT_NUM + 3]; #if LV_IME_PINYIN_USE_DEFAULT_DICT -lv_pinyin_dict_t lv_ime_pinyin_def_dict[] = { +static const lv_pinyin_dict_t lv_ime_pinyin_def_dict[] = { { "a", "啊" }, { "ai", "愛" }, { "an", "安暗案" }, @@ -252,13 +256,13 @@ lv_pinyin_dict_t lv_ime_pinyin_def_dict[] = { { "o", "" }, { "ou", "歐" }, { "pa", "怕" }, - { "pian", "片便" }, { "pai", "迫派排" }, { "pan", "判番" }, { "pang", "旁" }, { "pei", "配" }, { "peng", "朋" }, { "pi", "疲否" }, + { "pian", "片便" }, { "pin", "品貧" }, { "ping", "平評" }, { "po", "迫破泊頗" }, @@ -398,7 +402,6 @@ lv_pinyin_dict_t lv_ime_pinyin_def_dict[] = { }; #endif - /********************** * MACROS **********************/ @@ -414,16 +417,10 @@ lv_obj_t * lv_ime_pinyin_create(lv_obj_t * parent) return obj; } - /*===================== * Setter functions *====================*/ -/** - * Set the keyboard of Pinyin input method. - * @param obj pointer to a Pinyin input method object - * @param dict pointer to a Pinyin input method keyboard - */ void lv_ime_pinyin_set_keyboard(lv_obj_t * obj, lv_obj_t * kb) { if(kb) { @@ -434,15 +431,12 @@ void lv_ime_pinyin_set_keyboard(lv_obj_t * obj, lv_obj_t * kb) lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; pinyin_ime->kb = kb; + lv_obj_set_parent(obj, lv_obj_get_parent(kb)); + lv_obj_set_parent(pinyin_ime->cand_panel, lv_obj_get_parent(kb)); lv_obj_add_event_cb(pinyin_ime->kb, lv_ime_pinyin_kb_event, LV_EVENT_VALUE_CHANGED, obj); lv_obj_align_to(pinyin_ime->cand_panel, pinyin_ime->kb, LV_ALIGN_OUT_TOP_MID, 0, 0); } -/** - * Set the dictionary of Pinyin input method. - * @param obj pointer to a Pinyin input method object - * @param dict pointer to a Pinyin input method dictionary - */ void lv_ime_pinyin_set_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -450,11 +444,6 @@ void lv_ime_pinyin_set_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict) init_pinyin_dict(obj, dict); } -/** - * Set mode, 26-key input(k26) or 9-key input(k9). - * @param obj pointer to a Pinyin input method object - * @param mode the mode from 'lv_keyboard_mode_t' - */ void lv_ime_pinyin_set_mode(lv_obj_t * obj, lv_ime_pinyin_mode_t mode) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -467,8 +456,8 @@ void lv_ime_pinyin_set_mode(lv_obj_t * obj, lv_ime_pinyin_mode_t mode) #if LV_IME_PINYIN_USE_K9_MODE if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) { pinyin_k9_init_data(obj); - lv_keyboard_set_map(pinyin_ime->kb, LV_KEYBOARD_MODE_USER_1, (const char *)lv_btnm_def_pinyin_k9_map, - (const)default_kb_ctrl_k9_map); + lv_keyboard_set_map(pinyin_ime->kb, LV_KEYBOARD_MODE_USER_1, (const char **)lv_btnm_def_pinyin_k9_map, + default_kb_ctrl_k9_map); lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_USER_1); } #endif @@ -478,11 +467,6 @@ void lv_ime_pinyin_set_mode(lv_obj_t * obj, lv_ime_pinyin_mode_t mode) * Getter functions *====================*/ -/** - * Set the dictionary of Pinyin input method. - * @param obj pointer to a Pinyin IME object - * @return pointer to the Pinyin IME keyboard - */ lv_obj_t * lv_ime_pinyin_get_kb(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -492,11 +476,6 @@ lv_obj_t * lv_ime_pinyin_get_kb(lv_obj_t * obj) return pinyin_ime->kb; } -/** - * Set the dictionary of Pinyin input method. - * @param obj pointer to a Pinyin input method object - * @return pointer to the Pinyin input method candidate panel - */ lv_obj_t * lv_ime_pinyin_get_cand_panel(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -506,12 +485,7 @@ lv_obj_t * lv_ime_pinyin_get_cand_panel(lv_obj_t * obj) return pinyin_ime->cand_panel; } -/** - * Set the dictionary of Pinyin input method. - * @param obj pointer to a Pinyin input method object - * @return pointer to the Pinyin input method dictionary - */ -lv_pinyin_dict_t * lv_ime_pinyin_get_dict(lv_obj_t * obj) +const lv_pinyin_dict_t * lv_ime_pinyin_get_dict(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -558,27 +532,24 @@ static void lv_ime_pinyin_constructor(const lv_obj_class_t * class_p, lv_obj_t * pinyin_ime->py_page = 0; pinyin_ime->ta_count = 0; pinyin_ime->cand_num = 0; - lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); - lv_memset_00(pinyin_ime->py_num, sizeof(pinyin_ime->py_num)); - lv_memset_00(pinyin_ime->py_pos, sizeof(pinyin_ime->py_pos)); + lv_memzero(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); + lv_memzero(pinyin_ime->py_num, sizeof(pinyin_ime->py_num)); + lv_memzero(pinyin_ime->py_pos, sizeof(pinyin_ime->py_pos)); lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN); - lv_obj_set_size(obj, LV_PCT(100), LV_PCT(55)); - lv_obj_align(obj, LV_ALIGN_BOTTOM_MID, 0, 0); - #if LV_IME_PINYIN_USE_DEFAULT_DICT init_pinyin_dict(obj, lv_ime_pinyin_def_dict); #endif /* Init pinyin_ime->cand_panel */ - pinyin_ime->cand_panel = lv_btnmatrix_create(lv_scr_act()); - lv_btnmatrix_set_map(pinyin_ime->cand_panel, (const char **)lv_btnm_def_pinyin_sel_map); + pinyin_ime->cand_panel = lv_buttonmatrix_create(lv_obj_get_parent(obj)); + lv_buttonmatrix_set_map(pinyin_ime->cand_panel, (const char **)lv_btnm_def_pinyin_sel_map); lv_obj_set_size(pinyin_ime->cand_panel, LV_PCT(100), LV_PCT(5)); lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); - lv_btnmatrix_set_one_checked(pinyin_ime->cand_panel, true); - lv_obj_clear_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_CLICK_FOCUSABLE); + lv_buttonmatrix_set_one_checked(pinyin_ime->cand_panel, true); + lv_obj_remove_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_CLICK_FOCUSABLE); /* Set cand_panel style*/ // Default style @@ -608,7 +579,7 @@ static void lv_ime_pinyin_constructor(const lv_obj_class_t * class_p, lv_obj_t * pinyin_ime->k9_input_str_len = 0; pinyin_ime->k9_py_ll_pos = 0; pinyin_ime->k9_legal_py_count = 0; - lv_memset_00(pinyin_ime->k9_input_str, LV_IME_PINYIN_K9_MAX_INPUT); + lv_memzero(pinyin_ime->k9_input_str, LV_IME_PINYIN_K9_MAX_INPUT); pinyin_k9_init_data(obj); @@ -616,7 +587,6 @@ static void lv_ime_pinyin_constructor(const lv_obj_class_t * class_p, lv_obj_t * #endif } - static void lv_ime_pinyin_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { LV_UNUSED(class_p); @@ -624,17 +594,16 @@ static void lv_ime_pinyin_destructor(const lv_obj_class_t * class_p, lv_obj_t * lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; if(lv_obj_is_valid(pinyin_ime->kb)) - lv_obj_del(pinyin_ime->kb); + lv_obj_delete(pinyin_ime->kb); if(lv_obj_is_valid(pinyin_ime->cand_panel)) - lv_obj_del(pinyin_ime->cand_panel); + lv_obj_delete(pinyin_ime->cand_panel); } - static void lv_ime_pinyin_kb_event(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * kb = lv_event_get_target(e); + lv_obj_t * kb = lv_event_get_current_target(e); lv_obj_t * obj = lv_event_get_user_data(e); lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; @@ -644,28 +613,29 @@ static void lv_ime_pinyin_kb_event(lv_event_t * e) #endif if(code == LV_EVENT_VALUE_CHANGED) { - uint16_t btn_id = lv_btnmatrix_get_selected_btn(kb); - if(btn_id == LV_BTNMATRIX_BTN_NONE) return; + uint16_t btn_id = lv_buttonmatrix_get_selected_button(kb); + if(btn_id == LV_BUTTONMATRIX_BUTTON_NONE) return; - const char * txt = lv_btnmatrix_get_btn_text(kb, lv_btnmatrix_get_selected_btn(kb)); + const char * txt = lv_buttonmatrix_get_button_text(kb, lv_buttonmatrix_get_selected_button(kb)); if(txt == NULL) return; + lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb); + #if LV_IME_PINYIN_USE_K9_MODE if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) { - lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb); - uint16_t tmp_btn_str_len = strlen(pinyin_ime->input_char); - if((btn_id >= 16) && (tmp_btn_str_len > 0) && (btn_id < (16 + LV_IME_PINYIN_K9_CAND_TEXT_NUM))) { - tmp_btn_str_len = strlen(pinyin_ime->input_char); - lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); + + uint16_t tmp_button_str_len = lv_strlen(pinyin_ime->input_char); + if((btn_id >= 16) && (tmp_button_str_len > 0) && (btn_id < (16 + LV_IME_PINYIN_K9_CAND_TEXT_NUM))) { + lv_memzero(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); strcat(pinyin_ime->input_char, txt); pinyin_input_proc(obj); - for(int index = 0; index < (pinyin_ime->ta_count + tmp_btn_str_len); index++) { - lv_textarea_del_char(ta); + for(int index = 0; index < (pinyin_ime->ta_count + tmp_button_str_len); index++) { + lv_textarea_delete_char(ta); } - pinyin_ime->ta_count = tmp_btn_str_len; - pinyin_ime->k9_input_str_len = tmp_btn_str_len; + pinyin_ime->ta_count = tmp_button_str_len; + pinyin_ime->k9_input_str_len = tmp_button_str_len; lv_textarea_add_text(ta, pinyin_ime->input_char); return; @@ -673,11 +643,11 @@ static void lv_ime_pinyin_kb_event(lv_event_t * e) } #endif - if(strcmp(txt, "Enter") == 0 || strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) { + if(lv_strcmp(txt, "Enter") == 0 || lv_strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) { pinyin_ime_clear_data(obj); lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); } - else if(strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) { + else if(lv_strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) { // del input char if(pinyin_ime->ta_count > 0) { if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26) @@ -687,44 +657,51 @@ static void lv_ime_pinyin_kb_event(lv_event_t * e) pinyin_ime->k9_input_str[pinyin_ime->ta_count - 1] = '\0'; #endif - pinyin_ime->ta_count = pinyin_ime->ta_count - 1; + pinyin_ime->ta_count--; if(pinyin_ime->ta_count <= 0) { + pinyin_ime_clear_data(obj); lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); -#if LV_IME_PINYIN_USE_K9_MODE - lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str)); - strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0"); - strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0"); -#endif } else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26) { pinyin_input_proc(obj); } #if LV_IME_PINYIN_USE_K9_MODE else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) { - pinyin_ime->k9_input_str_len = strlen(pinyin_ime->input_char) - 1; + pinyin_ime->k9_input_str_len = lv_strlen(pinyin_ime->input_char) - 1; pinyin_k9_get_legal_py(obj, pinyin_ime->k9_input_str, k9_py_map); pinyin_k9_fill_cand(obj); pinyin_input_proc(obj); + pinyin_ime->ta_count--; } #endif } } - else if((strcmp(txt, "ABC") == 0) || (strcmp(txt, "abc") == 0) || (strcmp(txt, "1#") == 0)) { - pinyin_ime->ta_count = 0; - lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); + else if((lv_strcmp(txt, "ABC") == 0) || (lv_strcmp(txt, "abc") == 0) || (lv_strcmp(txt, "1#") == 0) || + (lv_strcmp(txt, LV_SYMBOL_OK) == 0)) { + pinyin_ime_clear_data(obj); return; } - else if(strcmp(txt, LV_SYMBOL_KEYBOARD) == 0) { + else if(lv_strcmp(txt, "123") == 0) { + for(uint16_t i = 0; i < lv_strlen(txt); i++) + lv_textarea_delete_char(ta); + + pinyin_ime_clear_data(obj); + lv_textarea_set_cursor_pos(ta, LV_TEXTAREA_CURSOR_LAST); + lv_ime_pinyin_set_mode(obj, LV_IME_PINYIN_MODE_K9_NUMBER); + lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_NUMBER); + lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); + } + else if(lv_strcmp(txt, LV_SYMBOL_KEYBOARD) == 0) { if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K26) { - lv_ime_pinyin_set_mode(pinyin_ime, LV_IME_PINYIN_MODE_K9); + lv_ime_pinyin_set_mode(obj, LV_IME_PINYIN_MODE_K9); } - else { - lv_ime_pinyin_set_mode(pinyin_ime, LV_IME_PINYIN_MODE_K26); + else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) { + lv_ime_pinyin_set_mode(obj, LV_IME_PINYIN_MODE_K26); lv_keyboard_set_mode(pinyin_ime->kb, LV_KEYBOARD_MODE_TEXT_LOWER); } - pinyin_ime_clear_data(obj); - } - else if(strcmp(txt, LV_SYMBOL_OK) == 0) { + else if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9_NUMBER) { + lv_ime_pinyin_set_mode(obj, LV_IME_PINYIN_MODE_K9); + } pinyin_ime_clear_data(obj); } else if((pinyin_ime->mode == LV_IME_PINYIN_MODE_K26) && ((txt[0] >= 'a' && txt[0] <= 'z') || (txt[0] >= 'A' && @@ -736,10 +713,11 @@ static void lv_ime_pinyin_kb_event(lv_event_t * e) #if LV_IME_PINYIN_USE_K9_MODE else if((pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) && (txt[0] >= 'a' && txt[0] <= 'z')) { for(uint16_t i = 0; i < 8; i++) { - if((strcmp(txt, k9_py_map[i]) == 0) || (strcmp(txt, "abc ") == 0)) { - if(strcmp(txt, "abc ") == 0) pinyin_ime->k9_input_str_len += strlen(k9_py_map[i]) + 1; - else pinyin_ime->k9_input_str_len += strlen(k9_py_map[i]); + if((lv_strcmp(txt, k9_py_map[i]) == 0) || (lv_strcmp(txt, "abc ") == 0)) { + if(lv_strcmp(txt, "abc ") == 0) pinyin_ime->k9_input_str_len += lv_strlen(k9_py_map[i]) + 1; + else pinyin_ime->k9_input_str_len += lv_strlen(k9_py_map[i]); pinyin_ime->k9_input_str[pinyin_ime->ta_count] = 50 + i; + pinyin_ime->k9_input_str[pinyin_ime->ta_count + 1] = '\0'; break; } @@ -748,41 +726,45 @@ static void lv_ime_pinyin_kb_event(lv_event_t * e) pinyin_k9_fill_cand(obj); pinyin_input_proc(obj); } - else if(strcmp(txt, LV_SYMBOL_LEFT) == 0) { + else if(lv_strcmp(txt, LV_SYMBOL_LEFT) == 0) { pinyin_k9_cand_page_proc(obj, 0); } - else if(strcmp(txt, LV_SYMBOL_RIGHT) == 0) { + else if(lv_strcmp(txt, LV_SYMBOL_RIGHT) == 0) { pinyin_k9_cand_page_proc(obj, 1); } #endif } } - static void lv_ime_pinyin_cand_panel_event(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * cand_panel = lv_event_get_target(e); + lv_obj_t * cand_panel = lv_event_get_current_target(e); lv_obj_t * obj = (lv_obj_t *)lv_event_get_user_data(e); lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; if(code == LV_EVENT_VALUE_CHANGED) { - uint32_t id = lv_btnmatrix_get_selected_btn(cand_panel); - if(id == 0) { + lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb); + if(ta == NULL) return; + + uint32_t id = lv_buttonmatrix_get_selected_button(cand_panel); + if(id == LV_BUTTONMATRIX_BUTTON_NONE) { + return; + } + else if(id == 0) { pinyin_page_proc(obj, 0); return; } - if(id == (LV_IME_PINYIN_CAND_TEXT_NUM + 1)) { + else if(id == (LV_IME_PINYIN_CAND_TEXT_NUM + 1)) { pinyin_page_proc(obj, 1); return; } - const char * txt = lv_btnmatrix_get_btn_text(cand_panel, id); - lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb); + const char * txt = lv_buttonmatrix_get_button_text(cand_panel, id); uint16_t index = 0; for(index = 0; index < pinyin_ime->ta_count; index++) - lv_textarea_del_char(ta); + lv_textarea_delete_char(ta); lv_textarea_add_text(ta, txt); @@ -790,7 +772,6 @@ static void lv_ime_pinyin_cand_panel_event(lv_event_t * e) } } - static void pinyin_input_proc(lv_obj_t * obj) { lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; @@ -803,7 +784,7 @@ static void pinyin_input_proc(lv_obj_t * obj) pinyin_ime->py_page = 0; for(uint8_t i = 0; i < LV_IME_PINYIN_CAND_TEXT_NUM; i++) { - memset(lv_pinyin_cand_str[i], 0x00, sizeof(lv_pinyin_cand_str[i])); + lv_memset(lv_pinyin_cand_str[i], 0x00, sizeof(lv_pinyin_cand_str[i])); lv_pinyin_cand_str[i][0] = ' '; } @@ -814,14 +795,16 @@ static void pinyin_input_proc(lv_obj_t * obj) } } - lv_obj_clear_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); } static void pinyin_page_proc(lv_obj_t * obj, uint16_t dir) { lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; uint16_t page_num = pinyin_ime->cand_num / LV_IME_PINYIN_CAND_TEXT_NUM; - uint16_t sur = pinyin_ime->cand_num % LV_IME_PINYIN_CAND_TEXT_NUM; + uint16_t remainder = pinyin_ime->cand_num % LV_IME_PINYIN_CAND_TEXT_NUM; + + if(!pinyin_ime->cand_str) return; if(dir == 0) { if(pinyin_ime->py_page) { @@ -829,7 +812,7 @@ static void pinyin_page_proc(lv_obj_t * obj, uint16_t dir) } } else { - if(sur == 0) { + if(remainder == 0) { page_num -= 1; } if(pinyin_ime->py_page < page_num) { @@ -839,15 +822,15 @@ static void pinyin_page_proc(lv_obj_t * obj, uint16_t dir) } for(uint8_t i = 0; i < LV_IME_PINYIN_CAND_TEXT_NUM; i++) { - memset(lv_pinyin_cand_str[i], 0x00, sizeof(lv_pinyin_cand_str[i])); + lv_memset(lv_pinyin_cand_str[i], 0x00, sizeof(lv_pinyin_cand_str[i])); lv_pinyin_cand_str[i][0] = ' '; } // fill buf uint16_t offset = pinyin_ime->py_page * (3 * LV_IME_PINYIN_CAND_TEXT_NUM); for(uint8_t i = 0; (i < pinyin_ime->cand_num && i < LV_IME_PINYIN_CAND_TEXT_NUM); i++) { - if((sur > 0) && (pinyin_ime->py_page == page_num)) { - if(i > sur) + if((remainder > 0) && (pinyin_ime->py_page == page_num)) { + if(i > remainder) break; } for(uint8_t j = 0; j < 3; j++) { @@ -856,11 +839,10 @@ static void pinyin_page_proc(lv_obj_t * obj, uint16_t dir) } } - static void lv_ime_pinyin_style_change_event(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; @@ -870,8 +852,7 @@ static void lv_ime_pinyin_style_change_event(lv_event_t * e) } } - -static void init_pinyin_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict) +static void init_pinyin_dict(lv_obj_t * obj, const lv_pinyin_dict_t * dict) { lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; @@ -905,12 +886,11 @@ static void init_pinyin_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict) } } - static char * pinyin_search_matching(lv_obj_t * obj, char * py_str, uint16_t * cand_num) { lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; - lv_pinyin_dict_t * cpHZ; + const lv_pinyin_dict_t * cpHZ; uint8_t index, len = 0, offset; volatile uint8_t count = 0; @@ -918,9 +898,10 @@ static char * pinyin_search_matching(lv_obj_t * obj, char * py_str, uint16_t * c if(*py_str == 'i') return NULL; if(*py_str == 'u') return NULL; if(*py_str == 'v') return NULL; + if(*py_str == ' ') return NULL; offset = py_str[0] - 'a'; - len = strlen(py_str); + len = lv_strlen(py_str); cpHZ = &pinyin_ime->dict[pinyin_ime->py_pos[offset]]; count = pinyin_ime->py_num[offset]; @@ -935,7 +916,7 @@ static char * pinyin_search_matching(lv_obj_t * obj, char * py_str, uint16_t * c // perfect match if(len == 1 || index == len) { // The Chinese character in UTF-8 encoding format is 3 bytes - * cand_num = strlen((const char *)(cpHZ->py_mb)) / 3; + * cand_num = lv_strlen((const char *)(cpHZ->py_mb)) / 3; return (char *)(cpHZ->py_mb); } cpHZ++; @@ -947,64 +928,70 @@ static void pinyin_ime_clear_data(lv_obj_t * obj) { lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; - #if LV_IME_PINYIN_USE_K9_MODE if(pinyin_ime->mode == LV_IME_PINYIN_MODE_K9) { pinyin_ime->k9_input_str_len = 0; pinyin_ime->k9_py_ll_pos = 0; pinyin_ime->k9_legal_py_count = 0; - lv_memset_00(pinyin_ime->k9_input_str, LV_IME_PINYIN_K9_MAX_INPUT); - lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str)); - strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0"); - strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0"); + lv_memzero(pinyin_ime->k9_input_str, LV_IME_PINYIN_K9_MAX_INPUT); + lv_memzero(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str)); + for(uint8_t i = 0; i < LV_IME_PINYIN_CAND_TEXT_NUM; i++) { + lv_strcpy(lv_pinyin_k9_cand_str[i], " "); + } + lv_strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0"); + lv_strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0"); + lv_buttonmatrix_set_map(pinyin_ime->kb, (const char **)lv_btnm_def_pinyin_k9_map); } #endif pinyin_ime->ta_count = 0; - lv_memset_00(lv_pinyin_cand_str, (sizeof(lv_pinyin_cand_str))); - lv_memset_00(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); + for(uint8_t i = 0; i < LV_IME_PINYIN_CAND_TEXT_NUM; i++) { + lv_memset(lv_pinyin_cand_str[i], 0x00, sizeof(lv_pinyin_cand_str[i])); + lv_pinyin_cand_str[i][0] = ' '; + } + lv_memzero(pinyin_ime->input_char, sizeof(pinyin_ime->input_char)); lv_obj_add_flag(pinyin_ime->cand_panel, LV_OBJ_FLAG_HIDDEN); } - #if LV_IME_PINYIN_USE_K9_MODE static void pinyin_k9_init_data(lv_obj_t * obj) { - lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; + LV_UNUSED(obj); uint16_t py_str_i = 0; uint16_t btnm_i = 0; for(btnm_i = 19; btnm_i < (LV_IME_PINYIN_K9_CAND_TEXT_NUM + 21); btnm_i++) { if(py_str_i == LV_IME_PINYIN_K9_CAND_TEXT_NUM) { - strcpy(lv_pinyin_k9_cand_str[py_str_i], LV_SYMBOL_RIGHT"\0"); + lv_strcpy(lv_pinyin_k9_cand_str[py_str_i], LV_SYMBOL_RIGHT"\0"); } else if(py_str_i == LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1) { - strcpy(lv_pinyin_k9_cand_str[py_str_i], "\0"); + lv_strcpy(lv_pinyin_k9_cand_str[py_str_i], "\0"); } else { - strcpy(lv_pinyin_k9_cand_str[py_str_i], " \0"); + lv_strcpy(lv_pinyin_k9_cand_str[py_str_i], " \0"); } lv_btnm_def_pinyin_k9_map[btnm_i] = lv_pinyin_k9_cand_str[py_str_i]; py_str_i++; } - default_kb_ctrl_k9_map[0] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; - default_kb_ctrl_k9_map[4] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; - default_kb_ctrl_k9_map[5] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; - default_kb_ctrl_k9_map[9] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; - default_kb_ctrl_k9_map[10] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; - default_kb_ctrl_k9_map[14] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; - default_kb_ctrl_k9_map[15] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; - default_kb_ctrl_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 16] = LV_KEYBOARD_CTRL_BTN_FLAGS | 1; + default_kb_ctrl_k9_map[0] = LV_BUTTONMATRIX_CTRL_CHECKED | 1; + default_kb_ctrl_k9_map[1] = LV_BUTTONMATRIX_CTRL_NO_REPEAT | LV_BUTTONMATRIX_CTRL_CLICK_TRIG | 1; + default_kb_ctrl_k9_map[4] = LV_BUTTONMATRIX_CTRL_CHECKED | 1; + default_kb_ctrl_k9_map[5] = LV_BUTTONMATRIX_CTRL_CHECKED | 1; + default_kb_ctrl_k9_map[9] = LV_KEYBOARD_CTRL_BUTTON_FLAGS | 1; + default_kb_ctrl_k9_map[10] = LV_BUTTONMATRIX_CTRL_CHECKED | 1; + default_kb_ctrl_k9_map[14] = LV_BUTTONMATRIX_CTRL_CHECKED | 1; + default_kb_ctrl_k9_map[15] = LV_BUTTONMATRIX_CTRL_CHECKED | 1; + default_kb_ctrl_k9_map[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 16] = LV_BUTTONMATRIX_CTRL_CHECKED | 1; } static void pinyin_k9_get_legal_py(lv_obj_t * obj, char * k9_input, const char * py9_map[]) { lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; - uint16_t len = strlen(k9_input); + uint16_t len = lv_strlen(k9_input); if((len == 0) || (len >= LV_IME_PINYIN_K9_MAX_INPUT)) { return; @@ -1014,7 +1001,7 @@ static void pinyin_k9_get_legal_py(lv_obj_t * obj, char * k9_input, const char * int mark[LV_IME_PINYIN_K9_MAX_INPUT] = {0}; int index = 0; int flag = 0; - int count = 0; + uint16_t count = 0; uint32_t ll_len = 0; ime_pinyin_k9_py_str_t * ll_index = NULL; @@ -1027,10 +1014,10 @@ static void pinyin_k9_get_legal_py(lv_obj_t * obj, char * k9_input, const char * if(pinyin_k9_is_valid_py(obj, py_comp)) { if((count >= ll_len) || (ll_len == 0)) { ll_index = _lv_ll_ins_tail(&pinyin_ime->k9_legal_py_ll); - strcpy(ll_index->py_str, py_comp); + lv_strcpy(ll_index->py_str, py_comp); } else if((count < ll_len)) { - strcpy(ll_index->py_str, py_comp); + lv_strcpy(ll_index->py_str, py_comp); ll_index = _lv_ll_get_next(&pinyin_ime->k9_legal_py_ll, ll_index); } count++; @@ -1039,7 +1026,7 @@ static void pinyin_k9_get_legal_py(lv_obj_t * obj, char * k9_input, const char * } else { flag = mark[index]; - if(flag < strlen(py9_map[k9_input[index] - '2'])) { + if((size_t)flag < lv_strlen(py9_map[k9_input[index] - '2'])) { py_comp[index] = py9_map[k9_input[index] - '2'][flag]; mark[index] = mark[index] + 1; index++; @@ -1057,15 +1044,13 @@ static void pinyin_k9_get_legal_py(lv_obj_t * obj, char * k9_input, const char * } } - /*true: visible; false: not visible*/ static bool pinyin_k9_is_valid_py(lv_obj_t * obj, char * py_str) { lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; - lv_pinyin_dict_t * cpHZ = NULL; + const lv_pinyin_dict_t * cpHZ = NULL; uint8_t index = 0, len = 0, offset = 0; - uint16_t ret = 1; volatile uint8_t count = 0; if(*py_str == '\0') return false; @@ -1074,7 +1059,7 @@ static bool pinyin_k9_is_valid_py(lv_obj_t * obj, char * py_str) if(*py_str == 'v') return false; offset = py_str[0] - 'a'; - len = strlen(py_str); + len = lv_strlen(py_str); cpHZ = &pinyin_ime->dict[pinyin_ime->py_pos[offset]]; count = pinyin_ime->py_num[offset]; @@ -1095,10 +1080,8 @@ static bool pinyin_k9_is_valid_py(lv_obj_t * obj, char * py_str) return false; } - static void pinyin_k9_fill_cand(lv_obj_t * obj) { - static uint16_t len = 0; uint16_t index = 0, tmp_len = 0; ime_pinyin_k9_py_str_t * ll_index = NULL; @@ -1106,21 +1089,28 @@ static void pinyin_k9_fill_cand(lv_obj_t * obj) tmp_len = pinyin_ime->k9_legal_py_count; - if(tmp_len != len) { - lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str)); - strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0"); - strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0"); - len = tmp_len; + if(tmp_len != cand_len) { + lv_memzero(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str)); + lv_strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0"); + lv_strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0"); + cand_len = tmp_len; } ll_index = _lv_ll_get_head(&pinyin_ime->k9_legal_py_ll); - strcpy(pinyin_ime->input_char, ll_index->py_str); + lv_strcpy(pinyin_ime->input_char, ll_index->py_str); + + for(uint8_t i = 0; i < LV_IME_PINYIN_K9_CAND_TEXT_NUM; i++) { + lv_strcpy(lv_pinyin_k9_cand_str[i], " "); + } + while(ll_index) { - if((index >= LV_IME_PINYIN_K9_CAND_TEXT_NUM) || \ - (index >= pinyin_ime->k9_legal_py_count)) + if(index >= LV_IME_PINYIN_K9_CAND_TEXT_NUM) break; - strcpy(lv_pinyin_k9_cand_str[index], ll_index->py_str); + if(index < pinyin_ime->k9_legal_py_count) { + lv_strcpy(lv_pinyin_k9_cand_str[index], ll_index->py_str); + } + ll_index = _lv_ll_get_next(&pinyin_ime->k9_legal_py_ll, ll_index); /*Find the next list*/ index++; } @@ -1128,13 +1118,12 @@ static void pinyin_k9_fill_cand(lv_obj_t * obj) lv_obj_t * ta = lv_keyboard_get_textarea(pinyin_ime->kb); for(index = 0; index < pinyin_ime->k9_input_str_len; index++) { - lv_textarea_del_char(ta); + lv_textarea_delete_char(ta); } - pinyin_ime->k9_input_str_len = strlen(pinyin_ime->input_char); + pinyin_ime->k9_input_str_len = lv_strlen(pinyin_ime->input_char); lv_textarea_add_text(ta, pinyin_ime->input_char); } - static void pinyin_k9_cand_page_proc(lv_obj_t * obj, uint16_t dir) { lv_ime_pinyin_t * pinyin_ime = (lv_ime_pinyin_t *)obj; @@ -1144,7 +1133,6 @@ static void pinyin_k9_cand_page_proc(lv_obj_t * obj, uint16_t dir) if((ll_len > LV_IME_PINYIN_K9_CAND_TEXT_NUM) && (pinyin_ime->k9_legal_py_count > LV_IME_PINYIN_K9_CAND_TEXT_NUM)) { ime_pinyin_k9_py_str_t * ll_index = NULL; - uint16_t tmp_btn_str_len = 0; int count = 0; ll_index = _lv_ll_get_head(&pinyin_ime->k9_legal_py_ll); @@ -1157,18 +1145,22 @@ static void pinyin_k9_cand_page_proc(lv_obj_t * obj, uint16_t dir) if((NULL == ll_index) && (dir == 1)) return; - lv_memset_00(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str)); - strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0"); - strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0"); + lv_memzero(lv_pinyin_k9_cand_str, sizeof(lv_pinyin_k9_cand_str)); + lv_strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM], LV_SYMBOL_RIGHT"\0"); + lv_strcpy(lv_pinyin_k9_cand_str[LV_IME_PINYIN_K9_CAND_TEXT_NUM + 1], "\0"); // next page if(dir == 1) { + for(uint8_t i = 0; i < LV_IME_PINYIN_K9_CAND_TEXT_NUM; i++) { + lv_strcpy(lv_pinyin_k9_cand_str[i], " "); + } + count = 0; while(ll_index) { if(count >= (LV_IME_PINYIN_K9_CAND_TEXT_NUM - 1)) break; - strcpy(lv_pinyin_k9_cand_str[count], ll_index->py_str); + lv_strcpy(lv_pinyin_k9_cand_str[count], ll_index->py_str); ll_index = _lv_ll_get_next(&pinyin_ime->k9_legal_py_ll, ll_index); /*Find the next list*/ count++; } @@ -1177,12 +1169,15 @@ static void pinyin_k9_cand_page_proc(lv_obj_t * obj, uint16_t dir) } // previous page else { + for(uint8_t i = 0; i < LV_IME_PINYIN_K9_CAND_TEXT_NUM; i++) { + lv_strcpy(lv_pinyin_k9_cand_str[i], " "); + } count = LV_IME_PINYIN_K9_CAND_TEXT_NUM - 1; ll_index = _lv_ll_get_prev(&pinyin_ime->k9_legal_py_ll, ll_index); while(ll_index) { if(count < 0) break; - strcpy(lv_pinyin_k9_cand_str[count], ll_index->py_str); + lv_strcpy(lv_pinyin_k9_cand_str[count], ll_index->py_str); ll_index = _lv_ll_get_prev(&pinyin_ime->k9_legal_py_ll, ll_index); /*Find the previous list*/ count--; } @@ -1198,4 +1193,3 @@ static void pinyin_k9_cand_page_proc(lv_obj_t * obj, uint16_t dir) #endif /*LV_IME_PINYIN_USE_K9_MODE*/ #endif /*LV_USE_IME_PINYIN*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/ime/lv_ime_pinyin.h b/lib/libesp32_lvgl/lvgl/src/others/ime/lv_ime_pinyin.h similarity index 89% rename from lib/libesp32_lvgl/lvgl/src/extra/others/ime/lv_ime_pinyin.h rename to lib/libesp32_lvgl/lvgl/src/others/ime/lv_ime_pinyin.h index 3ff7bb980..a7dee9612 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/ime/lv_ime_pinyin.h +++ b/lib/libesp32_lvgl/lvgl/src/others/ime/lv_ime_pinyin.h @@ -28,6 +28,7 @@ extern "C" { typedef enum { LV_IME_PINYIN_MODE_K26, LV_IME_PINYIN_MODE_K9, + LV_IME_PINYIN_MODE_K9_NUMBER, } lv_ime_pinyin_mode_t; /*Data of pinyin_dict*/ @@ -46,12 +47,12 @@ typedef struct { lv_obj_t obj; lv_obj_t * kb; lv_obj_t * cand_panel; - lv_pinyin_dict_t * dict; + const lv_pinyin_dict_t * dict; lv_ll_t k9_legal_py_ll; char * cand_str; /* Candidate string */ char input_char[16]; /* Input box character */ #if LV_IME_PINYIN_USE_K9_MODE - char k9_input_str[LV_IME_PINYIN_K9_MAX_INPUT]; /* 9-key input(k9) mode input string */ + char k9_input_str[LV_IME_PINYIN_K9_MAX_INPUT + 1]; /* 9-key input(k9) mode input string */ uint16_t k9_py_ll_pos; /* Current pinyin map pages(k9) */ uint16_t k9_legal_py_count; /* Count of legal Pinyin numbers(k9) */ uint16_t k9_input_str_len; /* 9-key input(k9) mode input string max len */ @@ -61,13 +62,15 @@ typedef struct { uint16_t py_page; /* Current pinyin map pages(k26) */ uint16_t py_num[26]; /* Number and length of Pinyin */ uint16_t py_pos[26]; /* Pinyin position */ - uint8_t mode : 1; /* Set mode, 1: 26-key input(k26), 0: 9-key input(k9). Default: 1. */ + lv_ime_pinyin_mode_t mode; /* Set mode, 1: 26-key input(k26), 0: 9-key input(k9). Default: 1. */ } lv_ime_pinyin_t; /*********************** * GLOBAL VARIABLES ***********************/ +extern const lv_obj_class_t lv_ime_pinyin_class; + /********************** * GLOBAL PROTOTYPES **********************/ @@ -80,7 +83,7 @@ lv_obj_t * lv_ime_pinyin_create(lv_obj_t * parent); /** * Set the keyboard of Pinyin input method. * @param obj pointer to a Pinyin input method object - * @param dict pointer to a Pinyin input method keyboard + * @param kb pointer to a Pinyin input method keyboard */ void lv_ime_pinyin_set_keyboard(lv_obj_t * obj, lv_obj_t * kb); @@ -98,7 +101,6 @@ void lv_ime_pinyin_set_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict); */ void lv_ime_pinyin_set_mode(lv_obj_t * obj, lv_ime_pinyin_mode_t mode); - /*===================== * Getter functions *====================*/ @@ -110,7 +112,6 @@ void lv_ime_pinyin_set_mode(lv_obj_t * obj, lv_ime_pinyin_mode_t mode); */ lv_obj_t * lv_ime_pinyin_get_kb(lv_obj_t * obj); - /** * Set the dictionary of Pinyin input method. * @param obj pointer to a Pinyin input method object @@ -118,13 +119,12 @@ lv_obj_t * lv_ime_pinyin_get_kb(lv_obj_t * obj); */ lv_obj_t * lv_ime_pinyin_get_cand_panel(lv_obj_t * obj); - /** * Set the dictionary of Pinyin input method. * @param obj pointer to a Pinyin input method object * @return pointer to the Pinyin input method dictionary */ -lv_pinyin_dict_t * lv_ime_pinyin_get_dict(lv_obj_t * obj); +const lv_pinyin_dict_t * lv_ime_pinyin_get_dict(lv_obj_t * obj); /*===================== * Other functions @@ -141,5 +141,3 @@ lv_pinyin_dict_t * lv_ime_pinyin_get_dict(lv_obj_t * obj); #endif #endif /*LV_USE_IME_PINYIN*/ - - diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/imgfont/lv_imgfont.c b/lib/libesp32_lvgl/lvgl/src/others/imgfont/lv_imgfont.c similarity index 62% rename from lib/libesp32_lvgl/lvgl/src/extra/others/imgfont/lv_imgfont.c rename to lib/libesp32_lvgl/lvgl/src/others/imgfont/lv_imgfont.c index ad4ab6023..5a617ad80 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/imgfont/lv_imgfont.c +++ b/lib/libesp32_lvgl/lvgl/src/others/imgfont/lv_imgfont.c @@ -13,21 +13,21 @@ /********************* * DEFINES *********************/ -#define LV_IMGFONT_PATH_MAX_LEN 64 /********************** * TYPEDEFS **********************/ typedef struct { - lv_font_t * font; - lv_get_imgfont_path_cb_t path_cb; - char path[LV_IMGFONT_PATH_MAX_LEN]; + lv_font_t font; + lv_imgfont_get_path_cb_t path_cb; + void * user_data; } imgfont_dsc_t; /********************** * STATIC PROTOTYPES **********************/ -static const uint8_t * imgfont_get_glyph_bitmap(const lv_font_t * font, uint32_t unicode); +static const void * imgfont_get_glyph_bitmap(lv_font_glyph_dsc_t * g_dsc, uint32_t unicode, + lv_draw_buf_t * draw_buf); static bool imgfont_get_glyph_dsc(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode, uint32_t unicode_next); @@ -46,20 +46,16 @@ static bool imgfont_get_glyph_dsc(const lv_font_t * font, lv_font_glyph_dsc_t * /********************** * GLOBAL FUNCTIONS **********************/ -lv_font_t * lv_imgfont_create(uint16_t height, lv_get_imgfont_path_cb_t path_cb) +lv_font_t * lv_imgfont_create(uint16_t height, lv_imgfont_get_path_cb_t path_cb, void * user_data) { - LV_ASSERT_MSG(LV_IMGFONT_PATH_MAX_LEN > sizeof(lv_img_dsc_t), - "LV_IMGFONT_PATH_MAX_LEN must be greater than sizeof(lv_img_dsc_t)"); - - size_t size = sizeof(imgfont_dsc_t) + sizeof(lv_font_t); - imgfont_dsc_t * dsc = (imgfont_dsc_t *)lv_mem_alloc(size); + imgfont_dsc_t * dsc = lv_malloc_zeroed(sizeof(imgfont_dsc_t)); + LV_ASSERT_MALLOC(dsc); if(dsc == NULL) return NULL; - lv_memset_00(dsc, size); - dsc->font = (lv_font_t *)(((char *)dsc) + sizeof(imgfont_dsc_t)); dsc->path_cb = path_cb; + dsc->user_data = user_data; - lv_font_t * font = dsc->font; + lv_font_t * font = &dsc->font; font->dsc = dsc; font->get_glyph_dsc = imgfont_get_glyph_dsc; font->get_glyph_bitmap = imgfont_get_glyph_bitmap; @@ -69,29 +65,31 @@ lv_font_t * lv_imgfont_create(uint16_t height, lv_get_imgfont_path_cb_t path_cb) font->underline_position = 0; font->underline_thickness = 0; - return dsc->font; + return font; } void lv_imgfont_destroy(lv_font_t * font) { - if(font == NULL) { - return; - } + LV_ASSERT_NULL(font); imgfont_dsc_t * dsc = (imgfont_dsc_t *)font->dsc; - lv_mem_free(dsc); + lv_free(dsc); } /********************** * STATIC FUNCTIONS **********************/ -static const uint8_t * imgfont_get_glyph_bitmap(const lv_font_t * font, uint32_t unicode) +static const void * imgfont_get_glyph_bitmap(lv_font_glyph_dsc_t * g_dsc, uint32_t unicode, + lv_draw_buf_t * draw_buf) { - LV_UNUSED(unicode); - LV_ASSERT_NULL(font); + LV_UNUSED(draw_buf); + const lv_font_t * font = g_dsc->resolved_font; + imgfont_dsc_t * dsc = (imgfont_dsc_t *)font->dsc; - return (uint8_t *)dsc->path; + int32_t offset_y = 0; + const void * img_src = dsc->path_cb(font, unicode, 0, &offset_y, dsc->user_data); + return img_src; } static bool imgfont_get_glyph_dsc(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, @@ -103,12 +101,13 @@ static bool imgfont_get_glyph_dsc(const lv_font_t * font, lv_font_glyph_dsc_t * LV_ASSERT_NULL(dsc); if(dsc->path_cb == NULL) return false; - if(!dsc->path_cb(dsc->font, dsc->path, LV_IMGFONT_PATH_MAX_LEN, unicode, unicode_next)) { - return false; - } + int32_t offset_y = 0; - lv_img_header_t header; - if(lv_img_decoder_get_info(dsc->path, &header) != LV_RES_OK) { + const void * img_src = dsc->path_cb(font, unicode, unicode_next, &offset_y, dsc->user_data); + if(img_src == NULL) return false; + + lv_image_header_t header; + if(lv_image_decoder_get_info(img_src, &header) != LV_RESULT_OK) { return false; } @@ -118,7 +117,7 @@ static bool imgfont_get_glyph_dsc(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out->box_h = header.h; dsc_out->bpp = LV_IMGFONT_BPP; /* is image identifier */ dsc_out->ofs_x = 0; - dsc_out->ofs_y = 0; + dsc_out->ofs_y = offset_y; return true; } diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/imgfont/lv_imgfont.h b/lib/libesp32_lvgl/lvgl/src/others/imgfont/lv_imgfont.h similarity index 72% rename from lib/libesp32_lvgl/lvgl/src/extra/others/imgfont/lv_imgfont.h rename to lib/libesp32_lvgl/lvgl/src/others/imgfont/lv_imgfont.h index 5069b62f4..247ce8d39 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/imgfont/lv_imgfont.h +++ b/lib/libesp32_lvgl/lvgl/src/others/imgfont/lv_imgfont.h @@ -26,8 +26,9 @@ extern "C" { **********************/ /* gets the image path name of this character */ -typedef bool (*lv_get_imgfont_path_cb_t)(const lv_font_t * font, void * img_src, - uint16_t len, uint32_t unicode, uint32_t unicode_next); +typedef const void * (*lv_imgfont_get_path_cb_t)(const lv_font_t * font, + uint32_t unicode, uint32_t unicode_next, + int32_t * offset_y, void * user_data); /********************** * GLOBAL PROTOTYPES @@ -37,9 +38,10 @@ typedef bool (*lv_get_imgfont_path_cb_t)(const lv_font_t * font, void * img_src, * Creates a image font with info parameter specified. * @param height font size * @param path_cb a function to get the image path name of character. + * @param user_data pointer to user data * @return pointer to the new imgfont or NULL if create error. */ -lv_font_t * lv_imgfont_create(uint16_t height, lv_get_imgfont_path_cb_t path_cb); +lv_font_t * lv_imgfont_create(uint16_t height, lv_imgfont_get_path_cb_t path_cb, void * user_data); /** * Destroy a image font that has been created. diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/monkey/lv_monkey.c b/lib/libesp32_lvgl/lvgl/src/others/monkey/lv_monkey.c similarity index 78% rename from lib/libesp32_lvgl/lvgl/src/extra/others/monkey/lv_monkey.c rename to lib/libesp32_lvgl/lvgl/src/others/monkey/lv_monkey.c index 6ec45e22b..1259a9d3c 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/monkey/lv_monkey.c +++ b/lib/libesp32_lvgl/lvgl/src/others/monkey/lv_monkey.c @@ -19,16 +19,13 @@ /********************** * TYPEDEFS **********************/ -typedef struct _lv_monkey { +struct _lv_monkey { lv_monkey_config_t config; - lv_indev_drv_t indev_drv; lv_indev_data_t indev_data; lv_indev_t * indev; lv_timer_t * timer; -#if LV_USE_USER_DATA void * user_data; -#endif -} lv_monkey_t; +}; static const lv_key_t lv_key_map[] = { LV_KEY_UP, @@ -49,7 +46,7 @@ static const lv_key_t lv_key_map[] = { * STATIC PROTOTYPES **********************/ -static void lv_monkey_read_cb(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); +static void lv_monkey_read_cb(lv_indev_t * indev, lv_indev_data_t * data); static int32_t lv_monkey_random(int32_t howsmall, int32_t howbig); static void lv_monkey_timer_cb(lv_timer_t * timer); @@ -59,7 +56,7 @@ static void lv_monkey_timer_cb(lv_timer_t * timer); void lv_monkey_config_init(lv_monkey_config_t * config) { - lv_memset_00(config, sizeof(lv_monkey_config_t)); + lv_memzero(config, sizeof(lv_monkey_config_t)); config->type = LV_INDEV_TYPE_POINTER; config->period_range.min = MONKEY_PERIOD_RANGE_MIN_DEF; config->period_range.max = MONKEY_PERIOD_RANGE_MAX_DEF; @@ -67,24 +64,17 @@ void lv_monkey_config_init(lv_monkey_config_t * config) lv_monkey_t * lv_monkey_create(const lv_monkey_config_t * config) { - lv_monkey_t * monkey = lv_mem_alloc(sizeof(lv_monkey_t)); + lv_monkey_t * monkey = lv_malloc_zeroed(sizeof(lv_monkey_t)); LV_ASSERT_MALLOC(monkey); - lv_memset_00(monkey, sizeof(lv_monkey_t)); - monkey->config = *config; - - lv_indev_drv_t * drv = &monkey->indev_drv; - lv_indev_drv_init(drv); - drv->type = config->type; - drv->read_cb = lv_monkey_read_cb; - drv->user_data = monkey; - monkey->timer = lv_timer_create(lv_monkey_timer_cb, monkey->config.period_range.min, monkey); lv_timer_pause(monkey->timer); - monkey->indev = lv_indev_drv_register(drv); - + monkey->indev = lv_indev_create(); + lv_indev_set_type(monkey->indev, config->type); + lv_indev_set_read_cb(monkey->indev, lv_monkey_read_cb); + lv_indev_set_user_data(monkey->indev, monkey); return monkey; } @@ -106,8 +96,6 @@ bool lv_monkey_get_enable(lv_monkey_t * monkey) return !monkey->timer->paused; } -#if LV_USE_USER_DATA - void lv_monkey_set_user_data(lv_monkey_t * monkey, void * user_data) { LV_ASSERT_NULL(monkey); @@ -120,24 +108,22 @@ void * lv_monkey_get_user_data(lv_monkey_t * monkey) return monkey->user_data; } -#endif - -void lv_monkey_del(lv_monkey_t * monkey) +void lv_monkey_delete(lv_monkey_t * monkey) { LV_ASSERT_NULL(monkey); - lv_timer_del(monkey->timer); + lv_timer_delete(monkey->timer); lv_indev_delete(monkey->indev); - lv_mem_free(monkey); + lv_free(monkey); } /********************** * STATIC FUNCTIONS **********************/ -static void lv_monkey_read_cb(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) +static void lv_monkey_read_cb(lv_indev_t * indev, lv_indev_data_t * data) { - lv_monkey_t * monkey = indev_drv->user_data; + lv_monkey_t * monkey = lv_indev_get_user_data(indev); data->btn_id = monkey->indev_data.btn_id; data->point = monkey->indev_data.point; @@ -159,10 +145,10 @@ static void lv_monkey_timer_cb(lv_timer_t * timer) lv_monkey_t * monkey = timer->user_data; lv_indev_data_t * data = &monkey->indev_data; - switch(monkey->indev_drv.type) { + switch(lv_indev_get_type(monkey->indev)) { case LV_INDEV_TYPE_POINTER: - data->point.x = (lv_coord_t)lv_monkey_random(0, LV_HOR_RES - 1); - data->point.y = (lv_coord_t)lv_monkey_random(0, LV_VER_RES - 1); + data->point.x = (int32_t)lv_monkey_random(0, LV_HOR_RES - 1); + data->point.y = (int32_t)lv_monkey_random(0, LV_VER_RES - 1); break; case LV_INDEV_TYPE_ENCODER: data->enc_diff = (int16_t)lv_monkey_random(monkey->config.input_range.min, monkey->config.input_range.max); diff --git a/lib/libesp32_lvgl/lvgl/src/extra/others/monkey/lv_monkey.h b/lib/libesp32_lvgl/lvgl/src/others/monkey/lv_monkey.h similarity index 95% rename from lib/libesp32_lvgl/lvgl/src/extra/others/monkey/lv_monkey.h rename to lib/libesp32_lvgl/lvgl/src/others/monkey/lv_monkey.h index bf5e13c62..92b024d09 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/others/monkey/lv_monkey.h +++ b/lib/libesp32_lvgl/lvgl/src/others/monkey/lv_monkey.h @@ -32,8 +32,10 @@ typedef struct { /**< Monkey execution period*/ struct { + //! @cond Doxygen_Suppress uint32_t min; uint32_t max; + //! @endcond } period_range; /**< The range of input value*/ @@ -81,8 +83,6 @@ void lv_monkey_set_enable(lv_monkey_t * monkey, bool en); */ bool lv_monkey_get_enable(lv_monkey_t * monkey); -#if LV_USE_USER_DATA - /** * Set the user_data field of the monkey * @param monkey pointer to a monkey @@ -97,13 +97,11 @@ void lv_monkey_set_user_data(lv_monkey_t * monkey, void * user_data); */ void * lv_monkey_get_user_data(lv_monkey_t * monkey); -#endif/*LV_USE_USER_DATA*/ - /** * Delete monkey * @param monkey pointer to monkey */ -void lv_monkey_del(lv_monkey_t * monkey); +void lv_monkey_delete(lv_monkey_t * monkey); /********************** * MACROS diff --git a/lib/libesp32_lvgl/lvgl/src/others/observer/lv_observer.c b/lib/libesp32_lvgl/lvgl/src/others/observer/lv_observer.c new file mode 100644 index 000000000..6298c8d52 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/others/observer/lv_observer.c @@ -0,0 +1,709 @@ +/** + * @file lv_observer.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_observer.h" +#if LV_USE_OBSERVER + +#include "../../lvgl.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + uint32_t flag; + lv_subject_value_t value; + uint32_t inv : 1; +} flag_and_cond_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static void unsubscribe_on_delete_cb(lv_event_t * e); +static void group_notify_cb(lv_observer_t * observer, lv_subject_t * subject); +static lv_observer_t * bind_to_bitfield(lv_subject_t * subject, lv_obj_t * obj, lv_observer_cb_t cb, uint32_t flag, + int32_t ref_value, bool inv); +static void obj_flag_observer_cb(lv_observer_t * observer, lv_subject_t * subject); +static void obj_state_observer_cb(lv_observer_t * observer, lv_subject_t * subject); + +#if LV_USE_BUTTON + static void btn_value_changed_event_cb(lv_event_t * e); +#endif + +#if LV_USE_LABEL + static void label_text_observer_cb(lv_observer_t * observer, lv_subject_t * subject); +#endif + +#if LV_USE_ARC + static void arc_value_changed_event_cb(lv_event_t * e); + static void arc_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject); +#endif + +#if LV_USE_SLIDER + static void slider_value_changed_event_cb(lv_event_t * e); + static void slider_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject); +#endif + +#if LV_USE_ROLLER + static void roller_value_changed_event_cb(lv_event_t * e); + static void roller_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject); +#endif + +#if LV_USE_DROPDOWN + static void dropdown_value_changed_event_cb(lv_event_t * e); + static void dropdown_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject); +#endif + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_subject_init_int(lv_subject_t * subject, int32_t value) +{ + lv_memzero(subject, sizeof(lv_subject_t)); + subject->type = LV_SUBJECT_TYPE_INT; + subject->value.num = value; + subject->prev_value.num = value; + _lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t)); +} + +void lv_subject_set_int(lv_subject_t * subject, int32_t value) +{ + if(subject->type != LV_SUBJECT_TYPE_INT) { + LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_INT"); + return; + } + + subject->prev_value.num = subject->value.num; + subject->value.num = value; + lv_subject_notify(subject); +} + +int32_t lv_subject_get_int(lv_subject_t * subject) +{ + if(subject->type != LV_SUBJECT_TYPE_INT) { + LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_INT"); + return 0; + } + + return subject->value.num; +} + +int32_t lv_subject_get_previous_int(lv_subject_t * subject) +{ + if(subject->type != LV_SUBJECT_TYPE_INT) { + LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_INT"); + return 0; + } + + return subject->prev_value.num; +} + +void lv_subject_init_string(lv_subject_t * subject, char * buf, char * prev_buf, size_t size, const char * value) +{ + lv_memzero(subject, sizeof(lv_subject_t)); + lv_strncpy(buf, value, size); + if(prev_buf) lv_strncpy(prev_buf, value, size); + + subject->type = LV_SUBJECT_TYPE_STRING; + subject->size = size; + subject->value.pointer = buf; + subject->prev_value.pointer = prev_buf; + + _lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t)); +} + +void lv_subject_copy_string(lv_subject_t * subject, const char * buf) +{ + if(subject->type != LV_SUBJECT_TYPE_STRING) { + LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_INT"); + return; + } + + if(subject->size < 1) return; + if(subject->prev_value.pointer) { + lv_strncpy((char *)subject->prev_value.pointer, subject->value.pointer, subject->size - 1); + } + + lv_strncpy((char *)subject->value.pointer, buf, subject->size - 1); + + lv_subject_notify(subject); + +} + +const char * lv_subject_get_string(lv_subject_t * subject) +{ + if(subject->type != LV_SUBJECT_TYPE_STRING) { + LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_STRING"); + return ""; + } + + return subject->value.pointer; +} + +const char * lv_subject_get_previous_string(lv_subject_t * subject) +{ + if(subject->type != LV_SUBJECT_TYPE_STRING) { + LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_STRING"); + return NULL; + } + + return subject->prev_value.pointer; +} + +void lv_subject_init_pointer(lv_subject_t * subject, void * value) +{ + lv_memzero(subject, sizeof(lv_subject_t)); + subject->type = LV_SUBJECT_TYPE_POINTER; + subject->value.pointer = value; + subject->prev_value.pointer = value; + _lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t)); +} + +void lv_subject_set_pointer(lv_subject_t * subject, void * ptr) +{ + if(subject->type != LV_SUBJECT_TYPE_POINTER) { + LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_POINTER"); + return; + } + + subject->prev_value.pointer = subject->value.pointer; + subject->value.pointer = ptr; + lv_subject_notify(subject); +} + +const void * lv_subject_get_pointer(lv_subject_t * subject) +{ + if(subject->type != LV_SUBJECT_TYPE_POINTER) { + LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_POINTER"); + return NULL; + } + + return subject->value.pointer; +} + +const void * lv_subject_get_previous_pointer(lv_subject_t * subject) +{ + if(subject->type != LV_SUBJECT_TYPE_POINTER) { + LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_POINTER"); + return NULL; + } + + return subject->prev_value.pointer; +} + +void lv_subject_init_color(lv_subject_t * subject, lv_color_t color) +{ + lv_memzero(subject, sizeof(lv_subject_t)); + subject->type = LV_SUBJECT_TYPE_COLOR; + subject->value.color = color; + subject->prev_value.color = color; + _lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t)); +} + +void lv_subject_set_color(lv_subject_t * subject, lv_color_t color) +{ + if(subject->type != LV_SUBJECT_TYPE_COLOR) { + LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_COLOR"); + return; + } + + subject->prev_value.color = subject->value.color; + subject->value.color = color; + lv_subject_notify(subject); +} + +lv_color_t lv_subject_get_color(lv_subject_t * subject) +{ + if(subject->type != LV_SUBJECT_TYPE_COLOR) { + LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_COLOR"); + return lv_color_black(); + } + + return subject->value.color; +} + +lv_color_t lv_subject_get_previous_color(lv_subject_t * subject) +{ + if(subject->type != LV_SUBJECT_TYPE_COLOR) { + LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_COLOR"); + return lv_color_black(); + } + + return subject->prev_value.color; +} + +void lv_subject_init_group(lv_subject_t * subject, lv_subject_t * list[], uint32_t list_len) +{ + subject->type = LV_SUBJECT_TYPE_GROUP; + subject->size = list_len; + _lv_ll_init(&(subject->subs_ll), sizeof(lv_observer_t)); + subject->value.pointer = list; + + /* bind all subjects to this subject */ + uint32_t i; + for(i = 0; i < list_len; i++) { + /*If a subject in the group changes notify the group itself*/ + lv_subject_add_observer(list[i], group_notify_cb, subject); + } +} + +lv_subject_t * lv_subject_get_group_element(lv_subject_t * subject, int32_t index) +{ + if(subject->type != LV_SUBJECT_TYPE_GROUP) { + LV_LOG_WARN("Subject type is not LV_SUBJECT_TYPE_GROUP"); + return NULL; + } + + if(index >= subject->size) return NULL; + + return ((lv_subject_t **)(subject->value.pointer))[index]; +} + +lv_observer_t * lv_subject_add_observer(lv_subject_t * subject, lv_observer_cb_t cb, void * user_data) +{ + lv_observer_t * observer = lv_subject_add_observer_obj(subject, cb, NULL, user_data); + return observer; +} + +lv_observer_t * lv_subject_add_observer_obj(lv_subject_t * subject, lv_observer_cb_t cb, lv_obj_t * obj, + void * user_data) +{ + LV_ASSERT_NULL(subject); + if(subject->type == LV_SUBJECT_TYPE_INVALID) { + LV_LOG_WARN("Subject not initialized yet"); + return NULL; + } + lv_observer_t * observer = _lv_ll_ins_tail(&(subject->subs_ll)); + LV_ASSERT_MALLOC(observer); + if(observer == NULL) return NULL; + + lv_memzero(observer, sizeof(*observer)); + + observer->subject = subject; + observer->cb = cb; + observer->user_data = user_data; + observer->target = obj; + /* subscribe to delete event of the object */ + if(obj != NULL) { + lv_obj_add_event_cb(obj, unsubscribe_on_delete_cb, LV_EVENT_DELETE, observer); + } + + /* update object immediately */ + if(observer->cb) observer->cb(observer, subject); + + return observer; +} + +lv_observer_t * lv_subject_add_observer_with_target(lv_subject_t * subject, lv_observer_cb_t cb, void * target, + void * user_data) +{ + LV_ASSERT_NULL(subject); + if(subject->type == LV_SUBJECT_TYPE_INVALID) { + LV_LOG_WARN("Subject not initialized yet"); + return NULL; + } + lv_observer_t * observer = _lv_ll_ins_tail(&(subject->subs_ll)); + LV_ASSERT_MALLOC(observer); + if(observer == NULL) return NULL; + + lv_memzero(observer, sizeof(*observer)); + + observer->subject = subject; + observer->cb = cb; + observer->user_data = user_data; + observer->target = target; + + /* update object immediately */ + if(observer->cb) observer->cb(observer, subject); + + return observer; +} + +void lv_observer_remove(lv_observer_t * observer) +{ + LV_ASSERT_NULL(observer); + + observer->subject->notify_restart_query = 1; + + _lv_ll_remove(&(observer->subject->subs_ll), observer); + + if(observer->auto_free_user_data) { + lv_free(observer->user_data); + } + lv_free(observer); +} + +void lv_subject_remove_all_obj(lv_subject_t * subject, lv_obj_t * obj) +{ + LV_ASSERT_NULL(subject); + if(subject->type == LV_SUBJECT_TYPE_INVALID) { + LV_LOG_WARN("Subject not initialized yet"); + return; + } + while(lv_obj_remove_event_cb(obj, unsubscribe_on_delete_cb)); + while(lv_obj_remove_event_cb(obj, btn_value_changed_event_cb)); + while(lv_obj_remove_event_cb(obj, arc_value_changed_event_cb)); +#if LV_USE_ROLLER + while(lv_obj_remove_event_cb(obj, roller_value_changed_event_cb)); +#endif + +#if LV_USE_DROPDOWN + while(lv_obj_remove_event_cb(obj, dropdown_value_changed_event_cb)); +#endif + + lv_observer_t * observer = _lv_ll_get_head(&subject->subs_ll); + while(observer) { + lv_observer_t * observer_next = _lv_ll_get_next(&subject->subs_ll, observer); + if(observer->target == obj) { + lv_observer_remove(observer); + } + observer = observer_next; + } +} + +void * lv_observer_get_target(lv_observer_t * observer) +{ + LV_ASSERT_NULL(observer); + + return observer->target; +} + +void lv_subject_notify(lv_subject_t * subject) +{ + LV_ASSERT_NULL(subject); + + lv_observer_t * observer; + _LV_LL_READ(&(subject->subs_ll), observer) { + observer->notified = 0; + } + + do { + subject->notify_restart_query = 0; + _LV_LL_READ(&(subject->subs_ll), observer) { + if(observer->cb && observer->notified == 0) { + observer->cb(observer, subject); + if(subject->notify_restart_query) break; + observer->notified = 1; + } + } + } while(subject->notify_restart_query); +} + +lv_observer_t * lv_obj_bind_flag_if_eq(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag, int32_t ref_value) +{ + lv_observer_t * observable = bind_to_bitfield(subject, obj, obj_flag_observer_cb, flag, ref_value, false); + return observable; +} + +lv_observer_t * lv_obj_bind_flag_if_not_eq(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag, + int32_t ref_value) +{ + lv_observer_t * observable = bind_to_bitfield(subject, obj, obj_flag_observer_cb, flag, ref_value, true); + return observable; +} + +lv_observer_t * lv_obj_bind_state_if_eq(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state, int32_t ref_value) +{ + lv_observer_t * observable = bind_to_bitfield(subject, obj, obj_state_observer_cb, state, ref_value, false); + return observable; +} + +lv_observer_t * lv_obj_bind_state_if_not_eq(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state, int32_t ref_value) +{ + lv_observer_t * observable = bind_to_bitfield(subject, obj, obj_state_observer_cb, state, ref_value, true); + return observable; +} + +#if LV_USE_BUTTON +lv_observer_t * lv_button_bind_checked(lv_obj_t * obj, lv_subject_t * subject) +{ + lv_observer_t * observable = bind_to_bitfield(subject, obj, obj_state_observer_cb, LV_STATE_CHECKED, 1, false); + lv_obj_add_event_cb(obj, btn_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject); + return observable; +} +#endif /*LV_USE_BUTTON*/ + +#if LV_USE_LABEL +lv_observer_t * lv_label_bind_text(lv_obj_t * obj, lv_subject_t * subject, const char * fmt) +{ + if(fmt == NULL) { + if(subject->type != LV_SUBJECT_TYPE_STRING && subject->type != LV_SUBJECT_TYPE_POINTER) { + LV_LOG_WARN("Incompatible subject type: %d", subject->type); + return NULL; + } + } + else { + if(subject->type != LV_SUBJECT_TYPE_STRING && subject->type != LV_SUBJECT_TYPE_POINTER && + subject->type != LV_SUBJECT_TYPE_INT) { + LV_LOG_WARN("Incompatible subject type: %d", subject->type); + return NULL; + } + } + + lv_observer_t * observer = lv_subject_add_observer_obj(subject, label_text_observer_cb, obj, (void *)fmt); + return observer; +} +#endif /*LV_USE_LABEL*/ + +#if LV_USE_ARC +lv_observer_t * lv_arc_bind_value(lv_obj_t * obj, lv_subject_t * subject) +{ + if(subject->type != LV_SUBJECT_TYPE_INT) { + LV_LOG_WARN("Incompatible subject type: %d", subject->type); + return NULL; + } + + lv_obj_add_event_cb(obj, arc_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject); + + lv_observer_t * observer = lv_subject_add_observer_obj(subject, arc_value_observer_cb, obj, NULL); + return observer; +} +#endif /*LV_USE_ARC*/ + +#if LV_USE_SLIDER +lv_observer_t * lv_slider_bind_value(lv_obj_t * obj, lv_subject_t * subject) +{ + if(subject->type != LV_SUBJECT_TYPE_INT) { + LV_LOG_WARN("Incompatible subject type: %d", subject->type); + return NULL; + } + + lv_obj_add_event_cb(obj, slider_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject); + + lv_observer_t * observer = lv_subject_add_observer_obj(subject, slider_value_observer_cb, obj, NULL); + return observer; +} +#endif /*LV_USE_SLIDER*/ + +#if LV_USE_ROLLER + +lv_observer_t * lv_roller_bind_value(lv_obj_t * obj, lv_subject_t * subject) +{ + if(subject->type != LV_SUBJECT_TYPE_INT) { + LV_LOG_WARN("Incompatible subject type: %d", subject->type); + return NULL; + } + + lv_obj_add_event_cb(obj, roller_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject); + + lv_observer_t * observer = lv_subject_add_observer_obj(subject, roller_value_observer_cb, obj, NULL); + return observer; + +} +#endif /*LV_USE_ROLLER*/ + +#if LV_USE_DROPDOWN + +lv_observer_t * lv_dropdown_bind_value(lv_obj_t * obj, lv_subject_t * subject) +{ + if(subject->type != LV_SUBJECT_TYPE_INT) { + LV_LOG_WARN("Incompatible subject type: %d", subject->type); + return NULL; + } + + lv_obj_add_event_cb(obj, dropdown_value_changed_event_cb, LV_EVENT_VALUE_CHANGED, subject); + + lv_observer_t * observer = lv_subject_add_observer_obj(subject, dropdown_value_observer_cb, obj, NULL); + return observer; + +} + +#endif /*LV_USE_DROPDOWN*/ + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void group_notify_cb(lv_observer_t * observer, lv_subject_t * subject) +{ + LV_UNUSED(subject); + lv_subject_t * subject_group = observer->user_data; + lv_subject_notify(subject_group); +} + +static void unsubscribe_on_delete_cb(lv_event_t * e) +{ + lv_observer_t * observer = lv_event_get_user_data(e); + lv_observer_remove(observer); +} + +static lv_observer_t * bind_to_bitfield(lv_subject_t * subject, lv_obj_t * obj, lv_observer_cb_t cb, uint32_t flag, + int32_t ref_value, bool inv) +{ + if(subject->type != LV_SUBJECT_TYPE_INT) { + LV_LOG_WARN("Incompatible subject type: %d", subject->type); + return NULL; + } + + flag_and_cond_t * p = lv_malloc(sizeof(flag_and_cond_t)); + if(p == NULL) { + LV_LOG_WARN("Out of memory"); + return NULL; + } + + p->flag = flag; + p->value.num = ref_value; + p->inv = inv; + + lv_observer_t * observable = lv_subject_add_observer_obj(subject, cb, obj, p); + observable->auto_free_user_data = 1; + return observable; +} + +static void obj_flag_observer_cb(lv_observer_t * observer, lv_subject_t * subject) +{ + flag_and_cond_t * p = observer->user_data; + + bool res = subject->value.num == p->value.num; + if(p->inv) res = !res; + + if(res) { + lv_obj_add_flag(observer->target, p->flag); + } + else { + lv_obj_remove_flag(observer->target, p->flag); + } +} + +static void obj_state_observer_cb(lv_observer_t * observer, lv_subject_t * subject) +{ + flag_and_cond_t * p = observer->user_data; + + bool res = subject->value.num == p->value.num; + if(p->inv) res = !res; + + if(res) { + lv_obj_add_state(observer->target, p->flag); + } + else { + lv_obj_remove_state(observer->target, p->flag); + } +} + +#if LV_USE_BUTTON + +static void btn_value_changed_event_cb(lv_event_t * e) +{ + lv_obj_t * obj = lv_event_get_current_target(e); + lv_subject_t * subject = lv_event_get_user_data(e); + + lv_subject_set_int(subject, lv_obj_has_state(obj, LV_STATE_CHECKED)); +} + +#endif /*LV_USE_BUTTON*/ + +#if LV_USE_LABEL + +static void label_text_observer_cb(lv_observer_t * observer, lv_subject_t * subject) +{ + const char * fmt = observer->user_data; + + if(fmt == NULL) { + lv_label_set_text(observer->target, subject->value.pointer); + } + else { + switch(subject->type) { + case LV_SUBJECT_TYPE_INT: + lv_label_set_text_fmt(observer->target, fmt, subject->value.num); + break; + case LV_SUBJECT_TYPE_STRING: + case LV_SUBJECT_TYPE_POINTER: + lv_label_set_text_fmt(observer->target, fmt, subject->value.pointer); + break; + default: + break; + } + } +} + +#endif /*LV_USE_LABEL*/ + +#if LV_USE_ARC + +static void arc_value_changed_event_cb(lv_event_t * e) +{ + lv_obj_t * arc = lv_event_get_current_target(e); + lv_subject_t * subject = lv_event_get_user_data(e); + + lv_subject_set_int(subject, lv_arc_get_value(arc)); +} + +static void arc_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject) +{ + lv_arc_set_value(observer->target, subject->value.num); +} + +#endif /*LV_USE_ARC*/ + +#if LV_USE_SLIDER + +static void slider_value_changed_event_cb(lv_event_t * e) +{ + lv_obj_t * slider = lv_event_get_current_target(e); + lv_subject_t * subject = lv_event_get_user_data(e); + + lv_subject_set_int(subject, lv_slider_get_value(slider)); +} + +static void slider_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject) +{ + lv_slider_set_value(observer->target, subject->value.num, LV_ANIM_OFF); +} + +#endif /*LV_USE_SLIDER*/ + +#if LV_USE_ROLLER + +static void roller_value_changed_event_cb(lv_event_t * e) +{ + lv_obj_t * roller = lv_event_get_current_target(e); + lv_subject_t * subject = lv_event_get_user_data(e); + + lv_subject_set_int(subject, lv_roller_get_selected(roller)); +} + +static void roller_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject) +{ + if((int32_t)lv_roller_get_selected(observer->target) != subject->value.num) { + lv_roller_set_selected(observer->target, subject->value.num, LV_ANIM_OFF); + } +} + +#endif /*LV_USE_ROLLER*/ + +#if LV_USE_DROPDOWN + +static void dropdown_value_changed_event_cb(lv_event_t * e) +{ + lv_obj_t * dropdown = lv_event_get_current_target(e); + lv_subject_t * subject = lv_event_get_user_data(e); + + lv_subject_set_int(subject, lv_dropdown_get_selected(dropdown)); +} + +static void dropdown_value_observer_cb(lv_observer_t * observer, lv_subject_t * subject) +{ + lv_dropdown_set_selected(observer->target, subject->value.num); +} + +#endif /*LV_USE_DROPDOWN*/ + +#endif /*LV_USE_OBSERVER*/ diff --git a/lib/libesp32_lvgl/lvgl/src/others/observer/lv_observer.h b/lib/libesp32_lvgl/lvgl/src/others/observer/lv_observer.h new file mode 100644 index 000000000..e1c9cb6b7 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/others/observer/lv_observer.h @@ -0,0 +1,406 @@ +/** + * @file lv_observer.h + * + */ + +#ifndef LV_OBSERVER_H +#define LV_OBSERVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../core/lv_obj.h" +#if LV_USE_OBSERVER + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +struct _lv_observer_t; +typedef struct _lv_observer_t lv_observer_t; + +typedef enum { + LV_SUBJECT_TYPE_INVALID = 0, /**< indicates subject not initialized yet*/ + LV_SUBJECT_TYPE_NONE = 1, /**< a null value like None or NILt*/ + LV_SUBJECT_TYPE_INT = 2, /**< an int32_t*/ + LV_SUBJECT_TYPE_POINTER = 3, /**< a void pointer*/ + LV_SUBJECT_TYPE_COLOR = 4, /**< an lv_color_t*/ + LV_SUBJECT_TYPE_GROUP = 5, /**< an array of subjects*/ + LV_SUBJECT_TYPE_STRING = 6, /**< a char pointer*/ +} lv_subject_type_t; + +/** + * A common type to handle all the various observable types in the same way + */ +typedef union { + int32_t num; /**< Integer number (opacity, enums, booleans or "normal" numbers)*/ + const void * pointer; /**< Constant pointer (string buffer, format string, font, cone text, etc)*/ + lv_color_t color; /**< Color */ +} lv_subject_value_t; + +/** + * The subject (an observable value) + */ +typedef struct { + lv_ll_t subs_ll; /**< Subscribers*/ + uint32_t type : 4; + uint32_t size : 28; /**< Might be used to store a size related to `type`*/ + lv_subject_value_t value; /**< Actual value*/ + lv_subject_value_t prev_value; /**< Previous value*/ + uint32_t notify_restart_query : 1; /**< If an observer deleted start notifying from the beginning. */ + void * user_data; /**< Additional parameter, can be used freely by the user*/ +} lv_subject_t; + +/** + * Callback called when the observed value changes + * @param observer pointer to the observer of the callback + * @param subject pointer to the subject of the observer + */ +typedef void (*lv_observer_cb_t)(lv_observer_t * observer, lv_subject_t * subject); + +/** + * The observer object: a descriptor returned when subscribing LVGL widgets to subjects + */ +struct _lv_observer_t { + lv_subject_t * subject; /**< The observed value */ + lv_observer_cb_t cb; /**< Callback that should be called when the value changes*/ + void * target; /**< A target for the observer, e.g. a widget or style*/ + void * user_data; /**< Additional parameter supplied when subscribing*/ + uint32_t auto_free_user_data : 1; /**< Automatically free user data when the observer is removed */ + uint32_t notified : 1; /**< Mark if this observer was already notified*/ +}; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize an integer type subject + * @param subject pointer to the subject + * @param value initial value + */ +void lv_subject_init_int(lv_subject_t * subject, int32_t value); + +/** + * Set the value of an integer subject. It will notify all the observers as well. + * @param subject pointer to the subject + * @param value the new value + */ +void lv_subject_set_int(lv_subject_t * subject, int32_t value); + +/** + * Get the current value of an integer subject + * @param subject pointer to the subject + * @return the current value + */ +int32_t lv_subject_get_int(lv_subject_t * subject); + +/** + * Get the previous value of an integer subject + * @param subject pointer to the subject + * @return the current value + */ +int32_t lv_subject_get_previous_int(lv_subject_t * subject); + +/** + * Initialize a string type subject + * @param subject pointer to the subject + * @param buf pointer to a buffer to store the string + * @param prev_buf pointer to a buffer to store the previous string, can be NULL if not used + * @param size size of the buffer + * @param value initial value as a string, e.g. "hello" + * @note the string subject stores the whole string, not only a pointer + */ +void lv_subject_init_string(lv_subject_t * subject, char * buf, char * prev_buf, size_t size, const char * value); + +/** + * Copy a string to a subject. It will notify all the observers as well. + * @param subject pointer to the subject + * @param buf the new string + */ +void lv_subject_copy_string(lv_subject_t * subject, const char * buf); + +/** + * Get the current value of an string subject + * @param subject pointer to the subject + * @return pointer to the buffer containing the current value + */ +const char * lv_subject_get_string(lv_subject_t * subject); + +/** + * Get the previous value of an string subject + * @param subject pointer to the subject + * @return pointer to the buffer containing the current value + * @note NULL will be returned if NULL was passed in `lv_subject_init_string()` + * as `prev_buf` + */ +const char * lv_subject_get_previous_string(lv_subject_t * subject); + +/** + * Initialize an pointer type subject + * @param subject pointer to the subject + * @param value initial value + */ +void lv_subject_init_pointer(lv_subject_t * subject, void * value); + +/** + * Set the value of a pointer subject. It will notify all the observers as well. + * @param subject pointer to the subject + * @param value the new value + */ +void lv_subject_set_pointer(lv_subject_t * subject, void * ptr); + +/** + * Get the current value of a pointer subject + * @param subject pointer to the subject + * @return the current value + */ +const void * lv_subject_get_pointer(lv_subject_t * subject); + +/** + * Get the previous value of a pointer subject + * @param subject pointer to the subject + * @return the current value + */ +const void * lv_subject_get_previous_pointer(lv_subject_t * subject); + +/** + * Initialize an color type subject + * @param subject pointer to the subject + * @param value initial value + */ +void lv_subject_init_color(lv_subject_t * subject, lv_color_t color); + +/** + * Set the value of a color subject. It will notify all the observers as well. + * @param subject pointer to the subject + * @param value the new value + */ +void lv_subject_set_color(lv_subject_t * subject, lv_color_t color); + +/** + * Get the current value of a color subject + * @param subject pointer to the subject + * @return the current value + */ +lv_color_t lv_subject_get_color(lv_subject_t * subject); + +/** + * Get the previous value of a color subject + * @param subject pointer to the subject + * @return the current value + */ +lv_color_t lv_subject_get_previous_color(lv_subject_t * subject); + +/** + * Initialize a subject group + * @param subject pointer to the subject + * @param list list of other subject addresses, any of these changes `subject` will be notified + * @param list_len number of elements in `list` + */ +void lv_subject_init_group(lv_subject_t * subject, lv_subject_t * list[], uint32_t list_len); + +/** + * Get an element from the subject group's list + * @param subject pointer to the subject + * @param index index of the element to get + * @return pointer a subject from the list, or NULL if the index is out of bounds + */ +lv_subject_t * lv_subject_get_group_element(lv_subject_t * subject, int32_t index); + +/** + * Add an observer to a subject. When the subject changes `observer_cb` will be called. + * @param subject pointer to the subject + * @param observer_cb the callback to call + * @param user_data optional user data + * @return pointer to the created observer + */ +lv_observer_t * lv_subject_add_observer(lv_subject_t * subject, lv_observer_cb_t observer_cb, void * user_data); + +/** + * Add an observer to a subject for an object. + * When the object is deleted, it will be removed from the subject automatically. + * @param subject pointer to the subject + * @param observer_cb the callback to call + * @param obj pointer to an object + * @param user_data optional user data + * @return pointer to the created observer + */ +lv_observer_t * lv_subject_add_observer_obj(lv_subject_t * subject, lv_observer_cb_t observer_cb, lv_obj_t * obj, + void * user_data); + +/** + * Add an observer to a subject and also save a target. + * @param subject pointer to the subject + * @param observer_cb the callback to call + * @param target pointer to any data + * @param user_data optional user data + * @return pointer to the created observer + */ +lv_observer_t * lv_subject_add_observer_with_target(lv_subject_t * subject, lv_observer_cb_t cb, void * target, + void * user_data); + +/** + * Remove an observer from its subject + * @param observer pointer to an observer + */ +void lv_observer_remove(lv_observer_t * observer); + +/** + * Remove all observers from their subject related to an object + * @param observer pointer to an observer + * @param obj pointer to an object + */ +void lv_subject_remove_all_obj(lv_subject_t * subject, lv_obj_t * obj); + +/** + * Get the target of an observer + * @param observer pointer to an observer + * @return pointer to the saved target + */ +void * lv_observer_get_target(lv_observer_t * observer); + +/** + * Get the target object of the observer. + * It's the same as `lv_observer_get_target` and added only + * for semantic reasons + * @param observer pointer to an observer + * @return pointer to the saved object target + */ +static inline lv_obj_t * lv_observer_get_target_obj(lv_observer_t * observer) +{ + return (lv_obj_t *)lv_observer_get_target(observer); +} + +/** + * Notify all observers of subject + * @param subject pointer to a subject + */ +void lv_subject_notify(lv_subject_t * subject); + +/** + * Set an object flag if an integer subject's value is equal to a reference value, clear the flag otherwise + * @param obj pointer to an object + * @param subject pointer to a subject + * @param flag a flag to set or clear (e.g. `LV_OBJ_FLAG_HIDDEN`) + * @param ref_value a reference value to compare the subject's value with + * @return pointer to the created observer + */ +lv_observer_t * lv_obj_bind_flag_if_eq(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag, int32_t ref_value); + +/** + * Set an object flag if an integer subject's value is not equal to a reference value, clear the flag otherwise + * @param obj pointer to an object + * @param subject pointer to a subject + * @param flag a flag to set or clear (e.g. `LV_OBJ_FLAG_HIDDEN`) + * @param ref_value a reference value to compare the subject's value with + * @return pointer to the created observer + */ +lv_observer_t * lv_obj_bind_flag_if_not_eq(lv_obj_t * obj, lv_subject_t * subject, lv_obj_flag_t flag, + int32_t ref_value); + +/** + * Set an object state if an integer subject's value is equal to a reference value, clear the flag otherwise + * @param obj pointer to an object + * @param subject pointer to a subject + * @param flag a state to set or clear (e.g. `LV_STATE_CHECKED`) + * @param ref_value a reference value to compare the subject's value with + * @return pointer to the created observer + */ +lv_observer_t * lv_obj_bind_state_if_eq(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state, int32_t ref_value); + +/** + * Set an object state if an integer subject's value is not equal to a reference value, clear the flag otherwise + * @param obj pointer to an object + * @param subject pointer to a subject + * @param flag a state to set or clear (e.g. `LV_STATE_CHECKED`) + * @param ref_value a reference value to compare the subject's value with + * @return pointer to the created observer + */ +lv_observer_t * lv_obj_bind_state_if_not_eq(lv_obj_t * obj, lv_subject_t * subject, lv_state_t state, + int32_t ref_value); + +#if LV_USE_BUTTON +/** + * Set an integer subject to 1 when a button is checked and set it 0 when unchecked. + * @param obj pointer to a button + * @param subject pointer to a subject + * @return pointer to the created observer + */ +lv_observer_t * lv_button_bind_checked(lv_obj_t * obj, lv_subject_t * subject); +#endif + +#if LV_USE_LABEL +/** + * Bind an integer, string, or pointer subject to a label. + * @param obj pointer to a label + * @param subject pointer to a subject + * @param fmt an optional format string with 1 format specifier (e.g. "%d °C") + * or NULL to bind the value directly. + * @return pointer to the created observer + * @note fmt == NULL can be used only with string and pointer subjects. + * @note if the subject is a pointer must point to a `\0` terminated string. + */ +lv_observer_t * lv_label_bind_text(lv_obj_t * obj, lv_subject_t * subject, const char * fmt); +#endif + +#if LV_USE_ARC +/** + * Bind an integer subject to an arc's value + * @param obj pointer to an arc + * @param subject pointer to a subject + * @return pointer to the created observer + */ +lv_observer_t * lv_arc_bind_value(lv_obj_t * obj, lv_subject_t * subject); +#endif + +#if LV_USE_SLIDER +/** + * Bind an integer subject to a slider's value + * @param obj pointer to a slider + * @param subject pointer to a subject + * @return pointer to the created observer + */ +lv_observer_t * lv_slider_bind_value(lv_obj_t * obj, lv_subject_t * subject); +#endif + +#if LV_USE_ROLLER +/** + * Bind an integer subject to a roller's value + * @param obj pointer to a roller + * @param subject pointer to a subject + * @return pointer to the created observer + */ +lv_observer_t * lv_roller_bind_value(lv_obj_t * obj, lv_subject_t * subject); +#endif + +#if LV_USE_DROPDOWN +/** + * Bind an integer subject to a dropdown's value + * @param obj pointer to a drop down + * @param subject pointer to a subject + * @return pointer to the created observer + */ +lv_observer_t * lv_dropdown_bind_value(lv_obj_t * obj, lv_subject_t * subject); +#endif + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_OBSERVER*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_OBSERVER_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/others/snapshot/lv_snapshot.c b/lib/libesp32_lvgl/lvgl/src/others/snapshot/lv_snapshot.c new file mode 100644 index 000000000..0238448e8 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/others/snapshot/lv_snapshot.c @@ -0,0 +1,177 @@ +/** + * @file lv_snapshot.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_snapshot.h" +#if LV_USE_SNAPSHOT + +#include +#include "../../display/lv_display.h" +#include "../../core/lv_refr.h" +#include "../../display/lv_display_private.h" +#include "../../stdlib/lv_string.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +uint32_t lv_snapshot_buf_size_needed(lv_obj_t * obj, lv_color_format_t cf) +{ + LV_ASSERT_NULL(obj); + switch(cf) { + case LV_COLOR_FORMAT_RGB565: + case LV_COLOR_FORMAT_RGB888: + case LV_COLOR_FORMAT_XRGB8888: + case LV_COLOR_FORMAT_ARGB8888: + break; + default: + LV_LOG_WARN("Not supported color format"); + return 0; + } + + lv_obj_update_layout(obj); + + /*Width and height determine snapshot image size.*/ + int32_t w = lv_obj_get_width(obj); + int32_t h = lv_obj_get_height(obj); + int32_t ext_size = _lv_obj_get_ext_draw_size(obj); + w += ext_size * 2; + h += ext_size * 2; + + return lv_draw_buf_width_to_stride(w, cf) * h; +} + +lv_result_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_color_format_t cf, lv_image_dsc_t * dsc, void * buf, + uint32_t buf_size) +{ + LV_ASSERT_NULL(obj); + LV_ASSERT_NULL(dsc); + LV_ASSERT_NULL(buf); + + switch(cf) { + case LV_COLOR_FORMAT_RGB565: + case LV_COLOR_FORMAT_RGB888: + case LV_COLOR_FORMAT_XRGB8888: + case LV_COLOR_FORMAT_ARGB8888: + break; + default: + LV_LOG_WARN("Not supported color format"); + return LV_RESULT_INVALID; + } + + uint32_t buf_size_needed = lv_snapshot_buf_size_needed(obj, cf); + if(buf_size_needed == 0 || buf_size < buf_size_needed) return LV_RESULT_INVALID; + + LV_ASSERT_MSG(buf == lv_draw_buf_align(buf, cf), "Buffer is not aligned"); + + /*Width and height determine snapshot image size.*/ + int32_t w = lv_obj_get_width(obj); + int32_t h = lv_obj_get_height(obj); + int32_t ext_size = _lv_obj_get_ext_draw_size(obj); + w += ext_size * 2; + h += ext_size * 2; + + lv_area_t snapshot_area; + lv_obj_get_coords(obj, &snapshot_area); + lv_area_increase(&snapshot_area, ext_size, ext_size); + + lv_memzero(buf, buf_size); + dsc->data = buf; + dsc->data_size = buf_size_needed; + /*Keep header flags unchanged, because we don't know if it's allocated or not.*/ + dsc->header.w = w; + dsc->header.h = h; + dsc->header.cf = cf; + dsc->header.magic = LV_IMAGE_HEADER_MAGIC; + + lv_layer_t layer; + lv_memzero(&layer, sizeof(layer)); + + lv_draw_buf_t draw_buf; + lv_draw_buf_from_image(&draw_buf, dsc); + + layer.draw_buf = &draw_buf; + layer.buf_area.x1 = snapshot_area.x1; + layer.buf_area.y1 = snapshot_area.y1; + layer.buf_area.x2 = snapshot_area.x1 + w - 1; + layer.buf_area.y2 = snapshot_area.y1 + h - 1; + layer.color_format = cf; + layer._clip_area = snapshot_area; + + lv_display_t * disp_old = _lv_refr_get_disp_refreshing(); + lv_display_t * disp_new = lv_obj_get_display(obj); + lv_layer_t * layer_old = disp_new->layer_head; + disp_new->layer_head = &layer; + + _lv_refr_set_disp_refreshing(disp_new); + lv_obj_redraw(&layer, obj); + + while(layer.draw_task_head) { + lv_draw_dispatch_wait_for_request(); + lv_draw_dispatch_layer(NULL, &layer); + } + + disp_new->layer_head = layer_old; + _lv_refr_set_disp_refreshing(disp_old); + + return LV_RESULT_OK; +} + +lv_image_dsc_t * lv_snapshot_take(lv_obj_t * obj, lv_color_format_t cf) +{ + LV_ASSERT_NULL(obj); + int32_t w = lv_obj_get_width(obj); + int32_t h = lv_obj_get_height(obj); + int32_t ext_size = _lv_obj_get_ext_draw_size(obj); + w += ext_size * 2; + h += ext_size * 2; + if(w == 0 || h == 0) return NULL; + + lv_draw_buf_t * draw_buf = lv_draw_buf_create(w, h, cf, LV_STRIDE_AUTO); + if(draw_buf == NULL) return NULL; + + if(lv_snapshot_take_to_buf(obj, cf, (lv_image_dsc_t *)draw_buf, draw_buf->data, draw_buf->data_size) != LV_RESULT_OK) { + lv_draw_buf_destroy(draw_buf); + return NULL; + } + + return (lv_image_dsc_t *)draw_buf; +} + +void lv_snapshot_free(lv_image_dsc_t * dsc) +{ + if(!dsc) + return; + + lv_draw_buf_destroy((lv_draw_buf_t *)dsc); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_SNAPSHOT*/ diff --git a/lib/libesp32_lvgl/lvgl/src/others/snapshot/lv_snapshot.h b/lib/libesp32_lvgl/lvgl/src/others/snapshot/lv_snapshot.h new file mode 100644 index 000000000..d1823501a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/others/snapshot/lv_snapshot.h @@ -0,0 +1,78 @@ +/** + * @file lv_snapshot.h + * + */ + +#ifndef LV_SNAPSHOT_H +#define LV_SNAPSHOT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include + +#include "../../core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +#if LV_USE_SNAPSHOT +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Take snapshot for object with its children, alloc the memory needed. + * @param obj the object to generate snapshot. + * @param cf color format for generated image. + * @return a pointer to an image descriptor, or NULL if failed. + */ +lv_image_dsc_t * lv_snapshot_take(lv_obj_t * obj, lv_color_format_t cf); + +/** + * Free the snapshot image returned by @ref lv_snapshot_take + * It will firstly free the data image takes, then the image descriptor. + * @param dsc the image descriptor generated by lv_snapshot_take. + */ +void lv_snapshot_free(lv_image_dsc_t * dsc); + +/** + * Get the buffer needed for object snapshot image. + * @param obj the object to generate snapshot. + * @param cf color format for generated image. + * @return the buffer size needed in bytes + */ +uint32_t lv_snapshot_buf_size_needed(lv_obj_t * obj, lv_color_format_t cf); + +/** + * Take snapshot for object with its children, save image info to provided buffer. + * @param obj the object to generate snapshot. + * @param cf color format for generated image. + * @param dsc image descriptor to store the image result. + * @param buf the buffer to store image data. It must meet align requirement. + * @param buf_size provided buffer size in bytes. + * @return LV_RESULT_OK on success, LV_RESULT_INVALID on error. + */ +lv_result_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_color_format_t cf, lv_image_dsc_t * dsc, void * buf, + uint32_t buf_size); + +/********************** + * MACROS + **********************/ +#endif /*LV_USE_SNAPSHOT*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/others/sysmon/lv_sysmon.c b/lib/libesp32_lvgl/lvgl/src/others/sysmon/lv_sysmon.c new file mode 100644 index 000000000..50bb83d66 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/others/sysmon/lv_sysmon.c @@ -0,0 +1,260 @@ +/** + * @file lv_sysmon.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_sysmon.h" + +#if LV_USE_SYSMON + +#include "../../core/lv_global.h" +#include "../../misc/lv_async.h" +#include "../../stdlib/lv_string.h" +#include "../../widgets/label/lv_label.h" + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_sysmon_class + +#define SYSMON_REFR_PERIOD_DEF 300 /* ms */ + +#if defined(LV_USE_PERF_MONITOR) && LV_USE_PERF_MONITOR + #define sysmon_perf LV_GLOBAL_DEFAULT()->sysmon_perf + #define _USE_PERF_MONITOR 1 +#else + #define _USE_PERF_MONITOR 0 +#endif + +#if defined(LV_USE_MEM_MONITOR) && LV_USE_MEM_MONITOR + #define sysmon_mem LV_GLOBAL_DEFAULT()->sysmon_mem + #define _USE_MEM_MONITOR 1 +#else + #define _USE_MEM_MONITOR 0 +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void sysmon_backend_init_async_cb(void * user_data); + +#if _USE_PERF_MONITOR + static void perf_update_timer_cb(lv_timer_t * t); + static void perf_observer_cb(lv_observer_t * observer, lv_subject_t * subject); +#endif + +#if _USE_MEM_MONITOR + static void mem_update_timer_cb(lv_timer_t * t); + static void mem_observer_cb(lv_observer_t * observer, lv_subject_t * subject); +#endif + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void _lv_sysmon_builtin_init(void) +{ +#if _USE_PERF_MONITOR + static lv_sysmon_perf_info_t perf_info; + lv_subject_init_pointer(&sysmon_perf.subject, &perf_info); + sysmon_perf.timer = lv_timer_create(perf_update_timer_cb, SYSMON_REFR_PERIOD_DEF, &perf_info); +#endif + +#if _USE_MEM_MONITOR + static lv_mem_monitor_t mem_info; + lv_subject_init_pointer(&sysmon_mem.subject, &mem_info); + sysmon_mem.timer = lv_timer_create(mem_update_timer_cb, SYSMON_REFR_PERIOD_DEF, &mem_info); +#endif + + lv_async_call(sysmon_backend_init_async_cb, NULL); +} + +void _lv_sysmon_builtin_deinit(void) +{ + lv_async_call_cancel(sysmon_backend_init_async_cb, NULL); +#if _USE_PERF_MONITOR + lv_timer_delete(sysmon_perf.timer); +#endif +} + +lv_obj_t * lv_sysmon_create(lv_obj_t * parent) +{ + LV_LOG_INFO("begin"); + lv_obj_t * label = lv_label_create(parent); + lv_obj_set_style_bg_opa(label, LV_OPA_50, 0); + lv_obj_set_style_bg_color(label, lv_color_black(), 0); + lv_obj_set_style_text_color(label, lv_color_white(), 0); + lv_obj_set_style_pad_all(label, 3, 0); + lv_label_set_text(label, "?"); + return label; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#if _USE_PERF_MONITOR + +static void perf_monitor_disp_event_cb(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_sysmon_perf_info_t * info = (lv_sysmon_perf_info_t *)lv_subject_get_pointer(&sysmon_perf.subject); + + switch(code) { + case LV_EVENT_REFR_START: + info->measured.refr_interval_sum += lv_tick_elaps(info->measured.refr_start); + info->measured.refr_start = lv_tick_get(); + break; + case LV_EVENT_REFR_READY: + info->measured.refr_elaps_sum += lv_tick_elaps(info->measured.refr_start); + info->measured.refr_cnt++; + break; + case LV_EVENT_RENDER_START: + info->measured.render_start = lv_tick_get(); + break; + case LV_EVENT_RENDER_READY: + info->measured.render_elaps_sum += lv_tick_elaps(info->measured.render_start); + info->measured.render_cnt++; + break; + case LV_EVENT_FLUSH_START: + info->measured.flush_start = lv_tick_get(); + break; + case LV_EVENT_FLUSH_FINISH: + info->measured.flush_elaps_sum += lv_tick_elaps(info->measured.flush_start); + info->measured.flush_cnt++; + break; + default: + break; + } +} +uint32_t lv_os_get_idle_percent(void); + +static void perf_update_timer_cb(lv_timer_t * t) +{ + uint32_t LV_SYSMON_GET_IDLE(void); + + lv_sysmon_perf_info_t * info = lv_timer_get_user_data(t); + info->calculated.run_cnt++; + + info->calculated.fps = info->measured.refr_interval_sum ? (1000 * info->measured.refr_cnt / + info->measured.refr_interval_sum) : 0; + info->calculated.cpu = 100 - LV_SYSMON_GET_IDLE(); + info->calculated.refr_avg_time = info->measured.refr_cnt ? (info->measured.refr_elaps_sum / info->measured.refr_cnt) : + 0; + info->calculated.flush_avg_time = info->measured.flush_cnt ? (info->measured.flush_elaps_sum / info->measured.flush_cnt) + : 0; + /*Flush time was measured in rendering time so subtract it*/ + info->calculated.render_avg_time = info->measured.render_cnt ? ((info->measured.render_elaps_sum - + info->measured.flush_elaps_sum) / + info->measured.render_cnt) : 0; + + info->calculated.cpu_avg_total = ((info->calculated.cpu_avg_total * (info->calculated.run_cnt - 1)) + + info->calculated.cpu) / info->calculated.run_cnt; + info->calculated.fps_avg_total = ((info->calculated.fps_avg_total * (info->calculated.run_cnt - 1)) + + info->calculated.fps) / info->calculated.run_cnt; + + lv_subject_set_pointer(&sysmon_perf.subject, info); + + lv_sysmon_perf_info_t prev_info = *info; + lv_memzero(info, sizeof(lv_sysmon_perf_info_t)); + info->measured.refr_start = prev_info.measured.refr_start; + info->calculated.cpu_avg_total = prev_info.calculated.cpu_avg_total; + info->calculated.fps_avg_total = prev_info.calculated.fps_avg_total; + info->calculated.run_cnt = prev_info.calculated.run_cnt; +} + +static void perf_observer_cb(lv_observer_t * observer, lv_subject_t * subject) +{ + lv_obj_t * label = lv_observer_get_target(observer); + const lv_sysmon_perf_info_t * perf = lv_subject_get_pointer(subject); + +#if LV_USE_PERF_MONITOR_LOG_MODE + LV_UNUSED(label); + LV_LOG("sysmon: " + "%" LV_PRIu32 " FPS (refr_cnt: %" LV_PRIu32 " | redraw_cnt: %" LV_PRIu32 " | flush_cnt: %" LV_PRIu32 "), " + "refr %" LV_PRIu32 "ms (render %" LV_PRIu32 "ms | flush %" LV_PRIu32 "ms), " + "CPU %" LV_PRIu32 "%%\n", + perf->calculated.fps, perf->measured.refr_cnt, perf->measured.render_cnt, perf->measured.flush_cnt, + perf->calculated.refr_avg_time, perf->calculated.render_real_avg_time, perf->calculated.flush_avg_time, + perf->calculated.cpu); +#else + lv_label_set_text_fmt( + label, + "%" LV_PRIu32" FPS, %" LV_PRIu32 "%% CPU\n" + "%" LV_PRIu32" ms (%" LV_PRIu32" | %" LV_PRIu32")", + perf->calculated.fps, perf->calculated.cpu, + perf->calculated.render_avg_time + perf->calculated.flush_avg_time, + perf->calculated.render_avg_time, perf->calculated.flush_avg_time + ); +#endif /*LV_USE_PERF_MONITOR_LOG_MODE*/ +} + +#endif + +#if _USE_MEM_MONITOR + +static void mem_update_timer_cb(lv_timer_t * t) +{ + lv_mem_monitor_t * mem_mon = lv_timer_get_user_data(t); + lv_mem_monitor(mem_mon); + lv_subject_set_pointer(&sysmon_mem.subject, mem_mon); +} + +static void mem_observer_cb(lv_observer_t * observer, lv_subject_t * subject) +{ + lv_obj_t * label = lv_observer_get_target(observer); + const lv_mem_monitor_t * mon = lv_subject_get_pointer(subject); + + uint32_t used_size = mon->total_size - mon->free_size;; + uint32_t used_kb = used_size / 1024; + uint32_t used_kb_tenth = (used_size - (used_kb * 1024)) / 102; + lv_label_set_text_fmt(label, + "%"LV_PRIu32 ".%"LV_PRIu32 " kB, %d%%\n" + "%d%% frag.", + used_kb, used_kb_tenth, mon->used_pct, + mon->frag_pct); +} + +#endif + +static void sysmon_backend_init_async_cb(void * user_data) +{ + LV_UNUSED(user_data); + +#if _USE_PERF_MONITOR + lv_display_add_event_cb(lv_display_get_default(), perf_monitor_disp_event_cb, LV_EVENT_ALL, NULL); + + lv_obj_t * obj1 = lv_sysmon_create(lv_layer_sys()); + lv_obj_align(obj1, LV_USE_PERF_MONITOR_POS, 0, 0); + lv_subject_add_observer_obj(&sysmon_perf.subject, perf_observer_cb, obj1, NULL); +#if LV_USE_PERF_MONITOR_LOG_MODE + lv_obj_add_flag(obj1, LV_OBJ_FLAG_HIDDEN); +#endif + +#endif + +#if _USE_MEM_MONITOR + lv_obj_t * obj2 = lv_sysmon_create(lv_layer_sys()); + lv_obj_align(obj2, LV_USE_MEM_MONITOR_POS, 0, 0); + lv_subject_add_observer_obj(&sysmon_mem.subject, mem_observer_cb, obj2, NULL); +#endif +} + +#endif /*LV_USE_SYSMON*/ diff --git a/lib/libesp32_lvgl/lvgl/src/others/sysmon/lv_sysmon.h b/lib/libesp32_lvgl/lvgl/src/others/sysmon/lv_sysmon.h new file mode 100644 index 000000000..132a132d6 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/others/sysmon/lv_sysmon.h @@ -0,0 +1,110 @@ +/** + * @file lv_sysmon.h + * + */ + +#ifndef LV_SYSMON_H +#define LV_SYSMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../misc/lv_timer.h" +#include "../../others/observer/lv_observer.h" + +#if LV_USE_SYSMON + +#if LV_USE_LABEL == 0 +#error "lv_sysmon: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) " +#endif + +#if LV_USE_OBSERVER == 0 +#error "lv_observer: lv_observer is required. Enable it in lv_conf.h (LV_USE_OBSERVER 1) " +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_subject_t subject; + lv_timer_t * timer; +} lv_sysmon_backend_data_t; + +#if LV_USE_PERF_MONITOR +typedef struct { + struct { + uint32_t refr_start; + uint32_t refr_interval_sum; + uint32_t refr_elaps_sum; + uint32_t refr_cnt; + uint32_t render_start; + uint32_t render_elaps_sum; /*Contains the flush time too*/ + uint32_t render_cnt; + uint32_t flush_start; + uint32_t flush_elaps_sum; + uint32_t flush_cnt; + } measured; + + struct { + uint32_t fps; + uint32_t cpu; + uint32_t refr_avg_time; + uint32_t render_avg_time; /**< Pure rendering time without flush time*/ + uint32_t flush_avg_time; /**< Pure flushing time without rendering time*/ + uint32_t cpu_avg_total; + uint32_t fps_avg_total; + uint32_t run_cnt; + } calculated; + +} lv_sysmon_perf_info_t; +#endif + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a system monitor object. + * @param parent pointer to an object, it will be the parent of the new system monitor + * @return pointer to the new system monitor object + */ +lv_obj_t * lv_sysmon_create(lv_obj_t * parent); + +/** + * Set the refresh period of the system monitor object + * @param obj pointer to a system monitor object + * @param period the refresh period in milliseconds + */ +void lv_sysmon_set_refr_period(lv_obj_t * obj, uint32_t period); + +/** + * Initialize built-in system monitor, such as performance and memory monitor. + */ +void _lv_sysmon_builtin_init(void); + +/** + * DeInitialize built-in system monitor, such as performance and memory monitor. + */ +void _lv_sysmon_builtin_deinit(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_SYSMON*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_SYSMON_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/others/vg_lite_tvg/vg_lite.h b/lib/libesp32_lvgl/lvgl/src/others/vg_lite_tvg/vg_lite.h new file mode 100644 index 000000000..f7a613700 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/others/vg_lite_tvg/vg_lite.h @@ -0,0 +1,1379 @@ +/**************************************************************************** +* +* Copyright 2012 - 2023 Vivante Corporation, Santa Clara, California. +* All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* 'Software'), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sub license, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject +* to the following conditions: +* +* The above copyright notice and this permission notice (including the +* next paragraph) shall be included in all copies or substantial +* portions of the Software. +* +* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +* +*****************************************************************************/ + +#ifndef _vg_lite_h_ +#define _vg_lite_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_MSC_VER) +#define inline __inline +#endif + +#include +#include + + +/* VGLite API Constants *******************************************************************************************************************/ + +#define VGLITE_HEADER_VERSION 7 + +#ifndef VGLITE_VERSION_3_0 +#define VGLITE_VERSION_3_0 1 + +#define VGLITE_MAKE_VERSION(major, minor, patch) (((major) << 16) | ((minor) << 8) | (patch)) +#define VGLITE_VERSION_MAJOR(version) (((uint32_t)(version) >> 16) & 0xff) +#define VGLITE_VERSION_MINOR(version) (((uint32_t)(version) >> 8) & 0xff) +#define VGLITE_VERSION_PATCH(version) ((uint32_t)(version) & 0xff) + +#define VGLITE_API_VERSION_3_0 VGLITE_MAKE_VERSION(3, 0, 0) + +#define VGLITE_RELEASE_VERSION VGLITE_MAKE_VERSION(4,0,47) + +#define VGL_FALSE 0 +#define VGL_TRUE 1 + +/* Path command (op code). */ +#define VLC_OP_END 0x00 +#define VLC_OP_CLOSE 0x01 +#define VLC_OP_MOVE 0x02 +#define VLC_OP_MOVE_REL 0x03 +#define VLC_OP_LINE 0x04 +#define VLC_OP_LINE_REL 0x05 +#define VLC_OP_QUAD 0x06 +#define VLC_OP_QUAD_REL 0x07 +#define VLC_OP_CUBIC 0x08 +#define VLC_OP_CUBIC_REL 0x09 +#define VLC_OP_BREAK 0x0A +#define VLC_OP_HLINE 0x0B +#define VLC_OP_HLINE_REL 0x0C +#define VLC_OP_VLINE 0x0D +#define VLC_OP_VLINE_REL 0x0E +#define VLC_OP_SQUAD 0x0F +#define VLC_OP_SQUAD_REL 0x10 +#define VLC_OP_SCUBIC 0x11 +#define VLC_OP_SCUBIC_REL 0x12 +#define VLC_OP_SCCWARC 0x13 +#define VLC_OP_SCCWARC_REL 0x14 +#define VLC_OP_SCWARC 0x15 +#define VLC_OP_SCWARC_REL 0x16 +#define VLC_OP_LCCWARC 0x17 +#define VLC_OP_LCCWARC_REL 0x18 +#define VLC_OP_LCWARC 0x19 +#define VLC_OP_LCWARC_REL 0x1A + +/* Macros for path manipulating: See path definitions. */ +#define VLM_PATH_ENABLE_UPLOAD(path) (path).uploaded.property |= 1 +#define VLM_PATH_DISABLE_UPLOAD(path) (path).uploaded.property &= (~1) +#define VLM_PATH_GET_UPLOAD_BIT(path) ((path).uploaded.property & 1) + +/* Gradient constants. */ +#define VLC_MAX_COLOR_RAMP_STOPS 256 /*! The max number of radial gradient stops. */ +#define VLC_MAX_GRADIENT_STOPS 16 /*! The max number of gradient stops. */ +#define VLC_GRADIENT_BUFFER_WIDTH 1024 /*! The internal gradient buffer width.*/ + + +/* API name defines for backward compatibility to VGLite 2.0 APIs */ +#define vg_lite_buffer_upload vg_lite_upload_buffer +#define vg_lite_path_append vg_lite_append_path +#define vg_lite_path_calc_length vg_lite_get_path_length +#define vg_lite_set_ts_buffer vg_lite_set_tess_buffer +#define vg_lite_set_draw_path_type vg_lite_set_path_type +#define vg_lite_create_mask_layer vg_lite_create_masklayer +#define vg_lite_fill_mask_layer vg_lite_fill_masklayer +#define vg_lite_blend_mask_layer vg_lite_blend_masklayer +#define vg_lite_generate_mask_layer_by_path vg_lite_render_masklayer +#define vg_lite_set_mask_layer vg_lite_set_masklayer +#define vg_lite_destroy_mask_layer vg_lite_destroy_masklayer +#define vg_lite_enable_mask vg_lite_enable_masklayer +#define vg_lite_enable_color_transformation vg_lite_enable_color_transform +#define vg_lite_set_color_transformation vg_lite_set_color_transform +#define vg_lite_set_image_global_alpha vg_lite_source_global_alpha +#define vg_lite_set_dest_global_alpha vg_lite_dest_global_alpha +#define vg_lite_clear_rad_grad vg_lite_clear_radial_grad +#define vg_lite_update_rad_grad vg_lite_update_radial_grad +#define vg_lite_get_rad_grad_matrix vg_lite_get_radial_grad_matrix +#define vg_lite_set_rad_grad vg_lite_set_radial_grad +#define vg_lite_draw_linear_gradient vg_lite_draw_linear_grad +#define vg_lite_draw_radial_gradient vg_lite_draw_radial_grad +#define vg_lite_draw_gradient vg_lite_draw_grad +#define vg_lite_mem_avail vg_lite_get_mem_size +#define vg_lite_set_update_stroke vg_lite_update_stroke + +#define vg_lite_buffer_image_mode_t vg_lite_image_mode_t +#define vg_lite_draw_path_type_t vg_lite_path_type_t +#define vg_lite_linear_gradient_ext_t vg_lite_ext_linear_gradient_t +#define vg_lite_buffer_transparency_mode_t vg_lite_transparency_t + + +/* VGLite API Types ***********************************************************************************************************************/ + +typedef unsigned char vg_lite_uint8_t; +typedef char vg_lite_int8_t; +typedef short vg_lite_int16_t; +typedef unsigned short vg_lite_uint16_t; +typedef int vg_lite_int32_t; +typedef unsigned int vg_lite_uint32_t; +typedef unsigned long long vg_lite_uint64_t; +typedef float vg_lite_float_t; +typedef double vg_lite_double_t; +typedef char vg_lite_char; +typedef char* vg_lite_string; +typedef void* vg_lite_pointer; +typedef void vg_lite_void; +typedef unsigned int vg_lite_color_t; + + +/* VGLite API Enumerations ****************************************************************************************************************/ + +#ifndef VG_LITE_ERROR +#define VG_LITE_ERROR 1 + + /* Error codes that the vg_lite functions can return. */ + typedef enum vg_lite_error + { + VG_LITE_SUCCESS = 0, /*! Success. */ + VG_LITE_INVALID_ARGUMENT, /*! An invalid argument was specified. */ + VG_LITE_OUT_OF_MEMORY, /*! Out of memory. */ + VG_LITE_NO_CONTEXT, /*! No context or an unintialized context specified. */ + VG_LITE_TIMEOUT, /*! A timeout has occurred during a wait. */ + VG_LITE_OUT_OF_RESOURCES, /*! Out of system resources. */ + VG_LITE_GENERIC_IO, /*! Cannot communicate with the kernel driver. */ + VG_LITE_NOT_SUPPORT, /*! Function call not supported. */ + VG_LITE_ALREADY_EXISTS, /*! Object already exists */ + VG_LITE_NOT_ALIGNED, /*! Data alignment error */ + VG_LITE_FLEXA_TIME_OUT, /*! VG timeout requesting for segment buffer */ + VG_LITE_FLEXA_HANDSHAKE_FAIL, /*! VG and SBI synchronizer handshake failed */ + } vg_lite_error_t; +#endif + + /* Chip features bit */ + typedef enum vg_lite_feature + { + gcFEATURE_BIT_VG_IM_INDEX_FORMAT, + gcFEATURE_BIT_VG_SCISSOR, + gcFEATURE_BIT_VG_BORDER_CULLING, + gcFEATURE_BIT_VG_RGBA2_FORMAT, + gcFEATURE_BIT_VG_QUALITY_8X, + gcFEATURE_BIT_VG_IM_FASTCLAER, + gcFEATURE_BIT_VG_RADIAL_GRADIENT, + gcFEATURE_BIT_VG_GLOBAL_ALPHA, + gcFEATURE_BIT_VG_RGBA8_ETC2_EAC, + gcFEATURE_BIT_VG_COLOR_KEY, + gcFEATURE_BIT_VG_DOUBLE_IMAGE, + gcFEATURE_BIT_VG_YUV_OUTPUT, + gcFEATURE_BIT_VG_FLEXA, + gcFEATURE_BIT_VG_24BIT, + gcFEATURE_BIT_VG_DITHER, + gcFEATURE_BIT_VG_USE_DST, + gcFEATURE_BIT_VG_PE_CLEAR, + gcFEATURE_BIT_VG_IM_INPUT, + gcFEATURE_BIT_VG_DEC_COMPRESS, + gcFEATURE_BIT_VG_LINEAR_GRADIENT_EXT, + gcFEATURE_BIT_VG_MASK, + gcFEATURE_BIT_VG_MIRROR, + gcFEATURE_BIT_VG_GAMMA, + gcFEATURE_BIT_VG_NEW_BLEND_MODE, + gcFEATURE_BIT_VG_STENCIL, + gcFEATURE_BIT_VG_SRC_PREMULTIPLIED, /*! Valid only if gcFEATURE_BIT_VG_HW_PREMULTIPLY is 0 */ + gcFEATURE_BIT_VG_HW_PREMULTIPLY, /*! HW multiplier can accept either premultiplied or not */ + gcFEATURE_BIT_VG_COLOR_TRANSFORMATION, + gcFEATURE_BIT_VG_LVGL_SUPPORT, + gcFEATURE_BIT_VG_INDEX_ENDIAN, + gcFEATURE_BIT_VG_24BIT_PLANAR, + gcFEATURE_BIT_VG_PIXEL_MATRIX, + gcFEATURE_BIT_VG_NEW_IMAGE_INDEX, + gcFEATURE_BIT_VG_PARALLEL_PATHS, + gcFEATURE_BIT_VG_STRIPE_MODE, + gcFEATURE_BIT_VG_IM_DEC_INPUT, + gcFEATURE_BIT_VG_GAUSSIAN_BLUR, + gcFEATURE_BIT_VG_RECTANGLE_TILED_OUT, + gcFEATURE_BIT_VG_TESSELLATION_TILED_OUT, + gcFEATURE_BIT_VG_IM_REPEAT_REFLECT, + gcFEATURE_BIT_VG_YUY2_INPUT, + gcFEATURE_BIT_VG_YUV_INPUT, + gcFEATURE_BIT_VG_YUV_TILED_INPUT, + gcFEATURE_BIT_VG_AYUV_INPUT, + gcFEATURE_BIT_VG_16PIXELS_ALIGN, + gcFEATURE_BIT_VG_DEC_COMPRESS_2_0, + gcFEATURE_COUNT + } vg_lite_feature_t; + + /* Rendering quality enums. */ + typedef enum vg_lite_quality + { + VG_LITE_HIGH, /*! High quality 16x anti-aliasing path. */ + VG_LITE_UPPER, /*! Upper quality 8x anti-aliasing path. */ + VG_LITE_MEDIUM, /*! Medium quality 4x anti-aliasing path. */ + VG_LITE_LOW, /*! Low quality path without any anti-aliasing. */ + } vg_lite_quality_t; + + /* Format of path coordinates. */ + typedef enum vg_lite_format + { + VG_LITE_S8, /*! Signed 8-bit coordinates. */ + VG_LITE_S16, /*! Signed 16-bit coordinates. */ + VG_LITE_S32, /*! Signed 32-bit coordinates. */ + VG_LITE_FP32, /*! 32-bit floating point coordinates. */ + } vg_lite_format_t; + + /* Format of pixel buffer. */ + typedef enum vg_lite_buffer_format + { + /* OpenVG VGImageFormat enums: + * Note: The bits for each color channel are stored within a machine word + * from MSB to LSB in the order indicated by the pixel format name. + * This is opposite of VG_LITE_* formats (from LSB to MSB). + */ + + /* RGB{A,X} channel ordering */ + VG_sRGBX_8888 = 0, + VG_sRGBA_8888 = 1, + VG_sRGBA_8888_PRE = 2, + VG_sRGB_565 = 3, + VG_sRGBA_5551 = 4, + VG_sRGBA_4444 = 5, + VG_sL_8 = 6, + VG_lRGBX_8888 = 7, + VG_lRGBA_8888 = 8, + VG_lRGBA_8888_PRE = 9, + VG_lL_8 = 10, + VG_A_8 = 11, + VG_BW_1 = 12, + VG_A_1 = 13, + VG_A_4 = 14, + + VG_sRGBX_8888_PRE = 15, + VG_sRGB_565_PRE = 16, + VG_sRGBA_5551_PRE = 17, + VG_sRGBA_4444_PRE = 18, + VG_lRGBX_8888_PRE = 19, + VG_lRGB_565 = 20, + VG_lRGB_565_PRE = 21, + VG_lRGBA_5551 = 22, + VG_lRGBA_5551_PRE = 23, + VG_lRGBA_4444 = 24, + VG_lRGBA_4444_PRE = 25, + + /* {A,X}RGB channel ordering */ + VG_sXRGB_8888 = 0 | (1 << 6), + VG_sARGB_8888 = 1 | (1 << 6), + VG_sARGB_8888_PRE = 2 | (1 << 6), + VG_sARGB_1555 = 4 | (1 << 6), + VG_sARGB_4444 = 5 | (1 << 6), + VG_lXRGB_8888 = 7 | (1 << 6), + VG_lARGB_8888 = 8 | (1 << 6), + VG_lARGB_8888_PRE = 9 | (1 << 6), + + /* BGR{A,X} channel ordering */ + VG_sBGRX_8888 = 0 | (1 << 7), + VG_sBGRA_8888 = 1 | (1 << 7), + VG_sBGRA_8888_PRE = 2 | (1 << 7), + VG_sBGR_565 = 3 | (1 << 7), + VG_sBGRA_5551 = 4 | (1 << 7), + VG_sBGRA_4444 = 5 | (1 << 7), + VG_lBGRX_8888 = 7 | (1 << 7), + VG_lBGRA_8888 = 8 | (1 << 7), + VG_lBGRA_8888_PRE = 9 | (1 << 7), + + /* {A,X}BGR channel ordering */ + VG_sXBGR_8888 = 0 | (1 << 6) | (1 << 7), + VG_sABGR_8888 = 1 | (1 << 6) | (1 << 7), + VG_sABGR_8888_PRE = 2 | (1 << 6) | (1 << 7), + VG_sABGR_1555 = 4 | (1 << 6) | (1 << 7), + VG_sABGR_4444 = 5 | (1 << 6) | (1 << 7), + VG_lXBGR_8888 = 7 | (1 << 6) | (1 << 7), + VG_lABGR_8888 = 8 | (1 << 6) | (1 << 7), + VG_lABGR_8888_PRE = 9 | (1 << 6) | (1 << 7), + + /* Original VGLite API image format enums: + * Note: The bits for each color channel are stored within a machine word + * from LSB to MSB in the order indicated by the pixel format name. + * This is opposite of OPENVG VG_* formats (from MSB to LSB). + */ + VG_LITE_RGBA8888 = 0 | (1 << 10), + VG_LITE_BGRA8888 = 1 | (1 << 10), + VG_LITE_RGBX8888 = 2 | (1 << 10), + VG_LITE_BGRX8888 = 3 | (1 << 10), + VG_LITE_RGB565 = 4 | (1 << 10), + VG_LITE_BGR565 = 5 | (1 << 10), + VG_LITE_RGBA4444 = 6 | (1 << 10), + VG_LITE_BGRA4444 = 7 | (1 << 10), + VG_LITE_BGRA5551 = 8 | (1 << 10), + VG_LITE_A4 = 9 | (1 << 10), + VG_LITE_A8 = 10 | (1 << 10), + VG_LITE_L8 = 11 | (1 << 10), + VG_LITE_YUYV = 12 | (1 << 10), + VG_LITE_YUY2 = 13 | (1 << 10), + VG_LITE_ANV12 = 14 | (1 << 10), + VG_LITE_AYUY2 = 15 | (1 << 10), + VG_LITE_NV12 = 16 | (1 << 10), + VG_LITE_YV12 = 17 | (1 << 10), + VG_LITE_YV24 = 18 | (1 << 10), + VG_LITE_YV16 = 19 | (1 << 10), + VG_LITE_NV16 = 20 | (1 << 10), + VG_LITE_YUY2_TILED = 21 | (1 << 10), + VG_LITE_NV12_TILED = 22 | (1 << 10), + VG_LITE_ANV12_TILED = 23 | (1 << 10), + VG_LITE_AYUY2_TILED = 24 | (1 << 10), + VG_LITE_RGBA2222 = 25 | (1 << 10), + VG_LITE_BGRA2222 = 26 | (1 << 10), + VG_LITE_ABGR2222 = 27 | (1 << 10), + VG_LITE_ARGB2222 = 28 | (1 << 10), + VG_LITE_ABGR4444 = 29 | (1 << 10), + VG_LITE_ARGB4444 = 30 | (1 << 10), + VG_LITE_ABGR8888 = 31 | (1 << 10), + VG_LITE_ARGB8888 = 32 | (1 << 10), + VG_LITE_ABGR1555 = 33 | (1 << 10), + VG_LITE_RGBA5551 = 34 | (1 << 10), + VG_LITE_ARGB1555 = 35 | (1 << 10), + VG_LITE_XBGR8888 = 36 | (1 << 10), + VG_LITE_XRGB8888 = 37 | (1 << 10), + VG_LITE_RGBA8888_ETC2_EAC = 38 | (1 << 10), + VG_LITE_RGB888 = 39 | (1 << 10), + VG_LITE_BGR888 = 40 | (1 << 10), + VG_LITE_ABGR8565 = 41 | (1 << 10), + VG_LITE_BGRA5658 = 42 | (1 << 10), + VG_LITE_ARGB8565 = 43 | (1 << 10), + VG_LITE_RGBA5658 = 44 | (1 << 10), + VG_LITE_ABGR8565_PLANAR = 45 | (1 << 10), + VG_LITE_BGRA5658_PLANAR = 46 | (1 << 10), + VG_LITE_ARGB8565_PLANAR = 47 | (1 << 10), + VG_LITE_RGBA5658_PLANAR = 48 | (1 << 10), + + VG_LITE_INDEX_1 = 0 | (1 << 11), /*! Indexed format. */ + VG_LITE_INDEX_2 = 1 | (1 << 11), + VG_LITE_INDEX_4 = 2 | (1 << 11), + VG_LITE_INDEX_8 = 3 | (1 << 11), + + } vg_lite_buffer_format_t; + + /* Swizzle of packed YUV format UV channels. */ + typedef enum vg_lite_swizzle + { + VG_LITE_SWIZZLE_UV, + VG_LITE_SWIZZLE_VU, + } vg_lite_swizzle_t; + + /* The YUV<->RGB conversion rule. */ + typedef enum vg_lite_yuv2rgb + { + VG_LITE_YUV601, + VG_LITE_YUV709, + } vg_lite_yuv2rgb_t; + + /* The pixel layout in a buffer. */ + typedef enum vg_lite_buffer_layout + { + VG_LITE_LINEAR, + VG_LITE_TILED, + } vg_lite_buffer_layout_t; + + /* The image (buffer) rendering mode. Match OpenVG enum VGImageMode */ + typedef enum vg_lite_image_mode + { + /* For enum value backward compatibility */ + VG_LITE_ZERO = 0, + VG_LITE_NORMAL_IMAGE_MODE = 0x1F00, + VG_LITE_MULTIPLY_IMAGE_MODE = 0x1F01, + VG_LITE_STENCIL_MODE = 0x1F02, + VG_LITE_NONE_IMAGE_MODE = 0x1F03, + VG_LITE_RECOLOR_MODE = 0x1F04, + } vg_lite_image_mode_t; + + /* The image (buffer) transparency mode. */ + typedef enum vg_lite_transparency + { + VG_LITE_IMAGE_OPAQUE, + VG_LITE_IMAGE_TRANSPARENT + } vg_lite_transparency_t; + + /* Blending modes. VG_BLEND_* match OpenVG enum VGBlendMode. + * S and D represent source and destination color channels. + * Sa and Da represent the source and destination alpha channels. + */ + typedef enum vg_lite_blend + { + VG_LITE_BLEND_NONE = 0, /*! S, No blend, Non-premultiplied */ + VG_LITE_BLEND_SRC_OVER = 1, /*! S + (1 - Sa) * D , Non-premultiplied */ + VG_LITE_BLEND_DST_OVER = 2, /*! (1 - Da) * S + D , Non-premultiplied */ + VG_LITE_BLEND_SRC_IN = 3, /*! Da * S , Non-premultiplied */ + VG_LITE_BLEND_DST_IN = 4, /*! Sa * D , Non-premultiplied */ + VG_LITE_BLEND_MULTIPLY = 5, /*! S * (1 - Da) + D * (1 - Sa) + S * D , Non-premultiplied */ + VG_LITE_BLEND_SCREEN = 6, /*! S + D - S * D , Non-premultiplied */ + VG_LITE_BLEND_DARKEN = 7, /*! min(SrcOver, DstOver) , Non-premultiplied */ + VG_LITE_BLEND_LIGHTEN = 8, /*! max(SrcOver, DstOver) , Non-premultiplied */ + VG_LITE_BLEND_ADDITIVE = 9, /*! S + D , Non-premultiplied */ + VG_LITE_BLEND_SUBTRACT = 10, /*! D * (1 - Sa) , Non-premultiplied */ + VG_LITE_BLEND_SUBTRACT_LVGL = 11, /*! D - S , Non-premultiplied */ + VG_LITE_BLEND_NORMAL_LVGL = 12, /*! S * Sa + (1 - Sa) * D , Non-premultiplied */ + VG_LITE_BLEND_ADDITIVE_LVGL = 13, /*! (S + D) * Sa + D * (1 - Sa) , Non-premultiplied */ + VG_LITE_BLEND_MULTIPLY_LVGL = 14, /*! (S * D) * Sa + D * (1 - Sa) , Non-premultiplied */ + VG_LITE_BLEND_PREMULTIPLY_SRC_OVER = 15, /*! S * Sa + (1 - Sa) * D , Non-premultiplied */ + + OPENVG_BLEND_SRC = 0x2000, /*! Copy SRC, no blend, Premultiplied */ + OPENVG_BLEND_SRC_OVER = 0x2001, /*! Porter-Duff SRC_OVER blend, Premultiplied */ + OPENVG_BLEND_DST_OVER = 0x2002, /*! Porter-Duff DST_OVER blend, Premultiplied */ + OPENVG_BLEND_SRC_IN = 0x2003, /*! Porter-Duff SRC_IN blend, Premultiplied */ + OPENVG_BLEND_DST_IN = 0x2004, /*! Porter-Duff DST_IN blend, Premultiplied */ + OPENVG_BLEND_MULTIPLY = 0x2005, /*! Porter-Duff MULTIPLY blend, Premultiplied */ + OPENVG_BLEND_SCREEN = 0x2006, /*! Porter-Duff SCREEN blend, Premultiplied */ + OPENVG_BLEND_DARKEN = 0x2007, /*! Porter-Duff DARKEN blend, Premultiplied */ + OPENVG_BLEND_LIGHTEN = 0x2008, /*! Porter-Duff LIGHTEN blend, Premultiplied */ + OPENVG_BLEND_ADDITIVE = 0x2009, /*! Porter-Duff ADDITIVE blend, Premultiplied */ + } vg_lite_blend_t; + + /* Fill rules. Match OpenVG enum VGFillRule */ + typedef enum vg_lite_fill + { + VG_LITE_FILL_EVEN_ODD = 0x1900, /*! A pixel is drawn it it crosses an odd number of path pixels. */ + VG_LITE_FILL_NON_ZERO = 0x1901, /*! A pixel is drawn if it crosses at least one path pixel. */ + } vg_lite_fill_t; + + /* Global alpha modes. */ + typedef enum vg_lite_global_alpha + { + VG_LITE_NORMAL = 0, /*! Use original src/dst alpha value. */ + VG_LITE_GLOBAL, /*! Use global src/dst alpha value to replace original src/dst alpha value. */ + VG_LITE_SCALED, /*! Multiply global src/dst alpha value and original src/dst alpha value. */ + } vg_lite_global_alpha_t; + + /* Filter modes. */ + typedef enum vg_lite_filter + { + VG_LITE_FILTER_POINT = 0, /*! Fetch the nearest image pixel. */ + VG_LITE_FILTER_LINEAR = 0x1000, /*! Used for linear paint. */ + VG_LITE_FILTER_BI_LINEAR = 0x2000, /*! Use a 2x2 box around the image pixel and perform an interpolation. */ + VG_LITE_FILTER_GAUSSIAN = 0x3000, /*! Perform 3x3 gaussian blur with the convolution for image pixel. */ + } vg_lite_filter_t; + + /* Pattern padding mode. Match OpenVG enum VGTilingMode. */ + typedef enum vg_lite_pattern_mode + { + VG_LITE_PATTERN_COLOR = 0x1D00, /*! Pixel outside the bounds of sourceimage should be taken as the color */ + VG_LITE_PATTERN_PAD = 0x1D01, /*! Pixel outside the bounds of sourceimage should be taken as having the same color as the closest edge pixel */ + VG_LITE_PATTERN_REPEAT = 0x1D02, /*! Pixel outside the bounds of sourceimage should be repeated indefinitely in all directions */ + VG_LITE_PATTERN_REFLECT = 0x1D03, /*! Pixel outside the bounds of sourceimage should be reflected indefinitely in all directions */ + } vg_lite_pattern_mode_t; + + /* Paint type. Match OpenVG enum VGPaintType. */ + typedef enum vg_lite_paint_type + { + /* For enum value backward compatibility */ + VG_LITE_PAINT_ZERO = 0, + VG_LITE_PAINT_COLOR = 0x1B00, + VG_LITE_PAINT_LINEAR_GRADIENT = 0x1B01, + VG_LITE_PAINT_RADIAL_GRADIENT = 0x1B02, + VG_LITE_PAINT_PATTERN = 0x1B03, + } vg_lite_paint_type_t; + + /* Radial gradient padding mode. Match OpenVG enum VGColorRampSpreadMode */ + typedef enum + { + VG_LITE_GRADIENT_SPREAD_FILL = 0, + VG_LITE_GRADIENT_SPREAD_PAD = 0x1C00, + VG_LITE_GRADIENT_SPREAD_REPEAT = 0x1C01, + VG_LITE_GRADIENT_SPREAD_REFLECT = 0x1C02, + } vg_lite_gradient_spreadmode_t; + + /* Decnano Compress mode. */ + typedef enum vg_lite_compress_mode + { + VG_LITE_DEC_DISABLE = 0, /*! disable compress */ + VG_LITE_DEC_NON_SAMPLE, /*! compress ratio is 1.6 if use ARGB8888, compress ratio is 2 if use XRGB8888 */ + VG_LITE_DEC_HSAMPLE, /*! compress ratio is 2 if use ARGB8888, compress ratio is 2.6 if use XRGB8888 */ + VG_LITE_DEC_HV_SAMPLE, /*! compress ratio is 2.6 if use ARGB8888, compress ratio is 4 if use XRGB8888 */ + } vg_lite_compress_mode_t; + + /* Draw path type. Match OpenVG enum VGPaintMode */ + typedef enum vg_lite_path_type + { + /* For enum value backward compatibility */ + VG_LITE_DRAW_ZERO = 0, + VG_LITE_DRAW_STROKE_PATH = (1<<0), + VG_LITE_DRAW_FILL_PATH = (1<<1), + VG_LITE_DRAW_FILL_STROKE_PATH = (1<<1 | 1<<0), + } vg_lite_path_type_t; + + /* End cap style. Match OpenVG enum VGCapStyle */ + typedef enum vg_lite_cap_style + { + VG_LITE_CAP_BUTT = 0x1700, + VG_LITE_CAP_ROUND = 0x1701, + VG_LITE_CAP_SQUARE = 0x1702, + } vg_lite_cap_style_t; + + /* Line join styles. Match OpenVG enum VGJoinStyle */ + typedef enum vg_lite_join_style + { + VG_LITE_JOIN_MITER = 0x1800, + VG_LITE_JOIN_ROUND = 0x1801, + VG_LITE_JOIN_BEVEL = 0x1802, + } vg_lite_join_style_t; + + /* Mask operation mode. Match OpenVG enum VGMaskOperation */ + typedef enum vg_lite_mask_operation + { + VG_LITE_CLEAR_MASK = 0x1500, /*! Set all dest mask values to 0 */ + VG_LITE_FILL_MASK = 0x1501, /*! Set all dest mask values to 1 */ + VG_LITE_SET_MASK = 0x1502, /*! Copy from src masklayer to dest masklayer. */ + VG_LITE_UNION_MASK = 0x1503, /*! Replace dest masklayer by its union with src masklayer. */ + VG_LITE_INTERSECT_MASK = 0x1504, /*! Replace dest masklayer by its intersection with src masklayer. */ + VG_LITE_SUBTRACT_MASK = 0x1505, /*! Subtract src mask in dest masklayer */ + } vg_lite_mask_operation_t; + + /* Mirror orientation mode. */ + typedef enum vg_lite_orientation + { + VG_LITE_ORIENTATION_TOP_BOTTOM, + VG_LITE_ORIENTATION_BOTTOM_TOP, + } vg_lite_orientation_t; + + /* Gamma conversion mode. */ + typedef enum vg_lite_gamma_conversion + { + VG_LITE_GAMMA_NO_CONVERSION, /*! Leave color as is. */ + VG_LITE_GAMMA_LINEAR, /*! Convert from sRGB to linear space. */ + VG_LITE_GAMMA_NON_LINEAR /*! Convert from linear to sRGB space. */ + } vg_lite_gamma_conversion_t; + + /* Index endian */ + typedef enum vg_lite_index_endian + { + VG_LITE_INDEX_LITTLE_ENDIAN, /*! Parse the index pixel from low to high, + *! when using index1, the parsing order is bit0~bit7. + *! when using index2, the parsing order is bit0:1,bit2:3,bit4:5.bit6:7. + *! when using index4, the parsing order is bit0:3,bit4:7. + */ + VG_LITE_INDEX_BIG_ENDIAN, /*! Parse the index pixel from low to high, + *! when using index1, the parsing order is bit7~bit0. + *! when using index2, the parsing order is bit7:6,bit5:4,bit3:2.bit1:0. + *! when using index4, the parsing order is bit4:7,bit0:3. + */ + } vg_lite_index_endian_t; + + /* Map flag*/ + typedef enum vg_lite_map_flag + { + VG_LITE_MAP_USER_MEMORY = 0, + VG_LITE_MAP_DMABUF = 0x01, + } vg_lite_map_flag_t; + + /*VGLite parameters variable*/ + typedef enum vg_lite_param_type + { + VG_LITE_SCISSOR_RECT, /*! count must be 4n for x, y, right, bottom */ + } vg_lite_param_type_t; + +/* VGLite API Structures ******************************************************************************************************************/ + + /* VGLite driver information */ + typedef struct vg_lite_info { + vg_lite_uint32_t api_version; + vg_lite_uint32_t header_version; + vg_lite_uint32_t release_version; + vg_lite_uint32_t reserved; + } vg_lite_info_t; + + /* A 2D Point definition. */ + typedef struct vg_lite_point { + vg_lite_int32_t x; + vg_lite_int32_t y; + } vg_lite_point_t; + + /* Four 2D Point that form a polygon */ + typedef vg_lite_point_t vg_lite_point4_t[4]; + + /* A rectangle.*/ + typedef struct vg_lite_rectangle { + vg_lite_int32_t x; /*! Left coordinate of rectangle. */ + vg_lite_int32_t y; /*! Top coordinate of rectangle. */ + vg_lite_int32_t width; /*! Width of rectangle. */ + vg_lite_int32_t height; /*! Height of rectangle. */ + } vg_lite_rectangle_t; + + typedef struct vg_lite_matrix { + vg_lite_float_t m[3][3]; /*! The 3x3 matrix is in [row][column] order. */ + vg_lite_float_t scaleX; + vg_lite_float_t scaleY; + vg_lite_float_t angle; + } vg_lite_matrix_t; + + typedef struct vg_lite_yuvinfo + { + vg_lite_swizzle_t swizzle; /*! UV swizzle. */ + vg_lite_yuv2rgb_t yuv2rgb; /*! 601 or 709 conversion standard. */ + vg_lite_uint32_t uv_planar; /*! UV(U) planar address. */ + vg_lite_uint32_t v_planar; /*! V planar address. */ + vg_lite_uint32_t alpha_planar; /*! Alpha planar address. */ + vg_lite_uint32_t uv_stride; /*! UV(U) stride. */ + vg_lite_uint32_t v_stride; /*! V stride. */ + vg_lite_uint32_t alpha_stride; /*! Alpha stride. */ + vg_lite_uint32_t uv_height; /*! UV(U) height. */ + vg_lite_uint32_t v_height; /*! V height. */ + vg_lite_pointer uv_memory; /*! The logical pointer to the UV(U) planar memory. */ + vg_lite_pointer v_memory; /*! The logical pointer to the V planar memory. */ + vg_lite_pointer uv_handle; /*! The memory handle of the UV(U) planar. */ + vg_lite_pointer v_handle; /*! The memory handle of the V planar. */ + } vg_lite_yuvinfo_t; + + typedef struct vg_lite_path_point* vg_lite_path_point_ptr; + typedef struct vg_lite_path_point + { + /* X coordinate. */ + vg_lite_float_t x; + + /* Y coordinate. */ + vg_lite_float_t y; + + /* Flatten flag for flattened path. */ + vg_lite_uint8_t flatten_flag; + + /* Curve type for stroke path. */ + vg_lite_uint8_t curve_type; + + /* X tangent. */ + vg_lite_float_t tangentX; + + /* Y tangent. */ + vg_lite_float_t tangentY; + + /* Length of the line. */ + vg_lite_float_t length; + + /* Pointer to next point node. */ + vg_lite_path_point_ptr next; + + /* Pointer to previous point node. */ + vg_lite_path_point_ptr prev; + + } vg_lite_path_point_t; + + typedef struct vg_lite_sub_path* vg_lite_sub_path_ptr; + typedef struct vg_lite_sub_path + { + /* Pointer to next sub path. */ + vg_lite_sub_path_ptr next; + + /* Number of points. */ + vg_lite_uint32_t point_count; + + /* Point list. */ + vg_lite_path_point_ptr point_list; + + /* Last point. */ + vg_lite_path_point_ptr end_point; + + /* Whether is path is closed. */ + vg_lite_uint8_t closed; + + /* Sub path length. */ + vg_lite_float_t length; + + } vg_lite_sub_path_t; + + /* Save divided path data according to MOVE/MOVE_REL. */ + typedef struct vg_lite_path_list* vg_lite_path_list_ptr; + typedef struct vg_lite_path_list + { + vg_lite_path_point_ptr path_points; + vg_lite_path_point_ptr path_end; + vg_lite_uint32_t point_count; + vg_lite_path_list_ptr next; + vg_lite_uint8_t closed; + + } vg_lite_path_list_t; + + typedef struct vg_lite_stroke + { + /* Stroke parameters */ + vg_lite_cap_style_t cap_style; + vg_lite_join_style_t join_style; + vg_lite_float_t line_width; + vg_lite_float_t miter_limit; + vg_lite_float_t *dash_pattern; + vg_lite_uint32_t pattern_count; + vg_lite_float_t dash_phase; + vg_lite_float_t dash_length; + vg_lite_uint32_t dash_index; + vg_lite_float_t half_width; + + /* Total length of stroke dash patterns. */ + vg_lite_float_t pattern_length; + + /* For fast checking. */ + vg_lite_float_t miter_square; + + /* Temp storage of stroke subPath. */ + vg_lite_path_point_ptr path_points; + vg_lite_path_point_ptr path_end; + vg_lite_uint32_t point_count; + vg_lite_path_point_ptr left_point; + vg_lite_path_point_ptr right_point; + vg_lite_path_point_ptr stroke_points; + vg_lite_path_point_ptr stroke_end; + vg_lite_uint32_t stroke_count; + + /* Divide stroke path according to move or move_rel for avoiding implicit closure. */ + vg_lite_path_list_ptr path_list_divide; + + /* pointer to current divided path data. */ + vg_lite_path_list_ptr cur_list; + + /* Flag that add end_path in driver. */ + vg_lite_uint8_t add_end; + vg_lite_uint8_t dash_reset; + + /* Sub path list. */ + vg_lite_sub_path_ptr stroke_paths; + + /* Last sub path. */ + vg_lite_sub_path_ptr last_stroke; + + /* Swing area handling. */ + vg_lite_uint32_t swing_handling; + vg_lite_float_t swing_deltax; + vg_lite_float_t swing_deltay; + vg_lite_path_point_ptr swing_start; + vg_lite_path_point_ptr swing_stroke; + vg_lite_float_t swing_length; + vg_lite_float_t swing_centlen; + vg_lite_uint32_t swing_count; + vg_lite_uint8_t need_swing; + vg_lite_uint8_t swing_ccw; + + vg_lite_float_t stroke_length; + vg_lite_uint32_t stroke_size; + + /* The stroke line is fat line. */ + vg_lite_uint8_t fattened; + vg_lite_uint8_t closed; + + } vg_lite_stroke_t; + + /* Fast clear buffer. */ + typedef struct vg_lite_fc_buffer + { + vg_lite_int32_t width; /*! Width of the buffer in pixels. */ + vg_lite_int32_t height; /*! height of the buffer in pixels. */ + vg_lite_int32_t stride; /*! The number of bytes to move from one line in the buffer to the next line. */ + vg_lite_pointer handle; /*! The memory handle of the buffer's memory as allocated by the VGLite kernel. */ + vg_lite_pointer memory; /*! The logical pointer to the buffer's memory for the CPU. */ + vg_lite_uint32_t address; /*! The address to the buffer's memory for the hardware. */ + vg_lite_uint32_t color; /*! The fastclear color value. */ + } vg_lite_fc_buffer_t; + + /* Structure for any image or render target. */ + typedef struct vg_lite_buffer + { + vg_lite_int32_t width; /*! Width of the buffer in pixels. */ + vg_lite_int32_t height; /*! Height of the buffer in pixels. */ + vg_lite_int32_t stride; /*! The number of bytes to move from one line in the buffer to the next line. */ + vg_lite_buffer_layout_t tiled; /*! Indicating the buffer memory layout is linear or tiled. */ + vg_lite_buffer_format_t format; /*! The pixel format of the buffer. */ + vg_lite_pointer handle; /*! The memory handle of the buffer's memory as allocated by the VGLite kernel. */ + vg_lite_pointer memory; /*! The logical pointer to the buffer's memory for the CPU. */ + vg_lite_uint32_t address; /*! The address to the buffer's memory for the hardware. */ + vg_lite_yuvinfo_t yuv; /*! The yuv format details. */ + vg_lite_image_mode_t image_mode; /*! The blit image mode. */ + vg_lite_transparency_t transparency_mode; /*! image transparency mode. */ + vg_lite_fc_buffer_t fc_buffer[3]; /*! 3 fastclear buffers,reserved YUV format. */ + vg_lite_compress_mode_t compress_mode; /*! Refer to the definition by vg_lite_compress_mode_t. */ + vg_lite_index_endian_t index_endian; /*! Refer to the definition by vg_lite_index_endian_t. */ + vg_lite_paint_type_t paintType; /*! Get paintcolor from different paint types. */ + vg_lite_uint8_t fc_enable; /*! enable im fastclear. */ + vg_lite_uint8_t scissor_layer; /*! The buffer is scissor buffer. */ + vg_lite_uint8_t premultiplied; /*! The RGB pixel values are alpha-premultipled */ + } vg_lite_buffer_t; + + /* Memory allocation info by kernel. */ + typedef struct vg_lite_hw_memory + { + vg_lite_pointer handle; /*! gpu memory object handle. */ + vg_lite_pointer memory; /*! logical memory address. */ + vg_lite_uint32_t address; /*! GPU memory address. */ + vg_lite_uint32_t bytes; /*! Size of memory. */ + vg_lite_uint32_t property; /*! Currently bit0 is used for path upload state: + *! 1 : enable auto path data uploading. + *! 0 : disable path data uploading. path data is embedded in command buffer. */ + } vg_lite_hw_memory_t; + + /* Path info for drawing command. */ + typedef struct vg_lite_path + { + vg_lite_float_t bounding_box[4]; /*! Bounding box specified as left, top, right, and bottom. */ + vg_lite_quality_t quality; /*! Quality hint for the path. */ + vg_lite_format_t format; /*! Coordinate format. */ + vg_lite_hw_memory_t uploaded; /*! Path data that has been upload into GPU addressable memory. */ + vg_lite_uint32_t path_length; /*! Number of bytes in the path data. */ + vg_lite_pointer path; /*! Pointer to the physical description of the path. */ + vg_lite_int8_t path_changed; /*! Indicate whether path data is synced with command buffer (uploaded) or not. */ + vg_lite_int8_t pdata_internal; /*! Indicate whether path data memory is allocated by driver. */ + vg_lite_path_type_t path_type; /*! Refer to the definition by vg_lite_path_type_t. */ + vg_lite_stroke_t *stroke; /*! Pointer to a vg_lite_stroke_t structure.*/ + vg_lite_pointer stroke_path; /*! Pointer to the physical description of the stroke path. */ + vg_lite_uint32_t stroke_size; /*! Number of bytes in the stroke path data. */ + vg_lite_color_t stroke_color; /*! The stroke path fill color. */ + vg_lite_int8_t add_end; /*! Flag that add end_path in driver. */ + } vg_lite_path_t; + + /* Color ramp definition. */ + typedef struct vg_lite_color_ramp + { + vg_lite_float_t stop; /*! Value for the color stop. */ + vg_lite_float_t red; /*! Red color channel value for the color stop. */ + vg_lite_float_t green; /*! Green color channel value for the color stop. */ + vg_lite_float_t blue; /*! Blue color channel value for the color stop. */ + vg_lite_float_t alpha; /*! Alpha color channel value for the color stop. */ + } vg_lite_color_ramp_t; + + /* Linear gradient parameter */ + typedef struct vg_lite_linear_gradient_parameter + { + vg_lite_float_t X0; + vg_lite_float_t Y0; + vg_lite_float_t X1; + vg_lite_float_t Y1; + } vg_lite_linear_gradient_parameter_t; + + typedef struct vg_lite_radial_gradient_parameter + { + vg_lite_float_t cx; /*! x coordinate of the center point. */ + vg_lite_float_t cy; /*! y coordinate of the center point. */ + vg_lite_float_t r; /*! radius. */ + vg_lite_float_t fx; /*! x coordinate of the focal point. */ + vg_lite_float_t fy; /*! y coordinate of the focal point. */ + } vg_lite_radial_gradient_parameter_t; + + /* Linear gradient definition. */ + typedef struct vg_lite_linear_gradient { + vg_lite_uint32_t colors[VLC_MAX_GRADIENT_STOPS]; /*! Colors for stops. */ + vg_lite_uint32_t count; /*! Count of colors, up to 16. */ + vg_lite_uint32_t stops[VLC_MAX_GRADIENT_STOPS]; /*! Color stops, value from 0 to 255. */ + vg_lite_matrix_t matrix; /*! The matrix to transform the gradient. */ + vg_lite_buffer_t image; /*! The image for rendering as gradient pattern. */ + } vg_lite_linear_gradient_t; + + /* Extended linear gradient definition. */ + typedef struct vg_lite_ext_linear_gradient { + vg_lite_uint32_t count; /*! Count of colors, up to 256. */ + vg_lite_matrix_t matrix; /*! The matrix to transform the gradient. */ + vg_lite_buffer_t image; /*! The image for rendering as gradient pattern. */ + vg_lite_linear_gradient_parameter_t linear_grad; /*! Include center point,focal point and radius.*/ + + vg_lite_uint32_t ramp_length; /*! Color ramp for gradient paints provided to driver. */ + vg_lite_color_ramp_t color_ramp[VLC_MAX_COLOR_RAMP_STOPS]; + + vg_lite_uint32_t converted_length; /*! Converted internal color ramp. */ + vg_lite_color_ramp_t converted_ramp[VLC_MAX_COLOR_RAMP_STOPS + 2]; + + vg_lite_uint8_t pre_multiplied; /*! If color values of color_ramp[] are multiply by alpha value of color_ramp[]. */ + vg_lite_gradient_spreadmode_t spread_mode; /*! The spread mode that applied to the pixels out of the image after transformed. */ + } vg_lite_ext_linear_gradient_t; + + /* Radial gradient definition. */ + typedef struct vg_lite_radial_gradient + { + vg_lite_uint32_t count; /*! Count of colors, up to 256. */ + vg_lite_matrix_t matrix; /*! The matrix to transform the gradient. */ + vg_lite_buffer_t image; /*! The image for rendering as gradient pattern. */ + vg_lite_radial_gradient_parameter_t radial_grad; /*! Include center point,focal point and radius.*/ + + vg_lite_uint32_t ramp_length; /*! Color ramp for gradient paints provided to the driver. */ + vg_lite_color_ramp_t color_ramp[VLC_MAX_COLOR_RAMP_STOPS]; + + vg_lite_uint32_t converted_length; /*! Converted internal color ramp. */ + vg_lite_color_ramp_t converted_ramp[VLC_MAX_COLOR_RAMP_STOPS + 2]; + + vg_lite_uint8_t pre_multiplied; /*! If color values of color_ramp[] are multiply by alpha value of color_ramp[]. */ + vg_lite_gradient_spreadmode_t spread_mode; /*! The spread mode that applied to the pixels out of the image after transformed. */ + } vg_lite_radial_gradient_t; + + /* Colorkey definition */ + typedef struct vg_lite_color_key + { + vg_lite_uint8_t enable; /*! The color key is effective only when "enable" is ture, */ + vg_lite_uint8_t low_r; /*! The R chanel of low_rgb. */ + vg_lite_uint8_t low_g; /*! The G chanel of low_rgb. */ + vg_lite_uint8_t low_b; /*! The B chanel of low_rgb. */ + vg_lite_uint8_t alpha; /*! The alpha channel to replace destination pixel alpha channel.*/ + vg_lite_uint8_t hign_r; /*! The R chanel of hign_rgb. */ + vg_lite_uint8_t hign_g; /*! The G chanel of hign_rgb. */ + vg_lite_uint8_t hign_b; /*! The B chanel of hign_rgb. */ + } vg_lite_color_key_t; + + /* Four colorkey definition. + * rgb_hi_0, rgb_lo_0, alpha_0, enable_0; + * rgb_hi_1, rgb_lo_1, alpha_1, enable_1; + * rgb_hi_2, rgb_lo_2, alpha_2, enable_2; + * rgb_hi_3, rgb_lo_3, alpha_3, enable_3; + * Priority order: color_key_0 > color_key_1 > color_key_2 > color_key_3. + */ + typedef vg_lite_color_key_t vg_lite_color_key4_t[4]; + + /* Pixel matrix values */ + typedef vg_lite_float_t vg_lite_pixel_matrix_t[20]; + + /* HW pixel channel enable flags */ + typedef struct vg_lite_pixel_channel_enable + { + vg_lite_uint8_t enable_a; /*! Enable A channel.*/ + vg_lite_uint8_t enable_b; /*! Enable B channel. */ + vg_lite_uint8_t enable_g; /*! Enable G channel. */ + vg_lite_uint8_t enable_r; /*! Enable R channel. */ + } vg_lite_pixel_channel_enable_t; + + /* Pixel color transform */ + typedef struct vg_lite_color_transform + { + vg_lite_float_t a_scale; + vg_lite_float_t a_bias; + vg_lite_float_t r_scale; + vg_lite_float_t r_bias; + vg_lite_float_t g_scale; + vg_lite_float_t g_bias; + vg_lite_float_t b_scale; + vg_lite_float_t b_bias; + } vg_lite_color_transform_t; + +/* VGLite API Functions *******************************************************************************************************************/ + + /* Initialize a vglite context. */ + vg_lite_error_t vg_lite_init(vg_lite_int32_t tess_width, vg_lite_int32_t tess_height); + + /* Destroy a vglite context. */ + vg_lite_error_t vg_lite_close(void); + + /* Get the VGLite driver information. */ + vg_lite_error_t vg_lite_get_info(vg_lite_info_t* info); + + /* Get the GPU chip information. */ + vg_lite_uint32_t vg_lite_get_product_info(vg_lite_char *name, vg_lite_uint32_t *chip_id, vg_lite_uint32_t *chip_rev); + + /* Query if a specific feature is supported. */ + vg_lite_uint32_t vg_lite_query_feature(vg_lite_feature_t feature); + + /* Flush command buffer and wait for GPU to complete. */ + vg_lite_error_t vg_lite_finish(void); + + /* Flush the command buffer without waiting for GPU to complete. */ + vg_lite_error_t vg_lite_flush(void); + + /* Get the value of register from register's address. */ + vg_lite_error_t vg_lite_get_register(vg_lite_uint32_t address, vg_lite_uint32_t* result); + + /* Generate a 3x3 homogenous matrix to transform 4 source coordinates to 4 target coordinates. */ + vg_lite_error_t vg_lite_get_transform_matrix(vg_lite_point4_t src, vg_lite_point4_t dst, vg_lite_matrix_t *mat); + + /* Allocate a buffer from GPU hardware accessible memory. */ + vg_lite_error_t vg_lite_allocate(vg_lite_buffer_t *buffer); + + /* Free a buffer allocated by vg_lite_allocate() */ + vg_lite_error_t vg_lite_free(vg_lite_buffer_t *buffer); + + /* Upload RGB or YUV pixel data to an allocated buffer. */ + vg_lite_error_t vg_lite_upload_buffer(vg_lite_buffer_t *buffer, vg_lite_uint8_t *data[3], vg_lite_uint32_t stride[3]); + + /* Map a buffer into hardware accessible address space. */ + vg_lite_error_t vg_lite_map(vg_lite_buffer_t *buffer, vg_lite_map_flag_t flag, int32_t fd); + + /* Unmap a buffer that is mapped */ + vg_lite_error_t vg_lite_unmap(vg_lite_buffer_t *buffer); + + /* flush cache */ + vg_lite_error_t vg_lite_flush_mapped_buffer(vg_lite_buffer_t * buffer); + + /* Fill a buffer rectangle area with a specified color. */ + vg_lite_error_t vg_lite_clear(vg_lite_buffer_t *target, vg_lite_rectangle_t *rect, vg_lite_color_t color); + + /* Copy a source image to target buffer with transformation, blending, color mixing, and filtering. */ + vg_lite_error_t vg_lite_blit(vg_lite_buffer_t *target, + vg_lite_buffer_t *source, + vg_lite_matrix_t *matrix, + vg_lite_blend_t blend, + vg_lite_color_t color, + vg_lite_filter_t filter); + + /* Copy a rectangle area of source image to target buffer with transformation, blending, color mixing, and filtering. */ + vg_lite_error_t vg_lite_blit_rect(vg_lite_buffer_t *target, + vg_lite_buffer_t *source, + vg_lite_rectangle_t *rect, + vg_lite_matrix_t *matrix, + vg_lite_blend_t blend, + vg_lite_color_t color, + vg_lite_filter_t filter); + + /* Copy two source images to the target buffer with transformation, blending, and filtering. */ + vg_lite_error_t vg_lite_blit2(vg_lite_buffer_t *target, + vg_lite_buffer_t *source0, + vg_lite_buffer_t *source1, + vg_lite_matrix_t *matrix0, + vg_lite_matrix_t *matrix1, + vg_lite_blend_t blend, + vg_lite_filter_t filter); + + /* Copy a rectangle area of source image to target buffer without transformation, blending, color mixing, and filtering. */ + vg_lite_error_t vg_lite_copy_image(vg_lite_buffer_t *target, + vg_lite_buffer_t *source, + vg_lite_int32_t sx, + vg_lite_int32_t sy, + vg_lite_int32_t dx, + vg_lite_int32_t dy, + vg_lite_int32_t width, + vg_lite_int32_t height); + + /* Draw a path to a target buffer with transformation, color, and blending */ + vg_lite_error_t vg_lite_draw(vg_lite_buffer_t *target, + vg_lite_path_t *path, + vg_lite_fill_t fill_rule, + vg_lite_matrix_t *matrix, + vg_lite_blend_t blend, + vg_lite_color_t color); + + /* Set stroke path attributes. */ + vg_lite_error_t vg_lite_set_stroke(vg_lite_path_t *path, + vg_lite_cap_style_t cap_style, + vg_lite_join_style_t join_style, + vg_lite_float_t line_width, + vg_lite_float_t miter_limit, + vg_lite_float_t *dash_pattern, + vg_lite_uint32_t pattern_count, + vg_lite_float_t dash_phase, + vg_lite_color_t color); + + /* Update stroke path. */ + vg_lite_error_t vg_lite_update_stroke(vg_lite_path_t *path); + + /* Set path type. */ + vg_lite_error_t vg_lite_set_path_type(vg_lite_path_t *path, vg_lite_path_type_t path_type); + + /* Clears all attributes of a path. */ + vg_lite_error_t vg_lite_clear_path(vg_lite_path_t *path); + + /* Upload a path to GPU memory so GPU can access it directly. */ + vg_lite_error_t vg_lite_upload_path(vg_lite_path_t *path); + + /* Initialize a path object with attributes. */ + vg_lite_error_t vg_lite_init_path(vg_lite_path_t *path, + vg_lite_format_t format, + vg_lite_quality_t quality, + vg_lite_uint32_t length, + vg_lite_pointer data, + vg_lite_float_t min_x, + vg_lite_float_t min_y, + vg_lite_float_t max_x, + vg_lite_float_t max_y); + + /* Initializes a arc path with attributes. */ + vg_lite_error_t vg_lite_init_arc_path(vg_lite_path_t *path, + vg_lite_format_t format, + vg_lite_quality_t quality, + vg_lite_uint32_t length, + vg_lite_pointer data, + vg_lite_float_t min_x, + vg_lite_float_t min_y, + vg_lite_float_t max_x, + vg_lite_float_t max_y); + + /* Return the size (in bytes) of command buffer for a path opcode array. */ + vg_lite_uint32_t vg_lite_get_path_length(vg_lite_uint8_t *opcode, + vg_lite_uint32_t count, + vg_lite_format_t format); + + /* Generate command buffer for the (path) based on input opcodes (opcode) and coordinates (data). */ + vg_lite_error_t vg_lite_append_path(vg_lite_path_t *path, + vg_lite_uint8_t *opcode, + vg_lite_pointer data, + vg_lite_uint32_t seg_count); + + /* Set CLUT (Color Look Up Table) for index image. The (colors) is in ARGB format. */ + vg_lite_error_t vg_lite_set_CLUT(vg_lite_uint32_t count, vg_lite_uint32_t *colors); + + /* Draw a path that is filled by a transformed image pattern. */ + vg_lite_error_t vg_lite_draw_pattern(vg_lite_buffer_t *target, + vg_lite_path_t *path, + vg_lite_fill_t fill_rule, + vg_lite_matrix_t *path_matrix, + vg_lite_buffer_t *pattern_image, + vg_lite_matrix_t *pattern_matrix, + vg_lite_blend_t blend, + vg_lite_pattern_mode_t pattern_mode, + vg_lite_color_t pattern_color, + vg_lite_color_t color, + vg_lite_filter_t filter); + + /* Initialize a linear gradient object with default attributes. */ + vg_lite_error_t vg_lite_init_grad(vg_lite_linear_gradient_t *grad); + + /* Reset a linear gradient object attributes. */ + vg_lite_error_t vg_lite_clear_grad(vg_lite_linear_gradient_t *grad); + + /* Update a linear gradient object. */ + vg_lite_error_t vg_lite_update_grad(vg_lite_linear_gradient_t *grad); + + /* Return pointer to a linear gradient object's matrix. */ + vg_lite_matrix_t* vg_lite_get_grad_matrix(vg_lite_linear_gradient_t *grad); + + /* Set attributes for a linear gradient object. */ + vg_lite_error_t vg_lite_set_grad(vg_lite_linear_gradient_t *grad, + vg_lite_uint32_t count, + vg_lite_uint32_t *colors, + vg_lite_uint32_t *stops); + + /* Draw a path with a linear gradient object pattern. */ + vg_lite_error_t vg_lite_draw_grad(vg_lite_buffer_t *target, + vg_lite_path_t *path, + vg_lite_fill_t fill_rule, + vg_lite_matrix_t *matrix, + vg_lite_linear_gradient_t *grad, + vg_lite_blend_t blend); + + /* Reset an extended linear gradient object attributes and free image buffer. */ + vg_lite_error_t vg_lite_clear_linear_grad(vg_lite_ext_linear_gradient_t *grad); + + /* Update an extended linear gradient object. */ + vg_lite_error_t vg_lite_update_linear_grad(vg_lite_ext_linear_gradient_t *grad); + + /* Return pointer to an extended linear gradient object's matrix. */ + vg_lite_matrix_t* vg_lite_get_linear_grad_matrix(vg_lite_ext_linear_gradient_t *grad); + + /* Set attributes for an extended linear gradient object. */ + vg_lite_error_t vg_lite_set_linear_grad(vg_lite_ext_linear_gradient_t *grad, + vg_lite_uint32_t count, + vg_lite_color_ramp_t *color_ramp, + vg_lite_linear_gradient_parameter_t grad_param, + vg_lite_gradient_spreadmode_t spread_mode, + vg_lite_uint8_t pre_mult); + + /* Draw a path with an extended linear gradient object. */ + vg_lite_error_t vg_lite_draw_linear_grad(vg_lite_buffer_t *target, + vg_lite_path_t *path, + vg_lite_fill_t fill_rule, + vg_lite_matrix_t *path_matrix, + vg_lite_ext_linear_gradient_t *grad, + vg_lite_color_t paint_color, + vg_lite_blend_t blend, + vg_lite_filter_t filter); + + /* Reset a radial gradient object attributes and free image buffer. */ + vg_lite_error_t vg_lite_clear_radial_grad(vg_lite_radial_gradient_t *grad); + + /* Update a radial gradient object. */ + vg_lite_error_t vg_lite_update_radial_grad(vg_lite_radial_gradient_t *grad); + + /* Return pointer to a radial gradient object's matrix. */ + vg_lite_matrix_t* vg_lite_get_radial_grad_matrix(vg_lite_radial_gradient_t *grad); + + /* Set attributes for a radial gradient object. */ + vg_lite_error_t vg_lite_set_radial_grad(vg_lite_radial_gradient_t *grad, + vg_lite_uint32_t count, + vg_lite_color_ramp_t *color_ramp, + vg_lite_radial_gradient_parameter_t grad_param, + vg_lite_gradient_spreadmode_t spread_mode, + vg_lite_uint8_t pre_mult); + + /* Draw a path with a radial gradient object pattern. */ + vg_lite_error_t vg_lite_draw_radial_grad(vg_lite_buffer_t *target, + vg_lite_path_t *path, + vg_lite_fill_t fill_rule, + vg_lite_matrix_t *path_matrix, + vg_lite_radial_gradient_t *grad, + vg_lite_color_t paint_color, + vg_lite_blend_t blend, + vg_lite_filter_t filter); + + /* Load an identity matrix. */ + vg_lite_error_t vg_lite_identity(vg_lite_matrix_t *matrix); + + /* Translate a matrix. */ + vg_lite_error_t vg_lite_translate(vg_lite_float_t x, vg_lite_float_t y, vg_lite_matrix_t *matrix); + + /* Scale a matrix. */ + vg_lite_error_t vg_lite_scale(vg_lite_float_t scale_x, vg_lite_float_t scale_y, vg_lite_matrix_t *matrix); + + /* Rotate a matrix. */ + vg_lite_error_t vg_lite_rotate(vg_lite_float_t degrees, vg_lite_matrix_t *matrix); + + /* Set and enable a scissor rectangle for render target. */ + vg_lite_error_t vg_lite_set_scissor(vg_lite_int32_t x, vg_lite_int32_t y, vg_lite_int32_t right, vg_lite_int32_t bottom); + + /* Set scissor rectangles on mask layer. Scissor rects are enabled/disabled by following APIs. */ + vg_lite_error_t vg_lite_scissor_rects(vg_lite_uint32_t nums, vg_lite_rectangle_t rect[]); + + /* Enable scissor rects defined on mask layer. */ + vg_lite_error_t vg_lite_enable_scissor(void); + + /* Disable scissor rects defined on mask layer. */ + vg_lite_error_t vg_lite_disable_scissor(void); + + /* Query size of available contiguous video memory. */ + vg_lite_error_t vg_lite_get_mem_size(vg_lite_uint32_t *size); + + /* Set global alpha value for source image */ + vg_lite_error_t vg_lite_source_global_alpha(vg_lite_global_alpha_t alpha_mode, vg_lite_uint8_t alpha_value); + + /* Set global alpha value for destination image. */ + vg_lite_error_t vg_lite_dest_global_alpha(vg_lite_global_alpha_t alpha_mode, vg_lite_uint8_t alpha_value); + + /* Set colorkey. */ + vg_lite_error_t vg_lite_set_color_key(vg_lite_color_key4_t colorkey); + + /* Enable dither function. Dither is OFF by default. */ + vg_lite_error_t vg_lite_enable_dither(void); + + /* Disable dither function. Dither is OFF by default. */ + vg_lite_error_t vg_lite_disable_dither(void); + + /* Set a 64-byte aligned memory buffer (physical) as VGLite tessellation buffer. */ + vg_lite_error_t vg_lite_set_tess_buffer(vg_lite_uint32_t physical, vg_lite_uint32_t size); + + /* Can be called before vg_lite_init() to overwrite the default VG_LITE_COMMAND_BUFFER_SIZE */ + vg_lite_error_t vg_lite_set_command_buffer_size(vg_lite_uint32_t size); + + /* Set a user-defined external memory buffer (physical, 64-byte aligned) as VGLite command buffer. */ + vg_lite_error_t vg_lite_set_command_buffer(vg_lite_uint32_t physical, vg_lite_uint32_t size); + + /* Setup a pixel transform matrix m[20] which transforms each pixel as following: + * + * |a'| |m0 m1 m2 m3 m4 | |a| + * |r'| |m5 m6 m7 m8 m9 | |r| + * |g'| = |m10 m11 m12 m13 m14|.|g| + * |b'| |m15 m16 m17 m18 m19| |b| + * |1 | |0 0 0 0 1 | |1| + * + * The pixel transform for A, R, G, B channel can be enabled/disabled individually with (channel) parameter. + */ + vg_lite_error_t vg_lite_set_pixel_matrix(vg_lite_pixel_matrix_t matrix, vg_lite_pixel_channel_enable_t *channel); + + /* Setup 3x3 gaussian blur weight values to filter image pixels. + * + * Paramters w0, w1, w2 define a 3x3 gaussian blur weight matrix as below + * + * | w2 w1 w2 | + * | w1 w0 w1 | + * | w2 w1 w2 | + * + * The sum of 9 kernel weights must be 1.0 to avoid convolution overflow ( w0 + 4*w1 + 4*w2 = 1.0 ). + * The 3x3 weight matrix applies to a 3x3 pixel block + * + * | pixel[i-1][j-1] pixel[i][j-1] pixel[i+1][j-1]| + * | pixel[i-1][j] pixel[i][j] pixel[i+1][j] | + * | pixel[i-1][j+1] pixel[i][j+1] pixel[i+1][j+1]| + * + * With the following dot product equation: + * + * color[i][j] = w2*pixel[i-1][j-1] + w1*pixel[i][j-1] + w2*pixel[i+1][j-1] + * + w1*pixel[i-1][j] + w0*pixel[i][j] + w1*pixel[i+1][j] + * + w2*pixel[i-1][j+1] + w1*pixel[i][j+1] + w2*pixel[i+1][j+1]; + */ + vg_lite_error_t vg_lite_gaussian_filter(vg_lite_float_t w0, vg_lite_float_t w1, vg_lite_float_t w2); + + /* Enable masklayer function. Masklayer is OFF by default. */ + vg_lite_error_t vg_lite_enable_masklayer(void); + + /* Disable masklayer function. Masklayer is OFF by default. */ + vg_lite_error_t vg_lite_disable_masklayer(void); + + /* Setup a masklayer. */ + vg_lite_error_t vg_lite_set_masklayer(vg_lite_buffer_t *masklayer); + + /* Free a masklayer and disable mask operation. */ + vg_lite_error_t vg_lite_destroy_masklayer(vg_lite_buffer_t *masklayer); + + /* Create a masklayer with default format A8 and default pixel value 255. */ + vg_lite_error_t vg_lite_create_masklayer(vg_lite_buffer_t *masklayer, + vg_lite_uint32_t width, + vg_lite_uint32_t height); + + /* Set pixel values for a rectangle area in a masklayer */ + vg_lite_error_t vg_lite_fill_masklayer(vg_lite_buffer_t *masklayer, + vg_lite_rectangle_t *rect, + vg_lite_uint8_t value); + + /* Blend a rectangle area of src masklayer with dst masklayer according to (operation). */ + vg_lite_error_t vg_lite_blend_masklayer(vg_lite_buffer_t *dst, + vg_lite_buffer_t *src, + vg_lite_mask_operation_t operation, + vg_lite_rectangle_t *rect); + + /* Render a (path) with (fill_rule), (color), (matrix) to the masklayer. */ + vg_lite_error_t vg_lite_render_masklayer(vg_lite_buffer_t *masklayer, + vg_lite_mask_operation_t operation, + vg_lite_path_t *path, + vg_lite_fill_t fill_rule, + vg_lite_color_t color, + vg_lite_matrix_t *matrix); + + /* Set mirror orientation. */ + vg_lite_error_t vg_lite_set_mirror(vg_lite_orientation_t orientation); + + /* Set gamma value. */ + vg_lite_error_t vg_lite_set_gamma(vg_lite_gamma_conversion_t gamma_value); + + /* Enable color transformation, which is OFF by default. */ + vg_lite_error_t vg_lite_enable_color_transform(void); + + /* Disable color transformation, which is OFF by default. */ + vg_lite_error_t vg_lite_disable_color_transform(void); + + /* Set pixel color transformation scale and bias values for each pixel channel. */ + vg_lite_error_t vg_lite_set_color_transform(vg_lite_color_transform_t *values); + + /* Set flexa stream id. */ + vg_lite_error_t vg_lite_flexa_set_stream(vg_lite_uint8_t stream_id); + + /* set flexa background buffer.*/ + vg_lite_error_t vg_lite_flexa_bg_buffer(vg_lite_uint8_t stream_id, + vg_lite_buffer_t *buffer, + vg_lite_uint32_t seg_count, + vg_lite_uint32_t seg_size); + + /* Enable flexa. */ + vg_lite_error_t vg_lite_flexa_enable(void); + + /* Disable flexa.*/ + vg_lite_error_t vg_lite_flexa_disable(void); + + /* Set flexa stop flag after the last frame. */ + vg_lite_error_t vg_lite_flexa_stop_frame(void); + + /* Dump command buffer */ + vg_lite_error_t vg_lite_dump_command_buffer(void); + + /* Return VGLite parameters in params[] array */ + vg_lite_error_t vg_lite_get_parameter(vg_lite_param_type_t type, + vg_lite_int32_t count, + vg_lite_float_t* params); + +#endif /* VGLITE_VERSION_3_0 */ + +#ifdef __cplusplus +} +#endif +#endif /* _vg_lite_h_ */ \ No newline at end of file diff --git a/lib/libesp32_lvgl/lvgl/src/others/vg_lite_tvg/vg_lite_matrix.c b/lib/libesp32_lvgl/lvgl/src/others/vg_lite_tvg/vg_lite_matrix.c new file mode 100644 index 000000000..a152fca9e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/others/vg_lite_tvg/vg_lite_matrix.c @@ -0,0 +1,162 @@ +/** + * @file vg_lite_matrix.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_USE_DRAW_VG_LITE && LV_USE_VG_LITE_THORVG + +#include +#include +#include "vg_lite.h" + +/********************* + * DEFINES + *********************/ + +#define VG_SW_BLIT_PRECISION_OPT 1 + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +vg_lite_error_t vg_lite_identity(vg_lite_matrix_t * matrix) +{ + /* Set identify matrix. */ + matrix->m[0][0] = 1.0f; + matrix->m[0][1] = 0.0f; + matrix->m[0][2] = 0.0f; + matrix->m[1][0] = 0.0f; + matrix->m[1][1] = 1.0f; + matrix->m[1][2] = 0.0f; + matrix->m[2][0] = 0.0f; + matrix->m[2][1] = 0.0f; + matrix->m[2][2] = 1.0f; + +#if VG_SW_BLIT_PRECISION_OPT + matrix->scaleX = 1.0f; + matrix->scaleY = 1.0f; + matrix->angle = 0.0f; +#endif /* VG_SW_BLIT_PRECISION_OPT */ + + return VG_LITE_SUCCESS; +} + +static void multiply(vg_lite_matrix_t * matrix, vg_lite_matrix_t * mult) +{ + vg_lite_matrix_t temp; + int row, column; + + /* Process all rows. */ + for(row = 0; row < 3; row++) { + /* Process all columns. */ + for(column = 0; column < 3; column++) { + /* Compute matrix entry. */ + temp.m[row][column] = (matrix->m[row][0] * mult->m[0][column]) + + (matrix->m[row][1] * mult->m[1][column]) + + (matrix->m[row][2] * mult->m[2][column]); + } + } + + /* Copy temporary matrix into result. */ +#if VG_SW_BLIT_PRECISION_OPT + memcpy(matrix, &temp, sizeof(vg_lite_float_t) * 9); +#else + memcpy(matrix, &temp, sizeof(temp)); +#endif /* VG_SW_BLIT_PRECISION_OPT */ +} + +vg_lite_error_t vg_lite_translate(vg_lite_float_t x, vg_lite_float_t y, vg_lite_matrix_t * matrix) +{ + /* Set translation matrix. */ + vg_lite_matrix_t t = { { {1.0f, 0.0f, x}, + {0.0f, 1.0f, y}, + {0.0f, 0.0f, 1.0f}, + }, + 0.0f, 0.0f, 0.0f + }; + + /* Multiply with current matrix. */ + multiply(matrix, &t); + + return VG_LITE_SUCCESS; +} + +vg_lite_error_t vg_lite_scale(vg_lite_float_t scale_x, vg_lite_float_t scale_y, vg_lite_matrix_t * matrix) +{ + /* Set scale matrix. */ + vg_lite_matrix_t s = { { {scale_x, 0.0f, 0.0f}, + {0.0f, scale_y, 0.0f}, + {0.0f, 0.0f, 1.0f}, + }, + 0.0f, 0.0f, 0.0f + }; + + /* Multiply with current matrix. */ + multiply(matrix, &s); + +#if VG_SW_BLIT_PRECISION_OPT + matrix->scaleX = matrix->scaleX * scale_x; + matrix->scaleY = matrix->scaleY * scale_y; +#endif /* VG_SW_BLIT_PRECISION_OPT */ + + return VG_LITE_SUCCESS; +} + +vg_lite_error_t vg_lite_rotate(vg_lite_float_t degrees, vg_lite_matrix_t * matrix) +{ + /* Convert degrees into radians. */ + vg_lite_float_t angle = (degrees / 180.0f) * 3.141592654f; + + /* Compuet cosine and sine values. */ + vg_lite_float_t cos_angle = cosf(angle); + vg_lite_float_t sin_angle = sinf(angle); + + /* Set rotation matrix. */ + vg_lite_matrix_t r = { { {cos_angle, -sin_angle, 0.0f}, + {sin_angle, cos_angle, 0.0f}, + {0.0f, 0.0f, 1.0f}, + }, + 0.0f, 0.0f, 0.0f + }; + + /* Multiply with current matrix. */ + multiply(matrix, &r); + +#if VG_SW_BLIT_PRECISION_OPT + matrix->angle = matrix->angle + degrees; + if(matrix->angle >= 360) { + vg_lite_uint32_t count = (vg_lite_uint32_t)matrix->angle / 360; + matrix->angle = matrix->angle - count * 360; + } +#endif /* VG_SW_BLIT_PRECISION_OPT */ + + return VG_LITE_SUCCESS; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_USE_VG_LITE_THORVG*/ \ No newline at end of file diff --git a/lib/libesp32_lvgl/lvgl/src/others/vg_lite_tvg/vg_lite_tvg.cpp b/lib/libesp32_lvgl/lvgl/src/others/vg_lite_tvg/vg_lite_tvg.cpp new file mode 100644 index 000000000..0daa28fa1 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/others/vg_lite_tvg/vg_lite_tvg.cpp @@ -0,0 +1,2407 @@ +/** + * @file vg_lite_tvg.cpp + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" +#if LV_USE_DRAW_VG_LITE && LV_USE_VG_LITE_THORVG + +#include "vg_lite.h" +#include "../../lvgl.h" +#include "../../libs/thorvg/thorvg.h" +#include +#include +#include +#include +#include +#include + +#if LV_VG_LITE_THORVG_YUV_SUPPORT + #include +#endif + +/********************* + * DEFINES + *********************/ + +#ifndef LV_VG_LITE_THORVG_BUF_ADDR_ALIGN + #define LV_VG_LITE_THORVG_BUF_ADDR_ALIGN 64 +#endif + +#define TVG_CANVAS_ENGINE CanvasEngine::Sw +#define TVG_COLOR(COLOR) B(COLOR), G(COLOR), R(COLOR), A(COLOR) +#define TVG_IS_VG_FMT_SUPPORT(fmt) ((fmt) == VG_LITE_BGRA8888 || (fmt) == VG_LITE_BGRX8888) + +#define TVG_CHECK_RETURN_VG_ERROR(FUNC) \ + do { \ + Result res = FUNC; \ + if (res != Result::Success) { \ + LV_LOG_ERROR("Executed '" #FUNC "' error: %d", (int)res); \ + return vg_lite_error_conv(res); \ + } \ + } while (0) +#define TVG_CHECK_RETURN_RESULT(FUNC) \ + do { \ + Result res = FUNC; \ + if (res != Result::Success) { \ + LV_LOG_ERROR("Executed '" #FUNC "' error: %d", (int)res);\ + return res; \ + } \ + } while (0) + +/* clang-format off */ + +#define IS_INDEX_FMT(fmt) \ + ((fmt) == VG_LITE_INDEX_1 \ + || (fmt) == VG_LITE_INDEX_2 \ + || (fmt) == VG_LITE_INDEX_4 \ + || (fmt) == VG_LITE_INDEX_8) + +#define VLC_GET_ARG(CUR, INDEX) vlc_get_arg((cur + (INDEX) * fmt_len), path->format); +#define VLC_GET_OP_CODE(ptr) (*((uint8_t*)ptr)) +#define VLC_OP_ARG_LEN(OP, LEN) \ + case VLC_OP_##OP: \ + return (LEN) + +#define A(color) ((color) >> 24) +#define R(color) (((color) & 0x00ff0000) >> 16) +#define G(color) (((color) & 0x0000ff00) >> 8) +#define B(color) ((color) & 0xff) +#define ARGB(a, r, g, b) ((a) << 24) | ((r) << 16) | ((g) << 8) | (b) +#define MIN(a, b) (a) > (b) ? (b) : (a) +#define MAX(a, b) (a) > (b) ? (a) : (b) +#define UDIV255(x) (((x) * 0x8081U) >> 0x17) +#define LERP(v1, v2, w) ((v1) * (w) + (v2) * (1.0f - (w))) +#define CLAMP(x, min, max) (((x) < (min)) ? (min) : ((x) > (max)) ? (max) : (x)) +#define COLOR_FROM_RAMP(ColorRamp) (((vg_lite_float_t*)ColorRamp) + 1) + +#define VG_LITE_RETURN_ERROR(func) \ + if ((error = func) != VG_LITE_SUCCESS) \ + return error + +#define VG_LITE_ALIGN(number, align_bytes) \ + (((number) + ((align_bytes)-1)) & ~((align_bytes)-1)) + +#define VG_LITE_IS_ALIGNED(num, align) (((uintptr_t)(num) & ((align)-1)) == 0) + +#define VG_LITE_IS_ALPHA_FORMAT(format) \ + ((format) == VG_LITE_A8 || (format) == VG_LITE_A4) + +/* clang-format on */ + +/********************** + * TYPEDEFS + **********************/ + +using namespace tvg; + +#pragma pack(1) +typedef struct { + uint8_t blue; + uint8_t green; + uint8_t red; +} vg_color24_t; + +typedef struct { + uint16_t blue : 5; + uint16_t green : 6; + uint16_t red : 5; +} vg_color16_t; + +typedef struct { + vg_color16_t c; + uint8_t alpha; +} vg_color16_alpha_t; + +typedef struct { + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t alpha; +} vg_color32_t; + +#pragma pack() + +class vg_lite_ctx +{ + public: + std::unique_ptr canvas; + void * target_buffer; + vg_lite_uint32_t target_px_size; + vg_lite_buffer_format_t target_format; + + public: + vg_lite_ctx() + : target_buffer { nullptr } + , target_px_size { 0 } + , target_format { VG_LITE_BGRA8888 } + , clut_2colors { 0 } + , clut_4colors { 0 } + , clut_16colors { 0 } + , clut_256colors { 0 } + { + canvas = SwCanvas::gen(); + } + + vg_lite_uint32_t * get_image_buffer(vg_lite_uint32_t w, vg_lite_uint32_t h) + { + src_buffer.resize(w * h); + return src_buffer.data(); + } + + vg_lite_uint32_t * get_temp_target_buffer(vg_lite_uint32_t w, vg_lite_uint32_t h) + { + vg_lite_uint32_t px_size = w * h; + if(px_size > dest_buffer.size()) { + + /* During resize, the first address of the vector may change + * to ensure that there is no unfinished drawing. + */ + LV_ASSERT(target_buffer == nullptr); + dest_buffer.resize(w * h); + } + return dest_buffer.data(); + } + + vg_lite_uint32_t * get_temp_target_buffer() + { + return dest_buffer.data(); + } + + void set_CLUT(vg_lite_uint32_t count, const vg_lite_uint32_t * colors) + { + switch(count) { + case 2: + memcpy(clut_2colors, colors, sizeof(clut_2colors)); + break; + case 4: + memcpy(clut_4colors, colors, sizeof(clut_4colors)); + break; + case 16: + memcpy(clut_16colors, colors, sizeof(clut_16colors)); + break; + case 256: + memcpy(clut_256colors, colors, sizeof(clut_256colors)); + break; + default: + LV_ASSERT(false); + break; + } + } + + const vg_lite_uint32_t * get_CLUT(vg_lite_buffer_format_t format) + { + switch(format) { + case VG_LITE_INDEX_1: + return clut_2colors; + + case VG_LITE_INDEX_2: + return clut_2colors; + + case VG_LITE_INDEX_4: + return clut_4colors; + + case VG_LITE_INDEX_8: + return clut_256colors; + + default: + break; + } + + LV_ASSERT(false); + return nullptr; + } + + static vg_lite_ctx * get_instance() + { + static vg_lite_ctx instance; + return &instance; + } + + private: + /* */ + std::vector src_buffer; + std::vector dest_buffer; + + vg_lite_uint32_t clut_2colors[2]; + vg_lite_uint32_t clut_4colors[4]; + vg_lite_uint32_t clut_16colors[16]; + vg_lite_uint32_t clut_256colors[256]; +}; + +template +class vg_lite_converter +{ + public: + typedef void (*converter_cb_t)(DEST_TYPE * dest, const SRC_TYPE * src, vg_lite_uint32_t px_size, + vg_lite_uint32_t color); + + public: + vg_lite_converter(converter_cb_t converter) + : _converter_cb(converter) + { + } + + void convert(vg_lite_buffer_t * dest_buf, const vg_lite_buffer_t * src_buf, vg_lite_uint32_t color = 0) + { + LV_ASSERT(_converter_cb); + uint8_t * dest = (uint8_t *)dest_buf->memory; + const uint8_t * src = (const uint8_t *)src_buf->memory; + vg_lite_uint32_t h = src_buf->height; + + while(h--) { + _converter_cb((DEST_TYPE *)dest, (const SRC_TYPE *)src, src_buf->width, color); + dest += dest_buf->stride; + src += src_buf->stride; + } + } + + private: + converter_cb_t _converter_cb; +}; + +typedef vg_lite_float_t FLOATVECTOR4[4]; + +/********************** + * STATIC PROTOTYPES + **********************/ + +static vg_lite_error_t vg_lite_error_conv(Result result); +static Matrix matrix_conv(const vg_lite_matrix_t * matrix); +static FillRule fill_rule_conv(vg_lite_fill_t fill); +static BlendMethod blend_method_conv(vg_lite_blend_t blend); +static Result shape_append_path(std::unique_ptr & shape, vg_lite_path_t * path, vg_lite_matrix_t * matrix); +static Result shape_append_rect(std::unique_ptr & shape, const vg_lite_buffer_t * target, + const vg_lite_rectangle_t * rect); +static Result canvas_set_target(vg_lite_ctx * ctx, vg_lite_buffer_t * target); +static Result picture_load(vg_lite_ctx * ctx, std::unique_ptr & picture, const vg_lite_buffer_t * source, + vg_lite_color_t color = 0); + +static inline bool math_zero(float a) +{ + return (fabs(a) < FLT_EPSILON); +} + +static inline bool math_equal(float a, float b) +{ + return math_zero(a - b); +} + +static void ClampColor(FLOATVECTOR4 Source, FLOATVECTOR4 Target, uint8_t Premultiplied); +static uint8_t PackColorComponent(vg_lite_float_t value); +static void get_format_bytes(vg_lite_buffer_format_t format, + vg_lite_uint32_t * mul, + vg_lite_uint32_t * div, + vg_lite_uint32_t * bytes_align); + +/********************** + * STATIC VARIABLES + **********************/ + +/* color converters */ + +static vg_lite_converter conv_bgra8888_to_bgr565( + [](vg_color16_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */) +{ + while(px_size--) { + dest->red = src->red >> 3; + dest->green = src->green >> 2; + dest->blue = src->blue >> 3; + src++; + dest++; + } +}); + +static vg_lite_converter conv_bgra8888_to_bgra5658( + [](vg_color16_alpha_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */) +{ + while(px_size--) { + dest->c.red = src->red >> 3; + dest->c.green = src->green >> 2; + dest->c.blue = src->blue >> 3; + dest->alpha = src->alpha; + src++; + dest++; + } +}); + +static vg_lite_converter conv_bgr565_to_bgra8888( + [](vg_color32_t * dest, const vg_color16_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */) +{ + while(px_size--) { + dest->red = src->red << 3; + dest->green = src->green << 2; + dest->blue = src->blue << 3; + dest->alpha = 0xFF; + src++; + dest++; + } +}); + +static vg_lite_converter conv_bgra5658_to_bgra8888( + [](vg_color32_t * dest, const vg_color16_alpha_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */) +{ + while(px_size--) { + dest->red = src->c.red << 3; + dest->green = src->c.green << 2; + dest->blue = src->c.blue << 3; + dest->alpha = src->alpha; + src++; + dest++; + } +}); + +static vg_lite_converter conv_bgrx8888_to_bgra8888( + [](vg_color32_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */) +{ + while(px_size--) { + *dest = *src; + dest->alpha = 0xFF; + dest++; + src++; + } +}); + +static vg_lite_converter conv_bgr888_to_bgra8888( + [](vg_color32_t * dest, const vg_color24_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t /* color */) +{ + while(px_size--) { + dest->red = src->red; + dest->green = src->green; + dest->blue = src->blue; + dest->alpha = 0xFF; + src++; + dest++; + } +}); + +static vg_lite_converter conv_alpha8_to_bgra8888( + [](vg_color32_t * dest, const uint8_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t color) +{ + while(px_size--) { + uint8_t alpha = *src; + dest->alpha = alpha; + dest->red = UDIV255(B(color) * alpha); + dest->green = UDIV255(G(color) * alpha); + dest->blue = UDIV255(R(color) * alpha); + dest++; + src++; + } +}); + +static vg_lite_converter conv_alpha4_to_bgra8888( + [](vg_color32_t * dest, const uint8_t * src, vg_lite_uint32_t px_size, vg_lite_uint32_t color) +{ + /* 1 byte -> 2 px */ + px_size /= 2; + + while(px_size--) { + /* high 4bit */ + uint8_t alpha = (*src & 0xF0); + dest->alpha = alpha; + dest->red = UDIV255(B(color) * alpha); + dest->green = UDIV255(G(color) * alpha); + dest->blue = UDIV255(R(color) * alpha); + dest++; + + /* low 4bit */ + alpha = (*src & 0x0F) << 4; + dest->alpha = alpha; + dest->red = UDIV255(B(color) * alpha); + dest->green = UDIV255(G(color) * alpha); + dest->blue = UDIV255(R(color) * alpha); + + dest++; + src++; + } +}); + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +extern "C" { + + void gpu_init(void) + { + vg_lite_init(0, 0); + } + + vg_lite_error_t vg_lite_allocate(vg_lite_buffer_t * buffer) + { + if(buffer->format == VG_LITE_RGBA8888_ETC2_EAC && (buffer->width % 16 || buffer->height % 4)) { + return VG_LITE_INVALID_ARGUMENT; + } + + /* Reset planar. */ + buffer->yuv.uv_planar = buffer->yuv.v_planar = buffer->yuv.alpha_planar = 0; + + /* Align height in case format is tiled. */ + if(buffer->format >= VG_LITE_YUY2 && buffer->format <= VG_LITE_NV16) { + buffer->height = VG_LITE_ALIGN(buffer->height, 4); + buffer->yuv.swizzle = VG_LITE_SWIZZLE_UV; + } + + if(buffer->format >= VG_LITE_YUY2_TILED && buffer->format <= VG_LITE_AYUY2_TILED) { + buffer->height = VG_LITE_ALIGN(buffer->height, 4); + buffer->tiled = VG_LITE_TILED; + buffer->yuv.swizzle = VG_LITE_SWIZZLE_UV; + } + + vg_lite_uint32_t mul, div, align; + get_format_bytes(buffer->format, &mul, &div, &align); + vg_lite_uint32_t stride = VG_LITE_ALIGN((buffer->width * mul / div), align); + + buffer->stride = stride; + buffer->memory = aligned_alloc(LV_VG_LITE_THORVG_BUF_ADDR_ALIGN, stride * buffer->height); + LV_ASSERT(buffer->memory); + buffer->address = (vg_lite_uint32_t)(uintptr_t)buffer->memory; + buffer->handle = buffer->memory; + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_free(vg_lite_buffer_t * buffer) + { + LV_ASSERT(buffer->memory); + free(buffer->memory); + memset(buffer, 0, sizeof(vg_lite_buffer_t)); + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_upload_buffer(vg_lite_buffer_t * buffer, vg_lite_uint8_t * data[3], vg_lite_uint32_t stride[3]) + { + LV_UNUSED(buffer); + LV_UNUSED(data); + LV_UNUSED(stride); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_map(vg_lite_buffer_t * buffer, vg_lite_map_flag_t flag, int32_t fd) + { + LV_UNUSED(buffer); + LV_UNUSED(flag); + LV_UNUSED(fd); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_unmap(vg_lite_buffer_t * buffer) + { + LV_UNUSED(buffer); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_clear(vg_lite_buffer_t * target, vg_lite_rectangle_t * rectangle, vg_lite_color_t color) + { + auto ctx = vg_lite_ctx::get_instance(); + TVG_CHECK_RETURN_VG_ERROR(canvas_set_target(ctx, target)); + + auto shape = Shape::gen(); + TVG_CHECK_RETURN_VG_ERROR(shape_append_rect(shape, target, rectangle)); + TVG_CHECK_RETURN_VG_ERROR(shape->fill(TVG_COLOR(color))); + TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(shape))); + + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_blit(vg_lite_buffer_t * target, + vg_lite_buffer_t * source, + vg_lite_matrix_t * matrix, + vg_lite_blend_t blend, + vg_lite_color_t color, + vg_lite_filter_t filter) + { + LV_UNUSED(filter); + auto ctx = vg_lite_ctx::get_instance(); + canvas_set_target(ctx, target); + + auto picture = Picture::gen(); + + TVG_CHECK_RETURN_VG_ERROR(picture_load(ctx, picture, source, color)); + TVG_CHECK_RETURN_VG_ERROR(picture->transform(matrix_conv(matrix))); + TVG_CHECK_RETURN_VG_ERROR(picture->blend(blend_method_conv(blend))); + TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(picture))); + + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_blit2(vg_lite_buffer_t * target, + vg_lite_buffer_t * source0, + vg_lite_buffer_t * source1, + vg_lite_matrix_t * matrix0, + vg_lite_matrix_t * matrix1, + vg_lite_blend_t blend, + vg_lite_filter_t filter) + { + if(!vg_lite_query_feature(gcFEATURE_BIT_VG_DOUBLE_IMAGE)) { + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t error; + + VG_LITE_RETURN_ERROR(vg_lite_blit(target, source0, matrix0, blend, 0, filter)); + VG_LITE_RETURN_ERROR(vg_lite_blit(target, source1, matrix1, blend, 0, filter)); + + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_blit_rect(vg_lite_buffer_t * target, + vg_lite_buffer_t * source, + vg_lite_rectangle_t * rect, + vg_lite_matrix_t * matrix, + vg_lite_blend_t blend, + vg_lite_color_t color, + vg_lite_filter_t filter) + { + LV_UNUSED(filter); + auto ctx = vg_lite_ctx::get_instance(); + TVG_CHECK_RETURN_VG_ERROR(canvas_set_target(ctx, target)); + + auto shape = Shape::gen(); + TVG_CHECK_RETURN_VG_ERROR(shape_append_rect(shape, target, rect)); + TVG_CHECK_RETURN_VG_ERROR(shape->transform(matrix_conv(matrix))); + + auto picture = tvg::Picture::gen(); + TVG_CHECK_RETURN_VG_ERROR(picture_load(ctx, picture, source, color)); + TVG_CHECK_RETURN_VG_ERROR(picture->transform(matrix_conv(matrix))); + TVG_CHECK_RETURN_VG_ERROR(picture->blend(blend_method_conv(blend))); + TVG_CHECK_RETURN_VG_ERROR(picture->composite(std::move(shape), CompositeMethod::ClipPath)); + TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(picture))); + + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_init(int32_t tessellation_width, int32_t tessellation_height) + { + LV_UNUSED(tessellation_width); + LV_UNUSED(tessellation_height); +#if LV_VG_LITE_THORVG_THREAD_RENDER + /* Threads Count */ + auto threads = std::thread::hardware_concurrency(); + if(threads > 0) { + --threads; /* Allow the designated main thread capacity */ + } +#endif + + /* Initialize ThorVG Engine */ + TVG_CHECK_RETURN_VG_ERROR(Initializer::init(TVG_CANVAS_ENGINE, 0)); + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_close(void) + { + TVG_CHECK_RETURN_VG_ERROR(Initializer::term(TVG_CANVAS_ENGINE)); + return VG_LITE_SUCCESS; + } + + static void picture_bgra8888_to_bgr565(vg_color16_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size) + { + while(px_size--) { + dest->red = src->red >> 3; + dest->green = src->green >> 2; + dest->blue = src->blue >> 3; + src++; + dest++; + } + } + + static void picture_bgra8888_to_bgra5658(vg_color16_alpha_t * dest, const vg_color32_t * src, vg_lite_uint32_t px_size) + { + while(px_size--) { + dest->c.red = src->red >> 3; + dest->c.green = src->green >> 2; + dest->c.blue = src->blue >> 3; + dest->alpha = src->alpha; + src++; + dest++; + } + } + + vg_lite_error_t vg_lite_finish(void) + { + vg_lite_ctx * ctx = vg_lite_ctx::get_instance(); + + if(ctx->canvas->draw() == Result::InsufficientCondition) { + return VG_LITE_SUCCESS; + } + + TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->sync()); + TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->clear(true)); + + /* If target_buffer is not in a format supported by thorvg, software conversion is required. */ + if(ctx->target_buffer) { + switch(ctx->target_format) { + case VG_LITE_BGR565: + picture_bgra8888_to_bgr565( + (vg_color16_t *)ctx->target_buffer, + (const vg_color32_t *)ctx->get_temp_target_buffer(), + ctx->target_px_size); + break; + case VG_LITE_BGRA5658: + picture_bgra8888_to_bgra5658( + (vg_color16_alpha_t *)ctx->target_buffer, + (const vg_color32_t *)ctx->get_temp_target_buffer(), + ctx->target_px_size); + break; + default: + LV_LOG_ERROR("unsupported format: %d", ctx->target_format); + LV_ASSERT(false); + break; + } + + /* finish convert, clean target buffer info */ + ctx->target_buffer = nullptr; + ctx->target_px_size = 0; + } + + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_flush(void) + { + return vg_lite_finish(); + } + + vg_lite_error_t vg_lite_draw(vg_lite_buffer_t * target, + vg_lite_path_t * path, + vg_lite_fill_t fill_rule, + vg_lite_matrix_t * matrix, + vg_lite_blend_t blend, + vg_lite_color_t color) + { + auto ctx = vg_lite_ctx::get_instance(); + TVG_CHECK_RETURN_VG_ERROR(canvas_set_target(ctx, target)); + + auto shape = Shape::gen(); + TVG_CHECK_RETURN_VG_ERROR(shape_append_path(shape, path, matrix)); + TVG_CHECK_RETURN_VG_ERROR(shape->transform(matrix_conv(matrix))); + TVG_CHECK_RETURN_VG_ERROR(shape->fill(fill_rule_conv(fill_rule));); + TVG_CHECK_RETURN_VG_ERROR(shape->blend(blend_method_conv(blend))); + TVG_CHECK_RETURN_VG_ERROR(shape->fill(TVG_COLOR(color))); + TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(shape))); + + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_get_register(vg_lite_uint32_t address, vg_lite_uint32_t * result) + { + LV_UNUSED(address); + LV_UNUSED(result); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_get_info(vg_lite_info_t * info) + { + info->api_version = VGLITE_API_VERSION_3_0; + info->header_version = VGLITE_HEADER_VERSION; + info->release_version = VGLITE_RELEASE_VERSION; + info->reserved = 0; + return VG_LITE_SUCCESS; + } + + vg_lite_uint32_t vg_lite_get_product_info(char * name, vg_lite_uint32_t * chip_id, vg_lite_uint32_t * chip_rev) + { + strcpy(name, "GCNanoLiteV"); + *chip_id = 0x265; + *chip_rev = 0x2000; + return 1; + } + + vg_lite_uint32_t vg_lite_query_feature(vg_lite_feature_t feature) + { + switch(feature) { + case gcFEATURE_BIT_VG_IM_INDEX_FORMAT: + case gcFEATURE_BIT_VG_SCISSOR: + case gcFEATURE_BIT_VG_BORDER_CULLING: + case gcFEATURE_BIT_VG_RGBA2_FORMAT: + case gcFEATURE_BIT_VG_IM_FASTCLAER: + case gcFEATURE_BIT_VG_GLOBAL_ALPHA: + case gcFEATURE_BIT_VG_COLOR_KEY: + case gcFEATURE_BIT_VG_24BIT: + case gcFEATURE_BIT_VG_DITHER: + case gcFEATURE_BIT_VG_USE_DST: + +#if LV_VG_LITE_THORVG_LVGL_BLEND_SUPPORT + case gcFEATURE_BIT_VG_LVGL_SUPPORT: +#endif + +#if LV_VG_LITE_THORVG_YUV_SUPPORT + case gcFEATURE_BIT_VG_YUV_INPUT: +#endif + +#if LV_VG_LITE_THORVG_16PIXELS_ALIGN + case gcFEATURE_BIT_VG_16PIXELS_ALIGN: +#endif + return 1; + default: + break; + } + return 0; + } + + vg_lite_error_t vg_lite_init_path(vg_lite_path_t * path, + vg_lite_format_t data_format, + vg_lite_quality_t quality, + vg_lite_uint32_t path_length, + void * path_data, + vg_lite_float_t min_x, vg_lite_float_t min_y, + vg_lite_float_t max_x, vg_lite_float_t max_y) + { + if(!path) { + return VG_LITE_INVALID_ARGUMENT; + } + + path->format = data_format; + path->quality = quality; + path->bounding_box[0] = min_x; + path->bounding_box[1] = min_y; + path->bounding_box[2] = max_x; + path->bounding_box[3] = max_y; + + path->path_length = path_length; + path->path = path_data; + + path->path_changed = 1; + path->uploaded.address = 0; + path->uploaded.bytes = 0; + path->uploaded.handle = NULL; + path->uploaded.memory = NULL; + path->pdata_internal = 0; + + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_init_arc_path(vg_lite_path_t * path, + vg_lite_format_t data_format, + vg_lite_quality_t quality, + vg_lite_uint32_t path_length, + void * path_data, + vg_lite_float_t min_x, vg_lite_float_t min_y, + vg_lite_float_t max_x, vg_lite_float_t max_y) + { + LV_UNUSED(path); + LV_UNUSED(data_format); + LV_UNUSED(quality); + LV_UNUSED(path_length); + LV_UNUSED(path_data); + LV_UNUSED(min_x); + LV_UNUSED(min_y); + LV_UNUSED(max_x); + LV_UNUSED(max_y); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_clear_path(vg_lite_path_t * path) + { + LV_UNUSED(path); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_uint32_t vg_lite_get_path_length(vg_lite_uint8_t * opcode, + vg_lite_uint32_t count, + vg_lite_format_t format) + { + LV_UNUSED(opcode); + LV_UNUSED(count); + LV_UNUSED(format); + return 0; + } + + vg_lite_error_t vg_lite_append_path(vg_lite_path_t * path, + uint8_t * cmd, + void * data, + vg_lite_uint32_t seg_count) + { + LV_UNUSED(path); + LV_UNUSED(cmd); + LV_UNUSED(data); + LV_UNUSED(seg_count); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_upload_path(vg_lite_path_t * path) + { + LV_UNUSED(path); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_set_CLUT(vg_lite_uint32_t count, + vg_lite_uint32_t * colors) + { + if(!vg_lite_query_feature(gcFEATURE_BIT_VG_IM_INDEX_FORMAT)) { + return VG_LITE_NOT_SUPPORT; + } + LV_ASSERT(colors); + + auto ctx = vg_lite_ctx::get_instance(); + ctx->set_CLUT(count, colors); + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_draw_pattern(vg_lite_buffer_t * target, + vg_lite_path_t * path, + vg_lite_fill_t fill_rule, + vg_lite_matrix_t * path_matrix, + vg_lite_buffer_t * pattern_image, + vg_lite_matrix_t * pattern_matrix, + vg_lite_blend_t blend, + vg_lite_pattern_mode_t pattern_mode, + vg_lite_color_t pattern_color, + vg_lite_color_t color, + vg_lite_filter_t filter) + { + LV_UNUSED(pattern_mode); + LV_UNUSED(pattern_color); + LV_UNUSED(filter); + + auto ctx = vg_lite_ctx::get_instance(); + TVG_CHECK_RETURN_VG_ERROR(canvas_set_target(ctx, target)); + + auto shape = Shape::gen(); + TVG_CHECK_RETURN_VG_ERROR(shape_append_path(shape, path, path_matrix)); + TVG_CHECK_RETURN_VG_ERROR(shape->fill(fill_rule_conv(fill_rule))); + TVG_CHECK_RETURN_VG_ERROR(shape->transform(matrix_conv(path_matrix))); + + auto picture = tvg::Picture::gen(); + TVG_CHECK_RETURN_VG_ERROR(picture_load(ctx, picture, pattern_image, color)); + TVG_CHECK_RETURN_VG_ERROR(picture->transform(matrix_conv(pattern_matrix))); + TVG_CHECK_RETURN_VG_ERROR(picture->blend(blend_method_conv(blend))); + TVG_CHECK_RETURN_VG_ERROR(picture->composite(std::move(shape), CompositeMethod::ClipPath)); + TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(picture))); + + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_init_grad(vg_lite_linear_gradient_t * grad) + { + vg_lite_error_t error = VG_LITE_SUCCESS; + + /* Set the member values according to driver defaults. */ + grad->image.width = VLC_GRADIENT_BUFFER_WIDTH; + grad->image.height = 1; + grad->image.stride = 0; + grad->image.format = VG_LITE_BGRA8888; + + /* Allocate the image for gradient. */ + error = vg_lite_allocate(&grad->image); + + grad->count = 0; + + return error; + } + + vg_lite_error_t vg_lite_set_linear_grad(vg_lite_ext_linear_gradient_t * grad, + vg_lite_uint32_t count, + vg_lite_color_ramp_t * color_ramp, + vg_lite_linear_gradient_parameter_t linear_gradient, + vg_lite_gradient_spreadmode_t spread_mode, + vg_lite_uint8_t pre_multiplied) + { + static vg_lite_color_ramp_t default_ramp[] = { + { + 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }, + { + 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f + } + }; + + vg_lite_uint32_t i, trg_count; + vg_lite_float_t prev_stop; + vg_lite_color_ramp_t * src_ramp; + vg_lite_color_ramp_t * src_ramp_last; + vg_lite_color_ramp_t * trg_ramp; + + /* Reset the count. */ + trg_count = 0; + + if((linear_gradient.X0 == linear_gradient.X1) && (linear_gradient.Y0 == linear_gradient.Y1)) + return VG_LITE_INVALID_ARGUMENT; + + grad->linear_grad = linear_gradient; + grad->pre_multiplied = pre_multiplied; + grad->spread_mode = spread_mode; + + if(!count || count > VLC_MAX_COLOR_RAMP_STOPS || color_ramp == NULL) + goto Empty_sequence_handler; + + for(i = 0; i < count; i++) + grad->color_ramp[i] = color_ramp[i]; + grad->ramp_length = count; + + /* Determine the last source ramp. */ + src_ramp_last + = grad->color_ramp + + grad->ramp_length; + + /* Set the initial previous stop. */ + prev_stop = -1; + + /* Reset the count. */ + trg_count = 0; + + /* Walk through the source ramp. */ + for( + src_ramp = grad->color_ramp, trg_ramp = grad->converted_ramp; + (src_ramp < src_ramp_last) && (trg_count < VLC_MAX_COLOR_RAMP_STOPS + 2); + src_ramp += 1) { + /* Must be in increasing order. */ + if(src_ramp->stop < prev_stop) { + /* Ignore the entire sequence. */ + trg_count = 0; + break; + } + + /* Update the previous stop value. */ + prev_stop = src_ramp->stop; + + /* Must be within [0..1] range. */ + if((src_ramp->stop < 0.0f) || (src_ramp->stop > 1.0f)) { + /* Ignore. */ + continue; + } + + /* Clamp color. */ + ClampColor(COLOR_FROM_RAMP(src_ramp), COLOR_FROM_RAMP(trg_ramp), 0); + + /* First stop greater then zero? */ + if((trg_count == 0) && (src_ramp->stop > 0.0f)) { + /* Force the first stop to 0.0f. */ + trg_ramp->stop = 0.0f; + + /* Replicate the entry. */ + trg_ramp[1] = *trg_ramp; + trg_ramp[1].stop = src_ramp->stop; + + /* Advance. */ + trg_ramp += 2; + trg_count += 2; + } + else { + /* Set the stop value. */ + trg_ramp->stop = src_ramp->stop; + + /* Advance. */ + trg_ramp += 1; + trg_count += 1; + } + } + + /* Empty sequence? */ + if(trg_count == 0) { + memcpy(grad->converted_ramp, default_ramp, sizeof(default_ramp)); + grad->converted_length = sizeof(default_ramp) / 5; + } + else { + /* The last stop must be at 1.0. */ + if(trg_ramp[-1].stop != 1.0f) { + /* Replicate the last entry. */ + *trg_ramp = trg_ramp[-1]; + + /* Force the last stop to 1.0f. */ + trg_ramp->stop = 1.0f; + + /* Update the final entry count. */ + trg_count += 1; + } + + /* Set new length. */ + grad->converted_length = trg_count; + } + return VG_LITE_SUCCESS; + +Empty_sequence_handler: + memcpy(grad->converted_ramp, default_ramp, sizeof(default_ramp)); + grad->converted_length = sizeof(default_ramp) / 5; + + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_update_linear_grad(vg_lite_ext_linear_gradient_t * grad) + { + vg_lite_uint32_t ramp_length; + vg_lite_color_ramp_t * color_ramp; + vg_lite_uint32_t common, stop; + vg_lite_uint32_t i, width; + uint8_t * bits; + vg_lite_float_t x0, y0, x1, y1, length; + vg_lite_error_t error = VG_LITE_SUCCESS; + + /* Get shortcuts to the color ramp. */ + ramp_length = grad->converted_length; + color_ramp = grad->converted_ramp; + + x0 = grad->linear_grad.X0; + y0 = grad->linear_grad.Y0; + x1 = grad->linear_grad.X1; + y1 = grad->linear_grad.Y1; + length = (vg_lite_float_t)sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); + + if(length <= 0) + return VG_LITE_INVALID_ARGUMENT; + /* Find the common denominator of the color ramp stops. */ + if(length < 1) { + common = 1; + } + else { + common = (vg_lite_uint32_t)length; + } + + for(i = 0; i < ramp_length; ++i) { + if(color_ramp[i].stop != 0.0f) { + vg_lite_float_t mul = common * color_ramp[i].stop; + vg_lite_float_t frac = mul - (vg_lite_float_t)floor(mul); + if(frac > 0.00013f) { /* Suppose error for zero is 0.00013 */ + common = MAX(common, (vg_lite_uint32_t)(1.0f / frac + 0.5f)); + } + } + } + + /* Compute the width of the required color array. */ + width = common + 1; + + /* Allocate the color ramp surface. */ + memset(&grad->image, 0, sizeof(grad->image)); + grad->image.width = width; + grad->image.height = 1; + grad->image.stride = 0; + grad->image.image_mode = VG_LITE_NONE_IMAGE_MODE; + grad->image.format = VG_LITE_ABGR8888; + + /* Allocate the image for gradient. */ + VG_LITE_RETURN_ERROR(vg_lite_allocate(&grad->image)); + memset(grad->image.memory, 0, grad->image.stride * grad->image.height); + width = common + 1; + /* Set pointer to color array. */ + bits = (uint8_t *)grad->image.memory; + + /* Start filling the color array. */ + stop = 0; + for(i = 0; i < width; ++i) { + vg_lite_float_t gradient; + vg_lite_float_t color[4]; + vg_lite_float_t color1[4]; + vg_lite_float_t color2[4]; + vg_lite_float_t weight; + + if(i == 241) + i = 241; + /* Compute gradient for current color array entry. */ + gradient = (vg_lite_float_t)i / (vg_lite_float_t)(width - 1); + + /* Find the entry in the color ramp that matches or exceeds this + ** gradient. */ + while(gradient > color_ramp[stop].stop) { + ++stop; + } + + if(gradient == color_ramp[stop].stop) { + /* Perfect match weight 1.0. */ + weight = 1.0f; + + /* Use color ramp color. */ + color1[3] = color_ramp[stop].alpha; + color1[2] = color_ramp[stop].blue; + color1[1] = color_ramp[stop].green; + color1[0] = color_ramp[stop].red; + + color2[3] = color2[2] = color2[1] = color2[0] = 0.0f; + } + else { + if(stop == 0) { + return VG_LITE_INVALID_ARGUMENT; + } + /* Compute weight. */ + weight = (color_ramp[stop].stop - gradient) + / (color_ramp[stop].stop - color_ramp[stop - 1].stop); + + /* Grab color ramp color of previous stop. */ + color1[3] = color_ramp[stop - 1].alpha; + color1[2] = color_ramp[stop - 1].blue; + color1[1] = color_ramp[stop - 1].green; + color1[0] = color_ramp[stop - 1].red; + + /* Grab color ramp color of current stop. */ + color2[3] = color_ramp[stop].alpha; + color2[2] = color_ramp[stop].blue; + color2[1] = color_ramp[stop].green; + color2[0] = color_ramp[stop].red; + } + + if(grad->pre_multiplied) { + /* Pre-multiply the first color. */ + color1[2] *= color1[3]; + color1[1] *= color1[3]; + color1[0] *= color1[3]; + + /* Pre-multiply the second color. */ + color2[2] *= color2[3]; + color2[1] *= color2[3]; + color2[0] *= color2[3]; + } + + /* Filter the colors per channel. */ + color[3] = LERP(color1[3], color2[3], weight); + color[2] = LERP(color1[2], color2[2], weight); + color[1] = LERP(color1[1], color2[1], weight); + color[0] = LERP(color1[0], color2[0], weight); + + /* Pack the final color. */ + *bits++ = PackColorComponent(color[3]); + *bits++ = PackColorComponent(color[2]); + *bits++ = PackColorComponent(color[1]); + *bits++ = PackColorComponent(color[0]); + } + + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_set_radial_grad(vg_lite_radial_gradient_t * grad, + vg_lite_uint32_t count, + vg_lite_color_ramp_t * color_ramp, + vg_lite_radial_gradient_parameter_t radial_grad, + vg_lite_gradient_spreadmode_t spread_mode, + vg_lite_uint8_t pre_multiplied) + { + static vg_lite_color_ramp_t defaultRamp[] = { + { + 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }, + { + 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f + } + }; + + vg_lite_uint32_t i, trgCount; + vg_lite_float_t prevStop; + vg_lite_color_ramp_t * srcRamp; + vg_lite_color_ramp_t * srcRampLast; + vg_lite_color_ramp_t * trgRamp; + + /* Reset the count. */ + trgCount = 0; + + if(radial_grad.r <= 0) + return VG_LITE_INVALID_ARGUMENT; + + grad->radial_grad = radial_grad; + grad->pre_multiplied = pre_multiplied; + grad->spread_mode = spread_mode; + + if(!count || count > VLC_MAX_COLOR_RAMP_STOPS || color_ramp == NULL) + goto Empty_sequence_handler; + + for(i = 0; i < count; i++) + grad->color_ramp[i] = color_ramp[i]; + grad->ramp_length = count; + + /* Determine the last source ramp. */ + srcRampLast + = grad->color_ramp + + grad->ramp_length; + + /* Set the initial previous stop. */ + prevStop = -1; + + /* Reset the count. */ + trgCount = 0; + + /* Walk through the source ramp. */ + for( + srcRamp = grad->color_ramp, trgRamp = grad->converted_ramp; + (srcRamp < srcRampLast) && (trgCount < VLC_MAX_COLOR_RAMP_STOPS + 2); + srcRamp += 1) { + /* Must be in increasing order. */ + if(srcRamp->stop < prevStop) { + /* Ignore the entire sequence. */ + trgCount = 0; + break; + } + + /* Update the previous stop value. */ + prevStop = srcRamp->stop; + + /* Must be within [0..1] range. */ + if((srcRamp->stop < 0.0f) || (srcRamp->stop > 1.0f)) { + /* Ignore. */ + continue; + } + + /* Clamp color. */ + ClampColor(COLOR_FROM_RAMP(srcRamp), COLOR_FROM_RAMP(trgRamp), 0); + + /* First stop greater then zero? */ + if((trgCount == 0) && (srcRamp->stop > 0.0f)) { + /* Force the first stop to 0.0f. */ + trgRamp->stop = 0.0f; + + /* Replicate the entry. */ + trgRamp[1] = *trgRamp; + trgRamp[1].stop = srcRamp->stop; + + /* Advance. */ + trgRamp += 2; + trgCount += 2; + } + else { + /* Set the stop value. */ + trgRamp->stop = srcRamp->stop; + + /* Advance. */ + trgRamp += 1; + trgCount += 1; + } + } + + /* Empty sequence? */ + if(trgCount == 0) { + memcpy(grad->converted_ramp, defaultRamp, sizeof(defaultRamp)); + grad->converted_length = sizeof(defaultRamp) / 5; + } + else { + /* The last stop must be at 1.0. */ + if(trgRamp[-1].stop != 1.0f) { + /* Replicate the last entry. */ + *trgRamp = trgRamp[-1]; + + /* Force the last stop to 1.0f. */ + trgRamp->stop = 1.0f; + + /* Update the final entry count. */ + trgCount += 1; + } + + /* Set new length. */ + grad->converted_length = trgCount; + } + return VG_LITE_SUCCESS; + +Empty_sequence_handler: + memcpy(grad->converted_ramp, defaultRamp, sizeof(defaultRamp)); + grad->converted_length = sizeof(defaultRamp) / 5; + + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_update_radial_grad(vg_lite_radial_gradient_t * grad) + { + vg_lite_uint32_t ramp_length; + vg_lite_color_ramp_t * colorRamp; + vg_lite_uint32_t common, stop; + vg_lite_uint32_t i, width; + uint8_t * bits; + vg_lite_error_t error = VG_LITE_SUCCESS; + vg_lite_uint32_t align, mul, div; + + /* Get shortcuts to the color ramp. */ + ramp_length = grad->converted_length; + colorRamp = grad->converted_ramp; + + if(grad->radial_grad.r <= 0) + return VG_LITE_INVALID_ARGUMENT; + + /* Find the common denominator of the color ramp stops. */ + if(grad->radial_grad.r < 1) { + common = 1; + } + else { + common = (vg_lite_uint32_t)grad->radial_grad.r; + } + + for(i = 0; i < ramp_length; ++i) { + if(colorRamp[i].stop != 0.0f) { + vg_lite_float_t m = common * colorRamp[i].stop; + vg_lite_float_t frac = m - (vg_lite_float_t)floor(m); + if(frac > 0.00013f) { /* Suppose error for zero is 0.00013 */ + common = MAX(common, (vg_lite_uint32_t)(1.0f / frac + 0.5f)); + } + } + } + + /* Compute the width of the required color array. */ + width = common + 1; + width = (width + 15) & (~0xf); + + /* Allocate the color ramp surface. */ + memset(&grad->image, 0, sizeof(grad->image)); + grad->image.width = width; + grad->image.height = 1; + grad->image.stride = 0; + grad->image.image_mode = VG_LITE_NONE_IMAGE_MODE; + grad->image.format = VG_LITE_ABGR8888; + + /* Allocate the image for gradient. */ + VG_LITE_RETURN_ERROR(vg_lite_allocate(&grad->image)); + + get_format_bytes(VG_LITE_ABGR8888, &mul, &div, &align); + width = grad->image.stride * div / mul; + + /* Set pointer to color array. */ + bits = (uint8_t *)grad->image.memory; + + /* Start filling the color array. */ + stop = 0; + for(i = 0; i < width; ++i) { + vg_lite_float_t gradient; + vg_lite_float_t color[4]; + vg_lite_float_t color1[4]; + vg_lite_float_t color2[4]; + vg_lite_float_t weight; + + /* Compute gradient for current color array entry. */ + gradient = (vg_lite_float_t)i / (vg_lite_float_t)(width - 1); + + /* Find the entry in the color ramp that matches or exceeds this + ** gradient. */ + while(gradient > colorRamp[stop].stop) { + ++stop; + } + + if(gradient == colorRamp[stop].stop) { + /* Perfect match weight 1.0. */ + weight = 1.0f; + + /* Use color ramp color. */ + color1[3] = colorRamp[stop].alpha; + color1[2] = colorRamp[stop].blue; + color1[1] = colorRamp[stop].green; + color1[0] = colorRamp[stop].red; + + color2[3] = color2[2] = color2[1] = color2[0] = 0.0f; + } + else { + /* Compute weight. */ + weight = (colorRamp[stop].stop - gradient) + / (colorRamp[stop].stop - colorRamp[stop - 1].stop); + + /* Grab color ramp color of previous stop. */ + color1[3] = colorRamp[stop - 1].alpha; + color1[2] = colorRamp[stop - 1].blue; + color1[1] = colorRamp[stop - 1].green; + color1[0] = colorRamp[stop - 1].red; + + /* Grab color ramp color of current stop. */ + color2[3] = colorRamp[stop].alpha; + color2[2] = colorRamp[stop].blue; + color2[1] = colorRamp[stop].green; + color2[0] = colorRamp[stop].red; + } + + if(grad->pre_multiplied) { + /* Pre-multiply the first color. */ + color1[2] *= color1[3]; + color1[1] *= color1[3]; + color1[0] *= color1[3]; + + /* Pre-multiply the second color. */ + color2[2] *= color2[3]; + color2[1] *= color2[3]; + color2[0] *= color2[3]; + } + + /* Filter the colors per channel. */ + color[3] = LERP(color1[3], color2[3], weight); + color[2] = LERP(color1[2], color2[2], weight); + color[1] = LERP(color1[1], color2[1], weight); + color[0] = LERP(color1[0], color2[0], weight); + + /* Pack the final color. */ + *bits++ = PackColorComponent(color[3]); + *bits++ = PackColorComponent(color[2]); + *bits++ = PackColorComponent(color[1]); + *bits++ = PackColorComponent(color[0]); + } + + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_set_grad(vg_lite_linear_gradient_t * grad, + vg_lite_uint32_t count, + vg_lite_uint32_t * colors, + vg_lite_uint32_t * stops) + { + vg_lite_uint32_t i; + + grad->count = 0; /* Opaque B&W gradient */ + if(!count || count > VLC_MAX_GRADIENT_STOPS || colors == NULL || stops == NULL) + return VG_LITE_SUCCESS; + + /* Check stops validity */ + for(i = 0; i < count; i++) + if(stops[i] < VLC_GRADIENT_BUFFER_WIDTH) { + if(!grad->count || stops[i] > grad->stops[grad->count - 1]) { + grad->stops[grad->count] = stops[i]; + grad->colors[grad->count] = colors[i]; + grad->count++; + } + else if(stops[i] == grad->stops[grad->count - 1]) { + /* Equal stops : use the color corresponding to the last stop + in the sequence */ + grad->colors[grad->count - 1] = colors[i]; + } + } + + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_update_grad(vg_lite_linear_gradient_t * grad) + { + vg_lite_error_t error = VG_LITE_SUCCESS; + int32_t r0, g0, b0, a0; + int32_t r1, g1, b1, a1; + int32_t lr, lg, lb, la; + vg_lite_uint32_t i; + int32_t j; + int32_t ds, dr, dg, db, da; + vg_lite_uint32_t * buffer = (vg_lite_uint32_t *)grad->image.memory; + + if(grad->count == 0) { + /* If no valid stops have been specified (e.g., due to an empty input + * array, out-of-range, or out-of-order stops), a stop at 0 with color + * 0xFF000000 (opaque black) and a stop at 255 with color 0xFFFFFFFF + * (opaque white) are implicitly defined. */ + grad->stops[0] = 0; + grad->colors[0] = 0xFF000000; /* Opaque black */ + grad->stops[1] = 255; + grad->colors[1] = 0xFFFFFFFF; /* Opaque white */ + grad->count = 2; + } + else if(grad->count && grad->stops[0] != 0) { + /* If at least one valid stop has been specified, but none has been + * defined with an offset of 0, an implicit stop is added with an + * offset of 0 and the same color as the first user-defined stop. */ + for(i = 0; i < grad->stops[0]; i++) + buffer[i] = grad->colors[0]; + } + a0 = A(grad->colors[0]); + r0 = R(grad->colors[0]); + g0 = G(grad->colors[0]); + b0 = B(grad->colors[0]); + + /* Calculate the colors for each pixel of the image. */ + for(i = 0; i < grad->count - 1; i++) { + buffer[grad->stops[i]] = grad->colors[i]; + ds = grad->stops[i + 1] - grad->stops[i]; + a1 = A(grad->colors[i + 1]); + r1 = R(grad->colors[i + 1]); + g1 = G(grad->colors[i + 1]); + b1 = B(grad->colors[i + 1]); + + da = a1 - a0; + dr = r1 - r0; + dg = g1 - g0; + db = b1 - b0; + + for(j = 1; j < ds; j++) { + la = a0 + da * j / ds; + lr = r0 + dr * j / ds; + lg = g0 + dg * j / ds; + lb = b0 + db * j / ds; + + buffer[grad->stops[i] + j] = ARGB(la, lr, lg, lb); + } + + a0 = a1; + r0 = r1; + g0 = g1; + b0 = b1; + } + + /* If at least one valid stop has been specified, but none has been defined + * with an offset of 255, an implicit stop is added with an offset of 255 + * and the same color as the last user-defined stop. */ + for(i = grad->stops[grad->count - 1]; i < VLC_GRADIENT_BUFFER_WIDTH; i++) + buffer[i] = grad->colors[grad->count - 1]; + + return error; + } + + vg_lite_error_t vg_lite_clear_linear_grad(vg_lite_ext_linear_gradient_t * grad) + { + vg_lite_error_t error = VG_LITE_SUCCESS; + + grad->count = 0; + /* Release the image resource. */ + if(grad->image.handle != NULL) { + error = vg_lite_free(&grad->image); + } + + return error; + } + + vg_lite_error_t vg_lite_clear_grad(vg_lite_linear_gradient_t * grad) + { + vg_lite_error_t error = VG_LITE_SUCCESS; + + grad->count = 0; + /* Release the image resource. */ + if(grad->image.handle != NULL) { + error = vg_lite_free(&grad->image); + } + + return error; + } + + vg_lite_error_t vg_lite_clear_radial_grad(vg_lite_radial_gradient_t * grad) + { + vg_lite_error_t error = VG_LITE_SUCCESS; + + grad->count = 0; + /* Release the image resource. */ + if(grad->image.handle != NULL) { + error = vg_lite_free(&grad->image); + } + + return error; + } + + vg_lite_matrix_t * vg_lite_get_linear_grad_matrix(vg_lite_ext_linear_gradient_t * grad) + { + return &grad->matrix; + } + + vg_lite_matrix_t * vg_lite_get_grad_matrix(vg_lite_linear_gradient_t * grad) + { + return &grad->matrix; + } + + vg_lite_matrix_t * vg_lite_get_radial_grad_matrix(vg_lite_radial_gradient_t * grad) + { + return &grad->matrix; + } + + vg_lite_error_t vg_lite_draw_grad(vg_lite_buffer_t * target, + vg_lite_path_t * path, + vg_lite_fill_t fill_rule, + vg_lite_matrix_t * matrix, + vg_lite_linear_gradient_t * grad, + vg_lite_blend_t blend) + { + auto ctx = vg_lite_ctx::get_instance(); + TVG_CHECK_RETURN_VG_ERROR(canvas_set_target(ctx, target)); + + auto shape = Shape::gen(); + TVG_CHECK_RETURN_VG_ERROR(shape_append_path(shape, path, matrix)); + TVG_CHECK_RETURN_VG_ERROR(shape->transform(matrix_conv(matrix))); + TVG_CHECK_RETURN_VG_ERROR(shape->fill(fill_rule_conv(fill_rule));); + TVG_CHECK_RETURN_VG_ERROR(shape->blend(blend_method_conv(blend))); + + float x_min = path->bounding_box[0]; + float y_min = path->bounding_box[1]; + float x_max = path->bounding_box[2]; + float y_max = path->bounding_box[3]; + + auto linearGrad = LinearGradient::gen(); + + if(matrix->m[0][1] != 0) { + /* vertical */ + linearGrad->linear(x_min, y_min, x_min, y_max); + } + else { + /* horizontal */ + linearGrad->linear(x_min, y_min, x_max, y_min); + } + + linearGrad->transform(matrix_conv(&grad->matrix)); + linearGrad->spread(FillSpread::Reflect); + + tvg::Fill::ColorStop colorStops[VLC_MAX_GRADIENT_STOPS]; + for(vg_lite_uint32_t i = 0; i < grad->count; i++) { + colorStops[i].offset = grad->stops[i] / 255.0f; + colorStops[i].r = R(grad->colors[i]); + colorStops[i].g = G(grad->colors[i]); + colorStops[i].b = B(grad->colors[i]); + colorStops[i].a = A(grad->colors[i]); + } + TVG_CHECK_RETURN_VG_ERROR(linearGrad->colorStops(colorStops, grad->count)); + + TVG_CHECK_RETURN_VG_ERROR(shape->fill(std::move(linearGrad))); + TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(shape))); + + return VG_LITE_SUCCESS; + } + + vg_lite_error_t vg_lite_draw_radial_grad(vg_lite_buffer_t * target, + vg_lite_path_t * path, + vg_lite_fill_t fill_rule, + vg_lite_matrix_t * path_matrix, + vg_lite_radial_gradient_t * grad, + vg_lite_color_t paint_color, + vg_lite_blend_t blend, + vg_lite_filter_t filter) + { + LV_UNUSED(target); + LV_UNUSED(path); + LV_UNUSED(fill_rule); + LV_UNUSED(path_matrix); + LV_UNUSED(grad); + LV_UNUSED(paint_color); + LV_UNUSED(blend); + LV_UNUSED(filter); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_set_command_buffer_size(vg_lite_uint32_t size) + { + LV_UNUSED(size); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_set_scissor(int32_t x, int32_t y, int32_t right, int32_t bottom) + { + LV_UNUSED(x); + LV_UNUSED(y); + LV_UNUSED(right); + LV_UNUSED(bottom); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_enable_scissor(void) + { + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_disable_scissor(void) + { + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_get_mem_size(vg_lite_uint32_t * size) + { + *size = 0; + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_source_global_alpha(vg_lite_global_alpha_t alpha_mode, uint8_t alpha_value) + { + LV_UNUSED(alpha_mode); + LV_UNUSED(alpha_value); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_dest_global_alpha(vg_lite_global_alpha_t alpha_mode, uint8_t alpha_value) + { + LV_UNUSED(alpha_mode); + LV_UNUSED(alpha_value); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_set_color_key(vg_lite_color_key4_t colorkey) + { + LV_UNUSED(colorkey); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_set_flexa_stream_id(uint8_t stream_id) + { + LV_UNUSED(stream_id); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_set_flexa_current_background_buffer(uint8_t stream_id, + vg_lite_buffer_t * buffer, + vg_lite_uint32_t background_segment_count, + vg_lite_uint32_t background_segment_size) + { + LV_UNUSED(stream_id); + LV_UNUSED(buffer); + LV_UNUSED(background_segment_count); + LV_UNUSED(background_segment_size); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_enable_flexa(void) + { + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_disable_flexa(void) + { + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_set_flexa_stop_frame(void) + { + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_enable_dither(void) + { + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_disable_dither(void) + { + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_set_tess_buffer(vg_lite_uint32_t physical, vg_lite_uint32_t size) + { + LV_UNUSED(physical); + LV_UNUSED(size); + return VG_LITE_NOT_SUPPORT; + } + + vg_lite_error_t vg_lite_set_command_buffer(vg_lite_uint32_t physical, vg_lite_uint32_t size) + { + LV_UNUSED(physical); + LV_UNUSED(size); + return VG_LITE_NOT_SUPPORT; + } +} /* extern "C" */ + +/********************** + * STATIC FUNCTIONS + **********************/ + +static vg_lite_error_t vg_lite_error_conv(Result result) +{ + switch(result) { + case Result::Success: + return VG_LITE_SUCCESS; + + case Result::InvalidArguments: + return VG_LITE_INVALID_ARGUMENT; + + case Result::InsufficientCondition: + return VG_LITE_OUT_OF_RESOURCES; + + case Result::FailedAllocation: + return VG_LITE_OUT_OF_MEMORY; + + case Result::NonSupport: + return VG_LITE_NOT_SUPPORT; + + default: + break; + } + + return VG_LITE_TIMEOUT; +} + +static Matrix matrix_conv(const vg_lite_matrix_t * matrix) +{ + return *(Matrix *)matrix; +} + +static FillRule fill_rule_conv(vg_lite_fill_t fill) +{ + if(fill == VG_LITE_FILL_EVEN_ODD) { + return FillRule::EvenOdd; + } + + return FillRule::Winding; +} + +static BlendMethod blend_method_conv(vg_lite_blend_t blend) +{ + switch(blend) { + case VG_LITE_BLEND_NONE: + return BlendMethod::SrcOver; + + case VG_LITE_BLEND_NORMAL_LVGL: + return BlendMethod::Normal; + + case VG_LITE_BLEND_SRC_OVER: + return BlendMethod::Normal; + + case VG_LITE_BLEND_SCREEN: + return BlendMethod::Screen; + + case VG_LITE_BLEND_ADDITIVE: + return BlendMethod::Add; + + case VG_LITE_BLEND_MULTIPLY: + return BlendMethod::Multiply; + + default: + break; + } + + return BlendMethod::Normal; +} + +static float vlc_get_arg(const void * data, vg_lite_format_t format) +{ + switch(format) { + case VG_LITE_S8: + return *((int8_t *)data); + + case VG_LITE_S16: + return *((int16_t *)data); + + case VG_LITE_S32: + return *((int32_t *)data); + + case VG_LITE_FP32: + return *((float *)data); + + default: + LV_LOG_ERROR("UNKNOW_FORMAT: %d", format); + break; + } + + return 0; +} + +static uint8_t vlc_format_len(vg_lite_format_t format) +{ + switch(format) { + case VG_LITE_S8: + return 1; + case VG_LITE_S16: + return 2; + case VG_LITE_S32: + return 4; + case VG_LITE_FP32: + return 4; + default: + LV_LOG_ERROR("UNKNOW_FORMAT: %d", format); + LV_ASSERT(false); + break; + } + + return 0; +} + +static uint8_t vlc_op_arg_len(uint8_t vlc_op) +{ + switch(vlc_op) { + VLC_OP_ARG_LEN(END, 0); + VLC_OP_ARG_LEN(CLOSE, 0); + VLC_OP_ARG_LEN(MOVE, 2); + VLC_OP_ARG_LEN(MOVE_REL, 2); + VLC_OP_ARG_LEN(LINE, 2); + VLC_OP_ARG_LEN(LINE_REL, 2); + VLC_OP_ARG_LEN(QUAD, 4); + VLC_OP_ARG_LEN(QUAD_REL, 4); + VLC_OP_ARG_LEN(CUBIC, 6); + VLC_OP_ARG_LEN(CUBIC_REL, 6); + VLC_OP_ARG_LEN(SCCWARC, 5); + VLC_OP_ARG_LEN(SCCWARC_REL, 5); + VLC_OP_ARG_LEN(SCWARC, 5); + VLC_OP_ARG_LEN(SCWARC_REL, 5); + VLC_OP_ARG_LEN(LCCWARC, 5); + VLC_OP_ARG_LEN(LCCWARC_REL, 5); + VLC_OP_ARG_LEN(LCWARC, 5); + VLC_OP_ARG_LEN(LCWARC_REL, 5); + default: + LV_LOG_ERROR("UNKNOW_VLC_OP: 0x%x", vlc_op); + LV_ASSERT(false); + break; + } + + return 0; +} + +static Result shape_append_path(std::unique_ptr & shape, vg_lite_path_t * path, vg_lite_matrix_t * matrix) +{ + uint8_t fmt_len = vlc_format_len(path->format); + uint8_t * cur = (uint8_t *)path->path; + uint8_t * end = cur + path->path_length; + + while(cur < end) { + /* get op code */ + uint8_t op_code = VLC_GET_OP_CODE(cur); + + /* get arguments length */ + uint8_t arg_len = vlc_op_arg_len(op_code); + + /* skip op code */ + cur += fmt_len; + + switch(op_code) { + case VLC_OP_MOVE: { + float x = VLC_GET_ARG(cur, 0); + float y = VLC_GET_ARG(cur, 1); + TVG_CHECK_RETURN_RESULT(shape->moveTo(x, y)); + } + break; + + case VLC_OP_LINE: { + float x = VLC_GET_ARG(cur, 0); + float y = VLC_GET_ARG(cur, 1); + TVG_CHECK_RETURN_RESULT(shape->lineTo(x, y)); + } + break; + + case VLC_OP_QUAD: { + /* hack pre point */ + float qcx0 = VLC_GET_ARG(cur, -3); + float qcy0 = VLC_GET_ARG(cur, -2); + float qcx1 = VLC_GET_ARG(cur, 0); + float qcy1 = VLC_GET_ARG(cur, 1); + float x = VLC_GET_ARG(cur, 2); + float y = VLC_GET_ARG(cur, 3); + + qcx0 += (qcx1 - qcx0) * 2 / 3; + qcy0 += (qcy1 - qcy0) * 2 / 3; + qcx1 = x + (qcx1 - x) * 2 / 3; + qcy1 = y + (qcy1 - y) * 2 / 3; + + TVG_CHECK_RETURN_RESULT(shape->cubicTo(qcx0, qcy0, qcx1, qcy1, x, y)); + } + break; + + case VLC_OP_CUBIC: { + float cx1 = VLC_GET_ARG(cur, 0); + float cy1 = VLC_GET_ARG(cur, 1); + float cx2 = VLC_GET_ARG(cur, 2); + float cy2 = VLC_GET_ARG(cur, 3); + float x = VLC_GET_ARG(cur, 4); + float y = VLC_GET_ARG(cur, 5); + TVG_CHECK_RETURN_RESULT(shape->cubicTo(cx1, cy1, cx2, cy2, x, y)); + } + break; + + case VLC_OP_CLOSE: + case VLC_OP_END: { + TVG_CHECK_RETURN_RESULT(shape->close()); + } + break; + + default: + break; + } + + cur += arg_len * fmt_len; + } + + float x_min = path->bounding_box[0]; + float y_min = path->bounding_box[1]; + float x_max = path->bounding_box[2]; + float y_max = path->bounding_box[3]; + + if(math_equal(x_min, __FLT_MIN__) && math_equal(y_min, __FLT_MIN__) + && math_equal(x_max, __FLT_MAX__) && math_equal(y_max, __FLT_MAX__)) { + return Result::Success; + } + + auto cilp = Shape::gen(); + TVG_CHECK_RETURN_RESULT(cilp->appendRect(x_min, y_min, x_max - x_min, y_max - y_min, 0, 0)); + TVG_CHECK_RETURN_RESULT(cilp->transform(matrix_conv(matrix))); + TVG_CHECK_RETURN_RESULT(shape->composite(std::move(cilp), CompositeMethod::ClipPath)); + + return Result::Success; +} + +static Result shape_append_rect(std::unique_ptr & shape, const vg_lite_buffer_t * target, + const vg_lite_rectangle_t * rect) +{ + if(rect) { + TVG_CHECK_RETURN_RESULT(shape->appendRect(rect->x, rect->y, rect->width, rect->height, 0, 0)); + } + else if(target) { + TVG_CHECK_RETURN_RESULT(shape->appendRect(0, 0, target->width, target->height, 0, 0)); + } + else { + return Result::InvalidArguments; + } + + return Result::Success; +} + +static Result canvas_set_target(vg_lite_ctx * ctx, vg_lite_buffer_t * target) +{ + vg_lite_uint32_t * target_buffer = nullptr; + + /* if target_buffer needs to be changed, finish current drawing */ + if(ctx->target_buffer && ctx->target_buffer != target->memory) { + vg_lite_finish(); + } + + ctx->target_format = target->format; + + if(TVG_IS_VG_FMT_SUPPORT(target->format)) { + /* if target format is supported by VG, use target buffer directly */ + target_buffer = (vg_lite_uint32_t *)target->memory; + ctx->target_buffer = nullptr; + ctx->target_px_size = 0; + } + else { + /* if target format is not supported by VG, use internal buffer */ + target_buffer = ctx->get_temp_target_buffer(target->width, target->height); + ctx->target_buffer = target->memory; + ctx->target_px_size = target->width * target->height; + } + + Result res = ctx->canvas->target( + (uint32_t *)target_buffer, + target->width, + target->width, + target->height, + SwCanvas::ARGB8888); + + return res; +} + +static vg_lite_uint32_t width_to_stride(vg_lite_uint32_t w, vg_lite_buffer_format_t color_format) +{ + if(vg_lite_query_feature(gcFEATURE_BIT_VG_16PIXELS_ALIGN)) { + w = VG_LITE_ALIGN(w, 16); + } + + vg_lite_uint32_t mul, div, align; + get_format_bytes(color_format, &mul, &div, &align); + return VG_LITE_ALIGN((w * mul / div), align); +} + +static bool decode_indexed_line( + vg_lite_buffer_format_t color_format, + const vg_lite_uint32_t * palette, + int32_t x, int32_t y, + int32_t w_px, const uint8_t * in, vg_lite_uint32_t * out) +{ + uint8_t px_size; + uint16_t mask; + + vg_lite_uint32_t w_byte = width_to_stride(w_px, color_format); + + in += w_byte * y; /*First pixel*/ + out += w_px * y; + + int8_t shift = 0; + switch(color_format) { + case VG_LITE_INDEX_1: + px_size = 1; + in += x / 8; /*8pixel per byte*/ + shift = 7 - (x & 0x7); + break; + case VG_LITE_INDEX_2: + px_size = 2; + in += x / 4; /*4pixel per byte*/ + shift = 6 - 2 * (x & 0x3); + break; + case VG_LITE_INDEX_4: + px_size = 4; + in += x / 2; /*2pixel per byte*/ + shift = 4 - 4 * (x & 0x1); + break; + case VG_LITE_INDEX_8: + px_size = 8; + in += x; + shift = 0; + break; + default: + LV_ASSERT(false); + return false; + } + + mask = (1 << px_size) - 1; /*E.g. px_size = 2; mask = 0x03*/ + + int32_t i; + for(i = 0; i < w_px; i++) { + uint8_t val_act = (*in >> shift) & mask; + out[i] = palette[val_act]; + + shift -= px_size; + if(shift < 0) { + shift = 8 - px_size; + in++; + } + } + return true; +} + +static Result picture_load(vg_lite_ctx * ctx, std::unique_ptr & picture, const vg_lite_buffer_t * source, + vg_lite_color_t color) +{ + vg_lite_uint32_t * image_buffer; + LV_ASSERT(VG_LITE_IS_ALIGNED(source->memory, LV_VG_LITE_THORVG_BUF_ADDR_ALIGN)); + +#if LV_VG_LITE_THORVG_16PIXELS_ALIGN + LV_ASSERT(VG_LITE_IS_ALIGNED(source->width, 16)); +#endif + + if(source->format == VG_LITE_BGRA8888 && source->image_mode == VG_LITE_NORMAL_IMAGE_MODE) { + image_buffer = (vg_lite_uint32_t *)source->memory; + } + else { + vg_lite_uint32_t width = source->width; + vg_lite_uint32_t height = source->height; + vg_lite_uint32_t px_size = width * height; + image_buffer = ctx->get_image_buffer(width, height); + + vg_lite_buffer_t target; + memset(&target, 0, sizeof(target)); + target.memory = image_buffer; + target.format = VG_LITE_BGRA8888; + target.width = width; + target.height = height; + target.stride = width_to_stride(width, target.format); + + switch(source->format) { + case VG_LITE_INDEX_1: + case VG_LITE_INDEX_2: + case VG_LITE_INDEX_4: + case VG_LITE_INDEX_8: { + const vg_lite_uint32_t * clut_colors = ctx->get_CLUT(source->format); + for(vg_lite_uint32_t y = 0; y < height; y++) { + decode_indexed_line(source->format, clut_colors, 0, y, width, (uint8_t *)source->memory, image_buffer); + } + } + break; + + case VG_LITE_A4: { + conv_alpha4_to_bgra8888.convert(&target, source, color); + } + break; + + case VG_LITE_A8: { + conv_alpha8_to_bgra8888.convert(&target, source, color); + } + break; + + case VG_LITE_BGRX8888: { + conv_bgrx8888_to_bgra8888.convert(&target, source); + } + break; + + case VG_LITE_BGR888: { + conv_bgr888_to_bgra8888.convert(&target, source); + } + break; + + case VG_LITE_BGRA5658: { + conv_bgra5658_to_bgra8888.convert(&target, source); + } + break; + + case VG_LITE_BGR565: { + conv_bgr565_to_bgra8888.convert(&target, source); + } + break; + +#if LV_VG_LITE_THORVG_YUV_SUPPORT + case VG_LITE_NV12: { + libyuv::NV12ToARGB((const uint8_t *)source->memory, source->stride, (const uint8_t *)source->yuv.uv_memory, + source->yuv.uv_stride, + (uint8_t *)image_buffer, source->width * sizeof(vg_lite_uint32_t), width, height); + } + break; +#endif + + case VG_LITE_BGRA8888: { + memcpy(image_buffer, source->memory, px_size * sizeof(vg_color32_t)); + } + break; + + default: + LV_LOG_ERROR("unsupported format: %d", source->format); + LV_ASSERT(false); + break; + } + + /* multiply color */ + if(source->image_mode == VG_LITE_MULTIPLY_IMAGE_MODE && !VG_LITE_IS_ALPHA_FORMAT(source->format)) { + vg_color32_t * dest = (vg_color32_t *)image_buffer; + while(px_size--) { + dest->alpha = UDIV255(dest->alpha * A(color)); + dest->red = UDIV255(dest->red * B(color)); + dest->green = UDIV255(dest->green * G(color)); + dest->blue = UDIV255(dest->blue * R(color)); + dest++; + } + } + } + + TVG_CHECK_RETURN_RESULT(picture->load((uint32_t *)image_buffer, source->width, source->height, true)); + + return Result::Success; +} + +static void ClampColor(FLOATVECTOR4 Source, FLOATVECTOR4 Target, uint8_t Premultiplied) +{ + vg_lite_float_t colorMax; + /* Clamp the alpha channel. */ + Target[3] = CLAMP(Source[3], 0.0f, 1.0f); + + /* Determine the maximum value for the color channels. */ + colorMax = Premultiplied ? Target[3] : 1.0f; + + /* Clamp the color channels. */ + Target[0] = CLAMP(Source[0], 0.0f, colorMax); + Target[1] = CLAMP(Source[1], 0.0f, colorMax); + Target[2] = CLAMP(Source[2], 0.0f, colorMax); +} + +static uint8_t PackColorComponent(vg_lite_float_t value) +{ + /* Compute the rounded normalized value. */ + vg_lite_float_t rounded = value * 255.0f + 0.5f; + + /* Get the integer part. */ + int32_t roundedInt = (int32_t)rounded; + + /* Clamp to 0..1 range. */ + uint8_t clamped = (uint8_t)CLAMP(roundedInt, 0, 255); + + /* Return result. */ + return clamped; +} + +/* Get the bpp information of a color format. */ +static void get_format_bytes(vg_lite_buffer_format_t format, + vg_lite_uint32_t * mul, + vg_lite_uint32_t * div, + vg_lite_uint32_t * bytes_align) +{ + *mul = *div = 1; + *bytes_align = 4; + switch(format) { + case VG_LITE_L8: + case VG_LITE_A8: + case VG_LITE_RGBA8888_ETC2_EAC: + break; + + case VG_LITE_A4: + *div = 2; + break; + + case VG_LITE_ABGR1555: + case VG_LITE_ARGB1555: + case VG_LITE_BGRA5551: + case VG_LITE_RGBA5551: + case VG_LITE_RGBA4444: + case VG_LITE_BGRA4444: + case VG_LITE_ABGR4444: + case VG_LITE_ARGB4444: + case VG_LITE_RGB565: + case VG_LITE_BGR565: + case VG_LITE_YUYV: + case VG_LITE_YUY2: + case VG_LITE_YUY2_TILED: + /* AYUY2 buffer memory = YUY2 + alpha. */ + case VG_LITE_AYUY2: + case VG_LITE_AYUY2_TILED: + /* ABGR8565_PLANAR buffer memory = RGB565 + alpha. */ + case VG_LITE_ABGR8565_PLANAR: + case VG_LITE_ARGB8565_PLANAR: + case VG_LITE_RGBA5658_PLANAR: + case VG_LITE_BGRA5658_PLANAR: + *mul = 2; + break; + + case VG_LITE_RGBA8888: + case VG_LITE_BGRA8888: + case VG_LITE_ABGR8888: + case VG_LITE_ARGB8888: + case VG_LITE_RGBX8888: + case VG_LITE_BGRX8888: + case VG_LITE_XBGR8888: + case VG_LITE_XRGB8888: + *mul = 4; + break; + + case VG_LITE_NV12: + case VG_LITE_NV12_TILED: + *mul = 3; + break; + + case VG_LITE_ANV12: + case VG_LITE_ANV12_TILED: + *mul = 4; + break; + + case VG_LITE_INDEX_1: + *div = 8; + *bytes_align = 8; + break; + + case VG_LITE_INDEX_2: + *div = 4; + *bytes_align = 8; + break; + + case VG_LITE_INDEX_4: + *div = 2; + *bytes_align = 8; + break; + + case VG_LITE_INDEX_8: + *bytes_align = 1; + break; + + case VG_LITE_RGBA2222: + case VG_LITE_BGRA2222: + case VG_LITE_ABGR2222: + case VG_LITE_ARGB2222: + *mul = 1; + break; + + case VG_LITE_RGB888: + case VG_LITE_BGR888: + case VG_LITE_ABGR8565: + case VG_LITE_BGRA5658: + case VG_LITE_ARGB8565: + case VG_LITE_RGBA5658: + *mul = 3; + break; + + /* OpenVG format*/ + case VG_sRGBX_8888: + case VG_sRGBA_8888: + case VG_sRGBA_8888_PRE: + case VG_lRGBX_8888: + case VG_lRGBA_8888: + case VG_lRGBA_8888_PRE: + case VG_sXRGB_8888: + case VG_sARGB_8888: + case VG_sARGB_8888_PRE: + case VG_lXRGB_8888: + case VG_lARGB_8888: + case VG_lARGB_8888_PRE: + case VG_sBGRX_8888: + case VG_sBGRA_8888: + case VG_sBGRA_8888_PRE: + case VG_lBGRX_8888: + case VG_lBGRA_8888: + case VG_sXBGR_8888: + case VG_sABGR_8888: + case VG_lBGRA_8888_PRE: + case VG_sABGR_8888_PRE: + case VG_lXBGR_8888: + case VG_lABGR_8888: + case VG_lABGR_8888_PRE: + *mul = 4; + break; + + case VG_sRGBA_5551: + case VG_sRGBA_4444: + case VG_sARGB_1555: + case VG_sARGB_4444: + case VG_sBGRA_5551: + case VG_sBGRA_4444: + case VG_sABGR_1555: + case VG_sABGR_4444: + case VG_sRGB_565: + case VG_sBGR_565: + *mul = 2; + break; + + case VG_sL_8: + case VG_lL_8: + case VG_A_8: + break; + + case VG_BW_1: + case VG_A_4: + case VG_A_1: + *div = 2; + break; + + default: + break; + } +} +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_mem_core_builtin.c b/lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_mem_core_builtin.c new file mode 100644 index 000000000..c8f3233e3 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_mem_core_builtin.c @@ -0,0 +1,263 @@ +/** + * @file lv_malloc_core.c + */ + +/********************* + * INCLUDES + *********************/ +#include "../lv_mem.h" +#if LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN + +#include "lv_tlsf.h" +#include "../lv_string.h" +#include "../../misc/lv_assert.h" +#include "../../misc/lv_log.h" +#include "../../misc/lv_ll.h" +#include "../../misc/lv_math.h" +#include "../../osal/lv_os.h" +#include "../../core/lv_global.h" + +#ifdef LV_MEM_POOL_INCLUDE + #include LV_MEM_POOL_INCLUDE +#endif + +/********************* + * DEFINES + *********************/ +/*memset the allocated memories to 0xaa and freed memories to 0xbb (just for testing purposes)*/ +#ifndef LV_MEM_ADD_JUNK + #define LV_MEM_ADD_JUNK 0 +#endif + +#ifdef LV_ARCH_64 + #define MEM_UNIT uint64_t + #define ALIGN_MASK 0x7 +#else + #define MEM_UNIT uint32_t + #define ALIGN_MASK 0x3 +#endif +#define state LV_GLOBAL_DEFAULT()->tlsf_state + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_mem_walker(void * ptr, size_t size, int used, void * user); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ +#if LV_USE_LOG && LV_LOG_TRACE_MEM + #define LV_TRACE_MEM(...) LV_LOG_TRACE(__VA_ARGS__) +#else + #define LV_TRACE_MEM(...) +#endif + +#define _COPY(d, s) *d = *s; d++; s++; +#define _SET(d, v) *d = v; d++; +#define _REPEAT8(expr) expr expr expr expr expr expr expr expr + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_mem_init(void) +{ +#if LV_USE_OS + lv_mutex_init(&state.mutex); +#endif + +#if LV_MEM_ADR == 0 +#ifdef LV_MEM_POOL_ALLOC + state.tlsf = lv_tlsf_create_with_pool((void *)LV_MEM_POOL_ALLOC(LV_MEM_SIZE), LV_MEM_SIZE); +#else + /*Allocate a large array to store the dynamically allocated data*/ + static LV_ATTRIBUTE_LARGE_RAM_ARRAY MEM_UNIT work_mem_int[LV_MEM_SIZE / sizeof(MEM_UNIT)]; + state.tlsf = lv_tlsf_create_with_pool((void *)work_mem_int, LV_MEM_SIZE); +#endif +#else + state.tlsf = lv_tlsf_create_with_pool((void *)LV_MEM_ADR, LV_MEM_SIZE); +#endif + + _lv_ll_init(&state.pool_ll, sizeof(lv_pool_t)); + + /*Record the first pool*/ + lv_pool_t * pool_p = _lv_ll_ins_tail(&state.pool_ll); + LV_ASSERT_MALLOC(pool_p); + *pool_p = lv_tlsf_get_pool(state.tlsf); + +#if LV_MEM_ADD_JUNK + LV_LOG_WARN("LV_MEM_ADD_JUNK is enabled which makes LVGL much slower"); +#endif +} + +void lv_mem_deinit(void) +{ + _lv_ll_clear(&state.pool_ll); + lv_tlsf_destroy(state.tlsf); +#if LV_USE_OS + lv_mutex_delete(&state.mutex); +#endif +} + +lv_mem_pool_t lv_mem_add_pool(void * mem, size_t bytes) +{ + lv_mem_pool_t new_pool = lv_tlsf_add_pool(state.tlsf, mem, bytes); + if(!new_pool) { + LV_LOG_WARN("failed to add memory pool, address: %p, size: %zu", mem, bytes); + return NULL; + } + + lv_pool_t * pool_p = _lv_ll_ins_tail(&state.pool_ll); + LV_ASSERT_MALLOC(pool_p); + *pool_p = new_pool; + + return new_pool; +} + +void lv_mem_remove_pool(lv_mem_pool_t pool) +{ + lv_pool_t * pool_p; + _LV_LL_READ(&state.pool_ll, pool_p) { + if(*pool_p == pool) { + _lv_ll_remove(&state.pool_ll, pool_p); + lv_free(pool_p); + lv_tlsf_remove_pool(state.tlsf, pool); + return; + } + } + LV_LOG_WARN("invalid pool: %p", pool); +} + +void * lv_malloc_core(size_t size) +{ +#if LV_USE_OS + lv_mutex_lock(&state.mutex); +#endif + state.cur_used += size; + state.max_used = LV_MAX(state.cur_used, state.max_used); + void * p = lv_tlsf_malloc(state.tlsf, size); + +#if LV_USE_OS + lv_mutex_unlock(&state.mutex); +#endif + return p; +} + +void * lv_realloc_core(void * p, size_t new_size) +{ +#if LV_USE_OS + lv_mutex_lock(&state.mutex); +#endif + + void * p_new = lv_tlsf_realloc(state.tlsf, p, new_size); + +#if LV_USE_OS + lv_mutex_unlock(&state.mutex); +#endif + + return p_new; +} + +void lv_free_core(void * p) +{ +#if LV_USE_OS + lv_mutex_lock(&state.mutex); +#endif + +#if LV_MEM_ADD_JUNK + lv_memset(p, 0xbb, lv_tlsf_block_size(data)); +#endif + size_t size = lv_tlsf_free(state.tlsf, p); + if(state.cur_used > size) state.cur_used -= size; + else state.cur_used = 0; + +#if LV_USE_OS + lv_mutex_unlock(&state.mutex); +#endif +} + +void lv_mem_monitor_core(lv_mem_monitor_t * mon_p) +{ + /*Init the data*/ + lv_memzero(mon_p, sizeof(lv_mem_monitor_t)); + LV_TRACE_MEM("begin"); + + lv_pool_t * pool_p; + _LV_LL_READ(&state.pool_ll, pool_p) { + lv_tlsf_walk_pool(*pool_p, lv_mem_walker, mon_p); + } + + mon_p->used_pct = 100 - (uint64_t)100U * mon_p->free_size / mon_p->total_size; + if(mon_p->free_size > 0) { + mon_p->frag_pct = (uint64_t)mon_p->free_biggest_size * 100U / mon_p->free_size; + mon_p->frag_pct = 100 - mon_p->frag_pct; + } + else { + mon_p->frag_pct = 0; /*no fragmentation if all the RAM is used*/ + } + + mon_p->max_used = state.max_used; + + LV_TRACE_MEM("finished"); +} + +lv_result_t lv_mem_test_core(void) +{ +#if LV_USE_OS + lv_mutex_lock(&state.mutex); +#endif + if(lv_tlsf_check(state.tlsf)) { + LV_LOG_WARN("failed"); +#if LV_USE_OS + lv_mutex_unlock(&state.mutex); +#endif + return LV_RESULT_INVALID; + } + + lv_pool_t * pool_p; + _LV_LL_READ(&state.pool_ll, pool_p) { + if(lv_tlsf_check_pool(*pool_p)) { + LV_LOG_WARN("pool failed"); +#if LV_USE_OS + lv_mutex_unlock(&state.mutex); +#endif + return LV_RESULT_INVALID; + } + } + + LV_TRACE_MEM("passed"); +#if LV_USE_OS + lv_mutex_unlock(&state.mutex); +#endif + return LV_RESULT_OK; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_mem_walker(void * ptr, size_t size, int used, void * user) +{ + LV_UNUSED(ptr); + + lv_mem_monitor_t * mon_p = user; + mon_p->total_size += size; + if(used) { + mon_p->used_cnt++; + } + else { + mon_p->free_cnt++; + mon_p->free_size += size; + if(size > mon_p->free_biggest_size) + mon_p->free_biggest_size = size; + } +} +#endif /*LV_STDLIB_BUILTIN*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_printf.c b/lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_sprintf_builtin.c similarity index 97% rename from lib/libesp32_lvgl/lvgl/src/misc/lv_printf.c rename to lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_sprintf_builtin.c index 9077a7a11..d5fc55537 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_printf.c +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_sprintf_builtin.c @@ -32,13 +32,13 @@ /*Original repository: https://github.com/mpaland/printf*/ -#include "lv_printf.h" +#include "../../lv_conf_internal.h" +#if LV_USE_STDLIB_SPRINTF == LV_STDLIB_BUILTIN -#if LV_SPRINTF_CUSTOM == 0 +#include "../lv_sprintf.h" +#include "../../misc/lv_types.h" -#include - -#define PRINTF_DISABLE_SUPPORT_FLOAT (!LV_SPRINTF_USE_FLOAT) +#define PRINTF_DISABLE_SUPPORT_FLOAT (!LV_USE_FLOAT) // 'ntoa' conversion buffer size, this must be big enough to hold one converted // numeric number including padded zeros (dynamically created on stack) @@ -107,6 +107,11 @@ #define FLAGS_PRECISION (1U << 10U) #define FLAGS_ADAPT_EXP (1U << 11U) +typedef struct { + const char * fmt; + va_list * va; +} lv_vaformat_t; + // import float.h for DBL_MAX #if defined(PRINTF_SUPPORT_FLOAT) #include @@ -547,7 +552,7 @@ static size_t _etoa(out_fct_type out, char * buffer, size_t idx, size_t maxlen, #endif // PRINTF_SUPPORT_FLOAT // internal vsnprintf -static int _vsnprintf(out_fct_type out, char * buffer, const size_t maxlen, const char * format, va_list va) +static int _lv_vsnprintf(out_fct_type out, char * buffer, const size_t maxlen, const char * format, va_list va) { unsigned int flags, width, precision, n; size_t idx = 0U; @@ -754,7 +759,7 @@ static int _vsnprintf(out_fct_type out, char * buffer, const size_t maxlen, cons va_list copy; va_copy(copy, *vaf->va); - idx += _vsnprintf(out, buffer + idx, maxlen - idx, vaf->fmt, copy); + idx += _lv_vsnprintf(out, buffer + idx, maxlen - idx, vaf->fmt, copy); va_end(copy); } else { @@ -860,20 +865,22 @@ static int _vsnprintf(out_fct_type out, char * buffer, const size_t maxlen, cons return (int)idx; } +/////////////////////////////////////////////////////////////////////////////// +/// GLOBAL FUNCTIONS FOR LVGL /////////////////////////////////////////////////////////////////////////////// int lv_snprintf(char * buffer, size_t count, const char * format, ...) { va_list va; va_start(va, format); - const int ret = _vsnprintf(_out_buffer, buffer, count, format, va); + const int ret = _lv_vsnprintf(_out_buffer, buffer, count, format, va); va_end(va); return ret; } int lv_vsnprintf(char * buffer, size_t count, const char * format, va_list va) { - return _vsnprintf(_out_buffer, buffer, count, format, va); + return _lv_vsnprintf(_out_buffer, buffer, count, format, va); } -#endif /*LV_SPRINTF_CUSTOM*/ +#endif /*LV_STDLIB_BUILTIN*/ diff --git a/lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_string_builtin.c b/lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_string_builtin.c new file mode 100644 index 000000000..1e8ba46ab --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_string_builtin.c @@ -0,0 +1,223 @@ +/** + * @file lv_string.c + */ + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" +#if LV_USE_STDLIB_STRING == LV_STDLIB_BUILTIN +#include "../../misc/lv_assert.h" +#include "../../misc/lv_log.h" +#include "../../misc/lv_math.h" +#include "../../stdlib/lv_string.h" +#include "../../stdlib/lv_mem.h" + +/********************* + * DEFINES + *********************/ +#ifdef LV_ARCH_64 + #define MEM_UNIT uint64_t + #define ALIGN_MASK 0x7 +#else + #define MEM_UNIT uint32_t + #define ALIGN_MASK 0x3 +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ +#if LV_USE_LOG && LV_LOG_TRACE_MEM + #define LV_TRACE_MEM(...) LV_LOG_TRACE(__VA_ARGS__) +#else + #define LV_TRACE_MEM(...) +#endif + +#define _COPY(d, s) *d = *s; d++; s++; +#define _SET(d, v) *d = v; d++; +#define _REPEAT8(expr) expr expr expr expr expr expr expr expr + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +LV_ATTRIBUTE_FAST_MEM void * lv_memcpy(void * dst, const void * src, size_t len) +{ + uint8_t * d8 = dst; + const uint8_t * s8 = src; + + /*Simplify for small memories*/ + if(len < 16) { + while(len) { + *d8 = *s8; + d8++; + s8++; + len--; + } + return dst; + } + + lv_uintptr_t d_align = (lv_uintptr_t)d8 & ALIGN_MASK; + lv_uintptr_t s_align = (lv_uintptr_t)s8 & ALIGN_MASK; + + /*Byte copy for unaligned memories*/ + if(s_align != d_align) { + while(len > 32) { + _REPEAT8(_COPY(d8, s8)); + _REPEAT8(_COPY(d8, s8)); + _REPEAT8(_COPY(d8, s8)); + _REPEAT8(_COPY(d8, s8)); + len -= 32; + } + while(len) { + _COPY(d8, s8) + len--; + } + return dst; + } + + /*Make the memories aligned*/ + if(d_align) { + d_align = ALIGN_MASK + 1 - d_align; + while(d_align && len) { + _COPY(d8, s8); + d_align--; + len--; + } + } + + uint32_t * d32 = (uint32_t *)d8; + const uint32_t * s32 = (uint32_t *)s8; + while(len > 32) { + _REPEAT8(_COPY(d32, s32)) + len -= 32; + } + + d8 = (uint8_t *)d32; + s8 = (const uint8_t *)s32; + while(len) { + _COPY(d8, s8) + len--; + } + + return dst; +} + +LV_ATTRIBUTE_FAST_MEM void lv_memset(void * dst, uint8_t v, size_t len) +{ + uint8_t * d8 = (uint8_t *)dst; + uintptr_t d_align = (lv_uintptr_t) d8 & ALIGN_MASK; + + /*Make the address aligned*/ + if(d_align) { + d_align = ALIGN_MASK + 1 - d_align; + while(d_align && len) { + _SET(d8, v); + len--; + d_align--; + } + } + + uint32_t v32 = (uint32_t)v + ((uint32_t)v << 8) + ((uint32_t)v << 16) + ((uint32_t)v << 24); + uint32_t * d32 = (uint32_t *)d8; + + while(len > 32) { + _REPEAT8(_SET(d32, v32)); + len -= 32; + } + + d8 = (uint8_t *)d32; + while(len) { + _SET(d8, v); + len--; + } +} + +LV_ATTRIBUTE_FAST_MEM void * lv_memmove(void * dst, const void * src, size_t len) +{ + if(dst < src || (char *)dst > ((char *)src + len)) { + return lv_memcpy(dst, src, len); + } + + if(dst > src) { + char * tmp = (char *)dst + len - 1; + char * s = (char *)src + len - 1; + + while(len--) { + *tmp-- = *s--; + } + } + else { + char * tmp = (char *)dst; + char * s = (char *)src; + + while(len--) { + *tmp++ = *s++; + } + } + + return dst; +} + +/* See https://en.cppreference.com/w/c/string/byte/strlen for reference */ +size_t lv_strlen(const char * str) +{ + size_t i = 0; + while(str[i]) i++; + + return i; +} + +char * lv_strncpy(char * dst, const char * src, size_t dst_size) +{ + size_t i; + for(i = 0; i < dst_size - 1 && src[i]; i++) { + dst[i] = src[i]; + } + dst[i] = '\0'; + return dst; +} + +char * lv_strcpy(char * dst, const char * src) +{ + char * tmp = dst; + while((*dst++ = *src++) != '\0'); + return tmp; +} + +int32_t lv_strcmp(const char * s1, const char * s2) +{ + while(*s1 && (*s1 == *s2)) { + s1++; + s2++; + } + return *(const unsigned char *)s1 - *(const unsigned char *)s2; +} + +char * lv_strdup(const char * src) +{ + size_t len = lv_strlen(src) + 1; + char * dst = lv_malloc(len); + if(dst == NULL) return NULL; + + lv_memcpy(dst, src, len); /*do memcpy is faster than strncpy when length is known*/ + return dst; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_STDLIB_BUILTIN*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.c b/lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_tlsf.c similarity index 99% rename from lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.c rename to lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_tlsf.c index 27e0a46cf..8910b05ef 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.c +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_tlsf.c @@ -1,16 +1,16 @@ -#include "../lv_conf_internal.h" -#if LV_MEM_CUSTOM == 0 +#include "../../lv_conf_internal.h" +#if LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN #include #include "lv_tlsf.h" -#include "lv_mem.h" -#include "lv_log.h" -#include "lv_assert.h" +#include "../../stdlib/lv_string.h" +#include "../../misc/lv_log.h" +#include "../../misc/lv_assert.h" #undef printf #define printf LV_LOG_ERROR -#define TLSF_MAX_POOL_SIZE LV_MEM_SIZE +#define TLSF_MAX_POOL_SIZE (LV_MEM_SIZE + LV_MEM_POOL_EXPAND_SIZE) #if !defined(_DEBUG) #define _DEBUG 0 @@ -358,7 +358,6 @@ static const size_t block_size_min = sizeof(block_header_t) - sizeof(block_header_t *); static const size_t block_size_max = tlsf_cast(size_t, 1) << FL_INDEX_MAX; - /* The TLSF control structure. */ typedef struct control_t { /* Empty lists point at this block to indicate they are free. */ @@ -1243,4 +1242,4 @@ void * lv_tlsf_realloc(lv_tlsf_t tlsf, void * ptr, size_t size) return p; } -#endif /* LV_MEM_CUSTOM == 0 */ +#endif /*LV_STDLIB_BUILTIN*/ diff --git a/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.h b/lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_tlsf.h similarity index 91% rename from lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.h rename to lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_tlsf.h index f12590b60..0fa6decbe 100644 --- a/lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.h +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/builtin/lv_tlsf.h @@ -1,5 +1,5 @@ -#include "../lv_conf_internal.h" -#if LV_MEM_CUSTOM == 0 +#include "../../lv_conf_internal.h" +#if LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN #ifndef LV_TLSF_H #define LV_TLSF_H @@ -43,6 +43,9 @@ #include +#include "../../osal/lv_os.h" +#include "../../misc/lv_ll.h" + #if defined(__cplusplus) extern "C" { #endif @@ -52,6 +55,16 @@ extern "C" { typedef void * lv_tlsf_t; typedef void * lv_pool_t; +typedef struct { +#if LV_USE_OS + lv_mutex_t mutex; +#endif + lv_tlsf_t tlsf; + uint32_t cur_used; + uint32_t max_used; + lv_ll_t pool_ll; +} lv_tlsf_state_t; + /* Create/destroy a memory pool. */ lv_tlsf_t lv_tlsf_create(void * mem); lv_tlsf_t lv_tlsf_create_with_pool(void * mem, size_t bytes); @@ -92,4 +105,4 @@ int lv_tlsf_check_pool(lv_pool_t pool); #endif /*LV_TLSF_H*/ -#endif /* LV_MEM_CUSTOM == 0 */ +#endif /*LV_STDLIB_BUILTIN*/ diff --git a/lib/libesp32_lvgl/lvgl/src/stdlib/clib/lv_mem_core_clib.c b/lib/libesp32_lvgl/lvgl/src/stdlib/clib/lv_mem_core_clib.c new file mode 100644 index 000000000..9cdddf4d1 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/clib/lv_mem_core_clib.c @@ -0,0 +1,94 @@ +/** + * @file lv_malloc_core.c + */ + +/********************* + * INCLUDES + *********************/ +#include "../lv_mem.h" +#if LV_USE_STDLIB_MALLOC == LV_STDLIB_CLIB +#include "../../stdlib/lv_mem.h" +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_mem_init(void) +{ + return; /*Nothing to init*/ +} + +void lv_mem_deinit(void) +{ + return; /*Nothing to deinit*/ + +} + +lv_mem_pool_t lv_mem_add_pool(void * mem, size_t bytes) +{ + /*Not supported*/ + LV_UNUSED(mem); + LV_UNUSED(bytes); + return NULL; +} + +void lv_mem_remove_pool(lv_mem_pool_t pool) +{ + /*Not supported*/ + LV_UNUSED(pool); + return; +} + +void * lv_malloc_core(size_t size) +{ + return malloc(size); +} + +void * lv_realloc_core(void * p, size_t new_size) +{ + return realloc(p, new_size); +} + +void lv_free_core(void * p) +{ + free(p); +} + +void lv_mem_monitor_core(lv_mem_monitor_t * mon_p) +{ + /*Not supported*/ + LV_UNUSED(mon_p); + return; +} + +lv_result_t lv_mem_test_core(void) +{ + /*Not supported*/ + return LV_RESULT_OK; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_STDLIB_CLIB*/ diff --git a/lib/libesp32_lvgl/lvgl/src/stdlib/clib/lv_sprintf_clib.c b/lib/libesp32_lvgl/lvgl/src/stdlib/clib/lv_sprintf_clib.c new file mode 100644 index 000000000..4f4fb9c74 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/clib/lv_sprintf_clib.c @@ -0,0 +1,58 @@ + +/** + * @file lv_templ.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" +#if LV_USE_STDLIB_SPRINTF == LV_STDLIB_CLIB +#include +#include +#include "../lv_sprintf.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +int lv_snprintf(char * buffer, size_t count, const char * format, ...) +{ + va_list va; + va_start(va, format); + const int ret = vsnprintf(buffer, count, format, va); + va_end(va); + return ret; +} + +int lv_vsnprintf(char * buffer, size_t count, const char * format, va_list va) +{ + return vsnprintf(buffer, count, format, va); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/stdlib/clib/lv_string_clib.c b/lib/libesp32_lvgl/lvgl/src/stdlib/clib/lv_string_clib.c new file mode 100644 index 000000000..7bb35ea93 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/clib/lv_string_clib.c @@ -0,0 +1,93 @@ +/** + * @file lv_string.c + */ + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" +#if LV_USE_STDLIB_STRING == LV_STDLIB_CLIB +#include "../lv_string.h" +#include "../lv_mem.h" /*Need lv_malloc*/ +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +LV_ATTRIBUTE_FAST_MEM void * lv_memcpy(void * dst, const void * src, size_t len) +{ + return memcpy(dst, src, len); +} + +LV_ATTRIBUTE_FAST_MEM void lv_memset(void * dst, uint8_t v, size_t len) +{ + memset(dst, v, len); +} + +LV_ATTRIBUTE_FAST_MEM void * lv_memmove(void * dst, const void * src, size_t len) +{ + return memmove(dst, src, len); +} + +size_t lv_strlen(const char * str) +{ + return strlen(str); +} + +char * lv_strncpy(char * dst, const char * src, size_t dest_size) +{ + if(dest_size > 0) { + dst[0] = '\0'; + strncat(dst, src, dest_size - 1); + } + + return dst; +} + +char * lv_strcpy(char * dst, const char * src) +{ + return strcpy(dst, src); +} + +int32_t lv_strcmp(const char * s1, const char * s2) +{ + return strcmp(s1, s2); +} + +char * lv_strdup(const char * src) +{ + /*strdup uses malloc, so use the lv_malloc when LV_USE_STDLIB_MALLOC is not LV_STDLIB_CLIB */ + size_t len = lv_strlen(src) + 1; + char * dst = lv_malloc(len); + if(dst == NULL) return NULL; + + lv_memcpy(dst, src, len); /*do memcpy is faster than strncpy when length is known*/ + return dst; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_STDLIB_CLIB*/ diff --git a/lib/libesp32_lvgl/lvgl/src/stdlib/lv_mem.c b/lib/libesp32_lvgl/lvgl/src/stdlib/lv_mem.c new file mode 100644 index 000000000..95c1fcb17 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/lv_mem.c @@ -0,0 +1,168 @@ +/** + * @file lv_mem.c + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_mem.h" +#include "lv_string.h" +#include "../misc/lv_assert.h" +#include "../misc/lv_log.h" +#include "../core/lv_global.h" + +#if LV_USE_OS == LV_OS_PTHREAD + #include +#endif + +/********************* + * DEFINES + *********************/ +/*memset the allocated memories to 0xaa and freed memories to 0xbb (just for testing purposes)*/ +#ifndef LV_MEM_ADD_JUNK + #define LV_MEM_ADD_JUNK 0 +#endif + +#define zero_mem LV_GLOBAL_DEFAULT()->memory_zero + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +void * lv_malloc_core(size_t size); +void * lv_realloc_core(void * p, size_t new_size); +void lv_free_core(void * p); +void lv_mem_monitor_core(lv_mem_monitor_t * mon_p); +lv_result_t lv_mem_test_core(void); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ +#if LV_USE_LOG && LV_LOG_TRACE_MEM + #define LV_TRACE_MEM(...) LV_LOG_TRACE(__VA_ARGS__) +#else + #define LV_TRACE_MEM(...) +#endif + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void * lv_malloc(size_t size) +{ + LV_TRACE_MEM("allocating %lu bytes", (unsigned long)size); + if(size == 0) { + LV_TRACE_MEM("using zero_mem"); + return &zero_mem; + } + + void * alloc = lv_malloc_core(size); + + if(alloc == NULL) { + LV_LOG_INFO("couldn't allocate memory (%lu bytes)", (unsigned long)size); +#if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO + lv_mem_monitor_t mon; + lv_mem_monitor(&mon); + LV_LOG_INFO("used: %6d (%3d %%), frag: %3d %%, biggest free: %6d", + (int)(mon.total_size - mon.free_size), mon.used_pct, mon.frag_pct, + (int)mon.free_biggest_size); +#endif + return NULL; + } + +#if LV_MEM_ADD_JUNK + lv_memset(alloc, 0xaa, size); +#endif + + LV_TRACE_MEM("allocated at %p", alloc); + return alloc; +} + +void * lv_malloc_zeroed(size_t size) +{ + LV_TRACE_MEM("allocating %lu bytes", (unsigned long)size); + if(size == 0) { + LV_TRACE_MEM("using zero_mem"); + return &zero_mem; + } + + void * alloc = lv_malloc_core(size); + if(alloc == NULL) { + LV_LOG_INFO("couldn't allocate memory (%lu bytes)", (unsigned long)size); +#if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO + lv_mem_monitor_t mon; + lv_mem_monitor(&mon); + LV_LOG_INFO("used: %6d (%3d %%), frag: %3d %%, biggest free: %6d", + (int)(mon.total_size - mon.free_size), mon.used_pct, mon.frag_pct, + (int)mon.free_biggest_size); +#endif + return NULL; + } + + lv_memzero(alloc, size); + + LV_TRACE_MEM("allocated at %p", alloc); + return alloc; +} + +void lv_free(void * data) +{ + LV_TRACE_MEM("freeing %p", data); + if(data == &zero_mem) return; + if(data == NULL) return; + + lv_free_core(data); +} + +void * lv_realloc(void * data_p, size_t new_size) +{ + LV_TRACE_MEM("reallocating %p with %lu size", data_p, (unsigned long)new_size); + if(new_size == 0) { + LV_TRACE_MEM("using zero_mem"); + lv_free(data_p); + return &zero_mem; + } + + if(data_p == &zero_mem) return lv_malloc(new_size); + + void * new_p = lv_realloc_core(data_p, new_size); + + if(new_p == NULL) { + LV_LOG_ERROR("couldn't reallocate memory"); + return NULL; + } + + LV_TRACE_MEM("reallocated at %p", new_p); + return new_p; +} + +lv_result_t lv_mem_test(void) +{ + if(zero_mem != ZERO_MEM_SENTINEL) { + LV_LOG_WARN("zero_mem is written"); + return LV_RESULT_INVALID; + } + + return lv_mem_test_core(); +} + +void lv_mem_monitor(lv_mem_monitor_t * mon_p) +{ + lv_memzero(mon_p, sizeof(lv_mem_monitor_t)); + lv_mem_monitor_core(mon_p); +} + +/********************** + * STATIC FUNCTIONS + **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/stdlib/lv_mem.h b/lib/libesp32_lvgl/lvgl/src/stdlib/lv_mem.h new file mode 100644 index 000000000..48a176379 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/lv_mem.h @@ -0,0 +1,143 @@ +/** + * @file lv_mem.h + * + */ + +#ifndef LV_MEM_H +#define LV_MEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include +#include +#include + +#include "../misc/lv_types.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef void * lv_mem_pool_t; + +/** + * Heap information structure. + */ +typedef struct { + uint32_t total_size; /**< Total heap size*/ + uint32_t free_cnt; + uint32_t free_size; /**< Size of available memory*/ + uint32_t free_biggest_size; + uint32_t used_cnt; + uint32_t max_used; /**< Max size of Heap memory used*/ + uint8_t used_pct; /**< Percentage used*/ + uint8_t frag_pct; /**< Amount of fragmentation*/ +} lv_mem_monitor_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Initialize to use malloc/free/realloc etc + */ +void lv_mem_init(void); + +/** + * Drop all dynamically allocated memory and reset the memory pools' state + */ +void lv_mem_deinit(void); + +lv_mem_pool_t lv_mem_add_pool(void * mem, size_t bytes); + +void lv_mem_remove_pool(lv_mem_pool_t pool); + +/** + * Allocate memory dynamically + * @param size requested size in bytes + * @return pointer to allocated uninitialized memory, or NULL on failure + */ +void * lv_malloc(size_t size); + +/** + * Allocate zeroed memory dynamically + * @param size requested size in bytes + * @return pointer to allocated zeroed memory, or NULL on failure + */ +void * lv_malloc_zeroed(size_t size); + +/** + * Free an allocated data + * @param data pointer to an allocated memory + */ +void lv_free(void * data); + +/** + * Reallocate a memory with a new size. The old content will be kept. + * @param data_p pointer to an allocated memory. + * Its content will be copied to the new memory block and freed + * @param new_size the desired new size in byte + * @return pointer to the new memory, NULL on failure + */ +void * lv_realloc(void * data_p, size_t new_size); + +/** + * Used internally to execute a plain `malloc` operation + * @param size size in bytes to `malloc` + */ +void * lv_malloc_core(size_t size); + +/** + * Used internally to execute a plain `free` operation + * @param p memory address to free + */ +void lv_free_core(void * p); + +/** + * Used internally to execute a plain realloc operation + * @param p memory address to realloc + * @param new_size size in bytes to realloc + */ +void * lv_realloc_core(void * p, size_t new_size); + +/** + * Used internally to execute a plain malloc operation + * @param size size in bytes to malloc + */ +void lv_mem_monitor_core(lv_mem_monitor_t * mon_p); + +lv_result_t lv_mem_test_core(void); + +/** + * @brief Tests the memory allocation system by allocating and freeing a block of memory. + * @return LV_RESULT_OK if the memory allocation system is working properly, or LV_RESULT_INVALID if there is an error. + */ +lv_result_t lv_mem_test(void); + +/** + * Give information about the work memory of dynamic allocation + * @param mon_p pointer to a lv_mem_monitor_t variable, + * the result of the analysis will be stored here + */ +void lv_mem_monitor(lv_mem_monitor_t * mon_p); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_MEM_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/stdlib/lv_sprintf.h b/lib/libesp32_lvgl/lvgl/src/stdlib/lv_sprintf.h new file mode 100644 index 000000000..cd5a80346 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/lv_sprintf.h @@ -0,0 +1,47 @@ +/** + * lv_snprintf.h + * + */ + +#ifndef _LV_SPRINTF_H_ +#define _LV_SPRINTF_H_ + +#if defined(__has_include) + #if __has_include() + #include + /* platform-specific printf format for int32_t, usually "d" or "ld" */ + #define LV_PRId32 PRId32 + #define LV_PRIu32 PRIu32 + #define LV_PRIx32 PRIx32 + #define LV_PRIX32 PRIX32 + #else + #define LV_PRId32 "d" + #define LV_PRIu32 "u" + #define LV_PRIx32 "x" + #define LV_PRIX32 "X" + #endif +#else + /* hope this is correct for ports without __has_include or without inttypes.h */ + #define LV_PRId32 "d" + #define LV_PRIu32 "u" + #define LV_PRIx32 "x" + #define LV_PRIX32 "X" +#endif + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int lv_snprintf(char * buffer, size_t count, const char * format, ...); + +int lv_vsnprintf(char * buffer, size_t count, const char * format, va_list va); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /* _LV_SPRINTF_H_*/ diff --git a/lib/libesp32_lvgl/lvgl/src/stdlib/lv_string.h b/lib/libesp32_lvgl/lvgl/src/stdlib/lv_string.h new file mode 100644 index 000000000..20cda4ecf --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/lv_string.h @@ -0,0 +1,125 @@ +/** + * @file lv_stringn.h + * + */ + +#ifndef LV_STRING_H +#define LV_STRING_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" +#include +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * @brief Copies a block of memory from a source address to a destination address. + * @param dst Pointer to the destination array where the content is to be copied. + * @param src Pointer to the source of data to be copied. + * @param len Number of bytes to copy. + * @return Pointer to the destination array. + * @note The function does not check for any overlapping of the source and destination memory blocks. + */ +void * lv_memcpy(void * dst, const void * src, size_t len); + +/** + * @brief Fills a block of memory with a specified value. + * @param dst Pointer to the destination array to fill with the specified value. + * @param v Value to be set. The value is passed as an int, but the function fills + * the block of memory using the unsigned char conversion of this value. + * @param len Number of bytes to be set to the value. + */ +void lv_memset(void * dst, uint8_t v, size_t len); + +/** + * @brief Move a block of memory from source to destination + * @param dst Pointer to the destination array where the content is to be copied. + * @param src Pointer to the source of data to be copied. + * @param len Number of bytes to copy + * @return Pointer to the destination array. + */ +void * lv_memmove(void * dst, const void * src, size_t len); + +/** + * Same as `memset(dst, 0x00, len)`. + * @param dst pointer to the destination buffer + * @param len number of byte to set + */ +static inline void lv_memzero(void * dst, size_t len) +{ + lv_memset(dst, 0x00, len); +} + +/** + * @brief Computes the length of the string str up to, but not including the terminating null character. + * @param str Pointer to the null-terminated byte string to be examined. + * @return The length of the string in bytes. + */ +size_t lv_strlen(const char * str); + +/** + * @brief Copies up to dest_size characters from the string pointed to by src to the character array pointed to by dst. + * @param dst Pointer to the destination array where the content is to be copied. + * @param src Pointer to the source of data to be copied. + * @param dest_size Maximum number of characters to be copied to dst, including the null character. + * @return A pointer to the destination array, which is dst. + */ +char * lv_strncpy(char * dst, const char * src, size_t dest_size); + +/** + * @brief Copies the string pointed to by src, including the terminating null character, + * to the character array pointed to by dst. + * @param dst Pointer to the destination array where the content is to be copied. + * @param src Pointer to the source of data to be copied. + * @return A pointer to the destination array, which is dst. + */ +char * lv_strcpy(char * dst, const char * src); + +/** + * @brief This function will compare two strings without specified length. + * @param s1 pointer to the first string + * @param s2 pointer to the second string + * @return the difference between the value of the first unmatching character. + */ +int32_t lv_strcmp(const char * s1, const char * s2); + +/** + * @brief Duplicate a string by allocating a new one and copying the content. + * @param src Pointer to the source of data to be copied. + * @return A pointer to the new allocated string. NULL if failed. + */ +char * lv_strdup(const char * src); + +/** + * @brief Duplicate a string by allocating a new one and copying the content. + * @param src Pointer to the source of data to be copied. + * @return A pointer to the new allocated string. NULL if failed. + */ +char * lv_strdup(const char * src); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_STRING_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/stdlib/micropython/lv_mem_core_micropython.c b/lib/libesp32_lvgl/lvgl/src/stdlib/micropython/lv_mem_core_micropython.c new file mode 100644 index 000000000..69c8bd681 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/micropython/lv_mem_core_micropython.c @@ -0,0 +1,95 @@ +/** + * @file lv_malloc_core.c + */ + +/********************* + * INCLUDES + *********************/ +#include "../lv_mem.h" +#if LV_USE_STDLIB_MALLOC == LV_STDLIB_MICROPYTHON +#include "../../stdlib/lv_mem.h" +#include "include/lv_mp_mem_custom_include.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_mem_init(void) +{ + return; /*Nothing to init*/ +} + +void lv_mem_deinit(void) +{ + return; /*Nothing to deinit*/ + +} + +lv_mem_pool_t lv_mem_add_pool(void * mem, size_t bytes) +{ + /*Not supported*/ + LV_UNUSED(mem); + LV_UNUSED(bytes); + return NULL; +} + +void lv_mem_remove_pool(lv_mem_pool_t pool) +{ + /*Not supported*/ + LV_UNUSED(pool); + return; +} + +void * lv_malloc_core(size_t size) +{ + return m_malloc(size); +} + +void * lv_realloc_core(void * p, size_t new_size) +{ + return m_realloc(p, new_size); +} + +void lv_free_core(void * p) +{ + m_free(p); +} + +void lv_mem_monitor_core(lv_mem_monitor_t * mon_p) +{ + /*Not supported*/ + LV_UNUSED(mon_p); + return; +} + +lv_result_t lv_mem_test_core(void) +{ + /*Not supported*/ + return LV_RESULT_OK; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_STDLIB_MICROPYTHON*/ diff --git a/lib/libesp32_lvgl/lvgl/src/stdlib/rtthread/lv_mem_core_rtthread.c b/lib/libesp32_lvgl/lvgl/src/stdlib/rtthread/lv_mem_core_rtthread.c new file mode 100644 index 000000000..29a600a6a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/rtthread/lv_mem_core_rtthread.c @@ -0,0 +1,98 @@ +/** + * @file lv_malloc_core_rtthread.c + */ + +/********************* + * INCLUDES + *********************/ +#include "../lv_mem.h" +#if LV_USE_STDLIB_MALLOC == LV_STDLIB_RTTHREAD +#include "../../stdlib/lv_mem.h" +#include + +#ifndef RT_USING_HEAP + #error "lv_mem_core_rtthread: RT_USING_HEAP is required. Define it in rtconfig.h" +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_mem_init(void) +{ + return; /*Nothing to init*/ +} + +void lv_mem_deinit(void) +{ + return; /*Nothing to deinit*/ +} + +lv_mem_pool_t lv_mem_add_pool(void * mem, size_t bytes) +{ + /*Not supported*/ + LV_UNUSED(mem); + LV_UNUSED(bytes); + return NULL; +} + +void lv_mem_remove_pool(lv_mem_pool_t pool) +{ + /*Not supported*/ + LV_UNUSED(pool); + return; +} + +void * lv_malloc_core(size_t size) +{ + return rt_malloc(size); +} + +void * lv_realloc_core(void * p, size_t new_size) +{ + return rt_realloc(p, new_size); +} + +void lv_free_core(void * p) +{ + rt_free(p); +} + +void lv_mem_monitor_core(lv_mem_monitor_t * mon_p) +{ + /*Not supported*/ + LV_UNUSED(mon_p); + return; +} + +lv_result_t lv_mem_test_core(void) +{ + /*Not supported*/ + return LV_RESULT_OK; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_STDLIB_RTTHREAD*/ diff --git a/lib/libesp32_lvgl/lvgl/src/stdlib/rtthread/lv_sprintf_rtthread.c b/lib/libesp32_lvgl/lvgl/src/stdlib/rtthread/lv_sprintf_rtthread.c new file mode 100644 index 000000000..721f4fd05 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/rtthread/lv_sprintf_rtthread.c @@ -0,0 +1,61 @@ +/** + * @file lv_sprintf_rtthread.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" +#if LV_USE_STDLIB_SPRINTF == LV_STDLIB_RTTHREAD +#include +#include +#include "../lv_sprintf.h" + +#if LV_USE_FLOAT == 1 + #warning "lv_sprintf_rtthread: rtthread not support float in sprintf" +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +int lv_snprintf(char * buffer, size_t count, const char * format, ...) +{ + va_list va; + va_start(va, format); + const int ret = rt_vsnprintf(buffer, count, format, va); + va_end(va); + return ret; +} + +int lv_vsnprintf(char * buffer, size_t count, const char * format, va_list va) +{ + return rt_vsnprintf(buffer, count, format, va); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_STDLIB_RTTHREAD*/ diff --git a/lib/libesp32_lvgl/lvgl/src/stdlib/rtthread/lv_string_rtthread.c b/lib/libesp32_lvgl/lvgl/src/stdlib/rtthread/lv_string_rtthread.c new file mode 100644 index 000000000..02480c74a --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/stdlib/rtthread/lv_string_rtthread.c @@ -0,0 +1,92 @@ +/** + * @file lv_string_rtthread.c + */ + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" +#if LV_USE_STDLIB_STRING == LV_STDLIB_RTTHREAD +#include "../lv_string.h" +#include "../lv_mem.h" /*Need lv_malloc*/ +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +LV_ATTRIBUTE_FAST_MEM void * lv_memcpy(void * dst, const void * src, size_t len) +{ + return rt_memcpy(dst, src, len); +} + +LV_ATTRIBUTE_FAST_MEM void lv_memset(void * dst, uint8_t v, size_t len) +{ + rt_memset(dst, v, len); +} + +LV_ATTRIBUTE_FAST_MEM void * lv_memmove(void * dst, const void * src, size_t len) +{ + return rt_memmove(dst, src, len); +} + +size_t lv_strlen(const char * str) +{ + return rt_strlen(str); +} + +char * lv_strncpy(char * dst, const char * src, size_t dest_size) +{ + return rt_strncpy(dst, src, dest_size); +} + +char * lv_strcpy(char * dst, const char * src) +{ + return rt_strcpy(dst, src); +} + +int32_t lv_strcmp(const char * s1, const char * s2) +{ + return rt_strcmp(s1, s2); +} + +char * lv_strdup(const char * src) +{ + /*strdup uses rt_malloc, so use the lv_malloc when LV_USE_STDLIB_MALLOC is not LV_STDLIB_RTTHREAD */ +#if LV_USE_STDLIB_MALLOC != LV_STDLIB_RTTHREAD + size_t len = lv_strlen(src) + 1; + char * dst = lv_malloc(len); + if(dst == NULL) return NULL; + + lv_memcpy(dst, src, len); /*do memcpy is faster than strncpy when length is known*/ + return dst; +#else + return rt_strdup(src); +#endif +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /*LV_STDLIB_RTTHREAD*/ diff --git a/lib/libesp32_lvgl/lvgl/src/themes/default/lv_theme_default.c b/lib/libesp32_lvgl/lvgl/src/themes/default/lv_theme_default.c new file mode 100644 index 000000000..a6a5eb242 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/themes/default/lv_theme_default.c @@ -0,0 +1,1219 @@ +/** + * @file lv_theme_default.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" /*To see all the widgets*/ + +#if LV_USE_THEME_DEFAULT + +#include "../lv_theme.h" +#include "../../misc/lv_color.h" +#include "../../core/lv_global.h" + +/********************* + * DEFINES + *********************/ + +struct _my_theme_t; +typedef struct _my_theme_t my_theme_t; + +#define theme_def (*(my_theme_t **)(&LV_GLOBAL_DEFAULT()->theme_default)) + +#define MODE_DARK 1 +#define RADIUS_DEFAULT _LV_DPX_CALC(theme->disp_dpi, theme->disp_size == DISP_LARGE ? 12 : 8) + +/*SCREEN*/ +#define LIGHT_COLOR_SCR lv_palette_lighten(LV_PALETTE_GREY, 4) +#define LIGHT_COLOR_CARD lv_color_white() +#define LIGHT_COLOR_TEXT lv_palette_darken(LV_PALETTE_GREY, 4) +#define LIGHT_COLOR_GREY lv_palette_lighten(LV_PALETTE_GREY, 2) +#define DARK_COLOR_SCR lv_color_hex(0x15171A) +#define DARK_COLOR_CARD lv_color_hex(0x282b30) +#define DARK_COLOR_TEXT lv_palette_lighten(LV_PALETTE_GREY, 5) +#define DARK_COLOR_GREY lv_color_hex(0x2f3237) + +#define TRANSITION_TIME LV_THEME_DEFAULT_TRANSITION_TIME +#define BORDER_WIDTH _LV_DPX_CALC(theme->disp_dpi, 2) +#define OUTLINE_WIDTH _LV_DPX_CALC(theme->disp_dpi, 3) + +#define PAD_DEF _LV_DPX_CALC(theme->disp_dpi, theme->disp_size == DISP_LARGE ? 24 : theme->disp_size == DISP_MEDIUM ? 20 : 16) +#define PAD_SMALL _LV_DPX_CALC(theme->disp_dpi, theme->disp_size == DISP_LARGE ? 14 : theme->disp_size == DISP_MEDIUM ? 12 : 10) +#define PAD_TINY _LV_DPX_CALC(theme->disp_dpi, theme->disp_size == DISP_LARGE ? 8 : theme->disp_size == DISP_MEDIUM ? 6 : 2) + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + lv_style_t scr; + lv_style_t scrollbar; + lv_style_t scrollbar_scrolled; + lv_style_t card; + lv_style_t btn; + + /*Utility*/ + lv_style_t bg_color_primary; + lv_style_t bg_color_primary_muted; + lv_style_t bg_color_secondary; + lv_style_t bg_color_secondary_muted; + lv_style_t bg_color_grey; + lv_style_t bg_color_white; + lv_style_t pressed; + lv_style_t disabled; + lv_style_t pad_zero; + lv_style_t pad_tiny; + lv_style_t pad_small; + lv_style_t pad_normal; + lv_style_t pad_gap; + lv_style_t line_space_large; + lv_style_t text_align_center; + lv_style_t outline_primary; + lv_style_t outline_secondary; + lv_style_t circle; + lv_style_t no_radius; + lv_style_t clip_corner; +#if LV_THEME_DEFAULT_GROW + lv_style_t grow; +#endif + lv_style_t transition_delayed; + lv_style_t transition_normal; + lv_style_t anim; + lv_style_t anim_fast; + + /*Parts*/ + lv_style_t knob; + +#if LV_USE_ARC + lv_style_t arc_indic; + lv_style_t arc_indic_primary; +#endif + +#if LV_USE_CHART + lv_style_t chart_series, chart_indic, chart_bg; +#endif + +#if LV_USE_DROPDOWN + lv_style_t dropdown_list; +#endif + +#if LV_USE_CHECKBOX + lv_style_t cb_marker, cb_marker_checked; +#endif + +#if LV_USE_SWITCH + lv_style_t switch_knob; +#endif + +#if LV_USE_LINE + lv_style_t line; +#endif + +#if LV_USE_TABLE + lv_style_t table_cell; +#endif + +#if LV_USE_TEXTAREA + lv_style_t ta_cursor, ta_placeholder; +#endif + +#if LV_USE_CALENDAR + lv_style_t calendar_btnm_bg, calendar_btnm_day, calendar_header; +#endif + +#if LV_USE_MENU + lv_style_t menu_bg, menu_cont, menu_sidebar_cont, menu_main_cont, menu_page, menu_header_cont, menu_header_btn, + menu_section, menu_pressed, menu_separator; +#endif + +#if LV_USE_MSGBOX + lv_style_t msgbox_backdrop_bg; +#endif + +#if LV_USE_KEYBOARD + lv_style_t keyboard_button_bg; +#endif + +#if LV_USE_LIST + lv_style_t list_bg, list_btn, list_item_grow; +#endif + +#if LV_USE_TABVIEW + lv_style_t tab_bg_focus, tab_btn; +#endif +#if LV_USE_LED + lv_style_t led; +#endif + +#if LV_USE_SCALE + lv_style_t scale; +#endif +} my_theme_styles_t; + +typedef enum { + DISP_SMALL = 3, + DISP_MEDIUM = 2, + DISP_LARGE = 1, +} disp_size_t; + +struct _my_theme_t { + lv_theme_t base; + disp_size_t disp_size; + int32_t disp_dpi; + lv_color_t color_scr; + lv_color_t color_text; + lv_color_t color_card; + lv_color_t color_grey; + bool inited; + my_theme_styles_t styles; + + lv_color_filter_dsc_t dark_filter; + lv_color_filter_dsc_t grey_filter; + +#if LV_THEME_DEFAULT_TRANSITION_TIME + lv_style_transition_dsc_t trans_delayed; + lv_style_transition_dsc_t trans_normal; +#endif +}; + +/********************** + * STATIC PROTOTYPES + **********************/ +static void theme_apply(lv_theme_t * th, lv_obj_t * obj); +static void style_init_reset(lv_style_t * style); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * STATIC FUNCTIONS + **********************/ + +static lv_color_t dark_color_filter_cb(const lv_color_filter_dsc_t * f, lv_color_t c, lv_opa_t opa) +{ + LV_UNUSED(f); + return lv_color_darken(c, opa); +} + +static lv_color_t grey_filter_cb(const lv_color_filter_dsc_t * f, lv_color_t color, lv_opa_t opa) +{ + LV_UNUSED(f); + if(theme_def->base.flags & MODE_DARK) return lv_color_mix(lv_palette_darken(LV_PALETTE_GREY, 2), color, opa); + else return lv_color_mix(lv_palette_lighten(LV_PALETTE_GREY, 2), color, opa); +} + +static void style_init(my_theme_t * theme) +{ +#if TRANSITION_TIME + static const lv_style_prop_t trans_props[] = { + LV_STYLE_BG_OPA, LV_STYLE_BG_COLOR, + LV_STYLE_TRANSFORM_WIDTH, LV_STYLE_TRANSFORM_HEIGHT, + LV_STYLE_TRANSLATE_Y, LV_STYLE_TRANSLATE_X, + LV_STYLE_TRANSFORM_ROTATION, + LV_STYLE_TRANSFORM_SCALE_X, LV_STYLE_TRANSFORM_SCALE_Y, + LV_STYLE_COLOR_FILTER_OPA, LV_STYLE_COLOR_FILTER_DSC, + 0 + }; +#endif + + theme->color_scr = theme->base.flags & MODE_DARK ? DARK_COLOR_SCR : LIGHT_COLOR_SCR; + theme->color_text = theme->base.flags & MODE_DARK ? DARK_COLOR_TEXT : LIGHT_COLOR_TEXT; + theme->color_card = theme->base.flags & MODE_DARK ? DARK_COLOR_CARD : LIGHT_COLOR_CARD; + theme->color_grey = theme->base.flags & MODE_DARK ? DARK_COLOR_GREY : LIGHT_COLOR_GREY; + + style_init_reset(&theme->styles.transition_delayed); + style_init_reset(&theme->styles.transition_normal); +#if TRANSITION_TIME + lv_style_transition_dsc_init(&theme->trans_delayed, trans_props, lv_anim_path_linear, TRANSITION_TIME, 70, NULL); + lv_style_transition_dsc_init(&theme->trans_normal, trans_props, lv_anim_path_linear, TRANSITION_TIME, 0, NULL); + + lv_style_set_transition(&theme->styles.transition_delayed, + &theme->trans_delayed); /*Go back to default state with delay*/ + + lv_style_set_transition(&theme->styles.transition_normal, &theme->trans_normal); /*Go back to default state with delay*/ +#endif + + style_init_reset(&theme->styles.scrollbar); + lv_color_t sb_color = (theme->base.flags & MODE_DARK) ? lv_palette_darken(LV_PALETTE_GREY, + 2) : lv_palette_main(LV_PALETTE_GREY); + lv_style_set_bg_color(&theme->styles.scrollbar, sb_color); + + lv_style_set_radius(&theme->styles.scrollbar, LV_RADIUS_CIRCLE); + lv_style_set_pad_all(&theme->styles.scrollbar, _LV_DPX_CALC(theme->disp_dpi, 7)); + lv_style_set_width(&theme->styles.scrollbar, _LV_DPX_CALC(theme->disp_dpi, 5)); + lv_style_set_bg_opa(&theme->styles.scrollbar, LV_OPA_40); +#if TRANSITION_TIME + lv_style_set_transition(&theme->styles.scrollbar, &theme->trans_normal); +#endif + + style_init_reset(&theme->styles.scrollbar_scrolled); + lv_style_set_bg_opa(&theme->styles.scrollbar_scrolled, LV_OPA_COVER); + + style_init_reset(&theme->styles.scr); + lv_style_set_bg_opa(&theme->styles.scr, LV_OPA_COVER); + lv_style_set_bg_color(&theme->styles.scr, theme->color_scr); + lv_style_set_text_color(&theme->styles.scr, theme->color_text); + lv_style_set_text_font(&theme->styles.scr, theme->base.font_normal); + lv_style_set_pad_row(&theme->styles.scr, PAD_SMALL); + lv_style_set_pad_column(&theme->styles.scr, PAD_SMALL); + + style_init_reset(&theme->styles.card); + lv_style_set_radius(&theme->styles.card, RADIUS_DEFAULT); + lv_style_set_bg_opa(&theme->styles.card, LV_OPA_COVER); + lv_style_set_bg_color(&theme->styles.card, theme->color_card); + lv_style_set_border_color(&theme->styles.card, theme->color_grey); + lv_style_set_border_width(&theme->styles.card, BORDER_WIDTH); + lv_style_set_border_post(&theme->styles.card, true); + lv_style_set_text_color(&theme->styles.card, theme->color_text); + lv_style_set_pad_all(&theme->styles.card, PAD_DEF); + lv_style_set_pad_row(&theme->styles.card, PAD_SMALL); + lv_style_set_pad_column(&theme->styles.card, PAD_SMALL); + lv_style_set_line_color(&theme->styles.card, lv_palette_main(LV_PALETTE_GREY)); + lv_style_set_line_width(&theme->styles.card, _LV_DPX_CALC(theme->disp_dpi, 1)); + + style_init_reset(&theme->styles.outline_primary); + lv_style_set_outline_color(&theme->styles.outline_primary, theme->base.color_primary); + lv_style_set_outline_width(&theme->styles.outline_primary, OUTLINE_WIDTH); + lv_style_set_outline_pad(&theme->styles.outline_primary, OUTLINE_WIDTH); + lv_style_set_outline_opa(&theme->styles.outline_primary, LV_OPA_50); + + style_init_reset(&theme->styles.outline_secondary); + lv_style_set_outline_color(&theme->styles.outline_secondary, theme->base.color_secondary); + lv_style_set_outline_width(&theme->styles.outline_secondary, OUTLINE_WIDTH); + lv_style_set_outline_opa(&theme->styles.outline_secondary, LV_OPA_50); + + style_init_reset(&theme->styles.btn); + lv_style_set_radius(&theme->styles.btn, + _LV_DPX_CALC(theme->disp_dpi, theme->disp_size == DISP_LARGE ? 16 : theme->disp_size == DISP_MEDIUM ? 12 : 8)); + lv_style_set_bg_opa(&theme->styles.btn, LV_OPA_COVER); + lv_style_set_bg_color(&theme->styles.btn, theme->color_grey); + if(!(theme->base.flags & MODE_DARK)) { + lv_style_set_shadow_color(&theme->styles.btn, lv_palette_main(LV_PALETTE_GREY)); + lv_style_set_shadow_width(&theme->styles.btn, LV_DPX(3)); + lv_style_set_shadow_opa(&theme->styles.btn, LV_OPA_50); + lv_style_set_shadow_offset_y(&theme->styles.btn, _LV_DPX_CALC(theme->disp_dpi, LV_DPX(4))); + } + lv_style_set_text_color(&theme->styles.btn, theme->color_text); + lv_style_set_pad_hor(&theme->styles.btn, PAD_DEF); + lv_style_set_pad_ver(&theme->styles.btn, PAD_SMALL); + lv_style_set_pad_column(&theme->styles.btn, _LV_DPX_CALC(theme->disp_dpi, 5)); + lv_style_set_pad_row(&theme->styles.btn, _LV_DPX_CALC(theme->disp_dpi, 5)); + + lv_color_filter_dsc_init(&theme->dark_filter, dark_color_filter_cb); + lv_color_filter_dsc_init(&theme->grey_filter, grey_filter_cb); + + style_init_reset(&theme->styles.pressed); + lv_style_set_color_filter_dsc(&theme->styles.pressed, &theme->dark_filter); + lv_style_set_color_filter_opa(&theme->styles.pressed, 35); + + style_init_reset(&theme->styles.disabled); + lv_style_set_color_filter_dsc(&theme->styles.disabled, &theme->grey_filter); + lv_style_set_color_filter_opa(&theme->styles.disabled, LV_OPA_50); + + style_init_reset(&theme->styles.clip_corner); + lv_style_set_clip_corner(&theme->styles.clip_corner, true); + lv_style_set_border_post(&theme->styles.clip_corner, true); + + style_init_reset(&theme->styles.pad_normal); + lv_style_set_pad_all(&theme->styles.pad_normal, PAD_DEF); + lv_style_set_pad_row(&theme->styles.pad_normal, PAD_DEF); + lv_style_set_pad_column(&theme->styles.pad_normal, PAD_DEF); + + style_init_reset(&theme->styles.pad_small); + lv_style_set_pad_all(&theme->styles.pad_small, PAD_SMALL); + lv_style_set_pad_gap(&theme->styles.pad_small, PAD_SMALL); + + style_init_reset(&theme->styles.pad_gap); + lv_style_set_pad_row(&theme->styles.pad_gap, _LV_DPX_CALC(theme->disp_dpi, 10)); + lv_style_set_pad_column(&theme->styles.pad_gap, _LV_DPX_CALC(theme->disp_dpi, 10)); + + style_init_reset(&theme->styles.line_space_large); + lv_style_set_text_line_space(&theme->styles.line_space_large, _LV_DPX_CALC(theme->disp_dpi, 20)); + + style_init_reset(&theme->styles.text_align_center); + lv_style_set_text_align(&theme->styles.text_align_center, LV_TEXT_ALIGN_CENTER); + + style_init_reset(&theme->styles.pad_zero); + lv_style_set_pad_all(&theme->styles.pad_zero, 0); + lv_style_set_pad_row(&theme->styles.pad_zero, 0); + lv_style_set_pad_column(&theme->styles.pad_zero, 0); + + style_init_reset(&theme->styles.pad_tiny); + lv_style_set_pad_all(&theme->styles.pad_tiny, PAD_TINY); + lv_style_set_pad_row(&theme->styles.pad_tiny, PAD_TINY); + lv_style_set_pad_column(&theme->styles.pad_tiny, PAD_TINY); + + style_init_reset(&theme->styles.bg_color_primary); + lv_style_set_bg_color(&theme->styles.bg_color_primary, theme->base.color_primary); + lv_style_set_text_color(&theme->styles.bg_color_primary, lv_color_white()); + lv_style_set_bg_opa(&theme->styles.bg_color_primary, LV_OPA_COVER); + + style_init_reset(&theme->styles.bg_color_primary_muted); + lv_style_set_bg_color(&theme->styles.bg_color_primary_muted, theme->base.color_primary); + lv_style_set_text_color(&theme->styles.bg_color_primary_muted, theme->base.color_primary); + lv_style_set_bg_opa(&theme->styles.bg_color_primary_muted, LV_OPA_20); + + style_init_reset(&theme->styles.bg_color_secondary); + lv_style_set_bg_color(&theme->styles.bg_color_secondary, theme->base.color_secondary); + lv_style_set_text_color(&theme->styles.bg_color_secondary, lv_color_white()); + lv_style_set_bg_opa(&theme->styles.bg_color_secondary, LV_OPA_COVER); + + style_init_reset(&theme->styles.bg_color_secondary_muted); + lv_style_set_bg_color(&theme->styles.bg_color_secondary_muted, theme->base.color_secondary); + lv_style_set_text_color(&theme->styles.bg_color_secondary_muted, theme->base.color_secondary); + lv_style_set_bg_opa(&theme->styles.bg_color_secondary_muted, LV_OPA_20); + + style_init_reset(&theme->styles.bg_color_grey); + lv_style_set_bg_color(&theme->styles.bg_color_grey, theme->color_grey); + lv_style_set_bg_opa(&theme->styles.bg_color_grey, LV_OPA_COVER); + lv_style_set_text_color(&theme->styles.bg_color_grey, theme->color_text); + + style_init_reset(&theme->styles.bg_color_white); + lv_style_set_bg_color(&theme->styles.bg_color_white, theme->color_card); + lv_style_set_bg_opa(&theme->styles.bg_color_white, LV_OPA_COVER); + lv_style_set_text_color(&theme->styles.bg_color_white, theme->color_text); + + style_init_reset(&theme->styles.circle); + lv_style_set_radius(&theme->styles.circle, LV_RADIUS_CIRCLE); + + style_init_reset(&theme->styles.no_radius); + lv_style_set_radius(&theme->styles.no_radius, 0); + +#if LV_THEME_DEFAULT_GROW + style_init_reset(&theme->styles.grow); + lv_style_set_transform_width(&theme->styles.grow, _LV_DPX_CALC(theme->disp_dpi, 3)); + lv_style_set_transform_height(&theme->styles.grow, _LV_DPX_CALC(theme->disp_dpi, 3)); +#endif + + style_init_reset(&theme->styles.knob); + lv_style_set_bg_color(&theme->styles.knob, theme->base.color_primary); + lv_style_set_bg_opa(&theme->styles.knob, LV_OPA_COVER); + lv_style_set_pad_all(&theme->styles.knob, _LV_DPX_CALC(theme->disp_dpi, 6)); + lv_style_set_radius(&theme->styles.knob, LV_RADIUS_CIRCLE); + + style_init_reset(&theme->styles.anim); + lv_style_set_anim_duration(&theme->styles.anim, 200); + + style_init_reset(&theme->styles.anim_fast); + lv_style_set_anim_duration(&theme->styles.anim_fast, 120); + +#if LV_USE_ARC + style_init_reset(&theme->styles.arc_indic); + lv_style_set_arc_color(&theme->styles.arc_indic, theme->color_grey); + lv_style_set_arc_width(&theme->styles.arc_indic, _LV_DPX_CALC(theme->disp_dpi, 15)); + lv_style_set_arc_rounded(&theme->styles.arc_indic, true); + + style_init_reset(&theme->styles.arc_indic_primary); + lv_style_set_arc_color(&theme->styles.arc_indic_primary, theme->base.color_primary); +#endif + +#if LV_USE_DROPDOWN + style_init_reset(&theme->styles.dropdown_list); + lv_style_set_max_height(&theme->styles.dropdown_list, LV_DPI_DEF * 2); +#endif +#if LV_USE_CHECKBOX + style_init_reset(&theme->styles.cb_marker); + lv_style_set_pad_all(&theme->styles.cb_marker, _LV_DPX_CALC(theme->disp_dpi, 3)); + lv_style_set_border_width(&theme->styles.cb_marker, BORDER_WIDTH); + lv_style_set_border_color(&theme->styles.cb_marker, theme->base.color_primary); + lv_style_set_bg_color(&theme->styles.cb_marker, theme->color_card); + lv_style_set_bg_opa(&theme->styles.cb_marker, LV_OPA_COVER); + lv_style_set_radius(&theme->styles.cb_marker, RADIUS_DEFAULT / 2); + + style_init_reset(&theme->styles.cb_marker_checked); + lv_style_set_bg_image_src(&theme->styles.cb_marker_checked, LV_SYMBOL_OK); + lv_style_set_text_color(&theme->styles.cb_marker_checked, lv_color_white()); + lv_style_set_text_font(&theme->styles.cb_marker_checked, theme->base.font_small); +#endif + +#if LV_USE_SWITCH + style_init_reset(&theme->styles.switch_knob); + lv_style_set_pad_all(&theme->styles.switch_knob, - _LV_DPX_CALC(theme->disp_dpi, 4)); + lv_style_set_bg_color(&theme->styles.switch_knob, lv_color_white()); +#endif + +#if LV_USE_LINE + style_init_reset(&theme->styles.line); + lv_style_set_line_width(&theme->styles.line, 1); + lv_style_set_line_color(&theme->styles.line, theme->color_text); +#endif + +#if LV_USE_CHART + style_init_reset(&theme->styles.chart_bg); + lv_style_set_border_post(&theme->styles.chart_bg, false); + lv_style_set_pad_column(&theme->styles.chart_bg, _LV_DPX_CALC(theme->disp_dpi, 10)); + lv_style_set_line_color(&theme->styles.chart_bg, theme->color_grey); + + style_init_reset(&theme->styles.chart_series); + lv_style_set_line_width(&theme->styles.chart_series, _LV_DPX_CALC(theme->disp_dpi, 3)); + lv_style_set_radius(&theme->styles.chart_series, _LV_DPX_CALC(theme->disp_dpi, 3)); + + int32_t chart_size = _LV_DPX_CALC(theme->disp_dpi, 8); + lv_style_set_size(&theme->styles.chart_series, chart_size, chart_size); + lv_style_set_pad_column(&theme->styles.chart_series, _LV_DPX_CALC(theme->disp_dpi, 2)); + + style_init_reset(&theme->styles.chart_indic); + lv_style_set_radius(&theme->styles.chart_indic, LV_RADIUS_CIRCLE); + lv_style_set_size(&theme->styles.chart_indic, chart_size, chart_size); + lv_style_set_bg_color(&theme->styles.chart_indic, theme->base.color_primary); + lv_style_set_bg_opa(&theme->styles.chart_indic, LV_OPA_COVER); +#endif + +#if LV_USE_MENU + style_init_reset(&theme->styles.menu_bg); + lv_style_set_pad_all(&theme->styles.menu_bg, 0); + lv_style_set_pad_gap(&theme->styles.menu_bg, 0); + lv_style_set_radius(&theme->styles.menu_bg, 0); + lv_style_set_clip_corner(&theme->styles.menu_bg, true); + lv_style_set_border_side(&theme->styles.menu_bg, LV_BORDER_SIDE_NONE); + + style_init_reset(&theme->styles.menu_section); + lv_style_set_radius(&theme->styles.menu_section, RADIUS_DEFAULT); + lv_style_set_clip_corner(&theme->styles.menu_section, true); + lv_style_set_bg_opa(&theme->styles.menu_section, LV_OPA_COVER); + lv_style_set_bg_color(&theme->styles.menu_section, theme->color_card); + lv_style_set_text_color(&theme->styles.menu_section, theme->color_text); + + style_init_reset(&theme->styles.menu_cont); + lv_style_set_pad_hor(&theme->styles.menu_cont, PAD_SMALL); + lv_style_set_pad_ver(&theme->styles.menu_cont, PAD_SMALL); + lv_style_set_pad_gap(&theme->styles.menu_cont, PAD_SMALL); + lv_style_set_border_width(&theme->styles.menu_cont, _LV_DPX_CALC(theme->disp_dpi, 1)); + lv_style_set_border_opa(&theme->styles.menu_cont, LV_OPA_10); + lv_style_set_border_color(&theme->styles.menu_cont, theme->color_text); + lv_style_set_border_side(&theme->styles.menu_cont, LV_BORDER_SIDE_NONE); + + style_init_reset(&theme->styles.menu_sidebar_cont); + lv_style_set_pad_all(&theme->styles.menu_sidebar_cont, 0); + lv_style_set_pad_gap(&theme->styles.menu_sidebar_cont, 0); + lv_style_set_border_width(&theme->styles.menu_sidebar_cont, _LV_DPX_CALC(theme->disp_dpi, 1)); + lv_style_set_border_opa(&theme->styles.menu_sidebar_cont, LV_OPA_10); + lv_style_set_border_color(&theme->styles.menu_sidebar_cont, theme->color_text); + lv_style_set_border_side(&theme->styles.menu_sidebar_cont, LV_BORDER_SIDE_RIGHT); + + style_init_reset(&theme->styles.menu_main_cont); + lv_style_set_pad_all(&theme->styles.menu_main_cont, 0); + lv_style_set_pad_gap(&theme->styles.menu_main_cont, 0); + + style_init_reset(&theme->styles.menu_header_cont); + lv_style_set_pad_hor(&theme->styles.menu_header_cont, PAD_SMALL); + lv_style_set_pad_ver(&theme->styles.menu_header_cont, PAD_TINY); + lv_style_set_pad_gap(&theme->styles.menu_header_cont, PAD_SMALL); + + style_init_reset(&theme->styles.menu_header_btn); + lv_style_set_pad_hor(&theme->styles.menu_header_btn, PAD_TINY); + lv_style_set_pad_ver(&theme->styles.menu_header_btn, PAD_TINY); + lv_style_set_shadow_opa(&theme->styles.menu_header_btn, LV_OPA_TRANSP); + lv_style_set_bg_opa(&theme->styles.menu_header_btn, LV_OPA_TRANSP); + lv_style_set_text_color(&theme->styles.menu_header_btn, theme->color_text); + + style_init_reset(&theme->styles.menu_page); + lv_style_set_pad_hor(&theme->styles.menu_page, 0); + lv_style_set_pad_gap(&theme->styles.menu_page, 0); + + style_init_reset(&theme->styles.menu_pressed); + lv_style_set_bg_opa(&theme->styles.menu_pressed, LV_OPA_20); + lv_style_set_bg_color(&theme->styles.menu_pressed, lv_palette_main(LV_PALETTE_GREY)); + + style_init_reset(&theme->styles.menu_separator); + lv_style_set_bg_opa(&theme->styles.menu_separator, LV_OPA_TRANSP); + lv_style_set_pad_ver(&theme->styles.menu_separator, PAD_TINY); +#endif + +#if LV_USE_TABLE + style_init_reset(&theme->styles.table_cell); + lv_style_set_border_width(&theme->styles.table_cell, _LV_DPX_CALC(theme->disp_dpi, 1)); + lv_style_set_border_color(&theme->styles.table_cell, theme->color_grey); + lv_style_set_border_side(&theme->styles.table_cell, LV_BORDER_SIDE_TOP | LV_BORDER_SIDE_BOTTOM); +#endif + +#if LV_USE_TEXTAREA + style_init_reset(&theme->styles.ta_cursor); + lv_style_set_border_color(&theme->styles.ta_cursor, theme->color_text); + lv_style_set_border_width(&theme->styles.ta_cursor, _LV_DPX_CALC(theme->disp_dpi, 2)); + lv_style_set_pad_left(&theme->styles.ta_cursor, - _LV_DPX_CALC(theme->disp_dpi, 1)); + lv_style_set_border_side(&theme->styles.ta_cursor, LV_BORDER_SIDE_LEFT); + lv_style_set_anim_duration(&theme->styles.ta_cursor, 400); + + style_init_reset(&theme->styles.ta_placeholder); + lv_style_set_text_color(&theme->styles.ta_placeholder, + (theme->base.flags & MODE_DARK) ? lv_palette_darken(LV_PALETTE_GREY, + 2) : lv_palette_lighten(LV_PALETTE_GREY, 1)); +#endif + +#if LV_USE_CALENDAR + style_init_reset(&theme->styles.calendar_btnm_bg); + lv_style_set_pad_all(&theme->styles.calendar_btnm_bg, PAD_SMALL); + lv_style_set_pad_gap(&theme->styles.calendar_btnm_bg, PAD_SMALL / 2); + + style_init_reset(&theme->styles.calendar_btnm_day); + lv_style_set_border_width(&theme->styles.calendar_btnm_day, _LV_DPX_CALC(theme->disp_dpi, 1)); + lv_style_set_border_color(&theme->styles.calendar_btnm_day, theme->color_grey); + lv_style_set_bg_color(&theme->styles.calendar_btnm_day, theme->color_card); + lv_style_set_bg_opa(&theme->styles.calendar_btnm_day, LV_OPA_20); + + style_init_reset(&theme->styles.calendar_header); + lv_style_set_pad_hor(&theme->styles.calendar_header, PAD_SMALL); + lv_style_set_pad_top(&theme->styles.calendar_header, PAD_SMALL); + lv_style_set_pad_bottom(&theme->styles.calendar_header, PAD_TINY); + lv_style_set_pad_gap(&theme->styles.calendar_header, PAD_SMALL); +#endif + +#if LV_USE_MSGBOX + style_init_reset(&theme->styles.msgbox_backdrop_bg); + lv_style_set_bg_color(&theme->styles.msgbox_backdrop_bg, lv_palette_main(LV_PALETTE_GREY)); + lv_style_set_bg_opa(&theme->styles.msgbox_backdrop_bg, LV_OPA_50); +#endif +#if LV_USE_KEYBOARD + style_init_reset(&theme->styles.keyboard_button_bg); + lv_style_set_shadow_width(&theme->styles.keyboard_button_bg, 0); + lv_style_set_radius(&theme->styles.keyboard_button_bg, + theme->disp_size == DISP_SMALL ? RADIUS_DEFAULT / 2 : RADIUS_DEFAULT); +#endif + +#if LV_USE_TABVIEW + style_init_reset(&theme->styles.tab_btn); + lv_style_set_border_color(&theme->styles.tab_btn, theme->base.color_primary); + lv_style_set_border_width(&theme->styles.tab_btn, BORDER_WIDTH * 2); + lv_style_set_border_side(&theme->styles.tab_btn, LV_BORDER_SIDE_BOTTOM); + lv_style_set_pad_top(&theme->styles.tab_btn, BORDER_WIDTH * 2); + + style_init_reset(&theme->styles.tab_bg_focus); + lv_style_set_outline_pad(&theme->styles.tab_bg_focus, -BORDER_WIDTH); +#endif + +#if LV_USE_LIST + style_init_reset(&theme->styles.list_bg); + lv_style_set_pad_hor(&theme->styles.list_bg, PAD_DEF); + lv_style_set_pad_ver(&theme->styles.list_bg, 0); + lv_style_set_pad_gap(&theme->styles.list_bg, 0); + lv_style_set_clip_corner(&theme->styles.list_bg, true); + + style_init_reset(&theme->styles.list_btn); + lv_style_set_border_width(&theme->styles.list_btn, _LV_DPX_CALC(theme->disp_dpi, 1)); + lv_style_set_border_color(&theme->styles.list_btn, theme->color_grey); + lv_style_set_border_side(&theme->styles.list_btn, LV_BORDER_SIDE_BOTTOM); + lv_style_set_pad_all(&theme->styles.list_btn, PAD_SMALL); + lv_style_set_pad_column(&theme->styles.list_btn, PAD_SMALL); + + style_init_reset(&theme->styles.list_item_grow); + lv_style_set_transform_width(&theme->styles.list_item_grow, PAD_DEF); +#endif + +#if LV_USE_LED + style_init_reset(&theme->styles.led); + lv_style_set_bg_opa(&theme->styles.led, LV_OPA_COVER); + lv_style_set_bg_color(&theme->styles.led, lv_color_white()); + lv_style_set_bg_grad_color(&theme->styles.led, lv_palette_main(LV_PALETTE_GREY)); + lv_style_set_radius(&theme->styles.led, LV_RADIUS_CIRCLE); + lv_style_set_shadow_width(&theme->styles.led, _LV_DPX_CALC(theme->disp_dpi, 15)); + lv_style_set_shadow_color(&theme->styles.led, lv_color_white()); + lv_style_set_shadow_spread(&theme->styles.led, _LV_DPX_CALC(theme->disp_dpi, 5)); +#endif + +#if LV_USE_SCALE + style_init_reset(&theme->styles.scale); + lv_style_set_line_color(&theme->styles.scale, theme->color_text); + lv_style_set_line_width(&theme->styles.scale, LV_DPX(2)); + lv_style_set_arc_color(&theme->styles.scale, theme->color_text); + lv_style_set_arc_width(&theme->styles.scale, LV_DPX(2)); +#endif +} + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_theme_t * lv_theme_default_init(lv_display_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, + const lv_font_t * font) +{ + /*This trick is required only to avoid the garbage collection of + *styles' data if LVGL is used in a binding (e.g. Micropython) + *In a general case styles could be in a simple `static lv_style_t my_style...` variables*/ + + if(!lv_theme_default_is_inited()) { + theme_def = lv_malloc_zeroed(sizeof(my_theme_t)); + } + + my_theme_t * theme = theme_def; + + lv_display_t * new_disp = disp == NULL ? lv_display_get_default() : disp; + int32_t new_dpi = lv_display_get_dpi(new_disp); + int32_t hor_res = lv_display_get_horizontal_resolution(new_disp); + disp_size_t new_size; + + if(hor_res <= 320) new_size = DISP_SMALL; + else if(hor_res < 720) new_size = DISP_MEDIUM; + else new_size = DISP_LARGE; + + /* check theme information whether will change or not*/ + if(theme->inited && theme->disp_dpi == new_dpi && + theme->disp_size == new_size && + lv_color_eq(theme->base.color_primary, color_primary) && + lv_color_eq(theme->base.color_secondary, color_secondary) && + (theme->base.flags == dark ? MODE_DARK : 0) && + theme->base.font_small == font) { + return (lv_theme_t *) theme; + + } + + theme->disp_size = new_size; + theme->disp_dpi = new_dpi; + theme->base.disp = new_disp; + theme->base.color_primary = color_primary; + theme->base.color_secondary = color_secondary; + theme->base.font_small = font; + theme->base.font_normal = font; + theme->base.font_large = font; + theme->base.apply_cb = theme_apply; + theme->base.flags = dark ? MODE_DARK : 0; + + style_init(theme); + + if(disp == NULL || lv_display_get_theme(disp) == (lv_theme_t *)theme) lv_obj_report_style_change(NULL); + + theme->inited = true; + + return (lv_theme_t *) theme; +} + +void lv_theme_default_deinit(void) +{ + my_theme_t * theme = theme_def; + if(theme) { + if(theme->inited) { + lv_style_t * theme_styles = (lv_style_t *)(&(theme->styles)); + uint32_t i; + for(i = 0; i < sizeof(my_theme_styles_t) / sizeof(lv_style_t); i++) { + lv_style_reset(theme_styles + i); + } + + } + lv_free(theme_def); + theme_def = NULL; + } +} + +lv_theme_t * lv_theme_default_get(void) +{ + if(!lv_theme_default_is_inited()) { + return NULL; + } + + return (lv_theme_t *)theme_def; +} + +bool lv_theme_default_is_inited(void) +{ + my_theme_t * theme = theme_def; + if(theme == NULL) return false; + return theme->inited; +} + +static void theme_apply(lv_theme_t * th, lv_obj_t * obj) +{ + LV_UNUSED(th); + + my_theme_t * theme = theme_def; + + if(lv_obj_get_parent(obj) == NULL) { + lv_obj_add_style(obj, &theme->styles.scr, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + return; + } + + if(lv_obj_check_type(obj, &lv_obj_class)) { +#if LV_USE_TABVIEW + lv_obj_t * parent = lv_obj_get_parent(obj); + /*Tabview content area*/ + if(parent && lv_obj_check_type(parent, &lv_tabview_class) && lv_obj_get_index(obj) == 1) { + return; + } + /*Tabview button container*/ + else if(lv_obj_check_type(parent, &lv_tabview_class) && lv_obj_get_index(obj) == 0) { + lv_obj_add_style(obj, &theme->styles.bg_color_white, 0); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.tab_bg_focus, LV_STATE_FOCUS_KEY); + return; + } + /*Tabview pages*/ + else if(parent && lv_obj_check_type(lv_obj_get_parent(parent), &lv_tabview_class)) { + lv_obj_add_style(obj, &theme->styles.pad_normal, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + return; + } +#endif + +#if LV_USE_WIN + /*Header*/ + if(lv_obj_get_index(obj) == 0 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { + lv_obj_add_style(obj, &theme->styles.bg_color_grey, 0); + lv_obj_add_style(obj, &theme->styles.pad_tiny, 0); + return; + } + /*Content*/ + else if(lv_obj_get_index(obj) == 1 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { + lv_obj_add_style(obj, &theme->styles.scr, 0); + lv_obj_add_style(obj, &theme->styles.pad_normal, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + return; + } +#endif + +#if LV_USE_CALENDAR + if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_calendar_class)) { + /*No style*/ + return; + } +#endif + + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + } +#if LV_USE_BUTTON + else if(lv_obj_check_type(obj, &lv_button_class)) { + +#if LV_USE_TABVIEW + lv_obj_t * parent = lv_obj_get_parent(obj); + if(parent && lv_obj_get_index(parent) == 0) { /*Tabview header*/ + if(lv_obj_check_type(lv_obj_get_parent(parent), &lv_tabview_class)) { + lv_obj_add_style(obj, &theme->styles.pressed, LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.bg_color_primary_muted, LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.tab_btn, LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.outline_secondary, LV_STATE_EDITED); + lv_obj_add_style(obj, &theme->styles.tab_bg_focus, LV_STATE_FOCUS_KEY); + return; + } + } + +#endif + lv_obj_add_style(obj, &theme->styles.btn, 0); + lv_obj_add_style(obj, &theme->styles.bg_color_primary, 0); + lv_obj_add_style(obj, &theme->styles.transition_delayed, 0); + lv_obj_add_style(obj, &theme->styles.pressed, LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.transition_normal, LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); +#if LV_THEME_DEFAULT_GROW + lv_obj_add_style(obj, &theme->styles.grow, LV_STATE_PRESSED); +#endif + lv_obj_add_style(obj, &theme->styles.bg_color_secondary, LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.disabled, LV_STATE_DISABLED); + +#if LV_USE_MENU + if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_menu_sidebar_header_cont_class) || + lv_obj_check_type(lv_obj_get_parent(obj), &lv_menu_main_header_cont_class)) { + lv_obj_add_style(obj, &theme->styles.menu_header_btn, 0); + lv_obj_add_style(obj, &theme->styles.menu_pressed, LV_STATE_PRESSED); + } +#endif + } +#endif + +#if LV_USE_LINE + else if(lv_obj_check_type(obj, &lv_line_class)) { + lv_obj_add_style(obj, &theme->styles.line, 0); + } +#endif + +#if LV_USE_BUTTONMATRIX + else if(lv_obj_check_type(obj, &lv_buttonmatrix_class)) { + +#if LV_USE_CALENDAR + if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_calendar_class)) { + lv_obj_add_style(obj, &theme->styles.calendar_btnm_bg, 0); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.outline_secondary, LV_STATE_EDITED); + lv_obj_add_style(obj, &theme->styles.calendar_btnm_day, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.pressed, LV_PART_ITEMS | LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.disabled, LV_PART_ITEMS | LV_STATE_DISABLED); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.outline_secondary, LV_PART_ITEMS | LV_STATE_EDITED); + return; + } +#endif + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.outline_secondary, LV_STATE_EDITED); + lv_obj_add_style(obj, &theme->styles.btn, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.disabled, LV_PART_ITEMS | LV_STATE_DISABLED); + lv_obj_add_style(obj, &theme->styles.pressed, LV_PART_ITEMS | LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.bg_color_primary, LV_PART_ITEMS | LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.outline_secondary, LV_PART_ITEMS | LV_STATE_EDITED); + } +#endif + +#if LV_USE_BAR + else if(lv_obj_check_type(obj, &lv_bar_class)) { + lv_obj_add_style(obj, &theme->styles.bg_color_primary_muted, 0); + lv_obj_add_style(obj, &theme->styles.circle, 0); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.outline_secondary, LV_STATE_EDITED); + lv_obj_add_style(obj, &theme->styles.bg_color_primary, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.circle, LV_PART_INDICATOR); + } +#endif + +#if LV_USE_SLIDER + else if(lv_obj_check_type(obj, &lv_slider_class)) { + lv_obj_add_style(obj, &theme->styles.bg_color_primary_muted, 0); + lv_obj_add_style(obj, &theme->styles.circle, 0); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.outline_secondary, LV_STATE_EDITED); + lv_obj_add_style(obj, &theme->styles.bg_color_primary, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.circle, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.knob, LV_PART_KNOB); +#if LV_THEME_DEFAULT_GROW + lv_obj_add_style(obj, &theme->styles.grow, LV_PART_KNOB | LV_STATE_PRESSED); +#endif + lv_obj_add_style(obj, &theme->styles.transition_delayed, LV_PART_KNOB); + lv_obj_add_style(obj, &theme->styles.transition_normal, LV_PART_KNOB | LV_STATE_PRESSED); + } +#endif + +#if LV_USE_TABLE + else if(lv_obj_check_type(obj, &lv_table_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.pad_zero, 0); + lv_obj_add_style(obj, &theme->styles.no_radius, 0); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.outline_secondary, LV_STATE_EDITED); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + lv_obj_add_style(obj, &theme->styles.bg_color_white, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.table_cell, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.pad_normal, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.pressed, LV_PART_ITEMS | LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.bg_color_primary, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.bg_color_secondary, LV_PART_ITEMS | LV_STATE_EDITED); + } +#endif + +#if LV_USE_CHECKBOX + else if(lv_obj_check_type(obj, &lv_checkbox_class)) { + lv_obj_add_style(obj, &theme->styles.pad_gap, 0); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.disabled, LV_PART_INDICATOR | LV_STATE_DISABLED); + lv_obj_add_style(obj, &theme->styles.cb_marker, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.bg_color_primary, LV_PART_INDICATOR | LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.cb_marker_checked, LV_PART_INDICATOR | LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.pressed, LV_PART_INDICATOR | LV_STATE_PRESSED); +#if LV_THEME_DEFAULT_GROW + lv_obj_add_style(obj, &theme->styles.grow, LV_PART_INDICATOR | LV_STATE_PRESSED); +#endif + lv_obj_add_style(obj, &theme->styles.transition_normal, LV_PART_INDICATOR | LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.transition_delayed, LV_PART_INDICATOR); + } +#endif + +#if LV_USE_SWITCH + else if(lv_obj_check_type(obj, &lv_switch_class)) { + lv_obj_add_style(obj, &theme->styles.bg_color_grey, 0); + lv_obj_add_style(obj, &theme->styles.circle, 0); + lv_obj_add_style(obj, &theme->styles.anim_fast, 0); + lv_obj_add_style(obj, &theme->styles.disabled, LV_STATE_DISABLED); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.bg_color_primary, LV_PART_INDICATOR | LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.circle, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.disabled, LV_PART_INDICATOR | LV_STATE_DISABLED); + lv_obj_add_style(obj, &theme->styles.knob, LV_PART_KNOB); + lv_obj_add_style(obj, &theme->styles.bg_color_white, LV_PART_KNOB); + lv_obj_add_style(obj, &theme->styles.switch_knob, LV_PART_KNOB); + lv_obj_add_style(obj, &theme->styles.disabled, LV_PART_KNOB | LV_STATE_DISABLED); + + lv_obj_add_style(obj, &theme->styles.transition_normal, LV_PART_INDICATOR | LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.transition_normal, LV_PART_INDICATOR); + } +#endif + +#if LV_USE_CHART + else if(lv_obj_check_type(obj, &lv_chart_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.pad_small, 0); + lv_obj_add_style(obj, &theme->styles.chart_bg, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + lv_obj_add_style(obj, &theme->styles.chart_series, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.chart_indic, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.chart_series, LV_PART_CURSOR); + } +#endif + +#if LV_USE_ROLLER + else if(lv_obj_check_type(obj, &lv_roller_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.anim, 0); + lv_obj_add_style(obj, &theme->styles.line_space_large, 0); + lv_obj_add_style(obj, &theme->styles.text_align_center, 0); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.outline_secondary, LV_STATE_EDITED); + lv_obj_add_style(obj, &theme->styles.bg_color_primary, LV_PART_SELECTED); + } +#endif + +#if LV_USE_DROPDOWN + else if(lv_obj_check_type(obj, &lv_dropdown_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.pad_small, 0); + lv_obj_add_style(obj, &theme->styles.transition_delayed, 0); + lv_obj_add_style(obj, &theme->styles.transition_normal, LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.pressed, LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.outline_secondary, LV_STATE_EDITED); + lv_obj_add_style(obj, &theme->styles.transition_normal, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.disabled, LV_STATE_DISABLED); + } + else if(lv_obj_check_type(obj, &lv_dropdownlist_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.clip_corner, 0); + lv_obj_add_style(obj, &theme->styles.line_space_large, 0); + lv_obj_add_style(obj, &theme->styles.dropdown_list, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + lv_obj_add_style(obj, &theme->styles.bg_color_white, LV_PART_SELECTED); + lv_obj_add_style(obj, &theme->styles.bg_color_primary, LV_PART_SELECTED | LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.pressed, LV_PART_SELECTED | LV_STATE_PRESSED); + } +#endif + +#if LV_USE_ARC + else if(lv_obj_check_type(obj, &lv_arc_class)) { + lv_obj_add_style(obj, &theme->styles.arc_indic, 0); + lv_obj_add_style(obj, &theme->styles.arc_indic, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.arc_indic_primary, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.knob, LV_PART_KNOB); + } +#endif + +#if LV_USE_SPINNER + else if(lv_obj_check_type(obj, &lv_spinner_class)) { + lv_obj_add_style(obj, &theme->styles.arc_indic, 0); + lv_obj_add_style(obj, &theme->styles.arc_indic, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.arc_indic_primary, LV_PART_INDICATOR); + } +#endif + +#if LV_USE_TEXTAREA + else if(lv_obj_check_type(obj, &lv_textarea_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.pad_small, 0); + lv_obj_add_style(obj, &theme->styles.disabled, LV_STATE_DISABLED); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.outline_secondary, LV_STATE_EDITED); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + lv_obj_add_style(obj, &theme->styles.ta_cursor, LV_PART_CURSOR | LV_STATE_FOCUSED); + lv_obj_add_style(obj, &theme->styles.ta_placeholder, LV_PART_TEXTAREA_PLACEHOLDER); + } +#endif + +#if LV_USE_CALENDAR + else if(lv_obj_check_type(obj, &lv_calendar_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.pad_zero, 0); + } + +#if LV_USE_CALENDAR_HEADER_ARROW + else if(lv_obj_check_type(obj, &lv_calendar_header_arrow_class)) { + lv_obj_add_style(obj, &theme->styles.calendar_header, 0); + } +#endif + +#if LV_USE_CALENDAR_HEADER_DROPDOWN + else if(lv_obj_check_type(obj, &lv_calendar_header_dropdown_class)) { + lv_obj_add_style(obj, &theme->styles.calendar_header, 0); + } +#endif +#endif + +#if LV_USE_KEYBOARD + else if(lv_obj_check_type(obj, &lv_keyboard_class)) { + lv_obj_add_style(obj, &theme->styles.scr, 0); + lv_obj_add_style(obj, theme->disp_size == DISP_LARGE ? &theme->styles.pad_small : &theme->styles.pad_tiny, 0); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.outline_secondary, LV_STATE_EDITED); + lv_obj_add_style(obj, &theme->styles.btn, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.disabled, LV_PART_ITEMS | LV_STATE_DISABLED); + lv_obj_add_style(obj, &theme->styles.bg_color_white, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.keyboard_button_bg, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.pressed, LV_PART_ITEMS | LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.bg_color_grey, LV_PART_ITEMS | LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.bg_color_primary_muted, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.bg_color_secondary_muted, LV_PART_ITEMS | LV_STATE_EDITED); + } +#endif +#if LV_USE_LIST + else if(lv_obj_check_type(obj, &lv_list_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.list_bg, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + return; + } + else if(lv_obj_check_type(obj, &lv_list_text_class)) { + lv_obj_add_style(obj, &theme->styles.bg_color_grey, 0); + lv_obj_add_style(obj, &theme->styles.list_item_grow, 0); + } + else if(lv_obj_check_type(obj, &lv_list_button_class)) { + lv_obj_add_style(obj, &theme->styles.bg_color_white, 0); + lv_obj_add_style(obj, &theme->styles.list_btn, 0); + lv_obj_add_style(obj, &theme->styles.bg_color_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.list_item_grow, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.list_item_grow, LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.pressed, LV_STATE_PRESSED); + + } +#endif +#if LV_USE_MENU + else if(lv_obj_check_type(obj, &lv_menu_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.menu_bg, 0); + } + else if(lv_obj_check_type(obj, &lv_menu_sidebar_cont_class)) { + lv_obj_add_style(obj, &theme->styles.menu_sidebar_cont, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + } + else if(lv_obj_check_type(obj, &lv_menu_main_cont_class)) { + lv_obj_add_style(obj, &theme->styles.menu_main_cont, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + } + else if(lv_obj_check_type(obj, &lv_menu_cont_class)) { + lv_obj_add_style(obj, &theme->styles.menu_cont, 0); + lv_obj_add_style(obj, &theme->styles.menu_pressed, LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.bg_color_primary_muted, LV_STATE_PRESSED | LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.bg_color_primary_muted, LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.bg_color_primary, LV_STATE_FOCUS_KEY); + } + else if(lv_obj_check_type(obj, &lv_menu_sidebar_header_cont_class) || + lv_obj_check_type(obj, &lv_menu_main_header_cont_class)) { + lv_obj_add_style(obj, &theme->styles.menu_header_cont, 0); + } + else if(lv_obj_check_type(obj, &lv_menu_page_class)) { + lv_obj_add_style(obj, &theme->styles.menu_page, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + } + else if(lv_obj_check_type(obj, &lv_menu_section_class)) { + lv_obj_add_style(obj, &theme->styles.menu_section, 0); + } + else if(lv_obj_check_type(obj, &lv_menu_separator_class)) { + lv_obj_add_style(obj, &theme->styles.menu_separator, 0); + } +#endif +#if LV_USE_MSGBOX + else if(lv_obj_check_type(obj, &lv_msgbox_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.pad_zero, 0); + return; + } + else if(lv_obj_check_type(obj, &lv_msgbox_backdrop_class)) { + lv_obj_add_style(obj, &theme->styles.msgbox_backdrop_bg, 0); + return; + } + else if(lv_obj_check_type(obj, &lv_msgbox_header_class)) { + lv_obj_add_style(obj, &theme->styles.pad_tiny, 0); + lv_obj_add_style(obj, &theme->styles.bg_color_grey, 0); + return; + } + else if(lv_obj_check_type(obj, &lv_msgbox_footer_class)) { + lv_obj_add_style(obj, &theme->styles.pad_tiny, 0); + return; + } + else if(lv_obj_check_type(obj, &lv_msgbox_header_button_class) || + lv_obj_check_type(obj, &lv_msgbox_footer_button_class)) { + lv_obj_add_style(obj, &theme->styles.btn, 0); + lv_obj_add_style(obj, &theme->styles.bg_color_primary, 0); + lv_obj_add_style(obj, &theme->styles.transition_delayed, 0); + lv_obj_add_style(obj, &theme->styles.pressed, LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.transition_normal, LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.bg_color_secondary, LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.disabled, LV_STATE_DISABLED); + return; + } + + if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_msgbox_class)) { + lv_obj_add_style(obj, &theme->styles.pad_tiny, 0); + return; + } + +#endif + +#if LV_USE_SPINBOX + else if(lv_obj_check_type(obj, &lv_spinbox_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.pad_small, 0); + lv_obj_add_style(obj, &theme->styles.outline_primary, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.outline_secondary, LV_STATE_EDITED); + lv_obj_add_style(obj, &theme->styles.bg_color_primary, LV_PART_CURSOR); + } +#endif +#if LV_USE_TILEVIEW + else if(lv_obj_check_type(obj, &lv_tileview_class)) { + lv_obj_add_style(obj, &theme->styles.scr, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + } + else if(lv_obj_check_type(obj, &lv_tileview_tile_class)) { + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); + } +#endif + +#if LV_USE_TABVIEW + else if(lv_obj_check_type(obj, &lv_tabview_class)) { + lv_obj_add_style(obj, &theme->styles.scr, 0); + lv_obj_add_style(obj, &theme->styles.pad_zero, 0); + } +#endif + +#if LV_USE_WIN + else if(lv_obj_check_type(obj, &lv_win_class)) { + lv_obj_add_style(obj, &theme->styles.clip_corner, 0); + } +#endif + +#if LV_USE_LED + else if(lv_obj_check_type(obj, &lv_led_class)) { + lv_obj_add_style(obj, &theme->styles.led, 0); + } +#endif + +#if LV_USE_SCALE + else if(lv_obj_check_type(obj, &lv_scale_class)) { + lv_obj_add_style(obj, &theme->styles.scale, LV_PART_MAIN); + lv_obj_add_style(obj, &theme->styles.scale, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.scale, LV_PART_ITEMS); + } +#endif +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void style_init_reset(lv_style_t * style) +{ + if(theme_def->inited) { + lv_style_reset(style); + } + else { + lv_style_init(style); + } +} + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.h b/lib/libesp32_lvgl/lvgl/src/themes/default/lv_theme_default.h similarity index 81% rename from lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.h rename to lib/libesp32_lvgl/lvgl/src/themes/default/lv_theme_default.h index 5b1fd9186..72d9acbfa 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/themes/default/lv_theme_default.h +++ b/lib/libesp32_lvgl/lvgl/src/themes/default/lv_theme_default.h @@ -13,7 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../core/lv_obj.h" +#include "../lv_theme.h" #if LV_USE_THEME_DEFAULT @@ -31,12 +31,14 @@ extern "C" { /** * Initialize the theme + * @param disp pointer to display * @param color_primary the primary color of the theme * @param color_secondary the secondary color for the theme + * @param dark * @param font pointer to a font to use. * @return a pointer to reference this theme later */ -lv_theme_t * lv_theme_default_init(lv_disp_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, +lv_theme_t * lv_theme_default_init(lv_display_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font); /** @@ -51,6 +53,11 @@ lv_theme_t * lv_theme_default_get(void); */ bool lv_theme_default_is_inited(void); +/** + * Deinitialize the default theme + */ +void lv_theme_default_deinit(void); + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_theme.c b/lib/libesp32_lvgl/lvgl/src/themes/lv_theme.c similarity index 71% rename from lib/libesp32_lvgl/lvgl/src/core/lv_theme.c rename to lib/libesp32_lvgl/lvgl/src/themes/lv_theme.c index b46cdcc4c..352047539 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_theme.c +++ b/lib/libesp32_lvgl/lvgl/src/themes/lv_theme.c @@ -20,6 +20,7 @@ * STATIC PROTOTYPES **********************/ static void apply_theme(lv_theme_t * th, lv_obj_t * obj); +static void apply_theme_recursion(lv_theme_t * th, lv_obj_t * obj); /********************** * STATIC VARIABLES @@ -35,15 +36,10 @@ static void apply_theme(lv_theme_t * th, lv_obj_t * obj); lv_theme_t * lv_theme_get_from_obj(lv_obj_t * obj) { - lv_disp_t * disp = obj ? lv_obj_get_disp(obj) : lv_disp_get_default(); - return lv_disp_get_theme(disp); + lv_display_t * disp = obj ? lv_obj_get_display(obj) : lv_display_get_default(); + return lv_display_get_theme(disp); } -/** - * Apply the active theme on an object - * @param obj pointer to an object - * @param name the name of the theme element to apply. E.g. `LV_THEME_BTN` - */ void lv_theme_apply(lv_obj_t * obj) { lv_theme_t * th = lv_theme_get_from_obj(obj); @@ -51,27 +47,14 @@ void lv_theme_apply(lv_obj_t * obj) lv_obj_remove_style_all(obj); - apply_theme(th, obj); /*Apply the theme including the base theme(s)*/ + apply_theme_recursion(th, obj); /*Apply the theme including the base theme(s)*/ } -/** - * Set a base theme for a theme. - * The styles from the base them will be added before the styles of the current theme. - * Arbitrary long chain of themes can be created by setting base themes. - * @param new_theme pointer to theme which base should be set - * @param base pointer to the base theme - */ void lv_theme_set_parent(lv_theme_t * new_theme, lv_theme_t * base) { new_theme->parent = base; } -/** - * Set a callback for a theme. - * The callback is used to add styles to different objects - * @param theme pointer to theme which callback should be set - * @param cb pointer to the callback - */ void lv_theme_set_apply_cb(lv_theme_t * theme, lv_theme_apply_cb_t apply_cb) { theme->apply_cb = apply_cb; @@ -116,3 +99,21 @@ static void apply_theme(lv_theme_t * th, lv_obj_t * obj) if(th->parent) apply_theme(th->parent, obj); if(th->apply_cb) th->apply_cb(th, obj); } + +static void apply_theme_recursion(lv_theme_t * th, lv_obj_t * obj) +{ + const lv_obj_class_t * original_class_p = obj->class_p; + + if(obj->class_p->base_class && obj->class_p->theme_inheritable == LV_OBJ_CLASS_THEME_INHERITABLE_TRUE) { + /*Apply the base class theme in obj*/ + obj->class_p = obj->class_p->base_class; + + /*apply the base first*/ + apply_theme_recursion(th, obj); + } + + /*Restore the original class*/ + obj->class_p = original_class_p; + + apply_theme(th, obj); +} diff --git a/lib/libesp32_lvgl/lvgl/src/core/lv_theme.h b/lib/libesp32_lvgl/lvgl/src/themes/lv_theme.h similarity index 89% rename from lib/libesp32_lvgl/lvgl/src/core/lv_theme.h rename to lib/libesp32_lvgl/lvgl/src/themes/lv_theme.h index ef46336c8..fc19f4c45 100644 --- a/lib/libesp32_lvgl/lvgl/src/core/lv_theme.h +++ b/lib/libesp32_lvgl/lvgl/src/themes/lv_theme.h @@ -23,23 +23,20 @@ extern "C" { * TYPEDEFS **********************/ -struct _lv_theme_t; -struct _lv_disp_t; +typedef void (*lv_theme_apply_cb_t)(lv_theme_t *, lv_obj_t *); -typedef void (*lv_theme_apply_cb_t)(struct _lv_theme_t *, lv_obj_t *); - -typedef struct _lv_theme_t { +struct _lv_theme_t { lv_theme_apply_cb_t apply_cb; - struct _lv_theme_t * parent; /**< Apply the current theme's style on top of this theme.*/ + lv_theme_t * parent; /**< Apply the current theme's style on top of this theme.*/ void * user_data; - struct _lv_disp_t * disp; + lv_display_t * disp; lv_color_t color_primary; lv_color_t color_secondary; const lv_font_t * font_small; const lv_font_t * font_normal; const lv_font_t * font_large; uint32_t flags; /*Any custom flag used by the theme*/ -} lv_theme_t; +}; /********************** * GLOBAL PROTOTYPES @@ -113,6 +110,10 @@ lv_color_t lv_theme_get_color_secondary(lv_obj_t * obj); * MACROS **********************/ +#include "default/lv_theme_default.h" +#include "mono/lv_theme_mono.h" +#include "simple/lv_theme_simple.h" + #ifdef __cplusplus } /*extern "C"*/ #endif diff --git a/lib/libesp32_lvgl/lvgl/src/themes/mono/lv_theme_mono.c b/lib/libesp32_lvgl/lvgl/src/themes/mono/lv_theme_mono.c new file mode 100644 index 000000000..fdcf11dcb --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/themes/mono/lv_theme_mono.c @@ -0,0 +1,531 @@ +/** + * @file lv_theme_mono.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_THEME_MONO + +#include "lv_theme_mono.h" +#include "../../core/lv_global.h" + +/********************* + * DEFINES + *********************/ +struct _my_theme_t; +typedef struct _my_theme_t my_theme_t; + +#define theme_def (*(my_theme_t **)(&LV_GLOBAL_DEFAULT()->theme_mono)) + +#define COLOR_FG dark_bg ? lv_color_white() : lv_color_black() +#define COLOR_BG dark_bg ? lv_color_black() : lv_color_white() + +#define BORDER_W_NORMAL 1 +#define BORDER_W_PR 3 +#define BORDER_W_DIS 0 +#define BORDER_W_FOCUS 1 +#define BORDER_W_EDIT 2 +#define PAD_DEF 4 + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + lv_style_t scr; + lv_style_t card; + lv_style_t scrollbar; + lv_style_t pr; + lv_style_t inv; + lv_style_t disabled; + lv_style_t focus; + lv_style_t edit; + lv_style_t pad_gap; + lv_style_t pad_zero; + lv_style_t no_radius; + lv_style_t radius_circle; + lv_style_t large_border; + lv_style_t large_line_space; + lv_style_t underline; +#if LV_USE_TEXTAREA + lv_style_t ta_cursor; +#endif +#if LV_USE_CHART + lv_style_t chart_indic; +#endif +} my_theme_styles_t; + +struct _my_theme_t { + lv_theme_t base; + my_theme_styles_t styles; + bool inited; +}; + +/********************** + * STATIC PROTOTYPES + **********************/ +static void style_init_reset(lv_style_t * style); +static void theme_apply(lv_theme_t * th, lv_obj_t * obj); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void style_init(my_theme_t * theme, bool dark_bg, const lv_font_t * font) +{ + style_init_reset(&theme->styles.scrollbar); + lv_style_set_bg_opa(&theme->styles.scrollbar, LV_OPA_COVER); + lv_style_set_bg_color(&theme->styles.scrollbar, COLOR_FG); + lv_style_set_width(&theme->styles.scrollbar, PAD_DEF); + + style_init_reset(&theme->styles.scr); + lv_style_set_bg_opa(&theme->styles.scr, LV_OPA_COVER); + lv_style_set_bg_color(&theme->styles.scr, COLOR_BG); + lv_style_set_text_color(&theme->styles.scr, COLOR_FG); + lv_style_set_pad_row(&theme->styles.scr, PAD_DEF); + lv_style_set_pad_column(&theme->styles.scr, PAD_DEF); + lv_style_set_text_font(&theme->styles.scr, font); + + style_init_reset(&theme->styles.card); + lv_style_set_bg_opa(&theme->styles.card, LV_OPA_COVER); + lv_style_set_bg_color(&theme->styles.card, COLOR_BG); + lv_style_set_border_color(&theme->styles.card, COLOR_FG); + lv_style_set_radius(&theme->styles.card, 2); + lv_style_set_border_width(&theme->styles.card, BORDER_W_NORMAL); + lv_style_set_pad_all(&theme->styles.card, PAD_DEF); + lv_style_set_pad_gap(&theme->styles.card, PAD_DEF); + lv_style_set_text_color(&theme->styles.card, COLOR_FG); + lv_style_set_line_width(&theme->styles.card, 2); + lv_style_set_line_color(&theme->styles.card, COLOR_FG); + lv_style_set_arc_width(&theme->styles.card, 2); + lv_style_set_arc_color(&theme->styles.card, COLOR_FG); + lv_style_set_outline_color(&theme->styles.card, COLOR_FG); + lv_style_set_anim_duration(&theme->styles.card, 300); + + style_init_reset(&theme->styles.pr); + lv_style_set_border_width(&theme->styles.pr, BORDER_W_PR); + + style_init_reset(&theme->styles.inv); + lv_style_set_bg_opa(&theme->styles.inv, LV_OPA_COVER); + lv_style_set_bg_color(&theme->styles.inv, COLOR_FG); + lv_style_set_border_color(&theme->styles.inv, COLOR_BG); + lv_style_set_line_color(&theme->styles.inv, COLOR_BG); + lv_style_set_arc_color(&theme->styles.inv, COLOR_BG); + lv_style_set_text_color(&theme->styles.inv, COLOR_BG); + lv_style_set_outline_color(&theme->styles.inv, COLOR_BG); + + style_init_reset(&theme->styles.disabled); + lv_style_set_border_width(&theme->styles.disabled, BORDER_W_DIS); + + style_init_reset(&theme->styles.focus); + lv_style_set_outline_width(&theme->styles.focus, 1); + lv_style_set_outline_pad(&theme->styles.focus, BORDER_W_FOCUS); + + style_init_reset(&theme->styles.edit); + lv_style_set_outline_width(&theme->styles.edit, BORDER_W_EDIT); + + style_init_reset(&theme->styles.large_border); + lv_style_set_border_width(&theme->styles.large_border, BORDER_W_EDIT); + + style_init_reset(&theme->styles.pad_gap); + lv_style_set_pad_gap(&theme->styles.pad_gap, PAD_DEF); + + style_init_reset(&theme->styles.pad_zero); + lv_style_set_pad_all(&theme->styles.pad_zero, 0); + lv_style_set_pad_gap(&theme->styles.pad_zero, 0); + + style_init_reset(&theme->styles.no_radius); + lv_style_set_radius(&theme->styles.no_radius, 0); + + style_init_reset(&theme->styles.radius_circle); + lv_style_set_radius(&theme->styles.radius_circle, LV_RADIUS_CIRCLE); + + style_init_reset(&theme->styles.large_line_space); + lv_style_set_text_line_space(&theme->styles.large_line_space, 6); + + style_init_reset(&theme->styles.underline); + lv_style_set_text_decor(&theme->styles.underline, LV_TEXT_DECOR_UNDERLINE); + +#if LV_USE_TEXTAREA + style_init_reset(&theme->styles.ta_cursor); + lv_style_set_border_side(&theme->styles.ta_cursor, LV_BORDER_SIDE_LEFT); + lv_style_set_border_color(&theme->styles.ta_cursor, COLOR_FG); + lv_style_set_border_width(&theme->styles.ta_cursor, 2); + lv_style_set_bg_opa(&theme->styles.ta_cursor, LV_OPA_TRANSP); + lv_style_set_anim_duration(&theme->styles.ta_cursor, 500); +#endif + +#if LV_USE_CHART + style_init_reset(&theme->styles.chart_indic); + lv_style_set_radius(&theme->styles.chart_indic, LV_RADIUS_CIRCLE); + lv_style_set_size(&theme->styles.chart_indic, lv_display_dpx(theme->base.disp, 8), lv_display_dpx(theme->base.disp, 8)); + lv_style_set_bg_color(&theme->styles.chart_indic, COLOR_FG); + lv_style_set_bg_opa(&theme->styles.chart_indic, LV_OPA_COVER); +#endif +} + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +bool lv_theme_mono_is_inited(void) +{ + my_theme_t * theme = theme_def; + if(theme == NULL) return false; + return theme->inited; +} + +void lv_theme_mono_deinit(void) +{ + my_theme_t * theme = theme_def; + if(theme) { + if(theme->inited) { + lv_style_t * theme_styles = (lv_style_t *)(&(theme->styles)); + uint32_t i; + for(i = 0; i < sizeof(my_theme_styles_t) / sizeof(lv_style_t); i++) { + lv_style_reset(theme_styles + i); + } + } + lv_free(theme_def); + theme_def = NULL; + } +} + +lv_theme_t * lv_theme_mono_init(lv_display_t * disp, bool dark_bg, const lv_font_t * font) +{ + /*This trick is required only to avoid the garbage collection of + *styles' data if LVGL is used in a binding (e.g. Micropython) + *In a general case styles could be in simple `static lv_style_t my_style...` variables*/ + if(!lv_theme_mono_is_inited()) { + theme_def = lv_malloc_zeroed(sizeof(my_theme_t)); + } + + my_theme_t * theme = theme_def; + + theme->base.disp = disp; + theme->base.font_small = LV_FONT_DEFAULT; + theme->base.font_normal = LV_FONT_DEFAULT; + theme->base.font_large = LV_FONT_DEFAULT; + theme->base.apply_cb = theme_apply; + + style_init(theme, dark_bg, font); + + if(disp == NULL || lv_display_get_theme(disp) == (lv_theme_t *) theme) lv_obj_report_style_change(NULL); + + theme->inited = true; + + return (lv_theme_t *)theme_def; +} + +static void theme_apply(lv_theme_t * th, lv_obj_t * obj) +{ + LV_UNUSED(th); + + my_theme_t * theme = theme_def; + + if(lv_obj_get_parent(obj) == NULL) { + lv_obj_add_style(obj, &theme->styles.scr, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + return; + } + + if(lv_obj_check_type(obj, &lv_obj_class)) { +#if LV_USE_TABVIEW + lv_obj_t * parent = lv_obj_get_parent(obj); + /*Tabview content area*/ + if(lv_obj_check_type(parent, &lv_tabview_class)) { + return; + } + /*Tabview pages*/ + else if(lv_obj_check_type(lv_obj_get_parent(parent), &lv_tabview_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.no_radius, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + return; + } +#endif + +#if LV_USE_WIN + /*Header*/ + if(lv_obj_get_index(obj) == 0 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.no_radius, 0); + return; + } + /*Content*/ + else if(lv_obj_get_index(obj) == 1 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.no_radius, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + return; + } +#endif + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + } +#if LV_USE_BUTTON + else if(lv_obj_check_type(obj, &lv_button_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.pr, LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.inv, LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.disabled, LV_STATE_DISABLED); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.edit, LV_STATE_EDITED); + } +#endif + +#if LV_USE_BUTTONMATRIX + else if(lv_obj_check_type(obj, &lv_buttonmatrix_class)) { +#if LV_USE_MSGBOX + if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_msgbox_class)) { + lv_obj_add_style(obj, &theme->styles.pad_gap, 0); + lv_obj_add_style(obj, &theme->styles.card, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.pr, LV_PART_ITEMS | LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.disabled, LV_PART_ITEMS | LV_STATE_DISABLED); + lv_obj_add_style(obj, &theme->styles.underline, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.large_border, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); + return; + } +#endif +#if LV_USE_TABVIEW + if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_tabview_class)) { + lv_obj_add_style(obj, &theme->styles.pad_gap, 0); + lv_obj_add_style(obj, &theme->styles.card, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.pr, LV_PART_ITEMS | LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.inv, LV_PART_ITEMS | LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.disabled, LV_PART_ITEMS | LV_STATE_DISABLED); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.underline, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.large_border, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); + return; + } +#endif + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.card, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.pr, LV_PART_ITEMS | LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.inv, LV_PART_ITEMS | LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.disabled, LV_PART_ITEMS | LV_STATE_DISABLED); + lv_obj_add_style(obj, &theme->styles.underline, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.large_border, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); + } +#endif + +#if LV_USE_BAR + else if(lv_obj_check_type(obj, &lv_bar_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.pad_zero, 0); + lv_obj_add_style(obj, &theme->styles.inv, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + } +#endif + +#if LV_USE_SLIDER + else if(lv_obj_check_type(obj, &lv_slider_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.pad_zero, 0); + lv_obj_add_style(obj, &theme->styles.inv, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.card, LV_PART_KNOB); + lv_obj_add_style(obj, &theme->styles.radius_circle, LV_PART_KNOB); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.edit, LV_STATE_EDITED); + } +#endif + +#if LV_USE_TABLE + else if(lv_obj_check_type(obj, &lv_table_class)) { + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.card, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.no_radius, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.pr, LV_PART_ITEMS | LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.inv, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.edit, LV_STATE_EDITED); + } +#endif + +#if LV_USE_CHECKBOX + else if(lv_obj_check_type(obj, &lv_checkbox_class)) { + lv_obj_add_style(obj, &theme->styles.pad_gap, LV_PART_MAIN); + lv_obj_add_style(obj, &theme->styles.card, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.disabled, LV_PART_INDICATOR | LV_STATE_DISABLED); + lv_obj_add_style(obj, &theme->styles.inv, LV_PART_INDICATOR | LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.pr, LV_PART_INDICATOR | LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.edit, LV_STATE_EDITED); + } +#endif + +#if LV_USE_SWITCH + else if(lv_obj_check_type(obj, &lv_switch_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.radius_circle, 0); + lv_obj_add_style(obj, &theme->styles.pad_zero, 0); + lv_obj_add_style(obj, &theme->styles.inv, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.radius_circle, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.card, LV_PART_KNOB); + lv_obj_add_style(obj, &theme->styles.radius_circle, LV_PART_KNOB); + lv_obj_add_style(obj, &theme->styles.pad_zero, LV_PART_KNOB); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.edit, LV_STATE_EDITED); + } +#endif + +#if LV_USE_CHART + else if(lv_obj_check_type(obj, &lv_chart_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.chart_indic, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.card, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.card, LV_PART_CURSOR); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + } +#endif + +#if LV_USE_ROLLER + else if(lv_obj_check_type(obj, &lv_roller_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.large_line_space, 0); + lv_obj_add_style(obj, &theme->styles.inv, LV_PART_SELECTED); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.edit, LV_STATE_EDITED); + } +#endif + +#if LV_USE_DROPDOWN + else if(lv_obj_check_type(obj, &lv_dropdown_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.pr, LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.edit, LV_STATE_EDITED); + } + else if(lv_obj_check_type(obj, &lv_dropdownlist_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.large_line_space, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.inv, LV_PART_SELECTED | LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.pr, LV_PART_SELECTED | LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.edit, LV_STATE_EDITED); + } +#endif + +#if LV_USE_ARC + else if(lv_obj_check_type(obj, &lv_arc_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.inv, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.pad_zero, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.card, LV_PART_KNOB); + lv_obj_add_style(obj, &theme->styles.radius_circle, LV_PART_KNOB); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.edit, LV_STATE_EDITED); + } +#endif + +#if LV_USE_TEXTAREA + else if(lv_obj_check_type(obj, &lv_textarea_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.ta_cursor, LV_PART_CURSOR | LV_STATE_FOCUSED); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUSED); + lv_obj_add_style(obj, &theme->styles.edit, LV_STATE_EDITED); + } +#endif + +#if LV_USE_CALENDAR + else if(lv_obj_check_type(obj, &lv_calendar_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.no_radius, 0); + lv_obj_add_style(obj, &theme->styles.pr, LV_PART_ITEMS | LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.disabled, LV_PART_ITEMS | LV_STATE_DISABLED); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.edit, LV_STATE_EDITED); + lv_obj_add_style(obj, &theme->styles.large_border, LV_PART_ITEMS | LV_STATE_FOCUS_KEY); + } +#endif + +#if LV_USE_KEYBOARD + else if(lv_obj_check_type(obj, &lv_keyboard_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.card, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.pr, LV_PART_ITEMS | LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.inv, LV_PART_ITEMS | LV_STATE_CHECKED); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.edit, LV_STATE_EDITED); + lv_obj_add_style(obj, &theme->styles.large_border, LV_PART_ITEMS | LV_STATE_EDITED); + } +#endif +#if LV_USE_LIST + else if(lv_obj_check_type(obj, &lv_list_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + return; + } + else if(lv_obj_check_type(obj, &lv_list_text_class)) { + + } + else if(lv_obj_check_type(obj, &lv_list_button_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.pr, LV_STATE_PRESSED); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.large_border, LV_STATE_EDITED); + + } +#endif +#if LV_USE_MSGBOX + else if(lv_obj_check_type(obj, &lv_msgbox_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + return; + } +#endif +#if LV_USE_SPINBOX + else if(lv_obj_check_type(obj, &lv_spinbox_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + lv_obj_add_style(obj, &theme->styles.inv, LV_PART_CURSOR); + lv_obj_add_style(obj, &theme->styles.focus, LV_STATE_FOCUS_KEY); + lv_obj_add_style(obj, &theme->styles.edit, LV_STATE_EDITED); + } +#endif +#if LV_USE_TILEVIEW + else if(lv_obj_check_type(obj, &lv_tileview_class)) { + lv_obj_add_style(obj, &theme->styles.scr, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + } + else if(lv_obj_check_type(obj, &lv_tileview_tile_class)) { + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + } +#endif + +#if LV_USE_LED + else if(lv_obj_check_type(obj, &lv_led_class)) { + lv_obj_add_style(obj, &theme->styles.card, 0); + } +#endif +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void style_init_reset(lv_style_t * style) +{ + if(lv_theme_mono_is_inited()) { + lv_style_reset(style); + } + else { + lv_style_init(style); + } +} + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.h b/lib/libesp32_lvgl/lvgl/src/themes/mono/lv_theme_mono.h similarity index 77% rename from lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.h rename to lib/libesp32_lvgl/lvgl/src/themes/mono/lv_theme_mono.h index 10b8f186d..fafe27f24 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/themes/mono/lv_theme_mono.h +++ b/lib/libesp32_lvgl/lvgl/src/themes/mono/lv_theme_mono.h @@ -13,7 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../core/lv_obj.h" +#include "../lv_theme.h" #if LV_USE_THEME_MONO @@ -31,12 +31,12 @@ extern "C" { /** * Initialize the theme - * @param color_primary the primary color of the theme - * @param color_secondary the secondary color for the theme + * @param disp pointer to display + * @param dark_bg * @param font pointer to a font to use. * @return a pointer to reference this theme later */ -lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t * font); +lv_theme_t * lv_theme_mono_init(lv_display_t * disp, bool dark_bg, const lv_font_t * font); /** * Check if the theme is initialized @@ -44,6 +44,11 @@ lv_theme_t * lv_theme_mono_init(lv_disp_t * disp, bool dark_bg, const lv_font_t */ bool lv_theme_mono_is_inited(void); +/** + * Deinitialize the mono theme + */ +void lv_theme_mono_deinit(void); + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/themes/simple/lv_theme_simple.c b/lib/libesp32_lvgl/lvgl/src/themes/simple/lv_theme_simple.c new file mode 100644 index 000000000..6eb2b2c9c --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/themes/simple/lv_theme_simple.c @@ -0,0 +1,437 @@ +/** + * @file lv_theme_simple.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" /*To see all the widgets*/ + +#if LV_USE_THEME_SIMPLE + +#include "lv_theme_simple.h" +#include "../../core/lv_global.h" + +/********************* + * DEFINES + *********************/ + +struct _my_theme_t; +typedef struct _my_theme_t my_theme_t; + +#define theme_def (*(my_theme_t **)(&LV_GLOBAL_DEFAULT()->theme_simple)) + +#define COLOR_SCR lv_palette_lighten(LV_PALETTE_GREY, 4) +#define COLOR_WHITE lv_color_white() +#define COLOR_LIGHT lv_palette_lighten(LV_PALETTE_GREY, 2) +#define COLOR_DARK lv_palette_main(LV_PALETTE_GREY) +#define COLOR_DIM lv_palette_darken(LV_PALETTE_GREY, 2) +#define SCROLLBAR_WIDTH 2 + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + lv_style_t scr; + lv_style_t transp; + lv_style_t white; + lv_style_t light; + lv_style_t dark; + lv_style_t dim; + lv_style_t scrollbar; +#if LV_USE_ARC + lv_style_t arc_line; + lv_style_t arc_knob; +#endif +#if LV_USE_TEXTAREA + lv_style_t ta_cursor; +#endif +} my_theme_styles_t; + +struct _my_theme_t { + lv_theme_t base; + my_theme_styles_t styles; + bool inited; +}; + +/********************** + * STATIC PROTOTYPES + **********************/ +static void style_init_reset(lv_style_t * style); +static void theme_apply(lv_theme_t * th, lv_obj_t * obj); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void style_init(my_theme_t * theme) +{ + style_init_reset(&theme->styles.scrollbar); + lv_style_set_bg_opa(&theme->styles.scrollbar, LV_OPA_COVER); + lv_style_set_bg_color(&theme->styles.scrollbar, COLOR_DARK); + lv_style_set_width(&theme->styles.scrollbar, SCROLLBAR_WIDTH); + + style_init_reset(&theme->styles.scr); + lv_style_set_bg_opa(&theme->styles.scr, LV_OPA_COVER); + lv_style_set_bg_color(&theme->styles.scr, COLOR_SCR); + lv_style_set_text_color(&theme->styles.scr, COLOR_DIM); + + style_init_reset(&theme->styles.transp); + lv_style_set_bg_opa(&theme->styles.transp, LV_OPA_TRANSP); + + style_init_reset(&theme->styles.white); + lv_style_set_bg_opa(&theme->styles.white, LV_OPA_COVER); + lv_style_set_bg_color(&theme->styles.white, COLOR_WHITE); + lv_style_set_line_width(&theme->styles.white, 1); + lv_style_set_line_color(&theme->styles.white, COLOR_WHITE); + lv_style_set_arc_width(&theme->styles.white, 2); + lv_style_set_arc_color(&theme->styles.white, COLOR_WHITE); + + style_init_reset(&theme->styles.light); + lv_style_set_bg_opa(&theme->styles.light, LV_OPA_COVER); + lv_style_set_bg_color(&theme->styles.light, COLOR_LIGHT); + lv_style_set_line_width(&theme->styles.light, 1); + lv_style_set_line_color(&theme->styles.light, COLOR_LIGHT); + lv_style_set_arc_width(&theme->styles.light, 2); + lv_style_set_arc_color(&theme->styles.light, COLOR_LIGHT); + + style_init_reset(&theme->styles.dark); + lv_style_set_bg_opa(&theme->styles.dark, LV_OPA_COVER); + lv_style_set_bg_color(&theme->styles.dark, COLOR_DARK); + lv_style_set_line_width(&theme->styles.dark, 1); + lv_style_set_line_color(&theme->styles.dark, COLOR_DARK); + lv_style_set_arc_width(&theme->styles.dark, 2); + lv_style_set_arc_color(&theme->styles.dark, COLOR_DARK); + + style_init_reset(&theme->styles.dim); + lv_style_set_bg_opa(&theme->styles.dim, LV_OPA_COVER); + lv_style_set_bg_color(&theme->styles.dim, COLOR_DIM); + lv_style_set_line_width(&theme->styles.dim, 1); + lv_style_set_line_color(&theme->styles.dim, COLOR_DIM); + lv_style_set_arc_width(&theme->styles.dim, 2); + lv_style_set_arc_color(&theme->styles.dim, COLOR_DIM); + +#if LV_USE_ARC + style_init_reset(&theme->styles.arc_line); + lv_style_set_arc_width(&theme->styles.arc_line, 6); + style_init_reset(&theme->styles.arc_knob); + lv_style_set_pad_all(&theme->styles.arc_knob, 5); +#endif + +#if LV_USE_TEXTAREA + style_init_reset(&theme->styles.ta_cursor); + lv_style_set_border_side(&theme->styles.ta_cursor, LV_BORDER_SIDE_LEFT); + lv_style_set_border_color(&theme->styles.ta_cursor, COLOR_DIM); + lv_style_set_border_width(&theme->styles.ta_cursor, 2); + lv_style_set_bg_opa(&theme->styles.ta_cursor, LV_OPA_TRANSP); + lv_style_set_anim_duration(&theme->styles.ta_cursor, 500); +#endif +} + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +bool lv_theme_simple_is_inited(void) +{ + my_theme_t * theme = theme_def; + if(theme == NULL) return false; + return theme->inited; +} + +lv_theme_t * lv_theme_simple_get(void) +{ + if(!lv_theme_simple_is_inited()) { + return NULL; + } + + return (lv_theme_t *)theme_def; +} + +void lv_theme_simple_deinit(void) +{ + my_theme_t * theme = theme_def; + if(theme) { + if(theme->inited) { + lv_style_t * theme_styles = (lv_style_t *)(&(theme->styles)); + uint32_t i; + for(i = 0; i < sizeof(my_theme_styles_t) / sizeof(lv_style_t); i++) { + lv_style_reset(theme_styles + i); + } + } + lv_free(theme_def); + theme_def = NULL; + } +} + +lv_theme_t * lv_theme_simple_init(lv_display_t * disp) +{ + /*This trick is required only to avoid the garbage collection of + *styles' data if LVGL is used in a binding (e.g. Micropython) + *In a general case styles could be in simple `static lv_style_t my_style...` variables*/ + if(!lv_theme_simple_is_inited()) { + theme_def = lv_malloc_zeroed(sizeof(my_theme_t)); + } + + my_theme_t * theme = theme_def; + + theme->base.disp = disp; + theme->base.font_small = LV_FONT_DEFAULT; + theme->base.font_normal = LV_FONT_DEFAULT; + theme->base.font_large = LV_FONT_DEFAULT; + theme->base.apply_cb = theme_apply; + + style_init(theme); + + if(disp == NULL || lv_display_get_theme(disp) == (lv_theme_t *)theme) { + lv_obj_report_style_change(NULL); + } + + theme->inited = true; + + return (lv_theme_t *)theme_def; +} + +static void theme_apply(lv_theme_t * th, lv_obj_t * obj) +{ + LV_UNUSED(th); + + my_theme_t * theme = theme_def; + + if(lv_obj_get_parent(obj) == NULL) { + lv_obj_add_style(obj, &theme->styles.scr, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + return; + } + + if(lv_obj_check_type(obj, &lv_obj_class)) { +#if LV_USE_TABVIEW + lv_obj_t * parent = lv_obj_get_parent(obj); + /*Tabview content area*/ + if(lv_obj_check_type(parent, &lv_tabview_class)) { + lv_obj_add_style(obj, &theme->styles.scr, 0); + return; + } + /*Tabview pages*/ + else if(lv_obj_check_type(lv_obj_get_parent(parent), &lv_tabview_class)) { + lv_obj_add_style(obj, &theme->styles.scr, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + return; + } +#endif + +#if LV_USE_WIN + /*Header*/ + if(lv_obj_get_index(obj) == 0 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { + lv_obj_add_style(obj, &theme->styles.light, 0); + return; + } + /*Content*/ + else if(lv_obj_get_index(obj) == 1 && lv_obj_check_type(lv_obj_get_parent(obj), &lv_win_class)) { + lv_obj_add_style(obj, &theme->styles.light, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + return; + } +#endif + lv_obj_add_style(obj, &theme->styles.white, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + } +#if LV_USE_BUTTON + else if(lv_obj_check_type(obj, &lv_button_class)) { + lv_obj_add_style(obj, &theme->styles.dark, 0); + } +#endif + +#if LV_USE_BUTTONMATRIX + else if(lv_obj_check_type(obj, &lv_buttonmatrix_class)) { +#if LV_USE_MSGBOX + if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_msgbox_class)) { + lv_obj_add_style(obj, &theme->styles.light, LV_PART_ITEMS); + return; + } +#endif +#if LV_USE_TABVIEW + if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_tabview_class)) { + lv_obj_add_style(obj, &theme->styles.light, LV_PART_ITEMS); + return; + } +#endif + lv_obj_add_style(obj, &theme->styles.white, 0); + lv_obj_add_style(obj, &theme->styles.light, LV_PART_ITEMS); + } +#endif + +#if LV_USE_BAR + else if(lv_obj_check_type(obj, &lv_bar_class)) { + lv_obj_add_style(obj, &theme->styles.light, 0); + lv_obj_add_style(obj, &theme->styles.dark, LV_PART_INDICATOR); + } +#endif + +#if LV_USE_SLIDER + else if(lv_obj_check_type(obj, &lv_slider_class)) { + lv_obj_add_style(obj, &theme->styles.light, 0); + lv_obj_add_style(obj, &theme->styles.dark, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.dim, LV_PART_KNOB); + } +#endif + +#if LV_USE_TABLE + else if(lv_obj_check_type(obj, &lv_table_class)) { + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.light, LV_PART_ITEMS); + } +#endif + +#if LV_USE_CHECKBOX + else if(lv_obj_check_type(obj, &lv_checkbox_class)) { + lv_obj_add_style(obj, &theme->styles.light, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.dark, LV_PART_INDICATOR | LV_STATE_CHECKED); + } +#endif + +#if LV_USE_SWITCH + else if(lv_obj_check_type(obj, &lv_switch_class)) { + lv_obj_add_style(obj, &theme->styles.light, 0); + lv_obj_add_style(obj, &theme->styles.dim, LV_PART_KNOB); + } +#endif + +#if LV_USE_CHART + else if(lv_obj_check_type(obj, &lv_chart_class)) { + lv_obj_add_style(obj, &theme->styles.white, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.light, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.dark, LV_PART_CURSOR); + } +#endif + +#if LV_USE_ROLLER + else if(lv_obj_check_type(obj, &lv_roller_class)) { + lv_obj_add_style(obj, &theme->styles.light, 0); + lv_obj_add_style(obj, &theme->styles.dark, LV_PART_SELECTED); + } +#endif + +#if LV_USE_DROPDOWN + else if(lv_obj_check_type(obj, &lv_dropdown_class)) { + lv_obj_add_style(obj, &theme->styles.white, 0); + } + else if(lv_obj_check_type(obj, &lv_dropdownlist_class)) { + lv_obj_add_style(obj, &theme->styles.white, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.light, LV_PART_SELECTED); + lv_obj_add_style(obj, &theme->styles.dark, LV_PART_SELECTED | LV_STATE_CHECKED); + } +#endif + +#if LV_USE_ARC + else if(lv_obj_check_type(obj, &lv_arc_class)) { + lv_obj_add_style(obj, &theme->styles.light, 0); + lv_obj_add_style(obj, &theme->styles.transp, 0); + lv_obj_add_style(obj, &theme->styles.arc_line, 0); + lv_obj_add_style(obj, &theme->styles.dark, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.arc_line, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.dim, LV_PART_KNOB); + lv_obj_add_style(obj, &theme->styles.arc_knob, LV_PART_KNOB); + } +#endif + +#if LV_USE_SPINNER + else if(lv_obj_check_type(obj, &lv_spinner_class)) { + lv_obj_add_style(obj, &theme->styles.light, 0); + lv_obj_add_style(obj, &theme->styles.transp, 0); + lv_obj_add_style(obj, &theme->styles.arc_line, 0); + lv_obj_add_style(obj, &theme->styles.dark, LV_PART_INDICATOR); + lv_obj_add_style(obj, &theme->styles.arc_line, LV_PART_INDICATOR); + } +#endif + +#if LV_USE_TEXTAREA + else if(lv_obj_check_type(obj, &lv_textarea_class)) { + lv_obj_add_style(obj, &theme->styles.white, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + lv_obj_add_style(obj, &theme->styles.ta_cursor, LV_PART_CURSOR | LV_STATE_FOCUSED); + } +#endif + +#if LV_USE_CALENDAR + else if(lv_obj_check_type(obj, &lv_calendar_class)) { + lv_obj_add_style(obj, &theme->styles.light, 0); + } +#endif + +#if LV_USE_KEYBOARD + else if(lv_obj_check_type(obj, &lv_keyboard_class)) { + lv_obj_add_style(obj, &theme->styles.scr, 0); + lv_obj_add_style(obj, &theme->styles.white, LV_PART_ITEMS); + lv_obj_add_style(obj, &theme->styles.light, LV_PART_ITEMS | LV_STATE_CHECKED); + } +#endif +#if LV_USE_LIST + else if(lv_obj_check_type(obj, &lv_list_class)) { + lv_obj_add_style(obj, &theme->styles.light, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + return; + } + else if(lv_obj_check_type(obj, &lv_list_text_class)) { + + } + else if(lv_obj_check_type(obj, &lv_list_button_class)) { + lv_obj_add_style(obj, &theme->styles.dark, 0); + + } +#endif +#if LV_USE_MSGBOX + else if(lv_obj_check_type(obj, &lv_msgbox_class)) { + lv_obj_add_style(obj, &theme->styles.light, 0); + return; + } +#endif +#if LV_USE_SPINBOX + else if(lv_obj_check_type(obj, &lv_spinbox_class)) { + lv_obj_add_style(obj, &theme->styles.light, 0); + lv_obj_add_style(obj, &theme->styles.dark, LV_PART_CURSOR); + } +#endif +#if LV_USE_TILEVIEW + else if(lv_obj_check_type(obj, &lv_tileview_class)) { + lv_obj_add_style(obj, &theme->styles.scr, 0); + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + } + else if(lv_obj_check_type(obj, &lv_tileview_tile_class)) { + lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); + } +#endif + +#if LV_USE_LED + else if(lv_obj_check_type(obj, &lv_led_class)) { + lv_obj_add_style(obj, &theme->styles.light, 0); + } +#endif +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void style_init_reset(lv_style_t * style) +{ + if(lv_theme_simple_is_inited()) { + lv_style_reset(style); + } + else { + lv_style_init(style); + } +} + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.h b/lib/libesp32_lvgl/lvgl/src/themes/simple/lv_theme_simple.h similarity index 57% rename from lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.h rename to lib/libesp32_lvgl/lvgl/src/themes/simple/lv_theme_simple.h index 93a8fa841..671736655 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/themes/basic/lv_theme_basic.h +++ b/lib/libesp32_lvgl/lvgl/src/themes/simple/lv_theme_simple.h @@ -1,10 +1,10 @@ /** - * @file lv_theme_basic.h + * @file lv_theme_simple.h * */ -#ifndef LV_THEME_BASIC_H -#define LV_THEME_BASIC_H +#ifndef LV_THEME_SIMPLE_H +#define LV_THEME_SIMPLE_H #ifdef __cplusplus extern "C" { @@ -13,9 +13,10 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../core/lv_obj.h" +#include "../lv_theme.h" +#include "../../display/lv_display.h" -#if LV_USE_THEME_BASIC +#if LV_USE_THEME_SIMPLE /********************* * DEFINES @@ -34,13 +35,24 @@ extern "C" { * @param disp pointer to display to attach the theme * @return a pointer to reference this theme later */ -lv_theme_t * lv_theme_basic_init(lv_disp_t * disp); +lv_theme_t * lv_theme_simple_init(lv_display_t * disp); /** * Check if the theme is initialized * @return true if default theme is initialized, false otherwise */ -bool lv_theme_basic_is_inited(void); +bool lv_theme_simple_is_inited(void); + +/** + * Get simple theme + * @return a pointer to simple theme, or NULL if this is not initialized + */ +lv_theme_t * lv_theme_simple_get(void); + +/** + * Deinitialize the simple theme + */ +void lv_theme_simple_deinit(void); /********************** * MACROS @@ -52,4 +64,4 @@ bool lv_theme_basic_is_inited(void); } /*extern "C"*/ #endif -#endif /*LV_THEME_BASIC_H*/ +#endif /*LV_THEME_SIMPLE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_tick.c b/lib/libesp32_lvgl/lvgl/src/tick/lv_tick.c similarity index 54% rename from lib/libesp32_lvgl/lvgl/src/hal/lv_hal_tick.c rename to lib/libesp32_lvgl/lvgl/src/tick/lv_tick.c index 6c8434622..2e4626b78 100644 --- a/lib/libesp32_lvgl/lvgl/src/hal/lv_hal_tick.c +++ b/lib/libesp32_lvgl/lvgl/src/tick/lv_tick.c @@ -1,21 +1,19 @@ /** - * @file lv_hal_tick.c + * @file lv_tick.c * Provide access to the system tick with 1 millisecond resolution */ /********************* * INCLUDES *********************/ -#include "lv_hal_tick.h" +#include "lv_tick.h" #include - -#if LV_TICK_CUSTOM == 1 - #include LV_TICK_CUSTOM_INCLUDE -#endif +#include "../core/lv_global.h" /********************* * DEFINES *********************/ +#define state LV_GLOBAL_DEFAULT()->tick_state /********************** * TYPEDEFS @@ -28,10 +26,6 @@ /********************** * STATIC VARIABLES **********************/ -#if !LV_TICK_CUSTOM - static uint32_t sys_time = 0; - static volatile uint8_t tick_irq_flag; -#endif /********************** * MACROS @@ -41,25 +35,20 @@ * GLOBAL FUNCTIONS **********************/ -#if !LV_TICK_CUSTOM -/** - * You have to call this function periodically - * @param tick_period the call period of this function in milliseconds - */ -void LV_ATTRIBUTE_TICK_INC lv_tick_inc(uint32_t tick_period) +LV_ATTRIBUTE_TICK_INC void lv_tick_inc(uint32_t tick_period) { - tick_irq_flag = 0; - sys_time += tick_period; -} -#endif + lv_tick_state_t * state_p = &state; + + state_p->sys_irq_flag = 0; + state_p->sys_time += tick_period; +} -/** - * Get the elapsed milliseconds since start up - * @return the elapsed milliseconds - */ uint32_t lv_tick_get(void) { -#if LV_TICK_CUSTOM == 0 + lv_tick_state_t * state_p = &state; + + if(state_p->tick_get_cb) + return state_p->tick_get_cb(); /*If `lv_tick_inc` is called from an interrupt while `sys_time` is read *the result might be corrupted. @@ -68,21 +57,13 @@ uint32_t lv_tick_get(void) *until `tick_irq_flag` remains `1`.*/ uint32_t result; do { - tick_irq_flag = 1; - result = sys_time; - } while(!tick_irq_flag); /*Continue until see a non interrupted cycle*/ + state_p->sys_irq_flag = 1; + result = state_p->sys_time; + } while(!state_p->sys_irq_flag); /*Continue until see a non interrupted cycle*/ return result; -#else - return LV_TICK_CUSTOM_SYS_TIME_EXPR; -#endif } -/** - * Get the elapsed milliseconds since a previous time stamp - * @param prev_tick a previous time stamp (return value of lv_tick_get() ) - * @return the elapsed milliseconds since 'prev_tick' - */ uint32_t lv_tick_elaps(uint32_t prev_tick) { uint32_t act_time = lv_tick_get(); @@ -99,6 +80,34 @@ uint32_t lv_tick_elaps(uint32_t prev_tick) return prev_tick; } +void lv_delay_ms(uint32_t ms) +{ + if(state.delay_cb) { + state.delay_cb(ms); + } + else { + uint32_t t = lv_tick_get(); + while(lv_tick_elaps(t) < ms) { + /*Do something to no call `lv_tick_elaps` too often as it might interfere with interrupts*/ + volatile uint32_t i; + volatile uint32_t x = ms; + for(i = 0; i < 100; i++) { + x = x * 3; + } + } + } +} + +void lv_tick_set_cb(lv_tick_get_cb_t cb) +{ + state.tick_get_cb = cb; +} + +void lv_delay_set_cb(lv_delay_cb_t cb) +{ + state.delay_cb = cb; +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/tick/lv_tick.h b/lib/libesp32_lvgl/lvgl/src/tick/lv_tick.h new file mode 100644 index 000000000..da8620371 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/tick/lv_tick.h @@ -0,0 +1,93 @@ +/** + * @file lv_hal_tick.h + * Provide access to the system tick with 1 millisecond resolution + */ + +#ifndef LV_HAL_TICK_H +#define LV_HAL_TICK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lv_conf_internal.h" + +#include +#include + +/********************* + * DEFINES + *********************/ +#ifndef LV_ATTRIBUTE_TICK_INC +#define LV_ATTRIBUTE_TICK_INC +#endif + +/********************** + * TYPEDEFS + **********************/ +typedef uint32_t (*lv_tick_get_cb_t)(void); + +typedef void (*lv_delay_cb_t)(uint32_t ms); + +typedef struct { + uint32_t sys_time; + volatile uint8_t sys_irq_flag; + lv_tick_get_cb_t tick_get_cb; + lv_delay_cb_t delay_cb; +} lv_tick_state_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * You have to call this function periodically + * @param tick_period the call period of this function in milliseconds + */ +LV_ATTRIBUTE_TICK_INC void lv_tick_inc(uint32_t tick_period); + +/** + * Get the elapsed milliseconds since start up + * @return the elapsed milliseconds + */ +uint32_t lv_tick_get(void); + +/** + * Get the elapsed milliseconds since a previous time stamp + * @param prev_tick a previous time stamp (return value of lv_tick_get() ) + * @return the elapsed milliseconds since 'prev_tick' + */ +uint32_t lv_tick_elaps(uint32_t prev_tick); + +/** + * Delay for the given milliseconds. + * By default it's a blocking delay, but with `lv_delay_set_cb()` + * a custom delay function can be set too + * @param ms the number of milliseconds to delay + */ +void lv_delay_ms(uint32_t ms); + +/** + * Set the custom callback for 'lv_tick_get' + * @param cb call this callback on 'lv_tick_get' + */ +void lv_tick_set_cb(lv_tick_get_cb_t cb); + +/** + * Set a custom callback for 'lv_dalay_ms' + * @param cb call this callback in 'lv_dalay_ms' + */ +void lv_delay_set_cb(lv_delay_cb_t cb); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_HAL_TICK_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/animimg/lv_animimg.c b/lib/libesp32_lvgl/lvgl/src/widgets/animimage/lv_animimage.c similarity index 65% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/animimg/lv_animimg.c rename to lib/libesp32_lvgl/lvgl/src/widgets/animimage/lv_animimage.c index 072d02e05..a0ebdca38 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/animimg/lv_animimg.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/animimage/lv_animimage.c @@ -6,21 +6,21 @@ /********************* * INCLUDES *********************/ -#include "lv_animimg.h" +#include "lv_animimage.h" #if LV_USE_ANIMIMG != 0 /*Testing of dependencies*/ -#if LV_USE_IMG == 0 - #error "lv_animimg: lv_img is required. Enable it in lv_conf.h (LV_USE_IMG 1) " +#if LV_USE_IMAGE == 0 + #error "lv_animimg: lv_img is required. Enable it in lv_conf.h (LV_USE_IMAGE 1) " #endif -#include "../../../misc/lv_assert.h" -#include "../../../draw/lv_img_decoder.h" -#include "../../../misc/lv_fs.h" -#include "../../../misc/lv_txt.h" -#include "../../../misc/lv_math.h" -#include "../../../misc/lv_log.h" -#include "../../../misc/lv_anim.h" +#include "../../draw/lv_image_decoder.h" +#include "../../misc/lv_assert.h" +#include "../../misc/lv_fs.h" +#include "../../misc/lv_text.h" +#include "../../misc/lv_math.h" +#include "../../misc/lv_log.h" +#include "../../misc/lv_anim.h" /********************* * DEFINES @@ -42,10 +42,12 @@ static void lv_animimg_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob /********************** * STATIC VARIABLES **********************/ + const lv_obj_class_t lv_animimg_class = { .constructor_cb = lv_animimg_constructor, .instance_size = sizeof(lv_animimg_t), - .base_class = &lv_img_class + .base_class = &lv_image_class, + .name = "animimg", }; /********************** @@ -64,13 +66,13 @@ lv_obj_t * lv_animimg_create(lv_obj_t * parent) return obj; } -void lv_animimg_set_src(lv_obj_t * obj, const void * dsc[], uint8_t num) +void lv_animimg_set_src(lv_obj_t * obj, const void * dsc[], size_t num) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_animimg_t * animimg = (lv_animimg_t *)obj; animimg->dsc = dsc; animimg->pic_count = num; - lv_anim_set_values(&animimg->anim, 0, num); + lv_anim_set_values(&animimg->anim, 0, (int32_t)num - 1); } void lv_animimg_start(lv_obj_t * obj) @@ -88,11 +90,11 @@ void lv_animimg_set_duration(lv_obj_t * obj, uint32_t duration) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_animimg_t * animimg = (lv_animimg_t *)obj; - lv_anim_set_time(&animimg->anim, duration); + lv_anim_set_duration(&animimg->anim, duration); lv_anim_set_playback_delay(&animimg->anim, duration); } -void lv_animimg_set_repeat_count(lv_obj_t * obj, uint16_t count) +void lv_animimg_set_repeat_count(lv_obj_t * obj, uint32_t count) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_animimg_t * animimg = (lv_animimg_t *)obj; @@ -103,6 +105,34 @@ void lv_animimg_set_repeat_count(lv_obj_t * obj, uint16_t count) * Getter functions *====================*/ +const void ** lv_animimg_get_src(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_animimg_t * animimg = (lv_animimg_t *)obj; + return animimg->dsc; +} + +uint8_t lv_animimg_get_src_count(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_animimg_t * animimg = (lv_animimg_t *)obj; + return animimg->pic_count; +} + +uint32_t lv_animimg_get_duration(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_animimg_t * animimg = (lv_animimg_t *)obj; + return lv_anim_get_time(&animimg->anim); +} + +uint32_t lv_animimg_get_repeat_count(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_animimg_t * animimg = (lv_animimg_t *)obj; + return lv_anim_get_repeat_count(&animimg->anim); +} + /********************** * STATIC FUNCTIONS **********************/ @@ -116,10 +146,11 @@ static void lv_animimg_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob animimg->dsc = NULL; animimg->pic_count = -1; - //initial animation + + /*initial animation*/ lv_anim_init(&animimg->anim); lv_anim_set_var(&animimg->anim, obj); - lv_anim_set_time(&animimg->anim, 30); + lv_anim_set_duration(&animimg->anim, 30); lv_anim_set_exec_cb(&animimg->anim, (lv_anim_exec_xcb_t)index_change); lv_anim_set_values(&animimg->anim, 0, 1); lv_anim_set_repeat_count(&animimg->anim, LV_ANIM_REPEAT_INFINITE); @@ -127,12 +158,12 @@ static void lv_animimg_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob static void index_change(lv_obj_t * obj, int32_t index) { - lv_coord_t idx; + int32_t idx; lv_animimg_t * animimg = (lv_animimg_t *)obj; idx = index % animimg->pic_count; - lv_img_set_src(obj, animimg->dsc[idx]); + lv_image_set_src(obj, animimg->dsc[idx]); } #endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/animimage/lv_animimage.h b/lib/libesp32_lvgl/lvgl/src/widgets/animimage/lv_animimage.h new file mode 100644 index 000000000..87df81540 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/animimage/lv_animimage.h @@ -0,0 +1,136 @@ +/** + * @file lv_animimg.h + * + */ + +#ifndef LV_ANIM_IMAGE_H +#define LV_ANIM_IMAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../image/lv_image.h" + +#if LV_USE_ANIMIMG != 0 + +/*Testing of dependencies*/ +#if LV_USE_IMAGE == 0 +#error "lv_animimg: lv_img is required. Enable it in lv_conf.h (LV_USE_IMAGE 1)" +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_animimg_class; + +/*Data of the animimage*/ +typedef struct { + lv_image_t img; + lv_anim_t anim; + /*picture sequence */ + const void ** dsc; + int8_t pic_count; +} lv_animimg_t; + +/*Image parts*/ +enum _lv_animimg_part_t { + LV_ANIM_IMAGE_PART_MAIN, +}; + +#ifdef DOXYGEN +typedef _lv_animimg_part_t lv_animimg_part_t; +#else +typedef uint8_t lv_animimg_part_t; +#endif + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an animation image objects + * @param parent pointer to an object, it will be the parent of the new button + * @return pointer to the created animation image object + */ +lv_obj_t * lv_animimg_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the image animation images source. + * @param img pointer to an animation image object + * @param dsc pointer to a series images + * @param num images' number + */ +void lv_animimg_set_src(lv_obj_t * img, const void * dsc[], size_t num); + +/** + * Startup the image animation. + * @param obj pointer to an animation image object + */ +void lv_animimg_start(lv_obj_t * obj); + +/** + * Set the image animation duration time. unit:ms + * @param img pointer to an animation image object + * @param duration the duration in milliseconds + */ +void lv_animimg_set_duration(lv_obj_t * img, uint32_t duration); + +/** + * Set the image animation repeatedly play times. + * @param img pointer to an animation image object + * @param count the number of times to repeat the animation + */ +void lv_animimg_set_repeat_count(lv_obj_t * img, uint32_t count); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the image animation images source. + * @param img pointer to an animation image object + * @return a pointer that will point to a series images + */ +const void ** lv_animimg_get_src(lv_obj_t * img); + +/** + * Get the image animation images source. + * @param img pointer to an animation image object + * @return the number of source images + */ +uint8_t lv_animimg_get_src_count(lv_obj_t * img); + +/** + * Get the image animation duration time. unit:ms + * @param img pointer to an animation image object + * @return the animation duration time + */ +uint32_t lv_animimg_get_duration(lv_obj_t * img); + +/** + * Get the image animation repeat play times. + * @param img pointer to an animation image object + * @return the repeat count + */ +uint32_t lv_animimg_get_repeat_count(lv_obj_t * img); + +#endif /*LV_USE_ANIMIMG*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_ANIM_IMAGE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.c b/lib/libesp32_lvgl/lvgl/src/widgets/arc/lv_arc.c similarity index 69% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.c rename to lib/libesp32_lvgl/lvgl/src/widgets/arc/lv_arc.c index 63cf57740..4465a0b40 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/arc/lv_arc.c @@ -9,11 +9,11 @@ #include "lv_arc.h" #if LV_USE_ARC != 0 -#include "../core/lv_group.h" -#include "../core/lv_indev.h" -#include "../misc/lv_assert.h" -#include "../misc/lv_math.h" -#include "../draw/lv_draw_arc.h" +#include "../../core/lv_group.h" +#include "../../indev/lv_indev.h" +#include "../../misc/lv_assert.h" +#include "../../misc/lv_math.h" +#include "../../draw/lv_draw_arc.h" /********************* * DEFINES @@ -37,14 +37,15 @@ static void lv_arc_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void lv_arc_draw(lv_event_t * e); static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e); -static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angle, lv_part_t part); +static void inv_arc_area(lv_obj_t * arc, lv_value_precise_t start_angle, lv_value_precise_t end_angle, lv_part_t part); static void inv_knob_area(lv_obj_t * obj); -static void get_center(const lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r); -static lv_coord_t get_angle(const lv_obj_t * obj); -static void get_knob_area(lv_obj_t * arc, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area); +static void get_center(const lv_obj_t * obj, lv_point_t * center, int32_t * arc_r); +static lv_value_precise_t get_angle(const lv_obj_t * obj); +static void get_knob_area(lv_obj_t * arc, const lv_point_t * center, int32_t r, lv_area_t * knob_area); static void value_update(lv_obj_t * arc); -static lv_coord_t knob_get_extra_size(lv_obj_t * obj); -static bool lv_arc_angle_within_bg_bounds(lv_obj_t * obj, const uint32_t angle, const uint32_t tolerance_deg); +static int32_t knob_get_extra_size(lv_obj_t * obj); +static bool lv_arc_angle_within_bg_bounds(lv_obj_t * obj, const lv_value_precise_t angle, + const lv_value_precise_t tolerance_deg); /********************** * STATIC VARIABLES @@ -54,7 +55,8 @@ const lv_obj_class_t lv_arc_class = { .event_cb = lv_arc_event, .instance_size = sizeof(lv_arc_t), .editable = LV_OBJ_CLASS_EDITABLE_TRUE, - .base_class = &lv_obj_class + .base_class = &lv_obj_class, + .name = "arc", }; /********************** @@ -85,15 +87,15 @@ lv_obj_t * lv_arc_create(lv_obj_t * parent) * Setter functions *====================*/ -void lv_arc_set_start_angle(lv_obj_t * obj, uint16_t start) +void lv_arc_set_start_angle(lv_obj_t * obj, lv_value_precise_t start) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_arc_t * arc = (lv_arc_t *)obj; if(start > 360) start -= 360; - int16_t old_delta = arc->indic_angle_end - arc->indic_angle_start; - int16_t new_delta = arc->indic_angle_end - start; + lv_value_precise_t old_delta = arc->indic_angle_end - arc->indic_angle_start; + lv_value_precise_t new_delta = arc->indic_angle_end - start; if(old_delta < 0) old_delta = 360 + old_delta; if(new_delta < 0) new_delta = 360 + new_delta; @@ -109,14 +111,14 @@ void lv_arc_set_start_angle(lv_obj_t * obj, uint16_t start) inv_knob_area(obj); } -void lv_arc_set_end_angle(lv_obj_t * obj, uint16_t end) +void lv_arc_set_end_angle(lv_obj_t * obj, lv_value_precise_t end) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_arc_t * arc = (lv_arc_t *)obj; if(end > 360) end -= 360; - int16_t old_delta = arc->indic_angle_end - arc->indic_angle_start; - int16_t new_delta = end - arc->indic_angle_start; + lv_value_precise_t old_delta = arc->indic_angle_end - arc->indic_angle_start; + lv_value_precise_t new_delta = end - arc->indic_angle_start; if(old_delta < 0) old_delta = 360 + old_delta; if(new_delta < 0) new_delta = 360 + new_delta; @@ -132,21 +134,21 @@ void lv_arc_set_end_angle(lv_obj_t * obj, uint16_t end) inv_knob_area(obj); } -void lv_arc_set_angles(lv_obj_t * obj, uint16_t start, uint16_t end) +void lv_arc_set_angles(lv_obj_t * obj, lv_value_precise_t start, lv_value_precise_t end) { lv_arc_set_end_angle(obj, end); lv_arc_set_start_angle(obj, start); } -void lv_arc_set_bg_start_angle(lv_obj_t * obj, uint16_t start) +void lv_arc_set_bg_start_angle(lv_obj_t * obj, lv_value_precise_t start) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_arc_t * arc = (lv_arc_t *)obj; if(start > 360) start -= 360; - int16_t old_delta = arc->bg_angle_end - arc->bg_angle_start; - int16_t new_delta = arc->bg_angle_end - start; + lv_value_precise_t old_delta = arc->bg_angle_end - arc->bg_angle_start; + lv_value_precise_t new_delta = arc->bg_angle_end - start; if(old_delta < 0) old_delta = 360 + old_delta; if(new_delta < 0) new_delta = 360 + new_delta; @@ -160,15 +162,15 @@ void lv_arc_set_bg_start_angle(lv_obj_t * obj, uint16_t start) value_update(obj); } -void lv_arc_set_bg_end_angle(lv_obj_t * obj, uint16_t end) +void lv_arc_set_bg_end_angle(lv_obj_t * obj, lv_value_precise_t end) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_arc_t * arc = (lv_arc_t *)obj; if(end > 360) end -= 360; - int16_t old_delta = arc->bg_angle_end - arc->bg_angle_start; - int16_t new_delta = end - arc->bg_angle_start; + lv_value_precise_t old_delta = arc->bg_angle_end - arc->bg_angle_start; + lv_value_precise_t new_delta = end - arc->bg_angle_start; if(old_delta < 0) old_delta = 360 + old_delta; if(new_delta < 0) new_delta = 360 + new_delta; @@ -182,13 +184,13 @@ void lv_arc_set_bg_end_angle(lv_obj_t * obj, uint16_t end) value_update(obj); } -void lv_arc_set_bg_angles(lv_obj_t * obj, uint16_t start, uint16_t end) +void lv_arc_set_bg_angles(lv_obj_t * obj, lv_value_precise_t start, lv_value_precise_t end) { lv_arc_set_bg_end_angle(obj, end); lv_arc_set_bg_start_angle(obj, start); } -void lv_arc_set_rotation(lv_obj_t * obj, uint16_t rotation) +void lv_arc_set_rotation(lv_obj_t * obj, int32_t rotation) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_arc_t * arc = (lv_arc_t *)obj; @@ -203,12 +205,12 @@ void lv_arc_set_mode(lv_obj_t * obj, lv_arc_mode_t type) LV_ASSERT_OBJ(obj, MY_CLASS); lv_arc_t * arc = (lv_arc_t *)obj; - int16_t val = arc->value; + int32_t val = arc->value; arc->type = type; arc->value = -1; /** Force set_value handling*/ - int16_t bg_midpoint, bg_end = arc->bg_angle_end; + lv_value_precise_t bg_midpoint, bg_end = arc->bg_angle_end; if(arc->bg_angle_end < arc->bg_angle_start) bg_end = arc->bg_angle_end + 360; switch(arc->type) { @@ -227,14 +229,14 @@ void lv_arc_set_mode(lv_obj_t * obj, lv_arc_mode_t type) lv_arc_set_value(obj, val); } -void lv_arc_set_value(lv_obj_t * obj, int16_t value) +void lv_arc_set_value(lv_obj_t * obj, int32_t value) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_arc_t * arc = (lv_arc_t *)obj; if(arc->value == value) return; - int16_t new_value; + int32_t new_value; new_value = value > arc->max_value ? arc->max_value : value; new_value = new_value < arc->min_value ? arc->min_value : new_value; @@ -244,7 +246,7 @@ void lv_arc_set_value(lv_obj_t * obj, int16_t value) value_update(obj); } -void lv_arc_set_range(lv_obj_t * obj, int16_t min, int16_t max) +void lv_arc_set_range(lv_obj_t * obj, int32_t min, int32_t max) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_arc_t * arc = (lv_arc_t *)obj; @@ -264,7 +266,7 @@ void lv_arc_set_range(lv_obj_t * obj, int16_t min, int16_t max) value_update(obj); /*value has changed relative to the new range*/ } -void lv_arc_set_change_rate(lv_obj_t * obj, uint16_t rate) +void lv_arc_set_change_rate(lv_obj_t * obj, uint32_t rate) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_arc_t * arc = (lv_arc_t *)obj; @@ -272,47 +274,55 @@ void lv_arc_set_change_rate(lv_obj_t * obj, uint16_t rate) arc->chg_rate = rate; } +void lv_arc_set_knob_offset(lv_obj_t * obj, int32_t offset) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_arc_t * arc = (lv_arc_t *)obj; + + arc->knob_offset = offset; +} + /*===================== * Getter functions *====================*/ -uint16_t lv_arc_get_angle_start(lv_obj_t * obj) +lv_value_precise_t lv_arc_get_angle_start(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); return ((lv_arc_t *) obj)->indic_angle_start; } -uint16_t lv_arc_get_angle_end(lv_obj_t * obj) +lv_value_precise_t lv_arc_get_angle_end(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); return ((lv_arc_t *) obj)->indic_angle_end; } -uint16_t lv_arc_get_bg_angle_start(lv_obj_t * obj) +lv_value_precise_t lv_arc_get_bg_angle_start(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); return ((lv_arc_t *) obj)->bg_angle_start; } -uint16_t lv_arc_get_bg_angle_end(lv_obj_t * obj) +lv_value_precise_t lv_arc_get_bg_angle_end(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); return ((lv_arc_t *) obj)->bg_angle_end; } -int16_t lv_arc_get_value(const lv_obj_t * obj) +int32_t lv_arc_get_value(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); return ((lv_arc_t *) obj)->value; } -int16_t lv_arc_get_min_value(const lv_obj_t * obj) +int32_t lv_arc_get_min_value(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); return ((lv_arc_t *) obj)->min_value; } -int16_t lv_arc_get_max_value(const lv_obj_t * obj) +int32_t lv_arc_get_max_value(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); return ((lv_arc_t *) obj)->max_value; @@ -324,12 +334,23 @@ lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj) return ((lv_arc_t *) obj)->type; } +int32_t lv_arc_get_rotation(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + return ((lv_arc_t *)obj)->rotation; +} + +int32_t lv_arc_get_knob_offset(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + return ((lv_arc_t *)obj)->knob_offset; +} + /*===================== * Other functions *====================*/ - -void lv_arc_align_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_align, lv_coord_t r_offset) +void lv_arc_align_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_align, int32_t r_offset) { LV_ASSERT_OBJ(obj, MY_CLASS); LV_ASSERT_NULL(obj_to_align); @@ -337,20 +358,20 @@ void lv_arc_align_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_align, lv lv_obj_update_layout(obj); lv_point_t center; - lv_coord_t arc_r; + int32_t arc_r; get_center(obj, ¢er, &arc_r); - lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); - lv_coord_t indic_width_half = indic_width / 2; + int32_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); + int32_t indic_width_half = indic_width / 2; arc_r -= indic_width_half; arc_r += r_offset; - uint16_t angle = get_angle(obj); - lv_coord_t knob_x = (arc_r * lv_trigo_sin(angle + 90)) >> LV_TRIGO_SHIFT; - lv_coord_t knob_y = (arc_r * lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT; + int32_t angle = (int32_t)get_angle(obj); + int32_t knob_x = (arc_r * lv_trigo_sin(angle + 90)) >> LV_TRIGO_SHIFT; + int32_t knob_y = (arc_r * lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT; lv_obj_align_to(obj_to_align, obj, LV_ALIGN_CENTER, knob_x, knob_y); } -void lv_arc_rotate_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_rotate, lv_coord_t r_offset) +void lv_arc_rotate_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_rotate, int32_t r_offset) { LV_ASSERT_OBJ(obj, MY_CLASS); LV_ASSERT_NULL(obj_to_rotate); @@ -358,10 +379,10 @@ void lv_arc_rotate_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_rotate, lv_obj_update_layout(obj); lv_point_t center; - lv_coord_t arc_r; + int32_t arc_r; get_center(obj, ¢er, &arc_r); - lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); - lv_coord_t indic_width_half = indic_width / 2; + int32_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); + int32_t indic_width_half = indic_width / 2; arc_r -= indic_width_half; arc_r += r_offset; @@ -369,15 +390,14 @@ void lv_arc_rotate_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_rotate, lv_obj_update_layout(obj); - uint16_t angle = get_angle(obj); - lv_coord_t pivot_x = obj_to_rotate->coords.x1 - center.x; - lv_coord_t pivot_y = obj_to_rotate->coords.y1 - center.y; + int32_t angle = (int32_t)get_angle(obj); + int32_t pivot_x = obj_to_rotate->coords.x1 - center.x; + int32_t pivot_y = obj_to_rotate->coords.y1 - center.y; lv_obj_set_style_transform_pivot_x(obj_to_rotate, -pivot_x, 0); lv_obj_set_style_transform_pivot_y(obj_to_rotate, -pivot_y, 0); - lv_obj_set_style_transform_angle(obj_to_rotate, angle * 10 + 900, 0); + lv_obj_set_style_transform_rotation(obj_to_rotate, angle * 10 + 900, 0); } - /********************** * STATIC FUNCTIONS **********************/ @@ -407,10 +427,9 @@ static void lv_arc_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) arc->in_out = CLICK_OUTSIDE_BG_ANGLES; lv_obj_add_flag(obj, LV_OBJ_FLAG_CLICKABLE); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN | LV_OBJ_FLAG_SCROLLABLE); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN | LV_OBJ_FLAG_SCROLLABLE); lv_obj_set_ext_click_area(obj, LV_DPI_DEF / 10); - LV_TRACE_OBJ_CREATE("finished"); } @@ -418,17 +437,17 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) { LV_UNUSED(class_p); - lv_res_t res; + lv_result_t res; /*Call the ancestor's event handler*/ res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); - lv_arc_t * arc = (lv_arc_t *)lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); + lv_arc_t * arc = (lv_arc_t *)obj; if(code == LV_EVENT_PRESSING) { - lv_indev_t * indev = lv_indev_get_act(); + lv_indev_t * indev = lv_indev_active(); if(indev == NULL) return; /*Handle only pointers here*/ @@ -440,7 +459,7 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) /*Make point relative to the arc's center*/ lv_point_t center; - lv_coord_t r; + int32_t r; get_center(obj, ¢er, &r); p.x -= center.x; @@ -448,7 +467,7 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) /*Enter dragging mode if pressed out of the knob*/ if(arc->dragging == false) { - lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); + int32_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); r -= indic_width; /*Add some more sensitive area if there is no advanced git testing. * (Advanced hit testing is more precise)*/ @@ -474,8 +493,8 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) if(p.x == 0 && p.y == 0) return; /*Calculate the angle of the pressed point*/ - int16_t angle; - int16_t bg_end = arc->bg_angle_end; + lv_value_precise_t angle; + lv_value_precise_t bg_end = arc->bg_angle_end; if(arc->bg_angle_end < arc->bg_angle_start) { bg_end = arc->bg_angle_end + 360; } @@ -488,17 +507,17 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) if(angle < 0) angle += 360; const uint32_t circumference = (uint32_t)((2U * r * 314U) / 100U); /* Equivalent to: 2r * 3.14, avoiding floats */ - const uint32_t tolerance_deg = (360U * LV_DPX(50U)) / circumference; + const lv_value_precise_t tolerance_deg = (360 * lv_dpx(50U)) / circumference; const uint32_t min_close_prev = (uint32_t) arc->min_close; - const bool is_angle_within_bg_bounds = lv_arc_angle_within_bg_bounds(obj, (uint32_t) angle, tolerance_deg); + const bool is_angle_within_bg_bounds = lv_arc_angle_within_bg_bounds(obj, angle, tolerance_deg); if(!is_angle_within_bg_bounds) { return; } - int16_t deg_range = bg_end - arc->bg_angle_start; - int16_t last_angle_rel = arc->last_angle - arc->bg_angle_start; - int16_t delta_angle = angle - last_angle_rel; + lv_value_precise_t deg_range = bg_end - arc->bg_angle_start; + lv_value_precise_t last_angle_rel = arc->last_angle - arc->bg_angle_start; + lv_value_precise_t delta_angle = angle - last_angle_rel; /*Do not allow big jumps (jumps bigger than 280°). *It's mainly to avoid jumping to the opposite end if the "dead" range between min. and max. is crossed. @@ -531,7 +550,7 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) uint32_t delta_tick = lv_tick_elaps(arc->last_tick); /* delta_angle_max can never be signed. delta_tick is always signed, same for ch_rate */ - const uint16_t delta_angle_max = (arc->chg_rate * delta_tick) / 1000; + const lv_value_precise_t delta_angle_max = (arc->chg_rate * delta_tick) / 1000; if(delta_angle > delta_angle_max) { delta_angle = delta_angle_max; @@ -544,21 +563,26 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) angle = last_angle_rel + delta_angle; /*Apply the limited angle change*/ /*Rounding for symmetry*/ - int32_t round = ((bg_end - arc->bg_angle_start) * 8) / (arc->max_value - arc->min_value); - round = (round + 4) >> 4; + lv_value_precise_t round = ((bg_end - arc->bg_angle_start) * 8) / (arc->max_value - arc->min_value); + round = (round + 4) / 16; angle += round; angle += arc->bg_angle_start; /*Make the angle absolute again*/ /*Set the new value*/ - int16_t old_value = arc->value; - int16_t new_value = lv_map(angle, arc->bg_angle_start, bg_end, arc->min_value, arc->max_value); + int32_t old_value = arc->value; + int32_t new_value = lv_map((int32_t)angle, (int32_t)arc->bg_angle_start, (int32_t)bg_end, arc->min_value, + arc->max_value); + if(arc->type == LV_ARC_MODE_REVERSE) { + new_value = arc->max_value - new_value + arc->min_value; + } + if(new_value != lv_arc_get_value(obj)) { arc->last_tick = lv_tick_get(); /*Cache timestamp for the next iteration*/ lv_arc_set_value(obj, new_value); /*set_value caches the last_angle for the next iteration*/ if(new_value != old_value) { - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; + res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RESULT_OK) return; } } @@ -573,14 +597,14 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) /*Leave edit mode if released. (No need to wait for LONG_PRESS)*/ lv_group_t * g = lv_obj_get_group(obj); bool editing = lv_group_get_editing(g); - lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); + lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_active()); if(indev_type == LV_INDEV_TYPE_ENCODER) { if(editing) lv_group_set_editing(g, false); } } else if(code == LV_EVENT_KEY) { - char c = *((char *)lv_event_get_param(e)); + uint32_t c = lv_event_get_key(e); int16_t old_value = arc->value; if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { @@ -591,21 +615,21 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) } if(old_value != arc->value) { - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; + res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RESULT_OK) return; } } else if(code == LV_EVENT_HIT_TEST) { lv_hit_test_info_t * info = lv_event_get_param(e); lv_point_t p; - lv_coord_t r; + int32_t r; get_center(obj, &p, &r); - lv_coord_t ext_click_area = 0; + int32_t ext_click_area = 0; if(obj->spec_attr) ext_click_area = obj->spec_attr->ext_click_pad; - lv_coord_t w = lv_obj_get_style_arc_width(obj, LV_PART_MAIN); + int32_t w = lv_obj_get_style_arc_width(obj, LV_PART_MAIN); r -= w + ext_click_area; lv_area_t a; @@ -621,22 +645,22 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) info->res = _lv_area_is_point_on(&a, info->point, LV_RADIUS_CIRCLE); } else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); - lv_coord_t bg_pad = LV_MAX4(bg_left, bg_right, bg_top, bg_bottom); + int32_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + int32_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + int32_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + int32_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + int32_t bg_pad = LV_MAX4(bg_left, bg_right, bg_top, bg_bottom); - lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); - lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); - lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); - lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); - lv_coord_t knob_pad = LV_MAX4(knob_left, knob_right, knob_top, knob_bottom) + 2; + int32_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); + int32_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); + int32_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); + int32_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); + int32_t knob_pad = LV_MAX4(knob_left, knob_right, knob_top, knob_bottom) + 2; - lv_coord_t knob_extra_size = knob_pad - bg_pad; + int32_t knob_extra_size = knob_pad - bg_pad; knob_extra_size += knob_get_extra_size(obj); - lv_coord_t * s = lv_event_get_param(e); + int32_t * s = lv_event_get_param(e); *s = LV_MAX(*s, knob_extra_size); } else if(code == LV_EVENT_DRAW_MAIN) { @@ -646,62 +670,44 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) static void lv_arc_draw(lv_event_t * e) { - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_arc_t * arc = (lv_arc_t *)obj; - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); lv_point_t center; - lv_coord_t arc_r; + int32_t arc_r; get_center(obj, ¢er, &arc_r); - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - /*Draw the background arc*/ lv_draw_arc_dsc_t arc_dsc; if(arc_r > 0) { lv_draw_arc_dsc_init(&arc_dsc); lv_obj_init_draw_arc_dsc(obj, LV_PART_MAIN, &arc_dsc); - - part_draw_dsc.part = LV_PART_MAIN; - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_ARC_DRAW_PART_BACKGROUND; - part_draw_dsc.p1 = ¢er; - part_draw_dsc.radius = arc_r; - part_draw_dsc.arc_dsc = &arc_dsc; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - - lv_draw_arc(draw_ctx, &arc_dsc, ¢er, part_draw_dsc.radius, arc->bg_angle_start + arc->rotation, - arc->bg_angle_end + arc->rotation); - - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); + arc_dsc.center = center; + arc_dsc.start_angle = arc->bg_angle_start + arc->rotation; + arc_dsc.end_angle = arc->bg_angle_end + arc->rotation; + arc_dsc.radius = arc_r; + lv_draw_arc(layer, &arc_dsc); } /*Make the indicator arc smaller or larger according to its greatest padding value*/ - lv_coord_t left_indic = lv_obj_get_style_pad_left(obj, LV_PART_INDICATOR); - lv_coord_t right_indic = lv_obj_get_style_pad_right(obj, LV_PART_INDICATOR); - lv_coord_t top_indic = lv_obj_get_style_pad_top(obj, LV_PART_INDICATOR); - lv_coord_t bottom_indic = lv_obj_get_style_pad_bottom(obj, LV_PART_INDICATOR); - lv_coord_t indic_r = arc_r - LV_MAX4(left_indic, right_indic, top_indic, bottom_indic); + int32_t left_indic = lv_obj_get_style_pad_left(obj, LV_PART_INDICATOR); + int32_t right_indic = lv_obj_get_style_pad_right(obj, LV_PART_INDICATOR); + int32_t top_indic = lv_obj_get_style_pad_top(obj, LV_PART_INDICATOR); + int32_t bottom_indic = lv_obj_get_style_pad_bottom(obj, LV_PART_INDICATOR); + int32_t indic_r = arc_r - LV_MAX4(left_indic, right_indic, top_indic, bottom_indic); if(indic_r > 0) { lv_draw_arc_dsc_init(&arc_dsc); lv_obj_init_draw_arc_dsc(obj, LV_PART_INDICATOR, &arc_dsc); + arc_dsc.center = center; + arc_dsc.start_angle = arc->indic_angle_start + arc->rotation; + arc_dsc.end_angle = arc->indic_angle_end + arc->rotation; - part_draw_dsc.part = LV_PART_INDICATOR; - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_ARC_DRAW_PART_FOREGROUND; - part_draw_dsc.p1 = ¢er; - part_draw_dsc.radius = indic_r; - part_draw_dsc.arc_dsc = &arc_dsc; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); + arc_dsc.radius = indic_r; - if(arc_dsc.width > part_draw_dsc.radius) arc_dsc.width = part_draw_dsc.radius; - lv_draw_arc(draw_ctx, &arc_dsc, ¢er, part_draw_dsc.radius, arc->indic_angle_start + arc->rotation, - arc->indic_angle_end + arc->rotation); - - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); + lv_draw_arc(layer, &arc_dsc); } lv_area_t knob_area; @@ -710,20 +716,10 @@ static void lv_arc_draw(lv_event_t * e) lv_draw_rect_dsc_t knob_rect_dsc; lv_draw_rect_dsc_init(&knob_rect_dsc); lv_obj_init_draw_rect_dsc(obj, LV_PART_KNOB, &knob_rect_dsc); - - part_draw_dsc.part = LV_PART_KNOB; - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_ARC_DRAW_PART_KNOB; - part_draw_dsc.draw_area = &knob_area; - part_draw_dsc.rect_dsc = &knob_rect_dsc; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - - lv_draw_rect(draw_ctx, &knob_rect_dsc, &knob_area); - - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); + lv_draw_rect(layer, &knob_rect_dsc, &knob_area); } -static void inv_arc_area(lv_obj_t * obj, uint16_t start_angle, uint16_t end_angle, lv_part_t part) +static void inv_arc_area(lv_obj_t * obj, lv_value_precise_t start_angle, lv_value_precise_t end_angle, lv_part_t part) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -743,12 +739,12 @@ static void inv_arc_area(lv_obj_t * obj, uint16_t start_angle, uint16_t end_angl if(start_angle > 360) start_angle -= 360; if(end_angle > 360) end_angle -= 360; - lv_coord_t r; + int32_t r; lv_point_t c; get_center(obj, &c, &r); - lv_coord_t w = lv_obj_get_style_arc_width(obj, part); - lv_coord_t rounded = lv_obj_get_style_arc_rounded(obj, part); + int32_t w = lv_obj_get_style_arc_width(obj, part); + int32_t rounded = lv_obj_get_style_arc_rounded(obj, part); lv_area_t inv_area; lv_draw_arc_get_area(c.x, c.y, r, start_angle, end_angle, w, rounded, &inv_area); @@ -759,13 +755,13 @@ static void inv_arc_area(lv_obj_t * obj, uint16_t start_angle, uint16_t end_angl static void inv_knob_area(lv_obj_t * obj) { lv_point_t c; - lv_coord_t r; + int32_t r; get_center(obj, &c, &r); lv_area_t a; get_knob_area(obj, &c, r, &a); - lv_coord_t knob_extra_size = knob_get_extra_size(obj); + int32_t knob_extra_size = knob_get_extra_size(obj); if(knob_extra_size > 0) { lv_area_increase(&a, knob_extra_size, knob_extra_size); @@ -774,15 +770,15 @@ static void inv_knob_area(lv_obj_t * obj) lv_obj_invalidate_area(obj, &a); } -static void get_center(const lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r) +static void get_center(const lv_obj_t * obj, lv_point_t * center, int32_t * arc_r) { - lv_coord_t left_bg = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t right_bg = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t top_bg = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t bottom_bg = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + int32_t left_bg = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + int32_t right_bg = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + int32_t top_bg = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + int32_t bottom_bg = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); - lv_coord_t r = (LV_MIN(lv_obj_get_width(obj) - left_bg - right_bg, - lv_obj_get_height(obj) - top_bg - bottom_bg)) / 2; + int32_t r = (LV_MIN(lv_obj_get_width(obj) - left_bg - right_bg, + lv_obj_get_height(obj) - top_bg - bottom_bg)) / 2; center->x = obj->coords.x1 + r + left_bg; center->y = obj->coords.y1 + r + top_bg; @@ -790,10 +786,10 @@ static void get_center(const lv_obj_t * obj, lv_point_t * center, lv_coord_t * a if(arc_r) *arc_r = r; } -static lv_coord_t get_angle(const lv_obj_t * obj) +static lv_value_precise_t get_angle(const lv_obj_t * obj) { lv_arc_t * arc = (lv_arc_t *)obj; - uint16_t angle = arc->rotation; + lv_value_precise_t angle = arc->rotation; if(arc->type == LV_ARC_MODE_NORMAL) { angle += arc->indic_angle_end; } @@ -801,12 +797,12 @@ static lv_coord_t get_angle(const lv_obj_t * obj) angle += arc->indic_angle_start; } else if(arc->type == LV_ARC_MODE_SYMMETRICAL) { - int16_t bg_end = arc->bg_angle_end; + lv_value_precise_t bg_end = arc->bg_angle_end; if(arc->bg_angle_end < arc->bg_angle_start) bg_end = arc->bg_angle_end + 360; - int16_t indic_end = arc->indic_angle_end; + lv_value_precise_t indic_end = arc->indic_angle_end; if(arc->indic_angle_end < arc->indic_angle_start) indic_end = arc->indic_angle_end + 360; - int32_t angle_midpoint = (int32_t)(arc->bg_angle_start + bg_end) / 2; + lv_value_precise_t angle_midpoint = (int32_t)(arc->bg_angle_start + bg_end) / 2; if(arc->indic_angle_start < angle_midpoint) angle += arc->indic_angle_start; else if(indic_end > angle_midpoint) angle += arc->indic_angle_end; else angle += angle_midpoint; @@ -815,21 +811,21 @@ static lv_coord_t get_angle(const lv_obj_t * obj) return angle; } - -static void get_knob_area(lv_obj_t * obj, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area) +static void get_knob_area(lv_obj_t * obj, const lv_point_t * center, int32_t r, lv_area_t * knob_area) { - lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); - lv_coord_t indic_width_half = indic_width / 2; + int32_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR); + int32_t indic_width_half = indic_width / 2; r -= indic_width_half; - lv_coord_t angle = get_angle(obj); - lv_coord_t knob_x = (r * lv_trigo_sin(angle + 90)) >> LV_TRIGO_SHIFT; - lv_coord_t knob_y = (r * lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT; + int32_t angle = (int32_t)get_angle(obj); + int32_t knob_offset = lv_arc_get_knob_offset(obj); + int32_t knob_x = (r * lv_trigo_sin(knob_offset + angle + 90)) >> LV_TRIGO_SHIFT; + int32_t knob_y = (r * lv_trigo_sin(knob_offset + angle)) >> LV_TRIGO_SHIFT; - lv_coord_t left_knob = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); - lv_coord_t right_knob = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); - lv_coord_t top_knob = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); - lv_coord_t bottom_knob = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); + int32_t left_knob = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); + int32_t right_knob = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); + int32_t top_knob = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); + int32_t bottom_knob = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); knob_area->x1 = center->x + knob_x - left_knob - indic_width_half; knob_area->x2 = center->x + knob_x + right_knob + indic_width_half; @@ -849,32 +845,33 @@ static void value_update(lv_obj_t * obj) /*If the value is still not set to any value do not update*/ if(arc->value == VALUE_UNSET) return; - int16_t bg_midpoint, range_midpoint, bg_end = arc->bg_angle_end; + lv_value_precise_t bg_midpoint, bg_end = arc->bg_angle_end; + int32_t range_midpoint; if(arc->bg_angle_end < arc->bg_angle_start) bg_end = arc->bg_angle_end + 360; - int16_t angle; + int32_t angle; switch(arc->type) { case LV_ARC_MODE_SYMMETRICAL: bg_midpoint = (arc->bg_angle_start + bg_end) / 2; range_midpoint = (int32_t)(arc->min_value + arc->max_value) / 2; if(arc->value < range_midpoint) { - angle = lv_map(arc->value, arc->min_value, range_midpoint, arc->bg_angle_start, bg_midpoint); + angle = lv_map(arc->value, arc->min_value, range_midpoint, (int32_t)arc->bg_angle_start, (int32_t)bg_midpoint); lv_arc_set_start_angle(obj, angle); lv_arc_set_end_angle(obj, bg_midpoint); } else { - angle = lv_map(arc->value, range_midpoint, arc->max_value, bg_midpoint, bg_end); + angle = lv_map(arc->value, range_midpoint, arc->max_value, (int32_t)bg_midpoint, (int32_t)bg_end); lv_arc_set_start_angle(obj, bg_midpoint); lv_arc_set_end_angle(obj, angle); } break; case LV_ARC_MODE_REVERSE: - angle = lv_map(arc->value, arc->min_value, arc->max_value, bg_end, arc->bg_angle_start); + angle = lv_map(arc->value, arc->min_value, arc->max_value, (int32_t)bg_end, (int32_t)arc->bg_angle_start); lv_arc_set_angles(obj, angle, arc->bg_angle_end); break; case LV_ARC_MODE_NORMAL: - angle = lv_map(arc->value, arc->min_value, arc->max_value, arc->bg_angle_start, bg_end); + angle = lv_map(arc->value, arc->min_value, arc->max_value, (int32_t)arc->bg_angle_start, (int32_t)bg_end); lv_arc_set_angles(obj, arc->bg_angle_start, angle); break; @@ -885,15 +882,15 @@ static void value_update(lv_obj_t * obj) arc->last_angle = angle; /*Cache angle for slew rate limiting*/ } -static lv_coord_t knob_get_extra_size(lv_obj_t * obj) +static int32_t knob_get_extra_size(lv_obj_t * obj) { - lv_coord_t knob_shadow_size = 0; + int32_t knob_shadow_size = 0; knob_shadow_size += lv_obj_get_style_shadow_width(obj, LV_PART_KNOB); knob_shadow_size += lv_obj_get_style_shadow_spread(obj, LV_PART_KNOB); - knob_shadow_size += LV_ABS(lv_obj_get_style_shadow_ofs_x(obj, LV_PART_KNOB)); - knob_shadow_size += LV_ABS(lv_obj_get_style_shadow_ofs_y(obj, LV_PART_KNOB)); + knob_shadow_size += LV_ABS(lv_obj_get_style_shadow_offset_x(obj, LV_PART_KNOB)); + knob_shadow_size += LV_ABS(lv_obj_get_style_shadow_offset_y(obj, LV_PART_KNOB)); - lv_coord_t knob_outline_size = 0; + int32_t knob_outline_size = 0; knob_outline_size += lv_obj_get_style_outline_width(obj, LV_PART_KNOB); knob_outline_size += lv_obj_get_style_outline_pad(obj, LV_PART_KNOB); @@ -922,13 +919,14 @@ static lv_coord_t knob_get_extra_size(lv_obj_t * obj) * * @return true if angle is within arc background bounds, false otherwise */ -static bool lv_arc_angle_within_bg_bounds(lv_obj_t * obj, const uint32_t angle, const uint32_t tolerance_deg) +static bool lv_arc_angle_within_bg_bounds(lv_obj_t * obj, const lv_value_precise_t angle, + const lv_value_precise_t tolerance_deg) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_arc_t * arc = (lv_arc_t *)obj; - uint32_t smaller_angle = 0; - uint32_t bigger_angle = 0; + lv_value_precise_t smaller_angle = 0; + lv_value_precise_t bigger_angle = 0; /* Determine which background angle is smaller and bigger */ if(arc->bg_angle_start < arc->bg_angle_end) { @@ -943,7 +941,7 @@ static bool lv_arc_angle_within_bg_bounds(lv_obj_t * obj, const uint32_t angle, /* Angle is between both background angles */ if((smaller_angle <= angle) && (angle <= bigger_angle)) { - if(((bigger_angle - smaller_angle) / 2U) >= angle) { + if(((bigger_angle - smaller_angle) / 2) >= angle) { arc->min_close = 1; } else { @@ -956,8 +954,8 @@ static bool lv_arc_angle_within_bg_bounds(lv_obj_t * obj, const uint32_t angle, } /* Distance between background start and end angles is less than tolerance, * consider the click inside the arc */ - else if(((smaller_angle - tolerance_deg) <= 0U) && - (360U - (bigger_angle + (smaller_angle - tolerance_deg)))) { + else if(((smaller_angle - tolerance_deg) <= 0) && + (360 - (bigger_angle + (smaller_angle - tolerance_deg))) != 0) { arc->min_close = 1; arc->in_out = CLICK_INSIDE_BG_ANGLES; @@ -976,7 +974,7 @@ static bool lv_arc_angle_within_bg_bounds(lv_obj_t * obj, const uint32_t angle, * Start angle is bigger or equal to tolerance */ if((smaller_angle >= tolerance_deg) /* (360° - T) --- A --- 360° */ - && ((angle >= (360U - tolerance_deg)) && (angle <= 360U))) { + && ((angle >= (360 - tolerance_deg)) && (angle <= 360))) { arc->min_close = 1; arc->in_out = CLICK_OUTSIDE_BG_ANGLES; @@ -985,14 +983,14 @@ static bool lv_arc_angle_within_bg_bounds(lv_obj_t * obj, const uint32_t angle, /* Tolerance is bigger than bg start angle */ else if((smaller_angle < tolerance_deg) /* (360° - (T - S)) --- A --- 360° */ - && (((360U - (tolerance_deg - smaller_angle)) <= angle)) && (angle <= 360U)) { + && (((360 - (tolerance_deg - smaller_angle)) <= angle)) && (angle <= 360)) { arc->min_close = 1; arc->in_out = CLICK_OUTSIDE_BG_ANGLES; return true; } /* 360° is bigger than background end angle + tolerance */ - else if((360U >= (bigger_angle + tolerance_deg)) + else if((360 >= (bigger_angle + tolerance_deg)) /* E --- A --- (E + T) */ && ((bigger_angle <= (angle + smaller_angle)) && ((angle + smaller_angle) <= (bigger_angle + tolerance_deg)))) { @@ -1003,8 +1001,8 @@ static bool lv_arc_angle_within_bg_bounds(lv_obj_t * obj, const uint32_t angle, } /* Background end angle + tolerance is bigger than 360° and bg_start_angle + tolerance is not near 0° + ((bg_end_angle + tolerance) - 360°) * Here we can assume background is not near 0° because of the first two initial checks */ - else if((360U < (bigger_angle + tolerance_deg)) - && (angle <= 0U + ((bigger_angle + tolerance_deg) - 360U)) && (angle > bigger_angle)) { + else if((360 < (bigger_angle + tolerance_deg)) + && (angle <= 0 + ((bigger_angle + tolerance_deg) - 360)) && (angle > bigger_angle)) { arc->min_close = 0; arc->in_out = CLICK_OUTSIDE_BG_ANGLES; diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/arc/lv_arc.h b/lib/libesp32_lvgl/lvgl/src/widgets/arc/lv_arc.h new file mode 100644 index 000000000..bea60c6ef --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/arc/lv_arc.h @@ -0,0 +1,273 @@ +/** + * @file lv_arc.h + * + */ + +#ifndef LV_ARC_H +#define LV_ARC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" + +#if LV_USE_ARC != 0 + +#include "../../core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +enum _lv_arc_mode_t { + LV_ARC_MODE_NORMAL, + LV_ARC_MODE_SYMMETRICAL, + LV_ARC_MODE_REVERSE +}; + +#ifdef DOXYGEN +typedef _lv_arc_mode_t lv_arc_mode_t; +#else +typedef uint8_t lv_arc_mode_t; +#endif /*DOXYGEN*/ + +typedef struct { + lv_obj_t obj; + int32_t rotation; + lv_value_precise_t indic_angle_start; + lv_value_precise_t indic_angle_end; + lv_value_precise_t bg_angle_start; + lv_value_precise_t bg_angle_end; + int32_t value; /*Current value of the arc*/ + int32_t min_value; /*Minimum value of the arc*/ + int32_t max_value; /*Maximum value of the arc*/ + uint32_t dragging : 1; + uint32_t type : 2; + uint32_t min_close : 1; /*1: the last pressed angle was closer to minimum end*/ + uint32_t in_out : 1; /* 1: The click was within the background arc angles. 0: Click outside */ + uint32_t chg_rate; /*Drag angle rate of change of the arc (degrees/sec)*/ + uint32_t last_tick; /*Last dragging event timestamp of the arc*/ + lv_value_precise_t last_angle; /*Last dragging angle of the arc*/ + int16_t knob_offset; /*knob offset from the main arc*/ +} lv_arc_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_arc_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an arc object + * @param parent pointer to an object, it will be the parent of the new arc + * @return pointer to the created arc + */ +lv_obj_t * lv_arc_create(lv_obj_t * parent); + +/*====================== + * Add/remove functions + *=====================*/ + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the start angle of an arc. 0 deg: right, 90 bottom, etc. + * @param obj pointer to an arc object + * @param start the start angle. (if `LV_USE_FLOAT` is enabled it can be fractional too.) + */ +void lv_arc_set_start_angle(lv_obj_t * obj, lv_value_precise_t start); + +/** + * Set the end angle of an arc. 0 deg: right, 90 bottom, etc. + * @param obj pointer to an arc object + * @param end the end angle (if `LV_USE_FLOAT` is enabled it can be fractional too.) + */ +void lv_arc_set_end_angle(lv_obj_t * obj, lv_value_precise_t end); + +/** + * Set the start and end angles + * @param obj pointer to an arc object + * @param start the start angle (if `LV_USE_FLOAT` is enabled it can be fractional too.) + * @param end the end angle (if `LV_USE_FLOAT` is enabled it can be fractional too.) + */ +void lv_arc_set_angles(lv_obj_t * obj, lv_value_precise_t start, lv_value_precise_t end); + +/** + * Set the start angle of an arc background. 0 deg: right, 90 bottom, etc. + * @param obj pointer to an arc object + * @param start the start angle (if `LV_USE_FLOAT` is enabled it can be fractional too.) + */ +void lv_arc_set_bg_start_angle(lv_obj_t * obj, lv_value_precise_t start); + +/** + * Set the start angle of an arc background. 0 deg: right, 90 bottom etc. + * @param obj pointer to an arc object + * @param end the end angle (if `LV_USE_FLOAT` is enabled it can be fractional too.) + */ +void lv_arc_set_bg_end_angle(lv_obj_t * obj, lv_value_precise_t end); + +/** + * Set the start and end angles of the arc background + * @param obj pointer to an arc object + * @param start the start angle (if `LV_USE_FLOAT` is enabled it can be fractional too.) + * @param end the end angle (if `LV_USE_FLOAT` is enabled it can be fractional too.) + */ +void lv_arc_set_bg_angles(lv_obj_t * obj, lv_value_precise_t start, lv_value_precise_t end); + +/** + * Set the rotation for the whole arc + * @param obj pointer to an arc object + * @param rotation rotation angle + */ +void lv_arc_set_rotation(lv_obj_t * obj, int32_t rotation); + +/** + * Set the type of arc. + * @param obj pointer to arc object + * @param type arc's mode + */ +void lv_arc_set_mode(lv_obj_t * obj, lv_arc_mode_t type); + +/** + * Set a new value on the arc + * @param obj pointer to an arc object + * @param value new value + */ +void lv_arc_set_value(lv_obj_t * obj, int32_t value); + +/** + * Set minimum and the maximum values of an arc + * @param obj pointer to the arc object + * @param min minimum value + * @param max maximum value + */ +void lv_arc_set_range(lv_obj_t * obj, int32_t min, int32_t max); + +/** + * Set a change rate to limit the speed how fast the arc should reach the pressed point. + * @param obj pointer to an arc object + * @param rate the change rate + */ +void lv_arc_set_change_rate(lv_obj_t * obj, uint32_t rate); + +/** + * Set an offset angle for the knob + * @param obj pointer to an arc object + * @param offset knob offset from main arc in degrees + */ +void lv_arc_set_knob_offset(lv_obj_t * obj, int32_t offset); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the start angle of an arc. + * @param obj pointer to an arc object + * @return the start angle [0..360] (if `LV_USE_FLOAT` is enabled it can be fractional too.) + */ +lv_value_precise_t lv_arc_get_angle_start(lv_obj_t * obj); + +/** + * Get the end angle of an arc. + * @param obj pointer to an arc object + * @return the end angle [0..360] (if `LV_USE_FLOAT` is enabled it can be fractional too.) + */ +lv_value_precise_t lv_arc_get_angle_end(lv_obj_t * obj); + +/** + * Get the start angle of an arc background. + * @param obj pointer to an arc object + * @return the start angle [0..360] (if `LV_USE_FLOAT` is enabled it can be fractional too.) + */ +lv_value_precise_t lv_arc_get_bg_angle_start(lv_obj_t * obj); + +/** + * Get the end angle of an arc background. + * @param obj pointer to an arc object + * @return the end angle [0..360] (if `LV_USE_FLOAT` is enabled it can be fractional too.) + */ +lv_value_precise_t lv_arc_get_bg_angle_end(lv_obj_t * obj); + +/** + * Get the value of an arc + * @param obj pointer to an arc object + * @return the value of the arc + */ +int32_t lv_arc_get_value(const lv_obj_t * obj); + +/** + * Get the minimum value of an arc + * @param obj pointer to an arc object + * @return the minimum value of the arc + */ +int32_t lv_arc_get_min_value(const lv_obj_t * obj); + +/** + * Get the maximum value of an arc + * @param obj pointer to an arc object + * @return the maximum value of the arc + */ +int32_t lv_arc_get_max_value(const lv_obj_t * obj); + +/** + * Get whether the arc is type or not. + * @param obj pointer to an arc object + * @return arc's mode + */ +lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj); + +/** + * Get the rotation for the whole arc + * @param obj pointer to an arc object + * @return arc's current rotation + */ +int32_t lv_arc_get_rotation(const lv_obj_t * obj); + +/** + * Get the current knob angle offset + * @param obj pointer to an arc object + * @return arc's current knob offset + */ +int32_t lv_arc_get_knob_offset(const lv_obj_t * obj); + +/*===================== + * Other functions + *====================*/ + +/** + * Align an object to the current position of the arc (knob) + * @param obj pointer to an arc object + * @param obj_to_align pointer to an object to align + * @param r_offset consider the radius larger with this value (< 0: for smaller radius) + */ +void lv_arc_align_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_align, int32_t r_offset); + +/** + * Rotate an object to the current position of the arc (knob) + * @param obj pointer to an arc object + * @param obj_to_rotate pointer to an object to rotate + * @param r_offset consider the radius larger with this value (< 0: for smaller radius) + */ +void lv_arc_rotate_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_rotate, int32_t r_offset); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_ARC*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_ARC_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_bar.c b/lib/libesp32_lvgl/lvgl/src/widgets/bar/lv_bar.c similarity index 57% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_bar.c rename to lib/libesp32_lvgl/lvgl/src/widgets/bar/lv_bar.c index a057618ec..44e72213e 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_bar.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/bar/lv_bar.c @@ -9,10 +9,10 @@ #include "lv_bar.h" #if LV_USE_BAR != 0 -#include "../misc/lv_assert.h" -#include "../draw/lv_draw.h" -#include "../misc/lv_anim.h" -#include "../misc/lv_math.h" +#include "../../draw/lv_draw.h" +#include "../../misc/lv_assert.h" +#include "../../misc/lv_anim.h" +#include "../../misc/lv_math.h" /********************* * DEFINES @@ -52,7 +52,7 @@ static void lv_bar_set_value_with_anim(lv_obj_t * obj, int32_t new_value, int32_ _lv_bar_anim_t * anim_info, lv_anim_enable_t en); static void lv_bar_init_anim(lv_obj_t * bar, _lv_bar_anim_t * bar_anim); static void lv_bar_anim(void * bar, int32_t value); -static void lv_bar_anim_ready(lv_anim_t * a); +static void lv_bar_anim_completed(lv_anim_t * a); /********************** * STATIC VARIABLES @@ -64,7 +64,8 @@ const lv_obj_class_t lv_bar_class = { .width_def = LV_DPI_DEF * 2, .height_def = LV_DPI_DEF / 10, .instance_size = sizeof(lv_bar_t), - .base_class = &lv_obj_class + .base_class = &lv_obj_class, + .name = "bar", }; /********************** @@ -98,6 +99,7 @@ void lv_bar_set_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim) value = value < bar->start_value ? bar->start_value : value; /*Can't be smaller than the left value*/ if(bar->cur_value == value) return; + lv_bar_set_value_with_anim(obj, value, &bar->cur_value, &bar->cur_value_anim, anim); } @@ -115,6 +117,7 @@ void lv_bar_set_start_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim value = value > bar->cur_value ? bar->cur_value : value; /*Can't be greater than the right value*/ if(bar->start_value == value) return; + lv_bar_set_value_with_anim(obj, value, &bar->start_value, &bar->start_value_anim, anim); } @@ -124,22 +127,27 @@ void lv_bar_set_range(lv_obj_t * obj, int32_t min, int32_t max) lv_bar_t * bar = (lv_bar_t *)obj; - if(bar->min_value == min && bar->max_value == max) return; + bar->val_reversed = min > max; - bar->max_value = max; - bar->min_value = min; + int32_t real_min = bar->val_reversed ? max : min; + int32_t real_max = bar->val_reversed ? min : max; + if(bar->min_value == real_min && bar->max_value == real_max) return; + + bar->max_value = real_max; + bar->min_value = real_min; if(lv_bar_get_mode(obj) != LV_BAR_MODE_RANGE) - bar->start_value = min; + bar->start_value = real_min; - if(bar->cur_value > max) { - bar->cur_value = max; + if(bar->cur_value > real_max) { + bar->cur_value = real_max; lv_bar_set_value(obj, bar->cur_value, LV_ANIM_OFF); } - if(bar->cur_value < min) { - bar->cur_value = min; + if(bar->cur_value < real_min) { + bar->cur_value = real_min; lv_bar_set_value(obj, bar->cur_value, LV_ANIM_OFF); } + lv_obj_invalidate(obj); } @@ -182,7 +190,7 @@ int32_t lv_bar_get_min_value(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_bar_t * bar = (lv_bar_t *)obj; - return bar->min_value; + return bar->val_reversed ? bar->max_value : bar->min_value; } int32_t lv_bar_get_max_value(const lv_obj_t * obj) @@ -190,7 +198,7 @@ int32_t lv_bar_get_max_value(const lv_obj_t * obj) LV_ASSERT_OBJ(obj, MY_CLASS); lv_bar_t * bar = (lv_bar_t *)obj; - return bar->max_value; + return bar->val_reversed ? bar->min_value : bar->max_value; } lv_bar_mode_t lv_bar_get_mode(lv_obj_t * obj) @@ -201,6 +209,15 @@ lv_bar_mode_t lv_bar_get_mode(lv_obj_t * obj) return bar->mode; } +bool lv_bar_is_symmetrical(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_bar_t * bar = (lv_bar_t *)obj; + + return bar->mode == LV_BAR_MODE_SYMMETRICAL && bar->min_value < 0 && bar->max_value > 0 && + bar->start_value == bar->min_value; +} + /********************** * STATIC FUNCTIONS **********************/ @@ -220,12 +237,13 @@ static void lv_bar_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) bar->indic_area.y1 = 0; bar->indic_area.y2 = 0; bar->mode = LV_BAR_MODE_NORMAL; + bar->val_reversed = false; lv_bar_init_anim(obj, &bar->cur_value_anim); lv_bar_init_anim(obj, &bar->start_value_anim); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_CHECKABLE); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_CHECKABLE); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLLABLE); lv_bar_set_value(obj, 0, LV_ANIM_OFF); LV_TRACE_OBJ_CREATE("finished"); @@ -236,39 +254,41 @@ static void lv_bar_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) LV_UNUSED(class_p); lv_bar_t * bar = (lv_bar_t *)obj; - lv_anim_del(&bar->cur_value_anim, NULL); - lv_anim_del(&bar->start_value_anim, NULL); + lv_anim_delete(&bar->cur_value_anim, NULL); + lv_anim_delete(&bar->start_value_anim, NULL); } static void draw_indic(lv_event_t * e) { - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_bar_t * bar = (lv_bar_t *)obj; - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); lv_area_t bar_coords; lv_obj_get_coords(obj, &bar_coords); - lv_coord_t transf_w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN); - lv_coord_t transf_h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN); - bar_coords.x1 -= transf_w; - bar_coords.x2 += transf_w; - bar_coords.y1 -= transf_h; - bar_coords.y2 += transf_h; - lv_coord_t barw = lv_area_get_width(&bar_coords); - lv_coord_t barh = lv_area_get_height(&bar_coords); + int32_t transf_w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN); + int32_t transf_h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN); + lv_area_increase(&bar_coords, transf_w, transf_h); + int32_t barw = lv_area_get_width(&bar_coords); + int32_t barh = lv_area_get_height(&bar_coords); int32_t range = bar->max_value - bar->min_value; - bool hor = barw >= barh ? true : false; - bool sym = false; - if(bar->mode == LV_BAR_MODE_SYMMETRICAL && bar->min_value < 0 && bar->max_value > 0 && - bar->start_value == bar->min_value) sym = true; + + /*Prevent division by 0*/ + if(range == 0) { + range = 1; + } + + bool hor = barw >= barh; + bool sym = lv_bar_is_symmetrical(obj); /*Calculate the indicator area*/ - lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + int32_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + int32_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + int32_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + int32_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + /*Respect padding and minimum width/height too*/ lv_area_copy(&bar->indic_area, &bar_coords); bar->indic_area.x1 += bg_left; @@ -285,16 +305,16 @@ static void draw_indic(lv_event_t * e) bar->indic_area.x2 = bar->indic_area.x1 + LV_BAR_SIZE_MIN; } - lv_coord_t indicw = lv_area_get_width(&bar->indic_area); - lv_coord_t indich = lv_area_get_height(&bar->indic_area); + int32_t indic_max_w = lv_area_get_width(&bar->indic_area); + int32_t indic_max_h = lv_area_get_height(&bar->indic_area); /*Calculate the indicator length*/ - lv_coord_t anim_length = hor ? indicw : indich; + int32_t anim_length = hor ? indic_max_w : indic_max_h; - lv_coord_t anim_cur_value_x, anim_start_value_x; + int32_t anim_cur_value_x, anim_start_value_x; - lv_coord_t * axis1, * axis2; - lv_coord_t (*indic_length_calc)(const lv_area_t * area); + int32_t * axis1, * axis2; + int32_t (*indic_length_calc)(const lv_area_t * area); if(hor) { axis1 = &bar->indic_area.x1; @@ -308,9 +328,9 @@ static void draw_indic(lv_event_t * e) } if(LV_BAR_IS_ANIMATING(bar->start_value_anim)) { - lv_coord_t anim_start_value_start_x = + int32_t anim_start_value_start_x = (int32_t)((int32_t)anim_length * (bar->start_value_anim.anim_start - bar->min_value)) / range; - lv_coord_t anim_start_value_end_x = + int32_t anim_start_value_end_x = (int32_t)((int32_t)anim_length * (bar->start_value_anim.anim_end - bar->min_value)) / range; anim_start_value_x = (((anim_start_value_end_x - anim_start_value_start_x) * bar->start_value_anim.anim_state) / @@ -323,9 +343,9 @@ static void draw_indic(lv_event_t * e) } if(LV_BAR_IS_ANIMATING(bar->cur_value_anim)) { - lv_coord_t anim_cur_value_start_x = + int32_t anim_cur_value_start_x = (int32_t)((int32_t)anim_length * (bar->cur_value_anim.anim_start - bar->min_value)) / range; - lv_coord_t anim_cur_value_end_x = + int32_t anim_cur_value_end_x = (int32_t)((int32_t)anim_length * (bar->cur_value_anim.anim_end - bar->min_value)) / range; anim_cur_value_x = anim_cur_value_start_x + (((anim_cur_value_end_x - anim_cur_value_start_x) * @@ -336,10 +356,17 @@ static void draw_indic(lv_event_t * e) anim_cur_value_x = (int32_t)((int32_t)anim_length * (bar->cur_value - bar->min_value)) / range; } + /** + * The drawing direction of the bar can be reversed only when one of the two conditions(value inversion + * or horizontal direction base dir is LV_BASE_DIR_RTL) is met. + */ lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN); - if(hor && base_dir == LV_BASE_DIR_RTL) { + bool hor_need_reversed = hor && base_dir == LV_BASE_DIR_RTL; + bool reversed = bar->val_reversed ^ hor_need_reversed; + + if(reversed) { /*Swap axes*/ - lv_coord_t * tmp; + int32_t * tmp; tmp = axis1; axis1 = axis2; axis2 = tmp; @@ -356,47 +383,50 @@ static void draw_indic(lv_event_t * e) *axis1 = *axis2 - anim_cur_value_x + 1; *axis2 -= anim_start_value_x; } + if(sym) { - lv_coord_t zero, shift; + int32_t zero, shift; shift = (-bar->min_value * anim_length) / range; + if(hor) { - zero = *axis1 + shift; - if(*axis2 > zero) - *axis1 = zero; + int32_t * left = reversed ? axis2 : axis1; + int32_t * right = reversed ? axis1 : axis2; + if(reversed) + zero = *axis1 - shift + 1; + else + zero = *axis1 + shift; + + if(*axis2 > zero) { + *right = *axis2; + *left = zero; + } else { - *axis1 = *axis2; - *axis2 = zero; + *left = *axis2; + *right = zero; } } else { - zero = *axis2 - shift + 1; - if(*axis1 > zero) - *axis2 = zero; - else { - *axis2 = *axis1; - *axis1 = zero; + int32_t * top = reversed ? axis2 : axis1; + int32_t * bottom = reversed ? axis1 : axis2; + if(reversed) + zero = *axis2 + shift; + else + zero = *axis2 - shift + 1; + + if(*axis1 > zero) { + *bottom = *axis1; + *top = zero; } - if(*axis2 < *axis1) { - /*swap*/ - zero = *axis1; - *axis1 = *axis2; - *axis2 = zero; + else { + *top = *axis1; + *bottom = zero; } } } - /*Do not draw a zero length indicator but at least call the draw part events*/ + /*Do not draw a zero length indicator but at least call the draw task event*/ if(!sym && indic_length_calc(&bar->indic_area) <= 1) { - - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.part = LV_PART_INDICATOR; - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_BAR_DRAW_PART_INDICATOR; - part_draw_dsc.draw_area = &bar->indic_area; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); + lv_obj_send_event(obj, LV_EVENT_DRAW_TASK_ADDED, NULL); return; } @@ -407,134 +437,148 @@ static void draw_indic(lv_event_t * e) lv_draw_rect_dsc_init(&draw_rect_dsc); lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &draw_rect_dsc); - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.part = LV_PART_INDICATOR; - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_BAR_DRAW_PART_INDICATOR; - part_draw_dsc.rect_dsc = &draw_rect_dsc; - part_draw_dsc.draw_area = &bar->indic_area; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - - lv_coord_t bg_radius = lv_obj_get_style_radius(obj, LV_PART_MAIN); - lv_coord_t short_side = LV_MIN(barw, barh); + int32_t bg_radius = lv_obj_get_style_radius(obj, LV_PART_MAIN); + int32_t short_side = LV_MIN(barw, barh); if(bg_radius > short_side >> 1) bg_radius = short_side >> 1; - lv_coord_t indic_radius = draw_rect_dsc.radius; - short_side = LV_MIN(indicw, indich); + int32_t indic_radius = draw_rect_dsc.radius; + short_side = LV_MIN(lv_area_get_width(&bar->indic_area), lv_area_get_height(&bar->indic_area)); if(indic_radius > short_side >> 1) indic_radius = short_side >> 1; - /*Draw only the shadow and outline only if the indicator is long enough. - *The radius of the bg and the indicator can make a strange shape where - *it'd be very difficult to draw shadow.*/ - if((hor && lv_area_get_width(&bar->indic_area) > indic_radius * 2) || - (!hor && lv_area_get_height(&bar->indic_area) > indic_radius * 2)) { - lv_opa_t bg_opa = draw_rect_dsc.bg_opa; - lv_opa_t bg_img_opa = draw_rect_dsc.bg_img_opa; - lv_opa_t border_opa = draw_rect_dsc.border_opa; - draw_rect_dsc.bg_opa = LV_OPA_TRANSP; - draw_rect_dsc.bg_img_opa = LV_OPA_TRANSP; - draw_rect_dsc.border_opa = LV_OPA_TRANSP; + /*Cases: + * Simple: + * - indicator area is the same or smaller then the bg + * - indicator has the same or larger radius than the bg + * - what to do? just draw the indicator + * Radius issue: + * - indicator area is the same or smaller then bg + * - indicator has smaller radius than the bg and the indicator overflows on the corners + * - what to do? draw the indicator on a layer and clip to bg radius + * Larger indicator: + * - indicator area is the larger then the bg + * - radius doesn't matter + * - shadow doesn't matter + * - what to do? just draw the indicator + * Shadow: + * - indicator area is the same or smaller then the bg + * - indicator has the same or larger radius than the bg (shadow needs to be drawn on strange clipped shape) + * - what to do? don't draw the shadow if the indicator is too small has strange shape + * Gradient: + * - the indicator has a gradient + * - what to do? draw it on a bg sized layer clip the indicator are from the gradient + * + */ - lv_draw_rect(draw_ctx, &draw_rect_dsc, &bar->indic_area); + bool gradient = false; + if(hor && draw_rect_dsc.bg_grad.dir == LV_GRAD_DIR_HOR) gradient = true; + else if(!hor && draw_rect_dsc.bg_grad.dir == LV_GRAD_DIR_VER) gradient = true; - draw_rect_dsc.bg_opa = bg_opa; - draw_rect_dsc.bg_img_opa = bg_img_opa; - draw_rect_dsc.border_opa = border_opa; + bool radius_issue = true; + /*The indicator is fully drawn if it's larger than the bg*/ + if((bg_left < 0 || bg_right < 0 || bg_top < 0 || bg_bottom < 0)) radius_issue = false; + else if(indic_radius >= bg_radius) radius_issue = false; + else if(_lv_area_is_in(&indic_area, &bar_coords, bg_radius)) radius_issue = false; + + if(radius_issue || gradient) { + if(!radius_issue) { + /*Draw only the shadow*/ + lv_draw_rect_dsc_t draw_tmp_dsc = draw_rect_dsc; + draw_tmp_dsc.border_opa = 0; + draw_tmp_dsc.outline_opa = 0; + draw_tmp_dsc.bg_opa = 0; + draw_tmp_dsc.bg_image_opa = 0; + lv_draw_rect(layer, &draw_tmp_dsc, &indic_area); + } + else { + draw_rect_dsc.border_opa = 0; + draw_rect_dsc.outline_opa = 0; + } + draw_rect_dsc.shadow_opa = 0; + + /*If clipped for any reason can the border, outline, and shadow + *would be clipped and looked ugly so don't draw them*/ + lv_draw_rect_dsc_t draw_tmp_dsc = draw_rect_dsc; + draw_tmp_dsc.border_opa = 0; + draw_tmp_dsc.outline_opa = 0; + draw_tmp_dsc.shadow_opa = 0; + lv_area_t indic_draw_area = indic_area; + if(gradient) { + if(hor) { + indic_draw_area.x1 = bar_coords.x1 + bg_left; + indic_draw_area.x2 = bar_coords.x2 - bg_right; + } + else { + indic_draw_area.y1 = bar_coords.y1 + bg_top; + indic_draw_area.y2 = bar_coords.y2 - bg_bottom; + } + draw_tmp_dsc.radius = 0; + } + + lv_layer_t * layer_indic = lv_draw_layer_create(layer, LV_COLOR_FORMAT_ARGB8888, &indic_draw_area); + + lv_draw_rect(layer_indic, &draw_tmp_dsc, &indic_draw_area); + + lv_draw_mask_rect_dsc_t mask_dsc; + lv_draw_mask_rect_dsc_init(&mask_dsc); + if(radius_issue) { + mask_dsc.area = bar_coords; + mask_dsc.radius = bg_radius; + lv_draw_mask_rect(layer_indic, &mask_dsc); + } + + if(gradient) { + mask_dsc.area = indic_area; + mask_dsc.radius = indic_radius; + lv_draw_mask_rect(layer_indic, &mask_dsc); + } + + lv_draw_image_dsc_t layer_draw_dsc; + lv_draw_image_dsc_init(&layer_draw_dsc); + layer_draw_dsc.src = layer_indic; + lv_draw_layer(layer, &layer_draw_dsc, &indic_draw_area); + + /*Add the border, outline, and shadow only to the indicator area. + *They might have disabled if there is a radius_issue*/ + draw_tmp_dsc = draw_rect_dsc; + draw_tmp_dsc.bg_opa = 0; + draw_tmp_dsc.bg_image_opa = 0; + lv_draw_rect(layer, &draw_tmp_dsc, &indic_area); } - -#if LV_DRAW_COMPLEX - lv_draw_mask_radius_param_t mask_bg_param; - lv_area_t bg_mask_area; - bg_mask_area.x1 = obj->coords.x1 + bg_left; - bg_mask_area.x2 = obj->coords.x2 - bg_right; - bg_mask_area.y1 = obj->coords.y1 + bg_top; - bg_mask_area.y2 = obj->coords.y2 - bg_bottom; - - lv_draw_mask_radius_init(&mask_bg_param, &bg_mask_area, bg_radius, false); - lv_coord_t mask_bg_id = lv_draw_mask_add(&mask_bg_param, NULL); -#endif - - /*Draw_only the background and background image*/ - lv_opa_t shadow_opa = draw_rect_dsc.shadow_opa; - lv_opa_t border_opa = draw_rect_dsc.border_opa; - draw_rect_dsc.border_opa = LV_OPA_TRANSP; - draw_rect_dsc.shadow_opa = LV_OPA_TRANSP; - - /*Get the max possible indicator area. The gradient should be applied on this*/ - lv_area_t mask_indic_max_area; - lv_area_copy(&mask_indic_max_area, &bar_coords); - mask_indic_max_area.x1 += bg_left; - mask_indic_max_area.y1 += bg_top; - mask_indic_max_area.x2 -= bg_right; - mask_indic_max_area.y2 -= bg_bottom; - if(hor && lv_area_get_height(&mask_indic_max_area) < LV_BAR_SIZE_MIN) { - mask_indic_max_area.y1 = obj->coords.y1 + (barh / 2) - (LV_BAR_SIZE_MIN / 2); - mask_indic_max_area.y2 = mask_indic_max_area.y1 + LV_BAR_SIZE_MIN; + else { + lv_draw_rect(layer, &draw_rect_dsc, &indic_area); } - else if(!hor && lv_area_get_width(&mask_indic_max_area) < LV_BAR_SIZE_MIN) { - mask_indic_max_area.x1 = obj->coords.x1 + (barw / 2) - (LV_BAR_SIZE_MIN / 2); - mask_indic_max_area.x2 = mask_indic_max_area.x1 + LV_BAR_SIZE_MIN; - } - -#if LV_DRAW_COMPLEX - /*Create a mask to the current indicator area to see only this part from the whole gradient.*/ - lv_draw_mask_radius_param_t mask_indic_param; - lv_draw_mask_radius_init(&mask_indic_param, &bar->indic_area, draw_rect_dsc.radius, false); - int16_t mask_indic_id = lv_draw_mask_add(&mask_indic_param, NULL); -#endif - - lv_draw_rect(draw_ctx, &draw_rect_dsc, &mask_indic_max_area); - draw_rect_dsc.border_opa = border_opa; - draw_rect_dsc.shadow_opa = shadow_opa; - - /*Draw the border*/ - draw_rect_dsc.bg_opa = LV_OPA_TRANSP; - draw_rect_dsc.bg_img_opa = LV_OPA_TRANSP; - draw_rect_dsc.shadow_opa = LV_OPA_TRANSP; - lv_draw_rect(draw_ctx, &draw_rect_dsc, &bar->indic_area); - -#if LV_DRAW_COMPLEX - lv_draw_mask_free_param(&mask_indic_param); - lv_draw_mask_free_param(&mask_bg_param); - lv_draw_mask_remove_id(mask_indic_id); - lv_draw_mask_remove_id(mask_bg_id); -#endif - - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); } static void lv_bar_event(const lv_obj_class_t * class_p, lv_event_t * e) { LV_UNUSED(class_p); - lv_res_t res; + lv_result_t res; /*Call the ancestor's event handler*/ res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - lv_coord_t indic_size; + int32_t indic_size; indic_size = lv_obj_calculate_ext_draw_size(obj, LV_PART_INDICATOR); /*Bg size is handled by lv_obj*/ - lv_coord_t * s = lv_event_get_param(e); + int32_t * s = lv_event_get_param(e); *s = LV_MAX(*s, indic_size); /*Calculate the indicator area*/ - lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + int32_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + int32_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + int32_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + int32_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); - lv_coord_t pad = LV_MIN4(bg_left, bg_right, bg_top, bg_bottom); + int32_t pad = LV_MIN4(bg_left, bg_right, bg_top, bg_bottom); if(pad < 0) { - *s = LV_MAX(*s, -pad); + *s = *s - pad; } } else if(code == LV_EVENT_PRESSED || code == LV_EVENT_RELEASED) { @@ -553,7 +597,7 @@ static void lv_bar_anim(void * var, int32_t value) lv_obj_invalidate(bar_anim->bar); } -static void lv_bar_anim_ready(lv_anim_t * a) +static void lv_bar_anim_completed(lv_anim_t * a) { _lv_bar_anim_t * var = a->var; lv_obj_t * obj = (lv_obj_t *)var->bar; @@ -571,10 +615,15 @@ static void lv_bar_set_value_with_anim(lv_obj_t * obj, int32_t new_value, int32_ _lv_bar_anim_t * anim_info, lv_anim_enable_t en) { if(en == LV_ANIM_OFF) { - lv_anim_del(anim_info, NULL); + lv_anim_delete(anim_info, NULL); anim_info->anim_state = LV_BAR_ANIM_STATE_INV; *value_ptr = new_value; lv_obj_invalidate((lv_obj_t *)obj); + + /*Stop the previous animation if it exists*/ + lv_anim_delete(anim_info, NULL); + /*Reset animation state*/ + lv_bar_init_anim(obj, anim_info); } else { /*No animation in progress -> simply set the values*/ @@ -589,15 +638,15 @@ static void lv_bar_set_value_with_anim(lv_obj_t * obj, int32_t new_value, int32_ } *value_ptr = new_value; /*Stop the previous animation if it exists*/ - lv_anim_del(anim_info, NULL); + lv_anim_delete(anim_info, NULL); lv_anim_t a; lv_anim_init(&a); lv_anim_set_var(&a, anim_info); lv_anim_set_exec_cb(&a, lv_bar_anim); lv_anim_set_values(&a, LV_BAR_ANIM_STATE_START, LV_BAR_ANIM_STATE_END); - lv_anim_set_ready_cb(&a, lv_bar_anim_ready); - lv_anim_set_time(&a, lv_obj_get_style_anim_time(obj, LV_PART_MAIN)); + lv_anim_set_completed_cb(&a, lv_bar_anim_completed); + lv_anim_set_duration(&a, lv_obj_get_style_anim_duration(obj, LV_PART_MAIN)); lv_anim_start(&a); } } diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_bar.h b/lib/libesp32_lvgl/lvgl/src/widgets/bar/lv_bar.h similarity index 72% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_bar.h rename to lib/libesp32_lvgl/lvgl/src/widgets/bar/lv_bar.h index 1726425b0..d2a882a05 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_bar.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/bar/lv_bar.h @@ -13,14 +13,13 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../lv_conf_internal.h" +#include "../../lv_conf_internal.h" #if LV_USE_BAR != 0 -#include "../core/lv_obj.h" -#include "../misc/lv_anim.h" -#include "lv_btn.h" -#include "lv_label.h" +#include "../../core/lv_obj.h" +#include "../../misc/lv_anim.h" +#include "../label/lv_label.h" /********************* * DEFINES @@ -29,13 +28,17 @@ extern "C" { /********************** * TYPEDEFS **********************/ - -enum { +enum _lv_bar_mode_t { LV_BAR_MODE_NORMAL, LV_BAR_MODE_SYMMETRICAL, LV_BAR_MODE_RANGE }; + +#ifdef DOXYGEN +typedef _lv_bar_mode_t lv_bar_mode_t; +#else typedef uint8_t lv_bar_mode_t; +#endif /*DOXYGEN*/ typedef struct { lv_obj_t * bar; @@ -51,20 +54,13 @@ typedef struct { int32_t max_value; /**< Maximum value of the bar*/ int32_t start_value; /**< Start value of the bar*/ lv_area_t indic_area; /**< Save the indicator area. Might be used by derived types*/ + bool val_reversed; /**< Whether value been reversed */ _lv_bar_anim_t cur_value_anim; _lv_bar_anim_t start_value_anim; lv_bar_mode_t mode : 2; /**< Type of bar*/ } lv_bar_t; -extern const lv_obj_class_t lv_bar_class; - -/** - * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_bar_class` - * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` - */ -typedef enum { - LV_BAR_DRAW_PART_INDICATOR, /**< The indicator*/ -} lv_bar_draw_part_type_t; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_bar_class; /********************** * GLOBAL PROTOTYPES @@ -72,8 +68,8 @@ typedef enum { /** * Create a bar object - * @param parent pointer to an object, it will be the parent of the new bar - * @return pointer to the created bar + * @param parent pointer to an object, it will be the parent of the new bar + * @return pointer to the created bar */ lv_obj_t * lv_bar_create(lv_obj_t * parent); @@ -83,17 +79,17 @@ lv_obj_t * lv_bar_create(lv_obj_t * parent); /** * Set a new value on the bar - * @param bar pointer to a bar object - * @param value new value - * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately + * @param obj pointer to a bar object + * @param value new value + * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately */ void lv_bar_set_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim); /** * Set a new start value on the bar - * @param obj pointer to a bar object - * @param value new start value - * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately + * @param obj pointer to a bar object + * @param start_value new start value + * @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately */ void lv_bar_set_start_value(lv_obj_t * obj, int32_t start_value, lv_anim_enable_t anim); @@ -102,6 +98,7 @@ void lv_bar_set_start_value(lv_obj_t * obj, int32_t start_value, lv_anim_enable_ * @param obj pointer to the bar object * @param min minimum value * @param max maximum value + * @note If min is greater than max, the drawing direction becomes to the oppsite direction. */ void lv_bar_set_range(lv_obj_t * obj, int32_t min, int32_t max); @@ -151,6 +148,13 @@ int32_t lv_bar_get_max_value(const lv_obj_t * obj); */ lv_bar_mode_t lv_bar_get_mode(lv_obj_t * obj); +/** + * Give the bar is in symmetrical mode or not + * @param obj pointer to bar object + * @return true: in symmetrical mode false : not in +*/ +bool lv_bar_is_symmetrical(lv_obj_t * obj); + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_btn.c b/lib/libesp32_lvgl/lvgl/src/widgets/button/lv_button.c similarity index 65% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_btn.c rename to lib/libesp32_lvgl/lvgl/src/widgets/button/lv_button.c index 5676dc7a4..70dbe9099 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_btn.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/button/lv_button.c @@ -7,15 +7,13 @@ * INCLUDES *********************/ -#include "lv_btn.h" -#if LV_USE_BTN != 0 - -#include "../extra/layouts/flex/lv_flex.h" +#include "lv_button.h" +#if LV_USE_BUTTON != 0 /********************* * DEFINES *********************/ -#define MY_CLASS &lv_btn_class +#define MY_CLASS &lv_button_class /********************** * TYPEDEFS @@ -24,18 +22,19 @@ /********************** * STATIC PROTOTYPES **********************/ -static void lv_btn_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_button_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); /********************** * STATIC VARIABLES **********************/ -const lv_obj_class_t lv_btn_class = { - .constructor_cb = lv_btn_constructor, +const lv_obj_class_t lv_button_class = { + .constructor_cb = lv_button_constructor, .width_def = LV_SIZE_CONTENT, .height_def = LV_SIZE_CONTENT, .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, - .instance_size = sizeof(lv_btn_t), - .base_class = &lv_obj_class + .instance_size = sizeof(lv_button_t), + .base_class = &lv_obj_class, + .name = "btn", }; /********************** @@ -46,7 +45,7 @@ const lv_obj_class_t lv_btn_class = { * GLOBAL FUNCTIONS **********************/ -lv_obj_t * lv_btn_create(lv_obj_t * parent) +lv_obj_t * lv_button_create(lv_obj_t * parent) { LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); @@ -58,12 +57,12 @@ lv_obj_t * lv_btn_create(lv_obj_t * parent) * STATIC FUNCTIONS **********************/ -static void lv_btn_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +static void lv_button_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { LV_UNUSED(class_p); LV_TRACE_OBJ_CREATE("begin"); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLLABLE); lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS); LV_TRACE_OBJ_CREATE("finished"); diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_btn.h b/lib/libesp32_lvgl/lvgl/src/widgets/button/lv_button.h similarity index 67% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_btn.h rename to lib/libesp32_lvgl/lvgl/src/widgets/button/lv_button.h index 1d471f975..08ba1cdbc 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_btn.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/button/lv_button.h @@ -3,8 +3,8 @@ * */ -#ifndef LV_BTN_H -#define LV_BTN_H +#ifndef LV_BUTTON_H +#define LV_BUTTON_H #ifdef __cplusplus extern "C" { @@ -13,10 +13,10 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../lv_conf_internal.h" +#include "../../lv_conf_internal.h" -#if LV_USE_BTN != 0 -#include "../core/lv_obj.h" +#if LV_USE_BUTTON != 0 +#include "../../core/lv_obj.h" /********************* * DEFINES @@ -28,9 +28,9 @@ extern "C" { typedef struct { lv_obj_t obj; -} lv_btn_t; +} lv_button_t; -extern const lv_obj_class_t lv_btn_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_button_class; /********************** * GLOBAL PROTOTYPES @@ -41,16 +41,16 @@ extern const lv_obj_class_t lv_btn_class; * @param parent pointer to an object, it will be the parent of the new button * @return pointer to the created button */ -lv_obj_t * lv_btn_create(lv_obj_t * parent); +lv_obj_t * lv_button_create(lv_obj_t * parent); /********************** * MACROS **********************/ -#endif /*LV_USE_BTN*/ +#endif /*LV_USE_BUTTON*/ #ifdef __cplusplus } /*extern "C"*/ #endif -#endif /*LV_BTN_H*/ +#endif /*LV_BUTTON_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.c b/lib/libesp32_lvgl/lvgl/src/widgets/buttonmatrix/lv_buttonmatrix.c similarity index 57% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.c rename to lib/libesp32_lvgl/lvgl/src/widgets/buttonmatrix/lv_buttonmatrix.c index fd14e56e9..291d69a78 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/buttonmatrix/lv_buttonmatrix.c @@ -6,24 +6,25 @@ /********************* * INCLUDES *********************/ -#include "lv_btnmatrix.h" -#if LV_USE_BTNMATRIX != 0 +#include "lv_buttonmatrix.h" +#if LV_USE_BUTTONMATRIX != 0 -#include "../misc/lv_assert.h" -#include "../core/lv_indev.h" -#include "../core/lv_group.h" -#include "../draw/lv_draw.h" -#include "../core/lv_refr.h" -#include "../misc/lv_txt.h" -#include "../misc/lv_txt_ap.h" +#include "../../misc/lv_assert.h" +#include "../../indev/lv_indev.h" +#include "../../core/lv_group.h" +#include "../../draw/lv_draw.h" +#include "../../core/lv_refr.h" +#include "../../misc/lv_text.h" +#include "../../misc/lv_text_ap.h" +#include "../../stdlib/lv_string.h" /********************* * DEFINES *********************/ -#define MY_CLASS &lv_btnmatrix_class +#define MY_CLASS &lv_buttonmatrix_class #define BTN_EXTRA_CLICK_AREA_MAX (LV_DPI_DEF / 10) -#define LV_BTNMATRIX_WIDTH_MASK 0x000F +#define LV_BUTTONMATRIX_WIDTH_MASK 0x000F /********************** * TYPEDEFS @@ -32,42 +33,44 @@ /********************** * STATIC PROTOTYPES **********************/ -static void lv_btnmatrix_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void lv_btnmatrix_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e); +static void lv_buttonmatrix_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_buttonmatrix_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_buttonmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e); static void draw_main(lv_event_t * e); -static uint8_t get_button_width(lv_btnmatrix_ctrl_t ctrl_bits); -static bool button_is_hidden(lv_btnmatrix_ctrl_t ctrl_bits); -static bool button_is_checked(lv_btnmatrix_ctrl_t ctrl_bits); -static bool button_is_repeat_disabled(lv_btnmatrix_ctrl_t ctrl_bits); -static bool button_is_inactive(lv_btnmatrix_ctrl_t ctrl_bits); -static bool button_is_click_trig(lv_btnmatrix_ctrl_t ctrl_bits); -static bool button_is_popover(lv_btnmatrix_ctrl_t ctrl_bits); -static bool button_is_checkable(lv_btnmatrix_ctrl_t ctrl_bits); -static bool button_is_recolor(lv_btnmatrix_ctrl_t ctrl_bits); -static bool button_get_checked(lv_btnmatrix_ctrl_t ctrl_bits); -static uint16_t get_button_from_point(lv_obj_t * obj, lv_point_t * p); -static void allocate_btn_areas_and_controls(const lv_obj_t * obj, const char ** map); -static void invalidate_button_area(const lv_obj_t * obj, uint16_t btn_idx); -static void make_one_button_checked(lv_obj_t * obj, uint16_t btn_idx); +static uint32_t get_button_width(lv_buttonmatrix_ctrl_t ctrl_bits); +static bool button_is_hidden(lv_buttonmatrix_ctrl_t ctrl_bits); +static bool button_is_checked(lv_buttonmatrix_ctrl_t ctrl_bits); +static bool button_is_repeat_disabled(lv_buttonmatrix_ctrl_t ctrl_bits); +static bool button_is_inactive(lv_buttonmatrix_ctrl_t ctrl_bits); +static bool button_is_click_trig(lv_buttonmatrix_ctrl_t ctrl_bits); +static bool button_is_popover(lv_buttonmatrix_ctrl_t ctrl_bits); +static bool button_is_checkable(lv_buttonmatrix_ctrl_t ctrl_bits); +static bool button_get_checked(lv_buttonmatrix_ctrl_t ctrl_bits); +static uint32_t get_button_from_point(lv_obj_t * obj, lv_point_t * p); +static void allocate_button_areas_and_controls(const lv_obj_t * obj, const char ** map); +static void invalidate_button_area(const lv_obj_t * obj, uint32_t btn_idx); +static void make_one_button_checked(lv_obj_t * obj, uint32_t btn_idx); static bool has_popovers_in_top_row(lv_obj_t * obj); /********************** * STATIC VARIABLES **********************/ -static const char * lv_btnmatrix_def_map[] = {"Btn1", "Btn2", "Btn3", "\n", "Btn4", "Btn5", ""}; +#if LV_WIDGETS_HAS_DEFAULT_VALUE +static const char * lv_buttonmatrix_def_map[] = {"Btn1", "Btn2", "Btn3", "\n", "Btn4", "Btn5", ""}; +#endif -const lv_obj_class_t lv_btnmatrix_class = { - .constructor_cb = lv_btnmatrix_constructor, - .destructor_cb = lv_btnmatrix_destructor, - .event_cb = lv_btnmatrix_event, +const lv_obj_class_t lv_buttonmatrix_class = { + .constructor_cb = lv_buttonmatrix_constructor, + .destructor_cb = lv_buttonmatrix_destructor, + .event_cb = lv_buttonmatrix_event, .width_def = LV_DPI_DEF * 2, .height_def = LV_DPI_DEF, - .instance_size = sizeof(lv_btnmatrix_t), + .instance_size = sizeof(lv_buttonmatrix_t), .editable = LV_OBJ_CLASS_EDITABLE_TRUE, .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, - .base_class = &lv_obj_class + .base_class = &lv_obj_class, + .name = "btnmatrix", }; /********************** @@ -78,7 +81,7 @@ const lv_obj_class_t lv_btnmatrix_class = { * GLOBAL FUNCTIONS **********************/ -lv_obj_t * lv_btnmatrix_create(lv_obj_t * parent) +lv_obj_t * lv_buttonmatrix_create(lv_obj_t * parent) { LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); @@ -90,30 +93,30 @@ lv_obj_t * lv_btnmatrix_create(lv_obj_t * parent) * Setter functions *====================*/ -void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]) +void lv_buttonmatrix_set_map(lv_obj_t * obj, const char * map[]) { LV_ASSERT_OBJ(obj, MY_CLASS); if(map == NULL) return; - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; /*Analyze the map and create the required number of buttons*/ - allocate_btn_areas_and_controls(obj, map); + allocate_button_areas_and_controls(obj, map); btnm->map_p = map; lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN); /*Set size and positions of the buttons*/ - lv_coord_t pleft = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t ptop = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t prow = lv_obj_get_style_pad_row(obj, LV_PART_MAIN); - lv_coord_t pcol = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); + int32_t sleft = lv_obj_get_style_space_left(obj, LV_PART_MAIN); + int32_t stop = lv_obj_get_style_space_top(obj, LV_PART_MAIN); + int32_t prow = lv_obj_get_style_pad_row(obj, LV_PART_MAIN); + int32_t pcol = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); - lv_coord_t max_w = lv_obj_get_content_width(obj); - lv_coord_t max_h = lv_obj_get_content_height(obj); + int32_t max_w = lv_obj_get_content_width(obj); + int32_t max_h = lv_obj_get_content_height(obj); /*Calculate the position of each row*/ - lv_coord_t max_h_no_gap = max_h - (prow * (btnm->row_cnt - 1)); + int32_t max_h_no_gap = max_h - (prow * (btnm->row_cnt - 1)); /*Count the units and the buttons in a line *(A button can be 1,2,3... unit wide)*/ @@ -124,8 +127,8 @@ void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]) /*Count the units and the buttons in a line*/ uint32_t row; for(row = 0; row < btnm->row_cnt; row++) { - uint16_t unit_cnt = 0; /*Number of units in a row*/ - uint16_t btn_cnt = 0; /*Number of buttons in a row*/ + uint32_t unit_cnt = 0; /*Number of units in a row*/ + uint32_t btn_cnt = 0; /*Number of buttons in a row*/ /*Count the buttons and units in this row*/ while(map_row[btn_cnt] && strcmp(map_row[btn_cnt], "\n") != 0 && map_row[btn_cnt][0] != '\0') { unit_cnt += get_button_width(btnm->ctrl_bits[btn_tot_i + btn_cnt]); @@ -138,11 +141,11 @@ void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]) continue; } - lv_coord_t row_y1 = ptop + (max_h_no_gap * row) / btnm->row_cnt + row * prow; - lv_coord_t row_y2 = ptop + (max_h_no_gap * (row + 1)) / btnm->row_cnt + row * prow - 1; + int32_t row_y1 = stop + (max_h_no_gap * row) / btnm->row_cnt + row * prow; + int32_t row_y2 = stop + (max_h_no_gap * (row + 1)) / btnm->row_cnt + row * prow - 1; /*Set the button size and positions*/ - lv_coord_t max_w_no_gap = max_w - (pcol * (btn_cnt - 1)); + int32_t max_w_no_gap = max_w - (pcol * (btn_cnt - 1)); if(max_w_no_gap < 0) max_w_no_gap = 0; uint32_t row_unit_cnt = 0; /*The current unit position in the row*/ @@ -150,12 +153,12 @@ void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]) for(btn = 0; btn < btn_cnt; btn++, btn_tot_i++, txt_tot_i++) { uint32_t btn_u = get_button_width(btnm->ctrl_bits[btn_tot_i]); - lv_coord_t btn_x1 = (max_w_no_gap * row_unit_cnt) / unit_cnt + btn * pcol; - lv_coord_t btn_x2 = (max_w_no_gap * (row_unit_cnt + btn_u)) / unit_cnt + btn * pcol - 1; + int32_t btn_x1 = (max_w_no_gap * row_unit_cnt) / unit_cnt + btn * pcol; + int32_t btn_x2 = (max_w_no_gap * (row_unit_cnt + btn_u)) / unit_cnt + btn * pcol - 1; /*If RTL start from the right*/ if(base_dir == LV_BASE_DIR_RTL) { - lv_coord_t tmp = btn_x1; + int32_t tmp = btn_x1; btn_x1 = btn_x2; btn_x2 = tmp; @@ -163,8 +166,8 @@ void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]) btn_x2 = max_w - btn_x2; } - btn_x1 += pleft; - btn_x2 += pleft; + btn_x1 += sleft; + btn_x2 += sleft; lv_area_set(&btnm->button_areas[btn_tot_i], btn_x1, row_y1, btn_x2, row_y2); @@ -181,122 +184,104 @@ void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]) lv_obj_invalidate(obj); } -void lv_btnmatrix_set_ctrl_map(lv_obj_t * obj, const lv_btnmatrix_ctrl_t ctrl_map[]) +void lv_buttonmatrix_set_ctrl_map(lv_obj_t * obj, const lv_buttonmatrix_ctrl_t ctrl_map[]) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; - lv_memcpy(btnm->ctrl_bits, ctrl_map, sizeof(lv_btnmatrix_ctrl_t) * btnm->btn_cnt); + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; + lv_memcpy(btnm->ctrl_bits, ctrl_map, sizeof(lv_buttonmatrix_ctrl_t) * btnm->btn_cnt); - lv_btnmatrix_set_map(obj, btnm->map_p); + lv_buttonmatrix_set_map(obj, btnm->map_p); } -void lv_btnmatrix_set_selected_btn(lv_obj_t * obj, uint16_t btn_id) +void lv_buttonmatrix_set_selected_button(lv_obj_t * obj, uint32_t btn_id) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; - if(btn_id >= btnm->btn_cnt && btn_id != LV_BTNMATRIX_BTN_NONE) return; + if(btn_id >= btnm->btn_cnt && btn_id != LV_BUTTONMATRIX_BUTTON_NONE) return; invalidate_button_area(obj, btnm->btn_id_sel); btnm->btn_id_sel = btn_id; invalidate_button_area(obj, btn_id); } -void lv_btnmatrix_set_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl) +void lv_buttonmatrix_set_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; if(btn_id >= btnm->btn_cnt) return; - if(btnm->one_check && (ctrl & LV_BTNMATRIX_CTRL_CHECKED)) { - lv_btnmatrix_clear_btn_ctrl_all(obj, LV_BTNMATRIX_CTRL_CHECKED); - } - - /* If we hide a button if all buttons are now hidden hide the whole button matrix to make focus behave correctly */ - if(ctrl & LV_BTNMATRIX_CTRL_HIDDEN) { - bool all_buttons_hidden = true; - if(btnm->btn_cnt > 1) { - for(uint16_t btn_idx = 0; btn_idx < btnm->btn_cnt; btn_idx++) { - if(btn_idx == btn_id) continue; - if(!(btnm->ctrl_bits[btn_idx] & LV_BTNMATRIX_CTRL_HIDDEN)) all_buttons_hidden = false; - } - - } - if(all_buttons_hidden) lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN); + if(btnm->one_check && (ctrl & LV_BUTTONMATRIX_CTRL_CHECKED)) { + lv_buttonmatrix_clear_button_ctrl_all(obj, LV_BUTTONMATRIX_CTRL_CHECKED); } btnm->ctrl_bits[btn_id] |= ctrl; invalidate_button_area(obj, btn_id); - if(ctrl & LV_BTNMATRIX_CTRL_POPOVER) { + if(ctrl & LV_BUTTONMATRIX_CTRL_POPOVER) { lv_obj_refresh_ext_draw_size(obj); } } -void lv_btnmatrix_clear_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl) +void lv_buttonmatrix_clear_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; if(btn_id >= btnm->btn_cnt) return; - /* If all buttons were hidden the whole button matrix is hidden so we need to check and remove hidden flag if present */ - if(ctrl & LV_BTNMATRIX_CTRL_HIDDEN) { - if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) lv_obj_clear_flag(obj, LV_OBJ_FLAG_HIDDEN); - } - btnm->ctrl_bits[btn_id] &= (~ctrl); invalidate_button_area(obj, btn_id); - if(ctrl & LV_BTNMATRIX_CTRL_POPOVER) { + if(ctrl & LV_BUTTONMATRIX_CTRL_POPOVER) { lv_obj_refresh_ext_draw_size(obj); } } -void lv_btnmatrix_set_btn_ctrl_all(lv_obj_t * obj, lv_btnmatrix_ctrl_t ctrl) +void lv_buttonmatrix_set_button_ctrl_all(lv_obj_t * obj, lv_buttonmatrix_ctrl_t ctrl) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj;; - uint16_t i; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; + uint32_t i; for(i = 0; i < btnm->btn_cnt; i++) { - lv_btnmatrix_set_btn_ctrl(obj, i, ctrl); + lv_buttonmatrix_set_button_ctrl(obj, i, ctrl); } } -void lv_btnmatrix_clear_btn_ctrl_all(lv_obj_t * obj, lv_btnmatrix_ctrl_t ctrl) +void lv_buttonmatrix_clear_button_ctrl_all(lv_obj_t * obj, lv_buttonmatrix_ctrl_t ctrl) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj;; - uint16_t i; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; + uint32_t i; for(i = 0; i < btnm->btn_cnt; i++) { - lv_btnmatrix_clear_btn_ctrl(obj, i, ctrl); + lv_buttonmatrix_clear_button_ctrl(obj, i, ctrl); } } -void lv_btnmatrix_set_btn_width(lv_obj_t * obj, uint16_t btn_id, uint8_t width) +void lv_buttonmatrix_set_button_width(lv_obj_t * obj, uint32_t btn_id, uint32_t width) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj;; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; if(btn_id >= btnm->btn_cnt) return; - btnm->ctrl_bits[btn_id] &= (~LV_BTNMATRIX_WIDTH_MASK); - btnm->ctrl_bits[btn_id] |= (LV_BTNMATRIX_WIDTH_MASK & width); + btnm->ctrl_bits[btn_id] &= (~LV_BUTTONMATRIX_WIDTH_MASK); + btnm->ctrl_bits[btn_id] |= (LV_BUTTONMATRIX_WIDTH_MASK & width); - lv_btnmatrix_set_map(obj, btnm->map_p); + lv_buttonmatrix_set_map(obj, btnm->map_p); } -void lv_btnmatrix_set_one_checked(lv_obj_t * obj, bool en) +void lv_buttonmatrix_set_one_checked(lv_obj_t * obj, bool en) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj;; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; btnm->one_check = en; /*If more than one button is toggled only the first one should be*/ @@ -307,33 +292,33 @@ void lv_btnmatrix_set_one_checked(lv_obj_t * obj, bool en) * Getter functions *====================*/ -const char ** lv_btnmatrix_get_map(const lv_obj_t * obj) +const char ** lv_buttonmatrix_get_map(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj;; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; return btnm->map_p; } -uint16_t lv_btnmatrix_get_selected_btn(const lv_obj_t * obj) +uint32_t lv_buttonmatrix_get_selected_button(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj;; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; return btnm->btn_id_sel; } -const char * lv_btnmatrix_get_btn_text(const lv_obj_t * obj, uint16_t btn_id) +const char * lv_buttonmatrix_get_button_text(const lv_obj_t * obj, uint32_t btn_id) { LV_ASSERT_OBJ(obj, MY_CLASS); - if(btn_id == LV_BTNMATRIX_BTN_NONE) return NULL; + if(btn_id == LV_BUTTONMATRIX_BUTTON_NONE) return NULL; - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; if(btn_id > btnm->btn_cnt) return NULL; - uint16_t txt_i = 0; - uint16_t btn_i = 0; + uint32_t txt_i = 0; + uint32_t btn_i = 0; /*Search the text of btnm->btn_pr the buttons text in the map *Skip "\n"-s*/ @@ -348,21 +333,21 @@ const char * lv_btnmatrix_get_btn_text(const lv_obj_t * obj, uint16_t btn_id) return btnm->map_p[txt_i]; } -bool lv_btnmatrix_has_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl) +bool lv_buttonmatrix_has_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj;; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; if(btn_id >= btnm->btn_cnt) return false; - return ((btnm->ctrl_bits[btn_id] & ctrl) == ctrl) ? true : false; + return (btnm->ctrl_bits[btn_id] & ctrl) == ctrl; } -bool lv_btnmatrix_get_one_checked(const lv_obj_t * obj) +bool lv_buttonmatrix_get_one_checked(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj;; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; return btnm->one_check; } @@ -371,77 +356,79 @@ bool lv_btnmatrix_get_one_checked(const lv_obj_t * obj) * STATIC FUNCTIONS **********************/ -static void lv_btnmatrix_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +static void lv_buttonmatrix_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { LV_UNUSED(class_p); LV_TRACE_OBJ_CREATE("begin"); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; btnm->btn_cnt = 0; btnm->row_cnt = 0; - btnm->btn_id_sel = LV_BTNMATRIX_BTN_NONE; + btnm->btn_id_sel = LV_BUTTONMATRIX_BUTTON_NONE; btnm->button_areas = NULL; btnm->ctrl_bits = NULL; btnm->map_p = NULL; btnm->one_check = 0; - lv_btnmatrix_set_map(obj, lv_btnmatrix_def_map); +#if LV_WIDGETS_HAS_DEFAULT_VALUE + lv_buttonmatrix_set_map(obj, lv_buttonmatrix_def_map); +#endif LV_TRACE_OBJ_CREATE("finished"); } -static void lv_btnmatrix_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +static void lv_buttonmatrix_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { LV_TRACE_OBJ_CREATE("begin"); LV_UNUSED(class_p); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; - lv_mem_free(btnm->button_areas); - lv_mem_free(btnm->ctrl_bits); + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; + lv_free(btnm->button_areas); + lv_free(btnm->ctrl_bits); btnm->button_areas = NULL; btnm->ctrl_bits = NULL; LV_TRACE_OBJ_CREATE("finished"); } -static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e) +static void lv_buttonmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e) { LV_UNUSED(class_p); - lv_res_t res; + lv_result_t res; /*Call the ancestor's event handler*/ res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; + lv_obj_t * obj = lv_event_get_current_target(e); + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; lv_point_t p; if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { if(has_popovers_in_top_row(obj)) { /*reserve one row worth of extra space to account for popovers in the top row*/ - lv_coord_t s = btnm->row_cnt > 0 ? lv_obj_get_content_height(obj) / btnm->row_cnt : 0; + int32_t s = btnm->row_cnt > 0 ? lv_obj_get_content_height(obj) / btnm->row_cnt : 0; lv_event_set_ext_draw_size(e, s); } } if(code == LV_EVENT_STYLE_CHANGED) { - lv_btnmatrix_set_map(obj, btnm->map_p); + lv_buttonmatrix_set_map(obj, btnm->map_p); } else if(code == LV_EVENT_SIZE_CHANGED) { - lv_btnmatrix_set_map(obj, btnm->map_p); + lv_buttonmatrix_set_map(obj, btnm->map_p); } else if(code == LV_EVENT_PRESSED) { - void * param = lv_event_get_param(e); + lv_indev_t * indev = lv_event_get_indev(e); invalidate_button_area(obj, btnm->btn_id_sel); - lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); + lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_active()); if(indev_type == LV_INDEV_TYPE_POINTER || indev_type == LV_INDEV_TYPE_BUTTON) { - uint16_t btn_pr; + uint32_t btn_pr; /*Search the pressed area*/ - lv_indev_get_point(param, &p); + lv_indev_get_point(indev, &p); btn_pr = get_button_from_point(obj, &p); /*Handle the case where there is no button there*/ - btnm->btn_id_sel = LV_BTNMATRIX_BTN_NONE; - if(btn_pr != LV_BTNMATRIX_BTN_NONE) { + btnm->btn_id_sel = LV_BUTTONMATRIX_BUTTON_NONE; + if(btn_pr != LV_BUTTONMATRIX_BUTTON_NONE) { if(button_is_inactive(btnm->ctrl_bits[btn_pr]) == false && button_is_hidden(btnm->ctrl_bits[btn_pr]) == false) { btnm->btn_id_sel = btn_pr; @@ -449,76 +436,54 @@ static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e) } } else { - btnm->btn_id_sel = LV_BTNMATRIX_BTN_NONE; + btnm->btn_id_sel = LV_BUTTONMATRIX_BUTTON_NONE; } } - if(btnm->btn_id_sel != LV_BTNMATRIX_BTN_NONE) { + if(btnm->btn_id_sel != LV_BUTTONMATRIX_BUTTON_NONE) { if(button_is_click_trig(btnm->ctrl_bits[btnm->btn_id_sel]) == false && button_is_popover(btnm->ctrl_bits[btnm->btn_id_sel]) == false && button_is_inactive(btnm->ctrl_bits[btnm->btn_id_sel]) == false && button_is_hidden(btnm->ctrl_bits[btnm->btn_id_sel]) == false) { uint32_t b = btnm->btn_id_sel; - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &b); - if(res != LV_RES_OK) return; + res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, &b); + if(res != LV_RESULT_OK) return; } } } else if(code == LV_EVENT_PRESSING) { - void * param = lv_event_get_param(e); - uint16_t btn_pr = LV_BTNMATRIX_BTN_NONE; - /*Search the pressed area*/ - lv_indev_t * indev = lv_indev_get_act(); - lv_indev_type_t indev_type = lv_indev_get_type(indev); - if(indev_type == LV_INDEV_TYPE_ENCODER || indev_type == LV_INDEV_TYPE_KEYPAD) return; - - lv_indev_get_point(indev, &p); - btn_pr = get_button_from_point(obj, &p); - /*Invalidate to old and the new areas*/ - if(btn_pr != btnm->btn_id_sel) { - if(btnm->btn_id_sel != LV_BTNMATRIX_BTN_NONE) { - invalidate_button_area(obj, btnm->btn_id_sel); - } - - btnm->btn_id_sel = btn_pr; - - lv_indev_reset_long_press(param); /*Start the log press time again on the new button*/ - if(btn_pr != LV_BTNMATRIX_BTN_NONE && - button_is_inactive(btnm->ctrl_bits[btn_pr]) == false && - button_is_hidden(btnm->ctrl_bits[btn_pr]) == false) { - invalidate_button_area(obj, btn_pr); - /*Send VALUE_CHANGED for the newly pressed button*/ - if(button_is_click_trig(btnm->ctrl_bits[btn_pr]) == false && - button_is_popover(btnm->ctrl_bits[btnm->btn_id_sel]) == false) { - uint32_t b = btn_pr; - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &b); - if(res != LV_RES_OK) return; - } + /*If a slid to a new button, discard the current button and don't press any buttons*/ + if(btnm->btn_id_sel != LV_BUTTONMATRIX_BUTTON_NONE) { + lv_indev_t * indev = lv_event_get_indev(e); + lv_indev_get_point(indev, &p); + uint32_t btn_pr = get_button_from_point(obj, &p); + if(btn_pr != btnm->btn_id_sel) { + invalidate_button_area(obj, btnm->btn_id_sel); /*Invalidate the old area*/ + btnm->btn_id_sel = LV_BUTTONMATRIX_BUTTON_NONE; } } } else if(code == LV_EVENT_RELEASED) { - if(btnm->btn_id_sel != LV_BTNMATRIX_BTN_NONE) { + if(btnm->btn_id_sel != LV_BUTTONMATRIX_BUTTON_NONE) { /*Toggle the button if enabled*/ if(button_is_checkable(btnm->ctrl_bits[btnm->btn_id_sel]) && !button_is_inactive(btnm->ctrl_bits[btnm->btn_id_sel])) { if(button_get_checked(btnm->ctrl_bits[btnm->btn_id_sel]) && !btnm->one_check) { - btnm->ctrl_bits[btnm->btn_id_sel] &= (~LV_BTNMATRIX_CTRL_CHECKED); + btnm->ctrl_bits[btnm->btn_id_sel] &= (~LV_BUTTONMATRIX_CTRL_CHECKED); } else { - btnm->ctrl_bits[btnm->btn_id_sel] |= LV_BTNMATRIX_CTRL_CHECKED; + btnm->ctrl_bits[btnm->btn_id_sel] |= LV_BUTTONMATRIX_CTRL_CHECKED; } if(btnm->one_check) make_one_button_checked(obj, btnm->btn_id_sel); } - if((button_is_click_trig(btnm->ctrl_bits[btnm->btn_id_sel]) == true || button_is_popover(btnm->ctrl_bits[btnm->btn_id_sel]) == true) && button_is_inactive(btnm->ctrl_bits[btnm->btn_id_sel]) == false && button_is_hidden(btnm->ctrl_bits[btnm->btn_id_sel]) == false) { uint32_t b = btnm->btn_id_sel; - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &b); - if(res != LV_RES_OK) return; + res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, &b); + if(res != LV_RESULT_OK) return; } } @@ -527,24 +492,24 @@ static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e) } else if(code == LV_EVENT_LONG_PRESSED_REPEAT) { - if(btnm->btn_id_sel != LV_BTNMATRIX_BTN_NONE) { + if(btnm->btn_id_sel != LV_BUTTONMATRIX_BUTTON_NONE) { if(button_is_repeat_disabled(btnm->ctrl_bits[btnm->btn_id_sel]) == false && button_is_inactive(btnm->ctrl_bits[btnm->btn_id_sel]) == false && button_is_hidden(btnm->ctrl_bits[btnm->btn_id_sel]) == false) { uint32_t b = btnm->btn_id_sel; - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &b); - if(res != LV_RES_OK) return; + res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, &b); + if(res != LV_RESULT_OK) return; } } } else if(code == LV_EVENT_PRESS_LOST) { invalidate_button_area(obj, btnm->btn_id_sel); - btnm->btn_id_sel = LV_BTNMATRIX_BTN_NONE; + btnm->btn_id_sel = LV_BUTTONMATRIX_BUTTON_NONE; } else if(code == LV_EVENT_FOCUSED) { if(btnm->btn_cnt == 0) return; - lv_indev_t * indev = lv_event_get_param(e); + lv_indev_t * indev = lv_event_get_indev(e); lv_indev_type_t indev_type = lv_indev_get_type(indev); /*If not focused by an input device assume the last input device*/ @@ -555,82 +520,91 @@ static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e) bool editing = lv_group_get_editing(lv_obj_get_group(obj)); /*Focus the first button if there is not selected button*/ - if(btnm->btn_id_sel == LV_BTNMATRIX_BTN_NONE) { + if(btnm->btn_id_sel == LV_BUTTONMATRIX_BUTTON_NONE) { if(indev_type == LV_INDEV_TYPE_KEYPAD || (indev_type == LV_INDEV_TYPE_ENCODER && editing)) { uint32_t b = 0; if(btnm->one_check) { - while(button_is_hidden(btnm->ctrl_bits[b]) || button_is_inactive(btnm->ctrl_bits[b]) || - button_is_checked(btnm->ctrl_bits[b]) == false) b++; + while(b < btnm->btn_cnt && + (button_is_hidden(btnm->ctrl_bits[b]) || + button_is_inactive(btnm->ctrl_bits[b]) || + button_is_checked(btnm->ctrl_bits[b]) == false)) { + b++; + } } else { - while(button_is_hidden(btnm->ctrl_bits[b]) || button_is_inactive(btnm->ctrl_bits[b])) b++; + while(b < btnm->btn_cnt && + (button_is_hidden(btnm->ctrl_bits[b]) || + button_is_inactive(btnm->ctrl_bits[b]))) { + b++; + } } btnm->btn_id_sel = b; } else { - btnm->btn_id_sel = LV_BTNMATRIX_BTN_NONE; + btnm->btn_id_sel = LV_BUTTONMATRIX_BUTTON_NONE; } } } else if(code == LV_EVENT_DEFOCUSED || code == LV_EVENT_LEAVE) { - if(btnm->btn_id_sel != LV_BTNMATRIX_BTN_NONE) invalidate_button_area(obj, btnm->btn_id_sel); - btnm->btn_id_sel = LV_BTNMATRIX_BTN_NONE; + // TODO + // if(btnm->btn_id_sel != LV_BUTTONMATRIX_BUTTON_NONE) invalidate_button_area(obj, btnm->btn_id_sel); + // btnm->btn_id_sel = LV_BUTTONMATRIX_BUTTON_NONE; } else if(code == LV_EVENT_KEY) { invalidate_button_area(obj, btnm->btn_id_sel); - char c = *((char *)lv_event_get_param(e)); + uint32_t c = lv_event_get_key(e); if(c == LV_KEY_RIGHT) { - if(btnm->btn_id_sel == LV_BTNMATRIX_BTN_NONE) btnm->btn_id_sel = 0; + if(btnm->btn_id_sel == LV_BUTTONMATRIX_BUTTON_NONE) btnm->btn_id_sel = 0; else btnm->btn_id_sel++; if(btnm->btn_id_sel >= btnm->btn_cnt) btnm->btn_id_sel = 0; - uint16_t btn_id_start = btnm->btn_id_sel; + uint32_t btn_id_start = btnm->btn_id_sel; while(button_is_hidden(btnm->ctrl_bits[btnm->btn_id_sel]) || button_is_inactive(btnm->ctrl_bits[btnm->btn_id_sel])) { btnm->btn_id_sel++; if(btnm->btn_id_sel >= btnm->btn_cnt) btnm->btn_id_sel = 0; if(btnm->btn_id_sel == btn_id_start) { - btnm->btn_id_sel = LV_BTNMATRIX_BTN_NONE; + btnm->btn_id_sel = LV_BUTTONMATRIX_BUTTON_NONE; break; } } } else if(c == LV_KEY_LEFT) { - if(btnm->btn_id_sel == LV_BTNMATRIX_BTN_NONE) btnm->btn_id_sel = 0; + if(btnm->btn_id_sel == LV_BUTTONMATRIX_BUTTON_NONE) btnm->btn_id_sel = 0; if(btnm->btn_id_sel == 0) btnm->btn_id_sel = btnm->btn_cnt - 1; else if(btnm->btn_id_sel > 0) btnm->btn_id_sel--; - uint16_t btn_id_start = btnm->btn_id_sel; + uint32_t btn_id_start = btnm->btn_id_sel; while(button_is_hidden(btnm->ctrl_bits[btnm->btn_id_sel]) || button_is_inactive(btnm->ctrl_bits[btnm->btn_id_sel])) { if(btnm->btn_id_sel > 0) btnm->btn_id_sel--; else btnm->btn_id_sel = btnm->btn_cnt - 1; if(btnm->btn_id_sel == btn_id_start) { - btnm->btn_id_sel = LV_BTNMATRIX_BTN_NONE; + btnm->btn_id_sel = LV_BUTTONMATRIX_BUTTON_NONE; break; } } } else if(c == LV_KEY_DOWN) { - lv_coord_t col_gap = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); + int32_t col_gap = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); /*Find the area below the current*/ - if(btnm->btn_id_sel == LV_BTNMATRIX_BTN_NONE) { + if(btnm->btn_id_sel == LV_BUTTONMATRIX_BUTTON_NONE) { btnm->btn_id_sel = 0; while(button_is_hidden(btnm->ctrl_bits[btnm->btn_id_sel]) || button_is_inactive(btnm->ctrl_bits[btnm->btn_id_sel])) { btnm->btn_id_sel++; if(btnm->btn_id_sel >= btnm->btn_cnt) { - btnm->btn_id_sel = LV_BTNMATRIX_BTN_NONE; + btnm->btn_id_sel = LV_BUTTONMATRIX_BUTTON_NONE; break; } } } else { - uint16_t area_below; - lv_coord_t pr_center = + uint32_t area_below; + int32_t pr_center = btnm->button_areas[btnm->btn_id_sel].x1 + (lv_area_get_width(&btnm->button_areas[btnm->btn_id_sel]) >> 1); for(area_below = btnm->btn_id_sel; area_below < btnm->btn_cnt; area_below++) { @@ -647,21 +621,21 @@ static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e) } } else if(c == LV_KEY_UP) { - lv_coord_t col_gap = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); + int32_t col_gap = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); /*Find the area below the current*/ - if(btnm->btn_id_sel == LV_BTNMATRIX_BTN_NONE) { + if(btnm->btn_id_sel == LV_BUTTONMATRIX_BUTTON_NONE) { btnm->btn_id_sel = 0; while(button_is_hidden(btnm->ctrl_bits[btnm->btn_id_sel]) || button_is_inactive(btnm->ctrl_bits[btnm->btn_id_sel])) { btnm->btn_id_sel++; if(btnm->btn_id_sel >= btnm->btn_cnt) { - btnm->btn_id_sel = LV_BTNMATRIX_BTN_NONE; + btnm->btn_id_sel = LV_BUTTONMATRIX_BUTTON_NONE; break; } } } else { int16_t area_above; - lv_coord_t pr_center = + int32_t pr_center = btnm->button_areas[btnm->btn_id_sel].x1 + (lv_area_get_width(&btnm->button_areas[btnm->btn_id_sel]) >> 1); for(area_above = btnm->btn_id_sel; area_above >= 0; area_above--) { @@ -687,11 +661,11 @@ static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e) static void draw_main(lv_event_t * e) { - lv_obj_t * obj = lv_event_get_target(e); - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; + lv_obj_t * obj = lv_event_get_current_target(e); + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; if(btnm->btn_cnt == 0) return; - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); obj->skip_trans = 1; lv_area_t area_obj; @@ -699,8 +673,8 @@ static void draw_main(lv_event_t * e) lv_area_t btn_area; - uint16_t btn_i = 0; - uint16_t txt_i = 0; + uint32_t btn_i = 0; + uint32_t txt_i = 0; lv_draw_rect_dsc_t draw_rect_dsc_act; lv_draw_label_dsc_t draw_label_dsc_act; @@ -718,24 +692,15 @@ static void draw_main(lv_event_t * e) obj->skip_trans = 0; obj->state = state_ori; - lv_coord_t ptop = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t pbottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); - lv_coord_t pleft = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t pright = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + int32_t ptop = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + int32_t pbottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + int32_t pleft = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + int32_t pright = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); #if LV_USE_ARABIC_PERSIAN_CHARS - const size_t txt_ap_size = 256 ; - char * txt_ap = lv_mem_buf_get(txt_ap_size); + char txt_ap[256]; #endif - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.part = LV_PART_ITEMS; - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_BTNMATRIX_DRAW_PART_BTN; - part_draw_dsc.rect_dsc = &draw_rect_dsc_act; - part_draw_dsc.label_dsc = &draw_label_dsc_act; - for(btn_i = 0; btn_i < btnm->btn_cnt; btn_i++, txt_i++) { /*Search the next valid text in the map*/ while(strcmp(btnm->map_p[txt_i], "\n") == 0) { @@ -781,14 +746,7 @@ static void draw_main(lv_event_t * e) obj->skip_trans = 0; } - bool recolor = button_is_recolor(btnm->ctrl_bits[btn_i]); - if(recolor) draw_label_dsc_act.flag |= LV_TEXT_FLAG_RECOLOR; - else draw_label_dsc_act.flag &= ~LV_TEXT_FLAG_RECOLOR; - - - part_draw_dsc.draw_area = &btn_area; - part_draw_dsc.id = btn_i; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); + draw_rect_dsc_act.base.id1 = btn_i; /*Remove borders on the edges if `LV_BORDER_SIDE_INTERNAL`*/ if(draw_rect_dsc_act.border_side & LV_BORDER_SIDE_INTERNAL) { @@ -799,68 +757,66 @@ static void draw_main(lv_event_t * e) if(btn_area.y2 == obj->coords.y2 - pbottom) draw_rect_dsc_act.border_side &= ~LV_BORDER_SIDE_BOTTOM; } - lv_coord_t btn_height = lv_area_get_height(&btn_area); + int32_t btn_height = lv_area_get_height(&btn_area); - if((btn_state & LV_STATE_PRESSED) && (btnm->ctrl_bits[btn_i] & LV_BTNMATRIX_CTRL_POPOVER)) { + if((btn_state & LV_STATE_PRESSED) && (btnm->ctrl_bits[btn_i] & LV_BUTTONMATRIX_CTRL_POPOVER)) { /*Push up the upper boundary of the btn area to create the popover*/ btn_area.y1 -= btn_height; } /*Draw the background*/ - lv_draw_rect(draw_ctx, &draw_rect_dsc_act, &btn_area); + lv_draw_rect(layer, &draw_rect_dsc_act, &btn_area); /*Calculate the size of the text*/ const lv_font_t * font = draw_label_dsc_act.font; - lv_coord_t letter_space = draw_label_dsc_act.letter_space; - lv_coord_t line_space = draw_label_dsc_act.line_space; + int32_t letter_space = draw_label_dsc_act.letter_space; + int32_t line_space = draw_label_dsc_act.line_space; const char * txt = btnm->map_p[txt_i]; #if LV_USE_ARABIC_PERSIAN_CHARS /*Get the size of the Arabic text and process it*/ - size_t len_ap = _lv_txt_ap_calc_bytes_cnt(txt); - if(len_ap < txt_ap_size) { - _lv_txt_ap_proc(txt, txt_ap); + size_t len_ap = _lv_text_ap_calc_bytes_count(txt); + if(len_ap < sizeof(txt_ap)) { + _lv_text_ap_proc(txt, txt_ap); txt = txt_ap; } #endif lv_point_t txt_size; - lv_txt_get_size(&txt_size, txt, font, letter_space, - line_space, lv_area_get_width(&area_obj), draw_label_dsc_act.flag); + lv_text_get_size(&txt_size, txt, font, letter_space, + line_space, lv_area_get_width(&area_obj), draw_label_dsc_act.flag); btn_area.x1 += (lv_area_get_width(&btn_area) - txt_size.x) / 2; btn_area.y1 += (lv_area_get_height(&btn_area) - txt_size.y) / 2; btn_area.x2 = btn_area.x1 + txt_size.x; btn_area.y2 = btn_area.y1 + txt_size.y; - if((btn_state & LV_STATE_PRESSED) && (btnm->ctrl_bits[btn_i] & LV_BTNMATRIX_CTRL_POPOVER)) { + if((btn_state & LV_STATE_PRESSED) && (btnm->ctrl_bits[btn_i] & LV_BUTTONMATRIX_CTRL_POPOVER)) { /*Push up the button text into the popover*/ btn_area.y1 -= btn_height / 2; btn_area.y2 -= btn_height / 2; } /*Draw the text*/ - lv_draw_label(draw_ctx, &draw_label_dsc_act, &btn_area, txt, NULL); - - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); + draw_label_dsc_act.text = txt; + draw_label_dsc_act.text_local = true; + draw_label_dsc_act.base.id1 = btn_i; + lv_draw_label(layer, &draw_label_dsc_act, &btn_area); } obj->skip_trans = 0; -#if LV_USE_ARABIC_PERSIAN_CHARS - lv_mem_buf_release(txt_ap); -#endif } /** * Create the required number of buttons and control bytes according to a map * @param obj pointer to button matrix object * @param map_p pointer to a string array */ -static void allocate_btn_areas_and_controls(const lv_obj_t * obj, const char ** map) +static void allocate_button_areas_and_controls(const lv_obj_t * obj, const char ** map) { - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; btnm->row_cnt = 1; /*Count the buttons in the map*/ - uint16_t btn_cnt = 0; - uint16_t i = 0; + uint32_t btn_cnt = 0; + uint32_t i = 0; while(map[i] && map[i][0] != '\0') { if(strcmp(map[i], "\n") != 0) { /*Do not count line breaks*/ btn_cnt++; @@ -875,21 +831,21 @@ static void allocate_btn_areas_and_controls(const lv_obj_t * obj, const char ** if(btn_cnt == btnm->btn_cnt) return; if(btnm->button_areas != NULL) { - lv_mem_free(btnm->button_areas); + lv_free(btnm->button_areas); btnm->button_areas = NULL; } if(btnm->ctrl_bits != NULL) { - lv_mem_free(btnm->ctrl_bits); + lv_free(btnm->ctrl_bits); btnm->ctrl_bits = NULL; } - btnm->button_areas = lv_mem_alloc(sizeof(lv_area_t) * btn_cnt); + btnm->button_areas = lv_malloc(sizeof(lv_area_t) * btn_cnt); LV_ASSERT_MALLOC(btnm->button_areas); - btnm->ctrl_bits = lv_mem_alloc(sizeof(lv_btnmatrix_ctrl_t) * btn_cnt); + btnm->ctrl_bits = lv_malloc(sizeof(lv_buttonmatrix_ctrl_t) * btn_cnt); LV_ASSERT_MALLOC(btnm->ctrl_bits); if(btnm->button_areas == NULL || btnm->ctrl_bits == NULL) btn_cnt = 0; - lv_memset_00(btnm->ctrl_bits, sizeof(lv_btnmatrix_ctrl_t) * btn_cnt); + lv_memzero(btnm->ctrl_bits, sizeof(lv_buttonmatrix_ctrl_t) * btn_cnt); btnm->btn_cnt = btn_cnt; } @@ -899,78 +855,74 @@ static void allocate_btn_areas_and_controls(const lv_obj_t * obj, const char ** * @param ctrl_bits least significant 3 bits used (1..7 valid values) * @return the width of the button in units */ -static uint8_t get_button_width(lv_btnmatrix_ctrl_t ctrl_bits) +static uint32_t get_button_width(lv_buttonmatrix_ctrl_t ctrl_bits) { - uint8_t w = ctrl_bits & LV_BTNMATRIX_WIDTH_MASK; + uint32_t w = ctrl_bits & LV_BUTTONMATRIX_WIDTH_MASK; return w != 0 ? w : 1; } -static bool button_is_hidden(lv_btnmatrix_ctrl_t ctrl_bits) +static bool button_is_hidden(lv_buttonmatrix_ctrl_t ctrl_bits) { - return (ctrl_bits & LV_BTNMATRIX_CTRL_HIDDEN) ? true : false; + return ctrl_bits & LV_BUTTONMATRIX_CTRL_HIDDEN; } -static bool button_is_checked(lv_btnmatrix_ctrl_t ctrl_bits) +static bool button_is_checked(lv_buttonmatrix_ctrl_t ctrl_bits) { - return (ctrl_bits & LV_BTNMATRIX_CTRL_CHECKED) ? true : false; + return ctrl_bits & LV_BUTTONMATRIX_CTRL_CHECKED; } -static bool button_is_repeat_disabled(lv_btnmatrix_ctrl_t ctrl_bits) +static bool button_is_repeat_disabled(lv_buttonmatrix_ctrl_t ctrl_bits) { - return (ctrl_bits & LV_BTNMATRIX_CTRL_NO_REPEAT) ? true : false; + return ctrl_bits & LV_BUTTONMATRIX_CTRL_NO_REPEAT; } -static bool button_is_inactive(lv_btnmatrix_ctrl_t ctrl_bits) +static bool button_is_inactive(lv_buttonmatrix_ctrl_t ctrl_bits) { - return (ctrl_bits & LV_BTNMATRIX_CTRL_DISABLED) ? true : false; + return ctrl_bits & LV_BUTTONMATRIX_CTRL_DISABLED; } -static bool button_is_click_trig(lv_btnmatrix_ctrl_t ctrl_bits) +static bool button_is_click_trig(lv_buttonmatrix_ctrl_t ctrl_bits) { - return (ctrl_bits & LV_BTNMATRIX_CTRL_CLICK_TRIG) ? true : false; + return ctrl_bits & LV_BUTTONMATRIX_CTRL_CLICK_TRIG; } -static bool button_is_popover(lv_btnmatrix_ctrl_t ctrl_bits) +static bool button_is_popover(lv_buttonmatrix_ctrl_t ctrl_bits) { - return (ctrl_bits & LV_BTNMATRIX_CTRL_POPOVER) ? true : false; + return ctrl_bits & LV_BUTTONMATRIX_CTRL_POPOVER; } -static bool button_is_checkable(lv_btnmatrix_ctrl_t ctrl_bits) +static bool button_is_checkable(lv_buttonmatrix_ctrl_t ctrl_bits) { - return (ctrl_bits & LV_BTNMATRIX_CTRL_CHECKABLE) ? true : false; + return ctrl_bits & LV_BUTTONMATRIX_CTRL_CHECKABLE; } -static bool button_get_checked(lv_btnmatrix_ctrl_t ctrl_bits) +static bool button_get_checked(lv_buttonmatrix_ctrl_t ctrl_bits) { - return (ctrl_bits & LV_BTNMATRIX_CTRL_CHECKED) ? true : false; + return ctrl_bits & LV_BUTTONMATRIX_CTRL_CHECKED; } -static bool button_is_recolor(lv_btnmatrix_ctrl_t ctrl_bits) -{ - return (ctrl_bits & LV_BTNMATRIX_CTRL_RECOLOR) ? true : false; -} /** * Gives the button id of a button under a given point * @param obj pointer to a button matrix object * @param p a point with absolute coordinates - * @return the id of the button or LV_BTNMATRIX_BTN_NONE. + * @return the id of the button or LV_BUTTONMATRIX_BUTTON_NONE. */ -static uint16_t get_button_from_point(lv_obj_t * obj, lv_point_t * p) +static uint32_t get_button_from_point(lv_obj_t * obj, lv_point_t * p) { lv_area_t obj_cords; lv_area_t btn_area; - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj;; - uint16_t i; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; + uint32_t i; lv_obj_get_coords(obj, &obj_cords); - lv_coord_t w = lv_obj_get_width(obj); - lv_coord_t h = lv_obj_get_height(obj); - lv_coord_t pleft = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t pright = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t ptop = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t pbottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); - lv_coord_t prow = lv_obj_get_style_pad_row(obj, LV_PART_MAIN); - lv_coord_t pcol = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); + int32_t w = lv_obj_get_width(obj); + int32_t h = lv_obj_get_height(obj); + int32_t pleft = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + int32_t pright = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + int32_t ptop = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + int32_t pbottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + int32_t prow = lv_obj_get_style_pad_row(obj, LV_PART_MAIN); + int32_t pcol = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); /*Get the half gap. Button look larger with this value. (+1 for rounding error)*/ prow = (prow / 2) + 1 + (prow & 1); @@ -1003,19 +955,19 @@ static uint16_t get_button_from_point(lv_obj_t * obj, lv_point_t * p) } } - if(i == btnm->btn_cnt) i = LV_BTNMATRIX_BTN_NONE; + if(i == btnm->btn_cnt) i = LV_BUTTONMATRIX_BUTTON_NONE; return i; } -static void invalidate_button_area(const lv_obj_t * obj, uint16_t btn_idx) +static void invalidate_button_area(const lv_obj_t * obj, uint32_t btn_idx) { - if(btn_idx == LV_BTNMATRIX_BTN_NONE) return; + if(btn_idx == LV_BUTTONMATRIX_BUTTON_NONE) return; lv_area_t btn_area; lv_area_t obj_area; - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj;; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; if(btn_idx >= btnm->btn_cnt) return; lv_area_copy(&btn_area, &btnm->button_areas[btn_idx]); @@ -1023,11 +975,11 @@ static void invalidate_button_area(const lv_obj_t * obj, uint16_t btn_idx) /*The buttons might have outline and shadow so make the invalidation larger with the gaps between the buttons. *It assumes that the outline or shadow is smaller than the gaps*/ - lv_coord_t row_gap = lv_obj_get_style_pad_row(obj, LV_PART_MAIN); - lv_coord_t col_gap = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); + int32_t row_gap = lv_obj_get_style_pad_row(obj, LV_PART_MAIN); + int32_t col_gap = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); /*Be sure to have a minimal extra space if row/col_gap is small*/ - lv_coord_t dpi = lv_disp_get_dpi(lv_obj_get_disp(obj)); + int32_t dpi = lv_display_get_dpi(lv_obj_get_display(obj)); row_gap = LV_MAX(row_gap, dpi / 10); col_gap = LV_MAX(col_gap, dpi / 10); @@ -1037,7 +989,7 @@ static void invalidate_button_area(const lv_obj_t * obj, uint16_t btn_idx) btn_area.x2 += obj_area.x1 + row_gap; btn_area.y2 += obj_area.y1 + col_gap; - if((btn_idx == btnm->btn_id_sel) && (btnm->ctrl_bits[btn_idx] & LV_BTNMATRIX_CTRL_POPOVER)) { + if((btn_idx == btnm->btn_id_sel) && (btnm->ctrl_bits[btn_idx] & LV_BUTTONMATRIX_CTRL_POPOVER)) { /*Push up the upper boundary of the btn area to also invalidate the popover*/ btn_area.y1 -= lv_area_get_height(&btn_area); } @@ -1051,31 +1003,31 @@ static void invalidate_button_area(const lv_obj_t * obj, uint16_t btn_idx) * @param obj Button matrix object * @param btn_idx Button that should remain toggled */ -static void make_one_button_checked(lv_obj_t * obj, uint16_t btn_idx) +static void make_one_button_checked(lv_obj_t * obj, uint32_t btn_idx) { /*Save whether the button was toggled*/ - bool was_toggled = lv_btnmatrix_has_btn_ctrl(obj, btn_idx, LV_BTNMATRIX_CTRL_CHECKED); + bool was_toggled = lv_buttonmatrix_has_button_ctrl(obj, btn_idx, LV_BUTTONMATRIX_CTRL_CHECKED); - lv_btnmatrix_clear_btn_ctrl_all(obj, LV_BTNMATRIX_CTRL_CHECKED); + lv_buttonmatrix_clear_button_ctrl_all(obj, LV_BUTTONMATRIX_CTRL_CHECKED); - if(was_toggled) lv_btnmatrix_set_btn_ctrl(obj, btn_idx, LV_BTNMATRIX_CTRL_CHECKED); + if(was_toggled) lv_buttonmatrix_set_button_ctrl(obj, btn_idx, LV_BUTTONMATRIX_CTRL_CHECKED); } /** - * Check if any of the buttons in the first row has the LV_BTNMATRIX_CTRL_POPOVER control flag set. + * Check if any of the buttons in the first row has the LV_BUTTONMATRIX_CTRL_POPOVER control flag set. * @param obj Button matrix object * @return true if at least one button has the flag, false otherwise */ static bool has_popovers_in_top_row(lv_obj_t * obj) { - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; if(btnm->row_cnt <= 0) { return false; } const char ** map_row = btnm->map_p; - uint16_t btn_cnt = 0; + uint32_t btn_cnt = 0; while(map_row[btn_cnt] && strcmp(map_row[btn_cnt], "\n") != 0 && map_row[btn_cnt][0] != '\0') { if(button_is_popover(btnm->ctrl_bits[btn_cnt])) { diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.h b/lib/libesp32_lvgl/lvgl/src/widgets/buttonmatrix/lv_buttonmatrix.h similarity index 50% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.h rename to lib/libesp32_lvgl/lvgl/src/widgets/buttonmatrix/lv_buttonmatrix.h index 2edf202cc..64c0d1b55 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_btnmatrix.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/buttonmatrix/lv_buttonmatrix.h @@ -3,8 +3,8 @@ * */ -#ifndef LV_BTNMATRIX_H -#define LV_BTNMATRIX_H +#ifndef LV_BUTTONMATRIX_H +#define LV_BUTTONMATRIX_H #ifdef __cplusplus extern "C" { @@ -13,17 +13,17 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../lv_conf_internal.h" +#include "../../lv_conf_internal.h" -#if LV_USE_BTNMATRIX != 0 +#if LV_USE_BUTTONMATRIX != 0 -#include "../core/lv_obj.h" +#include "../../core/lv_obj.h" /********************* * DEFINES *********************/ -#define LV_BTNMATRIX_BTN_NONE 0xFFFF -LV_EXPORT_CONST_INT(LV_BTNMATRIX_BTN_NONE); +#define LV_BUTTONMATRIX_BUTTON_NONE 0xFFFF +LV_EXPORT_CONST_INT(LV_BUTTONMATRIX_BUTTON_NONE); /********************** * TYPEDEFS @@ -31,48 +31,44 @@ LV_EXPORT_CONST_INT(LV_BTNMATRIX_BTN_NONE); /** Type to store button control bits (disabled, hidden etc.) * The first 3 bits are used to store the width*/ -enum { - _LV_BTNMATRIX_WIDTH = 0x000F, /**< Reserved to store the size units*/ - LV_BTNMATRIX_CTRL_HIDDEN = 0x0010, /**< Button hidden*/ - LV_BTNMATRIX_CTRL_NO_REPEAT = 0x0020, /**< Do not repeat press this button.*/ - LV_BTNMATRIX_CTRL_DISABLED = 0x0040, /**< Disable this button.*/ - LV_BTNMATRIX_CTRL_CHECKABLE = 0x0080, /**< The button can be toggled.*/ - LV_BTNMATRIX_CTRL_CHECKED = 0x0100, /**< Button is currently toggled (e.g. checked).*/ - LV_BTNMATRIX_CTRL_CLICK_TRIG = 0x0200, /**< 1: Send LV_EVENT_VALUE_CHANGE on CLICK, 0: Send LV_EVENT_VALUE_CHANGE on PRESS*/ - LV_BTNMATRIX_CTRL_POPOVER = 0x0400, /**< Show a popover when pressing this key*/ - LV_BTNMATRIX_CTRL_RECOLOR = 0x0800, /**< Enable text recoloring with `#color`*/ - _LV_BTNMATRIX_CTRL_RESERVED_1 = 0x1000, /**< Reserved for later use*/ - _LV_BTNMATRIX_CTRL_RESERVED_2 = 0x2000, /**< Reserved for later use*/ - LV_BTNMATRIX_CTRL_CUSTOM_1 = 0x4000, /**< Custom free to use flag*/ - LV_BTNMATRIX_CTRL_CUSTOM_2 = 0x8000, /**< Custom free to use flag*/ +enum _lv_buttonmatrix_ctrl_t { + _LV_BUTTONMATRIX_WIDTH = 0x000F, /**< Reserved to store the size units*/ + LV_BUTTONMATRIX_CTRL_HIDDEN = 0x0010, /**< Button hidden*/ + LV_BUTTONMATRIX_CTRL_NO_REPEAT = 0x0020, /**< Do not repeat press this button.*/ + LV_BUTTONMATRIX_CTRL_DISABLED = 0x0040, /**< Disable this button.*/ + LV_BUTTONMATRIX_CTRL_CHECKABLE = 0x0080, /**< The button can be toggled.*/ + LV_BUTTONMATRIX_CTRL_CHECKED = 0x0100, /**< Button is currently toggled (e.g. checked).*/ + LV_BUTTONMATRIX_CTRL_CLICK_TRIG = 0x0200, /**< 1: Send LV_EVENT_VALUE_CHANGE on CLICK, 0: Send LV_EVENT_VALUE_CHANGE on PRESS*/ + LV_BUTTONMATRIX_CTRL_POPOVER = 0x0400, /**< Show a popover when pressing this key*/ + _LV_BUTTONMATRIX_CTRL_RESERVED_1 = 0x0800, /**< Reserved for later use*/ + _LV_BUTTONMATRIX_CTRL_RESERVED_2 = 0x1000, /**< Reserved for later use*/ + _LV_BUTTONMATRIX_CTRL_RESERVED_3 = 0x2000, /**< Reserved for later use*/ + LV_BUTTONMATRIX_CTRL_CUSTOM_1 = 0x4000, /**< Custom free to use flag*/ + LV_BUTTONMATRIX_CTRL_CUSTOM_2 = 0x8000, /**< Custom free to use flag*/ }; -typedef uint16_t lv_btnmatrix_ctrl_t; +#ifdef DOXYGEN +typedef _lv_buttonmatrix_ctrl_t lv_buttonmatrix_ctrl_t; +#else +typedef uint32_t lv_buttonmatrix_ctrl_t; +#endif /*DOXYGEN*/ -typedef bool (*lv_btnmatrix_btn_draw_cb_t)(lv_obj_t * btnm, uint32_t btn_id, const lv_area_t * draw_area, - const lv_area_t * clip_area); +typedef bool (*lv_buttonmatrix_button_draw_cb_t)(lv_obj_t * btnm, uint32_t btn_id, const lv_area_t * draw_area, + const lv_area_t * clip_area); /*Data of button matrix*/ typedef struct { lv_obj_t obj; const char ** map_p; /*Pointer to the current map*/ lv_area_t * button_areas; /*Array of areas of buttons*/ - lv_btnmatrix_ctrl_t * ctrl_bits; /*Array of control bytes*/ - uint16_t btn_cnt; /*Number of button in 'map_p'(Handled by the library)*/ - uint16_t row_cnt; /*Number of rows in 'map_p'(Handled by the library)*/ - uint16_t btn_id_sel; /*Index of the active button (being pressed/released etc) or LV_BTNMATRIX_BTN_NONE*/ - uint8_t one_check : 1; /*Single button toggled at once*/ -} lv_btnmatrix_t; + lv_buttonmatrix_ctrl_t * ctrl_bits; /*Array of control bytes*/ + uint32_t btn_cnt; /*Number of button in 'map_p'(Handled by the library)*/ + uint32_t row_cnt; /*Number of rows in 'map_p'(Handled by the library)*/ + uint32_t btn_id_sel; /*Index of the active button (being pressed/released etc) or LV_BUTTONMATRIX_BUTTON_NONE*/ + uint32_t one_check : 1; /*Single button toggled at once*/ +} lv_buttonmatrix_t; -extern const lv_obj_class_t lv_btnmatrix_class; - -/** - * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_btnmatrix_class` - * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` - */ -typedef enum { - LV_BTNMATRIX_DRAW_PART_BTN, /**< The rectangle and label of buttons*/ -} lv_btnmatrix_draw_part_type_t; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_buttonmatrix_class; /********************** * GLOBAL PROTOTYPES @@ -83,7 +79,7 @@ typedef enum { * @param parent pointer to an object, it will be the parent of the new button matrix * @return pointer to the created button matrix */ -lv_obj_t * lv_btnmatrix_create(lv_obj_t * parent); +lv_obj_t * lv_buttonmatrix_create(lv_obj_t * parent); /*===================== * Setter functions @@ -96,79 +92,79 @@ lv_obj_t * lv_btnmatrix_create(lv_obj_t * parent); * @param obj pointer to a button matrix object * @param map pointer a string array. The last string has to be: "". Use "\n" to make a line break. */ -void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]); +void lv_buttonmatrix_set_map(lv_obj_t * obj, const char * map[]); /** * Set the button control map (hidden, disabled etc.) for a button matrix. * The control map array will be copied and so may be deallocated after this * function returns. * @param obj pointer to a button matrix object - * @param ctrl_map pointer to an array of `lv_btn_ctrl_t` control bytes. The + * @param ctrl_map pointer to an array of `lv_button_ctrl_t` control bytes. The * length of the array and position of the elements must match * the number and order of the individual buttons (i.e. excludes * newline entries). * An element of the map should look like e.g.: - * `ctrl_map[0] = width | LV_BTNMATRIX_CTRL_NO_REPEAT | LV_BTNMATRIX_CTRL_TGL_ENABLE` + * `ctrl_map[0] = width | LV_BUTTONMATRIX_CTRL_NO_REPEAT | LV_BUTTONMATRIX_CTRL_TGL_ENABLE` */ -void lv_btnmatrix_set_ctrl_map(lv_obj_t * obj, const lv_btnmatrix_ctrl_t ctrl_map[]); +void lv_buttonmatrix_set_ctrl_map(lv_obj_t * obj, const lv_buttonmatrix_ctrl_t ctrl_map[]); /** * Set the selected buttons * @param obj pointer to button matrix object - * @param btn_id 0 based index of the button to modify. (Not counting new lines) + * @param btn_id 0 based index of the button to modify. (Not counting new lines) */ -void lv_btnmatrix_set_selected_btn(lv_obj_t * obj, uint16_t btn_id); +void lv_buttonmatrix_set_selected_button(lv_obj_t * obj, uint32_t btn_id); /** * Set the attributes of a button of the button matrix * @param obj pointer to button matrix object * @param btn_id 0 based index of the button to modify. (Not counting new lines) - * @param ctrl OR-ed attributs. E.g. `LV_BTNMATRIX_CTRL_NO_REPEAT | LV_BTNMATRIX_CTRL_CHECKABLE` + * @param ctrl OR-ed attributes. E.g. `LV_BUTTONMATRIX_CTRL_NO_REPEAT | LV_BUTTONMATRIX_CTRL_CHECKABLE` */ -void lv_btnmatrix_set_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl); +void lv_buttonmatrix_set_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl); /** * Clear the attributes of a button of the button matrix * @param obj pointer to button matrix object * @param btn_id 0 based index of the button to modify. (Not counting new lines) - * @param ctrl OR-ed attributs. E.g. `LV_BTNMATRIX_CTRL_NO_REPEAT | LV_BTNMATRIX_CTRL_CHECKABLE` + * @param ctrl OR-ed attributes. E.g. `LV_BUTTONMATRIX_CTRL_NO_REPEAT | LV_BUTTONMATRIX_CTRL_CHECKABLE` */ -void lv_btnmatrix_clear_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl); +void lv_buttonmatrix_clear_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl); /** * Set attributes of all buttons of a button matrix * @param obj pointer to a button matrix object - * @param ctrl attribute(s) to set from `lv_btnmatrix_ctrl_t`. Values can be ORed. + * @param ctrl attribute(s) to set from `lv_buttonmatrix_ctrl_t`. Values can be ORed. */ -void lv_btnmatrix_set_btn_ctrl_all(lv_obj_t * obj, lv_btnmatrix_ctrl_t ctrl); +void lv_buttonmatrix_set_button_ctrl_all(lv_obj_t * obj, lv_buttonmatrix_ctrl_t ctrl); /** * Clear the attributes of all buttons of a button matrix * @param obj pointer to a button matrix object - * @param ctrl attribute(s) to set from `lv_btnmatrix_ctrl_t`. Values can be ORed. + * @param ctrl attribute(s) to set from `lv_buttonmatrix_ctrl_t`. Values can be ORed. * @param en true: set the attributes; false: clear the attributes */ -void lv_btnmatrix_clear_btn_ctrl_all(lv_obj_t * obj, lv_btnmatrix_ctrl_t ctrl); +void lv_buttonmatrix_clear_button_ctrl_all(lv_obj_t * obj, lv_buttonmatrix_ctrl_t ctrl); /** * Set a single button's relative width. * This method will cause the matrix be regenerated and is a relatively * expensive operation. It is recommended that initial width be specified using - * `lv_btnmatrix_set_ctrl_map` and this method only be used for dynamic changes. + * `lv_buttonmatrix_set_ctrl_map` and this method only be used for dynamic changes. * @param obj pointer to button matrix object * @param btn_id 0 based index of the button to modify. - * @param width relative width compared to the buttons in the same row. [1..7] + * @param width relative width compared to the buttons in the same row. [1..15] */ -void lv_btnmatrix_set_btn_width(lv_obj_t * obj, uint16_t btn_id, uint8_t width); +void lv_buttonmatrix_set_button_width(lv_obj_t * obj, uint32_t btn_id, uint32_t width); /** * Make the button matrix like a selector widget (only one button may be checked at a time). - * `LV_BTNMATRIX_CTRL_CHECKABLE` must be enabled on the buttons to be selected using - * `lv_btnmatrix_set_ctrl()` or `lv_btnmatrix_set_btn_ctrl_all()`. + * `LV_BUTTONMATRIX_CTRL_CHECKABLE` must be enabled on the buttons to be selected using + * `lv_buttonmatrix_set_ctrl()` or `lv_buttonmatrix_set_button_ctrl_all()`. * @param obj pointer to a button matrix object * @param en whether "one check" mode is enabled */ -void lv_btnmatrix_set_one_checked(lv_obj_t * obj, bool en); +void lv_buttonmatrix_set_one_checked(lv_obj_t * obj, bool en); /*===================== * Getter functions @@ -179,15 +175,15 @@ void lv_btnmatrix_set_one_checked(lv_obj_t * obj, bool en); * @param obj pointer to a button matrix object * @return the current map */ -const char ** lv_btnmatrix_get_map(const lv_obj_t * obj); +const char ** lv_buttonmatrix_get_map(const lv_obj_t * obj); /** * Get the index of the lastly "activated" button by the user (pressed, released, focused etc) * Useful in the `event_cb` to get the text of the button, check if hidden etc. * @param obj pointer to button matrix object - * @return index of the last released button (LV_BTNMATRIX_BTN_NONE: if unset) + * @return index of the last released button (LV_BUTTONMATRIX_BUTTON_NONE: if unset) */ -uint16_t lv_btnmatrix_get_selected_btn(const lv_obj_t * obj); +uint32_t lv_buttonmatrix_get_selected_button(const lv_obj_t * obj); /** * Get the button's text @@ -195,7 +191,7 @@ uint16_t lv_btnmatrix_get_selected_btn(const lv_obj_t * obj); * @param btn_id the index a button not counting new line characters. * @return text of btn_index` button */ -const char * lv_btnmatrix_get_btn_text(const lv_obj_t * obj, uint16_t btn_id); +const char * lv_buttonmatrix_get_button_text(const lv_obj_t * obj, uint32_t btn_id); /** * Get the whether a control value is enabled or disabled for button of a button matrix @@ -204,23 +200,23 @@ const char * lv_btnmatrix_get_btn_text(const lv_obj_t * obj, uint16_t btn_id); * @param ctrl control values to check (ORed value can be used) * @return true: the control attribute is enabled false: disabled */ -bool lv_btnmatrix_has_btn_ctrl(lv_obj_t * obj, uint16_t btn_id, lv_btnmatrix_ctrl_t ctrl); +bool lv_buttonmatrix_has_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl); /** * Tell whether "one check" mode is enabled or not. * @param obj Button matrix object * @return true: "one check" mode is enabled; false: disabled */ -bool lv_btnmatrix_get_one_checked(const lv_obj_t * obj); +bool lv_buttonmatrix_get_one_checked(const lv_obj_t * obj); /********************** * MACROS **********************/ -#endif /*LV_USE_BTNMATRIX*/ +#endif /*LV_USE_BUTTONMATRIX*/ #ifdef __cplusplus } /*extern "C"*/ #endif -#endif /*LV_BTNMATRIX_H*/ +#endif /*LV_BUTTONMATRIX_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.c b/lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar.c similarity index 68% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.c rename to lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar.c index b806d2529..ddaa6929f 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar.c @@ -10,13 +10,13 @@ #include "../../../lvgl.h" #if LV_USE_CALENDAR -#include "../../../misc/lv_assert.h" +#include "../../misc/lv_assert.h" /********************* * DEFINES *********************/ -#define LV_CALENDAR_CTRL_TODAY LV_BTNMATRIX_CTRL_CUSTOM_1 -#define LV_CALENDAR_CTRL_HIGHLIGHT LV_BTNMATRIX_CTRL_CUSTOM_2 +#define LV_CALENDAR_CTRL_TODAY LV_BUTTONMATRIX_CTRL_CUSTOM_1 +#define LV_CALENDAR_CTRL_HIGHLIGHT LV_BUTTONMATRIX_CTRL_CUSTOM_2 #define MY_CLASS &lv_calendar_class @@ -28,7 +28,7 @@ * STATIC PROTOTYPES **********************/ static void lv_calendar_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void draw_part_begin_event_cb(lv_event_t * e); +static void draw_task_added_event_cb(lv_event_t * e); static uint8_t get_day_of_week(uint32_t year, uint32_t month, uint32_t day); static uint8_t get_month_length(int32_t year, int32_t month); @@ -38,13 +38,15 @@ static void highlight_update(lv_obj_t * calendar); /********************** * STATIC VARIABLES **********************/ + const lv_obj_class_t lv_calendar_class = { .constructor_cb = lv_calendar_constructor, .width_def = (LV_DPI_DEF * 3) / 2, .height_def = (LV_DPI_DEF * 3) / 2, .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, .instance_size = sizeof(lv_calendar_t), - .base_class = &lv_obj_class + .base_class = &lv_obj_class, + .name = "calendar", }; static const char * day_names_def[7] = LV_CALENDAR_DEFAULT_DAY_NAMES; @@ -93,7 +95,7 @@ void lv_calendar_set_today_date(lv_obj_t * obj, uint32_t year, uint32_t month, u highlight_update(obj); } -void lv_calendar_set_highlighted_dates(lv_obj_t * obj, lv_calendar_date_t highlighted[], uint16_t date_num) +void lv_calendar_set_highlighted_dates(lv_obj_t * obj, lv_calendar_date_t highlighted[], size_t date_num) { LV_ASSERT_NULL(highlighted); @@ -123,9 +125,9 @@ void lv_calendar_set_showed_date(lv_obj_t * obj, uint32_t year, uint32_t month) uint32_t i; /*Remove the disabled state but revert it for day names*/ - lv_btnmatrix_clear_btn_ctrl_all(calendar->btnm, LV_BTNMATRIX_CTRL_DISABLED); + lv_buttonmatrix_clear_button_ctrl_all(calendar->btnm, LV_BUTTONMATRIX_CTRL_DISABLED); for(i = 0; i < 7; i++) { - lv_btnmatrix_set_btn_ctrl(calendar->btnm, i, LV_BTNMATRIX_CTRL_DISABLED); + lv_buttonmatrix_set_button_ctrl(calendar->btnm, i, LV_BUTTONMATRIX_CTRL_DISABLED); } uint8_t act_mo_len = get_month_length(d.year, d.month); @@ -138,30 +140,30 @@ void lv_calendar_set_showed_date(lv_obj_t * obj, uint32_t year, uint32_t month) uint8_t prev_mo_len = get_month_length(d.year, d.month - 1); for(i = 0, c = prev_mo_len - day_first + 1; i < day_first; i++, c++) { lv_snprintf(calendar->nums[i], sizeof(calendar->nums[0]), "%d", c); - lv_btnmatrix_set_btn_ctrl(calendar->btnm, i + 7, LV_BTNMATRIX_CTRL_DISABLED); + lv_buttonmatrix_set_button_ctrl(calendar->btnm, i + 7, LV_BUTTONMATRIX_CTRL_DISABLED); } for(i = day_first + act_mo_len, c = 1; i < 6 * 7; i++, c++) { lv_snprintf(calendar->nums[i], sizeof(calendar->nums[0]), "%d", c); - lv_btnmatrix_set_btn_ctrl(calendar->btnm, i + 7, LV_BTNMATRIX_CTRL_DISABLED); + lv_buttonmatrix_set_button_ctrl(calendar->btnm, i + 7, LV_BUTTONMATRIX_CTRL_DISABLED); } highlight_update(obj); /*Reset the focused button if the days changes*/ - if(lv_btnmatrix_get_selected_btn(calendar->btnm) != LV_BTNMATRIX_BTN_NONE) { - lv_btnmatrix_set_selected_btn(calendar->btnm, day_first + 7); + if(lv_buttonmatrix_get_selected_button(calendar->btnm) != LV_BUTTONMATRIX_BUTTON_NONE) { + lv_buttonmatrix_set_selected_button(calendar->btnm, day_first + 7); } lv_obj_invalidate(obj); /* The children of the calendar are probably headers. * Notify them to let the headers updated to the new date*/ - uint32_t child_cnt = lv_obj_get_child_cnt(obj); + uint32_t child_cnt = lv_obj_get_child_count(obj); for(i = 0; i < child_cnt; i++) { lv_obj_t * child = lv_obj_get_child(obj, i); if(child == calendar->btnm) continue; - lv_event_send(child, LV_EVENT_VALUE_CHANGED, obj); + lv_obj_send_event(child, LV_EVENT_VALUE_CHANGED, obj); } } @@ -200,7 +202,7 @@ lv_calendar_date_t * lv_calendar_get_highlighted_dates(const lv_obj_t * obj) return calendar->highlighted_dates; } -uint16_t lv_calendar_get_highlighted_dates_num(const lv_obj_t * obj) +size_t lv_calendar_get_highlighted_dates_num(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_calendar_t * calendar = (lv_calendar_t *)obj; @@ -208,20 +210,20 @@ uint16_t lv_calendar_get_highlighted_dates_num(const lv_obj_t * obj) return calendar->highlighted_dates_num; } -lv_res_t lv_calendar_get_pressed_date(const lv_obj_t * obj, lv_calendar_date_t * date) +lv_result_t lv_calendar_get_pressed_date(const lv_obj_t * obj, lv_calendar_date_t * date) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_calendar_t * calendar = (lv_calendar_t *)obj; - uint16_t d = lv_btnmatrix_get_selected_btn(calendar->btnm); - if(d == LV_BTNMATRIX_BTN_NONE) { + uint32_t d = lv_buttonmatrix_get_selected_button(calendar->btnm); + if(d == LV_BUTTONMATRIX_BUTTON_NONE) { date->year = 0; date->month = 0; date->day = 0; - return LV_RES_INV; + return LV_RESULT_INVALID; } - const char * txt = lv_btnmatrix_get_btn_text(calendar->btnm, lv_btnmatrix_get_selected_btn(calendar->btnm)); + const char * txt = lv_buttonmatrix_get_button_text(calendar->btnm, lv_buttonmatrix_get_selected_button(calendar->btnm)); if(txt[1] == 0) date->day = txt[0] - '0'; else date->day = (txt[0] - '0') * 10 + (txt[1] - '0'); @@ -229,10 +231,9 @@ lv_res_t lv_calendar_get_pressed_date(const lv_obj_t * obj, lv_calendar_date_t * date->year = calendar->showed_date.year; date->month = calendar->showed_date.month; - return LV_RES_OK; + return LV_RESULT_OK; } - /********************** * STATIC FUNCTIONS **********************/ @@ -243,6 +244,8 @@ static void lv_calendar_constructor(const lv_obj_class_t * class_p, lv_obj_t * o lv_calendar_t * calendar = (lv_calendar_t *)obj; /*Initialize the allocated 'ext'*/ + +#if LV_WIDGETS_HAS_DEFAULT_VALUE calendar->today.year = 2020; calendar->today.month = 1; calendar->today.day = 1; @@ -250,11 +253,12 @@ static void lv_calendar_constructor(const lv_obj_class_t * class_p, lv_obj_t * o calendar->showed_date.year = 2020; calendar->showed_date.month = 1; calendar->showed_date.day = 1; +#endif calendar->highlighted_dates = NULL; calendar->highlighted_dates_num = 0; - lv_memset_00(calendar->nums, sizeof(calendar->nums)); + lv_memzero(calendar->nums, sizeof(calendar->nums)); uint8_t i; uint8_t j = 0; for(i = 0; i < 8 * 7; i++) { @@ -273,51 +277,67 @@ static void lv_calendar_constructor(const lv_obj_class_t * class_p, lv_obj_t * o } calendar->map[8 * 7 - 1] = ""; - calendar->btnm = lv_btnmatrix_create(obj); - lv_btnmatrix_set_map(calendar->btnm, calendar->map); - lv_btnmatrix_set_btn_ctrl_all(calendar->btnm, LV_BTNMATRIX_CTRL_CLICK_TRIG | LV_BTNMATRIX_CTRL_NO_REPEAT); - lv_obj_add_event_cb(calendar->btnm, draw_part_begin_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL); + calendar->btnm = lv_buttonmatrix_create(obj); + lv_buttonmatrix_set_map(calendar->btnm, calendar->map); + lv_buttonmatrix_set_button_ctrl_all(calendar->btnm, LV_BUTTONMATRIX_CTRL_CLICK_TRIG | LV_BUTTONMATRIX_CTRL_NO_REPEAT); + lv_obj_add_event_cb(calendar->btnm, draw_task_added_event_cb, LV_EVENT_DRAW_TASK_ADDED, NULL); lv_obj_set_width(calendar->btnm, lv_pct(100)); + lv_obj_add_flag(calendar->btnm, LV_OBJ_FLAG_EVENT_BUBBLE | LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS); lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_grow(calendar->btnm, 1); +#if LV_WIDGETS_HAS_DEFAULT_VALUE lv_calendar_set_showed_date(obj, calendar->showed_date.year, calendar->showed_date.month); lv_calendar_set_today_date(obj, calendar->today.year, calendar->today.month, calendar->today.day); +#endif - lv_obj_add_flag(calendar->btnm, LV_OBJ_FLAG_EVENT_BUBBLE); } -static void draw_part_begin_event_cb(lv_event_t * e) +static void draw_task_added_event_cb(lv_event_t * e) { - lv_obj_t * obj = lv_event_get_target(e); - lv_obj_draw_part_dsc_t * dsc = lv_event_get_param(e); - if(dsc->part == LV_PART_ITEMS) { - /*Day name styles*/ - if(dsc->id < 7) { - dsc->rect_dsc->bg_opa = LV_OPA_TRANSP; - dsc->rect_dsc->border_opa = LV_OPA_TRANSP; - } - else if(lv_btnmatrix_has_btn_ctrl(obj, dsc->id, LV_BTNMATRIX_CTRL_DISABLED)) { - dsc->rect_dsc->bg_opa = LV_OPA_TRANSP; - dsc->rect_dsc->border_opa = LV_OPA_TRANSP; - dsc->label_dsc->color = lv_palette_main(LV_PALETTE_GREY); - } + lv_obj_t * obj = lv_event_get_current_target(e); + lv_draw_task_t * draw_task = lv_event_get_param(e); + if(((lv_draw_dsc_base_t *)draw_task->draw_dsc)->part != LV_PART_ITEMS) return; - if(lv_btnmatrix_has_btn_ctrl(obj, dsc->id, LV_CALENDAR_CTRL_HIGHLIGHT)) { - dsc->rect_dsc->bg_opa = LV_OPA_40; - dsc->rect_dsc->bg_color = lv_theme_get_color_primary(obj); - if(lv_btnmatrix_get_selected_btn(obj) == dsc->id) { - dsc->rect_dsc->bg_opa = LV_OPA_70; - } - } + lv_draw_fill_dsc_t * fill_draw_dsc = NULL; + lv_draw_border_dsc_t * border_draw_dsc = NULL; - if(lv_btnmatrix_has_btn_ctrl(obj, dsc->id, LV_CALENDAR_CTRL_TODAY)) { - dsc->rect_dsc->border_opa = LV_OPA_COVER; - dsc->rect_dsc->border_color = lv_theme_get_color_primary(obj); - dsc->rect_dsc->border_width += 1; - } + if(draw_task->type == LV_DRAW_TASK_TYPE_FILL) { + fill_draw_dsc = draw_task->draw_dsc; + } + else if(draw_task->type == LV_DRAW_TASK_TYPE_BORDER) { + border_draw_dsc = draw_task->draw_dsc; + } + else { + return; + } + int32_t id = ((lv_draw_dsc_base_t *)draw_task->draw_dsc)->id1; + + /*Day name styles*/ + if(id < 7) { + if(fill_draw_dsc) fill_draw_dsc->opa = LV_OPA_TRANSP; + if(border_draw_dsc) border_draw_dsc->opa = LV_OPA_TRANSP; + } + else if(lv_buttonmatrix_has_button_ctrl(obj, id, LV_BUTTONMATRIX_CTRL_DISABLED)) { + if(fill_draw_dsc) fill_draw_dsc->opa = LV_OPA_TRANSP; + if(border_draw_dsc) border_draw_dsc->opa = LV_OPA_TRANSP; + } + + if(lv_buttonmatrix_has_button_ctrl(obj, id, LV_CALENDAR_CTRL_HIGHLIGHT)) { + if(border_draw_dsc) border_draw_dsc->color = lv_theme_get_color_primary(obj); + if(fill_draw_dsc) fill_draw_dsc->opa = LV_OPA_40; + if(fill_draw_dsc) fill_draw_dsc->color = lv_theme_get_color_primary(obj); + if(lv_buttonmatrix_get_selected_button(obj) == (uint32_t)id) { + if(fill_draw_dsc) fill_draw_dsc->opa = LV_OPA_70; + } + } + + if(lv_buttonmatrix_has_button_ctrl(obj, id, LV_CALENDAR_CTRL_TODAY)) { + if(border_draw_dsc) border_draw_dsc->opa = LV_OPA_COVER; + if(border_draw_dsc) border_draw_dsc->color = lv_theme_get_color_primary(obj); + if(border_draw_dsc) border_draw_dsc->width += 1; } } @@ -378,24 +398,24 @@ static uint8_t get_day_of_week(uint32_t year, uint32_t month, uint32_t day) static void highlight_update(lv_obj_t * obj) { lv_calendar_t * calendar = (lv_calendar_t *)obj; - uint16_t i; + uint32_t i; /*Clear all kind of selection*/ - lv_btnmatrix_clear_btn_ctrl_all(calendar->btnm, LV_CALENDAR_CTRL_TODAY | LV_CALENDAR_CTRL_HIGHLIGHT); + lv_buttonmatrix_clear_button_ctrl_all(calendar->btnm, LV_CALENDAR_CTRL_TODAY | LV_CALENDAR_CTRL_HIGHLIGHT); uint8_t day_first = get_day_of_week(calendar->showed_date.year, calendar->showed_date.month, 1); if(calendar->highlighted_dates) { for(i = 0; i < calendar->highlighted_dates_num; i++) { if(calendar->highlighted_dates[i].year == calendar->showed_date.year && calendar->highlighted_dates[i].month == calendar->showed_date.month) { - lv_btnmatrix_set_btn_ctrl(calendar->btnm, calendar->highlighted_dates[i].day - 1 + day_first + 7, - LV_CALENDAR_CTRL_HIGHLIGHT); + lv_buttonmatrix_set_button_ctrl(calendar->btnm, calendar->highlighted_dates[i].day - 1 + day_first + 7, + LV_CALENDAR_CTRL_HIGHLIGHT); } } } if(calendar->showed_date.year == calendar->today.year && calendar->showed_date.month == calendar->today.month) { - lv_btnmatrix_set_btn_ctrl(calendar->btnm, calendar->today.day - 1 + day_first + 7, LV_CALENDAR_CTRL_TODAY); + lv_buttonmatrix_set_button_ctrl(calendar->btnm, calendar->today.day - 1 + day_first + 7, LV_CALENDAR_CTRL_TODAY); } } diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.h b/lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar.h similarity index 64% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.h rename to lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar.h index 2511b2fac..00e06a423 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar.h @@ -13,7 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../widgets/lv_btnmatrix.h" +#include "../buttonmatrix/lv_buttonmatrix.h" #if LV_USE_CALENDAR @@ -37,23 +37,27 @@ typedef struct { /*Data of calendar*/ typedef struct { lv_obj_t obj; - lv_obj_t * btnm; /*New data for this type*/ - lv_calendar_date_t today; /*Date of today*/ - lv_calendar_date_t showed_date; /*Currently visible month (day is ignored)*/ - lv_calendar_date_t * - highlighted_dates; /*Apply different style on these days (pointer to an array defined by the user)*/ - uint16_t highlighted_dates_num; /*Number of elements in `highlighted_days`*/ + lv_obj_t * btnm; + lv_calendar_date_t today; /**< Date of today*/ + lv_calendar_date_t showed_date; /**< Currently visible month (day is ignored)*/ + lv_calendar_date_t * highlighted_dates; /**< Apply different style on these days (pointer to user-defined array)*/ + size_t highlighted_dates_num; /**< Number of elements in `highlighted_days`*/ const char * map[8 * 7]; char nums [7 * 6][4]; } lv_calendar_t; -extern const lv_obj_class_t lv_calendar_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_calendar_class; /********************** * GLOBAL PROTOTYPES **********************/ +/** + * Create a calendar widget + * @param parent pointer to an object, it will be the parent of the new calendar + * @return pointer the created calendar + */ lv_obj_t * lv_calendar_create(lv_obj_t * parent); /*====================== @@ -88,7 +92,7 @@ void lv_calendar_set_showed_date(lv_obj_t * obj, uint32_t year, uint32_t month); * Only the pointer will be saved so this variable can't be local which will be destroyed later. * @param date_num number of dates in the array */ -void lv_calendar_set_highlighted_dates(lv_obj_t * obj, lv_calendar_date_t highlighted[], uint16_t date_num); +void lv_calendar_set_highlighted_dates(lv_obj_t * obj, lv_calendar_date_t highlighted[], size_t date_num); /** * Set the name of the days @@ -106,46 +110,47 @@ void lv_calendar_set_day_names(lv_obj_t * obj, const char ** day_names); /** * Get the button matrix object of the calendar. * It shows the dates and day names. - * @param obj pointer to a calendar object - * @return pointer to a the button matrix + * @param obj pointer to a calendar object + * @return pointer to a the button matrix */ lv_obj_t * lv_calendar_get_btnmatrix(const lv_obj_t * obj); /** * Get the today's date - * @param calendar pointer to a calendar object - * @return return pointer to an `lv_calendar_date_t` variable containing the date of today. + * @param calendar pointer to a calendar object + * @return return pointer to an `lv_calendar_date_t` variable containing the date of today. */ const lv_calendar_date_t * lv_calendar_get_today_date(const lv_obj_t * calendar); /** * Get the currently showed - * @param calendar pointer to a calendar object - * @return pointer to an `lv_calendar_date_t` variable containing the date is being shown. + * @param calendar pointer to a calendar object + * @return pointer to an `lv_calendar_date_t` variable containing the date is being shown. */ const lv_calendar_date_t * lv_calendar_get_showed_date(const lv_obj_t * calendar); /** * Get the highlighted dates - * @param calendar pointer to a calendar object - * @return pointer to an `lv_calendar_date_t` array containing the dates. + * @param calendar pointer to a calendar object + * @return pointer to an `lv_calendar_date_t` array containing the dates. */ lv_calendar_date_t * lv_calendar_get_highlighted_dates(const lv_obj_t * calendar); /** * Get the number of the highlighted dates - * @param calendar pointer to a calendar object - * @return number of highlighted days + * @param calendar pointer to a calendar object + * @return number of highlighted days */ -uint16_t lv_calendar_get_highlighted_dates_num(const lv_obj_t * calendar); +size_t lv_calendar_get_highlighted_dates_num(const lv_obj_t * calendar); /** * Get the currently pressed day - * @param calendar pointer to a calendar object - * @param date store the pressed date here - * @return LV_RES_OK: there is a valid pressed date; LV_RES_INV: there is no pressed data + * @param calendar pointer to a calendar object + * @param date store the pressed date here + * @return LV_RESULT_OK: there is a valid pressed date + * LV_RESULT_INVALID: there is no pressed data */ -lv_res_t lv_calendar_get_pressed_date(const lv_obj_t * calendar, lv_calendar_date_t * date); +lv_result_t lv_calendar_get_pressed_date(const lv_obj_t * calendar, lv_calendar_date_t * date); /*===================== * Other functions @@ -155,6 +160,9 @@ lv_res_t lv_calendar_get_pressed_date(const lv_obj_t * calendar, lv_calendar_dat * MACROS **********************/ +#include "lv_calendar_header_arrow.h" +#include "lv_calendar_header_dropdown.h" + #endif /*LV_USE_CALENDAR*/ #ifdef __cplusplus diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.c b/lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar_header_arrow.c similarity index 82% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.c rename to lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar_header_arrow.c index fecb1392e..a9daad4ae 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar_header_arrow.c @@ -7,11 +7,11 @@ * INCLUDES *********************/ #include "lv_calendar_header_arrow.h" -#if LV_USE_CALENDAR_HEADER_ARROW +#if LV_USE_CALENDAR && LV_USE_CALENDAR_HEADER_ARROW #include "lv_calendar.h" -#include "../../../widgets/lv_btn.h" -#include "../../../widgets/lv_label.h" +#include "../button/lv_button.h" +#include "../label/lv_label.h" #include "../../layouts/flex/lv_flex.h" /********************* @@ -32,11 +32,13 @@ static void value_changed_event_cb(lv_event_t * e); /********************** * STATIC VARIABLES **********************/ + const lv_obj_class_t lv_calendar_header_arrow_class = { .base_class = &lv_obj_class, .constructor_cb = my_constructor, .width_def = LV_PCT(100), - .height_def = LV_DPI_DEF / 3 + .height_def = LV_DPI_DEF / 3, + .name = "calendar-header-arrow", }; static const char * month_names_def[12] = LV_CALENDAR_DEFAULT_MONTH_NAMES; @@ -71,36 +73,36 @@ static void my_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(obj, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START); - lv_obj_t * mo_prev = lv_btn_create(obj); - lv_obj_set_style_bg_img_src(mo_prev, LV_SYMBOL_LEFT, 0); + lv_obj_t * mo_prev = lv_button_create(obj); + lv_obj_set_style_bg_image_src(mo_prev, LV_SYMBOL_LEFT, 0); lv_obj_set_height(mo_prev, lv_pct(100)); lv_obj_update_layout(mo_prev); - lv_coord_t btn_size = lv_obj_get_height(mo_prev); + int32_t btn_size = lv_obj_get_height(mo_prev); lv_obj_set_width(mo_prev, btn_size); lv_obj_add_event_cb(mo_prev, month_event_cb, LV_EVENT_CLICKED, NULL); - lv_obj_clear_flag(mo_prev, LV_OBJ_FLAG_CLICK_FOCUSABLE); + lv_obj_remove_flag(mo_prev, LV_OBJ_FLAG_CLICK_FOCUSABLE); lv_obj_t * label = lv_label_create(obj); lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_flex_grow(label, 1); - lv_obj_t * mo_next = lv_btn_create(obj); - lv_obj_set_style_bg_img_src(mo_next, LV_SYMBOL_RIGHT, 0); + lv_obj_t * mo_next = lv_button_create(obj); + lv_obj_set_style_bg_image_src(mo_next, LV_SYMBOL_RIGHT, 0); lv_obj_set_size(mo_next, btn_size, btn_size); lv_obj_add_event_cb(mo_next, month_event_cb, LV_EVENT_CLICKED, NULL); - lv_obj_clear_flag(mo_next, LV_OBJ_FLAG_CLICK_FOCUSABLE); + lv_obj_remove_flag(mo_next, LV_OBJ_FLAG_CLICK_FOCUSABLE); lv_obj_add_event_cb(obj, value_changed_event_cb, LV_EVENT_VALUE_CHANGED, NULL); /*Refresh the drop downs*/ - lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); } static void month_event_cb(lv_event_t * e) { - lv_obj_t * btn = lv_event_get_target(e); + lv_obj_t * btn = lv_event_get_current_target(e); lv_obj_t * header = lv_obj_get_parent(btn); lv_obj_t * calendar = lv_obj_get_parent(header); @@ -137,7 +139,7 @@ static void month_event_cb(lv_event_t * e) static void value_changed_event_cb(lv_event_t * e) { - lv_obj_t * header = lv_event_get_target(e); + lv_obj_t * header = lv_event_get_current_target(e); lv_obj_t * calendar = lv_obj_get_parent(header); const lv_calendar_date_t * cur_date = lv_calendar_get_showed_date(calendar); @@ -146,4 +148,3 @@ static void value_changed_event_cb(lv_event_t * e) } #endif /*LV_USE_CALENDAR_HEADER_ARROW*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.h b/lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar_header_arrow.h similarity index 83% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.h rename to lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar_header_arrow.h index 609ccb0ca..a04b355cc 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar_header_arrow.h @@ -13,8 +13,8 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../core/lv_obj.h" -#if LV_USE_CALENDAR_HEADER_ARROW +#include "../../core/lv_obj.h" +#if LV_USE_CALENDAR && LV_USE_CALENDAR_HEADER_ARROW /********************* * DEFINES @@ -23,7 +23,7 @@ extern "C" { /********************** * TYPEDEFS **********************/ -extern const lv_obj_class_t lv_calendar_header_arrow_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_calendar_header_arrow_class; /********************** * GLOBAL PROTOTYPES diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.c b/lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar_header_dropdown.c similarity index 64% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.c rename to lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar_header_dropdown.c index 5e8f90d4a..77d508be9 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar_header_dropdown.c @@ -7,10 +7,10 @@ * INCLUDES *********************/ #include "lv_calendar_header_dropdown.h" -#if LV_USE_CALENDAR_HEADER_DROPDOWN +#if LV_USE_CALENDAR && LV_USE_CALENDAR_HEADER_DROPDOWN #include "lv_calendar.h" -#include "../../../widgets/lv_dropdown.h" +#include "../dropdown/lv_dropdown.h" #include "../../layouts/flex/lv_flex.h" /********************* @@ -32,16 +32,18 @@ static void value_changed_event_cb(lv_event_t * e); /********************** * STATIC VARIABLES **********************/ + const lv_obj_class_t lv_calendar_header_dropdown_class = { .base_class = &lv_obj_class, .width_def = LV_PCT(100), .height_def = LV_SIZE_CONTENT, - .constructor_cb = my_constructor + .constructor_cb = my_constructor, + .name = "calendar-header-dropdown", }; static const char * month_list = "01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12"; static const char * year_list = { - "2023\n2022\n2021\n" + "2025\n2024\n2023\n2022\n2021\n" "2020\n2019\n2018\n2017\n2016\n2015\n2014\n2013\n2012\n2011\n2010\n2009\n2008\n2007\n2006\n2005\n2004\n2003\n2002\n2001\n" "2000\n1999\n1998\n1997\n1996\n1995\n1994\n1993\n1992\n1991\n1990\n1989\n1988\n1987\n1986\n1985\n1984\n1983\n1982\n1981\n" "1980\n1979\n1978\n1977\n1976\n1975\n1974\n1973\n1972\n1971\n1970\n1969\n1968\n1967\n1966\n1965\n1964\n1963\n1962\n1961\n" @@ -66,6 +68,31 @@ lv_obj_t * lv_calendar_header_dropdown_create(lv_obj_t * parent) return obj; } +void lv_calendar_header_dropdown_set_year_list(lv_obj_t * parent, const char * years_list) +{ + /* Search for the header dropdown */ + lv_obj_t * header = lv_obj_get_child_by_type(parent, 0, &lv_calendar_header_dropdown_class); + if(NULL == header) { + /* Header not found */ + return; + } + + /* Search for the year dropdown + * Index is 0 because in the header dropdown constructor the year dropdpwn (year_dd) + * is the first created child of the header */ + const int32_t year_dropdown_index = 0; + lv_obj_t * year_dropdown = lv_obj_get_child_by_type(header, year_dropdown_index, &lv_dropdown_class); + if(NULL == year_dropdown) { + /* year dropdpwn not found */ + return; + } + + lv_dropdown_clear_options(year_dropdown); + lv_dropdown_set_options(year_dropdown, years_list); + + lv_obj_invalidate(parent); +} + /********************** * STATIC FUNCTIONS **********************/ @@ -92,15 +119,15 @@ static void my_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) lv_obj_add_event_cb(obj, value_changed_event_cb, LV_EVENT_VALUE_CHANGED, NULL); /*Refresh the drop downs*/ - lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); } static void month_event_cb(lv_event_t * e) { - lv_obj_t * dropdown = lv_event_get_target(e); + lv_obj_t * dropdown = lv_event_get_current_target(e); lv_obj_t * calendar = lv_event_get_user_data(e); - uint16_t sel = lv_dropdown_get_selected(dropdown); + uint32_t sel = lv_dropdown_get_selected(dropdown); const lv_calendar_date_t * d; d = lv_calendar_get_showed_date(calendar); @@ -112,31 +139,44 @@ static void month_event_cb(lv_event_t * e) static void year_event_cb(lv_event_t * e) { - lv_obj_t * dropdown = lv_event_get_target(e); + lv_obj_t * dropdown = lv_event_get_current_target(e); lv_obj_t * calendar = lv_event_get_user_data(e); - uint16_t sel = lv_dropdown_get_selected(dropdown); + uint32_t sel = lv_dropdown_get_selected(dropdown); const lv_calendar_date_t * d; d = lv_calendar_get_showed_date(calendar); + + /* Get the first year on the options list + * NOTE: Assumes the first 4 digits in the option list are numbers */ + const char * year_p = lv_dropdown_get_options(dropdown); + const uint32_t year = (year_p[0] - '0') * 1000 + (year_p[1] - '0') * 100 + (year_p[2] - '0') * 10 + + (year_p[3] - '0'); + lv_calendar_date_t newd = *d; - newd.year = 2023 - sel; + newd.year = year - sel; lv_calendar_set_showed_date(calendar, newd.year, newd.month); } static void value_changed_event_cb(lv_event_t * e) { - lv_obj_t * header = lv_event_get_target(e); + lv_obj_t * header = lv_event_get_current_target(e); lv_obj_t * calendar = lv_obj_get_parent(header); const lv_calendar_date_t * cur_date = lv_calendar_get_showed_date(calendar); lv_obj_t * year_dd = lv_obj_get_child(header, 0); - lv_dropdown_set_selected(year_dd, 2023 - cur_date->year); + + /* Get the first year on the options list + * NOTE: Assumes the first 4 digits in the option list are numbers */ + const char * year_p = lv_dropdown_get_options(year_dd); + const uint32_t year = (year_p[0] - '0') * 1000 + (year_p[1] - '0') * 100 + (year_p[2] - '0') * 10 + + (year_p[3] - '0'); + + lv_dropdown_set_selected(year_dd, year - cur_date->year); lv_obj_t * month_dd = lv_obj_get_child(header, 1); lv_dropdown_set_selected(month_dd, cur_date->month - 1); } #endif /*LV_USE_CALENDAR_HEADER_ARROW*/ - diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.h b/lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar_header_dropdown.h similarity index 52% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.h rename to lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar_header_dropdown.h index fca219768..1ca87762e 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/calendar/lv_calendar_header_dropdown.h @@ -13,8 +13,12 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../core/lv_obj.h" -#if LV_USE_CALENDAR_HEADER_DROPDOWN +#include "../../core/lv_obj.h" +#if LV_USE_CALENDAR && LV_USE_CALENDAR_HEADER_DROPDOWN + +#if LV_USE_DROPDOWN == 0 +#error "LV_USE_DROPDOWN needs to be enabled" +#endif /********************* * DEFINES @@ -23,7 +27,7 @@ extern "C" { /********************** * TYPEDEFS **********************/ -extern const lv_obj_class_t lv_calendar_header_dropdown_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_calendar_header_dropdown_class; /********************** * GLOBAL PROTOTYPES @@ -36,6 +40,15 @@ extern const lv_obj_class_t lv_calendar_header_dropdown_class; */ lv_obj_t * lv_calendar_header_dropdown_create(lv_obj_t * parent); +/** + * Sets a custom calendar year list + * @param parent pointer to a calendar object + * @param years_list pointer to an const char array with the years list, see lv_dropdown set_options for more information. + * E.g. `const char * years = "2023\n2022\n2021\n2020\n2019" + * Only the pointer will be saved so this variable can't be local which will be destroyed later. + */ +void lv_calendar_header_dropdown_set_year_list(lv_obj_t * parent, const char * years_list); + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/canvas/lv_canvas.c b/lib/libesp32_lvgl/lvgl/src/widgets/canvas/lv_canvas.c new file mode 100644 index 000000000..0fe0e43c9 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/canvas/lv_canvas.c @@ -0,0 +1,366 @@ +/** + * @file lv_canvas.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_canvas.h" +#if LV_USE_CANVAS != 0 +#include "../../misc/lv_assert.h" +#include "../../misc/lv_math.h" +#include "../../draw/lv_draw.h" +#include "../../core/lv_refr.h" +#include "../../display/lv_display.h" +#include "../../draw/sw/lv_draw_sw.h" +#include "../../stdlib/lv_string.h" +#include "../../misc/cache/lv_cache.h" +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_canvas_class + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_canvas_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_canvas_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); + +/********************** + * STATIC VARIABLES + **********************/ + +const lv_obj_class_t lv_canvas_class = { + .constructor_cb = lv_canvas_constructor, + .destructor_cb = lv_canvas_destructor, + .instance_size = sizeof(lv_canvas_t), + .base_class = &lv_image_class, + .name = "canvas", +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_canvas_create(lv_obj_t * parent) +{ + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + return obj; +} + +/*===================== + * Setter functions + *====================*/ + +void lv_canvas_set_buffer(lv_obj_t * obj, void * buf, int32_t w, int32_t h, lv_color_format_t cf) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(buf); + + lv_canvas_t * canvas = (lv_canvas_t *)obj; + uint32_t stride = lv_draw_buf_width_to_stride(w, cf); + lv_draw_buf_init(&canvas->static_buf, w, h, cf, stride, buf, stride * h); + canvas->draw_buf = &canvas->static_buf; + + const void * src = lv_image_get_src(obj); + if(src) { + lv_image_cache_drop(src); + } + + lv_image_set_src(obj, canvas->draw_buf); + lv_image_cache_drop(canvas->draw_buf); +} + +void lv_canvas_set_draw_buf(lv_obj_t * obj, lv_draw_buf_t * draw_buf) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(draw_buf); + + lv_canvas_t * canvas = (lv_canvas_t *)obj; + canvas->draw_buf = draw_buf; + + const void * src = lv_image_get_src(obj); + if(src) { + lv_image_cache_drop(src); + } + + lv_image_set_src(obj, draw_buf); + lv_image_cache_drop(draw_buf); +} + +void lv_canvas_set_px(lv_obj_t * obj, int32_t x, int32_t y, lv_color_t color, lv_opa_t opa) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_canvas_t * canvas = (lv_canvas_t *)obj; + lv_draw_buf_t * draw_buf = canvas->draw_buf; + + lv_color_format_t cf = draw_buf->header.cf; + uint32_t stride = draw_buf->header.stride; + uint8_t * data = lv_draw_buf_goto_xy(draw_buf, x, y); + + if(LV_COLOR_FORMAT_IS_INDEXED(cf)) { + /*Indexed image bpp could be less than 8, calculate again*/ + uint8_t * buf = (uint8_t *)canvas->draw_buf->data; + buf += 8; + buf += y * stride; + buf += x >> 3; + uint32_t bit = 7 - (x & 0x7); + uint32_t c_int = color.blue; + + *buf &= ~(1 << bit); + *buf |= c_int << bit; + } + else if(cf == LV_COLOR_FORMAT_A8) { + *data = opa; + } + else if(cf == LV_COLOR_FORMAT_RGB565) { + lv_color16_t * buf = (lv_color16_t *)data; + buf->red = color.red >> 3; + buf->green = color.green >> 2; + buf->blue = color.blue >> 3; + } + else if(cf == LV_COLOR_FORMAT_RGB888) { + data[2] = color.red; + data[1] = color.green; + data[0] = color.blue; + } + else if(cf == LV_COLOR_FORMAT_XRGB8888) { + data[2] = color.red; + data[1] = color.green; + data[0] = color.blue; + data[3] = 0xFF; + } + else if(cf == LV_COLOR_FORMAT_ARGB8888) { + lv_color32_t * buf = (lv_color32_t *)data; + buf->red = color.red; + buf->green = color.green; + buf->blue = color.blue; + buf->alpha = opa; + } + lv_obj_invalidate(obj); +} + +void lv_canvas_set_palette(lv_obj_t * obj, uint8_t id, lv_color32_t c) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_canvas_t * canvas = (lv_canvas_t *)obj; + + lv_image_dsc_t dsc; + lv_draw_buf_to_image(canvas->draw_buf, &dsc); + + lv_image_buf_set_palette(&dsc, id, c); + lv_obj_invalidate(obj); +} + +/*===================== + * Getter functions + *====================*/ + +lv_draw_buf_t * lv_canvas_get_draw_buf(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_canvas_t * canvas = (lv_canvas_t *)obj; + return canvas->draw_buf; +} + +lv_color32_t lv_canvas_get_px(lv_obj_t * obj, int32_t x, int32_t y) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_color32_t ret = { 0 }; + lv_canvas_t * canvas = (lv_canvas_t *)obj; + if(canvas->draw_buf == NULL) return ret; + + lv_image_header_t * header = &canvas->draw_buf->header; + const uint8_t * px = lv_draw_buf_goto_xy(canvas->draw_buf, x, y); + + switch(header->cf) { + case LV_COLOR_FORMAT_ARGB8888: + ret = *(lv_color32_t *)px; + break; + case LV_COLOR_FORMAT_RGB888: + case LV_COLOR_FORMAT_XRGB8888: + ret.red = px[2]; + ret.green = px[1]; + ret.blue = px[0]; + ret.alpha = 0xFF; + break; + case LV_COLOR_FORMAT_RGB565: { + lv_color16_t * c16 = (lv_color16_t *) px; + ret.red = (c16[x].red * 2106) >> 8; /*To make it rounded*/ + ret.green = (c16[x].green * 1037) >> 8; + ret.blue = (c16[x].blue * 2106) >> 8; + ret.alpha = 0xFF; + break; + } + case LV_COLOR_FORMAT_A8: { + lv_color_t alpha_color = lv_obj_get_style_image_recolor(obj, LV_PART_MAIN); + ret.red = alpha_color.red; + ret.green = alpha_color.green; + ret.blue = alpha_color.blue; + ret.alpha = px[0]; + break; + } + default: + lv_memzero(&ret, sizeof(lv_color32_t)); + break; + } + + return ret; +} + +lv_image_dsc_t * lv_canvas_get_image(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_canvas_t * canvas = (lv_canvas_t *)obj; + return (lv_image_dsc_t *)canvas->draw_buf; +} + +const void * lv_canvas_get_buf(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_canvas_t * canvas = (lv_canvas_t *)obj; + if(canvas->draw_buf) + return canvas->draw_buf->unaligned_data; + + return NULL; +} + +/*===================== + * Other functions + *====================*/ + +void lv_canvas_copy_buf(lv_obj_t * obj, const lv_area_t * canvas_area, lv_draw_buf_t * dest_buf, + const lv_area_t * dest_area) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(canvas_area && dest_buf); + + lv_canvas_t * canvas = (lv_canvas_t *)obj; + if(canvas->draw_buf == NULL) return; + + LV_ASSERT_MSG(canvas->draw_buf->header.cf != dest_buf->header.cf, "Color formats must be the same"); + + lv_draw_buf_copy(canvas->draw_buf, canvas_area, dest_buf, dest_area); +} + +void lv_canvas_fill_bg(lv_obj_t * obj, lv_color_t color, lv_opa_t opa) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_canvas_t * canvas = (lv_canvas_t *)obj; + lv_draw_buf_t * draw_buf = canvas->draw_buf; + if(draw_buf == NULL) return; + + lv_image_header_t * header = &draw_buf->header; + uint32_t x; + uint32_t y; + + uint32_t stride = header->stride; + uint8_t * data = draw_buf->data; + if(header->cf == LV_COLOR_FORMAT_RGB565) { + uint16_t c16 = lv_color_to_u16(color); + for(y = 0; y < header->h; y++) { + uint16_t * buf16 = (uint16_t *)(data + y * stride); + for(x = 0; x < header->w; x++) { + buf16[x] = c16; + } + } + } + else if(header->cf == LV_COLOR_FORMAT_XRGB8888 || header->cf == LV_COLOR_FORMAT_ARGB8888) { + uint32_t c32 = lv_color_to_u32(color); + if(header->cf == LV_COLOR_FORMAT_ARGB8888) { + c32 &= 0x00ffffff; + c32 |= (uint32_t)opa << 24; + } + for(y = 0; y < header->h; y++) { + uint32_t * buf32 = (uint32_t *)(data + y * stride); + for(x = 0; x < header->w; x++) { + buf32[x] = c32; + } + } + } + else if(header->cf == LV_COLOR_FORMAT_RGB888) { + for(y = 0; y < header->h; y++) { + uint8_t * buf8 = (uint8_t *)(data + y * stride); + for(x = 0; x < header->w * 3; x += 3) { + buf8[x + 0] = color.blue; + buf8[x + 1] = color.green; + buf8[x + 2] = color.red; + } + } + } + else { + for(y = 0; y < header->h; y++) { + for(x = 0; x < header->w; x++) { + lv_canvas_set_px(obj, x, y, color, opa); + } + } + } + + lv_obj_invalidate(obj); +} + +void lv_canvas_init_layer(lv_obj_t * obj, lv_layer_t * layer) +{ + LV_ASSERT_NULL(obj); + LV_ASSERT_NULL(layer); + lv_canvas_t * canvas = (lv_canvas_t *)obj; + if(canvas->draw_buf == NULL) return; + + lv_image_header_t * header = &canvas->draw_buf->header; + lv_area_t canvas_area = {0, 0, header->w - 1, header->h - 1}; + lv_memzero(layer, sizeof(*layer)); + + layer->draw_buf = canvas->draw_buf; + layer->color_format = header->cf; + layer->buf_area = canvas_area; + layer->_clip_area = canvas_area; +} + +void lv_canvas_finish_layer(lv_obj_t * canvas, lv_layer_t * layer) +{ + while(layer->draw_task_head) { + lv_draw_dispatch_wait_for_request(); + lv_draw_dispatch_layer(lv_obj_get_display(canvas), layer); + } +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_canvas_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + LV_UNUSED(obj); +} + +static void lv_canvas_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + LV_TRACE_OBJ_CREATE("begin"); + + lv_canvas_t * canvas = (lv_canvas_t *)obj; + if(canvas->draw_buf == NULL) return; + + lv_image_cache_drop(&canvas->draw_buf); +} + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/canvas/lv_canvas.h b/lib/libesp32_lvgl/lvgl/src/widgets/canvas/lv_canvas.h new file mode 100644 index 000000000..bb39f98c4 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/canvas/lv_canvas.h @@ -0,0 +1,193 @@ +/** + * @file lv_canvas.h + * + */ + +#ifndef LV_CANVAS_H +#define LV_CANVAS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" + +#if LV_USE_CANVAS != 0 + +#include "../image/lv_image.h" +#include "../../draw/lv_draw_image.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_canvas_class; + +/*Data of canvas*/ +typedef struct { + lv_image_t img; + lv_draw_buf_t * draw_buf; + lv_draw_buf_t static_buf; +} lv_canvas_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a canvas object + * @param parent pointer to an object, it will be the parent of the new canvas + * @return pointer to the created canvas + */ +lv_obj_t * lv_canvas_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a buffer for the canvas. + * Use `lv_canvas_set_draw_buf` instead if you need to set a buffer with alignment requirement. + * @param buf a buffer where the content of the canvas will be. + * The required size is (lv_image_color_format_get_px_size(cf) * w) / 8 * h) + * It can be allocated with `lv_malloc()` or + * it can be statically allocated array (e.g. static lv_color_t buf[100*50]) or + * it can be an address in RAM or external SRAM + * @param canvas pointer to a canvas object + * @param w width of the canvas + * @param h height of the canvas + * @param cf color format. `LV_COLOR_FORMAT...` + */ +void lv_canvas_set_buffer(lv_obj_t * obj, void * buf, int32_t w, int32_t h, lv_color_format_t cf); + +/** + * Set a draw buffer for the canvas. A draw buffer either can be allocated by `lv_draw_buf_create()` + * or defined statically by `LV_DRAW_BUF_DEFINE`. When buffer start address and stride has alignment + * requirement, it's recommended to use `lv_draw_buf_create`. + * @param obj pointer to a canvas object + * @param draw_buf pointer to a draw buffer + */ +void lv_canvas_set_draw_buf(lv_obj_t * obj, lv_draw_buf_t * draw_buf); + +/** + * Set a pixel's color and opacity + * @param obj pointer to a canvas + * @param x X coordinate of the pixel + * @param y Y coordinate of the pixel + * @param color the color + * @param opa the opacity + * @note The following color formats are supported + * LV_COLOR_FORMAT_I1/2/4/8, LV_COLOR_FORMAT_A8, + * LV_COLOR_FORMAT_RGB565, LV_COLOR_FORMAT_RGB888, + * LV_COLOR_FORMAT_XRGB8888, LV_COLOR_FORMAT_ARGB8888 + */ +void lv_canvas_set_px(lv_obj_t * obj, int32_t x, int32_t y, lv_color_t color, lv_opa_t opa); + +/** + * Set the palette color of a canvas for index format. Valid only for `LV_COLOR_FORMAT_I1/2/4/8` + * @param canvas pointer to canvas object + * @param id the palette color to set: + * - for `LV_COLOR_FORMAT_I1`: 0..1 + * - for `LV_COLOR_FORMAT_I2`: 0..3 + * - for `LV_COLOR_FORMAT_I4`: 0..15 + * - for `LV_COLOR_FORMAT_I8`: 0..255 + * @param c the color to set + */ +void lv_canvas_set_palette(lv_obj_t * canvas, uint8_t id, lv_color32_t c); + +/*===================== + * Getter functions + *====================*/ + +lv_draw_buf_t * lv_canvas_get_draw_buf(lv_obj_t * obj); + +/** + * Get a pixel's color and opacity + * @param obj pointer to a canvas + * @param x X coordinate of the pixel + * @param y Y coordinate of the pixel + * @return ARGB8888 color of the pixel + */ +lv_color32_t lv_canvas_get_px(lv_obj_t * obj, int32_t x, int32_t y); + +/** + * Get the image of the canvas as a pointer to an `lv_image_dsc_t` variable. + * @param canvas pointer to a canvas object + * @return pointer to the image descriptor. + */ +lv_image_dsc_t * lv_canvas_get_image(lv_obj_t * canvas); + +/** + * Return the pointer for the buffer. + * It's recommended to use this function instead of the buffer form the + * return value of lv_canvas_get_image() as is can be aligned + * @param canvas pointer to a canvas object + * @return pointer to the buffer + */ +const void * lv_canvas_get_buf(lv_obj_t * canvas); + +/*===================== + * Other functions + *====================*/ + +/** + * Copy a buffer to the canvas + * @param canvas pointer to a canvas object + * @param canvas_area the area of the canvas to copy + * @param dest_buf pointer to a buffer to store the copied data + * @param dest_area the area of the destination buffer to copy to. If omitted NULL, copy to the whole `dest_buf` + */ +void lv_canvas_copy_buf(lv_obj_t * obj, const lv_area_t * canvas_area, lv_draw_buf_t * dest_buf, + const lv_area_t * dest_area); + +/** + * Fill the canvas with color + * @param canvas pointer to a canvas + * @param color the background color + * @param opa the desired opacity + */ +void lv_canvas_fill_bg(lv_obj_t * obj, lv_color_t color, lv_opa_t opa); + +/** + * Initialize a layer to use LVGL's generic draw functions (lv_draw_rect/label/...) on the canvas. + * Needs to be usd in pair with `lv_canvas_finish_layer`. + * @param canvas pointer to a canvas + * @param layer pointer to a layer variable to initialize + */ +void lv_canvas_init_layer(lv_obj_t * canvas, lv_layer_t * layer); + +/** + * Wait until all the drawings are finished on layer. + * Needs to be usd in pair with `lv_canvas_init_layer`. + * @param canvas pointer to a canvas + * @param layer pointer to a layer to finalize + */ +void lv_canvas_finish_layer(lv_obj_t * canvas, lv_layer_t * layer); + +/********************** + * MACROS + **********************/ + +#define LV_CANVAS_BUF_SIZE(w, h, bpp, stride) (((((w * bpp + 7) >> 3) + stride - 1) & ~(stride - 1)) * h + LV_DRAW_BUF_ALIGN) + +/** + * Just a wrapper to `LV_CANVAS_BUF_SIZE` for bindings. + */ +static inline uint32_t lv_canvas_buf_size(int32_t w, int32_t h, uint8_t bpp, uint8_t stride) +{ + return (uint32_t)LV_CANVAS_BUF_SIZE(w, h, bpp, stride); +} + +#endif /*LV_USE_CANVAS*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_CANVAS_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/chart/lv_chart.c b/lib/libesp32_lvgl/lvgl/src/widgets/chart/lv_chart.c new file mode 100644 index 000000000..40d05ff89 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/chart/lv_chart.c @@ -0,0 +1,1332 @@ +/** + * @file lv_chart.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_chart.h" +#if LV_USE_CHART != 0 + +#include "../../misc/lv_assert.h" + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_chart_class + +#define LV_CHART_HDIV_DEF 3 +#define LV_CHART_VDIV_DEF 5 +#define LV_CHART_POINT_CNT_DEF 10 +#define LV_CHART_LABEL_MAX_TEXT_LENGTH 16 + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_chart_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_chart_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_chart_event(const lv_obj_class_t * class_p, lv_event_t * e); + +static void draw_div_lines(lv_obj_t * obj, lv_layer_t * layer); +static void draw_series_line(lv_obj_t * obj, lv_layer_t * layer); +static void draw_series_bar(lv_obj_t * obj, lv_layer_t * layer); +static void draw_series_scatter(lv_obj_t * obj, lv_layer_t * layer); +static void draw_cursors(lv_obj_t * obj, lv_layer_t * layer); +static uint32_t get_index_from_x(lv_obj_t * obj, int32_t x); +static void invalidate_point(lv_obj_t * obj, uint32_t i); +static void new_points_alloc(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t cnt, int32_t ** a); + +/********************** + * STATIC VARIABLES + **********************/ + +const lv_obj_class_t lv_chart_class = { + .constructor_cb = lv_chart_constructor, + .destructor_cb = lv_chart_destructor, + .event_cb = lv_chart_event, + .width_def = LV_PCT(100), + .height_def = LV_DPI_DEF * 2, + .instance_size = sizeof(lv_chart_t), + .base_class = &lv_obj_class, + .name = "chart", +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_chart_create(lv_obj_t * parent) +{ + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + return obj; +} + +void lv_chart_set_type(lv_obj_t * obj, lv_chart_type_t type) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_chart_t * chart = (lv_chart_t *)obj; + if(chart->type == type) return; + + if(chart->type == LV_CHART_TYPE_SCATTER) { + lv_chart_series_t * ser; + _LV_LL_READ_BACK(&chart->series_ll, ser) { + lv_free(ser->x_points); + ser->x_points = NULL; + } + } + + if(type == LV_CHART_TYPE_SCATTER) { + lv_chart_series_t * ser; + _LV_LL_READ_BACK(&chart->series_ll, ser) { + ser->x_points = lv_malloc(sizeof(lv_point_t) * chart->point_cnt); + LV_ASSERT_MALLOC(ser->x_points); + if(ser->x_points == NULL) return; + } + } + + chart->type = type; + + lv_chart_refresh(obj); +} + +void lv_chart_set_point_count(lv_obj_t * obj, uint32_t cnt) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_chart_t * chart = (lv_chart_t *)obj; + if(chart->point_cnt == cnt) return; + + lv_chart_series_t * ser; + + if(cnt < 1) cnt = 1; + + _LV_LL_READ_BACK(&chart->series_ll, ser) { + if(chart->type == LV_CHART_TYPE_SCATTER) { + if(!ser->x_ext_buf_assigned) new_points_alloc(obj, ser, cnt, &ser->x_points); + } + if(!ser->y_ext_buf_assigned) new_points_alloc(obj, ser, cnt, &ser->y_points); + ser->start_point = 0; + } + + chart->point_cnt = cnt; + + lv_chart_refresh(obj); +} + +void lv_chart_set_range(lv_obj_t * obj, lv_chart_axis_t axis, int32_t min, int32_t max) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + max = max == min ? max + 1 : max; + + lv_chart_t * chart = (lv_chart_t *)obj; + switch(axis) { + case LV_CHART_AXIS_PRIMARY_Y: + chart->ymin[0] = min; + chart->ymax[0] = max; + break; + case LV_CHART_AXIS_SECONDARY_Y: + chart->ymin[1] = min; + chart->ymax[1] = max; + break; + case LV_CHART_AXIS_PRIMARY_X: + chart->xmin[0] = min; + chart->xmax[0] = max; + break; + case LV_CHART_AXIS_SECONDARY_X: + chart->xmin[1] = min; + chart->xmax[1] = max; + break; + default: + LV_LOG_WARN("Invalid axis: %d", axis); + return; + } + + lv_chart_refresh(obj); +} + +void lv_chart_set_update_mode(lv_obj_t * obj, lv_chart_update_mode_t update_mode) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_chart_t * chart = (lv_chart_t *)obj; + if(chart->update_mode == update_mode) return; + + chart->update_mode = update_mode; + lv_obj_invalidate(obj); +} + +void lv_chart_set_div_line_count(lv_obj_t * obj, uint8_t hdiv, uint8_t vdiv) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_chart_t * chart = (lv_chart_t *)obj; + if(chart->hdiv_cnt == hdiv && chart->vdiv_cnt == vdiv) return; + + chart->hdiv_cnt = hdiv; + chart->vdiv_cnt = vdiv; + + lv_obj_invalidate(obj); +} + +lv_chart_type_t lv_chart_get_type(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_chart_t * chart = (lv_chart_t *)obj; + return chart->type; +} + +uint32_t lv_chart_get_point_count(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_chart_t * chart = (lv_chart_t *)obj; + return chart->point_cnt; +} + +uint32_t lv_chart_get_x_start_point(const lv_obj_t * obj, lv_chart_series_t * ser) +{ + LV_ASSERT_NULL(ser); + LV_UNUSED(obj); + + return ser->start_point; +} + +void lv_chart_get_point_pos_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t id, lv_point_t * p_out) +{ + LV_ASSERT_NULL(obj); + LV_ASSERT_NULL(ser); + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_chart_t * chart = (lv_chart_t *)obj; + if(id >= chart->point_cnt) { + LV_LOG_WARN("Invalid index: %"LV_PRIu32, id); + p_out->x = 0; + p_out->y = 0; + return; + } + + int32_t w = lv_obj_get_content_width(obj); + int32_t h = lv_obj_get_content_height(obj); + + if(chart->type == LV_CHART_TYPE_LINE) { + p_out->x = (w * id) / (chart->point_cnt - 1); + } + else if(chart->type == LV_CHART_TYPE_SCATTER) { + p_out->x = lv_map(ser->x_points[id], chart->xmin[ser->x_axis_sec], chart->xmax[ser->x_axis_sec], 0, w); + } + else if(chart->type == LV_CHART_TYPE_BAR) { + uint32_t ser_cnt = _lv_ll_get_len(&chart->series_ll); + int32_t ser_gap = lv_obj_get_style_pad_column(obj, LV_PART_ITEMS); + + /*Gap between the columns on adjacent X ticks*/ + int32_t block_gap = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); + + int32_t block_w = (w - ((chart->point_cnt - 1) * block_gap)) / chart->point_cnt; + + p_out->x = (int32_t)((int32_t)(w - block_w) * id) / (chart->point_cnt - 1); + lv_chart_series_t * ser_i = NULL; + uint32_t ser_idx = 0; + _LV_LL_READ_BACK(&chart->series_ll, ser_i) { + if(ser_i == ser) break; + ser_idx++; + } + + p_out->x = (int32_t)((int32_t)(w + block_gap) * id) / chart->point_cnt; + p_out->x += block_w * ser_idx / ser_cnt; + + int32_t col_w = (block_w - (ser_gap * (ser_cnt - 1))) / ser_cnt; + p_out->x += col_w / 2; + } + + int32_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + p_out->x += lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; + p_out->x -= lv_obj_get_scroll_left(obj); + + uint32_t start_point = chart->update_mode == LV_CHART_UPDATE_MODE_SHIFT ? ser->start_point : 0; + id = ((int32_t)start_point + id) % chart->point_cnt; + int32_t temp_y = 0; + temp_y = (int32_t)((int32_t)ser->y_points[id] - chart->ymin[ser->y_axis_sec]) * h; + temp_y = temp_y / (chart->ymax[ser->y_axis_sec] - chart->ymin[ser->y_axis_sec]); + p_out->y = h - temp_y; + p_out->y += lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; + p_out->y -= lv_obj_get_scroll_top(obj); +} + +void lv_chart_refresh(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_obj_invalidate(obj); +} + +/*====================== + * Series + *=====================*/ + +lv_chart_series_t * lv_chart_add_series(lv_obj_t * obj, lv_color_t color, lv_chart_axis_t axis) +{ + LV_LOG_INFO("begin"); + + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_chart_t * chart = (lv_chart_t *)obj; + + /* Allocate space for a new series and add it to the chart series linked list */ + lv_chart_series_t * ser = _lv_ll_ins_tail(&chart->series_ll); + LV_ASSERT_MALLOC(ser); + if(ser == NULL) return NULL; + + /* Allocate memory for point_cnt points, handle failure below */ + ser->y_points = lv_malloc(sizeof(int32_t) * chart->point_cnt); + LV_ASSERT_MALLOC(ser->y_points); + + if(chart->type == LV_CHART_TYPE_SCATTER) { + ser->x_points = lv_malloc(sizeof(int32_t) * chart->point_cnt); + LV_ASSERT_MALLOC(ser->x_points); + if(NULL == ser->x_points) { + lv_free(ser->y_points); + _lv_ll_remove(&chart->series_ll, ser); + lv_free(ser); + return NULL; + } + } + else { + ser->x_points = NULL; + } + + if(ser->y_points == NULL) { + _lv_ll_remove(&chart->series_ll, ser); + lv_free(ser); + return NULL; + } + + /* Set series properties on successful allocation */ + ser->color = color; + ser->start_point = 0; + ser->y_ext_buf_assigned = false; + ser->hidden = 0; + ser->x_axis_sec = axis & LV_CHART_AXIS_SECONDARY_X ? 1 : 0; + ser->y_axis_sec = axis & LV_CHART_AXIS_SECONDARY_Y ? 1 : 0; + + uint32_t i; + const int32_t def = LV_CHART_POINT_NONE; + int32_t * p_tmp = ser->y_points; + for(i = 0; i < chart->point_cnt; i++) { + *p_tmp = def; + p_tmp++; + } + + return ser; +} + +void lv_chart_remove_series(lv_obj_t * obj, lv_chart_series_t * series) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(series); + + lv_chart_t * chart = (lv_chart_t *)obj; + if(!series->y_ext_buf_assigned && series->y_points) lv_free(series->y_points); + if(!series->x_ext_buf_assigned && series->x_points) lv_free(series->x_points); + + _lv_ll_remove(&chart->series_ll, series); + lv_free(series); + + return; +} + +void lv_chart_hide_series(lv_obj_t * chart, lv_chart_series_t * series, bool hide) +{ + LV_ASSERT_OBJ(chart, MY_CLASS); + LV_ASSERT_NULL(series); + + series->hidden = hide ? 1 : 0; + lv_chart_refresh(chart); +} + +void lv_chart_set_series_color(lv_obj_t * chart, lv_chart_series_t * series, lv_color_t color) +{ + LV_ASSERT_OBJ(chart, MY_CLASS); + LV_ASSERT_NULL(series); + + series->color = color; + lv_chart_refresh(chart); +} + +void lv_chart_set_x_start_point(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t id) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(ser); + + lv_chart_t * chart = (lv_chart_t *)obj; + if(id >= chart->point_cnt) return; + ser->start_point = id; +} + +lv_chart_series_t * lv_chart_get_series_next(const lv_obj_t * obj, const lv_chart_series_t * ser) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_chart_t * chart = (lv_chart_t *)obj; + if(ser == NULL) return _lv_ll_get_head(&chart->series_ll); + else return _lv_ll_get_next(&chart->series_ll, ser); +} + +/*===================== + * Cursor + *====================*/ + +lv_chart_cursor_t * lv_chart_add_cursor(lv_obj_t * obj, lv_color_t color, lv_dir_t dir) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_chart_t * chart = (lv_chart_t *)obj; + lv_chart_cursor_t * cursor = _lv_ll_ins_head(&chart->cursor_ll); + LV_ASSERT_MALLOC(cursor); + if(cursor == NULL) return NULL; + + lv_point_set(&cursor->pos, LV_CHART_POINT_NONE, LV_CHART_POINT_NONE); + cursor->point_id = LV_CHART_POINT_NONE; + cursor->pos_set = 0; + cursor->color = color; + cursor->dir = dir; + + return cursor; +} + +void lv_chart_set_cursor_pos(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_point_t * pos) +{ + LV_ASSERT_NULL(cursor); + LV_UNUSED(chart); + + cursor->pos = *pos; + cursor->pos_set = 1; + lv_chart_refresh(chart); +} + +void lv_chart_set_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_chart_series_t * ser, uint32_t point_id) +{ + LV_ASSERT_NULL(cursor); + LV_UNUSED(chart); + + cursor->point_id = point_id; + cursor->pos_set = 0; + if(ser == NULL) ser = lv_chart_get_series_next(chart, NULL); + cursor->ser = ser; + lv_chart_refresh(chart); +} + +lv_point_t lv_chart_get_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * cursor) +{ + LV_ASSERT_NULL(cursor); + LV_UNUSED(chart); + + return cursor->pos; +} + +/*===================== + * Set/Get value(s) + *====================*/ + +void lv_chart_set_all_value(lv_obj_t * obj, lv_chart_series_t * ser, int32_t value) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(ser); + + lv_chart_t * chart = (lv_chart_t *)obj; + uint32_t i; + for(i = 0; i < chart->point_cnt; i++) { + ser->y_points[i] = value; + } + ser->start_point = 0; + lv_chart_refresh(obj); +} + +void lv_chart_set_next_value(lv_obj_t * obj, lv_chart_series_t * ser, int32_t value) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(ser); + + lv_chart_t * chart = (lv_chart_t *)obj; + ser->y_points[ser->start_point] = value; + invalidate_point(obj, ser->start_point); + ser->start_point = (ser->start_point + 1) % chart->point_cnt; + invalidate_point(obj, ser->start_point); +} + +void lv_chart_set_next_value2(lv_obj_t * obj, lv_chart_series_t * ser, int32_t x_value, int32_t y_value) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(ser); + + lv_chart_t * chart = (lv_chart_t *)obj; + + if(chart->type != LV_CHART_TYPE_SCATTER) { + LV_LOG_WARN("Type must be LV_CHART_TYPE_SCATTER"); + return; + } + + ser->x_points[ser->start_point] = x_value; + ser->y_points[ser->start_point] = y_value; + ser->start_point = (ser->start_point + 1) % chart->point_cnt; + invalidate_point(obj, ser->start_point); +} + +void lv_chart_set_value_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t id, int32_t value) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(ser); + lv_chart_t * chart = (lv_chart_t *)obj; + + if(id >= chart->point_cnt) return; + ser->y_points[id] = value; + invalidate_point(obj, id); +} + +void lv_chart_set_value_by_id2(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t id, int32_t x_value, + int32_t y_value) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(ser); + lv_chart_t * chart = (lv_chart_t *)obj; + + if(chart->type != LV_CHART_TYPE_SCATTER) { + LV_LOG_WARN("Type must be LV_CHART_TYPE_SCATTER"); + return; + } + + if(id >= chart->point_cnt) return; + ser->x_points[id] = x_value; + ser->y_points[id] = y_value; + invalidate_point(obj, id); +} + +void lv_chart_set_ext_y_array(lv_obj_t * obj, lv_chart_series_t * ser, int32_t array[]) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(ser); + + if(!ser->y_ext_buf_assigned && ser->y_points) lv_free(ser->y_points); + ser->y_ext_buf_assigned = true; + ser->y_points = array; + lv_obj_invalidate(obj); +} + +void lv_chart_set_ext_x_array(lv_obj_t * obj, lv_chart_series_t * ser, int32_t array[]) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(ser); + + if(!ser->x_ext_buf_assigned && ser->x_points) lv_free(ser->x_points); + ser->x_ext_buf_assigned = true; + ser->x_points = array; + lv_obj_invalidate(obj); +} + +int32_t * lv_chart_get_y_array(const lv_obj_t * obj, lv_chart_series_t * ser) +{ + LV_UNUSED(obj); + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(ser); + return ser->y_points; +} + +int32_t * lv_chart_get_x_array(const lv_obj_t * obj, lv_chart_series_t * ser) +{ + LV_UNUSED(obj); + LV_ASSERT_OBJ(obj, MY_CLASS); + LV_ASSERT_NULL(ser); + return ser->x_points; +} + +uint32_t lv_chart_get_pressed_point(const lv_obj_t * obj) +{ + lv_chart_t * chart = (lv_chart_t *)obj; + return chart->pressed_point_id; +} + +int32_t lv_chart_get_first_point_center_offset(lv_obj_t * obj) +{ + lv_chart_t * chart = (lv_chart_t *)obj; + + int32_t x_ofs = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + if(chart->type == LV_CHART_TYPE_BAR) { + lv_obj_update_layout(obj); + /*Gap between the columns on ~adjacent X*/ + int32_t block_gap = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); + int32_t w = lv_obj_get_content_width(obj); + int32_t block_w = (w + block_gap) / (chart->point_cnt); + + x_ofs += (block_w - block_gap) / 2; + } + + return x_ofs; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_chart_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + LV_TRACE_OBJ_CREATE("begin"); + + lv_chart_t * chart = (lv_chart_t *)obj; + + _lv_ll_init(&chart->series_ll, sizeof(lv_chart_series_t)); + _lv_ll_init(&chart->cursor_ll, sizeof(lv_chart_cursor_t)); + + chart->ymin[0] = 0; + chart->xmin[0] = 0; + chart->ymin[1] = 0; + chart->xmin[1] = 0; + chart->ymax[0] = 100; + chart->xmax[0] = 100; + chart->ymax[1] = 100; + chart->xmax[1] = 100; + + chart->hdiv_cnt = LV_CHART_HDIV_DEF; + chart->vdiv_cnt = LV_CHART_VDIV_DEF; + chart->point_cnt = LV_CHART_POINT_CNT_DEF; + chart->pressed_point_id = LV_CHART_POINT_NONE; + chart->type = LV_CHART_TYPE_LINE; + chart->update_mode = LV_CHART_UPDATE_MODE_SHIFT; + + LV_TRACE_OBJ_CREATE("finished"); +} + +static void lv_chart_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + LV_TRACE_OBJ_CREATE("begin"); + + lv_chart_t * chart = (lv_chart_t *)obj; + lv_chart_series_t * ser; + while(chart->series_ll.head) { + ser = _lv_ll_get_head(&chart->series_ll); + if(!ser) continue; + + if(!ser->y_ext_buf_assigned) lv_free(ser->y_points); + if(!ser->x_ext_buf_assigned) lv_free(ser->x_points); + + _lv_ll_remove(&chart->series_ll, ser); + lv_free(ser); + } + _lv_ll_clear(&chart->series_ll); + + lv_chart_cursor_t * cur; + while(chart->cursor_ll.head) { + cur = _lv_ll_get_head(&chart->cursor_ll); + _lv_ll_remove(&chart->cursor_ll, cur); + lv_free(cur); + } + _lv_ll_clear(&chart->cursor_ll); + + LV_TRACE_OBJ_CREATE("finished"); +} + +static void lv_chart_event(const lv_obj_class_t * class_p, lv_event_t * e) +{ + LV_UNUSED(class_p); + + /*Call the ancestor's event handler*/ + lv_result_t res; + + res = lv_obj_event_base(MY_CLASS, e); + if(res != LV_RESULT_OK) return; + + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * obj = lv_event_get_current_target(e); + + lv_chart_t * chart = (lv_chart_t *)obj; + if(code == LV_EVENT_PRESSED) { + lv_indev_t * indev = lv_indev_active(); + lv_point_t p; + lv_indev_get_point(indev, &p); + + p.x -= obj->coords.x1; + uint32_t id = get_index_from_x(obj, p.x + lv_obj_get_scroll_left(obj)); + if(id != (uint32_t)chart->pressed_point_id) { + invalidate_point(obj, id); + invalidate_point(obj, chart->pressed_point_id); + chart->pressed_point_id = id; + lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); + } + } + else if(code == LV_EVENT_RELEASED) { + invalidate_point(obj, chart->pressed_point_id); + chart->pressed_point_id = LV_CHART_POINT_NONE; + } + else if(code == LV_EVENT_DRAW_MAIN) { + lv_layer_t * layer = lv_event_get_layer(e); + draw_div_lines(obj, layer); + + if(_lv_ll_is_empty(&chart->series_ll) == false) { + if(chart->type == LV_CHART_TYPE_LINE) draw_series_line(obj, layer); + else if(chart->type == LV_CHART_TYPE_BAR) draw_series_bar(obj, layer); + else if(chart->type == LV_CHART_TYPE_SCATTER) draw_series_scatter(obj, layer); + } + + draw_cursors(obj, layer); + } +} + +static void draw_div_lines(lv_obj_t * obj, lv_layer_t * layer) +{ + lv_chart_t * chart = (lv_chart_t *)obj; + + lv_area_t series_clip_area; + bool mask_ret = _lv_area_intersect(&series_clip_area, &obj->coords, &layer->_clip_area); + if(mask_ret == false) return; + + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = series_clip_area; + + int16_t i; + int16_t i_start; + int16_t i_end; + int32_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; + int32_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; + int32_t w = lv_obj_get_content_width(obj); + int32_t h = lv_obj_get_content_height(obj); + + lv_draw_line_dsc_t line_dsc; + lv_draw_line_dsc_init(&line_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_MAIN, &line_dsc); + + lv_opa_t border_opa = lv_obj_get_style_border_opa(obj, LV_PART_MAIN); + int32_t border_w = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + lv_border_side_t border_side = lv_obj_get_style_border_side(obj, LV_PART_MAIN); + + int32_t scroll_left = lv_obj_get_scroll_left(obj); + int32_t scroll_top = lv_obj_get_scroll_top(obj); + if(chart->hdiv_cnt != 0) { + int32_t y_ofs = obj->coords.y1 + pad_top - scroll_top; + line_dsc.p1.x = obj->coords.x1; + line_dsc.p2.x = obj->coords.x2; + + i_start = 0; + i_end = chart->hdiv_cnt; + if(border_opa > LV_OPA_MIN && border_w > 0) { + if((border_side & LV_BORDER_SIDE_TOP) && (lv_obj_get_style_pad_top(obj, LV_PART_MAIN) == 0)) i_start++; + if((border_side & LV_BORDER_SIDE_BOTTOM) && (lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN) == 0)) i_end--; + } + + for(i = i_start; i < i_end; i++) { + line_dsc.p1.y = (int32_t)((int32_t)h * i) / (chart->hdiv_cnt - 1); + line_dsc.p1.y += y_ofs; + line_dsc.p2.y = line_dsc.p1.y; + line_dsc.base.id1 = i; + + lv_draw_line(layer, &line_dsc); + } + } + + if(chart->vdiv_cnt != 0) { + int32_t x_ofs = obj->coords.x1 + pad_left - scroll_left; + line_dsc.p1.y = obj->coords.y1; + line_dsc.p2.y = obj->coords.y2; + i_start = 0; + i_end = chart->vdiv_cnt; + if(border_opa > LV_OPA_MIN && border_w > 0) { + if((border_side & LV_BORDER_SIDE_LEFT) && (lv_obj_get_style_pad_left(obj, LV_PART_MAIN) == 0)) i_start++; + if((border_side & LV_BORDER_SIDE_RIGHT) && (lv_obj_get_style_pad_right(obj, LV_PART_MAIN) == 0)) i_end--; + } + + for(i = i_start; i < i_end; i++) { + line_dsc.p1.x = (int32_t)((int32_t)w * i) / (chart->vdiv_cnt - 1); + line_dsc.p1.x += x_ofs; + line_dsc.p2.x = line_dsc.p1.x; + line_dsc.base.id1 = i; + + lv_draw_line(layer, &line_dsc); + } + } + + layer->_clip_area = clip_area_ori; +} + +static void draw_series_line(lv_obj_t * obj, lv_layer_t * layer) +{ + lv_area_t clip_area; + if(_lv_area_intersect(&clip_area, &obj->coords, &layer->_clip_area) == false) return; + + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area; + + lv_chart_t * chart = (lv_chart_t *)obj; + if(chart->point_cnt < 2) return; + + uint32_t i; + int32_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; + int32_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; + int32_t w = lv_obj_get_content_width(obj); + int32_t h = lv_obj_get_content_height(obj); + int32_t x_ofs = obj->coords.x1 + pad_left - lv_obj_get_scroll_left(obj); + int32_t y_ofs = obj->coords.y1 + pad_top - lv_obj_get_scroll_top(obj); + lv_chart_series_t * ser; + + lv_area_t series_clip_area; + bool mask_ret = _lv_area_intersect(&series_clip_area, &obj->coords, &layer->_clip_area); + if(mask_ret == false) return; + + lv_draw_line_dsc_t line_dsc; + lv_draw_line_dsc_init(&line_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_ITEMS, &line_dsc); + + lv_draw_rect_dsc_t point_dsc_default; + lv_draw_rect_dsc_init(&point_dsc_default); + lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &point_dsc_default); + + int32_t point_w = lv_obj_get_style_width(obj, LV_PART_INDICATOR) / 2; + int32_t point_h = lv_obj_get_style_height(obj, LV_PART_INDICATOR) / 2; + + /*Do not bother with line ending is the point will over it*/ + if(LV_MIN(point_w, point_h) > line_dsc.width / 2) line_dsc.raw_end = 1; + if(line_dsc.width == 1) line_dsc.raw_end = 1; + + /*If there are at least as many points as pixels then draw only vertical lines*/ + bool crowded_mode = (int32_t)chart->point_cnt >= w; + + /*Go through all data lines*/ + _LV_LL_READ_BACK(&chart->series_ll, ser) { + if(ser->hidden) continue; + line_dsc.color = ser->color; + point_dsc_default.bg_color = ser->color; + line_dsc.base.id2 = 0; + point_dsc_default.base.id2 = 0; + + int32_t start_point = chart->update_mode == LV_CHART_UPDATE_MODE_SHIFT ? ser->start_point : 0; + + line_dsc.p1.x = x_ofs; + line_dsc.p2.x = x_ofs; + + int32_t p_act = start_point; + int32_t p_prev = start_point; + int32_t y_tmp = (int32_t)((int32_t)ser->y_points[p_prev] - chart->ymin[ser->y_axis_sec]) * h; + y_tmp = y_tmp / (chart->ymax[ser->y_axis_sec] - chart->ymin[ser->y_axis_sec]); + line_dsc.p2.y = h - y_tmp + y_ofs; + + lv_value_precise_t y_min = line_dsc.p2.y; + lv_value_precise_t y_max = line_dsc.p2.y; + + for(i = 0; i < chart->point_cnt; i++) { + line_dsc.p1.x = line_dsc.p2.x; + line_dsc.p1.y = line_dsc.p2.y; + + if(line_dsc.p1.x > clip_area_ori.x2 + point_w + 1) break; + line_dsc.p2.x = (lv_value_precise_t)((w * i) / (chart->point_cnt - 1)) + x_ofs; + + p_act = (start_point + i) % chart->point_cnt; + + y_tmp = (int32_t)((int32_t)ser->y_points[p_act] - chart->ymin[ser->y_axis_sec]) * h; + y_tmp = y_tmp / (chart->ymax[ser->y_axis_sec] - chart->ymin[ser->y_axis_sec]); + line_dsc.p2.y = h - y_tmp + y_ofs; + + if(line_dsc.p2.x < clip_area_ori.x1 - point_w - 1) { + p_prev = p_act; + continue; + } + + /*Don't draw the first point. A second point is also required to draw the line*/ + if(i != 0) { + if(crowded_mode) { + if(ser->y_points[p_prev] != LV_CHART_POINT_NONE && ser->y_points[p_act] != LV_CHART_POINT_NONE) { + /*Draw only one vertical line between the min and max y-values on the same x-value*/ + y_max = LV_MAX(y_max, line_dsc.p2.y); + y_min = LV_MIN(y_min, line_dsc.p2.y); + if(line_dsc.p1.x != line_dsc.p2.x) { + lv_value_precise_t y_cur = line_dsc.p2.y; + line_dsc.p2.x--; /*It's already on the next x value*/ + line_dsc.p1.x = line_dsc.p2.x; + line_dsc.p1.y = y_min; + line_dsc.p2.y = y_max; + if(line_dsc.p1.y == line_dsc.p2.y) line_dsc.p2.y++; /*If they are the same no line will be drawn*/ + lv_draw_line(layer, &line_dsc); + line_dsc.p2.x++; /*Compensate the previous x--*/ + y_min = y_cur; /*Start the line of the next x from the current last y*/ + y_max = y_cur; + } + } + } + else { + lv_area_t point_area; + point_area.x1 = (int32_t)line_dsc.p1.x - point_w; + point_area.x2 = (int32_t)line_dsc.p1.x + point_w; + point_area.y1 = (int32_t)line_dsc.p1.y - point_h; + point_area.y2 = (int32_t)line_dsc.p1.y + point_h; + + if(ser->y_points[p_prev] != LV_CHART_POINT_NONE && ser->y_points[p_act] != LV_CHART_POINT_NONE) { + line_dsc.base.id2 = i; + lv_draw_line(layer, &line_dsc); + } + + if(point_w && point_h && ser->y_points[p_prev] != LV_CHART_POINT_NONE) { + point_dsc_default.base.id2 = i - 1; + lv_draw_rect(layer, &point_dsc_default, &point_area); + } + } + + } + p_prev = p_act; + } + + /*Draw the last point*/ + if(!crowded_mode && i == chart->point_cnt) { + + if(ser->y_points[p_act] != LV_CHART_POINT_NONE) { + lv_area_t point_area; + point_area.x1 = (int32_t)line_dsc.p2.x - point_w; + point_area.x2 = (int32_t)line_dsc.p2.x + point_w; + point_area.y1 = (int32_t)line_dsc.p2.y - point_h; + point_area.y2 = (int32_t)line_dsc.p2.y + point_h; + point_dsc_default.base.id2 = i - 1; + lv_draw_rect(layer, &point_dsc_default, &point_area); + } + + point_dsc_default.base.id1++; + line_dsc.base.id1++; + } + } + + layer->_clip_area = clip_area_ori; +} + +static void draw_series_scatter(lv_obj_t * obj, lv_layer_t * layer) +{ + + lv_area_t clip_area; + if(_lv_area_intersect(&clip_area, &obj->coords, &layer->_clip_area) == false) return; + + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area; + + lv_chart_t * chart = (lv_chart_t *)obj; + + uint32_t i; + int32_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + int32_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + int32_t w = lv_obj_get_content_width(obj); + int32_t h = lv_obj_get_content_height(obj); + int32_t x_ofs = obj->coords.x1 + pad_left + border_width - lv_obj_get_scroll_left(obj); + int32_t y_ofs = obj->coords.y1 + pad_top + border_width - lv_obj_get_scroll_top(obj); + lv_chart_series_t * ser; + + lv_draw_line_dsc_t line_dsc; + lv_draw_line_dsc_init(&line_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_ITEMS, &line_dsc); + + lv_draw_rect_dsc_t point_dsc_default; + lv_draw_rect_dsc_init(&point_dsc_default); + lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &point_dsc_default); + + int32_t point_w = lv_obj_get_style_width(obj, LV_PART_INDICATOR) / 2; + int32_t point_h = lv_obj_get_style_height(obj, LV_PART_INDICATOR) / 2; + + /*Do not bother with line ending is the point will over it*/ + if(LV_MIN(point_w, point_h) > line_dsc.width / 2) line_dsc.raw_end = 1; + if(line_dsc.width == 1) line_dsc.raw_end = 1; + + /*Go through all data lines*/ + _LV_LL_READ_BACK(&chart->series_ll, ser) { + if(ser->hidden) continue; + line_dsc.color = ser->color; + point_dsc_default.bg_color = ser->color; + + int32_t start_point = chart->update_mode == LV_CHART_UPDATE_MODE_SHIFT ? ser->start_point : 0; + + line_dsc.p1.x = x_ofs; + line_dsc.p2.x = x_ofs; + + int32_t p_act = start_point; + int32_t p_prev = start_point; + if(ser->y_points[p_act] != LV_CHART_POINT_CNT_DEF) { + line_dsc.p2.x = lv_map(ser->x_points[p_act], chart->xmin[ser->x_axis_sec], chart->xmax[ser->x_axis_sec], 0, w); + line_dsc.p2.x += x_ofs; + + line_dsc.p2.y = lv_map(ser->y_points[p_act], chart->ymin[ser->y_axis_sec], chart->ymax[ser->y_axis_sec], 0, h); + line_dsc.p2.y = h - line_dsc.p2.y; + line_dsc.p2.y += y_ofs; + } + else { + line_dsc.p2.x = (lv_value_precise_t)LV_COORD_MIN; + line_dsc.p2.y = (lv_value_precise_t)LV_COORD_MIN; + } + + for(i = 0; i < chart->point_cnt; i++) { + line_dsc.p1.x = line_dsc.p2.x; + line_dsc.p1.y = line_dsc.p2.y; + + p_act = (start_point + i) % chart->point_cnt; + if(ser->y_points[p_act] != LV_CHART_POINT_NONE) { + line_dsc.p2.y = lv_map(ser->y_points[p_act], chart->ymin[ser->y_axis_sec], chart->ymax[ser->y_axis_sec], 0, h); + line_dsc.p2.y = h - line_dsc.p2.y; + line_dsc.p2.y += y_ofs; + + line_dsc.p2.x = lv_map(ser->x_points[p_act], chart->xmin[ser->x_axis_sec], chart->xmax[ser->x_axis_sec], 0, w); + line_dsc.p2.x += x_ofs; + } + else { + p_prev = p_act; + continue; + } + + /*Don't draw the first point. A second point is also required to draw the line*/ + if(i != 0) { + lv_area_t point_area; + point_area.x1 = (int32_t)line_dsc.p1.x - point_w; + point_area.x2 = (int32_t)line_dsc.p1.x + point_w; + point_area.y1 = (int32_t)line_dsc.p1.y - point_h; + point_area.y2 = (int32_t)line_dsc.p1.y + point_h; + + if(ser->y_points[p_prev] != LV_CHART_POINT_NONE && ser->y_points[p_act] != LV_CHART_POINT_NONE) { + line_dsc.base.id2 = i; + lv_draw_line(layer, &line_dsc); + if(point_w && point_h) { + point_dsc_default.base.id2 = i; + lv_draw_rect(layer, &point_dsc_default, &point_area); + } + } + + p_prev = p_act; + } + + /*Draw the last point*/ + if(i == chart->point_cnt) { + + if(ser->y_points[p_act] != LV_CHART_POINT_NONE) { + lv_area_t point_area; + point_area.x1 = (int32_t)line_dsc.p2.x - point_w; + point_area.x2 = (int32_t)line_dsc.p2.x + point_w; + point_area.y1 = (int32_t)line_dsc.p2.y - point_h; + point_area.y2 = (int32_t)line_dsc.p2.y + point_h; + + point_dsc_default.base.id2 = i; + lv_draw_rect(layer, &point_dsc_default, &point_area); + } + } + } + line_dsc.base.id1++; + point_dsc_default.base.id1++; + layer->_clip_area = clip_area_ori; + } +} + +static void draw_series_bar(lv_obj_t * obj, lv_layer_t * layer) +{ + lv_area_t clip_area; + if(_lv_area_intersect(&clip_area, &obj->coords, &layer->_clip_area) == false) return; + + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area; + + lv_chart_t * chart = (lv_chart_t *)obj; + + uint32_t i; + lv_area_t col_a; + int32_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + int32_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + int32_t w = lv_obj_get_content_width(obj); + int32_t h = lv_obj_get_content_height(obj); + int32_t y_tmp; + lv_chart_series_t * ser; + uint32_t ser_cnt = _lv_ll_get_len(&chart->series_ll); + int32_t block_gap = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); /*Gap between the column on ~adjacent X*/ + int32_t block_w = (w - ((chart->point_cnt - 1) * block_gap)) / chart->point_cnt; + int32_t ser_gap = lv_obj_get_style_pad_column(obj, LV_PART_ITEMS); /*Gap between the columns on the ~same X*/ + int32_t col_w = (block_w - (ser_cnt - 1) * ser_gap) / ser_cnt; + if(col_w < 1) col_w = 1; + + int32_t border_w = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t x_ofs = pad_left - lv_obj_get_scroll_left(obj) + border_w; + int32_t y_ofs = pad_top - lv_obj_get_scroll_top(obj) + border_w; + + lv_draw_rect_dsc_t col_dsc; + lv_draw_rect_dsc_init(&col_dsc); + lv_obj_init_draw_rect_dsc(obj, LV_PART_ITEMS, &col_dsc); + col_dsc.bg_grad.dir = LV_GRAD_DIR_NONE; + col_dsc.bg_opa = LV_OPA_COVER; + + /*Make the cols longer with `radius` to clip the rounding from the bottom*/ + col_a.y2 = obj->coords.y2 + col_dsc.radius; + + /*Go through all points*/ + for(i = 0; i < chart->point_cnt; i++) { + int32_t x_act = (int32_t)((int32_t)(w - block_w) * i) / (chart->point_cnt - 1) + obj->coords.x1 + x_ofs; + col_dsc.base.id2 = i; + col_dsc.base.id1 = 0; + + /*Draw the current point of all data line*/ + _LV_LL_READ(&chart->series_ll, ser) { + if(ser->hidden) continue; + + int32_t start_point = chart->update_mode == LV_CHART_UPDATE_MODE_SHIFT ? ser->start_point : 0; + + col_a.x1 = x_act; + col_a.x2 = col_a.x1 + col_w - 1; + x_act += col_w + ser_gap; + + if(col_a.x2 < clip_area.x1) continue; + if(col_a.x1 > clip_area.x2) break; + + col_dsc.bg_color = ser->color; + + int32_t p_act = (start_point + i) % chart->point_cnt; + y_tmp = (int32_t)((int32_t)ser->y_points[p_act] - chart->ymin[ser->y_axis_sec]) * h; + y_tmp = y_tmp / (chart->ymax[ser->y_axis_sec] - chart->ymin[ser->y_axis_sec]); + col_a.y1 = h - y_tmp + obj->coords.y1 + y_ofs; + + if(ser->y_points[p_act] != LV_CHART_POINT_NONE) { + lv_draw_rect(layer, &col_dsc, &col_a); + } + col_dsc.base.id1++; + } + } + layer->_clip_area = clip_area_ori; +} + +static void draw_cursors(lv_obj_t * obj, lv_layer_t * layer) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_chart_t * chart = (lv_chart_t *)obj; + if(_lv_ll_is_empty(&chart->cursor_ll)) return; + + lv_area_t clip_area; + if(!_lv_area_intersect(&clip_area, &layer->_clip_area, &obj->coords)) return; + + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area; + + lv_chart_cursor_t * cursor; + + lv_draw_line_dsc_t line_dsc_ori; + lv_draw_line_dsc_init(&line_dsc_ori); + lv_obj_init_draw_line_dsc(obj, LV_PART_CURSOR, &line_dsc_ori); + + lv_draw_rect_dsc_t point_dsc_ori; + lv_draw_rect_dsc_init(&point_dsc_ori); + lv_obj_init_draw_rect_dsc(obj, LV_PART_CURSOR, &point_dsc_ori); + + lv_draw_line_dsc_t line_dsc; + lv_draw_rect_dsc_t point_dsc_tmp; + + int32_t point_w = lv_obj_get_style_width(obj, LV_PART_CURSOR) / 2; + int32_t point_h = lv_obj_get_style_width(obj, LV_PART_CURSOR) / 2; + + /*Go through all cursor lines*/ + _LV_LL_READ_BACK(&chart->cursor_ll, cursor) { + lv_memcpy(&line_dsc, &line_dsc_ori, sizeof(lv_draw_line_dsc_t)); + lv_memcpy(&point_dsc_tmp, &point_dsc_ori, sizeof(lv_draw_rect_dsc_t)); + line_dsc.color = cursor->color; + point_dsc_tmp.bg_color = cursor->color; + + int32_t cx; + int32_t cy; + if(cursor->pos_set) { + cx = cursor->pos.x; + cy = cursor->pos.y; + } + else { + if(cursor->point_id == LV_CHART_POINT_NONE) continue; + lv_point_t p; + lv_chart_get_point_pos_by_id(obj, cursor->ser, cursor->point_id, &p); + cx = p.x; + cy = p.y; + } + + cx += obj->coords.x1; + cy += obj->coords.y1; + + lv_area_t point_area; + bool draw_point = point_w && point_h; + point_area.x1 = cx - point_w; + point_area.x2 = cx + point_w; + point_area.y1 = cy - point_h; + point_area.y2 = cy + point_h; + + if(cursor->dir & LV_DIR_HOR) { + line_dsc.p1.x = cursor->dir & LV_DIR_LEFT ? obj->coords.x1 : cx; + line_dsc.p1.y = cy; + line_dsc.p2.x = cursor->dir & LV_DIR_RIGHT ? obj->coords.x2 : cx; + line_dsc.p2.y = line_dsc.p1.y; + + line_dsc.base.id2 = 0; + point_dsc_tmp.base.id2 = 0; + + lv_draw_line(layer, &line_dsc); + + if(draw_point) { + lv_draw_rect(layer, &point_dsc_tmp, &point_area); + } + } + + if(cursor->dir & LV_DIR_VER) { + line_dsc.p1.x = cx; + line_dsc.p1.y = cursor->dir & LV_DIR_TOP ? obj->coords.y1 : cy; + line_dsc.p2.x = line_dsc.p1.x; + line_dsc.p2.y = cursor->dir & LV_DIR_BOTTOM ? obj->coords.y2 : cy; + + line_dsc.base.id2 = 1; + point_dsc_tmp.base.id2 = 1; + + lv_draw_line(layer, &line_dsc); + + if(draw_point) { + lv_draw_rect(layer, &point_dsc_tmp, &point_area); + } + } + line_dsc_ori.base.id1++; + point_dsc_ori.base.id1++; + } + + layer->_clip_area = clip_area_ori; +} + +/** + * Get the nearest index to an X coordinate + * @param chart pointer to a chart object + * @param coord the coordination of the point relative to the series area. + * @return the found index + */ +static uint32_t get_index_from_x(lv_obj_t * obj, int32_t x) +{ + lv_chart_t * chart = (lv_chart_t *)obj; + int32_t w = lv_obj_get_content_width(obj); + int32_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + x -= pad_left; + + if(x < 0) return 0; + if(x > w) return chart->point_cnt - 1; + if(chart->type == LV_CHART_TYPE_LINE) return (x * (chart->point_cnt - 1) + w / 2) / w; + if(chart->type == LV_CHART_TYPE_BAR) return (x * chart->point_cnt) / w; + + return 0; +} + +static void invalidate_point(lv_obj_t * obj, uint32_t i) +{ + lv_chart_t * chart = (lv_chart_t *)obj; + if(i >= chart->point_cnt) return; + + int32_t w = lv_obj_get_content_width(obj); + int32_t scroll_left = lv_obj_get_scroll_left(obj); + + /*In shift mode the whole chart changes so the whole object*/ + if(chart->update_mode == LV_CHART_UPDATE_MODE_SHIFT) { + lv_obj_invalidate(obj); + return; + } + + if(chart->type == LV_CHART_TYPE_LINE) { + int32_t bwidth = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t pleft = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + int32_t x_ofs = obj->coords.x1 + pleft + bwidth - scroll_left; + int32_t line_width = lv_obj_get_style_line_width(obj, LV_PART_ITEMS); + int32_t point_w = lv_obj_get_style_width(obj, LV_PART_INDICATOR); + + lv_area_t coords; + lv_area_copy(&coords, &obj->coords); + coords.y1 -= line_width + point_w; + coords.y2 += line_width + point_w; + + if(i < chart->point_cnt - 1) { + coords.x1 = ((w * i) / (chart->point_cnt - 1)) + x_ofs - line_width - point_w; + coords.x2 = ((w * (i + 1)) / (chart->point_cnt - 1)) + x_ofs + line_width + point_w; + lv_obj_invalidate_area(obj, &coords); + } + + if(i > 0) { + coords.x1 = ((w * (i - 1)) / (chart->point_cnt - 1)) + x_ofs - line_width - point_w; + coords.x2 = ((w * i) / (chart->point_cnt - 1)) + x_ofs + line_width + point_w; + lv_obj_invalidate_area(obj, &coords); + } + } + else if(chart->type == LV_CHART_TYPE_BAR) { + lv_area_t col_a; + /*Gap between the column on ~adjacent X*/ + int32_t block_gap = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); + + int32_t block_w = (w + block_gap) / chart->point_cnt; + + int32_t bwidth = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t x_act; + x_act = (int32_t)((int32_t)(block_w) * i) ; + x_act += obj->coords.x1 + bwidth + lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + + lv_obj_get_coords(obj, &col_a); + col_a.x1 = x_act - scroll_left; + col_a.x2 = col_a.x1 + block_w; + col_a.x1 -= block_gap; + + lv_obj_invalidate_area(obj, &col_a); + } + else { + lv_obj_invalidate(obj); + } +} + +static void new_points_alloc(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t cnt, int32_t ** a) +{ + if((*a) == NULL) return; + + lv_chart_t * chart = (lv_chart_t *) obj; + uint32_t point_cnt_old = chart->point_cnt; + uint32_t i; + + if(ser->start_point != 0) { + int32_t * new_points = lv_malloc(sizeof(int32_t) * cnt); + LV_ASSERT_MALLOC(new_points); + if(new_points == NULL) return; + + if(cnt >= point_cnt_old) { + for(i = 0; i < point_cnt_old; i++) { + new_points[i] = + (*a)[(i + ser->start_point) % point_cnt_old]; /*Copy old contents to new array*/ + } + for(i = point_cnt_old; i < cnt; i++) { + new_points[i] = LV_CHART_POINT_NONE; /*Fill up the rest with default value*/ + } + } + else { + for(i = 0; i < cnt; i++) { + new_points[i] = + (*a)[(i + ser->start_point) % point_cnt_old]; /*Copy old contents to new array*/ + } + } + + /*Switch over pointer from old to new*/ + lv_free((*a)); + (*a) = new_points; + } + else { + (*a) = lv_realloc((*a), sizeof(int32_t) * cnt); + LV_ASSERT_MALLOC((*a)); + if((*a) == NULL) return; + /*Initialize the new points*/ + if(cnt > point_cnt_old) { + for(i = point_cnt_old - 1; i < cnt; i++) { + (*a)[i] = LV_CHART_POINT_NONE; + } + } + } +} + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.h b/lib/libesp32_lvgl/lvgl/src/widgets/chart/lv_chart.h similarity index 70% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.h rename to lib/libesp32_lvgl/lvgl/src/widgets/chart/lv_chart.h index 394c0e7b0..c3628f9e3 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/chart/lv_chart.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/chart/lv_chart.h @@ -13,7 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../lvgl.h" +#include "../../lvgl.h" #if LV_USE_CHART != 0 @@ -22,11 +22,7 @@ extern "C" { *********************/ /**Default value of points. Can be used to not draw a point*/ -#if LV_USE_LARGE_COORD -#define LV_CHART_POINT_NONE (INT32_MAX) -#else -#define LV_CHART_POINT_NONE (INT16_MAX) -#endif +#define LV_CHART_POINT_NONE (INT32_MAX) LV_EXPORT_CONST_INT(LV_CHART_POINT_NONE); /********************** @@ -36,103 +32,91 @@ LV_EXPORT_CONST_INT(LV_CHART_POINT_NONE); /** * Chart types */ -enum { +enum _lv_chart_type_t { LV_CHART_TYPE_NONE, /**< Don't draw the series*/ LV_CHART_TYPE_LINE, /**< Connect the points with lines*/ LV_CHART_TYPE_BAR, /**< Draw columns*/ LV_CHART_TYPE_SCATTER, /**< Draw points and lines in 2D (x,y coordinates)*/ }; + +#ifdef DOXYGEN +typedef _lv_chart_type_t lv_chart_type_t; +#else typedef uint8_t lv_chart_type_t; +#endif /*DOXYGEN*/ /** * Chart update mode for `lv_chart_set_next` */ -enum { +enum _lv_chart_update_mode_t { LV_CHART_UPDATE_MODE_SHIFT, /**< Shift old data to the left and add the new one the right*/ LV_CHART_UPDATE_MODE_CIRCULAR, /**< Add the new data in a circular way*/ }; + +#ifdef DOXYGEN +typedef _lv_chart_update_mode_t lv_chart_update_mode_t; +#else typedef uint8_t lv_chart_update_mode_t; +#endif /*DOXYGEN*/ /** * Enumeration of the axis' */ -enum { +enum _lv_chart_axis_t { LV_CHART_AXIS_PRIMARY_Y = 0x00, LV_CHART_AXIS_SECONDARY_Y = 0x01, LV_CHART_AXIS_PRIMARY_X = 0x02, LV_CHART_AXIS_SECONDARY_X = 0x04, _LV_CHART_AXIS_LAST }; + +#ifdef DOXYGEN +typedef _lv_chart_axis_t lv_chart_axis_t; +#else typedef uint8_t lv_chart_axis_t; +#endif /*DOXYGEN*/ /** * Descriptor a chart series */ typedef struct { - lv_coord_t * x_points; - lv_coord_t * y_points; + int32_t * x_points; + int32_t * y_points; lv_color_t color; - uint16_t start_point; - uint8_t hidden : 1; - uint8_t x_ext_buf_assigned : 1; - uint8_t y_ext_buf_assigned : 1; - uint8_t x_axis_sec : 1; - uint8_t y_axis_sec : 1; + uint32_t start_point; + uint32_t hidden : 1; + uint32_t x_ext_buf_assigned : 1; + uint32_t y_ext_buf_assigned : 1; + uint32_t x_axis_sec : 1; + uint32_t y_axis_sec : 1; } lv_chart_series_t; typedef struct { lv_point_t pos; - lv_coord_t point_id; + int32_t point_id; lv_color_t color; lv_chart_series_t * ser; lv_dir_t dir; - uint8_t pos_set: 1; /*1: pos is set; 0: point_id is set*/ + uint32_t pos_set: 1; /*1: pos is set; 0: point_id is set*/ } lv_chart_cursor_t; -typedef struct { - lv_coord_t major_len; - lv_coord_t minor_len; - lv_coord_t draw_size; - uint32_t minor_cnt : 15; - uint32_t major_cnt : 15; - uint32_t label_en : 1; -} lv_chart_tick_dsc_t; - - typedef struct { lv_obj_t obj; lv_ll_t series_ll; /**< Linked list for the series (stores lv_chart_series_t)*/ lv_ll_t cursor_ll; /**< Linked list for the cursors (stores lv_chart_cursor_t)*/ - lv_chart_tick_dsc_t tick[4]; - lv_coord_t ymin[2]; - lv_coord_t ymax[2]; - lv_coord_t xmin[2]; - lv_coord_t xmax[2]; - lv_coord_t pressed_point_id; - uint16_t hdiv_cnt; /**< Number of horizontal division lines*/ - uint16_t vdiv_cnt; /**< Number of vertical division lines*/ - uint16_t point_cnt; /**< Point number in a data line*/ - uint16_t zoom_x; - uint16_t zoom_y; + int32_t ymin[2]; + int32_t ymax[2]; + int32_t xmin[2]; + int32_t xmax[2]; + int32_t pressed_point_id; + uint32_t hdiv_cnt; /**< Number of horizontal division lines*/ + uint32_t vdiv_cnt; /**< Number of vertical division lines*/ + uint32_t point_cnt; /**< Point number in a data line*/ lv_chart_type_t type : 3; /**< Line or column chart*/ lv_chart_update_mode_t update_mode : 1; } lv_chart_t; -extern const lv_obj_class_t lv_chart_class; - -/** - * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_chart_class` - * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` - */ -typedef enum { - LV_CHART_DRAW_PART_DIV_LINE_INIT, /**< Used before/after drawn the div lines*/ - LV_CHART_DRAW_PART_DIV_LINE_HOR, /**< Used for each horizontal division lines*/ - LV_CHART_DRAW_PART_DIV_LINE_VER, /**< Used for each vertical division lines*/ - LV_CHART_DRAW_PART_LINE_AND_POINT, /**< Used on line and scatter charts for lines and points*/ - LV_CHART_DRAW_PART_BAR, /**< Used on bar charts for the rectangles*/ - LV_CHART_DRAW_PART_CURSOR, /**< Used on cursor lines and points*/ - LV_CHART_DRAW_PART_TICK_LABEL, /**< Used on tick lines and labels*/ -} lv_chart_draw_part_type_t; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_chart_class; /********************** * GLOBAL PROTOTYPES @@ -156,7 +140,7 @@ void lv_chart_set_type(lv_obj_t * obj, lv_chart_type_t type); * @param obj pointer to a chart object * @param cnt new number of points on the data lines */ -void lv_chart_set_point_count(lv_obj_t * obj, uint16_t cnt); +void lv_chart_set_point_count(lv_obj_t * obj, uint32_t cnt); /** * Set the minimal and maximal y values on an axis @@ -165,12 +149,12 @@ void lv_chart_set_point_count(lv_obj_t * obj, uint16_t cnt); * @param min minimum value of the y axis * @param max maximum value of the y axis */ -void lv_chart_set_range(lv_obj_t * obj, lv_chart_axis_t axis, lv_coord_t min, lv_coord_t max); +void lv_chart_set_range(lv_obj_t * obj, lv_chart_axis_t axis, int32_t min, int32_t max); /** * Set update mode of the chart object. Affects - * @param obj pointer to a chart object - * @param mode the update mode + * @param obj pointer to a chart object + * @param update_mode the update mode */ void lv_chart_set_update_mode(lv_obj_t * obj, lv_chart_update_mode_t update_mode); @@ -182,49 +166,6 @@ void lv_chart_set_update_mode(lv_obj_t * obj, lv_chart_update_mode_t update_mode */ void lv_chart_set_div_line_count(lv_obj_t * obj, uint8_t hdiv, uint8_t vdiv); -/** - * Zoom into the chart in X direction - * @param obj pointer to a chart object - * @param zoom_x zoom in x direction. LV_ZOOM_NONE or 256 for no zoom, 512 double zoom - */ -void lv_chart_set_zoom_x(lv_obj_t * obj, uint16_t zoom_x); - -/** - * Zoom into the chart in Y direction - * @param obj pointer to a chart object - * @param zoom_y zoom in y direction. LV_ZOOM_NONE or 256 for no zoom, 512 double zoom - */ -void lv_chart_set_zoom_y(lv_obj_t * obj, uint16_t zoom_y); - -/** - * Get X zoom of a chart - * @param obj pointer to a chart object - * @return the X zoom value - */ -uint16_t lv_chart_get_zoom_x(const lv_obj_t * obj); - -/** - * Get Y zoom of a chart - * @param obj pointer to a chart object - * @return the Y zoom value - */ -uint16_t lv_chart_get_zoom_y(const lv_obj_t * obj); - -/** - * Set the number of tick lines on an axis - * @param obj pointer to a chart object - * @param axis an axis which ticks count should be set - * @param major_len length of major ticks - * @param minor_len length of minor ticks - * @param major_cnt number of major ticks on the axis - * @param minor_cnt number of minor ticks between two major ticks - * @param label_en true: enable label drawing on major ticks - * @param draw_size extra size required to draw the tick and labels - * (start with 20 px and increase if the ticks/labels are clipped) - */ -void lv_chart_set_axis_tick(lv_obj_t * obj, lv_chart_axis_t axis, lv_coord_t major_len, lv_coord_t minor_len, - lv_coord_t major_cnt, lv_coord_t minor_cnt, bool label_en, lv_coord_t draw_size); - /** * Get the type of a chart * @param obj pointer to chart object @@ -234,31 +175,31 @@ lv_chart_type_t lv_chart_get_type(const lv_obj_t * obj); /** * Get the data point number per data line on chart - * @param chart pointer to chart object + * @param obj pointer to chart object * @return point number on each data line */ -uint16_t lv_chart_get_point_count(const lv_obj_t * obj); +uint32_t lv_chart_get_point_count(const lv_obj_t * obj); /** * Get the current index of the x-axis start point in the data array - * @param chart pointer to a chart object + * @param obj pointer to a chart object * @param ser pointer to a data series on 'chart' * @return the index of the current x start point in the data array */ -uint16_t lv_chart_get_x_start_point(const lv_obj_t * obj, lv_chart_series_t * ser); +uint32_t lv_chart_get_x_start_point(const lv_obj_t * obj, lv_chart_series_t * ser); /** * Get the position of a point to the chart. - * @param chart pointer to a chart object + * @param obj pointer to a chart object * @param ser pointer to series * @param id the index. * @param p_out store the result position here */ -void lv_chart_get_point_pos_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_point_t * p_out); +void lv_chart_get_point_pos_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t id, lv_point_t * p_out); /** * Refresh a chart if its data line has changed - * @param chart pointer to chart object + * @param obj pointer to chart object */ void lv_chart_refresh(lv_obj_t * obj); @@ -271,20 +212,20 @@ void lv_chart_refresh(lv_obj_t * obj); * @param obj pointer to a chart object * @param color color of the data series * @param axis the y axis to which the series should be attached (::LV_CHART_AXIS_PRIMARY_Y or ::LV_CHART_AXIS_SECONDARY_Y) - * @return pointer to the allocated data series + * @return pointer to the allocated data series or NULL on failure */ lv_chart_series_t * lv_chart_add_series(lv_obj_t * obj, lv_color_t color, lv_chart_axis_t axis); /** * Deallocate and remove a data series from a chart - * @param chart pointer to a chart object + * @param obj pointer to a chart object * @param series pointer to a data series on 'chart' */ void lv_chart_remove_series(lv_obj_t * obj, lv_chart_series_t * series); /** * Hide/Unhide a single series of a chart. - * @param obj pointer to a chart object. + * @param chart pointer to a chart object. * @param series pointer to a series object * @param hide true: hide the series */ @@ -292,7 +233,7 @@ void lv_chart_hide_series(lv_obj_t * chart, lv_chart_series_t * series, bool hid /** * Change the color of a series - * @param obj pointer to a chart object. + * @param chart pointer to a chart object. * @param series pointer to a series object * @param color the new color of the series */ @@ -305,7 +246,7 @@ void lv_chart_set_series_color(lv_obj_t * chart, lv_chart_series_t * series, lv_ * @param ser pointer to a data series on 'chart' * @param id the index of the x point in the data array */ -void lv_chart_set_x_start_point(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id); +void lv_chart_set_x_start_point(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t id); /** * Get the next series. @@ -315,8 +256,6 @@ void lv_chart_set_x_start_point(lv_obj_t * obj, lv_chart_series_t * ser, uint16_ */ lv_chart_series_t * lv_chart_get_series_next(const lv_obj_t * chart, const lv_chart_series_t * ser); - - /*===================== * Cursor *====================*/ @@ -332,7 +271,7 @@ lv_chart_cursor_t * lv_chart_add_cursor(lv_obj_t * obj, lv_color_t color, lv_di /** * Set the coordinate of the cursor with respect to the paddings - * @param obj pointer to a chart object + * @param chart pointer to a chart object * @param cursor pointer to the cursor * @param pos the new coordinate of cursor relative to the chart */ @@ -340,17 +279,17 @@ void lv_chart_set_cursor_pos(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_po /** * Stick the cursor to a point - * @param obj pointer to a chart object + * @param chart pointer to a chart object * @param cursor pointer to the cursor * @param ser pointer to a series * @param point_id the point's index or `LV_CHART_POINT_NONE` to not assign to any points. */ void lv_chart_set_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_chart_series_t * ser, - uint16_t point_id); + uint32_t point_id); /** * Get the coordinate of the cursor with respect to the paddings - * @param obj pointer to a chart object + * @param chart pointer to a chart object * @param cursor pointer to cursor * @return coordinate of the cursor as lv_point_t */ @@ -366,7 +305,7 @@ lv_point_t lv_chart_get_cursor_point(lv_obj_t * chart, lv_chart_cursor_t * curso * @param ser pointer to a data series on 'chart' * @param value the new value for all points. `LV_CHART_POINT_NONE` can be used to hide the points. */ -void lv_chart_set_all_value(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t value); +void lv_chart_set_all_value(lv_obj_t * obj, lv_chart_series_t * ser, int32_t value); /** * Set the next point's Y value according to the update mode policy. @@ -374,7 +313,7 @@ void lv_chart_set_all_value(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t * @param ser pointer to a data series on 'chart' * @param value the new value of the next data */ -void lv_chart_set_next_value(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t value); +void lv_chart_set_next_value(lv_obj_t * obj, lv_chart_series_t * ser, int32_t value); /** * Set the next point's X and Y value according to the update mode policy. @@ -383,7 +322,7 @@ void lv_chart_set_next_value(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t * @param x_value the new X value of the next data * @param y_value the new Y value of the next data */ -void lv_chart_set_next_value2(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t x_value, lv_coord_t y_value); +void lv_chart_set_next_value2(lv_obj_t * obj, lv_chart_series_t * ser, int32_t x_value, int32_t y_value); /** * Set an individual point's y value of a chart's series directly based on its index @@ -392,7 +331,7 @@ void lv_chart_set_next_value2(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_ * @param id the index of the x point in the array * @param value value to assign to array point */ -void lv_chart_set_value_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_coord_t value); +void lv_chart_set_value_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t id, int32_t value); /** * Set an individual point's x and y value of a chart's series directly based on its index @@ -403,8 +342,8 @@ void lv_chart_set_value_by_id(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t * @param x_value the new X value of the next data * @param y_value the new Y value of the next data */ -void lv_chart_set_value_by_id2(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t id, lv_coord_t x_value, - lv_coord_t y_value); +void lv_chart_set_value_by_id2(lv_obj_t * obj, lv_chart_series_t * ser, uint32_t id, int32_t x_value, + int32_t y_value); /** * Set an external array for the y data points to use for the chart @@ -413,7 +352,7 @@ void lv_chart_set_value_by_id2(lv_obj_t * obj, lv_chart_series_t * ser, uint16_t * @param ser pointer to a data series on 'chart' * @param array external array of points for chart */ -void lv_chart_set_ext_y_array(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t array[]); +void lv_chart_set_ext_y_array(lv_obj_t * obj, lv_chart_series_t * ser, int32_t array[]); /** * Set an external array for the x data points to use for the chart @@ -422,7 +361,7 @@ void lv_chart_set_ext_y_array(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_ * @param ser pointer to a data series on 'chart' * @param array external array of points for chart */ -void lv_chart_set_ext_x_array(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t array[]); +void lv_chart_set_ext_x_array(lv_obj_t * obj, lv_chart_series_t * ser, int32_t array[]); /** * Get the array of y values of a series @@ -430,7 +369,7 @@ void lv_chart_set_ext_x_array(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_ * @param ser pointer to a data series on 'chart' * @return the array of values with 'point_count' elements */ -lv_coord_t * lv_chart_get_y_array(const lv_obj_t * obj, lv_chart_series_t * ser); +int32_t * lv_chart_get_y_array(const lv_obj_t * obj, lv_chart_series_t * ser); /** * Get the array of x values of a series @@ -438,7 +377,7 @@ lv_coord_t * lv_chart_get_y_array(const lv_obj_t * obj, lv_chart_series_t * ser) * @param ser pointer to a data series on 'chart' * @return the array of values with 'point_count' elements */ -lv_coord_t * lv_chart_get_x_array(const lv_obj_t * obj, lv_chart_series_t * ser); +int32_t * lv_chart_get_x_array(const lv_obj_t * obj, lv_chart_series_t * ser); /** * Get the index of the currently pressed point. It's the same for every series. @@ -447,6 +386,14 @@ lv_coord_t * lv_chart_get_x_array(const lv_obj_t * obj, lv_chart_series_t * ser) */ uint32_t lv_chart_get_pressed_point(const lv_obj_t * obj); +/** + * Get the overall offset from the chart's side to the center of the first point. + * In case of a bar chart it will be the center of the first column group + * @param obj pointer to a chart object + * @return the offset of the center + */ +int32_t lv_chart_get_first_point_center_offset(lv_obj_t * obj); + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_checkbox.c b/lib/libesp32_lvgl/lvgl/src/widgets/checkbox/lv_checkbox.c similarity index 53% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_checkbox.c rename to lib/libesp32_lvgl/lvgl/src/widgets/checkbox/lv_checkbox.c index fa79b3793..157559b79 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_checkbox.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/checkbox/lv_checkbox.c @@ -9,10 +9,11 @@ #include "lv_checkbox.h" #if LV_USE_CHECKBOX != 0 -#include "../misc/lv_assert.h" -#include "../misc/lv_txt_ap.h" -#include "../core/lv_group.h" -#include "../draw/lv_draw.h" +#include "../../misc/lv_assert.h" +#include "../../misc/lv_text_ap.h" +#include "../../core/lv_group.h" +#include "../../draw/lv_draw.h" +#include "../../stdlib/lv_string.h" /********************* * DEFINES @@ -42,7 +43,8 @@ const lv_obj_class_t lv_checkbox_class = { .height_def = LV_SIZE_CONTENT, .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, .instance_size = sizeof(lv_checkbox_t), - .base_class = &lv_obj_class + .base_class = &lv_obj_class, + .name = "checkbox", }; /********************** @@ -68,23 +70,30 @@ lv_obj_t * lv_checkbox_create(lv_obj_t * parent) void lv_checkbox_set_text(lv_obj_t * obj, const char * txt) { lv_checkbox_t * cb = (lv_checkbox_t *)obj; + + if(NULL != txt) { + size_t len; + #if LV_USE_ARABIC_PERSIAN_CHARS - size_t len = _lv_txt_ap_calc_bytes_cnt(txt); + len = _lv_text_ap_calc_bytes_count(txt) + 1; #else - size_t len = strlen(txt); + len = lv_strlen(txt) + 1; #endif - char * _txt = (char *)cb->txt; - if(!cb->static_txt) _txt = lv_mem_realloc(_txt, len + 1); - else _txt = lv_mem_alloc(len + 1); + if(!cb->static_txt) cb->txt = lv_realloc(cb->txt, len); + else cb->txt = lv_malloc(len); + + LV_ASSERT_MALLOC(cb->txt); + if(NULL == cb->txt) return; + #if LV_USE_ARABIC_PERSIAN_CHARS - _lv_txt_ap_proc(txt, _txt); + _lv_text_ap_proc(txt, cb->txt); #else - strcpy(_txt, txt); + lv_strcpy(cb->txt, txt); #endif - cb->txt = _txt; - cb->static_txt = 0; + cb->static_txt = 0; + } lv_obj_refresh_self_size(obj); lv_obj_invalidate(obj); @@ -94,7 +103,7 @@ void lv_checkbox_set_text_static(lv_obj_t * obj, const char * txt) { lv_checkbox_t * cb = (lv_checkbox_t *)obj; - if(!cb->static_txt) lv_mem_free((void *)cb->txt); + if(!cb->static_txt) lv_free(cb->txt); cb->txt = (char *)txt; cb->static_txt = 1; @@ -124,11 +133,18 @@ static void lv_checkbox_constructor(const lv_obj_class_t * class_p, lv_obj_t * o lv_checkbox_t * cb = (lv_checkbox_t *)obj; - cb->txt = "Check box"; +#if LV_WIDGETS_HAS_DEFAULT_VALUE + cb->txt = (char *)"Check box"; cb->static_txt = 1; +#else + cb->txt = (char *)""; + cb->static_txt = 1; +#endif + lv_obj_add_flag(obj, LV_OBJ_FLAG_CLICKABLE); lv_obj_add_flag(obj, LV_OBJ_FLAG_CHECKABLE); lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLLABLE); LV_TRACE_OBJ_CREATE("finished"); } @@ -140,7 +156,7 @@ static void lv_checkbox_destructor(const lv_obj_class_t * class_p, lv_obj_t * ob lv_checkbox_t * cb = (lv_checkbox_t *)obj; if(!cb->static_txt) { - lv_mem_free((void *)cb->txt); + lv_free(cb->txt); cb->txt = NULL; } LV_TRACE_OBJ_CREATE("finished"); @@ -150,31 +166,31 @@ static void lv_checkbox_event(const lv_obj_class_t * class_p, lv_event_t * e) { LV_UNUSED(class_p); - lv_res_t res; + lv_result_t res; /*Call the ancestor's event handler*/ res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); if(code == LV_EVENT_GET_SELF_SIZE) { lv_point_t * p = lv_event_get_param(e); lv_checkbox_t * cb = (lv_checkbox_t *)obj; const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t font_h = lv_font_get_line_height(font); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + int32_t font_h = lv_font_get_line_height(font); + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); lv_point_t txt_size; - lv_txt_get_size(&txt_size, cb->txt, font, letter_space, line_space, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + lv_text_get_size(&txt_size, cb->txt, font, letter_space, line_space, LV_COORD_MAX, LV_TEXT_FLAG_NONE); - lv_coord_t bg_colp = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); - lv_coord_t marker_leftp = lv_obj_get_style_pad_left(obj, LV_PART_INDICATOR); - lv_coord_t marker_rightp = lv_obj_get_style_pad_right(obj, LV_PART_INDICATOR); - lv_coord_t marker_topp = lv_obj_get_style_pad_top(obj, LV_PART_INDICATOR); - lv_coord_t marker_bottomp = lv_obj_get_style_pad_bottom(obj, LV_PART_INDICATOR); + int32_t bg_colp = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); + int32_t marker_leftp = lv_obj_get_style_pad_left(obj, LV_PART_INDICATOR); + int32_t marker_rightp = lv_obj_get_style_pad_right(obj, LV_PART_INDICATOR); + int32_t marker_topp = lv_obj_get_style_pad_top(obj, LV_PART_INDICATOR); + int32_t marker_bottomp = lv_obj_get_style_pad_bottom(obj, LV_PART_INDICATOR); lv_point_t marker_size; marker_size.x = font_h + marker_leftp + marker_rightp; marker_size.y = font_h + marker_topp + marker_bottomp; @@ -183,8 +199,8 @@ static void lv_checkbox_event(const lv_obj_class_t * class_p, lv_event_t * e) p->y = LV_MAX(marker_size.y, txt_size.y); } else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - lv_coord_t * s = lv_event_get_param(e); - lv_coord_t m = lv_obj_calculate_ext_draw_size(obj, LV_PART_INDICATOR); + int32_t * s = lv_event_get_param(e); + int32_t m = lv_obj_calculate_ext_draw_size(obj, LV_PART_INDICATOR); *s = LV_MAX(*s, m); } else if(code == LV_EVENT_DRAW_MAIN) { @@ -194,71 +210,74 @@ static void lv_checkbox_event(const lv_obj_class_t * class_p, lv_event_t * e) static void lv_checkbox_draw(lv_event_t * e) { - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_checkbox_t * cb = (lv_checkbox_t *)obj; - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t font_h = lv_font_get_line_height(font); + int32_t font_h = lv_font_get_line_height(font); - lv_coord_t bg_border = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t bg_topp = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + bg_border; - lv_coord_t bg_leftp = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + bg_border; - lv_coord_t bg_colp = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); + const bool is_rtl = LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN); - lv_coord_t marker_leftp = lv_obj_get_style_pad_left(obj, LV_PART_INDICATOR); - lv_coord_t marker_rightp = lv_obj_get_style_pad_right(obj, LV_PART_INDICATOR); - lv_coord_t marker_topp = lv_obj_get_style_pad_top(obj, LV_PART_INDICATOR); - lv_coord_t marker_bottomp = lv_obj_get_style_pad_bottom(obj, LV_PART_INDICATOR); + int32_t bg_border = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t bg_topp = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + bg_border; + int32_t bg_p = is_rtl ? lv_obj_get_style_pad_right(obj, LV_PART_MAIN) : lv_obj_get_style_pad_left(obj, + LV_PART_MAIN) + bg_border; + int32_t bg_colp = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); - lv_coord_t transf_w = lv_obj_get_style_transform_width(obj, LV_PART_INDICATOR); - lv_coord_t transf_h = lv_obj_get_style_transform_height(obj, LV_PART_INDICATOR); + int32_t marker_leftp = lv_obj_get_style_pad_left(obj, LV_PART_INDICATOR); + int32_t marker_rightp = lv_obj_get_style_pad_right(obj, LV_PART_INDICATOR); + int32_t marker_topp = lv_obj_get_style_pad_top(obj, LV_PART_INDICATOR); + int32_t marker_bottomp = lv_obj_get_style_pad_bottom(obj, LV_PART_INDICATOR); + + int32_t transf_w = lv_obj_get_style_transform_width(obj, LV_PART_INDICATOR); + int32_t transf_h = lv_obj_get_style_transform_height(obj, LV_PART_INDICATOR); lv_draw_rect_dsc_t indic_dsc; lv_draw_rect_dsc_init(&indic_dsc); lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &indic_dsc); lv_area_t marker_area; - marker_area.x1 = obj->coords.x1 + bg_leftp; - marker_area.x2 = marker_area.x1 + font_h + marker_leftp + marker_rightp - 1; + if(is_rtl) { + marker_area.x2 = obj->coords.x2 - bg_p; + marker_area.x1 = marker_area.x2 - font_h - marker_leftp - marker_rightp + 1; + } + else { + marker_area.x1 = obj->coords.x1 + bg_p; + marker_area.x2 = marker_area.x1 + font_h + marker_leftp + marker_rightp - 1; + } marker_area.y1 = obj->coords.y1 + bg_topp; marker_area.y2 = marker_area.y1 + font_h + marker_topp + marker_bottomp - 1; lv_area_t marker_area_transf; lv_area_copy(&marker_area_transf, &marker_area); - marker_area_transf.x1 -= transf_w; - marker_area_transf.x2 += transf_w; - marker_area_transf.y1 -= transf_h; - marker_area_transf.y2 += transf_h; + lv_area_increase(&marker_area_transf, transf_w, transf_h); - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.rect_dsc = &indic_dsc; - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_CHECKBOX_DRAW_PART_BOX; - part_draw_dsc.draw_area = &marker_area_transf; - part_draw_dsc.part = LV_PART_INDICATOR; + lv_draw_rect(layer, &indic_dsc, &marker_area_transf); - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_rect(draw_ctx, &indic_dsc, &marker_area_transf); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); lv_point_t txt_size; - lv_txt_get_size(&txt_size, cb->txt, font, letter_space, line_space, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + lv_text_get_size(&txt_size, cb->txt, font, letter_space, line_space, LV_COORD_MAX, LV_TEXT_FLAG_NONE); lv_draw_label_dsc_t txt_dsc; lv_draw_label_dsc_init(&txt_dsc); lv_obj_init_draw_label_dsc(obj, LV_PART_MAIN, &txt_dsc); + txt_dsc.text = cb->txt; - lv_coord_t y_ofs = (lv_area_get_height(&marker_area) - font_h) / 2; + int32_t y_ofs = (lv_area_get_height(&marker_area) - font_h) / 2; lv_area_t txt_area; - txt_area.x1 = marker_area.x2 + bg_colp; - txt_area.x2 = txt_area.x1 + txt_size.x; + if(is_rtl) { + txt_area.x2 = marker_area.x1 - bg_colp; + txt_area.x1 = txt_area.x2 - txt_size.x; + } + else { + txt_area.x1 = marker_area.x2 + bg_colp; + txt_area.x2 = txt_area.x1 + txt_size.x; + } txt_area.y1 = obj->coords.y1 + bg_topp + y_ofs; txt_area.y2 = txt_area.y1 + txt_size.y; - lv_draw_label(draw_ctx, &txt_dsc, &txt_area, cb->txt, NULL); + lv_draw_label(layer, &txt_dsc, &txt_area); } #endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_checkbox.h b/lib/libesp32_lvgl/lvgl/src/widgets/checkbox/lv_checkbox.h similarity index 76% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_checkbox.h rename to lib/libesp32_lvgl/lvgl/src/widgets/checkbox/lv_checkbox.h index 11405bd21..1a0b3df1d 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_checkbox.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/checkbox/lv_checkbox.h @@ -13,8 +13,8 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../lv_conf_internal.h" -#include "../core/lv_obj.h" +#include "../../lv_conf_internal.h" +#include "../../core/lv_obj.h" #if LV_USE_CHECKBOX != 0 @@ -28,19 +28,11 @@ extern "C" { typedef struct { lv_obj_t obj; - const char * txt; + char * txt; uint32_t static_txt : 1; } lv_checkbox_t; -extern const lv_obj_class_t lv_checkbox_class; - -/** - * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_checkbox_class` - * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` - */ -typedef enum { - LV_CHECKBOX_DRAW_PART_BOX, /**< The tick box*/ -} lv_checkbox_draw_part_type_t; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_checkbox_class; /********************** * GLOBAL PROTOTYPES @@ -60,7 +52,7 @@ lv_obj_t * lv_checkbox_create(lv_obj_t * parent); /** * Set the text of a check box. `txt` will be copied and may be deallocated * after this function returns. - * @param cb pointer to a check box + * @param obj pointer to a check box * @param txt the text of the check box. NULL to refresh with the current text. */ void lv_checkbox_set_text(lv_obj_t * obj, const char * txt); @@ -68,7 +60,7 @@ void lv_checkbox_set_text(lv_obj_t * obj, const char * txt); /** * Set the text of a check box. `txt` must not be deallocated during the life * of this checkbox. - * @param cb pointer to a check box + * @param obj pointer to a check box * @param txt the text of the check box. */ void lv_checkbox_set_text_static(lv_obj_t * obj, const char * txt); @@ -79,7 +71,7 @@ void lv_checkbox_set_text_static(lv_obj_t * obj, const char * txt); /** * Get the text of a check box - * @param cb pointer to check box object + * @param obj pointer to check box object * @return pointer to the text of the check box */ const char * lv_checkbox_get_text(const lv_obj_t * obj); diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.c b/lib/libesp32_lvgl/lvgl/src/widgets/dropdown/lv_dropdown.c similarity index 76% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.c rename to lib/libesp32_lvgl/lvgl/src/widgets/dropdown/lv_dropdown.c index 765bdde81..22653d797 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/dropdown/lv_dropdown.c @@ -6,19 +6,20 @@ /********************* * INCLUDES *********************/ -#include "../core/lv_obj.h" +#include "../../core/lv_obj.h" #include "lv_dropdown.h" #if LV_USE_DROPDOWN != 0 -#include "../misc/lv_assert.h" -#include "../draw/lv_draw.h" -#include "../core/lv_group.h" -#include "../core/lv_indev.h" -#include "../core/lv_disp.h" -#include "../font/lv_symbol_def.h" -#include "../misc/lv_anim.h" -#include "../misc/lv_math.h" -#include "../misc/lv_txt_ap.h" +#include "../../misc/lv_assert.h" +#include "../../draw/lv_draw.h" +#include "../../core/lv_group.h" +#include "../../indev/lv_indev.h" +#include "../../display/lv_display.h" +#include "../../font/lv_symbol_def.h" +#include "../../misc/lv_anim.h" +#include "../../misc/lv_math.h" +#include "../../misc/lv_text_ap.h" +#include "../../stdlib/lv_string.h" #include /********************* @@ -47,18 +48,19 @@ static void lv_dropdownlist_destructor(const lv_obj_class_t * class_p, lv_obj_t static void lv_dropdown_list_event(const lv_obj_class_t * class_p, lv_event_t * e); static void draw_list(lv_event_t * e); -static void draw_box(lv_obj_t * dropdown_obj, lv_draw_ctx_t * draw_ctx, uint16_t id, lv_state_t state); -static void draw_box_label(lv_obj_t * dropdown_obj, lv_draw_ctx_t * draw_ctx, uint16_t id, lv_state_t state); -static lv_res_t btn_release_handler(lv_obj_t * obj); -static lv_res_t list_release_handler(lv_obj_t * list_obj); +static void draw_box(lv_obj_t * dropdown_obj, lv_layer_t * layer, uint32_t id, lv_state_t state); +static void draw_box_label(lv_obj_t * dropdown_obj, lv_layer_t * layer, uint32_t id, lv_state_t state); +static lv_result_t btn_release_handler(lv_obj_t * obj); +static lv_result_t list_release_handler(lv_obj_t * list_obj); static void list_press_handler(lv_obj_t * page); -static uint16_t get_id_on_point(lv_obj_t * dropdown_obj, lv_coord_t y); +static uint32_t get_id_on_point(lv_obj_t * dropdown_obj, int32_t y); static void position_to_selected(lv_obj_t * obj); static lv_obj_t * get_label(const lv_obj_t * obj); /********************** * STATIC VARIABLES **********************/ + const lv_obj_class_t lv_dropdown_class = { .constructor_cb = lv_dropdown_constructor, .destructor_cb = lv_dropdown_destructor, @@ -68,7 +70,8 @@ const lv_obj_class_t lv_dropdown_class = { .instance_size = sizeof(lv_dropdown_t), .editable = LV_OBJ_CLASS_EDITABLE_TRUE, .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, - .base_class = &lv_obj_class + .base_class = &lv_obj_class, + .name = "dropdown", }; const lv_obj_class_t lv_dropdownlist_class = { @@ -76,10 +79,10 @@ const lv_obj_class_t lv_dropdownlist_class = { .destructor_cb = lv_dropdownlist_destructor, .event_cb = lv_dropdown_list_event, .instance_size = sizeof(lv_dropdown_list_t), - .base_class = &lv_obj_class + .base_class = &lv_obj_class, + .name = "dropdown-list", }; - /********************** * MACROS **********************/ @@ -130,25 +133,25 @@ void lv_dropdown_set_options(lv_obj_t * obj, const char * options) /*Allocate space for the new text*/ #if LV_USE_ARABIC_PERSIAN_CHARS == 0 - size_t len = strlen(options) + 1; + size_t len = lv_strlen(options) + 1; #else - size_t len = _lv_txt_ap_calc_bytes_cnt(options) + 1; + size_t len = _lv_text_ap_calc_bytes_count(options) + 1; #endif if(dropdown->options != NULL && dropdown->static_txt == 0) { - lv_mem_free(dropdown->options); + lv_free(dropdown->options); dropdown->options = NULL; } - dropdown->options = lv_mem_alloc(len); + dropdown->options = lv_malloc(len); LV_ASSERT_MALLOC(dropdown->options); if(dropdown->options == NULL) return; #if LV_USE_ARABIC_PERSIAN_CHARS == 0 - strcpy(dropdown->options, options); + lv_strcpy(dropdown->options, options); #else - _lv_txt_ap_proc(options, dropdown->options); + _lv_text_ap_proc(options, dropdown->options); #endif /*Now the text is dynamically allocated*/ @@ -176,7 +179,7 @@ void lv_dropdown_set_options_static(lv_obj_t * obj, const char * options) dropdown->sel_opt_id_orig = 0; if(dropdown->static_txt == 0 && dropdown->options != NULL) { - lv_mem_free(dropdown->options); + lv_free(dropdown->options); dropdown->options = NULL; } @@ -197,26 +200,22 @@ void lv_dropdown_add_option(lv_obj_t * obj, const char * option, uint32_t pos) /*Convert static options to dynamic*/ if(dropdown->static_txt != 0) { char * static_options = dropdown->options; - size_t len = strlen(static_options) + 1; - - dropdown->options = lv_mem_alloc(len); + dropdown->options = lv_strdup(static_options); LV_ASSERT_MALLOC(dropdown->options); if(dropdown->options == NULL) return; - - strcpy(dropdown->options, static_options); dropdown->static_txt = 0; } /*Allocate space for the new option*/ - size_t old_len = (dropdown->options == NULL) ? 0 : strlen(dropdown->options); + size_t old_len = (dropdown->options == NULL) ? 0 : lv_strlen(dropdown->options); #if LV_USE_ARABIC_PERSIAN_CHARS == 0 - size_t ins_len = strlen(option) + 1; + size_t ins_len = lv_strlen(option) + 1; #else - size_t ins_len = _lv_txt_ap_calc_bytes_cnt(option) + 1; + size_t ins_len = _lv_text_ap_calc_bytes_count(option) + 1; #endif size_t new_len = ins_len + old_len + 2; /*+2 for terminating NULL and possible \n*/ - dropdown->options = lv_mem_realloc(dropdown->options, new_len + 1); + dropdown->options = lv_realloc(dropdown->options, new_len + 1); LV_ASSERT_MALLOC(dropdown->options); if(dropdown->options == NULL) return; @@ -236,21 +235,21 @@ void lv_dropdown_add_option(lv_obj_t * obj, const char * option, uint32_t pos) /*Add delimiter to existing options*/ if((insert_pos > 0) && (pos >= dropdown->option_cnt)) - _lv_txt_ins(dropdown->options, _lv_txt_encoded_get_char_id(dropdown->options, insert_pos++), "\n"); + _lv_text_ins(dropdown->options, _lv_text_encoded_get_char_id(dropdown->options, insert_pos++), "\n"); /*Insert the new option, adding \n if necessary*/ - char * ins_buf = lv_mem_buf_get(ins_len + 2); /*+ 2 for terminating NULL and possible \n*/ + char * ins_buf = lv_malloc(ins_len + 2); /*+ 2 for terminating NULL and possible \n*/ LV_ASSERT_MALLOC(ins_buf); if(ins_buf == NULL) return; #if LV_USE_ARABIC_PERSIAN_CHARS == 0 - strcpy(ins_buf, option); + lv_strcpy(ins_buf, option); #else - _lv_txt_ap_proc(option, ins_buf); + _lv_text_ap_proc(option, ins_buf); #endif if(pos < dropdown->option_cnt) strcat(ins_buf, "\n"); - _lv_txt_ins(dropdown->options, _lv_txt_encoded_get_char_id(dropdown->options, insert_pos), ins_buf); - lv_mem_buf_release(ins_buf); + _lv_text_ins(dropdown->options, _lv_text_encoded_get_char_id(dropdown->options, insert_pos), ins_buf); + lv_free(ins_buf); dropdown->option_cnt++; @@ -265,7 +264,7 @@ void lv_dropdown_clear_options(lv_obj_t * obj) if(dropdown->options == NULL) return; if(dropdown->static_txt == 0) - lv_mem_free(dropdown->options); + lv_free(dropdown->options); dropdown->options = NULL; dropdown->static_txt = 0; @@ -275,7 +274,7 @@ void lv_dropdown_clear_options(lv_obj_t * obj) if(dropdown->list) lv_obj_invalidate(dropdown->list); } -void lv_dropdown_set_selected(lv_obj_t * obj, uint16_t sel_opt) +void lv_dropdown_set_selected(lv_obj_t * obj, uint32_t sel_opt) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -350,7 +349,7 @@ const char * lv_dropdown_get_options(const lv_obj_t * obj) return dropdown->options == NULL ? "" : dropdown->options; } -uint16_t lv_dropdown_get_selected(const lv_obj_t * obj) +uint32_t lv_dropdown_get_selected(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -359,7 +358,7 @@ uint16_t lv_dropdown_get_selected(const lv_obj_t * obj) return dropdown->sel_opt_id; } -uint16_t lv_dropdown_get_option_cnt(const lv_obj_t * obj) +uint32_t lv_dropdown_get_option_count(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -379,7 +378,7 @@ void lv_dropdown_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf size_t txt_len; if(dropdown->options) { - txt_len = strlen(dropdown->options); + txt_len = lv_strlen(dropdown->options); } else { buf[0] = '\0'; @@ -393,7 +392,7 @@ void lv_dropdown_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf uint32_t c; for(c = 0; i < txt_len && dropdown->options[i] != '\n'; c++, i++) { if(buf_size && c >= buf_size - 1) { - LV_LOG_WARN("lv_dropdown_get_selected_str: the buffer was too small"); + LV_LOG_WARN("the buffer was too small"); break; } buf[c] = dropdown->options[i]; @@ -407,10 +406,10 @@ int32_t lv_dropdown_get_option_index(lv_obj_t * obj, const char * option) const char * opts = lv_dropdown_get_options(obj); uint32_t char_i = 0; uint32_t opt_i = 0; - uint32_t option_len = strlen(option); const char * start = opts; + const size_t option_len = lv_strlen(option); /*avoid recomputing this multiple times in the loop*/ - while(start[char_i] != '\0') { + while(start[0] != '\0') { for(char_i = 0; (start[char_i] != '\n') && (start[char_i] != '\0'); char_i++); if(option_len == char_i && memcmp(start, option, LV_MIN(option_len, char_i)) == 0) { @@ -426,7 +425,6 @@ int32_t lv_dropdown_get_option_index(lv_obj_t * obj, const char * option) return -1; } - const char * lv_dropdown_get_symbol(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -461,10 +459,10 @@ void lv_dropdown_open(lv_obj_t * dropdown_obj) lv_obj_add_state(dropdown_obj, LV_STATE_CHECKED); lv_obj_set_parent(dropdown->list, lv_obj_get_screen(dropdown_obj)); lv_obj_move_to_index(dropdown->list, -1); - lv_obj_clear_flag(dropdown->list, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(dropdown->list, LV_OBJ_FLAG_HIDDEN); /*To allow styling the list*/ - lv_event_send(dropdown_obj, LV_EVENT_READY, NULL); + lv_obj_send_event(dropdown_obj, LV_EVENT_READY, NULL); lv_obj_t * label = get_label(dropdown_obj); lv_label_set_text_static(label, dropdown->options); @@ -477,13 +475,13 @@ void lv_dropdown_open(lv_obj_t * dropdown_obj) lv_obj_set_width(dropdown->list, lv_obj_get_width(dropdown_obj)); } - lv_coord_t label_h = lv_obj_get_height(label); - lv_coord_t border_width = lv_obj_get_style_border_width(dropdown->list, LV_PART_MAIN); - lv_coord_t top = lv_obj_get_style_pad_top(dropdown->list, LV_PART_MAIN) + border_width; - lv_coord_t bottom = lv_obj_get_style_pad_bottom(dropdown->list, LV_PART_MAIN) + border_width; + int32_t label_h = lv_obj_get_height(label); + int32_t border_width = lv_obj_get_style_border_width(dropdown->list, LV_PART_MAIN); + int32_t top = lv_obj_get_style_pad_top(dropdown->list, LV_PART_MAIN) + border_width; + int32_t bottom = lv_obj_get_style_pad_bottom(dropdown->list, LV_PART_MAIN) + border_width; - lv_coord_t list_fit_h = label_h + top + bottom; - lv_coord_t list_h = list_fit_h; + int32_t list_fit_h = label_h + top + bottom; + int32_t list_h = list_fit_h; lv_dir_t dir = dropdown->dir; /*No space on the bottom? See if top is better.*/ @@ -526,8 +524,8 @@ void lv_dropdown_open(lv_obj_t * dropdown_obj) lv_obj_update_layout(dropdown->list); if(dropdown->dir == LV_DIR_LEFT || dropdown->dir == LV_DIR_RIGHT) { - lv_coord_t y1 = lv_obj_get_y(dropdown->list); - lv_coord_t y2 = lv_obj_get_y2(dropdown->list); + int32_t y1 = lv_obj_get_y(dropdown->list); + int32_t y2 = lv_obj_get_y2(dropdown->list); if(y2 >= LV_VER_RES) { lv_obj_set_y(dropdown->list, y1 - (y2 - LV_VER_RES) - 1); } @@ -554,13 +552,13 @@ void lv_dropdown_close(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); - lv_obj_clear_state(obj, LV_STATE_CHECKED); + lv_obj_remove_state(obj, LV_STATE_CHECKED); lv_dropdown_t * dropdown = (lv_dropdown_t *)obj; dropdown->pr_opt_id = LV_DROPDOWN_PR_NONE; lv_obj_add_flag(dropdown->list, LV_OBJ_FLAG_HIDDEN); - lv_event_send(obj, LV_EVENT_CANCEL, NULL); + lv_obj_send_event(obj, LV_EVENT_CANCEL, NULL); } bool lv_dropdown_is_open(lv_obj_t * obj) @@ -604,7 +602,9 @@ static void lv_dropdown_constructor(const lv_obj_class_t * class_p, lv_obj_t * o dropdown->dir = LV_DIR_BOTTOM; lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS); +#if LV_WIDGETS_HAS_DEFAULT_VALUE lv_dropdown_set_options_static(obj, "Option 1\nOption 2\nOption 3"); +#endif dropdown->list = lv_dropdown_list_create(lv_obj_get_screen(obj)); lv_dropdown_list_t * list = (lv_dropdown_list_t *)dropdown->list; @@ -619,12 +619,12 @@ static void lv_dropdown_destructor(const lv_obj_class_t * class_p, lv_obj_t * ob lv_dropdown_t * dropdown = (lv_dropdown_t *)obj; if(dropdown->list) { - lv_obj_del(dropdown->list); + lv_obj_delete(dropdown->list); dropdown->list = NULL; } if(!dropdown->static_txt) { - lv_mem_free(dropdown->options); + lv_free(dropdown->options); dropdown->options = NULL; } } @@ -634,8 +634,8 @@ static void lv_dropdownlist_constructor(const lv_obj_class_t * class_p, lv_obj_t LV_UNUSED(class_p); LV_TRACE_OBJ_CREATE("begin"); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICK_FOCUSABLE); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_CLICK_FOCUSABLE); lv_obj_add_flag(obj, LV_OBJ_FLAG_IGNORE_LAYOUT); lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN); @@ -657,20 +657,20 @@ static void lv_dropdown_event(const lv_obj_class_t * class_p, lv_event_t * e) { LV_UNUSED(class_p); - lv_res_t res; + lv_result_t res; /*Call the ancestor's event handler*/ res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_dropdown_t * dropdown = (lv_dropdown_t *)obj; if(code == LV_EVENT_FOCUSED) { lv_group_t * g = lv_obj_get_group(obj); bool editing = lv_group_get_editing(g); - lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); + lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_active()); /*Encoders need special handling*/ if(indev_type == LV_INDEV_TYPE_ENCODER) { @@ -690,7 +690,7 @@ static void lv_dropdown_event(const lv_obj_class_t * class_p, lv_event_t * e) } else if(code == LV_EVENT_RELEASED) { res = btn_release_handler(obj); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; } else if(code == LV_EVENT_STYLE_CHANGED) { lv_obj_refresh_self_size(obj); @@ -704,7 +704,7 @@ static void lv_dropdown_event(const lv_obj_class_t * class_p, lv_event_t * e) p->y = lv_font_get_line_height(font); } else if(code == LV_EVENT_KEY) { - char c = *((char *)lv_event_get_param(e)); + uint32_t c = lv_event_get_key(e); if(c == LV_KEY_RIGHT || c == LV_KEY_DOWN) { if(!lv_dropdown_is_open(obj)) { lv_dropdown_open(obj); @@ -731,10 +731,10 @@ static void lv_dropdown_event(const lv_obj_class_t * class_p, lv_event_t * e) else if(c == LV_KEY_ENTER) { /* Handle the ENTER key only if it was send by an other object. * Do no process it if ENTER is sent by the dropdown because it's handled in LV_EVENT_RELEASED */ - lv_obj_t * indev_obj = lv_indev_get_obj_act(); + lv_obj_t * indev_obj = lv_indev_get_active_obj(); if(indev_obj != obj) { res = btn_release_handler(obj); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; } } } @@ -747,20 +747,20 @@ static void lv_dropdown_list_event(const lv_obj_class_t * class_p, lv_event_t * { LV_UNUSED(class_p); - lv_res_t res; + lv_result_t res; /*Call the ancestor's event handler*/ lv_event_code_t code = lv_event_get_code(e); if(code != LV_EVENT_DRAW_POST) { res = lv_obj_event_base(MY_CLASS_LIST, e); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; } - lv_obj_t * list = lv_event_get_target(e); + lv_obj_t * list = lv_event_get_current_target(e); lv_obj_t * dropdown_obj = ((lv_dropdown_list_t *)list)->dropdown; lv_dropdown_t * dropdown = (lv_dropdown_t *)dropdown_obj; if(code == LV_EVENT_RELEASED) { - if(lv_indev_get_scroll_obj(lv_indev_get_act()) == NULL) { + if(lv_indev_get_scroll_obj(lv_indev_active()) == NULL) { list_release_handler(list); } } @@ -774,21 +774,20 @@ static void lv_dropdown_list_event(const lv_obj_class_t * class_p, lv_event_t * else if(code == LV_EVENT_DRAW_POST) { draw_list(e); res = lv_obj_event_base(MY_CLASS_LIST, e); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; } } - static void draw_main(lv_event_t * e) { - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_dropdown_t * dropdown = (lv_dropdown_t *)obj; - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; - lv_coord_t right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN) + border_width; - lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; + int32_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; + int32_t right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN) + border_width; + int32_t top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; lv_draw_label_dsc_t symbol_dsc; lv_draw_label_dsc_init(&symbol_dsc); @@ -796,9 +795,9 @@ static void draw_main(lv_event_t * e) /*If no text specified use the selected option*/ const char * opt_txt; + char buf[128]; if(dropdown->text) opt_txt = dropdown->text; else { - char * buf = lv_mem_buf_get(128); lv_dropdown_get_selected_str(obj, buf, 128); opt_txt = buf; } @@ -808,20 +807,20 @@ static void draw_main(lv_event_t * e) if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) symbol_to_left = true; if(dropdown->symbol) { - lv_img_src_t symbol_type = lv_img_src_get_type(dropdown->symbol); - lv_coord_t symbol_w; - lv_coord_t symbol_h; - if(symbol_type == LV_IMG_SRC_SYMBOL) { + lv_image_src_t symbol_type = lv_image_src_get_type(dropdown->symbol); + int32_t symbol_w; + int32_t symbol_h; + if(symbol_type == LV_IMAGE_SRC_SYMBOL) { lv_point_t size; - lv_txt_get_size(&size, dropdown->symbol, symbol_dsc.font, symbol_dsc.letter_space, symbol_dsc.line_space, LV_COORD_MAX, - symbol_dsc.flag); + lv_text_get_size(&size, dropdown->symbol, symbol_dsc.font, symbol_dsc.letter_space, symbol_dsc.line_space, LV_COORD_MAX, + symbol_dsc.flag); symbol_w = size.x; symbol_h = size.y; } else { - lv_img_header_t header; - lv_res_t res = lv_img_decoder_get_info(dropdown->symbol, &header); - if(res == LV_RES_OK) { + lv_image_header_t header; + lv_result_t res = lv_image_decoder_get_info(dropdown->symbol, &header); + if(res == LV_RESULT_OK) { symbol_w = header.w; symbol_h = header.h; } @@ -841,21 +840,22 @@ static void draw_main(lv_event_t * e) symbol_area.x2 = symbol_area.x1 + symbol_w - 1; } - if(symbol_type == LV_IMG_SRC_SYMBOL) { + if(symbol_type == LV_IMAGE_SRC_SYMBOL) { symbol_area.y1 = obj->coords.y1 + top; symbol_area.y2 = symbol_area.y1 + symbol_h - 1; - lv_draw_label(draw_ctx, &symbol_dsc, &symbol_area, dropdown->symbol, NULL); + symbol_dsc.text = dropdown->symbol; + lv_draw_label(layer, &symbol_dsc, &symbol_area); } else { symbol_area.y1 = obj->coords.y1 + (lv_obj_get_height(obj) - symbol_h) / 2; symbol_area.y2 = symbol_area.y1 + symbol_h - 1; - lv_draw_img_dsc_t img_dsc; - lv_draw_img_dsc_init(&img_dsc); - lv_obj_init_draw_img_dsc(obj, LV_PART_INDICATOR, &img_dsc); - img_dsc.pivot.x = symbol_w / 2; - img_dsc.pivot.y = symbol_h / 2; - img_dsc.angle = lv_obj_get_style_transform_angle(obj, LV_PART_INDICATOR); - lv_draw_img(draw_ctx, &img_dsc, &symbol_area, dropdown->symbol); + lv_draw_image_dsc_t img_dsc; + lv_draw_image_dsc_init(&img_dsc); + lv_obj_init_draw_image_dsc(obj, LV_PART_INDICATOR, &img_dsc); + lv_point_set(&img_dsc.pivot, symbol_w / 2, symbol_h / 2); + img_dsc.rotation = lv_obj_get_style_transform_rotation(obj, LV_PART_INDICATOR); + img_dsc.src = dropdown->symbol; + lv_draw_image(layer, &img_dsc, &symbol_area); } } @@ -864,8 +864,8 @@ static void draw_main(lv_event_t * e) lv_obj_init_draw_label_dsc(obj, LV_PART_MAIN, &label_dsc); lv_point_t size; - lv_txt_get_size(&size, opt_txt, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, LV_COORD_MAX, - label_dsc.flag); + lv_text_get_size(&size, opt_txt, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, LV_COORD_MAX, + label_dsc.flag); lv_area_t txt_area; txt_area.y1 = obj->coords.y1 + top; @@ -886,50 +886,52 @@ static void draw_main(lv_event_t * e) txt_area.x2 = txt_area.x1 + size.x; } } - lv_draw_label(draw_ctx, &label_dsc, &txt_area, opt_txt, NULL); + label_dsc.text = opt_txt; if(dropdown->text == NULL) { - lv_mem_buf_release((char *)opt_txt); + label_dsc.text_local = true; } + + lv_draw_label(layer, &label_dsc, &txt_area); } static void draw_list(lv_event_t * e) { - lv_obj_t * list_obj = lv_event_get_target(e); + lv_obj_t * list_obj = lv_event_get_current_target(e); lv_dropdown_list_t * list = (lv_dropdown_list_t *)list_obj; lv_obj_t * dropdown_obj = list->dropdown; lv_dropdown_t * dropdown = (lv_dropdown_t *)dropdown_obj; - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); /* Clip area might be too large too to shadow but * the selected option can be drawn on only the background*/ lv_area_t clip_area_core; bool has_common; - has_common = _lv_area_intersect(&clip_area_core, draw_ctx->clip_area, &dropdown->list->coords); + has_common = _lv_area_intersect(&clip_area_core, &layer->_clip_area, &dropdown->list->coords); if(has_common) { - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &clip_area_core; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area_core; if(dropdown->selected_highlight) { if(dropdown->pr_opt_id == dropdown->sel_opt_id) { - draw_box(dropdown_obj, draw_ctx, dropdown->pr_opt_id, LV_STATE_CHECKED | LV_STATE_PRESSED); - draw_box_label(dropdown_obj, draw_ctx, dropdown->pr_opt_id, LV_STATE_CHECKED | LV_STATE_PRESSED); + draw_box(dropdown_obj, layer, dropdown->pr_opt_id, LV_STATE_CHECKED | LV_STATE_PRESSED); + draw_box_label(dropdown_obj, layer, dropdown->pr_opt_id, LV_STATE_CHECKED | LV_STATE_PRESSED); } else { - draw_box(dropdown_obj, draw_ctx, dropdown->pr_opt_id, LV_STATE_PRESSED); - draw_box_label(dropdown_obj, draw_ctx, dropdown->pr_opt_id, LV_STATE_PRESSED); - draw_box(dropdown_obj, draw_ctx, dropdown->sel_opt_id, LV_STATE_CHECKED); - draw_box_label(dropdown_obj, draw_ctx, dropdown->sel_opt_id, LV_STATE_CHECKED); + draw_box(dropdown_obj, layer, dropdown->pr_opt_id, LV_STATE_PRESSED); + draw_box_label(dropdown_obj, layer, dropdown->pr_opt_id, LV_STATE_PRESSED); + draw_box(dropdown_obj, layer, dropdown->sel_opt_id, LV_STATE_CHECKED); + draw_box_label(dropdown_obj, layer, dropdown->sel_opt_id, LV_STATE_CHECKED); } } else { - draw_box(dropdown_obj, draw_ctx, dropdown->pr_opt_id, LV_STATE_PRESSED); - draw_box_label(dropdown_obj, draw_ctx, dropdown->pr_opt_id, LV_STATE_PRESSED); + draw_box(dropdown_obj, layer, dropdown->pr_opt_id, LV_STATE_PRESSED); + draw_box_label(dropdown_obj, layer, dropdown->pr_opt_id, LV_STATE_PRESSED); } - draw_ctx->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } } -static void draw_box(lv_obj_t * dropdown_obj, lv_draw_ctx_t * draw_ctx, uint16_t id, lv_state_t state) +static void draw_box(lv_obj_t * dropdown_obj, lv_layer_t * layer, uint32_t id, lv_state_t state) { if(id == LV_DROPDOWN_PR_NONE) return; @@ -944,8 +946,8 @@ static void draw_box(lv_obj_t * dropdown_obj, lv_draw_ctx_t * draw_ctx, uint16_t /*Draw a rectangle under the selected item*/ const lv_font_t * font = lv_obj_get_style_text_font(list_obj, LV_PART_SELECTED); - lv_coord_t line_space = lv_obj_get_style_text_line_space(list_obj, LV_PART_SELECTED); - lv_coord_t font_h = lv_font_get_line_height(font); + int32_t line_space = lv_obj_get_style_text_line_space(list_obj, LV_PART_SELECTED); + int32_t font_h = lv_font_get_line_height(font); /*Draw the selected*/ lv_obj_t * label = get_label(dropdown_obj); @@ -961,13 +963,13 @@ static void draw_box(lv_obj_t * dropdown_obj, lv_draw_ctx_t * draw_ctx, uint16_t lv_draw_rect_dsc_t sel_rect; lv_draw_rect_dsc_init(&sel_rect); lv_obj_init_draw_rect_dsc(list_obj, LV_PART_SELECTED, &sel_rect); - lv_draw_rect(draw_ctx, &sel_rect, &rect_area); + lv_draw_rect(layer, &sel_rect, &rect_area); list_obj->state = state_ori; list_obj->skip_trans = 0; } -static void draw_box_label(lv_obj_t * dropdown_obj, lv_draw_ctx_t * draw_ctx, uint16_t id, lv_state_t state) +static void draw_box_label(lv_obj_t * dropdown_obj, lv_layer_t * layer, uint32_t id, lv_state_t state) { if(id == LV_DROPDOWN_PR_NONE) return; @@ -990,7 +992,7 @@ static void draw_box_label(lv_obj_t * dropdown_obj, lv_draw_ctx_t * draw_ctx, ui lv_obj_t * label = get_label(dropdown_obj); if(label == NULL) return; - lv_coord_t font_h = lv_font_get_line_height(label_dsc.font); + int32_t font_h = lv_font_get_line_height(label_dsc.font); lv_area_t area_sel; area_sel.y1 = label->coords.y1; @@ -1002,31 +1004,31 @@ static void draw_box_label(lv_obj_t * dropdown_obj, lv_draw_ctx_t * draw_ctx, ui area_sel.x2 = list_obj->coords.x2; lv_area_t mask_sel; bool area_ok; - area_ok = _lv_area_intersect(&mask_sel, draw_ctx->clip_area, &area_sel); + area_ok = _lv_area_intersect(&mask_sel, &layer->_clip_area, &area_sel); if(area_ok) { - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &mask_sel; - lv_draw_label(draw_ctx, &label_dsc, &label->coords, lv_label_get_text(label), NULL); - draw_ctx->clip_area = clip_area_ori; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = mask_sel; + label_dsc.text = lv_label_get_text(label); + lv_draw_label(layer, &label_dsc, &label->coords); + layer->_clip_area = clip_area_ori; } list_obj->state = state_orig; list_obj->skip_trans = 0; } - -static lv_res_t btn_release_handler(lv_obj_t * obj) +static lv_result_t btn_release_handler(lv_obj_t * obj) { lv_dropdown_t * dropdown = (lv_dropdown_t *)obj; - lv_indev_t * indev = lv_indev_get_act(); + lv_indev_t * indev = lv_indev_active(); if(lv_indev_get_scroll_obj(indev) == NULL) { if(lv_dropdown_is_open(obj)) { lv_dropdown_close(obj); if(dropdown->sel_opt_id_orig != dropdown->sel_opt_id) { dropdown->sel_opt_id_orig = dropdown->sel_opt_id; - lv_res_t res; + lv_result_t res; uint32_t id = dropdown->sel_opt_id; /*Just to use uint32_t in event data*/ - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &id); - if(res != LV_RES_OK) return res; + res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, &id); + if(res != LV_RESULT_OK) return res; lv_obj_invalidate(obj); } lv_indev_type_t indev_type = lv_indev_get_type(indev); @@ -1042,21 +1044,21 @@ static lv_res_t btn_release_handler(lv_obj_t * obj) dropdown->sel_opt_id = dropdown->sel_opt_id_orig; lv_obj_invalidate(obj); } - return LV_RES_OK; + return LV_RESULT_OK; } /** * Called when a drop down list is released to open it or set new option * @param list pointer to the drop down list's list - * @return LV_RES_INV if the list is not being deleted in the user callback. Else LV_RES_OK + * @return LV_RESULT_INVALID if the list is not being deleted in the user callback. Else LV_RESULT_OK */ -static lv_res_t list_release_handler(lv_obj_t * list_obj) +static lv_result_t list_release_handler(lv_obj_t * list_obj) { lv_dropdown_list_t * list = (lv_dropdown_list_t *) list_obj; lv_obj_t * dropdown_obj = list->dropdown; lv_dropdown_t * dropdown = (lv_dropdown_t *)dropdown_obj; - lv_indev_t * indev = lv_indev_get_act(); + lv_indev_t * indev = lv_indev_active(); /*Leave edit mode once a new item is selected*/ if(lv_indev_get_type(indev) == LV_INDEV_TYPE_ENCODER) { dropdown->sel_opt_id_orig = dropdown->sel_opt_id; @@ -1080,10 +1082,10 @@ static lv_res_t list_release_handler(lv_obj_t * list_obj) if(dropdown->text == NULL) lv_obj_invalidate(dropdown_obj); uint32_t id = dropdown->sel_opt_id; /*Just to use uint32_t in event data*/ - lv_res_t res = lv_event_send(dropdown_obj, LV_EVENT_VALUE_CHANGED, &id); - if(res != LV_RES_OK) return res; + lv_result_t res = lv_obj_send_event(dropdown_obj, LV_EVENT_VALUE_CHANGED, &id); + if(res != LV_RESULT_OK) return res; - return LV_RES_OK; + return LV_RESULT_OK; } static void list_press_handler(lv_obj_t * list_obj) @@ -1092,7 +1094,7 @@ static void list_press_handler(lv_obj_t * list_obj) lv_obj_t * dropdown_obj = list->dropdown; lv_dropdown_t * dropdown = (lv_dropdown_t *)dropdown_obj; - lv_indev_t * indev = lv_indev_get_act(); + lv_indev_t * indev = lv_indev_active(); if(indev && (lv_indev_get_type(indev) == LV_INDEV_TYPE_POINTER || lv_indev_get_type(indev) == LV_INDEV_TYPE_BUTTON)) { lv_point_t p; lv_indev_get_point(indev, &p); @@ -1101,7 +1103,7 @@ static void list_press_handler(lv_obj_t * list_obj) } } -static uint16_t get_id_on_point(lv_obj_t * dropdown_obj, lv_coord_t y) +static uint32_t get_id_on_point(lv_obj_t * dropdown_obj, int32_t y) { lv_dropdown_t * dropdown = (lv_dropdown_t *)dropdown_obj; lv_obj_t * label = get_label(dropdown_obj); @@ -1109,13 +1111,13 @@ static uint16_t get_id_on_point(lv_obj_t * dropdown_obj, lv_coord_t y) y -= label->coords.y1; const lv_font_t * font = lv_obj_get_style_text_font(label, LV_PART_MAIN); - lv_coord_t font_h = lv_font_get_line_height(font); - lv_coord_t line_space = lv_obj_get_style_text_line_space(label, LV_PART_MAIN); + int32_t font_h = lv_font_get_line_height(font); + int32_t line_space = lv_obj_get_style_text_line_space(label, LV_PART_MAIN); y += line_space / 2; - lv_coord_t h = font_h + line_space; + int32_t h = font_h + line_space; - uint16_t opt = y / h; + uint32_t opt = y / h; if(opt >= dropdown->option_cnt) opt = dropdown->option_cnt - 1; return opt; @@ -1135,10 +1137,10 @@ static void position_to_selected(lv_obj_t * dropdown_obj) if(lv_obj_get_height(label) <= lv_obj_get_content_height(dropdown_obj)) return; const lv_font_t * font = lv_obj_get_style_text_font(label, LV_PART_MAIN); - lv_coord_t font_h = lv_font_get_line_height(font); - lv_coord_t line_space = lv_obj_get_style_text_line_space(label, LV_PART_MAIN); - lv_coord_t unit_h = font_h + line_space; - lv_coord_t line_y1 = dropdown->sel_opt_id * unit_h; + int32_t font_h = lv_font_get_line_height(font); + int32_t line_space = lv_obj_get_style_text_line_space(label, LV_PART_MAIN); + int32_t unit_h = font_h + line_space; + int32_t line_y1 = dropdown->sel_opt_id * unit_h; /*Scroll to the selected option*/ lv_obj_scroll_to_y(dropdown->list, line_y1, LV_ANIM_OFF); diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.h b/lib/libesp32_lvgl/lvgl/src/widgets/dropdown/lv_dropdown.h similarity index 91% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.h rename to lib/libesp32_lvgl/lvgl/src/widgets/dropdown/lv_dropdown.h index 0c55e862c..614f5f192 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_dropdown.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/dropdown/lv_dropdown.h @@ -13,7 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../lv_conf_internal.h" +#include "../../lv_conf_internal.h" #if LV_USE_DROPDOWN != 0 @@ -23,7 +23,7 @@ extern "C" { #error "lv_dropdown: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1)" #endif -#include "../widgets/lv_label.h" +#include "../label/lv_label.h" /********************* * DEFINES @@ -41,10 +41,10 @@ typedef struct { const char * text; /**< Text to display on the dropdown's button*/ const void * symbol; /**< Arrow or other icon when the drop-down list is closed*/ char * options; /**< Options in a '\n' separated list*/ - uint16_t option_cnt; /**< Number of options*/ - uint16_t sel_opt_id; /**< Index of the currently selected option*/ - uint16_t sel_opt_id_orig; /**< Store the original index on focus*/ - uint16_t pr_opt_id; /**< Index of the currently pressed option*/ + uint32_t option_cnt; /**< Number of options*/ + uint32_t sel_opt_id; /**< Index of the currently selected option*/ + uint32_t sel_opt_id_orig; /**< Store the original index on focus*/ + uint32_t pr_opt_id; /**< Index of the currently pressed option*/ lv_dir_t dir : 4; /**< Direction in which the list should open*/ uint8_t static_txt : 1; /**< 1: Only a pointer is saved in `options`*/ uint8_t selected_highlight: 1; /**< 1: Make the selected option highlighted in the list*/ @@ -55,8 +55,8 @@ typedef struct { lv_obj_t * dropdown; } lv_dropdown_list_t; -extern const lv_obj_class_t lv_dropdown_class; -extern const lv_obj_class_t lv_dropdownlist_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_dropdown_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_dropdownlist_class; /********************** * GLOBAL PROTOTYPES @@ -117,7 +117,7 @@ void lv_dropdown_clear_options(lv_obj_t * obj); * @param obj pointer to drop-down list object * @param sel_opt id of the selected option (0 ... number of option - 1); */ -void lv_dropdown_set_selected(lv_obj_t * obj, uint16_t sel_opt); +void lv_dropdown_set_selected(lv_obj_t * obj, uint32_t sel_opt); /** * Set the direction of the a drop-down list @@ -172,14 +172,14 @@ const char * lv_dropdown_get_options(const lv_obj_t * obj); * @param obj pointer to drop-down list object * @return index of the selected option (0 ... number of option - 1); */ -uint16_t lv_dropdown_get_selected(const lv_obj_t * obj); +uint32_t lv_dropdown_get_selected(const lv_obj_t * obj); /** * Get the total number of options * @param obj pointer to drop-down list object * @return the total number of options in the list */ -uint16_t lv_dropdown_get_option_cnt(const lv_obj_t * obj); +uint32_t lv_dropdown_get_option_count(const lv_obj_t * obj); /** * Get the current selected option as a string @@ -224,7 +224,7 @@ lv_dir_t lv_dropdown_get_dir(const lv_obj_t * obj); /** * Open the drop.down list - * @param obj pointer to drop-down list object + * @param dropdown_obj pointer to drop-down list object */ void lv_dropdown_open(lv_obj_t * dropdown_obj); diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/image/lv_image.c b/lib/libesp32_lvgl/lvgl/src/widgets/image/lv_image.c new file mode 100644 index 000000000..1f4984cdd --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/image/lv_image.c @@ -0,0 +1,817 @@ +/** + * @file lv_img.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_image.h" +#if LV_USE_IMAGE != 0 + +#include "../../stdlib/lv_string.h" + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_image_class + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_image_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_image_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_image_event(const lv_obj_class_t * class_p, lv_event_t * e); +static void draw_image(lv_event_t * e); +static void scale_update(lv_obj_t * obj, int32_t scale_x, int32_t scale_y); +static void update_align(lv_obj_t * obj); + +#if LV_USE_OBJ_PROPERTY +static const lv_property_ops_t properties[] = { + { + .id = LV_PROPERTY_IMAGE_SRC, + .setter = lv_image_set_src, + .getter = lv_image_get_src, + }, + { + .id = LV_PROPERTY_IMAGE_OFFSET_X, + .setter = lv_image_set_offset_x, + .getter = lv_image_get_offset_x, + }, + { + .id = LV_PROPERTY_IMAGE_OFFSET_Y, + .setter = lv_image_set_offset_y, + .getter = lv_image_get_offset_y, + }, + { + .id = LV_PROPERTY_IMAGE_ROTATION, + .setter = lv_image_set_rotation, + .getter = lv_image_get_rotation, + }, + { + .id = LV_PROPERTY_IMAGE_PIVOT, + .setter = _lv_image_set_pivot, + .getter = lv_image_get_pivot, + }, + { + .id = LV_PROPERTY_IMAGE_SCALE, + .setter = lv_image_set_scale, + .getter = lv_image_get_scale, + }, + { + .id = LV_PROPERTY_IMAGE_SCALE_X, + .setter = lv_image_set_scale_x, + .getter = lv_image_get_scale_x, + }, + { + .id = LV_PROPERTY_IMAGE_SCALE_Y, + .setter = lv_image_set_scale_y, + .getter = lv_image_get_scale_y, + }, + { + .id = LV_PROPERTY_IMAGE_BLEND_MODE, + .setter = lv_image_set_blend_mode, + .getter = lv_image_get_blend_mode, + }, + { + .id = LV_PROPERTY_IMAGE_ANTIALIAS, + .setter = lv_image_set_antialias, + .getter = lv_image_get_antialias, + }, + { + .id = LV_PROPERTY_IMAGE_ALIGN, + .setter = lv_image_set_inner_align, + .getter = lv_image_get_align, + }, +}; +#endif + +/********************** + * STATIC VARIABLES + **********************/ +const lv_obj_class_t lv_image_class = { + .constructor_cb = lv_image_constructor, + .destructor_cb = lv_image_destructor, + .event_cb = lv_image_event, + .width_def = LV_SIZE_CONTENT, + .height_def = LV_SIZE_CONTENT, + .instance_size = sizeof(lv_image_t), + .base_class = &lv_obj_class, + .name = "image", +#if LV_USE_OBJ_PROPERTY + .prop_index_start = LV_PROPERTY_IMAGE_START, + .prop_index_end = LV_PROPERTY_IMAGE_END, + .properties = properties, + .properties_count = sizeof(properties) / sizeof(properties[0]), +#endif +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_image_create(lv_obj_t * parent) +{ + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + return obj; +} + +/*===================== + * Setter functions + *====================*/ + +void lv_image_set_src(lv_obj_t * obj, const void * src) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_obj_invalidate(obj); + + lv_image_src_t src_type = lv_image_src_get_type(src); + lv_image_t * img = (lv_image_t *)obj; + +#if LV_USE_LOG && LV_LOG_LEVEL >= LV_LOG_LEVEL_INFO + switch(src_type) { + case LV_IMAGE_SRC_FILE: + LV_LOG_TRACE("`LV_IMAGE_SRC_FILE` type found"); + break; + case LV_IMAGE_SRC_VARIABLE: + LV_LOG_TRACE("`LV_IMAGE_SRC_VARIABLE` type found"); + break; + case LV_IMAGE_SRC_SYMBOL: + LV_LOG_TRACE("`LV_IMAGE_SRC_SYMBOL` type found"); + break; + default: + LV_LOG_WARN("unknown type"); + } +#endif + + /*If the new source type is unknown free the memories of the old source*/ + if(src_type == LV_IMAGE_SRC_UNKNOWN) { + LV_LOG_WARN("unknown image type"); + if(img->src_type == LV_IMAGE_SRC_SYMBOL || img->src_type == LV_IMAGE_SRC_FILE) { + lv_free((void *)img->src); + } + img->src = NULL; + img->src_type = LV_IMAGE_SRC_UNKNOWN; + return; + } + + lv_image_header_t header; + lv_result_t res = lv_image_decoder_get_info(src, &header); + if(res != LV_RESULT_OK) { +#if LV_USE_LOG + char buf[24]; + LV_LOG_WARN("failed to get image info: %s", + src_type == LV_IMAGE_SRC_FILE ? (const char *)src : (lv_snprintf(buf, sizeof(buf), "%p", src), buf)); +#endif /*LV_USE_LOG*/ + return; + } + + /*Save the source*/ + if(src_type == LV_IMAGE_SRC_VARIABLE) { + /*If memory was allocated because of the previous `src_type` then free it*/ + if(img->src_type == LV_IMAGE_SRC_FILE || img->src_type == LV_IMAGE_SRC_SYMBOL) { + lv_free((void *)img->src); + } + img->src = src; + } + else if(src_type == LV_IMAGE_SRC_FILE || src_type == LV_IMAGE_SRC_SYMBOL) { + /*If the new and the old src are the same then it was only a refresh.*/ + if(img->src != src) { + const void * old_src = NULL; + /*If memory was allocated because of the previous `src_type` then save its pointer and free after allocation. + *It's important to allocate first to be sure the new data will be on a new address. + *Else `img_cache` wouldn't see the change in source.*/ + if(img->src_type == LV_IMAGE_SRC_FILE || img->src_type == LV_IMAGE_SRC_SYMBOL) { + old_src = img->src; + } + char * new_str = lv_strdup(src); + LV_ASSERT_MALLOC(new_str); + if(new_str == NULL) return; + img->src = new_str; + + if(old_src) lv_free((void *)old_src); + } + } + + if(src_type == LV_IMAGE_SRC_SYMBOL) { + /*`lv_image_dsc_get_info` couldn't set the width and height of a font so set it here*/ + const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); + int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + lv_point_t size; + lv_text_get_size(&size, src, font, letter_space, line_space, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + header.w = size.x; + header.h = size.y; + } + + img->src_type = src_type; + img->w = header.w; + img->h = header.h; + img->cf = header.cf; + + lv_obj_refresh_self_size(obj); + + update_align(obj); + + /*Provide enough room for the rotated corners*/ + if(img->rotation || img->scale_x != LV_SCALE_NONE || img->scale_y != LV_SCALE_NONE) { + lv_obj_refresh_ext_draw_size(obj); + } + + lv_obj_invalidate(obj); +} + +void lv_image_set_offset_x(lv_obj_t * obj, int32_t x) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + img->offset.x = x; + lv_obj_invalidate(obj); +} + +void lv_image_set_offset_y(lv_obj_t * obj, int32_t y) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + img->offset.y = y; + lv_obj_invalidate(obj); +} + +void lv_image_set_rotation(lv_obj_t * obj, int32_t angle) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + if(img->align > _LV_IMAGE_ALIGN_AUTO_TRANSFORM) { + angle = 0; + } + else { + while(angle >= 3600) angle -= 3600; + while(angle < 0) angle += 3600; + } + + if((uint32_t)angle == img->rotation) return; + + lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/ + int32_t w = lv_obj_get_width(obj); + int32_t h = lv_obj_get_height(obj); + lv_area_t a; + lv_point_t pivot_px; + lv_image_get_pivot(obj, &pivot_px); + _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->scale_x, img->scale_y, &pivot_px); + a.x1 += obj->coords.x1; + a.y1 += obj->coords.y1; + a.x2 += obj->coords.x1; + a.y2 += obj->coords.y1; + lv_obj_invalidate_area(obj, &a); + + img->rotation = angle; + + /* Disable invalidations because lv_obj_refresh_ext_draw_size would invalidate + * the whole ext draw area */ + lv_display_t * disp = lv_obj_get_display(obj); + lv_display_enable_invalidation(disp, false); + lv_obj_refresh_ext_draw_size(obj); + lv_display_enable_invalidation(disp, true); + + _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->scale_x, img->scale_y, &pivot_px); + a.x1 += obj->coords.x1; + a.y1 += obj->coords.y1; + a.x2 += obj->coords.x1; + a.y2 += obj->coords.y1; + lv_obj_invalidate_area(obj, &a); +} + +void lv_image_set_pivot(lv_obj_t * obj, int32_t x, int32_t y) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + if(img->align > _LV_IMAGE_ALIGN_AUTO_TRANSFORM) { + x = 0; + y = 0; + } + + if(img->pivot.x == x && img->pivot.y == y) return; + + lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/ + int32_t w = lv_obj_get_width(obj); + int32_t h = lv_obj_get_height(obj); + lv_area_t a; + lv_point_t pivot_px; + lv_image_get_pivot(obj, &pivot_px); + _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->scale_x, img->scale_y, &pivot_px); + a.x1 += obj->coords.x1; + a.y1 += obj->coords.y1; + a.x2 += obj->coords.x1; + a.y2 += obj->coords.y1; + lv_obj_invalidate_area(obj, &a); + + lv_point_set(&img->pivot, x, y); + + /* Disable invalidations because lv_obj_refresh_ext_draw_size would invalidate + * the whole ext draw area */ + lv_display_t * disp = lv_obj_get_display(obj); + lv_display_enable_invalidation(disp, false); + lv_obj_refresh_ext_draw_size(obj); + lv_display_enable_invalidation(disp, true); + + lv_image_get_pivot(obj, &pivot_px); + _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->scale_x, img->scale_y, &pivot_px); + a.x1 += obj->coords.x1; + a.y1 += obj->coords.y1; + a.x2 += obj->coords.x1; + a.y2 += obj->coords.y1; + lv_obj_invalidate_area(obj, &a); +} + +void lv_image_set_scale(lv_obj_t * obj, uint32_t zoom) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + /*If scale is set internally, do no overwrite it*/ + if(img->align > _LV_IMAGE_ALIGN_AUTO_TRANSFORM) return; + + if(zoom == img->scale_x && zoom == img->scale_y) return; + + if(zoom == 0) zoom = 1; + + scale_update(obj, zoom, zoom); +} + +void lv_image_set_scale_x(lv_obj_t * obj, uint32_t zoom) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + /*If scale is set internally, do no overwrite it*/ + if(img->align > _LV_IMAGE_ALIGN_AUTO_TRANSFORM) return; + + if(zoom == img->scale_x) return; + + if(zoom == 0) zoom = 1; + + scale_update(obj, zoom, img->scale_y); +} + +void lv_image_set_scale_y(lv_obj_t * obj, uint32_t zoom) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + /*If scale is set internally, do no overwrite it*/ + if(img->align > _LV_IMAGE_ALIGN_AUTO_TRANSFORM) return; + + if(zoom == img->scale_y) return; + + if(zoom == 0) zoom = 1; + + scale_update(obj, img->scale_x, zoom); +} + +void lv_image_set_blend_mode(lv_obj_t * obj, lv_blend_mode_t blend_mode) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + /*If scale is set internally, do no overwrite it*/ + if(img->blend_mode == blend_mode) return; + + img->blend_mode = blend_mode; + + lv_obj_invalidate(obj); +} + +void lv_image_set_antialias(lv_obj_t * obj, bool antialias) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + if(antialias == img->antialias) return; + + img->antialias = antialias; + lv_obj_invalidate(obj); +} + +void lv_image_set_inner_align(lv_obj_t * obj, lv_image_align_t align) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + if(align == img->align) return; + + img->align = align; + + update_align(obj); + + lv_obj_invalidate(obj); +} + +/*===================== + * Getter functions + *====================*/ + +const void * lv_image_get_src(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + return img->src; +} + +int32_t lv_image_get_offset_x(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + return img->offset.x; +} + +int32_t lv_image_get_offset_y(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + return img->offset.y; +} + +int32_t lv_image_get_rotation(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + return img->rotation; +} + +void lv_image_get_pivot(lv_obj_t * obj, lv_point_t * pivot) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + pivot->x = lv_pct_to_px(img->pivot.x, img->w); + pivot->y = lv_pct_to_px(img->pivot.y, img->h); +} + +int32_t lv_image_get_scale(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + return img->scale_x; +} + +int32_t lv_image_get_scale_x(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + return img->scale_x; +} + +int32_t lv_image_get_scale_y(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + return img->scale_y; +} + +lv_blend_mode_t lv_image_get_blend_mode(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + return img->blend_mode; +} + +bool lv_image_get_antialias(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + return img->antialias ? true : false; +} + +lv_image_align_t lv_image_get_inner_align(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + return img->align; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_image_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + LV_TRACE_OBJ_CREATE("begin"); + + lv_image_t * img = (lv_image_t *)obj; + + img->src = NULL; + img->src_type = LV_IMAGE_SRC_UNKNOWN; + img->cf = LV_COLOR_FORMAT_UNKNOWN; + img->w = lv_obj_get_width(obj); + img->h = lv_obj_get_height(obj); + img->rotation = 0; + img->scale_x = LV_SCALE_NONE; + img->scale_y = LV_SCALE_NONE; + img->antialias = LV_COLOR_DEPTH > 8 ? 1 : 0; + lv_point_set(&img->offset, 0, 0); + lv_point_set(&img->pivot, LV_PCT(50), LV_PCT(50)); /*Default pivot to image center*/ + img->align = LV_IMAGE_ALIGN_CENTER; + + lv_obj_remove_flag(obj, LV_OBJ_FLAG_CLICKABLE); + lv_obj_add_flag(obj, LV_OBJ_FLAG_ADV_HITTEST); + + LV_TRACE_OBJ_CREATE("finished"); +} + +static void lv_image_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + lv_image_t * img = (lv_image_t *)obj; + if(img->src_type == LV_IMAGE_SRC_FILE || img->src_type == LV_IMAGE_SRC_SYMBOL) { + lv_free((void *)img->src); + img->src = NULL; + img->src_type = LV_IMAGE_SRC_UNKNOWN; + } +} + +static void lv_image_event(const lv_obj_class_t * class_p, lv_event_t * e) +{ + LV_UNUSED(class_p); + + lv_event_code_t code = lv_event_get_code(e); + + /*Call the ancestor's event handler*/ + lv_result_t res = lv_obj_event_base(MY_CLASS, e); + if(res != LV_RESULT_OK) return; + + lv_obj_t * obj = lv_event_get_current_target(e); + lv_image_t * img = (lv_image_t *)obj; + lv_point_t pivot_px; + lv_image_get_pivot(obj, &pivot_px); + + if(code == LV_EVENT_STYLE_CHANGED) { + /*Refresh the file name to refresh the symbol text size*/ + if(img->src_type == LV_IMAGE_SRC_SYMBOL) { + lv_image_set_src(obj, img->src); + } + else { + /*With transformation it might change*/ + lv_obj_refresh_ext_draw_size(obj); + } + } + else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { + + int32_t * s = lv_event_get_param(e); + + /*If the image has angle provide enough room for the rotated corners*/ + if(img->rotation || img->scale_x != LV_SCALE_NONE || img->scale_y != LV_SCALE_NONE) { + lv_area_t a; + int32_t w = lv_obj_get_width(obj); + int32_t h = lv_obj_get_height(obj); + _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->scale_x, img->scale_y, &pivot_px); + *s = LV_MAX(*s, -a.x1); + *s = LV_MAX(*s, -a.y1); + *s = LV_MAX(*s, a.x2 - w); + *s = LV_MAX(*s, a.y2 - h); + } + } + else if(code == LV_EVENT_HIT_TEST) { + lv_hit_test_info_t * info = lv_event_get_param(e); + + /*If the object is exactly image sized (not cropped, not mosaic) and transformed + *perform hit test on its transformed area*/ + if(img->w == lv_obj_get_width(obj) && img->h == lv_obj_get_height(obj) && + (img->scale_x != LV_SCALE_NONE || img->scale_y != LV_SCALE_NONE || + img->rotation != 0 || img->pivot.x != img->w / 2 || img->pivot.y != img->h / 2)) { + + int32_t w = lv_obj_get_width(obj); + int32_t h = lv_obj_get_height(obj); + lv_area_t coords; + _lv_image_buf_get_transformed_area(&coords, w, h, img->rotation, img->scale_x, img->scale_y, &pivot_px); + coords.x1 += obj->coords.x1; + coords.y1 += obj->coords.y1; + coords.x2 += obj->coords.x1; + coords.y2 += obj->coords.y1; + + info->res = _lv_area_is_point_on(&coords, info->point, 0); + } + else { + lv_area_t a; + lv_obj_get_click_area(obj, &a); + info->res = _lv_area_is_point_on(&a, info->point, 0); + } + } + else if(code == LV_EVENT_GET_SELF_SIZE) { + lv_point_t * p = lv_event_get_param(e); + p->x = img->w; + p->y = img->h; + } + else if(code == LV_EVENT_DRAW_MAIN || code == LV_EVENT_DRAW_POST || code == LV_EVENT_COVER_CHECK) { + draw_image(e); + } +} + +static void draw_image(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * obj = lv_event_get_current_target(e); + lv_image_t * img = (lv_image_t *)obj; + if(code == LV_EVENT_COVER_CHECK) { + lv_cover_check_info_t * info = lv_event_get_param(e); + if(info->res == LV_COVER_RES_MASKED) return; + if(img->src_type == LV_IMAGE_SRC_UNKNOWN || img->src_type == LV_IMAGE_SRC_SYMBOL) { + info->res = LV_COVER_RES_NOT_COVER; + return; + } + + /*Non true color format might have "holes"*/ + if(lv_color_format_has_alpha(img->cf)) { + info->res = LV_COVER_RES_NOT_COVER; + return; + } + + /*With not LV_OPA_COVER images can't cover an area */ + if(lv_obj_get_style_image_opa(obj, LV_PART_MAIN) != LV_OPA_COVER) { + info->res = LV_COVER_RES_NOT_COVER; + return; + } + + if(img->rotation != 0) { + info->res = LV_COVER_RES_NOT_COVER; + return; + } + + if(img->scale_x == LV_SCALE_NONE && img->scale_y == LV_SCALE_NONE) { + if(_lv_area_is_in(info->area, &obj->coords, 0) == false) { + info->res = LV_COVER_RES_NOT_COVER; + return; + } + } + else { + lv_area_t a; + lv_point_t pivot_px; + lv_image_get_pivot(obj, &pivot_px); + _lv_image_buf_get_transformed_area(&a, lv_obj_get_width(obj), lv_obj_get_height(obj), 0, img->scale_x, img->scale_y, + &pivot_px); + a.x1 += obj->coords.x1; + a.y1 += obj->coords.y1; + a.x2 += obj->coords.x1; + a.y2 += obj->coords.y1; + + if(_lv_area_is_in(info->area, &a, 0) == false) { + info->res = LV_COVER_RES_NOT_COVER; + return; + } + } + } + else if(code == LV_EVENT_DRAW_MAIN) { + + if(img->h == 0 || img->w == 0) return; + if(img->scale_x == 0 || img->scale_y == 0) return; + + lv_layer_t * layer = lv_event_get_layer(e); + + if(img->src_type == LV_IMAGE_SRC_FILE || img->src_type == LV_IMAGE_SRC_VARIABLE) { + lv_draw_image_dsc_t draw_dsc; + lv_draw_image_dsc_init(&draw_dsc); + lv_obj_init_draw_image_dsc(obj, LV_PART_MAIN, &draw_dsc); + + lv_area_t clip_area_ori = layer->_clip_area; + + lv_image_get_pivot(obj, &draw_dsc.pivot); + draw_dsc.scale_x = img->scale_x; + draw_dsc.scale_y = img->scale_y; + draw_dsc.rotation = img->rotation; + draw_dsc.antialias = img->antialias; + draw_dsc.blend_mode = img->blend_mode; + draw_dsc.src = img->src; + + lv_area_t img_area = {obj->coords.x1, obj->coords.y1, + obj->coords.x1 + img->w - 1, obj->coords.y1 + img->h - 1 + }; + if(img->align < _LV_IMAGE_ALIGN_AUTO_TRANSFORM) { + lv_area_align(&obj->coords, &img_area, img->align, img->offset.x, img->offset.y); + } + else if(img->align == LV_IMAGE_ALIGN_TILE) { + _lv_area_intersect(&layer->_clip_area, &layer->_clip_area, &obj->coords); + lv_area_move(&img_area, img->offset.x, img->offset.y); + + lv_area_move(&img_area, + ((layer->_clip_area.x1 - img_area.x1 - (img->w - 1)) / img->w) * img->w, + ((layer->_clip_area.y1 - img_area.y1 - (img->h - 1)) / img->h) * img->h); + draw_dsc.tile = 1; + } + + lv_draw_image(layer, &draw_dsc, &img_area); + layer->_clip_area = clip_area_ori; + + } + else if(img->src_type == LV_IMAGE_SRC_SYMBOL) { + lv_draw_label_dsc_t label_dsc; + lv_draw_label_dsc_init(&label_dsc); + lv_obj_init_draw_label_dsc(obj, LV_PART_MAIN, &label_dsc); + label_dsc.text = img->src; + lv_draw_label(layer, &label_dsc, &obj->coords); + } + else if(img->src == NULL) { + /*Do not need to draw image when src is NULL*/ + LV_LOG_WARN("image source is NULL"); + } + else { + /*Trigger the error handler of image draw*/ + LV_LOG_WARN("image source type is unknown"); + } + } +} + +static void scale_update(lv_obj_t * obj, int32_t scale_x, int32_t scale_y) +{ + lv_image_t * img = (lv_image_t *)obj; + + lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/ + int32_t w = lv_obj_get_width(obj); + int32_t h = lv_obj_get_height(obj); + lv_area_t a; + lv_point_t pivot_px; + lv_image_get_pivot(obj, &pivot_px); + _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->scale_x, img->scale_y, &pivot_px); + a.x1 += obj->coords.x1 - 1; + a.y1 += obj->coords.y1 - 1; + a.x2 += obj->coords.x1 + 1; + a.y2 += obj->coords.y1 + 1; + lv_obj_invalidate_area(obj, &a); + + img->scale_x = scale_x; + img->scale_y = scale_y; + + /* Disable invalidations because lv_obj_refresh_ext_draw_size would invalidate + * the whole ext draw area */ + lv_display_t * disp = lv_obj_get_display(obj); + lv_display_enable_invalidation(disp, false); + lv_obj_refresh_ext_draw_size(obj); + lv_display_enable_invalidation(disp, true); + + _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->scale_x, img->scale_y, &pivot_px); + a.x1 += obj->coords.x1 - 1; + a.y1 += obj->coords.y1 - 1; + a.x2 += obj->coords.x1 + 1; + a.y2 += obj->coords.y1 + 1; + lv_obj_invalidate_area(obj, &a); +} + +static void update_align(lv_obj_t * obj) +{ + lv_image_t * img = (lv_image_t *)obj; + if(img->align == LV_IMAGE_ALIGN_STRETCH) { + lv_image_set_rotation(obj, 0); + lv_image_set_pivot(obj, 0, 0); + int32_t scale_x = lv_obj_get_width(obj) * LV_SCALE_NONE / img->w; + int32_t scale_y = lv_obj_get_height(obj) * LV_SCALE_NONE / img->h; + scale_update(obj, scale_x, scale_y); + } + else if(img->align == LV_IMAGE_ALIGN_TILE) { + lv_image_set_rotation(obj, 0); + lv_image_set_pivot(obj, 0, 0); + scale_update(obj, LV_SCALE_NONE, LV_SCALE_NONE); + + } +} +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/image/lv_image.h b/lib/libesp32_lvgl/lvgl/src/widgets/image/lv_image.h new file mode 100644 index 000000000..f02696d67 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/image/lv_image.h @@ -0,0 +1,330 @@ +/** + * @file lv_img.h + * + */ + +#ifndef LV_IMAGE_H +#define LV_IMAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" + +#if LV_USE_IMAGE != 0 + +/*Testing of dependencies*/ +#if LV_USE_LABEL == 0 +#error "lv_img: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1)" +#endif + +#include "../../core/lv_obj.h" +#include "../../misc/lv_fs.h" +#include "../../draw/lv_draw.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/** + * Data of image + */ +typedef struct { + lv_obj_t obj; + const void * src; /**< Image source: Pointer to an array or a file or a symbol*/ + lv_point_t offset; + int32_t w; /**< Width of the image (Handled by the library)*/ + int32_t h; /**< Height of the image (Handled by the library)*/ + uint32_t rotation; /**< Rotation angle of the image*/ + uint32_t scale_x; /**< 256 means no zoom, 512 double size, 128 half size*/ + uint32_t scale_y; /**< 256 means no zoom, 512 double size, 128 half size*/ + lv_point_t pivot; /**< Rotation center of the image*/ + uint32_t src_type : 2; /**< See: lv_image_src_t*/ + uint32_t cf : 5; /**< Color format from `lv_color_format_t`*/ + uint32_t antialias : 1; /**< Apply anti-aliasing in transformations (rotate, zoom)*/ + uint32_t align: 4; /**< Image size mode when image size and object size is different. See `lv_image_align_t`*/ + uint32_t blend_mode: 4; /**< Element of `lv_blend_mode_t`*/ +} lv_image_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_image_class; + +/** + * Image size mode, when image size and object size is different + */ +enum _lv_image_align_t { + LV_IMAGE_ALIGN_DEFAULT = 0, + LV_IMAGE_ALIGN_TOP_LEFT, + LV_IMAGE_ALIGN_TOP_MID, + LV_IMAGE_ALIGN_TOP_RIGHT, + LV_IMAGE_ALIGN_BOTTOM_LEFT, + LV_IMAGE_ALIGN_BOTTOM_MID, + LV_IMAGE_ALIGN_BOTTOM_RIGHT, + LV_IMAGE_ALIGN_LEFT_MID, + LV_IMAGE_ALIGN_RIGHT_MID, + LV_IMAGE_ALIGN_CENTER, + _LV_IMAGE_ALIGN_AUTO_TRANSFORM, + LV_IMAGE_ALIGN_STRETCH, + LV_IMAGE_ALIGN_TILE, +}; + +#ifdef DOXYGEN +typedef _lv_image_align_t lv_image_align_t; +#else +typedef uint8_t lv_image_align_t; +#endif /*DOXYGEN*/ + +#if LV_USE_OBJ_PROPERTY +enum { + LV_PROPERTY_ID(IMAGE, SRC, LV_PROPERTY_TYPE_IMGSRC, 0), + LV_PROPERTY_ID(IMAGE, OFFSET_X, LV_PROPERTY_TYPE_INT, 1), + LV_PROPERTY_ID(IMAGE, OFFSET_Y, LV_PROPERTY_TYPE_INT, 2), + LV_PROPERTY_ID(IMAGE, ROTATION, LV_PROPERTY_TYPE_INT, 3), + LV_PROPERTY_ID(IMAGE, PIVOT, LV_PROPERTY_TYPE_POINTER, 4), + LV_PROPERTY_ID(IMAGE, SCALE, LV_PROPERTY_TYPE_INT, 5), + LV_PROPERTY_ID(IMAGE, SCALE_X, LV_PROPERTY_TYPE_INT, 6), + LV_PROPERTY_ID(IMAGE, SCALE_Y, LV_PROPERTY_TYPE_INT, 7), + LV_PROPERTY_ID(IMAGE, BLEND_MODE, LV_PROPERTY_TYPE_INT, 8), + LV_PROPERTY_ID(IMAGE, ANTIALIAS, LV_PROPERTY_TYPE_INT, 9), + LV_PROPERTY_ID(IMAGE, ALIGN, LV_PROPERTY_TYPE_INT, 10), + LV_PROPERTY_IMAGE_END, +}; +#endif + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an image object + * @param parent pointer to an object, it will be the parent of the new image + * @return pointer to the created image + */ +lv_obj_t * lv_image_create(lv_obj_t * parent); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the image data to display on the object + * @param obj pointer to an image object + * @param src 1) pointer to an ::lv_image_dsc_t descriptor (converted by LVGL's image converter) (e.g. &my_img) or + * 2) path to an image file (e.g. "S:/dir/img.bin")or + * 3) a SYMBOL (e.g. LV_SYMBOL_OK) + */ +void lv_image_set_src(lv_obj_t * obj, const void * src); + +/** + * Set an offset for the source of an image so the image will be displayed from the new origin. + * @param obj pointer to an image + * @param x the new offset along x axis. + */ +void lv_image_set_offset_x(lv_obj_t * obj, int32_t x); + +/** + * Set an offset for the source of an image. + * so the image will be displayed from the new origin. + * @param obj pointer to an image + * @param y the new offset along y axis. + */ +void lv_image_set_offset_y(lv_obj_t * obj, int32_t y); + +/** + * Set the rotation angle of the image. + * The image will be rotated around the set pivot set by `lv_image_set_pivot()` + * Note that indexed and alpha only images can't be transformed. + * @param obj pointer to an image object + * @param angle rotation in degree with 0.1 degree resolution (0..3600: clock wise) + * @note if image_align is `LV_IMAGE_ALIGN_STRETCH` or `LV_IMAGE_ALIGN_FIT` + * rotation will be set to 0 automatically. + * + */ +void lv_image_set_rotation(lv_obj_t * obj, int32_t angle); + +/** + * Set the rotation center of the image. + * The image will be rotated around this point. + * x, y can be set with value of LV_PCT, lv_image_get_pivot will return the true pixel coordinate of pivot in this case. + * @param obj pointer to an image object + * @param x rotation center x of the image + * @param y rotation center y of the image + */ +void lv_image_set_pivot(lv_obj_t * obj, int32_t x, int32_t y); + +/** + * Set pivot similar to get_pivot + */ +static inline void _lv_image_set_pivot(lv_obj_t * obj, lv_point_t * pivot) +{ + lv_image_set_pivot(obj, pivot->x, pivot->y); +} + +/** + * Set the zoom factor of the image. + * Note that indexed and alpha only images can't be transformed. + * @param img pointer to an image object + * @param zoom the zoom factor. + * @example 256 or LV_ZOOM_IMAGE_NONE for no zoom + * @example <256: scale down + * @example >256 scale up + * @example 128 half size + * @example 512 double size + */ +void lv_image_set_scale(lv_obj_t * obj, uint32_t zoom); + +/** + * Set the horizontal zoom factor of the image. + * Note that indexed and alpha only images can't be transformed. + * @param img pointer to an image object + * @param zoom the zoom factor. + * @example 256 or LV_ZOOM_IMAGE_NONE for no zoom + * @example <256: scale down + * @example >256 scale up + * @example 128 half size + * @example 512 double size + */ +void lv_image_set_scale_x(lv_obj_t * obj, uint32_t zoom); + +/** + * Set the vertical zoom factor of the image. + * Note that indexed and alpha only images can't be transformed. + * @param img pointer to an image object + * @param zoom the zoom factor. + * @example 256 or LV_ZOOM_IMAGE_NONE for no zoom + * @example <256: scale down + * @example >256 scale up + * @example 128 half size + * @example 512 double size + */ +void lv_image_set_scale_y(lv_obj_t * obj, uint32_t zoom); + +/** + * Set the blend mode of an image. + * @param obj pointer to an image object + * @param blend_mode the new blend mode + */ +void lv_image_set_blend_mode(lv_obj_t * obj, lv_blend_mode_t blend_mode); + +/** + * Enable/disable anti-aliasing for the transformations (rotate, zoom) or not. + * The quality is better with anti-aliasing looks better but slower. + * @param obj pointer to an image object + * @param antialias true: anti-aliased; false: not anti-aliased + */ +void lv_image_set_antialias(lv_obj_t * obj, bool antialias); + +/** + * Set the image object size mode. + * @param obj pointer to an image object + * @param align the new align mode. + * @note if image_align is `LV_IMAGE_ALIGN_STRETCH` or `LV_IMAGE_ALIGN_FIT` + * rotation, scale and pivot will be overwritten and controlled internally. + */ +void lv_image_set_inner_align(lv_obj_t * obj, lv_image_align_t align); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the source of the image + * @param obj pointer to an image object + * @return the image source (symbol, file name or ::lv-img_dsc_t for C arrays) + */ +const void * lv_image_get_src(lv_obj_t * obj); + +/** + * Get the offset's x attribute of the image object. + * @param obj pointer to an image + * @return offset X value. + */ +int32_t lv_image_get_offset_x(lv_obj_t * obj); + +/** + * Get the offset's y attribute of the image object. + * @param obj pointer to an image + * @return offset Y value. + */ +int32_t lv_image_get_offset_y(lv_obj_t * obj); + +/** + * Get the rotation of the image. + * @param obj pointer to an image object + * @return rotation in 0.1 degrees (0..3600) + * @note if image_align is `LV_IMAGE_ALIGN_STRETCH` or `LV_IMAGE_ALIGN_FIT` + * rotation will be set to 0 automatically. + */ +int32_t lv_image_get_rotation(lv_obj_t * obj); + +/** + * Get the pivot (rotation center) of the image. + * If pivot is set with LV_PCT, convert it to px before return. + * @param obj pointer to an image object + * @param pivot store the rotation center here + */ +void lv_image_get_pivot(lv_obj_t * obj, lv_point_t * pivot); + +/** + * Get the zoom factor of the image. + * @param obj pointer to an image object + * @return zoom factor (256: no zoom) + */ +int32_t lv_image_get_scale(lv_obj_t * obj); + +/** + * Get the horizontal zoom factor of the image. + * @param obj pointer to an image object + * @return zoom factor (256: no zoom) + */ +int32_t lv_image_get_scale_x(lv_obj_t * obj); + +/** + * Get the vertical zoom factor of the image. + * @param obj pointer to an image object + * @return zoom factor (256: no zoom) + */ +int32_t lv_image_get_scale_y(lv_obj_t * obj); + +/** + * Get the current blend mode of the image + * @param obj pointer to an image object + * @return the current blend mode + */ +lv_blend_mode_t lv_image_get_blend_mode(lv_obj_t * obj); + +/** + * Get whether the transformations (rotate, zoom) are anti-aliased or not + * @param obj pointer to an image object + * @return true: anti-aliased; false: not anti-aliased + */ +bool lv_image_get_antialias(lv_obj_t * obj); + +/** + * Get the size mode of the image + * @param obj pointer to an image object + * @return element of @ref lv_image_align_t + */ +lv_image_align_t lv_image_get_inner_align(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +/** Use this macro to declare an image in a C file*/ +#define LV_IMAGE_DECLARE(var_name) extern const lv_image_dsc_t var_name + +#endif /*LV_USE_IMAGE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_IMAGE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/imagebutton/lv_imagebutton.c b/lib/libesp32_lvgl/lvgl/src/widgets/imagebutton/lv_imagebutton.c new file mode 100644 index 000000000..77f6f3360 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/imagebutton/lv_imagebutton.c @@ -0,0 +1,347 @@ +/** + * @file lv_imagebutton.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_imagebutton.h" + +#if LV_USE_IMAGEBUTTON != 0 + +#include "../../stdlib/lv_string.h" + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_imagebutton_class + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_imagebutton_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void draw_main(lv_event_t * e); +static void lv_imagebutton_event(const lv_obj_class_t * class_p, lv_event_t * e); +static void refr_image(lv_obj_t * imagebutton); +static lv_imagebutton_state_t suggest_state(lv_obj_t * imagebutton, lv_imagebutton_state_t state); +static lv_imagebutton_state_t get_state(const lv_obj_t * imagebutton); +static void update_src_info(lv_imagebutton_src_info_t * info, const void * src); + +/********************** + * STATIC VARIABLES + **********************/ + +const lv_obj_class_t lv_imagebutton_class = { + .base_class = &lv_obj_class, + .width_def = LV_SIZE_CONTENT, + .height_def = LV_SIZE_CONTENT, + .instance_size = sizeof(lv_imagebutton_t), + .constructor_cb = lv_imagebutton_constructor, + .event_cb = lv_imagebutton_event, + .name = "imagebutton", +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_imagebutton_create(lv_obj_t * parent) +{ + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + return obj; +} + +/*===================== + * Setter functions + *====================*/ + +void lv_imagebutton_set_src(lv_obj_t * obj, lv_imagebutton_state_t state, const void * src_left, const void * src_mid, + const void * src_right) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + + update_src_info(&imagebutton->src_left[state], src_left); + update_src_info(&imagebutton->src_mid[state], src_mid); + update_src_info(&imagebutton->src_right[state], src_right); + + refr_image(obj); +} + +void lv_imagebutton_set_state(lv_obj_t * obj, lv_imagebutton_state_t state) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_state_t obj_state = LV_STATE_DEFAULT; + if(state == LV_IMAGEBUTTON_STATE_PRESSED || + state == LV_IMAGEBUTTON_STATE_CHECKED_PRESSED) obj_state |= LV_STATE_PRESSED; + if(state == LV_IMAGEBUTTON_STATE_DISABLED || + state == LV_IMAGEBUTTON_STATE_CHECKED_DISABLED) obj_state |= LV_STATE_DISABLED; + if(state == LV_IMAGEBUTTON_STATE_CHECKED_DISABLED || state == LV_IMAGEBUTTON_STATE_CHECKED_PRESSED || + state == LV_IMAGEBUTTON_STATE_CHECKED_RELEASED) { + obj_state |= LV_STATE_CHECKED; + } + + lv_obj_remove_state(obj, LV_STATE_CHECKED | LV_STATE_PRESSED | LV_STATE_DISABLED); + lv_obj_add_state(obj, obj_state); + + refr_image(obj); +} + +/*===================== + * Getter functions + *====================*/ + +const void * lv_imagebutton_get_src_left(lv_obj_t * obj, lv_imagebutton_state_t state) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + + return imagebutton->src_left[state].img_src; +} + +const void * lv_imagebutton_get_src_middle(lv_obj_t * obj, lv_imagebutton_state_t state) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + + return imagebutton->src_mid[state].img_src; +} + +const void * lv_imagebutton_get_src_right(lv_obj_t * obj, lv_imagebutton_state_t state) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + + return imagebutton->src_right[state].img_src; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_imagebutton_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + /*Initialize the allocated 'ext'*/ + + lv_memzero(&imagebutton->src_mid, sizeof(imagebutton->src_mid)); + lv_memzero(&imagebutton->src_left, sizeof(imagebutton->src_left)); + lv_memzero(&imagebutton->src_right, sizeof(imagebutton->src_right)); +} + +static void lv_imagebutton_event(const lv_obj_class_t * class_p, lv_event_t * e) +{ + LV_UNUSED(class_p); + + lv_result_t res = lv_obj_event_base(&lv_imagebutton_class, e); + if(res != LV_RESULT_OK) return; + + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * obj = lv_event_get_current_target(e); + if(code == LV_EVENT_PRESSED || code == LV_EVENT_RELEASED || code == LV_EVENT_PRESS_LOST) { + refr_image(obj); + } + else if(code == LV_EVENT_DRAW_MAIN) { + draw_main(e); + } + else if(code == LV_EVENT_COVER_CHECK) { + lv_cover_check_info_t * info = lv_event_get_param(e); + if(info->res != LV_COVER_RES_MASKED) info->res = LV_COVER_RES_NOT_COVER; + } + else if(code == LV_EVENT_GET_SELF_SIZE) { + lv_point_t * p = lv_event_get_self_size_info(e); + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + lv_imagebutton_state_t state = suggest_state(obj, get_state(obj)); + if(imagebutton->src_left[state].img_src == NULL && + imagebutton->src_mid[state].img_src != NULL && + imagebutton->src_right[state].img_src == NULL) { + p->x = LV_MAX(p->x, imagebutton->src_mid[state].header.w); + } + } +} + +static void draw_main(lv_event_t * e) +{ + lv_obj_t * obj = lv_event_get_current_target(e); + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + lv_layer_t * layer = lv_event_get_layer(e); + + /*Just draw_main an image*/ + lv_imagebutton_state_t state = suggest_state(obj, get_state(obj)); + + /*Simply draw the middle src if no tiled*/ + lv_imagebutton_src_info_t * src_info = &imagebutton->src_left[state]; + + int32_t tw = lv_obj_get_style_transform_width(obj, LV_PART_MAIN); + int32_t th = lv_obj_get_style_transform_height(obj, LV_PART_MAIN); + lv_area_t coords; + lv_area_copy(&coords, &obj->coords); + lv_area_increase(&coords, tw, th); + + lv_draw_image_dsc_t img_dsc; + lv_draw_image_dsc_init(&img_dsc); + lv_obj_init_draw_image_dsc(obj, LV_PART_MAIN, &img_dsc); + + lv_area_t coords_part; + int32_t left_w = 0; + int32_t right_w = 0; + + if(src_info->img_src) { + left_w = src_info->header.w; + coords_part.x1 = coords.x1; + coords_part.y1 = coords.y1; + coords_part.x2 = coords.x1 + src_info->header.w - 1; + coords_part.y2 = coords.y1 + src_info->header.h - 1; + img_dsc.src = src_info->img_src; + lv_draw_image(layer, &img_dsc, &coords_part); + } + + src_info = &imagebutton->src_right[state]; + if(src_info->img_src) { + right_w = src_info->header.w; + coords_part.x1 = coords.x2 - src_info->header.w + 1; + coords_part.y1 = coords.y1; + coords_part.x2 = coords.x2; + coords_part.y2 = coords.y1 + src_info->header.h - 1; + img_dsc.src = src_info->img_src; + lv_draw_image(layer, &img_dsc, &coords_part); + } + + src_info = &imagebutton->src_mid[state]; + if(src_info->img_src) { + lv_area_t clip_area_center; + clip_area_center.x1 = coords.x1 + left_w; + clip_area_center.x2 = coords.x2 - right_w; + clip_area_center.y1 = coords.y1; + clip_area_center.y2 = coords.y2; + + bool comm_res; + comm_res = _lv_area_intersect(&clip_area_center, &clip_area_center, &layer->_clip_area); + if(comm_res) { + int32_t i; + + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area_center; + + coords_part.x1 = coords.x1 + left_w; + coords_part.y1 = coords.y1; + coords_part.x2 = coords_part.x1 + src_info->header.w - 1; + coords_part.y2 = coords_part.y1 + src_info->header.h - 1; + + for(i = coords_part.x1; i < (int32_t)(clip_area_center.x2 + src_info->header.w - 1); i += src_info->header.w) { + img_dsc.src = src_info->img_src; + lv_draw_image(layer, &img_dsc, &coords_part); + coords_part.x1 = coords_part.x2 + 1; + coords_part.x2 += src_info->header.w; + } + layer->_clip_area = clip_area_ori; + } + } +} + +static void refr_image(lv_obj_t * obj) +{ + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + lv_imagebutton_state_t state = suggest_state(obj, get_state(obj)); + + const void * src = imagebutton->src_mid[state].img_src; + if(src == NULL) return; + + lv_obj_refresh_self_size(obj); + lv_obj_set_height(obj, imagebutton->src_mid[state].header.h); /*Keep the user defined width*/ + + lv_obj_invalidate(obj); +} + +/** + * If `src` is not defined for the current state try to get a state which is related to the current but has `src`. + * E.g. if the PRESSED src is not set but the RELEASED does, use the RELEASED. + * @param imagebutton pointer to an image button + * @param state the state to convert + * @return the suggested state + */ +static lv_imagebutton_state_t suggest_state(lv_obj_t * obj, lv_imagebutton_state_t state) +{ + lv_imagebutton_t * imagebutton = (lv_imagebutton_t *)obj; + if(imagebutton->src_mid[state].img_src == NULL) { + switch(state) { + case LV_IMAGEBUTTON_STATE_PRESSED: + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_RELEASED].img_src) return LV_IMAGEBUTTON_STATE_RELEASED; + break; + case LV_IMAGEBUTTON_STATE_CHECKED_RELEASED: + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_RELEASED].img_src) return LV_IMAGEBUTTON_STATE_RELEASED; + break; + case LV_IMAGEBUTTON_STATE_CHECKED_PRESSED: + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_CHECKED_RELEASED].img_src) return LV_IMAGEBUTTON_STATE_CHECKED_RELEASED; + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_PRESSED].img_src) return LV_IMAGEBUTTON_STATE_PRESSED; + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_RELEASED].img_src) return LV_IMAGEBUTTON_STATE_RELEASED; + break; + case LV_IMAGEBUTTON_STATE_DISABLED: + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_RELEASED].img_src) return LV_IMAGEBUTTON_STATE_RELEASED; + break; + case LV_IMAGEBUTTON_STATE_CHECKED_DISABLED: + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_CHECKED_RELEASED].img_src) return LV_IMAGEBUTTON_STATE_CHECKED_RELEASED; + if(imagebutton->src_mid[LV_IMAGEBUTTON_STATE_RELEASED].img_src) return LV_IMAGEBUTTON_STATE_RELEASED; + break; + default: + break; + } + } + + return state; +} + +static lv_imagebutton_state_t get_state(const lv_obj_t * imagebutton) +{ + LV_ASSERT_OBJ(imagebutton, MY_CLASS); + + lv_state_t obj_state = lv_obj_get_state(imagebutton); + + if(obj_state & LV_STATE_DISABLED) { + if(obj_state & LV_STATE_CHECKED) return LV_IMAGEBUTTON_STATE_CHECKED_DISABLED; + else return LV_IMAGEBUTTON_STATE_DISABLED; + } + + if(obj_state & LV_STATE_CHECKED) { + if(obj_state & LV_STATE_PRESSED) return LV_IMAGEBUTTON_STATE_CHECKED_PRESSED; + else return LV_IMAGEBUTTON_STATE_CHECKED_RELEASED; + } + else { + if(obj_state & LV_STATE_PRESSED) return LV_IMAGEBUTTON_STATE_PRESSED; + else return LV_IMAGEBUTTON_STATE_RELEASED; + } +} + +static void update_src_info(lv_imagebutton_src_info_t * info, const void * src) +{ + if(!src) { + lv_memzero(info, sizeof(lv_imagebutton_src_info_t)); + return; + } + + lv_result_t res = lv_image_decoder_get_info(src, &info->header); + if(res != LV_RESULT_OK) { + LV_LOG_WARN("can't get info"); + return; + } + + info->img_src = src; +} + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/imagebutton/lv_imagebutton.h b/lib/libesp32_lvgl/lvgl/src/widgets/imagebutton/lv_imagebutton.h new file mode 100644 index 000000000..1f91eb682 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/imagebutton/lv_imagebutton.h @@ -0,0 +1,134 @@ +/** + * @file lv_imagebutton.h + * + */ + +#ifndef LV_IMAGEBUTTON_H +#define LV_IMAGEBUTTON_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../core/lv_obj.h" + +#if LV_USE_IMAGEBUTTON != 0 + +/********************* + * DEFINES + *********************/ +typedef enum { + LV_IMAGEBUTTON_STATE_RELEASED, + LV_IMAGEBUTTON_STATE_PRESSED, + LV_IMAGEBUTTON_STATE_DISABLED, + LV_IMAGEBUTTON_STATE_CHECKED_RELEASED, + LV_IMAGEBUTTON_STATE_CHECKED_PRESSED, + LV_IMAGEBUTTON_STATE_CHECKED_DISABLED, + _LV_IMAGEBUTTON_STATE_NUM, +} lv_imagebutton_state_t; + +typedef struct { + const void * img_src; + lv_image_header_t header; +} lv_imagebutton_src_info_t; + +/********************** + * TYPEDEFS + **********************/ +/*Data of image button*/ +typedef struct { + lv_obj_t obj; + lv_imagebutton_src_info_t src_mid[_LV_IMAGEBUTTON_STATE_NUM]; /*Store center images to each state*/ + lv_imagebutton_src_info_t src_left[_LV_IMAGEBUTTON_STATE_NUM]; /*Store left side images to each state*/ + lv_imagebutton_src_info_t src_right[_LV_IMAGEBUTTON_STATE_NUM]; /*Store right side images to each state*/ +} lv_imagebutton_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_imagebutton_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an image button object + * @param parent pointer to an object, it will be the parent of the new image button + * @return pointer to the created image button + */ +lv_obj_t * lv_imagebutton_create(lv_obj_t * parent); + +/*====================== + * Add/remove functions + *=====================*/ + +/*===================== + * Setter functions + *====================*/ + +/** + * Set images for a state of the image button + * @param imagebutton pointer to an image button object + * @param state for which state set the new image + * @param src_left pointer to an image source for the left side of the button (a C array or path to + * a file) + * @param src_mid pointer to an image source for the middle of the button (ideally 1px wide) (a C + * array or path to a file) + * @param src_right pointer to an image source for the right side of the button (a C array or path + * to a file) + */ +void lv_imagebutton_set_src(lv_obj_t * imagebutton, lv_imagebutton_state_t state, const void * src_left, + const void * src_mid, + const void * src_right); + +/** + * Use this function instead of `lv_obj_add/remove_state` to set a state manually + * @param imagebutton pointer to an image button object + * @param state the new state + */ +void lv_imagebutton_set_state(lv_obj_t * imagebutton, lv_imagebutton_state_t state); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the left image in a given state + * @param imagebutton pointer to an image button object + * @param state the state where to get the image (from `lv_button_state_t`) ` + * @return pointer to the left image source (a C array or path to a file) + */ +const void * lv_imagebutton_get_src_left(lv_obj_t * imagebutton, lv_imagebutton_state_t state); + +/** + * Get the middle image in a given state + * @param imagebutton pointer to an image button object + * @param state the state where to get the image (from `lv_button_state_t`) ` + * @return pointer to the middle image source (a C array or path to a file) + */ +const void * lv_imagebutton_get_src_middle(lv_obj_t * imagebutton, lv_imagebutton_state_t state); + +/** + * Get the right image in a given state + * @param imagebutton pointer to an image button object + * @param state the state where to get the image (from `lv_button_state_t`) ` + * @return pointer to the left image source (a C array or path to a file) + */ +const void * lv_imagebutton_get_src_right(lv_obj_t * imagebutton, lv_imagebutton_state_t state); + +/*===================== + * Other functions + *====================*/ + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_IMAGEBUTTON*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_IMAGEBUTTON_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.c b/lib/libesp32_lvgl/lvgl/src/widgets/keyboard/lv_keyboard.c similarity index 52% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.c rename to lib/libesp32_lvgl/lvgl/src/widgets/keyboard/lv_keyboard.c index cbb5e1c4f..ea12d8e04 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/keyboard/lv_keyboard.c @@ -10,8 +10,9 @@ #include "lv_keyboard.h" #if LV_USE_KEYBOARD -#include "../../../widgets/lv_textarea.h" -#include "../../../misc/lv_assert.h" +#include "../textarea/lv_textarea.h" +#include "../../misc/lv_assert.h" +#include "../../stdlib/lv_string.h" #include @@ -19,7 +20,7 @@ * DEFINES *********************/ #define MY_CLASS &lv_keyboard_class -#define LV_KB_BTN(width) LV_BTNMATRIX_CTRL_POPOVER | width +#define LV_KB_BTN(width) LV_BUTTONMATRIX_CTRL_POPOVER | width /********************** * TYPEDEFS @@ -37,52 +38,93 @@ static void lv_keyboard_update_ctrl_map(lv_obj_t * obj); /********************** * STATIC VARIABLES **********************/ + const lv_obj_class_t lv_keyboard_class = { .constructor_cb = lv_keyboard_constructor, .width_def = LV_PCT(100), .height_def = LV_PCT(50), .instance_size = sizeof(lv_keyboard_t), .editable = 1, - .base_class = &lv_btnmatrix_class + .base_class = &lv_buttonmatrix_class, + .name = "keyboard", }; static const char * const default_kb_map_lc[] = {"1#", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", LV_SYMBOL_BACKSPACE, "\n", "ABC", "a", "s", "d", "f", "g", "h", "j", "k", "l", LV_SYMBOL_NEW_LINE, "\n", "_", "-", "z", "x", "c", "v", "b", "n", "m", ".", ",", ":", "\n", - LV_SYMBOL_KEYBOARD, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, "" + LV_SYMBOL_KEYBOARD, +#if LV_USE_ARABIC_PERSIAN_CHARS == 1 + "أب", +#endif + LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, "" }; -static const lv_btnmatrix_ctrl_t default_kb_ctrl_lc_map[] = { - LV_KEYBOARD_CTRL_BTN_FLAGS | 5, LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_BTNMATRIX_CTRL_CHECKED | 7, - LV_KEYBOARD_CTRL_BTN_FLAGS | 6, LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_BTNMATRIX_CTRL_CHECKED | 7, - LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), - LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_BTNMATRIX_CTRL_CHECKED | 2, 6, LV_BTNMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2 +static const lv_buttonmatrix_ctrl_t default_kb_ctrl_lc_map[] = { + LV_KEYBOARD_CTRL_BUTTON_FLAGS | 5, LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_BUTTONMATRIX_CTRL_CHECKED | 7, + LV_KEYBOARD_CTRL_BUTTON_FLAGS | 6, LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_BUTTONMATRIX_CTRL_CHECKED | 7, + LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), + LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, +#if LV_USE_ARABIC_PERSIAN_CHARS == 1 + LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, +#endif + LV_BUTTONMATRIX_CTRL_CHECKED | 2, 6, LV_BUTTONMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2 }; static const char * const default_kb_map_uc[] = {"1#", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", LV_SYMBOL_BACKSPACE, "\n", "abc", "A", "S", "D", "F", "G", "H", "J", "K", "L", LV_SYMBOL_NEW_LINE, "\n", "_", "-", "Z", "X", "C", "V", "B", "N", "M", ".", ",", ":", "\n", - LV_SYMBOL_KEYBOARD, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, "" + LV_SYMBOL_CLOSE, +#if LV_USE_ARABIC_PERSIAN_CHARS == 1 + "أب", +#endif + LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, "" }; -static const lv_btnmatrix_ctrl_t default_kb_ctrl_uc_map[] = { - LV_KEYBOARD_CTRL_BTN_FLAGS | 5, LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_BTNMATRIX_CTRL_CHECKED | 7, - LV_KEYBOARD_CTRL_BTN_FLAGS | 6, LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_BTNMATRIX_CTRL_CHECKED | 7, - LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), - LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_BTNMATRIX_CTRL_CHECKED | 2, 6, LV_BTNMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2 +static const lv_buttonmatrix_ctrl_t default_kb_ctrl_uc_map[] = { + LV_KEYBOARD_CTRL_BUTTON_FLAGS | 5, LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_BUTTONMATRIX_CTRL_CHECKED | 7, + LV_KEYBOARD_CTRL_BUTTON_FLAGS | 6, LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_BUTTONMATRIX_CTRL_CHECKED | 7, + LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), + LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, +#if LV_USE_ARABIC_PERSIAN_CHARS == 1 + LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, +#endif + LV_BUTTONMATRIX_CTRL_CHECKED | 2, 6, LV_BUTTONMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2 }; +#if LV_USE_ARABIC_PERSIAN_CHARS == 1 +static const char * const default_kb_map_ar[] = { + "1#", "ض", "ص", "ث", "ق", "ف", "غ", "ع", "ه", "خ", "ح", "ج", "\n", + "ش", "س", "ي", "ب", "ل", "ا", "ت", "ن", "م", "ك", "ط", LV_SYMBOL_BACKSPACE, "\n", + "ذ", "ء", "ؤ", "ر", "ى", "ة", "و", "ز", "ظ", "د", "ز", "ظ", "د", "\n", + LV_SYMBOL_CLOSE, "abc", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_NEW_LINE, LV_SYMBOL_OK, "" +}; + +static const lv_buttonmatrix_ctrl_t default_kb_ctrl_ar_map[] = { + LV_KEYBOARD_CTRL_BUTTON_FLAGS | 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, 2, 6, 2, 3, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2 +}; +#endif static const char * const default_kb_map_spec[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", LV_SYMBOL_BACKSPACE, "\n", "abc", "+", "&", "/", "*", "=", "%", "!", "?", "#", "<", ">", "\n", "\\", "@", "$", "(", ")", "{", "}", "[", "]", ";", "\"", "'", "\n", - LV_SYMBOL_KEYBOARD, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, "" + LV_SYMBOL_KEYBOARD, +#if LV_USE_ARABIC_PERSIAN_CHARS == 1 + "أب", +#endif + LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, "" }; -static const lv_btnmatrix_ctrl_t default_kb_ctrl_spec_map[] = { - LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | 2, - LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), +static const lv_buttonmatrix_ctrl_t default_kb_ctrl_spec_map[] = { + LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | 2, + LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), - LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_BTNMATRIX_CTRL_CHECKED | 2, 6, LV_BTNMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2 + LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, +#if LV_USE_ARABIC_PERSIAN_CHARS == 1 + LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, +#endif + LV_BUTTONMATRIX_CTRL_CHECKED | 2, 6, LV_BUTTONMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2 }; static const char * const default_kb_map_num[] = {"1", "2", "3", LV_SYMBOL_KEYBOARD, "\n", @@ -91,14 +133,14 @@ static const char * const default_kb_map_num[] = {"1", "2", "3", LV_SYMBOL_KEYBO "+/-", "0", ".", LV_SYMBOL_LEFT, LV_SYMBOL_RIGHT, "" }; -static const lv_btnmatrix_ctrl_t default_kb_ctrl_num_map[] = { - 1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 2, - 1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 2, +static const lv_buttonmatrix_ctrl_t default_kb_ctrl_num_map[] = { + 1, 1, 1, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, + 1, 1, 1, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, 1, 1, 1, 2, 1, 1, 1, 1, 1 }; -static const char * * kb_map[9] = { +static const char * * kb_map[10] = { (const char * *)default_kb_map_lc, (const char * *)default_kb_map_uc, (const char * *)default_kb_map_spec, @@ -107,9 +149,12 @@ static const char * * kb_map[9] = { (const char * *)default_kb_map_lc, (const char * *)default_kb_map_lc, (const char * *)default_kb_map_lc, - (const char * *)NULL, +#if LV_USE_ARABIC_PERSIAN_CHARS == 1 + (const char * *)default_kb_map_ar, +#endif + (const char * *)NULL }; -static const lv_btnmatrix_ctrl_t * kb_ctrl[9] = { +static const lv_buttonmatrix_ctrl_t * kb_ctrl[10] = { default_kb_ctrl_lc_map, default_kb_ctrl_uc_map, default_kb_ctrl_spec_map, @@ -118,7 +163,10 @@ static const lv_btnmatrix_ctrl_t * kb_ctrl[9] = { default_kb_ctrl_lc_map, default_kb_ctrl_lc_map, default_kb_ctrl_lc_map, - NULL, +#if LV_USE_ARABIC_PERSIAN_CHARS == 1 + default_kb_ctrl_ar_map, +#endif + NULL }; /********************** @@ -129,11 +177,6 @@ static const lv_btnmatrix_ctrl_t * kb_ctrl[9] = { * GLOBAL FUNCTIONS **********************/ -/** - * Create a Keyboard object - * @param parent pointer to an object, it will be the parent of the new keyboard - * @return pointer to the created keyboard - */ lv_obj_t * lv_keyboard_create(lv_obj_t * parent) { LV_LOG_INFO("begin"); @@ -146,11 +189,6 @@ lv_obj_t * lv_keyboard_create(lv_obj_t * parent) * Setter functions *====================*/ -/** - * Assign a Text Area to the Keyboard. The pressed characters will be put there. - * @param kb pointer to a Keyboard object - * @param ta pointer to a Text Area object to write there - */ void lv_keyboard_set_textarea(lv_obj_t * obj, lv_obj_t * ta) { if(ta) { @@ -162,7 +200,7 @@ void lv_keyboard_set_textarea(lv_obj_t * obj, lv_obj_t * ta) /*Hide the cursor of the old Text area if cursor management is enabled*/ if(keyboard->ta) { - lv_obj_clear_state(obj, LV_STATE_FOCUSED); + lv_obj_remove_state(obj, LV_STATE_FOCUSED); } keyboard->ta = ta; @@ -173,11 +211,6 @@ void lv_keyboard_set_textarea(lv_obj_t * obj, lv_obj_t * ta) } } -/** - * Set a new a mode (text or number map) - * @param kb pointer to a Keyboard object - * @param mode the mode from 'lv_keyboard_mode_t' - */ void lv_keyboard_set_mode(lv_obj_t * obj, lv_keyboard_mode_t mode) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -188,11 +221,6 @@ void lv_keyboard_set_mode(lv_obj_t * obj, lv_keyboard_mode_t mode) lv_keyboard_update_map(obj); } -/** - * Show the button title in a popover when pressed. - * @param kb pointer to a Keyboard object - * @param en whether "popovers" mode is enabled - */ void lv_keyboard_set_popovers(lv_obj_t * obj, bool en) { lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; @@ -205,16 +233,10 @@ void lv_keyboard_set_popovers(lv_obj_t * obj, bool en) lv_keyboard_update_ctrl_map(obj); } -/** - * Set a new map for the keyboard - * @param kb pointer to a Keyboard object - * @param mode keyboard map to alter 'lv_keyboard_mode_t' - * @param map pointer to a string array to describe the map. - * See 'lv_btnmatrix_set_map()' for more info. - */ void lv_keyboard_set_map(lv_obj_t * obj, lv_keyboard_mode_t mode, const char * map[], - const lv_btnmatrix_ctrl_t ctrl_map[]) + const lv_buttonmatrix_ctrl_t ctrl_map[]) { + LV_ASSERT_OBJ(obj, MY_CLASS); kb_map[mode] = map; kb_ctrl[mode] = ctrl_map; lv_keyboard_update_map(obj); @@ -224,11 +246,6 @@ void lv_keyboard_set_map(lv_obj_t * obj, lv_keyboard_mode_t mode, const char * m * Getter functions *====================*/ -/** - * Assign a Text Area to the Keyboard. The pressed characters will be put there. - * @param kb pointer to a Keyboard object - * @return pointer to the assigned Text Area object - */ lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -236,11 +253,6 @@ lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * obj) return keyboard->ta; } -/** - * Set a new a mode (text or number map) - * @param kb pointer to a Keyboard object - * @return the current mode from 'lv_keyboard_mode_t' - */ lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -248,12 +260,7 @@ lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * obj) return keyboard->mode; } -/** - * Tell whether "popovers" mode is enabled or not. - * @param kb pointer to a Keyboard object - * @return true: "popovers" mode is enabled; false: disabled - */ -bool lv_btnmatrix_get_popovers(const lv_obj_t * obj) +bool lv_buttonmatrix_get_popovers(const lv_obj_t * obj) { lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; return keyboard->popovers; @@ -263,60 +270,61 @@ bool lv_btnmatrix_get_popovers(const lv_obj_t * obj) * Other functions *====================*/ -/** - * Default keyboard event to add characters to the Text area and change the map. - * If a custom `event_cb` is added to the keyboard this function can be called from it to handle the - * button clicks - * @param kb pointer to a keyboard - * @param event the triggering event - */ void lv_keyboard_def_event_cb(lv_event_t * e) { - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); LV_ASSERT_OBJ(obj, MY_CLASS); lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; - uint16_t btn_id = lv_btnmatrix_get_selected_btn(obj); - if(btn_id == LV_BTNMATRIX_BTN_NONE) return; + uint32_t btn_id = lv_buttonmatrix_get_selected_button(obj); + if(btn_id == LV_BUTTONMATRIX_BUTTON_NONE) return; - const char * txt = lv_btnmatrix_get_btn_text(obj, lv_btnmatrix_get_selected_btn(obj)); + const char * txt = lv_buttonmatrix_get_button_text(obj, btn_id); if(txt == NULL) return; - if(strcmp(txt, "abc") == 0) { + if(lv_strcmp(txt, "abc") == 0) { keyboard->mode = LV_KEYBOARD_MODE_TEXT_LOWER; - lv_btnmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_TEXT_LOWER]); + lv_buttonmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_TEXT_LOWER]); lv_keyboard_update_ctrl_map(obj); return; } - else if(strcmp(txt, "ABC") == 0) { +#if LV_USE_ARABIC_PERSIAN_CHARS == 1 + else if(lv_strcmp(txt, "أب") == 0) { + keyboard->mode = LV_KEYBOARD_MODE_TEXT_ARABIC; + lv_buttonmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_TEXT_ARABIC]); + lv_keyboard_update_ctrl_map(obj); + return; + } +#endif + else if(lv_strcmp(txt, "ABC") == 0) { keyboard->mode = LV_KEYBOARD_MODE_TEXT_UPPER; - lv_btnmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_TEXT_UPPER]); + lv_buttonmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_TEXT_UPPER]); lv_keyboard_update_ctrl_map(obj); return; } - else if(strcmp(txt, "1#") == 0) { + else if(lv_strcmp(txt, "1#") == 0) { keyboard->mode = LV_KEYBOARD_MODE_SPECIAL; - lv_btnmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_SPECIAL]); + lv_buttonmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_SPECIAL]); lv_keyboard_update_ctrl_map(obj); return; } - else if(strcmp(txt, LV_SYMBOL_CLOSE) == 0 || strcmp(txt, LV_SYMBOL_KEYBOARD) == 0) { - lv_res_t res = lv_event_send(obj, LV_EVENT_CANCEL, NULL); - if(res != LV_RES_OK) return; + else if(lv_strcmp(txt, LV_SYMBOL_CLOSE) == 0 || lv_strcmp(txt, LV_SYMBOL_KEYBOARD) == 0) { + lv_result_t res = lv_obj_send_event(obj, LV_EVENT_CANCEL, NULL); + if(res != LV_RESULT_OK) return; if(keyboard->ta) { - res = lv_event_send(keyboard->ta, LV_EVENT_CANCEL, NULL); - if(res != LV_RES_OK) return; + res = lv_obj_send_event(keyboard->ta, LV_EVENT_CANCEL, NULL); + if(res != LV_RESULT_OK) return; } return; } - else if(strcmp(txt, LV_SYMBOL_OK) == 0) { - lv_res_t res = lv_event_send(obj, LV_EVENT_READY, NULL); - if(res != LV_RES_OK) return; + else if(lv_strcmp(txt, LV_SYMBOL_OK) == 0) { + lv_result_t res = lv_obj_send_event(obj, LV_EVENT_READY, NULL); + if(res != LV_RESULT_OK) return; if(keyboard->ta) { - res = lv_event_send(keyboard->ta, LV_EVENT_READY, NULL); - if(res != LV_RES_OK) return; + res = lv_obj_send_event(keyboard->ta, LV_EVENT_READY, NULL); + if(res != LV_RESULT_OK) return; } return; } @@ -324,34 +332,34 @@ void lv_keyboard_def_event_cb(lv_event_t * e) /*Add the characters to the text area if set*/ if(keyboard->ta == NULL) return; - if(strcmp(txt, "Enter") == 0 || strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) { + if(lv_strcmp(txt, "Enter") == 0 || lv_strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) { lv_textarea_add_char(keyboard->ta, '\n'); if(lv_textarea_get_one_line(keyboard->ta)) { - lv_res_t res = lv_event_send(keyboard->ta, LV_EVENT_READY, NULL); - if(res != LV_RES_OK) return; + lv_result_t res = lv_obj_send_event(keyboard->ta, LV_EVENT_READY, NULL); + if(res != LV_RESULT_OK) return; } } - else if(strcmp(txt, LV_SYMBOL_LEFT) == 0) { + else if(lv_strcmp(txt, LV_SYMBOL_LEFT) == 0) { lv_textarea_cursor_left(keyboard->ta); } - else if(strcmp(txt, LV_SYMBOL_RIGHT) == 0) { + else if(lv_strcmp(txt, LV_SYMBOL_RIGHT) == 0) { lv_textarea_cursor_right(keyboard->ta); } - else if(strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) { - lv_textarea_del_char(keyboard->ta); + else if(lv_strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) { + lv_textarea_delete_char(keyboard->ta); } - else if(strcmp(txt, "+/-") == 0) { - uint16_t cur = lv_textarea_get_cursor_pos(keyboard->ta); + else if(lv_strcmp(txt, "+/-") == 0) { + uint32_t cur = lv_textarea_get_cursor_pos(keyboard->ta); const char * ta_txt = lv_textarea_get_text(keyboard->ta); if(ta_txt[0] == '-') { lv_textarea_set_cursor_pos(keyboard->ta, 1); - lv_textarea_del_char(keyboard->ta); + lv_textarea_delete_char(keyboard->ta); lv_textarea_add_char(keyboard->ta, '+'); lv_textarea_set_cursor_pos(keyboard->ta, cur); } else if(ta_txt[0] == '+') { lv_textarea_set_cursor_pos(keyboard->ta, 1); - lv_textarea_del_char(keyboard->ta); + lv_textarea_delete_char(keyboard->ta); lv_textarea_add_char(keyboard->ta, '-'); lv_textarea_set_cursor_pos(keyboard->ta, cur); } @@ -373,7 +381,7 @@ void lv_keyboard_def_event_cb(lv_event_t * e) static void lv_keyboard_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { LV_UNUSED(class_p); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICK_FOCUSABLE); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_CLICK_FOCUSABLE); lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; keyboard->ta = NULL; @@ -394,7 +402,7 @@ static void lv_keyboard_constructor(const lv_obj_class_t * class_p, lv_obj_t * o static void lv_keyboard_update_map(lv_obj_t * obj) { lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; - lv_btnmatrix_set_map(obj, kb_map[keyboard->mode]); + lv_buttonmatrix_set_map(obj, kb_map[keyboard->mode]); lv_keyboard_update_ctrl_map(obj); } @@ -407,23 +415,24 @@ static void lv_keyboard_update_ctrl_map(lv_obj_t * obj) lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; if(keyboard->popovers) { - /*Apply the current control map (already includes LV_BTNMATRIX_CTRL_POPOVER flags)*/ - lv_btnmatrix_set_ctrl_map(obj, kb_ctrl[keyboard->mode]); + /*Apply the current control map (already includes LV_BUTTONMATRIX_CTRL_POPOVER flags)*/ + lv_buttonmatrix_set_ctrl_map(obj, kb_ctrl[keyboard->mode]); } else { /*Make a copy of the current control map*/ - lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; - lv_btnmatrix_ctrl_t * ctrl_map = lv_mem_alloc(btnm->btn_cnt * sizeof(lv_btnmatrix_ctrl_t)); - lv_memcpy(ctrl_map, kb_ctrl[keyboard->mode], sizeof(lv_btnmatrix_ctrl_t) * btnm->btn_cnt); + lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj; + lv_buttonmatrix_ctrl_t * ctrl_map = lv_malloc(btnm->btn_cnt * sizeof(lv_buttonmatrix_ctrl_t)); + lv_memcpy(ctrl_map, kb_ctrl[keyboard->mode], sizeof(lv_buttonmatrix_ctrl_t) * btnm->btn_cnt); - /*Remove all LV_BTNMATRIX_CTRL_POPOVER flags*/ - for(uint16_t i = 0; i < btnm->btn_cnt; i++) { - ctrl_map[i] &= (~LV_BTNMATRIX_CTRL_POPOVER); + /*Remove all LV_BUTTONMATRIX_CTRL_POPOVER flags*/ + uint32_t i; + for(i = 0; i < btnm->btn_cnt; i++) { + ctrl_map[i] &= (~LV_BUTTONMATRIX_CTRL_POPOVER); } /*Apply new control map and clean up*/ - lv_btnmatrix_set_ctrl_map(obj, ctrl_map); - lv_mem_free(ctrl_map); + lv_buttonmatrix_set_ctrl_map(obj, ctrl_map); + lv_free(ctrl_map); } } diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.h b/lib/libesp32_lvgl/lvgl/src/widgets/keyboard/lv_keyboard.h similarity index 56% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.h rename to lib/libesp32_lvgl/lvgl/src/widgets/keyboard/lv_keyboard.h index 7f65cd75a..c2c84ba82 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/keyboard/lv_keyboard.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/keyboard/lv_keyboard.h @@ -13,30 +13,30 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../widgets/lv_btnmatrix.h" +#include "../buttonmatrix/lv_buttonmatrix.h" #if LV_USE_KEYBOARD /*Testing of dependencies*/ -#if LV_USE_BTNMATRIX == 0 -#error "lv_kb: lv_btnm is required. Enable it in lv_conf.h (LV_USE_BTNMATRIX 1) " +#if LV_USE_BUTTONMATRIX == 0 +#error "lv_buttonmatrix is required. Enable it in lv_conf.h (LV_USE_BUTTONMATRIX 1) " #endif #if LV_USE_TEXTAREA == 0 -#error "lv_kb: lv_ta is required. Enable it in lv_conf.h (LV_USE_TEXTAREA 1) " +#error "lv_textare is required. Enable it in lv_conf.h (LV_USE_TEXTAREA 1) " #endif /********************* * DEFINES *********************/ -#define LV_KEYBOARD_CTRL_BTN_FLAGS (LV_BTNMATRIX_CTRL_NO_REPEAT | LV_BTNMATRIX_CTRL_CLICK_TRIG | LV_BTNMATRIX_CTRL_CHECKED) +#define LV_KEYBOARD_CTRL_BUTTON_FLAGS (LV_BUTTONMATRIX_CTRL_NO_REPEAT | LV_BUTTONMATRIX_CTRL_CLICK_TRIG | LV_BUTTONMATRIX_CTRL_CHECKED) /********************** * TYPEDEFS **********************/ /** Current keyboard mode.*/ -enum { +enum _lv_keyboard_mode_t { LV_KEYBOARD_MODE_TEXT_LOWER, LV_KEYBOARD_MODE_TEXT_UPPER, LV_KEYBOARD_MODE_SPECIAL, @@ -45,18 +45,26 @@ enum { LV_KEYBOARD_MODE_USER_2, LV_KEYBOARD_MODE_USER_3, LV_KEYBOARD_MODE_USER_4, +#if LV_USE_ARABIC_PERSIAN_CHARS == 1 + LV_KEYBOARD_MODE_TEXT_ARABIC +#endif }; + +#ifdef DOXYGEN +typedef _lv_keyboard_mode_t lv_keyboard_mode_t; +#else typedef uint8_t lv_keyboard_mode_t; +#endif /*DOXYGEN*/ /*Data of keyboard*/ typedef struct { - lv_btnmatrix_t btnm; + lv_buttonmatrix_t btnm; lv_obj_t * ta; /*Pointer to the assigned text area*/ lv_keyboard_mode_t mode; /*Key map type*/ uint8_t popovers : 1; /*Show button titles in popovers on press*/ } lv_keyboard_t; -extern const lv_obj_class_t lv_keyboard_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_keyboard_class; /********************** * GLOBAL PROTOTYPES @@ -64,8 +72,8 @@ extern const lv_obj_class_t lv_keyboard_class; /** * Create a Keyboard object - * @param parent pointer to an object, it will be the parent of the new keyboard - * @return pointer to the created keyboard + * @param parent pointer to an object, it will be the parent of the new keyboard + * @return pointer to the created keyboard */ lv_obj_t * lv_keyboard_create(lv_obj_t * parent); @@ -75,34 +83,36 @@ lv_obj_t * lv_keyboard_create(lv_obj_t * parent); /** * Assign a Text Area to the Keyboard. The pressed characters will be put there. - * @param kb pointer to a Keyboard object - * @param ta pointer to a Text Area object to write there + * @param kb pointer to a Keyboard object + * @param ta pointer to a Text Area object to write there */ void lv_keyboard_set_textarea(lv_obj_t * kb, lv_obj_t * ta); /** * Set a new a mode (text or number map) - * @param kb pointer to a Keyboard object - * @param mode the mode from 'lv_keyboard_mode_t' + * @param kb pointer to a Keyboard object + * @param mode the mode from 'lv_keyboard_mode_t' */ void lv_keyboard_set_mode(lv_obj_t * kb, lv_keyboard_mode_t mode); /** * Show the button title in a popover when pressed. - * @param kb pointer to a Keyboard object - * @param en whether "popovers" mode is enabled + * @param kb pointer to a Keyboard object + * @param en whether "popovers" mode is enabled */ void lv_keyboard_set_popovers(lv_obj_t * kb, bool en); /** * Set a new map for the keyboard - * @param kb pointer to a Keyboard object - * @param mode keyboard map to alter 'lv_keyboard_mode_t' - * @param map pointer to a string array to describe the map. - * See 'lv_btnmatrix_set_map()' for more info. + * @param kb pointer to a Keyboard object + * @param mode keyboard map to alter 'lv_keyboard_mode_t' + * @param map pointer to a string array to describe the map. + * See 'lv_buttonmatrix_set_map()' for more info. + * @param ctrl_map See 'lv_buttonmatrix_set_ctrl_map()' for more info. + */ void lv_keyboard_set_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const char * map[], - const lv_btnmatrix_ctrl_t ctrl_map[]); + const lv_buttonmatrix_ctrl_t ctrl_map[]); /*===================== * Getter functions @@ -110,44 +120,44 @@ void lv_keyboard_set_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const char * ma /** * Assign a Text Area to the Keyboard. The pressed characters will be put there. - * @param kb pointer to a Keyboard object - * @return pointer to the assigned Text Area object + * @param kb pointer to a Keyboard object + * @return pointer to the assigned Text Area object */ lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * kb); /** * Set a new a mode (text or number map) - * @param kb pointer to a Keyboard object - * @return the current mode from 'lv_keyboard_mode_t' + * @param kb pointer to a Keyboard object + * @return the current mode from 'lv_keyboard_mode_t' */ lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * kb); /** * Tell whether "popovers" mode is enabled or not. - * @param kb pointer to a Keyboard object - * @return true: "popovers" mode is enabled; false: disabled + * @param obj pointer to a Keyboard object + * @return true: "popovers" mode is enabled; false: disabled */ -bool lv_btnmatrix_get_popovers(const lv_obj_t * obj); +bool lv_buttonmatrix_get_popovers(const lv_obj_t * obj); /** * Get the current map of a keyboard - * @param kb pointer to a keyboard object - * @return the current map + * @param kb pointer to a keyboard object + * @return the current map */ static inline const char ** lv_keyboard_get_map_array(const lv_obj_t * kb) { - return lv_btnmatrix_get_map(kb); + return lv_buttonmatrix_get_map(kb); } /** * Get the index of the lastly "activated" button by the user (pressed, released, focused etc) * Useful in the `event_cb` to get the text of the button, check if hidden etc. * @param obj pointer to button matrix object - * @return index of the last released button (LV_BTNMATRIX_BTN_NONE: if unset) + * @return index of the last released button (LV_BUTTONMATRIX_BUTTON_NONE: if unset) */ -static inline uint16_t lv_keyboard_get_selected_btn(const lv_obj_t * obj) +static inline uint32_t lv_keyboard_get_selected_button(const lv_obj_t * obj) { - return lv_btnmatrix_get_selected_btn(obj); + return lv_buttonmatrix_get_selected_button(obj); } /** @@ -156,9 +166,9 @@ static inline uint16_t lv_keyboard_get_selected_btn(const lv_obj_t * obj) * @param btn_id the index a button not counting new line characters. * @return text of btn_index` button */ -static inline const char * lv_keyboard_get_btn_text(const lv_obj_t * obj, uint16_t btn_id) +static inline const char * lv_keyboard_get_button_text(const lv_obj_t * obj, uint32_t btn_id) { - return lv_btnmatrix_get_btn_text(obj, btn_id); + return lv_buttonmatrix_get_button_text(obj, btn_id); } /*===================== @@ -169,8 +179,7 @@ static inline const char * lv_keyboard_get_btn_text(const lv_obj_t * obj, uint16 * Default keyboard event to add characters to the Text area and change the map. * If a custom `event_cb` is added to the keyboard this function can be called from it to handle the * button clicks - * @param kb pointer to a keyboard - * @param event the triggering event + * @param e the triggering event */ void lv_keyboard_def_event_cb(lv_event_t * e); diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.c b/lib/libesp32_lvgl/lvgl/src/widgets/label/lv_label.c similarity index 67% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_label.c rename to lib/libesp32_lvgl/lvgl/src/widgets/label/lv_label.c index f4fbe01a5..4986d78f1 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/label/lv_label.c @@ -8,22 +8,24 @@ *********************/ #include "lv_label.h" #if LV_USE_LABEL != 0 -#include "../core/lv_obj.h" -#include "../misc/lv_assert.h" -#include "../core/lv_group.h" -#include "../draw/lv_draw.h" -#include "../misc/lv_color.h" -#include "../misc/lv_math.h" -#include "../misc/lv_bidi.h" -#include "../misc/lv_txt_ap.h" -#include "../misc/lv_printf.h" +#include "../../core/lv_obj.h" +#include "../../misc/lv_assert.h" +#include "../../core/lv_group.h" +#include "../../display/lv_display.h" +#include "../../draw/lv_draw.h" +#include "../../misc/lv_color.h" +#include "../../misc/lv_math.h" +#include "../../misc/lv_bidi.h" +#include "../../misc/lv_text_ap.h" +#include "../../stdlib/lv_sprintf.h" +#include "../../stdlib/lv_string.h" /********************* * DEFINES *********************/ #define MY_CLASS &lv_label_class -#define LV_LABEL_DEF_SCROLL_SPEED (lv_disp_get_dpi(lv_obj_get_disp(obj)) / 3) +#define LV_LABEL_DEF_SCROLL_SPEED lv_anim_speed_clamped(40, 300, 10000) #define LV_LABEL_SCROLL_DELAY 300 #define LV_LABEL_DOT_END_INV 0xFFFFFFFF #define LV_LABEL_HINT_HEIGHT_LIMIT 1024 /*Enable "hint" to buffer info about labels larger than this. (Speed up drawing)*/ @@ -48,6 +50,11 @@ static char * lv_label_get_dot_tmp(lv_obj_t * label); static void lv_label_dot_tmp_free(lv_obj_t * label); static void set_ofs_x_anim(void * obj, int32_t v); static void set_ofs_y_anim(void * obj, int32_t v); +static size_t get_text_length(const char * text); +static void copy_text_to_label(lv_label_t * label, const char * text); +static lv_text_flag_t get_label_flags(lv_label_t * label); +static void calculate_x_coordinate(int32_t * x, const lv_text_align_t align, const char * txt, + uint32_t length, const lv_font_t * font, int32_t letter_space, lv_area_t * txt_coords); /********************** * STATIC VARIABLES @@ -59,7 +66,8 @@ const lv_obj_class_t lv_label_class = { .width_def = LV_SIZE_CONTENT, .height_def = LV_SIZE_CONTENT, .instance_size = sizeof(lv_label_t), - .base_class = &lv_obj_class + .base_class = &lv_obj_class, + .name = "label", }; /********************** @@ -92,50 +100,31 @@ void lv_label_set_text(lv_obj_t * obj, const char * text) /*If text is NULL then just refresh with the current text*/ if(text == NULL) text = label->text; - if(label->text == text && label->static_txt == 0) { - /*If set its own text then reallocate it (maybe its size changed)*/ -#if LV_USE_ARABIC_PERSIAN_CHARS - /*Get the size of the text and process it*/ - size_t len = _lv_txt_ap_calc_bytes_cnt(text); + const size_t text_len = get_text_length(text); - label->text = lv_mem_realloc(label->text, len); + /*If set its own text then reallocate it (maybe its size changed)*/ + if(label->text == text && label->static_txt == 0) { + label->text = lv_realloc(label->text, text_len); LV_ASSERT_MALLOC(label->text); if(label->text == NULL) return; - _lv_txt_ap_proc(label->text, label->text); -#else - label->text = lv_mem_realloc(label->text, strlen(label->text) + 1); +#if LV_USE_ARABIC_PERSIAN_CHARS + _lv_text_ap_proc(label->text, label->text); #endif - LV_ASSERT_MALLOC(label->text); - if(label->text == NULL) return; } else { /*Free the old text*/ if(label->text != NULL && label->static_txt == 0) { - lv_mem_free(label->text); + lv_free(label->text); label->text = NULL; } -#if LV_USE_ARABIC_PERSIAN_CHARS - /*Get the size of the text and process it*/ - size_t len = _lv_txt_ap_calc_bytes_cnt(text); - - label->text = lv_mem_alloc(len); + label->text = lv_malloc(text_len); LV_ASSERT_MALLOC(label->text); if(label->text == NULL) return; - _lv_txt_ap_proc(text, label->text); -#else - /*Get the size of the text*/ - size_t len = strlen(text) + 1; - - /*Allocate space for the new text*/ - label->text = lv_mem_alloc(len); - LV_ASSERT_MALLOC(label->text); - if(label->text == NULL) return; - strcpy(label->text, text); -#endif + copy_text_to_label(label, text); /*Now the text is dynamically allocated*/ label->static_txt = 0; @@ -159,13 +148,13 @@ void lv_label_set_text_fmt(lv_obj_t * obj, const char * fmt, ...) } if(label->text != NULL && label->static_txt == 0) { - lv_mem_free(label->text); + lv_free(label->text); label->text = NULL; } va_list args; va_start(args, fmt); - label->text = _lv_txt_set_text_vfmt(fmt, args); + label->text = _lv_text_set_text_vfmt(fmt, args); va_end(args); label->static_txt = 0; /*Now the text is dynamically allocated*/ @@ -178,7 +167,7 @@ void lv_label_set_text_static(lv_obj_t * obj, const char * text) lv_label_t * label = (lv_label_t *)obj; if(label->static_txt == 0 && label->text != NULL) { - lv_mem_free(label->text); + lv_free(label->text); label->text = NULL; } @@ -197,10 +186,9 @@ void lv_label_set_long_mode(lv_obj_t * obj, lv_label_long_mode_t long_mode) lv_label_t * label = (lv_label_t *)obj; /*Delete the old animation (if exists)*/ - lv_anim_del(obj, set_ofs_x_anim); - lv_anim_del(obj, set_ofs_y_anim); - label->offset.x = 0; - label->offset.y = 0; + lv_anim_delete(obj, set_ofs_x_anim); + lv_anim_delete(obj, set_ofs_y_anim); + lv_point_set(&label->offset, 0, 0); if(long_mode == LV_LABEL_LONG_SCROLL || long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR || long_mode == LV_LABEL_LONG_CLIP) label->expand = 1; @@ -216,20 +204,7 @@ void lv_label_set_long_mode(lv_obj_t * obj, lv_label_long_mode_t long_mode) lv_label_refr_text(obj); } -void lv_label_set_recolor(lv_obj_t * obj, bool en) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_label_t * label = (lv_label_t *)obj; - if(label->recolor == en) return; - - label->recolor = en == false ? 0 : 1; - - /*Refresh the text because the potential color codes in text needs to be hidden or revealed*/ - lv_label_refr_text(obj); -} - -void lv_label_set_text_sel_start(lv_obj_t * obj, uint32_t index) +void lv_label_set_text_selection_start(lv_obj_t * obj, uint32_t index) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -243,7 +218,7 @@ void lv_label_set_text_sel_start(lv_obj_t * obj, uint32_t index) #endif } -void lv_label_set_text_sel_end(lv_obj_t * obj, uint32_t index) +void lv_label_set_text_selection_end(lv_obj_t * obj, uint32_t index) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -275,22 +250,14 @@ lv_label_long_mode_t lv_label_get_long_mode(const lv_obj_t * obj) return label->long_mode; } -bool lv_label_get_recolor(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_label_t * label = (lv_label_t *)obj; - return label->recolor == 0 ? false : true; -} - void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t * pos) { LV_ASSERT_OBJ(obj, MY_CLASS); LV_ASSERT_NULL(pos); lv_label_t * label = (lv_label_t *)obj; - const char * txt = lv_label_get_text(obj); - lv_text_align_t align = lv_obj_calculate_style_text_align(obj, LV_PART_MAIN, txt); + const char * txt = lv_label_get_text(obj); + const lv_text_align_t align = lv_obj_calculate_style_text_align(obj, LV_PART_MAIN, txt); if(txt[0] == '\0') { pos->y = 0; @@ -304,32 +271,32 @@ void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t case LV_TEXT_ALIGN_CENTER: pos->x = lv_obj_get_content_width(obj) / 2; break; + default: + break; } return; } - lv_area_t txt_coords; - lv_obj_get_content_coords(obj, &txt_coords); - - uint32_t line_start = 0; - uint32_t new_line_start = 0; - lv_coord_t max_w = lv_area_get_width(&txt_coords); - const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); - lv_coord_t letter_height = lv_font_get_line_height(font); - lv_coord_t y = 0; - lv_text_flag_t flag = LV_TEXT_FLAG_NONE; - - if(label->recolor != 0) flag |= LV_TEXT_FLAG_RECOLOR; - if(label->expand != 0) flag |= LV_TEXT_FLAG_EXPAND; + lv_text_flag_t flag = get_label_flags(label); if(lv_obj_get_style_width(obj, LV_PART_MAIN) == LV_SIZE_CONTENT && !obj->w_layout) flag |= LV_TEXT_FLAG_FIT; - uint32_t byte_id = _lv_txt_encoded_get_byte_id(txt, char_id); + const uint32_t byte_id = _lv_text_encoded_get_byte_id(txt, char_id); + /*Search the line of the index letter*/ + const int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + const int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); - /*Search the line of the index letter*/; + const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); + const int32_t letter_height = lv_font_get_line_height(font); + + lv_area_t txt_coords; + lv_obj_get_content_coords(obj, &txt_coords); + const int32_t max_w = lv_area_get_width(&txt_coords); + + int32_t y = 0; + uint32_t line_start = 0; + uint32_t new_line_start = 0; while(txt[new_line_start] != '\0') { - new_line_start += _lv_txt_get_next_line(&txt[line_start], font, letter_space, max_w, NULL, flag); + new_line_start += _lv_text_get_next_line(&txt[line_start], font, letter_space, max_w, NULL, flag); if(byte_id < new_line_start || txt[new_line_start] == '\0') break; /*The line of 'index' letter begins at 'line_start'*/ @@ -358,7 +325,7 @@ void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t bidi_txt = &txt[line_start]; } else { - uint32_t line_char_id = _lv_txt_encoded_get_char_id(&txt[line_start], byte_id - line_start); + uint32_t line_char_id = _lv_text_encoded_get_char_id(&txt[line_start], byte_id - line_start); bool is_rtl; uint32_t visual_char_pos = _lv_bidi_get_visual_pos(&txt[line_start], &mutable_bidi_txt, new_line_start - line_start, @@ -366,7 +333,7 @@ void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t bidi_txt = mutable_bidi_txt; if(is_rtl) visual_char_pos++; - visual_byte_pos = _lv_txt_encoded_get_byte_id(bidi_txt, visual_char_pos); + visual_byte_pos = _lv_text_encoded_get_byte_id(bidi_txt, visual_char_pos); } #else bidi_txt = &txt[line_start]; @@ -374,31 +341,22 @@ void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t #endif /*Calculate the x coordinate*/ - lv_coord_t x = lv_txt_get_width(bidi_txt, visual_byte_pos, font, letter_space, flag); + int32_t x = lv_text_get_width(bidi_txt, visual_byte_pos, font, letter_space); if(char_id != line_start) x += letter_space; - if(align == LV_TEXT_ALIGN_CENTER) { - lv_coord_t line_w; - line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, letter_space, flag); - x += lv_area_get_width(&txt_coords) / 2 - line_w / 2; - - } - else if(align == LV_TEXT_ALIGN_RIGHT) { - lv_coord_t line_w; - line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, letter_space, flag); - - x += lv_area_get_width(&txt_coords) - line_w; - } + uint32_t length = new_line_start - line_start; + calculate_x_coordinate(&x, align, bidi_txt, length, font, letter_space, &txt_coords); pos->x = x; pos->y = y; #if LV_USE_BIDI - if(mutable_bidi_txt) lv_mem_buf_release(mutable_bidi_txt); + if(mutable_bidi_txt) lv_free(mutable_bidi_txt); #endif } -uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in) +uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in, bool bidi) { + LV_UNUSED(bidi); LV_ASSERT_OBJ(obj, MY_CLASS); LV_ASSERT_NULL(pos_in); lv_label_t * label = (lv_label_t *)obj; @@ -412,32 +370,26 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in) const char * txt = lv_label_get_text(obj); uint32_t line_start = 0; uint32_t new_line_start = 0; - lv_coord_t max_w = lv_area_get_width(&txt_coords); + int32_t max_w = lv_area_get_width(&txt_coords); const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); - lv_coord_t letter_height = lv_font_get_line_height(font); - lv_coord_t y = 0; - lv_text_flag_t flag = LV_TEXT_FLAG_NONE; - uint32_t logical_pos; - char * bidi_txt; + const int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + const int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + const int32_t letter_height = lv_font_get_line_height(font); + int32_t y = 0; - if(label->recolor != 0) flag |= LV_TEXT_FLAG_RECOLOR; - if(label->expand != 0) flag |= LV_TEXT_FLAG_EXPAND; + lv_text_flag_t flag = get_label_flags(label); if(lv_obj_get_style_width(obj, LV_PART_MAIN) == LV_SIZE_CONTENT && !obj->w_layout) flag |= LV_TEXT_FLAG_FIT; - lv_text_align_t align = lv_obj_calculate_style_text_align(obj, LV_PART_MAIN, label->text); - /*Search the line of the index letter*/; while(txt[line_start] != '\0') { - new_line_start += _lv_txt_get_next_line(&txt[line_start], font, letter_space, max_w, NULL, flag); + new_line_start += _lv_text_get_next_line(&txt[line_start], font, letter_space, max_w, NULL, flag); if(pos.y <= y + letter_height) { /*The line is found (stored in 'line_start')*/ /*Include the NULL terminator in the last line*/ uint32_t tmp = new_line_start; uint32_t letter; - letter = _lv_txt_encoded_prev(txt, &tmp); + letter = _lv_text_encoded_prev(txt, &tmp); if(letter != '\n' && txt[new_line_start] == '\0') new_line_start++; break; } @@ -446,29 +398,27 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in) line_start = new_line_start; } + char * bidi_txt; + #if LV_USE_BIDI - bidi_txt = lv_mem_buf_get(new_line_start - line_start + 1); - uint32_t txt_len = new_line_start - line_start; - if(new_line_start > 0 && txt[new_line_start - 1] == '\0' && txt_len > 0) txt_len--; - _lv_bidi_process_paragraph(txt + line_start, bidi_txt, txt_len, lv_obj_get_style_base_dir(obj, LV_PART_MAIN), NULL, 0); -#else - bidi_txt = (char *)txt + line_start; + uint32_t txt_len; + if(bidi) { + bidi_txt = lv_malloc(new_line_start - line_start + 1); + txt_len = new_line_start - line_start; + if(new_line_start > 0 && txt[new_line_start - 1] == '\0' && txt_len > 0) txt_len--; + _lv_bidi_process_paragraph(txt + line_start, bidi_txt, txt_len, lv_obj_get_style_base_dir(obj, LV_PART_MAIN), NULL, 0); + } + else #endif + { + bidi_txt = (char *)txt + line_start; + } /*Calculate the x coordinate*/ - lv_coord_t x = 0; - if(align == LV_TEXT_ALIGN_CENTER) { - lv_coord_t line_w; - line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, letter_space, flag); - x += lv_area_get_width(&txt_coords) / 2 - line_w / 2; - } - else if(align == LV_TEXT_ALIGN_RIGHT) { - lv_coord_t line_w; - line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, letter_space, flag); - x += lv_area_get_width(&txt_coords) - line_w; - } - - lv_text_cmd_state_t cmd_state = LV_TEXT_CMD_STATE_WAIT; + int32_t x = 0; + const lv_text_align_t align = lv_obj_calculate_style_text_align(obj, LV_PART_MAIN, label->text); + uint32_t length = new_line_start - line_start; + calculate_x_coordinate(&x, align, bidi_txt, length, font, letter_space, &txt_coords); uint32_t i = 0; uint32_t i_act = i; @@ -479,16 +429,9 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in) /*Be careful 'i' already points to the next character*/ uint32_t letter; uint32_t letter_next; - _lv_txt_encoded_letter_next_2(bidi_txt, &letter, &letter_next, &i); + _lv_text_encoded_letter_next_2(bidi_txt, &letter, &letter_next, &i); - /*Handle the recolor command*/ - if((flag & LV_TEXT_FLAG_RECOLOR) != 0) { - if(_lv_txt_is_cmd(&cmd_state, bidi_txt[i]) != false) { - continue; /*Skip the letter if it is part of a command*/ - } - } - - lv_coord_t gw = lv_font_get_glyph_width(font, letter, letter_next); + int32_t gw = lv_font_get_glyph_width(font, letter, letter_next); /*Finish if the x position or the last char of the next line is reached*/ if(pos.x < x + gw || i + line_start == new_line_start || txt[i_act + line_start] == '\0') { @@ -501,24 +444,29 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in) } } + uint32_t logical_pos; #if LV_USE_BIDI - /*Handle Bidi*/ - uint32_t cid = _lv_txt_encoded_get_char_id(bidi_txt, i); - if(txt[line_start + i] == '\0') { - logical_pos = i; + if(bidi) { + /*Handle Bidi*/ + uint32_t cid = _lv_text_encoded_get_char_id(bidi_txt, i); + if(txt[line_start + i] == '\0') { + logical_pos = i; + } + else { + bool is_rtl; + logical_pos = _lv_bidi_get_logical_pos(&txt[line_start], NULL, + txt_len, lv_obj_get_style_base_dir(obj, LV_PART_MAIN), cid, &is_rtl); + if(is_rtl) logical_pos++; + } + lv_free(bidi_txt); } - else { - bool is_rtl; - logical_pos = _lv_bidi_get_logical_pos(&txt[line_start], NULL, - txt_len, lv_obj_get_style_base_dir(obj, LV_PART_MAIN), cid, &is_rtl); - if(is_rtl) logical_pos++; - } - lv_mem_buf_release(bidi_txt); -#else - logical_pos = _lv_txt_encoded_get_char_id(bidi_txt, i); + else #endif + { + logical_pos = _lv_text_encoded_get_char_id(bidi_txt, i); + } - return logical_pos + _lv_txt_encoded_get_char_id(txt, line_start); + return logical_pos + _lv_text_encoded_get_char_id(txt, line_start); } bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos) @@ -532,23 +480,19 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos) lv_label_t * label = (lv_label_t *)obj; uint32_t line_start = 0; uint32_t new_line_start = 0; - lv_coord_t max_w = lv_area_get_width(&txt_coords); + const int32_t max_w = lv_area_get_width(&txt_coords); const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); - lv_coord_t letter_height = lv_font_get_line_height(font); - lv_text_align_t align = lv_obj_calculate_style_text_align(obj, LV_PART_MAIN, label->text); + const int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + const int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + const int32_t letter_height = lv_font_get_line_height(font); - lv_coord_t y = 0; - lv_text_flag_t flag = LV_TEXT_FLAG_NONE; - - if(label->recolor != 0) flag |= LV_TEXT_FLAG_RECOLOR; - if(label->expand != 0) flag |= LV_TEXT_FLAG_EXPAND; + lv_text_flag_t flag = get_label_flags(label); if(lv_obj_get_style_width(obj, LV_PART_MAIN) == LV_SIZE_CONTENT && !obj->w_layout) flag |= LV_TEXT_FLAG_FIT; - /*Search the line of the index letter*/; + /*Search the line of the index letter*/ + int32_t y = 0; while(txt[line_start] != '\0') { - new_line_start += _lv_txt_get_next_line(&txt[line_start], font, letter_space, max_w, NULL, flag); + new_line_start += _lv_text_get_next_line(&txt[line_start], font, letter_space, max_w, NULL, flag); if(pos->y <= y + letter_height) break; /*The line is found (stored in 'line_start')*/ y += letter_height + line_space; @@ -557,21 +501,19 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos) } /*Calculate the x coordinate*/ - lv_coord_t x = 0; - lv_coord_t last_x = 0; + const lv_text_align_t align = lv_obj_calculate_style_text_align(obj, LV_PART_MAIN, label->text); + + int32_t x = 0; if(align == LV_TEXT_ALIGN_CENTER) { - lv_coord_t line_w; - line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, letter_space, flag); + const int32_t line_w = lv_text_get_width(&txt[line_start], new_line_start - line_start, font, letter_space); x += lv_area_get_width(&txt_coords) / 2 - line_w / 2; } else if(align == LV_TEXT_ALIGN_RIGHT) { - lv_coord_t line_w; - line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, letter_space, flag); + const int32_t line_w = lv_text_get_width(&txt[line_start], new_line_start - line_start, font, letter_space); x += lv_area_get_width(&txt_coords) - line_w; } - lv_text_cmd_state_t cmd_state = LV_TEXT_CMD_STATE_WAIT; - + int32_t last_x = 0; uint32_t i = line_start; uint32_t i_current = i; uint32_t letter = '\0'; @@ -581,14 +523,8 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos) while(i <= new_line_start - 1) { /*Get the current letter and the next letter for kerning*/ /*Be careful 'i' already points to the next character*/ - _lv_txt_encoded_letter_next_2(txt, &letter, &letter_next, &i); + _lv_text_encoded_letter_next_2(txt, &letter, &letter_next, &i); - /*Handle the recolor command*/ - if((flag & LV_TEXT_FLAG_RECOLOR) != 0) { - if(_lv_txt_is_cmd(&cmd_state, txt[i]) != false) { - continue; /*Skip the letter if it is part of a command*/ - } - } last_x = x; x += lv_font_get_glyph_width(font, letter, letter_next); if(pos->x < x) { @@ -600,7 +536,7 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos) } } - int32_t max_diff = lv_font_get_glyph_width(font, letter, letter_next) + letter_space + 1; + const int32_t max_diff = lv_font_get_glyph_width(font, letter, letter_next) + letter_space + 1; return (pos->x >= (last_x - letter_space) && pos->x <= (last_x + max_diff)); } @@ -611,7 +547,6 @@ uint32_t lv_label_get_text_selection_start(const lv_obj_t * obj) #if LV_LABEL_TEXT_SELECTION lv_label_t * label = (lv_label_t *)obj; return label->sel_start; - #else LV_UNUSED(obj); /*Unused*/ return LV_LABEL_TEXT_SELECTION_OFF; @@ -648,18 +583,18 @@ void lv_label_ins_text(lv_obj_t * obj, uint32_t pos, const char * txt) lv_obj_invalidate(obj); /*Allocate space for the new text*/ - size_t old_len = strlen(label->text); - size_t ins_len = strlen(txt); + size_t old_len = lv_strlen(label->text); + size_t ins_len = lv_strlen(txt); size_t new_len = ins_len + old_len; - label->text = lv_mem_realloc(label->text, new_len + 1); + label->text = lv_realloc(label->text, new_len + 1); LV_ASSERT_MALLOC(label->text); if(label->text == NULL) return; if(pos == LV_LABEL_POS_LAST) { - pos = _lv_txt_get_encoded_length(label->text); + pos = _lv_text_get_encoded_length(label->text); } - _lv_txt_ins(label->text, pos, txt); + _lv_text_ins(label->text, pos, txt); lv_label_set_text(obj, NULL); } @@ -669,13 +604,13 @@ void lv_label_cut_text(lv_obj_t * obj, uint32_t pos, uint32_t cnt) lv_label_t * label = (lv_label_t *)obj; /*Can not append to static text*/ - if(label->static_txt != 0) return; + if(label->static_txt) return; lv_obj_invalidate(obj); char * label_txt = lv_label_get_text(obj); /*Delete the characters*/ - _lv_txt_cut(label_txt, pos, cnt); + _lv_text_cut(label_txt, pos, cnt); /*Refresh the label*/ lv_label_refr_text(obj); @@ -694,11 +629,9 @@ static void lv_label_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) label->text = NULL; label->static_txt = 0; - label->recolor = 0; label->dot_end = LV_LABEL_DOT_END_INV; label->long_mode = LV_LABEL_LONG_WRAP; - label->offset.x = 0; - label->offset.y = 0; + lv_point_set(&label->offset, 0, 0); #if LV_LABEL_LONG_TXT_HINT label->hint.line_start = -1; @@ -713,10 +646,9 @@ static void lv_label_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) label->dot.tmp_ptr = NULL; label->dot_tmp_alloc = 0; - lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICKABLE); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_CLICKABLE); lv_label_set_long_mode(obj, LV_LABEL_LONG_WRAP); - lv_label_set_text(obj, "Text"); - + lv_label_set_text(obj, LV_LABEL_DEFAULT_TEXT); LV_TRACE_OBJ_CREATE("finished"); } @@ -727,7 +659,7 @@ static void lv_label_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) lv_label_t * label = (lv_label_t *)obj; lv_label_dot_tmp_free(obj); - if(!label->static_txt) lv_mem_free(label->text); + if(!label->static_txt) lv_free(label->text); label->text = NULL; } @@ -735,16 +667,14 @@ static void lv_label_event(const lv_obj_class_t * class_p, lv_event_t * e) { LV_UNUSED(class_p); - lv_res_t res; - /*Call the ancestor's event handler*/ - res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; + const lv_result_t res = lv_obj_event_base(MY_CLASS, e); + if(res != LV_RESULT_OK) return; - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + const lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * obj = lv_event_get_current_target(e); - if(code == LV_EVENT_STYLE_CHANGED) { + if((code == LV_EVENT_STYLE_CHANGED) || (code == LV_EVENT_SIZE_CHANGED)) { /*Revert dots for proper refresh*/ lv_label_revert_dots(obj); lv_label_refr_text(obj); @@ -755,58 +685,58 @@ static void lv_label_event(const lv_obj_class_t * class_p, lv_event_t * e) * To avoid this add some extra draw area. * font_h / 4 is an empirical value. */ const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t font_h = lv_font_get_line_height(font); + const int32_t font_h = lv_font_get_line_height(font); lv_event_set_ext_draw_size(e, font_h / 4); } - else if(code == LV_EVENT_SIZE_CHANGED) { - lv_label_revert_dots(obj); - lv_label_refr_text(obj); - } else if(code == LV_EVENT_GET_SELF_SIZE) { - lv_point_t size; lv_label_t * label = (lv_label_t *)obj; - const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - lv_text_flag_t flag = LV_TEXT_FLAG_NONE; - if(label->recolor != 0) flag |= LV_TEXT_FLAG_RECOLOR; - if(label->expand != 0) flag |= LV_TEXT_FLAG_EXPAND; + if(label->invalid_size_cache) { + const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); + int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + lv_text_flag_t flag = LV_TEXT_FLAG_NONE; + if(label->expand != 0) flag |= LV_TEXT_FLAG_EXPAND; - lv_coord_t w = lv_obj_get_content_width(obj); - if(lv_obj_get_style_width(obj, LV_PART_MAIN) == LV_SIZE_CONTENT && !obj->w_layout) w = LV_COORD_MAX; - else w = lv_obj_get_content_width(obj); + int32_t w = lv_obj_get_content_width(obj); + if(lv_obj_get_style_width(obj, LV_PART_MAIN) == LV_SIZE_CONTENT && !obj->w_layout) w = LV_COORD_MAX; + else w = lv_obj_get_content_width(obj); - lv_txt_get_size(&size, label->text, font, letter_space, line_space, w, flag); + lv_text_get_size(&label->size_cache, label->text, font, letter_space, line_space, w, flag); + label->invalid_size_cache = false; + } lv_point_t * self_size = lv_event_get_param(e); - self_size->x = LV_MAX(self_size->x, size.x); - self_size->y = LV_MAX(self_size->y, size.y); + self_size->x = LV_MAX(self_size->x, label->size_cache.x); + self_size->y = LV_MAX(self_size->y, label->size_cache.y); } else if(code == LV_EVENT_DRAW_MAIN) { draw_main(e); } } - static void draw_main(lv_event_t * e) { - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_label_t * label = (lv_label_t *)obj; - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); lv_area_t txt_coords; lv_obj_get_content_coords(obj, &txt_coords); lv_text_flag_t flag = LV_TEXT_FLAG_NONE; - if(label->recolor != 0) flag |= LV_TEXT_FLAG_RECOLOR; if(label->expand != 0) flag |= LV_TEXT_FLAG_EXPAND; if(lv_obj_get_style_width(obj, LV_PART_MAIN) == LV_SIZE_CONTENT && !obj->w_layout) flag |= LV_TEXT_FLAG_FIT; lv_draw_label_dsc_t label_draw_dsc; lv_draw_label_dsc_init(&label_draw_dsc); - + label_draw_dsc.text = label->text; label_draw_dsc.ofs_x = label->offset.x; label_draw_dsc.ofs_y = label->offset.y; +#if LV_LABEL_LONG_TXT_HINT + if(label->long_mode != LV_LABEL_LONG_SCROLL_CIRCULAR && lv_area_get_height(&txt_coords) >= LV_LABEL_HINT_HEIGHT_LIMIT) { + label_draw_dsc.hint = &label->hint; + } +#endif label_draw_dsc.flag = flag; lv_obj_init_draw_label_dsc(obj, LV_PART_MAIN, &label_draw_dsc); @@ -824,48 +754,41 @@ static void draw_main(lv_event_t * e) if((label->long_mode == LV_LABEL_LONG_SCROLL || label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) && (label_draw_dsc.align == LV_TEXT_ALIGN_CENTER || label_draw_dsc.align == LV_TEXT_ALIGN_RIGHT)) { lv_point_t size; - lv_txt_get_size(&size, label->text, label_draw_dsc.font, label_draw_dsc.letter_space, label_draw_dsc.line_space, - LV_COORD_MAX, flag); + lv_text_get_size(&size, label->text, label_draw_dsc.font, label_draw_dsc.letter_space, label_draw_dsc.line_space, + LV_COORD_MAX, flag); if(size.x > lv_area_get_width(&txt_coords)) { label_draw_dsc.align = LV_TEXT_ALIGN_LEFT; } } -#if LV_LABEL_LONG_TXT_HINT - lv_draw_label_hint_t * hint = &label->hint; - if(label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR || lv_area_get_height(&txt_coords) < LV_LABEL_HINT_HEIGHT_LIMIT) - hint = NULL; - -#else - /*Just for compatibility*/ - lv_draw_label_hint_t * hint = NULL; -#endif lv_area_t txt_clip; - bool is_common = _lv_area_intersect(&txt_clip, &txt_coords, draw_ctx->clip_area); - if(!is_common) return; + bool is_common = _lv_area_intersect(&txt_clip, &txt_coords, &layer->_clip_area); + if(!is_common) { + return; + } if(label->long_mode == LV_LABEL_LONG_WRAP) { - lv_coord_t s = lv_obj_get_scroll_top(obj); + int32_t s = lv_obj_get_scroll_top(obj); lv_area_move(&txt_coords, 0, -s); txt_coords.y2 = obj->coords.y2; } if(label->long_mode == LV_LABEL_LONG_SCROLL || label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) { - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &txt_clip; - lv_draw_label(draw_ctx, &label_draw_dsc, &txt_coords, label->text, hint); - draw_ctx->clip_area = clip_area_ori; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = txt_clip; + lv_draw_label(layer, &label_draw_dsc, &txt_coords); + layer->_clip_area = clip_area_ori; } else { - lv_draw_label(draw_ctx, &label_draw_dsc, &txt_coords, label->text, hint); + lv_draw_label(layer, &label_draw_dsc, &txt_coords); } - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &txt_clip; + lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = txt_clip; if(label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) { lv_point_t size; - lv_txt_get_size(&size, label->text, label_draw_dsc.font, label_draw_dsc.letter_space, label_draw_dsc.line_space, - LV_COORD_MAX, flag); + lv_text_get_size(&size, label->text, label_draw_dsc.font, label_draw_dsc.letter_space, label_draw_dsc.line_space, + LV_COORD_MAX, flag); /*Draw the text again on label to the original to make a circular effect */ if(size.x > lv_area_get_width(&txt_coords)) { @@ -873,7 +796,7 @@ static void draw_main(lv_event_t * e) lv_font_get_glyph_width(label_draw_dsc.font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT; label_draw_dsc.ofs_y = label->offset.y; - lv_draw_label(draw_ctx, &label_draw_dsc, &txt_coords, label->text, hint); + lv_draw_label(layer, &label_draw_dsc, &txt_coords); } /*Draw the text again below the original to make a circular effect */ @@ -881,11 +804,36 @@ static void draw_main(lv_event_t * e) label_draw_dsc.ofs_x = label->offset.x; label_draw_dsc.ofs_y = label->offset.y + size.y + lv_font_get_line_height(label_draw_dsc.font); - lv_draw_label(draw_ctx, &label_draw_dsc, &txt_coords, label->text, hint); + lv_draw_label(layer, &label_draw_dsc, &txt_coords); } } - draw_ctx->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; +} + +static void overwrite_anim_property(lv_anim_t * dest, const lv_anim_t * src, lv_label_long_mode_t mode) +{ + switch(mode) { + case LV_LABEL_LONG_SCROLL: + /** If the dest animation is already running, overwrite is not allowed */ + if(dest->act_time <= 0) + dest->act_time = src->act_time; + dest->repeat_cnt = src->repeat_cnt; + dest->repeat_delay = src->repeat_delay; + dest->completed_cb = src->completed_cb; + dest->playback_delay = src->playback_delay; + break; + case LV_LABEL_LONG_SCROLL_CIRCULAR: + /** If the dest animation is already running, overwrite is not allowed */ + if(dest->act_time <= 0) + dest->act_time = src->act_time; + dest->repeat_cnt = src->repeat_cnt; + dest->repeat_delay = src->repeat_delay; + dest->completed_cb = src->completed_cb; + break; + default: + break; + } } /** @@ -899,29 +847,30 @@ static void lv_label_refr_text(lv_obj_t * obj) #if LV_LABEL_LONG_TXT_HINT label->hint.line_start = -1; /*The hint is invalid if the text changes*/ #endif + label->invalid_size_cache = true; lv_area_t txt_coords; lv_obj_get_content_coords(obj, &txt_coords); - lv_coord_t max_w = lv_area_get_width(&txt_coords); + int32_t max_w = lv_area_get_width(&txt_coords); const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); /*Calc. the height and longest line*/ lv_point_t size; lv_text_flag_t flag = LV_TEXT_FLAG_NONE; - if(label->recolor != 0) flag |= LV_TEXT_FLAG_RECOLOR; if(label->expand != 0) flag |= LV_TEXT_FLAG_EXPAND; if(lv_obj_get_style_width(obj, LV_PART_MAIN) == LV_SIZE_CONTENT && !obj->w_layout) flag |= LV_TEXT_FLAG_FIT; - lv_txt_get_size(&size, label->text, font, letter_space, line_space, max_w, flag); + lv_text_get_size(&size, label->text, font, letter_space, line_space, max_w, flag); lv_obj_refresh_self_size(obj); /*In scroll mode start an offset animation*/ if(label->long_mode == LV_LABEL_LONG_SCROLL) { - uint16_t anim_speed = lv_obj_get_style_anim_speed(obj, LV_PART_MAIN); - if(anim_speed == 0) anim_speed = LV_LABEL_DEF_SCROLL_SPEED; + const lv_anim_t * anim_template = lv_obj_get_style_anim(obj, LV_PART_MAIN); + uint32_t anim_time = lv_obj_get_style_anim_duration(obj, LV_PART_MAIN); + if(anim_time == 0) anim_time = LV_LABEL_DEF_SCROLL_SPEED; lv_anim_t a; lv_anim_init(&a); lv_anim_set_var(&a, obj); @@ -931,8 +880,10 @@ static void lv_label_refr_text(lv_obj_t * obj) bool hor_anim = false; if(size.x > lv_area_get_width(&txt_coords)) { + int32_t start = 0; + int32_t end = 0; + #if LV_USE_BIDI - int32_t start, end; lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN); if(base_dir == LV_BASE_DIR_AUTO) @@ -946,12 +897,11 @@ static void lv_label_refr_text(lv_obj_t * obj) start = 0; end = lv_area_get_width(&txt_coords) - size.x; } +#else + end = lv_area_get_width(&txt_coords) - size.x; +#endif lv_anim_set_values(&a, start, end); -#else - lv_anim_set_values(&a, 0, lv_area_get_width(&txt_coords) - size.x); - lv_anim_set_exec_cb(&a, set_ofs_x_anim); -#endif lv_anim_set_exec_cb(&a, set_ofs_x_anim); lv_anim_t * anim_cur = lv_anim_get(obj, set_ofs_x_anim); @@ -961,7 +911,7 @@ static void lv_label_refr_text(lv_obj_t * obj) act_time = anim_cur->act_time; playback_now = anim_cur->playback_now; } - if(act_time < a.time) { + if(act_time < a.duration) { a.act_time = act_time; /*To keep the old position*/ a.early_apply = 0; if(playback_now) { @@ -974,14 +924,18 @@ static void lv_label_refr_text(lv_obj_t * obj) } } - lv_anim_set_time(&a, lv_anim_speed_to_time(anim_speed, a.start_value, a.end_value)); - lv_anim_set_playback_time(&a, a.time); + lv_anim_set_duration(&a, anim_time); + lv_anim_set_playback_duration(&a, a.duration); + + /*If a template animation exists, overwrite some property*/ + if(anim_template) + overwrite_anim_property(&a, anim_template, label->long_mode); lv_anim_start(&a); hor_anim = true; } else { /*Delete the offset animation if not required*/ - lv_anim_del(obj, set_ofs_x_anim); + lv_anim_delete(obj, set_ofs_x_anim); label->offset.x = 0; } @@ -996,7 +950,7 @@ static void lv_label_refr_text(lv_obj_t * obj) act_time = anim_cur->act_time; playback_now = anim_cur->playback_now; } - if(act_time < a.time) { + if(act_time < a.duration) { a.act_time = act_time; /*To keep the old position*/ a.early_apply = 0; if(playback_now) { @@ -1009,21 +963,25 @@ static void lv_label_refr_text(lv_obj_t * obj) } } - lv_anim_set_time(&a, lv_anim_speed_to_time(anim_speed, a.start_value, a.end_value)); - lv_anim_set_playback_time(&a, a.time); + lv_anim_set_duration(&a, anim_time); + lv_anim_set_playback_duration(&a, a.duration); + + /*If a template animation exists, overwrite some property*/ + if(anim_template) + overwrite_anim_property(&a, anim_template, label->long_mode); lv_anim_start(&a); } else { /*Delete the offset animation if not required*/ - lv_anim_del(obj, set_ofs_y_anim); + lv_anim_delete(obj, set_ofs_y_anim); label->offset.y = 0; } } /*In roll inf. mode keep the size but start offset animations*/ else if(label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) { const lv_anim_t * anim_template = lv_obj_get_style_anim(obj, LV_PART_MAIN); - uint16_t anim_speed = lv_obj_get_style_anim_speed(obj, LV_PART_MAIN); - if(anim_speed == 0) anim_speed = LV_LABEL_DEF_SCROLL_SPEED; + uint32_t anim_time = lv_obj_get_style_anim_duration(obj, LV_PART_MAIN); + if(anim_time == 0) anim_time = LV_LABEL_DEF_SCROLL_SPEED; lv_anim_t a; lv_anim_init(&a); lv_anim_set_var(&a, obj); @@ -1052,17 +1010,16 @@ static void lv_label_refr_text(lv_obj_t * obj) lv_anim_set_values(&a, 0, -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT); #endif lv_anim_set_exec_cb(&a, set_ofs_x_anim); - lv_anim_set_time(&a, lv_anim_speed_to_time(anim_speed, a.start_value, a.end_value)); + lv_anim_set_duration(&a, anim_time); lv_anim_t * anim_cur = lv_anim_get(obj, set_ofs_x_anim); int32_t act_time = anim_cur ? anim_cur->act_time : 0; - /*If a template animation exists, consider it's start delay and repeat delay*/ + /*If a template animation exists, overwrite some property*/ if(anim_template) { - a.act_time = anim_template->act_time; - a.repeat_delay = anim_template->repeat_delay; + overwrite_anim_property(&a, anim_template, label->long_mode); } - else if(act_time < a.time) { + else if(act_time < a.duration) { a.act_time = act_time; /*To keep the old position when the label text is updated mid-scrolling*/ a.early_apply = 0; } @@ -1072,24 +1029,23 @@ static void lv_label_refr_text(lv_obj_t * obj) } else { /*Delete the offset animation if not required*/ - lv_anim_del(obj, set_ofs_x_anim); + lv_anim_delete(obj, set_ofs_x_anim); label->offset.x = 0; } if(size.y > lv_area_get_height(&txt_coords) && hor_anim == false) { lv_anim_set_values(&a, 0, -size.y - (lv_font_get_line_height(font))); lv_anim_set_exec_cb(&a, set_ofs_y_anim); - lv_anim_set_time(&a, lv_anim_speed_to_time(anim_speed, a.start_value, a.end_value)); + lv_anim_set_duration(&a, anim_time); lv_anim_t * anim_cur = lv_anim_get(obj, set_ofs_y_anim); int32_t act_time = anim_cur ? anim_cur->act_time : 0; - /*If a template animation exists, consider it's start delay and repeat delay*/ + /*If a template animation exists, overwrite some property*/ if(anim_template) { - a.act_time = anim_template->act_time; - a.repeat_delay = anim_template->repeat_delay; + overwrite_anim_property(&a, anim_template, label->long_mode); } - else if(act_time < a.time) { + else if(act_time < a.duration) { a.act_time = act_time; /*To keep the old position when the label text is updated mid-scrolling*/ a.early_apply = 0; } @@ -1098,7 +1054,7 @@ static void lv_label_refr_text(lv_obj_t * obj) } else { /*Delete the offset animation if not required*/ - lv_anim_del(obj, set_ofs_y_anim); + lv_anim_delete(obj, set_ofs_y_anim); label->offset.y = 0; } } @@ -1109,12 +1065,12 @@ static void lv_label_refr_text(lv_obj_t * obj) else if(size.y <= lv_font_get_line_height(font)) { /*No dots are required for one-line texts*/ label->dot_end = LV_LABEL_DOT_END_INV; } - else if(_lv_txt_get_encoded_length(label->text) <= LV_LABEL_DOT_NUM) { /*Don't turn to dots all the characters*/ + else if(_lv_text_get_encoded_length(label->text) <= LV_LABEL_DOT_NUM) { /*Don't turn to dots all the characters*/ label->dot_end = LV_LABEL_DOT_END_INV; } else { lv_point_t p; - lv_coord_t y_overed; + int32_t y_overed; p.x = lv_area_get_width(&txt_coords) - (lv_font_get_glyph_width(font, '.', '.') + letter_space) * LV_LABEL_DOT_NUM; /*Shrink with dots*/ @@ -1130,13 +1086,13 @@ static void lv_label_refr_text(lv_obj_t * obj) p.y -= line_space; } - uint32_t letter_id = lv_label_get_letter_on(obj, &p); + uint32_t letter_id = lv_label_get_letter_on(obj, &p, false); /*Be sure there is space for the dots*/ - size_t txt_len = strlen(label->text); - uint32_t byte_id = _lv_txt_encoded_get_byte_id(label->text, letter_id); + size_t txt_len = lv_strlen(label->text); + uint32_t byte_id = _lv_text_encoded_get_byte_id(label->text, letter_id); while(byte_id + LV_LABEL_DOT_NUM > txt_len) { - _lv_txt_encoded_prev(label->text, &byte_id); + _lv_text_encoded_prev(label->text, &byte_id); letter_id--; } @@ -1145,8 +1101,8 @@ static void lv_label_refr_text(lv_obj_t * obj) uint32_t i; uint8_t len = 0; for(i = 0; i <= LV_LABEL_DOT_NUM; i++) { - len += _lv_txt_encoded_size(&label->text[byte_id]); - _lv_txt_encoded_next(label->text, &byte_id); + len += _lv_text_encoded_size(&label->text[byte_id]); + _lv_text_encoded_next(label->text, &byte_id); if(len > LV_LABEL_DOT_NUM || byte_id > txt_len) { break; } @@ -1168,25 +1124,25 @@ static void lv_label_refr_text(lv_obj_t * obj) lv_obj_invalidate(obj); } - static void lv_label_revert_dots(lv_obj_t * obj) { - lv_label_t * label = (lv_label_t *)obj; if(label->long_mode != LV_LABEL_LONG_DOT) return; if(label->dot_end == LV_LABEL_DOT_END_INV) return; - uint32_t letter_i = label->dot_end - LV_LABEL_DOT_NUM; - uint32_t byte_i = _lv_txt_encoded_get_byte_id(label->text, letter_i); + + const uint32_t letter_i = label->dot_end - LV_LABEL_DOT_NUM; + const uint32_t byte_i = _lv_text_encoded_get_byte_id(label->text, letter_i); /*Restore the characters*/ - uint8_t i = 0; + uint8_t i = 0; char * dot_tmp = lv_label_get_dot_tmp(obj); while(label->text[byte_i + i] != '\0') { label->text[byte_i + i] = dot_tmp[i]; i++; } label->text[byte_i + i] = dot_tmp[i]; + lv_label_dot_tmp_free(obj); label->dot_end = LV_LABEL_DOT_END_INV; @@ -1207,7 +1163,7 @@ static bool lv_label_set_dot_tmp(lv_obj_t * obj, char * data, uint32_t len) if(len > sizeof(char *)) { /*Memory needs to be allocated. Allocates an additional byte *for a NULL-terminator so it can be copied.*/ - label->dot.tmp_ptr = lv_mem_alloc(len + 1); + label->dot.tmp_ptr = lv_malloc(len + 1); if(label->dot.tmp_ptr == NULL) { LV_LOG_ERROR("Failed to allocate memory for dot_tmp_ptr"); return false; @@ -1249,13 +1205,12 @@ static void lv_label_dot_tmp_free(lv_obj_t * obj) { lv_label_t * label = (lv_label_t *)obj; if(label->dot_tmp_alloc && label->dot.tmp_ptr) { - lv_mem_free(label->dot.tmp_ptr); + lv_free(label->dot.tmp_ptr); } label->dot_tmp_alloc = false; label->dot.tmp_ptr = NULL; } - static void set_ofs_x_anim(void * obj, int32_t v) { lv_label_t * label = (lv_label_t *)obj; @@ -1270,5 +1225,51 @@ static void set_ofs_y_anim(void * obj, int32_t v) lv_obj_invalidate(obj); } +static size_t get_text_length(const char * text) +{ + size_t len = 0; +#if LV_USE_ARABIC_PERSIAN_CHARS + len = _lv_text_ap_calc_bytes_count(text); +#else + len = lv_strlen(text) + 1; +#endif + + return len; +} + +static void copy_text_to_label(lv_label_t * label, const char * text) +{ +#if LV_USE_ARABIC_PERSIAN_CHARS + _lv_text_ap_proc(text, label->text); +#else + lv_strcpy(label->text, text); +#endif +} + +static lv_text_flag_t get_label_flags(lv_label_t * label) +{ + lv_text_flag_t flag = LV_TEXT_FLAG_NONE; + + if(label->expand) flag |= LV_TEXT_FLAG_EXPAND; + + return flag; +} + +/* Function created because of this pattern be used in multiple functions */ +static void calculate_x_coordinate(int32_t * x, const lv_text_align_t align, const char * txt, uint32_t length, + const lv_font_t * font, int32_t letter_space, lv_area_t * txt_coords) +{ + if(align == LV_TEXT_ALIGN_CENTER) { + const int32_t line_w = lv_text_get_width(txt, length, font, letter_space); + *x += lv_area_get_width(txt_coords) / 2 - line_w / 2; + } + else if(align == LV_TEXT_ALIGN_RIGHT) { + const int32_t line_w = lv_text_get_width(txt, length, font, letter_space); + *x += lv_area_get_width(txt_coords) - line_w; + } + else { + /* Nothing to do */ + } +} #endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.h b/lib/libesp32_lvgl/lvgl/src/widgets/label/lv_label.h similarity index 84% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_label.h rename to lib/libesp32_lvgl/lvgl/src/widgets/label/lv_label.h index b31a63e59..7a6ea3d85 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_label.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/label/lv_label.h @@ -13,24 +13,28 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../lv_conf_internal.h" +#include "../../lv_conf_internal.h" #if LV_USE_LABEL != 0 #include -#include "../core/lv_obj.h" -#include "../font/lv_font.h" -#include "../font/lv_symbol_def.h" -#include "../misc/lv_txt.h" -#include "../draw/lv_draw.h" +#include "../../core/lv_obj.h" +#include "../../font/lv_font.h" +#include "../../font/lv_symbol_def.h" +#include "../../misc/lv_text.h" +#include "../../draw/lv_draw.h" /********************* * DEFINES *********************/ -#define LV_LABEL_WAIT_CHAR_COUNT 3 #define LV_LABEL_DOT_NUM 3 #define LV_LABEL_POS_LAST 0xFFFF #define LV_LABEL_TEXT_SELECTION_OFF LV_DRAW_LABEL_NO_TXT_SEL +#if LV_WIDGETS_HAS_DEFAULT_VALUE +#define LV_LABEL_DEFAULT_TEXT "Text" +#else +#define LV_LABEL_DEFAULT_TEXT "" +#endif LV_EXPORT_CONST_INT(LV_LABEL_DOT_NUM); LV_EXPORT_CONST_INT(LV_LABEL_POS_LAST); @@ -41,14 +45,19 @@ LV_EXPORT_CONST_INT(LV_LABEL_TEXT_SELECTION_OFF); **********************/ /** Long mode behaviors. Used in 'lv_label_ext_t'*/ -enum { - LV_LABEL_LONG_WRAP, /**< Keep the object width, wrap the too long lines and expand the object height*/ +enum _lv_label_long_mode_t { + LV_LABEL_LONG_WRAP, /**< Keep the object width, wrap lines longer than object width and expand the object height*/ LV_LABEL_LONG_DOT, /**< Keep the size and write dots at the end if the text is too long*/ LV_LABEL_LONG_SCROLL, /**< Keep the size and roll the text back and forth*/ LV_LABEL_LONG_SCROLL_CIRCULAR, /**< Keep the size and roll the text circularly*/ LV_LABEL_LONG_CLIP, /**< Keep the size and clip the text out of it*/ }; + +#ifdef DOXYGEN +typedef _lv_label_long_mode_t lv_label_long_mode_t; +#else typedef uint8_t lv_label_long_mode_t; +#endif /*DOXYGEN*/ typedef struct { lv_obj_t obj; @@ -68,15 +77,16 @@ typedef struct { uint32_t sel_end; #endif + lv_point_t size_cache; /*Text size cache*/ lv_point_t offset; /*Text draw position offset*/ lv_label_long_mode_t long_mode : 3; /*Determine what to do with the long texts*/ uint8_t static_txt : 1; /*Flag to indicate the text is static*/ - uint8_t recolor : 1; /*Enable in-line letter re-coloring*/ uint8_t expand : 1; /*Ignore real width (used by the library with LV_LABEL_LONG_SCROLL)*/ - uint8_t dot_tmp_alloc : 1; /*1: dot is allocated, 0: dot directly holds up to 4 chars*/ + uint8_t dot_tmp_alloc : 1; /*1: dot is allocated, 0: dot directly holds up to 4 chars*/ + uint8_t invalid_size_cache : 1; /*1: Recalculate size and update cache*/ } lv_label_t; -extern const lv_obj_class_t lv_label_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_label_class; /********************** * GLOBAL PROTOTYPES @@ -117,34 +127,26 @@ void lv_label_set_text_fmt(lv_obj_t * obj, const char * fmt, ...) LV_FORMAT_ATTR void lv_label_set_text_static(lv_obj_t * obj, const char * text); /** - * Set the behavior of the label with longer text then the object size + * Set the behavior of the label with text longer than the object size * @param obj pointer to a label object * @param long_mode the new mode from 'lv_label_long_mode' enum. * In LV_LONG_WRAP/DOT/SCROLL/SCROLL_CIRC the size of the label should be set AFTER this function */ void lv_label_set_long_mode(lv_obj_t * obj, lv_label_long_mode_t long_mode); -/** - * Enable the recoloring by in-line commands - * @param obj pointer to a label object - * @param en true: enable recoloring, false: disable - * @example "This is a #ff0000 red# word" - */ -void lv_label_set_recolor(lv_obj_t * obj, bool en); - /** * Set where text selection should start * @param obj pointer to a label object * @param index character index from where selection should start. `LV_LABEL_TEXT_SELECTION_OFF` for no selection */ -void lv_label_set_text_sel_start(lv_obj_t * obj, uint32_t index); +void lv_label_set_text_selection_start(lv_obj_t * obj, uint32_t index); /** * Set where text selection should end * @param obj pointer to a label object * @param index character index where selection should end. `LV_LABEL_TEXT_SELECTION_OFF` for no selection */ -void lv_label_set_text_sel_end(lv_obj_t * obj, uint32_t index); +void lv_label_set_text_selection_end(lv_obj_t * obj, uint32_t index); /*===================== * Getter functions @@ -164,17 +166,10 @@ char * lv_label_get_text(const lv_obj_t * obj); */ lv_label_long_mode_t lv_label_get_long_mode(const lv_obj_t * obj); -/** - * Get the recoloring attribute - * @param obj pointer to a label object - * @return true: recoloring is enabled, false: disable - */ -bool lv_label_get_recolor(const lv_obj_t * obj); - /** * Get the relative x and y coordinates of a letter * @param obj pointer to a label object - * @param index index of the character [0 ... text length - 1]. + * @param char_id index of the character [0 ... text length - 1]. * Expressed in character index, not byte index (different in UTF-8) * @param pos store the result here (E.g. index = 0 gives 0;0 coordinates if the text if aligned to the left) */ @@ -183,11 +178,12 @@ void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t /** * Get the index of letter on a relative point of a label. * @param obj pointer to label object - * @param pos pointer to point with coordinates on a the label + * @param pos_in pointer to point with coordinates on a the label + * @param bidi whether to use bidi processed * @return The index of the letter on the 'pos_p' point (E.g. on 0;0 is the 0. letter if aligned to the left) * Expressed in character index and not byte index (different in UTF-8) */ -uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in); +uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in, bool bidi); /** * Check if a character is drawn under a point. diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/led/lv_led.c b/lib/libesp32_lvgl/lvgl/src/widgets/led/lv_led.c similarity index 78% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/led/lv_led.c rename to lib/libesp32_lvgl/lvgl/src/widgets/led/lv_led.c index 88b7b87da..d9aa4ca2b 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/led/lv_led.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/led/lv_led.c @@ -9,7 +9,9 @@ #include "lv_led.h" #if LV_USE_LED -#include "../../../misc/lv_assert.h" +#include "../../misc/lv_assert.h" +#include "../../themes/lv_theme.h" +#include "../../misc/lv_color.h" /********************* * DEFINES @@ -29,6 +31,7 @@ static void lv_led_event(const lv_obj_class_t * class_p, lv_event_t * e); /********************** * STATIC VARIABLES **********************/ + const lv_obj_class_t lv_led_class = { .base_class = &lv_obj_class, .constructor_cb = lv_led_constructor, @@ -36,6 +39,7 @@ const lv_obj_class_t lv_led_class = { .height_def = LV_DPI_DEF / 5, .event_cb = lv_led_event, .instance_size = sizeof(lv_led_t), + .name = "led", }; /********************** @@ -46,11 +50,6 @@ const lv_obj_class_t lv_led_class = { * GLOBAL FUNCTIONS **********************/ -/** - * Create a led object - * @param parent pointer to an object, it will be the parent of the new led - * @return pointer to the created led - */ lv_obj_t * lv_led_create(lv_obj_t * parent) { LV_LOG_INFO("begin"); @@ -63,11 +62,6 @@ lv_obj_t * lv_led_create(lv_obj_t * parent) * Setter functions *====================*/ -/** - * Set the color of the LED - * @param led pointer to a LED object - * @param color the color of the LED - */ void lv_led_set_color(lv_obj_t * obj, lv_color_t color) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -77,11 +71,6 @@ void lv_led_set_color(lv_obj_t * obj, lv_color_t color) lv_obj_invalidate(obj); } -/** - * Set the brightness of a LED object - * @param led pointer to a LED object - * @param bright LV_LED_BRIGHT_MIN (max. dark) ... LV_LED_BRIGHT_MAX (max. light) - */ void lv_led_set_brightness(lv_obj_t * obj, uint8_t bright) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -95,28 +84,16 @@ void lv_led_set_brightness(lv_obj_t * obj, uint8_t bright) lv_obj_invalidate(obj); } -/** - * Light on a LED - * @param led pointer to a LED object - */ void lv_led_on(lv_obj_t * led) { lv_led_set_brightness(led, LV_LED_BRIGHT_MAX); } -/** - * Light off a LED - * @param led pointer to a LED object - */ void lv_led_off(lv_obj_t * led) { lv_led_set_brightness(led, LV_LED_BRIGHT_MIN); } -/** - * Toggle the state of a LED - * @param led pointer to a LED object - */ void lv_led_toggle(lv_obj_t * obj) { uint8_t bright = lv_led_get_brightness(obj); @@ -130,11 +107,6 @@ void lv_led_toggle(lv_obj_t * obj) * Getter functions *====================*/ -/** - * Get the brightness of a LEd object - * @param led pointer to LED object - * @return bright 0 (max. dark) ... 255 (max. light) - */ uint8_t lv_led_get_brightness(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -159,16 +131,16 @@ static void lv_led_event(const lv_obj_class_t * class_p, lv_event_t * e) { LV_UNUSED(class_p); - lv_res_t res; + lv_result_t res; /* Call the ancestor's event handler */ lv_event_code_t code = lv_event_get_code(e); if(code != LV_EVENT_DRAW_MAIN && code != LV_EVENT_DRAW_MAIN_END) { res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; } - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); if(code == LV_EVENT_DRAW_MAIN) { /*Make darker colors in a temporary style according to the brightness*/ lv_led_t * led = (lv_led_t *)obj; @@ -202,19 +174,9 @@ static void lv_led_event(const lv_obj_class_t * class_p, lv_event_t * e) rect_dsc.shadow_spread = ((led->bright - LV_LED_BRIGHT_MIN) * rect_dsc.shadow_spread) / (LV_LED_BRIGHT_MAX - LV_LED_BRIGHT_MIN); - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.draw_area = &obj->coords; - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_LED_DRAW_PART_RECTANGLE; - part_draw_dsc.rect_dsc = &rect_dsc; - part_draw_dsc.part = LV_PART_MAIN; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_rect(draw_ctx, &rect_dsc, &obj->coords); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); + lv_draw_rect(layer, &rect_dsc, &obj->coords); } } diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/led/lv_led.h b/lib/libesp32_lvgl/lvgl/src/widgets/led/lv_led.h similarity index 65% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/led/lv_led.h rename to lib/libesp32_lvgl/lvgl/src/widgets/led/lv_led.h index 368bcd23c..f1ac52d87 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/led/lv_led.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/led/lv_led.h @@ -13,11 +13,10 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../lvgl.h" +#include "../../core/lv_obj.h" #if LV_USE_LED - /********************* * DEFINES *********************/ @@ -42,15 +41,7 @@ typedef struct { uint8_t bright; /**< Current brightness of the LED (0..255)*/ } lv_led_t; -extern const lv_obj_class_t lv_led_class; - -/** - * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_led_class` - * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` - */ -typedef enum { - LV_LED_DRAW_PART_RECTANGLE, /**< The main rectangle*/ -} lv_led_draw_part_type_t; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_led_class; /********************** * GLOBAL PROTOTYPES @@ -58,8 +49,8 @@ typedef enum { /** * Create a led object - * @param parent pointer to an object, it will be the parent of the new led - * @return pointer to the created led + * @param parent pointer to an object, it will be the parent of the new led + * @return pointer to the created led */ lv_obj_t * lv_led_create(lv_obj_t * parent); @@ -72,33 +63,33 @@ void lv_led_set_color(lv_obj_t * led, lv_color_t color); /** * Set the brightness of a LED object - * @param led pointer to a LED object - * @param bright LV_LED_BRIGHT_MIN (max. dark) ... LV_LED_BRIGHT_MAX (max. light) + * @param led pointer to a LED object + * @param bright LV_LED_BRIGHT_MIN (max. dark) ... LV_LED_BRIGHT_MAX (max. light) */ void lv_led_set_brightness(lv_obj_t * led, uint8_t bright); /** * Light on a LED - * @param led pointer to a LED object + * @param led pointer to a LED object */ void lv_led_on(lv_obj_t * led); /** * Light off a LED - * @param led pointer to a LED object + * @param led pointer to a LED object */ void lv_led_off(lv_obj_t * led); /** * Toggle the state of a LED - * @param led pointer to a LED object + * @param led pointer to a LED object */ void lv_led_toggle(lv_obj_t * led); /** - * Get the brightness of a LEd object - * @param led pointer to LED object - * @return bright 0 (max. dark) ... 255 (max. light) + * Get the brightness of a LED object + * @param obj pointer to LED object + * @return bright 0 (max. dark) ... 255 (max. light) */ uint8_t lv_led_get_brightness(const lv_obj_t * obj); @@ -112,5 +103,4 @@ uint8_t lv_led_get_brightness(const lv_obj_t * obj); } /*extern "C"*/ #endif - #endif /*LV_LED_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_line.c b/lib/libesp32_lvgl/lvgl/src/widgets/line/lv_line.c similarity index 64% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_line.c rename to lib/libesp32_lvgl/lvgl/src/widgets/line/lv_line.c index df32bd051..1b6f32451 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_line.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/line/lv_line.c @@ -9,9 +9,9 @@ #include "lv_line.h" #if LV_USE_LINE != 0 -#include "../misc/lv_assert.h" -#include "../draw/lv_draw.h" -#include "../misc/lv_math.h" +#include "../../misc/lv_assert.h" +#include "../../misc/lv_math.h" +#include "../../draw/lv_draw.h" #include #include #include @@ -40,7 +40,8 @@ const lv_obj_class_t lv_line_class = { .width_def = LV_SIZE_CONTENT, .height_def = LV_SIZE_CONTENT, .instance_size = sizeof(lv_line_t), - .base_class = &lv_obj_class + .base_class = &lv_obj_class, + .name = "line", }; /********************** @@ -63,7 +64,7 @@ lv_obj_t * lv_line_create(lv_obj_t * parent) * Setter functions *====================*/ -void lv_line_set_points(lv_obj_t * obj, const lv_point_t points[], uint16_t point_num) +void lv_line_set_points(lv_obj_t * obj, const lv_point_precise_t points[], uint32_t point_num) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -116,28 +117,38 @@ static void lv_line_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) line->point_array = NULL; line->y_inv = 0; - lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICKABLE); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_CLICKABLE); LV_TRACE_OBJ_CREATE("finished"); } +static inline lv_value_precise_t resolve_point_coord(lv_value_precise_t coord, int32_t max) +{ + if(LV_COORD_IS_PCT((int32_t)coord)) { + return LV_CLAMP(0, max * LV_COORD_GET_PCT((int32_t)coord) / 100, max); + } + else { + return coord; + } +} + static void lv_line_event(const lv_obj_class_t * class_p, lv_event_t * e) { LV_UNUSED(class_p); - lv_res_t res; + lv_result_t res; /*Call the ancestor's event handler*/ res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { /*The corner of the skew lines is out of the intended area*/ - lv_coord_t line_width = lv_obj_get_style_line_width(obj, LV_PART_MAIN); - lv_coord_t * s = lv_event_get_param(e); + int32_t line_width = lv_obj_get_style_line_width(obj, LV_PART_MAIN); + int32_t * s = lv_event_get_param(e); if(*s < line_width) *s = line_width; } else if(code == LV_EVENT_GET_SELF_SIZE) { @@ -146,54 +157,60 @@ static void lv_line_event(const lv_obj_class_t * class_p, lv_event_t * e) if(line->point_num == 0 || line->point_array == NULL) return; lv_point_t * p = lv_event_get_param(e); - lv_coord_t w = 0; - lv_coord_t h = 0; + int32_t w = 0; + int32_t h = 0; - uint16_t i; + uint32_t i; for(i = 0; i < line->point_num; i++) { - w = LV_MAX(line->point_array[i].x, w); - h = LV_MAX(line->point_array[i].y, h); + if(!LV_COORD_IS_PCT((int32_t)line->point_array[i].x)) { + w = (int32_t)LV_MAX(line->point_array[i].x, w); + } + + if(!LV_COORD_IS_PCT((int32_t)line->point_array[i].y)) { + h = (int32_t)LV_MAX(line->point_array[i].y, h); + } } - lv_coord_t line_width = lv_obj_get_style_line_width(obj, LV_PART_MAIN); - w += line_width; - h += line_width; p->x = w; p->y = h; } else if(code == LV_EVENT_DRAW_MAIN) { lv_line_t * line = (lv_line_t *)obj; - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); if(line->point_num == 0 || line->point_array == NULL) return; lv_area_t area; lv_obj_get_coords(obj, &area); - lv_coord_t x_ofs = area.x1 - lv_obj_get_scroll_x(obj); - lv_coord_t y_ofs = area.y1 - lv_obj_get_scroll_y(obj); - lv_coord_t h = lv_obj_get_height(obj); + int32_t x_ofs = area.x1 - lv_obj_get_scroll_x(obj); + int32_t y_ofs = area.y1 - lv_obj_get_scroll_y(obj); lv_draw_line_dsc_t line_dsc; lv_draw_line_dsc_init(&line_dsc); lv_obj_init_draw_line_dsc(obj, LV_PART_MAIN, &line_dsc); /*Read all points and draw the lines*/ - uint16_t i; + uint32_t i; for(i = 0; i < line->point_num - 1; i++) { - lv_point_t p1; - lv_point_t p2; - p1.x = line->point_array[i].x + x_ofs; - p2.x = line->point_array[i + 1].x + x_ofs; + int32_t w = lv_obj_get_width(obj); + int32_t h = lv_obj_get_height(obj); + + line_dsc.p1.x = resolve_point_coord(line->point_array[i].x, w) + x_ofs; + line_dsc.p1.y = resolve_point_coord(line->point_array[i].y, h); + + line_dsc.p2.x = resolve_point_coord(line->point_array[i + 1].x, w) + x_ofs; + line_dsc.p2.y = resolve_point_coord(line->point_array[i + 1].y, h); if(line->y_inv == 0) { - p1.y = line->point_array[i].y + y_ofs; - p2.y = line->point_array[i + 1].y + y_ofs; + line_dsc.p1.y = line_dsc.p1.y + y_ofs; + line_dsc.p2.y = line_dsc.p2.y + y_ofs; } else { - p1.y = h - line->point_array[i].y + y_ofs; - p2.y = h - line->point_array[i + 1].y + y_ofs; + line_dsc.p1.y = h - line_dsc.p1.y + y_ofs; + line_dsc.p2.y = h - line_dsc.p2.y + y_ofs; } - lv_draw_line(draw_ctx, &line_dsc, &p1, &p2); + + lv_draw_line(layer, &line_dsc); line_dsc.round_start = 0; /*Draw the rounding only on the end points after the first line*/ } } diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_line.h b/lib/libesp32_lvgl/lvgl/src/widgets/line/lv_line.h similarity index 80% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_line.h rename to lib/libesp32_lvgl/lvgl/src/widgets/line/lv_line.h index 54fa248b5..6a2423a22 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_line.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/line/lv_line.h @@ -13,12 +13,9 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../lv_conf_internal.h" - +#include "../../core/lv_obj.h" #if LV_USE_LINE != 0 -#include "../core/lv_obj.h" - /********************* * DEFINES *********************/ @@ -30,12 +27,12 @@ extern "C" { /*Data of line*/ typedef struct { lv_obj_t obj; - const lv_point_t * point_array; /**< Pointer to an array with the points of the line*/ - uint16_t point_num; /**< Number of points in 'point_array'*/ - uint8_t y_inv : 1; /**< 1: y == 0 will be on the bottom*/ + const lv_point_precise_t * point_array; /**< Pointer to an array with the points of the line*/ + uint32_t point_num; /**< Number of points in 'point_array'*/ + uint32_t y_inv : 1; /**< 1: y == 0 will be on the bottom*/ } lv_line_t; -extern const lv_obj_class_t lv_line_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_line_class; /********************** * GLOBAL PROTOTYPES @@ -58,7 +55,7 @@ lv_obj_t * lv_line_create(lv_obj_t * parent); * @param points an array of points. Only the address is saved, so the array needs to be alive while the line exists * @param point_num number of points in 'point_a' */ -void lv_line_set_points(lv_obj_t * obj, const lv_point_t points[], uint16_t point_num); +void lv_line_set_points(lv_obj_t * obj, const lv_point_precise_t points[], uint32_t point_num); /** * Enable (or disable) the y coordinate inversion. diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.c b/lib/libesp32_lvgl/lvgl/src/widgets/list/lv_list.c similarity index 61% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.c rename to lib/libesp32_lvgl/lvgl/src/widgets/list/lv_list.c index 29355fd3c..60dc6ddf1 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/list/lv_list.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/list/lv_list.c @@ -7,10 +7,11 @@ * INCLUDES *********************/ #include "lv_list.h" -#include "../../../core/lv_disp.h" -#include "../../../widgets/lv_label.h" -#include "../../../widgets/lv_img.h" -#include "../../../widgets/lv_btn.h" +#include "../../layouts/flex/lv_flex.h" +#include "../../display/lv_display.h" +#include "../label/lv_label.h" +#include "../image/lv_image.h" +#include "../button/lv_button.h" #if LV_USE_LIST @@ -26,19 +27,25 @@ /********************** * STATIC PROTOTYPES **********************/ - const lv_obj_class_t lv_list_class = { .base_class = &lv_obj_class, .width_def = (LV_DPI_DEF * 3) / 2, - .height_def = LV_DPI_DEF * 2 + .height_def = LV_DPI_DEF * 2, + .name = "list", }; -const lv_obj_class_t lv_list_btn_class = { - .base_class = &lv_btn_class, +const lv_obj_class_t lv_list_button_class = { + .base_class = &lv_button_class, + .width_def = LV_PCT(100), + .height_def = LV_SIZE_CONTENT, + .name = "list-btn", }; const lv_obj_class_t lv_list_text_class = { .base_class = &lv_label_class, + .width_def = LV_PCT(100), + .height_def = LV_SIZE_CONTENT, + .name = "list-text", }; /********************** @@ -65,26 +72,24 @@ lv_obj_t * lv_list_create(lv_obj_t * parent) lv_obj_t * lv_list_add_text(lv_obj_t * list, const char * txt) { LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(&lv_list_text_class, list); lv_obj_class_init_obj(obj); lv_label_set_text(obj, txt); - lv_label_set_long_mode(obj, LV_LABEL_LONG_SCROLL_CIRCULAR); - lv_obj_set_width(obj, LV_PCT(100)); return obj; } -lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * icon, const char * txt) +lv_obj_t * lv_list_add_button(lv_obj_t * list, const void * icon, const char * txt) { LV_LOG_INFO("begin"); - lv_obj_t * obj = lv_obj_class_create_obj(&lv_list_btn_class, list); + lv_obj_t * obj = lv_obj_class_create_obj(&lv_list_button_class, list); lv_obj_class_init_obj(obj); - lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW); -#if LV_USE_IMG == 1 +#if LV_USE_IMAGE == 1 if(icon) { - lv_obj_t * img = lv_img_create(obj); - lv_img_set_src(img, icon); + lv_obj_t * img = lv_image_create(obj); + lv_image_set_src(img, icon); } #endif @@ -98,11 +103,11 @@ lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * icon, const char * txt) return obj; } -const char * lv_list_get_btn_text(lv_obj_t * list, lv_obj_t * btn) +const char * lv_list_get_button_text(lv_obj_t * list, lv_obj_t * btn) { LV_UNUSED(list); uint32_t i; - for(i = 0; i < lv_obj_get_child_cnt(btn); i++) { + for(i = 0; i < lv_obj_get_child_count(btn); i++) { lv_obj_t * child = lv_obj_get_child(btn, i); if(lv_obj_check_type(child, &lv_label_class)) { return lv_label_get_text(child); @@ -113,6 +118,19 @@ const char * lv_list_get_btn_text(lv_obj_t * list, lv_obj_t * btn) return ""; } +void lv_list_set_button_text(lv_obj_t * list, lv_obj_t * btn, const char * txt) +{ + LV_UNUSED(list); + uint32_t i; + for(i = 0; i < lv_obj_get_child_count(btn); i++) { + lv_obj_t * child = lv_obj_get_child(btn, i); + if(lv_obj_check_type(child, &lv_label_class)) { + lv_label_set_text(child, txt); + return; + } + } +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/list/lv_list.h b/lib/libesp32_lvgl/lvgl/src/widgets/list/lv_list.h new file mode 100644 index 000000000..c01c086df --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/list/lv_list.h @@ -0,0 +1,86 @@ +/** + * @file lv_win.h + * + */ + +#ifndef LV_LIST_H +#define LV_LIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../core/lv_obj.h" + +#if LV_USE_LIST + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_list_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_list_text_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_list_button_class; +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a list object + * @param parent pointer to an object, it will be the parent of the new list + * @return pointer to the created list + */ +lv_obj_t * lv_list_create(lv_obj_t * parent); + +/** + * Add text to a list + * @param list pointer to a list, it will be the parent of the new label + * @param txt text of the new label + * @return pointer to the created label + */ +lv_obj_t * lv_list_add_text(lv_obj_t * list, const char * txt); + +/** + * Add button to a list + * @param list pointer to a list, it will be the parent of the new button + * @param icon icon for the button, when NULL it will have no icon + * @param txt text of the new button, when NULL no text will be added + * @return pointer to the created button + */ +lv_obj_t * lv_list_add_button(lv_obj_t * list, const void * icon, const char * txt); + +/** + * Get text of a given list button + * @param list pointer to a list + * @param btn pointer to the button + * @return text of btn, if btn doesn't have text "" will be returned + */ +const char * lv_list_get_button_text(lv_obj_t * list, lv_obj_t * btn); + +/** + * Set text of a given list button + * @param list pointer to a list + * @param btn pointer to the button + * @param txt pointer to the text + * @return text of btn, if btn doesn't have text "" will be returned + */ +void lv_list_set_button_text(lv_obj_t * list, lv_obj_t * btn, const char * txt); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_LIST*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_LIST_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.h deleted file mode 100644 index 6a8a07246..000000000 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.h +++ /dev/null @@ -1,257 +0,0 @@ -/** - * @file lv_arc.h - * - */ - -#ifndef LV_ARC_H -#define LV_ARC_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_ARC != 0 - -#include "../core/lv_obj.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -enum { - LV_ARC_MODE_NORMAL, - LV_ARC_MODE_SYMMETRICAL, - LV_ARC_MODE_REVERSE -}; -typedef uint8_t lv_arc_mode_t; - -typedef struct { - lv_obj_t obj; - uint16_t rotation; - uint16_t indic_angle_start; - uint16_t indic_angle_end; - uint16_t bg_angle_start; - uint16_t bg_angle_end; - int16_t value; /*Current value of the arc*/ - int16_t min_value; /*Minimum value of the arc*/ - int16_t max_value; /*Maximum value of the arc*/ - uint32_t dragging : 1; - uint32_t type : 2; - uint32_t min_close : 1; /*1: the last pressed angle was closer to minimum end*/ - uint32_t in_out : 1; /* 1: The click was within the background arc angles. 0: Click outside */ - uint32_t chg_rate; /*Drag angle rate of change of the arc (degrees/sec)*/ - uint32_t last_tick; /*Last dragging event timestamp of the arc*/ - int16_t last_angle; /*Last dragging angle of the arc*/ -} lv_arc_t; - -extern const lv_obj_class_t lv_arc_class; - -/** - * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_arc_class` - * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` - */ -typedef enum { - LV_ARC_DRAW_PART_BACKGROUND, /**< The background arc*/ - LV_ARC_DRAW_PART_FOREGROUND, /**< The foreground arc*/ - LV_ARC_DRAW_PART_KNOB, /**< The knob*/ -} lv_arc_draw_part_type_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create an arc object - * @param parent pointer to an object, it will be the parent of the new arc - * @return pointer to the created arc - */ -lv_obj_t * lv_arc_create(lv_obj_t * parent); - -/*====================== - * Add/remove functions - *=====================*/ - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the start angle of an arc. 0 deg: right, 90 bottom, etc. - * @param obj pointer to an arc object - * @param start the start angle - */ -void lv_arc_set_start_angle(lv_obj_t * obj, uint16_t start); - -/** - * Set the end angle of an arc. 0 deg: right, 90 bottom, etc. - * @param obj pointer to an arc object - * @param end the end angle - */ -void lv_arc_set_end_angle(lv_obj_t * obj, uint16_t end); - -/** - * Set the start and end angles - * @param obj pointer to an arc object - * @param start the start angle - * @param end the end angle - */ -void lv_arc_set_angles(lv_obj_t * obj, uint16_t start, uint16_t end); - -/** - * Set the start angle of an arc background. 0 deg: right, 90 bottom, etc. - * @param obj pointer to an arc object - * @param start the start angle - */ -void lv_arc_set_bg_start_angle(lv_obj_t * obj, uint16_t start); - -/** - * Set the start angle of an arc background. 0 deg: right, 90 bottom etc. - * @param obj pointer to an arc object - * @param end the end angle - */ -void lv_arc_set_bg_end_angle(lv_obj_t * obj, uint16_t end); - -/** - * Set the start and end angles of the arc background - * @param obj pointer to an arc object - * @param start the start angle - * @param end the end angle - */ -void lv_arc_set_bg_angles(lv_obj_t * obj, uint16_t start, uint16_t end); - -/** - * Set the rotation for the whole arc - * @param obj pointer to an arc object - * @param rotation rotation angle - */ -void lv_arc_set_rotation(lv_obj_t * obj, uint16_t rotation); - -/** - * Set the type of arc. - * @param obj pointer to arc object - * @param mode arc's mode - */ -void lv_arc_set_mode(lv_obj_t * obj, lv_arc_mode_t type); - -/** - * Set a new value on the arc - * @param obj pointer to an arc object - * @param value new value - */ -void lv_arc_set_value(lv_obj_t * obj, int16_t value); - -/** - * Set minimum and the maximum values of an arc - * @param obj pointer to the arc object - * @param min minimum value - * @param max maximum value - */ -void lv_arc_set_range(lv_obj_t * obj, int16_t min, int16_t max); - -/** - * Set a change rate to limit the speed how fast the arc should reach the pressed point. - * @param obj pointer to an arc object - * @param rate the change rate - */ -void lv_arc_set_change_rate(lv_obj_t * obj, uint16_t rate); - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the start angle of an arc. - * @param obj pointer to an arc object - * @return the start angle [0..360] - */ -uint16_t lv_arc_get_angle_start(lv_obj_t * obj); - -/** - * Get the end angle of an arc. - * @param obj pointer to an arc object - * @return the end angle [0..360] - */ -uint16_t lv_arc_get_angle_end(lv_obj_t * obj); - -/** - * Get the start angle of an arc background. - * @param obj pointer to an arc object - * @return the start angle [0..360] - */ -uint16_t lv_arc_get_bg_angle_start(lv_obj_t * obj); - -/** - * Get the end angle of an arc background. - * @param obj pointer to an arc object - * @return the end angle [0..360] - */ -uint16_t lv_arc_get_bg_angle_end(lv_obj_t * obj); - -/** - * Get the value of an arc - * @param obj pointer to an arc object - * @return the value of the arc - */ -int16_t lv_arc_get_value(const lv_obj_t * obj); - -/** - * Get the minimum value of an arc - * @param obj pointer to an arc object - * @return the minimum value of the arc - */ -int16_t lv_arc_get_min_value(const lv_obj_t * obj); - -/** - * Get the maximum value of an arc - * @param obj pointer to an arc object - * @return the maximum value of the arc - */ -int16_t lv_arc_get_max_value(const lv_obj_t * obj); - -/** - * Get whether the arc is type or not. - * @param obj pointer to an arc object - * @return arc's mode - */ -lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj); - -/*===================== - * Other functions - *====================*/ - -/** - * Align an object to the current position of the arc (knob) - * @param obj pointer to an arc object - * @param obj_to_align pointer to an object to align - * @param r_offset consider the radius larger with this value (< 0: for smaller radius) - */ -void lv_arc_align_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_align, lv_coord_t r_offset); - -/** - * Rotate an object to the current position of the arc (knob) - * @param obj pointer to an arc object - * @param obj_to_align pointer to an object to rotate - * @param r_offset consider the radius larger with this value (< 0: for smaller radius) - */ -void lv_arc_rotate_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_rotate, lv_coord_t r_offset); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_ARC*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_ARC_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.c deleted file mode 100644 index 1f949272e..000000000 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.c +++ /dev/null @@ -1,836 +0,0 @@ -/** - * @file lv_canvas.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_canvas.h" -#include "../misc/lv_assert.h" -#include "../misc/lv_math.h" -#include "../draw/lv_draw.h" -#include "../core/lv_refr.h" - -#if LV_USE_CANVAS != 0 - -#include "../draw/sw/lv_draw_sw.h" - -/********************* - * DEFINES - *********************/ -#define MY_CLASS &lv_canvas_class - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void lv_canvas_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void lv_canvas_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void init_fake_disp(lv_obj_t * canvas, lv_disp_t * disp, lv_disp_drv_t * drv, lv_area_t * clip_area); -static void deinit_fake_disp(lv_obj_t * canvas, lv_disp_t * disp); - -/********************** - * STATIC VARIABLES - **********************/ -const lv_obj_class_t lv_canvas_class = { - .constructor_cb = lv_canvas_constructor, - .destructor_cb = lv_canvas_destructor, - .instance_size = sizeof(lv_canvas_t), - .base_class = &lv_img_class -}; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_obj_t * lv_canvas_create(lv_obj_t * parent) -{ - LV_LOG_INFO("begin"); - lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); - lv_obj_class_init_obj(obj); - return obj; -} - -/*===================== - * Setter functions - *====================*/ - -void lv_canvas_set_buffer(lv_obj_t * obj, void * buf, lv_coord_t w, lv_coord_t h, lv_img_cf_t cf) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - LV_ASSERT_NULL(buf); - - lv_canvas_t * canvas = (lv_canvas_t *)obj; - - canvas->dsc.header.cf = cf; - canvas->dsc.header.w = w; - canvas->dsc.header.h = h; - canvas->dsc.data = buf; - - lv_img_set_src(obj, &canvas->dsc); - lv_img_cache_invalidate_src(&canvas->dsc); -} - -void lv_canvas_set_px_color(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_color_t c) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_canvas_t * canvas = (lv_canvas_t *)obj; - - lv_img_buf_set_px_color(&canvas->dsc, x, y, c); - lv_obj_invalidate(obj); -} - -void lv_canvas_set_px_opa(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_opa_t opa) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_canvas_t * canvas = (lv_canvas_t *)obj; - - lv_img_buf_set_px_alpha(&canvas->dsc, x, y, opa); - lv_obj_invalidate(obj); -} - -void lv_canvas_set_palette(lv_obj_t * obj, uint8_t id, lv_color_t c) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_canvas_t * canvas = (lv_canvas_t *)obj; - - lv_img_buf_set_palette(&canvas->dsc, id, c); - lv_obj_invalidate(obj); -} - -/*===================== - * Getter functions - *====================*/ - -lv_color_t lv_canvas_get_px(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_canvas_t * canvas = (lv_canvas_t *)obj; - lv_color_t color = lv_obj_get_style_img_recolor(obj, LV_PART_MAIN); - - return lv_img_buf_get_px_color(&canvas->dsc, x, y, color); -} - -lv_img_dsc_t * lv_canvas_get_img(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_canvas_t * canvas = (lv_canvas_t *)obj; - return &canvas->dsc; -} - -/*===================== - * Other functions - *====================*/ - -void lv_canvas_copy_buf(lv_obj_t * obj, const void * to_copy, lv_coord_t x, lv_coord_t y, lv_coord_t w, lv_coord_t h) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - LV_ASSERT_NULL(to_copy); - - lv_canvas_t * canvas = (lv_canvas_t *)obj; - - if(x + w - 1 >= (lv_coord_t)canvas->dsc.header.w || y + h - 1 >= (lv_coord_t)canvas->dsc.header.h) { - LV_LOG_WARN("lv_canvas_copy_buf: x or y out of the canvas"); - return; - } - - uint32_t px_size = lv_img_cf_get_px_size(canvas->dsc.header.cf) >> 3; - uint32_t px = canvas->dsc.header.w * y * px_size + x * px_size; - uint8_t * to_copy8 = (uint8_t *)to_copy; - lv_coord_t i; - for(i = 0; i < h; i++) { - lv_memcpy((void *)&canvas->dsc.data[px], to_copy8, w * px_size); - px += canvas->dsc.header.w * px_size; - to_copy8 += w * px_size; - } -} - -void lv_canvas_transform(lv_obj_t * obj, lv_img_dsc_t * src_img, int16_t angle, uint16_t zoom, lv_coord_t offset_x, - lv_coord_t offset_y, - int32_t pivot_x, int32_t pivot_y, bool antialias) -{ -#if LV_DRAW_COMPLEX - LV_ASSERT_OBJ(obj, MY_CLASS); - LV_ASSERT_NULL(src_img); - - lv_canvas_t * canvas = (lv_canvas_t *)obj; - lv_img_dsc_t * dest_img = &canvas->dsc; - - int32_t x; - int32_t y; - - lv_draw_img_dsc_t draw_dsc; - lv_draw_img_dsc_init(&draw_dsc); - draw_dsc.angle = angle; - draw_dsc.zoom = zoom; - draw_dsc.pivot.x = pivot_x; - draw_dsc.pivot.y = pivot_y; - draw_dsc.antialias = antialias; - - lv_area_t dest_area; - dest_area.x1 = -offset_x; - dest_area.x2 = dest_area.x1 + dest_img->header.w - 1; - dest_area.y1 = -offset_y; - dest_area.y2 = -offset_y; - - lv_color_t * cbuf = lv_mem_alloc(dest_img->header.w * sizeof(lv_color_t)); - lv_opa_t * abuf = lv_mem_alloc(dest_img->header.w * sizeof(lv_opa_t)); - for(y = 0; y < dest_img->header.h; y++) { - if(y + offset_y >= 0) { - lv_draw_sw_transform(NULL, &dest_area, src_img->data, src_img->header.w, src_img->header.h, src_img->header.w, - &draw_dsc, canvas->dsc.header.cf, cbuf, abuf); - - for(x = 0; x < dest_img->header.w; x++) { - if(abuf[x]) { - lv_img_buf_set_px_color(dest_img, x, y, cbuf[x]); - lv_img_buf_set_px_alpha(dest_img, x, y, abuf[x]); - } - } - - dest_area.y1++; - dest_area.y2++; - } - } - lv_mem_free(cbuf); - lv_mem_free(abuf); - - lv_obj_invalidate(obj); - -#else - LV_UNUSED(obj); - LV_UNUSED(src_img); - LV_UNUSED(angle); - LV_UNUSED(zoom); - LV_UNUSED(offset_x); - LV_UNUSED(offset_y); - LV_UNUSED(pivot_x); - LV_UNUSED(pivot_y); - LV_UNUSED(antialias); - LV_LOG_WARN("Can't transform canvas with LV_DRAW_COMPLEX == 0"); -#endif -} - -void lv_canvas_blur_hor(lv_obj_t * obj, const lv_area_t * area, uint16_t r) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - if(r == 0) return; - - lv_canvas_t * canvas = (lv_canvas_t *)obj; - - lv_area_t a; - if(area) { - lv_area_copy(&a, area); - if(a.x1 < 0) a.x1 = 0; - if(a.y1 < 0) a.y1 = 0; - if(a.x2 > canvas->dsc.header.w - 1) a.x2 = canvas->dsc.header.w - 1; - if(a.y2 > canvas->dsc.header.h - 1) a.y2 = canvas->dsc.header.h - 1; - } - else { - a.x1 = 0; - a.y1 = 0; - a.x2 = canvas->dsc.header.w - 1; - a.y2 = canvas->dsc.header.h - 1; - } - - lv_color_t color = lv_obj_get_style_img_recolor(obj, LV_PART_MAIN); - - uint16_t r_back = r / 2; - uint16_t r_front = r / 2; - - if((r & 0x1) == 0) r_back--; - - bool has_alpha = lv_img_cf_has_alpha(canvas->dsc.header.cf); - - lv_coord_t line_w = lv_img_buf_get_img_size(canvas->dsc.header.w, 1, canvas->dsc.header.cf); - uint8_t * line_buf = lv_mem_buf_get(line_w); - - lv_img_dsc_t line_img; - line_img.data = line_buf; - line_img.header.always_zero = 0; - line_img.header.w = canvas->dsc.header.w; - line_img.header.h = 1; - line_img.header.cf = canvas->dsc.header.cf; - - lv_coord_t x; - lv_coord_t y; - lv_coord_t x_safe; - - for(y = a.y1; y <= a.y2; y++) { - uint32_t asum = 0; - uint32_t rsum = 0; - uint32_t gsum = 0; - uint32_t bsum = 0; - - lv_color_t c; - lv_opa_t opa = LV_OPA_TRANSP; - lv_memcpy(line_buf, &canvas->dsc.data[y * line_w], line_w); - - for(x = a.x1 - r_back; x <= a.x1 + r_front; x++) { - x_safe = x < 0 ? 0 : x; - x_safe = x_safe > canvas->dsc.header.w - 1 ? canvas->dsc.header.w - 1 : x_safe; - - c = lv_img_buf_get_px_color(&line_img, x_safe, 0, color); - if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, x_safe, 0); - - rsum += c.ch.red; -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP - gsum += (c.ch.green_h << 3) + c.ch.green_l; -#else - gsum += c.ch.green; -#endif - bsum += c.ch.blue; - if(has_alpha) asum += opa; - } - - /*Just to indicate that the px is visible*/ - if(has_alpha == false) asum = LV_OPA_COVER; - - for(x = a.x1; x <= a.x2; x++) { - - if(asum) { - c.ch.red = rsum / r; -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP - uint8_t gtmp = gsum / r; - c.ch.green_h = gtmp >> 3; - c.ch.green_l = gtmp & 0x7; -#else - c.ch.green = gsum / r; -#endif - c.ch.blue = bsum / r; - if(has_alpha) opa = asum / r; - - lv_img_buf_set_px_color(&canvas->dsc, x, y, c); - } - if(has_alpha) lv_img_buf_set_px_alpha(&canvas->dsc, x, y, opa); - - x_safe = x - r_back; - x_safe = x_safe < 0 ? 0 : x_safe; - c = lv_img_buf_get_px_color(&line_img, x_safe, 0, color); - if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, x_safe, 0); - - rsum -= c.ch.red; -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP - gsum -= (c.ch.green_h << 3) + c.ch.green_l; -#else - gsum -= c.ch.green; -#endif - bsum -= c.ch.blue; - if(has_alpha) asum -= opa; - - x_safe = x + 1 + r_front; - x_safe = x_safe > canvas->dsc.header.w - 1 ? canvas->dsc.header.w - 1 : x_safe; - c = lv_img_buf_get_px_color(&line_img, x_safe, 0, lv_color_white()); - if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, x_safe, 0); - - rsum += c.ch.red; -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP - gsum += (c.ch.green_h << 3) + c.ch.green_l; -#else - gsum += c.ch.green; -#endif - bsum += c.ch.blue; - if(has_alpha) asum += opa; - } - } - lv_obj_invalidate(obj); - - lv_mem_buf_release(line_buf); -} - -void lv_canvas_blur_ver(lv_obj_t * obj, const lv_area_t * area, uint16_t r) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - if(r == 0) return; - - lv_canvas_t * canvas = (lv_canvas_t *)obj; - - lv_area_t a; - if(area) { - lv_area_copy(&a, area); - if(a.x1 < 0) a.x1 = 0; - if(a.y1 < 0) a.y1 = 0; - if(a.x2 > canvas->dsc.header.w - 1) a.x2 = canvas->dsc.header.w - 1; - if(a.y2 > canvas->dsc.header.h - 1) a.y2 = canvas->dsc.header.h - 1; - } - else { - a.x1 = 0; - a.y1 = 0; - a.x2 = canvas->dsc.header.w - 1; - a.y2 = canvas->dsc.header.h - 1; - } - - lv_color_t color = lv_obj_get_style_img_recolor(obj, LV_PART_MAIN); - - uint16_t r_back = r / 2; - uint16_t r_front = r / 2; - - if((r & 0x1) == 0) r_back--; - - bool has_alpha = lv_img_cf_has_alpha(canvas->dsc.header.cf); - lv_coord_t col_w = lv_img_buf_get_img_size(1, canvas->dsc.header.h, canvas->dsc.header.cf); - uint8_t * col_buf = lv_mem_buf_get(col_w); - lv_img_dsc_t line_img; - - line_img.data = col_buf; - line_img.header.always_zero = 0; - line_img.header.w = 1; - line_img.header.h = canvas->dsc.header.h; - line_img.header.cf = canvas->dsc.header.cf; - - lv_coord_t x; - lv_coord_t y; - lv_coord_t y_safe; - - for(x = a.x1; x <= a.x2; x++) { - uint32_t asum = 0; - uint32_t rsum = 0; - uint32_t gsum = 0; - uint32_t bsum = 0; - - lv_color_t c; - lv_opa_t opa = LV_OPA_COVER; - - for(y = a.y1 - r_back; y <= a.y1 + r_front; y++) { - y_safe = y < 0 ? 0 : y; - y_safe = y_safe > canvas->dsc.header.h - 1 ? canvas->dsc.header.h - 1 : y_safe; - - c = lv_img_buf_get_px_color(&canvas->dsc, x, y_safe, color); - if(has_alpha) opa = lv_img_buf_get_px_alpha(&canvas->dsc, x, y_safe); - - lv_img_buf_set_px_color(&line_img, 0, y_safe, c); - if(has_alpha) lv_img_buf_set_px_alpha(&line_img, 0, y_safe, opa); - - rsum += c.ch.red; -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP - gsum += (c.ch.green_h << 3) + c.ch.green_l; -#else - gsum += c.ch.green; -#endif - bsum += c.ch.blue; - if(has_alpha) asum += opa; - } - - /*Just to indicate that the px is visible*/ - if(has_alpha == false) asum = LV_OPA_COVER; - - for(y = a.y1; y <= a.y2; y++) { - if(asum) { - c.ch.red = rsum / r; -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP - uint8_t gtmp = gsum / r; - c.ch.green_h = gtmp >> 3; - c.ch.green_l = gtmp & 0x7; -#else - c.ch.green = gsum / r; -#endif - c.ch.blue = bsum / r; - if(has_alpha) opa = asum / r; - - lv_img_buf_set_px_color(&canvas->dsc, x, y, c); - } - if(has_alpha) lv_img_buf_set_px_alpha(&canvas->dsc, x, y, opa); - - y_safe = y - r_back; - y_safe = y_safe < 0 ? 0 : y_safe; - c = lv_img_buf_get_px_color(&line_img, 0, y_safe, color); - if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, 0, y_safe); - - rsum -= c.ch.red; -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP - gsum -= (c.ch.green_h << 3) + c.ch.green_l; -#else - gsum -= c.ch.green; -#endif - bsum -= c.ch.blue; - if(has_alpha) asum -= opa; - - y_safe = y + 1 + r_front; - y_safe = y_safe > canvas->dsc.header.h - 1 ? canvas->dsc.header.h - 1 : y_safe; - - c = lv_img_buf_get_px_color(&canvas->dsc, x, y_safe, color); - if(has_alpha) opa = lv_img_buf_get_px_alpha(&canvas->dsc, x, y_safe); - - lv_img_buf_set_px_color(&line_img, 0, y_safe, c); - if(has_alpha) lv_img_buf_set_px_alpha(&line_img, 0, y_safe, opa); - - rsum += c.ch.red; -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP - gsum += (c.ch.green_h << 3) + c.ch.green_l; -#else - gsum += c.ch.green; -#endif - bsum += c.ch.blue; - if(has_alpha) asum += opa; - } - } - - lv_obj_invalidate(obj); - - lv_mem_buf_release(col_buf); -} - -void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color, lv_opa_t opa) -{ - LV_ASSERT_OBJ(canvas, MY_CLASS); - - lv_img_dsc_t * dsc = lv_canvas_get_img(canvas); - - if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) { - uint32_t row_byte_cnt = (dsc->header.w + 7) >> 3; - /*+8 skip the palette*/ - lv_memset((uint8_t *)dsc->data + 8, color.full ? 0xff : 0x00, row_byte_cnt * dsc->header.h); - } - else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) { - uint32_t row_byte_cnt = (dsc->header.w + 7) >> 3; - lv_memset((uint8_t *)dsc->data, opa > LV_OPA_50 ? 0xff : 0x00, row_byte_cnt * dsc->header.h); - } - else { - uint32_t x; - uint32_t y; - for(y = 0; y < dsc->header.h; y++) { - for(x = 0; x < dsc->header.w; x++) { - lv_img_buf_set_px_color(dsc, x, y, color); - lv_img_buf_set_px_alpha(dsc, x, y, opa); - } - } - } - - lv_obj_invalidate(canvas); -} - -void lv_canvas_draw_rect(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t w, lv_coord_t h, - const lv_draw_rect_dsc_t * draw_dsc) -{ - LV_ASSERT_OBJ(canvas, MY_CLASS); - - lv_img_dsc_t * dsc = lv_canvas_get_img(canvas); - - if(dsc->header.cf >= LV_IMG_CF_INDEXED_1BIT && dsc->header.cf <= LV_IMG_CF_INDEXED_8BIT) { - LV_LOG_WARN("lv_canvas_draw_rect: can't draw to LV_IMG_CF_INDEXED canvas"); - return; - } - - /*Create a dummy display to fool the lv_draw function. - *It will think it draws to real screen.*/ - lv_disp_t fake_disp; - lv_disp_drv_t driver; - lv_area_t clip_area; - init_fake_disp(canvas, &fake_disp, &driver, &clip_area); - - lv_disp_t * refr_ori = _lv_refr_get_disp_refreshing(); - _lv_refr_set_disp_refreshing(&fake_disp); - - /*Disable anti-aliasing if drawing with transparent color to chroma keyed canvas*/ - lv_color_t ctransp = LV_COLOR_CHROMA_KEY; - if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED && - draw_dsc->bg_color.full == ctransp.full) { - fake_disp.driver->antialiasing = 0; - } - - lv_area_t coords; - coords.x1 = x; - coords.y1 = y; - coords.x2 = x + w - 1; - coords.y2 = y + h - 1; - - lv_draw_rect(driver.draw_ctx, draw_dsc, &coords); - - _lv_refr_set_disp_refreshing(refr_ori); - - deinit_fake_disp(canvas, &fake_disp); - - lv_obj_invalidate(canvas); -} - -void lv_canvas_draw_text(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t max_w, - lv_draw_label_dsc_t * draw_dsc, const char * txt) -{ - LV_ASSERT_OBJ(canvas, MY_CLASS); - - lv_img_dsc_t * dsc = lv_canvas_get_img(canvas); - - if(dsc->header.cf >= LV_IMG_CF_INDEXED_1BIT && dsc->header.cf <= LV_IMG_CF_INDEXED_8BIT) { - LV_LOG_WARN("lv_canvas_draw_text: can't draw to LV_IMG_CF_INDEXED canvas"); - return; - } - - /*Create a dummy display to fool the lv_draw function. - *It will think it draws to real screen.*/ - lv_disp_t fake_disp; - lv_disp_drv_t driver; - lv_area_t clip_area; - init_fake_disp(canvas, &fake_disp, &driver, &clip_area); - - lv_disp_t * refr_ori = _lv_refr_get_disp_refreshing(); - _lv_refr_set_disp_refreshing(&fake_disp); - - lv_area_t coords; - coords.x1 = x; - coords.y1 = y; - coords.x2 = x + max_w - 1; - coords.y2 = dsc->header.h - 1; - lv_draw_label(driver.draw_ctx, draw_dsc, &coords, txt, NULL); - - _lv_refr_set_disp_refreshing(refr_ori); - - deinit_fake_disp(canvas, &fake_disp); - - lv_obj_invalidate(canvas); -} - -void lv_canvas_draw_img(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, const void * src, - const lv_draw_img_dsc_t * draw_dsc) -{ - LV_ASSERT_OBJ(canvas, MY_CLASS); - - lv_img_dsc_t * dsc = lv_canvas_get_img(canvas); - - if(dsc->header.cf >= LV_IMG_CF_INDEXED_1BIT && dsc->header.cf <= LV_IMG_CF_INDEXED_8BIT) { - LV_LOG_WARN("lv_canvas_draw_img: can't draw to LV_IMG_CF_INDEXED canvas"); - return; - } - - lv_img_header_t header; - lv_res_t res = lv_img_decoder_get_info(src, &header); - if(res != LV_RES_OK) { - LV_LOG_WARN("lv_canvas_draw_img: Couldn't get the image data."); - return; - } - /*Create a dummy display to fool the lv_draw function. - *It will think it draws to real screen.*/ - lv_disp_t fake_disp; - lv_disp_drv_t driver; - lv_area_t clip_area; - init_fake_disp(canvas, &fake_disp, &driver, &clip_area); - - lv_disp_t * refr_ori = _lv_refr_get_disp_refreshing(); - _lv_refr_set_disp_refreshing(&fake_disp); - - lv_area_t coords; - coords.x1 = x; - coords.y1 = y; - coords.x2 = x + header.w - 1; - coords.y2 = y + header.h - 1; - - lv_draw_img(driver.draw_ctx, draw_dsc, &coords, src); - - _lv_refr_set_disp_refreshing(refr_ori); - - deinit_fake_disp(canvas, &fake_disp); - - lv_obj_invalidate(canvas); -} - -void lv_canvas_draw_line(lv_obj_t * canvas, const lv_point_t points[], uint32_t point_cnt, - const lv_draw_line_dsc_t * draw_dsc) -{ - LV_ASSERT_OBJ(canvas, MY_CLASS); - - lv_img_dsc_t * dsc = lv_canvas_get_img(canvas); - - if(dsc->header.cf >= LV_IMG_CF_INDEXED_1BIT && dsc->header.cf <= LV_IMG_CF_INDEXED_8BIT) { - LV_LOG_WARN("lv_canvas_draw_line: can't draw to LV_IMG_CF_INDEXED canvas"); - return; - } - - /*Create a dummy display to fool the lv_draw function. - *It will think it draws to real screen.*/ - lv_disp_t fake_disp; - lv_disp_drv_t driver; - lv_area_t clip_area; - init_fake_disp(canvas, &fake_disp, &driver, &clip_area); - - lv_disp_t * refr_ori = _lv_refr_get_disp_refreshing(); - _lv_refr_set_disp_refreshing(&fake_disp); - - - /*Disable anti-aliasing if drawing with transparent color to chroma keyed canvas*/ - lv_color_t ctransp = LV_COLOR_CHROMA_KEY; - if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED && - draw_dsc->color.full == ctransp.full) { - fake_disp.driver->antialiasing = 0; - } - - uint32_t i; - for(i = 0; i < point_cnt - 1; i++) { - lv_draw_line(driver.draw_ctx, draw_dsc, &points[i], &points[i + 1]); - } - - _lv_refr_set_disp_refreshing(refr_ori); - - deinit_fake_disp(canvas, &fake_disp); - - lv_obj_invalidate(canvas); -} - -void lv_canvas_draw_polygon(lv_obj_t * canvas, const lv_point_t points[], uint32_t point_cnt, - const lv_draw_rect_dsc_t * draw_dsc) -{ - LV_ASSERT_OBJ(canvas, MY_CLASS); - - lv_img_dsc_t * dsc = lv_canvas_get_img(canvas); - - if(dsc->header.cf >= LV_IMG_CF_INDEXED_1BIT && dsc->header.cf <= LV_IMG_CF_INDEXED_8BIT) { - LV_LOG_WARN("lv_canvas_draw_polygon: can't draw to LV_IMG_CF_INDEXED canvas"); - return; - } - - /*Create a dummy display to fool the lv_draw function. - *It will think it draws to real screen.*/ - lv_disp_t fake_disp; - lv_disp_drv_t driver; - lv_area_t clip_area; - init_fake_disp(canvas, &fake_disp, &driver, &clip_area); - - lv_disp_t * refr_ori = _lv_refr_get_disp_refreshing(); - _lv_refr_set_disp_refreshing(&fake_disp); - - /*Disable anti-aliasing if drawing with transparent color to chroma keyed canvas*/ - lv_color_t ctransp = LV_COLOR_CHROMA_KEY; - if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED && - draw_dsc->bg_color.full == ctransp.full) { - fake_disp.driver->antialiasing = 0; - } - - lv_draw_polygon(driver.draw_ctx, draw_dsc, points, point_cnt); - - _lv_refr_set_disp_refreshing(refr_ori); - - deinit_fake_disp(canvas, &fake_disp); - - lv_obj_invalidate(canvas); -} - -void lv_canvas_draw_arc(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t r, int32_t start_angle, - int32_t end_angle, const lv_draw_arc_dsc_t * draw_dsc) -{ -#if LV_DRAW_COMPLEX - LV_ASSERT_OBJ(canvas, MY_CLASS); - - lv_img_dsc_t * dsc = lv_canvas_get_img(canvas); - - if(dsc->header.cf >= LV_IMG_CF_INDEXED_1BIT && dsc->header.cf <= LV_IMG_CF_INDEXED_8BIT) { - LV_LOG_WARN("lv_canvas_draw_arc: can't draw to LV_IMG_CF_INDEXED canvas"); - return; - } - - /*Create a dummy display to fool the lv_draw function. - *It will think it draws to real screen.*/ - lv_disp_t fake_disp; - lv_disp_drv_t driver; - lv_area_t clip_area; - init_fake_disp(canvas, &fake_disp, &driver, &clip_area); - - lv_disp_t * refr_ori = _lv_refr_get_disp_refreshing(); - _lv_refr_set_disp_refreshing(&fake_disp); - - lv_point_t p = {x, y}; - lv_draw_arc(driver.draw_ctx, draw_dsc, &p, r, start_angle, end_angle); - - _lv_refr_set_disp_refreshing(refr_ori); - - deinit_fake_disp(canvas, &fake_disp); - - lv_obj_invalidate(canvas); -#else - LV_UNUSED(canvas); - LV_UNUSED(x); - LV_UNUSED(y); - LV_UNUSED(r); - LV_UNUSED(start_angle); - LV_UNUSED(end_angle); - LV_UNUSED(draw_dsc); - LV_LOG_WARN("Can't draw arc with LV_DRAW_COMPLEX == 0"); -#endif -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void lv_canvas_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) -{ - LV_UNUSED(class_p); - LV_TRACE_OBJ_CREATE("begin"); - - lv_canvas_t * canvas = (lv_canvas_t *)obj; - - canvas->dsc.header.always_zero = 0; - canvas->dsc.header.cf = LV_IMG_CF_TRUE_COLOR; - canvas->dsc.header.h = 0; - canvas->dsc.header.w = 0; - canvas->dsc.data_size = 0; - canvas->dsc.data = NULL; - - lv_img_set_src(obj, &canvas->dsc); - - LV_TRACE_OBJ_CREATE("finished"); -} - -static void lv_canvas_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) -{ - LV_UNUSED(class_p); - LV_TRACE_OBJ_CREATE("begin"); - - lv_canvas_t * canvas = (lv_canvas_t *)obj; - lv_img_cache_invalidate_src(&canvas->dsc); -} - - -static void init_fake_disp(lv_obj_t * canvas, lv_disp_t * disp, lv_disp_drv_t * drv, lv_area_t * clip_area) -{ - lv_img_dsc_t * dsc = lv_canvas_get_img(canvas); - - clip_area->x1 = 0; - clip_area->x2 = dsc->header.w - 1; - clip_area->y1 = 0; - clip_area->y2 = dsc->header.h - 1; - - /*Allocate the fake driver on the stack as the entire display doesn't outlive this function*/ - lv_memset_00(disp, sizeof(lv_disp_t)); - disp->driver = drv; - - lv_disp_drv_init(disp->driver); - disp->driver->hor_res = dsc->header.w; - disp->driver->ver_res = dsc->header.h; - - lv_draw_ctx_t * draw_ctx = lv_mem_alloc(sizeof(lv_draw_sw_ctx_t)); - LV_ASSERT_MALLOC(draw_ctx); - if(draw_ctx == NULL) return; - lv_draw_sw_init_ctx(drv, draw_ctx); - disp->driver->draw_ctx = draw_ctx; - draw_ctx->clip_area = clip_area; - draw_ctx->buf_area = clip_area; - draw_ctx->buf = (void *)dsc->data; - - lv_disp_drv_use_generic_set_px_cb(disp->driver, dsc->header.cf); - if(LV_COLOR_SCREEN_TRANSP && dsc->header.cf != LV_IMG_CF_TRUE_COLOR_ALPHA) { - drv->screen_transp = 0; - } -} - -static void deinit_fake_disp(lv_obj_t * canvas, lv_disp_t * disp) -{ - LV_UNUSED(canvas); - lv_draw_sw_deinit_ctx(disp->driver, disp->driver->draw_ctx); - lv_mem_free(disp->driver->draw_ctx); -} - - - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.h deleted file mode 100644 index 71f051614..000000000 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_canvas.h +++ /dev/null @@ -1,280 +0,0 @@ -/** - * @file lv_canvas.h - * - */ - -#ifndef LV_CANVAS_H -#define LV_CANVAS_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_CANVAS != 0 - -#include "../core/lv_obj.h" -#include "../widgets/lv_img.h" -#include "../draw/lv_draw_img.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ -extern const lv_obj_class_t lv_canvas_class; - -/*Data of canvas*/ -typedef struct { - lv_img_t img; - lv_img_dsc_t dsc; -} lv_canvas_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create a canvas object - * @param parent pointer to an object, it will be the parent of the new canvas - * @return pointer to the created canvas - */ -lv_obj_t * lv_canvas_create(lv_obj_t * parent); - -/*===================== - * Setter functions - *====================*/ - -/** - * Set a buffer for the canvas. - * @param buf a buffer where the content of the canvas will be. - * The required size is (lv_img_color_format_get_px_size(cf) * w) / 8 * h) - * It can be allocated with `lv_mem_alloc()` or - * it can be statically allocated array (e.g. static lv_color_t buf[100*50]) or - * it can be an address in RAM or external SRAM - * @param canvas pointer to a canvas object - * @param w width of the canvas - * @param h height of the canvas - * @param cf color format. `LV_IMG_CF_...` - */ -void lv_canvas_set_buffer(lv_obj_t * canvas, void * buf, lv_coord_t w, lv_coord_t h, lv_img_cf_t cf); - -/** - * Set the color of a pixel on the canvas - * @param canvas - * @param x x coordinate of the point to set - * @param y x coordinate of the point to set - * @param c color of the pixel - */ -void lv_canvas_set_px_color(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c); - -/** - * DEPRECATED: added only for backward compatibility - */ -static inline void lv_canvas_set_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c) -{ - lv_canvas_set_px_color(canvas, x, y, c); -} - -/** - * Set the opacity of a pixel on the canvas - * @param canvas - * @param x x coordinate of the point to set - * @param y x coordinate of the point to set - * @param opa opacity of the pixel (0..255) - */ -void lv_canvas_set_px_opa(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_opa_t opa); - - -/** - * Set the palette color of a canvas with index format. Valid only for `LV_IMG_CF_INDEXED1/2/4/8` - * @param canvas pointer to canvas object - * @param id the palette color to set: - * - for `LV_IMG_CF_INDEXED1`: 0..1 - * - for `LV_IMG_CF_INDEXED2`: 0..3 - * - for `LV_IMG_CF_INDEXED4`: 0..15 - * - for `LV_IMG_CF_INDEXED8`: 0..255 - * @param c the color to set - */ -void lv_canvas_set_palette(lv_obj_t * canvas, uint8_t id, lv_color_t c); - -/*===================== - * Getter functions - *====================*/ - -/** - * Get the color of a pixel on the canvas - * @param canvas - * @param x x coordinate of the point to set - * @param y x coordinate of the point to set - * @return color of the point - */ -lv_color_t lv_canvas_get_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y); - -/** - * Get the image of the canvas as a pointer to an `lv_img_dsc_t` variable. - * @param canvas pointer to a canvas object - * @return pointer to the image descriptor. - */ -lv_img_dsc_t * lv_canvas_get_img(lv_obj_t * canvas); - -/*===================== - * Other functions - *====================*/ - -/** - * Copy a buffer to the canvas - * @param canvas pointer to a canvas object - * @param to_copy buffer to copy. The color format has to match with the canvas's buffer color - * format - * @param x left side of the destination position - * @param y top side of the destination position - * @param w width of the buffer to copy - * @param h height of the buffer to copy - */ -void lv_canvas_copy_buf(lv_obj_t * canvas, const void * to_copy, lv_coord_t x, lv_coord_t y, lv_coord_t w, - lv_coord_t h); - -/** - * Transform and image and store the result on a canvas. - * @param canvas pointer to a canvas object to store the result of the transformation. - * @param img pointer to an image descriptor to transform. - * Can be the image descriptor of an other canvas too (`lv_canvas_get_img()`). - * @param angle the angle of rotation (0..3600), 0.1 deg resolution - * @param zoom zoom factor (256 no zoom); - * @param offset_x offset X to tell where to put the result data on destination canvas - * @param offset_y offset X to tell where to put the result data on destination canvas - * @param pivot_x pivot X of rotation. Relative to the source canvas - * Set to `source width / 2` to rotate around the center - * @param pivot_y pivot Y of rotation. Relative to the source canvas - * Set to `source height / 2` to rotate around the center - * @param antialias apply anti-aliasing during the transformation. Looks better but slower. - */ -void lv_canvas_transform(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, uint16_t zoom, lv_coord_t offset_x, - lv_coord_t offset_y, - int32_t pivot_x, int32_t pivot_y, bool antialias); - -/** - * Apply horizontal blur on the canvas - * @param canvas pointer to a canvas object - * @param area the area to blur. If `NULL` the whole canvas will be blurred. - * @param r radius of the blur - */ -void lv_canvas_blur_hor(lv_obj_t * canvas, const lv_area_t * area, uint16_t r); - -/** - * Apply vertical blur on the canvas - * @param canvas pointer to a canvas object - * @param area the area to blur. If `NULL` the whole canvas will be blurred. - * @param r radius of the blur - */ -void lv_canvas_blur_ver(lv_obj_t * canvas, const lv_area_t * area, uint16_t r); - -/** - * Fill the canvas with color - * @param canvas pointer to a canvas - * @param color the background color - * @param opa the desired opacity - */ -void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color, lv_opa_t opa); - -/** - * Draw a rectangle on the canvas - * @param canvas pointer to a canvas object - * @param x left coordinate of the rectangle - * @param y top coordinate of the rectangle - * @param w width of the rectangle - * @param h height of the rectangle - * @param draw_dsc descriptor of the rectangle - */ -void lv_canvas_draw_rect(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t w, lv_coord_t h, - const lv_draw_rect_dsc_t * draw_dsc); - -/** - * Draw a text on the canvas. - * @param canvas pointer to a canvas object - * @param x left coordinate of the text - * @param y top coordinate of the text - * @param max_w max width of the text. The text will be wrapped to fit into this size - * @param draw_dsc pointer to a valid label descriptor `lv_draw_label_dsc_t` - * @param txt text to display - */ -void lv_canvas_draw_text(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t max_w, - lv_draw_label_dsc_t * draw_dsc, const char * txt); - -/** - * Draw an image on the canvas - * @param canvas pointer to a canvas object - * @param x left coordinate of the image - * @param y top coordinate of the image - * @param src image source. Can be a pointer an `lv_img_dsc_t` variable or a path an image. - * @param draw_dsc pointer to a valid label descriptor `lv_draw_img_dsc_t` - */ -void lv_canvas_draw_img(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, const void * src, - const lv_draw_img_dsc_t * draw_dsc); - -/** - * Draw a line on the canvas - * @param canvas pointer to a canvas object - * @param points point of the line - * @param point_cnt number of points - * @param draw_dsc pointer to an initialized `lv_draw_line_dsc_t` variable - */ -void lv_canvas_draw_line(lv_obj_t * canvas, const lv_point_t points[], uint32_t point_cnt, - const lv_draw_line_dsc_t * draw_dsc); - -/** - * Draw a polygon on the canvas - * @param canvas pointer to a canvas object - * @param points point of the polygon - * @param point_cnt number of points - * @param draw_dsc pointer to an initialized `lv_draw_rect_dsc_t` variable - */ -void lv_canvas_draw_polygon(lv_obj_t * canvas, const lv_point_t points[], uint32_t point_cnt, - const lv_draw_rect_dsc_t * draw_dsc); - -/** - * Draw an arc on the canvas - * @param canvas pointer to a canvas object - * @param x origo x of the arc - * @param y origo y of the arc - * @param r radius of the arc - * @param start_angle start angle in degrees - * @param end_angle end angle in degrees - * @param draw_dsc pointer to an initialized `lv_draw_line_dsc_t` variable - */ -void lv_canvas_draw_arc(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t r, int32_t start_angle, - int32_t end_angle, const lv_draw_arc_dsc_t * draw_dsc); - -/********************** - * MACROS - **********************/ -#define LV_CANVAS_BUF_SIZE_TRUE_COLOR(w, h) LV_IMG_BUF_SIZE_TRUE_COLOR(w, h) -#define LV_CANVAS_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h) LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h) -#define LV_CANVAS_BUF_SIZE_TRUE_COLOR_ALPHA(w, h) LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h) - -/*+ 1: to be sure no fractional row*/ -#define LV_CANVAS_BUF_SIZE_ALPHA_1BIT(w, h) LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) -#define LV_CANVAS_BUF_SIZE_ALPHA_2BIT(w, h) LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) -#define LV_CANVAS_BUF_SIZE_ALPHA_4BIT(w, h) LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) -#define LV_CANVAS_BUF_SIZE_ALPHA_8BIT(w, h) LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) - -/*4 * X: for palette*/ -#define LV_CANVAS_BUF_SIZE_INDEXED_1BIT(w, h) LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h) -#define LV_CANVAS_BUF_SIZE_INDEXED_2BIT(w, h) LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h) -#define LV_CANVAS_BUF_SIZE_INDEXED_4BIT(w, h) LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h) -#define LV_CANVAS_BUF_SIZE_INDEXED_8BIT(w, h) LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h) - -#endif /*LV_USE_CANVAS*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_CANVAS_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.c deleted file mode 100644 index 3246e4a69..000000000 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.c +++ /dev/null @@ -1,692 +0,0 @@ -/** - * @file lv_img.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_img.h" -#if LV_USE_IMG != 0 - -#include "../core/lv_disp.h" -#include "../misc/lv_assert.h" -#include "../draw/lv_img_decoder.h" -#include "../misc/lv_fs.h" -#include "../misc/lv_txt.h" -#include "../misc/lv_math.h" -#include "../misc/lv_log.h" - -/********************* - * DEFINES - *********************/ -#define MY_CLASS &lv_img_class - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void lv_img_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void lv_img_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void lv_img_event(const lv_obj_class_t * class_p, lv_event_t * e); -static void draw_img(lv_event_t * e); - -/********************** - * STATIC VARIABLES - **********************/ -const lv_obj_class_t lv_img_class = { - .constructor_cb = lv_img_constructor, - .destructor_cb = lv_img_destructor, - .event_cb = lv_img_event, - .width_def = LV_SIZE_CONTENT, - .height_def = LV_SIZE_CONTENT, - .instance_size = sizeof(lv_img_t), - .base_class = &lv_obj_class -}; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_obj_t * lv_img_create(lv_obj_t * parent) -{ - LV_LOG_INFO("begin"); - lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); - lv_obj_class_init_obj(obj); - return obj; -} - -/*===================== - * Setter functions - *====================*/ - -void lv_img_set_src(lv_obj_t * obj, const void * src) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_obj_invalidate(obj); - - lv_img_src_t src_type = lv_img_src_get_type(src); - lv_img_t * img = (lv_img_t *)obj; - -#if LV_USE_LOG && LV_LOG_LEVEL >= LV_LOG_LEVEL_INFO - switch(src_type) { - case LV_IMG_SRC_FILE: - LV_LOG_TRACE("lv_img_set_src: `LV_IMG_SRC_FILE` type found"); - break; - case LV_IMG_SRC_VARIABLE: - LV_LOG_TRACE("lv_img_set_src: `LV_IMG_SRC_VARIABLE` type found"); - break; - case LV_IMG_SRC_SYMBOL: - LV_LOG_TRACE("lv_img_set_src: `LV_IMG_SRC_SYMBOL` type found"); - break; - default: - LV_LOG_WARN("lv_img_set_src: unknown type"); - } -#endif - - /*If the new source type is unknown free the memories of the old source*/ - if(src_type == LV_IMG_SRC_UNKNOWN) { - LV_LOG_WARN("lv_img_set_src: unknown image type"); - if(img->src_type == LV_IMG_SRC_SYMBOL || img->src_type == LV_IMG_SRC_FILE) { - lv_mem_free((void *)img->src); - } - img->src = NULL; - img->src_type = LV_IMG_SRC_UNKNOWN; - return; - } - - lv_img_header_t header; - lv_img_decoder_get_info(src, &header); - - /*Save the source*/ - if(src_type == LV_IMG_SRC_VARIABLE) { - /*If memory was allocated because of the previous `src_type` then free it*/ - if(img->src_type == LV_IMG_SRC_FILE || img->src_type == LV_IMG_SRC_SYMBOL) { - lv_mem_free((void *)img->src); - } - img->src = src; - } - else if(src_type == LV_IMG_SRC_FILE || src_type == LV_IMG_SRC_SYMBOL) { - /*If the new and the old src are the same then it was only a refresh.*/ - if(img->src != src) { - const void * old_src = NULL; - /*If memory was allocated because of the previous `src_type` then save its pointer and free after allocation. - *It's important to allocate first to be sure the new data will be on a new address. - *Else `img_cache` wouldn't see the change in source.*/ - if(img->src_type == LV_IMG_SRC_FILE || img->src_type == LV_IMG_SRC_SYMBOL) { - old_src = img->src; - } - char * new_str = lv_mem_alloc(strlen(src) + 1); - LV_ASSERT_MALLOC(new_str); - if(new_str == NULL) return; - strcpy(new_str, src); - img->src = new_str; - - if(old_src) lv_mem_free((void *)old_src); - } - } - - if(src_type == LV_IMG_SRC_SYMBOL) { - /*`lv_img_dsc_get_info` couldn't set the width and height of a font so set it here*/ - const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - lv_point_t size; - lv_txt_get_size(&size, src, font, letter_space, line_space, LV_COORD_MAX, LV_TEXT_FLAG_NONE); - header.w = size.x; - header.h = size.y; - } - - img->src_type = src_type; - img->w = header.w; - img->h = header.h; - img->cf = header.cf; - img->pivot.x = header.w / 2; - img->pivot.y = header.h / 2; - - lv_obj_refresh_self_size(obj); - - /*Provide enough room for the rotated corners*/ - if(img->angle || img->zoom != LV_IMG_ZOOM_NONE) lv_obj_refresh_ext_draw_size(obj); - - lv_obj_invalidate(obj); -} - -void lv_img_set_offset_x(lv_obj_t * obj, lv_coord_t x) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_img_t * img = (lv_img_t *)obj; - - img->offset.x = x; - lv_obj_invalidate(obj); -} - -void lv_img_set_offset_y(lv_obj_t * obj, lv_coord_t y) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_img_t * img = (lv_img_t *)obj; - - img->offset.y = y; - lv_obj_invalidate(obj); -} - -void lv_img_set_angle(lv_obj_t * obj, int16_t angle) -{ - while(angle >= 3600) angle -= 3600; - while(angle < 0) angle += 3600; - - lv_img_t * img = (lv_img_t *)obj; - if(angle == img->angle) return; - - lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/ - lv_coord_t w = lv_obj_get_width(obj); - lv_coord_t h = lv_obj_get_height(obj); - lv_area_t a; - _lv_img_buf_get_transformed_area(&a, w, h, img->angle, img->zoom, &img->pivot); - a.x1 += obj->coords.x1; - a.y1 += obj->coords.y1; - a.x2 += obj->coords.x1; - a.y2 += obj->coords.y1; - lv_obj_invalidate_area(obj, &a); - - img->angle = angle; - - /* Disable invalidations because lv_obj_refresh_ext_draw_size would invalidate - * the whole ext draw area */ - lv_disp_t * disp = lv_obj_get_disp(obj); - lv_disp_enable_invalidation(disp, false); - lv_obj_refresh_ext_draw_size(obj); - lv_disp_enable_invalidation(disp, true); - - _lv_img_buf_get_transformed_area(&a, w, h, img->angle, img->zoom, &img->pivot); - a.x1 += obj->coords.x1; - a.y1 += obj->coords.y1; - a.x2 += obj->coords.x1; - a.y2 += obj->coords.y1; - lv_obj_invalidate_area(obj, &a); -} - -void lv_img_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) -{ - lv_img_t * img = (lv_img_t *)obj; - if(img->pivot.x == x && img->pivot.y == y) return; - - lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/ - lv_coord_t w = lv_obj_get_width(obj); - lv_coord_t h = lv_obj_get_height(obj); - lv_area_t a; - _lv_img_buf_get_transformed_area(&a, w, h, img->angle, img->zoom, &img->pivot); - a.x1 += obj->coords.x1; - a.y1 += obj->coords.y1; - a.x2 += obj->coords.x1; - a.y2 += obj->coords.y1; - lv_obj_invalidate_area(obj, &a); - - img->pivot.x = x; - img->pivot.y = y; - - /* Disable invalidations because lv_obj_refresh_ext_draw_size would invalidate - * the whole ext draw area */ - lv_disp_t * disp = lv_obj_get_disp(obj); - lv_disp_enable_invalidation(disp, false); - lv_obj_refresh_ext_draw_size(obj); - lv_disp_enable_invalidation(disp, true); - - _lv_img_buf_get_transformed_area(&a, w, h, img->angle, img->zoom, &img->pivot); - a.x1 += obj->coords.x1; - a.y1 += obj->coords.y1; - a.x2 += obj->coords.x1; - a.y2 += obj->coords.y1; - lv_obj_invalidate_area(obj, &a); -} - -void lv_img_set_zoom(lv_obj_t * obj, uint16_t zoom) -{ - lv_img_t * img = (lv_img_t *)obj; - if(zoom == img->zoom) return; - - if(zoom == 0) zoom = 1; - - lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/ - lv_coord_t w = lv_obj_get_width(obj); - lv_coord_t h = lv_obj_get_height(obj); - lv_area_t a; - _lv_img_buf_get_transformed_area(&a, w, h, img->angle, img->zoom >> 8, &img->pivot); - a.x1 += obj->coords.x1 - 1; - a.y1 += obj->coords.y1 - 1; - a.x2 += obj->coords.x1 + 1; - a.y2 += obj->coords.y1 + 1; - lv_obj_invalidate_area(obj, &a); - - img->zoom = zoom; - - /* Disable invalidations because lv_obj_refresh_ext_draw_size would invalidate - * the whole ext draw area */ - lv_disp_t * disp = lv_obj_get_disp(obj); - lv_disp_enable_invalidation(disp, false); - lv_obj_refresh_ext_draw_size(obj); - lv_disp_enable_invalidation(disp, true); - - _lv_img_buf_get_transformed_area(&a, w, h, img->angle, img->zoom, &img->pivot); - a.x1 += obj->coords.x1 - 1; - a.y1 += obj->coords.y1 - 1; - a.x2 += obj->coords.x1 + 1; - a.y2 += obj->coords.y1 + 1; - lv_obj_invalidate_area(obj, &a); -} - -void lv_img_set_antialias(lv_obj_t * obj, bool antialias) -{ - lv_img_t * img = (lv_img_t *)obj; - if(antialias == img->antialias) return; - - img->antialias = antialias; - lv_obj_invalidate(obj); -} - -void lv_img_set_size_mode(lv_obj_t * obj, lv_img_size_mode_t mode) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_img_t * img = (lv_img_t *)obj; - if(mode == img->obj_size_mode) return; - - img->obj_size_mode = mode; - lv_obj_invalidate(obj); -} - -/*===================== - * Getter functions - *====================*/ - -const void * lv_img_get_src(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_img_t * img = (lv_img_t *)obj; - - return img->src; -} - -lv_coord_t lv_img_get_offset_x(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_img_t * img = (lv_img_t *)obj; - - return img->offset.x; -} - -lv_coord_t lv_img_get_offset_y(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_img_t * img = (lv_img_t *)obj; - - return img->offset.y; -} - -uint16_t lv_img_get_angle(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_img_t * img = (lv_img_t *)obj; - - return img->angle; -} - -void lv_img_get_pivot(lv_obj_t * obj, lv_point_t * pivot) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_img_t * img = (lv_img_t *)obj; - - *pivot = img->pivot; -} - -uint16_t lv_img_get_zoom(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_img_t * img = (lv_img_t *)obj; - - return img->zoom; -} - -bool lv_img_get_antialias(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - - lv_img_t * img = (lv_img_t *)obj; - - return img->antialias ? true : false; -} - -lv_img_size_mode_t lv_img_get_size_mode(lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_img_t * img = (lv_img_t *)obj; - return img->obj_size_mode; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void lv_img_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) -{ - LV_UNUSED(class_p); - LV_TRACE_OBJ_CREATE("begin"); - - lv_img_t * img = (lv_img_t *)obj; - - img->src = NULL; - img->src_type = LV_IMG_SRC_UNKNOWN; - img->cf = LV_IMG_CF_UNKNOWN; - img->w = lv_obj_get_width(obj); - img->h = lv_obj_get_height(obj); - img->angle = 0; - img->zoom = LV_IMG_ZOOM_NONE; - img->antialias = LV_COLOR_DEPTH > 8 ? 1 : 0; - img->offset.x = 0; - img->offset.y = 0; - img->pivot.x = 0; - img->pivot.y = 0; - img->obj_size_mode = LV_IMG_SIZE_MODE_VIRTUAL; - - lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICKABLE); - lv_obj_add_flag(obj, LV_OBJ_FLAG_ADV_HITTEST); - - LV_TRACE_OBJ_CREATE("finished"); -} - -static void lv_img_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) -{ - LV_UNUSED(class_p); - lv_img_t * img = (lv_img_t *)obj; - if(img->src_type == LV_IMG_SRC_FILE || img->src_type == LV_IMG_SRC_SYMBOL) { - lv_mem_free((void *)img->src); - img->src = NULL; - img->src_type = LV_IMG_SRC_UNKNOWN; - } -} - -static lv_point_t lv_img_get_transformed_size(lv_obj_t * obj) -{ - lv_img_t * img = (lv_img_t *)obj; - - - lv_area_t area_transform; - _lv_img_buf_get_transformed_area(&area_transform, img->w, img->h, - img->angle, img->zoom, &img->pivot); - - return (lv_point_t) { - lv_area_get_width(&area_transform), lv_area_get_height(&area_transform) - }; -} - -static void lv_img_event(const lv_obj_class_t * class_p, lv_event_t * e) -{ - LV_UNUSED(class_p); - - lv_event_code_t code = lv_event_get_code(e); - - /*Ancestor events will be called during drawing*/ - if(code != LV_EVENT_DRAW_MAIN && code != LV_EVENT_DRAW_POST) { - /*Call the ancestor's event handler*/ - lv_res_t res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; - } - - lv_obj_t * obj = lv_event_get_target(e); - lv_img_t * img = (lv_img_t *)obj; - - if(code == LV_EVENT_STYLE_CHANGED) { - /*Refresh the file name to refresh the symbol text size*/ - if(img->src_type == LV_IMG_SRC_SYMBOL) { - lv_img_set_src(obj, img->src); - } - else { - /*With transformation it might change*/ - lv_obj_refresh_ext_draw_size(obj); - } - } - else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - - lv_coord_t * s = lv_event_get_param(e); - - /*If the image has angle provide enough room for the rotated corners*/ - if(img->angle || img->zoom != LV_IMG_ZOOM_NONE) { - lv_area_t a; - lv_coord_t w = lv_obj_get_width(obj); - lv_coord_t h = lv_obj_get_height(obj); - _lv_img_buf_get_transformed_area(&a, w, h, img->angle, img->zoom, &img->pivot); - *s = LV_MAX(*s, -a.x1); - *s = LV_MAX(*s, -a.y1); - *s = LV_MAX(*s, a.x2 - w); - *s = LV_MAX(*s, a.y2 - h); - } - } - else if(code == LV_EVENT_HIT_TEST) { - lv_hit_test_info_t * info = lv_event_get_param(e); - - /*If the object is exactly image sized (not cropped, not mosaic) and transformed - *perform hit test on its transformed area*/ - if(img->w == lv_obj_get_width(obj) && img->h == lv_obj_get_height(obj) && - (img->zoom != LV_IMG_ZOOM_NONE || img->angle != 0 || img->pivot.x != img->w / 2 || img->pivot.y != img->h / 2)) { - - lv_coord_t w = lv_obj_get_width(obj); - lv_coord_t h = lv_obj_get_height(obj); - lv_area_t coords; - _lv_img_buf_get_transformed_area(&coords, w, h, img->angle, img->zoom, &img->pivot); - coords.x1 += obj->coords.x1; - coords.y1 += obj->coords.y1; - coords.x2 += obj->coords.x1; - coords.y2 += obj->coords.y1; - - info->res = _lv_area_is_point_on(&coords, info->point, 0); - } - else { - lv_area_t a; - lv_obj_get_click_area(obj, &a); - info->res = _lv_area_is_point_on(&a, info->point, 0); - } - } - else if(code == LV_EVENT_GET_SELF_SIZE) { - lv_point_t * p = lv_event_get_param(e); - if(img->obj_size_mode == LV_IMG_SIZE_MODE_REAL) { - *p = lv_img_get_transformed_size(obj); - } - else { - p->x = img->w; - p->y = img->h; - } - } - else if(code == LV_EVENT_DRAW_MAIN || code == LV_EVENT_DRAW_POST || code == LV_EVENT_COVER_CHECK) { - draw_img(e); - } -} - -static void draw_img(lv_event_t * e) -{ - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); - lv_img_t * img = (lv_img_t *)obj; - if(code == LV_EVENT_COVER_CHECK) { - lv_cover_check_info_t * info = lv_event_get_param(e); - if(info->res == LV_COVER_RES_MASKED) return; - if(img->src_type == LV_IMG_SRC_UNKNOWN || img->src_type == LV_IMG_SRC_SYMBOL) { - info->res = LV_COVER_RES_NOT_COVER; - return; - } - - /*Non true color format might have "holes"*/ - if(img->cf != LV_IMG_CF_TRUE_COLOR && img->cf != LV_IMG_CF_RAW) { - info->res = LV_COVER_RES_NOT_COVER; - return; - } - - /*With not LV_OPA_COVER images can't cover an area */ - if(lv_obj_get_style_img_opa(obj, LV_PART_MAIN) != LV_OPA_COVER) { - info->res = LV_COVER_RES_NOT_COVER; - return; - } - - if(img->angle != 0) { - info->res = LV_COVER_RES_NOT_COVER; - return; - } - - const lv_area_t * clip_area = lv_event_get_param(e); - if(img->zoom == LV_IMG_ZOOM_NONE) { - if(_lv_area_is_in(clip_area, &obj->coords, 0) == false) { - info->res = LV_COVER_RES_NOT_COVER; - return; - } - } - else { - lv_area_t a; - _lv_img_buf_get_transformed_area(&a, lv_obj_get_width(obj), lv_obj_get_height(obj), 0, img->zoom, &img->pivot); - a.x1 += obj->coords.x1; - a.y1 += obj->coords.y1; - a.x2 += obj->coords.x1; - a.y2 += obj->coords.y1; - - if(_lv_area_is_in(clip_area, &a, 0) == false) { - info->res = LV_COVER_RES_NOT_COVER; - return; - } - } - } - else if(code == LV_EVENT_DRAW_MAIN || code == LV_EVENT_DRAW_POST) { - - lv_coord_t obj_w = lv_obj_get_width(obj); - lv_coord_t obj_h = lv_obj_get_height(obj); - - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t pleft = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; - lv_coord_t pright = lv_obj_get_style_pad_right(obj, LV_PART_MAIN) + border_width; - lv_coord_t ptop = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; - lv_coord_t pbottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN) + border_width; - - lv_point_t bg_pivot; - bg_pivot.x = img->pivot.x + pleft; - bg_pivot.y = img->pivot.y + ptop; - lv_area_t bg_coords; - - if(img->obj_size_mode == LV_IMG_SIZE_MODE_REAL) { - /*Object size equals to transformed image size*/ - lv_obj_get_coords(obj, &bg_coords); - } - else { - _lv_img_buf_get_transformed_area(&bg_coords, obj_w, obj_h, - img->angle, img->zoom, &bg_pivot); - - /*Modify the coordinates to draw the background for the rotated and scaled coordinates*/ - bg_coords.x1 += obj->coords.x1; - bg_coords.y1 += obj->coords.y1; - bg_coords.x2 += obj->coords.x1; - bg_coords.y2 += obj->coords.y1; - } - - lv_area_t ori_coords; - lv_area_copy(&ori_coords, &obj->coords); - lv_area_copy(&obj->coords, &bg_coords); - - lv_res_t res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; - - lv_area_copy(&obj->coords, &ori_coords); - - if(code == LV_EVENT_DRAW_MAIN) { - if(img->h == 0 || img->w == 0) return; - if(img->zoom == 0) return; - - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); - - lv_area_t img_max_area; - lv_area_copy(&img_max_area, &obj->coords); - - lv_point_t img_size_final = lv_img_get_transformed_size(obj); - - if(img->obj_size_mode == LV_IMG_SIZE_MODE_REAL) { - img_max_area.x1 -= ((img->w - img_size_final.x) + 1) / 2; - img_max_area.x2 -= ((img->w - img_size_final.x) + 1) / 2; - img_max_area.y1 -= ((img->h - img_size_final.y) + 1) / 2; - img_max_area.y2 -= ((img->h - img_size_final.y) + 1) / 2; - } - else { - img_max_area.x2 = img_max_area.x1 + lv_area_get_width(&bg_coords) - 1; - img_max_area.y2 = img_max_area.y1 + lv_area_get_height(&bg_coords) - 1; - } - - img_max_area.x1 += pleft; - img_max_area.y1 += ptop; - img_max_area.x2 -= pright; - img_max_area.y2 -= pbottom; - - if(img->src_type == LV_IMG_SRC_FILE || img->src_type == LV_IMG_SRC_VARIABLE) { - lv_draw_img_dsc_t img_dsc; - lv_draw_img_dsc_init(&img_dsc); - lv_obj_init_draw_img_dsc(obj, LV_PART_MAIN, &img_dsc); - - img_dsc.zoom = img->zoom; - img_dsc.angle = img->angle; - img_dsc.pivot.x = img->pivot.x; - img_dsc.pivot.y = img->pivot.y; - img_dsc.antialias = img->antialias; - - lv_area_t img_clip_area; - img_clip_area.x1 = bg_coords.x1 + pleft; - img_clip_area.y1 = bg_coords.y1 + ptop; - img_clip_area.x2 = bg_coords.x2 - pright; - img_clip_area.y2 = bg_coords.y2 - pbottom; - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - - if(!_lv_area_intersect(&img_clip_area, draw_ctx->clip_area, &img_clip_area)) return; - draw_ctx->clip_area = &img_clip_area; - - lv_area_t coords_tmp; - lv_coord_t offset_x = img->offset.x % img->w; - lv_coord_t offset_y = img->offset.y % img->h; - coords_tmp.y1 = img_max_area.y1 + offset_y; - if(coords_tmp.y1 > img_max_area.y1) coords_tmp.y1 -= img->h; - coords_tmp.y2 = coords_tmp.y1 + img->h - 1; - - for(; coords_tmp.y1 < img_max_area.y2; coords_tmp.y1 += img_size_final.y, coords_tmp.y2 += img_size_final.y) { - coords_tmp.x1 = img_max_area.x1 + offset_x; - if(coords_tmp.x1 > img_max_area.x1) coords_tmp.x1 -= img->w; - coords_tmp.x2 = coords_tmp.x1 + img->w - 1; - - for(; coords_tmp.x1 < img_max_area.x2; coords_tmp.x1 += img_size_final.x, coords_tmp.x2 += img_size_final.x) { - lv_draw_img(draw_ctx, &img_dsc, &coords_tmp, img->src); - } - } - draw_ctx->clip_area = clip_area_ori; - } - else if(img->src_type == LV_IMG_SRC_SYMBOL) { - lv_draw_label_dsc_t label_dsc; - lv_draw_label_dsc_init(&label_dsc); - lv_obj_init_draw_label_dsc(obj, LV_PART_MAIN, &label_dsc); - - lv_draw_label(draw_ctx, &label_dsc, &obj->coords, img->src, NULL); - } - else { - /*Trigger the error handler of image draw*/ - LV_LOG_WARN("draw_img: image source type is unknown"); - lv_draw_img(draw_ctx, NULL, &obj->coords, NULL); - } - } - } -} - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.h b/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.h deleted file mode 100644 index eb76c8d98..000000000 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_img.h +++ /dev/null @@ -1,234 +0,0 @@ -/** - * @file lv_img.h - * - */ - -#ifndef LV_IMG_H -#define LV_IMG_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include "../lv_conf_internal.h" - -#if LV_USE_IMG != 0 - -/*Testing of dependencies*/ -#if LV_USE_LABEL == 0 -#error "lv_img: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1)" -#endif - -#include "../core/lv_obj.h" -#include "../misc/lv_fs.h" -#include "../draw/lv_draw.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/** - * Data of image - */ -typedef struct { - lv_obj_t obj; - const void * src; /*Image source: Pointer to an array or a file or a symbol*/ - lv_point_t offset; - lv_coord_t w; /*Width of the image (Handled by the library)*/ - lv_coord_t h; /*Height of the image (Handled by the library)*/ - uint16_t angle; /*rotation angle of the image*/ - lv_point_t pivot; /*rotation center of the image*/ - uint16_t zoom; /*256 means no zoom, 512 double size, 128 half size*/ - uint8_t src_type : 2; /*See: lv_img_src_t*/ - uint8_t cf : 5; /*Color format from `lv_img_color_format_t`*/ - uint8_t antialias : 1; /*Apply anti-aliasing in transformations (rotate, zoom)*/ - uint8_t obj_size_mode: 2; /*Image size mode when image size and object size is different.*/ -} lv_img_t; - -extern const lv_obj_class_t lv_img_class; - -/** - * Image size mode, when image size and object size is different - */ -enum { - /** Zoom doesn't affect the coordinates of the object, - * however if zoomed in the image is drawn out of the its coordinates. - * The layout's won't change on zoom */ - LV_IMG_SIZE_MODE_VIRTUAL = 0, - - /** If the object size is set to SIZE_CONTENT, then object size equals zoomed image size. - * It causes layout recalculation. - * If the object size is set explicitly, the image will be cropped when zoomed in.*/ - LV_IMG_SIZE_MODE_REAL, -}; - -typedef uint8_t lv_img_size_mode_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Create an image object - * @param parent pointer to an object, it will be the parent of the new image - * @return pointer to the created image - */ -lv_obj_t * lv_img_create(lv_obj_t * parent); - -/*===================== - * Setter functions - *====================*/ - -/** - * Set the image data to display on the object - * @param obj pointer to an image object - * @param src_img 1) pointer to an ::lv_img_dsc_t descriptor (converted by LVGL's image converter) (e.g. &my_img) or - * 2) path to an image file (e.g. "S:/dir/img.bin")or - * 3) a SYMBOL (e.g. LV_SYMBOL_OK) - */ -void lv_img_set_src(lv_obj_t * obj, const void * src); - -/** - * Set an offset for the source of an image so the image will be displayed from the new origin. - * @param obj pointer to an image - * @param x the new offset along x axis. - */ -void lv_img_set_offset_x(lv_obj_t * obj, lv_coord_t x); - -/** - * Set an offset for the source of an image. - * so the image will be displayed from the new origin. - * @param obj pointer to an image - * @param y the new offset along y axis. - */ -void lv_img_set_offset_y(lv_obj_t * obj, lv_coord_t y); - - -/** - * Set the rotation angle of the image. - * The image will be rotated around the set pivot set by `lv_img_set_pivot()` - * Note that indexed and alpha only images can't be transformed. - * @param obj pointer to an image object - * @param angle rotation angle in degree with 0.1 degree resolution (0..3600: clock wise) - */ -void lv_img_set_angle(lv_obj_t * obj, int16_t angle); - -/** - * Set the rotation center of the image. - * The image will be rotated around this point. - * @param obj pointer to an image object - * @param x rotation center x of the image - * @param y rotation center y of the image - */ -void lv_img_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y); - - -/** - * Set the zoom factor of the image. - * Note that indexed and alpha only images can't be transformed. - * @param img pointer to an image object - * @param zoom the zoom factor. - * @example 256 or LV_ZOOM_IMG_NONE for no zoom - * @example <256: scale down - * @example >256 scale up - * @example 128 half size - * @example 512 double size - */ -void lv_img_set_zoom(lv_obj_t * obj, uint16_t zoom); - -/** - * Enable/disable anti-aliasing for the transformations (rotate, zoom) or not. - * The quality is better with anti-aliasing looks better but slower. - * @param obj pointer to an image object - * @param antialias true: anti-aliased; false: not anti-aliased - */ -void lv_img_set_antialias(lv_obj_t * obj, bool antialias); - -/** - * Set the image object size mode. - * - * @param obj pointer to an image object - * @param mode the new size mode. - */ -void lv_img_set_size_mode(lv_obj_t * obj, lv_img_size_mode_t mode); -/*===================== - * Getter functions - *====================*/ - -/** - * Get the source of the image - * @param obj pointer to an image object - * @return the image source (symbol, file name or ::lv-img_dsc_t for C arrays) - */ -const void * lv_img_get_src(lv_obj_t * obj); - -/** - * Get the offset's x attribute of the image object. - * @param img pointer to an image - * @return offset X value. - */ -lv_coord_t lv_img_get_offset_x(lv_obj_t * obj); - -/** - * Get the offset's y attribute of the image object. - * @param obj pointer to an image - * @return offset Y value. - */ -lv_coord_t lv_img_get_offset_y(lv_obj_t * obj); - -/** - * Get the rotation angle of the image. - * @param obj pointer to an image object - * @return rotation angle in 0.1 degrees (0..3600) - */ -uint16_t lv_img_get_angle(lv_obj_t * obj); - -/** - * Get the pivot (rotation center) of the image. - * @param img pointer to an image object - * @param pivot store the rotation center here - */ -void lv_img_get_pivot(lv_obj_t * obj, lv_point_t * pivot); - -/** - * Get the zoom factor of the image. - * @param obj pointer to an image object - * @return zoom factor (256: no zoom) - */ -uint16_t lv_img_get_zoom(lv_obj_t * obj); - -/** - * Get whether the transformations (rotate, zoom) are anti-aliased or not - * @param obj pointer to an image object - * @return true: anti-aliased; false: not anti-aliased - */ -bool lv_img_get_antialias(lv_obj_t * obj); - -/** - * Get the size mode of the image - * @param obj pointer to an image object - * @return element of @ref lv_img_size_mode_t - */ -lv_img_size_mode_t lv_img_get_size_mode(lv_obj_t * obj); - -/********************** - * MACROS - **********************/ - -/** Use this macro to declare an image in a C file*/ -#define LV_IMG_DECLARE(var_name) extern const lv_img_dsc_t var_name; - -#endif /*LV_USE_IMG*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*LV_IMG_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.c b/lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.c deleted file mode 100644 index 98711da40..000000000 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.c +++ /dev/null @@ -1,447 +0,0 @@ -/** - * @file lv_slider.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_slider.h" -#if LV_USE_SLIDER != 0 - -#include "../misc/lv_assert.h" -#include "../core/lv_group.h" -#include "../core/lv_indev.h" -#include "../draw/lv_draw.h" -#include "../misc/lv_math.h" -#include "../core/lv_disp.h" -#include "lv_img.h" - -/********************* - * DEFINES - *********************/ -#define MY_CLASS &lv_slider_class - -#define LV_SLIDER_KNOB_COORD(is_rtl, area) (is_rtl ? area.x1 : area.x2) - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static void lv_slider_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -static void lv_slider_event(const lv_obj_class_t * class_p, lv_event_t * e); -static void position_knob(lv_obj_t * obj, lv_area_t * knob_area, const lv_coord_t knob_size, const bool hor); -static void draw_knob(lv_event_t * e); -static bool is_slider_horizontal(lv_obj_t * obj); - -/********************** - * STATIC VARIABLES - **********************/ -const lv_obj_class_t lv_slider_class = { - .constructor_cb = lv_slider_constructor, - .event_cb = lv_slider_event, - .editable = LV_OBJ_CLASS_EDITABLE_TRUE, - .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, - .instance_size = sizeof(lv_slider_t), - .base_class = &lv_bar_class -}; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -lv_obj_t * lv_slider_create(lv_obj_t * parent) -{ - LV_LOG_INFO("begin"); - lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); - lv_obj_class_init_obj(obj); - return obj; -} - -bool lv_slider_is_dragged(const lv_obj_t * obj) -{ - LV_ASSERT_OBJ(obj, MY_CLASS); - lv_slider_t * slider = (lv_slider_t *)obj; - - return slider->dragging ? true : false; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void lv_slider_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) -{ - LV_UNUSED(class_p); - lv_slider_t * slider = (lv_slider_t *)obj; - - /*Initialize the allocated 'slider'*/ - slider->value_to_set = NULL; - slider->dragging = 0U; - slider->left_knob_focus = 0U; - - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); - lv_obj_set_ext_click_area(obj, LV_DPX(8)); -} - -static void lv_slider_event(const lv_obj_class_t * class_p, lv_event_t * e) -{ - LV_UNUSED(class_p); - - lv_res_t res; - - /*Call the ancestor's event handler*/ - res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; - - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); - lv_slider_t * slider = (lv_slider_t *)obj; - lv_slider_mode_t type = lv_slider_get_mode(obj); - - /*Advanced hit testing: react only on dragging the knob(s)*/ - if(code == LV_EVENT_HIT_TEST) { - lv_hit_test_info_t * info = lv_event_get_param(e); - lv_coord_t ext_click_area = obj->spec_attr ? obj->spec_attr->ext_click_pad : 0; - - /*Ordinary slider: was the knob area hit?*/ - lv_area_t a; - lv_area_copy(&a, &slider->right_knob_area); - lv_area_increase(&a, ext_click_area, ext_click_area); - info->res = _lv_area_is_point_on(&a, info->point, 0); - - /*There's still a chance that there is a hit if there is another knob*/ - if((info->res == false) && (type == LV_SLIDER_MODE_RANGE)) { - lv_area_copy(&a, &slider->left_knob_area); - lv_area_increase(&a, ext_click_area, ext_click_area); - info->res = _lv_area_is_point_on(&a, info->point, 0); - } - } - else if(code == LV_EVENT_PRESSED) { - lv_obj_invalidate(obj); - - lv_point_t p; - slider->dragging = true; - if(type == LV_SLIDER_MODE_NORMAL || type == LV_SLIDER_MODE_SYMMETRICAL) { - slider->value_to_set = &slider->bar.cur_value; - } - else if(type == LV_SLIDER_MODE_RANGE) { - lv_indev_get_point(lv_indev_get_act(), &p); - bool hor = lv_obj_get_width(obj) >= lv_obj_get_height(obj); - lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN); - - lv_coord_t dist_left, dist_right; - if(hor) { - if((base_dir != LV_BASE_DIR_RTL && p.x > slider->right_knob_area.x2) || (base_dir == LV_BASE_DIR_RTL && - p.x < slider->right_knob_area.x1)) { - slider->value_to_set = &slider->bar.cur_value; - } - else if((base_dir != LV_BASE_DIR_RTL && p.x < slider->left_knob_area.x1) || (base_dir == LV_BASE_DIR_RTL && - p.x > slider->left_knob_area.x2)) { - slider->value_to_set = &slider->bar.start_value; - } - else { - /*Calculate the distance from each knob*/ - dist_left = LV_ABS((slider->left_knob_area.x1 + (slider->left_knob_area.x2 - slider->left_knob_area.x1) / 2) - p.x); - dist_right = LV_ABS((slider->right_knob_area.x1 + (slider->right_knob_area.x2 - slider->right_knob_area.x1) / 2) - p.x); - - /*Use whichever one is closer*/ - if(dist_right < dist_left) { - slider->value_to_set = &slider->bar.cur_value; - slider->left_knob_focus = 0; - } - else { - slider->value_to_set = &slider->bar.start_value; - slider->left_knob_focus = 1; - } - } - } - else { - if(p.y < slider->right_knob_area.y1) { - slider->value_to_set = &slider->bar.cur_value; - } - else if(p.y > slider->left_knob_area.y2) { - slider->value_to_set = &slider->bar.start_value; - } - else { - /*Calculate the distance from each knob*/ - dist_left = LV_ABS((slider->left_knob_area.y1 + (slider->left_knob_area.y2 - slider->left_knob_area.y1) / 2) - p.y); - dist_right = LV_ABS((slider->right_knob_area.y1 + (slider->right_knob_area.y2 - slider->right_knob_area.y1) / 2) - p.y); - - /*Use whichever one is closer*/ - if(dist_right < dist_left) { - slider->value_to_set = &slider->bar.cur_value; - slider->left_knob_focus = 0; - } - else { - slider->value_to_set = &slider->bar.start_value; - slider->left_knob_focus = 1; - } - } - } - } - } - else if(code == LV_EVENT_PRESSING && slider->value_to_set != NULL) { - lv_indev_t * indev = lv_indev_get_act(); - if(lv_indev_get_type(indev) != LV_INDEV_TYPE_POINTER) return; - - lv_point_t p; - lv_indev_get_point(indev, &p); - int32_t new_value = 0; - - const int32_t range = slider->bar.max_value - slider->bar.min_value; - if(is_slider_horizontal(obj)) { - const lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - const lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - const lv_coord_t w = lv_obj_get_width(obj); - const lv_coord_t indic_w = w - bg_left - bg_right; - - if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) { - /*Make the point relative to the indicator*/ - new_value = (obj->coords.x2 - bg_right) - p.x; - } - else { - /*Make the point relative to the indicator*/ - new_value = p.x - (obj->coords.x1 + bg_left); - } - new_value = (new_value * range + indic_w / 2) / indic_w; - new_value += slider->bar.min_value; - } - else { - const lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - const lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); - const lv_coord_t h = lv_obj_get_height(obj); - const lv_coord_t indic_h = h - bg_bottom - bg_top; - - /*Make the point relative to the indicator*/ - new_value = p.y - (obj->coords.y2 + bg_bottom); - new_value = (-new_value * range + indic_h / 2) / indic_h; - new_value += slider->bar.min_value; - } - - int32_t real_max_value = slider->bar.max_value; - int32_t real_min_value = slider->bar.min_value; - /*Figure out the min. and max. for this mode*/ - if(slider->value_to_set == &slider->bar.start_value) { - real_max_value = slider->bar.cur_value; - } - else { - real_min_value = slider->bar.start_value; - } - - new_value = LV_CLAMP(real_min_value, new_value, real_max_value); - if(*slider->value_to_set != new_value) { - if(slider->value_to_set == &slider->bar.start_value) { - lv_bar_set_start_value(obj, new_value, LV_ANIM_ON); - } - else { - lv_bar_set_value(obj, new_value, LV_ANIM_ON); - } - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; - } - - } - else if(code == LV_EVENT_RELEASED || code == LV_EVENT_PRESS_LOST) { - slider->dragging = false; - slider->value_to_set = NULL; - - lv_obj_invalidate(obj); - - /*Leave edit mode if released. (No need to wait for LONG_PRESS)*/ - lv_group_t * g = lv_obj_get_group(obj); - bool editing = lv_group_get_editing(g); - lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); - if(indev_type == LV_INDEV_TYPE_ENCODER) { - if(editing) { - if(lv_slider_get_mode(obj) == LV_SLIDER_MODE_RANGE) { - if(slider->left_knob_focus == 0) slider->left_knob_focus = 1; - else { - slider->left_knob_focus = 0; - lv_group_set_editing(g, false); - } - } - else { - lv_group_set_editing(g, false); - } - } - } - - } - else if(code == LV_EVENT_FOCUSED) { - lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); - if(indev_type == LV_INDEV_TYPE_ENCODER || indev_type == LV_INDEV_TYPE_KEYPAD) { - slider->left_knob_focus = 0; - } - } - else if(code == LV_EVENT_SIZE_CHANGED) { - lv_obj_refresh_ext_draw_size(obj); - } - else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); - lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); - lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); - lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); - - /*The smaller size is the knob diameter*/ - lv_coord_t zoom = lv_obj_get_style_transform_zoom(obj, LV_PART_KNOB); - lv_coord_t trans_w = lv_obj_get_style_transform_width(obj, LV_PART_KNOB); - lv_coord_t trans_h = lv_obj_get_style_transform_height(obj, LV_PART_KNOB); - lv_coord_t knob_size = LV_MIN(lv_obj_get_width(obj) + 2 * trans_w, lv_obj_get_height(obj) + 2 * trans_h) >> 1; - knob_size = (knob_size * zoom) >> 8; - knob_size += LV_MAX(LV_MAX(knob_left, knob_right), LV_MAX(knob_bottom, knob_top)); - knob_size += 2; /*For rounding error*/ - knob_size += lv_obj_calculate_ext_draw_size(obj, LV_PART_KNOB); - - /*Indic. size is handled by bar*/ - lv_coord_t * s = lv_event_get_param(e); - *s = LV_MAX(*s, knob_size); - - } - else if(code == LV_EVENT_KEY) { - char c = *((char *)lv_event_get_param(e)); - - if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { - if(!slider->left_knob_focus) lv_slider_set_value(obj, lv_slider_get_value(obj) + 1, LV_ANIM_ON); - else lv_slider_set_left_value(obj, lv_slider_get_left_value(obj) + 1, LV_ANIM_ON); - } - else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { - if(!slider->left_knob_focus) lv_slider_set_value(obj, lv_slider_get_value(obj) - 1, LV_ANIM_ON); - else lv_slider_set_left_value(obj, lv_slider_get_left_value(obj) - 1, LV_ANIM_ON); - } - else { - return; - } - - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; - } - else if(code == LV_EVENT_DRAW_MAIN) { - draw_knob(e); - } -} - -static void draw_knob(lv_event_t * e) -{ - lv_obj_t * obj = lv_event_get_target(e); - lv_slider_t * slider = (lv_slider_t *)obj; - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); - - const bool is_rtl = LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN); - const bool is_horizontal = is_slider_horizontal(obj); - - lv_area_t knob_area; - lv_coord_t knob_size; - bool is_symmetrical = false; - if(slider->bar.mode == LV_BAR_MODE_SYMMETRICAL && slider->bar.min_value < 0 && - slider->bar.max_value > 0) is_symmetrical = true; - - if(is_horizontal) { - knob_size = lv_obj_get_height(obj); - if(is_symmetrical && slider->bar.cur_value < 0) knob_area.x1 = slider->bar.indic_area.x1; - else knob_area.x1 = LV_SLIDER_KNOB_COORD(is_rtl, slider->bar.indic_area); - } - else { - knob_size = lv_obj_get_width(obj); - if(is_symmetrical && slider->bar.cur_value < 0) knob_area.y1 = slider->bar.indic_area.y2; - else knob_area.y1 = slider->bar.indic_area.y1; - } - - lv_draw_rect_dsc_t knob_rect_dsc; - lv_draw_rect_dsc_init(&knob_rect_dsc); - lv_obj_init_draw_rect_dsc(obj, LV_PART_KNOB, &knob_rect_dsc); - /* Update knob area with knob style */ - position_knob(obj, &knob_area, knob_size, is_horizontal); - /* Update right knob area with calculated knob area */ - lv_area_copy(&slider->right_knob_area, &knob_area); - - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.part = LV_PART_KNOB; - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_SLIDER_DRAW_PART_KNOB; - part_draw_dsc.id = 0; - part_draw_dsc.draw_area = &slider->right_knob_area; - part_draw_dsc.rect_dsc = &knob_rect_dsc; - - if(lv_slider_get_mode(obj) != LV_SLIDER_MODE_RANGE) { - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_rect(draw_ctx, &knob_rect_dsc, &slider->right_knob_area); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } - else { - /*Save the draw part_draw_dsc. because it can be modified in the event*/ - lv_draw_rect_dsc_t knob_rect_dsc_tmp; - lv_memcpy(&knob_rect_dsc_tmp, &knob_rect_dsc, sizeof(lv_draw_rect_dsc_t)); - /* Draw the right knob */ - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_rect(draw_ctx, &knob_rect_dsc, &slider->right_knob_area); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - - /*Calculate the second knob area*/ - if(is_horizontal) { - /*use !is_rtl to get the other knob*/ - knob_area.x1 = LV_SLIDER_KNOB_COORD(!is_rtl, slider->bar.indic_area); - } - else { - knob_area.y1 = slider->bar.indic_area.y2; - } - position_knob(obj, &knob_area, knob_size, is_horizontal); - lv_area_copy(&slider->left_knob_area, &knob_area); - - lv_memcpy(&knob_rect_dsc, &knob_rect_dsc_tmp, sizeof(lv_draw_rect_dsc_t)); - part_draw_dsc.type = LV_SLIDER_DRAW_PART_KNOB_LEFT; - part_draw_dsc.draw_area = &slider->left_knob_area; - part_draw_dsc.rect_dsc = &knob_rect_dsc; - part_draw_dsc.id = 1; - - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); - lv_draw_rect(draw_ctx, &knob_rect_dsc, &slider->left_knob_area); - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - } -} - -static void position_knob(lv_obj_t * obj, lv_area_t * knob_area, const lv_coord_t knob_size, const bool hor) -{ - if(hor) { - knob_area->x1 -= (knob_size >> 1); - knob_area->x2 = knob_area->x1 + knob_size - 1; - knob_area->y1 = obj->coords.y1; - knob_area->y2 = obj->coords.y2; - } - else { - knob_area->y1 -= (knob_size >> 1); - knob_area->y2 = knob_area->y1 + knob_size - 1; - knob_area->x1 = obj->coords.x1; - knob_area->x2 = obj->coords.x2; - } - - lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); - lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); - lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); - lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); - - lv_coord_t transf_w = lv_obj_get_style_transform_width(obj, LV_PART_KNOB); - lv_coord_t transf_h = lv_obj_get_style_transform_height(obj, LV_PART_KNOB); - - /*Apply the paddings on the knob area*/ - knob_area->x1 -= knob_left + transf_w; - knob_area->x2 += knob_right + transf_w; - knob_area->y1 -= knob_top + transf_h; - knob_area->y2 += knob_bottom + transf_h; -} - -static bool is_slider_horizontal(lv_obj_t * obj) -{ - return lv_obj_get_width(obj) >= lv_obj_get_height(obj); -} - -#endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_widgets.mk b/lib/libesp32_lvgl/lvgl/src/widgets/lv_widgets.mk deleted file mode 100644 index 4e62dc583..000000000 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_widgets.mk +++ /dev/null @@ -1,20 +0,0 @@ -CSRCS += lv_arc.c -CSRCS += lv_bar.c -CSRCS += lv_btn.c -CSRCS += lv_btnmatrix.c -CSRCS += lv_canvas.c -CSRCS += lv_checkbox.c -CSRCS += lv_dropdown.c -CSRCS += lv_img.c -CSRCS += lv_label.c -CSRCS += lv_line.c -CSRCS += lv_roller.c -CSRCS += lv_slider.c -CSRCS += lv_switch.c -CSRCS += lv_table.c -CSRCS += lv_textarea.c - -DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/widgets -VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/widgets - -CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/widgets" diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/menu/lv_menu.c b/lib/libesp32_lvgl/lvgl/src/widgets/menu/lv_menu.c similarity index 78% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/menu/lv_menu.c rename to lib/libesp32_lvgl/lvgl/src/widgets/menu/lv_menu.c index f8dfd41cb..899a00329 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/menu/lv_menu.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/menu/lv_menu.c @@ -15,11 +15,12 @@ *********************/ #define MY_CLASS &lv_menu_class -#include "../../../core/lv_obj.h" -#include "../../layouts/flex/lv_flex.h" -#include "../../../widgets/lv_label.h" -#include "../../../widgets/lv_btn.h" -#include "../../../widgets/lv_img.h" +#include "../../core/lv_obj.h" +#include "../../layouts/lv_layout.h" +#include "../../stdlib/lv_string.h" +#include "../label/lv_label.h" +#include "../button/lv_button.h" +#include "../image/lv_image.h" /********************** * TYPEDEFS @@ -41,7 +42,8 @@ const lv_obj_class_t lv_menu_class = { .base_class = &lv_obj_class, .width_def = (LV_DPI_DEF * 3) / 2, .height_def = LV_DPI_DEF * 2, - .instance_size = sizeof(lv_menu_t) + .instance_size = sizeof(lv_menu_t), + .name = "menu", }; const lv_obj_class_t lv_menu_page_class = { .constructor_cb = lv_menu_page_constructor, @@ -49,50 +51,54 @@ const lv_obj_class_t lv_menu_page_class = { .base_class = &lv_obj_class, .width_def = LV_PCT(100), .height_def = LV_SIZE_CONTENT, - .instance_size = sizeof(lv_menu_page_t) + .instance_size = sizeof(lv_menu_page_t), + .name = "menu-page", }; const lv_obj_class_t lv_menu_cont_class = { .constructor_cb = lv_menu_cont_constructor, .base_class = &lv_obj_class, .width_def = LV_PCT(100), - .height_def = LV_SIZE_CONTENT + .height_def = LV_SIZE_CONTENT, + .name = "menu-cont", }; const lv_obj_class_t lv_menu_section_class = { .constructor_cb = lv_menu_section_constructor, .base_class = &lv_obj_class, .width_def = LV_PCT(100), - .height_def = LV_SIZE_CONTENT + .height_def = LV_SIZE_CONTENT, + .name = "menu-section", }; const lv_obj_class_t lv_menu_separator_class = { .base_class = &lv_obj_class, .width_def = LV_SIZE_CONTENT, - .height_def = LV_SIZE_CONTENT + .height_def = LV_SIZE_CONTENT, + .name = "menu-separator", }; const lv_obj_class_t lv_menu_sidebar_cont_class = { - .base_class = &lv_obj_class + .base_class = &lv_obj_class, }; const lv_obj_class_t lv_menu_main_cont_class = { - .base_class = &lv_obj_class + .base_class = &lv_obj_class, }; const lv_obj_class_t lv_menu_main_header_cont_class = { - .base_class = &lv_obj_class + .base_class = &lv_obj_class, }; const lv_obj_class_t lv_menu_sidebar_header_cont_class = { - .base_class = &lv_obj_class + .base_class = &lv_obj_class, }; static void lv_menu_refr(lv_obj_t * obj); static void lv_menu_refr_sidebar_header_mode(lv_obj_t * obj); static void lv_menu_refr_main_header_mode(lv_obj_t * obj); static void lv_menu_load_page_event_cb(lv_event_t * e); -static void lv_menu_obj_del_event_cb(lv_event_t * e); +static void lv_menu_obj_delete_event_cb(lv_event_t * e); static void lv_menu_back_event_cb(lv_event_t * e); static void lv_menu_value_changed_event_cb(lv_event_t * e); /********************** @@ -106,7 +112,7 @@ static void lv_menu_value_changed_event_cb(lv_event_t * e); /********************** * GLOBAL FUNCTIONS **********************/ -bool lv_menu_item_back_btn_is_root(lv_obj_t * menu, lv_obj_t * obj); +bool lv_menu_item_back_button_is_root(lv_obj_t * menu, lv_obj_t * obj); void lv_menu_clear_history(lv_obj_t * obj); lv_obj_t * lv_menu_create(lv_obj_t * parent) @@ -117,22 +123,17 @@ lv_obj_t * lv_menu_create(lv_obj_t * parent) return obj; } -lv_obj_t * lv_menu_page_create(lv_obj_t * parent, char * title) +lv_obj_t * lv_menu_page_create(lv_obj_t * parent, char const * const title) { LV_LOG_INFO("begin"); lv_obj_t * obj = lv_obj_class_create_obj(&lv_menu_page_class, parent); lv_obj_class_init_obj(obj); lv_menu_page_t * page = (lv_menu_page_t *)obj; - if(title) { - page->title = lv_mem_alloc(strlen(title) + 1); - LV_ASSERT_MALLOC(page->title); - if(page->title == NULL) return NULL; - strcpy(page->title, title); - } - else { - page->title = NULL; - } + /* Initialise the object */ + page->title = NULL; + page->static_title = false; + lv_menu_set_page_title(obj, title); return obj; } @@ -177,7 +178,7 @@ void lv_menu_refr(lv_obj_t * obj) page = act_hist->page; /* Delete the current item from the history */ _lv_ll_remove(history_ll, act_hist); - lv_mem_free(act_hist); + lv_free(act_hist); menu->cur_depth--; } @@ -195,11 +196,6 @@ void lv_menu_set_page(lv_obj_t * obj, lv_obj_t * page) lv_menu_t * menu = (lv_menu_t *)obj; - /* Guard against setting the same page again */ - if(menu->main_page == page) { - return; - } - /* Hide previous page */ if(menu->main_page != NULL) { lv_obj_set_parent(menu->main_page, menu->storage); @@ -229,7 +225,7 @@ void lv_menu_set_page(lv_obj_t * obj, lv_obj_t * page) lv_obj_add_state(menu->selected_tab, LV_STATE_CHECKED); } else { - lv_obj_clear_state(menu->selected_tab, LV_STATE_CHECKED); + lv_obj_remove_state(menu->selected_tab, LV_STATE_CHECKED); } } @@ -237,39 +233,39 @@ void lv_menu_set_page(lv_obj_t * obj, lv_obj_t * page) if(menu->sidebar_page != NULL) { /* With sidebar enabled */ if(menu->sidebar_generated) { - if(menu->mode_root_back_btn == LV_MENU_ROOT_BACK_BTN_ENABLED) { + if(menu->mode_root_back_btn == LV_MENU_ROOT_BACK_BUTTON_ENABLED) { /* Root back btn is always shown if enabled*/ - lv_obj_clear_flag(menu->sidebar_header_back_btn, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(menu->sidebar_header_back_btn, LV_OBJ_FLAG_HIDDEN); lv_obj_add_flag(menu->sidebar_header_back_btn, LV_OBJ_FLAG_CLICKABLE); } else { lv_obj_add_flag(menu->sidebar_header_back_btn, LV_OBJ_FLAG_HIDDEN); - lv_obj_clear_flag(menu->sidebar_header_back_btn, LV_OBJ_FLAG_CLICKABLE); + lv_obj_remove_flag(menu->sidebar_header_back_btn, LV_OBJ_FLAG_CLICKABLE); } } if(menu->cur_depth >= 2) { - lv_obj_clear_flag(menu->main_header_back_btn, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(menu->main_header_back_btn, LV_OBJ_FLAG_HIDDEN); lv_obj_add_flag(menu->main_header_back_btn, LV_OBJ_FLAG_CLICKABLE); } else { lv_obj_add_flag(menu->main_header_back_btn, LV_OBJ_FLAG_HIDDEN); - lv_obj_clear_flag(menu->main_header_back_btn, LV_OBJ_FLAG_CLICKABLE); + lv_obj_remove_flag(menu->main_header_back_btn, LV_OBJ_FLAG_CLICKABLE); } } else { /* With sidebar disabled */ - if(menu->cur_depth >= 2 || menu->mode_root_back_btn == LV_MENU_ROOT_BACK_BTN_ENABLED) { - lv_obj_clear_flag(menu->main_header_back_btn, LV_OBJ_FLAG_HIDDEN); + if(menu->cur_depth >= 2 || menu->mode_root_back_btn == LV_MENU_ROOT_BACK_BUTTON_ENABLED) { + lv_obj_remove_flag(menu->main_header_back_btn, LV_OBJ_FLAG_HIDDEN); lv_obj_add_flag(menu->main_header_back_btn, LV_OBJ_FLAG_CLICKABLE); } else { lv_obj_add_flag(menu->main_header_back_btn, LV_OBJ_FLAG_HIDDEN); - lv_obj_clear_flag(menu->main_header_back_btn, LV_OBJ_FLAG_CLICKABLE); + lv_obj_remove_flag(menu->main_header_back_btn, LV_OBJ_FLAG_CLICKABLE); } } - lv_event_send((lv_obj_t *)menu, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_send_event((lv_obj_t *)menu, LV_EVENT_VALUE_CHANGED, NULL); lv_menu_refr_main_header_mode(obj); } @@ -291,7 +287,7 @@ void lv_menu_set_sidebar_page(lv_obj_t * obj, lv_obj_t * page) lv_obj_set_size(sidebar_cont, LV_PCT(30), LV_PCT(100)); lv_obj_set_flex_flow(sidebar_cont, LV_FLEX_FLOW_COLUMN); lv_obj_add_flag(sidebar_cont, LV_OBJ_FLAG_EVENT_BUBBLE); - lv_obj_clear_flag(sidebar_cont, LV_OBJ_FLAG_CLICKABLE); + lv_obj_remove_flag(sidebar_cont, LV_OBJ_FLAG_CLICKABLE); menu->sidebar = sidebar_cont; lv_obj_t * sidebar_header = lv_obj_class_create_obj(&lv_menu_sidebar_header_cont_class, sidebar_cont); @@ -299,18 +295,18 @@ void lv_menu_set_sidebar_page(lv_obj_t * obj, lv_obj_t * page) lv_obj_set_size(sidebar_header, LV_PCT(100), LV_SIZE_CONTENT); lv_obj_set_flex_flow(sidebar_header, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(sidebar_header, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); - lv_obj_clear_flag(sidebar_header, LV_OBJ_FLAG_CLICKABLE); + lv_obj_remove_flag(sidebar_header, LV_OBJ_FLAG_CLICKABLE); lv_obj_add_flag(sidebar_header, LV_OBJ_FLAG_EVENT_BUBBLE); menu->sidebar_header = sidebar_header; - lv_obj_t * sidebar_header_back_btn = lv_btn_create(menu->sidebar_header); + lv_obj_t * sidebar_header_back_btn = lv_button_create(menu->sidebar_header); lv_obj_add_event_cb(sidebar_header_back_btn, lv_menu_back_event_cb, LV_EVENT_CLICKED, menu); lv_obj_add_flag(sidebar_header_back_btn, LV_OBJ_FLAG_EVENT_BUBBLE); lv_obj_set_flex_flow(sidebar_header_back_btn, LV_FLEX_FLOW_ROW); menu->sidebar_header_back_btn = sidebar_header_back_btn; - lv_obj_t * sidebar_header_back_icon = lv_img_create(menu->sidebar_header_back_btn); - lv_img_set_src(sidebar_header_back_icon, LV_SYMBOL_LEFT); + lv_obj_t * sidebar_header_back_icon = lv_image_create(menu->sidebar_header_back_btn); + lv_image_set_src(sidebar_header_back_icon, LV_SYMBOL_LEFT); lv_obj_t * sidebar_header_title = lv_label_create(menu->sidebar_header); lv_obj_add_flag(sidebar_header_title, LV_OBJ_FLAG_HIDDEN); @@ -327,7 +323,7 @@ void lv_menu_set_sidebar_page(lv_obj_t * obj, lv_obj_t * page) /* Sidebar should be disabled */ if(menu->sidebar_generated) { lv_obj_set_parent(menu->sidebar_page, menu->storage); - lv_obj_del(menu->sidebar); + lv_obj_delete(menu->sidebar); menu->sidebar_generated = false; } @@ -337,27 +333,27 @@ void lv_menu_set_sidebar_page(lv_obj_t * obj, lv_obj_t * page) lv_menu_refr(obj); } -void lv_menu_set_mode_header(lv_obj_t * obj, lv_menu_mode_header_t mode_header) +void lv_menu_set_mode_header(lv_obj_t * obj, lv_menu_mode_header_t mode) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_menu_t * menu = (lv_menu_t *)obj; - if(menu->mode_header != mode_header) { - menu->mode_header = mode_header; + if(menu->mode_header != mode) { + menu->mode_header = mode; lv_menu_refr_main_header_mode(obj); if(menu->sidebar_generated) lv_menu_refr_sidebar_header_mode(obj); } } -void lv_menu_set_mode_root_back_btn(lv_obj_t * obj, lv_menu_mode_root_back_btn_t mode_root_back_btn) +void lv_menu_set_mode_root_back_button(lv_obj_t * obj, lv_menu_mode_root_back_button_t mode) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_menu_t * menu = (lv_menu_t *)obj; - if(menu->mode_root_back_btn != mode_root_back_btn) { - menu->mode_root_back_btn = mode_root_back_btn; + if(menu->mode_root_back_btn != mode) { + menu->mode_root_back_btn = mode; lv_menu_refr(obj); } } @@ -367,21 +363,74 @@ void lv_menu_set_load_page_event(lv_obj_t * menu, lv_obj_t * obj, lv_obj_t * pag LV_ASSERT_OBJ(menu, MY_CLASS); lv_obj_add_flag(obj, LV_OBJ_FLAG_CLICKABLE); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLLABLE); lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS); /* Remove old event */ - if(lv_obj_remove_event_cb(obj, lv_menu_load_page_event_cb)) { - lv_event_send(obj, LV_EVENT_DELETE, NULL); - lv_obj_remove_event_cb(obj, lv_menu_obj_del_event_cb); + uint32_t i; + uint32_t event_cnt = lv_obj_get_event_count(obj); + for(i = 0; i < event_cnt; i++) { + lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(obj, i); + if(lv_event_dsc_get_cb(event_dsc) == lv_menu_load_page_event_cb) { + lv_obj_send_event(obj, LV_EVENT_DELETE, NULL); + lv_obj_remove_event(obj, i); + break; + } } - lv_menu_load_page_event_data_t * event_data = lv_mem_alloc(sizeof(lv_menu_load_page_event_data_t)); + lv_menu_load_page_event_data_t * event_data = lv_malloc(sizeof(lv_menu_load_page_event_data_t)); event_data->menu = menu; event_data->page = page; lv_obj_add_event_cb(obj, lv_menu_load_page_event_cb, LV_EVENT_CLICKED, event_data); - lv_obj_add_event_cb(obj, lv_menu_obj_del_event_cb, LV_EVENT_DELETE, event_data); + lv_obj_add_event_cb(obj, lv_menu_obj_delete_event_cb, LV_EVENT_DELETE, event_data); +} + +void lv_menu_set_page_title(lv_obj_t * page_obj, char const * const title) +{ + LV_LOG_INFO("begin"); + lv_menu_page_t * page = (lv_menu_page_t *)page_obj; + + /* Cleanup any previous set titles */ + if((!page->static_title) && page->title) { + lv_free(page->title); + page->title = NULL; + } + + if(title) { + page->static_title = false; + page->title = lv_strdup(title); + LV_ASSERT_MALLOC(page->title); + if(page->title == NULL) { + return; + } + } + else { + page->title = NULL; + page->static_title = false; + } +} + +void lv_menu_set_page_title_static(lv_obj_t * page_obj, char const * const title) +{ + LV_LOG_INFO("begin"); + lv_menu_page_t * page = (lv_menu_page_t *)page_obj; + + /* Cleanup any previous set titles */ + if((!page->static_title) && page->title) { + lv_free(page->title); + page->title = NULL; + } + + /* Set or clear the static title text */ + if(title) { + page->title = (char *) title; + page->static_title = true; + } + else { + page->title = NULL; + page->static_title = false; + } } /*===================== @@ -411,7 +460,7 @@ lv_obj_t * lv_menu_get_main_header(lv_obj_t * obj) return menu->main_header; } -lv_obj_t * lv_menu_get_main_header_back_btn(lv_obj_t * obj) +lv_obj_t * lv_menu_get_main_header_back_button(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -427,7 +476,7 @@ lv_obj_t * lv_menu_get_sidebar_header(lv_obj_t * obj) return menu->sidebar_header; } -lv_obj_t * lv_menu_get_sidebar_header_back_btn(lv_obj_t * obj) +lv_obj_t * lv_menu_get_sidebar_header_back_button(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -435,7 +484,7 @@ lv_obj_t * lv_menu_get_sidebar_header_back_btn(lv_obj_t * obj) return menu->sidebar_header_back_btn; } -bool lv_menu_back_btn_is_root(lv_obj_t * menu, lv_obj_t * obj) +bool lv_menu_back_button_is_root(lv_obj_t * menu, lv_obj_t * obj) { LV_ASSERT_OBJ(menu, MY_CLASS); @@ -477,7 +526,7 @@ static void lv_menu_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) lv_menu_t * menu = (lv_menu_t *)obj; menu->mode_header = LV_MENU_HEADER_TOP_FIXED; - menu->mode_root_back_btn = LV_MENU_ROOT_BACK_BTN_DISABLED; + menu->mode_root_back_btn = LV_MENU_ROOT_BACK_BUTTON_DISABLED; menu->cur_depth = 0; menu->prev_depth = 0; menu->sidebar_generated = false; @@ -499,7 +548,7 @@ static void lv_menu_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) lv_obj_set_flex_grow(main_cont, 1); lv_obj_set_flex_flow(main_cont, LV_FLEX_FLOW_COLUMN); lv_obj_add_flag(main_cont, LV_OBJ_FLAG_EVENT_BUBBLE); - lv_obj_clear_flag(main_cont, LV_OBJ_FLAG_CLICKABLE); + lv_obj_remove_flag(main_cont, LV_OBJ_FLAG_CLICKABLE); menu->main = main_cont; lv_obj_t * main_header = lv_obj_class_create_obj(&lv_menu_main_header_cont_class, main_cont); @@ -507,19 +556,19 @@ static void lv_menu_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) lv_obj_set_size(main_header, LV_PCT(100), LV_SIZE_CONTENT); lv_obj_set_flex_flow(main_header, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(main_header, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); - lv_obj_clear_flag(main_header, LV_OBJ_FLAG_CLICKABLE); + lv_obj_remove_flag(main_header, LV_OBJ_FLAG_CLICKABLE); lv_obj_add_flag(main_header, LV_OBJ_FLAG_EVENT_BUBBLE); menu->main_header = main_header; /* Create the default simple back btn and title */ - lv_obj_t * main_header_back_btn = lv_btn_create(menu->main_header); + lv_obj_t * main_header_back_btn = lv_button_create(menu->main_header); lv_obj_add_event_cb(main_header_back_btn, lv_menu_back_event_cb, LV_EVENT_CLICKED, menu); lv_obj_add_flag(main_header_back_btn, LV_OBJ_FLAG_EVENT_BUBBLE); lv_obj_set_flex_flow(main_header_back_btn, LV_FLEX_FLOW_ROW); menu->main_header_back_btn = main_header_back_btn; - lv_obj_t * main_header_back_icon = lv_img_create(menu->main_header_back_btn); - lv_img_set_src(main_header_back_icon, LV_SYMBOL_LEFT); + lv_obj_t * main_header_back_icon = lv_image_create(menu->main_header_back_btn); + lv_image_set_src(main_header_back_icon, LV_SYMBOL_LEFT); lv_obj_t * main_header_title = lv_label_create(menu->main_header); lv_obj_add_flag(main_header_title, LV_OBJ_FLAG_HIDDEN); @@ -564,10 +613,11 @@ static void lv_menu_page_destructor(const lv_obj_class_t * class_p, lv_obj_t * o lv_menu_page_t * page = (lv_menu_page_t *)obj; - if(page->title != NULL) { - lv_mem_free(page->title); - page->title = NULL; + if((!page->static_title) && page->title != NULL) { + lv_free(page->title); } + page->title = NULL; + page->static_title = false; } static void lv_menu_cont_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) @@ -575,14 +625,14 @@ static void lv_menu_cont_constructor(const lv_obj_class_t * class_p, lv_obj_t * LV_UNUSED(class_p); lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(obj, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICKABLE); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_CLICKABLE); } static void lv_menu_section_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { LV_UNUSED(class_p); lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICKABLE); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_CLICKABLE); } static void lv_menu_refr_sidebar_header_mode(lv_obj_t * obj) @@ -616,7 +666,7 @@ static void lv_menu_refr_sidebar_header_mode(lv_obj_t * obj) lv_obj_add_flag(menu->sidebar_header, LV_OBJ_FLAG_HIDDEN); } else { - lv_obj_clear_flag(menu->sidebar_header, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(menu->sidebar_header, LV_OBJ_FLAG_HIDDEN); } } @@ -652,13 +702,13 @@ static void lv_menu_refr_main_header_mode(lv_obj_t * obj) lv_obj_add_flag(menu->main_header, LV_OBJ_FLAG_HIDDEN); } else { - lv_obj_clear_flag(menu->main_header, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(menu->main_header, LV_OBJ_FLAG_HIDDEN); } } static void lv_menu_load_page_event_cb(lv_event_t * e) { - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_menu_load_page_event_data_t * event_data = lv_event_get_user_data(e); lv_menu_t * menu = (lv_menu_t *)(event_data->menu); lv_obj_t * page = event_data->page; @@ -680,7 +730,7 @@ static void lv_menu_load_page_event_cb(lv_event_t * e) if(sidebar) { /* Clear checked state of previous obj */ if(menu->selected_tab != obj && menu->selected_tab != NULL) { - lv_obj_clear_state(menu->selected_tab, LV_STATE_CHECKED); + lv_obj_remove_state(menu->selected_tab, LV_STATE_CHECKED); } lv_menu_clear_history((lv_obj_t *)menu); @@ -697,10 +747,10 @@ static void lv_menu_load_page_event_cb(lv_event_t * e) } } -static void lv_menu_obj_del_event_cb(lv_event_t * e) +static void lv_menu_obj_delete_event_cb(lv_event_t * e) { lv_menu_load_page_event_data_t * event_data = lv_event_get_user_data(e); - lv_mem_free(event_data); + lv_free(event_data); } static void lv_menu_back_event_cb(lv_event_t * e) @@ -708,14 +758,14 @@ static void lv_menu_back_event_cb(lv_event_t * e) lv_event_code_t code = lv_event_get_code(e); /* LV_EVENT_CLICKED */ if(code == LV_EVENT_CLICKED) { - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_menu_t * menu = (lv_menu_t *)lv_event_get_user_data(e); if(!(obj == menu->main_header_back_btn || obj == menu->sidebar_header_back_btn)) return; menu->prev_depth = menu->cur_depth; /* Save the previous value for user event handler */ - if(lv_menu_back_btn_is_root((lv_obj_t *)menu, obj)) return; + if(lv_menu_back_button_is_root((lv_obj_t *)menu, obj)) return; lv_ll_t * history_ll = &(menu->history_ll); @@ -729,7 +779,7 @@ static void lv_menu_back_event_cb(lv_event_t * e) /* Previous menu exists */ /* Delete the current item from the history */ _lv_ll_remove(history_ll, act_hist); - lv_mem_free(act_hist); + lv_free(act_hist); menu->cur_depth--; /* Create the previous menu. * Remove it from the history because `lv_menu_set_page` will add it again */ @@ -737,7 +787,7 @@ static void lv_menu_back_event_cb(lv_event_t * e) menu->cur_depth--; lv_menu_set_page(&(menu->obj), prev_hist->page); - lv_mem_free(prev_hist); + lv_free(prev_hist); } } } @@ -751,7 +801,7 @@ static void lv_menu_value_changed_event_cb(lv_event_t * e) if(main_page != NULL && menu->main_header_title != NULL) { if(main_page->title != NULL) { lv_label_set_text(menu->main_header_title, main_page->title); - lv_obj_clear_flag(menu->main_header_title, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(menu->main_header_title, LV_OBJ_FLAG_HIDDEN); } else { lv_obj_add_flag(menu->main_header_title, LV_OBJ_FLAG_HIDDEN); @@ -762,7 +812,7 @@ static void lv_menu_value_changed_event_cb(lv_event_t * e) if(sidebar_page != NULL && menu->sidebar_header_title != NULL) { if(sidebar_page->title != NULL) { lv_label_set_text(menu->sidebar_header_title, sidebar_page->title); - lv_obj_clear_flag(menu->sidebar_header_title, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(menu->sidebar_header_title, LV_OBJ_FLAG_HIDDEN); } else { lv_obj_add_flag(menu->sidebar_header_title, LV_OBJ_FLAG_HIDDEN); diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/menu/lv_menu.h b/lib/libesp32_lvgl/lvgl/src/widgets/menu/lv_menu.h new file mode 100644 index 000000000..c187ff134 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/menu/lv_menu.h @@ -0,0 +1,270 @@ +/** + * @file lv_menu.h + * + */ + +#ifndef LV_MENU_H +#define LV_MENU_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../core/lv_obj.h" + +#if LV_USE_MENU + +#if LV_USE_FLEX == 0 +#error "LV_USE_FLEX needs to be enabled" +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +enum _lv_menu_mode_header_t { + LV_MENU_HEADER_TOP_FIXED, /* Header is positioned at the top */ + LV_MENU_HEADER_TOP_UNFIXED, /* Header is positioned at the top and can be scrolled out of view*/ + LV_MENU_HEADER_BOTTOM_FIXED /* Header is positioned at the bottom */ +}; + +#ifdef DOXYGEN +typedef _lv_menu_mode_header_t lv_menu_mode_header_t; +#else +typedef uint8_t lv_menu_mode_header_t; +#endif /*DOXYGEN*/ + +enum _lv_menu_mode_root_back_button_t { + LV_MENU_ROOT_BACK_BUTTON_DISABLED, + LV_MENU_ROOT_BACK_BUTTON_ENABLED +}; + +#ifdef DOXYGEN +typedef _lv_menu_mode_root_back_button_t lv_menu_mode_root_back_button_t; +#else +typedef uint8_t lv_menu_mode_root_back_button_t; +#endif /*DOXYGEN*/ + +typedef struct /// @cond +/** + * Tells Doxygen to ignore a duplicate declaration + */ + lv_menu_load_page_event_data_t +/// @endcond +{ + lv_obj_t * menu; + lv_obj_t * page; +} lv_menu_load_page_event_data_t ; + +typedef struct { + lv_obj_t * page; +} lv_menu_history_t; + +typedef struct { + lv_obj_t obj; + lv_obj_t * storage; /* a pointer to obj that is the parent of all pages not displayed */ + lv_obj_t * main; + lv_obj_t * main_page; + lv_obj_t * main_header; + lv_obj_t * + main_header_back_btn; /* a pointer to obj that on click triggers back btn event handler, can be same as 'main_header' */ + lv_obj_t * main_header_title; + lv_obj_t * sidebar; + lv_obj_t * sidebar_page; + lv_obj_t * sidebar_header; + lv_obj_t * + sidebar_header_back_btn; /* a pointer to obj that on click triggers back btn event handler, can be same as 'sidebar_header' */ + lv_obj_t * sidebar_header_title; + lv_obj_t * selected_tab; + lv_ll_t history_ll; + uint8_t cur_depth; + uint8_t prev_depth; + uint8_t sidebar_generated : 1; + lv_menu_mode_header_t mode_header : 2; + lv_menu_mode_root_back_button_t mode_root_back_btn : 1; +} lv_menu_t; + +typedef struct { + lv_obj_t obj; + char * title; + bool static_title; +} lv_menu_page_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_menu_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_menu_page_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_menu_cont_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_menu_section_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_menu_separator_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_menu_sidebar_cont_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_menu_main_cont_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_menu_sidebar_header_cont_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_menu_main_header_cont_class; +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a menu object + * @param parent pointer to an object, it will be the parent of the new menu + * @return pointer to the created menu + */ +lv_obj_t * lv_menu_create(lv_obj_t * parent); + +/** + * Create a menu page object + * @param parent pointer to menu object + * @param title pointer to text for title in header (NULL to not display title) + * @return pointer to the created menu page + */ +lv_obj_t * lv_menu_page_create(lv_obj_t * parent, char const * const title); + +/** + * Create a menu cont object + * @param parent pointer to an object, it will be the parent of the new menu cont object + * @return pointer to the created menu cont + */ +lv_obj_t * lv_menu_cont_create(lv_obj_t * parent); + +/** + * Create a menu section object + * @param parent pointer to an object, it will be the parent of the new menu section object + * @return pointer to the created menu section + */ +lv_obj_t * lv_menu_section_create(lv_obj_t * parent); + +/** + * Create a menu separator object + * @param parent pointer to an object, it will be the parent of the new menu separator object + * @return pointer to the created menu separator + */ +lv_obj_t * lv_menu_separator_create(lv_obj_t * parent); +/*===================== + * Setter functions + *====================*/ +/** + * Set menu page to display in main + * @param obj pointer to the menu + * @param page pointer to the menu page to set (NULL to clear main and clear menu history) + */ +void lv_menu_set_page(lv_obj_t * obj, lv_obj_t * page); + +/** + * Set menu page title + * @param page pointer to the menu page + * @param title pointer to text for title in header (NULL to not display title) + */ +void lv_menu_set_page_title(lv_obj_t * page, char const * const title); + +/** + * Set menu page title with a static text. It will not be saved by the label so the 'text' variable + * has to be 'alive' while the page exists. + * @param page pointer to the menu page + * @param title pointer to text for title in header (NULL to not display title) + */ +void lv_menu_set_page_title_static(lv_obj_t * page, char const * const title); + +/** + * Set menu page to display in sidebar + * @param obj pointer to the menu + * @param page pointer to the menu page to set (NULL to clear sidebar) + */ +void lv_menu_set_sidebar_page(lv_obj_t * obj, lv_obj_t * page); + +/** + * Set the how the header should behave and its position + * @param obj pointer to a menu + * @param mode LV_MENU_HEADER_TOP_FIXED/TOP_UNFIXED/BOTTOM_FIXED + */ +void lv_menu_set_mode_header(lv_obj_t * obj, lv_menu_mode_header_t mode); + +/** + * Set whether back button should appear at root + * @param obj pointer to a menu + * @param mode LV_MENU_ROOT_BACK_BUTTON_DISABLED/ENABLED + */ +void lv_menu_set_mode_root_back_button(lv_obj_t * obj, lv_menu_mode_root_back_button_t mode); + +/** + * Add menu to the menu item + * @param menu pointer to the menu + * @param obj pointer to the obj + * @param page pointer to the page to load when obj is clicked + */ +void lv_menu_set_load_page_event(lv_obj_t * menu, lv_obj_t * obj, lv_obj_t * page); + +/*===================== + * Getter functions + *====================*/ +/** +* Get a pointer to menu page that is currently displayed in main +* @param obj pointer to the menu +* @return pointer to current page +*/ +lv_obj_t * lv_menu_get_cur_main_page(lv_obj_t * obj); + +/** +* Get a pointer to menu page that is currently displayed in sidebar +* @param obj pointer to the menu +* @return pointer to current page +*/ +lv_obj_t * lv_menu_get_cur_sidebar_page(lv_obj_t * obj); + +/** +* Get a pointer to main header obj +* @param obj pointer to the menu +* @return pointer to main header obj +*/ +lv_obj_t * lv_menu_get_main_header(lv_obj_t * obj); + +/** +* Get a pointer to main header back btn obj +* @param obj pointer to the menu +* @return pointer to main header back btn obj +*/ +lv_obj_t * lv_menu_get_main_header_back_button(lv_obj_t * obj); + +/** +* Get a pointer to sidebar header obj +* @param obj pointer to the menu +* @return pointer to sidebar header obj +*/ +lv_obj_t * lv_menu_get_sidebar_header(lv_obj_t * obj); + +/** +* Get a pointer to sidebar header obj +* @param obj pointer to the menu +* @return pointer to sidebar header back btn obj +*/ +lv_obj_t * lv_menu_get_sidebar_header_back_button(lv_obj_t * obj); + +/** + * Check if an obj is a root back btn + * @param menu pointer to the menu + * @param obj pointer to the back button + * @return true if it is a root back btn + */ +bool lv_menu_back_button_is_root(lv_obj_t * menu, lv_obj_t * obj); + +/** + * Clear menu history + * @param obj pointer to the menu + */ +void lv_menu_clear_history(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_MENU*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_MENU_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/msgbox/lv_msgbox.c b/lib/libesp32_lvgl/lvgl/src/widgets/msgbox/lv_msgbox.c new file mode 100644 index 000000000..b1cc16caf --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/msgbox/lv_msgbox.c @@ -0,0 +1,278 @@ +/** + * @file lv_msgbox.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_msgbox.h" +#if LV_USE_MSGBOX + +#include "../label/lv_label.h" +#include "../button/lv_button.h" +#include "../image/lv_image.h" +#include "../../misc/lv_assert.h" +#include "../../display/lv_display.h" +#include "../../layouts/flex/lv_flex.h" +#include "../../stdlib/lv_string.h" + +/********************* + * DEFINES + *********************/ +#define LV_MSGBOX_FLAG_AUTO_PARENT LV_OBJ_FLAG_WIDGET_1 /*Mark that the parent was automatically created*/ +#define MY_CLASS &lv_msgbox_class + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void msgbox_close_click_event_cb(lv_event_t * e); + +/********************** + * STATIC VARIABLES + **********************/ +const lv_obj_class_t lv_msgbox_class = { + .base_class = &lv_obj_class, + .width_def = LV_DPI_DEF * 2, + .height_def = LV_SIZE_CONTENT, + .instance_size = sizeof(lv_msgbox_t), + .name = "msgbox", +}; + +const lv_obj_class_t lv_msgbox_header_class = { + .base_class = &lv_obj_class, + .width_def = LV_PCT(100), + .height_def = LV_DPI_DEF / 3, + .instance_size = sizeof(lv_obj_t), + .name = "msgbox-header", +}; + +const lv_obj_class_t lv_msgbox_content_class = { + .base_class = &lv_obj_class, + .width_def = LV_PCT(100), + .height_def = LV_SIZE_CONTENT, + .instance_size = sizeof(lv_obj_t), + .name = "msgbox-content", +}; + +const lv_obj_class_t lv_msgbox_footer_class = { + .base_class = &lv_obj_class, + .width_def = LV_PCT(100), + .height_def = LV_DPI_DEF / 3, + .instance_size = sizeof(lv_obj_t), + .name = "msgbox-footer", +}; + +const lv_obj_class_t lv_msgbox_footer_button_class = { + .base_class = &lv_obj_class, + .width_def = LV_SIZE_CONTENT, + .height_def = LV_PCT(100), + .instance_size = sizeof(lv_obj_t), + .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, + .name = "msgbox-footer-button", +}; + +const lv_obj_class_t lv_msgbox_header_button_class = { + .base_class = &lv_obj_class, + .width_def = LV_DPI_DEF / 3, + .height_def = LV_PCT(100), + .instance_size = sizeof(lv_obj_t), + .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, + .name = "msgbox-header-button", +}; + +const lv_obj_class_t lv_msgbox_backdrop_class = { + .base_class = &lv_obj_class, + .width_def = LV_PCT(100), + .height_def = LV_PCT(100), + .instance_size = sizeof(lv_obj_t), + .name = "msgbox-backdrop", +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_msgbox_create(lv_obj_t * parent) +{ + LV_LOG_INFO("begin"); + bool auto_parent = false; + if(parent == NULL) { + auto_parent = true; + parent = lv_obj_class_create_obj(&lv_msgbox_backdrop_class, lv_layer_top()); + LV_ASSERT_MALLOC(parent); + lv_obj_class_init_obj(parent); + lv_obj_remove_flag(parent, LV_OBJ_FLAG_IGNORE_LAYOUT); + lv_obj_set_size(parent, LV_PCT(100), LV_PCT(100)); + } + + lv_obj_t * obj = lv_obj_class_create_obj(&lv_msgbox_class, parent); + LV_ASSERT_MALLOC(obj); + if(obj == NULL) return NULL; + lv_obj_class_init_obj(obj); + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN); + + if(auto_parent) lv_obj_add_flag(obj, LV_MSGBOX_FLAG_AUTO_PARENT); + + mbox->content = lv_obj_class_create_obj(&lv_msgbox_content_class, obj); + LV_ASSERT_MALLOC(obj); + if(mbox->content == NULL) return NULL; + lv_obj_class_init_obj(mbox->content); + lv_obj_set_flex_flow(mbox->content, LV_FLEX_FLOW_COLUMN); + + lv_obj_center(obj); + return obj; +} + +lv_obj_t * lv_msgbox_add_title(lv_obj_t * obj, const char * title) +{ + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + if(mbox->header == NULL) { + mbox->header = lv_obj_class_create_obj(&lv_msgbox_header_class, obj); + LV_ASSERT_MALLOC(obj); + if(mbox->header == NULL) return NULL; + lv_obj_class_init_obj(mbox->header); + + lv_obj_set_size(mbox->header, lv_pct(100), lv_display_get_dpi(lv_obj_get_display(obj)) / 3); + lv_obj_set_flex_flow(mbox->header, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(mbox->header, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + lv_obj_move_to_index(mbox->header, 0); + } + + if(mbox->title == NULL) { + mbox->title = lv_label_create(mbox->header); + lv_obj_set_flex_grow(mbox->title, 1); + } + + lv_label_set_text(mbox->title, title); + + return mbox->title; +} + +lv_obj_t * lv_msgbox_add_header_button(lv_obj_t * obj, const void * icon) +{ + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + if(mbox->header == NULL) { + lv_msgbox_add_title(obj, ""); /*Just to push the buttons to the right*/ + } + + lv_obj_t * btn = lv_obj_class_create_obj(&lv_msgbox_header_button_class, mbox->header); + LV_ASSERT_MALLOC(obj); + if(btn == NULL) return NULL; + lv_obj_class_init_obj(btn); + + if(icon) { + lv_obj_t * img = lv_image_create(btn); + lv_image_set_src(img, icon); + lv_obj_align(img, LV_ALIGN_CENTER, 0, 0); + } + + return btn; +} + +lv_obj_t * lv_msgbox_add_text(lv_obj_t * obj, const char * text) +{ + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + + lv_obj_t * label = lv_label_create(mbox->content); + lv_label_set_text(label, text); + lv_obj_set_width(label, lv_pct(100)); + + return label; +} + +lv_obj_t * lv_msgbox_add_footer_button(lv_obj_t * obj, const char * text) +{ + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + if(mbox->footer == NULL) { + mbox->footer = lv_obj_class_create_obj(&lv_msgbox_footer_class, obj); + LV_ASSERT_MALLOC(obj); + if(mbox->footer == NULL) return NULL; + lv_obj_class_init_obj(mbox->footer); + + lv_obj_set_flex_flow(mbox->footer, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(mbox->footer, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + } + + lv_obj_t * btn = lv_obj_class_create_obj(&lv_msgbox_footer_button_class, mbox->footer); + LV_ASSERT_MALLOC(obj); + if(btn == NULL) return NULL; + lv_obj_class_init_obj(btn); + + if(text) { + lv_obj_t * label = lv_label_create(btn); + lv_label_set_text(label, text); + lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); + } + + return btn; +} + +lv_obj_t * lv_msgbox_add_close_button(lv_obj_t * obj) +{ + lv_obj_t * btn = lv_msgbox_add_header_button(obj, LV_SYMBOL_CLOSE); + lv_obj_add_event_cb(btn, msgbox_close_click_event_cb, LV_EVENT_CLICKED, NULL); + return btn; +} + +lv_obj_t * lv_msgbox_get_header(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + return mbox->header; +} + +lv_obj_t * lv_msgbox_get_footer(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + return mbox->header; +} + +lv_obj_t * lv_msgbox_get_content(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + return mbox->content; +} + +lv_obj_t * lv_msgbox_get_title(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_msgbox_t * mbox = (lv_msgbox_t *)obj; + return mbox->title; +} + +void lv_msgbox_close(lv_obj_t * obj) +{ + if(lv_obj_has_flag(obj, LV_MSGBOX_FLAG_AUTO_PARENT)) lv_obj_delete(lv_obj_get_parent(obj)); + else lv_obj_delete(obj); +} + +void lv_msgbox_close_async(lv_obj_t * obj) +{ + if(lv_obj_has_flag(obj, LV_MSGBOX_FLAG_AUTO_PARENT)) lv_obj_delete_async(lv_obj_get_parent(obj)); + else lv_obj_delete_async(obj); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void msgbox_close_click_event_cb(lv_event_t * e) +{ + lv_obj_t * btn = lv_event_get_current_target(e); + lv_obj_t * mbox = lv_obj_get_parent(lv_obj_get_parent(btn)); + lv_msgbox_close(mbox); +} + +#endif /*LV_USE_MSGBOX*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/msgbox/lv_msgbox.h b/lib/libesp32_lvgl/lvgl/src/widgets/msgbox/lv_msgbox.h new file mode 100644 index 000000000..b7413ee7e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/msgbox/lv_msgbox.h @@ -0,0 +1,153 @@ +/** + * @file lv_mbox.h + * + */ + +#ifndef LV_MSGBOX_H +#define LV_MSGBOX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../core/lv_obj.h" + +#if LV_USE_MSGBOX + +/*Testing of dependencies*/ +#if LV_USE_BUTTONMATRIX == 0 +#error "lv_mbox: lv_btnm is required. Enable it in lv_conf.h (LV_USE_BUTTONMATRIX 1) " +#endif + +#if LV_USE_LABEL == 0 +#error "lv_mbox: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) " +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_obj_t obj; + lv_obj_t * header; + lv_obj_t * content; + lv_obj_t * footer; + lv_obj_t * title; +} lv_msgbox_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_msgbox_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_msgbox_header_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_msgbox_content_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_msgbox_footer_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_msgbox_header_button_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_msgbox_footer_button_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_msgbox_backdrop_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an empty message box + * @param parent the parent of the message box + * @return the created message box + */ +lv_obj_t * lv_msgbox_create(lv_obj_t * parent); + +/** + * Add title to the message box. It also creates a header for the title. + * @param obj pointer to a message box + * @param title the text of the tile + * @return the created title label + */ +lv_obj_t * lv_msgbox_add_title(lv_obj_t * obj, const char * title); + +/** + * Add a button to the header of to the message box. It also creates a header. + * @param obj pointer to a message box + * @param icon the icon of the button + * @return the created button + */ +lv_obj_t * lv_msgbox_add_header_button(lv_obj_t * obj, const void * icon); + +/** + * Add a text to the content area of message box. Multiply texts will be created below each other. + * @param obj pointer to a message box + * @param icon the icon of the button + * @return the created button + */ +lv_obj_t * lv_msgbox_add_text(lv_obj_t * obj, const char * text); + +/** + * Add a button to the footer of to the message box. It also creates a footer. + * @param obj pointer to a message box + * @param text the text of the button + * @return the created button + */ +lv_obj_t * lv_msgbox_add_footer_button(lv_obj_t * obj, const char * text); + +/** + * Add a close button to the message box. It also create a header. + * @param obj pointer to a message box + * @return the created close button + */ +lv_obj_t * lv_msgbox_add_close_button(lv_obj_t * obj); + +/** + * Get the header widget + * @param obj pointer to a message box + * @return the header, or NULL if not exists + */ +lv_obj_t * lv_msgbox_get_header(lv_obj_t * obj); + +/** + * Get the footer widget + * @param obj pointer to a message box + * @return the footer, or NULL if not exists + */ +lv_obj_t * lv_msgbox_get_footer(lv_obj_t * obj); + +/** + * Get the content widget + * @param obj pointer to a message box + * @return the content, or NULL if not exists + */ +lv_obj_t * lv_msgbox_get_content(lv_obj_t * obj); + +/** + * Get the title label + * @param obj pointer to a message box + * @return the title, or NULL if not exists + */ +lv_obj_t * lv_msgbox_get_title(lv_obj_t * obj); + +/** + * Close a message box + * @param obj pointer to a message box + */ +void lv_msgbox_close(lv_obj_t * mbox); + +/** + * Close a message box in the next call of the message box + * @param obj pointer to a message box + */ +void lv_msgbox_close_async(lv_obj_t * mbox); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_MSGBOX*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_MSGBOX_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_objx_templ.c b/lib/libesp32_lvgl/lvgl/src/widgets/objx_templ/lv_objx_templ.c similarity index 95% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_objx_templ.c rename to lib/libesp32_lvgl/lvgl/src/widgets/objx_templ/lv_objx_templ.c index 91565466a..7a3614a2b 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_objx_templ.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/objx_templ/lv_objx_templ.c @@ -47,7 +47,8 @@ const lv_obj_class_t lv_templ_class = { .instance_size = sizeof(lv_templ_t), .group_def = LV_OBJ_CLASS_GROUP_DEF_INHERIT, .editable = LV_OBJ_CLASS_EDITABLE_INHERIT, - .base_class = &lv_templ_class + .base_class = &lv_templ_class, + .name = "templ", }; /********************** @@ -124,11 +125,11 @@ static void lv_templ_event(const lv_obj_class_t * class_p, lv_event_t * e) { LV_UNUSED(class_p); - lv_res_t res; + lv_result_t res; /*Call the ancestor's event handler*/ - res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; + res = LV_EVENT_base(MY_CLASS, e); + if(res != LV_RESULT_OK) return; /*Add the widget specific event handling here*/ } diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_objx_templ.h b/lib/libesp32_lvgl/lvgl/src/widgets/objx_templ/lv_objx_templ.h similarity index 95% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_objx_templ.h rename to lib/libesp32_lvgl/lvgl/src/widgets/objx_templ/lv_objx_templ.h index 9de5285b5..ccf1e1c3e 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_objx_templ.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/objx_templ/lv_objx_templ.h @@ -39,7 +39,7 @@ typedef struct { /*New data for this type*/ } lv_templ_t; -extern const lv_obj_class_t lv_templ_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_templ_class; /********************** * GLOBAL PROTOTYPES diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.c b/lib/libesp32_lvgl/lvgl/src/widgets/roller/lv_roller.c similarity index 64% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.c rename to lib/libesp32_lvgl/lvgl/src/widgets/roller/lv_roller.c index f79e88274..146841de2 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/roller/lv_roller.c @@ -9,17 +9,20 @@ #include "lv_roller.h" #if LV_USE_ROLLER != 0 -#include "../misc/lv_assert.h" -#include "../draw/lv_draw.h" -#include "../core/lv_group.h" -#include "../core/lv_indev.h" -#include "../core/lv_indev_scroll.h" +#include "../../misc/lv_assert.h" +#include "../../draw/lv_draw.h" +#include "../../core/lv_group.h" +#include "../../indev/lv_indev.h" +#include "../../indev/lv_indev_scroll.h" +#include "../../indev/lv_indev_private.h" +#include "../../stdlib/lv_string.h" /********************* * DEFINES *********************/ #define MY_CLASS &lv_roller_class #define MY_CLASS_LABEL &lv_roller_label_class +#define EXTRA_INF_SIZE 1000 /*[px]: add the options multiple times until getting this height*/ /********************** * TYPEDEFS @@ -35,12 +38,13 @@ static void draw_main(lv_event_t * e); static void draw_label(lv_event_t * e); static void get_sel_area(lv_obj_t * obj, lv_area_t * sel_area); static void refr_position(lv_obj_t * obj, lv_anim_enable_t animen); -static lv_res_t release_handler(lv_obj_t * obj); +static lv_result_t release_handler(lv_obj_t * obj); static void inf_normalize(lv_obj_t * obj_scrl); static lv_obj_t * get_label(const lv_obj_t * obj); -static lv_coord_t get_selected_label_width(const lv_obj_t * obj); -static void scroll_anim_ready_cb(lv_anim_t * a); +static int32_t get_selected_label_width(const lv_obj_t * obj); +static void scroll_anim_completed_cb(lv_anim_t * a); static void set_y_anim(void * obj, int32_t v); +static void transform_vect_recursive(lv_obj_t * roller, lv_point_t * vect); /********************** * STATIC VARIABLES @@ -53,13 +57,15 @@ const lv_obj_class_t lv_roller_class = { .instance_size = sizeof(lv_roller_t), .editable = LV_OBJ_CLASS_EDITABLE_TRUE, .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, - .base_class = &lv_obj_class + .base_class = &lv_obj_class, + .name = "roller", }; const lv_obj_class_t lv_roller_label_class = { .event_cb = lv_roller_label_event, .instance_size = sizeof(lv_label_t), - .base_class = &lv_label_class + .base_class = &lv_label_class, + .name = "roller-label", }; /********************** @@ -70,11 +76,6 @@ const lv_obj_class_t lv_roller_label_class = { * GLOBAL FUNCTIONS **********************/ -/** - * Create a roller object - * @param parent pointer to an object, it will be the parent of the new roller - * @return pointer to the created roller - */ lv_obj_t * lv_roller_create(lv_obj_t * parent) { LV_LOG_INFO("begin"); @@ -87,12 +88,6 @@ lv_obj_t * lv_roller_create(lv_obj_t * parent) * Setter functions *====================*/ -/** - * Set the options on a roller - * @param roller pointer to roller object - * @param options a string with '\n' separated options. E.g. "One\nTwo\nThree" - * @param mode `LV_ROLLER_MODE_NORMAL` or `LV_ROLLER_MODE_INFINITE` - */ void lv_roller_set_options(lv_obj_t * obj, const char * options, lv_roller_mode_t mode) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -119,20 +114,26 @@ void lv_roller_set_options(lv_obj_t * obj, const char * options, lv_roller_mode_ else { roller->mode = LV_ROLLER_MODE_INFINITE; - size_t opt_len = strlen(options) + 1; /*+1 to add '\n' after option lists*/ - char * opt_extra = lv_mem_buf_get(opt_len * LV_ROLLER_INF_PAGES); - uint8_t i; - for(i = 0; i < LV_ROLLER_INF_PAGES; i++) { - strcpy(&opt_extra[opt_len * i], options); + const lv_font_t * font = lv_obj_get_style_text_font(obj, 0); + int32_t normal_h = roller->option_cnt * (lv_font_get_line_height(font) + lv_obj_get_style_text_letter_space(obj, 0)); + roller->inf_page_cnt = LV_CLAMP(3, EXTRA_INF_SIZE / normal_h, 15); + if(!(roller->inf_page_cnt & 1)) roller->inf_page_cnt++; /*Make it odd*/ + LV_LOG_INFO("Using %" LV_PRIu32 " pages to make the roller look infinite", roller->inf_page_cnt); + + size_t opt_len = lv_strlen(options) + 1; /*+1 to add '\n' after option lists*/ + char * opt_extra = lv_malloc(opt_len * roller->inf_page_cnt); + uint32_t i; + for(i = 0; i < roller->inf_page_cnt; i++) { + lv_strcpy(&opt_extra[opt_len * i], options); opt_extra[opt_len * (i + 1) - 1] = '\n'; } - opt_extra[opt_len * LV_ROLLER_INF_PAGES - 1] = '\0'; + opt_extra[opt_len * roller->inf_page_cnt - 1] = '\0'; lv_label_set_text(label, opt_extra); - lv_mem_buf_release(opt_extra); + lv_free(opt_extra); - roller->sel_opt_id = ((LV_ROLLER_INF_PAGES / 2) + 0) * roller->option_cnt; + roller->sel_opt_id = ((roller->inf_page_cnt / 2) + 0) * roller->option_cnt; - roller->option_cnt = roller->option_cnt * LV_ROLLER_INF_PAGES; + roller->option_cnt = roller->option_cnt * roller->inf_page_cnt; inf_normalize(obj); } @@ -143,13 +144,7 @@ void lv_roller_set_options(lv_obj_t * obj, const char * options, lv_roller_mode_ } -/** - * Set the selected option - * @param roller pointer to a roller object - * @param sel_opt id of the selected option (0 ... number of option - 1); - * @param anim_en LV_ANIM_ON: set with animation; LV_ANOM_OFF set immediately - */ -void lv_roller_set_selected(lv_obj_t * obj, uint16_t sel_opt, lv_anim_enable_t anim) +void lv_roller_set_selected(lv_obj_t * obj, uint32_t sel_opt, lv_anim_enable_t anim) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -161,15 +156,15 @@ void lv_roller_set_selected(lv_obj_t * obj, uint16_t sel_opt, lv_anim_enable_t a /*In infinite mode interpret the new ID relative to the currently visible "page"*/ if(roller->mode == LV_ROLLER_MODE_INFINITE) { - uint32_t real_option_cnt = roller->option_cnt / LV_ROLLER_INF_PAGES; - uint16_t current_page = roller->sel_opt_id / real_option_cnt; + uint32_t real_option_cnt = roller->option_cnt / roller->inf_page_cnt; + uint32_t current_page = roller->sel_opt_id / real_option_cnt; /*Set by the user to e.g. 0, 1, 2, 3... *Upscale the value to the current page*/ if(sel_opt < real_option_cnt) { - uint16_t act_opt = roller->sel_opt_id - current_page * real_option_cnt; + uint32_t act_opt = roller->sel_opt_id - current_page * real_option_cnt; int32_t sel_opt_signed = sel_opt; /*Huge jump? Probably from last to first or first to last option.*/ - if(LV_ABS((int16_t)act_opt - sel_opt) > real_option_cnt / 2) { + if((uint32_t)LV_ABS((int16_t)(act_opt - sel_opt)) > real_option_cnt / 2) { if(act_opt > sel_opt) sel_opt_signed += real_option_cnt; else sel_opt_signed -= real_option_cnt; } @@ -183,18 +178,13 @@ void lv_roller_set_selected(lv_obj_t * obj, uint16_t sel_opt, lv_anim_enable_t a refr_position(obj, anim); } -/** - * Set the height to show the given number of rows (options) - * @param roller pointer to a roller object - * @param row_cnt number of desired visible rows - */ -void lv_roller_set_visible_row_count(lv_obj_t * obj, uint8_t row_cnt) +void lv_roller_set_visible_row_count(lv_obj_t * obj, uint32_t row_cnt) { LV_ASSERT_OBJ(obj, MY_CLASS); const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + int32_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); lv_obj_set_height(obj, (lv_font_get_line_height(font) + line_space) * row_cnt + 2 * border_width); } @@ -202,18 +192,13 @@ void lv_roller_set_visible_row_count(lv_obj_t * obj, uint8_t row_cnt) * Getter functions *====================*/ -/** - * Get the id of the selected option - * @param roller pointer to a roller object - * @return id of the selected option (0 ... number of option - 1); - */ -uint16_t lv_roller_get_selected(const lv_obj_t * obj) +uint32_t lv_roller_get_selected(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_roller_t * roller = (lv_roller_t *)obj; if(roller->mode == LV_ROLLER_MODE_INFINITE) { - uint16_t real_id_cnt = roller->option_cnt / LV_ROLLER_INF_PAGES; + uint32_t real_id_cnt = roller->option_cnt / roller->inf_page_cnt; return roller->sel_opt_id % real_id_cnt; } else { @@ -221,12 +206,6 @@ uint16_t lv_roller_get_selected(const lv_obj_t * obj) } } -/** - * Get the current selected option as a string - * @param ddlist pointer to ddlist object - * @param buf pointer to an array to store the string - * @param buf_size size of `buf` in bytes. 0: to ignore it. - */ void lv_roller_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_size) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -234,9 +213,9 @@ void lv_roller_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_s lv_roller_t * roller = (lv_roller_t *)obj; lv_obj_t * label = get_label(obj); uint32_t i; - uint16_t line = 0; + uint32_t line = 0; const char * opt_txt = lv_label_get_text(label); - size_t txt_len = strlen(opt_txt); + size_t txt_len = lv_strlen(opt_txt); for(i = 0; i < txt_len && line != roller->sel_opt_id; i++) { if(opt_txt[i] == '\n') line++; @@ -245,7 +224,7 @@ void lv_roller_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_s uint32_t c; for(c = 0; i < txt_len && opt_txt[i] != '\n'; c++, i++) { if(buf_size && c >= buf_size - 1) { - LV_LOG_WARN("lv_dropdown_get_selected_str: the buffer was too small"); + LV_LOG_WARN("the buffer was too small"); break; } buf[c] = opt_txt[i]; @@ -254,7 +233,6 @@ void lv_roller_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_s buf[c] = '\0'; } - /** * Get the options of a roller * @param roller pointer to roller object @@ -267,19 +245,13 @@ const char * lv_roller_get_options(const lv_obj_t * obj) return lv_label_get_text(get_label(obj)); } - -/** - * Get the total number of options - * @param roller pointer to a roller object - * @return the total number of options - */ -uint16_t lv_roller_get_option_cnt(const lv_obj_t * obj) +uint32_t lv_roller_get_option_count(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_roller_t * roller = (lv_roller_t *)obj; if(roller->mode == LV_ROLLER_MODE_INFINITE) { - return roller->option_cnt / LV_ROLLER_INF_PAGES; + return roller->option_cnt / roller->inf_page_cnt; } else { return roller->option_cnt; @@ -290,7 +262,6 @@ uint16_t lv_roller_get_option_cnt(const lv_obj_t * obj) * STATIC FUNCTIONS **********************/ - static void lv_roller_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) { LV_UNUSED(class_p); @@ -301,29 +272,30 @@ static void lv_roller_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj roller->sel_opt_id = 0; roller->sel_opt_id_ori = 0; - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN_VER); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN_VER); LV_LOG_INFO("begin"); lv_obj_t * label = lv_obj_class_create_obj(&lv_roller_label_class, obj); lv_obj_class_init_obj(label); +#if LV_WIDGETS_HAS_DEFAULT_VALUE lv_roller_set_options(obj, "Option 1\nOption 2\nOption 3\nOption 4\nOption 5", LV_ROLLER_MODE_NORMAL); - - LV_LOG_TRACE("finshed"); +#endif + LV_LOG_TRACE("finished"); } static void lv_roller_event(const lv_obj_class_t * class_p, lv_event_t * e) { LV_UNUSED(class_p); - lv_res_t res; + lv_result_t res; /*Call the ancestor's event handler*/ res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + const lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_roller_t * roller = (lv_roller_t *)obj; if(code == LV_EVENT_GET_SELF_SIZE) { @@ -333,7 +305,7 @@ static void lv_roller_event(const lv_obj_class_t * class_p, lv_event_t * e) else if(code == LV_EVENT_STYLE_CHANGED) { lv_obj_t * label = get_label(obj); /*Be sure the label's style is updated before processing the roller*/ - if(label) lv_event_send(label, LV_EVENT_STYLE_CHANGED, NULL); + if(label) lv_obj_send_event(label, LV_EVENT_STYLE_CHANGED, NULL); lv_obj_refresh_self_size(obj); refr_position(obj, LV_ANIM_OFF); } @@ -342,12 +314,14 @@ static void lv_roller_event(const lv_obj_class_t * class_p, lv_event_t * e) } else if(code == LV_EVENT_PRESSED) { roller->moved = 0; - lv_anim_del(get_label(obj), set_y_anim); + lv_anim_delete(get_label(obj), set_y_anim); } else if(code == LV_EVENT_PRESSING) { - lv_indev_t * indev = lv_indev_get_act(); + lv_indev_t * indev = lv_indev_active(); lv_point_t p; lv_indev_get_vect(indev, &p); + + transform_vect_recursive(obj, &p); if(p.y) { lv_obj_t * label = get_label(obj); lv_obj_set_y(label, lv_obj_get_y(label) + p.y); @@ -359,26 +333,27 @@ static void lv_roller_event(const lv_obj_class_t * class_p, lv_event_t * e) } else if(code == LV_EVENT_FOCUSED) { lv_group_t * g = lv_obj_get_group(obj); - bool editing = lv_group_get_editing(g); - lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); + lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_active()); /*Encoders need special handling*/ if(indev_type == LV_INDEV_TYPE_ENCODER) { - /*In navigate mode revert the original value*/ - if(!editing) { + const bool editing = lv_group_get_editing(g); + + /*Save the current state when entered to edit mode*/ + if(editing) { + roller->sel_opt_id_ori = roller->sel_opt_id; + } + else { /*In navigate mode revert the original value*/ if(roller->sel_opt_id != roller->sel_opt_id_ori) { roller->sel_opt_id = roller->sel_opt_id_ori; refr_position(obj, LV_ANIM_ON); } } - /*Save the current state when entered to edit mode*/ - else { - roller->sel_opt_id_ori = roller->sel_opt_id; - } } else { - roller->sel_opt_id_ori = roller->sel_opt_id; /*Save the current value. Used to revert this state if - ENTER won't be pressed*/ + /*Save the current value. Used to revert this + *state if ENTER won't be pressed*/ + roller->sel_opt_id_ori = roller->sel_opt_id; } } else if(code == LV_EVENT_DEFOCUSED) { @@ -389,18 +364,17 @@ static void lv_roller_event(const lv_obj_class_t * class_p, lv_event_t * e) } } else if(code == LV_EVENT_KEY) { - char c = *((char *)lv_event_get_param(e)); + uint32_t c = lv_event_get_key(e); if(c == LV_KEY_RIGHT || c == LV_KEY_DOWN) { if(roller->sel_opt_id + 1 < roller->option_cnt) { - uint16_t ori_id = roller->sel_opt_id_ori; /*lv_roller_set_selected will overwrite this*/ + uint32_t ori_id = roller->sel_opt_id_ori; /*lv_roller_set_selected will overwrite this*/ lv_roller_set_selected(obj, roller->sel_opt_id + 1, LV_ANIM_ON); roller->sel_opt_id_ori = ori_id; } } else if(c == LV_KEY_LEFT || c == LV_KEY_UP) { if(roller->sel_opt_id > 0) { - uint16_t ori_id = roller->sel_opt_id_ori; /*lv_roller_set_selected will overwrite this*/ - + uint32_t ori_id = roller->sel_opt_id_ori; /*lv_roller_set_selected will overwrite this*/ lv_roller_set_selected(obj, roller->sel_opt_id - 1, LV_ANIM_ON); roller->sel_opt_id_ori = ori_id; } @@ -419,23 +393,23 @@ static void lv_roller_label_event(const lv_obj_class_t * class_p, lv_event_t * e { LV_UNUSED(class_p); - lv_res_t res; + lv_result_t res; lv_event_code_t code = lv_event_get_code(e); /*LV_EVENT_DRAW_MAIN will be called in the draw function*/ if(code != LV_EVENT_DRAW_MAIN) { /* Call the ancestor's event handler */ res = lv_obj_event_base(MY_CLASS_LABEL, e); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; } - lv_obj_t * label = lv_event_get_target(e); + lv_obj_t * label = lv_event_get_current_target(e); if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { /*If the selected text has a larger font it needs some extra space to draw it*/ - lv_coord_t * s = lv_event_get_param(e); + int32_t * s = lv_event_get_param(e); lv_obj_t * obj = lv_obj_get_parent(label); - lv_coord_t sel_w = get_selected_label_width(obj); - lv_coord_t label_w = lv_obj_get_width(label); + int32_t sel_w = get_selected_label_width(obj); + int32_t label_w = lv_obj_get_width(label); *s = LV_MAX(*s, sel_w - label_w); } else if(code == LV_EVENT_SIZE_CHANGED) { @@ -446,24 +420,23 @@ static void lv_roller_label_event(const lv_obj_class_t * class_p, lv_event_t * e } } - static void draw_main(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); if(code == LV_EVENT_DRAW_MAIN) { /*Draw the selected rectangle*/ - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); lv_area_t sel_area; get_sel_area(obj, &sel_area); lv_draw_rect_dsc_t sel_dsc; lv_draw_rect_dsc_init(&sel_dsc); lv_obj_init_draw_rect_dsc(obj, LV_PART_SELECTED, &sel_dsc); - lv_draw_rect(draw_ctx, &sel_dsc, &sel_area); + lv_draw_rect(layer, &sel_dsc, &sel_area); } /*Post draw when the children are drawn*/ else if(code == LV_EVENT_DRAW_POST) { - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); lv_draw_label_dsc_t label_dsc; lv_draw_label_dsc_init(&label_dsc); @@ -474,18 +447,17 @@ static void draw_main(lv_event_t * e) get_sel_area(obj, &sel_area); lv_area_t mask_sel; bool area_ok; - area_ok = _lv_area_intersect(&mask_sel, draw_ctx->clip_area, &sel_area); + area_ok = _lv_area_intersect(&mask_sel, &layer->_clip_area, &sel_area); if(area_ok) { lv_obj_t * label = get_label(obj); - if(lv_label_get_recolor(label)) label_dsc.flag |= LV_TEXT_FLAG_RECOLOR; /*Get the size of the "selected text"*/ lv_point_t res_p; - lv_txt_get_size(&res_p, lv_label_get_text(label), label_dsc.font, label_dsc.letter_space, label_dsc.line_space, - lv_obj_get_width(obj), LV_TEXT_FLAG_EXPAND); + lv_text_get_size(&res_p, lv_label_get_text(label), label_dsc.font, label_dsc.letter_space, label_dsc.line_space, + lv_obj_get_width(obj), LV_TEXT_FLAG_EXPAND); /*Move the selected label proportionally with the background label*/ - lv_coord_t roller_h = lv_obj_get_height(obj); + int32_t roller_h = lv_obj_get_height(obj); int32_t label_y_prop = label->coords.y1 - (roller_h / 2 + obj->coords.y1); /*label offset from the middle line of the roller*/ label_y_prop = (label_y_prop * 16384) / lv_obj_get_height( @@ -493,7 +465,7 @@ static void draw_main(lv_event_t * e) /*Apply a correction with different line heights*/ const lv_font_t * normal_label_font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t corr = (label_dsc.font->line_height - normal_label_font->line_height) / 2; + int32_t corr = (label_dsc.font->line_height - normal_label_font->line_height) / 2; /*Apply the proportional position to the selected text*/ res_p.y -= corr; @@ -501,9 +473,9 @@ static void draw_main(lv_event_t * e) label_sel_y += (label_y_prop * res_p.y) >> 14; label_sel_y -= corr; - lv_coord_t bwidth = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t pleft = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t pright = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + int32_t bwidth = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t pleft = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + int32_t pright = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); /*Draw the selected text*/ lv_area_t label_sel_area; @@ -513,10 +485,11 @@ static void draw_main(lv_event_t * e) label_sel_area.y2 = label_sel_area.y1 + res_p.y; label_dsc.flag |= LV_TEXT_FLAG_EXPAND; - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &mask_sel; - lv_draw_label(draw_ctx, &label_dsc, &label_sel_area, lv_label_get_text(label), NULL); - draw_ctx->clip_area = clip_area_ori; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = mask_sel; + label_dsc.text = lv_label_get_text(label); + lv_draw_label(layer, &label_dsc, &label_sel_area); + layer->_clip_area = clip_area_ori; } } } @@ -525,22 +498,21 @@ static void draw_label(lv_event_t * e) { /* Split the drawing of the label into an upper (above the selected area) * and a lower (below the selected area)*/ - lv_obj_t * label_obj = lv_event_get_target(e); + lv_obj_t * label_obj = lv_event_get_current_target(e); lv_obj_t * roller = lv_obj_get_parent(label_obj); lv_draw_label_dsc_t label_draw_dsc; lv_draw_label_dsc_init(&label_draw_dsc); lv_obj_init_draw_label_dsc(roller, LV_PART_MAIN, &label_draw_dsc); - if(lv_label_get_recolor(label_obj)) label_draw_dsc.flag |= LV_TEXT_FLAG_RECOLOR; - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); /*If the roller has shadow or outline it has some ext. draw size *therefore the label can overflow the roller's boundaries. *To solve this limit the clip area to the "plain" roller.*/ - const lv_area_t * clip_area_ori = draw_ctx->clip_area; + const lv_area_t clip_area_ori = layer->_clip_area; lv_area_t roller_clip_area; - if(!_lv_area_intersect(&roller_clip_area, draw_ctx->clip_area, &roller->coords)) return; - draw_ctx->clip_area = &roller_clip_area; + if(!_lv_area_intersect(&roller_clip_area, &layer->_clip_area, &roller->coords)) return; + layer->_clip_area = roller_clip_area; lv_area_t sel_area; get_sel_area(roller, &sel_area); @@ -550,25 +522,27 @@ static void draw_label(lv_event_t * e) clip2.y1 = label_obj->coords.y1; clip2.x2 = label_obj->coords.x2; clip2.y2 = sel_area.y1; - if(_lv_area_intersect(&clip2, draw_ctx->clip_area, &clip2)) { - const lv_area_t * clip_area_ori2 = draw_ctx->clip_area; - draw_ctx->clip_area = &clip2; - lv_draw_label(draw_ctx, &label_draw_dsc, &label_obj->coords, lv_label_get_text(label_obj), NULL); - draw_ctx->clip_area = clip_area_ori2; + if(_lv_area_intersect(&clip2, &layer->_clip_area, &clip2)) { + const lv_area_t clip_area_ori2 = layer->_clip_area; + layer->_clip_area = clip2; + label_draw_dsc.text = lv_label_get_text(label_obj); + lv_draw_label(layer, &label_draw_dsc, &label_obj->coords); + layer->_clip_area = clip_area_ori2; } clip2.x1 = label_obj->coords.x1; clip2.y1 = sel_area.y2; clip2.x2 = label_obj->coords.x2; clip2.y2 = label_obj->coords.y2; - if(_lv_area_intersect(&clip2, draw_ctx->clip_area, &clip2)) { - const lv_area_t * clip_area_ori2 = draw_ctx->clip_area; - draw_ctx->clip_area = &clip2; - lv_draw_label(draw_ctx, &label_draw_dsc, &label_obj->coords, lv_label_get_text(label_obj), NULL); - draw_ctx->clip_area = clip_area_ori2; + if(_lv_area_intersect(&clip2, &layer->_clip_area, &clip2)) { + const lv_area_t clip_area_ori2 = layer->_clip_area; + layer->_clip_area = clip2; + label_draw_dsc.text = lv_label_get_text(label_obj); + lv_draw_label(layer, &label_draw_dsc, &label_obj->coords); + layer->_clip_area = clip_area_ori2; } - draw_ctx->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } static void get_sel_area(lv_obj_t * obj, lv_area_t * sel_area) @@ -576,10 +550,10 @@ static void get_sel_area(lv_obj_t * obj, lv_area_t * sel_area) const lv_font_t * font_main = lv_obj_get_style_text_font(obj, LV_PART_MAIN); const lv_font_t * font_sel = lv_obj_get_style_text_font(obj, LV_PART_SELECTED); - lv_coord_t font_main_h = lv_font_get_line_height(font_main); - lv_coord_t font_sel_h = lv_font_get_line_height(font_sel); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - lv_coord_t d = (font_sel_h + font_main_h) / 2 + line_space; + int32_t font_main_h = lv_font_get_line_height(font_main); + int32_t font_sel_h = lv_font_get_line_height(font_sel); + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + int32_t d = (font_sel_h + font_main_h) / 2 + line_space; sel_area->y1 = obj->coords.y1 + lv_obj_get_height(obj) / 2 - d / 2; sel_area->y2 = sel_area->y1 + d; lv_area_t roller_coords; @@ -593,48 +567,53 @@ static void get_sel_area(lv_obj_t * obj, lv_area_t * sel_area) /** * Refresh the position of the roller. It uses the id stored in: roller->ddlist.selected_option_id * @param roller pointer to a roller object - * @param anim_en LV_ANIM_ON: refresh with animation; LV_ANOM_OFF: without animation + * @param anim_en LV_ANIM_ON: refresh with animation; LV_ANIM_OFF: without animation */ static void refr_position(lv_obj_t * obj, lv_anim_enable_t anim_en) { lv_obj_t * label = get_label(obj); if(label == NULL) return; - lv_text_align_t align = lv_obj_calculate_style_text_align(label, LV_PART_MAIN, lv_label_get_text(label)); + const lv_text_align_t align = lv_obj_calculate_style_text_align(label, LV_PART_MAIN, lv_label_get_text(label)); + int32_t x = 0; switch(align) { case LV_TEXT_ALIGN_CENTER: - lv_obj_set_x(label, (lv_obj_get_content_width(obj) - lv_obj_get_width(label)) / 2); + x = (lv_obj_get_content_width(obj) - lv_obj_get_width(label)) / 2; break; case LV_TEXT_ALIGN_RIGHT: - lv_obj_set_x(label, lv_obj_get_content_width(obj) - lv_obj_get_width(label)); + x = lv_obj_get_content_width(obj) - lv_obj_get_width(label); break; case LV_TEXT_ALIGN_LEFT: - lv_obj_set_x(label, 0); + x = 0; + break; + default: + /* Invalid alignment */ break; } + lv_obj_set_x(label, x); - lv_roller_t * roller = (lv_roller_t *)obj; const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - lv_coord_t font_h = lv_font_get_line_height(font); - lv_coord_t h = lv_obj_get_content_height(obj); - uint16_t anim_time = lv_obj_get_style_anim_time(obj, LV_PART_MAIN); + const int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + const int32_t font_h = lv_font_get_line_height(font); + const int32_t h = lv_obj_get_content_height(obj); + uint32_t anim_time = lv_obj_get_style_anim_duration(obj, LV_PART_MAIN); /*Normally the animation's `end_cb` sets correct position of the roller if infinite. - *But without animations do it manually*/ + *But without animations we have to do it manually*/ if(anim_en == LV_ANIM_OFF || anim_time == 0) { inf_normalize(obj); } + /* Calculate animation configuration */ + lv_roller_t * roller = (lv_roller_t *)obj; int32_t id = roller->sel_opt_id; - lv_coord_t sel_y1 = id * (font_h + line_space); - lv_coord_t mid_y1 = h / 2 - font_h / 2; - - lv_coord_t new_y = mid_y1 - sel_y1; + const int32_t sel_y1 = id * (font_h + line_space); + const int32_t mid_y1 = h / 2 - font_h / 2; + const int32_t new_y = mid_y1 - sel_y1; if(anim_en == LV_ANIM_OFF || anim_time == 0) { - lv_anim_del(label, set_y_anim); + lv_anim_delete(label, set_y_anim); lv_obj_set_y(label, new_y); } else { @@ -643,19 +622,19 @@ static void refr_position(lv_obj_t * obj, lv_anim_enable_t anim_en) lv_anim_set_var(&a, label); lv_anim_set_exec_cb(&a, set_y_anim); lv_anim_set_values(&a, lv_obj_get_y(label), new_y); - lv_anim_set_time(&a, anim_time); - lv_anim_set_ready_cb(&a, scroll_anim_ready_cb); + lv_anim_set_duration(&a, anim_time); + lv_anim_set_completed_cb(&a, scroll_anim_completed_cb); lv_anim_set_path_cb(&a, lv_anim_path_ease_out); lv_anim_start(&a); } } -static lv_res_t release_handler(lv_obj_t * obj) +static lv_result_t release_handler(lv_obj_t * obj) { lv_obj_t * label = get_label(obj); - if(label == NULL) return LV_RES_OK; + if(label == NULL) return LV_RESULT_OK; - lv_indev_t * indev = lv_indev_get_act(); + lv_indev_t * indev = lv_indev_active(); lv_roller_t * roller = (lv_roller_t *)obj; /*Leave edit mode once a new option is selected*/ @@ -681,7 +660,7 @@ static lv_res_t release_handler(lv_obj_t * obj) p.y -= label->coords.y1; p.x -= label->coords.x1; uint32_t letter_i; - letter_i = lv_label_get_letter_on(label, &p); + letter_i = lv_label_get_letter_on(label, &p, true); const char * txt = lv_label_get_text(label); uint32_t i = 0; @@ -689,7 +668,7 @@ static lv_res_t release_handler(lv_obj_t * obj) uint32_t letter_cnt = 0; for(letter_cnt = 0; letter_cnt < letter_i; letter_cnt++) { - uint32_t letter = _lv_txt_encoded_next(txt, &i); + uint32_t letter = _lv_text_encoded_next(txt, &i); /*Count he lines to reach the clicked letter. But ignore the last '\n' because it * still belongs to the clicked line*/ if(letter == '\n' && i_prev != letter_i) new_opt++; @@ -699,16 +678,28 @@ static lv_res_t release_handler(lv_obj_t * obj) else { /*If dragged then align the list to have an element in the middle*/ const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - lv_coord_t font_h = lv_font_get_line_height(font); + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + int32_t font_h = lv_font_get_line_height(font); - lv_coord_t label_unit = font_h + line_space; - lv_coord_t mid = obj->coords.y1 + (obj->coords.y2 - obj->coords.y1) / 2; - lv_coord_t label_y1 = label->coords.y1 + lv_indev_scroll_throw_predict(indev, LV_DIR_VER); + int32_t label_unit = font_h + line_space; + int32_t mid = obj->coords.y1 + (obj->coords.y2 - obj->coords.y1) / 2; + + lv_point_t p = indev->pointer.scroll_throw_vect_ori; + transform_vect_recursive(obj, &p); + + int32_t scroll_throw = indev->scroll_throw; + int32_t sum = 0; + int32_t v = p.y; + while(v) { + sum += v; + v = v * (100 - scroll_throw) / 100; + } + + int32_t label_y1 = label->coords.y1 + sum; int32_t id = (mid - label_y1) / label_unit; if(id < 0) id = 0; - if(id >= roller->option_cnt) id = roller->option_cnt - 1; + if(id >= (int32_t)roller->option_cnt) id = roller->option_cnt - 1; new_opt = id; } @@ -719,7 +710,7 @@ static lv_res_t release_handler(lv_obj_t * obj) } uint32_t id = roller->sel_opt_id; /*Just to use uint32_t in event data*/ - lv_res_t res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &id); + lv_result_t res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, &id); return res; } @@ -732,25 +723,24 @@ static void inf_normalize(lv_obj_t * obj) lv_roller_t * roller = (lv_roller_t *)obj; if(roller->mode == LV_ROLLER_MODE_INFINITE) { - uint16_t real_id_cnt = roller->option_cnt / LV_ROLLER_INF_PAGES; + uint32_t real_id_cnt = roller->option_cnt / roller->inf_page_cnt; roller->sel_opt_id = roller->sel_opt_id % real_id_cnt; - roller->sel_opt_id += (LV_ROLLER_INF_PAGES / 2) * real_id_cnt; /*Select the middle page*/ + roller->sel_opt_id += (roller->inf_page_cnt / 2) * real_id_cnt; /*Select the middle page*/ roller->sel_opt_id_ori = roller->sel_opt_id % real_id_cnt; - roller->sel_opt_id_ori += (LV_ROLLER_INF_PAGES / 2) * real_id_cnt; /*Select the middle page*/ + roller->sel_opt_id_ori += (roller->inf_page_cnt / 2) * real_id_cnt; /*Select the middle page*/ /*Move to the new id*/ const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - lv_coord_t font_h = lv_font_get_line_height(font); - lv_coord_t h = lv_obj_get_content_height(obj); + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + int32_t font_h = lv_font_get_line_height(font); + int32_t h = lv_obj_get_content_height(obj); lv_obj_t * label = get_label(obj); - - lv_coord_t sel_y1 = roller->sel_opt_id * (font_h + line_space); - lv_coord_t mid_y1 = h / 2 - font_h / 2; - lv_coord_t new_y = mid_y1 - sel_y1; + int32_t sel_y1 = roller->sel_opt_id * (font_h + line_space); + int32_t mid_y1 = h / 2 - font_h / 2; + int32_t new_y = mid_y1 - sel_y1; lv_obj_set_y(label, new_y); } } @@ -760,30 +750,49 @@ static lv_obj_t * get_label(const lv_obj_t * obj) return lv_obj_get_child(obj, 0); } - -static lv_coord_t get_selected_label_width(const lv_obj_t * obj) +static int32_t get_selected_label_width(const lv_obj_t * obj) { lv_obj_t * label = get_label(obj); if(label == NULL) return 0; const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_SELECTED); - lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_SELECTED); + int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_SELECTED); const char * txt = lv_label_get_text(label); lv_point_t size; - lv_txt_get_size(&size, txt, font, letter_space, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + lv_text_get_size(&size, txt, font, letter_space, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); return size.x; } -static void scroll_anim_ready_cb(lv_anim_t * a) +static void scroll_anim_completed_cb(lv_anim_t * a) { lv_obj_t * obj = lv_obj_get_parent(a->var); /*The label is animated*/ inf_normalize(obj); } - static void set_y_anim(void * obj, int32_t v) { lv_obj_set_y(obj, v); } +static void transform_vect_recursive(lv_obj_t * roller, lv_point_t * vect) +{ + int16_t angle = 0; + int32_t scale_x = 256; + int32_t scale_y = 256; + lv_obj_t * parent = roller; + while(parent) { + angle += lv_obj_get_style_transform_rotation(parent, 0); + int32_t zoom_act_x = lv_obj_get_style_transform_scale_x_safe(parent, 0); + int32_t zoom_act_y = lv_obj_get_style_transform_scale_y_safe(parent, 0); + scale_x = (scale_y * zoom_act_x) >> 8; + scale_y = (scale_y * zoom_act_y) >> 8; + parent = lv_obj_get_parent(parent); + } + lv_point_t pivot = { 0, 0 }; + + scale_x = 256 * 256 / scale_x; + scale_y = 256 * 256 / scale_y; + lv_point_transform(vect, -angle, scale_x, scale_y, &pivot, false); +} + #endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.h b/lib/libesp32_lvgl/lvgl/src/widgets/roller/lv_roller.h similarity index 77% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.h rename to lib/libesp32_lvgl/lvgl/src/widgets/roller/lv_roller.h index 14411dea6..960994886 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_roller.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/roller/lv_roller.h @@ -13,7 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../lv_conf_internal.h" +#include "../../core/lv_obj.h" #if LV_USE_ROLLER != 0 @@ -22,8 +22,7 @@ extern "C" { #error "lv_roller: lv_label is required. Enable it in lv_conf.h (LV_USE_ROLLER 1)" #endif -#include "../core/lv_obj.h" -#include "lv_label.h" +#include "../label/lv_label.h" /********************* * DEFINES @@ -34,24 +33,28 @@ extern "C" { **********************/ /** Roller mode.*/ -enum { +enum _lv_roller_mode_t { LV_ROLLER_MODE_NORMAL, /**< Normal mode (roller ends at the end of the options).*/ LV_ROLLER_MODE_INFINITE, /**< Infinite mode (roller can be scrolled forever).*/ }; +#ifdef DOXYGEN +typedef _lv_roller_mode_t lv_roller_mode_t; +#else typedef uint8_t lv_roller_mode_t; +#endif /*DOXYGEN*/ typedef struct { lv_obj_t obj; - uint16_t option_cnt; /**< Number of options*/ - uint16_t sel_opt_id; /**< Index of the current option*/ - uint16_t sel_opt_id_ori; /**< Store the original index on focus*/ + uint32_t option_cnt; /**< Number of options*/ + uint32_t sel_opt_id; /**< Index of the current option*/ + uint32_t sel_opt_id_ori; /**< Store the original index on focus*/ + uint32_t inf_page_cnt; /**< Number of extra pages added to make the roller look infinite */ lv_roller_mode_t mode : 1; uint32_t moved : 1; } lv_roller_t; -extern const lv_obj_class_t lv_roller_class; - +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_roller_class; /********************** * GLOBAL PROTOTYPES @@ -80,16 +83,16 @@ void lv_roller_set_options(lv_obj_t * obj, const char * options, lv_roller_mode_ * Set the selected option * @param obj pointer to a roller object * @param sel_opt index of the selected option (0 ... number of option - 1); - * @param anim_en LV_ANIM_ON: set with animation; LV_ANOM_OFF set immediately + * @param anim LV_ANIM_ON: set with animation; LV_ANOM_OFF set immediately */ -void lv_roller_set_selected(lv_obj_t * obj, uint16_t sel_opt, lv_anim_enable_t anim); +void lv_roller_set_selected(lv_obj_t * obj, uint32_t sel_opt, lv_anim_enable_t anim); /** * Set the height to show the given number of rows (options) * @param obj pointer to a roller object * @param row_cnt number of desired visible rows */ -void lv_roller_set_visible_row_count(lv_obj_t * obj, uint8_t row_cnt); +void lv_roller_set_visible_row_count(lv_obj_t * obj, uint32_t row_cnt); /*===================== * Getter functions @@ -100,7 +103,7 @@ void lv_roller_set_visible_row_count(lv_obj_t * obj, uint8_t row_cnt); * @param obj pointer to a roller object * @return index of the selected option (0 ... number of option - 1); */ -uint16_t lv_roller_get_selected(const lv_obj_t * obj); +uint32_t lv_roller_get_selected(const lv_obj_t * obj); /** * Get the current selected option as a string. @@ -110,7 +113,6 @@ uint16_t lv_roller_get_selected(const lv_obj_t * obj); */ void lv_roller_get_selected_str(const lv_obj_t * obj, char * buf, uint32_t buf_size); - /** * Get the options of a roller * @param obj pointer to roller object @@ -123,7 +125,7 @@ const char * lv_roller_get_options(const lv_obj_t * obj); * @param obj pointer to a roller object * @return the total number of options */ -uint16_t lv_roller_get_option_cnt(const lv_obj_t * obj); +uint32_t lv_roller_get_option_count(const lv_obj_t * obj); /********************** * MACROS diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/scale/lv_scale.c b/lib/libesp32_lvgl/lvgl/src/widgets/scale/lv_scale.c new file mode 100644 index 000000000..cee6ba11f --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/scale/lv_scale.c @@ -0,0 +1,1444 @@ +/** + * @file lv_scale.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_scale.h" +#if LV_USE_SCALE != 0 + +#include "../../core/lv_group.h" +#include "../../misc/lv_assert.h" +#include "../../misc/lv_math.h" +#include "../../draw/lv_draw_arc.h" + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_scale_class + +#define LV_SCALE_LABEL_TXT_LEN (20U) +#define LV_SCALE_DEFAULT_ANGLE_RANGE ((uint32_t) 270U) +#define LV_SCALE_DEFAULT_ROTATION ((int32_t) 135U) +#define LV_SCALE_TICK_IDX_DEFAULT_ID ((uint32_t) 255U) +#define LV_SCALE_DEFAULT_LABEL_GAP ((uint32_t) 15U) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void lv_scale_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_scale_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_scale_event(const lv_obj_class_t * class_p, lv_event_t * event); + +static void scale_draw_main(lv_obj_t * obj, lv_event_t * event); +static void scale_draw_indicator(lv_obj_t * obj, lv_event_t * event); + +static void scale_get_center(const lv_obj_t * obj, lv_point_t * center, int32_t * arc_r); +static void scale_get_tick_points(lv_obj_t * obj, const uint32_t tick_idx, bool is_major_tick, + lv_point_t * tick_point_a, lv_point_t * tick_point_b); +static void scale_get_label_coords(lv_obj_t * obj, lv_draw_label_dsc_t * label_dsc, lv_point_t * tick_point, + lv_area_t * label_coords); +static void scale_set_indicator_label_properties(lv_obj_t * obj, lv_draw_label_dsc_t * label_dsc, + lv_style_t * indicator_section_style); +static void scale_set_line_properties(lv_obj_t * obj, lv_draw_line_dsc_t * line_dsc, lv_style_t * section_style, + uint32_t part); +static void scale_set_arc_properties(lv_obj_t * obj, lv_draw_arc_dsc_t * arc_dsc, lv_style_t * section_style); +/* Helpers */ +static void scale_find_section_tick_idx(lv_obj_t * obj); +static void scale_store_main_line_tick_width_compensation(lv_obj_t * obj, const uint32_t tick_idx, + const bool is_major_tick, const int32_t major_tick_width, const int32_t minor_tick_width); +static void scale_store_section_line_tick_width_compensation(lv_obj_t * obj, const bool is_major_tick, + lv_draw_label_dsc_t * label_dsc, lv_draw_line_dsc_t * major_tick_dsc, lv_draw_line_dsc_t * minor_tick_dsc, + const int32_t tick_value, const uint8_t tick_idx, lv_point_t * tick_point_a); +static void scale_build_custom_label_text(lv_obj_t * obj, lv_draw_label_dsc_t * label_dsc, + const uint16_t major_tick_idx); + +/********************** + * STATIC VARIABLES + **********************/ + +const lv_obj_class_t lv_scale_class = { + .constructor_cb = lv_scale_constructor, + .destructor_cb = lv_scale_destructor, + .event_cb = lv_scale_event, + .instance_size = sizeof(lv_scale_t), + .editable = LV_OBJ_CLASS_EDITABLE_TRUE, + .base_class = &lv_obj_class, + .name = "scale", +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_scale_create(lv_obj_t * parent) +{ + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + return obj; +} + +/*====================== + * Add/remove functions + *=====================*/ + +/* + * New object specific "add" or "remove" functions come here + */ + +/*===================== + * Setter functions + *====================*/ + +void lv_scale_set_mode(lv_obj_t * obj, lv_scale_mode_t mode) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_scale_t * scale = (lv_scale_t *)obj; + + scale->mode = mode; + + lv_obj_invalidate(obj); +} + +void lv_scale_set_total_tick_count(lv_obj_t * obj, uint32_t total_tick_count) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_scale_t * scale = (lv_scale_t *)obj; + + scale->total_tick_count = total_tick_count; + + lv_obj_invalidate(obj); +} + +void lv_scale_set_major_tick_every(lv_obj_t * obj, uint32_t major_tick_every) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_scale_t * scale = (lv_scale_t *)obj; + + scale->major_tick_every = major_tick_every; + + lv_obj_invalidate(obj); +} + +void lv_scale_set_label_show(lv_obj_t * obj, bool show_label) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_scale_t * scale = (lv_scale_t *)obj; + + scale->label_enabled = show_label; + + lv_obj_invalidate(obj); +} + +void lv_scale_set_range(lv_obj_t * obj, int32_t min, int32_t max) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_scale_t * scale = (lv_scale_t *)obj; + + scale->range_min = min; + scale->range_max = max; + + lv_obj_invalidate(obj); +} + +void lv_scale_set_angle_range(lv_obj_t * obj, uint32_t angle_range) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_scale_t * scale = (lv_scale_t *)obj; + + scale->angle_range = angle_range; + + lv_obj_invalidate(obj); +} + +void lv_scale_set_rotation(lv_obj_t * obj, int32_t rotation) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_scale_t * scale = (lv_scale_t *)obj; + + scale->rotation = rotation; + + lv_obj_invalidate(obj); +} + +void lv_scale_set_line_needle_value(lv_obj_t * obj, lv_obj_t * needle_line, int32_t needle_length, + int32_t value) +{ + int32_t angle; + int32_t scale_width, scale_height; + int32_t actual_needle_length; + int32_t needle_length_x, needle_length_y; + static lv_point_precise_t needle_line_points[2]; + + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_scale_t * scale = (lv_scale_t *)obj; + if((scale->mode != LV_SCALE_MODE_ROUND_INNER) && + (scale->mode != LV_SCALE_MODE_ROUND_OUTER)) { + return; + } + + lv_obj_align(needle_line, LV_ALIGN_TOP_LEFT, 0, 0); + + scale_width = lv_obj_get_style_width(obj, LV_PART_MAIN); + scale_height = lv_obj_get_style_height(obj, LV_PART_MAIN); + + if(scale_width != scale_height) { + return; + } + + if(needle_length >= scale_width / 2) { + actual_needle_length = scale_width / 2; + } + else if(needle_length >= 0) { + actual_needle_length = needle_length; + } + else if(needle_length + scale_width / 2 < 0) { + actual_needle_length = 0; + } + else { + actual_needle_length = scale_width / 2 + needle_length; + } + + if(value < scale->range_min) { + angle = 0; + } + else if(value > scale->range_max) { + angle = scale->angle_range; + } + else { + angle = scale->angle_range * (value - scale->range_min) / (scale->range_max - scale->range_min); + } + + needle_length_x = (actual_needle_length * lv_trigo_cos(scale->rotation + angle)) >> LV_TRIGO_SHIFT; + needle_length_y = (actual_needle_length * lv_trigo_sin(scale->rotation + angle)) >> LV_TRIGO_SHIFT; + + needle_line_points[0].x = scale_width / 2; + needle_line_points[0].y = scale_height / 2; + needle_line_points[1].x = scale_width / 2 + needle_length_x; + needle_line_points[1].y = scale_height / 2 + needle_length_y; + + lv_line_set_points(needle_line, needle_line_points, 2); +} + +void lv_scale_set_image_needle_value(lv_obj_t * obj, lv_obj_t * needle_img, int32_t value) +{ + int32_t angle; + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_scale_t * scale = (lv_scale_t *)obj; + if((scale->mode != LV_SCALE_MODE_ROUND_INNER) && + (scale->mode != LV_SCALE_MODE_ROUND_OUTER)) { + return; + } + + if(value < scale->range_min) { + angle = 0; + } + else if(value > scale->range_max) { + angle = scale->angle_range; + } + else { + angle = scale->angle_range * (value - scale->range_min) / (scale->range_max - scale->range_min); + } + + lv_image_set_rotation(needle_img, (scale->rotation + angle) * 10); +} + +void lv_scale_set_text_src(lv_obj_t * obj, const char * txt_src[]) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_scale_t * scale = (lv_scale_t *)obj; + + scale->txt_src = txt_src; + scale->custom_label_cnt = 0; + if(scale->txt_src) { + int32_t idx; + for(idx = 0; txt_src[idx]; ++idx) { + scale->custom_label_cnt++; + } + } + + lv_obj_invalidate(obj); +} + +void lv_scale_set_post_draw(lv_obj_t * obj, bool en) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_scale_t * scale = (lv_scale_t *)obj; + + scale->post_draw = en; + + lv_obj_invalidate(obj); +} + +lv_scale_section_t * lv_scale_add_section(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_scale_t * scale = (lv_scale_t *)obj; + lv_scale_section_t * section = _lv_ll_ins_head(&scale->section_ll); + LV_ASSERT_MALLOC(section); + if(section == NULL) return NULL; + + /* Section default values */ + section->main_style = NULL; + section->indicator_style = NULL; + section->items_style = NULL; + section->minor_range = 0U; + section->major_range = 0U; + section->first_tick_idx_in_section = LV_SCALE_TICK_IDX_DEFAULT_ID; + section->last_tick_idx_in_section = LV_SCALE_TICK_IDX_DEFAULT_ID; + section->first_tick_idx_is_major = 0U; + section->last_tick_idx_is_major = 0U; + section->first_tick_in_section_width = 0U; + section->last_tick_in_section_width = 0U; + + return section; +} + +void lv_scale_section_set_range(lv_scale_section_t * section, int32_t minor_range, int32_t major_range) +{ + if(NULL == section) return; + + section->minor_range = minor_range; + section->major_range = major_range; +} + +void lv_scale_section_set_style(lv_scale_section_t * section, uint32_t part, lv_style_t * section_part_style) +{ + if(NULL == section) return; + + switch(part) { + case LV_PART_MAIN: + section->main_style = section_part_style; + break; + case LV_PART_INDICATOR: + section->indicator_style = section_part_style; + break; + case LV_PART_ITEMS: + section->items_style = section_part_style; + break; + default: + /* Invalid part */ + break; + } +} + +/*===================== + * Getter functions + *====================*/ + +lv_scale_mode_t lv_scale_get_mode(lv_obj_t * obj) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + return scale->mode; +} + +int32_t lv_scale_get_total_tick_count(lv_obj_t * obj) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + return scale->total_tick_count; +} + +int32_t lv_scale_get_major_tick_every(lv_obj_t * obj) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + return scale->major_tick_every; +} + +bool lv_scale_get_label_show(lv_obj_t * obj) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + return scale->label_enabled; +} + +uint32_t lv_scale_get_angle_range(lv_obj_t * obj) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + return scale->angle_range; +} + +int32_t lv_scale_get_range_min_value(lv_obj_t * obj) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + return scale->range_min; +} + +int32_t lv_scale_get_range_max_value(lv_obj_t * obj) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + return scale->range_max; +} + +/*===================== + * Other functions + *====================*/ + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_scale_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + LV_TRACE_OBJ_CREATE("begin"); + + lv_scale_t * scale = (lv_scale_t *)obj; + + _lv_ll_init(&scale->section_ll, sizeof(lv_scale_section_t)); + + scale->total_tick_count = LV_SCALE_TOTAL_TICK_COUNT_DEFAULT; + scale->major_tick_every = LV_SCALE_MAJOR_TICK_EVERY_DEFAULT; + scale->mode = LV_SCALE_MODE_HORIZONTAL_BOTTOM; + scale->label_enabled = LV_SCALE_LABEL_ENABLED_DEFAULT; + scale->angle_range = LV_SCALE_DEFAULT_ANGLE_RANGE; + scale->rotation = LV_SCALE_DEFAULT_ROTATION; + scale->range_min = 0U; + scale->range_max = 100U; + scale->last_tick_width = 0U; + scale->first_tick_width = 0U; + scale->post_draw = false; + scale->custom_label_cnt = 0U; + scale->txt_src = NULL; + + LV_TRACE_OBJ_CREATE("finished"); +} + +static void lv_scale_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + LV_TRACE_OBJ_CREATE("begin"); + + lv_scale_t * scale = (lv_scale_t *)obj; + lv_scale_section_t * section; + while(scale->section_ll.head) { + section = _lv_ll_get_head(&scale->section_ll); + _lv_ll_remove(&scale->section_ll, section); + lv_free(section); + } + _lv_ll_clear(&scale->section_ll); + + LV_TRACE_OBJ_CREATE("finished"); +} + +static void lv_scale_event(const lv_obj_class_t * class_p, lv_event_t * event) +{ + LV_UNUSED(class_p); + + /*Call the ancestor's event handler*/ + lv_result_t res = lv_obj_event_base(MY_CLASS, event); + if(res != LV_RESULT_OK) return; + + lv_event_code_t event_code = lv_event_get_code(event); + lv_obj_t * obj = lv_event_get_current_target(event); + lv_scale_t * scale = (lv_scale_t *) obj; + LV_UNUSED(scale); + + if(event_code == LV_EVENT_DRAW_MAIN) { + if(scale->post_draw == false) { + scale_find_section_tick_idx(obj); + scale_draw_indicator(obj, event); + scale_draw_main(obj, event); + } + } + if(event_code == LV_EVENT_DRAW_POST) { + if(scale->post_draw == true) { + scale_find_section_tick_idx(obj); + scale_draw_indicator(obj, event); + scale_draw_main(obj, event); + } + } + else if(event_code == LV_EVENT_REFR_EXT_DRAW_SIZE) { + /* NOTE: Extend scale draw size so the first tick label can be shown */ + lv_event_set_ext_draw_size(event, 100); + } + else { + /* Nothing to do. Invalid event */ + } +} + +static void scale_draw_indicator(lv_obj_t * obj, lv_event_t * event) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + lv_layer_t * layer = lv_event_get_layer(event); + + if(scale->total_tick_count <= 1) return; + + lv_draw_label_dsc_t label_dsc; + lv_draw_label_dsc_init(&label_dsc); + /* Formatting the labels with the configured style for LV_PART_INDICATOR */ + lv_obj_init_draw_label_dsc(obj, LV_PART_INDICATOR, &label_dsc); + + /* Major tick style */ + lv_draw_line_dsc_t major_tick_dsc; + lv_draw_line_dsc_init(&major_tick_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_INDICATOR, &major_tick_dsc); + + /* Configure line draw descriptor for the minor tick drawing */ + lv_draw_line_dsc_t minor_tick_dsc; + lv_draw_line_dsc_init(&minor_tick_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_ITEMS, &minor_tick_dsc); + + /* Main line style */ + lv_draw_line_dsc_t main_line_dsc; + lv_draw_line_dsc_init(&main_line_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_MAIN, &main_line_dsc); + + const int32_t major_len = lv_obj_get_style_length(obj, LV_PART_INDICATOR); + + if((LV_SCALE_MODE_VERTICAL_LEFT == scale->mode || LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) + || (LV_SCALE_MODE_HORIZONTAL_BOTTOM == scale->mode || LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode)) { + + uint32_t total_tick_count = scale->total_tick_count; + uint32_t tick_idx = 0; + uint32_t major_tick_idx = 0; + for(tick_idx = 0; tick_idx < total_tick_count; tick_idx++) { + /* A major tick is the one which has a label in it */ + bool is_major_tick = false; + if(tick_idx % scale->major_tick_every == 0) is_major_tick = true; + if(is_major_tick) major_tick_idx++; + + const int32_t tick_value = lv_map(tick_idx, 0U, total_tick_count - 1, scale->range_min, scale->range_max); + + /* Overwrite label and tick properties if tick value is within section range */ + lv_scale_section_t * section; + _LV_LL_READ_BACK(&scale->section_ll, section) { + if(section->minor_range <= tick_value && section->major_range >= tick_value) { + if(is_major_tick) { + scale_set_indicator_label_properties(obj, &label_dsc, section->indicator_style); + scale_set_line_properties(obj, &major_tick_dsc, section->indicator_style, LV_PART_INDICATOR); + } + else { + scale_set_line_properties(obj, &minor_tick_dsc, section->items_style, LV_PART_ITEMS); + } + break; + } + else { + /* Tick is not in section, get the proper styles */ + lv_obj_init_draw_label_dsc(obj, LV_PART_INDICATOR, &label_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_INDICATOR, &major_tick_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_ITEMS, &minor_tick_dsc); + } + } + + /* The tick is represented by a line. We need two points to draw it */ + lv_point_t tick_point_a; + lv_point_t tick_point_b; + scale_get_tick_points(obj, tick_idx, is_major_tick, &tick_point_a, &tick_point_b); + + /* Setup a label if they're enabled and we're drawing a major tick */ + if(scale->label_enabled && is_major_tick) { + /* Label text setup */ + char text_buffer[LV_SCALE_LABEL_TXT_LEN] = {0}; + lv_area_t label_coords; + + /* Check if the custom text array has element for this major tick index */ + if(scale->txt_src) { + scale_build_custom_label_text(obj, &label_dsc, major_tick_idx); + } + else { /* Add label with mapped values */ + lv_snprintf(text_buffer, sizeof(text_buffer), "%" LV_PRId32, tick_value); + label_dsc.text = text_buffer; + label_dsc.text_local = 1; + } + + scale_get_label_coords(obj, &label_dsc, &tick_point_b, &label_coords); + lv_draw_label(layer, &label_dsc, &label_coords); + } + + /* Store initial and last tick widths to be used in the main line drawing */ + scale_store_main_line_tick_width_compensation(obj, tick_idx, is_major_tick, major_tick_dsc.width, minor_tick_dsc.width); + + /* Store the first and last section tick vertical/horizontal position */ + scale_store_section_line_tick_width_compensation(obj, is_major_tick, &label_dsc, &major_tick_dsc, &minor_tick_dsc, + tick_value, tick_idx, &tick_point_a); + + if(is_major_tick) { + major_tick_dsc.p1 = lv_point_to_precise(&tick_point_a); + major_tick_dsc.p2 = lv_point_to_precise(&tick_point_b); + lv_draw_line(layer, &major_tick_dsc); + } + else { + minor_tick_dsc.p1 = lv_point_to_precise(&tick_point_a); + minor_tick_dsc.p2 = lv_point_to_precise(&tick_point_b); + lv_draw_line(layer, &minor_tick_dsc); + } + } + } + else if(LV_SCALE_MODE_ROUND_OUTER == scale->mode || LV_SCALE_MODE_ROUND_INNER == scale->mode) { + lv_area_t scale_area; + lv_obj_get_content_coords(obj, &scale_area); + + /* Find the center of the scale */ + lv_point_t center_point; + int32_t radius_edge = LV_MIN(lv_area_get_width(&scale_area) / 2U, lv_area_get_height(&scale_area) / 2U); + center_point.x = scale_area.x1 + radius_edge; + center_point.y = scale_area.y1 + radius_edge; + + /* Major tick */ + major_tick_dsc.raw_end = 0; + + uint32_t label_gap = LV_SCALE_DEFAULT_LABEL_GAP; /* TODO: Add to style properties */ + uint32_t tick_idx = 0; + uint32_t major_tick_idx = 0; + for(tick_idx = 0; tick_idx < scale->total_tick_count; tick_idx++) { + /* A major tick is the one which has a label in it */ + bool is_major_tick = false; + if(tick_idx % scale->major_tick_every == 0) is_major_tick = true; + if(is_major_tick) major_tick_idx++; + + const int32_t tick_value = lv_map(tick_idx, 0U, scale->total_tick_count - 1, scale->range_min, scale->range_max); + + /* Overwrite label and tick properties if tick value is within section range */ + lv_scale_section_t * section; + _LV_LL_READ_BACK(&scale->section_ll, section) { + if(section->minor_range <= tick_value && section->major_range >= tick_value) { + if(is_major_tick) { + scale_set_indicator_label_properties(obj, &label_dsc, section->indicator_style); + scale_set_line_properties(obj, &major_tick_dsc, section->indicator_style, LV_PART_INDICATOR); + } + else { + scale_set_line_properties(obj, &minor_tick_dsc, section->items_style, LV_PART_ITEMS); + } + break; + } + else { + /* Tick is not in section, get the proper styles */ + lv_obj_init_draw_label_dsc(obj, LV_PART_INDICATOR, &label_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_INDICATOR, &major_tick_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_ITEMS, &minor_tick_dsc); + } + } + + /* The tick is represented by a line. We need two points to draw it */ + lv_point_t tick_point_a; + lv_point_t tick_point_b; + scale_get_tick_points(obj, tick_idx, is_major_tick, &tick_point_a, &tick_point_b); + + /* Setup a label if they're enabled and we're drawing a major tick */ + if(scale->label_enabled && is_major_tick) { + /* Label text setup */ + char text_buffer[LV_SCALE_LABEL_TXT_LEN] = {0}; + lv_area_t label_coords; + + /* Check if the custom text array has element for this major tick index */ + if(scale->txt_src) { + scale_build_custom_label_text(obj, &label_dsc, major_tick_idx); + } + else { /* Add label with mapped values */ + lv_snprintf(text_buffer, sizeof(text_buffer), "%" LV_PRId32, tick_value); + label_dsc.text = text_buffer; + label_dsc.text_local = 1; + } + + /* Also take into consideration the letter space of the style */ + int32_t angle_upscale = ((tick_idx * scale->angle_range) * 10U) / (scale->total_tick_count - 1); + angle_upscale += scale->rotation * 10U; + + uint32_t radius_text = 0; + if(LV_SCALE_MODE_ROUND_INNER == scale->mode) { + radius_text = (radius_edge - major_len) - (label_gap + label_dsc.letter_space); + } + else if(LV_SCALE_MODE_ROUND_OUTER == scale->mode) { + radius_text = (radius_edge + major_len) + (label_gap + label_dsc.letter_space); + } + else { /* Nothing to do */ } + + lv_point_t point; + point.x = center_point.x + radius_text; + point.y = center_point.y; + lv_point_transform(&point, angle_upscale, LV_SCALE_NONE, LV_SCALE_NONE, ¢er_point, false); + scale_get_label_coords(obj, &label_dsc, &point, &label_coords); + + lv_draw_label(layer, &label_dsc, &label_coords); + } + + /* Store initial and last tick widths to be used in the main line drawing */ + scale_store_main_line_tick_width_compensation(obj, tick_idx, is_major_tick, major_tick_dsc.width, minor_tick_dsc.width); + + if(is_major_tick) { + major_tick_dsc.p1 = lv_point_to_precise(&tick_point_a); + major_tick_dsc.p2 = lv_point_to_precise(&tick_point_b); + lv_draw_line(layer, &major_tick_dsc); + } + else { + minor_tick_dsc.p1 = lv_point_to_precise(&tick_point_a); + minor_tick_dsc.p2 = lv_point_to_precise(&tick_point_b); + lv_draw_line(layer, &minor_tick_dsc); + } + } + } + else { /* Nothing to do */ } +} + +static void scale_draw_main(lv_obj_t * obj, lv_event_t * event) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + lv_layer_t * layer = lv_event_get_layer(event); + + if(scale->total_tick_count <= 1) return; + + if((LV_SCALE_MODE_VERTICAL_LEFT == scale->mode || LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) + || (LV_SCALE_MODE_HORIZONTAL_BOTTOM == scale->mode || LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode)) { + + /* Configure both line and label draw descriptors for the tick and label drawings */ + lv_draw_line_dsc_t line_dsc; + lv_draw_line_dsc_init(&line_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_MAIN, &line_dsc); + + /* Get style properties so they can be used in the main line drawing */ + const int32_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + const int32_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; + const int32_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN) + border_width; + const int32_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; + const int32_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN) + border_width; + + int32_t x_ofs = 0U; + int32_t y_ofs = 0U; + + if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode) { + x_ofs = obj->coords.x2 + (line_dsc.width / 2U) - pad_right; + y_ofs = obj->coords.y1 + pad_top; + } + else if(LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) { + x_ofs = obj->coords.x1 + (line_dsc.width / 2U) + pad_left; + y_ofs = obj->coords.y1 + pad_top; + } + if(LV_SCALE_MODE_HORIZONTAL_BOTTOM == scale->mode) { + x_ofs = obj->coords.x1 + pad_right; + y_ofs = obj->coords.y1 + (line_dsc.width / 2U) + pad_top; + } + else if(LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode) { + x_ofs = obj->coords.x1 + pad_left; + y_ofs = obj->coords.y2 + (line_dsc.width / 2U) - pad_bottom; + } + else { /* Nothing to do */ } + + lv_point_t main_line_point_a; + lv_point_t main_line_point_b; + + /* Setup the tick points */ + if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode || LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) { + main_line_point_a.x = x_ofs - 1U; + main_line_point_a.y = y_ofs; + main_line_point_b.x = x_ofs - 1U; + main_line_point_b.y = obj->coords.y2 - pad_bottom; + + /* Adjust main line with initial and last tick width */ + main_line_point_a.y -= scale->last_tick_width / 2U; + main_line_point_b.y += scale->first_tick_width / 2U; + } + else { + main_line_point_a.x = x_ofs; + main_line_point_a.y = y_ofs; + /* X of second point starts at the edge of the object minus the left pad */ + main_line_point_b.x = obj->coords.x2 - (pad_left); + main_line_point_b.y = y_ofs; + + /* Adjust main line with initial and last tick width */ + main_line_point_a.x -= scale->last_tick_width / 2U; + main_line_point_b.x += scale->first_tick_width / 2U; + } + + line_dsc.p1 = lv_point_to_precise(&main_line_point_a); + line_dsc.p2 = lv_point_to_precise(&main_line_point_b); + lv_draw_line(layer, &line_dsc); + + lv_scale_section_t * section; + _LV_LL_READ_BACK(&scale->section_ll, section) { + lv_draw_line_dsc_t main_line_section_dsc; + lv_draw_line_dsc_init(&main_line_section_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_MAIN, &main_line_section_dsc); + + /* Calculate the points of the section line */ + lv_point_t main_point_a; + lv_point_t main_point_b; + + /* Calculate the position of the section based on the ticks (first and last) index */ + if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode || LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) { + /* Calculate position of the first tick in the section */ + main_point_a.x = main_line_point_a.x; + int32_t tmp = (int32_t)(section->first_tick_in_section_width / 2U); + main_point_a.y = section->first_tick_in_section.y + tmp; + + /* Calculate position of the last tick in the section */ + main_point_b.x = main_line_point_a.x; + tmp = (int32_t)(section->last_tick_in_section_width / 2U); + main_point_b.y = section->last_tick_in_section.y - tmp; + } + else { + /* Calculate position of the first tick in the section */ + int32_t tmp = (int32_t)(section->first_tick_in_section_width / 2U); + main_point_a.x = section->first_tick_in_section.x - tmp; + main_point_a.y = main_line_point_a.y; + + /* Calculate position of the last tick in the section */ + tmp = (int32_t)(section->last_tick_in_section_width / 2U); + main_point_b.x = section->last_tick_in_section.x + tmp; + main_point_b.y = main_line_point_a.y; + } + + scale_set_line_properties(obj, &main_line_section_dsc, section->main_style, LV_PART_MAIN); + + main_line_section_dsc.p1.x = main_point_a.x; + main_line_section_dsc.p1.y = main_point_a.y; + main_line_section_dsc.p2.x = main_point_b.x; + main_line_section_dsc.p2.y = main_point_b.y; + lv_draw_line(layer, &main_line_section_dsc); + } + } + else if(LV_SCALE_MODE_ROUND_OUTER == scale->mode || LV_SCALE_MODE_ROUND_INNER == scale->mode) { + /* Configure arc draw descriptors for the main part */ + lv_draw_arc_dsc_t arc_dsc; + lv_draw_arc_dsc_init(&arc_dsc); + lv_obj_init_draw_arc_dsc(obj, LV_PART_MAIN, &arc_dsc); + + lv_point_t arc_center; + int32_t arc_radius; + scale_get_center(obj, &arc_center, &arc_radius); + + /* TODO: Add compensation for the width of the first and last tick over the arc */ + const int32_t start_angle = lv_map(scale->range_min, scale->range_min, scale->range_max, scale->rotation, + scale->rotation + scale->angle_range); + const int32_t end_angle = lv_map(scale->range_max, scale->range_min, scale->range_max, scale->rotation, + scale->rotation + scale->angle_range); + + arc_dsc.center = arc_center; + arc_dsc.radius = arc_radius; + arc_dsc.start_angle = start_angle; + arc_dsc.end_angle = end_angle; + + lv_draw_arc(layer, &arc_dsc); + + lv_scale_section_t * section; + _LV_LL_READ_BACK(&scale->section_ll, section) { + lv_draw_arc_dsc_t main_arc_section_dsc; + lv_draw_arc_dsc_init(&main_arc_section_dsc); + lv_obj_init_draw_arc_dsc(obj, LV_PART_MAIN, &main_arc_section_dsc); + + lv_point_t section_arc_center; + int32_t section_arc_radius; + scale_get_center(obj, §ion_arc_center, §ion_arc_radius); + + /* TODO: Add compensation for the width of the first and last tick over the arc */ + const int32_t section_start_angle = lv_map(section->minor_range, scale->range_min, scale->range_max, scale->rotation, + scale->rotation + scale->angle_range); + const int32_t section_end_angle = lv_map(section->major_range, scale->range_min, scale->range_max, scale->rotation, + scale->rotation + scale->angle_range); + + scale_set_arc_properties(obj, &main_arc_section_dsc, section->main_style); + + main_arc_section_dsc.center = section_arc_center; + main_arc_section_dsc.radius = section_arc_radius; + main_arc_section_dsc.start_angle = section_start_angle; + main_arc_section_dsc.end_angle = section_end_angle; + + lv_draw_arc(layer, &main_arc_section_dsc); + } + } + else { /* Nothing to do */ } +} + +/** + * Get center point and radius of scale arc + * @param obj pointer to a scale object + * @param center pointer to center + * @param arc_r pointer to arc radius + */ +static void scale_get_center(const lv_obj_t * obj, lv_point_t * center, int32_t * arc_r) +{ + int32_t left_bg = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + int32_t right_bg = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + int32_t top_bg = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + int32_t bottom_bg = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + + int32_t r = (LV_MIN(lv_obj_get_width(obj) - left_bg - right_bg, lv_obj_get_height(obj) - top_bg - bottom_bg)) / 2U; + + center->x = obj->coords.x1 + r + left_bg; + center->y = obj->coords.y1 + r + top_bg; + + if(arc_r) *arc_r = r; +} + +/** + * Get points for ticks + * + * In order to draw ticks we need two points, this interface returns both points for all scale modes. + * + * @param obj pointer to a scale object + * @param tick_idx index of the current tick + * @param is_major_tick true if tick_idx is a major tick + * @param tick_point_a pointer to point 'a' of the tick + * @param tick_point_b pointer to point 'b' of the tick + */ +static void scale_get_tick_points(lv_obj_t * obj, const uint32_t tick_idx, bool is_major_tick, + lv_point_t * tick_point_a, lv_point_t * tick_point_b) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + + /* Main line style */ + lv_draw_line_dsc_t main_line_dsc; + lv_draw_line_dsc_init(&main_line_dsc); + lv_obj_init_draw_line_dsc(obj, LV_PART_MAIN, &main_line_dsc); + + int32_t minor_len = 0; + int32_t major_len = 0; + + if(is_major_tick) { + major_len = lv_obj_get_style_length(obj, LV_PART_INDICATOR); + } + else { + minor_len = lv_obj_get_style_length(obj, LV_PART_ITEMS); + } + + if((LV_SCALE_MODE_VERTICAL_LEFT == scale->mode || LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) + || (LV_SCALE_MODE_HORIZONTAL_BOTTOM == scale->mode || LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode)) { + + /* Get style properties so they can be used in the tick and label drawing */ + const int32_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + const int32_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN) + border_width; + const int32_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN) + border_width; + const int32_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN) + border_width; + const int32_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; + const int32_t tick_pad_right = lv_obj_get_style_pad_right(obj, LV_PART_ITEMS); + const int32_t tick_pad_left = lv_obj_get_style_pad_left(obj, LV_PART_ITEMS); + const int32_t tick_pad_top = lv_obj_get_style_pad_top(obj, LV_PART_ITEMS); + const int32_t tick_pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_ITEMS); + + int32_t x_ofs = 0U; + int32_t y_ofs = 0U; + + if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode) { + x_ofs = obj->coords.x2 + (main_line_dsc.width / 2U) - pad_right; + y_ofs = obj->coords.y1 + (pad_top + tick_pad_top); + } + else if(LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) { + x_ofs = obj->coords.x1 + (main_line_dsc.width / 2U) + pad_left; + y_ofs = obj->coords.y1 + (pad_top + tick_pad_top); + } + else if(LV_SCALE_MODE_HORIZONTAL_BOTTOM == scale->mode) { + x_ofs = obj->coords.x1 + (pad_right + tick_pad_right); + y_ofs = obj->coords.y1 + (main_line_dsc.width / 2U) + pad_top; + } + /* LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode */ + else { + x_ofs = obj->coords.x1 + (pad_left + tick_pad_left); + y_ofs = obj->coords.y2 + (main_line_dsc.width / 2U) - pad_bottom; + } + + /* Adjust length when tick will be drawn on horizontal top or vertical right scales */ + if((LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode) || (LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode)) { + if(is_major_tick) { + major_len *= -1; + } + else { + minor_len *= -1; + } + } + else { /* Nothing to do */ } + + const int32_t tick_length = is_major_tick ? major_len : minor_len; + /* NOTE + * Minus 1 because tick count starts at 0 + * TODO + * What if total_tick_count is 1? This will lead to an division by 0 further down */ + const uint32_t tmp_tick_count = scale->total_tick_count - 1U; + + /* Calculate the position of the tick points based on the mode and tick index */ + if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode || LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) { + /* Vertical position starts at y2 of the scale main line, we start at y2 because the ticks are drawn from bottom to top */ + int32_t vertical_position = obj->coords.y2 - (pad_bottom + tick_pad_bottom); + + /* Position the last tick */ + if(tmp_tick_count == tick_idx) { + vertical_position = y_ofs; + } + /* Otherwise adjust the tick position depending of its index and number of ticks on the scale */ + else if(0 != tick_idx) { + const int32_t scale_total_height = lv_obj_get_height(obj) - (pad_top + pad_bottom + tick_pad_top + tick_pad_bottom); + const int32_t offset = ((int32_t) tick_idx * (int32_t) scale_total_height) / (int32_t)(tmp_tick_count); + vertical_position -= offset; + } + else { /* Nothing to do */ } + + tick_point_a->x = x_ofs - 1U; /* Move extra pixel out of scale boundary */ + tick_point_a->y = vertical_position; + tick_point_b->x = tick_point_a->x - tick_length; + tick_point_b->y = vertical_position; + } + else { + /* Horizontal position starts at x1 of the scale main line */ + int32_t horizontal_position = x_ofs; + + /* Position the last tick */ + if(tmp_tick_count == tick_idx) { + horizontal_position = obj->coords.x2 - (pad_left + tick_pad_left); + } + /* Otherwise adjust the tick position depending of its index and number of ticks on the scale */ + else if(0U != tick_idx) { + const int32_t scale_total_width = lv_obj_get_width(obj) - (pad_right + pad_left + tick_pad_right + tick_pad_left); + const int32_t offset = ((int32_t) tick_idx * (int32_t) scale_total_width) / (int32_t)(tmp_tick_count); + horizontal_position += offset; + } + else { /* Nothing to do */ } + + tick_point_a->x = horizontal_position; + tick_point_a->y = y_ofs; + tick_point_b->x = horizontal_position; + tick_point_b->y = tick_point_a->y + tick_length; + } + } + else if(LV_SCALE_MODE_ROUND_OUTER == scale->mode || LV_SCALE_MODE_ROUND_INNER == scale->mode) { + lv_area_t scale_area; + lv_obj_get_content_coords(obj, &scale_area); + + /* Find the center of the scale */ + lv_point_t center_point; + const int32_t radius_edge = LV_MIN(lv_area_get_width(&scale_area) / 2U, lv_area_get_height(&scale_area) / 2U); + center_point.x = scale_area.x1 + radius_edge; + center_point.y = scale_area.y1 + radius_edge; + + int32_t angle_upscale = ((tick_idx * scale->angle_range) * 10U) / (scale->total_tick_count - 1); + angle_upscale += scale->rotation * 10U; + + /* Draw a little bit longer lines to be sure the mask will clip them correctly + * and to get a better precision. Adding the main line width to the calculation so we don't have gaps + * between the arc and the ticks */ + int32_t point_closer_to_arc = 0; + int32_t adjusted_radio_with_tick_len = 0; + if(LV_SCALE_MODE_ROUND_INNER == scale->mode) { + point_closer_to_arc = radius_edge - main_line_dsc.width; + adjusted_radio_with_tick_len = point_closer_to_arc - (is_major_tick ? major_len : minor_len); + } + /* LV_SCALE_MODE_ROUND_OUTER == scale->mode */ + else { + point_closer_to_arc = radius_edge - main_line_dsc.width; + adjusted_radio_with_tick_len = point_closer_to_arc + (is_major_tick ? major_len : minor_len); + } + + tick_point_a->x = center_point.x + point_closer_to_arc; + tick_point_a->y = center_point.y; + lv_point_transform(tick_point_a, angle_upscale, LV_SCALE_NONE, LV_SCALE_NONE, ¢er_point, false); + + tick_point_b->x = center_point.x + adjusted_radio_with_tick_len; + tick_point_b->y = center_point.y; + lv_point_transform(tick_point_b, angle_upscale, LV_SCALE_NONE, LV_SCALE_NONE, ¢er_point, false); + } + else { /* Nothing to do */ } +} + +/** + * Get coordinates for label + * + * @param obj pointer to a scale object + * @param label_dsc pointer to label descriptor + * @param tick_point pointer to reference tick + * @param label_coords pointer to label coordinates output + */ +static void scale_get_label_coords(lv_obj_t * obj, lv_draw_label_dsc_t * label_dsc, lv_point_t * tick_point, + lv_area_t * label_coords) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + + /* Reserve appropriate size for the tick label */ + lv_point_t label_size; + lv_text_get_size(&label_size, label_dsc->text, + label_dsc->font, label_dsc->letter_space, label_dsc->line_space, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + + /* Set the label draw area at some distance of the major tick */ + if((LV_SCALE_MODE_HORIZONTAL_BOTTOM == scale->mode) || (LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode)) { + label_coords->x1 = tick_point->x - (label_size.x / 2U); + label_coords->x2 = tick_point->x + (label_size.x / 2U); + + if(LV_SCALE_MODE_HORIZONTAL_BOTTOM == scale->mode) { + label_coords->y1 = tick_point->y + lv_obj_get_style_pad_bottom(obj, LV_PART_INDICATOR); + label_coords->y2 = label_coords->y1 + label_size.y; + } + else { + label_coords->y2 = tick_point->y - lv_obj_get_style_pad_top(obj, LV_PART_INDICATOR); + label_coords->y1 = label_coords->y2 - label_size.y; + } + } + else if((LV_SCALE_MODE_VERTICAL_LEFT == scale->mode) || (LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode)) { + label_coords->y1 = tick_point->y - (label_size.y / 2U); + label_coords->y2 = tick_point->y + (label_size.y / 2U); + + if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode) { + label_coords->x1 = tick_point->x - label_size.x - lv_obj_get_style_pad_left(obj, LV_PART_INDICATOR); + label_coords->x2 = tick_point->x - lv_obj_get_style_pad_left(obj, LV_PART_INDICATOR); + } + else { + label_coords->x1 = tick_point->x + lv_obj_get_style_pad_right(obj, LV_PART_INDICATOR); + label_coords->x2 = tick_point->x + label_size.x + lv_obj_get_style_pad_right(obj, LV_PART_INDICATOR); + } + } + else if(LV_SCALE_MODE_ROUND_OUTER == scale->mode || LV_SCALE_MODE_ROUND_INNER == scale->mode) { + label_coords->x1 = tick_point->x - (label_size.x / 2U); + label_coords->y1 = tick_point->y - (label_size.y / 2U); + label_coords->x2 = label_coords->x1 + label_size.x; + label_coords->y2 = label_coords->y1 + label_size.y; + } + else { /* Nothing to do */ } +} + +/** + * Set line properties + * + * Checks if the line has a custom section configuration or not and sets the properties accordingly. + * + * @param obj pointer to a scale object + * @param line_dsc pointer to line descriptor + * @param items_section_style pointer to indicator section style + * @param part line part, example: LV_PART_INDICATOR, LV_PART_ITEMS, LV_PART_MAIN + */ +static void scale_set_line_properties(lv_obj_t * obj, lv_draw_line_dsc_t * line_dsc, lv_style_t * section_style, + uint32_t part) +{ + if(section_style) { + lv_style_value_t value; + lv_result_t res; + + /* Line width */ + res = lv_style_get_prop(section_style, LV_STYLE_LINE_WIDTH, &value); + if(res == LV_RESULT_OK) { + line_dsc->width = (int32_t)value.num; + } + else { + line_dsc->width = lv_obj_get_style_line_width(obj, part); + } + + /* Line color */ + res = lv_style_get_prop(section_style, LV_STYLE_LINE_COLOR, &value); + if(res == LV_RESULT_OK) { + line_dsc->color = value.color; + } + else { + line_dsc->color = lv_obj_get_style_line_color(obj, part); + } + + /* Line opa */ + res = lv_style_get_prop(section_style, LV_STYLE_LINE_OPA, &value); + if(res == LV_RESULT_OK) { + line_dsc->opa = (lv_opa_t)value.num; + } + else { + line_dsc->opa = lv_obj_get_style_line_opa(obj, part); + } + } + else { + line_dsc->color = lv_obj_get_style_line_color(obj, part); + line_dsc->opa = lv_obj_get_style_line_opa(obj, part); + line_dsc->width = lv_obj_get_style_line_width(obj, part); + } +} + +/** + * Set arc properties + * + * Checks if the arc has a custom section configuration or not and sets the properties accordingly. + * + * @param obj pointer to a scale object + * @param line_dsc pointer to arc descriptor + * @param items_section_style pointer to indicator section style + */ +static void scale_set_arc_properties(lv_obj_t * obj, lv_draw_arc_dsc_t * arc_dsc, lv_style_t * section_style) +{ + if(section_style) { + lv_style_value_t value; + lv_result_t res; + + /* Line width */ + res = lv_style_get_prop(section_style, LV_STYLE_ARC_WIDTH, &value); + if(res == LV_RESULT_OK) { + arc_dsc->width = (int32_t)value.num; + } + else { + arc_dsc->width = lv_obj_get_style_line_width(obj, LV_PART_MAIN); + } + + /* Line color */ + res = lv_style_get_prop(section_style, LV_STYLE_ARC_COLOR, &value); + if(res == LV_RESULT_OK) { + arc_dsc->color = value.color; + } + else { + arc_dsc->color = lv_obj_get_style_line_color(obj, LV_PART_MAIN); + } + + /* Line opa */ + res = lv_style_get_prop(section_style, LV_STYLE_ARC_OPA, &value); + if(res == LV_RESULT_OK) { + arc_dsc->opa = (lv_opa_t)value.num; + } + else { + arc_dsc->opa = lv_obj_get_style_line_opa(obj, LV_PART_MAIN); + } + } + else { + arc_dsc->color = lv_obj_get_style_line_color(obj, LV_PART_MAIN); + arc_dsc->opa = lv_obj_get_style_line_opa(obj, LV_PART_MAIN); + arc_dsc->width = lv_obj_get_style_line_width(obj, LV_PART_MAIN); + } +} + +/** + * Set indicator label properties + * + * Checks if the indicator has a custom section configuration or not and sets the properties accordingly. + * + * @param obj pointer to a scale object + * @param label_dsc pointer to label descriptor + * @param items_section_style pointer to indicator section style + */ +static void scale_set_indicator_label_properties(lv_obj_t * obj, lv_draw_label_dsc_t * label_dsc, + lv_style_t * indicator_section_style) +{ + if(indicator_section_style) { + lv_style_value_t value; + lv_result_t res; + + /* Text color */ + res = lv_style_get_prop(indicator_section_style, LV_STYLE_TEXT_COLOR, &value); + if(res == LV_RESULT_OK) { + label_dsc->color = value.color; + } + else { + label_dsc->color = lv_obj_get_style_text_color(obj, LV_PART_INDICATOR); + } + + /* Text opa */ + res = lv_style_get_prop(indicator_section_style, LV_STYLE_TEXT_OPA, &value); + if(res == LV_RESULT_OK) { + label_dsc->opa = (lv_opa_t)value.num; + } + else { + label_dsc->opa = lv_obj_get_style_text_opa(obj, LV_PART_INDICATOR); + } + + /* Text letter space */ + res = lv_style_get_prop(indicator_section_style, LV_STYLE_TEXT_LETTER_SPACE, &value); + if(res == LV_RESULT_OK) { + label_dsc->letter_space = (int32_t)value.num; + } + else { + label_dsc->letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_INDICATOR); + } + + /* Text font */ + res = lv_style_get_prop(indicator_section_style, LV_STYLE_TEXT_FONT, &value); + if(res == LV_RESULT_OK) { + label_dsc->font = (const lv_font_t *)value.ptr; + } + else { + label_dsc->font = lv_obj_get_style_text_font(obj, LV_PART_INDICATOR); + } + } + else { + /* If label is not within a range then get the indicator style */ + label_dsc->color = lv_obj_get_style_text_color(obj, LV_PART_INDICATOR); + label_dsc->opa = lv_obj_get_style_text_opa(obj, LV_PART_INDICATOR); + label_dsc->letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_INDICATOR); + label_dsc->font = lv_obj_get_style_text_font(obj, LV_PART_INDICATOR); + } +} + +static void scale_find_section_tick_idx(lv_obj_t * obj) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + + const int32_t min_out = scale->range_min; + const int32_t max_out = scale->range_max; + const uint32_t total_tick_count = scale->total_tick_count; + + /* Section handling */ + uint32_t tick_idx = 0; + for(tick_idx = 0; tick_idx < total_tick_count; tick_idx++) { + bool is_major_tick = false; + if(tick_idx % scale->major_tick_every == 0) is_major_tick = true; + + const int32_t tick_value = lv_map(tick_idx, 0U, total_tick_count - 1, min_out, max_out); + + lv_scale_section_t * section; + _LV_LL_READ_BACK(&scale->section_ll, section) { + if(section->minor_range <= tick_value && section->major_range >= tick_value) { + if(LV_SCALE_TICK_IDX_DEFAULT_ID == section->first_tick_idx_in_section) { + section->first_tick_idx_in_section = tick_idx; + section->first_tick_idx_is_major = is_major_tick; + } + if(section->first_tick_idx_in_section != tick_idx) { + section->last_tick_idx_in_section = tick_idx; + section->last_tick_idx_is_major = is_major_tick; + } + } + else { /* Nothing to do */ } + } + } +} + +/** + * Stores the width of the initial and last tick of the main line + * + * This width is used to compensate the main line drawing taking into consideration the widths of both ticks + * + * @param obj pointer to a scale object + * @param tick_idx index of the current tick + * @param is_major_tick true if tick_idx is a major tick + * @param major_tick_width width of the major tick + * @param minor_tick_width width of the minor tick + */ +static void scale_store_main_line_tick_width_compensation(lv_obj_t * obj, const uint32_t tick_idx, + const bool is_major_tick, const int32_t major_tick_width, const int32_t minor_tick_width) +{ + lv_scale_t * scale = (lv_scale_t *)obj; + const bool is_first_tick = 0U == tick_idx; + const bool is_last_tick = scale->total_tick_count == tick_idx; + const int32_t tick_width = is_major_tick ? major_tick_width : minor_tick_width; + + /* Exit early if tick_idx is not the first nor last tick on the main line */ + if(((!is_last_tick) && (!is_first_tick)) + /* Exit early if scale mode is round. It doesn't support main line compensation */ + || ((LV_SCALE_MODE_ROUND_INNER == scale->mode) || (LV_SCALE_MODE_ROUND_OUTER == scale->mode))) { + return; + } + + if(is_last_tick) { + /* Mode is vertical */ + if((LV_SCALE_MODE_VERTICAL_LEFT == scale->mode) || (LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode)) { + scale->last_tick_width = tick_width; + } + /* Mode is horizontal */ + else { + scale->first_tick_width = tick_width; + } + } + /* is_first_tick */ + else { + /* Mode is vertical */ + if((LV_SCALE_MODE_VERTICAL_LEFT == scale->mode) || (LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode)) { + scale->first_tick_width = tick_width; + } + /* Mode is horizontal */ + else { + scale->last_tick_width = tick_width; + } + } +} + +/** + * Sets the text of the tick label descriptor when using custom labels + * + * Sets the text pointer when valid custom label is available, otherwise set it to NULL. + * + * @param obj pointer to a scale object + * @param label_dsc pointer to the label descriptor + * @param major_tick_idx index of the current major tick + */ +static void scale_build_custom_label_text(lv_obj_t * obj, lv_draw_label_dsc_t * label_dsc, + const uint16_t major_tick_idx) +{ + lv_scale_t * scale = (lv_scale_t *) obj; + + /* Check if the scale has valid custom labels available, + * this avoids reading past txt_src array when the scale requires more tick labels than available */ + if(major_tick_idx <= scale->custom_label_cnt) { + if(scale->txt_src[major_tick_idx - 1U]) { + label_dsc->text = scale->txt_src[major_tick_idx - 1U]; + label_dsc->text_local = 0; + } + else { + label_dsc->text = NULL; + } + } + else { + label_dsc->text = NULL; + } +} + +/** + * Stores tick width compensation information for main line sections + * + * @param obj pointer to a scale object + * @param is_major_tick Indicates if tick is major or not + * @param label_dsc pointer to the label descriptor + * @param major_tick_dsc pointer to the major_tick_dsc + * @param minor_tick_dsc pointer to the minor_tick_dsc + * @param tick_value Current tick value, used to know if tick_idx belongs to a section or not + * @param tick_idx Current tick index + * @param tick_point_a Pointer to tick point a + */ +static void scale_store_section_line_tick_width_compensation(lv_obj_t * obj, const bool is_major_tick, + lv_draw_label_dsc_t * label_dsc, lv_draw_line_dsc_t * major_tick_dsc, lv_draw_line_dsc_t * minor_tick_dsc, + const int32_t tick_value, const uint8_t tick_idx, lv_point_t * tick_point_a) +{ + lv_scale_t * scale = (lv_scale_t *) obj; + lv_scale_section_t * section; + + _LV_LL_READ_BACK(&scale->section_ll, section) { + if(section->minor_range <= tick_value && section->major_range >= tick_value) { + if(is_major_tick) { + scale_set_indicator_label_properties(obj, label_dsc, section->indicator_style); + scale_set_line_properties(obj, major_tick_dsc, section->indicator_style, LV_PART_INDICATOR); + } + else { + scale_set_line_properties(obj, minor_tick_dsc, section->items_style, LV_PART_ITEMS); + } + } + + int32_t tmp_width = 0; + + if(tick_idx == section->first_tick_idx_in_section) { + if(section->first_tick_idx_is_major) { + tmp_width = major_tick_dsc->width; + } + else { + tmp_width = minor_tick_dsc->width; + } + + section->first_tick_in_section.y = tick_point_a->y; + /* Add 1px as adjustment if tmp_width is odd */ + if(tmp_width & 0x01U) { + if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode || LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) { + tmp_width += 1U; + } + else { + tmp_width -= 1U; + } + } + section->first_tick_in_section_width = tmp_width; + } + else if(tick_idx == section->last_tick_idx_in_section) { + if(section->last_tick_idx_is_major) { + tmp_width = major_tick_dsc->width; + } + else { + tmp_width = minor_tick_dsc->width; + } + + section->last_tick_in_section.y = tick_point_a->y; + /* Add 1px as adjustment if tmp_width is odd */ + if(tmp_width & 0x01U) { + if(LV_SCALE_MODE_VERTICAL_LEFT == scale->mode || LV_SCALE_MODE_VERTICAL_RIGHT == scale->mode) { + tmp_width -= 1U; + } + else { + tmp_width += 1U; + } + } + section->last_tick_in_section_width = tmp_width; + } + else { /* Nothing to do */ } + } +} + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/scale/lv_scale.h b/lib/libesp32_lvgl/lvgl/src/widgets/scale/lv_scale.h new file mode 100644 index 000000000..8ac377eb1 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/scale/lv_scale.h @@ -0,0 +1,286 @@ +/** + * @file lv_scale.h + * + */ + +#ifndef LV_SCALE_H +#define LV_SCALE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" + +#if LV_USE_SCALE != 0 + +#include "../../core/lv_obj.h" +#include "../line/lv_line.h" +#include "../image/lv_image.h" + +/********************* + * DEFINES + *********************/ + +/**Default value of total minor ticks. */ +#define LV_SCALE_TOTAL_TICK_COUNT_DEFAULT (11U) +LV_EXPORT_CONST_INT(LV_SCALE_TOTAL_TICK_COUNT_DEFAULT); + +/**Default value of major tick every nth ticks. */ +#define LV_SCALE_MAJOR_TICK_EVERY_DEFAULT (5U) +LV_EXPORT_CONST_INT(LV_SCALE_MAJOR_TICK_EVERY_DEFAULT); + +/**Default value of scale label enabled. */ +#define LV_SCALE_LABEL_ENABLED_DEFAULT (1U) +LV_EXPORT_CONST_INT(LV_SCALE_LABEL_ENABLED_DEFAULT); + +/********************** + * TYPEDEFS + **********************/ + +/** + * Scale mode + */ +enum { + LV_SCALE_MODE_HORIZONTAL_TOP = 0x00U, + LV_SCALE_MODE_HORIZONTAL_BOTTOM = 0x01U, + LV_SCALE_MODE_VERTICAL_LEFT = 0x02U, + LV_SCALE_MODE_VERTICAL_RIGHT = 0x04U, + LV_SCALE_MODE_ROUND_INNER = 0x08U, + LV_SCALE_MODE_ROUND_OUTER = 0x10U, + _LV_SCALE_MODE_LAST +}; +typedef uint32_t lv_scale_mode_t; + +typedef struct { + lv_style_t * main_style; + lv_style_t * indicator_style; + lv_style_t * items_style; + int32_t minor_range; + int32_t major_range; + uint32_t first_tick_idx_in_section; + uint32_t last_tick_idx_in_section; + uint32_t first_tick_idx_is_major; + uint32_t last_tick_idx_is_major; + int32_t first_tick_in_section_width; + int32_t last_tick_in_section_width; + lv_point_t first_tick_in_section; + lv_point_t last_tick_in_section; +} lv_scale_section_t; + +typedef struct { + lv_obj_t obj; + lv_ll_t section_ll; /**< Linked list for the sections (stores lv_scale_section_t)*/ + const char ** txt_src; + lv_scale_mode_t mode; + int32_t range_min; + int32_t range_max; + uint32_t total_tick_count : 15; + uint32_t major_tick_every : 15; + uint32_t label_enabled : 1; + uint32_t post_draw : 1; + /* Round scale */ + uint32_t angle_range; + int32_t rotation; + /* Private properties */ + int32_t custom_label_cnt; + int32_t last_tick_width; + int32_t first_tick_width; +} lv_scale_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_scale_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create an scale object + * @param parent pointer to an object, it will be the parent of the new scale + * @return pointer to the created scale + */ +lv_obj_t * lv_scale_create(lv_obj_t * parent); + +/*====================== + * Add/remove functions + *=====================*/ + +/*===================== + * Setter functions + *====================*/ + +/** + * Set scale mode. See @ref lv_scale_mode_t + * @param obj pointer the scale object + * @param mode the new scale mode + */ +void lv_scale_set_mode(lv_obj_t * obj, lv_scale_mode_t mode); + +/** + * Set scale total tick count (including minor and major ticks) + * @param obj pointer the scale object + * @param total_tick_count New total tick count + */ +void lv_scale_set_total_tick_count(lv_obj_t * obj, uint32_t total_tick_count); + +/** + * Sets how often the major tick will be drawn + * @param obj pointer the scale object + * @param major_tick_every the new count for major tick drawing + */ +void lv_scale_set_major_tick_every(lv_obj_t * obj, uint32_t major_tick_every); + +/** + * Sets label visibility + * @param obj pointer the scale object + * @param show_label true/false to enable tick label + */ +void lv_scale_set_label_show(lv_obj_t * obj, bool show_label); + +/** + * Set the minimal and maximal values on a scale + * @param obj pointer to a scale object + * @param min minimum value of the scale + * @param max maximum value of the scale + */ +void lv_scale_set_range(lv_obj_t * obj, int32_t min, int32_t max); + +/** + * Set properties specific to round scale + * @param obj pointer to a scale object + * @param angle_range the angular range of the scale + */ +void lv_scale_set_angle_range(lv_obj_t * obj, uint32_t angle_range); + +/** + * Set properties specific to round scale + * @param obj pointer to a scale object + * @param rotation the angular offset from the 3 o'clock position (clock-wise) + */ +void lv_scale_set_rotation(lv_obj_t * obj, int32_t rotation); + +/** + * Point the needle to the corresponding value through the line + * @param obj pointer to a scale object + * @param needle_line needle_line of the scale + * @param needle_length length of the needle + * needle_length>0 needle_length=needle_length; + * needle_length<0 needle_length=radius-|needle_length|; + * @param value needle to point to the corresponding value + */ +void lv_scale_set_line_needle_value(lv_obj_t * obj, lv_obj_t * needle_line, int32_t needle_length, + int32_t value); + +/** + * Point the needle to the corresponding value through the image, + image must point to the right. E.g. -O------> + * @param obj pointer to a scale object + * @param needle_img needle_img of the scale + * @param value needle to point to the corresponding value + */ +void lv_scale_set_image_needle_value(lv_obj_t * obj, lv_obj_t * needle_img, int32_t value); + +/** + * Set custom text source for major ticks labels + * @param obj pointer to a scale object + * @param txt_src pointer to an array of strings which will be display at major ticks + */ +void lv_scale_set_text_src(lv_obj_t * obj, const char * txt_src[]); + +/** + * Draw the scale after all the children are drawn + * @param obj pointer to a scale object + * @param en true: enable post draw + */ +void lv_scale_set_post_draw(lv_obj_t * obj, bool en); + +/** + * Add a section to the given scale + * @param obj pointer to a scale object + * @return pointer to the new section + */ +lv_scale_section_t * lv_scale_add_section(lv_obj_t * obj); + +/** + * Set the range for the given scale section + * @param section pointer to a scale section object + * @param minor_range section new minor range + * @param major_range section new major range + */ +void lv_scale_section_set_range(lv_scale_section_t * section, int32_t minor_range, int32_t major_range); + +/** + * Set the style of the part for the given scale section + * @param section pointer to a scale section object + * @param part the part for the section, e.g. LV_PART_INDICATOR + * @param section_part_style Pointer to the section part style + */ +void lv_scale_section_set_style(lv_scale_section_t * section, uint32_t part, lv_style_t * section_part_style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get scale mode. See @ref lv_scale_mode_t + * @param obj pointer the scale object + * @return Scale mode + */ +lv_scale_mode_t lv_scale_get_mode(lv_obj_t * obj); + +/** + * Get scale total tick count (including minor and major ticks) + * @param obj pointer the scale object + * @return Scale total tick count + */ +int32_t lv_scale_get_total_tick_count(lv_obj_t * obj); + +/** + * Gets how often the major tick will be drawn + * @param obj pointer the scale object + * @return Scale major tick every count + */ +int32_t lv_scale_get_major_tick_every(lv_obj_t * obj); + +/** + * Gets label visibility + * @param obj pointer the scale object + * @return true if tick label is enabled, false otherwise + */ +bool lv_scale_get_label_show(lv_obj_t * obj); + +/** + * Get angle range of a round scale + * @param obj pointer to a scale object + * @return Scale angle_range + */ +uint32_t lv_scale_get_angle_range(lv_obj_t * obj); + +/** + * Get the min range for the given scale section + * @param obj pointer to a scale section object + * @return section minor range + */ +int32_t lv_scale_get_range_min_value(lv_obj_t * obj); + +/** + * Get the max range for the given scale section + * @param obj pointer to a scale section object + * @return section max range + */ +int32_t lv_scale_get_range_max_value(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_SCALE*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_SCALE_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/slider/lv_slider.c b/lib/libesp32_lvgl/lvgl/src/widgets/slider/lv_slider.c new file mode 100644 index 000000000..577b91e30 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/slider/lv_slider.c @@ -0,0 +1,490 @@ +/** + * @file lv_slider.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_slider.h" +#if LV_USE_SLIDER != 0 + +#include "../../misc/lv_assert.h" +#include "../../core/lv_group.h" +#include "../../indev/lv_indev.h" +#include "../../indev/lv_indev_private.h" +#include "../../display/lv_display.h" +#include "../../draw/lv_draw.h" +#include "../../stdlib/lv_string.h" +#include "../../misc/lv_math.h" +#include "../image/lv_image.h" + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_slider_class + +#define LV_SLIDER_KNOB_COORD(is_reversed, area) (is_reversed ? area.x1 : area.x2) +#define LV_SLIDER_KNOB_COORD_VERTICAL(is_reversed, area) (is_reversed ? area.y2 : area.y1) + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_slider_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_slider_event(const lv_obj_class_t * class_p, lv_event_t * e); +static void position_knob(lv_obj_t * obj, lv_area_t * knob_area, const int32_t knob_size, const bool hor); +static void draw_knob(lv_event_t * e); +static bool is_slider_horizontal(lv_obj_t * obj); +static void drag_start(lv_obj_t * obj); +static void update_knob_pos(lv_obj_t * obj, bool check_drag); + +/********************** + * STATIC VARIABLES + **********************/ +const lv_obj_class_t lv_slider_class = { + .constructor_cb = lv_slider_constructor, + .event_cb = lv_slider_event, + .editable = LV_OBJ_CLASS_EDITABLE_TRUE, + .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, + .instance_size = sizeof(lv_slider_t), + .base_class = &lv_bar_class, + .name = "slider", +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_slider_create(lv_obj_t * parent) +{ + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + return obj; +} + +bool lv_slider_is_dragged(const lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_slider_t * slider = (lv_slider_t *)obj; + + return slider->dragging; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_slider_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + lv_slider_t * slider = (lv_slider_t *)obj; + + /*Initialize the allocated 'slider'*/ + slider->value_to_set = NULL; + slider->dragging = 0U; + slider->left_knob_focus = 0U; + + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN_HOR); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS); + lv_obj_set_ext_click_area(obj, LV_DPX(8)); +} + +static void lv_slider_event(const lv_obj_class_t * class_p, lv_event_t * e) +{ + LV_UNUSED(class_p); + + lv_result_t res; + + /*Call the ancestor's event handler*/ + res = lv_obj_event_base(MY_CLASS, e); + if(res != LV_RESULT_OK) return; + + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * obj = lv_event_get_current_target(e); + lv_slider_t * slider = (lv_slider_t *)obj; + lv_slider_mode_t type = lv_slider_get_mode(obj); + + /*Advanced hit testing: react only on dragging the knob(s)*/ + if(code == LV_EVENT_HIT_TEST) { + lv_hit_test_info_t * info = lv_event_get_param(e); + int32_t ext_click_area = obj->spec_attr ? obj->spec_attr->ext_click_pad : 0; + + /*Ordinary slider: was the knob area hit?*/ + lv_area_t a; + lv_area_copy(&a, &slider->right_knob_area); + lv_area_increase(&a, ext_click_area, ext_click_area); + info->res = _lv_area_is_point_on(&a, info->point, 0); + + /*There's still a chance that there is a hit if there is another knob*/ + if((info->res == false) && (type == LV_SLIDER_MODE_RANGE)) { + lv_area_copy(&a, &slider->left_knob_area); + lv_area_increase(&a, ext_click_area, ext_click_area); + info->res = _lv_area_is_point_on(&a, info->point, 0); + } + } + else if(code == LV_EVENT_PRESSED) { + /*Save the pressed coordinates*/ + lv_indev_get_point(lv_indev_active(), &slider->pressed_point); + lv_obj_transform_point(obj, &slider->pressed_point, true, true); + } + else if(code == LV_EVENT_PRESSING) { + update_knob_pos(obj, true); + } + else if(code == LV_EVENT_RELEASED || code == LV_EVENT_PRESS_LOST) { + update_knob_pos(obj, false); + slider->dragging = false; + slider->value_to_set = NULL; + + lv_obj_invalidate(obj); + + /*Leave edit mode if released. (No need to wait for LONG_PRESS)*/ + lv_group_t * g = lv_obj_get_group(obj); + bool editing = lv_group_get_editing(g); + lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_active()); + if(indev_type == LV_INDEV_TYPE_ENCODER) { + if(editing) { + if(lv_slider_get_mode(obj) == LV_SLIDER_MODE_RANGE) { + if(slider->left_knob_focus == 0) slider->left_knob_focus = 1; + else { + slider->left_knob_focus = 0; + lv_group_set_editing(g, false); + } + } + else { + lv_group_set_editing(g, false); + } + } + } + else if(indev_type == LV_INDEV_TYPE_POINTER) { + if(is_slider_horizontal(obj)) lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN_VER); + else lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN_HOR); + } + } + else if(code == LV_EVENT_FOCUSED) { + lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_active()); + if(indev_type == LV_INDEV_TYPE_ENCODER || indev_type == LV_INDEV_TYPE_KEYPAD) { + slider->left_knob_focus = 0; + } + } + else if(code == LV_EVENT_SIZE_CHANGED) { + if(is_slider_horizontal(obj)) { + lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN_VER); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN_HOR); + } + else { + lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN_HOR); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN_VER); + } + lv_obj_refresh_ext_draw_size(obj); + } + else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { + int32_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); + int32_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); + int32_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); + int32_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); + + /*The smaller size is the knob diameter*/ + int32_t trans_w = lv_obj_get_style_transform_width(obj, LV_PART_KNOB); + int32_t trans_h = lv_obj_get_style_transform_height(obj, LV_PART_KNOB); + int32_t knob_size = LV_MIN(lv_obj_get_width(obj) + 2 * trans_w, lv_obj_get_height(obj) + 2 * trans_h) >> 1; + knob_size += LV_MAX(LV_MAX(knob_left, knob_right), LV_MAX(knob_bottom, knob_top)); + knob_size += 2; /*For rounding error*/ + knob_size += lv_obj_calculate_ext_draw_size(obj, LV_PART_KNOB); + + /*Indic. size is handled by bar*/ + int32_t * s = lv_event_get_param(e); + *s = LV_MAX(*s, knob_size); + + } + else if(code == LV_EVENT_KEY) { + uint32_t c = lv_event_get_key(e); + + if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { + if(!slider->left_knob_focus) lv_slider_set_value(obj, lv_slider_get_value(obj) + 1, LV_ANIM_ON); + else lv_slider_set_left_value(obj, lv_slider_get_left_value(obj) + 1, LV_ANIM_ON); + } + else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { + if(!slider->left_knob_focus) lv_slider_set_value(obj, lv_slider_get_value(obj) - 1, LV_ANIM_ON); + else lv_slider_set_left_value(obj, lv_slider_get_left_value(obj) - 1, LV_ANIM_ON); + } + else { + return; + } + + res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RESULT_OK) return; + } + else if(code == LV_EVENT_DRAW_MAIN) { + draw_knob(e); + } +} + +static void draw_knob(lv_event_t * e) +{ + lv_obj_t * obj = lv_event_get_current_target(e); + lv_slider_t * slider = (lv_slider_t *)obj; + lv_layer_t * layer = lv_event_get_layer(e); + + const bool is_rtl = LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN); + const bool is_horizontal = is_slider_horizontal(obj); + const bool is_reversed = slider->bar.val_reversed ^ (is_rtl && is_horizontal); + + lv_area_t knob_area; + int32_t knob_size; + bool is_symmetrical = lv_slider_is_symmetrical(obj); + + if(is_horizontal) { + knob_size = lv_obj_get_height(obj); + if(is_symmetrical && + slider->bar.cur_value < 0) knob_area.x1 = LV_SLIDER_KNOB_COORD(!is_reversed, slider->bar.indic_area); + else knob_area.x1 = LV_SLIDER_KNOB_COORD(is_reversed, slider->bar.indic_area); + } + else { + knob_size = lv_obj_get_width(obj); + if(is_symmetrical && + slider->bar.cur_value < 0) knob_area.y1 = LV_SLIDER_KNOB_COORD_VERTICAL(!is_reversed, slider->bar.indic_area); + else knob_area.y1 = LV_SLIDER_KNOB_COORD_VERTICAL(is_reversed, slider->bar.indic_area); + } + lv_draw_rect_dsc_t knob_rect_dsc; + lv_draw_rect_dsc_init(&knob_rect_dsc); + lv_obj_init_draw_rect_dsc(obj, LV_PART_KNOB, &knob_rect_dsc); + /* Update knob area with knob style */ + position_knob(obj, &knob_area, knob_size, is_horizontal); + /* Update right knob area with calculated knob area */ + lv_area_copy(&slider->right_knob_area, &knob_area); + + if(lv_slider_get_mode(obj) != LV_SLIDER_MODE_RANGE) { + lv_draw_rect(layer, &knob_rect_dsc, &slider->right_knob_area); + } + else { + /*Save the draw part_draw_dsc. because it can be modified in the event*/ + lv_draw_rect_dsc_t knob_rect_dsc_tmp; + lv_memcpy(&knob_rect_dsc_tmp, &knob_rect_dsc, sizeof(lv_draw_rect_dsc_t)); + /* Draw the right knob */ + lv_draw_rect(layer, &knob_rect_dsc, &slider->right_knob_area); + + /*Calculate the second knob area*/ + if(is_horizontal) { + /*use !is_reversed to get the other knob*/ + knob_area.x1 = LV_SLIDER_KNOB_COORD(!is_reversed, slider->bar.indic_area); + } + else { + knob_area.y1 = LV_SLIDER_KNOB_COORD_VERTICAL(!is_reversed, slider->bar.indic_area); + } + position_knob(obj, &knob_area, knob_size, is_horizontal); + lv_area_copy(&slider->left_knob_area, &knob_area); + + lv_memcpy(&knob_rect_dsc, &knob_rect_dsc_tmp, sizeof(lv_draw_rect_dsc_t)); + + lv_draw_rect(layer, &knob_rect_dsc, &slider->left_knob_area); + } +} + +static void position_knob(lv_obj_t * obj, lv_area_t * knob_area, const int32_t knob_size, const bool hor) +{ + if(hor) { + knob_area->x1 -= (knob_size >> 1); + knob_area->x2 = knob_area->x1 + knob_size - 1; + knob_area->y1 = obj->coords.y1; + knob_area->y2 = obj->coords.y2; + } + else { + knob_area->y1 -= (knob_size >> 1); + knob_area->y2 = knob_area->y1 + knob_size - 1; + knob_area->x1 = obj->coords.x1; + knob_area->x2 = obj->coords.x2; + } + + int32_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); + int32_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); + int32_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); + int32_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); + + int32_t transf_w = lv_obj_get_style_transform_width(obj, LV_PART_KNOB); + int32_t transf_h = lv_obj_get_style_transform_height(obj, LV_PART_KNOB); + + /*Apply the paddings on the knob area*/ + knob_area->x1 -= knob_left + transf_w; + knob_area->x2 += knob_right + transf_w; + knob_area->y1 -= knob_top + transf_h; + knob_area->y2 += knob_bottom + transf_h; +} + +static bool is_slider_horizontal(lv_obj_t * obj) +{ + return lv_obj_get_width(obj) >= lv_obj_get_height(obj); +} + +static void drag_start(lv_obj_t * obj) +{ + lv_slider_t * slider = (lv_slider_t *)obj; + lv_slider_mode_t mode = lv_slider_get_mode(obj); + lv_point_t p; + slider->dragging = true; + if(mode == LV_SLIDER_MODE_NORMAL || mode == LV_SLIDER_MODE_SYMMETRICAL) { + slider->value_to_set = &slider->bar.cur_value; + } + else if(mode == LV_SLIDER_MODE_RANGE) { + lv_indev_get_point(lv_indev_active(), &p); + lv_obj_transform_point(obj, &p, true, true); + const bool is_rtl = LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN); + const bool is_horizontal = is_slider_horizontal(obj); + const bool is_reversed = slider->bar.val_reversed ^ (is_rtl && is_horizontal); + int32_t dist_left, dist_right; + if(is_horizontal) { + if((!is_reversed && p.x > slider->right_knob_area.x2) || (is_reversed && p.x < slider->right_knob_area.x1)) { + slider->value_to_set = &slider->bar.cur_value; + } + else if((!is_reversed && p.x < slider->left_knob_area.x1) || (is_reversed && p.x > slider->left_knob_area.x2)) { + slider->value_to_set = &slider->bar.start_value; + } + else { + /*Calculate the distance from each knob*/ + dist_left = LV_ABS((slider->left_knob_area.x1 + (slider->left_knob_area.x2 - slider->left_knob_area.x1) / 2) - p.x); + dist_right = LV_ABS((slider->right_knob_area.x1 + (slider->right_knob_area.x2 - slider->right_knob_area.x1) / 2) - p.x); + /*Use whichever one is closer*/ + if(dist_right < dist_left) { + slider->value_to_set = &slider->bar.cur_value; + slider->left_knob_focus = 0; + } + else { + slider->value_to_set = &slider->bar.start_value; + slider->left_knob_focus = 1; + } + } + } + else { + if((!is_reversed && p.y < slider->right_knob_area.y1) || (is_reversed && p.y > slider->right_knob_area.y2)) { + slider->value_to_set = &slider->bar.cur_value; + } + else if((!is_reversed && p.y > slider->left_knob_area.y2) || (is_reversed && p.y < slider->left_knob_area.y1)) { + slider->value_to_set = &slider->bar.start_value; + } + else { + /*Calculate the distance from each knob*/ + dist_left = LV_ABS((slider->left_knob_area.y1 + (slider->left_knob_area.y2 - slider->left_knob_area.y1) / 2) - p.y); + dist_right = LV_ABS((slider->right_knob_area.y1 + (slider->right_knob_area.y2 - slider->right_knob_area.y1) / 2) - p.y); + + /*Use whichever one is closer*/ + if(dist_right < dist_left) { + slider->value_to_set = &slider->bar.cur_value; + slider->left_knob_focus = 0; + } + else { + slider->value_to_set = &slider->bar.start_value; + slider->left_knob_focus = 1; + } + } + } + } +} + +static void update_knob_pos(lv_obj_t * obj, bool check_drag) +{ + lv_slider_t * slider = (lv_slider_t *)obj; + lv_indev_t * indev = lv_indev_active(); + if(lv_indev_get_type(indev) != LV_INDEV_TYPE_POINTER) + return; + if(lv_indev_get_scroll_obj(indev) != NULL) + return; + + lv_point_t p; + lv_indev_get_point(indev, &p); + lv_obj_transform_point(obj, &p, true, true); + + bool is_hor = is_slider_horizontal(obj); + + if(check_drag && !slider->dragging) { + int32_t ofs = is_hor ? (p.x - slider->pressed_point.x) : (p.y - slider->pressed_point.y); + + /*Stop processing when offset is below scroll_limit*/ + if(LV_ABS(ofs) < indev->scroll_limit) { + return; + } + } + + if(!slider->value_to_set) { + /*Ready to start drag*/ + drag_start(obj); + } + + int32_t new_value = 0; + const int32_t range = slider->bar.max_value - slider->bar.min_value; + const bool is_rtl = LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN); + const bool is_horizontal = is_slider_horizontal(obj); + const bool is_reversed = slider->bar.val_reversed ^ (is_rtl && is_horizontal); + + if(is_hor) { + const int32_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + const int32_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + const int32_t w = lv_obj_get_width(obj); + const int32_t indic_w = w - bg_left - bg_right; + + if(is_reversed) { + /*Make the point relative to the indicator*/ + new_value = (obj->coords.x2 - bg_right) - p.x; + } + else { + /*Make the point relative to the indicator*/ + new_value = p.x - (obj->coords.x1 + bg_left); + } + if(indic_w) { + new_value = (new_value * range + indic_w / 2) / indic_w; + new_value += slider->bar.min_value; + } + } + else { + const int32_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + const int32_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + const int32_t h = lv_obj_get_height(obj); + const int32_t indic_h = h - bg_bottom - bg_top; + + if(is_reversed) { + /*Make the point relative to the indicator*/ + new_value = p.y - (obj->coords.y1 + bg_top); + } + else { + /*Make the point relative to the indicator*/ + new_value = p.y - (obj->coords.y2 + bg_bottom); + new_value = -new_value; + } + new_value = (new_value * range + indic_h / 2) / indic_h; + new_value += slider->bar.min_value; + } + + int32_t real_max_value = slider->bar.max_value; + int32_t real_min_value = slider->bar.min_value; + /*Figure out the min. and max. for this mode*/ + if(slider->value_to_set == &slider->bar.start_value) { + real_max_value = slider->bar.cur_value; + } + else { + real_min_value = slider->bar.start_value; + } + + new_value = LV_CLAMP(real_min_value, new_value, real_max_value); + if(*slider->value_to_set != new_value) { + *slider->value_to_set = new_value; + if(is_hor) + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN_VER); + else + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN_HOR); + + lv_obj_invalidate(obj); + lv_result_t res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RESULT_OK) + return; + } +} + +#endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.h b/lib/libesp32_lvgl/lvgl/src/widgets/slider/lv_slider.h similarity index 89% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.h rename to lib/libesp32_lvgl/lvgl/src/widgets/slider/lv_slider.h index 386950ce1..6c83c14f0 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_slider.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/slider/lv_slider.h @@ -13,7 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../lv_conf_internal.h" +#include "../bar/lv_bar.h" #if LV_USE_SLIDER != 0 @@ -22,9 +22,6 @@ extern "C" { #error "lv_slider: lv_bar is required. Enable it in lv_conf.h (LV_USE_BAR 1)" #endif -#include "../core/lv_obj.h" -#include "lv_bar.h" - /********************* * DEFINES *********************/ @@ -32,33 +29,29 @@ extern "C" { /********************** * TYPEDEFS **********************/ - -enum { +enum _lv_slider_mode_t { LV_SLIDER_MODE_NORMAL = LV_BAR_MODE_NORMAL, LV_SLIDER_MODE_SYMMETRICAL = LV_BAR_MODE_SYMMETRICAL, LV_SLIDER_MODE_RANGE = LV_BAR_MODE_RANGE }; + +#ifdef DOXYGEN +typedef _lv_slider_mode_t lv_slider_mode_t; +#else typedef uint8_t lv_slider_mode_t; +#endif /*DOXYGEN*/ typedef struct { lv_bar_t bar; /*Add the ancestor's type first*/ lv_area_t left_knob_area; lv_area_t right_knob_area; + lv_point_t pressed_point; int32_t * value_to_set; /*Which bar value to set*/ uint8_t dragging : 1; /*1: the slider is being dragged*/ uint8_t left_knob_focus : 1; /*1: with encoder now the right knob can be adjusted*/ } lv_slider_t; -extern const lv_obj_class_t lv_slider_class; - -/** - * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_slider_class` - * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` - */ -typedef enum { - LV_SLIDER_DRAW_PART_KNOB, /**< The main (right) knob's rectangle*/ - LV_SLIDER_DRAW_PART_KNOB_LEFT, /**< The left knob's rectangle*/ -} lv_slider_draw_part_type_t; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_slider_class; /********************** * GLOBAL PROTOTYPES @@ -171,7 +164,7 @@ bool lv_slider_is_dragged(const lv_obj_t * obj); /** * Get the mode of the slider. - * @param obj pointer to a bar object + * @param slider pointer to a slider object * @return see ::lv_slider_mode_t */ static inline lv_slider_mode_t lv_slider_get_mode(lv_obj_t * slider) @@ -182,6 +175,16 @@ static inline lv_slider_mode_t lv_slider_get_mode(lv_obj_t * slider) else return LV_SLIDER_MODE_NORMAL; } +/** + * Give the slider is in symmetrical mode or not + * @param obj pointer to slider object + * @return true: in symmetrical mode false : not in +*/ +static inline bool lv_slider_is_symmetrical(lv_obj_t * obj) +{ + return lv_bar_is_symmetrical(obj); +} + /********************** * MACROS **********************/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.c b/lib/libesp32_lvgl/lvgl/src/widgets/span/lv_span.c similarity index 73% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.c rename to lib/libesp32_lvgl/lvgl/src/widgets/span/lv_span.c index 6f970c54e..539c94d1d 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/span/lv_span.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/span/lv_span.c @@ -10,12 +10,14 @@ #if LV_USE_SPAN != 0 -#include "../../../misc/lv_assert.h" +#include "../../misc/lv_assert.h" +#include "../../core/lv_global.h" /********************* * DEFINES *********************/ #define MY_CLASS &lv_spangroup_class +#define snippet_stack LV_GLOBAL_DEFAULT()->span_snippet_stack /********************** * TYPEDEFS @@ -24,15 +26,15 @@ typedef struct { lv_span_t * span; const char * txt; const lv_font_t * font; - uint16_t bytes; - lv_coord_t txt_w; - lv_coord_t line_h; - lv_coord_t letter_space; + uint32_t bytes; + int32_t txt_w; + int32_t line_h; + int32_t letter_space; } lv_snippet_t; struct _snippet_stack { lv_snippet_t stack[LV_SPAN_SNIPPET_STACK_SIZE]; - uint16_t index; + uint32_t index; }; /********************** @@ -45,28 +47,27 @@ static void draw_main(lv_event_t * e); static void refresh_self_size(lv_obj_t * obj); static const lv_font_t * lv_span_get_style_text_font(lv_obj_t * par, lv_span_t * span); -static lv_coord_t lv_span_get_style_text_letter_space(lv_obj_t * par, lv_span_t * span); +static int32_t lv_span_get_style_text_letter_space(lv_obj_t * par, lv_span_t * span); static lv_color_t lv_span_get_style_text_color(lv_obj_t * par, lv_span_t * span); static lv_opa_t lv_span_get_style_text_opa(lv_obj_t * par, lv_span_t * span); static lv_opa_t lv_span_get_style_text_blend_mode(lv_obj_t * par, lv_span_t * span); static int32_t lv_span_get_style_text_decor(lv_obj_t * par, lv_span_t * span); static inline void span_text_check(const char ** text); -static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx); -static bool lv_txt_get_snippet(const char * txt, const lv_font_t * font, lv_coord_t letter_space, - lv_coord_t max_width, lv_text_flag_t flag, lv_coord_t * use_width, - uint32_t * end_ofs); +static void lv_draw_span(lv_obj_t * obj, lv_layer_t * layer); +static bool lv_text_get_snippet(const char * txt, const lv_font_t * font, int32_t letter_space, + int32_t max_width, lv_text_flag_t flag, int32_t * use_width, + uint32_t * end_ofs); static void lv_snippet_clear(void); -static uint16_t lv_get_snippet_cnt(void); +static uint32_t lv_get_snippet_count(void); static void lv_snippet_push(lv_snippet_t * item); -static lv_snippet_t * lv_get_snippet(uint16_t index); -static lv_coord_t convert_indent_pct(lv_obj_t * spans, lv_coord_t width); +static lv_snippet_t * lv_get_snippet(uint32_t index); +static int32_t convert_indent_pct(lv_obj_t * spans, int32_t width); /********************** * STATIC VARIABLES **********************/ -static struct _snippet_stack snippet_stack; const lv_obj_class_t lv_spangroup_class = { .base_class = &lv_obj_class, @@ -76,6 +77,7 @@ const lv_obj_class_t lv_spangroup_class = { .instance_size = sizeof(lv_spangroup_t), .width_def = LV_SIZE_CONTENT, .height_def = LV_SIZE_CONTENT, + .name = "span", }; /********************** @@ -85,6 +87,19 @@ const lv_obj_class_t lv_spangroup_class = { /********************** * GLOBAL FUNCTIONS **********************/ +void lv_span_stack_init(void) +{ + struct _snippet_stack * stack = snippet_stack = lv_malloc(sizeof(struct _snippet_stack)); + LV_ASSERT_MALLOC(stack); + if(!stack) { + LV_LOG_ERROR("malloc failed for snippet_stack"); + } +} + +void lv_span_stack_deinit(void) +{ + lv_free(snippet_stack); +} lv_obj_t * lv_spangroup_create(lv_obj_t * par) { @@ -114,7 +129,7 @@ lv_span_t * lv_spangroup_new_span(lv_obj_t * obj) return span; } -void lv_spangroup_del_span(lv_obj_t * obj, lv_span_t * span) +void lv_spangroup_delete_span(lv_obj_t * obj, lv_span_t * span) { if(obj == NULL || span == NULL) { return; @@ -127,10 +142,12 @@ void lv_spangroup_del_span(lv_obj_t * obj, lv_span_t * span) if(cur_span == span) { _lv_ll_remove(&spans->child_ll, cur_span); if(cur_span->txt && cur_span->static_flag == 0) { - lv_mem_free(cur_span->txt); + lv_free(cur_span->txt); + cur_span->txt = NULL; } lv_style_reset(&cur_span->style); - lv_mem_free(cur_span); + lv_free(cur_span); + cur_span = NULL; break; } } @@ -148,14 +165,21 @@ void lv_span_set_text(lv_span_t * span, const char * text) return; } + size_t text_alloc_len = lv_strlen(text) + 1; + if(span->txt == NULL || span->static_flag == 1) { - span->txt = lv_mem_alloc(strlen(text) + 1); + span->txt = lv_malloc(text_alloc_len); + LV_ASSERT_MALLOC(span->txt); } else { - span->txt = lv_mem_realloc(span->txt, strlen(text) + 1); + span->txt = lv_realloc(span->txt, text_alloc_len); + LV_ASSERT_MALLOC(span->txt); } + + if(span->txt == NULL) return; + span->static_flag = 0; - strcpy(span->txt, text); + lv_memcpy(span->txt, text, text_alloc_len); refresh_self_size(span->spangroup); } @@ -167,7 +191,8 @@ void lv_span_set_text_static(lv_span_t * span, const char * text) } if(span->txt && span->static_flag == 0) { - lv_mem_free(span->txt); + lv_free(span->txt); + span->txt = NULL; } span->static_flag = 1; span->txt = (char *)text; @@ -185,12 +210,12 @@ void lv_spangroup_set_overflow(lv_obj_t * obj, lv_span_overflow_t overflow) LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; if(spans->overflow == overflow) return; - + if(overflow >= _LV_SPAN_OVERFLOW_LAST) return; spans->overflow = overflow; lv_obj_invalidate(obj); } -void lv_spangroup_set_indent(lv_obj_t * obj, lv_coord_t indent) +void lv_spangroup_set_indent(lv_obj_t * obj, int32_t indent) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; @@ -205,11 +230,14 @@ void lv_spangroup_set_mode(lv_obj_t * obj, lv_span_mode_t mode) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; + + if(mode >= _LV_SPAN_MODE_LAST) return; + spans->mode = mode; lv_spangroup_refr_mode(obj); } -void lv_spangroup_set_lines(lv_obj_t * obj, int32_t lines) +void lv_spangroup_set_max_lines(lv_obj_t * obj, int32_t lines) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; @@ -258,7 +286,7 @@ lv_span_t * lv_spangroup_get_child(const lv_obj_t * obj, int32_t id) return NULL; } -uint32_t lv_spangroup_get_child_cnt(const lv_obj_t * obj) +uint32_t lv_spangroup_get_span_count(const lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -283,7 +311,7 @@ lv_span_overflow_t lv_spangroup_get_overflow(lv_obj_t * obj) return spans->overflow; } -lv_coord_t lv_spangroup_get_indent(lv_obj_t * obj) +int32_t lv_spangroup_get_indent(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; @@ -297,7 +325,7 @@ lv_span_mode_t lv_spangroup_get_mode(lv_obj_t * obj) return spans->mode; } -int32_t lv_spangroup_get_lines(lv_obj_t * obj) +int32_t lv_spangroup_get_max_lines(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; @@ -326,11 +354,11 @@ void lv_spangroup_refr_mode(lv_obj_t * obj) lv_obj_set_width(obj, 100); } if(lv_obj_get_style_height(obj, LV_PART_MAIN) == LV_SIZE_CONTENT) { - lv_coord_t width = lv_obj_get_style_width(obj, LV_PART_MAIN); + int32_t width = lv_obj_get_style_width(obj, LV_PART_MAIN); if(LV_COORD_IS_PCT(width)) { width = 100; } - lv_coord_t height = lv_spangroup_get_expand_height(obj, width); + int32_t height = lv_spangroup_get_expand_height(obj, width); lv_obj_set_content_height(obj, height); } } @@ -338,16 +366,16 @@ void lv_spangroup_refr_mode(lv_obj_t * obj) refresh_self_size(obj); } -lv_coord_t lv_spangroup_get_max_line_h(lv_obj_t * obj) +int32_t lv_spangroup_get_max_line_height(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; - lv_coord_t max_line_h = 0; + int32_t max_line_h = 0; lv_span_t * cur_span; _LV_LL_READ(&spans->child_ll, cur_span) { const lv_font_t * font = lv_span_get_style_text_font(obj, cur_span); - lv_coord_t line_h = lv_font_get_line_height(font); + int32_t line_h = lv_font_get_line_height(font); if(line_h > max_line_h) { max_line_h = line_h; } @@ -367,7 +395,7 @@ uint32_t lv_spangroup_get_expand_width(lv_obj_t * obj, uint32_t max_width) uint32_t width = LV_COORD_IS_PCT(spans->indent) ? 0 : spans->indent; lv_span_t * cur_span; - lv_coord_t letter_space = 0; + int32_t letter_space = 0; _LV_LL_READ(&spans->child_ll, cur_span) { const lv_font_t * font = lv_span_get_style_text_font(obj, cur_span); letter_space = lv_span_get_style_text_letter_space(obj, cur_span); @@ -378,9 +406,9 @@ uint32_t lv_spangroup_get_expand_width(lv_obj_t * obj, uint32_t max_width) if(max_width > 0 && width >= max_width) { return max_width; } - uint32_t letter = _lv_txt_encoded_next(cur_txt, &j); - uint32_t letter_next = _lv_txt_encoded_next(&cur_txt[j], NULL); - uint16_t letter_w = lv_font_get_glyph_width(font, letter, letter_next); + uint32_t letter = _lv_text_encoded_next(cur_txt, &j); + uint32_t letter_next = _lv_text_encoded_next(&cur_txt[j], NULL); + uint32_t letter_w = lv_font_get_glyph_width(font, letter, letter_next); width = width + letter_w + letter_space; } } @@ -388,7 +416,7 @@ uint32_t lv_spangroup_get_expand_width(lv_obj_t * obj, uint32_t max_width) return width - letter_space; } -lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width) +int32_t lv_spangroup_get_expand_height(lv_obj_t * obj, int32_t width) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spangroup_t * spans = (lv_spangroup_t *)obj; @@ -398,15 +426,14 @@ lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width) /* init draw variable */ lv_text_flag_t txt_flag = LV_TEXT_FLAG_NONE; - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - lv_coord_t max_width = width; - lv_coord_t indent = convert_indent_pct(obj, max_width); - lv_coord_t max_w = max_width - indent; /* first line need minus indent */ + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + int32_t max_width = width; + int32_t indent = convert_indent_pct(obj, max_width); + int32_t max_w = max_width - indent; /* first line need minus indent */ /* coords of draw span-txt */ lv_point_t txt_pos; - txt_pos.y = 0; - txt_pos.x = 0 + indent; /* first line need add indent */ + lv_point_set(&txt_pos, 0, indent); /* first line need add indent */ lv_span_t * cur_span = _lv_ll_get_head(&spans->child_ll); const char * cur_txt = cur_span->txt; @@ -420,7 +447,7 @@ lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width) /* the loop control how many lines need to draw */ while(cur_span) { int snippet_cnt = 0; - lv_coord_t max_line_h = 0; /* the max height of span-font when a line have a lot of span */ + int32_t max_line_h = 0; /* the max height of span-font when a line have a lot of span */ /* the loop control to find a line and push the relevant span info into stack */ while(1) { @@ -445,9 +472,9 @@ lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width) /* get current span text line info */ uint32_t next_ofs = 0; - lv_coord_t use_width = 0; - bool isfill = lv_txt_get_snippet(&cur_txt[cur_txt_ofs], snippet.font, snippet.letter_space, - max_w, txt_flag, &use_width, &next_ofs); + int32_t use_width = 0; + bool isfill = lv_text_get_snippet(&cur_txt[cur_txt_ofs], snippet.font, snippet.letter_space, + max_w, txt_flag, &use_width, &next_ofs); /* break word deal width */ if(isfill && next_ofs > 0 && snippet_cnt > 0) { @@ -456,11 +483,11 @@ lv_coord_t lv_spangroup_get_expand_height(lv_obj_t * obj, lv_coord_t width) } uint32_t tmp_ofs = next_ofs; - uint32_t letter = _lv_txt_encoded_prev(&cur_txt[cur_txt_ofs], &tmp_ofs); - if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_txt_is_break_char(letter))) { + uint32_t letter = _lv_text_encoded_prev(&cur_txt[cur_txt_ofs], &tmp_ofs); + if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_text_is_break_char(letter))) { tmp_ofs = 0; - letter = _lv_txt_encoded_next(&cur_txt[cur_txt_ofs + next_ofs], &tmp_ofs); - if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_txt_is_break_char(letter))) { + letter = _lv_text_encoded_next(&cur_txt[cur_txt_ofs + next_ofs], &tmp_ofs); + if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_text_is_break_char(letter))) { break; } } @@ -520,10 +547,11 @@ static void lv_spangroup_destructor(const lv_obj_class_t * class_p, lv_obj_t * o while(cur_span) { _lv_ll_remove(&spans->child_ll, cur_span); if(cur_span->txt && cur_span->static_flag == 0) { - lv_mem_free(cur_span->txt); + lv_free(cur_span->txt); + cur_span->txt = NULL; } lv_style_reset(&cur_span->style); - lv_mem_free(cur_span); + lv_free(cur_span); cur_span = _lv_ll_get_head(&spans->child_ll); } } @@ -533,10 +561,10 @@ static void lv_spangroup_event(const lv_obj_class_t * class_p, lv_event_t * e) LV_UNUSED(class_p); /* Call the ancestor's event handler */ - if(lv_obj_event_base(MY_CLASS, e) != LV_RES_OK) return; + if(lv_obj_event_base(MY_CLASS, e) != LV_RESULT_OK) return; lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_spangroup_t * spans = (lv_spangroup_t *)obj; if(code == LV_EVENT_DRAW_MAIN) { @@ -549,14 +577,14 @@ static void lv_spangroup_event(const lv_obj_class_t * class_p, lv_event_t * e) refresh_self_size(obj); } else if(code == LV_EVENT_GET_SELF_SIZE) { - lv_coord_t width = 0; - lv_coord_t height = 0; + int32_t width = 0; + int32_t height = 0; lv_point_t * self_size = lv_event_get_param(e); if(spans->mode == LV_SPAN_MODE_EXPAND) { if(spans->refresh) { - spans->cache_w = (lv_coord_t)lv_spangroup_get_expand_width(obj, 0); - spans->cache_h = lv_spangroup_get_max_line_h(obj); + spans->cache_w = (int32_t)lv_spangroup_get_expand_width(obj, 0); + spans->cache_h = lv_spangroup_get_max_line_height(obj); spans->refresh = 0; } width = spans->cache_w; @@ -587,18 +615,18 @@ static void lv_spangroup_event(const lv_obj_class_t * class_p, lv_event_t * e) static void draw_main(lv_event_t * e) { - lv_obj_t * obj = lv_event_get_target(e); - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_obj_t * obj = lv_event_get_current_target(e); + lv_layer_t * layer = lv_event_get_layer(e); - lv_draw_span(obj, draw_ctx); + lv_draw_span(obj, layer); } /** * @return true for txt fill the max_width. */ -static bool lv_txt_get_snippet(const char * txt, const lv_font_t * font, - lv_coord_t letter_space, lv_coord_t max_width, lv_text_flag_t flag, - lv_coord_t * use_width, uint32_t * end_ofs) +static bool lv_text_get_snippet(const char * txt, const lv_font_t * font, + int32_t letter_space, int32_t max_width, lv_text_flag_t flag, + int32_t * use_width, uint32_t * end_ofs) { if(txt == NULL || txt[0] == '\0') { *end_ofs = 0; @@ -606,7 +634,14 @@ static bool lv_txt_get_snippet(const char * txt, const lv_font_t * font, return false; } - uint32_t ofs = _lv_txt_get_next_line(txt, font, letter_space, max_width, use_width, flag); + int32_t real_max_width = max_width; +#if !LV_USE_FONT_PLACEHOLDER + /* fix incomplete text display when disable the placeholder. */ + /* workaround by: https://github.com/lvgl/lvgl/issues/3685 */ + real_max_width++; +#endif + + uint32_t ofs = _lv_text_get_next_line(txt, font, letter_space, real_max_width, use_width, flag); *end_ofs = ofs; if(txt[ofs] == '\0' && *use_width < max_width) { @@ -619,36 +654,37 @@ static bool lv_txt_get_snippet(const char * txt, const lv_font_t * font, static void lv_snippet_push(lv_snippet_t * item) { - if(snippet_stack.index < LV_SPAN_SNIPPET_STACK_SIZE) { - memcpy(&snippet_stack.stack[snippet_stack.index], item, sizeof(lv_snippet_t)); - snippet_stack.index++; + struct _snippet_stack * stack_p = snippet_stack; + if(stack_p->index < LV_SPAN_SNIPPET_STACK_SIZE) { + memcpy(&stack_p->stack[stack_p->index], item, sizeof(lv_snippet_t)); + stack_p->index++; } else { LV_LOG_ERROR("span draw stack overflow, please set LV_SPAN_SNIPPET_STACK_SIZE too larger"); } } -static uint16_t lv_get_snippet_cnt(void) +static uint32_t lv_get_snippet_count(void) { - return snippet_stack.index; + return snippet_stack->index; } -static lv_snippet_t * lv_get_snippet(uint16_t index) +static lv_snippet_t * lv_get_snippet(uint32_t index) { - return &snippet_stack.stack[index]; + return &snippet_stack->stack[index]; } static void lv_snippet_clear(void) { - snippet_stack.index = 0; + snippet_stack->index = 0; } static const lv_font_t * lv_span_get_style_text_font(lv_obj_t * par, lv_span_t * span) { const lv_font_t * font; lv_style_value_t value; - lv_res_t res = lv_style_get_prop(&span->style, LV_STYLE_TEXT_FONT, &value); - if(res != LV_RES_OK) { + lv_result_t res = lv_style_get_prop(&span->style, LV_STYLE_TEXT_FONT, &value); + if(res != LV_RESULT_OK) { font = lv_obj_get_style_text_font(par, LV_PART_MAIN); } else { @@ -657,16 +693,16 @@ static const lv_font_t * lv_span_get_style_text_font(lv_obj_t * par, lv_span_t * return font; } -static lv_coord_t lv_span_get_style_text_letter_space(lv_obj_t * par, lv_span_t * span) +static int32_t lv_span_get_style_text_letter_space(lv_obj_t * par, lv_span_t * span) { - lv_coord_t letter_space; + int32_t letter_space; lv_style_value_t value; - lv_res_t res = lv_style_get_prop(&span->style, LV_STYLE_TEXT_LETTER_SPACE, &value); - if(res != LV_RES_OK) { + lv_result_t res = lv_style_get_prop(&span->style, LV_STYLE_TEXT_LETTER_SPACE, &value); + if(res != LV_RESULT_OK) { letter_space = lv_obj_get_style_text_letter_space(par, LV_PART_MAIN); } else { - letter_space = (lv_coord_t)value.num; + letter_space = (int32_t)value.num; } return letter_space; } @@ -674,8 +710,8 @@ static lv_coord_t lv_span_get_style_text_letter_space(lv_obj_t * par, lv_span_t static lv_color_t lv_span_get_style_text_color(lv_obj_t * par, lv_span_t * span) { lv_style_value_t value; - lv_res_t res = lv_style_get_prop(&span->style, LV_STYLE_TEXT_COLOR, &value); - if(res != LV_RES_OK) { + lv_result_t res = lv_style_get_prop(&span->style, LV_STYLE_TEXT_COLOR, &value); + if(res != LV_RESULT_OK) { value.color = lv_obj_get_style_text_color(par, LV_PART_MAIN); } return value.color; @@ -685,8 +721,8 @@ static lv_opa_t lv_span_get_style_text_opa(lv_obj_t * par, lv_span_t * span) { lv_opa_t opa; lv_style_value_t value; - lv_res_t res = lv_style_get_prop(&span->style, LV_STYLE_TEXT_OPA, &value); - if(res != LV_RES_OK) { + lv_result_t res = lv_style_get_prop(&span->style, LV_STYLE_TEXT_OPA, &value); + if(res != LV_RESULT_OK) { opa = (lv_opa_t)lv_obj_get_style_text_opa(par, LV_PART_MAIN); } else { @@ -699,8 +735,8 @@ static lv_blend_mode_t lv_span_get_style_text_blend_mode(lv_obj_t * par, lv_span { lv_blend_mode_t mode; lv_style_value_t value; - lv_res_t res = lv_style_get_prop(&span->style, LV_STYLE_BLEND_MODE, &value); - if(res != LV_RES_OK) { + lv_result_t res = lv_style_get_prop(&span->style, LV_STYLE_BLEND_MODE, &value); + if(res != LV_RESULT_OK) { mode = (lv_blend_mode_t)lv_obj_get_style_blend_mode(par, LV_PART_MAIN); } else { @@ -713,8 +749,8 @@ static int32_t lv_span_get_style_text_decor(lv_obj_t * par, lv_span_t * span) { int32_t decor; lv_style_value_t value; - lv_res_t res = lv_style_get_prop(&span->style, LV_STYLE_TEXT_DECOR, &value); - if(res != LV_RES_OK) { + lv_result_t res = lv_style_get_prop(&span->style, LV_STYLE_TEXT_DECOR, &value); + if(res != LV_RESULT_OK) { decor = (lv_text_decor_t)lv_obj_get_style_text_decor(par, LV_PART_MAIN);; } else { @@ -731,11 +767,11 @@ static inline void span_text_check(const char ** text) } } -static lv_coord_t convert_indent_pct(lv_obj_t * obj, lv_coord_t width) +static int32_t convert_indent_pct(lv_obj_t * obj, int32_t width) { lv_spangroup_t * spans = (lv_spangroup_t *)obj; - lv_coord_t indent = spans->indent; + int32_t indent = spans->indent; if(LV_COORD_IS_PCT(spans->indent)) { if(spans->mode == LV_SPAN_MODE_EXPAND) { indent = 0; @@ -754,7 +790,7 @@ static lv_coord_t convert_indent_pct(lv_obj_t * obj, lv_coord_t width) * @param coords coordinates of the label * @param mask the label will be drawn only in this area */ -static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) +static void lv_draw_span(lv_obj_t * obj, lv_layer_t * layer) { lv_area_t coords; @@ -769,16 +805,16 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) /* return if no draw area */ lv_area_t clip_area; - if(!_lv_area_intersect(&clip_area, &coords, draw_ctx->clip_area)) return; - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &clip_area; + if(!_lv_area_intersect(&clip_area, &coords, &layer->_clip_area)) return; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area; /* init draw variable */ lv_text_flag_t txt_flag = LV_TEXT_FLAG_NONE; - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN);; - lv_coord_t max_width = lv_area_get_width(&coords); - lv_coord_t indent = convert_indent_pct(obj, max_width); - lv_coord_t max_w = max_width - indent; /* first line need minus indent */ + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN);; + int32_t max_width = lv_area_get_width(&coords); + int32_t indent = convert_indent_pct(obj, max_width); + int32_t max_w = max_width - indent; /* first line need minus indent */ lv_opa_t obj_opa = lv_obj_get_style_opa_recursive(obj, LV_PART_MAIN); /* coords of draw span-txt */ @@ -791,7 +827,7 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) span_text_check(&cur_txt); uint32_t cur_txt_ofs = 0; lv_snippet_t snippet; /* use to save cur_span info and push it to stack */ - lv_memset_00(&snippet, sizeof(snippet)); + lv_memzero(&snippet, sizeof(snippet)); lv_draw_label_dsc_t label_draw_dsc; lv_draw_label_dsc_init(&label_draw_dsc); @@ -801,8 +837,8 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) while(cur_span) { bool is_end_line = false; bool ellipsis_valid = false; - lv_coord_t max_line_h = 0; /* the max height of span-font when a line have a lot of span */ - lv_coord_t max_baseline = 0; /*baseline of the highest span*/ + int32_t max_line_h = 0; /* the max height of span-font when a line have a lot of span */ + int32_t max_baseline = 0; /*baseline of the highest span*/ lv_snippet_clear(); /* the loop control to find a line and push the relevant span info into stack */ @@ -828,23 +864,23 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) /* get current span text line info */ uint32_t next_ofs = 0; - lv_coord_t use_width = 0; - bool isfill = lv_txt_get_snippet(&cur_txt[cur_txt_ofs], snippet.font, snippet.letter_space, - max_w, txt_flag, &use_width, &next_ofs); + int32_t use_width = 0; + bool isfill = lv_text_get_snippet(&cur_txt[cur_txt_ofs], snippet.font, snippet.letter_space, + max_w, txt_flag, &use_width, &next_ofs); if(isfill) { - if(next_ofs > 0 && lv_get_snippet_cnt() > 0) { - /* To prevent infinite loops, the _lv_txt_get_next_line() may return incomplete words, */ - /* This phenomenon should be avoided when lv_get_snippet_cnt() > 0 */ + if(next_ofs > 0 && lv_get_snippet_count() > 0) { + /* To prevent infinite loops, the _lv_text_get_next_line() may return incomplete words, */ + /* This phenomenon should be avoided when lv_get_snippet_count() > 0 */ if(max_w < use_width) { break; } uint32_t tmp_ofs = next_ofs; - uint32_t letter = _lv_txt_encoded_prev(&cur_txt[cur_txt_ofs], &tmp_ofs); - if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_txt_is_break_char(letter))) { + uint32_t letter = _lv_text_encoded_prev(&cur_txt[cur_txt_ofs], &tmp_ofs); + if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_text_is_break_char(letter))) { tmp_ofs = 0; - letter = _lv_txt_encoded_next(&cur_txt[cur_txt_ofs + next_ofs], &tmp_ofs); - if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_txt_is_break_char(letter))) { + letter = _lv_text_encoded_next(&cur_txt[cur_txt_ofs + next_ofs], &tmp_ofs); + if(!(letter == '\0' || letter == '\n' || letter == '\r' || _lv_text_is_break_char(letter))) { break; } } @@ -869,7 +905,7 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) /* start current line deal with */ - uint16_t item_cnt = lv_get_snippet_cnt(); + uint32_t item_cnt = lv_get_snippet_count(); if(item_cnt == 0) { /* break if stack is empty */ break; } @@ -877,7 +913,7 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) /* Whether the current line is the end line and does overflow processing */ { lv_snippet_t * last_snippet = lv_get_snippet(item_cnt - 1); - lv_coord_t next_line_h = last_snippet->line_h; + int32_t next_line_h = last_snippet->line_h; if(last_snippet->txt[last_snippet->bytes] == '\0') { next_line_h = 0; lv_span_t * next_span = _lv_ll_get_next(&spans->child_ll, last_snippet->span); @@ -887,11 +923,11 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) } if(txt_pos.y + max_line_h + next_line_h - line_space > coords.y2 + 1) { /* for overflow if is end line. */ if(last_snippet->txt[last_snippet->bytes] != '\0') { - last_snippet->bytes = strlen(last_snippet->txt); - last_snippet->txt_w = lv_txt_get_width(last_snippet->txt, last_snippet->bytes, last_snippet->font, - last_snippet->letter_space, txt_flag); + last_snippet->bytes = lv_strlen(last_snippet->txt); + last_snippet->txt_w = lv_text_get_width(last_snippet->txt, last_snippet->bytes, last_snippet->font, + last_snippet->letter_space); } - ellipsis_valid = spans->overflow == LV_SPAN_OVERFLOW_ELLIPSIS ? true : false; + ellipsis_valid = spans->overflow == LV_SPAN_OVERFLOW_ELLIPSIS; is_end_line = true; } } @@ -904,9 +940,10 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) /* align deal with */ lv_text_align_t align = lv_obj_get_style_text_align(obj, LV_PART_MAIN); if(align == LV_TEXT_ALIGN_CENTER || align == LV_TEXT_ALIGN_RIGHT) { - lv_coord_t align_ofs = 0; - lv_coord_t txts_w = is_first_line ? indent : 0; - for(int i = 0; i < item_cnt; i++) { + int32_t align_ofs = 0; + int32_t txts_w = is_first_line ? indent : 0; + uint32_t i; + for(i = 0; i < item_cnt; i++) { lv_snippet_t * pinfo = lv_get_snippet(i); txts_w = txts_w + pinfo->txt_w + pinfo->letter_space; } @@ -919,7 +956,7 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) } /* draw line letters */ - int i; + uint32_t i; for(i = 0; i < item_cnt; i++) { lv_snippet_t * pinfo = lv_get_snippet(i); @@ -934,18 +971,18 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) label_draw_dsc.font = lv_span_get_style_text_font(obj, pinfo->span); label_draw_dsc.blend_mode = lv_span_get_style_text_blend_mode(obj, pinfo->span); if(obj_opa < LV_OPA_MAX) { - label_draw_dsc.opa = (uint16_t)((uint16_t)label_draw_dsc.opa * obj_opa) >> 8; + label_draw_dsc.opa = LV_OPA_MIX2(label_draw_dsc.opa, obj_opa); } uint32_t txt_bytes = pinfo->bytes; /* overflow */ - uint16_t dot_letter_w = 0; - uint16_t dot_width = 0; + uint32_t dot_letter_w = 0; + uint32_t dot_width = 0; if(ellipsis_valid) { dot_letter_w = lv_font_get_glyph_width(pinfo->font, '.', '.'); dot_width = dot_letter_w * 3; } - lv_coord_t ellipsis_width = coords.x1 + max_width - dot_width; + int32_t ellipsis_width = coords.x1 + max_width - dot_width; uint32_t j = 0; while(j < txt_bytes) { @@ -953,8 +990,8 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) if(pos.x > clip_area.x2) { break; } - uint32_t letter = _lv_txt_encoded_next(bidi_txt, &j); - uint32_t letter_next = _lv_txt_encoded_next(&bidi_txt[j], NULL); + uint32_t letter = _lv_text_encoded_next(bidi_txt, &j); + uint32_t letter_next = _lv_text_encoded_next(&bidi_txt[j], NULL); int32_t letter_w = lv_font_get_glyph_width(pinfo->font, letter, letter_next); /* skip invalid fields */ @@ -967,7 +1004,7 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) if(ellipsis_valid && pos.x + letter_w + pinfo->letter_space > ellipsis_width) { for(int ell = 0; ell < 3; ell++) { - lv_draw_letter(draw_ctx, &label_draw_dsc, &pos, '.'); + lv_draw_character(layer, &label_draw_dsc, &pos, '.'); pos.x = pos.x + dot_letter_w + pinfo->letter_space; } if(pos.x <= ellipsis_width) { @@ -976,7 +1013,7 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) break; } else { - lv_draw_letter(draw_ctx, &label_draw_dsc, &pos, letter); + lv_draw_character(layer, &label_draw_dsc, &pos, letter); if(letter_w > 0) { pos.x = pos.x + letter_w + pinfo->letter_space; } @@ -994,23 +1031,17 @@ static void lv_draw_span(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx) line_dsc.blend_mode = label_draw_dsc.blend_mode; if(decor & LV_TEXT_DECOR_STRIKETHROUGH) { - lv_point_t p1; - lv_point_t p2; - p1.x = txt_pos.x; - p1.y = pos.y + ((pinfo->line_h - line_space) >> 1) + (line_dsc.width >> 1); - p2.x = pos.x; - p2.y = p1.y; - lv_draw_line(draw_ctx, &line_dsc, &p1, &p2); + int32_t y = pos.y + ((pinfo->line_h - line_space) >> 1) + (line_dsc.width >> 1); + lv_point_precise_set(&line_dsc.p1, txt_pos.x, y); + lv_point_precise_set(&line_dsc.p2, pos.x, y); + lv_draw_line(layer, &line_dsc); } if(decor & LV_TEXT_DECOR_UNDERLINE) { - lv_point_t p1; - lv_point_t p2; - p1.x = txt_pos.x; - p1.y = pos.y + pinfo->line_h - line_space - pinfo->font->base_line - pinfo->font->underline_position; - p2.x = pos.x; - p2.y = p1.y; - lv_draw_line(draw_ctx, &line_dsc, &p1, &p2); + int32_t y = pos.y + pinfo->line_h - line_space - pinfo->font->base_line - pinfo->font->underline_position; + lv_point_precise_set(&line_dsc.p1, txt_pos.x, y); + lv_point_precise_set(&line_dsc.p2, pos.x, y); + lv_draw_line(layer, &line_dsc); } } txt_pos.x = pos.x; @@ -1022,12 +1053,12 @@ Next_line_init: txt_pos.x = coords.x1; txt_pos.y += max_line_h; if(is_end_line || txt_pos.y > clip_area.y2 + 1) { - draw_ctx->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; return; } max_w = max_width; } - draw_ctx->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } static void refresh_self_size(lv_obj_t * obj) diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/span/lv_span.h b/lib/libesp32_lvgl/lvgl/src/widgets/span/lv_span.h new file mode 100644 index 000000000..fe87c9ffb --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/span/lv_span.h @@ -0,0 +1,261 @@ +/** + * @file lv_span.h + * + */ + +#ifndef LV_SPAN_H +#define LV_SPAN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_SPAN != 0 + +/********************* + * DEFINES + *********************/ +#ifndef LV_SPAN_SNIPPET_STACK_SIZE +#define LV_SPAN_SNIPPET_STACK_SIZE 64 +#endif + +/********************** + * TYPEDEFS + **********************/ +enum _lv_span_overflow_t { + LV_SPAN_OVERFLOW_CLIP, + LV_SPAN_OVERFLOW_ELLIPSIS, + _LV_SPAN_OVERFLOW_LAST, /**< Fence member*/ +}; + +#ifdef DOXYGEN +typedef _lv_span_overflow_t lv_span_overflow_t; +#else +typedef uint32_t lv_span_overflow_t; +#endif /*DOXYGEN*/ + +enum _lv_span_mode_t { + LV_SPAN_MODE_FIXED, /**< fixed the obj size*/ + LV_SPAN_MODE_EXPAND, /**< Expand the object size to the text size*/ + LV_SPAN_MODE_BREAK, /**< Keep width, break the too long lines and expand height*/ + _LV_SPAN_MODE_LAST /**< Fence member*/ +}; + +#ifdef DOXYGEN +typedef _lv_span_mode_t lv_span_mode_t; +#else +typedef uint32_t lv_span_mode_t; +#endif /*DOXYGEN*/ + +typedef struct { + char * txt; /* a pointer to display text */ + lv_obj_t * spangroup; /* a pointer to spangroup */ + lv_style_t style; /* display text style */ + uint32_t static_flag : 1;/* the text is static flag */ +} lv_span_t; + +/** Data of label*/ +typedef struct { + lv_obj_t obj; + int32_t lines; + int32_t indent; /* first line indent */ + int32_t cache_w; /* the cache automatically calculates the width */ + int32_t cache_h; /* similar cache_w */ + lv_ll_t child_ll; + uint32_t mode : 2; /* details see lv_span_mode_t */ + uint32_t overflow : 1; /* details see lv_span_overflow_t */ + uint32_t refresh : 1; /* the spangroup need refresh cache_w and cache_h */ +} lv_spangroup_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_spangroup_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_span_stack_init(void); +void lv_span_stack_deinit(void); + +/** + * Create a spangroup object + * @param parent pointer to an object, it will be the parent of the new spangroup + * @return pointer to the created spangroup + */ +lv_obj_t * lv_spangroup_create(lv_obj_t * parent); + +/** + * Create a span string descriptor and add to spangroup. + * @param obj pointer to a spangroup object. + * @return pointer to the created span. + */ +lv_span_t * lv_spangroup_new_span(lv_obj_t * obj); + +/** + * Remove the span from the spangroup and free memory. + * @param obj pointer to a spangroup object. + * @param span pointer to a span. + */ +void lv_spangroup_delete_span(lv_obj_t * obj, lv_span_t * span); + +/*===================== + * Setter functions + *====================*/ + +/** + * Set a new text for a span. Memory will be allocated to store the text by the span. + * @param span pointer to a span. + * @param text pointer to a text. + */ +void lv_span_set_text(lv_span_t * span, const char * text); + +/** + * Set a static text. It will not be saved by the span so the 'text' variable + * has to be 'alive' while the span exist. + * @param span pointer to a span. + * @param text pointer to a text. + */ +void lv_span_set_text_static(lv_span_t * span, const char * text); + +/** + * Set the align of the spangroup. + * @param obj pointer to a spangroup object. + * @param align see lv_text_align_t for details. + */ +void lv_spangroup_set_align(lv_obj_t * obj, lv_text_align_t align); + +/** + * Set the overflow of the spangroup. + * @param obj pointer to a spangroup object. + * @param overflow see lv_span_overflow_t for details. + */ +void lv_spangroup_set_overflow(lv_obj_t * obj, lv_span_overflow_t overflow); + +/** + * Set the indent of the spangroup. + * @param obj pointer to a spangroup object. + * @param indent the first line indentation + */ +void lv_spangroup_set_indent(lv_obj_t * obj, int32_t indent); + +/** + * Set the mode of the spangroup. + * @param obj pointer to a spangroup object. + * @param mode see lv_span_mode_t for details. + */ +void lv_spangroup_set_mode(lv_obj_t * obj, lv_span_mode_t mode); + +/** + * Set maximum lines of the spangroup. + * @param obj pointer to a spangroup object. + * @param lines max lines that can be displayed in LV_SPAN_MODE_BREAK mode. < 0 means no limit. + */ +void lv_spangroup_set_max_lines(lv_obj_t * obj, int32_t lines); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get a spangroup child by its index. + * + * @param obj The spangroup object + * @param id the index of the child. + * 0: the oldest (firstly created) child + * 1: the second oldest + * child count-1: the youngest + * -1: the youngest + * -2: the second youngest + * @return The child span at index `id`, or NULL if the ID does not exist + */ +lv_span_t * lv_spangroup_get_child(const lv_obj_t * obj, int32_t id); + +/** + * Get number of spans + * @param obj the spangroup object to get the child count of. + * @return the span count of the spangroup. + */ +uint32_t lv_spangroup_get_span_count(const lv_obj_t * obj); + +/** + * Get the align of the spangroup. + * @param obj pointer to a spangroup object. + * @return the align value. + */ +lv_text_align_t lv_spangroup_get_align(lv_obj_t * obj); + +/** + * Get the overflow of the spangroup. + * @param obj pointer to a spangroup object. + * @return the overflow value. + */ +lv_span_overflow_t lv_spangroup_get_overflow(lv_obj_t * obj); + +/** + * Get the indent of the spangroup. + * @param obj pointer to a spangroup object. + * @return the indent value. + */ +int32_t lv_spangroup_get_indent(lv_obj_t * obj); + +/** + * Get the mode of the spangroup. + * @param obj pointer to a spangroup object. + */ +lv_span_mode_t lv_spangroup_get_mode(lv_obj_t * obj); + +/** + * Get maximum lines of the spangroup. + * @param obj pointer to a spangroup object. + * @return the max lines value. + */ +int32_t lv_spangroup_get_max_lines(lv_obj_t * obj); + +/** + * Get max line height of all span in the spangroup. + * @param obj pointer to a spangroup object. + */ +int32_t lv_spangroup_get_max_line_height(lv_obj_t * obj); + +/** + * Get the text content width when all span of spangroup on a line. + * @param obj pointer to a spangroup object. + * @param max_width if text content width >= max_width, return max_width + * to reduce computation, if max_width == 0, returns the text content width. + * @return text content width or max_width. + */ +uint32_t lv_spangroup_get_expand_width(lv_obj_t * obj, uint32_t max_width); + +/** + * Get the text content height with width fixed. + * @param obj pointer to a spangroup object. + * @param width the width of the span group. + + */ +int32_t lv_spangroup_get_expand_height(lv_obj_t * obj, int32_t width); + +/*===================== + * Other functions + *====================*/ + +/** + * Update the mode of the spangroup. + * @param obj pointer to a spangroup object. + */ +void lv_spangroup_refr_mode(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_SPAN*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_SPAN_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.c b/lib/libesp32_lvgl/lvgl/src/widgets/spinbox/lv_spinbox.c similarity index 57% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.c rename to lib/libesp32_lvgl/lvgl/src/widgets/spinbox/lv_spinbox.c index 37db45c37..fd17ba710 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/spinbox/lv_spinbox.c @@ -9,12 +9,16 @@ #include "lv_spinbox.h" #if LV_USE_SPINBOX -#include "../../../misc/lv_assert.h" +#include "../../misc/lv_assert.h" +#include "../../indev/lv_indev.h" +#include "../../stdlib/lv_string.h" /********************* * DEFINES *********************/ #define MY_CLASS &lv_spinbox_class +#define LV_SPINBOX_MAX_DIGIT_COUNT_WITH_8BYTES (LV_SPINBOX_MAX_DIGIT_COUNT + 8U) +#define LV_SPINBOX_MAX_DIGIT_COUNT_WITH_4BYTES (LV_SPINBOX_MAX_DIGIT_COUNT + 4U) /********************** * TYPEDEFS @@ -37,7 +41,8 @@ const lv_obj_class_t lv_spinbox_class = { .width_def = LV_DPI_DEF, .instance_size = sizeof(lv_spinbox_t), .editable = LV_OBJ_CLASS_EDITABLE_TRUE, - .base_class = &lv_textarea_class + .base_class = &lv_textarea_class, + .name = "spinbox", }; /********************** * MACROS @@ -59,70 +64,48 @@ lv_obj_t * lv_spinbox_create(lv_obj_t * parent) * Setter functions *====================*/ -/** - * Set spinbox value - * @param obj pointer to spinbox - * @param i value to be set - */ -void lv_spinbox_set_value(lv_obj_t * obj, int32_t i) +void lv_spinbox_set_value(lv_obj_t * obj, int32_t v) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; - if(i > spinbox->range_max) i = spinbox->range_max; - if(i < spinbox->range_min) i = spinbox->range_min; + if(v > spinbox->range_max) v = spinbox->range_max; + if(v < spinbox->range_min) v = spinbox->range_min; - spinbox->value = i; + spinbox->value = v; lv_spinbox_updatevalue(obj); } -/** - * Set spinbox rollover function - * @param spinbox pointer to spinbox - * @param b true or false to enable or disable (default) - */ -void lv_spinbox_set_rollover(lv_obj_t * obj, bool b) +void lv_spinbox_set_rollover(lv_obj_t * obj, bool rollover) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; - spinbox->rollover = b; + spinbox->rollover = rollover; } -/** - * Set spinbox digit format (digit count and decimal format) - * @param spinbox pointer to spinbox - * @param digit_count number of digit excluding the decimal separator and the sign - * @param separator_position number of digit before the decimal point. If 0, decimal point is not - * shown - */ -void lv_spinbox_set_digit_format(lv_obj_t * obj, uint8_t digit_count, uint8_t separator_position) +void lv_spinbox_set_digit_format(lv_obj_t * obj, uint32_t digit_count, uint32_t sep_pos) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; if(digit_count > LV_SPINBOX_MAX_DIGIT_COUNT) digit_count = LV_SPINBOX_MAX_DIGIT_COUNT; - if(separator_position >= digit_count) separator_position = 0; + if(sep_pos >= digit_count) sep_pos = 0; if(digit_count < LV_SPINBOX_MAX_DIGIT_COUNT) { - int64_t max_val = lv_pow(10, digit_count); + const int64_t max_val = lv_pow(10, digit_count); if(spinbox->range_max > max_val - 1) spinbox->range_max = max_val - 1; - if(spinbox->range_min < - max_val + 1) spinbox->range_min = - max_val + 1; + if(spinbox->range_min < -max_val + 1) spinbox->range_min = -max_val + 1; } spinbox->digit_count = digit_count; - spinbox->dec_point_pos = separator_position; + spinbox->dec_point_pos = sep_pos; lv_spinbox_updatevalue(obj); } -/** - * Set spinbox step - * @param spinbox pointer to spinbox - * @param step steps on increment/decrement - */ void lv_spinbox_set_step(lv_obj_t * obj, uint32_t step) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -132,12 +115,6 @@ void lv_spinbox_set_step(lv_obj_t * obj, uint32_t step) lv_spinbox_updatevalue(obj); } -/** - * Set spinbox value range - * @param spinbox pointer to spinbox - * @param range_min maximum value, inclusive - * @param range_max minimum value, inclusive - */ void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -152,29 +129,20 @@ void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max) lv_spinbox_updatevalue(obj); } -/** - * Set cursor position to a specific digit for edition - * @param spinbox pointer to spinbox - * @param pos selected position in spinbox - */ -void lv_spinbox_set_cursor_pos(lv_obj_t * obj, uint8_t pos) +void lv_spinbox_set_cursor_pos(lv_obj_t * obj, uint32_t pos) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; - int32_t step_limit; - step_limit = LV_MAX(spinbox->range_max, (spinbox->range_min < 0 ? (-spinbox->range_min) : spinbox->range_min)); - int32_t new_step = spinbox->step * lv_pow(10, pos); + + const int32_t step_limit = LV_MAX(spinbox->range_max, LV_ABS(spinbox->range_min)); + const int32_t new_step = lv_pow(10, pos); + if(pos <= 0) spinbox->step = 1; else if(new_step <= step_limit) spinbox->step = new_step; lv_spinbox_updatevalue(obj); } -/** - * Set direction of digit step when clicking an encoder button while in editing mode - * @param spinbox pointer to spinbox - * @param direction the direction (LV_DIR_RIGHT or LV_DIR_LEFT) - */ void lv_spinbox_set_digit_step_direction(lv_obj_t * obj, lv_dir_t direction) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -187,11 +155,6 @@ void lv_spinbox_set_digit_step_direction(lv_obj_t * obj, lv_dir_t direction) * Getter functions *====================*/ -/** - * Get the spinbox numeral value (user has to convert to float according to its digit format) - * @param obj pointer to spinbox - * @return value integer value of the spinbox - */ int32_t lv_spinbox_get_value(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -199,11 +162,7 @@ int32_t lv_spinbox_get_value(lv_obj_t * obj) return spinbox->value; } -/** - * Get the spinbox step value (user has to convert to float according to its digit format) - * @param obj pointer to spinbox - * @return value integer step value of the spinbox - */ + int32_t lv_spinbox_get_step(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -216,44 +175,29 @@ int32_t lv_spinbox_get_step(lv_obj_t * obj) * Other functions *====================*/ -/** - * Select next lower digit for edition - * @param obj pointer to spinbox - */ void lv_spinbox_step_next(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; - int32_t new_step = spinbox->step / 10; - if((new_step) > 0) - spinbox->step = new_step; - else - spinbox->step = 1; + const int32_t new_step = spinbox->step / 10; + spinbox->step = (new_step > 0) ? new_step : 1; lv_spinbox_updatevalue(obj); } -/** - * Select next higher digit for edition - * @param obj pointer to spinbox - */ void lv_spinbox_step_prev(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; - int32_t step_limit; - step_limit = LV_MAX(spinbox->range_max, (spinbox->range_min < 0 ? (-spinbox->range_min) : spinbox->range_min)); - int32_t new_step = spinbox->step * 10; + + const int32_t step_limit = LV_MAX(spinbox->range_max, LV_ABS(spinbox->range_min)); + const int32_t new_step = spinbox->step * 10; if(new_step <= step_limit) spinbox->step = new_step; lv_spinbox_updatevalue(obj); } -/** - * Get spinbox rollover function status - * @param obj pointer to spinbox - */ bool lv_spinbox_get_rollover(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -262,55 +206,62 @@ bool lv_spinbox_get_rollover(lv_obj_t * obj) return spinbox->rollover; } -/** - * Increment spinbox value by one step - * @param obj pointer to spinbox - */ void lv_spinbox_increment(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; - if(spinbox->value + spinbox->step <= spinbox->range_max) { - /*Special mode when zero crossing*/ - if((spinbox->value + spinbox->step) > 0 && spinbox->value < 0) spinbox->value = -spinbox->value; - spinbox->value += spinbox->step; + int32_t v = spinbox->value; + /* Special mode when zero crossing. E.g -3+10 should be 3, not 7. + * Pretend we are on -7 now.*/ + if((spinbox->value < 0) && (spinbox->value + spinbox->step) > 0) { + v = -(spinbox->step + spinbox->value); + } + if(v + spinbox->step <= spinbox->range_max) { + v += spinbox->step; } else { - // Rollover? + /*Rollover?*/ if((spinbox->rollover) && (spinbox->value == spinbox->range_max)) - spinbox->value = spinbox->range_min; + v = spinbox->range_min; else - spinbox->value = spinbox->range_max; + v = spinbox->range_max; } - lv_spinbox_updatevalue(obj); + if(v != spinbox->value) { + spinbox->value = v; + lv_spinbox_updatevalue(obj); + } } -/** - * Decrement spinbox value by one step - * @param obj pointer to spinbox - */ void lv_spinbox_decrement(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; - if(spinbox->value - spinbox->step >= spinbox->range_min) { - /*Special mode when zero crossing*/ - if((spinbox->value - spinbox->step) < 0 && spinbox->value > 0) spinbox->value = -spinbox->value; - spinbox->value -= spinbox->step; + int32_t v = spinbox->value; + /* Special mode when zero crossing. E.g 3-10 should be -3, not -7. + * Pretend we are on 7 now.*/ + if((spinbox->value > 0) && (spinbox->value - spinbox->step) < 0) { + v = spinbox->step - spinbox->value; + } + + if(v - spinbox->step >= spinbox->range_min) { + v -= spinbox->step; } else { /*Rollover?*/ if((spinbox->rollover) && (spinbox->value == spinbox->range_min)) - spinbox->value = spinbox->range_max; + v = spinbox->range_max; else - spinbox->value = spinbox->range_min; + v = spinbox->range_min; } - lv_spinbox_updatevalue(obj); + if(v != spinbox->value) { + spinbox->value = v; + lv_spinbox_updatevalue(obj); + } } /********************** @@ -347,38 +298,36 @@ static void lv_spinbox_event(const lv_obj_class_t * class_p, lv_event_t * e) LV_UNUSED(class_p); /*Call the ancestor's event handler*/ - lv_res_t res = LV_RES_OK; + lv_result_t res = LV_RESULT_OK; res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + const lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; if(code == LV_EVENT_RELEASED) { /*If released with an ENCODER then move to the next digit*/ - lv_indev_t * indev = lv_indev_get_act(); - if(lv_indev_get_type(indev) == LV_INDEV_TYPE_ENCODER) { - if(lv_group_get_editing(lv_obj_get_group(obj))) { - if(spinbox->digit_count > 1) { - if(spinbox->digit_step_dir == LV_DIR_RIGHT) { - if(spinbox->step > 1) { - lv_spinbox_step_next(obj); - } - else { - /*Restart from the MSB*/ - spinbox->step = lv_pow(10, spinbox->digit_count - 2); - lv_spinbox_step_prev(obj); - } + lv_indev_t * indev = lv_indev_active(); + if(lv_indev_get_type(indev) == LV_INDEV_TYPE_ENCODER && lv_group_get_editing(lv_obj_get_group(obj))) { + if(spinbox->digit_count > 1) { + if(spinbox->digit_step_dir == LV_DIR_RIGHT) { + if(spinbox->step > 1) { + lv_spinbox_step_next(obj); } else { - if(spinbox->step < lv_pow(10, spinbox->digit_count - 1)) { - lv_spinbox_step_prev(obj); - } - else { - /*Restart from the LSB*/ - spinbox->step = 10; - lv_spinbox_step_next(obj); - } + /*Restart from the MSB*/ + spinbox->step = lv_pow(10, spinbox->digit_count - 2); + lv_spinbox_step_prev(obj); + } + } + else { + if(spinbox->step < lv_pow(10, spinbox->digit_count - 1)) { + lv_spinbox_step_prev(obj); + } + else { + /*Restart from the LSB*/ + spinbox->step = 10; + lv_spinbox_step_next(obj); } } } @@ -387,33 +336,38 @@ static void lv_spinbox_event(const lv_obj_class_t * class_p, lv_event_t * e) * Set `step` accordingly*/ else { const char * txt = lv_textarea_get_text(obj); - size_t txt_len = strlen(txt); + const size_t txt_len = lv_strlen(txt); + /* Check cursor position */ + /* Cursor is in '.' digit */ if(txt[spinbox->ta.cursor.pos] == '.') { lv_textarea_cursor_left(obj); } + /* Cursor is already in the right-most digit */ else if(spinbox->ta.cursor.pos == (uint32_t)txt_len) { lv_textarea_set_cursor_pos(obj, txt_len - 1); } + /* Cursor is already in the left-most digit AND range_min is negative */ else if(spinbox->ta.cursor.pos == 0 && spinbox->range_min < 0) { lv_textarea_set_cursor_pos(obj, 1); } - size_t len = spinbox->digit_count - 1; - uint16_t cp = spinbox->ta.cursor.pos; - + /* Handle spinbox with decimal point (spinbox->dec_point_pos != 0) */ + uint32_t cp = spinbox->ta.cursor.pos; if(spinbox->ta.cursor.pos > spinbox->dec_point_pos && spinbox->dec_point_pos != 0) cp--; + + const size_t len = spinbox->digit_count - 1; uint32_t pos = len - cp; if(spinbox->range_min < 0) pos++; spinbox->step = 1; - uint16_t i; + uint32_t i; for(i = 0; i < pos; i++) spinbox->step *= 10; } } else if(code == LV_EVENT_KEY) { - lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); + lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_active()); uint32_t c = *((uint32_t *)lv_event_get_param(e)); /*uint32_t because can be UTF-8*/ if(c == LV_KEY_RIGHT) { @@ -434,6 +388,9 @@ static void lv_spinbox_event(const lv_obj_class_t * class_p, lv_event_t * e) else if(c == LV_KEY_DOWN) { lv_spinbox_decrement(obj); } + else { + lv_textarea_add_char(obj, c); + } } } @@ -441,12 +398,12 @@ static void lv_spinbox_updatevalue(lv_obj_t * obj) { lv_spinbox_t * spinbox = (lv_spinbox_t *)obj; - char buf[LV_SPINBOX_MAX_DIGIT_COUNT + 8]; - lv_memset_00(buf, sizeof(buf)); - char * buf_p = buf; - uint8_t cur_shift_left = 0; + /* LV_SPINBOX_MAX_DIGIT_COUNT_WITH_8BYTES (18): Max possible digit_count value (15) + sign + decimal point + NULL terminator */ + char textarea_txt[LV_SPINBOX_MAX_DIGIT_COUNT_WITH_8BYTES] = {0U}; + char * buf_p = textarea_txt; - if(spinbox->range_min < 0) { // hide sign if there are only positive values + uint32_t cur_shift_left = 0; + if(spinbox->range_min < 0) { /*hide sign if there are only positive values*/ /*Add the sign*/ (*buf_p) = spinbox->value >= 0 ? '+' : '-'; buf_p++; @@ -456,33 +413,34 @@ static void lv_spinbox_updatevalue(lv_obj_t * obj) cur_shift_left++; } - int32_t i; - char digits[LV_SPINBOX_MAX_DIGIT_COUNT + 4]; - /*Convert the numbers to string (the sign is already handled so always covert positive number)*/ - lv_snprintf(digits, sizeof(digits), "%" LV_PRId32, LV_ABS(spinbox->value)); + /*Convert the numbers to string (the sign is already handled so always convert positive number)*/ + char digits[LV_SPINBOX_MAX_DIGIT_COUNT_WITH_4BYTES]; + lv_snprintf(digits, LV_SPINBOX_MAX_DIGIT_COUNT_WITH_4BYTES, "%" LV_PRId32, LV_ABS(spinbox->value)); /*Add leading zeros*/ - int lz_cnt = spinbox->digit_count - (int)strlen(digits); - if(lz_cnt > 0) { - for(i = (uint16_t)strlen(digits); i >= 0; i--) { - digits[i + lz_cnt] = digits[i]; + int32_t i; + const size_t digits_len = lv_strlen(digits); + + const int leading_zeros_cnt = spinbox->digit_count - digits_len; + if(leading_zeros_cnt) { + for(i = (int32_t) digits_len; i >= 0; i--) { + digits[i + leading_zeros_cnt] = digits[i]; } - for(i = 0; i < lz_cnt; i++) { + /* NOTE: Substitute with memset? */ + for(i = 0; i < leading_zeros_cnt; i++) { digits[i] = '0'; } } - int32_t intDigits; - intDigits = (spinbox->dec_point_pos == 0) ? spinbox->digit_count : spinbox->dec_point_pos; - /*Add the decimal part*/ - for(i = 0; i < intDigits && digits[i] != '\0'; i++) { + const uint32_t intDigits = (spinbox->dec_point_pos == 0) ? spinbox->digit_count : spinbox->dec_point_pos; + for(i = 0; i < (int32_t)intDigits && digits[i] != '\0'; i++) { (*buf_p) = digits[i]; buf_p++; } - if(spinbox->dec_point_pos != 0) { - /*Insert the decimal point*/ + /*Insert the decimal point*/ + if(spinbox->dec_point_pos) { (*buf_p) = '.'; buf_p++; @@ -493,11 +451,11 @@ static void lv_spinbox_updatevalue(lv_obj_t * obj) } /*Refresh the text*/ - lv_textarea_set_text(obj, (char *)buf); + lv_textarea_set_text(obj, (char *)textarea_txt); /*Set the cursor position*/ - int32_t step = spinbox->step; - uint8_t cur_pos = (uint8_t)spinbox->digit_count; + int32_t step = spinbox->step; + uint32_t cur_pos = (uint32_t)spinbox->digit_count; while(step >= 10) { step /= 10; cur_pos--; diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.h b/lib/libesp32_lvgl/lvgl/src/widgets/spinbox/lv_spinbox.h similarity index 58% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.h rename to lib/libesp32_lvgl/lvgl/src/widgets/spinbox/lv_spinbox.h index 1a4bc322f..267026f2e 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinbox/lv_spinbox.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/spinbox/lv_spinbox.h @@ -13,7 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../lvgl.h" +#include "../textarea/lv_textarea.h" #if LV_USE_SPINBOX @@ -39,22 +39,22 @@ typedef struct { int32_t range_max; int32_t range_min; int32_t step; - uint16_t digit_count : 4; - uint16_t dec_point_pos : 4; /*if 0, there is no separator and the number is an integer*/ - uint16_t rollover : 1; // Set to true for rollover functionality - uint16_t digit_step_dir : 2; // the direction the digit will step on encoder button press when editing + uint32_t digit_count : 4; + uint32_t dec_point_pos : 4; /*if 0, there is no separator and the number is an integer*/ + uint32_t rollover : 1; /* Set to true for rollover functionality*/ + uint32_t digit_step_dir : 2; /* the direction the digit will step on encoder button press when editing*/ } lv_spinbox_t; -extern const lv_obj_class_t lv_spinbox_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_spinbox_class; /********************** * GLOBAL PROTOTYPES **********************/ /** - * Create a Spinbox object - * @param parent pointer to an object, it will be the parent of the new spinbox - * @return pointer to the created spinbox + * Create a spinbox object + * @param parent pointer to an object, it will be the parent of the new spinbox + * @return pointer to the created spinbox */ lv_obj_t * lv_spinbox_create(lv_obj_t * parent); @@ -64,37 +64,37 @@ lv_obj_t * lv_spinbox_create(lv_obj_t * parent); /** * Set spinbox value - * @param obj pointer to spinbox - * @param i value to be set + * @param obj pointer to spinbox + * @param v value to be set */ -void lv_spinbox_set_value(lv_obj_t * obj, int32_t i); +void lv_spinbox_set_value(lv_obj_t * obj, int32_t v); /** * Set spinbox rollover function - * @param obj pointer to spinbox - * @param b true or false to enable or disable (default) + * @param obj pointer to spinbox + * @param rollover true or false to enable or disable (default) */ -void lv_spinbox_set_rollover(lv_obj_t * obj, bool b); +void lv_spinbox_set_rollover(lv_obj_t * obj, bool rollover); /** * Set spinbox digit format (digit count and decimal format) - * @param obj pointer to spinbox - * @param digit_count number of digit excluding the decimal separator and the sign - * @param separator_position number of digit before the decimal point. If 0, decimal point is not + * @param obj pointer to spinbox + * @param digit_count number of digit excluding the decimal separator and the sign + * @param sep_pos number of digit before the decimal point. If 0, decimal point is not * shown */ -void lv_spinbox_set_digit_format(lv_obj_t * obj, uint8_t digit_count, uint8_t separator_position); +void lv_spinbox_set_digit_format(lv_obj_t * obj, uint32_t digit_count, uint32_t sep_pos); /** * Set spinbox step - * @param obj pointer to spinbox - * @param step steps on increment/decrement. Can be 1, 10, 100, 1000, etc the digit that will change. + * @param obj pointer to spinbox + * @param step steps on increment/decrement. Can be 1, 10, 100, 1000, etc the digit that will change. */ void lv_spinbox_set_step(lv_obj_t * obj, uint32_t step); /** * Set spinbox value range - * @param obj pointer to spinbox + * @param obj pointer to spinbox * @param range_min maximum value, inclusive * @param range_max minimum value, inclusive */ @@ -102,15 +102,15 @@ void lv_spinbox_set_range(lv_obj_t * obj, int32_t range_min, int32_t range_max); /** * Set cursor position to a specific digit for edition - * @param obj pointer to spinbox - * @param pos selected position in spinbox + * @param obj pointer to spinbox + * @param pos selected position in spinbox */ -void lv_spinbox_set_cursor_pos(lv_obj_t * obj, uint8_t pos); +void lv_spinbox_set_cursor_pos(lv_obj_t * obj, uint32_t pos); /** * Set direction of digit step when clicking an encoder button while in editing mode - * @param obj pointer to spinbox - * @param direction the direction (LV_DIR_RIGHT or LV_DIR_LEFT) + * @param obj pointer to spinbox + * @param direction the direction (LV_DIR_RIGHT or LV_DIR_LEFT) */ void lv_spinbox_set_digit_step_direction(lv_obj_t * obj, lv_dir_t direction); @@ -120,21 +120,21 @@ void lv_spinbox_set_digit_step_direction(lv_obj_t * obj, lv_dir_t direction); /** * Get spinbox rollover function status - * @param obj pointer to spinbox + * @param obj pointer to spinbox */ bool lv_spinbox_get_rollover(lv_obj_t * obj); /** * Get the spinbox numeral value (user has to convert to float according to its digit format) - * @param obj pointer to spinbox - * @return value integer value of the spinbox + * @param obj pointer to spinbox + * @return value integer value of the spinbox */ int32_t lv_spinbox_get_value(lv_obj_t * obj); /** * Get the spinbox step value (user has to convert to float according to its digit format) - * @param obj pointer to spinbox - * @return value integer step value of the spinbox + * @param obj pointer to spinbox + * @return value integer step value of the spinbox */ int32_t lv_spinbox_get_step(lv_obj_t * obj); @@ -144,25 +144,25 @@ int32_t lv_spinbox_get_step(lv_obj_t * obj); /** * Select next lower digit for edition by dividing the step by 10 - * @param obj pointer to spinbox + * @param obj pointer to spinbox */ void lv_spinbox_step_next(lv_obj_t * obj); /** * Select next higher digit for edition by multiplying the step by 10 - * @param obj pointer to spinbox + * @param obj pointer to spinbox */ void lv_spinbox_step_prev(lv_obj_t * obj); /** * Increment spinbox value by one step - * @param obj pointer to spinbox + * @param obj pointer to spinbox */ void lv_spinbox_increment(lv_obj_t * obj); /** * Decrement spinbox value by one step - * @param obj pointer to spinbox + * @param obj pointer to spinbox */ void lv_spinbox_decrement(lv_obj_t * obj); @@ -170,10 +170,6 @@ void lv_spinbox_decrement(lv_obj_t * obj); * MACROS **********************/ -/* It was ambiguous in MicroPython. See https://github.com/lvgl/lvgl/issues/3301 - * TODO remove in v9*/ -#define lv_spinbox_set_pos lv_spinbox_set_cursor_pos - #endif /*LV_USE_SPINBOX*/ #ifdef __cplusplus diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinner/lv_spinner.c b/lib/libesp32_lvgl/lvgl/src/widgets/spinner/lv_spinner.c similarity index 58% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/spinner/lv_spinner.c rename to lib/libesp32_lvgl/lvgl/src/widgets/spinner/lv_spinner.c index b9b32203a..81eee4619 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinner/lv_spinner.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/spinner/lv_spinner.c @@ -12,6 +12,8 @@ /********************* * DEFINES *********************/ +#define DEF_ARC_ANGLE 200 +#define DEF_TIME 1000 /********************** * TYPEDEFS @@ -21,20 +23,18 @@ * STATIC PROTOTYPES **********************/ static void lv_spinner_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); -void arc_anim_start_angle(void * obj, int32_t v); -void arc_anim_end_angle(void * obj, int32_t v); +static void arc_anim_start_angle(void * obj, int32_t v); +static void arc_anim_end_angle(void * obj, int32_t v); /********************** * STATIC VARIABLES **********************/ const lv_obj_class_t lv_spinner_class = { .base_class = &lv_arc_class, - .constructor_cb = lv_spinner_constructor + .constructor_cb = lv_spinner_constructor, + .name = "spinner", }; -static uint32_t time_param; -static uint32_t arc_length_param; - /********************** * MACROS **********************/ @@ -43,21 +43,38 @@ static uint32_t arc_length_param; * GLOBAL FUNCTIONS **********************/ -/** - * Create a spinner object - * @param parent pointer to an object, it will be the parent of the new spinner - * @return pointer to the created spinner - */ -lv_obj_t * lv_spinner_create(lv_obj_t * parent, uint32_t time, uint32_t arc_length) +lv_obj_t * lv_spinner_create(lv_obj_t * parent) { - time_param = time; - arc_length_param = arc_length; lv_obj_t * obj = lv_obj_class_create_obj(&lv_spinner_class, parent); lv_obj_class_init_obj(obj); return obj; } +void lv_spinner_set_anim_params(lv_obj_t * obj, uint32_t t, uint32_t angle) +{ + /*Delete the current animation*/ + lv_anim_delete(obj, NULL); + + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, obj); + lv_anim_set_exec_cb(&a, arc_anim_end_angle); + lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); + lv_anim_set_duration(&a, t); + lv_anim_set_values(&a, angle, 360 + angle); + lv_anim_start(&a); + + lv_anim_set_path_cb(&a, lv_anim_path_custom_bezier3); + lv_anim_set_bezier3_param(&a, LV_BEZIER_VAL_FLOAT(0.42), LV_BEZIER_VAL_FLOAT(0.58), + LV_BEZIER_VAL_FLOAT(0), LV_BEZIER_VAL_FLOAT(1)); + lv_anim_set_values(&a, 0, 360); + lv_anim_set_exec_cb(&a, arc_anim_start_angle); + lv_anim_start(&a); + + lv_arc_set_bg_angles(obj, 0, 360); + lv_arc_set_rotation(obj, 270); +} /********************** * STATIC FUNCTIONS @@ -69,36 +86,19 @@ static void lv_spinner_constructor(const lv_obj_class_t * class_p, lv_obj_t * ob LV_UNUSED(class_p); - lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICKABLE); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_CLICKABLE); - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, obj); - lv_anim_set_exec_cb(&a, arc_anim_end_angle); - lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); - lv_anim_set_time(&a, time_param); - lv_anim_set_values(&a, arc_length_param, 360 + arc_length_param); - lv_anim_start(&a); - - lv_anim_set_path_cb(&a, lv_anim_path_ease_in_out); - lv_anim_set_values(&a, 0, 360); - lv_anim_set_exec_cb(&a, arc_anim_start_angle); - lv_anim_start(&a); - - lv_arc_set_bg_angles(obj, 0, 360); - lv_arc_set_rotation(obj, 270); + lv_spinner_set_anim_params(obj, DEF_TIME, DEF_ARC_ANGLE); } - -void arc_anim_start_angle(void * obj, int32_t v) +static void arc_anim_start_angle(void * obj, int32_t v) { - lv_arc_set_start_angle(obj, (uint16_t) v); + lv_arc_set_start_angle(obj, (uint32_t) v); } - -void arc_anim_end_angle(void * obj, int32_t v) +static void arc_anim_end_angle(void * obj, int32_t v) { - lv_arc_set_end_angle(obj, (uint16_t) v); + lv_arc_set_end_angle(obj, (uint32_t) v); } #endif /*LV_USE_SPINNER*/ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinner/lv_spinner.h b/lib/libesp32_lvgl/lvgl/src/widgets/spinner/lv_spinner.h similarity index 56% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/spinner/lv_spinner.h rename to lib/libesp32_lvgl/lvgl/src/widgets/spinner/lv_spinner.h index 2ab36f64d..7b5f41666 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/spinner/lv_spinner.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/spinner/lv_spinner.h @@ -29,13 +29,26 @@ extern "C" { /********************** * TYPEDEFS **********************/ -extern const lv_obj_class_t lv_spinner_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_spinner_class; /********************** * GLOBAL PROTOTYPES **********************/ -lv_obj_t * lv_spinner_create(lv_obj_t * parent, uint32_t time, uint32_t arc_length); +/** + * Create a spinner widget + * @param parent pointer to an object, it will be the parent of the new spinner. + * @return the created spinner + */ +lv_obj_t * lv_spinner_create(lv_obj_t * parent); + +/** + * Set the animation time and arc length of the spinner + * @param obj pointer to a spinner + * @param t the animation time in milliseconds + * @param angle the angle of the arc in degrees + */ +void lv_spinner_set_anim_params(lv_obj_t * obj, uint32_t t, uint32_t angle); /********************** * MACROS diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_switch.c b/lib/libesp32_lvgl/lvgl/src/widgets/switch/lv_switch.c similarity index 71% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_switch.c rename to lib/libesp32_lvgl/lvgl/src/widgets/switch/lv_switch.c index b32861043..eab1a4906 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_switch.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/switch/lv_switch.c @@ -10,12 +10,11 @@ #if LV_USE_SWITCH != 0 -#include "../misc/lv_assert.h" -#include "../misc/lv_math.h" -#include "../misc/lv_anim.h" -#include "../core/lv_indev.h" -#include "../core/lv_disp.h" -#include "lv_img.h" +#include "../../misc/lv_assert.h" +#include "../../misc/lv_math.h" +#include "../../misc/lv_anim.h" +#include "../../indev/lv_indev.h" +#include "../../display/lv_display.h" /********************* * DEFINES @@ -47,7 +46,7 @@ static void draw_main(lv_event_t * e); static void lv_switch_anim_exec_cb(void * sw, int32_t value); static void lv_switch_trigger_anim(lv_obj_t * obj); -static void lv_switch_anim_ready(lv_anim_t * a); +static void lv_switch_anim_completed(lv_anim_t * a); /********************** * STATIC VARIABLES **********************/ @@ -59,7 +58,8 @@ const lv_obj_class_t lv_switch_class = { .height_def = (4 * LV_DPI_DEF) / 17, .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, .instance_size = sizeof(lv_switch_t), - .base_class = &lv_obj_class + .base_class = &lv_obj_class, + .name = "switch", }; /********************** @@ -91,7 +91,7 @@ static void lv_switch_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj sw->anim_state = LV_SWITCH_ANIM_STATE_INV; - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLLABLE); lv_obj_add_flag(obj, LV_OBJ_FLAG_CHECKABLE); lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS); @@ -103,34 +103,34 @@ static void lv_switch_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) LV_UNUSED(class_p); lv_switch_t * sw = (lv_switch_t *)obj; - lv_anim_del(sw, NULL); + lv_anim_delete(sw, NULL); } static void lv_switch_event(const lv_obj_class_t * class_p, lv_event_t * e) { LV_UNUSED(class_p); - lv_res_t res; + lv_result_t res; /*Call the ancestor's event handler*/ res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { - lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); - lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); - lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); - lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); + int32_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); + int32_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); + int32_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); + int32_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); /*The smaller size is the knob diameter*/ - lv_coord_t knob_size = LV_MAX4(knob_left, knob_right, knob_bottom, knob_top); + int32_t knob_size = LV_MAX4(knob_left, knob_right, knob_bottom, knob_top); knob_size += _LV_SWITCH_KNOB_EXT_AREA_CORRECTION; knob_size += lv_obj_calculate_ext_draw_size(obj, LV_PART_KNOB); - lv_coord_t * s = lv_event_get_param(e); + int32_t * s = lv_event_get_param(e); *s = LV_MAX(*s, knob_size); *s = LV_MAX(*s, lv_obj_calculate_ext_draw_size(obj, LV_PART_INDICATOR)); } @@ -145,35 +145,25 @@ static void lv_switch_event(const lv_obj_class_t * class_p, lv_event_t * e) static void draw_main(lv_event_t * e) { - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_switch_t * sw = (lv_switch_t *)obj; - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); - - /*Calculate the indicator area*/ - lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); - lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + lv_layer_t * layer = lv_event_get_layer(e); /*Draw the indicator*/ - /*Respect the background's padding*/ lv_area_t indic_area; - lv_area_copy(&indic_area, &obj->coords); - indic_area.x1 += bg_left; - indic_area.x2 -= bg_right; - indic_area.y1 += bg_top; - indic_area.y2 -= bg_bottom; + /*Exclude background's padding*/ + lv_obj_get_content_coords(obj, &indic_area); lv_draw_rect_dsc_t draw_indic_dsc; lv_draw_rect_dsc_init(&draw_indic_dsc); lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &draw_indic_dsc); - lv_draw_rect(draw_ctx, &draw_indic_dsc, &indic_area); + lv_draw_rect(layer, &draw_indic_dsc, &indic_area); /*Draw the knob*/ - lv_coord_t anim_value_x = 0; - lv_coord_t knob_size = lv_obj_get_height(obj); - lv_coord_t anim_length = lv_area_get_width(&obj->coords) - knob_size; + int32_t anim_value_x = 0; + int32_t knob_size = lv_obj_get_height(obj); + int32_t anim_length = lv_area_get_width(&obj->coords) - knob_size; if(LV_SWITCH_IS_ANIMATING(sw)) { /* Use the animation's coordinate */ @@ -190,16 +180,14 @@ static void draw_main(lv_event_t * e) } lv_area_t knob_area; - knob_area.x1 = obj->coords.x1 + anim_value_x; - knob_area.x2 = knob_area.x1 + knob_size; + lv_area_copy(&knob_area, &obj->coords); + knob_area.x1 += anim_value_x; + knob_area.x2 = knob_area.x1 + (knob_size > 0 ? knob_size - 1 : 0); - knob_area.y1 = obj->coords.y1; - knob_area.y2 = obj->coords.y2; - - lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); - lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); - lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); - lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); + int32_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); + int32_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); + int32_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); + int32_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); /*Apply the paddings on the knob area*/ knob_area.x1 -= knob_left; @@ -211,7 +199,7 @@ static void draw_main(lv_event_t * e) lv_draw_rect_dsc_init(&knob_rect_dsc); lv_obj_init_draw_rect_dsc(obj, LV_PART_KNOB, &knob_rect_dsc); - lv_draw_rect(draw_ctx, &knob_rect_dsc, &knob_area); + lv_draw_rect(layer, &knob_rect_dsc, &knob_area); } static void lv_switch_anim_exec_cb(void * var, int32_t value) @@ -224,7 +212,7 @@ static void lv_switch_anim_exec_cb(void * var, int32_t value) /** * Resets the switch's animation state to "no animation in progress". */ -static void lv_switch_anim_ready(lv_anim_t * a) +static void lv_switch_anim_completed(lv_anim_t * a) { lv_switch_t * sw = a->var; sw->anim_state = LV_SWITCH_ANIM_STATE_INV; @@ -240,7 +228,7 @@ static void lv_switch_trigger_anim(lv_obj_t * obj) LV_ASSERT_OBJ(obj, MY_CLASS); lv_switch_t * sw = (lv_switch_t *)obj; - uint32_t anim_dur_full = lv_obj_get_style_anim_time(obj, LV_PART_MAIN); + uint32_t anim_dur_full = lv_obj_get_style_anim_duration(obj, LV_PART_MAIN); if(anim_dur_full > 0) { bool chk = lv_obj_get_state(obj) & LV_STATE_CHECKED; @@ -260,18 +248,17 @@ static void lv_switch_trigger_anim(lv_obj_t * obj) uint32_t anim_dur = (anim_dur_full * LV_ABS(anim_start - anim_end)) / LV_SWITCH_ANIM_STATE_END; /*Stop the previous animation if it exists*/ - lv_anim_del(sw, NULL); + lv_anim_delete(sw, NULL); lv_anim_t a; lv_anim_init(&a); lv_anim_set_var(&a, sw); lv_anim_set_exec_cb(&a, lv_switch_anim_exec_cb); lv_anim_set_values(&a, anim_start, anim_end); - lv_anim_set_ready_cb(&a, lv_switch_anim_ready); - lv_anim_set_time(&a, anim_dur); + lv_anim_set_completed_cb(&a, lv_switch_anim_completed); + lv_anim_set_duration(&a, anim_dur); lv_anim_start(&a); } } - #endif diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_switch.h b/lib/libesp32_lvgl/lvgl/src/widgets/switch/lv_switch.h similarity index 75% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_switch.h rename to lib/libesp32_lvgl/lvgl/src/widgets/switch/lv_switch.h index 83ca81bc4..da14450aa 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_switch.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/switch/lv_switch.h @@ -13,11 +13,11 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../lv_conf_internal.h" +#include "../../lv_conf_internal.h" #if LV_USE_SWITCH != 0 -#include "../core/lv_obj.h" +#include "../../core/lv_obj.h" /********************* * DEFINES @@ -35,7 +35,7 @@ typedef struct { int32_t anim_state; } lv_switch_t; -extern const lv_obj_class_t lv_switch_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_switch_class; /********************** * GLOBAL PROTOTYPES @@ -43,8 +43,8 @@ extern const lv_obj_class_t lv_switch_class; /** * Create a switch object - * @param parent pointer to an object, it will be the parent of the new switch - * @return pointer to the created switch + * @param parent pointer to an object, it will be the parent of the new switch + * @return pointer to the created switch */ lv_obj_t * lv_switch_create(lv_obj_t * parent); diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_table.c b/lib/libesp32_lvgl/lvgl/src/widgets/table/lv_table.c similarity index 68% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_table.c rename to lib/libesp32_lvgl/lvgl/src/widgets/table/lv_table.c index 968cf8703..85e4c33e5 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_table.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/table/lv_table.c @@ -9,13 +9,14 @@ #include "lv_table.h" #if LV_USE_TABLE != 0 -#include "../core/lv_indev.h" -#include "../misc/lv_assert.h" -#include "../misc/lv_txt.h" -#include "../misc/lv_txt_ap.h" -#include "../misc/lv_math.h" -#include "../misc/lv_printf.h" -#include "../draw/lv_draw.h" +#include "../../indev/lv_indev.h" +#include "../../misc/lv_assert.h" +#include "../../misc/lv_text.h" +#include "../../misc/lv_text_ap.h" +#include "../../misc/lv_math.h" +#include "../../stdlib/lv_sprintf.h" +#include "../../draw/lv_draw.h" +#include "../../stdlib/lv_string.h" /********************* * DEFINES @@ -33,15 +34,15 @@ static void lv_table_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) static void lv_table_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void lv_table_event(const lv_obj_class_t * class_p, lv_event_t * e); static void draw_main(lv_event_t * e); -static lv_coord_t get_row_height(lv_obj_t * obj, uint16_t row_id, const lv_font_t * font, - lv_coord_t letter_space, lv_coord_t line_space, - lv_coord_t cell_left, lv_coord_t cell_right, lv_coord_t cell_top, lv_coord_t cell_bottom); +static int32_t get_row_height(lv_obj_t * obj, uint32_t row_id, const lv_font_t * font, + int32_t letter_space, int32_t line_space, + int32_t cell_left, int32_t cell_right, int32_t cell_top, int32_t cell_bottom); static void refr_size_form_row(lv_obj_t * obj, uint32_t start_row); static void refr_cell_size(lv_obj_t * obj, uint32_t row, uint32_t col); -static lv_res_t get_pressed_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col); +static lv_result_t get_pressed_cell(lv_obj_t * obj, uint32_t * row, uint32_t * col); static size_t get_cell_txt_len(const char * txt); static void copy_cell_txt(lv_table_cell_t * dst, const char * txt); -static void get_cell_area(lv_obj_t * obj, uint16_t row, uint16_t col, lv_area_t * area); +static void get_cell_area(lv_obj_t * obj, uint32_t row, uint32_t col, lv_area_t * area); static void scroll_to_selected_cell(lv_obj_t * obj); static inline bool is_cell_empty(void * cell) @@ -62,6 +63,7 @@ const lv_obj_class_t lv_table_class = { .editable = LV_OBJ_CLASS_EDITABLE_TRUE, .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, .instance_size = sizeof(lv_table_t), + .name = "table", }; /********************** * MACROS @@ -83,7 +85,7 @@ lv_obj_t * lv_table_create(lv_obj_t * parent) * Setter functions *====================*/ -void lv_table_set_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col, const char * txt) +void lv_table_set_cell_value(lv_obj_t * obj, uint32_t row, uint32_t col, const char * txt) { LV_ASSERT_OBJ(obj, MY_CLASS); LV_ASSERT_NULL(txt); @@ -91,8 +93,8 @@ void lv_table_set_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col, const c lv_table_t * table = (lv_table_t *)obj; /*Auto expand*/ - if(col >= table->col_cnt) lv_table_set_col_cnt(obj, col + 1); - if(row >= table->row_cnt) lv_table_set_row_cnt(obj, row + 1); + if(col >= table->col_cnt) lv_table_set_column_count(obj, col + 1); + if(row >= table->row_cnt) lv_table_set_row_count(obj, row + 1); uint32_t cell = row * table->col_cnt + col; lv_table_cell_ctrl_t ctrl = 0; @@ -100,41 +102,37 @@ void lv_table_set_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col, const c /*Save the control byte*/ if(table->cell_data[cell]) ctrl = table->cell_data[cell]->ctrl; -#if LV_USE_USER_DATA void * user_data = NULL; /*Save the user data*/ if(table->cell_data[cell]) user_data = table->cell_data[cell]->user_data; -#endif size_t to_allocate = get_cell_txt_len(txt); - table->cell_data[cell] = lv_mem_realloc(table->cell_data[cell], to_allocate); + table->cell_data[cell] = lv_realloc(table->cell_data[cell], to_allocate); LV_ASSERT_MALLOC(table->cell_data[cell]); if(table->cell_data[cell] == NULL) return; copy_cell_txt(table->cell_data[cell], txt); table->cell_data[cell]->ctrl = ctrl; -#if LV_USE_USER_DATA table->cell_data[cell]->user_data = user_data; -#endif refr_cell_size(obj, row, col); } -void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, const char * fmt, ...) +void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint32_t row, uint32_t col, const char * fmt, ...) { LV_ASSERT_OBJ(obj, MY_CLASS); LV_ASSERT_NULL(fmt); lv_table_t * table = (lv_table_t *)obj; if(col >= table->col_cnt) { - lv_table_set_col_cnt(obj, col + 1); + lv_table_set_column_count(obj, col + 1); } /*Auto expand*/ if(row >= table->row_cnt) { - lv_table_set_row_cnt(obj, row + 1); + lv_table_set_row_count(obj, row + 1); } uint32_t cell = row * table->col_cnt + col; @@ -143,12 +141,10 @@ void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, con /*Save the control byte*/ if(table->cell_data[cell]) ctrl = table->cell_data[cell]->ctrl; -#if LV_USE_USER_DATA void * user_data = NULL; /*Save the user_data*/ if(table->cell_data[cell]) user_data = table->cell_data[cell]->user_data; -#endif va_list ap, ap2; va_start(ap, fmt); @@ -160,7 +156,7 @@ void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, con #if LV_USE_ARABIC_PERSIAN_CHARS /*Put together the text according to the format string*/ - char * raw_txt = lv_mem_buf_get(len + 1); + char * raw_txt = lv_malloc(len + 1); LV_ASSERT_MALLOC(raw_txt); if(raw_txt == NULL) { va_end(ap2); @@ -170,19 +166,19 @@ void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, con lv_vsnprintf(raw_txt, len + 1, fmt, ap2); /*Get the size of the Arabic text and process it*/ - size_t len_ap = _lv_txt_ap_calc_bytes_cnt(raw_txt); - table->cell_data[cell] = lv_mem_realloc(table->cell_data[cell], sizeof(lv_table_cell_t) + len_ap + 1); + size_t len_ap = _lv_text_ap_calc_bytes_count(raw_txt); + table->cell_data[cell] = lv_realloc(table->cell_data[cell], sizeof(lv_table_cell_t) + len_ap + 1); LV_ASSERT_MALLOC(table->cell_data[cell]); if(table->cell_data[cell] == NULL) { va_end(ap2); return; } - _lv_txt_ap_proc(raw_txt, table->cell_data[cell]->txt); + _lv_text_ap_proc(raw_txt, table->cell_data[cell]->txt); - lv_mem_buf_release(raw_txt); + lv_free(raw_txt); #else - table->cell_data[cell] = lv_mem_realloc(table->cell_data[cell], - sizeof(lv_table_cell_t) + len + 1); /*+1: trailing '\0; */ + table->cell_data[cell] = lv_realloc(table->cell_data[cell], + sizeof(lv_table_cell_t) + len + 1); /*+1: trailing '\0; */ LV_ASSERT_MALLOC(table->cell_data[cell]); if(table->cell_data[cell] == NULL) { va_end(ap2); @@ -197,13 +193,11 @@ void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, con va_end(ap2); table->cell_data[cell]->ctrl = ctrl; -#if LV_USE_USER_DATA table->cell_data[cell]->user_data = user_data; -#endif refr_cell_size(obj, row, col); } -void lv_table_set_row_cnt(lv_obj_t * obj, uint16_t row_cnt) +void lv_table_set_row_count(lv_obj_t * obj, uint32_t row_cnt) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -211,30 +205,28 @@ void lv_table_set_row_cnt(lv_obj_t * obj, uint16_t row_cnt) if(table->row_cnt == row_cnt) return; - uint16_t old_row_cnt = table->row_cnt; + uint32_t old_row_cnt = table->row_cnt; table->row_cnt = row_cnt; - table->row_h = lv_mem_realloc(table->row_h, table->row_cnt * sizeof(table->row_h[0])); + table->row_h = lv_realloc(table->row_h, table->row_cnt * sizeof(table->row_h[0])); LV_ASSERT_MALLOC(table->row_h); if(table->row_h == NULL) return; /*Free the unused cells*/ if(old_row_cnt > row_cnt) { - uint16_t old_cell_cnt = old_row_cnt * table->col_cnt; + uint32_t old_cell_cnt = old_row_cnt * table->col_cnt; uint32_t new_cell_cnt = table->col_cnt * table->row_cnt; uint32_t i; for(i = new_cell_cnt; i < old_cell_cnt; i++) { -#if LV_USE_USER_DATA - if(table->cell_data[i]->user_data) { - lv_mem_free(table->cell_data[i]->user_data); + if(table->cell_data[i] && table->cell_data[i]->user_data) { + lv_free(table->cell_data[i]->user_data); table->cell_data[i]->user_data = NULL; } -#endif - lv_mem_free(table->cell_data[i]); + lv_free(table->cell_data[i]); } } - table->cell_data = lv_mem_realloc(table->cell_data, table->row_cnt * table->col_cnt * sizeof(lv_table_cell_t *)); + table->cell_data = lv_realloc(table->cell_data, table->row_cnt * table->col_cnt * sizeof(lv_table_cell_t *)); LV_ASSERT_MALLOC(table->cell_data); if(table->cell_data == NULL) return; @@ -242,13 +234,13 @@ void lv_table_set_row_cnt(lv_obj_t * obj, uint16_t row_cnt) if(old_row_cnt < row_cnt) { uint32_t old_cell_cnt = old_row_cnt * table->col_cnt; uint32_t new_cell_cnt = table->col_cnt * table->row_cnt; - lv_memset_00(&table->cell_data[old_cell_cnt], (new_cell_cnt - old_cell_cnt) * sizeof(table->cell_data[0])); + lv_memzero(&table->cell_data[old_cell_cnt], (new_cell_cnt - old_cell_cnt) * sizeof(table->cell_data[0])); } refr_size_form_row(obj, 0); } -void lv_table_set_col_cnt(lv_obj_t * obj, uint16_t col_cnt) +void lv_table_set_column_count(lv_obj_t * obj, uint32_t col_cnt) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -256,15 +248,15 @@ void lv_table_set_col_cnt(lv_obj_t * obj, uint16_t col_cnt) if(table->col_cnt == col_cnt) return; - uint16_t old_col_cnt = table->col_cnt; + uint32_t old_col_cnt = table->col_cnt; table->col_cnt = col_cnt; - lv_table_cell_t ** new_cell_data = lv_mem_alloc(table->row_cnt * table->col_cnt * sizeof(lv_table_cell_t *)); + lv_table_cell_t ** new_cell_data = lv_malloc(table->row_cnt * table->col_cnt * sizeof(lv_table_cell_t *)); LV_ASSERT_MALLOC(new_cell_data); if(new_cell_data == NULL) return; uint32_t new_cell_cnt = table->col_cnt * table->row_cnt; - lv_memset_00(new_cell_data, new_cell_cnt * sizeof(table->cell_data[0])); + lv_memzero(new_cell_data, new_cell_cnt * sizeof(table->cell_data[0])); /*The new column(s) messes up the mapping of `cell_data`*/ uint32_t old_col_start; @@ -275,29 +267,27 @@ void lv_table_set_col_cnt(lv_obj_t * obj, uint16_t col_cnt) old_col_start = row * old_col_cnt; new_col_start = row * col_cnt; - lv_memcpy_small(&new_cell_data[new_col_start], &table->cell_data[old_col_start], - sizeof(new_cell_data[0]) * min_col_cnt); + lv_memcpy(&new_cell_data[new_col_start], &table->cell_data[old_col_start], + sizeof(new_cell_data[0]) * min_col_cnt); /*Free the old cells (only if the table becomes smaller)*/ int32_t i; - for(i = 0; i < (int32_t)old_col_cnt - col_cnt; i++) { + for(i = 0; i < (int32_t)old_col_cnt - (int32_t)col_cnt; i++) { uint32_t idx = old_col_start + min_col_cnt + i; -#if LV_USE_USER_DATA if(table->cell_data[idx]->user_data) { - lv_mem_free(table->cell_data[idx]->user_data); + lv_free(table->cell_data[idx]->user_data); table->cell_data[idx]->user_data = NULL; } -#endif - lv_mem_free(table->cell_data[idx]); + lv_free(table->cell_data[idx]); table->cell_data[idx] = NULL; } } - lv_mem_free(table->cell_data); + lv_free(table->cell_data); table->cell_data = new_cell_data; /*Initialize the new column widths if any*/ - table->col_w = lv_mem_realloc(table->col_w, col_cnt * sizeof(table->col_w[0])); + table->col_w = lv_realloc(table->col_w, col_cnt * sizeof(table->col_w[0])); LV_ASSERT_MALLOC(table->col_w); if(table->col_w == NULL) return; @@ -306,78 +296,72 @@ void lv_table_set_col_cnt(lv_obj_t * obj, uint16_t col_cnt) table->col_w[col] = LV_DPI_DEF; } - refr_size_form_row(obj, 0) ; } -void lv_table_set_col_width(lv_obj_t * obj, uint16_t col_id, lv_coord_t w) +void lv_table_set_column_width(lv_obj_t * obj, uint32_t col_id, int32_t w) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_table_t * table = (lv_table_t *)obj; /*Auto expand*/ - if(col_id >= table->col_cnt) lv_table_set_col_cnt(obj, col_id + 1); + if(col_id >= table->col_cnt) lv_table_set_column_count(obj, col_id + 1); table->col_w[col_id] = w; refr_size_form_row(obj, 0); } -void lv_table_add_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl) +void lv_table_add_cell_ctrl(lv_obj_t * obj, uint32_t row, uint32_t col, lv_table_cell_ctrl_t ctrl) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_table_t * table = (lv_table_t *)obj; /*Auto expand*/ - if(col >= table->col_cnt) lv_table_set_col_cnt(obj, col + 1); - if(row >= table->row_cnt) lv_table_set_row_cnt(obj, row + 1); + if(col >= table->col_cnt) lv_table_set_column_count(obj, col + 1); + if(row >= table->row_cnt) lv_table_set_row_count(obj, row + 1); uint32_t cell = row * table->col_cnt + col; if(is_cell_empty(table->cell_data[cell])) { - table->cell_data[cell] = lv_mem_alloc(sizeof(lv_table_cell_t) + 1); /*+1: trailing '\0 */ + table->cell_data[cell] = lv_malloc(sizeof(lv_table_cell_t) + 1); /*+1: trailing '\0 */ LV_ASSERT_MALLOC(table->cell_data[cell]); if(table->cell_data[cell] == NULL) return; table->cell_data[cell]->ctrl = 0; -#if LV_USE_USER_DATA table->cell_data[cell]->user_data = NULL; -#endif table->cell_data[cell]->txt[0] = '\0'; } table->cell_data[cell]->ctrl |= ctrl; } -void lv_table_clear_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl) +void lv_table_clear_cell_ctrl(lv_obj_t * obj, uint32_t row, uint32_t col, lv_table_cell_ctrl_t ctrl) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_table_t * table = (lv_table_t *)obj; /*Auto expand*/ - if(col >= table->col_cnt) lv_table_set_col_cnt(obj, col + 1); - if(row >= table->row_cnt) lv_table_set_row_cnt(obj, row + 1); + if(col >= table->col_cnt) lv_table_set_column_count(obj, col + 1); + if(row >= table->row_cnt) lv_table_set_row_count(obj, row + 1); uint32_t cell = row * table->col_cnt + col; if(is_cell_empty(table->cell_data[cell])) { - table->cell_data[cell] = lv_mem_alloc(sizeof(lv_table_cell_t) + 1); /*+1: trailing '\0 */ + table->cell_data[cell] = lv_malloc(sizeof(lv_table_cell_t) + 1); /*+1: trailing '\0 */ LV_ASSERT_MALLOC(table->cell_data[cell]); if(table->cell_data[cell] == NULL) return; table->cell_data[cell]->ctrl = 0; -#if LV_USE_USER_DATA table->cell_data[cell]->user_data = NULL; -#endif table->cell_data[cell]->txt[0] = '\0'; } table->cell_data[cell]->ctrl &= (~ctrl); } -#if LV_USE_USER_DATA void lv_table_set_cell_user_data(lv_obj_t * obj, uint16_t row, uint16_t col, void * user_data) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -385,13 +369,13 @@ void lv_table_set_cell_user_data(lv_obj_t * obj, uint16_t row, uint16_t col, voi lv_table_t * table = (lv_table_t *)obj; /*Auto expand*/ - if(col >= table->col_cnt) lv_table_set_col_cnt(obj, col + 1); - if(row >= table->row_cnt) lv_table_set_row_cnt(obj, row + 1); + if(col >= table->col_cnt) lv_table_set_column_count(obj, col + 1); + if(row >= table->row_cnt) lv_table_set_row_count(obj, row + 1); uint32_t cell = row * table->col_cnt + col; if(is_cell_empty(table->cell_data[cell])) { - table->cell_data[cell] = lv_mem_alloc(sizeof(lv_table_cell_t) + 1); /*+1: trailing '\0 */ + table->cell_data[cell] = lv_malloc(sizeof(lv_table_cell_t) + 1); /*+1: trailing '\0 */ LV_ASSERT_MALLOC(table->cell_data[cell]); if(table->cell_data[cell] == NULL) return; @@ -401,18 +385,17 @@ void lv_table_set_cell_user_data(lv_obj_t * obj, uint16_t row, uint16_t col, voi } if(table->cell_data[cell]->user_data) { - lv_mem_free(table->cell_data[cell]->user_data); + lv_free(table->cell_data[cell]->user_data); } table->cell_data[cell]->user_data = user_data; } -#endif /*===================== * Getter functions *====================*/ -const char * lv_table_get_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col) +const char * lv_table_get_cell_value(lv_obj_t * obj, uint32_t row, uint32_t col) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -428,7 +411,7 @@ const char * lv_table_get_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col) return table->cell_data[cell]->txt; } -uint16_t lv_table_get_row_cnt(lv_obj_t * obj) +uint32_t lv_table_get_row_count(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -436,7 +419,7 @@ uint16_t lv_table_get_row_cnt(lv_obj_t * obj) return table->row_cnt; } -uint16_t lv_table_get_col_cnt(lv_obj_t * obj) +uint32_t lv_table_get_column_count(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -444,27 +427,27 @@ uint16_t lv_table_get_col_cnt(lv_obj_t * obj) return table->col_cnt; } -lv_coord_t lv_table_get_col_width(lv_obj_t * obj, uint16_t col) +int32_t lv_table_get_column_width(lv_obj_t * obj, uint32_t col) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_table_t * table = (lv_table_t *)obj; if(col >= table->col_cnt) { - LV_LOG_WARN("lv_table_set_col_width: too big 'col_id'. Must be < LV_TABLE_COL_MAX."); + LV_LOG_WARN("too big 'col_id'. Must be < LV_TABLE_COL_MAX."); return 0; } return table->col_w[col]; } -bool lv_table_has_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl) +bool lv_table_has_cell_ctrl(lv_obj_t * obj, uint32_t row, uint32_t col, lv_table_cell_ctrl_t ctrl) { LV_ASSERT_OBJ(obj, MY_CLASS); lv_table_t * table = (lv_table_t *)obj; if(row >= table->row_cnt || col >= table->col_cnt) { - LV_LOG_WARN("lv_table_get_cell_crop: invalid row or column"); + LV_LOG_WARN("invalid row or column"); return false; } uint32_t cell = row * table->col_cnt + col; @@ -473,14 +456,13 @@ bool lv_table_has_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table else return (table->cell_data[cell]->ctrl & ctrl) == ctrl; } -void lv_table_get_selected_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col) +void lv_table_get_selected_cell(lv_obj_t * obj, uint32_t * row, uint32_t * col) { lv_table_t * table = (lv_table_t *)obj; *row = table->row_act; *col = table->col_act; } -#if LV_USE_USER_DATA void * lv_table_get_cell_user_data(lv_obj_t * obj, uint16_t row, uint16_t col) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -496,7 +478,6 @@ void * lv_table_get_cell_user_data(lv_obj_t * obj, uint16_t row, uint16_t col) return table->cell_data[cell]->user_data; } -#endif /********************** * STATIC FUNCTIONS @@ -511,11 +492,11 @@ static void lv_table_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) table->col_cnt = 1; table->row_cnt = 1; - table->col_w = lv_mem_alloc(table->col_cnt * sizeof(table->col_w[0])); - table->row_h = lv_mem_alloc(table->row_cnt * sizeof(table->row_h[0])); + table->col_w = lv_malloc(table->col_cnt * sizeof(table->col_w[0])); + table->row_h = lv_malloc(table->row_cnt * sizeof(table->row_h[0])); table->col_w[0] = LV_DPI_DEF; table->row_h[0] = LV_DPI_DEF; - table->cell_data = lv_mem_realloc(table->cell_data, table->row_cnt * table->col_cnt * sizeof(lv_table_cell_t *)); + table->cell_data = lv_realloc(table->cell_data, table->row_cnt * table->col_cnt * sizeof(lv_table_cell_t *)); table->cell_data[0] = NULL; LV_TRACE_OBJ_CREATE("finished"); @@ -526,37 +507,35 @@ static void lv_table_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) LV_UNUSED(class_p); lv_table_t * table = (lv_table_t *)obj; /*Free the cell texts*/ - uint16_t i; + uint32_t i; for(i = 0; i < table->col_cnt * table->row_cnt; i++) { if(table->cell_data[i]) { -#if LV_USE_USER_DATA if(table->cell_data[i]->user_data) { - lv_mem_free(table->cell_data[i]->user_data); + lv_free(table->cell_data[i]->user_data); table->cell_data[i]->user_data = NULL; } -#endif - lv_mem_free(table->cell_data[i]); + lv_free(table->cell_data[i]); table->cell_data[i] = NULL; } } - if(table->cell_data) lv_mem_free(table->cell_data); - if(table->row_h) lv_mem_free(table->row_h); - if(table->col_w) lv_mem_free(table->col_w); + if(table->cell_data) lv_free(table->cell_data); + if(table->row_h) lv_free(table->row_h); + if(table->col_w) lv_free(table->col_w); } static void lv_table_event(const lv_obj_class_t * class_p, lv_event_t * e) { LV_UNUSED(class_p); - lv_res_t res; + lv_result_t res; /*Call the ancestor's event handler*/ res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_table_t * table = (lv_table_t *)obj; if(code == LV_EVENT_STYLE_CHANGED) { @@ -565,21 +544,21 @@ static void lv_table_event(const lv_obj_class_t * class_p, lv_event_t * e) else if(code == LV_EVENT_GET_SELF_SIZE) { lv_point_t * p = lv_event_get_param(e); uint32_t i; - lv_coord_t w = 0; + int32_t w = 0; for(i = 0; i < table->col_cnt; i++) w += table->col_w[i]; - lv_coord_t h = 0; + int32_t h = 0; for(i = 0; i < table->row_cnt; i++) h += table->row_h[i]; p->x = w - 1; p->y = h - 1; } else if(code == LV_EVENT_PRESSED || code == LV_EVENT_PRESSING) { - uint16_t col; - uint16_t row; - lv_res_t pr_res = get_pressed_cell(obj, &row, &col); + uint32_t col; + uint32_t row; + lv_result_t pr_res = get_pressed_cell(obj, &row, &col); - if(pr_res == LV_RES_OK && (table->col_act != col || table->row_act != row)) { + if(pr_res == LV_RESULT_OK && (table->col_act != col || table->row_act != row)) { table->col_act = col; table->row_act = row; lv_obj_invalidate(obj); @@ -587,14 +566,14 @@ static void lv_table_event(const lv_obj_class_t * class_p, lv_event_t * e) } else if(code == LV_EVENT_RELEASED) { lv_obj_invalidate(obj); - lv_indev_t * indev = lv_indev_get_act(); + lv_indev_t * indev = lv_indev_active(); lv_obj_t * scroll_obj = lv_indev_get_scroll_obj(indev); if(table->col_act != LV_TABLE_CELL_NONE && table->row_act != LV_TABLE_CELL_NONE && scroll_obj == NULL) { - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; + res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RESULT_OK) return; } - lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); + lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_active()); if(indev_type == LV_INDEV_TYPE_POINTER || indev_type == LV_INDEV_TYPE_BUTTON) { table->col_act = LV_TABLE_CELL_NONE; table->row_act = LV_TABLE_CELL_NONE; @@ -615,8 +594,8 @@ static void lv_table_event(const lv_obj_class_t * class_p, lv_event_t * e) return; } - if(col >= table->col_cnt) col = 0; - if(row >= table->row_cnt) row = 0; + if(col >= (int32_t)table->col_cnt) col = 0; + if(row >= (int32_t)table->row_cnt) row = 0; if(c == LV_KEY_LEFT) col--; else if(c == LV_KEY_RIGHT) col++; @@ -624,8 +603,8 @@ static void lv_table_event(const lv_obj_class_t * class_p, lv_event_t * e) else if(c == LV_KEY_DOWN) row++; else return; - if(col >= table->col_cnt) { - if(row < table->row_cnt - 1) { + if(col >= (int32_t)table->col_cnt) { + if(row < (int32_t)table->row_cnt - 1) { col = 0; row++; } @@ -643,22 +622,22 @@ static void lv_table_event(const lv_obj_class_t * class_p, lv_event_t * e) } } - if(row >= table->row_cnt) { + if(row >= (int32_t)table->row_cnt) { row = table->row_cnt - 1; } else if(row < 0) { row = 0; } - if(table->col_act != col || table->row_act != row) { + if((int32_t)table->col_act != col || (int32_t)table->row_act != row) { table->col_act = col; table->row_act = row; lv_obj_invalidate(obj); scroll_to_selected_cell(obj); + res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); - res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; } } else if(code == LV_EVENT_DRAW_MAIN) { @@ -666,26 +645,25 @@ static void lv_table_event(const lv_obj_class_t * class_p, lv_event_t * e) } } - static void draw_main(lv_event_t * e) { - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_table_t * table = (lv_table_t *)obj; - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); lv_area_t clip_area; - if(!_lv_area_intersect(&clip_area, &obj->coords, draw_ctx->clip_area)) return; + if(!_lv_area_intersect(&clip_area, &obj->coords, &layer->_clip_area)) return; - const lv_area_t * clip_area_ori = draw_ctx->clip_area; - draw_ctx->clip_area = &clip_area; + const lv_area_t clip_area_ori = layer->_clip_area; + layer->_clip_area = clip_area; lv_point_t txt_size; lv_area_t cell_area; - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); - lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); - lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); + int32_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + int32_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); + int32_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + int32_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); lv_state_t state_ori = obj->state; obj->state = LV_STATE_DEFAULT; @@ -702,25 +680,19 @@ static void draw_main(lv_event_t * e) obj->state = state_ori; obj->skip_trans = 0; - uint16_t col; - uint16_t row; - uint16_t cell = 0; + uint32_t col; + uint32_t row; + uint32_t cell = 0; cell_area.y2 = obj->coords.y1 + bg_top - 1 - lv_obj_get_scroll_y(obj) + border_width; - lv_coord_t scroll_x = lv_obj_get_scroll_x(obj) ; + cell_area.x1 = 0; + cell_area.x2 = 0; + int32_t scroll_x = lv_obj_get_scroll_x(obj) ; bool rtl = lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL; /*Handle custom drawer*/ - lv_obj_draw_part_dsc_t part_draw_dsc; - lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); - part_draw_dsc.part = LV_PART_ITEMS; - part_draw_dsc.class_p = MY_CLASS; - part_draw_dsc.type = LV_TABLE_DRAW_PART_CELL; - part_draw_dsc.rect_dsc = &rect_dsc_act; - part_draw_dsc.label_dsc = &label_dsc_act; - for(row = 0; row < table->row_cnt; row++) { - lv_coord_t h_row = table->row_h[row]; + int32_t h_row = table->row_h[row]; cell_area.y1 = cell_area.y2 + 1; cell_area.y2 = cell_area.y1 + h_row - 1; @@ -743,7 +715,7 @@ static void draw_main(lv_event_t * e) cell_area.x2 = cell_area.x1 + table->col_w[col] - 1; } - uint16_t col_merge = 0; + uint32_t col_merge = 0; for(col_merge = 0; col_merge + col < table->col_cnt - 1; col_merge++) { lv_table_cell_t * next_cell_data = table->cell_data[cell + col_merge]; @@ -751,7 +723,7 @@ static void draw_main(lv_event_t * e) lv_table_cell_ctrl_t merge_ctrl = (lv_table_cell_ctrl_t) next_cell_data->ctrl; if(merge_ctrl & LV_TABLE_CELL_CTRL_MERGE_RIGHT) { - lv_coord_t offset = table->col_w[col + col_merge + 1]; + int32_t offset = table->col_w[col + col_merge + 1]; if(rtl) cell_area.x1 -= offset; else cell_area.x2 += offset; @@ -809,17 +781,18 @@ static void draw_main(lv_event_t * e) obj->skip_trans = 0; } - part_draw_dsc.draw_area = &cell_area_border; - part_draw_dsc.id = row * table->col_cnt + col; - lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); + rect_dsc_act.base.id1 = row; + rect_dsc_act.base.id2 = col; + label_dsc_act.base.id1 = row; + label_dsc_act.base.id2 = col; - lv_draw_rect(draw_ctx, &rect_dsc_act, &cell_area_border); + lv_draw_rect(layer, &rect_dsc_act, &cell_area_border); if(table->cell_data[cell]) { - const lv_coord_t cell_left = lv_obj_get_style_pad_left(obj, LV_PART_ITEMS); - const lv_coord_t cell_right = lv_obj_get_style_pad_right(obj, LV_PART_ITEMS); - const lv_coord_t cell_top = lv_obj_get_style_pad_top(obj, LV_PART_ITEMS); - const lv_coord_t cell_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_ITEMS); + const int32_t cell_left = lv_obj_get_style_pad_left(obj, LV_PART_ITEMS); + const int32_t cell_right = lv_obj_get_style_pad_right(obj, LV_PART_ITEMS); + const int32_t cell_top = lv_obj_get_style_pad_top(obj, LV_PART_ITEMS); + const int32_t cell_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_ITEMS); lv_text_flag_t txt_flags = LV_TEXT_FLAG_NONE; lv_area_t txt_area; @@ -829,12 +802,12 @@ static void draw_main(lv_event_t * e) txt_area.y2 = cell_area.y2 - cell_bottom; /*Align the content to the middle if not cropped*/ - bool crop = ctrl & LV_TABLE_CELL_CTRL_TEXT_CROP ? true : false; + bool crop = ctrl & LV_TABLE_CELL_CTRL_TEXT_CROP; if(crop) txt_flags = LV_TEXT_FLAG_EXPAND; - lv_txt_get_size(&txt_size, table->cell_data[cell]->txt, label_dsc_def.font, - label_dsc_act.letter_space, label_dsc_act.line_space, - lv_area_get_width(&txt_area), txt_flags); + lv_text_get_size(&txt_size, table->cell_data[cell]->txt, label_dsc_def.font, + label_dsc_act.letter_space, label_dsc_act.line_space, + lv_area_get_width(&txt_area), txt_flags); /*Align the content to the middle if not cropped*/ if(!crop) { @@ -846,42 +819,41 @@ static void draw_main(lv_event_t * e) bool label_mask_ok; label_mask_ok = _lv_area_intersect(&label_clip_area, &clip_area, &cell_area); if(label_mask_ok) { - draw_ctx->clip_area = &label_clip_area; - lv_draw_label(draw_ctx, &label_dsc_act, &txt_area, table->cell_data[cell]->txt, NULL); - draw_ctx->clip_area = &clip_area; + layer->_clip_area = label_clip_area; + label_dsc_act.text = table->cell_data[cell]->txt; + lv_draw_label(layer, &label_dsc_act, &txt_area); + layer->_clip_area = clip_area; } } - lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); - cell += col_merge + 1; col += col_merge; } } - draw_ctx->clip_area = clip_area_ori; + layer->_clip_area = clip_area_ori; } /* Refreshes size of the table starting from @start_row row */ static void refr_size_form_row(lv_obj_t * obj, uint32_t start_row) { - const lv_coord_t cell_pad_left = lv_obj_get_style_pad_left(obj, LV_PART_ITEMS); - const lv_coord_t cell_pad_right = lv_obj_get_style_pad_right(obj, LV_PART_ITEMS); - const lv_coord_t cell_pad_top = lv_obj_get_style_pad_top(obj, LV_PART_ITEMS); - const lv_coord_t cell_pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_ITEMS); + const int32_t cell_pad_left = lv_obj_get_style_pad_left(obj, LV_PART_ITEMS); + const int32_t cell_pad_right = lv_obj_get_style_pad_right(obj, LV_PART_ITEMS); + const int32_t cell_pad_top = lv_obj_get_style_pad_top(obj, LV_PART_ITEMS); + const int32_t cell_pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_ITEMS); - lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_ITEMS); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_ITEMS); + int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_ITEMS); + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_ITEMS); const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_ITEMS); - const lv_coord_t minh = lv_obj_get_style_min_height(obj, LV_PART_ITEMS); - const lv_coord_t maxh = lv_obj_get_style_max_height(obj, LV_PART_ITEMS); + const int32_t minh = lv_obj_get_style_min_height(obj, LV_PART_ITEMS); + const int32_t maxh = lv_obj_get_style_max_height(obj, LV_PART_ITEMS); lv_table_t * table = (lv_table_t *)obj; uint32_t i; for(i = start_row; i < table->row_cnt; i++) { - lv_coord_t calculated_height = get_row_height(obj, i, font, letter_space, line_space, - cell_pad_left, cell_pad_right, cell_pad_top, cell_pad_bottom); + int32_t calculated_height = get_row_height(obj, i, font, letter_space, line_space, + cell_pad_left, cell_pad_right, cell_pad_top, cell_pad_bottom); table->row_h[i] = LV_CLAMP(minh, calculated_height, maxh); } @@ -889,29 +861,28 @@ static void refr_size_form_row(lv_obj_t * obj, uint32_t start_row) lv_obj_invalidate(obj); } - static void refr_cell_size(lv_obj_t * obj, uint32_t row, uint32_t col) { - const lv_coord_t cell_pad_left = lv_obj_get_style_pad_left(obj, LV_PART_ITEMS); - const lv_coord_t cell_pad_right = lv_obj_get_style_pad_right(obj, LV_PART_ITEMS); - const lv_coord_t cell_pad_top = lv_obj_get_style_pad_top(obj, LV_PART_ITEMS); - const lv_coord_t cell_pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_ITEMS); + const int32_t cell_pad_left = lv_obj_get_style_pad_left(obj, LV_PART_ITEMS); + const int32_t cell_pad_right = lv_obj_get_style_pad_right(obj, LV_PART_ITEMS); + const int32_t cell_pad_top = lv_obj_get_style_pad_top(obj, LV_PART_ITEMS); + const int32_t cell_pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_ITEMS); - lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_ITEMS); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_ITEMS); + int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_ITEMS); + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_ITEMS); const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_ITEMS); - const lv_coord_t minh = lv_obj_get_style_min_height(obj, LV_PART_ITEMS); - const lv_coord_t maxh = lv_obj_get_style_max_height(obj, LV_PART_ITEMS); + const int32_t minh = lv_obj_get_style_min_height(obj, LV_PART_ITEMS); + const int32_t maxh = lv_obj_get_style_max_height(obj, LV_PART_ITEMS); lv_table_t * table = (lv_table_t *)obj; - lv_coord_t calculated_height = get_row_height(obj, row, font, letter_space, line_space, - cell_pad_left, cell_pad_right, cell_pad_top, cell_pad_bottom); + int32_t calculated_height = get_row_height(obj, row, font, letter_space, line_space, + cell_pad_left, cell_pad_right, cell_pad_top, cell_pad_bottom); - lv_coord_t prev_row_size = table->row_h[row]; + int32_t prev_row_size = table->row_h[row]; table->row_h[row] = LV_CLAMP(minh, calculated_height, maxh); - /*If the row height havn't changed invalidate only this cell*/ + /*If the row height haven't changed invalidate only this cell*/ if(prev_row_size == table->row_h[row]) { lv_area_t cell_area; get_cell_area(obj, row, col, &cell_area); @@ -924,19 +895,19 @@ static void refr_cell_size(lv_obj_t * obj, uint32_t row, uint32_t col) } } -static lv_coord_t get_row_height(lv_obj_t * obj, uint16_t row_id, const lv_font_t * font, - lv_coord_t letter_space, lv_coord_t line_space, - lv_coord_t cell_left, lv_coord_t cell_right, lv_coord_t cell_top, lv_coord_t cell_bottom) +static int32_t get_row_height(lv_obj_t * obj, uint32_t row_id, const lv_font_t * font, + int32_t letter_space, int32_t line_space, + int32_t cell_left, int32_t cell_right, int32_t cell_top, int32_t cell_bottom) { lv_table_t * table = (lv_table_t *)obj; - lv_coord_t h_max = lv_font_get_line_height(font) + cell_top + cell_bottom; + int32_t h_max = lv_font_get_line_height(font) + cell_top + cell_bottom; /* Calculate the cell_data index where to start */ - uint16_t row_start = row_id * table->col_cnt; + uint32_t row_start = row_id * table->col_cnt; /* Traverse the cells in the row_id row */ - uint16_t cell; - uint16_t col; + uint32_t cell; + uint32_t col; for(cell = row_start, col = 0; cell < row_start + table->col_cnt; cell++, col++) { lv_table_cell_t * cell_data = table->cell_data[cell]; @@ -944,12 +915,12 @@ static lv_coord_t get_row_height(lv_obj_t * obj, uint16_t row_id, const lv_font_ continue; } - lv_coord_t txt_w = table->col_w[col]; + int32_t txt_w = table->col_w[col]; /* Traverse the current row from the first until the penultimate column. * Increment the text width if the cell has the LV_TABLE_CELL_CTRL_MERGE_RIGHT control, * exit the traversal when the current cell control is not LV_TABLE_CELL_CTRL_MERGE_RIGHT */ - uint16_t col_merge = 0; + uint32_t col_merge = 0; for(col_merge = 0; col_merge + col < table->col_cnt - 1; col_merge++) { lv_table_cell_t * next_cell_data = table->cell_data[cell + col_merge]; @@ -976,8 +947,8 @@ static lv_coord_t get_row_height(lv_obj_t * obj, uint16_t row_id, const lv_font_ lv_point_t txt_size; txt_w -= cell_left + cell_right; - lv_txt_get_size(&txt_size, table->cell_data[cell]->txt, font, - letter_space, line_space, txt_w, LV_TEXT_FLAG_NONE); + lv_text_get_size(&txt_size, table->cell_data[cell]->txt, font, + letter_space, line_space, txt_w, LV_TEXT_FLAG_NONE); h_max = LV_MAX(txt_size.y + cell_top + cell_bottom, h_max); /*Skip until one element after the last merged column*/ @@ -989,23 +960,23 @@ static lv_coord_t get_row_height(lv_obj_t * obj, uint16_t row_id, const lv_font_ return h_max; } -static lv_res_t get_pressed_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col) +static lv_result_t get_pressed_cell(lv_obj_t * obj, uint32_t * row, uint32_t * col) { lv_table_t * table = (lv_table_t *)obj; - lv_indev_type_t type = lv_indev_get_type(lv_indev_get_act()); + lv_indev_type_t type = lv_indev_get_type(lv_indev_active()); if(type != LV_INDEV_TYPE_POINTER && type != LV_INDEV_TYPE_BUTTON) { if(col) *col = LV_TABLE_CELL_NONE; if(row) *row = LV_TABLE_CELL_NONE; - return LV_RES_INV; + return LV_RESULT_INVALID; } lv_point_t p; - lv_indev_get_point(lv_indev_get_act(), &p); + lv_indev_get_point(lv_indev_active(), &p); - lv_coord_t tmp; + int32_t tmp; if(col) { - lv_coord_t x = p.x + lv_obj_get_scroll_x(obj); + int32_t x = p.x + lv_obj_get_scroll_x(obj); if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) { x = obj->coords.x2 - lv_obj_get_style_pad_right(obj, LV_PART_MAIN) - x; @@ -1024,7 +995,7 @@ static lv_res_t get_pressed_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col) } if(row) { - lv_coord_t y = p.y + lv_obj_get_scroll_y(obj);; + int32_t y = p.y + lv_obj_get_scroll_y(obj);; y -= obj->coords.y1; y -= lv_obj_get_style_pad_top(obj, LV_PART_MAIN); @@ -1037,7 +1008,7 @@ static lv_res_t get_pressed_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col) } } - return LV_RES_OK; + return LV_RESULT_OK; } /* Returns number of bytes to allocate based on chars configuration */ @@ -1046,7 +1017,7 @@ static size_t get_cell_txt_len(const char * txt) size_t retval = 0; #if LV_USE_ARABIC_PERSIAN_CHARS - retval = sizeof(lv_table_cell_t) + _lv_txt_ap_calc_bytes_cnt(txt) + 1; + retval = sizeof(lv_table_cell_t) + _lv_text_ap_calc_bytes_count(txt) + 1; #else retval = sizeof(lv_table_cell_t) + strlen(txt) + 1; #endif @@ -1058,13 +1029,13 @@ static size_t get_cell_txt_len(const char * txt) static void copy_cell_txt(lv_table_cell_t * dst, const char * txt) { #if LV_USE_ARABIC_PERSIAN_CHARS - _lv_txt_ap_proc(txt, dst->txt); + _lv_text_ap_proc(txt, dst->txt); #else strcpy(dst->txt, txt); #endif } -static void get_cell_area(lv_obj_t * obj, uint16_t row, uint16_t col, lv_area_t * area) +static void get_cell_area(lv_obj_t * obj, uint32_t row, uint32_t col, lv_area_t * area) { lv_table_t * table = (lv_table_t *)obj; @@ -1077,7 +1048,7 @@ static void get_cell_area(lv_obj_t * obj, uint16_t row, uint16_t col, lv_area_t bool rtl = lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL; if(rtl) { area->x1 += lv_obj_get_scroll_x(obj); - lv_coord_t w = lv_obj_get_width(obj); + int32_t w = lv_obj_get_width(obj); area->x2 = w - area->x1 - lv_obj_get_style_pad_right(obj, 0); area->x1 = area->x2 - table->col_w[col]; } @@ -1099,7 +1070,6 @@ static void get_cell_area(lv_obj_t * obj, uint16_t row, uint16_t col, lv_area_t } - static void scroll_to_selected_cell(lv_obj_t * obj) { lv_table_t * table = (lv_table_t *)obj; diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_table.h b/lib/libesp32_lvgl/lvgl/src/widgets/table/lv_table.h similarity index 76% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_table.h rename to lib/libesp32_lvgl/lvgl/src/widgets/table/lv_table.h index 9c60a7673..80db47b05 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_table.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/table/lv_table.h @@ -13,7 +13,8 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../lv_conf_internal.h" + +#include "../label/lv_label.h" #if LV_USE_TABLE != 0 @@ -22,9 +23,6 @@ extern "C" { #error "lv_table: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1)" #endif -#include "../core/lv_obj.h" -#include "lv_label.h" - /********************* * DEFINES *********************/ @@ -35,7 +33,7 @@ LV_EXPORT_CONST_INT(LV_TABLE_CELL_NONE); * TYPEDEFS **********************/ -enum { +enum _lv_table_cell_ctrl_t { LV_TABLE_CELL_CTRL_MERGE_RIGHT = 1 << 0, LV_TABLE_CELL_CTRL_TEXT_CROP = 1 << 1, LV_TABLE_CELL_CTRL_CUSTOM_1 = 1 << 4, @@ -44,38 +42,32 @@ enum { LV_TABLE_CELL_CTRL_CUSTOM_4 = 1 << 7, }; -typedef uint8_t lv_table_cell_ctrl_t; +#ifdef DOXYGEN +typedef _lv_table_cell_ctrl_t lv_table_cell_ctrl_t; +#else +typedef uint32_t lv_table_cell_ctrl_t; +#endif /*DOXYGEN*/ /*Data of cell*/ typedef struct { lv_table_cell_ctrl_t ctrl; -#if LV_USE_USER_DATA void * user_data; /**< Custom user data*/ -#endif char txt[]; } lv_table_cell_t; /*Data of table*/ typedef struct { lv_obj_t obj; - uint16_t col_cnt; - uint16_t row_cnt; + uint32_t col_cnt; + uint32_t row_cnt; lv_table_cell_t ** cell_data; - lv_coord_t * row_h; - lv_coord_t * col_w; - uint16_t col_act; - uint16_t row_act; + int32_t * row_h; + int32_t * col_w; + uint32_t col_act; + uint32_t row_act; } lv_table_t; -extern const lv_obj_class_t lv_table_class; - -/** - * `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_table_class` - * Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END` - */ -typedef enum { - LV_TABLE_DRAW_PART_CELL, /**< A cell*/ -} lv_table_draw_part_type_t; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_table_class; /********************** * GLOBAL PROTOTYPES @@ -100,7 +92,7 @@ lv_obj_t * lv_table_create(lv_obj_t * parent); * @param txt text to display in the cell. It will be copied and saved so this variable is not required after this function call. * @note New roes/columns are added automatically if required */ -void lv_table_set_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col, const char * txt); +void lv_table_set_cell_value(lv_obj_t * obj, uint32_t row, uint32_t col, const char * txt); /** * Set the value of a cell. Memory will be allocated to store the text by the table. @@ -110,21 +102,22 @@ void lv_table_set_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col, const c * @param fmt `printf`-like format * @note New roes/columns are added automatically if required */ -void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, const char * fmt, ...); +void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint32_t row, uint32_t col, const char * fmt, + ...) LV_FORMAT_ATTRIBUTE(4, 5); /** * Set the number of rows * @param obj table pointer to a Table object * @param row_cnt number of rows */ -void lv_table_set_row_cnt(lv_obj_t * obj, uint16_t row_cnt); +void lv_table_set_row_count(lv_obj_t * obj, uint32_t row_cnt); /** * Set the number of columns * @param obj table pointer to a Table object * @param col_cnt number of columns. */ -void lv_table_set_col_cnt(lv_obj_t * obj, uint16_t col_cnt); +void lv_table_set_column_count(lv_obj_t * obj, uint32_t col_cnt); /** * Set the width of a column @@ -132,7 +125,7 @@ void lv_table_set_col_cnt(lv_obj_t * obj, uint16_t col_cnt); * @param col_id id of the column [0 .. LV_TABLE_COL_MAX -1] * @param w width of the column */ -void lv_table_set_col_width(lv_obj_t * obj, uint16_t col_id, lv_coord_t w); +void lv_table_set_column_width(lv_obj_t * obj, uint32_t col_id, int32_t w); /** * Add control bits to the cell. @@ -141,8 +134,7 @@ void lv_table_set_col_width(lv_obj_t * obj, uint16_t col_id, lv_coord_t w); * @param col id of the column [0 .. col_cnt -1] * @param ctrl OR-ed values from ::lv_table_cell_ctrl_t */ -void lv_table_add_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl); - +void lv_table_add_cell_ctrl(lv_obj_t * obj, uint32_t row, uint32_t col, lv_table_cell_ctrl_t ctrl); /** * Clear control bits of the cell. @@ -151,18 +143,19 @@ void lv_table_add_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table * @param col id of the column [0 .. col_cnt -1] * @param ctrl OR-ed values from ::lv_table_cell_ctrl_t */ -void lv_table_clear_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl); +void lv_table_clear_cell_ctrl(lv_obj_t * obj, uint32_t row, uint32_t col, lv_table_cell_ctrl_t ctrl); -#if LV_USE_USER_DATA /** * Add custom user data to the cell. * @param obj pointer to a Table object * @param row id of the row [0 .. row_cnt -1] * @param col id of the column [0 .. col_cnt -1] - * @param user_data pointer to the new user_data. It must be allocated by user as it will be freed automatically + * @param user_data pointer to the new user_data. + * Should be allocated by `lv_malloc`, + * and it will be freed automatically when the table is deleted or + * when the cell is dropped due to lower row or column count. */ void lv_table_set_cell_user_data(lv_obj_t * obj, uint16_t row, uint16_t col, void * user_data); -#endif /*===================== * Getter functions @@ -175,21 +168,21 @@ void lv_table_set_cell_user_data(lv_obj_t * obj, uint16_t row, uint16_t col, voi * @param col id of the column [0 .. col_cnt -1] * @return text in the cell */ -const char * lv_table_get_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col); +const char * lv_table_get_cell_value(lv_obj_t * obj, uint32_t row, uint32_t col); /** * Get the number of rows. * @param obj table pointer to a Table object * @return number of rows. */ -uint16_t lv_table_get_row_cnt(lv_obj_t * obj); +uint32_t lv_table_get_row_count(lv_obj_t * obj); /** * Get the number of columns. * @param obj table pointer to a Table object * @return number of columns. */ -uint16_t lv_table_get_col_cnt(lv_obj_t * obj); +uint32_t lv_table_get_column_count(lv_obj_t * obj); /** * Get the width of a column @@ -197,7 +190,7 @@ uint16_t lv_table_get_col_cnt(lv_obj_t * obj); * @param col id of the column [0 .. LV_TABLE_COL_MAX -1] * @return width of the column */ -lv_coord_t lv_table_get_col_width(lv_obj_t * obj, uint16_t col); +int32_t lv_table_get_column_width(lv_obj_t * obj, uint32_t col); /** * Get whether a cell has the control bits @@ -207,7 +200,7 @@ lv_coord_t lv_table_get_col_width(lv_obj_t * obj, uint16_t col); * @param ctrl OR-ed values from ::lv_table_cell_ctrl_t * @return true: all control bits are set; false: not all control bits are set */ -bool lv_table_has_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl); +bool lv_table_has_cell_ctrl(lv_obj_t * obj, uint32_t row, uint32_t col, lv_table_cell_ctrl_t ctrl); /** * Get the selected cell (pressed and or focused) @@ -215,9 +208,8 @@ bool lv_table_has_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table * @param row pointer to variable to store the selected row (LV_TABLE_CELL_NONE: if no cell selected) * @param col pointer to variable to store the selected column (LV_TABLE_CELL_NONE: if no cell selected) */ -void lv_table_get_selected_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col); +void lv_table_get_selected_cell(lv_obj_t * obj, uint32_t * row, uint32_t * col); -#if LV_USE_USER_DATA /** * Get custom user data to the cell. * @param obj pointer to a Table object @@ -225,7 +217,6 @@ void lv_table_get_selected_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col); * @param col id of the column [0 .. col_cnt -1] */ void * lv_table_get_cell_user_data(lv_obj_t * obj, uint16_t row, uint16_t col); -#endif /********************** * MACROS diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/tabview/lv_tabview.c b/lib/libesp32_lvgl/lvgl/src/widgets/tabview/lv_tabview.c new file mode 100644 index 000000000..f0e11952f --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/tabview/lv_tabview.c @@ -0,0 +1,344 @@ +/** + * @file lv_tabview.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_tabview.h" +#if LV_USE_TABVIEW + +#include "../../misc/lv_assert.h" +#include "../../indev/lv_indev_private.h" + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_tabview_class + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_tabview_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_tabview_event(const lv_obj_class_t * class_p, lv_event_t * e); +static void button_clicked_event_cb(lv_event_t * e); +static void cont_scroll_end_event_cb(lv_event_t * e); + +/********************** + * STATIC VARIABLES + **********************/ +const lv_obj_class_t lv_tabview_class = { + .constructor_cb = lv_tabview_constructor, + .event_cb = lv_tabview_event, + .width_def = LV_PCT(100), + .height_def = LV_PCT(100), + .base_class = &lv_obj_class, + .instance_size = sizeof(lv_tabview_t), + .name = "tabview", +}; + +typedef struct { + lv_dir_t tab_pos; + int32_t tab_size; +} lv_tabview_create_info_t; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_tabview_create(lv_obj_t * parent) +{ + LV_LOG_INFO("begin"); + + lv_obj_t * obj = lv_obj_class_create_obj(&lv_tabview_class, parent); + lv_obj_class_init_obj(obj); + return obj; +} + +lv_obj_t * lv_tabview_add_tab(lv_obj_t * obj, const char * name) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_obj_t * cont = lv_tabview_get_content(obj); + + lv_obj_t * page = lv_obj_create(cont); + lv_obj_set_size(page, lv_pct(100), lv_pct(100)); + uint32_t tab_idx = lv_obj_get_child_count(cont); + + lv_obj_t * tab_bar = lv_tabview_get_tab_bar(obj); + + lv_obj_t * button = lv_button_create(tab_bar); + lv_obj_set_flex_grow(button, 1); + lv_obj_set_size(button, lv_pct(100), lv_pct(100)); + lv_obj_add_event_cb(button, button_clicked_event_cb, LV_EVENT_CLICKED, NULL); + lv_group_t * g = lv_group_get_default(); + if(g) lv_group_add_obj(g, button); + + lv_obj_t * label = lv_label_create(button); + lv_label_set_text(label, name); + lv_obj_center(label); + + if(tab_idx == 1) { + lv_tabview_set_active(obj, 0, LV_ANIM_OFF); + } + + return page; +} + +void lv_tabview_rename_tab(lv_obj_t * obj, uint32_t idx, const char * new_name) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_obj_t * tab_bar = lv_tabview_get_tab_bar(obj); + lv_obj_t * button = lv_obj_get_child_by_type(tab_bar, idx, &lv_button_class); + lv_obj_t * label = lv_obj_get_child_by_type(button, 0, &lv_label_class); + lv_label_set_text(label, new_name); +} + +void lv_tabview_set_active(lv_obj_t * obj, uint32_t idx, lv_anim_enable_t anim_en) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_tabview_t * tabview = (lv_tabview_t *)obj; + + lv_obj_t * cont = lv_tabview_get_content(obj); + lv_obj_t * tab_bar = lv_tabview_get_tab_bar(obj); + + uint32_t tab_cnt = lv_tabview_get_tab_count(obj); + if(idx >= tab_cnt) { + idx = tab_cnt - 1; + } + + /*To be sure lv_obj_get_content_width will return valid value*/ + lv_obj_update_layout(obj); + + if(cont == NULL) return; + + if((tabview->tab_pos & LV_DIR_VER) != 0) { + int32_t gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN); + int32_t w = lv_obj_get_content_width(cont); + if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) { + lv_obj_scroll_to_x(cont, idx * (gap + w), anim_en); + } + else { + int32_t id_rtl = -(int32_t)idx; + lv_obj_scroll_to_x(cont, (gap + w) * id_rtl, anim_en); + } + } + else { + int32_t gap = lv_obj_get_style_pad_row(cont, LV_PART_MAIN); + int32_t h = lv_obj_get_content_height(cont); + lv_obj_scroll_to_y(cont, idx * (gap + h), anim_en); + } + + uint32_t i = 0; + lv_obj_t * button = lv_obj_get_child_by_type(tab_bar, i, &lv_button_class); + while(button) { + lv_obj_set_state(button, LV_STATE_CHECKED, i == idx); + i++; + button = lv_obj_get_child_by_type(tab_bar, (int32_t)i, &lv_button_class); + } + + tabview->tab_cur = idx; +} + +void lv_tabview_set_tab_bar_position(lv_obj_t * obj, lv_dir_t dir) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_tabview_t * tabview = (lv_tabview_t *)obj; + + switch(dir) { + case LV_DIR_TOP: + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN); + break; + case LV_DIR_BOTTOM: + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN_REVERSE); + break; + case LV_DIR_LEFT: + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW); + break; + case LV_DIR_RIGHT: + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW_REVERSE); + break; + } + + lv_obj_t * tab_bar = lv_tabview_get_tab_bar(obj); + lv_obj_t * cont = lv_tabview_get_content(obj); + + switch(dir) { + case LV_DIR_TOP: + case LV_DIR_BOTTOM: + lv_obj_set_width(cont, LV_PCT(100)); + lv_obj_set_flex_grow(cont, 1); + lv_obj_set_flex_flow(tab_bar, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_ROW); + lv_obj_set_scroll_snap_x(cont, LV_SCROLL_SNAP_CENTER); + lv_obj_set_scroll_snap_y(cont, LV_SCROLL_SNAP_NONE); + break; + case LV_DIR_LEFT: + case LV_DIR_RIGHT: + lv_obj_set_height(cont, LV_PCT(100)); + lv_obj_set_flex_grow(cont, 1); + lv_obj_set_flex_flow(tab_bar, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN); + lv_obj_set_scroll_snap_x(cont, LV_SCROLL_SNAP_NONE); + lv_obj_set_scroll_snap_y(cont, LV_SCROLL_SNAP_CENTER); + break; + } + + bool was_ver = tabview->tab_pos & LV_DIR_VER; + bool now_ver = dir & LV_DIR_VER; + + if(was_ver != now_ver) { + int32_t dpi = lv_display_get_dpi(lv_obj_get_display(obj)); + if(now_ver) { + lv_obj_set_size(tab_bar, lv_pct(100), dpi / 2); + } + else { + lv_obj_set_size(tab_bar, dpi, lv_pct(100)); + } + } + tabview->tab_pos = dir; +} + +void lv_tabview_set_tab_bar_size(lv_obj_t * obj, int32_t size) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_tabview_t * tabview = (lv_tabview_t *)obj; + + lv_obj_t * tab_bar = lv_tabview_get_tab_bar(obj); + if(tabview->tab_pos & LV_DIR_VER) { + lv_obj_set_height(tab_bar, size); + } + else { + lv_obj_set_width(tab_bar, size); + } + +} + +uint32_t lv_tabview_get_tab_active(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_tabview_t * tabview = (lv_tabview_t *)obj; + return tabview->tab_cur; +} + +uint32_t lv_tabview_get_tab_count(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_obj_t * tab_bar = lv_tabview_get_tab_bar(obj); + return lv_obj_get_child_count_by_type(tab_bar, &lv_button_class); +} + +lv_obj_t * lv_tabview_get_content(lv_obj_t * tv) +{ + return lv_obj_get_child(tv, 1); +} + +lv_obj_t * lv_tabview_get_tab_bar(lv_obj_t * tv) +{ + return lv_obj_get_child(tv, 0); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_tabview_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + lv_tabview_t * tabview = (lv_tabview_t *)obj; + tabview->tab_pos = LV_DIR_NONE; /*Invalid value to apply the default TOP direction correctly*/ + + lv_obj_set_size(obj, LV_PCT(100), LV_PCT(100)); + + lv_obj_t * cont; + + lv_obj_create(obj); + cont = lv_obj_create(obj); + lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_ROW); + + lv_obj_add_event_cb(cont, cont_scroll_end_event_cb, LV_EVENT_ALL, NULL); + lv_obj_set_scrollbar_mode(cont, LV_SCROLLBAR_MODE_OFF); + lv_tabview_set_tab_bar_position(obj, LV_DIR_TOP); + + lv_obj_add_flag(cont, LV_OBJ_FLAG_SCROLL_ONE); + lv_obj_remove_flag(cont, LV_OBJ_FLAG_SCROLL_ON_FOCUS); +} + +static void lv_tabview_event(const lv_obj_class_t * class_p, lv_event_t * e) +{ + LV_UNUSED(class_p); + lv_result_t res = lv_obj_event_base(&lv_tabview_class, e); + if(res != LV_RESULT_OK) return; + + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * target = lv_event_get_current_target(e); + + if(code == LV_EVENT_SIZE_CHANGED) { + lv_tabview_set_active(target, lv_tabview_get_tab_active(target), LV_ANIM_OFF); + } +} + +static void button_clicked_event_cb(lv_event_t * e) +{ + lv_obj_t * button = lv_event_get_current_target(e); + + lv_obj_t * tv = lv_obj_get_parent(lv_obj_get_parent(button)); + int32_t idx = lv_obj_get_index_by_type(button, &lv_button_class); + lv_tabview_set_active(tv, idx, LV_ANIM_OFF); +} + +static void cont_scroll_end_event_cb(lv_event_t * e) +{ + lv_obj_t * cont = lv_event_get_current_target(e); + lv_event_code_t code = lv_event_get_code(e); + + lv_obj_t * tv = lv_obj_get_parent(cont); + lv_tabview_t * tv_obj = (lv_tabview_t *)tv; + if(code == LV_EVENT_LAYOUT_CHANGED) { + lv_tabview_set_active(tv, lv_tabview_get_tab_active(tv), LV_ANIM_OFF); + } + else if(code == LV_EVENT_SCROLL_END) { + lv_indev_t * indev = lv_indev_active(); + if(indev && indev->state == LV_INDEV_STATE_PRESSED) { + return; + } + + lv_point_t p; + lv_obj_get_scroll_end(cont, &p); + + int32_t t; + if((tv_obj->tab_pos & LV_DIR_VER) != 0) { + int32_t w = lv_obj_get_content_width(cont); + if(lv_obj_get_style_base_dir(tv, LV_PART_MAIN) == LV_BASE_DIR_RTL) t = -(p.x - w / 2) / w; + else t = (p.x + w / 2) / w; + } + else { + int32_t h = lv_obj_get_content_height(cont); + t = (p.y + h / 2) / h; + } + + if(t < 0) t = 0; + bool new_tab = false; + if(t != (int32_t)lv_tabview_get_tab_active(tv)) new_tab = true; + + /*If not scrolled by an indev set the tab immediately*/ + if(lv_indev_active()) { + lv_tabview_set_active(tv, t, LV_ANIM_ON); + } + else { + lv_tabview_set_active(tv, t, LV_ANIM_OFF); + } + + if(new_tab) lv_obj_send_event(tv, LV_EVENT_VALUE_CHANGED, NULL); + } +} +#endif /*LV_USE_TABVIEW*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/tabview/lv_tabview.h b/lib/libesp32_lvgl/lvgl/src/widgets/tabview/lv_tabview.h new file mode 100644 index 000000000..27e8a394e --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/widgets/tabview/lv_tabview.h @@ -0,0 +1,123 @@ +/** + * @file lv_templ.h + * + */ + +#ifndef LV_TABVIEW_H +#define LV_TABVIEW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" + +#if LV_USE_TABVIEW + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +typedef struct { + lv_obj_t obj; + uint32_t tab_cur; + lv_dir_t tab_pos; +} lv_tabview_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_tabview_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a tabview widget + * @param parent pointer to a parent widget + * @return the created tabview + */ +lv_obj_t * lv_tabview_create(lv_obj_t * parent); + +/** + * Add a tab to the tabview + * @param obj pointer to a tabview widget + * @param name the name of the tab, it will be displayed on the tab bar + * @return the widget where the content of the tab can be created + */ +lv_obj_t * lv_tabview_add_tab(lv_obj_t * obj, const char * name); + +/** + * Change the name of the tab + * @param obj pointer to a tabview widget + * @param idx the index of the tab to rename + * @param new_name the new name as a string + */ +void lv_tabview_rename_tab(lv_obj_t * obj, uint32_t idx, const char * new_name); + +/** + * Show a tab + * @param obj pointer to a tabview widget + * @param idx the index of the tab to show + * @param anim_en LV_ANIM_ON/OFF + */ +void lv_tabview_set_active(lv_obj_t * obj, uint32_t idx, lv_anim_enable_t anim_en); + +/** + * Set the position of the tab bar + * @param obj pointer to a tabview widget + * @param dir LV_DIR_TOP/BOTTOM/LEFT/RIGHT + */ +void lv_tabview_set_tab_bar_position(lv_obj_t * obj, lv_dir_t dir); + +/** + * Set the width or height of the tab bar + * @param size size of the tab bar in pixels or percentage. + * will be used as width or height based on the position of the tab bar) + */ +void lv_tabview_set_tab_bar_size(lv_obj_t * obj, int32_t size); + +/** + * Get the number of tabs + * @param obj pointer to a tabview widget + * @return the number of tabs + */ +uint32_t lv_tabview_get_tab_count(lv_obj_t * obj); + +/** + * Get the current tab's index + * @param obj pointer to a tabview widget + * @return the zero based indoex of the current tab + */ +uint32_t lv_tabview_get_tab_active(lv_obj_t * obj); + +/** + * Get the widget where the container of each tab is created + * @param obj pointer to a tabview widget + * @return the main container widget + */ +lv_obj_t * lv_tabview_get_content(lv_obj_t * obj); + +/** + * Get the tab bar where the buttons are created + * @param obj pointer to a tabview widget + * @return the tabbar + */ +lv_obj_t * lv_tabview_get_tab_bar(lv_obj_t * obj); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_TABVIEW*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_TABVIEW_H*/ diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.c b/lib/libesp32_lvgl/lvgl/src/widgets/textarea/lv_textarea.c similarity index 80% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.c rename to lib/libesp32_lvgl/lvgl/src/widgets/textarea/lv_textarea.c index 4d497e669..8a76e5f79 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/textarea/lv_textarea.c @@ -10,14 +10,15 @@ #if LV_USE_TEXTAREA != 0 #include -#include "../misc/lv_assert.h" -#include "../core/lv_group.h" -#include "../core/lv_refr.h" -#include "../core/lv_indev.h" -#include "../draw/lv_draw.h" -#include "../misc/lv_anim.h" -#include "../misc/lv_txt.h" -#include "../misc/lv_math.h" +#include "../../core/lv_group.h" +#include "../../core/lv_refr.h" +#include "../../indev/lv_indev.h" +#include "../../draw/lv_draw.h" +#include "../../misc/lv_assert.h" +#include "../../misc/lv_anim.h" +#include "../../misc/lv_text.h" +#include "../../misc/lv_math.h" +#include "../../stdlib/lv_string.h" /********************* * DEFINES @@ -49,13 +50,13 @@ static void lv_textarea_event(const lv_obj_class_t * class_p, lv_event_t * e); static void label_event_cb(lv_event_t * e); static void cursor_blink_anim_cb(void * obj, int32_t show); static void pwd_char_hider_anim(void * obj, int32_t x); -static void pwd_char_hider_anim_ready(lv_anim_t * a); +static void pwd_char_hider_anim_completed(lv_anim_t * a); static void pwd_char_hider(lv_obj_t * obj); static bool char_is_accepted(lv_obj_t * obj, uint32_t c); static void start_cursor_blink(lv_obj_t * obj); static void refr_cursor_area(lv_obj_t * obj); static void update_cursor_position_on_click(lv_event_t * e); -static lv_res_t insert_handler(lv_obj_t * obj, const char * txt); +static lv_result_t insert_handler(lv_obj_t * obj, const char * txt); static void draw_placeholder(lv_event_t * e); static void draw_cursor(lv_event_t * e); static void auto_hide_characters(lv_obj_t * obj); @@ -72,7 +73,8 @@ const lv_obj_class_t lv_textarea_class = { .width_def = LV_DPI_DEF * 2, .height_def = LV_DPI_DEF, .instance_size = sizeof(lv_textarea_t), - .base_class = &lv_obj_class + .base_class = &lv_obj_class, + .name = "textarea", }; static const char * ta_insert_replace; @@ -118,10 +120,10 @@ void lv_textarea_add_char(lv_obj_t * obj, uint32_t c) if(c != 0) while(*letter_buf == 0) ++letter_buf; #endif - lv_res_t res = insert_handler(obj, letter_buf); - if(res != LV_RES_OK) return; + lv_result_t res = insert_handler(obj, letter_buf); + if(res != LV_RESULT_OK) return; - uint32_t c_uni = _lv_txt_encoded_next((const char *)&c, NULL); + uint32_t c_uni = _lv_text_encoded_next((const char *)&c, NULL); if(char_is_accepted(obj, c_uni) == false) { LV_LOG_INFO("Character is not accepted by the text area (too long text or not in the accepted list)"); @@ -141,12 +143,12 @@ void lv_textarea_add_char(lv_obj_t * obj, uint32_t c) if(ta->pwd_mode) { /*+2: the new char + \0*/ - size_t realloc_size = strlen(ta->pwd_tmp) + strlen(letter_buf) + 1; - ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, realloc_size); + size_t realloc_size = lv_strlen(ta->pwd_tmp) + lv_strlen(letter_buf) + 1; + ta->pwd_tmp = lv_realloc(ta->pwd_tmp, realloc_size); LV_ASSERT_MALLOC(ta->pwd_tmp); if(ta->pwd_tmp == NULL) return; - _lv_txt_ins(ta->pwd_tmp, ta->cursor.pos, (const char *)letter_buf); + _lv_text_ins(ta->pwd_tmp, ta->cursor.pos, (const char *)letter_buf); /*Auto hide characters*/ auto_hide_characters(obj); @@ -155,7 +157,7 @@ void lv_textarea_add_char(lv_obj_t * obj, uint32_t c) /*Move the cursor after the new character*/ lv_textarea_set_cursor_pos(obj, lv_textarea_get_cursor_pos(obj) + 1); - lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); } void lv_textarea_add_text(lv_obj_t * obj, const char * txt) @@ -171,14 +173,14 @@ void lv_textarea_add_text(lv_obj_t * obj, const char * txt) if(lv_textarea_get_accepted_chars(obj) || lv_textarea_get_max_length(obj)) { uint32_t i = 0; while(txt[i] != '\0') { - uint32_t c = _lv_txt_encoded_next(txt, &i); - lv_textarea_add_char(obj, _lv_txt_unicode_to_encoded(c)); + uint32_t c = _lv_text_encoded_next(txt, &i); + lv_textarea_add_char(obj, _lv_text_unicode_to_encoded(c)); } return; } - lv_res_t res = insert_handler(obj, txt); - if(res != LV_RES_OK) return; + lv_result_t res = insert_handler(obj, txt); + if(res != LV_RESULT_OK) return; /*If the textarea is empty, invalidate it to hide the placeholder*/ if(ta->placeholder_txt) { @@ -191,24 +193,24 @@ void lv_textarea_add_text(lv_obj_t * obj, const char * txt) lv_textarea_clear_selection(obj); if(ta->pwd_mode) { - size_t realloc_size = strlen(ta->pwd_tmp) + strlen(txt) + 1; - ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, realloc_size); + size_t realloc_size = lv_strlen(ta->pwd_tmp) + lv_strlen(txt) + 1; + ta->pwd_tmp = lv_realloc(ta->pwd_tmp, realloc_size); LV_ASSERT_MALLOC(ta->pwd_tmp); if(ta->pwd_tmp == NULL) return; - _lv_txt_ins(ta->pwd_tmp, ta->cursor.pos, txt); + _lv_text_ins(ta->pwd_tmp, ta->cursor.pos, txt); /*Auto hide characters*/ auto_hide_characters(obj); } /*Move the cursor after the new text*/ - lv_textarea_set_cursor_pos(obj, lv_textarea_get_cursor_pos(obj) + _lv_txt_get_encoded_length(txt)); + lv_textarea_set_cursor_pos(obj, lv_textarea_get_cursor_pos(obj) + _lv_text_get_encoded_length(txt)); - lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); } -void lv_textarea_del_char(lv_obj_t * obj) +void lv_textarea_delete_char(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -219,13 +221,13 @@ void lv_textarea_del_char(lv_obj_t * obj) char del_buf[2] = {LV_KEY_DEL, '\0'}; - lv_res_t res = insert_handler(obj, del_buf); - if(res != LV_RES_OK) return; + lv_result_t res = insert_handler(obj, del_buf); + if(res != LV_RESULT_OK) return; char * label_txt = lv_label_get_text(ta->label); /*Delete a character*/ - _lv_txt_cut(label_txt, ta->cursor.pos - 1, 1); + _lv_text_cut(label_txt, ta->cursor.pos - 1, 1); /*Refresh the label*/ lv_label_set_text(ta->label, label_txt); @@ -238,9 +240,9 @@ void lv_textarea_del_char(lv_obj_t * obj) } if(ta->pwd_mode) { - _lv_txt_cut(ta->pwd_tmp, ta->cursor.pos - 1, 1); + _lv_text_cut(ta->pwd_tmp, ta->cursor.pos - 1, 1); - ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, strlen(ta->pwd_tmp) + 1); + ta->pwd_tmp = lv_realloc(ta->pwd_tmp, lv_strlen(ta->pwd_tmp) + 1); LV_ASSERT_MALLOC(ta->pwd_tmp); if(ta->pwd_tmp == NULL) return; } @@ -248,17 +250,17 @@ void lv_textarea_del_char(lv_obj_t * obj) /*Move the cursor to the place of the deleted character*/ lv_textarea_set_cursor_pos(obj, ta->cursor.pos - 1); - lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); } -void lv_textarea_del_char_forward(lv_obj_t * obj) +void lv_textarea_delete_char_forward(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); uint32_t cp = lv_textarea_get_cursor_pos(obj); lv_textarea_set_cursor_pos(obj, cp + 1); - if(cp != lv_textarea_get_cursor_pos(obj)) lv_textarea_del_char(obj); + if(cp != lv_textarea_get_cursor_pos(obj)) lv_textarea_delete_char(obj); } /*===================== @@ -284,8 +286,8 @@ void lv_textarea_set_text(lv_obj_t * obj, const char * txt) } uint32_t i = 0; while(txt[i] != '\0') { - uint32_t c = _lv_txt_encoded_next(txt, &i); - lv_textarea_add_char(obj, _lv_txt_unicode_to_encoded(c)); + uint32_t c = _lv_text_encoded_next(txt, &i); + lv_textarea_add_char(obj, _lv_text_unicode_to_encoded(c)); } } else { @@ -300,16 +302,15 @@ void lv_textarea_set_text(lv_obj_t * obj, const char * txt) } if(ta->pwd_mode) { - ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, strlen(txt) + 1); + ta->pwd_tmp = lv_strdup(txt); LV_ASSERT_MALLOC(ta->pwd_tmp); if(ta->pwd_tmp == NULL) return; - strcpy(ta->pwd_tmp, txt); /*Auto hide characters*/ auto_hide_characters(obj); } - lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); } void lv_textarea_set_placeholder_text(lv_obj_t * obj, const char * txt) @@ -319,22 +320,22 @@ void lv_textarea_set_placeholder_text(lv_obj_t * obj, const char * txt) lv_textarea_t * ta = (lv_textarea_t *)obj; - size_t txt_len = strlen(txt); + size_t txt_len = lv_strlen(txt); if((txt_len == 0) && (ta->placeholder_txt)) { - lv_mem_free(ta->placeholder_txt); + lv_free(ta->placeholder_txt); ta->placeholder_txt = NULL; } else { /*Allocate memory for the placeholder_txt text*/ /*NOTE: Using special realloc behavior, malloc-like when data_p is NULL*/ - ta->placeholder_txt = lv_mem_realloc(ta->placeholder_txt, txt_len + 1); + ta->placeholder_txt = lv_realloc(ta->placeholder_txt, txt_len + 1); LV_ASSERT_MALLOC(ta->placeholder_txt); if(ta->placeholder_txt == NULL) { - LV_LOG_ERROR("lv_textarea_set_placeholder_text: couldn't allocate memory for placeholder"); + LV_LOG_ERROR("couldn't allocate memory for placeholder"); return; } - strcpy(ta->placeholder_txt, txt); + lv_strcpy(ta->placeholder_txt, txt); ta->placeholder_txt[txt_len] = '\0'; } @@ -348,7 +349,7 @@ void lv_textarea_set_cursor_pos(lv_obj_t * obj, int32_t pos) lv_textarea_t * ta = (lv_textarea_t *)obj; if((uint32_t)ta->cursor.pos == (uint32_t)pos) return; - uint32_t len = _lv_txt_get_encoded_length(lv_label_get_text(ta->label)); + uint32_t len = _lv_text_get_encoded_length(lv_label_get_text(ta->label)); if(pos < 0) pos = len + pos; @@ -366,12 +367,12 @@ void lv_textarea_set_cursor_pos(lv_obj_t * obj, int32_t pos) /*The text area needs to have it's final size to see if the cursor is out of the area or not*/ /*Check the top*/ - lv_coord_t font_h = lv_font_get_line_height(font); + int32_t font_h = lv_font_get_line_height(font); if(cur_pos.y < lv_obj_get_scroll_top(obj)) { lv_obj_scroll_to_y(obj, cur_pos.y, LV_ANIM_ON); } /*Check the bottom*/ - lv_coord_t h = lv_obj_get_content_height(obj); + int32_t h = lv_obj_get_content_height(obj); if(cur_pos.y + font_h - lv_obj_get_scroll_top(obj) > h) { lv_obj_scroll_to_y(obj, cur_pos.y - h + font_h, LV_ANIM_ON); } @@ -381,7 +382,7 @@ void lv_textarea_set_cursor_pos(lv_obj_t * obj, int32_t pos) lv_obj_scroll_to_x(obj, cur_pos.x, LV_ANIM_ON); } /*Check the right*/ - lv_coord_t w = lv_obj_get_content_width(obj); + int32_t w = lv_obj_get_content_width(obj); if(cur_pos.x + font_h - lv_obj_get_scroll_left(obj) > w) { lv_obj_scroll_to_x(obj, cur_pos.x - w + font_h, LV_ANIM_ON); } @@ -412,14 +413,10 @@ void lv_textarea_set_password_mode(lv_obj_t * obj, bool en) /*Pwd mode is now enabled*/ if(en) { char * txt = lv_label_get_text(ta->label); - size_t len = strlen(txt); - - ta->pwd_tmp = lv_mem_alloc(len + 1); + ta->pwd_tmp = lv_strdup(txt); LV_ASSERT_MALLOC(ta->pwd_tmp); if(ta->pwd_tmp == NULL) return; - strcpy(ta->pwd_tmp, txt); - pwd_char_hider(obj); lv_textarea_clear_selection(obj); @@ -428,7 +425,7 @@ void lv_textarea_set_password_mode(lv_obj_t * obj, bool en) else { lv_textarea_clear_selection(obj); lv_label_set_text(ta->label, ta->pwd_tmp); - lv_mem_free(ta->pwd_tmp); + lv_free(ta->pwd_tmp); ta->pwd_tmp = NULL; } @@ -443,22 +440,22 @@ void lv_textarea_set_password_bullet(lv_obj_t * obj, const char * bullet) lv_textarea_t * ta = (lv_textarea_t *)obj; if(!bullet && (ta->pwd_bullet)) { - lv_mem_free(ta->pwd_bullet); + lv_free(ta->pwd_bullet); ta->pwd_bullet = NULL; } else { - size_t txt_len = strlen(bullet); + size_t txt_len = lv_strlen(bullet); /*Allocate memory for the pwd_bullet text*/ /*NOTE: Using special realloc behavior, malloc-like when data_p is NULL*/ - ta->pwd_bullet = lv_mem_realloc(ta->pwd_bullet, txt_len + 1); + ta->pwd_bullet = lv_realloc(ta->pwd_bullet, txt_len + 1); LV_ASSERT_MALLOC(ta->pwd_bullet); if(ta->pwd_bullet == NULL) { - LV_LOG_ERROR("lv_textarea_set_password_bullet: couldn't allocate memory for bullet"); + LV_LOG_ERROR("couldn't allocate memory for bullet"); return; } - strcpy(ta->pwd_bullet, bullet); + lv_memcpy(ta->pwd_bullet, bullet, txt_len); ta->pwd_bullet[txt_len] = '\0'; } @@ -473,8 +470,8 @@ void lv_textarea_set_one_line(lv_obj_t * obj, bool en) if(ta->one_line == en) return; ta->one_line = en ? 1U : 0U; - lv_coord_t width = en ? LV_SIZE_CONTENT : lv_pct(100); - lv_coord_t min_width_value = en ? lv_pct(100) : 0; + int32_t width = en ? LV_SIZE_CONTENT : lv_pct(100); + int32_t min_width_value = en ? lv_pct(100) : 0; lv_obj_set_width(ta->label, width); lv_obj_set_style_min_width(ta->label, min_width_value, 0); @@ -531,7 +528,7 @@ void lv_textarea_set_text_selection(lv_obj_t * obj, bool en) #endif } -void lv_textarea_set_password_show_time(lv_obj_t * obj, uint16_t time) +void lv_textarea_set_password_show_time(lv_obj_t * obj, uint32_t time) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -609,7 +606,7 @@ bool lv_textarea_get_cursor_click_pos(lv_obj_t * obj) LV_ASSERT_OBJ(obj, MY_CLASS); lv_textarea_t * ta = (lv_textarea_t *)obj; - return ta->cursor.click_pos ? true : false; + return ta->cursor.click_pos; } bool lv_textarea_get_password_mode(const lv_obj_t * obj) @@ -695,7 +692,7 @@ bool lv_textarea_get_text_selection(lv_obj_t * obj) #endif } -uint16_t lv_textarea_get_password_show_time(lv_obj_t * obj) +uint32_t lv_textarea_get_password_show_time(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -704,6 +701,19 @@ uint16_t lv_textarea_get_password_show_time(lv_obj_t * obj) return ta->pwd_show_time; } +uint32_t lv_textarea_get_current_char(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + const char * txt = lv_textarea_get_text(obj); + lv_textarea_t * ta = (lv_textarea_t *)obj; + uint32_t pos = ta->cursor.pos; + if(_lv_text_get_encoded_length(txt) >= pos && pos > 0) + return _lv_text_encoded_prev(txt, &pos); + else + return 0; +} + /*===================== * Other functions *====================*/ @@ -717,8 +727,8 @@ void lv_textarea_clear_selection(lv_obj_t * obj) if(lv_label_get_text_selection_start(ta->label) != LV_DRAW_LABEL_NO_TXT_SEL || lv_label_get_text_selection_end(ta->label) != LV_DRAW_LABEL_NO_TXT_SEL) { - lv_label_set_text_sel_start(ta->label, LV_DRAW_LABEL_NO_TXT_SEL); - lv_label_set_text_sel_end(ta->label, LV_DRAW_LABEL_NO_TXT_SEL); + lv_label_set_text_selection_start(ta->label, LV_DRAW_LABEL_NO_TXT_SEL); + lv_label_set_text_selection_end(ta->label, LV_DRAW_LABEL_NO_TXT_SEL); } #else LV_UNUSED(obj); /*Unused*/ @@ -757,18 +767,18 @@ void lv_textarea_cursor_down(lv_obj_t * obj) /*Increment the y with one line and keep the valid x*/ - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t font_h = lv_font_get_line_height(font); + int32_t font_h = lv_font_get_line_height(font); pos.y += font_h + line_space + 1; pos.x = ta->cursor.valid_x; /*Do not go below the last line*/ if(pos.y < lv_obj_get_height(ta->label)) { /*Get the letter index on the new cursor position and set it*/ - uint32_t new_cur_pos = lv_label_get_letter_on(ta->label, &pos); + uint32_t new_cur_pos = lv_label_get_letter_on(ta->label, &pos, true); - lv_coord_t cur_valid_x_tmp = ta->cursor.valid_x; /*Cursor position set overwrites the valid position*/ + int32_t cur_valid_x_tmp = ta->cursor.valid_x; /*Cursor position set overwrites the valid position*/ lv_textarea_set_cursor_pos(obj, new_cur_pos); ta->cursor.valid_x = cur_valid_x_tmp; } @@ -785,15 +795,15 @@ void lv_textarea_cursor_up(lv_obj_t * obj) lv_label_get_letter_pos(ta->label, lv_textarea_get_cursor_pos(obj), &pos); /*Decrement the y with one line and keep the valid x*/ - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t font_h = lv_font_get_line_height(font); + int32_t font_h = lv_font_get_line_height(font); pos.y -= font_h + line_space - 1; pos.x = ta->cursor.valid_x; /*Get the letter index on the new cursor position and set it*/ - uint32_t new_cur_pos = lv_label_get_letter_on(ta->label, &pos); - lv_coord_t cur_valid_x_tmp = ta->cursor.valid_x; /*Cursor position set overwrites the valid position*/ + uint32_t new_cur_pos = lv_label_get_letter_on(ta->label, &pos, true); + int32_t cur_valid_x_tmp = ta->cursor.valid_x; /*Cursor position set overwrites the valid position*/ lv_textarea_set_cursor_pos(obj, new_cur_pos); ta->cursor.valid_x = cur_valid_x_tmp; } @@ -832,6 +842,8 @@ static void lv_textarea_constructor(const lv_obj_class_t * class_p, lv_obj_t * o lv_label_set_text(ta->label, ""); lv_obj_add_event_cb(ta->label, label_event_cb, LV_EVENT_ALL, NULL); lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLL_WITH_ARROW); + lv_textarea_set_cursor_pos(obj, 0); start_cursor_blink(obj); @@ -845,15 +857,15 @@ static void lv_textarea_destructor(const lv_obj_class_t * class_p, lv_obj_t * ob lv_textarea_t * ta = (lv_textarea_t *)obj; if(ta->pwd_tmp != NULL) { - lv_mem_free(ta->pwd_tmp); + lv_free(ta->pwd_tmp); ta->pwd_tmp = NULL; } if(ta->pwd_bullet != NULL) { - lv_mem_free(ta->pwd_bullet); + lv_free(ta->pwd_bullet); ta->pwd_bullet = NULL; } if(ta->placeholder_txt != NULL) { - lv_mem_free(ta->placeholder_txt); + lv_free(ta->placeholder_txt); ta->placeholder_txt = NULL; } } @@ -862,13 +874,13 @@ static void lv_textarea_event(const lv_obj_class_t * class_p, lv_event_t * e) { LV_UNUSED(class_p); - lv_res_t res; + lv_result_t res; /*Call the ancestor's event handler*/ res = lv_obj_event_base(MY_CLASS, e); - if(res != LV_RES_OK) return; + if(res != LV_RESULT_OK) return; lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); if(code == LV_EVENT_FOCUSED) { start_cursor_blink(obj); @@ -884,15 +896,15 @@ static void lv_textarea_event(const lv_obj_class_t * class_p, lv_event_t * e) else if(c == LV_KEY_DOWN) lv_textarea_cursor_down(obj); else if(c == LV_KEY_BACKSPACE) - lv_textarea_del_char(obj); + lv_textarea_delete_char(obj); else if(c == LV_KEY_DEL) - lv_textarea_del_char_forward(obj); + lv_textarea_delete_char_forward(obj); else if(c == LV_KEY_HOME) lv_textarea_set_cursor_pos(obj, 0); else if(c == LV_KEY_END) lv_textarea_set_cursor_pos(obj, LV_TEXTAREA_CURSOR_LAST); else if(c == LV_KEY_ENTER && lv_textarea_get_one_line(obj)) - lv_event_send(obj, LV_EVENT_READY, NULL); + lv_obj_send_event(obj, LV_EVENT_READY, NULL); else { lv_textarea_add_char(obj, c); } @@ -912,7 +924,7 @@ static void lv_textarea_event(const lv_obj_class_t * class_p, lv_event_t * e) static void label_event_cb(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * label = lv_event_get_target(e); + lv_obj_t * label = lv_event_get_current_target(e); lv_obj_t * ta = lv_obj_get_parent(label); if(code == LV_EVENT_STYLE_CHANGED || code == LV_EVENT_SIZE_CHANGED) { @@ -922,8 +934,6 @@ static void label_event_cb(lv_event_t * e) } } - - /** * Called to blink the cursor * @param ta pointer to a text area @@ -961,7 +971,7 @@ static void pwd_char_hider_anim(void * obj, int32_t x) * Call when an animation is ready to convert all characters to '*' * @param a pointer to the animation */ -static void pwd_char_hider_anim_ready(lv_anim_t * a) +static void pwd_char_hider_anim_completed(lv_anim_t * a) { lv_obj_t * obj = a->var; pwd_char_hider(obj); @@ -980,12 +990,12 @@ static void pwd_char_hider(lv_obj_t * obj) /* When ta->label is empty we get 0 back */ char * txt = lv_label_get_text(ta->label); - uint32_t enc_len = _lv_txt_get_encoded_length(txt); + uint32_t enc_len = _lv_text_get_encoded_length(txt); if(enc_len == 0) return; const char * bullet = lv_textarea_get_password_bullet(obj); - const size_t bullet_len = strlen(bullet); - char * txt_tmp = lv_mem_buf_get(enc_len * bullet_len + 1); + const size_t bullet_len = lv_strlen(bullet); + char * txt_tmp = lv_malloc(enc_len * bullet_len + 1); uint32_t i; for(i = 0; i < enc_len; i++) { @@ -994,7 +1004,7 @@ static void pwd_char_hider(lv_obj_t * obj) txt_tmp[i * bullet_len] = '\0'; lv_label_set_text(ta->label, txt_tmp); - lv_mem_buf_release(txt_tmp); + lv_free(txt_tmp); refr_cursor_area(obj); } @@ -1010,7 +1020,7 @@ static bool char_is_accepted(lv_obj_t * obj, uint32_t c) lv_textarea_t * ta = (lv_textarea_t *)obj; /*Too many characters?*/ - if(ta->max_length > 0 && _lv_txt_get_encoded_length(lv_textarea_get_text(obj)) >= ta->max_length) { + if(ta->max_length > 0 && _lv_text_get_encoded_length(lv_textarea_get_text(obj)) >= ta->max_length) { return false; } @@ -1019,7 +1029,7 @@ static bool char_is_accepted(lv_obj_t * obj, uint32_t c) uint32_t i = 0; while(ta->accepted_chars[i] != '\0') { - uint32_t a = _lv_txt_encoded_next(ta->accepted_chars, &i); + uint32_t a = _lv_text_encoded_next(ta->accepted_chars, &i); if(a == c) return true; /*Accepted*/ } @@ -1029,9 +1039,9 @@ static bool char_is_accepted(lv_obj_t * obj, uint32_t c) static void start_cursor_blink(lv_obj_t * obj) { lv_textarea_t * ta = (lv_textarea_t *)obj; - uint32_t blink_time = lv_obj_get_style_anim_time(obj, LV_PART_CURSOR); + uint32_t blink_time = lv_obj_get_style_anim_duration(obj, LV_PART_CURSOR); if(blink_time == 0) { - lv_anim_del(obj, cursor_blink_anim_cb); + lv_anim_delete(obj, cursor_blink_anim_cb); ta->cursor.show = 1; } else { @@ -1039,8 +1049,8 @@ static void start_cursor_blink(lv_obj_t * obj) lv_anim_init(&a); lv_anim_set_var(&a, ta); lv_anim_set_exec_cb(&a, cursor_blink_anim_cb); - lv_anim_set_time(&a, blink_time); - lv_anim_set_playback_time(&a, blink_time); + lv_anim_set_duration(&a, blink_time); + lv_anim_set_playback_duration(&a, blink_time); lv_anim_set_values(&a, 1, 0); lv_anim_set_path_cb(&a, lv_anim_path_step); lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); @@ -1053,22 +1063,22 @@ static void refr_cursor_area(lv_obj_t * obj) lv_textarea_t * ta = (lv_textarea_t *)obj; const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); uint32_t cur_pos = lv_textarea_get_cursor_pos(obj); const char * txt = lv_label_get_text(ta->label); - uint32_t byte_pos = _lv_txt_encoded_get_byte_id(txt, cur_pos); - uint32_t letter = _lv_txt_encoded_next(&txt[byte_pos], NULL); + uint32_t byte_pos = _lv_text_encoded_get_byte_id(txt, cur_pos); + uint32_t letter = _lv_text_encoded_next(&txt[byte_pos], NULL); /* Letter height and width */ - const lv_coord_t letter_h = lv_font_get_line_height(font); + const int32_t letter_h = lv_font_get_line_height(font); /*Set letter_w (set not 0 on non printable but valid chars)*/ uint32_t letter_space = letter; if(is_valid_but_non_printable_char(letter)) { letter_space = ' '; } - lv_coord_t letter_w = lv_font_get_glyph_width(font, letter_space, IGNORE_KERNING); + int32_t letter_w = lv_font_get_glyph_width(font, letter_space, IGNORE_KERNING); lv_point_t letter_pos; lv_label_get_letter_pos(ta->label, cur_pos, &letter_pos); @@ -1083,8 +1093,8 @@ static void refr_cursor_area(lv_obj_t * obj) letter_pos.y += letter_h + line_space; if(letter != '\0') { - byte_pos += _lv_txt_encoded_size(&txt[byte_pos]); - letter = _lv_txt_encoded_next(&txt[byte_pos], NULL); + byte_pos += _lv_text_encoded_size(&txt[byte_pos]); + letter = _lv_text_encoded_next(&txt[byte_pos], NULL); } uint32_t tmp = letter; @@ -1098,11 +1108,11 @@ static void refr_cursor_area(lv_obj_t * obj) ta->cursor.txt_byte_pos = byte_pos; /*Calculate the cursor according to its type*/ - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_CURSOR); - lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_CURSOR) + border_width; - lv_coord_t bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_CURSOR) + border_width; - lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_CURSOR) + border_width; - lv_coord_t right = lv_obj_get_style_pad_right(obj, LV_PART_CURSOR) + border_width; + int32_t border_width = lv_obj_get_style_border_width(obj, LV_PART_CURSOR); + int32_t top = lv_obj_get_style_pad_top(obj, LV_PART_CURSOR) + border_width; + int32_t bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_CURSOR) + border_width; + int32_t left = lv_obj_get_style_pad_left(obj, LV_PART_CURSOR) + border_width; + int32_t right = lv_obj_get_style_pad_right(obj, LV_PART_CURSOR) + border_width; lv_area_t cur_area; cur_area.x1 = letter_pos.x - left; @@ -1131,10 +1141,10 @@ static void refr_cursor_area(lv_obj_t * obj) static void update_cursor_position_on_click(lv_event_t * e) { - lv_indev_t * click_source = lv_indev_get_act(); + lv_indev_t * click_source = lv_indev_active(); if(click_source == NULL) return; - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_textarea_t * ta = (lv_textarea_t *)obj; if(ta->cursor.click_pos == 0) return; @@ -1157,8 +1167,8 @@ static void update_cursor_position_on_click(lv_event_t * e) const lv_event_code_t code = lv_event_get_code(e); - lv_coord_t label_width = lv_obj_get_width(ta->label); - uint16_t char_id_at_click = 0; + int32_t label_width = lv_obj_get_width(ta->label); + uint32_t char_id_at_click = 0; #if LV_LABEL_TEXT_SELECTION lv_label_t * label_data = (lv_label_t *)ta->label; @@ -1174,7 +1184,7 @@ static void update_cursor_position_on_click(lv_event_t * e) click_outside_label = true; } else { - char_id_at_click = lv_label_get_letter_on(ta->label, &rel_pos); + char_id_at_click = lv_label_get_letter_on(ta->label, &rel_pos, true); click_outside_label = !lv_label_is_char_under_pos(ta->label, &rel_pos); } @@ -1184,7 +1194,7 @@ static void update_cursor_position_on_click(lv_event_t * e) ta->sel_start = char_id_at_click; ta->sel_end = LV_LABEL_TEXT_SELECTION_OFF; ta->text_sel_in_prog = 1; - lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN); } else if(ta->text_sel_in_prog && code == LV_EVENT_PRESSING) { /*Input device may be moving. Store the end position*/ @@ -1238,40 +1248,40 @@ static void update_cursor_position_on_click(lv_event_t * e) char_id_at_click = LV_TEXTAREA_CURSOR_LAST; } else { - char_id_at_click = lv_label_get_letter_on(ta->label, &rel_pos); + char_id_at_click = lv_label_get_letter_on(ta->label, &rel_pos, true); } if(code == LV_EVENT_PRESSED) lv_textarea_set_cursor_pos(obj, char_id_at_click); #endif } -/* Returns LV_RES_OK when no operation were performed - * Returns LV_RES_INV when a user defined text was inserted */ -static lv_res_t insert_handler(lv_obj_t * obj, const char * txt) +/* Returns LV_RESULT_OK when no operation were performed + * Returns LV_RESULT_INVALID when a user defined text was inserted */ +static lv_result_t insert_handler(lv_obj_t * obj, const char * txt) { ta_insert_replace = NULL; - lv_event_send(obj, LV_EVENT_INSERT, (char *)txt); + lv_obj_send_event(obj, LV_EVENT_INSERT, (char *)txt); /* Drop txt if insert replace is set to '\0' */ if(ta_insert_replace && ta_insert_replace[0] == '\0') - return LV_RES_INV; + return LV_RESULT_INVALID; if(ta_insert_replace) { /*Add the replaced text directly it's different from the original*/ - if(strcmp(ta_insert_replace, txt)) { + if(lv_strcmp(ta_insert_replace, txt)) { lv_textarea_add_text(obj, ta_insert_replace); - return LV_RES_INV; + return LV_RESULT_INVALID; } } - return LV_RES_OK; + return LV_RESULT_OK; } static void draw_placeholder(lv_event_t * e) { - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_textarea_t * ta = (lv_textarea_t *)obj; - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); const char * txt = lv_label_get_text(ta->label); /*Draw the place holder*/ @@ -1282,21 +1292,22 @@ static void draw_placeholder(lv_event_t * e) if(ta->one_line) ph_dsc.flag |= LV_TEXT_FLAG_EXPAND; - lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); - lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); + int32_t left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); + int32_t top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); + int32_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN); lv_area_t ph_coords; lv_area_copy(&ph_coords, &obj->coords); lv_area_move(&ph_coords, left + border_width, top + border_width); - lv_draw_label(draw_ctx, &ph_dsc, &ph_coords, ta->placeholder_txt, NULL); + ph_dsc.text = ta->placeholder_txt; + lv_draw_label(layer, &ph_dsc, &ph_coords); } } static void draw_cursor(lv_event_t * e) { - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_textarea_t * ta = (lv_textarea_t *)obj; - lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_layer_t * layer = lv_event_get_layer(e); const char * txt = lv_label_get_text(ta->label); if(ta->cursor.show == 0) return; @@ -1309,19 +1320,18 @@ static void draw_cursor(lv_event_t * e) lv_area_t cur_area; lv_area_copy(&cur_area, &ta->cursor.area); - cur_area.x1 += ta->label->coords.x1; cur_area.y1 += ta->label->coords.y1; cur_area.x2 += ta->label->coords.x1; cur_area.y2 += ta->label->coords.y1; - lv_draw_rect(draw_ctx, &cur_dsc, &cur_area); + lv_draw_rect(layer, &cur_dsc, &cur_area); - lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_CURSOR); - lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_CURSOR) + border_width; - lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_CURSOR) + border_width; + int32_t border_width = lv_obj_get_style_border_width(obj, LV_PART_CURSOR); + int32_t left = lv_obj_get_style_pad_left(obj, LV_PART_CURSOR) + border_width; + int32_t top = lv_obj_get_style_pad_top(obj, LV_PART_CURSOR) + border_width; char letter_buf[8] = {0}; - lv_memcpy(letter_buf, &txt[ta->cursor.txt_byte_pos], _lv_txt_encoded_size(&txt[ta->cursor.txt_byte_pos])); + lv_memcpy(letter_buf, &txt[ta->cursor.txt_byte_pos], _lv_text_encoded_size(&txt[ta->cursor.txt_byte_pos])); cur_area.x1 += left; cur_area.y1 += top; @@ -1333,8 +1343,10 @@ static void draw_cursor(lv_event_t * e) lv_draw_label_dsc_t cur_label_dsc; lv_draw_label_dsc_init(&cur_label_dsc); lv_obj_init_draw_label_dsc(obj, LV_PART_CURSOR, &cur_label_dsc); - if(cur_dsc.bg_opa > LV_OPA_MIN || cur_label_dsc.color.full != label_color.full) { - lv_draw_label(draw_ctx, &cur_label_dsc, &cur_area, letter_buf, NULL); + if(cur_dsc.bg_opa > LV_OPA_MIN || !lv_color_eq(cur_label_dsc.color, label_color)) { + cur_label_dsc.text = letter_buf; + cur_label_dsc.text_local = true; + lv_draw_label(layer, &cur_label_dsc, &cur_area); } } @@ -1350,10 +1362,10 @@ static void auto_hide_characters(lv_obj_t * obj) lv_anim_init(&a); lv_anim_set_var(&a, ta); lv_anim_set_exec_cb(&a, pwd_char_hider_anim); - lv_anim_set_time(&a, ta->pwd_show_time); + lv_anim_set_duration(&a, ta->pwd_show_time); lv_anim_set_values(&a, 0, 1); lv_anim_set_path_cb(&a, lv_anim_path_step); - lv_anim_set_ready_cb(&a, pwd_char_hider_anim_ready); + lv_anim_set_completed_cb(&a, pwd_char_hider_anim_completed); lv_anim_start(&a); } } diff --git a/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.h b/lib/libesp32_lvgl/lvgl/src/widgets/textarea/lv_textarea.h similarity index 92% rename from lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.h rename to lib/libesp32_lvgl/lvgl/src/widgets/textarea/lv_textarea.h index 4b3289b48..336585c34 100644 --- a/lib/libesp32_lvgl/lvgl/src/widgets/lv_textarea.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/textarea/lv_textarea.h @@ -13,18 +13,15 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../lv_conf_internal.h" +#include "../label/lv_label.h" #if LV_USE_TEXTAREA != 0 /*Testing of dependencies*/ #if LV_USE_LABEL == 0 -#error "lv_ta: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1)" +#error "lv_textarea: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1)" #endif -#include "../core/lv_obj.h" -#include "lv_label.h" - /********************* * DEFINES *********************/ @@ -45,9 +42,9 @@ typedef struct { char * pwd_bullet; /*Replacement characters displayed in password mode*/ const char * accepted_chars; /*Only these characters will be accepted. NULL: accept all*/ uint32_t max_length; /*The max. number of characters. 0: no limit*/ - uint16_t pwd_show_time; /*Time to show characters in password mode before change them to '*'*/ + uint32_t pwd_show_time; /*Time to show characters in password mode before change them to '*'*/ struct { - lv_coord_t valid_x; /*Used when stepping up/down to a shorter line. + int32_t valid_x; /*Used when stepping up/down to a shorter line. *(Used by the library)*/ uint32_t pos; /*The current cursor position *(0: before 1st letter; 1: before 2nd letter ...)*/ @@ -66,7 +63,7 @@ typedef struct { uint8_t one_line : 1; /*One line mode (ignore line breaks)*/ } lv_textarea_t; -extern const lv_obj_class_t lv_textarea_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_textarea_class; enum { LV_PART_TEXTAREA_PLACEHOLDER = LV_PART_CUSTOM_FIRST, @@ -89,7 +86,7 @@ lv_obj_t * lv_textarea_create(lv_obj_t * parent); /** * Insert a character to the current cursor position. - * To add a wide char, e.g. 'Á' use `_lv_txt_encoded_conv_wc('Á')` + * To add a wide char, e.g. 'Á' use `_lv_text_encoded_conv_wc('Á')` * @param obj pointer to a text area object * @param c a character (e.g. 'a') */ @@ -106,13 +103,13 @@ void lv_textarea_add_text(lv_obj_t * obj, const char * txt); * Delete a the left character from the current cursor position * @param obj pointer to a text area object */ -void lv_textarea_del_char(lv_obj_t * obj); +void lv_textarea_delete_char(lv_obj_t * obj); /** * Delete the right character from the current cursor position * @param obj pointer to a text area object */ -void lv_textarea_del_char_forward(lv_obj_t * obj); +void lv_textarea_delete_char_forward(lv_obj_t * obj); /*===================== * Setter functions @@ -204,7 +201,7 @@ void lv_textarea_set_text_selection(lv_obj_t * obj, bool en); * @param obj pointer to a text area object * @param time show time in milliseconds. 0: hide immediately. */ -void lv_textarea_set_password_show_time(lv_obj_t * obj, uint16_t time); +void lv_textarea_set_password_show_time(lv_obj_t * obj, uint32_t time); /** * Deprecated: use the normal text_align style property instead @@ -309,7 +306,14 @@ bool lv_textarea_get_text_selection(lv_obj_t * obj); * @param obj pointer to a text area object * @return show time in milliseconds. 0: hide immediately. */ -uint16_t lv_textarea_get_password_show_time(lv_obj_t * obj); +uint32_t lv_textarea_get_password_show_time(lv_obj_t * obj); + +/** + * Get a the character from the current cursor position + * @param obj pointer to a text area object + * @return a the character or 0 + */ +uint32_t lv_textarea_get_current_char(lv_obj_t * obj); /*===================== * Other functions diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.c b/lib/libesp32_lvgl/lvgl/src/widgets/tileview/lv_tileview.c similarity index 57% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.c rename to lib/libesp32_lvgl/lvgl/src/widgets/tileview/lv_tileview.c index 17fdb519a..dad187fa4 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/tileview/lv_tileview.c @@ -7,7 +7,8 @@ * INCLUDES *********************/ #include "lv_tileview.h" -#include "../../../core/lv_indev.h" +#include "../../indev/lv_indev.h" +#include "../../indev/lv_indev_private.h" #if LV_USE_TILEVIEW /********************* @@ -29,19 +30,19 @@ static void tileview_event_cb(lv_event_t * e); * STATIC VARIABLES **********************/ -const lv_obj_class_t lv_tileview_class = {.constructor_cb = lv_tileview_constructor, - .base_class = &lv_obj_class, - .instance_size = sizeof(lv_tileview_t) - }; +const lv_obj_class_t lv_tileview_class = { + .constructor_cb = lv_tileview_constructor, + .base_class = &lv_obj_class, + .instance_size = sizeof(lv_tileview_t), + .name = "tileview", +}; -const lv_obj_class_t lv_tileview_tile_class = {.constructor_cb = lv_tileview_tile_constructor, - .base_class = &lv_obj_class, - .instance_size = sizeof(lv_tileview_tile_t) - }; - -static lv_dir_t create_dir; -static uint32_t create_col_id; -static uint32_t create_row_id; +const lv_obj_class_t lv_tileview_tile_class = { + .constructor_cb = lv_tileview_tile_constructor, + .base_class = &lv_obj_class, + .instance_size = sizeof(lv_tileview_tile_t), + .name = "tile", +}; /********************** * MACROS @@ -66,19 +67,25 @@ lv_obj_t * lv_tileview_create(lv_obj_t * parent) lv_obj_t * lv_tileview_add_tile(lv_obj_t * tv, uint8_t col_id, uint8_t row_id, lv_dir_t dir) { LV_LOG_INFO("begin"); - create_dir = dir; - create_col_id = col_id; - create_row_id = row_id; lv_obj_t * obj = lv_obj_class_create_obj(&lv_tileview_tile_class, tv); lv_obj_class_init_obj(obj); + lv_obj_set_pos(obj, col_id * lv_obj_get_content_width(tv), + row_id * lv_obj_get_content_height(tv)); + + lv_tileview_tile_t * tile = (lv_tileview_tile_t *)obj; + tile->dir = dir; + + if(col_id == 0 && row_id == 0) { + lv_obj_set_scroll_dir(tv, dir); + } return obj; } -void lv_obj_set_tile(lv_obj_t * obj, lv_obj_t * tile_obj, lv_anim_enable_t anim_en) +void lv_tileview_set_tile(lv_obj_t * obj, lv_obj_t * tile_obj, lv_anim_enable_t anim_en) { - lv_coord_t tx = lv_obj_get_x(tile_obj); - lv_coord_t ty = lv_obj_get_y(tile_obj); + int32_t tx = lv_obj_get_x(tile_obj); + int32_t ty = lv_obj_get_y(tile_obj); lv_tileview_tile_t * tile = (lv_tileview_tile_t *)tile_obj; lv_tileview_t * tv = (lv_tileview_t *) obj; @@ -88,23 +95,23 @@ void lv_obj_set_tile(lv_obj_t * obj, lv_obj_t * tile_obj, lv_anim_enable_t anim_ lv_obj_scroll_to(obj, tx, ty, anim_en); } -void lv_obj_set_tile_id(lv_obj_t * tv, uint32_t col_id, uint32_t row_id, lv_anim_enable_t anim_en) +void lv_tileview_set_tile_by_index(lv_obj_t * tv, uint32_t col_id, uint32_t row_id, lv_anim_enable_t anim_en) { lv_obj_update_layout(tv); - lv_coord_t w = lv_obj_get_content_width(tv); - lv_coord_t h = lv_obj_get_content_height(tv); + int32_t w = lv_obj_get_content_width(tv); + int32_t h = lv_obj_get_content_height(tv); - lv_coord_t tx = col_id * w; - lv_coord_t ty = row_id * h; + int32_t tx = col_id * w; + int32_t ty = row_id * h; uint32_t i; - for(i = 0; i < lv_obj_get_child_cnt(tv); i++) { + for(i = 0; i < lv_obj_get_child_count(tv); i++) { lv_obj_t * tile_obj = lv_obj_get_child(tv, i); - lv_coord_t x = lv_obj_get_x(tile_obj); - lv_coord_t y = lv_obj_get_y(tile_obj); + int32_t x = lv_obj_get_x(tile_obj); + int32_t y = lv_obj_get_y(tile_obj); if(x == tx && y == ty) { - lv_obj_set_tile(tv, tile_obj, anim_en); + lv_tileview_set_tile(tv, tile_obj, anim_en); return; } } @@ -112,7 +119,7 @@ void lv_obj_set_tile_id(lv_obj_t * tv, uint32_t col_id, uint32_t row_id, lv_anim LV_LOG_WARN("No tile found with at (%d,%d) index", (int)col_id, (int)row_id); } -lv_obj_t * lv_tileview_get_tile_act(lv_obj_t * obj) +lv_obj_t * lv_tileview_get_tile_active(lv_obj_t * obj) { lv_tileview_t * tv = (lv_tileview_t *) obj; return tv->tile_act; @@ -137,54 +144,44 @@ static void lv_tileview_tile_constructor(const lv_obj_class_t * class_p, lv_obj_ { LV_UNUSED(class_p); - lv_obj_t * parent = lv_obj_get_parent(obj); lv_obj_set_size(obj, LV_PCT(100), LV_PCT(100)); lv_obj_update_layout(obj); /*Be sure the size is correct*/ - lv_obj_set_pos(obj, create_col_id * lv_obj_get_content_width(parent), - create_row_id * lv_obj_get_content_height(parent)); - - lv_tileview_tile_t * tile = (lv_tileview_tile_t *)obj; - tile->dir = create_dir; - - if(create_col_id == 0 && create_row_id == 0) { - lv_obj_set_scroll_dir(parent, create_dir); - } } static void tileview_event_cb(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * obj = lv_event_get_target(e); + lv_obj_t * obj = lv_event_get_current_target(e); lv_tileview_t * tv = (lv_tileview_t *) obj; if(code == LV_EVENT_SCROLL_END) { - lv_indev_t * indev = lv_indev_get_act(); - if(indev && indev->proc.state == LV_INDEV_STATE_PRESSED) { + lv_indev_t * indev = lv_indev_active(); + if(indev && indev->state == LV_INDEV_STATE_PRESSED) { return; } - lv_coord_t w = lv_obj_get_content_width(obj); - lv_coord_t h = lv_obj_get_content_height(obj); + int32_t w = lv_obj_get_content_width(obj); + int32_t h = lv_obj_get_content_height(obj); lv_point_t scroll_end; lv_obj_get_scroll_end(obj, &scroll_end); - lv_coord_t left = scroll_end.x; - lv_coord_t top = scroll_end.y; + int32_t left = scroll_end.x; + int32_t top = scroll_end.y; - lv_coord_t tx = ((left + (w / 2)) / w) * w; - lv_coord_t ty = ((top + (h / 2)) / h) * h; + int32_t tx = ((left + (w / 2)) / w) * w; + int32_t ty = ((top + (h / 2)) / h) * h; lv_dir_t dir = LV_DIR_ALL; uint32_t i; - for(i = 0; i < lv_obj_get_child_cnt(obj); i++) { + for(i = 0; i < lv_obj_get_child_count(obj); i++) { lv_obj_t * tile_obj = lv_obj_get_child(obj, i); - lv_coord_t x = lv_obj_get_x(tile_obj); - lv_coord_t y = lv_obj_get_y(tile_obj); + int32_t x = lv_obj_get_x(tile_obj); + int32_t y = lv_obj_get_y(tile_obj); if(x == tx && y == ty) { lv_tileview_tile_t * tile = (lv_tileview_tile_t *)tile_obj; tv->tile_act = (lv_obj_t *)tile; dir = tile->dir; - lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); break; } } diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.h b/lib/libesp32_lvgl/lvgl/src/widgets/tileview/lv_tileview.h similarity index 71% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.h rename to lib/libesp32_lvgl/lvgl/src/widgets/tileview/lv_tileview.h index 7adeec333..6413a1b15 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/tileview/lv_tileview.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/tileview/lv_tileview.h @@ -13,7 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "../../../core/lv_obj.h" +#include "../../core/lv_obj.h" #if LV_USE_TILEVIEW @@ -34,8 +34,8 @@ typedef struct { lv_dir_t dir; } lv_tileview_tile_t; -extern const lv_obj_class_t lv_tileview_class; -extern const lv_obj_class_t lv_tileview_tile_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_tileview_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_tileview_tile_class; /********************** * GLOBAL PROTOTYPES @@ -50,10 +50,10 @@ lv_obj_t * lv_tileview_create(lv_obj_t * parent); lv_obj_t * lv_tileview_add_tile(lv_obj_t * tv, uint8_t col_id, uint8_t row_id, lv_dir_t dir); -void lv_obj_set_tile(lv_obj_t * tv, lv_obj_t * tile_obj, lv_anim_enable_t anim_en); -void lv_obj_set_tile_id(lv_obj_t * tv, uint32_t col_id, uint32_t row_id, lv_anim_enable_t anim_en); +void lv_tileview_set_tile(lv_obj_t * tv, lv_obj_t * tile_obj, lv_anim_enable_t anim_en); +void lv_tileview_set_tile_by_index(lv_obj_t * tv, uint32_t col_id, uint32_t row_id, lv_anim_enable_t anim_en); -lv_obj_t * lv_tileview_get_tile_act(lv_obj_t * obj); +lv_obj_t * lv_tileview_get_tile_active(lv_obj_t * obj); /*===================== * Other functions diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/win/lv_win.c b/lib/libesp32_lvgl/lvgl/src/widgets/win/lv_win.c similarity index 81% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/win/lv_win.c rename to lib/libesp32_lvgl/lvgl/src/widgets/win/lv_win.c index 92c3b8baa..9be1a888c 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/win/lv_win.c +++ b/lib/libesp32_lvgl/lvgl/src/widgets/win/lv_win.c @@ -9,7 +9,6 @@ #include "lv_win.h" #if LV_USE_WIN - /********************* * DEFINES *********************/ @@ -31,9 +30,9 @@ const lv_obj_class_t lv_win_class = { .width_def = LV_PCT(100), .height_def = LV_PCT(100), .base_class = &lv_obj_class, - .instance_size = sizeof(lv_win_t) + .instance_size = sizeof(lv_win_t), + .name = "win", }; -static lv_coord_t create_header_height; /********************** * MACROS **********************/ @@ -42,11 +41,9 @@ static lv_coord_t create_header_height; * GLOBAL FUNCTIONS **********************/ -lv_obj_t * lv_win_create(lv_obj_t * parent, lv_coord_t header_height) +lv_obj_t * lv_win_create(lv_obj_t * parent) { LV_LOG_INFO("begin"); - create_header_height = header_height; - lv_obj_t * obj = lv_obj_class_create_obj(&lv_win_class, parent); lv_obj_class_init_obj(obj); return obj; @@ -62,15 +59,17 @@ lv_obj_t * lv_win_add_title(lv_obj_t * win, const char * txt) return title; } -lv_obj_t * lv_win_add_btn(lv_obj_t * win, const void * icon, lv_coord_t btn_w) +lv_obj_t * lv_win_add_button(lv_obj_t * win, const void * icon, int32_t btn_w) { lv_obj_t * header = lv_win_get_header(win); - lv_obj_t * btn = lv_btn_create(header); + lv_obj_t * btn = lv_button_create(header); lv_obj_set_size(btn, btn_w, LV_PCT(100)); - lv_obj_t * img = lv_img_create(btn); - lv_img_set_src(img, icon); - lv_obj_align(img, LV_ALIGN_CENTER, 0, 0); + if(icon) { + lv_obj_t * img = lv_image_create(btn); + lv_image_set_src(img, icon); + lv_obj_align(img, LV_ALIGN_CENTER, 0, 0); + } return btn; } @@ -97,7 +96,7 @@ static void lv_win_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN); lv_obj_t * header = lv_obj_create(obj); - lv_obj_set_size(header, LV_PCT(100), create_header_height); + lv_obj_set_size(header, LV_PCT(100), lv_display_get_dpi(lv_obj_get_display(obj)) / 2); lv_obj_set_flex_flow(header, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(header, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); @@ -107,4 +106,3 @@ static void lv_win_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) } #endif - diff --git a/lib/libesp32_lvgl/lvgl/src/extra/widgets/win/lv_win.h b/lib/libesp32_lvgl/lvgl/src/widgets/win/lv_win.h similarity index 76% rename from lib/libesp32_lvgl/lvgl/src/extra/widgets/win/lv_win.h rename to lib/libesp32_lvgl/lvgl/src/widgets/win/lv_win.h index 4342b3104..55691f77b 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/widgets/win/lv_win.h +++ b/lib/libesp32_lvgl/lvgl/src/widgets/win/lv_win.h @@ -14,7 +14,7 @@ extern "C" { * INCLUDES *********************/ #include "../../../lvgl.h" - +#if LV_USE_WIN /********************* * DEFINES *********************/ @@ -26,24 +26,23 @@ typedef struct { lv_obj_t obj; } lv_win_t; -extern const lv_obj_class_t lv_win_class; +LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_win_class; /********************** * GLOBAL PROTOTYPES **********************/ -lv_obj_t * lv_win_create(lv_obj_t * parent, lv_coord_t header_height); - +lv_obj_t * lv_win_create(lv_obj_t * parent); lv_obj_t * lv_win_add_title(lv_obj_t * win, const char * txt); -lv_obj_t * lv_win_add_btn(lv_obj_t * win, const void * icon, lv_coord_t btn_w); +lv_obj_t * lv_win_add_button(lv_obj_t * win, const void * icon, int32_t btn_w); lv_obj_t * lv_win_get_header(lv_obj_t * win); lv_obj_t * lv_win_get_content(lv_obj_t * win); /********************** * MACROS **********************/ - +#endif /*LV_USE_WIN*/ #ifdef __cplusplus } /*extern "C"*/ #endif diff --git a/tasmota/berry/haspmota_src/haspmota_core/haspmota.be b/tasmota/berry/haspmota_src/haspmota_core/haspmota.be index 838a01d11..5358fd83c 100644 --- a/tasmota/berry/haspmota_src/haspmota_core/haspmota.be +++ b/tasmota/berry/haspmota_src/haspmota_core/haspmota.be @@ -55,7 +55,7 @@ class lvh_obj "page", "comment", "parentid", - "auto_size", # TODO not sure it's still needed in LVGL8 + # "auto_size", # TODO not sure it's still needed in LVGL8 # attributes for page "prev", "next", "back", "berry_run", # run Berry code after the object is created @@ -145,11 +145,6 @@ class lvh_obj # "meta": nil, # roller # "options": nil, - # qrcode - # "qr_size": nil, - # "qr_dark_color": nil, - # "qr_light_color": nil, - # "qr_text": nil, } #==================================================================== @@ -333,7 +328,7 @@ class lvh_obj # defer the actual action to the Tasmota event loop # print("-> CB fired","self",self,"obj",obj,"event",event.tomap(),"code",event.code) var oh = self._page._oh # haspmota global object - var code = event.code # materialize to a local variable, otherwise the value can change (and don't capture event object) + var code = event.get_code() # materialize to a local variable, otherwise the value can change (and don't capture event object) if self.action != "" && code == lv.EVENT_CLICKED # if clicked and action is declared, do the page change event tasmota.set_timer(0, /-> oh.do_action(self, code)) @@ -344,7 +339,7 @@ class lvh_obj import json var tas_event_more = "" # complementary data - if event.code == lv.EVENT_VALUE_CHANGED + if code == lv.EVENT_VALUE_CHANGED try # try to get the new val var val = self.val @@ -713,8 +708,7 @@ class lvh_obj # LV_PART_KNOB = 0x030000, /**< Like handle to grab to adjust the value*/ # LV_PART_SELECTED = 0x040000, /**< Indicate the currently selected option or section*/ # LV_PART_ITEMS = 0x050000, /**< Used if the widget has multiple similar elements (e.g. table cells)*/ - # LV_PART_TICKS = 0x060000, /**< Ticks on scale e.g. for a chart or meter*/ - # LV_PART_CURSOR = 0x070000, /**< Mark a specific place e.g. for text area's cursor or on a chart*/ + # LV_PART_CURSOR = 0x060000, /**< Mark a specific place e.g. for text area's cursor or on a chart*/ # LV_PART_CUSTOM_FIRST = 0x080000, /**< Extension point for custom widgets*/ # LV_PART_ANY = 0x0F0000, /**< Special value can be used in some functions to target all parts*/ # @@ -748,7 +742,7 @@ class lvh_obj lv.PART_ITEMS, # 30 TODO lv.PART_ITEMS, # 40 lv.PART_SELECTED, # 50 - lv.PART_TICKS, # 60 + lv.PART_ITEMS, # 60 lv.PART_CURSOR, # 70 lv.PART_SCROLLBAR, # 80 lv.PART_CUSTOM_FIRST, # 90 @@ -1141,7 +1135,7 @@ end #==================================================================== class lvh_spinner : lvh_arc static _lv_class = lv.spinner - var _anim_start, _anim_end # the two raw (lv_anim_ntv) objects used for the animation + var _speed, _angle # init # - create the LVGL encapsulated object @@ -1151,40 +1145,29 @@ class lvh_spinner : lvh_arc self._page = page var angle = jline.find("angle", 60) var speed = jline.find("speed", 1000) - self._lv_obj = lv.spinner(parent, speed, angle) + self._lv_obj = lv.spinner(parent) + self._lv_obj.set_anim_params(speed, angle) self.post_init() - # do some black magic to get the two lv_anim objects used to animate the spinner - var anim_start = lv.anim_get(self._lv_obj, self._lv_obj._arc_anim_start_angle) - var anim_end = lv.anim_get(self._lv_obj, self._lv_obj._arc_anim_end_angle) - # convert to a ctype C structure via pointer - self._anim_start = lv.anim_ntv(anim_start._p) - self._anim_end = lv.anim_ntv(anim_end._p) end - def set_angle(t) - t = int(t) - self._anim_end.start_value = t - self._anim_end.end_value = t + 360 - end - def get_angle() - return self._anim_end.start_value - self._anim_start.start_value - end - def set_speed(t) - t = int(t) - self._anim_start.time = t - self._anim_end.time = t - end - def get_speed() - return self._anim_start.time - end + def set_angle(t) end + def get_angle() end + def set_speed(t) end + def get_speed() end end #==================================================================== # img #==================================================================== class lvh_img : lvh_obj - static _lv_class = lv.img + static _lv_class = lv.image + def set_auto_size(v) + if v + self._lv_obj.set_inner_align(lv.IMAGE_ALIGN_STRETCH) + end + end + def get_auto_size() end def set_angle(v) v = int(v) self._lv_obj.set_angle(v) @@ -1200,28 +1183,20 @@ end class lvh_qrcode : lvh_obj static _lv_class = lv.qrcode - # init - # - create the LVGL encapsulated object - # arg1: parent object - # arg2: json line object - def init(parent, page, jline) - self._page = page - - var sz = jline.find("qr_size", 100) - var dark_col = self.parse_color(jline.find("qr_dark_color", "#000000")) - var light_col = self.parse_color(jline.find("qr_light_color", "#FFFFFF")) - - self._lv_obj = lv.qrcode(parent, sz, dark_col, light_col) - self.post_init() - end # ignore attributes, spinner can't be changed once created - def set_qr_size(t) end + def set_qr_size(t) self._lv_obj.set_size(t) end + def set_size(t) self._lv_obj.set_size(t) end def get_qr_size() end - def set_qr_dark_color(t) end + def get_size() end + def set_qr_dark_color(t) self._lv_obj.set_dark_color(self.parse_color(t)) end + def set_dark_color(t) self._lv_obj.set_dark_color(self.parse_color(t)) end def get_qr_dark_color() end - def set_qr_light_color(t) end + def get_dark_color() end + def set_qr_light_color(t) self._lv_obj.set_light_color(self.parse_color(t)) end + def set_light_color(t) self._lv_obj.set_light_color(self.parse_color(t)) end def get_qr_light_color() end + def get_light_color() end def set_qr_text(t) t = str(t) self._lv_obj.update(t, size(t)) @@ -1575,7 +1550,7 @@ class lvh_page var anim_lvgl = self.show_anim.find(anim, lv.SCR_LOAD_ANIM_NONE) # load new screen with animation, no delay, 500ms transition time, no auto-delete - lv.scr_load_anim(self._lv_scr, anim_lvgl, duration, 0, false) + lv.screen_load_anim(self._lv_scr, anim_lvgl, duration, 0, false) end end @@ -1633,11 +1608,20 @@ class HASPmota static def_templ_name = "pages.jsonl" # default template name def init() + self.fix_lv_version() import re self.re_page_target = re.compile("p\\d+") # nothing to put here up to now end + # make sure that `lv.version` returns a version number + static def fix_lv_version() + import introspect + var v = introspect.get(lv, "version") + # if `lv.version` does not exist, v is `module('undefined')` + if type(v) != 'int' lv.version = 8 end + end + def deinit() # remove previous rule if any if self._val_rule != nil @@ -1742,9 +1726,17 @@ class HASPmota var jline = json.load(jsonl[0]) if type(jline) == 'instance' + if tasmota.loglevel(4) + tasmota.log(f"HSP: parsing line '{jsonl[0]}' {tasmota.loglevel(4)=}", 4) + end self.parse_page(jline) # parse page first to create any page related objects, may change self.lvh_page_cur_idx # objects are created in the current page self.parse_obj(jline, self.lvh_pages[self.lvh_page_cur_idx]) # then parse object within this page + else + # check if it's invalid json + if size(string.tr(jsonl[0], " \t", "")) > 0 + tasmota.log(f"HSP: invalid JSON line '{jsonl[0]}'", 2) + end end jline = nil jsonl.remove(0) @@ -1933,11 +1925,11 @@ class HASPmota import introspect var event_ptr = introspect.toptr(event_ptr_i) # convert to comptr, because it was a pointer in the first place - if self.event self.event._change_buffer(event_ptr) + if self.event self.event._p = event_ptr else self.event = lv.lv_event(event_ptr) end - var user_data = self.event.user_data # it is supposed to be a pointer to the object + var user_data = self.event.get_user_data() # it is supposed to be a pointer to the object if int(user_data) != 0 var target_lvh_obj = introspect.fromptr(user_data) if type(target_lvh_obj) == 'instance' @@ -1972,7 +1964,6 @@ class HASPmota end # if line contains botn 'obj' and 'id', create the object - if obj_id == nil return end # if no object id, ignore line if obj_type != "nil" && obj_id != nil # 'obj_id' must be between 1 and 254 if obj_id < 1 || obj_id > 254 @@ -2046,6 +2037,7 @@ class HASPmota end end + if obj_id == nil return end # if no object id, ignore line if obj_id == 0 && obj_type != "nil" print("HSP: cannot specify 'obj' for 'id':0") return diff --git a/tasmota/berry/haspmota_src/haspmota_demo.tapp b/tasmota/berry/haspmota_src/haspmota_demo.tapp index 26c138e405bb3993e28fd9ad7a2b1871e99fdc8e..b7571d884a576b09bba881ff91658dafb9ac1b51 100644 GIT binary patch delta 10415 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 diff --git a/tasmota/berry/haspmota_src/haspmota_demo/lv_wifi_graph.be b/tasmota/berry/haspmota_src/haspmota_demo/lv_wifi_graph.be index bb03ec6c7..9ef562236 100644 --- a/tasmota/berry/haspmota_src/haspmota_demo/lv_wifi_graph.be +++ b/tasmota/berry/haspmota_src/haspmota_demo/lv_wifi_graph.be @@ -9,6 +9,9 @@ class lv_wifi_graph : lv.chart def init(parent) super(self).init(parent) + + # enforce valid lv.version + import introspect if type(introspect.get(lv, "version")) != 'int' lv.version = 8 end self.set_style_bg_color(lv.color(0x000000), lv.PART_MAIN | lv.STATE_DEFAULT) self.set_style_bg_opa(100, lv.PART_MAIN | lv.STATE_DEFAULT) @@ -22,7 +25,11 @@ class lv_wifi_graph : lv.chart self.set_div_line_count(0,0) # no lines self.set_type(lv.CHART_TYPE_LINE) - self.set_style_size(0, lv.PART_INDICATOR) # don't show dots + if lv.version == 8 + self.set_style_size(0, lv.PART_INDICATOR) # don't show dots + else + self.set_style_size(0, 0, lv.PART_INDICATOR) # don't show dots + end self.set_style_line_rounded(true, lv.PART_ITEMS) self.set_style_line_width(2, lv.PART_ITEMS) # don't show dots self.set_update_mode(lv.CHART_UPDATE_MODE_SHIFT) diff --git a/tasmota/berry/haspmota_src/haspmota_demo/pages.jsonl b/tasmota/berry/haspmota_src/haspmota_demo/pages.jsonl index 701cc32c9..9f1cb4ef1 100644 --- a/tasmota/berry/haspmota_src/haspmota_demo/pages.jsonl +++ b/tasmota/berry/haspmota_src/haspmota_demo/pages.jsonl @@ -36,17 +36,16 @@ {"page":4,"comment":"---------- Page 4 - fan animation ----------"} {"id":0,"bg_color":"#0000A0","bg_grad_color":"#000000","bg_grad_dir":1,"text_color":"#FFFFFF"} -{"id":11,"obj":"img","src":"A:/haspmota_demo.tapp#noun_Fan_35097_140.png","auto_size":1,"w":140,"h":140,"x":50,"y":50,"image_recolor":"#0080FF","image_recolor_opa":150} +{"id":11,"obj":"img","src":"A:/haspmota_demo.tapp#noun_Fan_35097_140.png","w":140,"h":140,"x":50,"y":50,"offset_y":18,"image_recolor":"#0080FF","image_recolor_opa":150} {"id":12,"obj":"spinner","parentid":11,"x":7,"y":6,"w":126,"h":126,"bg_opa":0,"border_width":0,"line_width":7,"line_width1":7,"type":2,"angle":120,"speed":1000,"value_str":3,"value_font":24} {"page":5,"comment":"---------- Page 5 - fancy watch ----------"} {"id":0,"bg_color":"#000000","bg_grad_color":"#000000","bg_grad_dir":1,"text_color":"#000000"} {"id":10,"obj":"img","src":"A:/haspmota_demo.tapp#watch_ren_back_240.png","x":40,"y":0,"w":240,"h":240} -{"id":11,"obj":"img","parentid":10,"src":"A:/haspmota_demo.tapp#watch_ren_hour_240.png","auto_size":1,"x":110,"y":45} -{"id":12,"obj":"img","parentid":10,"src":"A:/haspmota_demo.tapp#watch_ren_min_240.png","auto_size":1} -{"id":13,"obj":"img","parentid":10,"src":"A:/haspmota_demo.tapp#watch_ren_sec_240.png","auto_size":1,"x":110,"y":10} +{"id":11,"obj":"img","parentid":10,"src":"A:/haspmota_demo.tapp#watch_ren_hour_240.png","x":110,"y":45} +{"id":12,"obj":"img","parentid":10,"src":"A:/haspmota_demo.tapp#watch_ren_min_240.png"} +{"id":13,"obj":"img","parentid":10,"src":"A:/haspmota_demo.tapp#watch_ren_sec_240.png","x":110,"y":10} {"id":15,"obj":"label","parentid":10,"x":184,"y":112,"w":18,"h":16,"text":"","align":1,"text_font":"montserrat-14"} - {"comment":"--- Trigger sensors every 2 seconds ---","berry_run":"tasmota.add_cron('*/2 * * * * *', def () tasmota.publish_rule(tasmota.read_sensors()) end, 'oh_every_5_s')"} diff --git a/tasmota/berry/haspmota_src/haspmota_widgets/lv_wifi_graph.be b/tasmota/berry/haspmota_src/haspmota_widgets/lv_wifi_graph.be index bb03ec6c7..9ef562236 100644 --- a/tasmota/berry/haspmota_src/haspmota_widgets/lv_wifi_graph.be +++ b/tasmota/berry/haspmota_src/haspmota_widgets/lv_wifi_graph.be @@ -9,6 +9,9 @@ class lv_wifi_graph : lv.chart def init(parent) super(self).init(parent) + + # enforce valid lv.version + import introspect if type(introspect.get(lv, "version")) != 'int' lv.version = 8 end self.set_style_bg_color(lv.color(0x000000), lv.PART_MAIN | lv.STATE_DEFAULT) self.set_style_bg_opa(100, lv.PART_MAIN | lv.STATE_DEFAULT) @@ -22,7 +25,11 @@ class lv_wifi_graph : lv.chart self.set_div_line_count(0,0) # no lines self.set_type(lv.CHART_TYPE_LINE) - self.set_style_size(0, lv.PART_INDICATOR) # don't show dots + if lv.version == 8 + self.set_style_size(0, lv.PART_INDICATOR) # don't show dots + else + self.set_style_size(0, 0, lv.PART_INDICATOR) # don't show dots + end self.set_style_line_rounded(true, lv.PART_ITEMS) self.set_style_line_width(2, lv.PART_ITEMS) # don't show dots self.set_update_mode(lv.CHART_UPDATE_MODE_SHIFT) diff --git a/tasmota/lvgl_berry/tasmota_logo_64.h b/tasmota/lvgl_berry/tasmota_logo_64.h deleted file mode 100644 index d67ee771d..000000000 --- a/tasmota/lvgl_berry/tasmota_logo_64.h +++ /dev/null @@ -1,110 +0,0 @@ -// #if defined(LV_LVGL_H_INCLUDE_SIMPLE) -// #include "lvgl.h" -// #else -// #include "lvgl/lvgl.h" -// #endif - - -// #ifndef LV_ATTRIBUTE_MEM_ALIGN -// #define LV_ATTRIBUTE_MEM_ALIGN -// #endif - -// #ifndef LV_ATTRIBUTE_IMG_TASMOTA_LOGO_64 -// #define LV_ATTRIBUTE_IMG_TASMOTA_LOGO_64 -// #endif - -const uint8_t tasmota_logo_64_map[] = { - 0x00, 0x00, 0x00, 0xff, /*Color of index 0*/ - 0x99, 0x99, 0x99, 0x66, /*Color of index 1*/ - 0x66, 0x66, 0x66, 0x99, /*Color of index 2*/ - 0xff, 0xff, 0xff, 0x00, /*Color of index 3*/ - - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x00, 0x00, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x0b, 0xe0, 0x00, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x2f, 0xf8, 0x00, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0xbf, 0xfe, 0x00, 0x0b, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x02, 0xff, 0xff, 0x80, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x0b, 0xff, 0xff, 0xe0, 0x00, 0xbf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf4, 0x00, 0x2f, 0xff, 0xff, 0xf8, 0x00, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xd0, 0x00, 0xbf, 0xff, 0xff, 0xfe, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x40, 0x00, 0xff, 0xff, 0xff, 0xff, 0x80, 0x02, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x00, 0x0b, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x00, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x2f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xd0, 0x00, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x0b, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x02, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0x00, 0x0b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0xbf, 0xff, 0xff, - 0xff, 0xff, 0xf8, 0x00, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x2f, 0xff, 0xff, - 0xff, 0xff, 0xd0, 0x00, 0xbf, 0xff, 0xff, 0xd5, 0x57, 0xff, 0xff, 0xfe, 0x00, 0x07, 0xff, 0xff, - 0xff, 0xff, 0x40, 0x00, 0xff, 0xff, 0xd8, 0x00, 0x00, 0x27, 0xff, 0xff, 0x80, 0x02, 0xff, 0xff, - 0xff, 0xfe, 0x00, 0x0b, 0xff, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xff, 0xe0, 0x00, 0xbf, 0xff, - 0xff, 0xf8, 0x00, 0x0f, 0xff, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf8, 0x00, 0x2f, 0xff, - 0xff, 0xd0, 0x00, 0xbf, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xfe, 0x00, 0x0b, 0xff, - 0xff, 0x80, 0x00, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x80, 0x02, 0xff, - 0xfe, 0x00, 0x0b, 0xff, 0xf0, 0x00, 0x02, 0x60, 0x0b, 0x80, 0x00, 0x0f, 0xff, 0xe0, 0x00, 0xbf, - 0xf8, 0x00, 0x0f, 0xff, 0xe0, 0x00, 0x1f, 0xe0, 0x0b, 0xf4, 0x00, 0x03, 0xff, 0xf8, 0x00, 0x2f, - 0xd0, 0x00, 0xbf, 0xff, 0x80, 0x01, 0xff, 0xe0, 0x0b, 0xff, 0x40, 0x02, 0xff, 0xfe, 0x00, 0x07, - 0x40, 0x00, 0xff, 0xfd, 0x00, 0x07, 0xff, 0xe0, 0x0b, 0xff, 0xd0, 0x00, 0x7f, 0xff, 0x80, 0x02, - 0x40, 0x03, 0xff, 0xfc, 0x00, 0x1f, 0xff, 0xe0, 0x0b, 0xff, 0xf4, 0x00, 0x3f, 0xff, 0xe0, 0x01, - 0xd0, 0x2f, 0xff, 0xf8, 0x00, 0x7f, 0xff, 0xe0, 0x0b, 0xff, 0xfd, 0x00, 0x2f, 0xff, 0xf8, 0x0b, - 0xf4, 0x3f, 0xff, 0xf0, 0x02, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0x80, 0x0f, 0xff, 0xfe, 0x2f, - 0xfd, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xc0, 0x0b, 0xff, 0xff, 0x7f, - 0xff, 0xff, 0xff, 0xc0, 0x0b, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xd0, 0x03, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x40, 0x0f, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x2f, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xf8, 0x02, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x2f, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xf4, 0x02, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xf4, 0x02, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xf4, 0x02, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xf4, 0x02, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x2f, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xf8, 0x02, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x40, 0x2f, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x40, 0x0f, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xd0, 0x03, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xc0, 0x0b, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xd0, 0x01, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0x40, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x00, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0x00, 0x0f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf4, 0x00, 0xbf, 0xff, 0xe0, 0x0b, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x00, 0x2f, 0xff, 0xe0, 0x0b, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfd, 0x00, 0x0b, 0xff, 0xe0, 0x0b, 0xff, 0xe0, 0x00, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xe0, 0x0b, 0xfd, 0x00, 0x02, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0xe0, 0x0b, 0xfc, 0x00, 0x0b, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xe0, 0x0b, 0xfc, 0x00, 0x2f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x3f, 0xe0, 0x0b, 0xfc, 0x00, 0xbf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x3f, 0xe0, 0x0b, 0xfc, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xe0, 0x0b, 0xfc, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xe0, 0x0b, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -}; - -const lv_img_dsc_t tasmota_logo_64 = { - { LV_IMG_CF_INDEXED_2BIT, 0, 0, 64, 64}, - 1040, - tasmota_logo_64_map -}; - -// typedef struct { -// lv_img_header_t header; -// uint32_t data_size; -// const uint8_t * data; -// } lv_img_dsc_t; - -// typedef struct { - -// uint32_t cf : 5; /* Color format: See `lv_img_color_format_t`*/ -// uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a -// non-printable character*/ - -// uint32_t reserved : 2; /*Reserved to be used later*/ - -// uint32_t w : 11; /*Width of the image map*/ -// uint32_t h : 11; /*Height of the image map*/ -// } lv_img_header_t; \ No newline at end of file diff --git a/tasmota/lvgl_berry/tasmota_logo_64_truecolor.h b/tasmota/lvgl_berry/tasmota_logo_64_truecolor.h deleted file mode 100644 index 87c12f939..000000000 --- a/tasmota/lvgl_berry/tasmota_logo_64_truecolor.h +++ /dev/null @@ -1,277 +0,0 @@ - -const uint8_t tasmota_logo_64_truecolor_map[] = { -#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8 - /*Pixel format: Blue: 2 bit, Green: 3 bit, Red: 3 bit*/ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xb7, 0xb6, 0xb6, 0xb7, 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x6d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x6d, 0xb7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xb7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x92, 0xdb, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xdb, 0x92, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xb7, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xb7, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, - 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, - 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xb7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, - 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, - 0xff, 0x92, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x92, 0xff, - 0xff, 0xff, 0x92, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x92, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xb6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb6, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x24, 0x00, 0x00, 0x00, 0x00, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x24, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x25, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x24, 0x00, 0x00, 0x00, 0x00, 0x25, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xdb, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xff, 0xff, 0xff, 0xff, 0x92, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb6, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xb7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x92, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -#endif -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0 - /*Pixel format: Blue: 5 bit, Green: 6 bit, Red: 5 bit*/ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x10, 0x84, 0xcf, 0x7b, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xef, 0x7b, 0x41, 0x08, 0x21, 0x08, 0xcf, 0x7b, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0xef, 0x7b, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xef, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x10, 0x84, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x10, 0x84, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0xa6, 0x31, 0xa7, 0x39, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x10, 0x84, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xf0, 0x83, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0xe7, 0x39, 0xbf, 0xff, 0xbf, 0xff, 0x08, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xcf, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7b, 0x41, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x42, 0xbe, 0xf7, 0xbf, 0xff, 0xbe, 0xf7, 0xdf, 0xff, 0x28, 0x42, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x20, 0x00, 0xf0, 0x83, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0x7e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0x08, 0x42, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x7b, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0x08, 0x42, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0x08, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xef, 0x7b, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0x08, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0xef, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x30, 0x84, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x21, 0x08, 0x08, 0x42, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x28, 0x42, 0x21, 0x08, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x84, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0xa6, 0x31, 0xdf, 0xff, 0xbe, 0xf7, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xbe, 0xf7, 0xc7, 0x39, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xf0, 0x83, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0xe7, 0x39, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x08, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xcf, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7b, 0x41, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x42, 0xbe, 0xf7, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0xdf, 0xff, 0x28, 0x42, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x20, 0x00, 0xf0, 0x83, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0x7e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0x08, 0x42, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x7b, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0x08, 0x42, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0x08, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xef, 0x7b, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0x08, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0xef, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x84, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x20, 0x00, 0x08, 0x42, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3c, 0xe7, 0x18, 0xc6, 0x14, 0xa5, 0xb2, 0x94, 0xb3, 0x9c, 0x14, 0xa5, 0x18, 0xc6, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x28, 0x42, 0x21, 0x08, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x84, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0xa6, 0x31, 0xdf, 0xff, 0xbe, 0xf7, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x96, 0xb5, 0xaa, 0x52, 0xa3, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x18, 0xaa, 0x52, 0x96, 0xb5, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xbe, 0xf7, 0xc7, 0x39, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xf0, 0x83, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x41, 0x08, 0xc7, 0x39, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x71, 0x8c, 0xa3, 0x18, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x82, 0x10, 0xcf, 0x7b, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0x28, 0x42, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7b, 0x41, 0x08, 0x00, 0x00, 0x82, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x31, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x34, 0xa5, 0x82, 0x10, 0x20, 0x00, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x61, 0x08, 0x41, 0x08, 0xa3, 0x18, 0x75, 0xad, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xe7, 0x39, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0xf0, 0x83, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xc7, 0x39, 0x9e, 0xf7, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xec, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x5a, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xbf, 0xff, 0x69, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x7b, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x86, 0x31, 0xbf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdb, 0xde, 0xc3, 0x18, 0x00, 0x00, 0x00, 0x00, 0x82, 0x10, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x41, 0x08, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x41, 0x08, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x82, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x21, 0x3c, 0xe7, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9e, 0xf7, 0x28, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xc7, 0x39, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xba, 0xd6, 0x24, 0x21, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x21, 0xef, 0x7b, 0x39, 0xce, 0x4d, 0x6b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x6b, 0x59, 0xce, 0xf0, 0x83, 0xe4, 0x20, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x25, 0x29, 0xba, 0xd6, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x49, 0x4a, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xef, 0x7b, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x08, 0x86, 0x31, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xba, 0xd6, 0xc7, 0x39, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x66, 0x31, 0x96, 0xb5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x96, 0xb5, 0x86, 0x31, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x39, 0x9a, 0xd6, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9e, 0xf7, 0x08, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0xef, 0x7b, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x30, 0x84, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x20, 0x00, 0xe7, 0x39, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x8c, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8e, 0x73, 0x00, 0x00, 0x41, 0x08, 0x41, 0x08, 0x00, 0x00, 0x8e, 0x73, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x10, 0x84, 0x20, 0x00, 0x00, 0x00, 0x41, 0x08, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x69, 0x4a, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0x39, 0x21, 0x08, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x84, 0xbf, 0xff, - 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0xa6, 0x31, 0xbe, 0xf7, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x51, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x18, 0x35, 0xad, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x75, 0xad, 0x82, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x8c, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0xc7, 0x39, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x7b, - 0x30, 0x84, 0x20, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xba, 0xd6, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x41, 0x08, 0xf7, 0xbd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbd, 0x00, 0x00, 0x41, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x9a, 0xd6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xe7, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x84, - 0xff, 0xff, 0x10, 0x84, 0x21, 0x08, 0x00, 0x00, 0x21, 0x08, 0x08, 0x42, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcb, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x21, 0x08, 0x00, 0x00, 0xb3, 0x9c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb2, 0x94, 0x00, 0x00, 0x41, 0x08, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0xab, 0x5a, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0xf7, 0x6a, 0x52, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x84, 0xff, 0xff, - 0xff, 0xff, 0xdf, 0xff, 0x10, 0x84, 0x20, 0x00, 0xa6, 0x31, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x28, 0x42, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8a, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0xc7, 0x39, 0x20, 0x00, 0xf0, 0x83, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xf4, 0xa4, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0xfb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xde, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xb2, 0x94, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xe3, 0x18, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0xeb, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0x8a, 0x52, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x04, 0x21, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xfb, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xf7, 0xbd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x34, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x62, 0x10, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x82, 0x10, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xbe, 0xf7, 0xff, 0xff, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0x7b, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x52, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0xae, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcb, 0x5a, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x83, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x30, 0x84, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xaa, 0x52, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x4a, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x92, 0x94, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x84, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x49, 0x4a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0x39, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x51, 0x8c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x51, 0x8c, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x42, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x42, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x84, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0x71, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x4a, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcb, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x7b, 0x9e, 0xf7, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x30, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, 0x39, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x8c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x18, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x9e, 0xf7, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1c, 0xe7, 0x61, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x18, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0xf7, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0xd3, 0x9c, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x14, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x10, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x41, 0x20, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0xa7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x6e, 0x73, 0x00, 0x00, 0x21, 0x08, 0x20, 0x00, 0x00, 0x00, 0x6d, 0x6b, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x86, 0x31, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x42, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x14, 0xa5, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0xb6, 0xb5, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x6b, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x4d, 0x6b, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x96, 0xb5, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0xad, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0x25, 0x29, 0x00, 0x00, 0x61, 0x08, 0x00, 0x00, 0x00, 0x00, 0x25, 0x29, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x73, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x6d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xe4, 0x20, 0x20, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x25, 0x29, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x51, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x62, 0x10, 0x41, 0x08, 0x00, 0x00, 0x49, 0x4a, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x4a, 0x00, 0x00, 0x61, 0x08, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00, 0x51, 0x8c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, 0xef, 0xa6, 0x31, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xcf, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0xa6, 0x31, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd7, 0xbd, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0xcb, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x73, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x6d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8a, 0x52, 0x00, 0x00, 0x21, 0x08, 0x21, 0x08, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0xd7, 0xbd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x8e, 0x73, 0x41, 0x08, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x41, 0x08, 0x21, 0x08, 0x45, 0x29, 0x38, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x38, 0xc6, 0x45, 0x29, 0x21, 0x08, 0x41, 0x08, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x41, 0x08, 0xaf, 0x7b, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xaa, 0x52, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x82, 0x10, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8e, 0x73, 0x00, 0x00, 0x21, 0x08, 0x20, 0x00, 0x00, 0x00, 0x8e, 0x73, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x82, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xab, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0x0c, 0x63, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x82, 0x10, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x8e, 0x73, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x8e, 0x73, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x82, 0x10, 0x62, 0x10, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0xab, 0x5a, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x6b, 0x00, 0x00, 0x41, 0x08, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x21, 0x08, 0x41, 0x08, 0x6d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0xff, 0xff, 0xd3, 0x9c, 0x82, 0x10, 0x21, 0x08, 0x00, 0x00, 0x41, 0x08, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x2c, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0x41, 0x08, 0x61, 0x08, 0x55, 0xad, 0xff, 0xff, 0xdf, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x3c, 0xe7, 0xcb, 0x5a, 0x41, 0x08, 0x41, 0x08, 0xdf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x41, 0x08, 0x21, 0x08, 0xab, 0x5a, 0x3d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xde, 0xae, 0x73, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xae, 0x73, 0xdb, 0xde, 0xbf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2d, 0x6b, 0x00, 0x00, 0x21, 0x08, 0x21, 0x08, 0x00, 0x00, 0x4d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x73, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x6d, 0x6b, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x6e, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -#endif -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP != 0 - /*Pixel format: Blue: 5 bit, Green: 6 bit, Red: 5 bit BUT the 2 bytes are swapped*/ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x84, 0x10, 0x7b, 0xcf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x7b, 0xef, 0x08, 0x41, 0x08, 0x21, 0x7b, 0xcf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0xef, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x7b, 0xef, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x7b, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x84, 0x10, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x84, 0x10, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x31, 0xa6, 0x39, 0xa7, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x84, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x83, 0xf0, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x39, 0xe7, 0xff, 0xbf, 0xff, 0xbf, 0x42, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x7b, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0xef, 0x08, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x08, 0xf7, 0xbe, 0xff, 0xbf, 0xf7, 0xbe, 0xff, 0xdf, 0x42, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x20, 0x83, 0xf0, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xe7, 0xf7, 0x7e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0x42, 0x08, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xef, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x39, 0xe7, 0xf7, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0x42, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xe7, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0x42, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x7b, 0xef, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x39, 0xe7, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x9e, 0x42, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x7b, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x84, 0x30, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x08, 0x21, 0x42, 0x08, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x42, 0x28, 0x08, 0x21, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x84, 0x30, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x31, 0xa6, 0xff, 0xdf, 0xf7, 0xbe, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xdf, 0xf7, 0xbe, 0x39, 0xc7, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x83, 0xf0, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x39, 0xe7, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x42, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x7b, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0xef, 0x08, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x08, 0xf7, 0xbe, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0xff, 0xdf, 0x42, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x20, 0x83, 0xf0, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xe7, 0xf7, 0x7e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0x42, 0x08, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xef, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0xef, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x39, 0xe7, 0xf7, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0x42, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xe7, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0x42, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x7b, 0xef, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x39, 0xe7, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x9e, 0x42, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x7b, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x30, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x20, 0x42, 0x08, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0x3c, 0xc6, 0x18, 0xa5, 0x14, 0x94, 0xb2, 0x9c, 0xb3, 0xa5, 0x14, 0xc6, 0x18, 0xe7, 0x3c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x42, 0x28, 0x08, 0x21, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x84, 0x30, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x31, 0xa6, 0xff, 0xdf, 0xf7, 0xbe, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xb5, 0x96, 0x52, 0xaa, 0x18, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xc3, 0x52, 0xaa, 0xb5, 0x96, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xdf, 0xf7, 0xbe, 0x39, 0xc7, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x83, 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x08, 0x41, 0x39, 0xc7, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x8c, 0x71, 0x18, 0xa3, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x10, 0x82, 0x7b, 0xcf, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xf7, 0x9e, 0x42, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0xef, 0x08, 0x41, 0x00, 0x00, 0x10, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x86, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x34, 0x10, 0x82, 0x00, 0x20, 0x10, 0x62, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, 0x08, 0x41, 0x18, 0xa3, 0xad, 0x75, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x39, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x83, 0xf0, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x39, 0xc7, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x62, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0xab, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xbf, 0x4a, 0x69, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xef, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0xef, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x31, 0x86, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xde, 0xdb, 0x18, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x10, 0x82, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x08, 0x41, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x08, 0x41, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10, 0x82, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, 0xe7, 0x3c, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xf7, 0x9e, 0x42, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x39, 0xc7, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xba, 0x21, 0x24, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x21, 0x04, 0x7b, 0xef, 0xce, 0x39, 0x6b, 0x4d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x2d, 0xce, 0x59, 0x83, 0xf0, 0x20, 0xe4, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x29, 0x25, 0xd6, 0xba, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x4a, 0x49, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x7b, 0xef, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x08, 0x21, 0x31, 0x86, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xd6, 0xba, 0x39, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x31, 0x66, 0xb5, 0x96, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb5, 0x96, 0x31, 0x86, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xc7, 0xd6, 0x9a, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xf7, 0x9e, 0x42, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x7b, 0xef, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x84, 0x30, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x20, 0x39, 0xe7, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4a, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x31, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x73, 0x8e, 0x00, 0x00, 0x08, 0x41, 0x08, 0x41, 0x00, 0x00, 0x73, 0x8e, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x84, 0x10, 0x00, 0x20, 0x00, 0x00, 0x08, 0x41, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x69, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x39, 0xe7, 0x08, 0x21, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x84, 0x30, 0xff, 0xbf, - 0x84, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x31, 0xa6, 0xf7, 0xbe, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8c, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x18, 0xa3, 0xad, 0x35, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x8e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xad, 0x75, 0x10, 0x82, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x51, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x9e, 0x39, 0xc7, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xcf, - 0x84, 0x30, 0x00, 0x20, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x39, 0xa7, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xba, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x08, 0x41, 0xbd, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbd, 0xf7, 0x00, 0x00, 0x08, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0xd6, 0x9a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x39, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x10, - 0xff, 0xff, 0x84, 0x10, 0x08, 0x21, 0x00, 0x00, 0x08, 0x21, 0x42, 0x08, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x08, 0x21, 0x00, 0x00, 0x9c, 0xb3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x94, 0xb2, 0x00, 0x00, 0x08, 0x41, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5a, 0xab, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x7e, 0x52, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x84, 0x10, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xdf, 0x84, 0x10, 0x00, 0x20, 0x31, 0xa6, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xde, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x42, 0x28, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x52, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xf7, 0xbe, 0x39, 0xc7, 0x00, 0x20, 0x83, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xa4, 0xf4, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0xde, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xde, 0xfb, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0x94, 0xb2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x18, 0xe3, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x5a, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0x52, 0x8a, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x21, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xde, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xbd, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbd, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x10, 0x62, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x10, 0x82, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xf7, 0xbe, 0xff, 0xff, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0x7b, 0xaf, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x52, 0x6a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x52, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x73, 0xae, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0xcb, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x83, 0xf0, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x52, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4a, 0x49, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x94, 0x92, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x4a, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x39, 0xe7, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x8c, 0x51, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8c, 0x51, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x42, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x42, 0x08, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x84, 0x10, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x9e, 0x8c, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0xcb, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xaf, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x39, 0xa7, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x51, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xc6, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xf7, 0x9e, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0x1c, 0x08, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xc6, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x7e, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x9c, 0xd3, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x82, 0xef, 0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0xe8, 0x00, 0x20, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x39, 0xa7, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x73, 0x6e, 0x00, 0x00, 0x08, 0x21, 0x00, 0x20, 0x00, 0x00, 0x6b, 0x6d, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x31, 0x86, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x42, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0xb5, 0xb6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x6d, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x6b, 0x4d, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xb5, 0x96, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x35, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7d, 0x29, 0x25, 0x00, 0x00, 0x08, 0x61, 0x00, 0x00, 0x00, 0x00, 0x29, 0x25, 0xef, 0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0x73, 0x6e, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x6b, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7d, 0x20, 0xe4, 0x00, 0x20, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x29, 0x25, 0xf7, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8c, 0x51, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0x08, 0x41, 0x00, 0x00, 0x4a, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x2d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0x4a, 0x49, 0x00, 0x00, 0x08, 0x61, 0x10, 0x62, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x51, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x5d, 0x31, 0xa6, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xdf, 0x7b, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x31, 0xa6, 0xef, 0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbd, 0xd7, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x5a, 0xcb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x73, 0x6e, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x6b, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0x52, 0x8a, 0x00, 0x00, 0x08, 0x21, 0x08, 0x21, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0xbd, 0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0x73, 0x8e, 0x08, 0x41, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x08, 0x41, 0x08, 0x21, 0x29, 0x45, 0xc6, 0x38, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc6, 0x38, 0x29, 0x45, 0x08, 0x21, 0x08, 0x41, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x08, 0x41, 0x7b, 0xaf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x52, 0xaa, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x82, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x73, 0x8e, 0x00, 0x00, 0x08, 0x21, 0x00, 0x20, 0x00, 0x00, 0x73, 0x8e, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x10, 0x82, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x5a, 0xab, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0x63, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x10, 0x82, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x73, 0x8e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x73, 0x8e, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x10, 0x82, 0x10, 0x62, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x5a, 0xab, 0xf7, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x6d, 0x00, 0x00, 0x08, 0x41, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x08, 0x21, 0x08, 0x41, 0x6b, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x9e, 0xff, 0xff, 0x9c, 0xd3, 0x10, 0x82, 0x08, 0x21, 0x00, 0x00, 0x08, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x63, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x2d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x41, 0x00, 0x00, 0x08, 0x41, 0x08, 0x61, 0xad, 0x55, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xe7, 0x3c, 0x5a, 0xcb, 0x08, 0x41, 0x08, 0x41, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x6b, 0x4d, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x08, 0x41, 0x08, 0x21, 0x5a, 0xab, 0xef, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xde, 0xdb, 0x73, 0xae, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x73, 0xae, 0xde, 0xdb, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x2d, 0x00, 0x00, 0x08, 0x21, 0x08, 0x21, 0x00, 0x00, 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x6b, 0x6d, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x73, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -#endif -#if LV_COLOR_DEPTH == 32 - /*Pixel format: Blue: 8 bit, Green: 8 bit, Red: 8 bit, Fix 0xFF: 8 bit, */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0x7f, 0x7f, 0x7f, 0xff, 0x7a, 0x7a, 0x7a, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0x7b, 0x7b, 0x7b, 0xff, 0x07, 0x07, 0x07, 0xff, 0x06, 0x06, 0x06, 0xff, 0x7a, 0x7a, 0x7a, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x7e, 0x7e, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x7a, 0x7a, 0x7a, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x7b, 0x7b, 0xff, 0x03, 0x03, 0x03, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0x80, 0x80, 0x80, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x7c, 0x7c, 0x7c, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0x7f, 0x7f, 0x7f, 0xff, 0x01, 0x01, 0x01, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x7b, 0x7b, 0x7b, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0x82, 0x82, 0x82, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x82, 0x82, 0x82, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x82, 0x82, 0x82, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0x09, 0x09, 0xff, 0x34, 0x34, 0x34, 0xff, 0x35, 0x35, 0x35, 0xff, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x07, 0x07, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x80, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0x7e, 0x7e, 0x7e, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0x09, 0x09, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0x3f, 0x3f, 0x3f, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x77, 0x77, 0x77, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0x7c, 0x7c, 0x7c, 0xff, 0x08, 0x08, 0x08, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x3f, 0x3f, 0x3f, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0x44, 0x44, 0x44, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x06, 0x06, 0x06, 0xff, 0x04, 0x04, 0x04, 0xff, 0x7d, 0x7d, 0x7d, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x7f, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x3c, 0x3c, 0x3c, 0xff, 0xee, 0xee, 0xee, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0x3f, 0x3f, 0x3f, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x7b, 0x7b, 0x7b, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x7b, 0x7b, 0xff, 0x02, 0x02, 0x02, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x3c, 0x3c, 0x3c, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0x41, 0x41, 0x41, 0xff, 0x02, 0x02, 0x02, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x7f, 0x7f, 0x7f, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0x41, 0x41, 0x41, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x7c, 0x7c, 0x7c, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0x80, 0x80, 0x80, 0xff, 0x02, 0x02, 0x02, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x3c, 0x3c, 0x3c, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0x41, 0x41, 0x41, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x7b, 0x7b, 0x7b, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0x83, 0x83, 0x83, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x3f, 0x3f, 0x3f, 0xff, 0xef, 0xef, 0xef, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0x43, 0x43, 0x43, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x07, 0x07, 0x07, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x84, 0x84, 0x84, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0x81, 0x81, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0xff, 0x34, 0x34, 0x34, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0x3a, 0x3a, 0x3a, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x7a, 0x7a, 0x7a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0x7d, 0x7d, 0x7d, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0x09, 0x09, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0x3f, 0x3f, 0x3f, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x77, 0x77, 0x77, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x7c, 0x7c, 0x7c, 0xff, 0x07, 0x07, 0x07, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x3f, 0x3f, 0x3f, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0x44, 0x44, 0x44, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x06, 0x06, 0x06, 0xff, 0x04, 0x04, 0x04, 0xff, 0x7d, 0x7d, 0x7d, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x3c, 0x3c, 0x3c, 0xff, 0xee, 0xee, 0xee, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0x3f, 0x3f, 0x3f, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x7b, 0x7b, 0x7b, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x7b, 0x7b, 0xff, 0x03, 0x03, 0x03, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x3c, 0x3c, 0x3c, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0x41, 0x41, 0x41, 0xff, 0x02, 0x02, 0x02, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0x7f, 0x7f, 0x7f, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0x41, 0x41, 0x41, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x7c, 0x7c, 0x7c, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0x7f, 0x7f, 0x7f, 0xff, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x3c, 0x3c, 0x3c, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0x41, 0x41, 0x41, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x7b, 0x7b, 0x7b, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0x83, 0x83, 0x83, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x07, 0x07, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x3f, 0x3f, 0x3f, 0xff, 0xef, 0xef, 0xef, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xe4, 0xe4, 0xe4, 0xff, 0xc0, 0xc0, 0xc0, 0xff, 0xa2, 0xa2, 0xa2, 0xff, 0x94, 0x94, 0x94, 0xff, 0x95, 0x95, 0x95, 0xff, 0xa2, 0xa2, 0xa2, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xe3, 0xe3, 0xe3, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0x43, 0x43, 0x43, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x07, 0x07, 0x07, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x84, 0x84, 0x84, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x82, 0x82, 0x82, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0xff, 0x33, 0x33, 0x33, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xaf, 0xaf, 0xaf, 0xff, 0x53, 0x53, 0x53, 0xff, 0x16, 0x16, 0x16, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x03, 0x03, 0x03, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0xff, 0x54, 0x54, 0x54, 0xff, 0xaf, 0xaf, 0xaf, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0x3a, 0x3a, 0x3a, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x7a, 0x7a, 0x7a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0x7d, 0x7d, 0x7d, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x06, 0x06, 0x06, 0xff, 0x08, 0x08, 0x08, 0xff, 0x38, 0x38, 0x38, 0xff, 0xf2, 0xf2, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x8c, 0x8c, 0x8c, 0xff, 0x15, 0x15, 0x15, 0xff, 0x07, 0x07, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0x09, 0x09, 0xff, 0x12, 0x12, 0x12, 0xff, 0x78, 0x78, 0x78, 0xff, 0xf1, 0xf1, 0xf1, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xef, 0xef, 0xff, 0x44, 0x44, 0x44, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x77, 0x77, 0x77, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x7c, 0x7c, 0x7c, 0xff, 0x07, 0x07, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x10, 0x10, 0x10, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x30, 0x30, 0x30, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa3, 0xa3, 0xa3, 0xff, 0x10, 0x10, 0x10, 0xff, 0x04, 0x04, 0x04, 0xff, 0x0d, 0x0d, 0x0d, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0x09, 0x09, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x09, 0x09, 0x09, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0b, 0x0b, 0x0b, 0xff, 0x09, 0x09, 0x09, 0xff, 0x16, 0x16, 0x16, 0xff, 0xab, 0xab, 0xab, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0x3c, 0x3c, 0x3c, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x03, 0x03, 0x03, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x7d, 0x7d, 0x7d, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0xfd, 0xfd, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x39, 0x39, 0x39, 0xff, 0xef, 0xef, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0x5e, 0x5e, 0x5e, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x07, 0x07, 0x07, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0x09, 0x09, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x55, 0x55, 0x55, 0xff, 0xf2, 0xf2, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0x4b, 0x4b, 0x4b, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x7b, 0x7b, 0x7b, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xfa, 0xfa, 0xfa, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x7b, 0x7b, 0xff, 0x03, 0x03, 0x03, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x01, 0x01, 0x01, 0xff, 0x31, 0x31, 0x31, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xda, 0xda, 0xda, 0xff, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x11, 0x11, 0x11, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0xff, 0x09, 0x09, 0x09, 0xff, 0x00, 0x00, 0x00, 0xff, 0x06, 0x06, 0x06, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0xff, 0x07, 0x07, 0x07, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x10, 0x10, 0x10, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x1f, 0x1f, 0xff, 0xe3, 0xe3, 0xe3, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xf1, 0xf1, 0xf1, 0xff, 0x43, 0x43, 0x43, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0x7f, 0x7f, 0x7f, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x3a, 0x3a, 0x3a, 0xff, 0xef, 0xef, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd3, 0xd3, 0xd3, 0xff, 0x23, 0x23, 0x23, 0xff, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x20, 0x20, 0x20, 0xff, 0x7c, 0x7c, 0x7c, 0xff, 0xc6, 0xc6, 0xc6, 0xff, 0x68, 0x68, 0x68, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0xff, 0x66, 0x66, 0x66, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0x7d, 0x7d, 0x7d, 0xff, 0x1e, 0x1e, 0x1e, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x25, 0x25, 0x25, 0xff, 0xd3, 0xd3, 0xd3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0x49, 0x49, 0x49, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x7c, 0x7c, 0x7c, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0x7f, 0x7f, 0x7f, 0xff, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x30, 0x30, 0x30, 0xff, 0xf2, 0xf2, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xd3, 0xd3, 0xd3, 0xff, 0x39, 0x39, 0x39, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x07, 0x07, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x04, 0x04, 0x04, 0xff, 0x2e, 0x2e, 0x2e, 0xff, 0xaf, 0xaf, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0x6e, 0x6e, 0x6e, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x6d, 0x6d, 0x6d, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaf, 0xaf, 0xff, 0x2f, 0x2f, 0x2f, 0xff, 0x01, 0x01, 0x01, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x37, 0x37, 0x37, 0xff, 0xd0, 0xd0, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xf2, 0xf2, 0xf2, 0xff, 0x42, 0x42, 0x42, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x7b, 0x7b, 0x7b, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xfb, 0xfb, 0xff, 0x83, 0x83, 0x83, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x07, 0x07, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0x47, 0x47, 0x47, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x85, 0x85, 0x85, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x6f, 0x6f, 0xff, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0xff, 0x70, 0x70, 0x70, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0x80, 0x80, 0x80, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0a, 0x0a, 0x0a, 0xff, 0x05, 0x05, 0x05, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x4b, 0x4b, 0x4b, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3c, 0x3c, 0x3c, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x07, 0x07, 0x07, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x84, 0x84, 0x84, 0xff, 0xf5, 0xf5, 0xf5, 0xff, - 0x82, 0x82, 0x82, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0xff, 0x33, 0x33, 0x33, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0x89, 0x89, 0x89, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x15, 0x15, 0x15, 0xff, 0xa5, 0xa5, 0xa5, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x6e, 0x6e, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x6f, 0x6f, 0x6f, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xac, 0xac, 0xac, 0xff, 0x12, 0x12, 0x12, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x02, 0x02, 0x02, 0xff, 0x8a, 0x8a, 0x8a, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xf2, 0xf2, 0xf2, 0xff, 0x3a, 0x3a, 0x3a, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x7a, 0x7a, 0x7a, 0xff, - 0x84, 0x84, 0x84, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x35, 0x35, 0x35, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xd3, 0xd3, 0xd3, 0xff, 0x05, 0x05, 0x05, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x06, 0x06, 0x06, 0xff, 0x02, 0x02, 0x02, 0xff, 0x07, 0x07, 0x07, 0xff, 0xbc, 0xbc, 0xbc, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xbb, 0xbb, 0xbb, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0a, 0x0a, 0x0a, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x06, 0x06, 0x06, 0xff, 0xd1, 0xd1, 0xd1, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x81, 0x81, 0x81, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x06, 0x06, 0x06, 0xff, 0x3f, 0x3f, 0x3f, 0xff, 0xf2, 0xf2, 0xf2, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0x58, 0x58, 0x58, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0a, 0x0a, 0x0a, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x95, 0x95, 0x95, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0x94, 0x94, 0x94, 0xff, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0xff, 0x07, 0x07, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x56, 0x56, 0x56, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed, 0xed, 0xed, 0xff, 0x4d, 0x4d, 0x4d, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xfe, 0xfe, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0x82, 0x82, 0x82, 0xff, 0x03, 0x03, 0x03, 0xff, 0x33, 0x33, 0x33, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd7, 0xd7, 0xd7, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x43, 0x43, 0x43, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0x4f, 0x4f, 0x4f, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0xd9, 0xd9, 0xd9, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0x38, 0x38, 0x38, 0xff, 0x03, 0x03, 0x03, 0xff, 0x7e, 0x7e, 0x7e, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfb, 0xfb, 0xfb, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0x9d, 0x9d, 0x9d, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x79, 0x79, 0x79, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xdb, 0xdb, 0xff, 0x07, 0x07, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x7c, 0x7c, 0x7c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x93, 0x93, 0x93, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0xfc, 0xfc, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1c, 0x1c, 0x1c, 0xff, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x5c, 0x5c, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0x52, 0x52, 0x52, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x06, 0x06, 0x06, 0xff, 0x1f, 0x1f, 0x1f, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0xbb, 0xbb, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xbc, 0xbc, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xd9, 0xd9, 0xd9, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xfe, 0xfe, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xa4, 0xa4, 0xa4, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x05, 0x05, 0x05, 0xff, 0x0d, 0x0d, 0x0d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0x0f, 0x0f, 0x0f, 0xff, 0x04, 0x04, 0x04, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xa1, 0xa1, 0xa1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xf2, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xfd, 0xfd, 0xfd, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x76, 0x76, 0x76, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0x09, 0x09, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x4d, 0x4d, 0x4d, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x4d, 0x4d, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x07, 0x07, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x73, 0x73, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x57, 0x57, 0x57, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x7d, 0x7d, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0x83, 0x83, 0x83, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x53, 0x53, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0x48, 0x48, 0x48, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x8f, 0x8f, 0x8f, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0x83, 0x83, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x48, 0x48, 0x48, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3c, 0x3c, 0x3c, 0xff, 0x02, 0x02, 0x02, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x89, 0x89, 0x89, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8a, 0x8a, 0x8a, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x40, 0x40, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x40, 0x40, 0xff, 0x07, 0x07, 0x07, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x82, 0x82, 0x82, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xf1, 0xf1, 0xff, 0x8b, 0x8b, 0x8b, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x47, 0x47, 0x47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x57, 0x57, 0x57, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x76, 0x76, 0x76, 0xff, 0xf2, 0xf2, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x6c, 0x6c, 0x6c, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x5f, 0x5f, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0x84, 0x84, 0x84, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x38, 0x38, 0x38, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x35, 0x35, 0x35, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x89, 0x89, 0x89, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xc0, 0xc0, 0xc0, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x03, 0x03, 0x03, 0xff, 0x01, 0x01, 0x01, 0xff, 0xef, 0xef, 0xef, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xe0, 0xe0, 0xff, 0x0c, 0x0c, 0x0c, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0xc0, 0xc0, 0xc0, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xee, 0xee, 0xee, 0xff, 0x09, 0x09, 0x09, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x98, 0x98, 0x98, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x68, 0x68, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x9f, 0x9f, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x0f, 0x0f, 0x0f, 0xff, 0xea, 0xea, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0x3e, 0x3e, 0xff, 0x03, 0x03, 0x03, 0xff, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x6d, 0x6d, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x6c, 0x6c, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x30, 0x30, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0x09, 0x09, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x42, 0x42, 0x42, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xa2, 0xa2, 0xa2, 0xff, 0x01, 0x01, 0x01, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0a, 0x0a, 0x0a, 0xff, 0x02, 0x02, 0x02, 0xff, 0xb4, 0xb4, 0xb4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0x6b, 0x6b, 0x6b, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb0, 0xb0, 0xb0, 0xff, 0x01, 0x01, 0x01, 0xff, 0x09, 0x09, 0x09, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0xa6, 0xa6, 0xa6, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xec, 0xec, 0xff, 0x26, 0x26, 0x26, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0b, 0x0b, 0x0b, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x25, 0x25, 0x25, 0xff, 0xe9, 0xe9, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x6d, 0x6d, 0xff, 0x08, 0x08, 0x08, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x07, 0x07, 0x07, 0xff, 0x6b, 0x6b, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xec, 0xec, 0xff, 0x1e, 0x1e, 0x1e, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0x09, 0x09, 0xff, 0x00, 0x00, 0x00, 0xff, 0x25, 0x25, 0x25, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x88, 0x88, 0x88, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0d, 0x0d, 0x0d, 0xff, 0x07, 0x07, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x48, 0x48, 0x48, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x67, 0x67, 0x67, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x66, 0x66, 0x66, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x4a, 0x4a, 0x4a, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0c, 0x0c, 0x0c, 0xff, 0x0e, 0x0e, 0x0e, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x87, 0x87, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe9, 0xe9, 0xe9, 0xff, 0x34, 0x34, 0x34, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x69, 0x69, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0x77, 0x77, 0x77, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x06, 0x06, 0x06, 0xff, 0x34, 0x34, 0x34, 0xff, 0xe8, 0xe8, 0xe8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xb7, 0xb7, 0xff, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0xff, 0x58, 0x58, 0x58, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0x6d, 0x6d, 0x6d, 0xff, 0x07, 0x07, 0x07, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x06, 0x06, 0x06, 0xff, 0x6c, 0x6c, 0x6c, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x52, 0x52, 0x52, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00, 0xff, 0xb9, 0xb9, 0xb9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0x72, 0x72, 0x72, 0xff, 0x07, 0x07, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x07, 0x07, 0x07, 0xff, 0x05, 0x05, 0x05, 0xff, 0x29, 0x29, 0x29, 0xff, 0xc4, 0xc4, 0xc4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0x69, 0x69, 0x69, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x68, 0x68, 0x68, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc4, 0xc4, 0xc4, 0xff, 0x2a, 0x2a, 0x2a, 0xff, 0x05, 0x05, 0x05, 0xff, 0x07, 0x07, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0a, 0x0a, 0x0a, 0xff, 0x76, 0x76, 0x76, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x54, 0x54, 0x54, 0xff, 0x00, 0x00, 0x00, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x04, 0x04, 0x04, 0xff, 0x11, 0x11, 0x11, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0x72, 0x72, 0x72, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x71, 0x71, 0x71, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0x12, 0x12, 0x12, 0xff, 0x01, 0x01, 0x01, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x55, 0x55, 0x55, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0x60, 0x60, 0x60, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0a, 0x0a, 0x0a, 0xff, 0x10, 0x10, 0x10, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0x70, 0x70, 0x70, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x04, 0x04, 0x04, 0xff, 0x00, 0x00, 0x00, 0xff, 0x71, 0x71, 0x71, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0x0f, 0x0f, 0x0f, 0xff, 0x0d, 0x0d, 0x0d, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x55, 0x55, 0x55, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0x6c, 0x6c, 0x6c, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0a, 0x0a, 0x0a, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6c, 0x6c, 0x6c, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x6d, 0x6d, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x06, 0x06, 0x06, 0xff, 0x08, 0x08, 0x08, 0xff, 0x6c, 0x6c, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xef, 0xef, 0xef, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0x98, 0x98, 0x98, 0xff, 0x10, 0x10, 0x10, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0x64, 0x64, 0x64, 0xff, 0x02, 0x02, 0x02, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0xff, 0x00, 0x00, 0x00, 0xff, 0x66, 0x66, 0x66, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x07, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0a, 0x0a, 0x0a, 0xff, 0x0b, 0x0b, 0x0b, 0xff, 0xa8, 0xa8, 0xa8, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xe3, 0xe3, 0xff, 0x57, 0x57, 0x57, 0xff, 0x07, 0x07, 0x07, 0xff, 0x09, 0x09, 0x09, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0x68, 0x68, 0x68, 0xff, 0x07, 0x07, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x04, 0x04, 0x04, 0xff, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0x08, 0x08, 0x08, 0xff, 0x06, 0x06, 0x06, 0xff, 0x55, 0x55, 0x55, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xd7, 0xd7, 0xd7, 0xff, 0x74, 0x74, 0x74, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x69, 0x69, 0x69, 0xff, 0x03, 0x03, 0x03, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x6b, 0x6b, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0x73, 0x73, 0x73, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x06, 0x06, 0x06, 0xff, 0x00, 0x00, 0x00, 0xff, 0x68, 0x68, 0x68, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xf7, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6c, 0x6c, 0x6c, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x6e, 0x6e, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6c, 0x6c, 0x6c, 0xff, 0x05, 0x05, 0x05, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0x6d, 0x6d, 0x6d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -#endif -}; - -const lv_img_dsc_t tasmota_logo_64_truecolor = { - { LV_IMG_CF_TRUE_COLOR, 0, 0, 64, 64}, - 4096 * LV_COLOR_SIZE / 8, - tasmota_logo_64_truecolor_map -}; diff --git a/tasmota/lvgl_berry/tasmota_logo_64_truecolor_alpha.h b/tasmota/lvgl_berry/tasmota_logo_64_truecolor_alpha.h deleted file mode 100644 index 9e79a1c21..000000000 --- a/tasmota/lvgl_berry/tasmota_logo_64_truecolor_alpha.h +++ /dev/null @@ -1,277 +0,0 @@ - -const uint8_t tasmota_logo_64_truecolor_map[] = { -#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8 - /*Pixel format: Blue: 2 bit, Green: 3 bit, Red: 3 bit, Alpha 8 bit */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x38, 0x00, 0x4b, 0x00, 0x5f, 0x00, 0x5f, 0x00, 0x4b, 0x00, 0x38, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4c, 0x00, 0x94, 0x00, 0xdb, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xdb, 0x00, 0x94, 0x00, 0x4c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xe3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xe3, 0x00, 0x6f, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0xec, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xec, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xa8, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xa8, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0xdf, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xdf, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0xe3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xdb, 0x00, 0x7b, 0x00, 0x38, 0x00, 0x98, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x9b, 0x00, 0x38, 0x00, 0x7b, 0x00, 0xdb, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xe3, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0xe4, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xd7, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0xd4, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xe4, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xbf, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xfc, 0x00, 0x80, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x80, 0x00, 0xfc, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xbf, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, - 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xf4, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0xf4, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, - 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0xfb, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xfb, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0xfb, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xfb, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, - 0x00, 0x00, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xff, 0x00, 0xc3, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0xf8, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xf8, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xc3, 0x00, 0xff, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xfb, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0xfb, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xef, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xfb, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xfb, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xf7, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xf7, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xe4, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xe0, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xe0, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xe4, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0xdb, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xdb, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xa3, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xa3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xfc, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xd3, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0xd3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xa4, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xa4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xac, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xac, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x94, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0xec, 0x00, 0xff, 0x00, 0xff, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0xff, 0x00, 0xff, 0x00, 0xec, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x98, 0x00, 0xf8, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0xf8, 0x00, 0x98, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -#endif -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0 - /*Pixel format: Blue: 5 bit, Green: 6 bit, Red: 5 bit, Alpha 8 bit*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x38, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x38, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x94, 0x00, 0x00, 0xdb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x94, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x6f, 0x00, 0x00, 0xe3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0xec, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xec, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0xdf, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xe3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x38, 0x00, 0x00, 0x98, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x38, 0x00, 0x00, 0x7b, 0x00, 0x00, 0xdb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xe4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0xd4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xbf, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, - 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xfb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0xfb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xfb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xef, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xfb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xf7, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xe4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0xdb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xa3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0xd3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xa4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xac, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xac, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x94, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0xec, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xec, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x98, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x98, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -#endif -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP != 0 - /*Pixel format: Blue: 5 bit Green: 6 bit, Red: 5 bit, Alpha 8 bit BUT the 2 color bytes are swapped*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x38, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x38, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x94, 0x00, 0x00, 0xdb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x94, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x6f, 0x00, 0x00, 0xe3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0xec, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xec, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0xdf, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xe3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x38, 0x00, 0x00, 0x98, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x38, 0x00, 0x00, 0x7b, 0x00, 0x00, 0xdb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xe4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0xd4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xbf, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, - 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xfb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0xfb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xfb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xef, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xfb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xf7, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xe4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0xdb, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xa3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0xd3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xa4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xac, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xac, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x94, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0xec, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xec, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x98, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x98, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -#endif -#if LV_COLOR_DEPTH == 32 - /*Pixel format: Blue: 8 bit, Green: 8 bit, Red: 8 bit, Alpha: 8 bit*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x4c, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xdb, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xdb, 0x02, 0x02, 0x02, 0x94, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x6f, 0x01, 0x01, 0x01, 0xe3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xe3, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x01, 0x01, 0xec, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xec, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x02, 0x02, 0xa8, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0xa8, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x01, 0x01, 0x01, 0xdf, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xdf, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x01, 0x01, 0x01, 0xe3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xdb, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x38, 0x02, 0x02, 0x02, 0x98, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x9b, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x7b, 0x01, 0x01, 0x01, 0xdb, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xe3, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x01, 0x01, 0xe4, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xd7, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x01, 0x01, 0x01, 0xd4, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x01, 0xbf, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xfc, 0x02, 0x02, 0x02, 0x80, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x02, 0x02, 0x80, 0x01, 0x01, 0x01, 0xfc, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xbf, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0x01, 0x01, 0xf4, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, - 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x01, 0x01, 0x01, 0xfb, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xfb, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, 0x01, 0x01, 0xfb, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xfb, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x9c, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x80, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x01, 0x01, 0xf8, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xb8, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xc3, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x87, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xfb, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x01, 0x01, 0x01, 0xfb, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xd0, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0xa7, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x01, 0xef, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x83, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xb3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x9b, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x8b, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xb3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xbf, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0xab, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x93, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xc8, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xfb, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xfb, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x01, 0x01, 0xf7, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xf7, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xbf, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xcb, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x01, 0x01, 0xe4, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x01, 0x01, 0xe0, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xb0, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x01, 0x01, 0xdb, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x90, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xdb, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x01, 0x01, 0x01, 0xfc, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0xa3, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x02, 0x02, 0xa3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x88, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xd3, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x01, 0x01, 0x01, 0xd3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0xa4, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xf3, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0xa4, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x01, 0xac, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xf4, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xac, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xf4, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x94, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x01, 0x01, 0x01, 0xec, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xf4, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xec, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x02, 0x02, 0x02, 0x98, 0x01, 0x01, 0x01, 0xf8, 0x01, 0x01, 0x01, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xf4, 0x01, 0x01, 0x01, 0xf8, 0x02, 0x02, 0x02, 0x98, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x02, 0x02, 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x88, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x94, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0xff, 0x02, 0x02, 0x02, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -#endif -}; - -const lv_img_dsc_t tasmota_logo_64_truecolor = { - { LV_IMG_CF_TRUE_COLOR_ALPHA, 0, 0, 64, 64}, - 4096 * LV_IMG_PX_SIZE_ALPHA_BYTE, - tasmota_logo_64_truecolor_map -}; diff --git a/tasmota/lvgl_berry/tasmota_lv_conf.h b/tasmota/lvgl_berry/tasmota_lv_conf.h index bd8464e35..dc7d7972f 100644 --- a/tasmota/lvgl_berry/tasmota_lv_conf.h +++ b/tasmota/lvgl_berry/tasmota_lv_conf.h @@ -1,6 +1,6 @@ /** * @file lv_conf.h - * Configuration file for v8.3.0 + * Configuration file for v9.0.0 */ /* @@ -17,39 +17,35 @@ #ifndef LV_CONF_H #define LV_CONF_H -#include - /*==================== COLOR SETTINGS *====================*/ -/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/ +/*Color depth: 8 (A8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/ #define LV_COLOR_DEPTH 16 -/*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/ -#define LV_COLOR_16_SWAP 1 - -/*Enable features to draw on transparent background. - *It's required if opa, and transform_* style properties are used. - *Can be also used if the UI is above another layer, e.g. an OSD menu or video player.*/ -#define LV_COLOR_SCREEN_TRANSP 0 - -/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. - * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */ -#define LV_COLOR_MIX_ROUND_OFS 0 - -/*Images pixels with this color will not be drawn if they are chroma keyed)*/ -#define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/ - /*========================= - MEMORY SETTINGS + STDLIB WRAPPER SETTINGS *=========================*/ -/*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/ -#define LV_MEM_CUSTOM 1 -#if LV_MEM_CUSTOM == 0 - /*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/ - #define LV_MEM_SIZE (48U * 1024U) /*[bytes]*/ +/* Possible values + * - LV_STDLIB_BUILTIN: LVGL's built in implementation + * - LV_STDLIB_CLIB: Standard C functions, like malloc, strlen, etc + * - LV_STDLIB_MICROPYTHON: MicroPython implementation + * - LV_STDLIB_RTTHREAD: RT-Thread implementation + * - LV_STDLIB_CUSTOM: Implement the functions externally + */ +#define LV_USE_STDLIB_MALLOC LV_STDLIB_CUSTOM // TASMOTA +#define LV_USE_STDLIB_STRING LV_STDLIB_CLIB // TASMOTA +#define LV_USE_STDLIB_SPRINTF LV_STDLIB_CLIB // TASMOTA + + +#if LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN + /*Size of the memory available for `lv_malloc()` in bytes (>= 2kB)*/ + #define LV_MEM_SIZE (64 * 1024U) /*[bytes]*/ + + /*Size of the memory expand for `lv_malloc()` in bytes*/ + #define LV_MEM_POOL_EXPAND_SIZE 0 /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/ #define LV_MEM_ADR 0 /*0: unused*/ @@ -58,163 +54,134 @@ #undef LV_MEM_POOL_INCLUDE #undef LV_MEM_POOL_ALLOC #endif - -#else /*LV_MEM_CUSTOM*/ - #define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ - #define LV_MEM_CUSTOM_ALLOC lvbe_malloc - #define LV_MEM_CUSTOM_FREE lvbe_free - #define LV_MEM_CUSTOM_REALLOC lvbe_realloc -#endif /*LV_MEM_CUSTOM*/ - -/*Number of the intermediate memory buffer used during rendering and other internal processing mechanisms. - *You will see an error log message if there wasn't enough buffers. */ -#define LV_MEM_BUF_MAX_NUM 16 - -/*Use the standard `memcpy` and `memset` instead of LVGL's own functions. (Might or might not be faster).*/ -#define LV_MEMCPY_MEMSET_STD 0 +#endif /*LV_USE_MALLOC == LV_STDLIB_BUILTIN*/ /*==================== HAL SETTINGS *====================*/ -/*Default display refresh period. LVG will redraw changed areas with this period time*/ -#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ - -/*Input device read period in milliseconds*/ -#define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/ - -/*Use a custom tick source that tells the elapsed time in milliseconds. - *It removes the need to manually update the tick with `lv_tick_inc()`)*/ -#define LV_TICK_CUSTOM 0 -#if LV_TICK_CUSTOM - #define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ - #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ -#endif /*LV_TICK_CUSTOM*/ +/*Default display refresh, input device read and animation step period.*/ +#define LV_DEF_REFR_PERIOD 33 /*[ms]*/ /*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings. *(Not so important, you can adjust it to modify default sizes and spaces)*/ #define LV_DPI_DEF 130 /*[px/inch]*/ +/*================= + * OPERATING SYSTEM + *=================*/ +/*Select an operating system to use. Possible options: + * - LV_OS_NONE + * - LV_OS_PTHREAD + * - LV_OS_FREERTOS + * - LV_OS_CMSIS_RTOS2 + * - LV_OS_RTTHREAD + * - LV_OS_WINDOWS + * - LV_OS_CUSTOM */ +#define LV_USE_OS LV_OS_NONE + +#if LV_USE_OS == LV_OS_CUSTOM + #define LV_OS_CUSTOM_INCLUDE +#endif + +/*======================== + * RENDERING CONFIGURATION + *========================*/ + +/*Align the stride of all layers and images to this bytes*/ +#define LV_DRAW_BUF_STRIDE_ALIGN 1 + +/*Align the start address of draw_buf addresses to this bytes*/ +#define LV_DRAW_BUF_ALIGN 4 + +#define LV_USE_DRAW_SW 1 +#if LV_USE_DRAW_SW == 1 + /* Set the number of draw unit. + * > 1 requires an operating system enabled in `LV_USE_OS` + * > 1 means multiply threads will render the screen in parallel */ + #define LV_DRAW_SW_DRAW_UNIT_CNT 1 + + /* Use Arm-2D to accelerate the sw render */ + #define LV_USE_DRAW_ARM2D_SYNC 0 + + /* If a widget has `style_opa < 255` (not `bg_opa`, `text_opa` etc) or not NORMAL blend mode + * it is buffered into a "simple" layer before rendering. The widget can be buffered in smaller chunks. + * "Transformed layers" (if `transform_angle/zoom` are set) use larger buffers + * and can't be drawn in chunks. */ + + /*The target buffer size for simple layer chunks.*/ + #define LV_DRAW_SW_LAYER_SIMPLE_BUF_SIZE (24 * 1024) /*[bytes]*/ + + /* 0: use a simple renderer capable of drawing only simple rectangles with gradient, images, texts, and straight lines only + * 1: use a complex renderer capable of drawing rounded corners, shadow, skew lines, and arcs too */ + #define LV_DRAW_SW_COMPLEX 1 + + #if LV_DRAW_SW_COMPLEX == 1 + /*Allow buffering some shadow calculation. + *LV_DRAW_SW_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius` + *Caching has LV_DRAW_SW_SHADOW_CACHE_SIZE^2 RAM cost*/ + #define LV_DRAW_SW_SHADOW_CACHE_SIZE 0 + + /* Set number of maximally cached circle data. + * The circumference of 1/4 circle are saved for anti-aliasing + * radius * 4 bytes are used per circle (the most often used radiuses are saved) + * 0: to disable caching */ + #define LV_DRAW_SW_CIRCLE_CACHE_SIZE 4 + #endif + + #define LV_USE_DRAW_SW_ASM LV_DRAW_SW_ASM_NONE + + #if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_CUSTOM + #define LV_DRAW_SW_ASM_CUSTOM_INCLUDE "" + #endif +#endif + +/* Use NXP's VG-Lite GPU on iMX RTxxx platforms. */ +#define LV_USE_DRAW_VGLITE 0 + +#if LV_USE_DRAW_VGLITE + /* Enable blit quality degradation workaround recommended for screen's dimension > 352 pixels. */ + #define LV_USE_VGLITE_BLIT_SPLIT 0 + + #if LV_USE_OS + /* Enable VGLite draw async. Queue multiple tasks and flash them once to the GPU. */ + #define LV_USE_VGLITE_DRAW_ASYNC 1 + #endif + + /* Enable VGLite asserts. */ + #define LV_USE_VGLITE_ASSERT 0 +#endif + +/* Use NXP's PXP on iMX RTxxx platforms. */ +#define LV_USE_DRAW_PXP 0 + +#if LV_USE_DRAW_PXP + /* Enable PXP asserts. */ + #define LV_USE_PXP_ASSERT 0 +#endif + +/* Use Renesas Dave2D on RA platforms. */ +#define LV_USE_DRAW_DAVE2D 0 + +/* Draw using cached SDL textures*/ +#define LV_USE_DRAW_SDL 0 + +/* Use VG-Lite GPU. */ +#define LV_USE_DRAW_VG_LITE 0 + +#if LV_USE_DRAW_VG_LITE +/* Enable VG-Lite custom external 'gpu_init()' function */ +#define LV_VG_LITE_USE_GPU_INIT 0 + +/* Enable VG-Lite assert. */ +#define LV_VG_LITE_USE_ASSERT 0 + +#endif + /*======================= * FEATURE CONFIGURATION *=======================*/ -/*------------- - * Drawing - *-----------*/ - -/*Enable complex draw engine. - *Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/ -#define LV_DRAW_COMPLEX 1 -#if LV_DRAW_COMPLEX != 0 - - /*Allow buffering some shadow calculation. - *LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius` - *Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/ - #define LV_SHADOW_CACHE_SIZE 0 - - /* Set number of maximally cached circle data. - * The circumference of 1/4 circle are saved for anti-aliasing - * radius * 4 bytes are used per circle (the most often used radiuses are saved) - * 0: to disable caching */ - #define LV_CIRCLE_CACHE_SIZE 4 -#endif /*LV_DRAW_COMPLEX*/ - -/** - * "Simple layers" are used when a widget has `style_opa < 255` to buffer the widget into a layer - * and blend it as an image with the given opacity. - * Note that `bg_opa`, `text_opa` etc don't require buffering into layer) - * The widget can be buffered in smaller chunks to avoid using large buffers. - * - * - LV_LAYER_SIMPLE_BUF_SIZE: [bytes] the optimal target buffer size. LVGL will try to allocate it - * - LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE: [bytes] used if `LV_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated. - * - * Both buffer sizes are in bytes. - * "Transformed layers" (where transform_angle/zoom properties are used) use larger buffers - * and can't be drawn in chunks. So these settings affects only widgets with opacity. - */ -#define LV_LAYER_SIMPLE_BUF_SIZE (24 * 1024) -#define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE (3 * 1024) - -/*Default image cache size. Image caching keeps the images opened. - *If only the built-in image formats are used there is no real advantage of caching. (I.e. if no new image decoder is added) - *With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. - *However the opened images might consume additional RAM. - *0: to disable caching*/ -#define LV_IMG_CACHE_DEF_SIZE 1 -#define LV_IMG_CACHE_DEF_SIZE_PSRAM 20 // special Tasmota setting when PSRAM is used - -/*Number of stops allowed per gradient. Increase this to allow more stops. - *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ -#define LV_GRADIENT_MAX_STOPS 2 - -/*Default gradient buffer size. - *When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again. - *LV_GRAD_CACHE_DEF_SIZE sets the size of this cache in bytes. - *If the cache is too small the map will be allocated only while it's required for the drawing. - *0 mean no caching.*/ -#define LV_GRAD_CACHE_DEF_SIZE 0 - -/*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display) - *LV_DITHER_GRADIENT implies allocating one or two more lines of the object's rendering surface - *The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion */ -#define LV_DITHER_GRADIENT 1 -#if LV_DITHER_GRADIENT - /*Add support for error diffusion dithering. - *Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing. - *The increase in memory consumption is (24 bits * object's width)*/ - #define LV_DITHER_ERROR_DIFFUSION 1 -#endif - -/*Maximum buffer size to allocate for rotation. - *Only used if software rotation is enabled in the display driver.*/ -#define LV_DISP_ROT_MAX_BUF (10*1024) - -/*------------- - * GPU - *-----------*/ - -/*Use Arm's 2D acceleration library Arm-2D */ -#define LV_USE_GPU_ARM2D 0 - -/*Use STM32's DMA2D (aka Chrom Art) GPU*/ -#define LV_USE_GPU_STM32_DMA2D 0 -#if LV_USE_GPU_STM32_DMA2D - /*Must be defined to include path of CMSIS header of target processor - e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ - #define LV_GPU_DMA2D_CMSIS_INCLUDE -#endif - -/*Use SWM341's DMA2D GPU*/ -#define LV_USE_GPU_SWM341_DMA2D 0 -#if LV_USE_GPU_SWM341_DMA2D - #define LV_GPU_SWM341_DMA2D_INCLUDE "SWM341.h" -#endif - -/*Use NXP's PXP GPU iMX RTxxx platforms*/ -#define LV_USE_GPU_NXP_PXP 0 -#if LV_USE_GPU_NXP_PXP - /*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c) - * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS - * has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected. - *0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init() - */ - #define LV_USE_GPU_NXP_PXP_AUTO_INIT 0 -#endif - -/*Use NXP's VG-Lite GPU iMX RTxxx platforms*/ -#define LV_USE_GPU_NXP_VG_LITE 0 - -/*Use SDL renderer API*/ -#define LV_USE_GPU_SDL 0 -#if LV_USE_GPU_SDL - #define LV_GPU_SDL_INCLUDE_PATH - /*Texture cache size, 8MB by default*/ - #define LV_GPU_SDL_LRU_SIZE (1024 * 1024 * 8) - /*Custom blend mode for mask drawing, disable if you need to link with older SDL2 lib*/ - #define LV_GPU_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6)) -#endif - /*------------- * Logging *-----------*/ @@ -230,21 +197,30 @@ *LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail *LV_LOG_LEVEL_USER Only logs added by the user *LV_LOG_LEVEL_NONE Do not log anything*/ - #define LV_LOG_LEVEL LV_LOG_LEVEL_WARN + #define LV_LOG_LEVEL LV_LOG_LEVEL_INFO /*1: Print the log with 'printf'; *0: User need to register a callback with `lv_log_register_print_cb()`*/ #define LV_LOG_PRINTF 0 + /*1: Enable print timestamp; + *0: Disable print timestamp*/ + #define LV_LOG_USE_TIMESTAMP 1 + + /*1: Print file and line number of the log; + *0: Do not print file and line number of the log*/ + #define LV_LOG_USE_FILE_LINE 1 + /*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/ - #define LV_LOG_TRACE_MEM 1 - #define LV_LOG_TRACE_TIMER 1 + #define LV_LOG_TRACE_MEM 0 + #define LV_LOG_TRACE_TIMER 0 #define LV_LOG_TRACE_INDEV 1 - #define LV_LOG_TRACE_DISP_REFR 1 + #define LV_LOG_TRACE_DISP_REFR 0 #define LV_LOG_TRACE_EVENT 1 - #define LV_LOG_TRACE_OBJ_CREATE 1 - #define LV_LOG_TRACE_LAYOUT 1 - #define LV_LOG_TRACE_ANIM 1 + #define LV_LOG_TRACE_OBJ_CREATE 0 + #define LV_LOG_TRACE_LAYOUT 0 + #define LV_LOG_TRACE_ANIM 0 + #define LV_LOG_TRACE_CACHE 1 #endif /*LV_USE_LOG*/ @@ -265,43 +241,81 @@ #define LV_ASSERT_HANDLER while(1); /*Halt by default*/ /*------------- - * Others + * Debug *-----------*/ -/*1: Show CPU usage and FPS count*/ -#define LV_USE_PERF_MONITOR 0 -#if LV_USE_PERF_MONITOR - #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT -#endif - -/*1: Show the used memory and the memory fragmentation - * Requires LV_MEM_CUSTOM = 0*/ -#define LV_USE_MEM_MONITOR 0 -#if LV_USE_MEM_MONITOR - #define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT -#endif - /*1: Draw random colored rectangles over the redrawn areas*/ #define LV_USE_REFR_DEBUG 0 -/*Change the built in (v)snprintf functions*/ -#define LV_SPRINTF_CUSTOM 0 -#if LV_SPRINTF_CUSTOM - #define LV_SPRINTF_INCLUDE - #define lv_snprintf snprintf - #define lv_vsnprintf vsnprintf -#else /*LV_SPRINTF_CUSTOM*/ - #define LV_SPRINTF_USE_FLOAT 0 -#endif /*LV_SPRINTF_CUSTOM*/ +/*1: Draw a red overlay for ARGB layers and a green overlay for RGB layers*/ +#define LV_USE_LAYER_DEBUG 0 -#define LV_USE_USER_DATA 1 +/*1: Draw overlays with different colors for each draw_unit's tasks. + *Also add the index number of the draw unit on white background. + *For layers add the index number of the draw unit on black background.*/ +#define LV_USE_PARALLEL_DRAW_DEBUG 0 -/*Garbage Collector settings - *Used if lvgl is bound to higher level language and the memory is managed by that language*/ -#define LV_ENABLE_GC 0 -#if LV_ENABLE_GC != 0 - #define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ -#endif /*LV_ENABLE_GC*/ +/*------------- + * Others + *-----------*/ + +#define LV_ENABLE_GLOBAL_CUSTOM 0 +#if LV_ENABLE_GLOBAL_CUSTOM + /*Header to include for the custom 'lv_global' function"*/ + #define LV_GLOBAL_CUSTOM_INCLUDE +#endif + +/*Default cache size in bytes. + *Used by image decoders such as `lv_lodepng` to keep the decoded image in the memory. + *If size is not set to 0, the decoder will fail to decode when the cache is full. + *If size is 0, the cache function is not enabled and the decoded mem will be released immediately after use.*/ +#define LV_IMG_CACHE_DEF_SIZE_PSRAM (1024*1024) +#define LV_IMG_CACHE_DEF_SIZE_NOPSRAM (32*1024) +#define LV_CACHE_DEF_SIZE 1024 // TASMOTA very low value as a place-holder, the true value is adjusted later + +/*Default number of image header cache entries. The cache is used to store the headers of images + *The main logic is like `LV_CACHE_DEF_SIZE` but for image headers.*/ +#define LV_IMAGE_HEADER_CACHE_DEF_CNT 10 + +/*Number of stops allowed per gradient. Increase this to allow more stops. + *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ +#define LV_GRADIENT_MAX_STOPS 2 + +/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. + * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */ +#define LV_COLOR_MIX_ROUND_OFS 0 + +/* Add 2 x 32 bit variables to each lv_obj_t to speed up getting style properties */ +#define LV_OBJ_STYLE_CACHE 0 + +/* Add `id` field to `lv_obj_t` */ +#define LV_USE_OBJ_ID 1 // TASMOTA + +/* Use lvgl builtin method for obj ID */ +#define LV_USE_OBJ_ID_BUILTIN 1 // TASMOTA + +/*Use obj property set/get API*/ +#define LV_USE_OBJ_PROPERTY 0 + +/* VG-Lite Simulator */ +/*Requires: LV_USE_THORVG_INTERNAL or LV_USE_THORVG_EXTERNAL */ +#define LV_USE_VG_LITE_THORVG 0 + +#if LV_USE_VG_LITE_THORVG + + /*Enable LVGL's blend mode support*/ + #define LV_VG_LITE_THORVG_LVGL_BLEND_SUPPORT 0 + + /*Enable YUV color format support*/ + #define LV_VG_LITE_THORVG_YUV_SUPPORT 0 + + /*Enable 16 pixels alignment*/ + #define LV_VG_LITE_THORVG_16PIXELS_ALIGN 1 + + /*Enable multi-thread render*/ + #define LV_VG_LITE_THORVG_THREAD_RENDER 0 + +#endif /*===================== * COMPILER SETTINGS @@ -316,7 +330,7 @@ /*Define a custom attribute to `lv_timer_handler` function*/ #define LV_ATTRIBUTE_TIMER_HANDLER -/*Define a custom attribute to `lv_disp_flush_ready` function*/ +/*Define a custom attribute to `lv_display_flush_ready` function*/ #define LV_ATTRIBUTE_FLUSH_READY /*Required alignment size for buffers*/ @@ -335,15 +349,15 @@ /*Place performance critical functions into a faster memory (e.g RAM)*/ #define LV_ATTRIBUTE_FAST_MEM -/*Prefix variables that are used in GPU accelerated operations, often these need to be placed in RAM sections that are DMA accessible*/ -#define LV_ATTRIBUTE_DMA - /*Export integer constant to binding. This macro is used with constants in the form of LV_ that *should also appear on LVGL binding API such as Micropython.*/ #define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/ -/*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/ -#define LV_USE_LARGE_COORD 0 +/*Prefix all global extern data with this*/ +#define LV_ATTRIBUTE_EXTERN_DATA + +/* Use `float` as `lv_value_precise_t` */ +#define LV_USE_FLOAT 0 /*================== * FONT USAGE @@ -352,12 +366,12 @@ /*Montserrat fonts with ASCII range and some symbols using bpp = 4 *https://fonts.google.com/specimen/Montserrat*/ #define LV_FONT_MONTSERRAT_8 0 -#define LV_FONT_MONTSERRAT_10 1 +#define LV_FONT_MONTSERRAT_10 1 // TASMOTA #define LV_FONT_MONTSERRAT_12 0 #define LV_FONT_MONTSERRAT_14 1 #define LV_FONT_MONTSERRAT_16 0 #define LV_FONT_MONTSERRAT_18 0 -#define LV_FONT_MONTSERRAT_20 1 +#define LV_FONT_MONTSERRAT_20 1 // TASMOTA #define LV_FONT_MONTSERRAT_22 0 #define LV_FONT_MONTSERRAT_24 0 #define LV_FONT_MONTSERRAT_26 0 @@ -374,19 +388,18 @@ #define LV_FONT_MONTSERRAT_48 0 /*Demonstrate special features*/ -#define LV_FONT_MONTSERRAT_12_SUBPX 0 -#define LV_FONT_MONTSERRAT_28_COMPRESSED 1 /*bpp = 3*/ +#define LV_FONT_MONTSERRAT_28_COMPRESSED 1 // TASMOTA /*bpp = 3*/ #define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, Persian letters and all their forms*/ #define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/ /*Pixel perfect monospace fonts*/ -#define LV_FONT_UNSCII_8 1 -#define LV_FONT_UNSCII_16 1 +#define LV_FONT_UNSCII_8 1 // TASMOTA +#define LV_FONT_UNSCII_16 1 // TASMOTA /*Optionally declare custom fonts here. *You can use these fonts as default font too and they will be available globally. *E.g. #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) LV_FONT_DECLARE(my_font_2)*/ -// Tasmota specific +// TASMOTA specific #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(seg7_8) \ LV_FONT_DECLARE(seg7_10) \ LV_FONT_DECLARE(seg7_12) \ @@ -435,14 +448,7 @@ #define LV_FONT_FMT_TXT_LARGE 0 /*Enables/disables support for compressed fonts.*/ -#define LV_USE_FONT_COMPRESSED 1 - -/*Enable subpixel rendering*/ -#define LV_USE_FONT_SUBPX 1 -#if LV_USE_FONT_SUBPX - /*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/ - #define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/ -#endif +#define LV_USE_FONT_COMPRESSED 1 // TASMOTA /*Enable drawing placeholders when glyph dsc is not found*/ #define LV_USE_FONT_PLACEHOLDER 1 @@ -460,7 +466,7 @@ #define LV_TXT_ENC LV_TXT_ENC_UTF8 /*Can break (wrap) texts on these chars*/ -#define LV_TXT_BREAK_CHARS " ,.;:-_" +#define LV_TXT_BREAK_CHARS " ,.;:-_)]}" /*If a word is at least this long, will break wherever "prettiest" *To disable, set to a value <= 0*/ @@ -474,9 +480,6 @@ *Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/ #define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3 -/*The control character to use for signalling text recoloring.*/ -#define LV_TXT_COLOR_CMD "#" - /*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts. *The direction will be processed according to the Unicode Bidirectional Algorithm: *https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ @@ -494,61 +497,24 @@ #define LV_USE_ARABIC_PERSIAN_CHARS 0 /*================== - * WIDGET USAGE + * WIDGETS *================*/ /*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/ +#define LV_WIDGETS_HAS_DEFAULT_VALUE 1 + +#define LV_USE_ANIMIMG 1 + #define LV_USE_ARC 1 #define LV_USE_BAR 1 -#define LV_USE_BTN 1 +#define LV_USE_BUTTON 1 -#define LV_USE_BTNMATRIX 1 +#define LV_USE_BUTTONMATRIX 1 -#define LV_USE_CANVAS 1 - -#define LV_USE_CHECKBOX 1 - -#define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ - -#define LV_USE_IMG 1 /*Requires: lv_label*/ - -#define LV_USE_LABEL 1 -#if LV_USE_LABEL - #define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ - #define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ -#endif - -#define LV_USE_LINE 1 - -#define LV_USE_ROLLER 1 /*Requires: lv_label*/ -#if LV_USE_ROLLER - #define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/ -#endif - -#define LV_USE_SLIDER 1 /*Requires: lv_bar*/ - -#define LV_USE_SWITCH 1 - -#define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ -#if LV_USE_TEXTAREA != 0 - #define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ -#endif - -#define LV_USE_TABLE 1 - -/*================== - * EXTRA COMPONENTS - *==================*/ - -/*----------- - * Widgets - *----------*/ -#define LV_USE_ANIMIMG 1 - -#define LV_USE_CALENDAR 0 +#define LV_USE_CALENDAR 1 #if LV_USE_CALENDAR #define LV_CALENDAR_WEEK_STARTS_MONDAY 0 #if LV_CALENDAR_WEEK_STARTS_MONDAY @@ -562,24 +528,43 @@ #define LV_USE_CALENDAR_HEADER_DROPDOWN 1 #endif /*LV_USE_CALENDAR*/ +#define LV_USE_CANVAS 1 + #define LV_USE_CHART 1 -#define LV_USE_COLORWHEEL 1 +#define LV_USE_CHECKBOX 1 -#define LV_USE_IMGBTN 1 +#define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ + +#define LV_USE_IMAGE 1 /*Requires: lv_label*/ + +#define LV_USE_IMAGEBUTTON 1 #define LV_USE_KEYBOARD 1 +#define LV_USE_LABEL 1 +#if LV_USE_LABEL + #define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ + #define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ + #define LV_LABEL_WAIT_CHAR_COUNT 3 /*The count of wait chart*/ +#endif + #define LV_USE_LED 1 +#define LV_USE_LINE 1 + #define LV_USE_LIST 1 #define LV_USE_MENU 1 -#define LV_USE_METER 1 - #define LV_USE_MSGBOX 1 +#define LV_USE_ROLLER 1 /*Requires: lv_label*/ + +#define LV_USE_SCALE 1 + +#define LV_USE_SLIDER 1 /*Requires: lv_bar*/ + #define LV_USE_SPAN 1 #if LV_USE_SPAN /*A line text can contain maximum num of span descriptor */ @@ -590,15 +575,24 @@ #define LV_USE_SPINNER 1 +#define LV_USE_SWITCH 1 + +#define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ +#if LV_USE_TEXTAREA != 0 + #define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ +#endif + +#define LV_USE_TABLE 1 + #define LV_USE_TABVIEW 1 #define LV_USE_TILEVIEW 1 -#define LV_USE_WIN 0 +#define LV_USE_WIN 1 -/*----------- - * Themes - *----------*/ +/*================== + * THEMES + *==================*/ /*A simple, impressive and very complete theme*/ #define LV_USE_THEME_DEFAULT 1 @@ -615,14 +609,14 @@ #endif /*LV_USE_THEME_DEFAULT*/ /*A very simple theme that is a good starting point for a custom theme*/ -#define LV_USE_THEME_BASIC 1 +#define LV_USE_THEME_SIMPLE 1 /*A theme designed for monochrome displays*/ #define LV_USE_THEME_MONO 1 -/*----------- - * Layouts - *----------*/ +/*================== + * LAYOUTS + *==================*/ /*A layout similar to Flexbox in CSS.*/ #define LV_USE_FLEX 1 @@ -630,9 +624,9 @@ /*A layout similar to Grid in CSS.*/ #define LV_USE_GRID 1 -/*--------------------- - * 3rd party libraries - *--------------------*/ +/*==================== + * 3RD PARTS LIBRARIES + *====================*/ /*File system interfaces for common APIs */ @@ -667,42 +661,93 @@ #define LV_FS_FATFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ #endif -/*PNG decoder library*/ -#define LV_USE_PNG 1 +/*API for memory-mapped file access. */ +#define LV_USE_FS_MEMFS 0 +#if LV_USE_FS_MEMFS + #define LV_FS_MEMFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ +#endif + +/*LODEPNG decoder library*/ +#define LV_USE_LODEPNG 1 // TASMOTA + +/*PNG decoder(libpng) library*/ +#define LV_USE_LIBPNG 0 /*BMP decoder library*/ #define LV_USE_BMP 0 /* JPG + split JPG decoder library. * Split JPG is a custom format optimized for embedded systems. */ -#define LV_USE_SJPG 0 +#define LV_USE_TJPGD 0 + +/* libjpeg-turbo decoder library. + * Supports complete JPEG specifications and high-performance JPEG decoding. */ +#define LV_USE_LIBJPEG_TURBO 0 /*GIF decoder library*/ #define LV_USE_GIF 0 +#if LV_USE_GIF +/*GIF decoder accelerate*/ +#define LV_GIF_CACHE_DECODE_DATA 0 +#endif + + +/*Decode bin images to RAM*/ +#define LV_BIN_DECODER_RAM_LOAD 0 + +/*RLE decompress library*/ +#define LV_USE_RLE 0 /*QR code library*/ -#define LV_USE_QRCODE 1 +#define LV_USE_QRCODE 1 // TASMOTA + +/*Barcode code library*/ +#define LV_USE_BARCODE 0 /*FreeType library*/ -#define LV_USE_FREETYPE 1 +#define LV_USE_FREETYPE 1 // TASMOTA #if LV_USE_FREETYPE - /*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/ - #define LV_FREETYPE_CACHE_SIZE (16 * 1024) - #if LV_FREETYPE_CACHE_SIZE >= 0 - /* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */ - /* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */ - /* if font size >= 256, must be configured as image cache */ - #define LV_FREETYPE_SBIT_CACHE 0 - /* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */ - /* (0:use system defaults) */ - #define LV_FREETYPE_CACHE_FT_FACES 0 - #define LV_FREETYPE_CACHE_FT_SIZES 0 - #endif + /*Memory used by FreeType to cache characters in kilobytes*/ + #define LV_FREETYPE_CACHE_SIZE 64 // TODO TASMOTA (only with PSRAM ?) + + /*Let FreeType to use LVGL memory and file porting*/ + #define LV_FREETYPE_USE_LVGL_PORT 0 + + /* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */ + /* (0:use system defaults) */ + #define LV_FREETYPE_CACHE_FT_FACES 8 + #define LV_FREETYPE_CACHE_FT_SIZES 8 + #define LV_FREETYPE_CACHE_FT_GLYPH_CNT 256 +#endif + +/* Built-in TTF decoder */ +#define LV_USE_TINY_TTF 0 +#if LV_USE_TINY_TTF + /* Enable loading TTF data from files */ + #define LV_TINY_TTF_FILE_SUPPORT 0 #endif /*Rlottie library*/ #define LV_USE_RLOTTIE 0 +/*Enable Vector Graphic APIs*/ +#define LV_USE_VECTOR_GRAPHIC 1 // TASMOTA + +/* Enable ThorVG (vector graphics library) from the src/libs folder */ +#define LV_USE_THORVG_INTERNAL 0 + +/* Enable ThorVG by assuming that its installed and linked to the project */ +#define LV_USE_THORVG_EXTERNAL 0 + +/*Enable LZ4 compress/decompress lib*/ +#define LV_USE_LZ4 0 + +/*Use lvgl built-in LZ4 lib*/ +#define LV_USE_LZ4_INTERNAL 0 + +/*Use external LZ4 library*/ +#define LV_USE_LZ4_EXTERNAL 0 + /*FFmpeg library for image decoding and playing videos *Supports all major image formats so do not enable other image decoder with it*/ #define LV_USE_FFMPEG 0 @@ -711,13 +756,65 @@ #define LV_FFMPEG_DUMP_FORMAT 0 #endif -/*----------- - * Others - *----------*/ +/*================== + * OTHERS + *==================*/ /*1: Enable API to take snapshot for object*/ #define LV_USE_SNAPSHOT 0 +/*1: Enable system monitor component*/ +#define LV_USE_SYSMON 0 +#if LV_USE_SYSMON + /*Get the idle percentage. E.g. uint32_t my_get_idle(void);*/ + #define LV_SYSMON_GET_IDLE lv_timer_get_idle + + /*1: Show CPU usage and FPS count + * Requires `LV_USE_SYSMON = 1`*/ + #define LV_USE_PERF_MONITOR 0 + #if LV_USE_PERF_MONITOR + #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT + + /*0: Displays performance data on the screen, 1: Prints performance data using log.*/ + #define LV_USE_PERF_MONITOR_LOG_MODE 0 + #endif + + /*1: Show the used memory and the memory fragmentation + * Requires `LV_USE_BUILTIN_MALLOC = 1` + * Requires `LV_USE_SYSMON = 1`*/ + #define LV_USE_MEM_MONITOR 0 + #if LV_USE_MEM_MONITOR + #define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT + #endif + +#endif /*LV_USE_SYSMON*/ + +/*1: Enable the runtime performance profiler*/ +#define LV_USE_PROFILER 0 +#if LV_USE_PROFILER + /*1: Enable the built-in profiler*/ + #define LV_USE_PROFILER_BUILTIN 1 + #if LV_USE_PROFILER_BUILTIN + /*Default profiler trace buffer size*/ + #define LV_PROFILER_BUILTIN_BUF_SIZE (16 * 1024) /*[bytes]*/ + #endif + + /*Header to include for the profiler*/ + #define LV_PROFILER_INCLUDE "lvgl/src/misc/lv_profiler_builtin.h" + + /*Profiler start point function*/ + #define LV_PROFILER_BEGIN LV_PROFILER_BUILTIN_BEGIN + + /*Profiler end point function*/ + #define LV_PROFILER_END LV_PROFILER_BUILTIN_END + + /*Profiler start point function with custom tag*/ + #define LV_PROFILER_BEGIN_TAG LV_PROFILER_BUILTIN_BEGIN_TAG + + /*Profiler end point function with custom tag*/ + #define LV_PROFILER_END_TAG LV_PROFILER_BUILTIN_END_TAG +#endif + /*1: Enable Monkey test*/ #define LV_USE_MONKEY 0 @@ -730,8 +827,8 @@ /*1: Support using images as font in label or span widgets */ #define LV_USE_IMGFONT 0 -/*1: Enable a published subscriber based messaging system */ -#define LV_USE_MSG 0 +/*1: Enable an observer pattern implementation*/ +#define LV_USE_OBSERVER 0 // TASMOTA /*1: Enable Pinyin input method*/ /*Requires: lv_keyboard*/ @@ -748,15 +845,101 @@ #define LV_IME_PINYIN_USE_K9_MODE 1 #if LV_IME_PINYIN_USE_K9_MODE == 1 #define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3 - #endif // LV_IME_PINYIN_USE_K9_MODE + #endif /*LV_IME_PINYIN_USE_K9_MODE*/ #endif +/*1: Enable file explorer*/ +/*Requires: lv_table*/ +#define LV_USE_FILE_EXPLORER 0 +#if LV_USE_FILE_EXPLORER + /*Maximum length of path*/ + #define LV_FILE_EXPLORER_PATH_MAX_LEN (128) + /*Quick access bar, 1:use, 0:not use*/ + /*Requires: lv_list*/ + #define LV_FILE_EXPLORER_QUICK_ACCESS 1 +#endif + +/*================== + * DEVICES + *==================*/ + +/*Use SDL to open window on PC and handle mouse and keyboard*/ +#define LV_USE_SDL 0 +#if LV_USE_SDL + #define LV_SDL_INCLUDE_PATH + #define LV_SDL_RENDER_MODE LV_DISPLAY_RENDER_MODE_DIRECT /*LV_DISPLAY_RENDER_MODE_DIRECT is recommended for best performance*/ + #define LV_SDL_BUF_COUNT 1 /*1 or 2*/ + #define LV_SDL_FULLSCREEN 0 /*1: Make the window full screen by default*/ + #define LV_SDL_DIRECT_EXIT 1 /*1: Exit the application when all SDL windows are closed*/ +#endif + +/*Use X11 to open window on Linux desktop and handle mouse and keyboard*/ +#define LV_USE_X11 0 +#if LV_USE_X11 + #define LV_X11_DIRECT_EXIT 1 /*Exit the application when all X11 windows have been closed*/ + #define LV_X11_DOUBLE_BUFFER 1 /*Use double buffers for endering*/ + /*select only 1 of the following render modes (LV_X11_RENDER_MODE_PARTIAL preferred!)*/ + #define LV_X11_RENDER_MODE_PARTIAL 1 /*Partial render mode (preferred)*/ + #define LV_X11_RENDER_MODE_DIRECT 0 /*direct render mode*/ + #define LV_X11_RENDER_MODE_FULL 0 /*Full render mode*/ +#endif + +/*Driver for /dev/fb*/ +#define LV_USE_LINUX_FBDEV 0 +#if LV_USE_LINUX_FBDEV + #define LV_LINUX_FBDEV_BSD 0 + #define LV_LINUX_FBDEV_RENDER_MODE LV_DISPLAY_RENDER_MODE_PARTIAL + #define LV_LINUX_FBDEV_BUFFER_COUNT 0 + #define LV_LINUX_FBDEV_BUFFER_SIZE 60 +#endif + +/*Use Nuttx to open window and handle touchscreen*/ +#define LV_USE_NUTTX 0 + +#if LV_USE_NUTTX + #define LV_USE_NUTTX_LIBUV 0 + + /*Use Nuttx custom init API to open window and handle touchscreen*/ + #define LV_USE_NUTTX_CUSTOM_INIT 0 + + /*Driver for /dev/lcd*/ + #define LV_USE_NUTTX_LCD 0 + #if LV_USE_NUTTX_LCD + #define LV_NUTTX_LCD_BUFFER_COUNT 0 + #define LV_NUTTX_LCD_BUFFER_SIZE 60 + #endif + + /*Driver for /dev/input*/ + #define LV_USE_NUTTX_TOUCHSCREEN 0 + +#endif + +/*Driver for /dev/dri/card*/ +#define LV_USE_LINUX_DRM 0 + +/*Interface for TFT_eSPI*/ +#define LV_USE_TFT_ESPI 0 + +/*Driver for evdev input devices*/ +#define LV_USE_EVDEV 0 + +/*Drivers for LCD devices connected via SPI/parallel port*/ +#define LV_USE_ST7735 0 +#define LV_USE_ST7789 0 +#define LV_USE_ST7796 0 +#define LV_USE_ILI9341 0 + +#define LV_USE_GENERIC_MIPI (LV_USE_ST7735 | LV_USE_ST7789 | LV_USE_ST7796 | LV_USE_ILI9341) + +/* LVGL Windows backend */ +#define LV_USE_WINDOWS 0 + /*================== * EXAMPLES *==================*/ /*Enable the examples to be built with the library*/ -#define LV_BUILD_EXAMPLES 0 +#define LV_BUILD_EXAMPLES 0 // TASMOTA /*=================== * DEMO USAGE @@ -765,7 +948,7 @@ /*Show some widget. It might be required to increase `LV_MEM_SIZE` */ #define LV_USE_DEMO_WIDGETS 0 #if LV_USE_DEMO_WIDGETS -#define LV_DEMO_WIDGETS_SLIDESHOW 0 + #define LV_DEMO_WIDGETS_SLIDESHOW 0 #endif /*Demonstrate the usage of encoder and keyboard*/ @@ -773,10 +956,9 @@ /*Benchmark your system*/ #define LV_USE_DEMO_BENCHMARK 0 -#if LV_USE_DEMO_BENCHMARK -/*Use RGB565A8 images with 16 bit color depth instead of ARGB8565*/ -#define LV_DEMO_BENCHMARK_RGB565A8 0 -#endif + +/*Render test for each primitives. Requires at least 480x272 display*/ +#define LV_USE_DEMO_RENDER 0 /*Stress test for LVGL*/ #define LV_USE_DEMO_STRESS 0 @@ -791,6 +973,20 @@ #define LV_DEMO_MUSIC_AUTO_PLAY 0 #endif +/*Flex layout demo*/ +#define LV_USE_DEMO_FLEX_LAYOUT 0 + +/*Smart-phone like multi-language demo*/ +#define LV_USE_DEMO_MULTILANG 0 + +/*Widget transformation demo*/ +#define LV_USE_DEMO_TRANSFORM 0 + +/*Demonstrate scroll settings*/ +#define LV_USE_DEMO_SCROLL 0 + +/*Vector graphic demo*/ +#define LV_USE_DEMO_VECTOR_GRAPHIC 0 /*--END OF LV_CONF_H--*/ #endif /*LV_CONF_H*/ diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index ce1a1f3f2..661a11921 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -1183,14 +1183,18 @@ #define USE_LVGL_BG_DEFAULT 0x000000 // Default color for the uninitialized background screen (black) // Disabling select widgets that will be rarely used in Tasmota (-13KB) // Main widgets as defined in LVGL8 + #define BE_LV_WIDGET_OBJ #define BE_LV_WIDGET_ARC #define BE_LV_WIDGET_BAR - #define BE_LV_WIDGET_BTN - #define BE_LV_WIDGET_BTNMATRIX + #define BE_LV_WIDGET_BTN // LVGL 8 + #define BE_LV_WIDGET_BUTTON // LVGL 9 + #define BE_LV_WIDGET_BTNMATRIX // LVGL 8 + #define BE_LV_WIDGET_BUTTONMATRIX // LVGL 9 #define BE_LV_WIDGET_CANVAS #define BE_LV_WIDGET_CHECKBOX #define BE_LV_WIDGET_DROPDOWN - #define BE_LV_WIDGET_IMG + #define BE_LV_WIDGET_IMG // LVGL 8 + #define BE_LV_WIDGET_IMAGE // LVGL 9 #define BE_LV_WIDGET_LABEL #define BE_LV_WIDGET_LINE #define BE_LV_WIDGET_ROLLER @@ -1199,20 +1203,23 @@ #define BE_LV_WIDGET_TABLE #define BE_LV_WIDGET_TEXTAREA + #define BE_LV_WIDGET_ANIMIMG #define BE_LV_WIDGET_CHART #define BE_LV_WIDGET_COLORWHEEL - #define BE_LV_WIDGET_IMGBTN + #define BE_LV_WIDGET_IMGBTN // LVGL 8 + #define BE_LV_WIDGET_IMAGEBUTTON // LVGL 9 + // #define BE_LV_WIDGET_KEYBOARD #define BE_LV_WIDGET_LED + // #define BE_LV_WIDGET_LIST #define BE_LV_WIDGET_METER #define BE_LV_WIDGET_MSGBOX + #define BE_LV_WIDGET_QRCODE + #define BE_LV_WIDGET_SCALE #define BE_LV_WIDGET_SPINBOX #define BE_LV_WIDGET_SPINNER - // #define BE_LV_WIDGET_KEYBOARD + #define BE_LV_WIDGET_SPANGROUP // #define BE_LV_WIDGET_TABVIEW // #define BE_LV_WIDGET_TILEVIEW - // #define BE_LV_WIDGET_LIST - - #define BE_LV_WIDGET_QRCODE #endif // ESP32 diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_lvgl.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_lvgl.ino index 59e49f58f..ada69de9a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_lvgl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_lvgl.ino @@ -34,7 +34,6 @@ #include "be_mapping.h" #include "be_ctypes.h" #include "lv_berry.h" -#include "Adafruit_LvGL_Glue.h" // Berry easy logging extern "C" { @@ -43,7 +42,11 @@ extern "C" { extern const size_t lv_classes_size; } -extern Adafruit_LvGL_Glue * glue; +// Forward declaration of helper functions +extern bool lvgl_started(void); +extern void lvgl_set_screenshot_file(File * file); +extern void lvgl_reset_screenshot_file(void); +File * lvgl_get_screenshot_file(void); /******************************************************************** * Structures used by LVGL_Berry @@ -95,7 +98,7 @@ public: class LVBE_globals { public: - lv_indev_drv_t indev_drv; + lv_indev_t * indev; // TODO still needed? or `indev_list` is enough? LList indev_list; // input devices LVBE_button btn[3]; @@ -129,12 +132,16 @@ extern "C" { #ifdef USE_LVGL_FREETYPE int argc = be_top(vm); if (argc == 3 && be_isstring(vm, 1) && be_isint(vm, 2) && be_isint(vm, 3)) { - lv_ft_info_t info = {}; - info.name = be_tostring(vm, 1); - info.weight = be_toint(vm, 2); - info.style = be_toint(vm, 3); - lv_ft_font_init(&info); - lv_font_t * font = info.font; + +// lv_font_t * lv_freetype_font_create(const char * pathname, lv_freetype_font_render_mode_t render_mode, uint32_t size, +// lv_freetype_font_style_t style); + // lv_ft_info_t info = {}; + const char * name = be_tostring(vm, 1); + int32_t weight = be_toint(vm, 2); + int32_t style = be_toint(vm, 3); + lv_font_t * font = lv_freetype_font_create(name, LV_FREETYPE_FONT_RENDER_MODE_BITMAP, weight, style); + // lv_ft_font_init(&info); + // lv_font_t * font = info.font; if (font != nullptr) { be_find_global_or_module_member(vm, "lv.lv_font"); @@ -379,10 +386,10 @@ extern "C" { /*********************************************************************************************\ * Tasmota Logo \*********************************************************************************************/ - #include "lvgl_berry/tasmota_logo_64_truecolor_alpha.h" + extern const lv_img_dsc_t TASMOTA_Symbol_64; - void lv_img_set_tasmota_logo(lv_obj_t * img) { - lv_img_set_src(img, &tasmota_logo_64_truecolor); + void lv_image_set_tasmota_logo(lv_obj_t * img) { + lv_image_set_src(img, &TASMOTA_Symbol_64); } /*********************************************************************************************\ @@ -423,7 +430,7 @@ extern "C" { * * lv.register_button_encoder([inv: bool]) -> nil \*********************************************************************************************/ - void lvbe_encoder_with_keys_read(lv_indev_drv_t * drv, lv_indev_data_t*data); + void lvbe_encoder_with_keys_read(lv_indev_t * drv, lv_indev_data_t*data); int lv0_register_button_encoder(bvm *vm); // add buttons with encoder logic int lv0_register_button_encoder(bvm *vm) { @@ -448,15 +455,14 @@ extern "C" { lvbe.btn[2].set_inverted(inverted); berry_log_C(D_LOG_LVGL "Button Rotary encoder using GPIOs %d,%d,%d%s", btn0, btn1, btn2, inverted ? " (inverted)" : ""); - lv_indev_drv_init(&lvbe.indev_drv); - lvbe.indev_drv.type = LV_INDEV_TYPE_ENCODER; - lvbe.indev_drv.read_cb = lvbe_encoder_with_keys_read; + lvbe.indev = lv_indev_create(); + lv_indev_set_type(lvbe.indev, LV_INDEV_TYPE_ENCODER); + lv_indev_set_read_cb(lvbe.indev, lvbe_encoder_with_keys_read); - lv_indev_t * indev = lv_indev_drv_register(&lvbe.indev_drv); - lvbe.indev_list.addHead(indev); // keep track of indevs + lvbe.indev_list.addHead(lvbe.indev); // keep track of indevs // TODO what do we do with it? - be_find_global_or_module_member(vm, "lv.lv_indev"); - be_pushint(vm, (int32_t) indev); + be_find_global_or_module_member(vm, "lv.indev"); + be_pushcomptr(vm, (void*)lvbe.indev); be_call(vm, 1); be_pop(vm, 1); @@ -476,7 +482,7 @@ extern "C" { // lv_indev_state_t state; /**< LV_INDEV_STATE_REL or LV_INDEV_STATE_PR*/ // } lv_indev_data_t; - void lvbe_encoder_with_keys_read(lv_indev_drv_t * drv, lv_indev_data_t *data){ + void lvbe_encoder_with_keys_read(lv_indev_t * drv, lv_indev_data_t *data){ // scan through buttons if we need to report something uint32_t i; for (i = 0; i < 3; i++) { @@ -508,16 +514,16 @@ extern "C" { \********************************************************************************************/ int lv0_screenshot(bvm *vm); int lv0_screenshot(bvm *vm) { - if (!glue) { be_return_nil(vm); } + if (!lvgl_started()) { be_return_nil(vm); } char fname[32]; snprintf(fname, sizeof(fname), "/screenshot-%d.bmp", Rtc.utc_time); File f = dfsp->open(fname, "w"); if (f) { - glue->setScreenshotFile(&f); + lvgl_set_screenshot_file(&f); - uint32_t bmp_width = lv_disp_get_hor_res(nullptr); - uint32_t bmp_height = lv_disp_get_ver_res(nullptr); + uint32_t bmp_width = lv_display_get_horizontal_resolution(nullptr); + uint32_t bmp_height = lv_display_get_vertical_resolution(nullptr); // write BMP header static const uint8_t bmp_sign[] = { 0x42, 0x4d }; // BM = Windows @@ -560,10 +566,10 @@ extern "C" { // now we can write the pixels array // redraw screen - lv_obj_invalidate(lv_scr_act()); + lv_obj_invalidate(lv_screen_active()); lv_refr_now(lv_disp_get_default()); - glue->stopScreenshot(); + lvgl_reset_screenshot_file(); f.close(); } be_pushstring(vm, fname); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino b/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino index 9540bf562..992dfed23 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino @@ -18,7 +18,7 @@ */ -#ifdef USE_LVGL +#if defined(USE_LVGL) && defined(USE_UNIVERSAL_DISPLAY) #include #include "lvgl.h" @@ -30,20 +30,26 @@ #include "freertos/task.h" #include "freertos/semphr.h" -#include "Adafruit_LvGL_Glue.h" - -Adafruit_LvGL_Glue * glue; +struct LVGL_Glue { + lv_display_t *lv_display = nullptr; + lv_indev_t *lv_indev = nullptr; + lv_color_t *lv_pixel_buf = nullptr; + lv_color_t *lv_pixel_buf2 = nullptr; + Ticker tick; + File * screenshot = nullptr; + bool first_frame = true; // Tracks if a call to `lv_flush_callback` needs to wait for DMA transfer to complete +}; +LVGL_Glue * lvgl_glue; // ************************************************** // Logging // ************************************************** #if LV_USE_LOG #ifdef USE_BERRY -static void lvbe_debug(const char *msg); -static void lvbe_debug(const char *msg) { +static void lvbe_debug(lv_log_level_t, const char *msg); +static void lvbe_debug(lv_log_level_t, const char *msg) { be_writebuffer("LVG: ", sizeof("LVG: ")); be_writebuffer(msg, strlen(msg)); - be_writebuffer("\n", sizeof("\n")); } #endif #endif @@ -54,16 +60,13 @@ static void lvbe_debug(const char *msg) { // This is the flush function required for LittlevGL screen updates. // It receives a bounding rect and an array of pixel data (conveniently // already in 565 format, so the Earth was lucky there). -void lv_flush_callback(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p); -void lv_flush_callback(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) { - // Get pointer to glue object from indev user data - Adafruit_LvGL_Glue *glue = (Adafruit_LvGL_Glue *)disp->user_data; - +void lv_flush_callback(lv_display_t *disp, const lv_area_t *area, uint8_t *color_p); +void lv_flush_callback(lv_display_t *disp, const lv_area_t *area, uint8_t *color_p) { uint16_t width = (area->x2 - area->x1 + 1); uint16_t height = (area->y2 - area->y1 + 1); // check if we are currently doing a screenshot - if (glue->getScreenshotFile() != nullptr) { + if (lvgl_glue->screenshot != nullptr) { // save pixels to file int32_t btw = (width * height * LV_COLOR_DEPTH + 7) / 8; while (btw > 0) { @@ -72,7 +75,7 @@ void lv_flush_callback(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *c for (uint32_t i = 0; i < btw / 2; i++) (pix[i] = pix[i] << 8 | pix[i] >> 8); #endif if (btw > 0) { // if we had a previous error (ex disk full) don't try to write anymore - int32_t ret = glue->getScreenshotFile()->write((const uint8_t*) color_p, btw); + int32_t ret = lvgl_glue->screenshot->write((const uint8_t*) color_p, btw); if (ret >= 0) { btw -= ret; } else { @@ -84,25 +87,23 @@ void lv_flush_callback(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *c return; // ok } - Renderer *display = glue->display; - - if (!glue->first_frame) { - //display->dmaWait(); // Wait for prior DMA transfer to complete - //display->endWrite(); // End transaction from any prior call + if (!lvgl_glue->first_frame) { + //renderer->dmaWait(); // Wait for prior DMA transfer to complete + //disrendererplay->endWrite(); // End transaction from any prior call } else { - glue->first_frame = false; + lvgl_glue->first_frame = false; } uint32_t pixels_len = width * height; uint32_t chrono_start = millis(); - display->setAddrWindow(area->x1, area->y1, area->x1+width, area->y1+height); - display->pushColors((uint16_t *)color_p, pixels_len, false); - display->setAddrWindow(0,0,0,0); + renderer->setAddrWindow(area->x1, area->y1, area->x1+width, area->y1+height); + renderer->pushColors((uint16_t *)color_p, pixels_len, true); + renderer->setAddrWindow(0,0,0,0); uint32_t chrono_time = millis() - chrono_start; lv_disp_flush_ready(disp); - if (pixels_len >= 10000 && (!display->lvgl_param.use_dma)) { + if (pixels_len >= 10000 && (!renderer->lvgl_param.use_dma)) { AddLog(LOG_LEVEL_DEBUG, D_LOG_LVGL "Refreshed %d pixels in %d ms (%i pix/ms)", pixels_len, chrono_time, chrono_time > 0 ? pixels_len / chrono_time : -1); } @@ -336,54 +337,136 @@ extern "C" { } +// ARCHITECTURE-SPECIFIC TIMER STUFF --------------------------------------- + +extern void lv_flush_callback(lv_display_t *disp, const lv_area_t *area, uint8_t * px_map); + +// Tick interval for LittlevGL internal timekeeping; 1 to 10 ms recommended +static const int lv_tick_interval_ms = 5; + +static void lv_tick_handler(void) { lv_tick_inc(lv_tick_interval_ms); } + +// TOUCHSCREEN STUFF ------------------------------------------------------- + +uint32_t Touch_Status(int32_t sel); + +//typedef void (*lv_indev_read_cb_t)(lv_indev_t * indev, lv_indev_data_t * data); +void lvgl_touchscreen_read(lv_indev_t *indev_drv, lv_indev_data_t *data); +void lvgl_touchscreen_read(lv_indev_t *indev_drv, lv_indev_data_t *data) { + data->point.x = Touch_Status(1); // Last-pressed coordinates + data->point.y = Touch_Status(2); + data->state = Touch_Status(0) ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; + data->continue_reading = false; /*No buffering now so no more data read*/ + // keep data for TS calibration + lv_ts_calibration.state = data->state; + if (data->state == LV_INDEV_STATE_PRESSED) { // if not pressed, the data may be invalid + AddLog(LOG_LEVEL_DEBUG_MORE, "LVG: TS: %i, %i", data->point.x, data->point.y); + lv_ts_calibration.x = data->point.x; + lv_ts_calibration.y = data->point.y; + lv_ts_calibration.raw_x = Touch_Status(-1); + lv_ts_calibration.raw_y = Touch_Status(-2); + } +} + +// Actual RAM usage will be 2X these figures, since using 2 DMA buffers... +#define LV_BUFFER_ROWS 60 // Most others have a bit more space + /************************************************************ * Initialize the display / touchscreen drivers then launch lvgl * - * We use Adafruit_LvGL_Glue to leverage the Adafruit - * display ecosystem. + * We use our own simplified mapping on top of Universal display ************************************************************/ extern Renderer *Init_uDisplay(const char *desc); - void start_lvgl(const char * uconfig); void start_lvgl(const char * uconfig) { - if (glue != nullptr) { + if (lvgl_glue != nullptr) { AddLog(LOG_LEVEL_DEBUG, D_LOG_LVGL "LVGL was already initialized"); return; } if (!renderer || uconfig) { -#ifdef USE_UNIVERSAL_DISPLAY // TODO - we will probably support only UNIV_DISPLAY renderer = Init_uDisplay((char*)uconfig); + AddLog(LOG_LEVEL_ERROR, "LVG: Could not start Universal Display"); if (!renderer) return; -#else - return; -#endif } renderer->DisplayOnff(true); // ************************************************** - // Initialize the glue between Adafruit and LVGL + // Initialize LVGL // ************************************************** - glue = new Adafruit_LvGL_Glue(); + lvgl_glue = new LVGL_Glue; - // Initialize glue, passing in address of display & touchscreen - LvGLStatus status = glue->begin(renderer, (void*)1, false); - if (status != LVGL_OK) { - AddLog(LOG_LEVEL_ERROR, PSTR("Glue error %d"), status); + // Initialize lvgl_glue, passing in address of display & touchscreen + lv_init(); + + // Allocate LvGL display buffer (x2 because DMA double buffering) + bool status_ok = true; + size_t lvgl_buffer_size; + do { + //lvgl_buffer_size = LV_HOR_RES_MAX * LV_BUFFER_ROWS; + uint32_t flushlines = renderer->lvgl_pars()->fluslines; + lvgl_buffer_size = renderer->width() * (flushlines ? flushlines:LV_BUFFER_ROWS); + if (renderer->lvgl_pars()->use_dma) { + lvgl_buffer_size /= 2; + if (lvgl_buffer_size < 1000000) { + lvgl_glue->lv_pixel_buf2 = new lv_color_t[lvgl_buffer_size]; + } + if (!lvgl_glue->lv_pixel_buf2) { + status_ok = false; + break; + } + } + + lvgl_glue->lv_pixel_buf = new lv_color_t[lvgl_buffer_size]; + if (!lvgl_glue->lv_pixel_buf) { + status_ok = false; + break; + } + } while (0); + + if (!status_ok) { + if (lvgl_glue->lv_pixel_buf) { + delete[] lvgl_glue->lv_pixel_buf; + lvgl_glue->lv_pixel_buf = NULL; + } + if (lvgl_glue->lv_pixel_buf2) { + delete[] lvgl_glue->lv_pixel_buf2; + lvgl_glue->lv_pixel_buf2 = NULL; + } + delete lvgl_glue; + lvgl_glue = nullptr; + AddLog(LOG_LEVEL_ERROR, "LVG: Could not allocate buffers"); return; } + // Initialize LvGL display driver + lvgl_glue->lv_display = lv_display_create(renderer->width(), renderer->height()); + lv_display_set_flush_cb(lvgl_glue->lv_display, lv_flush_callback); + lv_display_set_buffers(lvgl_glue->lv_display, lvgl_glue->lv_pixel_buf, lvgl_glue->lv_pixel_buf2, lvgl_buffer_size, LV_DISPLAY_RENDER_MODE_PARTIAL); + + // Initialize LvGL input device (touchscreen already started) + lvgl_glue->lv_indev = lv_indev_create(); + lv_indev_set_type(lvgl_glue->lv_indev, LV_INDEV_TYPE_POINTER); + lv_indev_set_read_cb(lvgl_glue->lv_indev, lvgl_touchscreen_read); + + // ESP 32------------------------------------------------ + lvgl_glue->tick.attach_ms(lv_tick_interval_ms, lv_tick_handler); + // ----------------------------------------- + // Set the default background color of the display // This is normally overriden by an opaque screen on top #ifdef USE_BERRY // By default set the display color to black and opacity to 100% - lv_disp_set_bg_color(NULL, lv_color_from_uint32(USE_LVGL_BG_DEFAULT)); - lv_disp_set_bg_opa(NULL, LV_OPA_COVER); - lv_obj_set_style_bg_color(lv_scr_act(), lv_color_from_uint32(USE_LVGL_BG_DEFAULT), static_cast(LV_PART_MAIN) | static_cast(LV_STATE_DEFAULT)); - lv_obj_set_style_bg_opa(lv_scr_act(), LV_OPA_COVER, static_cast(LV_PART_MAIN) | static_cast(LV_STATE_DEFAULT)); + lv_obj_t * background = lv_layer_bottom(); + lv_obj_set_style_bg_color(background, lv_color_hex(USE_LVGL_BG_DEFAULT), static_cast(LV_PART_MAIN) | static_cast(LV_STATE_DEFAULT)); + lv_obj_set_style_bg_opa(background, LV_OPA_COVER, static_cast(LV_PART_MAIN) | static_cast(LV_STATE_DEFAULT)); + // lv_disp_set_bg_color(NULL, lv_color_from_uint32(USE_LVGL_BG_DEFAULT)); + // lv_disp_set_bg_opa(NULL, LV_OPA_COVER); + lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(USE_LVGL_BG_DEFAULT), static_cast(LV_PART_MAIN) | static_cast(LV_STATE_DEFAULT)); + lv_obj_set_style_bg_opa(lv_screen_active(), LV_OPA_COVER, static_cast(LV_PART_MAIN) | static_cast(LV_STATE_DEFAULT)); #if LV_USE_LOG lv_log_register_print_cb(lvbe_debug); @@ -420,16 +503,42 @@ void start_lvgl(const char * uconfig) { UsePSRAM() ? USE_LVGL_FREETYPE_MAX_BYTES_PSRAM : USE_LVGL_FREETYPE_MAX_BYTES); #endif #ifdef USE_LVGL_PNG_DECODER - lv_png_init(); + lv_lodepng_init(); #endif // USE_LVGL_PNG_DECODER + // TODO check later about cache size if (UsePSRAM()) { - lv_img_cache_set_size(LV_IMG_CACHE_DEF_SIZE_PSRAM); + lv_cache_set_max_size(LV_GLOBAL_DEFAULT()->img_cache, LV_IMG_CACHE_DEF_SIZE_PSRAM, nullptr); + } else { + lv_cache_set_max_size(LV_GLOBAL_DEFAULT()->img_cache, LV_IMG_CACHE_DEF_SIZE_NOPSRAM, nullptr); } AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_LVGL "LVGL initialized")); } +/*********************************************************************************************\ + * Callable from Berry +\*********************************************************************************************/ +bool lvgl_started(void); +bool lvgl_started(void) { + return (lvgl_glue != nullptr); +} + +void lvgl_set_screenshot_file(File * file); +void lvgl_set_screenshot_file(File * file) { + lvgl_glue->screenshot = file; +} + +void lvgl_reset_screenshot_file(void); +void lvgl_reset_screenshot_file(void) { + lvgl_glue->screenshot = nullptr; +} + +File * lvgl_get_screenshot_file(void); +File * lvgl_get_screenshot_file(void) { + return lvgl_glue->screenshot; +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -441,7 +550,7 @@ bool Xdrv54(uint32_t function) case FUNC_INIT: break; case FUNC_LOOP: - if (glue) { + if (lvgl_glue) { if (TasmotaGlobal.sleep > USE_LVGL_MAX_SLEEP) { TasmotaGlobal.sleep = USE_LVGL_MAX_SLEEP; // sleep is max 10ms } @@ -479,4 +588,4 @@ bool Xdrv54(uint32_t function) return result; } -#endif // USE_LVGL +#endif // defined(USE_LVGL) && defined(USE_UNIVERSAL_DISPLAY) From 32ce27495acc6c3b18b8dc65025c9b0647aae2f5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 5 Feb 2024 12:19:14 +0100 Subject: [PATCH 270/303] Update changelogs --- CHANGELOG.md | 2 +- RELEASENOTES.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b94263100..98918f6fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ All notable changes to this project will be documented in this file. ### Breaking Changed - Matter aggregator relocated to endpoint 1 for Google compatibility, may break existing associations (#20654) -- LVGL library updated to v9.0.0, some small breaking changes in C, none in HASPmota +- ESP32 LVGL library from v8.3.11 to v9.0.0, some small breaking changes in C, none in HASPmota (#20659) ### Changed - Library OneWire-Stickbreaker by TasmotaOneWire supporting Shelly Plus Add-On (#20580) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c1fc8e472..c22fad3c7 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -163,6 +163,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Matter add human readable names for TimeSync cluster [#20666](https://github.com/arendst/Tasmota/issues/20666) ### Breaking Changed +- ESP32 LVGL library from v8.3.11 to v9.0.0, some small breaking changes in C, none in HASPmota [#20659](https://github.com/arendst/Tasmota/issues/20659) - Refactoring of Berry `animate` module for WS2812 Leds [#20236](https://github.com/arendst/Tasmota/issues/20236) - Matter aggregator relocated to endpoint 1 for Google compatibility, may break existing associations [#20654](https://github.com/arendst/Tasmota/issues/20654) From a4083263260db66a7b8afe7422cd33da023d452b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 5 Feb 2024 12:24:32 +0100 Subject: [PATCH 271/303] Bump version to v13.3.0.5 --- CHANGELOG.md | 17 +++++++++++++---- RELEASENOTES.md | 2 +- tasmota/include/tasmota_version.h | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98918f6fd..0ada7fc65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,19 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - Development -## [13.3.0.4] +## [13.3.0.5] +### Added + +### Breaking Changed +- ESP32 LVGL library from v8.3.11 to v9.0.0, some small breaking changes in C, none in HASPmota (#20659) + +### Changed + +### Fixed + +### Removed + +## [13.3.0.4] 20240205 ### Added - HASPmota support for `min` and `max` attribute in `slider` (#20582) - ESP32-C3 support for GPIO11 (#18350) @@ -14,7 +26,6 @@ All notable changes to this project will be documented in this file. ### Breaking Changed - Matter aggregator relocated to endpoint 1 for Google compatibility, may break existing associations (#20654) -- ESP32 LVGL library from v8.3.11 to v9.0.0, some small breaking changes in C, none in HASPmota (#20659) ### Changed - Library OneWire-Stickbreaker by TasmotaOneWire supporting Shelly Plus Add-On (#20580) @@ -30,8 +41,6 @@ All notable changes to this project will be documented in this file. - Matter error when removing device from Google Home (#20665) - Matter exception when fabrics is not initialized (#20667) -### Removed - ## [13.3.0.3] 20240122 ### Added - Berry `debug.caller` (#20470) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c22fad3c7..935f227c8 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -116,7 +116,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm [Complete list](BUILDS.md) of available feature and sensors. -## Changelog v13.3.0.4 +## Changelog v13.3.0.5 ### Added - Command ``TimedPower [,ON|OFF|TOGGLE|BLINK]`` executes ``Power [ON|OFF|TOGGLE|BLINK] `` and after executes ``Power [OFF|ON|TOGGLE|OFF]`` - Display of active drivers using command ``status 4`` diff --git a/tasmota/include/tasmota_version.h b/tasmota/include/tasmota_version.h index d88cfd5b7..ff562e7d0 100644 --- a/tasmota/include/tasmota_version.h +++ b/tasmota/include/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t TASMOTA_VERSION = 0x0D030004; // 13.3.0.4 +const uint32_t TASMOTA_VERSION = 0x0D030005; // 13.3.0.5 #endif // _TASMOTA_VERSION_H_ From 6cfe979f1b4e88b7076aa2679c3412f40206f6f5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 5 Feb 2024 15:09:49 +0100 Subject: [PATCH 272/303] Enable GPIO viewer on ESP32 --- tasmota/include/tasmota_configurations.h | 1 + tasmota/include/tasmota_configurations_ESP32.h | 1 + tasmota/my_user_config.h | 1 + 3 files changed, 3 insertions(+) diff --git a/tasmota/include/tasmota_configurations.h b/tasmota/include/tasmota_configurations.h index a680dc89a..9dfb0ad64 100644 --- a/tasmota/include/tasmota_configurations.h +++ b/tasmota/include/tasmota_configurations.h @@ -862,6 +862,7 @@ //#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set #undef USE_KNX // Disable KNX IP Protocol Support //#undef USE_WEBSERVER // Disable Webserver +#undef USE_GPIO_VIEWER // Disable GPIO Viewer to see realtime GPIO states (+5k6 code) #undef USE_ENHANCED_GUI_WIFI_SCAN // Disable wifi scan output with BSSID (+0k5 code) #undef USE_WEBSEND_RESPONSE // Disable command WebSend response message (+1k code) #undef USE_EMULATION // Disable Wemo or Hue emulation diff --git a/tasmota/include/tasmota_configurations_ESP32.h b/tasmota/include/tasmota_configurations_ESP32.h index 7b86bdd3c..15fc570c1 100644 --- a/tasmota/include/tasmota_configurations_ESP32.h +++ b/tasmota/include/tasmota_configurations_ESP32.h @@ -60,6 +60,7 @@ //#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set #undef USE_KNX // Disable KNX IP Protocol Support //#undef USE_WEBSERVER // Disable Webserver +#undef USE_GPIO_VIEWER // Enable GPIO Viewer to see realtime GPIO states (+5k6 code) #undef USE_ENHANCED_GUI_WIFI_SCAN // Disable wifi scan output with BSSID (+0k5 code) #undef USE_WEBSEND_RESPONSE // Disable command WebSend response message (+1k code) #undef USE_EMULATION // Disable Wemo or Hue emulation diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 661a11921..530a4199c 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -1097,6 +1097,7 @@ #endif #define USE_ESP32_SENSORS // Add support for ESP32 temperature and optional hall effect sensor +#define USE_GPIO_VIEWER // Enable GPIO Viewer to see realtime GPIO states (+5k6 code) // #define USE_DALI // Add support for DALI #define DALI_IN_INVERT 0 // DALI RX inverted ? From f88a8a6765618d220d0b74af8423159fde9d4eb7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 5 Feb 2024 15:59:37 +0100 Subject: [PATCH 273/303] Add berry divider --- lib/libesp32/berry_tasmota/src/embedded/i2c_axp192.be | 2 +- tasmota/berry/audio/audio_slm.be | 2 +- tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/libesp32/berry_tasmota/src/embedded/i2c_axp192.be b/lib/libesp32/berry_tasmota/src/embedded/i2c_axp192.be index 56ce22147..b9254af1d 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/i2c_axp192.be +++ b/lib/libesp32/berry_tasmota/src/embedded/i2c_axp192.be @@ -165,7 +165,7 @@ class AXP192 : I2C_Driver "{s}Batt Voltage{m}%.3f V{e}".. "{s}Batt Current{m}%.1f mA{e}".. #"{s}Batt Power{m}%.3f{e}".. - "{s}Temp AXP{m}%.1f °C{e}", + "{s}AXP Temperature{m}%.1f °C{e}", self.get_vbus_voltage(), self.get_vbus_voltage(), self.get_bat_voltage(), self.get_bat_current(), #self.get_bat_power(), diff --git a/tasmota/berry/audio/audio_slm.be b/tasmota/berry/audio/audio_slm.be index 303cc2c01..4f74da153 100644 --- a/tasmota/berry/audio/audio_slm.be +++ b/tasmota/berry/audio/audio_slm.be @@ -61,7 +61,7 @@ class Audio_SLM self.audio_input.get_gain(), self.rms, self.peak / 32767) - tasmota.web_send(msg) + tasmota.web_send_decimal(msg) self.peak = 0 self.rms = 0 end diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino index 563abacef..a476032c4 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino @@ -790,7 +790,7 @@ extern "C" { */ - // web append with decimal conversion + // web append without decimal conversion int32_t l_webSend(bvm *vm); int32_t l_webSend(bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments @@ -814,6 +814,7 @@ extern "C" { be_pop(vm, top); // avoid Error be_top is non zero message #ifdef USE_WEBSERVER WSContentSend_PD(PSTR("%s"), msg); + WSContentSeparator(0); #endif // USE_WEBSERVER be_return_nil(vm); // Return nil when something goes wrong } From 2dc46394dc104bfef3440a8f694b7902227ddc84 Mon Sep 17 00:00:00 2001 From: arendst Date: Mon, 5 Feb 2024 15:00:31 +0000 Subject: [PATCH 274/303] Solidified Code updated --- lib/libesp32/berry_tasmota/src/solidify/solidified_i2c_axp192.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_i2c_axp192.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_i2c_axp192.h index 27a7bf5a7..a3be29b1a 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_i2c_axp192.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_i2c_axp192.h @@ -655,7 +655,7 @@ be_local_closure(AXP192_web_sensor, /* name */ /* K2 */ be_nested_str(_X7Bs_X7DVBus_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D), /* K3 */ be_nested_str(_X7Bs_X7DBatt_X20Voltage_X7Bm_X7D_X25_X2E3f_X20V_X7Be_X7D), /* K4 */ be_nested_str(_X7Bs_X7DBatt_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D), - /* K5 */ be_nested_str(_X7Bs_X7DTemp_X20AXP_X7Bm_X7D_X25_X2E1f_X20_X26deg_X3BC_X7Be_X7D), + /* K5 */ be_nested_str(_X7Bs_X7DAXP_X20Temperature_X7Bm_X7D_X25_X2E1f_X20_X26deg_X3BC_X7Be_X7D), /* K6 */ be_nested_str(get_vbus_voltage), /* K7 */ be_nested_str(get_bat_voltage), /* K8 */ be_nested_str(get_bat_current), From 22581b0f7e56f70735918ab720021fd3f4c4fc6d Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Tue, 6 Feb 2024 16:02:49 +0100 Subject: [PATCH 275/303] Matter fix exception when calling remove_fabric (#20674) --- .../src/embedded/Matter_Expirable.be | 6 ++- .../solidify/solidified_Matter_Expirable.h | 38 ++++++++++--------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Expirable.be b/lib/libesp32/berry_matter/src/embedded/Matter_Expirable.be index 83da9d5d4..5186808e4 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Expirable.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Expirable.be @@ -142,8 +142,10 @@ class Matter_Expirable_list : list # remove - override # def remove(i) - if i >= 0 && i < size(self) self[i].before_remove() end - return super(self).remove(i) + if i != nil + if i >= 0 && i < size(self) self[i].before_remove() end + return super(self).remove(i) + end end ############################################################# diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Expirable.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Expirable.h index 4888f31a9..8fa5663aa 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Expirable.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Expirable.h @@ -482,24 +482,28 @@ be_local_closure(Matter_Expirable_list_remove, /* name */ }), be_str_weak(remove), &be_const_str_solidified, - ( &(const binstruction[17]) { /* code */ - 0x28080300, // 0000 GE R2 R1 K0 - 0x780A0007, // 0001 JMPF R2 #000A - 0x6008000C, // 0002 GETGBL R2 G12 - 0x5C0C0000, // 0003 MOVE R3 R0 - 0x7C080200, // 0004 CALL R2 1 - 0x14080202, // 0005 LT R2 R1 R2 - 0x780A0002, // 0006 JMPF R2 #000A - 0x94080001, // 0007 GETIDX R2 R0 R1 - 0x8C080501, // 0008 GETMET R2 R2 K1 - 0x7C080200, // 0009 CALL R2 1 - 0x60080003, // 000A GETGBL R2 G3 - 0x5C0C0000, // 000B MOVE R3 R0 + ( &(const binstruction[21]) { /* code */ + 0x4C080000, // 0000 LDNIL R2 + 0x20080202, // 0001 NE R2 R1 R2 + 0x780A0010, // 0002 JMPF R2 #0014 + 0x28080300, // 0003 GE R2 R1 K0 + 0x780A0007, // 0004 JMPF R2 #000D + 0x6008000C, // 0005 GETGBL R2 G12 + 0x5C0C0000, // 0006 MOVE R3 R0 + 0x7C080200, // 0007 CALL R2 1 + 0x14080202, // 0008 LT R2 R1 R2 + 0x780A0002, // 0009 JMPF R2 #000D + 0x94080001, // 000A GETIDX R2 R0 R1 + 0x8C080501, // 000B GETMET R2 R2 K1 0x7C080200, // 000C CALL R2 1 - 0x8C080502, // 000D GETMET R2 R2 K2 - 0x5C100200, // 000E MOVE R4 R1 - 0x7C080400, // 000F CALL R2 2 - 0x80040400, // 0010 RET 1 R2 + 0x60080003, // 000D GETGBL R2 G3 + 0x5C0C0000, // 000E MOVE R3 R0 + 0x7C080200, // 000F CALL R2 1 + 0x8C080502, // 0010 GETMET R2 R2 K2 + 0x5C100200, // 0011 MOVE R4 R1 + 0x7C080400, // 0012 CALL R2 2 + 0x80040400, // 0013 RET 1 R2 + 0x80000000, // 0014 RET 0 }) ) ); From 5e4a1d7b32572df2143e20619311549700c83f50 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Wed, 7 Feb 2024 05:25:51 +0100 Subject: [PATCH 276/303] Matter fix configuration loading (#20677) --- .../berry_matter/src/embedded/Matter_UI.be | 3 +- .../src/embedded/Matter_zz_Device.be | 6 +- .../src/solidify/solidified_Matter_UI.h | 329 +++++++++--------- .../solidify/solidified_Matter_zz_Device.h | 14 +- 4 files changed, 183 insertions(+), 169 deletions(-) diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_UI.be b/lib/libesp32/berry_matter/src/embedded/Matter_UI.be index a8b372f2c..279d47ad3 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_UI.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_UI.be @@ -1012,6 +1012,7 @@ class Matter_UI # Show bridge status ####################################################################### def show_bridge_status() + if (self.device.plugins == nil) return end import webserver var bridge_plugin_by_host @@ -1063,7 +1064,7 @@ class Matter_UI if self.matter_enabled() # mtc0 = close, mtc1 = open commissioning - var fabrics_count = self.device.sessions.count_active_fabrics() + var fabrics_count = (self.device.sessions != nil) ? self.device.sessions.count_active_fabrics() : 0 if fabrics_count == 0 webserver.content_send(format("
%s
", "Matter: No active association")) else diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be b/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be index 3a6289f22..2459771a4 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be @@ -785,7 +785,7 @@ class Matter_Device self.next_ep = j.find("nextep", self.next_ep) self.plugins_config = j.find("config") if self.plugins_config != nil - tasmota.log("MTR: load_config = " + str(self.plugins_config), 3) + tasmota.log(f"MTR: Load_config = {self.plugins_config}", 3) self.adjust_next_ep() dirty = self.check_config_ep() self.plugins_persist = true @@ -796,7 +796,7 @@ class Matter_Device end except .. as e, m if e != "io_error" - tasmota.log("MTR: Session_Store::load Exception:" + str(e) + "|" + str(m), 2) + tasmota.log("MTR: load_param Exception:" + str(e) + "|" + str(m), 2) end end @@ -1408,7 +1408,7 @@ class Matter_Device # copy into list so we can change the map on the fly var dirty = false var keys = [] - for k: self.plugins_config.keys() k.push(int(k)) end + for k: self.plugins_config.keys() keys.push(int(k)) end for ep: keys if ep == 0 tasmota.log("MTR: invalid entry with ep '0'", 2) diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_UI.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_UI.h index 58097a058..8618007f7 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_UI.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_UI.h @@ -456,49 +456,56 @@ be_local_closure(Matter_UI_web_sensor, /* name */ }), be_str_weak(web_sensor), &be_const_str_solidified, - ( &(const binstruction[42]) { /* code */ + ( &(const binstruction[49]) { /* code */ 0xA4060000, // 0000 IMPORT R1 K0 0x8C080101, // 0001 GETMET R2 R0 K1 0x7C080200, // 0002 CALL R2 1 - 0x780A0024, // 0003 JMPF R2 #0029 + 0x780A002B, // 0003 JMPF R2 #0030 0x88080102, // 0004 GETMBR R2 R0 K2 0x88080503, // 0005 GETMBR R2 R2 K3 - 0x8C080504, // 0006 GETMET R2 R2 K4 - 0x7C080200, // 0007 CALL R2 1 - 0x1C0C0505, // 0008 EQ R3 R2 K5 - 0x780E0006, // 0009 JMPF R3 #0011 - 0x8C0C0306, // 000A GETMET R3 R1 K6 - 0x60140018, // 000B GETGBL R5 G24 - 0x58180007, // 000C LDCONST R6 K7 - 0x581C0008, // 000D LDCONST R7 K8 - 0x7C140400, // 000E CALL R5 2 - 0x7C0C0400, // 000F CALL R3 2 - 0x7002000F, // 0010 JMP #0021 - 0x240C0509, // 0011 GT R3 R2 K9 - 0x8C100306, // 0012 GETMET R4 R1 K6 - 0x60180018, // 0013 GETGBL R6 G24 - 0x581C0007, // 0014 LDCONST R7 K7 - 0x60200008, // 0015 GETGBL R8 G8 - 0x5C240400, // 0016 MOVE R9 R2 - 0x7C200200, // 0017 CALL R8 1 - 0x00221408, // 0018 ADD R8 K10 R8 - 0x0020110B, // 0019 ADD R8 R8 K11 - 0x780E0001, // 001A JMPF R3 #001D - 0x5824000C, // 001B LDCONST R9 K12 - 0x70020000, // 001C JMP #001E - 0x5824000D, // 001D LDCONST R9 K13 - 0x00201009, // 001E ADD R8 R8 R9 - 0x7C180400, // 001F CALL R6 2 - 0x7C100400, // 0020 CALL R4 2 - 0x8C0C010E, // 0021 GETMET R3 R0 K14 - 0x7C0C0200, // 0022 CALL R3 1 - 0x880C0102, // 0023 GETMBR R3 R0 K2 - 0x8C0C070F, // 0024 GETMET R3 R3 K15 - 0x7C0C0200, // 0025 CALL R3 1 - 0x780E0001, // 0026 JMPF R3 #0029 - 0x8C0C0110, // 0027 GETMET R3 R0 K16 - 0x7C0C0200, // 0028 CALL R3 1 - 0x80000000, // 0029 RET 0 + 0x4C0C0000, // 0006 LDNIL R3 + 0x20080403, // 0007 NE R2 R2 R3 + 0x780A0004, // 0008 JMPF R2 #000E + 0x88080102, // 0009 GETMBR R2 R0 K2 + 0x88080503, // 000A GETMBR R2 R2 K3 + 0x8C080504, // 000B GETMET R2 R2 K4 + 0x7C080200, // 000C CALL R2 1 + 0x70020000, // 000D JMP #000F + 0x58080005, // 000E LDCONST R2 K5 + 0x1C0C0505, // 000F EQ R3 R2 K5 + 0x780E0006, // 0010 JMPF R3 #0018 + 0x8C0C0306, // 0011 GETMET R3 R1 K6 + 0x60140018, // 0012 GETGBL R5 G24 + 0x58180007, // 0013 LDCONST R6 K7 + 0x581C0008, // 0014 LDCONST R7 K8 + 0x7C140400, // 0015 CALL R5 2 + 0x7C0C0400, // 0016 CALL R3 2 + 0x7002000F, // 0017 JMP #0028 + 0x240C0509, // 0018 GT R3 R2 K9 + 0x8C100306, // 0019 GETMET R4 R1 K6 + 0x60180018, // 001A GETGBL R6 G24 + 0x581C0007, // 001B LDCONST R7 K7 + 0x60200008, // 001C GETGBL R8 G8 + 0x5C240400, // 001D MOVE R9 R2 + 0x7C200200, // 001E CALL R8 1 + 0x00221408, // 001F ADD R8 K10 R8 + 0x0020110B, // 0020 ADD R8 R8 K11 + 0x780E0001, // 0021 JMPF R3 #0024 + 0x5824000C, // 0022 LDCONST R9 K12 + 0x70020000, // 0023 JMP #0025 + 0x5824000D, // 0024 LDCONST R9 K13 + 0x00201009, // 0025 ADD R8 R8 R9 + 0x7C180400, // 0026 CALL R6 2 + 0x7C100400, // 0027 CALL R4 2 + 0x8C0C010E, // 0028 GETMET R3 R0 K14 + 0x7C0C0200, // 0029 CALL R3 1 + 0x880C0102, // 002A GETMBR R3 R0 K2 + 0x8C0C070F, // 002B GETMET R3 R3 K15 + 0x7C0C0200, // 002C CALL R3 1 + 0x780E0001, // 002D JMPF R3 #0030 + 0x8C0C0110, // 002E GETMET R3 R0 K16 + 0x7C0C0200, // 002F CALL R3 1 + 0x80000000, // 0030 RET 0 }) ) ); @@ -1790,10 +1797,10 @@ be_local_closure(Matter_UI_show_bridge_status, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[27]) { /* constants */ - /* K0 */ be_nested_str_weak(webserver), - /* K1 */ be_const_int(0), - /* K2 */ be_nested_str_weak(device), - /* K3 */ be_nested_str_weak(plugins), + /* K0 */ be_nested_str_weak(device), + /* K1 */ be_nested_str_weak(plugins), + /* K2 */ be_nested_str_weak(webserver), + /* K3 */ be_const_int(0), /* K4 */ be_nested_str_weak(matter), /* K5 */ be_nested_str_weak(Plugin_Bridge_HTTP), /* K6 */ be_nested_str_weak(http_remote), @@ -1820,123 +1827,129 @@ be_local_closure(Matter_UI_show_bridge_status, /* name */ }), be_str_weak(show_bridge_status), &be_const_str_solidified, - ( &(const binstruction[116]) { /* code */ - 0xA4060000, // 0000 IMPORT R1 K0 - 0x4C080000, // 0001 LDNIL R2 - 0x580C0001, // 0002 LDCONST R3 K1 - 0x6010000C, // 0003 GETGBL R4 G12 - 0x88140102, // 0004 GETMBR R5 R0 K2 - 0x88140B03, // 0005 GETMBR R5 R5 K3 - 0x7C100200, // 0006 CALL R4 1 - 0x14100604, // 0007 LT R4 R3 R4 - 0x7812001D, // 0008 JMPF R4 #0027 - 0x88100102, // 0009 GETMBR R4 R0 K2 - 0x88100903, // 000A GETMBR R4 R4 K3 - 0x94100803, // 000B GETIDX R4 R4 R3 - 0x6014000F, // 000C GETGBL R5 G15 - 0x5C180800, // 000D MOVE R6 R4 - 0xB81E0800, // 000E GETNGBL R7 K4 - 0x881C0F05, // 000F GETMBR R7 R7 K5 - 0x7C140400, // 0010 CALL R5 2 - 0x78160012, // 0011 JMPF R5 #0025 - 0x4C140000, // 0012 LDNIL R5 - 0x1C140405, // 0013 EQ R5 R2 R5 - 0x78160002, // 0014 JMPF R5 #0018 - 0x60140013, // 0015 GETGBL R5 G19 - 0x7C140000, // 0016 CALL R5 0 - 0x5C080A00, // 0017 MOVE R2 R5 - 0x88140906, // 0018 GETMBR R5 R4 K6 - 0x88140B07, // 0019 GETMBR R5 R5 K7 - 0x8C180508, // 001A GETMET R6 R2 K8 - 0x5C200A00, // 001B MOVE R8 R5 - 0x7C180400, // 001C CALL R6 2 - 0x741A0002, // 001D JMPT R6 #0021 - 0x60180012, // 001E GETGBL R6 G18 - 0x7C180000, // 001F CALL R6 0 - 0x98080A06, // 0020 SETIDX R2 R5 R6 - 0x94180405, // 0021 GETIDX R6 R2 R5 - 0x8C180D09, // 0022 GETMET R6 R6 K9 - 0x5C200800, // 0023 MOVE R8 R4 - 0x7C180400, // 0024 CALL R6 2 - 0x000C070A, // 0025 ADD R3 R3 K10 - 0x7001FFDB, // 0026 JMP #0003 - 0x4C100000, // 0027 LDNIL R4 - 0x1C100404, // 0028 EQ R4 R2 R4 - 0x78120000, // 0029 JMPF R4 #002B - 0x80000800, // 002A RET 0 - 0x8C10030B, // 002B GETMET R4 R1 K11 - 0x5818000C, // 002C LDCONST R6 K12 - 0x7C100400, // 002D CALL R4 2 - 0x8C10030B, // 002E GETMET R4 R1 K11 - 0x5818000D, // 002F LDCONST R6 K13 - 0x7C100400, // 0030 CALL R4 2 + ( &(const binstruction[122]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x88040301, // 0001 GETMBR R1 R1 K1 + 0x4C080000, // 0002 LDNIL R2 + 0x1C040202, // 0003 EQ R1 R1 R2 + 0x78060000, // 0004 JMPF R1 #0006 + 0x80000200, // 0005 RET 0 + 0xA4060400, // 0006 IMPORT R1 K2 + 0x4C080000, // 0007 LDNIL R2 + 0x580C0003, // 0008 LDCONST R3 K3 + 0x6010000C, // 0009 GETGBL R4 G12 + 0x88140100, // 000A GETMBR R5 R0 K0 + 0x88140B01, // 000B GETMBR R5 R5 K1 + 0x7C100200, // 000C CALL R4 1 + 0x14100604, // 000D LT R4 R3 R4 + 0x7812001D, // 000E JMPF R4 #002D + 0x88100100, // 000F GETMBR R4 R0 K0 + 0x88100901, // 0010 GETMBR R4 R4 K1 + 0x94100803, // 0011 GETIDX R4 R4 R3 + 0x6014000F, // 0012 GETGBL R5 G15 + 0x5C180800, // 0013 MOVE R6 R4 + 0xB81E0800, // 0014 GETNGBL R7 K4 + 0x881C0F05, // 0015 GETMBR R7 R7 K5 + 0x7C140400, // 0016 CALL R5 2 + 0x78160012, // 0017 JMPF R5 #002B + 0x4C140000, // 0018 LDNIL R5 + 0x1C140405, // 0019 EQ R5 R2 R5 + 0x78160002, // 001A JMPF R5 #001E + 0x60140013, // 001B GETGBL R5 G19 + 0x7C140000, // 001C CALL R5 0 + 0x5C080A00, // 001D MOVE R2 R5 + 0x88140906, // 001E GETMBR R5 R4 K6 + 0x88140B07, // 001F GETMBR R5 R5 K7 + 0x8C180508, // 0020 GETMET R6 R2 K8 + 0x5C200A00, // 0021 MOVE R8 R5 + 0x7C180400, // 0022 CALL R6 2 + 0x741A0002, // 0023 JMPT R6 #0027 + 0x60180012, // 0024 GETGBL R6 G18 + 0x7C180000, // 0025 CALL R6 0 + 0x98080A06, // 0026 SETIDX R2 R5 R6 + 0x94180405, // 0027 GETIDX R6 R2 R5 + 0x8C180D09, // 0028 GETMET R6 R6 K9 + 0x5C200800, // 0029 MOVE R8 R4 + 0x7C180400, // 002A CALL R6 2 + 0x000C070A, // 002B ADD R3 R3 K10 + 0x7001FFDB, // 002C JMP #0009 + 0x4C100000, // 002D LDNIL R4 + 0x1C100404, // 002E EQ R4 R2 R4 + 0x78120000, // 002F JMPF R4 #0031 + 0x80000800, // 0030 RET 0 0x8C10030B, // 0031 GETMET R4 R1 K11 - 0xB81A0800, // 0032 GETNGBL R6 K4 - 0x88180D0E, // 0033 GETMBR R6 R6 K14 - 0x7C100400, // 0034 CALL R4 2 - 0x60100010, // 0035 GETGBL R4 G16 - 0x88140102, // 0036 GETMBR R5 R0 K2 - 0x8C140B0F, // 0037 GETMET R5 R5 K15 - 0x5C1C0400, // 0038 MOVE R7 R2 - 0x7C140400, // 0039 CALL R5 2 - 0x7C100200, // 003A CALL R4 1 - 0xA8020030, // 003B EXBLK 0 #006D - 0x5C140800, // 003C MOVE R5 R4 - 0x7C140000, // 003D CALL R5 0 - 0x8C180310, // 003E GETMET R6 R1 K16 - 0x5C200A00, // 003F MOVE R8 R5 - 0x7C180400, // 0040 CALL R6 2 - 0x8C1C0310, // 0041 GETMET R7 R1 K16 - 0x88240102, // 0042 GETMBR R9 R0 K2 - 0x8C241311, // 0043 GETMET R9 R9 K17 - 0x5C2C0A00, // 0044 MOVE R11 R5 - 0x7C240400, // 0045 CALL R9 2 - 0x8C241312, // 0046 GETMET R9 R9 K18 - 0x582C0013, // 0047 LDCONST R11 K19 - 0x5C300A00, // 0048 MOVE R12 R5 - 0x7C240600, // 0049 CALL R9 3 - 0x7C1C0400, // 004A CALL R7 2 - 0x8C20030B, // 004B GETMET R8 R1 K11 - 0x60280018, // 004C GETGBL R10 G24 - 0x582C0014, // 004D LDCONST R11 K20 - 0x5C300C00, // 004E MOVE R12 R6 - 0x5C340C00, // 004F MOVE R13 R6 - 0x5C380E00, // 0050 MOVE R14 R7 - 0x7C280800, // 0051 CALL R10 4 - 0x7C200400, // 0052 CALL R8 2 - 0x94200405, // 0053 GETIDX R8 R2 R5 - 0x94201101, // 0054 GETIDX R8 R8 K1 - 0x88201106, // 0055 GETMBR R8 R8 K6 - 0x8C24030B, // 0056 GETMET R9 R1 K11 - 0x8C2C1115, // 0057 GETMET R11 R8 K21 - 0x7C2C0200, // 0058 CALL R11 1 - 0x7C240400, // 0059 CALL R9 2 - 0x60240010, // 005A GETGBL R9 G16 - 0x94280405, // 005B GETIDX R10 R2 R5 - 0x7C240200, // 005C CALL R9 1 - 0xA802000A, // 005D EXBLK 0 #0069 - 0x5C281200, // 005E MOVE R10 R9 - 0x7C280000, // 005F CALL R10 0 - 0x8C2C030B, // 0060 GETMET R11 R1 K11 - 0x58340016, // 0061 LDCONST R13 K22 - 0x7C2C0400, // 0062 CALL R11 2 - 0x8C2C1517, // 0063 GETMET R11 R10 K23 - 0x7C2C0200, // 0064 CALL R11 1 - 0x8C2C030B, // 0065 GETMET R11 R1 K11 - 0x58340018, // 0066 LDCONST R13 K24 - 0x7C2C0400, // 0067 CALL R11 2 - 0x7001FFF4, // 0068 JMP #005E - 0x58240019, // 0069 LDCONST R9 K25 - 0xAC240200, // 006A CATCH R9 1 0 - 0xB0080000, // 006B RAISE 2 R0 R0 - 0x7001FFCE, // 006C JMP #003C - 0x58100019, // 006D LDCONST R4 K25 - 0xAC100200, // 006E CATCH R4 1 0 - 0xB0080000, // 006F RAISE 2 R0 R0 - 0x8C10030B, // 0070 GETMET R4 R1 K11 - 0x5818001A, // 0071 LDCONST R6 K26 - 0x7C100400, // 0072 CALL R4 2 - 0x80000000, // 0073 RET 0 + 0x5818000C, // 0032 LDCONST R6 K12 + 0x7C100400, // 0033 CALL R4 2 + 0x8C10030B, // 0034 GETMET R4 R1 K11 + 0x5818000D, // 0035 LDCONST R6 K13 + 0x7C100400, // 0036 CALL R4 2 + 0x8C10030B, // 0037 GETMET R4 R1 K11 + 0xB81A0800, // 0038 GETNGBL R6 K4 + 0x88180D0E, // 0039 GETMBR R6 R6 K14 + 0x7C100400, // 003A CALL R4 2 + 0x60100010, // 003B GETGBL R4 G16 + 0x88140100, // 003C GETMBR R5 R0 K0 + 0x8C140B0F, // 003D GETMET R5 R5 K15 + 0x5C1C0400, // 003E MOVE R7 R2 + 0x7C140400, // 003F CALL R5 2 + 0x7C100200, // 0040 CALL R4 1 + 0xA8020030, // 0041 EXBLK 0 #0073 + 0x5C140800, // 0042 MOVE R5 R4 + 0x7C140000, // 0043 CALL R5 0 + 0x8C180310, // 0044 GETMET R6 R1 K16 + 0x5C200A00, // 0045 MOVE R8 R5 + 0x7C180400, // 0046 CALL R6 2 + 0x8C1C0310, // 0047 GETMET R7 R1 K16 + 0x88240100, // 0048 GETMBR R9 R0 K0 + 0x8C241311, // 0049 GETMET R9 R9 K17 + 0x5C2C0A00, // 004A MOVE R11 R5 + 0x7C240400, // 004B CALL R9 2 + 0x8C241312, // 004C GETMET R9 R9 K18 + 0x582C0013, // 004D LDCONST R11 K19 + 0x5C300A00, // 004E MOVE R12 R5 + 0x7C240600, // 004F CALL R9 3 + 0x7C1C0400, // 0050 CALL R7 2 + 0x8C20030B, // 0051 GETMET R8 R1 K11 + 0x60280018, // 0052 GETGBL R10 G24 + 0x582C0014, // 0053 LDCONST R11 K20 + 0x5C300C00, // 0054 MOVE R12 R6 + 0x5C340C00, // 0055 MOVE R13 R6 + 0x5C380E00, // 0056 MOVE R14 R7 + 0x7C280800, // 0057 CALL R10 4 + 0x7C200400, // 0058 CALL R8 2 + 0x94200405, // 0059 GETIDX R8 R2 R5 + 0x94201103, // 005A GETIDX R8 R8 K3 + 0x88201106, // 005B GETMBR R8 R8 K6 + 0x8C24030B, // 005C GETMET R9 R1 K11 + 0x8C2C1115, // 005D GETMET R11 R8 K21 + 0x7C2C0200, // 005E CALL R11 1 + 0x7C240400, // 005F CALL R9 2 + 0x60240010, // 0060 GETGBL R9 G16 + 0x94280405, // 0061 GETIDX R10 R2 R5 + 0x7C240200, // 0062 CALL R9 1 + 0xA802000A, // 0063 EXBLK 0 #006F + 0x5C281200, // 0064 MOVE R10 R9 + 0x7C280000, // 0065 CALL R10 0 + 0x8C2C030B, // 0066 GETMET R11 R1 K11 + 0x58340016, // 0067 LDCONST R13 K22 + 0x7C2C0400, // 0068 CALL R11 2 + 0x8C2C1517, // 0069 GETMET R11 R10 K23 + 0x7C2C0200, // 006A CALL R11 1 + 0x8C2C030B, // 006B GETMET R11 R1 K11 + 0x58340018, // 006C LDCONST R13 K24 + 0x7C2C0400, // 006D CALL R11 2 + 0x7001FFF4, // 006E JMP #0064 + 0x58240019, // 006F LDCONST R9 K25 + 0xAC240200, // 0070 CATCH R9 1 0 + 0xB0080000, // 0071 RAISE 2 R0 R0 + 0x7001FFCE, // 0072 JMP #0042 + 0x58100019, // 0073 LDCONST R4 K25 + 0xAC100200, // 0074 CATCH R4 1 0 + 0xB0080000, // 0075 RAISE 2 R0 R0 + 0x8C10030B, // 0076 GETMET R4 R1 K11 + 0x5818001A, // 0077 LDCONST R6 K26 + 0x7C100400, // 0078 CALL R4 2 + 0x80000000, // 0079 RET 0 }) ) ); diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h index 29afc6f0a..cc928bf8e 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h @@ -3899,7 +3899,7 @@ be_local_closure(Matter_Device_check_config_ep, /* name */ 0xA8020007, // 0008 EXBLK 0 #0011 0x5C100600, // 0009 MOVE R4 R3 0x7C100000, // 000A CALL R4 0 - 0x8C140902, // 000B GETMET R5 R4 K2 + 0x8C140502, // 000B GETMET R5 R2 K2 0x601C0009, // 000C GETGBL R7 G9 0x5C200800, // 000D MOVE R8 R4 0x7C1C0200, // 000E CALL R7 1 @@ -4447,7 +4447,7 @@ be_local_closure(Matter_Device_load_param, /* name */ /* K16 */ be_nested_str_weak(config), /* K17 */ be_nested_str_weak(tasmota), /* K18 */ be_nested_str_weak(log), - /* K19 */ be_nested_str_weak(MTR_X3A_X20load_config_X20_X3D_X20), + /* K19 */ be_nested_str_weak(MTR_X3A_X20Load_config_X20_X3D_X20_X25s), /* K20 */ be_const_int(3), /* K21 */ be_nested_str_weak(adjust_next_ep), /* K22 */ be_nested_str_weak(check_config_ep), @@ -4456,7 +4456,7 @@ be_local_closure(Matter_Device_load_param, /* name */ /* K25 */ be_nested_str_weak(remotes), /* K26 */ be_nested_str_weak(MTR_X3A_X20load_remotes_X20_X3D_X20), /* K27 */ be_nested_str_weak(io_error), - /* K28 */ be_nested_str_weak(MTR_X3A_X20Session_Store_X3A_X3Aload_X20Exception_X3A), + /* K28 */ be_nested_str_weak(MTR_X3A_X20load_param_X20Exception_X3A), /* K29 */ be_nested_str_weak(_X7C), /* K30 */ be_const_int(2), /* K31 */ be_nested_str_weak(random), @@ -4521,10 +4521,10 @@ be_local_closure(Matter_Device_load_param, /* name */ 0x781E000E, // 0032 JMPF R7 #0042 0xB81E2200, // 0033 GETNGBL R7 K17 0x8C1C0F12, // 0034 GETMET R7 R7 K18 - 0x60240008, // 0035 GETGBL R9 G8 - 0x8828010F, // 0036 GETMBR R10 R0 K15 - 0x7C240200, // 0037 CALL R9 1 - 0x00262609, // 0038 ADD R9 K19 R9 + 0x60240018, // 0035 GETGBL R9 G24 + 0x58280013, // 0036 LDCONST R10 K19 + 0x882C010F, // 0037 GETMBR R11 R0 K15 + 0x7C240400, // 0038 CALL R9 2 0x58280014, // 0039 LDCONST R10 K20 0x7C1C0600, // 003A CALL R7 3 0x8C1C0115, // 003B GETMET R7 R0 K21 From 0bc6f82a8157f80d8eac9b0cc6718ccffc506033 Mon Sep 17 00:00:00 2001 From: Christian Baars Date: Wed, 7 Feb 2024 10:30:30 +0100 Subject: [PATCH 277/303] MI32 legacy: use disconnect reason as error code (#20676) --- tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino index 1ee386063..1dfa9d217 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino @@ -95,11 +95,12 @@ class MI32SensorCallback : public NimBLEClientCallbacks { MI32.mode.connected = 1; pclient->updateConnParams(8,11,0,1000); } - void onDisconnect(NimBLEClient* pclient) { + void onDisconnect(NimBLEClient* pclient, int reason) { MI32.mode.connected = 0; MI32.infoMsg = MI32_DID_DISCONNECT; - MI32.conCtx->error = MI32_CONN_DID_DISCCONNECT; - MI32.mode.triggerBerryConnCB = 1; //mainly for unexpected or requested disconnects + MI32.conCtx->error = reason; + MI32.conCtx->operation = 5; //set for all disconnects that come from the remote device or connection loss + MI32.mode.triggerBerryConnCB = 1; //AddLog(LOG_LEVEL_DEBUG,PSTR("disconnected")); } }; @@ -2738,4 +2739,4 @@ bool Xsns62(uint32_t function) #endif // USE_MI_ESP32 #endif // CONFIG_IDF_TARGET_ESP32 or CONFIG_IDF_TARGET_ESP32C3 #endif // ESP32 -#endif // USE_BLE_ESP32 \ No newline at end of file +#endif // USE_BLE_ESP32 From 9471a29ad9e5c319fac6d2f593aa29a9f4497ddc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 7 Feb 2024 13:10:26 +0100 Subject: [PATCH 278/303] Add support for JSON settings file --- .../xdrv_50_filesystem.ino | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino b/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino index df3dd7260..3f627b4d7 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino @@ -538,6 +538,179 @@ bool UfsExecuteCommandFile(const char *fname) { return false; } +/*********************************************************************************************\ + * File JSON settings support + * + * {"UserSet1":{"Param1":123,"Param2":"Text1"},"UserSet2":{"Param1":123,"Param2":"Text2"},"UserSet3":{"Param1":123,"Param2":"Text3"}} +\*********************************************************************************************/ + +bool UfsJsonSettingsWrite(const char* data) { + // Add new UserSet replacing present UserSet + // Input {"UserSet2":{"Param1":123,"Param2":"Text2"}} + + if (!TfsFileExists(TASM_FILE_JSON_SETTINGS)) { + File ofile = ffsp->open(TASM_FILE_JSON_SETTINGS, "w"); + if (!ofile) { return false; } + + ofile.write((uint8_t*)data, strlen(data)); + ofile.close(); + return true; + } + + char bfname[16]; + strcpy_P(bfname, PSTR("/gtmp.json")); + File ofile = ffsp->open(bfname, "w"); + if (!ofile) { return false; } + File ifile = ffsp->open(TASM_FILE_JSON_SETTINGS, "r"); + if (!ifile) { + ofile.close(); + ffsp->remove(bfname); + return false; + } + + char *p = strchr(data, '"'); + if (!p) { return false; } + char *q = strchr(++p, '"'); + if (!q) { return false; } + uint32_t len = (uint32_t)q - (uint32_t)p; + char key[len +1]; + memcpy(key, p, len); + key[len] = '\0'; // key = UserSet2 + + char buffer[32]; // Max key length + uint8_t buf[1]; + uint32_t index = 0; + uint32_t bracket_count = 0; + int entries = 0; + bool quote = false; + bool mine = false; + while (ifile.available()) { // Process file + ifile.read(buf, 1); + if (bracket_count > 1) { // Copy or skip old data + if (!mine) { + ofile.write(buf, 1); // Copy data + } + if (buf[0] == '}') { + bracket_count--; + } + } else { + if (buf[0] == '}') { // Last bracket + break; // End of file + } + else if (buf[0] == '{') { + bracket_count++; + if (bracket_count > 1) { // Skip first bracket + entries++; + } + } + else if (buf[0] == '"') { + quote ^= 1; + if (quote) { + index = 0; + } else { + buffer[index] = '\0'; // End of key name + mine = (!strcasecmp(buffer, key)); + if (mine) { + entries--; // Skip old data + } else { + ofile.write((entries) ? (uint8_t*)",\"" : (uint8_t*)"{\"", 2); + ofile.write((uint8_t*)buffer, strlen(buffer)); + ofile.write((uint8_t*)"\":{", 3); + } + } + } + else { + buffer[index++] = buf[0]; // Add key name + if (index > sizeof(buffer) -2) { + break; // Key name too long + } + } + } + } + ifile.close(); + // Append new data + ofile.write((entries) ? (uint8_t*)"," : (uint8_t*)"{", 1); + ofile.write((uint8_t*)data +1, strlen(data) -1); + ofile.close(); + if (index > sizeof(buffer) -2) { return false; } + ffsp->remove(TASM_FILE_JSON_SETTINGS); + ffsp->rename(bfname, TASM_FILE_JSON_SETTINGS); + return true; +} + +String UfsJsonSettingsRead(const char* key) { + // Input "UserSet2" + // Returns {"Param1":123,"Param2":"Text2"} + + String data = ""; + if (!TfsFileExists(TASM_FILE_JSON_SETTINGS)) { return data; } + File file = ffsp->open(TASM_FILE_JSON_SETTINGS, "r"); + if (!file) { return data; } + + Trim((char*)key); + char buffer[128]; + uint8_t buf[1] = { 0 }; + uint32_t index = 0; + uint32_t bracket_count = 0; + bool quote = false; + bool mine = false; + while (file.available()) { // Process file + file.read(buf, 1); + if (bracket_count > 1) { // Build JSON + if (mine) { + buffer[index++] = buf[0]; // Add key data + if (index > sizeof(buffer) -2) { + buffer[index] = '\0'; + data += buffer; // Add buffer to result + index = 0; + } + } + if (buf[0] == '}') { + bracket_count--; + if (1 == bracket_count) { + if (mine) { + break; // End of key data + } else { + index = 0; // End of data which is not mine + } + } + } + } else { + if (buf[0] == '}') { // Last bracket + index = 0; + break; // End of file - key not found + } + else if (buf[0] == '{') { + bracket_count++; + if (bracket_count > 1) { // Skip first bracket + index = 0; + buffer[index++] = buf[0]; // Start of key data + } + } + else if (buf[0] == '"') { + quote ^= 1; + if (quote) { + index = 0; + } else { + buffer[index] = '\0'; // End of key name + mine = (!strcasecmp(buffer, key)); + } + } + else { + buffer[index++] = buf[0]; // Add key name + if (index > sizeof(buffer) -2) { + index = 0; + break; // Key name too long + } + } + } + } + file.close(); + buffer[index] = '\0'; + data += buffer; + return data; +} + /*********************************************************************************************\ * Commands \*********************************************************************************************/ From b31ff75f3c61372e19f8c9681bbed7fa9bad0793 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 7 Feb 2024 14:25:38 +0100 Subject: [PATCH 279/303] Revert "Add support for JSON settings file" This reverts commit 9471a29ad9e5c319fac6d2f593aa29a9f4497ddc. --- .../xdrv_50_filesystem.ino | 173 ------------------ 1 file changed, 173 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino b/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino index 3f627b4d7..df3dd7260 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino @@ -538,179 +538,6 @@ bool UfsExecuteCommandFile(const char *fname) { return false; } -/*********************************************************************************************\ - * File JSON settings support - * - * {"UserSet1":{"Param1":123,"Param2":"Text1"},"UserSet2":{"Param1":123,"Param2":"Text2"},"UserSet3":{"Param1":123,"Param2":"Text3"}} -\*********************************************************************************************/ - -bool UfsJsonSettingsWrite(const char* data) { - // Add new UserSet replacing present UserSet - // Input {"UserSet2":{"Param1":123,"Param2":"Text2"}} - - if (!TfsFileExists(TASM_FILE_JSON_SETTINGS)) { - File ofile = ffsp->open(TASM_FILE_JSON_SETTINGS, "w"); - if (!ofile) { return false; } - - ofile.write((uint8_t*)data, strlen(data)); - ofile.close(); - return true; - } - - char bfname[16]; - strcpy_P(bfname, PSTR("/gtmp.json")); - File ofile = ffsp->open(bfname, "w"); - if (!ofile) { return false; } - File ifile = ffsp->open(TASM_FILE_JSON_SETTINGS, "r"); - if (!ifile) { - ofile.close(); - ffsp->remove(bfname); - return false; - } - - char *p = strchr(data, '"'); - if (!p) { return false; } - char *q = strchr(++p, '"'); - if (!q) { return false; } - uint32_t len = (uint32_t)q - (uint32_t)p; - char key[len +1]; - memcpy(key, p, len); - key[len] = '\0'; // key = UserSet2 - - char buffer[32]; // Max key length - uint8_t buf[1]; - uint32_t index = 0; - uint32_t bracket_count = 0; - int entries = 0; - bool quote = false; - bool mine = false; - while (ifile.available()) { // Process file - ifile.read(buf, 1); - if (bracket_count > 1) { // Copy or skip old data - if (!mine) { - ofile.write(buf, 1); // Copy data - } - if (buf[0] == '}') { - bracket_count--; - } - } else { - if (buf[0] == '}') { // Last bracket - break; // End of file - } - else if (buf[0] == '{') { - bracket_count++; - if (bracket_count > 1) { // Skip first bracket - entries++; - } - } - else if (buf[0] == '"') { - quote ^= 1; - if (quote) { - index = 0; - } else { - buffer[index] = '\0'; // End of key name - mine = (!strcasecmp(buffer, key)); - if (mine) { - entries--; // Skip old data - } else { - ofile.write((entries) ? (uint8_t*)",\"" : (uint8_t*)"{\"", 2); - ofile.write((uint8_t*)buffer, strlen(buffer)); - ofile.write((uint8_t*)"\":{", 3); - } - } - } - else { - buffer[index++] = buf[0]; // Add key name - if (index > sizeof(buffer) -2) { - break; // Key name too long - } - } - } - } - ifile.close(); - // Append new data - ofile.write((entries) ? (uint8_t*)"," : (uint8_t*)"{", 1); - ofile.write((uint8_t*)data +1, strlen(data) -1); - ofile.close(); - if (index > sizeof(buffer) -2) { return false; } - ffsp->remove(TASM_FILE_JSON_SETTINGS); - ffsp->rename(bfname, TASM_FILE_JSON_SETTINGS); - return true; -} - -String UfsJsonSettingsRead(const char* key) { - // Input "UserSet2" - // Returns {"Param1":123,"Param2":"Text2"} - - String data = ""; - if (!TfsFileExists(TASM_FILE_JSON_SETTINGS)) { return data; } - File file = ffsp->open(TASM_FILE_JSON_SETTINGS, "r"); - if (!file) { return data; } - - Trim((char*)key); - char buffer[128]; - uint8_t buf[1] = { 0 }; - uint32_t index = 0; - uint32_t bracket_count = 0; - bool quote = false; - bool mine = false; - while (file.available()) { // Process file - file.read(buf, 1); - if (bracket_count > 1) { // Build JSON - if (mine) { - buffer[index++] = buf[0]; // Add key data - if (index > sizeof(buffer) -2) { - buffer[index] = '\0'; - data += buffer; // Add buffer to result - index = 0; - } - } - if (buf[0] == '}') { - bracket_count--; - if (1 == bracket_count) { - if (mine) { - break; // End of key data - } else { - index = 0; // End of data which is not mine - } - } - } - } else { - if (buf[0] == '}') { // Last bracket - index = 0; - break; // End of file - key not found - } - else if (buf[0] == '{') { - bracket_count++; - if (bracket_count > 1) { // Skip first bracket - index = 0; - buffer[index++] = buf[0]; // Start of key data - } - } - else if (buf[0] == '"') { - quote ^= 1; - if (quote) { - index = 0; - } else { - buffer[index] = '\0'; // End of key name - mine = (!strcasecmp(buffer, key)); - } - } - else { - buffer[index++] = buf[0]; // Add key name - if (index > sizeof(buffer) -2) { - index = 0; - break; // Key name too long - } - } - } - } - file.close(); - buffer[index] = '\0'; - data += buffer; - return data; -} - /*********************************************************************************************\ * Commands \*********************************************************************************************/ From ab8676d865e3d9f323819643199d819e594dabf8 Mon Sep 17 00:00:00 2001 From: Fulvio Spelta Date: Wed, 7 Feb 2024 15:57:09 +0100 Subject: [PATCH 280/303] SetOption158 publish/suppress ModbusReceived MQTT messages (#20678) --- tasmota/include/tasmota_globals.h | 3 +++ tasmota/include/tasmota_types.h | 2 +- tasmota/my_user_config.h | 1 + tasmota/tasmota_support/settings.ino | 1 + .../xdrv_63_modbus_bridge.ino | 18 +++++++++++++++--- 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/tasmota/include/tasmota_globals.h b/tasmota/include/tasmota_globals.h index 3fe15e195..7a7492877 100644 --- a/tasmota/include/tasmota_globals.h +++ b/tasmota/include/tasmota_globals.h @@ -314,6 +314,9 @@ String EthernetMacAddress(void); #ifndef MQTT_LWT_ONLINE #define MQTT_LWT_ONLINE "Online" // MQTT LWT online topic message #endif +#ifndef MQTT_DISABLE_MODBUSRECEIVED +#define MQTT_DISABLE_MODBUSRECEIVED 0 // 1 = Disable ModbusReceived mqtt messages, 0 = Enable ModbusReceived mqtt messages (default) +#endif #ifndef MESSZ #define MESSZ 1040 // Max number of characters in JSON message string (Hass discovery and nice MQTT_MAX_PACKET_SIZE = 1200) diff --git a/tasmota/include/tasmota_types.h b/tasmota/include/tasmota_types.h index b2df33857..6df44ec1c 100755 --- a/tasmota/include/tasmota_types.h +++ b/tasmota/include/tasmota_types.h @@ -191,7 +191,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t zcfallingedge : 1; // bit 9 (v13.0.0.1) - SetOption155 - (ZCDimmer) Enable rare falling Edge dimmer instead of leading edge uint32_t sen5x_passive_mode : 1; // bit 10 (v13.1.0.1) - SetOption156 - (Sen5x) Run in passive mode when there is another I2C master (e.g. Ikea Vindstyrka), i.e. do not set up Sen5x sensor, higher polling interval uint32_t neopool_outputsensitive : 1; // bit 11 (v13.2.0.1) - SetOption157 - (NeoPool) Output sensitive data (1) - uint32_t spare12 : 1; // bit 12 + uint32_t mqtt_disable_modbus : 1; // bit 12 (v13.2.0.1) - SetOption158 - (MQTT) Disable publish ModbusReceived MQTT messages, you must use event trigger rules instead. uint32_t spare13 : 1; // bit 13 uint32_t spare14 : 1; // bit 14 uint32_t spare15 : 1; // bit 15 diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 530a4199c..45fca83a1 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -418,6 +418,7 @@ #define MQTT_TELE_RETAIN 0 // Tele messages may send retain flag (0 = off, 1 = on) #define MQTT_CLEAN_SESSION 1 // Mqtt clean session connection (0 = No clean session, 1 = Clean session (default)) #define MQTT_DISABLE_SSERIALRECEIVED 0 // 1 = Disable sserialreceived mqtt messages, 0 = Enable sserialreceived mqtt messages (default) +#define MQTT_DISABLE_MODBUSRECEIVED 0 // 1 = Disable ModbusReceived mqtt messages, 0 = Enable ModbusReceived mqtt messages (default) // -- MQTT - Domoticz ----------------------------- #define USE_DOMOTICZ // Enable Domoticz (+6k code, +0.3k mem) diff --git a/tasmota/tasmota_support/settings.ino b/tasmota/tasmota_support/settings.ino index 987192320..cd31f2ee3 100644 --- a/tasmota/tasmota_support/settings.ino +++ b/tasmota/tasmota_support/settings.ino @@ -1121,6 +1121,7 @@ void SettingsDefaultSet2(void) { flag5.mqtt_persistent |= ~MQTT_CLEAN_SESSION; flag6.mqtt_disable_sserialrec |= MQTT_DISABLE_SSERIALRECEIVED; // flag.mqtt_serial |= 0; + flag6.mqtt_disable_modbus |= MQTT_DISABLE_MODBUSRECEIVED; flag.device_index_enable |= MQTT_POWER_FORMAT; flag3.time_append_timezone |= MQTT_APPEND_TIMEZONE; flag3.button_switch_force_local |= MQTT_BUTTON_SWITCH_FORCE_LOCAL; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino index ed82cd0ff..bc3f78bbf 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_63_modbus_bridge.ino @@ -380,7 +380,11 @@ void ModbusBridgeHandle(void) } ResponseAppend_P(PSTR("]}")); ResponseJsonEnd(); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_MODBUS_RECEIVED)); + if (Settings->flag6.mqtt_disable_modbus ) { // SetOption158 If it is activated, Tasmota will not publish ModbusReceived MQTT messages, but it will proccess event trigger rules + XdrvRulesProcess(0); + } else { + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_MODBUS_RECEIVED)); + } } else if (modbusBridge.type == ModbusBridgeType::mb_hex) { @@ -394,7 +398,11 @@ void ModbusBridgeHandle(void) } ResponseAppend_P(PSTR("]}")); ResponseJsonEnd(); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_MODBUS_RECEIVED)); + if (Settings->flag6.mqtt_disable_modbus ) { // SetOption158 If it is activated, Tasmota will not publish ModbusReceived MQTT messages, but it will proccess event trigger rules + XdrvRulesProcess(0); + } else { + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_MODBUS_RECEIVED)); + } } else if ((modbusBridge.buffer[1] > 0) && (modbusBridge.buffer[1] < 7)) { @@ -556,7 +564,11 @@ void ModbusBridgeHandle(void) ResponseAppend_P(PSTR("}")); ResponseJsonEnd(); if (errorcode == ModbusBridgeError::noerror) - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_MODBUS_RECEIVED)); + if (Settings->flag6.mqtt_disable_modbus ) { // SetOption158 If it is activated, Tasmota will not publish ModbusReceived MQTT messages, but it will proccess event trigger rules + XdrvRulesProcess(0); + } else { + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_MODBUS_RECEIVED)); + } } else errorcode = ModbusBridgeError::wrongfunctioncode; From 4fb9e10fcf697370697a6e2a01cd693b63d3cde0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 7 Feb 2024 16:17:11 +0100 Subject: [PATCH 281/303] Add SO158 --- tasmota/include/tasmota_types.h | 2 +- tools/decode-status.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tasmota/include/tasmota_types.h b/tasmota/include/tasmota_types.h index 6df44ec1c..1a37f6033 100755 --- a/tasmota/include/tasmota_types.h +++ b/tasmota/include/tasmota_types.h @@ -191,7 +191,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t zcfallingedge : 1; // bit 9 (v13.0.0.1) - SetOption155 - (ZCDimmer) Enable rare falling Edge dimmer instead of leading edge uint32_t sen5x_passive_mode : 1; // bit 10 (v13.1.0.1) - SetOption156 - (Sen5x) Run in passive mode when there is another I2C master (e.g. Ikea Vindstyrka), i.e. do not set up Sen5x sensor, higher polling interval uint32_t neopool_outputsensitive : 1; // bit 11 (v13.2.0.1) - SetOption157 - (NeoPool) Output sensitive data (1) - uint32_t mqtt_disable_modbus : 1; // bit 12 (v13.2.0.1) - SetOption158 - (MQTT) Disable publish ModbusReceived MQTT messages, you must use event trigger rules instead. + uint32_t mqtt_disable_modbus : 1; // bit 12 (v13.3.0.5) - SetOption158 - (MQTT) Disable publish ModbusReceived MQTT messages, you must use event trigger rules instead uint32_t spare13 : 1; // bit 13 uint32_t spare14 : 1; // bit 14 uint32_t spare15 : 1; // bit 15 diff --git a/tools/decode-status.py b/tools/decode-status.py index 922472118..c6de2333d 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -213,7 +213,8 @@ a_setoption = [[ "(ZCDimmer) Enable rare falling Edge dimmer instead of leading edge", "(Sen5x) Run in passive mode when there is another I2C master (e.g. Ikea Vindstyrka), i.e. do not set up Sen5x sensor, higher polling interval", "(NeoPool) Output sensitive data (1)", - "","","","", + "(MQTT) Disable publish ModbusReceived MQTT messages, you must use event trigger rules instead", + "","","", "","","","", "","","","", "","","","", @@ -337,7 +338,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v13.3.0.2 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v13.3.0.5 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj)) From 715914bdd0e9f3cd312ed61e2ab7f5a1fd33b9d8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 7 Feb 2024 22:55:39 +0100 Subject: [PATCH 282/303] Add internal support for persistent JSON settings using single file --- CHANGELOG.md | 1 + tasmota/tasmota_support/settings.ino | 17 +- .../xdrv_122_file_json_settings_demo.ino | 230 ++++++++++++++++++ .../xdrv_122_file_settings_demo.ino | 4 +- .../xdrv_50_filesystem.ino | 219 +++++++++++++++++ 5 files changed, 462 insertions(+), 9 deletions(-) create mode 100644 tasmota/tasmota_xdrv_driver/xdrv_122_file_json_settings_demo.ino diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ada7fc65..348be9510 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. ## [13.3.0.5] ### Added +- Internal support for persistent JSON settings using single file ### Breaking Changed - ESP32 LVGL library from v8.3.11 to v9.0.0, some small breaking changes in C, none in HASPmota (#20659) diff --git a/tasmota/tasmota_support/settings.ino b/tasmota/tasmota_support/settings.ino index cd31f2ee3..1ee96f41b 100644 --- a/tasmota/tasmota_support/settings.ino +++ b/tasmota/tasmota_support/settings.ino @@ -420,7 +420,7 @@ bool SettingsBufferAlloc(uint32_t upload_size) { } else { char filename[14]; for (uint32_t i = 0; i < 129; i++) { - snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_DRIVER), i); + snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_DRIVER), i); // /.drvset012 uint32_t fsize = TfsFileSize(filename); if (fsize) { if (settings_size == sizeof(TSettings)) { @@ -466,7 +466,7 @@ uint32_t SettingsConfigBackup(void) { filebuf_ptr += sizeof(TSettings); char filename[14]; for (uint32_t i = 0; i < 129; i++) { - snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_DRIVER), i); // /.drvset012 + snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_DRIVER), i); // /.drvset012 uint32_t fsize = TfsFileSize(filename); if (fsize) { // Add tar header with file size @@ -474,7 +474,7 @@ uint32_t SettingsConfigBackup(void) { filebuf_ptr[14] = fsize; filebuf_ptr[15] = fsize >> 8; filebuf_ptr += 16; - if (XdrvCallDriver(i, FUNC_RESTORE_SETTINGS)) { // Enabled driver + if (i && (XdrvCallDriver(i, FUNC_RESTORE_SETTINGS))) { // Enabled driver // Use most relevant config data which might not have been saved to file // AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: Backup driver %d"), i); uint32_t data_size = fsize; // Fix possible buffer overflow @@ -565,10 +565,13 @@ bool SettingsConfigRestore(void) { uint32_t driver = atoi((const char*)filebuf_ptr +8); // /.drvset012 = 12 uint32_t fsize = filebuf_ptr[15] << 8 | filebuf_ptr[14]; // Tar header settings size filebuf_ptr += 16; // Start of file settings - uint32_t buffer_crc32 = filebuf_ptr[3] << 24 | filebuf_ptr[2] << 16 | filebuf_ptr[1] << 8 | filebuf_ptr[0]; - bool valid_buffer = (GetCfgCrc32(filebuf_ptr +4, fsize -4) == buffer_crc32); + bool valid_buffer = true; + if (driver) { + uint32_t buffer_crc32 = filebuf_ptr[3] << 24 | filebuf_ptr[2] << 16 | filebuf_ptr[1] << 8 | filebuf_ptr[0]; + valid_buffer = (GetCfgCrc32(filebuf_ptr +4, fsize -4) == buffer_crc32); + } if (valid_buffer) { - if (XdrvCallDriver(driver, FUNC_RESTORE_SETTINGS)) { + if (driver && (XdrvCallDriver(driver, FUNC_RESTORE_SETTINGS))) { // Restore live config data which will be saved to file before restart // AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: Restore driver %d"), driver); filebuf_ptr[1]++; // Force invalid crc32 to enable auto upgrade after restart @@ -1120,8 +1123,8 @@ void SettingsDefaultSet2(void) { flag5.mqtt_switches |= MQTT_SWITCHES; flag5.mqtt_persistent |= ~MQTT_CLEAN_SESSION; flag6.mqtt_disable_sserialrec |= MQTT_DISABLE_SSERIALRECEIVED; -// flag.mqtt_serial |= 0; flag6.mqtt_disable_modbus |= MQTT_DISABLE_MODBUSRECEIVED; +// flag.mqtt_serial |= 0; flag.device_index_enable |= MQTT_POWER_FORMAT; flag3.time_append_timezone |= MQTT_APPEND_TIMEZONE; flag3.button_switch_force_local |= MQTT_BUTTON_SWITCH_FORCE_LOCAL; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_122_file_json_settings_demo.ino b/tasmota/tasmota_xdrv_driver/xdrv_122_file_json_settings_demo.ino new file mode 100644 index 000000000..1b61874f0 --- /dev/null +++ b/tasmota/tasmota_xdrv_driver/xdrv_122_file_json_settings_demo.ino @@ -0,0 +1,230 @@ +/* + xdrv_122_file_json_settings_demo.ino - Demo for Tasmota + + Copyright (C) 2024 Theo Arends + + 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 . +*/ + +// Enable this define to use this demo +//#define USE_DRV_FILE_JSON_DEMO + +#ifdef USE_DRV_FILE_JSON_DEMO +/*********************************************************************************************\ + * JSON settings load and save demo using Tasmota file system + * + * To test this file: + * - Have hardware with at least 2M flash + * - Enable a board with at least 256k filesystem in platform_override.ini +\*********************************************************************************************/ +#warning **** USE_DRV_FILE_JSON_DEMO is enabled **** + +#define XDRV_122 122 +#define XDRV_KEY "drvset122" + +#define DRV_DEMO_MAX_DRV_TEXT 16 + +const uint16_t DRV_DEMO_VERSION = 0x0105; // Latest driver version (See settings deltas below) + +// Global structure containing driver saved variables +struct { + uint32_t crc32; // To detect file changes + uint16_t version; // To detect driver function changes + char drv_text[DRV_DEMO_MAX_DRV_TEXT][10]; +} DrvDemoSettings; + +// Global structure containing driver non-saved variables +struct { + uint32_t any_value; +} DrvDemoGlobal; + +/*********************************************************************************************\ + * Driver Settings load and save +\*********************************************************************************************/ + +bool DrvDemoLoadData(void) { + char key[20]; + snprintf_P(key, sizeof(key), PSTR(XDRV_KEY)); + String json = UfsJsonSettingsRead(key); + if (json.length() == 0) { return false; } + + JsonParser parser((char*)json.c_str()); + JsonParserObject root = parser.getRootObject(); + if (!root) { return false; } + + JsonParserToken val = root[PSTR("Crc")]; + if (val) { + DrvDemoSettings.crc32 = val.getUInt(); + } + val = root[PSTR("Version")]; + if (val) { + DrvDemoSettings.version = val.getInt(); + } + JsonParserArray arr = root[PSTR("Text")]; + if (arr) { + for (uint32_t i = 0; i < DRV_DEMO_MAX_DRV_TEXT; i++) { + if (arr[i]) { + snprintf(DrvDemoSettings.drv_text[i], 10, arr[i].getStr()); + } + } + } + return true; +} + +bool DrvDemoSaveData(void) { + Response_P(PSTR("{\"" XDRV_KEY "\":{\"Crc\":%u,\"Version\":%u,\"Text\":["), DrvDemoSettings.crc32, DrvDemoSettings.version); + for (uint32_t i = 0; i < DRV_DEMO_MAX_DRV_TEXT; i++) { + ResponseAppend_P(PSTR("%s\"%s\""), (i)?",":"", DrvDemoSettings.drv_text[i]); + } + ResponseAppend_P(PSTR("]}}")); + return UfsJsonSettingsWrite(ResponseData()); +} + +void DrvDemoDeleteData(void) { + char key[20]; + snprintf_P(key, sizeof(key), PSTR(XDRV_KEY)); + UfsJsonSettingsDelete(key); // Use defaults +} + +/*********************************************************************************************/ + +void DrvDemoSettingsLoad(bool erase) { + // Called from FUNC_PRE_INIT (erase = 0) once at restart + // Called from FUNC_RESET_SETTINGS (erase = 1) after command reset 4, 5, or 6 + + // *** Start init default values in case key is not found *** + AddLog(LOG_LEVEL_INFO, PSTR("DRV: " D_USE_DEFAULTS)); + + memset(&DrvDemoSettings, 0x00, sizeof(DrvDemoSettings)); + DrvDemoSettings.version = DRV_DEMO_VERSION; + // Init any other parameter in struct DrvDemoSettings + snprintf_P(DrvDemoSettings.drv_text[0], sizeof(DrvDemoSettings.drv_text[0]), PSTR("Azalea")); + + // *** End Init default values *** + +#ifndef USE_UFILESYS + AddLog(LOG_LEVEL_INFO, PSTR("CFG: Demo use defaults as file system not enabled")); +#else + // Try to load key + if (erase) { + DrvDemoDeleteData(); + } + else if (DrvDemoLoadData()) { + if (DrvDemoSettings.version != DRV_DEMO_VERSION) { // Fix version dependent changes + + // *** Start fix possible setting deltas *** + if (DrvDemoSettings.version < 0x0103) { + AddLog(LOG_LEVEL_INFO, PSTR("CFG: Update oldest version restore")); + + snprintf_P(DrvDemoSettings.drv_text[1], sizeof(DrvDemoSettings.drv_text[1]), PSTR("Begonia")); + } + if (DrvDemoSettings.version < 0x0104) { + AddLog(LOG_LEVEL_INFO, PSTR("CFG: Update old version restore")); + + } + + // *** End setting deltas *** + + // Set current version and save settings + DrvDemoSettings.version = DRV_DEMO_VERSION; + DrvDemoSettingsSave(); + } + AddLog(LOG_LEVEL_INFO, PSTR("CFG: Demo loaded from file")); + } + else { + // File system not ready: No flash space reserved for file system + AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: Demo use defaults as file system not ready or key not found")); + } +#endif // USE_UFILESYS +} + +void DrvDemoSettingsSave(void) { + // Called from FUNC_SAVE_SETTINGS every SaveData second and at restart +#ifdef USE_UFILESYS + uint32_t crc32 = GetCfgCrc32((uint8_t*)&DrvDemoSettings +4, sizeof(DrvDemoSettings) -4); // Skip crc32 + if (crc32 != DrvDemoSettings.crc32) { + // Try to save file /.drvset122 + DrvDemoSettings.crc32 = crc32; + + if (DrvDemoSaveData()) { + AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: Demo saved to file")); + } else { + // File system not ready: No flash space reserved for file system + AddLog(LOG_LEVEL_DEBUG, PSTR("CFG: ERROR Demo file system not ready or unable to save file")); + } + } +#endif // USE_UFILESYS +} + +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ + +// Demo command line commands +const char kDrvDemoCommands[] PROGMEM = "Drv|" // Prefix + "Text"; + +void (* const DrvDemoCommand[])(void) PROGMEM = { + &CmndDrvText }; + +void CmndDrvText(void) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= DRV_DEMO_MAX_DRV_TEXT)) { + if (!XdrvMailbox.usridx) { + // Command DrvText + for (uint32_t i = 0; i < DRV_DEMO_MAX_DRV_TEXT; i++) { + AddLog(LOG_LEVEL_DEBUG, PSTR("DRV: DrvText%02d %s"), i, DrvDemoSettings.drv_text[i]); + } + ResponseCmndDone(); + } else { + // Command DrvText + uint32_t index = XdrvMailbox.index -1; + if (XdrvMailbox.data_len > 0) { + snprintf_P(DrvDemoSettings.drv_text[index], sizeof(DrvDemoSettings.drv_text[index]), XdrvMailbox.data); + } + ResponseCmndIdxChar(DrvDemoSettings.drv_text[index]); + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv122(uint32_t function) { + bool result = false; + + switch (function) { + case FUNC_RESET_SETTINGS: + DrvDemoSettingsLoad(1); + break; + case FUNC_SAVE_SETTINGS: + DrvDemoSettingsSave(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kDrvDemoCommands, DrvDemoCommand); + break; + case FUNC_PRE_INIT: + DrvDemoSettingsLoad(0); + break; + case FUNC_SAVE_BEFORE_RESTART: + // !!! DO NOT USE AS IT'S FUNCTION IS BETTER HANDLED BY FUNC_SAVE_SETTINGS !!! + break; + case FUNC_ACTIVE: + result = true; + break; + } + return result; +} + +#endif // USE_DRV_FILE_DEMO \ No newline at end of file diff --git a/tasmota/tasmota_xdrv_driver/xdrv_122_file_settings_demo.ino b/tasmota/tasmota_xdrv_driver/xdrv_122_file_settings_demo.ino index 7680df760..c00221b60 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_122_file_settings_demo.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_122_file_settings_demo.ino @@ -109,11 +109,11 @@ void DrvDemoSettingsLoad(bool erase) { if (DrvDemoSettings.version != DRV_DEMO_VERSION) { // Fix version dependent changes // *** Start fix possible setting deltas *** - if (Settings->version < 0x01010100) { + if (DrvDemoSettings.version < 0x01010100) { AddLog(LOG_LEVEL_INFO, PSTR("CFG: Update oldest version restore")); } - if (Settings->version < 0x01010101) { + if (DrvDemoSettings.version < 0x01010101) { AddLog(LOG_LEVEL_INFO, PSTR("CFG: Update old version restore")); } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino b/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino index df3dd7260..0e5576669 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino @@ -538,6 +538,225 @@ bool UfsExecuteCommandFile(const char *fname) { return false; } +/*********************************************************************************************\ + * File JSON settings support using file /.drvset000 + * + * {"UserSet1":{"Param1":123,"Param2":"Text1"},"UserSet2":{"Param1":123,"Param2":"Text2"},"UserSet3":{"Param1":123,"Param2":"Text3"}} +\*********************************************************************************************/ + +bool _UfsJsonSettingsUpdate(const char* data) { + // Delete: Input UserSet2 + // Append: Input {"UserSet2":{"Param1":123,"Param2":"Text2"}} + + char filename[14]; + snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_DRIVER), 0); // /.drvset000 + if (!TfsFileExists(filename)) { return false; } // Error - File not found + + char bfname[14]; + strcpy_P(bfname, PSTR("/settmp")); + File ofile = ffsp->open(bfname, "w"); + if (!ofile) { return false; } // Error - unable to open temporary file + File ifile = ffsp->open(filename, "r"); + if (!ifile) { + ofile.close(); + ffsp->remove(bfname); + return false; // Error - unable to open settings file + } + + bool append = false; + char* key = (char*)data; + char key_pos[32]; // Max key length + char *p = strchr(data, '"'); + if (p) { + append = true; + char *q = strchr(++p, '"'); + if (!q) { return false; } // Error - No valid key provided in data to append + uint32_t len = (uint32_t)q - (uint32_t)p; + memcpy(key_pos, p, len); + key_pos[len] = '\0'; // key = UserSet2 + key = key_pos; + } + + char buffer[32]; // Max key length + uint8_t buf[1]; + uint32_t index = 0; + uint32_t bracket_count = 0; + int entries = 0; + bool quote = false; + bool mine = false; + bool deleted = false; + while (ifile.available()) { // Process file + ifile.read(buf, 1); + if (bracket_count > 1) { // Copy or skip old data + if (!mine) { + ofile.write(buf, 1); // Copy data + } + if (buf[0] == '}') { + bracket_count--; + } + } else { + if (buf[0] == '}') { // Last bracket + break; // End of file + } + else if (buf[0] == '{') { + bracket_count++; + if (bracket_count > 1) { // Skip first bracket + entries++; + } + } + else if (buf[0] == '"') { + quote ^= 1; + if (quote) { + index = 0; + } else { + buffer[index] = '\0'; // End of key name + mine = (!strcasecmp(buffer, key)); + if (mine) { + entries--; // Skip old data + deleted = true; + } else { + ofile.write((entries) ? (uint8_t*)",\"" : (uint8_t*)"{\"", 2); + ofile.write((uint8_t*)buffer, strlen(buffer)); + ofile.write((uint8_t*)"\":{", 3); + } + } + } + else { + buffer[index++] = buf[0]; // Add key name + if (index > sizeof(buffer) -2) { + break; // Key name too long + } + } + } + } + ifile.close(); + if (append) { + // Append new data + ofile.write((entries) ? (uint8_t*)"," : (uint8_t*)"{", 1); + ofile.write((uint8_t*)data +1, strlen(data) -1); + } else { + // Delete data + if (entries) { + ofile.write((uint8_t*)"}", 1); + } + } + ofile.close(); + + if (index > sizeof(buffer) -2) { + // No changes + ffsp->remove(bfname); + return false; // Error - Key name too long + } + ffsp->remove(filename); + ffsp->rename(bfname, filename); + if (!append) { + // Delete data + if (!entries) { + ffsp->remove(filename); + } + return deleted; // State - 0 = Not found, 1 = Deleted + } + return true; // State - Append success +} + +bool UfsJsonSettingsDelete(const char* key) { + // Delete: Input UserSet2 + // Output 0 = Not found, 1 = Deleted + return _UfsJsonSettingsUpdate(key); // State - 0 = Not found, 1 = Deleted +} + +bool UfsJsonSettingsWrite(const char* data) { + // Add new UserSet replacing present UserSet + // Input {"UserSet2":{"Param1":123,"Param2":"Text2"}} + // Output 0 = Error, 1 = Append success + + char filename[14]; + snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_DRIVER), 0); // /.drvset000 + if (!TfsFileExists(filename)) { + File ofile = ffsp->open(filename, "w"); + if (!ofile) { return false; } // Error - unable to open settings file + ofile.write((uint8_t*)data, strlen(data)); + ofile.close(); + return true; // State - Append success + } + return _UfsJsonSettingsUpdate(data); // State - 0 = Error, 1 = Append success +} + +String UfsJsonSettingsRead(const char* key) { + // Read: Input UserSet2 + // Output "" = Error, {"Param1":123,"Param2":"Text2"} = Data + + String data = ""; + char filename[14]; + snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_DRIVER), 0); // /.drvset000 + if (!TfsFileExists(filename)) { return data; } // Error - File not found + File file = ffsp->open(filename, "r"); + if (!file) { return data; } // Error - unable to open settings file + + Trim((char*)key); + char buffer[128]; + uint8_t buf[1] = { 0 }; + uint32_t index = 0; + uint32_t bracket_count = 0; + bool quote = false; + bool mine = false; + while (file.available()) { // Process file + file.read(buf, 1); + if (bracket_count > 1) { // Build JSON + if (mine) { + buffer[index++] = buf[0]; // Add key data + if (index > sizeof(buffer) -2) { + buffer[index] = '\0'; + data += buffer; // Add buffer to result + index = 0; + } + } + if (buf[0] == '}') { + bracket_count--; + if (1 == bracket_count) { + if (mine) { + break; // End of key data + } else { + index = 0; // End of data which is not mine + } + } + } + } else { + if (buf[0] == '}') { // Last bracket + index = 0; + break; // End of file - key not found + } + else if (buf[0] == '{') { + bracket_count++; + if (bracket_count > 1) { // Skip first bracket + index = 0; + buffer[index++] = buf[0]; // Start of key data + } + } + else if (buf[0] == '"') { + quote ^= 1; + if (quote) { + index = 0; + } else { + buffer[index] = '\0'; // End of key name + mine = (!strcasecmp(buffer, key)); + } + } + else { + buffer[index++] = buf[0]; // Add key name + if (index > sizeof(buffer) -2) { + index = 0; + break; // Key name too long + } + } + } + } + file.close(); + buffer[index] = '\0'; + data += buffer; + return data; // State - "" = Error, {"Param1":123,"Param2":"Text2"} = Data +} + /*********************************************************************************************\ * Commands \*********************************************************************************************/ From a5e3391ca8d39c3707df3554944f718d07073737 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 8 Feb 2024 02:42:21 +0100 Subject: [PATCH 283/303] Matter fix introspect.contains (#20685) --- lib/libesp32/berry/src/be_api.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/libesp32/berry/src/be_api.c b/lib/libesp32/berry/src/be_api.c index 31755604f..6ccb65c5a 100644 --- a/lib/libesp32/berry/src/be_api.c +++ b/lib/libesp32/berry/src/be_api.c @@ -665,6 +665,7 @@ BERRY_API bbool be_copy(bvm *vm, int index) } /* `onlyins` limits the search to instance, and discards module. Makes sure getmethod does not return anything for module. */ +/* may return BE_NONE */ static int ins_member(bvm *vm, int index, const char *k, bbool onlyins) { int type = BE_NIL; @@ -681,12 +682,12 @@ static int ins_member(bvm *vm, int index, const char *k, bbool onlyins) bmodule *module = var_toobj(o); type = be_module_attr(vm, module, be_newstr(vm, k), top); } - return type == BE_NONE ? BE_NIL : type; + return type; } BERRY_API bbool be_getmember(bvm *vm, int index, const char *k) { - return ins_member(vm, index, k, bfalse) != BE_NIL; + return ins_member(vm, index, k, bfalse) != BE_NONE; } BERRY_API bbool be_getmethod(bvm *vm, int index, const char *k) From 57cf29c2fd84588b07b8c7c0acc888433964470b Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Wed, 7 Feb 2024 18:09:22 -0800 Subject: [PATCH 284/303] Matter improve `MtrInfo` (#20686) --- CHANGELOG.md | 1 + .../src/embedded/Matter_Plugin_1_Device.be | 8 + .../src/embedded/Matter_Plugin_2_Sensor.be | 10 - .../Matter_Plugin_2_Sensor_Contact.be | 9 - .../Matter_Plugin_2_Sensor_Occupancy.be | 9 - .../embedded/Matter_Plugin_2_Sensor_OnOff.be | 2 + .../solidified_Matter_Plugin_1_Device.h | 172 ++++--- .../solidified_Matter_Plugin_2_Sensor.h | 434 ++++++++---------- ...olidified_Matter_Plugin_2_Sensor_Contact.h | 288 +++++------- ...idified_Matter_Plugin_2_Sensor_Occupancy.h | 280 +++++------ 10 files changed, 560 insertions(+), 653 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 348be9510..bfb1f718f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. - ESP32 LVGL library from v8.3.11 to v9.0.0, some small breaking changes in C, none in HASPmota (#20659) ### Changed +- Matter improve `MtrInfo` ### Fixed diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Device.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Device.be index 8ddf9012b..4357a3844 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Device.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Device.be @@ -178,6 +178,7 @@ class Matter_Plugin_Device : Matter_Plugin # New values need to be appended with `,"key":value` (including prefix comma) def append_state_json() import introspect + import json var ret = "" # ret: string @@ -193,6 +194,13 @@ class Matter_Plugin_Device : Matter_Plugin end end + # If sensor with JSON_NAME using `val` + var json_name = introspect.get(self, 'JSON_NAME') + if json_name && introspect.contains(self, 'shadow_value') + var val = (self.shadow_value != nil) ? json.dump(self.shadow_value) : "null" + ret += f',"{json_name}":{val}' + end + # lights # print(f'{self=} {type(self)} {introspect.members(self)=}') _stats_json_inner("shadow_onoff", "Power") diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor.be index 1678f2a4f..a702a11af 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor.be @@ -106,15 +106,5 @@ class Matter_Plugin_Sensor : Matter_Plugin_Device super(self).update_virtual(payload_json) end - ############################################################# - # append_state_json - # - # Output the current state in JSON - # New values need to be appended with `,"key":value` (including prefix comma) - def append_state_json() - var val = (self.shadow_value != nil) ? self.shadow_value : "null" - return f',"{self.JSON_NAME}":{val}' - end - end matter.Plugin_Sensor = Matter_Plugin_Sensor diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Contact.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Contact.be index f560d9540..fbd061b1f 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Contact.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Contact.be @@ -119,14 +119,5 @@ class Matter_Plugin_Sensor_Contact : Matter_Plugin_Device super(self).update_virtual(payload_json) end - ############################################################# - # append_state_json - # - # Output the current state in JSON - # New values need to be appended with `,"key":value` (including prefix comma) - def append_state_json() - return f',"Contact":{int(self.shadow_contact)}' - end - end matter.Plugin_Sensor_Contact = Matter_Plugin_Sensor_Contact diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Occupancy.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Occupancy.be index 8ad690726..958386d59 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Occupancy.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Occupancy.be @@ -123,14 +123,5 @@ class Matter_Plugin_Sensor_Occupancy : Matter_Plugin_Device super(self).update_virtual(payload_json) end - ############################################################# - # append_state_json - # - # Output the current state in JSON - # New values need to be appended with `,"key":value` (including prefix comma) - def append_state_json() - return f',"Occupancy":{int(self.shadow_occupancy)}' - end - end matter.Plugin_Sensor_Occupancy = Matter_Plugin_Sensor_Occupancy diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_OnOff.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_OnOff.be index b7b1eb758..ce535f91c 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_OnOff.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_OnOff.be @@ -95,6 +95,8 @@ class Matter_Plugin_Sensor_OnOff : Matter_Plugin_Device # # Output the current state in JSON # New values need to be appended with `,"key":value` (including prefix comma) + # + # Override the default behavior to use the key `OnOff` instead of `Power` def append_state_json() return f',"OnOff":{int(self.shadow_onoff)}' end diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Device.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Device.h index 71adb3df2..f93586d65 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Device.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Device.h @@ -326,7 +326,7 @@ be_local_closure(Matter_Plugin_Device_read_attribute, /* name */ ********************************************************************/ be_local_closure(Matter_Plugin_Device_append_state_json, /* name */ be_nested_proto( - 7, /* nstack */ + 11, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -340,7 +340,7 @@ be_local_closure(Matter_Plugin_Device_append_state_json, /* name */ 1, /* has upvals */ ( &(const bupvaldesc[ 2]) { /* upvals */ be_local_const_upval(1, 0), - be_local_const_upval(1, 2), + be_local_const_upval(1, 3), }), 0, /* has sup protos */ NULL, /* no sub protos */ @@ -391,78 +391,112 @@ be_local_closure(Matter_Plugin_Device_append_state_json, /* name */ ), }), 1, /* has constants */ - ( &(const bvalue[22]) { /* constants */ + ( &(const bvalue[30]) { /* constants */ /* K0 */ be_nested_str_weak(introspect), - /* K1 */ be_nested_str_weak(), - /* K2 */ be_nested_str_weak(shadow_onoff), - /* K3 */ be_nested_str_weak(Power), - /* K4 */ be_nested_str_weak(shadow_bri), - /* K5 */ be_nested_str_weak(Bri), - /* K6 */ be_nested_str_weak(shadow_ct), - /* K7 */ be_nested_str_weak(CT), - /* K8 */ be_nested_str_weak(shadow_hue), - /* K9 */ be_nested_str_weak(Hue), - /* K10 */ be_nested_str_weak(shadow_sat), - /* K11 */ be_nested_str_weak(Sat), - /* K12 */ be_nested_str_weak(shadow_shutter_pos), - /* K13 */ be_nested_str_weak(ShutterPos), - /* K14 */ be_nested_str_weak(shadow_shutter_target), - /* K15 */ be_nested_str_weak(ShutterTarget), - /* K16 */ be_nested_str_weak(shadow_shutter_tilt), - /* K17 */ be_nested_str_weak(ShutterTilt), - /* K18 */ be_nested_str_weak(shadow_contact), - /* K19 */ be_nested_str_weak(Contact), - /* K20 */ be_nested_str_weak(shadow_occupancy), - /* K21 */ be_nested_str_weak(Occupancy), + /* K1 */ be_nested_str_weak(json), + /* K2 */ be_nested_str_weak(), + /* K3 */ be_nested_str_weak(get), + /* K4 */ be_nested_str_weak(JSON_NAME), + /* K5 */ be_nested_str_weak(contains), + /* K6 */ be_nested_str_weak(shadow_value), + /* K7 */ be_nested_str_weak(dump), + /* K8 */ be_nested_str_weak(null), + /* K9 */ be_nested_str_weak(_X2C_X22_X25s_X22_X3A_X25s), + /* K10 */ be_nested_str_weak(shadow_onoff), + /* K11 */ be_nested_str_weak(Power), + /* K12 */ be_nested_str_weak(shadow_bri), + /* K13 */ be_nested_str_weak(Bri), + /* K14 */ be_nested_str_weak(shadow_ct), + /* K15 */ be_nested_str_weak(CT), + /* K16 */ be_nested_str_weak(shadow_hue), + /* K17 */ be_nested_str_weak(Hue), + /* K18 */ be_nested_str_weak(shadow_sat), + /* K19 */ be_nested_str_weak(Sat), + /* K20 */ be_nested_str_weak(shadow_shutter_pos), + /* K21 */ be_nested_str_weak(ShutterPos), + /* K22 */ be_nested_str_weak(shadow_shutter_target), + /* K23 */ be_nested_str_weak(ShutterTarget), + /* K24 */ be_nested_str_weak(shadow_shutter_tilt), + /* K25 */ be_nested_str_weak(ShutterTilt), + /* K26 */ be_nested_str_weak(shadow_contact), + /* K27 */ be_nested_str_weak(Contact), + /* K28 */ be_nested_str_weak(shadow_occupancy), + /* K29 */ be_nested_str_weak(Occupancy), }), be_str_weak(append_state_json), &be_const_str_solidified, - ( &(const binstruction[45]) { /* code */ + ( &(const binstruction[71]) { /* code */ 0xA4060000, // 0000 IMPORT R1 K0 - 0x58080001, // 0001 LDCONST R2 K1 - 0x840C0000, // 0002 CLOSURE R3 P0 - 0x5C100600, // 0003 MOVE R4 R3 - 0x58140002, // 0004 LDCONST R5 K2 - 0x58180003, // 0005 LDCONST R6 K3 - 0x7C100400, // 0006 CALL R4 2 - 0x5C100600, // 0007 MOVE R4 R3 - 0x58140004, // 0008 LDCONST R5 K4 - 0x58180005, // 0009 LDCONST R6 K5 - 0x7C100400, // 000A CALL R4 2 - 0x5C100600, // 000B MOVE R4 R3 - 0x58140006, // 000C LDCONST R5 K6 - 0x58180007, // 000D LDCONST R6 K7 - 0x7C100400, // 000E CALL R4 2 - 0x5C100600, // 000F MOVE R4 R3 - 0x58140008, // 0010 LDCONST R5 K8 - 0x58180009, // 0011 LDCONST R6 K9 - 0x7C100400, // 0012 CALL R4 2 - 0x5C100600, // 0013 MOVE R4 R3 - 0x5814000A, // 0014 LDCONST R5 K10 - 0x5818000B, // 0015 LDCONST R6 K11 - 0x7C100400, // 0016 CALL R4 2 - 0x5C100600, // 0017 MOVE R4 R3 - 0x5814000C, // 0018 LDCONST R5 K12 - 0x5818000D, // 0019 LDCONST R6 K13 - 0x7C100400, // 001A CALL R4 2 - 0x5C100600, // 001B MOVE R4 R3 - 0x5814000E, // 001C LDCONST R5 K14 - 0x5818000F, // 001D LDCONST R6 K15 - 0x7C100400, // 001E CALL R4 2 - 0x5C100600, // 001F MOVE R4 R3 - 0x58140010, // 0020 LDCONST R5 K16 - 0x58180011, // 0021 LDCONST R6 K17 - 0x7C100400, // 0022 CALL R4 2 - 0x5C100600, // 0023 MOVE R4 R3 - 0x58140012, // 0024 LDCONST R5 K18 - 0x58180013, // 0025 LDCONST R6 K19 - 0x7C100400, // 0026 CALL R4 2 - 0x5C100600, // 0027 MOVE R4 R3 - 0x58140014, // 0028 LDCONST R5 K20 - 0x58180015, // 0029 LDCONST R6 K21 - 0x7C100400, // 002A CALL R4 2 - 0xA0000000, // 002B CLOSE R0 - 0x80040400, // 002C RET 1 R2 + 0xA40A0200, // 0001 IMPORT R2 K1 + 0x580C0002, // 0002 LDCONST R3 K2 + 0x84100000, // 0003 CLOSURE R4 P0 + 0x8C140303, // 0004 GETMET R5 R1 K3 + 0x5C1C0000, // 0005 MOVE R7 R0 + 0x58200004, // 0006 LDCONST R8 K4 + 0x7C140600, // 0007 CALL R5 3 + 0x78160013, // 0008 JMPF R5 #001D + 0x8C180305, // 0009 GETMET R6 R1 K5 + 0x5C200000, // 000A MOVE R8 R0 + 0x58240006, // 000B LDCONST R9 K6 + 0x7C180600, // 000C CALL R6 3 + 0x781A000E, // 000D JMPF R6 #001D + 0x88180106, // 000E GETMBR R6 R0 K6 + 0x4C1C0000, // 000F LDNIL R7 + 0x20180C07, // 0010 NE R6 R6 R7 + 0x781A0003, // 0011 JMPF R6 #0016 + 0x8C180507, // 0012 GETMET R6 R2 K7 + 0x88200106, // 0013 GETMBR R8 R0 K6 + 0x7C180400, // 0014 CALL R6 2 + 0x70020000, // 0015 JMP #0017 + 0x58180008, // 0016 LDCONST R6 K8 + 0x601C0018, // 0017 GETGBL R7 G24 + 0x58200009, // 0018 LDCONST R8 K9 + 0x5C240A00, // 0019 MOVE R9 R5 + 0x5C280C00, // 001A MOVE R10 R6 + 0x7C1C0600, // 001B CALL R7 3 + 0x000C0607, // 001C ADD R3 R3 R7 + 0x5C180800, // 001D MOVE R6 R4 + 0x581C000A, // 001E LDCONST R7 K10 + 0x5820000B, // 001F LDCONST R8 K11 + 0x7C180400, // 0020 CALL R6 2 + 0x5C180800, // 0021 MOVE R6 R4 + 0x581C000C, // 0022 LDCONST R7 K12 + 0x5820000D, // 0023 LDCONST R8 K13 + 0x7C180400, // 0024 CALL R6 2 + 0x5C180800, // 0025 MOVE R6 R4 + 0x581C000E, // 0026 LDCONST R7 K14 + 0x5820000F, // 0027 LDCONST R8 K15 + 0x7C180400, // 0028 CALL R6 2 + 0x5C180800, // 0029 MOVE R6 R4 + 0x581C0010, // 002A LDCONST R7 K16 + 0x58200011, // 002B LDCONST R8 K17 + 0x7C180400, // 002C CALL R6 2 + 0x5C180800, // 002D MOVE R6 R4 + 0x581C0012, // 002E LDCONST R7 K18 + 0x58200013, // 002F LDCONST R8 K19 + 0x7C180400, // 0030 CALL R6 2 + 0x5C180800, // 0031 MOVE R6 R4 + 0x581C0014, // 0032 LDCONST R7 K20 + 0x58200015, // 0033 LDCONST R8 K21 + 0x7C180400, // 0034 CALL R6 2 + 0x5C180800, // 0035 MOVE R6 R4 + 0x581C0016, // 0036 LDCONST R7 K22 + 0x58200017, // 0037 LDCONST R8 K23 + 0x7C180400, // 0038 CALL R6 2 + 0x5C180800, // 0039 MOVE R6 R4 + 0x581C0018, // 003A LDCONST R7 K24 + 0x58200019, // 003B LDCONST R8 K25 + 0x7C180400, // 003C CALL R6 2 + 0x5C180800, // 003D MOVE R6 R4 + 0x581C001A, // 003E LDCONST R7 K26 + 0x5820001B, // 003F LDCONST R8 K27 + 0x7C180400, // 0040 CALL R6 2 + 0x5C180800, // 0041 MOVE R6 R4 + 0x581C001C, // 0042 LDCONST R7 K28 + 0x5820001D, // 0043 LDCONST R8 K29 + 0x7C180400, // 0044 CALL R6 2 + 0xA0000000, // 0045 CLOSE R0 + 0x80040600, // 0046 RET 1 R3 }) ) ); diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor.h index e2d100e7b..ee3304726 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor.h @@ -6,230 +6,6 @@ extern const bclass be_class_Matter_Plugin_Sensor; -/******************************************************************** -** Solidified function: append_state_json -********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_append_state_json, /* name */ - be_nested_proto( - 6, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ - /* K0 */ be_nested_str_weak(shadow_value), - /* K1 */ be_nested_str_weak(null), - /* K2 */ be_nested_str_weak(_X2C_X22_X25s_X22_X3A_X25s), - /* K3 */ be_nested_str_weak(JSON_NAME), - }), - be_str_weak(append_state_json), - &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x4C080000, // 0001 LDNIL R2 - 0x20040202, // 0002 NE R1 R1 R2 - 0x78060001, // 0003 JMPF R1 #0006 - 0x88040100, // 0004 GETMBR R1 R0 K0 - 0x70020000, // 0005 JMP #0007 - 0x58040001, // 0006 LDCONST R1 K1 - 0x60080018, // 0007 GETGBL R2 G24 - 0x580C0002, // 0008 LDCONST R3 K2 - 0x88100103, // 0009 GETMBR R4 R0 K3 - 0x5C140200, // 000A MOVE R5 R1 - 0x7C080600, // 000B CALL R2 3 - 0x80040400, // 000C RET 1 R2 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_init, /* name */ - be_nested_proto( - 9, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(init), - /* K1 */ be_nested_str_weak(add_read_sensors_schedule), - /* K2 */ be_nested_str_weak(UPDATE_TIME), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x60100003, // 0000 GETGBL R4 G3 - 0x5C140000, // 0001 MOVE R5 R0 - 0x7C100200, // 0002 CALL R4 1 - 0x8C100900, // 0003 GETMET R4 R4 K0 - 0x5C180200, // 0004 MOVE R6 R1 - 0x5C1C0400, // 0005 MOVE R7 R2 - 0x5C200600, // 0006 MOVE R8 R3 - 0x7C100800, // 0007 CALL R4 4 - 0x8C100301, // 0008 GETMET R4 R1 K1 - 0x88180102, // 0009 GETMBR R6 R0 K2 - 0x7C100400, // 000A CALL R4 2 - 0x80000000, // 000B RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: value_changed -********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_value_changed, /* name */ - be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(value_changed), - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: parse_configuration -********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_parse_configuration, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota_sensor_filter), - /* K1 */ be_nested_str_weak(find), - /* K2 */ be_nested_str_weak(ARG), - /* K3 */ be_nested_str_weak(tasmota_sensor_matcher), - /* K4 */ be_nested_str_weak(tasmota), - /* K5 */ be_nested_str_weak(Rule_Matcher), - /* K6 */ be_nested_str_weak(parse), - }), - be_str_weak(parse_configuration), - &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x8C080301, // 0000 GETMET R2 R1 K1 - 0x88100102, // 0001 GETMBR R4 R0 K2 - 0x7C080400, // 0002 CALL R2 2 - 0x90020002, // 0003 SETMBR R0 K0 R2 - 0x88080100, // 0004 GETMBR R2 R0 K0 - 0x780A0005, // 0005 JMPF R2 #000C - 0xB80A0800, // 0006 GETNGBL R2 K4 - 0x88080505, // 0007 GETMBR R2 R2 K5 - 0x8C080506, // 0008 GETMET R2 R2 K6 - 0x88100100, // 0009 GETMBR R4 R0 K0 - 0x7C080400, // 000A CALL R2 2 - 0x90020602, // 000B SETMBR R0 K3 R2 - 0x80000000, // 000C RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: parse_sensors -********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_parse_sensors, /* name */ - be_nested_proto( - 8, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(VIRTUAL), - /* K1 */ be_nested_str_weak(tasmota_sensor_matcher), - /* K2 */ be_nested_str_weak(pre_value), - /* K3 */ be_nested_str_weak(match), - /* K4 */ be_nested_str_weak(shadow_value), - /* K5 */ be_nested_str_weak(value_changed), - }), - be_str_weak(parse_sensors), - &be_const_str_solidified, - ( &(const binstruction[22]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x740A0012, // 0001 JMPT R2 #0015 - 0x88080101, // 0002 GETMBR R2 R0 K1 - 0x780A0010, // 0003 JMPF R2 #0015 - 0x8C080102, // 0004 GETMET R2 R0 K2 - 0x6010000A, // 0005 GETGBL R4 G10 - 0x88140101, // 0006 GETMBR R5 R0 K1 - 0x8C140B03, // 0007 GETMET R5 R5 K3 - 0x5C1C0200, // 0008 MOVE R7 R1 - 0x7C140400, // 0009 CALL R5 2 - 0x7C100200, // 000A CALL R4 1 - 0x7C080400, // 000B CALL R2 2 - 0x4C0C0000, // 000C LDNIL R3 - 0x200C0403, // 000D NE R3 R2 R3 - 0x780E0005, // 000E JMPF R3 #0015 - 0x880C0104, // 000F GETMBR R3 R0 K4 - 0x200C0403, // 0010 NE R3 R2 R3 - 0x780E0002, // 0011 JMPF R3 #0015 - 0x8C0C0105, // 0012 GETMET R3 R0 K5 - 0x7C0C0200, // 0013 CALL R3 1 - 0x90020802, // 0014 SETMBR R0 K4 R2 - 0x80000000, // 0015 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: pre_value -********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_pre_value, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(pre_value), - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80040200, // 0000 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: update_virtual ********************************************************************/ @@ -288,6 +64,189 @@ be_local_closure(Matter_Plugin_Sensor_update_virtual, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: parse_sensors +********************************************************************/ +be_local_closure(Matter_Plugin_Sensor_parse_sensors, /* name */ + be_nested_proto( + 8, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(VIRTUAL), + /* K1 */ be_nested_str_weak(tasmota_sensor_matcher), + /* K2 */ be_nested_str_weak(pre_value), + /* K3 */ be_nested_str_weak(match), + /* K4 */ be_nested_str_weak(shadow_value), + /* K5 */ be_nested_str_weak(value_changed), + }), + be_str_weak(parse_sensors), + &be_const_str_solidified, + ( &(const binstruction[22]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x740A0012, // 0001 JMPT R2 #0015 + 0x88080101, // 0002 GETMBR R2 R0 K1 + 0x780A0010, // 0003 JMPF R2 #0015 + 0x8C080102, // 0004 GETMET R2 R0 K2 + 0x6010000A, // 0005 GETGBL R4 G10 + 0x88140101, // 0006 GETMBR R5 R0 K1 + 0x8C140B03, // 0007 GETMET R5 R5 K3 + 0x5C1C0200, // 0008 MOVE R7 R1 + 0x7C140400, // 0009 CALL R5 2 + 0x7C100200, // 000A CALL R4 1 + 0x7C080400, // 000B CALL R2 2 + 0x4C0C0000, // 000C LDNIL R3 + 0x200C0403, // 000D NE R3 R2 R3 + 0x780E0005, // 000E JMPF R3 #0015 + 0x880C0104, // 000F GETMBR R3 R0 K4 + 0x200C0403, // 0010 NE R3 R2 R3 + 0x780E0002, // 0011 JMPF R3 #0015 + 0x8C0C0105, // 0012 GETMET R3 R0 K5 + 0x7C0C0200, // 0013 CALL R3 1 + 0x90020802, // 0014 SETMBR R0 K4 R2 + 0x80000000, // 0015 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: parse_configuration +********************************************************************/ +be_local_closure(Matter_Plugin_Sensor_parse_configuration, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 7]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota_sensor_filter), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(ARG), + /* K3 */ be_nested_str_weak(tasmota_sensor_matcher), + /* K4 */ be_nested_str_weak(tasmota), + /* K5 */ be_nested_str_weak(Rule_Matcher), + /* K6 */ be_nested_str_weak(parse), + }), + be_str_weak(parse_configuration), + &be_const_str_solidified, + ( &(const binstruction[13]) { /* code */ + 0x8C080301, // 0000 GETMET R2 R1 K1 + 0x88100102, // 0001 GETMBR R4 R0 K2 + 0x7C080400, // 0002 CALL R2 2 + 0x90020002, // 0003 SETMBR R0 K0 R2 + 0x88080100, // 0004 GETMBR R2 R0 K0 + 0x780A0005, // 0005 JMPF R2 #000C + 0xB80A0800, // 0006 GETNGBL R2 K4 + 0x88080505, // 0007 GETMBR R2 R2 K5 + 0x8C080506, // 0008 GETMET R2 R2 K6 + 0x88100100, // 0009 GETMBR R4 R0 K0 + 0x7C080400, // 000A CALL R2 2 + 0x90020602, // 000B SETMBR R0 K3 R2 + 0x80000000, // 000C RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Matter_Plugin_Sensor_init, /* name */ + be_nested_proto( + 9, /* nstack */ + 4, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(init), + /* K1 */ be_nested_str_weak(add_read_sensors_schedule), + /* K2 */ be_nested_str_weak(UPDATE_TIME), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[12]) { /* code */ + 0x60100003, // 0000 GETGBL R4 G3 + 0x5C140000, // 0001 MOVE R5 R0 + 0x7C100200, // 0002 CALL R4 1 + 0x8C100900, // 0003 GETMET R4 R4 K0 + 0x5C180200, // 0004 MOVE R6 R1 + 0x5C1C0400, // 0005 MOVE R7 R2 + 0x5C200600, // 0006 MOVE R8 R3 + 0x7C100800, // 0007 CALL R4 4 + 0x8C100301, // 0008 GETMET R4 R1 K1 + 0x88180102, // 0009 GETMBR R6 R0 K2 + 0x7C100400, // 000A CALL R4 2 + 0x80000000, // 000B RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: pre_value +********************************************************************/ +be_local_closure(Matter_Plugin_Sensor_pre_value, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(pre_value), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80040200, // 0000 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: value_changed +********************************************************************/ +be_local_closure(Matter_Plugin_Sensor_value_changed, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(value_changed), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified class: Matter_Plugin_Sensor ********************************************************************/ @@ -295,22 +254,21 @@ extern const bclass be_class_Matter_Plugin_Device; be_local_class(Matter_Plugin_Sensor, 3, &be_class_Matter_Plugin_Device, - be_nested_map(14, + be_nested_map(13, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(UPDATE_TIME, 3), be_const_int(5000) }, - { be_const_key_weak(ARG, -1), be_nested_str_weak(filter) }, - { be_const_key_weak(append_state_json, 0), be_const_closure(Matter_Plugin_Sensor_append_state_json_closure) }, - { be_const_key_weak(update_virtual, -1), be_const_closure(Matter_Plugin_Sensor_update_virtual_closure) }, - { be_const_key_weak(tasmota_sensor_filter, -1), be_const_var(0) }, - { be_const_key_weak(init, 13), be_const_closure(Matter_Plugin_Sensor_init_closure) }, - { be_const_key_weak(tasmota_sensor_matcher, -1), be_const_var(1) }, - { be_const_key_weak(ARG_HINT, 12), be_nested_str_weak(Filter_X20pattern) }, - { be_const_key_weak(parse_sensors, 10), be_const_closure(Matter_Plugin_Sensor_parse_sensors_closure) }, - { be_const_key_weak(JSON_NAME, -1), be_nested_str_weak() }, - { be_const_key_weak(pre_value, -1), be_const_closure(Matter_Plugin_Sensor_pre_value_closure) }, - { be_const_key_weak(shadow_value, 7), be_const_var(2) }, - { be_const_key_weak(parse_configuration, -1), be_const_closure(Matter_Plugin_Sensor_parse_configuration_closure) }, + { be_const_key_weak(ARG, 1), be_nested_str_weak(filter) }, { be_const_key_weak(value_changed, -1), be_const_closure(Matter_Plugin_Sensor_value_changed_closure) }, + { be_const_key_weak(update_virtual, -1), be_const_closure(Matter_Plugin_Sensor_update_virtual_closure) }, + { be_const_key_weak(ARG_HINT, 9), be_nested_str_weak(Filter_X20pattern) }, + { be_const_key_weak(tasmota_sensor_matcher, -1), be_const_var(1) }, + { be_const_key_weak(parse_sensors, -1), be_const_closure(Matter_Plugin_Sensor_parse_sensors_closure) }, + { be_const_key_weak(JSON_NAME, 8), be_nested_str_weak() }, + { be_const_key_weak(parse_configuration, -1), be_const_closure(Matter_Plugin_Sensor_parse_configuration_closure) }, + { be_const_key_weak(init, -1), be_const_closure(Matter_Plugin_Sensor_init_closure) }, + { be_const_key_weak(pre_value, 12), be_const_closure(Matter_Plugin_Sensor_pre_value_closure) }, + { be_const_key_weak(shadow_value, -1), be_const_var(2) }, + { be_const_key_weak(UPDATE_TIME, -1), be_const_int(5000) }, + { be_const_key_weak(tasmota_sensor_filter, -1), be_const_var(0) }, })), be_str_weak(Matter_Plugin_Sensor) ); diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h index 1017a0d2d..dc4bd4205 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h @@ -7,32 +7,26 @@ extern const bclass be_class_Matter_Plugin_Sensor_Contact; /******************************************************************** -** Solidified function: append_state_json +** Solidified function: ********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_Contact_append_state_json, /* name */ +be_local_closure(Matter_Plugin_Sensor_Contact__X3Clambda_X3E, /* name */ be_nested_proto( - 5, /* nstack */ + 3, /* nstack */ 1, /* argc */ - 2, /* varg */ + 0, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(_X2C_X22Contact_X22_X3A_X25s), - /* K1 */ be_nested_str_weak(shadow_contact), - }), - be_str_weak(append_state_json), + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(_X3Clambda_X3E), &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0x60040018, // 0000 GETGBL R1 G24 - 0x58080000, // 0001 LDCONST R2 K0 - 0x600C0009, // 0002 GETGBL R3 G9 - 0x88100101, // 0003 GETMBR R4 R0 K1 - 0x7C0C0200, // 0004 CALL R3 1 - 0x7C040400, // 0005 CALL R1 2 - 0x80040200, // 0006 RET 1 R1 + ( &(const binstruction[ 4]) { /* code */ + 0x60040009, // 0000 GETGBL R1 G9 + 0x5C080000, // 0001 MOVE R2 R0 + 0x7C040200, // 0002 CALL R1 1 + 0x80040200, // 0003 RET 1 R1 }) ) ); @@ -40,40 +34,36 @@ be_local_closure(Matter_Plugin_Sensor_Contact_append_state_json, /* name */ /******************************************************************** -** Solidified function: parse_configuration +** Solidified function: init ********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_Contact_parse_configuration, /* name */ +be_local_closure(Matter_Plugin_Sensor_Contact_init, /* name */ be_nested_proto( - 7, /* nstack */ - 2, /* argc */ + 9, /* nstack */ + 4, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota_switch_index), - /* K1 */ be_nested_str_weak(find), - /* K2 */ be_nested_str_weak(ARG), - /* K3 */ be_const_int(1), - /* K4 */ be_const_int(0), + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(init), + /* K1 */ be_nested_str_weak(shadow_contact), }), - be_str_weak(parse_configuration), + be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x60080009, // 0000 GETGBL R2 G9 - 0x8C0C0301, // 0001 GETMET R3 R1 K1 - 0x88140102, // 0002 GETMBR R5 R0 K2 - 0x58180003, // 0003 LDCONST R6 K3 - 0x7C0C0600, // 0004 CALL R3 3 - 0x7C080200, // 0005 CALL R2 1 - 0x90020002, // 0006 SETMBR R0 K0 R2 - 0x88080100, // 0007 GETMBR R2 R0 K0 - 0x18080504, // 0008 LE R2 R2 K4 - 0x780A0000, // 0009 JMPF R2 #000B - 0x90020103, // 000A SETMBR R0 K0 K3 - 0x80000000, // 000B RET 0 + ( &(const binstruction[11]) { /* code */ + 0x60100003, // 0000 GETGBL R4 G3 + 0x5C140000, // 0001 MOVE R5 R0 + 0x7C100200, // 0002 CALL R4 1 + 0x8C100900, // 0003 GETMET R4 R4 K0 + 0x5C180200, // 0004 MOVE R6 R1 + 0x5C1C0400, // 0005 MOVE R7 R2 + 0x5C200600, // 0006 MOVE R8 R3 + 0x7C100800, // 0007 CALL R4 4 + 0x50100000, // 0008 LDBOOL R4 0 0 + 0x90020204, // 0009 SETMBR R0 K1 R4 + 0x80000000, // 000A RET 0 }) ) ); @@ -162,9 +152,9 @@ be_local_closure(Matter_Plugin_Sensor_Contact_update_shadow, /* name */ /******************************************************************** -** Solidified function: update_virtual +** Solidified function: parse_configuration ********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_Contact_update_virtual, /* name */ +be_local_closure(Matter_Plugin_Sensor_Contact_parse_configuration, /* name */ be_nested_proto( 7, /* nstack */ 2, /* argc */ @@ -174,106 +164,28 @@ be_local_closure(Matter_Plugin_Sensor_Contact_update_virtual, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(find), - /* K1 */ be_nested_str_weak(Contact), - /* K2 */ be_nested_str_weak(shadow_contact), - /* K3 */ be_nested_str_weak(attribute_updated), + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota_switch_index), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(ARG), + /* K3 */ be_const_int(1), /* K4 */ be_const_int(0), - /* K5 */ be_nested_str_weak(update_virtual), }), - be_str_weak(update_virtual), + be_str_weak(parse_configuration), &be_const_str_solidified, - ( &(const binstruction[25]) { /* code */ - 0x8C080300, // 0000 GETMET R2 R1 K0 - 0x58100001, // 0001 LDCONST R4 K1 - 0x7C080400, // 0002 CALL R2 2 - 0x4C0C0000, // 0003 LDNIL R3 - 0x200C0403, // 0004 NE R3 R2 R3 - 0x780E000B, // 0005 JMPF R3 #0012 - 0x600C0017, // 0006 GETGBL R3 G23 - 0x5C100400, // 0007 MOVE R4 R2 - 0x7C0C0200, // 0008 CALL R3 1 - 0x5C080600, // 0009 MOVE R2 R3 - 0x880C0102, // 000A GETMBR R3 R0 K2 - 0x200C0602, // 000B NE R3 R3 R2 - 0x780E0004, // 000C JMPF R3 #0012 - 0x8C0C0103, // 000D GETMET R3 R0 K3 - 0x54160044, // 000E LDINT R5 69 - 0x58180004, // 000F LDCONST R6 K4 - 0x7C0C0600, // 0010 CALL R3 3 - 0x90020402, // 0011 SETMBR R0 K2 R2 - 0x600C0003, // 0012 GETGBL R3 G3 - 0x5C100000, // 0013 MOVE R4 R0 - 0x7C0C0200, // 0014 CALL R3 1 - 0x8C0C0705, // 0015 GETMET R3 R3 K5 - 0x5C140200, // 0016 MOVE R5 R1 - 0x7C0C0400, // 0017 CALL R3 2 - 0x80000000, // 0018 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: -********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_Contact__X3Clambda_X3E, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(_X3Clambda_X3E), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x60040009, // 0000 GETGBL R1 G9 - 0x5C080000, // 0001 MOVE R2 R0 - 0x7C040200, // 0002 CALL R1 1 - 0x80040200, // 0003 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_Contact_init, /* name */ - be_nested_proto( - 9, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(init), - /* K1 */ be_nested_str_weak(shadow_contact), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[11]) { /* code */ - 0x60100003, // 0000 GETGBL R4 G3 - 0x5C140000, // 0001 MOVE R5 R0 - 0x7C100200, // 0002 CALL R4 1 - 0x8C100900, // 0003 GETMET R4 R4 K0 - 0x5C180200, // 0004 MOVE R6 R1 - 0x5C1C0400, // 0005 MOVE R7 R2 - 0x5C200600, // 0006 MOVE R8 R3 - 0x7C100800, // 0007 CALL R4 4 - 0x50100000, // 0008 LDBOOL R4 0 0 - 0x90020204, // 0009 SETMBR R0 K1 R4 - 0x80000000, // 000A RET 0 + ( &(const binstruction[12]) { /* code */ + 0x60080009, // 0000 GETGBL R2 G9 + 0x8C0C0301, // 0001 GETMET R3 R1 K1 + 0x88140102, // 0002 GETMBR R5 R0 K2 + 0x58180003, // 0003 LDCONST R6 K3 + 0x7C0C0600, // 0004 CALL R3 3 + 0x7C080200, // 0005 CALL R2 1 + 0x90020002, // 0006 SETMBR R0 K0 R2 + 0x88080100, // 0007 GETMBR R2 R0 K0 + 0x18080504, // 0008 LE R2 R2 K4 + 0x780A0000, // 0009 JMPF R2 #000B + 0x90020103, // 000A SETMBR R0 K0 K3 + 0x80000000, // 000B RET 0 }) ) ); @@ -369,6 +281,61 @@ be_local_closure(Matter_Plugin_Sensor_Contact_read_attribute, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: update_virtual +********************************************************************/ +be_local_closure(Matter_Plugin_Sensor_Contact_update_virtual, /* name */ + be_nested_proto( + 7, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(find), + /* K1 */ be_nested_str_weak(Contact), + /* K2 */ be_nested_str_weak(shadow_contact), + /* K3 */ be_nested_str_weak(attribute_updated), + /* K4 */ be_const_int(0), + /* K5 */ be_nested_str_weak(update_virtual), + }), + be_str_weak(update_virtual), + &be_const_str_solidified, + ( &(const binstruction[25]) { /* code */ + 0x8C080300, // 0000 GETMET R2 R1 K0 + 0x58100001, // 0001 LDCONST R4 K1 + 0x7C080400, // 0002 CALL R2 2 + 0x4C0C0000, // 0003 LDNIL R3 + 0x200C0403, // 0004 NE R3 R2 R3 + 0x780E000B, // 0005 JMPF R3 #0012 + 0x600C0017, // 0006 GETGBL R3 G23 + 0x5C100400, // 0007 MOVE R4 R2 + 0x7C0C0200, // 0008 CALL R3 1 + 0x5C080600, // 0009 MOVE R2 R3 + 0x880C0102, // 000A GETMBR R3 R0 K2 + 0x200C0602, // 000B NE R3 R3 R2 + 0x780E0004, // 000C JMPF R3 #0012 + 0x8C0C0103, // 000D GETMET R3 R0 K3 + 0x54160044, // 000E LDINT R5 69 + 0x58180004, // 000F LDCONST R6 K4 + 0x7C0C0600, // 0010 CALL R3 3 + 0x90020402, // 0011 SETMBR R0 K2 R2 + 0x600C0003, // 0012 GETGBL R3 G3 + 0x5C100000, // 0013 MOVE R4 R0 + 0x7C0C0200, // 0014 CALL R3 1 + 0x8C0C0705, // 0015 GETMET R3 R3 K5 + 0x5C140200, // 0016 MOVE R5 R1 + 0x7C0C0400, // 0017 CALL R3 2 + 0x80000000, // 0018 RET 0 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified class: Matter_Plugin_Sensor_Contact ********************************************************************/ @@ -376,22 +343,29 @@ extern const bclass be_class_Matter_Plugin_Device; be_local_class(Matter_Plugin_Sensor_Contact, 2, &be_class_Matter_Plugin_Device, - be_nested_map(17, + be_nested_map(16, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(read_attribute, 12), be_const_closure(Matter_Plugin_Sensor_Contact_read_attribute_closure) }, - { be_const_key_weak(append_state_json, -1), be_const_closure(Matter_Plugin_Sensor_Contact_append_state_json_closure) }, + { be_const_key_weak(ARG_TYPE, 4), be_const_static_closure(Matter_Plugin_Sensor_Contact__X3Clambda_X3E_closure) }, { be_const_key_weak(ARG_HINT, -1), be_nested_str_weak(Switch_X3Cx_X3E_X20number) }, + { be_const_key_weak(shadow_contact, -1), be_const_var(1) }, { be_const_key_weak(init, -1), be_const_closure(Matter_Plugin_Sensor_Contact_init_closure) }, - { be_const_key_weak(TYPES, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { + { be_const_key_weak(update_virtual, -1), be_const_closure(Matter_Plugin_Sensor_Contact_update_virtual_closure) }, + { be_const_key_weak(update_shadow, 15), be_const_closure(Matter_Plugin_Sensor_Contact_update_shadow_closure) }, + { be_const_key_weak(UPDATE_COMMANDS, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + be_const_list( * be_nested_list(1, + ( (struct bvalue*) &(const bvalue[]) { + be_nested_str_weak(Contact), + })) ) } )) }, + { be_const_key_weak(ARG, 6), be_nested_str_weak(switch) }, + { be_const_key_weak(UPDATE_TIME, -1), be_const_int(750) }, + { be_const_key_weak(DISPLAY_NAME, -1), be_nested_str_weak(Contact) }, + { be_const_key_weak(tasmota_switch_index, 11), be_const_var(0) }, + { be_const_key_weak(TYPES, 12), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { be_const_map( * be_nested_map(1, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(21, -1), be_const_int(1) }, })) ) } )) }, - { be_const_key_weak(parse_configuration, -1), be_const_closure(Matter_Plugin_Sensor_Contact_parse_configuration_closure) }, - { be_const_key_weak(shadow_contact, 16), be_const_var(1) }, - { be_const_key_weak(update_virtual, -1), be_const_closure(Matter_Plugin_Sensor_Contact_update_virtual_closure) }, - { be_const_key_weak(ARG, 7), be_nested_str_weak(switch) }, - { be_const_key_weak(CLUSTERS, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { + { be_const_key_weak(CLUSTERS, 14), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { @@ -449,17 +423,9 @@ be_local_class(Matter_Plugin_Sensor_Contact, be_const_int(65533), })) ) } )) }, })) ) } )) }, - { be_const_key_weak(tasmota_switch_index, -1), be_const_var(0) }, - { be_const_key_weak(DISPLAY_NAME, 0), be_nested_str_weak(Contact) }, - { be_const_key_weak(ARG_TYPE, 13), be_const_static_closure(Matter_Plugin_Sensor_Contact__X3Clambda_X3E_closure) }, - { be_const_key_weak(UPDATE_TIME, -1), be_const_int(750) }, - { be_const_key_weak(TYPE, -1), be_nested_str_weak(contact) }, - { be_const_key_weak(UPDATE_COMMANDS, 3), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(1, - ( (struct bvalue*) &(const bvalue[]) { - be_nested_str_weak(Contact), - })) ) } )) }, - { be_const_key_weak(update_shadow, -1), be_const_closure(Matter_Plugin_Sensor_Contact_update_shadow_closure) }, + { be_const_key_weak(TYPE, 9), be_nested_str_weak(contact) }, + { be_const_key_weak(read_attribute, -1), be_const_closure(Matter_Plugin_Sensor_Contact_read_attribute_closure) }, + { be_const_key_weak(parse_configuration, -1), be_const_closure(Matter_Plugin_Sensor_Contact_parse_configuration_closure) }, })), be_str_weak(Matter_Plugin_Sensor_Contact) ); diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Occupancy.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Occupancy.h index b88b02bd3..a26bb32ad 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Occupancy.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Occupancy.h @@ -7,32 +7,26 @@ extern const bclass be_class_Matter_Plugin_Sensor_Occupancy; /******************************************************************** -** Solidified function: append_state_json +** Solidified function: ********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_Occupancy_append_state_json, /* name */ +be_local_closure(Matter_Plugin_Sensor_Occupancy__X3Clambda_X3E, /* name */ be_nested_proto( - 5, /* nstack */ + 3, /* nstack */ 1, /* argc */ - 2, /* varg */ + 0, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(_X2C_X22Occupancy_X22_X3A_X25s), - /* K1 */ be_nested_str_weak(shadow_occupancy), - }), - be_str_weak(append_state_json), + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(_X3Clambda_X3E), &be_const_str_solidified, - ( &(const binstruction[ 7]) { /* code */ - 0x60040018, // 0000 GETGBL R1 G24 - 0x58080000, // 0001 LDCONST R2 K0 - 0x600C0009, // 0002 GETGBL R3 G9 - 0x88100101, // 0003 GETMBR R4 R0 K1 - 0x7C0C0200, // 0004 CALL R3 1 - 0x7C040400, // 0005 CALL R1 2 - 0x80040200, // 0006 RET 1 R1 + ( &(const binstruction[ 4]) { /* code */ + 0x60040009, // 0000 GETGBL R1 G9 + 0x5C080000, // 0001 MOVE R2 R0 + 0x7C040200, // 0002 CALL R1 1 + 0x80040200, // 0003 RET 1 R1 }) ) ); @@ -40,9 +34,9 @@ be_local_closure(Matter_Plugin_Sensor_Occupancy_append_state_json, /* name */ /******************************************************************** -** Solidified function: parse_configuration +** Solidified function: update_virtual ********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_Occupancy_parse_configuration, /* name */ +be_local_closure(Matter_Plugin_Sensor_Occupancy_update_virtual, /* name */ be_nested_proto( 7, /* nstack */ 2, /* argc */ @@ -52,28 +46,79 @@ be_local_closure(Matter_Plugin_Sensor_Occupancy_parse_configuration, /* name * 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(tasmota_switch_index), - /* K1 */ be_nested_str_weak(find), - /* K2 */ be_nested_str_weak(ARG), - /* K3 */ be_const_int(1), + ( &(const bvalue[ 6]) { /* constants */ + /* K0 */ be_nested_str_weak(find), + /* K1 */ be_nested_str_weak(Occupancy), + /* K2 */ be_nested_str_weak(shadow_occupancy), + /* K3 */ be_nested_str_weak(attribute_updated), /* K4 */ be_const_int(0), + /* K5 */ be_nested_str_weak(update_virtual), }), - be_str_weak(parse_configuration), + be_str_weak(update_virtual), &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x60080009, // 0000 GETGBL R2 G9 - 0x8C0C0301, // 0001 GETMET R3 R1 K1 - 0x88140102, // 0002 GETMBR R5 R0 K2 - 0x58180003, // 0003 LDCONST R6 K3 - 0x7C0C0600, // 0004 CALL R3 3 - 0x7C080200, // 0005 CALL R2 1 - 0x90020002, // 0006 SETMBR R0 K0 R2 - 0x88080100, // 0007 GETMBR R2 R0 K0 - 0x18080504, // 0008 LE R2 R2 K4 - 0x780A0000, // 0009 JMPF R2 #000B - 0x90020103, // 000A SETMBR R0 K0 K3 - 0x80000000, // 000B RET 0 + ( &(const binstruction[25]) { /* code */ + 0x8C080300, // 0000 GETMET R2 R1 K0 + 0x58100001, // 0001 LDCONST R4 K1 + 0x7C080400, // 0002 CALL R2 2 + 0x4C0C0000, // 0003 LDNIL R3 + 0x200C0403, // 0004 NE R3 R2 R3 + 0x780E000B, // 0005 JMPF R3 #0012 + 0x600C0017, // 0006 GETGBL R3 G23 + 0x5C100400, // 0007 MOVE R4 R2 + 0x7C0C0200, // 0008 CALL R3 1 + 0x5C080600, // 0009 MOVE R2 R3 + 0x880C0102, // 000A GETMBR R3 R0 K2 + 0x200C0602, // 000B NE R3 R3 R2 + 0x780E0004, // 000C JMPF R3 #0012 + 0x8C0C0103, // 000D GETMET R3 R0 K3 + 0x54160405, // 000E LDINT R5 1030 + 0x58180004, // 000F LDCONST R6 K4 + 0x7C0C0600, // 0010 CALL R3 3 + 0x90020402, // 0011 SETMBR R0 K2 R2 + 0x600C0003, // 0012 GETGBL R3 G3 + 0x5C100000, // 0013 MOVE R4 R0 + 0x7C0C0200, // 0014 CALL R3 1 + 0x8C0C0705, // 0015 GETMET R3 R3 K5 + 0x5C140200, // 0016 MOVE R5 R1 + 0x7C0C0400, // 0017 CALL R3 2 + 0x80000000, // 0018 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: init +********************************************************************/ +be_local_closure(Matter_Plugin_Sensor_Occupancy_init, /* name */ + be_nested_proto( + 9, /* nstack */ + 4, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(init), + /* K1 */ be_nested_str_weak(shadow_occupancy), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[11]) { /* code */ + 0x60100003, // 0000 GETGBL R4 G3 + 0x5C140000, // 0001 MOVE R5 R0 + 0x7C100200, // 0002 CALL R4 1 + 0x8C100900, // 0003 GETMET R4 R4 K0 + 0x5C180200, // 0004 MOVE R6 R1 + 0x5C1C0400, // 0005 MOVE R7 R2 + 0x5C200600, // 0006 MOVE R8 R3 + 0x7C100800, // 0007 CALL R4 4 + 0x50100000, // 0008 LDBOOL R4 0 0 + 0x90020204, // 0009 SETMBR R0 K1 R4 + 0x80000000, // 000A RET 0 }) ) ); @@ -162,9 +207,9 @@ be_local_closure(Matter_Plugin_Sensor_Occupancy_update_shadow, /* name */ /******************************************************************** -** Solidified function: update_virtual +** Solidified function: parse_configuration ********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_Occupancy_update_virtual, /* name */ +be_local_closure(Matter_Plugin_Sensor_Occupancy_parse_configuration, /* name */ be_nested_proto( 7, /* nstack */ 2, /* argc */ @@ -174,106 +219,28 @@ be_local_closure(Matter_Plugin_Sensor_Occupancy_update_virtual, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 6]) { /* constants */ - /* K0 */ be_nested_str_weak(find), - /* K1 */ be_nested_str_weak(Occupancy), - /* K2 */ be_nested_str_weak(shadow_occupancy), - /* K3 */ be_nested_str_weak(attribute_updated), + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(tasmota_switch_index), + /* K1 */ be_nested_str_weak(find), + /* K2 */ be_nested_str_weak(ARG), + /* K3 */ be_const_int(1), /* K4 */ be_const_int(0), - /* K5 */ be_nested_str_weak(update_virtual), }), - be_str_weak(update_virtual), + be_str_weak(parse_configuration), &be_const_str_solidified, - ( &(const binstruction[25]) { /* code */ - 0x8C080300, // 0000 GETMET R2 R1 K0 - 0x58100001, // 0001 LDCONST R4 K1 - 0x7C080400, // 0002 CALL R2 2 - 0x4C0C0000, // 0003 LDNIL R3 - 0x200C0403, // 0004 NE R3 R2 R3 - 0x780E000B, // 0005 JMPF R3 #0012 - 0x600C0017, // 0006 GETGBL R3 G23 - 0x5C100400, // 0007 MOVE R4 R2 - 0x7C0C0200, // 0008 CALL R3 1 - 0x5C080600, // 0009 MOVE R2 R3 - 0x880C0102, // 000A GETMBR R3 R0 K2 - 0x200C0602, // 000B NE R3 R3 R2 - 0x780E0004, // 000C JMPF R3 #0012 - 0x8C0C0103, // 000D GETMET R3 R0 K3 - 0x54160405, // 000E LDINT R5 1030 - 0x58180004, // 000F LDCONST R6 K4 - 0x7C0C0600, // 0010 CALL R3 3 - 0x90020402, // 0011 SETMBR R0 K2 R2 - 0x600C0003, // 0012 GETGBL R3 G3 - 0x5C100000, // 0013 MOVE R4 R0 - 0x7C0C0200, // 0014 CALL R3 1 - 0x8C0C0705, // 0015 GETMET R3 R3 K5 - 0x5C140200, // 0016 MOVE R5 R1 - 0x7C0C0400, // 0017 CALL R3 2 - 0x80000000, // 0018 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: -********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_Occupancy__X3Clambda_X3E, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(_X3Clambda_X3E), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x60040009, // 0000 GETGBL R1 G9 - 0x5C080000, // 0001 MOVE R2 R0 - 0x7C040200, // 0002 CALL R1 1 - 0x80040200, // 0003 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Matter_Plugin_Sensor_Occupancy_init, /* name */ - be_nested_proto( - 9, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(init), - /* K1 */ be_nested_str_weak(shadow_occupancy), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[11]) { /* code */ - 0x60100003, // 0000 GETGBL R4 G3 - 0x5C140000, // 0001 MOVE R5 R0 - 0x7C100200, // 0002 CALL R4 1 - 0x8C100900, // 0003 GETMET R4 R4 K0 - 0x5C180200, // 0004 MOVE R6 R1 - 0x5C1C0400, // 0005 MOVE R7 R2 - 0x5C200600, // 0006 MOVE R8 R3 - 0x7C100800, // 0007 CALL R4 4 - 0x50100000, // 0008 LDBOOL R4 0 0 - 0x90020204, // 0009 SETMBR R0 K1 R4 - 0x80000000, // 000A RET 0 + ( &(const binstruction[12]) { /* code */ + 0x60080009, // 0000 GETGBL R2 G9 + 0x8C0C0301, // 0001 GETMET R3 R1 K1 + 0x88140102, // 0002 GETMBR R5 R0 K2 + 0x58180003, // 0003 LDCONST R6 K3 + 0x7C0C0600, // 0004 CALL R3 3 + 0x7C080200, // 0005 CALL R2 1 + 0x90020002, // 0006 SETMBR R0 K0 R2 + 0x88080100, // 0007 GETMBR R2 R0 K0 + 0x18080504, // 0008 LE R2 R2 K4 + 0x780A0000, // 0009 JMPF R2 #000B + 0x90020103, // 000A SETMBR R0 K0 K3 + 0x80000000, // 000B RET 0 }) ) ); @@ -394,22 +361,18 @@ extern const bclass be_class_Matter_Plugin_Device; be_local_class(Matter_Plugin_Sensor_Occupancy, 2, &be_class_Matter_Plugin_Device, - be_nested_map(17, + be_nested_map(16, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(read_attribute, 12), be_const_closure(Matter_Plugin_Sensor_Occupancy_read_attribute_closure) }, - { be_const_key_weak(append_state_json, -1), be_const_closure(Matter_Plugin_Sensor_Occupancy_append_state_json_closure) }, + { be_const_key_weak(ARG_TYPE, 2), be_const_static_closure(Matter_Plugin_Sensor_Occupancy__X3Clambda_X3E_closure) }, { be_const_key_weak(ARG_HINT, -1), be_nested_str_weak(Switch_X3Cx_X3E_X20number) }, + { be_const_key_weak(update_virtual, -1), be_const_closure(Matter_Plugin_Sensor_Occupancy_update_virtual_closure) }, { be_const_key_weak(init, -1), be_const_closure(Matter_Plugin_Sensor_Occupancy_init_closure) }, - { be_const_key_weak(TYPES, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { - be_const_map( * be_nested_map(1, - ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_int(263, -1), be_const_int(2) }, - })) ) } )) }, - { be_const_key_weak(parse_configuration, -1), be_const_closure(Matter_Plugin_Sensor_Occupancy_parse_configuration_closure) }, - { be_const_key_weak(update_shadow, -1), be_const_closure(Matter_Plugin_Sensor_Occupancy_update_shadow_closure) }, + { be_const_key_weak(tasmota_switch_index, 9), be_const_var(0) }, + { be_const_key_weak(update_shadow, 14), be_const_closure(Matter_Plugin_Sensor_Occupancy_update_shadow_closure) }, { be_const_key_weak(DISPLAY_NAME, -1), be_nested_str_weak(Occupancy) }, - { be_const_key_weak(ARG, 16), be_nested_str_weak(switch) }, - { be_const_key_weak(CLUSTERS, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { + { be_const_key_weak(ARG, 12), be_nested_str_weak(switch) }, + { be_const_key_weak(UPDATE_TIME, -1), be_const_int(750) }, + { be_const_key_weak(CLUSTERS, 11), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { @@ -469,17 +432,20 @@ be_local_class(Matter_Plugin_Sensor_Occupancy, be_const_int(65533), })) ) } )) }, })) ) } )) }, - { be_const_key_weak(tasmota_switch_index, -1), be_const_var(0) }, - { be_const_key_weak(UPDATE_TIME, 0), be_const_int(750) }, - { be_const_key_weak(shadow_occupancy, 13), be_const_var(1) }, - { be_const_key_weak(ARG_TYPE, 7), be_const_static_closure(Matter_Plugin_Sensor_Occupancy__X3Clambda_X3E_closure) }, - { be_const_key_weak(TYPE, -1), be_nested_str_weak(occupancy) }, - { be_const_key_weak(UPDATE_COMMANDS, 3), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + { be_const_key_weak(read_attribute, 4), be_const_closure(Matter_Plugin_Sensor_Occupancy_read_attribute_closure) }, + { be_const_key_weak(TYPES, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { + be_const_map( * be_nested_map(1, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_int(263, -1), be_const_int(2) }, + })) ) } )) }, + { be_const_key_weak(UPDATE_COMMANDS, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { be_const_list( * be_nested_list(1, ( (struct bvalue*) &(const bvalue[]) { be_nested_str_weak(Occupancy), })) ) } )) }, - { be_const_key_weak(update_virtual, -1), be_const_closure(Matter_Plugin_Sensor_Occupancy_update_virtual_closure) }, + { be_const_key_weak(TYPE, 6), be_nested_str_weak(occupancy) }, + { be_const_key_weak(parse_configuration, -1), be_const_closure(Matter_Plugin_Sensor_Occupancy_parse_configuration_closure) }, + { be_const_key_weak(shadow_occupancy, -1), be_const_var(1) }, })), be_str_weak(Matter_Plugin_Sensor_Occupancy) ); From f06a8b2bdbfceb279488e81a7eb6c9fc5f5b3026 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Wed, 7 Feb 2024 20:58:56 -0800 Subject: [PATCH 285/303] Matter fix configuration loading (#20677) From b02de6de6f200a754574ea600d49db92bf3f0567 Mon Sep 17 00:00:00 2001 From: Christian Baars Date: Thu, 8 Feb 2024 11:31:48 +0100 Subject: [PATCH 286/303] add BLE.info() (#20682) --- lib/libesp32/berry_tasmota/src/be_MI32_lib.c | 3 ++ tasmota/include/xsns_62_esp32_mi.h | 5 +++ .../xdrv_52_3_berry_MI32.ino | 44 +++++++++++++++++++ .../tasmota_xsns_sensor/xsns_62_esp32_mi.ino | 1 - 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/lib/libesp32/berry_tasmota/src/be_MI32_lib.c b/lib/libesp32/berry_tasmota/src/be_MI32_lib.c index 3cddb77dc..5078de941 100644 --- a/lib/libesp32/berry_tasmota/src/be_MI32_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_MI32_lib.c @@ -46,6 +46,8 @@ module MI32 (scope: global) { extern int be_BLE_init(bvm *vm); +extern int be_BLE_info(bvm *vm); + extern void be_BLE_loop(void); BE_FUNC_CTYPE_DECLARE(be_BLE_loop, "", ""); @@ -83,6 +85,7 @@ BE_FUNC_CTYPE_DECLARE(be_BLE_adv_block, "", "@(bytes)~[i]"); module BLE (scope: global) { init, func(be_BLE_init) loop, ctype_func(be_BLE_loop) + info, func(be_BLE_info) conn_cb, ctype_func(be_BLE_reg_conn_cb) set_svc, ctype_func(be_BLE_set_service) run, ctype_func(be_BLE_run) diff --git a/tasmota/include/xsns_62_esp32_mi.h b/tasmota/include/xsns_62_esp32_mi.h index 2b9ec9e99..2d010270d 100644 --- a/tasmota/include/xsns_62_esp32_mi.h +++ b/tasmota/include/xsns_62_esp32_mi.h @@ -18,6 +18,11 @@ */ #ifdef USE_MI_ESP32 + +#pragma once + +#include + /*********************************************************************************************\ * structs and types \*********************************************************************************************/ diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_MI32.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_MI32.ino index eab484c2b..b836b7c3b 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_MI32.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_MI32.ino @@ -24,6 +24,8 @@ #if defined(USE_MI_ESP32) && !defined(USE_BLE_ESP32) +#include "include/xsns_62_esp32_mi.h" + /*********************************************************************************************\ * Native functions mapped to Berry functions * @@ -206,6 +208,48 @@ extern "C" { be_raisef(vm, "ble_error", "BLE: could not add MAC to watch list"); } + // BLE.info(void) -> map + int32_t be_BLE_info(struct bvm *vm); + int32_t be_BLE_info(struct bvm *vm) { + be_newobject(vm, "map"); + char _Role[16]; + GetTextIndexed(_Role, sizeof(_Role), MI32.role, HTTP_MI32_PARENT_BLE_ROLE); + char _role[16]; + LowerCase(_role,_Role); + be_map_insert_str(vm, "role", _role); + be_map_insert_str(vm, "local_addr", NimBLEDevice::toString().c_str()); + be_map_insert_int(vm, "power", NimBLEDevice::getPower()); + be_map_insert_int(vm, "MTU", NimBLEDevice::getMTU()); +#ifdef CONFIG_BT_NIMBLE_EXT_ADV // TODO - BLE 5 is very unsharp + be_map_insert_int(vm, "version", 5); +#else + be_map_insert_int(vm, "version", 4); +#endif +#ifdef CONFIG_BT_NIMBLE_PERSIST + be_map_insert_int(vm, "bonds", NimBLEDevice::getNumBonds()); +#else + be_map_insert_nil(vm, "bonds"); +#endif + if(MI32.mode.connected == 1){ + be_pushstring(vm, "connection"); + be_newobject(vm, "map"); + auto _info = NimBLEDevice::getClientList()->front()->getConnInfo(); + be_map_insert_str(vm, "peer_addr", _info.getAddress().toString().c_str()); + be_map_insert_int(vm, "RSSI", NimBLEDevice::getClientList()->front()->getRssi()); + be_map_insert_int(vm, "MTU", _info.getMTU()); + be_map_insert_bool(vm, "bonded", _info.isBonded()); + be_map_insert_bool(vm, "master", _info.isMaster()); + be_map_insert_bool(vm, "encrypted", _info.isEncrypted()); + be_map_insert_bool(vm, "authenticated", _info.isAuthenticated()); + + be_pop(vm, 1); + be_data_insert(vm, -3); + be_pop(vm, 2); + } + + be_pop(vm, 1); + be_return(vm); + } } //extern "C" diff --git a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino index 1dfa9d217..40878f001 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_62_esp32_mi.ino @@ -60,7 +60,6 @@ #define XSNS_62 62 -#include // undefine "trash" from the NimBLE stack, that collides with Tasmotas enum #undef LOG_LEVEL_DEBUG #undef LOG_LEVEL_NONE From 7d698a6752e735a791c988550214da3403e4ccb2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 8 Feb 2024 11:36:03 +0100 Subject: [PATCH 287/303] Update changelogs --- CHANGELOG.md | 3 ++- RELEASENOTES.md | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfb1f718f..aaa2e3bb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,13 @@ All notable changes to this project will be documented in this file. ## [13.3.0.5] ### Added - Internal support for persistent JSON settings using single file +- Command ``SetOption158`` to publish or suppress ModbusReceived MQTT messages (#20678) ### Breaking Changed - ESP32 LVGL library from v8.3.11 to v9.0.0, some small breaking changes in C, none in HASPmota (#20659) ### Changed -- Matter improve `MtrInfo` +- Matter improve `MtrInfo` (#20686) ### Fixed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 935f227c8..a10bf4647 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -119,6 +119,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ## Changelog v13.3.0.5 ### Added - Command ``TimedPower [,ON|OFF|TOGGLE|BLINK]`` executes ``Power [ON|OFF|TOGGLE|BLINK] `` and after executes ``Power [OFF|ON|TOGGLE|OFF]`` +- Command ``SetOption158`` to publish or suppress ModbusReceived MQTT messages [#20678](https://github.com/arendst/Tasmota/issues/20678) - Display of active drivers using command ``status 4`` - GPIO Viewer to see realtime GPIO states. Enable with define USE_GPIO_VIEWER - GPIO Viewer user selection of assets website now defaults to `https://ota.tasmota.com/tasmota|tasmota32/gpio_viewer/assets` @@ -184,6 +185,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Webcam tweaks [#20451](https://github.com/arendst/Tasmota/issues/20451) - IP stack compatible with new Core3 IPv6 implementation [#20509](https://github.com/arendst/Tasmota/issues/20509) - Refactored Pio filesystem download script [#20544](https://github.com/arendst/Tasmota/issues/20544) +- Matter improve `MtrInfo` [#20686](https://github.com/arendst/Tasmota/issues/20686) ### Fixed - CVE-2021-36603 Cross Site Scripting (XSS) vulnerability [#12221](https://github.com/arendst/Tasmota/issues/12221) From 2f0b1e8eddc01933a753cb3cc15eb5713c0c922c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 8 Feb 2024 14:42:58 +0100 Subject: [PATCH 288/303] Update example code --- .../xdrv_122_file_json_settings_demo.ino | 32 +++++++++---------- .../xdrv_50_filesystem.ino | 5 +++ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_122_file_json_settings_demo.ino b/tasmota/tasmota_xdrv_driver/xdrv_122_file_json_settings_demo.ino index 1b61874f0..a6d0c0523 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_122_file_json_settings_demo.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_122_file_json_settings_demo.ino @@ -31,7 +31,6 @@ #warning **** USE_DRV_FILE_JSON_DEMO is enabled **** #define XDRV_122 122 -#define XDRV_KEY "drvset122" #define DRV_DEMO_MAX_DRV_TEXT 16 @@ -53,9 +52,10 @@ struct { * Driver Settings load and save \*********************************************************************************************/ +#define XDRV_122_KEY "drvset122" + bool DrvDemoLoadData(void) { - char key[20]; - snprintf_P(key, sizeof(key), PSTR(XDRV_KEY)); + char key[] = XDRV_122_KEY; String json = UfsJsonSettingsRead(key); if (json.length() == 0) { return false; } @@ -63,19 +63,13 @@ bool DrvDemoLoadData(void) { JsonParserObject root = parser.getRootObject(); if (!root) { return false; } - JsonParserToken val = root[PSTR("Crc")]; - if (val) { - DrvDemoSettings.crc32 = val.getUInt(); - } - val = root[PSTR("Version")]; - if (val) { - DrvDemoSettings.version = val.getInt(); - } + DrvDemoSettings.crc32 = root.getUInt(PSTR("Crc"), DrvDemoSettings.crc32); + DrvDemoSettings.version = root.getUInt(PSTR("Version"), DrvDemoSettings.version); JsonParserArray arr = root[PSTR("Text")]; if (arr) { for (uint32_t i = 0; i < DRV_DEMO_MAX_DRV_TEXT; i++) { if (arr[i]) { - snprintf(DrvDemoSettings.drv_text[i], 10, arr[i].getStr()); + strlcpy(DrvDemoSettings.drv_text[i], arr[i].getStr(), sizeof(DrvDemoSettings.drv_text[0])); } } } @@ -83,17 +77,23 @@ bool DrvDemoLoadData(void) { } bool DrvDemoSaveData(void) { - Response_P(PSTR("{\"" XDRV_KEY "\":{\"Crc\":%u,\"Version\":%u,\"Text\":["), DrvDemoSettings.crc32, DrvDemoSettings.version); + Response_P(PSTR("{\"" XDRV_122_KEY "\":{" + "\"Crc\":%u," + "\"Version\":%u," + "\"Text\":["), + DrvDemoSettings.crc32, + DrvDemoSettings.version); for (uint32_t i = 0; i < DRV_DEMO_MAX_DRV_TEXT; i++) { - ResponseAppend_P(PSTR("%s\"%s\""), (i)?",":"", DrvDemoSettings.drv_text[i]); + ResponseAppend_P(PSTR("%s\"%s\""), + (i)?",":"", + DrvDemoSettings.drv_text[i]); } ResponseAppend_P(PSTR("]}}")); return UfsJsonSettingsWrite(ResponseData()); } void DrvDemoDeleteData(void) { - char key[20]; - snprintf_P(key, sizeof(key), PSTR(XDRV_KEY)); + char key[] = XDRV_122_KEY; UfsJsonSettingsDelete(key); // Use defaults } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino b/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino index 0e5576669..8295cc45a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino @@ -670,6 +670,11 @@ bool UfsJsonSettingsWrite(const char* data) { // Input {"UserSet2":{"Param1":123,"Param2":"Text2"}} // Output 0 = Error, 1 = Append success + String json = data; + JsonParser parser((char*)json.c_str()); + JsonParserObject root = parser.getRootObject(); + if (!root) { return false; } // Error - invalid JSON + char filename[14]; snprintf_P(filename, sizeof(filename), PSTR(TASM_FILE_DRIVER), 0); // /.drvset000 if (!TfsFileExists(filename)) { From 4e7e256892091001230a256391a713cecc60c7f9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 8 Feb 2024 16:45:28 +0100 Subject: [PATCH 289/303] Add ESP32 Core3 support for SPI ethernet on DM9051, W5500 and KSZ8851 --- CHANGELOG.md | 1 + RELEASENOTES.md | 1 + .../xdrv_82_esp32_ethernet.ino | 77 +++++++++---------- 3 files changed, 38 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aaa2e3bb7..b39956120 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - Internal support for persistent JSON settings using single file - Command ``SetOption158`` to publish or suppress ModbusReceived MQTT messages (#20678) +- ESP32 Core3 support for SPI ethernet on DM9051, W5500 and KSZ8851 ### Breaking Changed - ESP32 LVGL library from v8.3.11 to v9.0.0, some small breaking changes in C, none in HASPmota (#20659) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index a10bf4647..134474a39 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -136,6 +136,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - ESP32 MI BLE support for Xiaomi LYWSD02MMC [#20381](https://github.com/arendst/Tasmota/issues/20381) - ESP32 support for Shelly Plus Add-On using DS18x20 or DHT11/AM2301/DHT21/DHT22/AM2302/AM2321/SI7021 on GPIO0/1 [#20580](https://github.com/arendst/Tasmota/issues/20580) - ESP32 MI32 Legacy initial support for sensors using BTHOME packet format [#20625](https://github.com/arendst/Tasmota/issues/20625) +- ESP32 Core3 support for SPI ethernet on DM9051, W5500 and KSZ8851 - ESP32-C3 support for GPIO11 [#18350](https://github.com/arendst/Tasmota/issues/18350) - Berry GPIO viewer initial version using async webserver [#20416](https://github.com/arendst/Tasmota/issues/20416) - Berry `introspect.set()` for class attributes [#20339](https://github.com/arendst/Tasmota/issues/20339) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino b/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino index 63e1d7d51..9ea0e8f89 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino @@ -71,8 +71,11 @@ #endif #ifndef ETH_TYPE -#define ETH_TYPE ETH_PHY_LAN8720 // ETH.h eth_phy_type_t: 0 = ETH_PHY_LAN8720, 1 = ETH_PHY_TLK110/ETH_PHY_IP101, 2 = ETH_PHY_RTL8201, 3 = ETH_PHY_DP83848, 4 = ETH_PHY_DM9051, 5 = ETH_PHY_KSZ8081 - +#if ESP_IDF_VERSION_MAJOR >= 5 +#define ETH_TYPE ETH_PHY_LAN8720 // ETH.h eth_phy_type_t: 0 = ETH_PHY_LAN8720, 1 = ETH_PHY_TLK110/ETH_PHY_IP101, 2 = ETH_PHY_RTL8201, 3 = ETH_PHY_JL1101, 4 = ETH_PHY_DP83848, 5 = ETH_PHY_KSZ8041, 6 = ETH_PHY_KSZ8081, 7 = ETH_PHY_DM9051, 8 = ETH_PHY_W5500, 9 = ETH_PHY_KSZ8851 +#else +#define ETH_TYPE ETH_PHY_LAN8720 // ETH.h eth_phy_type_t: 0 = ETH_PHY_LAN8720, 1 = ETH_PHY_TLK110/ETH_PHY_IP101, 2 = ETH_PHY_RTL8201, 3 = ETH_PHY_DP83848, 4 = ETH_PHY_DM9051, 5 = ETH_PHY_KSZ8041, 6 = ETH_PHY_KSZ8081, 7 = ETH_PHY_JL1101 +#endif #endif #ifndef ETH_CLKMODE @@ -104,11 +107,11 @@ void EthernetEvent(arduino_event_t *event) { while (esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_ETH)) != ESP_OK) { delay(1); if (i-- == 0) { - AddLog(LOG_LEVEL_INFO, ">>>> HELP"); + AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ETH ">>>> HELP")); break; } } - AddLog(LOG_LEVEL_INFO, ">>>> ESP_IF_ETH i=%i", i); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ETH "ESP_IF_ETH i=%i"), i); } #endif // USE_IPV6 @@ -183,12 +186,6 @@ void EthernetSetIp(void) { void EthernetInit(void) { if (!Settings->flag4.network_ethernet) { return; } - if (!PinUsed(GPIO_ETH_PHY_MDC) && !PinUsed(GPIO_ETH_PHY_MDIO)) { - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_ETH "No ETH MDC and/or ETH MDIO GPIO defined")); - return; - } - - eth_config_change = 0; if (WT32_ETH01 == TasmotaGlobal.module_type) { Settings->eth_address = 1; // EthAddress @@ -196,45 +193,43 @@ void EthernetInit(void) { Settings->eth_clk_mode = ETH_CLOCK_GPIO0_IN; // EthClockMode } -// snprintf_P(Eth.hostname, sizeof(Eth.hostname), PSTR("%s-eth"), TasmotaGlobal.hostname); + if (!PinUsed(GPIO_ETH_PHY_MDC) && !PinUsed(GPIO_ETH_PHY_MDIO)) { + if (Settings->eth_type < 7) { + // CONFIG_ETH_USE_ESP32_EMAC + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_ETH "No ETH MDC and ETH MDIO GPIO defined")); + } else { + // CONFIG_ETH_SPI_ETHERNET + if (!PinUsed(GPIO_ETH_PHY_POWER)) { + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_ETH "No ETH MDC (SPI CS), ETH MDIO (SPI IRQ) and ETH POWER (SPI RST) GPIO defined")); + } + } + return; + } + + eth_config_change = 0; + strlcpy(eth_hostname, TasmotaGlobal.hostname, sizeof(eth_hostname) -5); // Make sure there is room for "-eth" strcat(eth_hostname, "-eth"); WiFi.onEvent(EthernetEvent); - int eth_power = Pin(GPIO_ETH_PHY_POWER); - int eth_mdc = Pin(GPIO_ETH_PHY_MDC); - int eth_mdio = Pin(GPIO_ETH_PHY_MDIO); -//#if CONFIG_IDF_TARGET_ESP32 - // fix an disconnection issue after rebooting Olimex POE - this forces a clean state for all GPIO involved in RMII -// gpio_reset_pin((gpio_num_t)GPIO_ETH_PHY_POWER); -// gpio_reset_pin((gpio_num_t)GPIO_ETH_PHY_MDC); -// gpio_reset_pin((gpio_num_t)GPIO_ETH_PHY_MDIO); -// gpio_reset_pin(GPIO_NUM_19); // EMAC_TXD0 - hardcoded -// gpio_reset_pin(GPIO_NUM_21); // EMAC_TX_EN - hardcoded -// gpio_reset_pin(GPIO_NUM_22); // EMAC_TXD1 - hardcoded -// gpio_reset_pin(GPIO_NUM_25); // EMAC_RXD0 - hardcoded -// gpio_reset_pin(GPIO_NUM_26); // EMAC_RXD1 - hardcoded -// gpio_reset_pin(GPIO_NUM_27); // EMAC_RX_CRS_DV - hardcoded -// switch (Settings->eth_clk_mode) { -// case 0: // ETH_CLOCK_GPIO0_IN -// case 1: // ETH_CLOCK_GPIO0_OUT -// gpio_reset_pin(GPIO_NUM_0); -// break; -// case 2: // ETH_CLOCK_GPIO16_OUT -// gpio_reset_pin(GPIO_NUM_16); -// break; -// case 3: // ETH_CLOCK_GPIO17_OUT -// gpio_reset_pin(GPIO_NUM_17); -// break; -// } -// delay(1); -//#endif // CONFIG_IDF_TARGET_ESP32 + int eth_mdc = Pin(GPIO_ETH_PHY_MDC); // Ethernet SPI CS (chip select) + int eth_mdio = Pin(GPIO_ETH_PHY_MDIO); // Ethernet SPI IRQ + int eth_power = Pin(GPIO_ETH_PHY_POWER); // Ethernet SPI RST + + bool init_ok = false; #if ESP_IDF_VERSION_MAJOR >= 5 - if (!ETH.begin( (eth_phy_type_t)Settings->eth_type, Settings->eth_address, eth_mdc, eth_mdio, eth_power, (eth_clock_mode_t)Settings->eth_clk_mode)) { + if (Settings->eth_type < 7) { + // CONFIG_ETH_USE_ESP32_EMAC + init_ok = (ETH.begin((eth_phy_type_t)Settings->eth_type, Settings->eth_address, eth_mdc, eth_mdio, eth_power, (eth_clock_mode_t)Settings->eth_clk_mode)); + } else { + // CONFIG_ETH_SPI_ETHERNET + init_ok = (ETH.begin((eth_phy_type_t)Settings->eth_type, Settings->eth_address, eth_mdc, eth_mdio, eth_power, SPI, ETH_PHY_SPI_FREQ_MHZ)); + } #else - if (!ETH.begin(Settings->eth_address, eth_power, eth_mdc, eth_mdio, (eth_phy_type_t)Settings->eth_type, (eth_clock_mode_t)Settings->eth_clk_mode)) { + init_ok = (ETH.begin(Settings->eth_address, eth_power, eth_mdc, eth_mdio, (eth_phy_type_t)Settings->eth_type, (eth_clock_mode_t)Settings->eth_clk_mode)); #endif + if (!init_ok) { AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_ETH "Bad PHY type or init error")); return; }; From 2f32e3c2ee77d9d6906187eb9db625ba6b17d56a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 9 Feb 2024 13:53:19 +0100 Subject: [PATCH 290/303] Fix C2 compile error --- tasmota/tasmota_support/support_esp32.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/tasmota_support/support_esp32.ino b/tasmota/tasmota_support/support_esp32.ino index 365f4d0f7..017830a5d 100644 --- a/tasmota/tasmota_support/support_esp32.ino +++ b/tasmota/tasmota_support/support_esp32.ino @@ -587,7 +587,7 @@ extern "C" { // `psramFound()` can return true even if no PSRAM is actually installed // This new version also checks `esp_spiram_is_initialized` to know if the PSRAM is initialized bool FoundPSRAM(void) { -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 +#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 return psramFound(); #else #if ESP_IDF_VERSION_MAJOR >= 5 @@ -1053,4 +1053,4 @@ void GpioForceHoldRelay(void) { /********************************************************************************************/ -#endif // ESP32 \ No newline at end of file +#endif // ESP32 From 523a28c39f9fcfa9f53f5d15d748f0ac6f4bcd19 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:54:47 +0100 Subject: [PATCH 291/303] Fix Touch logging --- tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino index 9a82e7eb8..d0a5adc30 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino @@ -234,7 +234,7 @@ bool CST816S_Touch_Init(uint8_t bus, int8_t irq_pin, int8_t rst_pin, int interru I2cReadBuffer(CST816S_address, 0xA7, versionInfo, 3, CST816S_bus); attachInterrupt(irq_pin, []{ CST816S_event_available = true; }, interrupt); CST816S_found = true; - AddLog(LOG_LEVEL_INFO, PSTR("TI: CST816S, version: %d, versionInfo: %d.%d.%d"), version, versionInfo[0], versionInfo[1], versionInfo[2]); + AddLog(LOG_LEVEL_INFO, PSTR("UTI: CST816S, version: %d, versionInfo: %d.%d.%d"), version, versionInfo[0], versionInfo[1], versionInfo[2]); return CST816S_found; } #endif // USE_CST816S @@ -290,10 +290,10 @@ bool FT5206_Touch_Init(TwoWire &i2c) { FT5206_found = false; FT5206_touchp = new FT5206_Class(); if (FT5206_touchp->begin(i2c, FT5206_address)) { - AddLog(LOG_LEVEL_INFO, PSTR("TI: FT5206")); + AddLog(LOG_LEVEL_INFO, PSTR("UTI: FT5206 initialized")); FT5206_found = true; } - //AddLog(LOG_LEVEL_INFO, PSTR("TS: FT5206 %d"),FT5206_found); + //AddLog(LOG_LEVEL_INFO, PSTR("UTI: FT5206 %d"),FT5206_found); return FT5206_found; } @@ -319,10 +319,10 @@ bool GT911_Touch_Init(TwoWire *i2c, int8_t irq_pin, int8_t rst_pin, uint16_t xs, GT911_found = false; GT911_touchp = new GT911(); if (ESP_OK == GT911_touchp->begin(i2c, irq_pin, rst_pin, xs, ys)) { - AddLog(LOG_LEVEL_INFO, PSTR("TI: GT911")); + AddLog(LOG_LEVEL_INFO, PSTR("UTI: GT911 initialized")); GT911_found = true; } else { - AddLog(LOG_LEVEL_INFO, PSTR("TI: GT911 failed")); + AddLog(LOG_LEVEL_INFO, PSTR("UTI: GT911 failed")); } return GT911_found; } From d015ee4679adab53005c614744bbbd79ec840c4d Mon Sep 17 00:00:00 2001 From: Benjamin Nestler <101095581+benjaminnestler@users.noreply.github.com> Date: Fri, 9 Feb 2024 18:36:35 +0100 Subject: [PATCH 292/303] Fixes redirects for Advanced Matter configuration UI (#20690) * CHG: Reload the advanced page after deletion of fabrics. * CHG: Redirect to Matter configuration page from advanced Matter configuration page --- .../berry_matter/src/embedded/Matter_UI.be | 9 +- .../src/solidify/solidified_Matter_UI.h | 149 +++++++++--------- 2 files changed, 79 insertions(+), 79 deletions(-) diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_UI.be b/lib/libesp32/berry_matter/src/embedded/Matter_UI.be index 279d47ad3..32b106050 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_UI.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_UI.be @@ -68,7 +68,7 @@ class Matter_UI # #################################################################################################### # Init web handlers # #################################################################################################### - # Displays a "Autoconf" button on the configuration page + # Displays the Configure Matter button on the configuration page def web_add_config_button() import webserver # webserver.content_send("

") @@ -524,7 +524,8 @@ class Matter_UI self.show_passcode_form() self.show_fabric_info() end - webserver.content_button(webserver.BUTTON_CONFIGURATION) + self.web_add_config_button() + #webserver.content_button(webserver.BUTTON_CONFIGURATION) webserver.content_stop() #- end of web page -# end @@ -812,8 +813,8 @@ class Matter_UI idx += 1 end end - #- reload same page -# - webserver.redirect("/matterc?") + #- reload advanced page -# + webserver.redirect("/mattera?") #---------------------------------------------------------------------# # Reset to default auto-configuration diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_UI.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_UI.h index 8618007f7..0a3b31927 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_UI.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_UI.h @@ -100,7 +100,7 @@ be_local_closure(Matter_UI_page_part_mgr_adv, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ + ( &(const bvalue[10]) { /* constants */ /* K0 */ be_nested_str_weak(webserver), /* K1 */ be_nested_str_weak(check_privileged_access), /* K2 */ be_nested_str_weak(content_start), @@ -109,13 +109,12 @@ be_local_closure(Matter_UI_page_part_mgr_adv, /* name */ /* K5 */ be_nested_str_weak(matter_enabled), /* K6 */ be_nested_str_weak(show_passcode_form), /* K7 */ be_nested_str_weak(show_fabric_info), - /* K8 */ be_nested_str_weak(content_button), - /* K9 */ be_nested_str_weak(BUTTON_CONFIGURATION), - /* K10 */ be_nested_str_weak(content_stop), + /* K8 */ be_nested_str_weak(web_add_config_button), + /* K9 */ be_nested_str_weak(content_stop), }), be_str_weak(page_part_mgr_adv), &be_const_str_solidified, - ( &(const binstruction[24]) { /* code */ + ( &(const binstruction[23]) { /* code */ 0xA4060000, // 0000 IMPORT R1 K0 0x8C080301, // 0001 GETMET R2 R1 K1 0x7C080200, // 0002 CALL R2 1 @@ -134,12 +133,11 @@ be_local_closure(Matter_UI_page_part_mgr_adv, /* name */ 0x7C080200, // 000F CALL R2 1 0x8C080107, // 0010 GETMET R2 R0 K7 0x7C080200, // 0011 CALL R2 1 - 0x8C080308, // 0012 GETMET R2 R1 K8 - 0x88100309, // 0013 GETMBR R4 R1 K9 - 0x7C080400, // 0014 CALL R2 2 - 0x8C08030A, // 0015 GETMET R2 R1 K10 - 0x7C080200, // 0016 CALL R2 1 - 0x80000000, // 0017 RET 0 + 0x8C080108, // 0012 GETMET R2 R0 K8 + 0x7C080200, // 0013 CALL R2 1 + 0x8C080309, // 0014 GETMET R2 R1 K9 + 0x7C080200, // 0015 CALL R2 1 + 0x80000000, // 0016 RET 0 }) ) ); @@ -2195,7 +2193,7 @@ be_local_closure(Matter_UI_page_part_ctl, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[100]) { /* constants */ + ( &(const bvalue[101]) { /* constants */ /* K0 */ be_nested_str_weak(webserver), /* K1 */ be_nested_str_weak(check_privileged_access), /* K2 */ be_nested_str_weak(string), @@ -2243,7 +2241,7 @@ be_local_closure(Matter_UI_page_part_ctl, /* name */ /* K44 */ be_nested_str_weak(get_fabric_index), /* K45 */ be_nested_str_weak(remove_fabric), /* K46 */ be_const_int(1), - /* K47 */ be_nested_str_weak(_X2Fmatterc_X3F), + /* K47 */ be_nested_str_weak(_X2Fmattera_X3F), /* K48 */ be_nested_str_weak(auto), /* K49 */ be_nested_str_weak(plugins_persist), /* K50 */ be_nested_str_weak(config), @@ -2272,30 +2270,31 @@ be_local_closure(Matter_UI_page_part_ctl, /* name */ /* K73 */ be_nested_str_weak(stop_iteration), /* K74 */ be_nested_str_weak(MTR_X3A_X20config_X20_X3D_X20_X25s), /* K75 */ be_nested_str_weak(MTR_X3A_X20config_X20error_X20_X3D_X20_X25s), - /* K76 */ be_nested_str_weak(addep), - /* K77 */ be_nested_str_weak(pi), - /* K78 */ be_nested_str_weak(MTR_X3A_X20add_X20endpoint_X20typ_X3D_X27_X25s_X27_X20arg_X3D_X27_X25s_X27), - /* K79 */ be_nested_str_weak(bridge_add_endpoint), - /* K80 */ be_nested_str_weak(addrem), - /* K81 */ be_nested_str_weak(url), - /* K82 */ be_nested_str_weak(value_error), - /* K83 */ be_nested_str_weak(url_X20shouldn_X27t_X20be_X20null), - /* K84 */ be_nested_str_weak(equal_map), - /* K85 */ be_nested_str_weak(MTR_X3A_X20remote_X20add_X20url_X3D_X27_X25s_X27_X20type_X3D_X27_X25s_X27_X20arg_X3D_X27_X25s_X27), - /* K86 */ be_nested_str_weak(del), - /* K87 */ be_nested_str_weak(bridge_remove_endpoint), - /* K88 */ be_nested_str_weak(content_start), - /* K89 */ be_nested_str_weak(Parameter_X20error), - /* K90 */ be_nested_str_weak(content_send_style), - /* K91 */ be_nested_str_weak(content_send), - /* K92 */ be_nested_str_weak(_X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EError_X3A_X3C_X2Fb_X3E_X25s_X3C_X2Fp_X3E), - /* K93 */ be_nested_str_weak(html_escape), - /* K94 */ be_nested_str_weak(content_button), - /* K95 */ be_nested_str_weak(BUTTON_CONFIGURATION), - /* K96 */ be_nested_str_weak(content_stop), - /* K97 */ be_nested_str_weak(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s), - /* K98 */ be_const_int(2), - /* K99 */ be_nested_str_weak(_X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E), + /* K76 */ be_nested_str_weak(_X2Fmatterc_X3F), + /* K77 */ be_nested_str_weak(addep), + /* K78 */ be_nested_str_weak(pi), + /* K79 */ be_nested_str_weak(MTR_X3A_X20add_X20endpoint_X20typ_X3D_X27_X25s_X27_X20arg_X3D_X27_X25s_X27), + /* K80 */ be_nested_str_weak(bridge_add_endpoint), + /* K81 */ be_nested_str_weak(addrem), + /* K82 */ be_nested_str_weak(url), + /* K83 */ be_nested_str_weak(value_error), + /* K84 */ be_nested_str_weak(url_X20shouldn_X27t_X20be_X20null), + /* K85 */ be_nested_str_weak(equal_map), + /* K86 */ be_nested_str_weak(MTR_X3A_X20remote_X20add_X20url_X3D_X27_X25s_X27_X20type_X3D_X27_X25s_X27_X20arg_X3D_X27_X25s_X27), + /* K87 */ be_nested_str_weak(del), + /* K88 */ be_nested_str_weak(bridge_remove_endpoint), + /* K89 */ be_nested_str_weak(content_start), + /* K90 */ be_nested_str_weak(Parameter_X20error), + /* K91 */ be_nested_str_weak(content_send_style), + /* K92 */ be_nested_str_weak(content_send), + /* K93 */ be_nested_str_weak(_X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EError_X3A_X3C_X2Fb_X3E_X25s_X3C_X2Fp_X3E), + /* K94 */ be_nested_str_weak(html_escape), + /* K95 */ be_nested_str_weak(content_button), + /* K96 */ be_nested_str_weak(BUTTON_CONFIGURATION), + /* K97 */ be_nested_str_weak(content_stop), + /* K98 */ be_nested_str_weak(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s), + /* K99 */ be_const_int(2), + /* K100 */ be_nested_str_weak(_X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E), }), be_str_weak(page_part_ctl), &be_const_str_solidified, @@ -2732,15 +2731,15 @@ be_local_closure(Matter_UI_page_part_ctl, /* name */ 0x8C1C0F13, // 01AD GETMET R7 R7 K19 0x7C1C0200, // 01AE CALL R7 1 0x8C1C0314, // 01AF GETMET R7 R1 K20 - 0x5824002F, // 01B0 LDCONST R9 K47 + 0x5824004C, // 01B0 LDCONST R9 K76 0x7C1C0400, // 01B1 CALL R7 2 0x700200BB, // 01B2 JMP #026F 0x8C180305, // 01B3 GETMET R6 R1 K5 - 0x5820004C, // 01B4 LDCONST R8 K76 + 0x5820004D, // 01B4 LDCONST R8 K77 0x7C180400, // 01B5 CALL R6 2 0x781A002B, // 01B6 JMPF R6 #01E3 0x8C18030E, // 01B7 GETMET R6 R1 K14 - 0x5820004D, // 01B8 LDCONST R8 K77 + 0x5820004E, // 01B8 LDCONST R8 K78 0x7C180400, // 01B9 CALL R6 2 0x8C1C030E, // 01BA GETMET R7 R1 K14 0x5824000E, // 01BB LDCONST R9 K14 @@ -2751,7 +2750,7 @@ be_local_closure(Matter_UI_page_part_ctl, /* name */ 0xB8261000, // 01C0 GETNGBL R9 K8 0x8C241309, // 01C1 GETMET R9 R9 K9 0x602C0018, // 01C2 GETGBL R11 G24 - 0x5830004E, // 01C3 LDCONST R12 K78 + 0x5830004F, // 01C3 LDCONST R12 K79 0x5C340C00, // 01C4 MOVE R13 R6 0x5C380E00, // 01C5 MOVE R14 R7 0x7C2C0600, // 01C6 CALL R11 3 @@ -2775,37 +2774,37 @@ be_local_closure(Matter_UI_page_part_ctl, /* name */ 0x5C3C0E00, // 01D8 MOVE R15 R7 0x7C2C0800, // 01D9 CALL R11 4 0x882C010C, // 01DA GETMBR R11 R0 K12 - 0x8C2C174F, // 01DB GETMET R11 R11 K79 + 0x8C2C1750, // 01DB GETMET R11 R11 K80 0x5C340C00, // 01DC MOVE R13 R6 0x5C381400, // 01DD MOVE R14 R10 0x7C2C0600, // 01DE CALL R11 3 0x8C280314, // 01DF GETMET R10 R1 K20 - 0x5830002F, // 01E0 LDCONST R12 K47 + 0x5830004C, // 01E0 LDCONST R12 K76 0x7C280400, // 01E1 CALL R10 2 0x7002008B, // 01E2 JMP #026F 0x8C180305, // 01E3 GETMET R6 R1 K5 - 0x58200050, // 01E4 LDCONST R8 K80 + 0x58200051, // 01E4 LDCONST R8 K81 0x7C180400, // 01E5 CALL R6 2 0x781A005E, // 01E6 JMPF R6 #0246 0x8C18030E, // 01E7 GETMET R6 R1 K14 - 0x58200051, // 01E8 LDCONST R8 K81 + 0x58200052, // 01E8 LDCONST R8 K82 0x7C180400, // 01E9 CALL R6 2 0x4C1C0000, // 01EA LDNIL R7 0x1C1C0C07, // 01EB EQ R7 R6 R7 0x741E0001, // 01EC JMPT R7 #01EF 0x1C1C0D3A, // 01ED EQ R7 R6 K58 0x781E0000, // 01EE JMPF R7 #01F0 - 0xB006A553, // 01EF RAISE 1 K82 K83 + 0xB006A754, // 01EF RAISE 1 K83 K84 0x581C0029, // 01F0 LDCONST R7 K41 0x60200008, // 01F1 GETGBL R8 G8 0x5C240E00, // 01F2 MOVE R9 R7 0x7C200200, // 01F3 CALL R8 1 0x8C240305, // 01F4 GETMET R9 R1 K5 - 0x002E9A08, // 01F5 ADD R11 K77 R8 + 0x002E9C08, // 01F5 ADD R11 K78 R8 0x7C240400, // 01F6 CALL R9 2 0x78260049, // 01F7 JMPF R9 #0242 0x8C24030E, // 01F8 GETMET R9 R1 K14 - 0x002E9A08, // 01F9 ADD R11 K77 R8 + 0x002E9C08, // 01F9 ADD R11 K78 R8 0x7C240400, // 01FA CALL R9 2 0x8C28030E, // 01FB GETMET R10 R1 K14 0x00321C08, // 01FC ADD R12 K14 R8 @@ -2825,7 +2824,7 @@ be_local_closure(Matter_UI_page_part_ctl, /* name */ 0x78360030, // 020A JMPF R13 #023C 0x60340013, // 020B GETGBL R13 G19 0x7C340000, // 020C CALL R13 0 - 0x9836A206, // 020D SETIDX R13 K81 R6 + 0x9836A406, // 020D SETIDX R13 K82 R6 0x98367209, // 020E SETIDX R13 K57 R9 0x782E0000, // 020F JMPF R11 #0211 0x98368A0B, // 0210 SETIDX R13 K69 R11 @@ -2842,7 +2841,7 @@ be_local_closure(Matter_UI_page_part_ctl, /* name */ 0xA802000B, // 021B EXBLK 0 #0228 0x5C401E00, // 021C MOVE R16 R15 0x7C400000, // 021D CALL R16 0 - 0x8C440154, // 021E GETMET R17 R0 K84 + 0x8C440155, // 021E GETMET R17 R0 K85 0x5C4C2000, // 021F MOVE R19 R16 0x5C501A00, // 0220 MOVE R20 R13 0x7C440600, // 0221 CALL R17 3 @@ -2860,7 +2859,7 @@ be_local_closure(Matter_UI_page_part_ctl, /* name */ 0xB83E1000, // 022D GETNGBL R15 K8 0x8C3C1F09, // 022E GETMET R15 R15 K9 0x60440018, // 022F GETGBL R17 G24 - 0x58480055, // 0230 LDCONST R18 K85 + 0x58480056, // 0230 LDCONST R18 K86 0x5C4C0C00, // 0231 MOVE R19 R6 0x5C501200, // 0232 MOVE R20 R9 0x5C541400, // 0233 MOVE R21 R10 @@ -2868,7 +2867,7 @@ be_local_closure(Matter_UI_page_part_ctl, /* name */ 0x5848000B, // 0235 LDCONST R18 K11 0x7C3C0600, // 0236 CALL R15 3 0x883C010C, // 0237 GETMBR R15 R0 K12 - 0x8C3C1F4F, // 0238 GETMET R15 R15 K79 + 0x8C3C1F50, // 0238 GETMET R15 R15 K80 0x5C441200, // 0239 MOVE R17 R9 0x5C481A00, // 023A MOVE R18 R13 0x7C3C0600, // 023B CALL R15 3 @@ -2879,7 +2878,7 @@ be_local_closure(Matter_UI_page_part_ctl, /* name */ 0x5C201800, // 0240 MOVE R8 R12 0x7001FFB1, // 0241 JMP #01F4 0x8C240314, // 0242 GETMET R9 R1 K20 - 0x582C002F, // 0243 LDCONST R11 K47 + 0x582C004C, // 0243 LDCONST R11 K76 0x7C240400, // 0244 CALL R9 2 0x70020028, // 0245 JMP #026F 0x4C180000, // 0246 LDNIL R6 @@ -2897,7 +2896,7 @@ be_local_closure(Matter_UI_page_part_ctl, /* name */ 0x7C240400, // 0252 CALL R9 2 0x8C280535, // 0253 GETMET R10 R2 K53 0x5C301200, // 0254 MOVE R12 R9 - 0x58340056, // 0255 LDCONST R13 K86 + 0x58340057, // 0255 LDCONST R13 K87 0x7C280600, // 0256 CALL R10 3 0x1C281529, // 0257 EQ R10 R10 K41 0x782A0005, // 0258 JMPF R10 #025F @@ -2917,30 +2916,30 @@ be_local_closure(Matter_UI_page_part_ctl, /* name */ 0x201C0C07, // 0266 NE R7 R6 R7 0x781E0006, // 0267 JMPF R7 #026F 0x881C010C, // 0268 GETMBR R7 R0 K12 - 0x8C1C0F57, // 0269 GETMET R7 R7 K87 + 0x8C1C0F58, // 0269 GETMET R7 R7 K88 0x5C240C00, // 026A MOVE R9 R6 0x7C1C0400, // 026B CALL R7 2 0x8C1C0314, // 026C GETMET R7 R1 K20 - 0x5824002F, // 026D LDCONST R9 K47 + 0x5824004C, // 026D LDCONST R9 K76 0x7C1C0400, // 026E CALL R7 2 0x78160011, // 026F JMPF R5 #0282 - 0x8C180358, // 0270 GETMET R6 R1 K88 - 0x58200059, // 0271 LDCONST R8 K89 + 0x8C180359, // 0270 GETMET R6 R1 K89 + 0x5820005A, // 0271 LDCONST R8 K90 0x7C180400, // 0272 CALL R6 2 - 0x8C18035A, // 0273 GETMET R6 R1 K90 + 0x8C18035B, // 0273 GETMET R6 R1 K91 0x7C180200, // 0274 CALL R6 1 - 0x8C18035B, // 0275 GETMET R6 R1 K91 + 0x8C18035C, // 0275 GETMET R6 R1 K92 0x60200018, // 0276 GETGBL R8 G24 - 0x5824005C, // 0277 LDCONST R9 K92 - 0x8C28035D, // 0278 GETMET R10 R1 K93 + 0x5824005D, // 0277 LDCONST R9 K93 + 0x8C28035E, // 0278 GETMET R10 R1 K94 0x5C300A00, // 0279 MOVE R12 R5 0x7C280400, // 027A CALL R10 2 0x7C200400, // 027B CALL R8 2 0x7C180400, // 027C CALL R6 2 - 0x8C18035E, // 027D GETMET R6 R1 K94 - 0x8820035F, // 027E GETMBR R8 R1 K95 + 0x8C18035F, // 027D GETMET R6 R1 K95 + 0x88200360, // 027E GETMBR R8 R1 K96 0x7C180400, // 027F CALL R6 2 - 0x8C180360, // 0280 GETMET R6 R1 K96 + 0x8C180361, // 0280 GETMET R6 R1 K97 0x7C180200, // 0281 CALL R6 1 0xA8040001, // 0282 EXBLK 1 1 0x7002001D, // 0283 JMP #02A2 @@ -2949,28 +2948,28 @@ be_local_closure(Matter_UI_page_part_ctl, /* name */ 0xB8221000, // 0286 GETNGBL R8 K8 0x8C201109, // 0287 GETMET R8 R8 K9 0x60280018, // 0288 GETGBL R10 G24 - 0x582C0061, // 0289 LDCONST R11 K97 + 0x582C0062, // 0289 LDCONST R11 K98 0x5C300C00, // 028A MOVE R12 R6 0x5C340E00, // 028B MOVE R13 R7 0x7C280600, // 028C CALL R10 3 - 0x582C0062, // 028D LDCONST R11 K98 + 0x582C0063, // 028D LDCONST R11 K99 0x7C200600, // 028E CALL R8 3 - 0x8C200358, // 028F GETMET R8 R1 K88 - 0x58280059, // 0290 LDCONST R10 K89 + 0x8C200359, // 028F GETMET R8 R1 K89 + 0x5828005A, // 0290 LDCONST R10 K90 0x7C200400, // 0291 CALL R8 2 - 0x8C20035A, // 0292 GETMET R8 R1 K90 + 0x8C20035B, // 0292 GETMET R8 R1 K91 0x7C200200, // 0293 CALL R8 1 - 0x8C20035B, // 0294 GETMET R8 R1 K91 + 0x8C20035C, // 0294 GETMET R8 R1 K92 0x60280018, // 0295 GETGBL R10 G24 - 0x582C0063, // 0296 LDCONST R11 K99 + 0x582C0064, // 0296 LDCONST R11 K100 0x5C300C00, // 0297 MOVE R12 R6 0x5C340E00, // 0298 MOVE R13 R7 0x7C280600, // 0299 CALL R10 3 0x7C200400, // 029A CALL R8 2 - 0x8C20035E, // 029B GETMET R8 R1 K94 - 0x8828035F, // 029C GETMBR R10 R1 K95 + 0x8C20035F, // 029B GETMET R8 R1 K95 + 0x88280360, // 029C GETMBR R10 R1 K96 0x7C200400, // 029D CALL R8 2 - 0x8C200360, // 029E GETMET R8 R1 K96 + 0x8C200361, // 029E GETMET R8 R1 K97 0x7C200200, // 029F CALL R8 1 0x70020000, // 02A0 JMP #02A2 0xB0080000, // 02A1 RAISE 2 R0 R0 From 3a44d19e8b3f38c713fe282d6f8c10df1e08ed8f Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 10 Feb 2024 09:13:56 -0800 Subject: [PATCH 293/303] Matter implement auto-attributes (#20694) --- CHANGELOG.md | 1 + .../generate/be_matter_clusters.h | 303 +--- .../berry_matter/src/be_matter_module.c | 44 +- .../src/embedded/Matter_0_Inspect.be | 18 +- .../src/embedded/Matter_Plugin_0.be | 87 +- .../embedded/Matter_Plugin_1_Aggregator.be | 13 +- .../src/embedded/Matter_Plugin_1_Device.be | 24 +- .../src/embedded/Matter_Plugin_1_Root.be | 11 +- .../embedded/Matter_Plugin_2_Bridge_HTTP.be | 7 +- .../src/embedded/Matter_Plugin_2_Light1.be | 15 +- .../src/embedded/Matter_Plugin_2_OnOff.be | 9 +- .../Matter_Plugin_2_Sensor_Contact.be | 9 +- .../Matter_Plugin_2_Sensor_Occupancy.be | 9 +- .../embedded/Matter_Plugin_2_Sensor_OnOff.be | 9 +- .../src/embedded/Matter_Plugin_2_Shutter.be | 10 +- .../embedded/Matter_Plugin_3_Bridge_Light0.be | 9 +- .../Matter_Plugin_3_Bridge_Sensor_Contact.be | 9 +- ...Matter_Plugin_3_Bridge_Sensor_Occupancy.be | 9 +- .../src/embedded/Matter_Plugin_3_Light2.be | 7 +- .../src/embedded/Matter_Plugin_3_Light3.be | 7 +- .../embedded/Matter_Plugin_3_Sensor_Flow.be | 9 +- .../Matter_Plugin_3_Sensor_Humidity.be | 9 +- .../Matter_Plugin_3_Sensor_Illuminance.be | 9 +- .../Matter_Plugin_3_Sensor_Pressure.be | 9 +- .../embedded/Matter_Plugin_3_Sensor_Temp.be | 9 +- .../embedded/Matter_Plugin_3_ShutterTilt.be | 3 +- .../embedded/Matter_Plugin_4_Bridge_Light1.be | 9 +- .../Matter_Plugin_4_Bridge_Sensor_Flow.be | 9 +- .../Matter_Plugin_4_Bridge_Sensor_Humidity.be | 9 +- ...tter_Plugin_4_Bridge_Sensor_Illuminance.be | 9 +- .../Matter_Plugin_4_Bridge_Sensor_Pressure.be | 9 +- .../Matter_Plugin_4_Bridge_Sensor_Temp.be | 9 +- .../embedded/Matter_Plugin_5_Bridge_Light2.be | 9 +- .../embedded/Matter_Plugin_5_Bridge_Light3.be | 10 +- .../solidify/solidified_Matter_0_Inspect.h | 146 +- .../src/solidify/solidified_Matter_Plugin_0.h | 1260 +++++++++-------- .../solidified_Matter_Plugin_1_Aggregator.h | 173 +-- .../solidified_Matter_Plugin_1_Device.h | 496 +++---- .../solidified_Matter_Plugin_1_Root.h | 270 ++-- .../solidified_Matter_Plugin_2_Bridge_HTTP.h | 42 +- .../solidified_Matter_Plugin_2_Light1.h | 206 ++- .../solidified_Matter_Plugin_2_OnOff.h | 85 +- ...olidified_Matter_Plugin_2_Sensor_Contact.h | 86 +- ...idified_Matter_Plugin_2_Sensor_Occupancy.h | 89 +- .../solidified_Matter_Plugin_2_Sensor_OnOff.h | 85 +- .../solidified_Matter_Plugin_2_Shutter.h | 102 +- ...solidified_Matter_Plugin_3_Bridge_Light0.h | 85 +- ...ed_Matter_Plugin_3_Bridge_Sensor_Contact.h | 86 +- ..._Matter_Plugin_3_Bridge_Sensor_Occupancy.h | 89 +- .../solidified_Matter_Plugin_3_Light2.h | 93 +- .../solidified_Matter_Plugin_3_Light3.h | 99 +- .../solidified_Matter_Plugin_3_Sensor_Flow.h | 90 +- ...lidified_Matter_Plugin_3_Sensor_Humidity.h | 90 +- ...ified_Matter_Plugin_3_Sensor_Illuminance.h | 90 +- ...lidified_Matter_Plugin_3_Sensor_Pressure.h | 90 +- .../solidified_Matter_Plugin_3_Sensor_Temp.h | 89 +- .../solidified_Matter_Plugin_3_ShutterTilt.h | 39 +- ...solidified_Matter_Plugin_4_Bridge_Light1.h | 100 +- ...ified_Matter_Plugin_4_Bridge_Sensor_Flow.h | 90 +- ...d_Matter_Plugin_4_Bridge_Sensor_Humidity.h | 90 +- ...atter_Plugin_4_Bridge_Sensor_Illuminance.h | 90 +- ...d_Matter_Plugin_4_Bridge_Sensor_Pressure.h | 90 +- ...ified_Matter_Plugin_4_Bridge_Sensor_Temp.h | 89 +- ...solidified_Matter_Plugin_5_Bridge_Light2.h | 102 +- ...solidified_Matter_Plugin_5_Bridge_Light3.h | 106 +- 65 files changed, 2735 insertions(+), 2733 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b39956120..80f4aecdd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. ### Changed - Matter improve `MtrInfo` (#20686) +- Matter implement auto-attributes ### Fixed diff --git a/lib/libesp32/berry_matter/generate/be_matter_clusters.h b/lib/libesp32/berry_matter/generate/be_matter_clusters.h index ce188476f..390bd2830 100644 --- a/lib/libesp32/berry_matter/generate/be_matter_clusters.h +++ b/lib/libesp32/berry_matter/generate/be_matter_clusters.h @@ -28,11 +28,6 @@ typedef struct { const matter_attribute_t matter_Attributes_0003[] = { { 0x0000, 0, 0x03, "IdentifyTime" }, { 0x0001, 0, 0x02, "IdentifyType" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -44,11 +39,6 @@ const matter_command_t matter_Commands_0003[] = { const matter_attribute_t matter_Attributes_0004[] = { { 0x0000, 0, 0x02, "NameSupport" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -68,11 +58,6 @@ const matter_attribute_t matter_Attributes_0005[] = { { 0x0002, 0, 0x02, "CurrentGroup" }, { 0x0003, 0, 0x02, "SceneValid" }, { 0x0004, 0, 0x02, "NameSupport" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -93,11 +78,6 @@ const matter_attribute_t matter_Attributes_0006[] = { { 0x4001, 0, 0x03, "OnTime" }, { 0x4002, 0, 0x03, "OffWaitTime" }, { 0x4003, 0, 0x03, "StartUpOnOff" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -114,11 +94,6 @@ const matter_command_t matter_Commands_0006[] = { const matter_attribute_t matter_Attributes_0007[] = { { 0x0000, 0, 0x02, "SwitchType" }, { 0x0010, 0, 0x03, "SwitchActions" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -141,11 +116,6 @@ const matter_attribute_t matter_Attributes_0008[] = { { 0x0013, 0, 0x03, "OffTransitionTime" }, { 0x0014, 0, 0x03, "DefaultMoveRate" }, { 0x4000, 0, 0x03, "StartUpCurrentLevel" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -165,11 +135,6 @@ const matter_attribute_t matter_Attributes_000F[] = { { 0x0051, 0, 0x03, "OutOfService" }, { 0x0055, 0, 0x03, "PresentValue" }, { 0x006F, 0, 0x02, "StatusFlags" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -182,11 +147,7 @@ const matter_attribute_t matter_Attributes_001D[] = { { 0x0001, 0, 0x02, "ServerList" }, { 0x0002, 0, 0x02, "ClientList" }, { 0x0003, 0, 0x02, "PartsList" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, + { 0x0004, 0, 0x02, "TagList" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -196,11 +157,6 @@ const matter_command_t matter_Commands_001D[] = { const matter_attribute_t matter_Attributes_001E[] = { { 0x0000, 0, 0x03, "Binding" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -214,11 +170,6 @@ const matter_attribute_t matter_Attributes_001F[] = { { 0x0002, 0, 0x02, "SubjectsPerAccessControlEntry" }, { 0x0003, 0, 0x02, "TargetsPerAccessControlEntry" }, { 0x0004, 0, 0x02, "AccessControlEntriesPerFabric" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -230,11 +181,6 @@ const matter_attribute_t matter_Attributes_0025[] = { { 0x0000, 0, 0x02, "ActionList" }, { 0x0001, 0, 0x02, "EndpointLists" }, { 0x0002, 0, 0x02, "SetupURL" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -275,11 +221,6 @@ const matter_attribute_t matter_Attributes_0028[] = { { 0x0011, 0, 0x02, "Reachable" }, { 0x0012, 0, 0x02, "UniqueID" }, { 0x0013, 0, 0x02, "CapabilityMinima" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -320,10 +261,6 @@ const matter_command_t matter_Commands_002A[] = { const matter_attribute_t matter_Attributes_002B[] = { { 0x0000, 0, 0x03, "ActiveLocale" }, { 0x0001, 0, 0x02, "SupportedLocales" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -335,10 +272,6 @@ const matter_attribute_t matter_Attributes_002C[] = { { 0x0000, 0, 0x03, "HourFormat" }, { 0x0001, 0, 0x03, "ActiveCalendarType" }, { 0x0002, 0, 0x02, "SupportedCalendarTypes" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -360,11 +293,6 @@ const matter_command_t matter_Commands_002D[] = { const matter_attribute_t matter_Attributes_002E[] = { { 0x0000, 0, 0x02, "Sources" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -404,11 +332,6 @@ const matter_attribute_t matter_Attributes_002F[] = { { 0x001C, 0, 0x02, "BatFunctionalWhileCharging" }, { 0x001D, 0, 0x02, "BatChargingCurrent" }, { 0x001E, 0, 0x02, "ActiveBatChargeFaults" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -422,11 +345,6 @@ const matter_attribute_t matter_Attributes_0030[] = { { 0x0002, 0, 0x02, "RegulatoryConfig" }, { 0x0003, 0, 0x02, "LocationCapability" }, { 0x0004, 0, 0x02, "SupportsConcurrentConnection" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -449,10 +367,6 @@ const matter_attribute_t matter_Attributes_0031[] = { { 0x0005, 0, 0x02, "LastNetworkingStatus" }, { 0x0006, 0, 0x02, "LastNetworkID" }, { 0x0007, 0, 0x02, "LastConnectErrorValue" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -467,11 +381,6 @@ const matter_command_t matter_Commands_0031[] = { }; const matter_attribute_t matter_Attributes_0032[] = { - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -490,11 +399,6 @@ const matter_attribute_t matter_Attributes_0033[] = { { 0x0006, 0, 0x02, "ActiveRadioFaults" }, { 0x0007, 0, 0x02, "ActiveNetworkFaults" }, { 0x0008, 0, 0x02, "TestEventTriggersEnabled" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -508,11 +412,6 @@ const matter_attribute_t matter_Attributes_0034[] = { { 0x0001, 0, 0x02, "CurrentHeapFree" }, { 0x0002, 0, 0x02, "CurrentHeapUsed" }, { 0x0003, 0, 0x02, "CurrentHeapHighWatermark" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -585,11 +484,6 @@ const matter_attribute_t matter_Attributes_0035[] = { { 0x003C, 0, 0x02, "ChannelPage0Mask" }, { 0x003D, 0, 0x02, "OperationalDatasetComponents" }, { 0x003E, 0, 0x02, "ActiveNetworkFaultsList" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -612,11 +506,6 @@ const matter_attribute_t matter_Attributes_0036[] = { { 0x000A, 0, 0x02, "PacketUnicastTxCount" }, { 0x000B, 0, 0x02, "CurrentMaxRate" }, { 0x000C, 0, 0x02, "OverrunCount" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -635,11 +524,6 @@ const matter_attribute_t matter_Attributes_0037[] = { { 0x0006, 0, 0x02, "OverrunCount" }, { 0x0007, 0, 0x02, "CarrierDetect" }, { 0x0008, 0, 0x02, "TimeSinceReset" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -662,11 +546,6 @@ const matter_attribute_t matter_Attributes_0038[] = { { 0x000A, 0, 0x02, "TimeZoneListMaxSize" }, { 0x000B, 0, 0x02, "DSTOffsetListMaxSize" }, { 0x000C, 0, 0x02, "SupportsDNSResolve" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -696,11 +575,6 @@ const matter_attribute_t matter_Attributes_0039[] = { { 0x000F, 0, 0x02, "SerialNumber" }, { 0x0011, 0, 0x02, "Reachable" }, { 0x0012, 0, 0x02, "UniqueID" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -712,11 +586,6 @@ const matter_attribute_t matter_Attributes_003B[] = { { 0x0000, 0, 0x02, "NumberOfPositions" }, { 0x0001, 0, 0x02, "CurrentPosition" }, { 0x0002, 0, 0x02, "MultiPressMax" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -728,11 +597,6 @@ const matter_attribute_t matter_Attributes_003C[] = { { 0x0000, 0, 0x02, "WindowStatus" }, { 0x0001, 0, 0x02, "AdminFabricIndex" }, { 0x0002, 0, 0x02, "AdminVendorId" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -750,11 +614,6 @@ const matter_attribute_t matter_Attributes_003E[] = { { 0x0003, 0, 0x02, "CommissionedFabrics" }, { 0x0004, 0, 0x02, "TrustedRootCertificates" }, { 0x0005, 0, 0x02, "CurrentFabricIndex" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -779,11 +638,6 @@ const matter_attribute_t matter_Attributes_003F[] = { { 0x0001, 0, 0x02, "GroupTable" }, { 0x0002, 0, 0x02, "MaxGroupsPerFabric" }, { 0x0003, 0, 0x02, "MaxGroupKeysPerFabric" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -797,11 +651,6 @@ const matter_command_t matter_Commands_003F[] = { const matter_attribute_t matter_Attributes_0040[] = { { 0x0000, 0, 0x02, "LabelList" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -811,10 +660,6 @@ const matter_command_t matter_Commands_0040[] = { const matter_attribute_t matter_Attributes_0041[] = { { 0x0000, 0, 0x03, "LabelList" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -824,11 +669,6 @@ const matter_command_t matter_Commands_0041[] = { const matter_attribute_t matter_Attributes_0045[] = { { 0x0000, 0, 0x02, "StateValue" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -843,11 +683,6 @@ const matter_attribute_t matter_Attributes_0050[] = { { 0x0003, 0, 0x02, "CurrentMode" }, { 0x0004, 0, 0x03, "StartUpMode" }, { 0x0005, 0, 0x03, "OnMode" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -882,11 +717,6 @@ const matter_attribute_t matter_Attributes_0101[] = { { 0x0030, 0, 0x03, "WrongCodeEntryLimit" }, { 0x0031, 0, 0x03, "UserCodeTemporaryDisableTime" }, { 0x0033, 0, 0x01, "RequirePINforRemoteOperation" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -935,11 +765,6 @@ const matter_attribute_t matter_Attributes_0102[] = { { 0x0013, 0, 0x02, "InstalledClosedLimitTilt" }, { 0x0017, 0, 0x03, "Mode" }, { 0x001A, 0, 0x02, "SafetyStatus" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -959,11 +784,6 @@ const matter_attribute_t matter_Attributes_0103[] = { { 0x0002, 0, 0x02, "BarrierSafetyStatus" }, { 0x0003, 0, 0x02, "BarrierCapabilities" }, { 0x000A, 0, 0x02, "BarrierPosition" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -997,11 +817,6 @@ const matter_attribute_t matter_Attributes_0200[] = { { 0x0017, 0, 0x03, "LifetimeEnergyConsumed" }, { 0x0020, 0, 0x03, "OperationMode" }, { 0x0021, 0, 0x03, "ControlMode" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1053,11 +868,6 @@ const matter_attribute_t matter_Attributes_0202[] = { { 0x0008, 0, 0x03, "RockSetting" }, { 0x0009, 0, 0x02, "WindSupport" }, { 0x000A, 0, 0x03, "WindSetting" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1069,11 +879,6 @@ const matter_attribute_t matter_Attributes_0204[] = { { 0x0000, 0, 0x03, "TemperatureDisplayMode" }, { 0x0001, 0, 0x03, "KeypadLockout" }, { 0x0002, 0, 0x03, "ScheduleProgrammingVisibility" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1134,11 +939,6 @@ const matter_attribute_t matter_Attributes_0300[] = { { 0x400C, 0, 0x02, "ColorTempPhysicalMaxMireds" }, { 0x400D, 0, 0x02, "CoupleColorTempToLevelMinMireds" }, { 0x4010, 0, 0x03, "StartUpColorTemperatureMireds" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1180,11 +980,6 @@ const matter_attribute_t matter_Attributes_0301[] = { { 0x0033, 0, 0x03, "LampBurnHours" }, { 0x0034, 0, 0x03, "LampAlarmMode" }, { 0x0035, 0, 0x03, "LampBurnHoursTripPoint" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1198,11 +993,6 @@ const matter_attribute_t matter_Attributes_0400[] = { { 0x0002, 0, 0x02, "MaxMeasuredValue" }, { 0x0003, 0, 0x02, "Tolerance" }, { 0x0004, 0, 0x02, "LightSensorType" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1250,11 +1040,6 @@ const matter_attribute_t matter_Attributes_0404[] = { { 0x0001, 0, 0x02, "MinMeasuredValue" }, { 0x0002, 0, 0x02, "MaxMeasuredValue" }, { 0x0003, 0, 0x02, "Tolerance" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1267,11 +1052,6 @@ const matter_attribute_t matter_Attributes_0405[] = { { 0x0001, 0, 0x02, "MinMeasuredValue" }, { 0x0002, 0, 0x02, "MaxMeasuredValue" }, { 0x0003, 0, 0x02, "Tolerance" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1283,11 +1063,6 @@ const matter_attribute_t matter_Attributes_0406[] = { { 0x0000, 0, 0x02, "Occupancy" }, { 0x0001, 0, 0x02, "OccupancySensorType" }, { 0x0002, 0, 0x02, "OccupancySensorTypeBitmap" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1297,11 +1072,6 @@ const matter_command_t matter_Commands_0406[] = { const matter_attribute_t matter_Attributes_0503[] = { { 0x0000, 0, 0x02, "MACAddress" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1313,11 +1083,6 @@ const matter_attribute_t matter_Attributes_0504[] = { { 0x0000, 0, 0x02, "ChannelList" }, { 0x0001, 0, 0x02, "Lineup" }, { 0x0002, 0, 0x02, "CurrentChannel" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1331,11 +1096,6 @@ const matter_command_t matter_Commands_0504[] = { const matter_attribute_t matter_Attributes_0505[] = { { 0x0000, 0, 0x02, "TargetList" }, { 0x0001, 0, 0x02, "CurrentTarget" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1352,11 +1112,6 @@ const matter_attribute_t matter_Attributes_0506[] = { { 0x0004, 0, 0x02, "PlaybackSpeed" }, { 0x0005, 0, 0x02, "SeekRangeEnd" }, { 0x0006, 0, 0x02, "SeekRangeStart" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1378,11 +1133,6 @@ const matter_command_t matter_Commands_0506[] = { const matter_attribute_t matter_Attributes_0507[] = { { 0x0000, 0, 0x02, "InputList" }, { 0x0001, 0, 0x02, "CurrentInput" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1395,11 +1145,6 @@ const matter_command_t matter_Commands_0507[] = { }; const matter_attribute_t matter_Attributes_0508[] = { - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1409,11 +1154,6 @@ const matter_command_t matter_Commands_0508[] = { }; const matter_attribute_t matter_Attributes_0509[] = { - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1425,11 +1165,6 @@ const matter_command_t matter_Commands_0509[] = { const matter_attribute_t matter_Attributes_050A[] = { { 0x0000, 0, 0x02, "AcceptHeader" }, { 0x0001, 0, 0x03, "SupportedStreamingProtocols" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1442,11 +1177,6 @@ const matter_command_t matter_Commands_050A[] = { const matter_attribute_t matter_Attributes_050B[] = { { 0x0000, 0, 0x02, "OutputList" }, { 0x0001, 0, 0x02, "CurrentOutput" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1459,11 +1189,6 @@ const matter_command_t matter_Commands_050B[] = { const matter_attribute_t matter_Attributes_050C[] = { { 0x0000, 0, 0x02, "CatalogList" }, { 0x0001, 0, 0x03, "CurrentApp" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1483,11 +1208,6 @@ const matter_attribute_t matter_Attributes_050D[] = { { 0x0005, 0, 0x02, "Status" }, { 0x0006, 0, 0x02, "ApplicationVersion" }, { 0x0007, 0, 0x02, "AllowedVendorList" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1496,11 +1216,6 @@ const matter_command_t matter_Commands_050D[] = { }; const matter_attribute_t matter_Attributes_050E[] = { - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1523,11 +1238,6 @@ const matter_attribute_t matter_Attributes_0B04[] = { { 0x050B, 0, 0x02, "ActivePower" }, { 0x050C, 0, 0x02, "ActivePowerMin" }, { 0x050D, 0, 0x02, "ActivePowerMax" }, - { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, - { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, - { 0xFFFB, 0, 0x02, "AttributeList" }, - { 0xFFFC, 0, 0x02, "FeatureMap" }, - { 0xFFFD, 0, 0x02, "ClusterRevision" }, { 0xFFFF, 0, 0x00, NULL }, }; @@ -1535,6 +1245,17 @@ const matter_command_t matter_Commands_0B04[] = { { 0xFFFF, NULL }, }; +// specifal cluster for attributes common to all clusters +const matter_attribute_t matter_Attributes_Common[] = { + { 0xFFF8, 0, 0x02, "GeneratedCommandList" }, + { 0xFFF9, 0, 0x02, "AcceptedCommandList" }, + { 0xFFFA, 0, 0x02, "EventList" }, + { 0xFFFB, 0, 0x02, "AttributeList" }, + { 0xFFFC, 0, 0x02, "FeatureMap" }, + { 0xFFFD, 0, 0x02, "ClusterRevision" }, + { 0xFFFF, 0, 0x00, NULL }, +}; + const matter_cluster_t matterAllClusters[] = { { 0x0003, "Identify", matter_Attributes_0003, matter_Commands_0003 }, { 0x0004, "Groups", matter_Attributes_0004, matter_Commands_0004 }, diff --git a/lib/libesp32/berry_matter/src/be_matter_module.c b/lib/libesp32/berry_matter/src/be_matter_module.c index ebaa2d616..693d090de 100644 --- a/lib/libesp32/berry_matter/src/be_matter_module.c +++ b/lib/libesp32/berry_matter/src/be_matter_module.c @@ -118,25 +118,35 @@ const char* matter_get_opcode_name(uint16_t opcode) { BE_FUNC_CTYPE_DECLARE(matter_get_opcode_name, "s", "i") const char* matter_get_attribute_name(uint16_t cluster, uint16_t attribute) { - for (const matter_cluster_t * cl = matterAllClusters; cl->id != 0xFFFF; cl++) { - if (cl->id == cluster) { - for (const matter_attribute_t * at = cl->attributes; at->id != 0xFFFF; at++) { - if (at->id == attribute) { - return at->name; + if (attribute < 0xFFF0) { + for (const matter_cluster_t * cl = matterAllClusters; cl->id != 0xFFFF; cl++) { + if (cl->id == cluster) { + for (const matter_attribute_t * at = cl->attributes; at->id != 0xFFFF; at++) { + if (at->id == attribute) { + return at->name; + } } } } + } else { + for (const matter_attribute_t * at = matter_Attributes_Common; at->id != 0xFFFF; at++) { + if (at->id == attribute) { + return at->name; + } + } } return NULL; } BE_FUNC_CTYPE_DECLARE(matter_get_attribute_name, "s", "ii") bbool matter_is_attribute_writable(uint16_t cluster, uint16_t attribute) { - for (const matter_cluster_t * cl = matterAllClusters; cl->id != 0xFFFF; cl++) { - if (cl->id == cluster) { - for (const matter_attribute_t * at = cl->attributes; at->id != 0xFFFF; at++) { - if (at->id == attribute) { - return (at->flags & 0x01) ? btrue : bfalse; + if (attribute < 0xFFF0) { + for (const matter_cluster_t * cl = matterAllClusters; cl->id != 0xFFFF; cl++) { + if (cl->id == cluster) { + for (const matter_attribute_t * at = cl->attributes; at->id != 0xFFFF; at++) { + if (at->id == attribute) { + return (at->flags & 0x01) ? btrue : bfalse; + } } } } @@ -146,14 +156,18 @@ bbool matter_is_attribute_writable(uint16_t cluster, uint16_t attribute) { BE_FUNC_CTYPE_DECLARE(matter_is_attribute_writable, "b", "ii") bbool matter_is_attribute_reportable(uint16_t cluster, uint16_t attribute) { - for (const matter_cluster_t * cl = matterAllClusters; cl->id != 0xFFFF; cl++) { - if (cl->id == cluster) { - for (const matter_attribute_t * at = cl->attributes; at->id != 0xFFFF; at++) { - if (at->id == attribute) { - return (at->flags & 0x02) ? btrue : bfalse; + if (attribute < 0xFFF0) { + for (const matter_cluster_t * cl = matterAllClusters; cl->id != 0xFFFF; cl++) { + if (cl->id == cluster) { + for (const matter_attribute_t * at = cl->attributes; at->id != 0xFFFF; at++) { + if (at->id == attribute) { + return (at->flags & 0x02) ? btrue : bfalse; + } } } } + } else { + return btrue; } return bfalse; } diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_0_Inspect.be b/lib/libesp32/berry_matter/src/embedded/Matter_0_Inspect.be index 5d6f31de0..acca8d64c 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_0_Inspect.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_0_Inspect.be @@ -83,7 +83,7 @@ matter.inspect = inspect # from the inheritance hierarchy #@ solidify:matter.consolidate_clusters,weak def consolidate_clusters(cl, m) - var cl_parent = super(cl).CLUSTERS + var cl_parent = super(cl) != nil ? super(cl).CLUSTERS : {} var ret = {} # clone cl_parent for k: cl_parent.keys() @@ -98,6 +98,22 @@ def consolidate_clusters(cl, m) if l == nil l = [] end ret[k] = l + m[k] end + # add all auto-attribbutes to each cluster + var AUTO_ATTRIBUTES = [ # pre-defined auto attributes for every cluster + 0xFFF8, # GeneratedCommandList - [] by default + 0xFFF9, # AcceptedCommandList - list of defined commands TODO for auto-generated + 0xFFFA, # EventList - [] by default + 0xFFFB, # AttributeList - list generated from cluster definition + 0xFFFC, # FeatureMap - 0 by default unless redefined + 0xFFFD, # ClusterRevision - 1 by default unless redefined + ] + for k: m.keys() + for at: AUTO_ATTRIBUTES + if ret[k].find(at) == nil + ret[k].push(at) + end + end + end # print(ret) return ret end diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_0.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_0.be index 000d5cfb2..2a53cc501 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_0.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_0.be @@ -36,8 +36,61 @@ class Matter_Plugin static var VIRTUAL = false # set to true only for virtual devices var update_next # next timestamp for update # Configuration of the plugin: clusters and type - static var CLUSTERS = { - 0x001D: [0,1,2,3,0xFFFC,0xFFFD], # Descriptor Cluster 9.5 p.453 + static var CLUSTERS = matter.consolidate_clusters(_class, { + 0x001D: [0,1,2,3], # Descriptor Cluster 9.5 p.453 + }) + static var COMMANDS = { + 0x001D: nil, # Descriptor Cluster 9.5 p.453 + } + # static var TYPES = { : } # needs to be defined for each endpoint + # `FEATURE_MAPS` contains any non-zero value per cluster, if not present default to `0` + static var FEATURE_MAPS = { # feature map per cluster + 0x0031: 0x04, # Put Eth for now which should work for any on-network + 0x0102: 1 + 4, # Lift + PA_LF + } + # `CLUSTER_REVISIONS` contains revision numbers for each cluster, or `1` if not present + static var CLUSTER_REVISIONS = { + 0x0003: 4, # New data model format and notation + 0x0004: 4, # New data model format and notation + 0x0005: 5, # "new data model format and notation" + 0x0006: 5, # Addition of Dead Front behavior and associated FeatureMap entry + 0x0008: 5, # "new data model format and notation" + 0x001D: 2, # Semantic tag list; TagList feature + # 0x001F: 1, # Initial Release + 0x0028: 2, # Added ProductAppearance attribute + # 0x002A: 1, # Initial Release + # 0x002B: 1, # Initial Release + # 0x002C: 1, # Initial Release + # 0x0030: 1, # Initial Release + # 0x0031: 1, # Initial Release + # 0x0032: 1, # Initial Release + # 0x0033: 1, # Initial Release + # 0x0034: 1, # Initial Release + 0x0038: 2, # + # 0x003C: 1, # Initial Release + # 0x003E: 1, # Initial Release + 0x003F: 2, # Clarify KeySetWrite validation and behavior on invalid epoch key lengths + # 0x0040: 1, # Initial Release + # 0x0041: 1, # Initial Release + # 0x0042: 1, # Initial Release + # 0x005B: 1, # Initial Release + # 0x005C: 1, # Initial Release + 0x0101: 7, # Added support for European door locks (unbolt feature) + 0x0102: 5, # New data model format and notation + 0x0200: 4, # Added feature map + 0x0201: 6, # Introduced the LTNE feature and adapted text (spec issue #5778) + 0x0202: 4, # Change conformance for FanModeSe­ quenceEnum + 0x0204: 2, # New data model format and notation, added "Conversion of Temperature Values for Display" section + 0x0300: 6, # Added clarifications to Scenes support for Matter + 0x0301: 4, # New data model format and notation + 0x0400: 3, # New data model format and notation + 0x0402: 4, # New data model format and notation + 0x0403: 3, # New data model format and notation + 0x0404: 3, # New data model format and notation + 0x0405: 3, # New data model format and notation + 0x0406: 3, # New data model format and notation + 0x0407: 3, # New data model format and notation + 0x0408: 3, # New data model format and notation } # Accepted Update commands for virtual devices static var UPDATE_COMMANDS = [] @@ -265,9 +318,35 @@ class Matter_Plugin return tlv_solo.set(TLV.U4, 1) # "Initial Release" end - else - return nil end + + # Handle attributes 0xFFF8 - 0xFFFD for all clusters + if attribute == 0xFFF8 # GeneratedCommandList + var gcl = TLV.Matter_TLV_array() + return gcl # return empty list + elif attribute == 0xFFF9 # AcceptedCommandList + var acli = TLV.Matter_TLV_array() + var attr_list = self.get_attribute_list(cluster) + var idx = 0 + while idx < size(attr_list) + acli.add_TLV(nil, TLV.U2, attr_list[idx]) + idx += 1 + end + return acli # TODO, empty list for now + elif attribute == 0xFFFA # EventList + var el = TLV.Matter_TLV_array() + return el # return empty list + elif attribute == 0xFFFB # AttributeList + var al = TLV.Matter_TLV_array() + return al # TODO + elif attribute == 0xFFFC # FeatureMap + var featuremap = self.FEATURE_MAPS.find(cluster, 0) + return tlv_solo.set(TLV.U4, featuremap) + elif attribute == 0xFFFD # ClusterRevision + var clusterrevision = self.CLUSTER_REVISIONS.find(cluster, 1) + return tlv_solo.set(TLV.U4, clusterrevision) + end + end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Aggregator.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Aggregator.be index 7c0fbc6f4..6e8771736 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Aggregator.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Aggregator.be @@ -28,7 +28,7 @@ class Matter_Plugin_Aggregator : Matter_Plugin static var DISPLAY_NAME = "Aggregator" # display name of the plug-in static var CLUSTERS = matter.consolidate_clusters(_class, { # 0x001D: inherited # Descriptor Cluster 9.5 p.453 - 0x0003: [0,1,0xFFFC,0xFFFD], # Identify 1.2 p.16 + 0x0003: [0,1,], # Identify 1.2 p.16 }) static var TYPES = { 0x000E: 1 } # Aggregator @@ -46,10 +46,6 @@ class Matter_Plugin_Aggregator : Matter_Plugin return tlv_solo.set(TLV.U2, 0) # no identification in progress elif attribute == 0x0001 # ---------- IdentifyType / enum8 ---------- return tlv_solo.set(TLV.U1, 0) # IdentifyType = 0x00 None - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) # no features - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 4) # "new data model format and notation" end elif cluster == 0x001D # ========== Descriptor Cluster 9.5 p.453 ========== @@ -68,15 +64,10 @@ class Matter_Plugin_Aggregator : Matter_Plugin end end return pl - else - return super(self).read_attribute(session, ctx, tlv_solo) end - else - return super(self).read_attribute(session, ctx, tlv_solo) - end - # no match found, return that the attribute is unsupported + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Device.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Device.be index 4357a3844..619646386 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Device.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Device.be @@ -25,9 +25,9 @@ class Matter_Plugin_Device : Matter_Plugin static var CLUSTERS = matter.consolidate_clusters(_class, { # 0x001D: inherited # Descriptor Cluster 9.5 p.453 0x0039: [3,5,0x0A,0x0F,0x11,0x12], # Bridged Device Basic Information 9.13 p.485 - 0x0003: [0,1,0xFFFC,0xFFFD], # Identify 1.2 p.16 - 0x0004: [0,0xFFFC,0xFFFD], # Groups 1.3 p.21 - 0x0005: [0,1,2,3,4,5,0xFFFC,0xFFFD], # Scenes 1.4 p.30 - no writable + 0x0003: [0,1], # Identify 1.2 p.16 + 0x0004: [0], # Groups 1.3 p.21 + 0x0005: [0,1,2,3,4,5], # Scenes 1.4 p.30 - no writable }) static var TYPES = { 0x0013: 1 } # fake type static var NON_BRIDGE_VENDOR = [ 0x1217, 0x1381 ] # Fabric VendorID not supporting Bridge mode @@ -52,29 +52,16 @@ class Matter_Plugin_Device : Matter_Plugin return tlv_solo.set(TLV.U2, 0) # no identification in progress elif attribute == 0x0001 # ---------- IdentifyType / enum8 ---------- return tlv_solo.set(TLV.U1, 0) # IdentifyType = 0x00 None - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) # no features - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 4) # "new data model format and notation" end # ==================================================================================================== elif cluster == 0x0004 # ========== Groups 1.3 p.21 ========== if attribute == 0x0000 # ---------- ---------- return nil # TODO - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0)# - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 4)# "new data model format and notation" end # ==================================================================================================== elif cluster == 0x0005 # ========== Scenes 1.4 p.30 - no writable ========== - if attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) # 0 = no Level Control for Lighting - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 4) # 0 = no Level Control for Lighting - end # ==================================================================================================== elif cluster == 0x001D # ========== Descriptor Cluster 9.5 p.453 ========== @@ -96,8 +83,6 @@ class Matter_Plugin_Device : Matter_Plugin d1.add_TLV(1, TLV.U2, 1) # Revision end return dtl - else - return super(self).read_attribute(session, ctx, tlv_solo) end # ==================================================================================================== @@ -121,9 +106,8 @@ class Matter_Plugin_Device : Matter_Plugin return tlv_solo.set(TLV.UTF1, tasmota.wifi().find("mac", "")) end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be index 8fc3e2b60..87af9396b 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be @@ -34,7 +34,7 @@ class Matter_Plugin_Root : Matter_Plugin 0x002B: [0,1], # Localization Configuration Cluster 11.3 p.580 0x002C: [0,1,2], # Time Format Localization Cluster 11.4 p.581 0x0030: [0,1,2,3,4], # GeneralCommissioning cluster 11.9 p.627 - 0x0031: [3,4,0xFFFC], # Network Commissioning Cluster cluster 11.8 p.606 + 0x0031: [3,4], # Network Commissioning Cluster cluster 11.8 p.606 0x0032: [], # Diagnostic Logs Cluster 11.10 p.637 0x0033: [0,1,2,8], # General Diagnostics Cluster 11.11 p.642 0x0034: [], # Software Diagnostics Cluster 11.12 p.654 @@ -301,8 +301,6 @@ class Matter_Plugin_Root : Matter_Plugin elif cluster == 0x0031 # ========== Network Commissioning Cluster cluster 11.8 p.606 ========== if attribute == 0x0003 # ---------- ConnectMaxTimeSeconds / uint8 ---------- return tlv_solo.set(TLV.U1, 30) # 30 - value taking from example in esp-matter - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0x04) # Put Eth for now which should work for any on-network end elif cluster == 0x001D # ========== Descriptor Cluster 9.5 p.453 ========== @@ -325,15 +323,10 @@ class Matter_Plugin_Root : Matter_Plugin end end return pl - else - return super(self).read_attribute(session, ctx, tlv_solo) end - else - return super(self).read_attribute(session, ctx, tlv_solo) - end - # no match found, return that the attribute is unsupported + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Bridge_HTTP.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Bridge_HTTP.be index 46087cd4e..75b2316df 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Bridge_HTTP.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Bridge_HTTP.be @@ -38,7 +38,7 @@ class Matter_Plugin_Bridge_HTTP : Matter_Plugin_Device # # 0x0003: inherited # Identify 1.2 p.16 # # 0x0004: inherited # Groups 1.3 p.21 # # 0x0005: inherited # Scenes 1.4 p.30 - no writable - # # 0x0006: [0,0xFFFC,0xFFFD], # On/Off 1.5 p.48 + # # 0x0006: [0], # On/Off 1.5 p.48 # # 0x0028: [0,1,2,3,4,5,6,7,8,9,0x0A,0x0F,0x12,0x13],# Basic Information Cluster cluster 11.1 p.565 # # 0x0039: [0x11] # Bridged Device Basic Information 9.13 p.485 @@ -207,13 +207,10 @@ class Matter_Plugin_Bridge_HTTP : Matter_Plugin_Device elif attribute == 0x0011 # ---------- Reachable / bool ---------- # self.is_reachable_lazy_sync() # Not needed anymore return tlv_solo.set(TLV.BOOL, self.http_remote.reachable) # TODO find a way to do a ping - else - return super(self).read_attribute(session, ctx, tlv_solo) end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Light1.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Light1.be index 4ba09f081..ab6de67fe 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Light1.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Light1.be @@ -32,8 +32,8 @@ class Matter_Plugin_Light1 : Matter_Plugin_Device # 0x0003: inherited # Identify 1.2 p.16 # 0x0004: inherited # Groups 1.3 p.21 # 0x0005: inherited # Scenes 1.4 p.30 - no writable - 0x0006: [0,0xFFFC,0xFFFD], # On/Off 1.5 p.48 - 0x0008: [0,2,3,0x0F,0x11,0xFFFC,0xFFFD], # Level Control 1.6 p.57 + 0x0006: [0], # On/Off 1.5 p.48 + 0x0008: [0,2,3,0x0F,0x11], # Level Control 1.6 p.57 }) static var UPDATE_COMMANDS = matter.UC_LIST(_class, "Power", "Bri") static var TYPES = { 0x0101: 2 } # Dimmable Light @@ -137,10 +137,6 @@ class Matter_Plugin_Light1 : Matter_Plugin_Device self.update_shadow_lazy() if attribute == 0x0000 # ---------- OnOff / bool ---------- return tlv_solo.set(TLV.BOOL, self.shadow_onoff) - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) # 0 = no Level Control for Lighting - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 4) # 0 = no Level Control for Lighting end # ==================================================================================================== @@ -156,15 +152,10 @@ class Matter_Plugin_Light1 : Matter_Plugin_Device return tlv_solo.set(TLV.U1, 0) # elif attribute == 0x0011 # ---------- OnLevel / u1 ---------- return tlv_solo.set(TLV.U1, self.shadow_bri) - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0X01) # OnOff - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 5) # "new data model format and notation" end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_OnOff.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_OnOff.be index a2966c7c6..89f3a5430 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_OnOff.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_OnOff.be @@ -35,7 +35,7 @@ class Matter_Plugin_OnOff : Matter_Plugin_Device # 0x0003: inherited # Identify 1.2 p.16 # 0x0004: inherited # Groups 1.3 p.21 # 0x0005: inherited # Scenes 1.4 p.30 - no writable - 0x0006: [0,0xFFFC,0xFFFD], # On/Off 1.5 p.48 + 0x0006: [0], # On/Off 1.5 p.48 }) static var UPDATE_COMMANDS = matter.UC_LIST(_class, "Power") static var TYPES = { 0x010A: 2 } # On/Off Plug-in Unit @@ -109,15 +109,10 @@ class Matter_Plugin_OnOff : Matter_Plugin_Device self.update_shadow_lazy() if attribute == 0x0000 # ---------- OnOff / bool ---------- return tlv_solo.set(TLV.BOOL, self.shadow_onoff) - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) # 0 = no Level Control for Lighting - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 4) # 0 = no Level Control for Lighting end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Contact.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Contact.be index fbd061b1f..b7d683039 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Contact.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Contact.be @@ -32,7 +32,7 @@ class Matter_Plugin_Sensor_Contact : Matter_Plugin_Device static var UPDATE_TIME = 750 # update every 750ms static var UPDATE_COMMANDS = matter.UC_LIST(_class, "Contact") static var CLUSTERS = matter.consolidate_clusters(_class, { - 0x0045: [0,0xFFFC,0xFFFD], # Boolean State p.70 - no writable + 0x0045: [0], # Boolean State p.70 - no writable }) static var TYPES = { 0x0015: 1 } # Contact Sensor, rev 1 @@ -92,15 +92,10 @@ class Matter_Plugin_Sensor_Contact : Matter_Plugin_Device else return tlv_solo.set(TLV.NULL, nil) end - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 1) # 1 = Initial release end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Occupancy.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Occupancy.be index 958386d59..2d9f09323 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Occupancy.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_Occupancy.be @@ -32,7 +32,7 @@ class Matter_Plugin_Sensor_Occupancy : Matter_Plugin_Device static var UPDATE_TIME = 750 # update every 750ms static var UPDATE_COMMANDS = matter.UC_LIST(_class, "Occupancy") static var CLUSTERS = matter.consolidate_clusters(_class, { - 0x0406: [0,1,2,0xFFFC,0xFFFD], # Occupancy Sensing p.105 - no writable + 0x0406: [0,1,2], # Occupancy Sensing p.105 - no writable }) static var TYPES = { 0x0107: 2 } # Occupancy Sensor, rev 2 @@ -96,15 +96,10 @@ class Matter_Plugin_Sensor_Occupancy : Matter_Plugin_Device return tlv_solo.set(TLV.U1, 3) # physical contact elif attribute == 0x0002 # ---------- OccupancySensorTypeBitmap / u8 ---------- return tlv_solo.set(TLV.U1, 0) # unknown - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 3) # 4 = New data model format and notation end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_OnOff.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_OnOff.be index ce535f91c..a2d2af9e6 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_OnOff.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Sensor_OnOff.be @@ -29,7 +29,7 @@ class Matter_Plugin_Sensor_OnOff : Matter_Plugin_Device static var ARG_TYPE = / x -> int(x) # function to convert argument to the right type static var UPDATE_TIME = 750 # update every 750ms static var CLUSTERS = matter.consolidate_clusters(_class, { - 0x0006: [0,0xFFFC,0xFFFD], # On/Off 1.5 p.48 + 0x0006: [0], # On/Off 1.5 p.48 }) static var TYPES = { 0x0850: 2 } # OnOff Sensor, rev 2 @@ -79,15 +79,10 @@ class Matter_Plugin_Sensor_OnOff : Matter_Plugin_Device self.update_shadow_lazy() if attribute == 0x0000 # ---------- OnOff / bool ---------- return tlv_solo.set(TLV.BOOL, self.shadow_onoff) - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) # 0 = no Level Control for Lighting - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 4) # 0 = no Level Control for Lighting end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Shutter.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Shutter.be index 424f74be8..704b2a7b9 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Shutter.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_2_Shutter.be @@ -34,7 +34,7 @@ class Matter_Plugin_Shutter : Matter_Plugin_Device # 0x0003: inherited # Identify 1.2 p.16 # 0x0004: inherited # Groups 1.3 p.21 # 0x0005: inherited # Scenes 1.4 p.30 - no writable - 0x0102: [0,5,7,0xA,0xB,0xD,0xE,0x17,0xFFFC,0xFFFD], # Window Covering 5.3 p.289 + 0x0102: [0,5,7,0xA,0xB,0xD,0xE,0x17], # Window Covering 5.3 p.289 }) static var TYPES = { 0x0202: 2 } # New data model format and notation @@ -129,16 +129,10 @@ class Matter_Plugin_Shutter : Matter_Plugin_Device elif attribute == 0x0017 # ---------- Mode / u8 ---------- return tlv_solo.set(TLV.U1, 0) # normal mode - - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 1 + 4) # Lift + PA_LF - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 5) # New data model format and notation end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Bridge_Light0.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Bridge_Light0.be index fe0bc8a81..87c0e22f9 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Bridge_Light0.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Bridge_Light0.be @@ -36,7 +36,7 @@ class Matter_Plugin_Bridge_Light0 : Matter_Plugin_Bridge_HTTP # 0x0003: inherited # Identify 1.2 p.16 # 0x0004: inherited # Groups 1.3 p.21 # 0x0005: inherited # Scenes 1.4 p.30 - no writable - 0x0006: [0,0xFFFC,0xFFFD], # On/Off 1.5 p.48 + 0x0006: [0], # On/Off 1.5 p.48 }) static var TYPES = { 0x0100: 2 } # OnOff Light, but not actually used because Relay is managed by OnOff @@ -97,15 +97,10 @@ class Matter_Plugin_Bridge_Light0 : Matter_Plugin_Bridge_HTTP self.update_shadow_lazy() if attribute == 0x0000 # ---------- OnOff / bool ---------- return tlv_solo.set(TLV.BOOL, self.shadow_onoff) - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) # 0 = no Level Control for Lighting - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 4) # 0 = no Level Control for Lighting end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Bridge_Sensor_Contact.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Bridge_Sensor_Contact.be index d4f738e26..fe8373987 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Bridge_Sensor_Contact.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Bridge_Sensor_Contact.be @@ -33,7 +33,7 @@ class Matter_Plugin_Bridge_Sensor_Contact : Matter_Plugin_Bridge_HTTP static var UPDATE_CMD = "Status 8" # command to send for updates static var CLUSTERS = matter.consolidate_clusters(_class, { - 0x0045: [0,0xFFFC,0xFFFD], # Boolean State p.70 - no writable + 0x0045: [0], # Boolean State p.70 - no writable }) static var TYPES = { 0x0015: 1 } # Contact Sensor, rev 1 @@ -81,15 +81,10 @@ class Matter_Plugin_Bridge_Sensor_Contact : Matter_Plugin_Bridge_HTTP else return tlv_solo.set(TLV.NULL, nil) end - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 1) # 1 = Initial release end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Bridge_Sensor_Occupancy.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Bridge_Sensor_Occupancy.be index 8279a6088..1ed2c5c59 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Bridge_Sensor_Occupancy.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Bridge_Sensor_Occupancy.be @@ -33,7 +33,7 @@ class Matter_Plugin_Bridge_Sensor_Occupancy : Matter_Plugin_Bridge_HTTP static var UPDATE_CMD = "Status 8" # command to send for updates static var CLUSTERS = matter.consolidate_clusters(_class, { - 0x0406: [0,1,2,0xFFFC,0xFFFD], # Occupancy Sensing p.105 - no writable + 0x0406: [0,1,2], # Occupancy Sensing p.105 - no writable }) static var TYPES = { 0x0107: 2 } # Occupancy Sensor, rev 2 @@ -85,15 +85,10 @@ class Matter_Plugin_Bridge_Sensor_Occupancy : Matter_Plugin_Bridge_HTTP return tlv_solo.set(TLV.U1, 3) # physical contact elif attribute == 0x0002 # ---------- OccupancySensorTypeBitmap / u8 ---------- return tlv_solo.set(TLV.U1, 0) # unknown - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 3) # 4 = New data model format and notation end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Light2.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Light2.be index 9bc4584d9..265514e29 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Light2.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Light2.be @@ -33,7 +33,7 @@ class Matter_Plugin_Light2 : Matter_Plugin_Light1 # 0x0005: inherited # Scenes 1.4 p.30 - no writable # 0x0006: inherited # On/Off 1.5 p.48 # 0x0008: inherited # Level Control 1.6 p.57 - 0x0300: [7,8,0xF,0x400B,0x400C,0xFFFC,0xFFFD], # Color Control 3.2 p.111 + 0x0300: [7,8,0xF,0x400B,0x400C], # Color Control 3.2 p.111 }) static var UPDATE_COMMANDS = matter.UC_LIST(_class, "CT") static var TYPES = { 0x010C: 2 } # Color Temperature Light @@ -132,13 +132,10 @@ class Matter_Plugin_Light2 : Matter_Plugin_Light1 elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- return tlv_solo.set(TLV.U4, 0x10) # CT - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 5) # "new data model format and notation, FeatureMap support" end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Light3.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Light3.be index 8f7dd46fd..a0b77dd21 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Light3.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Light3.be @@ -33,7 +33,7 @@ class Matter_Plugin_Light3 : Matter_Plugin_Light1 # 0x0005: inherited # Scenes 1.4 p.30 - no writable # 0x0006: inherited # On/Off 1.5 p.48 # 0x0008: inherited # Level Control 1.6 p.57 - 0x0300: [0,1,7,8,0xF,0x4001,0x400A,0xFFFC,0xFFFD],# Color Control 3.2 p.111 + 0x0300: [0,1,7,8,0xF,0x4001,0x400A], # Color Control 3.2 p.111 }) static var UPDATE_COMMANDS = matter.UC_LIST(_class, "Hue", "Sat") static var TYPES = { 0x010D: 2 } # Extended Color Light @@ -147,13 +147,10 @@ class Matter_Plugin_Light3 : Matter_Plugin_Light1 elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- return tlv_solo.set(TLV.U4, 0x01) # HS - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 5) # "new data model format and notation, FeatureMap support" end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Flow.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Flow.be index f7a12469d..9e418d453 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Flow.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Flow.be @@ -29,7 +29,7 @@ class Matter_Plugin_Sensor_Flow : Matter_Plugin_Sensor static var JSON_NAME = "Flow" # Name of the sensor attribute in JSON payloads static var UPDATE_COMMANDS = matter.UC_LIST(_class, "Flow") static var CLUSTERS = matter.consolidate_clusters(_class, { - 0x0404: [0,1,2,0xFFFC,0xFFFD], # Flow Measurement + 0x0404: [0,1,2], # Flow Measurement }) static var TYPES = { 0x0306: 1 } # Flow Sensor, rev 1 @@ -71,15 +71,10 @@ class Matter_Plugin_Sensor_Flow : Matter_Plugin_Sensor return tlv_solo.set(TLV.U2, 0) # 0 m3/h elif attribute == 0x0002 # ---------- MaxMeasuredValue / i16 ---------- return tlv_solo.set(TLV.U2, 65534) # 65534 m3/h - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) # 0 = no Extended Range - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 3) # 3 = New data model format and notation end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end end diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Humidity.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Humidity.be index e3ff44184..94c7d4a90 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Humidity.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Humidity.be @@ -29,7 +29,7 @@ class Matter_Plugin_Sensor_Humidity : Matter_Plugin_Sensor static var JSON_NAME = "Humidity" # Name of the sensor attribute in JSON payloads static var UPDATE_COMMANDS = matter.UC_LIST(_class, "Humidity") static var CLUSTERS = matter.consolidate_clusters(_class, { - 0x0405: [0,1,2,0xFFFC,0xFFFD], # Humidity Measurement p.102 - no writable + 0x0405: [0,1,2], # Humidity Measurement p.102 - no writable }) static var TYPES = { 0x0307: 2 } # Humidity Sensor, rev 2 @@ -71,15 +71,10 @@ class Matter_Plugin_Sensor_Humidity : Matter_Plugin_Sensor return tlv_solo.set(TLV.U2, 500) # 0% elif attribute == 0x0002 # ---------- MaxMeasuredValue / u16 ---------- return tlv_solo.set(TLV.U2, 10000) # 100% - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) # 0 = no Extended Range - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 3) # 3 = New data model format and notation end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end end diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Illuminance.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Illuminance.be index e49de236d..ac6144b30 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Illuminance.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Illuminance.be @@ -29,7 +29,7 @@ class Matter_Plugin_Sensor_Illuminance : Matter_Plugin_Sensor static var JSON_NAME = "Illuminance" # Name of the sensor attribute in JSON payloads static var UPDATE_COMMANDS = matter.UC_LIST(_class, "Illuminance") static var CLUSTERS = matter.consolidate_clusters(_class, { - 0x0400: [0,1,2,0xFFFC,0xFFFD], # Illuminance Measurement p.95 - no writable + 0x0400: [0,1,2], # Illuminance Measurement p.95 - no writable }) static var TYPES = { 0x0106: 2 } # Illuminance Sensor, rev 2 @@ -78,15 +78,10 @@ class Matter_Plugin_Sensor_Illuminance : Matter_Plugin_Sensor return tlv_solo.set(TLV.U2, 1) # 1 lux elif attribute == 0x0002 # ---------- MaxMeasuredValue / i16 ---------- return tlv_solo.set(TLV.U2, 0xFFFE) - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 3) # 3 = New data model format and notation end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end end diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Pressure.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Pressure.be index 54a0b7627..b41f21a97 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Pressure.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Pressure.be @@ -29,7 +29,7 @@ class Matter_Plugin_Sensor_Pressure : Matter_Plugin_Sensor static var JSON_NAME = "Pressure" # Name of the sensor attribute in JSON payloads static var UPDATE_COMMANDS = matter.UC_LIST(_class, "Pressure") static var CLUSTERS = matter.consolidate_clusters(_class, { - 0x0403: [0,1,2,0xFFFC,0xFFFD], # Pressure Measurement + 0x0403: [0,1,2], # Pressure Measurement }) static var TYPES = { 0x0305: 2 } # Pressure Sensor, rev 2 @@ -71,15 +71,10 @@ class Matter_Plugin_Sensor_Pressure : Matter_Plugin_Sensor return tlv_solo.set(TLV.I2, 500) # 500 hPA elif attribute == 0x0002 # ---------- MaxMeasuredValue / i16 ---------- return tlv_solo.set(TLV.I2, 1500) # 1500 hPA - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) # 0 = no Extended Range - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 3) # 3 = New data model format and notation end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end end diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Temp.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Temp.be index 2b6ac22f7..a6a540595 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Temp.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_Sensor_Temp.be @@ -29,7 +29,7 @@ class Matter_Plugin_Sensor_Temp : Matter_Plugin_Sensor static var JSON_NAME = "Temperature" # Name of the sensor attribute in JSON payloads static var UPDATE_COMMANDS = matter.UC_LIST(_class, "Temperature") static var CLUSTERS = matter.consolidate_clusters(_class, { - 0x0402: [0,1,2,0xFFFC,0xFFFD], # Temperature Measurement p.97 - no writable + 0x0402: [0,1,2], # Temperature Measurement p.97 - no writable }) static var TYPES = { 0x0302: 2 } # Temperature Sensor, rev 2 @@ -74,15 +74,10 @@ class Matter_Plugin_Sensor_Temp : Matter_Plugin_Sensor return tlv_solo.set(TLV.I2, -5000) # -50 °C elif attribute == 0x0002 # ---------- MaxMeasuredValue / i16 (*100) ---------- return tlv_solo.set(TLV.I2, 15000) # 150 °C - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 4) # 4 = New data model format and notation end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end end diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_ShutterTilt.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_ShutterTilt.be index f73548f69..f2dc0f44e 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_ShutterTilt.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_3_ShutterTilt.be @@ -33,7 +33,7 @@ class Matter_Plugin_ShutterTilt : Matter_Plugin_Shutter # 0x0003: inherited # Identify 1.2 p.16 # 0x0004: inherited # Groups 1.3 p.21 # 0x0005: inherited # Scenes 1.4 p.30 - no writable - 0x0102: [7,0xC,0xF,0xFFFC], # Window Covering 5.3 p.289 + 0x0102: [7,0xC,0xF], # Window Covering 5.3 p.289 }) # inherited static var TYPES = { 0x0202: 2 } # New data model format and notation @@ -125,7 +125,6 @@ class Matter_Plugin_ShutterTilt : Matter_Plugin_Shutter return tlv_solo.set(TLV.U4, 3 + 4 + 16) # Lift + Tilt + PA_LF + PA_TL end end - # else return super(self).read_attribute(session, ctx, tlv_solo) end diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Light1.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Light1.be index b20d27ff4..e2ada8078 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Light1.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Light1.be @@ -34,7 +34,7 @@ class Matter_Plugin_Bridge_Light1 : Matter_Plugin_Bridge_Light0 # 0x0004: inherited # Groups 1.3 p.21 # 0x0005: inherited # Scenes 1.4 p.30 - no writable # 0x0006: inherited # On/Off 1.5 p.48 - 0x0008: [0,2,3,0x0F,0x11,0xFFFC,0xFFFD], # Level Control 1.6 p.57 + 0x0008: [0,2,3,0x0F,0x11], # Level Control 1.6 p.57 }) static var TYPES = { 0x0101: 2 } # Dimmable Light @@ -101,15 +101,10 @@ class Matter_Plugin_Bridge_Light1 : Matter_Plugin_Bridge_Light0 else return tlv_solo.set(TLV.NULL, nil) end - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0X01) # OnOff - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 5) # "new data model format and notation" end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Flow.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Flow.be index ddd0bd1e2..24f765768 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Flow.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Flow.be @@ -28,7 +28,7 @@ class Matter_Plugin_Bridge_Sensor_Flow : Matter_Plugin_Bridge_Sensor static var DISPLAY_NAME = "Flow" # display name of the plug-in static var CLUSTERS = matter.consolidate_clusters(_class, { - 0x0404: [0,1,2,0xFFFC,0xFFFD], # Flow Measurement + 0x0404: [0,1,2], # Flow Measurement }) static var TYPES = { 0x0306: 1 } # Flow Sensor, rev 1 @@ -70,15 +70,10 @@ class Matter_Plugin_Bridge_Sensor_Flow : Matter_Plugin_Bridge_Sensor return tlv_solo.set(TLV.U2, 0) # 0 m3/h elif attribute == 0x0002 # ---------- MaxMeasuredValue / i16 ---------- return tlv_solo.set(TLV.U2, 65534) # 65534 m3/h - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) # 0 = no Extended Range - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 3) # 3 = New data model format and notation end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Humidity.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Humidity.be index 7e8b62342..05e25437a 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Humidity.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Humidity.be @@ -28,7 +28,7 @@ class Matter_Plugin_Bridge_Sensor_Humidity : Matter_Plugin_Bridge_Sensor static var DISPLAY_NAME = "Humidity" # display name of the plug-in static var CLUSTERS = matter.consolidate_clusters(_class, { - 0x0405: [0,1,2,0xFFFC,0xFFFD], # Humidity Measurement p.102 - no writable + 0x0405: [0,1,2], # Humidity Measurement p.102 - no writable }) static var TYPES = { 0x0307: 2 } # Humidity Sensor, rev 2 @@ -70,15 +70,10 @@ class Matter_Plugin_Bridge_Sensor_Humidity : Matter_Plugin_Bridge_Sensor return tlv_solo.set(TLV.U2, 500) # 0% elif attribute == 0x0002 # ---------- MaxMeasuredValue / u16 ---------- return tlv_solo.set(TLV.U2, 10000) # 100% - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) # 0 = no Extended Range - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 3) # 3 = New data model format and notation end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Illuminance.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Illuminance.be index 48e0bf8de..88e0e32ee 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Illuminance.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Illuminance.be @@ -28,7 +28,7 @@ class Matter_Plugin_Bridge_Sensor_Illuminance : Matter_Plugin_Bridge_Sensor static var DISPLAY_NAME = "Illuminance" # display name of the plug-in static var CLUSTERS = matter.consolidate_clusters(_class, { - 0x0400: [0,1,2,0xFFFC,0xFFFD], # Illuminance Measurement p.95 - no writable + 0x0400: [0,1,2], # Illuminance Measurement p.95 - no writable }) static var TYPES = { 0x0106: 2 } # Illuminance Sensor, rev 2 @@ -77,15 +77,10 @@ class Matter_Plugin_Bridge_Sensor_Illuminance : Matter_Plugin_Bridge_Sensor return tlv_solo.set(TLV.U2, 1) # 1 lux elif attribute == 0x0002 # ---------- MaxMeasuredValue / i16 ---------- return tlv_solo.set(TLV.U2, 0xFFFE) - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 3) # 3 = New data model format and notation end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Pressure.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Pressure.be index 86dec0081..53b78393a 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Pressure.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Pressure.be @@ -28,7 +28,7 @@ class Matter_Plugin_Bridge_Sensor_Pressure : Matter_Plugin_Bridge_Sensor static var DISPLAY_NAME = "Pressure" # display name of the plug-in static var CLUSTERS = matter.consolidate_clusters(_class, { - 0x0403: [0,1,2,0xFFFC,0xFFFD], # Pressure Measurement + 0x0403: [0,1,2], # Pressure Measurement }) static var TYPES = { 0x0305: 2 } # Temperature Sensor, rev 2 @@ -70,15 +70,10 @@ class Matter_Plugin_Bridge_Sensor_Pressure : Matter_Plugin_Bridge_Sensor return tlv_solo.set(TLV.I2, 500) # 500 hPA elif attribute == 0x0002 # ---------- MaxMeasuredValue / i16 ---------- return tlv_solo.set(TLV.I2, 1500) # 1500 hPA - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) # 0 = no Extended Range - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 3) # 3 = New data model format and notation end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Temp.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Temp.be index 771c6eb7d..8ee8f73d1 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Temp.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_4_Bridge_Sensor_Temp.be @@ -28,7 +28,7 @@ class Matter_Plugin_Bridge_Sensor_Temp : Matter_Plugin_Bridge_Sensor static var DISPLAY_NAME = "Temperature" # display name of the plug-in static var CLUSTERS = matter.consolidate_clusters(_class, { - 0x0402: [0,1,2,0xFFFC,0xFFFD], # Temperature Measurement p.97 - no writable + 0x0402: [0,1,2], # Temperature Measurement p.97 - no writable }) static var TYPES = { 0x0302: 2 } # Temperature Sensor, rev 2 @@ -73,15 +73,10 @@ class Matter_Plugin_Bridge_Sensor_Temp : Matter_Plugin_Bridge_Sensor return tlv_solo.set(TLV.I2, -5000) # -50 °C elif attribute == 0x0002 # ---------- MaxMeasuredValue / i16 (*100) ---------- return tlv_solo.set(TLV.I2, 15000) # 150 °C - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0) - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 4) # 4 = New data model format and notation end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_5_Bridge_Light2.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_5_Bridge_Light2.be index 56d1d9de6..0c8595885 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_5_Bridge_Light2.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_5_Bridge_Light2.be @@ -35,7 +35,7 @@ class Matter_Plugin_Bridge_Light2 : Matter_Plugin_Bridge_Light1 # 0x0005: inherited # Scenes 1.4 p.30 - no writable # 0x0006: inherited # On/Off 1.5 p.48 # 0x0008: inherited # Level Control 1.6 p.57 - 0x0300: [7,8,0xF,0x400A,0x400B,0x400C,0xFFFC,0xFFFD], # Color Control 3.2 p.111 + 0x0300: [7,8,0xF,0x400A,0x400B,0x400C], # Color Control 3.2 p.111 }) static var TYPES = { 0x010C: 2 } # Dimmable Light @@ -117,15 +117,10 @@ class Matter_Plugin_Bridge_Light2 : Matter_Plugin_Bridge_Light1 elif attribute == 0x400A # ---------- ColorCapabilities / map32 ---------- return tlv_solo.set(TLV.U4, 0x10) # CT - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0x10) # CT - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 5) # "new data model format and notation, FeatureMap support" end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_5_Bridge_Light3.be b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_5_Bridge_Light3.be index abb4e9672..5b4f0ab30 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_5_Bridge_Light3.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_Plugin_5_Bridge_Light3.be @@ -35,7 +35,7 @@ class Matter_Plugin_Bridge_Light3 : Matter_Plugin_Bridge_Light1 # 0x0005: inherited # Scenes 1.4 p.30 - no writable # 0x0006: inherited # On/Off 1.5 p.48 # 0x0008: inherited # Level Control 1.6 p.57 - 0x0300: [0,1,7,8,0xF,0x4001,0x400A,0xFFFC,0xFFFD],# Color Control 3.2 p.111 + 0x0300: [0,1,7,8,0xF,0x4001,0x400A], # Color Control 3.2 p.111 }) static var TYPES = { 0x010D: 2 } # Extended Color Light @@ -126,16 +126,10 @@ class Matter_Plugin_Bridge_Light3 : Matter_Plugin_Bridge_Light1 # Defined Primaries Information Attribute Set elif attribute == 0x0010 # ---------- NumberOfPrimaries / u1 ---------- return tlv_solo.set(TLV.U1, 0) - - elif attribute == 0xFFFC # ---------- FeatureMap / map32 ---------- - return tlv_solo.set(TLV.U4, 0x01) # HS - elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ---------- - return tlv_solo.set(TLV.U4, 5) # "new data model format and notation, FeatureMap support" end - else - return super(self).read_attribute(session, ctx, tlv_solo) end + return super(self).read_attribute(session, ctx, tlv_solo) end ############################################################# diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_0_Inspect.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_0_Inspect.h index 079f5e775..58bf18064 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_0_Inspect.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_0_Inspect.h @@ -233,7 +233,7 @@ be_local_closure(matter_inspect, /* name */ ********************************************************************/ be_local_closure(matter_consolidate_clusters, /* name */ be_nested_proto( - 9, /* nstack */ + 12, /* nstack */ 2, /* argc */ 0, /* varg */ 0, /* has upvals */ @@ -241,61 +241,117 @@ be_local_closure(matter_consolidate_clusters, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ + ( &(const bvalue[ 6]) { /* constants */ /* K0 */ be_nested_str_weak(CLUSTERS), /* K1 */ be_nested_str_weak(keys), /* K2 */ be_nested_str_weak(copy), /* K3 */ be_nested_str_weak(stop_iteration), /* K4 */ be_nested_str_weak(find), + /* K5 */ be_nested_str_weak(push), }), be_str_weak(consolidate_clusters), &be_const_str_solidified, - ( &(const binstruction[45]) { /* code */ + ( &(const binstruction[100]) { /* code */ 0x60080003, // 0000 GETGBL R2 G3 0x5C0C0000, // 0001 MOVE R3 R0 0x7C080200, // 0002 CALL R2 1 - 0x88080500, // 0003 GETMBR R2 R2 K0 - 0x600C0013, // 0004 GETGBL R3 G19 - 0x7C0C0000, // 0005 CALL R3 0 - 0x60100010, // 0006 GETGBL R4 G16 - 0x8C140501, // 0007 GETMET R5 R2 K1 - 0x7C140200, // 0008 CALL R5 1 - 0x7C100200, // 0009 CALL R4 1 - 0xA8020006, // 000A EXBLK 0 #0012 - 0x5C140800, // 000B MOVE R5 R4 - 0x7C140000, // 000C CALL R5 0 - 0x94180405, // 000D GETIDX R6 R2 R5 - 0x8C180D02, // 000E GETMET R6 R6 K2 - 0x7C180200, // 000F CALL R6 1 - 0x980C0A06, // 0010 SETIDX R3 R5 R6 - 0x7001FFF8, // 0011 JMP #000B - 0x58100003, // 0012 LDCONST R4 K3 - 0xAC100200, // 0013 CATCH R4 1 0 - 0xB0080000, // 0014 RAISE 2 R0 R0 - 0x60100010, // 0015 GETGBL R4 G16 - 0x8C140301, // 0016 GETMET R5 R1 K1 - 0x7C140200, // 0017 CALL R5 1 - 0x7C100200, // 0018 CALL R4 1 - 0xA802000E, // 0019 EXBLK 0 #0029 - 0x5C140800, // 001A MOVE R5 R4 - 0x7C140000, // 001B CALL R5 0 - 0x8C180704, // 001C GETMET R6 R3 K4 - 0x5C200A00, // 001D MOVE R8 R5 - 0x7C180400, // 001E CALL R6 2 - 0x4C1C0000, // 001F LDNIL R7 - 0x1C1C0C07, // 0020 EQ R7 R6 R7 - 0x781E0002, // 0021 JMPF R7 #0025 - 0x601C0012, // 0022 GETGBL R7 G18 - 0x7C1C0000, // 0023 CALL R7 0 - 0x5C180E00, // 0024 MOVE R6 R7 - 0x941C0205, // 0025 GETIDX R7 R1 R5 - 0x001C0C07, // 0026 ADD R7 R6 R7 - 0x980C0A07, // 0027 SETIDX R3 R5 R7 - 0x7001FFF0, // 0028 JMP #001A - 0x58100003, // 0029 LDCONST R4 K3 - 0xAC100200, // 002A CATCH R4 1 0 - 0xB0080000, // 002B RAISE 2 R0 R0 - 0x80040600, // 002C RET 1 R3 + 0x4C0C0000, // 0003 LDNIL R3 + 0x20080403, // 0004 NE R2 R2 R3 + 0x780A0004, // 0005 JMPF R2 #000B + 0x60080003, // 0006 GETGBL R2 G3 + 0x5C0C0000, // 0007 MOVE R3 R0 + 0x7C080200, // 0008 CALL R2 1 + 0x88080500, // 0009 GETMBR R2 R2 K0 + 0x70020001, // 000A JMP #000D + 0x60080013, // 000B GETGBL R2 G19 + 0x7C080000, // 000C CALL R2 0 + 0x600C0013, // 000D GETGBL R3 G19 + 0x7C0C0000, // 000E CALL R3 0 + 0x60100010, // 000F GETGBL R4 G16 + 0x8C140501, // 0010 GETMET R5 R2 K1 + 0x7C140200, // 0011 CALL R5 1 + 0x7C100200, // 0012 CALL R4 1 + 0xA8020006, // 0013 EXBLK 0 #001B + 0x5C140800, // 0014 MOVE R5 R4 + 0x7C140000, // 0015 CALL R5 0 + 0x94180405, // 0016 GETIDX R6 R2 R5 + 0x8C180D02, // 0017 GETMET R6 R6 K2 + 0x7C180200, // 0018 CALL R6 1 + 0x980C0A06, // 0019 SETIDX R3 R5 R6 + 0x7001FFF8, // 001A JMP #0014 + 0x58100003, // 001B LDCONST R4 K3 + 0xAC100200, // 001C CATCH R4 1 0 + 0xB0080000, // 001D RAISE 2 R0 R0 + 0x60100010, // 001E GETGBL R4 G16 + 0x8C140301, // 001F GETMET R5 R1 K1 + 0x7C140200, // 0020 CALL R5 1 + 0x7C100200, // 0021 CALL R4 1 + 0xA802000E, // 0022 EXBLK 0 #0032 + 0x5C140800, // 0023 MOVE R5 R4 + 0x7C140000, // 0024 CALL R5 0 + 0x8C180704, // 0025 GETMET R6 R3 K4 + 0x5C200A00, // 0026 MOVE R8 R5 + 0x7C180400, // 0027 CALL R6 2 + 0x4C1C0000, // 0028 LDNIL R7 + 0x1C1C0C07, // 0029 EQ R7 R6 R7 + 0x781E0002, // 002A JMPF R7 #002E + 0x601C0012, // 002B GETGBL R7 G18 + 0x7C1C0000, // 002C CALL R7 0 + 0x5C180E00, // 002D MOVE R6 R7 + 0x941C0205, // 002E GETIDX R7 R1 R5 + 0x001C0C07, // 002F ADD R7 R6 R7 + 0x980C0A07, // 0030 SETIDX R3 R5 R7 + 0x7001FFF0, // 0031 JMP #0023 + 0x58100003, // 0032 LDCONST R4 K3 + 0xAC100200, // 0033 CATCH R4 1 0 + 0xB0080000, // 0034 RAISE 2 R0 R0 + 0x60100012, // 0035 GETGBL R4 G18 + 0x7C100000, // 0036 CALL R4 0 + 0x5416FFF7, // 0037 LDINT R5 65528 + 0x40140805, // 0038 CONNECT R5 R4 R5 + 0x5416FFF8, // 0039 LDINT R5 65529 + 0x40140805, // 003A CONNECT R5 R4 R5 + 0x5416FFF9, // 003B LDINT R5 65530 + 0x40140805, // 003C CONNECT R5 R4 R5 + 0x5416FFFA, // 003D LDINT R5 65531 + 0x40140805, // 003E CONNECT R5 R4 R5 + 0x5416FFFB, // 003F LDINT R5 65532 + 0x40140805, // 0040 CONNECT R5 R4 R5 + 0x5416FFFC, // 0041 LDINT R5 65533 + 0x40140805, // 0042 CONNECT R5 R4 R5 + 0x60140010, // 0043 GETGBL R5 G16 + 0x8C180301, // 0044 GETMET R6 R1 K1 + 0x7C180200, // 0045 CALL R6 1 + 0x7C140200, // 0046 CALL R5 1 + 0xA8020017, // 0047 EXBLK 0 #0060 + 0x5C180A00, // 0048 MOVE R6 R5 + 0x7C180000, // 0049 CALL R6 0 + 0x601C0010, // 004A GETGBL R7 G16 + 0x5C200800, // 004B MOVE R8 R4 + 0x7C1C0200, // 004C CALL R7 1 + 0xA802000D, // 004D EXBLK 0 #005C + 0x5C200E00, // 004E MOVE R8 R7 + 0x7C200000, // 004F CALL R8 0 + 0x94240606, // 0050 GETIDX R9 R3 R6 + 0x8C241304, // 0051 GETMET R9 R9 K4 + 0x5C2C1000, // 0052 MOVE R11 R8 + 0x7C240400, // 0053 CALL R9 2 + 0x4C280000, // 0054 LDNIL R10 + 0x1C24120A, // 0055 EQ R9 R9 R10 + 0x78260003, // 0056 JMPF R9 #005B + 0x94240606, // 0057 GETIDX R9 R3 R6 + 0x8C241305, // 0058 GETMET R9 R9 K5 + 0x5C2C1000, // 0059 MOVE R11 R8 + 0x7C240400, // 005A CALL R9 2 + 0x7001FFF1, // 005B JMP #004E + 0x581C0003, // 005C LDCONST R7 K3 + 0xAC1C0200, // 005D CATCH R7 1 0 + 0xB0080000, // 005E RAISE 2 R0 R0 + 0x7001FFE7, // 005F JMP #0048 + 0x58140003, // 0060 LDCONST R5 K3 + 0xAC140200, // 0061 CATCH R5 1 0 + 0xB0080000, // 0062 RAISE 2 R0 R0 + 0x80040600, // 0063 RET 1 R3 }) ) ); diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_0.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_0.h index f34e08665..6969dce2d 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_0.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_0.h @@ -7,41 +7,61 @@ extern const bclass be_class_Matter_Plugin; /******************************************************************** -** Solidified function: ack_request +** Solidified function: every_250ms ********************************************************************/ -be_local_closure(Matter_Plugin_ack_request, /* name */ +be_local_closure(Matter_Plugin_every_250ms, /* name */ be_nested_proto( - 6, /* nstack */ - 2, /* argc */ + 4, /* nstack */ + 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_nested_str_weak(msg), - /* K1 */ be_nested_str_weak(device), - /* K2 */ be_nested_str_weak(message_handler), - /* K3 */ be_nested_str_weak(im), - /* K4 */ be_nested_str_weak(send_ack_now), + ( &(const bvalue[10]) { /* constants */ + /* K0 */ be_nested_str_weak(update_next), + /* K1 */ be_nested_str_weak(matter), + /* K2 */ be_nested_str_weak(jitter), + /* K3 */ be_nested_str_weak(UPDATE_TIME), + /* K4 */ be_nested_str_weak(tasmota), + /* K5 */ be_nested_str_weak(time_reached), + /* K6 */ be_nested_str_weak(tick), + /* K7 */ be_nested_str_weak(device), + /* K8 */ be_nested_str_weak(update_shadow), + /* K9 */ be_nested_str_weak(millis), }), - be_str_weak(ack_request), + be_str_weak(every_250ms), &be_const_str_solidified, - ( &(const binstruction[13]) { /* code */ - 0x88080300, // 0000 GETMBR R2 R1 K0 - 0x4C0C0000, // 0001 LDNIL R3 - 0x200C0403, // 0002 NE R3 R2 R3 - 0x780E0005, // 0003 JMPF R3 #000A - 0x880C0101, // 0004 GETMBR R3 R0 K1 - 0x880C0702, // 0005 GETMBR R3 R3 K2 - 0x880C0703, // 0006 GETMBR R3 R3 K3 - 0x8C0C0704, // 0007 GETMET R3 R3 K4 - 0x5C140400, // 0008 MOVE R5 R2 - 0x7C0C0400, // 0009 CALL R3 2 - 0x4C0C0000, // 000A LDNIL R3 - 0x90060003, // 000B SETMBR R1 K0 R3 - 0x80000000, // 000C RET 0 + ( &(const binstruction[28]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x4C080000, // 0001 LDNIL R2 + 0x1C040202, // 0002 EQ R1 R1 R2 + 0x78060005, // 0003 JMPF R1 #000A + 0xB8060200, // 0004 GETNGBL R1 K1 + 0x8C040302, // 0005 GETMET R1 R1 K2 + 0x880C0103, // 0006 GETMBR R3 R0 K3 + 0x7C040400, // 0007 CALL R1 2 + 0x90020001, // 0008 SETMBR R0 K0 R1 + 0x70020010, // 0009 JMP #001B + 0xB8060800, // 000A GETNGBL R1 K4 + 0x8C040305, // 000B GETMET R1 R1 K5 + 0x880C0100, // 000C GETMBR R3 R0 K0 + 0x7C040400, // 000D CALL R1 2 + 0x7806000B, // 000E JMPF R1 #001B + 0x88040106, // 000F GETMBR R1 R0 K6 + 0x88080107, // 0010 GETMBR R2 R0 K7 + 0x88080506, // 0011 GETMBR R2 R2 K6 + 0x20040202, // 0012 NE R1 R1 R2 + 0x78060001, // 0013 JMPF R1 #0016 + 0x8C040108, // 0014 GETMET R1 R0 K8 + 0x7C040200, // 0015 CALL R1 1 + 0xB8060800, // 0016 GETNGBL R1 K4 + 0x8C040309, // 0017 GETMET R1 R1 K9 + 0x880C0103, // 0018 GETMBR R3 R0 K3 + 0x7C040400, // 0019 CALL R1 2 + 0x90020001, // 001A SETMBR R0 K0 R1 + 0x80000000, // 001B RET 0 }) ) ); @@ -76,42 +96,12 @@ be_local_closure(Matter_Plugin_consolidate_clusters, /* name */ /******************************************************************** -** Solidified function: update_shadow +** Solidified function: subscribe_attribute ********************************************************************/ -be_local_closure(Matter_Plugin_update_shadow, /* name */ +be_local_closure(Matter_Plugin_subscribe_attribute, /* name */ be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(tick), - /* K1 */ be_nested_str_weak(device), - }), - be_str_weak(update_shadow), - &be_const_str_solidified, - ( &(const binstruction[ 4]) { /* code */ - 0x88040101, // 0000 GETMBR R1 R0 K1 - 0x88040300, // 0001 GETMBR R1 R1 K0 - 0x90020001, // 0002 SETMBR R0 K0 R1 - 0x80000000, // 0003 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: parse_sensors -********************************************************************/ -be_local_closure(Matter_Plugin_parse_sensors, /* name */ - be_nested_proto( - 2, /* nstack */ - 2, /* argc */ + 6, /* nstack */ + 5, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -119,10 +109,11 @@ be_local_closure(Matter_Plugin_parse_sensors, /* name */ NULL, /* no sub protos */ 0, /* has constants */ NULL, /* no const */ - be_str_weak(parse_sensors), + be_str_weak(subscribe_attribute), &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 + ( &(const binstruction[ 2]) { /* code */ + 0x4C140000, // 0000 LDNIL R5 + 0x80040A00, // 0001 RET 1 R5 }) ) ); @@ -130,9 +121,116 @@ be_local_closure(Matter_Plugin_parse_sensors, /* name */ /******************************************************************** -** Solidified function: consolidate_update_commands +** Solidified function: init ********************************************************************/ -be_local_closure(Matter_Plugin_consolidate_update_commands, /* name */ +be_local_closure(Matter_Plugin_init, /* name */ + be_nested_proto( + 8, /* nstack */ + 4, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 9]) { /* constants */ + /* K0 */ be_nested_str_weak(device), + /* K1 */ be_nested_str_weak(endpoint), + /* K2 */ be_nested_str_weak(clusters), + /* K3 */ be_nested_str_weak(consolidate_clusters), + /* K4 */ be_nested_str_weak(parse_configuration), + /* K5 */ be_nested_str_weak(node_label), + /* K6 */ be_nested_str_weak(find), + /* K7 */ be_nested_str_weak(name), + /* K8 */ be_nested_str_weak(), + }), + be_str_weak(init), + &be_const_str_solidified, + ( &(const binstruction[14]) { /* code */ + 0x90020001, // 0000 SETMBR R0 K0 R1 + 0x90020202, // 0001 SETMBR R0 K1 R2 + 0x8C100103, // 0002 GETMET R4 R0 K3 + 0x7C100200, // 0003 CALL R4 1 + 0x90020404, // 0004 SETMBR R0 K2 R4 + 0x8C100104, // 0005 GETMET R4 R0 K4 + 0x5C180600, // 0006 MOVE R6 R3 + 0x7C100400, // 0007 CALL R4 2 + 0x8C100706, // 0008 GETMET R4 R3 K6 + 0x58180007, // 0009 LDCONST R6 K7 + 0x581C0008, // 000A LDCONST R7 K8 + 0x7C100600, // 000B CALL R4 3 + 0x90020A04, // 000C SETMBR R0 K5 R4 + 0x80000000, // 000D RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: set_name +********************************************************************/ +be_local_closure(Matter_Plugin_set_name, /* name */ + be_nested_proto( + 6, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(node_label), + /* K1 */ be_nested_str_weak(attribute_updated), + }), + be_str_weak(set_name), + &be_const_str_solidified, + ( &(const binstruction[ 9]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x20080202, // 0001 NE R2 R1 R2 + 0x780A0003, // 0002 JMPF R2 #0007 + 0x8C080101, // 0003 GETMET R2 R0 K1 + 0x54120038, // 0004 LDINT R4 57 + 0x54160004, // 0005 LDINT R5 5 + 0x7C080600, // 0006 CALL R2 3 + 0x90020001, // 0007 SETMBR R0 K0 R1 + 0x80000000, // 0008 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: subscribe_event +********************************************************************/ +be_local_closure(Matter_Plugin_subscribe_event, /* name */ + be_nested_proto( + 6, /* nstack */ + 5, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(subscribe_event), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x4C140000, // 0000 LDNIL R5 + 0x80040A00, // 0001 RET 1 R5 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_name +********************************************************************/ +be_local_closure(Matter_Plugin_get_name, /* name */ be_nested_proto( 2, /* nstack */ 1, /* argc */ @@ -143,9 +241,9 @@ be_local_closure(Matter_Plugin_consolidate_update_commands, /* name */ NULL, /* no sub protos */ 1, /* has constants */ ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(UPDATE_COMMANDS), + /* K0 */ be_nested_str_weak(node_label), }), - be_str_weak(consolidate_update_commands), + be_str_weak(get_name), &be_const_str_solidified, ( &(const binstruction[ 2]) { /* code */ 0x88040100, // 0000 GETMBR R1 R0 K0 @@ -236,24 +334,39 @@ be_local_closure(Matter_Plugin_publish_command, /* name */ /******************************************************************** -** Solidified function: subscribe_attribute +** Solidified function: ui_conf_to_string ********************************************************************/ -be_local_closure(Matter_Plugin_subscribe_attribute, /* name */ +be_local_closure(Matter_Plugin_ui_conf_to_string, /* name */ be_nested_proto( - 6, /* nstack */ - 5, /* argc */ - 2, /* varg */ + 9, /* nstack */ + 2, /* argc */ + 4, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(subscribe_attribute), + 1, /* has constants */ + ( &(const bvalue[ 4]) { /* constants */ + /* K0 */ be_const_class(be_class_Matter_Plugin), + /* K1 */ be_nested_str_weak(ARG), + /* K2 */ be_nested_str_weak(find), + /* K3 */ be_nested_str_weak(), + }), + be_str_weak(ui_conf_to_string), &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x4C140000, // 0000 LDNIL R5 - 0x80040A00, // 0001 RET 1 R5 + ( &(const binstruction[12]) { /* code */ + 0x58080000, // 0000 LDCONST R2 K0 + 0x880C0101, // 0001 GETMBR R3 R0 K1 + 0x780E0006, // 0002 JMPF R3 #000A + 0x60100008, // 0003 GETGBL R4 G8 + 0x8C140302, // 0004 GETMET R5 R1 K2 + 0x5C1C0600, // 0005 MOVE R7 R3 + 0x58200003, // 0006 LDCONST R8 K3 + 0x7C140600, // 0007 CALL R5 3 + 0x7C100200, // 0008 CALL R4 1 + 0x70020000, // 0009 JMP #000B + 0x58100003, // 000A LDCONST R4 K3 + 0x80040800, // 000B RET 1 R4 }) ) ); @@ -273,7 +386,7 @@ be_local_closure(Matter_Plugin_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[18]) { /* constants */ + ( &(const bvalue[22]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -292,17 +405,21 @@ be_local_closure(Matter_Plugin_read_attribute, /* name */ /* K15 */ be_const_int(2), /* K16 */ be_const_int(3), /* K17 */ be_nested_str_weak(set), + /* K18 */ be_nested_str_weak(get_attribute_list), + /* K19 */ be_nested_str_weak(FEATURE_MAPS), + /* K20 */ be_nested_str_weak(find), + /* K21 */ be_nested_str_weak(CLUSTER_REVISIONS), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[92]) { /* code */ + ( &(const binstruction[160]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E001C, // 0004 LDINT R7 29 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0051, // 0006 JMPF R7 #0059 + 0x781E0050, // 0006 JMPF R7 #0058 0x1C1C0D04, // 0007 EQ R7 R6 K4 0x781E001B, // 0008 JMPF R7 #0025 0x8C1C0905, // 0009 GETMET R7 R4 K5 @@ -384,10 +501,78 @@ be_local_closure(Matter_Plugin_read_attribute, /* name */ 0x5828000B, // 0055 LDCONST R10 K11 0x7C1C0600, // 0056 CALL R7 3 0x80040E00, // 0057 RET 1 R7 - 0x70020001, // 0058 JMP #005B - 0x4C1C0000, // 0059 LDNIL R7 - 0x80040E00, // 005A RET 1 R7 - 0x80000000, // 005B RET 0 + 0x541EFFF7, // 0058 LDINT R7 65528 + 0x1C1C0C07, // 0059 EQ R7 R6 R7 + 0x781E0003, // 005A JMPF R7 #005F + 0x8C1C0905, // 005B GETMET R7 R4 K5 + 0x7C1C0200, // 005C CALL R7 1 + 0x80040E00, // 005D RET 1 R7 + 0x7002003F, // 005E JMP #009F + 0x541EFFF8, // 005F LDINT R7 65529 + 0x1C1C0C07, // 0060 EQ R7 R6 R7 + 0x781E0013, // 0061 JMPF R7 #0076 + 0x8C1C0905, // 0062 GETMET R7 R4 K5 + 0x7C1C0200, // 0063 CALL R7 1 + 0x8C200112, // 0064 GETMET R8 R0 K18 + 0x5C280A00, // 0065 MOVE R10 R5 + 0x7C200400, // 0066 CALL R8 2 + 0x58240004, // 0067 LDCONST R9 K4 + 0x6028000C, // 0068 GETGBL R10 G12 + 0x5C2C1000, // 0069 MOVE R11 R8 + 0x7C280200, // 006A CALL R10 1 + 0x1428120A, // 006B LT R10 R9 R10 + 0x782A0006, // 006C JMPF R10 #0074 + 0x8C280F09, // 006D GETMET R10 R7 K9 + 0x4C300000, // 006E LDNIL R12 + 0x8834090A, // 006F GETMBR R13 R4 K10 + 0x94381009, // 0070 GETIDX R14 R8 R9 + 0x7C280800, // 0071 CALL R10 4 + 0x0024130B, // 0072 ADD R9 R9 K11 + 0x7001FFF3, // 0073 JMP #0068 + 0x80040E00, // 0074 RET 1 R7 + 0x70020028, // 0075 JMP #009F + 0x541EFFF9, // 0076 LDINT R7 65530 + 0x1C1C0C07, // 0077 EQ R7 R6 R7 + 0x781E0003, // 0078 JMPF R7 #007D + 0x8C1C0905, // 0079 GETMET R7 R4 K5 + 0x7C1C0200, // 007A CALL R7 1 + 0x80040E00, // 007B RET 1 R7 + 0x70020021, // 007C JMP #009F + 0x541EFFFA, // 007D LDINT R7 65531 + 0x1C1C0C07, // 007E EQ R7 R6 R7 + 0x781E0003, // 007F JMPF R7 #0084 + 0x8C1C0905, // 0080 GETMET R7 R4 K5 + 0x7C1C0200, // 0081 CALL R7 1 + 0x80040E00, // 0082 RET 1 R7 + 0x7002001A, // 0083 JMP #009F + 0x541EFFFB, // 0084 LDINT R7 65532 + 0x1C1C0C07, // 0085 EQ R7 R6 R7 + 0x781E000A, // 0086 JMPF R7 #0092 + 0x881C0113, // 0087 GETMBR R7 R0 K19 + 0x8C1C0F14, // 0088 GETMET R7 R7 K20 + 0x5C240A00, // 0089 MOVE R9 R5 + 0x58280004, // 008A LDCONST R10 K4 + 0x7C1C0600, // 008B CALL R7 3 + 0x8C200711, // 008C GETMET R8 R3 K17 + 0x8828090E, // 008D GETMBR R10 R4 K14 + 0x5C2C0E00, // 008E MOVE R11 R7 + 0x7C200600, // 008F CALL R8 3 + 0x80041000, // 0090 RET 1 R8 + 0x7002000C, // 0091 JMP #009F + 0x541EFFFC, // 0092 LDINT R7 65533 + 0x1C1C0C07, // 0093 EQ R7 R6 R7 + 0x781E0009, // 0094 JMPF R7 #009F + 0x881C0115, // 0095 GETMBR R7 R0 K21 + 0x8C1C0F14, // 0096 GETMET R7 R7 K20 + 0x5C240A00, // 0097 MOVE R9 R5 + 0x5828000B, // 0098 LDCONST R10 K11 + 0x7C1C0600, // 0099 CALL R7 3 + 0x8C200711, // 009A GETMET R8 R3 K17 + 0x8828090E, // 009B GETMBR R10 R4 K14 + 0x5C2C0E00, // 009C MOVE R11 R7 + 0x7C200600, // 009D CALL R8 3 + 0x80041000, // 009E RET 1 R8 + 0x80000000, // 009F RET 0 }) ) ); @@ -395,34 +580,9 @@ be_local_closure(Matter_Plugin_read_attribute, /* name */ /******************************************************************** -** Solidified function: timed_request +** Solidified function: ack_request ********************************************************************/ -be_local_closure(Matter_Plugin_timed_request, /* name */ - be_nested_proto( - 5, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(timed_request), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x4C100000, // 0000 LDNIL R4 - 0x80040800, // 0001 RET 1 R4 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: set_name -********************************************************************/ -be_local_closure(Matter_Plugin_set_name, /* name */ +be_local_closure(Matter_Plugin_ack_request, /* name */ be_nested_proto( 6, /* nstack */ 2, /* argc */ @@ -432,248 +592,29 @@ be_local_closure(Matter_Plugin_set_name, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(node_label), - /* K1 */ be_nested_str_weak(attribute_updated), - }), - be_str_weak(set_name), - &be_const_str_solidified, - ( &(const binstruction[ 9]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x20080202, // 0001 NE R2 R1 R2 - 0x780A0003, // 0002 JMPF R2 #0007 - 0x8C080101, // 0003 GETMET R2 R0 K1 - 0x54120038, // 0004 LDINT R4 57 - 0x54160004, // 0005 LDINT R5 5 - 0x7C080600, // 0006 CALL R2 3 - 0x90020001, // 0007 SETMBR R0 K0 R1 - 0x80000000, // 0008 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: is_local_device -********************************************************************/ -be_local_closure(Matter_Plugin_is_local_device, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(is_local_device), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x50040200, // 0000 LDBOOL R1 1 0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_name -********************************************************************/ -be_local_closure(Matter_Plugin_get_name, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(node_label), - }), - be_str_weak(get_name), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: init -********************************************************************/ -be_local_closure(Matter_Plugin_init, /* name */ - be_nested_proto( - 8, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 9]) { /* constants */ - /* K0 */ be_nested_str_weak(device), - /* K1 */ be_nested_str_weak(endpoint), - /* K2 */ be_nested_str_weak(clusters), - /* K3 */ be_nested_str_weak(consolidate_clusters), - /* K4 */ be_nested_str_weak(parse_configuration), - /* K5 */ be_nested_str_weak(node_label), - /* K6 */ be_nested_str_weak(find), - /* K7 */ be_nested_str_weak(name), - /* K8 */ be_nested_str_weak(), - }), - be_str_weak(init), - &be_const_str_solidified, - ( &(const binstruction[14]) { /* code */ - 0x90020001, // 0000 SETMBR R0 K0 R1 - 0x90020202, // 0001 SETMBR R0 K1 R2 - 0x8C100103, // 0002 GETMET R4 R0 K3 - 0x7C100200, // 0003 CALL R4 1 - 0x90020404, // 0004 SETMBR R0 K2 R4 - 0x8C100104, // 0005 GETMET R4 R0 K4 - 0x5C180600, // 0006 MOVE R6 R3 - 0x7C100400, // 0007 CALL R4 2 - 0x8C100706, // 0008 GETMET R4 R3 K6 - 0x58180007, // 0009 LDCONST R6 K7 - 0x581C0008, // 000A LDCONST R7 K8 - 0x7C100600, // 000B CALL R4 3 - 0x90020A04, // 000C SETMBR R0 K5 R4 - 0x80000000, // 000D RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: update_shadow_lazy -********************************************************************/ -be_local_closure(Matter_Plugin_update_shadow_lazy, /* name */ - be_nested_proto( - 3, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(tick), + ( &(const bvalue[ 5]) { /* constants */ + /* K0 */ be_nested_str_weak(msg), /* K1 */ be_nested_str_weak(device), - /* K2 */ be_nested_str_weak(update_shadow), + /* K2 */ be_nested_str_weak(message_handler), + /* K3 */ be_nested_str_weak(im), + /* K4 */ be_nested_str_weak(send_ack_now), }), - be_str_weak(update_shadow_lazy), + be_str_weak(ack_request), &be_const_str_solidified, - ( &(const binstruction[11]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x88080101, // 0001 GETMBR R2 R0 K1 - 0x88080500, // 0002 GETMBR R2 R2 K0 - 0x20040202, // 0003 NE R1 R1 R2 - 0x78060004, // 0004 JMPF R1 #000A - 0x8C040102, // 0005 GETMET R1 R0 K2 - 0x7C040200, // 0006 CALL R1 1 - 0x88040101, // 0007 GETMBR R1 R0 K1 - 0x88040300, // 0008 GETMBR R1 R1 K0 - 0x90020001, // 0009 SETMBR R0 K0 R1 - 0x80000000, // 000A RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: invoke_request -********************************************************************/ -be_local_closure(Matter_Plugin_invoke_request, /* name */ - be_nested_proto( - 5, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 0, /* has constants */ - NULL, /* no const */ - be_str_weak(invoke_request), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x4C100000, // 0000 LDNIL R4 - 0x80040800, // 0001 RET 1 R4 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: ui_string_to_conf -********************************************************************/ -be_local_closure(Matter_Plugin_ui_string_to_conf, /* name */ - be_nested_proto( - 8, /* nstack */ - 3, /* argc */ - 4, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_const_class(be_class_Matter_Plugin), - /* K1 */ be_nested_str_weak(ARG), - /* K2 */ be_nested_str_weak(ARG_TYPE), - }), - be_str_weak(ui_string_to_conf), - &be_const_str_solidified, - ( &(const binstruction[10]) { /* code */ - 0x580C0000, // 0000 LDCONST R3 K0 - 0x88100101, // 0001 GETMBR R4 R0 K1 - 0x88140102, // 0002 GETMBR R5 R0 K2 - 0x780A0004, // 0003 JMPF R2 #0009 - 0x78120003, // 0004 JMPF R4 #0009 - 0x5C180A00, // 0005 MOVE R6 R5 - 0x5C1C0400, // 0006 MOVE R7 R2 - 0x7C180200, // 0007 CALL R6 1 - 0x98040806, // 0008 SETIDX R1 R4 R6 - 0x80040200, // 0009 RET 1 R1 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: get_endpoint -********************************************************************/ -be_local_closure(Matter_Plugin_get_endpoint, /* name */ - be_nested_proto( - 2, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(endpoint), - }), - be_str_weak(get_endpoint), - &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x80040200, // 0001 RET 1 R1 + ( &(const binstruction[13]) { /* code */ + 0x88080300, // 0000 GETMBR R2 R1 K0 + 0x4C0C0000, // 0001 LDNIL R3 + 0x200C0403, // 0002 NE R3 R2 R3 + 0x780E0005, // 0003 JMPF R3 #000A + 0x880C0101, // 0004 GETMBR R3 R0 K1 + 0x880C0702, // 0005 GETMBR R3 R3 K2 + 0x880C0703, // 0006 GETMBR R3 R3 K3 + 0x8C0C0704, // 0007 GETMET R3 R3 K4 + 0x5C140400, // 0008 MOVE R5 R2 + 0x7C0C0400, // 0009 CALL R3 2 + 0x4C0C0000, // 000A LDNIL R3 + 0x90060003, // 000B SETMBR R1 K0 R3 + 0x80000000, // 000C RET 0 }) ) ); @@ -713,32 +654,6 @@ be_local_closure(Matter_Plugin_get_attribute_list, /* name */ /*******************************************************************/ -/******************************************************************** -** Solidified function: append_state_json -********************************************************************/ -be_local_closure(Matter_Plugin_append_state_json, /* name */ - be_nested_proto( - 1, /* nstack */ - 1, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 1]) { /* constants */ - /* K0 */ be_nested_str_weak(), - }), - be_str_weak(append_state_json), - &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80060000, // 0000 RET 1 K0 - }) - ) -); -/*******************************************************************/ - - /******************************************************************** ** Solidified function: read_event ********************************************************************/ @@ -788,6 +703,120 @@ be_local_closure(Matter_Plugin_parse_configuration, /* name */ /*******************************************************************/ +/******************************************************************** +** Solidified function: consolidate_update_commands +********************************************************************/ +be_local_closure(Matter_Plugin_consolidate_update_commands, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(UPDATE_COMMANDS), + }), + be_str_weak(consolidate_update_commands), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: attribute_updated +********************************************************************/ +be_local_closure(Matter_Plugin_attribute_updated, /* name */ + be_nested_proto( + 10, /* nstack */ + 4, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(device), + /* K1 */ be_nested_str_weak(attribute_updated), + /* K2 */ be_nested_str_weak(endpoint), + }), + be_str_weak(attribute_updated), + &be_const_str_solidified, + ( &(const binstruction[ 8]) { /* code */ + 0x88100100, // 0000 GETMBR R4 R0 K0 + 0x8C100901, // 0001 GETMET R4 R4 K1 + 0x88180102, // 0002 GETMBR R6 R0 K2 + 0x5C1C0200, // 0003 MOVE R7 R1 + 0x5C200400, // 0004 MOVE R8 R2 + 0x5C240600, // 0005 MOVE R9 R3 + 0x7C100A00, // 0006 CALL R4 5 + 0x80000000, // 0007 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: timed_request +********************************************************************/ +be_local_closure(Matter_Plugin_timed_request, /* name */ + be_nested_proto( + 5, /* nstack */ + 4, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(timed_request), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x4C100000, // 0000 LDNIL R4 + 0x80040800, // 0001 RET 1 R4 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: get_endpoint +********************************************************************/ +be_local_closure(Matter_Plugin_get_endpoint, /* name */ + be_nested_proto( + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(endpoint), + }), + be_str_weak(get_endpoint), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x88040100, // 0000 GETMBR R1 R0 K0 + 0x80040200, // 0001 RET 1 R1 + }) + ) +); +/*******************************************************************/ + + /******************************************************************** ** Solidified function: state_json ********************************************************************/ @@ -846,12 +875,42 @@ be_local_closure(Matter_Plugin_state_json, /* name */ /******************************************************************** -** Solidified function: subscribe_event +** Solidified function: update_shadow ********************************************************************/ -be_local_closure(Matter_Plugin_subscribe_event, /* name */ +be_local_closure(Matter_Plugin_update_shadow, /* name */ be_nested_proto( - 6, /* nstack */ - 5, /* argc */ + 2, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(tick), + /* K1 */ be_nested_str_weak(device), + }), + be_str_weak(update_shadow), + &be_const_str_solidified, + ( &(const binstruction[ 4]) { /* code */ + 0x88040101, // 0000 GETMBR R1 R0 K1 + 0x88040300, // 0001 GETMBR R1 R1 K0 + 0x90020001, // 0002 SETMBR R0 K0 R1 + 0x80000000, // 0003 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: write_attribute +********************************************************************/ +be_local_closure(Matter_Plugin_write_attribute, /* name */ + be_nested_proto( + 5, /* nstack */ + 4, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -859,11 +918,11 @@ be_local_closure(Matter_Plugin_subscribe_event, /* name */ NULL, /* no sub protos */ 0, /* has constants */ NULL, /* no const */ - be_str_weak(subscribe_event), + be_str_weak(write_attribute), &be_const_str_solidified, ( &(const binstruction[ 2]) { /* code */ - 0x4C140000, // 0000 LDNIL R5 - 0x80040A00, // 0001 RET 1 R5 + 0x4C100000, // 0000 LDNIL R4 + 0x80040800, // 0001 RET 1 R4 }) ) ); @@ -914,11 +973,36 @@ be_local_closure(Matter_Plugin_has, /* name */ /******************************************************************** -** Solidified function: every_250ms +** Solidified function: invoke_request ********************************************************************/ -be_local_closure(Matter_Plugin_every_250ms, /* name */ +be_local_closure(Matter_Plugin_invoke_request, /* name */ be_nested_proto( - 4, /* nstack */ + 5, /* nstack */ + 4, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(invoke_request), + &be_const_str_solidified, + ( &(const binstruction[ 2]) { /* code */ + 0x4C100000, // 0000 LDNIL R4 + 0x80040800, // 0001 RET 1 R4 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: update_shadow_lazy +********************************************************************/ +be_local_closure(Matter_Plugin_update_shadow_lazy, /* name */ + be_nested_proto( + 3, /* nstack */ 1, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -926,49 +1010,75 @@ be_local_closure(Matter_Plugin_every_250ms, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[10]) { /* constants */ - /* K0 */ be_nested_str_weak(update_next), - /* K1 */ be_nested_str_weak(matter), - /* K2 */ be_nested_str_weak(jitter), - /* K3 */ be_nested_str_weak(UPDATE_TIME), - /* K4 */ be_nested_str_weak(tasmota), - /* K5 */ be_nested_str_weak(time_reached), - /* K6 */ be_nested_str_weak(tick), - /* K7 */ be_nested_str_weak(device), - /* K8 */ be_nested_str_weak(update_shadow), - /* K9 */ be_nested_str_weak(millis), + ( &(const bvalue[ 3]) { /* constants */ + /* K0 */ be_nested_str_weak(tick), + /* K1 */ be_nested_str_weak(device), + /* K2 */ be_nested_str_weak(update_shadow), }), - be_str_weak(every_250ms), + be_str_weak(update_shadow_lazy), &be_const_str_solidified, - ( &(const binstruction[28]) { /* code */ + ( &(const binstruction[11]) { /* code */ 0x88040100, // 0000 GETMBR R1 R0 K0 - 0x4C080000, // 0001 LDNIL R2 - 0x1C040202, // 0002 EQ R1 R1 R2 - 0x78060005, // 0003 JMPF R1 #000A - 0xB8060200, // 0004 GETNGBL R1 K1 - 0x8C040302, // 0005 GETMET R1 R1 K2 - 0x880C0103, // 0006 GETMBR R3 R0 K3 - 0x7C040400, // 0007 CALL R1 2 - 0x90020001, // 0008 SETMBR R0 K0 R1 - 0x70020010, // 0009 JMP #001B - 0xB8060800, // 000A GETNGBL R1 K4 - 0x8C040305, // 000B GETMET R1 R1 K5 - 0x880C0100, // 000C GETMBR R3 R0 K0 - 0x7C040400, // 000D CALL R1 2 - 0x7806000B, // 000E JMPF R1 #001B - 0x88040106, // 000F GETMBR R1 R0 K6 - 0x88080107, // 0010 GETMBR R2 R0 K7 - 0x88080506, // 0011 GETMBR R2 R2 K6 - 0x20040202, // 0012 NE R1 R1 R2 - 0x78060001, // 0013 JMPF R1 #0016 - 0x8C040108, // 0014 GETMET R1 R0 K8 - 0x7C040200, // 0015 CALL R1 1 - 0xB8060800, // 0016 GETNGBL R1 K4 - 0x8C040309, // 0017 GETMET R1 R1 K9 - 0x880C0103, // 0018 GETMBR R3 R0 K3 - 0x7C040400, // 0019 CALL R1 2 - 0x90020001, // 001A SETMBR R0 K0 R1 - 0x80000000, // 001B RET 0 + 0x88080101, // 0001 GETMBR R2 R0 K1 + 0x88080500, // 0002 GETMBR R2 R2 K0 + 0x20040202, // 0003 NE R1 R1 R2 + 0x78060004, // 0004 JMPF R1 #000A + 0x8C040102, // 0005 GETMET R1 R0 K2 + 0x7C040200, // 0006 CALL R1 1 + 0x88040101, // 0007 GETMBR R1 R0 K1 + 0x88040300, // 0008 GETMBR R1 R1 K0 + 0x90020001, // 0009 SETMBR R0 K0 R1 + 0x80000000, // 000A RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: update_virtual +********************************************************************/ +be_local_closure(Matter_Plugin_update_virtual, /* name */ + be_nested_proto( + 2, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 0, /* has constants */ + NULL, /* no const */ + be_str_weak(update_virtual), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: append_state_json +********************************************************************/ +be_local_closure(Matter_Plugin_append_state_json, /* name */ + be_nested_proto( + 1, /* nstack */ + 1, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 1]) { /* constants */ + /* K0 */ be_nested_str_weak(), + }), + be_str_weak(append_state_json), + &be_const_str_solidified, + ( &(const binstruction[ 1]) { /* code */ + 0x80060000, // 0000 RET 1 K0 }) ) ); @@ -1026,12 +1136,12 @@ be_local_closure(Matter_Plugin_contains_attribute, /* name */ /******************************************************************** -** Solidified function: write_attribute +** Solidified function: parse_sensors ********************************************************************/ -be_local_closure(Matter_Plugin_write_attribute, /* name */ +be_local_closure(Matter_Plugin_parse_sensors, /* name */ be_nested_proto( - 5, /* nstack */ - 4, /* argc */ + 2, /* nstack */ + 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -1039,46 +1149,10 @@ be_local_closure(Matter_Plugin_write_attribute, /* name */ NULL, /* no sub protos */ 0, /* has constants */ NULL, /* no const */ - be_str_weak(write_attribute), + be_str_weak(parse_sensors), &be_const_str_solidified, - ( &(const binstruction[ 2]) { /* code */ - 0x4C100000, // 0000 LDNIL R4 - 0x80040800, // 0001 RET 1 R4 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: attribute_updated -********************************************************************/ -be_local_closure(Matter_Plugin_attribute_updated, /* name */ - be_nested_proto( - 10, /* nstack */ - 4, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 3]) { /* constants */ - /* K0 */ be_nested_str_weak(device), - /* K1 */ be_nested_str_weak(attribute_updated), - /* K2 */ be_nested_str_weak(endpoint), - }), - be_str_weak(attribute_updated), - &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ - 0x88100100, // 0000 GETMBR R4 R0 K0 - 0x8C100901, // 0001 GETMET R4 R4 K1 - 0x88180102, // 0002 GETMBR R6 R0 K2 - 0x5C1C0200, // 0003 MOVE R7 R1 - 0x5C200400, // 0004 MOVE R8 R2 - 0x5C240600, // 0005 MOVE R9 R3 - 0x7C100A00, // 0006 CALL R4 5 - 0x80000000, // 0007 RET 0 + ( &(const binstruction[ 1]) { /* code */ + 0x80000000, // 0000 RET 0 }) ) ); @@ -1113,12 +1187,43 @@ be_local_closure(Matter_Plugin__X3Clambda_X3E, /* name */ /******************************************************************** -** Solidified function: update_virtual +** Solidified function: contains_cluster ********************************************************************/ -be_local_closure(Matter_Plugin_update_virtual, /* name */ +be_local_closure(Matter_Plugin_contains_cluster, /* name */ + be_nested_proto( + 5, /* nstack */ + 2, /* argc */ + 2, /* varg */ + 0, /* has upvals */ + NULL, /* no upvals */ + 0, /* has sup protos */ + NULL, /* no sub protos */ + 1, /* has constants */ + ( &(const bvalue[ 2]) { /* constants */ + /* K0 */ be_nested_str_weak(clusters), + /* K1 */ be_nested_str_weak(contains), + }), + be_str_weak(contains_cluster), + &be_const_str_solidified, + ( &(const binstruction[ 5]) { /* code */ + 0x88080100, // 0000 GETMBR R2 R0 K0 + 0x8C080501, // 0001 GETMET R2 R2 K1 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x80040400, // 0004 RET 1 R2 + }) + ) +); +/*******************************************************************/ + + +/******************************************************************** +** Solidified function: is_local_device +********************************************************************/ +be_local_closure(Matter_Plugin_is_local_device, /* name */ be_nested_proto( 2, /* nstack */ - 2, /* argc */ + 1, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -1126,10 +1231,11 @@ be_local_closure(Matter_Plugin_update_virtual, /* name */ NULL, /* no sub protos */ 0, /* has constants */ NULL, /* no const */ - be_str_weak(update_virtual), + be_str_weak(is_local_device), &be_const_str_solidified, - ( &(const binstruction[ 1]) { /* code */ - 0x80000000, // 0000 RET 0 + ( &(const binstruction[ 2]) { /* code */ + 0x50040200, // 0000 LDBOOL R1 1 0 + 0x80040200, // 0001 RET 1 R1 }) ) ); @@ -1183,70 +1289,36 @@ be_local_closure(Matter_Plugin_get_cluster_list, /* name */ /******************************************************************** -** Solidified function: ui_conf_to_string +** Solidified function: ui_string_to_conf ********************************************************************/ -be_local_closure(Matter_Plugin_ui_conf_to_string, /* name */ +be_local_closure(Matter_Plugin_ui_string_to_conf, /* name */ be_nested_proto( - 9, /* nstack */ - 2, /* argc */ + 8, /* nstack */ + 3, /* argc */ 4, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 4]) { /* constants */ + ( &(const bvalue[ 3]) { /* constants */ /* K0 */ be_const_class(be_class_Matter_Plugin), /* K1 */ be_nested_str_weak(ARG), - /* K2 */ be_nested_str_weak(find), - /* K3 */ be_nested_str_weak(), + /* K2 */ be_nested_str_weak(ARG_TYPE), }), - be_str_weak(ui_conf_to_string), + be_str_weak(ui_string_to_conf), &be_const_str_solidified, - ( &(const binstruction[12]) { /* code */ - 0x58080000, // 0000 LDCONST R2 K0 - 0x880C0101, // 0001 GETMBR R3 R0 K1 - 0x780E0006, // 0002 JMPF R3 #000A - 0x60100008, // 0003 GETGBL R4 G8 - 0x8C140302, // 0004 GETMET R5 R1 K2 - 0x5C1C0600, // 0005 MOVE R7 R3 - 0x58200003, // 0006 LDCONST R8 K3 - 0x7C140600, // 0007 CALL R5 3 - 0x7C100200, // 0008 CALL R4 1 - 0x70020000, // 0009 JMP #000B - 0x58100003, // 000A LDCONST R4 K3 - 0x80040800, // 000B RET 1 R4 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: contains_cluster -********************************************************************/ -be_local_closure(Matter_Plugin_contains_cluster, /* name */ - be_nested_proto( - 5, /* nstack */ - 2, /* argc */ - 2, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 2]) { /* constants */ - /* K0 */ be_nested_str_weak(clusters), - /* K1 */ be_nested_str_weak(contains), - }), - be_str_weak(contains_cluster), - &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x80040400, // 0004 RET 1 R2 + ( &(const binstruction[10]) { /* code */ + 0x580C0000, // 0000 LDCONST R3 K0 + 0x88100101, // 0001 GETMBR R4 R0 K1 + 0x88140102, // 0002 GETMBR R5 R0 K2 + 0x780A0004, // 0003 JMPF R2 #0009 + 0x78120003, // 0004 JMPF R4 #0009 + 0x5C180A00, // 0005 MOVE R6 R5 + 0x5C1C0400, // 0006 MOVE R7 R2 + 0x7C180200, // 0007 CALL R6 1 + 0x98040806, // 0008 SETIDX R1 R4 R6 + 0x80040200, // 0009 RET 1 R1 }) ) ); @@ -1259,71 +1331,115 @@ be_local_closure(Matter_Plugin_contains_cluster, /* name */ be_local_class(Matter_Plugin, 6, NULL, - be_nested_map(47, + be_nested_map(50, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(ack_request, -1), be_const_closure(Matter_Plugin_ack_request_closure) }, - { be_const_key_weak(parse_sensors, -1), be_const_closure(Matter_Plugin_parse_sensors_closure) }, - { be_const_key_weak(ui_conf_to_string, 45), be_const_static_closure(Matter_Plugin_ui_conf_to_string_closure) }, - { be_const_key_weak(clusters, 27), be_const_var(3) }, - { be_const_key_weak(ARG_HINT, -1), be_nested_str_weak(_Not_X20used_) }, - { be_const_key_weak(subscribe_attribute, -1), be_const_closure(Matter_Plugin_subscribe_attribute_closure) }, - { be_const_key_weak(timed_request, -1), be_const_closure(Matter_Plugin_timed_request_closure) }, + { be_const_key_weak(every_250ms, -1), be_const_closure(Matter_Plugin_every_250ms_closure) }, + { be_const_key_weak(DISPLAY_NAME, -1), be_nested_str_weak() }, + { be_const_key_weak(FEATURE_MAPS, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { + be_const_map( * be_nested_map(2, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_int(258, -1), be_const_int(5) }, + { be_const_key_int(49, -1), be_const_int(4) }, + })) ) } )) }, + { be_const_key_weak(read_attribute, -1), be_const_closure(Matter_Plugin_read_attribute_closure) }, + { be_const_key_weak(subscribe_attribute, 31), be_const_closure(Matter_Plugin_subscribe_attribute_closure) }, + { be_const_key_weak(init, -1), be_const_closure(Matter_Plugin_init_closure) }, + { be_const_key_weak(UPDATE_TIME, -1), be_const_int(5000) }, + { be_const_key_weak(set_name, 36), be_const_closure(Matter_Plugin_set_name_closure) }, { be_const_key_weak(endpoint, -1), be_const_var(2) }, - { be_const_key_weak(DISPLAY_NAME, 1), be_nested_str_weak() }, - { be_const_key_weak(update_shadow, 2), be_const_closure(Matter_Plugin_update_shadow_closure) }, - { be_const_key_weak(ARG_TYPE, -1), be_const_static_closure(Matter_Plugin__X3Clambda_X3E_closure) }, + { be_const_key_weak(UPDATE_COMMANDS, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { + be_const_list( * be_nested_list(0, + ( (struct bvalue*) &(const bvalue[]) { + })) ) } )) }, + { be_const_key_weak(VIRTUAL, -1), be_const_bool(0) }, + { be_const_key_weak(device, -1), be_const_var(1) }, + { be_const_key_weak(subscribe_event, 3), be_const_closure(Matter_Plugin_subscribe_event_closure) }, + { be_const_key_weak(read_event, -1), be_const_closure(Matter_Plugin_read_event_closure) }, { be_const_key_weak(publish_command, -1), be_const_closure(Matter_Plugin_publish_command_closure) }, - { be_const_key_weak(consolidate_clusters, 5), be_const_closure(Matter_Plugin_consolidate_clusters_closure) }, - { be_const_key_weak(set_name, 42), be_const_closure(Matter_Plugin_set_name_closure) }, - { be_const_key_weak(write_attribute, 23), be_const_closure(Matter_Plugin_write_attribute_closure) }, - { be_const_key_weak(VIRTUAL, 6), be_const_bool(0) }, - { be_const_key_weak(node_label, 34), be_const_var(5) }, + { be_const_key_weak(is_local_device, 21), be_const_closure(Matter_Plugin_is_local_device_closure) }, + { be_const_key_weak(CLUSTER_REVISIONS, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { + be_const_map( * be_nested_map(25, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_int(8, -1), be_const_int(5) }, + { be_const_key_int(1026, -1), be_const_int(4) }, + { be_const_key_int(1027, -1), be_const_int(3) }, + { be_const_key_int(3, 20), be_const_int(4) }, + { be_const_key_int(29, 17), be_const_int(2) }, + { be_const_key_int(5, 9), be_const_int(5) }, + { be_const_key_int(56, 11), be_const_int(2) }, + { be_const_key_int(257, 10), be_const_int(7) }, + { be_const_key_int(258, 0), be_const_int(5) }, + { be_const_key_int(1030, -1), be_const_int(3) }, + { be_const_key_int(1032, -1), be_const_int(3) }, + { be_const_key_int(1031, 23), be_const_int(3) }, + { be_const_key_int(512, -1), be_const_int(4) }, + { be_const_key_int(63, 22), be_const_int(2) }, + { be_const_key_int(514, -1), be_const_int(4) }, + { be_const_key_int(40, -1), be_const_int(2) }, + { be_const_key_int(516, -1), be_const_int(2) }, + { be_const_key_int(1029, 21), be_const_int(3) }, + { be_const_key_int(768, -1), be_const_int(6) }, + { be_const_key_int(769, -1), be_const_int(4) }, + { be_const_key_int(1028, -1), be_const_int(3) }, + { be_const_key_int(4, -1), be_const_int(4) }, + { be_const_key_int(513, -1), be_const_int(6) }, + { be_const_key_int(6, -1), be_const_int(5) }, + { be_const_key_int(1024, -1), be_const_int(3) }, + })) ) } )) }, + { be_const_key_weak(contains_cluster, -1), be_const_closure(Matter_Plugin_contains_cluster_closure) }, + { be_const_key_weak(parse_configuration, -1), be_const_closure(Matter_Plugin_parse_configuration_closure) }, + { be_const_key_weak(get_attribute_list, 33), be_const_closure(Matter_Plugin_get_attribute_list_closure) }, + { be_const_key_weak(consolidate_clusters, 13), be_const_closure(Matter_Plugin_consolidate_clusters_closure) }, + { be_const_key_weak(parse_sensors, 23), be_const_closure(Matter_Plugin_parse_sensors_closure) }, + { be_const_key_weak(contains_attribute, 29), be_const_closure(Matter_Plugin_contains_attribute_closure) }, + { be_const_key_weak(append_state_json, -1), be_const_closure(Matter_Plugin_append_state_json_closure) }, { be_const_key_weak(CLUSTERS, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { be_const_map( * be_nested_map(1, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(29, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, })) ) } )) }, - { be_const_key_weak(update_shadow_lazy, -1), be_const_closure(Matter_Plugin_update_shadow_lazy_closure) }, - { be_const_key_weak(update_next, 40), be_const_var(0) }, - { be_const_key_weak(invoke_request, -1), be_const_closure(Matter_Plugin_invoke_request_closure) }, - { be_const_key_weak(init, -1), be_const_closure(Matter_Plugin_init_closure) }, - { be_const_key_weak(ARG, 14), be_nested_str_weak() }, - { be_const_key_weak(get_endpoint, 17), be_const_closure(Matter_Plugin_get_endpoint_closure) }, - { be_const_key_weak(get_name, 20), be_const_closure(Matter_Plugin_get_name_closure) }, - { be_const_key_weak(ui_string_to_conf, 10), be_const_static_closure(Matter_Plugin_ui_string_to_conf_closure) }, - { be_const_key_weak(tick, 18), be_const_var(4) }, - { be_const_key_weak(TYPE, -1), be_nested_str_weak() }, - { be_const_key_weak(append_state_json, -1), be_const_closure(Matter_Plugin_append_state_json_closure) }, - { be_const_key_weak(read_event, -1), be_const_closure(Matter_Plugin_read_event_closure) }, - { be_const_key_weak(device, -1), be_const_var(1) }, - { be_const_key_weak(parse_configuration, -1), be_const_closure(Matter_Plugin_parse_configuration_closure) }, - { be_const_key_weak(state_json, -1), be_const_closure(Matter_Plugin_state_json_closure) }, - { be_const_key_weak(subscribe_event, -1), be_const_closure(Matter_Plugin_subscribe_event_closure) }, - { be_const_key_weak(get_attribute_list, -1), be_const_closure(Matter_Plugin_get_attribute_list_closure) }, - { be_const_key_weak(read_attribute, 26), be_const_closure(Matter_Plugin_read_attribute_closure) }, - { be_const_key_weak(has, -1), be_const_closure(Matter_Plugin_has_closure) }, - { be_const_key_weak(UPDATE_TIME, -1), be_const_int(5000) }, - { be_const_key_weak(every_250ms, -1), be_const_closure(Matter_Plugin_every_250ms_closure) }, - { be_const_key_weak(contains_attribute, -1), be_const_closure(Matter_Plugin_contains_attribute_closure) }, - { be_const_key_weak(is_local_device, 13), be_const_closure(Matter_Plugin_is_local_device_closure) }, { be_const_key_weak(attribute_updated, -1), be_const_closure(Matter_Plugin_attribute_updated_closure) }, - { be_const_key_weak(UPDATE_COMMANDS, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(0, - ( (struct bvalue*) &(const bvalue[]) { + { be_const_key_weak(timed_request, 41), be_const_closure(Matter_Plugin_timed_request_closure) }, + { be_const_key_weak(get_endpoint, -1), be_const_closure(Matter_Plugin_get_endpoint_closure) }, + { be_const_key_weak(update_next, 43), be_const_var(0) }, + { be_const_key_weak(TYPE, 32), be_nested_str_weak() }, + { be_const_key_weak(ui_conf_to_string, 28), be_const_static_closure(Matter_Plugin_ui_conf_to_string_closure) }, + { be_const_key_weak(tick, -1), be_const_var(4) }, + { be_const_key_weak(update_shadow, -1), be_const_closure(Matter_Plugin_update_shadow_closure) }, + { be_const_key_weak(ARG, 18), be_nested_str_weak() }, + { be_const_key_weak(has, -1), be_const_closure(Matter_Plugin_has_closure) }, + { be_const_key_weak(write_attribute, 34), be_const_closure(Matter_Plugin_write_attribute_closure) }, + { be_const_key_weak(COMMANDS, 42), be_const_simple_instance(be_nested_simple_instance(&be_class_map, { + be_const_map( * be_nested_map(1, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_const_key_int(29, -1), be_const_nil() }, })) ) } )) }, + { be_const_key_weak(invoke_request, -1), be_const_closure(Matter_Plugin_invoke_request_closure) }, + { be_const_key_weak(update_shadow_lazy, -1), be_const_closure(Matter_Plugin_update_shadow_lazy_closure) }, + { be_const_key_weak(state_json, 22), be_const_closure(Matter_Plugin_state_json_closure) }, { be_const_key_weak(update_virtual, -1), be_const_closure(Matter_Plugin_update_virtual_closure) }, + { be_const_key_weak(clusters, -1), be_const_var(3) }, + { be_const_key_weak(get_name, -1), be_const_closure(Matter_Plugin_get_name_closure) }, + { be_const_key_weak(node_label, -1), be_const_var(5) }, + { be_const_key_weak(ARG_TYPE, -1), be_const_static_closure(Matter_Plugin__X3Clambda_X3E_closure) }, + { be_const_key_weak(ARG_HINT, 17), be_nested_str_weak(_Not_X20used_) }, + { be_const_key_weak(ack_request, 15), be_const_closure(Matter_Plugin_ack_request_closure) }, { be_const_key_weak(get_cluster_list, -1), be_const_closure(Matter_Plugin_get_cluster_list_closure) }, - { be_const_key_weak(consolidate_update_commands, -1), be_const_closure(Matter_Plugin_consolidate_update_commands_closure) }, - { be_const_key_weak(contains_cluster, -1), be_const_closure(Matter_Plugin_contains_cluster_closure) }, + { be_const_key_weak(ui_string_to_conf, -1), be_const_static_closure(Matter_Plugin_ui_string_to_conf_closure) }, + { be_const_key_weak(consolidate_update_commands, 2), be_const_closure(Matter_Plugin_consolidate_update_commands_closure) }, })), be_str_weak(Matter_Plugin) ); diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Aggregator.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Aggregator.h index 20f1be289..03e9ed0d0 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Aggregator.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Aggregator.h @@ -19,7 +19,7 @@ be_local_closure(Matter_Plugin_Aggregator_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[19]) { /* constants */ + ( &(const bvalue[18]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -30,25 +30,24 @@ be_local_closure(Matter_Plugin_Aggregator_read_attribute, /* name */ /* K7 */ be_nested_str_weak(U2), /* K8 */ be_const_int(1), /* K9 */ be_nested_str_weak(U1), - /* K10 */ be_nested_str_weak(U4), - /* K11 */ be_const_int(2), - /* K12 */ be_nested_str_weak(Matter_TLV_array), - /* K13 */ be_nested_str_weak(add_TLV), - /* K14 */ be_nested_str_weak(device), - /* K15 */ be_nested_str_weak(get_active_endpoints), - /* K16 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), - /* K17 */ be_nested_str_weak(stop_iteration), - /* K18 */ be_nested_str_weak(read_attribute), + /* K10 */ be_const_int(2), + /* K11 */ be_nested_str_weak(Matter_TLV_array), + /* K12 */ be_nested_str_weak(add_TLV), + /* K13 */ be_nested_str_weak(device), + /* K14 */ be_nested_str_weak(get_active_endpoints), + /* K15 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), + /* K16 */ be_nested_str_weak(stop_iteration), + /* K17 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[103]) { /* code */ + ( &(const binstruction[73]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x1C1C0B04, // 0004 EQ R7 R5 K4 - 0x781E0021, // 0005 JMPF R7 #0028 + 0x781E000F, // 0005 JMPF R7 #0016 0x1C1C0D05, // 0006 EQ R7 R6 K5 0x781E0005, // 0007 JMPF R7 #000E 0x8C1C0706, // 0008 GETMET R7 R3 K6 @@ -56,96 +55,66 @@ be_local_closure(Matter_Plugin_Aggregator_read_attribute, /* name */ 0x58280005, // 000A LDCONST R10 K5 0x7C1C0600, // 000B CALL R7 3 0x80040E00, // 000C RET 1 R7 - 0x70020018, // 000D JMP #0027 + 0x70020006, // 000D JMP #0015 0x1C1C0D08, // 000E EQ R7 R6 K8 - 0x781E0005, // 000F JMPF R7 #0016 + 0x781E0004, // 000F JMPF R7 #0015 0x8C1C0706, // 0010 GETMET R7 R3 K6 0x88240909, // 0011 GETMBR R9 R4 K9 0x58280005, // 0012 LDCONST R10 K5 0x7C1C0600, // 0013 CALL R7 3 0x80040E00, // 0014 RET 1 R7 - 0x70020010, // 0015 JMP #0027 - 0x541EFFFB, // 0016 LDINT R7 65532 - 0x1C1C0C07, // 0017 EQ R7 R6 R7 - 0x781E0005, // 0018 JMPF R7 #001F - 0x8C1C0706, // 0019 GETMET R7 R3 K6 - 0x8824090A, // 001A GETMBR R9 R4 K10 - 0x58280005, // 001B LDCONST R10 K5 - 0x7C1C0600, // 001C CALL R7 3 - 0x80040E00, // 001D RET 1 R7 - 0x70020007, // 001E JMP #0027 - 0x541EFFFC, // 001F LDINT R7 65533 - 0x1C1C0C07, // 0020 EQ R7 R6 R7 - 0x781E0004, // 0021 JMPF R7 #0027 - 0x8C1C0706, // 0022 GETMET R7 R3 K6 - 0x8824090A, // 0023 GETMBR R9 R4 K10 - 0x542A0003, // 0024 LDINT R10 4 - 0x7C1C0600, // 0025 CALL R7 3 - 0x80040E00, // 0026 RET 1 R7 - 0x7002003D, // 0027 JMP #0066 - 0x541E001C, // 0028 LDINT R7 29 - 0x1C1C0A07, // 0029 EQ R7 R5 R7 - 0x781E0031, // 002A JMPF R7 #005D - 0x1C1C0D0B, // 002B EQ R7 R6 K11 - 0x781E0008, // 002C JMPF R7 #0036 - 0x8C1C090C, // 002D GETMET R7 R4 K12 - 0x7C1C0200, // 002E CALL R7 1 - 0x8C200F0D, // 002F GETMET R8 R7 K13 - 0x4C280000, // 0030 LDNIL R10 - 0x882C0907, // 0031 GETMBR R11 R4 K7 - 0x5432001D, // 0032 LDINT R12 30 - 0x7C200800, // 0033 CALL R8 4 - 0x80040E00, // 0034 RET 1 R7 - 0x70020025, // 0035 JMP #005C - 0x1C1C0D04, // 0036 EQ R7 R6 K4 - 0x781E001A, // 0037 JMPF R7 #0053 - 0x8C1C090C, // 0038 GETMET R7 R4 K12 - 0x7C1C0200, // 0039 CALL R7 1 - 0x8820010E, // 003A GETMBR R8 R0 K14 - 0x8C20110F, // 003B GETMET R8 R8 K15 - 0x50280200, // 003C LDBOOL R10 1 0 - 0x7C200400, // 003D CALL R8 2 - 0x60240010, // 003E GETGBL R9 G16 - 0x5C281000, // 003F MOVE R10 R8 - 0x7C240200, // 0040 CALL R9 1 - 0xA802000B, // 0041 EXBLK 0 #004E - 0x5C281200, // 0042 MOVE R10 R9 - 0x7C280000, // 0043 CALL R10 0 - 0xB82E0000, // 0044 GETNGBL R11 K0 - 0x882C1710, // 0045 GETMBR R11 R11 K16 - 0x202C140B, // 0046 NE R11 R10 R11 - 0x782E0004, // 0047 JMPF R11 #004D - 0x8C2C0F0D, // 0048 GETMET R11 R7 K13 - 0x4C340000, // 0049 LDNIL R13 - 0x88380907, // 004A GETMBR R14 R4 K7 - 0x5C3C1400, // 004B MOVE R15 R10 - 0x7C2C0800, // 004C CALL R11 4 - 0x7001FFF3, // 004D JMP #0042 - 0x58240011, // 004E LDCONST R9 K17 - 0xAC240200, // 004F CATCH R9 1 0 - 0xB0080000, // 0050 RAISE 2 R0 R0 - 0x80040E00, // 0051 RET 1 R7 - 0x70020008, // 0052 JMP #005C - 0x601C0003, // 0053 GETGBL R7 G3 - 0x5C200000, // 0054 MOVE R8 R0 - 0x7C1C0200, // 0055 CALL R7 1 - 0x8C1C0F12, // 0056 GETMET R7 R7 K18 - 0x5C240200, // 0057 MOVE R9 R1 - 0x5C280400, // 0058 MOVE R10 R2 - 0x5C2C0600, // 0059 MOVE R11 R3 - 0x7C1C0800, // 005A CALL R7 4 - 0x80040E00, // 005B RET 1 R7 - 0x70020008, // 005C JMP #0066 - 0x601C0003, // 005D GETGBL R7 G3 - 0x5C200000, // 005E MOVE R8 R0 - 0x7C1C0200, // 005F CALL R7 1 - 0x8C1C0F12, // 0060 GETMET R7 R7 K18 - 0x5C240200, // 0061 MOVE R9 R1 - 0x5C280400, // 0062 MOVE R10 R2 - 0x5C2C0600, // 0063 MOVE R11 R3 - 0x7C1C0800, // 0064 CALL R7 4 - 0x80040E00, // 0065 RET 1 R7 - 0x80000000, // 0066 RET 0 + 0x70020029, // 0015 JMP #0040 + 0x541E001C, // 0016 LDINT R7 29 + 0x1C1C0A07, // 0017 EQ R7 R5 R7 + 0x781E0026, // 0018 JMPF R7 #0040 + 0x1C1C0D0A, // 0019 EQ R7 R6 K10 + 0x781E0008, // 001A JMPF R7 #0024 + 0x8C1C090B, // 001B GETMET R7 R4 K11 + 0x7C1C0200, // 001C CALL R7 1 + 0x8C200F0C, // 001D GETMET R8 R7 K12 + 0x4C280000, // 001E LDNIL R10 + 0x882C0907, // 001F GETMBR R11 R4 K7 + 0x5432001D, // 0020 LDINT R12 30 + 0x7C200800, // 0021 CALL R8 4 + 0x80040E00, // 0022 RET 1 R7 + 0x7002001B, // 0023 JMP #0040 + 0x1C1C0D04, // 0024 EQ R7 R6 K4 + 0x781E0019, // 0025 JMPF R7 #0040 + 0x8C1C090B, // 0026 GETMET R7 R4 K11 + 0x7C1C0200, // 0027 CALL R7 1 + 0x8820010D, // 0028 GETMBR R8 R0 K13 + 0x8C20110E, // 0029 GETMET R8 R8 K14 + 0x50280200, // 002A LDBOOL R10 1 0 + 0x7C200400, // 002B CALL R8 2 + 0x60240010, // 002C GETGBL R9 G16 + 0x5C281000, // 002D MOVE R10 R8 + 0x7C240200, // 002E CALL R9 1 + 0xA802000B, // 002F EXBLK 0 #003C + 0x5C281200, // 0030 MOVE R10 R9 + 0x7C280000, // 0031 CALL R10 0 + 0xB82E0000, // 0032 GETNGBL R11 K0 + 0x882C170F, // 0033 GETMBR R11 R11 K15 + 0x202C140B, // 0034 NE R11 R10 R11 + 0x782E0004, // 0035 JMPF R11 #003B + 0x8C2C0F0C, // 0036 GETMET R11 R7 K12 + 0x4C340000, // 0037 LDNIL R13 + 0x88380907, // 0038 GETMBR R14 R4 K7 + 0x5C3C1400, // 0039 MOVE R15 R10 + 0x7C2C0800, // 003A CALL R11 4 + 0x7001FFF3, // 003B JMP #0030 + 0x58240010, // 003C LDCONST R9 K16 + 0xAC240200, // 003D CATCH R9 1 0 + 0xB0080000, // 003E RAISE 2 R0 R0 + 0x80040E00, // 003F RET 1 R7 + 0x601C0003, // 0040 GETGBL R7 G3 + 0x5C200000, // 0041 MOVE R8 R0 + 0x7C1C0200, // 0042 CALL R7 1 + 0x8C1C0F11, // 0043 GETMET R7 R7 K17 + 0x5C240200, // 0044 MOVE R9 R1 + 0x5C280400, // 0045 MOVE R10 R2 + 0x5C2C0600, // 0046 MOVE R11 R3 + 0x7C1C0800, // 0047 CALL R7 4 + 0x80040E00, // 0048 RET 1 R7 }) ) ); @@ -247,20 +216,28 @@ be_local_class(Matter_Plugin_Aggregator, be_const_map( * be_nested_map(2, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(29, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Device.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Device.h index f93586d65..b2ab1687f 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Device.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Device.h @@ -19,7 +19,7 @@ be_local_closure(Matter_Plugin_Device_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[37]) { /* constants */ + ( &(const bvalue[36]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -30,43 +30,42 @@ be_local_closure(Matter_Plugin_Device_read_attribute, /* name */ /* K7 */ be_nested_str_weak(U2), /* K8 */ be_const_int(1), /* K9 */ be_nested_str_weak(U1), - /* K10 */ be_nested_str_weak(U4), - /* K11 */ be_nested_str_weak(Matter_TLV_array), - /* K12 */ be_nested_str_weak(TYPES), - /* K13 */ be_nested_str_weak(keys), - /* K14 */ be_nested_str_weak(add_struct), - /* K15 */ be_nested_str_weak(add_TLV), - /* K16 */ be_nested_str_weak(stop_iteration), - /* K17 */ be_nested_str_weak(NON_BRIDGE_VENDOR), - /* K18 */ be_nested_str_weak(find), - /* K19 */ be_nested_str_weak(get_admin_vendor), - /* K20 */ be_nested_str_weak(device), - /* K21 */ be_nested_str_weak(disable_bridge_mode), - /* K22 */ be_nested_str_weak(read_attribute), - /* K23 */ be_nested_str_weak(string), - /* K24 */ be_nested_str_weak(UTF1), - /* K25 */ be_nested_str_weak(tasmota), - /* K26 */ be_nested_str_weak(cmd), - /* K27 */ be_nested_str_weak(DeviceName), - /* K28 */ be_nested_str_weak(get_name), - /* K29 */ be_nested_str_weak(Status_X202), - /* K30 */ be_nested_str_weak(StatusFWR), - /* K31 */ be_nested_str_weak(Version), - /* K32 */ be_nested_str_weak(_X28), - /* K33 */ be_nested_str_weak(wifi), - /* K34 */ be_nested_str_weak(mac), - /* K35 */ be_nested_str_weak(), - /* K36 */ be_nested_str_weak(BOOL), + /* K10 */ be_nested_str_weak(Matter_TLV_array), + /* K11 */ be_nested_str_weak(TYPES), + /* K12 */ be_nested_str_weak(keys), + /* K13 */ be_nested_str_weak(add_struct), + /* K14 */ be_nested_str_weak(add_TLV), + /* K15 */ be_nested_str_weak(stop_iteration), + /* K16 */ be_nested_str_weak(NON_BRIDGE_VENDOR), + /* K17 */ be_nested_str_weak(find), + /* K18 */ be_nested_str_weak(get_admin_vendor), + /* K19 */ be_nested_str_weak(device), + /* K20 */ be_nested_str_weak(disable_bridge_mode), + /* K21 */ be_nested_str_weak(string), + /* K22 */ be_nested_str_weak(UTF1), + /* K23 */ be_nested_str_weak(tasmota), + /* K24 */ be_nested_str_weak(cmd), + /* K25 */ be_nested_str_weak(DeviceName), + /* K26 */ be_nested_str_weak(get_name), + /* K27 */ be_nested_str_weak(Status_X202), + /* K28 */ be_nested_str_weak(StatusFWR), + /* K29 */ be_nested_str_weak(Version), + /* K30 */ be_nested_str_weak(_X28), + /* K31 */ be_nested_str_weak(wifi), + /* K32 */ be_nested_str_weak(mac), + /* K33 */ be_nested_str_weak(), + /* K34 */ be_nested_str_weak(BOOL), + /* K35 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[254]) { /* code */ + ( &(const binstruction[189]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x1C1C0B04, // 0004 EQ R7 R5 K4 - 0x781E0021, // 0005 JMPF R7 #0028 + 0x781E000F, // 0005 JMPF R7 #0016 0x1C1C0D05, // 0006 EQ R7 R6 K5 0x781E0005, // 0007 JMPF R7 #000E 0x8C1C0706, // 0008 GETMET R7 R3 K6 @@ -74,247 +73,182 @@ be_local_closure(Matter_Plugin_Device_read_attribute, /* name */ 0x58280005, // 000A LDCONST R10 K5 0x7C1C0600, // 000B CALL R7 3 0x80040E00, // 000C RET 1 R7 - 0x70020018, // 000D JMP #0027 + 0x70020006, // 000D JMP #0015 0x1C1C0D08, // 000E EQ R7 R6 K8 - 0x781E0005, // 000F JMPF R7 #0016 + 0x781E0004, // 000F JMPF R7 #0015 0x8C1C0706, // 0010 GETMET R7 R3 K6 0x88240909, // 0011 GETMBR R9 R4 K9 0x58280005, // 0012 LDCONST R10 K5 0x7C1C0600, // 0013 CALL R7 3 0x80040E00, // 0014 RET 1 R7 - 0x70020010, // 0015 JMP #0027 - 0x541EFFFB, // 0016 LDINT R7 65532 - 0x1C1C0C07, // 0017 EQ R7 R6 R7 - 0x781E0005, // 0018 JMPF R7 #001F - 0x8C1C0706, // 0019 GETMET R7 R3 K6 - 0x8824090A, // 001A GETMBR R9 R4 K10 - 0x58280005, // 001B LDCONST R10 K5 - 0x7C1C0600, // 001C CALL R7 3 - 0x80040E00, // 001D RET 1 R7 - 0x70020007, // 001E JMP #0027 - 0x541EFFFC, // 001F LDINT R7 65533 - 0x1C1C0C07, // 0020 EQ R7 R6 R7 - 0x781E0004, // 0021 JMPF R7 #0027 - 0x8C1C0706, // 0022 GETMET R7 R3 K6 - 0x8824090A, // 0023 GETMBR R9 R4 K10 - 0x542A0003, // 0024 LDINT R10 4 - 0x7C1C0600, // 0025 CALL R7 3 - 0x80040E00, // 0026 RET 1 R7 - 0x700200D4, // 0027 JMP #00FD - 0x541E0003, // 0028 LDINT R7 4 - 0x1C1C0A07, // 0029 EQ R7 R5 R7 - 0x781E0016, // 002A JMPF R7 #0042 - 0x1C1C0D05, // 002B EQ R7 R6 K5 - 0x781E0002, // 002C JMPF R7 #0030 - 0x4C1C0000, // 002D LDNIL R7 - 0x80040E00, // 002E RET 1 R7 - 0x70020010, // 002F JMP #0041 - 0x541EFFFB, // 0030 LDINT R7 65532 - 0x1C1C0C07, // 0031 EQ R7 R6 R7 - 0x781E0005, // 0032 JMPF R7 #0039 - 0x8C1C0706, // 0033 GETMET R7 R3 K6 - 0x8824090A, // 0034 GETMBR R9 R4 K10 - 0x58280005, // 0035 LDCONST R10 K5 - 0x7C1C0600, // 0036 CALL R7 3 - 0x80040E00, // 0037 RET 1 R7 - 0x70020007, // 0038 JMP #0041 - 0x541EFFFC, // 0039 LDINT R7 65533 - 0x1C1C0C07, // 003A EQ R7 R6 R7 - 0x781E0004, // 003B JMPF R7 #0041 - 0x8C1C0706, // 003C GETMET R7 R3 K6 - 0x8824090A, // 003D GETMBR R9 R4 K10 - 0x542A0003, // 003E LDINT R10 4 - 0x7C1C0600, // 003F CALL R7 3 - 0x80040E00, // 0040 RET 1 R7 - 0x700200BA, // 0041 JMP #00FD - 0x541E0004, // 0042 LDINT R7 5 - 0x1C1C0A07, // 0043 EQ R7 R5 R7 - 0x781E0011, // 0044 JMPF R7 #0057 - 0x541EFFFB, // 0045 LDINT R7 65532 - 0x1C1C0C07, // 0046 EQ R7 R6 R7 - 0x781E0005, // 0047 JMPF R7 #004E - 0x8C1C0706, // 0048 GETMET R7 R3 K6 - 0x8824090A, // 0049 GETMBR R9 R4 K10 - 0x58280005, // 004A LDCONST R10 K5 - 0x7C1C0600, // 004B CALL R7 3 - 0x80040E00, // 004C RET 1 R7 - 0x70020007, // 004D JMP #0056 - 0x541EFFFC, // 004E LDINT R7 65533 - 0x1C1C0C07, // 004F EQ R7 R6 R7 - 0x781E0004, // 0050 JMPF R7 #0056 - 0x8C1C0706, // 0051 GETMET R7 R3 K6 - 0x8824090A, // 0052 GETMBR R9 R4 K10 - 0x542A0003, // 0053 LDINT R10 4 - 0x7C1C0600, // 0054 CALL R7 3 - 0x80040E00, // 0055 RET 1 R7 - 0x700200A5, // 0056 JMP #00FD - 0x541E001C, // 0057 LDINT R7 29 - 0x1C1C0A07, // 0058 EQ R7 R5 R7 - 0x781E003E, // 0059 JMPF R7 #0099 - 0x1C1C0D05, // 005A EQ R7 R6 K5 - 0x781E0032, // 005B JMPF R7 #008F - 0x8C1C090B, // 005C GETMET R7 R4 K11 - 0x7C1C0200, // 005D CALL R7 1 - 0x8820010C, // 005E GETMBR R8 R0 K12 - 0x60240010, // 005F GETGBL R9 G16 - 0x8C28110D, // 0060 GETMET R10 R8 K13 - 0x7C280200, // 0061 CALL R10 1 - 0x7C240200, // 0062 CALL R9 1 - 0xA802000E, // 0063 EXBLK 0 #0073 - 0x5C281200, // 0064 MOVE R10 R9 - 0x7C280000, // 0065 CALL R10 0 - 0x8C2C0F0E, // 0066 GETMET R11 R7 K14 - 0x7C2C0200, // 0067 CALL R11 1 - 0x8C30170F, // 0068 GETMET R12 R11 K15 - 0x58380005, // 0069 LDCONST R14 K5 - 0x883C0907, // 006A GETMBR R15 R4 K7 - 0x5C401400, // 006B MOVE R16 R10 - 0x7C300800, // 006C CALL R12 4 - 0x8C30170F, // 006D GETMET R12 R11 K15 - 0x58380008, // 006E LDCONST R14 K8 - 0x883C0907, // 006F GETMBR R15 R4 K7 - 0x9440100A, // 0070 GETIDX R16 R8 R10 - 0x7C300800, // 0071 CALL R12 4 - 0x7001FFF0, // 0072 JMP #0064 - 0x58240010, // 0073 LDCONST R9 K16 - 0xAC240200, // 0074 CATCH R9 1 0 - 0xB0080000, // 0075 RAISE 2 R0 R0 - 0x88240111, // 0076 GETMBR R9 R0 K17 - 0x8C241312, // 0077 GETMET R9 R9 K18 - 0x8C2C0313, // 0078 GETMET R11 R1 K19 - 0x7C2C0200, // 0079 CALL R11 1 - 0x7C240400, // 007A CALL R9 2 - 0x4C280000, // 007B LDNIL R10 - 0x1C24120A, // 007C EQ R9 R9 R10 - 0x7826000E, // 007D JMPF R9 #008D - 0x88240114, // 007E GETMBR R9 R0 K20 - 0x88241315, // 007F GETMBR R9 R9 K21 - 0x7426000B, // 0080 JMPT R9 #008D - 0x8C240F0E, // 0081 GETMET R9 R7 K14 - 0x7C240200, // 0082 CALL R9 1 - 0x8C28130F, // 0083 GETMET R10 R9 K15 - 0x58300005, // 0084 LDCONST R12 K5 - 0x88340907, // 0085 GETMBR R13 R4 K7 - 0x543A0012, // 0086 LDINT R14 19 - 0x7C280800, // 0087 CALL R10 4 - 0x8C28130F, // 0088 GETMET R10 R9 K15 - 0x58300008, // 0089 LDCONST R12 K8 - 0x88340907, // 008A GETMBR R13 R4 K7 - 0x58380008, // 008B LDCONST R14 K8 - 0x7C280800, // 008C CALL R10 4 - 0x80040E00, // 008D RET 1 R7 - 0x70020008, // 008E JMP #0098 - 0x601C0003, // 008F GETGBL R7 G3 - 0x5C200000, // 0090 MOVE R8 R0 - 0x7C1C0200, // 0091 CALL R7 1 - 0x8C1C0F16, // 0092 GETMET R7 R7 K22 - 0x5C240200, // 0093 MOVE R9 R1 - 0x5C280400, // 0094 MOVE R10 R2 - 0x5C2C0600, // 0095 MOVE R11 R3 - 0x7C1C0800, // 0096 CALL R7 4 - 0x80040E00, // 0097 RET 1 R7 - 0x70020063, // 0098 JMP #00FD - 0x541E0038, // 0099 LDINT R7 57 - 0x1C1C0A07, // 009A EQ R7 R5 R7 - 0x781E0057, // 009B JMPF R7 #00F4 - 0xA41E2E00, // 009C IMPORT R7 K23 - 0x1C200D04, // 009D EQ R8 R6 K4 - 0x7822000A, // 009E JMPF R8 #00AA - 0x8C200706, // 009F GETMET R8 R3 K6 - 0x88280918, // 00A0 GETMBR R10 R4 K24 - 0xB82E3200, // 00A1 GETNGBL R11 K25 - 0x8C2C171A, // 00A2 GETMET R11 R11 K26 - 0x5834001B, // 00A3 LDCONST R13 K27 - 0x50380200, // 00A4 LDBOOL R14 1 0 - 0x7C2C0600, // 00A5 CALL R11 3 - 0x942C171B, // 00A6 GETIDX R11 R11 K27 - 0x7C200600, // 00A7 CALL R8 3 - 0x80041000, // 00A8 RET 1 R8 - 0x70020048, // 00A9 JMP #00F3 - 0x54220004, // 00AA LDINT R8 5 - 0x1C200C08, // 00AB EQ R8 R6 R8 - 0x78220006, // 00AC JMPF R8 #00B4 - 0x8C200706, // 00AD GETMET R8 R3 K6 - 0x88280918, // 00AE GETMBR R10 R4 K24 - 0x8C2C011C, // 00AF GETMET R11 R0 K28 - 0x7C2C0200, // 00B0 CALL R11 1 - 0x7C200600, // 00B1 CALL R8 3 - 0x80041000, // 00B2 RET 1 R8 - 0x7002003E, // 00B3 JMP #00F3 - 0x54220009, // 00B4 LDINT R8 10 - 0x1C200C08, // 00B5 EQ R8 R6 R8 - 0x78220015, // 00B6 JMPF R8 #00CD - 0xB8223200, // 00B7 GETNGBL R8 K25 - 0x8C20111A, // 00B8 GETMET R8 R8 K26 - 0x5828001D, // 00B9 LDCONST R10 K29 - 0x502C0200, // 00BA LDBOOL R11 1 0 - 0x7C200600, // 00BB CALL R8 3 - 0x9420111E, // 00BC GETIDX R8 R8 K30 - 0x9420111F, // 00BD GETIDX R8 R8 K31 - 0x8C240F12, // 00BE GETMET R9 R7 K18 - 0x5C2C1000, // 00BF MOVE R11 R8 - 0x58300020, // 00C0 LDCONST R12 K32 - 0x7C240600, // 00C1 CALL R9 3 - 0x24281305, // 00C2 GT R10 R9 K5 - 0x782A0002, // 00C3 JMPF R10 #00C7 - 0x04281308, // 00C4 SUB R10 R9 K8 - 0x402A0A0A, // 00C5 CONNECT R10 K5 R10 - 0x9420100A, // 00C6 GETIDX R8 R8 R10 - 0x8C280706, // 00C7 GETMET R10 R3 K6 - 0x88300918, // 00C8 GETMBR R12 R4 K24 - 0x5C341000, // 00C9 MOVE R13 R8 - 0x7C280600, // 00CA CALL R10 3 - 0x80041400, // 00CB RET 1 R10 - 0x70020025, // 00CC JMP #00F3 - 0x5422000E, // 00CD LDINT R8 15 - 0x1C200C08, // 00CE EQ R8 R6 R8 - 0x7822000B, // 00CF JMPF R8 #00DC - 0x8C200706, // 00D0 GETMET R8 R3 K6 - 0x88280918, // 00D1 GETMBR R10 R4 K24 - 0xB82E3200, // 00D2 GETNGBL R11 K25 - 0x8C2C1721, // 00D3 GETMET R11 R11 K33 - 0x7C2C0200, // 00D4 CALL R11 1 - 0x8C2C1712, // 00D5 GETMET R11 R11 K18 - 0x58340022, // 00D6 LDCONST R13 K34 - 0x58380023, // 00D7 LDCONST R14 K35 - 0x7C2C0600, // 00D8 CALL R11 3 - 0x7C200600, // 00D9 CALL R8 3 - 0x80041000, // 00DA RET 1 R8 - 0x70020016, // 00DB JMP #00F3 - 0x54220010, // 00DC LDINT R8 17 - 0x1C200C08, // 00DD EQ R8 R6 R8 - 0x78220005, // 00DE JMPF R8 #00E5 - 0x8C200706, // 00DF GETMET R8 R3 K6 - 0x88280924, // 00E0 GETMBR R10 R4 K36 - 0x582C0008, // 00E1 LDCONST R11 K8 - 0x7C200600, // 00E2 CALL R8 3 - 0x80041000, // 00E3 RET 1 R8 - 0x7002000D, // 00E4 JMP #00F3 - 0x54220011, // 00E5 LDINT R8 18 - 0x1C200C08, // 00E6 EQ R8 R6 R8 - 0x7822000A, // 00E7 JMPF R8 #00F3 - 0x8C200706, // 00E8 GETMET R8 R3 K6 - 0x88280918, // 00E9 GETMBR R10 R4 K24 - 0xB82E3200, // 00EA GETNGBL R11 K25 - 0x8C2C1721, // 00EB GETMET R11 R11 K33 - 0x7C2C0200, // 00EC CALL R11 1 - 0x8C2C1712, // 00ED GETMET R11 R11 K18 - 0x58340022, // 00EE LDCONST R13 K34 - 0x58380023, // 00EF LDCONST R14 K35 - 0x7C2C0600, // 00F0 CALL R11 3 - 0x7C200600, // 00F1 CALL R8 3 - 0x80041000, // 00F2 RET 1 R8 - 0x70020008, // 00F3 JMP #00FD - 0x601C0003, // 00F4 GETGBL R7 G3 - 0x5C200000, // 00F5 MOVE R8 R0 - 0x7C1C0200, // 00F6 CALL R7 1 - 0x8C1C0F16, // 00F7 GETMET R7 R7 K22 - 0x5C240200, // 00F8 MOVE R9 R1 - 0x5C280400, // 00F9 MOVE R10 R2 - 0x5C2C0600, // 00FA MOVE R11 R3 - 0x7C1C0800, // 00FB CALL R7 4 - 0x80040E00, // 00FC RET 1 R7 - 0x80000000, // 00FD RET 0 + 0x7002009D, // 0015 JMP #00B4 + 0x541E0003, // 0016 LDINT R7 4 + 0x1C1C0A07, // 0017 EQ R7 R5 R7 + 0x781E0004, // 0018 JMPF R7 #001E + 0x1C1C0D05, // 0019 EQ R7 R6 K5 + 0x781E0001, // 001A JMPF R7 #001D + 0x4C1C0000, // 001B LDNIL R7 + 0x80040E00, // 001C RET 1 R7 + 0x70020095, // 001D JMP #00B4 + 0x541E0004, // 001E LDINT R7 5 + 0x1C1C0A07, // 001F EQ R7 R5 R7 + 0x781E0000, // 0020 JMPF R7 #0022 + 0x70020091, // 0021 JMP #00B4 + 0x541E001C, // 0022 LDINT R7 29 + 0x1C1C0A07, // 0023 EQ R7 R5 R7 + 0x781E0034, // 0024 JMPF R7 #005A + 0x1C1C0D05, // 0025 EQ R7 R6 K5 + 0x781E0031, // 0026 JMPF R7 #0059 + 0x8C1C090A, // 0027 GETMET R7 R4 K10 + 0x7C1C0200, // 0028 CALL R7 1 + 0x8820010B, // 0029 GETMBR R8 R0 K11 + 0x60240010, // 002A GETGBL R9 G16 + 0x8C28110C, // 002B GETMET R10 R8 K12 + 0x7C280200, // 002C CALL R10 1 + 0x7C240200, // 002D CALL R9 1 + 0xA802000E, // 002E EXBLK 0 #003E + 0x5C281200, // 002F MOVE R10 R9 + 0x7C280000, // 0030 CALL R10 0 + 0x8C2C0F0D, // 0031 GETMET R11 R7 K13 + 0x7C2C0200, // 0032 CALL R11 1 + 0x8C30170E, // 0033 GETMET R12 R11 K14 + 0x58380005, // 0034 LDCONST R14 K5 + 0x883C0907, // 0035 GETMBR R15 R4 K7 + 0x5C401400, // 0036 MOVE R16 R10 + 0x7C300800, // 0037 CALL R12 4 + 0x8C30170E, // 0038 GETMET R12 R11 K14 + 0x58380008, // 0039 LDCONST R14 K8 + 0x883C0907, // 003A GETMBR R15 R4 K7 + 0x9440100A, // 003B GETIDX R16 R8 R10 + 0x7C300800, // 003C CALL R12 4 + 0x7001FFF0, // 003D JMP #002F + 0x5824000F, // 003E LDCONST R9 K15 + 0xAC240200, // 003F CATCH R9 1 0 + 0xB0080000, // 0040 RAISE 2 R0 R0 + 0x88240110, // 0041 GETMBR R9 R0 K16 + 0x8C241311, // 0042 GETMET R9 R9 K17 + 0x8C2C0312, // 0043 GETMET R11 R1 K18 + 0x7C2C0200, // 0044 CALL R11 1 + 0x7C240400, // 0045 CALL R9 2 + 0x4C280000, // 0046 LDNIL R10 + 0x1C24120A, // 0047 EQ R9 R9 R10 + 0x7826000E, // 0048 JMPF R9 #0058 + 0x88240113, // 0049 GETMBR R9 R0 K19 + 0x88241314, // 004A GETMBR R9 R9 K20 + 0x7426000B, // 004B JMPT R9 #0058 + 0x8C240F0D, // 004C GETMET R9 R7 K13 + 0x7C240200, // 004D CALL R9 1 + 0x8C28130E, // 004E GETMET R10 R9 K14 + 0x58300005, // 004F LDCONST R12 K5 + 0x88340907, // 0050 GETMBR R13 R4 K7 + 0x543A0012, // 0051 LDINT R14 19 + 0x7C280800, // 0052 CALL R10 4 + 0x8C28130E, // 0053 GETMET R10 R9 K14 + 0x58300008, // 0054 LDCONST R12 K8 + 0x88340907, // 0055 GETMBR R13 R4 K7 + 0x58380008, // 0056 LDCONST R14 K8 + 0x7C280800, // 0057 CALL R10 4 + 0x80040E00, // 0058 RET 1 R7 + 0x70020059, // 0059 JMP #00B4 + 0x541E0038, // 005A LDINT R7 57 + 0x1C1C0A07, // 005B EQ R7 R5 R7 + 0x781E0056, // 005C JMPF R7 #00B4 + 0xA41E2A00, // 005D IMPORT R7 K21 + 0x1C200D04, // 005E EQ R8 R6 K4 + 0x7822000A, // 005F JMPF R8 #006B + 0x8C200706, // 0060 GETMET R8 R3 K6 + 0x88280916, // 0061 GETMBR R10 R4 K22 + 0xB82E2E00, // 0062 GETNGBL R11 K23 + 0x8C2C1718, // 0063 GETMET R11 R11 K24 + 0x58340019, // 0064 LDCONST R13 K25 + 0x50380200, // 0065 LDBOOL R14 1 0 + 0x7C2C0600, // 0066 CALL R11 3 + 0x942C1719, // 0067 GETIDX R11 R11 K25 + 0x7C200600, // 0068 CALL R8 3 + 0x80041000, // 0069 RET 1 R8 + 0x70020048, // 006A JMP #00B4 + 0x54220004, // 006B LDINT R8 5 + 0x1C200C08, // 006C EQ R8 R6 R8 + 0x78220006, // 006D JMPF R8 #0075 + 0x8C200706, // 006E GETMET R8 R3 K6 + 0x88280916, // 006F GETMBR R10 R4 K22 + 0x8C2C011A, // 0070 GETMET R11 R0 K26 + 0x7C2C0200, // 0071 CALL R11 1 + 0x7C200600, // 0072 CALL R8 3 + 0x80041000, // 0073 RET 1 R8 + 0x7002003E, // 0074 JMP #00B4 + 0x54220009, // 0075 LDINT R8 10 + 0x1C200C08, // 0076 EQ R8 R6 R8 + 0x78220015, // 0077 JMPF R8 #008E + 0xB8222E00, // 0078 GETNGBL R8 K23 + 0x8C201118, // 0079 GETMET R8 R8 K24 + 0x5828001B, // 007A LDCONST R10 K27 + 0x502C0200, // 007B LDBOOL R11 1 0 + 0x7C200600, // 007C CALL R8 3 + 0x9420111C, // 007D GETIDX R8 R8 K28 + 0x9420111D, // 007E GETIDX R8 R8 K29 + 0x8C240F11, // 007F GETMET R9 R7 K17 + 0x5C2C1000, // 0080 MOVE R11 R8 + 0x5830001E, // 0081 LDCONST R12 K30 + 0x7C240600, // 0082 CALL R9 3 + 0x24281305, // 0083 GT R10 R9 K5 + 0x782A0002, // 0084 JMPF R10 #0088 + 0x04281308, // 0085 SUB R10 R9 K8 + 0x402A0A0A, // 0086 CONNECT R10 K5 R10 + 0x9420100A, // 0087 GETIDX R8 R8 R10 + 0x8C280706, // 0088 GETMET R10 R3 K6 + 0x88300916, // 0089 GETMBR R12 R4 K22 + 0x5C341000, // 008A MOVE R13 R8 + 0x7C280600, // 008B CALL R10 3 + 0x80041400, // 008C RET 1 R10 + 0x70020025, // 008D JMP #00B4 + 0x5422000E, // 008E LDINT R8 15 + 0x1C200C08, // 008F EQ R8 R6 R8 + 0x7822000B, // 0090 JMPF R8 #009D + 0x8C200706, // 0091 GETMET R8 R3 K6 + 0x88280916, // 0092 GETMBR R10 R4 K22 + 0xB82E2E00, // 0093 GETNGBL R11 K23 + 0x8C2C171F, // 0094 GETMET R11 R11 K31 + 0x7C2C0200, // 0095 CALL R11 1 + 0x8C2C1711, // 0096 GETMET R11 R11 K17 + 0x58340020, // 0097 LDCONST R13 K32 + 0x58380021, // 0098 LDCONST R14 K33 + 0x7C2C0600, // 0099 CALL R11 3 + 0x7C200600, // 009A CALL R8 3 + 0x80041000, // 009B RET 1 R8 + 0x70020016, // 009C JMP #00B4 + 0x54220010, // 009D LDINT R8 17 + 0x1C200C08, // 009E EQ R8 R6 R8 + 0x78220005, // 009F JMPF R8 #00A6 + 0x8C200706, // 00A0 GETMET R8 R3 K6 + 0x88280922, // 00A1 GETMBR R10 R4 K34 + 0x582C0008, // 00A2 LDCONST R11 K8 + 0x7C200600, // 00A3 CALL R8 3 + 0x80041000, // 00A4 RET 1 R8 + 0x7002000D, // 00A5 JMP #00B4 + 0x54220011, // 00A6 LDINT R8 18 + 0x1C200C08, // 00A7 EQ R8 R6 R8 + 0x7822000A, // 00A8 JMPF R8 #00B4 + 0x8C200706, // 00A9 GETMET R8 R3 K6 + 0x88280916, // 00AA GETMBR R10 R4 K22 + 0xB82E2E00, // 00AB GETNGBL R11 K23 + 0x8C2C171F, // 00AC GETMET R11 R11 K31 + 0x7C2C0200, // 00AD CALL R11 1 + 0x8C2C1711, // 00AE GETMET R11 R11 K17 + 0x58340020, // 00AF LDCONST R13 K32 + 0x58380021, // 00B0 LDCONST R14 K33 + 0x7C2C0600, // 00B1 CALL R11 3 + 0x7C200600, // 00B2 CALL R8 3 + 0x80041000, // 00B3 RET 1 R8 + 0x601C0003, // 00B4 GETGBL R7 G3 + 0x5C200000, // 00B5 MOVE R8 R0 + 0x7C1C0200, // 00B6 CALL R7 1 + 0x8C1C0F23, // 00B7 GETMET R7 R7 K35 + 0x5C240200, // 00B8 MOVE R9 R1 + 0x5C280400, // 00B9 MOVE R10 R2 + 0x5C2C0600, // 00BA MOVE R11 R3 + 0x7C1C0800, // 00BB CALL R7 4 + 0x80040E00, // 00BC RET 1 R7 }) ) ); @@ -610,7 +544,7 @@ be_local_class(Matter_Plugin_Device, be_const_map( * be_nested_map(5, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -618,21 +552,29 @@ be_local_class(Matter_Plugin_Device, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -640,19 +582,33 @@ be_local_class(Matter_Plugin_Device, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h index 1857edafe..81040d471 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_1_Root.h @@ -117,7 +117,7 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[958]) { /* code */ + ( &(const binstruction[937]) { /* code */ 0xA4120000, // 0000 IMPORT R4 K0 0xB8160200, // 0001 GETNGBL R5 K1 0x88140B02, // 0002 GETMBR R5 R5 K2 @@ -174,11 +174,11 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x502C0000, // 0035 LDBOOL R11 0 0 0x7C200600, // 0036 CALL R8 3 0x80041000, // 0037 RET 1 R8 - 0x70020383, // 0038 JMP #03BD + 0x70020366, // 0038 JMP #03A0 0x54220031, // 0039 LDINT R8 50 0x1C200C08, // 003A EQ R8 R6 R8 0x78220000, // 003B JMPF R8 #003D - 0x7002037F, // 003C JMP #03BD + 0x70020362, // 003C JMP #03A0 0x54220032, // 003D LDINT R8 51 0x1C200C08, // 003E EQ R8 R6 R8 0x782200DC, // 003F JMPF R8 #011D @@ -402,11 +402,11 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x502C0000, // 0119 LDBOOL R11 0 0 0x7C200600, // 011A CALL R8 3 0x80041000, // 011B RET 1 R8 - 0x7002029F, // 011C JMP #03BD + 0x70020282, // 011C JMP #03A0 0x54220033, // 011D LDINT R8 52 0x1C200C08, // 011E EQ R8 R6 R8 0x78220000, // 011F JMPF R8 #0121 - 0x7002029B, // 0120 JMP #03BD + 0x7002027E, // 0120 JMP #03A0 0x54220037, // 0121 LDINT R8 56 0x1C200C08, // 0122 EQ R8 R6 R8 0x7822002B, // 0123 JMPF R8 #0150 @@ -453,7 +453,7 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x5C301000, // 014C MOVE R12 R8 0x7C240600, // 014D CALL R9 3 0x80041200, // 014E RET 1 R9 - 0x7002026C, // 014F JMP #03BD + 0x7002024F, // 014F JMP #03A0 0x5422003D, // 0150 LDINT R8 62 0x1C200C08, // 0151 EQ R8 R6 R8 0x782200B6, // 0152 JMPF R8 #020A @@ -639,7 +639,7 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x5C301000, // 0206 MOVE R12 R8 0x7C240600, // 0207 CALL R9 3 0x80041200, // 0208 RET 1 R9 - 0x700201B2, // 0209 JMP #03BD + 0x70020195, // 0209 JMP #03A0 0x5422003B, // 020A LDINT R8 60 0x1C200C08, // 020B EQ R8 R6 R8 0x7822003C, // 020C JMPF R8 #024A @@ -703,7 +703,7 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x4C300000, // 0246 LDNIL R12 0x7C240600, // 0247 CALL R9 3 0x80041200, // 0248 RET 1 R9 - 0x70020172, // 0249 JMP #03BD + 0x70020155, // 0249 JMP #03A0 0x54220027, // 024A LDINT R8 40 0x1C200C08, // 024B EQ R8 R6 R8 0x782200BA, // 024C JMPF R8 #0308 @@ -893,11 +893,11 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x5834000F, // 0304 LDCONST R13 K15 0x7C240800, // 0305 CALL R9 4 0x80041000, // 0306 RET 1 R8 - 0x700200B4, // 0307 JMP #03BD + 0x70020097, // 0307 JMP #03A0 0x5422003E, // 0308 LDINT R8 63 0x1C200C08, // 0309 EQ R8 R6 R8 0x78220000, // 030A JMPF R8 #030C - 0x700200B0, // 030B JMP #03BD + 0x70020093, // 030B JMP #03A0 0x54220029, // 030C LDINT R8 42 0x1C200C08, // 030D EQ R8 R6 R8 0x7822001D, // 030E JMPF R8 #032D @@ -930,7 +930,7 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x4C2C0000, // 0329 LDNIL R11 0x7C200600, // 032A CALL R8 3 0x80041000, // 032B RET 1 R8 - 0x7002008F, // 032C JMP #03BD + 0x70020072, // 032C JMP #03A0 0x5422002A, // 032D LDINT R8 43 0x1C200C08, // 032E EQ R8 R6 R8 0x78220016, // 032F JMPF R8 #0347 @@ -956,7 +956,7 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x7C340200, // 0343 CALL R13 1 0x7C240800, // 0344 CALL R9 4 0x80041000, // 0345 RET 1 R8 - 0x70020075, // 0346 JMP #03BD + 0x70020058, // 0346 JMP #03A0 0x5422002B, // 0347 LDINT R8 44 0x1C200C08, // 0348 EQ R8 R6 R8 0x7822001C, // 0349 JMPF R8 #0367 @@ -988,94 +988,73 @@ be_local_closure(Matter_Plugin_Root_read_attribute, /* name */ 0x7C300600, // 0363 CALL R12 3 0x7C240600, // 0364 CALL R9 3 0x80041000, // 0365 RET 1 R8 - 0x70020055, // 0366 JMP #03BD + 0x70020038, // 0366 JMP #03A0 0x54220030, // 0367 LDINT R8 49 0x1C200C08, // 0368 EQ R8 R6 R8 - 0x78220010, // 0369 JMPF R8 #037B + 0x78220007, // 0369 JMPF R8 #0372 0x1C200F0F, // 036A EQ R8 R7 K15 - 0x78220005, // 036B JMPF R8 #0372 + 0x78220004, // 036B JMPF R8 #0371 0x8C200706, // 036C GETMET R8 R3 K6 0x88280B0E, // 036D GETMBR R10 R5 K14 0x542E001D, // 036E LDINT R11 30 0x7C200600, // 036F CALL R8 3 0x80041000, // 0370 RET 1 R8 - 0x70020007, // 0371 JMP #037A - 0x5422FFFB, // 0372 LDINT R8 65532 - 0x1C200E08, // 0373 EQ R8 R7 R8 - 0x78220004, // 0374 JMPF R8 #037A - 0x8C200706, // 0375 GETMET R8 R3 K6 - 0x88280B2A, // 0376 GETMBR R10 R5 K42 - 0x542E0003, // 0377 LDINT R11 4 - 0x7C200600, // 0378 CALL R8 3 - 0x80041000, // 0379 RET 1 R8 - 0x70020041, // 037A JMP #03BD - 0x5422001C, // 037B LDINT R8 29 - 0x1C200C08, // 037C EQ R8 R6 R8 - 0x78220035, // 037D JMPF R8 #03B4 - 0x1C200F0D, // 037E EQ R8 R7 K13 - 0x78220008, // 037F JMPF R8 #0389 - 0x8C200B11, // 0380 GETMET R8 R5 K17 - 0x7C200200, // 0381 CALL R8 1 - 0x8C24110B, // 0382 GETMET R9 R8 K11 - 0x4C2C0000, // 0383 LDNIL R11 - 0x88300B0C, // 0384 GETMBR R12 R5 K12 - 0x5436001E, // 0385 LDINT R13 31 - 0x7C240800, // 0386 CALL R9 4 - 0x80041000, // 0387 RET 1 R8 - 0x70020029, // 0388 JMP #03B3 - 0x1C200F0F, // 0389 EQ R8 R7 K15 - 0x7822001E, // 038A JMPF R8 #03AA - 0x8C200B11, // 038B GETMET R8 R5 K17 - 0x7C200200, // 038C CALL R8 1 - 0x88240136, // 038D GETMBR R9 R0 K54 - 0x8C24135B, // 038E GETMET R9 R9 K91 - 0x502C0200, // 038F LDBOOL R11 1 0 - 0x7C240400, // 0390 CALL R9 2 - 0x88280136, // 0391 GETMBR R10 R0 K54 - 0x8828155C, // 0392 GETMBR R10 R10 K92 - 0x602C0010, // 0393 GETGBL R11 G16 - 0x5C301200, // 0394 MOVE R12 R9 - 0x7C2C0200, // 0395 CALL R11 1 - 0xA802000D, // 0396 EXBLK 0 #03A5 - 0x5C301600, // 0397 MOVE R12 R11 - 0x7C300000, // 0398 CALL R12 0 - 0x5C341400, // 0399 MOVE R13 R10 - 0x78360003, // 039A JMPF R13 #039F - 0xB8360200, // 039B GETNGBL R13 K1 - 0x88341B3D, // 039C GETMBR R13 R13 K61 - 0x2034180D, // 039D NE R13 R12 R13 - 0x78360004, // 039E JMPF R13 #03A4 - 0x8C34110B, // 039F GETMET R13 R8 K11 - 0x4C3C0000, // 03A0 LDNIL R15 - 0x88400B0C, // 03A1 GETMBR R16 R5 K12 - 0x5C441800, // 03A2 MOVE R17 R12 - 0x7C340800, // 03A3 CALL R13 4 - 0x7001FFF1, // 03A4 JMP #0397 - 0x582C003F, // 03A5 LDCONST R11 K63 - 0xAC2C0200, // 03A6 CATCH R11 1 0 - 0xB0080000, // 03A7 RAISE 2 R0 R0 + 0x7002002D, // 0371 JMP #03A0 + 0x5422001C, // 0372 LDINT R8 29 + 0x1C200C08, // 0373 EQ R8 R6 R8 + 0x7822002A, // 0374 JMPF R8 #03A0 + 0x1C200F0D, // 0375 EQ R8 R7 K13 + 0x78220008, // 0376 JMPF R8 #0380 + 0x8C200B11, // 0377 GETMET R8 R5 K17 + 0x7C200200, // 0378 CALL R8 1 + 0x8C24110B, // 0379 GETMET R9 R8 K11 + 0x4C2C0000, // 037A LDNIL R11 + 0x88300B0C, // 037B GETMBR R12 R5 K12 + 0x5436001E, // 037C LDINT R13 31 + 0x7C240800, // 037D CALL R9 4 + 0x80041000, // 037E RET 1 R8 + 0x7002001F, // 037F JMP #03A0 + 0x1C200F0F, // 0380 EQ R8 R7 K15 + 0x7822001D, // 0381 JMPF R8 #03A0 + 0x8C200B11, // 0382 GETMET R8 R5 K17 + 0x7C200200, // 0383 CALL R8 1 + 0x88240136, // 0384 GETMBR R9 R0 K54 + 0x8C24135B, // 0385 GETMET R9 R9 K91 + 0x502C0200, // 0386 LDBOOL R11 1 0 + 0x7C240400, // 0387 CALL R9 2 + 0x88280136, // 0388 GETMBR R10 R0 K54 + 0x8828155C, // 0389 GETMBR R10 R10 K92 + 0x602C0010, // 038A GETGBL R11 G16 + 0x5C301200, // 038B MOVE R12 R9 + 0x7C2C0200, // 038C CALL R11 1 + 0xA802000D, // 038D EXBLK 0 #039C + 0x5C301600, // 038E MOVE R12 R11 + 0x7C300000, // 038F CALL R12 0 + 0x5C341400, // 0390 MOVE R13 R10 + 0x78360003, // 0391 JMPF R13 #0396 + 0xB8360200, // 0392 GETNGBL R13 K1 + 0x88341B3D, // 0393 GETMBR R13 R13 K61 + 0x2034180D, // 0394 NE R13 R12 R13 + 0x78360004, // 0395 JMPF R13 #039B + 0x8C34110B, // 0396 GETMET R13 R8 K11 + 0x4C3C0000, // 0397 LDNIL R15 + 0x88400B0C, // 0398 GETMBR R16 R5 K12 + 0x5C441800, // 0399 MOVE R17 R12 + 0x7C340800, // 039A CALL R13 4 + 0x7001FFF1, // 039B JMP #038E + 0x582C003F, // 039C LDCONST R11 K63 + 0xAC2C0200, // 039D CATCH R11 1 0 + 0xB0080000, // 039E RAISE 2 R0 R0 + 0x80041000, // 039F RET 1 R8 + 0x60200003, // 03A0 GETGBL R8 G3 + 0x5C240000, // 03A1 MOVE R9 R0 + 0x7C200200, // 03A2 CALL R8 1 + 0x8C20115D, // 03A3 GETMET R8 R8 K93 + 0x5C280200, // 03A4 MOVE R10 R1 + 0x5C2C0400, // 03A5 MOVE R11 R2 + 0x5C300600, // 03A6 MOVE R12 R3 + 0x7C200800, // 03A7 CALL R8 4 0x80041000, // 03A8 RET 1 R8 - 0x70020008, // 03A9 JMP #03B3 - 0x60200003, // 03AA GETGBL R8 G3 - 0x5C240000, // 03AB MOVE R9 R0 - 0x7C200200, // 03AC CALL R8 1 - 0x8C20115D, // 03AD GETMET R8 R8 K93 - 0x5C280200, // 03AE MOVE R10 R1 - 0x5C2C0400, // 03AF MOVE R11 R2 - 0x5C300600, // 03B0 MOVE R12 R3 - 0x7C200800, // 03B1 CALL R8 4 - 0x80041000, // 03B2 RET 1 R8 - 0x70020008, // 03B3 JMP #03BD - 0x60200003, // 03B4 GETGBL R8 G3 - 0x5C240000, // 03B5 MOVE R9 R0 - 0x7C200200, // 03B6 CALL R8 1 - 0x8C20115D, // 03B7 GETMET R8 R8 K93 - 0x5C280200, // 03B8 MOVE R10 R1 - 0x5C2C0400, // 03B9 MOVE R11 R2 - 0x5C300600, // 03BA MOVE R12 R3 - 0x7C200800, // 03BB CALL R8 4 - 0x80041000, // 03BC RET 1 R8 - 0x80000000, // 03BD RET 0 }) ) ); @@ -2141,50 +2120,84 @@ be_local_class(Matter_Plugin_Root, be_const_map( * be_nested_map(14, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(56, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(7), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 11), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(44, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(31, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(2), be_const_int(3), be_const_int(4), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(60, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(63, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(0, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(62, 13), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -2192,38 +2205,73 @@ be_local_class(Matter_Plugin_Root, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(49, 5), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(4), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(50, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(0, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(51, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(8), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(52, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(0, + be_const_list( * be_nested_list(6, ( (struct bvalue*) &(const bvalue[]) { + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(43, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(2, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(40, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(15, + be_const_list( * be_nested_list(21, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -2240,15 +2288,27 @@ be_local_class(Matter_Plugin_Root, be_const_int(17), be_const_int(18), be_const_int(19), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(48, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(5, + be_const_list( * be_nested_list(11, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), be_const_int(4), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, })) ) } )) }, })), diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Bridge_HTTP.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Bridge_HTTP.h index 418f03eae..01c1452de 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Bridge_HTTP.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Bridge_HTTP.h @@ -596,14 +596,14 @@ be_local_closure(Matter_Plugin_Bridge_HTTP_read_attribute, /* name */ }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[115]) { /* code */ + ( &(const binstruction[103]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0038, // 0004 LDINT R7 57 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0061, // 0006 JMPF R7 #0069 + 0x781E0056, // 0006 JMPF R7 #005E 0xA41E0800, // 0007 IMPORT R7 K4 0x1C200D05, // 0008 EQ R8 R6 K5 0x78220012, // 0009 JMPF R8 #001D @@ -625,7 +625,7 @@ be_local_closure(Matter_Plugin_Bridge_HTTP_read_attribute, /* name */ 0x4C300000, // 0019 LDNIL R12 0x7C240600, // 001A CALL R9 3 0x80041200, // 001B RET 1 R9 - 0x7002004A, // 001C JMP #0068 + 0x70020040, // 001C JMP #005E 0x54220009, // 001D LDINT R8 10 0x1C200C08, // 001E EQ R8 R6 R8 0x7822001B, // 001F JMPF R8 #003C @@ -656,7 +656,7 @@ be_local_closure(Matter_Plugin_Bridge_HTTP_read_attribute, /* name */ 0x4C300000, // 0038 LDNIL R12 0x7C240600, // 0039 CALL R9 3 0x80041200, // 003A RET 1 R9 - 0x7002002B, // 003B JMP #0068 + 0x70020021, // 003B JMP #005E 0x5422000E, // 003C LDINT R8 15 0x1C200C08, // 003D EQ R8 R6 R8 0x74220002, // 003E JMPT R8 #0042 @@ -681,37 +681,25 @@ be_local_closure(Matter_Plugin_Bridge_HTTP_read_attribute, /* name */ 0x4C300000, // 0051 LDNIL R12 0x7C240600, // 0052 CALL R9 3 0x80041200, // 0053 RET 1 R9 - 0x70020012, // 0054 JMP #0068 + 0x70020008, // 0054 JMP #005E 0x54220010, // 0055 LDINT R8 17 0x1C200C08, // 0056 EQ R8 R6 R8 - 0x78220006, // 0057 JMPF R8 #005F + 0x78220005, // 0057 JMPF R8 #005E 0x8C20070A, // 0058 GETMET R8 R3 K10 0x88280912, // 0059 GETMBR R10 R4 K18 0x882C0106, // 005A GETMBR R11 R0 K6 0x882C1713, // 005B GETMBR R11 R11 K19 0x7C200600, // 005C CALL R8 3 0x80041000, // 005D RET 1 R8 - 0x70020008, // 005E JMP #0068 - 0x60200003, // 005F GETGBL R8 G3 - 0x5C240000, // 0060 MOVE R9 R0 - 0x7C200200, // 0061 CALL R8 1 - 0x8C201114, // 0062 GETMET R8 R8 K20 - 0x5C280200, // 0063 MOVE R10 R1 - 0x5C2C0400, // 0064 MOVE R11 R2 - 0x5C300600, // 0065 MOVE R12 R3 - 0x7C200800, // 0066 CALL R8 4 - 0x80041000, // 0067 RET 1 R8 - 0x70020008, // 0068 JMP #0072 - 0x601C0003, // 0069 GETGBL R7 G3 - 0x5C200000, // 006A MOVE R8 R0 - 0x7C1C0200, // 006B CALL R7 1 - 0x8C1C0F14, // 006C GETMET R7 R7 K20 - 0x5C240200, // 006D MOVE R9 R1 - 0x5C280400, // 006E MOVE R10 R2 - 0x5C2C0600, // 006F MOVE R11 R3 - 0x7C1C0800, // 0070 CALL R7 4 - 0x80040E00, // 0071 RET 1 R7 - 0x80000000, // 0072 RET 0 + 0x601C0003, // 005E GETGBL R7 G3 + 0x5C200000, // 005F MOVE R8 R0 + 0x7C1C0200, // 0060 CALL R7 1 + 0x8C1C0F14, // 0061 GETMET R7 R7 K20 + 0x5C240200, // 0062 MOVE R9 R1 + 0x5C280400, // 0063 MOVE R10 R2 + 0x5C2C0600, // 0064 MOVE R11 R3 + 0x7C1C0800, // 0065 CALL R7 4 + 0x80040E00, // 0066 RET 1 R7 }) ) ); diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Light1.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Light1.h index cdbd20304..eb7e8a61b 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Light1.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Light1.h @@ -474,7 +474,7 @@ be_local_closure(Matter_Plugin_Light1_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[16]) { /* constants */ + ( &(const bvalue[14]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -484,127 +484,87 @@ be_local_closure(Matter_Plugin_Light1_read_attribute, /* name */ /* K6 */ be_nested_str_weak(set), /* K7 */ be_nested_str_weak(BOOL), /* K8 */ be_nested_str_weak(shadow_onoff), - /* K9 */ be_nested_str_weak(U4), - /* K10 */ be_nested_str_weak(U1), - /* K11 */ be_nested_str_weak(shadow_bri), - /* K12 */ be_const_int(2), - /* K13 */ be_const_int(3), - /* K14 */ be_const_int(1), - /* K15 */ be_nested_str_weak(read_attribute), + /* K9 */ be_nested_str_weak(U1), + /* K10 */ be_nested_str_weak(shadow_bri), + /* K11 */ be_const_int(2), + /* K12 */ be_const_int(3), + /* K13 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[110]) { /* code */ + ( &(const binstruction[72]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0005, // 0004 LDINT R7 6 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E001B, // 0006 JMPF R7 #0023 + 0x781E0009, // 0006 JMPF R7 #0011 0x8C1C0104, // 0007 GETMET R7 R0 K4 0x7C1C0200, // 0008 CALL R7 1 0x1C1C0D05, // 0009 EQ R7 R6 K5 - 0x781E0005, // 000A JMPF R7 #0011 + 0x781E0004, // 000A JMPF R7 #0010 0x8C1C0706, // 000B GETMET R7 R3 K6 0x88240907, // 000C GETMBR R9 R4 K7 0x88280108, // 000D GETMBR R10 R0 K8 0x7C1C0600, // 000E CALL R7 3 0x80040E00, // 000F RET 1 R7 - 0x70020010, // 0010 JMP #0022 - 0x541EFFFB, // 0011 LDINT R7 65532 - 0x1C1C0C07, // 0012 EQ R7 R6 R7 - 0x781E0005, // 0013 JMPF R7 #001A - 0x8C1C0706, // 0014 GETMET R7 R3 K6 - 0x88240909, // 0015 GETMBR R9 R4 K9 - 0x58280005, // 0016 LDCONST R10 K5 - 0x7C1C0600, // 0017 CALL R7 3 - 0x80040E00, // 0018 RET 1 R7 - 0x70020007, // 0019 JMP #0022 - 0x541EFFFC, // 001A LDINT R7 65533 - 0x1C1C0C07, // 001B EQ R7 R6 R7 - 0x781E0004, // 001C JMPF R7 #0022 - 0x8C1C0706, // 001D GETMET R7 R3 K6 - 0x88240909, // 001E GETMBR R9 R4 K9 - 0x542A0003, // 001F LDINT R10 4 - 0x7C1C0600, // 0020 CALL R7 3 - 0x80040E00, // 0021 RET 1 R7 - 0x70020049, // 0022 JMP #006D - 0x541E0007, // 0023 LDINT R7 8 - 0x1C1C0A07, // 0024 EQ R7 R5 R7 - 0x781E003D, // 0025 JMPF R7 #0064 - 0x8C1C0104, // 0026 GETMET R7 R0 K4 - 0x7C1C0200, // 0027 CALL R7 1 - 0x1C1C0D05, // 0028 EQ R7 R6 K5 - 0x781E0005, // 0029 JMPF R7 #0030 - 0x8C1C0706, // 002A GETMET R7 R3 K6 - 0x8824090A, // 002B GETMBR R9 R4 K10 - 0x8828010B, // 002C GETMBR R10 R0 K11 - 0x7C1C0600, // 002D CALL R7 3 - 0x80040E00, // 002E RET 1 R7 - 0x70020032, // 002F JMP #0063 - 0x1C1C0D0C, // 0030 EQ R7 R6 K12 - 0x781E0005, // 0031 JMPF R7 #0038 - 0x8C1C0706, // 0032 GETMET R7 R3 K6 - 0x8824090A, // 0033 GETMBR R9 R4 K10 - 0x58280005, // 0034 LDCONST R10 K5 - 0x7C1C0600, // 0035 CALL R7 3 - 0x80040E00, // 0036 RET 1 R7 - 0x7002002A, // 0037 JMP #0063 - 0x1C1C0D0D, // 0038 EQ R7 R6 K13 - 0x781E0005, // 0039 JMPF R7 #0040 + 0x7002002D, // 0010 JMP #003F + 0x541E0007, // 0011 LDINT R7 8 + 0x1C1C0A07, // 0012 EQ R7 R5 R7 + 0x781E002A, // 0013 JMPF R7 #003F + 0x8C1C0104, // 0014 GETMET R7 R0 K4 + 0x7C1C0200, // 0015 CALL R7 1 + 0x1C1C0D05, // 0016 EQ R7 R6 K5 + 0x781E0005, // 0017 JMPF R7 #001E + 0x8C1C0706, // 0018 GETMET R7 R3 K6 + 0x88240909, // 0019 GETMBR R9 R4 K9 + 0x8828010A, // 001A GETMBR R10 R0 K10 + 0x7C1C0600, // 001B CALL R7 3 + 0x80040E00, // 001C RET 1 R7 + 0x70020020, // 001D JMP #003F + 0x1C1C0D0B, // 001E EQ R7 R6 K11 + 0x781E0005, // 001F JMPF R7 #0026 + 0x8C1C0706, // 0020 GETMET R7 R3 K6 + 0x88240909, // 0021 GETMBR R9 R4 K9 + 0x58280005, // 0022 LDCONST R10 K5 + 0x7C1C0600, // 0023 CALL R7 3 + 0x80040E00, // 0024 RET 1 R7 + 0x70020018, // 0025 JMP #003F + 0x1C1C0D0C, // 0026 EQ R7 R6 K12 + 0x781E0005, // 0027 JMPF R7 #002E + 0x8C1C0706, // 0028 GETMET R7 R3 K6 + 0x88240909, // 0029 GETMBR R9 R4 K9 + 0x542A00FD, // 002A LDINT R10 254 + 0x7C1C0600, // 002B CALL R7 3 + 0x80040E00, // 002C RET 1 R7 + 0x70020010, // 002D JMP #003F + 0x541E000E, // 002E LDINT R7 15 + 0x1C1C0C07, // 002F EQ R7 R6 R7 + 0x781E0005, // 0030 JMPF R7 #0037 + 0x8C1C0706, // 0031 GETMET R7 R3 K6 + 0x88240909, // 0032 GETMBR R9 R4 K9 + 0x58280005, // 0033 LDCONST R10 K5 + 0x7C1C0600, // 0034 CALL R7 3 + 0x80040E00, // 0035 RET 1 R7 + 0x70020007, // 0036 JMP #003F + 0x541E0010, // 0037 LDINT R7 17 + 0x1C1C0C07, // 0038 EQ R7 R6 R7 + 0x781E0004, // 0039 JMPF R7 #003F 0x8C1C0706, // 003A GETMET R7 R3 K6 - 0x8824090A, // 003B GETMBR R9 R4 K10 - 0x542A00FD, // 003C LDINT R10 254 + 0x88240909, // 003B GETMBR R9 R4 K9 + 0x8828010A, // 003C GETMBR R10 R0 K10 0x7C1C0600, // 003D CALL R7 3 0x80040E00, // 003E RET 1 R7 - 0x70020022, // 003F JMP #0063 - 0x541E000E, // 0040 LDINT R7 15 - 0x1C1C0C07, // 0041 EQ R7 R6 R7 - 0x781E0005, // 0042 JMPF R7 #0049 - 0x8C1C0706, // 0043 GETMET R7 R3 K6 - 0x8824090A, // 0044 GETMBR R9 R4 K10 - 0x58280005, // 0045 LDCONST R10 K5 - 0x7C1C0600, // 0046 CALL R7 3 + 0x601C0003, // 003F GETGBL R7 G3 + 0x5C200000, // 0040 MOVE R8 R0 + 0x7C1C0200, // 0041 CALL R7 1 + 0x8C1C0F0D, // 0042 GETMET R7 R7 K13 + 0x5C240200, // 0043 MOVE R9 R1 + 0x5C280400, // 0044 MOVE R10 R2 + 0x5C2C0600, // 0045 MOVE R11 R3 + 0x7C1C0800, // 0046 CALL R7 4 0x80040E00, // 0047 RET 1 R7 - 0x70020019, // 0048 JMP #0063 - 0x541E0010, // 0049 LDINT R7 17 - 0x1C1C0C07, // 004A EQ R7 R6 R7 - 0x781E0005, // 004B JMPF R7 #0052 - 0x8C1C0706, // 004C GETMET R7 R3 K6 - 0x8824090A, // 004D GETMBR R9 R4 K10 - 0x8828010B, // 004E GETMBR R10 R0 K11 - 0x7C1C0600, // 004F CALL R7 3 - 0x80040E00, // 0050 RET 1 R7 - 0x70020010, // 0051 JMP #0063 - 0x541EFFFB, // 0052 LDINT R7 65532 - 0x1C1C0C07, // 0053 EQ R7 R6 R7 - 0x781E0005, // 0054 JMPF R7 #005B - 0x8C1C0706, // 0055 GETMET R7 R3 K6 - 0x88240909, // 0056 GETMBR R9 R4 K9 - 0x5828000E, // 0057 LDCONST R10 K14 - 0x7C1C0600, // 0058 CALL R7 3 - 0x80040E00, // 0059 RET 1 R7 - 0x70020007, // 005A JMP #0063 - 0x541EFFFC, // 005B LDINT R7 65533 - 0x1C1C0C07, // 005C EQ R7 R6 R7 - 0x781E0004, // 005D JMPF R7 #0063 - 0x8C1C0706, // 005E GETMET R7 R3 K6 - 0x88240909, // 005F GETMBR R9 R4 K9 - 0x542A0004, // 0060 LDINT R10 5 - 0x7C1C0600, // 0061 CALL R7 3 - 0x80040E00, // 0062 RET 1 R7 - 0x70020008, // 0063 JMP #006D - 0x601C0003, // 0064 GETGBL R7 G3 - 0x5C200000, // 0065 MOVE R8 R0 - 0x7C1C0200, // 0066 CALL R7 1 - 0x8C1C0F0F, // 0067 GETMET R7 R7 K15 - 0x5C240200, // 0068 MOVE R9 R1 - 0x5C280400, // 0069 MOVE R10 R2 - 0x5C2C0600, // 006A MOVE R11 R3 - 0x7C1C0800, // 006B CALL R7 4 - 0x80040E00, // 006C RET 1 R7 - 0x80000000, // 006D RET 0 }) ) ); @@ -740,28 +700,36 @@ be_local_class(Matter_Plugin_Light1, be_const_map( * be_nested_map(7, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(29, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(8, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(11, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(2), be_const_int(3), be_const_int(15), be_const_int(17), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -769,24 +737,38 @@ be_local_class(Matter_Plugin_Light1, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -794,13 +776,21 @@ be_local_class(Matter_Plugin_Light1, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(6, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_OnOff.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_OnOff.h index 79973bcd2..968917d0b 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_OnOff.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_OnOff.h @@ -107,7 +107,7 @@ be_local_closure(Matter_Plugin_OnOff_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ + ( &(const bvalue[10]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -117,57 +117,36 @@ be_local_closure(Matter_Plugin_OnOff_read_attribute, /* name */ /* K6 */ be_nested_str_weak(set), /* K7 */ be_nested_str_weak(BOOL), /* K8 */ be_nested_str_weak(shadow_onoff), - /* K9 */ be_nested_str_weak(U4), - /* K10 */ be_nested_str_weak(read_attribute), + /* K9 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[45]) { /* code */ + ( &(const binstruction[25]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0005, // 0004 LDINT R7 6 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E001B, // 0006 JMPF R7 #0023 + 0x781E0008, // 0006 JMPF R7 #0010 0x8C1C0104, // 0007 GETMET R7 R0 K4 0x7C1C0200, // 0008 CALL R7 1 0x1C1C0D05, // 0009 EQ R7 R6 K5 - 0x781E0005, // 000A JMPF R7 #0011 + 0x781E0004, // 000A JMPF R7 #0010 0x8C1C0706, // 000B GETMET R7 R3 K6 0x88240907, // 000C GETMBR R9 R4 K7 0x88280108, // 000D GETMBR R10 R0 K8 0x7C1C0600, // 000E CALL R7 3 0x80040E00, // 000F RET 1 R7 - 0x70020010, // 0010 JMP #0022 - 0x541EFFFB, // 0011 LDINT R7 65532 - 0x1C1C0C07, // 0012 EQ R7 R6 R7 - 0x781E0005, // 0013 JMPF R7 #001A - 0x8C1C0706, // 0014 GETMET R7 R3 K6 - 0x88240909, // 0015 GETMBR R9 R4 K9 - 0x58280005, // 0016 LDCONST R10 K5 - 0x7C1C0600, // 0017 CALL R7 3 + 0x601C0003, // 0010 GETGBL R7 G3 + 0x5C200000, // 0011 MOVE R8 R0 + 0x7C1C0200, // 0012 CALL R7 1 + 0x8C1C0F09, // 0013 GETMET R7 R7 K9 + 0x5C240200, // 0014 MOVE R9 R1 + 0x5C280400, // 0015 MOVE R10 R2 + 0x5C2C0600, // 0016 MOVE R11 R3 + 0x7C1C0800, // 0017 CALL R7 4 0x80040E00, // 0018 RET 1 R7 - 0x70020007, // 0019 JMP #0022 - 0x541EFFFC, // 001A LDINT R7 65533 - 0x1C1C0C07, // 001B EQ R7 R6 R7 - 0x781E0004, // 001C JMPF R7 #0022 - 0x8C1C0706, // 001D GETMET R7 R3 K6 - 0x88240909, // 001E GETMBR R9 R4 K9 - 0x542A0003, // 001F LDINT R10 4 - 0x7C1C0600, // 0020 CALL R7 3 - 0x80040E00, // 0021 RET 1 R7 - 0x70020008, // 0022 JMP #002C - 0x601C0003, // 0023 GETGBL R7 G3 - 0x5C200000, // 0024 MOVE R8 R0 - 0x7C1C0200, // 0025 CALL R7 1 - 0x8C1C0F0A, // 0026 GETMET R7 R7 K10 - 0x5C240200, // 0027 MOVE R9 R1 - 0x5C280400, // 0028 MOVE R10 R2 - 0x5C2C0600, // 0029 MOVE R11 R3 - 0x7C1C0800, // 002A CALL R7 4 - 0x80040E00, // 002B RET 1 R7 - 0x80000000, // 002C RET 0 }) ) ); @@ -465,14 +444,18 @@ be_local_class(Matter_Plugin_OnOff, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(6, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -480,11 +463,15 @@ be_local_class(Matter_Plugin_OnOff, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -492,29 +479,47 @@ be_local_class(Matter_Plugin_OnOff, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h index dc4bd4205..8900284a9 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Contact.h @@ -205,7 +205,7 @@ be_local_closure(Matter_Plugin_Sensor_Contact_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[12]) { /* constants */ + ( &(const bvalue[10]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -215,22 +215,20 @@ be_local_closure(Matter_Plugin_Sensor_Contact_read_attribute, /* name */ /* K6 */ be_nested_str_weak(set), /* K7 */ be_nested_str_weak(BOOL), /* K8 */ be_nested_str_weak(NULL), - /* K9 */ be_nested_str_weak(U4), - /* K10 */ be_const_int(1), - /* K11 */ be_nested_str_weak(read_attribute), + /* K9 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[53]) { /* code */ + ( &(const binstruction[33]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0044, // 0004 LDINT R7 69 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0023, // 0006 JMPF R7 #002B + 0x781E0010, // 0006 JMPF R7 #0018 0x1C1C0D04, // 0007 EQ R7 R6 K4 - 0x781E000F, // 0008 JMPF R7 #0019 + 0x781E000E, // 0008 JMPF R7 #0018 0x881C0105, // 0009 GETMBR R7 R0 K5 0x4C200000, // 000A LDNIL R8 0x201C0E08, // 000B NE R7 R7 R8 @@ -246,35 +244,15 @@ be_local_closure(Matter_Plugin_Sensor_Contact_read_attribute, /* name */ 0x4C280000, // 0015 LDNIL R10 0x7C1C0600, // 0016 CALL R7 3 0x80040E00, // 0017 RET 1 R7 - 0x70020010, // 0018 JMP #002A - 0x541EFFFB, // 0019 LDINT R7 65532 - 0x1C1C0C07, // 001A EQ R7 R6 R7 - 0x781E0005, // 001B JMPF R7 #0022 - 0x8C1C0706, // 001C GETMET R7 R3 K6 - 0x88240909, // 001D GETMBR R9 R4 K9 - 0x58280004, // 001E LDCONST R10 K4 - 0x7C1C0600, // 001F CALL R7 3 + 0x601C0003, // 0018 GETGBL R7 G3 + 0x5C200000, // 0019 MOVE R8 R0 + 0x7C1C0200, // 001A CALL R7 1 + 0x8C1C0F09, // 001B GETMET R7 R7 K9 + 0x5C240200, // 001C MOVE R9 R1 + 0x5C280400, // 001D MOVE R10 R2 + 0x5C2C0600, // 001E MOVE R11 R3 + 0x7C1C0800, // 001F CALL R7 4 0x80040E00, // 0020 RET 1 R7 - 0x70020007, // 0021 JMP #002A - 0x541EFFFC, // 0022 LDINT R7 65533 - 0x1C1C0C07, // 0023 EQ R7 R6 R7 - 0x781E0004, // 0024 JMPF R7 #002A - 0x8C1C0706, // 0025 GETMET R7 R3 K6 - 0x88240909, // 0026 GETMBR R9 R4 K9 - 0x5828000A, // 0027 LDCONST R10 K10 - 0x7C1C0600, // 0028 CALL R7 3 - 0x80040E00, // 0029 RET 1 R7 - 0x70020008, // 002A JMP #0034 - 0x601C0003, // 002B GETGBL R7 G3 - 0x5C200000, // 002C MOVE R8 R0 - 0x7C1C0200, // 002D CALL R7 1 - 0x8C1C0F0B, // 002E GETMET R7 R7 K11 - 0x5C240200, // 002F MOVE R9 R1 - 0x5C280400, // 0030 MOVE R10 R2 - 0x5C2C0600, // 0031 MOVE R11 R3 - 0x7C1C0800, // 0032 CALL R7 4 - 0x80040E00, // 0033 RET 1 R7 - 0x80000000, // 0034 RET 0 }) ) ); @@ -369,7 +347,7 @@ be_local_class(Matter_Plugin_Sensor_Contact, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -377,19 +355,27 @@ be_local_class(Matter_Plugin_Sensor_Contact, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(3, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -397,28 +383,46 @@ be_local_class(Matter_Plugin_Sensor_Contact, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(69, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Occupancy.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Occupancy.h index a26bb32ad..a423b4a6f 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Occupancy.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_Occupancy.h @@ -260,7 +260,7 @@ be_local_closure(Matter_Plugin_Sensor_Occupancy_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ + ( &(const bvalue[13]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -273,19 +273,18 @@ be_local_closure(Matter_Plugin_Sensor_Occupancy_read_attribute, /* name */ /* K9 */ be_const_int(1), /* K10 */ be_const_int(3), /* K11 */ be_const_int(2), - /* K12 */ be_nested_str_weak(U4), - /* K13 */ be_nested_str_weak(read_attribute), + /* K12 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[69]) { /* code */ + ( &(const binstruction[49]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0405, // 0004 LDINT R7 1030 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0033, // 0006 JMPF R7 #003B + 0x781E0020, // 0006 JMPF R7 #0028 0x1C1C0D04, // 0007 EQ R7 R6 K4 0x781E000F, // 0008 JMPF R7 #0019 0x881C0105, // 0009 GETMBR R7 R0 K5 @@ -303,7 +302,7 @@ be_local_closure(Matter_Plugin_Sensor_Occupancy_read_attribute, /* name */ 0x4C280000, // 0015 LDNIL R10 0x7C1C0600, // 0016 CALL R7 3 0x80040E00, // 0017 RET 1 R7 - 0x70020020, // 0018 JMP #003A + 0x7002000E, // 0018 JMP #0028 0x1C1C0D09, // 0019 EQ R7 R6 K9 0x781E0005, // 001A JMPF R7 #0021 0x8C1C0706, // 001B GETMET R7 R3 K6 @@ -311,43 +310,23 @@ be_local_closure(Matter_Plugin_Sensor_Occupancy_read_attribute, /* name */ 0x5828000A, // 001D LDCONST R10 K10 0x7C1C0600, // 001E CALL R7 3 0x80040E00, // 001F RET 1 R7 - 0x70020018, // 0020 JMP #003A + 0x70020006, // 0020 JMP #0028 0x1C1C0D0B, // 0021 EQ R7 R6 K11 - 0x781E0005, // 0022 JMPF R7 #0029 + 0x781E0004, // 0022 JMPF R7 #0028 0x8C1C0706, // 0023 GETMET R7 R3 K6 0x88240907, // 0024 GETMBR R9 R4 K7 0x58280004, // 0025 LDCONST R10 K4 0x7C1C0600, // 0026 CALL R7 3 0x80040E00, // 0027 RET 1 R7 - 0x70020010, // 0028 JMP #003A - 0x541EFFFB, // 0029 LDINT R7 65532 - 0x1C1C0C07, // 002A EQ R7 R6 R7 - 0x781E0005, // 002B JMPF R7 #0032 - 0x8C1C0706, // 002C GETMET R7 R3 K6 - 0x8824090C, // 002D GETMBR R9 R4 K12 - 0x58280004, // 002E LDCONST R10 K4 - 0x7C1C0600, // 002F CALL R7 3 + 0x601C0003, // 0028 GETGBL R7 G3 + 0x5C200000, // 0029 MOVE R8 R0 + 0x7C1C0200, // 002A CALL R7 1 + 0x8C1C0F0C, // 002B GETMET R7 R7 K12 + 0x5C240200, // 002C MOVE R9 R1 + 0x5C280400, // 002D MOVE R10 R2 + 0x5C2C0600, // 002E MOVE R11 R3 + 0x7C1C0800, // 002F CALL R7 4 0x80040E00, // 0030 RET 1 R7 - 0x70020007, // 0031 JMP #003A - 0x541EFFFC, // 0032 LDINT R7 65533 - 0x1C1C0C07, // 0033 EQ R7 R6 R7 - 0x781E0004, // 0034 JMPF R7 #003A - 0x8C1C0706, // 0035 GETMET R7 R3 K6 - 0x8824090C, // 0036 GETMBR R9 R4 K12 - 0x5828000A, // 0037 LDCONST R10 K10 - 0x7C1C0600, // 0038 CALL R7 3 - 0x80040E00, // 0039 RET 1 R7 - 0x70020008, // 003A JMP #0044 - 0x601C0003, // 003B GETGBL R7 G3 - 0x5C200000, // 003C MOVE R8 R0 - 0x7C1C0200, // 003D CALL R7 1 - 0x8C1C0F0D, // 003E GETMET R7 R7 K13 - 0x5C240200, // 003F MOVE R9 R1 - 0x5C280400, // 0040 MOVE R10 R2 - 0x5C2C0600, // 0041 MOVE R11 R3 - 0x7C1C0800, // 0042 CALL R7 4 - 0x80040E00, // 0043 RET 1 R7 - 0x80000000, // 0044 RET 0 }) ) ); @@ -376,7 +355,7 @@ be_local_class(Matter_Plugin_Sensor_Occupancy, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -384,18 +363,26 @@ be_local_class(Matter_Plugin_Sensor_Occupancy, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -403,31 +390,49 @@ be_local_class(Matter_Plugin_Sensor_Occupancy, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(1030, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(5, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_OnOff.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_OnOff.h index 3bc3d3148..8f8f8c192 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_OnOff.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Sensor_OnOff.h @@ -168,7 +168,7 @@ be_local_closure(Matter_Plugin_Sensor_OnOff_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ + ( &(const bvalue[10]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -178,57 +178,36 @@ be_local_closure(Matter_Plugin_Sensor_OnOff_read_attribute, /* name */ /* K6 */ be_nested_str_weak(set), /* K7 */ be_nested_str_weak(BOOL), /* K8 */ be_nested_str_weak(shadow_onoff), - /* K9 */ be_nested_str_weak(U4), - /* K10 */ be_nested_str_weak(read_attribute), + /* K9 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[45]) { /* code */ + ( &(const binstruction[25]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0005, // 0004 LDINT R7 6 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E001B, // 0006 JMPF R7 #0023 + 0x781E0008, // 0006 JMPF R7 #0010 0x8C1C0104, // 0007 GETMET R7 R0 K4 0x7C1C0200, // 0008 CALL R7 1 0x1C1C0D05, // 0009 EQ R7 R6 K5 - 0x781E0005, // 000A JMPF R7 #0011 + 0x781E0004, // 000A JMPF R7 #0010 0x8C1C0706, // 000B GETMET R7 R3 K6 0x88240907, // 000C GETMBR R9 R4 K7 0x88280108, // 000D GETMBR R10 R0 K8 0x7C1C0600, // 000E CALL R7 3 0x80040E00, // 000F RET 1 R7 - 0x70020010, // 0010 JMP #0022 - 0x541EFFFB, // 0011 LDINT R7 65532 - 0x1C1C0C07, // 0012 EQ R7 R6 R7 - 0x781E0005, // 0013 JMPF R7 #001A - 0x8C1C0706, // 0014 GETMET R7 R3 K6 - 0x88240909, // 0015 GETMBR R9 R4 K9 - 0x58280005, // 0016 LDCONST R10 K5 - 0x7C1C0600, // 0017 CALL R7 3 + 0x601C0003, // 0010 GETGBL R7 G3 + 0x5C200000, // 0011 MOVE R8 R0 + 0x7C1C0200, // 0012 CALL R7 1 + 0x8C1C0F09, // 0013 GETMET R7 R7 K9 + 0x5C240200, // 0014 MOVE R9 R1 + 0x5C280400, // 0015 MOVE R10 R2 + 0x5C2C0600, // 0016 MOVE R11 R3 + 0x7C1C0800, // 0017 CALL R7 4 0x80040E00, // 0018 RET 1 R7 - 0x70020007, // 0019 JMP #0022 - 0x541EFFFC, // 001A LDINT R7 65533 - 0x1C1C0C07, // 001B EQ R7 R6 R7 - 0x781E0004, // 001C JMPF R7 #0022 - 0x8C1C0706, // 001D GETMET R7 R3 K6 - 0x88240909, // 001E GETMBR R9 R4 K9 - 0x542A0003, // 001F LDINT R10 4 - 0x7C1C0600, // 0020 CALL R7 3 - 0x80040E00, // 0021 RET 1 R7 - 0x70020008, // 0022 JMP #002C - 0x601C0003, // 0023 GETGBL R7 G3 - 0x5C200000, // 0024 MOVE R8 R0 - 0x7C1C0200, // 0025 CALL R7 1 - 0x8C1C0F0A, // 0026 GETMET R7 R7 K10 - 0x5C240200, // 0027 MOVE R9 R1 - 0x5C280400, // 0028 MOVE R10 R2 - 0x5C2C0600, // 0029 MOVE R11 R3 - 0x7C1C0800, // 002A CALL R7 4 - 0x80040E00, // 002B RET 1 R7 - 0x80000000, // 002C RET 0 }) ) ); @@ -281,14 +260,18 @@ be_local_class(Matter_Plugin_Sensor_OnOff, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(6, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -296,11 +279,15 @@ be_local_class(Matter_Plugin_Sensor_OnOff, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -308,29 +295,47 @@ be_local_class(Matter_Plugin_Sensor_OnOff, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Shutter.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Shutter.h index b8d03111b..eb73d03f8 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Shutter.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_2_Shutter.h @@ -224,7 +224,7 @@ be_local_closure(Matter_Plugin_Shutter_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[18]) { /* constants */ + ( &(const bvalue[17]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -241,12 +241,11 @@ be_local_closure(Matter_Plugin_Shutter_read_attribute, /* name */ /* K13 */ be_nested_str_weak(shadow_shutter_direction), /* K14 */ be_const_int(2), /* K15 */ be_nested_str_weak(shadow_shutter_target), - /* K16 */ be_nested_str_weak(U4), - /* K17 */ be_nested_str_weak(read_attribute), + /* K16 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[152]) { /* code */ + ( &(const binstruction[131]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 @@ -254,7 +253,7 @@ be_local_closure(Matter_Plugin_Shutter_read_attribute, /* name */ 0x4C1C0000, // 0004 LDNIL R7 0x54220101, // 0005 LDINT R8 258 0x1C200A08, // 0006 EQ R8 R5 R8 - 0x78220085, // 0007 JMPF R8 #008E + 0x78220071, // 0007 JMPF R8 #007A 0x8C200104, // 0008 GETMET R8 R0 K4 0x7C200200, // 0009 CALL R8 1 0x8C200105, // 000A GETMET R8 R0 K5 @@ -266,7 +265,7 @@ be_local_closure(Matter_Plugin_Shutter_read_attribute, /* name */ 0x542E00FE, // 0010 LDINT R11 255 0x7C200600, // 0011 CALL R8 3 0x80041000, // 0012 RET 1 R8 - 0x70020078, // 0013 JMP #008D + 0x70020065, // 0013 JMP #007A 0x54220004, // 0014 LDINT R8 5 0x1C200C08, // 0015 EQ R8 R6 R8 0x78220005, // 0016 JMPF R8 #001D @@ -275,7 +274,7 @@ be_local_closure(Matter_Plugin_Shutter_read_attribute, /* name */ 0x582C0006, // 0019 LDCONST R11 K6 0x7C200600, // 001A CALL R8 3 0x80041000, // 001B RET 1 R8 - 0x7002006F, // 001C JMP #008D + 0x7002005C, // 001C JMP #007A 0x54220006, // 001D LDINT R8 7 0x1C200C08, // 001E EQ R8 R6 R8 0x78220006, // 001F JMPF R8 #0027 @@ -285,7 +284,7 @@ be_local_closure(Matter_Plugin_Shutter_read_attribute, /* name */ 0x002E140B, // 0023 ADD R11 K10 R11 0x7C200600, // 0024 CALL R8 3 0x80041000, // 0025 RET 1 R8 - 0x70020065, // 0026 JMP #008D + 0x70020052, // 0026 JMP #007A 0x5422000C, // 0027 LDINT R8 13 0x1C200C08, // 0028 EQ R8 R6 R8 0x78220005, // 0029 JMPF R8 #0030 @@ -294,7 +293,7 @@ be_local_closure(Matter_Plugin_Shutter_read_attribute, /* name */ 0x542E00FE, // 002C LDINT R11 255 0x7C200600, // 002D CALL R8 3 0x80041000, // 002E RET 1 R8 - 0x7002005C, // 002F JMP #008D + 0x70020049, // 002F JMP #007A 0x5422000D, // 0030 LDINT R8 14 0x1C200C08, // 0031 EQ R8 R6 R8 0x78220013, // 0032 JMPF R8 #0047 @@ -317,7 +316,7 @@ be_local_closure(Matter_Plugin_Shutter_read_attribute, /* name */ 0x5C2C0E00, // 0043 MOVE R11 R7 0x7C200600, // 0044 CALL R8 3 0x80041000, // 0045 RET 1 R8 - 0x70020045, // 0046 JMP #008D + 0x70020032, // 0046 JMP #007A 0x54220009, // 0047 LDINT R8 10 0x1C200C08, // 0048 EQ R8 R6 R8 0x78220010, // 0049 JMPF R8 #005B @@ -337,7 +336,7 @@ be_local_closure(Matter_Plugin_Shutter_read_attribute, /* name */ 0x5C301000, // 0057 MOVE R12 R8 0x7C240600, // 0058 CALL R9 3 0x80041200, // 0059 RET 1 R9 - 0x70020031, // 005A JMP #008D + 0x7002001E, // 005A JMP #007A 0x5422000A, // 005B LDINT R8 11 0x1C200C08, // 005C EQ R8 R6 R8 0x78220013, // 005D JMPF R8 #0072 @@ -360,45 +359,24 @@ be_local_closure(Matter_Plugin_Shutter_read_attribute, /* name */ 0x5C2C0E00, // 006E MOVE R11 R7 0x7C200600, // 006F CALL R8 3 0x80041000, // 0070 RET 1 R8 - 0x7002001A, // 0071 JMP #008D + 0x70020007, // 0071 JMP #007A 0x54220016, // 0072 LDINT R8 23 0x1C200C08, // 0073 EQ R8 R6 R8 - 0x78220005, // 0074 JMPF R8 #007B + 0x78220004, // 0074 JMPF R8 #007A 0x8C200707, // 0075 GETMET R8 R3 K7 0x88280908, // 0076 GETMBR R10 R4 K8 0x582C0006, // 0077 LDCONST R11 K6 0x7C200600, // 0078 CALL R8 3 0x80041000, // 0079 RET 1 R8 - 0x70020011, // 007A JMP #008D - 0x5422FFFB, // 007B LDINT R8 65532 - 0x1C200C08, // 007C EQ R8 R6 R8 - 0x78220006, // 007D JMPF R8 #0085 - 0x8C200707, // 007E GETMET R8 R3 K7 - 0x88280910, // 007F GETMBR R10 R4 K16 - 0x542E0003, // 0080 LDINT R11 4 - 0x002E140B, // 0081 ADD R11 K10 R11 - 0x7C200600, // 0082 CALL R8 3 - 0x80041000, // 0083 RET 1 R8 - 0x70020007, // 0084 JMP #008D - 0x5422FFFC, // 0085 LDINT R8 65533 - 0x1C200C08, // 0086 EQ R8 R6 R8 - 0x78220004, // 0087 JMPF R8 #008D - 0x8C200707, // 0088 GETMET R8 R3 K7 - 0x88280910, // 0089 GETMBR R10 R4 K16 - 0x542E0004, // 008A LDINT R11 5 - 0x7C200600, // 008B CALL R8 3 - 0x80041000, // 008C RET 1 R8 - 0x70020008, // 008D JMP #0097 - 0x60200003, // 008E GETGBL R8 G3 - 0x5C240000, // 008F MOVE R9 R0 - 0x7C200200, // 0090 CALL R8 1 - 0x8C201111, // 0091 GETMET R8 R8 K17 - 0x5C280200, // 0092 MOVE R10 R1 - 0x5C2C0400, // 0093 MOVE R11 R2 - 0x5C300600, // 0094 MOVE R12 R3 - 0x7C200800, // 0095 CALL R8 4 - 0x80041000, // 0096 RET 1 R8 - 0x80000000, // 0097 RET 0 + 0x60200003, // 007A GETGBL R8 G3 + 0x5C240000, // 007B MOVE R9 R0 + 0x7C200200, // 007C CALL R8 1 + 0x8C201110, // 007D GETMET R8 R8 K16 + 0x5C280200, // 007E MOVE R10 R1 + 0x5C2C0400, // 007F MOVE R11 R2 + 0x5C300600, // 0080 MOVE R12 R3 + 0x7C200800, // 0081 CALL R8 4 + 0x80041000, // 0082 RET 1 R8 }) ) ); @@ -670,7 +648,7 @@ be_local_class(Matter_Plugin_Shutter, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(258, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(10, + be_const_list( * be_nested_list(14, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(5), @@ -680,11 +658,15 @@ be_local_class(Matter_Plugin_Shutter, be_const_int(13), be_const_int(14), be_const_int(23), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -692,11 +674,15 @@ be_local_class(Matter_Plugin_Shutter, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -704,29 +690,47 @@ be_local_class(Matter_Plugin_Shutter, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Light0.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Light0.h index 4e2bedd20..e4a9b75dd 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Light0.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Light0.h @@ -120,7 +120,7 @@ be_local_closure(Matter_Plugin_Bridge_Light0_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[11]) { /* constants */ + ( &(const bvalue[10]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -130,57 +130,36 @@ be_local_closure(Matter_Plugin_Bridge_Light0_read_attribute, /* name */ /* K6 */ be_nested_str_weak(set), /* K7 */ be_nested_str_weak(BOOL), /* K8 */ be_nested_str_weak(shadow_onoff), - /* K9 */ be_nested_str_weak(U4), - /* K10 */ be_nested_str_weak(read_attribute), + /* K9 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[45]) { /* code */ + ( &(const binstruction[25]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0005, // 0004 LDINT R7 6 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E001B, // 0006 JMPF R7 #0023 + 0x781E0008, // 0006 JMPF R7 #0010 0x8C1C0104, // 0007 GETMET R7 R0 K4 0x7C1C0200, // 0008 CALL R7 1 0x1C1C0D05, // 0009 EQ R7 R6 K5 - 0x781E0005, // 000A JMPF R7 #0011 + 0x781E0004, // 000A JMPF R7 #0010 0x8C1C0706, // 000B GETMET R7 R3 K6 0x88240907, // 000C GETMBR R9 R4 K7 0x88280108, // 000D GETMBR R10 R0 K8 0x7C1C0600, // 000E CALL R7 3 0x80040E00, // 000F RET 1 R7 - 0x70020010, // 0010 JMP #0022 - 0x541EFFFB, // 0011 LDINT R7 65532 - 0x1C1C0C07, // 0012 EQ R7 R6 R7 - 0x781E0005, // 0013 JMPF R7 #001A - 0x8C1C0706, // 0014 GETMET R7 R3 K6 - 0x88240909, // 0015 GETMBR R9 R4 K9 - 0x58280005, // 0016 LDCONST R10 K5 - 0x7C1C0600, // 0017 CALL R7 3 + 0x601C0003, // 0010 GETGBL R7 G3 + 0x5C200000, // 0011 MOVE R8 R0 + 0x7C1C0200, // 0012 CALL R7 1 + 0x8C1C0F09, // 0013 GETMET R7 R7 K9 + 0x5C240200, // 0014 MOVE R9 R1 + 0x5C280400, // 0015 MOVE R10 R2 + 0x5C2C0600, // 0016 MOVE R11 R3 + 0x7C1C0800, // 0017 CALL R7 4 0x80040E00, // 0018 RET 1 R7 - 0x70020007, // 0019 JMP #0022 - 0x541EFFFC, // 001A LDINT R7 65533 - 0x1C1C0C07, // 001B EQ R7 R6 R7 - 0x781E0004, // 001C JMPF R7 #0022 - 0x8C1C0706, // 001D GETMET R7 R3 K6 - 0x88240909, // 001E GETMBR R9 R4 K9 - 0x542A0003, // 001F LDINT R10 4 - 0x7C1C0600, // 0020 CALL R7 3 - 0x80040E00, // 0021 RET 1 R7 - 0x70020008, // 0022 JMP #002C - 0x601C0003, // 0023 GETGBL R7 G3 - 0x5C200000, // 0024 MOVE R8 R0 - 0x7C1C0200, // 0025 CALL R7 1 - 0x8C1C0F0A, // 0026 GETMET R7 R7 K10 - 0x5C240200, // 0027 MOVE R9 R1 - 0x5C280400, // 0028 MOVE R10 R2 - 0x5C2C0600, // 0029 MOVE R11 R3 - 0x7C1C0800, // 002A CALL R7 4 - 0x80040E00, // 002B RET 1 R7 - 0x80000000, // 002C RET 0 }) ) ); @@ -494,14 +473,18 @@ be_local_class(Matter_Plugin_Bridge_Light0, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(6, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -509,11 +492,15 @@ be_local_class(Matter_Plugin_Bridge_Light0, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -521,29 +508,47 @@ be_local_class(Matter_Plugin_Bridge_Light0, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Contact.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Contact.h index 85a650a73..e39b2ffa0 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Contact.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Contact.h @@ -209,7 +209,7 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Contact_read_attribute, /* name * 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[12]) { /* constants */ + ( &(const bvalue[10]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -219,22 +219,20 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Contact_read_attribute, /* name * /* K6 */ be_nested_str_weak(set), /* K7 */ be_nested_str_weak(BOOL), /* K8 */ be_nested_str_weak(NULL), - /* K9 */ be_nested_str_weak(U4), - /* K10 */ be_const_int(1), - /* K11 */ be_nested_str_weak(read_attribute), + /* K9 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[53]) { /* code */ + ( &(const binstruction[33]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0044, // 0004 LDINT R7 69 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0023, // 0006 JMPF R7 #002B + 0x781E0010, // 0006 JMPF R7 #0018 0x1C1C0D04, // 0007 EQ R7 R6 K4 - 0x781E000F, // 0008 JMPF R7 #0019 + 0x781E000E, // 0008 JMPF R7 #0018 0x881C0105, // 0009 GETMBR R7 R0 K5 0x4C200000, // 000A LDNIL R8 0x201C0E08, // 000B NE R7 R7 R8 @@ -250,35 +248,15 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Contact_read_attribute, /* name * 0x4C280000, // 0015 LDNIL R10 0x7C1C0600, // 0016 CALL R7 3 0x80040E00, // 0017 RET 1 R7 - 0x70020010, // 0018 JMP #002A - 0x541EFFFB, // 0019 LDINT R7 65532 - 0x1C1C0C07, // 001A EQ R7 R6 R7 - 0x781E0005, // 001B JMPF R7 #0022 - 0x8C1C0706, // 001C GETMET R7 R3 K6 - 0x88240909, // 001D GETMBR R9 R4 K9 - 0x58280004, // 001E LDCONST R10 K4 - 0x7C1C0600, // 001F CALL R7 3 + 0x601C0003, // 0018 GETGBL R7 G3 + 0x5C200000, // 0019 MOVE R8 R0 + 0x7C1C0200, // 001A CALL R7 1 + 0x8C1C0F09, // 001B GETMET R7 R7 K9 + 0x5C240200, // 001C MOVE R9 R1 + 0x5C280400, // 001D MOVE R10 R2 + 0x5C2C0600, // 001E MOVE R11 R3 + 0x7C1C0800, // 001F CALL R7 4 0x80040E00, // 0020 RET 1 R7 - 0x70020007, // 0021 JMP #002A - 0x541EFFFC, // 0022 LDINT R7 65533 - 0x1C1C0C07, // 0023 EQ R7 R6 R7 - 0x781E0004, // 0024 JMPF R7 #002A - 0x8C1C0706, // 0025 GETMET R7 R3 K6 - 0x88240909, // 0026 GETMBR R9 R4 K9 - 0x5828000A, // 0027 LDCONST R10 K10 - 0x7C1C0600, // 0028 CALL R7 3 - 0x80040E00, // 0029 RET 1 R7 - 0x70020008, // 002A JMP #0034 - 0x601C0003, // 002B GETGBL R7 G3 - 0x5C200000, // 002C MOVE R8 R0 - 0x7C1C0200, // 002D CALL R7 1 - 0x8C1C0F0B, // 002E GETMET R7 R7 K11 - 0x5C240200, // 002F MOVE R9 R1 - 0x5C280400, // 0030 MOVE R10 R2 - 0x5C2C0600, // 0031 MOVE R11 R3 - 0x7C1C0800, // 0032 CALL R7 4 - 0x80040E00, // 0033 RET 1 R7 - 0x80000000, // 0034 RET 0 }) ) ); @@ -352,7 +330,7 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Contact, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -360,19 +338,27 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Contact, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(3, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -380,28 +366,46 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Contact, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(69, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Occupancy.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Occupancy.h index 8961d1881..20fbfe3b6 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Occupancy.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Bridge_Sensor_Occupancy.h @@ -209,7 +209,7 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Occupancy_read_attribute, /* name 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ + ( &(const bvalue[13]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -222,19 +222,18 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Occupancy_read_attribute, /* name /* K9 */ be_const_int(1), /* K10 */ be_const_int(3), /* K11 */ be_const_int(2), - /* K12 */ be_nested_str_weak(U4), - /* K13 */ be_nested_str_weak(read_attribute), + /* K12 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[69]) { /* code */ + ( &(const binstruction[49]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0405, // 0004 LDINT R7 1030 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0033, // 0006 JMPF R7 #003B + 0x781E0020, // 0006 JMPF R7 #0028 0x1C1C0D04, // 0007 EQ R7 R6 K4 0x781E000F, // 0008 JMPF R7 #0019 0x881C0105, // 0009 GETMBR R7 R0 K5 @@ -252,7 +251,7 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Occupancy_read_attribute, /* name 0x4C280000, // 0015 LDNIL R10 0x7C1C0600, // 0016 CALL R7 3 0x80040E00, // 0017 RET 1 R7 - 0x70020020, // 0018 JMP #003A + 0x7002000E, // 0018 JMP #0028 0x1C1C0D09, // 0019 EQ R7 R6 K9 0x781E0005, // 001A JMPF R7 #0021 0x8C1C0706, // 001B GETMET R7 R3 K6 @@ -260,43 +259,23 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Occupancy_read_attribute, /* name 0x5828000A, // 001D LDCONST R10 K10 0x7C1C0600, // 001E CALL R7 3 0x80040E00, // 001F RET 1 R7 - 0x70020018, // 0020 JMP #003A + 0x70020006, // 0020 JMP #0028 0x1C1C0D0B, // 0021 EQ R7 R6 K11 - 0x781E0005, // 0022 JMPF R7 #0029 + 0x781E0004, // 0022 JMPF R7 #0028 0x8C1C0706, // 0023 GETMET R7 R3 K6 0x88240907, // 0024 GETMBR R9 R4 K7 0x58280004, // 0025 LDCONST R10 K4 0x7C1C0600, // 0026 CALL R7 3 0x80040E00, // 0027 RET 1 R7 - 0x70020010, // 0028 JMP #003A - 0x541EFFFB, // 0029 LDINT R7 65532 - 0x1C1C0C07, // 002A EQ R7 R6 R7 - 0x781E0005, // 002B JMPF R7 #0032 - 0x8C1C0706, // 002C GETMET R7 R3 K6 - 0x8824090C, // 002D GETMBR R9 R4 K12 - 0x58280004, // 002E LDCONST R10 K4 - 0x7C1C0600, // 002F CALL R7 3 + 0x601C0003, // 0028 GETGBL R7 G3 + 0x5C200000, // 0029 MOVE R8 R0 + 0x7C1C0200, // 002A CALL R7 1 + 0x8C1C0F0C, // 002B GETMET R7 R7 K12 + 0x5C240200, // 002C MOVE R9 R1 + 0x5C280400, // 002D MOVE R10 R2 + 0x5C2C0600, // 002E MOVE R11 R3 + 0x7C1C0800, // 002F CALL R7 4 0x80040E00, // 0030 RET 1 R7 - 0x70020007, // 0031 JMP #003A - 0x541EFFFC, // 0032 LDINT R7 65533 - 0x1C1C0C07, // 0033 EQ R7 R6 R7 - 0x781E0004, // 0034 JMPF R7 #003A - 0x8C1C0706, // 0035 GETMET R7 R3 K6 - 0x8824090C, // 0036 GETMBR R9 R4 K12 - 0x5828000A, // 0037 LDCONST R10 K10 - 0x7C1C0600, // 0038 CALL R7 3 - 0x80040E00, // 0039 RET 1 R7 - 0x70020008, // 003A JMP #0044 - 0x601C0003, // 003B GETGBL R7 G3 - 0x5C200000, // 003C MOVE R8 R0 - 0x7C1C0200, // 003D CALL R7 1 - 0x8C1C0F0D, // 003E GETMET R7 R7 K13 - 0x5C240200, // 003F MOVE R9 R1 - 0x5C280400, // 0040 MOVE R10 R2 - 0x5C2C0600, // 0041 MOVE R11 R3 - 0x7C1C0800, // 0042 CALL R7 4 - 0x80040E00, // 0043 RET 1 R7 - 0x80000000, // 0044 RET 0 }) ) ); @@ -373,7 +352,7 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Occupancy, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -381,18 +360,26 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Occupancy, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -400,31 +387,49 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Occupancy, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(1030, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(5, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light2.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light2.h index 78bad5ab1..f52fc8830 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light2.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light2.h @@ -352,14 +352,14 @@ be_local_closure(Matter_Plugin_Light2_read_attribute, /* name */ }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[82]) { /* code */ + ( &(const binstruction[71]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E02FF, // 0004 LDINT R7 768 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0040, // 0006 JMPF R7 #0048 + 0x781E0036, // 0006 JMPF R7 #003E 0x8C1C0104, // 0007 GETMET R7 R0 K4 0x7C1C0200, // 0008 CALL R7 1 0x541E0006, // 0009 LDINT R7 7 @@ -370,7 +370,7 @@ be_local_closure(Matter_Plugin_Light2_read_attribute, /* name */ 0x88280107, // 000E GETMBR R10 R0 K7 0x7C1C0600, // 000F CALL R7 3 0x80040E00, // 0010 RET 1 R7 - 0x70020034, // 0011 JMP #0047 + 0x7002002B, // 0011 JMP #003E 0x541E0007, // 0012 LDINT R7 8 0x1C1C0C07, // 0013 EQ R7 R6 R7 0x781E0005, // 0014 JMPF R7 #001B @@ -379,7 +379,7 @@ be_local_closure(Matter_Plugin_Light2_read_attribute, /* name */ 0x58280008, // 0017 LDCONST R10 K8 0x7C1C0600, // 0018 CALL R7 3 0x80040E00, // 0019 RET 1 R7 - 0x7002002B, // 001A JMP #0047 + 0x70020022, // 001A JMP #003E 0x541E000E, // 001B LDINT R7 15 0x1C1C0C07, // 001C EQ R7 R6 R7 0x781E0005, // 001D JMPF R7 #0024 @@ -388,7 +388,7 @@ be_local_closure(Matter_Plugin_Light2_read_attribute, /* name */ 0x58280009, // 0020 LDCONST R10 K9 0x7C1C0600, // 0021 CALL R7 3 0x80040E00, // 0022 RET 1 R7 - 0x70020022, // 0023 JMP #0047 + 0x70020019, // 0023 JMP #003E 0x541E400A, // 0024 LDINT R7 16395 0x1C1C0C07, // 0025 EQ R7 R6 R7 0x781E0005, // 0026 JMPF R7 #002D @@ -397,7 +397,7 @@ be_local_closure(Matter_Plugin_Light2_read_attribute, /* name */ 0x8828010A, // 0029 GETMBR R10 R0 K10 0x7C1C0600, // 002A CALL R7 3 0x80040E00, // 002B RET 1 R7 - 0x70020019, // 002C JMP #0047 + 0x70020010, // 002C JMP #003E 0x541E400B, // 002D LDINT R7 16396 0x1C1C0C07, // 002E EQ R7 R6 R7 0x781E0005, // 002F JMPF R7 #0036 @@ -406,35 +406,24 @@ be_local_closure(Matter_Plugin_Light2_read_attribute, /* name */ 0x8828010B, // 0032 GETMBR R10 R0 K11 0x7C1C0600, // 0033 CALL R7 3 0x80040E00, // 0034 RET 1 R7 - 0x70020010, // 0035 JMP #0047 + 0x70020007, // 0035 JMP #003E 0x541EFFFB, // 0036 LDINT R7 65532 0x1C1C0C07, // 0037 EQ R7 R6 R7 - 0x781E0005, // 0038 JMPF R7 #003F + 0x781E0004, // 0038 JMPF R7 #003E 0x8C1C0705, // 0039 GETMET R7 R3 K5 0x8824090C, // 003A GETMBR R9 R4 K12 0x542A000F, // 003B LDINT R10 16 0x7C1C0600, // 003C CALL R7 3 0x80040E00, // 003D RET 1 R7 - 0x70020007, // 003E JMP #0047 - 0x541EFFFC, // 003F LDINT R7 65533 - 0x1C1C0C07, // 0040 EQ R7 R6 R7 - 0x781E0004, // 0041 JMPF R7 #0047 - 0x8C1C0705, // 0042 GETMET R7 R3 K5 - 0x8824090C, // 0043 GETMBR R9 R4 K12 - 0x542A0004, // 0044 LDINT R10 5 - 0x7C1C0600, // 0045 CALL R7 3 + 0x601C0003, // 003E GETGBL R7 G3 + 0x5C200000, // 003F MOVE R8 R0 + 0x7C1C0200, // 0040 CALL R7 1 + 0x8C1C0F0D, // 0041 GETMET R7 R7 K13 + 0x5C240200, // 0042 MOVE R9 R1 + 0x5C280400, // 0043 MOVE R10 R2 + 0x5C2C0600, // 0044 MOVE R11 R3 + 0x7C1C0800, // 0045 CALL R7 4 0x80040E00, // 0046 RET 1 R7 - 0x70020008, // 0047 JMP #0051 - 0x601C0003, // 0048 GETGBL R7 G3 - 0x5C200000, // 0049 MOVE R8 R0 - 0x7C1C0200, // 004A CALL R7 1 - 0x8C1C0F0D, // 004B GETMET R7 R7 K13 - 0x5C240200, // 004C MOVE R9 R1 - 0x5C280400, // 004D MOVE R10 R2 - 0x5C2C0600, // 004E MOVE R11 R3 - 0x7C1C0800, // 004F CALL R7 4 - 0x80040E00, // 0050 RET 1 R7 - 0x80000000, // 0051 RET 0 }) ) ); @@ -517,18 +506,22 @@ be_local_class(Matter_Plugin_Light2, be_const_map( * be_nested_map(8, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(8, 7), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(11, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(2), be_const_int(3), be_const_int(15), be_const_int(17), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -536,34 +529,52 @@ be_local_class(Matter_Plugin_Light2, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(29, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(3, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(5, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -571,24 +582,36 @@ be_local_class(Matter_Plugin_Light2, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(6, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(768, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(11, ( (struct bvalue*) &(const bvalue[]) { be_const_int(7), be_const_int(8), be_const_int(15), be_const_int(16395), be_const_int(16396), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light3.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light3.h index 1a0b7a981..db81f7d67 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light3.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Light3.h @@ -542,14 +542,14 @@ be_local_closure(Matter_Plugin_Light3_read_attribute, /* name */ }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[107]) { /* code */ + ( &(const binstruction[96]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E02FF, // 0004 LDINT R7 768 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0059, // 0006 JMPF R7 #0061 + 0x781E004F, // 0006 JMPF R7 #0057 0x8C1C0104, // 0007 GETMET R7 R0 K4 0x7C1C0200, // 0008 CALL R7 1 0x1C1C0D05, // 0009 EQ R7 R6 K5 @@ -559,7 +559,7 @@ be_local_closure(Matter_Plugin_Light3_read_attribute, /* name */ 0x88280108, // 000D GETMBR R10 R0 K8 0x7C1C0600, // 000E CALL R7 3 0x80040E00, // 000F RET 1 R7 - 0x7002004E, // 0010 JMP #0060 + 0x70020045, // 0010 JMP #0057 0x1C1C0D09, // 0011 EQ R7 R6 K9 0x781E0005, // 0012 JMPF R7 #0019 0x8C1C0706, // 0013 GETMET R7 R3 K6 @@ -567,7 +567,7 @@ be_local_closure(Matter_Plugin_Light3_read_attribute, /* name */ 0x8828010A, // 0015 GETMBR R10 R0 K10 0x7C1C0600, // 0016 CALL R7 3 0x80040E00, // 0017 RET 1 R7 - 0x70020046, // 0018 JMP #0060 + 0x7002003D, // 0018 JMP #0057 0x541E0006, // 0019 LDINT R7 7 0x1C1C0C07, // 001A EQ R7 R6 R7 0x781E0005, // 001B JMPF R7 #0022 @@ -576,7 +576,7 @@ be_local_closure(Matter_Plugin_Light3_read_attribute, /* name */ 0x58280005, // 001E LDCONST R10 K5 0x7C1C0600, // 001F CALL R7 3 0x80040E00, // 0020 RET 1 R7 - 0x7002003D, // 0021 JMP #0060 + 0x70020034, // 0021 JMP #0057 0x541E0007, // 0022 LDINT R7 8 0x1C1C0C07, // 0023 EQ R7 R6 R7 0x781E0005, // 0024 JMPF R7 #002B @@ -585,7 +585,7 @@ be_local_closure(Matter_Plugin_Light3_read_attribute, /* name */ 0x58280005, // 0027 LDCONST R10 K5 0x7C1C0600, // 0028 CALL R7 3 0x80040E00, // 0029 RET 1 R7 - 0x70020034, // 002A JMP #0060 + 0x7002002B, // 002A JMP #0057 0x541E000E, // 002B LDINT R7 15 0x1C1C0C07, // 002C EQ R7 R6 R7 0x781E0005, // 002D JMPF R7 #0034 @@ -594,7 +594,7 @@ be_local_closure(Matter_Plugin_Light3_read_attribute, /* name */ 0x58280005, // 0030 LDCONST R10 K5 0x7C1C0600, // 0031 CALL R7 3 0x80040E00, // 0032 RET 1 R7 - 0x7002002B, // 0033 JMP #0060 + 0x70020022, // 0033 JMP #0057 0x541E4000, // 0034 LDINT R7 16385 0x1C1C0C07, // 0035 EQ R7 R6 R7 0x781E0005, // 0036 JMPF R7 #003D @@ -603,7 +603,7 @@ be_local_closure(Matter_Plugin_Light3_read_attribute, /* name */ 0x58280005, // 0039 LDCONST R10 K5 0x7C1C0600, // 003A CALL R7 3 0x80040E00, // 003B RET 1 R7 - 0x70020022, // 003C JMP #0060 + 0x70020019, // 003C JMP #0057 0x541E4009, // 003D LDINT R7 16394 0x1C1C0C07, // 003E EQ R7 R6 R7 0x781E0005, // 003F JMPF R7 #0046 @@ -612,7 +612,7 @@ be_local_closure(Matter_Plugin_Light3_read_attribute, /* name */ 0x58280009, // 0042 LDCONST R10 K9 0x7C1C0600, // 0043 CALL R7 3 0x80040E00, // 0044 RET 1 R7 - 0x70020019, // 0045 JMP #0060 + 0x70020010, // 0045 JMP #0057 0x541E000F, // 0046 LDINT R7 16 0x1C1C0C07, // 0047 EQ R7 R6 R7 0x781E0005, // 0048 JMPF R7 #004F @@ -621,35 +621,24 @@ be_local_closure(Matter_Plugin_Light3_read_attribute, /* name */ 0x58280005, // 004B LDCONST R10 K5 0x7C1C0600, // 004C CALL R7 3 0x80040E00, // 004D RET 1 R7 - 0x70020010, // 004E JMP #0060 + 0x70020007, // 004E JMP #0057 0x541EFFFB, // 004F LDINT R7 65532 0x1C1C0C07, // 0050 EQ R7 R6 R7 - 0x781E0005, // 0051 JMPF R7 #0058 + 0x781E0004, // 0051 JMPF R7 #0057 0x8C1C0706, // 0052 GETMET R7 R3 K6 0x8824090B, // 0053 GETMBR R9 R4 K11 0x58280009, // 0054 LDCONST R10 K9 0x7C1C0600, // 0055 CALL R7 3 0x80040E00, // 0056 RET 1 R7 - 0x70020007, // 0057 JMP #0060 - 0x541EFFFC, // 0058 LDINT R7 65533 - 0x1C1C0C07, // 0059 EQ R7 R6 R7 - 0x781E0004, // 005A JMPF R7 #0060 - 0x8C1C0706, // 005B GETMET R7 R3 K6 - 0x8824090B, // 005C GETMBR R9 R4 K11 - 0x542A0004, // 005D LDINT R10 5 - 0x7C1C0600, // 005E CALL R7 3 + 0x601C0003, // 0057 GETGBL R7 G3 + 0x5C200000, // 0058 MOVE R8 R0 + 0x7C1C0200, // 0059 CALL R7 1 + 0x8C1C0F0C, // 005A GETMET R7 R7 K12 + 0x5C240200, // 005B MOVE R9 R1 + 0x5C280400, // 005C MOVE R10 R2 + 0x5C2C0600, // 005D MOVE R11 R3 + 0x7C1C0800, // 005E CALL R7 4 0x80040E00, // 005F RET 1 R7 - 0x70020008, // 0060 JMP #006A - 0x601C0003, // 0061 GETGBL R7 G3 - 0x5C200000, // 0062 MOVE R8 R0 - 0x7C1C0200, // 0063 CALL R7 1 - 0x8C1C0F0C, // 0064 GETMET R7 R7 K12 - 0x5C240200, // 0065 MOVE R9 R1 - 0x5C280400, // 0066 MOVE R10 R2 - 0x5C2C0600, // 0067 MOVE R11 R3 - 0x7C1C0800, // 0068 CALL R7 4 - 0x80040E00, // 0069 RET 1 R7 - 0x80000000, // 006A RET 0 }) ) ); @@ -679,18 +668,22 @@ be_local_class(Matter_Plugin_Light3, be_const_map( * be_nested_map(8, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(8, 7), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(11, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(2), be_const_int(3), be_const_int(15), be_const_int(17), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -698,34 +691,52 @@ be_local_class(Matter_Plugin_Light3, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(29, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(3, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(5, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -733,18 +744,26 @@ be_local_class(Matter_Plugin_Light3, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(6, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(768, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(9, + be_const_list( * be_nested_list(13, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -753,6 +772,10 @@ be_local_class(Matter_Plugin_Light3, be_const_int(15), be_const_int(16385), be_const_int(16394), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Flow.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Flow.h index 8510fa70f..77de122bf 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Flow.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Flow.h @@ -50,7 +50,7 @@ be_local_closure(Matter_Plugin_Sensor_Flow_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ + ( &(const bvalue[12]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -62,20 +62,18 @@ be_local_closure(Matter_Plugin_Sensor_Flow_read_attribute, /* name */ /* K8 */ be_nested_str_weak(NULL), /* K9 */ be_const_int(1), /* K10 */ be_const_int(2), - /* K11 */ be_nested_str_weak(U4), - /* K12 */ be_const_int(3), - /* K13 */ be_nested_str_weak(read_attribute), + /* K11 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[71]) { /* code */ + ( &(const binstruction[51]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0403, // 0004 LDINT R7 1028 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0035, // 0006 JMPF R7 #003D + 0x781E0022, // 0006 JMPF R7 #002A 0x1C1C0D04, // 0007 EQ R7 R6 K4 0x781E0011, // 0008 JMPF R7 #001B 0x881C0105, // 0009 GETMBR R7 R0 K5 @@ -95,7 +93,7 @@ be_local_closure(Matter_Plugin_Sensor_Flow_read_attribute, /* name */ 0x4C280000, // 0017 LDNIL R10 0x7C1C0600, // 0018 CALL R7 3 0x80040E00, // 0019 RET 1 R7 - 0x70020020, // 001A JMP #003C + 0x7002000E, // 001A JMP #002A 0x1C1C0D09, // 001B EQ R7 R6 K9 0x781E0005, // 001C JMPF R7 #0023 0x8C1C0706, // 001D GETMET R7 R3 K6 @@ -103,43 +101,23 @@ be_local_closure(Matter_Plugin_Sensor_Flow_read_attribute, /* name */ 0x58280004, // 001F LDCONST R10 K4 0x7C1C0600, // 0020 CALL R7 3 0x80040E00, // 0021 RET 1 R7 - 0x70020018, // 0022 JMP #003C + 0x70020006, // 0022 JMP #002A 0x1C1C0D0A, // 0023 EQ R7 R6 K10 - 0x781E0005, // 0024 JMPF R7 #002B + 0x781E0004, // 0024 JMPF R7 #002A 0x8C1C0706, // 0025 GETMET R7 R3 K6 0x88240907, // 0026 GETMBR R9 R4 K7 0x542AFFFD, // 0027 LDINT R10 65534 0x7C1C0600, // 0028 CALL R7 3 0x80040E00, // 0029 RET 1 R7 - 0x70020010, // 002A JMP #003C - 0x541EFFFB, // 002B LDINT R7 65532 - 0x1C1C0C07, // 002C EQ R7 R6 R7 - 0x781E0005, // 002D JMPF R7 #0034 - 0x8C1C0706, // 002E GETMET R7 R3 K6 - 0x8824090B, // 002F GETMBR R9 R4 K11 - 0x58280004, // 0030 LDCONST R10 K4 - 0x7C1C0600, // 0031 CALL R7 3 + 0x601C0003, // 002A GETGBL R7 G3 + 0x5C200000, // 002B MOVE R8 R0 + 0x7C1C0200, // 002C CALL R7 1 + 0x8C1C0F0B, // 002D GETMET R7 R7 K11 + 0x5C240200, // 002E MOVE R9 R1 + 0x5C280400, // 002F MOVE R10 R2 + 0x5C2C0600, // 0030 MOVE R11 R3 + 0x7C1C0800, // 0031 CALL R7 4 0x80040E00, // 0032 RET 1 R7 - 0x70020007, // 0033 JMP #003C - 0x541EFFFC, // 0034 LDINT R7 65533 - 0x1C1C0C07, // 0035 EQ R7 R6 R7 - 0x781E0004, // 0036 JMPF R7 #003C - 0x8C1C0706, // 0037 GETMET R7 R3 K6 - 0x8824090B, // 0038 GETMBR R9 R4 K11 - 0x5828000C, // 0039 LDCONST R10 K12 - 0x7C1C0600, // 003A CALL R7 3 - 0x80040E00, // 003B RET 1 R7 - 0x70020008, // 003C JMP #0046 - 0x601C0003, // 003D GETGBL R7 G3 - 0x5C200000, // 003E MOVE R8 R0 - 0x7C1C0200, // 003F CALL R7 1 - 0x8C1C0F0D, // 0040 GETMET R7 R7 K13 - 0x5C240200, // 0041 MOVE R9 R1 - 0x5C280400, // 0042 MOVE R10 R2 - 0x5C2C0600, // 0043 MOVE R11 R3 - 0x7C1C0800, // 0044 CALL R7 4 - 0x80040E00, // 0045 RET 1 R7 - 0x80000000, // 0046 RET 0 }) ) ); @@ -207,7 +185,7 @@ be_local_class(Matter_Plugin_Sensor_Flow, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -215,11 +193,15 @@ be_local_class(Matter_Plugin_Sensor_Flow, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -227,38 +209,60 @@ be_local_class(Matter_Plugin_Sensor_Flow, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(1028, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(5, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Humidity.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Humidity.h index 4a8ad5775..c0472c631 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Humidity.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Humidity.h @@ -50,7 +50,7 @@ be_local_closure(Matter_Plugin_Sensor_Humidity_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ + ( &(const bvalue[12]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -62,20 +62,18 @@ be_local_closure(Matter_Plugin_Sensor_Humidity_read_attribute, /* name */ /* K8 */ be_nested_str_weak(NULL), /* K9 */ be_const_int(1), /* K10 */ be_const_int(2), - /* K11 */ be_nested_str_weak(U4), - /* K12 */ be_const_int(3), - /* K13 */ be_nested_str_weak(read_attribute), + /* K11 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[71]) { /* code */ + ( &(const binstruction[51]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0404, // 0004 LDINT R7 1029 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0035, // 0006 JMPF R7 #003D + 0x781E0022, // 0006 JMPF R7 #002A 0x1C1C0D04, // 0007 EQ R7 R6 K4 0x781E0011, // 0008 JMPF R7 #001B 0x881C0105, // 0009 GETMBR R7 R0 K5 @@ -95,7 +93,7 @@ be_local_closure(Matter_Plugin_Sensor_Humidity_read_attribute, /* name */ 0x4C280000, // 0017 LDNIL R10 0x7C1C0600, // 0018 CALL R7 3 0x80040E00, // 0019 RET 1 R7 - 0x70020020, // 001A JMP #003C + 0x7002000E, // 001A JMP #002A 0x1C1C0D09, // 001B EQ R7 R6 K9 0x781E0005, // 001C JMPF R7 #0023 0x8C1C0706, // 001D GETMET R7 R3 K6 @@ -103,43 +101,23 @@ be_local_closure(Matter_Plugin_Sensor_Humidity_read_attribute, /* name */ 0x542A01F3, // 001F LDINT R10 500 0x7C1C0600, // 0020 CALL R7 3 0x80040E00, // 0021 RET 1 R7 - 0x70020018, // 0022 JMP #003C + 0x70020006, // 0022 JMP #002A 0x1C1C0D0A, // 0023 EQ R7 R6 K10 - 0x781E0005, // 0024 JMPF R7 #002B + 0x781E0004, // 0024 JMPF R7 #002A 0x8C1C0706, // 0025 GETMET R7 R3 K6 0x88240907, // 0026 GETMBR R9 R4 K7 0x542A270F, // 0027 LDINT R10 10000 0x7C1C0600, // 0028 CALL R7 3 0x80040E00, // 0029 RET 1 R7 - 0x70020010, // 002A JMP #003C - 0x541EFFFB, // 002B LDINT R7 65532 - 0x1C1C0C07, // 002C EQ R7 R6 R7 - 0x781E0005, // 002D JMPF R7 #0034 - 0x8C1C0706, // 002E GETMET R7 R3 K6 - 0x8824090B, // 002F GETMBR R9 R4 K11 - 0x58280004, // 0030 LDCONST R10 K4 - 0x7C1C0600, // 0031 CALL R7 3 + 0x601C0003, // 002A GETGBL R7 G3 + 0x5C200000, // 002B MOVE R8 R0 + 0x7C1C0200, // 002C CALL R7 1 + 0x8C1C0F0B, // 002D GETMET R7 R7 K11 + 0x5C240200, // 002E MOVE R9 R1 + 0x5C280400, // 002F MOVE R10 R2 + 0x5C2C0600, // 0030 MOVE R11 R3 + 0x7C1C0800, // 0031 CALL R7 4 0x80040E00, // 0032 RET 1 R7 - 0x70020007, // 0033 JMP #003C - 0x541EFFFC, // 0034 LDINT R7 65533 - 0x1C1C0C07, // 0035 EQ R7 R6 R7 - 0x781E0004, // 0036 JMPF R7 #003C - 0x8C1C0706, // 0037 GETMET R7 R3 K6 - 0x8824090B, // 0038 GETMBR R9 R4 K11 - 0x5828000C, // 0039 LDCONST R10 K12 - 0x7C1C0600, // 003A CALL R7 3 - 0x80040E00, // 003B RET 1 R7 - 0x70020008, // 003C JMP #0046 - 0x601C0003, // 003D GETGBL R7 G3 - 0x5C200000, // 003E MOVE R8 R0 - 0x7C1C0200, // 003F CALL R7 1 - 0x8C1C0F0D, // 0040 GETMET R7 R7 K13 - 0x5C240200, // 0041 MOVE R9 R1 - 0x5C280400, // 0042 MOVE R10 R2 - 0x5C2C0600, // 0043 MOVE R11 R3 - 0x7C1C0800, // 0044 CALL R7 4 - 0x80040E00, // 0045 RET 1 R7 - 0x80000000, // 0046 RET 0 }) ) ); @@ -207,7 +185,7 @@ be_local_class(Matter_Plugin_Sensor_Humidity, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -215,19 +193,27 @@ be_local_class(Matter_Plugin_Sensor_Humidity, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(3, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -235,30 +221,48 @@ be_local_class(Matter_Plugin_Sensor_Humidity, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(1029, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(5, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Illuminance.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Illuminance.h index 81d05c19f..eef1f845b 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Illuminance.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Illuminance.h @@ -50,7 +50,7 @@ be_local_closure(Matter_Plugin_Sensor_Illuminance_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ + ( &(const bvalue[12]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -62,20 +62,18 @@ be_local_closure(Matter_Plugin_Sensor_Illuminance_read_attribute, /* name */ /* K8 */ be_nested_str_weak(NULL), /* K9 */ be_const_int(1), /* K10 */ be_const_int(2), - /* K11 */ be_nested_str_weak(U4), - /* K12 */ be_const_int(3), - /* K13 */ be_nested_str_weak(read_attribute), + /* K11 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[71]) { /* code */ + ( &(const binstruction[51]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E03FF, // 0004 LDINT R7 1024 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0035, // 0006 JMPF R7 #003D + 0x781E0022, // 0006 JMPF R7 #002A 0x1C1C0D04, // 0007 EQ R7 R6 K4 0x781E0011, // 0008 JMPF R7 #001B 0x881C0105, // 0009 GETMBR R7 R0 K5 @@ -95,7 +93,7 @@ be_local_closure(Matter_Plugin_Sensor_Illuminance_read_attribute, /* name */ 0x4C280000, // 0017 LDNIL R10 0x7C1C0600, // 0018 CALL R7 3 0x80040E00, // 0019 RET 1 R7 - 0x70020020, // 001A JMP #003C + 0x7002000E, // 001A JMP #002A 0x1C1C0D09, // 001B EQ R7 R6 K9 0x781E0005, // 001C JMPF R7 #0023 0x8C1C0706, // 001D GETMET R7 R3 K6 @@ -103,43 +101,23 @@ be_local_closure(Matter_Plugin_Sensor_Illuminance_read_attribute, /* name */ 0x58280009, // 001F LDCONST R10 K9 0x7C1C0600, // 0020 CALL R7 3 0x80040E00, // 0021 RET 1 R7 - 0x70020018, // 0022 JMP #003C + 0x70020006, // 0022 JMP #002A 0x1C1C0D0A, // 0023 EQ R7 R6 K10 - 0x781E0005, // 0024 JMPF R7 #002B + 0x781E0004, // 0024 JMPF R7 #002A 0x8C1C0706, // 0025 GETMET R7 R3 K6 0x88240907, // 0026 GETMBR R9 R4 K7 0x542AFFFD, // 0027 LDINT R10 65534 0x7C1C0600, // 0028 CALL R7 3 0x80040E00, // 0029 RET 1 R7 - 0x70020010, // 002A JMP #003C - 0x541EFFFB, // 002B LDINT R7 65532 - 0x1C1C0C07, // 002C EQ R7 R6 R7 - 0x781E0005, // 002D JMPF R7 #0034 - 0x8C1C0706, // 002E GETMET R7 R3 K6 - 0x8824090B, // 002F GETMBR R9 R4 K11 - 0x58280004, // 0030 LDCONST R10 K4 - 0x7C1C0600, // 0031 CALL R7 3 + 0x601C0003, // 002A GETGBL R7 G3 + 0x5C200000, // 002B MOVE R8 R0 + 0x7C1C0200, // 002C CALL R7 1 + 0x8C1C0F0B, // 002D GETMET R7 R7 K11 + 0x5C240200, // 002E MOVE R9 R1 + 0x5C280400, // 002F MOVE R10 R2 + 0x5C2C0600, // 0030 MOVE R11 R3 + 0x7C1C0800, // 0031 CALL R7 4 0x80040E00, // 0032 RET 1 R7 - 0x70020007, // 0033 JMP #003C - 0x541EFFFC, // 0034 LDINT R7 65533 - 0x1C1C0C07, // 0035 EQ R7 R6 R7 - 0x781E0004, // 0036 JMPF R7 #003C - 0x8C1C0706, // 0037 GETMET R7 R3 K6 - 0x8824090B, // 0038 GETMBR R9 R4 K11 - 0x5828000C, // 0039 LDCONST R10 K12 - 0x7C1C0600, // 003A CALL R7 3 - 0x80040E00, // 003B RET 1 R7 - 0x70020008, // 003C JMP #0046 - 0x601C0003, // 003D GETGBL R7 G3 - 0x5C200000, // 003E MOVE R8 R0 - 0x7C1C0200, // 003F CALL R7 1 - 0x8C1C0F0D, // 0040 GETMET R7 R7 K13 - 0x5C240200, // 0041 MOVE R9 R1 - 0x5C280400, // 0042 MOVE R10 R2 - 0x5C2C0600, // 0043 MOVE R11 R3 - 0x7C1C0800, // 0044 CALL R7 4 - 0x80040E00, // 0045 RET 1 R7 - 0x80000000, // 0046 RET 0 }) ) ); @@ -219,7 +197,7 @@ be_local_class(Matter_Plugin_Sensor_Illuminance, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -227,18 +205,26 @@ be_local_class(Matter_Plugin_Sensor_Illuminance, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -246,31 +232,49 @@ be_local_class(Matter_Plugin_Sensor_Illuminance, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(1024, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(5, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Pressure.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Pressure.h index 56dcdbd6e..b64f251ac 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Pressure.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Pressure.h @@ -50,7 +50,7 @@ be_local_closure(Matter_Plugin_Sensor_Pressure_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ + ( &(const bvalue[12]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -62,20 +62,18 @@ be_local_closure(Matter_Plugin_Sensor_Pressure_read_attribute, /* name */ /* K8 */ be_nested_str_weak(NULL), /* K9 */ be_const_int(1), /* K10 */ be_const_int(2), - /* K11 */ be_nested_str_weak(U4), - /* K12 */ be_const_int(3), - /* K13 */ be_nested_str_weak(read_attribute), + /* K11 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[71]) { /* code */ + ( &(const binstruction[51]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0402, // 0004 LDINT R7 1027 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0035, // 0006 JMPF R7 #003D + 0x781E0022, // 0006 JMPF R7 #002A 0x1C1C0D04, // 0007 EQ R7 R6 K4 0x781E0011, // 0008 JMPF R7 #001B 0x881C0105, // 0009 GETMBR R7 R0 K5 @@ -95,7 +93,7 @@ be_local_closure(Matter_Plugin_Sensor_Pressure_read_attribute, /* name */ 0x4C280000, // 0017 LDNIL R10 0x7C1C0600, // 0018 CALL R7 3 0x80040E00, // 0019 RET 1 R7 - 0x70020020, // 001A JMP #003C + 0x7002000E, // 001A JMP #002A 0x1C1C0D09, // 001B EQ R7 R6 K9 0x781E0005, // 001C JMPF R7 #0023 0x8C1C0706, // 001D GETMET R7 R3 K6 @@ -103,43 +101,23 @@ be_local_closure(Matter_Plugin_Sensor_Pressure_read_attribute, /* name */ 0x542A01F3, // 001F LDINT R10 500 0x7C1C0600, // 0020 CALL R7 3 0x80040E00, // 0021 RET 1 R7 - 0x70020018, // 0022 JMP #003C + 0x70020006, // 0022 JMP #002A 0x1C1C0D0A, // 0023 EQ R7 R6 K10 - 0x781E0005, // 0024 JMPF R7 #002B + 0x781E0004, // 0024 JMPF R7 #002A 0x8C1C0706, // 0025 GETMET R7 R3 K6 0x88240907, // 0026 GETMBR R9 R4 K7 0x542A05DB, // 0027 LDINT R10 1500 0x7C1C0600, // 0028 CALL R7 3 0x80040E00, // 0029 RET 1 R7 - 0x70020010, // 002A JMP #003C - 0x541EFFFB, // 002B LDINT R7 65532 - 0x1C1C0C07, // 002C EQ R7 R6 R7 - 0x781E0005, // 002D JMPF R7 #0034 - 0x8C1C0706, // 002E GETMET R7 R3 K6 - 0x8824090B, // 002F GETMBR R9 R4 K11 - 0x58280004, // 0030 LDCONST R10 K4 - 0x7C1C0600, // 0031 CALL R7 3 + 0x601C0003, // 002A GETGBL R7 G3 + 0x5C200000, // 002B MOVE R8 R0 + 0x7C1C0200, // 002C CALL R7 1 + 0x8C1C0F0B, // 002D GETMET R7 R7 K11 + 0x5C240200, // 002E MOVE R9 R1 + 0x5C280400, // 002F MOVE R10 R2 + 0x5C2C0600, // 0030 MOVE R11 R3 + 0x7C1C0800, // 0031 CALL R7 4 0x80040E00, // 0032 RET 1 R7 - 0x70020007, // 0033 JMP #003C - 0x541EFFFC, // 0034 LDINT R7 65533 - 0x1C1C0C07, // 0035 EQ R7 R6 R7 - 0x781E0004, // 0036 JMPF R7 #003C - 0x8C1C0706, // 0037 GETMET R7 R3 K6 - 0x8824090B, // 0038 GETMBR R9 R4 K11 - 0x5828000C, // 0039 LDCONST R10 K12 - 0x7C1C0600, // 003A CALL R7 3 - 0x80040E00, // 003B RET 1 R7 - 0x70020008, // 003C JMP #0046 - 0x601C0003, // 003D GETGBL R7 G3 - 0x5C200000, // 003E MOVE R8 R0 - 0x7C1C0200, // 003F CALL R7 1 - 0x8C1C0F0D, // 0040 GETMET R7 R7 K13 - 0x5C240200, // 0041 MOVE R9 R1 - 0x5C280400, // 0042 MOVE R10 R2 - 0x5C2C0600, // 0043 MOVE R11 R3 - 0x7C1C0800, // 0044 CALL R7 4 - 0x80040E00, // 0045 RET 1 R7 - 0x80000000, // 0046 RET 0 }) ) ); @@ -206,7 +184,7 @@ be_local_class(Matter_Plugin_Sensor_Pressure, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -214,20 +192,28 @@ be_local_class(Matter_Plugin_Sensor_Pressure, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(1027, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(5, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -235,29 +221,47 @@ be_local_class(Matter_Plugin_Sensor_Pressure, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Temp.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Temp.h index 1b22cb9d1..7294dfc88 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Temp.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_Sensor_Temp.h @@ -50,7 +50,7 @@ be_local_closure(Matter_Plugin_Sensor_Temp_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[13]) { /* constants */ + ( &(const bvalue[12]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -62,19 +62,18 @@ be_local_closure(Matter_Plugin_Sensor_Temp_read_attribute, /* name */ /* K8 */ be_nested_str_weak(NULL), /* K9 */ be_const_int(1), /* K10 */ be_const_int(2), - /* K11 */ be_nested_str_weak(U4), - /* K12 */ be_nested_str_weak(read_attribute), + /* K11 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[69]) { /* code */ + ( &(const binstruction[49]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0401, // 0004 LDINT R7 1026 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0033, // 0006 JMPF R7 #003B + 0x781E0020, // 0006 JMPF R7 #0028 0x1C1C0D04, // 0007 EQ R7 R6 K4 0x781E000F, // 0008 JMPF R7 #0019 0x881C0105, // 0009 GETMBR R7 R0 K5 @@ -92,7 +91,7 @@ be_local_closure(Matter_Plugin_Sensor_Temp_read_attribute, /* name */ 0x4C280000, // 0015 LDNIL R10 0x7C1C0600, // 0016 CALL R7 3 0x80040E00, // 0017 RET 1 R7 - 0x70020020, // 0018 JMP #003A + 0x7002000E, // 0018 JMP #0028 0x1C1C0D09, // 0019 EQ R7 R6 K9 0x781E0005, // 001A JMPF R7 #0021 0x8C1C0706, // 001B GETMET R7 R3 K6 @@ -100,43 +99,23 @@ be_local_closure(Matter_Plugin_Sensor_Temp_read_attribute, /* name */ 0x5429EC77, // 001D LDINT R10 -5000 0x7C1C0600, // 001E CALL R7 3 0x80040E00, // 001F RET 1 R7 - 0x70020018, // 0020 JMP #003A + 0x70020006, // 0020 JMP #0028 0x1C1C0D0A, // 0021 EQ R7 R6 K10 - 0x781E0005, // 0022 JMPF R7 #0029 + 0x781E0004, // 0022 JMPF R7 #0028 0x8C1C0706, // 0023 GETMET R7 R3 K6 0x88240907, // 0024 GETMBR R9 R4 K7 0x542A3A97, // 0025 LDINT R10 15000 0x7C1C0600, // 0026 CALL R7 3 0x80040E00, // 0027 RET 1 R7 - 0x70020010, // 0028 JMP #003A - 0x541EFFFB, // 0029 LDINT R7 65532 - 0x1C1C0C07, // 002A EQ R7 R6 R7 - 0x781E0005, // 002B JMPF R7 #0032 - 0x8C1C0706, // 002C GETMET R7 R3 K6 - 0x8824090B, // 002D GETMBR R9 R4 K11 - 0x58280004, // 002E LDCONST R10 K4 - 0x7C1C0600, // 002F CALL R7 3 + 0x601C0003, // 0028 GETGBL R7 G3 + 0x5C200000, // 0029 MOVE R8 R0 + 0x7C1C0200, // 002A CALL R7 1 + 0x8C1C0F0B, // 002B GETMET R7 R7 K11 + 0x5C240200, // 002C MOVE R9 R1 + 0x5C280400, // 002D MOVE R10 R2 + 0x5C2C0600, // 002E MOVE R11 R3 + 0x7C1C0800, // 002F CALL R7 4 0x80040E00, // 0030 RET 1 R7 - 0x70020007, // 0031 JMP #003A - 0x541EFFFC, // 0032 LDINT R7 65533 - 0x1C1C0C07, // 0033 EQ R7 R6 R7 - 0x781E0004, // 0034 JMPF R7 #003A - 0x8C1C0706, // 0035 GETMET R7 R3 K6 - 0x8824090B, // 0036 GETMBR R9 R4 K11 - 0x542A0003, // 0037 LDINT R10 4 - 0x7C1C0600, // 0038 CALL R7 3 - 0x80040E00, // 0039 RET 1 R7 - 0x70020008, // 003A JMP #0044 - 0x601C0003, // 003B GETGBL R7 G3 - 0x5C200000, // 003C MOVE R8 R0 - 0x7C1C0200, // 003D CALL R7 1 - 0x8C1C0F0C, // 003E GETMET R7 R7 K12 - 0x5C240200, // 003F MOVE R9 R1 - 0x5C280400, // 0040 MOVE R10 R2 - 0x5C2C0600, // 0041 MOVE R11 R3 - 0x7C1C0800, // 0042 CALL R7 4 - 0x80040E00, // 0043 RET 1 R7 - 0x80000000, // 0044 RET 0 }) ) ); @@ -219,16 +198,20 @@ be_local_class(Matter_Plugin_Sensor_Temp, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(1026, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(5, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -236,11 +219,15 @@ be_local_class(Matter_Plugin_Sensor_Temp, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -248,29 +235,47 @@ be_local_class(Matter_Plugin_Sensor_Temp, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_ShutterTilt.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_ShutterTilt.h index 9b6b6eea4..3914bb053 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_ShutterTilt.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_3_ShutterTilt.h @@ -440,7 +440,7 @@ be_local_class(Matter_Plugin_ShutterTilt, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(258, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(14, + be_const_list( * be_nested_list(17, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(5), @@ -450,15 +450,18 @@ be_local_class(Matter_Plugin_ShutterTilt, be_const_int(13), be_const_int(14), be_const_int(23), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), be_const_int(7), be_const_int(12), be_const_int(15), - be_const_int(65532), })) ) } )) }, { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -466,11 +469,15 @@ be_local_class(Matter_Plugin_ShutterTilt, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -478,29 +485,47 @@ be_local_class(Matter_Plugin_ShutterTilt, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Light1.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Light1.h index 09091811a..2c40875ff 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Light1.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Light1.h @@ -195,7 +195,7 @@ be_local_closure(Matter_Plugin_Bridge_Light1_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[15]) { /* constants */ + ( &(const bvalue[13]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -208,20 +208,18 @@ be_local_closure(Matter_Plugin_Bridge_Light1_read_attribute, /* name */ /* K9 */ be_nested_str_weak(NULL), /* K10 */ be_const_int(2), /* K11 */ be_const_int(3), - /* K12 */ be_nested_str_weak(U4), - /* K13 */ be_const_int(1), - /* K14 */ be_nested_str_weak(read_attribute), + /* K12 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[99]) { /* code */ + ( &(const binstruction[79]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0007, // 0004 LDINT R7 8 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0051, // 0006 JMPF R7 #0059 + 0x781E003E, // 0006 JMPF R7 #0046 0x8C1C0104, // 0007 GETMET R7 R0 K4 0x7C1C0200, // 0008 CALL R7 1 0x1C1C0D05, // 0009 EQ R7 R6 K5 @@ -241,7 +239,7 @@ be_local_closure(Matter_Plugin_Bridge_Light1_read_attribute, /* name */ 0x4C280000, // 0017 LDNIL R10 0x7C1C0600, // 0018 CALL R7 3 0x80040E00, // 0019 RET 1 R7 - 0x7002003C, // 001A JMP #0058 + 0x7002002A, // 001A JMP #0046 0x1C1C0D0A, // 001B EQ R7 R6 K10 0x781E0005, // 001C JMPF R7 #0023 0x8C1C0707, // 001D GETMET R7 R3 K7 @@ -249,7 +247,7 @@ be_local_closure(Matter_Plugin_Bridge_Light1_read_attribute, /* name */ 0x58280005, // 001F LDCONST R10 K5 0x7C1C0600, // 0020 CALL R7 3 0x80040E00, // 0021 RET 1 R7 - 0x70020034, // 0022 JMP #0058 + 0x70020022, // 0022 JMP #0046 0x1C1C0D0B, // 0023 EQ R7 R6 K11 0x781E0005, // 0024 JMPF R7 #002B 0x8C1C0707, // 0025 GETMET R7 R3 K7 @@ -257,7 +255,7 @@ be_local_closure(Matter_Plugin_Bridge_Light1_read_attribute, /* name */ 0x542A00FD, // 0027 LDINT R10 254 0x7C1C0600, // 0028 CALL R7 3 0x80040E00, // 0029 RET 1 R7 - 0x7002002C, // 002A JMP #0058 + 0x7002001A, // 002A JMP #0046 0x541E000E, // 002B LDINT R7 15 0x1C1C0C07, // 002C EQ R7 R6 R7 0x781E0005, // 002D JMPF R7 #0034 @@ -266,10 +264,10 @@ be_local_closure(Matter_Plugin_Bridge_Light1_read_attribute, /* name */ 0x58280005, // 0030 LDCONST R10 K5 0x7C1C0600, // 0031 CALL R7 3 0x80040E00, // 0032 RET 1 R7 - 0x70020023, // 0033 JMP #0058 + 0x70020011, // 0033 JMP #0046 0x541E0010, // 0034 LDINT R7 17 0x1C1C0C07, // 0035 EQ R7 R6 R7 - 0x781E000F, // 0036 JMPF R7 #0047 + 0x781E000E, // 0036 JMPF R7 #0046 0x881C0106, // 0037 GETMBR R7 R0 K6 0x4C200000, // 0038 LDNIL R8 0x201C0E08, // 0039 NE R7 R7 R8 @@ -285,35 +283,15 @@ be_local_closure(Matter_Plugin_Bridge_Light1_read_attribute, /* name */ 0x4C280000, // 0043 LDNIL R10 0x7C1C0600, // 0044 CALL R7 3 0x80040E00, // 0045 RET 1 R7 - 0x70020010, // 0046 JMP #0058 - 0x541EFFFB, // 0047 LDINT R7 65532 - 0x1C1C0C07, // 0048 EQ R7 R6 R7 - 0x781E0005, // 0049 JMPF R7 #0050 - 0x8C1C0707, // 004A GETMET R7 R3 K7 - 0x8824090C, // 004B GETMBR R9 R4 K12 - 0x5828000D, // 004C LDCONST R10 K13 - 0x7C1C0600, // 004D CALL R7 3 + 0x601C0003, // 0046 GETGBL R7 G3 + 0x5C200000, // 0047 MOVE R8 R0 + 0x7C1C0200, // 0048 CALL R7 1 + 0x8C1C0F0C, // 0049 GETMET R7 R7 K12 + 0x5C240200, // 004A MOVE R9 R1 + 0x5C280400, // 004B MOVE R10 R2 + 0x5C2C0600, // 004C MOVE R11 R3 + 0x7C1C0800, // 004D CALL R7 4 0x80040E00, // 004E RET 1 R7 - 0x70020007, // 004F JMP #0058 - 0x541EFFFC, // 0050 LDINT R7 65533 - 0x1C1C0C07, // 0051 EQ R7 R6 R7 - 0x781E0004, // 0052 JMPF R7 #0058 - 0x8C1C0707, // 0053 GETMET R7 R3 K7 - 0x8824090C, // 0054 GETMBR R9 R4 K12 - 0x542A0004, // 0055 LDINT R10 5 - 0x7C1C0600, // 0056 CALL R7 3 - 0x80040E00, // 0057 RET 1 R7 - 0x70020008, // 0058 JMP #0062 - 0x601C0003, // 0059 GETGBL R7 G3 - 0x5C200000, // 005A MOVE R8 R0 - 0x7C1C0200, // 005B CALL R7 1 - 0x8C1C0F0E, // 005C GETMET R7 R7 K14 - 0x5C240200, // 005D MOVE R9 R1 - 0x5C280400, // 005E MOVE R10 R2 - 0x5C2C0600, // 005F MOVE R11 R3 - 0x7C1C0800, // 0060 CALL R7 4 - 0x80040E00, // 0061 RET 1 R7 - 0x80000000, // 0062 RET 0 }) ) ); @@ -558,28 +536,36 @@ be_local_class(Matter_Plugin_Bridge_Light1, be_const_map( * be_nested_map(7, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(29, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(8, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(11, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(2), be_const_int(3), be_const_int(15), be_const_int(17), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -587,24 +573,38 @@ be_local_class(Matter_Plugin_Bridge_Light1, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -612,13 +612,21 @@ be_local_class(Matter_Plugin_Bridge_Light1, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(6, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Flow.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Flow.h index bc0401c1a..538581fca 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Flow.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Flow.h @@ -83,7 +83,7 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Flow_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ + ( &(const bvalue[12]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -95,20 +95,18 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Flow_read_attribute, /* name */ /* K8 */ be_nested_str_weak(NULL), /* K9 */ be_const_int(1), /* K10 */ be_const_int(2), - /* K11 */ be_nested_str_weak(U4), - /* K12 */ be_const_int(3), - /* K13 */ be_nested_str_weak(read_attribute), + /* K11 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[71]) { /* code */ + ( &(const binstruction[51]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0403, // 0004 LDINT R7 1028 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0035, // 0006 JMPF R7 #003D + 0x781E0022, // 0006 JMPF R7 #002A 0x1C1C0D04, // 0007 EQ R7 R6 K4 0x781E0011, // 0008 JMPF R7 #001B 0x881C0105, // 0009 GETMBR R7 R0 K5 @@ -128,7 +126,7 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Flow_read_attribute, /* name */ 0x4C280000, // 0017 LDNIL R10 0x7C1C0600, // 0018 CALL R7 3 0x80040E00, // 0019 RET 1 R7 - 0x70020020, // 001A JMP #003C + 0x7002000E, // 001A JMP #002A 0x1C1C0D09, // 001B EQ R7 R6 K9 0x781E0005, // 001C JMPF R7 #0023 0x8C1C0706, // 001D GETMET R7 R3 K6 @@ -136,43 +134,23 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Flow_read_attribute, /* name */ 0x58280004, // 001F LDCONST R10 K4 0x7C1C0600, // 0020 CALL R7 3 0x80040E00, // 0021 RET 1 R7 - 0x70020018, // 0022 JMP #003C + 0x70020006, // 0022 JMP #002A 0x1C1C0D0A, // 0023 EQ R7 R6 K10 - 0x781E0005, // 0024 JMPF R7 #002B + 0x781E0004, // 0024 JMPF R7 #002A 0x8C1C0706, // 0025 GETMET R7 R3 K6 0x88240907, // 0026 GETMBR R9 R4 K7 0x542AFFFD, // 0027 LDINT R10 65534 0x7C1C0600, // 0028 CALL R7 3 0x80040E00, // 0029 RET 1 R7 - 0x70020010, // 002A JMP #003C - 0x541EFFFB, // 002B LDINT R7 65532 - 0x1C1C0C07, // 002C EQ R7 R6 R7 - 0x781E0005, // 002D JMPF R7 #0034 - 0x8C1C0706, // 002E GETMET R7 R3 K6 - 0x8824090B, // 002F GETMBR R9 R4 K11 - 0x58280004, // 0030 LDCONST R10 K4 - 0x7C1C0600, // 0031 CALL R7 3 + 0x601C0003, // 002A GETGBL R7 G3 + 0x5C200000, // 002B MOVE R8 R0 + 0x7C1C0200, // 002C CALL R7 1 + 0x8C1C0F0B, // 002D GETMET R7 R7 K11 + 0x5C240200, // 002E MOVE R9 R1 + 0x5C280400, // 002F MOVE R10 R2 + 0x5C2C0600, // 0030 MOVE R11 R3 + 0x7C1C0800, // 0031 CALL R7 4 0x80040E00, // 0032 RET 1 R7 - 0x70020007, // 0033 JMP #003C - 0x541EFFFC, // 0034 LDINT R7 65533 - 0x1C1C0C07, // 0035 EQ R7 R6 R7 - 0x781E0004, // 0036 JMPF R7 #003C - 0x8C1C0706, // 0037 GETMET R7 R3 K6 - 0x8824090B, // 0038 GETMBR R9 R4 K11 - 0x5828000C, // 0039 LDCONST R10 K12 - 0x7C1C0600, // 003A CALL R7 3 - 0x80040E00, // 003B RET 1 R7 - 0x70020008, // 003C JMP #0046 - 0x601C0003, // 003D GETGBL R7 G3 - 0x5C200000, // 003E MOVE R8 R0 - 0x7C1C0200, // 003F CALL R7 1 - 0x8C1C0F0D, // 0040 GETMET R7 R7 K13 - 0x5C240200, // 0041 MOVE R9 R1 - 0x5C280400, // 0042 MOVE R10 R2 - 0x5C2C0600, // 0043 MOVE R11 R3 - 0x7C1C0800, // 0044 CALL R7 4 - 0x80040E00, // 0045 RET 1 R7 - 0x80000000, // 0046 RET 0 }) ) ); @@ -244,7 +222,7 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Flow, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -252,11 +230,15 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Flow, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -264,38 +246,60 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Flow, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(1028, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(5, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Humidity.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Humidity.h index fc8e54655..32bfb71ad 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Humidity.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Humidity.h @@ -83,7 +83,7 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Humidity_read_attribute, /* name 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ + ( &(const bvalue[12]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -95,20 +95,18 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Humidity_read_attribute, /* name /* K8 */ be_nested_str_weak(NULL), /* K9 */ be_const_int(1), /* K10 */ be_const_int(2), - /* K11 */ be_nested_str_weak(U4), - /* K12 */ be_const_int(3), - /* K13 */ be_nested_str_weak(read_attribute), + /* K11 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[71]) { /* code */ + ( &(const binstruction[51]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0404, // 0004 LDINT R7 1029 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0035, // 0006 JMPF R7 #003D + 0x781E0022, // 0006 JMPF R7 #002A 0x1C1C0D04, // 0007 EQ R7 R6 K4 0x781E0011, // 0008 JMPF R7 #001B 0x881C0105, // 0009 GETMBR R7 R0 K5 @@ -128,7 +126,7 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Humidity_read_attribute, /* name 0x4C280000, // 0017 LDNIL R10 0x7C1C0600, // 0018 CALL R7 3 0x80040E00, // 0019 RET 1 R7 - 0x70020020, // 001A JMP #003C + 0x7002000E, // 001A JMP #002A 0x1C1C0D09, // 001B EQ R7 R6 K9 0x781E0005, // 001C JMPF R7 #0023 0x8C1C0706, // 001D GETMET R7 R3 K6 @@ -136,43 +134,23 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Humidity_read_attribute, /* name 0x542A01F3, // 001F LDINT R10 500 0x7C1C0600, // 0020 CALL R7 3 0x80040E00, // 0021 RET 1 R7 - 0x70020018, // 0022 JMP #003C + 0x70020006, // 0022 JMP #002A 0x1C1C0D0A, // 0023 EQ R7 R6 K10 - 0x781E0005, // 0024 JMPF R7 #002B + 0x781E0004, // 0024 JMPF R7 #002A 0x8C1C0706, // 0025 GETMET R7 R3 K6 0x88240907, // 0026 GETMBR R9 R4 K7 0x542A270F, // 0027 LDINT R10 10000 0x7C1C0600, // 0028 CALL R7 3 0x80040E00, // 0029 RET 1 R7 - 0x70020010, // 002A JMP #003C - 0x541EFFFB, // 002B LDINT R7 65532 - 0x1C1C0C07, // 002C EQ R7 R6 R7 - 0x781E0005, // 002D JMPF R7 #0034 - 0x8C1C0706, // 002E GETMET R7 R3 K6 - 0x8824090B, // 002F GETMBR R9 R4 K11 - 0x58280004, // 0030 LDCONST R10 K4 - 0x7C1C0600, // 0031 CALL R7 3 + 0x601C0003, // 002A GETGBL R7 G3 + 0x5C200000, // 002B MOVE R8 R0 + 0x7C1C0200, // 002C CALL R7 1 + 0x8C1C0F0B, // 002D GETMET R7 R7 K11 + 0x5C240200, // 002E MOVE R9 R1 + 0x5C280400, // 002F MOVE R10 R2 + 0x5C2C0600, // 0030 MOVE R11 R3 + 0x7C1C0800, // 0031 CALL R7 4 0x80040E00, // 0032 RET 1 R7 - 0x70020007, // 0033 JMP #003C - 0x541EFFFC, // 0034 LDINT R7 65533 - 0x1C1C0C07, // 0035 EQ R7 R6 R7 - 0x781E0004, // 0036 JMPF R7 #003C - 0x8C1C0706, // 0037 GETMET R7 R3 K6 - 0x8824090B, // 0038 GETMBR R9 R4 K11 - 0x5828000C, // 0039 LDCONST R10 K12 - 0x7C1C0600, // 003A CALL R7 3 - 0x80040E00, // 003B RET 1 R7 - 0x70020008, // 003C JMP #0046 - 0x601C0003, // 003D GETGBL R7 G3 - 0x5C200000, // 003E MOVE R8 R0 - 0x7C1C0200, // 003F CALL R7 1 - 0x8C1C0F0D, // 0040 GETMET R7 R7 K13 - 0x5C240200, // 0041 MOVE R9 R1 - 0x5C280400, // 0042 MOVE R10 R2 - 0x5C2C0600, // 0043 MOVE R11 R3 - 0x7C1C0800, // 0044 CALL R7 4 - 0x80040E00, // 0045 RET 1 R7 - 0x80000000, // 0046 RET 0 }) ) ); @@ -252,7 +230,7 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Humidity, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -260,19 +238,27 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Humidity, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(3, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -280,30 +266,48 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Humidity, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(1029, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(5, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Illuminance.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Illuminance.h index 8bd28e910..563e3eb59 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Illuminance.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Illuminance.h @@ -95,7 +95,7 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Illuminance_read_attribute, /* na 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ + ( &(const bvalue[12]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -107,20 +107,18 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Illuminance_read_attribute, /* na /* K8 */ be_nested_str_weak(NULL), /* K9 */ be_const_int(1), /* K10 */ be_const_int(2), - /* K11 */ be_nested_str_weak(U4), - /* K12 */ be_const_int(3), - /* K13 */ be_nested_str_weak(read_attribute), + /* K11 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[71]) { /* code */ + ( &(const binstruction[51]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E03FF, // 0004 LDINT R7 1024 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0035, // 0006 JMPF R7 #003D + 0x781E0022, // 0006 JMPF R7 #002A 0x1C1C0D04, // 0007 EQ R7 R6 K4 0x781E0011, // 0008 JMPF R7 #001B 0x881C0105, // 0009 GETMBR R7 R0 K5 @@ -140,7 +138,7 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Illuminance_read_attribute, /* na 0x4C280000, // 0017 LDNIL R10 0x7C1C0600, // 0018 CALL R7 3 0x80040E00, // 0019 RET 1 R7 - 0x70020020, // 001A JMP #003C + 0x7002000E, // 001A JMP #002A 0x1C1C0D09, // 001B EQ R7 R6 K9 0x781E0005, // 001C JMPF R7 #0023 0x8C1C0706, // 001D GETMET R7 R3 K6 @@ -148,43 +146,23 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Illuminance_read_attribute, /* na 0x58280009, // 001F LDCONST R10 K9 0x7C1C0600, // 0020 CALL R7 3 0x80040E00, // 0021 RET 1 R7 - 0x70020018, // 0022 JMP #003C + 0x70020006, // 0022 JMP #002A 0x1C1C0D0A, // 0023 EQ R7 R6 K10 - 0x781E0005, // 0024 JMPF R7 #002B + 0x781E0004, // 0024 JMPF R7 #002A 0x8C1C0706, // 0025 GETMET R7 R3 K6 0x88240907, // 0026 GETMBR R9 R4 K7 0x542AFFFD, // 0027 LDINT R10 65534 0x7C1C0600, // 0028 CALL R7 3 0x80040E00, // 0029 RET 1 R7 - 0x70020010, // 002A JMP #003C - 0x541EFFFB, // 002B LDINT R7 65532 - 0x1C1C0C07, // 002C EQ R7 R6 R7 - 0x781E0005, // 002D JMPF R7 #0034 - 0x8C1C0706, // 002E GETMET R7 R3 K6 - 0x8824090B, // 002F GETMBR R9 R4 K11 - 0x58280004, // 0030 LDCONST R10 K4 - 0x7C1C0600, // 0031 CALL R7 3 + 0x601C0003, // 002A GETGBL R7 G3 + 0x5C200000, // 002B MOVE R8 R0 + 0x7C1C0200, // 002C CALL R7 1 + 0x8C1C0F0B, // 002D GETMET R7 R7 K11 + 0x5C240200, // 002E MOVE R9 R1 + 0x5C280400, // 002F MOVE R10 R2 + 0x5C2C0600, // 0030 MOVE R11 R3 + 0x7C1C0800, // 0031 CALL R7 4 0x80040E00, // 0032 RET 1 R7 - 0x70020007, // 0033 JMP #003C - 0x541EFFFC, // 0034 LDINT R7 65533 - 0x1C1C0C07, // 0035 EQ R7 R6 R7 - 0x781E0004, // 0036 JMPF R7 #003C - 0x8C1C0706, // 0037 GETMET R7 R3 K6 - 0x8824090B, // 0038 GETMBR R9 R4 K11 - 0x5828000C, // 0039 LDCONST R10 K12 - 0x7C1C0600, // 003A CALL R7 3 - 0x80040E00, // 003B RET 1 R7 - 0x70020008, // 003C JMP #0046 - 0x601C0003, // 003D GETGBL R7 G3 - 0x5C200000, // 003E MOVE R8 R0 - 0x7C1C0200, // 003F CALL R7 1 - 0x8C1C0F0D, // 0040 GETMET R7 R7 K13 - 0x5C240200, // 0041 MOVE R9 R1 - 0x5C280400, // 0042 MOVE R10 R2 - 0x5C2C0600, // 0043 MOVE R11 R3 - 0x7C1C0800, // 0044 CALL R7 4 - 0x80040E00, // 0045 RET 1 R7 - 0x80000000, // 0046 RET 0 }) ) ); @@ -256,7 +234,7 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Illuminance, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -264,18 +242,26 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Illuminance, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -283,31 +269,49 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Illuminance, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(1024, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(5, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Pressure.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Pressure.h index 4edf27096..6632731e9 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Pressure.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Pressure.h @@ -82,7 +82,7 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Pressure_read_attribute, /* name 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[14]) { /* constants */ + ( &(const bvalue[12]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -94,20 +94,18 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Pressure_read_attribute, /* name /* K8 */ be_nested_str_weak(NULL), /* K9 */ be_const_int(1), /* K10 */ be_const_int(2), - /* K11 */ be_nested_str_weak(U4), - /* K12 */ be_const_int(3), - /* K13 */ be_nested_str_weak(read_attribute), + /* K11 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[71]) { /* code */ + ( &(const binstruction[51]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0402, // 0004 LDINT R7 1027 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0035, // 0006 JMPF R7 #003D + 0x781E0022, // 0006 JMPF R7 #002A 0x1C1C0D04, // 0007 EQ R7 R6 K4 0x781E0011, // 0008 JMPF R7 #001B 0x881C0105, // 0009 GETMBR R7 R0 K5 @@ -127,7 +125,7 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Pressure_read_attribute, /* name 0x4C280000, // 0017 LDNIL R10 0x7C1C0600, // 0018 CALL R7 3 0x80040E00, // 0019 RET 1 R7 - 0x70020020, // 001A JMP #003C + 0x7002000E, // 001A JMP #002A 0x1C1C0D09, // 001B EQ R7 R6 K9 0x781E0005, // 001C JMPF R7 #0023 0x8C1C0706, // 001D GETMET R7 R3 K6 @@ -135,43 +133,23 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Pressure_read_attribute, /* name 0x542A01F3, // 001F LDINT R10 500 0x7C1C0600, // 0020 CALL R7 3 0x80040E00, // 0021 RET 1 R7 - 0x70020018, // 0022 JMP #003C + 0x70020006, // 0022 JMP #002A 0x1C1C0D0A, // 0023 EQ R7 R6 K10 - 0x781E0005, // 0024 JMPF R7 #002B + 0x781E0004, // 0024 JMPF R7 #002A 0x8C1C0706, // 0025 GETMET R7 R3 K6 0x88240907, // 0026 GETMBR R9 R4 K7 0x542A05DB, // 0027 LDINT R10 1500 0x7C1C0600, // 0028 CALL R7 3 0x80040E00, // 0029 RET 1 R7 - 0x70020010, // 002A JMP #003C - 0x541EFFFB, // 002B LDINT R7 65532 - 0x1C1C0C07, // 002C EQ R7 R6 R7 - 0x781E0005, // 002D JMPF R7 #0034 - 0x8C1C0706, // 002E GETMET R7 R3 K6 - 0x8824090B, // 002F GETMBR R9 R4 K11 - 0x58280004, // 0030 LDCONST R10 K4 - 0x7C1C0600, // 0031 CALL R7 3 + 0x601C0003, // 002A GETGBL R7 G3 + 0x5C200000, // 002B MOVE R8 R0 + 0x7C1C0200, // 002C CALL R7 1 + 0x8C1C0F0B, // 002D GETMET R7 R7 K11 + 0x5C240200, // 002E MOVE R9 R1 + 0x5C280400, // 002F MOVE R10 R2 + 0x5C2C0600, // 0030 MOVE R11 R3 + 0x7C1C0800, // 0031 CALL R7 4 0x80040E00, // 0032 RET 1 R7 - 0x70020007, // 0033 JMP #003C - 0x541EFFFC, // 0034 LDINT R7 65533 - 0x1C1C0C07, // 0035 EQ R7 R6 R7 - 0x781E0004, // 0036 JMPF R7 #003C - 0x8C1C0706, // 0037 GETMET R7 R3 K6 - 0x8824090B, // 0038 GETMBR R9 R4 K11 - 0x5828000C, // 0039 LDCONST R10 K12 - 0x7C1C0600, // 003A CALL R7 3 - 0x80040E00, // 003B RET 1 R7 - 0x70020008, // 003C JMP #0046 - 0x601C0003, // 003D GETGBL R7 G3 - 0x5C200000, // 003E MOVE R8 R0 - 0x7C1C0200, // 003F CALL R7 1 - 0x8C1C0F0D, // 0040 GETMET R7 R7 K13 - 0x5C240200, // 0041 MOVE R9 R1 - 0x5C280400, // 0042 MOVE R10 R2 - 0x5C2C0600, // 0043 MOVE R11 R3 - 0x7C1C0800, // 0044 CALL R7 4 - 0x80040E00, // 0045 RET 1 R7 - 0x80000000, // 0046 RET 0 }) ) ); @@ -243,7 +221,7 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Pressure, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -251,20 +229,28 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Pressure, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(1027, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(5, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -272,29 +258,47 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Pressure, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 0), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Temp.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Temp.h index cd3d6572a..d257139a0 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Temp.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_4_Bridge_Sensor_Temp.h @@ -95,7 +95,7 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Temp_read_attribute, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[13]) { /* constants */ + ( &(const bvalue[12]) { /* constants */ /* K0 */ be_nested_str_weak(matter), /* K1 */ be_nested_str_weak(TLV), /* K2 */ be_nested_str_weak(cluster), @@ -107,19 +107,18 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Temp_read_attribute, /* name */ /* K8 */ be_nested_str_weak(NULL), /* K9 */ be_const_int(1), /* K10 */ be_const_int(2), - /* K11 */ be_nested_str_weak(U4), - /* K12 */ be_nested_str_weak(read_attribute), + /* K11 */ be_nested_str_weak(read_attribute), }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[69]) { /* code */ + ( &(const binstruction[49]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E0401, // 0004 LDINT R7 1026 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0033, // 0006 JMPF R7 #003B + 0x781E0020, // 0006 JMPF R7 #0028 0x1C1C0D04, // 0007 EQ R7 R6 K4 0x781E000F, // 0008 JMPF R7 #0019 0x881C0105, // 0009 GETMBR R7 R0 K5 @@ -137,7 +136,7 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Temp_read_attribute, /* name */ 0x4C280000, // 0015 LDNIL R10 0x7C1C0600, // 0016 CALL R7 3 0x80040E00, // 0017 RET 1 R7 - 0x70020020, // 0018 JMP #003A + 0x7002000E, // 0018 JMP #0028 0x1C1C0D09, // 0019 EQ R7 R6 K9 0x781E0005, // 001A JMPF R7 #0021 0x8C1C0706, // 001B GETMET R7 R3 K6 @@ -145,43 +144,23 @@ be_local_closure(Matter_Plugin_Bridge_Sensor_Temp_read_attribute, /* name */ 0x5429EC77, // 001D LDINT R10 -5000 0x7C1C0600, // 001E CALL R7 3 0x80040E00, // 001F RET 1 R7 - 0x70020018, // 0020 JMP #003A + 0x70020006, // 0020 JMP #0028 0x1C1C0D0A, // 0021 EQ R7 R6 K10 - 0x781E0005, // 0022 JMPF R7 #0029 + 0x781E0004, // 0022 JMPF R7 #0028 0x8C1C0706, // 0023 GETMET R7 R3 K6 0x88240907, // 0024 GETMBR R9 R4 K7 0x542A3A97, // 0025 LDINT R10 15000 0x7C1C0600, // 0026 CALL R7 3 0x80040E00, // 0027 RET 1 R7 - 0x70020010, // 0028 JMP #003A - 0x541EFFFB, // 0029 LDINT R7 65532 - 0x1C1C0C07, // 002A EQ R7 R6 R7 - 0x781E0005, // 002B JMPF R7 #0032 - 0x8C1C0706, // 002C GETMET R7 R3 K6 - 0x8824090B, // 002D GETMBR R9 R4 K11 - 0x58280004, // 002E LDCONST R10 K4 - 0x7C1C0600, // 002F CALL R7 3 + 0x601C0003, // 0028 GETGBL R7 G3 + 0x5C200000, // 0029 MOVE R8 R0 + 0x7C1C0200, // 002A CALL R7 1 + 0x8C1C0F0B, // 002B GETMET R7 R7 K11 + 0x5C240200, // 002C MOVE R9 R1 + 0x5C280400, // 002D MOVE R10 R2 + 0x5C2C0600, // 002E MOVE R11 R3 + 0x7C1C0800, // 002F CALL R7 4 0x80040E00, // 0030 RET 1 R7 - 0x70020007, // 0031 JMP #003A - 0x541EFFFC, // 0032 LDINT R7 65533 - 0x1C1C0C07, // 0033 EQ R7 R6 R7 - 0x781E0004, // 0034 JMPF R7 #003A - 0x8C1C0706, // 0035 GETMET R7 R3 K6 - 0x8824090B, // 0036 GETMBR R9 R4 K11 - 0x542A0003, // 0037 LDINT R10 4 - 0x7C1C0600, // 0038 CALL R7 3 - 0x80040E00, // 0039 RET 1 R7 - 0x70020008, // 003A JMP #0044 - 0x601C0003, // 003B GETGBL R7 G3 - 0x5C200000, // 003C MOVE R8 R0 - 0x7C1C0200, // 003D CALL R7 1 - 0x8C1C0F0C, // 003E GETMET R7 R7 K12 - 0x5C240200, // 003F MOVE R9 R1 - 0x5C280400, // 0040 MOVE R10 R2 - 0x5C2C0600, // 0041 MOVE R11 R3 - 0x7C1C0800, // 0042 CALL R7 4 - 0x80040E00, // 0043 RET 1 R7 - 0x80000000, // 0044 RET 0 }) ) ); @@ -261,16 +240,20 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Temp, be_const_map( * be_nested_map(6, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(1026, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(5, + be_const_list( * be_nested_list(9, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(5, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -278,11 +261,15 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Temp, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -290,29 +277,47 @@ be_local_class(Matter_Plugin_Bridge_Sensor_Temp, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(3, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(29, 1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light2.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light2.h index c832d9323..4e7688159 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light2.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light2.h @@ -381,14 +381,14 @@ be_local_closure(Matter_Plugin_Bridge_Light2_read_attribute, /* name */ }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[101]) { /* code */ + ( &(const binstruction[81]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E02FF, // 0004 LDINT R7 768 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E0053, // 0006 JMPF R7 #005B + 0x781E0040, // 0006 JMPF R7 #0048 0x8C1C0104, // 0007 GETMET R7 R0 K4 0x7C1C0200, // 0008 CALL R7 1 0x541E0006, // 0009 LDINT R7 7 @@ -409,7 +409,7 @@ be_local_closure(Matter_Plugin_Bridge_Light2_read_attribute, /* name */ 0x4C280000, // 0018 LDNIL R10 0x7C1C0600, // 0019 CALL R7 3 0x80040E00, // 001A RET 1 R7 - 0x7002003D, // 001B JMP #005A + 0x7002002B, // 001B JMP #0048 0x541E0007, // 001C LDINT R7 8 0x1C1C0C07, // 001D EQ R7 R6 R7 0x781E0005, // 001E JMPF R7 #0025 @@ -418,7 +418,7 @@ be_local_closure(Matter_Plugin_Bridge_Light2_read_attribute, /* name */ 0x58280009, // 0021 LDCONST R10 K9 0x7C1C0600, // 0022 CALL R7 3 0x80040E00, // 0023 RET 1 R7 - 0x70020034, // 0024 JMP #005A + 0x70020022, // 0024 JMP #0048 0x541E000E, // 0025 LDINT R7 15 0x1C1C0C07, // 0026 EQ R7 R6 R7 0x781E0005, // 0027 JMPF R7 #002E @@ -427,7 +427,7 @@ be_local_closure(Matter_Plugin_Bridge_Light2_read_attribute, /* name */ 0x5828000A, // 002A LDCONST R10 K10 0x7C1C0600, // 002B CALL R7 3 0x80040E00, // 002C RET 1 R7 - 0x7002002B, // 002D JMP #005A + 0x70020019, // 002D JMP #0048 0x541E400A, // 002E LDINT R7 16395 0x1C1C0C07, // 002F EQ R7 R6 R7 0x781E0005, // 0030 JMPF R7 #0037 @@ -436,7 +436,7 @@ be_local_closure(Matter_Plugin_Bridge_Light2_read_attribute, /* name */ 0x8828010B, // 0033 GETMBR R10 R0 K11 0x7C1C0600, // 0034 CALL R7 3 0x80040E00, // 0035 RET 1 R7 - 0x70020022, // 0036 JMP #005A + 0x70020010, // 0036 JMP #0048 0x541E400B, // 0037 LDINT R7 16396 0x1C1C0C07, // 0038 EQ R7 R6 R7 0x781E0005, // 0039 JMPF R7 #0040 @@ -445,44 +445,24 @@ be_local_closure(Matter_Plugin_Bridge_Light2_read_attribute, /* name */ 0x8828010C, // 003C GETMBR R10 R0 K12 0x7C1C0600, // 003D CALL R7 3 0x80040E00, // 003E RET 1 R7 - 0x70020019, // 003F JMP #005A + 0x70020007, // 003F JMP #0048 0x541E4009, // 0040 LDINT R7 16394 0x1C1C0C07, // 0041 EQ R7 R6 R7 - 0x781E0005, // 0042 JMPF R7 #0049 + 0x781E0004, // 0042 JMPF R7 #0048 0x8C1C0706, // 0043 GETMET R7 R3 K6 0x8824090D, // 0044 GETMBR R9 R4 K13 0x542A000F, // 0045 LDINT R10 16 0x7C1C0600, // 0046 CALL R7 3 0x80040E00, // 0047 RET 1 R7 - 0x70020010, // 0048 JMP #005A - 0x541EFFFB, // 0049 LDINT R7 65532 - 0x1C1C0C07, // 004A EQ R7 R6 R7 - 0x781E0005, // 004B JMPF R7 #0052 - 0x8C1C0706, // 004C GETMET R7 R3 K6 - 0x8824090D, // 004D GETMBR R9 R4 K13 - 0x542A000F, // 004E LDINT R10 16 - 0x7C1C0600, // 004F CALL R7 3 + 0x601C0003, // 0048 GETGBL R7 G3 + 0x5C200000, // 0049 MOVE R8 R0 + 0x7C1C0200, // 004A CALL R7 1 + 0x8C1C0F0E, // 004B GETMET R7 R7 K14 + 0x5C240200, // 004C MOVE R9 R1 + 0x5C280400, // 004D MOVE R10 R2 + 0x5C2C0600, // 004E MOVE R11 R3 + 0x7C1C0800, // 004F CALL R7 4 0x80040E00, // 0050 RET 1 R7 - 0x70020007, // 0051 JMP #005A - 0x541EFFFC, // 0052 LDINT R7 65533 - 0x1C1C0C07, // 0053 EQ R7 R6 R7 - 0x781E0004, // 0054 JMPF R7 #005A - 0x8C1C0706, // 0055 GETMET R7 R3 K6 - 0x8824090D, // 0056 GETMBR R9 R4 K13 - 0x542A0004, // 0057 LDINT R10 5 - 0x7C1C0600, // 0058 CALL R7 3 - 0x80040E00, // 0059 RET 1 R7 - 0x70020008, // 005A JMP #0064 - 0x601C0003, // 005B GETGBL R7 G3 - 0x5C200000, // 005C MOVE R8 R0 - 0x7C1C0200, // 005D CALL R7 1 - 0x8C1C0F0E, // 005E GETMET R7 R7 K14 - 0x5C240200, // 005F MOVE R9 R1 - 0x5C280400, // 0060 MOVE R10 R2 - 0x5C2C0600, // 0061 MOVE R11 R3 - 0x7C1C0800, // 0062 CALL R7 4 - 0x80040E00, // 0063 RET 1 R7 - 0x80000000, // 0064 RET 0 }) ) ); @@ -549,18 +529,22 @@ be_local_class(Matter_Plugin_Bridge_Light2, be_const_map( * be_nested_map(8, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(8, 7), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(11, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(2), be_const_int(3), be_const_int(15), be_const_int(17), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -568,34 +552,52 @@ be_local_class(Matter_Plugin_Bridge_Light2, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(29, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(3, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(5, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -603,18 +605,26 @@ be_local_class(Matter_Plugin_Bridge_Light2, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(6, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(768, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(7), be_const_int(8), @@ -622,6 +632,10 @@ be_local_class(Matter_Plugin_Bridge_Light2, be_const_int(16394), be_const_int(16395), be_const_int(16396), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light3.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light3.h index 30d57117a..bed876797 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light3.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_Plugin_5_Bridge_Light3.h @@ -326,14 +326,14 @@ be_local_closure(Matter_Plugin_Bridge_Light3_read_attribute, /* name */ }), be_str_weak(read_attribute), &be_const_str_solidified, - ( &(const binstruction[127]) { /* code */ + ( &(const binstruction[107]) { /* code */ 0xB8120000, // 0000 GETNGBL R4 K0 0x88100901, // 0001 GETMBR R4 R4 K1 0x88140502, // 0002 GETMBR R5 R2 K2 0x88180503, // 0003 GETMBR R6 R2 K3 0x541E02FF, // 0004 LDINT R7 768 0x1C1C0A07, // 0005 EQ R7 R5 R7 - 0x781E006D, // 0006 JMPF R7 #0075 + 0x781E005A, // 0006 JMPF R7 #0062 0x8C1C0104, // 0007 GETMET R7 R0 K4 0x7C1C0200, // 0008 CALL R7 1 0x1C1C0D05, // 0009 EQ R7 R6 K5 @@ -353,7 +353,7 @@ be_local_closure(Matter_Plugin_Bridge_Light3_read_attribute, /* name */ 0x4C280000, // 0017 LDNIL R10 0x7C1C0600, // 0018 CALL R7 3 0x80040E00, // 0019 RET 1 R7 - 0x70020058, // 001A JMP #0074 + 0x70020046, // 001A JMP #0062 0x1C1C0D0A, // 001B EQ R7 R6 K10 0x781E000F, // 001C JMPF R7 #002D 0x881C010B, // 001D GETMBR R7 R0 K11 @@ -371,7 +371,7 @@ be_local_closure(Matter_Plugin_Bridge_Light3_read_attribute, /* name */ 0x4C280000, // 0029 LDNIL R10 0x7C1C0600, // 002A CALL R7 3 0x80040E00, // 002B RET 1 R7 - 0x70020046, // 002C JMP #0074 + 0x70020034, // 002C JMP #0062 0x541E0006, // 002D LDINT R7 7 0x1C1C0C07, // 002E EQ R7 R6 R7 0x781E0005, // 002F JMPF R7 #0036 @@ -380,7 +380,7 @@ be_local_closure(Matter_Plugin_Bridge_Light3_read_attribute, /* name */ 0x58280005, // 0032 LDCONST R10 K5 0x7C1C0600, // 0033 CALL R7 3 0x80040E00, // 0034 RET 1 R7 - 0x7002003D, // 0035 JMP #0074 + 0x7002002B, // 0035 JMP #0062 0x541E0007, // 0036 LDINT R7 8 0x1C1C0C07, // 0037 EQ R7 R6 R7 0x781E0005, // 0038 JMPF R7 #003F @@ -389,7 +389,7 @@ be_local_closure(Matter_Plugin_Bridge_Light3_read_attribute, /* name */ 0x58280005, // 003B LDCONST R10 K5 0x7C1C0600, // 003C CALL R7 3 0x80040E00, // 003D RET 1 R7 - 0x70020034, // 003E JMP #0074 + 0x70020022, // 003E JMP #0062 0x541E000E, // 003F LDINT R7 15 0x1C1C0C07, // 0040 EQ R7 R6 R7 0x781E0005, // 0041 JMPF R7 #0048 @@ -398,7 +398,7 @@ be_local_closure(Matter_Plugin_Bridge_Light3_read_attribute, /* name */ 0x58280005, // 0044 LDCONST R10 K5 0x7C1C0600, // 0045 CALL R7 3 0x80040E00, // 0046 RET 1 R7 - 0x7002002B, // 0047 JMP #0074 + 0x70020019, // 0047 JMP #0062 0x541E4000, // 0048 LDINT R7 16385 0x1C1C0C07, // 0049 EQ R7 R6 R7 0x781E0005, // 004A JMPF R7 #0051 @@ -407,7 +407,7 @@ be_local_closure(Matter_Plugin_Bridge_Light3_read_attribute, /* name */ 0x58280005, // 004D LDCONST R10 K5 0x7C1C0600, // 004E CALL R7 3 0x80040E00, // 004F RET 1 R7 - 0x70020022, // 0050 JMP #0074 + 0x70020010, // 0050 JMP #0062 0x541E4009, // 0051 LDINT R7 16394 0x1C1C0C07, // 0052 EQ R7 R6 R7 0x781E0005, // 0053 JMPF R7 #005A @@ -416,44 +416,24 @@ be_local_closure(Matter_Plugin_Bridge_Light3_read_attribute, /* name */ 0x5828000A, // 0056 LDCONST R10 K10 0x7C1C0600, // 0057 CALL R7 3 0x80040E00, // 0058 RET 1 R7 - 0x70020019, // 0059 JMP #0074 + 0x70020007, // 0059 JMP #0062 0x541E000F, // 005A LDINT R7 16 0x1C1C0C07, // 005B EQ R7 R6 R7 - 0x781E0005, // 005C JMPF R7 #0063 + 0x781E0004, // 005C JMPF R7 #0062 0x8C1C0707, // 005D GETMET R7 R3 K7 0x88240908, // 005E GETMBR R9 R4 K8 0x58280005, // 005F LDCONST R10 K5 0x7C1C0600, // 0060 CALL R7 3 0x80040E00, // 0061 RET 1 R7 - 0x70020010, // 0062 JMP #0074 - 0x541EFFFB, // 0063 LDINT R7 65532 - 0x1C1C0C07, // 0064 EQ R7 R6 R7 - 0x781E0005, // 0065 JMPF R7 #006C - 0x8C1C0707, // 0066 GETMET R7 R3 K7 - 0x8824090C, // 0067 GETMBR R9 R4 K12 - 0x5828000A, // 0068 LDCONST R10 K10 - 0x7C1C0600, // 0069 CALL R7 3 + 0x601C0003, // 0062 GETGBL R7 G3 + 0x5C200000, // 0063 MOVE R8 R0 + 0x7C1C0200, // 0064 CALL R7 1 + 0x8C1C0F0D, // 0065 GETMET R7 R7 K13 + 0x5C240200, // 0066 MOVE R9 R1 + 0x5C280400, // 0067 MOVE R10 R2 + 0x5C2C0600, // 0068 MOVE R11 R3 + 0x7C1C0800, // 0069 CALL R7 4 0x80040E00, // 006A RET 1 R7 - 0x70020007, // 006B JMP #0074 - 0x541EFFFC, // 006C LDINT R7 65533 - 0x1C1C0C07, // 006D EQ R7 R6 R7 - 0x781E0004, // 006E JMPF R7 #0074 - 0x8C1C0707, // 006F GETMET R7 R3 K7 - 0x8824090C, // 0070 GETMBR R9 R4 K12 - 0x542A0004, // 0071 LDINT R10 5 - 0x7C1C0600, // 0072 CALL R7 3 - 0x80040E00, // 0073 RET 1 R7 - 0x70020008, // 0074 JMP #007E - 0x601C0003, // 0075 GETGBL R7 G3 - 0x5C200000, // 0076 MOVE R8 R0 - 0x7C1C0200, // 0077 CALL R7 1 - 0x8C1C0F0D, // 0078 GETMET R7 R7 K13 - 0x5C240200, // 0079 MOVE R9 R1 - 0x5C280400, // 007A MOVE R10 R2 - 0x5C2C0600, // 007B MOVE R11 R3 - 0x7C1C0800, // 007C CALL R7 4 - 0x80040E00, // 007D RET 1 R7 - 0x80000000, // 007E RET 0 }) ) ); @@ -725,18 +705,22 @@ be_local_class(Matter_Plugin_Bridge_Light3, be_const_map( * be_nested_map(8, ( (struct bmapnode*) &(const bmapnode[]) { { be_const_key_int(8, 7), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(7, + be_const_list( * be_nested_list(11, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(2), be_const_int(3), be_const_int(15), be_const_int(17), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(57, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(3), be_const_int(5), @@ -744,34 +728,52 @@ be_local_class(Matter_Plugin_Bridge_Light3, be_const_int(15), be_const_int(17), be_const_int(18), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), + be_const_int(65532), + be_const_int(65533), })) ) } )) }, { be_const_key_int(29, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(6, + be_const_list( * be_nested_list(10, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), be_const_int(2), be_const_int(3), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(3, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(4, + be_const_list( * be_nested_list(8, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(4, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(5, 2), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(8, + be_const_list( * be_nested_list(12, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -779,18 +781,26 @@ be_local_class(Matter_Plugin_Bridge_Light3, be_const_int(3), be_const_int(4), be_const_int(5), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(6, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(3, + be_const_list( * be_nested_list(7, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, { be_const_key_int(768, -1), be_const_simple_instance(be_nested_simple_instance(&be_class_list, { - be_const_list( * be_nested_list(9, + be_const_list( * be_nested_list(13, ( (struct bvalue*) &(const bvalue[]) { be_const_int(0), be_const_int(1), @@ -799,6 +809,10 @@ be_local_class(Matter_Plugin_Bridge_Light3, be_const_int(15), be_const_int(16385), be_const_int(16394), + be_const_int(65528), + be_const_int(65529), + be_const_int(65530), + be_const_int(65531), be_const_int(65532), be_const_int(65533), })) ) } )) }, From 66ff68df784087d3fafc2569d3ae05d53f900b8a Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 11 Feb 2024 02:14:01 -0800 Subject: [PATCH 294/303] LVGL9 restore missing layouts (#20701) --- CHANGELOG.md | 1 + .../generate/LVGL_API_Reference.md | 9 ++++++ .../generate/be_lv_c_mapping.h | 6 ++++ .../generate/be_lvgl_module.c | 31 ++++++++++++++++-- .../generate/be_lvgl_widgets_lib.c | 6 ++++ .../lv_binding_berry/mapping/lv_enum.h | 32 +++++++++++++++++++ .../lv_binding_berry/mapping/lv_funcs.h | 13 ++++++++ .../lv_binding_berry/tools/preprocessor.py | 4 +-- 8 files changed, 98 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80f4aecdd..05d9887a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ All notable changes to this project will be documented in this file. - Matter implement auto-attributes ### Fixed +- LVGL9 restore missing layouts ### Removed diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/LVGL_API_Reference.md b/lib/libesp32_lvgl/lv_binding_berry/generate/LVGL_API_Reference.md index 117a701e1..4a7e64c3c 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/LVGL_API_Reference.md +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/LVGL_API_Reference.md @@ -79,12 +79,15 @@ draw_rect|comptr, lv.draw_rect_dsc, lv.area||[lv_draw_rect](https://docs.lvgl.io draw_rect_dsc_init|lv.draw_rect_dsc||[lv_draw_rect_dsc_init](https://docs.lvgl.io/9.0/search.html?q=lv_draw_rect_dsc_init) draw_vector|comptr||[lv_draw_vector](https://docs.lvgl.io/9.0/search.html?q=lv_draw_vector) event_register_id||int|[lv_event_register_id](https://docs.lvgl.io/9.0/search.html?q=lv_event_register_id) +flex_init|||[lv_flex_init](https://docs.lvgl.io/9.0/search.html?q=lv_flex_init) font_get_glyph_width|lv.font, int, int|int|[lv_font_get_glyph_width](https://docs.lvgl.io/9.0/search.html?q=lv_font_get_glyph_width) font_get_line_height|lv.font|int|[lv_font_get_line_height](https://docs.lvgl.io/9.0/search.html?q=lv_font_get_line_height) font_set_kerning|lv.font, int||[lv_font_set_kerning](https://docs.lvgl.io/9.0/search.html?q=lv_font_set_kerning) get_hor_res||int|[lv_get_hor_res](https://docs.lvgl.io/9.0/search.html?q=lv_get_hor_res) get_ts_calibration||lv.ts_calibration|[lv_get_ts_calibration](https://docs.lvgl.io/9.0/search.html?q=lv_get_ts_calibration) get_ver_res||int|[lv_get_ver_res](https://docs.lvgl.io/9.0/search.html?q=lv_get_ver_res) +grid_fr|int|int|[lv_grid_fr](https://docs.lvgl.io/9.0/search.html?q=lv_grid_fr) +grid_init|||[lv_grid_init](https://docs.lvgl.io/9.0/search.html?q=lv_grid_init) group_by_index|int|lv.group|[lv_group_by_index](https://docs.lvgl.io/9.0/search.html?q=lv_group_by_index) group_get_count||int|[lv_group_get_count](https://docs.lvgl.io/9.0/search.html?q=lv_group_get_count) group_get_default||lv.group|[lv_group_get_default](https://docs.lvgl.io/9.0/search.html?q=lv_group_get_default) @@ -826,6 +829,12 @@ set_align|int||[lv_obj_set_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_ set_content_height|int||[lv_obj_set_content_height](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_content_height) set_content_width|int||[lv_obj_set_content_width](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_content_width) set_ext_click_area|int||[lv_obj_set_ext_click_area](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_ext_click_area) +set_flex_align|int, int, int||[lv_obj_set_flex_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_flex_align) +set_flex_flow|int||[lv_obj_set_flex_flow](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_flex_flow) +set_flex_grow|int||[lv_obj_set_flex_grow](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_flex_grow) +set_grid_align|int, int||[lv_obj_set_grid_align](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_grid_align) +set_grid_cell|int, int, int, int, int, int||[lv_obj_set_grid_cell](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_grid_cell) +set_grid_dsc_array|lv.int_arr, lv.int_arr||[lv_obj_set_grid_dsc_array](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_grid_dsc_array) set_height|int||[lv_obj_set_height](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_height) set_layout|int||[lv_obj_set_layout](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_layout) set_local_style_prop|int, int, int||[lv_obj_set_local_style_prop](https://docs.lvgl.io/9.0/search.html?q=lv_obj_set_local_style_prop) diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h index 47009cd7c..d44163ba6 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lv_c_mapping.h @@ -480,6 +480,12 @@ const be_ntv_func_def_t lv_obj_func[] = { { "set_content_height", { (const void*) &lv_obj_set_content_height, "", "(lv.obj)i" } }, { "set_content_width", { (const void*) &lv_obj_set_content_width, "", "(lv.obj)i" } }, { "set_ext_click_area", { (const void*) &lv_obj_set_ext_click_area, "", "(lv.obj)i" } }, + { "set_flex_align", { (const void*) &lv_obj_set_flex_align, "", "(lv.obj)iii" } }, + { "set_flex_flow", { (const void*) &lv_obj_set_flex_flow, "", "(lv.obj)i" } }, + { "set_flex_grow", { (const void*) &lv_obj_set_flex_grow, "", "(lv.obj)i" } }, + { "set_grid_align", { (const void*) &lv_obj_set_grid_align, "", "(lv.obj)ii" } }, + { "set_grid_cell", { (const void*) &lv_obj_set_grid_cell, "", "(lv.obj)iiiiii" } }, + { "set_grid_dsc_array", { (const void*) &lv_obj_set_grid_dsc_array, "", "(lv.obj)(lv.int_arr)(lv.int_arr)" } }, { "set_height", { (const void*) &lv_obj_set_height, "", "(lv.obj)i" } }, { "set_layout", { (const void*) &lv_obj_set_layout, "", "(lv.obj)i" } }, { "set_local_style_prop", { (const void*) &lv_obj_set_local_style_prop, "", "(lv.obj)iii" } }, diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c index da333e5b6..f921483dd 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_module.c @@ -101,12 +101,15 @@ const be_ntv_func_def_t lv_func[] = { { "draw_rect_dsc_init", { (const void*) &lv_draw_rect_dsc_init, "", "(lv.draw_rect_dsc)" } }, { "draw_vector", { (const void*) &lv_draw_vector, "", "c" } }, { "event_register_id", { (const void*) &lv_event_register_id, "i", "" } }, + { "flex_init", { (const void*) &lv_flex_init, "", "" } }, { "font_get_glyph_width", { (const void*) &lv_font_get_glyph_width, "i", "(lv.font)ii" } }, { "font_get_line_height", { (const void*) &lv_font_get_line_height, "i", "(lv.font)" } }, { "font_set_kerning", { (const void*) &lv_font_set_kerning, "", "(lv.font)i" } }, { "get_hor_res", { (const void*) &lv_get_hor_res, "i", "" } }, { "get_ts_calibration", { (const void*) &lv_get_ts_calibration, "lv.ts_calibration", "" } }, { "get_ver_res", { (const void*) &lv_get_ver_res, "i", "" } }, + { "grid_fr", { (const void*) &lv_grid_fr, "i", "i" } }, + { "grid_init", { (const void*) &lv_grid_init, "", "" } }, { "group_by_index", { (const void*) &lv_group_by_index, "lv.group", "i" } }, { "group_get_count", { (const void*) &lv_group_get_count, "i", "" } }, { "group_get_default", { (const void*) &lv_group_get_default, "lv.group", "" } }, @@ -453,6 +456,20 @@ const be_const_member_t lv0_constants[] = { { "EVENT_STYLE_CHANGED", be_cconst_int(LV_EVENT_STYLE_CHANGED) }, { "EVENT_VALUE_CHANGED", be_cconst_int(LV_EVENT_VALUE_CHANGED) }, { "EVENT_VSYNC", be_cconst_int(LV_EVENT_VSYNC) }, + { "FLEX_ALIGN_CENTER", be_cconst_int(LV_FLEX_ALIGN_CENTER) }, + { "FLEX_ALIGN_END", be_cconst_int(LV_FLEX_ALIGN_END) }, + { "FLEX_ALIGN_SPACE_AROUND", be_cconst_int(LV_FLEX_ALIGN_SPACE_AROUND) }, + { "FLEX_ALIGN_SPACE_BETWEEN", be_cconst_int(LV_FLEX_ALIGN_SPACE_BETWEEN) }, + { "FLEX_ALIGN_SPACE_EVENLY", be_cconst_int(LV_FLEX_ALIGN_SPACE_EVENLY) }, + { "FLEX_ALIGN_START", be_cconst_int(LV_FLEX_ALIGN_START) }, + { "FLEX_FLOW_COLUMN", be_cconst_int(LV_FLEX_FLOW_COLUMN) }, + { "FLEX_FLOW_COLUMN_REVERSE", be_cconst_int(LV_FLEX_FLOW_COLUMN_REVERSE) }, + { "FLEX_FLOW_COLUMN_WRAP", be_cconst_int(LV_FLEX_FLOW_COLUMN_WRAP) }, + { "FLEX_FLOW_COLUMN_WRAP_REVERSE", be_cconst_int(LV_FLEX_FLOW_COLUMN_WRAP_REVERSE) }, + { "FLEX_FLOW_ROW", be_cconst_int(LV_FLEX_FLOW_ROW) }, + { "FLEX_FLOW_ROW_REVERSE", be_cconst_int(LV_FLEX_FLOW_ROW_REVERSE) }, + { "FLEX_FLOW_ROW_WRAP", be_cconst_int(LV_FLEX_FLOW_ROW_WRAP) }, + { "FLEX_FLOW_ROW_WRAP_REVERSE", be_cconst_int(LV_FLEX_FLOW_ROW_WRAP_REVERSE) }, { "FS_MODE_RD", be_cconst_int(LV_FS_MODE_RD) }, { "FS_MODE_WR", be_cconst_int(LV_FS_MODE_WR) }, { "FS_RES_BUSY", be_cconst_int(LV_FS_RES_BUSY) }, @@ -477,7 +494,16 @@ const be_const_member_t lv0_constants[] = { { "GRAD_DIR_HOR", be_cconst_int(LV_GRAD_DIR_HOR) }, { "GRAD_DIR_NONE", be_cconst_int(LV_GRAD_DIR_NONE) }, { "GRAD_DIR_VER", be_cconst_int(LV_GRAD_DIR_VER) }, + { "GRID_ALIGN_CENTER", be_cconst_int(LV_GRID_ALIGN_CENTER) }, + { "GRID_ALIGN_END", be_cconst_int(LV_GRID_ALIGN_END) }, + { "GRID_ALIGN_SPACE_AROUND", be_cconst_int(LV_GRID_ALIGN_SPACE_AROUND) }, + { "GRID_ALIGN_SPACE_BETWEEN", be_cconst_int(LV_GRID_ALIGN_SPACE_BETWEEN) }, + { "GRID_ALIGN_SPACE_EVENLY", be_cconst_int(LV_GRID_ALIGN_SPACE_EVENLY) }, + { "GRID_ALIGN_START", be_cconst_int(LV_GRID_ALIGN_START) }, + { "GRID_ALIGN_STRETCH", be_cconst_int(LV_GRID_ALIGN_STRETCH) }, + { "GRID_CONTENT", be_cconst_int(LV_GRID_CONTENT) }, { "GRID_FR", be_cconst_int(LV_GRID_FR(0)) }, + { "GRID_TEMPLATE_LAST", be_cconst_int(LV_GRID_TEMPLATE_LAST) }, { "GROUP_REFOCUS_POLICY_NEXT", be_cconst_int(LV_GROUP_REFOCUS_POLICY_NEXT) }, { "GROUP_REFOCUS_POLICY_PREV", be_cconst_int(LV_GROUP_REFOCUS_POLICY_PREV) }, { "IMAGEBUTTON_STATE_CHECKED_DISABLED", be_cconst_int(LV_IMAGEBUTTON_STATE_CHECKED_DISABLED) }, @@ -551,8 +577,9 @@ const be_const_member_t lv0_constants[] = { { "LAYER_TYPE_NONE", be_cconst_int(LV_LAYER_TYPE_NONE) }, { "LAYER_TYPE_SIMPLE", be_cconst_int(LV_LAYER_TYPE_SIMPLE) }, { "LAYER_TYPE_TRANSFORM", be_cconst_int(LV_LAYER_TYPE_TRANSFORM) }, - { ">LAYOUT_FLEX", be_ctype(be_LV_LAYOUT_FLEX) }, - { ">LAYOUT_GRID", be_ctype(be_LV_LAYOUT_GRID) }, + { "LAYOUT_FLEX", be_cconst_int(LV_LAYOUT_FLEX) }, + { "LAYOUT_GRID", be_cconst_int(LV_LAYOUT_GRID) }, + { "LAYOUT_NONE", be_cconst_int(LV_LAYOUT_NONE) }, { "LOG_LEVEL_ERROR", be_cconst_int(LV_LOG_LEVEL_ERROR) }, { "LOG_LEVEL_INFO", be_cconst_int(LV_LOG_LEVEL_INFO) }, { "LOG_LEVEL_NONE", be_cconst_int(LV_LOG_LEVEL_NONE) }, diff --git a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c index 83015cef2..3fbbe50c1 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c +++ b/lib/libesp32_lvgl/lv_binding_berry/generate/be_lvgl_widgets_lib.c @@ -493,6 +493,12 @@ extern int lvbe_obj_set_align(bvm *vm); extern int lvbe_obj_set_content_height(bvm *vm); extern int lvbe_obj_set_content_width(bvm *vm); extern int lvbe_obj_set_ext_click_area(bvm *vm); +extern int lvbe_obj_set_flex_align(bvm *vm); +extern int lvbe_obj_set_flex_flow(bvm *vm); +extern int lvbe_obj_set_flex_grow(bvm *vm); +extern int lvbe_obj_set_grid_align(bvm *vm); +extern int lvbe_obj_set_grid_cell(bvm *vm); +extern int lvbe_obj_set_grid_dsc_array(bvm *vm); extern int lvbe_obj_set_height(bvm *vm); extern int lvbe_obj_set_layout(bvm *vm); extern int lvbe_obj_set_local_style_prop(bvm *vm); diff --git a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h index ddb97acd4..bcdc37624 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h +++ b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_enum.h @@ -402,6 +402,38 @@ LV_IMAGE_SRC_FILE LV_IMAGE_SRC_SYMBOL LV_IMAGE_SRC_UNKNOWN +// File: ../../lvgl/src/layouts/flex/lv_flex.h +LV_FLEX_ALIGN_START +LV_FLEX_ALIGN_END +LV_FLEX_ALIGN_CENTER +LV_FLEX_ALIGN_SPACE_EVENLY +LV_FLEX_ALIGN_SPACE_AROUND +LV_FLEX_ALIGN_SPACE_BETWEEN + +LV_FLEX_FLOW_ROW +LV_FLEX_FLOW_COLUMN +LV_FLEX_FLOW_ROW_WRAP +LV_FLEX_FLOW_ROW_REVERSE +LV_FLEX_FLOW_ROW_WRAP_REVERSE +LV_FLEX_FLOW_COLUMN_WRAP +LV_FLEX_FLOW_COLUMN_REVERSE +LV_FLEX_FLOW_COLUMN_WRAP_REVERSE + +// File: ../../lvgl/src/layouts/grid/lv_grid.h +LV_GRID_ALIGN_START +LV_GRID_ALIGN_CENTER +LV_GRID_ALIGN_END +LV_GRID_ALIGN_STRETCH +LV_GRID_ALIGN_SPACE_EVENLY +LV_GRID_ALIGN_SPACE_AROUND +LV_GRID_ALIGN_SPACE_BETWEEN + +LV_GRID_CONTENT +LV_GRID_TEMPLATE_LAST +// File: ../../lvgl/src/layouts/lv_layout.h +LV_LAYOUT_NONE +LV_LAYOUT_FLEX +LV_LAYOUT_GRID // File: ../../lvgl/src/misc/lv_anim.h LV_ANIM_OFF LV_ANIM_ON diff --git a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h index 7104025ba..4505316ab 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h +++ b/lib/libesp32_lvgl/lv_binding_berry/mapping/lv_funcs.h @@ -700,6 +700,19 @@ bool lv_indev_remove_event(lv_indev_t * indev, uint32_t index) uint32_t lv_indev_remove_event_cb_with_user_data(lv_indev_t * indev, lv_event_cb_t event_cb, void * user_data) lv_result_t lv_indev_send_event(lv_indev_t * indev, lv_event_code_t code, void * param) +// ../../lvgl/src/layouts/flex/lv_flex.h +void lv_flex_init(void) +void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow) +void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place, lv_flex_align_t track_cross_place) +void lv_obj_set_flex_grow(lv_obj_t * obj, uint8_t grow) + +// ../../lvgl/src/layouts/grid/lv_grid.h +void lv_grid_init(void) +void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const int32_t col_dsc[], const int32_t row_dsc[]) +void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid_align_t row_align) +void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t column_align, int32_t col_pos, int32_t col_span, lv_grid_align_t row_align, int32_t row_pos, int32_t row_span) +static inline int32_t lv_grid_fr(uint8_t x) + // ../../lvgl/src/libs/qrcode/lv_qrcode.h lv_obj_t * lv_qrcode_create(lv_obj_t * parent) void lv_qrcode_set_size(lv_obj_t * obj, int32_t size) diff --git a/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py b/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py index fad19e18f..8858928c6 100644 --- a/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py +++ b/lib/libesp32_lvgl/lv_binding_berry/tools/preprocessor.py @@ -55,6 +55,7 @@ lv_fun_globs = [ "libs/qrcode/lv_qrcode.h", "core/*.h", "indev/lv_indev.h", + "layouts/*/*.h", # "draw/*.h", "themes/lv_theme.h", "draw/lv_draw_arc.h", @@ -184,8 +185,7 @@ lv_fun_globs = [ "misc/*.h", "widgets/*/*.h", "display/lv_display.h", - "extra/widgets/**/*.h", - "extra/layouts/**/*.h", + "layouts/**/*.h", ] headers_names = list_files(lv_src_prefix, lv_fun_globs) From 72b18eff4c3136f9664769fd08b576d86f9075fd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 11 Feb 2024 11:47:31 +0100 Subject: [PATCH 295/303] Update changelogs --- CHANGELOG.md | 5 +++-- RELEASENOTES.md | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05d9887a0..7b52e5776 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,10 +14,11 @@ All notable changes to this project will be documented in this file. ### Changed - Matter improve `MtrInfo` (#20686) -- Matter implement auto-attributes +- Matter implement auto-attributes (#20694) ### Fixed -- LVGL9 restore missing layouts +- Matter redirects for Advanced Matter configuration UI (#20690) +- LVGL9 restore missing layouts (#20701) ### Removed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 134474a39..aa871d75d 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -187,6 +187,8 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - IP stack compatible with new Core3 IPv6 implementation [#20509](https://github.com/arendst/Tasmota/issues/20509) - Refactored Pio filesystem download script [#20544](https://github.com/arendst/Tasmota/issues/20544) - Matter improve `MtrInfo` [#20686](https://github.com/arendst/Tasmota/issues/20686) +- Matter redirects for Advanced Matter configuration UI [#20690](https://github.com/arendst/Tasmota/issues/20690) +- Matter implement auto-attributes [#20694](https://github.com/arendst/Tasmota/issues/20694) ### Fixed - CVE-2021-36603 Cross Site Scripting (XSS) vulnerability [#12221](https://github.com/arendst/Tasmota/issues/12221) From 238013ba90429b0916be295280366d25e7610854 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 11 Feb 2024 16:32:05 +0100 Subject: [PATCH 296/303] Fix AXP192 register - Fix AXP192 register use - Add more delay to fix intermittent FT5206 init failure --- tasmota/berry/drivers/AXP192_M5Stack_Core2.be | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tasmota/berry/drivers/AXP192_M5Stack_Core2.be b/tasmota/berry/drivers/AXP192_M5Stack_Core2.be index a7293ba8e..33342bd82 100644 --- a/tasmota/berry/drivers/AXP192_M5Stack_Core2.be +++ b/tasmota/berry/drivers/AXP192_M5Stack_Core2.be @@ -52,7 +52,7 @@ class AXP192_M5Stack_Core2 : AXP192 # Automatic shutdown function setting when the key duration is longer than the shutdown duration = turn on # PWROK signal delay after power on = 64ms # Shutdown duration setting = 4s - self.write8(0x34, 0x4C) + self.write8(0x36, 0x4C) # ADC all-on # Bit 7: Battery voltage ADC enable @@ -69,10 +69,17 @@ class AXP192_M5Stack_Core2 : AXP192 self.set_lcd_reset(false) tasmota.delay(100) # wait for 100ms self.set_lcd_reset(true) - tasmota.delay(100) # wait for 100ms + tasmota.delay(200) # wait for 200ms - # bus power mode_output - self.set_buf_power_mode(false) + # Indicates whether the voltage of VBUS is higher than VHOLD when the external power supply VBUS is connected + if self.read8(0X00) & 0x08 + self.write_bit(0x30, 7, true) + # if v-bus can use, disable M-Bus 5V output to input + self.set_buf_power_mode(true) + else + # if not, enable M-Bus 5V output + self.set_buf_power_mode(false) + end tasmota.add_driver(self) end @@ -113,7 +120,7 @@ class AXP192_M5Stack_Core2 : AXP192 self.write8(0x12, self.read8(0x12) & 0xBF) # set EXTEN to disable 5v boost self.write8(0x90, self.read8(0x90) & 0xF8 | 0x01) # set GPIO0 to float, using enternal pulldown resistor to enable supply from BUS_5VS else - self.write8(0x91, self.read8(0x91) & 0x0F | 0xF0) + self.write8(0x91, self.read8(0x91) & 0x0F | 0xF0) # Set GPIO to 3.3V (LDO OUTPUT mode) self.write8(0x90, self.read8(0x90) & 0xF8 | 0x02) # set GPIO0 to LDO OUTPUT , pullup N_VBUSEN to disable supply from BUS_5V self.write8(0x12, self.read8(0x12) | 0x40) # set EXTEN to enable 5v boost end From 710ed2e42c10813237aeb0fd78dc7c5e49bf6b29 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 11 Feb 2024 08:27:40 -0800 Subject: [PATCH 297/303] Berry option to invert serial (#20707) --- CHANGELOG.md | 1 + .../tasmota_xdrv_driver/xdrv_52_3_berry_serial.ino | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b52e5776..cf4b98742 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. - Internal support for persistent JSON settings using single file - Command ``SetOption158`` to publish or suppress ModbusReceived MQTT messages (#20678) - ESP32 Core3 support for SPI ethernet on DM9051, W5500 and KSZ8851 +- Berry option to invert serial ### Breaking Changed - ESP32 LVGL library from v8.3.11 to v9.0.0, some small breaking changes in C, none in HASPmota (#20659) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_serial.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_serial.ino index 2ffe1dab6..7729a6ef0 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_serial.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_serial.ino @@ -26,10 +26,7 @@ /*********************************************************************************************\ * Native functions mapped to Berry functions * - * import wire - * - * wire.get_free_heap() -> int - * + * `ser = serial(4, 5, 9600, serial.SERIAL_7E1)` \*********************************************************************************************/ extern "C" { TasmotaSerial * b_serial_get(struct bvm *vm) { @@ -39,7 +36,7 @@ extern "C" { return ow; } - // Berry: `init(rx_gpio:int, tx_gpio:int, speed:int [, config:int])` + // Berry: `init(rx_gpio:int, tx_gpio:int, speed:int [, config:int, inverted:bool])` int32_t b_serial_init(struct bvm *vm); int32_t b_serial_init(struct bvm *vm) { int32_t argc = be_top(vm); // Get the number of arguments @@ -48,10 +45,14 @@ extern "C" { int32_t tx = be_toint(vm, 3); int32_t speed = be_toint(vm, 4); int32_t mode = SERIAL_8N1; + bool inverted = false; if (argc >= 5 && be_isint(vm, 5)) { mode = be_toint(vm, 5); } - TasmotaSerial * ser = new TasmotaSerial(rx, tx); + if (argc >= 6 && be_isbool(vm, 6)) { + inverted = be_tobool(vm, 6); + } + TasmotaSerial * ser = new TasmotaSerial(rx, tx, 0, 0, TM_SERIAL_BUFFER_SIZE, inverted); bool ok = ser->begin(speed, mode); if (!ok) { delete ser; From fa7e225d5b1f1bad454dc0e2b73da8dd03366746 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 11 Feb 2024 08:53:06 -0800 Subject: [PATCH 298/303] Matter minor fix to logs (#20708) --- .../berry_matter/src/embedded/Matter_UI.be | 1 - .../src/embedded/Matter_zz_Device.be | 2 +- .../solidify/solidified_Matter_zz_Device.h | 244 +++++++++--------- 3 files changed, 123 insertions(+), 124 deletions(-) diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_UI.be b/lib/libesp32/berry_matter/src/embedded/Matter_UI.be index 32b106050..5064bd3e8 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_UI.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_UI.be @@ -36,7 +36,6 @@ class Matter_UI "|temperature|pressure|illuminance|humidity|occupancy|onoff|contact|flow" "|-virtual|v_relay|v_light0|v_light1|v_light2|v_light3" "|v_temp|v_pressure|v_illuminance|v_humidity|v_occupancy|v_contact|v_flow" - # static var _CLASSES_HTTP = "-http" static var _CLASSES_TYPES2= "|http_relay|http_light0|http_light1|http_light2|http_light3" "|http_temperature|http_pressure|http_illuminance|http_humidity" "|http_occupancy|http_contact|http_flow" diff --git a/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be b/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be index 2459771a4..5459b581b 100644 --- a/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be +++ b/lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be @@ -839,6 +839,7 @@ class Matter_Device # always include an aggregator for dynamic endpoints self.plugins.push(matter.Plugin_Aggregator(self, matter.AGGREGATOR_ENDPOINT, {})) + tasmota.log(format("MTR: endpoint = %5i type:%s%s", matter.AGGREGATOR_ENDPOINT, 'aggregator', ''), 2) for ep: endpoints if ep == 0 continue end # skip endpoint 0 @@ -860,7 +861,6 @@ class Matter_Device tasmota.log("MTR: Exception" + str(e) + "|" + str(m), 2) end end - tasmota.log(format("MTR: endpoint = %5i type:%s%s", matter.AGGREGATOR_ENDPOINT, 'aggregator', ''), 2) tasmota.publish_result('{"Matter":{"Initialized":1}}', 'Matter') end diff --git a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h index cc928bf8e..d5af95655 100644 --- a/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h +++ b/lib/libesp32/berry_matter/src/solidify/solidified_Matter_zz_Device.h @@ -3048,19 +3048,19 @@ be_local_closure(Matter_Device__instantiate_plugins_from_config, /* name */ /* K12 */ be_nested_str_weak(), /* K13 */ be_nested_str_weak(Plugin_Aggregator), /* K14 */ be_nested_str_weak(AGGREGATOR_ENDPOINT), - /* K15 */ be_nested_str_weak(find), - /* K16 */ be_nested_str_weak(type), - /* K17 */ be_nested_str_weak(MTR_X3A_X20no_X20class_X20name_X2C_X20skipping), - /* K18 */ be_const_int(3), - /* K19 */ be_nested_str_weak(MTR_X3A_X20only_X20one_X20root_X20node_X20allowed), - /* K20 */ be_nested_str_weak(plugins_classes), - /* K21 */ be_nested_str_weak(MTR_X3A_X20unknown_X20class_X20name_X20_X27), - /* K22 */ be_nested_str_weak(_X27_X20skipping), - /* K23 */ be_nested_str_weak(conf_to_log), - /* K24 */ be_nested_str_weak(MTR_X3A_X20Exception), - /* K25 */ be_nested_str_weak(_X7C), - /* K26 */ be_nested_str_weak(stop_iteration), - /* K27 */ be_nested_str_weak(aggregator), + /* K15 */ be_nested_str_weak(aggregator), + /* K16 */ be_nested_str_weak(find), + /* K17 */ be_nested_str_weak(type), + /* K18 */ be_nested_str_weak(MTR_X3A_X20no_X20class_X20name_X2C_X20skipping), + /* K19 */ be_const_int(3), + /* K20 */ be_nested_str_weak(MTR_X3A_X20only_X20one_X20root_X20node_X20allowed), + /* K21 */ be_nested_str_weak(plugins_classes), + /* K22 */ be_nested_str_weak(MTR_X3A_X20unknown_X20class_X20name_X20_X27), + /* K23 */ be_nested_str_weak(_X27_X20skipping), + /* K24 */ be_nested_str_weak(conf_to_log), + /* K25 */ be_nested_str_weak(MTR_X3A_X20Exception), + /* K26 */ be_nested_str_weak(_X7C), + /* K27 */ be_nested_str_weak(stop_iteration), /* K28 */ be_nested_str_weak(publish_result), /* K29 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Initialized_X22_X3A1_X7D_X7D), /* K30 */ be_nested_str_weak(Matter), @@ -3107,115 +3107,115 @@ be_local_closure(Matter_Device__instantiate_plugins_from_config, /* name */ 0x7C240000, // 0024 CALL R9 0 0x7C140800, // 0025 CALL R5 4 0x7C0C0400, // 0026 CALL R3 2 - 0x600C0010, // 0027 GETGBL R3 G16 - 0x5C100400, // 0028 MOVE R4 R2 - 0x7C0C0200, // 0029 CALL R3 1 - 0xA802005A, // 002A EXBLK 0 #0086 - 0x5C100600, // 002B MOVE R4 R3 - 0x7C100000, // 002C CALL R4 0 - 0x1C140909, // 002D EQ R5 R4 K9 - 0x78160000, // 002E JMPF R5 #0030 - 0x7001FFFA, // 002F JMP #002B - 0xA8020042, // 0030 EXBLK 0 #0074 - 0x60140008, // 0031 GETGBL R5 G8 - 0x5C180800, // 0032 MOVE R6 R4 - 0x7C140200, // 0033 CALL R5 1 - 0x94140205, // 0034 GETIDX R5 R1 R5 - 0x8C180B0F, // 0035 GETMET R6 R5 K15 - 0x58200010, // 0036 LDCONST R8 K16 - 0x7C180400, // 0037 CALL R6 2 - 0x4C1C0000, // 0038 LDNIL R7 - 0x1C1C0C07, // 0039 EQ R7 R6 R7 - 0x781E0006, // 003A JMPF R7 #0042 - 0xB81E0200, // 003B GETNGBL R7 K1 - 0x8C1C0F02, // 003C GETMET R7 R7 K2 - 0x58240011, // 003D LDCONST R9 K17 - 0x58280012, // 003E LDCONST R10 K18 - 0x7C1C0600, // 003F CALL R7 3 - 0xA8040001, // 0040 EXBLK 1 1 - 0x7001FFE8, // 0041 JMP #002B - 0x1C1C0D0B, // 0042 EQ R7 R6 K11 - 0x781E0006, // 0043 JMPF R7 #004B - 0xB81E0200, // 0044 GETNGBL R7 K1 - 0x8C1C0F02, // 0045 GETMET R7 R7 K2 - 0x58240013, // 0046 LDCONST R9 K19 - 0x58280012, // 0047 LDCONST R10 K18 - 0x7C1C0600, // 0048 CALL R7 3 - 0xA8040001, // 0049 EXBLK 1 1 - 0x7001FFDF, // 004A JMP #002B - 0x881C0114, // 004B GETMBR R7 R0 K20 - 0x8C1C0F0F, // 004C GETMET R7 R7 K15 - 0x5C240C00, // 004D MOVE R9 R6 - 0x7C1C0400, // 004E CALL R7 2 - 0x4C200000, // 004F LDNIL R8 - 0x1C200E08, // 0050 EQ R8 R7 R8 - 0x7822000A, // 0051 JMPF R8 #005D - 0xB8220200, // 0052 GETNGBL R8 K1 - 0x8C201102, // 0053 GETMET R8 R8 K2 - 0x60280008, // 0054 GETGBL R10 G8 - 0x5C2C0C00, // 0055 MOVE R11 R6 - 0x7C280200, // 0056 CALL R10 1 - 0x002A2A0A, // 0057 ADD R10 K21 R10 - 0x00281516, // 0058 ADD R10 R10 K22 - 0x582C0004, // 0059 LDCONST R11 K4 - 0x7C200600, // 005A CALL R8 3 - 0xA8040001, // 005B EXBLK 1 1 - 0x7001FFCD, // 005C JMP #002B - 0x5C200E00, // 005D MOVE R8 R7 - 0x5C240000, // 005E MOVE R9 R0 - 0x5C280800, // 005F MOVE R10 R4 - 0x5C2C0A00, // 0060 MOVE R11 R5 - 0x7C200600, // 0061 CALL R8 3 - 0x88240105, // 0062 GETMBR R9 R0 K5 - 0x8C241306, // 0063 GETMET R9 R9 K6 - 0x5C2C1000, // 0064 MOVE R11 R8 - 0x7C240400, // 0065 CALL R9 2 - 0xB8260200, // 0066 GETNGBL R9 K1 - 0x8C241302, // 0067 GETMET R9 R9 K2 - 0x602C0018, // 0068 GETGBL R11 G24 - 0x5830000A, // 0069 LDCONST R12 K10 - 0x5C340800, // 006A MOVE R13 R4 - 0x5C380C00, // 006B MOVE R14 R6 - 0x8C3C0117, // 006C GETMET R15 R0 K23 - 0x5C440A00, // 006D MOVE R17 R5 - 0x7C3C0400, // 006E CALL R15 2 - 0x7C2C0800, // 006F CALL R11 4 - 0x58300004, // 0070 LDCONST R12 K4 - 0x7C240600, // 0071 CALL R9 3 - 0xA8040001, // 0072 EXBLK 1 1 - 0x70020010, // 0073 JMP #0085 - 0xAC140002, // 0074 CATCH R5 0 2 - 0x7002000D, // 0075 JMP #0084 - 0xB81E0200, // 0076 GETNGBL R7 K1 - 0x8C1C0F02, // 0077 GETMET R7 R7 K2 - 0x60240008, // 0078 GETGBL R9 G8 - 0x5C280A00, // 0079 MOVE R10 R5 - 0x7C240200, // 007A CALL R9 1 - 0x00263009, // 007B ADD R9 K24 R9 - 0x00241319, // 007C ADD R9 R9 K25 - 0x60280008, // 007D GETGBL R10 G8 - 0x5C2C0C00, // 007E MOVE R11 R6 - 0x7C280200, // 007F CALL R10 1 - 0x0024120A, // 0080 ADD R9 R9 R10 - 0x58280004, // 0081 LDCONST R10 K4 - 0x7C1C0600, // 0082 CALL R7 3 - 0x70020000, // 0083 JMP #0085 - 0xB0080000, // 0084 RAISE 2 R0 R0 - 0x7001FFA4, // 0085 JMP #002B - 0x580C001A, // 0086 LDCONST R3 K26 - 0xAC0C0200, // 0087 CATCH R3 1 0 - 0xB0080000, // 0088 RAISE 2 R0 R0 - 0xB80E0200, // 0089 GETNGBL R3 K1 - 0x8C0C0702, // 008A GETMET R3 R3 K2 - 0x60140018, // 008B GETGBL R5 G24 - 0x5818000A, // 008C LDCONST R6 K10 - 0xB81E0E00, // 008D GETNGBL R7 K7 - 0x881C0F0E, // 008E GETMBR R7 R7 K14 - 0x5820001B, // 008F LDCONST R8 K27 - 0x5824000C, // 0090 LDCONST R9 K12 - 0x7C140800, // 0091 CALL R5 4 - 0x58180004, // 0092 LDCONST R6 K4 - 0x7C0C0600, // 0093 CALL R3 3 + 0xB80E0200, // 0027 GETNGBL R3 K1 + 0x8C0C0702, // 0028 GETMET R3 R3 K2 + 0x60140018, // 0029 GETGBL R5 G24 + 0x5818000A, // 002A LDCONST R6 K10 + 0xB81E0E00, // 002B GETNGBL R7 K7 + 0x881C0F0E, // 002C GETMBR R7 R7 K14 + 0x5820000F, // 002D LDCONST R8 K15 + 0x5824000C, // 002E LDCONST R9 K12 + 0x7C140800, // 002F CALL R5 4 + 0x58180004, // 0030 LDCONST R6 K4 + 0x7C0C0600, // 0031 CALL R3 3 + 0x600C0010, // 0032 GETGBL R3 G16 + 0x5C100400, // 0033 MOVE R4 R2 + 0x7C0C0200, // 0034 CALL R3 1 + 0xA802005A, // 0035 EXBLK 0 #0091 + 0x5C100600, // 0036 MOVE R4 R3 + 0x7C100000, // 0037 CALL R4 0 + 0x1C140909, // 0038 EQ R5 R4 K9 + 0x78160000, // 0039 JMPF R5 #003B + 0x7001FFFA, // 003A JMP #0036 + 0xA8020042, // 003B EXBLK 0 #007F + 0x60140008, // 003C GETGBL R5 G8 + 0x5C180800, // 003D MOVE R6 R4 + 0x7C140200, // 003E CALL R5 1 + 0x94140205, // 003F GETIDX R5 R1 R5 + 0x8C180B10, // 0040 GETMET R6 R5 K16 + 0x58200011, // 0041 LDCONST R8 K17 + 0x7C180400, // 0042 CALL R6 2 + 0x4C1C0000, // 0043 LDNIL R7 + 0x1C1C0C07, // 0044 EQ R7 R6 R7 + 0x781E0006, // 0045 JMPF R7 #004D + 0xB81E0200, // 0046 GETNGBL R7 K1 + 0x8C1C0F02, // 0047 GETMET R7 R7 K2 + 0x58240012, // 0048 LDCONST R9 K18 + 0x58280013, // 0049 LDCONST R10 K19 + 0x7C1C0600, // 004A CALL R7 3 + 0xA8040001, // 004B EXBLK 1 1 + 0x7001FFE8, // 004C JMP #0036 + 0x1C1C0D0B, // 004D EQ R7 R6 K11 + 0x781E0006, // 004E JMPF R7 #0056 + 0xB81E0200, // 004F GETNGBL R7 K1 + 0x8C1C0F02, // 0050 GETMET R7 R7 K2 + 0x58240014, // 0051 LDCONST R9 K20 + 0x58280013, // 0052 LDCONST R10 K19 + 0x7C1C0600, // 0053 CALL R7 3 + 0xA8040001, // 0054 EXBLK 1 1 + 0x7001FFDF, // 0055 JMP #0036 + 0x881C0115, // 0056 GETMBR R7 R0 K21 + 0x8C1C0F10, // 0057 GETMET R7 R7 K16 + 0x5C240C00, // 0058 MOVE R9 R6 + 0x7C1C0400, // 0059 CALL R7 2 + 0x4C200000, // 005A LDNIL R8 + 0x1C200E08, // 005B EQ R8 R7 R8 + 0x7822000A, // 005C JMPF R8 #0068 + 0xB8220200, // 005D GETNGBL R8 K1 + 0x8C201102, // 005E GETMET R8 R8 K2 + 0x60280008, // 005F GETGBL R10 G8 + 0x5C2C0C00, // 0060 MOVE R11 R6 + 0x7C280200, // 0061 CALL R10 1 + 0x002A2C0A, // 0062 ADD R10 K22 R10 + 0x00281517, // 0063 ADD R10 R10 K23 + 0x582C0004, // 0064 LDCONST R11 K4 + 0x7C200600, // 0065 CALL R8 3 + 0xA8040001, // 0066 EXBLK 1 1 + 0x7001FFCD, // 0067 JMP #0036 + 0x5C200E00, // 0068 MOVE R8 R7 + 0x5C240000, // 0069 MOVE R9 R0 + 0x5C280800, // 006A MOVE R10 R4 + 0x5C2C0A00, // 006B MOVE R11 R5 + 0x7C200600, // 006C CALL R8 3 + 0x88240105, // 006D GETMBR R9 R0 K5 + 0x8C241306, // 006E GETMET R9 R9 K6 + 0x5C2C1000, // 006F MOVE R11 R8 + 0x7C240400, // 0070 CALL R9 2 + 0xB8260200, // 0071 GETNGBL R9 K1 + 0x8C241302, // 0072 GETMET R9 R9 K2 + 0x602C0018, // 0073 GETGBL R11 G24 + 0x5830000A, // 0074 LDCONST R12 K10 + 0x5C340800, // 0075 MOVE R13 R4 + 0x5C380C00, // 0076 MOVE R14 R6 + 0x8C3C0118, // 0077 GETMET R15 R0 K24 + 0x5C440A00, // 0078 MOVE R17 R5 + 0x7C3C0400, // 0079 CALL R15 2 + 0x7C2C0800, // 007A CALL R11 4 + 0x58300004, // 007B LDCONST R12 K4 + 0x7C240600, // 007C CALL R9 3 + 0xA8040001, // 007D EXBLK 1 1 + 0x70020010, // 007E JMP #0090 + 0xAC140002, // 007F CATCH R5 0 2 + 0x7002000D, // 0080 JMP #008F + 0xB81E0200, // 0081 GETNGBL R7 K1 + 0x8C1C0F02, // 0082 GETMET R7 R7 K2 + 0x60240008, // 0083 GETGBL R9 G8 + 0x5C280A00, // 0084 MOVE R10 R5 + 0x7C240200, // 0085 CALL R9 1 + 0x00263209, // 0086 ADD R9 K25 R9 + 0x0024131A, // 0087 ADD R9 R9 K26 + 0x60280008, // 0088 GETGBL R10 G8 + 0x5C2C0C00, // 0089 MOVE R11 R6 + 0x7C280200, // 008A CALL R10 1 + 0x0024120A, // 008B ADD R9 R9 R10 + 0x58280004, // 008C LDCONST R10 K4 + 0x7C1C0600, // 008D CALL R7 3 + 0x70020000, // 008E JMP #0090 + 0xB0080000, // 008F RAISE 2 R0 R0 + 0x7001FFA4, // 0090 JMP #0036 + 0x580C001B, // 0091 LDCONST R3 K27 + 0xAC0C0200, // 0092 CATCH R3 1 0 + 0xB0080000, // 0093 RAISE 2 R0 R0 0xB80E0200, // 0094 GETNGBL R3 K1 0x8C0C071C, // 0095 GETMET R3 R3 K28 0x5814001D, // 0096 LDCONST R5 K29 From c73133b10ab54d6a224eba9102e2b2081926a04e Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Mon, 12 Feb 2024 04:50:58 -0800 Subject: [PATCH 299/303] LVGL simplification of custom widgets (#20711) --- .../src/embedded/lv_tasmota_widgets.be | 27 +- .../solidify/solidified_lv_tasmota_widgets.h | 852 +++++++++--------- 2 files changed, 446 insertions(+), 433 deletions(-) diff --git a/lib/libesp32/berry_tasmota/src/embedded/lv_tasmota_widgets.be b/lib/libesp32/berry_tasmota/src/embedded/lv_tasmota_widgets.be index 2796341bf..e9f464906 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/lv_tasmota_widgets.be +++ b/lib/libesp32/berry_tasmota/src/embedded/lv_tasmota_widgets.be @@ -91,18 +91,19 @@ class lv_signal_arcs : lv_obj var area, arc_dsc # instances of objects kept to avoid re-instanciating at each call def init(parent) - # init custom widget (don't call super constructor) - _lvgl.create_custom_widget(self, parent) + super(self).init(parent) + self.set_style_bg_opa(0, 0) # transparent background + self.set_style_border_width(0, 0) # remove border # own values self.percentage = 100 # pre-allocate buffers self.area = lv.area() self.arc_dsc = lv.draw_arc_dsc() + # we don't need a closure with `add_event_cb` because of special handling + self.add_event_cb(self.widget_event, lv.EVENT_DRAW_MAIN, 0) end - def widget_event(cl, event) - # Call the ancestor's event handler - if lv.obj_event_base(cl, event) != lv.RES_OK return end + def widget_event(event) var code = event.get_code() import math @@ -164,9 +165,6 @@ class lv_signal_arcs : lv_obj arc_dsc.end_angle = 270 + angle arc_dsc.color = self.percentage >= 75 ? on_color : off_color lv.draw_arc(layer, arc_dsc) - - #elif mode == lv.DESIGN_DRAW_POST # commented since we don't want a frame around this object - # self.ancestor_design.call(self, clip_area, mode) end end @@ -235,19 +233,20 @@ class lv_signal_bars : lv_obj var area, line_dsc # instances of objects kept to avoid re-instanciating at each call def init(parent) - # init custom widget (don't call super constructor) - _lvgl.create_custom_widget(self, parent) + super(self).init(parent) + self.set_style_bg_opa(0, 0) # transparent background + self.set_style_border_width(0, 0) # remove border # own values self.percentage = 100 # pre-allocate buffers self.area = lv.area() self.line_dsc = lv.draw_line_dsc() + # we don't need a closure with `add_event_cb` because of special handling + self.add_event_cb(self.widget_event, lv.EVENT_DRAW_MAIN, 0) end - def widget_event(cl, event) + def widget_event(event) # Call the ancestor's event handler - # tasmota.log(f">>>: widget_event {cl=} {event=}") - if lv.obj_event_base(cl, event) != lv.RES_OK return end var code = event.get_code() def atleast1(x) if x >= 1 return x else return 1 end end @@ -278,7 +277,6 @@ class lv_signal_bars : lv_obj var on_color = self.get_style_line_color(lv.PART_MAIN | lv.STATE_DEFAULT) var off_color = self.get_style_bg_color(lv.PART_MAIN | lv.STATE_DEFAULT) - # lv.event_send(self, lv.EVENT_DRAW_PART_BEGIN, line_dsc) for i:0..3 # 4 bars line_dsc.color = self.percentage >= (i+1)*20 ? on_color : off_color line_dsc.p1_y = y_ofs + height - 1 - bar_offset @@ -287,7 +285,6 @@ class lv_signal_bars : lv_obj line_dsc.p2_x = line_dsc.p1_x lv.draw_line(layer, line_dsc) end - # lv.event_send(self, lv.EVENT_DRAW_PART_END, line_dsc) end end diff --git a/lib/libesp32/berry_tasmota/src/solidify/solidified_lv_tasmota_widgets.h b/lib/libesp32/berry_tasmota/src/solidify/solidified_lv_tasmota_widgets.h index 53063b24d..518d6e719 100644 --- a/lib/libesp32/berry_tasmota/src/solidify/solidified_lv_tasmota_widgets.h +++ b/lib/libesp32/berry_tasmota/src/solidify/solidified_lv_tasmota_widgets.h @@ -399,8 +399,8 @@ extern const bclass be_class_lv_signal_arcs; ********************************************************************/ be_local_closure(lv_signal_arcs_widget_event, /* name */ be_nested_proto( - 29, /* nstack */ - 3, /* argc */ + 28, /* nstack */ + 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -431,219 +431,207 @@ be_local_closure(lv_signal_arcs_widget_event, /* name */ ), }), 1, /* has constants */ - ( &(const bvalue[37]) { /* constants */ - /* K0 */ be_nested_str_weak(lv), - /* K1 */ be_nested_str_weak(obj_event_base), - /* K2 */ be_nested_str_weak(RES_OK), - /* K3 */ be_nested_str_weak(get_code), - /* K4 */ be_nested_str_weak(math), - /* K5 */ be_nested_str_weak(get_height), - /* K6 */ be_nested_str_weak(get_width), - /* K7 */ be_const_int(2), - /* K8 */ be_const_int(3), - /* K9 */ be_nested_str_weak(EVENT_DRAW_MAIN), - /* K10 */ be_nested_str_weak(arc_dsc), - /* K11 */ be_nested_str_weak(get_param), - /* K12 */ be_nested_str_weak(get_layer), - /* K13 */ be_nested_str_weak(get_coords), - /* K14 */ be_nested_str_weak(area), - /* K15 */ be_nested_str_weak(x1), - /* K16 */ be_nested_str_weak(y1), - /* K17 */ be_nested_str_weak(draw_arc_dsc_init), - /* K18 */ be_nested_str_weak(init_draw_arc_dsc), - /* K19 */ be_nested_str_weak(PART_MAIN), - /* K20 */ be_nested_str_weak(rounded), - /* K21 */ be_const_int(1), - /* K22 */ be_nested_str_weak(width), - /* K23 */ be_nested_str_weak(get_style_line_color), - /* K24 */ be_nested_str_weak(STATE_DEFAULT), - /* K25 */ be_nested_str_weak(get_style_bg_color), - /* K26 */ be_nested_str_weak(deg), - /* K27 */ be_nested_str_weak(acos), - /* K28 */ be_nested_str_weak(center_x), - /* K29 */ be_nested_str_weak(center_y), - /* K30 */ be_nested_str_weak(color), - /* K31 */ be_nested_str_weak(percentage), - /* K32 */ be_nested_str_weak(radius), - /* K33 */ be_const_int(0), - /* K34 */ be_nested_str_weak(start_angle), - /* K35 */ be_nested_str_weak(end_angle), - /* K36 */ be_nested_str_weak(draw_arc), + ( &(const bvalue[35]) { /* constants */ + /* K0 */ be_nested_str_weak(get_code), + /* K1 */ be_nested_str_weak(math), + /* K2 */ be_nested_str_weak(get_height), + /* K3 */ be_nested_str_weak(get_width), + /* K4 */ be_const_int(2), + /* K5 */ be_const_int(3), + /* K6 */ be_nested_str_weak(lv), + /* K7 */ be_nested_str_weak(EVENT_DRAW_MAIN), + /* K8 */ be_nested_str_weak(arc_dsc), + /* K9 */ be_nested_str_weak(get_param), + /* K10 */ be_nested_str_weak(get_layer), + /* K11 */ be_nested_str_weak(get_coords), + /* K12 */ be_nested_str_weak(area), + /* K13 */ be_nested_str_weak(x1), + /* K14 */ be_nested_str_weak(y1), + /* K15 */ be_nested_str_weak(draw_arc_dsc_init), + /* K16 */ be_nested_str_weak(init_draw_arc_dsc), + /* K17 */ be_nested_str_weak(PART_MAIN), + /* K18 */ be_nested_str_weak(rounded), + /* K19 */ be_const_int(1), + /* K20 */ be_nested_str_weak(width), + /* K21 */ be_nested_str_weak(get_style_line_color), + /* K22 */ be_nested_str_weak(STATE_DEFAULT), + /* K23 */ be_nested_str_weak(get_style_bg_color), + /* K24 */ be_nested_str_weak(deg), + /* K25 */ be_nested_str_weak(acos), + /* K26 */ be_nested_str_weak(center_x), + /* K27 */ be_nested_str_weak(center_y), + /* K28 */ be_nested_str_weak(color), + /* K29 */ be_nested_str_weak(percentage), + /* K30 */ be_nested_str_weak(radius), + /* K31 */ be_const_int(0), + /* K32 */ be_nested_str_weak(start_angle), + /* K33 */ be_nested_str_weak(end_angle), + /* K34 */ be_nested_str_weak(draw_arc), }), be_str_weak(widget_event), &be_const_str_solidified, - ( &(const binstruction[171]) { /* code */ - 0xB80E0000, // 0000 GETNGBL R3 K0 - 0x8C0C0701, // 0001 GETMET R3 R3 K1 - 0x5C140200, // 0002 MOVE R5 R1 - 0x5C180400, // 0003 MOVE R6 R2 - 0x7C0C0600, // 0004 CALL R3 3 - 0xB8120000, // 0005 GETNGBL R4 K0 - 0x88100902, // 0006 GETMBR R4 R4 K2 - 0x200C0604, // 0007 NE R3 R3 R4 - 0x780E0000, // 0008 JMPF R3 #000A - 0x80000600, // 0009 RET 0 - 0x8C0C0503, // 000A GETMET R3 R2 K3 - 0x7C0C0200, // 000B CALL R3 1 - 0xA4120800, // 000C IMPORT R4 K4 - 0x84140000, // 000D CLOSURE R5 P0 - 0x8C180105, // 000E GETMET R6 R0 K5 - 0x7C180200, // 000F CALL R6 1 - 0x8C1C0106, // 0010 GETMET R7 R0 K6 - 0x7C1C0200, // 0011 CALL R7 1 - 0x5C200A00, // 0012 MOVE R8 R5 - 0x54260007, // 0013 LDINT R9 8 - 0x0C240C09, // 0014 DIV R9 R6 R9 - 0x7C200200, // 0015 CALL R8 1 - 0x5C240A00, // 0016 MOVE R9 R5 - 0x08281107, // 0017 MUL R10 R8 K7 - 0x04280C0A, // 0018 SUB R10 R6 R10 - 0x0C281508, // 0019 DIV R10 R10 K8 - 0x7C240200, // 001A CALL R9 1 - 0x0C281307, // 001B DIV R10 R9 K7 - 0xB82E0000, // 001C GETNGBL R11 K0 - 0x882C1709, // 001D GETMBR R11 R11 K9 - 0x1C2C060B, // 001E EQ R11 R3 R11 - 0x782E0089, // 001F JMPF R11 #00AA - 0x882C010A, // 0020 GETMBR R11 R0 K10 - 0x8C30050B, // 0021 GETMET R12 R2 K11 - 0x7C300200, // 0022 CALL R12 1 - 0x8C34050C, // 0023 GETMET R13 R2 K12 - 0x7C340200, // 0024 CALL R13 1 - 0x8C38010D, // 0025 GETMET R14 R0 K13 - 0x8840010E, // 0026 GETMBR R16 R0 K14 - 0x7C380400, // 0027 CALL R14 2 - 0x8838010E, // 0028 GETMBR R14 R0 K14 - 0x88381D0F, // 0029 GETMBR R14 R14 K15 - 0x883C010E, // 002A GETMBR R15 R0 K14 - 0x883C1F10, // 002B GETMBR R15 R15 K16 - 0xB8420000, // 002C GETNGBL R16 K0 - 0x8C402111, // 002D GETMET R16 R16 K17 - 0x5C481600, // 002E MOVE R18 R11 - 0x7C400400, // 002F CALL R16 2 - 0x8C400112, // 0030 GETMET R16 R0 K18 - 0xB84A0000, // 0031 GETNGBL R18 K0 - 0x88482513, // 0032 GETMBR R18 R18 K19 - 0x5C4C1600, // 0033 MOVE R19 R11 - 0x7C400600, // 0034 CALL R16 3 - 0x902E2915, // 0035 SETMBR R11 K20 K21 - 0x08401308, // 0036 MUL R16 R9 K8 - 0x00402115, // 0037 ADD R16 R16 K21 - 0x54460003, // 0038 LDINT R17 4 - 0x0C402011, // 0039 DIV R16 R16 R17 - 0x902E2C10, // 003A SETMBR R11 K22 R16 - 0x8C400117, // 003B GETMET R16 R0 K23 - 0xB84A0000, // 003C GETNGBL R18 K0 - 0x88482513, // 003D GETMBR R18 R18 K19 - 0xB84E0000, // 003E GETNGBL R19 K0 - 0x884C2718, // 003F GETMBR R19 R19 K24 - 0x30482413, // 0040 OR R18 R18 R19 - 0x7C400400, // 0041 CALL R16 2 - 0x8C440119, // 0042 GETMET R17 R0 K25 - 0xB84E0000, // 0043 GETNGBL R19 K0 - 0x884C2713, // 0044 GETMBR R19 R19 K19 - 0xB8520000, // 0045 GETNGBL R20 K0 - 0x88502918, // 0046 GETMBR R20 R20 K24 - 0x304C2614, // 0047 OR R19 R19 R20 - 0x7C440400, // 0048 CALL R17 2 - 0x04480C09, // 0049 SUB R18 R6 R9 - 0x0C4C0F07, // 004A DIV R19 R7 K7 - 0x044C260A, // 004B SUB R19 R19 R10 - 0x60500009, // 004C GETGBL R20 G9 - 0x54560059, // 004D LDINT R21 90 - 0x8C58091A, // 004E GETMET R22 R4 K26 - 0x8C60091B, // 004F GETMET R24 R4 K27 - 0x6068000A, // 0050 GETGBL R26 G10 - 0x5C6C2600, // 0051 MOVE R27 R19 - 0x7C680200, // 0052 CALL R26 1 - 0x606C000A, // 0053 GETGBL R27 G10 - 0x5C702400, // 0054 MOVE R28 R18 - 0x7C6C0200, // 0055 CALL R27 1 - 0x0C68341B, // 0056 DIV R26 R26 R27 - 0x7C600400, // 0057 CALL R24 2 - 0x7C580400, // 0058 CALL R22 2 - 0x04542A16, // 0059 SUB R21 R21 R22 - 0x7C500200, // 005A CALL R20 1 - 0x5456002C, // 005B LDINT R21 45 - 0x24542815, // 005C GT R21 R20 R21 - 0x78560000, // 005D JMPF R21 #005F - 0x5452002C, // 005E LDINT R20 45 - 0x0C540F07, // 005F DIV R21 R7 K7 - 0x00541C15, // 0060 ADD R21 R14 R21 - 0x902E3815, // 0061 SETMBR R11 K28 R21 - 0x00541E06, // 0062 ADD R21 R15 R6 - 0x04542B15, // 0063 SUB R21 R21 K21 - 0x04542A0A, // 0064 SUB R21 R21 R10 - 0x902E3A15, // 0065 SETMBR R11 K29 R21 - 0x8854011F, // 0066 GETMBR R21 R0 K31 - 0x545A0018, // 0067 LDINT R22 25 - 0x28542A16, // 0068 GE R21 R21 R22 - 0x78560001, // 0069 JMPF R21 #006C - 0x5C542000, // 006A MOVE R21 R16 - 0x70020000, // 006B JMP #006D - 0x5C542200, // 006C MOVE R21 R17 - 0x902E3C15, // 006D SETMBR R11 K30 R21 - 0x00541208, // 006E ADD R21 R9 R8 - 0x08564215, // 006F MUL R21 K33 R21 - 0x00542A0A, // 0070 ADD R21 R21 R10 - 0x902E4015, // 0071 SETMBR R11 K32 R21 - 0x902E4521, // 0072 SETMBR R11 K34 K33 - 0x54560131, // 0073 LDINT R21 306 - 0x902E4615, // 0074 SETMBR R11 K35 R21 - 0xB8560000, // 0075 GETNGBL R21 K0 - 0x8C542B24, // 0076 GETMET R21 R21 K36 - 0x5C5C1A00, // 0077 MOVE R23 R13 - 0x5C601600, // 0078 MOVE R24 R11 - 0x7C540600, // 0079 CALL R21 3 - 0x00541208, // 007A ADD R21 R9 R8 - 0x08562A15, // 007B MUL R21 K21 R21 - 0x00542A0A, // 007C ADD R21 R21 R10 - 0x04542B15, // 007D SUB R21 R21 K21 - 0x902E4015, // 007E SETMBR R11 K32 R21 - 0x5456010D, // 007F LDINT R21 270 - 0x04542A14, // 0080 SUB R21 R21 R20 - 0x902E4415, // 0081 SETMBR R11 K34 R21 - 0x5456010D, // 0082 LDINT R21 270 - 0x00542A14, // 0083 ADD R21 R21 R20 - 0x902E4615, // 0084 SETMBR R11 K35 R21 - 0x8854011F, // 0085 GETMBR R21 R0 K31 - 0x545A0031, // 0086 LDINT R22 50 - 0x28542A16, // 0087 GE R21 R21 R22 - 0x78560001, // 0088 JMPF R21 #008B - 0x5C542000, // 0089 MOVE R21 R16 - 0x70020000, // 008A JMP #008C - 0x5C542200, // 008B MOVE R21 R17 - 0x902E3C15, // 008C SETMBR R11 K30 R21 - 0xB8560000, // 008D GETNGBL R21 K0 - 0x8C542B24, // 008E GETMET R21 R21 K36 - 0x5C5C1A00, // 008F MOVE R23 R13 - 0x5C601600, // 0090 MOVE R24 R11 - 0x7C540600, // 0091 CALL R21 3 - 0x00541208, // 0092 ADD R21 R9 R8 - 0x08560E15, // 0093 MUL R21 K7 R21 - 0x00542A0A, // 0094 ADD R21 R21 R10 - 0x04542B07, // 0095 SUB R21 R21 K7 - 0x902E4015, // 0096 SETMBR R11 K32 R21 - 0x5456010D, // 0097 LDINT R21 270 - 0x04542A14, // 0098 SUB R21 R21 R20 - 0x902E4415, // 0099 SETMBR R11 K34 R21 - 0x5456010D, // 009A LDINT R21 270 - 0x00542A14, // 009B ADD R21 R21 R20 - 0x902E4615, // 009C SETMBR R11 K35 R21 - 0x8854011F, // 009D GETMBR R21 R0 K31 - 0x545A004A, // 009E LDINT R22 75 - 0x28542A16, // 009F GE R21 R21 R22 - 0x78560001, // 00A0 JMPF R21 #00A3 - 0x5C542000, // 00A1 MOVE R21 R16 - 0x70020000, // 00A2 JMP #00A4 - 0x5C542200, // 00A3 MOVE R21 R17 - 0x902E3C15, // 00A4 SETMBR R11 K30 R21 - 0xB8560000, // 00A5 GETNGBL R21 K0 - 0x8C542B24, // 00A6 GETMET R21 R21 K36 - 0x5C5C1A00, // 00A7 MOVE R23 R13 - 0x5C601600, // 00A8 MOVE R24 R11 - 0x7C540600, // 00A9 CALL R21 3 - 0x80000000, // 00AA RET 0 + ( &(const binstruction[161]) { /* code */ + 0x8C080300, // 0000 GETMET R2 R1 K0 + 0x7C080200, // 0001 CALL R2 1 + 0xA40E0200, // 0002 IMPORT R3 K1 + 0x84100000, // 0003 CLOSURE R4 P0 + 0x8C140102, // 0004 GETMET R5 R0 K2 + 0x7C140200, // 0005 CALL R5 1 + 0x8C180103, // 0006 GETMET R6 R0 K3 + 0x7C180200, // 0007 CALL R6 1 + 0x5C1C0800, // 0008 MOVE R7 R4 + 0x54220007, // 0009 LDINT R8 8 + 0x0C200A08, // 000A DIV R8 R5 R8 + 0x7C1C0200, // 000B CALL R7 1 + 0x5C200800, // 000C MOVE R8 R4 + 0x08240F04, // 000D MUL R9 R7 K4 + 0x04240A09, // 000E SUB R9 R5 R9 + 0x0C241305, // 000F DIV R9 R9 K5 + 0x7C200200, // 0010 CALL R8 1 + 0x0C241104, // 0011 DIV R9 R8 K4 + 0xB82A0C00, // 0012 GETNGBL R10 K6 + 0x88281507, // 0013 GETMBR R10 R10 K7 + 0x1C28040A, // 0014 EQ R10 R2 R10 + 0x782A0089, // 0015 JMPF R10 #00A0 + 0x88280108, // 0016 GETMBR R10 R0 K8 + 0x8C2C0309, // 0017 GETMET R11 R1 K9 + 0x7C2C0200, // 0018 CALL R11 1 + 0x8C30030A, // 0019 GETMET R12 R1 K10 + 0x7C300200, // 001A CALL R12 1 + 0x8C34010B, // 001B GETMET R13 R0 K11 + 0x883C010C, // 001C GETMBR R15 R0 K12 + 0x7C340400, // 001D CALL R13 2 + 0x8834010C, // 001E GETMBR R13 R0 K12 + 0x88341B0D, // 001F GETMBR R13 R13 K13 + 0x8838010C, // 0020 GETMBR R14 R0 K12 + 0x88381D0E, // 0021 GETMBR R14 R14 K14 + 0xB83E0C00, // 0022 GETNGBL R15 K6 + 0x8C3C1F0F, // 0023 GETMET R15 R15 K15 + 0x5C441400, // 0024 MOVE R17 R10 + 0x7C3C0400, // 0025 CALL R15 2 + 0x8C3C0110, // 0026 GETMET R15 R0 K16 + 0xB8460C00, // 0027 GETNGBL R17 K6 + 0x88442311, // 0028 GETMBR R17 R17 K17 + 0x5C481400, // 0029 MOVE R18 R10 + 0x7C3C0600, // 002A CALL R15 3 + 0x902A2513, // 002B SETMBR R10 K18 K19 + 0x083C1105, // 002C MUL R15 R8 K5 + 0x003C1F13, // 002D ADD R15 R15 K19 + 0x54420003, // 002E LDINT R16 4 + 0x0C3C1E10, // 002F DIV R15 R15 R16 + 0x902A280F, // 0030 SETMBR R10 K20 R15 + 0x8C3C0115, // 0031 GETMET R15 R0 K21 + 0xB8460C00, // 0032 GETNGBL R17 K6 + 0x88442311, // 0033 GETMBR R17 R17 K17 + 0xB84A0C00, // 0034 GETNGBL R18 K6 + 0x88482516, // 0035 GETMBR R18 R18 K22 + 0x30442212, // 0036 OR R17 R17 R18 + 0x7C3C0400, // 0037 CALL R15 2 + 0x8C400117, // 0038 GETMET R16 R0 K23 + 0xB84A0C00, // 0039 GETNGBL R18 K6 + 0x88482511, // 003A GETMBR R18 R18 K17 + 0xB84E0C00, // 003B GETNGBL R19 K6 + 0x884C2716, // 003C GETMBR R19 R19 K22 + 0x30482413, // 003D OR R18 R18 R19 + 0x7C400400, // 003E CALL R16 2 + 0x04440A08, // 003F SUB R17 R5 R8 + 0x0C480D04, // 0040 DIV R18 R6 K4 + 0x04482409, // 0041 SUB R18 R18 R9 + 0x604C0009, // 0042 GETGBL R19 G9 + 0x54520059, // 0043 LDINT R20 90 + 0x8C540718, // 0044 GETMET R21 R3 K24 + 0x8C5C0719, // 0045 GETMET R23 R3 K25 + 0x6064000A, // 0046 GETGBL R25 G10 + 0x5C682400, // 0047 MOVE R26 R18 + 0x7C640200, // 0048 CALL R25 1 + 0x6068000A, // 0049 GETGBL R26 G10 + 0x5C6C2200, // 004A MOVE R27 R17 + 0x7C680200, // 004B CALL R26 1 + 0x0C64321A, // 004C DIV R25 R25 R26 + 0x7C5C0400, // 004D CALL R23 2 + 0x7C540400, // 004E CALL R21 2 + 0x04502815, // 004F SUB R20 R20 R21 + 0x7C4C0200, // 0050 CALL R19 1 + 0x5452002C, // 0051 LDINT R20 45 + 0x24502614, // 0052 GT R20 R19 R20 + 0x78520000, // 0053 JMPF R20 #0055 + 0x544E002C, // 0054 LDINT R19 45 + 0x0C500D04, // 0055 DIV R20 R6 K4 + 0x00501A14, // 0056 ADD R20 R13 R20 + 0x902A3414, // 0057 SETMBR R10 K26 R20 + 0x00501C05, // 0058 ADD R20 R14 R5 + 0x04502913, // 0059 SUB R20 R20 K19 + 0x04502809, // 005A SUB R20 R20 R9 + 0x902A3614, // 005B SETMBR R10 K27 R20 + 0x8850011D, // 005C GETMBR R20 R0 K29 + 0x54560018, // 005D LDINT R21 25 + 0x28502815, // 005E GE R20 R20 R21 + 0x78520001, // 005F JMPF R20 #0062 + 0x5C501E00, // 0060 MOVE R20 R15 + 0x70020000, // 0061 JMP #0063 + 0x5C502000, // 0062 MOVE R20 R16 + 0x902A3814, // 0063 SETMBR R10 K28 R20 + 0x00501007, // 0064 ADD R20 R8 R7 + 0x08523E14, // 0065 MUL R20 K31 R20 + 0x00502809, // 0066 ADD R20 R20 R9 + 0x902A3C14, // 0067 SETMBR R10 K30 R20 + 0x902A411F, // 0068 SETMBR R10 K32 K31 + 0x54520131, // 0069 LDINT R20 306 + 0x902A4214, // 006A SETMBR R10 K33 R20 + 0xB8520C00, // 006B GETNGBL R20 K6 + 0x8C502922, // 006C GETMET R20 R20 K34 + 0x5C581800, // 006D MOVE R22 R12 + 0x5C5C1400, // 006E MOVE R23 R10 + 0x7C500600, // 006F CALL R20 3 + 0x00501007, // 0070 ADD R20 R8 R7 + 0x08522614, // 0071 MUL R20 K19 R20 + 0x00502809, // 0072 ADD R20 R20 R9 + 0x04502913, // 0073 SUB R20 R20 K19 + 0x902A3C14, // 0074 SETMBR R10 K30 R20 + 0x5452010D, // 0075 LDINT R20 270 + 0x04502813, // 0076 SUB R20 R20 R19 + 0x902A4014, // 0077 SETMBR R10 K32 R20 + 0x5452010D, // 0078 LDINT R20 270 + 0x00502813, // 0079 ADD R20 R20 R19 + 0x902A4214, // 007A SETMBR R10 K33 R20 + 0x8850011D, // 007B GETMBR R20 R0 K29 + 0x54560031, // 007C LDINT R21 50 + 0x28502815, // 007D GE R20 R20 R21 + 0x78520001, // 007E JMPF R20 #0081 + 0x5C501E00, // 007F MOVE R20 R15 + 0x70020000, // 0080 JMP #0082 + 0x5C502000, // 0081 MOVE R20 R16 + 0x902A3814, // 0082 SETMBR R10 K28 R20 + 0xB8520C00, // 0083 GETNGBL R20 K6 + 0x8C502922, // 0084 GETMET R20 R20 K34 + 0x5C581800, // 0085 MOVE R22 R12 + 0x5C5C1400, // 0086 MOVE R23 R10 + 0x7C500600, // 0087 CALL R20 3 + 0x00501007, // 0088 ADD R20 R8 R7 + 0x08520814, // 0089 MUL R20 K4 R20 + 0x00502809, // 008A ADD R20 R20 R9 + 0x04502904, // 008B SUB R20 R20 K4 + 0x902A3C14, // 008C SETMBR R10 K30 R20 + 0x5452010D, // 008D LDINT R20 270 + 0x04502813, // 008E SUB R20 R20 R19 + 0x902A4014, // 008F SETMBR R10 K32 R20 + 0x5452010D, // 0090 LDINT R20 270 + 0x00502813, // 0091 ADD R20 R20 R19 + 0x902A4214, // 0092 SETMBR R10 K33 R20 + 0x8850011D, // 0093 GETMBR R20 R0 K29 + 0x5456004A, // 0094 LDINT R21 75 + 0x28502815, // 0095 GE R20 R20 R21 + 0x78520001, // 0096 JMPF R20 #0099 + 0x5C501E00, // 0097 MOVE R20 R15 + 0x70020000, // 0098 JMP #009A + 0x5C502000, // 0099 MOVE R20 R16 + 0x902A3814, // 009A SETMBR R10 K28 R20 + 0xB8520C00, // 009B GETNGBL R20 K6 + 0x8C502922, // 009C GETMET R20 R20 K34 + 0x5C581800, // 009D MOVE R22 R12 + 0x5C5C1400, // 009E MOVE R23 R10 + 0x7C500600, // 009F CALL R20 3 + 0x80000000, // 00A0 RET 0 }) ) ); @@ -682,7 +670,7 @@ be_local_closure(lv_signal_arcs_get_percentage, /* name */ ********************************************************************/ be_local_closure(lv_signal_arcs_init, /* name */ be_nested_proto( - 6, /* nstack */ + 7, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -690,34 +678,54 @@ be_local_closure(lv_signal_arcs_init, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_nested_str_weak(_lvgl), - /* K1 */ be_nested_str_weak(create_custom_widget), - /* K2 */ be_nested_str_weak(percentage), - /* K3 */ be_nested_str_weak(area), - /* K4 */ be_nested_str_weak(lv), - /* K5 */ be_nested_str_weak(arc_dsc), - /* K6 */ be_nested_str_weak(draw_arc_dsc), + ( &(const bvalue[12]) { /* constants */ + /* K0 */ be_nested_str_weak(init), + /* K1 */ be_nested_str_weak(set_style_bg_opa), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(set_style_border_width), + /* K4 */ be_nested_str_weak(percentage), + /* K5 */ be_nested_str_weak(area), + /* K6 */ be_nested_str_weak(lv), + /* K7 */ be_nested_str_weak(arc_dsc), + /* K8 */ be_nested_str_weak(draw_arc_dsc), + /* K9 */ be_nested_str_weak(add_event_cb), + /* K10 */ be_nested_str_weak(widget_event), + /* K11 */ be_nested_str_weak(EVENT_DRAW_MAIN), }), be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[16]) { /* code */ - 0xB80A0000, // 0000 GETNGBL R2 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100000, // 0002 MOVE R4 R0 - 0x5C140200, // 0003 MOVE R5 R1 - 0x7C080600, // 0004 CALL R2 3 - 0x540A0063, // 0005 LDINT R2 100 - 0x90020402, // 0006 SETMBR R0 K2 R2 - 0xB80A0800, // 0007 GETNGBL R2 K4 - 0x8C080503, // 0008 GETMET R2 R2 K3 - 0x7C080200, // 0009 CALL R2 1 - 0x90020602, // 000A SETMBR R0 K3 R2 - 0xB80A0800, // 000B GETNGBL R2 K4 - 0x8C080506, // 000C GETMET R2 R2 K6 - 0x7C080200, // 000D CALL R2 1 - 0x90020A02, // 000E SETMBR R0 K5 R2 - 0x80000000, // 000F RET 0 + ( &(const binstruction[31]) { /* code */ + 0x60080003, // 0000 GETGBL R2 G3 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x8C080500, // 0003 GETMET R2 R2 K0 + 0x5C100200, // 0004 MOVE R4 R1 + 0x7C080400, // 0005 CALL R2 2 + 0x8C080101, // 0006 GETMET R2 R0 K1 + 0x58100002, // 0007 LDCONST R4 K2 + 0x58140002, // 0008 LDCONST R5 K2 + 0x7C080600, // 0009 CALL R2 3 + 0x8C080103, // 000A GETMET R2 R0 K3 + 0x58100002, // 000B LDCONST R4 K2 + 0x58140002, // 000C LDCONST R5 K2 + 0x7C080600, // 000D CALL R2 3 + 0x540A0063, // 000E LDINT R2 100 + 0x90020802, // 000F SETMBR R0 K4 R2 + 0xB80A0C00, // 0010 GETNGBL R2 K6 + 0x8C080505, // 0011 GETMET R2 R2 K5 + 0x7C080200, // 0012 CALL R2 1 + 0x90020A02, // 0013 SETMBR R0 K5 R2 + 0xB80A0C00, // 0014 GETNGBL R2 K6 + 0x8C080508, // 0015 GETMET R2 R2 K8 + 0x7C080200, // 0016 CALL R2 1 + 0x90020E02, // 0017 SETMBR R0 K7 R2 + 0x8C080109, // 0018 GETMET R2 R0 K9 + 0x8810010A, // 0019 GETMBR R4 R0 K10 + 0xB8160C00, // 001A GETNGBL R5 K6 + 0x88140B0B, // 001B GETMBR R5 R5 K11 + 0x58180002, // 001C LDCONST R6 K2 + 0x7C080800, // 001D CALL R2 4 + 0x80000000, // 001E RET 0 }) ) ); @@ -1160,8 +1168,8 @@ be_local_closure(lv_signal_bars_get_percentage, /* name */ ********************************************************************/ be_local_closure(lv_signal_bars_widget_event, /* name */ be_nested_proto( - 23, /* nstack */ - 3, /* argc */ + 22, /* nstack */ + 2, /* argc */ 2, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -1192,161 +1200,149 @@ be_local_closure(lv_signal_bars_widget_event, /* name */ ), }), 1, /* has constants */ - ( &(const bvalue[35]) { /* constants */ - /* K0 */ be_nested_str_weak(lv), - /* K1 */ be_nested_str_weak(obj_event_base), - /* K2 */ be_nested_str_weak(RES_OK), - /* K3 */ be_nested_str_weak(get_code), - /* K4 */ be_nested_str_weak(get_height), - /* K5 */ be_nested_str_weak(get_width), - /* K6 */ be_const_int(3), - /* K7 */ be_const_int(2), - /* K8 */ be_nested_str_weak(EVENT_DRAW_MAIN), - /* K9 */ be_nested_str_weak(line_dsc), - /* K10 */ be_nested_str_weak(get_param), - /* K11 */ be_nested_str_weak(get_layer), - /* K12 */ be_nested_str_weak(get_coords), - /* K13 */ be_nested_str_weak(area), - /* K14 */ be_nested_str_weak(x1), - /* K15 */ be_nested_str_weak(y1), - /* K16 */ be_nested_str_weak(draw_line_dsc_init), - /* K17 */ be_nested_str_weak(init_draw_line_dsc), - /* K18 */ be_nested_str_weak(PART_MAIN), - /* K19 */ be_nested_str_weak(round_start), - /* K20 */ be_const_int(1), - /* K21 */ be_nested_str_weak(round_end), - /* K22 */ be_nested_str_weak(width), - /* K23 */ be_nested_str_weak(get_style_line_color), - /* K24 */ be_nested_str_weak(STATE_DEFAULT), - /* K25 */ be_nested_str_weak(get_style_bg_color), - /* K26 */ be_const_int(0), - /* K27 */ be_nested_str_weak(color), - /* K28 */ be_nested_str_weak(percentage), - /* K29 */ be_nested_str_weak(p1_y), - /* K30 */ be_nested_str_weak(p1_x), - /* K31 */ be_nested_str_weak(p2_y), - /* K32 */ be_nested_str_weak(p2_x), - /* K33 */ be_nested_str_weak(draw_line), - /* K34 */ be_nested_str_weak(stop_iteration), + ( &(const bvalue[33]) { /* constants */ + /* K0 */ be_nested_str_weak(get_code), + /* K1 */ be_nested_str_weak(get_height), + /* K2 */ be_nested_str_weak(get_width), + /* K3 */ be_const_int(3), + /* K4 */ be_const_int(2), + /* K5 */ be_nested_str_weak(lv), + /* K6 */ be_nested_str_weak(EVENT_DRAW_MAIN), + /* K7 */ be_nested_str_weak(line_dsc), + /* K8 */ be_nested_str_weak(get_param), + /* K9 */ be_nested_str_weak(get_layer), + /* K10 */ be_nested_str_weak(get_coords), + /* K11 */ be_nested_str_weak(area), + /* K12 */ be_nested_str_weak(x1), + /* K13 */ be_nested_str_weak(y1), + /* K14 */ be_nested_str_weak(draw_line_dsc_init), + /* K15 */ be_nested_str_weak(init_draw_line_dsc), + /* K16 */ be_nested_str_weak(PART_MAIN), + /* K17 */ be_nested_str_weak(round_start), + /* K18 */ be_const_int(1), + /* K19 */ be_nested_str_weak(round_end), + /* K20 */ be_nested_str_weak(width), + /* K21 */ be_nested_str_weak(get_style_line_color), + /* K22 */ be_nested_str_weak(STATE_DEFAULT), + /* K23 */ be_nested_str_weak(get_style_bg_color), + /* K24 */ be_const_int(0), + /* K25 */ be_nested_str_weak(color), + /* K26 */ be_nested_str_weak(percentage), + /* K27 */ be_nested_str_weak(p1_y), + /* K28 */ be_nested_str_weak(p1_x), + /* K29 */ be_nested_str_weak(p2_y), + /* K30 */ be_nested_str_weak(p2_x), + /* K31 */ be_nested_str_weak(draw_line), + /* K32 */ be_nested_str_weak(stop_iteration), }), be_str_weak(widget_event), &be_const_str_solidified, - ( &(const binstruction[115]) { /* code */ - 0xB80E0000, // 0000 GETNGBL R3 K0 - 0x8C0C0701, // 0001 GETMET R3 R3 K1 - 0x5C140200, // 0002 MOVE R5 R1 - 0x5C180400, // 0003 MOVE R6 R2 - 0x7C0C0600, // 0004 CALL R3 3 - 0xB8120000, // 0005 GETNGBL R4 K0 - 0x88100902, // 0006 GETMBR R4 R4 K2 - 0x200C0604, // 0007 NE R3 R3 R4 - 0x780E0000, // 0008 JMPF R3 #000A - 0x80000600, // 0009 RET 0 - 0x8C0C0503, // 000A GETMET R3 R2 K3 - 0x7C0C0200, // 000B CALL R3 1 - 0x84100000, // 000C CLOSURE R4 P0 - 0x8C140104, // 000D GETMET R5 R0 K4 - 0x7C140200, // 000E CALL R5 1 - 0x8C180105, // 000F GETMET R6 R0 K5 - 0x7C180200, // 0010 CALL R6 1 - 0x5C1C0800, // 0011 MOVE R7 R4 - 0x5422000E, // 0012 LDINT R8 15 - 0x0C200C08, // 0013 DIV R8 R6 R8 - 0x7C1C0200, // 0014 CALL R7 1 - 0x5C200800, // 0015 MOVE R8 R4 - 0x08240F06, // 0016 MUL R9 R7 K6 - 0x04240C09, // 0017 SUB R9 R6 R9 - 0x542A0003, // 0018 LDINT R10 4 - 0x0C24120A, // 0019 DIV R9 R9 R10 - 0x7C200200, // 001A CALL R8 1 - 0x0C241107, // 001B DIV R9 R8 K7 - 0xB82A0000, // 001C GETNGBL R10 K0 - 0x88281508, // 001D GETMBR R10 R10 K8 - 0x1C28060A, // 001E EQ R10 R3 R10 - 0x782A0051, // 001F JMPF R10 #0072 - 0x88280109, // 0020 GETMBR R10 R0 K9 - 0x8C2C050A, // 0021 GETMET R11 R2 K10 - 0x7C2C0200, // 0022 CALL R11 1 - 0x8C30050B, // 0023 GETMET R12 R2 K11 - 0x7C300200, // 0024 CALL R12 1 - 0x8C34010C, // 0025 GETMET R13 R0 K12 - 0x883C010D, // 0026 GETMBR R15 R0 K13 - 0x7C340400, // 0027 CALL R13 2 - 0x8834010D, // 0028 GETMBR R13 R0 K13 - 0x88341B0E, // 0029 GETMBR R13 R13 K14 - 0x8838010D, // 002A GETMBR R14 R0 K13 - 0x88381D0F, // 002B GETMBR R14 R14 K15 - 0xB83E0000, // 002C GETNGBL R15 K0 - 0x8C3C1F10, // 002D GETMET R15 R15 K16 - 0x5C441400, // 002E MOVE R17 R10 - 0x7C3C0400, // 002F CALL R15 2 - 0x8C3C0111, // 0030 GETMET R15 R0 K17 - 0xB8460000, // 0031 GETNGBL R17 K0 - 0x88442312, // 0032 GETMBR R17 R17 K18 - 0x5C481400, // 0033 MOVE R18 R10 - 0x7C3C0600, // 0034 CALL R15 3 - 0x902A2714, // 0035 SETMBR R10 K19 K20 - 0x902A2B14, // 0036 SETMBR R10 K21 K20 - 0x902A2C08, // 0037 SETMBR R10 K22 R8 - 0x8C3C0117, // 0038 GETMET R15 R0 K23 - 0xB8460000, // 0039 GETNGBL R17 K0 - 0x88442312, // 003A GETMBR R17 R17 K18 - 0xB84A0000, // 003B GETNGBL R18 K0 - 0x88482518, // 003C GETMBR R18 R18 K24 - 0x30442212, // 003D OR R17 R17 R18 - 0x7C3C0400, // 003E CALL R15 2 - 0x8C400119, // 003F GETMET R16 R0 K25 - 0xB84A0000, // 0040 GETNGBL R18 K0 - 0x88482512, // 0041 GETMBR R18 R18 K18 - 0xB84E0000, // 0042 GETNGBL R19 K0 - 0x884C2718, // 0043 GETMBR R19 R19 K24 - 0x30482413, // 0044 OR R18 R18 R19 - 0x7C400400, // 0045 CALL R16 2 - 0x60440010, // 0046 GETGBL R17 G16 - 0x404A3506, // 0047 CONNECT R18 K26 K6 - 0x7C440200, // 0048 CALL R17 1 - 0xA8020024, // 0049 EXBLK 0 #006F - 0x5C482200, // 004A MOVE R18 R17 - 0x7C480000, // 004B CALL R18 0 - 0x884C011C, // 004C GETMBR R19 R0 K28 - 0x00502514, // 004D ADD R20 R18 K20 - 0x54560013, // 004E LDINT R21 20 - 0x08502815, // 004F MUL R20 R20 R21 - 0x284C2614, // 0050 GE R19 R19 R20 - 0x784E0001, // 0051 JMPF R19 #0054 - 0x5C4C1E00, // 0052 MOVE R19 R15 - 0x70020000, // 0053 JMP #0055 - 0x5C4C2000, // 0054 MOVE R19 R16 - 0x902A3613, // 0055 SETMBR R10 K27 R19 - 0x004C1C05, // 0056 ADD R19 R14 R5 - 0x044C2714, // 0057 SUB R19 R19 K20 - 0x044C2609, // 0058 SUB R19 R19 R9 - 0x902A3A13, // 0059 SETMBR R10 K29 R19 - 0x004C1007, // 005A ADD R19 R8 R7 - 0x084C2413, // 005B MUL R19 R18 R19 - 0x004C1A13, // 005C ADD R19 R13 R19 - 0x004C2609, // 005D ADD R19 R19 R9 - 0x902A3C13, // 005E SETMBR R10 K30 R19 - 0x044E0C12, // 005F SUB R19 K6 R18 - 0x04500A08, // 0060 SUB R20 R5 R8 - 0x084C2614, // 0061 MUL R19 R19 R20 - 0x54520003, // 0062 LDINT R20 4 - 0x0C4C2614, // 0063 DIV R19 R19 R20 - 0x004C1C13, // 0064 ADD R19 R14 R19 - 0x004C2609, // 0065 ADD R19 R19 R9 - 0x902A3E13, // 0066 SETMBR R10 K31 R19 - 0x884C151E, // 0067 GETMBR R19 R10 K30 - 0x902A4013, // 0068 SETMBR R10 K32 R19 - 0xB84E0000, // 0069 GETNGBL R19 K0 - 0x8C4C2721, // 006A GETMET R19 R19 K33 - 0x5C541800, // 006B MOVE R21 R12 - 0x5C581400, // 006C MOVE R22 R10 - 0x7C4C0600, // 006D CALL R19 3 - 0x7001FFDA, // 006E JMP #004A - 0x58440022, // 006F LDCONST R17 K34 - 0xAC440200, // 0070 CATCH R17 1 0 - 0xB0080000, // 0071 RAISE 2 R0 R0 - 0x80000000, // 0072 RET 0 + ( &(const binstruction[105]) { /* code */ + 0x8C080300, // 0000 GETMET R2 R1 K0 + 0x7C080200, // 0001 CALL R2 1 + 0x840C0000, // 0002 CLOSURE R3 P0 + 0x8C100101, // 0003 GETMET R4 R0 K1 + 0x7C100200, // 0004 CALL R4 1 + 0x8C140102, // 0005 GETMET R5 R0 K2 + 0x7C140200, // 0006 CALL R5 1 + 0x5C180600, // 0007 MOVE R6 R3 + 0x541E000E, // 0008 LDINT R7 15 + 0x0C1C0A07, // 0009 DIV R7 R5 R7 + 0x7C180200, // 000A CALL R6 1 + 0x5C1C0600, // 000B MOVE R7 R3 + 0x08200D03, // 000C MUL R8 R6 K3 + 0x04200A08, // 000D SUB R8 R5 R8 + 0x54260003, // 000E LDINT R9 4 + 0x0C201009, // 000F DIV R8 R8 R9 + 0x7C1C0200, // 0010 CALL R7 1 + 0x0C200F04, // 0011 DIV R8 R7 K4 + 0xB8260A00, // 0012 GETNGBL R9 K5 + 0x88241306, // 0013 GETMBR R9 R9 K6 + 0x1C240409, // 0014 EQ R9 R2 R9 + 0x78260051, // 0015 JMPF R9 #0068 + 0x88240107, // 0016 GETMBR R9 R0 K7 + 0x8C280308, // 0017 GETMET R10 R1 K8 + 0x7C280200, // 0018 CALL R10 1 + 0x8C2C0309, // 0019 GETMET R11 R1 K9 + 0x7C2C0200, // 001A CALL R11 1 + 0x8C30010A, // 001B GETMET R12 R0 K10 + 0x8838010B, // 001C GETMBR R14 R0 K11 + 0x7C300400, // 001D CALL R12 2 + 0x8830010B, // 001E GETMBR R12 R0 K11 + 0x8830190C, // 001F GETMBR R12 R12 K12 + 0x8834010B, // 0020 GETMBR R13 R0 K11 + 0x88341B0D, // 0021 GETMBR R13 R13 K13 + 0xB83A0A00, // 0022 GETNGBL R14 K5 + 0x8C381D0E, // 0023 GETMET R14 R14 K14 + 0x5C401200, // 0024 MOVE R16 R9 + 0x7C380400, // 0025 CALL R14 2 + 0x8C38010F, // 0026 GETMET R14 R0 K15 + 0xB8420A00, // 0027 GETNGBL R16 K5 + 0x88402110, // 0028 GETMBR R16 R16 K16 + 0x5C441200, // 0029 MOVE R17 R9 + 0x7C380600, // 002A CALL R14 3 + 0x90262312, // 002B SETMBR R9 K17 K18 + 0x90262712, // 002C SETMBR R9 K19 K18 + 0x90262807, // 002D SETMBR R9 K20 R7 + 0x8C380115, // 002E GETMET R14 R0 K21 + 0xB8420A00, // 002F GETNGBL R16 K5 + 0x88402110, // 0030 GETMBR R16 R16 K16 + 0xB8460A00, // 0031 GETNGBL R17 K5 + 0x88442316, // 0032 GETMBR R17 R17 K22 + 0x30402011, // 0033 OR R16 R16 R17 + 0x7C380400, // 0034 CALL R14 2 + 0x8C3C0117, // 0035 GETMET R15 R0 K23 + 0xB8460A00, // 0036 GETNGBL R17 K5 + 0x88442310, // 0037 GETMBR R17 R17 K16 + 0xB84A0A00, // 0038 GETNGBL R18 K5 + 0x88482516, // 0039 GETMBR R18 R18 K22 + 0x30442212, // 003A OR R17 R17 R18 + 0x7C3C0400, // 003B CALL R15 2 + 0x60400010, // 003C GETGBL R16 G16 + 0x40463103, // 003D CONNECT R17 K24 K3 + 0x7C400200, // 003E CALL R16 1 + 0xA8020024, // 003F EXBLK 0 #0065 + 0x5C442000, // 0040 MOVE R17 R16 + 0x7C440000, // 0041 CALL R17 0 + 0x8848011A, // 0042 GETMBR R18 R0 K26 + 0x004C2312, // 0043 ADD R19 R17 K18 + 0x54520013, // 0044 LDINT R20 20 + 0x084C2614, // 0045 MUL R19 R19 R20 + 0x28482413, // 0046 GE R18 R18 R19 + 0x784A0001, // 0047 JMPF R18 #004A + 0x5C481C00, // 0048 MOVE R18 R14 + 0x70020000, // 0049 JMP #004B + 0x5C481E00, // 004A MOVE R18 R15 + 0x90263212, // 004B SETMBR R9 K25 R18 + 0x00481A04, // 004C ADD R18 R13 R4 + 0x04482512, // 004D SUB R18 R18 K18 + 0x04482408, // 004E SUB R18 R18 R8 + 0x90263612, // 004F SETMBR R9 K27 R18 + 0x00480E06, // 0050 ADD R18 R7 R6 + 0x08482212, // 0051 MUL R18 R17 R18 + 0x00481812, // 0052 ADD R18 R12 R18 + 0x00482408, // 0053 ADD R18 R18 R8 + 0x90263812, // 0054 SETMBR R9 K28 R18 + 0x044A0611, // 0055 SUB R18 K3 R17 + 0x044C0807, // 0056 SUB R19 R4 R7 + 0x08482413, // 0057 MUL R18 R18 R19 + 0x544E0003, // 0058 LDINT R19 4 + 0x0C482413, // 0059 DIV R18 R18 R19 + 0x00481A12, // 005A ADD R18 R13 R18 + 0x00482408, // 005B ADD R18 R18 R8 + 0x90263A12, // 005C SETMBR R9 K29 R18 + 0x8848131C, // 005D GETMBR R18 R9 K28 + 0x90263C12, // 005E SETMBR R9 K30 R18 + 0xB84A0A00, // 005F GETNGBL R18 K5 + 0x8C48251F, // 0060 GETMET R18 R18 K31 + 0x5C501600, // 0061 MOVE R20 R11 + 0x5C541200, // 0062 MOVE R21 R9 + 0x7C480600, // 0063 CALL R18 3 + 0x7001FFDA, // 0064 JMP #0040 + 0x58400020, // 0065 LDCONST R16 K32 + 0xAC400200, // 0066 CATCH R16 1 0 + 0xB0080000, // 0067 RAISE 2 R0 R0 + 0x80000000, // 0068 RET 0 }) ) ); @@ -1358,7 +1354,7 @@ be_local_closure(lv_signal_bars_widget_event, /* name */ ********************************************************************/ be_local_closure(lv_signal_bars_init, /* name */ be_nested_proto( - 6, /* nstack */ + 7, /* nstack */ 2, /* argc */ 2, /* varg */ 0, /* has upvals */ @@ -1366,34 +1362,54 @@ be_local_closure(lv_signal_bars_init, /* name */ 0, /* has sup protos */ NULL, /* no sub protos */ 1, /* has constants */ - ( &(const bvalue[ 7]) { /* constants */ - /* K0 */ be_nested_str_weak(_lvgl), - /* K1 */ be_nested_str_weak(create_custom_widget), - /* K2 */ be_nested_str_weak(percentage), - /* K3 */ be_nested_str_weak(area), - /* K4 */ be_nested_str_weak(lv), - /* K5 */ be_nested_str_weak(line_dsc), - /* K6 */ be_nested_str_weak(draw_line_dsc), + ( &(const bvalue[12]) { /* constants */ + /* K0 */ be_nested_str_weak(init), + /* K1 */ be_nested_str_weak(set_style_bg_opa), + /* K2 */ be_const_int(0), + /* K3 */ be_nested_str_weak(set_style_border_width), + /* K4 */ be_nested_str_weak(percentage), + /* K5 */ be_nested_str_weak(area), + /* K6 */ be_nested_str_weak(lv), + /* K7 */ be_nested_str_weak(line_dsc), + /* K8 */ be_nested_str_weak(draw_line_dsc), + /* K9 */ be_nested_str_weak(add_event_cb), + /* K10 */ be_nested_str_weak(widget_event), + /* K11 */ be_nested_str_weak(EVENT_DRAW_MAIN), }), be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[16]) { /* code */ - 0xB80A0000, // 0000 GETNGBL R2 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100000, // 0002 MOVE R4 R0 - 0x5C140200, // 0003 MOVE R5 R1 - 0x7C080600, // 0004 CALL R2 3 - 0x540A0063, // 0005 LDINT R2 100 - 0x90020402, // 0006 SETMBR R0 K2 R2 - 0xB80A0800, // 0007 GETNGBL R2 K4 - 0x8C080503, // 0008 GETMET R2 R2 K3 - 0x7C080200, // 0009 CALL R2 1 - 0x90020602, // 000A SETMBR R0 K3 R2 - 0xB80A0800, // 000B GETNGBL R2 K4 - 0x8C080506, // 000C GETMET R2 R2 K6 - 0x7C080200, // 000D CALL R2 1 - 0x90020A02, // 000E SETMBR R0 K5 R2 - 0x80000000, // 000F RET 0 + ( &(const binstruction[31]) { /* code */ + 0x60080003, // 0000 GETGBL R2 G3 + 0x5C0C0000, // 0001 MOVE R3 R0 + 0x7C080200, // 0002 CALL R2 1 + 0x8C080500, // 0003 GETMET R2 R2 K0 + 0x5C100200, // 0004 MOVE R4 R1 + 0x7C080400, // 0005 CALL R2 2 + 0x8C080101, // 0006 GETMET R2 R0 K1 + 0x58100002, // 0007 LDCONST R4 K2 + 0x58140002, // 0008 LDCONST R5 K2 + 0x7C080600, // 0009 CALL R2 3 + 0x8C080103, // 000A GETMET R2 R0 K3 + 0x58100002, // 000B LDCONST R4 K2 + 0x58140002, // 000C LDCONST R5 K2 + 0x7C080600, // 000D CALL R2 3 + 0x540A0063, // 000E LDINT R2 100 + 0x90020802, // 000F SETMBR R0 K4 R2 + 0xB80A0C00, // 0010 GETNGBL R2 K6 + 0x8C080505, // 0011 GETMET R2 R2 K5 + 0x7C080200, // 0012 CALL R2 1 + 0x90020A02, // 0013 SETMBR R0 K5 R2 + 0xB80A0C00, // 0014 GETNGBL R2 K6 + 0x8C080508, // 0015 GETMET R2 R2 K8 + 0x7C080200, // 0016 CALL R2 1 + 0x90020E02, // 0017 SETMBR R0 K7 R2 + 0x8C080109, // 0018 GETMET R2 R0 K9 + 0x8810010A, // 0019 GETMBR R4 R0 K10 + 0xB8160C00, // 001A GETNGBL R5 K6 + 0x88140B0B, // 001B GETMBR R5 R5 K11 + 0x58180002, // 001C LDCONST R6 K2 + 0x7C080800, // 001D CALL R2 4 + 0x80000000, // 001E RET 0 }) ) ); From 280b71eb4153b91817172508255c097d958cd748 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 12 Feb 2024 21:25:19 +0100 Subject: [PATCH 300/303] Fix M5Core2 audio when connecting ethernet --- tasmota/berry/drivers/AXP192_M5Stack_Core2.be | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tasmota/berry/drivers/AXP192_M5Stack_Core2.be b/tasmota/berry/drivers/AXP192_M5Stack_Core2.be index 33342bd82..fbe8921c7 100644 --- a/tasmota/berry/drivers/AXP192_M5Stack_Core2.be +++ b/tasmota/berry/drivers/AXP192_M5Stack_Core2.be @@ -64,7 +64,10 @@ class AXP192_M5Stack_Core2 : AXP192 # Bit 1: APS voltage ADC enable # Bit 0: TS pin ADC function enable self.write8(0x82, 0xFF) - + + # Disable audio as ethernet uses the same GPIO + set_speaker_enable(false) + # Reset LCD Controller self.set_lcd_reset(false) tasmota.delay(100) # wait for 100ms From bddd9a9caf943018ba2d8dba8701a6d3c65ccce2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 12 Feb 2024 21:47:46 +0100 Subject: [PATCH 301/303] Update AXP192_M5Stack_Core2.be --- tasmota/berry/drivers/AXP192_M5Stack_Core2.be | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/berry/drivers/AXP192_M5Stack_Core2.be b/tasmota/berry/drivers/AXP192_M5Stack_Core2.be index fbe8921c7..1b08a148b 100644 --- a/tasmota/berry/drivers/AXP192_M5Stack_Core2.be +++ b/tasmota/berry/drivers/AXP192_M5Stack_Core2.be @@ -145,7 +145,7 @@ class AXP192_M5Stack_Core2 : AXP192 # respond to audio events def audio(cmd, idx, payload, raw) if cmd == "power" - self.set_speaker_enable(idx) + self.set_speaker_enable(idx ? 1 : 0) end end From 91237dff5bdfc0e975b93cbd8d629df2339fe0bd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 12 Feb 2024 22:14:20 +0100 Subject: [PATCH 302/303] Fix AXP driver --- tasmota/berry/drivers/AXP192_M5Stack_Core2.be | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/berry/drivers/AXP192_M5Stack_Core2.be b/tasmota/berry/drivers/AXP192_M5Stack_Core2.be index 1b08a148b..e06036bc2 100644 --- a/tasmota/berry/drivers/AXP192_M5Stack_Core2.be +++ b/tasmota/berry/drivers/AXP192_M5Stack_Core2.be @@ -66,7 +66,7 @@ class AXP192_M5Stack_Core2 : AXP192 self.write8(0x82, 0xFF) # Disable audio as ethernet uses the same GPIO - set_speaker_enable(false) + self.write_gpio(2, 0) # Reset LCD Controller self.set_lcd_reset(false) From 88f1e3593a328028eb30b21f3358560770ab365c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 13 Feb 2024 10:15:12 +0100 Subject: [PATCH 303/303] Fix GPIO Viewer --- tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino index 5a2da52b8..de81c64a8 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_121_gpioviewer.ino @@ -119,8 +119,9 @@ bool GVInit(void) { GV->port = GV_PORT; return true; } + return false; } - return false; + return true; } void GVStop(void) {